summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--LGPL_EXCEPTION.txt22
-rw-r--r--config.tests/arch/arch.cpp44
-rw-r--r--config.tests/avx512/avx512.cpp5
-rw-r--r--config_help.txt5
-rwxr-xr-xconfigure2
-rw-r--r--configure.json95
-rw-r--r--configure.pri57
-rw-r--r--doc/global/html-header-online.qdocconf77
-rw-r--r--doc/global/macros.qdocconf5
-rw-r--r--doc/global/template/style/cookie-confirm.css219
-rw-r--r--doc/global/template/style/online.css1316
-rw-r--r--doc/src/examples/bearermonitor.qdoc35
-rw-r--r--doc/src/examples/customtypesending.qdoc121
-rw-r--r--doc/src/examples/dbus-chat.qdoc36
-rw-r--r--doc/src/examples/digiflip.qdoc31
-rw-r--r--doc/src/examples/fingerpaint.qdoc42
-rw-r--r--doc/src/examples/flickable.qdoc33
-rw-r--r--doc/src/examples/flightinfo.qdoc33
-rw-r--r--doc/src/examples/htmlinfo.qdoc68
-rw-r--r--doc/src/examples/lightmaps.qdoc33
-rw-r--r--doc/src/examples/pinchzoom.qdoc38
-rw-r--r--doc/src/examples/raycasting.qdoc33
-rw-r--r--doc/src/examples/rsslisting.qdoc36
-rw-r--r--doc/src/examples/styleexample.qdoc33
-rw-r--r--doc/src/images/gradients-demo.pngbin93147 -> 85199 bytes
-rw-r--r--examples/corelib/serialization/cbordump/cbordump.pro14
-rw-r--r--examples/corelib/serialization/cbordump/main.cpp765
-rw-r--r--examples/corelib/serialization/cbordump/tag-transform.xslt25
-rw-r--r--examples/corelib/serialization/convert/cborconverter.cpp393
-rw-r--r--examples/corelib/serialization/convert/cborconverter.h85
-rw-r--r--examples/corelib/serialization/convert/convert.pro29
-rw-r--r--examples/corelib/serialization/convert/converter.h103
-rw-r--r--examples/corelib/serialization/convert/datastreamconverter.cpp273
-rw-r--r--examples/corelib/serialization/convert/datastreamconverter.h85
-rw-r--r--examples/corelib/serialization/convert/jsonconverter.cpp212
-rw-r--r--examples/corelib/serialization/convert/jsonconverter.h85
-rw-r--r--examples/corelib/serialization/convert/main.cpp234
-rw-r--r--examples/corelib/serialization/convert/nullconverter.cpp99
-rw-r--r--examples/corelib/serialization/convert/nullconverter.h69
-rw-r--r--examples/corelib/serialization/convert/textconverter.cpp160
-rw-r--r--examples/corelib/serialization/convert/textconverter.h70
-rw-r--r--examples/corelib/serialization/convert/xmlconverter.cpp514
-rw-r--r--examples/corelib/serialization/convert/xmlconverter.h69
-rw-r--r--examples/corelib/serialization/serialization.pro5
-rw-r--r--examples/corelib/threads/queuedcustomtype/window.cpp3
-rw-r--r--examples/examples.pro3
-rw-r--r--examples/gui/doc/src/rasterwindow.qdoc5
-rw-r--r--examples/gui/rasterwindow/rasterwindow.cpp4
-rw-r--r--examples/network/doc/images/secureudpclient-example.pngbin0 -> 23211 bytes
-rw-r--r--examples/network/doc/images/secureudpserver-example.pngbin0 -> 38412 bytes
-rw-r--r--examples/network/doc/src/secureudpclient.qdoc124
-rw-r--r--examples/network/doc/src/secureudpserver.qdoc131
-rw-r--r--examples/network/loopback/dialog.cpp55
-rw-r--r--examples/network/loopback/dialog.h27
-rw-r--r--examples/network/loopback/main.cpp4
-rw-r--r--examples/network/network-chat/client.cpp2
-rw-r--r--examples/network/network-chat/connection.cpp264
-rw-r--r--examples/network/network-chat/connection.h17
-rw-r--r--examples/network/network-chat/peermanager.cpp54
-rw-r--r--examples/network/network-chat/peermanager.h4
-rw-r--r--examples/network/network-chat/server.cpp3
-rw-r--r--examples/network/network.pro1
-rw-r--r--examples/network/secureudpclient/addressdialog.cpp118
-rw-r--r--examples/network/secureudpclient/addressdialog.h85
-rw-r--r--examples/network/secureudpclient/addressdialog.ui132
-rw-r--r--examples/network/secureudpclient/association.cpp197
-rw-r--r--examples/network/secureudpclient/association.h97
-rw-r--r--examples/network/secureudpclient/main.cpp64
-rw-r--r--examples/network/secureudpclient/mainwindow.cpp185
-rw-r--r--examples/network/secureudpclient/mainwindow.h111
-rw-r--r--examples/network/secureudpclient/mainwindow.ui198
-rw-r--r--examples/network/secureudpclient/secureudpclient.pro22
-rw-r--r--examples/network/secureudpserver/main.cpp64
-rw-r--r--examples/network/secureudpserver/mainwindow.cpp138
-rw-r--r--examples/network/secureudpserver/mainwindow.h92
-rw-r--r--examples/network/secureudpserver/mainwindow.ui207
-rw-r--r--examples/network/secureudpserver/nicselector.cpp95
-rw-r--r--examples/network/secureudpserver/nicselector.h84
-rw-r--r--examples/network/secureudpserver/nicselector.ui144
-rw-r--r--examples/network/secureudpserver/secureudpserver.pro21
-rw-r--r--examples/network/secureudpserver/server.cpp277
-rw-r--r--examples/network/secureudpserver/server.h107
-rw-r--r--examples/opengl/contextinfo/widget.cpp2
-rw-r--r--examples/opengl/qopenglwindow/main.cpp15
-rw-r--r--examples/touch/dials/dials.pro8
-rw-r--r--examples/touch/dials/doc/src/touch-dials.qdoc38
-rw-r--r--examples/touch/fingerpaint/fingerpaint.pro13
-rw-r--r--examples/touch/knobs/doc/src/touch-knobs.qdoc38
-rw-r--r--examples/touch/knobs/knobs.pro8
-rw-r--r--examples/touch/pinchzoom/pinchzoom.pro16
-rw-r--r--examples/vulkan/hellovulkantexture/hellovulkantexture.cpp16
-rw-r--r--examples/widgets/doc/src/customsortfiltermodel.qdoc16
-rw-r--r--examples/widgets/doc/src/gradients.qdoc7
-rw-r--r--examples/widgets/graphicsview/boxes/glextensions.h15
-rw-r--r--examples/widgets/graphicsview/boxes/scene.cpp16
-rw-r--r--examples/widgets/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp17
-rw-r--r--examples/widgets/mainwindows/mainwindow/mainwindow.cpp1
-rw-r--r--examples/widgets/painting/affine/affine.pro4
-rw-r--r--examples/widgets/painting/affine/xform.cpp8
-rw-r--r--examples/widgets/painting/composition/composition.cpp129
-rw-r--r--examples/widgets/painting/composition/composition.h18
-rw-r--r--examples/widgets/painting/composition/composition.pro4
-rw-r--r--examples/widgets/painting/composition/main.cpp7
-rw-r--r--examples/widgets/painting/deform/deform.pro4
-rw-r--r--examples/widgets/painting/deform/pathdeform.cpp35
-rw-r--r--examples/widgets/painting/gradients/gradients.cpp66
-rw-r--r--examples/widgets/painting/gradients/gradients.h7
-rw-r--r--examples/widgets/painting/gradients/gradients.html6
-rw-r--r--examples/widgets/painting/gradients/gradients.pro4
-rw-r--r--examples/widgets/painting/pathstroke/pathstroke.cpp16
-rw-r--r--examples/widgets/painting/pathstroke/pathstroke.pro4
-rw-r--r--examples/widgets/painting/shared/arthurwidgets.cpp80
-rw-r--r--examples/widgets/painting/shared/arthurwidgets.h46
-rw-r--r--examples/widgets/painting/shared/fbopaintdevice.cpp113
-rw-r--r--examples/widgets/painting/shared/fbopaintdevice.h91
-rw-r--r--examples/widgets/painting/shared/hoverpoints.cpp19
-rw-r--r--examples/widgets/painting/shared/shared.pri6
-rw-r--r--examples/widgets/richtext/calendar/mainwindow.cpp6
-rw-r--r--examples/widgets/richtext/textedit/example.html14
-rw-r--r--examples/widgets/richtext/textedit/textedit.cpp140
-rw-r--r--examples/widgets/tools/undo/main.cpp2
-rw-r--r--examples/widgets/touch/dials/dials.pro8
-rw-r--r--examples/widgets/touch/dials/dials.ui (renamed from examples/touch/dials/dials.ui)0
-rw-r--r--examples/widgets/touch/dials/doc/images/touch-dials-example.png (renamed from examples/touch/dials/doc/images/touch-dials-example.png)bin17676 -> 17676 bytes
-rw-r--r--examples/widgets/touch/dials/doc/src/touch-dials.qdoc38
-rw-r--r--examples/widgets/touch/dials/main.cpp (renamed from examples/touch/dials/main.cpp)0
-rw-r--r--examples/widgets/touch/fingerpaint/doc/src/fingerpaint.qdoc42
-rw-r--r--examples/widgets/touch/fingerpaint/fingerpaint.pro13
-rw-r--r--examples/widgets/touch/fingerpaint/main.cpp (renamed from examples/touch/fingerpaint/main.cpp)0
-rw-r--r--examples/widgets/touch/fingerpaint/mainwindow.cpp (renamed from examples/touch/fingerpaint/mainwindow.cpp)0
-rw-r--r--examples/widgets/touch/fingerpaint/mainwindow.h (renamed from examples/touch/fingerpaint/mainwindow.h)0
-rw-r--r--examples/widgets/touch/fingerpaint/scribblearea.cpp (renamed from examples/touch/fingerpaint/scribblearea.cpp)0
-rw-r--r--examples/widgets/touch/fingerpaint/scribblearea.h (renamed from examples/touch/fingerpaint/scribblearea.h)0
-rw-r--r--examples/widgets/touch/knobs/doc/images/touch-knobs-example.png (renamed from examples/touch/knobs/doc/images/touch-knobs-example.png)bin1290 -> 1290 bytes
-rw-r--r--examples/widgets/touch/knobs/doc/src/touch-knobs.qdoc38
-rw-r--r--examples/widgets/touch/knobs/knob.cpp (renamed from examples/touch/knobs/knob.cpp)0
-rw-r--r--examples/widgets/touch/knobs/knob.h (renamed from examples/touch/knobs/knob.h)0
-rw-r--r--examples/widgets/touch/knobs/knobs.pro8
-rw-r--r--examples/widgets/touch/knobs/main.cpp (renamed from examples/touch/knobs/main.cpp)0
-rw-r--r--examples/widgets/touch/pinchzoom/doc/images/pinch-zoom-example.pngbin0 -> 42493 bytes
-rw-r--r--examples/widgets/touch/pinchzoom/doc/src/pinchzoom.qdoc38
-rw-r--r--examples/widgets/touch/pinchzoom/graphicsview.cpp (renamed from examples/touch/pinchzoom/graphicsview.cpp)0
-rw-r--r--examples/widgets/touch/pinchzoom/graphicsview.h (renamed from examples/touch/pinchzoom/graphicsview.h)0
-rw-r--r--examples/widgets/touch/pinchzoom/images/cheese.jpg (renamed from examples/touch/pinchzoom/images/cheese.jpg)bin3029 -> 3029 bytes
-rw-r--r--examples/widgets/touch/pinchzoom/main.cpp (renamed from examples/touch/pinchzoom/main.cpp)0
-rw-r--r--examples/widgets/touch/pinchzoom/mice.qrc (renamed from examples/touch/pinchzoom/mice.qrc)0
-rw-r--r--examples/widgets/touch/pinchzoom/mouse.cpp (renamed from examples/touch/pinchzoom/mouse.cpp)0
-rw-r--r--examples/widgets/touch/pinchzoom/mouse.h (renamed from examples/touch/pinchzoom/mouse.h)0
-rw-r--r--examples/widgets/touch/pinchzoom/pinchzoom.pro16
-rw-r--r--examples/widgets/touch/touch.pro (renamed from examples/touch/touch.pro)0
-rw-r--r--examples/widgets/widgets.pro1
-rw-r--r--examples/widgets/widgets/tablet/mainwindow.cpp16
-rw-r--r--examples/widgets/widgets/tablet/mainwindow.h3
-rw-r--r--examples/widgets/widgets/tablet/tablet.pro5
-rw-r--r--examples/widgets/widgets/tablet/tabletcanvas.cpp12
-rw-r--r--examples/widgets/widgets/tablet/tabletcanvas.h1
-rw-r--r--header.MIT28
-rw-r--r--mkspecs/android-clang/qmake.conf6
-rw-r--r--mkspecs/common/android-base-head.conf7
-rw-r--r--mkspecs/common/android-base-tail.conf2
-rw-r--r--mkspecs/common/clang.conf2
-rw-r--r--mkspecs/common/g++-base.conf2
-rw-r--r--mkspecs/common/gcc-base.conf8
-rw-r--r--mkspecs/common/icc-base-unix.conf106
-rw-r--r--mkspecs/common/macx.conf7
-rw-r--r--mkspecs/common/msvc-desktop.conf4
-rw-r--r--mkspecs/common/msvc-version.conf6
-rw-r--r--mkspecs/common/qcc-base-qnx.conf10
-rw-r--r--mkspecs/common/winrt_winphone/qmake.conf4
-rw-r--r--mkspecs/features/ctest_testcase_common.prf4
-rw-r--r--mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in3
-rw-r--r--mkspecs/features/data/macros.cpp3
-rw-r--r--mkspecs/features/default_post.prf17
-rw-r--r--mkspecs/features/exclusive_builds.prf4
-rw-r--r--mkspecs/features/gc_binaries.prf3
-rw-r--r--mkspecs/features/lrelease.prf41
-rw-r--r--mkspecs/features/mac/default_post.prf23
-rw-r--r--mkspecs/features/qml_module.prf14
-rw-r--r--mkspecs/features/qml_plugin.prf10
-rw-r--r--mkspecs/features/qt.prf11
-rw-r--r--mkspecs/features/qt_app.prf3
-rw-r--r--mkspecs/features/qt_build_config.prf1
-rw-r--r--mkspecs/features/qt_common.prf32
-rw-r--r--mkspecs/features/qt_configure.prf167
-rw-r--r--mkspecs/features/qt_module.prf13
-rw-r--r--mkspecs/features/qt_test_helper.prf35
-rw-r--r--mkspecs/features/resources.prf36
-rw-r--r--mkspecs/features/simd.prf27
-rw-r--r--mkspecs/features/testcase.prf41
-rw-r--r--mkspecs/features/toolchain.prf37
-rw-r--r--mkspecs/features/uic.prf4
-rw-r--r--mkspecs/features/uikit/default_pre.prf2
-rw-r--r--mkspecs/features/uikit/gc_binaries.prf2
-rw-r--r--mkspecs/features/unix/separate_debug_info.prf10
-rw-r--r--mkspecs/features/wasm/qt.prf12
-rw-r--r--mkspecs/features/wasm/wasm.prf81
-rw-r--r--mkspecs/linux-icc/qmake.conf116
-rw-r--r--mkspecs/macx-clang/Info.plist.disable_highdpi8
-rw-r--r--mkspecs/macx-clang/qmake.conf4
-rw-r--r--mkspecs/macx-g++/qmake.conf4
-rw-r--r--mkspecs/macx-icc/qmake.conf88
-rw-r--r--mkspecs/macx-ios-clang/qmake.conf2
-rw-r--r--mkspecs/macx-tvos-clang/qmake.conf2
-rw-r--r--mkspecs/macx-watchos-clang/qmake.conf2
-rw-r--r--mkspecs/macx-xcode/default.xcscheme10
-rw-r--r--mkspecs/wasm-emscripten/qmake.conf90
-rw-r--r--mkspecs/wasm-emscripten/qplatformdefs.h181
-rw-r--r--mkspecs/win32-icc/qmake.conf1
-rw-r--r--qmake/Makefile.unix6
-rw-r--r--qmake/Makefile.win321
-rw-r--r--qmake/doc/src/qmake-manual.qdoc140
-rw-r--r--qmake/generators/mac/pbuilder_pbx.cpp38
-rw-r--r--qmake/generators/mac/pbuilder_pbx.h12
-rw-r--r--qmake/generators/makefile.cpp237
-rw-r--r--qmake/generators/makefile.h17
-rw-r--r--qmake/generators/makefiledeps.cpp28
-rw-r--r--qmake/generators/metamakefile.cpp28
-rw-r--r--qmake/generators/metamakefile.h2
-rw-r--r--qmake/generators/projectgenerator.cpp19
-rw-r--r--qmake/generators/projectgenerator.h10
-rw-r--r--qmake/generators/unix/unixmake.cpp70
-rw-r--r--qmake/generators/unix/unixmake.h25
-rw-r--r--qmake/generators/unix/unixmake2.cpp102
-rw-r--r--qmake/generators/win32/mingw_make.cpp56
-rw-r--r--qmake/generators/win32/mingw_make.h28
-rw-r--r--qmake/generators/win32/msbuild_objectmodel.cpp2
-rw-r--r--qmake/generators/win32/msbuild_objectmodel.h44
-rw-r--r--qmake/generators/win32/msvc_nmake.cpp11
-rw-r--r--qmake/generators/win32/msvc_nmake.h18
-rw-r--r--qmake/generators/win32/msvc_objectmodel.cpp2
-rw-r--r--qmake/generators/win32/msvc_objectmodel.h34
-rw-r--r--qmake/generators/win32/msvc_vcproj.cpp52
-rw-r--r--qmake/generators/win32/msvc_vcproj.h18
-rw-r--r--qmake/generators/win32/msvc_vcxproj.h2
-rw-r--r--qmake/generators/win32/registry.cpp6
-rw-r--r--qmake/generators/win32/winmakefile.cpp43
-rw-r--r--qmake/generators/win32/winmakefile.h14
-rw-r--r--qmake/library/ioutils.cpp6
-rw-r--r--qmake/library/proitems.h59
-rw-r--r--qmake/library/qmakebuiltins.cpp1470
-rw-r--r--qmake/library/qmakeevaluator.cpp35
-rw-r--r--qmake/library/qmakeevaluator.h14
-rw-r--r--qmake/library/qmakeevaluator_p.h22
-rw-r--r--qmake/library/qmakeparser.cpp18
-rw-r--r--qmake/library/qmakeparser.h4
-rw-r--r--qmake/library/qmakevfs.cpp37
-rw-r--r--qmake/library/qmakevfs.h6
-rw-r--r--qmake/main.cpp36
-rw-r--r--qmake/meta.cpp121
-rw-r--r--qmake/meta.h9
-rw-r--r--qmake/option.cpp4
-rw-r--r--qmake/option.h10
-rw-r--r--qmake/project.cpp10
-rw-r--r--qmake/property.cpp4
-rw-r--r--src/3rdparty/angle/AUTHORS9
-rw-r--r--src/3rdparty/angle/CONTRIBUTORS20
-rw-r--r--src/3rdparty/angle/LICENSE64
-rw-r--r--src/3rdparty/angle/SYSTEMINFO_LICENSE22
-rw-r--r--src/3rdparty/angle/TRACEEVENT_LICENSE27
-rw-r--r--src/3rdparty/angle/id/commit.h14
-rw-r--r--src/3rdparty/angle/include/EGL/egl.h24
-rw-r--r--src/3rdparty/angle/include/EGL/eglext.h464
-rw-r--r--src/3rdparty/angle/include/EGL/eglext_angle.h170
-rw-r--r--src/3rdparty/angle/include/EGL/eglplatform.h31
-rw-r--r--src/3rdparty/angle/include/GLES2/gl2.h14
-rw-r--r--src/3rdparty/angle/include/GLES2/gl2ext.h544
-rw-r--r--src/3rdparty/angle/include/GLES2/gl2ext_angle.h551
-rw-r--r--src/3rdparty/angle/include/GLES3/gl3ext.h24
-rw-r--r--src/3rdparty/angle/include/GLSLANG/ShaderLang.h667
-rw-r--r--src/3rdparty/angle/include/GLSLANG/ShaderVars.h161
-rw-r--r--src/3rdparty/angle/include/KHR/khrplatform.h9
-rw-r--r--src/3rdparty/angle/include/angle_gl.h5
-rw-r--r--src/3rdparty/angle/include/export.h8
-rw-r--r--src/3rdparty/angle/include/platform/Platform.h411
-rw-r--r--src/3rdparty/angle/include/platform/WorkaroundsD3D.h130
-rw-r--r--src/3rdparty/angle/qt_attribution.json4
-rw-r--r--src/3rdparty/angle/src/common/BitSetIterator.h156
-rw-r--r--src/3rdparty/angle/src/common/Color.h53
-rw-r--r--src/3rdparty/angle/src/common/Color.inl37
-rw-r--r--src/3rdparty/angle/src/common/MemoryBuffer.cpp105
-rw-r--r--src/3rdparty/angle/src/common/MemoryBuffer.h55
-rw-r--r--src/3rdparty/angle/src/common/Optional.h33
-rw-r--r--src/3rdparty/angle/src/common/angleutils.cpp62
-rw-r--r--src/3rdparty/angle/src/common/angleutils.h131
-rw-r--r--src/3rdparty/angle/src/common/bitset_utils.h498
-rw-r--r--src/3rdparty/angle/src/common/debug.cpp226
-rw-r--r--src/3rdparty/angle/src/common/debug.h266
-rw-r--r--src/3rdparty/angle/src/common/event_tracer.cpp37
-rw-r--r--src/3rdparty/angle/src/common/event_tracer.h14
-rw-r--r--src/3rdparty/angle/src/common/mathutil.cpp20
-rw-r--r--src/3rdparty/angle/src/common/mathutil.h571
-rw-r--r--src/3rdparty/angle/src/common/matrix_utils.h37
-rw-r--r--src/3rdparty/angle/src/common/platform.h47
-rw-r--r--src/3rdparty/angle/src/common/string_utils.cpp77
-rw-r--r--src/3rdparty/angle/src/common/string_utils.h38
-rw-r--r--src/3rdparty/angle/src/common/system_utils.h27
-rw-r--r--src/3rdparty/angle/src/common/system_utils_linux.cpp89
-rw-r--r--src/3rdparty/angle/src/common/system_utils_mac.cpp94
-rw-r--r--src/3rdparty/angle/src/common/system_utils_win.cpp79
-rw-r--r--src/3rdparty/angle/src/common/third_party/base/README.angle27
-rw-r--r--src/3rdparty/angle/src/common/third_party/base/anglebase/base_export.h13
-rw-r--r--src/3rdparty/angle/src/common/third_party/base/anglebase/containers/mru_cache.h275
-rw-r--r--src/3rdparty/angle/src/common/third_party/base/anglebase/logging.h26
-rw-r--r--src/3rdparty/angle/src/common/third_party/base/anglebase/macros.h17
-rw-r--r--src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/OWNERS3
-rw-r--r--src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_conversions.h179
-rw-r--r--src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_conversions_impl.h274
-rw-r--r--src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_math.h329
-rw-r--r--src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_math_impl.h575
-rw-r--r--src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_numerics_unittest.cc771
-rw-r--r--src/3rdparty/angle/src/common/third_party/base/anglebase/sha1.cc245
-rw-r--r--src/3rdparty/angle/src/common/third_party/base/anglebase/sha1.h36
-rw-r--r--src/3rdparty/angle/src/common/third_party/base/anglebase/sys_byteorder.h49
-rw-r--r--src/3rdparty/angle/src/common/third_party/smhasher/LICENSE23
-rw-r--r--src/3rdparty/angle/src/common/third_party/smhasher/README.angle14
-rw-r--r--src/3rdparty/angle/src/common/third_party/smhasher/src/PMurHash.cpp320
-rw-r--r--src/3rdparty/angle/src/common/third_party/smhasher/src/PMurHash.h59
-rw-r--r--src/3rdparty/angle/src/common/tls.cpp4
-rw-r--r--src/3rdparty/angle/src/common/uniform_type_info_autogen.cpp275
-rw-r--r--src/3rdparty/angle/src/common/utilities.cpp338
-rw-r--r--src/3rdparty/angle/src/common/utilities.h97
-rw-r--r--src/3rdparty/angle/src/common/vector_utils.h523
-rw-r--r--src/3rdparty/angle/src/compiler/fuzz/translator_fuzzer.cpp179
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp214
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h17
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.cpp2
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h6
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp630
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h24
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h8
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y85
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Input.cpp31
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Input.h26
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Lexer.cpp2
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Lexer.h4
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Macro.cpp35
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Macro.h12
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp297
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h55
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp72
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h20
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h12
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Token.cpp21
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Token.h29
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h17
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l55
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h18
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/pp_utils.h18
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.cpp155
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.h17
-rw-r--r--src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.cpp59
-rw-r--r--src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.h20
-rw-r--r--src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.cpp58
-rw-r--r--src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.h22
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp227
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h12
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BaseTypes.h958
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp107
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.h23
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp308
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h192
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp166
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h21
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp551
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h11
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Cache.cpp41
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Cache.h36
-rw-r--r--src/3rdparty/angle/src/compiler/translator/CallDAG.cpp261
-rw-r--r--src/3rdparty/angle/src/compiler/translator/CallDAG.h16
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ClampPointSize.cpp47
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ClampPointSize.h22
-rw-r--r--src/3rdparty/angle/src/compiler/translator/CodeGen.cpp81
-rw-r--r--src/3rdparty/angle/src/compiler/translator/CollectVariables.cpp869
-rw-r--r--src/3rdparty/angle/src/compiler/translator/CollectVariables.h37
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Common.h73
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Compiler.cpp1111
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Compiler.h221
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ConstantUnion.cpp681
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ConstantUnion.h399
-rw-r--r--src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp221
-rw-r--r--src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h48
-rw-r--r--src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.cpp147
-rw-r--r--src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.h32
-rw-r--r--src/3rdparty/angle/src/compiler/translator/DetectCallDepth.cpp185
-rw-r--r--src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h78
-rw-r--r--src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.cpp191
-rw-r--r--src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h71
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp105
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Diagnostics.h46
-rw-r--r--src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp139
-rw-r--r--src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h14
-rw-r--r--src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.cpp129
-rw-r--r--src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.h31
-rw-r--r--src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp868
-rw-r--r--src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h25
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.cpp153
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.h29
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.cpp96
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h65
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.cpp5
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.h7
-rw-r--r--src/3rdparty/angle/src/compiler/translator/FindMain.cpp38
-rw-r--r--src/3rdparty/angle/src/compiler/translator/FindMain.h23
-rw-r--r--src/3rdparty/angle/src/compiler/translator/FindSymbolNode.cpp58
-rw-r--r--src/3rdparty/angle/src/compiler/translator/FindSymbolNode.h27
-rw-r--r--src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.cpp88
-rw-r--r--src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h37
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.cpp97
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h53
-rw-r--r--src/3rdparty/angle/src/compiler/translator/HashNames.cpp72
-rw-r--r--src/3rdparty/angle/src/compiler/translator/HashNames.h14
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.cpp304
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.h76
-rw-r--r--src/3rdparty/angle/src/compiler/translator/InfoSink.cpp38
-rw-r--r--src/3rdparty/angle/src/compiler/translator/InfoSink.h78
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Initialize.cpp1252
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Initialize.h23
-rw-r--r--src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp15
-rw-r--r--src/3rdparty/angle/src/compiler/translator/InitializeDll.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h2
-rw-r--r--src/3rdparty/angle/src/compiler/translator/InitializeParseContext.cpp42
-rw-r--r--src/3rdparty/angle/src/compiler/translator/InitializeParseContext.h17
-rw-r--r--src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp325
-rw-r--r--src/3rdparty/angle/src/compiler/translator/InitializeVariables.h76
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IntermNode.cpp3818
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IntermNode.h847
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.cpp157
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.h75
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IntermNode_util.cpp254
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IntermNode_util.h60
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp630
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IntermTraverse.h355
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Intermediate.cpp508
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Intermediate.h75
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.cpp51
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.h20
-rw-r--r--src/3rdparty/angle/src/compiler/translator/LoopInfo.cpp211
-rw-r--r--src/3rdparty/angle/src/compiler/translator/LoopInfo.h80
-rw-r--r--src/3rdparty/angle/src/compiler/translator/MMap.h56
-rw-r--r--src/3rdparty/angle/src/compiler/translator/NodeSearch.h19
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Operator.cpp554
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Operator.h126
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp17
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputESSL.h23
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp80
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputGLSL.h17
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp1846
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h76
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp3540
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputHLSL.h186
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputTree.cpp682
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputTree.h22
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.cpp80
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.h34
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ParamType.h102
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ParseContext.cpp6080
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ParseContext.h767
-rw-r--r--src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp227
-rw-r--r--src/3rdparty/angle/src/compiler/translator/PoolAlloc.h220
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Pragma.h9
-rw-r--r--src/3rdparty/angle/src/compiler/translator/PruneEmptyDeclarations.cpp81
-rw-r--r--src/3rdparty/angle/src/compiler/translator/PruneEmptyDeclarations.h15
-rw-r--r--src/3rdparty/angle/src/compiler/translator/PruneNoOps.cpp156
-rw-r--r--src/3rdparty/angle/src/compiler/translator/PruneNoOps.h24
-rw-r--r--src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp58
-rw-r--r--src/3rdparty/angle/src/compiler/translator/QualifierAlive.h12
-rw-r--r--src/3rdparty/angle/src/compiler/translator/QualifierTypes.cpp784
-rw-r--r--src/3rdparty/angle/src/compiler/translator/QualifierTypes.h191
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.cpp94
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.h23
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp34
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h20
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.cpp83
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.h29
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.cpp319
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.h12
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.cpp56
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.h18
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.cpp43
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.h18
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.cpp116
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h21
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemovePow.cpp36
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemovePow.h5
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp187
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h42
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.cpp358
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.h24
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RenameFunction.h36
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.cpp62
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.h9
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp112
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h8
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.cpp154
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.h28
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.cpp94
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.h19
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp112
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.h20
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.cpp112
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.h23
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp275
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h49
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp3
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SearchSymbol.h4
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.cpp76
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.cpp52
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.h7
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp145
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.h12
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Severity.h22
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp426
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp397
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.cpp38
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.h25
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.cpp300
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.h25
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.cpp171
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.h28
-rw-r--r--src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp448
-rw-r--r--src/3rdparty/angle/src/compiler/translator/StructureHLSL.h41
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp448
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SymbolTable.h494
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.cpp28
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.h36
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.cpp1322
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.h76
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp146
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h15
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp214
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h17
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp119
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h21
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.cpp173
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.h34
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Types.cpp1045
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Types.h675
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp185
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h38
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp44
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h12
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.cpp318
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.h13
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp434
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UniformHLSL.h85
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.cpp105
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.h30
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp794
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h85
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.cpp62
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.h11
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp393
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h58
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.cpp29
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.h21
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp116
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h34
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp179
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h52
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.cpp174
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.h25
-rw-r--r--src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp673
-rw-r--r--src/3rdparty/angle/src/compiler/translator/VariableInfo.h77
-rw-r--r--src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp394
-rw-r--r--src/3rdparty/angle/src/compiler/translator/VariablePacker.h39
-rw-r--r--src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp284
-rw-r--r--src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.h25
-rw-r--r--src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp145
-rw-r--r--src/3rdparty/angle/src/compiler/translator/VersionGLSL.h14
-rw-r--r--src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.cpp132
-rw-r--r--src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.h22
-rw-r--r--src/3rdparty/angle/src/compiler/translator/blocklayout.cpp191
-rw-r--r--src/3rdparty/angle/src/compiler/translator/blocklayout.h75
-rw-r--r--src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp63
-rw-r--r--src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h32
-rw-r--r--src/3rdparty/angle/src/compiler/translator/compilerdebug.cpp37
-rw-r--r--src/3rdparty/angle/src/compiler/translator/compilerdebug.h53
-rw-r--r--src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.cpp95
-rw-r--r--src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h199
-rw-r--r--src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp255
-rw-r--r--src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h199
-rw-r--r--src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.cpp64
-rw-r--r--src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h31
-rw-r--r--src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphTraverse.cpp69
-rw-r--r--src/3rdparty/angle/src/compiler/translator/emulated_builtin_function_data_hlsl.json1382
-rw-r--r--src/3rdparty/angle/src/compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp859
-rw-r--r--src/3rdparty/angle/src/compiler/translator/glslang.h16
-rw-r--r--src/3rdparty/angle/src/compiler/translator/glslang.l183
-rw-r--r--src/3rdparty/angle/src/compiler/translator/glslang.y1027
-rw-r--r--src/3rdparty/angle/src/compiler/translator/intermOut.cpp626
-rw-r--r--src/3rdparty/angle/src/compiler/translator/length_limits.h7
-rw-r--r--src/3rdparty/angle/src/compiler/translator/parseConst.cpp264
-rw-r--r--src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp130
-rw-r--r--src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h39
-rw-r--r--src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp17
-rw-r--r--src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h32
-rw-r--r--src/3rdparty/angle/src/compiler/translator/util.cpp780
-rw-r--r--src/3rdparty/angle/src/compiler/translator/util.h60
-rw-r--r--src/3rdparty/angle/src/gpu_info_util/SystemInfo.cpp171
-rw-r--r--src/3rdparty/angle/src/gpu_info_util/SystemInfo.h73
-rw-r--r--src/3rdparty/angle/src/gpu_info_util/SystemInfo_internal.h38
-rw-r--r--src/3rdparty/angle/src/gpu_info_util/SystemInfo_libpci.cpp132
-rw-r--r--src/3rdparty/angle/src/gpu_info_util/SystemInfo_linux.cpp144
-rw-r--r--src/3rdparty/angle/src/gpu_info_util/SystemInfo_mac.mm170
-rw-r--r--src/3rdparty/angle/src/gpu_info_util/SystemInfo_win.cpp251
-rw-r--r--src/3rdparty/angle/src/gpu_info_util/SystemInfo_x11.cpp53
-rw-r--r--src/3rdparty/angle/src/id/commit.h3
-rw-r--r--src/3rdparty/angle/src/image_util/copyimage.cpp22
-rw-r--r--src/3rdparty/angle/src/image_util/copyimage.h36
-rw-r--r--src/3rdparty/angle/src/image_util/copyimage.inl34
-rw-r--r--src/3rdparty/angle/src/image_util/generatemip.h34
-rw-r--r--src/3rdparty/angle/src/image_util/generatemip.inl268
-rw-r--r--src/3rdparty/angle/src/image_util/imageformats.cpp1722
-rw-r--r--src/3rdparty/angle/src/image_util/imageformats.h700
-rw-r--r--src/3rdparty/angle/src/image_util/loadimage.cpp1323
-rw-r--r--src/3rdparty/angle/src/image_util/loadimage.h658
-rw-r--r--src/3rdparty/angle/src/image_util/loadimage.inl163
-rw-r--r--src/3rdparty/angle/src/image_util/loadimage_etc.cpp1729
-rw-r--r--src/3rdparty/angle/src/libANGLE/AttributeMap.cpp85
-rw-r--r--src/3rdparty/angle/src/libANGLE/AttributeMap.h22
-rw-r--r--src/3rdparty/angle/src/libANGLE/BinaryStream.h97
-rw-r--r--src/3rdparty/angle/src/libANGLE/Buffer.cpp187
-rw-r--r--src/3rdparty/angle/src/libANGLE/Buffer.h100
-rw-r--r--src/3rdparty/angle/src/libANGLE/Caps.cpp940
-rw-r--r--src/3rdparty/angle/src/libANGLE/Caps.h291
-rw-r--r--src/3rdparty/angle/src/libANGLE/Compiler.cpp143
-rw-r--r--src/3rdparty/angle/src/libANGLE/Compiler.h20
-rw-r--r--src/3rdparty/angle/src/libANGLE/Config.cpp36
-rw-r--r--src/3rdparty/angle/src/libANGLE/Config.h11
-rw-r--r--src/3rdparty/angle/src/libANGLE/Constants.h40
-rw-r--r--src/3rdparty/angle/src/libANGLE/Context.cpp5684
-rw-r--r--src/3rdparty/angle/src/libANGLE/Context.h1039
-rw-r--r--src/3rdparty/angle/src/libANGLE/ContextState.cpp839
-rw-r--r--src/3rdparty/angle/src/libANGLE/ContextState.h164
-rw-r--r--src/3rdparty/angle/src/libANGLE/Data.cpp56
-rw-r--r--src/3rdparty/angle/src/libANGLE/Data.h72
-rw-r--r--src/3rdparty/angle/src/libANGLE/Debug.cpp24
-rw-r--r--src/3rdparty/angle/src/libANGLE/Debug.h9
-rw-r--r--src/3rdparty/angle/src/libANGLE/Device.cpp21
-rw-r--r--src/3rdparty/angle/src/libANGLE/Display.cpp812
-rw-r--r--src/3rdparty/angle/src/libANGLE/Display.h124
-rw-r--r--src/3rdparty/angle/src/libANGLE/Error.cpp58
-rw-r--r--src/3rdparty/angle/src/libANGLE/Error.h205
-rw-r--r--src/3rdparty/angle/src/libANGLE/Error.inl32
-rw-r--r--src/3rdparty/angle/src/libANGLE/ErrorStrings.h173
-rw-r--r--src/3rdparty/angle/src/libANGLE/Fence.cpp48
-rw-r--r--src/3rdparty/angle/src/libANGLE/Fence.h16
-rw-r--r--src/3rdparty/angle/src/libANGLE/Framebuffer.cpp2021
-rw-r--r--src/3rdparty/angle/src/libANGLE/Framebuffer.h319
-rw-r--r--src/3rdparty/angle/src/libANGLE/FramebufferAttachment.cpp227
-rw-r--r--src/3rdparty/angle/src/libANGLE/FramebufferAttachment.h186
-rw-r--r--src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp34
-rw-r--r--src/3rdparty/angle/src/libANGLE/HandleAllocator.h8
-rw-r--r--src/3rdparty/angle/src/libANGLE/HandleRangeAllocator.cpp229
-rw-r--r--src/3rdparty/angle/src/libANGLE/HandleRangeAllocator.h60
-rw-r--r--src/3rdparty/angle/src/libANGLE/Image.cpp205
-rw-r--r--src/3rdparty/angle/src/libANGLE/Image.h66
-rw-r--r--src/3rdparty/angle/src/libANGLE/ImageIndex.cpp130
-rw-r--r--src/3rdparty/angle/src/libANGLE/ImageIndex.h14
-rw-r--r--src/3rdparty/angle/src/libANGLE/IndexRangeCache.cpp8
-rw-r--r--src/3rdparty/angle/src/libANGLE/IndexRangeCache.h3
-rw-r--r--src/3rdparty/angle/src/libANGLE/LoggingAnnotator.cpp44
-rw-r--r--src/3rdparty/angle/src/libANGLE/LoggingAnnotator.h31
-rw-r--r--src/3rdparty/angle/src/libANGLE/MemoryProgramCache.cpp772
-rw-r--r--src/3rdparty/angle/src/libANGLE/MemoryProgramCache.h130
-rw-r--r--src/3rdparty/angle/src/libANGLE/PackedGLEnums.h111
-rw-r--r--src/3rdparty/angle/src/libANGLE/PackedGLEnums_autogen.cpp174
-rw-r--r--src/3rdparty/angle/src/libANGLE/PackedGLEnums_autogen.h84
-rw-r--r--src/3rdparty/angle/src/libANGLE/Path.cpp78
-rw-r--r--src/3rdparty/angle/src/libANGLE/Path.h71
-rw-r--r--src/3rdparty/angle/src/libANGLE/Platform.cpp56
-rw-r--r--src/3rdparty/angle/src/libANGLE/Program.cpp2889
-rw-r--r--src/3rdparty/angle/src/libANGLE/Program.h641
-rw-r--r--src/3rdparty/angle/src/libANGLE/ProgramLinkedResources.cpp1040
-rw-r--r--src/3rdparty/angle/src/libANGLE/ProgramLinkedResources.h274
-rw-r--r--src/3rdparty/angle/src/libANGLE/ProgramPipeline.cpp65
-rw-r--r--src/3rdparty/angle/src/libANGLE/ProgramPipeline.h65
-rw-r--r--src/3rdparty/angle/src/libANGLE/Query.h3
-rw-r--r--src/3rdparty/angle/src/libANGLE/RefCountObject.cpp39
-rw-r--r--src/3rdparty/angle/src/libANGLE/RefCountObject.h88
-rw-r--r--src/3rdparty/angle/src/libANGLE/Renderbuffer.cpp147
-rw-r--r--src/3rdparty/angle/src/libANGLE/Renderbuffer.h43
-rw-r--r--src/3rdparty/angle/src/libANGLE/ResourceManager.cpp603
-rw-r--r--src/3rdparty/angle/src/libANGLE/ResourceManager.h298
-rw-r--r--src/3rdparty/angle/src/libANGLE/ResourceMap.h305
-rw-r--r--src/3rdparty/angle/src/libANGLE/Sampler.cpp73
-rw-r--r--src/3rdparty/angle/src/libANGLE/Sampler.h19
-rw-r--r--src/3rdparty/angle/src/libANGLE/Shader.cpp373
-rw-r--r--src/3rdparty/angle/src/libANGLE/Shader.h216
-rw-r--r--src/3rdparty/angle/src/libANGLE/SizedMRUCache.h174
-rw-r--r--src/3rdparty/angle/src/libANGLE/State.cpp1260
-rw-r--r--src/3rdparty/angle/src/libANGLE/State.h348
-rw-r--r--src/3rdparty/angle/src/libANGLE/Stream.cpp271
-rw-r--r--src/3rdparty/angle/src/libANGLE/Stream.h143
-rw-r--r--src/3rdparty/angle/src/libANGLE/Surface.cpp369
-rw-r--r--src/3rdparty/angle/src/libANGLE/Surface.h163
-rw-r--r--src/3rdparty/angle/src/libANGLE/Texture.cpp1509
-rw-r--r--src/3rdparty/angle/src/libANGLE/Texture.h359
-rw-r--r--src/3rdparty/angle/src/libANGLE/Thread.cpp91
-rw-r--r--src/3rdparty/angle/src/libANGLE/Thread.h51
-rw-r--r--src/3rdparty/angle/src/libANGLE/TransformFeedback.cpp159
-rw-r--r--src/3rdparty/angle/src/libANGLE/TransformFeedback.h61
-rw-r--r--src/3rdparty/angle/src/libANGLE/Uniform.cpp185
-rw-r--r--src/3rdparty/angle/src/libANGLE/Uniform.h100
-rw-r--r--src/3rdparty/angle/src/libANGLE/VaryingPacking.cpp408
-rw-r--r--src/3rdparty/angle/src/libANGLE/VaryingPacking.h184
-rw-r--r--src/3rdparty/angle/src/libANGLE/Version.h15
-rw-r--r--src/3rdparty/angle/src/libANGLE/Version.inl38
-rw-r--r--src/3rdparty/angle/src/libANGLE/VertexArray.cpp235
-rw-r--r--src/3rdparty/angle/src/libANGLE/VertexArray.h188
-rw-r--r--src/3rdparty/angle/src/libANGLE/VertexAttribute.cpp122
-rw-r--r--src/3rdparty/angle/src/libANGLE/VertexAttribute.h84
-rw-r--r--src/3rdparty/angle/src/libANGLE/VertexAttribute.inl47
-rw-r--r--src/3rdparty/angle/src/libANGLE/Workarounds.h29
-rw-r--r--src/3rdparty/angle/src/libANGLE/WorkerThread.cpp157
-rw-r--r--src/3rdparty/angle/src/libANGLE/WorkerThread.h284
-rw-r--r--src/3rdparty/angle/src/libANGLE/angletypes.cpp162
-rw-r--r--src/3rdparty/angle/src/libANGLE/angletypes.h307
-rw-r--r--src/3rdparty/angle/src/libANGLE/angletypes.inl47
-rw-r--r--src/3rdparty/angle/src/libANGLE/entry_points_enum_autogen.h336
-rw-r--r--src/3rdparty/angle/src/libANGLE/es3_copy_conversion_formats.json44
-rw-r--r--src/3rdparty/angle/src/libANGLE/es3_copy_conversion_table_autogen.cpp171
-rw-r--r--src/3rdparty/angle/src/libANGLE/es3_format_type_combinations.json171
-rw-r--r--src/3rdparty/angle/src/libANGLE/features.h12
-rw-r--r--src/3rdparty/angle/src/libANGLE/format_map_autogen.cpp1570
-rw-r--r--src/3rdparty/angle/src/libANGLE/format_map_data.json142
-rw-r--r--src/3rdparty/angle/src/libANGLE/formatutils.cpp1365
-rw-r--r--src/3rdparty/angle/src/libANGLE/formatutils.h141
-rw-r--r--src/3rdparty/angle/src/libANGLE/histogram_macros.h67
-rw-r--r--src/3rdparty/angle/src/libANGLE/packed_gl_enums.json35
-rw-r--r--src/3rdparty/angle/src/libANGLE/params.cpp68
-rw-r--r--src/3rdparty/angle/src/libANGLE/params.h228
-rw-r--r--src/3rdparty/angle/src/libANGLE/queryconversions.cpp206
-rw-r--r--src/3rdparty/angle/src/libANGLE/queryconversions.h87
-rw-r--r--src/3rdparty/angle/src/libANGLE/queryutils.cpp1916
-rw-r--r--src/3rdparty/angle/src/libANGLE/queryutils.h162
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/BufferImpl.h49
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/BufferImpl_mock.h32
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/ContextImpl.cpp119
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/ContextImpl.h186
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.cpp25
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.h60
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/EGLImplFactory.h68
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/FenceSyncImpl.h35
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/Format.h105
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/Format_ID_autogen.inl147
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/Format_table_autogen.cpp434
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.h54
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl.h65
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl_mock.h57
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/GLImplFactory.h93
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/Image.h77
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/ImageImpl.h16
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/ImageImpl_mock.h10
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/ImplFactory.h74
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/PathImpl.h36
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.cpp152
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.h66
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl_mock.h27
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/ProgramPipelineImpl.h32
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.cpp21
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.h24
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl_mock.h15
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/Renderer.cpp62
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/Renderer.h121
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/SamplerImpl.h20
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/ShaderImpl.h12
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/StreamProducerImpl.h39
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.cpp8
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.h35
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/SyncImpl.h34
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/TextureImpl.cpp63
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/TextureImpl.h136
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/TextureImpl_mock.h116
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl.h9
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl_mock.h8
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/VertexArrayImpl.h14
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/Workarounds.h74
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/angle_format_data.json24
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/angle_format_map.json132
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp208
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.h54
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp10
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.h4
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp27
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.h2
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp195
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.h43
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp714
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h123
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.cpp89
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.h27
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp305
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h83
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp86
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h12
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp30
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.h45
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp27
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.h4
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp250
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.h42
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.cpp23
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.h38
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp2199
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.h329
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h6
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp77
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h25
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp703
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.h391
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/SamplerD3D.h2
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp100
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.h44
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp16
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h7
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp274
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h97
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.cpp34
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h55
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp3088
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.h864
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.cpp39
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.h44
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.cpp46
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.h35
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp397
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/VaryingPacking.h175
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp347
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.h116
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp750
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.h108
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/WorkaroundsD3D.h66
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.cpp22
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.h35
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.inl32
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp2486
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h230
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp1379
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h174
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp1152
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h105
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp405
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h155
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp47
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h6
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp107
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h11
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp461
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h78
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp591
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h67
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp62
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h23
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp464
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h142
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h97
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h38
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp205
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h34
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.cpp24
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h27
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp363
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h47
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp521
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h137
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp359
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h90
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp4100
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h573
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp533
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h366
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp111
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h45
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp2797
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h484
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.cpp102
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h44
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp756
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h123
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp3701
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h555
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp124
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h60
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp9
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h4
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp413
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h82
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp149
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h25
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl45
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_data.json118
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_map_autogen.cpp516
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_data.json623
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp1896
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h5
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp1142
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h56
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/gen_load_functions_table.cpp0
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.cpp170
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h31
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json1116
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table.h31
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp2098
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp2461
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h375
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl644
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/MultiplyAlpha.hlsl131
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl11
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/ResolveDepthStencil.hlsl56
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dms11ps.h155
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_data.json77
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h51
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info_autogen.cpp203
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json1199
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json78
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp35
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h89
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp3037
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h85
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp220
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp217
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h53
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp67
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h48
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp131
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h38
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.cpp126
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h51
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp63
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h10
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp410
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h84
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp82
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h46
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Context9.cpp303
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Context9.h151
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h4
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp19
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h2
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp201
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h38
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp303
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h50
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp33
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h16
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.cpp39
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.h35
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp76
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h20
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp3
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h6
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp2164
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h407
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h10
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp6
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h2
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp98
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h13
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp123
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h30
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp219
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h84
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h24
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp94
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h18
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp46
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h1
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp321
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h26
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp104
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h11
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps34
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs18
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.cpp147
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h28
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.h28
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.inl266
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/imageformats.h1999
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.cpp697
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.h201
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.inl156
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimageSSE2.cpp125
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage_etc.cpp1435
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage_etc.h140
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/driver_utils.cpp120
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/driver_utils.h73
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/load_functions_data.json602
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/load_functions_table.h22
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/load_functions_table_autogen.cpp2459
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/renderer_utils.cpp549
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/renderer_utils.h254
-rw-r--r--src/3rdparty/angle/src/libANGLE/signal_utils.h187
-rw-r--r--src/3rdparty/angle/src/libANGLE/validationEGL.cpp2013
-rw-r--r--src/3rdparty/angle/src/libANGLE/validationEGL.h119
-rw-r--r--src/3rdparty/angle/src/libANGLE/validationES.cpp5533
-rw-r--r--src/3rdparty/angle/src/libANGLE/validationES.h573
-rw-r--r--src/3rdparty/angle/src/libANGLE/validationES2.cpp6313
-rw-r--r--src/3rdparty/angle/src/libANGLE/validationES2.h607
-rw-r--r--src/3rdparty/angle/src/libANGLE/validationES3.cpp3580
-rw-r--r--src/3rdparty/angle/src/libANGLE/validationES3.h415
-rw-r--r--src/3rdparty/angle/src/libANGLE/validationES31.cpp1786
-rw-r--r--src/3rdparty/angle/src/libANGLE/validationES31.h325
-rw-r--r--src/3rdparty/angle/src/libEGL/libEGL.cpp117
-rw-r--r--src/3rdparty/angle/src/libEGL/libEGL.def125
-rw-r--r--src/3rdparty/angle/src/libEGL/libEGL_mingw32.def125
-rw-r--r--src/3rdparty/angle/src/libEGL/libEGLd.def125
-rw-r--r--src/3rdparty/angle/src/libEGL/libEGLd_mingw32.def119
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_egl.cpp1516
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp784
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.h67
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.cpp4155
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.h163
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_autogen.cpp2612
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_autogen.h297
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.cpp2922
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.h610
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.cpp3057
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.h125
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_autogen.cpp2084
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_autogen.h284
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.cpp14
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.h23
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_1_autogen.cpp1430
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_1_autogen.h228
-rw-r--r--src/3rdparty/angle/src/libGLESv2/global_state.cpp250
-rw-r--r--src/3rdparty/angle/src/libGLESv2/global_state.h28
-rw-r--r--src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp1356
-rw-r--r--src/3rdparty/angle/src/libGLESv2/libGLESv2.def105
-rw-r--r--src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def714
-rw-r--r--src/3rdparty/angle/src/libGLESv2/libGLESv2d.def105
-rw-r--r--src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def716
-rw-r--r--src/3rdparty/angle/src/libGLESv2/proc_table.h24
-rw-r--r--src/3rdparty/angle/src/libGLESv2/proc_table_autogen.cpp548
-rw-r--r--src/3rdparty/angle/src/libGLESv2/proc_table_data.json662
-rw-r--r--src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.cpp10
-rw-r--r--src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h10
-rw-r--r--src/3rdparty/angle/src/third_party/libXNVCtrl/LICENSE22
-rw-r--r--src/3rdparty/angle/src/third_party/libXNVCtrl/NVCtrl.c1240
-rw-r--r--src/3rdparty/angle/src/third_party/libXNVCtrl/NVCtrl.h4365
-rw-r--r--src/3rdparty/angle/src/third_party/libXNVCtrl/NVCtrlLib.h707
-rw-r--r--src/3rdparty/angle/src/third_party/libXNVCtrl/README.angle14
-rw-r--r--src/3rdparty/angle/src/third_party/libXNVCtrl/nv_control.h652
-rw-r--r--src/3rdparty/angle/src/third_party/murmurhash/LICENSE2
-rw-r--r--src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.cpp335
-rw-r--r--src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h37
-rw-r--r--src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.cpp2
-rw-r--r--src/3rdparty/angle/src/third_party/trace_event/trace_event.h52
-rw-r--r--src/3rdparty/double-conversion/bignum-dtoa.cc8
-rw-r--r--src/3rdparty/double-conversion/bignum-dtoa.h2
-rw-r--r--src/3rdparty/double-conversion/bignum.cc15
-rw-r--r--src/3rdparty/double-conversion/bignum.h5
-rw-r--r--src/3rdparty/double-conversion/cached-powers.cc15
-rw-r--r--src/3rdparty/double-conversion/cached-powers.h2
-rw-r--r--src/3rdparty/double-conversion/diy-fp.cc4
-rw-r--r--src/3rdparty/double-conversion/diy-fp.h24
-rw-r--r--src/3rdparty/double-conversion/double-conversion.cc281
-rw-r--r--src/3rdparty/double-conversion/double-conversion.pri2
-rw-r--r--src/3rdparty/double-conversion/fast-dtoa.cc8
-rw-r--r--src/3rdparty/double-conversion/fast-dtoa.h2
-rw-r--r--src/3rdparty/double-conversion/fixed-dtoa.cc11
-rw-r--r--src/3rdparty/double-conversion/fixed-dtoa.h2
-rw-r--r--src/3rdparty/double-conversion/ieee.h8
-rw-r--r--src/3rdparty/double-conversion/include/double-conversion/double-conversion.h53
-rw-r--r--src/3rdparty/double-conversion/include/double-conversion/utils.h90
-rw-r--r--src/3rdparty/double-conversion/qt_attribution.json4
-rw-r--r--src/3rdparty/double-conversion/strtod.cc51
-rw-r--r--src/3rdparty/double-conversion/strtod.h2
-rw-r--r--src/3rdparty/freetype/qt_attribution.json2
-rw-r--r--src/3rdparty/gradle/gradle/wrapper/gradle-wrapper.jarbin54213 -> 54329 bytes
-rw-r--r--src/3rdparty/gradle/gradle/wrapper/gradle-wrapper.properties3
-rwxr-xr-xsrc/3rdparty/gradle/gradlew8
-rw-r--r--src/3rdparty/gradle/gradlew.bat2
-rw-r--r--src/3rdparty/harfbuzz-ng/qt_attribution.json2
-rw-r--r--src/3rdparty/harfbuzz/qt_attribution.json2
-rw-r--r--src/3rdparty/libjpeg.pri16
-rw-r--r--src/3rdparty/libjpeg/LICENSE16
-rwxr-xr-xsrc/3rdparty/libjpeg/import_from_libjpeg_tarball.sh8
-rw-r--r--src/3rdparty/libjpeg/jconfig.h23
-rw-r--r--src/3rdparty/libjpeg/jconfigint.h17
-rw-r--r--src/3rdparty/libjpeg/qt_attribution.json7
-rw-r--r--src/3rdparty/libjpeg/src/ChangeLog.md196
-rw-r--r--src/3rdparty/libjpeg/src/README.ijg64
-rw-r--r--[-rwxr-xr-x]src/3rdparty/libjpeg/src/README.md13
-rw-r--r--src/3rdparty/libjpeg/src/jaricom.c13
-rw-r--r--src/3rdparty/libjpeg/src/jcapimin.c44
-rw-r--r--src/3rdparty/libjpeg/src/jcapistd.c26
-rw-r--r--src/3rdparty/libjpeg/src/jcarith.c104
-rw-r--r--src/3rdparty/libjpeg/src/jccoefct.c102
-rw-r--r--src/3rdparty/libjpeg/src/jccolext.c46
-rw-r--r--src/3rdparty/libjpeg/src/jccolor.c377
-rw-r--r--src/3rdparty/libjpeg/src/jcdctmgr.c118
-rw-r--r--src/3rdparty/libjpeg/src/jchuff.c255
-rw-r--r--src/3rdparty/libjpeg/src/jchuff.h13
-rw-r--r--src/3rdparty/libjpeg/src/jcinit.c10
-rw-r--r--src/3rdparty/libjpeg/src/jcmainct.c40
-rw-r--r--src/3rdparty/libjpeg/src/jcmarker.c93
-rw-r--r--src/3rdparty/libjpeg/src/jcmaster.c135
-rw-r--r--src/3rdparty/libjpeg/src/jcomapi.c12
-rw-r--r--src/3rdparty/libjpeg/src/jconfig.h143
-rw-r--r--src/3rdparty/libjpeg/src/jconfig.h.in73
-rw-r--r--src/3rdparty/libjpeg/src/jconfigint.h13
-rw-r--r--src/3rdparty/libjpeg/src/jconfigint.h.in31
-rw-r--r--src/3rdparty/libjpeg/src/jcparam.c87
-rw-r--r--src/3rdparty/libjpeg/src/jcphuff.c675
-rw-r--r--src/3rdparty/libjpeg/src/jcprepct.c92
-rw-r--r--src/3rdparty/libjpeg/src/jcsample.c120
-rw-r--r--src/3rdparty/libjpeg/src/jctrans.c70
-rw-r--r--src/3rdparty/libjpeg/src/jdapimin.c42
-rw-r--r--src/3rdparty/libjpeg/src/jdapistd.c114
-rw-r--r--src/3rdparty/libjpeg/src/jdarith.c122
-rw-r--r--src/3rdparty/libjpeg/src/jdatadst.c50
-rw-r--r--src/3rdparty/libjpeg/src/jdatasrc.c52
-rw-r--r--src/3rdparty/libjpeg/src/jdcoefct.c247
-rw-r--r--src/3rdparty/libjpeg/src/jdcoefct.h6
-rw-r--r--src/3rdparty/libjpeg/src/jdcol565.c88
-rw-r--r--src/3rdparty/libjpeg/src/jdcolext.c34
-rw-r--r--src/3rdparty/libjpeg/src/jdcolor.c476
-rw-r--r--src/3rdparty/libjpeg/src/jdct.h148
-rw-r--r--src/3rdparty/libjpeg/src/jddctmgr.c32
-rw-r--r--src/3rdparty/libjpeg/src/jdhuff.c167
-rw-r--r--src/3rdparty/libjpeg/src/jdhuff.h98
-rw-r--r--src/3rdparty/libjpeg/src/jdinput.c99
-rw-r--r--src/3rdparty/libjpeg/src/jdmainct.c118
-rw-r--r--src/3rdparty/libjpeg/src/jdmainct.h12
-rw-r--r--src/3rdparty/libjpeg/src/jdmarker.c302
-rw-r--r--src/3rdparty/libjpeg/src/jdmaster.c173
-rw-r--r--src/3rdparty/libjpeg/src/jdmerge.c366
-rw-r--r--src/3rdparty/libjpeg/src/jdmrg565.c134
-rw-r--r--src/3rdparty/libjpeg/src/jdmrgext.c50
-rw-r--r--src/3rdparty/libjpeg/src/jdphuff.c141
-rw-r--r--src/3rdparty/libjpeg/src/jdpostct.c122
-rw-r--r--src/3rdparty/libjpeg/src/jdsample.c129
-rw-r--r--src/3rdparty/libjpeg/src/jdtrans.c14
-rw-r--r--src/3rdparty/libjpeg/src/jerror.c16
-rw-r--r--src/3rdparty/libjpeg/src/jerror.h99
-rw-r--r--src/3rdparty/libjpeg/src/jfdctflt.c58
-rw-r--r--src/3rdparty/libjpeg/src/jfdctfst.c50
-rw-r--r--src/3rdparty/libjpeg/src/jfdctint.c116
-rw-r--r--src/3rdparty/libjpeg/src/jidctflt.c112
-rw-r--r--src/3rdparty/libjpeg/src/jidctfst.c156
-rw-r--r--src/3rdparty/libjpeg/src/jidctint.c1722
-rw-r--r--src/3rdparty/libjpeg/src/jidctred.c254
-rw-r--r--src/3rdparty/libjpeg/src/jinclude.h20
-rw-r--r--src/3rdparty/libjpeg/src/jmemmgr.c304
-rw-r--r--src/3rdparty/libjpeg/src/jmemnobs.c32
-rw-r--r--src/3rdparty/libjpeg/src/jmemsys.h28
-rw-r--r--src/3rdparty/libjpeg/src/jmorecfg.h84
-rw-r--r--src/3rdparty/libjpeg/src/jpegcomp.h32
-rw-r--r--src/3rdparty/libjpeg/src/jpegint.h132
-rw-r--r--src/3rdparty/libjpeg/src/jpeglib.h210
-rw-r--r--src/3rdparty/libjpeg/src/jquant1.c190
-rw-r--r--src/3rdparty/libjpeg/src/jquant2.c357
-rw-r--r--src/3rdparty/libjpeg/src/jsimd.h182
-rw-r--r--src/3rdparty/libjpeg/src/jsimd_none.c244
-rw-r--r--src/3rdparty/libjpeg/src/jsimddct.h104
-rw-r--r--src/3rdparty/libjpeg/src/jstdhuff.c126
-rw-r--r--src/3rdparty/libjpeg/src/jutils.c20
-rw-r--r--src/3rdparty/libjpeg/src/jversion.h29
-rw-r--r--src/3rdparty/sqlite.pri5
-rw-r--r--src/3rdparty/sqlite/sqlite3.c21341
-rw-r--r--src/3rdparty/sqlite/sqlite3.h295
-rw-r--r--src/3rdparty/tinycbor/.gitignore81
-rw-r--r--src/3rdparty/tinycbor/LICENSE21
-rw-r--r--src/3rdparty/tinycbor/README13
-rw-r--r--src/3rdparty/tinycbor/VERSION1
-rw-r--r--src/3rdparty/tinycbor/qt_attribution.json14
-rw-r--r--src/3rdparty/tinycbor/src/cbor.h722
-rw-r--r--src/3rdparty/tinycbor/src/cborencoder.c677
-rw-r--r--src/3rdparty/tinycbor/src/cborerrorstrings.c188
-rw-r--r--src/3rdparty/tinycbor/src/cborinternal_p.h314
-rw-r--r--src/3rdparty/tinycbor/src/cborjson.h62
-rw-r--r--src/3rdparty/tinycbor/src/cborparser.c1526
-rw-r--r--src/3rdparty/tinycbor/src/compilersupport_p.h205
-rw-r--r--src/3rdparty/tinycbor/src/tinycbor-version.h3
-rw-r--r--src/3rdparty/tinycbor/tests/.gitignore15
-rw-r--r--src/3rdparty/tinycbor/tests/encoder/data.cpp310
-rw-r--r--src/3rdparty/tinycbor/tests/encoder/encoder.pro9
-rw-r--r--src/3rdparty/tinycbor/tests/encoder/tst_encoder.cpp496
-rw-r--r--src/3rdparty/tinycbor/tests/parser/data.cpp573
-rw-r--r--src/3rdparty/tinycbor/tests/parser/parser.pro10
-rw-r--r--src/3rdparty/tinycbor/tests/parser/tst_parser.cpp1667
-rw-r--r--src/3rdparty/wasm/DEJAVU-LICENSE187
-rw-r--r--src/3rdparty/wasm/DejaVuSans.ttfbin0 -> 493564 bytes
-rw-r--r--src/3rdparty/wasm/VERA-LICENSE15
-rw-r--r--src/3rdparty/wasm/Vera.ttfbin0 -> 65932 bytes
-rw-r--r--src/3rdparty/wasm/qt_attribution.json33
-rw-r--r--src/3rdparty/xcb/README8
-rw-r--r--src/3rdparty/xcb/include/xcb/randr.h175
-rw-r--r--src/3rdparty/xcb/include/xcb/render.h229
-rw-r--r--src/3rdparty/xcb/include/xcb/shape.h43
-rw-r--r--src/3rdparty/xcb/include/xcb/shm.h24
-rw-r--r--src/3rdparty/xcb/include/xcb/sync.h567
-rw-r--r--src/3rdparty/xcb/include/xcb/xfixes.h150
-rw-r--r--src/3rdparty/xcb/include/xcb/xinerama.h157
-rw-r--r--src/3rdparty/xcb/include/xcb/xinput.h9306
-rw-r--r--src/3rdparty/xcb/libxcb/randr.c817
-rw-r--r--src/3rdparty/xcb/libxcb/render.c950
-rw-r--r--src/3rdparty/xcb/libxcb/shape.c85
-rw-r--r--src/3rdparty/xcb/libxcb/shm.c19
-rw-r--r--src/3rdparty/xcb/libxcb/support_libxcb_versions_where_xcb_sumof_not_available.patch273
-rw-r--r--src/3rdparty/xcb/libxcb/sync.c751
-rw-r--r--src/3rdparty/xcb/libxcb/xfixes.c321
-rw-r--r--src/3rdparty/xcb/libxcb/xinerama.c212
-rw-r--r--src/3rdparty/xcb/libxcb/xinput.c14156
-rw-r--r--src/3rdparty/xcb/libxcb/xkb.c39
-rw-r--r--src/3rdparty/xkbcommon-x11.pri4
-rw-r--r--src/3rdparty/xkbcommon.pri62
-rw-r--r--src/3rdparty/xkbcommon/COPYING188
-rw-r--r--src/3rdparty/xkbcommon/Fix-compilation-on-libxcb-1.5.patch19
-rw-r--r--src/3rdparty/xkbcommon/LICENSE215
-rw-r--r--src/3rdparty/xkbcommon/NEWS289
-rw-r--r--src/3rdparty/xkbcommon/README.md112
-rw-r--r--src/3rdparty/xkbcommon/qt_attribution.json22
-rw-r--r--src/3rdparty/xkbcommon/src/compose/compose-state.c196
-rw-r--r--src/3rdparty/xkbcommon/src/compose/parser.c737
-rw-r--r--src/3rdparty/xkbcommon/src/compose/parser.h36
-rw-r--r--src/3rdparty/xkbcommon/src/compose/paths.c203
-rw-r--r--src/3rdparty/xkbcommon/src/compose/paths.h42
-rw-r--r--src/3rdparty/xkbcommon/src/compose/table.c219
-rw-r--r--src/3rdparty/xkbcommon/src/compose/table.h100
-rw-r--r--src/3rdparty/xkbcommon/src/context.c8
-rw-r--r--src/3rdparty/xkbcommon/src/darray.h25
-rw-r--r--src/3rdparty/xkbcommon/src/keymap-priv.c63
-rw-r--r--src/3rdparty/xkbcommon/src/keymap.c519
-rw-r--r--src/3rdparty/xkbcommon/src/keymap.h58
-rw-r--r--src/3rdparty/xkbcommon/src/keysym-utf.c19
-rw-r--r--src/3rdparty/xkbcommon/src/keysym.c26
-rw-r--r--src/3rdparty/xkbcommon/src/keysym.h7
-rw-r--r--src/3rdparty/xkbcommon/src/ks_tables.h798
-rw-r--r--src/3rdparty/xkbcommon/src/scanner-utils.h44
-rw-r--r--src/3rdparty/xkbcommon/src/state.c382
-rw-r--r--src/3rdparty/xkbcommon/src/text.c33
-rw-r--r--src/3rdparty/xkbcommon/src/text.h10
-rw-r--r--src/3rdparty/xkbcommon/src/utf8.c12
-rw-r--r--src/3rdparty/xkbcommon/src/utils.c70
-rw-r--r--src/3rdparty/xkbcommon/src/utils.h41
-rw-r--r--src/3rdparty/xkbcommon/src/x11/util.c14
-rw-r--r--src/3rdparty/xkbcommon/src/x11/x11-keymap.c48
-rw-r--r--src/3rdparty/xkbcommon/src/xkb-compat.c189
-rw-r--r--src/3rdparty/xkbcommon/src/xkb-keymap.c493
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/action.c238
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/action.h11
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/ast-build.c44
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/ast-build.h3
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/ast.h8
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/compat.c210
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/expr.c51
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/expr.h10
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/keycodes.c152
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/keymap-dump.c67
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/keymap.c309
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/parser-priv.h2
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/parser.c3610
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/parser.h245
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/rules.c128
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/scanner.c9
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/symbols.c300
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/types.c192
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/vmod.c37
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/vmod.h4
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/xkbcomp-keymap.c298
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/xkbcomp-parser.c3392
-rw-r--r--src/3rdparty/xkbcommon/xkbcommon/xkbcommon-compose.h493
-rw-r--r--src/3rdparty/xkbcommon/xkbcommon/xkbcommon-keysyms.h40
-rw-r--r--src/3rdparty/xkbcommon/xkbcommon/xkbcommon-x11.h78
-rw-r--r--src/3rdparty/xkbcommon/xkbcommon/xkbcommon.h386
-rw-r--r--src/android/jar/jar.pro2
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/CursorHandle.java9
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/EditContextView.java120
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/EditMenu.java142
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/EditPopupMenu.java85
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java361
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtNative.java56
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java20
-rw-r--r--src/android/templates/AndroidManifest.xml7
-rw-r--r--src/android/templates/build.gradle10
-rw-r--r--src/angle/patches/0001-ANGLE-Improve-Windows-Phone-Support.patch464
-rw-r--r--src/angle/patches/0001-ANGLE-Use-pixel-sizes-in-the-XAML-swap-chain.patch135
-rw-r--r--src/angle/patches/0001-Fix-build-for-MinGW.patch26
-rw-r--r--src/angle/patches/0002-ANGLE-Add-support-for-querying-platform-device.patch83
-rw-r--r--src/angle/patches/0002-ANGLE-Dynamically-load-D3D-compiler-from-a-list.patch62
-rw-r--r--src/angle/patches/0002-ANGLE-Fix-build-for-ARM.patch43
-rw-r--r--src/angle/patches/0002-ANGLE-Fix-compilation-with-MinGW.patch892
-rw-r--r--src/angle/patches/0003-ANGLE-Add-support-for-querying-platform-device.patch81
-rw-r--r--src/angle/patches/0003-ANGLE-Fix-Windows-Store-D3D-Trim-and-Level-9-require.patch58
-rw-r--r--src/angle/patches/0004-ANGLE-Allow-Windows-Phone-to-communicate-swap-region.patch146
-rw-r--r--src/angle/patches/0004-ANGLE-fix-usage-of-shared-handles-for-WinRT-applicat.patch37
-rw-r--r--src/angle/patches/0005-ANGLE-Fix-compilation-without-d3d11.patch59
-rw-r--r--src/angle/patches/0005-ANGLE-Fix-initialization-of-zero-sized-window.patch32
-rw-r--r--src/angle/patches/0006-ANGLE-Fix-Windows-Store-D3D-Trim-and-Level-9-requirements.patch57
-rw-r--r--src/angle/patches/0006-ANGLE-Fix-flickering-on-resize-when-D3D9-is-used.patch165
-rw-r--r--src/angle/patches/0007-ANGLE-D3D11-Suppress-keyboard-handling-of-DXGI.patch45
-rw-r--r--src/angle/patches/0007-ANGLE-Fix-resizing-of-windows.patch48
-rw-r--r--src/angle/patches/0008-ANGLE-Use-pixel-sizes-in-the-XAML-swap-chain.patch401
-rw-r--r--src/angle/patches/0008-ANGLE-winrt-Do-full-screen-update-if-the-the-window-.patch40
-rw-r--r--src/angle/patches/0009-ANGLE-glGetUniform-v-functions-to-work-properly.patch31
-rw-r--r--src/angle/patches/0009-Revert-Fix-scanForWantedComponents-not-ignoring-attr.patch67
-rw-r--r--src/angle/patches/0010-ANGLE-Disable-multisampling-to-avoid-crash-in-Qt-app.patch41
-rw-r--r--src/angle/patches/0010-ANGLE-fixed-usage-of-shared-handles-for-WinRT-WinPho.patch57
-rw-r--r--src/angle/patches/0011-ANGLE-Disable-support-for-shared-handles-in-warp-mod.patch44
-rw-r--r--src/angle/patches/0012-ANGLE-Fix-initialization-of-zero-sized-window.patch32
-rw-r--r--src/angle/patches/0013-ANGLE-Fix-crash-with-ltcg-on-Visual-Studio-2015-Upda.patch110
-rw-r--r--src/angle/patches/0014-ANGLE-Fix-flickering-on-resize-when-D3D9-is-used.patch157
-rw-r--r--src/angle/patches/0015-ANGLE-Use-ANGLE_D3D11_QDTD_AVAILABLE-to-check-struct-.patch32
-rw-r--r--src/angle/patches/0016-ANGLE-Fix-resizing-of-windows.patch57
-rw-r--r--src/angle/patches/0017-Remove-usage-of-auto_ptr-in-MacroExpander.patch31
-rw-r--r--src/angle/src/common/common.pri8
-rw-r--r--src/angle/src/common/gles_common.pri315
-rw-r--r--src/angle/src/compiler/preprocessor/preprocessor.pro7
-rw-r--r--src/angle/src/compiler/translator.pro87
-rw-r--r--src/angle/src/config.pri2
-rw-r--r--src/angle/src/libEGL/libEGL.pro1
-rw-r--r--src/corelib/Qt5CoreMacros.cmake45
-rw-r--r--src/corelib/animation/qabstractanimation.cpp12
-rw-r--r--src/corelib/animation/qparallelanimationgroup.cpp8
-rw-r--r--src/corelib/animation/qpropertyanimation.cpp9
-rw-r--r--src/corelib/animation/qsequentialanimationgroup.cpp9
-rw-r--r--src/corelib/animation/qvariantanimation.cpp14
-rw-r--r--src/corelib/codecs/qeucjpcodec_p.h10
-rw-r--r--src/corelib/codecs/qeuckrcodec_p.h20
-rw-r--r--src/corelib/codecs/qgb18030codec_p.h28
-rw-r--r--src/corelib/codecs/qiconvcodec_p.h8
-rw-r--r--src/corelib/codecs/qjiscodec_p.h10
-rw-r--r--src/corelib/codecs/qjpunicode.cpp54
-rw-r--r--src/corelib/codecs/qsjiscodec_p.h10
-rw-r--r--src/corelib/codecs/qtextcodec.cpp34
-rw-r--r--src/corelib/codecs/qtextcodec.h3
-rw-r--r--src/corelib/codecs/qtextcodec_p.h2
-rw-r--r--src/corelib/codecs/qutfcodec.cpp101
-rw-r--r--src/corelib/codecs/qutfcodec_p.h4
-rw-r--r--src/corelib/codecs/qwindowscodec_p.h8
-rw-r--r--src/corelib/configure.json11
-rw-r--r--src/corelib/corelib.pro1
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_animation_qparallelanimationgroup.cpp46
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_animation_qpropertyanimation.cpp48
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_animation_qsequentialanimationgroup.cpp47
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_animation_qvariantanimation.cpp52
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp109
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_global_qlogging.cpp42
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_global_qnumeric.cpp45
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_global_qoperatingsystemversion.cpp50
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_global_qrandom.cpp120
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qdebug.cpp84
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qfileselector.cpp82
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qloggingcategory.cpp57
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qtemporaryfile.cpp8
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qurl.cpp86
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_io_qurlquery.cpp43
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qdeadlinetimer.cpp123
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qmetaobject.cpp19
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp13
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_kernel_qtestsupport_core.cpp52
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_mimetype_qmimedatabase.cpp15
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_serialization_qcborstream.cpp347
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_serialization_qcborvalue.cpp69
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_serialization_qdatastream.cpp48
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_serialization_qjsondocument.cpp54
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_thread_qsemaphore.cpp29
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp41
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qbytearraymatcher.cpp46
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qcontiguouscache.cpp59
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qeasingcurve.cpp8
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp20
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qrect.cpp10
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qregularexpression.cpp18
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qscopeguard.cpp67
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qshareddata.cpp55
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qsharedpointer.cpp146
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qstring.cpp18
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qstringview.cpp51
-rw-r--r--src/corelib/doc/snippets/qstring/main.cpp5
-rw-r--r--src/corelib/doc/src/objectmodel/signalsandslots.qdoc4
-rw-r--r--src/corelib/doc/src/resource-system.qdoc1
-rw-r--r--src/corelib/global/archdetect.cpp2
-rw-r--r--src/corelib/global/global.pri1
-rw-r--r--src/corelib/global/qcompilerdetection.h24
-rw-r--r--src/corelib/global/qconfig-bootstrapped.h3
-rw-r--r--src/corelib/global/qendian.cpp919
-rw-r--r--src/corelib/global/qendian.h91
-rw-r--r--src/corelib/global/qendian.qdoc554
-rw-r--r--src/corelib/global/qglobal.cpp155
-rw-r--r--src/corelib/global/qglobal.h8
-rw-r--r--src/corelib/global/qglobalstatic.h2
-rw-r--r--src/corelib/global/qglobalstatic.qdoc2
-rw-r--r--src/corelib/global/qlogging.cpp82
-rw-r--r--src/corelib/global/qnamespace.h58
-rw-r--r--src/corelib/global/qnamespace.qdoc54
-rw-r--r--src/corelib/global/qnumeric.cpp7
-rw-r--r--src/corelib/global/qnumeric_p.h52
-rw-r--r--src/corelib/global/qoperatingsystemversion.cpp12
-rw-r--r--src/corelib/global/qoperatingsystemversion_win.cpp2
-rw-r--r--src/corelib/global/qprocessordetection.h8
-rw-r--r--src/corelib/global/qrandom.cpp83
-rw-r--r--src/corelib/global/qsystemdetection.h2
-rw-r--r--src/corelib/global/qtrace_p.h2
-rw-r--r--src/corelib/global/qversiontagging.cpp11
-rw-r--r--src/corelib/io/qdebug.cpp62
-rw-r--r--src/corelib/io/qdebug.h13
-rw-r--r--src/corelib/io/qdebug_p.h2
-rw-r--r--src/corelib/io/qdir.cpp30
-rw-r--r--src/corelib/io/qdir.h2
-rw-r--r--src/corelib/io/qfileselector.cpp44
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp48
-rw-r--r--src/corelib/io/qfilesystemengine_win.cpp19
-rw-r--r--src/corelib/io/qfilesystemiterator_win.cpp3
-rw-r--r--src/corelib/io/qfilesystemwatcher_fsevents.mm2
-rw-r--r--src/corelib/io/qfilesystemwatcher_win.cpp7
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp38
-rw-r--r--src/corelib/io/qfsfileengine_win.cpp51
-rw-r--r--src/corelib/io/qiodevice.cpp9
-rw-r--r--src/corelib/io/qloggingcategory.cpp19
-rw-r--r--src/corelib/io/qloggingregistry.cpp14
-rw-r--r--src/corelib/io/qprocess_unix.cpp1
-rw-r--r--src/corelib/io/qprocess_win.cpp123
-rw-r--r--src/corelib/io/qresource.cpp10
-rw-r--r--src/corelib/io/qsettings.cpp17
-rw-r--r--src/corelib/io/qsettings_mac.cpp18
-rw-r--r--src/corelib/io/qsettings_win.cpp91
-rw-r--r--src/corelib/io/qsettings_winrt.cpp18
-rw-r--r--src/corelib/io/qstandardpaths.cpp3
-rw-r--r--src/corelib/io/qtemporaryfile.cpp8
-rw-r--r--src/corelib/io/qurl.cpp152
-rw-r--r--src/corelib/io/qurlquery.cpp10
-rw-r--r--src/corelib/io/qurlrecode.cpp142
-rw-r--r--src/corelib/io/qwindowspipereader.cpp10
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.cpp17
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.h3
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.cpp247
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.h17
-rw-r--r--src/corelib/kernel/kernel.pri4
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.cpp18
-rw-r--r--src/corelib/kernel/qcfsocketnotifier.cpp6
-rw-r--r--src/corelib/kernel/qcore_mac.cpp2
-rw-r--r--src/corelib/kernel/qcore_mac_objc.mm57
-rw-r--r--src/corelib/kernel/qcore_mac_p.h154
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp112
-rw-r--r--src/corelib/kernel/qcoreapplication.h8
-rw-r--r--src/corelib/kernel/qcoreapplication_win.cpp642
-rw-r--r--src/corelib/kernel/qcoreevent.cpp8
-rw-r--r--src/corelib/kernel/qcoreglobaldata.cpp5
-rw-r--r--src/corelib/kernel/qdeadlinetimer.cpp86
-rw-r--r--src/corelib/kernel/qdeadlinetimer.h5
-rw-r--r--src/corelib/kernel/qelapsedtimer_win.cpp15
-rw-r--r--src/corelib/kernel/qeventdispatcher_cf.mm70
-rw-r--r--src/corelib/kernel/qeventdispatcher_cf_p.h36
-rw-r--r--src/corelib/kernel/qeventdispatcher_glib.cpp4
-rw-r--r--src/corelib/kernel/qeventdispatcher_glib_p.h1
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix.cpp2
-rw-r--r--src/corelib/kernel/qeventdispatcher_win.cpp112
-rw-r--r--src/corelib/kernel/qeventdispatcher_winrt.cpp22
-rw-r--r--src/corelib/kernel/qeventdispatcher_winrt_p.h1
-rw-r--r--src/corelib/kernel/qeventloop.cpp30
-rw-r--r--src/corelib/kernel/qmetaobject.cpp132
-rw-r--r--src/corelib/kernel/qmetaobject.h1
-rw-r--r--src/corelib/kernel/qmetaobject_p.h7
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder.cpp49
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder_p.h10
-rw-r--r--src/corelib/kernel/qmetatype.cpp234
-rw-r--r--src/corelib/kernel/qmetatype.h50
-rw-r--r--src/corelib/kernel/qmetatype_p.h16
-rw-r--r--src/corelib/kernel/qobject.cpp56
-rw-r--r--src/corelib/kernel/qobjectdefs_impl.h32
-rw-r--r--src/corelib/kernel/qsharedmemory_win.cpp14
-rw-r--r--src/corelib/kernel/qsystemerror.cpp4
-rw-r--r--src/corelib/kernel/qsystemsemaphore_win.cpp7
-rw-r--r--src/corelib/kernel/qtcore_eval.cpp2
-rw-r--r--src/corelib/kernel/qtestsupport_core.cpp116
-rw-r--r--src/corelib/kernel/qtestsupport_core.h92
-rw-r--r--src/corelib/kernel/qtimer.cpp42
-rw-r--r--src/corelib/kernel/qtimer.h17
-rw-r--r--src/corelib/kernel/qtranslator.cpp15
-rw-r--r--src/corelib/kernel/qvariant.cpp364
-rw-r--r--src/corelib/kernel/qvariant.h2
-rw-r--r--src/corelib/kernel/qwineventnotifier.cpp7
-rw-r--r--src/corelib/kernel/qwineventnotifier.h2
-rw-r--r--src/corelib/mimetypes/qmimedatabase.cpp24
-rw-r--r--src/corelib/plugin/plugin.pri1
-rw-r--r--src/corelib/plugin/qfactoryloader.cpp127
-rw-r--r--src/corelib/plugin/qfactoryloader_p.h3
-rw-r--r--src/corelib/plugin/qlibrary.cpp48
-rw-r--r--src/corelib/plugin/qlibrary_unix.cpp27
-rw-r--r--src/corelib/plugin/qlibrary_win.cpp4
-rw-r--r--src/corelib/plugin/qplugin.h28
-rw-r--r--src/corelib/plugin/qplugin_p.h75
-rw-r--r--src/corelib/plugin/qpluginloader.cpp11
-rw-r--r--src/corelib/plugin/qsystemlibrary.cpp2
-rw-r--r--src/corelib/qtcore.tracepoints39
-rw-r--r--src/corelib/serialization/qcborarray.cpp1221
-rw-r--r--src/corelib/serialization/qcborarray.h303
-rw-r--r--src/corelib/serialization/qcborcommon.h147
-rw-r--r--src/corelib/serialization/qcbordiagnostic.cpp347
-rw-r--r--src/corelib/serialization/qcbormap.cpp1766
-rw-r--r--src/corelib/serialization/qcbormap.h357
-rw-r--r--src/corelib/serialization/qcborstream.cpp2705
-rw-r--r--src/corelib/serialization/qcborstream.h267
-rw-r--r--src/corelib/serialization/qcborvalue.cpp2477
-rw-r--r--src/corelib/serialization/qcborvalue.h467
-rw-r--r--src/corelib/serialization/qcborvalue_p.h399
-rw-r--r--src/corelib/serialization/qdatastream.cpp11
-rw-r--r--src/corelib/serialization/qdatastream.h5
-rw-r--r--src/corelib/serialization/qjson.cpp1
-rw-r--r--src/corelib/serialization/qjson_p.h32
-rw-r--r--src/corelib/serialization/qjsonarray.cpp4
-rw-r--r--src/corelib/serialization/qjsonarray.h2
-rw-r--r--src/corelib/serialization/qjsoncbor.cpp954
-rw-r--r--src/corelib/serialization/qjsondocument.cpp16
-rw-r--r--src/corelib/serialization/qjsonobject.cpp11
-rw-r--r--src/corelib/serialization/qjsonobject.h2
-rw-r--r--src/corelib/serialization/qjsonparser.cpp1
-rw-r--r--src/corelib/serialization/qjsonvalue.cpp52
-rw-r--r--src/corelib/serialization/qjsonvalue.h3
-rw-r--r--src/corelib/serialization/qtextstream.cpp15
-rw-r--r--src/corelib/serialization/qtextstream.h1
-rw-r--r--src/corelib/serialization/qxmlstream.cpp2
-rw-r--r--src/corelib/serialization/serialization.pri16
-rw-r--r--src/corelib/statemachine/qhistorystate.cpp21
-rw-r--r--src/corelib/statemachine/qhistorystate_p.h17
-rw-r--r--src/corelib/thread/qfuture.h1
-rw-r--r--src/corelib/thread/qfutureinterface.h2
-rw-r--r--src/corelib/thread/qmutex.cpp4
-rw-r--r--src/corelib/thread/qmutex.h6
-rw-r--r--src/corelib/thread/qmutex_linux.cpp5
-rw-r--r--src/corelib/thread/qmutex_mac.cpp5
-rw-r--r--src/corelib/thread/qmutex_p.h3
-rw-r--r--src/corelib/thread/qmutex_unix.cpp6
-rw-r--r--src/corelib/thread/qmutexpool.cpp4
-rw-r--r--src/corelib/thread/qmutexpool_p.h4
-rw-r--r--src/corelib/thread/qreadwritelock.cpp7
-rw-r--r--src/corelib/thread/qreadwritelock.h6
-rw-r--r--src/corelib/thread/qreadwritelock_p.h6
-rw-r--r--src/corelib/thread/qsemaphore.cpp39
-rw-r--r--src/corelib/thread/qsemaphore.h7
-rw-r--r--src/corelib/thread/qthread.cpp130
-rw-r--r--src/corelib/thread/qthread.h24
-rw-r--r--src/corelib/thread/qthread_p.h29
-rw-r--r--src/corelib/thread/qthread_unix.cpp20
-rw-r--r--src/corelib/thread/qthread_win.cpp109
-rw-r--r--src/corelib/thread/qthreadpool.cpp4
-rw-r--r--src/corelib/thread/qthreadpool.h4
-rw-r--r--src/corelib/thread/qthreadpool_p.h3
-rw-r--r--src/corelib/thread/qthreadstorage.cpp3
-rw-r--r--src/corelib/thread/qthreadstorage.h79
-rw-r--r--src/corelib/thread/qwaitcondition.h9
-rw-r--r--src/corelib/thread/qwaitcondition_unix.cpp57
-rw-r--r--src/corelib/thread/qwaitcondition_win.cpp20
-rw-r--r--src/corelib/thread/thread.pri110
-rw-r--r--src/corelib/tools/qalgorithms.qdoc1
-rw-r--r--src/corelib/tools/qarraydata.h2
-rw-r--r--src/corelib/tools/qbytearray.cpp322
-rw-r--r--src/corelib/tools/qbytearray.h17
-rw-r--r--src/corelib/tools/qbytearraymatcher.cpp8
-rw-r--r--src/corelib/tools/qcollator.cpp15
-rw-r--r--src/corelib/tools/qcollator_icu.cpp4
-rw-r--r--src/corelib/tools/qcollator_p.h37
-rw-r--r--src/corelib/tools/qcontiguouscache.cpp21
-rw-r--r--src/corelib/tools/qcontiguouscache.h2
-rw-r--r--src/corelib/tools/qcryptographichash.cpp40
-rw-r--r--src/corelib/tools/qcryptographichash.h1
-rw-r--r--src/corelib/tools/qdatetime.cpp72
-rw-r--r--src/corelib/tools/qeasingcurve.cpp2
-rw-r--r--src/corelib/tools/qhash.cpp33
-rw-r--r--src/corelib/tools/qhash.h2
-rw-r--r--src/corelib/tools/qhashfunctions.h5
-rw-r--r--src/corelib/tools/qlinkedlist.h2
-rw-r--r--src/corelib/tools/qlist.h5
-rw-r--r--src/corelib/tools/qlocale.cpp121
-rw-r--r--src/corelib/tools/qlocale.h29
-rw-r--r--src/corelib/tools/qlocale.qdoc7
-rw-r--r--src/corelib/tools/qlocale_data_p.h11345
-rw-r--r--src/corelib/tools/qlocale_p.h8
-rw-r--r--src/corelib/tools/qlocale_tools.cpp28
-rw-r--r--src/corelib/tools/qlocale_tools_p.h13
-rw-r--r--src/corelib/tools/qlocale_win.cpp17
-rw-r--r--src/corelib/tools/qmakearray_p.h179
-rw-r--r--src/corelib/tools/qmap.h2
-rw-r--r--src/corelib/tools/qrect.cpp10
-rw-r--r--src/corelib/tools/qregexp.cpp56
-rw-r--r--src/corelib/tools/qregularexpression.cpp264
-rw-r--r--src/corelib/tools/qregularexpression.h11
-rw-r--r--src/corelib/tools/qringbuffer.cpp8
-rw-r--r--src/corelib/tools/qscopeguard.h96
-rw-r--r--src/corelib/tools/qscopeguard.qdoc55
-rw-r--r--src/corelib/tools/qset.h2
-rw-r--r--src/corelib/tools/qshareddata.cpp17
-rw-r--r--src/corelib/tools/qshareddata.h25
-rw-r--r--src/corelib/tools/qsharedpointer.cpp108
-rw-r--r--src/corelib/tools/qsimd.cpp271
-rw-r--r--src/corelib/tools/qsimd_p.h208
-rw-r--r--src/corelib/tools/qsimd_x86.cpp116
-rw-r--r--src/corelib/tools/qsimd_x86_p.h222
-rw-r--r--src/corelib/tools/qstring.cpp627
-rw-r--r--src/corelib/tools/qstring.h13
-rw-r--r--src/corelib/tools/qstringalgorithms.h1
-rw-r--r--src/corelib/tools/qstringlist.cpp25
-rw-r--r--src/corelib/tools/qstringlist.h13
-rw-r--r--src/corelib/tools/qstringliteral.h18
-rw-r--r--src/corelib/tools/qstringview.cpp27
-rw-r--r--src/corelib/tools/qstringview.h3
-rw-r--r--src/corelib/tools/qt_attribution.json6
-rw-r--r--src/corelib/tools/qtimezone.cpp14
-rw-r--r--src/corelib/tools/qtimezoneprivate.cpp45
-rw-r--r--src/corelib/tools/qtimezoneprivate_p.h3
-rw-r--r--src/corelib/tools/qtimezoneprivate_tz.cpp118
-rw-r--r--src/corelib/tools/qtimezoneprivate_win.cpp25
-rw-r--r--src/corelib/tools/qunicodetables_p.h6
-rw-r--r--src/corelib/tools/qvarlengtharray.h3
-rw-r--r--src/corelib/tools/qvector.h3
-rw-r--r--src/corelib/tools/tools.pri22
-rw-r--r--src/dbus/dbus_minimal_p.h7
-rw-r--r--src/dbus/qdbus_symbols.cpp8
-rw-r--r--src/dbus/qdbus_symbols_p.h57
-rw-r--r--src/dbus/qdbusmessage.cpp44
-rw-r--r--src/dbus/qdbusmessage.h3
-rw-r--r--src/dbus/qdbusmessage_p.h1
-rw-r--r--src/dbus/qdbusmetaobject.cpp2
-rw-r--r--src/dbus/qt_attribution.json3
-rw-r--r--src/gui/accessible/qaccessible.cpp44
-rw-r--r--src/gui/accessible/qaccessiblecache.cpp14
-rw-r--r--src/gui/accessible/qaccessiblecache_p.h1
-rw-r--r--src/gui/configure.json155
-rw-r--r--src/gui/configure.pri3
-rw-r--r--src/gui/doc/qtgui.qdocconf3
-rw-r--r--src/gui/doc/snippets/code/src_gui_accessible_qaccessible.cpp18
-rw-r--r--src/gui/doc/snippets/code/src_gui_math3d_qquaternion.cpp46
-rw-r--r--src/gui/doc/snippets/code/src_gui_opengl_qopenglbuffer.cpp49
-rw-r--r--src/gui/doc/snippets/code/src_gui_opengl_qopengldebug.cpp89
-rw-r--r--src/gui/doc/snippets/code/src_gui_opengl_qopenglfunctions.cpp101
-rw-r--r--src/gui/doc/snippets/code/src_gui_util_qdesktopservices.cpp28
-rw-r--r--src/gui/doc/snippets/code/src_gui_vulkan_qvulkanfunctions.cpp59
-rw-r--r--src/gui/doc/snippets/code/src_gui_vulkan_qvulkaninstance.cpp135
-rw-r--r--src/gui/doc/snippets/code/src_gui_vulkan_qvulkanwindow.cpp121
-rw-r--r--src/gui/image/image.pri5
-rw-r--r--src/gui/image/qbitmap.cpp52
-rw-r--r--src/gui/image/qbitmap.h1
-rw-r--r--src/gui/image/qicon.cpp33
-rw-r--r--src/gui/image/qicon.h3
-rw-r--r--src/gui/image/qiconloader.cpp20
-rw-r--r--src/gui/image/qiconloader_p.h3
-rw-r--r--src/gui/image/qimage.cpp312
-rw-r--r--src/gui/image/qimage.h7
-rw-r--r--src/gui/image/qimage_avx2.cpp67
-rw-r--r--src/gui/image/qimage_conversions.cpp826
-rw-r--r--src/gui/image/qimage_p.h11
-rw-r--r--src/gui/image/qimage_sse2.cpp125
-rw-r--r--src/gui/image/qimage_sse4.cpp76
-rw-r--r--src/gui/image/qimagereader.cpp131
-rw-r--r--src/gui/image/qimagereader.h1
-rw-r--r--src/gui/image/qimagereaderwriterhelpers.cpp180
-rw-r--r--src/gui/image/qimagereaderwriterhelpers_p.h139
-rw-r--r--src/gui/image/qimagewriter.cpp123
-rw-r--r--src/gui/image/qimagewriter.h1
-rw-r--r--src/gui/image/qmovie.cpp4
-rw-r--r--src/gui/image/qpixmap.cpp10
-rw-r--r--src/gui/image/qpixmap_blitter.cpp8
-rw-r--r--src/gui/image/qpixmap_raster.cpp11
-rw-r--r--src/gui/image/qpixmap_win.cpp423
-rw-r--r--src/gui/image/qpixmapcache.cpp25
-rw-r--r--src/gui/image/qpnghandler.cpp204
-rw-r--r--src/gui/image/qxbmhandler.cpp2
-rw-r--r--src/gui/image/qxpmhandler.cpp4
-rw-r--r--src/gui/itemmodels/qstandarditemmodel.cpp45
-rw-r--r--src/gui/itemmodels/qstandarditemmodel.h3
-rw-r--r--src/gui/kernel/kernel.pri7
-rw-r--r--src/gui/kernel/qdnd_p.h4
-rw-r--r--src/gui/kernel/qevent.cpp58
-rw-r--r--src/gui/kernel/qevent.h13
-rw-r--r--src/gui/kernel/qguiapplication.cpp146
-rw-r--r--src/gui/kernel/qguiapplication_p.h11
-rw-r--r--src/gui/kernel/qhighdpiscaling.cpp3
-rw-r--r--src/gui/kernel/qinputmethod.cpp18
-rw-r--r--src/gui/kernel/qinputmethod_p.h2
-rw-r--r--src/gui/kernel/qkeysequence.cpp5
-rw-r--r--src/gui/kernel/qopenglcontext.cpp100
-rw-r--r--src/gui/kernel/qopenglwindow.cpp6
-rw-r--r--src/gui/kernel/qpalette.cpp43
-rw-r--r--src/gui/kernel/qpalette.h4
-rw-r--r--src/gui/kernel/qplatformdialoghelper.cpp37
-rw-r--r--src/gui/kernel/qplatformdialoghelper.h23
-rw-r--r--src/gui/kernel/qplatformgraphicsbufferhelper.cpp41
-rw-r--r--src/gui/kernel/qplatformintegration.cpp4
-rw-r--r--src/gui/kernel/qplatformmenu.h1
-rw-r--r--src/gui/kernel/qplatformscreen.cpp2
-rw-r--r--src/gui/kernel/qplatformsurface.cpp25
-rw-r--r--src/gui/kernel/qplatformsurface.h9
-rw-r--r--src/gui/kernel/qplatformwindow.cpp84
-rw-r--r--src/gui/kernel/qplatformwindow.h5
-rw-r--r--src/gui/kernel/qplatformwindow_p.h2
-rw-r--r--src/gui/kernel/qshortcutmap.cpp13
-rw-r--r--src/gui/kernel/qsimpledrag.cpp132
-rw-r--r--src/gui/kernel/qsimpledrag_p.h32
-rw-r--r--src/gui/kernel/qsurface.cpp4
-rw-r--r--src/gui/kernel/qsurface.h6
-rw-r--r--src/gui/kernel/qtestsupport_gui.cpp83
-rw-r--r--src/gui/kernel/qtestsupport_gui.h56
-rw-r--r--src/gui/kernel/qwindow.cpp44
-rw-r--r--src/gui/kernel/qwindow_p.h6
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp71
-rw-r--r--src/gui/kernel/qwindowsysteminterface.h19
-rw-r--r--src/gui/kernel/qwindowsysteminterface_p.h3
-rw-r--r--src/gui/math3d/qquaternion.cpp8
-rw-r--r--src/gui/math3d/qvector2d.cpp67
-rw-r--r--src/gui/math3d/qvector2d.h74
-rw-r--r--src/gui/math3d/qvector3d.cpp97
-rw-r--r--src/gui/math3d/qvector3d.h94
-rw-r--r--src/gui/math3d/qvector4d.cpp124
-rw-r--r--src/gui/math3d/qvector4d.h112
-rw-r--r--src/gui/opengl/opengl.pri2
-rw-r--r--src/gui/opengl/qopengl.h2
-rw-r--r--src/gui/opengl/qopenglbuffer.cpp24
-rw-r--r--src/gui/opengl/qopengldebug.cpp67
-rw-r--r--src/gui/opengl/qopenglengineshadermanager.cpp75
-rw-r--r--src/gui/opengl/qopenglengineshadermanager_p.h4
-rw-r--r--src/gui/opengl/qopenglengineshadersource_p.h173
-rw-r--r--src/gui/opengl/qopenglextensions_p.h3
-rw-r--r--src/gui/opengl/qopenglframebufferobject.cpp86
-rw-r--r--src/gui/opengl/qopenglfunctions.cpp106
-rw-r--r--src/gui/opengl/qopenglfunctions.h3
-rw-r--r--src/gui/opengl/qopenglpaintengine.cpp102
-rw-r--r--src/gui/opengl/qopenglprogrambinarycache.cpp27
-rw-r--r--src/gui/opengl/qopenglshaderprogram.cpp88
-rw-r--r--src/gui/opengl/qopengltexturecache.cpp199
-rw-r--r--src/gui/opengl/qopengltexturecache_p.h24
-rw-r--r--src/gui/opengl/qopengltextureglyphcache.cpp10
-rw-r--r--src/gui/opengl/qopengltextureuploader.cpp328
-rw-r--r--src/gui/opengl/qopengltextureuploader_p.h84
-rw-r--r--src/gui/painting/WEBGRADIENTS_LICENSE.txt21
-rw-r--r--src/gui/painting/painting.pri9
-rw-r--r--src/gui/painting/qblendfunctions.cpp16
-rw-r--r--src/gui/painting/qbrush.cpp88
-rw-r--r--src/gui/painting/qbrush.h176
-rw-r--r--src/gui/painting/qcolor.cpp5
-rw-r--r--src/gui/painting/qcolorprofile_p.h156
-rw-r--r--src/gui/painting/qcompositionfunctions.cpp1094
-rw-r--r--src/gui/painting/qcosmeticstroker_p.h3
-rw-r--r--src/gui/painting/qdrawhelper.cpp3519
-rw-r--r--src/gui/painting/qdrawhelper_avx2.cpp69
-rw-r--r--src/gui/painting/qdrawhelper_neon.cpp181
-rw-r--r--src/gui/painting/qdrawhelper_p.h136
-rw-r--r--src/gui/painting/qdrawhelper_sse4.cpp266
-rw-r--r--src/gui/painting/qdrawhelper_ssse3.cpp59
-rw-r--r--src/gui/painting/qdrawingprimitive_sse2_p.h69
-rw-r--r--src/gui/painting/qemulationpaintengine.cpp27
-rw-r--r--src/gui/painting/qimagescale.cpp239
-rw-r--r--src/gui/painting/qimagescale_p.h9
-rw-r--r--src/gui/painting/qmemrotate.cpp33
-rw-r--r--src/gui/painting/qmemrotate_p.h1
-rw-r--r--src/gui/painting/qpagedpaintdevice.cpp68
-rw-r--r--src/gui/painting/qpagedpaintdevice.h8
-rw-r--r--src/gui/painting/qpagedpaintdevice_p.h40
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp5
-rw-r--r--src/gui/painting/qpaintengineex.cpp2
-rw-r--r--src/gui/painting/qpainter.cpp71
-rw-r--r--src/gui/painting/qpainter.h18
-rw-r--r--src/gui/painting/qpainterpath.cpp2
-rw-r--r--src/gui/painting/qpdf.cpp44
-rw-r--r--src/gui/painting/qpdf_p.h4
-rw-r--r--src/gui/painting/qpdfwriter.cpp35
-rw-r--r--src/gui/painting/qplatformbackingstore.cpp9
-rw-r--r--src/gui/painting/qplatformbackingstore.h2
-rw-r--r--src/gui/painting/qrgba64.h4
-rw-r--r--src/gui/painting/qrgba64_p.h39
-rw-r--r--src/gui/painting/qt_attribution.json14
-rw-r--r--src/gui/painting/qtriangulator.cpp30
-rw-r--r--src/gui/painting/webgradients.binaryjsonbin0 -> 50792 bytes
-rw-r--r--src/gui/painting/webgradients.css909
-rw-r--r--src/gui/qtgui.tracepoints21
-rw-r--r--src/gui/text/qcssparser.cpp11
-rw-r--r--src/gui/text/qfont.cpp13
-rw-r--r--src/gui/text/qfontdatabase.cpp9
-rw-r--r--src/gui/text/qfontengine.cpp2
-rw-r--r--src/gui/text/qstatictext.cpp9
-rw-r--r--src/gui/text/qtextcursor.cpp3
-rw-r--r--src/gui/text/qtextdocument.cpp52
-rw-r--r--src/gui/text/qtextdocument.h4
-rw-r--r--src/gui/text/qtextdocumentfragment.cpp40
-rw-r--r--src/gui/text/qtextdocumentfragment_p.h1
-rw-r--r--src/gui/text/qtextdocumentlayout.cpp42
-rw-r--r--src/gui/text/qtextengine.cpp93
-rw-r--r--src/gui/text/qtextengine_p.h8
-rw-r--r--src/gui/text/qtextformat.cpp57
-rw-r--r--src/gui/text/qtextformat.h14
-rw-r--r--src/gui/text/qtexthtmlparser.cpp7
-rw-r--r--src/gui/text/qtextlayout.cpp28
-rw-r--r--src/gui/text/qtextodfwriter.cpp261
-rw-r--r--src/gui/text/qtextodfwriter_p.h18
-rw-r--r--src/gui/text/qtextoption.cpp3
-rw-r--r--src/gui/text/qzip.cpp23
-rw-r--r--src/gui/util/qdesktopservices.cpp28
-rw-r--r--src/gui/util/qktxhandler.cpp199
-rw-r--r--src/gui/util/qktxhandler_p.h78
-rw-r--r--src/gui/util/qpkmhandler.cpp126
-rw-r--r--src/gui/util/qpkmhandler_p.h70
-rw-r--r--src/gui/util/qshadergraphloader.cpp15
-rw-r--r--src/gui/util/qshadernodesloader.cpp8
-rw-r--r--src/gui/util/qshadernodesloader_p.h1
-rw-r--r--src/gui/util/qtexturefiledata.cpp280
-rw-r--r--src/gui/util/qtexturefiledata_p.h115
-rw-r--r--src/gui/util/qtexturefilehandler_p.h79
-rw-r--r--src/gui/util/qtexturefilereader.cpp102
-rw-r--r--src/gui/util/qtexturefilereader_p.h88
-rw-r--r--src/gui/util/qvalidator.cpp38
-rw-r--r--src/gui/util/util.pri13
-rw-r--r--src/gui/vulkan/qvulkanfunctions.cpp21
-rw-r--r--src/gui/vulkan/qvulkaninstance.cpp97
-rw-r--r--src/gui/vulkan/qvulkanwindow.cpp94
-rw-r--r--src/network/access/access.pri7
-rw-r--r--src/network/access/http2/http2protocol.cpp3
-rw-r--r--src/network/access/qhsts.cpp5
-rw-r--r--src/network/access/qhttp2protocolhandler.cpp15
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp2
-rw-r--r--src/network/access/qhttpnetworkheader.cpp6
-rw-r--r--src/network/access/qhttpnetworkreply.cpp5
-rw-r--r--src/network/access/qnetworkaccessdebugpipebackend.cpp4
-rw-r--r--src/network/access/qnetworkaccessdebugpipebackend_p.h1
-rw-r--r--src/network/access/qnetworkaccessfilebackend.cpp6
-rw-r--r--src/network/access/qnetworkaccessfilebackend_p.h2
-rw-r--r--src/network/access/qnetworkaccessftpbackend.cpp61
-rw-r--r--src/network/access/qnetworkaccessftpbackend_p.h5
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp23
-rw-r--r--src/network/access/qnetworkaccessmanager.h3
-rw-r--r--src/network/access/qnetworkdiskcache.cpp6
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp4
-rw-r--r--src/network/access/qnetworkreplywasmimpl.cpp618
-rw-r--r--src/network/access/qnetworkreplywasmimpl_p.h143
-rw-r--r--src/network/access/qnetworkrequest.cpp134
-rw-r--r--src/network/access/qnetworkrequest.h6
-rw-r--r--src/network/bearer/qnetworksession.cpp21
-rw-r--r--src/network/configure.json28
-rw-r--r--src/network/configure.pri2
-rw-r--r--src/network/doc/snippets/code/src_network_access_qnetworkaccessmanager.cpp14
-rw-r--r--src/network/doc/snippets/code/src_network_bearer_qnetworksession.cpp60
-rw-r--r--src/network/doc/snippets/code/src_network_kernel_qnetworkdatagram.cpp64
-rw-r--r--src/network/doc/snippets/code/src_network_kernel_qnetworkinterface.cpp46
-rw-r--r--src/network/doc/snippets/code/src_network_ssl_qdtls.cpp138
-rw-r--r--src/network/doc/snippets/code/src_network_ssl_qdtlscookie.cpp125
-rw-r--r--src/network/doc/snippets/code/src_network_ssl_qsslpresharedkeyauthenticator.cpp53
-rw-r--r--src/network/doc/src/ssl.qdoc9
-rw-r--r--src/network/kernel/qauthenticator.cpp8
-rw-r--r--src/network/kernel/qdnslookup.cpp7
-rw-r--r--src/network/kernel/qdnslookup_p.h4
-rw-r--r--src/network/kernel/qhostinfo.cpp19
-rw-r--r--src/network/kernel/qhostinfo_p.h9
-rw-r--r--src/network/kernel/qhostinfo_win.cpp8
-rw-r--r--src/network/kernel/qnetworkdatagram.cpp15
-rw-r--r--src/network/kernel/qnetworkinterface.cpp8
-rw-r--r--src/network/kernel/qnetworkinterface_win.cpp21
-rw-r--r--src/network/kernel/qnetworkproxy_win.cpp15
-rw-r--r--src/network/socket/qabstractsocket.cpp5
-rw-r--r--src/network/socket/qhttpsocketengine.cpp5
-rw-r--r--src/network/socket/qlocalserver_win.cpp10
-rw-r--r--src/network/socket/qlocalsocket.cpp2
-rw-r--r--src/network/socket/qlocalsocket_win.cpp6
-rw-r--r--src/network/socket/qnativesocketengine_win.cpp7
-rw-r--r--src/network/ssl/qasn1element_p.h54
-rw-r--r--src/network/ssl/qdtls.cpp1163
-rw-r--r--src/network/ssl/qdtls.h186
-rw-r--r--src/network/ssl/qdtls_openssl.cpp1462
-rw-r--r--src/network/ssl/qdtls_openssl_p.h213
-rw-r--r--src/network/ssl/qdtls_p.h155
-rw-r--r--src/network/ssl/qpassworddigestor.cpp187
-rw-r--r--src/network/ssl/qpassworddigestor.h60
-rw-r--r--src/network/ssl/qssl.cpp4
-rw-r--r--src/network/ssl/qssl.h7
-rw-r--r--src/network/ssl/qsslcertificate.cpp70
-rw-r--r--src/network/ssl/qsslcertificate.h11
-rw-r--r--src/network/ssl/qsslcertificate_openssl.cpp34
-rw-r--r--src/network/ssl/qsslcertificate_p.h4
-rw-r--r--src/network/ssl/qsslcertificate_qt.cpp6
-rw-r--r--src/network/ssl/qsslcertificate_winrt.cpp5
-rw-r--r--src/network/ssl/qsslcertificateextension.h5
-rw-r--r--src/network/ssl/qsslconfiguration.cpp62
-rw-r--r--src/network/ssl/qsslconfiguration.h15
-rw-r--r--src/network/ssl/qsslconfiguration_p.h9
-rw-r--r--src/network/ssl/qsslcontext_openssl.cpp15
-rw-r--r--src/network/ssl/qsslcontext_openssl11.cpp86
-rw-r--r--src/network/ssl/qsslcontext_opensslpre11.cpp56
-rw-r--r--src/network/ssl/qssldiffiehellmanparameters_openssl.cpp4
-rw-r--r--src/network/ssl/qsslkey_openssl.cpp46
-rw-r--r--src/network/ssl/qsslkey_p.cpp97
-rw-r--r--src/network/ssl/qsslkey_p.h11
-rw-r--r--src/network/ssl/qsslkey_qt.cpp410
-rw-r--r--src/network/ssl/qsslpresharedkeyauthenticator.cpp19
-rw-r--r--src/network/ssl/qsslpresharedkeyauthenticator.h1
-rw-r--r--src/network/ssl/qsslsocket.cpp95
-rw-r--r--src/network/ssl/qsslsocket_mac.cpp193
-rw-r--r--src/network/ssl/qsslsocket_mac_p.h7
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp267
-rw-r--r--src/network/ssl/qsslsocket_openssl11.cpp2
-rw-r--r--src/network/ssl/qsslsocket_openssl11_symbols_p.h39
-rw-r--r--src/network/ssl/qsslsocket_openssl_p.h19
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols.cpp328
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols_p.h38
-rw-r--r--src/network/ssl/qsslsocket_opensslpre11_symbols_p.h15
-rw-r--r--src/network/ssl/qwindowscarootfetcher.cpp168
-rw-r--r--src/network/ssl/qwindowscarootfetcher_p.h79
-rw-r--r--src/network/ssl/ssl.pri66
-rw-r--r--src/opengl/doc/snippets/code/src_opengl_qglbuffer.cpp49
-rw-r--r--src/opengl/doc/snippets/code/src_opengl_qglfunctions.cpp75
-rw-r--r--src/opengl/doc/snippets/code/src_opengl_qgraphicsshadereffect.cpp84
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp3
-rw-r--r--src/opengl/qgl.cpp32
-rw-r--r--src/opengl/qgl_p.h2
-rw-r--r--src/opengl/qglbuffer.cpp11
-rw-r--r--src/opengl/qglframebufferobject.cpp22
-rw-r--r--src/opengl/qglfunctions.cpp37
-rw-r--r--src/opengl/qglpaintdevice.cpp1
-rw-r--r--src/opengl/qgraphicsshadereffect.cpp46
-rw-r--r--src/platformheaders/cocoafunctions/qcocoawindowfunctions.qdoc2
-rw-r--r--src/platformheaders/xcbfunctions/qxcbintegrationfunctions.h60
-rw-r--r--src/platformheaders/xcbfunctions/qxcbwindowfunctions.h21
-rw-r--r--src/platformheaders/xcbfunctions/qxcbwindowfunctions.qdoc75
-rw-r--r--src/platformheaders/xcbfunctions/xcbfunctions.pri1
-rw-r--r--src/platformsupport/clipboard/qmacmime.mm12
-rw-r--r--src/platformsupport/edid/qedidparser.cpp23
-rw-r--r--src/platformsupport/edid/qedidvendortable_p.h4296
-rw-r--r--src/platformsupport/eglconvenience/qxlibeglintegration.cpp14
-rw-r--r--src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp54
-rw-r--r--src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h3
-rw-r--r--src/platformsupport/eventdispatchers/qgenericunixeventdispatcher.cpp2
-rw-r--r--src/platformsupport/eventdispatchers/qgenericunixeventdispatcher_p.h3
-rw-r--r--src/platformsupport/eventdispatchers/qunixeventdispatcher.cpp5
-rw-r--r--src/platformsupport/eventdispatchers/qunixeventdispatcher_qpa_p.h3
-rw-r--r--src/platformsupport/eventdispatchers/qwindowsguieventdispatcher.cpp28
-rw-r--r--src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp9
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm52
-rw-r--r--src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm35
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp39
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp2
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h8
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp7
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h5
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp5
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite_p.h3
-rw-r--r--src/platformsupport/glxconvenience/qglxconvenience.cpp33
-rw-r--r--src/platformsupport/kmsconvenience/qkmsdevice.cpp159
-rw-r--r--src/platformsupport/kmsconvenience/qkmsdevice_p.h35
-rw-r--r--src/platformsupport/linuxaccessibility/constant_mappings.cpp2
-rw-r--r--src/platformsupport/services/genericunix/qgenericunixservices.cpp59
-rw-r--r--src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp26
-rw-r--r--src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h6
-rw-r--r--src/plugins/bearer/corewlan/qcorewlanengine.mm38
-rw-r--r--src/plugins/doc/snippets/code/src_plugins_platforms_qnx_qqnxwindow.cpp52
-rw-r--r--src/plugins/imageformats/jpeg/qjpeghandler.cpp6
-rw-r--r--src/plugins/platforms/android/androidjniinput.cpp30
-rw-r--r--src/plugins/platforms/android/androidjniinput.h4
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.cpp368
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.h41
-rw-r--r--src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp16
-rw-r--r--src/plugins/platforms/android/qandroidplatformmenubar.h2
-rw-r--r--src/plugins/platforms/cocoa/cocoa.pro16
-rw-r--r--src/plugins/platforms/cocoa/main.mm2
-rw-r--r--src/plugins/platforms/cocoa/messages.cpp18
-rw-r--r--src/plugins/platforms/cocoa/messages.h10
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.h5
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.mm8
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h9
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm86
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplication.h3
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplication.mm8
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h26
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm117
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm179
-rw-r--r--src/plugins/platforms/cocoa/qcocoaclipboard.mm6
-rw-r--r--src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm31
-rw-r--r--src/plugins/platforms/cocoa/qcocoacursor.mm20
-rw-r--r--src/plugins/platforms/cocoa/qcocoadrag.mm12
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.h5
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm132
-rw-r--r--src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm66
-rw-r--r--src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm70
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.h31
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.mm628
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.h88
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.mm204
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h11
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm87
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintrospection.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoakeymapper.h13
-rw-r--r--src/plugins/platforms/cocoa/qcocoakeymapper.mm29
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.mm80
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenubar.h7
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenubar.mm130
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuitem.h4
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuitem.mm212
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuloader.h36
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuloader.mm158
-rw-r--r--src/plugins/platforms/cocoa/qcocoanativeinterface.mm48
-rw-r--r--src/plugins/platforms/cocoa/qcocoansmenu.h22
-rw-r--r--src/plugins/platforms/cocoa/qcocoansmenu.mm151
-rw-r--r--src/plugins/platforms/cocoa/qcocoaprintdevice.mm22
-rw-r--r--src/plugins/platforms/cocoa/qcocoascreen.h14
-rw-r--r--src/plugins/platforms/cocoa/qcocoascreen.mm272
-rw-r--r--src/plugins/platforms/cocoa/qcocoasystemsettings.mm79
-rw-r--r--src/plugins/platforms/cocoa/qcocoasystemtrayicon.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm90
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.mm89
-rw-r--r--src/plugins/platforms/cocoa/qcocoavulkaninstance.h75
-rw-r--r--src/plugins/platforms/cocoa/qcocoavulkaninstance.mm95
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h26
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm838
-rw-r--r--src/plugins/platforms/cocoa/qmacclipboard.h4
-rw-r--r--src/plugins/platforms/cocoa/qmacclipboard.mm14
-rw-r--r--src/plugins/platforms/cocoa/qmultitouch_mac.mm2
-rw-r--r--src/plugins/platforms/cocoa/qnsview.h96
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm1939
-rw-r--r--src/plugins/platforms/cocoa/qnsview_accessibility.mm90
-rw-r--r--src/plugins/platforms/cocoa/qnsview_complextext.mm315
-rw-r--r--src/plugins/platforms/cocoa/qnsview_dragging.mm300
-rw-r--r--src/plugins/platforms/cocoa/qnsview_drawing.mm167
-rw-r--r--src/plugins/platforms/cocoa/qnsview_gestures.mm169
-rw-r--r--src/plugins/platforms/cocoa/qnsview_keys.mm262
-rw-r--r--src/plugins/platforms/cocoa/qnsview_menus.mm133
-rw-r--r--src/plugins/platforms/cocoa/qnsview_mouse.mm624
-rw-r--r--src/plugins/platforms/cocoa/qnsview_tablet.mm223
-rw-r--r--src/plugins/platforms/cocoa/qnsview_touch.mm100
-rw-r--r--src/plugins/platforms/cocoa/qnsviewaccessibility.mm93
-rw-r--r--src/plugins/platforms/cocoa/qnswindow.h1
-rw-r--r--src/plugins/platforms/cocoa/qnswindow.mm72
-rw-r--r--src/plugins/platforms/cocoa/qnswindowdelegate.h14
-rw-r--r--src/plugins/platforms/cocoa/qnswindowdelegate.mm41
-rw-r--r--src/plugins/platforms/cocoa/qpaintengine_mac.mm56
-rw-r--r--src/plugins/platforms/cocoa/qpaintengine_mac_p.h8
-rw-r--r--src/plugins/platforms/cocoa/qprintengine_mac.mm10
-rw-r--r--src/plugins/platforms/cocoa/qprintengine_mac_p.h2
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp6
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.cpp4
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.h4
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dcontext.h2
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.h2
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dhelpers.h10
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp4
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h2
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dnativeinterface.cpp2
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h4
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp6
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h2
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp8
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h2
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dplatformplugin.cpp2
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfshooks.cpp2
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsintegration.cpp3
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.pro1
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro1
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp115
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro1
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro1
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp6
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp5
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/eglfs_kms_vsp2.pro1
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/eglfs_mali.pro1
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/eglfs_rcar.pro1
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/eglfs_viv.pro1
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/eglfs_viv_wl.pro1
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/eglfs_x11.pro1
-rw-r--r--src/plugins/platforms/eglfs/eglfsdeviceintegration.pro2
-rw-r--r--src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosimagepickercontroller.h6
-rw-r--r--src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosimagepickercontroller.mm14
-rw-r--r--src/plugins/platforms/ios/qiosclipboard.mm24
-rw-r--r--src/plugins/platforms/ios/qioseventdispatcher.mm39
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.mm15
-rw-r--r--src/plugins/platforms/ios/qiosintegration.mm8
-rw-r--r--src/plugins/platforms/ios/qiosmenu.mm32
-rw-r--r--src/plugins/platforms/ios/qiosmessagedialog.h1
-rw-r--r--src/plugins/platforms/ios/qiosmessagedialog.mm20
-rw-r--r--src/plugins/platforms/ios/qiosoptionalplugininterface.h4
-rw-r--r--src/plugins/platforms/ios/qiosscreen.mm35
-rw-r--r--src/plugins/platforms/ios/qiostextinputoverlay.mm85
-rw-r--r--src/plugins/platforms/ios/qiostextresponder.h10
-rw-r--r--src/plugins/platforms/ios/qiostextresponder.mm56
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.h2
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.mm36
-rw-r--r--src/plugins/platforms/ios/qioswindow.mm6
-rw-r--r--src/plugins/platforms/ios/quiaccessibilityelement.h7
-rw-r--r--src/plugins/platforms/ios/quiaccessibilityelement.mm13
-rw-r--r--src/plugins/platforms/ios/quiview.h15
-rw-r--r--src/plugins/platforms/ios/quiview.mm117
-rw-r--r--src/plugins/platforms/ios/quiview_accessibility.mm7
-rw-r--r--src/plugins/platforms/platforms.pro2
-rw-r--r--src/plugins/platforms/qnx/qqnxglcontext.cpp2
-rw-r--r--src/plugins/platforms/qnx/qqnxglobal.cpp6
-rw-r--r--src/plugins/platforms/qnx/qqnxintegration.cpp70
-rw-r--r--src/plugins/platforms/qnx/qqnxintegration.h22
-rw-r--r--src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp45
-rw-r--r--src/plugins/platforms/qnx/qqnxscreeneventhandler.h2
-rw-r--r--src/plugins/platforms/qnx/qqnxscreeneventthread.cpp156
-rw-r--r--src/plugins/platforms/qnx/qqnxscreeneventthread.h26
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.cpp37
-rw-r--r--src/plugins/platforms/wasm/main.cpp54
-rw-r--r--src/plugins/platforms/wasm/qtloader.js516
-rw-r--r--src/plugins/platforms/wasm/qtlogo.svg67
-rw-r--r--src/plugins/platforms/wasm/qwasmbackingstore.cpp165
-rw-r--r--src/plugins/platforms/wasm/qwasmbackingstore.h70
-rw-r--r--src/plugins/platforms/wasm/qwasmcompositor.cpp721
-rw-r--r--src/plugins/platforms/wasm/qwasmcompositor.h169
-rw-r--r--src/plugins/platforms/wasm/qwasmcursor.cpp131
-rw-r--r--src/plugins/platforms/wasm/qwasmcursor.h43
-rw-r--r--src/plugins/platforms/wasm/qwasmeventdispatcher.cpp181
-rw-r--r--src/plugins/platforms/wasm/qwasmeventdispatcher.h64
-rw-r--r--src/plugins/platforms/wasm/qwasmeventtranslator.cpp558
-rw-r--r--src/plugins/platforms/wasm/qwasmeventtranslator.h210
-rw-r--r--src/plugins/platforms/wasm/qwasmfontdatabase.cpp86
-rw-r--r--src/plugins/platforms/wasm/qwasmfontdatabase.h49
-rw-r--r--src/plugins/platforms/wasm/qwasmintegration.cpp219
-rw-r--r--src/plugins/platforms/wasm/qwasmintegration.h92
-rw-r--r--src/plugins/platforms/wasm/qwasmopenglcontext.cpp147
-rw-r--r--src/plugins/platforms/wasm/qwasmopenglcontext.h63
-rw-r--r--src/plugins/platforms/wasm/qwasmscreen.cpp118
-rw-r--r--src/plugins/platforms/wasm/qwasmscreen.h82
-rw-r--r--src/plugins/platforms/wasm/qwasmstylepixmaps_p.h183
-rw-r--r--src/plugins/platforms/wasm/qwasmtheme.cpp50
-rw-r--r--src/plugins/platforms/wasm/qwasmtheme.h56
-rw-r--r--src/plugins/platforms/wasm/qwasmwindow.cpp401
-rw-r--r--src/plugins/platforms/wasm/qwasmwindow.h127
-rw-r--r--src/plugins/platforms/wasm/wasm.json3
-rw-r--r--src/plugins/platforms/wasm/wasm.pro65
-rw-r--r--src/plugins/platforms/wasm/wasm_shell.html61
-rw-r--r--src/plugins/platforms/windows/main.cpp2
-rw-r--r--src/plugins/platforms/windows/openglblacklists/default.json11
-rw-r--r--src/plugins/platforms/windows/qtwindowsglobal.h26
-rw-r--r--src/plugins/platforms/windows/qwin10helpers.cpp4
-rw-r--r--src/plugins/platforms/windows/qwin10helpers.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsclipboard.cpp31
-rw-r--r--src/plugins/platforms/windows/qwindowsclipboard.h3
-rw-r--r--src/plugins/platforms/windows/qwindowscombase.h4
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp251
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h56
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.cpp33
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.h14
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp59
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.h6
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.cpp77
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.h8
-rw-r--r--src/plugins/platforms/windows/qwindowsdropdataobject.cpp8
-rw-r--r--src/plugins/platforms/windows/qwindowsdropdataobject.h2
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.cpp16
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsgdiintegration.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsgdiintegration.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp18
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.h14
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.cpp19
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.h7
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp48
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.h11
-rw-r--r--src/plugins/platforms/windows/qwindowsinternalmimedata.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsinternalmimedata.h2
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp165
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.h10
-rw-r--r--src/plugins/platforms/windows/qwindowsmenu.h8
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.cpp90
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.h6
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.cpp175
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.cpp17
-rw-r--r--src/plugins/platforms/windows/qwindowsole.cpp21
-rw-r--r--src/plugins/platforms/windows/qwindowsole.h10
-rw-r--r--src/plugins/platforms/windows/qwindowsopenglcontext.h14
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.cpp112
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.h13
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.cpp799
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.h82
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp34
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.h8
-rw-r--r--src/plugins/platforms/windows/qwindowsservices.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsservices.h4
-rw-r--r--src/plugins/platforms/windows/qwindowssystemtrayicon.h2
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.cpp35
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.h35
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.cpp40
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.h7
-rw-r--r--src/plugins/platforms/windows/qwindowsthreadpoolrunner.h14
-rw-r--r--src/plugins/platforms/windows/qwindowsvulkaninstance.cpp33
-rw-r--r--src/plugins/platforms/windows/qwindowsvulkaninstance.h7
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp219
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h21
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp17
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.h8
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.cpp12
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h12
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.cpp15
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h16
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.cpp13
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h12
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.cpp13
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h8
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp17
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h42
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.cpp26
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.h15
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.cpp13
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h20
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp13
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h16
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp15
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h12
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp13
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h10
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.cpp13
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h12
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp13
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h24
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp31
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h43
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.cpp13
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h10
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp8
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiautils.h16
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.cpp13
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h12
-rw-r--r--src/plugins/platforms/windows/windows.pri6
-rw-r--r--src/plugins/platforms/winrt/main.cpp2
-rw-r--r--src/plugins/platforms/winrt/qwinrtbackingstore.cpp22
-rw-r--r--src/plugins/platforms/winrt/qwinrtbackingstore.h5
-rw-r--r--src/plugins/platforms/winrt/qwinrtcanvas.cpp142
-rw-r--r--src/plugins/platforms/winrt/qwinrtcanvas.h75
-rw-r--r--src/plugins/platforms/winrt/qwinrtclipboard.cpp5
-rw-r--r--src/plugins/platforms/winrt/qwinrtcursor.cpp65
-rw-r--r--src/plugins/platforms/winrt/qwinrtcursor.h3
-rw-r--r--src/plugins/platforms/winrt/qwinrtdrag.cpp27
-rw-r--r--src/plugins/platforms/winrt/qwinrtdrag.h4
-rw-r--r--src/plugins/platforms/winrt/qwinrteglcontext.h2
-rw-r--r--src/plugins/platforms/winrt/qwinrteventdispatcher.h2
-rw-r--r--src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp30
-rw-r--r--src/plugins/platforms/winrt/qwinrtfiledialoghelper.h2
-rw-r--r--src/plugins/platforms/winrt/qwinrtfileengine.cpp25
-rw-r--r--src/plugins/platforms/winrt/qwinrtfileengine.h4
-rw-r--r--src/plugins/platforms/winrt/qwinrtinputcontext.cpp6
-rw-r--r--src/plugins/platforms/winrt/qwinrtintegration.cpp17
-rw-r--r--src/plugins/platforms/winrt/qwinrtintegration.h5
-rw-r--r--src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp11
-rw-r--r--src/plugins/platforms/winrt/qwinrtmessagedialoghelper.h2
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.cpp136
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.h11
-rw-r--r--src/plugins/platforms/winrt/qwinrtservices.cpp10
-rw-r--r--src/plugins/platforms/winrt/qwinrtservices.h2
-rw-r--r--src/plugins/platforms/winrt/qwinrtwindow.cpp2
-rw-r--r--src/plugins/platforms/winrt/qwinrtwindow.h2
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiaaccessibility.cpp113
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiaaccessibility.h64
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiabaseprovider.cpp76
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiabaseprovider.h72
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiacontrolmetadata.cpp182
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiacontrolmetadata.h117
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiaemptypropertyvalue.h108
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiagriditemprovider.cpp160
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiagriditemprovider.h78
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiagridprovider.cpp135
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiagridprovider.h76
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiainvokeprovider.cpp88
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiainvokeprovider.h74
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiamainprovider.cpp789
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiamainprovider.h125
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiametadatacache.cpp112
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiametadatacache.h76
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiapeervector.cpp149
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiapeervector.h80
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiaprovidercache.cpp99
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiaprovidercache.h77
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiarangevalueprovider.cpp167
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiarangevalueprovider.h80
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionitemprovider.cpp214
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionitemprovider.h78
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionprovider.cpp158
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionprovider.h76
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiatableitemprovider.cpp141
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiatableitemprovider.h75
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiatableprovider.cpp167
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiatableprovider.h76
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiatextprovider.cpp232
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiatextprovider.h83
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiatextrangeprovider.cpp497
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiatextrangeprovider.h95
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiatoggleprovider.cpp104
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiatoggleprovider.h75
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.cpp182
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.h83
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiavalueprovider.cpp136
-rw-r--r--src/plugins/platforms/winrt/uiautomation/qwinrtuiavalueprovider.h77
-rw-r--r--src/plugins/platforms/winrt/uiautomation/uiautomation.pri45
-rw-r--r--src/plugins/platforms/winrt/winrt.pro4
-rw-r--r--src/plugins/platforms/xcb/README27
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp4
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp8
-rw-r--r--src/plugins/platforms/xcb/qxcbatom.cpp277
-rw-r--r--src/plugins/platforms/xcb/qxcbatom.h257
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.cpp225
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.h33
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.cpp124
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp1932
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h483
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_basic.cpp437
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_basic.h175
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_screens.cpp414
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp584
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.cpp6
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.cpp336
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.h15
-rw-r--r--src/plugins/platforms/xcb/qxcbeventdispatcher.cpp162
-rw-r--r--src/plugins/platforms/xcb/qxcbeventdispatcher.h117
-rw-r--r--src/plugins/platforms/xcb/qxcbeventqueue.cpp383
-rw-r--r--src/plugins/platforms/xcb/qxcbeventqueue.h162
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp58
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp908
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.h12
-rw-r--r--src/plugins/platforms/xcb/qxcbmain.cpp12
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.cpp72
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.h15
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp28
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h6
-rw-r--r--src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp41
-rw-r--r--src/plugins/platforms/xcb/qxcbsystemtraytracker.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbvulkaninstance.cpp29
-rw-r--r--src/plugins/platforms/xcb/qxcbvulkaninstance.h3
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp550
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h31
-rw-r--r--src/plugins/platforms/xcb/xcb-plugin.pro1
-rw-r--r--src/plugins/platforms/xcb/xcb-static/xcb-static.pro5
-rw-r--r--src/plugins/platforms/xcb/xcb_qpa_lib.pro25
-rw-r--r--src/plugins/platformthemes/flatpak/flatpak.json3
-rw-r--r--src/plugins/platformthemes/flatpak/flatpak.pro17
-rw-r--r--src/plugins/platformthemes/flatpak/main.cpp65
-rw-r--r--src/plugins/platformthemes/flatpak/qflatpakfiledialog.cpp355
-rw-r--r--src/plugins/platformthemes/flatpak/qflatpakfiledialog_p.h106
-rw-r--r--src/plugins/platformthemes/flatpak/qflatpaktheme.cpp196
-rw-r--r--src/plugins/platformthemes/flatpak/qflatpaktheme.h90
-rw-r--r--src/plugins/platformthemes/platformthemes.pro2
-rw-r--r--src/plugins/platformthemes/xdgdesktopportal/main.cpp67
-rw-r--r--src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp407
-rw-r--r--src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h106
-rw-r--r--src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp200
-rw-r--r--src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.h90
-rw-r--r--src/plugins/platformthemes/xdgdesktopportal/xdgdesktopportal.json3
-rw-r--r--src/plugins/platformthemes/xdgdesktopportal/xdgdesktopportal.pro17
-rw-r--r--src/plugins/printsupport/cups/qcupsprintengine.cpp13
-rw-r--r--src/plugins/printsupport/cups/qcupsprintengine_p.h1
-rw-r--r--src/plugins/printsupport/cups/qcupsprintersupport.cpp78
-rw-r--r--src/plugins/printsupport/cups/qppdprintdevice.cpp80
-rw-r--r--src/plugins/printsupport/cups/qppdprintdevice.h2
-rw-r--r--src/plugins/printsupport/windows/qwindowsprintdevice.cpp149
-rw-r--r--src/plugins/printsupport/windows/qwindowsprintdevice.h51
-rw-r--r--src/plugins/printsupport/windows/qwindowsprintersupport.h3
-rw-r--r--src/plugins/sqldrivers/configure.json2
-rw-r--r--src/plugins/sqldrivers/configure.pri14
-rw-r--r--src/plugins/sqldrivers/mysql/qsql_mysql.cpp12
-rw-r--r--src/plugins/sqldrivers/odbc/qsql_odbc.cpp11
-rw-r--r--src/plugins/sqldrivers/psql/qsql_psql.cpp7
-rw-r--r--src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp44
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac.mm209
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac_p_p.h1
-rw-r--r--src/plugins/styles/windowsvista/qwindowsvistastyle.cpp32
-rw-r--r--src/plugins/styles/windowsvista/qwindowsvistastyle_p.h43
-rw-r--r--src/plugins/styles/windowsvista/qwindowsxpstyle.cpp16
-rw-r--r--src/plugins/styles/windowsvista/qwindowsxpstyle_p.h42
-rw-r--r--src/printsupport/dialogs/qpagesetupdialog_mac.mm11
-rw-r--r--src/printsupport/dialogs/qpagesetupdialog_unix.cpp69
-rw-r--r--src/printsupport/dialogs/qpagesetupdialog_unix_p.h11
-rw-r--r--src/printsupport/dialogs/qpagesetupwidget.ui3
-rw-r--r--src/printsupport/dialogs/qprintdialog_mac.mm19
-rw-r--r--src/printsupport/dialogs/qprintdialog_unix.cpp909
-rw-r--r--src/printsupport/dialogs/qprintpreviewdialog.cpp5
-rw-r--r--src/printsupport/dialogs/qprintpropertieswidget.ui106
-rw-r--r--src/printsupport/kernel/qcups.cpp20
-rw-r--r--src/printsupport/kernel/qcups_p.h5
-rw-r--r--src/printsupport/kernel/qplatformprintdevice.cpp21
-rw-r--r--src/printsupport/kernel/qplatformprintdevice.h14
-rw-r--r--src/printsupport/kernel/qprintengine_pdf.cpp10
-rw-r--r--src/printsupport/kernel/qprintengine_pdf_p.h1
-rw-r--r--src/printsupport/kernel/qprintengine_win.cpp57
-rw-r--r--src/printsupport/kernel/qprinter.cpp50
-rw-r--r--src/printsupport/kernel/qprinter_p.h4
-rw-r--r--src/sql/configure.json22
-rw-r--r--src/sql/doc/snippets/code/doc_src_sql-driver.cpp2
-rw-r--r--src/sql/doc/snippets/code/src_sql_kernel_qsqldriver.cpp12
-rw-r--r--src/sql/doc/snippets/code/src_sql_kernel_qsqlresult.cpp12
-rw-r--r--src/sql/kernel/qsqlquery.cpp4
-rw-r--r--src/sql/kernel/qtsqlglobal.h1
-rw-r--r--src/sql/kernel/qtsqlglobal_p.h1
-rw-r--r--src/sql/models/qsqlquerymodel.h3
-rw-r--r--src/sql/models/qsqlquerymodel_p.h4
-rw-r--r--src/sql/models/qsqlrelationaldelegate.h25
-rw-r--r--src/sql/models/qsqlrelationaltablemodel.h2
-rw-r--r--src/sql/models/qsqltablemodel.cpp4
-rw-r--r--src/sql/models/qsqltablemodel.h2
-rw-r--r--src/sql/models/qsqltablemodel_p.h4
-rw-r--r--src/sql/sql.pro2
-rw-r--r--src/testlib/3rdparty/VALGRIND_LICENSE.txt4
-rw-r--r--src/testlib/3rdparty/callgrind_p.h60
-rw-r--r--src/testlib/3rdparty/qt_attribution.json6
-rw-r--r--src/testlib/3rdparty/valgrind_p.h5646
-rw-r--r--src/testlib/doc/snippets/code/doc_src_qtestlib.cpp30
-rw-r--r--src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp20
-rw-r--r--src/testlib/doc/src/qttest-index.qdoc5
-rw-r--r--src/testlib/doc/src/qttestlib-manual.qdoc12
-rw-r--r--src/testlib/qabstracttestlogger.cpp23
-rw-r--r--src/testlib/qabstracttestlogger_p.h8
-rw-r--r--src/testlib/qappletestlogger.cpp149
-rw-r--r--src/testlib/qappletestlogger_p.h95
-rw-r--r--src/testlib/qplaintestlogger.cpp18
-rw-r--r--src/testlib/qsignalspy.h8
-rw-r--r--src/testlib/qtaptestlogger.cpp254
-rw-r--r--src/testlib/qtaptestlogger_p.h85
-rw-r--r--src/testlib/qtest.h21
-rw-r--r--src/testlib/qtestcase.cpp73
-rw-r--r--src/testlib/qtestcase.h21
-rw-r--r--src/testlib/qtestcase.qdoc99
-rw-r--r--src/testlib/qtesteventloop.h5
-rw-r--r--src/testlib/qtestlog.cpp33
-rw-r--r--src/testlib/qtestlog_p.h6
-rw-r--r--src/testlib/qtestresult.cpp2
-rw-r--r--src/testlib/qtestsystem.h105
-rw-r--r--src/testlib/qxctestlogger.mm10
-rw-r--r--src/testlib/qxctestlogger_p.h2
-rw-r--r--src/testlib/testlib.pro9
-rw-r--r--src/tools/androiddeployqt/main.cpp66
-rw-r--r--src/tools/bootstrap/bootstrap.pro4
-rw-r--r--src/tools/moc/cbordevice.h96
-rw-r--r--src/tools/moc/generator.cpp183
-rw-r--r--src/tools/moc/generator.h6
-rw-r--r--src/tools/moc/moc.h7
-rw-r--r--src/tools/moc/moc.pri6
-rw-r--r--src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp2
-rw-r--r--src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp2
-rw-r--r--src/tools/rcc/main.cpp18
-rw-r--r--src/tools/rcc/rcc.cpp18
-rw-r--r--src/tools/rcc/rcc.h4
-rw-r--r--src/tools/tracegen/etw.cpp3
-rw-r--r--src/tools/tracegen/lttng.cpp4
-rw-r--r--src/tools/tracegen/provider.cpp39
-rw-r--r--src/tools/tracegen/provider.h2
-rw-r--r--src/tools/uic/cpp/cppwritedeclaration.cpp19
-rw-r--r--src/tools/uic/cpp/cppwriteinitialization.cpp256
-rw-r--r--src/tools/uic/cpp/cppwriteinitialization.h12
-rw-r--r--src/tools/uic/customwidgetsinfo.cpp4
-rw-r--r--src/tools/uic/driver.cpp4
-rw-r--r--src/tools/uic/driver.h1
-rw-r--r--src/tools/uic/main.cpp6
-rw-r--r--src/tools/uic/option.h2
-rw-r--r--src/tools/uic/treewalker.h2
-rw-r--r--src/tools/uic/ui4.cpp755
-rw-r--r--src/tools/uic/uic.cpp12
-rw-r--r--src/tools/uic/uic.h1
-rw-r--r--src/tools/uic/utils.h26
-rw-r--r--src/widgets/accessible/complexwidgets.cpp11
-rw-r--r--src/widgets/accessible/complexwidgets_p.h2
-rw-r--r--src/widgets/accessible/itemviews.cpp20
-rw-r--r--src/widgets/accessible/qaccessiblemenu.cpp7
-rw-r--r--src/widgets/accessible/qaccessiblewidgets.cpp4
-rw-r--r--src/widgets/dialogs/qcolordialog.cpp5
-rw-r--r--src/widgets/dialogs/qcolordialog.h5
-rw-r--r--src/widgets/dialogs/qdialog.cpp20
-rw-r--r--src/widgets/dialogs/qfiledialog.cpp39
-rw-r--r--src/widgets/dialogs/qfiledialog.h2
-rw-r--r--src/widgets/dialogs/qfiledialog_p.h14
-rw-r--r--src/widgets/dialogs/qfilesystemmodel.cpp35
-rw-r--r--src/widgets/dialogs/qfilesystemmodel_p.h6
-rw-r--r--src/widgets/dialogs/qfontdialog.cpp1
-rw-r--r--src/widgets/dialogs/qinputdialog.cpp7
-rw-r--r--src/widgets/dialogs/qmessagebox.cpp31
-rw-r--r--src/widgets/dialogs/qprogressdialog.cpp1
-rw-r--r--src/widgets/dialogs/qwizard_win.cpp6
-rw-r--r--src/widgets/dialogs/qwizard_win_p.h15
-rw-r--r--src/widgets/doc/images/qgridlayout.png (renamed from src/widgets/doc/images/gridlayout.png)bin1445 -> 1445 bytes
-rw-r--r--src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp4
-rw-r--r--src/widgets/doc/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp15
-rw-r--r--src/widgets/doc/snippets/code/src_gui_kernel_qformlayout.cpp48
-rw-r--r--src/widgets/doc/snippets/code/src_widgets_util_qscroller.cpp49
-rw-r--r--src/widgets/doc/snippets/code/src_widgets_widgets_qmainwindow.cpp58
-rw-r--r--src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc2
-rw-r--r--src/widgets/graphicsview/qgraphicsanchorlayout.h1
-rw-r--r--src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp6
-rw-r--r--src/widgets/graphicsview/qgraphicsanchorlayout_p.h7
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.cpp20
-rw-r--r--src/widgets/graphicsview/qgraphicsitem_p.h4
-rw-r--r--src/widgets/graphicsview/qgraphicsscene.cpp127
-rw-r--r--src/widgets/graphicsview/qgraphicsscene.h4
-rw-r--r--src/widgets/graphicsview/qgraphicsscene_p.h3
-rw-r--r--src/widgets/graphicsview/qgraphicssceneevent.cpp98
-rw-r--r--src/widgets/graphicsview/qgraphicssceneevent.h4
-rw-r--r--src/widgets/graphicsview/qgraphicsview.cpp16
-rw-r--r--src/widgets/itemviews/qabstractitemdelegate.cpp25
-rw-r--r--src/widgets/itemviews/qheaderview.cpp16
-rw-r--r--src/widgets/itemviews/qitemdelegate.cpp68
-rw-r--r--src/widgets/itemviews/qlistview.cpp66
-rw-r--r--src/widgets/itemviews/qlistview.h4
-rw-r--r--src/widgets/itemviews/qlistview_p.h2
-rw-r--r--src/widgets/itemviews/qlistwidget.cpp9
-rw-r--r--src/widgets/itemviews/qtableview.cpp55
-rw-r--r--src/widgets/itemviews/qtablewidget.cpp38
-rw-r--r--src/widgets/itemviews/qtablewidget.h1
-rw-r--r--src/widgets/itemviews/qtablewidget_p.h5
-rw-r--r--src/widgets/itemviews/qtreeview.cpp64
-rw-r--r--src/widgets/itemviews/qtreeview_p.h2
-rw-r--r--src/widgets/itemviews/qtreewidget.cpp56
-rw-r--r--src/widgets/itemviews/qtreewidget.h11
-rw-r--r--src/widgets/itemviews/qtreewidget_p.h7
-rw-r--r--src/widgets/kernel/kernel.pri6
-rw-r--r--src/widgets/kernel/qapplication.cpp90
-rw-r--r--src/widgets/kernel/qapplication_p.h2
-rw-r--r--src/widgets/kernel/qformlayout.cpp48
-rw-r--r--src/widgets/kernel/qgesture.cpp4
-rw-r--r--src/widgets/kernel/qgesturemanager.cpp2
-rw-r--r--src/widgets/kernel/qgesturemanager_p.h4
-rw-r--r--src/widgets/kernel/qgridlayout.cpp2
-rw-r--r--src/widgets/kernel/qlayout.cpp27
-rw-r--r--src/widgets/kernel/qlayout.h1
-rw-r--r--src/widgets/kernel/qmacgesturerecognizer_p.h18
-rw-r--r--src/widgets/kernel/qopenglwidget.cpp13
-rw-r--r--src/widgets/kernel/qshortcut.cpp12
-rw-r--r--src/widgets/kernel/qtestsupport_widgets.cpp113
-rw-r--r--src/widgets/kernel/qtestsupport_widgets.h61
-rw-r--r--src/widgets/kernel/qtooltip.cpp59
-rw-r--r--src/widgets/kernel/qwhatsthis.cpp10
-rw-r--r--src/widgets/kernel/qwhatsthis.h4
-rw-r--r--src/widgets/kernel/qwidget.cpp166
-rw-r--r--src/widgets/kernel/qwidget.h1
-rw-r--r--src/widgets/kernel/qwidget_p.h5
-rw-r--r--src/widgets/kernel/qwidgetbackingstore.cpp89
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp116
-rw-r--r--src/widgets/kernel/qwidgetwindow_p.h3
-rw-r--r--src/widgets/qtwidgets.tracepoints4
-rw-r--r--src/widgets/styles/images/titlebar-contexthelp-16.pngbin0 -> 396 bytes
-rw-r--r--src/widgets/styles/images/titlebar-contexthelp-32.pngbin0 -> 661 bytes
-rw-r--r--src/widgets/styles/images/titlebar-contexthelp-48.pngbin0 -> 891 bytes
-rw-r--r--src/widgets/styles/images/titlebar-max-16.pngbin0 -> 158 bytes
-rw-r--r--src/widgets/styles/images/titlebar-max-32.pngbin0 -> 163 bytes
-rw-r--r--src/widgets/styles/images/titlebar-max-48.pngbin0 -> 167 bytes
-rw-r--r--src/widgets/styles/images/titlebar-min-16.pngbin0 -> 166 bytes
-rw-r--r--src/widgets/styles/images/titlebar-min-32.pngbin0 -> 171 bytes
-rw-r--r--src/widgets/styles/images/titlebar-min-48.pngbin0 -> 175 bytes
-rw-r--r--src/widgets/styles/images/titlebar-shade-16.pngbin0 -> 253 bytes
-rw-r--r--src/widgets/styles/images/titlebar-shade-32.pngbin0 -> 282 bytes
-rw-r--r--src/widgets/styles/images/titlebar-shade-48.pngbin0 -> 339 bytes
-rw-r--r--src/widgets/styles/images/titlebar-unshade-16.pngbin0 -> 244 bytes
-rw-r--r--src/widgets/styles/images/titlebar-unshade-32.pngbin0 -> 294 bytes
-rw-r--r--src/widgets/styles/images/titlebar-unshade-48.pngbin0 -> 336 bytes
-rw-r--r--src/widgets/styles/images/toolbar-ext-h-16.pngbin0 -> 349 bytes
-rw-r--r--src/widgets/styles/images/toolbar-ext-h-32.pngbin0 -> 568 bytes
-rw-r--r--src/widgets/styles/images/toolbar-ext-h-8.pngbin0 -> 220 bytes
-rw-r--r--src/widgets/styles/images/toolbar-ext-h-rtl-16.pngbin0 -> 128 bytes
-rw-r--r--src/widgets/styles/images/toolbar-ext-h-rtl-32.pngbin0 -> 148 bytes
-rw-r--r--src/widgets/styles/images/toolbar-ext-h-rtl-8.pngbin0 -> 114 bytes
-rw-r--r--src/widgets/styles/images/toolbar-ext-macstyle.png (renamed from src/widgets/styles/images/toolbar-ext.png)bin516 -> 516 bytes
-rw-r--r--src/widgets/styles/images/toolbar-ext-macstyle@2x.png (renamed from src/widgets/styles/images/toolbar-ext@2x.png)bin505 -> 505 bytes
-rw-r--r--src/widgets/styles/images/toolbar-ext-v-10.pngbin0 -> 387 bytes
-rw-r--r--src/widgets/styles/images/toolbar-ext-v-20.pngbin0 -> 625 bytes
-rw-r--r--src/widgets/styles/images/toolbar-ext-v-5.pngbin0 -> 223 bytes
-rw-r--r--src/widgets/styles/qcommonstyle.cpp140
-rw-r--r--src/widgets/styles/qstyle.cpp7
-rw-r--r--src/widgets/styles/qstyle.h1
-rw-r--r--src/widgets/styles/qstyle.qrc28
-rw-r--r--src/widgets/styles/qstylehelper.cpp8
-rw-r--r--src/widgets/styles/qstylehelper_p.h1
-rw-r--r--src/widgets/styles/qstyleoption.cpp8
-rw-r--r--src/widgets/styles/qstyleoption.h2
-rw-r--r--src/widgets/styles/qstylesheetstyle.cpp141
-rw-r--r--src/widgets/styles/qstylesheetstyle_p.h8
-rw-r--r--src/widgets/styles/qwindowsstyle.cpp19
-rw-r--r--src/widgets/util/qcompleter.cpp46
-rw-r--r--src/widgets/util/qcompleter.h4
-rw-r--r--src/widgets/util/qscroller.cpp15
-rw-r--r--src/widgets/util/qsystemtrayicon.cpp2
-rw-r--r--src/widgets/util/qsystemtrayicon_x11.cpp70
-rw-r--r--src/widgets/util/qundostack.cpp55
-rw-r--r--src/widgets/util/qundostack.h5
-rw-r--r--src/widgets/widgets.pro3
-rw-r--r--src/widgets/widgets/qabstractspinbox.cpp72
-rw-r--r--src/widgets/widgets/qabstractspinbox.h7
-rw-r--r--src/widgets/widgets/qabstractspinbox_p.h4
-rw-r--r--src/widgets/widgets/qcombobox.cpp5
-rw-r--r--src/widgets/widgets/qdockarealayout.cpp14
-rw-r--r--src/widgets/widgets/qdockwidget.cpp13
-rw-r--r--src/widgets/widgets/qlabel.cpp30
-rw-r--r--src/widgets/widgets/qlineedit.cpp27
-rw-r--r--src/widgets/widgets/qlineedit.h1
-rw-r--r--src/widgets/widgets/qlineedit_p.cpp13
-rw-r--r--src/widgets/widgets/qmainwindow.cpp25
-rw-r--r--src/widgets/widgets/qmainwindowlayout.cpp56
-rw-r--r--src/widgets/widgets/qmainwindowlayout_p.h12
-rw-r--r--src/widgets/widgets/qmdiarea.cpp6
-rw-r--r--src/widgets/widgets/qmenu.cpp4
-rw-r--r--src/widgets/widgets/qmenu.h8
-rw-r--r--src/widgets/widgets/qmenu_mac.mm3
-rw-r--r--src/widgets/widgets/qmenubar.cpp2
-rw-r--r--src/widgets/widgets/qmenubar.h6
-rw-r--r--src/widgets/widgets/qplaintextedit.cpp23
-rw-r--r--src/widgets/widgets/qspinbox.cpp128
-rw-r--r--src/widgets/widgets/qspinbox.h8
-rw-r--r--src/widgets/widgets/qsplashscreen.cpp6
-rw-r--r--src/widgets/widgets/qsplitter.cpp17
-rw-r--r--src/widgets/widgets/qtabbar.cpp22
-rw-r--r--src/widgets/widgets/qtabbar_p.h17
-rw-r--r--src/widgets/widgets/qtabwidget.cpp2
-rw-r--r--src/widgets/widgets/qtextbrowser.cpp7
-rw-r--r--src/widgets/widgets/qtextedit.cpp9
-rw-r--r--src/widgets/widgets/qtoolbar.cpp2
-rw-r--r--src/widgets/widgets/qtoolbarlayout_p.h2
-rw-r--r--src/widgets/widgets/qwidgetlinecontrol.cpp10
-rw-r--r--src/widgets/widgets/qwidgetlinecontrol_p.h1
-rw-r--r--src/widgets/widgets/qwidgetresizehandler.cpp1
-rw-r--r--src/winmain/qtmain_winrt.cpp73
-rw-r--r--src/xml/doc/src/xml-processing.qdoc4
-rw-r--r--sync.profile2
-rw-r--r--tests/auto/auto.pro4
-rw-r--r--tests/auto/cmake/CMakeLists.txt1
-rw-r--r--tests/auto/cmake/test_add_big_resource/CMakeLists.txt13
-rw-r--r--tests/auto/cmake/test_add_big_resource/myobject.cpp44
-rw-r--r--tests/auto/cmake/test_add_big_resource/myobject.h44
-rw-r--r--tests/auto/cmake/test_add_big_resource/resource_file.txt1
-rw-r--r--tests/auto/cmake/test_add_big_resource/resource_file2.txt1
-rw-r--r--tests/auto/cmake/test_add_big_resource/test_add_big_resource.qrc6
-rw-r--r--tests/auto/cmake/test_add_big_resource/test_add_big_resource2.qrc6
-rw-r--r--tests/auto/cmake/test_opengl_lib/CMakeLists.txt14
-rw-r--r--tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp2
-rw-r--r--tests/auto/corelib/animation/qparallelanimationgroup/BLACKLIST1
-rw-r--r--tests/auto/corelib/animation/qsequentialanimationgroup/BLACKLIST1
-rw-r--r--tests/auto/corelib/codecs/qtextcodec/echo/echo.pro4
-rw-r--r--tests/auto/corelib/codecs/qtextcodec/qtextcodec.pro3
-rw-r--r--tests/auto/corelib/codecs/qtextcodec/test.pro6
-rw-r--r--tests/auto/corelib/codecs/qtextcodec/test/test.pro13
-rw-r--r--tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp9
-rw-r--r--tests/auto/corelib/codecs/utf8/tst_utf8.cpp15
-rw-r--r--tests/auto/corelib/codecs/utf8/utf8data.cpp30
-rw-r--r--tests/auto/corelib/global/qflags/tst_qflags.cpp24
-rw-r--r--tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp6
-rw-r--r--tests/auto/corelib/global/qlogging/app/app.pro11
-rw-r--r--tests/auto/corelib/global/qlogging/test/test.pro16
-rw-r--r--tests/auto/corelib/global/qlogging/tst_qlogging.cpp27
-rw-r--r--tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp2
-rw-r--r--tests/auto/corelib/global/qtendian/tst_qtendian.cpp176
-rw-r--r--tests/auto/corelib/io/qdebug/tst_qdebug.cpp16
-rw-r--r--tests/auto/corelib/io/qdir/tst_qdir.cpp1
-rw-r--r--tests/auto/corelib/io/qfile/.gitignore8
-rw-r--r--tests/auto/corelib/io/qfile/qfile.pro3
-rw-r--r--tests/auto/corelib/io/qfile/stdinprocess/main.cpp2
-rw-r--r--tests/auto/corelib/io/qfile/stdinprocess/stdinprocess.pro6
-rw-r--r--tests/auto/corelib/io/qfile/test.pro26
-rw-r--r--tests/auto/corelib/io/qfile/test/test.pro25
-rw-r--r--tests/auto/corelib/io/qfile/tst_qfile.cpp49
-rw-r--r--tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp42
-rw-r--r--tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp3
-rw-r--r--tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp7
-rw-r--r--tests/auto/corelib/io/qnodebug/tst_qnodebug.cpp2
-rw-r--r--tests/auto/corelib/io/qresourceengine/qresourceengine.pro27
-rw-r--r--tests/auto/corelib/io/qresourceengine/qresourceengine_test.pro33
-rw-r--r--tests/auto/corelib/io/qresourceengine/staticplugin/.gitignore1
-rw-r--r--tests/auto/corelib/io/qresourceengine/staticplugin/main.cpp9
-rw-r--r--tests/auto/corelib/io/qresourceengine/staticplugin/staticplugin.json1
-rw-r--r--tests/auto/corelib/io/qresourceengine/staticplugin/staticplugin.pro8
-rw-r--r--tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp14
-rw-r--r--tests/auto/corelib/io/qsettings/qsettings.pro2
-rw-r--r--tests/auto/corelib/io/qsettings/tst_qsettings.cpp6
-rw-r--r--tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp2
-rw-r--r--tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp2
-rw-r--r--tests/auto/corelib/io/qurl/tst_qurl.cpp52
-rw-r--r--tests/auto/corelib/itemmodels/itemmodels.pro7
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel/.gitignore1
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel/qsortfilterproxymodel.pro9
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp4853
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp4950
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h189
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/.gitignore1
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/qsortfilterproxymodel_regexp.pro16
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/tst_qsortfilterproxymodel_regexp.cpp69
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/.gitignore1
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/qsortfilterproxymodel_regularexpression.pro16
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/tst_qsortfilterproxymodel_regularexpression.cpp59
-rw-r--r--tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp4
-rw-r--r--tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.h2
-rw-r--r--tests/auto/corelib/kernel/qelapsedtimer/BLACKLIST1
-rw-r--r--tests/auto/corelib/kernel/qeventdispatcher/BLACKLIST3
-rw-r--r--tests/auto/corelib/kernel/qmetaenum/tst_qmetaenum.cpp23
-rw-r--r--tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp42
-rw-r--r--tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp2
-rw-r--r--tests/auto/corelib/kernel/qmetatype/qmetatype.pro2
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp247
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h18
-rw-r--r--tests/auto/corelib/kernel/qobject/.gitignore8
-rw-r--r--tests/auto/corelib/kernel/qobject/qobject.pro8
-rw-r--r--tests/auto/corelib/kernel/qobject/signalbug/signalbug.pro7
-rw-r--r--tests/auto/corelib/kernel/qobject/test.pro10
-rw-r--r--tests/auto/corelib/kernel/qobject/test/test.pro10
-rw-r--r--tests/auto/corelib/kernel/qobject/tst_qobject.cpp32
-rw-r--r--tests/auto/corelib/kernel/qsharedmemory/producerconsumer/main.cpp (renamed from tests/auto/corelib/kernel/qsharedmemory/sharedmemoryhelper/main.cpp)0
-rw-r--r--tests/auto/corelib/kernel/qsharedmemory/producerconsumer/producerconsumer.pro5
-rw-r--r--tests/auto/corelib/kernel/qsharedmemory/qsharedmemory.pro4
-rw-r--r--tests/auto/corelib/kernel/qsharedmemory/sharedmemoryhelper/sharedmemoryhelper.pro17
-rw-r--r--tests/auto/corelib/kernel/qsharedmemory/test.pro8
-rw-r--r--tests/auto/corelib/kernel/qsharedmemory/test/test.pro18
-rw-r--r--tests/auto/corelib/kernel/qsharedmemory/test/tst_qsharedmemory.cpp839
-rw-r--r--tests/auto/corelib/kernel/qsharedmemory/tst_qsharedmemory.cpp821
-rw-r--r--tests/auto/corelib/kernel/qsystemsemaphore/acquirerelease/acquirerelease.pro5
-rw-r--r--tests/auto/corelib/kernel/qsystemsemaphore/acquirerelease/main.cpp (renamed from tests/auto/corelib/kernel/qsystemsemaphore/systemsemaphorehelper/main.cpp)0
-rw-r--r--tests/auto/corelib/kernel/qsystemsemaphore/qsystemsemaphore.pro2
-rw-r--r--tests/auto/corelib/kernel/qsystemsemaphore/systemsemaphorehelper/systemsemaphorehelper.pro17
-rw-r--r--tests/auto/corelib/kernel/qsystemsemaphore/test.pro7
-rw-r--r--tests/auto/corelib/kernel/qsystemsemaphore/test/test.pro17
-rw-r--r--tests/auto/corelib/kernel/qsystemsemaphore/test/tst_qsystemsemaphore.cpp307
-rw-r--r--tests/auto/corelib/kernel/qsystemsemaphore/tst_qsystemsemaphore.cpp292
-rw-r--r--tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp29
-rw-r--r--tests/auto/corelib/kernel/qtranslator/android_testdata.qrc1
-rw-r--r--tests/auto/corelib/kernel/qtranslator/hellotr_empty.qm1
-rw-r--r--tests/auto/corelib/kernel/qtranslator/hellotr_empty.ts3
-rw-r--r--tests/auto/corelib/kernel/qtranslator/qtranslator.pro2
-rw-r--r--tests/auto/corelib/kernel/qtranslator/qtranslator.qrc1
-rw-r--r--tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp58
-rw-r--r--tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp21
-rw-r--r--tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy.foo3
-rw-r--r--tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy.xml21
-rw-r--r--tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy2.foo3
-rw-r--r--tests/auto/corelib/mimetypes/qmimedatabase/testdata.qrc3
-rw-r--r--tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp7
-rw-r--r--tests/auto/corelib/plugin/plugin.pro3
-rw-r--r--tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp64
-rw-r--r--tests/auto/corelib/plugin/qplugin/tst_qplugin.pro2
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.h2
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp39
-rw-r--r--tests/auto/corelib/plugin/qpluginloader/utf8_data.json17
-rw-r--r--tests/auto/corelib/serialization/qcborstreamreader/qcborstreamreader.pro11
-rw-r--r--tests/auto/corelib/serialization/qcborstreamreader/tst_qcborstreamreader.cpp1091
-rw-r--r--tests/auto/corelib/serialization/qcborstreamwriter/qcborstreamwriter.pro8
-rw-r--r--tests/auto/corelib/serialization/qcborstreamwriter/tst_qcborstreamwriter.cpp313
-rw-r--r--tests/auto/corelib/serialization/qcborvalue/qcborvalue.pro11
-rw-r--r--tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp1695
-rw-r--r--tests/auto/corelib/serialization/qcborvalue_json/qcborvalue_json.pro7
-rw-r--r--tests/auto/corelib/serialization/qcborvalue_json/tst_qcborvalue_json.cpp348
-rw-r--r--tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp63
-rw-r--r--tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp12
-rw-r--r--tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp32
-rw-r--r--tests/auto/corelib/serialization/serialization.pro4
-rw-r--r--tests/auto/corelib/thread/qfuture/tst_qfuture.cpp4
-rw-r--r--tests/auto/corelib/thread/qsemaphore/BLACKLIST2
-rw-r--r--tests/auto/corelib/thread/qthreadonce/qthreadonce.cpp3
-rw-r--r--tests/auto/corelib/thread/qthreadonce/qthreadonce.h4
-rw-r--r--tests/auto/corelib/thread/qthreadstorage/crashonexit/crashonexit.pro10
-rw-r--r--tests/auto/corelib/thread/qthreadstorage/test/test.pro17
-rw-r--r--tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp22
-rw-r--r--tests/auto/corelib/thread/thread.pro39
-rw-r--r--tests/auto/corelib/tools/collections/tst_collections.cpp4
-rw-r--r--tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp129
-rw-r--r--tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp24
-rw-r--r--tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp11
-rw-r--r--tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp5
-rw-r--r--tests/auto/corelib/tools/qexplicitlyshareddatapointer/tst_qexplicitlyshareddatapointer.cpp5
-rw-r--r--tests/auto/corelib/tools/qlocale/tst_qlocale.cpp695
-rw-r--r--tests/auto/corelib/tools/qmacautoreleasepool/qmacautoreleasepool.pro1
-rw-r--r--tests/auto/corelib/tools/qmakearray/qmakearray.pro4
-rw-r--r--tests/auto/corelib/tools/qmakearray/tst_qmakearray.cpp103
-rw-r--r--tests/auto/corelib/tools/qregularexpression/alwaysoptimize/alwaysoptimize.pro7
-rw-r--r--tests/auto/corelib/tools/qregularexpression/alwaysoptimize/tst_qregularexpression_alwaysoptimize.cpp51
-rw-r--r--tests/auto/corelib/tools/qregularexpression/defaultoptimize/defaultoptimize.pro7
-rw-r--r--tests/auto/corelib/tools/qregularexpression/defaultoptimize/tst_qregularexpression_defaultoptimize.cpp39
-rw-r--r--tests/auto/corelib/tools/qregularexpression/forceoptimize/forceoptimize.pro8
-rw-r--r--tests/auto/corelib/tools/qregularexpression/forceoptimize/tst_qregularexpression_forceoptimize.cpp39
-rw-r--r--tests/auto/corelib/tools/qregularexpression/qregularexpression.pro7
-rw-r--r--tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp289
-rw-r--r--tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.h74
-rw-r--r--tests/auto/corelib/tools/qscopeguard/qscopeguard.pro4
-rw-r--r--tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp85
-rw-r--r--tests/auto/corelib/tools/qsharedpointer/externaltests.cpp20
-rw-r--r--tests/auto/corelib/tools/qstring/tst_qstring.cpp99
-rw-r--r--tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp9
-rw-r--r--tests/auto/corelib/tools/qstringview/tst_qstringview.cpp20
-rw-r--r--tests/auto/corelib/tools/qtimeline/BLACKLIST2
-rw-r--r--tests/auto/corelib/tools/qtimezone/qtimezone.pro2
-rw-r--r--tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp25
-rw-r--r--tests/auto/corelib/tools/tools.pro1
-rw-r--r--tests/auto/dbus/qdbusinterface/qdbusinterface/qdbusinterface.pro9
-rw-r--r--tests/auto/dbus/qdbusinterface/qmyserver/qmyserver.cpp10
-rw-r--r--tests/auto/dbus/qdbusinterface/tst_qdbusinterface.cpp27
-rw-r--r--tests/auto/gui/gui.pro2
-rw-r--r--tests/auto/gui/image/qimage/images/jpeg_exif_utf8_comment.jpgbin0 -> 705 bytes
-rw-r--r--tests/auto/gui/image/qimage/qimage.pro3
-rw-r--r--tests/auto/gui/image/qimage/tst_qimage.cpp224
-rw-r--r--tests/auto/gui/image/qimagereader/images/basn0g16.pngbin0 -> 167 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/basn2c16.pngbin0 -> 302 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/basn4a16.pngbin0 -> 2206 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/basn6a16.pngbin0 -> 3435 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/kollada-16bpc.pngbin0 -> 24360 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/images/tbwn0g16.pngbin0 -> 1313 bytes
-rw-r--r--tests/auto/gui/image/qimagereader/qimagereader.pro3
-rw-r--r--tests/auto/gui/image/qimagereader/qimagereader.qrc69
-rw-r--r--tests/auto/gui/image/qimagereader/tst_qimagereader.cpp10
-rw-r--r--tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp1
-rw-r--r--tests/auto/gui/image/qpicture/qpicture.pro1
-rw-r--r--tests/auto/gui/image/qpicture/tst_qpicture.cpp38
-rw-r--r--tests/auto/gui/image/qpixmap/tst_qpixmap.cpp22
-rw-r--r--tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp3
-rw-r--r--tests/auto/gui/itemmodels/qstandarditem/tst_qstandarditem.cpp12
-rw-r--r--tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp26
-rw-r--r--tests/auto/gui/kernel/qguiapplication/BLACKLIST4
-rw-r--r--tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp6
-rw-r--r--tests/auto/gui/kernel/qpalette/tst_qpalette.cpp3
-rw-r--r--tests/auto/gui/kernel/qtouchevent/qtouchevent.pro1
-rw-r--r--tests/auto/gui/kernel/qwindow/BLACKLIST2
-rw-r--r--tests/auto/gui/kernel/qwindow/tst_qwindow.cpp122
-rw-r--r--tests/auto/gui/painting/qbrush/tst_qbrush.cpp21
-rw-r--r--tests/auto/gui/painting/qcolor/tst_qcolor.cpp20
-rw-r--r--tests/auto/gui/painting/qpainter/tst_qpainter.cpp63
-rw-r--r--tests/auto/gui/qopengl/tst_qopengl.cpp79
-rw-r--r--tests/auto/gui/text/qcssparser/tst_qcssparser.cpp6
-rw-r--r--tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp24
-rw-r--r--tests/auto/gui/text/qglyphrun/BLACKLIST3
-rw-r--r--tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp3
-rw-r--r--tests/auto/gui/text/qstatictext/tst_qstatictext.cpp62
-rw-r--r--tests/auto/gui/text/qtextcursor/tst_qtextcursor.cpp10
-rw-r--r--tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp12
-rw-r--r--tests/auto/gui/text/qtextdocumentlayout/tst_qtextdocumentlayout.cpp7
-rw-r--r--tests/auto/gui/text/qtextodfwriter/tst_qtextodfwriter.cpp4
-rw-r--r--tests/auto/gui/util/qdoublevalidator/tst_qdoublevalidator.cpp8
-rw-r--r--tests/auto/gui/util/qintvalidator/tst_qintvalidator.cpp8
-rw-r--r--tests/auto/gui/util/qtexturefilereader/qtexturefilereader.pro5
-rw-r--r--tests/auto/gui/util/qtexturefilereader/qtexturefilereader.qrc7
-rw-r--r--tests/auto/gui/util/qtexturefilereader/texturefiles/car.ktxbin0 -> 11908 bytes
-rw-r--r--tests/auto/gui/util/qtexturefilereader/texturefiles/car_mips.ktxbin0 -> 8088 bytes
-rw-r--r--tests/auto/gui/util/qtexturefilereader/texturefiles/pattern.pkmbin0 -> 2064 bytes
-rw-r--r--tests/auto/gui/util/qtexturefilereader/tst_qtexturefilereader.cpp111
-rw-r--r--tests/auto/gui/util/util.pro2
-rw-r--r--tests/auto/network-settings.h61
-rw-r--r--tests/auto/network/access/hpack/hpack.pro4
-rw-r--r--tests/auto/network/access/hsts/hsts.pro2
-rw-r--r--tests/auto/network/access/http2/http2.pro2
-rw-r--r--tests/auto/network/access/http2/http2srv.cpp32
-rw-r--r--tests/auto/network/access/http2/http2srv.h4
-rw-r--r--tests/auto/network/access/http2/tst_http2.cpp19
-rw-r--r--tests/auto/network/access/qnetworkreply/certs/qt-test-net-cacert.pem16
-rw-r--r--tests/auto/network/access/qnetworkreply/test/test.pro3
-rw-r--r--tests/auto/network/access/qnetworkreply/testserver_index.html3
-rw-r--r--tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp557
-rw-r--r--tests/auto/network/access/qnetworkrequest/tst_qnetworkrequest.cpp96
-rw-r--r--tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp4
-rw-r--r--tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp3
-rw-r--r--tests/auto/network/ssl/qdtls/certs/bogus-ca.crt20
-rw-r--r--tests/auto/network/ssl/qdtls/certs/bogus-ca.key27
-rw-r--r--tests/auto/network/ssl/qdtls/certs/bogus-client.crt19
-rw-r--r--tests/auto/network/ssl/qdtls/certs/bogus-client.key27
-rw-r--r--tests/auto/network/ssl/qdtls/certs/bogus-server.crt19
-rw-r--r--tests/auto/network/ssl/qdtls/certs/bogus-server.key27
-rw-r--r--tests/auto/network/ssl/qdtls/certs/fake-login.live.com.key15
-rw-r--r--tests/auto/network/ssl/qdtls/certs/fake-login.live.com.pem19
-rw-r--r--tests/auto/network/ssl/qdtls/certs/fluke.cert75
-rw-r--r--tests/auto/network/ssl/qdtls/certs/fluke.key15
-rw-r--r--tests/auto/network/ssl/qdtls/certs/ss-srv-cert.pem18
-rw-r--r--tests/auto/network/ssl/qdtls/certs/ss-srv-key.pem18
-rw-r--r--tests/auto/network/ssl/qdtls/qdtls.pro16
-rw-r--r--tests/auto/network/ssl/qdtls/tst_qdtls.cpp1324
-rw-r--r--tests/auto/network/ssl/qdtlscookie/qdtlscookie.pro15
-rw-r--r--tests/auto/network/ssl/qdtlscookie/tst_qdtlscookie.cpp478
-rw-r--r--tests/auto/network/ssl/qpassworddigestor/qpassworddigestor.pro4
-rw-r--r--tests/auto/network/ssl/qpassworddigestor/tst_qpassworddigestor.cpp171
-rw-r--r--tests/auto/network/ssl/qsslcertificate/qsslcertificate.pro1
-rw-r--r--tests/auto/network/ssl/qsslcipher/qsslcipher.pro1
-rw-r--r--tests/auto/network/ssl/qssldiffiehellmanparameters/qssldiffiehellmanparameters.pro1
-rw-r--r--tests/auto/network/ssl/qsslellipticcurve/qsslellipticcurve.pro1
-rw-r--r--tests/auto/network/ssl/qsslerror/qsslerror.pro1
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-MD5-DES.derbin0 -> 243 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-MD5-DES.pem8
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-MD5-RC2-64.derbin0 -> 243 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-MD5-RC2-64.pem8
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-SHA1-DES.derbin0 -> 243 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-SHA1-DES.pem8
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-SHA1-RC2-64.derbin0 -> 243 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-SHA1-RC2-64.pem8
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes128-hmacWithSHA1.derbin0 -> 290 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes128-hmacWithSHA1.pem9
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes128-hmacWithSHA256.derbin0 -> 304 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes128-hmacWithSHA256.pem9
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes256-hmacWithSHA1.derbin0 -> 290 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes256-hmacWithSHA1.pem9
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes256-hmacWithSHA256.derbin0 -> 304 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes256-hmacWithSHA256.pem9
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-des3-hmacWithSHA1.derbin0 -> 281 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-des3-hmacWithSHA1.pem8
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-des3-hmacWithSHA256.derbin0 -> 295 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-des3-hmacWithSHA256.pem9
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-2DES.derbin0 -> 244 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-2DES.pem8
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-3DES.derbin0 -> 244 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-3DES.pem8
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-128.derbin0 -> 244 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-128.pem8
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-40.derbin0 -> 244 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-40.pem8
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-128.derbin0 -> 237 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-128.pem7
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-40.derbin0 -> 237 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-40.pem7
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-rc2-hmacWithSHA1.derbin0 -> 289 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-rc2-hmacWithSHA1.pem9
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-rc2-hmacWithSHA256.derbin0 -> 303 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-rc2-hmacWithSHA256.pem9
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8.derbin0 -> 201 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8.pem7
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-MD5-DES.derbin0 -> 163 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-MD5-DES.pem6
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-MD5-RC2-64.derbin0 -> 163 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-MD5-RC2-64.pem6
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-SHA1-DES.derbin0 -> 163 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-SHA1-DES.pem6
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-SHA1-RC2-64.derbin0 -> 163 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-SHA1-RC2-64.pem6
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes128-hmacWithSHA1.derbin0 -> 209 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes128-hmacWithSHA1.pem7
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes128-hmacWithSHA256.derbin0 -> 223 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes128-hmacWithSHA256.pem7
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes256-hmacWithSHA1.derbin0 -> 209 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes256-hmacWithSHA1.pem7
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes256-hmacWithSHA256.derbin0 -> 223 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes256-hmacWithSHA256.pem7
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-des3-hmacWithSHA1.derbin0 -> 200 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-des3-hmacWithSHA1.pem7
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-des3-hmacWithSHA256.derbin0 -> 214 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-des3-hmacWithSHA256.pem7
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-2DES.derbin0 -> 164 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-2DES.pem6
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-3DES.derbin0 -> 164 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-3DES.pem6
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC2-128.derbin0 -> 164 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC2-128.pem6
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC2-40.derbin0 -> 164 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC2-40.pem6
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC4-128.derbin0 -> 157 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC4-128.pem6
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC4-40.derbin0 -> 157 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC4-40.pem6
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-rc2-hmacWithSHA1.derbin0 -> 208 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-rc2-hmacWithSHA1.pem7
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-rc2-hmacWithSHA256.derbin0 -> 222 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-rc2-hmacWithSHA256.pem7
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8.derbin0 -> 122 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8.pem5
-rwxr-xr-xtests/auto/network/ssl/qsslkey/keys/genkeys.sh55
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-MD5-DES.derbin0 -> 389 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-MD5-DES.pem11
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-MD5-RC2-64.derbin0 -> 389 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-MD5-RC2-64.pem11
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-SHA1-DES.derbin0 -> 389 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-SHA1-DES.pem11
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-SHA1-RC2-64.derbin0 -> 389 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-SHA1-RC2-64.pem11
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes128-hmacWithSHA1.derbin0 -> 435 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes128-hmacWithSHA1.pem12
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes128-hmacWithSHA256.derbin0 -> 449 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes128-hmacWithSHA256.pem12
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes256-hmacWithSHA1.derbin0 -> 435 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes256-hmacWithSHA1.pem12
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes256-hmacWithSHA256.derbin0 -> 449 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes256-hmacWithSHA256.pem12
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-des3-hmacWithSHA1.derbin0 -> 426 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-des3-hmacWithSHA1.pem11
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-des3-hmacWithSHA256.derbin0 -> 440 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-des3-hmacWithSHA256.pem12
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-2DES.derbin0 -> 390 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-2DES.pem11
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-3DES.derbin0 -> 390 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-3DES.pem11
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-128.derbin0 -> 390 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-128.pem11
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-40.derbin0 -> 390 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-40.pem11
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-128.derbin0 -> 384 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-128.pem10
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-40.derbin0 -> 384 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-40.pem10
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-rc2-hmacWithSHA1.derbin0 -> 426 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-rc2-hmacWithSHA1.pem11
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-rc2-hmacWithSHA256.derbin0 -> 440 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-rc2-hmacWithSHA256.pem12
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8.derbin0 -> 345 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8.pem10
-rw-r--r--tests/auto/network/ssl/qsslkey/qsslkey.pro1
-rw-r--r--tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp52
-rw-r--r--tests/auto/network/ssl/qsslsocket/qsslsocket.pro1
-rw-r--r--tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp97
-rw-r--r--tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro1
-rw-r--r--tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro1
-rw-r--r--tests/auto/network/ssl/ssl.pro11
-rw-r--r--tests/auto/opengl/qgl/BLACKLIST1
-rw-r--r--tests/auto/opengl/qglthreads/tst_qglthreads.cpp7
-rw-r--r--tests/auto/other/gestures/BLACKLIST12
-rw-r--r--tests/auto/other/lancelot/paintcommands.cpp49
-rw-r--r--tests/auto/other/lancelot/paintcommands.h2
-rw-r--r--tests/auto/other/lancelot/scripts/gradientxform_object.qps15
-rw-r--r--tests/auto/other/lancelot/scripts/image_dpr.qps43
-rw-r--r--tests/auto/other/macnativeevents/macnativeevents.pro2
-rw-r--r--tests/auto/other/other.pro8
-rw-r--r--tests/auto/other/qaccessibility/tst_qaccessibility.cpp4
-rw-r--r--tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp53
-rw-r--r--tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.mm4
-rw-r--r--tests/auto/other/qfocusevent/BLACKLIST1
-rw-r--r--tests/auto/other/qfocusevent/tst_qfocusevent.cpp5
-rw-r--r--tests/auto/printsupport/dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp3
-rw-r--r--tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp4
-rw-r--r--tests/auto/sql/kernel/qsqldriver/tst_qsqldriver.cpp20
-rw-r--r--tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp55
-rw-r--r--tests/auto/sql/kernel/qsqlresult/qsqlresult.pro2
-rw-r--r--tests/auto/sql/kernel/qsqlthread/tst_qsqlthread.cpp2
-rw-r--r--tests/auto/sql/models/qsqlrelationaldelegate/qsqlrelationaldelegate.pro5
-rw-r--r--tests/auto/sql/models/qsqlrelationaldelegate/tst_qsqlrelationaldelegate.cpp170
-rw-r--r--tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp47
-rw-r--r--tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp62
-rw-r--r--tests/auto/testlib/selftests/expected_assert.tap16
-rw-r--r--tests/auto/testlib/selftests/expected_badxml.tap61
-rw-r--r--tests/auto/testlib/selftests/expected_benchlibcounting.tap17
-rw-r--r--tests/auto/testlib/selftests/expected_benchlibeventcounter.tap15
-rw-r--r--tests/auto/testlib/selftests/expected_benchlibtickcounter.tap9
-rw-r--r--tests/auto/testlib/selftests/expected_benchlibwalltime.tap11
-rw-r--r--tests/auto/testlib/selftests/expected_cmptest.lightxml36
-rw-r--r--tests/auto/testlib/selftests/expected_cmptest.tap456
-rw-r--r--tests/auto/testlib/selftests/expected_cmptest.teamcity16
-rw-r--r--tests/auto/testlib/selftests/expected_cmptest.txt20
-rw-r--r--tests/auto/testlib/selftests/expected_cmptest.xml36
-rw-r--r--tests/auto/testlib/selftests/expected_cmptest.xunitxml18
-rw-r--r--tests/auto/testlib/selftests/expected_commandlinedata.tap20
-rw-r--r--tests/auto/testlib/selftests/expected_counting.tap118
-rw-r--r--tests/auto/testlib/selftests/expected_crashes_4.txt7
-rw-r--r--tests/auto/testlib/selftests/expected_datatable.tap183
-rw-r--r--tests/auto/testlib/selftests/expected_datetime.tap46
-rw-r--r--tests/auto/testlib/selftests/expected_exceptionthrow.tap14
-rw-r--r--tests/auto/testlib/selftests/expected_expectfail.tap96
-rw-r--r--tests/auto/testlib/selftests/expected_failcleanup.tap20
-rw-r--r--tests/auto/testlib/selftests/expected_failinit.tap19
-rw-r--r--tests/auto/testlib/selftests/expected_failinitdata.tap18
-rw-r--r--tests/auto/testlib/selftests/expected_fetchbogus.tap15
-rw-r--r--tests/auto/testlib/selftests/expected_findtestdata.tap10
-rw-r--r--tests/auto/testlib/selftests/expected_float.tap82
-rw-r--r--tests/auto/testlib/selftests/expected_globaldata.tap52
-rw-r--r--tests/auto/testlib/selftests/expected_keyboard.lightxml18
-rw-r--r--tests/auto/testlib/selftests/expected_keyboard.tap9
-rw-r--r--tests/auto/testlib/selftests/expected_keyboard.teamcity8
-rw-r--r--tests/auto/testlib/selftests/expected_keyboard.txt7
-rw-r--r--tests/auto/testlib/selftests/expected_keyboard.xml21
-rw-r--r--tests/auto/testlib/selftests/expected_keyboard.xunitxml12
-rw-r--r--tests/auto/testlib/selftests/expected_longstring.tap23
-rw-r--r--tests/auto/testlib/selftests/expected_maxwarnings.tap2011
-rw-r--r--tests/auto/testlib/selftests/expected_pairdiagnostics.tap32
-rw-r--r--tests/auto/testlib/selftests/expected_singleskip.tap9
-rw-r--r--tests/auto/testlib/selftests/expected_skip.tap13
-rw-r--r--tests/auto/testlib/selftests/expected_skipcleanup.tap9
-rw-r--r--tests/auto/testlib/selftests/expected_skipinit.tap8
-rw-r--r--tests/auto/testlib/selftests/expected_skipinitdata.tap7
-rw-r--r--tests/auto/testlib/selftests/expected_sleep.tap9
-rw-r--r--tests/auto/testlib/selftests/expected_strcmp.tap87
-rw-r--r--tests/auto/testlib/selftests/expected_subtest.tap68
-rw-r--r--tests/auto/testlib/selftests/expected_tuplediagnostics.lightxml34
-rw-r--r--tests/auto/testlib/selftests/expected_tuplediagnostics.tap33
-rw-r--r--tests/auto/testlib/selftests/expected_tuplediagnostics.teamcity14
-rw-r--r--tests/auto/testlib/selftests/expected_tuplediagnostics.txt15
-rw-r--r--tests/auto/testlib/selftests/expected_tuplediagnostics.xml37
-rw-r--r--tests/auto/testlib/selftests/expected_tuplediagnostics.xunitxml22
-rw-r--r--tests/auto/testlib/selftests/expected_verbose1.tap118
-rw-r--r--tests/auto/testlib/selftests/expected_verbose2.tap136
-rw-r--r--tests/auto/testlib/selftests/expected_verifyexceptionthrown.tap53
-rw-r--r--tests/auto/testlib/selftests/expected_warnings.tap42
-rw-r--r--tests/auto/testlib/selftests/expected_xunit.tap44
-rwxr-xr-xtests/auto/testlib/selftests/generate_expected_output.py28
-rw-r--r--tests/auto/testlib/selftests/keyboard/keyboard.pro7
-rw-r--r--tests/auto/testlib/selftests/keyboard/tst_keyboard.cpp88
-rw-r--r--tests/auto/testlib/selftests/selftests.pri8
-rw-r--r--tests/auto/testlib/selftests/selftests.qrc219
-rw-r--r--tests/auto/testlib/selftests/test/test.pro4
-rw-r--r--tests/auto/testlib/selftests/tst_selftests.cpp395
-rw-r--r--tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp65
-rw-r--r--tests/auto/testlib/selftests/tuplediagnostics/tuplediagnostics.pro6
-rw-r--r--tests/auto/testserver.pri109
-rw-r--r--tests/auto/tools/moc/cxx11-enums.h7
-rw-r--r--tests/auto/tools/moc/tst_moc.cpp34
-rw-r--r--tests/auto/tools/qmakelib/evaltest.cpp72
-rw-r--r--tests/auto/tools/uic/baseline/Dialog_with_Buttons_Bottom.ui.h4
-rw-r--r--tests/auto/tools/uic/baseline/Dialog_with_Buttons_Right.ui.h4
-rw-r--r--tests/auto/tools/uic/baseline/Dialog_without_Buttons.ui.h2
-rw-r--r--tests/auto/tools/uic/baseline/Main_Window.ui.h8
-rw-r--r--tests/auto/tools/uic/baseline/Widget.ui.h10
-rw-r--r--tests/auto/tools/uic/baseline/addlinkdialog.ui.h18
-rw-r--r--tests/auto/tools/uic/baseline/addtorrentform.ui.h48
-rw-r--r--tests/auto/tools/uic/baseline/authenticationdialog.ui.h20
-rw-r--r--tests/auto/tools/uic/baseline/backside.ui.h30
-rw-r--r--tests/auto/tools/uic/baseline/batchtranslation.ui.h34
-rw-r--r--tests/auto/tools/uic/baseline/bookmarkdialog.ui.h32
-rw-r--r--tests/auto/tools/uic/baseline/bookwindow.ui.h36
-rw-r--r--tests/auto/tools/uic/baseline/browserwidget.ui.h26
-rw-r--r--tests/auto/tools/uic/baseline/bug18156QTreeWidget.ui.h8
-rw-r--r--tests/auto/tools/uic/baseline/buttongroup.ui.h56
-rw-r--r--tests/auto/tools/uic/baseline/calculator.ui.h58
-rw-r--r--tests/auto/tools/uic/baseline/calculatorform.ui.h38
-rw-r--r--tests/auto/tools/uic/baseline/certificateinfo.ui.h20
-rw-r--r--tests/auto/tools/uic/baseline/chatdialog.ui.h16
-rw-r--r--tests/auto/tools/uic/baseline/chatmainwindow.ui.h32
-rw-r--r--tests/auto/tools/uic/baseline/chatsetnickname.ui.h16
-rw-r--r--tests/auto/tools/uic/baseline/config.ui.h104
-rw-r--r--tests/auto/tools/uic/baseline/connectdialog.ui.h28
-rw-r--r--tests/auto/tools/uic/baseline/controller.ui.h14
-rw-r--r--tests/auto/tools/uic/baseline/cookies.ui.h16
-rw-r--r--tests/auto/tools/uic/baseline/cookiesexceptions.ui.h36
-rw-r--r--tests/auto/tools/uic/baseline/default.ui.h52
-rw-r--r--tests/auto/tools/uic/baseline/dialog.ui.h10
-rw-r--r--tests/auto/tools/uic/baseline/downloaditem.ui.h22
-rw-r--r--tests/auto/tools/uic/baseline/downloads.ui.h12
-rw-r--r--tests/auto/tools/uic/baseline/embeddeddialog.ui.h20
-rw-r--r--tests/auto/tools/uic/baseline/enumnostdset.ui.h4
-rw-r--r--tests/auto/tools/uic/baseline/filespage.ui.h12
-rw-r--r--tests/auto/tools/uic/baseline/filternamedialog.ui.h12
-rw-r--r--tests/auto/tools/uic/baseline/filterpage.ui.h18
-rw-r--r--tests/auto/tools/uic/baseline/finddialog.ui.h32
-rw-r--r--tests/auto/tools/uic/baseline/form.ui.h20
-rw-r--r--tests/auto/tools/uic/baseline/formwindowsettings.ui.h56
-rw-r--r--tests/auto/tools/uic/baseline/generalpage.ui.h12
-rw-r--r--tests/auto/tools/uic/baseline/gridalignment.ui.h12
-rw-r--r--tests/auto/tools/uic/baseline/gridpanel.ui.h26
-rw-r--r--tests/auto/tools/uic/baseline/helpdialog.ui.h60
-rw-r--r--tests/auto/tools/uic/baseline/history.ui.h16
-rw-r--r--tests/auto/tools/uic/baseline/icontheme.ui.h20
-rw-r--r--tests/auto/tools/uic/baseline/idbased.ui.h6
-rw-r--r--tests/auto/tools/uic/baseline/identifierpage.ui.h12
-rw-r--r--tests/auto/tools/uic/baseline/imagedialog.ui.h36
-rw-r--r--tests/auto/tools/uic/baseline/inputpage.ui.h12
-rw-r--r--tests/auto/tools/uic/baseline/installdialog.ui.h26
-rw-r--r--tests/auto/tools/uic/baseline/languagesdialog.ui.h26
-rw-r--r--tests/auto/tools/uic/baseline/listwidgeteditor.ui.h28
-rw-r--r--tests/auto/tools/uic/baseline/mainwindow.ui.h88
-rw-r--r--tests/auto/tools/uic/baseline/mydialog.ui.h8
-rw-r--r--tests/auto/tools/uic/baseline/myform.ui.h26
-rw-r--r--tests/auto/tools/uic/baseline/newactiondialog.ui.h24
-rw-r--r--tests/auto/tools/uic/baseline/newdynamicpropertydialog.ui.h18
-rw-r--r--tests/auto/tools/uic/baseline/newform.ui.h16
-rw-r--r--tests/auto/tools/uic/baseline/orderdialog.ui.h18
-rw-r--r--tests/auto/tools/uic/baseline/outputpage.ui.h12
-rw-r--r--tests/auto/tools/uic/baseline/pagefold.ui.h56
-rw-r--r--tests/auto/tools/uic/baseline/paletteeditor.ui.h32
-rw-r--r--tests/auto/tools/uic/baseline/passworddialog.ui.h20
-rw-r--r--tests/auto/tools/uic/baseline/pathpage.ui.h16
-rw-r--r--tests/auto/tools/uic/baseline/phrasebookbox.ui.h32
-rw-r--r--tests/auto/tools/uic/baseline/pixmapfunction.ui47
-rw-r--r--tests/auto/tools/uic/baseline/pixmapfunction.ui.h74
-rw-r--r--tests/auto/tools/uic/baseline/plugindialog.ui.h14
-rw-r--r--tests/auto/tools/uic/baseline/preferencesdialog.ui.h36
-rw-r--r--tests/auto/tools/uic/baseline/previewconfigurationwidget.ui.h26
-rw-r--r--tests/auto/tools/uic/baseline/previewdialogbase.ui.h26
-rw-r--r--tests/auto/tools/uic/baseline/previewwidget.ui.h42
-rw-r--r--tests/auto/tools/uic/baseline/proxy.ui.h18
-rw-r--r--tests/auto/tools/uic/baseline/qfiledialog.ui.h54
-rw-r--r--tests/auto/tools/uic/baseline/qpagesetupwidget.ui.h86
-rw-r--r--tests/auto/tools/uic/baseline/qprintpropertieswidget.ui.h18
-rw-r--r--tests/auto/tools/uic/baseline/qprintsettingsoutput.ui.h66
-rw-r--r--tests/auto/tools/uic/baseline/qprintwidget.ui.h32
-rw-r--r--tests/auto/tools/uic/baseline/qsqlconnectiondialog.ui.h42
-rw-r--r--tests/auto/tools/uic/baseline/qtgradientdialog.ui.h8
-rw-r--r--tests/auto/tools/uic/baseline/qtgradienteditor.ui.h188
-rw-r--r--tests/auto/tools/uic/baseline/qtgradientview.ui.h16
-rw-r--r--tests/auto/tools/uic/baseline/qtgradientviewdialog.ui.h8
-rw-r--r--tests/auto/tools/uic/baseline/qtresourceeditordialog.ui.h32
-rw-r--r--tests/auto/tools/uic/baseline/qttoolbardialog.ui.h36
-rw-r--r--tests/auto/tools/uic/baseline/qttrid.ui.h56
-rw-r--r--tests/auto/tools/uic/baseline/querywidget.ui.h36
-rw-r--r--tests/auto/tools/uic/baseline/remotecontrol.ui.h56
-rw-r--r--tests/auto/tools/uic/baseline/saveformastemplate.ui.h18
-rw-r--r--tests/auto/tools/uic/baseline/settings.ui.h34
-rw-r--r--tests/auto/tools/uic/baseline/signalslotdialog.ui.h30
-rw-r--r--tests/auto/tools/uic/baseline/sslclient.ui.h36
-rw-r--r--tests/auto/tools/uic/baseline/sslerrors.ui.h16
-rw-r--r--tests/auto/tools/uic/baseline/statistics.ui.h42
-rw-r--r--tests/auto/tools/uic/baseline/stringlisteditor.ui.h32
-rw-r--r--tests/auto/tools/uic/baseline/stylesheeteditor.ui.h18
-rw-r--r--tests/auto/tools/uic/baseline/tabbedbrowser.ui.h28
-rw-r--r--tests/auto/tools/uic/baseline/tablewidgeteditor.ui.h66
-rw-r--r--tests/auto/tools/uic/baseline/tetrixwindow.ui.h30
-rw-r--r--tests/auto/tools/uic/baseline/textfinder.ui.h14
-rw-r--r--tests/auto/tools/uic/baseline/topicchooser.ui.h20
-rw-r--r--tests/auto/tools/uic/baseline/translatedialog.ui.h34
-rw-r--r--tests/auto/tools/uic/baseline/translation/Dialog_without_Buttons_tr.h2
-rw-r--r--tests/auto/tools/uic/baseline/translationsettings.ui.h18
-rw-r--r--tests/auto/tools/uic/baseline/treewidgeteditor.ui.h56
-rw-r--r--tests/auto/tools/uic/baseline/trpreviewtool.ui.h38
-rw-r--r--tests/auto/tools/uic/baseline/validators.ui.h86
-rw-r--r--tests/auto/tools/uic/baseline/wateringconfigdialog.ui.h46
-rw-r--r--tests/auto/widgets/dialogs/dialogs.pro1
-rw-r--r--tests/auto/widgets/dialogs/qcolordialog/qcolordialog.pro2
-rw-r--r--tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp6
-rw-r--r--tests/auto/widgets/dialogs/qdialog/BLACKLIST2
-rw-r--r--tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp11
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp96
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog2/BLACKLIST2
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp2
-rw-r--r--tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp79
-rw-r--r--tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp2
-rw-r--r--tests/auto/widgets/dialogs/qsidebar/tst_qsidebar.cpp9
-rw-r--r--tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp3
-rw-r--r--tests/auto/widgets/effects/qgraphicseffect/BLACKLIST3
-rw-r--r--tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp4
-rw-r--r--tests/auto/widgets/graphicsview/graphicsview.pro2
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp65
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsproxywidget/qgraphicsproxywidget.pro1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp128
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/BLACKLIST12
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp42
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp3
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp26
-rw-r--r--tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp9
-rw-r--r--tests/auto/widgets/itemviews/qcolumnview/tst_qcolumnview.cpp2
-rw-r--r--tests/auto/widgets/itemviews/qdirmodel/tst_qdirmodel.cpp18
-rw-r--r--tests/auto/widgets/itemviews/qheaderview/BLACKLIST3
-rw-r--r--tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp72
-rw-r--r--tests/auto/widgets/itemviews/qitemdelegate/BLACKLIST1
-rw-r--r--tests/auto/widgets/itemviews/qitemview/BLACKLIST2
-rw-r--r--tests/auto/widgets/itemviews/qitemview/tst_qitemview.cpp31
-rw-r--r--tests/auto/widgets/itemviews/qlistview/qlistview.pro1
-rw-r--r--tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp86
-rw-r--r--tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp21
-rw-r--r--tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp64
-rw-r--r--tests/auto/widgets/itemviews/qtreeview/BLACKLIST2
-rw-r--r--tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp11
-rw-r--r--tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp66
-rw-r--r--tests/auto/widgets/kernel/qapplication/BLACKLIST1
-rw-r--r--tests/auto/widgets/kernel/qapplication/desktopsettingsaware/desktopsettingsaware.pro12
-rw-r--r--tests/auto/widgets/kernel/qapplication/modal/modal.pro12
-rw-r--r--tests/auto/widgets/kernel/qapplication/test/test.pro26
-rw-r--r--tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp56
-rw-r--r--tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp20
-rw-r--r--tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp3
-rw-r--r--tests/auto/widgets/kernel/qgesturerecognizer/BLACKLIST2
-rw-r--r--tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp2
-rw-r--r--tests/auto/widgets/kernel/qsizepolicy/tst_qsizepolicy.cpp12
-rw-r--r--tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp7
-rw-r--r--tests/auto/widgets/kernel/qwidget/BLACKLIST39
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp193
-rw-r--r--tests/auto/widgets/kernel/qwidget_window/BLACKLIST3
-rw-r--r--tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp133
-rw-r--r--tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp12
-rw-r--r--tests/auto/widgets/styles/qstyle/tst_qstyle.cpp10
-rw-r--r--tests/auto/widgets/styles/qstylesheetstyle/images/testimage.pngbin299 -> 300 bytes
-rw-r--r--tests/auto/widgets/styles/qstylesheetstyle/images/testimage@2x.pngbin0 -> 318 bytes
-rw-r--r--tests/auto/widgets/styles/qstylesheetstyle/resources.qrc1
-rw-r--r--tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp88
-rw-r--r--tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp9
-rw-r--r--tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp4
-rw-r--r--tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp7
-rw-r--r--tests/auto/widgets/widgets/qcombobox/qcombobox.pro3
-rw-r--r--tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp57
-rw-r--r--tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp632
-rw-r--r--tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp23
-rw-r--r--tests/auto/widgets/widgets/qdoublespinbox/BLACKLIST2
-rw-r--r--tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp635
-rw-r--r--tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp91
-rw-r--r--tests/auto/widgets/widgets/qmainwindow/BLACKLIST2
-rw-r--r--tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp10
-rw-r--r--tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp29
-rw-r--r--tests/auto/widgets/widgets/qmdisubwindow/qmdisubwindow.pro2
-rw-r--r--tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp40
-rw-r--r--tests/auto/widgets/widgets/qmenu/BLACKLIST2
-rw-r--r--tests/auto/widgets/widgets/qmenu/qmenu.pro2
-rw-r--r--tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp181
-rw-r--r--tests/auto/widgets/widgets/qmenubar/BLACKLIST3
-rw-r--r--tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp7
-rw-r--r--tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp3
-rw-r--r--tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp3
-rw-r--r--tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp2
-rw-r--r--tests/auto/widgets/widgets/qsizegrip/BLACKLIST2
-rw-r--r--tests/auto/widgets/widgets/qsizegrip/tst_qsizegrip.cpp11
-rw-r--r--tests/auto/widgets/widgets/qspinbox/BLACKLIST3
-rw-r--r--tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp589
-rw-r--r--tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp6
-rw-r--r--tests/auto/widgets/widgets/qstatusbar/tst_qstatusbar.cpp3
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/qtextbrowser.pro2
-rw-r--r--tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp40
-rw-r--r--tests/auto/widgets/widgets/qtextedit/qtextedit.pro2
-rw-r--r--tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp6
-rw-r--r--tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp3
-rw-r--r--tests/auto/widgets/widgets/widgets.pro2
-rw-r--r--tests/baselineserver/shared/qbaselinetest.cpp30
-rw-r--r--tests/benchmarks/corelib/tools/qtimezone/main.cpp52
-rw-r--r--tests/benchmarks/corelib/tools/qtimezone/qtimezone.pro4
-rw-r--r--tests/benchmarks/corelib/tools/tools.pro1
-rw-r--r--tests/benchmarks/gui/graphicsview/graphicsview.pro16
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp234
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicslayout/qgraphicslayout.pro5
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp140
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicslinearlayout/qgraphicslinearlayout.pro5
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp120
-rw-r--r--tests/benchmarks/gui/gui.pro8
-rw-r--r--tests/benchmarks/gui/image/image.pro3
-rw-r--r--tests/benchmarks/gui/image/qimagereader/qimagereader.pro1
-rw-r--r--tests/benchmarks/gui/image/qimagereader/tst_qimagereader.cpp2
-rw-r--r--tests/benchmarks/gui/kernel/kernel.pro4
-rw-r--r--tests/benchmarks/gui/painting/painting.pro1
-rw-r--r--tests/benchmarks/gui/painting/qpainter/tst_qpainter.cpp4
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/GraphicsViewBenchmark.pro (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/GraphicsViewBenchmark.pro)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/GraphicsViewBenchmark.qrc (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/GraphicsViewBenchmark.qrc)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/main.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/main.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_001_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_001_58x58.png)bin6598 -> 6598 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_002_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_002_58x58.png)bin6687 -> 6687 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_003_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_003_58x58.png)bin6261 -> 6261 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_004_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_004_58x58.png)bin6783 -> 6783 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_005_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_005_58x58.png)bin6317 -> 6317 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_006_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_006_58x58.png)bin7020 -> 7020 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_007_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_007_58x58.png)bin3706 -> 3706 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_008_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_008_58x58.png)bin6749 -> 6749 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_009_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_009_58x58.png)bin5436 -> 5436 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_010_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_010_58x58.png)bin1454 -> 1454 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_001_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_001_58x58.png)bin2983 -> 2983 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_002_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_002_58x58.png)bin3463 -> 3463 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_003_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_003_58x58.png)bin763 -> 763 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_004_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_004_58x58.png)bin2252 -> 2252 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_005_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_005_58x58.png)bin2451 -> 2451 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_001_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_001_58x58.png)bin6330 -> 6330 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_002_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_002_58x58.png)bin6237 -> 6237 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_003_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_003_58x58.png)bin6192 -> 6192 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_004_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_004_58x58.png)bin7489 -> 7489 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_005_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_005_58x58.png)bin6764 -> 6764 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_006_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_006_58x58.png)bin6218 -> 6218 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_007_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_007_58x58.png)bin6122 -> 6122 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_008_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_008_58x58.png)bin6658 -> 6658 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_009_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_009_58x58.png)bin8293 -> 8293 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_010_58x58.png (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_010_58x58.png)bin4783 -> 4783 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_background_360x640px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_background_360x640px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_background_horisontal_640x360px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_background_horisontal_640x360px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_default_icon_52x52px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_default_icon_52x52px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_list_divider_360x76px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_list_divider_360x76px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_list_highlighter_360x76px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_list_highlighter_360x76px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_status_idle_33x33px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_status_idle_33x33px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_status_offline_33x33px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_status_offline_33x33px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_status_online_33x33px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_status_online_33x33px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_scroll_16x80px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_scroll_16x80px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_scrollbar_7x14px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_scrollbar_7x14px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_status_field_left_14x24px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_status_field_left_14x24px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_status_field_middle_14x24px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_status_field_middle_14x24px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_status_field_right_14x24px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_status_field_right_14x24px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_topbar_356x96px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_topbar_356x96px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_topbar_horisontal_636x96px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_topbar_horisontal_636x96px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_user_default_icon_68x68px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_user_default_icon_68x68px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_user_status_idle_38x38px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_user_status_idle_38x38px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_user_status_offline_38x38px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_user_status_offline_38x38px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_user_status_online_38x38px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_user_status_online_38x38px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/contacts/areacodes.txt (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/contacts/areacodes.txt)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/contacts/firstnamesF.txt (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/contacts/firstnamesF.txt)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/contacts/firstnamesM.txt (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/contacts/firstnamesM.txt)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/contacts/lastnames.txt (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/contacts/lastnames.txt)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_background_360x640px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_background_360x640px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_background_horisontal_640x360px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_background_horisontal_640x360px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_default_icon_53x53px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_default_icon_53x53px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_default_icon_highlight_53x53px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_default_icon_highlight_53x53px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_list_divider_360x76px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_list_divider_360x76px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_list_highlighter_357x80px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_list_highlighter_357x80px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_status_idle_27x47.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_status_idle_27x47.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_status_offline_27x47.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_status_offline_27x47.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_status_online_27x47.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_status_online_27x47.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_scroll_5x80px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_scroll_5x80px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_scrollbar_5x14px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_scrollbar_5x14px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_status_field_left_14x24px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_status_field_left_14x24px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_status_field_middle_10x24px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_status_field_middle_10x24px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_status_field_right_14x24px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_status_field_right_14x24px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_topbar_356x96px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_topbar_356x96px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_topbar_horisontal_636x96px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_topbar_horisontal_636x96px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_user_default_icon_84x68px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_user_default_icon_84x68px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_user_status_idle_24x24px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_user_status_idle_24x24px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_user_status_offline_24x24px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_user_status_offline_24x24px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_user_status_online_24x24px.svg (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_user_status_online_24x24px.svg)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemcontainer.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemcontainer.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemcontainer.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemcontainer.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemview.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemview.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemview.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemview.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractscrollarea.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractscrollarea.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractscrollarea.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractscrollarea.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractviewitem.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractviewitem.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractviewitem.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractviewitem.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/backgrounditem.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/backgrounditem.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/backgrounditem.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/backgrounditem.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/button.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/button.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/button.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/button.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/commandline.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/commandline.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/commandline.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/commandline.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/dummydatagen.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/dummydatagen.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/dummydatagen.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/dummydatagen.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/gvbwidget.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/gvbwidget.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/gvbwidget.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/gvbwidget.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/iconitem.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/iconitem.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/iconitem.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/iconitem.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglist.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglist.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglist.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglist.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglist.pri (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglist.pri)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglistview.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglistview.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglistview.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglistview.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/label.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/label.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/label.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/label.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listitem.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listitem.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listitem.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listitem.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listitemcache.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listitemcache.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listitemcache.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listitemcache.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listitemcontainer.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listitemcontainer.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listitemcontainer.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listitemcontainer.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listmodel.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listmodel.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listmodel.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listmodel.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listwidget.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listwidget.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listwidget.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listwidget.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/mainview.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/mainview.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/mainview.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/mainview.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/menu.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/menu.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/menu.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/menu.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/recycledlistitem.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/recycledlistitem.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/recycledlistitem.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/recycledlistitem.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/resourcemoninterface.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/resourcemoninterface.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/scrollbar.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/scrollbar.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/scrollbar.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/scrollbar.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/scroller.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/scroller.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/scroller.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/scroller.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/scroller_p.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/scroller_p.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/settings.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/settings.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/settings.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/settings.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/simplelist.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/simplelist.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/simplelist.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/simplelist.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/simplelistview.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/simplelistview.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/simplelistview.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/simplelistview.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/theme.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/theme.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/theme.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/theme.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/themeevent.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/themeevent.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/themeevent.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/themeevent.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/topbar.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/topbar.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/topbar.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/topbar.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/webview.cpp (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/webview.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/webview.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/webview.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/webview_p.h (renamed from tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/webview_p.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/functional/functional.pro (renamed from tests/benchmarks/gui/graphicsview/functional/functional.pro)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/graphicsview.pro10
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsanchorlayout/qgraphicsanchorlayout.pro (renamed from tests/benchmarks/gui/graphicsview/qgraphicsanchorlayout/qgraphicsanchorlayout.pro)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp (renamed from tests/benchmarks/gui/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro (renamed from tests/benchmarks/gui/graphicsview/qgraphicsitem/qgraphicsitem.pro)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp234
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicslayout/qgraphicslayout.pro5
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp143
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicslinearlayout/qgraphicslinearlayout.pro5
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp120
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro (renamed from tests/benchmarks/gui/graphicsview/qgraphicsscene/qgraphicsscene.pro)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp (renamed from tests/benchmarks/gui/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/chip.cpp (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/chip.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/chip.debug (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/chip.debug)bin863805 -> 863805 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/chip.h (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/chip.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/chip.pro (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/chip.pro)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/fileprint.png (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/fileprint.png)bin1456 -> 1456 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/images.qrc (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/images.qrc)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/main.cpp (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/main.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/mainwindow.cpp (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/mainwindow.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/mainwindow.h (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/mainwindow.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/qt4logo.png (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/qt4logo.png)bin48333 -> 48333 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/rotateleft.png (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/rotateleft.png)bin1754 -> 1754 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/rotateright.png (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/rotateright.png)bin1732 -> 1732 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/view.cpp (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/view.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/view.h (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/view.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/zoomin.png (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/zoomin.png)bin1622 -> 1622 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/zoomout.png (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/zoomout.png)bin1601 -> 1601 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/moveItems/main.cpp (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/moveItems/main.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/moveItems/moveItems.pro (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/moveItems/moveItems.pro)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/scrolltest/main.cpp (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/scrolltest/main.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/scrolltest/scrolltest.pro (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/scrolltest/scrolltest.pro)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/chip.cpp (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/chip.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/chip.h (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/chip.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/chiptester.cpp (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/chiptester.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/chiptester.h (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/chiptester.h)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/chiptester.pri (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/chiptester.pri)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/images.qrc (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/images.qrc)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/qt4logo.png (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/qt4logo.png)bin48333 -> 48333 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/images/designer.png (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/images/designer.png)bin4205 -> 4205 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/images/wine-big.jpeg (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/images/wine-big.jpeg)bin12249 -> 12249 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/images/wine.jpeg (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/images/wine.jpeg)bin2265 -> 2265 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/qgraphicsview.pro (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/qgraphicsview.pro)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/qgraphicsview.qrc (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/qgraphicsview.qrc)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/random.data (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/random.data)bin800 -> 800 bytes
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp (renamed from tests/benchmarks/gui/graphicsview/qgraphicsview/tst_qgraphicsview.cpp)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicswidget/qgraphicswidget.pro (renamed from tests/benchmarks/gui/graphicsview/qgraphicswidget/qgraphicswidget.pro)0
-rw-r--r--tests/benchmarks/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp (renamed from tests/benchmarks/gui/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp)0
-rw-r--r--tests/benchmarks/widgets/itemviews/itemviews.pro (renamed from tests/benchmarks/gui/itemviews/itemviews.pro)0
-rw-r--r--tests/benchmarks/widgets/itemviews/qheaderview/qheaderview.pro (renamed from tests/benchmarks/gui/itemviews/qheaderview/qheaderview.pro)0
-rw-r--r--tests/benchmarks/widgets/itemviews/qheaderview/qheaderviewbench.cpp (renamed from tests/benchmarks/gui/itemviews/qheaderview/qheaderviewbench.cpp)0
-rw-r--r--tests/benchmarks/widgets/itemviews/qtableview/qtableview.pro (renamed from tests/benchmarks/gui/itemviews/qtableview/qtableview.pro)0
-rw-r--r--tests/benchmarks/widgets/itemviews/qtableview/tst_qtableview.cpp (renamed from tests/benchmarks/gui/itemviews/qtableview/tst_qtableview.cpp)0
-rw-r--r--tests/benchmarks/widgets/kernel/kernel.pro4
-rw-r--r--tests/benchmarks/widgets/kernel/qapplication/main.cpp (renamed from tests/benchmarks/gui/kernel/qapplication/main.cpp)0
-rw-r--r--tests/benchmarks/widgets/kernel/qapplication/qapplication.pro (renamed from tests/benchmarks/gui/kernel/qapplication/qapplication.pro)0
-rw-r--r--tests/benchmarks/widgets/kernel/qwidget/qwidget.pro (renamed from tests/benchmarks/gui/kernel/qwidget/qwidget.pro)0
-rw-r--r--tests/benchmarks/widgets/kernel/qwidget/tst_qwidget.cpp (renamed from tests/benchmarks/gui/kernel/qwidget/tst_qwidget.cpp)0
-rw-r--r--tests/benchmarks/widgets/styles/qstylesheetstyle/main.cpp (renamed from tests/benchmarks/gui/styles/qstylesheetstyle/main.cpp)0
-rw-r--r--tests/benchmarks/widgets/styles/qstylesheetstyle/qstylesheetstyle.pro (renamed from tests/benchmarks/gui/styles/qstylesheetstyle/qstylesheetstyle.pro)0
-rw-r--r--tests/benchmarks/widgets/styles/styles.pro (renamed from tests/benchmarks/gui/styles/styles.pro)0
-rw-r--r--tests/benchmarks/widgets/widgets.pro10
-rw-r--r--tests/manual/cocoa/menurama/main.cpp37
-rw-r--r--tests/manual/cocoa/menurama/mainwindow.ui16
-rw-r--r--tests/manual/cocoa/qmaccocoaviewcontainer/TestMouseMovedNSView.h7
-rw-r--r--tests/manual/cocoa/qmaccocoaviewcontainer/TestMouseMovedNSView.m25
-rw-r--r--tests/manual/cocoa/qmaccocoaviewcontainer/main.mm2
-rw-r--r--tests/manual/cocoa/qt_on_cocoa/main.mm32
-rw-r--r--tests/manual/highdpi/dragwidget.cpp2
-rw-r--r--tests/manual/highdpi/main.cpp93
-rw-r--r--tests/manual/windowchildgeometry/controllerwidget.cpp6
-rw-r--r--tests/manual/windowgeometry/controllerwidget.cpp18
-rwxr-xr-xtests/testserver/apache2/apache2.sh77
-rw-r--r--tests/testserver/apache2/testdata/dav.conf7
-rw-r--r--tests/testserver/apache2/testdata/deflate.conf5
-rw-r--r--tests/testserver/apache2/testdata/main.conf56
-rw-r--r--tests/testserver/apache2/testdata/security.conf51
-rw-r--r--tests/testserver/apache2/testdata/ssl.conf2
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/echo.cgi11
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/get-cookie.cgi5
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/http-delete.cgi22
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/http-unknown-authentication-method.cgi17
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_expires500.cgi12
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/multipart.cgi42
-rwxr-xr-xtests/testserver/apache2/testdata/www/cgi-bin/set-cookie.cgi9
-rw-r--r--tests/testserver/apache2/testdata/www/htdocs/auth-digest/index.html1
-rw-r--r--tests/testserver/apache2/testdata/www/htdocs/digest-authfile1
-rw-r--r--tests/testserver/apache2/testdata/www/htdocs/fluke.gifbin0 -> 27906 bytes
-rw-r--r--tests/testserver/apache2/testdata/www/htdocs/index.html3
-rw-r--r--tests/testserver/apache2/testdata/www/htdocs/protected/.htaccess5
-rwxr-xr-xtests/testserver/apache2/testdata/www/htdocs/protected/cgi-bin/md5sum.cgi6
-rw-r--r--tests/testserver/apache2/testdata/www/htdocs/rfcs-auth/index.html1
-rwxr-xr-xtests/testserver/common/ssl.sh39
-rwxr-xr-xtests/testserver/common/startup.sh57
-rw-r--r--tests/testserver/common/testdata/ssl/private/qt-test-server-key.pem15
-rw-r--r--tests/testserver/common/testdata/ssl/qt-test-server-cert.pem16
-rw-r--r--tests/testserver/common/testdata/system/passwords12
-rwxr-xr-xtests/testserver/danted/danted.sh44
-rw-r--r--tests/testserver/danted/testdata/danted-authenticating.conf19
-rw-r--r--tests/testserver/danted/testdata/danted.conf19
-rw-r--r--tests/testserver/docker-compose.yml83
-rwxr-xr-xtests/testserver/ftp-proxy/ftp-proxy.sh40
-rwxr-xr-xtests/testserver/squid/squid.sh46
-rw-r--r--tests/testserver/squid/testdata/squid-authenticating-ntlm.conf41
-rw-r--r--tests/testserver/squid/testdata/squid.conf46
-rw-r--r--tests/testserver/vsftpd/testdata/ftp/pub/file-not-readable.txt1
-rw-r--r--tests/testserver/vsftpd/testdata/vsftpd.conf112
-rw-r--r--tests/testserver/vsftpd/testdata/vsftpd.user_list20
-rwxr-xr-xtests/testserver/vsftpd/vsftpd.sh66
-rwxr-xr-xutil/edid/qedidvendortable.py9
-rw-r--r--util/gradientgen/.gitignore2
-rwxr-xr-xutil/gradientgen/gradientgen.js133
-rw-r--r--util/gradientgen/package-lock.json183
-rw-r--r--util/gradientgen/package.json13
-rw-r--r--util/gradientgen/tobinaryjson.cpp54
-rw-r--r--util/gradientgen/tobinaryjson.pro4
-rwxr-xr-xutil/local_database/cldr2qlocalexml.py47
-rw-r--r--util/local_database/enumdata.py1576
-rwxr-xr-xutil/local_database/qlocalexml2cpp.py66
-rw-r--r--util/unicode/main.cpp8
-rwxr-xr-xutil/x86simdgen/generate.pl199
-rw-r--r--util/x86simdgen/simd.txt37
3552 files changed, 356673 insertions, 146991 deletions
diff --git a/.qmake.conf b/.qmake.conf
index afdc0cb413..5df08093cd 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.11.2
+MODULE_VERSION = 5.12.0
diff --git a/LGPL_EXCEPTION.txt b/LGPL_EXCEPTION.txt
deleted file mode 100644
index 5cdacb9a4e..0000000000
--- a/LGPL_EXCEPTION.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-The Qt Company Qt LGPL Exception version 1.1
-
-As an additional permission to the GNU Lesser General Public License version
-2.1, the object code form of a "work that uses the Library" may incorporate
-material from a header file that is part of the Library. You may distribute
-such object code under terms of your choice, provided that:
- (i) the header files of the Library have not been modified; and
- (ii) the incorporated material is limited to numerical parameters, data
- structure layouts, accessors, macros, inline functions and
- templates; and
- (iii) you comply with the terms of Section 6 of the GNU Lesser General
- Public License version 2.1.
-
-Moreover, you may apply this exception to a modified version of the Library,
-provided that such modification does not involve copying material from the
-Library into the modified Library's header files unless such material is
-limited to (i) numerical parameters; (ii) data structure layouts;
-(iii) accessors; and (iv) small macros, templates and inline functions of
-five lines or less in length.
-
-Furthermore, you are not required to apply this additional permission to a
-modified version of the Library.
diff --git a/config.tests/arch/arch.cpp b/config.tests/arch/arch.cpp
index bb3efec177..2ccfe127b5 100644
--- a/config.tests/arch/arch.cpp
+++ b/config.tests/arch/arch.cpp
@@ -80,19 +80,19 @@ const char msg2[] = "==Qt=magic=Qt== Sub-architecture:"
" avx2"
#endif
#ifdef __AVX512F__
-// AVX512 Foundation, Intel Xeon Phi codename "Knights Landing" and Intel Xeon codename "Skylake"
+// AVX512 Foundation, Intel Xeon Scalable ("Skylake" server), some Intel Core 7th generation ("Skylake")
" avx512f"
#endif
#ifdef __AVX512CD__
-// AVX512 Conflict Detection, Intel Xeon Phi codename "Knights Landing" and Intel Xeon codename "Skylake"
+// AVX512 Conflict Detection, Intel Xeon Scalable ("Skylake" server), some Intel Core 7th generation ("Skylake")
" avx512cd"
#endif
#ifdef __AVX512DQ__
-// AVX512 Double & Quadword, Intel Xeon processor codename "Skylake"
+// AVX512 Double & Quadword, Intel Xeon Scalable ("Skylake" server), some Intel Core 7th generation ("Skylake")
" avx512dq"
#endif
#ifdef __AVX512BW__
-// AVX512 Byte & Word, Intel Xeon processor codename "Skylake"
+// AVX512 Byte & Word, Intel Xeon Scalable ("Skylake" server), some Intel Core 7th generation ("Skylake")
" avx512bw"
#endif
#ifdef __AVX512ER__
@@ -104,7 +104,7 @@ const char msg2[] = "==Qt=magic=Qt== Sub-architecture:"
" avx512pf"
#endif
#ifdef __AVX512VL__
-// AVX512 Vector Length, Intel Xeon processor codename "Skylake"
+// AVX512 Vector Length, Intel Xeon Scalable ("Skylake" server), some Intel Core 7th generation ("Skylake")
" avx512vl"
#endif
#ifdef __AVX512IFMA__
@@ -115,6 +115,22 @@ const char msg2[] = "==Qt=magic=Qt== Sub-architecture:"
// AVX512 Vector Byte Manipulation Instructions, Intel processor codename "Cannonlake"
" avx512vbmi"
#endif
+#ifdef __AVX512VBMI2__
+// AVX512 Vector Byte Manipulation Instructions #2, Intel processor codename "Ice Lake"
+" avx512vbmi2"
+#endif
+#ifdef __AVX512VPOPCNTDQ__
+// AVX512 Vector Population Count Double & Quad, Future Intel Xeon Phi processor codename "Knights Mill", Intel processor codename "Ice Lake"
+" avx512vpopcntdq"
+#endif
+#ifdef __AVX5124FMAPS__
+// AVX512 4-iteration Fused Multiply Accumulation Packed Single, Future Intel Xeon Phi processor codename "Knights Mill"
+" avx5124fmaps"
+#endif
+#ifdef __AVX5124VNNIW__
+// AVX512 4-iteration Vector Neural Network Instructions Word, Future Intel Xeon Phi processor codename "Knights Mill"
+" avx5124vnniw"
+#endif
#ifdef __BMI__
// Bit Manipulation Instructions 1, Intel Core 4th Generation ("Haswell"), AMD "Bulldozer 2"
" bmi"
@@ -145,6 +161,14 @@ const char msg2[] = "==Qt=magic=Qt== Sub-architecture:"
// rdfsgsbase, wrfsgsbase, Intel Core 3rd Generation ("Ivy Bridge")
" fsgsbase"
#endif
+#ifdef __GFNI__
+// Galois Field new instructions, Intel processor codename "Ice Lake"
+" gfni"
+#endif
+#ifdef __IBT__
+// Indirect Branch Tracking, Intel processor TBA
+" ibt"
+#endif
#ifdef __LWP__
// LWP instructions, AMD "Bulldozer"
" lwp"
@@ -186,6 +210,10 @@ const char msg2[] = "==Qt=magic=Qt== Sub-architecture:"
// Prefetch data for writing, Intel Core 5th Generation ("Broadwell")
" prfchw"
#endif
+#ifdef __RDPID__
+// Read Processor ID, Intel processors codename "Ice Lake" and "Goldmont Plus"
+" rdpid"
+#endif
#ifdef __RDRND__
// Random number generator, Intel Core 3rd Generation ("Ivy Bridge")
" rdrnd"
@@ -199,9 +227,13 @@ const char msg2[] = "==Qt=magic=Qt== Sub-architecture:"
" rtm"
#endif
#ifdef __SHA__
-// SHA-1 and SHA-256 instructions, Intel processor TBA
+// SHA-1 and SHA-256 instructions, Intel processors codename "Cannon Lake" and "Goldmont"
" sha"
#endif
+#ifdef __SHSTK__
+// Shadow stack, Intel processor TBA
+" shstk"
+#endif
#if defined(__SSE__) || (defined(_M_IX86_FP) && _M_IX86_FP >= 1) || defined(_M_X64)
// Streaming SIMD Extensions, Intel Pentium III, AMD Athlon
" sse"
diff --git a/config.tests/avx512/avx512.cpp b/config.tests/avx512/avx512.cpp
index 29e88ebf15..4d47db8463 100644
--- a/config.tests/avx512/avx512.cpp
+++ b/config.tests/avx512/avx512.cpp
@@ -65,6 +65,10 @@ int main(int, char**argv)
d = _mm512_loadu_pd((double *)argv + 64);
f = _mm512_loadu_ps((float *)argv + 128);
+ // some intrinsic that GCC forgot until GCC 8
+ i = _mm512_maskz_set1_epi32(m, '?');
+ _mm512_mask_cvtepi32_storeu_epi8(argv, m, i);
+
#ifdef WANT_AVX512ER
/* AVX512 Exponential and Reciprocal */
f = _mm512_exp2a23_round_ps(f, 8);
@@ -84,6 +88,7 @@ int main(int, char**argv)
#ifdef WANT_AVX512BW
/* AVX512 Byte and Word support */
i = _mm512_mask_loadu_epi8(i, m, argv - 8);
+ _mm512_mask_cvtepi16_storeu_epi8(argv + 8, m, i);
#endif
#ifdef WANT_AVX512VL
/* AVX512 Vector Length */
diff --git a/config_help.txt b/config_help.txt
index f90d4439cd..5b32eb183f 100644
--- a/config_help.txt
+++ b/config_help.txt
@@ -98,6 +98,9 @@ Build options:
-gdb-index ........... Index the debug info to speed up GDB
[no; auto if -developer-build with debug info]
-strip ............... Strip release binaries of unneeded symbols [yes]
+ -gc-binaries ......... Place each function or data item into its own section
+ and enable linker garbage collection of unused
+ sections. [auto for static builds, otherwise no]
-force-asserts ....... Enable Q_ASSERT even in release builds [no]
-developer-build ..... Compile and link Qt for developing Qt itself
(exports for auto-tests, extra checks, etc.) [no]
@@ -298,7 +301,7 @@ Gui, printing, widget options:
-libinput .......... Enable libinput support [auto]
-mtdev ............. Enable mtdev support [auto]
-tslib ............. Enable tslib support [auto]
- -xinput2 ........... Enable XInput2 support [auto]
+ -xcb-xinput ........ Enable XInput2 support [auto]
-xkbcommon-x11 ..... Select xkbcommon used in combination with xcb
[system/qt/no]
-xkbcommon-evdev ... Enable X-less xkbcommon in combination with libinput
diff --git a/configure b/configure
index 2830a1b189..ef7bad1bfc 100755
--- a/configure
+++ b/configure
@@ -771,7 +771,7 @@ setBootstrapVariable()
echo "RM_RF = rm -rf" >> "$mkfile"
case `basename "$PLATFORM"` in
- win32-g++*)
+ win32-*g++*)
cat "$in_mkfile.win32" >> "$mkfile"
;;
*)
diff --git a/configure.json b/configure.json
index 2dc79137e8..522bd34e9b 100644
--- a/configure.json
+++ b/configure.json
@@ -11,6 +11,7 @@
"src/corelib",
"src/network",
"src/gui",
+ "src/sql",
"src/xml",
"src/widgets",
"src/printsupport",
@@ -79,6 +80,7 @@
"force-debug-info": { "type": "boolean", "name": "force_debug_info" },
"force-pkg-config": { "type": "void", "name": "pkg-config" },
"framework": "boolean",
+ "gc-binaries": { "type": "boolean", "name": "gc_binaries" },
"gdb-index": { "type": "boolean", "name": "gdb_index" },
"gcc-sysroot": "boolean",
"gcov": "boolean",
@@ -159,21 +161,16 @@
},
"sources": [
{ "libs": "-lzdll", "condition": "config.msvc" },
- { "libs": "-lz", "condition": "!config.msvc" }
+ { "libs": "-lzlib", "condition": "config.msvc" },
+ { "libs": "-lz", "condition": "!config.msvc" },
+ { "libs": "-s USE_ZLIB=1", "condition": "config.wasm" }
]
},
"dbus": {
"label": "D-Bus >= 1.2",
"test": {
"include": "dbus/dbus.h",
- "main": "(void) dbus_bus_get_private(DBUS_BUS_SYSTEM, (DBusError *)NULL);",
- "qmake": [
- "CONFIG += build_all",
- "CONFIG(debug, debug|release): \\",
- " LIBS += $$LIBS_DEBUG",
- "else: \\",
- " LIBS += $$LIBS_RELEASE"
- ]
+ "main": "(void) dbus_bus_get_private(DBUS_BUS_SYSTEM, (DBusError *)NULL);"
},
"sources": [
{ "type": "pkgConfig", "args": "dbus-1 >= 1.2" },
@@ -259,6 +256,36 @@
"type": "compile",
"test": "stl"
},
+ "c99": {
+ "label": "C99 support",
+ "type": "compile",
+ "test": {
+ "head": [
+ "#if __STDC_VERSION__ >= 199901L",
+ "// Compiler claims to support C99, trust it",
+ "#else",
+ "# error __STDC_VERSION__ must be >= 199901L",
+ "#endif"
+ ],
+ "lang": "c",
+ "qmake": "CONFIG += c99"
+ }
+ },
+ "c11": {
+ "label": "C11 support",
+ "type": "compile",
+ "test": {
+ "head": [
+ "#if __STDC_VERSION__ >= 201112L",
+ "// Compiler claims to support C11, trust it",
+ "#else",
+ "# error __STDC_VERSION__ must be >= 201112L",
+ "#endif"
+ ],
+ "lang": "c",
+ "qmake": "CONFIG += c11"
+ }
+ },
"c++14": {
"label": "C++14 support",
"type": "compile",
@@ -372,6 +399,17 @@
]
}
},
+ "gc_binaries": {
+ "label": "support for split sections and linker garbage collection",
+ "type": "compile",
+ "test": {
+ "qmake": [
+ "isEmpty(QMAKE_CFLAGS_SPLIT_SECTIONS): error(\"Nope\")",
+ "isEmpty(QMAKE_CXXFLAGS_SPLIT_SECTIONS): error(\"Nope\")",
+ "isEmpty(QMAKE_LFLAGS_GCSECTIONS): error(\"Nope\")"
+ ]
+ }
+ },
"sse2": {
"label": "SSE2 instructions",
"type": "x86Simd"
@@ -544,7 +582,7 @@
"shared": {
"label": "Building shared libraries",
"autoDetect": "!config.uikit",
- "condition": "!config.integrity",
+ "condition": "!config.integrity && !config.wasm",
"output": [
"shared",
"publicFeature",
@@ -568,6 +606,10 @@
"compiler-flags": {
"output": [ "compilerFlags" ]
},
+ "gc_binaries": {
+ "condition": "!features.shared && tests.gc_binaries",
+ "output": [ "privateFeature" ]
+ },
"gcc-sysroot": {
"output": [ "gccSysroot" ],
"condition": "input.sysroot != ''"
@@ -578,7 +620,7 @@
},
"use_gold_linker": {
"label": "Using gold linker",
- "condition": "!config.win32 && !config.integrity && tests.use_gold_linker",
+ "condition": "!config.win32 && !config.integrity && !config.wasm && tests.use_gold_linker",
"output": [ "privateConfig", "useGoldLinker" ]
},
"optimize_debug": {
@@ -688,6 +730,7 @@
"headersclean": {
"label": "Check for clean headers",
"autoDetect": "features.developer-build",
+ "condition": "!config.wasm",
"output": [ "privateConfig" ]
},
"framework": {
@@ -793,9 +836,22 @@
"condition": "features.c++14 && tests.c++1z",
"output": [ "publicFeature", "publicQtConfig" ]
},
+ "c89": {
+ "label": "C89"
+ },
+ "c99": {
+ "label": "C99",
+ "condition": "tests.c99",
+ "output": [ "publicFeature" ]
+ },
+ "c11": {
+ "label": "C11",
+ "condition": "features.c99 && tests.c11",
+ "output": [ "publicFeature" ]
+ },
"precompile_header": {
"label": "Using precompiled headers",
- "condition": "config.msvc || tests.precompile_header",
+ "condition": "tests.precompile_header",
"output": [
"privateConfig",
{ "type": "varRemove", "negative": true, "name": "CONFIG", "value": "'precompile_header'" }
@@ -1059,10 +1115,18 @@
"condition": "libs.zlib",
"output": [ "privateFeature" ]
},
+ "thread": {
+ "label": "Thread support",
+ "purpose": "Provides QThread and related classes.",
+ "section": "Kernel",
+ "condition": "!config.wasm",
+ "output": [ "publicFeature" ]
+ },
"future": {
"label": "QFuture",
"purpose": "Provides QFuture and related classes.",
"section": "Kernel",
+ "condition": "features.thread",
"output": [ "publicFeature" ]
},
"concurrent": {
@@ -1075,6 +1139,7 @@
"dbus": {
"label": "Qt D-Bus",
"autoDetect": "!config.uikit && !config.android && !config.winrt",
+ "condition": "features.thread",
"output": [ "privateFeature", "feature" ]
},
"dbus-linked": {
@@ -1110,6 +1175,7 @@
},
"sql": {
"label": "Qt Sql",
+ "condition": "features.thread",
"output": [ "privateFeature" ]
},
"testlib": {
@@ -1254,6 +1320,11 @@ Configure with '-qreal float' to create a build that is binary-compatible with 5
},
"shared",
{
+ "message": "Using C standard",
+ "type": "firstAvailableFeature",
+ "args": "c11 c99 c89"
+ },
+ {
"message": "Using C++ standard",
"type": "firstAvailableFeature",
"args": "c++1z c++14 c++11"
diff --git a/configure.pri b/configure.pri
index 6e7f6b76a4..64ed6b9ed8 100644
--- a/configure.pri
+++ b/configure.pri
@@ -68,7 +68,7 @@ defineReplace(qtConfFunc_crossCompile) {
}
defineReplace(qtConfFunc_licenseCheck) {
- exists($$QT_SOURCE_TREE/LICENSE.LGPL3)|exists($$QT_SOURCE_TREE/LICENSE.GPL2): \
+ exists($$QT_SOURCE_TREE/LICENSE.LGPL3)|exists($$QT_SOURCE_TREE/LICENSE.GPL2)|exists($$QT_SOURCE_TREE/LICENSE.GPL3): \
hasOpenSource = true
else: \
hasOpenSource = false
@@ -187,8 +187,13 @@ defineReplace(qtConfFunc_licenseCheck) {
theLicense = "GNU Lesser General Public License (LGPL) version 3"
showWhat = "Type 'L' to view the GNU Lesser General Public License version 3 (LGPLv3)."
gpl2Ok = false
+ gpl3Ok = false
winrt {
notTheLicense = "Note: GPL version 2 is not available on WinRT."
+ } else: wasm {
+ gpl3Ok = true
+ theLicense = "GNU General Public License (GPL) version 3"
+ showWhat = "Type 'G' to view the GNU General Public License version 3 (GPLv3)."
} else: $$qtConfEvaluate("features.android-style-assets") {
notTheLicense = "Note: GPL version 2 is not available due to using Android style assets."
} else {
@@ -230,6 +235,8 @@ defineReplace(qtConfFunc_licenseCheck) {
licenseFile = $$QT_SOURCE_TREE/LICENSE.LGPL3
} else: equals(commercial, no):equals(val, g):$$gpl2Ok {
licenseFile = $$QT_SOURCE_TREE/LICENSE.GPL2
+ } else: equals(commercial, no):equals(val, g):$$gpl3Ok {
+ licenseFile = $$QT_SOURCE_TREE/LICENSE.GPL3
} else {
next()
}
@@ -251,6 +258,11 @@ defineTest(qtConfTest_machineTuple) {
return(true)
}
+defineTest(qtConfTest_verifySpec) {
+ qtConfTest_compile($$1): return(true)
+ qtConfFatalError("Cannot compile a minimal program. The toolchain or QMakeSpec is broken.", log)
+}
+
defineTest(qtConfTest_architecture) {
!qtConfTest_compile($${1}): \
error("Could not determine $$eval($${1}.label). See config.log for details.")
@@ -263,6 +275,8 @@ defineTest(qtConfTest_architecture) {
content = $$cat($$test_out_dir/arch.exe, blob)
else: android:exists($$test_out_dir/libarch.so): \
content = $$cat($$test_out_dir/libarch.so, blob)
+ else: wasm:exists($$test_out_dir/arch.wasm): \
+ content = $$cat($$test_out_dir/arch.wasm, blob)
else: \
error("$$eval($${1}.label) detection binary not found.")
@@ -412,7 +426,7 @@ defineTest(qtConfTest_x86SimdAlways) {
qtConfCheckFeature($$f)
equals($${fpfx}.$${f}.available, true): configs += $$f
}
- $${1}.literal_args = $$system_quote(SIMD=$$join(configs, " "))
+ $${1}.literal_args = SIMD=$$join(configs, " ")
qtConfTest_compile($${1})
}
@@ -590,6 +604,9 @@ defineTest(qtConfOutput_prepareOptions) {
target_arch = armeabi-v7a
platform = $$eval(config.input.android-ndk-platform)
+ isEmpty(platform): equals(target_arch, arm64-v8a): \
+ platform = android-21
+
isEmpty(platform): \
platform = android-16 ### the windows configure disagrees ...
@@ -1141,6 +1158,12 @@ defineReplace(qtConfOutputPostProcess_publicPro) {
"QT_ICC_MINOR_VERSION = $$format_number($$replace(QMAKE_ICC_VER, "(..)(..)", "\\2"))" \
"QT_ICC_PATCH_VERSION = $$QMAKE_ICC_UPDATE_VER"
}
+ !isEmpty(QMAKE_GHS_VERSION) {
+ output += \
+ "QT_GHS_MAJOR_VERSION = $$replace(QMAKE_GHS_VERSION, "(.*)(.)(.)", "\\1")" \
+ "QT_GHS_MINOR_VERSION = $$replace(QMAKE_GHS_VERSION, "(.*)(.)(.)", "\\2")" \
+ "QT_GHS_PATCH_VERSION = $$replace(QMAKE_GHS_VERSION, "(.*)(.)(.)", "\\3")"
+ }
output += "QT_EDITION = $$config.input.qt_edition"
!contains(config.input.qt_edition, "(OpenSource|Preview)") {
@@ -1198,13 +1221,43 @@ defineReplace(qtConfReportArch) {
return("$$arch, CPU features: $$subarch")
}
+defineReplace(qtConfReportCompiler) {
+ clang_cl: {
+ return("clang-cl $${QMAKE_CLANG_MAJOR_VERSION}.$${QMAKE_CLANG_MINOR_VERSION}.$${QMAKE_CLANG_PATCH_VERSION}")
+ } else: clang {
+ !isEmpty(QMAKE_APPLE_CLANG_MAJOR_VERSION) {
+ return("clang (Apple) $${QMAKE_APPLE_CLANG_MAJOR_VERSION}.$${QMAKE_APPLE_CLANG_MINOR_VERSION}.$${QMAKE_APPLE_CLANG_PATCH_VERSION}")
+ } else {
+ return("clang $${QMAKE_CLANG_MAJOR_VERSION}.$${QMAKE_CLANG_MINOR_VERSION}.$${QMAKE_CLANG_PATCH_VERSION}")
+ }
+ } else: intel_icc {
+ return("intel_icc $$QMAKE_ICC_VER")
+ } else: intel_icl {
+ return("intel_icl $$QMAKE_ICC_VER")
+ } else: rim_qcc {
+ return("rim_qcc $${QMAKE_GCC_MAJOR_VERSION}.$${QMAKE_GCC_MINOR_VERSION}.$${QMAKE_GCC_PATCH_VERSION}")
+ } else: gcc {
+ return("gcc $${QMAKE_GCC_MAJOR_VERSION}.$${QMAKE_GCC_MINOR_VERSION}.$${QMAKE_GCC_PATCH_VERSION}")
+ } else: msvc {
+ return("msvc $$QMAKE_MSC_FULL_VER")
+ } else: ghs {
+ return("ghs $$QMAKE_GHS_VERSION")
+ } else {
+ return("unknown ($$QMAKE_COMPILER)")
+ }
+}
+
+
defineTest(qtConfReport_buildTypeAndConfig) {
!$$qtConfEvaluate("features.cross_compile") {
qtConfAddReport("Build type: $$[QMAKE_SPEC] ($$qtConfReportArch(architecture))")
+ qtConfAddReport("Compiler: $$qtConfReportCompiler()")
} else {
qtConfAddReport("Building on: $$[QMAKE_SPEC] ($$qtConfReportArch(host_architecture))")
qtConfAddReport("Building for: $$[QMAKE_XSPEC] ($$qtConfReportArch(architecture))")
+ qtConfAddReport("Target compiler: $$qtConfReportCompiler()")
}
+
qtConfAddReport()
qtConfAddReport("Configuration: $$eval($${currentConfig}.output.privatePro.append.CONFIG) $$eval($${currentConfig}.output.publicPro.append.QT_CONFIG)")
qtConfAddReport()
diff --git a/doc/global/html-header-online.qdocconf b/doc/global/html-header-online.qdocconf
index 02b7375d32..d674e76bb0 100644
--- a/doc/global/html-header-online.qdocconf
+++ b/doc/global/html-header-online.qdocconf
@@ -1,6 +1,7 @@
# HTML Header with qt.io branding and online links
HTML.stylesheets = template/style/online.css \
+ template/style/cookie-confirm.css \
template/style/gsc.css \
template/style/list_arrow.png \
template/style/list_expand.png \
@@ -14,6 +15,7 @@ HTML.stylesheets = template/style/online.css \
#for including files into the qch file. Relative to the outputdir of a QDoc build.
qhp.extraFiles += style/online.css \
+ style/cookie-confirm.css \
style/gsc.css \
style/list_arrow.png \
style/list_expand.png \
@@ -27,11 +29,13 @@ qhp.extraFiles += style/online.css \
HTML.headerstyles = \
" <link rel=\"stylesheet\" type=\"text/css\" href=\"style/online.css\" />\n" \
- " <link rel=\"shortcut icon\" href=\"//d3hp9ud7yvwzy0.cloudfront.net/wp-content/themes/oneqt/images/favicon.ico.gzip\" />\n"
+ " <link rel=\"shortcut icon\" href=\"//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/images/favicon.ico.gzip\" />\n"
HTML.headerscripts = \
" <script type=\"text/javascript\"> wpThemeFolder = \'http://qt.io/wp-content/themes/oneqt\'; </script>\n" \
- " <script type=\"text/javascript\" src=\"//d3hp9ud7yvwzy0.cloudfront.net/wp-content/themes/oneqt/js/combo.js.gzip\"></script>\n" \
+ " <script type=\"text/javascript\" src=\"//d33sqmjvzgs8hq.cloudfront.net/wp-includes/js/jquery/jquery.js.gzip\"></script>\n" \
+ " <script type=\"text/javascript\" src=\"//d33sqmjvzgs8hq.cloudfront.net/wp-includes/js/jquery/jquery-migrate.min.js.gzip\"></script>\n" \
+ " <script type=\"text/javascript\" src=\"//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/js/combo.js.gzip\"></script>\n" \
" <script type=\"text/javascript\" src=\"scripts/main.js\"></script>\n" \
" <script type=\"text/javascript\" src=\"scripts/extras.js\"></script>\n" \
" <script type=\"text/javascript\">\n" \
@@ -61,58 +65,25 @@ HTML.endheader = \
# minimal header
HTML.postheader = \
"<body>\n" \
- "<div class=\"header\" id=\"header\">\n" \
- "<header id=\"navbar\" class=\"\">\n" \
- " <div class=\"cookies_yum\">\n" \
- " <div>\n" \
- " <img src=\"//d3hp9ud7yvwzy0.cloudfront.net/wp-content/themes/oneqt/assets/images/cookie_small.png\" align=\"left\">\n" \
- " <p class=\"close_button\">\n" \
- " We bake cookies in your browser for a better experience. Using this site means that you consent. <a href=\"//qt.io/terms-conditions/\">Read More</a>\n" \
- " </p>\n" \
- " <a class=\"close\"></a>\n" \
- " </div>\n" \
+ "<div class=\"header\" id=\"tmpl_header\">\n" \
+ "<header class=\"\" id=\"navbar\"><div id=\"cookie-confirmation\" style=\"display:none\"><div id=\"cookie-confirmation-inner\"><p>We bake cookies in your browser for a better experience. Using this site means that you consent.\n" \
+ "<a href=\"https://www1.qt.io/terms-conditions/ \">Read more</a></p><div id=\"cookie-confirmation-buttons-area\"><a href=\"#\" id=\"confirmation-button\">Continue »</a>\n" \
+ "</div></div>\n" \
+ "<script>\n" \
+ " $('#confirmation-button').on('click', function() { $('#cookie-confirmation').fadeOut(); createCookie(\"cookies_nom\", \"yum\", 180); });\n" \
+ " if (!(readCookie('cookies_nom') == 'yum')) { $('#cookie-confirmation').fadeIn(); }\n" \
+ "</script>\n" \
+ "</div>\n" \
+ "<div class=\"container\">\n" \
+ " <div class=\"navbar-header cf\">\n" \
+ " <div id=\"mm-wrap\">\n" \
+ " <ul id=\"mm-helper\" class=\"mm-menu\" data-event=\"hover_intent\" data-effect=\"fade\" data-effect-speed=\"200\" data-panel-width=\"#navbar\" data-panel-inner-width=\"1280px\" data-second-click=\"go\" data-document-click=\"collapse\" data-vertical-behaviour=\"accordion\" data-breakpoint=\"0\">\n" \
+ " <li class=\"mm-item\"><a class=\"mm-link\" href=\"http://blog.qt.io/\" tabindex=\"0\">Blog</a></li>\n" \
+ " <li class=\"mm-item\"><a class=\"mm-link\" href=\"https://www.qt.io/contact-us/\" tabindex=\"0\">Contact Us</a></li>\n" \
+ " <li class=\"mm-item\"><a title=\"Qt Account\" class=\"mm-link\" href=\"https://account.qt.io/\" tabindex=\"0\"></a></li>\n" \
+ " </ul>\n" \
" </div>\n" \
- " <div class=\"container\">\n" \
- " <div class=\"navbar-header clearfix\">\n" \
- " <a href=\"#\" class=\"navbar-toggle\">\n" \
- " <figure>\n" \
- " <span class=\"line\"></span>\n" \
- " </figure>\n" \
- " <span>Menu</span>\n" \
- " </a>\n" \
- " <ul id=\"menuextras\">\n" \
- " <li>\n" \
- " <a href=\"//qt.io/partners/\" data-icon=\"\">\n" \
- " <span>Partners</span>\n" \
- " </a>\n" \
- " </li>\n" \
- " <li>\n" \
- " <a target=\"_blank\" href=\"http://blog.qt.io/\" data-icon=\"\">\n" \
- " <span>Blog</span>\n" \
- " </a>\n" \
- " </li>\n" \
- " <li class=\"sign-in\">\n" \
- " <a data-icon=\"\" class=\"signin\" href=\"https://account.qt.io/login\"><span>Sign in</span></a>\n" \
- " </li>\n" \
- " </ul>\n" \
- " <a href=\"http://qt.io/\" class=\"navbar-oneQt retina\" data-icon=\"\">\n" \
- " </a>\n" \
- " <nav class=\"navbar-menu clearfix\" role=\"navigation\">\n" \
- " <ul id=\"mainmenu\" class=\"menu\"><li id=\"menu-item-18\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-18\"><a href=\"http://qt.io/download/\">Download</a></li>\n" \
- "<li id=\"menu-item-12207\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-12207\"><a href=\"http://www.qt.io/qt-for-device-creation/\">Device Creation</a></li>\n" \
- "<li id=\"menu-item-12208\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-12208\"><a href=\"http://www.qt.io/application-development/\">Application Development</a></li>\n" \
- "<li id=\"menu-item-1381\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1381\"><a href=\"http://www.qt.io/services/\">Services</a></li>\n" \
- "<li id=\"menu-item-20\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-20\"><a href=\"http://www.qt.io/developers/\">Developers</a></li>\n" \
- "</ul> <ul class=\"menuextraslanguages\">\n" \
- " <li class=\"active dark\"><a class=\"dark\" href=\"http://qt.io/support/\">EN</a></li><li class=\"dark\"><a class=\"dark\" href=\"http://qt.io/ru/\">RU</a></li><li class=\"dark\"><a class=\"dark\" href=\"http://qt.io/zh-hans/\">ZH</a></li></ul>\n" \
- " </nav>\n" \
- " </div>\n" \
- " </div>\n" \
- "<div class=\"big_bar account\" style=\"\">\n" \
- " <div class=\"container\">\n" \
- " <h1><!-- mclude oneqt_no_cache_bMrsJxAh /wp-content/themes/oneqt/php_login_info_bottom_header.php --><!-- /mclude oneqt_no_cache_bMrsJxAh -->\n" \
- " <div class=\"col-1 right big_bar_button account\" style=\"margin-top:5px !important;\"></div>\n" \
- " </h1>\n" \
+ " <a class=\"navbar-oneQt retina\" data-icon=\"\" href=\"https://www.qt.io/\"></a>\n" \
" </div>\n" \
"</div>\n" \
"</header>\n" \
diff --git a/doc/global/macros.qdocconf b/doc/global/macros.qdocconf
index dbf8c5cc6a..704b1da277 100644
--- a/doc/global/macros.qdocconf
+++ b/doc/global/macros.qdocconf
@@ -19,6 +19,7 @@ macro.QD = "\\e{Qt Designer}"
macro.QL = "\\e{Qt Linguist}"
macro.QQV = "\\e{Qt QML Viewer}"
macro.QtVersion = "$QT_VERSION"
+macro.QtVer = "$QT_VER"
macro.param = "\\e"
macro.raisedaster.HTML = "<sup>*</sup>"
macro.rarrow.HTML = "&rarr;"
@@ -40,6 +41,10 @@ macro.endfloat.HTML = "</div>"
macro.clearfloat.HTML = "<br style=\"clear: both\" />"
macro.emptyspan.HTML = "<span></span>"
+# Expands to the minor version based on the QT_VER environment variable
+macro.QtMinorVersion = "$QT_VER"
+macro.QtMinorVersion.match = "\\d+\\.(\\d+)"
+
# Embed YouTube content by video ID - Example: \youtube dQw4w9WgXcQ
# Also requires a <ID>.jpg thumbnail for offline docs. In .qdocconf, add:
#
diff --git a/doc/global/template/style/cookie-confirm.css b/doc/global/template/style/cookie-confirm.css
new file mode 100644
index 0000000000..51e0e4a315
--- /dev/null
+++ b/doc/global/template/style/cookie-confirm.css
@@ -0,0 +1,219 @@
+body div#cookie-confirmation,
+body div#cookie-confirmation.can-use-gradients {
+ background:#222840 !important;
+ position:fixed !important;
+ box-shadow:0 0 10px #222840 !important;
+ border-bottom:none;
+ top:auto;
+ bottom:0;
+}
+body div#cookie-confirmation div#cookie-confirmation-inner,
+body div#cookie-confirmation.can-use-gradients div#cookie-confirmation-inner {
+ padding:0 30px !important;
+ overflow:hidden;
+ display:-ms-flexbox;
+ display:flex;
+ -ms-flex-direction:row;
+ flex-direction:row;
+ -ms-flex-align:center;
+ align-items:center;
+ height:60px;
+}
+
+body div#cookie-confirmation div#cookie-confirmation-inner p,
+body div#cookie-confirmation.can-use-gradients div#cookie-confirmation-inner p {
+ text-shadow:none !important;
+ font-family:"Titillium Web" !important;
+ font-size:inherit !important;
+ line-height:inherit !important;
+ float:left;
+ margin:0!important;
+}
+
+body div#cookie-confirmation div#cookie-confirmation-inner p a,
+body div#cookie-confirmation.can-use-gradients div#cookie-confirmation-inner p a {
+ font-family:inherit !important;
+ color:#41cd52 !important;
+ font-size:inherit !important;
+}
+body div#cookie-confirmation div#cookie-confirmation-inner #cookie-confirmation-buttons-area,
+body div#cookie-confirmation.can-use-gradients div#cookie-confirmation-inner #cookie-confirmation-buttons-area {
+ display:-ms-flexbox;
+ display:flex;
+ float:left;
+ margin-left:50px;
+}
+
+body div#cookie-confirmation div#cookie-confirmation-inner #cookie-confirmation-buttons-area a#confirmation-button,
+body div#cookie-confirmation.can-use-gradients div#cookie-confirmation-inner #cookie-confirmation-buttons-area a#confirmation-button {
+ text-shadow:none !important;
+ border-radius:0;
+ border:0 !important;
+ box-shadow:none;
+ line-height:32px !important;
+ height:32px !important;
+ font-size:16px !important;
+ font-weight:400 !important;
+ color:#fff !important;
+ font-family:"Titillium Web" !important;
+ display:inline-block;
+ padding:0 15px !important;
+ position:relative;
+ background:#41cd52 !important;
+ transition:all .2s ease-in-out;
+}
+body div#cookie-confirmation div#cookie-confirmation-inner #cookie-confirmation-buttons-area a#confirmation-button:hover,
+body div#cookie-confirmation.can-use-gradients div#cookie-confirmation-inner #cookie-confirmation-buttons-area a#confirmation-button:hover{
+ background:#17a81a !important;
+}
+
+body div#cookie-confirmation div#cookie-confirmation-inner #cookie-confirmation-buttons-area a#confirmation-button:after,
+body div#cookie-confirmation div#cookie-confirmation-inner #cookie-confirmation-buttons-area a#confirmation-button:before,
+body div#cookie-confirmation.can-use-gradients div#cookie-confirmation-inner #cookie-confirmation-buttons-area a#confirmation-button:after,
+body div#cookie-confirmation.can-use-gradients div#cookie-confirmation-inner #cookie-confirmation-buttons-area a#confirmation-button:before {
+ content:'';
+ width:20px;
+ height:20px;
+ background:#222840;
+ position:absolute;
+}
+
+body div#cookie-confirmation div#cookie-confirmation-inner #cookie-confirmation-buttons-area a#confirmation-button:before,
+body div#cookie-confirmation.can-use-gradients div#cookie-confirmation-inner #cookie-confirmation-buttons-area a#confirmation-button:before {
+ -ms-transform:rotate(45deg);
+ transform:rotate(45deg);
+ top:-12px;
+ left:-13px;
+}
+body div#cookie-confirmation div#cookie-confirmation-inner #cookie-confirmation-buttons-area a#confirmation-button:after,
+body div#cookie-confirmation.can-use-gradients div#cookie-confirmation-inner #cookie-confirmation-buttons-area a#confirmation-button:after {
+ -ms-transform:rotate(-135deg);
+ transform:rotate(-135deg);
+ top:auto;
+ right:-13px;
+ bottom:-12px;
+}
+
+/*! CSS Used from: Embedded */
+ div#cookie-confirmation{
+ position:absolute;
+ left:0;
+ top:0;
+ width:100%;
+ height:auto;
+ background-color:#2d2d2d;
+ border-bottom:1px solid gray;
+ border-bottom:1px solid rgba(0,0,0,0.5);
+ -webkit-box-shadow:0 1px 2px rgba(0,0,0,0.2);
+ -moz-box-shadow:0 1px 2px rgba(0,0,0,0.2);
+ box-shadow:0 1px 2px rgba(0,0,0,0.2);
+ font-size:14px !important;
+ line-height:18px !important;
+ font-family:helvetica neue,helvetica,arial,sans !important;
+ color:#fff !important;
+ text-shadow:0 1px 0 rgba(0,0,0,0.7) !important;
+ text-align:left !important;
+ z-index:100000000 !important;
+}
+div#cookie-confirmation.can-use-gradients{
+ background-color:rgba(0,0,0,0);
+ background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(0,0,0,0.9)), color-stop(100%, rgba(0,0,0,0.75)));
+ background-image:-webkit-linear-gradient(top, rgba(0,0,0,0.9),rgba(0,0,0,0.75));
+ background-image:-moz-linear-gradient(top, rgba(0,0,0,0.9),rgba(0,0,0,0.75));
+ background-image:-o-linear-gradient(top, rgba(0,0,0,0.9),rgba(0,0,0,0.75));
+ background-image:linear-gradient(top, rgba(0,0,0,0.9),rgba(0,0,0,0.75));
+ background-image:linear-gradient(to bottom, rgba(0,0,0,0.9),rgba(0,0,0,0.75));
+}
+ div#cookie-confirmation div#cookie-confirmation-inner{
+ padding:12px 18px 18px;
+}
+ div#cookie-confirmation div#cookie-confirmation-inner a{
+ font-family:helvetica neue,helvetica,arial,sans !important;
+ color:#add8e6 !important;
+ font-size:14px !important;
+ text-decoration:none !important;
+ background:none !important;
+ border:none !important;
+ font-weight:normal !important;
+}
+ div#cookie-confirmation div#cookie-confirmation-inner a:hover{
+ text-decoration:underline !important;
+ background:none !important;
+ border:none !important;
+}
+ div#cookie-confirmation div#cookie-confirmation-inner div#cookie-confirmation-buttons-area{
+ text-align:center !important;
+}
+ div#cookie-confirmation div#cookie-confirmation-inner a#confirmation-button{
+ font-family:helvetica neue,helvetica,arial,sans!important;
+ font-size:14px !important;
+ font-weight:normal !important;
+ margin-right:16px !important;
+ padding:4px 12px !important;
+ background-color:green !important;
+ border:1px solid gray !important;
+ border:1px solid rgba(0,0,0,0.5) !important;
+ background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, transparent), color-stop(100%, rgba(0,0,0,0.2)));
+ background-image:-webkit-linear-gradient(top, transparent,rgba(0,0,0,0.2));
+ background-image:-moz-linear-gradient(top, transparent,rgba(0,0,0,0.2));
+ background-image:-o-linear-gradient(top, transparent,rgba(0,0,0,0.2));
+ background-image:linear-gradient(top, transparent,rgba(0,0,0,0.2));
+ -webkit-border-radius:4px;
+ -moz-border-radius:4px;
+ -ms-border-radius:4px;
+ -o-border-radius:4px;
+ border-radius:4px;
+ -webkit-box-shadow:0 1px 2px rgba(0,0,0,0.2),inset 0 1px 0 rgba(255,255,255,0.5);
+ -moz-box-shadow:0 1px 2px rgba(0,0,0,0.2),inset 0 1px 0 rgba(255,255,255,0.5);
+ box-shadow:0 1px 2px rgba(0,0,0,0.2),inset 0 1px 0 rgba(255,255,255,0.5);
+ line-height:14px !important;
+ color:#fff !important;
+ text-shadow:0 1px 0 rgba(0,0,0,0.5) !important;
+ text-decoration:none !important;
+}
+ div#cookie-confirmation div#cookie-confirmation-inner a#confirmation-button:hover{
+ background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, transparent), color-stop(100%, rgba(0,0,0,0.3)));
+ background-image:-webkit-linear-gradient(top, transparent,rgba(0,0,0,0.3));
+ background-image:-moz-linear-gradient(top, transparent,rgba(0,0,0,0.3));
+ background-image:-o-linear-gradient(top, transparent,rgba(0,0,0,0.3));
+ background-image:linear-gradient(top, transparent,rgba(0,0,0,0.3));
+}
+ div#cookie-confirmation div#cookie-confirmation-inner a#confirmation-button:active{
+ background-image:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(0,0,0,0.3)), color-stop(100%, rgba(0,0,0,0.3)));
+ background-image:-webkit-linear-gradient(top, rgba(0,0,0,0.3),rgba(0,0,0,0.3));
+ background-image:-moz-linear-gradient(top, rgba(0,0,0,0.3),rgba(0,0,0,0.3));
+ background-image:-o-linear-gradient(top, rgba(0,0,0,0.3),rgba(0,0,0,0.3));
+ background-image:linear-gradient(top, rgba(0,0,0,0.3),rgba(0,0,0,0.3));
+ -webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.2);
+ -moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.2);
+ box-shadow:inset 0 1px 2px rgba(0,0,0,0.2);
+}
+div#cookie-confirmation div#cookie-confirmation-inner p{
+ line-height:18px !important;
+ font-family:helvetica neue,helvetica,arial,sans !important;
+ font-weight:normal !important;
+ font-size:14px !important;
+ margin:0 0 16px !important;
+ padding:0 !important;
+ color:#fff !important;
+ text-align:left !important;
+}
+@media screen and (max-width: 480px) {
+ div#cookie-confirmation {
+ font-size:12px !important;
+ }
+ div#cookie-confirmation div#cookie-confirmation-inner {
+ padding:8px 14px 14px !important;
+ }
+ div#cookie-confirmation div#cookie-confirmation-inner a {
+ font-size:12px !important;
+ }
+ div#cookie-confirmation div#cookie-confirmation-inner a#confirmation-button {
+ font-size:12px !important;
+ }
+ div#cookie-confirmation div#cookie-confirmation-inner p {
+ font-size:12px !important;
+ margin-bottom:12px !important;
+ line-height:15px !important;
+ }
+}
diff --git a/doc/global/template/style/online.css b/doc/global/template/style/online.css
index 7d84863b74..4bccee7409 100644
--- a/doc/global/template/style/online.css
+++ b/doc/global/template/style/online.css
@@ -1,3 +1,5 @@
+@import url('cookie-confirm.css') screen;
+
#navbar {
position:fixed;
top:0;
@@ -6,254 +8,172 @@
background:#fff;
width:100%
}
-#navbar .container {
- overflow:visible
-}
-.fixed .container {
+#navbar .container, .fixed .container {
+ max-width:1280px;
+ margin:0 auto;
+ padding:0 3.9%; /* 0? */
+ position:relative;
overflow:visible
}
-.box-shadowed-nav #navbar {
- border-bottom:1px solid #eee
-}
#navbar .navbar-header {
position:relative
}
-#navbar .navbar-toggle {
- display:none;
- float:right;
- line-height:18px;
- min-width:95px;
- position:relative;
- text-align:center;
- border-left:1px solid #eee;
- border-right:1px solid #eee;
- padding:10px 0 10px 0
+#menuextras li a:hover span {
+ color: #41cd52;
+}
+/* new header */
+#mm-wrap, #mm-wrap #mm-helper,
+#mm-wrap #mm-helper li.mm-item,
+#mm-wrap #mm-helper a.mm-link {
+ -moz-transition: none;
+ -o-transition: none;
+ -webkit-transition: none;
+ transition: none;
+ -webkit-border-radius: 0 0 0 0;
+ -moz-border-radius: 0 0 0 0;
+ -ms-border-radius: 0 0 0 0;
+ -o-border-radius: 0 0 0 0;
+ border-radius: 0 0 0 0;
+ -webkit-box-shadow: none;
+ -moz-box-shadow: none;
+ -ms-box-shadow: none;
+ -o-box-shadow: none;
+ box-shadow: none;
+ background: none;
+ border: 0;
+ bottom: auto;
+ box-sizing: border-box;
+ clip: auto;
+ color: #090e21;
+ display: block;
+ float: none;
+ font-family: inherit;
+ font-size: 14px;
+ height: auto;
+ left: auto;
+ line-height: 1.7;
+ list-style-type: none;
+ margin: 0;
+ min-height: 0;
+ opacity: 1;
+ outline: none;
+ overflow: visible;
+ padding: 0;
+ position: relative;
+ right: auto;
+ text-align: left;
+ text-decoration: none;
+ text-transform: none;
+ top: auto;
+ vertical-align: baseline;
+ visibility: inherit;
+ width: auto;
+}
+#mm-wrap #mm-helper {
+ visibility:visible;
+ text-align:right;
+ padding:0 0px 0 0px
}
-#navbar .navbar-toggle:hover figure {
- background:#5caa15
+#navbar #mm-wrap #mm-helper li.mm-item {
+ border-right:solid #f3f3f4 1px;
+ padding-right:30px;
+ padding-left:30px
}
-#navbar .navbar-toggle span {
- color:#bdbebf;
- font-weight:300
+#navbar #mm-wrap #mm-helper li.mm-item > a:hover {
+ opacity: .5
}
-#navbar .navbar-toggle figure {
- background:#7fc241;
- border-radius:100%;
- -webkit-border-radius:100%;
- -moz-border-radius:100%;
- transition:all 0.2s ease-in-out;
- -webkit-transition:all 0.2s ease-in-out;
- -moz-transition:all 0.2s ease-in-out;
- -ms-transition:all 0.2s ease-in-out;
- -o-transition:all 0.2s ease-in-out;
- height:26px;
- width:34px;
- padding:8px 0 0 0;
- margin-top:3px;
- margin-left:auto;
- margin-right:auto;
- text-align:center
-}
-#navbar .navbar-toggle figure span.line {
+#mm-wrap #mm-helper > li.mm-item {
+ margin:0 0 0 0;
display:inline-block;
- width:1.125em;
- height:0.1875em;
- background:#fff;
- transition:0.3s;
- position:relative;
- vertical-align:middle;
- margin-top:-3px
-}
-#navbar .navbar-toggle figure span.line:before,#navbar .navbar-toggle figure span.line:after {
- display:inline-block;
- width:1.125em;
- height:0.1875em;
- background:#fff;
- position:absolute;
- left:0;
- content:'';
- -webkit-transform-origin:0.28571rem center;
- transform-origin:0.28571rem center;
- transition:0.3s;
- -webkit-transition:0.3s;
- -moz-transition:0.3s;
- -ms-transition:0.3s;
- -o-transition:0.3s
-}
-#navbar .navbar-toggle figure span.line:before {
- top:6px
-}
-#navbar .navbar-toggle figure span.line:after {
- top:-6px
-}
-#navbar .navbar-toggle.opened figure {
- background:#5caa15
+ height:auto;
+ vertical-align:middle
}
-#navbar .navbar-toggle.opened span {
- color:#5caa15
+#navbar #mm-wrap #mm-helper li.mm-item:nth-child(3) {
+ border-right:0
}
-#navbar .navbar-toggle.opened span.line {
- background:transparent
+#mm-wrap #mm-helper a.mm-link {
+ cursor: pointer
}
-#navbar .navbar-toggle.opened span.line:before,#navbar .navbar-toggle.opened span.line:after {
- -webkit-transform-origin:50% 50%;
- -moz-transform-origin:50% 50%;
- transform-origin:50% 50%;
- top:0;
- width:23px;
- margin-left:-2px
-}
-#navbar .navbar-toggle.opened span.line:before {
- transform:rotate3d(0, 0, 1, 45deg);
- -webkit-transform:rotate3d(0, 0, 1, 45deg);
- -moz-transform:rotate3d(0, 0, 1, 45deg);
- -ms-transform:rotate3d(0, 0, 1, 45deg);
- -o-transform:rotate3d(0, 0, 1, 45deg);
- left:0
-}
-#navbar .navbar-toggle.opened span.line:after {
- transform:rotate3d(0, 0, 1, -45deg);
- -webkit-transform:rotate3d(0, 0, 1, -45deg);
- -moz-transform:rotate3d(0, 0, 1, -45deg);
- -ms-transform:rotate3d(0, 0, 1, -45deg);
- -o-transform:rotate3d(0, 0, 1, -45deg)
+@media (max-width: 1279px) {
+ #navbar {
+ padding:0;
+ position:relative;
+ }
+ #navbar .container {
+ max-width:100%
+ }
+ .container {
+ padding:0 2%
+ }
}
#navbar .navbar-oneQt {
display:inline;
float:left;
width:31px;
- padding:20px 8px;
- margin:0 15px 0 0
+ color:#41cd52
}
#navbar .navbar-oneQt:before {
content:attr(data-icon);
position:absolute;
- top:15px;
+ top:14px;
left:0;
- color:#80c342;
+ color:#41cd52;
font-family:'Qt Icons';
line-height:1;
- font-size:3.125em;
- transition:all 0.2s ease-in-out;
- -webkit-transition:all 0.2s ease-in-out;
- -moz-transition:all 0.2s ease-in-out;
- -ms-transition:all 0.2s ease-in-out;
- -o-transition:all 0.2s ease-in-out
-}
-.navbar-oneQt {
- color: #80c342 !important;
-}
-.navbar-oneQt:hover {
- color: #80c342;
-}
-#navbar .navbar-menu {
+ font-size:40px;
+ transition:all 0.3s ease-in-out;
+}
+#mm-wrap {
+ clear:both;
+ background:rgba(255, 255, 255, 0.1);
+ -webkit-border-radius:0px 0px 0px 0px;
+ -moz-border-radius:0px 0px 0px 0px;
+ -ms-border-radius:0px 0px 0px 0px;
+ -o-border-radius:0px 0px 0px 0px;
+ border-radius:0px 0px 0px 0px
+}
+#mm-wrap #mm-helper li.mm-item:last-child a {
+ background:transparent url("icon_avatar.png") 50% 50% no-repeat !important;
+ background-size:24px !important;
+ width:24px !important;
+ height:24px !important;
+}
+#navbar #mm-wrap #mm-helper li.mm-item > a {
+ opacity:1;
+ -webkit-transition:all 0.3s ease-in-out;
+ -moz-transition:all 0.3s ease-in-out;
+ -ms-transition:all 0.3s ease-in-out;
+ -o-transition:all 0.3s ease-in-out;
+ transition:all 0.3s ease-in-out;
+}
+#mm-wrap #mm-helper > li.mm-item > a.mm-link {
+ border-top:0px solid #fff;
+ border-left:0px solid #fff;
+ border-right:0px solid #fff;
+ border-bottom:0px solid #fff;
+ outline:none;
+ text-decoration:none;
+ padding:0 0 0 0;
+ line-height:70px;
+ font-weight:normal;
+ height:70px;
+ vertical-align:baseline;
+ text-align:left;
width:auto;
- float:left
-}
-.lt-ie9 #navbar {
- border-bottom:1px solid #ddd
-}
-#mainmenu {
- float:left;
- list-style:none;
- margin-left:16px
-}
-#mainmenu li {
- float:left;
- margin-left:0;
- list-style-type:none !important
-}
-#mainmenu li a {
display:block;
- padding:29px 0.7em;
- font-size:1.125em;
- font-weight:300;
- line-height:20px;
- height:80px;
- color:#26282a;
+ color:#090e21;
+ text-transform:none;
text-decoration:none;
- border:0px solid #80c342;
- -webkit-transition:all 0.2s ease-in-out;
- box-sizing:border-box;
- -webkit-box-sizing:border-box;
- -moz-box-sizing:border-box;
- *behavior:url(boxsizing.htc)
-}
-#mainmenu li a:hover {
- color:#5caa15;
- border-bottom:4px solid #80C342
-}
-#mainmenu li.current-menu-item a {
- color:#5caa15;
- border-bottom:4px solid #80C342
-}
-#menuextras, #mainmenu, #menuextraslanguages {
- margin-bottom:0
- }
-#menuextras {
- display:inline-block;
- float:right;
- list-style-type:none;
- margin-right:0;
- margin-left:0;
- letter-spacing:-0.31em;
- line-height:0
-}
-#menuextras li {
- letter-spacing:normal;
- float:left;
- display:inline-block
-}
-#menuextras li a {
- display:inline-block;
- text-align:center;
- height:80px;
- border-left:1px solid #eee;
- padding-top:14px;
- box-sizing:border-box;
- overflow:hidden;
- min-width:85px;
- font-weight:100
-}
-#menuextras li:last-child a {
- border-right:1px solid #eee;
-}
-#menuextras li a:before {
- display:inline-block;
- font-family:'Qt Icons';
- content:attr(data-icon);
- font-size:2.125em;
- width:100%;
- color:#80c342;
- line-height:1;
- transition:all 0.2s ease-in-out;
- -webkit-transition:all 0.2s ease-in-out;
- -moz-transition:all 0.2s ease-in-out;
- -ms-transition:all 0.2s ease-in-out;
- -o-transition:all 0.2s ease-in-out
-}
-#menuextras li a:hover:before {
- color:#5caa15
-}
-#menuextras .search.open a {
- color:#006325
-}
-#menuextras .search a {
- border-right:1px solid #eee
-}
-#menuextras li a span {
- color:#bdbebf;
- display:inline-block;
- overflow:hidden;
- max-height:30px;
- transition:max-height 0.2s ease-in-out;
- -webkit-transition:max-height 0.2s ease-in-out;
- -moz-transition:max-height 0.2s ease-in-out;
- -ms-transition:max-height 0.2s ease-in-out;
- -o-transition:max-height 0.2s ease-in-out;
- line-height:1.4;
- font-size:0.875em
-}
+ background:rgba(0, 0, 0, 0);
+ -webkit-border-radius:0px 0px 0px 0px;
+ -moz-border-radius:0px 0px 0px 0px;
+ -ms-border-radius:0px 0px 0px 0px;
+ -o-border-radius:0px 0px 0px 0px;
+ border-radius:0px 0px 0px 0px;
+ font-family:inherit;
+ font-size:14px;
+}
+/* end new header */
@media (min-width: 1320px) {
.context .flowListDiv dl.flowList {
-webkit-column-count:3;
@@ -262,44 +182,20 @@
}
}
@media (min-width: 1120px) {
- #navbar.fixed,#navbar.shadow_bottom {
- -moz-box-shadow:0px 0px 8px rgba(0,0,0,0.2);
- -webkit-box-shadow:0px 0px 8px rgba(0,0,0,0.2);
- box-shadow:0px 0px 8px rgba(0,0,0,0.2)
- }
- #navbar.fixed #menuextras li a,#navbar.shadow_bottom #menuextras li a {
- padding-top:9px;
- height:50px
- }
- #navbar.fixed #menuextras li a span,#navbar.shadow_bottom #menuextras li a span {
- max-height:0
- }
- #navbar.fixed #menuextras li a:before,#navbar.shadow_bottom #menuextras li a:before {
- font-size:30px
+ #navbar.fixed {
+ -moz-box-shadow:0px 0px 8px rgba(0,0,0,0.23);
+ -webkit-box-shadow:0px 0px 8px rgba(0,0,0,0.23);
+ box-shadow:0px 0px 8px rgba(0,0,0,0.23)
}
- #navbar.fixed #mainmenu li a {
+ #navbar.fixed #mm-wrap #mm-helper > li.mm-item > a.mm-link {
height:50px;
- padding:14px 0.7em
- }
- #navbar.fixed #mainmenu li a:hover {
- border-bottom:4px solid #5caa15
- }
- #navbar.fixed .navbar-toggle {
- padding:13px 14px 9px
- }
- #navbar.fixed #menuextras li.navbar-search {
- padding:0px 0
- }
- #navbar.fixed #menuextras ul.menuextraslinks,#navbar.fixed #menuextras ul.menuextraslanguages {
- display:none
+ line-height:50px
}
#navbar.fixed .navbar-oneQt:before {
font-size:35px;
top:7px
}
- #navbar.fixed #mainmenu li.current-menu-item a {
- border-bottom:4px solid #80C342
- }
+
.flowListDiv dl.flowList {
-webkit-column-count:2;
-moz-column-count:2;
@@ -311,85 +207,13 @@
padding:0;
position:relative
}
- #navbar .container {
- max-width:100%
- }
- #navbar .menuextraslanguages {
- bottom:10px !important;
- right:0
- }
- #navbar .menuextraslanguages li a {
- color:#7fc241 !important
- }
- #navbar .menuextraslanguages li.active a,#navbar .menuextraslanguages li a:hover {
- border-color:#7fc241 !important
+ #navbar .navbar-oneQt:before {
+ left:10px
}
#navbar .container {
+ max-width:100%;
padding:0
}
- #navbar .navbar-toggle {
- display:block
- }
- #navbar .navbar-oneQt,#navbar.fixed .navbar-oneQt,#navbar .navbar-oneQt:hover {
- margin-left:0;
- height:26px;
- width:22px;
- padding:7px 20px 7px 15px
- }
- #navbar .navbar-oneQt:before {
- left:20px
- }
- #navbar .navbar-menu {
- max-height:0;
- overflow:hidden;
- width:100%;
- border-top:1px solid #eee;
- -webkit-transition:all 600ms ease-in-out;
- -moz-transition:all 600ms ease-in-out;
- -o-transition:all 600ms ease-in-out;
- transition:all 600ms ease-in-out;
- position:relative
- }
- #mainmenu {
- float:none;
- width:100%;
- padding:0;
- margin:0
- }
- #mainmenu li {
- float:none;
- list-style:none
- }
- #mainmenu li:nth-child(odd) {
- background:rgba(0,0,0,0)
- }
- #mainmenu li a,#navbar.fixed #mainmenu li a {
- padding:10px;
- border-left:3px solid #fff;
- height:auto;
- width:100%
- }
- #mainmenu li.current-menu-item a,#navbar.fixed #mainmenu li.current-menu-item a {
- border-bottom:none;
- border-left:3px solid #5caa15;
- padding:10px
- }
- #mainmenu li a:hover {
- border-bottom:0;
- padding:10px;
- border-left:3px solid #5caa15
- }
- #navbar.fixed {
- -moz-box-shadow:0px 0px 0px rgba(0,0,0,0);
- -webkit-box-shadow:0px 0px 0px rgba(0,0,0,0);
- box-shadow:0px 0px 0px rgba(0,0,0,0)
- }
- .lt-ie9 #navbar.fixed {
- border-bottom:none
- }
- #menuextras li.navbar-search {
- padding:5px 0
- }
#footerbar .container {
padding:0
}
@@ -406,11 +230,11 @@
#footerbar .footer-main .theqtcompany {
clear:both;
float:left;
- margin:30px 0 28px 3%
+ margin:30px 0 8px 3%
}
#footerbar .footer-main .footer-social {
float:left;
- padding:30px 0px 0px 3%
+ padding:50px 0px 0px 3%
}
#footerbar #menu-footer-submenu {
clear:both;
@@ -422,121 +246,6 @@
margin-left: 0
}
}
-.in-page-nav {
- width:100%;
- background:#eeeeee
-}
-.in-page-nav ul {
- margin:0 auto;
- letter-spacing:-0.31em;
- max-width:1180px;
- text-align:center
-}
-.in-page-nav ul li {
- display:inline-block;
- letter-spacing:normal
-}
-.in-page-nav ul li a {
- color:#26282a;
- padding:25px 10px;
- display:inline-block
-}
-body.qt-account #navbar .navbar-oneQt {
- width:auto;
- height:auto
-}
-body.qt-account #navbar .navbar-oneQt:before {
- left:0;
- position:relative;
- display:inline-block;
- vertical-align:middle;
- top:0;
- margin-right:20px
-}
-body.qt-account #navbar .navbar-oneQt h2 {
- margin:0;
- color:#000;
- display:inline-block;
- vertical-align:middle
-}
-.landing header[role="banner"] {
- background:#26282a
-}
-.landing header[role="banner"] figure {
- max-width:1180px;
- margin:auto;
- position:relative
-}
-.landing header[role="banner"] figure img {
- max-width:100%
-}
-.landing header[role="banner"] figcaption {
- color:#fff;
- position:absolute;
- left:0px;
- width:100%;
- text-align:center
-}
-.landing header[role="banner"] figcaption.top {
- top:0
-}
-.landing header[role="banner"] figcaption.bottom {
- bottom:0
-}
-.landing header[role="banner"] figcaption h1 {
- margin:50px auto 0 auto;
- max-width:70%;
- font-weight:600
-}
-.landing header[role="banner"] figcaption h3 {
- margin-bottom:40px
-}
-.cookies_yum {
- background-color:#d6d6d6;
- display:none;
- line-height:1.625em;
- width:100%
-}
-.cookies_yum img {
- width:25px;
- top:6px;
- display:inline-block;
- position:absolute;
- left:6px
-}
-.cookies_yum div {
- margin:0 auto;
- max-width:1280px;
- min-height:30px;
- padding:6px 0px 6px 0px;
- position:relative
-}
-.cookies_yum p {
- color:#585a5c;
- margin:0px;
- font-size:0.79em;
- display:inline-block;
- line-height:1.2;
- padding:0 30px 0 50px
-}
-.cookies_yum p a {
- white-space:nowrap
-}
-.cookies_yum a:hover {
- color:white
-}
-.cookies_yum .close {
- width:15px;
- height:15px;
- background-image:url("cookiebar-x.png");
- background-size:15px 30px;
- background-position:top left;
- cursor:pointer;
- top:13px;
- right:13px;
- position:absolute;
- transition:none;
-}
#sidebar-toggle,#toc-toggle {
width:24px;
height:14px;
@@ -552,199 +261,10 @@ body.qt-account #navbar .navbar-oneQt h2 {
#sidebar-content > h2 {
display:none
}
-.cookies_yum .close:hover {
- background-position:bottom left
-}
-#bottom_header {
- display:block;
- position:absolute;
- width:100%;
- z-index:50;
- padding-top:15px
-}
-#bottom_header .container {
- overflow:visible
-}
-#bottom_header .left {
- font-weight:bolder
-}
-#bottom_header a {
- color:white;
- transition-duration:0.3s
-}
-#bottom_header .left a:hover {
- padding-left:10px
-}
-.fixed .menuextraslanguages {
- opacity:0;
- visibility:hidden
-}
-@media (max-width: 1120px) {
- .fixed .menuextraslanguages {
- opacity:1 !important;
- visibility:visible !important
- }
-}
-#navbar .menuextraslanguages {
- position:absolute;
- right:0;
- bottom:-35px;
- transition:all 0.2s ease-in-out;
- -webkit-transition:all 0.2s ease-in-out;
- -moz-transition:all 0.2s ease-in-out;
- -ms-transition:all 0.2s ease-in-out;
- -o-transition:all 0.2s ease-in-out
-}
-#navbar .menuextraslanguages li {
- display:inline;
- list-style:none;
- margin-left:3px;
- padding:0px 4px;
- font-size:0.6875em
-}
-#navbar .menuextraslanguages li.dark a {
- color:#868482
-}
-#navbar .menuextraslanguages li.dark a:hover {
- border:2px solid #868482
-}
-#navbar .menuextraslanguages li.active.dark a {
- border-color:#868482;
- color:#868482
-}
-#navbar .menuextraslanguages a {
- color:#fff;
- padding:2px 4px;
- border:2px solid transparent
-}
-#navbar .menuextraslanguages a:hover,#navbar .menuextraslanguages li.active a {
- border:2px solid #fff;
- color:#fff
-}
-#bottom_header .dark,#bottom_header .dark.active {
- color:#868482;
- transition-duration:0.3s;
- border-color:#868482 !important
-}
-#navbar .big_bar {
- width:100%;
- height:100px;
- background-color:#80C342;
- display:none;
- position:relative
-}
-#navbar .big_bar.search {
- height:auto;
- overflow:hidden;
- display:none
-}
-#navbar .big_bar ::-webkit-input-placeholder {
- color:#fff
-}
-#navbar .big_bar :-moz-input-placeholder {
- color:#fff
-}
-#navbar .big_bar ::-moz-input-placeholder {
- color:#fff
-}
-#navbar .big_bar :-ms-input-placeholder {
- color:#fff
-}
-#navbar .big_bar:hover>div .big_bar_button.account {
- background-position:right bottom
-}
-#navbar .big_bar.account h1 {
- padding-top:20px
-}
-#navbar .big_bar.account h1,#navbar .big_bar.account h1 a {
- color:#FFF;
- margin-bottom:5px
-}
-#navbar .big_bar.account h1 a:hover {
- color:#328930
-}
-#navbar .big_bar_button:hover {
- background-position:left bottom;
- cursor:pointer
-}
-#navbar .big_bar_button.account {
- background-position:right top
-}
-#navbar .big_bar input.big_bar_search {
- background:none repeat scroll 0 0 transparent;
- border:medium none;
- color:#fff;
- display:block;
- float:left;
- font-size:4em;
- outline:0 none;
- width:70%;
- line-height:1.3;
- height:auto;
- margin:10px 5%;
- padding:0;
- box-sizing:border-box;
- -webkit-box-sizing:border-box;
- -moz-box-sizing:border-box;
- *behavior:url(boxsizing.htc)
-}
-#navbar .big_bar_button {
- background-color:transparent;
- border:none;
- width:18%;
- transition-duration:0.3s;
- display:block;
- float:left;
- position:relative;
- font-family:'QT Icons';
- font-size:3.5em;
- color:#fff;
- margin:15px 2% 0 0 !important;
- text-align:right;
- padding-right:2px !important;
- transition:all 0.2s ease-in-out;
- -webkit-transition:all 0.2s ease-in-out;
- -moz-transition:all 0.2s ease-in-out;
- -ms-transition:all 0.2s ease-in-out;
- -o-transition:all 0.2s ease-in-out
-}
-#navbar .big_bar_button:focus,#navbar .big_bar_button:hover {
- outline:0;
- color:#ebebeb
-}
-.hero_slide>div {
- width:80%;
- margin:0 auto
-}
-.hero_slide>div:first-child>div {
- width:80%;
- margin:0 auto
-}
-.hero_slide .content {
- margin-top:70px
-}
-.hero_bar {
- padding-top:50px;
- padding-bottom:18px
-}
-.hero_bar p {
- font-size:0.875em;
- text-align:center
-}
-.hero_bar .arrow {
- bottom:65px;
- display:block;
- margin:0 auto;
- position:relative;
- right:260px;
- width:230px
-}
-.hero_bar .comment {
- margin:0
-}
#footerbar {
- background:#26282a;
- color:#fff
+ background:#222840;
+ color:#fff;
+ font-size: 0.9em;
}
#footerbar.fixed {
bottom:0;
@@ -761,10 +281,11 @@ body.qt-account #navbar .navbar-oneQt h2 {
}
#footerbar .footer-main .footer-nav li a {
display:block;
- padding:31px 10px 15px 0;
+ padding:30px 0 10px 0;
line-height:20px;
height:20px;
- color:#d6d6d6
+ color:#fff;
+ font-weight: 600;
}
#footerbar .footer-main .footer-nav li a:hover,#footerbar .footer-main .footer-nav li.current-menu-item a {
color:#eee
@@ -774,7 +295,8 @@ body.qt-account #navbar .navbar-oneQt h2 {
margin-bottom:0
}
#footerbar .footer-main .footer-nav .sub-menu li {
- float:none
+ float:none;
+ width: 100%;
}
#footerbar .footer-main .footer-nav .sub-menu ul {
padding:1px 1em;
@@ -785,11 +307,11 @@ body.qt-account #navbar .navbar-oneQt h2 {
margin-bottom:0
}
#footerbar .footer-main .footer-nav .sub-menu li a {
- padding:1px 0;
- font-size:0.786em;
- line-height:8px;
+ padding:2px 0;
+ font-size:1em;
float:none;
- color:#d6d6d6
+ color:#cecfd5;
+ font-weight: 400;
}
#footerbar .footer-main .footer-nav .sub-menu li a:hover,#footerbar .footer-main .footer-nav .sub-menu li.current-menu-item a {
color:#eee
@@ -806,7 +328,6 @@ body.qt-account #navbar .navbar-oneQt h2 {
#footerbar .footer-social {
display:inline;
float:right;
- padding-top:31px;
width:164px
}
#footerbar .footer-main .footer-social>div {
@@ -847,34 +368,33 @@ body.qt-account #navbar .navbar-oneQt h2 {
margin-bottom:0
}
@font-face {
- font-family:'Open Sans';
- font-style:normal;
- font-weight:300;
- src:local("Open Sans Light"),local("OpenSans-Light"),url(//fonts.gstatic.com/s/opensans/v10/DXI1ORHCpsQm3Vp6mXoaTYnF5uFdDttMLvmWuJdhhgs.ttf) format("truetype")
-}
+ font-family: 'Titillium Web';
+ font-style: normal;
+ font-weight: 400;
+ src: url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.eot");
+ /* IE9 Compat Modes */
+ src: local("Titillium Web"), local("TitilliumWeb-Regular"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.eot?#iefix") format("embedded-opentype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.woff2") format("woff2"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.woff") format("woff"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.ttf") format("truetype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.svg#TitilliumWeb") format("svg");
+ /* Legacy iOS */
+}
+/* titillium-web-italic - latin_latin-ext */
@font-face {
- font-family:'Open Sans';
- font-style:normal;
- font-weight:400;
- src:local("Open Sans"),local("OpenSans"),url(//fonts.gstatic.com/s/opensans/v10/cJZKeOuBrn4kERxqtaUH3aCWcynf_cDxXwCLxiixG1c.ttf) format("truetype")
-}
-@font-face {
- font-family:'Open Sans';
- font-style:normal;
- font-weight:600;
- src:local("Open Sans Semibold"),local("OpenSans-Semibold"),url(//fonts.gstatic.com/s/opensans/v10/MTP_ySUJH_bn48VBG8sNSonF5uFdDttMLvmWuJdhhgs.ttf) format("truetype")
-}
-@font-face {
- font-family:'Open Sans';
- font-style:normal;
- font-weight:700;
- src:local("Open Sans Bold"),local("OpenSans-Bold"),url(//fonts.gstatic.com/s/opensans/v10/k3k702ZOKiLJc3WVjuplzInF5uFdDttMLvmWuJdhhgs.ttf) format("truetype")
-}
+ font-family: 'Titillium Web';
+ font-style: italic;
+ font-weight: 400;
+ src: url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-italic.eot");
+ /* IE9 Compat Modes */
+ src: local("Titillium WebItalic"), local("TitilliumWeb-Italic"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-italic.eot?#iefix") format("embedded-opentype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-italic.woff2") format("woff2"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-italic.woff") format("woff"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-italic.ttf") format("truetype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-italic.svg#TitilliumWeb") format("svg");
+ /* Legacy iOS */
+}
+/* titillium-web-600 - latin_latin-ext */
@font-face {
- font-family:'Open Sans';
- font-style:normal;
- font-weight:800;
- src:local("Open Sans Extrabold"),local("OpenSans-Extrabold"),url(//fonts.gstatic.com/s/opensans/v10/EInbV5DfGHOiMmvb1Xr-honF5uFdDttMLvmWuJdhhgs.ttf) format("truetype")
+ font-family: 'Titillium Web';
+ font-style: normal;
+ font-weight: 600;
+ src: url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-600.eot");
+ /* IE9 Compat Modes */
+ src: local("Titillium WebSemiBold"), local("TitilliumWeb-SemiBold"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-600.eot?#iefix") format("embedded-opentype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-600.woff2") format("woff2"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-600.woff") format("woff"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-600.ttf") format("truetype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-600.svg#TitilliumWeb") format("svg");
+ /* Legacy iOS */
}
@font-face {
font-family:'Droid Sans Mono';
@@ -889,6 +409,14 @@ body.qt-account #navbar .navbar-oneQt h2 {
font-weight:normal;
font-style:normal
}
+@font-face {
+ font-family:'social-icons';
+ src:url("../style/social-icons.eot?54625607");
+ src:url("../style/social-icons.eot?54625607#iefix") format("embedded-opentype"),
+ url("../style/social-icons.woff?54625607") format("woff");
+ font-weight:normal;
+ font-style:normal
+}
.clearfix:before,.clearfix:after {
content:" ";
display:table
@@ -911,20 +439,15 @@ html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abb
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,caption,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video {
vertical-align:baseline
}
-body {
- font-family:“Open Sansâ€, Arial, Helvetica, sans-serif;
- line-height:1.5;
- font-weight:400
-}
h1,h2,h3,h4,h5,h6 {
font-weight:300
}
.context h2,.context h3,.context h4,.context h5,.context h6 {
- margin:1.5em 0 1em
+ margin:1.5em 0 0.75em
}
.context h1 {
- margin-bottom:1em;
- font-size:3.125em
+ margin-bottom:0.75em;
+ font-size:2.25em;
}
.context h3.fn,.context h3.flags {
color:#26282a;
@@ -982,13 +505,24 @@ h1,h2,h3,h4,h5,h6 {
padding:3px 5px 3px 10px;
text-align:right
}
+.centerAlign.functionIndex {
+ text-align:center;
+ font-size:150%;
+ margin-bottom: 1em
+}
article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section {
display:block
}
body {
line-height:1;
- font-family:"Open Sans", Arial, Helvetica, sans-serif;
- transition-duration:1s
+ font-family:'Titillium Web', Arial, Helvetica, sans-serif;
+ font-weight:400;
+ transition-duration:1s;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ font-size: 16px;
+ background-color:#f3f3f4;
+ color:#404244;
}
ol,ul {
list-style:none
@@ -997,25 +531,29 @@ ol,ul {
margin-top:0.75em;
margin-left:20px
}
-
-.context ol > li {
- margin-left: 20px
-}
-
.mainContent ol>li {
- list-style-type: decimal;
+ list-style-type:decimal;
+ margin-left:15px
}
-
.mainContent ol.a >li {
- list-style-type: lower-alpha;
+ list-style-type:lower-alpha;
}
-
.mainContent ol.A >li {
- list-style-type: upper-alpha;
+ list-style-type:upper-alpha;
+}
+.mainContent ol.i >li {
+ list-style-type:lower-roman;
+}
+.mainContent ol.I >li {
+ list-style-type:upper-roman;
+}
+.context li p {
+ margin-top:1em
}
-
blockquote,q {
- quotes:none
+ quotes:none;
+ border-left:10px solid #ddd;
+ padding-left:10px
}
blockquote:before,blockquote:after,q:before,q:after {
content:'';
@@ -1025,24 +563,33 @@ blockquote:before,blockquote:after,q:before,q:after {
table {
border-collapse:collapse;
border-spacing:0;
- margin-bottom:25px;
+ margin-bottom:5px;
width:100%
}
a {
- color:#5caa15;
+ color:#17a81a;
text-decoration:none;
transition-duration:0.3s
}
a:hover {
- color:#46a2da
+ color:#17a81a
}
-.main,.navbar-header,#footerbar>div {
+.main,#footerbar>div {
max-width:1280px;
width:95%;
margin:0 auto
}
.main {
- margin-top:100px
+ margin-top:80px
+}
+@media (max-width: 1120px) {
+ .main,.navbar-header,#footerbar>div {
+ width: 100%;
+ margin: 0;
+ }
+ .main .main-rounded {
+ padding: 0 15px;
+ }
}
.main_index {
background-color:#fff
@@ -1063,14 +610,14 @@ a:hover {
width:80%;
display:inline-block;
background-color:#fff;
- padding:35px;
+ padding: 25px 35px 20px 30px;
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
-ms-box-sizing:border-box;
box-sizing:border-box
}
.col-1 h2 {
- font-size:2.1875em;
+ font-size:1.8em;
font-weight:300;
line-height:1.1;
margin-bottom:0.83em;
@@ -1096,18 +643,31 @@ div.multi-column div {
}
.sidebar {
display:block;
- float:right;
+ position:relative;
+ position:sticky;
+ float:left;
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
-ms-box-sizing:border-box;
box-sizing:border-box;
width:20%;
- padding-left:30px
+ padding-right:20px
+}
+.sidebar li {
+ text-overflow:ellipsis;
+ overflow:hidden
}
.toc,.sectionlist {
- padding:35px;
+ padding:25px;
background-color:#fff;
- margin-bottom:2em
+ margin-bottom:1.25em
+}
+.sidebar .sectionlist p {
+ margin-bottom:0
+}
+.sectionlist.promo {
+ padding:0;
+ background-color:#f3f3f4
}
.sidebar-content:empty {
display:none;
@@ -1115,13 +675,13 @@ div.multi-column div {
}
.col-2 h2,.toc h3,.sidebar-content h2,.sidebar-content h3,.sectionlist h2 {
font-weight:400;
- margin-bottom:2em
+ margin-bottom:1em
}
.toc h3 a {
color:#404244
}
.title {
- font-size:3em;
+ font-size:2.25em;
font-weight:300;
letter-spacing:-1px;
line-height:1.15em;
@@ -1129,12 +689,12 @@ div.multi-column div {
word-wrap:break-word
}
.navigationbar,col-1 h2 {
- font-size:0.75em
+ font-size:0.85em
}
.navigationbar h1 {
- font-size:3.125em;
- margin-bottom:1em;
- margin-top:1em
+ font-size:2.5em;
+ margin-bottom:0.85em;
+ margin-top:0.85em
}
.navigationbar li {
display:inline-block;
@@ -1143,11 +703,7 @@ div.multi-column div {
padding-right:10px;
color:#585a5c
}
-.navigationbar li a {
- color:#58585c
-}
-body {
- background-color:#eee;
+.navigationbar ul:last-of-type li a {
color:#404244
}
.sectionlist li {
@@ -1161,20 +717,18 @@ dd {
margin-bottom:1.56em
}
.mainContent li {
- margin-top:0.8em;
+ margin-top:0.5em;
line-height:1.25em
}
.mainContent li.level2 {
margin-left:10px;
margin-top:0.4em;
font-size:0.9375em;
- line-height:1.15em;
}
.mainContent p {
- line-height:1.56em;
+ line-height:1.25em;
margin-bottom:1.5em;
- color:#404244;
- max-width:85%
+ color:#404244
}
.mainContent b {
font-weight:600
@@ -1189,7 +743,8 @@ dd {
margin-top:25px;
max-width:100%
}
-.naviNextPrevious.headerNavi {
+.naviNextPrevious.headerNavi,
+p.naviNextPrevious + p {
display:none
}
.nextPage {
@@ -1201,6 +756,9 @@ dd {
.nextPage:after {
content:" >"
}
+.navigationbar li a {
+ color:#404244
+}
.navigationbar li:after {
color:#404244;
content:"›";
@@ -1211,9 +769,6 @@ dd {
right:-2px;
top:-4px
}
-.navigationbar ul:last li a {
- color:#80c342
-}
.sub-navigation {
margin-top:10px
}
@@ -1221,7 +776,8 @@ dd {
content:none
}
.navigationbar {
- margin-bottom:10px
+ margin-bottom:10px;
+ line-height:1em
}
#buildversion {
font-style:italic;
@@ -1229,13 +785,17 @@ dd {
float:right
}
.copy-notice {
- width:65%;
+ width:75%;
font-size:0.75em;
- margin-top:50px;
- margin-bottom:25px;
+ margin:20px 35px 0 10px;
line-height:1.75em;
+ float:right;
color:#585a5c
}
+.copy-notice.index {
+ margin-top:10px;
+ float:none
+}
li a.active {
color:#585a5c
}
@@ -1266,36 +826,51 @@ li a.active {
list-style-image:url("list_arrow.png");
margin-left:15px;
color:#404244;
- line-height:1.16em
+ margin-top:0.65em;
+ line-height:1em
+}
+.mainContent table p {
+ margin:0px;
+ padding:0px
}
.mainContent table p {
margin:0px;
padding:0px;
- max-width:initial;
- min-height:2em
+ min-height:1.25em
}
-.mainContent table p.centerAlign {
- text-align:center
+.mainContent .qmldoc {
+ margin-top:0.75em
}
.context h2 {
- font-size:2.1875em
+ margin-top: 1.5em;
+ font-size:1.75em
}
.context h3 {
- font-size:1.75em
+ font-size:1.35em
}
.context h4 {
- font-size:1.375em
+ font-size:1.15em
}
.context p img {
margin-top:0.75em;
max-width:100%
}
+.context .table table img {
+ max-width:initial
+}
.context .border img {
- box-shadow:3px 3px 8px 3px rgba(200,200,200,0.5)
- }
+ box-shadow:3px 3px 8px 3px rgba(200,200,200,0.5)
+}
.context .border .player {
- box-shadow:3px 3px 8px 3px rgba(200,200,200,0.5)
- }
+ box-shadow:3px 3px 8px 3px rgba(200,200,200,0.5)
+}
+.context p.figCaption {
+ transform:translateY(-30px);
+ color:#606366;
+ font-size:95%;
+ margin-left:3px;
+ font-style:italic
+}
.context table {
vertical-align:initial
}
@@ -1313,6 +888,10 @@ table td,table th {
padding:5px 20px;
line-height:1.3
}
+.context .fixed table td {
+ min-width:50%;
+ width:50%
+}
table.alignedsummary,table.propsummary {
width:initial
}
@@ -1320,7 +899,7 @@ table.valuelist td.tblval {
font-size:0.75em
}
div.main_index .row {
- border-bottom:1px solid #eee
+ border-bottom:10px solid #f3f3f4
}
div.main_index .row {
position:relative
@@ -1329,7 +908,7 @@ div.main_index .row>div {
display:inline-block;
width:50%;
vertical-align:top;
- padding:50px;
+ padding:2em 3em;
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
-ms-box-sizing:border-box;
@@ -1349,14 +928,14 @@ div.main_index .row:after {
top:0;
right:50%;
height:100%;
- width:1px;
- background-color:#eee
+ width:10px;
+ background-color:#f3f3f4
}
div.table {
overflow-x:auto
}
.context tr > td > pre {
- font-size:0.85em
+ font-size:0.75em
}
p.qt_commercial {
border:3px solid #5caa15;
@@ -1380,8 +959,12 @@ div.qt_commercial {
border-top:5px solid #5caa15;
margin-bottom:50px
}
+div.pre {
+ position:relative;
+ height:auto
+}
pre, .LegaleseLeft {
- background-color:#404244;
+ background-color:#3a4055;
color:#fff;
display:block;
font-family:"Droid Sans Mono";
@@ -1389,12 +972,85 @@ pre, .LegaleseLeft {
overflow-x:auto;
margin-bottom:25px;
padding:25px;
- margin-top:0.75em
+ margin-top:0.75em;
+ font-size: .8em;
}
.mainContent .LegaleseLeft p {
color:#fff;
white-space: pre-wrap
}
+pre .str,code .str {
+ color:#aaaaaa
+}
+pre .kwd,code .kwd {
+ color:#ffff55
+}
+pre .com,code .com {
+ color:#55ffff
+}
+pre .typ,code .typ {
+ color:#4f9d08
+}
+pre a .typ,code a .typ {
+ color:#21be2b
+}
+pre .lit,code .lit {
+ color:#ff55ff
+}
+pre .pun,code .pun {
+ color:#fff
+}
+pre .pln,code .pln {
+ color:#fff
+}
+@media print {
+ pre {
+ background-color:#eee !important
+ }
+ pre .str,code .str {
+ color:#060
+ }
+ pre .kwd,code .kwd{
+ color:#006;
+ font-weight:bold
+ }
+ pre .com,code .com {
+ color:#600
+ }
+ pre .typ,code .typ {
+ color:#404;
+ font-weight:bold
+ }
+ pre .lit,code .lit {
+ color:#044
+ }
+ pre .pun,code .pun {
+ color:#440
+ }
+ pre .pln,code .pln {
+ color:#000
+ }
+}
+pre.wrap {
+ white-space:pre-wrap
+}
+pre span.wrap {
+ display:none;
+ background:url("wrap.png") no-repeat;
+ right:0;
+ top:2px;
+ position:absolute;
+ width:20px;
+ height:14px;
+ margin:4px;
+ opacity:0.65
+}
+span.wrap:hover {
+ opacity:1
+}
+span.wrap:active {
+ opacity:0.75
+}
.copy_text {
background-color:#46a2da;
color:#fff;
@@ -1488,6 +1144,7 @@ pre:hover>.copy_text {
padding:10px
}
.sidebar {
+ position:relative;
padding-top:0
}
.search .sidebar {
@@ -1496,7 +1153,7 @@ pre:hover>.copy_text {
}
.col-2 h2,.toc h3,.sidebar-content h2,.sidebar-content h3,.sectionlist h2 {
text-align:center;
- margin-bottom:0
+ margin-bottom:5px
}
div.main_index .row:after {
content:none
@@ -1504,18 +1161,12 @@ pre:hover>.copy_text {
div.main_index .row>div {
display:block !important;
width:100%;
- padding:0;
+ padding:15px;
margin:0
}
.context,.sidebar,.col-1 {
width:100%
}
- .main_index h2,h1 {
- text-align:center
- }
- .context h4,.context h3,.context h2 {
- text-align:center
- }
.sidebar-content,.col-2,.toc {
background-color:#fff;
margin-bottom:1em;
@@ -1528,7 +1179,6 @@ pre:hover>.copy_text {
display:block
}
.mainContent p {
- line-height:1.56em;
margin-bottom:1em;
max-width:100%
}
@@ -1538,6 +1188,22 @@ pre:hover>.copy_text {
.sectionlist {
padding:0
}
+ .sidebar > .sectionlist {
+ padding:20px
+ }
+ .sectionlist.promo {
+ max-width:46%;
+ margin:0 auto 1em auto;
+ float:left;
+ padding:0 2%
+ }
+ .sidebar .sidebar-content {
+ clear:both
+ }
+ .copy-notice {
+ float:none;
+ width:initial
+ }
}
[id]:target,[name]:target,[name]:target+* {
-webkit-animation:highlighter 3s;
@@ -1586,6 +1252,25 @@ pre:hover>.copy_text {
#footer {
clear:both
}
+.footer-social i {
+ font-family: "social-icons";
+ font-style: normal;
+ font-size:150%;
+ margin: .55em;
+ color: #cecfd5
+}
+.footer-social i:hover {
+ color: #eee
+}
+.footer-social .icon-twitter:before {
+ content: '\f099'
+}
+.footer-social .icon-facebook:before {
+ content: '\f09a'
+}
+.footer-social .icon-youtube:before {
+ content: '\f16a'
+}
.menuextraslanguages {
display:none;
visibility:hidden
@@ -1596,7 +1281,7 @@ form.gsc-search-box {
margin-right: 0 !important;
margin-bottom: 4px !important;
margin-left: 0 !important;
- width: 100% !important;
+ width: 102.5% !important;
}
table.gsc-search-box {
border-style: none !important;
@@ -1614,13 +1299,30 @@ table.gsc-search-box td.gsc-input {
padding-right: 0px !important;
}
table.gsc-search-box td.gsc-input input {
- background-position: 15px center !important;
+ background-position: 10px center !important;
}
td.gsc-search-button {
+ line-height: 1.0;
+ position: relative;
+ left: -29px;
width: 1% !important;
}
+td.gsib_b {
+ display:none
+}
+
+button.gsc-search-button {
+ background-color: #aaa;
+}
+
+button.gsc-search-button svg {
+ height:20px;
+ width:12px;
+ padding:2px !important;
+}
+
td.gsc-clear-button {
width: 14px !important;
visibility:hidden !important;
@@ -1638,6 +1340,7 @@ table.gsc-branding {
border-width: 0 !important;
border-spacing: 0 0 !important;
width: 100% !important;
+ display:none
}
.gsc-branding-text {
@@ -1704,7 +1407,6 @@ input.gsc-search-button:focus {
input.gsc-input {
background-color: #fff !important;
border: 1px solid #d6d6d6 !important;
- border-radius: 5px !important;
box-sizing: border-box !important;
-moz-box-sizing: border-box !important;
color: #868482 !important;
@@ -1714,7 +1416,7 @@ input.gsc-input {
}
input {
- font-family: 'Open Sans', Arial, Helvetica, sans-serif !important;
+ font-family: 'Titillium Web', Arial, Helvetica, sans-serif !important;
line-height: 1.5 !important;
font-weight: 300 !important;
vertical-align:middle
@@ -1726,9 +1428,34 @@ input:focus {
color: #000;
}
-a.qa-mark:target:before {
- content: "***";
- color: #ff0000;
+.animation {
+ width: 100%;
+ border-style: none;
+ border-width: 0
+}
+
+.player {
+ width: auto;
+ position: relative;
+ display: table;
+ margin-bottom:1.5em;
+}
+
+.playcontrol {
+ display: none;
+ background: url("play_icon.svg") no-repeat center,
+ linear-gradient(
+ rgba(0,0,0,0.15), rgba(0,0,0,0.15)
+ );
+ background-size: 25%;
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ left: 0%;
+ right: 0%;
+ top: 0%;
+ bottom: 0%;
+ margin: auto
}
.mainContent .video {
@@ -1743,6 +1470,7 @@ a.qa-mark:target:before {
padding-top:60%;
display:block
}
+
.mainContent .video iframe {
width:100%;
height:100%;
@@ -1750,3 +1478,67 @@ a.qa-mark:target:before {
top:0;
left:0
}
+
+/* expand/collapse code sections */
+pre input {
+ display:none;
+ visibility:hidden
+}
+pre label {
+ display:block;
+ margin:-3px 3px 0 -16px;
+ text-align:center;
+ color:#21be2b;
+ float:left;
+}
+pre label:hover {
+ color:#fff
+}
+pre label::before {
+ font-weight:600;
+ font-size:16px;
+ content:"+";
+ display:inline-block;
+ width:16px;
+ height:16px
+}
+#ec_expand {
+ height:16px;
+ overflow:hidden;
+ transition:height 0.35s;
+}
+#ec_expand::before {
+ content:"...*/";
+ color:#aaa;
+ background-color:#3a4055;
+ z-index:99 !important;
+ right:25px;
+ position:absolute
+}
+#ec_toggle:checked ~ #ec_expand {
+ height:initial
+}
+#ec_toggle:checked ~ #ec_expand::before {
+ content:""
+}
+#ec_toggle:checked ~ label::before {
+ content:"-"
+}
+
+/* permalinks */
+h2:hover > .plink,
+h3:hover > .plink,
+h4:hover > .plink,
+h5:hover > .plink {
+ opacity:1
+}
+a.plink {
+ opacity: 0;
+ padding-left: 8px;
+ font-size: 0.8em;
+ font-weight: 600;
+ transition: opacity 180ms ease-in-out;
+}
+a.plink::before {
+ content:'\00B6'
+}
diff --git a/doc/src/examples/bearermonitor.qdoc b/doc/src/examples/bearermonitor.qdoc
deleted file mode 100644
index ab68f99a7b..0000000000
--- a/doc/src/examples/bearermonitor.qdoc
+++ /dev/null
@@ -1,35 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE: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 bearermonitor
- \title Bearer Monitor Example
-
- The Bearer Monitor example shows how to use the Bearer Management API.
-
- \image bearermonitor-example.png Screenshot of the Bearer Monitor example
-*/
diff --git a/doc/src/examples/customtypesending.qdoc b/doc/src/examples/customtypesending.qdoc
deleted file mode 100644
index 9fd64b42fd..0000000000
--- a/doc/src/examples/customtypesending.qdoc
+++ /dev/null
@@ -1,121 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE: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 tools/customtypesending
- \title Custom Type Sending Example
-
- The Custom Type Sending example shows how to use a custom type with signals
- and slots.
-
- \image customtypesending-example.png
-
- \section1 Overview
-
- In the \l{Custom Type Example}, we showed how to integrate custom types
- with the meta-object system, enabling them to be stored in QVariant
- objects, written out in debugging information and used in signal-slot
- communication.
-
- In this example, we demonstrate that the preparations made to the
- \c Message class and its declaration with Q_DECLARE_METATYPE() enable it
- to be used with direct signal-slot connections. We do this by creating
- a \c Window class containing signals and slots whose signatures include
- \c Message arguments.
-
- \section1 The Window and Message Class Definitions
-
- We define a simple \c Window class with a signal and public slot that
- allow a \c Message object to be sent via a signal-slot connection:
-
- \snippet examples/tools/customtypesending/window.h Window class definition
-
- The window will contain a text editor to show the contents of a message
- and a push button that the user can click to send a message. To facilitate
- this, we also define the \c sendMessage() slot. We also keep a \c Message
- instance in the \c thisMessage private variable which holds the actual
- message to be sent.
-
- The \c Message class is defined in the following way:
-
- \snippet examples/tools/customtypesending/message.h custom type definition
-
- The type is declared to the meta-type system with the Q_DECLARE_METATYPE()
- macro:
-
- \snippet examples/tools/customtypesending/message.h custom type meta-type declaration
-
- This will make the type available for use in direct signal-slot connections.
-
- \section1 The Window Class Implementation
-
- The \c Window constructor sets up a user interface containing a text
- editor and a push button.
-
- \snippet examples/tools/customtypesending/window.cpp Window constructor
-
- The button's \l{QPushButton::}{clicked()} signal is connected to the
- window's \c{sendMessage()} slot, which emits the \c{messageSent(Message)}
- signal with the \c Message held by the \c thisMessage variable:
-
- \snippet examples/tools/customtypesending/window.cpp sending a message
-
- We implement a slot to allow the message to be received, and this also
- lets us set the message in the window programatically:
-
- \snippet examples/tools/customtypesending/window.cpp receiving a message
-
- In this function, we simply assign the new message to \c thisMessage
- and update the text in the editor.
-
- \section1 Making the Connection
-
- In the example's \c{main()} function, we perform the connection between
- two instances of the \c Window class:
-
- \snippet examples/tools/customtypesending/main.cpp main function
-
- We set the message for the first window and connect the
- \c{messageSent(Message)} signal from each window to the other's
- \c{setMessage(Message)} slot. Since the signals and slots mechanism is only
- concerned with the type, we can simplify the signatures of both the
- signal and slot when we make the connection.
-
- When the user clicks on the \uicontrol{Send message} button in either window,
- the message shown will be emitted in a signal that the other window will
- receive and display.
-
- \section1 Further Reading
-
- Although the custom \c Message type can be used with direct signals and
- slots, an additional registration step needs to be performed if you want
- to use it with queued signal-slot connections. See the
- \l{Queued Custom Type Example} for details.
-
- More information on using custom types with Qt can be found in the
- \l{Creating Custom Qt Types} document.
-*/
diff --git a/doc/src/examples/dbus-chat.qdoc b/doc/src/examples/dbus-chat.qdoc
deleted file mode 100644
index 703d4eef50..0000000000
--- a/doc/src/examples/dbus-chat.qdoc
+++ /dev/null
@@ -1,36 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE: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 dbus/dbus-chat
- \title D-Bus Chat Example
-
- The D-Bus Chat example shows how to use D-Bus to communicate between two
- applications.
-
- \image dbus-chat-example.png
-*/
diff --git a/doc/src/examples/digiflip.qdoc b/doc/src/examples/digiflip.qdoc
deleted file mode 100644
index 174b807a05..0000000000
--- a/doc/src/examples/digiflip.qdoc
+++ /dev/null
@@ -1,31 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE: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 embedded/digiflip
- \title Digiflip
-*/
diff --git a/doc/src/examples/fingerpaint.qdoc b/doc/src/examples/fingerpaint.qdoc
deleted file mode 100644
index 79001ddc7d..0000000000
--- a/doc/src/examples/fingerpaint.qdoc
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE: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 touch/fingerpaint
- \title Finger Paint Example
- \ingroup touchinputexamples
- \brief Shows the use of a touchscreen to make a simple painting application
-
- The Finger Paint example shows the use of a touchscreen with a custom widget
- to create a simple painting application.
-
- \image touch-fingerpaint-example.png
-
- This example was specifically designed to work with a touchscreen, using
- QTouchEvent instead of QMouseEvent to handle user input over the custom
- widget. As a result, it is not possible to draw with the mouse cursor.
-*/
diff --git a/doc/src/examples/flickable.qdoc b/doc/src/examples/flickable.qdoc
deleted file mode 100644
index f289f421c3..0000000000
--- a/doc/src/examples/flickable.qdoc
+++ /dev/null
@@ -1,33 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE: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 embedded/flickable
- \title Flickable List
-
- \image flickable-demo.png
-*/
diff --git a/doc/src/examples/flightinfo.qdoc b/doc/src/examples/flightinfo.qdoc
deleted file mode 100644
index 7e5162eb0e..0000000000
--- a/doc/src/examples/flightinfo.qdoc
+++ /dev/null
@@ -1,33 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE: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 embedded/flightinfo
- \title Flight Info
-
- \image flightinfo-demo.png
-*/
diff --git a/doc/src/examples/htmlinfo.qdoc b/doc/src/examples/htmlinfo.qdoc
deleted file mode 100644
index 8397a28715..0000000000
--- a/doc/src/examples/htmlinfo.qdoc
+++ /dev/null
@@ -1,68 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE: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 xml/htmlinfo
- \title XML HTML Info Example
-
- The XML HTML Info example provides a simple command line utility that
- scans the current directory for HTML files and prints statistics about
- them to standard out.
-
- The files are parsed using a QXmlStreamReader object. If the file does
- not contain a well-formed XML document, a description of the error is
- printed to the standard error console.
-
- \section1 Basic Operation
-
- The main function of the example uses QDir to access files in the current
- directory that match either "*.htm" or "*.html". For each file found,
- the \c parseHtmlFile() function is called.
-
- Reading XML is handled by an instance of the QXmlStreamReader class, which
- operates on the input file object:
-
- \snippet examples/xml/htmlinfo/main.cpp 0
-
- The work of parsing and the XML and extracting statistics is done in a
- while loop, and is driven by input from the reader:
-
- \snippet examples/xml/htmlinfo/main.cpp 1
-
- If more input is available, the next token from the input file is read
- and parsed. The program then looks for the specific element types,
- "title", "a", and "p", and stores information about them.
-
- When there is no more input, the loop terminates. If an error occurred,
- information is written to the standard out file via a stream, and the
- example exits:
-
- \snippet examples/xml/htmlinfo/main.cpp 2
-
- If no error occurred, the example prints some statistics from the data
- gathered in the loop, and then exits.
-*/
diff --git a/doc/src/examples/lightmaps.qdoc b/doc/src/examples/lightmaps.qdoc
deleted file mode 100644
index c9f1fd664f..0000000000
--- a/doc/src/examples/lightmaps.qdoc
+++ /dev/null
@@ -1,33 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE: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 embedded/lightmaps
- \title Light Maps
-
- \image lightmaps-demo.png
-*/
diff --git a/doc/src/examples/pinchzoom.qdoc b/doc/src/examples/pinchzoom.qdoc
deleted file mode 100644
index 077e9c5ee3..0000000000
--- a/doc/src/examples/pinchzoom.qdoc
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE: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 touch/pinchzoom
- \title Pinch Zoom Example
- \ingroup touchinputexamples
- \brief Shows how to recognize a gesture
-
- The Pinch Zoom example shows how to use low-level touch information
- to recognize a gesture.
-
- \image touch-pinchzoom-example.png
-*/
diff --git a/doc/src/examples/raycasting.qdoc b/doc/src/examples/raycasting.qdoc
deleted file mode 100644
index 16c1b7a754..0000000000
--- a/doc/src/examples/raycasting.qdoc
+++ /dev/null
@@ -1,33 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE: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 embedded/raycasting
- \title Ray Casting
-
- \image raycasting-demo.png
-*/
diff --git a/doc/src/examples/rsslisting.qdoc b/doc/src/examples/rsslisting.qdoc
deleted file mode 100644
index 6ca22ce5b5..0000000000
--- a/doc/src/examples/rsslisting.qdoc
+++ /dev/null
@@ -1,36 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE: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 xml/rsslisting
- \title RSS-Listing Example
-
- The RSS-Listing example shows how to create a widget that displays news items
- from RDF news sources.
-
- \image rsslistingexample.png
-*/
diff --git a/doc/src/examples/styleexample.qdoc b/doc/src/examples/styleexample.qdoc
deleted file mode 100644
index 6294800cef..0000000000
--- a/doc/src/examples/styleexample.qdoc
+++ /dev/null
@@ -1,33 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE: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 embedded/styleexample
- \title Embedded Styles
-
- \image styledemo-demo.png
-*/
diff --git a/doc/src/images/gradients-demo.png b/doc/src/images/gradients-demo.png
index d80708e048..4c0959561d 100644
--- a/doc/src/images/gradients-demo.png
+++ b/doc/src/images/gradients-demo.png
Binary files differ
diff --git a/examples/corelib/serialization/cbordump/cbordump.pro b/examples/corelib/serialization/cbordump/cbordump.pro
new file mode 100644
index 0000000000..7fb2ef69f0
--- /dev/null
+++ b/examples/corelib/serialization/cbordump/cbordump.pro
@@ -0,0 +1,14 @@
+QT += core
+QT -= gui
+
+TARGET = cbordump
+CONFIG += console
+CONFIG -= app_bundle
+
+TEMPLATE = app
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/corelib/serialization/cbordump
+INSTALLS += target
+
+SOURCES += main.cpp
diff --git a/examples/corelib/serialization/cbordump/main.cpp b/examples/corelib/serialization/cbordump/main.cpp
new file mode 100644
index 0000000000..222bd43645
--- /dev/null
+++ b/examples/corelib/serialization/cbordump/main.cpp
@@ -0,0 +1,765 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** 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 <QCborStreamReader>
+#include <QCommandLineParser>
+#include <QCommandLineOption>
+#include <QCoreApplication>
+#include <QFile>
+#include <QLocale>
+#include <QStack>
+
+#include <locale.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+/*
+ * To regenerate:
+ * curl -O https://www.iana.org/assignments/cbor-tags/cbor-tags.xml
+ * xsltproc tag-transform.xslt cbor-tags.xml
+ */
+
+// GENERATED CODE
+struct CborTagDescription
+{
+ QCborTag tag;
+ const char *description; // with space and parentheses
+};
+
+// CBOR Tags
+static const CborTagDescription tagDescriptions[] = {
+ // from https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml
+ { QCborTag(0), " (Standard date/time string; see Section 2.4.1 [RFC7049])" },
+ { QCborTag(1), " (Epoch-based date/time; see Section 2.4.1 [RFC7049])" },
+ { QCborTag(2), " (Positive bignum; see Section 2.4.2 [RFC7049])" },
+ { QCborTag(3), " (Negative bignum; see Section 2.4.2 [RFC7049])" },
+ { QCborTag(4), " (Decimal fraction; see Section 2.4.3 [RFC7049])" },
+ { QCborTag(5), " (Bigfloat; see Section 2.4.3 [RFC7049])" },
+ { QCborTag(16), " (COSE Single Recipient Encrypted Data Object [RFC8152])" },
+ { QCborTag(17), " (COSE Mac w/o Recipients Object [RFC8152])" },
+ { QCborTag(18), " (COSE Single Signer Data Object [RFC8152])" },
+ { QCborTag(21), " (Expected conversion to base64url encoding; see Section 2.4.4.2 [RFC7049])" },
+ { QCborTag(22), " (Expected conversion to base64 encoding; see Section 2.4.4.2 [RFC7049])" },
+ { QCborTag(23), " (Expected conversion to base16 encoding; see Section 2.4.4.2 [RFC7049])" },
+ { QCborTag(24), " (Encoded CBOR data item; see Section 2.4.4.1 [RFC7049])" },
+ { QCborTag(25), " (reference the nth previously seen string)" },
+ { QCborTag(26), " (Serialised Perl object with classname and constructor arguments)" },
+ { QCborTag(27), " (Serialised language-independent object with type name and constructor arguments)" },
+ { QCborTag(28), " (mark value as (potentially) shared)" },
+ { QCborTag(29), " (reference nth marked value)" },
+ { QCborTag(30), " (Rational number)" },
+ { QCborTag(32), " (URI; see Section 2.4.4.3 [RFC7049])" },
+ { QCborTag(33), " (base64url; see Section 2.4.4.3 [RFC7049])" },
+ { QCborTag(34), " (base64; see Section 2.4.4.3 [RFC7049])" },
+ { QCborTag(35), " (Regular expression; see Section 2.4.4.3 [RFC7049])" },
+ { QCborTag(36), " (MIME message; see Section 2.4.4.3 [RFC7049])" },
+ { QCborTag(37), " (Binary UUID ( section 4.1.2))" },
+ { QCborTag(38), " (Language-tagged string)" },
+ { QCborTag(39), " (Identifier)" },
+ { QCborTag(61), " (CBOR Web Token (CWT))" },
+ { QCborTag(96), " (COSE Encrypted Data Object [RFC8152])" },
+ { QCborTag(97), " (COSE MACed Data Object [RFC8152])" },
+ { QCborTag(98), " (COSE Signed Data Object [RFC8152])" },
+ { QCborTag(256), " (mark value as having string references)" },
+ { QCborTag(257), " (Binary MIME message)" },
+ { QCborTag(258), " (Mathematical finite set)" },
+ { QCborTag(260), " (Network Address (IPv4 or IPv6 or MAC Address))" },
+ { QCborTag(264), " (Decimal fraction with arbitrary exponent)" },
+ { QCborTag(265), " (Bigfloat with arbitrary exponent)" },
+ { QCborTag(1001), " (extended time)" },
+ { QCborTag(1002), " (duration)" },
+ { QCborTag(1003), " (period)" },
+ { QCborTag(22098), " (hint that indicates an additional level of indirection)" },
+ { QCborTag(55799), " (Self-describe CBOR; see Section 2.4.5 [RFC7049])" },
+ { QCborTag(15309736), " (RAINS Message)" },
+ { QCborTag(-1), nullptr }
+};
+// END GENERATED CODE
+
+enum {
+ // See RFC 7049 section 2.
+ SmallValueBitLength = 5,
+ SmallValueMask = (1 << SmallValueBitLength) - 1, /* 0x1f */
+ Value8Bit = 24,
+ Value16Bit = 25,
+ Value32Bit = 26,
+ Value64Bit = 27
+};
+
+struct CborDumper
+{
+ enum DumpOption {
+ ShowCompact = 0x01,
+ ShowWidthIndicators = 0x02,
+ ShowAnnotated = 0x04
+ };
+ Q_DECLARE_FLAGS(DumpOptions, DumpOption)
+
+ CborDumper(QFile *f, DumpOptions opts_);
+ QCborError dump();
+
+private:
+ void dumpOne(int nestingLevel);
+ void dumpOneDetailed(int nestingLevel);
+
+ void printByteArray(const QByteArray &ba);
+ void printWidthIndicator(quint64 value, char space = '\0');
+ void printStringWidthIndicator(quint64 value);
+
+ QCborStreamReader reader;
+ QByteArray data;
+ QStack<quint8> byteArrayEncoding;
+ qint64 offset = 0;
+ DumpOptions opts;
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(CborDumper::DumpOptions)
+
+static int cborNumberSize(quint64 value)
+{
+ int normalSize = 1;
+ if (value > std::numeric_limits<quint32>::max())
+ normalSize += 8;
+ else if (value > std::numeric_limits<quint16>::max())
+ normalSize += 4;
+ else if (value > std::numeric_limits<quint8>::max())
+ normalSize += 2;
+ else if (value >= Value8Bit)
+ normalSize += 1;
+ return normalSize;
+}
+
+CborDumper::CborDumper(QFile *f, DumpOptions opts_)
+ : opts(opts_)
+{
+ // try to mmap the file, this is faster
+ char *ptr = reinterpret_cast<char *>(f->map(0, f->size(), QFile::MapPrivateOption));
+ if (ptr) {
+ // worked
+ data = QByteArray::fromRawData(ptr, f->size());
+ reader.addData(data);
+ } else if ((opts & ShowAnnotated) || f->isSequential()) {
+ // details requires full contents, so allocate memory
+ data = f->readAll();
+ reader.addData(data);
+ } else {
+ // just use the QIODevice
+ reader.setDevice(f);
+ }
+}
+
+QCborError CborDumper::dump()
+{
+ byteArrayEncoding << quint8(QCborKnownTags::ExpectedBase16);
+ if (!reader.lastError()) {
+ if (opts & ShowAnnotated)
+ dumpOneDetailed(0);
+ else
+ dumpOne(0);
+ }
+
+ QCborError err = reader.lastError();
+ offset = reader.currentOffset();
+ if (err) {
+ fflush(stdout);
+ fprintf(stderr, "cbordump: decoding failed at %lld: %s\n",
+ offset, qPrintable(err.toString()));
+ if (!data.isEmpty())
+ fprintf(stderr, " bytes at %lld: %s\n", offset,
+ data.mid(offset, 9).toHex(' ').constData());
+ } else {
+ if (!opts.testFlag(ShowAnnotated))
+ printf("\n");
+ if (offset < data.size() || (reader.device() && reader.device()->bytesAvailable()))
+ fprintf(stderr, "Warning: bytes remaining at the end of the CBOR stream\n");
+ }
+
+ return err;
+}
+
+template <typename T> static inline bool canConvertTo(double v)
+{
+ // The [conv.fpint] (7.10 Floating-integral conversions) section of the
+ // standard says only exact conversions are guaranteed. Converting
+ // integrals to floating-point with loss of precision has implementation-
+ // defined behavior whether the next higher or next lower is returned;
+ // converting FP to integral is UB if it can't be represented.;
+ Q_STATIC_ASSERT(std::numeric_limits<T>::is_integer);
+
+ double supremum = ldexp(1, std::numeric_limits<T>::digits);
+ if (v >= supremum)
+ return false;
+
+ if (v < std::numeric_limits<T>::min()) // either zero or a power of two, so it's exact
+ return false;
+
+ // we're in range
+ return v == floor(v);
+}
+
+static QString fpToString(double v, const char *suffix)
+{
+ if (qIsInf(v))
+ return v < 0 ? QStringLiteral("-inf") : QStringLiteral("inf");
+ if (qIsNaN(v))
+ return QStringLiteral("nan");
+ if (canConvertTo<qint64>(v))
+ return QString::number(qint64(v)) + ".0" + suffix;
+ if (canConvertTo<quint64>(v))
+ return QString::number(quint64(v)) + ".0" + suffix;
+
+ QString s = QString::number(v, 'g', QLocale::FloatingPointShortest);
+ if (!s.contains('.') && !s.contains('e'))
+ s += '.';
+ s += suffix;
+ return s;
+};
+
+void CborDumper::dumpOne(int nestingLevel)
+{
+ QString indent(1, QLatin1Char(' '));
+ QString indented = indent;
+ if (!opts.testFlag(ShowCompact)) {
+ indent = QLatin1Char('\n') + QString(4 * nestingLevel, QLatin1Char(' '));
+ indented = QLatin1Char('\n') + QString(4 + 4 * nestingLevel, QLatin1Char(' '));
+ }
+
+ switch (reader.type()) {
+ case QCborStreamReader::UnsignedInteger: {
+ quint64 u = reader.toUnsignedInteger();
+ printf("%llu", u);
+ reader.next();
+ printWidthIndicator(u);
+ return;
+ }
+
+ case QCborStreamReader::NegativeInteger: {
+ quint64 n = quint64(reader.toNegativeInteger());
+ if (n == 0) // -2^64 (wrapped around)
+ printf("-18446744073709551616");
+ else
+ printf("-%llu", n);
+ reader.next();
+ printWidthIndicator(n);
+ return;
+ }
+
+ case QCborStreamReader::ByteArray:
+ case QCborStreamReader::String: {
+ bool isLengthKnown = reader.isLengthKnown();
+ if (!isLengthKnown) {
+ printf("(_ ");
+ ++offset;
+ }
+
+ QString comma;
+ if (reader.isByteArray()) {
+ auto r = reader.readByteArray();
+ while (r.status == QCborStreamReader::Ok) {
+ printf("%s", qPrintable(comma));
+ printByteArray(r.data);
+ printStringWidthIndicator(r.data.size());
+
+ r = reader.readByteArray();
+ comma = QLatin1Char(',') + indented;
+ }
+ } else {
+ auto r = reader.readString();
+ while (r.status == QCborStreamReader::Ok) {
+ printf("%s\"%s\"", qPrintable(comma), qPrintable(r.data));
+ printStringWidthIndicator(r.data.toUtf8().size());
+
+ r = reader.readString();
+ comma = QLatin1Char(',') + indented;
+ }
+ }
+
+ if (!isLengthKnown && !reader.lastError())
+ printf(")");
+ break;
+ }
+
+ case QCborStreamReader::Array:
+ case QCborStreamReader::Map: {
+ const char *delimiters = (reader.isArray() ? "[]" : "{}");
+ printf("%c", delimiters[0]);
+
+ if (reader.isLengthKnown()) {
+ quint64 len = reader.length();
+ reader.enterContainer();
+ printWidthIndicator(len, ' ');
+ } else {
+ reader.enterContainer();
+ offset = reader.currentOffset();
+ printf("_ ");
+ }
+
+ const char *comma = "";
+ while (!reader.lastError() && reader.hasNext()) {
+ printf("%s%s", comma, qPrintable(indented));
+ comma = ",";
+ dumpOne(nestingLevel + 1);
+
+ if (reader.parentContainerType() != QCborStreamReader::Map)
+ continue;
+ if (reader.lastError())
+ break;
+ printf(": ");
+ dumpOne(nestingLevel + 1);
+ }
+
+ if (!reader.lastError()) {
+ reader.leaveContainer();
+ printf("%s%c", qPrintable(indent), delimiters[1]);
+ }
+ break;
+ }
+
+ case QCborStreamReader::Tag: {
+ QCborTag tag = reader.toTag();
+ printf("%llu", quint64(tag));
+
+ if (tag == QCborKnownTags::ExpectedBase16 || tag == QCborKnownTags::ExpectedBase64
+ || tag == QCborKnownTags::ExpectedBase64url)
+ byteArrayEncoding.push(quint8(tag));
+
+ if (reader.next()) {
+ printWidthIndicator(quint64(tag));
+ printf("(");
+ dumpOne(nestingLevel); // same level!
+ printf(")");
+ }
+
+ if (tag == QCborKnownTags::ExpectedBase16 || tag == QCborKnownTags::ExpectedBase64
+ || tag == QCborKnownTags::ExpectedBase64url)
+ byteArrayEncoding.pop();
+ break;
+ }
+
+ case QCborStreamReader::SimpleType:
+ switch (reader.toSimpleType()) {
+ case QCborSimpleType::False:
+ printf("false");
+ break;
+ case QCborSimpleType::True:
+ printf("true");
+ break;
+ case QCborSimpleType::Null:
+ printf("null");
+ break;
+ case QCborSimpleType::Undefined:
+ printf("undefined");
+ break;
+ default:
+ printf("simple(%u)", quint8(reader.toSimpleType()));
+ break;
+ }
+ reader.next();
+ break;
+
+ case QCborStreamReader::Float16:
+ printf("%s", qPrintable(fpToString(reader.toFloat16(), "f16")));
+ reader.next();
+ break;
+ case QCborStreamReader::Float:
+ printf("%s", qPrintable(fpToString(reader.toFloat(), "f")));
+ reader.next();
+ break;
+ case QCborStreamReader::Double:
+ printf("%s", qPrintable(fpToString(reader.toDouble(), "")));
+ reader.next();
+ break;
+ case QCborStreamReader::Invalid:
+ return;
+ }
+
+ offset = reader.currentOffset();
+}
+
+void CborDumper::dumpOneDetailed(int nestingLevel)
+{
+ auto tagDescription = [](QCborTag tag) {
+ for (auto entry : tagDescriptions) {
+ if (entry.tag == tag)
+ return entry.description;
+ if (entry.tag > tag)
+ break;
+ }
+ return "";
+ };
+ auto printOverlong = [](int actualSize, quint64 value) {
+ if (cborNumberSize(value) != actualSize)
+ printf(" (overlong)");
+ };
+ auto print = [=](const char *descr, const char *fmt, ...) {
+ qint64 prevOffset = offset;
+ offset = reader.currentOffset();
+ if (prevOffset == offset)
+ return;
+
+ QByteArray bytes = data.mid(prevOffset, offset - prevOffset);
+ QByteArray indent(nestingLevel * 2, ' ');
+ printf("%-50s # %s ", (indent + bytes.toHex(' ')).constData(), descr);
+
+ va_list va;
+ va_start(va, fmt);
+ vprintf(fmt, va);
+ va_end(va);
+
+ if (strstr(fmt, "%ll")) {
+ // Only works because all callers below that use %ll, use it as the
+ // first arg
+ va_start(va, fmt);
+ quint64 value = va_arg(va, quint64);
+ va_end(va);
+ printOverlong(bytes.size(), value);
+ }
+
+ puts("");
+ };
+
+ auto printFp = [=](const char *descr, double d) {
+ QString s = fpToString(d, "");
+ if (s.size() <= 6)
+ return print(descr, "%s", qPrintable(s));
+ return print(descr, "%a", d);
+ };
+
+ auto printString = [=](const char *descr) {
+ QByteArray indent(nestingLevel * 2, ' ');
+ const char *chunkStr = (reader.isLengthKnown() ? "" : "chunk ");
+ int width = 48 - indent.size();
+ int bytesPerLine = qMax(width / 3, 5);
+
+ qsizetype size = reader.currentStringChunkSize();
+ if (size < 0)
+ return; // error
+ if (size >= std::numeric_limits<int>::max()) {
+ fprintf(stderr, "String length too big, %lli\n", qint64(size));
+ exit(EXIT_FAILURE);
+ }
+
+ // if asking for the current string chunk changes the offset, then it
+ // was chunked
+ print(descr, "(indeterminate length)");
+
+ QByteArray bytes(size, Qt::Uninitialized);
+ auto r = reader.readStringChunk(bytes.data(), bytes.size());
+ while (r.status == QCborStreamReader::Ok) {
+ // We'll have to decode the length's width directly from CBOR...
+ const char *lenstart = data.constData() + offset;
+ const char *lenend = lenstart + 1;
+ quint8 additionalInformation = (*lenstart & SmallValueMask);
+
+ // Decode this number directly from CBOR (see RFC 7049 section 2)
+ if (additionalInformation >= Value8Bit) {
+ if (additionalInformation == Value8Bit)
+ lenend += 1;
+ else if (additionalInformation == Value16Bit)
+ lenend += 2;
+ else if (additionalInformation == Value32Bit)
+ lenend += 4;
+ else
+ lenend += 8;
+ }
+
+ {
+ QByteArray lenbytes = QByteArray::fromRawData(lenstart, lenend - lenstart);
+ printf("%-50s # %s %slength %llu",
+ (indent + lenbytes.toHex(' ')).constData(), descr, chunkStr, quint64(size));
+ printOverlong(lenbytes.size(), size);
+ puts("");
+ }
+
+ offset = reader.currentOffset();
+
+ for (int i = 0; i < r.data; i += bytesPerLine) {
+ QByteArray section = bytes.mid(i, bytesPerLine);
+ printf(" %s%s", indent.constData(), section.toHex(' ').constData());
+
+ // print the decode
+ QByteArray spaces(width > 0 ? width - section.size() * 3 + 1: 0, ' ');
+ printf("%s # \"", spaces.constData());
+ auto ptr = reinterpret_cast<const uchar *>(section.constData());
+ for (int j = 0; j < section.size(); ++j)
+ printf("%c", ptr[j] >= 0x80 || ptr[j] < 0x20 ? '.' : ptr[j]);
+
+ puts("\"");
+ }
+
+ // get the next chunk
+ size = reader.currentStringChunkSize();
+ if (size < 0)
+ return; // error
+ if (size >= std::numeric_limits<int>::max()) {
+ fprintf(stderr, "String length too big, %lli\n", qint64(size));
+ exit(EXIT_FAILURE);
+ }
+ bytes.resize(size);
+ r = reader.readStringChunk(bytes.data(), bytes.size());
+ }
+ };
+
+ if (reader.lastError())
+ return;
+
+ switch (reader.type()) {
+ case QCborStreamReader::UnsignedInteger: {
+ quint64 u = reader.toUnsignedInteger();
+ reader.next();
+ if (u < 65536 || (u % 100000) == 0)
+ print("Unsigned integer", "%llu", u);
+ else
+ print("Unsigned integer", "0x%llx", u);
+ return;
+ }
+
+ case QCborStreamReader::NegativeInteger: {
+ quint64 n = quint64(reader.toNegativeInteger());
+ reader.next();
+ print("Negative integer", n == 0 ? "-18446744073709551616" : "-%llu", n);
+ return;
+ }
+
+ case QCborStreamReader::ByteArray:
+ case QCborStreamReader::String: {
+ bool isLengthKnown = reader.isLengthKnown();
+ const char *descr = (reader.isString() ? "Text string" : "Byte string");
+ if (!isLengthKnown)
+ ++nestingLevel;
+
+ printString(descr);
+ if (reader.lastError())
+ return;
+
+ if (!isLengthKnown) {
+ --nestingLevel;
+ print("Break", "");
+ }
+ break;
+ }
+
+ case QCborStreamReader::Array:
+ case QCborStreamReader::Map: {
+ const char *descr = (reader.isArray() ? "Array" : "Map");
+ if (reader.isLengthKnown()) {
+ quint64 len = reader.length();
+ reader.enterContainer();
+ print(descr, "length %llu", len);
+ } else {
+ reader.enterContainer();
+ print(descr, "(indeterminate length)");
+ }
+
+ while (!reader.lastError() && reader.hasNext())
+ dumpOneDetailed(nestingLevel + 1);
+
+ if (!reader.lastError()) {
+ reader.leaveContainer();
+ print("Break", "");
+ }
+ break;
+ }
+
+ case QCborStreamReader::Tag: {
+ QCborTag tag = reader.toTag();
+ reader.next();
+ print("Tag", "%llu%s", quint64(tag), tagDescription(tag));
+ dumpOneDetailed(nestingLevel + 1);
+ break;
+ }
+
+ case QCborStreamReader::SimpleType: {
+ QCborSimpleType st = reader.toSimpleType();
+ reader.next();
+ switch (st) {
+ case QCborSimpleType::False:
+ print("Simple Type", "false");
+ break;
+ case QCborSimpleType::True:
+ print("Simple Type", "true");
+ break;
+ case QCborSimpleType::Null:
+ print("Simple Type", "null");
+ break;
+ case QCborSimpleType::Undefined:
+ print("Simple Type", "undefined");
+ break;
+ default:
+ print("Simple Type", "%u", quint8(st));
+ break;
+ }
+ break;
+ }
+
+ case QCborStreamReader::Float16: {
+ double d = reader.toFloat16();
+ reader.next();
+ printFp("Float16", d);
+ break;
+ }
+ case QCborStreamReader::Float: {
+ double d = reader.toFloat();
+ reader.next();
+ printFp("Float", d);
+ break;
+ }
+ case QCborStreamReader::Double: {
+ double d = reader.toDouble();
+ reader.next();
+ printFp("Double", d);
+ break;
+ }
+ case QCborStreamReader::Invalid:
+ return;
+ }
+
+ offset = reader.currentOffset();
+}
+
+void CborDumper::printByteArray(const QByteArray &ba)
+{
+ switch (byteArrayEncoding.top()) {
+ default:
+ printf("h'%s'", ba.toHex(' ').constData());
+ break;
+
+ case quint8(QCborKnownTags::ExpectedBase64):
+ printf("b64'%s'", ba.toBase64().constData());
+ break;
+
+ case quint8(QCborKnownTags::ExpectedBase64url):
+ printf("b64'%s'", ba.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals).constData());
+ break;
+ }
+}
+
+void printIndicator(quint64 value, qint64 previousOffset, qint64 offset, char space)
+{
+ int normalSize = cborNumberSize(value);
+ int actualSize = offset - previousOffset;
+
+ if (actualSize != normalSize) {
+ Q_ASSERT(actualSize > 1);
+ actualSize -= 2;
+ printf("_%d", qPopulationCount(uint(actualSize)));
+ if (space)
+ printf("%c", space);
+ }
+}
+
+void CborDumper::printWidthIndicator(quint64 value, char space)
+{
+ qint64 previousOffset = offset;
+ offset = reader.currentOffset();
+ if (opts & ShowWidthIndicators)
+ printIndicator(value, previousOffset, offset, space);
+}
+
+void CborDumper::printStringWidthIndicator(quint64 value)
+{
+ qint64 previousOffset = offset;
+ offset = reader.currentOffset();
+ if (opts & ShowWidthIndicators)
+ printIndicator(value, previousOffset, offset - uint(value), '\0');
+}
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication app(argc, argv);
+ setlocale(LC_ALL, "C");
+
+ QCommandLineParser parser;
+ parser.setApplicationDescription(QStringLiteral("CBOR Dumper tool"));
+ parser.addHelpOption();
+
+ QCommandLineOption compact({QStringLiteral("c"), QStringLiteral("compact")},
+ QStringLiteral("Use compact form (no line breaks)"));
+ parser.addOption(compact);
+
+ QCommandLineOption showIndicators({QStringLiteral("i"), QStringLiteral("indicators")},
+ QStringLiteral("Show indicators for width of lengths and integrals"));
+ parser.addOption(showIndicators);
+
+ QCommandLineOption verbose({QStringLiteral("a"), QStringLiteral("annotated")},
+ QStringLiteral("Show bytes and annotated decoding"));
+ parser.addOption(verbose);
+
+ parser.addPositionalArgument(QStringLiteral("[source]"),
+ QStringLiteral("CBOR file to read from"));
+
+ parser.process(app);
+
+ CborDumper::DumpOptions opts;
+ if (parser.isSet(compact))
+ opts |= CborDumper::ShowCompact;
+ if (parser.isSet(showIndicators))
+ opts |= CborDumper::ShowWidthIndicators;
+ if (parser.isSet(verbose))
+ opts |= CborDumper::ShowAnnotated;
+
+ QStringList files = parser.positionalArguments();
+ if (files.isEmpty())
+ files << "-";
+ for (const QString &file : qAsConst(files)) {
+ QFile f(file);
+ if (file == "-" ? f.open(stdin, QIODevice::ReadOnly) : f.open(QIODevice::ReadOnly)) {
+ if (files.size() > 1)
+ printf("/ From \"%s\" /\n", qPrintable(file));
+
+ CborDumper dumper(&f, opts);
+ QCborError err = dumper.dump();
+ if (err)
+ return EXIT_FAILURE;
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/examples/corelib/serialization/cbordump/tag-transform.xslt b/examples/corelib/serialization/cbordump/tag-transform.xslt
new file mode 100644
index 0000000000..3cc1b9b293
--- /dev/null
+++ b/examples/corelib/serialization/cbordump/tag-transform.xslt
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:a="http://www.iana.org/assignments" xmlns="http://www.iana.org/assignments" xmlns:_="http://www.iana.org/assignments" xmlns:DEFAULT="http://www.iana.org/assignments" version="1.0">
+<xsl:output omit-xml-declaration="yes" indent="no" method="text"/>
+<xsl:template match="/a:registry[@id='cbor-tags']">struct CborTagDescription
+{
+ QCborTag tag;
+ const char *description; // with space and parentheses
+};
+
+// <xsl:value-of select="a:registry/a:title"/>
+static const CborTagDescription tagDescriptions[] = {
+ // from https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml
+<xsl:for-each select="a:registry/a:record">
+ <xsl:sort select="a:value" data-type="number"/>
+ <xsl:if test="a:semantics != ''">
+ <xsl:call-template name="row"/>
+ </xsl:if>
+ </xsl:for-each> { QCborTag(-1), nullptr }
+};
+</xsl:template>
+<xsl:template name="row"> { QCborTag(<xsl:value-of select="a:value"/>), " (<xsl:value-of select="a:semantics"/> <xsl:call-template name="xref"/>)" },
+</xsl:template>
+<xsl:template name="xref"><xsl:if test="a:xref/@type = 'rfc'"> [<xsl:value-of select="translate(a:xref/@data,'rfc','RFC')"/>]</xsl:if>
+</xsl:template>
+</xsl:stylesheet>
diff --git a/examples/corelib/serialization/convert/cborconverter.cpp b/examples/corelib/serialization/convert/cborconverter.cpp
new file mode 100644
index 0000000000..41724c935e
--- /dev/null
+++ b/examples/corelib/serialization/convert/cborconverter.cpp
@@ -0,0 +1,393 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** 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 "cborconverter.h"
+
+#include <QCborStreamReader>
+#include <QCborStreamWriter>
+#include <QCborMap>
+#include <QCborArray>
+#include <QCborValue>
+#include <QDataStream>
+#include <QDebug>
+#include <QFloat16>
+#include <QFile>
+#include <QMetaType>
+#include <QTextStream>
+
+#include <stdio.h>
+
+static CborConverter cborConverter;
+static CborDiagnosticDumper cborDiagnosticDumper;
+
+static const char optionHelp[] =
+ "convert-float-to-int=yes|no Write integers instead of floating point, if no\n"
+ " loss of precision occurs on conversion.\n"
+ "float16=yes|always|no Write using half-precision floating point.\n"
+ " If 'always', won't check for loss of precision.\n"
+ "float32=yes|always|no Write using single-precision floating point.\n"
+ " If 'always', won't check for loss of precision.\n"
+ "signature=yes|no Prepend the CBOR signature to the file output.\n"
+ ;
+
+static const char diagnosticHelp[] =
+ "extended=no|yes Use extended CBOR diagnostic format.\n"
+ "line-wrap=yes|no Split output into multiple lines.\n"
+ ;
+
+QT_BEGIN_NAMESPACE
+
+QDataStream &operator<<(QDataStream &ds, QCborSimpleType st)
+{
+ return ds << quint8(st);
+}
+
+QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st)
+{
+ quint8 v;
+ ds >> v;
+ st = QCborSimpleType(v);
+ return ds;
+}
+
+QDataStream &operator<<(QDataStream &ds, QCborTag tag)
+{
+ return ds << quint64(tag);
+}
+
+QDataStream &operator>>(QDataStream &ds, QCborTag &tag)
+{
+ quint64 v;
+ ds >> v;
+ tag = QCborTag(v);
+ return ds;
+}
+
+QT_END_NAMESPACE
+
+// We can't use QCborValue::toVariant directly because that would destroy
+// non-string keys in CBOR maps (QVariantMap can't handle those). Instead, we
+// have our own set of converter functions so we can keep the keys properly.
+
+static QVariant convertCborValue(const QCborValue &value);
+
+static QVariant convertCborMap(const QCborMap &map)
+{
+ VariantOrderedMap result;
+ result.reserve(map.size());
+ for (auto pair : map)
+ result.append({ convertCborValue(pair.first), convertCborValue(pair.second) });
+ return QVariant::fromValue(result);
+}
+
+static QVariant convertCborArray(const QCborArray &array)
+{
+ QVariantList result;
+ result.reserve(array.size());
+ for (auto value : array)
+ result.append(convertCborValue(value));
+ return result;
+}
+
+static QVariant convertCborValue(const QCborValue &value)
+{
+ if (value.isArray())
+ return convertCborArray(value.toArray());
+ if (value.isMap())
+ return convertCborMap(value.toMap());
+ return value.toVariant();
+}
+
+enum TrimFloatingPoint { Double, Float, Float16 };
+static QCborValue convertFromVariant(const QVariant &v, TrimFloatingPoint fpTrimming)
+{
+ if (v.userType() == QVariant::List) {
+ const QVariantList list = v.toList();
+ QCborArray array;
+ for (const QVariant &v : list)
+ array.append(convertFromVariant(v, fpTrimming));
+
+ return array;
+ }
+
+ if (v.userType() == qMetaTypeId<VariantOrderedMap>()) {
+ const auto m = v.value<VariantOrderedMap>();
+ QCborMap map;
+ for (const auto &pair : m)
+ map.insert(convertFromVariant(pair.first, fpTrimming),
+ convertFromVariant(pair.second, fpTrimming));
+ return map;
+ }
+
+ if (v.userType() == QVariant::Double && fpTrimming != Double) {
+ float f = float(v.toDouble());
+ if (fpTrimming == Float16)
+ return float(qfloat16(f));
+ return f;
+ }
+
+ return QCborValue::fromVariant(v);
+}
+
+QString CborDiagnosticDumper::name()
+{
+ return QStringLiteral("cbor-dump");
+}
+
+Converter::Direction CborDiagnosticDumper::directions()
+{
+ return Out;
+}
+
+Converter::Options CborDiagnosticDumper::outputOptions()
+{
+ return SupportsArbitraryMapKeys;
+}
+
+const char *CborDiagnosticDumper::optionsHelp()
+{
+ return diagnosticHelp;
+}
+
+bool CborDiagnosticDumper::probeFile(QIODevice *f)
+{
+ Q_UNUSED(f);
+ return false;
+}
+
+QVariant CborDiagnosticDumper::loadFile(QIODevice *f, Converter *&outputConverter)
+{
+ Q_UNREACHABLE();
+ Q_UNUSED(f);
+ Q_UNUSED(outputConverter);
+ return QVariant();
+}
+
+void CborDiagnosticDumper::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options)
+{
+ QCborValue::DiagnosticNotationOptions opts = QCborValue::LineWrapped;
+ for (const QString &s : options) {
+ QStringList pair = s.split('=');
+ if (pair.size() == 2) {
+ if (pair.first() == "line-wrap") {
+ opts &= ~QCborValue::LineWrapped;
+ if (pair.last() == "yes") {
+ opts |= QCborValue::LineWrapped;
+ continue;
+ } else if (pair.last() == "no") {
+ continue;
+ }
+ }
+ if (pair.first() == "extended") {
+ opts &= ~QCborValue::ExtendedFormat;
+ if (pair.last() == "yes")
+ opts |= QCborValue::ExtendedFormat;
+ continue;
+ }
+ }
+
+ fprintf(stderr, "Unknown CBOR diagnostic option '%s'. Available options are:\n%s",
+ qPrintable(s), diagnosticHelp);
+ exit(EXIT_FAILURE);
+ }
+
+ QTextStream out(f);
+ out << convertFromVariant(contents, Double).toDiagnosticNotation(opts)
+ << endl;
+}
+
+CborConverter::CborConverter()
+{
+ qRegisterMetaType<QCborTag>();
+ qRegisterMetaTypeStreamOperators<QCborTag>();
+ QMetaType::registerDebugStreamOperator<QCborTag>();
+}
+
+QString CborConverter::name()
+{
+ return "cbor";
+}
+
+Converter::Direction CborConverter::directions()
+{
+ return InOut;
+}
+
+Converter::Options CborConverter::outputOptions()
+{
+ return SupportsArbitraryMapKeys;
+}
+
+const char *CborConverter::optionsHelp()
+{
+ return optionHelp;
+}
+
+bool CborConverter::probeFile(QIODevice *f)
+{
+ if (QFile *file = qobject_cast<QFile *>(f)) {
+ if (file->fileName().endsWith(QLatin1String(".cbor")))
+ return true;
+ }
+ return f->isReadable() && f->peek(3) == QByteArray("\xd9\xd9\xf7", 3);
+}
+
+QVariant CborConverter::loadFile(QIODevice *f, Converter *&outputConverter)
+{
+ const char *ptr = nullptr;
+ if (auto file = qobject_cast<QFile *>(f))
+ ptr = reinterpret_cast<char *>(file->map(0, file->size()));
+
+ QByteArray mapped = QByteArray::fromRawData(ptr, ptr ? f->size() : 0);
+ QCborStreamReader reader(mapped);
+ if (!ptr)
+ reader.setDevice(f);
+
+ if (reader.isTag() && reader.toTag() == QCborKnownTags::Signature)
+ reader.next();
+
+ QCborValue contents = QCborValue::fromCbor(reader);
+ qint64 offset = reader.currentOffset();
+ if (reader.lastError()) {
+ fprintf(stderr, "Error loading CBOR contents (byte %lld): %s\n", offset,
+ qPrintable(reader.lastError().toString()));
+ fprintf(stderr, " bytes: %s\n",
+ (ptr ? mapped.mid(offset, 9) : f->read(9)).toHex(' ').constData());
+ exit(EXIT_FAILURE);
+ } else if (offset < mapped.size() || (!ptr && f->bytesAvailable())) {
+ fprintf(stderr, "Warning: bytes remaining at the end of the CBOR stream\n");
+ }
+
+ if (outputConverter == nullptr)
+ outputConverter = &cborDiagnosticDumper;
+ else if (outputConverter == null)
+ return QVariant();
+ else if (!outputConverter->outputOptions().testFlag(SupportsArbitraryMapKeys))
+ return contents.toVariant();
+ return convertCborValue(contents);
+}
+
+void CborConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options)
+{
+ bool useSignature = true;
+ bool useIntegers = true;
+ enum { Yes, No, Always } useFloat16 = Yes, useFloat = Yes;
+
+ for (const QString &s : options) {
+ QStringList pair = s.split('=');
+ if (pair.size() == 2) {
+ if (pair.first() == "convert-float-to-int") {
+ if (pair.last() == "yes") {
+ useIntegers = true;
+ continue;
+ } else if (pair.last() == "no") {
+ useIntegers = false;
+ continue;
+ }
+ }
+
+ if (pair.first() == "float16") {
+ if (pair.last() == "no") {
+ useFloat16 = No;
+ continue;
+ } else if (pair.last() == "yes") {
+ useFloat16 = Yes;
+ continue;
+ } else if (pair.last() == "always") {
+ useFloat16 = Always;
+ continue;
+ }
+ }
+
+ if (pair.first() == "float32") {
+ if (pair.last() == "no") {
+ useFloat = No;
+ continue;
+ } else if (pair.last() == "yes") {
+ useFloat = Yes;
+ continue;
+ } else if (pair.last() == "always") {
+ useFloat = Always;
+ continue;
+ }
+ }
+
+ if (pair.first() == "signature") {
+ if (pair.last() == "yes") {
+ useSignature = true;
+ continue;
+ } else if (pair.last() == "no") {
+ useSignature = false;
+ continue;
+ }
+ }
+ }
+
+ fprintf(stderr, "Unknown CBOR format option '%s'. Valid options are:\n%s",
+ qPrintable(s), optionHelp);
+ exit(EXIT_FAILURE);
+ }
+
+ QCborValue v = convertFromVariant(contents,
+ useFloat16 == Always ? Float16 : useFloat == Always ? Float : Double);
+ QCborStreamWriter writer(f);
+ if (useSignature)
+ writer.append(QCborKnownTags::Signature);
+
+ QCborValue::EncodingOptions opts;
+ if (useIntegers)
+ opts |= QCborValue::UseIntegers;
+ if (useFloat != No)
+ opts |= QCborValue::UseFloat;
+ if (useFloat16 != No)
+ opts |= QCborValue::UseFloat16;
+ v.toCbor(writer, opts);
+}
+
diff --git a/examples/corelib/serialization/convert/cborconverter.h b/examples/corelib/serialization/convert/cborconverter.h
new file mode 100644
index 0000000000..f0a89cb141
--- /dev/null
+++ b/examples/corelib/serialization/convert/cborconverter.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** 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$
+**
+****************************************************************************/
+
+#ifndef CBORCONVERTER_H
+#define CBORCONVERTER_H
+
+#include "converter.h"
+
+class CborDiagnosticDumper : public Converter
+{
+ // Converter interface
+public:
+ QString name() override;
+ Direction directions() override;
+ Options outputOptions() override;
+ const char *optionsHelp() override;
+ bool probeFile(QIODevice *f) override;
+ QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
+ void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
+};
+
+class CborConverter : public Converter
+{
+public:
+ CborConverter();
+
+ // Converter interface
+public:
+ QString name() override;
+ Direction directions() override;
+ Options outputOptions() override;
+ const char *optionsHelp() override;
+ bool probeFile(QIODevice *f) override;
+ QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
+ void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
+};
+
+#endif // CBORCONVERTER_H
diff --git a/examples/corelib/serialization/convert/convert.pro b/examples/corelib/serialization/convert/convert.pro
new file mode 100644
index 0000000000..d9b1de41e3
--- /dev/null
+++ b/examples/corelib/serialization/convert/convert.pro
@@ -0,0 +1,29 @@
+QT += core
+QT -= gui
+
+TARGET = convert
+CONFIG += console
+CONFIG -= app_bundle
+
+TEMPLATE = app
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/corelib/serialization/convert
+INSTALLS += target
+
+SOURCES += main.cpp \
+ cborconverter.cpp \
+ jsonconverter.cpp \
+ datastreamconverter.cpp \
+ textconverter.cpp \
+ xmlconverter.cpp \
+ nullconverter.cpp
+
+HEADERS += \
+ converter.h \
+ cborconverter.h \
+ jsonconverter.h \
+ datastreamconverter.h \
+ textconverter.h \
+ xmlconverter.h \
+ nullconverter.h
diff --git a/examples/corelib/serialization/convert/converter.h b/examples/corelib/serialization/convert/converter.h
new file mode 100644
index 0000000000..82e1fa1cb3
--- /dev/null
+++ b/examples/corelib/serialization/convert/converter.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** 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$
+**
+****************************************************************************/
+
+#ifndef CONVERTER_H
+#define CONVERTER_H
+
+#include <QIODevice>
+#include <QPair>
+#include <QVariant>
+#include <QVector>
+
+class VariantOrderedMap : public QVector<QPair<QVariant, QVariant>>
+{
+public:
+ VariantOrderedMap() = default;
+ VariantOrderedMap(const QVariantMap &map)
+ {
+ reserve(map.size());
+ for (auto it = map.begin(); it != map.end(); ++it)
+ append({it.key(), it.value()});
+ }
+};
+using Map = VariantOrderedMap;
+Q_DECLARE_METATYPE(Map)
+
+class Converter
+{
+protected:
+ Converter();
+
+public:
+ static Converter *null;
+
+ enum Direction {
+ In = 1, Out = 2, InOut = 3
+ };
+
+ enum Option {
+ SupportsArbitraryMapKeys = 0x01
+ };
+ Q_DECLARE_FLAGS(Options, Option)
+
+ virtual ~Converter() = 0;
+
+ virtual QString name() = 0;
+ virtual Direction directions() = 0;
+ virtual Options outputOptions() = 0;
+ virtual const char *optionsHelp() = 0;
+ virtual bool probeFile(QIODevice *f) = 0;
+ virtual QVariant loadFile(QIODevice *f, Converter *&outputConverter) = 0;
+ virtual void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) = 0;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(Converter::Options)
+
+#endif // CONVERTER_H
diff --git a/examples/corelib/serialization/convert/datastreamconverter.cpp b/examples/corelib/serialization/convert/datastreamconverter.cpp
new file mode 100644
index 0000000000..7cdb844141
--- /dev/null
+++ b/examples/corelib/serialization/convert/datastreamconverter.cpp
@@ -0,0 +1,273 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** 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 "datastreamconverter.h"
+
+#include <QDataStream>
+#include <QDebug>
+#include <QTextStream>
+
+static const char optionHelp[] =
+ "byteorder=host|big|little Byte order to use.\n"
+ "version=<n> QDataStream version (default: Qt 5.0).\n"
+ ;
+
+static const char signature[] = "qds";
+
+static DataStreamDumper dataStreamDumper;
+static DataStreamConverter DataStreamConverter;
+
+QDataStream &operator<<(QDataStream &ds, const VariantOrderedMap &map)
+{
+ ds << qint64(map.size());
+ for (const auto &pair : map)
+ ds << pair.first << pair.second;
+ return ds;
+}
+
+QDataStream &operator>>(QDataStream &ds, VariantOrderedMap &map)
+{
+ map.clear();
+
+ qint64 size;
+ ds >> size;
+ map.reserve(size);
+
+ while (size-- > 0) {
+ VariantOrderedMap::value_type pair;
+ ds >> pair.first >> pair.second;
+ map.append(pair);
+ }
+
+ return ds;
+}
+
+
+static QString dumpVariant(const QVariant &v, const QString &indent = QLatin1String("\n"))
+{
+ QString result;
+ QString indented = indent + QLatin1String(" ");
+
+ int type = v.userType();
+ if (type == qMetaTypeId<VariantOrderedMap>() || type == QVariant::Map) {
+ const auto map = (type == QVariant::Map) ?
+ VariantOrderedMap(v.toMap()) : v.value<VariantOrderedMap>();
+
+ result = QLatin1String("Map {");
+ for (const auto &pair : map) {
+ result += indented + dumpVariant(pair.first, indented);
+ result.chop(1); // remove comma
+ result += QLatin1String(" => ") + dumpVariant(pair.second, indented);
+
+ }
+ result.chop(1); // remove comma
+ result += indent + QLatin1String("},");
+ } else if (type == QVariant::List) {
+ const QVariantList list = v.toList();
+
+ result = QLatin1String("List [");
+ for (const auto &item : list)
+ result += indented + dumpVariant(item, indented);
+ result.chop(1); // remove comma
+ result += indent + QLatin1String("],");
+ } else {
+ QDebug debug(&result);
+ debug.nospace() << v << ',';
+ }
+ return result;
+}
+
+QString DataStreamDumper::name()
+{
+ return QStringLiteral("datastream-dump");
+}
+
+Converter::Direction DataStreamDumper::directions()
+{
+ return Out;
+}
+
+Converter::Options DataStreamDumper::outputOptions()
+{
+ return SupportsArbitraryMapKeys;
+}
+
+const char *DataStreamDumper::optionsHelp()
+{
+ return nullptr;
+}
+
+bool DataStreamDumper::probeFile(QIODevice *f)
+{
+ Q_UNUSED(f);
+ return false;
+}
+
+QVariant DataStreamDumper::loadFile(QIODevice *f, Converter *&outputConverter)
+{
+ Q_UNREACHABLE();
+ Q_UNUSED(f);
+ Q_UNUSED(outputConverter);
+ return QVariant();
+}
+
+void DataStreamDumper::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options)
+{
+ Q_UNUSED(options);
+ QString s = dumpVariant(contents);
+ s[s.size() - 1] = QLatin1Char('\n'); // replace the comma with newline
+
+ QTextStream out(f);
+ out << s;
+}
+
+DataStreamConverter::DataStreamConverter()
+{
+ qRegisterMetaType<VariantOrderedMap>();
+ qRegisterMetaTypeStreamOperators<VariantOrderedMap>();
+}
+
+QString DataStreamConverter::name()
+{
+ return QStringLiteral("datastream");
+}
+
+Converter::Direction DataStreamConverter::directions()
+{
+ return InOut;
+}
+
+Converter::Options DataStreamConverter::outputOptions()
+{
+ return SupportsArbitraryMapKeys;
+}
+
+const char *DataStreamConverter::optionsHelp()
+{
+ return optionHelp;
+}
+
+bool DataStreamConverter::probeFile(QIODevice *f)
+{
+ return f->isReadable() && f->peek(sizeof(signature) - 1) == signature;
+}
+
+QVariant DataStreamConverter::loadFile(QIODevice *f, Converter *&outputConverter)
+{
+ if (!outputConverter)
+ outputConverter = &dataStreamDumper;
+
+ char c;
+ if (f->read(sizeof(signature) -1) != signature ||
+ !f->getChar(&c) || (c != 'l' && c != 'B')) {
+ fprintf(stderr, "Could not load QDataStream file: invalid signature.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ QDataStream ds(f);
+ ds.setByteOrder(c == 'l' ? QDataStream::LittleEndian : QDataStream::BigEndian);
+
+ std::underlying_type<QDataStream::Version>::type version;
+ ds >> version;
+ ds.setVersion(QDataStream::Version(version));
+
+ QVariant result;
+ ds >> result;
+ return result;
+}
+
+void DataStreamConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options)
+{
+ QDataStream::Version version = QDataStream::Qt_5_0;
+ auto order = QDataStream::ByteOrder(QSysInfo::ByteOrder);
+ for (const QString &option : options) {
+ const QStringList pair = option.split('=');
+ if (pair.size() == 2) {
+ if (pair.first() == "byteorder") {
+ if (pair.last() == "little") {
+ order = QDataStream::LittleEndian;
+ continue;
+ } else if (pair.last() == "big") {
+ order = QDataStream::BigEndian;
+ continue;
+ } else if (pair.last() == "host") {
+ order = QDataStream::ByteOrder(QSysInfo::ByteOrder);
+ continue;
+ }
+ }
+ if (pair.first() == "version") {
+ bool ok;
+ int n = pair.last().toInt(&ok);
+ if (ok) {
+ version = QDataStream::Version(n);
+ continue;
+ }
+
+ fprintf(stderr, "Invalid version number '%s': must be a number from 1 to %d.\n",
+ qPrintable(pair.last()), QDataStream::Qt_DefaultCompiledVersion);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ fprintf(stderr, "Unknown QDataStream formatting option '%s'. Available options are:\n%s",
+ qPrintable(option), optionHelp);
+ exit(EXIT_FAILURE);
+ }
+
+ char c = order == QDataStream::LittleEndian ? 'l' : 'B';
+ f->write(signature);
+ f->write(&c, 1);
+
+ QDataStream ds(f);
+ ds.setVersion(version);
+ ds.setByteOrder(order);
+ ds << std::underlying_type<decltype(version)>::type(version);
+ ds << contents;
+}
diff --git a/examples/corelib/serialization/convert/datastreamconverter.h b/examples/corelib/serialization/convert/datastreamconverter.h
new file mode 100644
index 0000000000..1b74abc54f
--- /dev/null
+++ b/examples/corelib/serialization/convert/datastreamconverter.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** 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$
+**
+****************************************************************************/
+
+#ifndef DATASTREAMCONVERTER_H
+#define DATASTREAMCONVERTER_H
+
+#include "converter.h"
+
+class DataStreamDumper : public Converter
+{
+ // Converter interface
+public:
+ QString name() override;
+ Direction directions() override;
+ Options outputOptions() override;
+ const char *optionsHelp() override;
+ bool probeFile(QIODevice *f) override;
+ QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
+ void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
+};
+
+class DataStreamConverter : public Converter
+{
+public:
+ DataStreamConverter();
+
+ // Converter interface
+public:
+ QString name() override;
+ Direction directions() override;
+ Options outputOptions() override;
+ const char *optionsHelp() override;
+ bool probeFile(QIODevice *f) override;
+ QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
+ void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
+};
+
+#endif // DATASTREAMCONVERTER_H
diff --git a/examples/corelib/serialization/convert/jsonconverter.cpp b/examples/corelib/serialization/convert/jsonconverter.cpp
new file mode 100644
index 0000000000..80d1cc6827
--- /dev/null
+++ b/examples/corelib/serialization/convert/jsonconverter.cpp
@@ -0,0 +1,212 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** 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 "jsonconverter.h"
+
+#include <QFile>
+#include <QJsonArray>
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QJsonValue>
+
+static JsonConverter jsonConverter;
+static BinaryJsonConverter BinaryJsonConverter;
+
+static const char optionHelp[] =
+ "compact=no|yes Use compact JSON form.\n";
+
+static QJsonDocument convertFromVariant(const QVariant &v)
+{
+ QJsonDocument doc = QJsonDocument::fromVariant(v);
+ if (!doc.isObject() && !doc.isArray()) {
+ fprintf(stderr, "Could not convert contents to JSON.\n");
+ exit(EXIT_FAILURE);
+ }
+ return doc;
+}
+
+JsonConverter::JsonConverter()
+{
+}
+
+QString JsonConverter::name()
+{
+ return "json";
+}
+
+Converter::Direction JsonConverter::directions()
+{
+ return InOut;
+}
+
+Converter::Options JsonConverter::outputOptions()
+{
+ return {};
+}
+
+const char *JsonConverter::optionsHelp()
+{
+ return optionHelp;
+}
+
+bool JsonConverter::probeFile(QIODevice *f)
+{
+ if (QFile *file = qobject_cast<QFile *>(f)) {
+ if (file->fileName().endsWith(QLatin1String(".json")))
+ return true;
+ }
+
+ if (f->isReadable()) {
+ QByteArray ba = f->peek(1);
+ return ba == "{" || ba == "[";
+ }
+ return false;
+}
+
+QVariant JsonConverter::loadFile(QIODevice *f, Converter *&outputConverter)
+{
+ if (!outputConverter)
+ outputConverter = this;
+
+ QJsonParseError error;
+ QJsonDocument doc;
+ if (auto file = qobject_cast<QFile *>(f)) {
+ const char *ptr = reinterpret_cast<char *>(file->map(0, file->size()));
+ if (ptr)
+ doc = QJsonDocument::fromJson(QByteArray::fromRawData(ptr, file->size()), &error);
+ }
+
+ if (doc.isNull())
+ doc = QJsonDocument::fromJson(f->readAll(), &error);
+ if (error.error) {
+ fprintf(stderr, "Could not parse JSON content: offset %d: %s",
+ error.offset, qPrintable(error.errorString()));
+ exit(EXIT_FAILURE);
+ }
+ if (outputConverter == null)
+ return QVariant();
+ return doc.toVariant();
+}
+
+void JsonConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options)
+{
+ QJsonDocument::JsonFormat format = QJsonDocument::Indented;
+ for (const QString &s : options) {
+ if (s == QLatin1String("compact=no")) {
+ format = QJsonDocument::Indented;
+ } else if (s == QLatin1String("compact=yes")) {
+ format = QJsonDocument::Compact;
+ } else {
+ fprintf(stderr, "Unknown option '%s' to JSON output. Valid options are:\n%s", qPrintable(s), optionHelp);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ f->write(convertFromVariant(contents).toJson(format));
+}
+
+QString BinaryJsonConverter::name()
+{
+ return "binary-json";
+}
+
+Converter::Direction BinaryJsonConverter::directions()
+{
+ return InOut;
+}
+
+Converter::Options BinaryJsonConverter::outputOptions()
+{
+ return {};
+}
+
+const char *BinaryJsonConverter::optionsHelp()
+{
+ return nullptr;
+}
+
+bool BinaryJsonConverter::probeFile(QIODevice *f)
+{
+ return f->isReadable() && f->peek(4) == "qbjs";
+}
+
+QVariant BinaryJsonConverter::loadFile(QIODevice *f, Converter *&outputConverter)
+{
+ if (!outputConverter)
+ outputConverter = &jsonConverter;
+
+ QJsonDocument doc;
+ if (auto file = qobject_cast<QFile *>(f)) {
+ uchar *ptr = file->map(0, file->size());
+ if (ptr)
+ doc = QJsonDocument::fromRawData(reinterpret_cast<char *>(ptr), file->size());
+ }
+
+ if (doc.isNull())
+ doc = QJsonDocument::fromBinaryData(f->readAll());
+
+ if (!doc.isObject() && !doc.isArray()) {
+ fprintf(stderr, "Failed to load Binary JSON.\n");
+ exit(EXIT_FAILURE);
+ }
+ if (outputConverter == null)
+ return QVariant();
+ return doc.toVariant();
+}
+
+void BinaryJsonConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options)
+{
+ if (!options.isEmpty()) {
+ fprintf(stderr, "Unknown option '%s' to JSON output. This format has no options.\n", qPrintable(options.first()));
+ exit(EXIT_FAILURE);
+ }
+
+ f->write(convertFromVariant(contents).toBinaryData());
+}
diff --git a/examples/corelib/serialization/convert/jsonconverter.h b/examples/corelib/serialization/convert/jsonconverter.h
new file mode 100644
index 0000000000..17170603c7
--- /dev/null
+++ b/examples/corelib/serialization/convert/jsonconverter.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** 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$
+**
+****************************************************************************/
+
+#ifndef JSONCONVERTER_H
+#define JSONCONVERTER_H
+
+#include "converter.h"
+
+class JsonConverter : public Converter
+{
+public:
+ JsonConverter();
+
+ // Converter interface
+public:
+ QString name() override;
+ Direction directions() override;
+ Options outputOptions() override;
+ const char *optionsHelp() override;
+ bool probeFile(QIODevice *f) override;
+ QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
+ void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
+};
+
+class BinaryJsonConverter : public Converter
+{
+ // Converter interface
+public:
+ QString name() override;
+ Direction directions() override;
+ Options outputOptions() override;
+ const char *optionsHelp() override;
+ bool probeFile(QIODevice *f) override;
+ QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
+ void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
+};
+
+#endif // JSONCONVERTER_H
diff --git a/examples/corelib/serialization/convert/main.cpp b/examples/corelib/serialization/convert/main.cpp
new file mode 100644
index 0000000000..e9d14792b0
--- /dev/null
+++ b/examples/corelib/serialization/convert/main.cpp
@@ -0,0 +1,234 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** 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 "converter.h"
+
+#include <QCommandLineParser>
+#include <QCommandLineOption>
+#include <QCoreApplication>
+#include <QFile>
+#include <QFileInfo>
+
+#include <stdio.h>
+
+static QVector<Converter *> *availableConverters;
+
+Converter::Converter()
+{
+ if (!availableConverters)
+ availableConverters = new QVector<Converter *>;
+ availableConverters->append(this);
+}
+
+Converter::~Converter()
+{
+ availableConverters->removeAll(this);
+}
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication app(argc, argv);
+
+ QStringList inputFormats;
+ QStringList outputFormats;
+ for (Converter *conv : qAsConst(*availableConverters)) {
+ auto direction = conv->directions();
+ QString name = conv->name();
+ if (direction & Converter::In)
+ inputFormats << name;
+ if (direction & Converter::Out)
+ outputFormats << name;
+ }
+ inputFormats.sort();
+ outputFormats.sort();
+ inputFormats.prepend("auto");
+ outputFormats.prepend("auto");
+
+ QCommandLineParser parser;
+ parser.setApplicationDescription(QStringLiteral("Qt file format conversion tool"));
+ parser.addHelpOption();
+
+ QCommandLineOption inputFormatOption(QStringList{"I", "input-format"});
+ inputFormatOption.setDescription(QLatin1String("Select the input format for the input file. Available formats: ") +
+ inputFormats.join(", "));
+ inputFormatOption.setValueName("format");
+ inputFormatOption.setDefaultValue(inputFormats.constFirst());
+ parser.addOption(inputFormatOption);
+
+ QCommandLineOption outputFormatOption(QStringList{"O", "output-format"});
+ outputFormatOption.setDescription(QLatin1String("Select the output format for the output file. Available formats: ") +
+ outputFormats.join(", "));
+ outputFormatOption.setValueName("format");
+ outputFormatOption.setDefaultValue(outputFormats.constFirst());
+ parser.addOption(outputFormatOption);
+
+ QCommandLineOption optionOption(QStringList{"o", "option"});
+ optionOption.setDescription(QStringLiteral("Format-specific options. Use --format-options to find out what options are available."));
+ optionOption.setValueName("options...");
+ optionOption.setDefaultValues({});
+ parser.addOption(optionOption);
+
+ QCommandLineOption formatOptionsOption("format-options");
+ formatOptionsOption.setDescription(QStringLiteral("Prints the list of valid options for --option for the converter format <format>."));
+ formatOptionsOption.setValueName("format");
+ parser.addOption(formatOptionsOption);
+
+ parser.addPositionalArgument(QStringLiteral("[source]"),
+ QStringLiteral("File to read from (stdin if none)"));
+ parser.addPositionalArgument(QStringLiteral("[destination]"),
+ QStringLiteral("File to write to (stdout if none)"));
+
+ parser.process(app);
+
+ if (parser.isSet(formatOptionsOption)) {
+ QString format = parser.value(formatOptionsOption);
+ for (Converter *conv : qAsConst(*availableConverters)) {
+ if (conv->name() == format) {
+ const char *help = conv->optionsHelp();
+ if (help)
+ printf("The following options are available for format '%s':\n\n%s", qPrintable(format), help);
+ else
+ printf("Format '%s' supports no options.\n", qPrintable(format));
+ return EXIT_SUCCESS;
+ }
+ }
+
+ fprintf(stderr, "Unknown file format '%s'\n", qPrintable(format));
+ return EXIT_FAILURE;
+ }
+
+ Converter *inconv = nullptr;
+ QString format = parser.value(inputFormatOption);
+ if (format != "auto") {
+ for (Converter *conv : qAsConst(*availableConverters)) {
+ if (conv->name() == format) {
+ inconv = conv;
+ break;
+ }
+ }
+
+ if (!inconv) {
+ fprintf(stderr, "Unknown file format \"%s\"\n", qPrintable(format));
+ return EXIT_FAILURE;
+ }
+ }
+
+ Converter *outconv = nullptr;
+ format = parser.value(outputFormatOption);
+ if (format != "auto") {
+ for (Converter *conv : qAsConst(*availableConverters)) {
+ if (conv->name() == format) {
+ outconv = conv;
+ break;
+ }
+ }
+
+ if (!outconv) {
+ fprintf(stderr, "Unknown file format \"%s\"\n", qPrintable(format));
+ return EXIT_FAILURE;
+ }
+ }
+
+ QStringList files = parser.positionalArguments();
+ QFile input(files.value(0));
+ QFile output(files.value(1));
+
+ if (input.fileName().isEmpty())
+ input.open(stdin, QIODevice::ReadOnly);
+ else
+ input.open(QIODevice::ReadOnly);
+ if (!input.isOpen()) {
+ fprintf(stderr, "Could not open \"%s\" for reading: %s\n",
+ qPrintable(input.fileName()), qPrintable(input.errorString()));
+ return EXIT_FAILURE;
+ }
+
+ if (output.fileName().isEmpty())
+ output.open(stdout, QIODevice::WriteOnly | QIODevice::Truncate);
+ else
+ output.open(QIODevice::WriteOnly | QIODevice::Truncate);
+ if (!output.isOpen()) {
+ fprintf(stderr, "Could not open \"%s\" for writing: %s\n",
+ qPrintable(output.fileName()), qPrintable(output.errorString()));
+ return EXIT_FAILURE;
+ }
+
+ if (!inconv) {
+ // probe the input to find a file format
+ for (Converter *conv : qAsConst(*availableConverters)) {
+ if (conv->directions() & Converter::In && conv->probeFile(&input)) {
+ inconv = conv;
+ break;
+ }
+ }
+
+ if (!inconv) {
+ fprintf(stderr, "Could not determine input format. pass -I option.\n");
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (!outconv) {
+ // probe the output to find a file format
+ for (Converter *conv : qAsConst(*availableConverters)) {
+ if (conv->directions() & Converter::Out && conv->probeFile(&output)) {
+ outconv = conv;
+ break;
+ }
+ }
+ }
+
+ // now finally perform the conversion
+ QVariant data = inconv->loadFile(&input, outconv);
+ Q_ASSERT_X(outconv, "Converter Tool",
+ "Internal error: converter format did not provide default");
+ outconv->saveFile(&output, data, parser.values(optionOption));
+ return EXIT_SUCCESS;
+}
diff --git a/examples/corelib/serialization/convert/nullconverter.cpp b/examples/corelib/serialization/convert/nullconverter.cpp
new file mode 100644
index 0000000000..2de492e64e
--- /dev/null
+++ b/examples/corelib/serialization/convert/nullconverter.cpp
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** 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 "nullconverter.h"
+
+static NullConverter nullConverter;
+Converter* Converter::null = &nullConverter;
+
+QString NullConverter::name()
+{
+ return QLatin1String("null");
+}
+
+Converter::Direction NullConverter::directions()
+{
+ return Out;
+}
+
+Converter::Options NullConverter::outputOptions()
+{
+ return SupportsArbitraryMapKeys;
+}
+
+const char *NullConverter::optionsHelp()
+{
+ return nullptr;
+}
+
+bool NullConverter::probeFile(QIODevice *f)
+{
+ Q_UNUSED(f);
+ return false;
+}
+
+QVariant NullConverter::loadFile(QIODevice *f, Converter *&outputConverter)
+{
+ Q_UNUSED(f);
+ Q_UNUSED(outputConverter);
+ outputConverter = this;
+ return QVariant();
+}
+
+void NullConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options)
+{
+ if (!options.isEmpty()) {
+ fprintf(stderr, "Unknown option '%s' to null output. This format has no options.\n", qPrintable(options.first()));
+ exit(EXIT_FAILURE);
+ }
+
+ Q_UNUSED(f);
+ Q_UNUSED(contents);
+}
diff --git a/examples/corelib/serialization/convert/nullconverter.h b/examples/corelib/serialization/convert/nullconverter.h
new file mode 100644
index 0000000000..af7339f092
--- /dev/null
+++ b/examples/corelib/serialization/convert/nullconverter.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** 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$
+**
+****************************************************************************/
+
+#ifndef NULLCONVERTER_H
+#define NULLCONVERTER_H
+
+#include "converter.h"
+
+class NullConverter : public Converter
+{
+ // Converter interface
+public:
+ QString name() override;
+ Direction directions() override;
+ Options outputOptions() override;
+ const char *optionsHelp() override;
+ bool probeFile(QIODevice *f) override;
+ QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
+ void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
+};
+
+#endif // NULLCONVERTER_H
diff --git a/examples/corelib/serialization/convert/textconverter.cpp b/examples/corelib/serialization/convert/textconverter.cpp
new file mode 100644
index 0000000000..e80e69a0b5
--- /dev/null
+++ b/examples/corelib/serialization/convert/textconverter.cpp
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** 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 "textconverter.h"
+
+#include <QFile>
+#include <QTextStream>
+
+static void dumpVariant(QTextStream &out, const QVariant &v)
+{
+ switch (v.userType()) {
+ case QVariant::List: {
+ const QVariantList list = v.toList();
+ for (const QVariant &item : list)
+ dumpVariant(out, item);
+ break;
+ }
+
+ case QVariant::String: {
+ const QStringList list = v.toStringList();
+ for (const QString &s : list)
+ out << s << endl;
+ break;
+ }
+
+ case QVariant::Map: {
+ const QVariantMap map = v.toMap();
+ for (auto it = map.begin(); it != map.end(); ++it) {
+ out << it.key() << " => ";
+ dumpVariant(out, it.value());
+ }
+ break;
+ }
+
+ case QMetaType::Nullptr:
+ out << "(null)" << endl;
+ break;
+
+ default:
+ out << v.toString() << endl;
+ break;
+ }
+}
+
+QString TextConverter::name()
+{
+ return QStringLiteral("text");
+}
+
+Converter::Direction TextConverter::directions()
+{
+ return InOut;
+}
+
+Converter::Options TextConverter::outputOptions()
+{
+ return {};
+}
+
+const char *TextConverter::optionsHelp()
+{
+ return nullptr;
+}
+
+bool TextConverter::probeFile(QIODevice *f)
+{
+ if (QFile *file = qobject_cast<QFile *>(f))
+ return file->fileName().endsWith(QLatin1String(".txt"));
+ return false;
+}
+
+QVariant TextConverter::loadFile(QIODevice *f, Converter *&outputConverter)
+{
+ if (!outputConverter)
+ outputConverter = this;
+
+ QVariantList list;
+ QTextStream in(f);
+ QString line ;
+ while (!in.atEnd()) {
+ in.readLineInto(&line);
+
+ bool ok;
+ qint64 v = line.toLongLong(&ok);
+ if (ok) {
+ list.append(v);
+ continue;
+ }
+
+ double d = line.toDouble(&ok);
+ if (ok) {
+ list.append(d);
+ continue;
+ }
+
+ list.append(line);
+ }
+
+ return list;
+}
+
+void TextConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options)
+{
+ if (!options.isEmpty()) {
+ fprintf(stderr, "Unknown option '%s' to text output. This format has no options.\n", qPrintable(options.first()));
+ exit(EXIT_FAILURE);
+ }
+
+ QTextStream out(f);
+ dumpVariant(out, contents);
+}
+
+static TextConverter textConverter;
diff --git a/examples/corelib/serialization/convert/textconverter.h b/examples/corelib/serialization/convert/textconverter.h
new file mode 100644
index 0000000000..66f5136c02
--- /dev/null
+++ b/examples/corelib/serialization/convert/textconverter.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** 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$
+**
+****************************************************************************/
+
+#ifndef TEXTCONVERTER_H
+#define TEXTCONVERTER_H
+
+#include "converter.h"
+
+class TextConverter : public Converter
+{
+
+ // Converter interface
+public:
+ QString name() override;
+ Direction directions() override;
+ Options outputOptions() override;
+ const char *optionsHelp() override;
+ bool probeFile(QIODevice *f) override;
+ QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
+ void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
+};
+
+#endif // TEXTCONVERTER_H
diff --git a/examples/corelib/serialization/convert/xmlconverter.cpp b/examples/corelib/serialization/convert/xmlconverter.cpp
new file mode 100644
index 0000000000..62908273ce
--- /dev/null
+++ b/examples/corelib/serialization/convert/xmlconverter.cpp
@@ -0,0 +1,514 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** 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 "xmlconverter.h"
+
+#include <QBitArray>
+#include <QtCborCommon>
+#include <QFile>
+#include <QFloat16>
+#include <QMetaType>
+#include <QRegularExpression>
+#include <QUrl>
+#include <QXmlStreamReader>
+#include <QXmlStreamWriter>
+
+static const char optionHelp[] =
+ "compact=no|yes Use compact XML form.\n";
+
+static XmlConverter xmlConverter;
+
+static QVariant variantFromXml(QXmlStreamReader &xml, Converter::Options options);
+
+static QVariantList listFromXml(QXmlStreamReader &xml, Converter::Options options)
+{
+ QVariantList list;
+ while (!xml.atEnd() && !xml.isEndElement()) {
+ xml.readNext();
+ switch (xml.tokenType()) {
+ case QXmlStreamReader::StartElement:
+ list << variantFromXml(xml, options);
+ continue;
+
+ case QXmlStreamReader::EndElement:
+ continue;
+
+ case QXmlStreamReader::Comment:
+ // ignore comments
+ continue;
+
+ case QXmlStreamReader::Characters:
+ // ignore whitespace
+ if (xml.isWhitespace())
+ continue;
+ Q_FALLTHROUGH();
+
+ default:
+ break;
+ }
+
+ fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n",
+ xml.lineNumber(), xml.columnNumber(),
+ qPrintable(xml.tokenString()), qPrintable(xml.name().toString()));
+ exit(EXIT_FAILURE);
+ }
+
+ xml.readNext();
+ return list;
+}
+
+static VariantOrderedMap::value_type mapEntryFromXml(QXmlStreamReader &xml, Converter::Options options)
+{
+ QVariant key, value;
+ while (!xml.atEnd() && !xml.isEndElement()) {
+ xml.readNext();
+ switch (xml.tokenType()) {
+ case QXmlStreamReader::StartElement:
+ if (value.isValid())
+ break;
+ if (key.isValid())
+ value = variantFromXml(xml, options);
+ else
+ key = variantFromXml(xml, options);
+ continue;
+
+ case QXmlStreamReader::EndElement:
+ continue;
+
+ case QXmlStreamReader::Comment:
+ // ignore comments
+ continue;
+
+ case QXmlStreamReader::Characters:
+ // ignore whitespace
+ if (xml.isWhitespace())
+ continue;
+ Q_FALLTHROUGH();
+
+ default:
+ break;
+ }
+
+ fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n",
+ xml.lineNumber(), xml.columnNumber(),
+ qPrintable(xml.tokenString()), qPrintable(xml.name().toString()));
+ exit(EXIT_FAILURE);
+ }
+
+ return { key, value };
+}
+
+static QVariant mapFromXml(QXmlStreamReader &xml, Converter::Options options)
+{
+ QVariantMap map1;
+ VariantOrderedMap map2;
+
+ while (!xml.atEnd() && !xml.isEndElement()) {
+ xml.readNext();
+ switch (xml.tokenType()) {
+ case QXmlStreamReader::StartElement:
+ if (xml.name() == QLatin1String("entry")) {
+ auto pair = mapEntryFromXml(xml, options);
+ if (options & Converter::SupportsArbitraryMapKeys)
+ map2.append(pair);
+ else
+ map1.insert(pair.first.toString(), pair.second);
+ continue;
+ }
+ break;
+
+ case QXmlStreamReader::EndElement:
+ continue;
+
+ case QXmlStreamReader::Comment:
+ // ignore comments
+ continue;
+
+ case QXmlStreamReader::Characters:
+ // ignore whitespace
+ if (xml.isWhitespace())
+ continue;
+ Q_FALLTHROUGH();
+
+ default:
+ break;
+ }
+
+ fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n",
+ xml.lineNumber(), xml.columnNumber(),
+ qPrintable(xml.tokenString()), qPrintable(xml.name().toString()));
+ exit(EXIT_FAILURE);
+ }
+
+ xml.readNext();
+ if (options & Converter::SupportsArbitraryMapKeys)
+ return QVariant::fromValue(map2);
+ return map1;
+}
+
+static QVariant variantFromXml(QXmlStreamReader &xml, Converter::Options options)
+{
+ QStringRef name = xml.name();
+ if (name == QLatin1String("list"))
+ return listFromXml(xml, options);
+ if (name == QLatin1String("map"))
+ return mapFromXml(xml, options);
+ if (name != QLatin1String("value")) {
+ fprintf(stderr, "%lld:%lld: Invalid XML key '%s'.\n",
+ xml.lineNumber(), xml.columnNumber(), qPrintable(name.toString()));
+ exit(EXIT_FAILURE);
+ }
+
+ QXmlStreamAttributes attrs = xml.attributes();
+ QStringRef type = attrs.value(QLatin1String("type"));
+
+ forever {
+ xml.readNext();
+ if (xml.isComment())
+ continue;
+ if (xml.isCDATA() || xml.isCharacters() || xml.isEndElement())
+ break;
+
+ fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n",
+ xml.lineNumber(), xml.columnNumber(),
+ qPrintable(xml.tokenString()), qPrintable(name.toString()));
+ exit(EXIT_FAILURE);
+ }
+
+ QStringRef text = xml.text();
+ if (!xml.isCDATA())
+ text = text.trimmed();
+
+ QVariant result;
+ bool ok;
+ if (type.isEmpty()) {
+ // ok
+ } else if (type == QLatin1String("number")) {
+ // try integer first
+ qint64 v = text.toLongLong(&ok);
+ if (ok) {
+ result = v;
+ } else {
+ // let's see floating point
+ double d = text.toDouble(&ok);
+ result = d;
+ if (!ok) {
+ fprintf(stderr, "%lld:%lld: Invalid XML: could not interpret '%s' as a number.\n",
+ xml.lineNumber(), xml.columnNumber(), qPrintable(text.toString()));
+ exit(EXIT_FAILURE);
+ }
+ }
+ } else if (type == QLatin1String("bytes")) {
+ QByteArray data = text.toLatin1();
+ QStringRef encoding = attrs.value("encoding");
+ if (encoding == QLatin1String("base64url")) {
+ result = QByteArray::fromBase64(data, QByteArray::Base64UrlEncoding);
+ } else if (encoding == QLatin1String("hex")) {
+ result = QByteArray::fromHex(data);
+ } else if (encoding.isEmpty() || encoding == QLatin1String("base64")) {
+ result = QByteArray::fromBase64(data);
+ } else {
+ fprintf(stderr, "%lld:%lld: Invalid XML: unknown encoding '%s' for bytes.\n",
+ xml.lineNumber(), xml.columnNumber(), qPrintable(encoding.toString()));
+ exit(EXIT_FAILURE);
+ }
+ } else if (type == QLatin1String("string")) {
+ result = text.toString();
+ } else if (type == QLatin1String("null")) {
+ result = QVariant::fromValue(nullptr);
+ } else if (type == QLatin1String("CBOR simple type")) {
+ result = QVariant::fromValue(QCborSimpleType(text.toShort()));
+ } else if (type == QLatin1String("bits")) {
+ QBitArray ba;
+ ba.resize(text.size());
+ qsizetype n = 0;
+ for (qsizetype i = 0; i < text.size(); ++i) {
+ QChar c = text.at(i);
+ if (c == '1') {
+ ba.setBit(n++);
+ } else if (c == '0') {
+ ++n;
+ } else if (!c.isSpace()) {
+ fprintf(stderr, "%lld:%lld: Invalid XML: invalid bit string '%s'.\n",
+ xml.lineNumber(), xml.columnNumber(), qPrintable(text.toString()));
+ exit(EXIT_FAILURE);
+ }
+ }
+ ba.resize(n);
+ result = ba;
+ } else {
+ int id = QVariant::Invalid;
+ if (type == QLatin1String("datetime"))
+ id = QVariant::DateTime;
+ else if (type == QLatin1String("url"))
+ id = QVariant::Url;
+ else if (type == QLatin1String("uuid"))
+ id = QVariant::Uuid;
+ else if (type == QLatin1String("regex"))
+ id = QVariant::RegularExpression;
+ else
+ id = QMetaType::type(type.toLatin1());
+ if (id == QVariant::Invalid) {
+ fprintf(stderr, "%lld:%lld: Invalid XML: unknown type '%s'.\n",
+ xml.lineNumber(), xml.columnNumber(), qPrintable(type.toString()));
+ exit(EXIT_FAILURE);
+ }
+
+ result = text.toString();
+ if (!result.convert(id)) {
+ fprintf(stderr, "%lld:%lld: Invalid XML: could not parse content as type '%s'.\n",
+ xml.lineNumber(), xml.columnNumber(), qPrintable(type.toString()));
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ do {
+ xml.readNext();
+ } while (xml.isComment() || xml.isWhitespace());
+
+ if (!xml.isEndElement()) {
+ fprintf(stderr, "%lld:%lld: Invalid XML %s '%s'.\n",
+ xml.lineNumber(), xml.columnNumber(),
+ qPrintable(xml.tokenString()), qPrintable(name.toString()));
+ exit(EXIT_FAILURE);
+ }
+
+ xml.readNext();
+ return result;
+}
+
+static void variantToXml(QXmlStreamWriter &xml, const QVariant &v)
+{
+ int type = v.userType();
+ if (type == QVariant::List) {
+ QVariantList list = v.toList();
+ xml.writeStartElement("list");
+ for (const QVariant &v : list)
+ variantToXml(xml, v);
+ xml.writeEndElement();
+ } else if (type == QVariant::Map || type == qMetaTypeId<VariantOrderedMap>()) {
+ const VariantOrderedMap map = (type == QVariant::Map) ?
+ VariantOrderedMap(v.toMap()) :
+ v.value<VariantOrderedMap>();
+
+ xml.writeStartElement("map");
+ for (const auto &pair : map) {
+ xml.writeStartElement("entry");
+ variantToXml(xml, pair.first);
+ variantToXml(xml, pair.second);
+ xml.writeEndElement();
+ }
+ xml.writeEndElement();
+ } else {
+ xml.writeStartElement("value");
+ QString typeString = QStringLiteral("type");
+ switch (type) {
+ case QMetaType::Short:
+ case QMetaType::UShort:
+ case QMetaType::Int:
+ case QMetaType::UInt:
+ case QMetaType::Long:
+ case QMetaType::ULong:
+ case QMetaType::LongLong:
+ case QMetaType::ULongLong:
+ case QMetaType::Float:
+ case QMetaType::Double:
+ xml.writeAttribute(typeString, "number");
+ xml.writeCharacters(v.toString());
+ break;
+
+ case QMetaType::QByteArray:
+ xml.writeAttribute(typeString, "bytes");
+ xml.writeAttribute("encoding", "base64");
+ xml.writeCharacters(QString::fromLatin1(v.toByteArray().toBase64()));
+ break;
+
+ case QMetaType::QString:
+ xml.writeAttribute(typeString, "string");
+ xml.writeCDATA(v.toString());
+ break;
+
+ case QMetaType::Bool:
+ xml.writeAttribute(typeString, "bool");
+ xml.writeCharacters(v.toString());
+ break;
+
+ case QMetaType::Nullptr:
+ xml.writeAttribute(typeString, "null");
+ break;
+
+ case QMetaType::UnknownType:
+ break;
+
+ case QMetaType::QDate:
+ case QMetaType::QTime:
+ case QMetaType::QDateTime:
+ xml.writeAttribute(typeString, "dateime");
+ xml.writeCharacters(v.toString());
+ break;
+
+ case QMetaType::QUrl:
+ xml.writeAttribute(typeString, "url");
+ xml.writeCharacters(v.toUrl().toString(QUrl::FullyEncoded));
+ break;
+
+ case QMetaType::QUuid:
+ xml.writeAttribute(typeString, "uuid");
+ xml.writeCharacters(v.toString());
+ break;
+
+ case QMetaType::QBitArray:
+ xml.writeAttribute(typeString, "bits");
+ xml.writeCharacters([](const QBitArray &ba) {
+ QString result;
+ for (qsizetype i = 0; i < ba.size(); ++i) {
+ if (i && i % 72 == 0)
+ result += '\n';
+ result += QLatin1Char(ba.testBit(i) ? '1' : '0');
+ }
+ return result;
+ }(v.toBitArray()));
+ break;
+
+ case QMetaType::QRegularExpression:
+ xml.writeAttribute(typeString, "regex");
+ xml.writeCharacters(v.toRegularExpression().pattern());
+ break;
+
+ default:
+ if (type == qMetaTypeId<qfloat16>()) {
+ xml.writeAttribute(typeString, "number");
+ xml.writeCharacters(QString::number(float(v.value<qfloat16>())));
+ } else if (type == qMetaTypeId<QCborSimpleType>()) {
+ xml.writeAttribute(typeString, "CBOR simple type");
+ xml.writeCharacters(QString::number(int(v.value<QCborSimpleType>())));
+ } else {
+ // does this convert to string?
+ const char *typeName = v.typeName();
+ QVariant copy = v;
+ if (copy.convert(QVariant::String)) {
+ xml.writeAttribute(typeString, QString::fromLatin1(typeName));
+ xml.writeCharacters(copy.toString());
+ } else {
+ fprintf(stderr, "XML: don't know how to serialize type '%s'.\n", typeName);
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+ xml.writeEndElement();
+ }
+}
+
+QString XmlConverter::name()
+{
+ return QStringLiteral("xml");
+}
+
+Converter::Direction XmlConverter::directions()
+{
+ return InOut;
+}
+
+Converter::Options XmlConverter::outputOptions()
+{
+ return SupportsArbitraryMapKeys;
+}
+
+const char *XmlConverter::optionsHelp()
+{
+ return optionHelp;
+}
+
+bool XmlConverter::probeFile(QIODevice *f)
+{
+ if (QFile *file = qobject_cast<QFile *>(f)) {
+ if (file->fileName().endsWith(QLatin1String(".xml")))
+ return true;
+ }
+
+ return f->isReadable() && f->peek(5) == "<?xml";
+}
+
+QVariant XmlConverter::loadFile(QIODevice *f, Converter *&outputConverter)
+{
+ if (!outputConverter)
+ outputConverter = this;
+
+ QXmlStreamReader xml(f);
+ xml.readNextStartElement();
+ QVariant v = variantFromXml(xml, outputConverter->outputOptions());
+ if (xml.hasError()) {
+ fprintf(stderr, "XML error: %s", qPrintable(xml.errorString()));
+ exit(EXIT_FAILURE);
+ }
+
+ return v;
+}
+
+void XmlConverter::saveFile(QIODevice *f, const QVariant &contents, const QStringList &options)
+{
+ bool compact = false;
+ for (const QString &s : options) {
+ if (s == QLatin1String("compact=no")) {
+ compact = false;
+ } else if (s == QLatin1String("compact=yes")) {
+ compact = true;
+ } else {
+ fprintf(stderr, "Unknown option '%s' to XML output. Valid options are:\n%s", qPrintable(s), optionHelp);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ QXmlStreamWriter xml(f);
+ xml.setAutoFormatting(!compact);
+ xml.writeStartDocument();
+ variantToXml(xml, contents);
+ xml.writeEndDocument();
+}
diff --git a/examples/corelib/serialization/convert/xmlconverter.h b/examples/corelib/serialization/convert/xmlconverter.h
new file mode 100644
index 0000000000..8fc0fea592
--- /dev/null
+++ b/examples/corelib/serialization/convert/xmlconverter.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** 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$
+**
+****************************************************************************/
+
+#ifndef XMLCONVERTER_H
+#define XMLCONVERTER_H
+
+#include "converter.h"
+
+class XmlConverter : public Converter
+{
+ // Converter interface
+public:
+ QString name() override;
+ Direction directions() override;
+ Options outputOptions() override;
+ const char *optionsHelp() override;
+ bool probeFile(QIODevice *f) override;
+ QVariant loadFile(QIODevice *f, Converter *&outputConverter) override;
+ void saveFile(QIODevice *f, const QVariant &contents, const QStringList &options) override;
+};
+
+#endif // XMLCONVERTER_H
diff --git a/examples/corelib/serialization/serialization.pro b/examples/corelib/serialization/serialization.pro
index af4d3e6f0f..7651444f19 100644
--- a/examples/corelib/serialization/serialization.pro
+++ b/examples/corelib/serialization/serialization.pro
@@ -1,2 +1,5 @@
TEMPLATE = subdirs
-SUBDIRS = savegame
+SUBDIRS = \
+ cbordump \
+ convert \
+ savegame
diff --git a/examples/corelib/threads/queuedcustomtype/window.cpp b/examples/corelib/threads/queuedcustomtype/window.cpp
index 7b9004d868..2cefba1e17 100644
--- a/examples/corelib/threads/queuedcustomtype/window.cpp
+++ b/examples/corelib/threads/queuedcustomtype/window.cpp
@@ -108,9 +108,8 @@ void Window::loadImage()
void Window::loadImage(const QImage &image)
{
- QDesktopWidget desktop;
QImage useImage;
- QRect space = desktop.availableGeometry();
+ QRect space = QGuiApplication::primaryScreen()->availableGeometry();
if (image.width() > 0.75*space.width() || image.height() > 0.75*space.height())
useImage = image.scaled(0.75*space.width(), 0.75*space.height(),
Qt::KeepAspectRatio, Qt::SmoothTransformation);
diff --git a/examples/examples.pro b/examples/examples.pro
index 4ec5ca60e2..077e5828a9 100644
--- a/examples/examples.pro
+++ b/examples/examples.pro
@@ -4,8 +4,7 @@ CONFIG += no_docs_target
SUBDIRS = \
corelib \
embedded \
- qpa \
- touch
+ qpa
qtHaveModule(dbus): SUBDIRS += dbus
qtHaveModule(network): SUBDIRS += network
diff --git a/examples/gui/doc/src/rasterwindow.qdoc b/examples/gui/doc/src/rasterwindow.qdoc
index 36612e1707..0c52a62b8e 100644
--- a/examples/gui/doc/src/rasterwindow.qdoc
+++ b/examples/gui/doc/src/rasterwindow.qdoc
@@ -99,9 +99,8 @@
The resize event is guaranteed to be called prior to the window
being shown on screen and will also be called whenever the window
- is resized while on screen. We use this to resize the back buffer
- and call renderNow() if we are visible to immediately update the
- visual representation of the window on screen.
+ is resized while on screen. We use this to resize the back buffer,
+ and defer rendering to the corresponding/following expose event.
\snippet rasterwindow/rasterwindow.cpp 3
diff --git a/examples/gui/rasterwindow/rasterwindow.cpp b/examples/gui/rasterwindow/rasterwindow.cpp
index 3eacd20145..4dd2ac25ca 100644
--- a/examples/gui/rasterwindow/rasterwindow.cpp
+++ b/examples/gui/rasterwindow/rasterwindow.cpp
@@ -83,8 +83,6 @@ void RasterWindow::renderLater()
void RasterWindow::resizeEvent(QResizeEvent *resizeEvent)
{
m_backingStore->resize(resizeEvent->size());
- if (isExposed())
- renderNow();
}
//! [5]
@@ -109,7 +107,7 @@ void RasterWindow::renderNow()
QPaintDevice *device = m_backingStore->paintDevice();
QPainter painter(device);
- painter.fillRect(0, 0, width(), height(), Qt::white);
+ painter.fillRect(0, 0, width(), height(), QGradient::NightFade);
render(&painter);
painter.end();
diff --git a/examples/network/doc/images/secureudpclient-example.png b/examples/network/doc/images/secureudpclient-example.png
new file mode 100644
index 0000000000..a566aa4ce5
--- /dev/null
+++ b/examples/network/doc/images/secureudpclient-example.png
Binary files differ
diff --git a/examples/network/doc/images/secureudpserver-example.png b/examples/network/doc/images/secureudpserver-example.png
new file mode 100644
index 0000000000..a117b02834
--- /dev/null
+++ b/examples/network/doc/images/secureudpserver-example.png
Binary files differ
diff --git a/examples/network/doc/src/secureudpclient.qdoc b/examples/network/doc/src/secureudpclient.qdoc
new file mode 100644
index 0000000000..dc8538cf85
--- /dev/null
+++ b/examples/network/doc/src/secureudpclient.qdoc
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE: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 secureudpclient
+ \title DTLS client
+ \ingroup examples-network
+ \brief This example demonstrates how to implement client-side DTLS connections.
+
+ \image secureudpclient-example.png Screenshot of the DTLS client example.
+
+ \note The DTLS client example is intended to be run alongside the \l{secureudpserver}{DTLS server} example.
+
+ The example DTLS client can establish several DTLS connections to one
+ or many DTLS servers. A client-side DTLS connection is implemented by the
+ DtlsAssociation class. This class uses QUdpSocket to read and write datagrams
+ and QDtls for encryption:
+
+ \snippet secureudpclient/association.h 0
+
+ The constructor sets the minimal TLS configuration for the new DTLS connection,
+ and sets the address and the port of the server:
+
+ \dots
+ \snippet secureudpclient/association.cpp 1
+ \dots
+
+ The QDtls::handshakeTimeout() signal is connected to the handleTimeout() slot
+ to deal with packet loss and retransmission during the handshake phase:
+
+ \dots
+ \snippet secureudpclient/association.cpp 2
+ \dots
+
+ To ensure we receive only the datagrams from the server, we connect our UDP socket to the server:
+
+ \dots
+ \snippet secureudpclient/association.cpp 3
+ \dots
+
+ The QUdpSocket::readyRead() signal is connected to the readyRead() slot:
+
+ \dots
+ \snippet secureudpclient/association.cpp 13
+ \dots
+
+ When a secure connection to a server is established, a DtlsAssociation object
+ will be sending short ping messages to the server, using a timer:
+
+ \snippet secureudpclient/association.cpp 4
+
+ startHandshake() starts a handshake with the server:
+
+ \snippet secureudpclient/association.cpp 5
+
+ The readyRead() slot reads a datagram sent by the server:
+
+ \snippet secureudpclient/association.cpp 6
+
+ If the handshake was already completed, this datagram is decrypted:
+
+ \snippet secureudpclient/association.cpp 7
+
+ otherwise, we try to continue the handshake:
+
+ \snippet secureudpclient/association.cpp 8
+
+ When the handshake has completed, we send our first ping message:
+
+ \snippet secureudpclient/association.cpp 9
+
+ The pskRequired() slot provides the Pre-Shared Key (PSK) needed during the handshake
+ phase:
+
+ \snippet secureudpclient/association.cpp 14
+
+ \note For the sake of brevity, the definition of pskRequired() is oversimplified.
+ The documentation for the QSslPreSharedKeyAuthenticator class explains in detail
+ how this slot can be properly implemented.
+
+ pingTimeout() sends an encrypted message to the server:
+
+ \snippet secureudpclient/association.cpp 10
+
+ During the handshake phase the client must handle possible timeouts, which
+ can happen due to packet loss. The handshakeTimeout() slot retransmits
+ the handshake messages:
+
+ \snippet secureudpclient/association.cpp 11
+
+ Before a client connection is destroyed, its DTLS connection must be shut down:
+
+ \snippet secureudpclient/association.cpp 12
+
+ Error messages, informational messages, and decrypted responses from servers
+ are displayed by the UI:
+
+ \snippet secureudpclient/mainwindow.cpp 0
+*/
+
diff --git a/examples/network/doc/src/secureudpserver.qdoc b/examples/network/doc/src/secureudpserver.qdoc
new file mode 100644
index 0000000000..0857f7065f
--- /dev/null
+++ b/examples/network/doc/src/secureudpserver.qdoc
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE: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 secureudpserver
+ \title DTLS server
+ \ingroup examples-network
+ \brief This examples demonstrates how to implement a simple DTLS server.
+
+ \image secureudpserver-example.png Screenshot of the DTLS server example.
+
+ \note The DTLS server example is intended to be run alongside the \l{secureudpclient}{DTLS client} example.
+
+ The server is implemented by the DtlsServer class. It uses QUdpSocket,
+ QDtlsClientVerifier, and QDtls to test each client's reachability, complete a handshake,
+ and read and write encrypted messages.
+
+ \snippet secureudpserver/server.h 0
+
+ The constructor connects the QUdpSocket::readyRead() signal to its
+ readyRead() slot and sets the minimal needed TLS configuration:
+
+ \snippet secureudpserver/server.cpp 1
+
+ \note The server is not using a certificate and is relying on Pre-Shared
+ Key (PSK) handshake.
+
+ listen() binds QUdpSocket:
+
+ \snippet secureudpserver/server.cpp 2
+
+ The readyRead() slot processes incoming datagrams:
+
+ \dots
+ \snippet secureudpserver/server.cpp 3
+ \dots
+
+ After extracting an address and a port number, the server first tests
+ if it's a datagram from an already known peer:
+
+ \dots
+ \snippet secureudpserver/server.cpp 4
+ \dots
+
+ If it is a new, unknown address and port, the datagram is processed as a
+ potential ClientHello message, sent by a DTLS client:
+
+ \dots
+ \snippet secureudpserver/server.cpp 5
+ \dots
+
+ If it's a known DTLS client, the server either decrypts the datagram:
+
+ \dots
+ \snippet secureudpserver/server.cpp 6
+ \dots
+
+ or continues a handshake with this peer:
+
+ \dots
+ \snippet secureudpserver/server.cpp 7
+ \dots
+
+ handleNewConnection() verifies it's a reachable DTLS client, or sends a
+ HelloVerifyRequest:
+
+ \snippet secureudpserver/server.cpp 8
+ \dots
+
+ If the new client was verified to be a reachable DTLS client, the server creates
+ and configures a new QDtls object, and starts a server-side handshake:
+
+ \dots
+ \snippet secureudpserver/server.cpp 9
+ \dots
+
+ doHandshake() progresses through the handshake phase:
+
+ \snippet secureudpserver/server.cpp 11
+
+ During the handshake phase, the QDtls::pskRequired() signal is emitted and
+ the pskRequired() slot provides the preshared key:
+
+ \snippet secureudpserver/server.cpp 13
+
+ \note For the sake of brevity, the definition of pskRequired() is oversimplified.
+ The documentation for the QSslPreSharedKeyAuthenticator class explains in detail
+ how this slot can be properly implemented.
+
+ After the handshake is completed for the network peer, an encrypted DTLS
+ connection is considered to be established and the server decrypts subsequent
+ datagrams, sent by the peer, by calling decryptDatagram(). The server also
+ sends an encrypted response to the peer:
+
+ \snippet secureudpserver/server.cpp 12
+
+ The server closes its DTLS connections by calling QDtls::shutdown():
+
+ \snippet secureudpserver/server.cpp 14
+
+ During its operation, the server reports errors, informational messages, and
+ decrypted datagrams, by emitting signals errorMessage(), warningMessage(),
+ infoMessage(), and datagramReceived(). These messages are logged by the server's
+ UI:
+
+ \snippet secureudpserver/mainwindow.cpp 0
+*/
diff --git a/examples/network/loopback/dialog.cpp b/examples/network/loopback/dialog.cpp
index 99317b9c77..b4e6b0fd5e 100644
--- a/examples/network/loopback/dialog.cpp
+++ b/examples/network/loopback/dialog.cpp
@@ -48,11 +48,11 @@
**
****************************************************************************/
-#include <QtWidgets>
-#include <QtNetwork>
-
#include "dialog.h"
+#include <QtNetwork>
+#include <QtWidgets>
+
static const int TotalBytes = 50 * 1024 * 1024;
static const int PayloadSize = 64 * 1024; // 64 KB
@@ -71,15 +71,15 @@ Dialog::Dialog(QWidget *parent)
buttonBox->addButton(startButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);
- connect(startButton, SIGNAL(clicked()), this, SLOT(start()));
- connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
- connect(&tcpServer, SIGNAL(newConnection()),
- this, SLOT(acceptConnection()));
- connect(&tcpClient, SIGNAL(connected()), this, SLOT(startTransfer()));
- connect(&tcpClient, SIGNAL(bytesWritten(qint64)),
- this, SLOT(updateClientProgress(qint64)));
- connect(&tcpClient, SIGNAL(error(QAbstractSocket::SocketError)),
- this, SLOT(displayError(QAbstractSocket::SocketError)));
+ connect(startButton, &QAbstractButton::clicked, this, &Dialog::start);
+ connect(quitButton, &QAbstractButton::clicked, this, &QWidget::close);
+ connect(&tcpServer, &QTcpServer::newConnection,
+ this, &Dialog::acceptConnection);
+ connect(&tcpClient, &QAbstractSocket::connected, this, &Dialog::startTransfer);
+ connect(&tcpClient, &QIODevice::bytesWritten,
+ this, &Dialog::updateClientProgress);
+ connect(&tcpClient, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error),
+ this, &Dialog::displayError);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(clientProgressBar);
@@ -124,10 +124,18 @@ void Dialog::start()
void Dialog::acceptConnection()
{
tcpServerConnection = tcpServer.nextPendingConnection();
- connect(tcpServerConnection, SIGNAL(readyRead()),
- this, SLOT(updateServerProgress()));
- connect(tcpServerConnection, SIGNAL(error(QAbstractSocket::SocketError)),
- this, SLOT(displayError(QAbstractSocket::SocketError)));
+ if (!tcpServerConnection) {
+ serverStatusLabel->setText(tr("Error: got invalid pending connection!"));
+ return;
+ }
+
+ connect(tcpServerConnection, &QIODevice::readyRead,
+ this, &Dialog::updateServerProgress);
+ connect(tcpServerConnection,
+ QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error),
+ this, &Dialog::displayError);
+ connect(tcpServerConnection, &QTcpSocket::disconnected,
+ tcpServerConnection, &QTcpSocket::deleteLater);
serverStatusLabel->setText(tr("Accepted connection"));
tcpServer.close();
@@ -136,13 +144,13 @@ void Dialog::acceptConnection()
void Dialog::startTransfer()
{
// called when the TCP client connected to the loopback server
- bytesToWrite = TotalBytes - (int)tcpClient.write(QByteArray(PayloadSize, '@'));
+ bytesToWrite = TotalBytes - int(tcpClient.write(QByteArray(PayloadSize, '@')));
clientStatusLabel->setText(tr("Connected"));
}
void Dialog::updateServerProgress()
{
- bytesReceived += (int)tcpServerConnection->bytesAvailable();
+ bytesReceived += int(tcpServerConnection->bytesAvailable());
tcpServerConnection->readAll();
serverProgressBar->setMaximum(TotalBytes);
@@ -161,17 +169,16 @@ void Dialog::updateServerProgress()
void Dialog::updateClientProgress(qint64 numBytes)
{
- // callen when the TCP client has written some bytes
- bytesWritten += (int)numBytes;
+ // called when the TCP client has written some bytes
+ bytesWritten += int(numBytes);
// only write more if not finished and when the Qt write buffer is below a certain size.
- if (bytesToWrite > 0 && tcpClient.bytesToWrite() <= 4*PayloadSize)
- bytesToWrite -= (int)tcpClient.write(QByteArray(qMin(bytesToWrite, PayloadSize), '@'));
+ if (bytesToWrite > 0 && tcpClient.bytesToWrite() <= 4 * PayloadSize)
+ bytesToWrite -= tcpClient.write(QByteArray(qMin(bytesToWrite, PayloadSize), '@'));
clientProgressBar->setMaximum(TotalBytes);
clientProgressBar->setValue(bytesWritten);
- clientStatusLabel->setText(tr("Sent %1MB")
- .arg(bytesWritten / (1024 * 1024)));
+ clientStatusLabel->setText(tr("Sent %1MB").arg(bytesWritten / (1024 * 1024)));
}
void Dialog::displayError(QAbstractSocket::SocketError socketError)
diff --git a/examples/network/loopback/dialog.h b/examples/network/loopback/dialog.h
index b23cfa030b..a70c20550a 100644
--- a/examples/network/loopback/dialog.h
+++ b/examples/network/loopback/dialog.h
@@ -60,9 +60,6 @@ class QDialogButtonBox;
class QLabel;
class QProgressBar;
class QPushButton;
-class QTcpServer;
-class QTcpSocket;
-class QAction;
QT_END_NAMESPACE
class Dialog : public QDialog
@@ -70,7 +67,7 @@ class Dialog : public QDialog
Q_OBJECT
public:
- Dialog(QWidget *parent = 0);
+ Dialog(QWidget *parent = nullptr);
public slots:
void start();
@@ -81,21 +78,21 @@ public slots:
void displayError(QAbstractSocket::SocketError socketError);
private:
- QProgressBar *clientProgressBar;
- QProgressBar *serverProgressBar;
- QLabel *clientStatusLabel;
- QLabel *serverStatusLabel;
+ QProgressBar *clientProgressBar = nullptr;
+ QProgressBar *serverProgressBar = nullptr;
+ QLabel *clientStatusLabel = nullptr;
+ QLabel *serverStatusLabel = nullptr;
- QPushButton *startButton;
- QPushButton *quitButton;
- QDialogButtonBox *buttonBox;
+ QPushButton *startButton = nullptr;
+ QPushButton *quitButton = nullptr;
+ QDialogButtonBox *buttonBox = nullptr;
QTcpServer tcpServer;
QTcpSocket tcpClient;
- QTcpSocket *tcpServerConnection;
- int bytesToWrite;
- int bytesWritten;
- int bytesReceived;
+ QTcpSocket *tcpServerConnection = nullptr;
+ int bytesToWrite = 0;
+ int bytesWritten = 0;
+ int bytesReceived = 0;
};
#endif
diff --git a/examples/network/loopback/main.cpp b/examples/network/loopback/main.cpp
index 9959c472f4..094a11d4fc 100644
--- a/examples/network/loopback/main.cpp
+++ b/examples/network/loopback/main.cpp
@@ -48,10 +48,10 @@
**
****************************************************************************/
-#include <QApplication>
-
#include "dialog.h"
+#include <QApplication>
+
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
diff --git a/examples/network/network-chat/client.cpp b/examples/network/network-chat/client.cpp
index c1eda52a0c..97c2c44b6b 100644
--- a/examples/network/network-chat/client.cpp
+++ b/examples/network/network-chat/client.cpp
@@ -78,7 +78,7 @@ void Client::sendMessage(const QString &message)
QString Client::nickName() const
{
- return QString(peerManager->userName()) + '@' + QHostInfo::localHostName()
+ return peerManager->userName() + '@' + QHostInfo::localHostName()
+ ':' + QString::number(server.serverPort());
}
diff --git a/examples/network/network-chat/connection.cpp b/examples/network/network-chat/connection.cpp
index 332d5dc56b..58cf67eb6d 100644
--- a/examples/network/network-chat/connection.cpp
+++ b/examples/network/network-chat/connection.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -55,17 +56,29 @@
static const int TransferTimeout = 30 * 1000;
static const int PongTimeout = 60 * 1000;
static const int PingInterval = 5 * 1000;
-static const char SeparatorToken = ' ';
+
+/*
+ * Protocol is defined as follows, using the CBOR Data Definition Language:
+ *
+ * protocol = [
+ * greeting, ; must start with a greeting command
+ * * command ; zero or more regular commands after
+ * ]
+ * command = plaintext / ping / pong / greeting
+ * plaintext = { 0 => text }
+ * ping = { 1 => null }
+ * pong = { 2 => null }
+ * greeting = { 3 => text }
+ */
Connection::Connection(QObject *parent)
- : QTcpSocket(parent)
+ : QTcpSocket(parent), writer(this)
{
greetingMessage = tr("undefined");
username = tr("unknown");
state = WaitingForGreeting;
currentDataType = Undefined;
- numBytesForCurrentDataType = -1;
- transferTimerId = 0;
+ transferTimerId = -1;
isGreetingMessageSent = false;
pingTimer.setInterval(PingInterval);
@@ -76,6 +89,22 @@ Connection::Connection(QObject *parent)
this, SLOT(sendGreetingMessage()));
}
+Connection::Connection(qintptr socketDescriptor, QObject *parent)
+ : Connection(parent)
+{
+ setSocketDescriptor(socketDescriptor);
+ reader.setDevice(this);
+}
+
+Connection::~Connection()
+{
+ if (isGreetingMessageSent) {
+ // Indicate clean shutdown.
+ writer.endArray();
+ waitForBytesWritten(2000);
+ }
+}
+
QString Connection::name() const
{
return username;
@@ -91,9 +120,11 @@ bool Connection::sendMessage(const QString &message)
if (message.isEmpty())
return false;
- QByteArray msg = message.toUtf8();
- QByteArray data = "MESSAGE " + QByteArray::number(msg.size()) + ' ' + msg;
- return write(data) == data.size();
+ writer.startMap(1);
+ writer.append(PlainText);
+ writer.append(message);
+ writer.endMap();
+ return true;
}
void Connection::timerEvent(QTimerEvent *timerEvent)
@@ -101,61 +132,75 @@ void Connection::timerEvent(QTimerEvent *timerEvent)
if (timerEvent->timerId() == transferTimerId) {
abort();
killTimer(transferTimerId);
- transferTimerId = 0;
+ transferTimerId = -1;
}
}
void Connection::processReadyRead()
{
- if (state == WaitingForGreeting) {
- if (!readProtocolHeader())
- return;
- if (currentDataType != Greeting) {
- abort();
- return;
+ // we've got more data, let's parse
+ reader.reparse();
+ while (reader.lastError() == QCborError::NoError) {
+ if (state == WaitingForGreeting) {
+ if (!reader.isArray())
+ break; // protocol error
+
+ reader.enterContainer(); // we'll be in this array forever
+ state = ReadingGreeting;
+ } else if (reader.containerDepth() == 1) {
+ // Current state: no command read
+ // Next state: read command ID
+ if (!reader.hasNext()) {
+ reader.leaveContainer();
+ disconnectFromHost();
+ return;
+ }
+
+ if (!reader.isMap() || !reader.isLengthKnown() || reader.length() != 1)
+ break; // protocol error
+ reader.enterContainer();
+ } else if (currentDataType == Undefined) {
+ // Current state: read command ID
+ // Next state: read command payload
+ if (!reader.isInteger())
+ break; // protocol error
+ currentDataType = DataType(reader.toInteger());
+ reader.next();
+ } else {
+ // Current state: read command payload
+ if (reader.isString()) {
+ auto r = reader.readString();
+ buffer += r.data;
+ if (r.status != QCborStreamReader::EndOfString)
+ continue;
+ } else if (reader.isNull()) {
+ reader.next();
+ } else {
+ break; // protocol error
+ }
+
+ // Next state: no command read
+ reader.leaveContainer();
+ if (transferTimerId != -1) {
+ killTimer(transferTimerId);
+ transferTimerId = -1;
+ }
+
+ if (state == ReadingGreeting) {
+ if (currentDataType != Greeting)
+ break; // protocol error
+ processGreeting();
+ } else {
+ processData();
+ }
}
- state = ReadingGreeting;
}
- if (state == ReadingGreeting) {
- if (!hasEnoughData())
- return;
-
- buffer = read(numBytesForCurrentDataType);
- if (buffer.size() != numBytesForCurrentDataType) {
- abort();
- return;
- }
-
- username = QString(buffer) + '@' + peerAddress().toString() + ':'
- + QString::number(peerPort());
- currentDataType = Undefined;
- numBytesForCurrentDataType = 0;
- buffer.clear();
-
- if (!isValid()) {
- abort();
- return;
- }
-
- if (!isGreetingMessageSent)
- sendGreetingMessage();
-
- pingTimer.start();
- pongTime.start();
- state = ReadyForUse;
- emit readyForUse();
- }
+ if (reader.lastError() != QCborError::EndOfFile)
+ abort(); // parse error
- do {
- if (currentDataType == Undefined) {
- if (!readProtocolHeader())
- return;
- }
- if (!hasEnoughData())
- return;
- processData();
- } while (bytesAvailable() > 0);
+ if (transferTimerId != -1 && reader.containerDepth() > 1)
+ transferTimerId = startTimer(TransferTimeout);
}
void Connection::sendPing()
@@ -165,112 +210,58 @@ void Connection::sendPing()
return;
}
- write("PING 1 p");
+ writer.startMap(1);
+ writer.append(Ping);
+ writer.append(nullptr); // no payload
+ writer.endMap();
}
void Connection::sendGreetingMessage()
{
- QByteArray greeting = greetingMessage.toUtf8();
- QByteArray data = "GREETING " + QByteArray::number(greeting.size()) + ' ' + greeting;
- if (write(data) == data.size())
- isGreetingMessageSent = true;
-}
+ writer.startArray(); // this array never ends
-int Connection::readDataIntoBuffer(int maxSize)
-{
- if (maxSize > MaxBufferSize)
- return 0;
+ writer.startMap(1);
+ writer.append(Greeting);
+ writer.append(greetingMessage);
+ writer.endMap();
+ isGreetingMessageSent = true;
- int numBytesBeforeRead = buffer.size();
- if (numBytesBeforeRead == MaxBufferSize) {
- abort();
- return 0;
- }
-
- while (bytesAvailable() > 0 && buffer.size() < maxSize) {
- buffer.append(read(1));
- if (buffer.endsWith(SeparatorToken))
- break;
- }
- return buffer.size() - numBytesBeforeRead;
+ if (!reader.device())
+ reader.setDevice(this);
}
-int Connection::dataLengthForCurrentDataType()
+void Connection::processGreeting()
{
- if (bytesAvailable() <= 0 || readDataIntoBuffer() <= 0
- || !buffer.endsWith(SeparatorToken))
- return 0;
-
- buffer.chop(1);
- int number = buffer.toInt();
+ username = buffer + '@' + peerAddress().toString() + ':'
+ + QString::number(peerPort());
+ currentDataType = Undefined;
buffer.clear();
- return number;
-}
-
-bool Connection::readProtocolHeader()
-{
- if (transferTimerId) {
- killTimer(transferTimerId);
- transferTimerId = 0;
- }
-
- if (readDataIntoBuffer() <= 0) {
- transferTimerId = startTimer(TransferTimeout);
- return false;
- }
- if (buffer == "PING ") {
- currentDataType = Ping;
- } else if (buffer == "PONG ") {
- currentDataType = Pong;
- } else if (buffer == "MESSAGE ") {
- currentDataType = PlainText;
- } else if (buffer == "GREETING ") {
- currentDataType = Greeting;
- } else {
- currentDataType = Undefined;
+ if (!isValid()) {
abort();
- return false;
- }
-
- buffer.clear();
- numBytesForCurrentDataType = dataLengthForCurrentDataType();
- return true;
-}
-
-bool Connection::hasEnoughData()
-{
- if (transferTimerId) {
- QObject::killTimer(transferTimerId);
- transferTimerId = 0;
+ return;
}
- if (numBytesForCurrentDataType <= 0)
- numBytesForCurrentDataType = dataLengthForCurrentDataType();
-
- if (bytesAvailable() < numBytesForCurrentDataType
- || numBytesForCurrentDataType <= 0) {
- transferTimerId = startTimer(TransferTimeout);
- return false;
- }
+ if (!isGreetingMessageSent)
+ sendGreetingMessage();
- return true;
+ pingTimer.start();
+ pongTime.start();
+ state = ReadyForUse;
+ emit readyForUse();
}
void Connection::processData()
{
- buffer = read(numBytesForCurrentDataType);
- if (buffer.size() != numBytesForCurrentDataType) {
- abort();
- return;
- }
-
switch (currentDataType) {
case PlainText:
- emit newMessage(username, QString::fromUtf8(buffer));
+ emit newMessage(username, buffer);
break;
case Ping:
- write("PONG 1 p");
+ writer.startMap(1);
+ writer.append(Pong);
+ writer.append(nullptr); // no payload
+ writer.endMap();
break;
case Pong:
pongTime.restart();
@@ -280,6 +271,5 @@ void Connection::processData()
}
currentDataType = Undefined;
- numBytesForCurrentDataType = 0;
buffer.clear();
}
diff --git a/examples/network/network-chat/connection.h b/examples/network/network-chat/connection.h
index 67d25d4d1e..fa0671a522 100644
--- a/examples/network/network-chat/connection.h
+++ b/examples/network/network-chat/connection.h
@@ -51,10 +51,12 @@
#ifndef CONNECTION_H
#define CONNECTION_H
+#include <QCborStreamReader>
+#include <QCborStreamWriter>
+#include <QElapsedTimer>
#include <QHostAddress>
#include <QString>
#include <QTcpSocket>
-#include <QTime>
#include <QTimer>
static const int MaxBufferSize = 1024000;
@@ -78,6 +80,8 @@ public:
};
Connection(QObject *parent = 0);
+ Connection(qintptr socketDescriptor, QObject *parent = 0);
+ ~Connection();
QString name() const;
void setGreetingMessage(const QString &message);
@@ -96,20 +100,19 @@ private slots:
void sendGreetingMessage();
private:
- int readDataIntoBuffer(int maxSize = MaxBufferSize);
- int dataLengthForCurrentDataType();
- bool readProtocolHeader();
bool hasEnoughData();
+ void processGreeting();
void processData();
+ QCborStreamReader reader;
+ QCborStreamWriter writer;
QString greetingMessage;
QString username;
QTimer pingTimer;
- QTime pongTime;
- QByteArray buffer;
+ QElapsedTimer pongTime;
+ QString buffer;
ConnectionState state;
DataType currentDataType;
- int numBytesForCurrentDataType;
int transferTimerId;
bool isGreetingMessageSent;
};
diff --git a/examples/network/network-chat/peermanager.cpp b/examples/network/network-chat/peermanager.cpp
index c70cc5e56d..38fa2e8e50 100644
--- a/examples/network/network-chat/peermanager.cpp
+++ b/examples/network/network-chat/peermanager.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -62,16 +63,14 @@ PeerManager::PeerManager(Client *client)
{
this->client = client;
- QStringList envVariables;
- envVariables << "USERNAME" << "USER" << "USERDOMAIN"
- << "HOSTNAME" << "DOMAINNAME";
+ static const char *envVariables[] = {
+ "USERNAME", "USER", "USERDOMAIN", "HOSTNAME", "DOMAINNAME"
+ };
- QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
- foreach (QString string, envVariables) {
- if (environment.contains(string)) {
- username = environment.value(string).toUtf8();
+ for (const char *varname : envVariables) {
+ username = qEnvironmentVariable(varname);
+ if (!username.isNull())
break;
- }
}
if (username.isEmpty())
@@ -95,7 +94,7 @@ void PeerManager::setServerPort(int port)
serverPort = port;
}
-QByteArray PeerManager::userName() const
+QString PeerManager::userName() const
{
return username;
}
@@ -108,7 +107,7 @@ void PeerManager::startBroadcasting()
bool PeerManager::isLocalHostAddress(const QHostAddress &address)
{
foreach (QHostAddress localAddress, ipAddresses) {
- if (address == localAddress)
+ if (address.isEqual(localAddress))
return true;
}
return false;
@@ -116,9 +115,14 @@ bool PeerManager::isLocalHostAddress(const QHostAddress &address)
void PeerManager::sendBroadcastDatagram()
{
- QByteArray datagram(username);
- datagram.append('@');
- datagram.append(QByteArray::number(serverPort));
+ QByteArray datagram;
+ {
+ QCborStreamWriter writer(&datagram);
+ writer.startArray(2);
+ writer.append(username);
+ writer.append(serverPort);
+ writer.endArray();
+ }
bool validBroadcastAddresses = true;
foreach (QHostAddress address, broadcastAddresses) {
@@ -142,11 +146,27 @@ void PeerManager::readBroadcastDatagram()
&senderIp, &senderPort) == -1)
continue;
- QList<QByteArray> list = datagram.split('@');
- if (list.size() != 2)
- continue;
+ int senderServerPort;
+ {
+ // decode the datagram
+ QCborStreamReader reader(datagram);
+ if (reader.lastError() != QCborError::NoError || !reader.isArray())
+ continue;
+ if (!reader.isLengthKnown() || reader.length() != 2)
+ continue;
+
+ reader.enterContainer();
+ if (reader.lastError() != QCborError::NoError || !reader.isString())
+ continue;
+ while (reader.readString().status == QCborStreamReader::Ok) {
+ // we don't actually need the username right now
+ }
+
+ if (reader.lastError() != QCborError::NoError || !reader.isUnsignedInteger())
+ continue;
+ senderServerPort = reader.toInteger();
+ }
- int senderServerPort = list.at(1).toInt();
if (isLocalHostAddress(senderIp) && senderServerPort == serverPort)
continue;
diff --git a/examples/network/network-chat/peermanager.h b/examples/network/network-chat/peermanager.h
index 0bcd67579c..b79028235b 100644
--- a/examples/network/network-chat/peermanager.h
+++ b/examples/network/network-chat/peermanager.h
@@ -68,7 +68,7 @@ public:
PeerManager(Client *client);
void setServerPort(int port);
- QByteArray userName() const;
+ QString userName() const;
void startBroadcasting();
bool isLocalHostAddress(const QHostAddress &address);
@@ -87,7 +87,7 @@ private:
QList<QHostAddress> ipAddresses;
QUdpSocket broadcastSocket;
QTimer broadcastTimer;
- QByteArray username;
+ QString username;
int serverPort;
};
diff --git a/examples/network/network-chat/server.cpp b/examples/network/network-chat/server.cpp
index cc154728d5..b3e4a07f60 100644
--- a/examples/network/network-chat/server.cpp
+++ b/examples/network/network-chat/server.cpp
@@ -61,7 +61,6 @@ Server::Server(QObject *parent)
void Server::incomingConnection(qintptr socketDescriptor)
{
- Connection *connection = new Connection(this);
- connection->setSocketDescriptor(socketDescriptor);
+ Connection *connection = new Connection(socketDescriptor, this);
emit newConnection(connection);
}
diff --git a/examples/network/network.pro b/examples/network/network.pro
index d64b16c760..1556e26ab1 100644
--- a/examples/network/network.pro
+++ b/examples/network/network.pro
@@ -30,6 +30,7 @@ qtHaveModule(widgets) {
}
qtConfig(openssl): SUBDIRS += securesocketclient
+ qtConfig(dtls): SUBDIRS += secureudpserver secureudpclient
qtConfig(sctp): SUBDIRS += multistreamserver multistreamclient
}
diff --git a/examples/network/secureudpclient/addressdialog.cpp b/examples/network/secureudpclient/addressdialog.cpp
new file mode 100644
index 0000000000..ccb58c853c
--- /dev/null
+++ b/examples/network/secureudpclient/addressdialog.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 "addressdialog.h"
+#include "ui_addressdialog.h"
+
+#include <QtCore>
+#include <QtNetwork>
+#include <QtWidgets>
+
+#include <limits>
+
+AddressDialog::AddressDialog(QWidget *parent)
+ : QDialog(parent),
+ ui(new Ui::AddressDialog)
+{
+ ui->setupUi(this);
+ setupHostSelector();
+ setupPortSelector();
+}
+
+AddressDialog::~AddressDialog()
+{
+ delete ui;
+}
+
+QString AddressDialog::remoteName() const
+{
+ if (ui->addressSelector->count())
+ return ui->addressSelector->currentText();
+ return {};
+}
+
+quint16 AddressDialog::remotePort() const
+{
+ return quint16(ui->portSelector->text().toUInt());
+}
+
+void AddressDialog::setupHostSelector()
+{
+ QString name(QHostInfo::localHostName());
+ if (!name.isEmpty()) {
+ ui->addressSelector->addItem(name);
+ const QString domain = QHostInfo::localDomainName();
+ if (!domain.isEmpty())
+ ui->addressSelector->addItem(name + QChar('.') + domain);
+ }
+
+ if (name != QStringLiteral("localhost"))
+ ui->addressSelector->addItem(QStringLiteral("localhost"));
+
+ const QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
+ for (const QHostAddress &ipAddress : ipAddressesList) {
+ if (!ipAddress.isLoopback())
+ ui->addressSelector->addItem(ipAddress.toString());
+ }
+
+ ui->addressSelector->insertSeparator(ui->addressSelector->count());
+
+ for (const QHostAddress &ipAddress : ipAddressesList) {
+ if (ipAddress.isLoopback())
+ ui->addressSelector->addItem(ipAddress.toString());
+ }
+}
+
+void AddressDialog::setupPortSelector()
+{
+ ui->portSelector->setValidator(new QIntValidator(0, std::numeric_limits<quint16>::max(),
+ ui->portSelector));
+ ui->portSelector->setText(QStringLiteral("22334"));
+}
diff --git a/examples/network/secureudpclient/addressdialog.h b/examples/network/secureudpclient/addressdialog.h
new file mode 100644
index 0000000000..43792faa4b
--- /dev/null
+++ b/examples/network/secureudpclient/addressdialog.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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$
+**
+****************************************************************************/
+#ifndef ADDRESSDIALOG_H
+#define ADDRESSDIALOG_H
+
+#include <QDialog>
+
+QT_BEGIN_NAMESPACE
+
+namespace Ui {
+
+class AddressDialog;
+
+}
+
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+class AddressDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit AddressDialog(QWidget *parent = nullptr);
+ ~AddressDialog();
+
+ QString remoteName() const;
+ quint16 remotePort() const;
+
+private:
+ void setupHostSelector();
+ void setupPortSelector();
+
+ Ui::AddressDialog *ui = nullptr;
+};
+
+#endif // ADDRESSDIALOG_H
diff --git a/examples/network/secureudpclient/addressdialog.ui b/examples/network/secureudpclient/addressdialog.ui
new file mode 100644
index 0000000000..a7d9bdc253
--- /dev/null
+++ b/examples/network/secureudpclient/addressdialog.ui
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AddressDialog</class>
+ <widget class="QDialog" name="AddressDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>548</width>
+ <height>143</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Host info</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Host name (server's address):</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="addressSelector">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>320</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>320</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ <property name="frame">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Server port:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="portSelector">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>320</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>320</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>AddressDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>AddressDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/examples/network/secureudpclient/association.cpp b/examples/network/secureudpclient/association.cpp
new file mode 100644
index 0000000000..c950260078
--- /dev/null
+++ b/examples/network/secureudpclient/association.cpp
@@ -0,0 +1,197 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 "association.h"
+
+QT_BEGIN_NAMESPACE
+
+DtlsAssociation::DtlsAssociation(const QHostAddress &address, quint16 port,
+ const QString &connectionName)
+ : name(connectionName),
+ crypto(QSslSocket::SslClientMode)
+{
+ //! [1]
+ auto configuration = QSslConfiguration::defaultDtlsConfiguration();
+ configuration.setPeerVerifyMode(QSslSocket::VerifyNone);
+ crypto.setPeer(address, port);
+ crypto.setDtlsConfiguration(configuration);
+ //! [1]
+
+ //! [2]
+ connect(&crypto, &QDtls::handshakeTimeout, this, &DtlsAssociation::handshakeTimeout);
+ //! [2]
+ connect(&crypto, &QDtls::pskRequired, this, &DtlsAssociation::pskRequired);
+ //! [3]
+ socket.connectToHost(address.toString(), port);
+ //! [3]
+ //! [13]
+ connect(&socket, &QUdpSocket::readyRead, this, &DtlsAssociation::readyRead);
+ //! [13]
+ //! [4]
+ pingTimer.setInterval(5000);
+ connect(&pingTimer, &QTimer::timeout, this, &DtlsAssociation::pingTimeout);
+ //! [4]
+}
+
+//! [12]
+DtlsAssociation::~DtlsAssociation()
+{
+ if (crypto.isConnectionEncrypted())
+ crypto.shutdown(&socket);
+}
+//! [12]
+
+//! [5]
+void DtlsAssociation::startHandshake()
+{
+ if (socket.state() != QAbstractSocket::ConnectedState) {
+ emit infoMessage(tr("%1: connecting UDP socket first ...").arg(name));
+ connect(&socket, &QAbstractSocket::connected, this, &DtlsAssociation::udpSocketConnected);
+ return;
+ }
+
+ if (!crypto.doHandshake(&socket))
+ emit errorMessage(tr("%1: failed to start a handshake - %2").arg(name, crypto.dtlsErrorString()));
+ else
+ emit infoMessage(tr("%1: starting a handshake").arg(name));
+}
+//! [5]
+
+void DtlsAssociation::udpSocketConnected()
+{
+ emit infoMessage(tr("%1: UDP socket is now in ConnectedState, continue with handshake ...").arg(name));
+ startHandshake();
+}
+
+void DtlsAssociation::readyRead()
+{
+ //! [6]
+ QByteArray dgram(socket.pendingDatagramSize(), Qt::Uninitialized);
+ const qint64 bytesRead = socket.readDatagram(dgram.data(), dgram.size());
+ if (bytesRead <= 0) {
+ emit warningMessage(tr("%1: spurious read notification?").arg(name));
+ return;
+ }
+
+ dgram.resize(bytesRead);
+ //! [6]
+ //! [7]
+ if (crypto.isConnectionEncrypted()) {
+ const QByteArray plainText = crypto.decryptDatagram(&socket, dgram);
+ if (plainText.size()) {
+ emit serverResponse(name, dgram, plainText);
+ return;
+ }
+
+ if (crypto.dtlsError() == QDtlsError::RemoteClosedConnectionError) {
+ emit errorMessage(tr("%1: shutdown alert received").arg(name));
+ socket.close();
+ pingTimer.stop();
+ return;
+ }
+
+ emit warningMessage(tr("%1: zero-length datagram received?").arg(name));
+ } else {
+ //! [7]
+ //! [8]
+ if (!crypto.doHandshake(&socket, dgram)) {
+ emit errorMessage(tr("%1: handshake error - %2").arg(name, crypto.dtlsErrorString()));
+ return;
+ }
+ //! [8]
+
+ //! [9]
+ if (crypto.isConnectionEncrypted()) {
+ emit infoMessage(tr("%1: encrypted connection established!").arg(name));
+ pingTimer.start();
+ pingTimeout();
+ } else {
+ //! [9]
+ emit infoMessage(tr("%1: continuing with handshake ...").arg(name));
+ }
+ }
+}
+
+//! [11]
+void DtlsAssociation::handshakeTimeout()
+{
+ emit warningMessage(tr("%1: handshake timeout, trying to re-transmit").arg(name));
+ if (!crypto.handleTimeout(&socket))
+ emit errorMessage(tr("%1: failed to re-transmit - %2").arg(name, crypto.dtlsErrorString()));
+}
+//! [11]
+
+//! [14]
+void DtlsAssociation::pskRequired(QSslPreSharedKeyAuthenticator *auth)
+{
+ Q_ASSERT(auth);
+
+ emit infoMessage(tr("%1: providing pre-shared key ...").arg(name));
+ auth->setIdentity(name.toLatin1());
+ auth->setPreSharedKey(QByteArrayLiteral("\x1a\x2b\x3c\x4d\x5e\x6f"));
+}
+//! [14]
+
+//! [10]
+void DtlsAssociation::pingTimeout()
+{
+ static const QString message = QStringLiteral("I am %1, please, accept our ping %2");
+ const qint64 written = crypto.writeDatagramEncrypted(&socket, message.arg(name).arg(ping).toLatin1());
+ if (written <= 0) {
+ emit errorMessage(tr("%1: failed to send a ping - %2").arg(name, crypto.dtlsErrorString()));
+ pingTimer.stop();
+ return;
+ }
+
+ ++ping;
+}
+//! [10]
+
+QT_END_NAMESPACE
diff --git a/examples/network/secureudpclient/association.h b/examples/network/secureudpclient/association.h
new file mode 100644
index 0000000000..be89ce695e
--- /dev/null
+++ b/examples/network/secureudpclient/association.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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$
+**
+****************************************************************************/
+#ifndef ASSOCIATION_H
+#define ASSOCIATION_H
+
+#include <QtNetwork>
+#include <QtCore>
+
+QT_BEGIN_NAMESPACE
+
+//! [0]
+class DtlsAssociation : public QObject
+{
+ Q_OBJECT
+
+public:
+ DtlsAssociation(const QHostAddress &address, quint16 port,
+ const QString &connectionName);
+ ~DtlsAssociation();
+ void startHandshake();
+
+signals:
+ void errorMessage(const QString &message);
+ void warningMessage(const QString &message);
+ void infoMessage(const QString &message);
+ void serverResponse(const QString &clientInfo, const QByteArray &datagraam,
+ const QByteArray &plainText);
+
+private slots:
+ void udpSocketConnected();
+ void readyRead();
+ void handshakeTimeout();
+ void pskRequired(QSslPreSharedKeyAuthenticator *auth);
+ void pingTimeout();
+
+private:
+ QString name;
+ QUdpSocket socket;
+ QDtls crypto;
+
+ QTimer pingTimer;
+ unsigned ping = 0;
+
+ Q_DISABLE_COPY(DtlsAssociation)
+};
+//! [0]
+
+QT_END_NAMESPACE
+
+#endif // ASSOCIATION_H
diff --git a/examples/network/secureudpclient/main.cpp b/examples/network/secureudpclient/main.cpp
new file mode 100644
index 0000000000..2cf35878f2
--- /dev/null
+++ b/examples/network/secureudpclient/main.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 "mainwindow.h"
+
+int main(int argc, char *argv[])
+{
+ QT_USE_NAMESPACE
+
+ QApplication app(argc, argv);
+ MainWindow window;
+ window.show();
+
+ return app.exec();
+}
diff --git a/examples/network/secureudpclient/mainwindow.cpp b/examples/network/secureudpclient/mainwindow.cpp
new file mode 100644
index 0000000000..2fbf757c81
--- /dev/null
+++ b/examples/network/secureudpclient/mainwindow.cpp
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 <QtCore>
+#include <QtNetwork>
+
+#include "addressdialog.h"
+#include "association.h"
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+
+#include <utility>
+
+MainWindow::MainWindow(QWidget *parent)
+ : QMainWindow(parent),
+ ui(new Ui::MainWindow),
+ nameTemplate(QStringLiteral("Alice (clone number %1)"))
+{
+ ui->setupUi(this);
+ updateUi();
+}
+
+MainWindow::~MainWindow()
+{
+ delete ui;
+}
+
+//! [0]
+
+const QString colorizer(QStringLiteral("<font color=\"%1\">%2</font><br>"));
+
+void MainWindow::addErrorMessage(const QString &message)
+{
+ ui->clientMessages->insertHtml(colorizer.arg(QStringLiteral("Crimson"), message));
+}
+
+void MainWindow::addWarningMessage(const QString &message)
+{
+ ui->clientMessages->insertHtml(colorizer.arg(QStringLiteral("DarkOrange"), message));
+}
+
+void MainWindow::addInfoMessage(const QString &message)
+{
+ ui->clientMessages->insertHtml(colorizer.arg(QStringLiteral("DarkBlue"), message));
+}
+
+void MainWindow::addServerResponse(const QString &clientInfo, const QByteArray &datagram,
+ const QByteArray &plainText)
+{
+ static const QString messageColor = QStringLiteral("DarkMagenta");
+ static const QString formatter = QStringLiteral("<br>---------------"
+ "<br>%1 received a DTLS datagram:<br> %2"
+ "<br>As plain text:<br> %3");
+
+ const QString html = formatter.arg(clientInfo, QString::fromUtf8(datagram.toHex(' ')),
+ QString::fromUtf8(plainText));
+ ui->serverMessages->insertHtml(colorizer.arg(messageColor, html));
+}
+
+//! [0]
+
+void MainWindow::on_connectButton_clicked()
+{
+ if (lookupId != -1) {
+ QHostInfo::abortHostLookup(lookupId);
+ lookupId = -1;
+ port = 0;
+ updateUi();
+ return;
+ }
+
+ AddressDialog dialog;
+ if (dialog.exec() != QDialog::Accepted)
+ return;
+
+ const QString hostName = dialog.remoteName();
+ if (hostName.isEmpty())
+ return addWarningMessage(tr("Host name or address required to connect"));
+
+ port = dialog.remotePort();
+ QHostAddress remoteAddress;
+ if (remoteAddress.setAddress(hostName))
+ return startNewConnection(remoteAddress);
+
+ addInfoMessage(tr("Looking up the host ..."));
+ lookupId = QHostInfo::lookupHost(hostName, this, SLOT(lookupFinished(QHostInfo)));
+ updateUi();
+}
+
+void MainWindow::updateUi()
+{
+ ui->connectButton->setText(lookupId == -1 ? tr("Connect ...") : tr("Cancel lookup"));
+ ui->shutdownButton->setEnabled(connections.size() != 0);
+}
+
+void MainWindow::lookupFinished(const QHostInfo &hostInfo)
+{
+ if (hostInfo.lookupId() != lookupId)
+ return;
+
+ lookupId = -1;
+ updateUi();
+
+ if (hostInfo.error() != QHostInfo::NoError) {
+ addErrorMessage(hostInfo.errorString());
+ return;
+ }
+
+ const QList<QHostAddress> foundAddresses = hostInfo.addresses();
+ if (foundAddresses.empty()) {
+ addWarningMessage(tr("Host not found"));
+ return;
+ }
+
+ const auto remoteAddress = foundAddresses.at(0);
+ addInfoMessage(tr("Connecting to: %1").arg(remoteAddress.toString()));
+ startNewConnection(remoteAddress);
+}
+
+void MainWindow::startNewConnection(const QHostAddress &address)
+{
+ AssocPtr newConnection(new DtlsAssociation(address, port, nameTemplate.arg(nextId)));
+ connect(newConnection.data(), &DtlsAssociation::errorMessage, this, &MainWindow::addErrorMessage);
+ connect(newConnection.data(), &DtlsAssociation::warningMessage, this, &MainWindow::addWarningMessage);
+ connect(newConnection.data(), &DtlsAssociation::infoMessage, this, &MainWindow::addInfoMessage);
+ connect(newConnection.data(), &DtlsAssociation::serverResponse, this, &MainWindow::addServerResponse);
+ connections.push_back(std::move(newConnection));
+ connections.back()->startHandshake();
+ updateUi();
+
+ ++nextId;
+}
+
+void MainWindow::on_shutdownButton_clicked()
+{
+ connections.clear();
+ updateUi();
+}
diff --git a/examples/network/secureudpclient/mainwindow.h b/examples/network/secureudpclient/mainwindow.h
new file mode 100644
index 0000000000..0d443fd376
--- /dev/null
+++ b/examples/network/secureudpclient/mainwindow.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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$
+**
+****************************************************************************/
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QMainWindow>
+#include <QSharedPointer>
+#include <QVector>
+
+QT_BEGIN_NAMESPACE
+
+namespace Ui {
+
+class MainWindow;
+
+}
+
+class QHostAddress;
+class QHostInfo;
+
+class DtlsAssociation;
+
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindow(QWidget *parent = nullptr);
+ ~MainWindow();
+
+private slots:
+
+ void addErrorMessage(const QString &message);
+ void addWarningMessage(const QString &message);
+ void addInfoMessage(const QString &message);
+ void addServerResponse(const QString &clientInfo, const QByteArray &datagram,
+ const QByteArray &plainText);
+
+ void on_connectButton_clicked();
+ void on_shutdownButton_clicked();
+
+ void lookupFinished(const QHostInfo &hostInfo);
+
+private:
+ void updateUi();
+ void startNewConnection(const QHostAddress &address);
+
+ Ui::MainWindow *ui = nullptr;
+
+ using AssocPtr = QSharedPointer<DtlsAssociation>;
+ QVector<AssocPtr> connections;
+
+ QString nameTemplate;
+ unsigned nextId = 0;
+
+ quint16 port = 0;
+ int lookupId = -1;
+};
+
+#endif // MAINWINDOW_H
diff --git a/examples/network/secureudpclient/mainwindow.ui b/examples/network/secureudpclient/mainwindow.ui
new file mode 100644
index 0000000000..59a31974ee
--- /dev/null
+++ b/examples/network/secureudpclient/mainwindow.ui
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1200</width>
+ <height>550</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>1200</width>
+ <height>550</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>1200</width>
+ <height>550</height>
+ </size>
+ </property>
+ <property name="windowTitle">
+ <string>DTLS client</string>
+ </property>
+ <widget class="QWidget" name="centralwidget">
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>590</width>
+ <height>400</height>
+ </size>
+ </property>
+ <property name="title">
+ <string>DTLS info messages:</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <widget class="QTextEdit" name="clientMessages">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>30</y>
+ <width>570</width>
+ <height>360</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>570</width>
+ <height>360</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>570</width>
+ <height>360</height>
+ </size>
+ </property>
+ <property name="acceptDrops">
+ <bool>false</bool>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QPushButton" name="connectButton">
+ <property name="text">
+ <string>Connect ...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="shutdownButton">
+ <property name="text">
+ <string>Shutdown connections</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="minimumSize">
+ <size>
+ <width>580</width>
+ <height>490</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>580</width>
+ <height>490</height>
+ </size>
+ </property>
+ <property name="title">
+ <string>Received datagrams:</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <widget class="QTextEdit" name="serverMessages">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>30</y>
+ <width>560</width>
+ <height>450</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>560</width>
+ <height>450</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>560</width>
+ <height>450</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QMenuBar" name="menubar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1200</width>
+ <height>22</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QStatusBar" name="statusbar"/>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/examples/network/secureudpclient/secureudpclient.pro b/examples/network/secureudpclient/secureudpclient.pro
new file mode 100644
index 0000000000..44e4200994
--- /dev/null
+++ b/examples/network/secureudpclient/secureudpclient.pro
@@ -0,0 +1,22 @@
+QT += widgets network
+
+TARGET = secureudpclient
+TEMPLATE = app
+
+SOURCES += \
+ main.cpp \
+ association.cpp \
+ mainwindow.cpp \
+ addressdialog.cpp
+
+HEADERS += \
+ association.h \
+ mainwindow.h \
+ addressdialog.h
+
+FORMS += \
+ mainwindow.ui \
+ addressdialog.ui
+
+target.path = $$[QT_INSTALL_EXAMPLES]/network/secureudpclient
+INSTALLS += target
diff --git a/examples/network/secureudpserver/main.cpp b/examples/network/secureudpserver/main.cpp
new file mode 100644
index 0000000000..1a29d9d7ec
--- /dev/null
+++ b/examples/network/secureudpserver/main.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 "mainwindow.h"
+
+int main(int argc, char *argv[])
+{
+ QT_USE_NAMESPACE
+
+ QApplication a(argc, argv);
+ MainWindow w;
+ w.show();
+
+ return a.exec();
+}
diff --git a/examples/network/secureudpserver/mainwindow.cpp b/examples/network/secureudpserver/mainwindow.cpp
new file mode 100644
index 0000000000..ef1974c311
--- /dev/null
+++ b/examples/network/secureudpserver/mainwindow.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 "mainwindow.h"
+#include "nicselector.h"
+#include "ui_mainwindow.h"
+
+MainWindow::MainWindow()
+ : ui(new Ui::MainWindow)
+{
+ ui->setupUi(this);
+
+ connect(&server, &DtlsServer::errorMessage, this, &MainWindow::addErrorMessage);
+ connect(&server, &DtlsServer::warningMessage, this, &MainWindow::addWarningMessage);
+ connect(&server, &DtlsServer::infoMessage, this, &MainWindow::addInfoMessage);
+ connect(&server, &DtlsServer::datagramReceived, this, &MainWindow::addClientMessage);
+
+ updateUi();
+}
+
+MainWindow::~MainWindow()
+{
+ delete ui;
+}
+
+void MainWindow::on_startButton_clicked()
+{
+ if (!server.isListening()) {
+ NicSelector ipDialog;
+ if (ipDialog.exec() == QDialog::Accepted) {
+ const QHostAddress address = ipDialog.selectedIp();
+ const quint16 port = ipDialog.selectedPort();
+ if (address.isNull()) {
+ addErrorMessage(tr("Failed to start listening, no valid address/port"));
+ } else if (server.listen(address, port)) {
+ addInfoMessage(tr("Server is listening on address %1 and port %2")
+ .arg(address.toString())
+ .arg(port));
+ }
+ }
+ } else {
+ server.close();
+ addInfoMessage(tr("Server is not accepting new connections"));
+ }
+
+ updateUi();
+}
+
+void MainWindow::on_quitButton_clicked()
+{
+ QCoreApplication::exit(0);
+}
+
+void MainWindow::updateUi()
+{
+ server.isListening() ? ui->startButton->setText(tr("Stop listening"))
+ : ui->startButton->setText(tr("Start listening"));
+}
+
+//! [0]
+const QString colorizer(QStringLiteral("<font color=\"%1\">%2</font><br>"));
+
+void MainWindow::addErrorMessage(const QString &message)
+{
+ ui->serverInfo->insertHtml(colorizer.arg(QStringLiteral("Crimson"), message));
+}
+
+void MainWindow::addWarningMessage(const QString &message)
+{
+ ui->serverInfo->insertHtml(colorizer.arg(QStringLiteral("DarkOrange"), message));
+}
+
+void MainWindow::addInfoMessage(const QString &message)
+{
+ ui->serverInfo->insertHtml(colorizer.arg(QStringLiteral("DarkBlue"), message));
+}
+
+void MainWindow::addClientMessage(const QString &peerInfo, const QByteArray &datagram,
+ const QByteArray &plainText)
+{
+ static const QString messageColor = QStringLiteral("DarkMagenta");
+ static const QString formatter = QStringLiteral("<br>---------------"
+ "<br>A message from %1"
+ "<br>DTLS datagram:<br> %2"
+ "<br>As plain text:<br> %3");
+
+ const QString html = formatter.arg(peerInfo, QString::fromUtf8(datagram.toHex(' ')),
+ QString::fromUtf8(plainText));
+ ui->messages->insertHtml(colorizer.arg(messageColor, html));
+}
+//! [0]
diff --git a/examples/network/secureudpserver/mainwindow.h b/examples/network/secureudpserver/mainwindow.h
new file mode 100644
index 0000000000..b39d984d50
--- /dev/null
+++ b/examples/network/secureudpserver/mainwindow.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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$
+**
+****************************************************************************/
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include "server.h"
+
+#include <QMainWindow>
+
+QT_BEGIN_NAMESPACE
+
+namespace Ui {
+class MainWindow;
+}
+
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ MainWindow();
+ ~MainWindow();
+
+private slots:
+ void addErrorMessage(const QString &message);
+ void addWarningMessage(const QString &message);
+ void addInfoMessage(const QString &message);
+ void addClientMessage(const QString &peerInfo, const QByteArray &datagram,
+ const QByteArray &plainText);
+
+ void on_startButton_clicked();
+ void on_quitButton_clicked();
+
+private:
+ void updateUi();
+
+ Ui::MainWindow *ui = nullptr;
+ DtlsServer server;
+};
+
+#endif // MAINWINDOW_H
diff --git a/examples/network/secureudpserver/mainwindow.ui b/examples/network/secureudpserver/mainwindow.ui
new file mode 100644
index 0000000000..e25e19921b
--- /dev/null
+++ b/examples/network/secureudpserver/mainwindow.ui
@@ -0,0 +1,207 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1090</width>
+ <height>670</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>1090</width>
+ <height>670</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>1090</width>
+ <height>670</height>
+ </size>
+ </property>
+ <property name="windowTitle">
+ <string>DTLS server</string>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ <widget class="QWidget" name="layoutWidget">
+ <property name="geometry">
+ <rect>
+ <x>20</x>
+ <y>20</y>
+ <width>1050</width>
+ <height>576</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QGroupBox" name="infoBox">
+ <property name="minimumSize">
+ <size>
+ <width>520</width>
+ <height>540</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>520</width>
+ <height>540</height>
+ </size>
+ </property>
+ <property name="title">
+ <string>Dtls server info:</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <widget class="QTextEdit" name="serverInfo">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>30</y>
+ <width>500</width>
+ <height>500</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>500</width>
+ <height>500</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>500</width>
+ <height>500</height>
+ </size>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="minimumSize">
+ <size>
+ <width>520</width>
+ <height>540</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>520</width>
+ <height>540</height>
+ </size>
+ </property>
+ <property name="title">
+ <string>Received messages:</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <widget class="QTextEdit" name="messages">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>30</y>
+ <width>500</width>
+ <height>500</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>500</width>
+ <height>500</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>500</width>
+ <height>500</height>
+ </size>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="startButton">
+ <property name="text">
+ <string>Start listening</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="quitButton">
+ <property name="text">
+ <string>Quit</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <widget class="QMenuBar" name="menuBar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1090</width>
+ <height>22</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QToolBar" name="mainToolBar">
+ <attribute name="toolBarArea">
+ <enum>TopToolBarArea</enum>
+ </attribute>
+ <attribute name="toolBarBreak">
+ <bool>false</bool>
+ </attribute>
+ </widget>
+ <widget class="QStatusBar" name="statusBar"/>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/examples/network/secureudpserver/nicselector.cpp b/examples/network/secureudpserver/nicselector.cpp
new file mode 100644
index 0000000000..ea26439d74
--- /dev/null
+++ b/examples/network/secureudpserver/nicselector.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 <limits>
+
+#include <QtCore>
+#include <QtNetwork>
+
+#include "nicselector.h"
+#include "ui_nicselector.h"
+
+NicSelector::NicSelector(QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::NicSelector)
+{
+ ui->setupUi(this);
+ auto portValidator = new QIntValidator(0, int(std::numeric_limits<quint16>::max()),
+ ui->portSelector);
+ ui->portSelector->setValidator(portValidator);
+ ui->portSelector->setText(QStringLiteral("22334"));
+
+ const QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
+ availableAddresses.reserve(ipAddressesList.size());
+ for (const QHostAddress &ip : ipAddressesList) {
+ if (ip != QHostAddress::LocalHost && ip.toIPv4Address()) {
+ availableAddresses.push_back(ip);
+ ui->ipSelector->addItem(ip.toString());
+ }
+ }
+}
+
+NicSelector::~NicSelector()
+{
+ delete ui;
+}
+
+QHostAddress NicSelector::selectedIp() const
+{
+ if (!availableAddresses.size())
+ return {};
+
+ return availableAddresses[ui->ipSelector->currentIndex()];
+}
+
+quint16 NicSelector::selectedPort() const
+{
+ return quint16(ui->portSelector->text().toUInt());
+}
diff --git a/examples/network/secureudpserver/nicselector.h b/examples/network/secureudpserver/nicselector.h
new file mode 100644
index 0000000000..7962a78318
--- /dev/null
+++ b/examples/network/secureudpserver/nicselector.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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$
+**
+****************************************************************************/
+
+#ifndef NICSELECTOR_H
+#define NICSELECTOR_H
+
+#include <QDialog>
+#include <QHostAddress>
+#include <QVector>
+
+QT_BEGIN_NAMESPACE
+
+namespace Ui {
+class NicSelector;
+}
+
+QT_END_NAMESPACE
+
+QT_USE_NAMESPACE
+
+class NicSelector : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit NicSelector(QWidget *parent = nullptr);
+ ~NicSelector();
+
+ QHostAddress selectedIp() const;
+ quint16 selectedPort() const;
+
+private:
+ Ui::NicSelector *ui = nullptr;
+ QVector<QHostAddress> availableAddresses;
+};
+
+#endif // NICSELECTOR_H
diff --git a/examples/network/secureudpserver/nicselector.ui b/examples/network/secureudpserver/nicselector.ui
new file mode 100644
index 0000000000..b0ba376b66
--- /dev/null
+++ b/examples/network/secureudpserver/nicselector.ui
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>NicSelector</class>
+ <widget class="QDialog" name="NicSelector">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>373</width>
+ <height>213</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>IP and port</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetFixedSize</enum>
+ </property>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Listen on address:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="ipSelector">
+ <property name="minimumSize">
+ <size>
+ <width>250</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetFixedSize</enum>
+ </property>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Port:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="portSelector">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>NicSelector</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>NicSelector</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/examples/network/secureudpserver/secureudpserver.pro b/examples/network/secureudpserver/secureudpserver.pro
new file mode 100644
index 0000000000..910655aae4
--- /dev/null
+++ b/examples/network/secureudpserver/secureudpserver.pro
@@ -0,0 +1,21 @@
+QT += widgets network
+
+TARGET = secureudpserver
+TEMPLATE = app
+
+SOURCES += \
+ main.cpp \
+ mainwindow.cpp \
+ server.cpp \
+ nicselector.cpp
+
+HEADERS += \
+ mainwindow.h \
+ server.h \
+ nicselector.h
+
+FORMS = mainwindow.ui \
+ nicselector.ui
+
+target.path = $$[QT_INSTALL_EXAMPLES]/network/secureudpserver
+INSTALLS += target
diff --git a/examples/network/secureudpserver/server.cpp b/examples/network/secureudpserver/server.cpp
new file mode 100644
index 0000000000..0d83fa9b51
--- /dev/null
+++ b/examples/network/secureudpserver/server.cpp
@@ -0,0 +1,277 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 "server.h"
+
+#include <algorithm>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+
+QString peer_info(const QHostAddress &address, quint16 port)
+{
+ const static QString info = QStringLiteral("(%1:%2)");
+ return info.arg(address.toString()).arg(port);
+}
+
+QString connection_info(QSharedPointer<QDtls> connection)
+{
+ QString info(DtlsServer::tr("Session cipher: "));
+ info += connection->sessionCipher().name();
+
+ info += DtlsServer::tr("; session protocol: ");
+ switch (connection->sessionProtocol()) {
+ case QSsl::DtlsV1_0:
+ info += DtlsServer::tr("DTLS 1.0.");
+ break;
+ case QSsl::DtlsV1_2:
+ info += DtlsServer::tr("DTLS 1.2.");
+ break;
+ case QSsl::DtlsV1_2OrLater:
+ info += DtlsServer::tr("DTLS 1.2 or later.");
+ break;
+ default:
+ info += DtlsServer::tr("Unknown protocol.");
+ }
+
+ return info;
+}
+
+} // unnamed namespace
+
+//! [1]
+DtlsServer::DtlsServer()
+{
+ connect(&serverSocket, &QAbstractSocket::readyRead, this, &DtlsServer::readyRead);
+
+ serverConfiguration = QSslConfiguration::defaultDtlsConfiguration();
+ serverConfiguration.setPreSharedKeyIdentityHint("Qt DTLS example server");
+ serverConfiguration.setPeerVerifyMode(QSslSocket::VerifyNone);
+}
+//! [1]
+
+DtlsServer::~DtlsServer()
+{
+ shutdown();
+}
+
+//! [2]
+bool DtlsServer::listen(const QHostAddress &address, quint16 port)
+{
+ if (address != serverSocket.localAddress() || port != serverSocket.localPort()) {
+ shutdown();
+ listening = serverSocket.bind(address, port);
+ if (!listening)
+ emit errorMessage(serverSocket.errorString());
+ } else {
+ listening = true;
+ }
+
+ return listening;
+}
+//! [2]
+
+bool DtlsServer::isListening() const
+{
+ return listening;
+}
+
+void DtlsServer::close()
+{
+ listening = false;
+}
+
+void DtlsServer::readyRead()
+{
+ //! [3]
+ const qint64 bytesToRead = serverSocket.pendingDatagramSize();
+ if (bytesToRead <= 0) {
+ emit warningMessage(tr("A spurious read notification"));
+ return;
+ }
+
+ QByteArray dgram(bytesToRead, Qt::Uninitialized);
+ QHostAddress peerAddress;
+ quint16 peerPort = 0;
+ const qint64 bytesRead = serverSocket.readDatagram(dgram.data(), dgram.size(),
+ &peerAddress, &peerPort);
+ if (bytesRead <= 0) {
+ emit warningMessage(tr("Failed to read a datagram: ") + serverSocket.errorString());
+ return;
+ }
+
+ dgram.resize(bytesRead);
+ //! [3]
+ //! [4]
+ if (peerAddress.isNull() || !peerPort) {
+ emit warningMessage(tr("Failed to extract peer info (address, port)"));
+ return;
+ }
+
+ const auto client = std::find_if(knownClients.begin(), knownClients.end(),
+ [&](const DtlsConnection &connection){
+ return connection->peerAddress() == peerAddress
+ && connection->peerPort() == peerPort;
+ });
+ //! [4]
+
+ //! [5]
+ if (client == knownClients.end())
+ return handleNewConnection(peerAddress, peerPort, dgram);
+ //! [5]
+
+ //! [6]
+ if ((*client)->isConnectionEncrypted()) {
+ decryptDatagram(*client, dgram);
+ if ((*client)->dtlsError() == QDtlsError::RemoteClosedConnectionError)
+ knownClients.erase(client);
+ return;
+ }
+ //! [6]
+
+ //! [7]
+ doHandshake(*client, dgram);
+ //! [7]
+}
+
+//! [13]
+void DtlsServer::pskRequired(QSslPreSharedKeyAuthenticator *auth)
+{
+ Q_ASSERT(auth);
+
+ emit infoMessage(tr("PSK callback, received a client's identity: '%1'")
+ .arg(QString::fromLatin1(auth->identity())));
+ auth->setPreSharedKey(QByteArrayLiteral("\x1a\x2b\x3c\x4d\x5e\x6f"));
+}
+//! [13]
+
+//! [8]
+void DtlsServer::handleNewConnection(const QHostAddress &peerAddress,
+ quint16 peerPort, const QByteArray &clientHello)
+{
+ if (!listening)
+ return;
+
+ const QString peerInfo = peer_info(peerAddress, peerPort);
+ if (cookieSender.verifyClient(&serverSocket, clientHello, peerAddress, peerPort)) {
+ emit infoMessage(peerInfo + tr(": verified, starting a handshake"));
+ //! [8]
+ //! [9]
+ DtlsConnection newConnection(new QDtls(QSslSocket::SslServerMode));
+ newConnection->setDtlsConfiguration(serverConfiguration);
+ newConnection->setPeer(peerAddress, peerPort);
+ newConnection->connect(newConnection.data(), &QDtls::pskRequired,
+ this, &DtlsServer::pskRequired);
+ knownClients.push_back(newConnection);
+ doHandshake(newConnection, clientHello);
+ //! [9]
+ } else if (cookieSender.dtlsError() != QDtlsError::NoError) {
+ emit errorMessage(tr("DTLS error: ") + cookieSender.dtlsErrorString());
+ } else {
+ emit infoMessage(peerInfo + tr(": not verified yet"));
+ }
+}
+
+//! [11]
+void DtlsServer::doHandshake(DtlsConnection newConnection, const QByteArray &clientHello)
+{
+ const bool result = newConnection->doHandshake(&serverSocket, clientHello);
+ if (!result) {
+ emit errorMessage(newConnection->dtlsErrorString());
+ return;
+ }
+
+ const QString peerInfo = peer_info(newConnection->peerAddress(),
+ newConnection->peerPort());
+ switch (newConnection->handshakeState()) {
+ case QDtls::HandshakeInProgress:
+ emit infoMessage(peerInfo + tr(": handshake is in progress ..."));
+ break;
+ case QDtls::HandshakeComplete:
+ emit infoMessage(tr("Connection with %1 encrypted. %2")
+ .arg(peerInfo, connection_info(newConnection)));
+ break;
+ default:
+ Q_UNREACHABLE();
+ }
+}
+//! [11]
+
+//! [12]
+void DtlsServer::decryptDatagram(DtlsConnection connection, const QByteArray &clientMessage)
+{
+ Q_ASSERT(connection->isConnectionEncrypted());
+
+ const QString peerInfo = peer_info(connection->peerAddress(), connection->peerPort());
+ const QByteArray dgram = connection->decryptDatagram(&serverSocket, clientMessage);
+ if (dgram.size()) {
+ emit datagramReceived(peerInfo, clientMessage, dgram);
+ connection->writeDatagramEncrypted(&serverSocket, tr("to %1: ACK").arg(peerInfo).toLatin1());
+ } else if (connection->dtlsError() == QDtlsError::NoError) {
+ emit warningMessage(peerInfo + ": " + tr("0 byte dgram, could be a re-connect attempt?"));
+ } else {
+ emit errorMessage(peerInfo + ": " + connection->dtlsErrorString());
+ }
+}
+//! [12]
+
+//! [14]
+void DtlsServer::shutdown()
+{
+ for (DtlsConnection &connection : knownClients)
+ connection->shutdown(&serverSocket);
+
+ knownClients.clear();
+ serverSocket.close();
+}
+//! [14]
+
+QT_END_NAMESPACE
diff --git a/examples/network/secureudpserver/server.h b/examples/network/secureudpserver/server.h
new file mode 100644
index 0000000000..b720368e7b
--- /dev/null
+++ b/examples/network/secureudpserver/server.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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$
+**
+****************************************************************************/
+#ifndef SERVER_H
+#define SERVER_H
+
+#include <QtCore>
+#include <QtNetwork>
+
+#include <vector>
+
+QT_BEGIN_NAMESPACE
+
+//! [0]
+class DtlsServer : public QObject
+{
+ Q_OBJECT
+
+public:
+ DtlsServer();
+ ~DtlsServer();
+
+ bool listen(const QHostAddress &address, quint16 port);
+ bool isListening() const;
+ void close();
+
+signals:
+ void errorMessage(const QString &message);
+ void warningMessage(const QString &message);
+ void infoMessage(const QString &message);
+
+ void datagramReceived(const QString &peerInfo, const QByteArray &cipherText,
+ const QByteArray &plainText);
+
+private slots:
+ void readyRead();
+ void pskRequired(QSslPreSharedKeyAuthenticator *auth);
+
+private:
+ void handleNewConnection(const QHostAddress &peerAddress, quint16 peerPort,
+ const QByteArray &clientHello);
+
+ using DtlsConnection = QSharedPointer<QDtls>;
+ void doHandshake(DtlsConnection newConnection, const QByteArray &clientHello);
+ void decryptDatagram(DtlsConnection connection, const QByteArray &clientMessage);
+ void shutdown();
+
+ bool listening = false;
+ QUdpSocket serverSocket;
+
+ QSslConfiguration serverConfiguration;
+ QDtlsClientVerifier cookieSender;
+ QVector<DtlsConnection> knownClients;
+
+ Q_DISABLE_COPY(DtlsServer)
+};
+//! [0]
+
+QT_END_NAMESPACE
+
+#endif // SERVER_H
diff --git a/examples/opengl/contextinfo/widget.cpp b/examples/opengl/contextinfo/widget.cpp
index fc21983f38..a5d9e98bf8 100644
--- a/examples/opengl/contextinfo/widget.cpp
+++ b/examples/opengl/contextinfo/widget.cpp
@@ -252,7 +252,7 @@ Widget::Widget(QWidget *parent)
if (QCoreApplication::testAttribute(Qt::AA_UseSoftwareOpenGL))
str << " Qt::AA_UseSoftwareOpenGL";
if (QCoreApplication::testAttribute(Qt::AA_UseDesktopOpenGL))
- str << " Qt::AA_UseSoftwareOpenGL";
+ str << " Qt::AA_UseDesktopOpenGL";
layout->addWidget(new QLabel(description));
setLayout(layout);
diff --git a/examples/opengl/qopenglwindow/main.cpp b/examples/opengl/qopenglwindow/main.cpp
index 4f008b45a6..8932269ddf 100644
--- a/examples/opengl/qopenglwindow/main.cpp
+++ b/examples/opengl/qopenglwindow/main.cpp
@@ -92,7 +92,6 @@ private:
QMatrix4x4 m_view;
QMatrix4x4 m_model_triangle;
QMatrix4x4 m_model_text;
- QBrush m_brush;
FragmentToy m_fragment_toy;
QStaticText m_text_layout;
@@ -111,16 +110,12 @@ OpenGLWindow::OpenGLWindow()
, m_text_layout("The triangle and this text is rendered with QPainter")
, m_animate(true)
{
+ setGeometry(300, 300, 500, 500);
+
m_view.lookAt(QVector3D(3,1,1),
QVector3D(0,0,0),
QVector3D(0,1,0));
- QLinearGradient gradient(QPointF(-1,-1), QPointF(1,1));
- gradient.setColorAt(0, Qt::red);
- gradient.setColorAt(1, Qt::green);
-
- m_brush = QBrush(gradient);
-
setAnimating(m_animate);
}
@@ -134,11 +129,11 @@ void OpenGLWindow::paintGL()
QMatrix4x4 mvp = m_projection * m_view * m_model_triangle;
p.setTransform(mvp.toTransform(), true);
- p.fillPath(painterPathForTriangle(), m_brush);
+ p.fillPath(painterPathForTriangle(), QBrush(QGradient(QGradient::NightFade)));
QTransform text_transform = (m_window_painter_matrix * m_view * m_model_text).toTransform();
p.setTransform(text_transform, false);
- p.setPen(QPen(Qt::white));
+ p.setPen(QPen(Qt::black));
m_text_layout.prepare(text_transform);
qreal x = - (m_text_layout.size().width() / 2);
qreal y = 0;
@@ -197,7 +192,7 @@ int main(int argc, char **argv)
fmt.setDepthBufferSize(24);
fmt.setStencilBufferSize(8);
window.setFormat(fmt);
- window.showMaximized();
+ window.show();
return app.exec();
}
diff --git a/examples/touch/dials/dials.pro b/examples/touch/dials/dials.pro
deleted file mode 100644
index 2c522a46f0..0000000000
--- a/examples/touch/dials/dials.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-QT += widgets
-
-SOURCES += main.cpp
-FORMS += dials.ui
-
-# install
-target.path = $$[QT_INSTALL_EXAMPLES]/touch/dials
-INSTALLS += target
diff --git a/examples/touch/dials/doc/src/touch-dials.qdoc b/examples/touch/dials/doc/src/touch-dials.qdoc
deleted file mode 100644
index 10784c8c0d..0000000000
--- a/examples/touch/dials/doc/src/touch-dials.qdoc
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE: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 touch/dials
- \title Touch Dials Example
- \ingroup touchinputexamples
- \brief Shows how to apply touch to a set of standard Qt widgets
-
- The Touch Dials example shows how to apply touch to a set of
- standard Qt widgets.
-
- \image touch-dials-example.png
-*/
diff --git a/examples/touch/fingerpaint/fingerpaint.pro b/examples/touch/fingerpaint/fingerpaint.pro
deleted file mode 100644
index f196f7eed4..0000000000
--- a/examples/touch/fingerpaint/fingerpaint.pro
+++ /dev/null
@@ -1,13 +0,0 @@
-QT += widgets
-requires(qtConfig(filedialog))
-qtHaveModule(printsupport): QT += printsupport
-
-HEADERS = mainwindow.h \
- scribblearea.h
-SOURCES = main.cpp \
- mainwindow.cpp \
- scribblearea.cpp
-
-# install
-target.path = $$[QT_INSTALL_EXAMPLES]/touch/fingerpaint
-INSTALLS += target
diff --git a/examples/touch/knobs/doc/src/touch-knobs.qdoc b/examples/touch/knobs/doc/src/touch-knobs.qdoc
deleted file mode 100644
index d39dd564b2..0000000000
--- a/examples/touch/knobs/doc/src/touch-knobs.qdoc
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE: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 touch/knobs
- \title Touch Knobs Example
- \ingroup touchinputexamples
- \brief Shows how to create custom controls that accept touch input
-
- The Touch Knobs example shows how to create custom controls that
- accept touch input.
-
- \image touch-knobs-example.png
-*/
diff --git a/examples/touch/knobs/knobs.pro b/examples/touch/knobs/knobs.pro
deleted file mode 100644
index 267ba26167..0000000000
--- a/examples/touch/knobs/knobs.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-QT += widgets
-
-HEADERS = knob.h
-SOURCES = main.cpp knob.cpp
-
-# install
-target.path = $$[QT_INSTALL_EXAMPLES]/touch/knobs
-INSTALLS += target
diff --git a/examples/touch/pinchzoom/pinchzoom.pro b/examples/touch/pinchzoom/pinchzoom.pro
deleted file mode 100644
index 9441cc1d92..0000000000
--- a/examples/touch/pinchzoom/pinchzoom.pro
+++ /dev/null
@@ -1,16 +0,0 @@
-QT += widgets
-
-HEADERS += \
- mouse.h \
- graphicsview.h
-SOURCES += \
- main.cpp \
- mouse.cpp \
- graphicsview.cpp
-
-RESOURCES += \
- mice.qrc
-
-# install
-target.path = $$[QT_INSTALL_EXAMPLES]/touch/pinchzoom
-INSTALLS += target
diff --git a/examples/vulkan/hellovulkantexture/hellovulkantexture.cpp b/examples/vulkan/hellovulkantexture/hellovulkantexture.cpp
index 67ae0ca5dc..257191ef4e 100644
--- a/examples/vulkan/hellovulkantexture/hellovulkantexture.cpp
+++ b/examples/vulkan/hellovulkantexture/hellovulkantexture.cpp
@@ -223,6 +223,16 @@ bool VulkanRenderer::createTextureImage(const QSize &size, VkImage *image, VkDev
VkMemoryRequirements memReq;
m_devFuncs->vkGetImageMemoryRequirements(dev, *image, &memReq);
+ if (!(memReq.memoryTypeBits & (1 << memIndex))) {
+ VkPhysicalDeviceMemoryProperties physDevMemProps;
+ m_window->vulkanInstance()->functions()->vkGetPhysicalDeviceMemoryProperties(m_window->physicalDevice(), &physDevMemProps);
+ for (uint32_t i = 0; i < physDevMemProps.memoryTypeCount; ++i) {
+ if (!(memReq.memoryTypeBits & (1 << i)))
+ continue;
+ memIndex = i;
+ }
+ }
+
VkMemoryAllocateInfo allocInfo = {
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
nullptr,
@@ -294,12 +304,12 @@ void VulkanRenderer::ensureTexture()
barrier.oldLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
- barrier.srcAccessMask = 0; // VK_ACCESS_HOST_WRITE_BIT ### no, keep validation layer happy (??)
+ 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_HOST_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
0, 0, nullptr, 0, nullptr,
1, &barrier);
@@ -312,7 +322,7 @@ void VulkanRenderer::ensureTexture()
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_HOST_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
0, 0, nullptr, 0, nullptr,
1, &barrier);
diff --git a/examples/widgets/doc/src/customsortfiltermodel.qdoc b/examples/widgets/doc/src/customsortfiltermodel.qdoc
index 6eab846e89..9f0d13dd83 100644
--- a/examples/widgets/doc/src/customsortfiltermodel.qdoc
+++ b/examples/widgets/doc/src/customsortfiltermodel.qdoc
@@ -121,14 +121,14 @@
\snippet itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp 6
- We use QRegExp to define a pattern for the addresses we are looking
- for. The QRegExp::indexIn() function attempts to find a match in
- the given string and returns the position of the first match, or
- -1 if there was no match. If the given string contains the
- pattern, we use QRegExp's \l {QRegExp::cap()}{cap()} function to
- retrieve the actual address. The \l {QRegExp::cap()}{cap()}
- function returns the text captured by the \e nth
- subexpression. The entire match has index 0 and the parenthesized
+ We use QRegularExpression to define a pattern for the addresses we
+ are looking for. The \l {QRegularExpression::match()}{match()} function
+ returns a QRegularExpressionMatch object which contains the result of
+ the matching. If there is a match,
+ \l {QRegularExpressionMatch::hasMatch()}{hasMatch()} returns true. The
+ result of the match can be retrieved with QRegularExpressionMatch's
+ \l {QRegularExpressionMatch::captured()}{captured()} function.
+ The entire match has index 0 and the parenthesized
subexpressions have indexes starting from 1 (excluding
non-capturing parentheses).
diff --git a/examples/widgets/doc/src/gradients.qdoc b/examples/widgets/doc/src/gradients.qdoc
index 936bd2b014..457e6f837a 100644
--- a/examples/widgets/doc/src/gradients.qdoc
+++ b/examples/widgets/doc/src/gradients.qdoc
@@ -51,7 +51,12 @@
gradient. You can move points, and add new ones, by clicking with the left
mouse button, and remove points by clicking with the right button.
- There are three default configurations available at the bottom of
+ There are three example configurations available at the bottom of
the page that are provided as suggestions on how a color table could be
configured.
+
+ Qt also provides a suite of named gradient presets. They are based on the
+ free WebGradients collection. Click on the name in the Presets box to show
+ the gradient. Use the arrow buttons to browse through the available
+ presets.
*/
diff --git a/examples/widgets/graphicsview/boxes/glextensions.h b/examples/widgets/graphicsview/boxes/glextensions.h
index ac73e61641..685700d866 100644
--- a/examples/widgets/graphicsview/boxes/glextensions.h
+++ b/examples/widgets/graphicsview/boxes/glextensions.h
@@ -78,18 +78,11 @@ glMapBuffer
glUnmapBuffer
*/
-#ifndef Q_OS_MAC
-# ifndef APIENTRYP
-# ifdef APIENTRY
-# define APIENTRYP APIENTRY *
-# else
-# define APIENTRY
-# define APIENTRYP *
-# endif
-# endif
-#else
+#ifndef APIENTRY
# define APIENTRY
-# define APIENTRYP *
+#endif
+#ifndef APIENTRYP
+# define APIENTRYP APIENTRY *
#endif
#ifndef GL_VERSION_1_2
diff --git a/examples/widgets/graphicsview/boxes/scene.cpp b/examples/widgets/graphicsview/boxes/scene.cpp
index f51cad99ac..1637c1f781 100644
--- a/examples/widgets/graphicsview/boxes/scene.cpp
+++ b/examples/widgets/graphicsview/boxes/scene.cpp
@@ -952,17 +952,17 @@ void Scene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
return;
if (event->buttons() & Qt::LeftButton) {
- m_trackBalls[0].move(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate());
+ m_trackBalls[0].move(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugated());
event->accept();
} else {
- m_trackBalls[0].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate());
+ m_trackBalls[0].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugated());
}
if (event->buttons() & Qt::RightButton) {
- m_trackBalls[1].move(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate());
+ m_trackBalls[1].move(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugated());
event->accept();
} else {
- m_trackBalls[1].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate());
+ m_trackBalls[1].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugated());
}
if (event->buttons() & Qt::MidButton) {
@@ -980,12 +980,12 @@ void Scene::mousePressEvent(QGraphicsSceneMouseEvent *event)
return;
if (event->buttons() & Qt::LeftButton) {
- m_trackBalls[0].push(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate());
+ m_trackBalls[0].push(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugated());
event->accept();
}
if (event->buttons() & Qt::RightButton) {
- m_trackBalls[1].push(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate());
+ m_trackBalls[1].push(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugated());
event->accept();
}
@@ -1002,12 +1002,12 @@ void Scene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
return;
if (event->button() == Qt::LeftButton) {
- m_trackBalls[0].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate());
+ m_trackBalls[0].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugated());
event->accept();
}
if (event->button() == Qt::RightButton) {
- m_trackBalls[1].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate());
+ m_trackBalls[1].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugated());
event->accept();
}
diff --git a/examples/widgets/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp b/examples/widgets/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp
index c93368b390..35426657d9 100644
--- a/examples/widgets/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp
+++ b/examples/widgets/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp
@@ -101,15 +101,20 @@ bool MySortFilterProxyModel::lessThan(const QModelIndex &left,
if (leftData.type() == QVariant::DateTime) {
return leftData.toDateTime() < rightData.toDateTime();
} else {
- static QRegExp emailPattern("[\\w\\.]*@[\\w\\.]*)");
+ static const QRegularExpression emailPattern("[\\w\\.]*@[\\w\\.]*");
QString leftString = leftData.toString();
- if(left.column() == 1 && emailPattern.indexIn(leftString) != -1)
- leftString = emailPattern.cap(1);
-
+ if (left.column() == 1) {
+ const QRegularExpressionMatch match = emailPattern.match(leftString);
+ if (match.hasMatch())
+ leftString = match.captured(0);
+ }
QString rightString = rightData.toString();
- if(right.column() == 1 && emailPattern.indexIn(rightString) != -1)
- rightString = emailPattern.cap(1);
+ if (right.column() == 1) {
+ const QRegularExpressionMatch match = emailPattern.match(rightString);
+ if (match.hasMatch())
+ rightString = match.captured(0);
+ }
return QString::localeAwareCompare(leftString, rightString) < 0;
}
diff --git a/examples/widgets/mainwindows/mainwindow/mainwindow.cpp b/examples/widgets/mainwindows/mainwindow/mainwindow.cpp
index fe31207326..4ba180f312 100644
--- a/examples/widgets/mainwindows/mainwindow/mainwindow.cpp
+++ b/examples/widgets/mainwindows/mainwindow/mainwindow.cpp
@@ -97,6 +97,7 @@ MainWindow::MainWindow(const CustomSizeHintMap &customSizeHints,
QWidget *parent, Qt::WindowFlags flags)
: QMainWindow(parent, flags)
{
+ Q_UNUSED(message);
setObjectName("MainWindow");
setWindowTitle("Qt Main Window Example");
diff --git a/examples/widgets/painting/affine/affine.pro b/examples/widgets/painting/affine/affine.pro
index 0ad869183c..0af18b82ca 100644
--- a/examples/widgets/painting/affine/affine.pro
+++ b/examples/widgets/painting/affine/affine.pro
@@ -1,10 +1,6 @@
SOURCES += main.cpp xform.cpp
HEADERS += xform.h
-qtHaveModule(opengl) {
- DEFINES += QT_OPENGL_SUPPORT
- QT += opengl
-}
QT += widgets
SHARED_FOLDER = ../shared
diff --git a/examples/widgets/painting/affine/xform.cpp b/examples/widgets/painting/affine/xform.cpp
index 20f6eb3c6d..dc01acf453 100644
--- a/examples/widgets/painting/affine/xform.cpp
+++ b/examples/widgets/painting/affine/xform.cpp
@@ -830,13 +830,11 @@ XFormWidget::XFormWidget(QWidget *parent)
QPushButton *showSourceButton = new QPushButton(mainGroup);
showSourceButton->setText(tr("Show Source"));
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
QPushButton *enableOpenGLButton = new QPushButton(mainGroup);
enableOpenGLButton->setText(tr("Use OpenGL"));
enableOpenGLButton->setCheckable(true);
enableOpenGLButton->setChecked(view->usesOpenGL());
- if (!QGLFormat::hasOpenGL())
- enableOpenGLButton->hide();
#endif
QPushButton *whatsThisButton = new QPushButton(mainGroup);
whatsThisButton->setText(tr("What's This?"));
@@ -871,7 +869,7 @@ XFormWidget::XFormWidget(QWidget *parent)
mainGroupLayout->addWidget(resetButton);
mainGroupLayout->addWidget(animateButton);
mainGroupLayout->addWidget(showSourceButton);
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
mainGroupLayout->addWidget(enableOpenGLButton);
#endif
mainGroupLayout->addWidget(whatsThisButton);
@@ -897,7 +895,7 @@ XFormWidget::XFormWidget(QWidget *parent)
connect(view, &XFormView::descriptionEnabledChanged, view->hoverPoints(), &HoverPoints::setDisabled);
connect(view, &XFormView::descriptionEnabledChanged, whatsThisButton, &QPushButton::setChecked);
connect(showSourceButton, &QPushButton::clicked, view, &XFormView::showSource);
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
connect(enableOpenGLButton, &QPushButton::clicked, view, &XFormView::enableOpenGL);
#endif
view->loadSourceFile(":res/affine/xform.cpp");
diff --git a/examples/widgets/painting/composition/composition.cpp b/examples/widgets/painting/composition/composition.cpp
index 0b57d3c7d3..3bc31b1fce 100644
--- a/examples/widgets/painting/composition/composition.cpp
+++ b/examples/widgets/painting/composition/composition.cpp
@@ -57,6 +57,11 @@
#include <QMouseEvent>
#include <qmath.h>
+#if QT_CONFIG(opengl)
+#include <QOpenGLFunctions>
+#include <QOpenGLWindow>
+#endif
+
const int animationInterval = 15; // update every 16 ms = ~60FPS
CompositionWidget::CompositionWidget(QWidget *parent)
@@ -136,14 +141,11 @@ CompositionWidget::CompositionWidget(QWidget *parent)
QPushButton *showSourceButton = new QPushButton(mainGroup);
showSourceButton->setText(tr("Show Source"));
-#if defined(USE_OPENGL) && !defined(QT_OPENGL_ES)
+#if QT_CONFIG(opengl)
QPushButton *enableOpenGLButton = new QPushButton(mainGroup);
enableOpenGLButton->setText(tr("Use OpenGL"));
enableOpenGLButton->setCheckable(true);
enableOpenGLButton->setChecked(view->usesOpenGL());
-
- if (!QGLFormat::hasOpenGL() || !QGLPixelBuffer::hasOpenGLPbuffers())
- enableOpenGLButton->hide();
#endif
QPushButton *whatsThisButton = new QPushButton(mainGroup);
whatsThisButton->setText(tr("What's This?"));
@@ -166,7 +168,7 @@ CompositionWidget::CompositionWidget(QWidget *parent)
mainGroupLayout->addWidget(animateButton);
mainGroupLayout->addWidget(whatsThisButton);
mainGroupLayout->addWidget(showSourceButton);
-#if defined(USE_OPENGL) && !defined(QT_OPENGL_ES)
+#if QT_CONFIG(opengl)
mainGroupLayout->addWidget(enableOpenGLButton);
#endif
@@ -210,7 +212,7 @@ CompositionWidget::CompositionWidget(QWidget *parent)
connect(whatsThisButton, SIGNAL(clicked(bool)), view, SLOT(setDescriptionEnabled(bool)));
connect(view, SIGNAL(descriptionEnabledChanged(bool)), whatsThisButton, SLOT(setChecked(bool)));
connect(showSourceButton, SIGNAL(clicked()), view, SLOT(showSource()));
-#if defined(USE_OPENGL) && !defined(QT_OPENGL_ES)
+#if QT_CONFIG(opengl)
connect(enableOpenGLButton, SIGNAL(clicked(bool)), view, SLOT(enableOpenGL(bool)));
#endif
connect(animateButton, SIGNAL(toggled(bool)), view, SLOT(setAnimationEnabled(bool)));
@@ -258,8 +260,7 @@ CompositionRenderer::CompositionRenderer(QWidget *parent)
m_circle_pos = QPoint(200, 100);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
-#ifdef USE_OPENGL
- m_pbuffer = 0;
+#if QT_CONFIG(opengl)
m_pbuffer_size = 1024;
#endif
}
@@ -350,8 +351,11 @@ void CompositionRenderer::drawSource(QPainter &p)
void CompositionRenderer::paint(QPainter *painter)
{
-#if defined(USE_OPENGL) && !defined(QT_OPENGL_ES)
- if (usesOpenGL()) {
+#if QT_CONFIG(opengl)
+ if (usesOpenGL() && glWindow()->isValid()) {
+
+ if (!m_blitter.isCreated())
+ m_blitter.create();
int new_pbuf_size = m_pbuffer_size;
if (size().width() > m_pbuffer_size || size().height() > m_pbuffer_size)
@@ -360,95 +364,46 @@ void CompositionRenderer::paint(QPainter *painter)
if (size().width() < m_pbuffer_size/2 && size().height() < m_pbuffer_size/2)
new_pbuf_size /= 2;
- if (!m_pbuffer || new_pbuf_size != m_pbuffer_size) {
- if (m_pbuffer) {
- m_pbuffer->deleteTexture(m_base_tex);
- m_pbuffer->deleteTexture(m_compositing_tex);
- delete m_pbuffer;
- }
-
- m_pbuffer = new QGLPixelBuffer(QSize(new_pbuf_size, new_pbuf_size), QGLFormat::defaultFormat(), glWidget());
- m_pbuffer->makeCurrent();
- m_base_tex = m_pbuffer->generateDynamicTexture();
- m_compositing_tex = m_pbuffer->generateDynamicTexture();
+ if (!m_fbo || new_pbuf_size != m_pbuffer_size) {
+ m_fbo.reset(new QFboPaintDevice(QSize(new_pbuf_size, new_pbuf_size), false, false));
m_pbuffer_size = new_pbuf_size;
}
if (size() != m_previous_size) {
m_previous_size = size();
- QPainter p(m_pbuffer);
- p.setCompositionMode(QPainter::CompositionMode_Source);
- p.fillRect(QRect(0, 0, m_pbuffer->width(), m_pbuffer->height()), Qt::transparent);
+ QPainter p(m_fbo.data());
drawBase(p);
p.end();
- m_pbuffer->updateDynamicTexture(m_base_tex);
+ m_base_tex = m_fbo->takeTexture();
}
- qreal x_fraction = width()/float(m_pbuffer->width());
- qreal y_fraction = height()/float(m_pbuffer->height());
-
+ painter->beginNativePainting();
{
- QPainter p(m_pbuffer);
- p.setCompositionMode(QPainter::CompositionMode_Source);
- p.fillRect(QRect(0, 0, m_pbuffer->width(), m_pbuffer->height()), Qt::transparent);
-
- p.save(); // Needed when using the GL1 engine
- p.beginNativePainting(); // Needed when using the GL2 engine
-
- glBindTexture(GL_TEXTURE_2D, m_base_tex);
- glEnable(GL_TEXTURE_2D);
- glColor4f(1.,1.,1.,1.);
-
- glBegin(GL_QUADS);
- {
- glTexCoord2f(0, 1.0);
- glVertex2f(0, 0);
-
- glTexCoord2f(x_fraction, 1.0);
- glVertex2f(width(), 0);
-
- glTexCoord2f(x_fraction, 1.0-y_fraction);
- glVertex2f(width(), height());
-
- glTexCoord2f(0, 1.0-y_fraction);
- glVertex2f(0, height());
- }
- glEnd();
-
- glDisable(GL_TEXTURE_2D);
-
- p.endNativePainting(); // Needed when using the GL2 engine
- p.restore(); // Needed when using the GL1 engine
-
+ QPainter p(m_fbo.data());
+ p.beginNativePainting();
+ m_blitter.bind();
+ const QRect targetRect(QPoint(0, 0), m_fbo->size());
+ const QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(targetRect, QRect(QPoint(0, 0), m_fbo->size()));
+ m_blitter.blit(m_base_tex, target, QOpenGLTextureBlitter::OriginBottomLeft);
+ m_blitter.release();
+ p.endNativePainting();
drawSource(p);
p.end();
- m_pbuffer->updateDynamicTexture(m_compositing_tex);
- }
-
- painter->beginNativePainting(); // Needed when using the GL2 engine
- glWidget()->makeCurrent(); // Needed when using the GL1 engine
- glBindTexture(GL_TEXTURE_2D, m_compositing_tex);
- glEnable(GL_TEXTURE_2D);
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- glColor4f(1.,1.,1.,1.);
- glBegin(GL_QUADS);
- {
- glTexCoord2f(0, 1.0);
- glVertex2f(0, 0);
-
- glTexCoord2f(x_fraction, 1.0);
- glVertex2f(width(), 0);
-
- glTexCoord2f(x_fraction, 1.0-y_fraction);
- glVertex2f(width(), height());
-
- glTexCoord2f(0, 1.0-y_fraction);
- glVertex2f(0, height());
+ m_compositing_tex = m_fbo->takeTexture();
}
- glEnd();
- glDisable(GL_TEXTURE_2D);
- painter->endNativePainting(); // Needed when using the GL2 engine
+ painter->endNativePainting();
+
+ painter->beginNativePainting();
+ auto *funcs = QOpenGLContext::currentContext()->functions();
+ funcs->glEnable(GL_BLEND);
+ funcs->glBlendEquation(GL_FUNC_ADD);
+ funcs->glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ m_blitter.bind();
+ const QRect targetRect(QPoint(0, 0), m_fbo->size());
+ const QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(targetRect, QRect(QPoint(0, 0), size()));
+ m_blitter.blit(m_compositing_tex, target, QOpenGLTextureBlitter::OriginBottomLeft);
+ m_blitter.release();
+ painter->endNativePainting();
} else
#endif
{
@@ -520,7 +475,7 @@ void CompositionRenderer::setCirclePos(const QPointF &pos)
const QRect oldRect = rectangle_around(m_circle_pos).toAlignedRect();
m_circle_pos = pos;
const QRect newRect = rectangle_around(m_circle_pos).toAlignedRect();
-#if defined(USE_OPENGL) && !defined(QT_OPENGL_ES)
+#if QT_CONFIG(opengl)
if (usesOpenGL()) {
update();
return;
diff --git a/examples/widgets/painting/composition/composition.h b/examples/widgets/painting/composition/composition.h
index 49853f503b..19150e2024 100644
--- a/examples/widgets/painting/composition/composition.h
+++ b/examples/widgets/painting/composition/composition.h
@@ -53,6 +53,11 @@
#include "arthurwidgets.h"
+#if QT_CONFIG(opengl)
+#include "fbopaintdevice.h"
+#include <QOpenGLTextureBlitter>
+#endif
+
#include <QPainter>
#include <QEvent>
@@ -61,10 +66,6 @@ class QPushButton;
class QRadioButton;
QT_END_NAMESPACE
-#ifdef QT_OPENGL_SUPPORT
-#include <QtOpenGL>
-#endif
-
class CompositionWidget : public QWidget
{
Q_OBJECT
@@ -186,12 +187,13 @@ private:
bool m_animation_enabled;
int m_animationTimer;
-#ifdef QT_OPENGL_SUPPORT
- QGLPixelBuffer *m_pbuffer;
- GLuint m_base_tex;
- GLuint m_compositing_tex;
+#if QT_CONFIG(opengl)
+ QScopedPointer<QFboPaintDevice> m_fbo;
int m_pbuffer_size; // width==height==size of pbuffer
+ uint m_base_tex;
+ uint m_compositing_tex;
QSize m_previous_size;
+ QOpenGLTextureBlitter m_blitter;
#endif
};
diff --git a/examples/widgets/painting/composition/composition.pro b/examples/widgets/painting/composition/composition.pro
index 5fdbe4a5a2..15d8c6e67b 100644
--- a/examples/widgets/painting/composition/composition.pro
+++ b/examples/widgets/painting/composition/composition.pro
@@ -6,10 +6,6 @@ SHARED_FOLDER = ../shared
include($$SHARED_FOLDER/shared.pri)
RESOURCES += composition.qrc
-qtHaveModule(opengl):!qtConfig(dynamicgl) {
- DEFINES += USE_OPENGL
- QT += opengl
-}
QT += widgets
# install
diff --git a/examples/widgets/painting/composition/main.cpp b/examples/widgets/painting/composition/main.cpp
index 1a5dfd3e5e..1f4ead7165 100644
--- a/examples/widgets/painting/composition/main.cpp
+++ b/examples/widgets/painting/composition/main.cpp
@@ -51,17 +51,12 @@
#include "composition.h"
#include <QApplication>
-#ifdef QT_OPENGL_SUPPORT
-#include <QtOpenGL>
-#endif
int main(int argc, char *argv[])
{
- // Q_INIT_RESOURCE(deform);
-
QApplication app(argc, argv);
- CompositionWidget compWidget(0);
+ CompositionWidget compWidget(nullptr);
QStyle *arthurStyle = new ArthurStyle();
compWidget.setStyle(arthurStyle);
diff --git a/examples/widgets/painting/deform/deform.pro b/examples/widgets/painting/deform/deform.pro
index 6409aaed96..498ec57686 100644
--- a/examples/widgets/painting/deform/deform.pro
+++ b/examples/widgets/painting/deform/deform.pro
@@ -7,10 +7,6 @@ include($$SHARED_FOLDER/shared.pri)
RESOURCES += deform.qrc
-qtHaveModule(opengl) {
- DEFINES += QT_OPENGL_SUPPORT
- QT += opengl
-}
QT += widgets
# install
diff --git a/examples/widgets/painting/deform/pathdeform.cpp b/examples/widgets/painting/deform/pathdeform.cpp
index 490a8508d6..7c3fe45277 100644
--- a/examples/widgets/painting/deform/pathdeform.cpp
+++ b/examples/widgets/painting/deform/pathdeform.cpp
@@ -50,7 +50,8 @@
#include "pathdeform.h"
-#include <QApplication>
+#include <QGuiApplication>
+#include <QScreen>
#include <QtDebug>
#include <QMouseEvent>
#include <QTimerEvent>
@@ -108,13 +109,11 @@ void PathDeformControls::layoutForDesktop()
QPushButton *showSourceButton = new QPushButton(mainGroup);
showSourceButton->setText(tr("Show Source"));
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
QPushButton *enableOpenGLButton = new QPushButton(mainGroup);
enableOpenGLButton->setText(tr("Use OpenGL"));
enableOpenGLButton->setCheckable(true);
enableOpenGLButton->setChecked(m_renderer->usesOpenGL());
- if (!QGLFormat::hasOpenGL())
- enableOpenGLButton->hide();
#endif
QPushButton *whatsThisButton = new QPushButton(mainGroup);
@@ -131,7 +130,7 @@ void PathDeformControls::layoutForDesktop()
mainGroupLayout->addWidget(textGroup);
mainGroupLayout->addWidget(animateButton);
mainGroupLayout->addStretch(1);
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
mainGroupLayout->addWidget(enableOpenGLButton);
#endif
mainGroupLayout->addWidget(showSourceButton);
@@ -157,7 +156,7 @@ void PathDeformControls::layoutForDesktop()
connect(deformSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setIntensity(int)));
connect(fontSizeSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setFontSize(int)));
connect(animateButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setAnimated(bool)));
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
connect(enableOpenGLButton, SIGNAL(clicked(bool)), m_renderer, SLOT(enableOpenGL(bool)));
#endif
@@ -200,13 +199,11 @@ void PathDeformControls::layoutForSmallScreen()
QPushButton *animateButton = new QPushButton(tr("Animated"), mainGroup);
animateButton->setCheckable(true);
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
QPushButton *enableOpenGLButton = new QPushButton(mainGroup);
enableOpenGLButton->setText(tr("Use OpenGL"));
enableOpenGLButton->setCheckable(mainGroup);
enableOpenGLButton->setChecked(m_renderer->usesOpenGL());
- if (!QGLFormat::hasOpenGL())
- enableOpenGLButton->hide();
#endif
QPushButton *quitButton = new QPushButton(tr("Quit"), mainGroup);
@@ -222,7 +219,7 @@ void PathDeformControls::layoutForSmallScreen()
mainGroupLayout->addWidget(fontSizeLabel, 2, 0, Qt::AlignRight);
mainGroupLayout->addWidget(fontSizeSlider, 2, 1);
mainGroupLayout->addWidget(animateButton, 3,0, 1,2);
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
mainGroupLayout->addWidget(enableOpenGLButton, 4,0, 1,2);
#endif
@@ -238,7 +235,7 @@ void PathDeformControls::layoutForSmallScreen()
connect(deformSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setIntensity(int)));
connect(fontSizeSlider, SIGNAL(valueChanged(int)), m_renderer, SLOT(setFontSize(int)));
connect(animateButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setAnimated(bool)));
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
connect(enableOpenGLButton, SIGNAL(clicked(bool)), m_renderer, SLOT(enableOpenGL(bool)));
#endif
@@ -247,7 +244,7 @@ void PathDeformControls::layoutForSmallScreen()
deformSlider->setValue(80);
fontSizeSlider->setValue(120);
- QRect screen_size = QApplication::desktop()->screenGeometry();
+ QRect screen_size = QGuiApplication::primaryScreen()->geometry();
radiusSlider->setValue(qMin(screen_size.width(), screen_size.height())/5);
m_renderer->setText(tr("Qt"));
@@ -277,7 +274,7 @@ PathDeformWidget::PathDeformWidget(QWidget *parent, bool smallScreen)
connect(m_renderer, SIGNAL(clicked()), this, SLOT(showControls()));
connect(m_controls, SIGNAL(okPressed()), this, SLOT(hideControls()));
- connect(m_controls, SIGNAL(quitPressed()), QApplication::instance(), SLOT(quit()));
+ connect(m_controls, SIGNAL(quitPressed()), QCoreApplication::instance(), SLOT(quit()));
}
@@ -462,7 +459,7 @@ void PathDeformRenderer::timerEvent(QTimerEvent *e)
m_pos.setY(height() - m_radius);
}
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
if (usesOpenGL()) {
update();
} else
@@ -482,6 +479,10 @@ void PathDeformRenderer::timerEvent(QTimerEvent *e)
void PathDeformRenderer::mousePressEvent(QMouseEvent *e)
{
+ if (m_show_doc) {
+ setDescriptionEnabled(false);
+ return;
+ }
setDescriptionEnabled(false);
m_repaintTimer.stop();
@@ -522,7 +523,7 @@ void PathDeformRenderer::mouseMoveEvent(QMouseEvent *e)
m_direction = (m_direction + dir) / 2;
}
m_pos = e->pos() + m_offset;
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
if (usesOpenGL()) {
update();
} else
@@ -615,7 +616,7 @@ void PathDeformRenderer::setRadius(int radius)
m_radius = radius;
generateLensPixmap();
if (!m_animated || m_radius < max) {
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
if (usesOpenGL()){
update();
return;
@@ -629,7 +630,7 @@ void PathDeformRenderer::setIntensity(int intensity)
{
m_intensity = intensity;
if (!m_animated) {
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
if (usesOpenGL()) {
update();
return;
diff --git a/examples/widgets/painting/gradients/gradients.cpp b/examples/widgets/painting/gradients/gradients.cpp
index 78c174a8bf..004f6710cd 100644
--- a/examples/widgets/painting/gradients/gradients.cpp
+++ b/examples/widgets/painting/gradients/gradients.cpp
@@ -301,8 +301,15 @@ GradientWidget::GradientWidget(QWidget *parent)
m_reflectSpreadButton = new QRadioButton(tr("Reflect Spread"), spreadGroup);
m_repeatSpreadButton = new QRadioButton(tr("Repeat Spread"), spreadGroup);
+ QGroupBox *presetsGroup = new QGroupBox(mainGroup);
+ presetsGroup->setTitle(tr("Presets"));
+ QPushButton *prevPresetButton = new QPushButton(tr("<"), presetsGroup);
+ m_presetButton = new QPushButton(tr("(unset)"), presetsGroup);
+ QPushButton *nextPresetButton = new QPushButton(tr(">"), presetsGroup);
+ updatePresetName();
+
QGroupBox *defaultsGroup = new QGroupBox(mainGroup);
- defaultsGroup->setTitle(tr("Defaults"));
+ defaultsGroup->setTitle(tr("Examples"));
QPushButton *default1Button = new QPushButton(tr("1"), defaultsGroup);
QPushButton *default2Button = new QPushButton(tr("2"), defaultsGroup);
QPushButton *default3Button = new QPushButton(tr("3"), defaultsGroup);
@@ -310,13 +317,11 @@ GradientWidget::GradientWidget(QWidget *parent)
QPushButton *showSourceButton = new QPushButton(mainGroup);
showSourceButton->setText(tr("Show Source"));
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
QPushButton *enableOpenGLButton = new QPushButton(mainGroup);
enableOpenGLButton->setText(tr("Use OpenGL"));
enableOpenGLButton->setCheckable(true);
enableOpenGLButton->setChecked(m_renderer->usesOpenGL());
- if (!QGLFormat::hasOpenGL())
- enableOpenGLButton->hide();
#endif
QPushButton *whatsThisButton = new QPushButton(mainGroup);
whatsThisButton->setText(tr("What's This?"));
@@ -327,15 +332,16 @@ GradientWidget::GradientWidget(QWidget *parent)
mainLayout->addWidget(m_renderer);
mainLayout->addWidget(mainGroup);
- mainGroup->setFixedWidth(180);
+ mainGroup->setFixedWidth(200);
QVBoxLayout *mainGroupLayout = new QVBoxLayout(mainGroup);
mainGroupLayout->addWidget(editorGroup);
mainGroupLayout->addWidget(typeGroup);
mainGroupLayout->addWidget(spreadGroup);
+ mainGroupLayout->addWidget(presetsGroup);
mainGroupLayout->addWidget(defaultsGroup);
mainGroupLayout->addStretch(1);
mainGroupLayout->addWidget(showSourceButton);
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
mainGroupLayout->addWidget(enableOpenGLButton);
#endif
mainGroupLayout->addWidget(whatsThisButton);
@@ -353,6 +359,11 @@ GradientWidget::GradientWidget(QWidget *parent)
spreadGroupLayout->addWidget(m_repeatSpreadButton);
spreadGroupLayout->addWidget(m_reflectSpreadButton);
+ QHBoxLayout *presetsGroupLayout = new QHBoxLayout(presetsGroup);
+ presetsGroupLayout->addWidget(prevPresetButton);
+ presetsGroupLayout->addWidget(m_presetButton, 1);
+ presetsGroupLayout->addWidget(nextPresetButton);
+
QHBoxLayout *defaultsGroupLayout = new QHBoxLayout(defaultsGroup);
defaultsGroupLayout->addWidget(default1Button);
defaultsGroupLayout->addWidget(default2Button);
@@ -375,6 +386,13 @@ GradientWidget::GradientWidget(QWidget *parent)
connect(m_repeatSpreadButton, &QRadioButton::clicked,
m_renderer, &GradientRenderer::setRepeatSpread);
+ connect(prevPresetButton, &QPushButton::clicked,
+ this, &GradientWidget::setPrevPreset);
+ connect(m_presetButton, &QPushButton::clicked,
+ this, &GradientWidget::setPreset);
+ connect(nextPresetButton, &QPushButton::clicked,
+ this, &GradientWidget::setNextPreset);
+
connect(default1Button, &QPushButton::clicked,
this, &GradientWidget::setDefault1);
connect(default2Button, &QPushButton::clicked,
@@ -386,7 +404,7 @@ GradientWidget::GradientWidget(QWidget *parent)
connect(showSourceButton, &QPushButton::clicked,
m_renderer, &GradientRenderer::showSource);
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
connect(enableOpenGLButton, QOverload<bool>::of(&QPushButton::clicked),
m_renderer, &ArthurFrame::enableOpenGL);
#endif
@@ -471,6 +489,40 @@ void GradientWidget::setDefault(int config)
m_renderer->setGradientStops(stops);
}
+void GradientWidget::updatePresetName()
+{
+ QMetaEnum presetEnum = QMetaEnum::fromType<QGradient::Preset>();
+ m_presetButton->setText(QLatin1String(presetEnum.key(m_presetIndex)));
+}
+
+void GradientWidget::changePresetBy(int indexOffset)
+{
+ QMetaEnum presetEnum = QMetaEnum::fromType<QGradient::Preset>();
+ m_presetIndex = qBound(0, m_presetIndex + indexOffset, presetEnum.keyCount() - 1);
+
+ QGradient::Preset preset = static_cast<QGradient::Preset>(presetEnum.value(m_presetIndex));
+ QGradient gradient(preset);
+ if (gradient.type() != QGradient::LinearGradient)
+ return;
+
+ QLinearGradient *linearGradientPointer = static_cast<QLinearGradient *>(&gradient);
+ QLineF objectStopsLine(linearGradientPointer->start(), linearGradientPointer->finalStop());
+ qreal scaleX = qFuzzyIsNull(objectStopsLine.dx()) ? 1.0 : (0.8 * m_renderer->width() / qAbs(objectStopsLine.dx()));
+ qreal scaleY = qFuzzyIsNull(objectStopsLine.dy()) ? 1.0 : (0.8 * m_renderer->height() / qAbs(objectStopsLine.dy()));
+ QLineF logicalStopsLine = QTransform::fromScale(scaleX, scaleY).map(objectStopsLine);
+ logicalStopsLine.translate(m_renderer->rect().center() - logicalStopsLine.center());
+ QPolygonF logicalStops;
+ logicalStops << logicalStopsLine.p1() << logicalStopsLine.p2();
+
+ m_linearButton->animateClick();
+ m_padSpreadButton->animateClick();
+ m_editor->setGradientStops(gradient.stops());
+ m_renderer->hoverPoints()->setPoints(logicalStops);
+ m_renderer->setGradientStops(gradient.stops());
+
+ updatePresetName();
+}
+
GradientRenderer::GradientRenderer(QWidget *parent)
: ArthurFrame(parent)
{
diff --git a/examples/widgets/painting/gradients/gradients.h b/examples/widgets/painting/gradients/gradients.h
index b4db298bb4..c6525d18f8 100644
--- a/examples/widgets/painting/gradients/gradients.h
+++ b/examples/widgets/painting/gradients/gradients.h
@@ -164,9 +164,14 @@ public slots:
void setDefault2() { setDefault(2); }
void setDefault3() { setDefault(3); }
void setDefault4() { setDefault(4); }
+ void setPreset() { changePresetBy(0); }
+ void setPrevPreset() { changePresetBy(-1); }
+ void setNextPreset() { changePresetBy(1); }
private:
void setDefault(int i);
+ void updatePresetName();
+ void changePresetBy(int indexOffset);
GradientRenderer *m_renderer;
GradientEditor *m_editor;
@@ -177,7 +182,9 @@ private:
QRadioButton *m_padSpreadButton;
QRadioButton *m_reflectSpreadButton;
QRadioButton *m_repeatSpreadButton;
+ QPushButton *m_presetButton;
+ int m_presetIndex = 0;
};
#endif // GRADIENTS_H
diff --git a/examples/widgets/painting/gradients/gradients.html b/examples/widgets/painting/gradients/gradients.html
index 1ea2c0ed6c..82c449035f 100644
--- a/examples/widgets/painting/gradients/gradients.html
+++ b/examples/widgets/painting/gradients/gradients.html
@@ -24,8 +24,12 @@ green and blue components while the last defines the alpha of the
gradient. You can move points, and add new ones, by clicking with the left
mouse button, and remove points by clicking with the right button.</p>
-<p>There are three default configurations available at the bottom of
+<p>There are three example configurations available at the bottom of
the page that are provided as suggestions on how a color table could be
configured.</p>
+<p>Qt also provides a suite of named gradient presets. They are based on the
+free WebGradients collection. Click on the name in the Presets box to show the
+gradient. Use the arrow buttons to browse through the available presets.</p>
+
</html>
diff --git a/examples/widgets/painting/gradients/gradients.pro b/examples/widgets/painting/gradients/gradients.pro
index 73f3974c62..14eccb6500 100644
--- a/examples/widgets/painting/gradients/gradients.pro
+++ b/examples/widgets/painting/gradients/gradients.pro
@@ -6,10 +6,6 @@ SHARED_FOLDER = ../shared
include($$SHARED_FOLDER/shared.pri)
RESOURCES += gradients.qrc
-qtHaveModule(opengl) {
- DEFINES += QT_OPENGL_SUPPORT
- QT += opengl
-}
QT += widgets
# install
diff --git a/examples/widgets/painting/pathstroke/pathstroke.cpp b/examples/widgets/painting/pathstroke/pathstroke.cpp
index 5a7b8fd9fe..b04998afac 100644
--- a/examples/widgets/painting/pathstroke/pathstroke.cpp
+++ b/examples/widgets/painting/pathstroke/pathstroke.cpp
@@ -211,13 +211,11 @@ void PathStrokeControls::layoutForDesktop()
QPushButton *showSourceButton = new QPushButton(mainGroup);
showSourceButton->setText(tr("Show Source"));
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
QPushButton *enableOpenGLButton = new QPushButton(mainGroup);
enableOpenGLButton->setText(tr("Use OpenGL"));
enableOpenGLButton->setCheckable(true);
enableOpenGLButton->setChecked(m_renderer->usesOpenGL());
- if (!QGLFormat::hasOpenGL())
- enableOpenGLButton->hide();
#endif
QPushButton *whatsThisButton = new QPushButton(mainGroup);
whatsThisButton->setText(tr("What's This?"));
@@ -242,7 +240,7 @@ void PathStrokeControls::layoutForDesktop()
mainGroupLayout->addWidget(animated);
mainGroupLayout->addStretch(1);
mainGroupLayout->addWidget(showSourceButton);
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
mainGroupLayout->addWidget(enableOpenGLButton);
#endif
mainGroupLayout->addWidget(whatsThisButton);
@@ -254,7 +252,7 @@ void PathStrokeControls::layoutForDesktop()
connect(penWidth, SIGNAL(valueChanged(int)), m_renderer, SLOT(setPenWidth(int)));
connect(showSourceButton, SIGNAL(clicked()), m_renderer, SLOT(showSource()));
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
connect(enableOpenGLButton, SIGNAL(clicked(bool)), m_renderer, SLOT(enableOpenGL(bool)));
#endif
connect(whatsThisButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setDescriptionEnabled(bool)));
@@ -290,13 +288,11 @@ void PathStrokeControls::layoutForSmallScreens()
penWidth->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
penWidth->setRange(0, 500);
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
QPushButton *enableOpenGLButton = new QPushButton(this);
enableOpenGLButton->setText(tr("Use OpenGL"));
enableOpenGLButton->setCheckable(true);
enableOpenGLButton->setChecked(m_renderer->usesOpenGL());
- if (!QGLFormat::hasOpenGL())
- enableOpenGLButton->hide();
#endif
// Layouts:
@@ -307,7 +303,7 @@ void PathStrokeControls::layoutForSmallScreens()
QVBoxLayout *leftLayout = new QVBoxLayout(0);
leftLayout->addWidget(m_capGroup);
leftLayout->addWidget(m_joinGroup);
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
leftLayout->addWidget(enableOpenGLButton);
#endif
leftLayout->addLayout(penWidthLayout);
@@ -330,7 +326,7 @@ void PathStrokeControls::layoutForSmallScreens()
mainLayout->addWidget(quitBtn, 2, 1, Qt::AlignHCenter | Qt::AlignTop);
mainLayout->addWidget(okBtn, 2, 2, Qt::AlignHCenter | Qt::AlignTop);
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
connect(enableOpenGLButton, SIGNAL(clicked(bool)), m_renderer, SLOT(enableOpenGL(bool)));
#endif
diff --git a/examples/widgets/painting/pathstroke/pathstroke.pro b/examples/widgets/painting/pathstroke/pathstroke.pro
index 8ab3cb9244..3e71b2db56 100644
--- a/examples/widgets/painting/pathstroke/pathstroke.pro
+++ b/examples/widgets/painting/pathstroke/pathstroke.pro
@@ -7,10 +7,6 @@ include($$SHARED_FOLDER/shared.pri)
RESOURCES += pathstroke.qrc
-qtHaveModule(opengl) {
- DEFINES += QT_OPENGL_SUPPORT
- QT += opengl
-}
QT += widgets
# install
diff --git a/examples/widgets/painting/shared/arthurwidgets.cpp b/examples/widgets/painting/shared/arthurwidgets.cpp
index 965660a3a3..442fb69ac1 100644
--- a/examples/widgets/painting/shared/arthurwidgets.cpp
+++ b/examples/widgets/painting/shared/arthurwidgets.cpp
@@ -60,6 +60,10 @@
#include <QTextBrowser>
#include <QBoxLayout>
#include <QRegularExpression>
+#include <QOffscreenSurface>
+#include <QOpenGLContext>
+#include <QOpenGLPaintDevice>
+#include <QOpenGLWindow>
extern QPixmap cached(const QString &img);
@@ -67,17 +71,12 @@ ArthurFrame::ArthurFrame(QWidget *parent)
: QWidget(parent)
, m_prefer_image(false)
{
-#ifdef QT_OPENGL_SUPPORT
- glw = 0;
+#if QT_CONFIG(opengl)
+ m_glWindow = nullptr;
+ m_glWidget = nullptr;
m_use_opengl = false;
- QGLFormat f = QGLFormat::defaultFormat();
- f.setSampleBuffers(true);
- f.setStencil(true);
- f.setAlpha(true);
- f.setAlphaBufferSize(8);
- QGLFormat::setDefaultFormat(f);
#endif
- m_document = 0;
+ m_document = nullptr;
m_show_doc = false;
m_tile = QPixmap(128, 128);
@@ -94,37 +93,55 @@ ArthurFrame::ArthurFrame(QWidget *parent)
}
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
void ArthurFrame::enableOpenGL(bool use_opengl)
{
if (m_use_opengl == use_opengl)
return;
- if (!glw && use_opengl) {
- glw = new GLWidget(this);
- glw->setAutoFillBackground(false);
- glw->disableAutoBufferSwap();
+ m_use_opengl = use_opengl;
+
+ if (!m_glWindow && use_opengl) {
+ createGlWindow();
QApplication::postEvent(this, new QResizeEvent(size(), size()));
}
- m_use_opengl = use_opengl;
if (use_opengl) {
- glw->show();
+ m_glWidget->show();
} else {
- if (glw)
- glw->hide();
+ if (m_glWidget)
+ m_glWidget->hide();
}
update();
}
+
+void ArthurFrame::createGlWindow()
+{
+ Q_ASSERT(m_use_opengl);
+
+ m_glWindow = new QOpenGLWindow();
+ QSurfaceFormat f = QSurfaceFormat::defaultFormat();
+ f.setSamples(4);
+ f.setAlphaBufferSize(8);
+ f.setStencilBufferSize(8);
+ m_glWindow->setFormat(f);
+ m_glWindow->setFlags(Qt::WindowTransparentForInput);
+ m_glWindow->resize(width() - 1, height() - 1);
+ m_glWindow->create();
+ m_glWidget = QWidget::createWindowContainer(m_glWindow, this);
+}
#endif
+
void ArthurFrame::paintEvent(QPaintEvent *e)
{
static QImage *static_image = 0;
+
QPainter painter;
+
if (preferImage()
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
&& !m_use_opengl
#endif
) {
@@ -142,10 +159,12 @@ void ArthurFrame::paintEvent(QPaintEvent *e)
painter.fillRect(0, height() - o, o, o, bg);
painter.fillRect(width() - o, height() - o, o, o, bg);
} else {
-#ifdef QT_OPENGL_SUPPORT
- if (m_use_opengl) {
- painter.begin(glw);
- painter.fillRect(QRectF(0, 0, glw->width(), glw->height()), palette().color(backgroundRole()));
+#if QT_CONFIG(opengl)
+ if (m_use_opengl && m_glWindow->isValid()) {
+ m_glWindow->makeCurrent();
+
+ painter.begin(m_glWindow);
+ painter.fillRect(QRectF(0, 0, m_glWindow->width(), m_glWindow->height()), palette().color(backgroundRole()));
} else {
painter.begin(this);
}
@@ -196,7 +215,7 @@ void ArthurFrame::paintEvent(QPaintEvent *e)
painter.drawPath(clipPath);
if (preferImage()
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
&& !m_use_opengl
#endif
) {
@@ -204,18 +223,17 @@ void ArthurFrame::paintEvent(QPaintEvent *e)
painter.begin(this);
painter.drawImage(e->rect(), *static_image, e->rect());
}
-
-#ifdef QT_OPENGL_SUPPORT
- if (m_use_opengl && (inherits("PathDeformRenderer") || inherits("PathStrokeRenderer") || inherits("CompositionRenderer") || m_show_doc))
- glw->swapBuffers();
+#if QT_CONFIG(opengl)
+ if (m_use_opengl)
+ m_glWindow->update();
#endif
}
void ArthurFrame::resizeEvent(QResizeEvent *e)
{
-#ifdef QT_OPENGL_SUPPORT
- if (glw)
- glw->setGeometry(0, 0, e->size().width()-1, e->size().height()-1);
+#if QT_CONFIG(opengl)
+ if (m_glWidget)
+ m_glWidget->setGeometry(0, 0, e->size().width()-1, e->size().height()-1);
#endif
QWidget::resizeEvent(e);
}
diff --git a/examples/widgets/painting/shared/arthurwidgets.h b/examples/widgets/painting/shared/arthurwidgets.h
index d6e1e44b3a..73e1310c0e 100644
--- a/examples/widgets/painting/shared/arthurwidgets.h
+++ b/examples/widgets/painting/shared/arthurwidgets.h
@@ -56,42 +56,13 @@
#include <QPushButton>
#include <QGroupBox>
-#if defined(QT_OPENGL_SUPPORT)
-#include <QGLWidget>
-#include <QEvent>
-class GLWidget : public QGLWidget
-{
-public:
- GLWidget(QWidget *parent)
- : QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
- {
- setAttribute(Qt::WA_AcceptTouchEvents);
- }
- void disableAutoBufferSwap() { setAutoBufferSwap(false); }
- void paintEvent(QPaintEvent *) override { parentWidget()->update(); }
-protected:
- bool event(QEvent *event) override
- {
- switch (event->type()) {
- case QEvent::TouchBegin:
- case QEvent::TouchUpdate:
- case QEvent::TouchEnd:
- event->ignore();
- return false;
- break;
- default:
- break;
- }
- return QGLWidget::event(event);
- }
-};
-#endif
-
+QT_FORWARD_DECLARE_CLASS(QOpenGLWindow)
QT_FORWARD_DECLARE_CLASS(QTextDocument)
QT_FORWARD_DECLARE_CLASS(QTextEdit)
QT_FORWARD_DECLARE_CLASS(QVBoxLayout)
class ArthurFrame : public QWidget
+
{
Q_OBJECT
public:
@@ -107,9 +78,8 @@ public:
void loadSourceFile(const QString &fileName);
bool preferImage() const { return m_prefer_image; }
-
-#if defined(QT_OPENGL_SUPPORT)
- QGLWidget *glWidget() const { return glw; }
+#if QT_CONFIG(opengl)
+ QOpenGLWindow *glWindow() const { return m_glWindow; }
#endif
public slots:
@@ -117,7 +87,7 @@ public slots:
void setDescriptionEnabled(bool enabled);
void showSource();
-#if defined(QT_OPENGL_SUPPORT)
+#if QT_CONFIG(opengl)
void enableOpenGL(bool use_opengl);
bool usesOpenGL() { return m_use_opengl; }
#endif
@@ -129,8 +99,10 @@ protected:
void paintEvent(QPaintEvent *) override;
void resizeEvent(QResizeEvent *) override;
-#if defined(QT_OPENGL_SUPPORT)
- GLWidget *glw;
+#if QT_CONFIG(opengl)
+ virtual void createGlWindow();
+ QOpenGLWindow *m_glWindow;
+ QWidget *m_glWidget;
bool m_use_opengl;
#endif
QPixmap m_tile;
diff --git a/examples/widgets/painting/shared/fbopaintdevice.cpp b/examples/widgets/painting/shared/fbopaintdevice.cpp
new file mode 100644
index 0000000000..8207090cc8
--- /dev/null
+++ b/examples/widgets/painting/shared/fbopaintdevice.cpp
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the demonstration applications 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 "fbopaintdevice.h"
+
+#include <QOffscreenSurface>
+#include <QOpenGLFunctions>
+
+QFboPaintDevice::QFboPaintDevice(const QSize& size, bool flipped, bool clearOnInit,
+ QOpenGLFramebufferObject::Attachment attachment)
+ : QOpenGLPaintDevice(size)
+{
+ QOpenGLFramebufferObjectFormat format;
+ format.setAttachment(attachment);
+ format.setSamples(4);
+ m_framebufferObject = new QOpenGLFramebufferObject(size, format);
+ QOffscreenSurface *surface = new QOffscreenSurface();
+ surface->create();
+ m_surface = surface;
+ setPaintFlipped(flipped);
+ if (clearOnInit) {
+ m_framebufferObject->bind();
+
+ context()->functions()->glClearColor(0, 0, 0, 0);
+ context()->functions()->glClear(GL_COLOR_BUFFER_BIT);
+ }
+}
+
+QFboPaintDevice::~QFboPaintDevice()
+{
+ delete m_framebufferObject;
+ delete m_surface;
+}
+
+void QFboPaintDevice::ensureActiveTarget()
+{
+ if (QOpenGLContext::currentContext() != context())
+ context()->makeCurrent(m_surface);
+
+ m_framebufferObject->bind();
+}
+
+GLuint QFboPaintDevice::takeTexture()
+{
+ // We have multisamples so we can't just forward takeTexture().
+ QOpenGLFramebufferObject resolvedFbo(m_framebufferObject->size(), m_framebufferObject->attachment());
+ QOpenGLFramebufferObject::blitFramebuffer(&resolvedFbo, m_framebufferObject);
+ return resolvedFbo.takeTexture();
+}
+
+QImage QFboPaintDevice::toImage() const
+{
+ QOpenGLContext* currentContext = QOpenGLContext::currentContext();
+ QSurface* currentSurface = currentContext ? currentContext->surface() : 0;
+
+ context()->makeCurrent(m_surface);
+
+ QImage image = m_framebufferObject->toImage(!paintFlipped());
+
+ if (currentContext)
+ currentContext->makeCurrent(currentSurface);
+ else
+ context()->doneCurrent();
+
+ return image;
+}
diff --git a/examples/widgets/painting/shared/fbopaintdevice.h b/examples/widgets/painting/shared/fbopaintdevice.h
new file mode 100644
index 0000000000..78451af895
--- /dev/null
+++ b/examples/widgets/painting/shared/fbopaintdevice.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the demonstration applications 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$
+**
+****************************************************************************/
+
+#ifndef QFBOPAINTDEVICE_H
+#define QFBOPAINTDEVICE_H
+
+#ifndef QT_NO_OPENGL
+
+#include <QImage>
+#include <QOpenGLFramebufferObject>
+#include <QOpenGLPaintDevice>
+#include <QSurface>
+
+class QFboPaintDevice : public QOpenGLPaintDevice {
+public:
+ QFboPaintDevice(const QSize&, bool flipped = false, bool clearOnInit = true,
+ QOpenGLFramebufferObject::Attachment = QOpenGLFramebufferObject::CombinedDepthStencil);
+ ~QFboPaintDevice();
+
+ // QOpenGLPaintDevice:
+ void ensureActiveTarget() override;
+
+ bool isValid() const { return m_framebufferObject->isValid(); }
+ GLuint handle() const { return m_framebufferObject->handle(); }
+ GLuint takeTexture();
+ QImage toImage() const;
+
+ bool bind() { return m_framebufferObject->bind(); }
+ bool release() { return m_framebufferObject->release(); }
+ QSize size() const { return m_framebufferObject->size(); }
+
+ QOpenGLFramebufferObject* framebufferObject() { return m_framebufferObject; }
+ const QOpenGLFramebufferObject* framebufferObject() const { return m_framebufferObject; }
+
+ static bool isSupported() { return QOpenGLFramebufferObject::hasOpenGLFramebufferObjects(); }
+
+private:
+ QOpenGLFramebufferObject *m_framebufferObject;
+ QSurface* m_surface;
+};
+
+#endif // QT_NO_OPENGL
+
+#endif // QFBOPAINTDEVICE_H
diff --git a/examples/widgets/painting/shared/hoverpoints.cpp b/examples/widgets/painting/shared/hoverpoints.cpp
index c735c83f6a..7cd8cc0b29 100644
--- a/examples/widgets/painting/shared/hoverpoints.cpp
+++ b/examples/widgets/painting/shared/hoverpoints.cpp
@@ -48,10 +48,6 @@
**
****************************************************************************/
-#ifdef QT_OPENGL_SUPPORT
-#include <QGLWidget>
-#endif
-
#include "arthurwidgets.h"
#include "hoverpoints.h"
@@ -269,11 +265,6 @@ bool HoverPoints::eventFilter(QObject *object, QEvent *event)
QApplication::sendEvent(object, event);
m_widget = that_widget;
paintPoints();
-#ifdef QT_OPENGL_SUPPORT
- ArthurFrame *af = qobject_cast<ArthurFrame *>(that_widget);
- if (af && af->usesOpenGL())
- af->glWidget()->swapBuffers();
-#endif
return true;
}
default:
@@ -288,12 +279,14 @@ bool HoverPoints::eventFilter(QObject *object, QEvent *event)
void HoverPoints::paintPoints()
{
QPainter p;
-#ifdef QT_OPENGL_SUPPORT
+#if QT_CONFIG(opengl)
ArthurFrame *af = qobject_cast<ArthurFrame *>(m_widget);
- if (af && af->usesOpenGL())
- p.begin(af->glWidget());
- else
+ if (af && af->usesOpenGL() && af->glWindow()->isValid()) {
+ af->glWindow()->makeCurrent();
+ p.begin(af->glWindow());
+ } else {
p.begin(m_widget);
+ }
#else
p.begin(m_widget);
#endif
diff --git a/examples/widgets/painting/shared/shared.pri b/examples/widgets/painting/shared/shared.pri
index 362cc6819c..cb08b00348 100644
--- a/examples/widgets/painting/shared/shared.pri
+++ b/examples/widgets/painting/shared/shared.pri
@@ -1,8 +1,8 @@
INCLUDEPATH += $$PWD
-qtHaveModule(opengl)|qtConfig(opengles2) {
- DEFINES += QT_OPENGL_SUPPORT
- QT += opengl widgets
+qtConfig(opengl) {
+ SOURCES += $$PWD/fbopaintdevice.cpp
+ HEADERS += $$PWD/fbopaintdevice.h
}
SOURCES += \
diff --git a/examples/widgets/richtext/calendar/mainwindow.cpp b/examples/widgets/richtext/calendar/mainwindow.cpp
index 12c418e0b1..38dc0e2849 100644
--- a/examples/widgets/richtext/calendar/mainwindow.cpp
+++ b/examples/widgets/richtext/calendar/mainwindow.cpp
@@ -66,7 +66,7 @@ MainWindow::MainWindow()
QComboBox *monthCombo = new QComboBox;
for (int month = 1; month <= 12; ++month)
- monthCombo->addItem(QDate::longMonthName(month));
+ monthCombo->addItem(QLocale::system().monthName(month));
QDateTimeEdit *yearEdit = new QDateTimeEdit;
yearEdit->setDisplayFormat("yyyy");
@@ -168,7 +168,7 @@ void MainWindow::insertCalendar()
QTextTableCell cell = table->cellAt(0, weekDay-1);
//! [11] //! [12]
QTextCursor cellCursor = cell.firstCursorPosition();
- cellCursor.insertText(QString("%1").arg(QDate::longDayName(weekDay)), boldFormat);
+ cellCursor.insertText(QLocale::system().dayName(weekDay), boldFormat);
}
//! [12]
@@ -194,7 +194,7 @@ void MainWindow::insertCalendar()
cursor.endEditBlock();
//! [14]
setWindowTitle(tr("Calendar for %1 %2"
- ).arg(QDate::longMonthName(selectedDate.month())
+ ).arg(QLocale::system().monthName(selectedDate.month())
).arg(selectedDate.year()));
}
//! [14]
diff --git a/examples/widgets/richtext/textedit/example.html b/examples/widgets/richtext/textedit/example.html
index e3a56d1154..99090a697f 100644
--- a/examples/widgets/richtext/textedit/example.html
+++ b/examples/widgets/richtext/textedit/example.html
@@ -1,14 +1,14 @@
<html><head><meta name="qrichtext" content="1" /><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>QTextEdit Example</title><style type="text/css">
p, li { white-space: pre-wrap; }
</style></head><body style=" font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;">
-<p align="center" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:20pt; font-weight:600;">QTextEdit</span></p>
+<h1 align="center" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:20pt; font-weight:600;">QTextEdit</span></h1>
<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">The QTextEdit widget is an advanced editor that supports formatted rich text. It can be used to display HTML and other rich document formats. Internally, QTextEdit uses the QTextDocument class to describe both the high-level structure of each document and the low-level formatting of paragraphs.</span></p>
<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;">If you are viewing this document in the <span style=" font-style:italic;">textedit</span> example, you can edit this document to explore Qt's rich text editing features. We have included some comments in each of the following sections to encourage you to experiment. </p>
-<p style=" margin-top:16px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; font-weight:600;"><span style=" font-size:16pt;">Font and Paragraph Styles</span></p>
+<h2 style=" margin-top:16px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; font-weight:600;"><span style=" font-size:16pt;">Font and Paragraph Styles</span></h2>
<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">QTextEdit supports </span><span style=" font-size:11pt; font-weight:600;">bold</span><span style=" font-size:11pt;">, </span><span style=" font-size:11pt; font-style:italic;">italic</span><span style=" font-size:11pt;">, and </span><span style=" font-size:11pt; text-decoration: underline;">underlined</span><span style=" font-size:11pt;"> font styles, and can display </span><span style=" font-size:11pt; font-weight:600; color:#00007f;">multicolored</span><span style=" font-size:11pt;"> </span><span style=" font-size:11pt; font-weight:600; color:#aa0000;">text</span><span style=" font-size:11pt;">. Font families such as </span><span style=" font-family:'Times New Roman'; font-size:11pt; font-weight:600;">Times New Roman</span><span style=" font-size:11pt;"> and </span><span style=" font-family:'Courier'; font-size:11pt; font-weight:600;">Courier</span><span style=" font-size:11pt;"> can also be used directly. </span><span style=" font-size:11pt; font-style:italic;">If you place the cursor in a region of styled text, the controls in the tool bars will change to reflect the current style.</span></p>
<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;">Paragraphs can be formatted so that the text is left-aligned, right-aligned, centered, or fully justified.</p>
<p align="center" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-style:italic;">Try changing the alignment of some text and resize the editor to see how the text layout changes.</span> </p>
-<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; font-weight:600;">Lists</span></p>
+<h2 align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; font-weight:600;">Lists</span></h2>
<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:16pt; font-weight:600;"><span style=" font-size:11pt; font-weight:400;">Different kinds of lists can be included in rich text documents. Standard bullet lists can be nested, using different symbols for each level of the list: </span></p>
<ul style="-qt-list-indent: 1;"><li style=" font-size:11pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Disc symbols are typically used for top-level list items. </li></ul>
<ul type=circle style="-qt-list-indent: 2;"><li style=" font-size:11pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Circle symbols can be used to distinguish between items in lower-level lists.</li></ul>
@@ -24,10 +24,10 @@ p, li { white-space: pre-wrap; }
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"></p>
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;">The list will automatically be renumbered if you add or remove items. <span style=" font-style:italic;">Try adding new sections to the above list or removing existing item to see the numbers change.</span> </p>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"></p>
-<p style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-size:16pt; font-weight:600;">Images</span></p>
+<h2 style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-size:16pt; font-weight:600;">Images</span></h2>
<p style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:16pt; font-weight:600;"><span style=" font-size:11pt; font-weight:400;">Inline images are treated like ordinary ranges of characters in the text editor, so they flow with the surrounding text. Images can also be selected in the same way as text, making it easy to cut, copy, and paste them. </span></p>
<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><img src=":/images/logo32.png" /><span style=" font-style:italic;"> Try to select this image by clicking and dragging over it with the mouse, or use the text cursor to select it by holding down Shift and using the arrow keys. You can then cut or copy it, and paste it into different parts of this document.</span></p>
-<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-size:16pt; font-weight:600;">Tables</span></p>
+<h2 align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-size:16pt; font-weight:600;">Tables</span></h2>
<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:16pt; font-weight:600;"><span style=" font-size:11pt; font-weight:400;">QTextEdit can arrange and format tables, supporting features such as row and column spans, text formatting within cells, and size constraints for columns. </span></p>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"></p>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"></p>
@@ -72,8 +72,8 @@ p, li { white-space: pre-wrap; }
<td></td></tr></table>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"></p>
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt; font-style:italic;">Try adding text to the cells in the table and experiment with the alignment of the paragraphs.</p>
-<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-size:16pt; font-weight:600;">Hyperlinks</span></p>
+<h2 style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-size:16pt; font-weight:600;">Hyperlinks</span></h2>
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">QTextEdit is designed to support hyperlinks between documents, and this feature is used extensively in </span><span style=" font-size:11pt; font-style:italic;">Qt Assistant</span><span style=" font-size:11pt;">. Hyperlinks are automatically created when an HTML file is imported into an editor. Since the rich text framework supports hyperlinks natively, they can also be created programatically.</span></p>
-<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-size:16pt; font-weight:600;">Undo and Redo</span></p>
+<h2 style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-size:16pt; font-weight:600;">Undo and Redo</span></h2>
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;">Full support for undo and redo operations is built into QTextEdit and the underlying rich text framework. Operations on a document can be packaged together to make editing a more comfortable experience for the user.</p>
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-style:italic;">Try making changes to this document and press Ctrl+Z to undo them. You can always recover the original contents of the document.</span> </p></body></html>
diff --git a/examples/widgets/richtext/textedit/textedit.cpp b/examples/widgets/richtext/textedit/textedit.cpp
index fe4ee4f499..0d51ce61ad 100644
--- a/examples/widgets/richtext/textedit/textedit.cpp
+++ b/examples/widgets/richtext/textedit/textedit.cpp
@@ -141,13 +141,23 @@ TextEdit::TextEdit(QWidget *parent)
#ifndef QT_NO_CLIPBOARD
actionCut->setEnabled(false);
+ connect(textEdit, &QTextEdit::copyAvailable, actionCut, &QAction::setEnabled);
actionCopy->setEnabled(false);
+ connect(textEdit, &QTextEdit::copyAvailable, actionCopy, &QAction::setEnabled);
connect(QApplication::clipboard(), &QClipboard::dataChanged, this, &TextEdit::clipboardDataChanged);
#endif
textEdit->setFocus();
setCurrentFileName(QString());
+
+#ifdef Q_OS_MACOS
+ // Use dark text on light background on macOS, also in dark mode.
+ QPalette pal = textEdit->palette();
+ pal.setColor(QPalette::Base, QColor(Qt::white));
+ pal.setColor(QPalette::Text, QColor(Qt::black));
+ textEdit->setPalette(pal);
+#endif
}
void TextEdit::closeEvent(QCloseEvent *e)
@@ -348,6 +358,12 @@ void TextEdit::setupTextActions()
comboStyle->addItem("Ordered List (Alpha upper)");
comboStyle->addItem("Ordered List (Roman lower)");
comboStyle->addItem("Ordered List (Roman upper)");
+ comboStyle->addItem("Heading 1");
+ comboStyle->addItem("Heading 2");
+ comboStyle->addItem("Heading 3");
+ comboStyle->addItem("Heading 4");
+ comboStyle->addItem("Heading 5");
+ comboStyle->addItem("Heading 6");
connect(comboStyle, QOverload<int>::of(&QComboBox::activated), this, &TextEdit::textStyle);
@@ -575,44 +591,56 @@ void TextEdit::textSize(const QString &p)
void TextEdit::textStyle(int styleIndex)
{
QTextCursor cursor = textEdit->textCursor();
+ QTextListFormat::Style style = QTextListFormat::ListStyleUndefined;
+
+ switch (styleIndex) {
+ case 1:
+ style = QTextListFormat::ListDisc;
+ break;
+ case 2:
+ style = QTextListFormat::ListCircle;
+ break;
+ case 3:
+ style = QTextListFormat::ListSquare;
+ break;
+ case 4:
+ style = QTextListFormat::ListDecimal;
+ break;
+ case 5:
+ style = QTextListFormat::ListLowerAlpha;
+ break;
+ case 6:
+ style = QTextListFormat::ListUpperAlpha;
+ break;
+ case 7:
+ style = QTextListFormat::ListLowerRoman;
+ break;
+ case 8:
+ style = QTextListFormat::ListUpperRoman;
+ break;
+ default:
+ break;
+ }
- if (styleIndex != 0) {
- QTextListFormat::Style style = QTextListFormat::ListDisc;
-
- switch (styleIndex) {
- default:
- case 1:
- style = QTextListFormat::ListDisc;
- break;
- case 2:
- style = QTextListFormat::ListCircle;
- break;
- case 3:
- style = QTextListFormat::ListSquare;
- break;
- case 4:
- style = QTextListFormat::ListDecimal;
- break;
- case 5:
- style = QTextListFormat::ListLowerAlpha;
- break;
- case 6:
- style = QTextListFormat::ListUpperAlpha;
- break;
- case 7:
- style = QTextListFormat::ListLowerRoman;
- break;
- case 8:
- style = QTextListFormat::ListUpperRoman;
- break;
- }
+ cursor.beginEditBlock();
- cursor.beginEditBlock();
+ QTextBlockFormat blockFmt = cursor.blockFormat();
- QTextBlockFormat blockFmt = cursor.blockFormat();
+ if (style == QTextListFormat::ListStyleUndefined) {
+ blockFmt.setObjectIndex(-1);
+ int headingLevel = styleIndex >= 9 ? styleIndex - 9 + 1 : 0; // H1 to H6, or Standard
+ blockFmt.setHeadingLevel(headingLevel);
+ cursor.setBlockFormat(blockFmt);
+ int sizeAdjustment = headingLevel ? 4 - headingLevel : 0; // H1 to H6: +3 to -2
+ QTextCharFormat fmt;
+ fmt.setFontWeight(headingLevel ? QFont::Bold : QFont::Normal);
+ fmt.setProperty(QTextFormat::FontSizeAdjustment, sizeAdjustment);
+ cursor.select(QTextCursor::LineUnderCursor);
+ cursor.mergeCharFormat(fmt);
+ textEdit->mergeCurrentCharFormat(fmt);
+ } else {
QTextListFormat listFmt;
-
if (cursor.currentList()) {
listFmt = cursor.currentList()->format();
} else {
@@ -620,18 +648,11 @@ void TextEdit::textStyle(int styleIndex)
blockFmt.setIndent(0);
cursor.setBlockFormat(blockFmt);
}
-
listFmt.setStyle(style);
-
cursor.createList(listFmt);
-
- cursor.endEditBlock();
- } else {
- // ####
- QTextBlockFormat bfmt;
- bfmt.setObjectIndex(-1);
- cursor.mergeBlockFormat(bfmt);
}
+
+ cursor.endEditBlock();
}
void TextEdit::textColor()
@@ -666,6 +687,41 @@ void TextEdit::currentCharFormatChanged(const QTextCharFormat &format)
void TextEdit::cursorPositionChanged()
{
alignmentChanged(textEdit->alignment());
+ QTextList *list = textEdit->textCursor().currentList();
+ if (list) {
+ switch (list->format().style()) {
+ case QTextListFormat::ListDisc:
+ comboStyle->setCurrentIndex(1);
+ break;
+ case QTextListFormat::ListCircle:
+ comboStyle->setCurrentIndex(2);
+ break;
+ case QTextListFormat::ListSquare:
+ comboStyle->setCurrentIndex(3);
+ break;
+ case QTextListFormat::ListDecimal:
+ comboStyle->setCurrentIndex(4);
+ break;
+ case QTextListFormat::ListLowerAlpha:
+ comboStyle->setCurrentIndex(5);
+ break;
+ case QTextListFormat::ListUpperAlpha:
+ comboStyle->setCurrentIndex(6);
+ break;
+ case QTextListFormat::ListLowerRoman:
+ comboStyle->setCurrentIndex(7);
+ break;
+ case QTextListFormat::ListUpperRoman:
+ comboStyle->setCurrentIndex(8);
+ break;
+ default:
+ comboStyle->setCurrentIndex(-1);
+ break;
+ }
+ } else {
+ int headingLevel = textEdit->textCursor().blockFormat().headingLevel();
+ comboStyle->setCurrentIndex(headingLevel ? headingLevel + 8 : 0);
+ }
}
void TextEdit::clipboardDataChanged()
diff --git a/examples/widgets/tools/undo/main.cpp b/examples/widgets/tools/undo/main.cpp
index eff44ca3e8..a5ec1b1b83 100644
--- a/examples/widgets/tools/undo/main.cpp
+++ b/examples/widgets/tools/undo/main.cpp
@@ -62,4 +62,4 @@ int main(int argc, char **argv)
win.show();
return app.exec();
-};
+}
diff --git a/examples/widgets/touch/dials/dials.pro b/examples/widgets/touch/dials/dials.pro
new file mode 100644
index 0000000000..0e823551cc
--- /dev/null
+++ b/examples/widgets/touch/dials/dials.pro
@@ -0,0 +1,8 @@
+QT += widgets
+
+SOURCES += main.cpp
+FORMS += dials.ui
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/widgets/touch/dials
+INSTALLS += target
diff --git a/examples/touch/dials/dials.ui b/examples/widgets/touch/dials/dials.ui
index 8ca7ae9475..8ca7ae9475 100644
--- a/examples/touch/dials/dials.ui
+++ b/examples/widgets/touch/dials/dials.ui
diff --git a/examples/touch/dials/doc/images/touch-dials-example.png b/examples/widgets/touch/dials/doc/images/touch-dials-example.png
index 60e1776fc3..60e1776fc3 100644
--- a/examples/touch/dials/doc/images/touch-dials-example.png
+++ b/examples/widgets/touch/dials/doc/images/touch-dials-example.png
Binary files differ
diff --git a/examples/widgets/touch/dials/doc/src/touch-dials.qdoc b/examples/widgets/touch/dials/doc/src/touch-dials.qdoc
new file mode 100644
index 0000000000..dec8248efb
--- /dev/null
+++ b/examples/widgets/touch/dials/doc/src/touch-dials.qdoc
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example touch/dials
+ \title Touch Dials Example
+ \ingroup touchinputexamples
+ \brief Shows how to apply touch to a set of standard Qt widgets.
+
+ The Touch Dials example shows how to apply touch to a set of
+ standard Qt widgets.
+
+ \image touch-dials-example.png
+*/
diff --git a/examples/touch/dials/main.cpp b/examples/widgets/touch/dials/main.cpp
index 071f485de3..071f485de3 100644
--- a/examples/touch/dials/main.cpp
+++ b/examples/widgets/touch/dials/main.cpp
diff --git a/examples/widgets/touch/fingerpaint/doc/src/fingerpaint.qdoc b/examples/widgets/touch/fingerpaint/doc/src/fingerpaint.qdoc
new file mode 100644
index 0000000000..6f8f636f86
--- /dev/null
+++ b/examples/widgets/touch/fingerpaint/doc/src/fingerpaint.qdoc
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example touch/fingerpaint
+ \title Finger Paint Example
+ \ingroup touchinputexamples
+ \brief Shows the use of a touchscreen to make a simple painting application.
+
+ The Finger Paint example shows the use of a touchscreen with a custom widget
+ to create a simple painting application.
+
+ \image touch-fingerpaint-example.png
+
+ This example was specifically designed to work with a touchscreen, using
+ QTouchEvent instead of QMouseEvent to handle user input over the custom
+ widget. As a result, it is not possible to draw with the mouse cursor.
+*/
diff --git a/examples/widgets/touch/fingerpaint/fingerpaint.pro b/examples/widgets/touch/fingerpaint/fingerpaint.pro
new file mode 100644
index 0000000000..6370da6607
--- /dev/null
+++ b/examples/widgets/touch/fingerpaint/fingerpaint.pro
@@ -0,0 +1,13 @@
+QT += widgets
+requires(qtConfig(filedialog))
+qtHaveModule(printsupport): QT += printsupport
+
+HEADERS = mainwindow.h \
+ scribblearea.h
+SOURCES = main.cpp \
+ mainwindow.cpp \
+ scribblearea.cpp
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/widgets/touch/fingerpaint
+INSTALLS += target
diff --git a/examples/touch/fingerpaint/main.cpp b/examples/widgets/touch/fingerpaint/main.cpp
index e7ab8856b7..e7ab8856b7 100644
--- a/examples/touch/fingerpaint/main.cpp
+++ b/examples/widgets/touch/fingerpaint/main.cpp
diff --git a/examples/touch/fingerpaint/mainwindow.cpp b/examples/widgets/touch/fingerpaint/mainwindow.cpp
index 0e45eea240..0e45eea240 100644
--- a/examples/touch/fingerpaint/mainwindow.cpp
+++ b/examples/widgets/touch/fingerpaint/mainwindow.cpp
diff --git a/examples/touch/fingerpaint/mainwindow.h b/examples/widgets/touch/fingerpaint/mainwindow.h
index 47c339050e..47c339050e 100644
--- a/examples/touch/fingerpaint/mainwindow.h
+++ b/examples/widgets/touch/fingerpaint/mainwindow.h
diff --git a/examples/touch/fingerpaint/scribblearea.cpp b/examples/widgets/touch/fingerpaint/scribblearea.cpp
index aa4e60c934..aa4e60c934 100644
--- a/examples/touch/fingerpaint/scribblearea.cpp
+++ b/examples/widgets/touch/fingerpaint/scribblearea.cpp
diff --git a/examples/touch/fingerpaint/scribblearea.h b/examples/widgets/touch/fingerpaint/scribblearea.h
index 5138e3a1ab..5138e3a1ab 100644
--- a/examples/touch/fingerpaint/scribblearea.h
+++ b/examples/widgets/touch/fingerpaint/scribblearea.h
diff --git a/examples/touch/knobs/doc/images/touch-knobs-example.png b/examples/widgets/touch/knobs/doc/images/touch-knobs-example.png
index 1cbd90d101..1cbd90d101 100644
--- a/examples/touch/knobs/doc/images/touch-knobs-example.png
+++ b/examples/widgets/touch/knobs/doc/images/touch-knobs-example.png
Binary files differ
diff --git a/examples/widgets/touch/knobs/doc/src/touch-knobs.qdoc b/examples/widgets/touch/knobs/doc/src/touch-knobs.qdoc
new file mode 100644
index 0000000000..6da5992195
--- /dev/null
+++ b/examples/widgets/touch/knobs/doc/src/touch-knobs.qdoc
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example touch/knobs
+ \title Touch Knobs Example
+ \ingroup touchinputexamples
+ \brief Shows how to create custom controls that accept touch input.
+
+ The Touch Knobs example shows how to create custom controls that
+ accept touch input.
+
+ \image touch-knobs-example.png
+*/
diff --git a/examples/touch/knobs/knob.cpp b/examples/widgets/touch/knobs/knob.cpp
index 12aaa1e948..12aaa1e948 100644
--- a/examples/touch/knobs/knob.cpp
+++ b/examples/widgets/touch/knobs/knob.cpp
diff --git a/examples/touch/knobs/knob.h b/examples/widgets/touch/knobs/knob.h
index c16b61d6f1..c16b61d6f1 100644
--- a/examples/touch/knobs/knob.h
+++ b/examples/widgets/touch/knobs/knob.h
diff --git a/examples/widgets/touch/knobs/knobs.pro b/examples/widgets/touch/knobs/knobs.pro
new file mode 100644
index 0000000000..0915b0665a
--- /dev/null
+++ b/examples/widgets/touch/knobs/knobs.pro
@@ -0,0 +1,8 @@
+QT += widgets
+
+HEADERS = knob.h
+SOURCES = main.cpp knob.cpp
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/widgets/touch/knobs
+INSTALLS += target
diff --git a/examples/touch/knobs/main.cpp b/examples/widgets/touch/knobs/main.cpp
index ea0e857e7b..ea0e857e7b 100644
--- a/examples/touch/knobs/main.cpp
+++ b/examples/widgets/touch/knobs/main.cpp
diff --git a/examples/widgets/touch/pinchzoom/doc/images/pinch-zoom-example.png b/examples/widgets/touch/pinchzoom/doc/images/pinch-zoom-example.png
new file mode 100644
index 0000000000..7db51fbf55
--- /dev/null
+++ b/examples/widgets/touch/pinchzoom/doc/images/pinch-zoom-example.png
Binary files differ
diff --git a/examples/widgets/touch/pinchzoom/doc/src/pinchzoom.qdoc b/examples/widgets/touch/pinchzoom/doc/src/pinchzoom.qdoc
new file mode 100644
index 0000000000..61db2f96c5
--- /dev/null
+++ b/examples/widgets/touch/pinchzoom/doc/src/pinchzoom.qdoc
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example touch/pinchzoom
+ \title Pinch Zoom Example
+ \ingroup touchinputexamples
+ \brief Shows how to recognize a gesture.
+
+ The Pinch Zoom example shows how to use low-level touch information
+ to recognize a gesture.
+
+ \image touch-pinchzoom-example.png
+*/
diff --git a/examples/touch/pinchzoom/graphicsview.cpp b/examples/widgets/touch/pinchzoom/graphicsview.cpp
index 54e134aea2..54e134aea2 100644
--- a/examples/touch/pinchzoom/graphicsview.cpp
+++ b/examples/widgets/touch/pinchzoom/graphicsview.cpp
diff --git a/examples/touch/pinchzoom/graphicsview.h b/examples/widgets/touch/pinchzoom/graphicsview.h
index d4e2e32d36..d4e2e32d36 100644
--- a/examples/touch/pinchzoom/graphicsview.h
+++ b/examples/widgets/touch/pinchzoom/graphicsview.h
diff --git a/examples/touch/pinchzoom/images/cheese.jpg b/examples/widgets/touch/pinchzoom/images/cheese.jpg
index dea5795fd0..dea5795fd0 100644
--- a/examples/touch/pinchzoom/images/cheese.jpg
+++ b/examples/widgets/touch/pinchzoom/images/cheese.jpg
Binary files differ
diff --git a/examples/touch/pinchzoom/main.cpp b/examples/widgets/touch/pinchzoom/main.cpp
index 938432600f..938432600f 100644
--- a/examples/touch/pinchzoom/main.cpp
+++ b/examples/widgets/touch/pinchzoom/main.cpp
diff --git a/examples/touch/pinchzoom/mice.qrc b/examples/widgets/touch/pinchzoom/mice.qrc
index accdb4d0a6..accdb4d0a6 100644
--- a/examples/touch/pinchzoom/mice.qrc
+++ b/examples/widgets/touch/pinchzoom/mice.qrc
diff --git a/examples/touch/pinchzoom/mouse.cpp b/examples/widgets/touch/pinchzoom/mouse.cpp
index 1e6814be13..1e6814be13 100644
--- a/examples/touch/pinchzoom/mouse.cpp
+++ b/examples/widgets/touch/pinchzoom/mouse.cpp
diff --git a/examples/touch/pinchzoom/mouse.h b/examples/widgets/touch/pinchzoom/mouse.h
index 870bfcd6c0..870bfcd6c0 100644
--- a/examples/touch/pinchzoom/mouse.h
+++ b/examples/widgets/touch/pinchzoom/mouse.h
diff --git a/examples/widgets/touch/pinchzoom/pinchzoom.pro b/examples/widgets/touch/pinchzoom/pinchzoom.pro
new file mode 100644
index 0000000000..ebbc7ddf1f
--- /dev/null
+++ b/examples/widgets/touch/pinchzoom/pinchzoom.pro
@@ -0,0 +1,16 @@
+QT += widgets
+
+HEADERS += \
+ mouse.h \
+ graphicsview.h
+SOURCES += \
+ main.cpp \
+ mouse.cpp \
+ graphicsview.cpp
+
+RESOURCES += \
+ mice.qrc
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/widgets/touch/pinchzoom
+INSTALLS += target
diff --git a/examples/touch/touch.pro b/examples/widgets/touch/touch.pro
index 018ec134eb..018ec134eb 100644
--- a/examples/touch/touch.pro
+++ b/examples/widgets/touch/touch.pro
diff --git a/examples/widgets/widgets.pro b/examples/widgets/widgets.pro
index 7e52125125..d975ea8307 100644
--- a/examples/widgets/widgets.pro
+++ b/examples/widgets/widgets.pro
@@ -19,6 +19,7 @@ SUBDIRS = \
scroller \
statemachine \
tools \
+ touch \
tutorials \
widgets
diff --git a/examples/widgets/widgets/tablet/mainwindow.cpp b/examples/widgets/widgets/tablet/mainwindow.cpp
index 994666d4de..a048119533 100644
--- a/examples/widgets/widgets/tablet/mainwindow.cpp
+++ b/examples/widgets/widgets/tablet/mainwindow.cpp
@@ -104,15 +104,16 @@ void MainWindow::setEventCompression(bool compress)
}
//! [5]
-void MainWindow::save()
+bool MainWindow::save()
{
QString path = QDir::currentPath() + "/untitled.png";
QString fileName = QFileDialog::getSaveFileName(this, tr("Save Picture"),
path);
-
- if (!m_canvas->saveImage(fileName))
+ bool success = m_canvas->saveImage(fileName);
+ if (!success)
QMessageBox::information(this, "Error Saving Picture",
"Could not save the image");
+ return success;
}
//! [5]
@@ -128,6 +129,14 @@ void MainWindow::load()
}
//! [6]
+void MainWindow::clear()
+{
+ if (QMessageBox::question(this, tr("Save changes"), tr("Do you want to save your changes?"),
+ QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel,
+ QMessageBox::Save) != QMessageBox::Save || save())
+ m_canvas->clear();
+}
+
//! [7]
void MainWindow::about()
{
@@ -142,6 +151,7 @@ void MainWindow::createMenus()
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(tr("&Open..."), this, &MainWindow::load, QKeySequence::Open);
fileMenu->addAction(tr("&Save As..."), this, &MainWindow::save, QKeySequence::SaveAs);
+ fileMenu->addAction(tr("&New"), this, &MainWindow::clear, QKeySequence::New);
fileMenu->addAction(tr("E&xit"), this, &MainWindow::close, QKeySequence::Quit);
QMenu *brushMenu = menuBar()->addMenu(tr("&Brush"));
diff --git a/examples/widgets/widgets/tablet/mainwindow.h b/examples/widgets/widgets/tablet/mainwindow.h
index 4b99324f04..4be28784b5 100644
--- a/examples/widgets/widgets/tablet/mainwindow.h
+++ b/examples/widgets/widgets/tablet/mainwindow.h
@@ -72,8 +72,9 @@ private slots:
void setLineWidthValuator(QAction *action);
void setSaturationValuator(QAction *action);
void setEventCompression(bool compress);
- void save();
+ bool save();
void load();
+ void clear();
void about();
private:
diff --git a/examples/widgets/widgets/tablet/tablet.pro b/examples/widgets/widgets/tablet/tablet.pro
index 5772cd0385..647dc2c2f7 100644
--- a/examples/widgets/widgets/tablet/tablet.pro
+++ b/examples/widgets/widgets/tablet/tablet.pro
@@ -10,6 +10,11 @@ SOURCES = mainwindow.cpp \
tabletapplication.cpp
RESOURCES += images.qrc
+# Avoid naming the target "tablet", as it would create an executable
+# named "tablet.exe" on Windows and trigger a bug (in the Wacom drivers, apparently)
+# preventing tablet messages from being received.
+TARGET = qttablet
+
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/widgets/tablet
INSTALLS += target
diff --git a/examples/widgets/widgets/tablet/tabletcanvas.cpp b/examples/widgets/widgets/tablet/tabletcanvas.cpp
index 73678ab754..bfcc84e182 100644
--- a/examples/widgets/widgets/tablet/tabletcanvas.cpp
+++ b/examples/widgets/widgets/tablet/tabletcanvas.cpp
@@ -90,6 +90,12 @@ bool TabletCanvas::loadImage(const QString &file)
}
//! [2]
+void TabletCanvas::clear()
+{
+ m_pixmap.fill(Qt::white);
+ update();
+}
+
//! [3]
void TabletCanvas::tabletEvent(QTabletEvent *event)
{
@@ -142,12 +148,14 @@ void TabletCanvas::initPixmap()
m_pixmap = newPixmap;
}
-void TabletCanvas::paintEvent(QPaintEvent *)
+void TabletCanvas::paintEvent(QPaintEvent *event)
{
if (m_pixmap.isNull())
initPixmap();
QPainter painter(this);
- painter.drawPixmap(0, 0, m_pixmap);
+ QRect pixmapPortion = QRect(event->rect().topLeft() * devicePixelRatioF(),
+ event->rect().size() * devicePixelRatioF());
+ painter.drawPixmap(event->rect().topLeft(), m_pixmap, pixmapPortion);
}
//! [4]
diff --git a/examples/widgets/widgets/tablet/tabletcanvas.h b/examples/widgets/widgets/tablet/tabletcanvas.h
index 671d5376f8..c63ef76893 100644
--- a/examples/widgets/widgets/tablet/tabletcanvas.h
+++ b/examples/widgets/widgets/tablet/tabletcanvas.h
@@ -79,6 +79,7 @@ public:
bool saveImage(const QString &file);
bool loadImage(const QString &file);
+ void clear();
void setAlphaChannelValuator(Valuator type)
{ m_alphaChannelValuator = type; }
void setColorSaturationValuator(Valuator type)
diff --git a/header.MIT b/header.MIT
new file mode 100644
index 0000000000..df431dda02
--- /dev/null
+++ b/header.MIT
@@ -0,0 +1,28 @@
+/****************************************************************************
+**
+** Copyright (C) YYYY Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the FOO module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:MIT$
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and associated documentation files (the "Software"), to deal
+** in the Software without restriction, including without limitation the rights
+** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+** copies of the Software, and to permit persons to whom the Software is
+** furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+** THE SOFTWARE.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
diff --git a/mkspecs/android-clang/qmake.conf b/mkspecs/android-clang/qmake.conf
index b665000d00..1f5e690329 100644
--- a/mkspecs/android-clang/qmake.conf
+++ b/mkspecs/android-clang/qmake.conf
@@ -40,7 +40,11 @@ QMAKE_CFLAGS += -DANDROID_HAS_WSTRING --sysroot=$$NDK_ROOT/sysroot \
ANDROID_SOURCES_CXX_STL_LIBDIR = $$NDK_ROOT/sources/cxx-stl/llvm-libc++/libs/$$ANDROID_TARGET_ARCH
ANDROID_STDCPP_PATH = $$ANDROID_SOURCES_CXX_STL_LIBDIR/libc++_shared.so
-ANDROID_CXX_STL_LIBS = -lc++
+
+exists($$ANDROID_SOURCES_CXX_STL_LIBDIR/libc++.so): \
+ ANDROID_CXX_STL_LIBS = -lc++
+else: \
+ ANDROID_CXX_STL_LIBS = $$ANDROID_SOURCES_CXX_STL_LIBDIR/libc++.so.$$replace(ANDROID_PLATFORM, "android-", "")
QMAKE_CFLAGS_OPTIMIZE_SIZE = -Oz
diff --git a/mkspecs/common/android-base-head.conf b/mkspecs/common/android-base-head.conf
index 9be6111915..c7c27298b9 100644
--- a/mkspecs/common/android-base-head.conf
+++ b/mkspecs/common/android-base-head.conf
@@ -75,3 +75,10 @@ equals(ANDROID_TARGET_ARCH, x86_64)|equals(ANDROID_TARGET_ARCH, mips64): \
QMAKE_ANDROID_PLATFORM_LIBDIR = $${QMAKE_ANDROID_PLATFORM_LIBDIR}64
CROSS_COMPILE = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-
+
+QMAKE_PCH_OUTPUT_EXT = .gch
+
+QMAKE_CFLAGS_PRECOMPILE = -x c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
+QMAKE_CFLAGS_USE_PRECOMPILE = -include ${QMAKE_PCH_OUTPUT_BASE}
+QMAKE_CXXFLAGS_PRECOMPILE = -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
+QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE
diff --git a/mkspecs/common/android-base-tail.conf b/mkspecs/common/android-base-tail.conf
index 7c3ae9566a..e239fa01c5 100644
--- a/mkspecs/common/android-base-tail.conf
+++ b/mkspecs/common/android-base-tail.conf
@@ -30,6 +30,8 @@ QMAKE_CFLAGS_THREAD = -D_REENTRANT
QMAKE_CFLAGS_HIDESYMS = -fvisibility=hidden
QMAKE_CFLAGS_NEON = -mfpu=neon
+QMAKE_CFLAGS_GNUC99 = -std=gnu99
+QMAKE_CFLAGS_GNUC11 = -std=gnu11
QMAKE_CXXFLAGS_CXX11 = -std=c++11
QMAKE_CXXFLAGS_CXX14 = -std=c++14
QMAKE_CXXFLAGS_CXX1Z = -std=c++1z
diff --git a/mkspecs/common/clang.conf b/mkspecs/common/clang.conf
index 0fb84bc1b3..5800aaa5b4 100644
--- a/mkspecs/common/clang.conf
+++ b/mkspecs/common/clang.conf
@@ -21,6 +21,8 @@ QMAKE_CFLAGS_PRECOMPILE = -x c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_
QMAKE_CFLAGS_USE_PRECOMPILE = -Xclang -include-pch -Xclang ${QMAKE_PCH_OUTPUT}
QMAKE_CFLAGS_LTCG = -flto
QMAKE_CFLAGS_DISABLE_LTCG = -fno-lto
+QMAKE_CFLAGS_GNUC99 = -std=gnu99
+QMAKE_CFLAGS_GNUC11 = -std=gnu11
QMAKE_CXXFLAGS_PRECOMPILE = -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE
diff --git a/mkspecs/common/g++-base.conf b/mkspecs/common/g++-base.conf
index c42c46b0ec..fa0f0c391d 100644
--- a/mkspecs/common/g++-base.conf
+++ b/mkspecs/common/g++-base.conf
@@ -27,6 +27,8 @@ QMAKE_CFLAGS_USE_PRECOMPILE = -include ${QMAKE_PCH_OUTPUT_BASE}
QMAKE_CXXFLAGS_PRECOMPILE = -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE
+QMAKE_CFLAGS_GNUC99 = -std=gnu99
+QMAKE_CFLAGS_GNUC11 = -std=gnu11
QMAKE_CXXFLAGS_CXX11 = -std=c++11
QMAKE_CXXFLAGS_CXX14 = -std=c++1y
QMAKE_CXXFLAGS_CXX1Z = -std=c++1z
diff --git a/mkspecs/common/gcc-base.conf b/mkspecs/common/gcc-base.conf
index 234f71d495..c2669e4833 100644
--- a/mkspecs/common/gcc-base.conf
+++ b/mkspecs/common/gcc-base.conf
@@ -50,7 +50,7 @@ QMAKE_CFLAGS_ISYSTEM = -isystem
QMAKE_CFLAGS_YACC += -Wno-unused -Wno-parentheses
QMAKE_CFLAGS_HIDESYMS += -fvisibility=hidden
QMAKE_CFLAGS_EXCEPTIONS_OFF += -fno-exceptions
-QMAKE_CFLAGS_SPLIT_SECTIONS += -ffunction-sections
+QMAKE_CFLAGS_SPLIT_SECTIONS += -ffunction-sections -fdata-sections
QMAKE_CFLAGS_LTCG = -flto -fno-fat-lto-objects
QMAKE_CFLAGS_LTCG_FATOBJECTS = -ffat-lto-objects
QMAKE_CFLAGS_DISABLE_LTCG = -fno-lto
@@ -81,6 +81,9 @@ QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO +=
QMAKE_LFLAGS_EXCEPTIONS_OFF +=
QMAKE_LFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG -fuse-linker-plugin
+QMAKE_CFLAGS_C99 = -std=c99
+QMAKE_CFLAGS_C11 = -std=c11
+
QMAKE_CFLAGS_SSE2 += -msse2
QMAKE_CFLAGS_SSE3 += -msse3
QMAKE_CFLAGS_SSSE3 += -mssse3
@@ -105,6 +108,9 @@ QMAKE_CFLAGS_NEON += -mfpu=neon
QMAKE_CFLAGS_MIPS_DSP += -mdsp
QMAKE_CFLAGS_MIPS_DSPR2 += -mdspr2
+# -march=haswell is supported as of GCC 4.9 and Clang 3.6
+QMAKE_CFLAGS_ARCH_HASWELL = -march=core-avx2
+
# Wrapper tools that understand .o/.a files with GIMPLE instead of machine code
QMAKE_AR_LTCG = gcc-ar cqs
QMAKE_NM_LTCG = gcc-nm -P
diff --git a/mkspecs/common/icc-base-unix.conf b/mkspecs/common/icc-base-unix.conf
new file mode 100644
index 0000000000..54eda984b7
--- /dev/null
+++ b/mkspecs/common/icc-base-unix.conf
@@ -0,0 +1,106 @@
+#
+# Base qmake configuration for ICC on *nix-systems
+#
+# Before making changes to this file, please read the comment in
+# icc-base.conf, to make sure the change goes in the right place.
+#
+# To verify that your change has the desired effect on the final configuration
+# you can use the manual test in tests/manual/mkspecs.
+#
+
+MAKEFILE_GENERATOR = UNIX
+QMAKE_COMPILER_DEFINES += __GNUC__
+
+QMAKE_COMPILER = gcc intel_icc # icc pretends to be gcc
+
+QMAKE_CFLAGS_OPTIMIZE = -O2
+QMAKE_CFLAGS_OPTIMIZE_SIZE = -Os
+
+QMAKE_CC = icc
+QMAKE_LEX = flex
+QMAKE_LEXFLAGS =
+QMAKE_YACC = yacc
+QMAKE_YACCFLAGS = -d
+QMAKE_CFLAGS =
+QMAKE_CFLAGS_APP = -fPIC
+QMAKE_CFLAGS_DEPS = -M
+QMAKE_CFLAGS_WARN_ON = -w1 -Wcheck -wd654,1572,411,873,1125,2259,2261,3280,3373
+QMAKE_CFLAGS_WARN_OFF = -w
+QMAKE_CFLAGS_RELEASE = $$QMAKE_CFLAGS_OPTIMIZE
+QMAKE_CFLAGS_DEBUG = -O0 -g
+QMAKE_CFLAGS_SHLIB = -fPIC
+QMAKE_CFLAGS_STATIC_LIB = $$QMAKE_CFLAGS_SHLIB
+QMAKE_CFLAGS_SPLIT_SECTIONS = -ffunction-sections -fdata-sections
+QMAKE_CFLAGS_LTCG = -ipo
+QMAKE_CFLAGS_DISABLE_LTCG = -no-ipo
+
+QMAKE_CFLAGS_SSE2 += -msse2
+QMAKE_CFLAGS_SSE3 += -msse3
+QMAKE_CFLAGS_SSSE3 += -mssse3
+QMAKE_CFLAGS_SSE4_1 += -msse4.1
+QMAKE_CFLAGS_SSE4_2 += -msse4.2
+QMAKE_CFLAGS_AVX += -march=core-avx
+QMAKE_CFLAGS_AVX2 += -march=core-avx2
+QMAKE_CFLAGS_AVX512F += -march=broadwell -xCOMMON-AVX512
+QMAKE_CFLAGS_AVX512CD += -march=broadwell -xCOMMON-AVX512
+QMAKE_CFLAGS_AVX512ER += -march=knl
+QMAKE_CFLAGS_AVX512PF += -march=knl
+QMAKE_CFLAGS_AVX512DQ += -march=skylake-avx512
+QMAKE_CFLAGS_AVX512BW += -march=skylake-avx512
+QMAKE_CFLAGS_AVX512VL += -march=skylake-avx512
+QMAKE_CFLAGS_AESNI += -maes
+QMAKE_CFLAGS_F16C += $$QMAKE_CFLAGS_AVX2
+QMAKE_CFLAGS_RDRND += -mrdrnd
+QMAKE_CFLAGS_SHANI += -msha
+
+QMAKE_CXX = icpc
+QMAKE_CXXFLAGS = $$QMAKE_CFLAGS
+QMAKE_CXXFLAGS_APP = $$QMAKE_CFLAGS_APP
+QMAKE_CXXFLAGS_DEPS = $$QMAKE_CFLAGS_DEPS
+QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON
+QMAKE_CXXFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF
+QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE
+QMAKE_CXXFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG
+QMAKE_CXXFLAGS_SHLIB = $$QMAKE_CFLAGS_SHLIB
+QMAKE_CXXFLAGS_STATIC_LIB = $$QMAKE_CFLAGS_STATIC_LIB
+QMAKE_CXXFLAGS_SPLIT_SECTIONS = $$QMAKE_CFLAGS_SPLIT_SECTIONS
+QMAKE_CXXFLAGS_EXCEPTIONS_OFF = -fno-exceptions
+QMAKE_CXXFLAGS_CXX11 = -std=c++11
+QMAKE_CXXFLAGS_CXX14 = -std=c++1y
+QMAKE_CXXFLAGS_CXX1Z = -std=c++1z
+QMAKE_CXXFLAGS_GNUCXX11 = -std=gnu++11
+QMAKE_CXXFLAGS_GNUCXX14 = -std=gnu++1y
+QMAKE_CXXFLAGS_GNUCXX1Z = -std=gnu++1z
+QMAKE_CXXFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG
+QMAKE_CXXFLAGS_DISABLE_LTCG = $$QMAKE_CFLAGS_DISABLE_LTCG
+
+# pch support
+CONFIG += icc_pch_style
+QMAKE_PCH_OUTPUT_EXT = .pchi
+QMAKE_CXXFLAGS_USE_PRECOMPILE = -pch-use ${QMAKE_PCH_OUTPUT} -include ${QMAKE_PCH_INPUT}
+QMAKE_CXXFLAGS_PRECOMPILE = -c -pch-create ${QMAKE_PCH_OUTPUT} -include ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_TEMP_OBJECT} ${QMAKE_PCH_TEMP_SOURCE}
+
+# Symbol visibility control
+QMAKE_CFLAGS_HIDESYMS += -fvisibility=hidden
+QMAKE_CXXFLAGS_HIDESYMS += $$QMAKE_CFLAGS_HIDESYMS -fvisibility-inlines-hidden
+
+QMAKE_LINK = icpc
+QMAKE_LINK_SHLIB = icpc
+QMAKE_LFLAGS =
+QMAKE_LFLAGS_RELEASE =
+QMAKE_LFLAGS_DEBUG =
+QMAKE_LFLAGS_THREAD =
+QMAKE_LFLAGS_RPATH = -Wl,-rpath,
+QMAKE_LFLAGS_CXX11 =
+QMAKE_LFLAGS_CXX14 =
+QMAKE_LFLAGS_CXX1Z =
+QMAKE_LFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG
+
+QMAKE_INCDIR =
+QMAKE_LIBDIR =
+QMAKE_INCDIR_X11 =
+QMAKE_LIBDIR_X11 =
+QMAKE_INCDIR_OPENGL =
+QMAKE_LIBDIR_OPENGL =
+
+QMAKE_CLEAN = -r $(OBJECTS_DIR)/ti_files
diff --git a/mkspecs/common/macx.conf b/mkspecs/common/macx.conf
index 8f9eda10d7..889027ada5 100644
--- a/mkspecs/common/macx.conf
+++ b/mkspecs/common/macx.conf
@@ -5,7 +5,10 @@
QMAKE_PLATFORM += macos osx macx
QMAKE_MAC_SDK = macosx
-QT_MAC_SDK_VERSION_TESTED_WITH = 10.13
+QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.12
+QMAKE_APPLE_DEVICE_ARCHS = x86_64
+QT_MAC_SDK_VERSION_MIN = 10.13
+QT_MAC_SDK_VERSION_MAX = 10.14
device.sdk = macosx
device.target = device
@@ -13,4 +16,6 @@ device.dir_affix = $${device.sdk}
device.CONFIG = $${device.sdk}
device.deployment_identifier = $${device.sdk}
+QMAKE_LIBS_VULKAN =
+
include(mac.conf)
diff --git a/mkspecs/common/msvc-desktop.conf b/mkspecs/common/msvc-desktop.conf
index b7d2eecc82..a4fadeb029 100644
--- a/mkspecs/common/msvc-desktop.conf
+++ b/mkspecs/common/msvc-desktop.conf
@@ -16,7 +16,9 @@ MAKEFILE_GENERATOR = MSVC.NET
QMAKE_PLATFORM = win32
QMAKE_COMPILER = msvc
CONFIG += flat debug_and_release debug_and_release_target precompile_header autogen_precompile_source embed_manifest_dll embed_manifest_exe
-DEFINES += UNICODE _UNICODE WIN32
+# MSVC 2017 15.8+ fixed std::aligned_storage but compilation fails without
+# _ENABLE_EXTENDED_ALIGNED_STORAGE flag since the fix breaks binary compatibility.
+DEFINES += UNICODE _UNICODE WIN32 _ENABLE_EXTENDED_ALIGNED_STORAGE
QMAKE_COMPILER_DEFINES += _WIN32
contains(QMAKE_TARGET.arch, x86_64) {
DEFINES += WIN64
diff --git a/mkspecs/common/msvc-version.conf b/mkspecs/common/msvc-version.conf
index 5805383a04..3fb55c9d81 100644
--- a/mkspecs/common/msvc-version.conf
+++ b/mkspecs/common/msvc-version.conf
@@ -110,12 +110,6 @@ greaterThan(QMAKE_MSC_VER, 1909) {
QMAKE_CXXFLAGS_CXX14 = -std:c++14
QMAKE_CXXFLAGS_CXX1Z = -std:c++17
}
-
- # MSVC 2017 15.8+ fixed std::aligned_storage but compilation fails without
- # this flag since the fix breaks binary compatibility.
- greaterThan(QMAKE_MSC_VER, 1914) {
- DEFINES += _ENABLE_EXTENDED_ALIGNED_STORAGE
- }
}
greaterThan(QMAKE_MSC_VER, 1910) {
diff --git a/mkspecs/common/qcc-base-qnx.conf b/mkspecs/common/qcc-base-qnx.conf
index 148645b4e9..21ce269006 100644
--- a/mkspecs/common/qcc-base-qnx.conf
+++ b/mkspecs/common/qcc-base-qnx.conf
@@ -42,9 +42,13 @@ QMAKE_INCDIR_POST = $${QNX_DIR}/usr/include $${QNX_DIR}/usr/include/freety
QMAKE_LIBDIR_POST = $${QNX_DIR}/$${QNX_CPUDIR}/lib $${QNX_DIR}/$${QNX_CPUDIR}/usr/lib
QMAKE_RPATHLINKDIR_POST += $${QNX_DIR}/$${QNX_CPUDIR}/lib $${QNX_DIR}/$${QNX_CPUDIR}/usr/lib
-QMAKE_CXXFLAGS_CXX11 = -Wc,-std=gnu++11
-QMAKE_CXXFLAGS_CXX14 = -Wc,-std=gnu++1y
-QMAKE_CXXFLAGS_CXX1Z = -Wc,-std=gnu++1z
+QMAKE_CXXFLAGS_CXX11 =
+QMAKE_CXXFLAGS_CXX14 =
+QMAKE_CXXFLAGS_CXX1Z =
+
+QMAKE_CXXFLAGS_GNUCXX11 = -Wc,-std=gnu++11
+QMAKE_CXXFLAGS_GNUCXX14 = -Wc,-std=gnu++1y
+QMAKE_CXXFLAGS_GNUCXX1Z = -Wc,-std=gnu++1z
QMAKE_LINK_C = $$QMAKE_CC
QMAKE_LINK_C_SHLIB = $$QMAKE_CC
diff --git a/mkspecs/common/winrt_winphone/qmake.conf b/mkspecs/common/winrt_winphone/qmake.conf
index 8c1a767dfa..375e084127 100644
--- a/mkspecs/common/winrt_winphone/qmake.conf
+++ b/mkspecs/common/winrt_winphone/qmake.conf
@@ -8,7 +8,9 @@ MAKEFILE_GENERATOR = MSBUILD
QMAKE_COMPILER = msvc
QMAKE_PLATFORM = winrt win32
CONFIG = package_manifest $$CONFIG incremental flat precompile_header autogen_precompile_source debug_and_release debug_and_release_target rtti
-DEFINES += UNICODE WIN32 QT_LARGEFILE_SUPPORT Q_BYTE_ORDER=Q_LITTLE_ENDIAN
+# MSVC 2017 15.8+ fixed std::aligned_storage but compilation fails without
+# _ENABLE_EXTENDED_ALIGNED_STORAGE flag since the fix breaks binary compatibility.
+DEFINES += UNICODE WIN32 QT_LARGEFILE_SUPPORT Q_BYTE_ORDER=Q_LITTLE_ENDIAN _ENABLE_EXTENDED_ALIGNED_STORAGE
QMAKE_COMPILER_DEFINES += _WIN32
DEPLOYMENT_PLUGIN += qwinrt
diff --git a/mkspecs/features/ctest_testcase_common.prf b/mkspecs/features/ctest_testcase_common.prf
index 0d5ff5f89c..63e31f5415 100644
--- a/mkspecs/features/ctest_testcase_common.prf
+++ b/mkspecs/features/ctest_testcase_common.prf
@@ -48,8 +48,8 @@ for (dep, dependentmodules): \
dependentmodules = $$join(mod_deps, ";")
QT_FOR_CONFIG += gui-private
-qtConfig(angle): CMAKE_GL_DEFINES = -DQT_WITH_ANGLE=True
-!qtConfig(egl): CMAKE_GL_DEFINES += -DNO_EGL=True
+qtHaveModule(gui):qtConfig(angle): CMAKE_GL_DEFINES = -DQT_WITH_ANGLE=True
+qtHaveModule(gui):!qtConfig(egl): CMAKE_GL_DEFINES += -DNO_EGL=True
CMAKE_MODULE_VERSIONS =
CMAKE_MODULES_UNDER_TEST =
diff --git a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in
index 27f4c277d6..3ed6dd5889 100644
--- a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in
+++ b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in
@@ -235,6 +235,9 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} PROPERTY
INTERFACE_COMPILE_DEFINITIONS $${MODULE_DEFINES})
+ set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} PROPERTY INTERFACE_QT_ENABLED_FEATURES $$join(QT.$${MODULE}.enabled_features, ";"))
+ set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} PROPERTY INTERFACE_QT_DISABLED_FEATURES $$join(QT.$${MODULE}.disabled_features, ";"))
+
set(_Qt5$${CMAKE_MODULE_NAME}_PRIVATE_DIRS_EXIST TRUE)
foreach (_Qt5$${CMAKE_MODULE_NAME}_PRIVATE_DIR ${Qt5$${CMAKE_MODULE_NAME}_OWN_PRIVATE_INCLUDE_DIRS})
if (NOT EXISTS ${_Qt5$${CMAKE_MODULE_NAME}_PRIVATE_DIR})
diff --git a/mkspecs/features/data/macros.cpp b/mkspecs/features/data/macros.cpp
index 9dcb8f0914..7a06fad1a6 100644
--- a/mkspecs/features/data/macros.cpp
+++ b/mkspecs/features/data/macros.cpp
@@ -27,3 +27,6 @@ QMAKE_GCC_MAJOR_VERSION = __GNUC__
QMAKE_GCC_MINOR_VERSION = __GNUC_MINOR__
QMAKE_GCC_PATCH_VERSION = __GNUC_PATCHLEVEL__
#endif
+#ifdef __ghs__
+QMAKE_GHS_VERSION = __GHS_VERSION_NUMBER
+#endif
diff --git a/mkspecs/features/default_post.prf b/mkspecs/features/default_post.prf
index 9eba5bcf00..fbf1f3b8df 100644
--- a/mkspecs/features/default_post.prf
+++ b/mkspecs/features/default_post.prf
@@ -113,6 +113,8 @@ breakpad {
!isEmpty(QMAKE_STRIP):QMAKE_POST_LINK = $$QMAKE_POST_LINK$$escape_expand(\\n\\t)$$quote($$QMAKE_STRIP $$DEBUGFILENAME)
}
+c++17: CONFIG += c++1z
+
!c++11:!c++14:!c++1z {
# Qt requires C++11 since 5.7, check if we need to force a compiler option
QT_COMPILER_STDCXX_no_L = $$replace(QT_COMPILER_STDCXX, "L$", "")
@@ -134,7 +136,7 @@ c++11|c++14|c++1z {
isEmpty(QMAKE_CXXFLAGS_GNU$$cxxstd) {
strict_c++: QMAKE_CXXFLAGS += $$QMAKE_CXXFLAGS_STRICTCXX
} else {
- !strict_c++: cxxstd = GNU$$cxxstd
+ !strict_c++|isEmpty(QMAKE_CXXFLAGS_$$cxxstd): cxxstd = GNU$$cxxstd
}
QMAKE_CXXFLAGS += $$eval(QMAKE_CXXFLAGS_$$cxxstd)
@@ -143,6 +145,19 @@ c++11|c++14|c++1z {
unset(cxxstd)
}
+c99|c11 {
+ c11: cstd = C11
+ else: cstd = C99
+
+ !isEmpty(QMAKE_CFLAGS_GNU$$cstd) {
+ !strict_c|isEmpty(QMAKE_CFLAGS_$$cstd): cstd = GNU$$cstd
+ }
+
+ QMAKE_CFLAGS += $$eval(QMAKE_CFLAGS_$$cstd)
+
+ unset(cstd)
+}
+
utf8_source {
QMAKE_CFLAGS += $$QMAKE_CFLAGS_UTF8_SOURCE
QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_UTF8_SOURCE
diff --git a/mkspecs/features/exclusive_builds.prf b/mkspecs/features/exclusive_builds.prf
index 2d7f0e1ab6..1ff9a04d42 100644
--- a/mkspecs/features/exclusive_builds.prf
+++ b/mkspecs/features/exclusive_builds.prf
@@ -38,5 +38,5 @@ defineTest(addExclusiveBuilds) {
}
# Default directories to process
-QMAKE_DIR_REPLACE = OBJECTS_DIR MOC_DIR RCC_DIR PRECOMPILED_DIR QGLTF_DIR DESTDIR TRACEGEN_DIR QMLCACHE_DIR
-QMAKE_DIR_REPLACE_SANE += QGLTF_DIR TRACEGEN_DIR QMLCACHE_DIR
+QMAKE_DIR_REPLACE = OBJECTS_DIR MOC_DIR RCC_DIR PRECOMPILED_DIR QGLTF_DIR DESTDIR TRACEGEN_DIR QMLCACHE_DIR LRELEASE_DIR
+QMAKE_DIR_REPLACE_SANE += QGLTF_DIR TRACEGEN_DIR QMLCACHE_DIR LRELEASE_DIR
diff --git a/mkspecs/features/gc_binaries.prf b/mkspecs/features/gc_binaries.prf
new file mode 100644
index 0000000000..111d5d95ef
--- /dev/null
+++ b/mkspecs/features/gc_binaries.prf
@@ -0,0 +1,3 @@
+QMAKE_CFLAGS += $$QMAKE_CFLAGS_SPLIT_SECTIONS
+QMAKE_CXXFLAGS += $$QMAKE_CXXFLAGS_SPLIT_SECTIONS
+QMAKE_LFLAGS += $$QMAKE_LFLAGS_GCSECTIONS
diff --git a/mkspecs/features/lrelease.prf b/mkspecs/features/lrelease.prf
new file mode 100644
index 0000000000..1e828b64df
--- /dev/null
+++ b/mkspecs/features/lrelease.prf
@@ -0,0 +1,41 @@
+# Automatically generate .qm files out of .ts files in TRANSLATIONS and
+# EXTRA_TRANSLATIONS.
+#
+# If embed_translations is enabled, the generated .qm files are made available
+# in the resource system under :/i18n/.
+#
+# Otherwise, the .qm files are available in the build directory in LRELEASE_DIR.
+# They can also be automatically installed by setting QM_FILES_INSTALL_PATH.
+
+qtPrepareTool(QMAKE_LRELEASE, lrelease)
+
+isEmpty(LRELEASE_DIR): LRELEASE_DIR = .qm
+isEmpty(QM_FILES_RESOURCE_PREFIX): QM_FILES_RESOURCE_PREFIX = i18n
+
+lrelease.name = lrelease
+lrelease.input = TRANSLATIONS EXTRA_TRANSLATIONS
+lrelease.output = $$LRELEASE_DIR/${QMAKE_FILE_IN_BASE}.qm
+lrelease.commands = $$QMAKE_LRELEASE ${QMAKE_FILE_IN} $$QMAKE_LRELEASE_FLAGS -qm ${QMAKE_FILE_OUT}
+silent: lrelease.commands = @echo lrelease ${QMAKE_FILE_IN} && $$lrelease.commands
+lrelease.CONFIG = no_link
+QMAKE_EXTRA_COMPILERS += lrelease
+
+all_translations = $$TRANSLATIONS $$EXTRA_TRANSLATIONS
+for (translation, all_translations) {
+ # mirrors $$LRELEASE_DIR/${QMAKE_FILE_IN_BASE}.qm above
+ translation = $$basename(translation)
+ QM_FILES += $$OUT_PWD/$$LRELEASE_DIR/$$replace(translation, \\..*$, .qm)
+}
+embed_translations {
+ qmake_qm_files.files = $$QM_FILES
+ qmake_qm_files.base = $$OUT_PWD/$$LRELEASE_DIR
+ qmake_qm_files.prefix = $$QM_FILES_RESOURCE_PREFIX
+ RESOURCES += qmake_qm_files
+} else {
+ !isEmpty(QM_FILES_INSTALL_PATH) {
+ qm_files.files = $$QM_FILES
+ qm_files.path = $$QM_FILES_INSTALL_PATH
+ INSTALLS += qm_files
+ }
+ lrelease.CONFIG += target_predeps no_clean
+}
diff --git a/mkspecs/features/mac/default_post.prf b/mkspecs/features/mac/default_post.prf
index 6ea667c1a5..99f68b78f5 100644
--- a/mkspecs/features/mac/default_post.prf
+++ b/mkspecs/features/mac/default_post.prf
@@ -9,29 +9,30 @@ contains(TEMPLATE, .*app) {
# Detect incompatible SDK versions
- !versionAtLeast(QMAKE_MAC_SDK_VERSION, $$QT_MAC_SDK_VERSION): \
- warning("Qt requires at least version $$QT_MAC_SDK_VERSION of the platform SDK," \
+ isEmpty(QT_MAC_SDK_VERSION_MIN): \
+ QT_MAC_SDK_VERSION_MIN = $$QT_MAC_SDK_VERSION
+
+ !versionAtLeast(QMAKE_MAC_SDK_VERSION, $$QT_MAC_SDK_VERSION_MIN): \
+ warning("Qt requires at least version $$QT_MAC_SDK_VERSION_MIN of the platform SDK," \
"you're using $${QMAKE_MAC_SDK_VERSION}. Please upgrade.")
- !isEmpty(QT_MAC_SDK_VERSION_TESTED_WITH) {
+ !isEmpty(QT_MAC_SDK_VERSION_MAX) {
# For Qt developers only
!isEmpty($$list($$(QT_MAC_SDK_NO_VERSION_CHECK))): \
CONFIG += sdk_no_version_check
- !sdk_no_version_check:!versionAtMost(QMAKE_MAC_SDK_VERSION, $$QT_MAC_SDK_VERSION_TESTED_WITH) {
- warning("Qt has only been tested with version $$QT_MAC_SDK_VERSION_TESTED_WITH"\
- "of the platform SDK, you're using $${QMAKE_MAC_SDK_VERSION}.")
+ QMAKE_MAC_SDK_MAJOR_MINOR_VERSION = $$replace(QMAKE_MAC_SDK_VERSION, "(\d+)(\.\d+)(\.\d+)?", \1\2)
+
+ !sdk_no_version_check:!versionAtMost(QMAKE_MAC_SDK_MAJOR_MINOR_VERSION, $$QT_MAC_SDK_VERSION_MAX) {
+ warning("Qt has only been tested with version $$QT_MAC_SDK_VERSION_MAX"\
+ "of the platform SDK, you're using $${QMAKE_MAC_SDK_MAJOR_MINOR_VERSION}.")
warning("This is an unsupported configuration. You may experience build issues," \
"and by using")
warning("the $$QMAKE_MAC_SDK_VERSION SDK you are opting in to new features" \
"that Qt has not been prepared for.")
- isEqual(QMAKE_MAC_SDK_VERSION, 10.14): \
- warning("E.g., 10.14 enables dark mode and layer-backed views," \
- "which Qt $${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION} does not support.")
-
warning("Please downgrade the SDK you use to build your app to version" \
- "$$QT_MAC_SDK_VERSION_TESTED_WITH, or configure")
+ "$$QT_MAC_SDK_VERSION_MAX, or configure")
warning("with CONFIG+=sdk_no_version_check when running qmake" \
"to silence this warning.")
}
diff --git a/mkspecs/features/qml_module.prf b/mkspecs/features/qml_module.prf
index 4db0040dc5..65212b2abf 100644
--- a/mkspecs/features/qml_module.prf
+++ b/mkspecs/features/qml_module.prf
@@ -31,13 +31,17 @@ qml1_target {
instbase = $$[QT_INSTALL_QML]
}
-!qml1_target:static: CONFIG += builtin_resources
+!qml1_target:static: \
+ CONFIG += builtin_resources
+else: \
+ CONFIG += install_qml_files
builtin_resources {
URITARGET = $$replace(URI, "\\.", "_")
- # Ensure the QML files are included in the resources. In static builds,
- # the QML engine reads also the qmldir file from the resources.
- $${URITARGET}.files = $$qmldir_file $$fq_qml_files
+ # In static builds, the QML engine reads also the qmldir file from the resources.
+ static: $${URITARGET}.files = $$qmldir_file
+ # Ensure the QML files are included in the resources.
+ $${URITARGET}.files += $$fq_qml_files
# qt-project.org/imports is the path used for locating imports inside the resources
$${URITARGET}.prefix = /qt-project.org/imports/$$TARGETPATH
RESOURCES += $${URITARGET}
@@ -47,7 +51,7 @@ builtin_resources {
qmldir.base = $$_PRO_FILE_PWD_
# Tools need qmldir and plugins.qmltypes always installed on the file system
qmldir.files = $$qmldir_file $$fq_aux_qml_files
-!builtin_resources: qmldir.files += $$fq_qml_files
+install_qml_files: qmldir.files += $$fq_qml_files
qmldir.path = $$instbase/$$TARGETPATH
INSTALLS += qmldir
diff --git a/mkspecs/features/qml_plugin.prf b/mkspecs/features/qml_plugin.prf
index d49f4c49c1..cd6377dcc6 100644
--- a/mkspecs/features/qml_plugin.prf
+++ b/mkspecs/features/qml_plugin.prf
@@ -110,8 +110,16 @@ load(qt_common)
load(resolve_target)
TARGETPATHBASE = $$replace(TARGETPATH, \\.\\d+\$, )
+
+ !qml1_target {
+ isEmpty(QMAKE_PLUGINDUMP_DEPENDENCIES_FILE):exists($$_PRO_FILE_PWD_/dependencies.json): \
+ QMAKE_PLUGINDUMP_DEPENDENCIES_FILE = $$_PRO_FILE_PWD_/dependencies.json
+ !isEmpty(QMAKE_PLUGINDUMP_DEPENDENCIES_FILE): \
+ QMAKE_QMLPLUGINDUMP_FLAGS += -dependencies $$shell_quote($$QMAKE_PLUGINDUMP_DEPENDENCIES_FILE)
+ }
+
qmltypes.target = qmltypes
- qmltypes.commands = $$QMLPLUGINDUMP -nonrelocatable $$replace(TARGETPATHBASE, /, .) $$IMPORT_VERSION > $$QMLTYPEFILE
+ qmltypes.commands = $$QMLPLUGINDUMP -nonrelocatable $$QMAKE_QMLPLUGINDUMP_FLAGS $$replace(TARGETPATHBASE, /, .) $$IMPORT_VERSION > $$QMLTYPEFILE
qmltypes.depends = $$QMAKE_RESOLVED_TARGET
} else {
qmltypes.CONFIG += recursive
diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf
index b57afcf72d..90e318e2a4 100644
--- a/mkspecs/features/qt.prf
+++ b/mkspecs/features/qt.prf
@@ -230,7 +230,16 @@ for(ever) {
QMAKE_FRAMEWORKPATH *= $$MODULE_FRAMEWORKS
!isEmpty(MODULE_MODULE) {
contains(MODULE_CONFIG, lib_bundle) {
- LIBS$$var_sfx += -framework $$MODULE_MODULE
+ framework = $$MODULE_MODULE
+ qtConfig(debug_and_release):!macx-xcode {
+ platform_target_suffix = $$qtPlatformTargetSuffix()
+ !isEmpty(platform_target_suffix): \
+ # The -framework linker argument supports a name[,suffix] version,
+ # where if the suffix is specified the framework is first searched
+ # for the library with the suffix and then without.
+ framework = $$framework,$$platform_target_suffix
+ }
+ LIBS$$var_sfx += -framework $$framework
} else {
!isEmpty(MODULE_LIBS_ADD): \
LIBS$$var_sfx += -L$$MODULE_LIBS_ADD
diff --git a/mkspecs/features/qt_app.prf b/mkspecs/features/qt_app.prf
index 883f8ca215..8354f30eea 100644
--- a/mkspecs/features/qt_app.prf
+++ b/mkspecs/features/qt_app.prf
@@ -20,9 +20,6 @@ isEmpty(QMAKE_TARGET_DESCRIPTION): \
isEmpty(QMAKE_INFO_PLIST): CONFIG -= app_bundle
-# This decreases the binary size for tools if statically linked
-QMAKE_LFLAGS += $$QMAKE_LFLAGS_GCSECTIONS
-
host_build: QT -= gui # no host tool will ever use gui
host_build:force_bootstrap {
!build_pass:qtConfig(release_tools): CONFIG += release
diff --git a/mkspecs/features/qt_build_config.prf b/mkspecs/features/qt_build_config.prf
index 021036e4f9..0c6c10dded 100644
--- a/mkspecs/features/qt_build_config.prf
+++ b/mkspecs/features/qt_build_config.prf
@@ -27,6 +27,7 @@ RCC_DIR = .rcc
UI_DIR = .uic
TRACEGEN_DIR = .tracegen
QMLCACHE_DIR = .qmlcache
+LRELEASE_DIR = .qm
intel_icl {
# ICL 14.0 has a bug that makes it not find #includes in dirs starting with .
MOC_DIR = tmp/moc
diff --git a/mkspecs/features/qt_common.prf b/mkspecs/features/qt_common.prf
index 415044bb64..4ad9946ae0 100644
--- a/mkspecs/features/qt_common.prf
+++ b/mkspecs/features/qt_common.prf
@@ -17,6 +17,8 @@ DEFINES *= QT_NO_NARROWING_CONVERSIONS_IN_CONNECT
qtConfig(c++11): CONFIG += c++11 strict_c++
qtConfig(c++14): CONFIG += c++14
qtConfig(c++1z): CONFIG += c++1z
+qtConfig(c99): CONFIG += c99
+qtConfig(c11): CONFIG += c11
qtConfig(stack-protector-strong): CONFIG += stack_protector_strong
contains(TEMPLATE, .*lib) {
# module and plugins
@@ -56,19 +58,31 @@ host_build:cross_compile: return()
# -Wvla: use of variable-length arrays (an extension to C++)
clang {
clang_ver = $${QT_CLANG_MAJOR_VERSION}.$${QT_CLANG_MINOR_VERSION}
+ apple_ver = $${QT_APPLE_CLANG_MAJOR_VERSION}.$${QT_APPLE_CLANG_MINOR_VERSION}
versionAtLeast(clang_ver, 3.5): \
QMAKE_CXXFLAGS_WARN_ON += -Wdate-time
- # Clang/LLVM 5.0 and Xcode 9.0 introduced unguarded availability warnings.
- # The same construct has been a hard error in Swift from the very beginning.
- apple_ver = $${QT_APPLE_CLANG_MAJOR_VERSION}.$${QT_APPLE_CLANG_MINOR_VERSION}
- darwin:if(versionAtLeast(clang_ver, 5.0)|versionAtLeast(apple_ver, 9.0)): \
+ versionAtLeast(clang_ver, 3.6)|versionAtLeast(apple_ver, 6.3): \
+ QMAKE_CXXFLAGS_WARN_ON += -Winconsistent-missing-override
+
+ darwin {
QMAKE_CXXFLAGS_WARN_ON += \
- -Werror=unguarded-availability \
- -Werror=unguarded-availability-new \
- -Werror=unsupported-availability-guard
+ -Wobjc-interface-ivars \
+ -Wobjc-method-access \
+ -Wobjc-multiple-method-names
+
+ # Clang/LLVM 5.0 and Xcode 9.0 introduced unguarded availability warnings.
+ # The same construct has been a hard error in Swift from the very beginning.
+ versionAtLeast(clang_ver, 5.0)|versionAtLeast(apple_ver, 9.0): \
+ QMAKE_CXXFLAGS_WARN_ON += \
+ -Werror=unguarded-availability \
+ -Werror=unguarded-availability-new \
+ -Werror=unsupported-availability-guard
+ }
} else: gcc:!intel_icc {
QMAKE_CXXFLAGS_WARN_ON += -Wvla
+ # GCC 5 fixed -Wmissing-field-initializers for when there are no initializers
+ lessThan(QT_GCC_MAJOR_VERSION, 5): QMAKE_CXXFLAGS_WARN_ON += -Wno-missing-field-initializers
# GCC 5 introduced -Wdate-time
greaterThan(QT_GCC_MAJOR_VERSION, 4): QMAKE_CXXFLAGS_WARN_ON += -Wdate-time
# GCC 6 introduced these
@@ -82,11 +96,11 @@ warnings_are_errors:warning_clean {
# This setting is compiler-dependent anyway because it depends on the version of the
# compiler.
clang {
- # Apple clang 4.0-4.2,5.0-5.1,6.0-6.4,7.0-7.3
+ # Apple clang 4.0-4.2,5.0-5.1,6.0-6.4,7.0-7.3,8.0-8.3,9.0-9.2
# Regular clang 3.x-6.0
apple_ver = $${QT_APPLE_CLANG_MAJOR_VERSION}.$${QT_APPLE_CLANG_MINOR_VERSION}
reg_ver = $${QT_CLANG_MAJOR_VERSION}.$${QT_CLANG_MINOR_VERSION}
- contains(apple_ver, "4\\.[012]|5\\.[01]|6\\.[01234]|7\\.[0123]")|contains(reg_ver, "[345]\\.|6\\.0") {
+ contains(apple_ver, "4\\.[012]|5\\.[01]|6\\.[01234]|7\\.[0123]|8\\.[0123]|9\\.[012]")|contains(reg_ver, "[345]\\.|6\\.0") {
QMAKE_CXXFLAGS_WARN_ON += -Werror -Wno-error=\\$${LITERAL_HASH}warnings -Wno-error=deprecated-declarations $$WERROR
}
} else:intel_icc:linux {
diff --git a/mkspecs/features/qt_configure.prf b/mkspecs/features/qt_configure.prf
index 4039bba431..81b820978a 100644
--- a/mkspecs/features/qt_configure.prf
+++ b/mkspecs/features/qt_configure.prf
@@ -495,6 +495,15 @@ defineTest(qtConfLibrary_inline) {
!defined($${1}.libs, var):isEmpty($${1}.builds._KEYS_): \
error("'inline' source in library '$$lib' specifies neither 'libs' nor 'builds'.")
+ # library lists are specified as strings in the json sources for
+ # readability, but it's a pain to work with that, so expand it now.
+ eval($${1}.libs = $$eval($${1}.libs))
+ export($${1}.libs)
+ for (b, $${1}.builds._KEYS_) {
+ eval($${1}.builds.$${b} = $$eval($${1}.builds.$${b}))
+ export($${1}.builds.$${b})
+ }
+
# if multiple libraries provide the same export, it makes sense
# to make them recognize the same input variables.
input = $$eval($${2}.alias)
@@ -507,7 +516,7 @@ defineTest(qtConfLibrary_inline) {
iv = $${input}.libs.$${b}
vars += $$eval(config.commandline.rev_assignments.$${iv})
defined(config.input.$${iv}, var) {
- $${1}.builds.$${b} = $$eval(config.input.$${iv})
+ eval($${1}.builds.$${b} = $$eval(config.input.$${iv}))
export($${1}.builds.$${b})
$${1}.builds._KEYS_ *= $${b}
any = true
@@ -528,28 +537,28 @@ defineTest(qtConfLibrary_inline) {
# direct libs. overwrites inline libs.
defined(config.input.$${input}.libs, var) {
- $${1}.libs = $$eval(config.input.$${input}.libs)
+ eval($${1}.libs = $$eval(config.input.$${input}.libs))
export($${1}.libs)
}
# prefix. prepends to (possibly overwritten) inline libs.
- prefix = $$val_escape(config.input.$${input}.prefix)
+ prefix = $$eval(config.input.$${input}.prefix)
!isEmpty(prefix) {
$${1}.includedir = $$prefix/include
export($${1}.includedir)
- $${1}.libs = "-L$$prefix/lib $$eval($${1}.libs)"
+ $${1}.libs = -L$$prefix/lib $$eval($${1}.libs)
export($${1}.libs)
}
- incdir = $$val_escape(config.input.$${input}.incdir)
+ incdir = $$eval(config.input.$${input}.incdir)
!isEmpty(incdir) {
$${1}.includedir = $$incdir
export($${1}.includedir)
}
- libdir = $$val_escape(config.input.$${input}.libdir)
+ libdir = $$eval(config.input.$${input}.libdir)
!isEmpty(libdir) {
- $${1}.libs = "-L$$libdir $$eval($${1}.libs)"
+ $${1}.libs = -L$$libdir $$eval($${1}.libs)
export($${1}.libs)
}
@@ -563,13 +572,12 @@ defineTest(qtConfLibrary_makeSpec) {
isEmpty(spec): \
error("makeSpec source in library '$$eval($${1}.library)' does not specify 'spec'.")
- $${1}.includedir = "$$val_escape(QMAKE_INCDIR_$$spec)"
+ $${1}.includedir = $$eval(QMAKE_INCDIR_$$spec)
export($${1}.includedir)
- libs =
+ $${1}.libs =
for (l, QMAKE_LIBDIR_$$spec): \
- libs += -L$$l
- libs += $$eval(QMAKE_LIBS_$$spec)
- $${1}.libs = "$$val_escape(libs)"
+ $${1}.libs += -L$$l
+ $${1}.libs += $$eval(QMAKE_LIBS_$$spec)
export($${1}.libs)
# the library definition is always in scope, so no point in exporting it.
@@ -596,13 +604,39 @@ defineTest(qtConfLibrary_pkgConfig) {
qtRunLoggedCommand("$$pkg_config --modversion $$args", version)|return(false)
qtRunLoggedCommand("$$pkg_config --libs-only-L $$args", libpaths)|return(false)
qtRunLoggedCommand("$$pkg_config --libs-only-l $$args", libs)|return(false)
- qtRunLoggedCommand("$$pkg_config --cflags $$args", $${1}.cflags)|return(false)
version ~= s/[^0-9.].*$//
$${1}.version = $$first(version)
export($${1}.version)
- libpaths += $$libs
- $${1}.libs = "$$libpaths"
+ eval($${1}.libs = $$libpaths $$libs)
export($${1}.libs)
+
+ qtRunLoggedCommand("$$pkg_config --cflags $$args", $${1}.cflags)|return(false)
+ # Split CFLAGS into stuff that goes into DEFINES, INCLUDEPATH, and other stuff.
+ # The compound variable is still set in case something wants to use it outside
+ # regular library exports.
+ defines =
+ includes =
+ ignored =
+ eval(cflags = $$eval($${1}.cflags))
+ for (i, cflags) {
+ contains(i, "-I.*") {
+ i ~= s/^-I//
+ includes += $$i
+ } else: contains(i, "-D.*") {
+ i ~= s/^-D//
+ defines += $$i
+ } else {
+ # Sometimes, pkg-config files include other flags
+ # we really don't need and shouldn't add.
+ ignored += $$i
+ }
+ }
+ !isEmpty(ignored): \
+ qtLog("Note: Dropped compiler flags '$$ignored'.")
+ $${1}.defines = $$defines
+ export($${1}.defines)
+ $${1}.includedir = $$includes
+ export($${1}.includedir)
return(true)
}
@@ -624,21 +658,35 @@ defineTest(qtConfTest_getPkgConfigVariable) {
}
defineReplace(qtConfLibraryArgs) {
- qmake_args =
- libs = $$eval($${1}.libs)
- !isEmpty(libs): \
- qmake_args += $$system_quote(LIBS += $$libs)
+ NAME = $$upper($$eval($${1}.library))
+ qmake_args = "QMAKE_LIBS_$${NAME} = $$val_escape($${1}.libs)"
for (b, $${1}.builds._KEYS_): \
- qmake_args += $$system_quote(LIBS_$$upper($$b) += $$eval($${1}.builds.$${b}))
+ qmake_args += "QMAKE_LIBS_$${NAME}_$$upper($$b) = $$val_escape($${1}.builds.$${b})"
includedir = $$eval($${1}.includedir)
!isEmpty(includedir): \
- qmake_args += $$system_quote(INCLUDEPATH *= $$includedir)
- cflags = $$eval($${1}.cflags)
- !isEmpty(cflags): \
- qmake_args += $$system_quote(QMAKE_CFLAGS += $$cflags) $$system_quote(QMAKE_CXXFLAGS += $$cflags)
+ qmake_args += "QMAKE_INCDIR_$${NAME} = $$val_escape(includedir)"
+ defines = $$eval($${1}.defines)
+ !isEmpty(defines): \
+ qmake_args += "QMAKE_DEFINES_$${NAME} = $$val_escape(defines)"
return($$qmake_args)
}
+defineReplace(qtConfAllLibraryArgs) {
+ isEmpty(1): return()
+ dep_uses =
+ dep_args =
+ for (use, 1) {
+ use_cfg = $$section(use, :, 0, 0)
+ use_lib = $$section(use, :, 1, 1)
+ dep_uses += $$use_lib
+ !isEmpty(use_cfg) {
+ lpfx = $${use_cfg}.libraries.$$use_lib
+ dep_args += $$qtConfLibraryArgs($${lpfx}.sources.$$eval($${lpfx}.source))
+ }
+ }
+ return("QMAKE_USE += $$dep_uses" $$dep_args)
+}
+
defineTest(qtConfExportLibrary) {
lpfx = $${currentConfig}.libraries.$$1
alias = $$eval($${lpfx}.alias)
@@ -650,38 +698,17 @@ defineTest(qtConfExportLibrary) {
!$$qtConfEvaluate($$eval($${spfx}.export)): return()
output = privatePro
-
- eval(libs = $$eval($${spfx}.libs))
- eval(cflags = $$eval($${spfx}.cflags))
- eval(includes = $$eval($${spfx}.includedir))
-
- # Split $$cflags into stuff that goes into DEFINES, INCLUDEPATH, and other stuff.
- defines =
- ignored =
- for (i, cflags) {
- contains(i, "-I.*") {
- i ~= s/^-I//
- includes += $$i
- } else: contains(i, "-D.*") {
- i ~= s/^-D//
- defines += $$i
- } else {
- # Sometimes, pkg-config files or *-config scripts include other flags
- # we really don't need and shouldn't add (pg_config is really bad).
- ignored += $$i
- }
- }
- !isEmpty(ignored): \
- qtConfAddNote("Dropped compiler flags '$$ignored' when detecting library '$$name'.")
-
NAME = $$upper($$name)
# LIBS is emitted even if empty, as this allows the library to be "seen".
+ libs = $$eval($${spfx}.libs)
qtConfOutputVar(assign, $$output, QMAKE_LIBS_$$NAME, $$libs)
for (b, $${spfx}.builds._KEYS_) {
- eval(blibs = $$eval($${spfx}.builds.$${b}))
+ blibs = $$eval($${spfx}.builds.$${b})
qtConfOutputVar(assign, $$output, QMAKE_LIBS_$${NAME}_$$upper($$b), $$blibs)
}
+ defines = $$eval($${spfx}.defines)
!isEmpty(defines): qtConfOutputVar(assign, $$output, QMAKE_DEFINES_$$NAME, $$defines)
+ includes = $$eval($${spfx}.includedir)
!isEmpty(includes): qtConfOutputVar(assign, $$output, QMAKE_INCDIR_$$NAME, $$includes)
!isEmpty($${currentConfig}.module): \
qtConfExtendVar($$output, "QT.$${currentModule}_private.libraries", $$name)
@@ -708,7 +735,7 @@ defineTest(qtConfHandleLibrary) {
export($${lpfx}.result)
return()
}
- use_args = $$eval($${lpfx}.literal_args)
+ resolved_uses = $$eval($${lpfx}.resolved_uses)
qtConfLoadResult($${lpfx}, $$1, "library") {
$$eval($${lpfx}.result): \
@@ -741,9 +768,12 @@ defineTest(qtConfHandleLibrary) {
next()
}
+ $${lpfx}.source = $$s
+ export($${lpfx}.source)
+
# if the library defines a test, use it to verify the source.
!isEmpty($${lpfx}.test)|!isEmpty($${lpfx}.test._KEYS_) {
- $${lpfx}.literal_args = $$qtConfLibraryArgs($$spfx) $$use_args
+ $${lpfx}.resolved_uses = $$currentConfig:$$1 $$resolved_uses
$${lpfx}.host = $$eval($${spfx}.host)
!qtConfTest_compile($$lpfx) {
qtLog(" => source failed verification.")
@@ -759,9 +789,6 @@ defineTest(qtConfHandleLibrary) {
for (b, $${spfx}.builds._KEYS_): \
$${lpfx}.cache += sources.$${s}.builds.$${b}
- $${lpfx}.source = $$s
- export($${lpfx}.source)
-
# immediately output the library as well.
qtConfExportLibrary($$1)
@@ -855,21 +882,30 @@ defineTest(qtConfTestPrepare_compile) {
!defined(QMAKE_LIBS_$$nu, var): \
error("Test $$1 tries to use undeclared library '$$u'")
# using an external library by exported name.
- $${1}.literal_args += $$system_quote(QMAKE_USE += $$u)
+ $${1}.resolved_uses += :$$u
} else {
lpfx = $${libConfig}.libraries.$${u}
- isEmpty($${lpfx}.source): \
+ !equals($${lpfx}.result, true): \
return(false)
- $${1}.literal_args += $$qtConfLibraryArgs($${lpfx}.sources.$$eval($${lpfx}.source))
+ $${1}.resolved_uses += $$libConfig:$$u
}
}
- export($${1}.literal_args)
+ export($${1}.resolved_uses)
return(true)
}
defineTest(qtConfPrepareCompileTestSource) {
test_dir = $$2
+ test_lang = $$eval($${1}.lang)
+ isEmpty(test_lang): test_lang = "c++"
+
+ equals(test_lang, "c++"): suffix = "cpp"
+ else: equals(test_lang, "c"): suffix = "c"
+ else: equals(test_lang, "objc"): suffix = "m"
+ else: equals(test_lang, "objc++"): suffix = "mm"
+ else: error("Unknown language '$$test_lang' in compile test $$1")
+
# Create source code
contents = "/* Generated by configure */"
# Custom code before includes
@@ -893,10 +929,10 @@ defineTest(qtConfPrepareCompileTestSource) {
" /* END TEST */" \
" return 0;" \
"}"
- write_file($$test_dir/main.cpp, contents)|error()
+ write_file($$test_dir/main.$$suffix, contents)|error()
# Create stub .pro file
- contents = "SOURCES = main.cpp"
+ contents = "SOURCES = main.$$suffix"
# Custom project code
for (ent, $$qtConfScalarOrList($${1}.qmake)): \
contents += $$ent
@@ -983,8 +1019,12 @@ defineTest(qtConfTest_compile) {
cont = "CONFIG += QTDIR_build"
write_file($$test_base_out_dir/.qmake.cache, cont)|error()
+ $${1}.literal_args += $$qtConfAllLibraryArgs($$eval($${1}.resolved_uses))
+
# add possible command line args
- qmake_args += $$qtConfPrepareArgs($$eval($${1}.args)) $$eval($${1}.literal_args)
+ qmake_args += \
+ $$qtConfPrepareArgs($$eval($${1}.args)) \
+ $$qtSystemQuote($$eval($${1}.literal_args))
qtRunLoggedCommand("$$test_cmd_base $$qmake_args $$system_quote($$test_dir)") {
qtRunLoggedCommand("$$test_cmd_base $$QMAKE_MAKE"): \
@@ -994,11 +1034,6 @@ defineTest(qtConfTest_compile) {
return(false)
}
-defineTest(qtConfTest_verifySpec) {
- qtConfTest_compile($$1): return(true)
- qtConfFatalError("Cannot compile a minimal program. The toolchain or QMakeSpec is broken.", log)
-}
-
defineTest(qtConfTest_files) {
for(i, $${1}.files._KEYS_) {
f = $$eval($${1}.files.$${i})
diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf
index 8c7adc45eb..51b5bde67a 100644
--- a/mkspecs/features/qt_module.prf
+++ b/mkspecs/features/qt_module.prf
@@ -29,8 +29,6 @@ host_build|staticlib: CONFIG += static
host_build {
QT -= gui # no host module will ever use gui
- QMAKE_CFLAGS += $$QMAKE_CFLAGS_SPLIT_SECTIONS
- QMAKE_CXXFLAGS += $$QMAKE_CXXFLAGS_SPLIT_SECTIONS
force_bootstrap {
!build_pass:qtConfig(release_tools): CONFIG += release
contains(QT, core(-private)?|xml) {
@@ -266,15 +264,20 @@ load(qt_installs)
load(qt_targets)
# this builds on top of qt_common
-!internal_module:!lib_bundle:if(unix|mingw) {
+!internal_module:if(unix|mingw) {
CONFIG += create_pc
QMAKE_PKGCONFIG_DESTDIR = pkgconfig
host_build: \
QMAKE_PKGCONFIG_LIBDIR = $$[QT_HOST_LIBS]
else: \
QMAKE_PKGCONFIG_LIBDIR = $$[QT_INSTALL_LIBS/raw]
- QMAKE_PKGCONFIG_INCDIR = $$[QT_INSTALL_HEADERS/raw]
- QMAKE_PKGCONFIG_CFLAGS = -D$$MODULE_DEFINE -I${includedir}/$$MODULE_INCNAME
+ lib_bundle {
+ QMAKE_PKGCONFIG_INCDIR = $$[QT_INSTALL_LIBS/raw]/$${MODULE_INCNAME}.framework/Headers
+ QMAKE_PKGCONFIG_CFLAGS = -D$$MODULE_DEFINE
+ } else {
+ QMAKE_PKGCONFIG_INCDIR = $$[QT_INSTALL_HEADERS/raw]
+ QMAKE_PKGCONFIG_CFLAGS = -D$$MODULE_DEFINE -I${includedir}/$$MODULE_INCNAME
+ }
QMAKE_PKGCONFIG_NAME = $$replace(TARGET, ^Qt, "Qt$$QT_MAJOR_VERSION ")
QMAKE_PKGCONFIG_FILE = $$replace(TARGET, ^Qt, Qt$$QT_MAJOR_VERSION)
for(i, MODULE_DEPENDS): \
diff --git a/mkspecs/features/qt_test_helper.prf b/mkspecs/features/qt_test_helper.prf
new file mode 100644
index 0000000000..5daa14731d
--- /dev/null
+++ b/mkspecs/features/qt_test_helper.prf
@@ -0,0 +1,35 @@
+#
+# W A R N I N G
+# -------------
+#
+# This file is not part of the Qt API. It exists purely as an
+# implementation detail. It may change from version to version
+# without notice, or even be removed.
+#
+# We mean it.
+#
+
+# If an auto test needs a helper application, this helper should
+# be put into the same directory as the test itself. This common
+# folder should be the test's "main directory" or a "debug" or "release"
+# subfolder inside this main directory if debug_and_release is enabled.
+# Additionally the helper's executable is suffixed with "_helper" to
+# avoid name clashes with its folder.
+
+CONFIG -= app_bundle
+CONFIG += console
+
+debug_and_release {
+ CONFIG(debug, debug|release) {
+ TARGET = ../../debug/$${TARGET}_helper
+ } else {
+ TARGET = ../../release/$${TARGET}_helper
+ }
+} else {
+ TARGET = ../$${TARGET}_helper
+}
+
+parentFolder = $$dirname(_PRO_FILE_PWD_)
+testFolder = $$basename(parentFolder)
+target.path = $$[QT_INSTALL_TESTS]/$$testFolder
+INSTALLS += target
diff --git a/mkspecs/features/resources.prf b/mkspecs/features/resources.prf
index ff45446219..a25846bd77 100644
--- a/mkspecs/features/resources.prf
+++ b/mkspecs/features/resources.prf
@@ -72,10 +72,44 @@ for(resource, RESOURCES) {
RESOURCES += $$resource_file
}
+!isEmpty(RESOURCES):contains(TEMPLATE, .*lib):plugin:static {
+ pluginName = $$lower($$replace(_PRO_FILE_, .*/([^/.]+)\\.[^/.]+, \\1))
+
+ resource_init_function = $${pluginName}_plugin_resource_init
+ DEFINES += "QT_PLUGIN_RESOURCE_INIT_FUNCTION=$$resource_init_function"
+
+ RESOURCE_INIT_CPP = $$OUT_PWD/$${pluginName}_plugin_resources.cpp
+
+ GENERATED_SOURCES += $$RESOURCE_INIT_CPP
+ QMAKE_DISTCLEAN += $$RESOURCE_INIT_CPP
+
+ !build_pass {
+ RESOURCE_INIT_CONT = \
+ "// This file is autogenerated by qmake. It contains a function that" \
+ "// references all resources the plugin includes and the function is" \
+ "// referenced by Qt_(MOC_)EXPORT_PLUGIN to ensure the inclusion in" \
+ "// the statically linked plugin." \
+ "$${LITERAL_HASH}include <QtCore/qglobal.h>" \
+ "void $${resource_init_function}() " \
+ "{" \
+
+ for (resource, RESOURCES) {
+ resource_name = $$section($$list($$basename(resource)), ., 0, 0)
+ resource_name = $$replace(resource_name, [^a-zA-Z0-9_], _)
+ RESOURCE_INIT_CONT += " Q_INIT_RESOURCE($$resource_name);"
+ }
+
+ RESOURCE_INIT_CONT += \
+ "}"
+
+ write_file($$RESOURCE_INIT_CPP, RESOURCE_INIT_CONT)|error()
+ }
+}
+
rcc.input = RESOURCES
rcc.name = RCC ${QMAKE_FILE_IN}
rcc.depend_command = $$QMAKE_RCC_DEP -list $$QMAKE_RESOURCE_FLAGS ${QMAKE_FILE_IN}
-rcc.CONFIG += add_inputs_as_makefile_deps
+rcc.CONFIG += add_inputs_as_makefile_deps dep_lines
!resources_big|ltcg|macx-xcode|contains(TEMPLATE, "vc.*") {
diff --git a/mkspecs/features/simd.prf b/mkspecs/features/simd.prf
index e4bee7107c..a0b40fcf11 100644
--- a/mkspecs/features/simd.prf
+++ b/mkspecs/features/simd.prf
@@ -141,6 +141,28 @@ addSimdCompiler(neon)
addSimdCompiler(mips_dsp)
addSimdCompiler(mips_dspr2)
+# Haswell sub-architecture
+defineTest(addSimdArch) {
+ name = arch_$$1
+ dependencies = $$2
+ upname = $$upper($$name)
+
+ cpu_features_missing =
+ for(part, dependencies) {
+ !contains(QT_CPU_FEATURES, $$part): cpu_features_missing = 1
+ }
+
+ CONFIG += $$name
+ isEmpty(cpu_features_missing): QT_CPU_FEATURES += $$name
+
+ export(QT_CPU_FEATURES)
+ export(CONFIG)
+ addSimdCompiler($$name)
+}
+
+isEmpty(QMAKE_CFLAGS_ARCH_HASWELL): QMAKE_CFLAGS_ARCH_HASWELL = $$QMAKE_CFLAGS_AVX2
+avx2: addSimdArch(haswell, avx2 bmi bmi2 f16c fma lzcnt popcnt)
+
# Follow the Intel compiler's lead and define profiles of AVX512 instructions
defineTest(addAvx512Profile) {
name = $$1
@@ -149,7 +171,7 @@ defineTest(addAvx512Profile) {
varname = QMAKE_CFLAGS_$$upname
cpu_features_missing =
- cflags = $$QMAKE_CFLAGS_AVX512F
+ cflags = $$QMAKE_CFLAGS_ARCH_HASWELL $$QMAKE_CFLAGS_AVX512F
for(part, dependencies) {
!CONFIG($$part): return() # Profile isn't supported by the compiler
@@ -168,7 +190,4 @@ defineTest(addAvx512Profile) {
addSimdCompiler($$name)
}
addAvx512Profile(avx512common, avx512cd)
-addAvx512Profile(avx512mic, avx512cd avx512er avx512pf)
addAvx512Profile(avx512core, avx512cd avx512bw avx512dq avx512vl)
-addAvx512Profile(avx512ifmavl, avx512ifma avx512vl)
-addAvx512Profile(avx512vbmivl, avx512vbmi avx512vl)
diff --git a/mkspecs/features/testcase.prf b/mkspecs/features/testcase.prf
index 8d51c9d028..79883b7f09 100644
--- a/mkspecs/features/testcase.prf
+++ b/mkspecs/features/testcase.prf
@@ -9,6 +9,18 @@ testcase_exceptions: CONFIG += exceptions
# Set in qt_build_config.prf
testcase_no_bundle: CONFIG -= app_bundle
+# Allow testcases to mark themselves as not supporting high-DPI
+testcase_lowdpi {
+ macos {
+ !isEmpty(QMAKE_INFO_PLIST): \
+ error("QMAKE_INFO_PLIST already set, can't apply testcase_lowdpi")
+
+ QMAKE_INFO_PLIST = $$QMAKESPEC/Info.plist.disable_highdpi
+ } else {
+ # TODO: Add support for other platforms if possible
+ }
+}
+
benchmark: type = benchmark
else: type = check
@@ -77,12 +89,11 @@ isEmpty(BUILDS)|build_pass {
# Install tests unless no_testcase_installs is set, or there is already
# a `target' in INSTALLS.
#
- # Tests are installed under a directory named after the target so that each
- # test has its own directory for testdata etc.
+ # Tests are installed under a directory named after their source folder
+ # so that each test has its own directory for testdata etc.
#
- load(resolve_target)
- TARGET_BASENAME = $$basename(QMAKE_RESOLVED_TARGET)
- target.path = $$[QT_INSTALL_TESTS]/$$TARGET_BASENAME
+ TEST_FOLDER = $$basename(_PRO_FILE_PWD_)
+ target.path = $$[QT_INSTALL_TESTS]/$$TEST_FOLDER
INSTALLS += target
}
@@ -183,20 +194,26 @@ isEmpty(BUILDS)|build_pass {
}
builtin_testdata {
- ALL_TESTDATA = $$TESTDATA $$GENERATED_TESTDATA
-
- # BLACKLIST needs to be added to the testdata
- BLACKLISTPATH = $$_PRO_FILE_PWD_/BLACKLIST
- exists($$BLACKLISTPATH): ALL_TESTDATA *= $$BLACKLISTPATH
-
# RESOURCES does not support wildcards (for good reasons)
- for(td, ALL_TESTDATA): \
+ for (td, TESTDATA): \
testdata.files += $$files($$absolute_path($$td, $$_PRO_FILE_PWD_))
+ # BLACKLIST needs to be added to the testdata
+ BLACKLISTPATH = $$_PRO_FILE_PWD_/BLACKLIST
+ exists($$BLACKLISTPATH): \
+ testdata.files *= $$BLACKLISTPATH
!isEmpty(testdata.files) {
testdata.base = $$_PRO_FILE_PWD_
RESOURCES += testdata
}
+ # Extra compilers don't create wildcards to start with.
+ for (td, GENERATED_TESTDATA): \
+ gentestdata.files += $$absolute_path($$td, $$OUT_PWD)
+ !isEmpty(gentestdata.files) {
+ gentestdata.base = $$OUT_PWD
+ RESOURCES += gentestdata
+ }
+
!isEmpty(TEST_HELPER_INSTALLS): \
error("This platform does not support tests which require helpers.")
}
diff --git a/mkspecs/features/toolchain.prf b/mkspecs/features/toolchain.prf
index fdf3d1cdd3..4ecfb8d889 100644
--- a/mkspecs/features/toolchain.prf
+++ b/mkspecs/features/toolchain.prf
@@ -34,7 +34,9 @@ isEmpty($${target_prefix}.INCDIRS) {
#
# Get default include and library paths from compiler
#
- gcc {
+ wasm {
+ # wasm compiler does not work here, just use defaults
+ } else: gcc {
cmd_suffix = "<$$QMAKE_SYSTEM_NULL_DEVICE >$$QMAKE_SYSTEM_NULL_DEVICE"
equals(QMAKE_HOST.os, Windows): \
cmd_prefix = "set LC_ALL=C&"
@@ -142,6 +144,29 @@ isEmpty($${target_prefix}.INCDIRS) {
!integrity: \
error("failed to parse default search paths from compiler output")
QMAKE_DEFAULT_LIBDIRS = $$unique(QMAKE_DEFAULT_LIBDIRS)
+ } else: ghs {
+ cmd = $$QMAKE_CXX $$QMAKE_CXXFLAGS -$${LITERAL_HASH} -o /tmp/fake_output /tmp/fake_input.cpp
+ output = $$system("$$cmd", blob, ec)
+ !equals(ec, 0): qtCompilerErrror($$QMAKE_CXX, $$output)
+ output ~= s/\\\\\\n {8}//g
+ output = $$split(output, $$escape_expand(\\n))
+ for (line, output) {
+ contains(line, "^[^ ]+/ecom[^ ]+ .* /tmp/fake_input\\.cpp") {
+ for (parameter, $$list($$line)) {
+ contains(parameter, "^(-I|--include_no_mmd=|--sys_include=).*") {
+ parameter ~= s/^(-I|--include_no_mmd=|--sys_include=)//
+ QMAKE_DEFAULT_INCDIRS += $$clean_path($$parameter)
+ }
+ }
+ } else: contains(line, "^[^ ]+/elxr .*") {
+ for (parameter, $$list($$line)) {
+ contains(parameter, "^-L.*") {
+ parameter ~= s/^-L//
+ QMAKE_DEFAULT_LIBDIRS += $$clean_path($$parameter)
+ }
+ }
+ }
+ }
} else: msvc {
# This doesn't differentiate between host and target,
# but neither do the compilers.
@@ -168,14 +193,14 @@ isEmpty($${target_prefix}.INCDIRS) {
#
defineReplace(qtVariablesFromMSVC) {
- ret = $$system("$$1 -nologo -E $$2 $$system_quote($$PWD/data/macros.cpp) <NUL 2>NUL", lines, ec)
+ ret = $$system("$$1 -nologo -E $$2 $$system_quote($$PWD/data/macros.cpp) 2>NUL", lines, ec)
!equals(ec, 0): qtCompilerErrror($$1, $$ret)
return($$ret)
}
defineReplace(qtVariablesFromGCC) {
ret = $$system("$$1 -E $$system_quote($$PWD/data/macros.cpp) \
- <$$QMAKE_SYSTEM_NULL_DEVICE 2>$$QMAKE_SYSTEM_NULL_DEVICE", lines, ec)
+ 2>$$QMAKE_SYSTEM_NULL_DEVICE", lines, ec)
!equals(ec, 0): qtCompilerErrror($$1, $$ret)
return($$ret)
}
@@ -199,11 +224,11 @@ isEmpty($${target_prefix}.COMPILER_MACROS) {
} else {
vars = $$qtVariablesFromMSVC($$QMAKE_CXX)
}
- } else: gcc {
+ } else: gcc|ghs {
vars = $$qtVariablesFromGCC($$QMAKE_CXX)
}
for (v, vars) {
- contains(v, $${LITERAL_HASH}.*)|contains(v, " *"): next()
+ !contains(v, "[A-Z_]+ = .*"): next()
# Set both <varname> for the outer scope ...
eval($$v)
v ~= s/ .*//
@@ -245,6 +270,8 @@ QMAKE_COMPILER_DEFINES += __cplusplus=$$QT_COMPILER_STDCXX
__GNUC__=$$QMAKE_GCC_MAJOR_VERSION \
__GNUC_MINOR__=$$QMAKE_GCC_MINOR_VERSION \
__GNUC_PATCHLEVEL__=$$QMAKE_GCC_PATCH_VERSION
+!isEmpty(QMAKE_GHS_VERSION): \
+ QMAKE_COMPILER_DEFINES += __ghs__ __GHS_VERSION_NUMBER=$$QMAKE_GHS_VERSION
QMAKE_CFLAGS += $$QMAKE_CFLAGS_MSVC_COMPAT
QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_MSVC_COMPAT
diff --git a/mkspecs/features/uic.prf b/mkspecs/features/uic.prf
index 134d3b4acb..1cedce5ae7 100644
--- a/mkspecs/features/uic.prf
+++ b/mkspecs/features/uic.prf
@@ -3,15 +3,13 @@ qtPrepareTool(QMAKE_UIC, uic, _DEP)
isEmpty(UI_DIR):UI_DIR = .
isEmpty(QMAKE_MOD_UIC):QMAKE_MOD_UIC = ui_
-contains(TEMPLATE, .*lib):dll: QMAKE_UIC_FLAGS += -no-stringliteral
-
uic.depends += $$QMAKE_UIC_EXE
uic.commands = $$QMAKE_UIC $$QMAKE_UIC_FLAGS ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}
uic.depend_command = $$QMAKE_UIC_DEP -d ${QMAKE_FILE_IN}
uic.output = $$UI_DIR/$${QMAKE_MOD_UIC}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_H)}
uic.input = FORMS
uic.variable_out = GENERATED_FILES
-uic.CONFIG += no_link target_predeps
+uic.CONFIG += no_link target_predeps dep_lines
uic.name = UIC ${QMAKE_FILE_IN}
silent:uic.commands = @echo uic ${QMAKE_FILE_IN} && $$uic.commands
QMAKE_EXTRA_COMPILERS += uic
diff --git a/mkspecs/features/uikit/default_pre.prf b/mkspecs/features/uikit/default_pre.prf
index 6a44a67bca..ea6882fbc8 100644
--- a/mkspecs/features/uikit/default_pre.prf
+++ b/mkspecs/features/uikit/default_pre.prf
@@ -24,5 +24,3 @@ load(default_pre)
!versionAtLeast(QMAKE_XCODE_VERSION, 4.3): \
error("This mkspec requires Xcode 4.3 or later")
-ios:shared:!versionAtLeast(QMAKE_IOS_DEPLOYMENT_TARGET, 8.0): \
- QMAKE_IOS_DEPLOYMENT_TARGET = 8.0
diff --git a/mkspecs/features/uikit/gc_binaries.prf b/mkspecs/features/uikit/gc_binaries.prf
new file mode 100644
index 0000000000..c4f7445951
--- /dev/null
+++ b/mkspecs/features/uikit/gc_binaries.prf
@@ -0,0 +1,2 @@
+# bitcode (release mode) is incompatible with splitting sections.
+!bitcode|!release: load(gc_binaries)
diff --git a/mkspecs/features/unix/separate_debug_info.prf b/mkspecs/features/unix/separate_debug_info.prf
index 0b34b17c27..9070cf33f0 100644
--- a/mkspecs/features/unix/separate_debug_info.prf
+++ b/mkspecs/features/unix/separate_debug_info.prf
@@ -72,10 +72,12 @@ have_target:!static:if(darwin|!isEmpty(QMAKE_OBJCOPY)) {
debug_info_plist_target.path += $${target.path}/$${debug_info_target_rel}.$$debug_info_suffix/Contents
INSTALLS += debug_info_plist_target
- debug_script_target.CONFIG += no_check_exist
- debug_script_target.files = $${debug_info_target}.$$debug_info_suffix/Contents/Resources/Python/$${TARGET}.py
- debug_script_target.path += $${target.path}/$${debug_info_target_rel}.$$debug_info_suffix/Contents/Resources/Python
- INSTALLS += debug_script_target
+ !isEmpty(debug_script.output) {
+ debug_script_target.CONFIG += no_check_exist
+ debug_script_target.files = $${debug_script.output}
+ debug_script_target.path += $${target.path}/$${debug_info_target_rel}.$$debug_info_suffix/Contents/Resources/Python
+ INSTALLS += debug_script_target
+ }
}
debug_info_target.CONFIG += no_check_exist
diff --git a/mkspecs/features/wasm/qt.prf b/mkspecs/features/wasm/qt.prf
new file mode 100644
index 0000000000..9b9b58d3de
--- /dev/null
+++ b/mkspecs/features/wasm/qt.prf
@@ -0,0 +1,12 @@
+
+qt_depends = $$resolve_depends(QT, "QT.")
+equals(TEMPLATE, app):contains(qt_depends, gui(-private)?) {
+ LIBS *= -L$$[QT_INSTALL_PLUGINS/get]/platforms
+
+ lib_name = wasm
+ lib_path_and_base = $$[QT_INSTALL_PLUGINS/get]/platforms/lib$${lib_name}$$qtPlatformTargetSuffix()
+ LIBS += -l$${lib_name}$$qtPlatformTargetSuffix() $$fromfile($${lib_path_and_base}.prl, QMAKE_PRL_LIBS)
+}
+
+load(qt)
+
diff --git a/mkspecs/features/wasm/wasm.prf b/mkspecs/features/wasm/wasm.prf
new file mode 100644
index 0000000000..278a6719c7
--- /dev/null
+++ b/mkspecs/features/wasm/wasm.prf
@@ -0,0 +1,81 @@
+
+# DESTDIR will be empty if not set in the app .pro file; make sure it has a value
+isEmpty(DESTDIR): DESTDIR = $$OUT_PWD
+
+# Create js and wasm files for applications
+contains(TEMPLATE, .*app) {
+ TARGET_BASE = $${TARGET}
+ TARGET_HTML = $${TARGET}.html
+ TARGET_JS = $${TARGET}.js
+
+ # Make the emscripten compiler generate a js file
+ TARGET = $$TARGET_JS
+
+ QMAKE_INCDIR += $$(HOME)/.emscripten_ports/openssl/include
+
+ CONFIG += static
+ js_file.files = $$TARGET_JS
+ js_file.path = $$target.path
+ isEmpty(js_file.path): \
+ js_file.path += ./
+ INSTALLS += js_file
+
+ # Copy hosting html and javascript to the application build directory.
+ exists($$[QT_INSTALL_PLUGINS]/platforms/wasm_shell.html) {
+ # don't pass this until it's installed somewhere
+ # otherwise makespec test fails during qt configure
+ WASM_PLUGIN_PATH = $$[QT_INSTALL_PLUGINS]/platforms
+ } else {
+ ## internal build. not installed
+ WASM_PLUGIN_PATH = $$PWD/../../../src/plugins/platforms/wasm
+ }
+
+ # Copy/Generate main .html file (e.g. myapp.html) from the webassembly_shell.html by
+ # replacing the app name placeholder with the actual app name.
+ apphtml.name = application main html file
+ apphtml.output = $$DESTDIR/$$TARGET_HTML
+ apphtml.commands = sed -e s/APPNAME/$$TARGET_BASE/g $$WASM_PLUGIN_PATH/wasm_shell.html > $$DESTDIR/$$TARGET_HTML
+ apphtml.input = $$WASM_PLUGIN_PATH/wasm_shell.html
+ apphtml.depends = $$apphtml.input
+ QMAKE_EXTRA_COMPILERS += apphtml
+
+ appjs.name = application qtloader.js
+ appjs.output = $$DESTDIR/qtloader.js
+ appjs.commands = $$QMAKE_COPY $$WASM_PLUGIN_PATH/qtloader.js $$DESTDIR
+ appjs.input = $$WASM_PLUGIN_PATH/qtloader.js
+ appjs.depends = $$appjs.input
+ QMAKE_EXTRA_COMPILERS += appjs
+
+ appsvg.name = application qtlogo.svg
+ appsvg.output = $$DESTDIR/qtlogo.svg
+ appsvg.commands = $$QMAKE_COPY $$WASM_PLUGIN_PATH/qtlogo.svg $$DESTDIR
+ appsvg.input = $$WASM_PLUGIN_PATH/qtlogo.svg
+ appsvg.depends = $$appsvg.input
+ QMAKE_EXTRA_COMPILERS += appsvg
+
+ QMAKE_EXTRA_TARGETS += apphtml appjs appsvg
+ POST_TARGETDEPS += apphtml appjs appsvg
+
+ # Add manual target to make "make -B shellfiles" work.
+ shellfiles.target = shellfiles
+ shellfiles.depends = apphtml appjs appsvg
+ QMAKE_EXTRA_TARGETS += shellfiles
+
+ # emscripten ports are linked into the main module (this app), not the Qt
+ # libs which reference them
+ qt {
+ qt_depends = $$resolve_depends(QT, "QT.")
+ contains(qt_depends, core(-private)?): QMAKE_LFLAGS += \
+ $$QMAKE_LIBS_THREAD $$QMAKE_LIBS_ZLIB
+ contains(qt_depends, gui(-private)?): QMAKE_LFLAGS += \
+ $$QMAKE_LIBS_FREETYPE $$QMAKE_LIBS_LIBPNG
+ }
+}
+
+# Creates the stand-alone version of the library from bitcode
+!static:contains(TEMPLATE, .*lib): {
+ load(resolve_target)
+ QMAKE_POST_LINK += $$QMAKE_LINK_SHLIB $$QMAKE_RESOLVED_TARGET -o $${QMAKE_RESOLVED_TARGET}.js
+
+ QMAKE_INCDIR += $$(HOME)/.emscripten_ports/openssl/include
+}
diff --git a/mkspecs/linux-icc/qmake.conf b/mkspecs/linux-icc/qmake.conf
index ec09afe381..75a601b1f1 100644
--- a/mkspecs/linux-icc/qmake.conf
+++ b/mkspecs/linux-icc/qmake.conf
@@ -1,104 +1,39 @@
#
# qmake configuration for linux-icc
#
+# Written for Intel C++ Compiler for Linux version 17.0 or higher
+#
-MAKEFILE_GENERATOR = UNIX
-
-QMAKE_COMPILER = gcc intel_icc # icc pretends to be gcc
+include(../common/icc-base-unix.conf)
-QMAKE_CFLAGS_OPTIMIZE = -O2
-QMAKE_CFLAGS_OPTIMIZE_SIZE = -Os
+# modifications to icc-base-unix.conf
-QMAKE_CC = icc
-QMAKE_LEX = flex
-QMAKE_LEXFLAGS =
-QMAKE_YACC = yacc
-QMAKE_YACCFLAGS = -d
-QMAKE_CFLAGS =
-QMAKE_CFLAGS_APP = -fPIC
-QMAKE_CFLAGS_DEPS = -M
-QMAKE_CFLAGS_WARN_ON = -w1 -Wall -Wcheck -wd1572,873,2259,2261,3373
-QMAKE_CFLAGS_WARN_OFF = -w
-QMAKE_CFLAGS_RELEASE = $$QMAKE_CFLAGS_OPTIMIZE
-QMAKE_CFLAGS_DEBUG = -O0 -g
-QMAKE_CFLAGS_SHLIB = -fPIC
-QMAKE_CFLAGS_STATIC_LIB = $$QMAKE_CFLAGS_SHLIB
QMAKE_CFLAGS_YACC =
QMAKE_CFLAGS_ISYSTEM = -isystem
QMAKE_CFLAGS_THREAD = -D_REENTRANT
-QMAKE_CFLAGS_SPLIT_SECTIONS = -ffunction-sections
-QMAKE_CFLAGS_LTCG = -ipo -fno-fat-lto-objects
-QMAKE_CFLAGS_LTCG_FATOBJECTS = -ffat-lto-objects
-QMAKE_CFLAGS_DISABLE_LTCG = -no-ipo
-QMAKE_CFLAGS_SSE2 += -xSSE2
-QMAKE_CFLAGS_SSE3 += -xSSE3
-QMAKE_CFLAGS_SSSE3 += -xSSSE3
-QMAKE_CFLAGS_SSE4_1 += -xSSE4.1
-QMAKE_CFLAGS_SSE4_2 += -xSSE4.2
-QMAKE_CFLAGS_AVX += -xAVX
-QMAKE_CFLAGS_AVX2 += -xCORE-AVX2
-QMAKE_CFLAGS_AVX512F += -xCOMMON-AVX512
-QMAKE_CFLAGS_AVX512CD += -xCOMMON-AVX512
-QMAKE_CFLAGS_AVX512ER += -xMIC-AVX512
-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_F16C += $$QMAKE_CFLAGS_AVX2
-QMAKE_CFLAGS_RDRND += -mrdrnd
-QMAKE_CFLAGS_SHANI += -msha
-
-QMAKE_CXX = icpc
-QMAKE_CXXFLAGS = $$QMAKE_CFLAGS
-QMAKE_CXXFLAGS_APP = $$QMAKE_CFLAGS_APP
-QMAKE_CXXFLAGS_DEPS = $$QMAKE_CFLAGS_DEPS
-QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON
-QMAKE_CXXFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF
-QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE
-QMAKE_CXXFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG
-QMAKE_CXXFLAGS_SHLIB = $$QMAKE_CFLAGS_SHLIB
-QMAKE_CXXFLAGS_STATIC_LIB = $$QMAKE_CFLAGS_STATIC_LIB
QMAKE_CXXFLAGS_YACC = $$QMAKE_CFLAGS_YACC
QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD
-QMAKE_CXXFLAGS_SPLIT_SECTIONS = $$QMAKE_CFLAGS_SPLIT_SECTIONS
-# Disabling exceptions disabled - workaround for QTBUG-36577
-#QMAKE_CXXFLAGS_EXCEPTIONS_OFF = -fno-exceptions
-QMAKE_CXXFLAGS_CXX11 = -std=c++11
-QMAKE_CXXFLAGS_CXX14 = -std=c++1y
-QMAKE_CXXFLAGS_CXX1Z = -std=c++1z
-QMAKE_CXXFLAGS_GNUCXX11 = -std=gnu++11
-QMAKE_CXXFLAGS_GNUCXX14 = -std=gnu++1y
-QMAKE_CXXFLAGS_GNUCXX1Z = -std=gnu++1z
-QMAKE_CXXFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG
-QMAKE_CXXFLAGS_LTCG_FATOBJECTS = $$QMAKE_CFLAGS_LTCG_FATOBJECTS
-QMAKE_CXXFLAGS_DISABLE_LTCG = $$QMAKE_CFLAGS_DISABLE_LTCG
-
-QMAKE_INCDIR =
-QMAKE_LIBDIR =
-QMAKE_INCDIR_X11 =
-QMAKE_LIBDIR_X11 =
-QMAKE_INCDIR_OPENGL =
-QMAKE_LIBDIR_OPENGL =
-QMAKE_LINK = icpc
-QMAKE_LINK_SHLIB = icpc
-QMAKE_LFLAGS =
-QMAKE_LFLAGS_RELEASE =
QMAKE_LFLAGS_APP = -pie
-QMAKE_LFLAGS_DEBUG =
QMAKE_LFLAGS_SHLIB = -shared -shared-intel
QMAKE_LFLAGS_PLUGIN = $$QMAKE_LFLAGS_SHLIB
QMAKE_LFLAGS_SONAME = -Wl,-soname,
-QMAKE_LFLAGS_THREAD =
QMAKE_LFLAGS_NOUNDEF = -Wl,-z,defs
-QMAKE_LFLAGS_RPATH = -Wl,-rpath,
QMAKE_LFLAGS_RPATHLINK = -Wl,-rpath-link,
-QMAKE_LFLAGS_CXX11 =
-QMAKE_LFLAGS_CXX14 =
-QMAKE_LFLAGS_CXX1Z =
-QMAKE_LFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG
+
+# -Bsymbolic-functions (ld) support
+QMAKE_LFLAGS_BSYMBOLIC_FUNC = -Wl,-Bsymbolic-functions
+QMAKE_LFLAGS_DYNAMIC_LIST = -Wl,--dynamic-list,
+QMAKE_LFLAGS_VERSION_SCRIPT = -Wl,--version-script,
+
+# fat LTO support for Linux ICC; not available for macOS ICC, see
+# https://software.intel.com/en-us/cpp-compiler-18.0-developer-guide-and-reference-ffat-lto-objects
+QMAKE_CFLAGS_LTCG += -fno-fat-lto-objects
+QMAKE_CXXFLAGS_LTCG += -fno-fat-lto-objects
+QMAKE_LFLAGS_LTCG += -fno-fat-lto-objects
+QMAKE_CFLAGS_LTCG_FATOBJECTS = -ffat-lto-objects
+QMAKE_CXXFLAGS_LTCG_FATOBJECTS = $$QMAKE_CFLAGS_LTCG_FATOBJECTS
QMAKE_LIBS =
QMAKE_LIBS_DYNLOAD = -ldl
@@ -111,22 +46,5 @@ QMAKE_OBJCOPY = objcopy
QMAKE_NM = nm -P
QMAKE_RANLIB =
-QMAKE_CLEAN = -r $(OBJECTS_DIR)/ti_files
-
-# pch support
-CONFIG += icc_pch_style
-QMAKE_PCH_OUTPUT_EXT = .pchi
-QMAKE_CXXFLAGS_USE_PRECOMPILE = -pch-use ${QMAKE_PCH_OUTPUT} -include ${QMAKE_PCH_INPUT}
-QMAKE_CXXFLAGS_PRECOMPILE = -c -pch-create ${QMAKE_PCH_OUTPUT} -include ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_TEMP_OBJECT} ${QMAKE_PCH_TEMP_SOURCE}
-
-# -Bsymbolic-functions (ld) support
-QMAKE_LFLAGS_BSYMBOLIC_FUNC = -Wl,-Bsymbolic-functions
-QMAKE_LFLAGS_DYNAMIC_LIST = -Wl,--dynamic-list,
-QMAKE_LFLAGS_VERSION_SCRIPT = -Wl,--version-script,
-
-# Symbol visibility control
-QMAKE_CFLAGS_HIDESYMS += -fvisibility=hidden
-QMAKE_CXXFLAGS_HIDESYMS += $$QMAKE_CFLAGS_HIDESYMS -fvisibility-inlines-hidden
-
include(../common/linux.conf)
load(qt_config)
diff --git a/mkspecs/macx-clang/Info.plist.disable_highdpi b/mkspecs/macx-clang/Info.plist.disable_highdpi
new file mode 100644
index 0000000000..a9b89888ad
--- /dev/null
+++ b/mkspecs/macx-clang/Info.plist.disable_highdpi
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>NSHighResolutionCapable</key>
+ <string>NO</string>
+</dict>
+</plist>
diff --git a/mkspecs/macx-clang/qmake.conf b/mkspecs/macx-clang/qmake.conf
index 14c885fd78..464f327ac4 100644
--- a/mkspecs/macx-clang/qmake.conf
+++ b/mkspecs/macx-clang/qmake.conf
@@ -2,10 +2,6 @@
# qmake configuration for Clang on OS X
#
-QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.11
-
-QMAKE_APPLE_DEVICE_ARCHS = x86_64
-
# Opt-in xcb QPA support with XQuartz:
#
# configure \
diff --git a/mkspecs/macx-g++/qmake.conf b/mkspecs/macx-g++/qmake.conf
index 5686610b17..d0e0026f1e 100644
--- a/mkspecs/macx-g++/qmake.conf
+++ b/mkspecs/macx-g++/qmake.conf
@@ -10,10 +10,6 @@ MAKEFILE_GENERATOR = UNIX
CONFIG += app_bundle incremental global_init_link_order lib_version_first
QMAKE_INCREMENTAL_STYLE = sublib
-QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.11
-
-QMAKE_APPLE_DEVICE_ARCHS = x86_64
-
include(../common/macx.conf)
include(../common/gcc-base-mac.conf)
include(../common/g++-macx.conf)
diff --git a/mkspecs/macx-icc/qmake.conf b/mkspecs/macx-icc/qmake.conf
index fa3944f843..4daad497af 100644
--- a/mkspecs/macx-icc/qmake.conf
+++ b/mkspecs/macx-icc/qmake.conf
@@ -1,107 +1,33 @@
#
# qmake configuration for macx-icc
#
-# Written for Intel C++ Compiler version 14.0 for OS X
+# Written for Intel C++ Compiler for macOS version 17.0 or higher
#
-MAKEFILE_GENERATOR = UNIX
+include(../common/icc-base-unix.conf)
+
+# modifications to icc-base-unix.conf
+
CONFIG += app_bundle
QMAKE_INCREMENTAL_STYLE = sublibs
-QMAKE_COMPILER_DEFINES += __APPLE__ __GNUC__
-
-QMAKE_COMPILER = gcc clang intel_icc # icc pretends to be gcc and clang
+QMAKE_COMPILER_DEFINES += __APPLE__
-QMAKE_CFLAGS_OPTIMIZE = -O2
-QMAKE_CFLAGS_OPTIMIZE_SIZE = -Os
+QMAKE_COMPILER += clang # icc pretends to be clang too
-QMAKE_CC = icc
-QMAKE_CFLAGS =
-QMAKE_CFLAGS_DEPS = -M
-QMAKE_CFLAGS_WARN_ON = -w1 -Wcheck -wd654,1572,411,873,1125,2259,2261,3280,3373
-QMAKE_CFLAGS_WARN_OFF = -w
-QMAKE_CFLAGS_RELEASE = $$QMAKE_CFLAGS_OPTIMIZE
-QMAKE_CFLAGS_DEBUG = -g -O0
-QMAKE_CFLAGS_SHLIB = -fPIC
-QMAKE_CFLAGS_STATIC_LIB = $$QMAKE_CFLAGS_SHLIB
QMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
QMAKE_CFLAGS_THREAD =
-QMAKE_CFLAGS_SPLIT_SECTIONS = -ffunction-sections
-QMAKE_CFLAGS_LTCG = -ipo
-QMAKE_CFLAGS_DISABLE_LTCG = -no-ipo
-QMAKE_CFLAGS_SSE2 += -msse2
-QMAKE_CFLAGS_SSE3 += -msse3
-QMAKE_CFLAGS_SSSE3 += -mssse3
-QMAKE_CFLAGS_SSE4_1 += -msse4.1
-QMAKE_CFLAGS_SSE4_2 += -msse4.2
-QMAKE_CFLAGS_AVX += -mavx
-QMAKE_CFLAGS_AVX2 += -march=core-avx2
-QMAKE_CFLAGS_AVX512F += -xCOMMON-AVX512
-QMAKE_CFLAGS_AVX512CD += -xCOMMON-AVX512
-QMAKE_CFLAGS_AVX512ER += -xMIC-AVX512
-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_F16C += $$QMAKE_CFLAGS_AVX2
-QMAKE_CFLAGS_RDRND += -mrdrnd
-QMAKE_CFLAGS_SHANI += -msha
-
-QMAKE_CXX = icpc
-QMAKE_CXXFLAGS = $$QMAKE_CFLAGS
-QMAKE_CXXFLAGS_DEPS = $$QMAKE_CFLAGS_DEPS
-QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON
-QMAKE_CXXFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF
-QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE
-QMAKE_CXXFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG
-QMAKE_CXXFLAGS_SHLIB = $$QMAKE_CFLAGS_SHLIB
-QMAKE_CXXFLAGS_STATIC_LIB = $$QMAKE_CFLAGS_STATIC_LIB
QMAKE_CXXFLAGS_YACC = $$QMAKE_CFLAGS_YACC
QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD
-QMAKE_CXXFLAGS_CXX11 = -std=c++11
-QMAKE_CXXFLAGS_CXX14 = -std=c++1y
-QMAKE_CXXFLAGS_CXX1Z = -std=c++1z
-QMAKE_CXXFLAGS_GNUCXX11 = -std=gnu++11
-QMAKE_CXXFLAGS_GNUCXX14 = -std=gnu++1y
-QMAKE_CXXFLAGS_GNUCXX1Z = -std=gnu++1z
-QMAKE_CXXFLAGS_SPLIT_SECTIONS = $$QMAKE_CFLAGS_SPLIT_SECTIONS
-QMAKE_CXXFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG
-QMAKE_CXXFLAGS_DISABLE_LTCG = $$QMAKE_CFLAGS_DISABLE_LTCG
-QMAKE_LINK = icpc
-QMAKE_LINK_SHLIB = icpc
-QMAKE_LFLAGS =
-QMAKE_LFLAGS_RELEASE =
-QMAKE_LFLAGS_DEBUG =
QMAKE_LFLAGS_SHLIB = -single_module -dynamiclib
QMAKE_LFLAGS_INCREMENTAL = -undefined suppress -flat_namespace
QMAKE_LFLAGS_PLUGIN = $$QMAKE_LFLAGS_SHLIB
QMAKE_LFLAGS_SONAME = -install_name$${LITERAL_WHITESPACE}
QMAKE_LFLAGS_HEADERPAD = -headerpad_max_install_names
-QMAKE_LFLAGS_THREAD =
-QMAKE_LFLAGS_RPATH = -Wl,-rpath,
-QMAKE_LFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG
QMAKE_LFLAGS_VERSION = -current_version$${LITERAL_WHITESPACE}
QMAKE_LFLAGS_COMPAT_VERSION = -compatibility_version$${LITERAL_WHITESPACE}
-QMAKE_CLEAN = -r $(OBJECTS_DIR)/ti_files
-
-# pch support
-CONFIG += icc_pch_style
-QMAKE_PCH_OUTPUT_EXT = .pchi
-QMAKE_CXXFLAGS_USE_PRECOMPILE = -pch-use ${QMAKE_PCH_OUTPUT} -include ${QMAKE_PCH_INPUT}
-QMAKE_CXXFLAGS_PRECOMPILE = -c -pch-create ${QMAKE_PCH_OUTPUT} -include ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_TEMP_OBJECT} ${QMAKE_PCH_TEMP_SOURCE}
-
-# Symbol visibility control
-QMAKE_CFLAGS_HIDESYMS += -fvisibility=hidden
-QMAKE_CXXFLAGS_HIDESYMS += $$QMAKE_CFLAGS_HIDESYMS -fvisibility-inlines-hidden
-
-QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.11
-
-QMAKE_APPLE_DEVICE_ARCHS = x86_64
-
include(../common/macx.conf)
-
load(qt_config)
diff --git a/mkspecs/macx-ios-clang/qmake.conf b/mkspecs/macx-ios-clang/qmake.conf
index d58b9fcbe1..88e96ef32e 100644
--- a/mkspecs/macx-ios-clang/qmake.conf
+++ b/mkspecs/macx-ios-clang/qmake.conf
@@ -2,7 +2,7 @@
# qmake configuration for macx-ios-clang
#
-QMAKE_IOS_DEPLOYMENT_TARGET = 10.0
+QMAKE_IOS_DEPLOYMENT_TARGET = 11.0
# Universal target (iPhone and iPad)
QMAKE_APPLE_TARGETED_DEVICE_FAMILY = 1,2
diff --git a/mkspecs/macx-tvos-clang/qmake.conf b/mkspecs/macx-tvos-clang/qmake.conf
index ab1a95fe88..77f6a02f7b 100644
--- a/mkspecs/macx-tvos-clang/qmake.conf
+++ b/mkspecs/macx-tvos-clang/qmake.conf
@@ -2,7 +2,7 @@
# qmake configuration for macx-tvos-clang
#
-QMAKE_TVOS_DEPLOYMENT_TARGET = 10.0
+QMAKE_TVOS_DEPLOYMENT_TARGET = 11.0
QMAKE_APPLE_TARGETED_DEVICE_FAMILY = 3
diff --git a/mkspecs/macx-watchos-clang/qmake.conf b/mkspecs/macx-watchos-clang/qmake.conf
index bd28722d44..8194261275 100644
--- a/mkspecs/macx-watchos-clang/qmake.conf
+++ b/mkspecs/macx-watchos-clang/qmake.conf
@@ -2,7 +2,7 @@
# qmake configuration for macx-watchos-clang
#
-QMAKE_WATCHOS_DEPLOYMENT_TARGET = 3.0
+QMAKE_WATCHOS_DEPLOYMENT_TARGET = 4.0
QMAKE_APPLE_TARGETED_DEVICE_FAMILY = 4
diff --git a/mkspecs/macx-xcode/default.xcscheme b/mkspecs/macx-xcode/default.xcscheme
index bda2b8c1c0..bd2cb0e565 100644
--- a/mkspecs/macx-xcode/default.xcscheme
+++ b/mkspecs/macx-xcode/default.xcscheme
@@ -17,7 +17,7 @@
BlueprintIdentifier = "@TARGET_PBX_KEY@"
BuildableName = "@QMAKE_ORIG_TARGET@"
BlueprintName = "@QMAKE_ORIG_TARGET@"
- ReferencedContainer = "container:@QMAKE_ORIG_TARGET@.xcodeproj">
+ ReferencedContainer = "container:@QMAKE_RELATIVE_PBX_DIR@">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
@@ -35,7 +35,7 @@
BlueprintIdentifier = "@TEST_BUNDLE_PBX_KEY@"
BuildableName = "Qt Test"
BlueprintName = "Qt Test"
- ReferencedContainer = "container:@QMAKE_ORIG_TARGET@.xcodeproj">
+ ReferencedContainer = "container:@QMAKE_RELATIVE_PBX_DIR@">
</BuildableReference>
</TestableReference>
</Testables>
@@ -45,7 +45,7 @@
BlueprintIdentifier = "@TARGET_PBX_KEY@"
BuildableName = "@QMAKE_ORIG_TARGET@"
BlueprintName = "@QMAKE_ORIG_TARGET@"
- ReferencedContainer = "container:@QMAKE_ORIG_TARGET@.xcodeproj">
+ ReferencedContainer = "container:@QMAKE_RELATIVE_PBX_DIR@">
</BuildableReference>
</MacroExpansion>
<CommandLineArguments>
@@ -71,7 +71,7 @@
BlueprintIdentifier = "@TARGET_PBX_KEY@"
BuildableName = "@QMAKE_ORIG_TARGET@"
BlueprintName = "@QMAKE_ORIG_TARGET@"
- ReferencedContainer = "container:@QMAKE_ORIG_TARGET@.xcodeproj">
+ ReferencedContainer = "container:@QMAKE_RELATIVE_PBX_DIR@">
</BuildableReference>
</BuildableProductRunnable>
<EnvironmentVariables>
@@ -96,7 +96,7 @@
BlueprintIdentifier = "@TARGET_PBX_KEY@"
BuildableName = "@QMAKE_ORIG_TARGET@"
BlueprintName = "@QMAKE_ORIG_TARGET@"
- ReferencedContainer = "container:@QMAKE_ORIG_TARGET@.xcodeproj">
+ ReferencedContainer = "container:@QMAKE_RELATIVE_PBX_DIR@">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
diff --git a/mkspecs/wasm-emscripten/qmake.conf b/mkspecs/wasm-emscripten/qmake.conf
new file mode 100644
index 0000000000..c3b67310c8
--- /dev/null
+++ b/mkspecs/wasm-emscripten/qmake.conf
@@ -0,0 +1,90 @@
+# qmake configuration for building with emscripten
+MAKEFILE_GENERATOR = UNIX
+QMAKE_PLATFORM = wasm unix
+
+include(../common/gcc-base.conf)
+include(../common/clang.conf)
+
+EMTERP_FLAGS = \
+ -s EMTERPRETIFY=1 \
+ -s EMTERPRETIFY_ASYNC=1 \
+ -s \"EMTERPRETIFY_FILE=\'data.binary\'\" \
+ -s ASSERTIONS=1 \
+ --profiling-funcs
+
+EMCC_COMMON_CFLAGS = \
+ -s USE_LIBPNG=1 \
+ -s USE_FREETYPE=1 \
+ -s USE_ZLIB=1
+
+EMCC_COMMON_LFLAGS = \
+ -s WASM=1 \
+ -s FULL_ES2=1 \
+ -s ALLOW_MEMORY_GROWTH=1 \
+ -s USE_WEBGL2=1 \
+ -s NO_EXIT_RUNTIME=0 \
+ -s ERROR_ON_UNDEFINED_SYMBOLS=1 \
+ --bind \
+ -s \"BINARYEN_METHOD=\'native-wasm\'\" \
+ -s \"BINARYEN_TRAP_MODE=\'clamp\'\"
+
+EMCC_COMMON_LFLAGS_DEBUG = \
+ $$EMCC_COMMON_LFLAGS \
+ -s ASSERTIONS=2 \
+ -s DEMANGLE_SUPPORT=1 \
+ # -s LIBRARY_DEBUG=1 \ #print out library calls, verbose
+ # -s SYSCALL_DEBUG=1 \ #print out sys calls, verbose
+ # -s FS_LOG=1 \ #print out filesystem ops, verbose
+ # -s SOCKET_DEBUG \ #print out socket,network data transfer
+ -s GL_DEBUG=1
+
+# the -s arguments can also be used with release builds
+# but here in debug for clarity
+
+QMAKE_COMPILER += emscripten
+
+QMAKE_CC = emcc
+QMAKE_CXX = em++
+
+QMAKE_CFLAGS += $$EMCC_COMMON_CFLAGS
+QMAKE_CXXFLAGS += $$EMCC_COMMON_CFLAGS
+
+# Practical debugging setup:
+# "-g4" preserves function names for stack traces
+# "-Os" produces reasonably sized binaries
+QMAKE_CFLAGS_DEBUG -= -g
+QMAKE_CXXFLAGS_DEBUG -= -g
+QMAKE_CFLAGS_DEBUG += -Os -g4
+QMAKE_CXXFLAGS_DEBUG += -Os -g4
+QMAKE_LFLAGS_DEBUG += -Os -g4
+
+QMAKE_CXXFLAGS_RELEASE -= -O2
+QMAKE_CXXFLAGS_RELEASE += -O3
+QMAKE_CFLAGS_RELEASE -= -O2
+QMAKE_CFLAGS_RELEASE += -O3
+QMAKE_LFLAGS_RELEASE += -O3
+MAKE_CFLAGS_OPTIMIZE += -O3
+MAKE_CFLAGS_OPTIMIZE_FULL += -Oz
+
+QMAKE_LINK = $$QMAKE_CXX
+QMAKE_LINK_SHLIB = $$QMAKE_CXX
+QMAKE_LINK_C = $$QMAKE_CC
+QMAKE_LINK_C_SHLIB = $$QMAKE_CC
+
+QMAKE_LIBS_THREAD = $$QMAKE_CFLAGS_THREAD
+
+QMAKE_LFLAGS += $$EMCC_COMMON_LFLAGS
+QMAKE_LFLAGS_DEBUG += $$EMCC_COMMON_LFLAGS_DEBUG
+
+QMAKE_PREFIX_SHLIB = lib
+QMAKE_EXTENSION_SHLIB = so # llvm bitcode, linked to js in post_link
+QMAKE_PREFIX_STATICLIB = lib
+QMAKE_EXTENSION_STATICLIB = a # llvm bitcode
+
+QMAKE_AR = emar cqs
+QMAKE_DISTCLEAN += *.html *.js *.wasm
+
+QT_QPA_DEFAULT_PLATFORM = wasm
+
+QTPLUGIN.platforms = wasm
+load(qt_config)
diff --git a/mkspecs/wasm-emscripten/qplatformdefs.h b/mkspecs/wasm-emscripten/qplatformdefs.h
new file mode 100644
index 0000000000..c1a0d7b1a8
--- /dev/null
+++ b/mkspecs/wasm-emscripten/qplatformdefs.h
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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$
+**
+****************************************************************************/
+
+#ifndef QPLATFORMDEFS_H
+#define QPLATFORMDEFS_H
+
+// Get Qt defines/settings
+
+#include "qglobal.h"
+
+// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs
+
+// 1) need to reset default environment if _BSD_SOURCE is defined
+// 2) need to specify POSIX thread interfaces explicitly in glibc 2.0
+// 3) it seems older glibc need this to include the X/Open stuff
+
+#include <unistd.h>
+
+// We are hot - unistd.h should have turned on the specific APIs we requested
+
+#include <features.h>
+#include <pthread.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <pwd.h>
+#include <signal.h>
+#include <dlfcn.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/ipc.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#ifndef QT_NO_IPV6IFNAME
+#include <net/if.h>
+#endif
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+
+#ifdef QT_LARGEFILE_SUPPORT
+#define QT_STATBUF struct stat64
+#define QT_STATBUF4TSTAT struct stat64
+#define QT_STAT ::stat64
+#define QT_FSTAT ::fstat64
+#define QT_LSTAT ::lstat64
+#define QT_OPEN ::open64
+#define QT_TRUNCATE ::truncate64
+#define QT_FTRUNCATE ::ftruncate64
+#define QT_LSEEK ::lseek64
+#else
+#define QT_STATBUF struct stat
+#define QT_STATBUF4TSTAT struct stat
+#define QT_STAT ::stat
+#define QT_FSTAT ::fstat
+#define QT_LSTAT ::lstat
+#define QT_OPEN ::open
+#define QT_TRUNCATE ::truncate
+#define QT_FTRUNCATE ::ftruncate
+#define QT_LSEEK ::lseek
+#endif
+
+#ifdef QT_LARGEFILE_SUPPORT
+#define QT_FOPEN ::fopen64
+#define QT_FSEEK ::fseeko64
+#define QT_FTELL ::ftello64
+#define QT_FGETPOS ::fgetpos64
+#define QT_FSETPOS ::fsetpos64
+#define QT_MMAP ::mmap64
+#define QT_FPOS_T fpos64_t
+#define QT_OFF_T off64_t
+#else
+#define QT_FOPEN ::fopen
+#define QT_FSEEK ::fseek
+#define QT_FTELL ::ftell
+#define QT_FGETPOS ::fgetpos
+#define QT_FSETPOS ::fsetpos
+#define QT_MMAP ::mmap
+#define QT_FPOS_T fpos_t
+#define QT_OFF_T long
+#endif
+
+#define QT_STAT_REG S_IFREG
+#define QT_STAT_DIR S_IFDIR
+#define QT_STAT_MASK S_IFMT
+#define QT_STAT_LNK S_IFLNK
+#define QT_SOCKET_CONNECT ::connect
+#define QT_SOCKET_BIND ::bind
+#define QT_FILENO fileno
+#define QT_CLOSE ::close
+#define QT_READ ::read
+#define QT_WRITE ::write
+#define QT_ACCESS ::access
+#define QT_GETCWD ::getcwd
+#define QT_CHDIR ::chdir
+#define QT_MKDIR ::mkdir
+#define QT_RMDIR ::rmdir
+#define QT_OPEN_LARGEFILE O_LARGEFILE
+#define QT_OPEN_RDONLY O_RDONLY
+#define QT_OPEN_WRONLY O_WRONLY
+#define QT_OPEN_RDWR O_RDWR
+#define QT_OPEN_CREAT O_CREAT
+#define QT_OPEN_TRUNC O_TRUNC
+#define QT_OPEN_APPEND O_APPEND
+#define QT_OPEN_EXCL O_EXCL
+
+// Directory iteration
+#define QT_DIR DIR
+
+#define QT_OPENDIR ::opendir
+#define QT_CLOSEDIR ::closedir
+
+#if defined(QT_LARGEFILE_SUPPORT) \
+ && defined(QT_USE_XOPEN_LFS_EXTENSIONS) \
+ && !defined(QT_NO_READDIR64)
+#define QT_DIRENT struct dirent64
+#define QT_READDIR ::readdir64
+#define QT_READDIR_R ::readdir64_r
+#else
+#define QT_DIRENT struct dirent
+#define QT_READDIR ::readdir
+#define QT_READDIR_R ::readdir_r
+#endif
+
+#define QT_SOCKET_CONNECT ::connect
+#define QT_SOCKET_BIND ::bind
+
+
+#define QT_SIGNAL_RETTYPE void
+#define QT_SIGNAL_ARGS int
+#define QT_SIGNAL_IGNORE SIG_IGN
+
+#define QT_SOCKLEN_T socklen_t
+
+#if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)
+#define QT_SNPRINTF ::snprintf
+#define QT_VSNPRINTF ::vsnprintf
+#endif
+
+#endif // QPLATFORMDEFS_H
diff --git a/mkspecs/win32-icc/qmake.conf b/mkspecs/win32-icc/qmake.conf
index 2447c712b1..3cb0d58824 100644
--- a/mkspecs/win32-icc/qmake.conf
+++ b/mkspecs/win32-icc/qmake.conf
@@ -12,7 +12,6 @@ include(../common/msvc-desktop.conf)
# modifications to msvc-desktop.conf
QMAKE_COMPILER += intel_icl
-DEFINES += _ENABLE_EXTENDED_ALIGNED_STORAGE
QMAKE_CFLAGS_OPTIMIZE_FULL = -O3
diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix
index 426387f0c2..29461be5c5 100644
--- a/qmake/Makefile.unix
+++ b/qmake/Makefile.unix
@@ -18,7 +18,7 @@ OBJS = \
#qt code (please keep in order matching DEPEND_SRC)
QOBJS = \
qtextcodec.o qutfcodec.o \
- qglobal.o qlogging.o qmalloc.o qnumeric.o qoperatingsystemversion.o qrandom.o \
+ qendian.o qglobal.o qlogging.o qmalloc.o qnumeric.o qoperatingsystemversion.o qrandom.o \
qabstractfileengine.o qbuffer.o qdatastream.o qdebug.o \
qdir.o qdiriterator.o \
qfile.o qfiledevice.o qfileinfo.o qfilesystemengine.o \
@@ -68,6 +68,7 @@ DEPEND_SRC = \
$(QMKGENSRC)/xmloutput.cpp \
$(SOURCE_PATH)/src/corelib/codecs/qtextcodec.cpp \
$(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp \
+ $(SOURCE_PATH)/src/corelib/global/qendian.cpp \
$(SOURCE_PATH)/src/corelib/global/qglobal.cpp \
$(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp \
$(SOURCE_PATH)/src/corelib/global/qlogging.cpp \
@@ -295,6 +296,9 @@ qdebug.o: $(SOURCE_PATH)/src/corelib/io/qdebug.cpp
qmalloc.o: $(SOURCE_PATH)/src/corelib/global/qmalloc.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $<
+qendian.o: $(SOURCE_PATH)/src/corelib/global/qendian.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
+
qglobal.o: $(SOURCE_PATH)/src/corelib/global/qglobal.cpp
$(CXX) -c -o $@ $(CXXFLAGS) $<
diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32
index 5292332187..a1699bd6f8 100644
--- a/qmake/Makefile.win32
+++ b/qmake/Makefile.win32
@@ -83,6 +83,7 @@ QTOBJS= \
qfsfileengine_win.obj \
qsystemlibrary.obj \
qfileinfo.obj \
+ qendian.obj \
qglobal.obj \
qhash.obj \
qiodevice.obj \
diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc
index b07ded3888..1a779a94b4 100644
--- a/qmake/doc/src/qmake-manual.qdoc
+++ b/qmake/doc/src/qmake-manual.qdoc
@@ -907,9 +907,9 @@
Platform-specific variables follow the naming pattern of the
variables which they extend or modify, but include the name of the relevant
- platform in their name. For example, \c QMAKE_LIBS can be used to specify a list
- of libraries that a project needs to link against, and \c QMAKE_LIBS_X11 can be
- used to extend or override this list.
+ platform in their name. For example, a makespec may use \c QMAKE_LIBS
+ to specify a list of libraries that each project needs to link against,
+ and \c QMAKE_LIBS_X11 would be used to extend this list.
\target CONFIG
\section1 CONFIG
@@ -956,14 +956,36 @@
default is used.
\row \li thread \li Thread support is enabled. This is enabled when CONFIG
includes \c qt, which is the default.
+ \row \li c99 \li C99 support is enabled. This option has no effect if
+ the compiler does not support C99, or can't select the C standard.
+ By default, the compiler default is used.
+ \row \li c11 \li C11 support is enabled. This option has no effect if
+ the compiler does not support C11, or can't select the C standard.
+ By default, the compiler default is used.
+ \row \li strict_c \li Disables support for C compiler extensions.
+ By default, they are enabled.
\row \li c++11 \li C++11 support is enabled. This option has no effect if
- the compiler does not support C++11.
- By default, support is disabled.
+ the compiler does not support C++11, or can't select the C++ standard.
+ By default, support is enabled.
\row \li c++14 \li C++14 support is enabled. This option has no effect if
- the compiler does not support C++14.
+ the compiler does not support C++14, or can't select the C++ standard.
+ By default, the compiler default is used.
+ \row \li c++1z \li C++17 support is enabled. This option has no effect if
+ the compiler does not support C++17, or can't select the C++ standard.
By default, support is disabled.
+ \row \li c++17 \li Same as c++1z.
+ \row \li strict_c++ \li Disables support for C++ compiler extensions.
+ By default, they are enabled.
\row \li depend_includepath \li Appending the value of INCLUDEPATH to
DEPENDPATH is enabled. Set by default.
+ \row \li lrelease \li Run \c lrelease for all files listed in
+ \l TRANSLATIONS and \l EXTRA_TRANSLATIONS. If \c embed_translations
+ is not set, install the generated .qm files into
+ QM_FILES_INSTALL_PATH. Use QMAKE_LRELEASE_FLAGS to add options to
+ the lrelease call. Not set by default.
+ \row \li embed_translations \li Embed the generated translations from
+ \c lrelease in the executable, under \l{QM_FILES_RESOURCE_PREFIX}.
+ Requires \c lrelease to be set, too. Not set by default.
\endtable
When you use the \c debug_and_release option (which is the default under
@@ -1149,6 +1171,24 @@
Specifies where to copy the \l{#TARGET}{target} dll.
+ \target EXTRA_TRANSLATIONS
+ \section1 EXTRA_TRANSLATIONS
+
+ Specifies a list of translation (.ts) files that contain
+ translations of the user interface text into non-native languages.
+
+ In contrast to \l TRANSLATIONS, translation files in \c EXTRA_TRANSLATIONS
+ will be processed only by \l{Using lrelease}{lrelease}, not
+ \l{Using lupdate}{lupdate}.
+
+ You can use \l{CONFIG}{CONFIG += lrelease} to automatically compile the
+ files during the build, and
+ \l{CONFIG}{CONFIG += lrelease embed_translations} to make them available in
+ \l{The Qt Resource System}.
+
+ See the \l{Qt Linguist Manual} for more information about
+ internationalization (i18n) and localization (l10n) with Qt.
+
\target FORMS
\section1 FORMS
@@ -1281,6 +1321,19 @@
\snippet code/doc_src_qmake-manual.pro 39
+ \target LIBS_PRIVATE
+ \section1 LIBS_PRIVATE
+
+ Specifies a list of libraries to be linked privately into the project.
+ The behavior of this variable is identical to \l LIBS, except that
+ shared library projects built for Unix do not expose these dependencies
+ in their link interface.
+
+ The effect of this is that if project C depends on library B which
+ depends on library A privately, but C also wants to use symbols from A
+ directly, it needs to link to A explicitly. Put differently, libraries
+ linked privately are not exposed transitively at build time.
+
\target LITERAL_HASH
\section1 LITERAL_HASH
@@ -1419,6 +1472,21 @@
\note Do not attempt to overwrite the value of this variable.
+ \target QM_FILES_RESOURCE_PREFIX
+ \section1 QM_FILES_RESOURCE_PREFIX
+
+ Specifies the directory in the resource system where \c .qm files will
+ be made available by \l{CONFIG}{CONFIG += embed_translations}.
+
+ The default is \c{:/i18n/}.
+
+ \target QM_FILES_INSTALL_PATH
+ \section1 QM_FILES_INSTALL_PATH
+
+ Specifies the target directory \c .qm files generated by
+ \l{CONFIG}{CONFIG += lrelease} will be installed to. Does not have any
+ effect if \l{CONFIG}{CONFIG += embed_translations} is set.
+
\target QMAKE_systemvariable
\section1 QMAKE
@@ -1994,7 +2062,19 @@
\section1 QMAKE_LIBDIR
- Specifies a list of system library paths.
+ Specifies a list of library search paths for all projects.
+ The value of this variable is typically handled by qmake
+ or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified.
+
+ To specify additional search paths in project files,
+ use \l LIBS like that, instead:
+ \badcode
+ LIBS += -L/path/to/libraries
+ \endcode
+
+ \section1 QMAKE_LIBDIR_POST
+
+ Specifies a list of system library search paths for all projects.
The value of this variable is typically handled by qmake
or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified.
@@ -2044,10 +2124,22 @@
\section1 QMAKE_LIBS
- Specifies all project libraries. The value of this variable
- is typically handled by qmake or
+ Specifies additional libraries each project needs to link against.
+ The value of this variable is typically handled by qmake or
\l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified.
+ To specify libraries in a project file, use \l LIBS instead.
+
+ \section1 QMAKE_LIBS_PRIVATE
+
+ Specifies additional private libraries each project needs to
+ link against.
+ The value of this variable is typically handled by qmake or
+ \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified.
+
+ To specify private libraries in a library project file,
+ use \l LIBS_PRIVATE instead.
+
\section1 QMAKE_LIBS_EGL
Specifies all EGL libraries when building Qt with OpenGL/ES
@@ -2134,6 +2226,12 @@
value of this variable is typically handled by qmake or
\l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified.
+ \target QMAKE_LRELEASE_FLAGS
+ \section1 QMAKE_LRELEASE_FLAGS
+
+ List of additional options passed to \l{Using lrelease}{lrelease} when
+ enabled through \l{CONFIG}{CONFIG += lrelease}.
+
\section1 QMAKE_OBJECTIVE_CFLAGS
Specifies the Objective C/C++ compiler flags for building
@@ -2342,9 +2440,7 @@
This variable is used to customize the list of options passed to the
\l{uic}{User Interface Compiler} in each of the build rules where it is
- used. For example, \c{-no-stringliteral} can be passed to use QLatin1String
- instead of QStringLiteral in generated code (which is the default for
- dynamic libraries).
+ used.
\section1 QMAKE_WATCHOS_DEPLOYMENT_TARGET
@@ -2613,11 +2709,21 @@
determine how the project is built, it is necessary to declare TEMPLATE on
the command line rather than use the \c -t option.
+ \target TRANSLATIONS
\section1 TRANSLATIONS
Specifies a list of translation (.ts) files that contain
translations of the user interface text into non-native languages.
+ Translation files in \c TRANSLATIONS will be processed by both
+ \l{Using lrelease}{lrelease} and \l{Using lupdate} tools. Use
+ \l EXTRA_TRANSLATIONS if you want only \c lrelease to process a file.
+
+ You can use \l{CONFIG}{CONFIG += lrelease} to automatically compile the
+ files during the build, and
+ \l{CONFIG}{CONFIG += lrelease embed_translations} to make them available in
+ \l{The Qt Resource System}.
+
See the \l{Qt Linguist Manual} for more information about
internationalization (i18n) and localization (l10n) with Qt.
@@ -2932,6 +3038,7 @@
\snippet code/doc_src_qmake-manual.pro 59
+ \target qmake-cat
\section2 cat(filename[, mode])
Returns the contents of \c filename. You can specify the following options
@@ -3298,6 +3405,10 @@
\snippet code/doc_src_qmake-manual.pro 72
+ Like \l {qmake-cat}{$$cat()}, the \a mode argument takes \c blob, \c lines,
+ \c true, and \false as value. However, the legacy word splitting rules
+ (i.e. empty or \c true, and \c false) differ subtly.
+
If you pass \c stsvar, the command's exit status will be stored in that
variable. If the command crashes, the status will be -1, otherwise a
non-negative exit code of the command's choosing. Usually, comparing
@@ -4511,6 +4622,11 @@
\li The dependencies for the output only get generated from the depends
member and from nowhere else.
\row
+ \li dep_lines
+ \li The output from the .depend_command is interpreted to be one file
+ per line. The default is to split on whitespace and is maintained
+ only for backwards compatibility reasons.
+ \row
\li no_link
\li Indicates that the output should not be added to the list of objects
to be linked in.
diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp
index a0aea70dc5..5407ed6c69 100644
--- a/qmake/generators/mac/pbuilder_pbx.cpp
+++ b/qmake/generators/mac/pbuilder_pbx.cpp
@@ -542,6 +542,10 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
QTextStream mkt(&mkf);
writeHeader(mkt);
mkt << "QMAKE = " << var("QMAKE_QMAKE") << endl;
+ project->values("QMAKE_MAKE_QMAKE_EXTRA_COMMANDS")
+ << "@echo 'warning: Xcode project has been regenerated, custom settings have been lost. " \
+ "Use CONFIG+=no_autoqmake to prevent this behavior in the future, " \
+ "at the cost of requiring manual project change tracking.'";
writeMakeQmake(mkt);
mkt.flush();
mkf.close();
@@ -825,7 +829,8 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
if(!project->isActiveConfig("staticlib")) { //DUMP LIBRARIES
ProStringList &libdirs = project->values("QMAKE_PBX_LIBPATHS"),
&frameworkdirs = project->values("QMAKE_FRAMEWORKPATH");
- static const char * const libs[] = { "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", 0 };
+ static const char * const libs[] = { "LIBS", "LIBS_PRIVATE",
+ "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", nullptr };
for (int i = 0; libs[i]; i++) {
tmp = project->values(libs[i]);
for(int x = 0; x < tmp.count();) {
@@ -848,7 +853,8 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
encode the version number in the Project file which might be a bad
things in days to come? --Sam
*/
- QString lib_file = QMakeMetaInfo::findLib(Option::normalizePath((*lit) + Option::dir_sep + lib));
+ QString lib_file = QMakeMetaInfo::checkLib(Option::normalizePath(
+ (*lit) + Option::dir_sep + lib + Option::prl_ext));
if (!lib_file.isEmpty()) {
QMakeMetaInfo libinfo(project);
if(libinfo.readLib(lib_file)) {
@@ -1417,7 +1423,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
testHost.append("Contents/MacOS/");
testHost.append(targetName);
- static const char * const configs[] = { "Debug", "Release", 0 };
+ static const char * const configs[] = { "Debug", "Release", nullptr };
for (int i = 0; configs[i]; i++) {
QString testBundleBuildConfig = keyFor(pbx_dir + "QMAKE_PBX_TEST_BUNDLE_BUILDCONFIG_" + configs[i]);
t << "\t\t" << testBundleBuildConfig << " = {\n"
@@ -1690,6 +1696,8 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
t << "\t\t\t\t" << writeSettings("OTHER_LDFLAGS",
fixListForOutput("SUBLIBS")
+ fixListForOutput("QMAKE_LFLAGS")
+ + fixListForOutput(fixLibFlags("LIBS"))
+ + fixListForOutput(fixLibFlags("LIBS_PRIVATE"))
+ fixListForOutput(fixLibFlags("QMAKE_LIBS"))
+ fixListForOutput(fixLibFlags("QMAKE_LIBS_PRIVATE")),
SettingsAsList, 6) << ";\n";
@@ -1782,6 +1790,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
schemeData.replace(QLatin1String("@QMAKE_ORIG_TARGET@"), target);
schemeData.replace(QLatin1String("@TARGET_PBX_KEY@"), keyFor(pbx_dir + "QMAKE_PBX_TARGET"));
schemeData.replace(QLatin1String("@TEST_BUNDLE_PBX_KEY@"), keyFor("QMAKE_TEST_BUNDLE_REFERENCE"));
+ schemeData.replace(QLatin1String("@QMAKE_RELATIVE_PBX_DIR@"), fileFixify(pbx_dir));
QTextStream outputSchemeStream(&outputSchemeFile);
outputSchemeStream << schemeData;
@@ -1876,33 +1885,28 @@ ProjectBuilderMakefileGenerator::keyFor(const QString &block)
bool
ProjectBuilderMakefileGenerator::openOutput(QFile &file, const QString &build) const
{
- if(QDir::isRelativePath(file.fileName()))
- file.setFileName(Option::output_dir + "/" + file.fileName()); //pwd when qmake was run
+ Q_ASSERT_X(QDir::isRelativePath(file.fileName()), "ProjectBuilderMakefileGenerator",
+ "runQMake() should have normalized the filename and made it relative");
+
QFileInfo fi(fileInfo(file.fileName()));
- if(fi.suffix() != "pbxproj" || file.fileName().isEmpty()) {
+ if (fi.suffix() != "pbxproj") {
QString output = file.fileName();
- if(fi.isDir())
- output += QDir::separator();
- if(!output.endsWith(projectSuffix())) {
- if(file.fileName().isEmpty() || fi.isDir()) {
- if(project->first("TEMPLATE") == "subdirs" || project->isEmpty("QMAKE_ORIG_TARGET"))
+ if (!output.endsWith(projectSuffix())) {
+ if (fi.fileName().isEmpty()) {
+ if (project->first("TEMPLATE") == "subdirs" || project->isEmpty("QMAKE_ORIG_TARGET"))
output += fileInfo(project->projectFile()).baseName();
else
output += project->first("QMAKE_ORIG_TARGET").toQString();
}
output += projectSuffix() + QDir::separator();
- } else if(output[(int)output.length() - 1] != QDir::separator()) {
+ } else {
output += QDir::separator();
}
output += QString("project.pbxproj");
file.setFileName(output);
- bool ret = UnixMakefileGenerator::openOutput(file, build);
- ((ProjectBuilderMakefileGenerator*)this)->pbx_dir = Option::output_dir.section(Option::dir_sep, 0, -1);
- Option::output_dir = pbx_dir.section(Option::dir_sep, 0, -2);
- return ret;
}
- ((ProjectBuilderMakefileGenerator*)this)->pbx_dir = Option::output_dir;
+ pbx_dir = Option::output_dir + Option::dir_sep + file.fileName().section(Option::dir_sep, 0, 0);
return UnixMakefileGenerator::openOutput(file, build);
}
diff --git a/qmake/generators/mac/pbuilder_pbx.h b/qmake/generators/mac/pbuilder_pbx.h
index 1d5cbc538d..f15c814cb4 100644
--- a/qmake/generators/mac/pbuilder_pbx.h
+++ b/qmake/generators/mac/pbuilder_pbx.h
@@ -36,11 +36,11 @@ QT_BEGIN_NAMESPACE
class ProjectBuilderMakefileGenerator : public UnixMakefileGenerator
{
bool writingUnixMakefileGenerator;
- QString pbx_dir;
+ mutable QString pbx_dir;
int pbuilderVersion() const;
bool writeSubDirs(QTextStream &);
bool writeMakeParts(QTextStream &);
- bool writeMakefile(QTextStream &);
+ bool writeMakefile(QTextStream &) override;
QString pbxbuild();
QHash<QString, QString> keys;
@@ -64,11 +64,11 @@ public:
ProjectBuilderMakefileGenerator();
~ProjectBuilderMakefileGenerator();
- virtual bool supportsMetaBuild() { return false; }
- virtual bool openOutput(QFile &, const QString &) const;
+ bool supportsMetaBuild() override { return false; }
+ bool openOutput(QFile &, const QString &) const override;
protected:
- bool doPrecompiledHeaders() const { return false; }
- virtual bool doDepends() const { return writingUnixMakefileGenerator && UnixMakefileGenerator::doDepends(); }
+ bool doPrecompiledHeaders() const override { return false; }
+ bool doDepends() const override { return writingUnixMakefileGenerator && UnixMakefileGenerator::doDepends(); }
};
inline ProjectBuilderMakefileGenerator::~ProjectBuilderMakefileGenerator()
diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp
index 73e09a1025..e41e391cad 100644
--- a/qmake/generators/makefile.cpp
+++ b/qmake/generators/makefile.cpp
@@ -96,7 +96,7 @@ bool MakefileGenerator::mkdir(const QString &in_path) const
// ** base makefile generator
MakefileGenerator::MakefileGenerator() :
- no_io(false), project(0)
+ no_io(false), project(nullptr)
{
}
@@ -164,7 +164,7 @@ MakefileGenerator::initOutPaths()
v["PRECOMPILED_DIR"] = v["OBJECTS_DIR"];
static const char * const dirs[] = { "OBJECTS_DIR", "DESTDIR",
"SUBLIBS_DIR", "DLLDESTDIR",
- "PRECOMPILED_DIR", 0 };
+ "PRECOMPILED_DIR", nullptr };
for (int x = 0; dirs[x]; x++) {
const ProKey dkey(dirs[x]);
if (v[dkey].isEmpty())
@@ -424,7 +424,7 @@ MakefileGenerator::init()
}
incs.append(project->specDir());
- const char * const cacheKeys[] = { "_QMAKE_STASH_", "_QMAKE_SUPER_CACHE_", 0 };
+ const char * const cacheKeys[] = { "_QMAKE_STASH_", "_QMAKE_SUPER_CACHE_", nullptr };
for (int i = 0; cacheKeys[i]; ++i) {
if (v[cacheKeys[i]].isEmpty())
continue;
@@ -614,7 +614,7 @@ MakefileGenerator::init()
//build up a list of compilers
QVector<Compiler> compilers;
{
- const char *builtins[] = { "OBJECTS", "SOURCES", "PRECOMPILED_HEADER", 0 };
+ const char *builtins[] = { "OBJECTS", "SOURCES", "PRECOMPILED_HEADER", nullptr };
for(x = 0; builtins[x]; ++x) {
Compiler compiler;
compiler.variable_in = builtins[x];
@@ -829,7 +829,7 @@ MakefileGenerator::init()
}
//fix up the target deps
- static const char * const fixpaths[] = { "PRE_TARGETDEPS", "POST_TARGETDEPS", 0 };
+ static const char * const fixpaths[] = { "PRE_TARGETDEPS", "POST_TARGETDEPS", nullptr };
for (int path = 0; fixpaths[path]; path++) {
ProStringList &l = v[fixpaths[path]];
for (ProStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) {
@@ -876,20 +876,37 @@ MakefileGenerator::init()
}
bool
-MakefileGenerator::processPrlFile(QString &file)
+MakefileGenerator::processPrlFile(QString &file, bool baseOnly)
{
- bool try_replace_file = false;
QString f = fileFixify(file, FileFixifyBackwards);
- QString meta_file = QMakeMetaInfo::findLib(f);
- if (!meta_file.isEmpty()) {
- try_replace_file = true;
- } else {
- QString tmp = f;
- int ext = tmp.lastIndexOf('.');
- if(ext != -1)
- tmp = tmp.left(ext);
- meta_file = QMakeMetaInfo::findLib(tmp);
+ // Explicitly given full .prl name
+ if (!baseOnly && f.endsWith(Option::prl_ext))
+ return processPrlFileCore(file, QStringRef(), f);
+ // Explicitly given or derived (from -l) base name
+ if (processPrlFileCore(file, QStringRef(), f + Option::prl_ext))
+ return true;
+ if (!baseOnly) {
+ // Explicitly given full library name
+ int off = qMax(f.lastIndexOf('/'), f.lastIndexOf('\\')) + 1;
+ int ext = f.midRef(off).lastIndexOf('.');
+ if (ext != -1)
+ return processPrlFileBase(file, f.midRef(off), f.leftRef(off + ext), off);
}
+ return false;
+}
+
+bool
+MakefileGenerator::processPrlFileBase(QString &origFile, const QStringRef &origName,
+ const QStringRef &fixedBase, int slashOff)
+{
+ return processPrlFileCore(origFile, origName, fixedBase + Option::prl_ext);
+}
+
+bool
+MakefileGenerator::processPrlFileCore(QString &origFile, const QStringRef &origName,
+ const QString &fixedFile)
+{
+ const QString meta_file = QMakeMetaInfo::checkLib(fixedFile);
if (meta_file.isEmpty())
return false;
QMakeMetaInfo libinfo(project);
@@ -898,9 +915,33 @@ MakefileGenerator::processPrlFile(QString &file)
fprintf(stderr, "Error processing meta file %s\n", meta_file.toLatin1().constData());
return false;
}
- if (project->isActiveConfig("no_read_prl_" + libinfo.type().toLower())) {
- debug_msg(2, "Ignored meta file %s [%s]",
- meta_file.toLatin1().constData(), libinfo.type().toLatin1().constData());
+ if (project->isActiveConfig("no_read_prl_qmake")) {
+ debug_msg(2, "Ignored meta file %s", meta_file.toLatin1().constData());
+ return false;
+ }
+ ProString tgt = libinfo.first("QMAKE_PRL_TARGET");
+ if (tgt.isEmpty()) {
+ fprintf(stderr, "Error: %s does not define QMAKE_PRL_TARGET\n",
+ meta_file.toLatin1().constData());
+ return false;
+ }
+ if (!tgt.contains('.') && !libinfo.values("QMAKE_PRL_CONFIG").contains("lib_bundle")) {
+ fprintf(stderr, "Error: %s defines QMAKE_PRL_TARGET without extension\n",
+ meta_file.toLatin1().constData());
+ return false;
+ }
+ if (origName.isEmpty()) {
+ // We got a .prl file as input, replace it with an actual library.
+ int off = qMax(origFile.lastIndexOf('/'), origFile.lastIndexOf('\\')) + 1;
+ debug_msg(1, " Replacing library reference %s with %s",
+ origFile.mid(off).toLatin1().constData(),
+ tgt.toQString().toLatin1().constData());
+ origFile.replace(off, 1000, tgt.toQString());
+ } else if (tgt != origName) {
+ // We got an actual library as input, and found the wrong .prl for it.
+ debug_msg(2, "Mismatched meta file %s (want %s, got %s)",
+ meta_file.toLatin1().constData(),
+ origName.toLatin1().constData(), tgt.toLatin1().constData());
return false;
}
project->values("QMAKE_CURRENT_PRL_LIBS") = libinfo.values("QMAKE_PRL_LIBS");
@@ -909,23 +950,6 @@ MakefileGenerator::processPrlFile(QString &file)
for (const ProString &def : libinfo.values("QMAKE_PRL_DEFINES"))
if (!defs.contains(def) && prl_defs.contains(def))
defs.append(def);
- if (try_replace_file) {
- ProString tgt = libinfo.first("QMAKE_PRL_TARGET");
- if (tgt.isEmpty()) {
- fprintf(stderr, "Error: %s does not define QMAKE_PRL_TARGET\n",
- meta_file.toLatin1().constData());
- } else if (!tgt.contains('.')
- && !libinfo.values("QMAKE_PRL_CONFIG").contains("lib_bundle")) {
- fprintf(stderr, "Error: %s defines QMAKE_PRL_TARGET without extension\n",
- meta_file.toLatin1().constData());
- } else {
- int off = qMax(file.lastIndexOf('/'), file.lastIndexOf('\\')) + 1;
- debug_msg(1, " Replacing library reference %s with %s",
- file.mid(off).toLatin1().constData(),
- tgt.toQString().toLatin1().constData());
- file.replace(off, 1000, tgt.toQString());
- }
- }
QString mf = fileFixify(meta_file);
if (!project->values("QMAKE_PRL_INTERNAL_FILES").contains(mf))
project->values("QMAKE_PRL_INTERNAL_FILES").append(mf);
@@ -988,12 +1012,10 @@ MakefileGenerator::writePrlFile(QTextStream &t)
t << "QMAKE_PRL_VERSION = " << project->first("VERSION") << endl;
if(project->isActiveConfig("staticlib") || project->isActiveConfig("explicitlib")) {
ProStringList libs;
- if(!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS"))
- libs = project->values("QMAKE_INTERNAL_PRL_LIBS");
+ if (!project->isActiveConfig("staticlib"))
+ libs << "LIBS" << "QMAKE_LIBS";
else
- libs << "QMAKE_LIBS"; //obvious one
- if(project->isActiveConfig("staticlib"))
- libs << "QMAKE_LIBS_PRIVATE";
+ libs << "LIBS" << "LIBS_PRIVATE" << "QMAKE_LIBS" << "QMAKE_LIBS_PRIVATE";
t << "QMAKE_PRL_LIBS =";
for (ProStringList::Iterator it = libs.begin(); it != libs.end(); ++it)
t << qv(project->values((*it).toKey()));
@@ -1078,18 +1100,7 @@ MakefileGenerator::write()
QString
MakefileGenerator::prlFileName(bool fixify)
{
- QString ret = project->first("TARGET_PRL").toQString();
- if(ret.isEmpty())
- ret = project->first("TARGET").toQString();
- int slsh = ret.lastIndexOf(Option::dir_sep);
- if(slsh != -1)
- ret.remove(0, slsh);
- if(!ret.endsWith(Option::prl_ext)) {
- int dot = ret.indexOf('.');
- if(dot != -1)
- ret.truncate(dot);
- ret += Option::prl_ext;
- }
+ QString ret = project->first("PRL_TARGET") + Option::prl_ext;
if(!project->isEmpty("QMAKE_BUNDLE"))
ret.prepend(project->first("QMAKE_BUNDLE") + Option::dir_sep);
if(fixify) {
@@ -1815,12 +1826,27 @@ MakefileGenerator::writeExtraTargets(QTextStream &t)
}
}
+static QStringList splitDeps(const QString &indeps, bool lineMode)
+{
+ if (!lineMode)
+ return indeps.simplified().split(' ');
+ QStringList deps = indeps.split('\n', QString::SkipEmptyParts);
+#ifdef Q_OS_WIN
+ for (auto &dep : deps) {
+ if (dep.endsWith(QLatin1Char('\r')))
+ dep.chop(1);
+ }
+#endif
+ return deps;
+}
+
void
MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
{
QString clean_targets;
const ProStringList &quc = project->values("QMAKE_EXTRA_COMPILERS");
for (ProStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) {
+ const ProStringList &config = project->values(ProKey(*it + ".CONFIG"));
QString tmp_out = fileFixify(project->first(ProKey(*it + ".output")).toQString(),
FileFixifyFromOutdir);
const QString tmp_cmd = project->values(ProKey(*it + ".commands")).join(' ');
@@ -1831,6 +1857,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
+ IoUtils::shellQuote(Option::fixPathToLocalOS(Option::output_dir, false))
+ QLatin1String(" && ");
}
+ const bool dep_lines = (config.indexOf("dep_lines") != -1);
const ProStringList &vars = project->values(ProKey(*it + ".variables"));
if(tmp_out.isEmpty() || tmp_cmd.isEmpty())
continue;
@@ -1847,7 +1874,6 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
}
t << "compiler_" << (*it) << "_make_all:";
- const ProStringList &config = project->values(ProKey(*it + ".CONFIG"));
if (config.indexOf("combine") != -1) {
// compilers with a combined input only have one output
QString input = project->first(ProKey(*it + ".output")).toQString();
@@ -1954,12 +1980,13 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
QT_PCLOSE(proc);
if(!indeps.isEmpty()) {
QDir outDir(Option::output_dir);
- // ### This is basically fubar. Add 'lines' flag to CONFIG?
- QStringList dep_cmd_deps = indeps.replace('\n', ' ').simplified().split(' ');
+ QStringList dep_cmd_deps = splitDeps(indeps, dep_lines);
for(int i = 0; i < dep_cmd_deps.count(); ++i) {
QString &file = dep_cmd_deps[i];
QString absFile = outDir.absoluteFilePath(file);
- if (exists(absFile)) {
+ if (absFile == file) {
+ // already absolute; don't do any checks.
+ } else if (exists(absFile)) {
file = absFile;
} else {
QString localFile;
@@ -1978,7 +2005,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
" prints paths relative to source directory",
(*it).toLatin1().constData());
else
- file.clear();
+ file = absFile; // fallback for generated resources
} else {
file = localFile;
}
@@ -2048,12 +2075,13 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
QT_PCLOSE(proc);
if(!indeps.isEmpty()) {
QDir outDir(Option::output_dir);
- // ### This is basically fubar. Add 'lines' flag to CONFIG?
- QStringList dep_cmd_deps = indeps.replace('\n', ' ').simplified().split(' ');
+ QStringList dep_cmd_deps = splitDeps(indeps, dep_lines);
for(int i = 0; i < dep_cmd_deps.count(); ++i) {
QString &file = dep_cmd_deps[i];
QString absFile = outDir.absoluteFilePath(file);
- if (exists(absFile)) {
+ if (absFile == file) {
+ // already absolute; don't do any checks.
+ } else if (exists(absFile)) {
file = absFile;
} else {
QString localFile;
@@ -2072,7 +2100,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
" prints paths relative to source directory",
(*it).toLatin1().constData());
else
- file.clear();
+ file = absFile; // fallback for generated resources
} else {
file = localFile;
}
@@ -2730,6 +2758,9 @@ MakefileGenerator::writeMakeQmake(QTextStream &t, bool noDummyQmakeAll)
const ProStringList &included = escapeDependencyPaths(project->values("QMAKE_INTERNAL_INCLUDED_FILES"));
t << included.join(QString(" \\\n\t\t")) << "\n\t"
<< qmake << endl;
+ const ProStringList &extraCommands = project->values("QMAKE_MAKE_QMAKE_EXTRA_COMMANDS");
+ if (!extraCommands.isEmpty())
+ t << "\t" << extraCommands.join(QString("\n\t")) << endl;
for(int include = 0; include < included.size(); ++include) {
const ProString &i = included.at(include);
if(!i.isEmpty())
@@ -2746,7 +2777,7 @@ MakefileGenerator::writeMakeQmake(QTextStream &t, bool noDummyQmakeAll)
QFileInfo
MakefileGenerator::fileInfo(QString file) const
{
- static QHash<FileInfoCacheKey, QFileInfo> *cache = 0;
+ static QHash<FileInfoCacheKey, QFileInfo> *cache = nullptr;
static QFileInfo noInfo = QFileInfo();
if(!cache) {
cache = new QHash<FileInfoCacheKey, QFileInfo>;
@@ -3132,54 +3163,31 @@ MakefileGenerator::specdir()
bool
MakefileGenerator::openOutput(QFile &file, const QString &build) const
{
- {
- QString outdir;
- if(!file.fileName().isEmpty()) {
- if(QDir::isRelativePath(file.fileName()))
- file.setFileName(Option::output_dir + "/" + file.fileName()); //pwd when qmake was run
- QFileInfo fi(fileInfo(file.fileName()));
- if(fi.isDir())
- outdir = file.fileName() + '/';
- }
- if(!outdir.isEmpty() || file.fileName().isEmpty()) {
- QString fname = "Makefile";
- if(!project->isEmpty("MAKEFILE"))
- fname = project->first("MAKEFILE").toQString();
- file.setFileName(outdir + fname);
- }
- }
- if(QDir::isRelativePath(file.fileName())) {
- QString fname = Option::output_dir; //pwd when qmake was run
- if(!fname.endsWith("/"))
- fname += "/";
- fname += file.fileName();
- file.setFileName(fname);
- }
- if(!build.isEmpty())
+ debug_msg(3, "asked to open output file '%s' in %s",
+ qPrintable(file.fileName()), qPrintable(Option::output_dir));
+
+ if (file.fileName().isEmpty()) {
+ file.setFileName(!project->isEmpty("MAKEFILE")
+ ? project->first("MAKEFILE").toQString() : "Makefile");
+ }
+
+ file.setFileName(QDir(Option::output_dir).absoluteFilePath(file.fileName()));
+
+ if (!build.isEmpty())
file.setFileName(file.fileName() + "." + build);
- if(project->isEmpty("QMAKE_MAKEFILE"))
+
+ if (project->isEmpty("QMAKE_MAKEFILE"))
project->values("QMAKE_MAKEFILE").append(file.fileName());
+
+ // Make required directories. Note that we do this based on the
+ // filename, not Option::output_dir, as the filename may include
+ // generator specific directories not included in output_dir.
int slsh = file.fileName().lastIndexOf('/');
- if(slsh != -1)
+ if (slsh != -1)
mkdir(file.fileName().left(slsh));
- if(file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
- QFileInfo fi(fileInfo(Option::output.fileName()));
- QString od;
- if(fi.isSymLink())
- od = fileInfo(fi.readLink()).absolutePath();
- else
- od = fi.path();
- od = QDir::fromNativeSeparators(od);
- if(QDir::isRelativePath(od)) {
- QString dir = Option::output_dir;
- if (!dir.endsWith('/') && !od.isEmpty())
- dir += '/';
- od.prepend(dir);
- }
- Option::output_dir = od;
- return true;
- }
- return false;
+
+ debug_msg(3, "opening output file %s", qPrintable(file.fileName()));
+ return file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate);
}
QString
@@ -3315,10 +3323,8 @@ MakefileGenerator::writePkgConfigFile()
t << "Libs: ";
QString pkgConfiglibName;
if (target_mode == TARG_MAC_MODE && project->isActiveConfig("lib_bundle")) {
- if (libDir != QLatin1String("/System/Library/Frameworks")
- && libDir != QLatin1String("/Library/Frameworks")) {
+ if (libDir != QLatin1String("/Library/Frameworks"))
t << "-F${libdir} ";
- }
ProString bundle;
if (!project->isEmpty("QMAKE_FRAMEWORK_BUNDLE_NAME"))
bundle = project->first("QMAKE_FRAMEWORK_BUNDLE_NAME");
@@ -3340,10 +3346,9 @@ MakefileGenerator::writePkgConfigFile()
if (project->isActiveConfig("staticlib")) {
ProStringList libs;
- if (!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS"))
- libs = project->values("QMAKE_INTERNAL_PRL_LIBS");
- else
- libs << "QMAKE_LIBS"; //obvious one
+ libs << "LIBS"; // FIXME: this should not be conditional on staticlib
+ libs << "LIBS_PRIVATE";
+ libs << "QMAKE_LIBS"; // FIXME: this should not be conditional on staticlib
libs << "QMAKE_LIBS_PRIVATE";
libs << "QMAKE_LFLAGS_THREAD"; //not sure about this one, but what about things like -pthread?
t << "Libs.private:";
@@ -3363,6 +3368,10 @@ MakefileGenerator::writePkgConfigFile()
;
if (!project->values("QMAKE_DEFAULT_INCDIRS").contains(includeDir))
t << "-I${includedir}";
+ if (target_mode == TARG_MAC_MODE && project->isActiveConfig("lib_bundle")
+ && libDir != QLatin1String("/Library/Frameworks")) {
+ t << " -F${libdir}";
+ }
t << endl;
// requires
diff --git a/qmake/generators/makefile.h b/qmake/generators/makefile.h
index f32bec650e..b5c150e1cb 100644
--- a/qmake/generators/makefile.h
+++ b/qmake/generators/makefile.h
@@ -124,9 +124,9 @@ protected:
{ return replaceExtraCompilerVariables(val, QStringList(in), QStringList(out), forShell); }
//interface to the source file info
- QMakeLocalFileName fixPathForFile(const QMakeLocalFileName &, bool);
- QMakeLocalFileName findFileForDep(const QMakeLocalFileName &, const QMakeLocalFileName &);
- QFileInfo findFileInfo(const QMakeLocalFileName &);
+ QMakeLocalFileName fixPathForFile(const QMakeLocalFileName &, bool) override;
+ QMakeLocalFileName findFileForDep(const QMakeLocalFileName &, const QMakeLocalFileName &) override;
+ QFileInfo findFileInfo(const QMakeLocalFileName &) override;
QMakeProject *project;
//escape
@@ -172,7 +172,7 @@ protected:
{ int ret; canExecute(cmdline, &ret); return ret; }
bool canExecute(const QStringList &cmdline, int *argv0) const;
inline bool canExecute(const QString &cmdline) const
- { return canExecute(cmdline.split(' '), 0); }
+ { return canExecute(cmdline.split(' '), nullptr); }
bool mkdir(const QString &dir) const;
QString mkdir_p_asstring(const QString &dir, bool escape=true) const;
@@ -198,7 +198,7 @@ protected:
//for prl
QString prlFileName(bool fixify=true);
void writePrlFile();
- bool processPrlFile(QString &);
+ bool processPrlFile(QString &, bool baseOnly);
virtual void writePrlFile(QTextStream &);
//make sure libraries are found
@@ -246,9 +246,14 @@ protected:
QString installMetaFile(const ProKey &replace_rule, const QString &src, const QString &dst);
+ virtual bool processPrlFileBase(QString &origFile, const QStringRef &origName,
+ const QStringRef &fixedBase, int slashOff);
+ bool processPrlFileCore(QString &origFile, const QStringRef &origName,
+ const QString &fixedFile);
+
public:
MakefileGenerator();
- virtual ~MakefileGenerator();
+ ~MakefileGenerator();
QMakeProject *projectFile() const;
void setProjectFile(QMakeProject *p);
diff --git a/qmake/generators/makefiledeps.cpp b/qmake/generators/makefiledeps.cpp
index ffccdefbe1..decc1d980c 100644
--- a/qmake/generators/makefiledeps.cpp
+++ b/qmake/generators/makefiledeps.cpp
@@ -81,7 +81,7 @@ const QString
struct SourceDependChildren;
struct SourceFile {
- SourceFile() : deps(0), type(QMakeSourceFileInfo::TYPE_UNKNOWN),
+ SourceFile() : deps(nullptr), type(QMakeSourceFileInfo::TYPE_UNKNOWN),
mocable(0), traversed(0), exists(1),
moc_checked(0), dep_checked(0), included_count(0) { }
~SourceFile();
@@ -95,8 +95,8 @@ struct SourceFile {
struct SourceDependChildren {
SourceFile **children;
int num_nodes, used_nodes;
- SourceDependChildren() : children(0), num_nodes(0), used_nodes(0) { }
- ~SourceDependChildren() { if(children) free(children); children = 0; }
+ SourceDependChildren() : children(nullptr), num_nodes(0), used_nodes(0) { }
+ ~SourceDependChildren() { if (children) free(children); children = nullptr; }
void addChild(SourceFile *s) {
if(num_nodes <= used_nodes) {
num_nodes += 200;
@@ -115,10 +115,10 @@ public:
SourceFile *lookupFile(const char *);
inline SourceFile *lookupFile(const QString &f) { return lookupFile(f.toLatin1().constData()); }
inline SourceFile *lookupFile(const QMakeLocalFileName &f) { return lookupFile(f.local().toLatin1().constData()); }
- void addFile(SourceFile *, const char *k=0, bool own=true);
+ void addFile(SourceFile *, const char *k = nullptr, bool own = true);
struct SourceFileNode {
- SourceFileNode() : key(0), next(0), file(0), own_file(1) { }
+ SourceFileNode() : key(nullptr), next(nullptr), file(nullptr), own_file(1) { }
~SourceFileNode() {
delete [] key;
if(own_file)
@@ -135,7 +135,7 @@ SourceFiles::SourceFiles()
{
nodes = (SourceFileNode**)malloc(sizeof(SourceFileNode*)*(num_nodes=3037));
for(int n = 0; n < num_nodes; n++)
- nodes[n] = 0;
+ nodes[n] = nullptr;
}
SourceFiles::~SourceFiles()
@@ -170,7 +170,7 @@ SourceFile *SourceFiles::lookupFile(const char *file)
if(!strcmp(p->key, file))
return p->file;
}
- return 0;
+ return nullptr;
}
void SourceFiles::addFile(SourceFile *p, const char *k, bool own_file)
@@ -259,11 +259,11 @@ QMakeSourceFileInfo::QMakeSourceFileInfo(const QString &cf)
dep_mode = Recursive;
//quick project lookups
- includes = files = 0;
+ includes = files = nullptr;
files_changed = false;
//buffer
- spare_buffer = 0;
+ spare_buffer = nullptr;
spare_buffer_size = 0;
//cache
@@ -281,7 +281,7 @@ QMakeSourceFileInfo::~QMakeSourceFileInfo()
//buffer
if(spare_buffer) {
free(spare_buffer);
- spare_buffer = 0;
+ spare_buffer = nullptr;
spare_buffer_size = 0;
}
@@ -538,7 +538,7 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file)
const QMakeLocalFileName sourceFile = fixPathForFile(file->file, true);
struct stat fst;
- char *buffer = 0;
+ char *buffer = nullptr;
int buffer_len = 0;
{
int fd;
@@ -588,7 +588,7 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file)
}
for (; x < buffer_len; ++x) {
bool try_local = true;
- char *inc = 0;
+ char *inc = nullptr;
if(file->type == QMakeSourceFileInfo::TYPE_UI) {
// skip whitespaces
while (x < buffer_len && (buffer[x] == ' ' || buffer[x] == '\t'))
@@ -802,7 +802,7 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file)
if (cpp_state == WantName)
buffer[clean] = '\0';
else // i.e. malformed
- inc = 0;
+ inc = nullptr;
cpp_state = InCode; // hereafter
break;
@@ -915,7 +915,7 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file)
file->moc_checked = true;
int buffer_len = 0;
- char *buffer = 0;
+ char *buffer = nullptr;
{
struct stat fst;
int fd;
diff --git a/qmake/generators/metamakefile.cpp b/qmake/generators/metamakefile.cpp
index 874b4286bc..8ebd0c61ce 100644
--- a/qmake/generators/metamakefile.cpp
+++ b/qmake/generators/metamakefile.cpp
@@ -62,11 +62,11 @@ private:
public:
BuildsMetaMakefileGenerator(QMakeProject *p, const QString &n, bool op) : MetaMakefileGenerator(p, n, op), init_flag(false) { }
- virtual ~BuildsMetaMakefileGenerator() { clearBuilds(); }
+ ~BuildsMetaMakefileGenerator() { clearBuilds(); }
- virtual bool init();
- virtual int type() const { return BUILDSMETATYPE; }
- virtual bool write();
+ bool init() override;
+ int type() const override { return BUILDSMETATYPE; }
+ bool write() override;
};
void
@@ -138,7 +138,7 @@ BuildsMetaMakefileGenerator::init()
bool
BuildsMetaMakefileGenerator::write()
{
- Build *glue = 0;
+ Build *glue = nullptr;
if(!makefiles.isEmpty() && !makefiles.first()->build.isNull()) {
glue = new Build;
glue->name = name;
@@ -228,7 +228,7 @@ MakefileGenerator
if (build_proj->read(project->projectFile()))
return createMakefileGenerator(build_proj);
}
- return 0;
+ return nullptr;
}
class SubdirsMetaMakefileGenerator : public MetaMakefileGenerator
@@ -236,7 +236,7 @@ class SubdirsMetaMakefileGenerator : public MetaMakefileGenerator
protected:
bool init_flag;
struct Subdir {
- Subdir() : makefile(0), indent(0) { }
+ Subdir() : makefile(nullptr), indent(0) { }
~Subdir() { delete makefile; }
QString input_dir;
QString output_dir, output_file;
@@ -248,11 +248,11 @@ protected:
public:
SubdirsMetaMakefileGenerator(QMakeProject *p, const QString &n, bool op) : MetaMakefileGenerator(p, n, op), init_flag(false) { }
- virtual ~SubdirsMetaMakefileGenerator();
+ ~SubdirsMetaMakefileGenerator();
- virtual bool init();
- virtual int type() const { return SUBDIRSMETATYPE; }
- virtual bool write();
+ bool init() override;
+ int type() const override { return SUBDIRSMETATYPE; }
+ bool write() override;
};
bool
@@ -336,7 +336,7 @@ SubdirsMetaMakefileGenerator::init()
hasError |= !sub->makefile->write();
delete sub;
qmakeClearCaches();
- sub = 0;
+ sub = nullptr;
Option::output.setFileName(output_name);
}
Option::output_dir = old_output_dir;
@@ -412,7 +412,7 @@ MetaMakefileGenerator::createMakefileGenerator(QMakeProject *proj, bool noIO)
{
Option::postProcessProject(proj);
- MakefileGenerator *mkfile = NULL;
+ MakefileGenerator *mkfile = nullptr;
if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) {
mkfile = new ProjectGenerator;
mkfile->setProjectFile(proj);
@@ -459,7 +459,7 @@ MetaMakefileGenerator::createMetaGenerator(QMakeProject *proj, const QString &na
{
Option::postProcessProject(proj);
- MetaMakefileGenerator *ret = 0;
+ MetaMakefileGenerator *ret = nullptr;
if ((Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
Option::qmake_mode == Option::QMAKE_GENERATE_PRL)) {
if (proj->first("TEMPLATE").endsWith("subdirs"))
diff --git a/qmake/generators/metamakefile.h b/qmake/generators/metamakefile.h
index 706bca3363..9337130143 100644
--- a/qmake/generators/metamakefile.h
+++ b/qmake/generators/metamakefile.h
@@ -49,7 +49,7 @@ public:
virtual ~MetaMakefileGenerator();
- static MetaMakefileGenerator *createMetaGenerator(QMakeProject *proj, const QString &name, bool op=true, bool *success = 0);
+ static MetaMakefileGenerator *createMetaGenerator(QMakeProject *proj, const QString &name, bool op=true, bool *success = nullptr);
static MakefileGenerator *createMakefileGenerator(QMakeProject *proj, bool noIO = false);
inline QMakeProject *projectFile() const { return project; }
diff --git a/qmake/generators/projectgenerator.cpp b/qmake/generators/projectgenerator.cpp
index 073d315aab..f45a90b851 100644
--- a/qmake/generators/projectgenerator.cpp
+++ b/qmake/generators/projectgenerator.cpp
@@ -229,7 +229,7 @@ ProjectGenerator::init()
ProStringList &h = v["HEADERS"];
bool no_qt_files = true;
- static const char *srcs[] = { "SOURCES", "YACCSOURCES", "LEXSOURCES", "FORMS", 0 };
+ static const char *srcs[] = { "SOURCES", "YACCSOURCES", "LEXSOURCES", "FORMS", nullptr };
for (int i = 0; srcs[i]; i++) {
const ProStringList &l = v[srcs[i]];
QMakeSourceFileInfo::SourceFileType type = QMakeSourceFileInfo::TYPE_C;
@@ -473,18 +473,11 @@ ProjectGenerator::getWritableVar(const char *vk, bool)
bool
ProjectGenerator::openOutput(QFile &file, const QString &build) const
{
- QString outdir;
- if(!file.fileName().isEmpty()) {
- QFileInfo fi(fileInfo(file.fileName()));
- if(fi.isDir())
- outdir = fi.path() + QDir::separator();
- }
- if(!outdir.isEmpty() || file.fileName().isEmpty()) {
- QString dir = qmake_getpwd();
- int s = dir.lastIndexOf('/');
- if(s != -1)
- dir = dir.right(dir.length() - (s + 1));
- file.setFileName(outdir + dir + Option::pro_ext);
+ ProString fileName = file.fileName();
+ if (!fileName.endsWith(Option::pro_ext)) {
+ if (fileName.isEmpty())
+ fileName = fileInfo(Option::output_dir).fileName();
+ file.setFileName(fileName + Option::pro_ext);
}
return MakefileGenerator::openOutput(file, build);
}
diff --git a/qmake/generators/projectgenerator.h b/qmake/generators/projectgenerator.h
index 89c66f1ec8..cbc9f371ab 100644
--- a/qmake/generators/projectgenerator.h
+++ b/qmake/generators/projectgenerator.h
@@ -40,16 +40,16 @@ class ProjectGenerator : public MakefileGenerator
QString getWritableVar(const char *, bool fixPath=true);
QString fixPathToQmake(const QString &file);
protected:
- virtual void init();
- virtual bool writeMakefile(QTextStream &);
+ void init() override;
+ bool writeMakefile(QTextStream &) override;
- virtual QString escapeFilePath(const QString &path) const { Q_ASSERT(false); return QString(); }
+ QString escapeFilePath(const QString &path) const override { Q_ASSERT(false); return QString(); }
public:
ProjectGenerator();
~ProjectGenerator();
- virtual bool supportsMetaBuild() { return false; }
- virtual bool openOutput(QFile &, const QString &) const;
+ bool supportsMetaBuild() override { return false; }
+ bool openOutput(QFile &, const QString &) const override;
};
inline ProjectGenerator::~ProjectGenerator()
diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp
index 894020d2bd..50ec8db79e 100644
--- a/qmake/generators/unix/unixmake.cpp
+++ b/qmake/generators/unix/unixmake.cpp
@@ -37,6 +37,17 @@
QT_BEGIN_NAMESPACE
+ProStringList UnixMakefileGenerator::libdirToFlags(const ProKey &key)
+{
+ ProStringList results;
+ for (const auto &libdir : qAsConst(project->values(key))) {
+ if (!project->isEmpty("QMAKE_LFLAGS_RPATH") && project->isActiveConfig("rpath_libdirs"))
+ project->values("QMAKE_LFLAGS") += var("QMAKE_LFLAGS_RPATH") + libdir;
+ results.append("-L" + escapeFilePath(libdir));
+ }
+ return results;
+}
+
void
UnixMakefileGenerator::init()
{
@@ -80,8 +91,6 @@ UnixMakefileGenerator::init()
}
project->values("QMAKE_ORIG_DESTDIR") = project->values("DESTDIR");
- project->values("QMAKE_LIBS") += project->values("LIBS");
- project->values("QMAKE_LIBS_PRIVATE") += project->values("LIBS_PRIVATE");
if((!project->isEmpty("QMAKE_LIB_FLAG") && !project->isActiveConfig("staticlib")) ||
(project->isActiveConfig("qt") && project->isActiveConfig("plugin"))) {
if(configs.indexOf("dll") == -1) configs.append("dll");
@@ -95,21 +104,13 @@ UnixMakefileGenerator::init()
project->isActiveConfig("dll"))
project->values("QMAKE_LFLAGS") += project->values("QMAKE_LFLAGS_PREBIND");
project->values("QMAKE_INCDIR") += project->values("QMAKE_INCDIR_POST");
- project->values("QMAKE_LIBDIR") += project->values("QMAKE_LIBDIR_POST");
project->values("QMAKE_RPATHDIR") += project->values("QMAKE_RPATHDIR_POST");
project->values("QMAKE_RPATHLINKDIR") += project->values("QMAKE_RPATHLINKDIR_POST");
if(!project->isEmpty("QMAKE_INCDIR"))
project->values("INCLUDEPATH") += project->values("QMAKE_INCDIR");
- ProStringList ldadd;
- if(!project->isEmpty("QMAKE_LIBDIR")) {
- const ProStringList &libdirs = project->values("QMAKE_LIBDIR");
- for(int i = 0; i < libdirs.size(); ++i) {
- if(!project->isEmpty("QMAKE_LFLAGS_RPATH") && project->isActiveConfig("rpath_libdirs"))
- project->values("QMAKE_LFLAGS") += var("QMAKE_LFLAGS_RPATH") + libdirs[i];
- project->values("QMAKE_LIBDIR_FLAGS") += "-L" + escapeFilePath(libdirs[i]);
- }
- }
- ldadd += project->values("QMAKE_LIBDIR_FLAGS");
+ // The order of the next two lines is relevant due to side effect on QMAKE_LFLAGS.
+ ProStringList ldadd = project->values("QMAKE_LIBDIR_FLAGS") + libdirToFlags("QMAKE_LIBDIR");
+ ProStringList ldaddpost = libdirToFlags("QMAKE_LIBDIR_POST");
if (project->isActiveConfig("mac")) {
if (!project->isEmpty("QMAKE_FRAMEWORKPATH")) {
const ProStringList &fwdirs = project->values("QMAKE_FRAMEWORKPATH");
@@ -118,8 +119,10 @@ UnixMakefileGenerator::init()
}
ldadd += project->values("QMAKE_FRAMEWORKPATH_FLAGS");
}
- ProStringList &qmklibs = project->values("QMAKE_LIBS");
+ ProStringList &qmklibs = project->values("LIBS");
qmklibs = ldadd + qmklibs;
+ ProStringList &qmklibspost = project->values("QMAKE_LIBS");
+ qmklibspost = ldaddpost + qmklibspost;
if (!project->isEmpty("QMAKE_RPATHDIR") && !project->isEmpty("QMAKE_LFLAGS_RPATH")) {
const ProStringList &rpathdirs = project->values("QMAKE_RPATHDIR");
for (int i = 0; i < rpathdirs.size(); ++i) {
@@ -300,35 +303,11 @@ UnixMakefileGenerator::init()
}
init2();
- project->values("QMAKE_INTERNAL_PRL_LIBS") << "QMAKE_LIBS";
ProString target = project->first("TARGET");
int slsh = target.lastIndexOf(Option::dir_sep);
if (slsh != -1)
target.chopFront(slsh + 1);
project->values("LIB_TARGET").prepend(target);
- if(!project->isEmpty("QMAKE_MAX_FILES_PER_AR")) {
- bool ok;
- int max_files = project->first("QMAKE_MAX_FILES_PER_AR").toInt(&ok);
- ProStringList ar_sublibs, objs = project->values("OBJECTS");
- if(ok && max_files > 5 && max_files < (int)objs.count()) {
- QString lib;
- for(int i = 0, obj_cnt = 0, lib_cnt = 0; i != objs.size(); ++i) {
- if((++obj_cnt) >= max_files) {
- if(lib_cnt) {
- lib.sprintf("lib%s-tmp%d.a",
- project->first("QMAKE_ORIG_TARGET").toLatin1().constData(), lib_cnt);
- ar_sublibs << lib;
- obj_cnt = 0;
- }
- lib_cnt++;
- }
- }
- }
- if(!ar_sublibs.isEmpty()) {
- project->values("QMAKE_AR_SUBLIBS") = ar_sublibs;
- project->values("QMAKE_INTERNAL_PRL_LIBS") << "QMAKE_AR_SUBLIBS";
- }
- }
}
QStringList
@@ -420,7 +399,8 @@ UnixMakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags)
libdirs.append(QMakeLocalFileName(dlib.toQString()));
frameworkdirs.append(QMakeLocalFileName("/System/Library/Frameworks"));
frameworkdirs.append(QMakeLocalFileName("/Library/Frameworks"));
- static const char * const lflags[] = { "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", 0 };
+ static const char * const lflags[] = { "LIBS", "LIBS_PRIVATE",
+ "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", nullptr };
for (int i = 0; lflags[i]; i++) {
ProStringList &l = project->values(lflags[i]);
for (ProStringList::Iterator it = l.begin(); it != l.end(); ) {
@@ -443,7 +423,7 @@ UnixMakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags)
dep_it != libdirs.end(); ++dep_it) {
QString libBase = (*dep_it).local() + '/'
+ project->first("QMAKE_PREFIX_SHLIB") + lib;
- if (linkPrl && processPrlFile(libBase))
+ if (linkPrl && processPrlFile(libBase, true))
goto found;
for (ProStringList::Iterator extit = extens.begin(); extit != extens.end(); ++extit) {
if (exists(libBase + '.' + (*extit)))
@@ -471,12 +451,12 @@ UnixMakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags)
}
for (const QMakeLocalFileName &dir : qAsConst(frameworkdirs)) {
QString frameworkDirectory = dir.local() + "/" + frameworkName + + ".framework/";
- QString suffixedPrl = frameworkDirectory + opt + Option::prl_ext;
- if (processPrlFile(suffixedPrl))
+ QString suffixedPrl = frameworkDirectory + opt;
+ if (processPrlFile(suffixedPrl, true))
break;
if (hasSuffix) {
- QString unsuffixedPrl = frameworkDirectory + frameworkName + Option::prl_ext;
- if (processPrlFile(unsuffixedPrl))
+ QString unsuffixedPrl = frameworkDirectory + frameworkName;
+ if (processPrlFile(unsuffixedPrl, true))
break;
}
}
@@ -487,7 +467,7 @@ UnixMakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags)
}
}
} else if (linkPrl) {
- processPrlFile(opt);
+ processPrlFile(opt, false);
}
ProStringList &prl_libs = project->values("QMAKE_CURRENT_PRL_LIBS");
diff --git a/qmake/generators/unix/unixmake.h b/qmake/generators/unix/unixmake.h
index da5cdb320c..5b0766855b 100644
--- a/qmake/generators/unix/unixmake.h
+++ b/qmake/generators/unix/unixmake.h
@@ -38,7 +38,7 @@ class UnixMakefileGenerator : public MakefileGenerator
bool include_deps;
QString libtoolFileName(bool fixify=true);
void writeLibtoolFile(); // for libtool
- void writePrlFile(QTextStream &);
+ void writePrlFile(QTextStream &) override;
public:
UnixMakefileGenerator();
@@ -46,26 +46,27 @@ public:
protected:
virtual bool doPrecompiledHeaders() const { return project->isActiveConfig("precompile_header"); }
- virtual bool doDepends() const { return !Option::mkfile::do_stub_makefile && MakefileGenerator::doDepends(); }
+ bool doDepends() const override { return !Option::mkfile::do_stub_makefile && MakefileGenerator::doDepends(); }
#ifdef Q_OS_WIN // MinGW x-compiling for QNX
- virtual QString installRoot() const;
+ QString installRoot() const override;
#endif
- virtual QString defaultInstall(const QString &);
- virtual ProString fixLibFlag(const ProString &lib);
+ QString defaultInstall(const QString &) override;
+ ProString fixLibFlag(const ProString &lib) override;
- virtual bool findLibraries(bool linkPrl, bool mergeLflags);
- virtual QString escapeFilePath(const QString &path) const;
+ bool findLibraries(bool linkPrl, bool mergeLflags) override;
+ QString escapeFilePath(const QString &path) const override;
ProString escapeFilePath(const ProString &path) const { return MakefileGenerator::escapeFilePath(path); }
- virtual QStringList &findDependencies(const QString &);
- virtual void init();
+ QStringList &findDependencies(const QString &) override;
+ void init() override;
- virtual void writeDefaultVariables(QTextStream &t);
- virtual void writeSubTargets(QTextStream &t, QList<SubTarget*> subtargets, int flags);
+ void writeDefaultVariables(QTextStream &t) override;
+ void writeSubTargets(QTextStream &t, QList<SubTarget*> subtargets, int flags) override;
void writeMakeParts(QTextStream &);
- bool writeMakefile(QTextStream &);
+ bool writeMakefile(QTextStream &) override;
private:
void init2();
+ ProStringList libdirToFlags(const ProKey &key);
};
inline UnixMakefileGenerator::~UnixMakefileGenerator()
diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp
index ecb0de3b52..976751b02c 100644
--- a/qmake/generators/unix/unixmake2.cpp
+++ b/qmake/generators/unix/unixmake2.cpp
@@ -213,7 +213,9 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
if(!project->isActiveConfig("staticlib")) {
t << "LINK = " << var("QMAKE_LINK") << endl;
t << "LFLAGS = " << var("QMAKE_LFLAGS") << endl;
- t << "LIBS = $(SUBLIBS) " << fixLibFlags("QMAKE_LIBS").join(' ') << ' '
+ t << "LIBS = $(SUBLIBS) " << fixLibFlags("LIBS").join(' ') << ' '
+ << fixLibFlags("LIBS_PRIVATE").join(' ') << ' '
+ << fixLibFlags("QMAKE_LIBS").join(' ') << ' '
<< fixLibFlags("QMAKE_LIBS_PRIVATE").join(' ') << endl;
}
@@ -280,11 +282,11 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
if (destd.endsWith('\\'))
destd += '\\';
t << "DESTDIR = " << destd << endl;
- t << "TARGET = " << fileVar("TARGET") << endl; // ### mixed use!
+ t << "TARGET = " << fileVar("TARGET") << endl;
if(project->isActiveConfig("plugin")) {
t << "TARGETD = " << fileVar("TARGET") << endl;
} else if(!project->isActiveConfig("staticlib") && project->values("QMAKE_APP_FLAG").isEmpty()) {
- t << "TARGETA = " << fileVar("TARGETA") << endl; // ### mixed use!
+ t << "TARGETA = " << fileVar("TARGETA") << endl;
if(!project->isEmpty("QMAKE_BUNDLE")) {
t << "TARGETD = " << fileVar("TARGET_x.y") << endl;
t << "TARGET0 = " << fileVar("TARGET_") << endl;
@@ -346,7 +348,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
t << mkdir_p_asstring("$(@D)", false) << "\n\t"
<< "@$(CC) " << cmd << " $< | sed \"s,^\\($(*F).o\\):," << odir << "\\1:,g\" >$@\n\n";
- static const char * const src[] = { "SOURCES", "GENERATED_SOURCES", 0 };
+ static const char * const src[] = { "SOURCES", "GENERATED_SOURCES", nullptr };
for (int x = 0; src[x]; x++) {
const ProStringList &l = project->values(src[x]);
for (ProStringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
@@ -502,7 +504,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
t << "\n\t" << var("QMAKE_POST_LINK");
t << endl << endl;
} else {
- t << "$(TARGET): " << depVar("PRE_TARGETDEPS") << " $(OBJECTS) "
+ t << depVar("TARGET") << ": " << depVar("PRE_TARGETDEPS") << " $(OBJECTS) "
<< target_deps << ' ' << depVar("POST_TARGETDEPS") << "\n\t";
if (project->first("TEMPLATE") != "aux") {
if (!destdir.isEmpty())
@@ -515,7 +517,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
}
t << endl << endl;
}
- allDeps = " $(TARGET)";
+ allDeps = ' ' + depVar("TARGET");
} else if(!project->isActiveConfig("staticlib")) {
QString destdir_r = project->first("DESTDIR").toQString(), incr_deps;
if(!project->isEmpty("QMAKE_BUNDLE")) {
@@ -580,14 +582,14 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
}
//real target
- t << destdir_d << "$(TARGET): " << depVar("PRE_TARGETDEPS") << ' '
+ t << destdir_d << depVar("TARGET") << ": " << depVar("PRE_TARGETDEPS") << ' '
<< incr_deps << " $(SUBLIBS) " << target_deps << ' ' << depVar("POST_TARGETDEPS");
} else {
- t << destdir_d << "$(TARGET): " << depVar("PRE_TARGETDEPS")
+ t << destdir_d << depVar("TARGET") << ": " << depVar("PRE_TARGETDEPS")
<< " $(OBJECTS) $(SUBLIBS) $(OBJCOMP) " << target_deps
<< ' ' << depVar("POST_TARGETDEPS");
}
- allDeps = ' ' + destdir_d + "$(TARGET)";
+ allDeps = ' ' + destdir_d + depVar("TARGET");
if(!destdir.isEmpty())
t << "\n\t" << mkdir_p_asstring(destdir, false);
if(!project->isEmpty("QMAKE_PRE_LINK"))
@@ -604,7 +606,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
t << "\n\t" << var("QMAKE_POST_LINK");
t << endl << endl;
} else if(!project->isEmpty("QMAKE_BUNDLE")) {
- bundledFiles << destdir_r + "$(TARGET)";
+ bundledFiles << destdir_r + var("TARGET");
t << "\n\t"
<< "-$(DEL_FILE) $(TARGET) $(TARGET0) $(DESTDIR)$(TARGET0)\n\t"
<< var("QMAKE_LINK_SHLIB_CMD") << "\n\t"
@@ -669,8 +671,8 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
t << endl << endl;
if (! project->isActiveConfig("plugin")) {
- t << "staticlib: $(TARGETA)\n\n";
- t << "$(TARGETA): " << depVar("PRE_TARGETDEPS") << " $(OBJECTS) $(OBJCOMP)";
+ t << "staticlib: " << depVar("TARGETA") << "\n\n";
+ t << depVar("TARGETA") << ": " << depVar("PRE_TARGETDEPS") << " $(OBJECTS) $(OBJCOMP)";
if(do_incremental)
t << " $(INCREMENTAL_OBJECTS)";
t << ' ' << depVar("POST_TARGETDEPS") << "\n\t";
@@ -690,56 +692,20 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
QString destdir_r = project->first("DESTDIR").toQString();
QString destdir_d = escapeDependencyPath(destdir_r);
QString destdir = escapeFilePath(destdir_r);
- allDeps = ' ' + destdir_d + "$(TARGET)"
- + varGlue("QMAKE_AR_SUBLIBS", ' ' + destdir_d, ' ' + destdir_d, "");
- t << "staticlib: " << destdir_d << "$(TARGET)\n\n";
- if(project->isEmpty("QMAKE_AR_SUBLIBS")) {
- t << destdir_d << "$(TARGET): " << depVar("PRE_TARGETDEPS")
- << " $(OBJECTS) $(OBJCOMP) " << depVar("POST_TARGETDEPS") << "\n\t";
- if(!destdir.isEmpty())
- t << mkdir_p_asstring(destdir, false) << "\n\t";
- if (!project->isEmpty("QMAKE_PRE_LINK"))
- t << var("QMAKE_PRE_LINK") << "\n\t";
- t << "-$(DEL_FILE) " << destdir << "$(TARGET)\n\t"
- << var("QMAKE_AR_CMD") << "\n";
- if(!project->isEmpty("QMAKE_POST_LINK"))
- t << "\t" << var("QMAKE_POST_LINK") << "\n";
- if(!project->isEmpty("QMAKE_RANLIB"))
- t << "\t$(RANLIB) " << destdir << "$(TARGET)\n";
- } else {
- int max_files = project->first("QMAKE_MAX_FILES_PER_AR").toInt();
- ProStringList objs = project->values("OBJECTS") + project->values("OBJCOMP"),
- libs = project->values("QMAKE_AR_SUBLIBS");
- libs.prepend("$(TARGET)");
- for (ProStringList::Iterator libit = libs.begin(), objit = objs.begin();
- libit != libs.end(); ++libit) {
- ProStringList build;
- for(int cnt = 0; cnt < max_files && objit != objs.end(); ++objit, cnt++)
- build << (*objit);
- QString ar;
- ProString lib = destdir + escapeFilePath(*libit);
- if((*libit) == "$(TARGET)") {
- t << destdir_d << "$(TARGET): " << depVar("PRE_TARGETDEPS")
- << ' ' << depVar("POST_TARGETDEPS") << valList(escapeDependencyPaths(build)) << "\n\t";
- ar = project->first("QMAKE_AR_CMD").toQString();
- ar.replace(QLatin1String("$(OBJECTS)"), escapeFilePaths(build).join(' '));
- } else {
- t << destdir_d << escapeDependencyPath(*libit) << ": "
- << valList(escapeDependencyPaths(build)) << "\n\t";
- ar = "$(AR) " + lib + ' ' + escapeFilePaths(build).join(' ');
- }
- if(!destdir.isEmpty())
- t << mkdir_p_asstring(destdir, false) << "\n\t";
- if (!project->isEmpty("QMAKE_PRE_LINK"))
- t << var("QMAKE_PRE_LINK") << "\n\t";
- t << "-$(DEL_FILE) " << lib << "\n\t"
- << ar << "\n";
- if(!project->isEmpty("QMAKE_POST_LINK"))
- t << "\t" << var("QMAKE_POST_LINK") << "\n";
- if(!project->isEmpty("QMAKE_RANLIB"))
- t << "\t$(RANLIB) " << lib << "\n";
- }
- }
+ allDeps = ' ' + destdir_d + depVar("TARGET");
+ t << "staticlib: " << destdir_d << "$(TARGET)\n\n"
+ << destdir_d << depVar("TARGET") << ": " << depVar("PRE_TARGETDEPS")
+ << " $(OBJECTS) $(OBJCOMP) " << depVar("POST_TARGETDEPS") << "\n\t";
+ if (!destdir.isEmpty())
+ t << mkdir_p_asstring(destdir, false) << "\n\t";
+ if (!project->isEmpty("QMAKE_PRE_LINK"))
+ t << var("QMAKE_PRE_LINK") << "\n\t";
+ t << "-$(DEL_FILE) " << destdir << "$(TARGET)\n\t"
+ << var("QMAKE_AR_CMD") << "\n";
+ if (!project->isEmpty("QMAKE_POST_LINK"))
+ t << "\t" << var("QMAKE_POST_LINK") << "\n";
+ if (!project->isEmpty("QMAKE_RANLIB"))
+ t << "\t$(RANLIB) " << destdir << "$(TARGET)\n";
t << endl << endl;
}
@@ -1244,7 +1210,8 @@ void UnixMakefileGenerator::init2()
if(!project->isEmpty("TARGET"))
project->values("TARGET").first().prepend(project->first("DESTDIR"));
} else if (project->isActiveConfig("staticlib")) {
- project->values("TARGET").first().prepend(project->first("QMAKE_PREFIX_STATICLIB"));
+ project->values("PRL_TARGET") =
+ project->values("TARGET").first().prepend(project->first("QMAKE_PREFIX_STATICLIB"));
project->values("TARGET").first() += "." + project->first("QMAKE_EXTENSION_STATICLIB");
if(project->values("QMAKE_AR_CMD").isEmpty())
project->values("QMAKE_AR_CMD").append("$(AR) $(DESTDIR)$(TARGET) $(OBJECTS)");
@@ -1278,6 +1245,7 @@ void UnixMakefileGenerator::init2()
QString prefix;
if(!project->isActiveConfig("no_plugin_name_prefix"))
prefix = "lib";
+ project->values("PRL_TARGET").prepend(prefix + project->first("TARGET"));
project->values("TARGET_x.y.z").append(prefix +
project->first("TARGET") + "." +
project->first("QMAKE_EXTENSION_PLUGIN"));
@@ -1291,6 +1259,7 @@ void UnixMakefileGenerator::init2()
"." + project->first("VER_MAJ"));
project->values("TARGET") = project->values("TARGET_x.y.z");
} else if (!project->isEmpty("QMAKE_HPUX_SHLIB")) {
+ project->values("PRL_TARGET").prepend("lib" + project->first("TARGET"));
project->values("TARGET_").append("lib" + project->first("TARGET") + ".sl");
if(project->isActiveConfig("lib_version_first"))
project->values("TARGET_x").append("lib" + project->first("VER_MAJ") + "." +
@@ -1300,6 +1269,7 @@ void UnixMakefileGenerator::init2()
project->first("VER_MAJ"));
project->values("TARGET") = project->values("TARGET_x");
} else if (!project->isEmpty("QMAKE_AIX_SHLIB")) {
+ project->values("PRL_TARGET").prepend("lib" + project->first("TARGET"));
project->values("TARGET_").append(project->first("QMAKE_PREFIX_STATICLIB") + project->first("TARGET")
+ "." + project->first("QMAKE_EXTENSION_STATICLIB"));
if(project->isActiveConfig("lib_version_first")) {
@@ -1331,6 +1301,7 @@ void UnixMakefileGenerator::init2()
}
project->values("TARGET") = project->values("TARGET_x.y.z");
} else {
+ project->values("PRL_TARGET").prepend("lib" + project->first("TARGET"));
project->values("TARGET_").append("lib" + project->first("TARGET") + "." +
project->first("QMAKE_EXTENSION_SHLIB"));
if(project->isActiveConfig("lib_version_first")) {
@@ -1510,10 +1481,7 @@ UnixMakefileGenerator::writeLibtoolFile()
t << "# Libraries that this one depends upon.\n";
ProStringList libs;
- if(!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS"))
- libs = project->values("QMAKE_INTERNAL_PRL_LIBS");
- else
- libs << "QMAKE_LIBS"; //obvious one
+ libs << "LIBS" << "QMAKE_LIBS";
t << "dependency_libs='";
for (ProStringList::ConstIterator it = libs.begin(); it != libs.end(); ++it)
t << fixLibFlags((*it).toKey()).join(' ') << ' ';
diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp
index 6fcfe96380..de7363e51b 100644
--- a/qmake/generators/win32/mingw_make.cpp
+++ b/qmake/generators/win32/mingw_make.cpp
@@ -73,6 +73,19 @@ MingwMakefileGenerator::parseLibFlag(const ProString &flag, ProString *arg)
return MakefileGenerator::parseLibFlag(flag, arg);
}
+bool MingwMakefileGenerator::processPrlFileBase(QString &origFile, const QStringRef &origName,
+ const QStringRef &fixedBase, int slashOff)
+{
+ if (origName.startsWith("lib")) {
+ QString newFixedBase = fixedBase.left(slashOff) + fixedBase.mid(slashOff + 3);
+ if (Win32MakefileGenerator::processPrlFileBase(origFile, origName,
+ QStringRef(&newFixedBase), slashOff)) {
+ return true;
+ }
+ }
+ return Win32MakefileGenerator::processPrlFileBase(origFile, origName, fixedBase, slashOff);
+}
+
bool MingwMakefileGenerator::writeMakefile(QTextStream &t)
{
writeHeader(t);
@@ -118,22 +131,25 @@ QString MingwMakefileGenerator::installRoot() const
return QStringLiteral("$(INSTALL_ROOT:@msyshack@%=%)");
}
-void createLdObjectScriptFile(const QString &fileName, const ProStringList &objList)
+void createLdResponseFile(const QString &fileName, const ProStringList &objList)
{
QString filePath = Option::output_dir + QDir::separator() + fileName;
QFile file(filePath);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream t(&file);
- t << "INPUT(\n";
for (ProStringList::ConstIterator it = objList.constBegin(); it != objList.constEnd(); ++it) {
QString path = (*it).toQString();
- // ### quoting?
- if (QDir::isRelativePath(path))
- t << "./" << path << endl;
- else
- t << path << endl;
+ // In response files, whitespace and special characters are
+ // escaped with a backslash; backslashes themselves can either
+ // be escaped into double backslashes, or, as this is a list of
+ // path names, converted to forward slashes.
+ path.replace(QLatin1Char('\\'), QLatin1String("/"))
+ .replace(QLatin1Char(' '), QLatin1String("\\ "))
+ .replace(QLatin1Char('\t'), QLatin1String("\\\t"))
+ .replace(QLatin1Char('"'), QLatin1String("\\\""))
+ .replace(QLatin1Char('\''), QLatin1String("\\'"));
+ t << path << endl;
}
- t << ");\n";
t.flush();
file.close();
}
@@ -191,11 +207,9 @@ void MingwMakefileGenerator::init()
return;
}
- project->values("TARGET_PRL").append(project->first("TARGET"));
-
processVars();
- project->values("QMAKE_LIBS") += project->values("RES_FILE");
+ project->values("LIBS") += project->values("RES_FILE");
if (project->isActiveConfig("dll")) {
QString destDir = "";
@@ -271,6 +285,8 @@ void MingwMakefileGenerator::writeLibsPart(QTextStream &t)
t << "LINKER = " << var("QMAKE_LINK") << endl;
t << "LFLAGS = " << var("QMAKE_LFLAGS") << endl;
t << "LIBS = "
+ << fixLibFlags("LIBS").join(' ') << ' '
+ << fixLibFlags("LIBS_PRIVATE").join(' ') << ' '
<< fixLibFlags("QMAKE_LIBS").join(' ') << ' '
<< fixLibFlags("QMAKE_LIBS_PRIVATE").join(' ') << endl;
}
@@ -296,14 +312,13 @@ void MingwMakefileGenerator::writeObjectsPart(QTextStream &t)
createArObjectScriptFile(ar_script_file, var("DEST_TARGET"), project->values("OBJECTS"));
objectsLinkLine = ar_cmd + " -M < " + escapeFilePath(ar_script_file);
} else {
- QString ld_script_file = var("QMAKE_LINK_OBJECT_SCRIPT") + "." + var("TARGET");
- if (!var("BUILD_NAME").isEmpty()) {
- ld_script_file += "." + var("BUILD_NAME");
- }
+ QString ld_response_file = var("QMAKE_LINK_OBJECT_SCRIPT") + "." + var("TARGET");
+ if (!var("BUILD_NAME").isEmpty())
+ ld_response_file += "." + var("BUILD_NAME");
if (!var("MAKEFILE").isEmpty())
- ld_script_file += "." + var("MAKEFILE");
- createLdObjectScriptFile(ld_script_file, project->values("OBJECTS"));
- objectsLinkLine = escapeFilePath(ld_script_file);
+ ld_response_file += "." + var("MAKEFILE");
+ createLdResponseFile(ld_response_file, project->values("OBJECTS"));
+ objectsLinkLine = "@" + escapeFilePath(ld_response_file);
}
Win32MakefileGenerator::writeObjectsPart(t);
}
@@ -312,8 +327,9 @@ void MingwMakefileGenerator::writeBuildRulesPart(QTextStream &t)
{
t << "first: all\n";
t << "all: " << escapeDependencyPath(fileFixify(Option::output.fileName()))
- << ' ' << depVar("ALL_DEPS") << " $(DESTDIR_TARGET)\n\n";
- t << "$(DESTDIR_TARGET): " << depVar("PRE_TARGETDEPS") << " $(OBJECTS) " << depVar("POST_TARGETDEPS");
+ << ' ' << depVar("ALL_DEPS") << ' ' << depVar("DEST_TARGET") << "\n\n";
+ t << depVar("DEST_TARGET") << ": "
+ << depVar("PRE_TARGETDEPS") << " $(OBJECTS) " << depVar("POST_TARGETDEPS");
if (project->first("TEMPLATE") == "aux") {
t << "\n\n";
return;
diff --git a/qmake/generators/win32/mingw_make.h b/qmake/generators/win32/mingw_make.h
index 6f041cfd4a..5da5b24088 100644
--- a/qmake/generators/win32/mingw_make.h
+++ b/qmake/generators/win32/mingw_make.h
@@ -40,25 +40,27 @@ public:
~MingwMakefileGenerator();
protected:
using MakefileGenerator::escapeDependencyPath;
- virtual QString escapeDependencyPath(const QString &path) const;
- virtual ProString fixLibFlag(const ProString &lib);
- virtual QString getManifestFileForRcFile() const;
- bool writeMakefile(QTextStream &);
- void init();
- virtual QString installRoot() const;
+ QString escapeDependencyPath(const QString &path) const override;
+ ProString fixLibFlag(const ProString &lib) override;
+ bool processPrlFileBase(QString &origFile, const QStringRef &origName,
+ const QStringRef &fixedBase, int slashOff) override;
+ QString getManifestFileForRcFile() const override;
+ bool writeMakefile(QTextStream &) override;
+ void init() override;
+ QString installRoot() const override;
private:
void writeMingwParts(QTextStream &);
- void writeIncPart(QTextStream &t);
- void writeLibsPart(QTextStream &t);
- void writeObjectsPart(QTextStream &t);
- void writeBuildRulesPart(QTextStream &t);
- void writeRcFilePart(QTextStream &t);
+ void writeIncPart(QTextStream &t) override;
+ void writeLibsPart(QTextStream &t) override;
+ void writeObjectsPart(QTextStream &t) override;
+ void writeBuildRulesPart(QTextStream &t) override;
+ void writeRcFilePart(QTextStream &t) override;
- QStringList &findDependencies(const QString &file);
+ QStringList &findDependencies(const QString &file) override;
QString preCompHeaderOut;
- virtual LibFlagType parseLibFlag(const ProString &flag, ProString *arg);
+ LibFlagType parseLibFlag(const ProString &flag, ProString *arg) override;
QString objectsLinkLine;
};
diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp
index 082f357d32..ad2976aa01 100644
--- a/qmake/generators/win32/msbuild_objectmodel.cpp
+++ b/qmake/generators/win32/msbuild_objectmodel.cpp
@@ -1207,7 +1207,7 @@ static inline QString toString(midlCharOption option)
static inline QString toString(midlErrorCheckOption option)
{
switch (option) {
- case midlAlignNotSet:
+ case midlEnableCustom:
break;
case midlDisableAll:
return "None";
diff --git a/qmake/generators/win32/msbuild_objectmodel.h b/qmake/generators/win32/msbuild_objectmodel.h
index 2e77537916..ce5711f2da 100644
--- a/qmake/generators/win32/msbuild_objectmodel.h
+++ b/qmake/generators/win32/msbuild_objectmodel.h
@@ -72,7 +72,7 @@ public:
return Uindex;
}
- void addElement(const QString &filepath, const VCFilterFile &allInfo){
+ void addElement(const QString &filepath, const VCFilterFile &allInfo) override {
QString newNodeName(filepath);
int index = pathIndex(filepath);
@@ -89,7 +89,7 @@ public:
n->addElement(filepath.mid(index+1), allInfo);
}
- void removeElements() {
+ void removeElements() override {
ChildrenMap::ConstIterator it = children.constBegin();
ChildrenMap::ConstIterator end = children.constEnd();
for( ; it != end; it++) {
@@ -100,8 +100,8 @@ public:
}
void generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &tagName, VCProject &tool,
- const QString &filter);
- bool hasElements() {
+ const QString &filter) override;
+ bool hasElements() override {
return children.size() != 0;
}
};
@@ -124,7 +124,7 @@ public:
return Uindex;
}
- void addElement(const QString &filepath, const VCFilterFile &allInfo){
+ void addElement(const QString &filepath, const VCFilterFile &allInfo) override {
QString newKey(filepath);
int index = pathIndex(filepath);
@@ -136,13 +136,13 @@ public:
children.insert(newKey + "\0" + allInfo.file, allInfo);
}
- void removeElements() {
+ void removeElements() override {
children.clear();
}
void generateXML(XmlOutput &xml, XmlOutput &xmlFilter, const QString &tagName, VCProject &proj,
- const QString &filter);
- bool hasElements() {
+ const QString &filter) override;
+ bool hasElements() override {
return children.size() != 0;
}
};
@@ -150,20 +150,20 @@ public:
class VCXProjectWriter : public VCProjectWriter
{
public:
- void write(XmlOutput &, VCProjectSingleConfig &);
- void write(XmlOutput &, VCProject &);
-
- void write(XmlOutput &, const VCCLCompilerTool &);
- void write(XmlOutput &, const VCLinkerTool &);
- void write(XmlOutput &, const VCMIDLTool &);
- void write(XmlOutput &, const VCCustomBuildTool &);
- void write(XmlOutput &, const VCLibrarianTool &);
- void write(XmlOutput &, const VCResourceCompilerTool &);
- void write(XmlOutput &, const VCEventTool &);
- void write(XmlOutput &, const VCDeploymentTool &);
- void write(XmlOutput &, const VCWinDeployQtTool &);
- void write(XmlOutput &, const VCConfiguration &);
- void write(XmlOutput &, VCFilter &);
+ void write(XmlOutput &, VCProjectSingleConfig &) override;
+ void write(XmlOutput &, VCProject &) override;
+
+ void write(XmlOutput &, const VCCLCompilerTool &) override;
+ void write(XmlOutput &, const VCLinkerTool &) override;
+ void write(XmlOutput &, const VCMIDLTool &) override;
+ void write(XmlOutput &, const VCCustomBuildTool &) override;
+ void write(XmlOutput &, const VCLibrarianTool &) override;
+ void write(XmlOutput &, const VCResourceCompilerTool &) override;
+ void write(XmlOutput &, const VCEventTool &) override;
+ void write(XmlOutput &, const VCDeploymentTool &) override;
+ void write(XmlOutput &, const VCWinDeployQtTool &) override;
+ void write(XmlOutput &, const VCConfiguration &) override;
+ void write(XmlOutput &, VCFilter &) override;
private:
struct OutputFilterData
diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp
index 92b4eb5054..f2cd7c633b 100644
--- a/qmake/generators/win32/msvc_nmake.cpp
+++ b/qmake/generators/win32/msvc_nmake.cpp
@@ -383,7 +383,7 @@ void NmakeMakefileGenerator::init()
processVars();
- project->values("QMAKE_LIBS") += project->values("RES_FILE");
+ project->values("LIBS") += project->values("RES_FILE");
if (!project->values("DEF_FILE").isEmpty()) {
QString defFileName = fileFixify(project->first("DEF_FILE").toQString());
@@ -499,7 +499,7 @@ void NmakeMakefileGenerator::writeImplicitRulesPart(QTextStream &t)
QSet<QString> source_directories;
if (useInferenceRules) {
source_directories.insert(".");
- static const char * const directories[] = { "UI_SOURCES_DIR", "UI_DIR", 0 };
+ static const char * const directories[] = { "UI_SOURCES_DIR", "UI_DIR", nullptr };
for (int y = 0; directories[y]; y++) {
QString dirTemp = project->first(directories[y]).toQString();
if (dirTemp.endsWith("\\"))
@@ -507,7 +507,7 @@ void NmakeMakefileGenerator::writeImplicitRulesPart(QTextStream &t)
if(!dirTemp.isEmpty())
source_directories.insert(dirTemp);
}
- static const char * const srcs[] = { "SOURCES", "GENERATED_SOURCES", 0 };
+ static const char * const srcs[] = { "SOURCES", "GENERATED_SOURCES", nullptr };
for (int x = 0; srcs[x]; x++) {
const ProStringList &l = project->values(srcs[x]);
for (ProStringList::ConstIterator sit = l.begin(); sit != l.end(); ++sit) {
@@ -584,8 +584,9 @@ void NmakeMakefileGenerator::writeBuildRulesPart(QTextStream &t)
t << "first: all\n";
t << "all: " << escapeDependencyPath(fileFixify(Option::output.fileName()))
- << ' ' << depVar("ALL_DEPS") << " $(DESTDIR_TARGET)\n\n";
- t << "$(DESTDIR_TARGET): " << depVar("PRE_TARGETDEPS") << " $(OBJECTS) " << depVar("POST_TARGETDEPS");
+ << ' ' << depVar("ALL_DEPS") << ' ' << depVar("DEST_TARGET") << "\n\n";
+ t << depVar("DEST_TARGET") << ": "
+ << depVar("PRE_TARGETDEPS") << " $(OBJECTS) " << depVar("POST_TARGETDEPS");
if (templateName == "aux") {
t << "\n\n";
return;
diff --git a/qmake/generators/win32/msvc_nmake.h b/qmake/generators/win32/msvc_nmake.h
index 67b609d0a6..67a56c7813 100644
--- a/qmake/generators/win32/msvc_nmake.h
+++ b/qmake/generators/win32/msvc_nmake.h
@@ -36,21 +36,21 @@ QT_BEGIN_NAMESPACE
class NmakeMakefileGenerator : public Win32MakefileGenerator
{
void writeNmakeParts(QTextStream &);
- bool writeMakefile(QTextStream &);
- void writeImplicitRulesPart(QTextStream &t);
- void writeBuildRulesPart(QTextStream &t);
+ bool writeMakefile(QTextStream &) override;
+ void writeImplicitRulesPart(QTextStream &t) override;
+ void writeBuildRulesPart(QTextStream &t) override;
void writeLinkCommand(QTextStream &t, const QString &extraFlags = QString(), const QString &extraInlineFileContent = QString());
void writeResponseFileFiles(QTextStream &t, const ProStringList &files);
int msvcVersion() const;
- void init();
+ void init() override;
static QStringList sourceFilesForImplicitRulesFilter();
protected:
- virtual void writeSubMakeCall(QTextStream &t, const QString &callPrefix,
- const QString &makeArguments);
- virtual QString defaultInstall(const QString &t);
- virtual QStringList &findDependencies(const QString &file);
- QString var(const ProKey &value) const;
+ void writeSubMakeCall(QTextStream &t, const QString &callPrefix,
+ const QString &makeArguments) override;
+ QString defaultInstall(const QString &t) override;
+ QStringList &findDependencies(const QString &file) override;
+ QString var(const ProKey &value) const override;
QString precompH, precompObj, precompPch;
QString precompObjC, precompPchC;
bool usePCH, usePCHC;
diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp
index 452a215024..4f0cee65e1 100644
--- a/qmake/generators/win32/msvc_objectmodel.cpp
+++ b/qmake/generators/win32/msvc_objectmodel.cpp
@@ -2183,7 +2183,7 @@ VCConfiguration::VCConfiguration()
// VCFilter ---------------------------------------------------------
VCFilter::VCFilter()
: ParseFiles(unset),
- Config(0)
+ Config(nullptr)
{
useCustomBuildTool = false;
useCompilerTool = false;
diff --git a/qmake/generators/win32/msvc_objectmodel.h b/qmake/generators/win32/msvc_objectmodel.h
index 10d44970ff..9d1a170489 100644
--- a/qmake/generators/win32/msvc_objectmodel.h
+++ b/qmake/generators/win32/msvc_objectmodel.h
@@ -484,7 +484,7 @@ public:
// Functions
VCCLCompilerTool();
- bool parseOption(const char* option);
+ bool parseOption(const char* option) override;
// Variables
QStringList AdditionalIncludeDirectories;
@@ -581,7 +581,7 @@ public:
// Functions
VCLinkerTool();
- bool parseOption(const char* option);
+ bool parseOption(const char* option) override;
// Variables
QStringList AdditionalDependencies;
@@ -676,7 +676,7 @@ class VCManifestTool : public VCToolBase
public:
VCManifestTool();
- bool parseOption(const char* option);
+ bool parseOption(const char* option) override;
triState EmbedManifest;
};
@@ -687,7 +687,7 @@ public:
// Functions
VCMIDLTool();
- bool parseOption(const char* option);
+ bool parseOption(const char* option) override;
// Variables
QStringList AdditionalIncludeDirectories;
@@ -741,7 +741,7 @@ public:
// Functions
VCLibrarianTool();
- bool parseOption(const char*){ return false; }
+ bool parseOption(const char*) override { return false; }
// Variables
QStringList AdditionalDependencies;
@@ -762,7 +762,7 @@ public:
// Functions
VCCustomBuildTool();
- bool parseOption(const char*){ return false; }
+ bool parseOption(const char*) override { return false; }
// Variables
QStringList AdditionalDependencies;
@@ -781,7 +781,7 @@ public:
// Functions
VCResourceCompilerTool();
- bool parseOption(const char*){ return false; }
+ bool parseOption(const char*) override { return false; }
// Variables
QStringList AdditionalIncludeDirectories;
@@ -815,7 +815,7 @@ protected:
// Functions
VCEventTool(const QString &eventName);
- bool parseOption(const char*){ return false; }
+ bool parseOption(const char*) override { return false; }
public:
// Variables
@@ -851,7 +851,7 @@ public:
VCWinDeployQtTool() {}
protected:
- bool parseOption(const char *) { return false; }
+ bool parseOption(const char *) override { return false; }
public:
// Variables
@@ -1037,7 +1037,7 @@ public:
return Uindex;
}
- void addElement(const QString &filepath, const VCFilterFile &allInfo){
+ void addElement(const QString &filepath, const VCFilterFile &allInfo) override {
QString newNodeName(filepath);
int index = pathIndex(filepath);
@@ -1054,7 +1054,7 @@ public:
n->addElement(filepath.mid(index+1), allInfo);
}
- void removeElements() {
+ void removeElements() override {
ChildrenMap::ConstIterator it = children.constBegin();
ChildrenMap::ConstIterator end = children.constEnd();
for( ; it != end; it++) {
@@ -1064,8 +1064,8 @@ public:
children.clear();
}
- void generateXML(XmlOutput &xml, const QString &tagName, VCProject &tool, const QString &filter);
- bool hasElements() {
+ void generateXML(XmlOutput &xml, const QString &tagName, VCProject &tool, const QString &filter) override;
+ bool hasElements() override {
return children.size() != 0;
}
};
@@ -1088,7 +1088,7 @@ public:
return Uindex;
}
- void addElement(const QString &filepath, const VCFilterFile &allInfo){
+ void addElement(const QString &filepath, const VCFilterFile &allInfo) override {
QString newKey(filepath);
int index = pathIndex(filepath);
@@ -1100,12 +1100,12 @@ public:
children.insert(newKey + "\0" + allInfo.file, allInfo);
}
- void removeElements() {
+ void removeElements() override {
children.clear();
}
- void generateXML(XmlOutput &xml, const QString &tagName, VCProject &proj, const QString &filter);
- bool hasElements() {
+ void generateXML(XmlOutput &xml, const QString &tagName, VCProject &proj, const QString &filter) override;
+ bool hasElements() override {
return children.size() != 0;
}
};
diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp
index 24d1657552..f7837fc1b4 100644
--- a/qmake/generators/win32/msvc_vcproj.cpp
+++ b/qmake/generators/win32/msvc_vcproj.cpp
@@ -112,7 +112,7 @@ VcprojGenerator::VcprojGenerator()
: Win32MakefileGenerator(),
is64Bit(false),
customBuildToolFilterFileSuffix(QStringLiteral(".cbt")),
- projectWriter(0)
+ projectWriter(nullptr)
{
}
@@ -208,16 +208,6 @@ struct VcsolutionDepend {
QStringList dependencies;
};
-/* Disable optimization in getProjectUUID() due to a compiler
- * bug in MSVC 2010 that causes ASSERT: "&other != this" in the QString
- * copy constructor for non-empty file names at:
- * filename.isEmpty()?project->first("QMAKE_MAKEFILE"):filename */
-
-#ifdef Q_CC_MSVC
-# pragma optimize( "g", off )
-# pragma warning ( disable : 4748 )
-#endif
-
QUuid VcprojGenerator::getProjectUUID(const QString &filename)
{
bool validUUID = true;
@@ -249,10 +239,6 @@ QUuid VcprojGenerator::getProjectUUID(const QString &filename)
return uuid;
}
-#ifdef Q_CC_MSVC
-# pragma optimize( "g", on )
-#endif
-
QUuid VcprojGenerator::increaseUUID(const QUuid &id)
{
QUuid result(id);
@@ -471,9 +457,8 @@ ProStringList VcprojGenerator::collectDependencies(QMakeProject *proj, QHash<QSt
newDep->dependencies << "idc.exe";
// Add all unknown libs to the deps
- QStringList where = QStringList() << "QMAKE_LIBS" << "QMAKE_LIBS_PRIVATE";
- if (!tmp_proj.isEmpty("QMAKE_INTERNAL_PRL_LIBS"))
- where = tmp_proj.values("QMAKE_INTERNAL_PRL_LIBS").toQStringList();
+ QStringList where = QStringList() << "LIBS" << "LIBS_PRIVATE"
+ << "QMAKE_LIBS" << "QMAKE_LIBS_PRIVATE";
for (QStringList::ConstIterator wit = where.begin();
wit != where.end(); ++wit) {
const ProStringList &l = tmp_proj.values(ProKey(*wit));
@@ -764,7 +749,7 @@ void VcprojGenerator::init()
projectTarget = Application;
} else if(project->first("TEMPLATE") == "vclib") {
if(project->isActiveConfig("staticlib")) {
- project->values("QMAKE_LIBS") += project->values("RES_FILE");
+ project->values("LIBS") += project->values("RES_FILE");
projectTarget = StaticLib;
} else
projectTarget = SharedLib;
@@ -1100,7 +1085,8 @@ void VcprojGenerator::initLinkerTool()
if (!project->values("DEF_FILE").isEmpty())
conf.linker.ModuleDefinitionFile = project->first("DEF_FILE").toQString();
- static const char * const lflags[] = { "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", 0 };
+ static const char * const lflags[] = { "LIBS", "LIBS_PRIVATE",
+ "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", nullptr };
for (int i = 0; lflags[i]; i++) {
const auto libs = fixLibFlags(lflags[i]);
for (const ProString &lib : libs) {
@@ -1195,7 +1181,8 @@ void VcprojGenerator::initDeploymentTool()
if (!dllPaths.isEmpty() &&
!(conf.WinRT && project->first("MSVC_VER").toQString() == "14.0")) {
// FIXME: This code should actually resolve the libraries from all Qt modules.
- ProStringList arg = project->values("QMAKE_LIBS") + project->values("QMAKE_LIBS_PRIVATE");
+ ProStringList arg = project->values("LIBS") + project->values("LIBS_PRIVATE")
+ + project->values("QMAKE_LIBS") + project->values("QMAKE_LIBS_PRIVATE");
bool qpaPluginDeployed = false;
for (ProStringList::ConstIterator it = arg.constBegin(); it != arg.constEnd(); ++it) {
QString dllName = (*it).toQString();
@@ -1617,20 +1604,15 @@ QString VcprojGenerator::replaceExtraCompilerVariables(
bool VcprojGenerator::openOutput(QFile &file, const QString &/*build*/) const
{
- QString outdir;
- if(!file.fileName().isEmpty()) {
- QFileInfo fi(fileInfo(file.fileName()));
- if(fi.isDir())
- outdir = file.fileName() + QDir::separator();
- }
- if(!outdir.isEmpty() || file.fileName().isEmpty()) {
- ProString ext = project->first("VCPROJ_EXTENSION");
- if(project->first("TEMPLATE") == "vcsubdirs")
- ext = project->first("VCSOLUTION_EXTENSION");
- ProString outputName = project->first("TARGET");
- if (!project->first("MAKEFILE").isEmpty())
- outputName = project->first("MAKEFILE");
- file.setFileName(outdir + outputName + ext);
+ ProString fileName = file.fileName();
+ ProString extension = project->first("TEMPLATE") == "vcsubdirs"
+ ? project->first("VCSOLUTION_EXTENSION") : project->first("VCPROJ_EXTENSION");
+ if (!fileName.endsWith(extension)) {
+ if (fileName.isEmpty()) {
+ fileName = !project->first("MAKEFILE").isEmpty()
+ ? project->first("MAKEFILE") : project->first("TARGET");
+ }
+ file.setFileName(fileName + extension);
}
return Win32MakefileGenerator::openOutput(file, QString());
}
diff --git a/qmake/generators/win32/msvc_vcproj.h b/qmake/generators/win32/msvc_vcproj.h
index 4882296b46..6af5ec7007 100644
--- a/qmake/generators/win32/msvc_vcproj.h
+++ b/qmake/generators/win32/msvc_vcproj.h
@@ -47,10 +47,10 @@ class VcprojGenerator : public Win32MakefileGenerator
bool is64Bit;
bool writeVcprojParts(QTextStream &);
- bool writeMakefile(QTextStream &);
- bool writeProjectMakefile();
+ bool writeMakefile(QTextStream &) override;
+ bool writeProjectMakefile() override;
- void init();
+ void init() override;
public:
VcprojGenerator();
@@ -70,14 +70,14 @@ public:
protected:
virtual VCProjectWriter *createProjectWriter();
- virtual bool doDepends() const { return false; } //never necesary
+ bool doDepends() const override { return false; } // Never necessary
using Win32MakefileGenerator::replaceExtraCompilerVariables;
- virtual QString replaceExtraCompilerVariables(const QString &, const QStringList &, const QStringList &, ReplaceFor);
- virtual bool supportsMetaBuild() { return true; }
- virtual bool supportsMergedBuilds() { return true; }
- virtual bool mergeBuildProject(MakefileGenerator *other);
+ QString replaceExtraCompilerVariables(const QString &, const QStringList &, const QStringList &, ReplaceFor) override;
+ bool supportsMetaBuild() override { return true; }
+ bool supportsMergedBuilds() override { return true; }
+ bool mergeBuildProject(MakefileGenerator *other) override;
- virtual bool openOutput(QFile &file, const QString &build) const;
+ bool openOutput(QFile &file, const QString &build) const override;
virtual void initProject();
void initConfiguration();
diff --git a/qmake/generators/win32/msvc_vcxproj.h b/qmake/generators/win32/msvc_vcxproj.h
index 8f68348693..7e02b6c32f 100644
--- a/qmake/generators/win32/msvc_vcxproj.h
+++ b/qmake/generators/win32/msvc_vcxproj.h
@@ -39,7 +39,7 @@ public:
VcxprojGenerator();
protected:
- virtual VCProjectWriter *createProjectWriter();
+ VCProjectWriter *createProjectWriter() override;
};
QT_END_NAMESPACE
diff --git a/qmake/generators/win32/registry.cpp b/qmake/generators/win32/registry.cpp
index 7320cb0551..3391ab9512 100644
--- a/qmake/generators/win32/registry.cpp
+++ b/qmake/generators/win32/registry.cpp
@@ -77,7 +77,7 @@ QString qt_readRegistryKey(HKEY parentHandle, const QString &rSubkey, unsigned l
QString rSubkeyName = keyName(rSubkey);
QString rSubkeyPath = keyPath(rSubkey);
- HKEY handle = 0;
+ HKEY handle = nullptr;
LONG res = RegOpenKeyEx(parentHandle, (wchar_t*)rSubkeyPath.utf16(), 0,
KEY_READ | options, &handle);
@@ -87,7 +87,7 @@ QString qt_readRegistryKey(HKEY parentHandle, const QString &rSubkey, unsigned l
// get the size and type of the value
DWORD dataType;
DWORD dataSize;
- res = RegQueryValueEx(handle, (wchar_t*)rSubkeyName.utf16(), 0, &dataType, 0, &dataSize);
+ res = RegQueryValueEx(handle, (wchar_t*)rSubkeyName.utf16(), nullptr, &dataType, nullptr, &dataSize);
if (res != ERROR_SUCCESS) {
RegCloseKey(handle);
return QString();
@@ -95,7 +95,7 @@ QString qt_readRegistryKey(HKEY parentHandle, const QString &rSubkey, unsigned l
// get the value
QByteArray data(dataSize, 0);
- res = RegQueryValueEx(handle, (wchar_t*)rSubkeyName.utf16(), 0, 0,
+ res = RegQueryValueEx(handle, (wchar_t*)rSubkeyName.utf16(), nullptr, nullptr,
reinterpret_cast<unsigned char*>(data.data()), &dataSize);
if (res != ERROR_SUCCESS) {
RegCloseKey(handle);
diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp
index bca27b7044..e0d03ccc1c 100644
--- a/qmake/generators/win32/winmakefile.cpp
+++ b/qmake/generators/win32/winmakefile.cpp
@@ -84,7 +84,8 @@ Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags)
if (impexts.isEmpty())
impexts = project->values("QMAKE_EXTENSION_STATICLIB");
QList<QMakeLocalFileName> dirs;
- static const char * const lflags[] = { "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", 0 };
+ static const char * const lflags[] = { "LIBS", "LIBS_PRIVATE",
+ "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", nullptr };
for (int i = 0; lflags[i]; i++) {
ProStringList &l = project->values(lflags[i]);
for (ProStringList::Iterator it = l.begin(); it != l.end();) {
@@ -106,7 +107,7 @@ Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags)
for (QList<QMakeLocalFileName>::Iterator dir_it = dirs.begin();
dir_it != dirs.end(); ++dir_it) {
QString cand = (*dir_it).real() + Option::dir_sep + lib;
- if (linkPrl && processPrlFile(cand)) {
+ if (linkPrl && processPrlFile(cand, true)) {
(*it) = cand;
goto found;
}
@@ -124,13 +125,13 @@ Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags)
} else if (linkPrl && type == LibFlagFile) {
QString lib = opt.toQString();
if (fileInfo(lib).isAbsolute()) {
- if (processPrlFile(lib))
+ if (processPrlFile(lib, false))
(*it) = lib;
} else {
for (QList<QMakeLocalFileName>::Iterator dir_it = dirs.begin();
dir_it != dirs.end(); ++dir_it) {
QString cand = (*dir_it).real() + Option::dir_sep + lib;
- if (processPrlFile(cand)) {
+ if (processPrlFile(cand, false)) {
(*it) = cand;
break;
}
@@ -163,12 +164,30 @@ Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags)
return true;
}
+bool Win32MakefileGenerator::processPrlFileBase(QString &origFile, const QStringRef &origName,
+ const QStringRef &fixedBase, int slashOff)
+{
+ if (MakefileGenerator::processPrlFileBase(origFile, origName, fixedBase, slashOff))
+ return true;
+ for (int off = fixedBase.length(); off > slashOff; off--) {
+ if (!fixedBase.at(off - 1).isDigit()) {
+ if (off != fixedBase.length()) {
+ return MakefileGenerator::processPrlFileBase(
+ origFile, origName, fixedBase.left(off), slashOff);
+ }
+ break;
+ }
+ }
+ return false;
+}
+
void Win32MakefileGenerator::processVars()
{
if (project->first("TEMPLATE").endsWith("aux"))
return;
- project->values("QMAKE_ORIG_TARGET") = project->values("TARGET");
+ project->values("PRL_TARGET") =
+ project->values("QMAKE_ORIG_TARGET") = project->values("TARGET");
if (project->isEmpty("QMAKE_PROJECT_NAME"))
project->values("QMAKE_PROJECT_NAME") = project->values("QMAKE_ORIG_TARGET");
else if (project->first("TEMPLATE").startsWith("vc"))
@@ -207,8 +226,8 @@ void Win32MakefileGenerator::processVars()
libs << QLatin1String("-L") + lib;
}
}
- project->values("QMAKE_LIBS") += libs + project->values("LIBS");
- project->values("QMAKE_LIBS_PRIVATE") += project->values("LIBS_PRIVATE");
+ ProStringList &qmklibs = project->values("LIBS");
+ qmklibs = libs + qmklibs;
if (project->values("TEMPLATE").contains("app")) {
project->values("QMAKE_CFLAGS") += project->values("QMAKE_CFLAGS_APP");
@@ -422,7 +441,7 @@ void Win32MakefileGenerator::writeCleanParts(QTextStream &t)
{
t << "clean: compiler_clean " << depVar("CLEAN_DEPS");
{
- const char *clean_targets[] = { "OBJECTS", "QMAKE_CLEAN", "CLEAN_FILES", 0 };
+ const char *clean_targets[] = { "OBJECTS", "QMAKE_CLEAN", "CLEAN_FILES", nullptr };
for(int i = 0; clean_targets[i]; ++i) {
const ProStringList &list = project->values(clean_targets[i]);
const QString del_statement("-$(DEL_FILE)");
@@ -451,7 +470,7 @@ void Win32MakefileGenerator::writeCleanParts(QTextStream &t)
t << "distclean: clean " << depVar("DISTCLEAN_DEPS");
{
- const char *clean_targets[] = { "QMAKE_DISTCLEAN", 0 };
+ const char *clean_targets[] = { "QMAKE_DISTCLEAN", nullptr };
for(int i = 0; clean_targets[i]; ++i) {
const ProStringList &list = project->values(clean_targets[i]);
const QString del_statement("-$(DEL_FILE)");
@@ -563,7 +582,7 @@ void Win32MakefileGenerator::writeStandardParts(QTextStream &t)
t << "DIST = " << fileVarList("DISTFILES") << ' '
<< fileVarList("HEADERS") << ' ' << fileVarList("SOURCES") << endl;
- t << "QMAKE_TARGET = " << fileVar("QMAKE_ORIG_TARGET") << endl;
+ t << "QMAKE_TARGET = " << fileVar("QMAKE_ORIG_TARGET") << endl; // unused
// The comment is important to maintain variable compatibility with Unix
// Makefiles, while not interpreting a trailing-slash as a linebreak
t << "DESTDIR = " << escapeFilePath(destDir) << " #avoid trailing-slash linebreak\n";
@@ -633,7 +652,9 @@ void Win32MakefileGenerator::writeLibsPart(QTextStream &t)
} else {
t << "LINKER = " << var("QMAKE_LINK") << endl;
t << "LFLAGS = " << var("QMAKE_LFLAGS") << endl;
- t << "LIBS = " << fixLibFlags("QMAKE_LIBS").join(' ') << ' '
+ t << "LIBS = " << fixLibFlags("LIBS").join(' ') << ' '
+ << fixLibFlags("LIBS_PRIVATE").join(' ') << ' '
+ << fixLibFlags("QMAKE_LIBS").join(' ') << ' '
<< fixLibFlags("QMAKE_LIBS_PRIVATE").join(' ') << endl;
}
}
diff --git a/qmake/generators/win32/winmakefile.h b/qmake/generators/win32/winmakefile.h
index b85a6b67df..4416951a09 100644
--- a/qmake/generators/win32/winmakefile.h
+++ b/qmake/generators/win32/winmakefile.h
@@ -39,7 +39,7 @@ public:
Win32MakefileGenerator();
~Win32MakefileGenerator();
protected:
- virtual QString defaultInstall(const QString &);
+ QString defaultInstall(const QString &) override;
virtual void writeCleanParts(QTextStream &t);
virtual void writeStandardParts(QTextStream &t);
virtual void writeIncPart(QTextStream &t);
@@ -48,16 +48,18 @@ protected:
virtual void writeImplicitRulesPart(QTextStream &t);
virtual void writeBuildRulesPart(QTextStream &);
using MakefileGenerator::escapeFilePath;
- virtual QString escapeFilePath(const QString &path) const;
+ QString escapeFilePath(const QString &path) const override;
using MakefileGenerator::escapeDependencyPath;
- virtual QString escapeDependencyPath(const QString &path) const;
+ QString escapeDependencyPath(const QString &path) const override;
virtual void writeRcFilePart(QTextStream &t);
- virtual bool findLibraries(bool linkPrl, bool mergeLflags);
+ bool findLibraries(bool linkPrl, bool mergeLflags) override;
- virtual LibFlagType parseLibFlag(const ProString &flag, ProString *arg);
- virtual ProString fixLibFlag(const ProString &lib);
+ LibFlagType parseLibFlag(const ProString &flag, ProString *arg) override;
+ ProString fixLibFlag(const ProString &lib) override;
+ bool processPrlFileBase(QString &origFile, const QStringRef &origName,
+ const QStringRef &fixedBase, int slashOff) override;
void processVars();
void fixTargetExt();
diff --git a/qmake/library/ioutils.cpp b/qmake/library/ioutils.cpp
index fd84dff59d..2b2c6d0078 100644
--- a/qmake/library/ioutils.cpp
+++ b/qmake/library/ioutils.cpp
@@ -200,7 +200,7 @@ QString IoUtils::shellQuoteWin(const QString &arg)
# if defined(Q_OS_WIN)
static QString windowsErrorCode()
{
- wchar_t *string = 0;
+ wchar_t *string = nullptr;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
@@ -244,7 +244,7 @@ bool IoUtils::touchFile(const QString &targetFileName, const QString &referenceF
return false;
}
FILETIME ft;
- GetFileTime(rHand, 0, 0, &ft);
+ GetFileTime(rHand, NULL, NULL, &ft);
CloseHandle(rHand);
HANDLE wHand = CreateFile((wchar_t*)targetFileName.utf16(),
GENERIC_WRITE, FILE_SHARE_READ,
@@ -253,7 +253,7 @@ bool IoUtils::touchFile(const QString &targetFileName, const QString &referenceF
*errorString = fL1S("Cannot open %1: %2").arg(targetFileName, windowsErrorCode());
return false;
}
- SetFileTime(wHand, 0, 0, &ft);
+ SetFileTime(wHand, NULL, NULL, &ft);
CloseHandle(wHand);
# endif
return true;
diff --git a/qmake/library/proitems.h b/qmake/library/proitems.h
index 1d7ebed3aa..2b09fc2074 100644
--- a/qmake/library/proitems.h
+++ b/qmake/library/proitems.h
@@ -78,12 +78,12 @@ public:
int sourceFile() const { return m_file; }
ProString &prepend(const ProString &other);
- ProString &append(const ProString &other, bool *pending = 0);
+ ProString &append(const ProString &other, bool *pending = nullptr);
ProString &append(const QString &other) { return append(ProString(other)); }
ProString &append(const QLatin1String other);
ProString &append(const char *other) { return append(QLatin1String(other)); }
ProString &append(QChar other);
- ProString &append(const ProStringList &other, bool *pending = 0, bool skipEmpty1st = false);
+ ProString &append(const ProStringList &other, bool *pending = nullptr, bool skipEmpty1st = false);
ProString &operator+=(const ProString &other) { return append(other); }
ProString &operator+=(const QString &other) { return append(other); }
ProString &operator+=(const QLatin1String other) { return append(other); }
@@ -133,9 +133,9 @@ public:
bool contains(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return indexOf(s, 0, cs) >= 0; }
bool contains(const char *s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return indexOf(QLatin1String(s), 0, cs) >= 0; }
bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return indexOf(c, 0, cs) >= 0; }
- int toLongLong(bool *ok = 0, int base = 10) const { return toQStringRef().toLongLong(ok, base); }
- int toInt(bool *ok = 0, int base = 10) const { return toQStringRef().toInt(ok, base); }
- short toShort(bool *ok = 0, int base = 10) const { return toQStringRef().toShort(ok, base); }
+ int toLongLong(bool *ok = nullptr, int base = 10) const { return toQStringRef().toLongLong(ok, base); }
+ int toInt(bool *ok = nullptr, int base = 10) const { return toQStringRef().toInt(ok, base); }
+ short toShort(bool *ok = nullptr, int base = 10) const { return toQStringRef().toShort(ok, base); }
uint hash() const { return m_hash; }
static uint hash(const QChar *p, int n);
@@ -229,6 +229,55 @@ inline bool operator!=(const QString &that, const ProString &other)
QTextStream &operator<<(QTextStream &t, const ProString &str);
+// This class manages read-only access to a ProString via a raw data QString
+// temporary, ensuring that the latter is accessed exclusively.
+class ProStringRoUser
+{
+public:
+ ProStringRoUser(QString &rs)
+ {
+ Q_ASSERT(rs.isDetached() || rs.isEmpty());
+ m_rs = &rs;
+ }
+ ProStringRoUser(const ProString &ps, QString &rs)
+ : ProStringRoUser(rs)
+ {
+ ps.toQString(rs);
+ }
+ // No destructor, as a RAII pattern cannot be used: references to the
+ // temporary string can legitimately outlive instances of this class
+ // (if they are held by Qt, e.g. in QRegExp).
+ QString &set(const ProString &ps) { return ps.toQString(*m_rs); }
+ QString &str() { return *m_rs; }
+
+protected:
+ QString *m_rs;
+};
+
+// This class manages read-write access to a ProString via a raw data QString
+// temporary, ensuring that the latter is accessed exclusively, and that raw
+// data does not leak outside its source's refcounting.
+class ProStringRwUser : public ProStringRoUser
+{
+public:
+ ProStringRwUser(QString &rs)
+ : ProStringRoUser(rs), m_ps(nullptr) {}
+ ProStringRwUser(const ProString &ps, QString &rs)
+ : ProStringRoUser(ps, rs), m_ps(&ps) {}
+ QString &set(const ProString &ps) { m_ps = &ps; return ProStringRoUser::set(ps); }
+ ProString extract(const QString &s) const
+ { return s.isSharedWith(*m_rs) ? *m_ps : ProString(s).setSource(*m_ps); }
+ ProString extract(const QString &s, const ProStringRwUser &other) const
+ {
+ if (other.m_ps && s.isSharedWith(*other.m_rs))
+ return *other.m_ps;
+ return extract(s);
+ }
+
+private:
+ const ProString *m_ps;
+};
+
class ProStringList : public QVector<ProString> {
public:
ProStringList() {}
diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp
index 6907dfc01d..f81bec158b 100644
--- a/qmake/library/qmakebuiltins.cpp
+++ b/qmake/library/qmakebuiltins.cpp
@@ -105,109 +105,138 @@ enum TestFunc {
T_MKPATH, T_WRITE_FILE, T_TOUCH, T_CACHE, T_RELOAD_PROPERTIES
};
+QMakeBuiltin::QMakeBuiltin(const QMakeBuiltinInit &d)
+ : index(d.func), minArgs(qMax(0, d.min_args)), maxArgs(d.max_args)
+{
+ static const char * const nstr[6] = { "no", "one", "two", "three", "four", "five" };
+ // For legacy reasons, there is actually no such thing as "no arguments"
+ // - there is only "empty first argument", which needs to be mapped back.
+ // -1 means "one, which may be empty", which is effectively zero, except
+ // for the error message if there are too many arguments.
+ int dmin = qAbs(d.min_args);
+ int dmax = d.max_args;
+ if (dmax == QMakeBuiltinInit::VarArgs) {
+ Q_ASSERT_X(dmin < 2, "init", d.name);
+ if (dmin == 1) {
+ Q_ASSERT_X(d.args != nullptr, "init", d.name);
+ usage = fL1S("%1(%2) requires at least one argument.")
+ .arg(fL1S(d.name), fL1S(d.args));
+ }
+ return;
+ }
+ int arange = dmax - dmin;
+ Q_ASSERT_X(arange >= 0, "init", d.name);
+ Q_ASSERT_X(d.args != nullptr, "init", d.name);
+ usage = arange > 1
+ ? fL1S("%1(%2) requires %3 to %4 arguments.")
+ .arg(fL1S(d.name), fL1S(d.args), fL1S(nstr[dmin]), fL1S(nstr[dmax]))
+ : arange > 0
+ ? fL1S("%1(%2) requires %3 or %4 arguments.")
+ .arg(fL1S(d.name), fL1S(d.args), fL1S(nstr[dmin]), fL1S(nstr[dmax]))
+ : dmax != 1
+ ? fL1S("%1(%2) requires %3 arguments.")
+ .arg(fL1S(d.name), fL1S(d.args), fL1S(nstr[dmax]))
+ : fL1S("%1(%2) requires one argument.")
+ .arg(fL1S(d.name), fL1S(d.args));
+}
+
void QMakeEvaluator::initFunctionStatics()
{
- static const struct {
- const char * const name;
- const ExpandFunc func;
- } expandInits[] = {
- { "member", E_MEMBER },
- { "str_member", E_STR_MEMBER },
- { "first", E_FIRST },
- { "take_first", E_TAKE_FIRST },
- { "last", E_LAST },
- { "take_last", E_TAKE_LAST },
- { "size", E_SIZE },
- { "str_size", E_STR_SIZE },
- { "cat", E_CAT },
- { "fromfile", E_FROMFILE },
- { "eval", E_EVAL },
- { "list", E_LIST },
- { "sprintf", E_SPRINTF },
- { "format_number", E_FORMAT_NUMBER },
- { "num_add", E_NUM_ADD },
- { "join", E_JOIN },
- { "split", E_SPLIT },
- { "basename", E_BASENAME },
- { "dirname", E_DIRNAME },
- { "section", E_SECTION },
- { "find", E_FIND },
- { "system", E_SYSTEM },
- { "unique", E_UNIQUE },
- { "sorted", E_SORTED },
- { "reverse", E_REVERSE },
- { "quote", E_QUOTE },
- { "escape_expand", E_ESCAPE_EXPAND },
- { "upper", E_UPPER },
- { "lower", E_LOWER },
- { "title", E_TITLE },
- { "re_escape", E_RE_ESCAPE },
- { "val_escape", E_VAL_ESCAPE },
- { "files", E_FILES },
- { "prompt", E_PROMPT },
- { "replace", E_REPLACE },
- { "sort_depends", E_SORT_DEPENDS },
- { "resolve_depends", E_RESOLVE_DEPENDS },
- { "enumerate_vars", E_ENUMERATE_VARS },
- { "shadowed", E_SHADOWED },
- { "absolute_path", E_ABSOLUTE_PATH },
- { "relative_path", E_RELATIVE_PATH },
- { "clean_path", E_CLEAN_PATH },
- { "system_path", E_SYSTEM_PATH },
- { "shell_path", E_SHELL_PATH },
- { "system_quote", E_SYSTEM_QUOTE },
- { "shell_quote", E_SHELL_QUOTE },
- { "getenv", E_GETENV },
+ static const QMakeBuiltinInit expandInits[] = {
+ { "member", E_MEMBER, 1, 3, "var, [start, [end]]" },
+ { "str_member", E_STR_MEMBER, -1, 3, "str, [start, [end]]" },
+ { "first", E_FIRST, 1, 1, "var" },
+ { "take_first", E_TAKE_FIRST, 1, 1, "var" },
+ { "last", E_LAST, 1, 1, "var" },
+ { "take_last", E_TAKE_LAST, 1, 1, "var" },
+ { "size", E_SIZE, 1, 1, "var" },
+ { "str_size", E_STR_SIZE, -1, 1, "str" },
+ { "cat", E_CAT, 1, 2, "file, [mode=true|blob|lines]" },
+ { "fromfile", E_FROMFILE, 2, 2, "file, var" },
+ { "eval", E_EVAL, 1, 1, "var" },
+ { "list", E_LIST, 0, QMakeBuiltinInit::VarArgs, nullptr },
+ { "sprintf", E_SPRINTF, 1, QMakeBuiltinInit::VarArgs, "format, ..." },
+ { "format_number", E_FORMAT_NUMBER, 1, 2, "number, [options...]" },
+ { "num_add", E_NUM_ADD, 1, QMakeBuiltinInit::VarArgs, "num, ..." },
+ { "join", E_JOIN, 1, 4, "var, [glue, [before, [after]]]" },
+ { "split", E_SPLIT, 1, 2, "var, sep" },
+ { "basename", E_BASENAME, 1, 1, "var" },
+ { "dirname", E_DIRNAME, 1, 1, "var" },
+ { "section", E_SECTION, 3, 4, "var, sep, begin, [end]" },
+ { "find", E_FIND, 2, 2, "var, str" },
+ { "system", E_SYSTEM, 1, 3, "command, [mode], [stsvar]" },
+ { "unique", E_UNIQUE, 1, 1, "var" },
+ { "sorted", E_SORTED, 1, 1, "var" },
+ { "reverse", E_REVERSE, 1, 1, "var" },
+ { "quote", E_QUOTE, 0, QMakeBuiltinInit::VarArgs, nullptr },
+ { "escape_expand", E_ESCAPE_EXPAND, 0, QMakeBuiltinInit::VarArgs, nullptr },
+ { "upper", E_UPPER, 0, QMakeBuiltinInit::VarArgs, nullptr },
+ { "lower", E_LOWER, 0, QMakeBuiltinInit::VarArgs, nullptr },
+ { "title", E_TITLE, 0, QMakeBuiltinInit::VarArgs, nullptr },
+ { "re_escape", E_RE_ESCAPE, 0, QMakeBuiltinInit::VarArgs, nullptr },
+ { "val_escape", E_VAL_ESCAPE, 1, 1, "var" },
+ { "files", E_FILES, 1, 2, "pattern, [recursive=false]" },
+ { "prompt", E_PROMPT, 1, 2, "question, [decorate=true]" },
+ { "replace", E_REPLACE, 3, 3, "var, before, after" },
+ { "sort_depends", E_SORT_DEPENDS, 1, 4, "var, [prefix, [suffixes, [prio-suffix]]]" },
+ { "resolve_depends", E_RESOLVE_DEPENDS, 1, 4, "var, [prefix, [suffixes, [prio-suffix]]]" },
+ { "enumerate_vars", E_ENUMERATE_VARS, 0, 0, "" },
+ { "shadowed", E_SHADOWED, 1, 1, "path" },
+ { "absolute_path", E_ABSOLUTE_PATH, -1, 2, "path, [base]" },
+ { "relative_path", E_RELATIVE_PATH, -1, 2, "path, [base]" },
+ { "clean_path", E_CLEAN_PATH, -1, 1, "path" },
+ { "system_path", E_SYSTEM_PATH, -1, 1, "path" },
+ { "shell_path", E_SHELL_PATH, -1, 1, "path" },
+ { "system_quote", E_SYSTEM_QUOTE, -1, 1, "arg" },
+ { "shell_quote", E_SHELL_QUOTE, -1, 1, "arg" },
+ { "getenv", E_GETENV, 1, 1, "arg" },
};
statics.expands.reserve((int)(sizeof(expandInits)/sizeof(expandInits[0])));
for (unsigned i = 0; i < sizeof(expandInits)/sizeof(expandInits[0]); ++i)
- statics.expands.insert(ProKey(expandInits[i].name), expandInits[i].func);
+ statics.expands.insert(ProKey(expandInits[i].name), QMakeBuiltin(expandInits[i]));
- static const struct {
- const char * const name;
- const TestFunc func;
- } testInits[] = {
- { "requires", T_REQUIRES },
- { "greaterThan", T_GREATERTHAN },
- { "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 },
- { "unset", T_UNSET },
- { "eval", T_EVAL },
- { "CONFIG", T_CONFIG },
- { "if", T_IF },
- { "isActiveConfig", T_CONFIG },
- { "system", T_SYSTEM },
- { "discard_from", T_DISCARD_FROM },
- { "defined", T_DEFINED },
- { "contains", T_CONTAINS },
- { "infile", T_INFILE },
- { "count", T_COUNT },
- { "isEmpty", T_ISEMPTY },
+ static const QMakeBuiltinInit testInits[] = {
+ { "requires", T_REQUIRES, 0, QMakeBuiltinInit::VarArgs, nullptr },
+ { "greaterThan", T_GREATERTHAN, 2, 2, "var, val" },
+ { "lessThan", T_LESSTHAN, 2, 2, "var, val" },
+ { "equals", T_EQUALS, 2, 2, "var, val" },
+ { "isEqual", T_EQUALS, 2, 2, "var, val" },
+ { "versionAtLeast", T_VERSION_AT_LEAST, 2, 2, "var, version" },
+ { "versionAtMost", T_VERSION_AT_MOST, 2, 2, "var, version" },
+ { "exists", T_EXISTS, 1, 1, "file" },
+ { "export", T_EXPORT, 1, 1, "var" },
+ { "clear", T_CLEAR, 1, 1, "var" },
+ { "unset", T_UNSET, 1, 1, "var" },
+ { "eval", T_EVAL, 0, QMakeBuiltinInit::VarArgs, nullptr },
+ { "CONFIG", T_CONFIG, 1, 2, "config, [mutuals]" },
+ { "if", T_IF, 1, 1, "condition" },
+ { "isActiveConfig", T_CONFIG, 1, 2, "config, [mutuals]" },
+ { "system", T_SYSTEM, 1, 1, "exec" },
+ { "discard_from", T_DISCARD_FROM, 1, 1, "file" },
+ { "defined", T_DEFINED, 1, 2, "object, [\"test\"|\"replace\"|\"var\"]" },
+ { "contains", T_CONTAINS, 2, 3, "var, val, [mutuals]" },
+ { "infile", T_INFILE, 2, 3, "file, var, [values]" },
+ { "count", T_COUNT, 2, 3, "var, count, [op=operator]" },
+ { "isEmpty", T_ISEMPTY, 1, 1, "var" },
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
- { "parseJson", T_PARSE_JSON },
+ { "parseJson", T_PARSE_JSON, 2, 2, "var, into" },
#endif
- { "load", T_LOAD },
- { "include", T_INCLUDE },
- { "debug", T_DEBUG },
- { "log", T_LOG },
- { "message", T_MESSAGE },
- { "warning", T_WARNING },
- { "error", T_ERROR },
- { "mkpath", T_MKPATH },
- { "write_file", T_WRITE_FILE },
- { "touch", T_TOUCH },
- { "cache", T_CACHE },
- { "reload_properties", T_RELOAD_PROPERTIES },
+ { "load", T_LOAD, 1, 2, "feature, [ignore_errors=false]" },
+ { "include", T_INCLUDE, 1, 3, "file, [into, [silent]]" },
+ { "debug", T_DEBUG, 2, 2, "level, message" },
+ { "log", T_LOG, 1, 1, "message" },
+ { "message", T_MESSAGE, 1, 1, "message" },
+ { "warning", T_WARNING, 1, 1, "message" },
+ { "error", T_ERROR, 0, 1, "message" },
+ { "mkpath", T_MKPATH, 1, 1, "path" },
+ { "write_file", T_WRITE_FILE, 1, 3, "name, [content var, [append] [exe]]" },
+ { "touch", T_TOUCH, 2, 2, "file, reffile" },
+ { "cache", T_CACHE, 0, 3, "[var], [set|add|sub] [transient] [super|stash], [srcvar]" },
+ { "reload_properties", T_RELOAD_PROPERTIES, 0, 0, "" },
};
statics.functions.reserve((int)(sizeof(testInits)/sizeof(testInits[0])));
for (unsigned i = 0; i < sizeof(testInits)/sizeof(testInits[0]); ++i)
- statics.functions.insert(ProKey(testInits[i].name), testInits[i].func);
+ statics.functions.insert(ProKey(testInits[i].name), QMakeBuiltin(testInits[i]));
}
static bool isTrue(const ProString &str)
@@ -234,8 +263,9 @@ QMakeEvaluator::getMemberArgs(const ProKey &func, int srclen, const ProStringLis
}
}
if (!ok) {
- evalError(fL1S("%1() argument 2 (start) '%2' invalid.")
- .arg(func.toQString(m_tmp1), start_str.toQString(m_tmp2)));
+ ProStringRoUser u1(func, m_tmp1);
+ ProStringRoUser u2(start_str, m_tmp2);
+ evalError(fL1S("%1() argument 2 (start) '%2' invalid.").arg(u1.str(), u2.str()));
return false;
}
} else {
@@ -243,8 +273,9 @@ QMakeEvaluator::getMemberArgs(const ProKey &func, int srclen, const ProStringLis
if (args.count() == 3)
*end = args.at(2).toInt(&ok);
if (!ok) {
- evalError(fL1S("%1() argument 3 (end) '%2' invalid.")
- .arg(func.toQString(m_tmp1), args.at(2).toQString(m_tmp2)));
+ ProStringRoUser u1(func, m_tmp1);
+ ProStringRoUser u2(args.at(2), m_tmp2);
+ evalError(fL1S("%1() argument 3 (end) '%2' invalid.").arg(u1.str(), u2.str()));
return false;
}
}
@@ -550,11 +581,33 @@ void QMakeEvaluator::populateDeps(
}
}
+QString QMakeEvaluator::filePathArg0(const ProStringList &args)
+{
+ ProStringRoUser u1(args.at(0), m_tmp1);
+ QString fn = resolvePath(u1.str());
+ fn.detach();
+ return fn;
+}
+
+QString QMakeEvaluator::filePathEnvArg0(const ProStringList &args)
+{
+ ProStringRoUser u1(args.at(0), m_tmp1);
+ QString fn = resolvePath(m_option->expandEnvVars(u1.str()));
+ fn.detach();
+ return fn;
+}
+
QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
- int func_t, const ProKey &func, const ProStringList &args, ProStringList &ret)
+ const QMakeBuiltin &adef, const ProKey &func, const ProStringList &args, ProStringList &ret)
{
traceMsg("calling built-in $$%s(%s)", dbgKey(func), dbgSepStrList(args));
+ int asz = args.size() > 1 ? args.size() : args.at(0).isEmpty() ? 0 : 1;
+ if (asz < adef.minArgs || asz > adef.maxArgs) {
+ evalError(adef.usage);
+ return ReturnTrue;
+ }
+ int func_t = adef.index;
switch (func_t) {
case E_BASENAME:
case E_DIRNAME:
@@ -565,319 +618,264 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
int beg = 0;
int end = -1;
if (func_t == E_SECTION) {
- if (args.count() != 3 && args.count() != 4) {
- evalError(fL1S("section(var, sep, begin, end) requires three or four arguments."));
- } else {
- var = args[0];
- sep = args.at(1).toQString();
- beg = args.at(2).toInt();
- if (args.count() == 4)
- end = args.at(3).toInt();
- }
+ var = args[0];
+ sep = args.at(1).toQString();
+ beg = args.at(2).toInt();
+ if (args.count() == 4)
+ end = args.at(3).toInt();
} else {
- if (args.count() != 1) {
- evalError(fL1S("%1(var) requires one argument.").arg(func.toQStringView()));
- } else {
- var = args[0];
- regexp = true;
- sep = QLatin1String("[\\\\/]");
- if (func_t == E_DIRNAME)
- end = -2;
- else
- beg = -1;
- }
+ var = args[0];
+ regexp = true;
+ sep = QLatin1String("[\\\\/]");
+ if (func_t == E_DIRNAME)
+ end = -2;
+ else
+ beg = -1;
}
if (!var.isEmpty()) {
const auto strings = values(map(var));
if (regexp) {
QRegExp sepRx(sep);
for (const ProString &str : strings) {
- const QString &rstr = str.toQString(m_tmp[m_toggle ^= 1]).section(sepRx, beg, end);
- ret << (rstr.isSharedWith(m_tmp[m_toggle]) ? str : ProString(rstr).setSource(str));
+ ProStringRwUser u1(str, m_tmp[m_toggle ^= 1]);
+ ret << u1.extract(u1.str().section(sepRx, beg, end));
}
} else {
for (const ProString &str : strings) {
- const QString &rstr = str.toQString(m_tmp1).section(sep, beg, end);
- ret << (rstr.isSharedWith(m_tmp1) ? str : ProString(rstr).setSource(str));
+ ProStringRwUser u1(str, m_tmp1);
+ ret << u1.extract(u1.str().section(sep, beg, end));
}
}
}
break;
}
- case E_SPRINTF:
- if (args.count() < 1) {
- evalError(fL1S("sprintf(format, ...) requires at least one argument."));
- } else {
- QString tmp = args.at(0).toQString(m_tmp1);
- for (int i = 1; i < args.count(); ++i)
- tmp = tmp.arg(args.at(i).toQStringView());
- ret << (tmp.isSharedWith(m_tmp1) ? args.at(0) : ProString(tmp).setSource(args.at(0)));
- }
+ case E_SPRINTF: {
+ ProStringRwUser u1(args.at(0), m_tmp1);
+ QString tmp = u1.str();
+ for (int i = 1; i < args.count(); ++i)
+ tmp = tmp.arg(args.at(i).toQStringView());
+ ret << u1.extract(tmp);
break;
- case E_FORMAT_NUMBER:
- if (args.count() > 2) {
- evalError(fL1S("format_number(number[, options...]) requires one or two arguments."));
- } else {
- int ibase = 10;
- int obase = 10;
- int width = 0;
- bool zeropad = false;
- bool leftalign = false;
- enum { DefaultSign, PadSign, AlwaysSign } sign = DefaultSign;
- if (args.count() >= 2) {
- const auto opts = split_value_list(args.at(1).toQStringRef());
- for (const ProString &opt : opts) {
- if (opt.startsWith(QLatin1String("ibase="))) {
- ibase = opt.mid(6).toInt();
- } else if (opt.startsWith(QLatin1String("obase="))) {
- obase = opt.mid(6).toInt();
- } else if (opt.startsWith(QLatin1String("width="))) {
- width = opt.mid(6).toInt();
- } else if (opt == QLatin1String("zeropad")) {
- zeropad = true;
- } else if (opt == QLatin1String("padsign")) {
- sign = PadSign;
- } else if (opt == QLatin1String("alwayssign")) {
- sign = AlwaysSign;
- } else if (opt == QLatin1String("leftalign")) {
- leftalign = true;
- } else {
- evalError(fL1S("format_number(): invalid format option %1.")
- .arg(opt.toQStringView()));
- goto formfail;
- }
+ }
+ case E_FORMAT_NUMBER: {
+ int ibase = 10;
+ int obase = 10;
+ int width = 0;
+ bool zeropad = false;
+ bool leftalign = false;
+ enum { DefaultSign, PadSign, AlwaysSign } sign = DefaultSign;
+ if (args.count() >= 2) {
+ const auto opts = split_value_list(args.at(1).toQStringRef());
+ for (const ProString &opt : opts) {
+ if (opt.startsWith(QLatin1String("ibase="))) {
+ ibase = opt.mid(6).toInt();
+ } else if (opt.startsWith(QLatin1String("obase="))) {
+ obase = opt.mid(6).toInt();
+ } else if (opt.startsWith(QLatin1String("width="))) {
+ width = opt.mid(6).toInt();
+ } else if (opt == QLatin1String("zeropad")) {
+ zeropad = true;
+ } else if (opt == QLatin1String("padsign")) {
+ sign = PadSign;
+ } else if (opt == QLatin1String("alwayssign")) {
+ sign = AlwaysSign;
+ } else if (opt == QLatin1String("leftalign")) {
+ leftalign = true;
+ } else {
+ evalError(fL1S("format_number(): invalid format option %1.")
+ .arg(opt.toQStringView()));
+ goto allfail;
}
}
- if (args.at(0).contains(QLatin1Char('.'))) {
- evalError(fL1S("format_number(): floats are currently not supported."));
- break;
+ }
+ if (args.at(0).contains(QLatin1Char('.'))) {
+ evalError(fL1S("format_number(): floats are currently not supported."));
+ break;
+ }
+ bool ok;
+ qlonglong num = args.at(0).toLongLong(&ok, ibase);
+ if (!ok) {
+ evalError(fL1S("format_number(): malformed number %2 for base %1.")
+ .arg(ibase).arg(args.at(0).toQStringView()));
+ break;
+ }
+ QString outstr;
+ if (num < 0) {
+ num = -num;
+ outstr = QLatin1Char('-');
+ } else if (sign == AlwaysSign) {
+ outstr = QLatin1Char('+');
+ } else if (sign == PadSign) {
+ outstr = QLatin1Char(' ');
+ }
+ QString numstr = QString::number(num, obase);
+ int space = width - outstr.length() - numstr.length();
+ if (space <= 0) {
+ outstr += numstr;
+ } else if (leftalign) {
+ outstr += numstr + QString(space, QLatin1Char(' '));
+ } else if (zeropad) {
+ outstr += QString(space, QLatin1Char('0')) + numstr;
+ } else {
+ outstr.prepend(QString(space, QLatin1Char(' ')));
+ outstr += numstr;
+ }
+ ret += ProString(outstr);
+ break;
+ }
+ case E_NUM_ADD: {
+ qlonglong sum = 0;
+ for (const ProString &arg : qAsConst(args)) {
+ if (arg.contains(QLatin1Char('.'))) {
+ evalError(fL1S("num_add(): floats are currently not supported."));
+ goto allfail;
}
bool ok;
- qlonglong num = args.at(0).toLongLong(&ok, ibase);
+ qlonglong num = arg.toLongLong(&ok);
if (!ok) {
- evalError(fL1S("format_number(): malformed number %2 for base %1.")
- .arg(ibase).arg(args.at(0).toQStringView()));
- break;
- }
- QString outstr;
- if (num < 0) {
- num = -num;
- outstr = QLatin1Char('-');
- } else if (sign == AlwaysSign) {
- outstr = QLatin1Char('+');
- } else if (sign == PadSign) {
- outstr = QLatin1Char(' ');
- }
- QString numstr = QString::number(num, obase);
- int space = width - outstr.length() - numstr.length();
- if (space <= 0) {
- outstr += numstr;
- } else if (leftalign) {
- outstr += numstr + QString(space, QLatin1Char(' '));
- } else if (zeropad) {
- outstr += QString(space, QLatin1Char('0')) + numstr;
- } else {
- outstr.prepend(QString(space, QLatin1Char(' ')));
- outstr += numstr;
+ evalError(fL1S("num_add(): malformed number %1.")
+ .arg(arg.toQStringView()));
+ goto allfail;
}
- ret += ProString(outstr);
+ sum += num;
}
- formfail:
- break;
- case E_NUM_ADD:
- if (args.count() < 1 || args.at(0).isEmpty()) {
- evalError(fL1S("num_add(num, ...) requires at least one argument."));
- } else {
- qlonglong sum = 0;
- for (const ProString &arg : qAsConst(args)) {
- if (arg.contains(QLatin1Char('.'))) {
- evalError(fL1S("num_add(): floats are currently not supported."));
- goto nafail;
- }
- bool ok;
- qlonglong num = arg.toLongLong(&ok);
- if (!ok) {
- evalError(fL1S("num_add(): malformed number %1.")
- .arg(arg.toQStringView()));
- goto nafail;
- }
- sum += num;
- }
- ret += ProString(QString::number(sum));
- }
- nafail:
+ ret += ProString(QString::number(sum));
break;
+ }
case E_JOIN: {
- if (args.count() < 1 || args.count() > 4) {
- evalError(fL1S("join(var, glue, before, after) requires one to four arguments."));
- } else {
- ProString glue, before, after;
- if (args.count() >= 2)
- glue = args.at(1);
- if (args.count() >= 3)
- before = args[2];
- if (args.count() == 4)
- after = args[3];
- const ProStringList &var = values(map(args.at(0)));
- if (!var.isEmpty()) {
- int src = currentFileId();
- for (const ProString &v : var)
- if (int s = v.sourceFile()) {
- src = s;
- break;
- }
- ret << ProString(before + var.join(glue) + after).setSource(src);
- }
+ ProString glue, before, after;
+ if (args.count() >= 2)
+ glue = args.at(1);
+ if (args.count() >= 3)
+ before = args[2];
+ if (args.count() == 4)
+ after = args[3];
+ const ProStringList &var = values(map(args.at(0)));
+ if (!var.isEmpty()) {
+ int src = currentFileId();
+ for (const ProString &v : var)
+ if (int s = v.sourceFile()) {
+ src = s;
+ break;
+ }
+ ret << ProString(before + var.join(glue) + after).setSource(src);
}
break;
}
- case E_SPLIT:
- if (args.count() < 1 || args.count() > 2) {
- evalError(fL1S("split(var, sep) requires one or two arguments."));
- } else {
- const QString &sep = (args.count() == 2) ? args.at(1).toQString(m_tmp1) : statics.field_sep;
- const auto vars = values(map(args.at(0)));
- for (const ProString &var : vars) {
- // FIXME: this is inconsistent with the "there are no empty strings" dogma.
- const auto splits = var.toQStringRef().split(sep, QString::KeepEmptyParts);
- for (const auto &splt : splits)
- ret << ProString(splt).setSource(var);
- }
+ case E_SPLIT: {
+ ProStringRoUser u1(m_tmp1);
+ const QString &sep = (args.count() == 2) ? u1.set(args.at(1)) : statics.field_sep;
+ const auto vars = values(map(args.at(0)));
+ for (const ProString &var : vars) {
+ // FIXME: this is inconsistent with the "there are no empty strings" dogma.
+ const auto splits = var.toQStringRef().split(sep, QString::KeepEmptyParts);
+ for (const auto &splt : splits)
+ ret << ProString(splt).setSource(var);
}
break;
- case E_MEMBER:
- if (args.count() < 1 || args.count() > 3) {
- evalError(fL1S("member(var, start, end) requires one to three arguments."));
- } else {
- const ProStringList &src = values(map(args.at(0)));
- int start, end;
- if (getMemberArgs(func, src.size(), args, &start, &end)) {
- ret.reserve(qAbs(end - start) + 1);
- if (start < end) {
- for (int i = start; i <= end && src.size() >= i; i++)
- ret += src.at(i);
- } else {
- for (int i = start; i >= end && src.size() >= i && i >= 0; i--)
- ret += src.at(i);
- }
+ }
+ case E_MEMBER: {
+ const ProStringList &src = values(map(args.at(0)));
+ int start, end;
+ if (getMemberArgs(func, src.size(), args, &start, &end)) {
+ ret.reserve(qAbs(end - start) + 1);
+ if (start < end) {
+ for (int i = start; i <= end && src.size() >= i; i++)
+ ret += src.at(i);
+ } else {
+ for (int i = start; i >= end && src.size() >= i && i >= 0; i--)
+ ret += src.at(i);
}
}
break;
- case E_STR_MEMBER:
- if (args.count() < 1 || args.count() > 3) {
- evalError(fL1S("str_member(str, start, end) requires one to three arguments."));
- } else {
- const ProString &src = args.at(0);
- int start, end;
- if (getMemberArgs(func, src.size(), args, &start, &end)) {
- QString res;
- res.reserve(qAbs(end - start) + 1);
- if (start < end) {
- for (int i = start; i <= end && src.size() >= i; i++)
- res += src.at(i);
- } else {
- for (int i = start; i >= end && src.size() >= i && i >= 0; i--)
- res += src.at(i);
- }
- ret += ProString(res);
+ }
+ case E_STR_MEMBER: {
+ const ProString &src = args.at(0);
+ int start, end;
+ if (getMemberArgs(func, src.size(), args, &start, &end)) {
+ QString res;
+ res.reserve(qAbs(end - start) + 1);
+ if (start < end) {
+ for (int i = start; i <= end && src.size() >= i; i++)
+ res += src.at(i);
+ } else {
+ for (int i = start; i >= end && src.size() >= i && i >= 0; i--)
+ res += src.at(i);
}
+ ret += ProString(res);
}
break;
+ }
case E_FIRST:
- case E_LAST:
- if (args.count() != 1) {
- evalError(fL1S("%1(var) requires one argument.").arg(func.toQStringView()));
- } else {
- const ProStringList &var = values(map(args.at(0)));
- if (!var.isEmpty()) {
- if (func_t == E_FIRST)
- ret.append(var[0]);
- else
- ret.append(var.last());
- }
+ case E_LAST: {
+ const ProStringList &var = values(map(args.at(0)));
+ if (!var.isEmpty()) {
+ if (func_t == E_FIRST)
+ ret.append(var[0]);
+ else
+ ret.append(var.last());
}
break;
+ }
case E_TAKE_FIRST:
- case E_TAKE_LAST:
- if (args.count() != 1) {
- evalError(fL1S("%1(var) requires one argument.").arg(func.toQStringView()));
- } else {
- ProStringList &var = valuesRef(map(args.at(0)));
- if (!var.isEmpty()) {
- if (func_t == E_TAKE_FIRST)
- ret.append(var.takeFirst());
- else
- ret.append(var.takeLast());
- }
+ case E_TAKE_LAST: {
+ ProStringList &var = valuesRef(map(args.at(0)));
+ if (!var.isEmpty()) {
+ if (func_t == E_TAKE_FIRST)
+ ret.append(var.takeFirst());
+ else
+ ret.append(var.takeLast());
}
break;
+ }
case E_SIZE:
- if (args.count() != 1)
- evalError(fL1S("size(var) requires one argument."));
- else
- ret.append(ProString(QString::number(values(map(args.at(0))).size())));
+ ret.append(ProString(QString::number(values(map(args.at(0))).size())));
break;
case E_STR_SIZE:
- if (args.count() != 1)
- evalError(fL1S("str_size(str) requires one argument."));
- else
- ret.append(ProString(QString::number(args.at(0).size())));
+ ret.append(ProString(QString::number(args.at(0).size())));
break;
- case E_CAT:
- if (args.count() < 1 || args.count() > 2) {
- evalError(fL1S("cat(file, singleline=true) requires one or two arguments."));
- } else {
- QString fn = resolvePath(m_option->expandEnvVars(args.at(0).toQString(m_tmp1)));
- fn.detach();
-
- bool blob = false;
- bool lines = false;
- bool singleLine = true;
- if (args.count() > 1) {
- if (!args.at(1).compare(QLatin1String("false"), Qt::CaseInsensitive))
- singleLine = false;
- else if (!args.at(1).compare(QLatin1String("blob"), Qt::CaseInsensitive))
- blob = true;
- else if (!args.at(1).compare(QLatin1String("lines"), Qt::CaseInsensitive))
- lines = true;
- }
-
- QFile qfile(fn);
- if (qfile.open(QIODevice::ReadOnly)) {
- QTextStream stream(&qfile);
- if (blob) {
- ret += ProString(stream.readAll());
- } else {
- while (!stream.atEnd()) {
- if (lines) {
- ret += ProString(stream.readLine());
- } else {
- const QString &line = stream.readLine();
- ret += split_value_list(QStringRef(&line).trimmed());
- if (!singleLine)
- ret += ProString("\n");
- }
+ case E_CAT: {
+ bool blob = false;
+ bool lines = false;
+ bool singleLine = true;
+ if (args.count() > 1) {
+ if (!args.at(1).compare(QLatin1String("false"), Qt::CaseInsensitive))
+ singleLine = false;
+ else if (!args.at(1).compare(QLatin1String("blob"), Qt::CaseInsensitive))
+ blob = true;
+ else if (!args.at(1).compare(QLatin1String("lines"), Qt::CaseInsensitive))
+ lines = true;
+ }
+ QString fn = filePathEnvArg0(args);
+ QFile qfile(fn);
+ if (qfile.open(QIODevice::ReadOnly)) {
+ QTextStream stream(&qfile);
+ if (blob) {
+ ret += ProString(stream.readAll());
+ } else {
+ while (!stream.atEnd()) {
+ if (lines) {
+ ret += ProString(stream.readLine());
+ } else {
+ const QString &line = stream.readLine();
+ ret += split_value_list(QStringRef(&line).trimmed());
+ if (!singleLine)
+ ret += ProString("\n");
}
}
}
}
break;
- case E_FROMFILE:
- if (args.count() != 2) {
- evalError(fL1S("fromfile(file, variable) requires two arguments."));
- } else {
- ProValueMap vars;
- QString fn = resolvePath(m_option->expandEnvVars(args.at(0).toQString(m_tmp1)));
- fn.detach();
- if (evaluateFileInto(fn, &vars, LoadProOnly) == ReturnTrue)
- ret = vars.value(map(args.at(1)));
- }
+ }
+ case E_FROMFILE: {
+ ProValueMap vars;
+ QString fn = filePathEnvArg0(args);
+ if (evaluateFileInto(fn, &vars, LoadProOnly) == ReturnTrue)
+ ret = vars.value(map(args.at(1)));
break;
+ }
case E_EVAL:
- if (args.count() != 1)
- evalError(fL1S("eval(variable) requires one argument."));
- else
- ret += values(map(args.at(0)));
+ ret += values(map(args.at(0)));
break;
case E_LIST: {
QString tmp;
@@ -888,84 +886,68 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
lst += split_value_list(arg.toQStringRef(), arg.sourceFile()); // Relies on deep copy
m_valuemapStack.top()[ret.at(0).toKey()] = lst;
break; }
- case E_FIND:
- if (args.count() != 2) {
- evalError(fL1S("find(var, str) requires two arguments."));
- } else {
- QRegExp regx(args.at(1).toQString());
- const auto vals = values(map(args.at(0)));
- for (const ProString &val : vals) {
- if (regx.indexIn(val.toQString(m_tmp[m_toggle ^= 1])) != -1)
- ret += val;
- }
+ case E_FIND: {
+ QRegExp regx(args.at(1).toQString());
+ const auto vals = values(map(args.at(0)));
+ for (const ProString &val : vals) {
+ ProStringRoUser u1(val, m_tmp[m_toggle ^= 1]);
+ if (regx.indexIn(u1.str()) != -1)
+ ret += val;
}
break;
- case E_SYSTEM:
- if (!m_skipLevel) {
- if (args.count() < 1 || args.count() > 3) {
- evalError(fL1S("system(command, [mode], [stsvar]) requires one to three arguments."));
+ }
+ case E_SYSTEM: {
+ if (m_skipLevel)
+ break;
+ bool blob = false;
+ bool lines = false;
+ bool singleLine = true;
+ if (args.count() > 1) {
+ if (!args.at(1).compare(QLatin1String("false"), Qt::CaseInsensitive))
+ singleLine = false;
+ else if (!args.at(1).compare(QLatin1String("blob"), Qt::CaseInsensitive))
+ blob = true;
+ else if (!args.at(1).compare(QLatin1String("lines"), Qt::CaseInsensitive))
+ lines = true;
+ }
+ int exitCode;
+ QByteArray bytes = getCommandOutput(args.at(0).toQString(), &exitCode);
+ if (args.count() > 2 && !args.at(2).isEmpty()) {
+ m_valuemapStack.top()[args.at(2).toKey()] =
+ ProStringList(ProString(QString::number(exitCode)));
+ }
+ if (lines) {
+ QTextStream stream(bytes);
+ while (!stream.atEnd())
+ ret += ProString(stream.readLine());
+ } else {
+ QString output = QString::fromLocal8Bit(bytes);
+ if (blob) {
+ ret += ProString(output);
} else {
- bool blob = false;
- bool lines = false;
- bool singleLine = true;
- if (args.count() > 1) {
- if (!args.at(1).compare(QLatin1String("false"), Qt::CaseInsensitive))
- singleLine = false;
- else if (!args.at(1).compare(QLatin1String("blob"), Qt::CaseInsensitive))
- blob = true;
- else if (!args.at(1).compare(QLatin1String("lines"), Qt::CaseInsensitive))
- lines = true;
- }
- int exitCode;
- QByteArray bytes = getCommandOutput(args.at(0).toQString(), &exitCode);
- if (args.count() > 2 && !args.at(2).isEmpty()) {
- m_valuemapStack.top()[args.at(2).toKey()] =
- ProStringList(ProString(QString::number(exitCode)));
- }
- if (lines) {
- QTextStream stream(bytes);
- while (!stream.atEnd())
- ret += ProString(stream.readLine());
- } else {
- QString output = QString::fromLocal8Bit(bytes);
- if (blob) {
- ret += ProString(output);
- } else {
- output.replace(QLatin1Char('\t'), QLatin1Char(' '));
- if (singleLine)
- output.replace(QLatin1Char('\n'), QLatin1Char(' '));
- ret += split_value_list(QStringRef(&output));
- }
- }
+ output.replace(QLatin1Char('\t'), QLatin1Char(' '));
+ if (singleLine)
+ output.replace(QLatin1Char('\n'), QLatin1Char(' '));
+ ret += split_value_list(QStringRef(&output));
}
}
break;
+ }
case E_UNIQUE:
- if (args.count() != 1) {
- evalError(fL1S("unique(var) requires one argument."));
- } else {
- ret = values(map(args.at(0)));
- ret.removeDuplicates();
- }
+ ret = values(map(args.at(0)));
+ ret.removeDuplicates();
break;
case E_SORTED:
- if (args.count() != 1) {
- evalError(fL1S("sorted(var) requires one argument."));
- } else {
- ret = values(map(args.at(0)));
- std::sort(ret.begin(), ret.end());
- }
+ ret = values(map(args.at(0)));
+ std::sort(ret.begin(), ret.end());
break;
- case E_REVERSE:
- if (args.count() != 1) {
- evalError(fL1S("reverse(var) requires one argument."));
- } else {
- ProStringList var = values(args.at(0).toKey());
- for (int i = 0; i < var.size() / 2; i++)
- qSwap(var[i], var[var.size() - i - 1]);
- ret += var;
- }
+ case E_REVERSE: {
+ ProStringList var = values(args.at(0).toKey());
+ for (int i = 0; i < var.size() / 2; i++)
+ qSwap(var[i], var[var.size() - i - 1]);
+ ret += var;
break;
+ }
case E_QUOTE:
ret += args;
break;
@@ -1004,25 +986,23 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
break;
case E_RE_ESCAPE:
for (int i = 0; i < args.size(); ++i) {
- const QString &rstr = QRegExp::escape(args.at(i).toQString(m_tmp1));
- ret << (rstr.isSharedWith(m_tmp1) ? args.at(i) : ProString(rstr).setSource(args.at(i)));
+ ProStringRwUser u1(args.at(i), m_tmp1);
+ ret << u1.extract(QRegExp::escape(u1.str()));
}
break;
- case E_VAL_ESCAPE:
- if (args.count() != 1) {
- evalError(fL1S("val_escape(var) requires one argument."));
- } else {
- const ProStringList &vals = values(args.at(0).toKey());
- ret.reserve(vals.size());
- for (const ProString &str : vals)
- ret += ProString(quoteValue(str));
- }
+ case E_VAL_ESCAPE: {
+ const ProStringList &vals = values(args.at(0).toKey());
+ ret.reserve(vals.size());
+ for (const ProString &str : vals)
+ ret += ProString(quoteValue(str));
break;
+ }
case E_UPPER:
case E_LOWER:
case E_TITLE:
for (int i = 0; i < args.count(); ++i) {
- QString rstr = args.at(i).toQString(m_tmp1);
+ ProStringRwUser u1(args.at(i), m_tmp1);
+ QString rstr = u1.str();
if (func_t == E_UPPER) {
rstr = rstr.toUpper();
} else {
@@ -1030,134 +1010,119 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
if (func_t == E_TITLE && rstr.length() > 0)
rstr[0] = rstr.at(0).toTitleCase();
}
- ret << (rstr.isSharedWith(m_tmp1) ? args.at(i) : ProString(rstr).setSource(args.at(i)));
+ ret << u1.extract(rstr);
}
break;
- case E_FILES:
- if (args.count() != 1 && args.count() != 2) {
- evalError(fL1S("files(pattern, recursive=false) requires one or two arguments."));
+ case E_FILES: {
+ bool recursive = false;
+ if (args.count() == 2)
+ recursive = isTrue(args.at(1));
+ QStringList dirs;
+ ProStringRoUser u1(args.at(0), m_tmp1);
+ QString r = m_option->expandEnvVars(u1.str())
+ .replace(QLatin1Char('\\'), QLatin1Char('/'));
+ QString pfx;
+ if (IoUtils::isRelativePath(r)) {
+ pfx = currentDirectory();
+ if (!pfx.endsWith(QLatin1Char('/')))
+ pfx += QLatin1Char('/');
+ }
+ int slash = r.lastIndexOf(QLatin1Char('/'));
+ if (slash != -1) {
+ dirs.append(r.left(slash+1));
+ r = r.mid(slash+1);
} else {
- bool recursive = false;
- if (args.count() == 2)
- recursive = isTrue(args.at(1));
- QStringList dirs;
- QString r = m_option->expandEnvVars(args.at(0).toQString(m_tmp1))
- .replace(QLatin1Char('\\'), QLatin1Char('/'));
- QString pfx;
- if (IoUtils::isRelativePath(r)) {
- pfx = currentDirectory();
- if (!pfx.endsWith(QLatin1Char('/')))
- pfx += QLatin1Char('/');
- }
- int slash = r.lastIndexOf(QLatin1Char('/'));
- if (slash != -1) {
- dirs.append(r.left(slash+1));
- r = r.mid(slash+1);
- } else {
- dirs.append(QString());
- }
+ dirs.append(QString());
+ }
- r.detach(); // Keep m_tmp out of QRegExp's cache
- QRegExp regex(r, Qt::CaseSensitive, QRegExp::Wildcard);
- for (int d = 0; d < dirs.count(); d++) {
- QString dir = dirs[d];
- QDir qdir(pfx + dir);
- for (int i = 0; i < (int)qdir.count(); ++i) {
- if (qdir[i] == statics.strDot || qdir[i] == statics.strDotDot)
- continue;
- QString fname = dir + qdir[i];
- if (IoUtils::fileType(pfx + fname) == IoUtils::FileIsDir) {
- if (recursive)
- dirs.append(fname + QLatin1Char('/'));
- }
- if (regex.exactMatch(qdir[i]))
- ret += ProString(fname).setSource(currentFileId());
+ r.detach(); // Keep m_tmp out of QRegExp's cache
+ QRegExp regex(r, Qt::CaseSensitive, QRegExp::Wildcard);
+ for (int d = 0; d < dirs.count(); d++) {
+ QString dir = dirs[d];
+ QDir qdir(pfx + dir);
+ for (int i = 0; i < (int)qdir.count(); ++i) {
+ if (qdir[i] == statics.strDot || qdir[i] == statics.strDotDot)
+ continue;
+ QString fname = dir + qdir[i];
+ if (IoUtils::fileType(pfx + fname) == IoUtils::FileIsDir) {
+ if (recursive)
+ dirs.append(fname + QLatin1Char('/'));
}
+ if (regex.exactMatch(qdir[i]))
+ ret += ProString(fname).setSource(currentFileId());
}
}
break;
+ }
#ifdef PROEVALUATOR_FULL
case E_PROMPT: {
- if (args.count() != 1 && args.count() != 2) {
- evalError(fL1S("prompt(question, [decorate=true]) requires one or two arguments."));
-// } else if (currentFileName() == QLatin1String("-")) {
-// evalError(fL1S("prompt(question) cannot be used when '-o -' is used"));
+ ProStringRoUser u1(args.at(0), m_tmp1);
+ QString msg = m_option->expandEnvVars(u1.str());
+ bool decorate = true;
+ if (args.count() == 2)
+ decorate = isTrue(args.at(1));
+ if (decorate) {
+ if (!msg.endsWith(QLatin1Char('?')))
+ msg += QLatin1Char('?');
+ fprintf(stderr, "Project PROMPT: %s ", qPrintable(msg));
} else {
- QString msg = m_option->expandEnvVars(args.at(0).toQString(m_tmp1));
- bool decorate = true;
- if (args.count() == 2)
- decorate = isTrue(args.at(1));
- if (decorate) {
- if (!msg.endsWith(QLatin1Char('?')))
- msg += QLatin1Char('?');
- fprintf(stderr, "Project PROMPT: %s ", qPrintable(msg));
- } else {
- fputs(qPrintable(msg), stderr);
- }
- QFile qfile;
- if (qfile.open(stdin, QIODevice::ReadOnly)) {
- QTextStream t(&qfile);
- const QString &line = t.readLine();
- if (t.atEnd()) {
- fputs("\n", stderr);
- evalError(fL1S("Unexpected EOF."));
- return ReturnError;
- }
- ret = split_value_list(QStringRef(&line));
+ fputs(qPrintable(msg), stderr);
+ }
+ QFile qfile;
+ if (qfile.open(stdin, QIODevice::ReadOnly)) {
+ QTextStream t(&qfile);
+ const QString &line = t.readLine();
+ if (t.atEnd()) {
+ fputs("\n", stderr);
+ evalError(fL1S("Unexpected EOF."));
+ return ReturnError;
}
+ ret = split_value_list(QStringRef(&line));
}
- break; }
+ break;
+ }
#endif
- case E_REPLACE:
- if (args.count() != 3 ) {
- evalError(fL1S("replace(var, before, after) requires three arguments."));
- } else {
- const QRegExp before(args.at(1).toQString());
- const QString &after(args.at(2).toQString(m_tmp2));
- const auto vals = values(map(args.at(0)));
- for (const ProString &val : vals) {
- QString rstr = val.toQString(m_tmp1);
- QString copy = rstr; // Force a detach on modify
- rstr.replace(before, after);
- ret << (rstr.isSharedWith(m_tmp1)
- ? val
- : rstr.isSharedWith(m_tmp2)
- ? args.at(2)
- : ProString(rstr).setSource(val));
- }
+ case E_REPLACE: {
+ const QRegExp before(args.at(1).toQString());
+ ProStringRwUser u2(args.at(2), m_tmp2);
+ const QString &after = u2.str();
+ const auto vals = values(map(args.at(0)));
+ for (const ProString &val : vals) {
+ ProStringRwUser u1(val, m_tmp1);
+ QString rstr = u1.str();
+ QString copy = rstr; // Force a detach on modify
+ rstr.replace(before, after);
+ ret << u1.extract(rstr, u2);
}
break;
+ }
case E_SORT_DEPENDS:
- case E_RESOLVE_DEPENDS:
- if (args.count() < 1 || args.count() > 4) {
- evalError(fL1S("%1(var, [prefix, [suffixes, [prio-suffix]]]) requires one to four arguments.")
- .arg(func.toQStringView()));
- } else {
- QHash<ProKey, QSet<ProKey> > dependencies;
- ProValueMap dependees;
- QMultiMap<int, ProString> rootSet;
- ProStringList orgList = values(args.at(0).toKey());
- ProString prefix = args.count() < 2 ? ProString() : args.at(1);
- ProString priosfx = args.count() < 4 ? ProString(".priority") : args.at(3);
- populateDeps(orgList, prefix,
- args.count() < 3 ? ProStringList(ProString(".depends"))
- : split_value_list(args.at(2).toQStringRef()),
- priosfx, dependencies, dependees, rootSet);
- while (!rootSet.isEmpty()) {
- QMultiMap<int, ProString>::iterator it = rootSet.begin();
- const ProString item = *it;
- rootSet.erase(it);
- if ((func_t == E_RESOLVE_DEPENDS) || orgList.contains(item))
- ret.prepend(item);
- for (const ProString &dep : qAsConst(dependees[item.toKey()])) {
- QSet<ProKey> &dset = dependencies[dep.toKey()];
- dset.remove(item.toKey());
- if (dset.isEmpty())
- rootSet.insert(first(ProKey(prefix + dep + priosfx)).toInt(), dep);
- }
+ case E_RESOLVE_DEPENDS: {
+ QHash<ProKey, QSet<ProKey> > dependencies;
+ ProValueMap dependees;
+ QMultiMap<int, ProString> rootSet;
+ ProStringList orgList = values(args.at(0).toKey());
+ ProString prefix = args.count() < 2 ? ProString() : args.at(1);
+ ProString priosfx = args.count() < 4 ? ProString(".priority") : args.at(3);
+ populateDeps(orgList, prefix,
+ args.count() < 3 ? ProStringList(ProString(".depends"))
+ : split_value_list(args.at(2).toQStringRef()),
+ priosfx, dependencies, dependees, rootSet);
+ while (!rootSet.isEmpty()) {
+ QMultiMap<int, ProString>::iterator it = rootSet.begin();
+ const ProString item = *it;
+ rootSet.erase(it);
+ if ((func_t == E_RESOLVE_DEPENDS) || orgList.contains(item))
+ ret.prepend(item);
+ for (const ProString &dep : qAsConst(dependees[item.toKey()])) {
+ QSet<ProKey> &dset = dependencies[dep.toKey()];
+ dset.remove(item.toKey());
+ if (dset.isEmpty())
+ rootSet.insert(first(ProKey(prefix + dep + priosfx)).toInt(), dep);
}
}
break;
+ }
case E_ENUMERATE_VARS: {
QSet<ProString> keys;
for (const ProValueMap &vmap : qAsConst(m_valuemapStack))
@@ -1167,120 +1132,94 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
for (const ProString &key : qAsConst(keys))
ret << key;
break; }
- case E_SHADOWED:
- if (args.count() != 1) {
- evalError(fL1S("shadowed(path) requires one argument."));
- } else {
- QString rstr = m_option->shadowedPath(resolvePath(args.at(0).toQString(m_tmp1)));
- if (rstr.isEmpty())
- break;
- ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) : ProString(rstr).setSource(args.at(0)));
- }
+ case E_SHADOWED: {
+ ProStringRwUser u1(args.at(0), m_tmp1);
+ QString rstr = m_option->shadowedPath(resolvePath(u1.str()));
+ if (!rstr.isEmpty())
+ ret << u1.extract(rstr);
break;
- case E_ABSOLUTE_PATH:
- if (args.count() > 2) {
- evalError(fL1S("absolute_path(path[, base]) requires one or two arguments."));
- } else {
- QString arg = args.at(0).toQString(m_tmp1);
- QString baseDir = args.count() > 1
- ? IoUtils::resolvePath(currentDirectory(), args.at(1).toQString(m_tmp2))
- : currentDirectory();
- QString rstr = arg.isEmpty() ? baseDir : IoUtils::resolvePath(baseDir, arg);
- ret << (rstr.isSharedWith(m_tmp1)
- ? args.at(0)
- : args.count() > 1 && rstr.isSharedWith(m_tmp2)
- ? args.at(1)
- : ProString(rstr).setSource(args.at(0)));
- }
+ }
+ case E_ABSOLUTE_PATH: {
+ ProStringRwUser u1(args.at(0), m_tmp1);
+ ProStringRwUser u2(m_tmp2);
+ QString baseDir = args.count() > 1
+ ? IoUtils::resolvePath(currentDirectory(), u2.set(args.at(1)))
+ : currentDirectory();
+ QString rstr = u1.str().isEmpty() ? baseDir : IoUtils::resolvePath(baseDir, u1.str());
+ ret << u1.extract(rstr, u2);
break;
- case E_RELATIVE_PATH:
- if (args.count() > 2) {
- evalError(fL1S("relative_path(path[, base]) requires one or two arguments."));
- } else {
- QString arg = args.at(0).toQString(m_tmp1);
- QString baseDir = args.count() > 1
- ? IoUtils::resolvePath(currentDirectory(), args.at(1).toQString(m_tmp2))
- : currentDirectory();
- QString absArg = arg.isEmpty() ? baseDir : IoUtils::resolvePath(baseDir, arg);
- QString rstr = QDir(baseDir).relativeFilePath(absArg);
- ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) : ProString(rstr).setSource(args.at(0)));
- }
+ }
+ case E_RELATIVE_PATH: {
+ ProStringRwUser u1(args.at(0), m_tmp1);
+ ProStringRoUser u2(m_tmp2);
+ QString baseDir = args.count() > 1
+ ? IoUtils::resolvePath(currentDirectory(), u2.set(args.at(1)))
+ : currentDirectory();
+ QString absArg = u1.str().isEmpty() ? baseDir : IoUtils::resolvePath(baseDir, u1.str());
+ QString rstr = QDir(baseDir).relativeFilePath(absArg);
+ ret << u1.extract(rstr);
break;
- case E_CLEAN_PATH:
- if (args.count() != 1) {
- evalError(fL1S("clean_path(path) requires one argument."));
- } else {
- QString rstr = QDir::cleanPath(args.at(0).toQString(m_tmp1));
- ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) : ProString(rstr).setSource(args.at(0)));
- }
+ }
+ case E_CLEAN_PATH: {
+ ProStringRwUser u1(args.at(0), m_tmp1);
+ ret << u1.extract(QDir::cleanPath(u1.str()));
break;
- case E_SYSTEM_PATH:
- if (args.count() != 1) {
- evalError(fL1S("system_path(path) requires one argument."));
- } else {
- QString rstr = args.at(0).toQString(m_tmp1);
+ }
+ case E_SYSTEM_PATH: {
+ ProStringRwUser u1(args.at(0), m_tmp1);
+ QString rstr = u1.str();
#ifdef Q_OS_WIN
- rstr.replace(QLatin1Char('/'), QLatin1Char('\\'));
+ rstr.replace(QLatin1Char('/'), QLatin1Char('\\'));
#else
- rstr.replace(QLatin1Char('\\'), QLatin1Char('/'));
+ rstr.replace(QLatin1Char('\\'), QLatin1Char('/'));
#endif
- ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) : ProString(rstr).setSource(args.at(0)));
- }
+ ret << u1.extract(rstr);
break;
- case E_SHELL_PATH:
- if (args.count() != 1) {
- evalError(fL1S("shell_path(path) requires one argument."));
+ }
+ case E_SHELL_PATH: {
+ ProStringRwUser u1(args.at(0), m_tmp1);
+ QString rstr = u1.str();
+ if (m_dirSep.startsWith(QLatin1Char('\\'))) {
+ rstr.replace(QLatin1Char('/'), QLatin1Char('\\'));
} else {
- QString rstr = args.at(0).toQString(m_tmp1);
- if (m_dirSep.startsWith(QLatin1Char('\\'))) {
- rstr.replace(QLatin1Char('/'), QLatin1Char('\\'));
- } else {
- rstr.replace(QLatin1Char('\\'), QLatin1Char('/'));
+ rstr.replace(QLatin1Char('\\'), QLatin1Char('/'));
#ifdef Q_OS_WIN
- // Convert d:/foo/bar to msys-style /d/foo/bar.
- if (rstr.length() > 2 && rstr.at(1) == QLatin1Char(':') && rstr.at(2) == QLatin1Char('/')) {
- rstr[1] = rstr.at(0);
- rstr[0] = QLatin1Char('/');
- }
-#endif
+ // Convert d:/foo/bar to msys-style /d/foo/bar.
+ if (rstr.length() > 2 && rstr.at(1) == QLatin1Char(':') && rstr.at(2) == QLatin1Char('/')) {
+ rstr[1] = rstr.at(0);
+ rstr[0] = QLatin1Char('/');
}
- ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) : ProString(rstr).setSource(args.at(0)));
+#endif
}
+ ret << u1.extract(rstr);
break;
- case E_SYSTEM_QUOTE:
- if (args.count() != 1) {
- evalError(fL1S("system_quote(arg) requires one argument."));
- } else {
- QString rstr = IoUtils::shellQuote(args.at(0).toQString(m_tmp1));
- ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) : ProString(rstr).setSource(args.at(0)));
- }
+ }
+ case E_SYSTEM_QUOTE: {
+ ProStringRwUser u1(args.at(0), m_tmp1);
+ ret << u1.extract(IoUtils::shellQuote(u1.str()));
break;
- case E_SHELL_QUOTE:
- if (args.count() != 1) {
- evalError(fL1S("shell_quote(arg) requires one argument."));
- } else {
- QString rstr = args.at(0).toQString(m_tmp1);
- if (m_dirSep.startsWith(QLatin1Char('\\')))
- rstr = IoUtils::shellQuoteWin(rstr);
- else
- rstr = IoUtils::shellQuoteUnix(rstr);
- ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) : ProString(rstr).setSource(args.at(0)));
- }
+ }
+ case E_SHELL_QUOTE: {
+ ProStringRwUser u1(args.at(0), m_tmp1);
+ QString rstr = u1.str();
+ if (m_dirSep.startsWith(QLatin1Char('\\')))
+ rstr = IoUtils::shellQuoteWin(rstr);
+ else
+ rstr = IoUtils::shellQuoteUnix(rstr);
+ ret << u1.extract(rstr);
break;
- case E_GETENV:
- if (args.count() != 1) {
- evalError(fL1S("getenv(arg) requires one argument."));
- } else {
- const ProString &var = args.at(0);
- const ProString &val = ProString(m_option->getEnv(var.toQString(m_tmp1)));
- ret << val;
- }
+ }
+ case E_GETENV: {
+ ProStringRoUser u1(args.at(0), m_tmp1);
+ ret << ProString(m_option->getEnv(u1.str()));
break;
+ }
default:
evalError(fL1S("Function '%1' is not implemented.").arg(func.toQStringView()));
break;
}
+ allfail:
return ReturnTrue;
}
@@ -1306,7 +1245,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::testFunc_cache(const ProStringList &
} else if (opt == QLatin1String("sub")) {
mode = CacheSub;
} else {
- evalError(fL1S("cache(): invalid flag %1.").arg(opt.toQString(m_tmp3)));
+ evalError(fL1S("cache(): invalid flag %1.").arg(opt.toQStringView()));
return ReturnFalse;
}
}
@@ -1450,17 +1389,18 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::testFunc_cache(const ProStringList &
}
QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
- int func_t, const ProKey &function, const ProStringList &args)
+ const QMakeInternal::QMakeBuiltin &adef, const ProKey &function, const ProStringList &args)
{
traceMsg("calling built-in %s(%s)", dbgKey(function), dbgSepStrList(args));
+ int asz = args.size() > 1 ? args.size() : args.at(0).isEmpty() ? 0 : 1;
+ if (asz < adef.minArgs || asz > adef.maxArgs) {
+ evalError(adef.usage);
+ return ReturnFalse;
+ }
+ int func_t = adef.index;
switch (func_t) {
case T_DEFINED: {
- if (args.count() < 1 || args.count() > 2) {
- evalError(fL1S("defined(function, [\"test\"|\"replace\"|\"var\"])"
- " requires one or two arguments."));
- return ReturnFalse;
- }
const ProKey &var = args.at(0).toKey();
if (args.count() > 1) {
if (args[1] == QLatin1String("test")) {
@@ -1479,10 +1419,6 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|| m_functionDefs.testFunctions.contains(var));
}
case T_EXPORT: {
- if (args.count() != 1) {
- evalError(fL1S("export(variable) requires one argument."));
- return ReturnFalse;
- }
const ProKey &var = map(args.at(0));
for (ProValueMapStack::Iterator vmi = m_valuemapStack.end();
--vmi != m_valuemapStack.begin(); ) {
@@ -1503,15 +1439,12 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
return ReturnTrue;
}
case T_DISCARD_FROM: {
- if (args.count() != 1 || args.at(0).isEmpty()) {
- evalError(fL1S("discard_from(file) requires one argument."));
- return ReturnFalse;
- }
if (m_valuemapStack.count() != 1) {
evalError(fL1S("discard_from() cannot be called from functions."));
return ReturnFalse;
}
- QString fn = resolvePath(args.at(0).toQString(m_tmp1));
+ ProStringRoUser u1(args.at(0), m_tmp1);
+ QString fn = resolvePath(u1.str());
QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
int pro = m_vfs->idForFileName(fn, flags | QMakeVfs::VfsAccessedOnly);
if (!pro)
@@ -1550,32 +1483,34 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
iif.removeAt(idx);
return ReturnTrue;
}
- case T_INFILE:
- if (args.count() < 2 || args.count() > 3) {
- evalError(fL1S("infile(file, var, [values]) requires two or three arguments."));
- } else {
- ProValueMap vars;
- QString fn = resolvePath(m_option->expandEnvVars(args.at(0).toQString(m_tmp1)));
- fn.detach();
- VisitReturn ok = evaluateFileInto(fn, &vars, LoadProOnly);
- if (ok != ReturnTrue)
- return ok;
- if (args.count() == 2)
- return returnBool(vars.contains(map(args.at(1))));
- QRegExp regx;
- const QString &qry = args.at(2).toQString(m_tmp1);
- if (qry != QRegExp::escape(qry)) {
- QString copy = qry;
- copy.detach();
- regx.setPattern(copy);
- }
- const auto strings = vars.value(map(args.at(1)));
- for (const ProString &s : strings) {
- if ((!regx.isEmpty() && regx.exactMatch(s.toQString(m_tmp[m_toggle ^= 1]))) || s == qry)
+ case T_INFILE: {
+ ProValueMap vars;
+ QString fn = filePathEnvArg0(args);
+ VisitReturn ok = evaluateFileInto(fn, &vars, LoadProOnly);
+ if (ok != ReturnTrue)
+ return ok;
+ if (args.count() == 2)
+ return returnBool(vars.contains(map(args.at(1))));
+ QRegExp regx;
+ ProStringRoUser u1(args.at(2), m_tmp1);
+ const QString &qry = u1.str();
+ if (qry != QRegExp::escape(qry)) {
+ QString copy = qry;
+ copy.detach();
+ regx.setPattern(copy);
+ }
+ const auto strings = vars.value(map(args.at(1)));
+ for (const ProString &s : strings) {
+ if (s == qry)
+ return ReturnTrue;
+ if (!regx.isEmpty()) {
+ ProStringRoUser u2(s, m_tmp[m_toggle ^= 1]);
+ if (regx.exactMatch(u2.str()))
return ReturnTrue;
}
}
return ReturnFalse;
+ }
case T_REQUIRES:
#ifdef PROEVALUATOR_FULL
if (checkRequirements(args) == ReturnError)
@@ -1583,32 +1518,24 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
#endif
return ReturnFalse; // Another qmake breakage
case T_EVAL: {
- VisitReturn ret = ReturnFalse;
- QString contents = args.join(statics.field_sep);
- ProFile *pro = m_parser->parsedProBlock(QStringRef(&contents),
- 0, m_current.pro->fileName(), m_current.line);
- if (m_cumulative || pro->isOk()) {
- m_locationStack.push(m_current);
- visitProBlock(pro, pro->tokPtr());
- ret = ReturnTrue; // This return value is not too useful, but that's qmake
- m_current = m_locationStack.pop();
- }
- pro->deref();
- return ret;
- }
+ VisitReturn ret = ReturnFalse;
+ QString contents = args.join(statics.field_sep);
+ ProFile *pro = m_parser->parsedProBlock(QStringRef(&contents),
+ 0, m_current.pro->fileName(), m_current.line);
+ if (m_cumulative || pro->isOk()) {
+ m_locationStack.push(m_current);
+ visitProBlock(pro, pro->tokPtr());
+ ret = ReturnTrue; // This return value is not too useful, but that's qmake
+ m_current = m_locationStack.pop();
+ }
+ pro->deref();
+ return ret;
+ }
case T_IF: {
- if (args.count() != 1) {
- evalError(fL1S("if(condition) requires one argument."));
- return ReturnFalse;
- }
return evaluateConditional(args.at(0).toQStringRef(),
m_current.pro->fileName(), m_current.line);
}
case T_CONFIG: {
- if (args.count() < 1 || args.count() > 2) {
- evalError(fL1S("CONFIG(config) requires one or two arguments."));
- return ReturnFalse;
- }
if (args.count() == 1)
return returnBool(isActiveConfig(args.at(0).toQStringRef()));
const auto mutuals = args.at(1).toQStringRef().split(QLatin1Char('|'),
@@ -1624,12 +1551,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
return ReturnFalse;
}
case T_CONTAINS: {
- if (args.count() < 2 || args.count() > 3) {
- evalError(fL1S("contains(var, val) requires two or three arguments."));
- return ReturnFalse;
- }
-
- const QString &qry = args.at(1).toQString(m_tmp1);
+ ProStringRoUser u1(args.at(1), m_tmp1);
+ const QString &qry = u1.str();
QRegExp regx;
if (qry != QRegExp::escape(qry)) {
QString copy = qry;
@@ -1640,19 +1563,29 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
if (args.count() == 2) {
for (int i = 0; i < l.size(); ++i) {
const ProString &val = l[i];
- if ((!regx.isEmpty() && regx.exactMatch(val.toQString(m_tmp[m_toggle ^= 1]))) || val == qry)
+ if (val == qry)
return ReturnTrue;
+ if (!regx.isEmpty()) {
+ ProStringRoUser u2(val, m_tmp[m_toggle ^= 1]);
+ if (regx.exactMatch(u2.str()))
+ return ReturnTrue;
+ }
}
} else {
const auto mutuals = args.at(2).toQStringRef().split(QLatin1Char('|'),
QString::SkipEmptyParts);
for (int i = l.size() - 1; i >= 0; i--) {
- const ProString val = l[i];
+ const ProString &val = l[i];
for (int mut = 0; mut < mutuals.count(); mut++) {
if (val.toQStringRef() == mutuals[mut].trimmed()) {
- return returnBool((!regx.isEmpty()
- && regx.exactMatch(val.toQString(m_tmp[m_toggle ^= 1])))
- || val == qry);
+ if (val == qry)
+ return ReturnTrue;
+ if (!regx.isEmpty()) {
+ ProStringRoUser u2(val, m_tmp[m_toggle ^= 1]);
+ if (regx.exactMatch(u2.str()))
+ return ReturnTrue;
+ }
+ return ReturnFalse;
}
}
}
@@ -1660,10 +1593,6 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
return ReturnFalse;
}
case T_COUNT: {
- if (args.count() != 2 && args.count() != 3) {
- evalError(fL1S("count(var, count, op=\"equals\") requires two or three arguments."));
- return ReturnFalse;
- }
int cnt = values(map(args.at(0))).count();
int val = args.at(1).toInt();
if (args.count() == 3) {
@@ -1688,11 +1617,6 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
}
case T_GREATERTHAN:
case T_LESSTHAN: {
- if (args.count() != 2) {
- evalError(fL1S("%1(variable, value) requires two arguments.")
- .arg(function.toQStringView()));
- return ReturnFalse;
- }
const ProString &rhs = args.at(1);
const QString &lhs = values(map(args.at(0))).join(statics.field_sep);
bool ok;
@@ -1710,20 +1634,10 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
return returnBool(lhs < rhs.toQStringRef());
}
case T_EQUALS:
- if (args.count() != 2) {
- evalError(fL1S("%1(variable, value) requires two arguments.")
- .arg(function.toQStringView()));
- return ReturnFalse;
- }
return returnBool(values(map(args.at(0))).join(statics.field_sep)
== args.at(1).toQStringView());
case T_VERSION_AT_LEAST:
case T_VERSION_AT_MOST: {
- if (args.count() != 2) {
- evalError(fL1S("%1(variable, versionNumber) requires two arguments.")
- .arg(function.toQStringView()));
- return ReturnFalse;
- }
const QVersionNumber lvn = QVersionNumber::fromString(values(args.at(0).toKey()).join('.'));
const QVersionNumber rvn = QVersionNumber::fromString(args.at(1).toQStringView());
if (func_t == T_VERSION_AT_LEAST)
@@ -1731,11 +1645,6 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
return returnBool(lvn <= rvn);
}
case T_CLEAR: {
- if (args.count() != 1) {
- evalError(fL1S("%1(variable) requires one argument.")
- .arg(function.toQStringView()));
- return ReturnFalse;
- }
ProValueMap *hsh;
ProValueMap::Iterator it;
const ProKey &var = map(args.at(0));
@@ -1748,11 +1657,6 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
return ReturnTrue;
}
case T_UNSET: {
- if (args.count() != 1) {
- evalError(fL1S("%1(variable) requires one argument.")
- .arg(function.toQStringView()));
- return ReturnFalse;
- }
ProValueMap *hsh;
ProValueMap::Iterator it;
const ProKey &var = map(args.at(0));
@@ -1768,23 +1672,15 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
}
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
case T_PARSE_JSON: {
- if (args.count() != 2) {
- evalError(fL1S("parseJson(variable, into) requires two arguments."));
- return ReturnFalse;
- }
-
QByteArray json = values(args.at(0).toKey()).join(QLatin1Char(' ')).toUtf8();
- QString parseInto = args.at(1).toQString(m_tmp2);
+ ProStringRoUser u1(args.at(1), m_tmp2);
+ QString parseInto = u1.str();
return parseJsonInto(json, parseInto, &m_valuemapStack.top());
}
#endif
case T_INCLUDE: {
- if (args.count() < 1 || args.count() > 3) {
- evalError(fL1S("include(file, [into, [silent]]) requires one, two or three arguments."));
- return ReturnFalse;
- }
QString parseInto;
- LoadFlags flags = 0;
+ LoadFlags flags;
if (m_cumulative)
flags = LoadSilent;
if (args.count() >= 2) {
@@ -1793,8 +1689,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
if (args.count() >= 3 && isTrue(args.at(2)))
flags = LoadSilent;
}
- QString fn = resolvePath(m_option->expandEnvVars(args.at(0).toQString(m_tmp1)));
- fn.detach();
+ QString fn = filePathEnvArg0(args);
VisitReturn ok;
if (parseInto.isEmpty()) {
ok = evaluateFileChecked(fn, QMakeHandler::EvalIncludeFile, LoadProOnly | flags);
@@ -1812,9 +1707,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
}
for (ProValueMap::ConstIterator it = symbols.constBegin();
it != symbols.constEnd(); ++it) {
- const QString &ky = it.key().toQString(m_tmp1);
- if (!ky.startsWith(QLatin1Char('.')))
- newMap.insert(ProKey(parseInto + ky), it.value());
+ if (!it.key().startsWith(QLatin1Char('.')))
+ newMap.insert(ProKey(parseInto + it.key()), it.value());
}
m_valuemapStack.top() = newMap;
}
@@ -1824,13 +1718,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
return ok;
}
case T_LOAD: {
- bool ignore_error = false;
- if (args.count() == 2) {
- ignore_error = isTrue(args.at(1));
- } else if (args.count() != 1) {
- evalError(fL1S("load(feature) requires one or two arguments."));
- return ReturnFalse;
- }
+ bool ignore_error = (args.count() == 2 && isTrue(args.at(1)));
VisitReturn ok = evaluateFeatureFile(m_option->expandEnvVars(args.at(0).toQString()),
ignore_error);
if (ok == ReturnFalse && ignore_error)
@@ -1839,13 +1727,10 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
}
case T_DEBUG: {
#ifdef PROEVALUATOR_DEBUG
- if (args.count() != 2) {
- evalError(fL1S("debug(level, message) requires two arguments."));
- return ReturnFalse;
- }
int level = args.at(0).toInt();
if (level <= m_debugLevel) {
- const QString &msg = m_option->expandEnvVars(args.at(1).toQString(m_tmp2));
+ ProStringRoUser u1(args.at(1), m_tmp1);
+ const QString &msg = m_option->expandEnvVars(u1.str());
debugMsg(level, "Project DEBUG: %s", qPrintable(msg));
}
#endif
@@ -1855,33 +1740,26 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
case T_ERROR:
case T_WARNING:
case T_MESSAGE: {
- if (args.count() != 1) {
- evalError(fL1S("%1(message) requires one argument.")
- .arg(function.toQStringView()));
- return ReturnFalse;
- }
- const QString &msg = m_option->expandEnvVars(args.at(0).toQString(m_tmp2));
+ ProStringRoUser u1(args.at(0), m_tmp1);
+ const QString &msg = m_option->expandEnvVars(u1.str());
if (!m_skipLevel) {
if (func_t == T_LOG) {
#ifdef PROEVALUATOR_FULL
fputs(msg.toLatin1().constData(), stderr);
#endif
} else if (!msg.isEmpty() || func_t != T_ERROR) {
+ ProStringRoUser u2(function, m_tmp2);
m_handler->fileMessage(
(func_t == T_ERROR ? QMakeHandler::ErrorMessage :
func_t == T_WARNING ? QMakeHandler::WarningMessage :
QMakeHandler::InfoMessage)
| (m_cumulative ? QMakeHandler::CumulativeEvalMessage : 0),
- fL1S("Project %1: %2").arg(function.toQString(m_tmp1).toUpper(), msg));
+ fL1S("Project %1: %2").arg(u2.str().toUpper(), msg));
}
}
return (func_t == T_ERROR && !m_cumulative) ? ReturnError : ReturnTrue;
}
case T_SYSTEM: {
- if (args.count() != 1) {
- evalError(fL1S("system(exec) requires one argument."));
- return ReturnFalse;
- }
#ifdef PROEVALUATOR_FULL
if (m_cumulative) // Anything else would be insanity
return ReturnFalse;
@@ -1905,19 +1783,10 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
#endif
}
case T_ISEMPTY: {
- if (args.count() != 1) {
- evalError(fL1S("isEmpty(var) requires one argument."));
- return ReturnFalse;
- }
return returnBool(values(map(args.at(0))).isEmpty());
}
case T_EXISTS: {
- if (args.count() != 1) {
- evalError(fL1S("exists(file) requires one argument."));
- return ReturnFalse;
- }
- const QString &file = resolvePath(m_option->expandEnvVars(args.at(0).toQString(m_tmp1)));
-
+ QString file = filePathEnvArg0(args);
// Don't use VFS here:
// - it supports neither listing nor even directories
// - it's unlikely that somebody would test for files they created themselves
@@ -1925,7 +1794,6 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
return ReturnTrue;
int slsh = file.lastIndexOf(QLatin1Char('/'));
QString fn = file.mid(slsh+1);
- fn.detach();
if (fn.contains(QLatin1Char('*')) || fn.contains(QLatin1Char('?'))) {
QString dirstr = file.left(slsh+1);
dirstr.detach();
@@ -1936,13 +1804,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
return ReturnFalse;
}
case T_MKPATH: {
- if (args.count() != 1) {
- evalError(fL1S("mkpath(file) requires one argument."));
- return ReturnFalse;
- }
#ifdef PROEVALUATOR_FULL
- QString fn = resolvePath(args.at(0).toQString(m_tmp1));
- fn.detach();
+ QString fn = filePathArg0(args);
if (!QDir::current().mkpath(fn)) {
evalError(fL1S("Cannot create directory %1.").arg(QDir::toNativeSeparators(fn)));
return ReturnFalse;
@@ -1951,10 +1814,6 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
return ReturnTrue;
}
case T_WRITE_FILE: {
- if (args.count() > 3) {
- evalError(fL1S("write_file(name, [content var, [append] [exe]]) requires one to three arguments."));
- return ReturnFalse;
- }
QIODevice::OpenMode mode = QIODevice::Truncate;
QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
QString contents;
@@ -1970,24 +1829,21 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
} else if (opt == QLatin1String("exe")) {
flags |= QMakeVfs::VfsExecutable;
} else {
- evalError(fL1S("write_file(): invalid flag %1.").arg(opt.toQString(m_tmp3)));
+ evalError(fL1S("write_file(): invalid flag %1.").arg(opt.toQStringView()));
return ReturnFalse;
}
}
}
}
- QString path = resolvePath(args.at(0).toQString(m_tmp1));
- path.detach(); // make sure to not leak m_tmp1 into the map of written files.
+ QString path = filePathArg0(args);
return writeFile(QString(), path, mode, flags, contents);
}
case T_TOUCH: {
- if (args.count() != 2) {
- evalError(fL1S("touch(file, reffile) requires two arguments."));
- return ReturnFalse;
- }
#ifdef PROEVALUATOR_FULL
- const QString &tfn = resolvePath(args.at(0).toQString(m_tmp1));
- const QString &rfn = resolvePath(args.at(1).toQString(m_tmp2));
+ ProStringRoUser u1(args.at(0), m_tmp1);
+ ProStringRoUser u2(args.at(1), m_tmp2);
+ const QString &tfn = resolvePath(u1.str());
+ const QString &rfn = resolvePath(u2.str());
QString error;
if (!IoUtils::touchFile(tfn, rfn, &error)) {
evalError(error);
@@ -1997,10 +1853,6 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
return ReturnTrue;
}
case T_CACHE:
- if (args.count() > 3) {
- evalError(fL1S("cache(var, [set|add|sub] [transient] [super|stash], [srcvar]) requires one to three arguments."));
- return ReturnFalse;
- }
return testFunc_cache(args);
case T_RELOAD_PROPERTIES:
#ifdef QT_BUILD_QMAKE
diff --git a/qmake/library/qmakeevaluator.cpp b/qmake/library/qmakeevaluator.cpp
index 6b23412327..432339d48e 100644
--- a/qmake/library/qmakeevaluator.cpp
+++ b/qmake/library/qmakeevaluator.cpp
@@ -118,7 +118,7 @@ bool operator==(const QMakeBaseKey &one, const QMakeBaseKey &two)
}
QMakeBaseEnv::QMakeBaseEnv()
- : evaluator(0)
+ : evaluator(nullptr)
{
#ifdef PROEVALUATOR_THREAD_SAFE
inProgress = false;
@@ -215,7 +215,7 @@ QMakeEvaluator::QMakeEvaluator(QMakeGlobals *option, QMakeParser *parser, QMakeV
initStatics();
// Configuration, more or less
- m_caller = 0;
+ m_caller = nullptr;
#ifdef PROEVALUATOR_CUMULATIVE
m_cumulative = false;
#endif
@@ -337,7 +337,8 @@ static void replaceInList(ProStringList *varlist,
const QRegExp &regexp, const QString &replace, bool global, QString &tmp)
{
for (ProStringList::Iterator varit = varlist->begin(); varit != varlist->end(); ) {
- QString val = varit->toQString(tmp);
+ ProStringRoUser u1(*varit, tmp);
+ QString val = u1.str();
QString copy = val; // Force detach and have a reference value
val.replace(regexp, replace);
if (!val.isSharedWith(copy) && val != copy) {
@@ -940,7 +941,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProVariable(
if (varName == statics.strTEMPLATE)
setTemplate();
else if (varName == statics.strQMAKE_PLATFORM)
- m_featureRoots = 0;
+ m_featureRoots = nullptr;
else if (varName == statics.strQMAKE_DIR_SEP)
m_dirSep = first(varName);
else if (varName == statics.strQMAKESPEC) {
@@ -949,7 +950,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProVariable(
if (IoUtils::isAbsolutePath(spec)) {
m_qmakespec = spec;
m_qmakespecName = IoUtils::fileName(m_qmakespec).toString();
- m_featureRoots = 0;
+ m_featureRoots = nullptr;
}
}
}
@@ -1336,7 +1337,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConfigFeatures()
bool finished = true;
ProStringList configs = values(statics.strCONFIG);
for (int i = configs.size() - 1; i >= 0; --i) {
- QString config = configs.at(i).toQString(m_tmp1).toLower();
+ ProStringRoUser u1(configs.at(i), m_tmp1);
+ QString config = u1.str().toLower();
if (!processed.contains(config)) {
config.detach();
processed.insert(config);
@@ -1592,7 +1594,7 @@ ProFile *QMakeEvaluator::currentProFile() const
{
if (m_profileStack.count() > 0)
return m_profileStack.top();
- return 0;
+ return nullptr;
}
int QMakeEvaluator::currentFileId() const
@@ -1640,7 +1642,8 @@ bool QMakeEvaluator::isActiveConfig(const QStringRef &config, bool regex)
// CONFIG variable
const auto configValues = values(statics.strCONFIG);
for (const ProString &configValue : configValues) {
- if (re.exactMatch(configValue.toQString(m_tmp[m_toggle ^= 1])))
+ ProStringRoUser u1(configValue, m_tmp[m_toggle ^= 1]);
+ if (re.exactMatch(u1.str()))
return true;
}
} else {
@@ -1749,9 +1752,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBoolFunction(
if (val)
return ReturnTrue;
} else {
+ ProStringRoUser u1(function, m_tmp1);
evalError(fL1S("Unexpected return value from test '%1': %2.")
- .arg(function.toQString(m_tmp1))
- .arg(ret.join(QLatin1String(" :: "))));
+ .arg(u1.str(), ret.join(QLatin1String(" :: "))));
}
}
return ReturnFalse;
@@ -1762,12 +1765,13 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBoolFunction(
QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditionalFunction(
const ProKey &func, const ushort *&tokPtr)
{
- if (int func_t = statics.functions.value(func)) {
+ auto adef = statics.functions.constFind(func);
+ if (adef != statics.functions.constEnd()) {
//why don't the builtin functions just use args_list? --Sam
ProStringList args;
if (expandVariableReferences(tokPtr, 5, &args, true) == ReturnError)
return ReturnError;
- return evaluateBuiltinConditional(func_t, func, args);
+ return evaluateBuiltinConditional(*adef, func, args);
}
QHash<ProKey, ProFunctionDef>::ConstIterator it =
@@ -1788,12 +1792,13 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditionalFunction(
QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateExpandFunction(
const ProKey &func, const ushort *&tokPtr, ProStringList *ret)
{
- if (int func_t = statics.expands.value(func)) {
+ auto adef = statics.expands.constFind(func);
+ if (adef != statics.expands.constEnd()) {
//why don't the builtin functions just use args_list? --Sam
ProStringList args;
if (expandVariableReferences(tokPtr, 5, &args, true) == ReturnError)
return ReturnError;
- return evaluateBuiltinExpand(func_t, func, args, *ret);
+ return evaluateBuiltinExpand(*adef, func, args, *ret);
}
QHash<ProKey, ProFunctionDef>::ConstIterator it =
@@ -1869,7 +1874,7 @@ ProValueMap *QMakeEvaluator::findValues(const ProKey &variableName, ProValueMap:
if (first && isFunctParam(variableName))
break;
}
- return 0;
+ return nullptr;
}
ProStringList &QMakeEvaluator::valuesRef(const ProKey &variableName)
diff --git a/qmake/library/qmakeevaluator.h b/qmake/library/qmakeevaluator.h
index dc35e1ddab..f617681cbb 100644
--- a/qmake/library/qmakeevaluator.h
+++ b/qmake/library/qmakeevaluator.h
@@ -105,6 +105,8 @@ public:
const ProValueMap &top() const { return last(); }
};
+namespace QMakeInternal { struct QMakeBuiltin; }
+
class QMAKE_EXPORT QMakeEvaluator
{
public:
@@ -186,6 +188,8 @@ public:
int currentFileId() const;
QString resolvePath(const QString &fileName) const
{ return QMakeInternal::IoUtils::resolvePath(currentDirectory(), fileName); }
+ QString filePathArg0(const ProStringList &args);
+ QString filePathEnvArg0(const ProStringList &args);
VisitReturn evaluateFile(const QString &fileName, QMakeHandler::EvalFileType type,
LoadFlags flags);
@@ -214,8 +218,10 @@ public:
VisitReturn evaluateExpandFunction(const ProKey &function, const ushort *&tokPtr, ProStringList *ret);
VisitReturn evaluateConditionalFunction(const ProKey &function, const ushort *&tokPtr);
- VisitReturn evaluateBuiltinExpand(int func_t, const ProKey &function, const ProStringList &args, ProStringList &ret);
- VisitReturn evaluateBuiltinConditional(int func_t, const ProKey &function, const ProStringList &args);
+ VisitReturn evaluateBuiltinExpand(const QMakeInternal::QMakeBuiltin &adef,
+ const ProKey &function, const ProStringList &args, ProStringList &ret);
+ VisitReturn evaluateBuiltinConditional(const QMakeInternal::QMakeBuiltin &adef,
+ const ProKey &function, const ProStringList &args);
VisitReturn evaluateConditional(const QStringRef &cond, const QString &where, int line = -1);
#ifdef PROEVALUATOR_FULL
@@ -276,9 +282,9 @@ public:
#endif
struct Location {
- Location() : pro(0), line(0) {}
+ Location() : pro(nullptr), line(0) {}
Location(ProFile *_pro, ushort _line) : pro(_pro), line(_line) {}
- void clear() { pro = 0; line = 0; }
+ void clear() { pro = nullptr; line = 0; }
ProFile *pro;
ushort line;
};
diff --git a/qmake/library/qmakeevaluator_p.h b/qmake/library/qmakeevaluator_p.h
index f386a49108..f888bc5765 100644
--- a/qmake/library/qmakeevaluator_p.h
+++ b/qmake/library/qmakeevaluator_p.h
@@ -64,6 +64,22 @@ QT_BEGIN_NAMESPACE
namespace QMakeInternal {
+struct QMakeBuiltinInit
+{
+ const char *name;
+ int func;
+ enum { VarArgs = 1000 };
+ int min_args, max_args;
+ const char *args;
+};
+
+struct QMakeBuiltin
+{
+ QMakeBuiltin(const QMakeBuiltinInit &data);
+ QString usage;
+ int index, minArgs, maxArgs;
+};
+
struct QMakeStatics {
QString field_sep;
QString strtrue;
@@ -83,8 +99,8 @@ struct QMakeStatics {
#ifdef PROEVALUATOR_FULL
ProKey strREQUIRES;
#endif
- QHash<ProKey, int> expands;
- QHash<ProKey, int> functions;
+ QHash<ProKey, QMakeBuiltin> expands;
+ QHash<ProKey, QMakeBuiltin> functions;
QHash<ProKey, ProKey> varMap;
ProStringList fakeValue;
};
@@ -93,6 +109,8 @@ extern QMakeStatics statics;
}
+Q_DECLARE_TYPEINFO(QMakeInternal::QMakeBuiltin, Q_MOVABLE_TYPE);
+
QT_END_NAMESPACE
#endif // QMAKEEVALUATOR_P_H
diff --git a/qmake/library/qmakeparser.cpp b/qmake/library/qmakeparser.cpp
index 37608c7a15..4c8360b459 100644
--- a/qmake/library/qmakeparser.cpp
+++ b/qmake/library/qmakeparser.cpp
@@ -45,11 +45,17 @@ QT_BEGIN_NAMESPACE
//
///////////////////////////////////////////////////////////////////////
+ProFileCache::ProFileCache()
+{
+ QMakeVfs::ref();
+}
+
ProFileCache::~ProFileCache()
{
for (const Entry &ent : qAsConst(parsed_files))
if (ent.pro)
ent.pro->deref();
+ QMakeVfs::deref();
}
void ProFileCache::discardFile(const QString &fileName, QMakeVfs *vfs)
@@ -215,7 +221,7 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
pro->itemsRef()->squeeze();
pro->ref();
} else {
- pro = 0;
+ pro = nullptr;
}
ent->pro = pro;
#ifdef PROPARSER_THREAD_SAFE
@@ -234,7 +240,7 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
if (readFile(id, flags, &contents))
pro = parsedProBlock(QStringRef(&contents), id, fileName, 1, FullGrammar);
else
- pro = 0;
+ pro = nullptr;
}
return pro;
}
@@ -437,7 +443,7 @@ void QMakeParser::read(ProFile *pro, const QStringRef &in, int line, SubGrammar
if (context == CtxPureValue) {
end = inend;
- cptr = 0;
+ cptr = nullptr;
lineCont = false;
indent = 0; // just gcc being stupid
goto nextChr;
@@ -449,7 +455,7 @@ void QMakeParser::read(ProFile *pro, const QStringRef &in, int line, SubGrammar
// First, skip leading whitespace
for (indent = 0; ; ++cur, ++indent) {
if (cur == inend) {
- cur = 0;
+ cur = nullptr;
goto flushLine;
}
c = *cur;
@@ -1112,7 +1118,7 @@ void QMakeParser::finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int arg
if (uc == ptr) {
// for(literal) (only "ever" would be legal if qmake was sane)
putTok(tokPtr, TokForLoop);
- putHashStr(tokPtr, (ushort *)0, (uint)0);
+ putHashStr(tokPtr, nullptr, (uint)0);
putBlockLen(tokPtr, 1 + 3 + nlen + 1);
putTok(tokPtr, TokHashLiteral);
putHashStr(tokPtr, uce + 2, nlen);
@@ -1135,7 +1141,7 @@ void QMakeParser::finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int arg
} else if (argc == 1) {
// for(non-literal) (this wouldn't be here if qmake was sane)
putTok(tokPtr, TokForLoop);
- putHashStr(tokPtr, (ushort *)0, (uint)0);
+ putHashStr(tokPtr, nullptr, (uint)0);
uc = uce;
goto doFor;
}
diff --git a/qmake/library/qmakeparser.h b/qmake/library/qmakeparser.h
index 3ae30dcf74..7b96d4e88f 100644
--- a/qmake/library/qmakeparser.h
+++ b/qmake/library/qmakeparser.h
@@ -110,7 +110,7 @@ private:
};
struct BlockScope {
- BlockScope() : start(0), braceLevel(0), special(false), inBranch(false), nest(NestNone) {}
+ BlockScope() : start(nullptr), braceLevel(0), special(false), inBranch(false), nest(NestNone) {}
BlockScope(const BlockScope &other) { *this = other; }
ushort *start; // Where this block started; store length here
int braceLevel; // Nesting of braces in scope
@@ -201,7 +201,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QMakeParser::ParseFlags)
class QMAKE_EXPORT ProFileCache
{
public:
- ProFileCache() {}
+ ProFileCache();
~ProFileCache();
void discardFile(int id);
diff --git a/qmake/library/qmakevfs.cpp b/qmake/library/qmakevfs.cpp
index 2239a2beec..3a54ef4023 100644
--- a/qmake/library/qmakevfs.cpp
+++ b/qmake/library/qmakevfs.cpp
@@ -52,11 +52,38 @@ QMakeVfs::QMakeVfs()
#ifndef QT_NO_TEXTCODEC
m_textCodec = 0;
#endif
+ ref();
+}
+
+QMakeVfs::~QMakeVfs()
+{
+ deref();
+}
+
+void QMakeVfs::ref()
+{
+#ifdef PROEVALUATOR_THREAD_SAFE
+ QMutexLocker locker(&s_mutex);
+#endif
+ ++s_refCount;
+}
+
+void QMakeVfs::deref()
+{
+#ifdef PROEVALUATOR_THREAD_SAFE
+ QMutexLocker locker(&s_mutex);
+#endif
+ if (!--s_refCount) {
+ s_fileIdCounter = 0;
+ s_fileIdMap.clear();
+ s_idFileMap.clear();
+ }
}
#ifdef PROPARSER_THREAD_SAFE
QMutex QMakeVfs::s_mutex;
#endif
+int QMakeVfs::s_refCount;
QAtomicInt QMakeVfs::s_fileIdCounter;
QHash<QString, int> QMakeVfs::s_fileIdMap;
QHash<int, QString> QMakeVfs::s_idFileMap;
@@ -114,16 +141,6 @@ QString QMakeVfs::fileNameForId(int id)
return s_idFileMap.value(id);
}
-void QMakeVfs::clearIds()
-{
-#ifdef PROEVALUATOR_THREAD_SAFE
- QMutexLocker locker(&s_mutex);
-#endif
- s_fileIdCounter = 0;
- s_fileIdMap.clear();
- s_idFileMap.clear();
-}
-
bool QMakeVfs::writeFile(int id, QIODevice::OpenMode mode, VfsFlags flags,
const QString &contents, QString *errStr)
{
diff --git a/qmake/library/qmakevfs.h b/qmake/library/qmakevfs.h
index 1217225471..68c21a3d37 100644
--- a/qmake/library/qmakevfs.h
+++ b/qmake/library/qmakevfs.h
@@ -76,10 +76,13 @@ public:
Q_DECLARE_FLAGS(VfsFlags, VfsFlag)
QMakeVfs();
+ ~QMakeVfs();
+
+ static void ref();
+ static void deref();
int idForFileName(const QString &fn, VfsFlags flags);
QString fileNameForId(int id);
- static void clearIds();
bool writeFile(int id, QIODevice::OpenMode mode, VfsFlags flags, const QString &contents, QString *errStr);
ReadResult readFile(int id, QString *contents, QString *errStr);
bool exists(const QString &fn, QMakeVfs::VfsFlags flags);
@@ -97,6 +100,7 @@ private:
#ifdef PROEVALUATOR_THREAD_SAFE
static QMutex s_mutex;
#endif
+ static int s_refCount;
static QAtomicInt s_fileIdCounter;
// Qt Creator's ProFile cache is a singleton to maximize its cross-project
// effectiveness (shared prf files from QtVersions).
diff --git a/qmake/main.cpp b/qmake/main.cpp
index 85709dc9bf..a4ef79227b 100644
--- a/qmake/main.cpp
+++ b/qmake/main.cpp
@@ -455,28 +455,22 @@ int runQMake(int argc, char **argv)
QString oldpwd = qmake_getpwd();
Option::output_dir = oldpwd; //for now this is the output dir
- if(Option::output.fileName() != "-") {
+ if (!Option::output.fileName().isEmpty() && Option::output.fileName() != "-") {
+ // The output 'filename', as given by the -o option, might include one
+ // or more directories, so we may need to rebase the output directory.
QFileInfo fi(Option::output);
- QString dir;
- if(fi.isDir()) {
- dir = fi.filePath();
- } else {
- QString tmp_dir = fi.path();
- if(!tmp_dir.isEmpty() && QFile::exists(tmp_dir))
- dir = tmp_dir;
- }
-#ifdef Q_OS_MAC
- if (fi.fileName().endsWith(QLatin1String(".pbxproj"))
- && dir.endsWith(QLatin1String(".xcodeproj")))
- dir += QStringLiteral("/..");
-#endif
- if(!dir.isNull() && dir != ".")
- Option::output_dir = dir;
- if (QDir::isRelativePath(Option::output_dir)) {
- Option::output.setFileName(fi.fileName());
- Option::output_dir.prepend(oldpwd + QLatin1Char('/'));
+
+ QDir dir(QDir::cleanPath(fi.isDir() ? fi.absoluteFilePath() : fi.absolutePath()));
+
+ // Don't treat Xcode project directory as part of OUT_PWD
+ if (dir.dirName().endsWith(QLatin1String(".xcodeproj"))) {
+ // Note: we're intentionally not using cdUp(), as the dir may not exist
+ dir.setPath(QDir::cleanPath(dir.filePath("..")));
}
- Option::output_dir = QDir::cleanPath(Option::output_dir);
+
+ Option::output_dir = dir.path();
+ QString absoluteFilePath = QDir::cleanPath(fi.absoluteFilePath());
+ Option::output.setFileName(absoluteFilePath.mid(Option::output_dir.length() + 1));
}
QMakeProperty prop;
@@ -552,7 +546,7 @@ int runQMake(int argc, char **argv)
exit_val = 5;
}
delete mkfile;
- mkfile = NULL;
+ mkfile = nullptr;
}
qmakeClearCaches();
return exit_val;
diff --git a/qmake/meta.cpp b/qmake/meta.cpp
index b47645b07f..2e8759b8ba 100644
--- a/qmake/meta.cpp
+++ b/qmake/meta.cpp
@@ -50,49 +50,19 @@ QMakeMetaInfo::readLib(const QString &meta_file)
return true;
}
- bool ret = false;
- if(!meta_file.isNull()) {
- if(meta_file.endsWith(Option::pkgcfg_ext)) {
- if((ret=readPkgCfgFile(meta_file)))
- meta_type = "pkgcfg";
- } else if(meta_file.endsWith(Option::libtool_ext)) {
- if((ret=readLibtoolFile(meta_file)))
- meta_type = "libtool";
- } else if(meta_file.endsWith(Option::prl_ext)) {
- QMakeProject proj;
- if (!proj.read(Option::normalizePath(meta_file), QMakeEvaluator::LoadProOnly))
- return false;
- meta_type = "qmake";
- vars = proj.variables();
- ret = true;
- } else {
- warn_msg(WarnLogic, "QMakeMetaInfo: unknown file format for %s",
- QDir::toNativeSeparators(meta_file).toLatin1().constData());
- }
- }
- if(ret)
- cache_vars.insert(meta_file, vars);
- return ret;
+ QMakeProject proj;
+ if (!proj.read(Option::normalizePath(meta_file), QMakeEvaluator::LoadProOnly))
+ return false;
+ vars = proj.variables();
+ cache_vars.insert(meta_file, vars);
+ return true;
}
QString
-QMakeMetaInfo::findLib(const QString &lib)
+QMakeMetaInfo::checkLib(const QString &lib)
{
- QString ret;
- QString extns[] = { Option::prl_ext, /*Option::pkgcfg_ext, Option::libtool_ext,*/ QString() };
- for(int extn = 0; !extns[extn].isNull(); extn++) {
- if(lib.endsWith(extns[extn]))
- ret = QFile::exists(lib) ? lib : QString();
- }
- if(ret.isNull()) {
- for(int extn = 0; !extns[extn].isNull(); extn++) {
- if(QFile::exists(lib + extns[extn])) {
- ret = lib + extns[extn];
- break;
- }
- }
- }
+ QString ret = QFile::exists(lib) ? lib : QString();
if(ret.isNull()) {
debug_msg(2, "QMakeMetaInfo: Cannot find info file for %s", lib.toLatin1().constData());
} else {
@@ -101,79 +71,4 @@ QMakeMetaInfo::findLib(const QString &lib)
return ret;
}
-
-bool
-QMakeMetaInfo::readLibtoolFile(const QString &f)
-{
- /* I can just run the .la through the .pro parser since they are compatible.. */
- QMakeProject proj;
- QString nf = Option::normalizePath(f);
- if (!proj.read(nf, QMakeEvaluator::LoadProOnly))
- return false;
- QString dirf = nf.section(QLatin1Char('/'), 0, -2);
- if(dirf == nf)
- dirf = "";
- else if(!dirf.isEmpty() && !dirf.endsWith(Option::output_dir))
- dirf += QLatin1Char('/');
- const ProValueMap &v = proj.variables();
- for (ProValueMap::ConstIterator it = v.begin(); it != v.end(); ++it) {
- ProStringList lst = it.value();
- if(lst.count() == 1 && (lst.first().startsWith("'") || lst.first().startsWith("\"")) &&
- lst.first().endsWith(QString(lst.first().at(0))))
- lst = ProStringList(lst.first().mid(1, lst.first().length() - 2));
- if(!vars.contains("QMAKE_PRL_TARGET") &&
- (it.key() == "dlname" || it.key() == "library_names" || it.key() == "old_library")) {
- ProString dir = v["libdir"].first();
- if ((dir.startsWith('\'') || dir.startsWith('"')) && dir.endsWith(dir.at(0)))
- dir = dir.mid(1, dir.length() - 2);
- dir = dir.trimmed();
- if(!dir.isEmpty() && !dir.endsWith(QLatin1Char('/')))
- dir += QLatin1Char('/');
- if(lst.count() == 1)
- lst = ProStringList(lst.first().toQString().split(" "));
- for (ProStringList::Iterator lst_it = lst.begin(); lst_it != lst.end(); ++lst_it) {
- bool found = false;
- QString dirs[] = { "", dir.toQString(), dirf, dirf + ".libs/", "(term)" };
- for(int i = 0; !found && dirs[i] != "(term)"; i++) {
- if(QFile::exists(dirs[i] + (*lst_it))) {
- QString targ = dirs[i] + (*lst_it);
- if(QDir::isRelativePath(targ))
- targ.prepend(qmake_getpwd() + QLatin1Char('/'));
- vars["QMAKE_PRL_TARGET"] << targ;
- found = true;
- }
- }
- if(found)
- break;
- }
- } else if(it.key() == "dependency_libs") {
- if(lst.count() == 1) {
- ProString dep = lst.first();
- if ((dep.startsWith('\'') || dep.startsWith('"')) && dep.endsWith(dep.at(0)))
- dep = dep.mid(1, dep.length() - 2);
- lst = ProStringList(dep.trimmed().toQString().split(" "));
- }
- for (ProStringList::Iterator lit = lst.begin(); lit != lst.end(); ++lit) {
- if((*lit).startsWith("-R")) {
- if(!conf->isEmpty("QMAKE_LFLAGS_RPATH"))
- (*lit) = conf->first("QMAKE_LFLAGS_RPATH") + (*lit).mid(2);
- }
- }
- ProStringList &prlLibs = vars["QMAKE_PRL_LIBS"];
- for (const ProString &s : qAsConst(lst)) {
- prlLibs.removeAll(s);
- prlLibs.append(s);
- }
- }
- }
- return true;
-}
-
-bool
-QMakeMetaInfo::readPkgCfgFile(const QString &f)
-{
- fprintf(stderr, "Must implement reading in pkg-config files (%s)!!!\n", f.toLatin1().constData());
- return false;
-}
-
QT_END_NAMESPACE
diff --git a/qmake/meta.h b/qmake/meta.h
index dd53cdc7a3..4721085fd2 100644
--- a/qmake/meta.h
+++ b/qmake/meta.h
@@ -41,20 +41,16 @@ class QMakeProject;
class QMakeMetaInfo
{
- bool readLibtoolFile(const QString &f);
- bool readPkgCfgFile(const QString &f);
QMakeProject *conf;
ProValueMap vars;
- QString meta_type;
static QHash<QString, ProValueMap> cache_vars;
public:
QMakeMetaInfo(QMakeProject *_conf);
// These functions expect the path to be normalized
- static QString findLib(const QString &lib);
+ static QString checkLib(const QString &lib);
bool readLib(const QString &meta_file);
- QString type() const;
bool isEmpty(const ProKey &v);
ProStringList &values(const ProKey &v);
ProString first(const ProKey &v);
@@ -64,9 +60,6 @@ public:
inline bool QMakeMetaInfo::isEmpty(const ProKey &v)
{ return !vars.contains(v) || vars[v].isEmpty(); }
-inline QString QMakeMetaInfo::type() const
-{ return meta_type; }
-
inline ProStringList &QMakeMetaInfo::values(const ProKey &v)
{ return vars[v]; }
diff --git a/qmake/option.cpp b/qmake/option.cpp
index baad644280..dcebeadcb8 100644
--- a/qmake/option.cpp
+++ b/qmake/option.cpp
@@ -507,7 +507,7 @@ QString
Option::fixString(QString string, uchar flags)
{
//const QString orig_string = string;
- static QHash<FixStringCacheKey, QString> *cache = 0;
+ static QHash<FixStringCacheKey, QString> *cache = nullptr;
if(!cache) {
cache = new QHash<FixStringCacheKey, QString>;
qmakeAddCacheClear(qmakeDeleteCacheClear<QHash<FixStringCacheKey, QString> >, (void**)&cache);
@@ -635,7 +635,7 @@ public:
QMakeCacheClearItem(qmakeCacheClearFunc f, void **d) : func(f), data(d) { }
~QMakeCacheClearItem() {
(*func)(*data);
- *data = 0;
+ *data = nullptr;
}
};
static QList<QMakeCacheClearItem*> cache_items;
diff --git a/qmake/option.h b/qmake/option.h
index eaa3706b24..25b2d64aaa 100644
--- a/qmake/option.h
+++ b/qmake/option.h
@@ -60,12 +60,12 @@ class QMakeProject;
class EvalHandler : public QMakeHandler {
public:
- void message(int type, const QString &msg, const QString &fileName, int lineNo);
+ void message(int type, const QString &msg, const QString &fileName, int lineNo) override;
- void fileMessage(int type, const QString &msg);
+ void fileMessage(int type, const QString &msg) override;
- void aboutToEval(ProFile *, ProFile *, EvalFileType);
- void doneWithEval(ProFile *);
+ void aboutToEval(ProFile *, ProFile *, EvalFileType) override;
+ void doneWithEval(ProFile *) override;
};
struct Option
@@ -108,7 +108,7 @@ struct Option
};
//both of these must be called..
- static int init(int argc=0, char **argv=0); //parse cmdline
+ static int init(int argc = 0, char **argv = nullptr); //parse cmdline
static void prepareProject(const QString &pfile);
static bool postProcessProject(QMakeProject *);
diff --git a/qmake/project.cpp b/qmake/project.cpp
index e6bdb04bfb..1bc9b352b5 100644
--- a/qmake/project.cpp
+++ b/qmake/project.cpp
@@ -82,8 +82,9 @@ bool QMakeProject::test(const ProKey &func, const QList<ProStringList> &args)
{
m_current.clear();
- if (int func_t = statics.functions.value(func))
- return boolRet(evaluateBuiltinConditional(func_t, func, prepareBuiltinArgs(args)));
+ auto adef = statics.functions.constFind(func);
+ if (adef != statics.functions.constEnd())
+ return boolRet(evaluateBuiltinConditional(*adef, func, prepareBuiltinArgs(args)));
QHash<ProKey, ProFunctionDef>::ConstIterator it =
m_functionDefs.testFunctions.constFind(func);
@@ -99,9 +100,10 @@ QStringList QMakeProject::expand(const ProKey &func, const QList<ProStringList>
{
m_current.clear();
- if (int func_t = statics.expands.value(func)) {
+ auto adef = statics.expands.constFind(func);
+ if (adef != statics.expands.constEnd()) {
ProStringList ret;
- if (evaluateBuiltinExpand(func_t, func, prepareBuiltinArgs(args), ret) == ReturnError)
+ if (evaluateBuiltinExpand(*adef, func, prepareBuiltinArgs(args), ret) == ReturnError)
exit(3);
return ret.toQStringList();
}
diff --git a/qmake/property.cpp b/qmake/property.cpp
index 9a8db8904d..c0a3ec0dab 100644
--- a/qmake/property.cpp
+++ b/qmake/property.cpp
@@ -68,7 +68,7 @@ static const struct {
{ "QMAKE_XSPEC", QLibraryInfo::TargetSpecPath, true, true },
};
-QMakeProperty::QMakeProperty() : settings(0)
+QMakeProperty::QMakeProperty() : settings(nullptr)
{
reload();
}
@@ -99,7 +99,7 @@ void QMakeProperty::reload()
QMakeProperty::~QMakeProperty()
{
delete settings;
- settings = 0;
+ settings = nullptr;
}
void QMakeProperty::initSettings()
diff --git a/src/3rdparty/angle/AUTHORS b/src/3rdparty/angle/AUTHORS
index 8de8fbddf6..5dacdf8fbd 100644
--- a/src/3rdparty/angle/AUTHORS
+++ b/src/3rdparty/angle/AUTHORS
@@ -1,4 +1,4 @@
-# This is the official list of The ANGLE Project Authors
+# This is the official list of The ANGLE Project Authors
# for copyright purposes.
# This file is distinct from the CONTRIBUTORS files.
# See the latter for an explanation.
@@ -26,6 +26,7 @@ Microsoft Open Technologies, Inc.
NVIDIA Corporation
Opera Software ASA
The Qt Company Ltd.
+Advanced Micro Devices, Inc.
Jacek Caban
Mark Callow
@@ -42,3 +43,9 @@ Yuri O'Donnell
Josh Soref
Maks Naumov
Jinyoung Hur
+Sebastian Bergstein
+James Ross-Gowan
+Nickolay Artamonov
+Ihsan Akmal
+Andrei Volykhin
+Jérôme Duval
diff --git a/src/3rdparty/angle/CONTRIBUTORS b/src/3rdparty/angle/CONTRIBUTORS
index 71e13b7a15..a767773b33 100644
--- a/src/3rdparty/angle/CONTRIBUTORS
+++ b/src/3rdparty/angle/CONTRIBUTORS
@@ -41,6 +41,7 @@ Google Inc.
Justin Schuh
Scott Graham
Corentin Wallez
+ Kai Ninomiya
Adobe Systems Inc.
Alexandru Chiculita
@@ -64,12 +65,21 @@ Intel Corporation
Andy Chen
Josh Triplett
Sudarsana Nagineni
+ Jiajia Qin
+ Jiawei Shao
+ Jie Chen
+ Qiankun Miao
+ Bryan Bernhart
+ Yunchao He
+ Xinghua Cao
+ Brandon Jones
Klarälvdalens Datakonsult AB
Milian Wolff
Mozilla Corp.
Ehsan Akhgari
+ Edwin Flores
Jeff Gilbert
Mike Hommey
Benoit Jacob
@@ -85,6 +95,10 @@ David Kilzer
Jacek Caban
Tibor den Ouden
Régis Fénéon
+Sebastian Bergstein
+James Ross-Gowan
+Andrei Volykhin
+Jérôme Duval
Microsoft Corporation
Cooper Partin
@@ -101,7 +115,13 @@ NVIDIA Corporation
Arun Patole
Qingqing Deng
Kimmo Kinnunen
+ Sami Väisänen
+ Martin Radev
Opera Software ASA
Daniel Bratell
Tomasz Moniuszko
+ David Landell
+
+Advanced Micro Devices, Inc.
+ Russ Lind
diff --git a/src/3rdparty/angle/LICENSE b/src/3rdparty/angle/LICENSE
index dc322e998d..bdacb32e36 100644
--- a/src/3rdparty/angle/LICENSE
+++ b/src/3rdparty/angle/LICENSE
@@ -1,32 +1,32 @@
-Copyright (C) 2002-2013 The ANGLE Project Authors.
-All rights reserved.
-
-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 TransGaming Inc., Google Inc., 3DLabs Inc.
- Ltd., nor the names of their 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.
+// Copyright (C) 2002-2013 The ANGLE Project Authors.
+// All rights reserved.
+//
+// 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 TransGaming Inc., Google Inc., 3DLabs Inc.
+// Ltd., nor the names of their 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.
diff --git a/src/3rdparty/angle/SYSTEMINFO_LICENSE b/src/3rdparty/angle/SYSTEMINFO_LICENSE
deleted file mode 100644
index c12444e3bc..0000000000
--- a/src/3rdparty/angle/SYSTEMINFO_LICENSE
+++ /dev/null
@@ -1,22 +0,0 @@
-Copyright (C) 2009 Apple Inc. All Rights Reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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.
diff --git a/src/3rdparty/angle/TRACEEVENT_LICENSE b/src/3rdparty/angle/TRACEEVENT_LICENSE
deleted file mode 100644
index 34d6cd9268..0000000000
--- a/src/3rdparty/angle/TRACEEVENT_LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright 2013 The Chromium Authors. All rights reserved.
-
-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 Google Inc. 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.
diff --git a/src/3rdparty/angle/id/commit.h b/src/3rdparty/angle/id/commit.h
new file mode 100644
index 0000000000..4c89a657c5
--- /dev/null
+++ b/src/3rdparty/angle/id/commit.h
@@ -0,0 +1,14 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// commit.h:
+// This is a default commit hash header, when git is not available.
+//
+
+#define ANGLE_COMMIT_HASH "unknown hash"
+#define ANGLE_COMMIT_HASH_SIZE 12
+#define ANGLE_COMMIT_DATE "unknown date"
+
+#define ANGLE_DISABLE_PROGRAM_BINARY_LOAD
diff --git a/src/3rdparty/angle/include/EGL/egl.h b/src/3rdparty/angle/include/EGL/egl.h
index 9f9e021804..29f30d94de 100644
--- a/src/3rdparty/angle/include/EGL/egl.h
+++ b/src/3rdparty/angle/include/EGL/egl.h
@@ -6,7 +6,7 @@ extern "C" {
#endif
/*
-** Copyright (c) 2013-2015 The Khronos Group Inc.
+** Copyright (c) 2013-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
@@ -31,14 +31,14 @@ extern "C" {
** This header is generated from the Khronos OpenGL / OpenGL ES XML
** API Registry. The current version of the Registry, generator scripts
** used to make the header, and the header can be found at
-** http://www.opengl.org/registry/
+** http://www.opengl.org/registry/egl
**
-** Khronos $Revision: 31566 $ on $Date: 2015-06-23 08:48:48 -0700 (Tue, 23 Jun 2015) $
+** Khronos $Revision$ on $Date$
*/
#include <EGL/eglplatform.h>
-/* Generated on date 20150623 */
+/* Generated on date 20161230 */
/* Generated C header for:
* API: egl
@@ -78,7 +78,7 @@ typedef void (*__eglMustCastToProperFunctionPointerType)(void);
#define EGL_CONFIG_ID 0x3028
#define EGL_CORE_NATIVE_ENGINE 0x305B
#define EGL_DEPTH_SIZE 0x3025
-#define EGL_DONT_CARE ((EGLint)-1)
+#define EGL_DONT_CARE EGL_CAST(EGLint,-1)
#define EGL_DRAW 0x3059
#define EGL_EXTENSIONS 0x3055
#define EGL_FALSE 0
@@ -95,9 +95,9 @@ typedef void (*__eglMustCastToProperFunctionPointerType)(void);
#define EGL_NONE 0x3038
#define EGL_NON_CONFORMANT_CONFIG 0x3051
#define EGL_NOT_INITIALIZED 0x3001
-#define EGL_NO_CONTEXT ((EGLContext)0)
-#define EGL_NO_DISPLAY ((EGLDisplay)0)
-#define EGL_NO_SURFACE ((EGLSurface)0)
+#define EGL_NO_CONTEXT EGL_CAST(EGLContext,0)
+#define EGL_NO_DISPLAY EGL_CAST(EGLDisplay,0)
+#define EGL_NO_SURFACE EGL_CAST(EGLSurface,0)
#define EGL_PBUFFER_BIT 0x0001
#define EGL_PIXMAP_BIT 0x0002
#define EGL_READ 0x305A
@@ -197,7 +197,7 @@ typedef void *EGLClientBuffer;
#define EGL_RGB_BUFFER 0x308E
#define EGL_SINGLE_BUFFER 0x3085
#define EGL_SWAP_BEHAVIOR 0x3093
-#define EGL_UNKNOWN ((EGLint)-1)
+#define EGL_UNKNOWN EGL_CAST(EGLint,-1)
#define EGL_VERTICAL_RESOLUTION 0x3091
EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI (EGLenum api);
EGLAPI EGLenum EGLAPIENTRY eglQueryAPI (void);
@@ -224,7 +224,7 @@ EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient (void);
#ifndef EGL_VERSION_1_4
#define EGL_VERSION_1_4 1
-#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0)
+#define EGL_DEFAULT_DISPLAY EGL_CAST(EGLNativeDisplayType,0)
#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200
#define EGL_MULTISAMPLE_RESOLVE 0x3099
#define EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A
@@ -266,7 +266,7 @@ typedef void *EGLImage;
#define EGL_FOREVER 0xFFFFFFFFFFFFFFFFull
#define EGL_TIMEOUT_EXPIRED 0x30F5
#define EGL_CONDITION_SATISFIED 0x30F6
-#define EGL_NO_SYNC ((EGLSync)0)
+#define EGL_NO_SYNC EGL_CAST(EGLSync,0)
#define EGL_SYNC_FENCE 0x30F9
#define EGL_GL_COLORSPACE 0x309D
#define EGL_GL_COLORSPACE_SRGB 0x3089
@@ -283,7 +283,7 @@ typedef void *EGLImage;
#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x30B7
#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x30B8
#define EGL_IMAGE_PRESERVED 0x30D2
-#define EGL_NO_IMAGE ((EGLImage)0)
+#define EGL_NO_IMAGE EGL_CAST(EGLImage,0)
EGLAPI EGLSync EGLAPIENTRY eglCreateSync (EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list);
EGLAPI EGLBoolean EGLAPIENTRY eglDestroySync (EGLDisplay dpy, EGLSync sync);
EGLAPI EGLint EGLAPIENTRY eglClientWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
diff --git a/src/3rdparty/angle/include/EGL/eglext.h b/src/3rdparty/angle/include/EGL/eglext.h
index 83490b8567..79f6ccd418 100644
--- a/src/3rdparty/angle/include/EGL/eglext.h
+++ b/src/3rdparty/angle/include/EGL/eglext.h
@@ -6,7 +6,7 @@ extern "C" {
#endif
/*
-** Copyright (c) 2013-2015 The Khronos Group Inc.
+** Copyright (c) 2013-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
@@ -31,14 +31,14 @@ extern "C" {
** This header is generated from the Khronos OpenGL / OpenGL ES XML
** API Registry. The current version of the Registry, generator scripts
** used to make the header, and the header can be found at
-** http://www.opengl.org/registry/
+** http://www.khronos.org/registry/egl
**
-** Khronos $Revision: 31566 $ on $Date: 2015-06-23 08:48:48 -0700 (Tue, 23 Jun 2015) $
+** Khronos $Git commit SHA1: a732b061e7 $ on $Git commit date: 2017-06-17 23:27:53 +0100 $
*/
#include <EGL/eglplatform.h>
-#define EGL_EGLEXT_VERSION 20150623
+#define EGL_EGLEXT_VERSION 20170627
/* Generated C header for:
* API: egl
@@ -77,6 +77,13 @@ EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSync64KHR (EGLDisplay dpy, EGLenum type,
#define EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR 0x0040
#endif /* EGL_KHR_config_attribs */
+#ifndef EGL_KHR_context_flush_control
+#define EGL_KHR_context_flush_control 1
+#define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0
+#define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097
+#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
+#endif /* EGL_KHR_context_flush_control */
+
#ifndef EGL_KHR_create_context
#define EGL_KHR_create_context 1
#define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098
@@ -99,6 +106,42 @@ EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSync64KHR (EGLDisplay dpy, EGLenum type,
#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31B3
#endif /* EGL_KHR_create_context_no_error */
+#ifndef EGL_KHR_debug
+#define EGL_KHR_debug 1
+typedef void *EGLLabelKHR;
+typedef void *EGLObjectKHR;
+typedef void (EGLAPIENTRY *EGLDEBUGPROCKHR)(EGLenum error,const char *command,EGLint messageType,EGLLabelKHR threadLabel,EGLLabelKHR objectLabel,const char* message);
+#define EGL_OBJECT_THREAD_KHR 0x33B0
+#define EGL_OBJECT_DISPLAY_KHR 0x33B1
+#define EGL_OBJECT_CONTEXT_KHR 0x33B2
+#define EGL_OBJECT_SURFACE_KHR 0x33B3
+#define EGL_OBJECT_IMAGE_KHR 0x33B4
+#define EGL_OBJECT_SYNC_KHR 0x33B5
+#define EGL_OBJECT_STREAM_KHR 0x33B6
+#define EGL_DEBUG_MSG_CRITICAL_KHR 0x33B9
+#define EGL_DEBUG_MSG_ERROR_KHR 0x33BA
+#define EGL_DEBUG_MSG_WARN_KHR 0x33BB
+#define EGL_DEBUG_MSG_INFO_KHR 0x33BC
+#define EGL_DEBUG_CALLBACK_KHR 0x33B8
+typedef EGLint (EGLAPIENTRYP PFNEGLDEBUGMESSAGECONTROLKHRPROC) (EGLDEBUGPROCKHR callback, const EGLAttrib *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEBUGKHRPROC) (EGLint attribute, EGLAttrib *value);
+typedef EGLint (EGLAPIENTRYP PFNEGLLABELOBJECTKHRPROC) (EGLDisplay display, EGLenum objectType, EGLObjectKHR object, EGLLabelKHR label);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLint EGLAPIENTRY eglDebugMessageControlKHR (EGLDEBUGPROCKHR callback, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDebugKHR (EGLint attribute, EGLAttrib *value);
+EGLAPI EGLint EGLAPIENTRY eglLabelObjectKHR (EGLDisplay display, EGLenum objectType, EGLObjectKHR object, EGLLabelKHR label);
+#endif
+#endif /* EGL_KHR_debug */
+
+#ifndef EGL_KHR_display_reference
+#define EGL_KHR_display_reference 1
+#define EGL_TRACK_REFERENCES_KHR 0x3352
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBKHRPROC) (EGLDisplay dpy, EGLint name, EGLAttrib *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribKHR (EGLDisplay dpy, EGLint name, EGLAttrib *value);
+#endif
+#endif /* EGL_KHR_display_reference */
+
#ifndef EGL_KHR_fence_sync
#define EGL_KHR_fence_sync 1
typedef khronos_utime_nanoseconds_t EGLTimeKHR;
@@ -161,7 +204,7 @@ EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR (EGLDisplay dpy, EGLSyncKHR sy
#define EGL_KHR_image 1
typedef void *EGLImageKHR;
#define EGL_NATIVE_PIXMAP_KHR 0x30B0
-#define EGL_NO_IMAGE_KHR ((EGLImageKHR)0)
+#define EGL_NO_IMAGE_KHR EGL_CAST(EGLImageKHR,0)
typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image);
#ifdef EGL_EGLEXT_PROTOTYPES
@@ -223,6 +266,16 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface64KHR (EGLDisplay dpy, EGLSurface s
#endif
#endif /* EGL_KHR_lock_surface3 */
+#ifndef EGL_KHR_mutable_render_buffer
+#define EGL_KHR_mutable_render_buffer 1
+#define EGL_MUTABLE_RENDER_BUFFER_BIT_KHR 0x1000
+#endif /* EGL_KHR_mutable_render_buffer */
+
+#ifndef EGL_KHR_no_config_context
+#define EGL_KHR_no_config_context 1
+#define EGL_NO_CONFIG_KHR EGL_CAST(EGLConfig,0)
+#endif /* EGL_KHR_no_config_context */
+
#ifndef EGL_KHR_partial_update
#define EGL_KHR_partial_update 1
#define EGL_BUFFER_AGE_KHR 0x313D
@@ -265,7 +318,7 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSetDamageRegionKHR (EGLDisplay dpy, EGLSurface
#define EGL_SYNC_REUSABLE_KHR 0x30FA
#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR 0x0001
#define EGL_FOREVER_KHR 0xFFFFFFFFFFFFFFFFull
-#define EGL_NO_SYNC_KHR ((EGLSyncKHR)0)
+#define EGL_NO_SYNC_KHR EGL_CAST(EGLSyncKHR,0)
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
#ifdef EGL_EGLEXT_PROTOTYPES
EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
@@ -278,7 +331,7 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR (EGLDisplay dpy, EGLSyncKHR sync,
typedef void *EGLStreamKHR;
typedef khronos_uint64_t EGLuint64KHR;
#ifdef KHRONOS_SUPPORT_INT64
-#define EGL_NO_STREAM_KHR ((EGLStreamKHR)0)
+#define EGL_NO_STREAM_KHR EGL_CAST(EGLStreamKHR,0)
#define EGL_CONSUMER_LATENCY_USEC_KHR 0x3210
#define EGL_PRODUCER_FRAME_KHR 0x3212
#define EGL_CONSUMER_FRAME_KHR 0x3213
@@ -306,6 +359,24 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamu64KHR (EGLDisplay dpy, EGLStreamKHR
#endif /* KHRONOS_SUPPORT_INT64 */
#endif /* EGL_KHR_stream */
+#ifndef EGL_KHR_stream_attrib
+#define EGL_KHR_stream_attrib 1
+#ifdef KHRONOS_SUPPORT_INT64
+typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMATTRIBKHRPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib *value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamAttribKHR (EGLDisplay dpy, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglSetStreamAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_KHR_stream_attrib */
+
#ifndef EGL_KHR_stream_consumer_gltexture
#define EGL_KHR_stream_consumer_gltexture 1
#ifdef EGL_KHR_stream
@@ -325,7 +396,7 @@ EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseKHR (EGLDisplay dpy, EGLSt
#define EGL_KHR_stream_cross_process_fd 1
typedef int EGLNativeFileDescriptorKHR;
#ifdef EGL_KHR_stream
-#define EGL_NO_FILE_DESCRIPTOR_KHR ((EGLNativeFileDescriptorKHR)(-1))
+#define EGL_NO_FILE_DESCRIPTOR_KHR EGL_CAST(EGLNativeFileDescriptorKHR,-1)
typedef EGLNativeFileDescriptorKHR (EGLAPIENTRYP PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor);
#ifdef EGL_EGLEXT_PROTOTYPES
@@ -402,11 +473,28 @@ EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncsANDROID (EGLDisplay dpy, EGLSetBlobF
#endif
#endif /* EGL_ANDROID_blob_cache */
+#ifndef EGL_ANDROID_create_native_client_buffer
+#define EGL_ANDROID_create_native_client_buffer 1
+#define EGL_NATIVE_BUFFER_USAGE_ANDROID 0x3143
+#define EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID 0x00000001
+#define EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID 0x00000002
+#define EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID 0x00000004
+typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLCREATENATIVECLIENTBUFFERANDROIDPROC) (const EGLint *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLClientBuffer EGLAPIENTRY eglCreateNativeClientBufferANDROID (const EGLint *attrib_list);
+#endif
+#endif /* EGL_ANDROID_create_native_client_buffer */
+
#ifndef EGL_ANDROID_framebuffer_target
#define EGL_ANDROID_framebuffer_target 1
#define EGL_FRAMEBUFFER_TARGET_ANDROID 0x3147
#endif /* EGL_ANDROID_framebuffer_target */
+#ifndef EGL_ANDROID_front_buffer_auto_refresh
+#define EGL_ANDROID_front_buffer_auto_refresh 1
+#define EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID 0x314C
+#endif /* EGL_ANDROID_front_buffer_auto_refresh */
+
#ifndef EGL_ANDROID_image_native_buffer
#define EGL_ANDROID_image_native_buffer 1
#define EGL_NATIVE_BUFFER_ANDROID 0x3140
@@ -424,6 +512,15 @@ EGLAPI EGLint EGLAPIENTRY eglDupNativeFenceFDANDROID (EGLDisplay dpy, EGLSyncKHR
#endif
#endif /* EGL_ANDROID_native_fence_sync */
+#ifndef EGL_ANDROID_presentation_time
+#define EGL_ANDROID_presentation_time 1
+typedef khronos_stime_nanoseconds_t EGLnsecsANDROID;
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLPRESENTATIONTIMEANDROIDPROC) (EGLDisplay dpy, EGLSurface surface, EGLnsecsANDROID time);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglPresentationTimeANDROID (EGLDisplay dpy, EGLSurface surface, EGLnsecsANDROID time);
+#endif
+#endif /* EGL_ANDROID_presentation_time */
+
#ifndef EGL_ANDROID_recordable
#define EGL_ANDROID_recordable 1
#define EGL_RECORDABLE_ANDROID 0x3142
@@ -440,11 +537,6 @@ EGLAPI EGLint EGLAPIENTRY eglDupNativeFenceFDANDROID (EGLDisplay dpy, EGLSyncKHR
#define EGL_D3D11_DEVICE_ANGLE 0x33A1
#endif /* EGL_ANGLE_device_d3d */
-#ifndef EGL_ANGLE_keyed_mutex
-#define EGL_ANGLE_keyed_mutex 1
-#define EGL_DXGI_KEYED_MUTEX_ANGLE 0x33A2
-#endif /* EGL_ANGLE_keyed_mutex */
-
#ifndef EGL_ANGLE_query_surface_pointer
#define EGL_ANGLE_query_surface_pointer 1
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
@@ -453,87 +545,30 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu
#endif
#endif /* EGL_ANGLE_query_surface_pointer */
-#ifndef EGL_ANGLE_software_display
-#define EGL_ANGLE_software_display 1
-#define EGL_SOFTWARE_DISPLAY_ANGLE ((EGLNativeDisplayType)-1)
-#endif /* EGL_ANGLE_software_display */
-
-#ifndef EGL_ANGLE_direct3d_display
-#define EGL_ANGLE_direct3d_display 1
-#define EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ((EGLNativeDisplayType)-2)
-#define EGL_D3D11_ONLY_DISPLAY_ANGLE ((EGLNativeDisplayType)-3)
-#endif /* EGL_ANGLE_direct3d_display */
-
#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle
#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1
#endif /* EGL_ANGLE_surface_d3d_texture_2d_share_handle */
-#ifndef EGL_ANGLE_direct_composition
-#define EGL_ANGLE_direct_composition 1
-#define EGL_DIRECT_COMPOSITION_ANGLE 0x33A5
-#endif /* EGL_ANGLE_direct_composition */
-
-#ifndef EGL_ANGLE_platform_angle
-#define EGL_ANGLE_platform_angle 1
-#define EGL_PLATFORM_ANGLE_ANGLE 0x3202
-#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203
-#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3204
-#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3205
-#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3206
-#endif /* EGL_ANGLE_platform_angle */
-
-#ifndef EGL_ANGLE_platform_angle_d3d
-#define EGL_ANGLE_platform_angle_d3d 1
-#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3207
-#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208
-#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE 0x3209
-#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE 0x320A
-#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE 0x320B
-#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE 0x320C
-#define EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE 0x320F
-#endif /* EGL_ANGLE_platform_angle_d3d */
-
-#ifndef EGL_ANGLE_platform_angle_opengl
-#define EGL_ANGLE_platform_angle_opengl 1
-#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x320D
-#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320E
-#endif /* EGL_ANGLE_platform_angle_opengl */
-
#ifndef EGL_ANGLE_window_fixed_size
#define EGL_ANGLE_window_fixed_size 1
#define EGL_FIXED_SIZE_ANGLE 0x3201
#endif /* EGL_ANGLE_window_fixed_size */
-#ifndef EGL_ANGLE_x11_visual
-#define EGL_ANGLE_x11_visual
-#define EGL_X11_VISUAL_ID_ANGLE 0x33A3
-#endif /* EGL_ANGLE_x11_visual */
-
-#ifndef EGL_ANGLE_flexible_surface_compatibility
-#define EGL_ANGLE_flexible_surface_compatibility 1
-#define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6
-#endif /* EGL_ANGLE_flexible_surface_compatibility */
-
-#ifndef EGL_ANGLE_surface_orientation
-#define EGL_ANGLE_surface_orientation
-#define EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE 0x33A7
-#define EGL_SURFACE_ORIENTATION_ANGLE 0x33A8
-#define EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE 0x0001
-#define EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE 0x0002
-#endif /* EGL_ANGLE_surface_orientation */
-
-#ifndef EGL_ANGLE_experimental_present_path
-#define EGL_ANGLE_experimental_present_path
-#define EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE 0x33A4
-#define EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE 0x33A9
-#define EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE 0x33AA
-#endif /* EGL_ANGLE_experimental_present_path */
+#ifndef EGL_ARM_implicit_external_sync
+#define EGL_ARM_implicit_external_sync 1
+#define EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM 0x328A
+#endif /* EGL_ARM_implicit_external_sync */
#ifndef EGL_ARM_pixmap_multisample_discard
#define EGL_ARM_pixmap_multisample_discard 1
#define EGL_DISCARD_SAMPLES_ARM 0x3286
#endif /* EGL_ARM_pixmap_multisample_discard */
+#ifndef EGL_EXT_bind_to_front
+#define EGL_EXT_bind_to_front 1
+#define EGL_FRONT_BUFFER_EXT 0x3464
+#endif /* EGL_EXT_bind_to_front */
+
#ifndef EGL_EXT_buffer_age
#define EGL_EXT_buffer_age 1
#define EGL_BUFFER_AGE_EXT 0x313D
@@ -543,6 +578,30 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu
#define EGL_EXT_client_extensions 1
#endif /* EGL_EXT_client_extensions */
+#ifndef EGL_EXT_compositor
+#define EGL_EXT_compositor 1
+#define EGL_PRIMARY_COMPOSITOR_CONTEXT_EXT 0x3460
+#define EGL_EXTERNAL_REF_ID_EXT 0x3461
+#define EGL_COMPOSITOR_DROP_NEWEST_FRAME_EXT 0x3462
+#define EGL_COMPOSITOR_KEEP_NEWEST_FRAME_EXT 0x3463
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORSETCONTEXTLISTEXTPROC) (const EGLint *external_ref_ids, EGLint num_entries);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORSETCONTEXTATTRIBUTESEXTPROC) (EGLint external_ref_id, const EGLint *context_attributes, EGLint num_entries);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORSETWINDOWLISTEXTPROC) (EGLint external_ref_id, const EGLint *external_win_ids, EGLint num_entries);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORSETWINDOWATTRIBUTESEXTPROC) (EGLint external_win_id, const EGLint *window_attributes, EGLint num_entries);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORBINDTEXWINDOWEXTPROC) (EGLint external_win_id);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORSETSIZEEXTPROC) (EGLint external_win_id, EGLint width, EGLint height);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOMPOSITORSWAPPOLICYEXTPROC) (EGLint external_win_id, EGLint policy);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSetContextListEXT (const EGLint *external_ref_ids, EGLint num_entries);
+EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSetContextAttributesEXT (EGLint external_ref_id, const EGLint *context_attributes, EGLint num_entries);
+EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSetWindowListEXT (EGLint external_ref_id, const EGLint *external_win_ids, EGLint num_entries);
+EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSetWindowAttributesEXT (EGLint external_win_id, const EGLint *window_attributes, EGLint num_entries);
+EGLAPI EGLBoolean EGLAPIENTRY eglCompositorBindTexWindowEXT (EGLint external_win_id);
+EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSetSizeEXT (EGLint external_win_id, EGLint width, EGLint height);
+EGLAPI EGLBoolean EGLAPIENTRY eglCompositorSwapPolicyEXT (EGLint external_win_id, EGLint policy);
+#endif
+#endif /* EGL_EXT_compositor */
+
#ifndef EGL_EXT_create_context_robustness
#define EGL_EXT_create_context_robustness 1
#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT 0x30BF
@@ -554,7 +613,7 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu
#ifndef EGL_EXT_device_base
#define EGL_EXT_device_base 1
typedef void *EGLDeviceEXT;
-#define EGL_NO_DEVICE_EXT ((EGLDeviceEXT)(0))
+#define EGL_NO_DEVICE_EXT EGL_CAST(EGLDeviceEXT,0)
#define EGL_BAD_DEVICE_EXT 0x322B
#define EGL_DEVICE_EXT 0x322C
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICEATTRIBEXTPROC) (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value);
@@ -569,16 +628,6 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT (EGLDisplay dpy, EGLint a
#endif
#endif /* EGL_EXT_device_base */
-#ifndef EGL_ANGLE_device_creation
-#define EGL_ANGLE_device_creation 1
-typedef EGLDeviceEXT (EGLAPIENTRYP PFNEGLCREATEDEVICEANGLEPROC) (EGLint device_type, void *native_device, const EGLAttrib *attrib_list);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLRELEASEDEVICEANGLEPROC) (EGLDeviceEXT device);
-#ifdef EGL_EGLEXT_PROTOTYPES
-EGLAPI EGLDeviceEXT EGLAPIENTRY eglCreateDeviceANGLE (EGLint device_type, void *native_device, const EGLAttrib *attrib_list);
-EGLAPI EGLBoolean EGLAPIENTRY eglReleaseDeviceANGLE (EGLDeviceEXT device);
-#endif
-#endif /* EGL_ANGLE_device_creation */
-
#ifndef EGL_EXT_device_drm
#define EGL_EXT_device_drm 1
#define EGL_DRM_DEVICE_FILE_EXT 0x3233
@@ -597,6 +646,36 @@ EGLAPI EGLBoolean EGLAPIENTRY eglReleaseDeviceANGLE (EGLDeviceEXT device);
#define EGL_EXT_device_query 1
#endif /* EGL_EXT_device_query */
+#ifndef EGL_EXT_gl_colorspace_bt2020_linear
+#define EGL_EXT_gl_colorspace_bt2020_linear 1
+#define EGL_GL_COLORSPACE_BT2020_LINEAR_EXT 0x333F
+#endif /* EGL_EXT_gl_colorspace_bt2020_linear */
+
+#ifndef EGL_EXT_gl_colorspace_bt2020_pq
+#define EGL_EXT_gl_colorspace_bt2020_pq 1
+#define EGL_GL_COLORSPACE_BT2020_PQ_EXT 0x3340
+#endif /* EGL_EXT_gl_colorspace_bt2020_pq */
+
+#ifndef EGL_EXT_gl_colorspace_display_p3
+#define EGL_EXT_gl_colorspace_display_p3 1
+#define EGL_GL_COLORSPACE_DISPLAY_P3_EXT 0x3363
+#endif /* EGL_EXT_gl_colorspace_display_p3 */
+
+#ifndef EGL_EXT_gl_colorspace_display_p3_linear
+#define EGL_EXT_gl_colorspace_display_p3_linear 1
+#define EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT 0x3362
+#endif /* EGL_EXT_gl_colorspace_display_p3_linear */
+
+#ifndef EGL_EXT_gl_colorspace_scrgb
+#define EGL_EXT_gl_colorspace_scrgb 1
+#define EGL_GL_COLORSPACE_SCRGB_EXT 0x3351
+#endif /* EGL_EXT_gl_colorspace_scrgb */
+
+#ifndef EGL_EXT_gl_colorspace_scrgb_linear
+#define EGL_EXT_gl_colorspace_scrgb_linear 1
+#define EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT 0x3350
+#endif /* EGL_EXT_gl_colorspace_scrgb_linear */
+
#ifndef EGL_EXT_image_dma_buf_import
#define EGL_EXT_image_dma_buf_import 1
#define EGL_LINUX_DMA_BUF_EXT 0x3270
@@ -623,6 +702,34 @@ EGLAPI EGLBoolean EGLAPIENTRY eglReleaseDeviceANGLE (EGLDeviceEXT device);
#define EGL_YUV_CHROMA_SITING_0_5_EXT 0x3285
#endif /* EGL_EXT_image_dma_buf_import */
+#ifndef EGL_EXT_image_dma_buf_import_modifiers
+#define EGL_EXT_image_dma_buf_import_modifiers 1
+#define EGL_DMA_BUF_PLANE3_FD_EXT 0x3440
+#define EGL_DMA_BUF_PLANE3_OFFSET_EXT 0x3441
+#define EGL_DMA_BUF_PLANE3_PITCH_EXT 0x3442
+#define EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT 0x3443
+#define EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT 0x3444
+#define EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT 0x3445
+#define EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT 0x3446
+#define EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT 0x3447
+#define EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT 0x3448
+#define EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT 0x3449
+#define EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT 0x344A
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDMABUFFORMATSEXTPROC) (EGLDisplay dpy, EGLint max_formats, EGLint *formats, EGLint *num_formats);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDMABUFMODIFIERSEXTPROC) (EGLDisplay dpy, EGLint format, EGLint max_modifiers, EGLuint64KHR *modifiers, EGLBoolean *external_only, EGLint *num_modifiers);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDmaBufFormatsEXT (EGLDisplay dpy, EGLint max_formats, EGLint *formats, EGLint *num_formats);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDmaBufModifiersEXT (EGLDisplay dpy, EGLint format, EGLint max_modifiers, EGLuint64KHR *modifiers, EGLBoolean *external_only, EGLint *num_modifiers);
+#endif
+#endif /* EGL_EXT_image_dma_buf_import_modifiers */
+
+#ifndef EGL_EXT_image_implicit_sync_control
+#define EGL_EXT_image_implicit_sync_control 1
+#define EGL_IMPORT_SYNC_TYPE_EXT 0x3470
+#define EGL_IMPORT_IMPLICIT_SYNC_EXT 0x3471
+#define EGL_IMPORT_EXPLICIT_SYNC_EXT 0x3472
+#endif /* EGL_EXT_image_implicit_sync_control */
+
#ifndef EGL_EXT_multiview_window
#define EGL_EXT_multiview_window 1
#define EGL_MULTIVIEW_VIEW_COUNT_EXT 0x3134
@@ -632,8 +739,8 @@ EGLAPI EGLBoolean EGLAPIENTRY eglReleaseDeviceANGLE (EGLDeviceEXT device);
#define EGL_EXT_output_base 1
typedef void *EGLOutputLayerEXT;
typedef void *EGLOutputPortEXT;
-#define EGL_NO_OUTPUT_LAYER_EXT ((EGLOutputLayerEXT)0)
-#define EGL_NO_OUTPUT_PORT_EXT ((EGLOutputPortEXT)0)
+#define EGL_NO_OUTPUT_LAYER_EXT EGL_CAST(EGLOutputLayerEXT,0)
+#define EGL_NO_OUTPUT_PORT_EXT EGL_CAST(EGLOutputPortEXT,0)
#define EGL_BAD_OUTPUT_LAYER_EXT 0x322D
#define EGL_BAD_OUTPUT_PORT_EXT 0x322E
#define EGL_SWAP_INTERVAL_EXT 0x322F
@@ -670,6 +777,13 @@ EGLAPI const char *EGLAPIENTRY eglQueryOutputPortStringEXT (EGLDisplay dpy, EGLO
#define EGL_OPENWF_PORT_ID_EXT 0x3239
#endif /* EGL_EXT_output_openwf */
+#ifndef EGL_EXT_pixel_format_float
+#define EGL_EXT_pixel_format_float 1
+#define EGL_COLOR_COMPONENT_TYPE_EXT 0x3339
+#define EGL_COLOR_COMPONENT_TYPE_FIXED_EXT 0x333A
+#define EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT 0x333B
+#endif /* EGL_EXT_pixel_format_float */
+
#ifndef EGL_EXT_platform_base
#define EGL_EXT_platform_base 1
typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list);
@@ -698,9 +812,13 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurfaceEXT (EGLDisplay dpy,
#define EGL_PLATFORM_X11_SCREEN_EXT 0x31D6
#endif /* EGL_EXT_platform_x11 */
+#ifndef EGL_EXT_protected_content
+#define EGL_EXT_protected_content 1
+#define EGL_PROTECTED_CONTENT_EXT 0x32C0
+#endif /* EGL_EXT_protected_content */
+
#ifndef EGL_EXT_protected_surface
#define EGL_EXT_protected_surface 1
-#define EGL_PROTECTED_CONTENT_EXT 0x32C0
#endif /* EGL_EXT_protected_surface */
#ifndef EGL_EXT_stream_consumer_egloutput
@@ -711,6 +829,27 @@ EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerOutputEXT (EGLDisplay dpy, EGLStr
#endif
#endif /* EGL_EXT_stream_consumer_egloutput */
+#ifndef EGL_EXT_surface_CTA861_3_metadata
+#define EGL_EXT_surface_CTA861_3_metadata 1
+#define EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT 0x3360
+#define EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT 0x3361
+#endif /* EGL_EXT_surface_CTA861_3_metadata */
+
+#ifndef EGL_EXT_surface_SMPTE2086_metadata
+#define EGL_EXT_surface_SMPTE2086_metadata 1
+#define EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT 0x3341
+#define EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT 0x3342
+#define EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT 0x3343
+#define EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT 0x3344
+#define EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT 0x3345
+#define EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT 0x3346
+#define EGL_SMPTE2086_WHITE_POINT_X_EXT 0x3347
+#define EGL_SMPTE2086_WHITE_POINT_Y_EXT 0x3348
+#define EGL_SMPTE2086_MAX_LUMINANCE_EXT 0x3349
+#define EGL_SMPTE2086_MIN_LUMINANCE_EXT 0x334A
+#define EGL_METADATA_SCALING_EXT 50000
+#endif /* EGL_EXT_surface_SMPTE2086_metadata */
+
#ifndef EGL_EXT_swap_buffers_with_damage
#define EGL_EXT_swap_buffers_with_damage 1
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
@@ -779,6 +918,12 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI (EGLDisplay dpy, EGLConfi
#define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103
#endif /* EGL_IMG_context_priority */
+#ifndef EGL_IMG_image_plane_attribs
+#define EGL_IMG_image_plane_attribs 1
+#define EGL_NATIVE_BUFFER_MULTIPLANE_SEPARATE_IMG 0x3105
+#define EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG 0x3106
+#endif /* EGL_IMG_image_plane_attribs */
+
#ifndef EGL_MESA_drm_image
#define EGL_MESA_drm_image 1
#define EGL_DRM_BUFFER_FORMAT_MESA 0x31D0
@@ -811,6 +956,11 @@ EGLAPI EGLBoolean EGLAPIENTRY eglExportDMABUFImageMESA (EGLDisplay dpy, EGLImage
#define EGL_PLATFORM_GBM_MESA 0x31D7
#endif /* EGL_MESA_platform_gbm */
+#ifndef EGL_MESA_platform_surfaceless
+#define EGL_MESA_platform_surfaceless 1
+#define EGL_PLATFORM_SURFACELESS_MESA 0x31DD
+#endif /* EGL_MESA_platform_surfaceless */
+
#ifndef EGL_NOK_swap_region
#define EGL_NOK_swap_region 1
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGIONNOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
@@ -894,6 +1044,129 @@ EGLAPI EGLBoolean EGLAPIENTRY eglPostSubBufferNV (EGLDisplay dpy, EGLSurface sur
#endif
#endif /* EGL_NV_post_sub_buffer */
+#ifndef EGL_NV_robustness_video_memory_purge
+#define EGL_NV_robustness_video_memory_purge 1
+#define EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV 0x334C
+#endif /* EGL_NV_robustness_video_memory_purge */
+
+#ifndef EGL_NV_stream_consumer_gltexture_yuv
+#define EGL_NV_stream_consumer_gltexture_yuv 1
+#define EGL_YUV_PLANE0_TEXTURE_UNIT_NV 0x332C
+#define EGL_YUV_PLANE1_TEXTURE_UNIT_NV 0x332D
+#define EGL_YUV_PLANE2_TEXTURE_UNIT_NV 0x332E
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALATTRIBSNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLAttrib *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalAttribsNV (EGLDisplay dpy, EGLStreamKHR stream, EGLAttrib *attrib_list);
+#endif
+#endif /* EGL_NV_stream_consumer_gltexture_yuv */
+
+#ifndef EGL_NV_stream_cross_display
+#define EGL_NV_stream_cross_display 1
+#define EGL_STREAM_CROSS_DISPLAY_NV 0x334E
+#endif /* EGL_NV_stream_cross_display */
+
+#ifndef EGL_NV_stream_cross_object
+#define EGL_NV_stream_cross_object 1
+#define EGL_STREAM_CROSS_OBJECT_NV 0x334D
+#endif /* EGL_NV_stream_cross_object */
+
+#ifndef EGL_NV_stream_cross_partition
+#define EGL_NV_stream_cross_partition 1
+#define EGL_STREAM_CROSS_PARTITION_NV 0x323F
+#endif /* EGL_NV_stream_cross_partition */
+
+#ifndef EGL_NV_stream_cross_process
+#define EGL_NV_stream_cross_process 1
+#define EGL_STREAM_CROSS_PROCESS_NV 0x3245
+#endif /* EGL_NV_stream_cross_process */
+
+#ifndef EGL_NV_stream_cross_system
+#define EGL_NV_stream_cross_system 1
+#define EGL_STREAM_CROSS_SYSTEM_NV 0x334F
+#endif /* EGL_NV_stream_cross_system */
+
+#ifndef EGL_NV_stream_fifo_next
+#define EGL_NV_stream_fifo_next 1
+#define EGL_PENDING_FRAME_NV 0x3329
+#define EGL_STREAM_TIME_PENDING_NV 0x332A
+#endif /* EGL_NV_stream_fifo_next */
+
+#ifndef EGL_NV_stream_fifo_synchronous
+#define EGL_NV_stream_fifo_synchronous 1
+#define EGL_STREAM_FIFO_SYNCHRONOUS_NV 0x3336
+#endif /* EGL_NV_stream_fifo_synchronous */
+
+#ifndef EGL_NV_stream_frame_limits
+#define EGL_NV_stream_frame_limits 1
+#define EGL_PRODUCER_MAX_FRAME_HINT_NV 0x3337
+#define EGL_CONSUMER_MAX_FRAME_HINT_NV 0x3338
+#endif /* EGL_NV_stream_frame_limits */
+
+#ifndef EGL_NV_stream_metadata
+#define EGL_NV_stream_metadata 1
+#define EGL_MAX_STREAM_METADATA_BLOCKS_NV 0x3250
+#define EGL_MAX_STREAM_METADATA_BLOCK_SIZE_NV 0x3251
+#define EGL_MAX_STREAM_METADATA_TOTAL_SIZE_NV 0x3252
+#define EGL_PRODUCER_METADATA_NV 0x3253
+#define EGL_CONSUMER_METADATA_NV 0x3254
+#define EGL_PENDING_METADATA_NV 0x3328
+#define EGL_METADATA0_SIZE_NV 0x3255
+#define EGL_METADATA1_SIZE_NV 0x3256
+#define EGL_METADATA2_SIZE_NV 0x3257
+#define EGL_METADATA3_SIZE_NV 0x3258
+#define EGL_METADATA0_TYPE_NV 0x3259
+#define EGL_METADATA1_TYPE_NV 0x325A
+#define EGL_METADATA2_TYPE_NV 0x325B
+#define EGL_METADATA3_TYPE_NV 0x325C
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBNVPROC) (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETSTREAMMETADATANVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLint n, EGLint offset, EGLint size, const void *data);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMMETADATANVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum name, EGLint n, EGLint offset, EGLint size, void *data);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribNV (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglSetStreamMetadataNV (EGLDisplay dpy, EGLStreamKHR stream, EGLint n, EGLint offset, EGLint size, const void *data);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamMetadataNV (EGLDisplay dpy, EGLStreamKHR stream, EGLenum name, EGLint n, EGLint offset, EGLint size, void *data);
+#endif
+#endif /* EGL_NV_stream_metadata */
+
+#ifndef EGL_NV_stream_remote
+#define EGL_NV_stream_remote 1
+#define EGL_STREAM_STATE_INITIALIZING_NV 0x3240
+#define EGL_STREAM_TYPE_NV 0x3241
+#define EGL_STREAM_PROTOCOL_NV 0x3242
+#define EGL_STREAM_ENDPOINT_NV 0x3243
+#define EGL_STREAM_LOCAL_NV 0x3244
+#define EGL_STREAM_PRODUCER_NV 0x3247
+#define EGL_STREAM_CONSUMER_NV 0x3248
+#define EGL_STREAM_PROTOCOL_FD_NV 0x3246
+#endif /* EGL_NV_stream_remote */
+
+#ifndef EGL_NV_stream_reset
+#define EGL_NV_stream_reset 1
+#define EGL_SUPPORT_RESET_NV 0x3334
+#define EGL_SUPPORT_REUSE_NV 0x3335
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLRESETSTREAMNVPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglResetStreamNV (EGLDisplay dpy, EGLStreamKHR stream);
+#endif
+#endif /* EGL_NV_stream_reset */
+
+#ifndef EGL_NV_stream_socket
+#define EGL_NV_stream_socket 1
+#define EGL_STREAM_PROTOCOL_SOCKET_NV 0x324B
+#define EGL_SOCKET_HANDLE_NV 0x324C
+#define EGL_SOCKET_TYPE_NV 0x324D
+#endif /* EGL_NV_stream_socket */
+
+#ifndef EGL_NV_stream_socket_inet
+#define EGL_NV_stream_socket_inet 1
+#define EGL_SOCKET_TYPE_INET_NV 0x324F
+#endif /* EGL_NV_stream_socket_inet */
+
+#ifndef EGL_NV_stream_socket_unix
+#define EGL_NV_stream_socket_unix 1
+#define EGL_SOCKET_TYPE_UNIX_NV 0x324E
+#endif /* EGL_NV_stream_socket_unix */
+
#ifndef EGL_NV_stream_sync
#define EGL_NV_stream_sync 1
#define EGL_SYNC_NEW_FRAME_NV 0x321F
@@ -920,7 +1193,7 @@ typedef khronos_utime_nanoseconds_t EGLTimeNV;
#define EGL_SYNC_TYPE_NV 0x30ED
#define EGL_SYNC_CONDITION_NV 0x30EE
#define EGL_SYNC_FENCE_NV 0x30EF
-#define EGL_NO_SYNC_NV ((EGLSyncNV)0)
+#define EGL_NO_SYNC_NV EGL_CAST(EGLSyncNV,0)
typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync);
typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync);
@@ -961,6 +1234,9 @@ EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV (void);
#define EGL_NATIVE_SURFACE_TIZEN 0x32A1
#endif /* EGL_TIZEN_image_native_surface */
+/* ANGLE EGL extensions */
+#include "eglext_angle.h"
+
#ifdef __cplusplus
}
#endif
diff --git a/src/3rdparty/angle/include/EGL/eglext_angle.h b/src/3rdparty/angle/include/EGL/eglext_angle.h
new file mode 100644
index 0000000000..95f0902838
--- /dev/null
+++ b/src/3rdparty/angle/include/EGL/eglext_angle.h
@@ -0,0 +1,170 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// eglext_angle.h: ANGLE modifications to the eglext.h header file.
+// Currently we don't include this file directly, we patch eglext.h
+// to include it implicitly so it is visible throughout our code.
+
+#ifndef INCLUDE_EGL_EGLEXT_ANGLE_
+#define INCLUDE_EGL_EGLEXT_ANGLE_
+
+// clang-format off
+
+#ifndef EGL_ANGLE_robust_resource_initialization
+#define EGL_ANGLE_robust_resource_initialization 1
+#define EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE 0x3453
+#endif /* EGL_ANGLE_robust_resource_initialization */
+
+#ifndef EGL_ANGLE_keyed_mutex
+#define EGL_ANGLE_keyed_mutex 1
+#define EGL_DXGI_KEYED_MUTEX_ANGLE 0x33A2
+#endif /* EGL_ANGLE_keyed_mutex */
+
+#ifndef EGL_ANGLE_d3d_texture_client_buffer
+#define EGL_ANGLE_d3d_texture_client_buffer 1
+#define EGL_D3D_TEXTURE_ANGLE 0x33A3
+#endif /* EGL_ANGLE_d3d_texture_client_buffer */
+
+#ifndef EGL_ANGLE_software_display
+#define EGL_ANGLE_software_display 1
+#define EGL_SOFTWARE_DISPLAY_ANGLE ((EGLNativeDisplayType)-1)
+#endif /* EGL_ANGLE_software_display */
+
+#ifndef EGL_ANGLE_direct3d_display
+#define EGL_ANGLE_direct3d_display 1
+#define EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ((EGLNativeDisplayType)-2)
+#define EGL_D3D11_ONLY_DISPLAY_ANGLE ((EGLNativeDisplayType)-3)
+#endif /* EGL_ANGLE_direct3d_display */
+
+#ifndef EGL_ANGLE_direct_composition
+#define EGL_ANGLE_direct_composition 1
+#define EGL_DIRECT_COMPOSITION_ANGLE 0x33A5
+#endif /* EGL_ANGLE_direct_composition */
+
+#ifndef EGL_ANGLE_platform_angle
+#define EGL_ANGLE_platform_angle 1
+#define EGL_PLATFORM_ANGLE_ANGLE 0x3202
+#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203
+#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3204
+#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3205
+#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3206
+#define EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE 0x3451
+#endif /* EGL_ANGLE_platform_angle */
+
+#ifndef EGL_ANGLE_platform_angle_d3d
+#define EGL_ANGLE_platform_angle_d3d 1
+#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3207
+#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE 0x3209
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE 0x320A
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE 0x320B
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE 0x320C
+#define EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE 0x320F
+#endif /* EGL_ANGLE_platform_angle_d3d */
+
+#ifndef EGL_ANGLE_platform_angle_opengl
+#define EGL_ANGLE_platform_angle_opengl 1
+#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x320D
+#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320E
+#endif /* EGL_ANGLE_platform_angle_opengl */
+
+#ifndef EGL_ANGLE_platform_angle_null
+#define EGL_ANGLE_platform_angle_null 1
+#define EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE 0x33AE
+#endif /* EGL_ANGLE_platform_angle_null */
+
+#ifndef EGL_ANGLE_platform_angle_vulkan
+#define EGL_ANGLE_platform_angle_vulkan 1
+#define EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE 0x3450
+#endif /* EGL_ANGLE_platform_angle_vulkan */
+
+#ifndef EGL_ANGLE_x11_visual
+#define EGL_ANGLE_x11_visual
+#define EGL_X11_VISUAL_ID_ANGLE 0x33A3
+#endif /* EGL_ANGLE_x11_visual */
+
+#ifndef EGL_ANGLE_flexible_surface_compatibility
+#define EGL_ANGLE_flexible_surface_compatibility 1
+#define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6
+#endif /* EGL_ANGLE_flexible_surface_compatibility */
+
+#ifndef EGL_ANGLE_surface_orientation
+#define EGL_ANGLE_surface_orientation
+#define EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE 0x33A7
+#define EGL_SURFACE_ORIENTATION_ANGLE 0x33A8
+#define EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE 0x0001
+#define EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE 0x0002
+#endif /* EGL_ANGLE_surface_orientation */
+
+#ifndef EGL_ANGLE_experimental_present_path
+#define EGL_ANGLE_experimental_present_path
+#define EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE 0x33A4
+#define EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE 0x33A9
+#define EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE 0x33AA
+#endif /* EGL_ANGLE_experimental_present_path */
+
+#ifndef EGL_ANGLE_stream_producer_d3d_texture_nv12
+#define EGL_ANGLE_stream_producer_d3d_texture_nv12
+#define EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE 0x33AB
+typedef EGLBoolean(EGLAPIENTRYP PFNEGLCREATESTREAMPRODUCERD3DTEXTURENV12ANGLEPROC)(EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+typedef EGLBoolean(EGLAPIENTRYP PFNEGLSTREAMPOSTD3DTEXTURENV12ANGLEPROC)(EGLDisplay dpy, EGLStreamKHR stream, void *texture, const EGLAttrib *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglCreateStreamProducerD3DTextureNV12ANGLE(EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamPostD3DTextureNV12ANGLE(EGLDisplay dpy, EGLStreamKHR stream, void *texture, const EGLAttrib *attrib_list);
+#endif
+#endif /* EGL_ANGLE_stream_producer_d3d_texture_nv12 */
+
+#ifndef EGL_ANGLE_create_context_webgl_compatibility
+#define EGL_ANGLE_create_context_webgl_compatibility 1
+#define EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE 0x3AAC
+#endif /* EGL_ANGLE_create_context_webgl_compatibility */
+
+#ifndef EGL_ANGLE_display_texture_share_group
+#define EGL_ANGLE_display_texture_share_group 1
+#define EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE 0x3AAF
+#endif /* EGL_ANGLE_display_texture_share_group */
+
+#ifndef EGL_CHROMIUM_create_context_bind_generates_resource
+#define EGL_CHROMIUM_create_context_bind_generates_resource 1
+#define EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM 0x3AAD
+#endif /* EGL_CHROMIUM_create_context_bind_generates_resource */
+
+#ifndef EGL_ANGLE_create_context_client_arrays
+#define EGL_ANGLE_create_context_client_arrays 1
+#define EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE 0x3452
+#endif /* EGL_ANGLE_create_context_client_arrays */
+
+#ifndef EGL_ANGLE_device_creation
+#define EGL_ANGLE_device_creation 1
+typedef EGLDeviceEXT(EGLAPIENTRYP PFNEGLCREATEDEVICEANGLEPROC) (EGLint device_type, void *native_device, const EGLAttrib *attrib_list);
+typedef EGLBoolean(EGLAPIENTRYP PFNEGLRELEASEDEVICEANGLEPROC) (EGLDeviceEXT device);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLDeviceEXT EGLAPIENTRY eglCreateDeviceANGLE(EGLint device_type, void *native_device, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglReleaseDeviceANGLE(EGLDeviceEXT device);
+#endif
+#endif /* EGL_ANGLE_device_creation */
+
+#ifndef EGL_ANGLE_program_cache_control
+#define EGL_ANGLE_program_cache_control 1
+#define EGL_PROGRAM_CACHE_SIZE_ANGLE 0x3455
+#define EGL_PROGRAM_CACHE_KEY_LENGTH_ANGLE 0x3456
+#define EGL_PROGRAM_CACHE_RESIZE_ANGLE 0x3457
+#define EGL_PROGRAM_CACHE_TRIM_ANGLE 0x3458
+#define EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE 0x3459
+typedef EGLint (EGLAPIENTRYP PFNEGLPROGRAMCACHEGETATTRIBANGLEPROC) (EGLDisplay dpy, EGLenum attrib);
+typedef void (EGLAPIENTRYP PFNEGLPROGRAMCACHEQUERYANGLEPROC) (EGLDisplay dpy, EGLint index, void *key, EGLint *keysize, void *binary, EGLint *binarysize);
+typedef void (EGLAPIENTRYP PFNEGPROGRAMCACHELPOPULATEANGLEPROC) (EGLDisplay dpy, const void *key, EGLint keysize, const void *binary, EGLint binarysize);
+typedef EGLint (EGLAPIENTRYP PFNEGLPROGRAMCACHERESIZEANGLEPROC) (EGLDisplay dpy, EGLint limit, EGLenum mode);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLint EGLAPIENTRY eglProgramCacheGetAttribANGLE(EGLDisplay dpy, EGLenum attrib);
+EGLAPI void EGLAPIENTRY eglProgramCacheQueryANGLE(EGLDisplay dpy, EGLint index, void *key, EGLint *keysize, void *binary, EGLint *binarysize);
+EGLAPI void EGLAPIENTRY eglProgramCachePopulateANGLE(EGLDisplay dpy, const void *key, EGLint keysize, const void *binary, EGLint binarysize);
+EGLAPI EGLint EGLAPIENTRY eglProgramCacheResizeANGLE(EGLDisplay dpy, EGLint limit, EGLenum mode);
+#endif
+#endif /* EGL_ANGLE_program_cache_control */
+
+// clang-format on
+
+#endif // INCLUDE_EGL_EGLEXT_ANGLE_
diff --git a/src/3rdparty/angle/include/EGL/eglplatform.h b/src/3rdparty/angle/include/EGL/eglplatform.h
index 6d550da9cd..333448be34 100644
--- a/src/3rdparty/angle/include/EGL/eglplatform.h
+++ b/src/3rdparty/angle/include/EGL/eglplatform.h
@@ -2,7 +2,7 @@
#define __eglplatform_h_
/*
-** Copyright (c) 2007-2013 The Khronos Group Inc.
+** Copyright (c) 2007-2016 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
@@ -83,7 +83,8 @@ typedef HWND EGLNativeWindowType;
typedef IInspectable* EGLNativeWindowType;
#endif
-#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */
+#elif defined(__APPLE__) || defined(__WINSCW__) || defined(__SYMBIAN32__) || \
+ defined(__Fuchsia__) || defined(__HAIKU__)
typedef int EGLNativeDisplayType;
typedef void *EGLNativeWindowType;
@@ -105,6 +106,12 @@ typedef intptr_t EGLNativeDisplayType;
typedef intptr_t EGLNativeWindowType;
typedef intptr_t EGLNativePixmapType;
+#elif defined(WL_EGL_PLATFORM)
+
+typedef struct wl_display *EGLNativeDisplayType;
+typedef struct wl_egl_pixmap *EGLNativePixmapType;
+typedef struct wl_egl_window *EGLNativeWindowType;
+
#elif defined(__unix__)
/* X11 (tentative) */
@@ -115,18 +122,6 @@ typedef Display *EGLNativeDisplayType;
typedef Pixmap EGLNativePixmapType;
typedef Window EGLNativeWindowType;
-#elif defined(__GNUC__) && ( defined(__APPLE_CPP__) || defined(__APPLE_CC__) || defined(__MACOS_CLASSIC__) )
-
-#if defined(__OBJC__)
-@class CALayer;
-#else
-class CALayer;
-#endif
-
-typedef void *EGLNativeDisplayType;
-typedef void *EGLNativePixmapType;
-typedef CALayer *EGLNativeWindowType;
-
#else
#error "Platform not recognized"
#endif
@@ -146,4 +141,12 @@ typedef EGLNativeWindowType NativeWindowType;
*/
typedef khronos_int32_t EGLint;
+
+/* C++ / C typecast macros for special EGL handle values */
+#if defined(__cplusplus)
+#define EGL_CAST(type, value) (static_cast<type>(value))
+#else
+#define EGL_CAST(type, value) ((type) (value))
+#endif
+
#endif /* __eglplatform_h */
diff --git a/src/3rdparty/angle/include/GLES2/gl2.h b/src/3rdparty/angle/include/GLES2/gl2.h
index 027e1f7136..975c3dc495 100644
--- a/src/3rdparty/angle/include/GLES2/gl2.h
+++ b/src/3rdparty/angle/include/GLES2/gl2.h
@@ -6,7 +6,7 @@ extern "C" {
#endif
/*
-** Copyright (c) 2013-2015 The Khronos Group Inc.
+** Copyright (c) 2013-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
@@ -31,9 +31,7 @@ extern "C" {
** This header is generated from the Khronos OpenGL / OpenGL ES XML
** API Registry. The current version of the Registry, generator scripts
** used to make the header, and the header can be found at
-** http://www.opengl.org/registry/
-**
-** Khronos $Revision: 31811 $ on $Date: 2015-08-10 00:01:11 -0700 (Mon, 10 Aug 2015) $
+** https://github.com/KhronosGroup/OpenGL-Registry
*/
#include <GLES2/gl2platform.h>
@@ -42,7 +40,11 @@ extern "C" {
#define GL_APIENTRYP GL_APIENTRY*
#endif
-/* Generated on date 20150809 */
+#ifndef GL_GLES_PROTOTYPES
+#define GL_GLES_PROTOTYPES 1
+#endif
+
+/* Generated on date 20170325 */
/* Generated C header for:
* API: gles2
@@ -520,7 +522,7 @@ typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GL
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
typedef void (GL_APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
-#ifdef GL_GLEXT_PROTOTYPES
+#if GL_GLES_PROTOTYPES
GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
diff --git a/src/3rdparty/angle/include/GLES2/gl2ext.h b/src/3rdparty/angle/include/GLES2/gl2ext.h
index 51886a2dcb..4def3ced4b 100644
--- a/src/3rdparty/angle/include/GLES2/gl2ext.h
+++ b/src/3rdparty/angle/include/GLES2/gl2ext.h
@@ -6,7 +6,7 @@ extern "C" {
#endif
/*
-** Copyright (c) 2013-2015 The Khronos Group Inc.
+** Copyright (c) 2013-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
@@ -31,16 +31,14 @@ extern "C" {
** This header is generated from the Khronos OpenGL / OpenGL ES XML
** API Registry. The current version of the Registry, generator scripts
** used to make the header, and the header can be found at
-** http://www.opengl.org/registry/
-**
-** Khronos $Revision: 31902 $ on $Date: 2015-09-03 15:44:53 -0700 (Thu, 03 Sep 2015) $
+** https://github.com/KhronosGroup/OpenGL-Registry
*/
#ifndef GL_APIENTRYP
#define GL_APIENTRYP GL_APIENTRY*
#endif
-/* Generated on date 20150903 */
+/* Generated on date 20170613 */
/* Generated C header for:
* API: gles2
@@ -225,6 +223,10 @@ GL_APICALL void GL_APIENTRY glGetnUniformuivKHR (GLuint program, GLint location,
#define GL_KHR_texture_compression_astc_ldr 1
#endif /* GL_KHR_texture_compression_astc_ldr */
+#ifndef GL_KHR_texture_compression_astc_sliced_3d
+#define GL_KHR_texture_compression_astc_sliced_3d 1
+#endif /* GL_KHR_texture_compression_astc_sliced_3d */
+
#ifndef GL_OES_EGL_image
#define GL_OES_EGL_image 1
typedef void *GLeglImageOES;
@@ -748,6 +750,34 @@ GL_APICALL GLboolean GL_APIENTRY glIsVertexArrayOES (GLuint array);
#define GL_INT_10_10_10_2_OES 0x8DF7
#endif /* GL_OES_vertex_type_10_10_10_2 */
+#ifndef GL_OES_viewport_array
+#define GL_OES_viewport_array 1
+#define GL_MAX_VIEWPORTS_OES 0x825B
+#define GL_VIEWPORT_SUBPIXEL_BITS_OES 0x825C
+#define GL_VIEWPORT_BOUNDS_RANGE_OES 0x825D
+#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX_OES 0x825F
+typedef void (GL_APIENTRYP PFNGLVIEWPORTARRAYVOESPROC) (GLuint first, GLsizei count, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTINDEXEDFOESPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTINDEXEDFVOESPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLSCISSORARRAYVOESPROC) (GLuint first, GLsizei count, const GLint *v);
+typedef void (GL_APIENTRYP PFNGLSCISSORINDEXEDOESPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSCISSORINDEXEDVOESPROC) (GLuint index, const GLint *v);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEARRAYFVOESPROC) (GLuint first, GLsizei count, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEINDEXEDFOESPROC) (GLuint index, GLfloat n, GLfloat f);
+typedef void (GL_APIENTRYP PFNGLGETFLOATI_VOESPROC) (GLenum target, GLuint index, GLfloat *data);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glViewportArrayvOES (GLuint first, GLsizei count, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glViewportIndexedfOES (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+GL_APICALL void GL_APIENTRY glViewportIndexedfvOES (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glScissorArrayvOES (GLuint first, GLsizei count, const GLint *v);
+GL_APICALL void GL_APIENTRY glScissorIndexedOES (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glScissorIndexedvOES (GLuint index, const GLint *v);
+GL_APICALL void GL_APIENTRY glDepthRangeArrayfvOES (GLuint first, GLsizei count, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glDepthRangeIndexedfOES (GLuint index, GLfloat n, GLfloat f);
+GL_APICALL void GL_APIENTRY glGetFloati_vOES (GLenum target, GLuint index, GLfloat *data);
+#endif
+#endif /* GL_OES_viewport_array */
+
#ifndef GL_AMD_compressed_3DC_texture
#define GL_AMD_compressed_3DC_texture 1
#define GL_3DC_X_AMD 0x87F9
@@ -1021,6 +1051,10 @@ GL_APICALL void GL_APIENTRY glGetSyncivAPPLE (GLsync sync, GLenum pname, GLsizei
#define GL_SHADER_BINARY_DMP 0x9250
#endif /* GL_DMP_shader_binary */
+#ifndef GL_EXT_EGL_image_array
+#define GL_EXT_EGL_image_array 1
+#endif /* GL_EXT_EGL_image_array */
+
#ifndef GL_EXT_YUV_target
#define GL_EXT_YUV_target 1
#define GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT 0x8BE7
@@ -1082,6 +1116,31 @@ GL_APICALL void GL_APIENTRY glBufferStorageEXT (GLenum target, GLsizeiptr size,
#endif
#endif /* GL_EXT_buffer_storage */
+#ifndef GL_EXT_clear_texture
+#define GL_EXT_clear_texture 1
+typedef void (GL_APIENTRYP PFNGLCLEARTEXIMAGEEXTPROC) (GLuint texture, GLint level, GLenum format, GLenum type, const void *data);
+typedef void (GL_APIENTRYP PFNGLCLEARTEXSUBIMAGEEXTPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glClearTexImageEXT (GLuint texture, GLint level, GLenum format, GLenum type, const void *data);
+GL_APICALL void GL_APIENTRY glClearTexSubImageEXT (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data);
+#endif
+#endif /* GL_EXT_clear_texture */
+
+#ifndef GL_EXT_clip_cull_distance
+#define GL_EXT_clip_cull_distance 1
+#define GL_MAX_CLIP_DISTANCES_EXT 0x0D32
+#define GL_MAX_CULL_DISTANCES_EXT 0x82F9
+#define GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT 0x82FA
+#define GL_CLIP_DISTANCE0_EXT 0x3000
+#define GL_CLIP_DISTANCE1_EXT 0x3001
+#define GL_CLIP_DISTANCE2_EXT 0x3002
+#define GL_CLIP_DISTANCE3_EXT 0x3003
+#define GL_CLIP_DISTANCE4_EXT 0x3004
+#define GL_CLIP_DISTANCE5_EXT 0x3005
+#define GL_CLIP_DISTANCE6_EXT 0x3006
+#define GL_CLIP_DISTANCE7_EXT 0x3007
+#endif /* GL_EXT_clip_cull_distance */
+
#ifndef GL_EXT_color_buffer_float
#define GL_EXT_color_buffer_float 1
#endif /* GL_EXT_color_buffer_float */
@@ -1096,6 +1155,10 @@ GL_APICALL void GL_APIENTRY glBufferStorageEXT (GLenum target, GLsizeiptr size,
#define GL_UNSIGNED_NORMALIZED_EXT 0x8C17
#endif /* GL_EXT_color_buffer_half_float */
+#ifndef GL_EXT_conservative_depth
+#define GL_EXT_conservative_depth 1
+#endif /* GL_EXT_conservative_depth */
+
#ifndef GL_EXT_copy_image
#define GL_EXT_copy_image 1
typedef void (GL_APIENTRYP PFNGLCOPYIMAGESUBDATAEXTPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
@@ -1267,6 +1330,27 @@ GL_APICALL void GL_APIENTRY glDrawElementsInstancedEXT (GLenum mode, GLsizei cou
#endif
#endif /* GL_EXT_draw_instanced */
+#ifndef GL_EXT_draw_transform_feedback
+#define GL_EXT_draw_transform_feedback 1
+typedef void (GL_APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKEXTPROC) (GLenum mode, GLuint id);
+typedef void (GL_APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDEXTPROC) (GLenum mode, GLuint id, GLsizei instancecount);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawTransformFeedbackEXT (GLenum mode, GLuint id);
+GL_APICALL void GL_APIENTRY glDrawTransformFeedbackInstancedEXT (GLenum mode, GLuint id, GLsizei instancecount);
+#endif
+#endif /* GL_EXT_draw_transform_feedback */
+
+#ifndef GL_EXT_external_buffer
+#define GL_EXT_external_buffer 1
+typedef void *GLeglClientBufferEXT;
+typedef void (GL_APIENTRYP PFNGLBUFFERSTORAGEEXTERNALEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags);
+typedef void (GL_APIENTRYP PFNGLNAMEDBUFFERSTORAGEEXTERNALEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBufferStorageExternalEXT (GLenum target, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags);
+GL_APICALL void GL_APIENTRY glNamedBufferStorageExternalEXT (GLuint buffer, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags);
+#endif
+#endif /* GL_EXT_external_buffer */
+
#ifndef GL_EXT_float_blend
#define GL_EXT_float_blend 1
#endif /* GL_EXT_float_blend */
@@ -1345,6 +1429,85 @@ GL_APICALL void GL_APIENTRY glFlushMappedBufferRangeEXT (GLenum target, GLintptr
#endif
#endif /* GL_EXT_map_buffer_range */
+#ifndef GL_EXT_memory_object
+#define GL_EXT_memory_object 1
+#define GL_TEXTURE_TILING_EXT 0x9580
+#define GL_DEDICATED_MEMORY_OBJECT_EXT 0x9581
+#define GL_PROTECTED_MEMORY_OBJECT_EXT 0x959B
+#define GL_NUM_TILING_TYPES_EXT 0x9582
+#define GL_TILING_TYPES_EXT 0x9583
+#define GL_OPTIMAL_TILING_EXT 0x9584
+#define GL_LINEAR_TILING_EXT 0x9585
+#define GL_NUM_DEVICE_UUIDS_EXT 0x9596
+#define GL_DEVICE_UUID_EXT 0x9597
+#define GL_DRIVER_UUID_EXT 0x9598
+#define GL_UUID_SIZE_EXT 16
+typedef void (GL_APIENTRYP PFNGLGETUNSIGNEDBYTEVEXTPROC) (GLenum pname, GLubyte *data);
+typedef void (GL_APIENTRYP PFNGLGETUNSIGNEDBYTEI_VEXTPROC) (GLenum target, GLuint index, GLubyte *data);
+typedef void (GL_APIENTRYP PFNGLDELETEMEMORYOBJECTSEXTPROC) (GLsizei n, const GLuint *memoryObjects);
+typedef GLboolean (GL_APIENTRYP PFNGLISMEMORYOBJECTEXTPROC) (GLuint memoryObject);
+typedef void (GL_APIENTRYP PFNGLCREATEMEMORYOBJECTSEXTPROC) (GLsizei n, GLuint *memoryObjects);
+typedef void (GL_APIENTRYP PFNGLMEMORYOBJECTPARAMETERIVEXTPROC) (GLuint memoryObject, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETMEMORYOBJECTPARAMETERIVEXTPROC) (GLuint memoryObject, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGEMEM2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGEMEM2DMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGEMEM3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGEMEM3DMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLBUFFERSTORAGEMEMEXTPROC) (GLenum target, GLsizeiptr size, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGEMEM2DEXTPROC) (GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGEMEM2DMULTISAMPLEEXTPROC) (GLuint texture, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGEMEM3DEXTPROC) (GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGEMEM3DMULTISAMPLEEXTPROC) (GLuint texture, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+typedef void (GL_APIENTRYP PFNGLNAMEDBUFFERSTORAGEMEMEXTPROC) (GLuint buffer, GLsizeiptr size, GLuint memory, GLuint64 offset);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetUnsignedBytevEXT (GLenum pname, GLubyte *data);
+GL_APICALL void GL_APIENTRY glGetUnsignedBytei_vEXT (GLenum target, GLuint index, GLubyte *data);
+GL_APICALL void GL_APIENTRY glDeleteMemoryObjectsEXT (GLsizei n, const GLuint *memoryObjects);
+GL_APICALL GLboolean GL_APIENTRY glIsMemoryObjectEXT (GLuint memoryObject);
+GL_APICALL void GL_APIENTRY glCreateMemoryObjectsEXT (GLsizei n, GLuint *memoryObjects);
+GL_APICALL void GL_APIENTRY glMemoryObjectParameterivEXT (GLuint memoryObject, GLenum pname, const GLint *params);
+GL_APICALL void GL_APIENTRY glGetMemoryObjectParameterivEXT (GLuint memoryObject, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glTexStorageMem2DEXT (GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glTexStorageMem2DMultisampleEXT (GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glTexStorageMem3DEXT (GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glTexStorageMem3DMultisampleEXT (GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glBufferStorageMemEXT (GLenum target, GLsizeiptr size, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glTextureStorageMem2DEXT (GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glTextureStorageMem2DMultisampleEXT (GLuint texture, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glTextureStorageMem3DEXT (GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glTextureStorageMem3DMultisampleEXT (GLuint texture, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+GL_APICALL void GL_APIENTRY glNamedBufferStorageMemEXT (GLuint buffer, GLsizeiptr size, GLuint memory, GLuint64 offset);
+#endif
+#endif /* GL_EXT_memory_object */
+
+#ifndef GL_EXT_memory_object_fd
+#define GL_EXT_memory_object_fd 1
+#define GL_HANDLE_TYPE_OPAQUE_FD_EXT 0x9586
+typedef void (GL_APIENTRYP PFNGLIMPORTMEMORYFDEXTPROC) (GLuint memory, GLuint64 size, GLenum handleType, GLint fd);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glImportMemoryFdEXT (GLuint memory, GLuint64 size, GLenum handleType, GLint fd);
+#endif
+#endif /* GL_EXT_memory_object_fd */
+
+#ifndef GL_EXT_memory_object_win32
+#define GL_EXT_memory_object_win32 1
+#define GL_HANDLE_TYPE_OPAQUE_WIN32_EXT 0x9587
+#define GL_HANDLE_TYPE_OPAQUE_WIN32_KMT_EXT 0x9588
+#define GL_DEVICE_LUID_EXT 0x9599
+#define GL_DEVICE_NODE_MASK_EXT 0x959A
+#define GL_LUID_SIZE_EXT 8
+#define GL_HANDLE_TYPE_D3D12_TILEPOOL_EXT 0x9589
+#define GL_HANDLE_TYPE_D3D12_RESOURCE_EXT 0x958A
+#define GL_HANDLE_TYPE_D3D11_IMAGE_EXT 0x958B
+#define GL_HANDLE_TYPE_D3D11_IMAGE_KMT_EXT 0x958C
+typedef void (GL_APIENTRYP PFNGLIMPORTMEMORYWIN32HANDLEEXTPROC) (GLuint memory, GLuint64 size, GLenum handleType, void *handle);
+typedef void (GL_APIENTRYP PFNGLIMPORTMEMORYWIN32NAMEEXTPROC) (GLuint memory, GLuint64 size, GLenum handleType, const void *name);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glImportMemoryWin32HandleEXT (GLuint memory, GLuint64 size, GLenum handleType, void *handle);
+GL_APICALL void GL_APIENTRY glImportMemoryWin32NameEXT (GLuint memory, GLuint64 size, GLenum handleType, const void *name);
+#endif
+#endif /* GL_EXT_memory_object_win32 */
+
#ifndef GL_EXT_multi_draw_arrays
#define GL_EXT_multi_draw_arrays 1
typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
@@ -1408,6 +1571,15 @@ GL_APICALL void GL_APIENTRY glGetIntegeri_vEXT (GLenum target, GLuint index, GLi
#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT 0x8D6A
#endif /* GL_EXT_occlusion_query_boolean */
+#ifndef GL_EXT_polygon_offset_clamp
+#define GL_EXT_polygon_offset_clamp 1
+#define GL_POLYGON_OFFSET_CLAMP_EXT 0x8E1B
+typedef void (GL_APIENTRYP PFNGLPOLYGONOFFSETCLAMPEXTPROC) (GLfloat factor, GLfloat units, GLfloat clamp);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glPolygonOffsetClampEXT (GLfloat factor, GLfloat units, GLfloat clamp);
+#endif
+#endif /* GL_EXT_polygon_offset_clamp */
+
#ifndef GL_EXT_post_depth_coverage
#define GL_EXT_post_depth_coverage 1
#endif /* GL_EXT_post_depth_coverage */
@@ -1421,6 +1593,12 @@ GL_APICALL void GL_APIENTRY glPrimitiveBoundingBoxEXT (GLfloat minX, GLfloat min
#endif
#endif /* GL_EXT_primitive_bounding_box */
+#ifndef GL_EXT_protected_textures
+#define GL_EXT_protected_textures 1
+#define GL_CONTEXT_FLAG_PROTECTED_CONTENT_BIT_EXT 0x00000010
+#define GL_TEXTURE_PROTECTED_EXT 0x8BFA
+#endif /* GL_EXT_protected_textures */
+
#ifndef GL_EXT_pvrtc_sRGB
#define GL_EXT_pvrtc_sRGB 1
#define GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT 0x8A54
@@ -1495,6 +1673,53 @@ GL_APICALL void GL_APIENTRY glGetnUniformivEXT (GLuint program, GLint location,
#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9
#endif /* GL_EXT_sRGB_write_control */
+#ifndef GL_EXT_semaphore
+#define GL_EXT_semaphore 1
+#define GL_LAYOUT_GENERAL_EXT 0x958D
+#define GL_LAYOUT_COLOR_ATTACHMENT_EXT 0x958E
+#define GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT 0x958F
+#define GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT 0x9590
+#define GL_LAYOUT_SHADER_READ_ONLY_EXT 0x9591
+#define GL_LAYOUT_TRANSFER_SRC_EXT 0x9592
+#define GL_LAYOUT_TRANSFER_DST_EXT 0x9593
+typedef void (GL_APIENTRYP PFNGLGENSEMAPHORESEXTPROC) (GLsizei n, GLuint *semaphores);
+typedef void (GL_APIENTRYP PFNGLDELETESEMAPHORESEXTPROC) (GLsizei n, const GLuint *semaphores);
+typedef GLboolean (GL_APIENTRYP PFNGLISSEMAPHOREEXTPROC) (GLuint semaphore);
+typedef void (GL_APIENTRYP PFNGLSEMAPHOREPARAMETERUI64VEXTPROC) (GLuint semaphore, GLenum pname, const GLuint64 *params);
+typedef void (GL_APIENTRYP PFNGLGETSEMAPHOREPARAMETERUI64VEXTPROC) (GLuint semaphore, GLenum pname, GLuint64 *params);
+typedef void (GL_APIENTRYP PFNGLWAITSEMAPHOREEXTPROC) (GLuint semaphore, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *srcLayouts);
+typedef void (GL_APIENTRYP PFNGLSIGNALSEMAPHOREEXTPROC) (GLuint semaphore, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *dstLayouts);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGenSemaphoresEXT (GLsizei n, GLuint *semaphores);
+GL_APICALL void GL_APIENTRY glDeleteSemaphoresEXT (GLsizei n, const GLuint *semaphores);
+GL_APICALL GLboolean GL_APIENTRY glIsSemaphoreEXT (GLuint semaphore);
+GL_APICALL void GL_APIENTRY glSemaphoreParameterui64vEXT (GLuint semaphore, GLenum pname, const GLuint64 *params);
+GL_APICALL void GL_APIENTRY glGetSemaphoreParameterui64vEXT (GLuint semaphore, GLenum pname, GLuint64 *params);
+GL_APICALL void GL_APIENTRY glWaitSemaphoreEXT (GLuint semaphore, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *srcLayouts);
+GL_APICALL void GL_APIENTRY glSignalSemaphoreEXT (GLuint semaphore, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *dstLayouts);
+#endif
+#endif /* GL_EXT_semaphore */
+
+#ifndef GL_EXT_semaphore_fd
+#define GL_EXT_semaphore_fd 1
+typedef void (GL_APIENTRYP PFNGLIMPORTSEMAPHOREFDEXTPROC) (GLuint semaphore, GLenum handleType, GLint fd);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glImportSemaphoreFdEXT (GLuint semaphore, GLenum handleType, GLint fd);
+#endif
+#endif /* GL_EXT_semaphore_fd */
+
+#ifndef GL_EXT_semaphore_win32
+#define GL_EXT_semaphore_win32 1
+#define GL_HANDLE_TYPE_D3D12_FENCE_EXT 0x9594
+#define GL_D3D12_FENCE_VALUE_EXT 0x9595
+typedef void (GL_APIENTRYP PFNGLIMPORTSEMAPHOREWIN32HANDLEEXTPROC) (GLuint semaphore, GLenum handleType, void *handle);
+typedef void (GL_APIENTRYP PFNGLIMPORTSEMAPHOREWIN32NAMEEXTPROC) (GLuint semaphore, GLenum handleType, const void *name);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glImportSemaphoreWin32HandleEXT (GLuint semaphore, GLenum handleType, void *handle);
+GL_APICALL void GL_APIENTRY glImportSemaphoreWin32NameEXT (GLuint semaphore, GLenum handleType, const void *name);
+#endif
+#endif /* GL_EXT_semaphore_win32 */
+
#ifndef GL_EXT_separate_shader_objects
#define GL_EXT_separate_shader_objects 1
#define GL_ACTIVE_PROGRAM_EXT 0x8259
@@ -1600,6 +1825,10 @@ GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x3fvEXT (GLuint program, GLin
#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52
#endif /* GL_EXT_shader_framebuffer_fetch */
+#ifndef GL_EXT_shader_group_vote
+#define GL_EXT_shader_group_vote 1
+#endif /* GL_EXT_shader_group_vote */
+
#ifndef GL_EXT_shader_implicit_conversions
#define GL_EXT_shader_implicit_conversions 1
#endif /* GL_EXT_shader_implicit_conversions */
@@ -1612,6 +1841,10 @@ GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x3fvEXT (GLuint program, GLin
#define GL_EXT_shader_io_blocks 1
#endif /* GL_EXT_shader_io_blocks */
+#ifndef GL_EXT_shader_non_constant_global_initializers
+#define GL_EXT_shader_non_constant_global_initializers 1
+#endif /* GL_EXT_shader_non_constant_global_initializers */
+
#ifndef GL_EXT_shader_pixel_local_storage
#define GL_EXT_shader_pixel_local_storage 1
#define GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT 0x8F63
@@ -1619,6 +1852,21 @@ GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x3fvEXT (GLuint program, GLin
#define GL_SHADER_PIXEL_LOCAL_STORAGE_EXT 0x8F64
#endif /* GL_EXT_shader_pixel_local_storage */
+#ifndef GL_EXT_shader_pixel_local_storage2
+#define GL_EXT_shader_pixel_local_storage2 1
+#define GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_FAST_SIZE_EXT 0x9650
+#define GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_SIZE_EXT 0x9651
+#define GL_FRAMEBUFFER_INCOMPLETE_INSUFFICIENT_SHADER_COMBINED_LOCAL_STORAGE_EXT 0x9652
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC) (GLuint target, GLsizei size);
+typedef GLsizei (GL_APIENTRYP PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC) (GLuint target);
+typedef void (GL_APIENTRYP PFNGLCLEARPIXELLOCALSTORAGEUIEXTPROC) (GLsizei offset, GLsizei n, const GLuint *values);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferPixelLocalStorageSizeEXT (GLuint target, GLsizei size);
+GL_APICALL GLsizei GL_APIENTRY glGetFramebufferPixelLocalStorageSizeEXT (GLuint target);
+GL_APICALL void GL_APIENTRY glClearPixelLocalStorageuiEXT (GLsizei offset, GLsizei n, const GLuint *values);
+#endif
+#endif /* GL_EXT_shader_pixel_local_storage2 */
+
#ifndef GL_EXT_shader_texture_lod
#define GL_EXT_shader_texture_lod 1
#endif /* GL_EXT_shader_texture_lod */
@@ -1652,6 +1900,10 @@ GL_APICALL void GL_APIENTRY glTexPageCommitmentEXT (GLenum target, GLint level,
#endif
#endif /* GL_EXT_sparse_texture */
+#ifndef GL_EXT_sparse_texture2
+#define GL_EXT_sparse_texture2 1
+#endif /* GL_EXT_sparse_texture2 */
+
#ifndef GL_EXT_tessellation_point_size
#define GL_EXT_tessellation_point_size 1
#endif /* GL_EXT_tessellation_point_size */
@@ -1755,6 +2007,11 @@ GL_APICALL void GL_APIENTRY glTexBufferRangeEXT (GLenum target, GLenum internalf
#endif
#endif /* GL_EXT_texture_buffer */
+#ifndef GL_EXT_texture_compression_astc_decode_mode
+#define GL_EXT_texture_compression_astc_decode_mode 1
+#define GL_TEXTURE_ASTC_DECODE_PRECISION_EXT 0x8F69
+#endif /* GL_EXT_texture_compression_astc_decode_mode */
+
#ifndef GL_EXT_texture_compression_dxt1
#define GL_EXT_texture_compression_dxt1 1
#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
@@ -1884,11 +2141,67 @@ GL_APICALL void GL_APIENTRY glTextureViewEXT (GLuint texture, GLenum target, GLu
#define GL_UNPACK_SKIP_PIXELS_EXT 0x0CF4
#endif /* GL_EXT_unpack_subimage */
+#ifndef GL_EXT_win32_keyed_mutex
+#define GL_EXT_win32_keyed_mutex 1
+typedef GLboolean (GL_APIENTRYP PFNGLACQUIREKEYEDMUTEXWIN32EXTPROC) (GLuint memory, GLuint64 key, GLuint timeout);
+typedef GLboolean (GL_APIENTRYP PFNGLRELEASEKEYEDMUTEXWIN32EXTPROC) (GLuint memory, GLuint64 key);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLboolean GL_APIENTRY glAcquireKeyedMutexWin32EXT (GLuint memory, GLuint64 key, GLuint timeout);
+GL_APICALL GLboolean GL_APIENTRY glReleaseKeyedMutexWin32EXT (GLuint memory, GLuint64 key);
+#endif
+#endif /* GL_EXT_win32_keyed_mutex */
+
+#ifndef GL_EXT_window_rectangles
+#define GL_EXT_window_rectangles 1
+#define GL_INCLUSIVE_EXT 0x8F10
+#define GL_EXCLUSIVE_EXT 0x8F11
+#define GL_WINDOW_RECTANGLE_EXT 0x8F12
+#define GL_WINDOW_RECTANGLE_MODE_EXT 0x8F13
+#define GL_MAX_WINDOW_RECTANGLES_EXT 0x8F14
+#define GL_NUM_WINDOW_RECTANGLES_EXT 0x8F15
+typedef void (GL_APIENTRYP PFNGLWINDOWRECTANGLESEXTPROC) (GLenum mode, GLsizei count, const GLint *box);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glWindowRectanglesEXT (GLenum mode, GLsizei count, const GLint *box);
+#endif
+#endif /* GL_EXT_window_rectangles */
+
#ifndef GL_FJ_shader_binary_GCCSO
#define GL_FJ_shader_binary_GCCSO 1
#define GL_GCCSO_SHADER_BINARY_FJ 0x9260
#endif /* GL_FJ_shader_binary_GCCSO */
+#ifndef GL_IMG_bindless_texture
+#define GL_IMG_bindless_texture 1
+typedef GLuint64 (GL_APIENTRYP PFNGLGETTEXTUREHANDLEIMGPROC) (GLuint texture);
+typedef GLuint64 (GL_APIENTRYP PFNGLGETTEXTURESAMPLERHANDLEIMGPROC) (GLuint texture, GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLUNIFORMHANDLEUI64IMGPROC) (GLint location, GLuint64 value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMHANDLEUI64VIMGPROC) (GLint location, GLsizei count, const GLuint64 *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64IMGPROC) (GLuint program, GLint location, GLuint64 value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64VIMGPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLuint64 GL_APIENTRY glGetTextureHandleIMG (GLuint texture);
+GL_APICALL GLuint64 GL_APIENTRY glGetTextureSamplerHandleIMG (GLuint texture, GLuint sampler);
+GL_APICALL void GL_APIENTRY glUniformHandleui64IMG (GLint location, GLuint64 value);
+GL_APICALL void GL_APIENTRY glUniformHandleui64vIMG (GLint location, GLsizei count, const GLuint64 *value);
+GL_APICALL void GL_APIENTRY glProgramUniformHandleui64IMG (GLuint program, GLint location, GLuint64 value);
+GL_APICALL void GL_APIENTRY glProgramUniformHandleui64vIMG (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+#endif
+#endif /* GL_IMG_bindless_texture */
+
+#ifndef GL_IMG_framebuffer_downsample
+#define GL_IMG_framebuffer_downsample 1
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_AND_DOWNSAMPLE_IMG 0x913C
+#define GL_NUM_DOWNSAMPLE_SCALES_IMG 0x913D
+#define GL_DOWNSAMPLE_SCALES_IMG 0x913E
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SCALE_IMG 0x913F
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DDOWNSAMPLEIMGPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint xscale, GLint yscale);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERDOWNSAMPLEIMGPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer, GLint xscale, GLint yscale);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferTexture2DDownsampleIMG (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint xscale, GLint yscale);
+GL_APICALL void GL_APIENTRY glFramebufferTextureLayerDownsampleIMG (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer, GLint xscale, GLint yscale);
+#endif
+#endif /* GL_IMG_framebuffer_downsample */
+
#ifndef GL_IMG_multisampled_render_to_texture
#define GL_IMG_multisampled_render_to_texture 1
#define GL_RENDERBUFFER_SAMPLES_IMG 0x9133
@@ -1933,6 +2246,18 @@ GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum target,
#define GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG 0x9138
#endif /* GL_IMG_texture_compression_pvrtc2 */
+#ifndef GL_IMG_texture_filter_cubic
+#define GL_IMG_texture_filter_cubic 1
+#define GL_CUBIC_IMG 0x9139
+#define GL_CUBIC_MIPMAP_NEAREST_IMG 0x913A
+#define GL_CUBIC_MIPMAP_LINEAR_IMG 0x913B
+#endif /* GL_IMG_texture_filter_cubic */
+
+#ifndef GL_INTEL_conservative_rasterization
+#define GL_INTEL_conservative_rasterization 1
+#define GL_CONSERVATIVE_RASTERIZATION_INTEL 0x83FE
+#endif /* GL_INTEL_conservative_rasterization */
+
#ifndef GL_INTEL_framebuffer_CMAA
#define GL_INTEL_framebuffer_CMAA 1
typedef void (GL_APIENTRYP PFNGLAPPLYFRAMEBUFFERATTACHMENTCMAAINTELPROC) (void);
@@ -1987,6 +2312,14 @@ GL_APICALL void GL_APIENTRY glGetPerfQueryInfoINTEL (GLuint queryId, GLuint quer
#endif
#endif /* GL_INTEL_performance_query */
+#ifndef GL_MESA_shader_integer_functions
+#define GL_MESA_shader_integer_functions 1
+#endif /* GL_MESA_shader_integer_functions */
+
+#ifndef GL_NVX_blend_equation_advanced_multi_draw_buffers
+#define GL_NVX_blend_equation_advanced_multi_draw_buffers 1
+#endif /* GL_NVX_blend_equation_advanced_multi_draw_buffers */
+
#ifndef GL_NV_bindless_texture
#define GL_NV_bindless_texture 1
typedef GLuint64 (GL_APIENTRYP PFNGLGETTEXTUREHANDLENVPROC) (GLuint texture);
@@ -2109,6 +2442,17 @@ GL_APICALL void GL_APIENTRY glSubpixelPrecisionBiasNV (GLuint xbits, GLuint ybit
#endif
#endif /* GL_NV_conservative_raster */
+#ifndef GL_NV_conservative_raster_pre_snap_triangles
+#define GL_NV_conservative_raster_pre_snap_triangles 1
+#define GL_CONSERVATIVE_RASTER_MODE_NV 0x954D
+#define GL_CONSERVATIVE_RASTER_MODE_POST_SNAP_NV 0x954E
+#define GL_CONSERVATIVE_RASTER_MODE_PRE_SNAP_TRIANGLES_NV 0x954F
+typedef void (GL_APIENTRYP PFNGLCONSERVATIVERASTERPARAMETERINVPROC) (GLenum pname, GLint param);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glConservativeRasterParameteriNV (GLenum pname, GLint param);
+#endif
+#endif /* GL_NV_conservative_raster_pre_snap_triangles */
+
#ifndef GL_NV_copy_buffer
#define GL_NV_copy_buffer 1
#define GL_COPY_READ_BUFFER_NV 0x8F36
@@ -2194,6 +2538,23 @@ GL_APICALL void GL_APIENTRY glDrawElementsInstancedNV (GLenum mode, GLsizei coun
#endif
#endif /* GL_NV_draw_instanced */
+#ifndef GL_NV_draw_vulkan_image
+#define GL_NV_draw_vulkan_image 1
+typedef void (GL_APIENTRY *GLVULKANPROCNV)(void);
+typedef void (GL_APIENTRYP PFNGLDRAWVKIMAGENVPROC) (GLuint64 vkImage, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1);
+typedef GLVULKANPROCNV (GL_APIENTRYP PFNGLGETVKPROCADDRNVPROC) (const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLWAITVKSEMAPHORENVPROC) (GLuint64 vkSemaphore);
+typedef void (GL_APIENTRYP PFNGLSIGNALVKSEMAPHORENVPROC) (GLuint64 vkSemaphore);
+typedef void (GL_APIENTRYP PFNGLSIGNALVKFENCENVPROC) (GLuint64 vkFence);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawVkImageNV (GLuint64 vkImage, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1);
+GL_APICALL GLVULKANPROCNV GL_APIENTRY glGetVkProcAddrNV (const GLchar *name);
+GL_APICALL void GL_APIENTRY glWaitVkSemaphoreNV (GLuint64 vkSemaphore);
+GL_APICALL void GL_APIENTRY glSignalVkSemaphoreNV (GLuint64 vkSemaphore);
+GL_APICALL void GL_APIENTRY glSignalVkFenceNV (GLuint64 vkFence);
+#endif
+#endif /* GL_NV_draw_vulkan_image */
+
#ifndef GL_NV_explicit_attrib_location
#define GL_NV_explicit_attrib_location 1
#endif /* GL_NV_explicit_attrib_location */
@@ -2296,6 +2657,109 @@ GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleNV (GLenum target, G
#define GL_NV_geometry_shader_passthrough 1
#endif /* GL_NV_geometry_shader_passthrough */
+#ifndef GL_NV_gpu_shader5
+#define GL_NV_gpu_shader5 1
+typedef khronos_int64_t GLint64EXT;
+typedef khronos_uint64_t GLuint64EXT;
+#define GL_INT64_NV 0x140E
+#define GL_UNSIGNED_INT64_NV 0x140F
+#define GL_INT8_NV 0x8FE0
+#define GL_INT8_VEC2_NV 0x8FE1
+#define GL_INT8_VEC3_NV 0x8FE2
+#define GL_INT8_VEC4_NV 0x8FE3
+#define GL_INT16_NV 0x8FE4
+#define GL_INT16_VEC2_NV 0x8FE5
+#define GL_INT16_VEC3_NV 0x8FE6
+#define GL_INT16_VEC4_NV 0x8FE7
+#define GL_INT64_VEC2_NV 0x8FE9
+#define GL_INT64_VEC3_NV 0x8FEA
+#define GL_INT64_VEC4_NV 0x8FEB
+#define GL_UNSIGNED_INT8_NV 0x8FEC
+#define GL_UNSIGNED_INT8_VEC2_NV 0x8FED
+#define GL_UNSIGNED_INT8_VEC3_NV 0x8FEE
+#define GL_UNSIGNED_INT8_VEC4_NV 0x8FEF
+#define GL_UNSIGNED_INT16_NV 0x8FF0
+#define GL_UNSIGNED_INT16_VEC2_NV 0x8FF1
+#define GL_UNSIGNED_INT16_VEC3_NV 0x8FF2
+#define GL_UNSIGNED_INT16_VEC4_NV 0x8FF3
+#define GL_UNSIGNED_INT64_VEC2_NV 0x8FF5
+#define GL_UNSIGNED_INT64_VEC3_NV 0x8FF6
+#define GL_UNSIGNED_INT64_VEC4_NV 0x8FF7
+#define GL_FLOAT16_NV 0x8FF8
+#define GL_FLOAT16_VEC2_NV 0x8FF9
+#define GL_FLOAT16_VEC3_NV 0x8FFA
+#define GL_FLOAT16_VEC4_NV 0x8FFB
+#define GL_PATCHES 0x000E
+typedef void (GL_APIENTRYP PFNGLUNIFORM1I64NVPROC) (GLint location, GLint64EXT x);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1UI64NVPROC) (GLint location, GLuint64EXT x);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMI64VNVPROC) (GLuint program, GLint location, GLint64EXT *params);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1I64NVPROC) (GLuint program, GLint location, GLint64EXT x);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glUniform1i64NV (GLint location, GLint64EXT x);
+GL_APICALL void GL_APIENTRY glUniform2i64NV (GLint location, GLint64EXT x, GLint64EXT y);
+GL_APICALL void GL_APIENTRY glUniform3i64NV (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+GL_APICALL void GL_APIENTRY glUniform4i64NV (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+GL_APICALL void GL_APIENTRY glUniform1i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GL_APICALL void GL_APIENTRY glUniform2i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GL_APICALL void GL_APIENTRY glUniform3i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GL_APICALL void GL_APIENTRY glUniform4i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GL_APICALL void GL_APIENTRY glUniform1ui64NV (GLint location, GLuint64EXT x);
+GL_APICALL void GL_APIENTRY glUniform2ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y);
+GL_APICALL void GL_APIENTRY glUniform3ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+GL_APICALL void GL_APIENTRY glUniform4ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+GL_APICALL void GL_APIENTRY glUniform1ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GL_APICALL void GL_APIENTRY glUniform2ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GL_APICALL void GL_APIENTRY glUniform3ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GL_APICALL void GL_APIENTRY glUniform4ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GL_APICALL void GL_APIENTRY glGetUniformi64vNV (GLuint program, GLint location, GLint64EXT *params);
+GL_APICALL void GL_APIENTRY glProgramUniform1i64NV (GLuint program, GLint location, GLint64EXT x);
+GL_APICALL void GL_APIENTRY glProgramUniform2i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y);
+GL_APICALL void GL_APIENTRY glProgramUniform3i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+GL_APICALL void GL_APIENTRY glProgramUniform4i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+GL_APICALL void GL_APIENTRY glProgramUniform1i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GL_APICALL void GL_APIENTRY glProgramUniform1ui64NV (GLuint program, GLint location, GLuint64EXT x);
+GL_APICALL void GL_APIENTRY glProgramUniform2ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y);
+GL_APICALL void GL_APIENTRY glProgramUniform3ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+GL_APICALL void GL_APIENTRY glProgramUniform4ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+GL_APICALL void GL_APIENTRY glProgramUniform1ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+#endif
+#endif /* GL_NV_gpu_shader5 */
+
#ifndef GL_NV_image_formats
#define GL_NV_image_formats 1
#endif /* GL_NV_image_formats */
@@ -2702,6 +3166,10 @@ GL_APICALL void GL_APIENTRY glResolveDepthValuesNV (void);
#define GL_NV_sample_mask_override_coverage 1
#endif /* GL_NV_sample_mask_override_coverage */
+#ifndef GL_NV_shader_atomic_fp16_vector
+#define GL_NV_shader_atomic_fp16_vector 1
+#endif /* GL_NV_shader_atomic_fp16_vector */
+
#ifndef GL_NV_shader_noperspective_interpolation
#define GL_NV_shader_noperspective_interpolation 1
#endif /* GL_NV_shader_noperspective_interpolation */
@@ -2768,11 +3236,32 @@ GL_APICALL GLboolean GL_APIENTRY glIsEnablediNV (GLenum target, GLuint index);
#define GL_NV_viewport_array2 1
#endif /* GL_NV_viewport_array2 */
+#ifndef GL_NV_viewport_swizzle
+#define GL_NV_viewport_swizzle 1
+#define GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV 0x9350
+#define GL_VIEWPORT_SWIZZLE_NEGATIVE_X_NV 0x9351
+#define GL_VIEWPORT_SWIZZLE_POSITIVE_Y_NV 0x9352
+#define GL_VIEWPORT_SWIZZLE_NEGATIVE_Y_NV 0x9353
+#define GL_VIEWPORT_SWIZZLE_POSITIVE_Z_NV 0x9354
+#define GL_VIEWPORT_SWIZZLE_NEGATIVE_Z_NV 0x9355
+#define GL_VIEWPORT_SWIZZLE_POSITIVE_W_NV 0x9356
+#define GL_VIEWPORT_SWIZZLE_NEGATIVE_W_NV 0x9357
+#define GL_VIEWPORT_SWIZZLE_X_NV 0x9358
+#define GL_VIEWPORT_SWIZZLE_Y_NV 0x9359
+#define GL_VIEWPORT_SWIZZLE_Z_NV 0x935A
+#define GL_VIEWPORT_SWIZZLE_W_NV 0x935B
+typedef void (GL_APIENTRYP PFNGLVIEWPORTSWIZZLENVPROC) (GLuint index, GLenum swizzlex, GLenum swizzley, GLenum swizzlez, GLenum swizzlew);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glViewportSwizzleNV (GLuint index, GLenum swizzlex, GLenum swizzley, GLenum swizzlez, GLenum swizzlew);
+#endif
+#endif /* GL_NV_viewport_swizzle */
+
#ifndef GL_OVR_multiview
#define GL_OVR_multiview 1
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR 0x9630
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR 0x9632
#define GL_MAX_VIEWS_OVR 0x9631
+#define GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR 0x9633
typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
#ifdef GL_GLEXT_PROTOTYPES
GL_APICALL void GL_APIENTRY glFramebufferTextureMultiviewOVR (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
@@ -2783,6 +3272,14 @@ GL_APICALL void GL_APIENTRY glFramebufferTextureMultiviewOVR (GLenum target, GLe
#define GL_OVR_multiview2 1
#endif /* GL_OVR_multiview2 */
+#ifndef GL_OVR_multiview_multisampled_render_to_texture
+#define GL_OVR_multiview_multisampled_render_to_texture 1
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei samples, GLint baseViewIndex, GLsizei numViews);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferTextureMultisampleMultiviewOVR (GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei samples, GLint baseViewIndex, GLsizei numViews);
+#endif
+#endif /* GL_OVR_multiview_multisampled_render_to_texture */
+
#ifndef GL_QCOM_alpha_test
#define GL_QCOM_alpha_test 1
#define GL_ALPHA_TEST_QCOM 0x0BC0
@@ -2863,11 +3360,32 @@ GL_APICALL void GL_APIENTRY glExtGetProgramBinarySourceQCOM (GLuint program, GLe
#endif
#endif /* GL_QCOM_extended_get2 */
+#ifndef GL_QCOM_framebuffer_foveated
+#define GL_QCOM_framebuffer_foveated 1
+#define GL_FOVEATION_ENABLE_BIT_QCOM 0x00000001
+#define GL_FOVEATION_SCALED_BIN_METHOD_BIT_QCOM 0x00000002
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERFOVEATIONCONFIGQCOMPROC) (GLuint framebuffer, GLuint numLayers, GLuint focalPointsPerLayer, GLuint requestedFeatures, GLuint *providedFeatures);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERFOVEATIONPARAMETERSQCOMPROC) (GLuint framebuffer, GLuint layer, GLuint focalPoint, GLfloat focalX, GLfloat focalY, GLfloat gainX, GLfloat gainY, GLfloat foveaArea);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferFoveationConfigQCOM (GLuint framebuffer, GLuint numLayers, GLuint focalPointsPerLayer, GLuint requestedFeatures, GLuint *providedFeatures);
+GL_APICALL void GL_APIENTRY glFramebufferFoveationParametersQCOM (GLuint framebuffer, GLuint layer, GLuint focalPoint, GLfloat focalX, GLfloat focalY, GLfloat gainX, GLfloat gainY, GLfloat foveaArea);
+#endif
+#endif /* GL_QCOM_framebuffer_foveated */
+
#ifndef GL_QCOM_perfmon_global_mode
#define GL_QCOM_perfmon_global_mode 1
#define GL_PERFMON_GLOBAL_MODE_QCOM 0x8FA0
#endif /* GL_QCOM_perfmon_global_mode */
+#ifndef GL_QCOM_shader_framebuffer_fetch_noncoherent
+#define GL_QCOM_shader_framebuffer_fetch_noncoherent 1
+#define GL_FRAMEBUFFER_FETCH_NONCOHERENT_QCOM 0x96A2
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERFETCHBARRIERQCOMPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferFetchBarrierQCOM (void);
+#endif
+#endif /* GL_QCOM_shader_framebuffer_fetch_noncoherent */
+
#ifndef GL_QCOM_tiled_rendering
#define GL_QCOM_tiled_rendering 1
#define GL_COLOR_BUFFER_BIT0_QCOM 0x00000001
@@ -2920,20 +3438,8 @@ GL_APICALL void GL_APIENTRY glEndTilingQCOM (GLbitfield preserveMask);
#define GL_SHADER_BINARY_VIV 0x8FC4
#endif /* GL_VIV_shader_binary */
-#ifndef GL_ANGLE_lossy_etc_decode
-#define GL_ANGLE_lossy_etc_decode 1
-#define GL_ETC1_RGB8_LOSSY_DECODE_ANGLE 0x9690
-#define GL_COMPRESSED_R11_LOSSY_DECODE_EAC_ANGLE 0x9691
-#define GL_COMPRESSED_SIGNED_R11_LOSSY_DECODE_EAC_ANGLE 0x9692
-#define GL_COMPRESSED_RG11_LOSSY_DECODE_EAC_ANGLE 0x9693
-#define GL_COMPRESSED_SIGNED_RG11_LOSSY_DECODE_EAC_ANGLE 0x9694
-#define GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE 0x9695
-#define GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE 0x9696
-#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE 0x9697
-#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE 0x9698
-#define GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE 0x9699
-#define GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE 0x969A
-#endif /* GL_ANGLE_lossy_etc_decode */
+/* ANGLE GLES2 extensions */
+#include "gl2ext_angle.h"
#ifdef __cplusplus
}
diff --git a/src/3rdparty/angle/include/GLES2/gl2ext_angle.h b/src/3rdparty/angle/include/GLES2/gl2ext_angle.h
new file mode 100644
index 0000000000..fc5a4bf35d
--- /dev/null
+++ b/src/3rdparty/angle/include/GLES2/gl2ext_angle.h
@@ -0,0 +1,551 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// gl2ext_angle.h: ANGLE modifications to the gl2ext.h header file.
+// Currently we don't include this file directly, we patch gl2ext.h
+// to include it implicitly so it is visible throughout our code.
+
+#ifndef INCLUDE_GLES2_GL2EXT_ANGLE_H_
+#define INCLUDE_GLES2_GL2EXT_ANGLE_H_
+
+// clang-format off
+
+#ifndef GL_ANGLE_client_arrays
+#define GL_ANGLE_client_arrays 1
+#define GL_CLIENT_ARRAYS_ANGLE 0x93AA
+#endif /* GL_ANGLE_client_arrays */
+
+#ifndef GL_ANGLE_request_extension
+#define GL_ANGLE_request_extension 1
+#define GL_REQUESTABLE_EXTENSIONS_ANGLE 0x93A8
+#define GL_NUM_REQUESTABLE_EXTENSIONS_ANGLE 0x93A8
+typedef void (GL_APIENTRYP PFNGLREQUESTEXTENSIONANGLEPROC) (const GLchar *name);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRequestExtensionANGLE (const GLchar *name);
+#endif
+#endif /* GL_ANGLE_webgl_compatibility */
+
+#ifndef GL_ANGLE_robust_resource_initialization
+#define GL_ANGLE_robust_resource_initialization 1
+#define GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE 0x93AB
+#endif /* GL_ANGLE_robust_resource_initialization */
+
+#ifndef GL_CHROMIUM_framebuffer_mixed_samples
+#define GL_CHROMIUM_frambuffer_mixed_samples 1
+#define GL_COVERAGE_MODULATION_CHROMIUM 0x9332
+typedef void (GL_APIENTRYP PFNGLCOVERAGEMODULATIONCHROMIUMPROC) (GLenum components);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCoverageModulationCHROMIUM(GLenum components);
+#endif
+#endif /* GL_CHROMIUM_framebuffer_mixed_samples */
+
+#ifndef GL_CHROMIUM_bind_generates_resource
+#define GL_CHROMIUM_bind_generates_resource 1
+#define GL_BIND_GENERATES_RESOURCE_CHROMIUM 0x9244
+#endif /* GL_CHROMIUM_bind_generates_resource */
+
+// needed by NV_path_rendering (and thus CHROMIUM_path_rendering)
+// but CHROMIUM_path_rendering only needs MatrixLoadfEXT, MatrixLoadIdentityEXT
+#ifndef GL_EXT_direct_state_access
+#define GL_EXT_direct_state_access 1
+typedef void(GL_APIENTRYP PFNGLMATRIXLOADFEXTPROC)(GLenum matrixMode, const GLfloat *m);
+typedef void(GL_APIENTRYP PFNGLMATRIXLOADIDENTITYEXTPROC)(GLenum matrixMode);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glMatrixLoadfEXT(GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixLoadIdentityEXT(GLenum matrixMode);
+#endif
+#endif /* GL_EXT_direct_state_access */
+
+#ifndef GL_CHROMIUM_path_rendering
+#define GL_CHROMIUM_path_rendering 1
+#define GL_PATH_MODELVIEW_CHROMIUM 0x1700
+#define GL_PATH_PROJECTION_CHROMIUM 0x1701
+#define GL_CLOSE_PATH_CHROMIUM 0x00
+#define GL_MOVE_TO_CHROMIUM 0x02
+#define GL_LINE_TO_CHROMIUM 0x04
+#define GL_QUADRATIC_CURVE_TO_CHROMIUM 0x0A
+#define GL_CUBIC_CURVE_TO_CHROMIUM 0x0C
+#define GL_CONIC_CURVE_TO_CHROMIUM 0x1A
+#define GL_PATH_MODELVIEW_MATRIX_CHROMIUM 0x0BA6
+#define GL_PATH_PROJECTION_MATRIX_CHROMIUM 0x0BA7
+#define GL_PATH_STROKE_WIDTH_CHROMIUM 0x9075
+#define GL_PATH_END_CAPS_CHROMIUM 0x9076
+#define GL_PATH_JOIN_STYLE_CHROMIUM 0x9079
+#define GL_PATH_MITER_LIMIT_CHROMIUM 0x907a
+#define GL_PATH_STROKE_BOUND_CHROMIUM 0x9086
+#define GL_FLAT_CHROMIUM 0x1D00
+#define GL_SQUARE_CHROMIUM 0x90a3
+#define GL_ROUND_CHROMIUM 0x90a4
+#define GL_BEVEL_CHROMIUM 0x90A6
+#define GL_MITER_REVERT_CHROMIUM 0x90A7
+#define GL_COUNT_UP_CHROMIUM 0x9088
+#define GL_COUNT_DOWN_CHROMIUM 0x9089
+#define GL_CONVEX_HULL_CHROMIUM 0x908B
+#define GL_BOUNDING_BOX_CHROMIUM 0x908D
+#define GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM 0x909C
+#define GL_EYE_LINEAR_CHROMIUM 0x2400
+#define GL_OBJECT_LINEAR_CHROMIUM 0x2401
+#define GL_CONSTANT_CHROMIUM 0x8576
+#define GL_TRANSLATE_X_CHROMIUM 0x908E
+#define GL_TRANSLATE_Y_CHROMIUM 0x908F
+#define GL_TRANSLATE_2D_CHROMIUM 0x9090
+#define GL_TRANSLATE_3D_CHROMIUM 0x9091
+#define GL_AFFINE_2D_CHROMIUM 0x9092
+#define GL_AFFINE_3D_CHROMIUM 0x9094
+#define GL_TRANSPOSE_AFFINE_2D_CHROMIUM 0x9096
+#define GL_TRANSPOSE_AFFINE_3D_CHROMIUM 0x9098
+typedef void(GL_APIENTRYP PFNGLMATRIXLOADFCHROMIUMPROC)(GLenum matrixMode, const GLfloat *m);
+typedef void(GL_APIENTRYP PFNGLMATRIXLOADIDENTITYCHROMIUMPROC)(GLenum matrixMode);
+typedef GLuint(GL_APIENTRYP PFNGLGENPATHSCHROMIUMPROC)(GLsizei range);
+typedef void(GL_APIENTRYP PFNGLDELETEPATHSCHROMIUMPROC)(GLuint path, GLsizei range);
+typedef GLboolean(GL_APIENTRYP PFNGLISPATHCHROMIUMPROC)(GLuint path);
+typedef void(GL_APIENTRYP PFNGLPATHCOMMANDSCHROMIUMPROC)(GLuint path,
+ GLsizei numCommands,
+ const GLubyte *commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const void *coords);
+typedef void(GL_APIENTRYP PFNGLPATHPARAMETERICHROMIUMPROC)(GLuint path, GLenum pname, GLint value);
+typedef void(GL_APIENTRYP PFNGLPATHPARAMETERFCHROMIUMPROC)(GLuint path,
+ GLenum pname,
+ GLfloat value);
+typedef void(GL_APIENTRYP PFNGLGETPATHPARAMETERIVCHROMIUMPROC)(GLuint path,
+ GLenum pname,
+ GLint *value);
+typedef void(GL_APIENTRYP PFNGLGETPATHPARAMETERFVCHROMIUMPROC)(GLuint path,
+ GLenum pname,
+ GLfloat *value);
+typedef void(GL_APIENTRYP PFNGLPATHSTENCILFUNCCHROMIUMPROC)(GLenum func, GLint ref, GLuint mask);
+typedef void(GL_APIENTRYP PFNGLSTENCILFILLPATHCHROMIUMPROC)(GLuint path,
+ GLenum fillMode,
+ GLuint mask);
+typedef void(GL_APIENTRYP PFNGLSTENCILSTROKEPATHCHROMIUMPROC)(GLuint path,
+ GLint reference,
+ GLuint mask);
+typedef void(GL_APIENTRYP PFNGLCOVERFILLPATHCHROMIUMPROC)(GLuint path, GLenum coverMode);
+typedef void(GL_APIENTRYP PFNGLCOVERSTROKEPATHCHROMIUMPROC)(GLuint path, GLenum coverMode);
+typedef void(GL_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHCHROMIUMPROC)(GLuint path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode);
+typedef void(GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHCHROMIUMPROC)(GLuint path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode);
+typedef void(GL_APIENTRYP PFNGLCOVERFILLPATHINSTANCEDCHROMIUMPROC)(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+typedef void(GL_APIENTRYP PFNGLCOVERSTROKEPATHINSTANCEDCHROMIUMPROC)(
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+typedef void(GL_APIENTRYP PFNGLSTENCILFILLPATHINSTANCEDCHROMIUMPROC)(
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+typedef void(GL_APIENTRYP PFNGLSTENCILSTROKEPATHINSTANCEDCHROMIUMPROC)(
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+typedef void(GL_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDCHROMIUMPROC)(
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+typedef void(GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDCHROMIUMPROC)(
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+
+typedef void(GL_APIENTRY PFNGLBINDFRAGMENTINPUTLOCATIONCHROMIUMPROC)(GLuint program,
+ GLint location,
+ const GLchar *name);
+typedef void(GL_APIENTRYP PFNGLPROGRAMPATHFRAGMENTINPUTGENCHROMIUMPROC)(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glMatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixLoadIdentityCHROMIUM(GLenum matrixMode);
+GL_APICALL GLuint GL_APIENTRY glGenPathsCHROMIUM(GLsizei range);
+GL_APICALL void GL_APIENTRY glDeletePathsCHROMIUM(GLuint path, GLsizei range);
+GL_APICALL GLboolean GL_APIENTRY glIsPathCHROMIUM(GLuint path);
+GL_APICALL void GL_APIENTRY glPathCommandsCHROMIUM(GLuint path,
+ GLsizei numCommands,
+ const GLubyte *commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const void *coords);
+GL_APICALL void GL_APIENTRY glPathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glPathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value);
+GL_APICALL void GL_APIENTRY glGetPathParameterivCHROMIUM(GLuint path, GLenum pname, GLint *value);
+GL_APICALL void GL_APIENTRY glGetPathParameterfvCHROMIUM(GLuint path, GLenum pname, GLfloat *value);
+GL_APICALL void GL_APIENTRY glPathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilFillPathCHROMIUM(GLuint path, GLenum fillMode, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilStrokePathCHROMIUM(GLuint path, GLint reference, GLuint mask);
+GL_APICALL void GL_APIENTRY glCoverFillPathCHROMIUM(GLuint path, GLenum coverMode);
+GL_APICALL void GL_APIENTRY glCoverStrokePathCHROMIUM(GLuint path, GLenum coverMode);
+GL_APICALL void GL_APIENTRY glStencilThenCoverFillPathCHROMIUM(GLuint path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode);
+GL_APICALL void GL_APIENTRY glStencilThenCoverStrokePathCHROMIUM(GLuint path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode);
+GL_APICALL void GL_APIENTRY glCoverFillPathInstancedCHROMIUM(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glCoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glStencilFillPathInstancedCHROMIUM(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glStencilStrokePathInstancedCHROMIUM(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY
+glStencilThenCoverFillPathInstancedCHROMIUM(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+
+GL_APICALL void GL_APIENTRY
+glStencilThenCoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+
+GL_APICALL void GL_APIENTRY glBindFragmentInputLocationCHROMIUM(GLuint program,
+ GLint location,
+ const GLchar *name);
+GL_APICALL void GL_APIENTRY glProgramPathFragmentInputGenCHROMIUM(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs);
+
+#endif
+#endif /* GL_CHROMIUM_path_rendering */
+
+#ifndef GL_CHROMIUM_copy_texture
+#define GL_CHROMIUM_copy_texture 1
+typedef void(GL_APIENTRYP PFNGLCOPYTEXTURECHROMIUMPROC)(GLuint sourceId,
+ GLint sourceLevel,
+ GLenum destTarget,
+ GLuint destId,
+ GLint destLevel,
+ GLint internalFormat,
+ GLenum destType,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha);
+typedef void(GL_APIENTRYP PFNGLCOPYSUBTEXTURECHROMIUMPROC)(GLuint sourceId,
+ GLint sourceLevel,
+ GLenum destTarget,
+ GLuint destId,
+ GLint destLevel,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCopyTextureCHROMIUM(GLuint sourceId,
+ GLint sourceLevel,
+ GLenum destTarget,
+ GLuint destId,
+ GLint destLevel,
+ GLint internalFormat,
+ GLenum destType,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha);
+GL_APICALL void GL_APIENTRY glCopySubTextureCHROMIUM(GLuint sourceId,
+ GLint sourceLevel,
+ GLenum destTarget,
+ GLuint destId,
+ GLint destLevel,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha);
+#endif
+#endif /* GL_CHROMIUM_copy_texture */
+
+#ifndef GL_CHROMIUM_compressed_copy_texture
+#define GL_CHROMIUM_compressed_copy_texture 1
+typedef void(GL_APIENTRYP PFNGLCOMPRESSEDCOPYTEXTURECHROMIUMPROC)(GLuint sourceId, GLuint destId);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCompressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId);
+#endif
+#endif /* GL_CHROMIUM_compressed_copy_texture */
+
+#ifndef GL_CHROMIUM_sync_query
+#define GL_CHROMIUM_sync_query 1
+#define GL_COMMANDS_COMPLETED_CHROMIUM 0x84F7
+#endif /* GL_CHROMIUM_sync_query */
+
+#ifndef GL_EXT_texture_compression_s3tc_srgb
+#define GL_EXT_texture_compression_s3tc_srgb 1
+#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
+#endif /* GL_EXT_texture_compression_s3tc_srgb */
+
+#ifndef GL_ANGLE_lossy_etc_decode
+#define GL_ANGLE_lossy_etc_decode 1
+#define GL_ETC1_RGB8_LOSSY_DECODE_ANGLE 0x9690
+#define GL_COMPRESSED_R11_LOSSY_DECODE_EAC_ANGLE 0x9691
+#define GL_COMPRESSED_SIGNED_R11_LOSSY_DECODE_EAC_ANGLE 0x9692
+#define GL_COMPRESSED_RG11_LOSSY_DECODE_EAC_ANGLE 0x9693
+#define GL_COMPRESSED_SIGNED_RG11_LOSSY_DECODE_EAC_ANGLE 0x9694
+#define GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE 0x9695
+#define GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE 0x9696
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE 0x9697
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE 0x9698
+#define GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE 0x9699
+#define GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE 0x969A
+#endif /* GL_ANGLE_lossy_etc_decode */
+
+#ifndef GL_ANGLE_robust_client_memory
+#define GL_ANGLE_robust_client_memory 1
+typedef void (GL_APIENTRYP PFNGLGETBOOLEANVROBUSTANGLE) (GLenum pname, GLsizei bufSize, GLsizei *length, GLboolean *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETFLOATVROBUSTANGLE) (GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *data);
+typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVROBUSTANGLE) (GLenum target, GLenum attachment, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERVROBUSTANGLE) (GLenum pname, GLsizei bufSize, GLsizei *length, GLint *data);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMIVROBUSTANGLE) (GLuint program, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERIVROBUSTANGLE) (GLuint shader, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERFVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMFVROBUSTANGLE) (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMIVROBUSTANGLE) (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBFVROBUSTANGLE) (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIVROBUSTANGLE) (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVROBUSTANGLE) (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, void **pointer);
+typedef void (GL_APIENTRYP PFNGLREADPIXELSROBUSTANGLE) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLsizei *length, GLsizei *columns, GLsizei *rows, void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE2DROBUSTANGLE) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLsizei bufSize, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, const GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE2DROBUSTANGLE) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DROBUSTANGLE) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, GLsizei bufSize, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DROBUSTANGLE) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DROBUSTANGLE) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, GLsizei bufSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DROBUSTANGLE) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, GLsizei bufSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DROBUSTANGLE) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, GLsizei bufSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DROBUSTANGLE) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, GLsizei bufSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLGETQUERYIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVROBUSTANGLE) (GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, void **params);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VROBUSTANGLE) (GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, GLint *data);
+typedef void (GL_APIENTRYP PFNGETINTERNALFORMATIVROBUSTANGLE) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIIVROBUSTANGLE) (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIUIVROBUSTANGLE) (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMUIVROBUSTANGLE) (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVROBUSTANGLE) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64VROBUSTANGLE) (GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *data);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64I_VROBUSTANGLE) (GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, GLint64 *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERI64VROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *params);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIVROBUSTANGLE) (GLuint sampler, GLenum pname, GLsizei bufSize, const GLint *param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFVROBUSTANGLE) (GLuint sampler, GLenum pname, GLsizei bufSize, const GLfloat *param);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIVROBUSTANGLE) (GLuint sampler, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERFVROBUSTANGLE) (GLuint sampler, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMINTERFACEIVROBUSTANGLE) (GLuint program, GLenum programInterface, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETBOOLEANI_VROBUSTANGLE) (GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, GLboolean *data);
+typedef void (GL_APIENTRYP PFNGLGETMULTISAMPLEFVROBUSTANGLE) (GLenum pname, GLuint index, GLsizei bufSize, GLsizei *length, GLfloat *val);
+typedef void (GL_APIENTRYP PFNGLGETTEXLEVELPARAMETERIVROBUSTANGLE) (GLenum target, GLint level, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXLEVELPARAMETERFVROBUSTANGLE) (GLenum target, GLint level, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETPOINTERVROBUSTANGLEROBUSTANGLE) (GLenum pname, GLsizei bufSize, GLsizei *length, void **params);
+typedef void (GL_APIENTRYP PFNGLREADNPIXELSROBUSTANGLE) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLsizei *length, GLsizei *columns, GLsizei *rows, void *data);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVROBUSTANGLE) (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVROBUSTANGLE) (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMUIVROBUSTANGLE) (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIUIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, const GLuint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIUIVROBUSTANGLE) (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIIVROBUSTANGLE) (GLuint sampler, GLenum pname, GLsizei bufSize, const GLint *param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIUIVROBUSTANGLE) (GLuint sampler, GLenum pname, GLsizei bufSize, const GLuint *param);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIIVROBUSTANGLE) (GLuint sampler, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVROBUSTANGLE) (GLuint sampler, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTIVROBUSTANGLE)(GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTI64VROBUSTANGLE)(GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUI64VROBUSTANGLE)(GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint64 *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetBooleanvRobustANGLE (GLenum pname, GLsizei bufSize, GLsizei *length, GLboolean *data);
+GL_APICALL void GL_APIENTRY glGetBufferParameterivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetFloatvRobustANGLE (GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *data);
+GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameterivRobustANGLE (GLenum target, GLenum attachment, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetIntegervRobustANGLE (GLenum pname, GLsizei bufSize, GLsizei *length, GLint *data);
+GL_APICALL void GL_APIENTRY glGetProgramivRobustANGLE (GLuint program, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetRenderbufferParameterivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetShaderivRobustANGLE (GLuint shader, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterfvRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetUniformfvRobustANGLE (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetUniformivRobustANGLE (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribfvRobustANGLE (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribivRobustANGLE (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribPointervRobustANGLE (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, void **pointer);
+GL_APICALL void GL_APIENTRY glReadPixelsRobustANGLE (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLsizei *length, GLsizei *columns, GLsizei *rows, void *pixels);
+GL_APICALL void GL_APIENTRY glTexImage2DRobustANGLE (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLsizei bufSize, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexParameterfvRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, const GLfloat *params);
+GL_APICALL void GL_APIENTRY glTexParameterivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, const GLint *params);
+GL_APICALL void GL_APIENTRY glTexSubImage2DRobustANGLE (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexImage3DRobustANGLE (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, GLsizei bufSize, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexSubImage3DRobustANGLE (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, const void *pixels);
+GL_APICALL void GL_APIENTRY glCompressedTexImage2DRobustANGLE(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, GLsizei bufSize, const void *data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage2DRobustANGLE(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, GLsizei bufSize, const void *data);
+GL_APICALL void GL_APIENTRY glCompressedTexImage3DRobustANGLE(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, GLsizei bufSize, const void *data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage3DRobustANGLE(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, GLsizei bufSize, const void *data);
+GL_APICALL void GL_APIENTRY glGetQueryivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectuivRobustANGLE (GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint *params);
+GL_APICALL void GL_APIENTRY glGetBufferPointervRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, void **params);
+GL_APICALL void GL_APIENTRY glGetIntegeri_vRobustANGLE (GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, GLint *data);
+GL_APICALL void GL_APIENTRY glGetInternalformativRobustANGLE (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribIivRobustANGLE (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribIuivRobustANGLE (GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint *params);
+GL_APICALL void GL_APIENTRY glGetUniformuivRobustANGLE (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLuint *params);
+GL_APICALL void GL_APIENTRY glGetActiveUniformBlockivRobustANGLE (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetInteger64vRobustANGLE (GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *data);
+GL_APICALL void GL_APIENTRY glGetInteger64i_vRobustANGLE (GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, GLint64 *data);
+GL_APICALL void GL_APIENTRY glGetBufferParameteri64vRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *params);
+GL_APICALL void GL_APIENTRY glSamplerParameterivRobustANGLE (GLuint sampler, GLenum pname, GLsizei bufSize, const GLint *param);
+GL_APICALL void GL_APIENTRY glSamplerParameterfvRobustANGLE (GLuint sampler, GLenum pname, GLsizei bufSize, const GLfloat *param);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterivRobustANGLE (GLuint sampler, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterfvRobustANGLE (GLuint sampler, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetFramebufferParameterivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetProgramInterfaceivRobustANGLE (GLuint program, GLenum programInterface, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetBooleani_vRobustANGLE (GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, GLboolean *data);
+GL_APICALL void GL_APIENTRY glGetMultisamplefvRobustANGLE (GLenum pname, GLuint index, GLsizei bufSize, GLsizei *length, GLfloat *val);
+GL_APICALL void GL_APIENTRY glGetTexLevelParameterivRobustANGLE (GLenum target, GLint level, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetTexLevelParameterfvRobustANGLE (GLenum target, GLint level, GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetPointervRobustANGLERobustANGLE (GLenum pname, GLsizei bufSize, GLsizei *length, void **params);
+GL_APICALL void GL_APIENTRY glReadnPixelsRobustANGLE (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLsizei *length, GLsizei *columns, GLsizei *rows, void *data);
+GL_APICALL void GL_APIENTRY glGetnUniformfvRobustANGLE (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetnUniformivRobustANGLE (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetnUniformuivRobustANGLE (GLuint program, GLint location, GLsizei bufSize, GLsizei *length, GLuint *params);
+GL_APICALL void GL_APIENTRY glTexParameterIivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, const GLint *params);
+GL_APICALL void GL_APIENTRY glTexParameterIuivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, const GLuint *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterIivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterIuivRobustANGLE (GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint *params);
+GL_APICALL void GL_APIENTRY glSamplerParameterIivRobustANGLE (GLuint sampler, GLenum pname, GLsizei bufSize, const GLint *param);
+GL_APICALL void GL_APIENTRY glSamplerParameterIuivRobustANGLE (GLuint sampler, GLenum pname, GLsizei bufSize, const GLuint *param);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterIivRobustANGLE (GLuint sampler, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterIuivRobustANGLE (GLuint sampler, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectivRobustANGLE(GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjecti64vRobustANGLE(GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectui64vRobustANGLE(GLuint id, GLenum pname, GLsizei bufSize, GLsizei *length, GLuint64 *params);
+#endif
+#endif /* GL_ANGLE_robust_client_memory */
+
+#ifndef GL_ANGLE_program_cache_control
+#define GL_ANGLE_program_cache_control 1
+#define GL_PROGRAM_CACHE_ENABLED_ANGLE 0x93AC
+#endif /* GL_ANGLE_program_cache_control */
+
+#ifndef GL_ANGLE_multiview
+#define GL_ANGLE_multiview 1
+// The next four enums coincide with the enums introduced by the GL_OVR_multiview extension and use the values reserved by that extension.
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE 0x9630
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE 0x9632
+#define GL_MAX_VIEWS_ANGLE 0x9631
+#define GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE 0x9633
+// The next four enums are reserved specifically for ANGLE.
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE 0x969B
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE 0x969C
+#define GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE 0x969D
+#define GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE 0x969E
+typedef void(GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTIVIEWLAYEREDANGLE)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
+typedef void(GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTIVIEWSIDEBYSIDEANGLE)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei numViews, const GLint *viewportOffsets);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferTextureMultiviewLayeredANGLE(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
+GL_APICALL void GL_APIENTRY glFramebufferTextureMultiviewSideBySideANGLE(GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei numViews, const GLint *viewportOffsets);
+#endif
+#endif /* GL_ANGLE_multiview */
+
+#ifndef GL_ANGLE_texture_rectangle
+#define GL_ANGLE_texture_rectangle 1
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ANGLE 0x84F8
+#define GL_TEXTURE_RECTANGLE_ANGLE 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE_ANGLE 0x84F6
+#define GL_SAMPLER_2D_RECT_ANGLE 0x8B63
+#endif /* GL_ANGLE_texture_rectangle */
+
+// clang-format on
+
+#endif // INCLUDE_GLES2_GL2EXT_ANGLE_H_
diff --git a/src/3rdparty/angle/include/GLES3/gl3ext.h b/src/3rdparty/angle/include/GLES3/gl3ext.h
deleted file mode 100644
index 4d4ea96c4d..0000000000
--- a/src/3rdparty/angle/include/GLES3/gl3ext.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef __gl3ext_h_
-#define __gl3ext_h_
-
-/* $Revision: 17809 $ on $Date:: 2012-05-14 08:03:36 -0700 #$ */
-
-/*
- * This document is licensed under the SGI Free Software B License Version
- * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
- */
-
-/* OpenGL ES 3 Extensions
- *
- * After an OES extension's interactions with OpenGl ES 3.0 have been documented,
- * its tokens and function definitions should be added to this file in a manner
- * that does not conflict with gl2ext.h or gl3.h.
- *
- * Tokens and function definitions for extensions that have become standard
- * features in OpenGL ES 3.0 will not be added to this file.
- *
- * Applications using OpenGL-ES-2-only extensions should include gl2ext.h
- */
-
-#endif /* __gl3ext_h_ */
-
diff --git a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h
index d02723e760..1468bb1464 100644
--- a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h
+++ b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h
@@ -6,27 +6,11 @@
#ifndef GLSLANG_SHADERLANG_H_
#define GLSLANG_SHADERLANG_H_
-#if defined(COMPONENT_BUILD) && !defined(ANGLE_TRANSLATOR_STATIC)
-#if defined(_WIN32) || defined(_WIN64)
-
-#if defined(ANGLE_TRANSLATOR_IMPLEMENTATION)
-#define COMPILER_EXPORT __declspec(dllexport)
-#else
-#define COMPILER_EXPORT __declspec(dllimport)
-#endif // defined(ANGLE_TRANSLATOR_IMPLEMENTATION)
-
-#else // defined(_WIN32) || defined(_WIN64)
-#define COMPILER_EXPORT __attribute__((visibility("default")))
-#endif
-
-#else // defined(COMPONENT_BUILD) && !defined(ANGLE_TRANSLATOR_STATIC)
-#define COMPILER_EXPORT
-#endif
-
#include <stddef.h>
#include "KHR/khrplatform.h"
+#include <array>
#include <map>
#include <string>
#include <vector>
@@ -36,51 +20,26 @@
// and the shading language compiler.
//
-namespace sh
-{
-// GLenum alias
-typedef unsigned int GLenum;
-}
-
-// Must be included after GLenum proxy typedef
// Note: make sure to increment ANGLE_SH_VERSION when changing ShaderVars.h
#include "ShaderVars.h"
// Version number for shader translation API.
// It is incremented every time the API changes.
-#define ANGLE_SH_VERSION 143
-
-typedef enum {
- SH_GLES2_SPEC = 0x8B40,
- SH_WEBGL_SPEC = 0x8B41,
-
- SH_GLES3_SPEC = 0x8B86,
- SH_WEBGL2_SPEC = 0x8B87,
-
- // The CSS Shaders spec is a subset of the WebGL spec.
- //
- // In both CSS vertex and fragment shaders, ANGLE:
- // (1) Reserves the "css_" prefix.
- // (2) Renames the main function to css_main.
- // (3) Disables the gl_MaxDrawBuffers built-in.
- //
- // In CSS fragment shaders, ANGLE:
- // (1) Disables the gl_FragColor built-in.
- // (2) Disables the gl_FragData built-in.
- // (3) Enables the css_MixColor built-in.
- // (4) Enables the css_ColorMatrix built-in.
- //
- // After passing a CSS shader through ANGLE, the browser is expected to append
- // a new main function to it.
- // This new main function will call the css_main function.
- // It may also perform additional operations like varying assignment, texture
- // access, and gl_FragColor assignment in order to implement the CSS Shaders
- // blend modes.
- //
- SH_CSS_SHADERS_SPEC = 0x8B42
-} ShShaderSpec;
-
-typedef enum
+#define ANGLE_SH_VERSION 190
+
+enum ShShaderSpec
+{
+ SH_GLES2_SPEC,
+ SH_WEBGL_SPEC,
+
+ SH_GLES3_SPEC,
+ SH_WEBGL2_SPEC,
+
+ SH_GLES3_1_SPEC,
+ SH_WEBGL3_SPEC,
+};
+
+enum ShShaderOutput
{
// ESSL output only supported in some configurations.
SH_ESSL_OUTPUT = 0x8B45,
@@ -99,147 +58,224 @@ typedef enum
SH_GLSL_440_CORE_OUTPUT = 0x8B87,
SH_GLSL_450_CORE_OUTPUT = 0x8B88,
- // HLSL output only supported in some configurations.
- // Deprecated:
- SH_HLSL_OUTPUT = 0x8B48,
- SH_HLSL9_OUTPUT = 0x8B48,
- SH_HLSL11_OUTPUT = 0x8B49,
-
// Prefer using these to specify HLSL output type:
SH_HLSL_3_0_OUTPUT = 0x8B48, // D3D 9
SH_HLSL_4_1_OUTPUT = 0x8B49, // D3D 11
- SH_HLSL_4_0_FL9_3_OUTPUT = 0x8B4A // D3D 11 feature level 9_3
-} ShShaderOutput;
+ SH_HLSL_4_0_FL9_3_OUTPUT = 0x8B4A, // D3D 11 feature level 9_3
+
+ // Output specialized GLSL to be fed to glslang for Vulkan SPIR.
+ SH_GLSL_VULKAN_OUTPUT = 0x8B4B,
+};
// Compile options.
-typedef enum {
- SH_VALIDATE = 0,
- SH_VALIDATE_LOOP_INDEXING = 0x0001,
- SH_INTERMEDIATE_TREE = 0x0002,
- SH_OBJECT_CODE = 0x0004,
- SH_VARIABLES = 0x0008,
- SH_LINE_DIRECTIVES = 0x0010,
- SH_SOURCE_PATH = 0x0020,
- SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX = 0x0040,
- // If a sampler array index happens to be a loop index,
- // 1) if its type is integer, unroll the loop.
- // 2) if its type is float, fail the shader compile.
- // This is to work around a mac driver bug.
- SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX = 0x0080,
-
- // This is needed only as a workaround for certain OpenGL driver bugs.
- SH_EMULATE_BUILT_IN_FUNCTIONS = 0x0100,
-
- // This is an experimental flag to enforce restrictions that aim to prevent
- // timing attacks.
- // It generates compilation errors for shaders that could expose sensitive
- // texture information via the timing channel.
- // To use this flag, you must compile the shader under the WebGL spec
- // (using the SH_WEBGL_SPEC flag).
- SH_TIMING_RESTRICTIONS = 0x0200,
-
- // This flag prints the dependency graph that is used to enforce timing
- // restrictions on fragment shaders.
- // This flag only has an effect if all of the following are true:
- // - The shader spec is SH_WEBGL_SPEC.
- // - The compile options contain the SH_TIMING_RESTRICTIONS flag.
- // - The shader type is GL_FRAGMENT_SHADER.
- SH_DEPENDENCY_GRAPH = 0x0400,
-
- // Enforce the GLSL 1.017 Appendix A section 7 packing restrictions.
- // This flag only enforces (and can only enforce) the packing
- // restrictions for uniform variables in both vertex and fragment
- // shaders. ShCheckVariablesWithinPackingLimits() lets embedders
- // enforce the packing restrictions for varying variables during
- // program link time.
- SH_ENFORCE_PACKING_RESTRICTIONS = 0x0800,
-
- // This flag ensures all indirect (expression-based) array indexing
- // is clamped to the bounds of the array. This ensures, for example,
- // that you cannot read off the end of a uniform, whether an array
- // vec234, or mat234 type. The ShArrayIndexClampingStrategy enum,
- // specified in the ShBuiltInResources when constructing the
- // compiler, selects the strategy for the clamping implementation.
- SH_CLAMP_INDIRECT_ARRAY_BOUNDS = 0x1000,
-
- // This flag limits the complexity of an expression.
- SH_LIMIT_EXPRESSION_COMPLEXITY = 0x2000,
-
- // This flag limits the depth of the call stack.
- SH_LIMIT_CALL_STACK_DEPTH = 0x4000,
-
- // This flag initializes gl_Position to vec4(0,0,0,0) at the
- // beginning of the vertex shader's main(), and has no effect in the
- // fragment shader. It is intended as a workaround for drivers which
- // incorrectly fail to link programs if gl_Position is not written.
- SH_INIT_GL_POSITION = 0x8000,
-
- // This flag replaces
- // "a && b" with "a ? b : false",
- // "a || b" with "a ? true : b".
- // This is to work around a MacOSX driver bug that |b| is executed
- // independent of |a|'s value.
- SH_UNFOLD_SHORT_CIRCUIT = 0x10000,
-
- // This flag initializes varyings without static use in vertex shader
- // at the beginning of main(), and has no effects in the fragment shader.
- // It is intended as a workaround for drivers which incorrectly optimize
- // out such varyings and cause a link failure.
- SH_INIT_VARYINGS_WITHOUT_STATIC_USE = 0x20000,
-
- // This flag scalarizes vec/ivec/bvec/mat constructor args.
- // It is intended as a workaround for Linux/Mac driver bugs.
- SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS = 0x40000,
-
- // This flag overwrites a struct name with a unique prefix.
- // It is intended as a workaround for drivers that do not handle
- // struct scopes correctly, including all Mac drivers and Linux AMD.
- SH_REGENERATE_STRUCT_NAMES = 0x80000,
-
- // This flag makes the compiler not prune unused function early in the
- // compilation process. Pruning coupled with SH_LIMIT_CALL_STACK_DEPTH
- // helps avoid bad shaders causing stack overflows.
- SH_DONT_PRUNE_UNUSED_FUNCTIONS = 0x100000,
-
- // This flag works around a bug in NVIDIA 331 series drivers related
- // to pow(x, y) where y is a constant vector.
- SH_REMOVE_POW_WITH_CONSTANT_EXPONENT = 0x200000,
-
- // This flag works around bugs in Mac drivers related to do-while by
- // transforming them into an other construct.
- SH_REWRITE_DO_WHILE_LOOPS = 0x400000,
-} ShCompileOptions;
+// The Compile options type is defined in ShaderVars.h, to allow ANGLE to import the ShaderVars
+// header without needing the ShaderLang header. This avoids some conflicts with glslang.
+
+const ShCompileOptions SH_VALIDATE = 0;
+const ShCompileOptions SH_VALIDATE_LOOP_INDEXING = UINT64_C(1) << 0;
+const ShCompileOptions SH_INTERMEDIATE_TREE = UINT64_C(1) << 1;
+const ShCompileOptions SH_OBJECT_CODE = UINT64_C(1) << 2;
+const ShCompileOptions SH_VARIABLES = UINT64_C(1) << 3;
+const ShCompileOptions SH_LINE_DIRECTIVES = UINT64_C(1) << 4;
+const ShCompileOptions SH_SOURCE_PATH = UINT64_C(1) << 5;
+
+// This flag will keep invariant declaration for input in fragment shader for GLSL >=4.20 on AMD.
+// From GLSL >= 4.20, it's optional to add invariant for fragment input, but GPU vendors have
+// different implementations about this. Some drivers forbid invariant in fragment for GLSL>= 4.20,
+// e.g. Linux Mesa, some drivers treat that as optional, e.g. NVIDIA, some drivers require invariant
+// must match between vertex and fragment shader, e.g. AMD. The behavior on AMD is obviously wrong.
+// Remove invariant for input in fragment shader to workaround the restriction on Intel Mesa.
+// But don't remove on AMD Linux to avoid triggering the bug on AMD.
+const ShCompileOptions SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT = UINT64_C(1) << 6;
+
+// Due to spec difference between GLSL 4.1 or lower and ESSL3, some platforms (for example, Mac OSX
+// core profile) require a variable's "invariant"/"centroid" qualifiers to match between vertex and
+// fragment shader. A simple solution to allow such shaders to link is to omit the two qualifiers.
+// AMD driver in Linux requires invariant qualifier to match between vertex and fragment shaders,
+// while ESSL3 disallows invariant qualifier in fragment shader and GLSL >= 4.2 doesn't require
+// invariant qualifier to match between shaders. Remove invariant qualifier from vertex shader to
+// workaround AMD driver bug.
+// Note that the two flags take effect on ESSL3 input shaders translated to GLSL 4.1 or lower and to
+// GLSL 4.2 or newer on Linux AMD.
+// TODO(zmo): This is not a good long-term solution. Simply dropping these qualifiers may break some
+// developers' content. A more complex workaround of dynamically generating, compiling, and
+// re-linking shaders that use these qualifiers should be implemented.
+const ShCompileOptions SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3 = UINT64_C(1) << 7;
+
+// This flag works around bug in Intel Mac drivers related to abs(i) where
+// i is an integer.
+const ShCompileOptions SH_EMULATE_ABS_INT_FUNCTION = UINT64_C(1) << 8;
+
+// Enforce the GLSL 1.017 Appendix A section 7 packing restrictions.
+// This flag only enforces (and can only enforce) the packing
+// restrictions for uniform variables in both vertex and fragment
+// shaders. ShCheckVariablesWithinPackingLimits() lets embedders
+// enforce the packing restrictions for varying variables during
+// program link time.
+const ShCompileOptions SH_ENFORCE_PACKING_RESTRICTIONS = UINT64_C(1) << 9;
+
+// This flag ensures all indirect (expression-based) array indexing
+// is clamped to the bounds of the array. This ensures, for example,
+// that you cannot read off the end of a uniform, whether an array
+// vec234, or mat234 type. The ShArrayIndexClampingStrategy enum,
+// specified in the ShBuiltInResources when constructing the
+// compiler, selects the strategy for the clamping implementation.
+const ShCompileOptions SH_CLAMP_INDIRECT_ARRAY_BOUNDS = UINT64_C(1) << 10;
+
+// This flag limits the complexity of an expression.
+const ShCompileOptions SH_LIMIT_EXPRESSION_COMPLEXITY = UINT64_C(1) << 11;
+
+// This flag limits the depth of the call stack.
+const ShCompileOptions SH_LIMIT_CALL_STACK_DEPTH = UINT64_C(1) << 12;
+
+// This flag initializes gl_Position to vec4(0,0,0,0) at the
+// beginning of the vertex shader's main(), and has no effect in the
+// fragment shader. It is intended as a workaround for drivers which
+// incorrectly fail to link programs if gl_Position is not written.
+const ShCompileOptions SH_INIT_GL_POSITION = UINT64_C(1) << 13;
+
+// This flag replaces
+// "a && b" with "a ? b : false",
+// "a || b" with "a ? true : b".
+// This is to work around a MacOSX driver bug that |b| is executed
+// independent of |a|'s value.
+const ShCompileOptions SH_UNFOLD_SHORT_CIRCUIT = UINT64_C(1) << 14;
+
+// This flag initializes output variables to 0 at the beginning of main().
+// It is to avoid undefined behaviors.
+const ShCompileOptions SH_INIT_OUTPUT_VARIABLES = UINT64_C(1) << 15;
+
+// This flag scalarizes vec/ivec/bvec/mat constructor args.
+// It is intended as a workaround for Linux/Mac driver bugs.
+const ShCompileOptions SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS = UINT64_C(1) << 16;
+
+// This flag overwrites a struct name with a unique prefix.
+// It is intended as a workaround for drivers that do not handle
+// struct scopes correctly, including all Mac drivers and Linux AMD.
+const ShCompileOptions SH_REGENERATE_STRUCT_NAMES = UINT64_C(1) << 17;
+
+// This flag makes the compiler not prune unused function early in the
+// compilation process. Pruning coupled with SH_LIMIT_CALL_STACK_DEPTH
+// helps avoid bad shaders causing stack overflows.
+const ShCompileOptions SH_DONT_PRUNE_UNUSED_FUNCTIONS = UINT64_C(1) << 18;
+
+// This flag works around a bug in NVIDIA 331 series drivers related
+// to pow(x, y) where y is a constant vector.
+const ShCompileOptions SH_REMOVE_POW_WITH_CONSTANT_EXPONENT = UINT64_C(1) << 19;
+
+// This flag works around bugs in Mac drivers related to do-while by
+// transforming them into an other construct.
+const ShCompileOptions SH_REWRITE_DO_WHILE_LOOPS = UINT64_C(1) << 20;
+
+// This flag works around a bug in the HLSL compiler optimizer that folds certain
+// constant pow expressions incorrectly. Only applies to the HLSL back-end. It works
+// by expanding the integer pow expressions into a series of multiplies.
+const ShCompileOptions SH_EXPAND_SELECT_HLSL_INTEGER_POW_EXPRESSIONS = UINT64_C(1) << 21;
+
+// Flatten "#pragma STDGL invariant(all)" into the declarations of
+// varying variables and built-in GLSL variables. This compiler
+// option is enabled automatically when needed.
+const ShCompileOptions SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL = UINT64_C(1) << 22;
+
+// Some drivers do not take into account the base level of the texture in the results of the
+// HLSL GetDimensions builtin. This flag instructs the compiler to manually add the base level
+// offsetting.
+const ShCompileOptions SH_HLSL_GET_DIMENSIONS_IGNORES_BASE_LEVEL = UINT64_C(1) << 23;
+
+// This flag works around an issue in translating GLSL function texelFetchOffset on
+// INTEL drivers. It works by translating texelFetchOffset into texelFetch.
+const ShCompileOptions SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH = UINT64_C(1) << 24;
+
+// This flag works around condition bug of for and while loops in Intel Mac OSX drivers.
+// Condition calculation is not correct. Rewrite it from "CONDITION" to "CONDITION && true".
+const ShCompileOptions SH_ADD_AND_TRUE_TO_LOOP_CONDITION = UINT64_C(1) << 25;
+
+// This flag works around a bug in evaluating unary minus operator on integer on some INTEL
+// drivers. It works by translating -(int) into ~(int) + 1.
+const ShCompileOptions SH_REWRITE_INTEGER_UNARY_MINUS_OPERATOR = UINT64_C(1) << 26;
+
+// This flag works around a bug in evaluating isnan() on some INTEL D3D and Mac OSX drivers.
+// It works by using an expression to emulate this function.
+const ShCompileOptions SH_EMULATE_ISNAN_FLOAT_FUNCTION = UINT64_C(1) << 27;
+
+// This flag will use all uniforms of unused std140 and shared uniform blocks at the
+// beginning of the vertex/fragment shader's main(). It is intended as a workaround for Mac
+// drivers with shader version 4.10. In those drivers, they will treat unused
+// std140 and shared uniform blocks' members as inactive. However, WebGL2.0 based on
+// OpenGL ES3.0.4 requires all members of a named uniform block declared with a shared or std140
+// layout qualifier to be considered active. The uniform block itself is also considered active.
+const ShCompileOptions SH_USE_UNUSED_STANDARD_SHARED_BLOCKS = UINT64_C(1) << 28;
+
+// This flag works around a bug in unary minus operator on float numbers on Intel
+// Mac OSX 10.11 drivers. It works by translating -float into 0.0 - float.
+const ShCompileOptions SH_REWRITE_FLOAT_UNARY_MINUS_OPERATOR = UINT64_C(1) << 29;
+
+// This flag works around a bug in evaluating atan(y, x) on some NVIDIA OpenGL drivers.
+// It works by using an expression to emulate this function.
+const ShCompileOptions SH_EMULATE_ATAN2_FLOAT_FUNCTION = UINT64_C(1) << 30;
+
+// Set to 1 to translate gl_ViewID_OVR to an uniform so that the extension can be emulated.
+// "uniform highp uint ViewID_OVR".
+const ShCompileOptions SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM = UINT64_C(1) << 31;
+
+// Set to initialize uninitialized local and global temporary variables. Should only be used with
+// GLSL output. In HLSL output variables are initialized regardless of if this flag is set.
+const ShCompileOptions SH_INITIALIZE_UNINITIALIZED_LOCALS = UINT64_C(1) << 32;
+
+// The flag modifies the shader in the following way:
+// Every occurrence of gl_InstanceID is replaced by the global temporary variable InstanceID.
+// Every occurrence of gl_ViewID_OVR is replaced by the varying variable ViewID_OVR.
+// At the beginning of the body of main() in a vertex shader the following initializers are added:
+// ViewID_OVR = uint(gl_InstanceID) % num_views;
+// InstanceID = gl_InstanceID / num_views;
+// ViewID_OVR is added as a varying variable to both the vertex and fragment shaders.
+const ShCompileOptions SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW = UINT64_C(1) << 33;
+
+// With the flag enabled the GLSL/ESSL vertex shader is modified to include code for viewport
+// selection in the following way:
+// - Code to enable the extension NV_viewport_array2 is included.
+// - Code to select the viewport index or layer is inserted at the beginning of main after
+// ViewID_OVR's initialization.
+// - A declaration of the uniform multiviewBaseViewLayerIndex.
+// Note: The SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW flag also has to be enabled to have the
+// temporary variable ViewID_OVR declared and initialized.
+const ShCompileOptions SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER = UINT64_C(1) << 34;
+
+// If the flag is enabled, gl_PointSize is clamped to the maximum point size specified in
+// ShBuiltInResources in vertex shaders.
+const ShCompileOptions SH_CLAMP_POINT_SIZE = UINT64_C(1) << 35;
+
+// Turn some arithmetic operations that operate on a float vector-scalar pair into vector-vector
+// operations. This is done recursively. Some scalar binary operations inside vector constructors
+// are also turned into vector operations.
+//
+// This is targeted to work around a bug in NVIDIA OpenGL drivers that was reproducible on NVIDIA
+// driver version 387.92. It works around the most common occurrences of the bug.
+const ShCompileOptions SH_REWRITE_VECTOR_SCALAR_ARITHMETIC = UINT64_C(1) << 36;
-// Defines alternate strategies for implementing array index clamping.
-typedef enum {
- // Use the clamp intrinsic for array index clamping.
- SH_CLAMP_WITH_CLAMP_INTRINSIC = 1,
+// Don't use loops to initialize uninitialized variables. Only has an effect if some kind of
+// variable initialization is turned on.
+const ShCompileOptions SH_DONT_USE_LOOPS_TO_INITIALIZE_VARIABLES = UINT64_C(1) << 37;
- // Use a user-defined function for array index clamping.
- SH_CLAMP_WITH_USER_DEFINED_INT_CLAMP_FUNCTION
-} ShArrayIndexClampingStrategy;
+// Defines alternate strategies for implementing array index clamping.
+enum ShArrayIndexClampingStrategy
+{
+ // Use the clamp intrinsic for array index clamping.
+ SH_CLAMP_WITH_CLAMP_INTRINSIC = 1,
-//
-// Driver must call this first, once, before doing any other
-// compiler operations.
-// If the function succeeds, the return value is true, else false.
-//
-COMPILER_EXPORT bool ShInitialize();
-//
-// Driver should call this at shutdown.
-// If the function succeeds, the return value is true, else false.
-//
-COMPILER_EXPORT bool ShFinalize();
+ // Use a user-defined function for array index clamping.
+ SH_CLAMP_WITH_USER_DEFINED_INT_CLAMP_FUNCTION
+};
// The 64 bits hash function. The first parameter is the input string; the
// second parameter is the string length.
-typedef khronos_uint64_t (*ShHashFunction64)(const char*, size_t);
+using ShHashFunction64 = khronos_uint64_t (*)(const char *, size_t);
//
// Implementation dependent built-in resources (constants and extensions).
// The names for these resources has been obtained by stripping gl_/GL_.
//
-typedef struct
+struct ShBuiltInResources
{
// Constants.
int MaxVertexAttribs;
@@ -255,6 +291,8 @@ typedef struct
// Set to 1 to enable the extension, else 0.
int OES_standard_derivatives;
int OES_EGL_image_external;
+ int OES_EGL_image_external_essl3;
+ int NV_EGL_stream_consumer_external;
int ARB_texture_rectangle;
int EXT_blend_func_extended;
int EXT_draw_buffers;
@@ -264,6 +302,9 @@ typedef struct
int EXT_shader_framebuffer_fetch;
int NV_shader_framebuffer_fetch;
int ARM_shader_framebuffer_fetch;
+ int OVR_multiview;
+ int EXT_YUV_target;
+ int OES_geometry_shader;
// Set to 1 to enable replacing GL_EXT_draw_buffers #extension directives
// with GL_NV_draw_buffers in ESSL output. This flag can be used to emulate
@@ -290,6 +331,9 @@ typedef struct
// GLES SL version 100 gl_MaxDualSourceDrawBuffersEXT value for EXT_blend_func_extended.
int MaxDualSourceDrawBuffers;
+ // Value of GL_MAX_VIEWS_OVR.
+ int MaxViewsOVR;
+
// Name Hashing.
// Set a 64 bit hash function to enable user-defined name hashing.
// Default is NULL.
@@ -299,19 +343,107 @@ typedef struct
// Default is SH_CLAMP_WITH_CLAMP_INTRINSIC.
ShArrayIndexClampingStrategy ArrayIndexClampingStrategy;
- // The maximum complexity an expression can be.
+ // The maximum complexity an expression can be when SH_LIMIT_EXPRESSION_COMPLEXITY is turned on.
int MaxExpressionComplexity;
// The maximum depth a call stack can be.
int MaxCallStackDepth;
-} ShBuiltInResources;
-//
-// Initialize built-in resources with minimum expected values.
-// Parameters:
-// resources: The object to initialize. Will be comparable with memcmp.
-//
-COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources *resources);
+ // The maximum number of parameters a function can have when SH_LIMIT_EXPRESSION_COMPLEXITY is
+ // turned on.
+ int MaxFunctionParameters;
+
+ // GLES 3.1 constants
+
+ // texture gather offset constraints.
+ int MinProgramTextureGatherOffset;
+ int MaxProgramTextureGatherOffset;
+
+ // maximum number of available image units
+ int MaxImageUnits;
+
+ // maximum number of image uniforms in a vertex shader
+ int MaxVertexImageUniforms;
+
+ // maximum number of image uniforms in a fragment shader
+ int MaxFragmentImageUniforms;
+
+ // maximum number of image uniforms in a compute shader
+ int MaxComputeImageUniforms;
+
+ // maximum total number of image uniforms in a program
+ int MaxCombinedImageUniforms;
+
+ // maximum number of uniform locations
+ int MaxUniformLocations;
+
+ // maximum number of ssbos and images in a shader
+ int MaxCombinedShaderOutputResources;
+
+ // maximum number of groups in each dimension
+ std::array<int, 3> MaxComputeWorkGroupCount;
+ // maximum number of threads per work group in each dimension
+ std::array<int, 3> MaxComputeWorkGroupSize;
+
+ // maximum number of total uniform components
+ int MaxComputeUniformComponents;
+
+ // maximum number of texture image units in a compute shader
+ int MaxComputeTextureImageUnits;
+
+ // maximum number of atomic counters in a compute shader
+ int MaxComputeAtomicCounters;
+
+ // maximum number of atomic counter buffers in a compute shader
+ int MaxComputeAtomicCounterBuffers;
+
+ // maximum number of atomic counters in a vertex shader
+ int MaxVertexAtomicCounters;
+
+ // maximum number of atomic counters in a fragment shader
+ int MaxFragmentAtomicCounters;
+
+ // maximum number of atomic counters in a program
+ int MaxCombinedAtomicCounters;
+
+ // maximum binding for an atomic counter
+ int MaxAtomicCounterBindings;
+
+ // maximum number of atomic counter buffers in a vertex shader
+ int MaxVertexAtomicCounterBuffers;
+
+ // maximum number of atomic counter buffers in a fragment shader
+ int MaxFragmentAtomicCounterBuffers;
+
+ // maximum number of atomic counter buffers in a program
+ int MaxCombinedAtomicCounterBuffers;
+
+ // maximum number of buffer object storage in machine units
+ int MaxAtomicCounterBufferSize;
+
+ // maximum number of uniform block bindings
+ int MaxUniformBufferBindings;
+
+ // maximum number of shader storage buffer bindings
+ int MaxShaderStorageBufferBindings;
+
+ // maximum point size (higher limit from ALIASED_POINT_SIZE_RANGE)
+ float MaxPointSize;
+
+ // OES_geometry_shader constants
+ int MaxGeometryUniformComponents;
+ int MaxGeometryUniformBlocks;
+ int MaxGeometryInputComponents;
+ int MaxGeometryOutputComponents;
+ int MaxGeometryOutputVertices;
+ int MaxGeometryTotalOutputComponents;
+ int MaxGeometryTextureImageUnits;
+ int MaxGeometryAtomicCounterBuffers;
+ int MaxGeometryAtomicCounters;
+ int MaxGeometryShaderStorageBlocks;
+ int MaxGeometryShaderInvocations;
+ int MaxGeometryImageUniforms;
+};
//
// ShHandle held by but opaque to the driver. It is allocated,
@@ -320,43 +452,60 @@ COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources *resources);
//
// If handle creation fails, 0 will be returned.
//
-typedef void *ShHandle;
+using ShHandle = void *;
+
+namespace sh
+{
+
+//
+// Driver must call this first, once, before doing any other compiler operations.
+// If the function succeeds, the return value is true, else false.
+//
+bool Initialize();
+//
+// Driver should call this at shutdown.
+// If the function succeeds, the return value is true, else false.
+//
+bool Finalize();
+
+//
+// Initialize built-in resources with minimum expected values.
+// Parameters:
+// resources: The object to initialize. Will be comparable with memcmp.
+//
+void InitBuiltInResources(ShBuiltInResources *resources);
//
-// Returns the a concatenated list of the items in ShBuiltInResources as a
-// null-terminated string.
+// Returns the a concatenated list of the items in ShBuiltInResources as a null-terminated string.
// This function must be updated whenever ShBuiltInResources is changed.
// Parameters:
// handle: Specifies the handle of the compiler to be used.
-COMPILER_EXPORT const std::string &ShGetBuiltInResourcesString(const ShHandle handle);
+const std::string &GetBuiltInResourcesString(const ShHandle handle);
//
// Driver calls these to create and destroy compiler objects.
//
-// Returns the handle of constructed compiler, null if the requested compiler is
-// not supported.
+// Returns the handle of constructed compiler, null if the requested compiler is not supported.
// Parameters:
// type: Specifies the type of shader - GL_FRAGMENT_SHADER or GL_VERTEX_SHADER.
-// spec: Specifies the language spec the compiler must conform to -
-// SH_GLES2_SPEC or SH_WEBGL_SPEC.
+// spec: Specifies the language spec the compiler must conform to - SH_GLES2_SPEC or SH_WEBGL_SPEC.
// output: Specifies the output code type - for example SH_ESSL_OUTPUT, SH_GLSL_OUTPUT,
// SH_HLSL_3_0_OUTPUT or SH_HLSL_4_1_OUTPUT. Note: Each output type may only
// be supported in some configurations.
// resources: Specifies the built-in resources.
-COMPILER_EXPORT ShHandle ShConstructCompiler(
- sh::GLenum type,
- ShShaderSpec spec,
- ShShaderOutput output,
- const ShBuiltInResources *resources);
-COMPILER_EXPORT void ShDestruct(ShHandle handle);
+ShHandle ConstructCompiler(sh::GLenum type,
+ ShShaderSpec spec,
+ ShShaderOutput output,
+ const ShBuiltInResources *resources);
+void Destruct(ShHandle handle);
//
// Compiles the given shader source.
// If the function succeeds, the return value is true, else false.
// Parameters:
// handle: Specifies the handle of compiler to be used.
-// shaderStrings: Specifies an array of pointers to null-terminated strings
-// containing the shader source code.
+// shaderStrings: Specifies an array of pointers to null-terminated strings containing the shader
+// source code.
// numStrings: Specifies the number of elements in shaderStrings array.
// compileOptions: A mask containing the following parameters:
// SH_VALIDATE: Validates shader to ensure that it conforms to the spec
@@ -368,45 +517,41 @@ COMPILER_EXPORT void ShDestruct(ShHandle handle);
// There is no need to specify this parameter when
// compiling for WebGL - it is implied.
// SH_INTERMEDIATE_TREE: Writes intermediate tree to info log.
-// Can be queried by calling ShGetInfoLog().
+// Can be queried by calling sh::GetInfoLog().
// SH_OBJECT_CODE: Translates intermediate tree to glsl or hlsl shader.
-// Can be queried by calling ShGetObjectCode().
+// Can be queried by calling sh::GetObjectCode().
// SH_VARIABLES: Extracts attributes, uniforms, and varyings.
// Can be queried by calling ShGetVariableInfo().
//
-COMPILER_EXPORT bool ShCompile(
- const ShHandle handle,
- const char * const shaderStrings[],
- size_t numStrings,
- int compileOptions);
+bool Compile(const ShHandle handle,
+ const char *const shaderStrings[],
+ size_t numStrings,
+ ShCompileOptions compileOptions);
// Clears the results from the previous compilation.
-COMPILER_EXPORT void ShClearResults(const ShHandle handle);
+void ClearResults(const ShHandle handle);
// Return the version of the shader language.
-COMPILER_EXPORT int ShGetShaderVersion(const ShHandle handle);
+int GetShaderVersion(const ShHandle handle);
// Return the currently set language output type.
-COMPILER_EXPORT ShShaderOutput ShGetShaderOutputType(
- const ShHandle handle);
+ShShaderOutput GetShaderOutputType(const ShHandle handle);
// Returns null-terminated information log for a compiled shader.
// Parameters:
// handle: Specifies the compiler
-COMPILER_EXPORT const std::string &ShGetInfoLog(const ShHandle handle);
+const std::string &GetInfoLog(const ShHandle handle);
// Returns null-terminated object code for a compiled shader.
// Parameters:
// handle: Specifies the compiler
-COMPILER_EXPORT const std::string &ShGetObjectCode(const ShHandle handle);
+const std::string &GetObjectCode(const ShHandle handle);
-// Returns a (original_name, hash) map containing all the user defined
-// names in the shader, including variable names, function names, struct
-// names, and struct field names.
+// Returns a (original_name, hash) map containing all the user defined names in the shader,
+// including variable names, function names, struct names, and struct field names.
// Parameters:
// handle: Specifies the compiler
-COMPILER_EXPORT const std::map<std::string, std::string> *ShGetNameHashingMap(
- const ShHandle handle);
+const std::map<std::string, std::string> *GetNameHashingMap(const ShHandle handle);
// Shader variable inspection.
// Returns a pointer to a list of variables of the designated type.
@@ -414,52 +559,50 @@ COMPILER_EXPORT const std::map<std::string, std::string> *ShGetNameHashingMap(
// Returns NULL on failure.
// Parameters:
// handle: Specifies the compiler
-COMPILER_EXPORT const std::vector<sh::Uniform> *ShGetUniforms(const ShHandle handle);
-COMPILER_EXPORT const std::vector<sh::Varying> *ShGetVaryings(const ShHandle handle);
-COMPILER_EXPORT const std::vector<sh::Attribute> *ShGetAttributes(const ShHandle handle);
-COMPILER_EXPORT const std::vector<sh::OutputVariable> *ShGetOutputVariables(const ShHandle handle);
-COMPILER_EXPORT const std::vector<sh::InterfaceBlock> *ShGetInterfaceBlocks(const ShHandle handle);
-
-typedef struct
-{
- sh::GLenum type;
- int size;
-} ShVariableInfo;
-
-// Returns true if the passed in variables pack in maxVectors following
-// the packing rules from the GLSL 1.017 spec, Appendix A, section 7.
+const std::vector<sh::Uniform> *GetUniforms(const ShHandle handle);
+const std::vector<sh::Varying> *GetVaryings(const ShHandle handle);
+const std::vector<sh::Varying> *GetInputVaryings(const ShHandle handle);
+const std::vector<sh::Varying> *GetOutputVaryings(const ShHandle handle);
+const std::vector<sh::Attribute> *GetAttributes(const ShHandle handle);
+const std::vector<sh::OutputVariable> *GetOutputVariables(const ShHandle handle);
+const std::vector<sh::InterfaceBlock> *GetInterfaceBlocks(const ShHandle handle);
+const std::vector<sh::InterfaceBlock> *GetUniformBlocks(const ShHandle handle);
+const std::vector<sh::InterfaceBlock> *GetShaderStorageBlocks(const ShHandle handle);
+sh::WorkGroupSize GetComputeShaderLocalGroupSize(const ShHandle handle);
+// Returns the number of views specified through the num_views layout qualifier. If num_views is
+// not set, the function returns -1.
+int GetVertexShaderNumViews(const ShHandle handle);
+
+// Returns true if the passed in variables pack in maxVectors followingthe packing rules from the
+// GLSL 1.017 spec, Appendix A, section 7.
// Returns false otherwise. Also look at the SH_ENFORCE_PACKING_RESTRICTIONS
// flag above.
// Parameters:
// maxVectors: the available rows of registers.
-// varInfoArray: an array of variable info (types and sizes).
-// varInfoArraySize: the size of the variable array.
-COMPILER_EXPORT bool ShCheckVariablesWithinPackingLimits(
- int maxVectors,
- ShVariableInfo *varInfoArray,
- size_t varInfoArraySize);
-
-// Gives the compiler-assigned register for an interface block.
-// The method writes the value to the output variable "indexOut".
-// Returns true if it found a valid interface block, false otherwise.
-// Parameters:
-// handle: Specifies the compiler
-// interfaceBlockName: Specifies the interface block
-// indexOut: output variable that stores the assigned register
-COMPILER_EXPORT bool ShGetInterfaceBlockRegister(const ShHandle handle,
- const std::string &interfaceBlockName,
- unsigned int *indexOut);
+// variables: an array of variables.
+bool CheckVariablesWithinPackingLimits(int maxVectors,
+ const std::vector<sh::ShaderVariable> &variables);
-// Gives the compiler-assigned register for uniforms in the default
-// interface block.
+// Gives the compiler-assigned register for a uniform block.
// The method writes the value to the output variable "indexOut".
-// Returns true if it found a valid default uniform, false otherwise.
+// Returns true if it found a valid uniform block, false otherwise.
// Parameters:
// handle: Specifies the compiler
-// interfaceBlockName: Specifies the uniform
+// uniformBlockName: Specifies the uniform block
// indexOut: output variable that stores the assigned register
-COMPILER_EXPORT bool ShGetUniformRegister(const ShHandle handle,
- const std::string &uniformName,
- unsigned int *indexOut);
+bool GetUniformBlockRegister(const ShHandle handle,
+ const std::string &uniformBlockName,
+ unsigned int *indexOut);
+
+// Gives a map from uniform names to compiler-assigned registers in the default uniform block.
+// Note that the map contains also registers of samplers that have been extracted from structs.
+const std::map<std::string, unsigned int> *GetUniformRegisterMap(const ShHandle handle);
+
+GLenum GetGeometryShaderInputPrimitiveType(const ShHandle handle);
+GLenum GetGeometryShaderOutputPrimitiveType(const ShHandle handle);
+int GetGeometryShaderInvocations(const ShHandle handle);
+int GetGeometryShaderMaxVertices(const ShHandle handle);
+
+} // namespace sh
#endif // GLSLANG_SHADERLANG_H_
diff --git a/src/3rdparty/angle/include/GLSLANG/ShaderVars.h b/src/3rdparty/angle/include/GLSLANG/ShaderVars.h
index af9b65b7f5..709428aebf 100644
--- a/src/3rdparty/angle/include/GLSLANG/ShaderVars.h
+++ b/src/3rdparty/angle/include/GLSLANG/ShaderVars.h
@@ -10,15 +10,18 @@
#ifndef GLSLANG_SHADERVARS_H_
#define GLSLANG_SHADERVARS_H_
+#include <algorithm>
+#include <array>
#include <string>
#include <vector>
-#include <algorithm>
-// Assume ShaderLang.h is included before ShaderVars.h, for sh::GLenum
-// Note: make sure to increment ANGLE_SH_VERSION when changing ShaderVars.h
+// This type is defined here to simplify ANGLE's integration with glslang for SPIRv.
+using ShCompileOptions = uint64_t;
namespace sh
{
+// GLenum alias
+typedef unsigned int GLenum;
// Varying interpolation qualifier, see section 4.3.9 of the ESSL 3.00.4 spec
enum InterpolationType
@@ -29,30 +32,65 @@ enum InterpolationType
};
// Validate link & SSO consistency of interpolation qualifiers
-COMPILER_EXPORT bool InterpolationTypesMatch(InterpolationType a, InterpolationType b);
+bool InterpolationTypesMatch(InterpolationType a, InterpolationType b);
// Uniform block layout qualifier, see section 4.3.8.3 of the ESSL 3.00.4 spec
enum BlockLayoutType
{
BLOCKLAYOUT_STANDARD,
+ BLOCKLAYOUT_STD140 = BLOCKLAYOUT_STANDARD,
+ BLOCKLAYOUT_STD430, // Shader storage block layout qualifier
BLOCKLAYOUT_PACKED,
BLOCKLAYOUT_SHARED
};
+// Interface Blocks, see section 4.3.9 of the ESSL 3.10 spec
+enum class BlockType
+{
+ BLOCK_UNIFORM,
+ BLOCK_BUFFER,
+
+ // Required in OpenGL ES 3.1 extension GL_OES_shader_io_blocks.
+ // TODO(jiawei.shao@intel.com): add BLOCK_OUT.
+ BLOCK_IN
+};
+
// Base class for all variables defined in shaders, including Varyings, Uniforms, etc
// Note: we must override the copy constructor and assignment operator so we can
// work around excessive GCC binary bloating:
// See https://code.google.com/p/angleproject/issues/detail?id=697
-struct COMPILER_EXPORT ShaderVariable
+struct ShaderVariable
{
ShaderVariable();
+ ShaderVariable(GLenum typeIn);
ShaderVariable(GLenum typeIn, unsigned int arraySizeIn);
~ShaderVariable();
ShaderVariable(const ShaderVariable &other);
ShaderVariable &operator=(const ShaderVariable &other);
- bool isArray() const { return arraySize > 0; }
- unsigned int elementCount() const { return std::max(1u, arraySize); }
+ bool isArrayOfArrays() const { return arraySizes.size() >= 2u; }
+ bool isArray() const { return !arraySizes.empty(); }
+ unsigned int getArraySizeProduct() const;
+
+ // Array size 0 means not an array when passed to or returned from these functions.
+ // Note that setArraySize() is deprecated and should not be used inside ANGLE.
+ unsigned int getOutermostArraySize() const { return isArray() ? arraySizes.back() : 0; }
+ void setArraySize(unsigned int size);
+
+ // Turn this ShaderVariable from an array into a specific element in that array. Will update
+ // flattenedOffsetInParentArrays.
+ void indexIntoArray(unsigned int arrayIndex);
+
+ // Get the nth nested array size from the top. Caller is responsible for range checking
+ // arrayNestingIndex.
+ unsigned int getNestedArraySize(unsigned int arrayNestingIndex) const;
+
+ // This function should only be used with variables that are of a basic type or an array of a
+ // basic type. Shader interface variables that are enumerated according to rules in GLES 3.1
+ // spec section 7.3.1.1 page 77 are fine. For those variables the return value should match the
+ // ARRAY_SIZE value that can be queried through the API.
+ unsigned int getBasicTypeElementCount() const;
+
bool isStruct() const { return !fields.empty(); }
// All of the shader's variables are described using nested data
@@ -70,20 +108,32 @@ struct COMPILER_EXPORT ShaderVariable
const ShaderVariable **leafVar,
std::string* originalFullName) const;
- bool isBuiltIn() const { return name.compare(0, 3, "gl_") == 0; }
+ bool isBuiltIn() const;
GLenum type;
GLenum precision;
std::string name;
std::string mappedName;
- unsigned int arraySize;
+
+ // Used to make an array type. Outermost array size is stored at the end of the vector.
+ std::vector<unsigned int> arraySizes;
+
+ // Offset of this variable in parent arrays. In case the parent is an array of arrays, the
+ // offset is outerArrayElement * innerArraySize + innerArrayElement.
+ // For example, if there's a variable declared as size 3 array of size 4 array of int:
+ // int a[3][4];
+ // then the flattenedOffsetInParentArrays of a[2] would be 2.
+ // and flattenedOffsetInParentArrays of a[2][1] would be 2*4 + 1 = 9.
+ unsigned int flattenedOffsetInParentArrays;
+
bool staticUse;
std::vector<ShaderVariable> fields;
std::string structName;
protected:
bool isSameVariableAtLinkTime(const ShaderVariable &other,
- bool matchPrecision) const;
+ bool matchPrecision,
+ bool matchName) const;
bool operator==(const ShaderVariable &other) const;
bool operator!=(const ShaderVariable &other) const
@@ -92,7 +142,21 @@ struct COMPILER_EXPORT ShaderVariable
}
};
-struct COMPILER_EXPORT Uniform : public ShaderVariable
+// A variable with an integer location to pass back to the GL API: either uniform (can have location
+// in GLES3.1+), vertex shader input or fragment shader output.
+struct VariableWithLocation : public ShaderVariable
+{
+ VariableWithLocation();
+ ~VariableWithLocation();
+ VariableWithLocation(const VariableWithLocation &other);
+ VariableWithLocation &operator=(const VariableWithLocation &other);
+ bool operator==(const VariableWithLocation &other) const;
+ bool operator!=(const VariableWithLocation &other) const { return !operator==(other); }
+
+ int location;
+};
+
+struct Uniform : public VariableWithLocation
{
Uniform();
~Uniform();
@@ -104,28 +168,17 @@ struct COMPILER_EXPORT Uniform : public ShaderVariable
return !operator==(other);
}
+ int binding;
+ int offset;
+
// Decide whether two uniforms are the same at shader link time,
// assuming one from vertex shader and the other from fragment shader.
- // See GLSL ES Spec 3.00.3, sec 4.3.5.
+ // GLSL ES Spec 3.00.3, section 4.3.5.
+ // GLSL ES Spec 3.10.4, section 4.4.5
bool isSameUniformAtLinkTime(const Uniform &other) const;
};
-// An interface variable is a variable which passes data between the GL data structures and the
-// shader execution: either vertex shader inputs or fragment shader outputs. These variables can
-// have integer locations to pass back to the GL API.
-struct COMPILER_EXPORT InterfaceVariable : public ShaderVariable
-{
- InterfaceVariable();
- ~InterfaceVariable();
- InterfaceVariable(const InterfaceVariable &other);
- InterfaceVariable &operator=(const InterfaceVariable &other);
- bool operator==(const InterfaceVariable &other) const;
- bool operator!=(const InterfaceVariable &other) const { return !operator==(other); }
-
- int location;
-};
-
-struct COMPILER_EXPORT Attribute : public InterfaceVariable
+struct Attribute : public VariableWithLocation
{
Attribute();
~Attribute();
@@ -135,7 +188,7 @@ struct COMPILER_EXPORT Attribute : public InterfaceVariable
bool operator!=(const Attribute &other) const { return !operator==(other); }
};
-struct COMPILER_EXPORT OutputVariable : public InterfaceVariable
+struct OutputVariable : public VariableWithLocation
{
OutputVariable();
~OutputVariable();
@@ -145,7 +198,7 @@ struct COMPILER_EXPORT OutputVariable : public InterfaceVariable
bool operator!=(const OutputVariable &other) const { return !operator==(other); }
};
-struct COMPILER_EXPORT InterfaceBlockField : public ShaderVariable
+struct InterfaceBlockField : public ShaderVariable
{
InterfaceBlockField();
~InterfaceBlockField();
@@ -167,7 +220,7 @@ struct COMPILER_EXPORT InterfaceBlockField : public ShaderVariable
bool isRowMajorLayout;
};
-struct COMPILER_EXPORT Varying : public ShaderVariable
+struct Varying : public VariableWithLocation
{
Varying();
~Varying();
@@ -193,7 +246,7 @@ struct COMPILER_EXPORT Varying : public ShaderVariable
bool isInvariant;
};
-struct COMPILER_EXPORT InterfaceBlock
+struct InterfaceBlock
{
InterfaceBlock();
~InterfaceBlock();
@@ -202,6 +255,15 @@ struct COMPILER_EXPORT InterfaceBlock
// Fields from blocks with non-empty instance names are prefixed with the block name.
std::string fieldPrefix() const;
+ std::string fieldMappedPrefix() const;
+
+ // Decide whether two interface blocks are the same at shader link time.
+ bool isSameInterfaceBlockAtLinkTime(const InterfaceBlock &other) const;
+
+ bool isBuiltIn() const;
+
+ bool isArray() const { return arraySize > 0; }
+ unsigned int elementCount() const { return std::max(1u, arraySize); }
std::string name;
std::string mappedName;
@@ -209,10 +271,45 @@ struct COMPILER_EXPORT InterfaceBlock
unsigned int arraySize;
BlockLayoutType layout;
bool isRowMajorLayout;
+ int binding;
bool staticUse;
+ BlockType blockType;
std::vector<InterfaceBlockField> fields;
};
+struct WorkGroupSize
+{
+ // Must have a trivial default constructor since it is used in YYSTYPE.
+ WorkGroupSize() = default;
+ explicit constexpr WorkGroupSize(int initialSize)
+ : localSizeQualifiers{initialSize, initialSize, initialSize}
+ {
+ }
+
+ void fill(int fillValue);
+ void setLocalSize(int localSizeX, int localSizeY, int localSizeZ);
+
+ int &operator[](size_t index);
+ int operator[](size_t index) const;
+ size_t size() const;
+
+ // Checks whether two work group size declarations match.
+ // Two work group size declarations are the same if the explicitly specified elements are the
+ // same or if one of them is specified as one and the other one is not specified
+ bool isWorkGroupSizeMatching(const WorkGroupSize &right) const;
+
+ // Checks whether any of the values are set.
+ bool isAnyValueSet() const;
+
+ // Checks whether all of the values are set.
+ bool isDeclared() const;
+
+ // Checks whether either all of the values are set, or none of them are.
+ bool isLocalSizeValid() const;
+
+ std::array<int, 3> localSizeQualifiers;
+};
+
} // namespace sh
#endif // GLSLANG_SHADERVARS_H_
diff --git a/src/3rdparty/angle/include/KHR/khrplatform.h b/src/3rdparty/angle/include/KHR/khrplatform.h
index c9e6f17d34..68fca48271 100644
--- a/src/3rdparty/angle/include/KHR/khrplatform.h
+++ b/src/3rdparty/angle/include/KHR/khrplatform.h
@@ -26,7 +26,7 @@
/* Khronos platform-specific types and definitions.
*
- * $Revision: 23298 $ on $Date: 2013-09-30 17:07:13 -0700 (Mon, 30 Sep 2013) $
+ * $Revision: 32517 $ on $Date: 2016-03-11 02:41:19 -0800 (Fri, 11 Mar 2016) $
*
* Adopters may modify this file to suit their platform. Adopters are
* encouraged to submit platform specific modifications to the Khronos
@@ -101,6 +101,9 @@
# define KHRONOS_APICALL __declspec(dllimport)
#elif defined (__SYMBIAN32__)
# define KHRONOS_APICALL IMPORT_C
+#elif defined(__ANDROID__)
+# include <sys/cdefs.h>
+# define KHRONOS_APICALL __attribute__((visibility("default"))) __NDK_FPABI__
#else
# define KHRONOS_APICALL
#endif
@@ -223,7 +226,7 @@ typedef signed short int khronos_int16_t;
typedef unsigned short int khronos_uint16_t;
/*
- * Types that differ between LLP64 and LP64 architectures - in LLP64,
+ * Types that differ between LLP64 and LP64 architectures - in LLP64,
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
* to be the only LLP64 architecture in current use.
*/
@@ -279,4 +282,4 @@ typedef enum {
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
} khronos_boolean_enum_t;
-#endif /* __khrplatform_h_ */
+#endif /* __khrplatform_h_ */ \ No newline at end of file
diff --git a/src/3rdparty/angle/include/angle_gl.h b/src/3rdparty/angle/include/angle_gl.h
index 18de80b60b..b70a31c273 100644
--- a/src/3rdparty/angle/include/angle_gl.h
+++ b/src/3rdparty/angle/include/angle_gl.h
@@ -16,9 +16,4 @@
#include "GLES3/gl31.h"
#include "GLES3/gl32.h"
-// The following enum is used in ANGLE, but is from desktop GL
-#ifndef GL_SAMPLER_2D_RECT_ARB
-#define GL_SAMPLER_2D_RECT_ARB 0x8B63
-#endif
-
#endif // ANGLEGL_H_
diff --git a/src/3rdparty/angle/include/export.h b/src/3rdparty/angle/include/export.h
index cdf6245d6d..cf144f92a5 100644
--- a/src/3rdparty/angle/include/export.h
+++ b/src/3rdparty/angle/include/export.h
@@ -9,14 +9,17 @@
#ifndef LIBGLESV2_EXPORT_H_
#define LIBGLESV2_EXPORT_H_
+#if !defined(ANGLE_EXPORT)
#if defined(_WIN32)
-# if defined(LIBGLESV2_IMPLEMENTATION) || defined(LIBANGLE_IMPLEMENTATION)
+#if defined(LIBGLESV2_IMPLEMENTATION) || defined(LIBANGLE_IMPLEMENTATION) || \
+ defined(LIBANGLE_UTIL_IMPLEMENTATION)
# define ANGLE_EXPORT __declspec(dllexport)
# else
# define ANGLE_EXPORT __declspec(dllimport)
# endif
#elif defined(__GNUC__)
-# if defined(LIBGLESV2_IMPLEMENTATION) || defined(LIBANGLE_IMPLEMENTATION)
+#if defined(LIBGLESV2_IMPLEMENTATION) || defined(LIBANGLE_IMPLEMENTATION) || \
+ defined(LIBANGLE_UTIL_IMPLEMENTATION)
# define ANGLE_EXPORT __attribute__((visibility ("default")))
# else
# define ANGLE_EXPORT
@@ -24,5 +27,6 @@
#else
# define ANGLE_EXPORT
#endif
+#endif // !defined(ANGLE_EXPORT)
#endif // LIBGLESV2_EXPORT_H_
diff --git a/src/3rdparty/angle/include/platform/Platform.h b/src/3rdparty/angle/include/platform/Platform.h
index 0e8cdf477f..aa1221a86e 100644
--- a/src/3rdparty/angle/include/platform/Platform.h
+++ b/src/3rdparty/angle/include/platform/Platform.h
@@ -10,15 +10,16 @@
#define ANGLE_PLATFORM_H
#include <stdint.h>
+#include <array>
#if defined(_WIN32)
# if !defined(LIBANGLE_IMPLEMENTATION)
# define ANGLE_PLATFORM_EXPORT __declspec(dllimport)
+# else
+# define ANGLE_PLATFORM_EXPORT __declspec(dllexport)
# endif
-#elif defined(__GNUC__)
-# if defined(LIBANGLE_IMPLEMENTATION)
-# define ANGLE_PLATFORM_EXPORT __attribute__((visibility ("default")))
-# endif
+#elif defined(__GNUC__) || defined(__clang__)
+# define ANGLE_PLATFORM_EXPORT __attribute__((visibility ("default")))
#endif
#if !defined(ANGLE_PLATFORM_EXPORT)
# define ANGLE_PLATFORM_EXPORT
@@ -32,137 +33,295 @@
namespace angle
{
+struct WorkaroundsD3D;
+using TraceEventHandle = uint64_t;
+using EGLDisplayType = void *;
+struct PlatformMethods;
-class Platform
-{
- public:
-
- // System --------------------------------------------------------------
-
- // Wall clock time in seconds since the epoch.
- // TODO(jmadill): investigate using an ANGLE internal time library
- virtual double currentTime() { return 0; }
-
- // Monotonically increasing time in seconds from an arbitrary fixed point in the past.
- // This function is expected to return at least millisecond-precision values. For this reason,
- // it is recommended that the fixed point be no further in the past than the epoch.
- virtual double monotonicallyIncreasingTime() { return 0; }
-
- // Logging ------------------------------------------------------------
-
- // Log an error message within the platform implementation.
- virtual void logError(const char *errorMessage) {}
-
- // Log a warning message within the platform implementation.
- virtual void logWarning(const char *warningMessage) {}
-
- // Log an info message within the platform implementation.
- virtual void logInfo(const char *infoMessage) {}
-
- // Tracing --------
-
- // Get a pointer to the enabled state of the given trace category. The
- // embedder can dynamically change the enabled state as trace event
- // recording is started and stopped by the application. Only long-lived
- // literal strings should be given as the category name. The implementation
- // expects the returned pointer to be held permanently in a local static. If
- // the unsigned char is non-zero, tracing is enabled. If tracing is enabled,
- // addTraceEvent is expected to be called by the trace event macros.
- virtual const unsigned char *getTraceCategoryEnabledFlag(const char *categoryName) { return 0; }
-
- typedef uint64_t TraceEventHandle;
-
- // Add a trace event to the platform tracing system. Depending on the actual
- // enabled state, this event may be recorded or dropped.
- // - phase specifies the type of event:
- // - BEGIN ('B'): Marks the beginning of a scoped event.
- // - END ('E'): Marks the end of a scoped event.
- // - COMPLETE ('X'): Marks the beginning of a scoped event, but doesn't
- // need a matching END event. Instead, at the end of the scope,
- // updateTraceEventDuration() must be called with the TraceEventHandle
- // returned from addTraceEvent().
- // - INSTANT ('I'): Standalone, instantaneous event.
- // - START ('S'): Marks the beginning of an asynchronous event (the end
- // event can occur in a different scope or thread). The id parameter is
- // used to match START/FINISH pairs.
- // - FINISH ('F'): Marks the end of an asynchronous event.
- // - COUNTER ('C'): Used to trace integer quantities that change over
- // time. The argument values are expected to be of type int.
- // - METADATA ('M'): Reserved for internal use.
- // - categoryEnabled is the pointer returned by getTraceCategoryEnabledFlag.
- // - name is the name of the event. Also used to match BEGIN/END and
- // START/FINISH pairs.
- // - id optionally allows events of the same name to be distinguished from
- // each other. For example, to trace the consutruction and destruction of
- // objects, specify the pointer as the id parameter.
- // - timestamp should be a time value returned from monotonicallyIncreasingTime.
- // - numArgs specifies the number of elements in argNames, argTypes, and
- // argValues.
- // - argNames is the array of argument names. Use long-lived literal strings
- // or specify the COPY flag.
- // - argTypes is the array of argument types:
- // - BOOL (1): bool
- // - UINT (2): unsigned long long
- // - INT (3): long long
- // - DOUBLE (4): double
- // - POINTER (5): void*
- // - STRING (6): char* (long-lived null-terminated char* string)
- // - COPY_STRING (7): char* (temporary null-terminated char* string)
- // - CONVERTABLE (8): WebConvertableToTraceFormat
- // - argValues is the array of argument values. Each value is the unsigned
- // long long member of a union of all supported types.
- // - flags can be 0 or one or more of the following, ORed together:
- // - COPY (0x1): treat all strings (name, argNames and argValues of type
- // string) as temporary so that they will be copied by addTraceEvent.
- // - HAS_ID (0x2): use the id argument to uniquely identify the event for
- // matching with other events of the same name.
- // - MANGLE_ID (0x4): specify this flag if the id parameter is the value
- // of a pointer.
- virtual TraceEventHandle addTraceEvent(char phase,
- const unsigned char *categoryEnabledFlag,
- const char *name,
- unsigned long long id,
- double timestamp,
- int numArgs,
- const char **argNames,
- const unsigned char *argTypes,
- const unsigned long long *argValues,
- unsigned char flags)
- {
- return 0;
- }
-
- // Set the duration field of a COMPLETE trace event.
- virtual void updateTraceEventDuration(const unsigned char *categoryEnabledFlag, const char *name, TraceEventHandle eventHandle) { }
-
- // Callbacks for reporting histogram data.
- // CustomCounts histogram has exponential bucket sizes, so that min=1, max=1000000, bucketCount=50 would do.
- virtual void histogramCustomCounts(const char *name, int sample, int min, int max, int bucketCount) { }
- // Enumeration histogram buckets are linear, boundaryValue should be larger than any possible sample value.
- virtual void histogramEnumeration(const char *name, int sample, int boundaryValue) { }
- // Unlike enumeration histograms, sparse histograms only allocate memory for non-empty buckets.
- virtual void histogramSparse(const char *name, int sample) { }
- // Boolean histograms track two-state variables.
- virtual void histogramBoolean(const char *name, bool sample) { }
-
- protected:
- virtual ~Platform() { }
-};
+// Use a C-like API to not trigger undefined calling behaviour.
+// Avoid using decltype here to work around sanitizer limitations.
+// TODO(jmadill): Use decltype here if/when UBSAN is fixed.
+
+// System --------------------------------------------------------------
+
+// Wall clock time in seconds since the epoch.
+// TODO(jmadill): investigate using an ANGLE internal time library
+using CurrentTimeFunc = double (*)(PlatformMethods *platform);
+inline double DefaultCurrentTime(PlatformMethods *platform)
+{
+ return 0.0;
+}
+
+// Monotonically increasing time in seconds from an arbitrary fixed point in the past.
+// This function is expected to return at least millisecond-precision values. For this reason,
+// it is recommended that the fixed point be no further in the past than the epoch.
+using MonotonicallyIncreasingTimeFunc = double (*)(PlatformMethods *platform);
+inline double DefaultMonotonicallyIncreasingTime(PlatformMethods *platform)
+{
+ return 0.0;
+}
+
+// Logging ------------------------------------------------------------
+
+// Log an error message within the platform implementation.
+using LogErrorFunc = void (*)(PlatformMethods *platform, const char *errorMessage);
+inline void DefaultLogError(PlatformMethods *platform, const char *errorMessage)
+{
+}
+
+// Log a warning message within the platform implementation.
+using LogWarningFunc = void (*)(PlatformMethods *platform, const char *warningMessage);
+inline void DefaultLogWarning(PlatformMethods *platform, const char *warningMessage)
+{
+}
+// Log an info message within the platform implementation.
+using LogInfoFunc = void (*)(PlatformMethods *platform, const char *infoMessage);
+inline void DefaultLogInfo(PlatformMethods *platform, const char *infoMessage)
+{
}
-extern "C"
+// Tracing --------
+
+// Get a pointer to the enabled state of the given trace category. The
+// embedder can dynamically change the enabled state as trace event
+// recording is started and stopped by the application. Only long-lived
+// literal strings should be given as the category name. The implementation
+// expects the returned pointer to be held permanently in a local static. If
+// the unsigned char is non-zero, tracing is enabled. If tracing is enabled,
+// addTraceEvent is expected to be called by the trace event macros.
+using GetTraceCategoryEnabledFlagFunc = const unsigned char *(*)(PlatformMethods *platform,
+ const char *categoryName);
+inline const unsigned char *DefaultGetTraceCategoryEnabledFlag(PlatformMethods *platform,
+ const char *categoryName)
{
+ return nullptr;
+}
-typedef void (ANGLE_APIENTRY *ANGLEPlatformInitializeFunc)(angle::Platform*);
-ANGLE_PLATFORM_EXPORT void ANGLE_APIENTRY ANGLEPlatformInitialize(angle::Platform*);
+//
+// Add a trace event to the platform tracing system. Depending on the actual
+// enabled state, this event may be recorded or dropped.
+// - phase specifies the type of event:
+// - BEGIN ('B'): Marks the beginning of a scoped event.
+// - END ('E'): Marks the end of a scoped event.
+// - COMPLETE ('X'): Marks the beginning of a scoped event, but doesn't
+// need a matching END event. Instead, at the end of the scope,
+// updateTraceEventDuration() must be called with the TraceEventHandle
+// returned from addTraceEvent().
+// - INSTANT ('I'): Standalone, instantaneous event.
+// - START ('S'): Marks the beginning of an asynchronous event (the end
+// event can occur in a different scope or thread). The id parameter is
+// used to match START/FINISH pairs.
+// - FINISH ('F'): Marks the end of an asynchronous event.
+// - COUNTER ('C'): Used to trace integer quantities that change over
+// time. The argument values are expected to be of type int.
+// - METADATA ('M'): Reserved for internal use.
+// - categoryEnabled is the pointer returned by getTraceCategoryEnabledFlag.
+// - name is the name of the event. Also used to match BEGIN/END and
+// START/FINISH pairs.
+// - id optionally allows events of the same name to be distinguished from
+// each other. For example, to trace the consutruction and destruction of
+// objects, specify the pointer as the id parameter.
+// - timestamp should be a time value returned from monotonicallyIncreasingTime.
+// - numArgs specifies the number of elements in argNames, argTypes, and
+// argValues.
+// - argNames is the array of argument names. Use long-lived literal strings
+// or specify the COPY flag.
+// - argTypes is the array of argument types:
+// - BOOL (1): bool
+// - UINT (2): unsigned long long
+// - INT (3): long long
+// - DOUBLE (4): double
+// - POINTER (5): void*
+// - STRING (6): char* (long-lived null-terminated char* string)
+// - COPY_STRING (7): char* (temporary null-terminated char* string)
+// - CONVERTABLE (8): WebConvertableToTraceFormat
+// - argValues is the array of argument values. Each value is the unsigned
+// long long member of a union of all supported types.
+// - flags can be 0 or one or more of the following, ORed together:
+// - COPY (0x1): treat all strings (name, argNames and argValues of type
+// string) as temporary so that they will be copied by addTraceEvent.
+// - HAS_ID (0x2): use the id argument to uniquely identify the event for
+// matching with other events of the same name.
+// - MANGLE_ID (0x4): specify this flag if the id parameter is the value
+// of a pointer.
+using AddTraceEventFunc = angle::TraceEventHandle (*)(PlatformMethods *platform,
+ char phase,
+ const unsigned char *categoryEnabledFlag,
+ const char *name,
+ unsigned long long id,
+ double timestamp,
+ int numArgs,
+ const char **argNames,
+ const unsigned char *argTypes,
+ const unsigned long long *argValues,
+ unsigned char flags);
+inline angle::TraceEventHandle DefaultAddTraceEvent(PlatformMethods *platform,
+ char phase,
+ const unsigned char *categoryEnabledFlag,
+ const char *name,
+ unsigned long long id,
+ double timestamp,
+ int numArgs,
+ const char **argNames,
+ const unsigned char *argTypes,
+ const unsigned long long *argValues,
+ unsigned char flags)
+{
+ return 0;
+}
-typedef void (ANGLE_APIENTRY *ANGLEPlatformShutdownFunc)();
-ANGLE_PLATFORM_EXPORT void ANGLE_APIENTRY ANGLEPlatformShutdown();
+// Set the duration field of a COMPLETE trace event.
+using UpdateTraceEventDurationFunc = void (*)(PlatformMethods *platform,
+ const unsigned char *categoryEnabledFlag,
+ const char *name,
+ angle::TraceEventHandle eventHandle);
+inline void DefaultUpdateTraceEventDuration(PlatformMethods *platform,
+ const unsigned char *categoryEnabledFlag,
+ const char *name,
+ angle::TraceEventHandle eventHandle)
+{
+}
+
+// Callbacks for reporting histogram data.
+// CustomCounts histogram has exponential bucket sizes, so that min=1, max=1000000, bucketCount=50
+// would do.
+using HistogramCustomCountsFunc = void (*)(PlatformMethods *platform,
+ const char *name,
+ int sample,
+ int min,
+ int max,
+ int bucketCount);
+inline void DefaultHistogramCustomCounts(PlatformMethods *platform,
+ const char *name,
+ int sample,
+ int min,
+ int max,
+ int bucketCount)
+{
+}
+// Enumeration histogram buckets are linear, boundaryValue should be larger than any possible sample
+// value.
+using HistogramEnumerationFunc = void (*)(PlatformMethods *platform,
+ const char *name,
+ int sample,
+ int boundaryValue);
+inline void DefaultHistogramEnumeration(PlatformMethods *platform,
+ const char *name,
+ int sample,
+ int boundaryValue)
+{
+}
+// Unlike enumeration histograms, sparse histograms only allocate memory for non-empty buckets.
+using HistogramSparseFunc = void (*)(PlatformMethods *platform, const char *name, int sample);
+inline void DefaultHistogramSparse(PlatformMethods *platform, const char *name, int sample)
+{
+}
+// Boolean histograms track two-state variables.
+using HistogramBooleanFunc = void (*)(PlatformMethods *platform, const char *name, bool sample);
+inline void DefaultHistogramBoolean(PlatformMethods *platform, const char *name, bool sample)
+{
+}
-typedef angle::Platform *(ANGLE_APIENTRY *ANGLEPlatformCurrentFunc)();
-ANGLE_PLATFORM_EXPORT angle::Platform *ANGLE_APIENTRY ANGLEPlatformCurrent();
+// Allows us to programatically override ANGLE's default workarounds for testing purposes.
+using OverrideWorkaroundsD3DFunc = void (*)(PlatformMethods *platform,
+ angle::WorkaroundsD3D *workaroundsD3D);
+inline void DefaultOverrideWorkaroundsD3D(PlatformMethods *platform,
+ angle::WorkaroundsD3D *workaroundsD3D)
+{
+}
+// Callback on a successful program link with the program binary. Can be used to store
+// shaders to disk. Keys are a 160-bit SHA-1 hash.
+using ProgramKeyType = std::array<uint8_t, 20>;
+using CacheProgramFunc = void (*)(PlatformMethods *platform,
+ const ProgramKeyType &key,
+ size_t programSize,
+ const uint8_t *programBytes);
+inline void DefaultCacheProgram(PlatformMethods *platform,
+ const ProgramKeyType &key,
+ size_t programSize,
+ const uint8_t *programBytes)
+{
}
+// Platform methods are enumerated here once.
+#define ANGLE_PLATFORM_OP(OP) \
+ OP(currentTime, CurrentTime) \
+ OP(monotonicallyIncreasingTime, MonotonicallyIncreasingTime) \
+ OP(logError, LogError) \
+ OP(logWarning, LogWarning) \
+ OP(logInfo, LogInfo) \
+ OP(getTraceCategoryEnabledFlag, GetTraceCategoryEnabledFlag) \
+ OP(addTraceEvent, AddTraceEvent) \
+ OP(updateTraceEventDuration, UpdateTraceEventDuration) \
+ OP(histogramCustomCounts, HistogramCustomCounts) \
+ OP(histogramEnumeration, HistogramEnumeration) \
+ OP(histogramSparse, HistogramSparse) \
+ OP(histogramBoolean, HistogramBoolean) \
+ OP(overrideWorkaroundsD3D, OverrideWorkaroundsD3D) \
+ OP(cacheProgram, CacheProgram)
+
+#define ANGLE_PLATFORM_METHOD_DEF(Name, CapsName) CapsName##Func Name = Default##CapsName;
+
+struct ANGLE_PLATFORM_EXPORT PlatformMethods
+{
+ PlatformMethods();
+
+ // User data pointer for any implementation specific members. Put it at the start of the
+ // platform structure so it doesn't become overwritten if one version of the platform
+ // adds or removes new members.
+ void *context = 0;
+
+ ANGLE_PLATFORM_OP(ANGLE_PLATFORM_METHOD_DEF);
+};
+
+#undef ANGLE_PLATFORM_METHOD_DEF
+
+// Subtract one to account for the context pointer.
+constexpr unsigned int g_NumPlatformMethods = (sizeof(PlatformMethods) / sizeof(uintptr_t)) - 1;
+
+#define ANGLE_PLATFORM_METHOD_STRING(Name) #Name
+#define ANGLE_PLATFORM_METHOD_STRING2(Name, CapsName) ANGLE_PLATFORM_METHOD_STRING(Name),
+
+constexpr const char *const g_PlatformMethodNames[g_NumPlatformMethods] = {
+ ANGLE_PLATFORM_OP(ANGLE_PLATFORM_METHOD_STRING2)};
+
+#undef ANGLE_PLATFORM_METHOD_STRING2
+#undef ANGLE_PLATFORM_METHOD_STRING
+
+} // namespace angle
+
+extern "C" {
+
+// Gets the platform methods on the passed-in EGL display. If the method name signature does not
+// match the compiled signature for this ANGLE, false is returned. On success true is returned.
+// The application should set any platform methods it cares about on the returned pointer.
+// If display is not valid, behaviour is undefined.
+
+ANGLE_PLATFORM_EXPORT bool ANGLE_APIENTRY ANGLEGetDisplayPlatform(angle::EGLDisplayType display,
+ const char *const methodNames[],
+ unsigned int methodNameCount,
+ void *context,
+ void *platformMethodsOut);
+
+// Sets the platform methods back to their defaults.
+// If display is not valid, behaviour is undefined.
+ANGLE_PLATFORM_EXPORT void ANGLE_APIENTRY ANGLEResetDisplayPlatform(angle::EGLDisplayType display);
+
+} // extern "C"
+
+namespace angle
+{
+typedef bool(ANGLE_APIENTRY *GetDisplayPlatformFunc)(angle::EGLDisplayType,
+ const char *const *,
+ unsigned int,
+ void *,
+ void *);
+typedef void(ANGLE_APIENTRY *ResetDisplayPlatformFunc)(angle::EGLDisplayType);
+} // namespace angle
+
+// This function is not exported
+angle::PlatformMethods *ANGLEPlatformCurrent();
+
#endif // ANGLE_PLATFORM_H
diff --git a/src/3rdparty/angle/include/platform/WorkaroundsD3D.h b/src/3rdparty/angle/include/platform/WorkaroundsD3D.h
new file mode 100644
index 0000000000..cc2abbf1d2
--- /dev/null
+++ b/src/3rdparty/angle/include/platform/WorkaroundsD3D.h
@@ -0,0 +1,130 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// WorkaroundsD3D.h: Workarounds for D3D driver bugs and other issues.
+
+#ifndef ANGLE_PLATFORM_WORKAROUNDSD3D_H_
+#define ANGLE_PLATFORM_WORKAROUNDSD3D_H_
+
+// TODO(jmadill,zmo,geofflang): make a workarounds library that can operate
+// independent of ANGLE's renderer. Workarounds should also be accessible
+// outside of the Renderer.
+
+namespace angle
+{
+struct CompilerWorkaroundsD3D
+{
+ bool skipOptimization = false;
+ bool useMaxOptimization = false;
+
+ // IEEE strictness needs to be enabled for NANs to work.
+ bool enableIEEEStrictness = false;
+};
+
+struct WorkaroundsD3D
+{
+ // On some systems, having extra rendertargets than necessary slows down the shader.
+ // We can fix this by optimizing those out of the shader. At the same time, we can
+ // work around a bug on some nVidia drivers that they ignore "null" render targets
+ // in D3D11, by compacting the active color attachments list to omit null entries.
+ bool mrtPerfWorkaround = false;
+
+ bool setDataFasterThanImageUpload = false;
+
+ // Some renderers can't disable mipmaps on a mipmapped texture (i.e. solely sample from level
+ // zero, and ignore the other levels). D3D11 Feature Level 10+ does this by setting MaxLOD to
+ // 0.0f in the Sampler state. D3D9 sets D3DSAMP_MIPFILTER to D3DTEXF_NONE. There is no
+ // equivalent to this in D3D11 Feature Level 9_3. This causes problems when (for example) an
+ // application creates a mipmapped texture2D, but sets GL_TEXTURE_MIN_FILTER to GL_NEAREST
+ // (i.e disables mipmaps). To work around this, D3D11 FL9_3 has to create two copies of the
+ // texture. The textures' level zeros are identical, but only one texture has mips.
+ bool zeroMaxLodWorkaround = false;
+
+ // Some renderers do not support Geometry Shaders so the Geometry Shader-based PointSprite
+ // emulation will not work. To work around this, D3D11 FL9_3 has to use a different pointsprite
+ // emulation that is implemented using instanced quads.
+ bool useInstancedPointSpriteEmulation = false;
+
+ // A bug fixed in NVIDIA driver version 347.88 < x <= 368.81 triggers a TDR when using
+ // CopySubresourceRegion from a staging texture to a depth/stencil in D3D11. The workaround
+ // is to use UpdateSubresource to trigger an extra copy. We disable this workaround on newer
+ // NVIDIA driver versions because of a second driver bug present with the workaround enabled.
+ // (See: http://anglebug.com/1452)
+ bool depthStencilBlitExtraCopy = false;
+
+ // The HLSL optimizer has a bug with optimizing "pow" in certain integer-valued expressions.
+ // We can work around this by expanding the pow into a series of multiplies if we're running
+ // under the affected compiler.
+ bool expandIntegerPowExpressions = false;
+
+ // NVIDIA drivers sometimes write out-of-order results to StreamOut buffers when transform
+ // feedback is used to repeatedly write to the same buffer positions.
+ bool flushAfterEndingTransformFeedback = false;
+
+ // Some drivers (NVIDIA) do not take into account the base level of the texture in the results
+ // of the HLSL GetDimensions builtin.
+ bool getDimensionsIgnoresBaseLevel = false;
+
+ // On some Intel drivers, HLSL's function texture.Load returns 0 when the parameter Location
+ // is negative, even if the sum of Offset and Location is in range. This may cause errors when
+ // translating GLSL's function texelFetchOffset into texture.Load, as it is valid for
+ // texelFetchOffset to use negative texture coordinates as its parameter P when the sum of P
+ // and Offset is in range. To work around this, we translate texelFetchOffset into texelFetch
+ // by adding Offset directly to Location before reading the texture.
+ bool preAddTexelFetchOffsets = false;
+
+ // On some AMD drivers, 1x1 and 2x2 mips of depth/stencil textures aren't sampled correctly.
+ // We can work around this bug by doing an internal blit to a temporary single-channel texture
+ // before we sample.
+ bool emulateTinyStencilTextures = false;
+
+ // In Intel driver, the data with format DXGI_FORMAT_B5G6R5_UNORM will be parsed incorrectly.
+ // This workaroud will disable B5G6R5 support when it's Intel driver. By default, it will use
+ // R8G8B8A8 format. This bug is fixed in version 4539 on Intel drivers.
+ bool disableB5G6R5Support = false;
+
+ // On some Intel drivers, evaluating unary minus operator on integer may get wrong answer in
+ // vertex shaders. To work around this bug, we translate -(int) into ~(int)+1.
+ // This driver bug is fixed in 20.19.15.4624.
+ bool rewriteUnaryMinusOperator = false;
+
+ // On some Intel drivers, using isnan() on highp float will get wrong answer. To work around
+ // this bug, we use an expression to emulate function isnan().
+ // Tracking bug: https://crbug.com/650547
+ // This driver bug is fixed in 21.20.16.4542.
+ bool emulateIsnanFloat = false;
+
+ // On some Intel drivers, using clear() may not take effect. To work around this bug, we call
+ // clear() twice on these platforms.
+ // Tracking bug: https://crbug.com/655534
+ bool callClearTwice = false;
+
+ // On some Intel drivers, copying from staging storage to constant buffer storage does not
+ // seem to work. Work around this by keeping system memory storage as a canonical reference
+ // for buffer data.
+ // D3D11-only workaround. See http://crbug.com/593024.
+ bool useSystemMemoryForConstantBuffers = false;
+
+ // This workaround is for the ANGLE_multiview extension. If enabled the viewport or render
+ // target slice will be selected in the geometry shader stage. The workaround flag is added to
+ // make it possible to select the code path in end2end and performance tests.
+ bool selectViewInGeometryShader = false;
+
+ // When rendering with no render target on D3D, two bugs lead to incorrect behavior on Intel
+ // drivers < 4815. The rendering samples always pass neglecting discard statements in pixel
+ // shader.
+ // 1. If rendertarget is not set, the pixel shader will be recompiled to drop 'SV_TARGET'.
+ // When using a pixel shader with no 'SV_TARGET' in a draw, the pixels are always generated even
+ // if they should be discard by 'discard' statements.
+ // 2. If ID3D11BlendState.RenderTarget[].RenderTargetWriteMask is 0 and rendertarget is not set,
+ // then rendering samples also pass neglecting discard statements in pixel shader.
+ // So we add a dummy texture as render target in such case. See http://anglebug.com/2152
+ bool addDummyTextureNoRenderTarget = false;
+};
+
+} // namespace angle
+
+#endif // ANGLE_PLATFORM_WORKAROUNDSD3D_H_
diff --git a/src/3rdparty/angle/qt_attribution.json b/src/3rdparty/angle/qt_attribution.json
index e35e1f0eb9..b10343d945 100644
--- a/src/3rdparty/angle/qt_attribution.json
+++ b/src/3rdparty/angle/qt_attribution.json
@@ -5,6 +5,10 @@
"QDocModule": "qtgui",
"QtUsage": "Used on Windows to implement OpenGL ES on top of DirectX. Configure with -no-opengl, or -opengl desktop to exclude.",
+ "Description": "The ANGLE library translates OpenGL ES API calls to hardware-supported APIs.",
+ "Homepage": "http://angleproject.org/",
+ "Version": "chromium/3280",
+
"License": "BSD 3-clause \"New\" or \"Revised\" License",
"LicenseId": "BSD-3-Clause",
"LicenseFile": "LICENSE",
diff --git a/src/3rdparty/angle/src/common/BitSetIterator.h b/src/3rdparty/angle/src/common/BitSetIterator.h
deleted file mode 100644
index 3248ce44c9..0000000000
--- a/src/3rdparty/angle/src/common/BitSetIterator.h
+++ /dev/null
@@ -1,156 +0,0 @@
-//
-// Copyright 2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// BitSetIterator:
-// A helper class to quickly bitscan bitsets for set bits.
-//
-
-#ifndef COMMON_BITSETITERATOR_H_
-#define COMMON_BITSETITERATOR_H_
-
-#include <stdint.h>
-
-#include <bitset>
-
-#include "common/angleutils.h"
-#include "common/debug.h"
-#include "common/mathutil.h"
-#include "common/platform.h"
-
-namespace angle
-{
-template <size_t N>
-class BitSetIterator final
-{
- public:
- BitSetIterator(const std::bitset<N> &bitset);
- BitSetIterator(const BitSetIterator &other);
- BitSetIterator &operator=(const BitSetIterator &other);
-
- class Iterator final
- {
- public:
- Iterator(const std::bitset<N> &bits);
- Iterator &operator++();
-
- bool operator==(const Iterator &other) const;
- bool operator!=(const Iterator &other) const;
- unsigned long operator*() const { return mCurrentBit; }
-
- private:
- unsigned long getNextBit();
-
- static const size_t BitsPerWord = sizeof(unsigned long) * 8;
- std::bitset<N> mBits;
- unsigned long mCurrentBit;
- unsigned long mOffset;
- };
-
- Iterator begin() const { return Iterator(mBits); }
- Iterator end() const { return Iterator(std::bitset<N>(0)); }
-
- private:
- const std::bitset<N> mBits;
-};
-
-template <size_t N>
-BitSetIterator<N>::BitSetIterator(const std::bitset<N> &bitset)
- : mBits(bitset)
-{
-}
-
-template <size_t N>
-BitSetIterator<N>::BitSetIterator(const BitSetIterator &other)
- : mBits(other.mBits)
-{
-}
-
-template <size_t N>
-BitSetIterator<N> &BitSetIterator<N>::operator=(const BitSetIterator &other)
-{
- mBits = other.mBits;
- return *this;
-}
-
-template <size_t N>
-BitSetIterator<N>::Iterator::Iterator(const std::bitset<N> &bits)
- : mBits(bits), mCurrentBit(0), mOffset(0)
-{
- if (bits.any())
- {
- mCurrentBit = getNextBit();
- }
- else
- {
- mOffset = static_cast<unsigned long>(rx::roundUp(N, BitsPerWord));
- }
-}
-
-template <size_t N>
-typename BitSetIterator<N>::Iterator &BitSetIterator<N>::Iterator::operator++()
-{
- ASSERT(mBits.any());
- mBits.set(mCurrentBit - mOffset, 0);
- mCurrentBit = getNextBit();
- return *this;
-}
-
-inline unsigned long ScanForward(unsigned long bits)
-{
- ASSERT(bits != 0);
-#if defined(ANGLE_PLATFORM_WINDOWS)
- unsigned long firstBitIndex = 0ul;
- unsigned char ret = _BitScanForward(&firstBitIndex, bits);
- ASSERT(ret != 0);
- UNUSED_ASSERTION_VARIABLE(ret);
- return firstBitIndex;
-#elif defined(ANGLE_PLATFORM_POSIX)
- return static_cast<unsigned long>(__builtin_ctzl(bits));
-#else
-#error Please implement bit-scan-forward for your platform!
-#endif
-}
-
-template <size_t N>
-bool BitSetIterator<N>::Iterator::operator==(const Iterator &other) const
-{
- return mOffset == other.mOffset && mBits == other.mBits;
-}
-
-template <size_t N>
-bool BitSetIterator<N>::Iterator::operator!=(const Iterator &other) const
-{
- return !(*this == other);
-}
-
-template <size_t N>
-unsigned long BitSetIterator<N>::Iterator::getNextBit()
-{
- static std::bitset<N> wordMask(std::numeric_limits<unsigned long>::max());
-
- while (mOffset < N)
- {
- unsigned long wordBits = (mBits & wordMask).to_ulong();
- if (wordBits != 0ul)
- {
- return ScanForward(wordBits) + mOffset;
- }
-
- mBits >>= BitsPerWord;
- mOffset += BitsPerWord;
- }
- return 0;
-}
-
-// Helper to avoid needing to specify the template parameter size
-template <size_t N>
-BitSetIterator<N> IterateBitSet(const std::bitset<N> &bitset)
-{
- return BitSetIterator<N>(bitset);
-}
-
-} // angle
-
-#endif // COMMON_BITSETITERATOR_H_
diff --git a/src/3rdparty/angle/src/common/Color.h b/src/3rdparty/angle/src/common/Color.h
new file mode 100644
index 0000000000..2b4d2f6fba
--- /dev/null
+++ b/src/3rdparty/angle/src/common/Color.h
@@ -0,0 +1,53 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Color.h : Defines the Color type used throughout the ANGLE libraries
+
+#ifndef COMMON_COLOR_H_
+#define COMMON_COLOR_H_
+
+namespace angle
+{
+
+template <typename T>
+struct Color
+{
+ T red;
+ T green;
+ T blue;
+ T alpha;
+
+ Color();
+ Color(T r, T g, T b, T a);
+};
+
+template <typename T>
+bool operator==(const Color<T> &a, const Color<T> &b);
+
+template <typename T>
+bool operator!=(const Color<T> &a, const Color<T> &b);
+
+typedef Color<float> ColorF;
+typedef Color<int> ColorI;
+typedef Color<unsigned int> ColorUI;
+
+} // namespace angle
+
+// TODO: Move this fully into the angle namespace
+namespace gl
+{
+
+template <typename T>
+using Color = angle::Color<T>;
+using ColorF = angle::ColorF;
+using ColorI = angle::ColorI;
+using ColorUI = angle::ColorUI;
+
+} // namespace gl
+
+#include "Color.inl"
+
+#endif // COMMON_COLOR_H_
diff --git a/src/3rdparty/angle/src/common/Color.inl b/src/3rdparty/angle/src/common/Color.inl
new file mode 100644
index 0000000000..c3073256b5
--- /dev/null
+++ b/src/3rdparty/angle/src/common/Color.inl
@@ -0,0 +1,37 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Color.inl : Inline definitions of some functions from Color.h
+
+namespace angle
+{
+
+template <typename T>
+Color<T>::Color() : Color(0, 0, 0, 0)
+{
+}
+
+template <typename T>
+Color<T>::Color(T r, T g, T b, T a) : red(r), green(g), blue(b), alpha(a)
+{
+}
+
+template <typename T>
+bool operator==(const Color<T> &a, const Color<T> &b)
+{
+ return a.red == b.red &&
+ a.green == b.green &&
+ a.blue == b.blue &&
+ a.alpha == b.alpha;
+}
+
+template <typename T>
+bool operator!=(const Color<T> &a, const Color<T> &b)
+{
+ return !(a == b);
+}
+
+} // namespace angle
diff --git a/src/3rdparty/angle/src/common/MemoryBuffer.cpp b/src/3rdparty/angle/src/common/MemoryBuffer.cpp
index e7a3fb4a2b..6f5188c69c 100644
--- a/src/3rdparty/angle/src/common/MemoryBuffer.cpp
+++ b/src/3rdparty/angle/src/common/MemoryBuffer.cpp
@@ -11,19 +11,18 @@
#include "common/debug.h"
-namespace rx
+namespace angle
{
-MemoryBuffer::MemoryBuffer()
- : mSize(0),
- mData(NULL)
+// MemoryBuffer implementation.
+MemoryBuffer::MemoryBuffer() : mSize(0), mData(nullptr)
{
}
MemoryBuffer::~MemoryBuffer()
{
free(mData);
- mData = NULL;
+ mData = nullptr;
}
bool MemoryBuffer::resize(size_t size)
@@ -31,7 +30,7 @@ bool MemoryBuffer::resize(size_t size)
if (size == 0)
{
free(mData);
- mData = NULL;
+ mData = nullptr;
mSize = 0;
return true;
}
@@ -42,8 +41,8 @@ bool MemoryBuffer::resize(size_t size)
}
// Only reallocate if the size has changed.
- uint8_t *newMemory = reinterpret_cast<uint8_t*>(malloc(sizeof(uint8_t) * size));
- if (newMemory == NULL)
+ uint8_t *newMemory = reinterpret_cast<uint8_t *>(malloc(sizeof(uint8_t) * size));
+ if (newMemory == nullptr)
{
return false;
}
@@ -61,20 +60,96 @@ bool MemoryBuffer::resize(size_t size)
return true;
}
-size_t MemoryBuffer::size() const
+void MemoryBuffer::fill(uint8_t datum)
{
- return mSize;
+ if (!empty())
+ {
+ std::fill(mData, mData + mSize, datum);
+ }
+}
+
+MemoryBuffer::MemoryBuffer(MemoryBuffer &&other) : MemoryBuffer()
+{
+ *this = std::move(other);
}
-const uint8_t *MemoryBuffer::data() const
+MemoryBuffer &MemoryBuffer::operator=(MemoryBuffer &&other)
{
- return mData;
+ std::swap(mSize, other.mSize);
+ std::swap(mData, other.mData);
+ return *this;
}
-uint8_t *MemoryBuffer::data()
+// ScratchBuffer implementation.
+
+ScratchBuffer::ScratchBuffer(uint32_t lifetime) : mLifetime(lifetime), mResetCounter(lifetime)
{
- ASSERT(mData);
- return mData;
}
+ScratchBuffer::~ScratchBuffer()
+{
+}
+
+bool ScratchBuffer::get(size_t requestedSize, MemoryBuffer **memoryBufferOut)
+{
+ return getImpl(requestedSize, memoryBufferOut, Optional<uint8_t>::Invalid());
}
+
+bool ScratchBuffer::getInitialized(size_t requestedSize,
+ MemoryBuffer **memoryBufferOut,
+ uint8_t initValue)
+{
+ return getImpl(requestedSize, memoryBufferOut, Optional<uint8_t>(initValue));
+}
+
+bool ScratchBuffer::getImpl(size_t requestedSize,
+ MemoryBuffer **memoryBufferOut,
+ Optional<uint8_t> initValue)
+{
+ if (mScratchMemory.size() == requestedSize)
+ {
+ mResetCounter = mLifetime;
+ *memoryBufferOut = &mScratchMemory;
+ return true;
+ }
+
+ if (mScratchMemory.size() > requestedSize)
+ {
+ tick();
+ }
+
+ if (mResetCounter == 0 || mScratchMemory.size() < requestedSize)
+ {
+ mScratchMemory.resize(0);
+ if (!mScratchMemory.resize(requestedSize))
+ {
+ return false;
+ }
+ mResetCounter = mLifetime;
+ if (initValue.valid())
+ {
+ mScratchMemory.fill(initValue.value());
+ }
+ }
+
+ ASSERT(mScratchMemory.size() >= requestedSize);
+
+ *memoryBufferOut = &mScratchMemory;
+ return true;
+}
+
+void ScratchBuffer::tick()
+{
+ if (mResetCounter > 0)
+ {
+ --mResetCounter;
+ }
+}
+
+void ScratchBuffer::clear()
+{
+ mResetCounter = mLifetime;
+ mScratchMemory.resize(0);
+}
+
+} // namespace angle
diff --git a/src/3rdparty/angle/src/common/MemoryBuffer.h b/src/3rdparty/angle/src/common/MemoryBuffer.h
index ec621cbca7..f76b9ee62e 100644
--- a/src/3rdparty/angle/src/common/MemoryBuffer.h
+++ b/src/3rdparty/angle/src/common/MemoryBuffer.h
@@ -7,32 +7,71 @@
#ifndef COMMON_MEMORYBUFFER_H_
#define COMMON_MEMORYBUFFER_H_
+#include "common/Optional.h"
#include "common/angleutils.h"
+#include "common/debug.h"
-#include <cstddef>
#include <stdint.h>
+#include <cstddef>
-namespace rx
+namespace angle
{
-class MemoryBuffer : angle::NonCopyable
+class MemoryBuffer final : NonCopyable
{
public:
MemoryBuffer();
~MemoryBuffer();
+ MemoryBuffer(MemoryBuffer &&other);
+ MemoryBuffer &operator=(MemoryBuffer &&other);
+
bool resize(size_t size);
- size_t size() const;
+ size_t size() const { return mSize; }
bool empty() const { return mSize == 0; }
- const uint8_t *data() const;
- uint8_t *data();
+ const uint8_t *data() const { return mData; }
+ uint8_t *data()
+ {
+ ASSERT(mData);
+ return mData;
+ }
+
+ void fill(uint8_t datum);
private:
size_t mSize;
uint8_t *mData;
};
-}
+class ScratchBuffer final : NonCopyable
+{
+ public:
+ // If we request a scratch buffer requesting a smaller size this many times, release and
+ // recreate the scratch buffer. This ensures we don't have a degenerate case where we are stuck
+ // hogging memory.
+ ScratchBuffer(uint32_t lifetime);
+ ~ScratchBuffer();
+
+ // Returns true with a memory buffer of the requested size, or false on failure.
+ bool get(size_t requestedSize, MemoryBuffer **memoryBufferOut);
+
+ // Same as get, but ensures new values are initialized to a fixed constant.
+ bool getInitialized(size_t requestedSize, MemoryBuffer **memoryBufferOut, uint8_t initValue);
+
+ // Ticks the release counter for the scratch buffer. Also done implicitly in get().
+ void tick();
+
+ void clear();
+
+ private:
+ bool getImpl(size_t requestedSize, MemoryBuffer **memoryBufferOut, Optional<uint8_t> initValue);
+
+ const uint32_t mLifetime;
+ uint32_t mResetCounter;
+ MemoryBuffer mScratchMemory;
+};
+
+} // namespace angle
-#endif // COMMON_MEMORYBUFFER_H_
+#endif // COMMON_MEMORYBUFFER_H_
diff --git a/src/3rdparty/angle/src/common/Optional.h b/src/3rdparty/angle/src/common/Optional.h
index 256f38f329..822de4de51 100644
--- a/src/3rdparty/angle/src/common/Optional.h
+++ b/src/3rdparty/angle/src/common/Optional.h
@@ -10,23 +10,16 @@
#ifndef COMMON_OPTIONAL_H_
#define COMMON_OPTIONAL_H_
+#include <utility>
+
template <class T>
struct Optional
{
- Optional()
- : mValid(false),
- mValue(T())
- {}
+ Optional() : mValid(false), mValue(T()) {}
- explicit Optional(const T &valueIn)
- : mValid(true),
- mValue(valueIn)
- {}
+ Optional(const T &valueIn) : mValid(true), mValue(valueIn) {}
- Optional(const Optional &other)
- : mValid(other.mValid),
- mValue(other.mValue)
- {}
+ Optional(const Optional &other) : mValid(other.mValid), mValue(other.mValue) {}
Optional &operator=(const Optional &other)
{
@@ -49,10 +42,7 @@ struct Optional
return *this;
}
- void reset()
- {
- mValid = false;
- }
+ void reset() { mValid = false; }
static Optional Invalid() { return Optional(); }
@@ -64,14 +54,15 @@ struct Optional
return ((mValid == other.mValid) && (!mValid || (mValue == other.mValue)));
}
- bool operator!=(const Optional &other) const
- {
- return !(*this == other);
- }
+ bool operator!=(const Optional &other) const { return !(*this == other); }
+
+ bool operator==(const T &value) const { return mValid && (mValue == value); }
+
+ bool operator!=(const T &value) const { return !(*this == value); }
private:
bool mValid;
T mValue;
};
-#endif // COMMON_OPTIONAL_H_
+#endif // COMMON_OPTIONAL_H_
diff --git a/src/3rdparty/angle/src/common/angleutils.cpp b/src/3rdparty/angle/src/common/angleutils.cpp
index 7099c21730..739d12a767 100644
--- a/src/3rdparty/angle/src/common/angleutils.cpp
+++ b/src/3rdparty/angle/src/common/angleutils.cpp
@@ -14,39 +14,61 @@
namespace angle
{
+// dirtyPointer is a special value that will make the comparison with any valid pointer fail and
+// force the renderer to re-apply the state.
const uintptr_t DirtyPointer = std::numeric_limits<uintptr_t>::max();
}
+std::string ArrayString(unsigned int i)
+{
+ // We assume that UINT_MAX and GL_INVALID_INDEX are equal.
+ ASSERT(i != UINT_MAX);
+
+ std::stringstream strstr;
+ strstr << "[";
+ strstr << i;
+ strstr << "]";
+ return strstr.str();
+}
+
+std::string ArrayIndexString(const std::vector<unsigned int> &indices)
+{
+ std::stringstream strstr;
+
+ for (auto indicesIt = indices.rbegin(); indicesIt != indices.rend(); ++indicesIt)
+ {
+ // We assume that UINT_MAX and GL_INVALID_INDEX are equal.
+ ASSERT(*indicesIt != UINT_MAX);
+ strstr << "[";
+ strstr << (*indicesIt);
+ strstr << "]";
+ }
+
+ return strstr.str();
+}
+
size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char>& outBuffer)
{
+ // The state of the va_list passed to vsnprintf is undefined after the call, do a copy in case
+ // we need to grow the buffer.
+ va_list varargCopy;
+ va_copy(varargCopy, vararg);
+
// Attempt to just print to the current buffer
- int len = vsnprintf(&(outBuffer.front()), outBuffer.size(), fmt, vararg);
+ int len = vsnprintf(&(outBuffer.front()), outBuffer.size(), fmt, varargCopy);
+ va_end(varargCopy);
+
if (len < 0 || static_cast<size_t>(len) >= outBuffer.size())
{
// Buffer was not large enough, calculate the required size and resize the buffer
- len = vsnprintf(NULL, 0, fmt, vararg);
+ len = vsnprintf(nullptr, 0, fmt, vararg);
outBuffer.resize(len + 1);
// Print again
- len = vsnprintf(&(outBuffer.front()), outBuffer.size(), fmt, vararg);
+ va_copy(varargCopy, vararg);
+ len = vsnprintf(&(outBuffer.front()), outBuffer.size(), fmt, varargCopy);
+ va_end(varargCopy);
}
ASSERT(len >= 0);
return static_cast<size_t>(len);
}
-
-std::string FormatString(const char *fmt, va_list vararg)
-{
- static std::vector<char> buffer(512);
-
- size_t len = FormatStringIntoVector(fmt, vararg, buffer);
- return std::string(&buffer[0], len);
-}
-
-std::string FormatString(const char *fmt, ...)
-{
- va_list vararg;
- va_start(vararg, fmt);
- std::string result = FormatString(fmt, vararg);
- va_end(vararg);
- return result;
-}
diff --git a/src/3rdparty/angle/src/common/angleutils.h b/src/3rdparty/angle/src/common/angleutils.h
index a0178fd414..ad32a2f03a 100644
--- a/src/3rdparty/angle/src/common/angleutils.h
+++ b/src/3rdparty/angle/src/common/angleutils.h
@@ -23,25 +23,59 @@
namespace angle
{
+#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
+using Microsoft::WRL::ComPtr;
+#endif // defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
+
class NonCopyable
{
- public:
+ protected:
NonCopyable() = default;
~NonCopyable() = default;
- protected:
+
+ private:
NonCopyable(const NonCopyable&) = delete;
void operator=(const NonCopyable&) = delete;
};
extern const uintptr_t DirtyPointer;
-}
+
+} // namespace angle
template <typename T, size_t N>
-inline size_t ArraySize(T(&)[N])
+constexpr inline size_t ArraySize(T (&)[N])
{
return N;
}
+template <typename T>
+class WrappedArray final : angle::NonCopyable
+{
+ public:
+ template <size_t N>
+ constexpr WrappedArray(const T (&data)[N]) : mArray(&data[0]), mSize(N)
+ {
+ }
+
+ constexpr WrappedArray() : mArray(nullptr), mSize(0) {}
+ constexpr WrappedArray(const T *data, size_t size) : mArray(data), mSize(size) {}
+
+ WrappedArray(WrappedArray &&other) : WrappedArray()
+ {
+ std::swap(mArray, other.mArray);
+ std::swap(mSize, other.mSize);
+ }
+
+ ~WrappedArray() {}
+
+ constexpr const T *get() const { return mArray; }
+ constexpr size_t size() const { return mSize; }
+
+ private:
+ const T *mArray;
+ size_t mSize;
+};
+
template <typename T, unsigned int N>
void SafeRelease(T (&resourceBlock)[N])
{
@@ -57,15 +91,15 @@ void SafeRelease(T& resource)
if (resource)
{
resource->Release();
- resource = NULL;
+ resource = nullptr;
}
}
template <typename T>
-void SafeDelete(T*& resource)
+void SafeDelete(T *&resource)
{
delete resource;
- resource = NULL;
+ resource = nullptr;
}
template <typename T>
@@ -82,7 +116,7 @@ template <typename T>
void SafeDeleteArray(T*& resource)
{
delete[] resource;
- resource = NULL;
+ resource = nullptr;
}
// Provide a less-than function for comparing structs
@@ -126,23 +160,11 @@ inline const char* MakeStaticString(const std::string &str)
return strings.insert(str).first->c_str();
}
-inline std::string ArrayString(unsigned int i)
-{
- // We assume UINT_MAX and GL_INVALID_INDEX are equal
- // See DynamicHLSL.cpp
- if (i == UINT_MAX)
- {
- return "";
- }
+std::string ArrayString(unsigned int i);
- std::stringstream strstr;
-
- strstr << "[";
- strstr << i;
- strstr << "]";
-
- return strstr.str();
-}
+// Indices are stored in vectors with the outermost index in the back. In the output of the function
+// the indices are reversed.
+std::string ArrayIndexString(const std::vector<unsigned int> &indices);
inline std::string Str(int i)
{
@@ -156,17 +178,76 @@ size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char>
std::string FormatString(const char *fmt, va_list vararg);
std::string FormatString(const char *fmt, ...);
+template <typename T>
+std::string ToString(const T &value)
+{
+ std::ostringstream o;
+ o << value;
+ return o.str();
+}
+
// snprintf is not defined with MSVC prior to to msvc14
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf
#endif
+#define GL_BGRX8_ANGLEX 0x6ABA
+#define GL_BGR565_ANGLEX 0x6ABB
#define GL_BGRA4_ANGLEX 0x6ABC
#define GL_BGR5_A1_ANGLEX 0x6ABD
#define GL_INT_64_ANGLEX 0x6ABE
-#define GL_STRUCT_ANGLEX 0x6ABF
+#define GL_UINT_64_ANGLEX 0x6ABF
+#define GL_BGRA8_SRGB_ANGLEX 0x6AC0
// Hidden enum for the NULL D3D device type.
#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE 0x6AC0
+// TODO(jmadill): Clean this up at some point.
+#define EGL_PLATFORM_ANGLE_PLATFORM_METHODS_ANGLEX 0x9999
+
+#define ANGLE_TRY_CHECKED_MATH(result) \
+ if (!result.IsValid()) \
+ { \
+ return gl::InternalError() << "Integer overflow."; \
+ }
+
+// The below inlining code lifted from V8.
+#if defined(__clang__) || (defined(__GNUC__) && defined(__has_attribute))
+#define ANGLE_HAS_ATTRIBUTE_ALWAYS_INLINE (__has_attribute(always_inline))
+#define ANGLE_HAS___FORCEINLINE 0
+#elif defined(_MSC_VER)
+#define ANGLE_HAS_ATTRIBUTE_ALWAYS_INLINE 0
+#define ANGLE_HAS___FORCEINLINE 1
+#else
+#define ANGLE_HAS_ATTRIBUTE_ALWAYS_INLINE 0
+#define ANGLE_HAS___FORCEINLINE 0
+#endif
+
+#if defined(NDEBUG) && ANGLE_HAS_ATTRIBUTE_ALWAYS_INLINE
+#define ANGLE_INLINE inline __attribute__((always_inline))
+#elif defined(NDEBUG) && ANGLE_HAS___FORCEINLINE
+#define ANGLE_INLINE __forceinline
+#else
+#define ANGLE_INLINE inline
+#endif
+
+#ifndef ANGLE_STRINGIFY
+#define ANGLE_STRINGIFY(x) #x
+#endif
+
+#ifndef ANGLE_MACRO_STRINGIFY
+#define ANGLE_MACRO_STRINGIFY(x) ANGLE_STRINGIFY(x)
+#endif
+
+// Detect support for C++17 [[nodiscard]]
+#if !defined(__has_cpp_attribute)
+#define __has_cpp_attribute(name) 0
+#endif // !defined(__has_cpp_attribute)
+
+#if __has_cpp_attribute(nodiscard)
+#define ANGLE_NO_DISCARD [[nodiscard]]
+#else
+#define ANGLE_NO_DISCARD
+#endif // __has_cpp_attribute(nodiscard)
+
#endif // COMMON_ANGLEUTILS_H_
diff --git a/src/3rdparty/angle/src/common/bitset_utils.h b/src/3rdparty/angle/src/common/bitset_utils.h
new file mode 100644
index 0000000000..4166a562a7
--- /dev/null
+++ b/src/3rdparty/angle/src/common/bitset_utils.h
@@ -0,0 +1,498 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// bitset_utils:
+// Bitset-related helper classes, such as a fast iterator to scan for set bits.
+//
+
+#ifndef COMMON_BITSETITERATOR_H_
+#define COMMON_BITSETITERATOR_H_
+
+#include <stdint.h>
+
+#include <bitset>
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+#include "common/mathutil.h"
+#include "common/platform.h"
+
+namespace angle
+{
+
+template <size_t N, typename BitsT>
+class BitSetT final
+{
+ public:
+ class Reference final
+ {
+ public:
+ ~Reference() {}
+ Reference &operator=(bool x)
+ {
+ mParent->set(mBit, x);
+ return *this;
+ }
+ explicit operator bool() const { return mParent->test(mBit); }
+
+ private:
+ friend class BitSetT;
+
+ Reference(BitSetT *parent, std::size_t bit) : mParent(parent), mBit(bit) {}
+
+ BitSetT *mParent;
+ std::size_t mBit;
+ };
+
+ class Iterator final
+ {
+ public:
+ Iterator(const BitSetT &bits);
+ Iterator &operator++();
+
+ bool operator==(const Iterator &other) const;
+ bool operator!=(const Iterator &other) const;
+ std::size_t operator*() const;
+
+ private:
+ std::size_t getNextBit();
+
+ BitSetT mBitsCopy;
+ std::size_t mCurrentBit;
+ };
+
+ BitSetT();
+ BitSetT(BitsT value);
+ ~BitSetT();
+
+ BitSetT(const BitSetT &other);
+ BitSetT &operator=(const BitSetT &other);
+
+ bool operator==(const BitSetT &other) const;
+ bool operator!=(const BitSetT &other) const;
+
+ constexpr bool operator[](std::size_t pos) const;
+ Reference operator[](std::size_t pos) { return Reference(this, pos); }
+
+ bool test(std::size_t pos) const;
+
+ bool all() const;
+ bool any() const;
+ bool none() const;
+ std::size_t count() const;
+
+ constexpr std::size_t size() const { return N; }
+
+ BitSetT &operator&=(const BitSetT &other);
+ BitSetT &operator|=(const BitSetT &other);
+ BitSetT &operator^=(const BitSetT &other);
+ BitSetT operator~() const;
+
+ BitSetT operator<<(std::size_t pos) const;
+ BitSetT &operator<<=(std::size_t pos);
+ BitSetT operator>>(std::size_t pos) const;
+ BitSetT &operator>>=(std::size_t pos);
+
+ BitSetT &set();
+ BitSetT &set(std::size_t pos, bool value = true);
+
+ BitSetT &reset();
+ BitSetT &reset(std::size_t pos);
+
+ BitSetT &flip();
+ BitSetT &flip(std::size_t pos);
+
+ unsigned long to_ulong() const { return static_cast<unsigned long>(mBits); }
+ BitsT bits() const { return mBits; }
+
+ Iterator begin() const { return Iterator(*this); }
+ Iterator end() const { return Iterator(BitSetT()); }
+
+ private:
+ constexpr static BitsT Bit(std::size_t x) { return (static_cast<BitsT>(1) << x); }
+ constexpr static BitsT Mask(std::size_t x) { return ((Bit(x - 1) - 1) << 1) + 1; }
+
+ BitsT mBits;
+};
+
+template <size_t N>
+class IterableBitSet : public std::bitset<N>
+{
+ public:
+ IterableBitSet() {}
+ IterableBitSet(const std::bitset<N> &implicitBitSet) : std::bitset<N>(implicitBitSet) {}
+
+ class Iterator final
+ {
+ public:
+ Iterator(const std::bitset<N> &bits);
+ Iterator &operator++();
+
+ bool operator==(const Iterator &other) const;
+ bool operator!=(const Iterator &other) const;
+ unsigned long operator*() const { return mCurrentBit; }
+
+ private:
+ unsigned long getNextBit();
+
+ static constexpr size_t BitsPerWord = sizeof(uint32_t) * 8;
+ std::bitset<N> mBits;
+ unsigned long mCurrentBit;
+ unsigned long mOffset;
+ };
+
+ Iterator begin() const { return Iterator(*this); }
+ Iterator end() const { return Iterator(std::bitset<N>(0)); }
+};
+
+template <size_t N>
+IterableBitSet<N>::Iterator::Iterator(const std::bitset<N> &bitset)
+ : mBits(bitset), mCurrentBit(0), mOffset(0)
+{
+ if (mBits.any())
+ {
+ mCurrentBit = getNextBit();
+ }
+ else
+ {
+ mOffset = static_cast<unsigned long>(rx::roundUp(N, BitsPerWord));
+ }
+}
+
+template <size_t N>
+typename IterableBitSet<N>::Iterator &IterableBitSet<N>::Iterator::operator++()
+{
+ ASSERT(mBits.any());
+ mBits.set(mCurrentBit - mOffset, 0);
+ mCurrentBit = getNextBit();
+ return *this;
+}
+
+template <size_t N>
+bool IterableBitSet<N>::Iterator::operator==(const Iterator &other) const
+{
+ return mOffset == other.mOffset && mBits == other.mBits;
+}
+
+template <size_t N>
+bool IterableBitSet<N>::Iterator::operator!=(const Iterator &other) const
+{
+ return !(*this == other);
+}
+
+template <size_t N>
+unsigned long IterableBitSet<N>::Iterator::getNextBit()
+{
+ // TODO(jmadill): Use 64-bit scan when possible.
+ static constexpr std::bitset<N> wordMask(std::numeric_limits<uint32_t>::max());
+
+ while (mOffset < N)
+ {
+ uint32_t wordBits = static_cast<uint32_t>((mBits & wordMask).to_ulong());
+ if (wordBits != 0)
+ {
+ return gl::ScanForward(wordBits) + mOffset;
+ }
+
+ mBits >>= BitsPerWord;
+ mOffset += BitsPerWord;
+ }
+ return 0;
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT>::BitSetT() : mBits(0)
+{
+ static_assert(N > 0, "Bitset type cannot support zero bits.");
+ static_assert(N <= sizeof(BitsT) * 8, "Bitset type cannot support a size this large.");
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT>::BitSetT(BitsT value) : mBits(value & Mask(N))
+{
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT>::~BitSetT()
+{
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT>::BitSetT(const BitSetT &other) : mBits(other.mBits)
+{
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> &BitSetT<N, BitsT>::operator=(const BitSetT &other)
+{
+ mBits = other.mBits;
+ return *this;
+}
+
+template <size_t N, typename BitsT>
+bool BitSetT<N, BitsT>::operator==(const BitSetT &other) const
+{
+ return mBits == other.mBits;
+}
+
+template <size_t N, typename BitsT>
+bool BitSetT<N, BitsT>::operator!=(const BitSetT &other) const
+{
+ return mBits != other.mBits;
+}
+
+template <size_t N, typename BitsT>
+constexpr bool BitSetT<N, BitsT>::operator[](std::size_t pos) const
+{
+ return test(pos);
+}
+
+template <size_t N, typename BitsT>
+bool BitSetT<N, BitsT>::test(std::size_t pos) const
+{
+ return (mBits & Bit(pos)) != 0;
+}
+
+template <size_t N, typename BitsT>
+bool BitSetT<N, BitsT>::all() const
+{
+ ASSERT(mBits == (mBits & Mask(N)));
+ return mBits == Mask(N);
+}
+
+template <size_t N, typename BitsT>
+bool BitSetT<N, BitsT>::any() const
+{
+ ASSERT(mBits == (mBits & Mask(N)));
+ return (mBits != 0);
+}
+
+template <size_t N, typename BitsT>
+bool BitSetT<N, BitsT>::none() const
+{
+ ASSERT(mBits == (mBits & Mask(N)));
+ return (mBits == 0);
+}
+
+template <size_t N, typename BitsT>
+std::size_t BitSetT<N, BitsT>::count() const
+{
+ return gl::BitCount(mBits);
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> &BitSetT<N, BitsT>::operator&=(const BitSetT &other)
+{
+ mBits &= other.mBits;
+ return *this;
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> &BitSetT<N, BitsT>::operator|=(const BitSetT &other)
+{
+ mBits |= other.mBits;
+ return *this;
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> &BitSetT<N, BitsT>::operator^=(const BitSetT &other)
+{
+ mBits = (mBits ^ other.mBits) & Mask(N);
+ return *this;
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> BitSetT<N, BitsT>::operator~() const
+{
+ return BitSetT<N, BitsT>(~mBits & Mask(N));
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> BitSetT<N, BitsT>::operator<<(std::size_t pos) const
+{
+ return BitSetT<N, BitsT>((mBits << pos) & Mask(N));
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> &BitSetT<N, BitsT>::operator<<=(std::size_t pos)
+{
+ mBits = (mBits << pos & Mask(N));
+ return *this;
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> BitSetT<N, BitsT>::operator>>(std::size_t pos) const
+{
+ return BitSetT<N, BitsT>(mBits >> pos);
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> &BitSetT<N, BitsT>::operator>>=(std::size_t pos)
+{
+ mBits = ((mBits >> pos) & Mask(N));
+ return *this;
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> &BitSetT<N, BitsT>::set()
+{
+ mBits = Mask(N);
+ return *this;
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> &BitSetT<N, BitsT>::set(std::size_t pos, bool value)
+{
+ if (value)
+ {
+ mBits |= Bit(pos);
+ }
+ else
+ {
+ reset(pos);
+ }
+ return *this;
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> &BitSetT<N, BitsT>::reset()
+{
+ mBits = 0;
+ return *this;
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> &BitSetT<N, BitsT>::reset(std::size_t pos)
+{
+ mBits &= ~Bit(pos);
+ return *this;
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> &BitSetT<N, BitsT>::flip()
+{
+ mBits ^= Mask(N);
+ return *this;
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT> &BitSetT<N, BitsT>::flip(std::size_t pos)
+{
+ mBits ^= Bit(pos);
+ return *this;
+}
+
+template <size_t N, typename BitsT>
+BitSetT<N, BitsT>::Iterator::Iterator(const BitSetT &bits) : mBitsCopy(bits), mCurrentBit(0)
+{
+ if (bits.any())
+ {
+ mCurrentBit = getNextBit();
+ }
+}
+
+template <size_t N, typename BitsT>
+typename BitSetT<N, BitsT>::Iterator &BitSetT<N, BitsT>::Iterator::operator++()
+{
+ ASSERT(mBitsCopy.any());
+ mBitsCopy.reset(mCurrentBit);
+ mCurrentBit = getNextBit();
+ return *this;
+}
+
+template <size_t N, typename BitsT>
+bool BitSetT<N, BitsT>::Iterator::operator==(const Iterator &other) const
+{
+ return mBitsCopy == other.mBitsCopy;
+}
+
+template <size_t N, typename BitsT>
+bool BitSetT<N, BitsT>::Iterator::operator!=(const Iterator &other) const
+{
+ return !(*this == other);
+}
+
+template <size_t N, typename BitsT>
+std::size_t BitSetT<N, BitsT>::Iterator::operator*() const
+{
+ return mCurrentBit;
+}
+
+template <size_t N, typename BitsT>
+std::size_t BitSetT<N, BitsT>::Iterator::getNextBit()
+{
+ if (mBitsCopy.none())
+ {
+ return 0;
+ }
+
+ return gl::ScanForward(mBitsCopy.mBits);
+}
+
+template <size_t N>
+using BitSet32 = BitSetT<N, uint32_t>;
+
+// ScanForward for 64-bits requires a 64-bit implementation.
+#if defined(ANGLE_IS_64_BIT_CPU)
+template <size_t N>
+using BitSet64 = BitSetT<N, uint64_t>;
+#endif // defined(ANGLE_IS_64_BIT_CPU)
+
+namespace priv
+{
+
+template <size_t N, typename T>
+using EnableIfBitsFit = typename std::enable_if<N <= sizeof(T) * 8>::type;
+
+template <size_t N, typename Enable = void>
+struct GetBitSet
+{
+ using Type = IterableBitSet<N>;
+};
+
+// Prefer 64-bit bitsets on 64-bit CPUs. They seem faster than 32-bit.
+#if defined(ANGLE_IS_64_BIT_CPU)
+template <size_t N>
+struct GetBitSet<N, EnableIfBitsFit<N, uint64_t>>
+{
+ using Type = BitSet64<N>;
+};
+#else
+template <size_t N>
+struct GetBitSet<N, EnableIfBitsFit<N, uint32_t>>
+{
+ using Type = BitSet32<N>;
+};
+#endif // defined(ANGLE_IS_64_BIT_CPU)
+
+} // namespace priv
+
+template <size_t N>
+using BitSet = typename priv::GetBitSet<N>::Type;
+
+} // angle
+
+template <size_t N, typename BitsT>
+inline angle::BitSetT<N, BitsT> operator&(const angle::BitSetT<N, BitsT> &lhs,
+ const angle::BitSetT<N, BitsT> &rhs)
+{
+ return angle::BitSetT<N, BitsT>(lhs.bits() & rhs.bits());
+}
+
+template <size_t N, typename BitsT>
+inline angle::BitSetT<N, BitsT> operator|(const angle::BitSetT<N, BitsT> &lhs,
+ const angle::BitSetT<N, BitsT> &rhs)
+{
+ return angle::BitSetT<N, BitsT>(lhs.bits() | rhs.bits());
+}
+
+template <size_t N, typename BitsT>
+inline angle::BitSetT<N, BitsT> operator^(const angle::BitSetT<N, BitsT> &lhs,
+ const angle::BitSetT<N, BitsT> &rhs)
+{
+ return angle::BitSetT<N, BitsT>(lhs.bits() ^ rhs.bits());
+}
+
+#endif // COMMON_BITSETITERATOR_H_
diff --git a/src/3rdparty/angle/src/common/debug.cpp b/src/3rdparty/angle/src/common/debug.cpp
index 1fcc062908..b02e80be5f 100644
--- a/src/3rdparty/angle/src/common/debug.cpp
+++ b/src/3rdparty/angle/src/common/debug.cpp
@@ -7,92 +7,61 @@
// debug.cpp: Debugging utilities.
#include "common/debug.h"
-#include "common/platform.h"
-#include "common/angleutils.h"
#include <stdarg.h>
-#include <vector>
-#include <fstream>
+
+#include <array>
#include <cstdio>
+#include <fstream>
+#include <ostream>
+#include <vector>
+
+#include "common/angleutils.h"
+#include "common/Optional.h"
namespace gl
{
namespace
{
-enum DebugTraceOutputType
-{
- DebugTraceOutputTypeNone,
- DebugTraceOutputTypeSetMarker,
- DebugTraceOutputTypeBeginEvent
-};
DebugAnnotator *g_debugAnnotator = nullptr;
-void output(bool traceInDebugOnly, MessageType messageType, DebugTraceOutputType outputType,
- const char *format, va_list vararg)
-{
- if (DebugAnnotationsActive())
- {
- static std::vector<char> buffer(512);
- size_t len = FormatStringIntoVector(format, vararg, buffer);
- std::wstring formattedWideMessage(buffer.begin(), buffer.begin() + len);
-
- ASSERT(g_debugAnnotator != nullptr);
- switch (outputType)
- {
- case DebugTraceOutputTypeNone:
- break;
- case DebugTraceOutputTypeBeginEvent:
- g_debugAnnotator->beginEvent(formattedWideMessage.c_str());
- break;
- case DebugTraceOutputTypeSetMarker:
- g_debugAnnotator->setMarker(formattedWideMessage.c_str());
- break;
- }
- }
+constexpr std::array<const char *, LOG_NUM_SEVERITIES> g_logSeverityNames = {
+ {"EVENT", "WARN", "ERR"}};
- std::string formattedMessage;
- UNUSED_VARIABLE(formattedMessage);
+constexpr const char *LogSeverityName(int severity)
+{
+ return (severity >= 0 && severity < LOG_NUM_SEVERITIES) ? g_logSeverityNames[severity]
+ : "UNKNOWN";
+}
-#if !defined(NDEBUG) && defined(_MSC_VER)
- if (messageType == MESSAGE_ERR)
- {
- if (formattedMessage.empty())
- {
- formattedMessage = FormatString(format, vararg);
- }
- OutputDebugStringA(formattedMessage.c_str());
- }
+bool ShouldCreateLogMessage(LogSeverity severity)
+{
+#if defined(ANGLE_TRACE_ENABLED)
+ return true;
+#elif defined(ANGLE_ENABLE_ASSERTS)
+ return severity == LOG_ERR;
+#else
+ return false;
#endif
+}
-#if defined(ANGLE_ENABLE_DEBUG_TRACE)
-#if defined(NDEBUG)
- if (traceInDebugOnly)
- {
- return;
- }
-#endif // NDEBUG
- if (formattedMessage.empty())
- {
- formattedMessage = FormatString(format, vararg);
- }
-
- static std::ofstream file(TRACE_OUTPUT_FILE, std::ofstream::app);
- if (file)
- {
- file.write(formattedMessage.c_str(), formattedMessage.length());
- file.flush();
- }
+} // namespace
-#if defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER)
- OutputDebugStringA(formattedMessage.c_str());
-#endif // ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER
+namespace priv
+{
-#endif // ANGLE_ENABLE_DEBUG_TRACE
+bool ShouldCreatePlatformLogMessage(LogSeverity severity)
+{
+#if defined(ANGLE_TRACE_ENABLED)
+ return true;
+#else
+ return severity != LOG_EVENT;
+#endif
}
-} // namespace
+} // namespace priv
bool DebugAnnotationsActive()
{
@@ -103,6 +72,11 @@ bool DebugAnnotationsActive()
#endif
}
+bool DebugAnnotationsInitialized()
+{
+ return g_debugAnnotator != nullptr;
+}
+
void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator)
{
UninitializeDebugAnnotations();
@@ -115,25 +89,20 @@ void UninitializeDebugAnnotations()
g_debugAnnotator = nullptr;
}
-void trace(bool traceInDebugOnly, MessageType messageType, const char *format, ...)
-{
- va_list vararg;
- va_start(vararg, format);
- output(traceInDebugOnly, messageType, DebugTraceOutputTypeSetMarker, format, vararg);
- va_end(vararg);
-}
-
-ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...)
+ScopedPerfEventHelper::ScopedPerfEventHelper(const char *format, ...)
{
#if !defined(ANGLE_ENABLE_DEBUG_TRACE)
if (!DebugAnnotationsActive())
{
return;
}
-#endif // !ANGLE_ENABLE_DEBUG_TRACE
+#endif // !ANGLE_ENABLE_DEBUG_TRACE
+
va_list vararg;
va_start(vararg, format);
- output(true, MESSAGE_EVENT, DebugTraceOutputTypeBeginEvent, format, vararg);
+ std::vector<char> buffer(512);
+ size_t len = FormatStringIntoVector(format, vararg, buffer);
+ ANGLE_LOG(EVENT) << std::string(&buffer[0], len);
va_end(vararg);
}
@@ -145,4 +114,107 @@ ScopedPerfEventHelper::~ScopedPerfEventHelper()
}
}
+LogMessage::LogMessage(const char *function, int line, LogSeverity severity)
+ : mFunction(function), mLine(line), mSeverity(severity)
+{
+ // EVENT() does not require additional function(line) info.
+ if (mSeverity != LOG_EVENT)
+ {
+ mStream << mFunction << "(" << mLine << "): ";
+ }
+}
+
+LogMessage::~LogMessage()
+{
+ if (DebugAnnotationsInitialized() && (mSeverity == LOG_ERR || mSeverity == LOG_WARN))
+ {
+ g_debugAnnotator->logMessage(*this);
+ }
+ else
+ {
+ Trace(getSeverity(), getMessage().c_str());
+ }
+}
+
+void Trace(LogSeverity severity, const char *message)
+{
+ if (!ShouldCreateLogMessage(severity))
+ {
+ return;
+ }
+
+ std::string str(message);
+
+ if (DebugAnnotationsActive())
+ {
+ std::wstring formattedWideMessage(str.begin(), str.end());
+
+ switch (severity)
+ {
+ case LOG_EVENT:
+ g_debugAnnotator->beginEvent(formattedWideMessage.c_str());
+ break;
+ default:
+ g_debugAnnotator->setMarker(formattedWideMessage.c_str());
+ break;
+ }
+ }
+
+ if (severity == LOG_ERR)
+ {
+ // Note: we use fprintf because <iostream> includes static initializers.
+ fprintf(stderr, "%s: %s\n", LogSeverityName(severity), str.c_str());
+ }
+
+#if defined(ANGLE_PLATFORM_WINDOWS) && \
+ (defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER) || !defined(NDEBUG))
+#if !defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER)
+ if (severity == LOG_ERR)
+#endif // !defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER)
+ {
+ OutputDebugStringA(str.c_str());
+ }
+#endif
+
+#if defined(ANGLE_ENABLE_DEBUG_TRACE)
+#if defined(NDEBUG)
+ if (severity == LOG_EVENT || severity == LOG_WARN)
+ {
+ return;
+ }
+#endif // defined(NDEBUG)
+ static std::ofstream file(TRACE_OUTPUT_FILE, std::ofstream::app);
+ if (file)
+ {
+ file << LogSeverityName(severity) << ": " << str << std::endl;
+ file.flush();
+ }
+#endif // defined(ANGLE_ENABLE_DEBUG_TRACE)
}
+
+LogSeverity LogMessage::getSeverity() const
+{
+ return mSeverity;
+}
+
+std::string LogMessage::getMessage() const
+{
+ return mStream.str();
+}
+
+#if defined(ANGLE_PLATFORM_WINDOWS)
+std::ostream &operator<<(std::ostream &os, const FmtHR &fmt)
+{
+ os << "HRESULT: ";
+ return FmtHexInt(os, fmt.mHR);
+}
+
+std::ostream &operator<<(std::ostream &os, const FmtErr &fmt)
+{
+ os << "error: ";
+ return FmtHexInt(os, fmt.mErr);
+}
+
+#endif // defined(ANGLE_PLATFORM_WINDOWS)
+
+} // namespace gl
diff --git a/src/3rdparty/angle/src/common/debug.h b/src/3rdparty/angle/src/common/debug.h
index 64cfef4cd9..290a4e8bb7 100644
--- a/src/3rdparty/angle/src/common/debug.h
+++ b/src/3rdparty/angle/src/common/debug.h
@@ -11,6 +11,10 @@
#include <assert.h>
#include <stdio.h>
+
+#include <ios>
+#include <iomanip>
+#include <sstream>
#include <string>
#include "common/angleutils.h"
@@ -22,17 +26,6 @@
namespace gl
{
-enum MessageType
-{
- MESSAGE_TRACE,
- MESSAGE_FIXME,
- MESSAGE_ERR,
- MESSAGE_EVENT,
-};
-
-// Outputs text to the debugging log, or the debugging window
-void trace(bool traceInDebugOnly, MessageType messageType, const char *format, ...);
-
// Pairs a D3D begin event with an end event.
class ScopedPerfEventHelper : angle::NonCopyable
{
@@ -41,50 +34,177 @@ class ScopedPerfEventHelper : angle::NonCopyable
~ScopedPerfEventHelper();
};
+using LogSeverity = int;
+// Note: the log severities are used to index into the array of names,
+// see g_logSeverityNames.
+constexpr LogSeverity LOG_EVENT = 0;
+constexpr LogSeverity LOG_WARN = 1;
+constexpr LogSeverity LOG_ERR = 2;
+constexpr LogSeverity LOG_NUM_SEVERITIES = 3;
+
+void Trace(LogSeverity severity, const char *message);
+
+// This class more or less represents a particular log message. You
+// create an instance of LogMessage and then stream stuff to it.
+// When you finish streaming to it, ~LogMessage is called and the
+// full message gets streamed to the appropriate destination.
+//
+// You shouldn't actually use LogMessage's constructor to log things,
+// though. You should use the ERR() and WARN() macros.
+class LogMessage : angle::NonCopyable
+{
+ public:
+ // Used for ANGLE_LOG(severity).
+ LogMessage(const char *function, int line, LogSeverity severity);
+ ~LogMessage();
+ std::ostream &stream() { return mStream; }
+
+ LogSeverity getSeverity() const;
+ std::string getMessage() const;
+
+ private:
+ const char *mFunction;
+ const int mLine;
+ const LogSeverity mSeverity;
+
+ std::ostringstream mStream;
+};
+
// Wraps the D3D9/D3D11 debug annotation functions.
+// Also handles redirecting logging destination.
class DebugAnnotator : angle::NonCopyable
{
public:
- DebugAnnotator() { };
+ DebugAnnotator(){};
virtual ~DebugAnnotator() { };
virtual void beginEvent(const wchar_t *eventName) = 0;
virtual void endEvent() = 0;
virtual void setMarker(const wchar_t *markerName) = 0;
virtual bool getStatus() = 0;
+ // Log Message Handler that gets passed every log message,
+ // when debug annotations are initialized,
+ // replacing default handling by LogMessage.
+ virtual void logMessage(const LogMessage &msg) const = 0;
};
void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator);
void UninitializeDebugAnnotations();
bool DebugAnnotationsActive();
+bool DebugAnnotationsInitialized();
+
+namespace priv
+{
+// This class is used to explicitly ignore values in the conditional logging macros. This avoids
+// compiler warnings like "value computed is not used" and "statement has no effect".
+class LogMessageVoidify
+{
+ public:
+ LogMessageVoidify() {}
+ // This has to be an operator with a precedence lower than << but higher than ?:
+ void operator&(std::ostream &) {}
+};
+
+// Used by ANGLE_LOG_IS_ON to lazy-evaluate stream arguments.
+bool ShouldCreatePlatformLogMessage(LogSeverity severity);
+
+template <int N, typename T>
+std::ostream &FmtHex(std::ostream &os, T value)
+{
+ os << "0x";
+
+ std::ios_base::fmtflags oldFlags = os.flags();
+ std::streamsize oldWidth = os.width();
+ std::ostream::char_type oldFill = os.fill();
+
+ os << std::hex << std::uppercase << std::setw(N) << std::setfill('0') << value;
+
+ os.flags(oldFlags);
+ os.width(oldWidth);
+ os.fill(oldFill);
+
+ return os;
+}
+} // namespace priv
+
+#if defined(ANGLE_PLATFORM_WINDOWS)
+class FmtHR
+{
+ public:
+ explicit FmtHR(HRESULT hresult) : mHR(hresult) {}
+ private:
+ HRESULT mHR;
+ friend std::ostream &operator<<(std::ostream &os, const FmtHR &fmt);
+};
+
+class FmtErr
+{
+ public:
+ explicit FmtErr(DWORD err) : mErr(err) {}
+
+ private:
+ DWORD mErr;
+ friend std::ostream &operator<<(std::ostream &os, const FmtErr &fmt);
+};
+#endif // defined(ANGLE_PLATFORM_WINDOWS)
+
+template <typename T>
+std::ostream &FmtHexShort(std::ostream &os, T value)
+{
+ return priv::FmtHex<4>(os, value);
+}
+template <typename T>
+std::ostream &FmtHexInt(std::ostream &os, T value)
+{
+ return priv::FmtHex<8>(os, value);
}
+// A few definitions of macros that don't generate much code. These are used
+// by ANGLE_LOG(). Since these are used all over our code, it's
+// better to have compact code for these operations.
+#define COMPACT_ANGLE_LOG_EX_EVENT(ClassName, ...) \
+ ::gl::ClassName(__FUNCTION__, __LINE__, ::gl::LOG_EVENT, ##__VA_ARGS__)
+#define COMPACT_ANGLE_LOG_EX_WARN(ClassName, ...) \
+ ::gl::ClassName(__FUNCTION__, __LINE__, ::gl::LOG_WARN, ##__VA_ARGS__)
+#define COMPACT_ANGLE_LOG_EX_ERR(ClassName, ...) \
+ ::gl::ClassName(__FUNCTION__, __LINE__, ::gl::LOG_ERR, ##__VA_ARGS__)
+
+#define COMPACT_ANGLE_LOG_EVENT COMPACT_ANGLE_LOG_EX_EVENT(LogMessage)
+#define COMPACT_ANGLE_LOG_WARN COMPACT_ANGLE_LOG_EX_WARN(LogMessage)
+#define COMPACT_ANGLE_LOG_ERR COMPACT_ANGLE_LOG_EX_ERR(LogMessage)
+
+#define ANGLE_LOG_IS_ON(severity) (::gl::priv::ShouldCreatePlatformLogMessage(::gl::LOG_##severity))
+
+// Helper macro which avoids evaluating the arguments to a stream if the condition doesn't hold.
+// Condition is evaluated once and only once.
+#define ANGLE_LAZY_STREAM(stream, condition) \
+ !(condition) ? static_cast<void>(0) : ::gl::priv::LogMessageVoidify() & (stream)
+
+// We use the preprocessor's merging operator, "##", so that, e.g.,
+// ANGLE_LOG(EVENT) becomes the token COMPACT_ANGLE_LOG_EVENT. There's some funny
+// subtle difference between ostream member streaming functions (e.g.,
+// ostream::operator<<(int) and ostream non-member streaming functions
+// (e.g., ::operator<<(ostream&, string&): it turns out that it's
+// impossible to stream something like a string directly to an unnamed
+// ostream. We employ a neat hack by calling the stream() member
+// function of LogMessage which seems to avoid the problem.
+#define ANGLE_LOG_STREAM(severity) COMPACT_ANGLE_LOG_##severity.stream()
+
+#define ANGLE_LOG(severity) ANGLE_LAZY_STREAM(ANGLE_LOG_STREAM(severity), ANGLE_LOG_IS_ON(severity))
+
+} // namespace gl
+
#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
#define ANGLE_TRACE_ENABLED
#endif
#define ANGLE_EMPTY_STATEMENT for (;;) break
-
-// A macro to output a trace of a function call and its arguments to the debugging log
-#if defined(ANGLE_TRACE_ENABLED)
-#define TRACE(message, ...) gl::trace(true, gl::MESSAGE_TRACE, "trace: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#else
-#define TRACE(message, ...) (void(0))
-#endif
-
-// A macro to output a function call and its arguments to the debugging log, to denote an item in need of fixing.
-#if defined(ANGLE_TRACE_ENABLED)
-#define FIXME(message, ...) gl::trace(false, gl::MESSAGE_FIXME, "fixme: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#else
-#define FIXME(message, ...) (void(0))
+#if !defined(NDEBUG) || defined(ANGLE_ENABLE_RELEASE_ASSERTS)
+#define ANGLE_ENABLE_ASSERTS
#endif
-// A macro to output a function call and its arguments to the debugging log, in case of error.
-#if defined(ANGLE_TRACE_ENABLED)
-#define ERR(message, ...) gl::trace(false, gl::MESSAGE_ERR, "err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#else
-#define ERR(message, ...) (void(0))
-#endif
+#define WARN() ANGLE_LOG(WARN)
+#define ERR() ANGLE_LOG(ERR)
// A macro to log a performance event around a scope.
#if defined(ANGLE_TRACE_ENABLED)
@@ -97,54 +217,70 @@ bool DebugAnnotationsActive();
#define EVENT(message, ...) (void(0))
#endif
-#if defined(ANGLE_TRACE_ENABLED)
-#undef ANGLE_TRACE_ENABLED
+#if defined(COMPILER_GCC) || defined(__clang__)
+#define ANGLE_CRASH() __builtin_trap()
+#else
+#define ANGLE_CRASH() ((void)(*(volatile char *)0 = 0))
#endif
-// A macro asserting a condition and outputting failures to the debug log
#if !defined(NDEBUG)
-#define ASSERT(expression) { \
- if(!(expression)) \
- ERR("\t! Assert failed in %s(%d): %s\n", __FUNCTION__, __LINE__, #expression); \
- assert(expression); \
- } ANGLE_EMPTY_STATEMENT
-#define UNUSED_ASSERTION_VARIABLE(variable)
+#define ANGLE_ASSERT_IMPL(expression) assert(expression)
#else
-#define ASSERT(expression) (void(0))
-#define UNUSED_ASSERTION_VARIABLE(variable) ((void)variable)
-#endif
+// TODO(jmadill): Detect if debugger is attached and break.
+#define ANGLE_ASSERT_IMPL(expression) ANGLE_CRASH()
+#endif // !defined(NDEBUG)
+
+// A macro asserting a condition and outputting failures to the debug log
+#if defined(ANGLE_ENABLE_ASSERTS)
+#define ASSERT(expression) \
+ (expression ? static_cast<void>(0) : ((ERR() << "\t! Assert failed in " << __FUNCTION__ << "(" \
+ << __LINE__ << "): " << #expression), \
+ ANGLE_ASSERT_IMPL(expression)))
+#else
+// These are just dummy values.
+#define COMPACT_ANGLE_LOG_EX_ASSERT(ClassName, ...) \
+ COMPACT_ANGLE_LOG_EX_EVENT(ClassName, ##__VA_ARGS__)
+#define COMPACT_ANGLE_LOG_ASSERT COMPACT_ANGLE_LOG_EVENT
+namespace gl
+{
+constexpr LogSeverity LOG_ASSERT = LOG_EVENT;
+} // namespace gl
+
+#define ASSERT(condition) \
+ ANGLE_LAZY_STREAM(ANGLE_LOG_STREAM(ASSERT), false ? !(condition) : false) \
+ << "Check failed: " #condition ". "
+#endif // defined(ANGLE_ENABLE_ASSERTS)
#define UNUSED_VARIABLE(variable) ((void)variable)
// A macro to indicate unimplemented functionality
-
-#if defined (ANGLE_TEST_CONFIG)
+#ifndef NOASSERT_UNIMPLEMENTED
#define NOASSERT_UNIMPLEMENTED 1
#endif
-// Define NOASSERT_UNIMPLEMENTED to non zero to skip the assert fail in the unimplemented checks
-// This will allow us to test with some automated test suites (eg dEQP) without crashing
-#ifndef NOASSERT_UNIMPLEMENTED
-#define NOASSERT_UNIMPLEMENTED 0
-#endif
+#if defined(ANGLE_TRACE_ENABLED) || defined(ANGLE_ENABLE_ASSERTS)
+#define UNIMPLEMENTED() \
+ { \
+ ERR() << "\t! Unimplemented: " << __FUNCTION__ << "(" << __FILE__ << ":" << __LINE__ \
+ << ")"; \
+ ASSERT(NOASSERT_UNIMPLEMENTED); \
+ } \
+ ANGLE_EMPTY_STATEMENT
-#if !defined(NDEBUG)
-#define UNIMPLEMENTED() { \
- FIXME("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__); \
- assert(NOASSERT_UNIMPLEMENTED); \
- } ANGLE_EMPTY_STATEMENT
+// A macro for code which is not expected to be reached under valid assumptions
+#define UNREACHABLE() \
+ ((ERR() << "\t! Unreachable reached: " << __FUNCTION__ << "(" << __FILE__ << ":" << __LINE__ \
+ << ")"), \
+ ASSERT(false))
#else
- #define UNIMPLEMENTED() FIXME("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__)
-#endif
+#define UNIMPLEMENTED() \
+ { \
+ ASSERT(NOASSERT_UNIMPLEMENTED); \
+ } \
+ ANGLE_EMPTY_STATEMENT
// A macro for code which is not expected to be reached under valid assumptions
-#if !defined(NDEBUG)
-#define UNREACHABLE() { \
- ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__); \
- assert(false); \
- } ANGLE_EMPTY_STATEMENT
-#else
- #define UNREACHABLE() ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__)
-#endif
+#define UNREACHABLE() ASSERT(false)
+#endif // defined(ANGLE_TRACE_ENABLED) || defined(ANGLE_ENABLE_ASSERTS)
#endif // COMMON_DEBUG_H_
diff --git a/src/3rdparty/angle/src/common/event_tracer.cpp b/src/3rdparty/angle/src/common/event_tracer.cpp
index c9eb5e3073..6dc8458acc 100644
--- a/src/3rdparty/angle/src/common/event_tracer.cpp
+++ b/src/3rdparty/angle/src/common/event_tracer.cpp
@@ -11,10 +11,11 @@ namespace angle
const unsigned char *GetTraceCategoryEnabledFlag(const char *name)
{
- angle::Platform *platform = ANGLEPlatformCurrent();
+ auto *platform = ANGLEPlatformCurrent();
ASSERT(platform);
- const unsigned char *categoryEnabledFlag = platform->getTraceCategoryEnabledFlag(name);
+ const unsigned char *categoryEnabledFlag =
+ platform->getTraceCategoryEnabledFlag(platform, name);
if (categoryEnabledFlag != nullptr)
{
return categoryEnabledFlag;
@@ -24,33 +25,31 @@ const unsigned char *GetTraceCategoryEnabledFlag(const char *name)
return &disabled;
}
-Platform::TraceEventHandle AddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id,
- int numArgs, const char** argNames, const unsigned char* argTypes,
- const unsigned long long* argValues, unsigned char flags)
+angle::TraceEventHandle AddTraceEvent(char phase,
+ const unsigned char *categoryGroupEnabled,
+ const char *name,
+ unsigned long long id,
+ int numArgs,
+ const char **argNames,
+ const unsigned char *argTypes,
+ const unsigned long long *argValues,
+ unsigned char flags)
{
- angle::Platform *platform = ANGLEPlatformCurrent();
+ auto *platform = ANGLEPlatformCurrent();
ASSERT(platform);
- double timestamp = platform->monotonicallyIncreasingTime();
+ double timestamp = platform->monotonicallyIncreasingTime(platform);
if (timestamp != 0)
{
- angle::Platform::TraceEventHandle handle =
- platform->addTraceEvent(phase,
- categoryGroupEnabled,
- name,
- id,
- timestamp,
- numArgs,
- argNames,
- argTypes,
- argValues,
- flags);
+ angle::TraceEventHandle handle =
+ platform->addTraceEvent(platform, phase, categoryGroupEnabled, name, id, timestamp,
+ numArgs, argNames, argTypes, argValues, flags);
ASSERT(handle != 0);
return handle;
}
- return static_cast<Platform::TraceEventHandle>(0);
+ return static_cast<angle::TraceEventHandle>(0);
}
} // namespace angle
diff --git a/src/3rdparty/angle/src/common/event_tracer.h b/src/3rdparty/angle/src/common/event_tracer.h
index ed70f249d2..9b30c750c1 100644
--- a/src/3rdparty/angle/src/common/event_tracer.h
+++ b/src/3rdparty/angle/src/common/event_tracer.h
@@ -12,11 +12,15 @@ namespace angle
{
const unsigned char *GetTraceCategoryEnabledFlag(const char* name);
-Platform::TraceEventHandle AddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name,
- unsigned long long id, int numArgs, const char** argNames,
- const unsigned char* argTypes, const unsigned long long* argValues,
- unsigned char flags);
-
+angle::TraceEventHandle AddTraceEvent(char phase,
+ const unsigned char *categoryGroupEnabled,
+ const char *name,
+ unsigned long long id,
+ int numArgs,
+ const char **argNames,
+ const unsigned char *argTypes,
+ const unsigned long long *argValues,
+ unsigned char flags);
}
#endif // COMMON_EVENT_TRACER_H_
diff --git a/src/3rdparty/angle/src/common/mathutil.cpp b/src/3rdparty/angle/src/common/mathutil.cpp
index 927b6ebebe..5db997c664 100644
--- a/src/3rdparty/angle/src/common/mathutil.cpp
+++ b/src/3rdparty/angle/src/common/mathutil.cpp
@@ -14,6 +14,9 @@
namespace gl
{
+namespace
+{
+
struct RGB9E5Data
{
unsigned int R : 9;
@@ -23,17 +26,20 @@ struct RGB9E5Data
};
// B is the exponent bias (15)
-static const int g_sharedexp_bias = 15;
+constexpr int g_sharedexp_bias = 15;
// N is the number of mantissa bits per component (9)
-static const int g_sharedexp_mantissabits = 9;
+constexpr int g_sharedexp_mantissabits = 9;
// Emax is the maximum allowed biased exponent value (31)
-static const int g_sharedexp_maxexponent = 31;
+constexpr int g_sharedexp_maxexponent = 31;
-static const float g_sharedexp_max = ((pow(2.0f, g_sharedexp_mantissabits) - 1) /
- pow(2.0f, g_sharedexp_mantissabits)) *
- pow(2.0f, g_sharedexp_maxexponent - g_sharedexp_bias);
+constexpr float g_sharedexp_max =
+ ((static_cast<float>(1 << g_sharedexp_mantissabits) - 1) /
+ static_cast<float>(1 << g_sharedexp_mantissabits)) *
+ static_cast<float>(1 << (g_sharedexp_maxexponent - g_sharedexp_bias));
+
+} // anonymous namespace
unsigned int convertRGBFloatsTo999E5(float red, float green, float blue)
{
@@ -64,4 +70,4 @@ void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float
*blue = inputData->B * pow(2.0f, (int)inputData->E - g_sharedexp_bias - g_sharedexp_mantissabits);
}
-}
+} // namespace gl
diff --git a/src/3rdparty/angle/src/common/mathutil.h b/src/3rdparty/angle/src/common/mathutil.h
index 3de62aef10..372e432066 100644
--- a/src/3rdparty/angle/src/common/mathutil.h
+++ b/src/3rdparty/angle/src/common/mathutil.h
@@ -9,9 +9,6 @@
#ifndef COMMON_MATHUTIL_H_
#define COMMON_MATHUTIL_H_
-#include "common/debug.h"
-#include "common/platform.h"
-
#include <limits>
#include <algorithm>
#include <math.h>
@@ -19,25 +16,27 @@
#include <stdint.h>
#include <stdlib.h>
+#include <anglebase/numerics/safe_math.h>
+
+#include "common/debug.h"
+#include "common/platform.h"
+
+namespace angle
+{
+using base::CheckedNumeric;
+using base::IsValueInRangeForNumericType;
+}
+
namespace gl
{
const unsigned int Float32One = 0x3F800000;
const unsigned short Float16One = 0x3C00;
-struct Vector4
-{
- Vector4() {}
- Vector4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
-
- float x;
- float y;
- float z;
- float w;
-};
-
-inline bool isPow2(int x)
+template<typename T>
+inline bool isPow2(T x)
{
+ static_assert(std::is_integral<T>::value, "isPow2 must be called on an integer type.");
return (x & (x - 1)) == 0 && (x != 0);
}
@@ -61,37 +60,52 @@ inline unsigned int ceilPow2(unsigned int x)
return x;
}
-inline int clampToInt(unsigned int x)
-{
- return static_cast<int>(std::min(x, static_cast<unsigned int>(std::numeric_limits<int>::max())));
-}
-
template <typename DestT, typename SrcT>
inline DestT clampCast(SrcT value)
{
- static const DestT destLo = std::numeric_limits<DestT>::min();
- static const DestT destHi = std::numeric_limits<DestT>::max();
- static const SrcT srcLo = static_cast<SrcT>(destLo);
- static const SrcT srcHi = static_cast<SrcT>(destHi);
-
- // When value is outside of or equal to the limits for DestT we use the DestT limit directly.
- // This avoids undefined behaviors due to loss of precision when converting from floats to
- // integers:
- // destHi for ints is 2147483647 but the closest float number is around 2147483648, so when
- // doing a conversion from float to int we run into an UB because the float is outside of the
- // range representable by the int.
- if (value <= srcLo)
- {
- return destLo;
- }
- else if (value >= srcHi)
+ // For floating-point types with denormalization, min returns the minimum positive normalized
+ // value. To find the value that has no values less than it, use numeric_limits::lowest.
+ constexpr const long double destLo =
+ static_cast<long double>(std::numeric_limits<DestT>::lowest());
+ constexpr const long double destHi =
+ static_cast<long double>(std::numeric_limits<DestT>::max());
+ constexpr const long double srcLo =
+ static_cast<long double>(std::numeric_limits<SrcT>::lowest());
+ constexpr long double srcHi = static_cast<long double>(std::numeric_limits<SrcT>::max());
+
+ if (destHi < srcHi)
{
- return destHi;
+ DestT destMax = std::numeric_limits<DestT>::max();
+ if (value >= static_cast<SrcT>(destMax))
+ {
+ return destMax;
+ }
}
- else
+
+ if (destLo > srcLo)
{
- return static_cast<DestT>(value);
+ DestT destLow = std::numeric_limits<DestT>::lowest();
+ if (value <= static_cast<SrcT>(destLow))
+ {
+ return destLow;
+ }
}
+
+ return static_cast<DestT>(value);
+}
+
+// Specialize clampCast for bool->int conversion to avoid MSVS 2015 performance warning when the max
+// value is casted to the source type.
+template <>
+inline unsigned int clampCast(bool value)
+{
+ return static_cast<unsigned int>(value);
+}
+
+template <>
+inline int clampCast(bool value)
+{
+ return static_cast<int>(value);
}
template<typename T, typename MIN, typename MAX>
@@ -127,7 +141,7 @@ inline unsigned int unorm(float x)
inline bool supportsSSE2()
{
-#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(_M_ARM)
+#if defined(ANGLE_USE_SSE)
static bool checked = false;
static bool supports = false;
@@ -136,21 +150,22 @@ inline bool supportsSSE2()
return supports;
}
- int info[4];
- __cpuid(info, 0);
-
- if (info[0] >= 1)
+#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(_M_ARM)
{
- __cpuid(info, 1);
+ int info[4];
+ __cpuid(info, 0);
- supports = (info[3] >> 26) & 1;
- }
+ if (info[0] >= 1)
+ {
+ __cpuid(info, 1);
+ supports = (info[3] >> 26) & 1;
+ }
+ }
+#endif // defined(ANGLE_PLATFORM_WINDOWS) && !defined(_M_ARM)
checked = true;
-
return supports;
-#else
- UNIMPLEMENTED();
+#else // defined(ANGLE_USE_SSE)
return false;
#endif
}
@@ -467,6 +482,43 @@ inline T shiftData(T input)
return (input & mask) << inputBitStart;
}
+inline unsigned int CountLeadingZeros(uint32_t x)
+{
+ // Use binary search to find the amount of leading zeros.
+ unsigned int zeros = 32u;
+ uint32_t y;
+
+ y = x >> 16u;
+ if (y != 0)
+ {
+ zeros = zeros - 16u;
+ x = y;
+ }
+ y = x >> 8u;
+ if (y != 0)
+ {
+ zeros = zeros - 8u;
+ x = y;
+ }
+ y = x >> 4u;
+ if (y != 0)
+ {
+ zeros = zeros - 4u;
+ x = y;
+ }
+ y = x >> 2u;
+ if (y != 0)
+ {
+ zeros = zeros - 2u;
+ x = y;
+ }
+ y = x >> 1u;
+ if (y != 0)
+ {
+ return zeros - 2u;
+ }
+ return zeros - x;
+}
inline unsigned char average(unsigned char a, unsigned char b)
{
@@ -520,38 +572,65 @@ inline unsigned int averageFloat10(unsigned int a, unsigned int b)
}
template <typename T>
-struct Range
+class Range
{
+ public:
Range() {}
- Range(T lo, T hi) : start(lo), end(hi) { ASSERT(lo <= hi); }
-
- T start;
- T end;
+ Range(T lo, T hi) : mLow(lo), mHigh(hi) {}
- T length() const { return end - start; }
+ T length() const { return (empty() ? 0 : (mHigh - mLow)); }
bool intersects(Range<T> other)
{
- if (start <= other.start)
+ if (mLow <= other.mLow)
{
- return other.start < end;
+ return other.mLow < mHigh;
}
else
{
- return start < other.end;
+ return mLow < other.mHigh;
}
}
+ // Assumes that end is non-inclusive.. for example, extending to 5 will make "end" 6.
void extend(T value)
{
- start = value > start ? value : start;
- end = value < end ? value : end;
+ mLow = value < mLow ? value : mLow;
+ mHigh = value >= mHigh ? (value + 1) : mHigh;
}
- bool empty() const
+ bool empty() const { return mHigh <= mLow; }
+
+ bool contains(T value) const { return value >= mLow && value < mHigh; }
+
+ class Iterator final
{
- return end <= start;
- }
+ public:
+ Iterator(T value) : mCurrent(value) {}
+
+ Iterator &operator++()
+ {
+ mCurrent++;
+ return *this;
+ }
+ bool operator==(const Iterator &other) const { return mCurrent == other.mCurrent; }
+ bool operator!=(const Iterator &other) const { return mCurrent != other.mCurrent; }
+ T operator*() const { return mCurrent; }
+
+ private:
+ T mCurrent;
+ };
+
+ Iterator begin() const { return Iterator(mLow); }
+
+ Iterator end() const { return Iterator(mHigh); }
+
+ T low() const { return mLow; }
+ T high() const { return mHigh; }
+
+ private:
+ T mLow;
+ T mHigh;
};
typedef Range<int> RangeI;
@@ -577,6 +656,22 @@ struct IndexRange
size_t vertexIndexCount;
};
+// Combine a floating-point value representing a mantissa (x) and an integer exponent (exp) into a
+// floating-point value. As in GLSL ldexp() built-in.
+inline float Ldexp(float x, int exp)
+{
+ if (exp > 128)
+ {
+ return std::numeric_limits<float>::infinity();
+ }
+ if (exp < -126)
+ {
+ return 0.0f;
+ }
+ double result = static_cast<double>(x) * std::pow(2.0, static_cast<double>(exp));
+ return static_cast<float>(result);
+}
+
// First, both normalized floating-point values are converted into 16-bit integer values.
// Then, the results are packed into the returned 32-bit unsigned integer.
// The first float value will be written to the least significant bits of the output;
@@ -632,6 +727,86 @@ inline void unpackUnorm2x16(uint32_t u, float *f1, float *f2)
*f2 = static_cast<float>(mostSignificantBits) / 65535.0f;
}
+// Helper functions intended to be used only here.
+namespace priv
+{
+
+inline uint8_t ToPackedUnorm8(float f)
+{
+ return static_cast<uint8_t>(roundf(clamp(f, 0.0f, 1.0f) * 255.0f));
+}
+
+inline int8_t ToPackedSnorm8(float f)
+{
+ return static_cast<int8_t>(roundf(clamp(f, -1.0f, 1.0f) * 127.0f));
+}
+
+} // namespace priv
+
+// Packs 4 normalized unsigned floating-point values to a single 32-bit unsigned integer. Works
+// similarly to packUnorm2x16. The floats are clamped to the range 0.0 to 1.0, and written to the
+// unsigned integer starting from the least significant bits.
+inline uint32_t PackUnorm4x8(float f1, float f2, float f3, float f4)
+{
+ uint8_t bits[4];
+ bits[0] = priv::ToPackedUnorm8(f1);
+ bits[1] = priv::ToPackedUnorm8(f2);
+ bits[2] = priv::ToPackedUnorm8(f3);
+ bits[3] = priv::ToPackedUnorm8(f4);
+ uint32_t result = 0u;
+ for (int i = 0; i < 4; ++i)
+ {
+ int shift = i * 8;
+ result |= (static_cast<uint32_t>(bits[i]) << shift);
+ }
+ return result;
+}
+
+// Unpacks 4 normalized unsigned floating-point values from a single 32-bit unsigned integer into f.
+// Works similarly to unpackUnorm2x16. The floats are unpacked starting from the least significant
+// bits.
+inline void UnpackUnorm4x8(uint32_t u, float *f)
+{
+ for (int i = 0; i < 4; ++i)
+ {
+ int shift = i * 8;
+ uint8_t bits = static_cast<uint8_t>((u >> shift) & 0xFF);
+ f[i] = static_cast<float>(bits) / 255.0f;
+ }
+}
+
+// Packs 4 normalized signed floating-point values to a single 32-bit unsigned integer. The floats
+// are clamped to the range -1.0 to 1.0, and written to the unsigned integer starting from the least
+// significant bits.
+inline uint32_t PackSnorm4x8(float f1, float f2, float f3, float f4)
+{
+ int8_t bits[4];
+ bits[0] = priv::ToPackedSnorm8(f1);
+ bits[1] = priv::ToPackedSnorm8(f2);
+ bits[2] = priv::ToPackedSnorm8(f3);
+ bits[3] = priv::ToPackedSnorm8(f4);
+ uint32_t result = 0u;
+ for (int i = 0; i < 4; ++i)
+ {
+ int shift = i * 8;
+ result |= ((static_cast<uint32_t>(bits[i]) & 0xFF) << shift);
+ }
+ return result;
+}
+
+// Unpacks 4 normalized signed floating-point values from a single 32-bit unsigned integer into f.
+// Works similarly to unpackSnorm2x16. The floats are unpacked starting from the least significant
+// bits, and clamped to the range -1.0 to 1.0.
+inline void UnpackSnorm4x8(uint32_t u, float *f)
+{
+ for (int i = 0; i < 4; ++i)
+ {
+ int shift = i * 8;
+ int8_t bits = static_cast<int8_t>((u >> shift) & 0xFF);
+ f[i] = clamp(static_cast<float>(bits) / 127.0f, -1.0f, 1.0f);
+ }
+}
+
// Returns an unsigned integer obtained by converting the two floating-point values to the 16-bit
// floating-point representation found in the OpenGL ES Specification, and then packing these
// two 16-bit integers into a 32-bit unsigned integer.
@@ -658,6 +833,179 @@ inline void unpackHalf2x16(uint32_t u, float *f1, float *f2)
*f2 = float16ToFloat32(mostSignificantBits);
}
+inline uint8_t sRGBToLinear(uint8_t srgbValue)
+{
+ float value = srgbValue / 255.0f;
+ if (value <= 0.04045f)
+ {
+ value = value / 12.92f;
+ }
+ else
+ {
+ value = std::pow((value + 0.055f) / 1.055f, 2.4f);
+ }
+ return static_cast<uint8_t>(clamp(value * 255.0f + 0.5f, 0.0f, 255.0f));
+}
+
+inline uint8_t linearToSRGB(uint8_t linearValue)
+{
+ float value = linearValue / 255.0f;
+ if (value <= 0.0f)
+ {
+ value = 0.0f;
+ }
+ else if (value < 0.0031308f)
+ {
+ value = value * 12.92f;
+ }
+ else if (value < 1.0f)
+ {
+ value = std::pow(value, 0.41666f) * 1.055f - 0.055f;
+ }
+ else
+ {
+ value = 1.0f;
+ }
+ return static_cast<uint8_t>(clamp(value * 255.0f + 0.5f, 0.0f, 255.0f));
+}
+
+// Reverse the order of the bits.
+inline uint32_t BitfieldReverse(uint32_t value)
+{
+ // TODO(oetuaho@nvidia.com): Optimize this if needed. There don't seem to be compiler intrinsics
+ // for this, and right now it's not used in performance-critical paths.
+ uint32_t result = 0u;
+ for (size_t j = 0u; j < 32u; ++j)
+ {
+ result |= (((value >> j) & 1u) << (31u - j));
+ }
+ return result;
+}
+
+// Count the 1 bits.
+#if defined(ANGLE_PLATFORM_WINDOWS)
+#if defined(_M_ARM)
+inline int BitCount(uint32_t bits)
+{
+ bits = bits - ((bits >> 1) & 0x55555555);
+ bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333);
+ return (((bits + (bits >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
+}
+#else // _M_ARM
+inline int BitCount(uint32_t bits)
+{
+ return static_cast<int>(__popcnt(bits));
+}
+#if defined(ANGLE_IS_64_BIT_CPU)
+inline int BitCount(uint64_t bits)
+{
+ return static_cast<int>(__popcnt64(bits));
+}
+#endif // !_M_ARM
+#endif // defined(ANGLE_IS_64_BIT_CPU)
+#endif // defined(ANGLE_PLATFORM_WINDOWS)
+
+#if defined(ANGLE_PLATFORM_POSIX)
+inline int BitCount(uint32_t bits)
+{
+ return __builtin_popcount(bits);
+}
+
+#if defined(ANGLE_IS_64_BIT_CPU)
+inline int BitCount(uint64_t bits)
+{
+ return __builtin_popcountll(bits);
+}
+#endif // defined(ANGLE_IS_64_BIT_CPU)
+#endif // defined(ANGLE_PLATFORM_POSIX)
+
+#if defined(ANGLE_PLATFORM_WINDOWS)
+// Return the index of the least significant bit set. Indexing is such that bit 0 is the least
+// significant bit. Implemented for different bit widths on different platforms.
+inline unsigned long ScanForward(uint32_t bits)
+{
+ ASSERT(bits != 0u);
+ unsigned long firstBitIndex = 0ul;
+ unsigned char ret = _BitScanForward(&firstBitIndex, bits);
+ ASSERT(ret != 0u);
+ return firstBitIndex;
+}
+
+#if defined(ANGLE_IS_64_BIT_CPU)
+inline unsigned long ScanForward(uint64_t bits)
+{
+ ASSERT(bits != 0u);
+ unsigned long firstBitIndex = 0ul;
+ unsigned char ret = _BitScanForward64(&firstBitIndex, bits);
+ ASSERT(ret != 0u);
+ return firstBitIndex;
+}
+#endif // defined(ANGLE_IS_64_BIT_CPU)
+#endif // defined(ANGLE_PLATFORM_WINDOWS)
+
+#if defined(ANGLE_PLATFORM_POSIX)
+inline unsigned long ScanForward(uint32_t bits)
+{
+ ASSERT(bits != 0u);
+ return static_cast<unsigned long>(__builtin_ctz(bits));
+}
+
+#if defined(ANGLE_IS_64_BIT_CPU)
+inline unsigned long ScanForward(uint64_t bits)
+{
+ ASSERT(bits != 0u);
+ return static_cast<unsigned long>(__builtin_ctzll(bits));
+}
+#endif // defined(ANGLE_IS_64_BIT_CPU)
+#endif // defined(ANGLE_PLATFORM_POSIX)
+
+// Return the index of the most significant bit set. Indexing is such that bit 0 is the least
+// significant bit.
+inline unsigned long ScanReverse(unsigned long bits)
+{
+ ASSERT(bits != 0u);
+#if defined(ANGLE_PLATFORM_WINDOWS)
+ unsigned long lastBitIndex = 0ul;
+ unsigned char ret = _BitScanReverse(&lastBitIndex, bits);
+ ASSERT(ret != 0u);
+ return lastBitIndex;
+#elif defined(ANGLE_PLATFORM_POSIX)
+ return static_cast<unsigned long>(sizeof(unsigned long) * CHAR_BIT - 1 - __builtin_clzl(bits));
+#else
+#error Please implement bit-scan-reverse for your platform!
+#endif
+}
+
+// Returns -1 on 0, otherwise the index of the least significant 1 bit as in GLSL.
+template <typename T>
+int FindLSB(T bits)
+{
+ static_assert(std::is_integral<T>::value, "must be integral type.");
+ if (bits == 0u)
+ {
+ return -1;
+ }
+ else
+ {
+ return static_cast<int>(ScanForward(bits));
+ }
+}
+
+// Returns -1 on 0, otherwise the index of the most significant 1 bit as in GLSL.
+template <typename T>
+int FindMSB(T bits)
+{
+ static_assert(std::is_integral<T>::value, "must be integral type.");
+ if (bits == 0u)
+ {
+ return -1;
+ }
+ else
+ {
+ return static_cast<int>(ScanReverse(bits));
+ }
+}
+
// Returns whether the argument is Not a Number.
// IEEE 754 single precision NaN representation: Exponent(8 bits) - 255, Mantissa(23 bits) - non-zero.
inline bool isNaN(float f)
@@ -676,41 +1024,98 @@ inline bool isInf(float f)
return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) && !(bitCast<uint32_t>(f) & 0x7fffffu);
}
+namespace priv
+{
+template <unsigned int N, unsigned int R>
+struct iSquareRoot
+{
+ static constexpr unsigned int solve()
+ {
+ return (R * R > N)
+ ? 0
+ : ((R * R == N) ? R : static_cast<unsigned int>(iSquareRoot<N, R + 1>::value));
+ }
+ enum Result
+ {
+ value = iSquareRoot::solve()
+ };
+};
+
+template <unsigned int N>
+struct iSquareRoot<N, N>
+{
+ enum result
+ {
+ value = N
+ };
+};
+
+} // namespace priv
+
+template <unsigned int N>
+constexpr unsigned int iSquareRoot()
+{
+ return priv::iSquareRoot<N, 1>::value;
}
-namespace rx
+// Sum, difference and multiplication operations for signed ints that wrap on 32-bit overflow.
+//
+// Unsigned types are defined to do arithmetic modulo 2^n in C++. For signed types, overflow
+// behavior is undefined.
+
+template <typename T>
+inline T WrappingSum(T lhs, T rhs)
{
+ uint32_t lhsUnsigned = static_cast<uint32_t>(lhs);
+ uint32_t rhsUnsigned = static_cast<uint32_t>(rhs);
+ return static_cast<T>(lhsUnsigned + rhsUnsigned);
+}
template <typename T>
-T roundUp(const T value, const T alignment)
+inline T WrappingDiff(T lhs, T rhs)
{
- return value + alignment - 1 - (value - 1) % alignment;
+ uint32_t lhsUnsigned = static_cast<uint32_t>(lhs);
+ uint32_t rhsUnsigned = static_cast<uint32_t>(rhs);
+ return static_cast<T>(lhsUnsigned - rhsUnsigned);
}
-inline unsigned int UnsignedCeilDivide(unsigned int value, unsigned int divisor)
+inline int32_t WrappingMul(int32_t lhs, int32_t rhs)
{
- unsigned int divided = value / divisor;
- return (divided + ((value % divisor == 0) ? 0 : 1));
+ int64_t lhsWide = static_cast<int64_t>(lhs);
+ int64_t rhsWide = static_cast<int64_t>(rhs);
+ // The multiplication is guaranteed not to overflow.
+ int64_t resultWide = lhsWide * rhsWide;
+ // Implement the desired wrapping behavior by masking out the high-order 32 bits.
+ resultWide = resultWide & 0xffffffffll;
+ // Casting to a narrower signed type is fine since the casted value is representable in the
+ // narrower type.
+ return static_cast<int32_t>(resultWide);
}
-template <class T>
-inline bool IsUnsignedAdditionSafe(T lhs, T rhs)
+} // namespace gl
+
+namespace rx
{
- static_assert(!std::numeric_limits<T>::is_signed, "T must be unsigned.");
- return (rhs <= std::numeric_limits<T>::max() - lhs);
+
+template <typename T>
+T roundUp(const T value, const T alignment)
+{
+ auto temp = value + alignment - static_cast<T>(1);
+ return temp - temp % alignment;
}
-template <class T>
-inline bool IsUnsignedMultiplicationSafe(T lhs, T rhs)
+template <typename T>
+angle::CheckedNumeric<T> CheckedRoundUp(const T value, const T alignment)
{
- static_assert(!std::numeric_limits<T>::is_signed, "T must be unsigned.");
- return (lhs == T(0) || rhs == T(0) || (rhs <= std::numeric_limits<T>::max() / lhs));
+ angle::CheckedNumeric<T> checkedValue(value);
+ angle::CheckedNumeric<T> checkedAlignment(alignment);
+ return roundUp(checkedValue, checkedAlignment);
}
-template <class SmallIntT, class BigIntT>
-inline bool IsIntegerCastSafe(BigIntT bigValue)
+inline unsigned int UnsignedCeilDivide(unsigned int value, unsigned int divisor)
{
- return (static_cast<BigIntT>(static_cast<SmallIntT>(bigValue)) == bigValue);
+ unsigned int divided = value / divisor;
+ return (divided + ((value % divisor == 0) ? 0 : 1));
}
#if defined(_MSC_VER)
@@ -730,8 +1135,8 @@ inline uint16_t RotR16(uint16_t x, int8_t r)
return (x >> r) | (x << (16 - r));
}
-#define ANGLE_ROTL(x,y) RotL(x,y)
-#define ANGLE_ROTR16(x,y) RotR16(x,y)
+#define ANGLE_ROTL(x, y) ::rx::RotL(x, y)
+#define ANGLE_ROTR16(x, y) ::rx::RotR16(x, y)
#endif // namespace rx
diff --git a/src/3rdparty/angle/src/common/matrix_utils.h b/src/3rdparty/angle/src/common/matrix_utils.h
index 6f3187c3e8..aa3f89536e 100644
--- a/src/3rdparty/angle/src/common/matrix_utils.h
+++ b/src/3rdparty/angle/src/common/matrix_utils.h
@@ -16,6 +16,7 @@
#include <vector>
#include "common/debug.h"
+#include "common/mathutil.h"
namespace angle
{
@@ -337,6 +338,42 @@ class Matrix
return result;
}
+ void setToIdentity()
+ {
+ ASSERT(rows() == columns());
+
+ const auto one = T(1);
+ const auto zero = T(0);
+
+ for (auto &e : mElements)
+ e = zero;
+
+ for (unsigned int i = 0; i < rows(); ++i)
+ {
+ const auto pos = i * columns() + (i % columns());
+ mElements[pos] = one;
+ }
+ }
+
+ template <unsigned int Size>
+ static void setToIdentity(T(&matrix)[Size])
+ {
+ static_assert(gl::iSquareRoot<Size>() != 0, "Matrix is not square.");
+
+ const auto cols = gl::iSquareRoot<Size>();
+ const auto one = T(1);
+ const auto zero = T(0);
+
+ for (auto &e : matrix)
+ e = zero;
+
+ for (unsigned int i = 0; i < cols; ++i)
+ {
+ const auto pos = i * cols + (i % cols);
+ matrix[pos] = one;
+ }
+ }
+
private:
std::vector<T> mElements;
unsigned int mRows;
diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h
index be4cb94987..47cd57b999 100644
--- a/src/3rdparty/angle/src/common/platform.h
+++ b/src/3rdparty/angle/src/common/platform.h
@@ -27,7 +27,9 @@
defined(__sun) || \
defined(__GLIBC__) || \
defined(__GNU__) || \
- defined(__QNX__)
+ defined(__QNX__) || \
+ defined(__Fuchsia__) || \
+ defined(__HAIKU__)
# define ANGLE_PLATFORM_POSIX 1
#else
# error Unsupported platform.
@@ -57,28 +59,22 @@
# endif
# if defined(ANGLE_ENABLE_D3D11)
-# include <d3d10_1.h>
-# include <d3d11.h>
-# include <dxgi.h>
-# if defined(__MINGW32__) && !defined(__d3d11sdklayers_h__)
-# define ANGLE_MINGW32_COMPAT
-# endif
-# if defined(_MSC_VER) && _MSC_VER >= 1800
-# define ANGLE_ENABLE_D3D11_1
-# endif
-# if defined(ANGLE_ENABLE_D3D11_1)
-# include <d3d11_1.h>
-# include <dxgi1_2.h>
-# endif
-# include <d3dcompiler.h>
+#include <d3d10_1.h>
+#include <d3d11.h>
+#include <d3d11_3.h>
+#include <d3dcompiler.h>
+#include <dxgi.h>
+#include <dxgi1_2.h>
# endif
+#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
+#include <wrl.h>
+#endif
+
# if defined(ANGLE_ENABLE_WINDOWS_STORE)
# include <dxgi1_3.h>
# if defined(_DEBUG)
-# if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
# include <DXProgrammableCapture.h>
-# endif
# include <dxgidebug.h>
# endif
# endif
@@ -87,8 +83,21 @@
# undef far
#endif
-#if !defined(_M_ARM) && !defined(ANGLE_PLATFORM_ANDROID)
-# define ANGLE_USE_SSE
+#if defined(_MSC_VER) && !defined(_M_ARM)
+#include <intrin.h>
+#define ANGLE_USE_SSE
+#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) && !defined(__MINGW32__)
+#include <x86intrin.h>
+#define ANGLE_USE_SSE
#endif
+// Mips and arm devices need to include stddef for size_t.
+#if defined(__mips__) || defined(__arm__) || defined(__aarch64__)
+#include <stddef.h>
+#endif
+
+// The MemoryBarrier function name collides with a macro under Windows
+// We will undef the macro so that the function name does not get replaced
+#undef MemoryBarrier
+
#endif // COMMON_PLATFORM_H_
diff --git a/src/3rdparty/angle/src/common/string_utils.cpp b/src/3rdparty/angle/src/common/string_utils.cpp
index acb0376bf9..26f384bb2a 100644
--- a/src/3rdparty/angle/src/common/string_utils.cpp
+++ b/src/3rdparty/angle/src/common/string_utils.cpp
@@ -9,9 +9,14 @@
#include "string_utils.h"
+#include <algorithm>
+#include <stdlib.h>
+#include <string.h>
#include <fstream>
#include <sstream>
+#include "common/platform.h"
+
namespace angle
{
@@ -133,4 +138,76 @@ bool ReadFileToString(const std::string &path, std::string *stringOut)
return !inFile.fail();
}
+Optional<std::vector<wchar_t>> WidenString(size_t length, const char *cString)
+{
+ std::vector<wchar_t> wcstring(length + 1);
+#if !defined(ANGLE_PLATFORM_WINDOWS)
+ size_t written = mbstowcs(wcstring.data(), cString, length + 1);
+ if (written == 0)
+ {
+ return Optional<std::vector<wchar_t>>::Invalid();
+ }
+#else
+ size_t convertedChars = 0;
+ errno_t err = mbstowcs_s(&convertedChars, wcstring.data(), length + 1, cString, _TRUNCATE);
+ if (err != 0)
+ {
+ return Optional<std::vector<wchar_t>>::Invalid();
+ }
+#endif
+ return Optional<std::vector<wchar_t>>(wcstring);
+}
+
+bool BeginsWith(const std::string &str, const std::string &prefix)
+{
+ return strncmp(str.c_str(), prefix.c_str(), prefix.length()) == 0;
+}
+
+bool BeginsWith(const std::string &str, const char *prefix)
+{
+ return strncmp(str.c_str(), prefix, strlen(prefix)) == 0;
+}
+
+bool BeginsWith(const char *str, const char *prefix)
+{
+ return strncmp(str, prefix, strlen(prefix)) == 0;
+}
+
+bool BeginsWith(const std::string &str, const std::string &prefix, const size_t prefixLength)
+{
+ return strncmp(str.c_str(), prefix.c_str(), prefixLength) == 0;
+}
+
+bool EndsWith(const std::string &str, const char *suffix)
+{
+ const auto len = strlen(suffix);
+ if (len > str.size())
+ return false;
+
+ const char *end = str.c_str() + str.size() - len;
+
+ return memcmp(end, suffix, len) == 0;
+}
+
+void ToLower(std::string *str)
+{
+ for (auto &ch : *str)
+ {
+ ch = static_cast<char>(::tolower(ch));
+ }
+}
+
+bool ReplaceSubstring(std::string *str,
+ const std::string &substring,
+ const std::string &replacement)
+{
+ size_t replacePos = str->find(substring);
+ if (replacePos == std::string::npos)
+ {
+ return false;
+ }
+ str->replace(replacePos, substring.size(), replacement);
+ return true;
}
+
+} // namespace angle
diff --git a/src/3rdparty/angle/src/common/string_utils.h b/src/3rdparty/angle/src/common/string_utils.h
index 131b17e086..07bf1ff81a 100644
--- a/src/3rdparty/angle/src/common/string_utils.h
+++ b/src/3rdparty/angle/src/common/string_utils.h
@@ -13,6 +13,8 @@
#include <string>
#include <vector>
+#include "common/Optional.h"
+
namespace angle
{
@@ -44,6 +46,40 @@ bool HexStringToUInt(const std::string &input, unsigned int *uintOut);
bool ReadFileToString(const std::string &path, std::string *stringOut);
-}
+Optional<std::vector<wchar_t>> WidenString(size_t length, const char *cString);
+
+// Check if the string str begins with the given prefix.
+// The comparison is case sensitive.
+bool BeginsWith(const std::string &str, const std::string &prefix);
+
+// Check if the string str begins with the given prefix.
+// Prefix may not be NULL and needs to be NULL terminated.
+// The comparison is case sensitive.
+bool BeginsWith(const std::string &str, const char *prefix);
+
+// Check if the string str begins with the given prefix.
+// str and prefix may not be NULL and need to be NULL terminated.
+// The comparison is case sensitive.
+bool BeginsWith(const char *str, const char *prefix);
+
+// Check if the string str begins with the first prefixLength characters of the given prefix.
+// The length of the prefix string should be greater than or equal to prefixLength.
+// The comparison is case sensitive.
+bool BeginsWith(const std::string &str, const std::string &prefix, const size_t prefixLength);
+
+// Check if the string str ends with the given suffix.
+// Suffix may not be NUL and needs to be NULL terminated.
+// The comparison is case sensitive.
+bool EndsWith(const std::string& str, const char* suffix);
+
+// Convert to lower-case.
+void ToLower(std::string *str);
+
+// Replaces the substring 'substring' in 'str' with 'replacement'. Returns true if successful.
+bool ReplaceSubstring(std::string *str,
+ const std::string &substring,
+ const std::string &replacement);
+
+} // namespace angle
#endif // LIBANGLE_STRING_UTILS_H_
diff --git a/src/3rdparty/angle/src/common/system_utils.h b/src/3rdparty/angle/src/common/system_utils.h
new file mode 100644
index 0000000000..d61faa53fd
--- /dev/null
+++ b/src/3rdparty/angle/src/common/system_utils.h
@@ -0,0 +1,27 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// system_utils.h: declaration of OS-specific utility functions
+
+#ifndef COMMON_SYSTEM_UTILS_H_
+#define COMMON_SYSTEM_UTILS_H_
+
+#include "common/angleutils.h"
+#include "common/Optional.h"
+
+namespace angle
+{
+
+const char *GetExecutablePath();
+const char *GetExecutableDirectory();
+const char *GetSharedLibraryExtension();
+Optional<std::string> GetCWD();
+bool SetCWD(const char *dirName);
+bool SetEnvironmentVar(const char *variableName, const char *value);
+
+} // namespace angle
+
+#endif // COMMON_SYSTEM_UTILS_H_
diff --git a/src/3rdparty/angle/src/common/system_utils_linux.cpp b/src/3rdparty/angle/src/common/system_utils_linux.cpp
new file mode 100644
index 0000000000..98ab4cce6d
--- /dev/null
+++ b/src/3rdparty/angle/src/common/system_utils_linux.cpp
@@ -0,0 +1,89 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// system_utils_linux.cpp: Implementation of OS-specific functions for Linux
+
+#include "system_utils.h"
+
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <array>
+
+namespace angle
+{
+
+namespace
+{
+
+std::string GetExecutablePathImpl()
+{
+ // We cannot use lstat to get the size of /proc/self/exe as it always returns 0
+ // so we just use a big buffer and hope the path fits in it.
+ char path[4096];
+
+ ssize_t result = readlink("/proc/self/exe", path, sizeof(path) - 1);
+ if (result < 0 || static_cast<size_t>(result) >= sizeof(path) - 1)
+ {
+ return "";
+ }
+
+ path[result] = '\0';
+ return path;
+}
+
+std::string GetExecutableDirectoryImpl()
+{
+ std::string executablePath = GetExecutablePath();
+ size_t lastPathSepLoc = executablePath.find_last_of("/");
+ return (lastPathSepLoc != std::string::npos) ? executablePath.substr(0, lastPathSepLoc) : "";
+}
+
+} // anonymous namespace
+
+const char *GetExecutablePath()
+{
+ // TODO(jmadill): Make global static string thread-safe.
+ const static std::string &exePath = GetExecutablePathImpl();
+ return exePath.c_str();
+}
+
+const char *GetExecutableDirectory()
+{
+ // TODO(jmadill): Make global static string thread-safe.
+ const static std::string &exeDir = GetExecutableDirectoryImpl();
+ return exeDir.c_str();
+}
+
+const char *GetSharedLibraryExtension()
+{
+ return "so";
+}
+
+Optional<std::string> GetCWD()
+{
+ std::array<char, 4096> pathBuf;
+ char *result = getcwd(pathBuf.data(), pathBuf.size());
+ if (result == nullptr)
+ {
+ return Optional<std::string>::Invalid();
+ }
+ return std::string(pathBuf.data());
+}
+
+bool SetCWD(const char *dirName)
+{
+ return (chdir(dirName) == 0);
+}
+
+bool SetEnvironmentVar(const char *variableName, const char *value)
+{
+ return (setenv(variableName, value, 1) == 0);
+}
+
+} // namespace angle
diff --git a/src/3rdparty/angle/src/common/system_utils_mac.cpp b/src/3rdparty/angle/src/common/system_utils_mac.cpp
new file mode 100644
index 0000000000..03b9185ab1
--- /dev/null
+++ b/src/3rdparty/angle/src/common/system_utils_mac.cpp
@@ -0,0 +1,94 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// system_utils_osx.cpp: Implementation of OS-specific functions for OSX
+
+#include "system_utils.h"
+
+#include <unistd.h>
+
+#include <cstdlib>
+#include <mach-o/dyld.h>
+#include <vector>
+
+#include <array>
+
+namespace angle
+{
+
+namespace
+{
+
+std::string GetExecutablePathImpl()
+{
+ std::string result;
+
+ uint32_t size = 0;
+ _NSGetExecutablePath(nullptr, &size);
+
+ std::vector<char> buffer;
+ buffer.resize(size + 1);
+
+ _NSGetExecutablePath(buffer.data(), &size);
+ buffer[size] = '\0';
+
+ if (!strrchr(buffer.data(), '/'))
+ {
+ return "";
+ }
+ return buffer.data();
+}
+
+std::string GetExecutableDirectoryImpl()
+{
+ std::string executablePath = GetExecutablePath();
+ size_t lastPathSepLoc = executablePath.find_last_of("/");
+ return (lastPathSepLoc != std::string::npos) ? executablePath.substr(0, lastPathSepLoc) : "";
+}
+
+} // anonymous namespace
+
+const char *GetExecutablePath()
+{
+ // TODO(jmadill): Make global static string thread-safe.
+ const static std::string &exePath = GetExecutablePathImpl();
+ return exePath.c_str();
+}
+
+const char *GetExecutableDirectory()
+{
+ // TODO(jmadill): Make global static string thread-safe.
+ const static std::string &exeDir = GetExecutableDirectoryImpl();
+ return exeDir.c_str();
+}
+
+const char *GetSharedLibraryExtension()
+{
+ return "dylib";
+}
+
+Optional<std::string> GetCWD()
+{
+ std::array<char, 4096> pathBuf;
+ char *result = getcwd(pathBuf.data(), pathBuf.size());
+ if (result == nullptr)
+ {
+ return Optional<std::string>::Invalid();
+ }
+ return std::string(pathBuf.data());
+}
+
+bool SetCWD(const char *dirName)
+{
+ return (chdir(dirName) == 0);
+}
+
+bool SetEnvironmentVar(const char *variableName, const char *value)
+{
+ return (setenv(variableName, value, 1) == 0);
+}
+
+} // namespace angle
diff --git a/src/3rdparty/angle/src/common/system_utils_win.cpp b/src/3rdparty/angle/src/common/system_utils_win.cpp
new file mode 100644
index 0000000000..6bb2bfbd3f
--- /dev/null
+++ b/src/3rdparty/angle/src/common/system_utils_win.cpp
@@ -0,0 +1,79 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// system_utils_win.cpp: Implementation of OS-specific functions for Windows
+
+#include "system_utils.h"
+
+#include <stdarg.h>
+#include <windows.h>
+#include <array>
+#include <vector>
+
+namespace angle
+{
+
+namespace
+{
+
+std::string GetExecutablePathImpl()
+{
+ std::array<char, MAX_PATH> executableFileBuf;
+ DWORD executablePathLen = GetModuleFileNameA(nullptr, executableFileBuf.data(),
+ static_cast<DWORD>(executableFileBuf.size()));
+ return (executablePathLen > 0 ? std::string(executableFileBuf.data()) : "");
+}
+
+std::string GetExecutableDirectoryImpl()
+{
+ std::string executablePath = GetExecutablePath();
+ size_t lastPathSepLoc = executablePath.find_last_of("\\/");
+ return (lastPathSepLoc != std::string::npos) ? executablePath.substr(0, lastPathSepLoc) : "";
+}
+
+} // anonymous namespace
+
+const char *GetExecutablePath()
+{
+ // TODO(jmadill): Make global static string thread-safe.
+ const static std::string &exePath = GetExecutablePathImpl();
+ return exePath.c_str();
+}
+
+const char *GetExecutableDirectory()
+{
+ // TODO(jmadill): Make global static string thread-safe.
+ const static std::string &exeDir = GetExecutableDirectoryImpl();
+ return exeDir.c_str();
+}
+
+const char *GetSharedLibraryExtension()
+{
+ return "dll";
+}
+
+Optional<std::string> GetCWD()
+{
+ std::array<char, MAX_PATH> pathBuf;
+ DWORD result = GetCurrentDirectoryA(static_cast<DWORD>(pathBuf.size()), pathBuf.data());
+ if (result == 0)
+ {
+ return Optional<std::string>::Invalid();
+ }
+ return std::string(pathBuf.data());
+}
+
+bool SetCWD(const char *dirName)
+{
+ return (SetCurrentDirectoryA(dirName) == TRUE);
+}
+
+bool SetEnvironmentVar(const char *variableName, const char *value)
+{
+ return (SetEnvironmentVariableA(variableName, value) == TRUE);
+}
+
+} // namespace angle
diff --git a/src/3rdparty/angle/src/common/third_party/base/README.angle b/src/3rdparty/angle/src/common/third_party/base/README.angle
new file mode 100644
index 0000000000..ca0943bc99
--- /dev/null
+++ b/src/3rdparty/angle/src/common/third_party/base/README.angle
@@ -0,0 +1,27 @@
+Name: Chromium base:: helper Classes
+Short Name: base::numerics, base::MRUCachem, base::SHA1
+Version:
+URL: https://chromium.googlesource.com/chromium/src/base/+/master
+SOURCE CODE: Copy the Chromium folder manually into this folder and run git cl format.
+Date: 24/05/2017
+Revision: 28b5bbb227d331c01e6ff9b2f8729732135aadc7 (Chromium)
+Security Critical: no
+License: Chromium
+License File: LICENSE in Chromium/src
+
+Description:
+base::numerics is a library for doing some simple safe math and conversions.
+base::MRUCache is a few collections of most-recently-used caching structures.
+base::SHA1 is a secure hashing algorithm.
+
+To update the checkout, simply overwrite the folder with Chromium's latest, apply
+the appropriate namespace, and make sure the paths are correct (anglebase/ instead of
+base/), and update the header guards and macros.
+
+Modifications:
+
+- the file scope is now anglebase/ from base/ to prevent include conflicts.
+- anglebase/logging.h defines (D)CHECK to be ASSERT to be compatible with ANGLE.
+- the headers use namespace angle::base instead of base:: to avoid ODR
+ violations when ANGLE code is mixed with Chromium code.
+- header guards and macros are changed from BASE to ANGLEBASE to prevent conflicts.
diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/base_export.h b/src/3rdparty/angle/src/common/third_party/base/anglebase/base_export.h
new file mode 100644
index 0000000000..1af5485336
--- /dev/null
+++ b/src/3rdparty/angle/src/common/third_party/base/anglebase/base_export.h
@@ -0,0 +1,13 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// base_export.h: Compatiblity hacks for importing Chromium's base/SHA1.
+
+#ifndef ANGLEBASE_BASE_EXPORT_H_
+#define ANGLEBASE_BASE_EXPORT_H_
+
+#define ANGLEBASE_EXPORT
+
+#endif // ANGLEBASE_BASE_EXPORT_H_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/containers/mru_cache.h b/src/3rdparty/angle/src/common/third_party/base/anglebase/containers/mru_cache.h
new file mode 100644
index 0000000000..fe4fec5768
--- /dev/null
+++ b/src/3rdparty/angle/src/common/third_party/base/anglebase/containers/mru_cache.h
@@ -0,0 +1,275 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file contains a template for a Most Recently Used cache that allows
+// constant-time access to items using a key, but easy identification of the
+// least-recently-used items for removal. Each key can only be associated with
+// one payload item at a time.
+//
+// The key object will be stored twice, so it should support efficient copying.
+//
+// NOTE: While all operations are O(1), this code is written for
+// legibility rather than optimality. If future profiling identifies this as
+// a bottleneck, there is room for smaller values of 1 in the O(1). :]
+
+#ifndef ANGLEBASE_CONTAINERS_MRU_CACHE_H_
+#define ANGLEBASE_CONTAINERS_MRU_CACHE_H_
+
+#include <stddef.h>
+
+#include <algorithm>
+#include <functional>
+#include <list>
+#include <map>
+#include <unordered_map>
+#include <utility>
+
+#include "anglebase/logging.h"
+#include "anglebase/macros.h"
+
+namespace angle
+{
+
+namespace base
+{
+
+// MRUCacheBase ----------------------------------------------------------------
+
+// This template is used to standardize map type containers that can be used
+// by MRUCacheBase. This level of indirection is necessary because of the way
+// that template template params and default template params interact.
+template <class KeyType, class ValueType, class CompareType>
+struct MRUCacheStandardMap
+{
+ typedef std::map<KeyType, ValueType, CompareType> Type;
+};
+
+// Base class for the MRU cache specializations defined below.
+template <class KeyType,
+ class PayloadType,
+ class HashOrCompareType,
+ template <typename, typename, typename> class MapType = MRUCacheStandardMap>
+class MRUCacheBase
+{
+ public:
+ // The payload of the list. This maintains a copy of the key so we can
+ // efficiently delete things given an element of the list.
+ typedef std::pair<KeyType, PayloadType> value_type;
+
+ private:
+ typedef std::list<value_type> PayloadList;
+ typedef
+ typename MapType<KeyType, typename PayloadList::iterator, HashOrCompareType>::Type KeyIndex;
+
+ public:
+ typedef typename PayloadList::size_type size_type;
+
+ typedef typename PayloadList::iterator iterator;
+ typedef typename PayloadList::const_iterator const_iterator;
+ typedef typename PayloadList::reverse_iterator reverse_iterator;
+ typedef typename PayloadList::const_reverse_iterator const_reverse_iterator;
+
+ enum
+ {
+ NO_AUTO_EVICT = 0
+ };
+
+ // The max_size is the size at which the cache will prune its members to when
+ // a new item is inserted. If the caller wants to manager this itself (for
+ // example, maybe it has special work to do when something is evicted), it
+ // can pass NO_AUTO_EVICT to not restrict the cache size.
+ explicit MRUCacheBase(size_type max_size) : max_size_(max_size) {}
+
+ virtual ~MRUCacheBase() {}
+
+ size_type max_size() const { return max_size_; }
+
+ // Inserts a payload item with the given key. If an existing item has
+ // the same key, it is removed prior to insertion. An iterator indicating the
+ // inserted item will be returned (this will always be the front of the list).
+ //
+ // The payload will be forwarded.
+ template <typename Payload>
+ iterator Put(const KeyType &key, Payload &&payload)
+ {
+ // Remove any existing payload with that key.
+ typename KeyIndex::iterator index_iter = index_.find(key);
+ if (index_iter != index_.end())
+ {
+ // Erase the reference to it. The index reference will be replaced in the
+ // code below.
+ Erase(index_iter->second);
+ }
+ else if (max_size_ != NO_AUTO_EVICT)
+ {
+ // New item is being inserted which might make it larger than the maximum
+ // size: kick the oldest thing out if necessary.
+ ShrinkToSize(max_size_ - 1);
+ }
+
+ ordering_.emplace_front(key, std::forward<Payload>(payload));
+ index_.emplace(key, ordering_.begin());
+ return ordering_.begin();
+ }
+
+ // Retrieves the contents of the given key, or end() if not found. This method
+ // has the side effect of moving the requested item to the front of the
+ // recency list.
+ iterator Get(const KeyType &key)
+ {
+ typename KeyIndex::iterator index_iter = index_.find(key);
+ if (index_iter == index_.end())
+ return end();
+ typename PayloadList::iterator iter = index_iter->second;
+
+ // Move the touched item to the front of the recency ordering.
+ ordering_.splice(ordering_.begin(), ordering_, iter);
+ return ordering_.begin();
+ }
+
+ // Retrieves the payload associated with a given key and returns it via
+ // result without affecting the ordering (unlike Get).
+ iterator Peek(const KeyType &key)
+ {
+ typename KeyIndex::const_iterator index_iter = index_.find(key);
+ if (index_iter == index_.end())
+ return end();
+ return index_iter->second;
+ }
+
+ const_iterator Peek(const KeyType &key) const
+ {
+ typename KeyIndex::const_iterator index_iter = index_.find(key);
+ if (index_iter == index_.end())
+ return end();
+ return index_iter->second;
+ }
+
+ // Exchanges the contents of |this| by the contents of the |other|.
+ void Swap(MRUCacheBase &other)
+ {
+ ordering_.swap(other.ordering_);
+ index_.swap(other.index_);
+ std::swap(max_size_, other.max_size_);
+ }
+
+ // Erases the item referenced by the given iterator. An iterator to the item
+ // following it will be returned. The iterator must be valid.
+ iterator Erase(iterator pos)
+ {
+ index_.erase(pos->first);
+ return ordering_.erase(pos);
+ }
+
+ // MRUCache entries are often processed in reverse order, so we add this
+ // convenience function (not typically defined by STL containers).
+ reverse_iterator Erase(reverse_iterator pos)
+ {
+ // We have to actually give it the incremented iterator to delete, since
+ // the forward iterator that base() returns is actually one past the item
+ // being iterated over.
+ return reverse_iterator(Erase((++pos).base()));
+ }
+
+ // Shrinks the cache so it only holds |new_size| items. If |new_size| is
+ // bigger or equal to the current number of items, this will do nothing.
+ void ShrinkToSize(size_type new_size)
+ {
+ for (size_type i = size(); i > new_size; i--)
+ Erase(rbegin());
+ }
+
+ // Deletes everything from the cache.
+ void Clear()
+ {
+ index_.clear();
+ ordering_.clear();
+ }
+
+ // Returns the number of elements in the cache.
+ size_type size() const
+ {
+ // We don't use ordering_.size() for the return value because
+ // (as a linked list) it can be O(n).
+ DCHECK(index_.size() == ordering_.size());
+ return index_.size();
+ }
+
+ // Allows iteration over the list. Forward iteration starts with the most
+ // recent item and works backwards.
+ //
+ // Note that since these iterators are actually iterators over a list, you
+ // can keep them as you insert or delete things (as long as you don't delete
+ // the one you are pointing to) and they will still be valid.
+ iterator begin() { return ordering_.begin(); }
+ const_iterator begin() const { return ordering_.begin(); }
+ iterator end() { return ordering_.end(); }
+ const_iterator end() const { return ordering_.end(); }
+
+ reverse_iterator rbegin() { return ordering_.rbegin(); }
+ const_reverse_iterator rbegin() const { return ordering_.rbegin(); }
+ reverse_iterator rend() { return ordering_.rend(); }
+ const_reverse_iterator rend() const { return ordering_.rend(); }
+
+ bool empty() const { return ordering_.empty(); }
+
+ private:
+ PayloadList ordering_;
+ KeyIndex index_;
+
+ size_type max_size_;
+
+ DISALLOW_COPY_AND_ASSIGN(MRUCacheBase);
+};
+
+// MRUCache --------------------------------------------------------------------
+
+// A container that does not do anything to free its data. Use this when storing
+// value types (as opposed to pointers) in the list.
+template <class KeyType, class PayloadType, class CompareType = std::less<KeyType>>
+class MRUCache : public MRUCacheBase<KeyType, PayloadType, CompareType>
+{
+ private:
+ using ParentType = MRUCacheBase<KeyType, PayloadType, CompareType>;
+
+ public:
+ // See MRUCacheBase, noting the possibility of using NO_AUTO_EVICT.
+ explicit MRUCache(typename ParentType::size_type max_size) : ParentType(max_size) {}
+ virtual ~MRUCache() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MRUCache);
+};
+
+// HashingMRUCache ------------------------------------------------------------
+
+template <class KeyType, class ValueType, class HashType>
+struct MRUCacheHashMap
+{
+ typedef std::unordered_map<KeyType, ValueType, HashType> Type;
+};
+
+// This class is similar to MRUCache, except that it uses std::unordered_map as
+// the map type instead of std::map. Note that your KeyType must be hashable to
+// use this cache or you need to provide a hashing class.
+template <class KeyType, class PayloadType, class HashType = std::hash<KeyType>>
+class HashingMRUCache : public MRUCacheBase<KeyType, PayloadType, HashType, MRUCacheHashMap>
+{
+ private:
+ using ParentType = MRUCacheBase<KeyType, PayloadType, HashType, MRUCacheHashMap>;
+
+ public:
+ // See MRUCacheBase, noting the possibility of using NO_AUTO_EVICT.
+ explicit HashingMRUCache(typename ParentType::size_type max_size) : ParentType(max_size) {}
+ virtual ~HashingMRUCache() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HashingMRUCache);
+};
+
+} // namespace base
+
+} // namespace angle
+
+#endif // ANGLEBASE_CONTAINERS_MRU_CACHE_H_
diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/logging.h b/src/3rdparty/angle/src/common/third_party/base/anglebase/logging.h
new file mode 100644
index 0000000000..85ad82b47d
--- /dev/null
+++ b/src/3rdparty/angle/src/common/third_party/base/anglebase/logging.h
@@ -0,0 +1,26 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// logging.h: Compatiblity hacks for importing Chromium's base/numerics.
+
+#ifndef ANGLEBASE_LOGGING_H_
+#define ANGLEBASE_LOGGING_H_
+
+#include "common/debug.h"
+
+#ifndef DCHECK
+#define DCHECK(X) ASSERT(X)
+#endif
+
+#ifndef CHECK
+#define CHECK(X) ASSERT(X)
+#endif
+
+// Unfortunately ANGLE relies on ASSERT being an empty statement, which these libs don't respect.
+#ifndef NOTREACHED
+#define NOTREACHED() UNREACHABLE()
+#endif
+
+#endif // ANGLEBASE_LOGGING_H_
diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/macros.h b/src/3rdparty/angle/src/common/third_party/base/anglebase/macros.h
new file mode 100644
index 0000000000..06391784e4
--- /dev/null
+++ b/src/3rdparty/angle/src/common/third_party/base/anglebase/macros.h
@@ -0,0 +1,17 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// macros.h: Compatiblity hacks for importing Chromium's MRUCache.
+
+#ifndef ANGLEBASE_MACROS_H_
+#define ANGLEBASE_MACROS_H_
+
+// A macro to disallow the copy constructor and operator= functions.
+// This should be used in the private: declarations for a class.
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName &) = delete; \
+ void operator=(const TypeName &) = delete
+
+#endif // ANGLEBASE_MACROS_H_
diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/OWNERS b/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/OWNERS
new file mode 100644
index 0000000000..41f35fc79b
--- /dev/null
+++ b/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/OWNERS
@@ -0,0 +1,3 @@
+jschuh@chromium.org
+tsepez@chromium.org
+
diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_conversions.h b/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_conversions.h
new file mode 100644
index 0000000000..43babc31a8
--- /dev/null
+++ b/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_conversions.h
@@ -0,0 +1,179 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ANGLEBASE_NUMERICS_SAFE_CONVERSIONS_H_
+#define ANGLEBASE_NUMERICS_SAFE_CONVERSIONS_H_
+
+#include <stddef.h>
+
+#include <limits>
+#include <type_traits>
+
+#include "anglebase/logging.h"
+#include "anglebase/numerics/safe_conversions_impl.h"
+
+namespace angle
+{
+
+namespace base
+{
+
+// Convenience function that returns true if the supplied value is in range
+// for the destination type.
+template <typename Dst, typename Src>
+constexpr bool IsValueInRangeForNumericType(Src value)
+{
+ return internal::DstRangeRelationToSrcRange<Dst>(value) == internal::RANGE_VALID;
+}
+
+// Convenience function for determining if a numeric value is negative without
+// throwing compiler warnings on: unsigned(value) < 0.
+template <typename T>
+constexpr typename std::enable_if<std::numeric_limits<T>::is_signed, bool>::type IsValueNegative(
+ T value)
+{
+ static_assert(std::numeric_limits<T>::is_specialized, "Argument must be numeric.");
+ return value < 0;
+}
+
+template <typename T>
+constexpr typename std::enable_if<!std::numeric_limits<T>::is_signed, bool>::type IsValueNegative(T)
+{
+ static_assert(std::numeric_limits<T>::is_specialized, "Argument must be numeric.");
+ return false;
+}
+
+// checked_cast<> is analogous to static_cast<> for numeric types,
+// except that it CHECKs that the specified numeric conversion will not
+// overflow or underflow. NaN source will always trigger a CHECK.
+template <typename Dst, typename Src>
+inline Dst checked_cast(Src value)
+{
+ CHECK(IsValueInRangeForNumericType<Dst>(value));
+ return static_cast<Dst>(value);
+}
+
+// HandleNaN will cause this class to CHECK(false).
+struct SaturatedCastNaNBehaviorCheck
+{
+ template <typename T>
+ static T HandleNaN()
+ {
+ CHECK(false);
+ return T();
+ }
+};
+
+// HandleNaN will return 0 in this case.
+struct SaturatedCastNaNBehaviorReturnZero
+{
+ template <typename T>
+ static constexpr T HandleNaN()
+ {
+ return T();
+ }
+};
+
+namespace internal
+{
+// This wrapper is used for C++11 constexpr support by avoiding the declaration
+// of local variables in the saturated_cast template function.
+template <typename Dst, class NaNHandler, typename Src>
+constexpr Dst saturated_cast_impl(const Src value, const RangeConstraint constraint)
+{
+ return constraint == RANGE_VALID
+ ? static_cast<Dst>(value)
+ : (constraint == RANGE_UNDERFLOW
+ ? std::numeric_limits<Dst>::min()
+ : (constraint == RANGE_OVERFLOW
+ ? std::numeric_limits<Dst>::max()
+ : (constraint == RANGE_INVALID
+ ? NaNHandler::template HandleNaN<Dst>()
+ : (NOTREACHED(), static_cast<Dst>(value)))));
+}
+} // namespace internal
+
+// saturated_cast<> is analogous to static_cast<> for numeric types, except
+// that the specified numeric conversion will saturate rather than overflow or
+// underflow. NaN assignment to an integral will defer the behavior to a
+// specified class. By default, it will return 0.
+template <typename Dst, class NaNHandler = SaturatedCastNaNBehaviorReturnZero, typename Src>
+constexpr Dst saturated_cast(Src value)
+{
+ return std::numeric_limits<Dst>::is_iec559
+ ? static_cast<Dst>(value) // Floating point optimization.
+ : internal::saturated_cast_impl<Dst, NaNHandler>(
+ value, internal::DstRangeRelationToSrcRange<Dst>(value));
+}
+
+// strict_cast<> is analogous to static_cast<> for numeric types, except that
+// it will cause a compile failure if the destination type is not large enough
+// to contain any value in the source type. It performs no runtime checking.
+template <typename Dst, typename Src>
+constexpr Dst strict_cast(Src value)
+{
+ static_assert(std::numeric_limits<Src>::is_specialized, "Argument must be numeric.");
+ static_assert(std::numeric_limits<Dst>::is_specialized, "Result must be numeric.");
+ static_assert((internal::StaticDstRangeRelationToSrcRange<Dst, Src>::value ==
+ internal::NUMERIC_RANGE_CONTAINED),
+ "The numeric conversion is out of range for this type. You "
+ "should probably use one of the following conversion "
+ "mechanisms on the value you want to pass:\n"
+ "- base::checked_cast\n"
+ "- base::saturated_cast\n"
+ "- base::CheckedNumeric");
+
+ return static_cast<Dst>(value);
+}
+
+// StrictNumeric implements compile time range checking between numeric types by
+// wrapping assignment operations in a strict_cast. This class is intended to be
+// used for function arguments and return types, to ensure the destination type
+// can always contain the source type. This is essentially the same as enforcing
+// -Wconversion in gcc and C4302 warnings on MSVC, but it can be applied
+// incrementally at API boundaries, making it easier to convert code so that it
+// compiles cleanly with truncation warnings enabled.
+// This template should introduce no runtime overhead, but it also provides no
+// runtime checking of any of the associated mathematical operations. Use
+// CheckedNumeric for runtime range checks of the actual value being assigned.
+template <typename T>
+class StrictNumeric
+{
+ public:
+ typedef T type;
+
+ constexpr StrictNumeric() : value_(0) {}
+
+ // Copy constructor.
+ template <typename Src>
+ constexpr StrictNumeric(const StrictNumeric<Src> &rhs) : value_(strict_cast<T>(rhs.value_))
+ {
+ }
+
+ // This is not an explicit constructor because we implicitly upgrade regular
+ // numerics to StrictNumerics to make them easier to use.
+ template <typename Src>
+ constexpr StrictNumeric(Src value) : value_(strict_cast<T>(value))
+ {
+ }
+
+ // The numeric cast operator basically handles all the magic.
+ template <typename Dst>
+ constexpr operator Dst() const
+ {
+ return strict_cast<Dst>(value_);
+ }
+
+ private:
+ const T value_;
+};
+
+// Explicitly make a shorter size_t typedef for convenience.
+typedef StrictNumeric<size_t> SizeT;
+
+} // namespace base
+
+} // namespace angle
+
+#endif // ANGLEBASE_NUMERICS_SAFE_CONVERSIONS_H_
diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_conversions_impl.h b/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_conversions_impl.h
new file mode 100644
index 0000000000..10ed6c7a7f
--- /dev/null
+++ b/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_conversions_impl.h
@@ -0,0 +1,274 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ANGLEBASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_
+#define ANGLEBASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_
+
+#include <limits.h>
+#include <stdint.h>
+
+#include <climits>
+#include <limits>
+
+namespace angle
+{
+
+namespace base
+{
+namespace internal
+{
+
+// The std library doesn't provide a binary max_exponent for integers, however
+// we can compute one by adding one to the number of non-sign bits. This allows
+// for accurate range comparisons between floating point and integer types.
+template <typename NumericType>
+struct MaxExponent
+{
+ static_assert(std::is_arithmetic<NumericType>::value, "Argument must be numeric.");
+ static const int value =
+ std::numeric_limits<NumericType>::is_iec559
+ ? std::numeric_limits<NumericType>::max_exponent
+ : (sizeof(NumericType) * CHAR_BIT + 1 - std::numeric_limits<NumericType>::is_signed);
+};
+
+enum IntegerRepresentation
+{
+ INTEGER_REPRESENTATION_UNSIGNED,
+ INTEGER_REPRESENTATION_SIGNED
+};
+
+// A range for a given nunmeric Src type is contained for a given numeric Dst
+// type if both numeric_limits<Src>::max() <= numeric_limits<Dst>::max() and
+// numeric_limits<Src>::min() >= numeric_limits<Dst>::min() are true.
+// We implement this as template specializations rather than simple static
+// comparisons to ensure type correctness in our comparisons.
+enum NumericRangeRepresentation
+{
+ NUMERIC_RANGE_NOT_CONTAINED,
+ NUMERIC_RANGE_CONTAINED
+};
+
+// Helper templates to statically determine if our destination type can contain
+// maximum and minimum values represented by the source type.
+
+template <typename Dst,
+ typename Src,
+ IntegerRepresentation DstSign = std::numeric_limits<Dst>::is_signed
+ ? INTEGER_REPRESENTATION_SIGNED
+ : INTEGER_REPRESENTATION_UNSIGNED,
+ IntegerRepresentation SrcSign = std::numeric_limits<Src>::is_signed
+ ? INTEGER_REPRESENTATION_SIGNED
+ : INTEGER_REPRESENTATION_UNSIGNED>
+struct StaticDstRangeRelationToSrcRange;
+
+// Same sign: Dst is guaranteed to contain Src only if its range is equal or
+// larger.
+template <typename Dst, typename Src, IntegerRepresentation Sign>
+struct StaticDstRangeRelationToSrcRange<Dst, Src, Sign, Sign>
+{
+ static const NumericRangeRepresentation value =
+ MaxExponent<Dst>::value >= MaxExponent<Src>::value ? NUMERIC_RANGE_CONTAINED
+ : NUMERIC_RANGE_NOT_CONTAINED;
+};
+
+// Unsigned to signed: Dst is guaranteed to contain source only if its range is
+// larger.
+template <typename Dst, typename Src>
+struct StaticDstRangeRelationToSrcRange<Dst,
+ Src,
+ INTEGER_REPRESENTATION_SIGNED,
+ INTEGER_REPRESENTATION_UNSIGNED>
+{
+ static const NumericRangeRepresentation value =
+ MaxExponent<Dst>::value > MaxExponent<Src>::value ? NUMERIC_RANGE_CONTAINED
+ : NUMERIC_RANGE_NOT_CONTAINED;
+};
+
+// Signed to unsigned: Dst cannot be statically determined to contain Src.
+template <typename Dst, typename Src>
+struct StaticDstRangeRelationToSrcRange<Dst,
+ Src,
+ INTEGER_REPRESENTATION_UNSIGNED,
+ INTEGER_REPRESENTATION_SIGNED>
+{
+ static const NumericRangeRepresentation value = NUMERIC_RANGE_NOT_CONTAINED;
+};
+
+enum RangeConstraint : unsigned char
+{
+ RANGE_VALID = 0x0, // Value can be represented by the destination type.
+ RANGE_UNDERFLOW = 0x1, // Value would overflow.
+ RANGE_OVERFLOW = 0x2, // Value would underflow.
+ RANGE_INVALID = RANGE_UNDERFLOW | RANGE_OVERFLOW // Invalid (i.e. NaN).
+};
+
+// Helper function for coercing an int back to a RangeContraint.
+constexpr RangeConstraint GetRangeConstraint(int integer_range_constraint)
+{
+ // TODO(jschuh): Once we get full C++14 support we want this
+ // assert(integer_range_constraint >= RANGE_VALID &&
+ // integer_range_constraint <= RANGE_INVALID)
+ return static_cast<RangeConstraint>(integer_range_constraint);
+}
+
+// This function creates a RangeConstraint from an upper and lower bound
+// check by taking advantage of the fact that only NaN can be out of range in
+// both directions at once.
+constexpr inline RangeConstraint GetRangeConstraint(bool is_in_upper_bound, bool is_in_lower_bound)
+{
+ return GetRangeConstraint((is_in_upper_bound ? 0 : RANGE_OVERFLOW) |
+ (is_in_lower_bound ? 0 : RANGE_UNDERFLOW));
+}
+
+// The following helper template addresses a corner case in range checks for
+// conversion from a floating-point type to an integral type of smaller range
+// but larger precision (e.g. float -> unsigned). The problem is as follows:
+// 1. Integral maximum is always one less than a power of two, so it must be
+// truncated to fit the mantissa of the floating point. The direction of
+// rounding is implementation defined, but by default it's always IEEE
+// floats, which round to nearest and thus result in a value of larger
+// magnitude than the integral value.
+// Example: float f = UINT_MAX; // f is 4294967296f but UINT_MAX
+// // is 4294967295u.
+// 2. If the floating point value is equal to the promoted integral maximum
+// value, a range check will erroneously pass.
+// Example: (4294967296f <= 4294967295u) // This is true due to a precision
+// // loss in rounding up to float.
+// 3. When the floating point value is then converted to an integral, the
+// resulting value is out of range for the target integral type and
+// thus is implementation defined.
+// Example: unsigned u = (float)INT_MAX; // u will typically overflow to 0.
+// To fix this bug we manually truncate the maximum value when the destination
+// type is an integral of larger precision than the source floating-point type,
+// such that the resulting maximum is represented exactly as a floating point.
+template <typename Dst, typename Src>
+struct NarrowingRange
+{
+ typedef typename std::numeric_limits<Src> SrcLimits;
+ typedef typename std::numeric_limits<Dst> DstLimits;
+ // The following logic avoids warnings where the max function is
+ // instantiated with invalid values for a bit shift (even though
+ // such a function can never be called).
+ static const int shift = (MaxExponent<Src>::value > MaxExponent<Dst>::value &&
+ SrcLimits::digits < DstLimits::digits &&
+ SrcLimits::is_iec559 &&
+ DstLimits::is_integer)
+ ? (DstLimits::digits - SrcLimits::digits)
+ : 0;
+
+ static constexpr Dst max()
+ {
+ // We use UINTMAX_C below to avoid compiler warnings about shifting floating
+ // points. Since it's a compile time calculation, it shouldn't have any
+ // performance impact.
+ return DstLimits::max() - static_cast<Dst>((UINTMAX_C(1) << shift) - 1);
+ }
+
+ static constexpr Dst min()
+ {
+ return std::numeric_limits<Dst>::is_iec559 ? -DstLimits::max() : DstLimits::min();
+ }
+};
+
+template <typename Dst,
+ typename Src,
+ IntegerRepresentation DstSign = std::numeric_limits<Dst>::is_signed
+ ? INTEGER_REPRESENTATION_SIGNED
+ : INTEGER_REPRESENTATION_UNSIGNED,
+ IntegerRepresentation SrcSign = std::numeric_limits<Src>::is_signed
+ ? INTEGER_REPRESENTATION_SIGNED
+ : INTEGER_REPRESENTATION_UNSIGNED,
+ NumericRangeRepresentation DstRange = StaticDstRangeRelationToSrcRange<Dst, Src>::value>
+struct DstRangeRelationToSrcRangeImpl;
+
+// The following templates are for ranges that must be verified at runtime. We
+// split it into checks based on signedness to avoid confusing casts and
+// compiler warnings on signed an unsigned comparisons.
+
+// Dst range is statically determined to contain Src: Nothing to check.
+template <typename Dst, typename Src, IntegerRepresentation DstSign, IntegerRepresentation SrcSign>
+struct DstRangeRelationToSrcRangeImpl<Dst, Src, DstSign, SrcSign, NUMERIC_RANGE_CONTAINED>
+{
+ static constexpr RangeConstraint Check(Src value) { return RANGE_VALID; }
+};
+
+// Signed to signed narrowing: Both the upper and lower boundaries may be
+// exceeded.
+template <typename Dst, typename Src>
+struct DstRangeRelationToSrcRangeImpl<Dst,
+ Src,
+ INTEGER_REPRESENTATION_SIGNED,
+ INTEGER_REPRESENTATION_SIGNED,
+ NUMERIC_RANGE_NOT_CONTAINED>
+{
+ static constexpr RangeConstraint Check(Src value)
+ {
+ return GetRangeConstraint((value <= NarrowingRange<Dst, Src>::max()),
+ (value >= NarrowingRange<Dst, Src>::min()));
+ }
+};
+
+// Unsigned to unsigned narrowing: Only the upper boundary can be exceeded.
+template <typename Dst, typename Src>
+struct DstRangeRelationToSrcRangeImpl<Dst,
+ Src,
+ INTEGER_REPRESENTATION_UNSIGNED,
+ INTEGER_REPRESENTATION_UNSIGNED,
+ NUMERIC_RANGE_NOT_CONTAINED>
+{
+ static constexpr RangeConstraint Check(Src value)
+ {
+ return GetRangeConstraint(value <= NarrowingRange<Dst, Src>::max(), true);
+ }
+};
+
+// Unsigned to signed: The upper boundary may be exceeded.
+template <typename Dst, typename Src>
+struct DstRangeRelationToSrcRangeImpl<Dst,
+ Src,
+ INTEGER_REPRESENTATION_SIGNED,
+ INTEGER_REPRESENTATION_UNSIGNED,
+ NUMERIC_RANGE_NOT_CONTAINED>
+{
+ static constexpr RangeConstraint Check(Src value)
+ {
+ return sizeof(Dst) > sizeof(Src)
+ ? RANGE_VALID
+ : GetRangeConstraint(value <= static_cast<Src>(NarrowingRange<Dst, Src>::max()),
+ true);
+ }
+};
+
+// Signed to unsigned: The upper boundary may be exceeded for a narrower Dst,
+// and any negative value exceeds the lower boundary.
+template <typename Dst, typename Src>
+struct DstRangeRelationToSrcRangeImpl<Dst,
+ Src,
+ INTEGER_REPRESENTATION_UNSIGNED,
+ INTEGER_REPRESENTATION_SIGNED,
+ NUMERIC_RANGE_NOT_CONTAINED>
+{
+ static constexpr RangeConstraint Check(Src value)
+ {
+ return (MaxExponent<Dst>::value >= MaxExponent<Src>::value)
+ ? GetRangeConstraint(true, value >= static_cast<Src>(0))
+ : GetRangeConstraint(value <= static_cast<Src>(NarrowingRange<Dst, Src>::max()),
+ value >= static_cast<Src>(0));
+ }
+};
+
+template <typename Dst, typename Src>
+constexpr RangeConstraint DstRangeRelationToSrcRange(Src value)
+{
+ static_assert(std::numeric_limits<Src>::is_specialized, "Argument must be numeric.");
+ static_assert(std::numeric_limits<Dst>::is_specialized, "Result must be numeric.");
+ return DstRangeRelationToSrcRangeImpl<Dst, Src>::Check(value);
+}
+
+} // namespace internal
+} // namespace base
+
+} // namespace angle
+
+#endif // ANGLEBASE_NUMERICS_SAFE_CONVERSIONS_IMPL_H_
diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_math.h b/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_math.h
new file mode 100644
index 0000000000..3af4db63f7
--- /dev/null
+++ b/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_math.h
@@ -0,0 +1,329 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ANGLEBASE_NUMERICS_SAFE_MATH_H_
+#define ANGLEBASE_NUMERICS_SAFE_MATH_H_
+
+#include <stddef.h>
+
+#include <limits>
+#include <type_traits>
+
+#include "anglebase/logging.h"
+#include "anglebase/numerics/safe_math_impl.h"
+
+namespace angle
+{
+
+namespace base
+{
+
+namespace internal
+{
+
+// CheckedNumeric implements all the logic and operators for detecting integer
+// boundary conditions such as overflow, underflow, and invalid conversions.
+// The CheckedNumeric type implicitly converts from floating point and integer
+// data types, and contains overloads for basic arithmetic operations (i.e.: +,
+// -, *, /, %).
+//
+// The following methods convert from CheckedNumeric to standard numeric values:
+// IsValid() - Returns true if the underlying numeric value is valid (i.e. has
+// has not wrapped and is not the result of an invalid conversion).
+// ValueOrDie() - Returns the underlying value. If the state is not valid this
+// call will crash on a CHECK.
+// ValueOrDefault() - Returns the current value, or the supplied default if the
+// state is not valid.
+// ValueFloating() - Returns the underlying floating point value (valid only
+// only for floating point CheckedNumeric types).
+//
+// Bitwise operations are explicitly not supported, because correct
+// handling of some cases (e.g. sign manipulation) is ambiguous. Comparison
+// operations are explicitly not supported because they could result in a crash
+// on a CHECK condition. You should use patterns like the following for these
+// operations:
+// Bitwise operation:
+// CheckedNumeric<int> checked_int = untrusted_input_value;
+// int x = checked_int.ValueOrDefault(0) | kFlagValues;
+// Comparison:
+// CheckedNumeric<size_t> checked_size = untrusted_input_value;
+// checked_size += HEADER LENGTH;
+// if (checked_size.IsValid() && checked_size.ValueOrDie() < buffer_size)
+// Do stuff...
+template <typename T>
+class CheckedNumeric
+{
+ static_assert(std::is_arithmetic<T>::value, "CheckedNumeric<T>: T must be a numeric type.");
+
+ public:
+ typedef T type;
+
+ CheckedNumeric() {}
+
+ // Copy constructor.
+ template <typename Src>
+ CheckedNumeric(const CheckedNumeric<Src> &rhs) : state_(rhs.ValueUnsafe(), rhs.validity())
+ {
+ }
+
+ template <typename Src>
+ CheckedNumeric(Src value, RangeConstraint validity) : state_(value, validity)
+ {
+ }
+
+ // This is not an explicit constructor because we implicitly upgrade regular
+ // numerics to CheckedNumerics to make them easier to use.
+ template <typename Src>
+ CheckedNumeric(Src value) // NOLINT(runtime/explicit)
+ : state_(value)
+ {
+ static_assert(std::numeric_limits<Src>::is_specialized, "Argument must be numeric.");
+ }
+
+ // This is not an explicit constructor because we want a seamless conversion
+ // from StrictNumeric types.
+ template <typename Src>
+ CheckedNumeric(StrictNumeric<Src> value) // NOLINT(runtime/explicit)
+ : state_(static_cast<Src>(value))
+ {
+ }
+
+ // IsValid() is the public API to test if a CheckedNumeric is currently valid.
+ bool IsValid() const { return validity() == RANGE_VALID; }
+
+ // ValueOrDie() The primary accessor for the underlying value. If the current
+ // state is not valid it will CHECK and crash.
+ T ValueOrDie() const
+ {
+ CHECK(IsValid());
+ return state_.value();
+ }
+
+ // ValueOrDefault(T default_value) A convenience method that returns the
+ // current value if the state is valid, and the supplied default_value for
+ // any other state.
+ T ValueOrDefault(T default_value) const { return IsValid() ? state_.value() : default_value; }
+
+ // ValueFloating() - Since floating point values include their validity state,
+ // we provide an easy method for extracting them directly, without a risk of
+ // crashing on a CHECK.
+ T ValueFloating() const
+ {
+ static_assert(std::numeric_limits<T>::is_iec559, "Argument must be float.");
+ return CheckedNumeric<T>::cast(*this).ValueUnsafe();
+ }
+
+ // validity() - DO NOT USE THIS IN EXTERNAL CODE - It is public right now for
+ // tests and to avoid a big matrix of friend operator overloads. But the
+ // values it returns are likely to change in the future.
+ // Returns: current validity state (i.e. valid, overflow, underflow, nan).
+ // TODO(jschuh): crbug.com/332611 Figure out and implement semantics for
+ // saturation/wrapping so we can expose this state consistently and implement
+ // saturated arithmetic.
+ RangeConstraint validity() const { return state_.validity(); }
+
+ // ValueUnsafe() - DO NOT USE THIS IN EXTERNAL CODE - It is public right now
+ // for tests and to avoid a big matrix of friend operator overloads. But the
+ // values it returns are likely to change in the future.
+ // Returns: the raw numeric value, regardless of the current state.
+ // TODO(jschuh): crbug.com/332611 Figure out and implement semantics for
+ // saturation/wrapping so we can expose this state consistently and implement
+ // saturated arithmetic.
+ T ValueUnsafe() const { return state_.value(); }
+
+ // Prototypes for the supported arithmetic operator overloads.
+ template <typename Src>
+ CheckedNumeric &operator+=(Src rhs);
+ template <typename Src>
+ CheckedNumeric &operator-=(Src rhs);
+ template <typename Src>
+ CheckedNumeric &operator*=(Src rhs);
+ template <typename Src>
+ CheckedNumeric &operator/=(Src rhs);
+ template <typename Src>
+ CheckedNumeric &operator%=(Src rhs);
+
+ CheckedNumeric operator-() const
+ {
+ RangeConstraint validity;
+ T value = CheckedNeg(state_.value(), &validity);
+ // Negation is always valid for floating point.
+ if (std::numeric_limits<T>::is_iec559)
+ return CheckedNumeric<T>(value);
+
+ validity = GetRangeConstraint(state_.validity() | validity);
+ return CheckedNumeric<T>(value, validity);
+ }
+
+ CheckedNumeric Abs() const
+ {
+ RangeConstraint validity;
+ T value = CheckedAbs(state_.value(), &validity);
+ // Absolute value is always valid for floating point.
+ if (std::numeric_limits<T>::is_iec559)
+ return CheckedNumeric<T>(value);
+
+ validity = GetRangeConstraint(state_.validity() | validity);
+ return CheckedNumeric<T>(value, validity);
+ }
+
+ // This function is available only for integral types. It returns an unsigned
+ // integer of the same width as the source type, containing the absolute value
+ // of the source, and properly handling signed min.
+ CheckedNumeric<typename UnsignedOrFloatForSize<T>::type> UnsignedAbs() const
+ {
+ return CheckedNumeric<typename UnsignedOrFloatForSize<T>::type>(
+ CheckedUnsignedAbs(state_.value()), state_.validity());
+ }
+
+ CheckedNumeric &operator++()
+ {
+ *this += 1;
+ return *this;
+ }
+
+ CheckedNumeric operator++(int)
+ {
+ CheckedNumeric value = *this;
+ *this += 1;
+ return value;
+ }
+
+ CheckedNumeric &operator--()
+ {
+ *this -= 1;
+ return *this;
+ }
+
+ CheckedNumeric operator--(int)
+ {
+ CheckedNumeric value = *this;
+ *this -= 1;
+ return value;
+ }
+
+ // These static methods behave like a convenience cast operator targeting
+ // the desired CheckedNumeric type. As an optimization, a reference is
+ // returned when Src is the same type as T.
+ template <typename Src>
+ static CheckedNumeric<T> cast(
+ Src u,
+ typename std::enable_if<std::numeric_limits<Src>::is_specialized, int>::type = 0)
+ {
+ return u;
+ }
+
+ template <typename Src>
+ static CheckedNumeric<T> cast(
+ const CheckedNumeric<Src> &u,
+ typename std::enable_if<!std::is_same<Src, T>::value, int>::type = 0)
+ {
+ return u;
+ }
+
+ static const CheckedNumeric<T> &cast(const CheckedNumeric<T> &u) { return u; }
+
+ private:
+ template <typename NumericType>
+ struct UnderlyingType
+ {
+ using type = NumericType;
+ };
+
+ template <typename NumericType>
+ struct UnderlyingType<CheckedNumeric<NumericType>>
+ {
+ using type = NumericType;
+ };
+
+ CheckedNumericState<T> state_;
+};
+
+// This is the boilerplate for the standard arithmetic operator overloads. A
+// macro isn't the prettiest solution, but it beats rewriting these five times.
+// Some details worth noting are:
+// * We apply the standard arithmetic promotions.
+// * We skip range checks for floating points.
+// * We skip range checks for destination integers with sufficient range.
+// TODO(jschuh): extract these out into templates.
+#define ANGLEBASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP) \
+ /* Binary arithmetic operator for CheckedNumerics of the same type. */ \
+ template <typename T> \
+ CheckedNumeric<typename ArithmeticPromotion<T>::type> operator OP( \
+ const CheckedNumeric<T> &lhs, const CheckedNumeric<T> &rhs) \
+ { \
+ typedef typename ArithmeticPromotion<T>::type Promotion; \
+ /* Floating point always takes the fast path */ \
+ if (std::numeric_limits<T>::is_iec559) \
+ return CheckedNumeric<T>(lhs.ValueUnsafe() OP rhs.ValueUnsafe()); \
+ if (IsIntegerArithmeticSafe<Promotion, T, T>::value) \
+ return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs.ValueUnsafe(), \
+ GetRangeConstraint(rhs.validity() | lhs.validity())); \
+ RangeConstraint validity = RANGE_VALID; \
+ T result = \
+ static_cast<T>(Checked##NAME(static_cast<Promotion>(lhs.ValueUnsafe()), \
+ static_cast<Promotion>(rhs.ValueUnsafe()), &validity)); \
+ return CheckedNumeric<Promotion>( \
+ result, GetRangeConstraint(validity | lhs.validity() | rhs.validity())); \
+ } \
+ /* Assignment arithmetic operator implementation from CheckedNumeric. */ \
+ template <typename T> \
+ template <typename Src> \
+ CheckedNumeric<T> &CheckedNumeric<T>::operator COMPOUND_OP(Src rhs) \
+ { \
+ *this = CheckedNumeric<T>::cast(*this) \
+ OP CheckedNumeric<typename UnderlyingType<Src>::type>::cast(rhs); \
+ return *this; \
+ } \
+ /* Binary arithmetic operator for CheckedNumeric of different type. */ \
+ template <typename T, typename Src> \
+ CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \
+ const CheckedNumeric<Src> &lhs, const CheckedNumeric<T> &rhs) \
+ { \
+ typedef typename ArithmeticPromotion<T, Src>::type Promotion; \
+ if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \
+ return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs.ValueUnsafe(), \
+ GetRangeConstraint(rhs.validity() | lhs.validity())); \
+ return CheckedNumeric<Promotion>::cast(lhs) OP CheckedNumeric<Promotion>::cast(rhs); \
+ } \
+ /* Binary arithmetic operator for left CheckedNumeric and right numeric. */ \
+ template <typename T, typename Src, \
+ typename std::enable_if<std::is_arithmetic<Src>::value>::type * = nullptr> \
+ CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \
+ const CheckedNumeric<T> &lhs, Src rhs) \
+ { \
+ typedef typename ArithmeticPromotion<T, Src>::type Promotion; \
+ if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \
+ return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs, lhs.validity()); \
+ return CheckedNumeric<Promotion>::cast(lhs) OP CheckedNumeric<Promotion>::cast(rhs); \
+ } \
+ /* Binary arithmetic operator for left numeric and right CheckedNumeric. */ \
+ template <typename T, typename Src, \
+ typename std::enable_if<std::is_arithmetic<Src>::value>::type * = nullptr> \
+ CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \
+ Src lhs, const CheckedNumeric<T> &rhs) \
+ { \
+ typedef typename ArithmeticPromotion<T, Src>::type Promotion; \
+ if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \
+ return CheckedNumeric<Promotion>(lhs OP rhs.ValueUnsafe(), rhs.validity()); \
+ return CheckedNumeric<Promotion>::cast(lhs) OP CheckedNumeric<Promotion>::cast(rhs); \
+ }
+
+ANGLEBASE_NUMERIC_ARITHMETIC_OPERATORS(Add, +, +=)
+ANGLEBASE_NUMERIC_ARITHMETIC_OPERATORS(Sub, -, -=)
+ANGLEBASE_NUMERIC_ARITHMETIC_OPERATORS(Mul, *, *=)
+ANGLEBASE_NUMERIC_ARITHMETIC_OPERATORS(Div, /, /=)
+ANGLEBASE_NUMERIC_ARITHMETIC_OPERATORS(Mod, %, %=)
+
+#undef ANGLEBASE_NUMERIC_ARITHMETIC_OPERATORS
+
+} // namespace internal
+
+using internal::CheckedNumeric;
+
+} // namespace base
+
+} // namespace angle
+
+#endif // ANGLEBASE_NUMERICS_SAFE_MATH_H_
diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_math_impl.h b/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_math_impl.h
new file mode 100644
index 0000000000..2831cc6ceb
--- /dev/null
+++ b/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_math_impl.h
@@ -0,0 +1,575 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ANGLEBASE_NUMERICS_SAFE_MATH_IMPL_H_
+#define ANGLEBASE_NUMERICS_SAFE_MATH_IMPL_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <climits>
+#include <cmath>
+#include <cstdlib>
+#include <limits>
+#include <type_traits>
+
+#include "anglebase/numerics/safe_conversions.h"
+
+namespace angle
+{
+
+namespace base
+{
+namespace internal
+{
+
+// Everything from here up to the floating point operations is portable C++,
+// but it may not be fast. This code could be split based on
+// platform/architecture and replaced with potentially faster implementations.
+
+// Integer promotion templates used by the portable checked integer arithmetic.
+template <size_t Size, bool IsSigned>
+struct IntegerForSizeAndSign;
+template <>
+struct IntegerForSizeAndSign<1, true>
+{
+ typedef int8_t type;
+};
+template <>
+struct IntegerForSizeAndSign<1, false>
+{
+ typedef uint8_t type;
+};
+template <>
+struct IntegerForSizeAndSign<2, true>
+{
+ typedef int16_t type;
+};
+template <>
+struct IntegerForSizeAndSign<2, false>
+{
+ typedef uint16_t type;
+};
+template <>
+struct IntegerForSizeAndSign<4, true>
+{
+ typedef int32_t type;
+};
+template <>
+struct IntegerForSizeAndSign<4, false>
+{
+ typedef uint32_t type;
+};
+template <>
+struct IntegerForSizeAndSign<8, true>
+{
+ typedef int64_t type;
+};
+template <>
+struct IntegerForSizeAndSign<8, false>
+{
+ typedef uint64_t type;
+};
+
+// WARNING: We have no IntegerForSizeAndSign<16, *>. If we ever add one to
+// support 128-bit math, then the ArithmeticPromotion template below will need
+// to be updated (or more likely replaced with a decltype expression).
+
+template <typename Integer>
+struct UnsignedIntegerForSize
+{
+ typedef
+ typename std::enable_if<std::numeric_limits<Integer>::is_integer,
+ typename IntegerForSizeAndSign<sizeof(Integer), false>::type>::type
+ type;
+};
+
+template <typename Integer>
+struct SignedIntegerForSize
+{
+ typedef
+ typename std::enable_if<std::numeric_limits<Integer>::is_integer,
+ typename IntegerForSizeAndSign<sizeof(Integer), true>::type>::type
+ type;
+};
+
+template <typename Integer>
+struct TwiceWiderInteger
+{
+ typedef typename std::enable_if<
+ std::numeric_limits<Integer>::is_integer,
+ typename IntegerForSizeAndSign<sizeof(Integer) * 2,
+ std::numeric_limits<Integer>::is_signed>::type>::type type;
+};
+
+template <typename Integer>
+struct PositionOfSignBit
+{
+ static const typename std::enable_if<std::numeric_limits<Integer>::is_integer, size_t>::type
+ value = CHAR_BIT * sizeof(Integer) - 1;
+};
+
+// This is used for UnsignedAbs, where we need to support floating-point
+// template instantiations even though we don't actually support the operations.
+// However, there is no corresponding implementation of e.g. CheckedUnsignedAbs,
+// so the float versions will not compile.
+template <typename Numeric,
+ bool IsInteger = std::numeric_limits<Numeric>::is_integer,
+ bool IsFloat = std::numeric_limits<Numeric>::is_iec559>
+struct UnsignedOrFloatForSize;
+
+template <typename Numeric>
+struct UnsignedOrFloatForSize<Numeric, true, false>
+{
+ typedef typename UnsignedIntegerForSize<Numeric>::type type;
+};
+
+template <typename Numeric>
+struct UnsignedOrFloatForSize<Numeric, false, true>
+{
+ typedef Numeric type;
+};
+
+// Helper templates for integer manipulations.
+
+template <typename T>
+constexpr bool HasSignBit(T x)
+{
+ // Cast to unsigned since right shift on signed is undefined.
+ return !!(static_cast<typename UnsignedIntegerForSize<T>::type>(x) >>
+ PositionOfSignBit<T>::value);
+}
+
+// This wrapper undoes the standard integer promotions.
+template <typename T>
+constexpr T BinaryComplement(T x)
+{
+ return static_cast<T>(~x);
+}
+
+// Here are the actual portable checked integer math implementations.
+// TODO(jschuh): Break this code out from the enable_if pattern and find a clean
+// way to coalesce things into the CheckedNumericState specializations below.
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer, T>::type
+CheckedAdd(T x, T y, RangeConstraint *validity)
+{
+ // Since the value of x+y is undefined if we have a signed type, we compute
+ // it using the unsigned type of the same size.
+ typedef typename UnsignedIntegerForSize<T>::type UnsignedDst;
+ UnsignedDst ux = static_cast<UnsignedDst>(x);
+ UnsignedDst uy = static_cast<UnsignedDst>(y);
+ UnsignedDst uresult = static_cast<UnsignedDst>(ux + uy);
+ // Addition is valid if the sign of (x + y) is equal to either that of x or
+ // that of y.
+ if (std::numeric_limits<T>::is_signed)
+ {
+ if (HasSignBit(BinaryComplement(static_cast<UnsignedDst>((uresult ^ ux) & (uresult ^ uy)))))
+ {
+ *validity = RANGE_VALID;
+ }
+ else
+ { // Direction of wrap is inverse of result sign.
+ *validity = HasSignBit(uresult) ? RANGE_OVERFLOW : RANGE_UNDERFLOW;
+ }
+ }
+ else
+ { // Unsigned is either valid or overflow.
+ *validity = BinaryComplement(x) >= y ? RANGE_VALID : RANGE_OVERFLOW;
+ }
+ return static_cast<T>(uresult);
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer, T>::type
+CheckedSub(T x, T y, RangeConstraint *validity)
+{
+ // Since the value of x+y is undefined if we have a signed type, we compute
+ // it using the unsigned type of the same size.
+ typedef typename UnsignedIntegerForSize<T>::type UnsignedDst;
+ UnsignedDst ux = static_cast<UnsignedDst>(x);
+ UnsignedDst uy = static_cast<UnsignedDst>(y);
+ UnsignedDst uresult = static_cast<UnsignedDst>(ux - uy);
+ // Subtraction is valid if either x and y have same sign, or (x-y) and x have
+ // the same sign.
+ if (std::numeric_limits<T>::is_signed)
+ {
+ if (HasSignBit(BinaryComplement(static_cast<UnsignedDst>((uresult ^ ux) & (ux ^ uy)))))
+ {
+ *validity = RANGE_VALID;
+ }
+ else
+ { // Direction of wrap is inverse of result sign.
+ *validity = HasSignBit(uresult) ? RANGE_OVERFLOW : RANGE_UNDERFLOW;
+ }
+ }
+ else
+ { // Unsigned is either valid or underflow.
+ *validity = x >= y ? RANGE_VALID : RANGE_UNDERFLOW;
+ }
+ return static_cast<T>(uresult);
+}
+
+// Integer multiplication is a bit complicated. In the fast case we just
+// we just promote to a twice wider type, and range check the result. In the
+// slow case we need to manually check that the result won't be truncated by
+// checking with division against the appropriate bound.
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && sizeof(T) * 2 <= sizeof(uintmax_t),
+ T>::type
+CheckedMul(T x, T y, RangeConstraint *validity)
+{
+ typedef typename TwiceWiderInteger<T>::type IntermediateType;
+ IntermediateType tmp = static_cast<IntermediateType>(x) * static_cast<IntermediateType>(y);
+ *validity = DstRangeRelationToSrcRange<T>(tmp);
+ return static_cast<T>(tmp);
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed &&
+ (sizeof(T) * 2 > sizeof(uintmax_t)),
+ T>::type
+CheckedMul(T x, T y, RangeConstraint *validity)
+{
+ // If either side is zero then the result will be zero.
+ if (!x || !y)
+ {
+ *validity = RANGE_VALID;
+ return static_cast<T>(0);
+ }
+ else if (x > 0)
+ {
+ if (y > 0)
+ *validity = x <= std::numeric_limits<T>::max() / y ? RANGE_VALID : RANGE_OVERFLOW;
+ else
+ *validity = y >= std::numeric_limits<T>::min() / x ? RANGE_VALID : RANGE_UNDERFLOW;
+ }
+ else
+ {
+ if (y > 0)
+ *validity = x >= std::numeric_limits<T>::min() / y ? RANGE_VALID : RANGE_UNDERFLOW;
+ else
+ *validity = y >= std::numeric_limits<T>::max() / x ? RANGE_VALID : RANGE_OVERFLOW;
+ }
+
+ return static_cast<T>(x * y);
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed &&
+ (sizeof(T) * 2 > sizeof(uintmax_t)),
+ T>::type
+CheckedMul(T x, T y, RangeConstraint *validity)
+{
+ *validity = (y == 0 || x <= std::numeric_limits<T>::max() / y) ? RANGE_VALID : RANGE_OVERFLOW;
+ return static_cast<T>(x * y);
+}
+
+// Division just requires a check for an invalid negation on signed min/-1.
+template <typename T>
+T CheckedDiv(T x,
+ T y,
+ RangeConstraint *validity,
+ typename std::enable_if<std::numeric_limits<T>::is_integer, int>::type = 0)
+{
+ if (std::numeric_limits<T>::is_signed && x == std::numeric_limits<T>::min() &&
+ y == static_cast<T>(-1))
+ {
+ *validity = RANGE_OVERFLOW;
+ return std::numeric_limits<T>::min();
+ }
+
+ *validity = RANGE_VALID;
+ return static_cast<T>(x / y);
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed,
+ T>::type
+CheckedMod(T x, T y, RangeConstraint *validity)
+{
+ *validity = y > 0 ? RANGE_VALID : RANGE_INVALID;
+ return static_cast<T>(x % y);
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed,
+ T>::type
+CheckedMod(T x, T y, RangeConstraint *validity)
+{
+ *validity = RANGE_VALID;
+ return static_cast<T>(x % y);
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed,
+ T>::type
+CheckedNeg(T value, RangeConstraint *validity)
+{
+ *validity = value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW;
+ // The negation of signed min is min, so catch that one.
+ return static_cast<T>(-value);
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed,
+ T>::type
+CheckedNeg(T value, RangeConstraint *validity)
+{
+ // The only legal unsigned negation is zero.
+ *validity = value ? RANGE_UNDERFLOW : RANGE_VALID;
+ return static_cast<T>(-static_cast<typename SignedIntegerForSize<T>::type>(value));
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed,
+ T>::type
+CheckedAbs(T value, RangeConstraint *validity)
+{
+ *validity = value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW;
+ return static_cast<T>(std::abs(value));
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed,
+ T>::type
+CheckedAbs(T value, RangeConstraint *validity)
+{
+ // T is unsigned, so |value| must already be positive.
+ *validity = RANGE_VALID;
+ return value;
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed,
+ typename UnsignedIntegerForSize<T>::type>::type
+CheckedUnsignedAbs(T value)
+{
+ typedef typename UnsignedIntegerForSize<T>::type UnsignedT;
+ return value == std::numeric_limits<T>::min()
+ ? static_cast<UnsignedT>(std::numeric_limits<T>::max()) + 1
+ : static_cast<UnsignedT>(std::abs(value));
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed,
+ T>::type
+CheckedUnsignedAbs(T value)
+{
+ // T is unsigned, so |value| must already be positive.
+ return static_cast<T>(value);
+}
+
+// These are the floating point stubs that the compiler needs to see. Only the
+// negation operation is ever called.
+#define ANGLEBASE_FLOAT_ARITHMETIC_STUBS(NAME) \
+ template <typename T> \
+ typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type Checked##NAME( \
+ T, T, RangeConstraint *) \
+ { \
+ NOTREACHED(); \
+ return static_cast<T>(0); \
+ }
+
+ANGLEBASE_FLOAT_ARITHMETIC_STUBS(Add)
+ANGLEBASE_FLOAT_ARITHMETIC_STUBS(Sub)
+ANGLEBASE_FLOAT_ARITHMETIC_STUBS(Mul)
+ANGLEBASE_FLOAT_ARITHMETIC_STUBS(Div)
+ANGLEBASE_FLOAT_ARITHMETIC_STUBS(Mod)
+
+#undef ANGLEBASE_FLOAT_ARITHMETIC_STUBS
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type CheckedNeg(T value,
+ RangeConstraint *)
+{
+ return static_cast<T>(-value);
+}
+
+template <typename T>
+typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type CheckedAbs(T value,
+ RangeConstraint *)
+{
+ return static_cast<T>(std::abs(value));
+}
+
+// Floats carry around their validity state with them, but integers do not. So,
+// we wrap the underlying value in a specialization in order to hide that detail
+// and expose an interface via accessors.
+enum NumericRepresentation
+{
+ NUMERIC_INTEGER,
+ NUMERIC_FLOATING,
+ NUMERIC_UNKNOWN
+};
+
+template <typename NumericType>
+struct GetNumericRepresentation
+{
+ static const NumericRepresentation value =
+ std::numeric_limits<NumericType>::is_integer
+ ? NUMERIC_INTEGER
+ : (std::numeric_limits<NumericType>::is_iec559 ? NUMERIC_FLOATING : NUMERIC_UNKNOWN);
+};
+
+template <typename T, NumericRepresentation type = GetNumericRepresentation<T>::value>
+class CheckedNumericState
+{
+};
+
+// Integrals require quite a bit of additional housekeeping to manage state.
+template <typename T>
+class CheckedNumericState<T, NUMERIC_INTEGER>
+{
+ private:
+ T value_;
+ RangeConstraint validity_ : CHAR_BIT; // Actually requires only two bits.
+
+ public:
+ template <typename Src, NumericRepresentation type>
+ friend class CheckedNumericState;
+
+ CheckedNumericState() : value_(0), validity_(RANGE_VALID) {}
+
+ template <typename Src>
+ CheckedNumericState(Src value, RangeConstraint validity)
+ : value_(static_cast<T>(value)),
+ validity_(GetRangeConstraint(validity | DstRangeRelationToSrcRange<T>(value)))
+ {
+ static_assert(std::numeric_limits<Src>::is_specialized, "Argument must be numeric.");
+ }
+
+ // Copy constructor.
+ template <typename Src>
+ CheckedNumericState(const CheckedNumericState<Src> &rhs)
+ : value_(static_cast<T>(rhs.value())),
+ validity_(GetRangeConstraint(rhs.validity() | DstRangeRelationToSrcRange<T>(rhs.value())))
+ {
+ }
+
+ template <typename Src>
+ explicit CheckedNumericState(
+ Src value,
+ typename std::enable_if<std::numeric_limits<Src>::is_specialized, int>::type = 0)
+ : value_(static_cast<T>(value)), validity_(DstRangeRelationToSrcRange<T>(value))
+ {
+ }
+
+ RangeConstraint validity() const { return validity_; }
+ T value() const { return value_; }
+};
+
+// Floating points maintain their own validity, but need translation wrappers.
+template <typename T>
+class CheckedNumericState<T, NUMERIC_FLOATING>
+{
+ private:
+ T value_;
+
+ public:
+ template <typename Src, NumericRepresentation type>
+ friend class CheckedNumericState;
+
+ CheckedNumericState() : value_(0.0) {}
+
+ template <typename Src>
+ CheckedNumericState(
+ Src value,
+ RangeConstraint validity,
+ typename std::enable_if<std::numeric_limits<Src>::is_integer, int>::type = 0)
+ {
+ switch (DstRangeRelationToSrcRange<T>(value))
+ {
+ case RANGE_VALID:
+ value_ = static_cast<T>(value);
+ break;
+
+ case RANGE_UNDERFLOW:
+ value_ = -std::numeric_limits<T>::infinity();
+ break;
+
+ case RANGE_OVERFLOW:
+ value_ = std::numeric_limits<T>::infinity();
+ break;
+
+ case RANGE_INVALID:
+ value_ = std::numeric_limits<T>::quiet_NaN();
+ break;
+
+ default:
+ NOTREACHED();
+ }
+ }
+
+ template <typename Src>
+ explicit CheckedNumericState(
+ Src value,
+ typename std::enable_if<std::numeric_limits<Src>::is_specialized, int>::type = 0)
+ : value_(static_cast<T>(value))
+ {
+ }
+
+ // Copy constructor.
+ template <typename Src>
+ CheckedNumericState(const CheckedNumericState<Src> &rhs) : value_(static_cast<T>(rhs.value()))
+ {
+ }
+
+ RangeConstraint validity() const
+ {
+ return GetRangeConstraint(value_ <= std::numeric_limits<T>::max(),
+ value_ >= -std::numeric_limits<T>::max());
+ }
+ T value() const { return value_; }
+};
+
+// For integers less than 128-bit and floats 32-bit or larger, we have the type
+// with the larger maximum exponent take precedence.
+enum ArithmeticPromotionCategory
+{
+ LEFT_PROMOTION,
+ RIGHT_PROMOTION
+};
+
+template <typename Lhs,
+ typename Rhs = Lhs,
+ ArithmeticPromotionCategory Promotion =
+ (MaxExponent<Lhs>::value > MaxExponent<Rhs>::value) ? LEFT_PROMOTION
+ : RIGHT_PROMOTION>
+struct ArithmeticPromotion;
+
+template <typename Lhs, typename Rhs>
+struct ArithmeticPromotion<Lhs, Rhs, LEFT_PROMOTION>
+{
+ typedef Lhs type;
+};
+
+template <typename Lhs, typename Rhs>
+struct ArithmeticPromotion<Lhs, Rhs, RIGHT_PROMOTION>
+{
+ typedef Rhs type;
+};
+
+// We can statically check if operations on the provided types can wrap, so we
+// can skip the checked operations if they're not needed. So, for an integer we
+// care if the destination type preserves the sign and is twice the width of
+// the source.
+template <typename T, typename Lhs, typename Rhs>
+struct IsIntegerArithmeticSafe
+{
+ static const bool value =
+ !std::numeric_limits<T>::is_iec559 &&
+ StaticDstRangeRelationToSrcRange<T, Lhs>::value == NUMERIC_RANGE_CONTAINED &&
+ sizeof(T) >= (2 * sizeof(Lhs)) &&
+ StaticDstRangeRelationToSrcRange<T, Rhs>::value != NUMERIC_RANGE_CONTAINED &&
+ sizeof(T) >= (2 * sizeof(Rhs));
+};
+
+} // namespace internal
+} // namespace base
+
+} // namespace angle
+
+#endif // ANGLEBASE_NUMERICS_SAFE_MATH_IMPL_H_
diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_numerics_unittest.cc b/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_numerics_unittest.cc
new file mode 100644
index 0000000000..052d850427
--- /dev/null
+++ b/src/3rdparty/angle/src/common/third_party/base/anglebase/numerics/safe_numerics_unittest.cc
@@ -0,0 +1,771 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <limits>
+#include <type_traits>
+
+#include "base/compiler_specific.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/numerics/safe_math.h"
+#include "build/build_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS)
+#include <mmintrin.h>
+#endif
+
+using std::numeric_limits;
+using base::CheckedNumeric;
+using base::checked_cast;
+using base::IsValueInRangeForNumericType;
+using base::IsValueNegative;
+using base::SizeT;
+using base::StrictNumeric;
+using base::saturated_cast;
+using base::strict_cast;
+using base::internal::MaxExponent;
+using base::internal::RANGE_VALID;
+using base::internal::RANGE_INVALID;
+using base::internal::RANGE_OVERFLOW;
+using base::internal::RANGE_UNDERFLOW;
+using base::internal::SignedIntegerForSize;
+
+// These tests deliberately cause arithmetic overflows. If the compiler is
+// aggressive enough, it can const fold these overflows. Disable warnings about
+// overflows for const expressions.
+#if defined(OS_WIN)
+#pragma warning(disable : 4756)
+#endif
+
+// This is a helper function for finding the maximum value in Src that can be
+// wholy represented as the destination floating-point type.
+template <typename Dst, typename Src>
+Dst GetMaxConvertibleToFloat()
+{
+ typedef numeric_limits<Dst> DstLimits;
+ typedef numeric_limits<Src> SrcLimits;
+ static_assert(SrcLimits::is_specialized, "Source must be numeric.");
+ static_assert(DstLimits::is_specialized, "Destination must be numeric.");
+ CHECK(DstLimits::is_iec559);
+
+ if (SrcLimits::digits <= DstLimits::digits &&
+ MaxExponent<Src>::value <= MaxExponent<Dst>::value)
+ return SrcLimits::max();
+ Src max = SrcLimits::max() / 2 + (SrcLimits::is_integer ? 1 : 0);
+ while (max != static_cast<Src>(static_cast<Dst>(max)))
+ {
+ max /= 2;
+ }
+ return static_cast<Dst>(max);
+}
+
+// Helper macros to wrap displaying the conversion types and line numbers.
+#define TEST_EXPECTED_VALIDITY(expected, actual) \
+ EXPECT_EQ(expected, CheckedNumeric<Dst>(actual).IsValid()) \
+ << "Result test: Value " << +(actual).ValueUnsafe() << " as " << dst << " on line " \
+ << line;
+
+#define TEST_EXPECTED_SUCCESS(actual) TEST_EXPECTED_VALIDITY(true, actual)
+#define TEST_EXPECTED_FAILURE(actual) TEST_EXPECTED_VALIDITY(false, actual)
+
+#define TEST_EXPECTED_VALUE(expected, actual) \
+ EXPECT_EQ(static_cast<Dst>(expected), CheckedNumeric<Dst>(actual).ValueUnsafe()) \
+ << "Result test: Value " << +((actual).ValueUnsafe()) << " as " << dst << " on line " \
+ << line;
+
+// Signed integer arithmetic.
+template <typename Dst>
+static void TestSpecializedArithmetic(
+ const char *dst,
+ int line,
+ typename std::enable_if<numeric_limits<Dst>::is_integer && numeric_limits<Dst>::is_signed,
+ int>::type = 0)
+{
+ typedef numeric_limits<Dst> DstLimits;
+ TEST_EXPECTED_FAILURE(-CheckedNumeric<Dst>(DstLimits::min()));
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()).Abs());
+ TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
+
+ TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + -1);
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) + -1);
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) + -DstLimits::max());
+
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) - 1);
+ TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) - -1);
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - -DstLimits::max());
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) - DstLimits::max());
+
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) * 2);
+
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) / -1);
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) / 2);
+
+ // Modulus is legal only for integers.
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
+ TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % 2);
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-1) % -2);
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) % 2);
+ TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
+ // Test all the different modulus combinations.
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
+ CheckedNumeric<Dst> checked_dst = 1;
+ TEST_EXPECTED_VALUE(0, checked_dst %= 1);
+}
+
+// Unsigned integer arithmetic.
+template <typename Dst>
+static void TestSpecializedArithmetic(
+ const char *dst,
+ int line,
+ typename std::enable_if<numeric_limits<Dst>::is_integer && !numeric_limits<Dst>::is_signed,
+ int>::type = 0)
+{
+ typedef numeric_limits<Dst> DstLimits;
+ TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::min()));
+ TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()).Abs());
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) + -1);
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::min()) - 1);
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) * 2);
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) / 2);
+ TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()).UnsignedAbs());
+ TEST_EXPECTED_SUCCESS(CheckedNumeric<typename SignedIntegerForSize<Dst>::type>(
+ std::numeric_limits<typename SignedIntegerForSize<Dst>::type>::min())
+ .UnsignedAbs());
+
+ // Modulus is legal only for integers.
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
+ TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % 2);
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::min()) % 2);
+ TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
+ // Test all the different modulus combinations.
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
+ CheckedNumeric<Dst> checked_dst = 1;
+ TEST_EXPECTED_VALUE(0, checked_dst %= 1);
+}
+
+// Floating point arithmetic.
+template <typename Dst>
+void TestSpecializedArithmetic(
+ const char *dst,
+ int line,
+ typename std::enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0)
+{
+ typedef numeric_limits<Dst> DstLimits;
+ TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::min()));
+
+ TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()).Abs());
+ TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
+
+ TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) + -1);
+ TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + 1);
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) + -DstLimits::max());
+
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - -DstLimits::max());
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(-DstLimits::max()) - DstLimits::max());
+
+ TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) * 2);
+
+ TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2);
+ EXPECT_EQ(static_cast<Dst>(1.0), CheckedNumeric<Dst>(1.0).ValueFloating());
+}
+
+// Generic arithmetic tests.
+template <typename Dst>
+static void TestArithmetic(const char *dst, int line)
+{
+ typedef numeric_limits<Dst> DstLimits;
+
+ EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid());
+ EXPECT_EQ(
+ false,
+ CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) * DstLimits::max()).IsValid());
+ EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDie());
+ EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDefault(1));
+ EXPECT_EQ(static_cast<Dst>(1),
+ CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) * DstLimits::max())
+ .ValueOrDefault(1));
+
+ // Test the operator combinations.
+ TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(2, 1 + CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(0, 1 - CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(1, 1 * CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(1, 1 / CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + 1);
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - 1);
+ TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * 1);
+ TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
+ CheckedNumeric<Dst> checked_dst = 1;
+ TEST_EXPECTED_VALUE(2, checked_dst += 1);
+ checked_dst = 1;
+ TEST_EXPECTED_VALUE(0, checked_dst -= 1);
+ checked_dst = 1;
+ TEST_EXPECTED_VALUE(1, checked_dst *= 1);
+ checked_dst = 1;
+ TEST_EXPECTED_VALUE(1, checked_dst /= 1);
+
+ // Generic negation.
+ TEST_EXPECTED_VALUE(0, -CheckedNumeric<Dst>());
+ TEST_EXPECTED_VALUE(-1, -CheckedNumeric<Dst>(1));
+ TEST_EXPECTED_VALUE(1, -CheckedNumeric<Dst>(-1));
+ TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1),
+ -CheckedNumeric<Dst>(DstLimits::max()));
+
+ // Generic absolute value.
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>().Abs());
+ TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).Abs());
+ TEST_EXPECTED_VALUE(DstLimits::max(), CheckedNumeric<Dst>(DstLimits::max()).Abs());
+
+ // Generic addition.
+ TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>() + 1));
+ TEST_EXPECTED_VALUE(2, (CheckedNumeric<Dst>(1) + 1));
+ TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) + 1));
+ TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::min()) + 1);
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) + DstLimits::max());
+
+ // Generic subtraction.
+ TEST_EXPECTED_VALUE(-1, (CheckedNumeric<Dst>() - 1));
+ TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(1) - 1));
+ TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) - 1));
+ TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) - 1);
+
+ // Generic multiplication.
+ TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>() * 1));
+ TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>(1) * 1));
+ TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) * 2));
+ TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * 0));
+ TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) * 0));
+ TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * -1));
+ TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) * DstLimits::max());
+
+ // Generic division.
+ TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() / 1);
+ TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
+ TEST_EXPECTED_VALUE(DstLimits::min() / 2, CheckedNumeric<Dst>(DstLimits::min()) / 2);
+ TEST_EXPECTED_VALUE(DstLimits::max() / 2, CheckedNumeric<Dst>(DstLimits::max()) / 2);
+
+ TestSpecializedArithmetic<Dst>(dst, line);
+}
+
+// Helper macro to wrap displaying the conversion types and line numbers.
+#define TEST_ARITHMETIC(Dst) TestArithmetic<Dst>(#Dst, __LINE__)
+
+TEST(SafeNumerics, SignedIntegerMath)
+{
+ TEST_ARITHMETIC(int8_t);
+ TEST_ARITHMETIC(int);
+ TEST_ARITHMETIC(intptr_t);
+ TEST_ARITHMETIC(intmax_t);
+}
+
+TEST(SafeNumerics, UnsignedIntegerMath)
+{
+ TEST_ARITHMETIC(uint8_t);
+ TEST_ARITHMETIC(unsigned int);
+ TEST_ARITHMETIC(uintptr_t);
+ TEST_ARITHMETIC(uintmax_t);
+}
+
+TEST(SafeNumerics, FloatingPointMath)
+{
+ TEST_ARITHMETIC(float);
+ TEST_ARITHMETIC(double);
+}
+
+// Enumerates the five different conversions types we need to test.
+enum NumericConversionType
+{
+ SIGN_PRESERVING_VALUE_PRESERVING,
+ SIGN_PRESERVING_NARROW,
+ SIGN_TO_UNSIGN_WIDEN_OR_EQUAL,
+ SIGN_TO_UNSIGN_NARROW,
+ UNSIGN_TO_SIGN_NARROW_OR_EQUAL,
+};
+
+// Template covering the different conversion tests.
+template <typename Dst, typename Src, NumericConversionType conversion>
+struct TestNumericConversion
+{
+};
+
+// EXPECT_EQ wrappers providing specific detail on test failures.
+#define TEST_EXPECTED_RANGE(expected, actual) \
+ EXPECT_EQ(expected, base::internal::DstRangeRelationToSrcRange<Dst>(actual)) \
+ << "Conversion test: " << src << " value " << actual << " to " << dst << " on line " \
+ << line;
+
+template <typename Dst, typename Src>
+struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING>
+{
+ static void Test(const char *dst, const char *src, int line)
+ {
+ typedef numeric_limits<Src> SrcLimits;
+ typedef numeric_limits<Dst> DstLimits;
+ // Integral to floating.
+ static_assert(
+ (DstLimits::is_iec559 && SrcLimits::is_integer) ||
+ // Not floating to integral and...
+ (!(DstLimits::is_integer && SrcLimits::is_iec559) &&
+ // Same sign, same numeric, source is narrower or same.
+ ((SrcLimits::is_signed == DstLimits::is_signed && sizeof(Dst) >= sizeof(Src)) ||
+ // Or signed destination and source is smaller
+ (DstLimits::is_signed && sizeof(Dst) > sizeof(Src)))),
+ "Comparison must be sign preserving and value preserving");
+
+ const CheckedNumeric<Dst> checked_dst = SrcLimits::max();
+ TEST_EXPECTED_SUCCESS(checked_dst);
+ if (MaxExponent<Dst>::value > MaxExponent<Src>::value)
+ {
+ if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1)
+ {
+ // At least twice larger type.
+ TEST_EXPECTED_SUCCESS(SrcLimits::max() * checked_dst);
+ }
+ else
+ { // Larger, but not at least twice as large.
+ TEST_EXPECTED_FAILURE(SrcLimits::max() * checked_dst);
+ TEST_EXPECTED_SUCCESS(checked_dst + 1);
+ }
+ }
+ else
+ { // Same width type.
+ TEST_EXPECTED_FAILURE(checked_dst + 1);
+ }
+
+ TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
+ if (SrcLimits::is_iec559)
+ {
+ TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max() * static_cast<Src>(-1));
+ TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
+ TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
+ TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
+ }
+ else if (numeric_limits<Src>::is_signed)
+ {
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
+ TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
+ }
+ }
+};
+
+template <typename Dst, typename Src>
+struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW>
+{
+ static void Test(const char *dst, const char *src, int line)
+ {
+ typedef numeric_limits<Src> SrcLimits;
+ typedef numeric_limits<Dst> DstLimits;
+ static_assert(SrcLimits::is_signed == DstLimits::is_signed,
+ "Destination and source sign must be the same");
+ static_assert(sizeof(Dst) < sizeof(Src) || (DstLimits::is_integer && SrcLimits::is_iec559),
+ "Destination must be narrower than source");
+
+ const CheckedNumeric<Dst> checked_dst;
+ TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
+ TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
+ TEST_EXPECTED_FAILURE(checked_dst - SrcLimits::max());
+
+ TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
+ if (SrcLimits::is_iec559)
+ {
+ TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
+ TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
+ TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
+ TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
+ if (DstLimits::is_integer)
+ {
+ if (SrcLimits::digits < DstLimits::digits)
+ {
+ TEST_EXPECTED_RANGE(RANGE_OVERFLOW, static_cast<Src>(DstLimits::max()));
+ }
+ else
+ {
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
+ }
+ TEST_EXPECTED_RANGE(RANGE_VALID,
+ static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::min()));
+ }
+ }
+ else if (SrcLimits::is_signed)
+ {
+ TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1));
+ TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
+ }
+ else
+ {
+ TEST_EXPECTED_FAILURE(checked_dst - static_cast<Src>(1));
+ TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
+ }
+ }
+};
+
+template <typename Dst, typename Src>
+struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL>
+{
+ static void Test(const char *dst, const char *src, int line)
+ {
+ typedef numeric_limits<Src> SrcLimits;
+ typedef numeric_limits<Dst> DstLimits;
+ static_assert(sizeof(Dst) >= sizeof(Src),
+ "Destination must be equal or wider than source.");
+ static_assert(SrcLimits::is_signed, "Source must be signed");
+ static_assert(!DstLimits::is_signed, "Destination must be unsigned");
+
+ const CheckedNumeric<Dst> checked_dst;
+ TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max());
+ TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
+ TEST_EXPECTED_FAILURE(checked_dst + -SrcLimits::max());
+
+ TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
+ TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
+ TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
+ }
+};
+
+template <typename Dst, typename Src>
+struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW>
+{
+ static void Test(const char *dst, const char *src, int line)
+ {
+ typedef numeric_limits<Src> SrcLimits;
+ typedef numeric_limits<Dst> DstLimits;
+ static_assert(
+ (DstLimits::is_integer && SrcLimits::is_iec559) || (sizeof(Dst) < sizeof(Src)),
+ "Destination must be narrower than source.");
+ static_assert(SrcLimits::is_signed, "Source must be signed.");
+ static_assert(!DstLimits::is_signed, "Destination must be unsigned.");
+
+ const CheckedNumeric<Dst> checked_dst;
+ TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
+ TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
+ TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
+ TEST_EXPECTED_FAILURE(checked_dst + -SrcLimits::max());
+
+ TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
+ TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
+ if (SrcLimits::is_iec559)
+ {
+ TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
+ TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
+ TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
+ TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
+ if (DstLimits::is_integer)
+ {
+ if (SrcLimits::digits < DstLimits::digits)
+ {
+ TEST_EXPECTED_RANGE(RANGE_OVERFLOW, static_cast<Src>(DstLimits::max()));
+ }
+ else
+ {
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
+ }
+ TEST_EXPECTED_RANGE(RANGE_VALID,
+ static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::min()));
+ }
+ }
+ else
+ {
+ TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min());
+ }
+ }
+};
+
+template <typename Dst, typename Src>
+struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL>
+{
+ static void Test(const char *dst, const char *src, int line)
+ {
+ typedef numeric_limits<Src> SrcLimits;
+ typedef numeric_limits<Dst> DstLimits;
+ static_assert(sizeof(Dst) <= sizeof(Src),
+ "Destination must be narrower or equal to source.");
+ static_assert(!SrcLimits::is_signed, "Source must be unsigned.");
+ static_assert(DstLimits::is_signed, "Destination must be signed.");
+
+ const CheckedNumeric<Dst> checked_dst;
+ TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
+ TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
+ TEST_EXPECTED_VALUE(SrcLimits::min(), checked_dst + SrcLimits::min());
+
+ TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min());
+ TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
+ TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
+ }
+};
+
+// Helper macro to wrap displaying the conversion types and line numbers
+#define TEST_NUMERIC_CONVERSION(d, s, t) TestNumericConversion<d, s, t>::Test(#d, #s, __LINE__)
+
+TEST(SafeNumerics, IntMinOperations)
+{
+ TEST_NUMERIC_CONVERSION(int8_t, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(uint8_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
+
+ TEST_NUMERIC_CONVERSION(int8_t, int, SIGN_PRESERVING_NARROW);
+ TEST_NUMERIC_CONVERSION(uint8_t, unsigned int, SIGN_PRESERVING_NARROW);
+ TEST_NUMERIC_CONVERSION(int8_t, float, SIGN_PRESERVING_NARROW);
+
+ TEST_NUMERIC_CONVERSION(uint8_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
+
+ TEST_NUMERIC_CONVERSION(uint8_t, int, SIGN_TO_UNSIGN_NARROW);
+ TEST_NUMERIC_CONVERSION(uint8_t, intmax_t, SIGN_TO_UNSIGN_NARROW);
+ TEST_NUMERIC_CONVERSION(uint8_t, float, SIGN_TO_UNSIGN_NARROW);
+
+ TEST_NUMERIC_CONVERSION(int8_t, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
+ TEST_NUMERIC_CONVERSION(int8_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
+}
+
+TEST(SafeNumerics, IntOperations)
+{
+ TEST_NUMERIC_CONVERSION(int, int, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(unsigned int, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(int, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(unsigned int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
+
+ TEST_NUMERIC_CONVERSION(int, intmax_t, SIGN_PRESERVING_NARROW);
+ TEST_NUMERIC_CONVERSION(unsigned int, uintmax_t, SIGN_PRESERVING_NARROW);
+ TEST_NUMERIC_CONVERSION(int, float, SIGN_PRESERVING_NARROW);
+ TEST_NUMERIC_CONVERSION(int, double, SIGN_PRESERVING_NARROW);
+
+ TEST_NUMERIC_CONVERSION(unsigned int, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
+ TEST_NUMERIC_CONVERSION(unsigned int, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
+
+ TEST_NUMERIC_CONVERSION(unsigned int, intmax_t, SIGN_TO_UNSIGN_NARROW);
+ TEST_NUMERIC_CONVERSION(unsigned int, float, SIGN_TO_UNSIGN_NARROW);
+ TEST_NUMERIC_CONVERSION(unsigned int, double, SIGN_TO_UNSIGN_NARROW);
+
+ TEST_NUMERIC_CONVERSION(int, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
+ TEST_NUMERIC_CONVERSION(int, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
+}
+
+TEST(SafeNumerics, IntMaxOperations)
+{
+ TEST_NUMERIC_CONVERSION(intmax_t, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(uintmax_t, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(intmax_t, int, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(uintmax_t, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(intmax_t, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(intmax_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
+
+ TEST_NUMERIC_CONVERSION(intmax_t, float, SIGN_PRESERVING_NARROW);
+ TEST_NUMERIC_CONVERSION(intmax_t, double, SIGN_PRESERVING_NARROW);
+
+ TEST_NUMERIC_CONVERSION(uintmax_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
+ TEST_NUMERIC_CONVERSION(uintmax_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
+
+ TEST_NUMERIC_CONVERSION(uintmax_t, float, SIGN_TO_UNSIGN_NARROW);
+ TEST_NUMERIC_CONVERSION(uintmax_t, double, SIGN_TO_UNSIGN_NARROW);
+
+ TEST_NUMERIC_CONVERSION(intmax_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
+}
+
+TEST(SafeNumerics, FloatOperations)
+{
+ TEST_NUMERIC_CONVERSION(float, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(float, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(float, int, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(float, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
+
+ TEST_NUMERIC_CONVERSION(float, double, SIGN_PRESERVING_NARROW);
+}
+
+TEST(SafeNumerics, DoubleOperations)
+{
+ TEST_NUMERIC_CONVERSION(double, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(double, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(double, int, SIGN_PRESERVING_VALUE_PRESERVING);
+ TEST_NUMERIC_CONVERSION(double, unsigned int, SIGN_PRESERVING_VALUE_PRESERVING);
+}
+
+TEST(SafeNumerics, SizeTOperations)
+{
+ TEST_NUMERIC_CONVERSION(size_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
+ TEST_NUMERIC_CONVERSION(int, size_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
+}
+
+TEST(SafeNumerics, CastTests)
+{
+// MSVC catches and warns that we're forcing saturation in these tests.
+// Since that's intentional, we need to shut this warning off.
+#if defined(COMPILER_MSVC)
+#pragma warning(disable : 4756)
+#endif
+
+ int small_positive = 1;
+ int small_negative = -1;
+ double double_small = 1.0;
+ double double_large = numeric_limits<double>::max();
+ double double_infinity = numeric_limits<float>::infinity();
+ double double_large_int = numeric_limits<int>::max();
+ double double_small_int = numeric_limits<int>::min();
+
+ // Just test that the casts compile, since the other tests cover logic.
+ EXPECT_EQ(0, checked_cast<int>(static_cast<size_t>(0)));
+ EXPECT_EQ(0, strict_cast<int>(static_cast<char>(0)));
+ EXPECT_EQ(0, strict_cast<int>(static_cast<unsigned char>(0)));
+ EXPECT_EQ(0U, strict_cast<unsigned>(static_cast<unsigned char>(0)));
+ EXPECT_EQ(1ULL, static_cast<uint64_t>(StrictNumeric<size_t>(1U)));
+ EXPECT_EQ(1ULL, static_cast<uint64_t>(SizeT(1U)));
+ EXPECT_EQ(1U, static_cast<size_t>(StrictNumeric<unsigned>(1U)));
+
+ EXPECT_TRUE(CheckedNumeric<uint64_t>(StrictNumeric<unsigned>(1U)).IsValid());
+ EXPECT_TRUE(CheckedNumeric<int>(StrictNumeric<unsigned>(1U)).IsValid());
+ EXPECT_FALSE(CheckedNumeric<unsigned>(StrictNumeric<int>(-1)).IsValid());
+
+ EXPECT_TRUE(IsValueNegative(-1));
+ EXPECT_TRUE(IsValueNegative(numeric_limits<int>::min()));
+ EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::min()));
+ EXPECT_TRUE(IsValueNegative(-numeric_limits<double>::max()));
+ EXPECT_FALSE(IsValueNegative(0));
+ EXPECT_FALSE(IsValueNegative(1));
+ EXPECT_FALSE(IsValueNegative(0u));
+ EXPECT_FALSE(IsValueNegative(1u));
+ EXPECT_FALSE(IsValueNegative(numeric_limits<int>::max()));
+ EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::max()));
+ EXPECT_FALSE(IsValueNegative(numeric_limits<double>::max()));
+
+ // These casts and coercions will fail to compile:
+ // EXPECT_EQ(0, strict_cast<int>(static_cast<size_t>(0)));
+ // EXPECT_EQ(0, strict_cast<size_t>(static_cast<int>(0)));
+ // EXPECT_EQ(1ULL, StrictNumeric<size_t>(1));
+ // EXPECT_EQ(1, StrictNumeric<size_t>(1U));
+
+ // Test various saturation corner cases.
+ EXPECT_EQ(saturated_cast<int>(small_negative), static_cast<int>(small_negative));
+ EXPECT_EQ(saturated_cast<int>(small_positive), static_cast<int>(small_positive));
+ EXPECT_EQ(saturated_cast<unsigned>(small_negative), static_cast<unsigned>(0));
+ EXPECT_EQ(saturated_cast<int>(double_small), static_cast<int>(double_small));
+ EXPECT_EQ(saturated_cast<int>(double_large), numeric_limits<int>::max());
+ EXPECT_EQ(saturated_cast<float>(double_large), double_infinity);
+ EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity);
+ EXPECT_EQ(numeric_limits<int>::min(), saturated_cast<int>(double_small_int));
+ EXPECT_EQ(numeric_limits<int>::max(), saturated_cast<int>(double_large_int));
+
+ float not_a_number =
+ std::numeric_limits<float>::infinity() - std::numeric_limits<float>::infinity();
+ EXPECT_TRUE(std::isnan(not_a_number));
+ EXPECT_EQ(0, saturated_cast<int>(not_a_number));
+}
+
+#if GTEST_HAS_DEATH_TEST
+
+TEST(SafeNumerics, SaturatedCastChecks)
+{
+ float not_a_number =
+ std::numeric_limits<float>::infinity() - std::numeric_limits<float>::infinity();
+ EXPECT_TRUE(std::isnan(not_a_number));
+ EXPECT_DEATH((saturated_cast<int, base::SaturatedCastNaNBehaviorCheck>(not_a_number)), "");
+}
+
+#endif // GTEST_HAS_DEATH_TEST
+
+TEST(SafeNumerics, IsValueInRangeForNumericType)
+{
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(1));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(2));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(-1));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0xffffffffu));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0xffffffff)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000000)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000001)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(std::numeric_limits<int32_t>::min()));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(std::numeric_limits<int64_t>::min()));
+
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(1));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(2));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(-1));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffff));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffffu));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0x80000000u));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0xffffffffu));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x80000000)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0xffffffff)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x100000000)));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(std::numeric_limits<int32_t>::min()));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
+ static_cast<int64_t>(std::numeric_limits<int32_t>::min())));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
+ static_cast<int64_t>(std::numeric_limits<int32_t>::min()) - 1));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(std::numeric_limits<int64_t>::min()));
+
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(1));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(2));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(-1));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0xffffffffu));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0xffffffff)));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000000)));
+ EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000001)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(std::numeric_limits<int32_t>::min()));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(INT64_C(-1)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(std::numeric_limits<int64_t>::min()));
+
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(1));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(2));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(-1));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffff));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffffu));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x80000000u));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0xffffffffu));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x80000000)));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0xffffffff)));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x100000000)));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x7fffffffffffffff)));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(UINT64_C(0x7fffffffffffffff)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int64_t>(UINT64_C(0x8000000000000000)));
+ EXPECT_FALSE(IsValueInRangeForNumericType<int64_t>(UINT64_C(0xffffffffffffffff)));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(std::numeric_limits<int32_t>::min()));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
+ static_cast<int64_t>(std::numeric_limits<int32_t>::min())));
+ EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(std::numeric_limits<int64_t>::min()));
+}
+
+TEST(SafeNumerics, CompoundNumericOperations)
+{
+ CheckedNumeric<int> a = 1;
+ CheckedNumeric<int> b = 2;
+ CheckedNumeric<int> c = 3;
+ CheckedNumeric<int> d = 4;
+ a += b;
+ EXPECT_EQ(3, a.ValueOrDie());
+ a -= c;
+ EXPECT_EQ(0, a.ValueOrDie());
+ d /= b;
+ EXPECT_EQ(2, d.ValueOrDie());
+ d *= d;
+ EXPECT_EQ(4, d.ValueOrDie());
+
+ CheckedNumeric<int> too_large = std::numeric_limits<int>::max();
+ EXPECT_TRUE(too_large.IsValid());
+ too_large += d;
+ EXPECT_FALSE(too_large.IsValid());
+ too_large -= d;
+ EXPECT_FALSE(too_large.IsValid());
+ too_large /= d;
+ EXPECT_FALSE(too_large.IsValid());
+}
diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/sha1.cc b/src/3rdparty/angle/src/common/third_party/base/anglebase/sha1.cc
new file mode 100644
index 0000000000..cb88ba06e1
--- /dev/null
+++ b/src/3rdparty/angle/src/common/third_party/base/anglebase/sha1.cc
@@ -0,0 +1,245 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "anglebase/sha1.h"
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "anglebase/sys_byteorder.h"
+
+namespace angle
+{
+
+namespace base
+{
+
+// Implementation of SHA-1. Only handles data in byte-sized blocks,
+// which simplifies the code a fair bit.
+
+// Identifier names follow notation in FIPS PUB 180-3, where you'll
+// also find a description of the algorithm:
+// http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf
+
+// Usage example:
+//
+// SecureHashAlgorithm sha;
+// while(there is data to hash)
+// sha.Update(moredata, size of data);
+// sha.Final();
+// memcpy(somewhere, sha.Digest(), 20);
+//
+// to reuse the instance of sha, call sha.Init();
+
+// TODO(jhawkins): Replace this implementation with a per-platform
+// implementation using each platform's crypto library. See
+// http://crbug.com/47218
+
+class SecureHashAlgorithm
+{
+ public:
+ SecureHashAlgorithm() { Init(); }
+
+ static const int kDigestSizeBytes;
+
+ void Init();
+ void Update(const void *data, size_t nbytes);
+ void Final();
+
+ // 20 bytes of message digest.
+ const unsigned char *Digest() const { return reinterpret_cast<const unsigned char *>(H); }
+
+ private:
+ void Pad();
+ void Process();
+
+ uint32_t A, B, C, D, E;
+
+ uint32_t H[5];
+
+ union {
+ uint32_t W[80];
+ uint8_t M[64];
+ };
+
+ uint32_t cursor;
+ uint64_t l;
+};
+
+static inline uint32_t f(uint32_t t, uint32_t B, uint32_t C, uint32_t D)
+{
+ if (t < 20)
+ {
+ return (B & C) | ((~B) & D);
+ }
+ else if (t < 40)
+ {
+ return B ^ C ^ D;
+ }
+ else if (t < 60)
+ {
+ return (B & C) | (B & D) | (C & D);
+ }
+ else
+ {
+ return B ^ C ^ D;
+ }
+}
+
+static inline uint32_t S(uint32_t n, uint32_t X)
+{
+ return (X << n) | (X >> (32 - n));
+}
+
+static inline uint32_t K(uint32_t t)
+{
+ if (t < 20)
+ {
+ return 0x5a827999;
+ }
+ else if (t < 40)
+ {
+ return 0x6ed9eba1;
+ }
+ else if (t < 60)
+ {
+ return 0x8f1bbcdc;
+ }
+ else
+ {
+ return 0xca62c1d6;
+ }
+}
+
+const int SecureHashAlgorithm::kDigestSizeBytes = 20;
+
+void SecureHashAlgorithm::Init()
+{
+ A = 0;
+ B = 0;
+ C = 0;
+ D = 0;
+ E = 0;
+ cursor = 0;
+ l = 0;
+ H[0] = 0x67452301;
+ H[1] = 0xefcdab89;
+ H[2] = 0x98badcfe;
+ H[3] = 0x10325476;
+ H[4] = 0xc3d2e1f0;
+}
+
+void SecureHashAlgorithm::Final()
+{
+ Pad();
+ Process();
+
+ for (int t = 0; t < 5; ++t)
+ H[t] = ByteSwap(H[t]);
+}
+
+void SecureHashAlgorithm::Update(const void *data, size_t nbytes)
+{
+ const uint8_t *d = reinterpret_cast<const uint8_t *>(data);
+ while (nbytes--)
+ {
+ M[cursor++] = *d++;
+ if (cursor >= 64)
+ Process();
+ l += 8;
+ }
+}
+
+void SecureHashAlgorithm::Pad()
+{
+ M[cursor++] = 0x80;
+
+ if (cursor > 64 - 8)
+ {
+ // pad out to next block
+ while (cursor < 64)
+ M[cursor++] = 0;
+
+ Process();
+ }
+
+ while (cursor < 64 - 8)
+ M[cursor++] = 0;
+
+ M[cursor++] = (l >> 56) & 0xff;
+ M[cursor++] = (l >> 48) & 0xff;
+ M[cursor++] = (l >> 40) & 0xff;
+ M[cursor++] = (l >> 32) & 0xff;
+ M[cursor++] = (l >> 24) & 0xff;
+ M[cursor++] = (l >> 16) & 0xff;
+ M[cursor++] = (l >> 8) & 0xff;
+ M[cursor++] = l & 0xff;
+}
+
+void SecureHashAlgorithm::Process()
+{
+ uint32_t t;
+
+ // Each a...e corresponds to a section in the FIPS 180-3 algorithm.
+
+ // a.
+ //
+ // W and M are in a union, so no need to memcpy.
+ // memcpy(W, M, sizeof(M));
+ for (t = 0; t < 16; ++t)
+ W[t] = ByteSwap(W[t]);
+
+ // b.
+ for (t = 16; t < 80; ++t)
+ W[t] = S(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]);
+
+ // c.
+ A = H[0];
+ B = H[1];
+ C = H[2];
+ D = H[3];
+ E = H[4];
+
+ // d.
+ for (t = 0; t < 80; ++t)
+ {
+ uint32_t TEMP = S(5, A) + f(t, B, C, D) + E + W[t] + K(t);
+ E = D;
+ D = C;
+ C = S(30, B);
+ B = A;
+ A = TEMP;
+ }
+
+ // e.
+ H[0] += A;
+ H[1] += B;
+ H[2] += C;
+ H[3] += D;
+ H[4] += E;
+
+ cursor = 0;
+}
+
+std::string SHA1HashString(const std::string &str)
+{
+ char hash[SecureHashAlgorithm::kDigestSizeBytes];
+ SHA1HashBytes(reinterpret_cast<const unsigned char *>(str.c_str()), str.length(),
+ reinterpret_cast<unsigned char *>(hash));
+ return std::string(hash, SecureHashAlgorithm::kDigestSizeBytes);
+}
+
+void SHA1HashBytes(const unsigned char *data, size_t len, unsigned char *hash)
+{
+ SecureHashAlgorithm sha;
+ sha.Update(data, len);
+ sha.Final();
+
+ memcpy(hash, sha.Digest(), SecureHashAlgorithm::kDigestSizeBytes);
+}
+
+} // namespace base
+
+} // namespace angle
diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/sha1.h b/src/3rdparty/angle/src/common/third_party/base/anglebase/sha1.h
new file mode 100644
index 0000000000..a60908814f
--- /dev/null
+++ b/src/3rdparty/angle/src/common/third_party/base/anglebase/sha1.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ANGLEBASE_SHA1_H_
+#define ANGLEBASE_SHA1_H_
+
+#include <stddef.h>
+
+#include <string>
+
+#include "anglebase/base_export.h"
+
+namespace angle
+{
+
+namespace base
+{
+
+// These functions perform SHA-1 operations.
+
+static const size_t kSHA1Length = 20; // Length in bytes of a SHA-1 hash.
+
+// Computes the SHA-1 hash of the input string |str| and returns the full
+// hash.
+ANGLEBASE_EXPORT std::string SHA1HashString(const std::string &str);
+
+// Computes the SHA-1 hash of the |len| bytes in |data| and puts the hash
+// in |hash|. |hash| must be kSHA1Length bytes long.
+ANGLEBASE_EXPORT void SHA1HashBytes(const unsigned char *data, size_t len, unsigned char *hash);
+
+} // namespace base
+
+} // namespace angle
+
+#endif // ANGLEBASE_SHA1_H_
diff --git a/src/3rdparty/angle/src/common/third_party/base/anglebase/sys_byteorder.h b/src/3rdparty/angle/src/common/third_party/base/anglebase/sys_byteorder.h
new file mode 100644
index 0000000000..43d1777f26
--- /dev/null
+++ b/src/3rdparty/angle/src/common/third_party/base/anglebase/sys_byteorder.h
@@ -0,0 +1,49 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// sys_byteorder.h: Compatiblity hacks for importing Chromium's base/SHA1.
+
+#ifndef ANGLEBASE_SYS_BYTEORDER_H_
+#define ANGLEBASE_SYS_BYTEORDER_H_
+
+namespace angle
+{
+
+namespace base
+{
+
+// Returns a value with all bytes in |x| swapped, i.e. reverses the endianness.
+inline uint16_t ByteSwap(uint16_t x)
+{
+#if defined(_MSC_VER)
+ return _byteswap_ushort(x);
+#else
+ return __builtin_bswap16(x);
+#endif
+}
+
+inline uint32_t ByteSwap(uint32_t x)
+{
+#if defined(_MSC_VER)
+ return _byteswap_ulong(x);
+#else
+ return __builtin_bswap32(x);
+#endif
+}
+
+inline uint64_t ByteSwap(uint64_t x)
+{
+#if defined(_MSC_VER)
+ return _byteswap_uint64(x);
+#else
+ return __builtin_bswap64(x);
+#endif
+}
+
+} // namespace base
+
+} // namespace angle
+
+#endif // ANGLEBASE_SYS_BYTEORDER_H_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/common/third_party/smhasher/LICENSE b/src/3rdparty/angle/src/common/third_party/smhasher/LICENSE
new file mode 100644
index 0000000000..3f18a844ad
--- /dev/null
+++ b/src/3rdparty/angle/src/common/third_party/smhasher/LICENSE
@@ -0,0 +1,23 @@
+All MurmurHash source files are placed in the public domain.
+
+The license below applies to all other code in SMHasher:
+
+Copyright (c) 2011 Google, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/src/3rdparty/angle/src/common/third_party/smhasher/README.angle b/src/3rdparty/angle/src/common/third_party/smhasher/README.angle
new file mode 100644
index 0000000000..b84ea3249b
--- /dev/null
+++ b/src/3rdparty/angle/src/common/third_party/smhasher/README.angle
@@ -0,0 +1,14 @@
+Name: SMHasher
+URL: http://code.google.com/p/smhasher/
+Version: 0
+Revision: 147
+License: MIT, Public Domain
+License File: LICENSE
+Security Critical: yes
+
+Description:
+This is a library containing the MurmurHash3 function, and a hashing function
+test suite.
+
+Licenses are MIT (SMHasher) and Public Domain (MurmurHash).
+
diff --git a/src/3rdparty/angle/src/common/third_party/smhasher/src/PMurHash.cpp b/src/3rdparty/angle/src/common/third_party/smhasher/src/PMurHash.cpp
new file mode 100644
index 0000000000..071bc31539
--- /dev/null
+++ b/src/3rdparty/angle/src/common/third_party/smhasher/src/PMurHash.cpp
@@ -0,0 +1,320 @@
+/*-----------------------------------------------------------------------------
+ * MurmurHash3 was written by Austin Appleby, and is placed in the public
+ * domain.
+ *
+ * This implementation was written by Shane Day, and is also public domain.
+ *
+ * This is a portable ANSI C implementation of MurmurHash3_x86_32 (Murmur3A)
+ * with support for progressive processing.
+ */
+
+/*-----------------------------------------------------------------------------
+
+If you want to understand the MurmurHash algorithm you would be much better
+off reading the original source. Just point your browser at:
+http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
+
+
+What this version provides?
+
+1. Progressive data feeding. Useful when the entire payload to be hashed
+does not fit in memory or when the data is streamed through the application.
+Also useful when hashing a number of strings with a common prefix. A partial
+hash of a prefix string can be generated and reused for each suffix string.
+
+2. Portability. Plain old C so that it should compile on any old compiler.
+Both CPU endian and access-alignment neutral, but avoiding inefficient code
+when possible depending on CPU capabilities.
+
+3. Drop in. I personally like nice self contained public domain code, making it
+easy to pilfer without loads of refactoring to work properly in the existing
+application code & makefile structure and mucking around with licence files.
+Just copy PMurHash.h and PMurHash.c and you're ready to go.
+
+
+How does it work?
+
+We can only process entire 32 bit chunks of input, except for the very end
+that may be shorter. So along with the partial hash we need to give back to
+the caller a carry containing up to 3 bytes that we were unable to process.
+This carry also needs to record the number of bytes the carry holds. I use
+the low 2 bits as a count (0..3) and the carry bytes are shifted into the
+high byte in stream order.
+
+To handle endianess I simply use a macro that reads a uint32_t and define
+that macro to be a direct read on little endian machines, a read and swap
+on big endian machines, or a byte-by-byte read if the endianess is unknown.
+
+-----------------------------------------------------------------------------*/
+
+
+#include "PMurHash.h"
+
+/* I used ugly type names in the header to avoid potential conflicts with
+ * application or system typedefs & defines. Since I'm not including any more
+ * headers below here I can rename these so that the code reads like C99 */
+#undef uint32_t
+#define uint32_t MH_UINT32
+#undef uint8_t
+#define uint8_t MH_UINT8
+
+/* MSVC warnings we choose to ignore */
+#if defined(_MSC_VER)
+ #pragma warning(disable: 4127) /* conditional expression is constant */
+#endif
+
+/*-----------------------------------------------------------------------------
+ * Endianess, misalignment capabilities and util macros
+ *
+ * The following 3 macros are defined in this section. The other macros defined
+ * are only needed to help derive these 3.
+ *
+ * READ_UINT32(x) Read a little endian unsigned 32-bit int
+ * UNALIGNED_SAFE Defined if READ_UINT32 works on non-word boundaries
+ * ROTL32(x,r) Rotate x left by r bits
+ */
+
+/* Convention is to define __BYTE_ORDER == to one of these values */
+#if !defined(__BIG_ENDIAN)
+ #define __BIG_ENDIAN 4321
+#endif
+#if !defined(__LITTLE_ENDIAN)
+ #define __LITTLE_ENDIAN 1234
+#endif
+
+/* I386 */
+#if defined(_M_IX86) || defined(__i386__) || defined(__i386) || defined(i386)
+ #define __BYTE_ORDER __LITTLE_ENDIAN
+ #define UNALIGNED_SAFE
+#endif
+
+/* gcc 'may' define __LITTLE_ENDIAN__ or __BIG_ENDIAN__ to 1 (Note the trailing __),
+ * or even _LITTLE_ENDIAN or _BIG_ENDIAN (Note the single _ prefix) */
+#if !defined(__BYTE_ORDER)
+ #if defined(__LITTLE_ENDIAN__) && __LITTLE_ENDIAN__==1 || defined(_LITTLE_ENDIAN) && _LITTLE_ENDIAN==1
+ #define __BYTE_ORDER __LITTLE_ENDIAN
+ #elif defined(__BIG_ENDIAN__) && __BIG_ENDIAN__==1 || defined(_BIG_ENDIAN) && _BIG_ENDIAN==1
+ #define __BYTE_ORDER __BIG_ENDIAN
+ #endif
+#endif
+
+/* gcc (usually) defines xEL/EB macros for ARM and MIPS endianess */
+#if !defined(__BYTE_ORDER)
+ #if defined(__ARMEL__) || defined(__MIPSEL__)
+ #define __BYTE_ORDER __LITTLE_ENDIAN
+ #endif
+ #if defined(__ARMEB__) || defined(__MIPSEB__)
+ #define __BYTE_ORDER __BIG_ENDIAN
+ #endif
+#endif
+
+/* Now find best way we can to READ_UINT32 */
+#if __BYTE_ORDER==__LITTLE_ENDIAN
+ /* CPU endian matches murmurhash algorithm, so read 32-bit word directly */
+ #define READ_UINT32(ptr) (*((uint32_t*)(ptr)))
+#elif __BYTE_ORDER==__BIG_ENDIAN
+ /* TODO: Add additional cases below where a compiler provided bswap32 is available */
+ #if defined(__GNUC__) && (__GNUC__>4 || (__GNUC__==4 && __GNUC_MINOR__>=3))
+ #define READ_UINT32(ptr) (__builtin_bswap32(*((uint32_t*)(ptr))))
+ #else
+ /* Without a known fast bswap32 we're just as well off doing this */
+ #define READ_UINT32(ptr) (ptr[0]|ptr[1]<<8|ptr[2]<<16|ptr[3]<<24)
+ #define UNALIGNED_SAFE
+ #endif
+#else
+ /* Unknown endianess so last resort is to read individual bytes */
+ #define READ_UINT32(ptr) (ptr[0]|ptr[1]<<8|ptr[2]<<16|ptr[3]<<24)
+
+ /* Since we're not doing word-reads we can skip the messing about with realignment */
+ #define UNALIGNED_SAFE
+#endif
+
+/* Find best way to ROTL32 */
+#if defined(_MSC_VER)
+ #include <stdlib.h> /* Microsoft put _rotl declaration in here */
+ #define ROTL32(x,r) _rotl(x,r)
+#else
+ /* gcc recognises this code and generates a rotate instruction for CPUs with one */
+ #define ROTL32(x,r) (((uint32_t)x << r) | ((uint32_t)x >> (32 - r)))
+#endif
+
+
+/*-----------------------------------------------------------------------------
+ * Core murmurhash algorithm macros */
+
+#define C1 (0xcc9e2d51)
+#define C2 (0x1b873593)
+
+/* This is the main processing body of the algorithm. It operates
+ * on each full 32-bits of input. */
+#define DOBLOCK(h1, k1) do{ \
+ k1 *= C1; \
+ k1 = ROTL32(k1,15); \
+ k1 *= C2; \
+ \
+ h1 ^= k1; \
+ h1 = ROTL32(h1,13); \
+ h1 = h1*5+0xe6546b64; \
+ }while(0)
+
+
+/* Append unaligned bytes to carry, forcing hash churn if we have 4 bytes */
+/* cnt=bytes to process, h1=name of h1 var, c=carry, n=bytes in c, ptr/len=payload */
+#define DOBYTES(cnt, h1, c, n, ptr, len) do{ \
+ int _i = cnt; \
+ while(_i--) { \
+ c = c>>8 | *ptr++<<24; \
+ n++; len--; \
+ if(n==4) { \
+ DOBLOCK(h1, c); \
+ n = 0; \
+ } \
+ } }while(0)
+
+/*---------------------------------------------------------------------------*/
+
+namespace angle
+{
+/* Main hashing function. Initialise carry to 0 and h1 to 0 or an initial seed
+ * if wanted. Both ph1 and pcarry are required arguments. */
+void PMurHash32_Process(uint32_t *ph1, uint32_t *pcarry, const void *key, int len)
+{
+ uint32_t h1 = *ph1;
+ uint32_t c = *pcarry;
+
+ const uint8_t *ptr = (uint8_t*)key;
+ const uint8_t *end;
+
+ /* Extract carry count from low 2 bits of c value */
+ int n = c & 3;
+
+#if defined(UNALIGNED_SAFE)
+ /* This CPU handles unaligned word access */
+
+ /* Consume any carry bytes */
+ int i = (4-n) & 3;
+ if(i && i <= len) {
+ DOBYTES(i, h1, c, n, ptr, len);
+ }
+
+ /* Process 32-bit chunks */
+ end = ptr + len/4*4;
+ for( ; ptr < end ; ptr+=4) {
+ uint32_t k1 = READ_UINT32(ptr);
+ DOBLOCK(h1, k1);
+ }
+
+#else /*UNALIGNED_SAFE*/
+ /* This CPU does not handle unaligned word access */
+
+ /* Consume enough so that the next data byte is word aligned */
+ int i = -(long)ptr & 3;
+ if(i && i <= len) {
+ DOBYTES(i, h1, c, n, ptr, len);
+ }
+
+ /* We're now aligned. Process in aligned blocks. Specialise for each possible carry count */
+ end = ptr + len/4*4;
+ switch(n) { /* how many bytes in c */
+ case 0: /* c=[----] w=[3210] b=[3210]=w c'=[----] */
+ for( ; ptr < end ; ptr+=4) {
+ uint32_t k1 = READ_UINT32(ptr);
+ DOBLOCK(h1, k1);
+ }
+ break;
+ case 1: /* c=[0---] w=[4321] b=[3210]=c>>24|w<<8 c'=[4---] */
+ for( ; ptr < end ; ptr+=4) {
+ uint32_t k1 = c>>24;
+ c = READ_UINT32(ptr);
+ k1 |= c<<8;
+ DOBLOCK(h1, k1);
+ }
+ break;
+ case 2: /* c=[10--] w=[5432] b=[3210]=c>>16|w<<16 c'=[54--] */
+ for( ; ptr < end ; ptr+=4) {
+ uint32_t k1 = c>>16;
+ c = READ_UINT32(ptr);
+ k1 |= c<<16;
+ DOBLOCK(h1, k1);
+ }
+ break;
+ case 3: /* c=[210-] w=[6543] b=[3210]=c>>8|w<<24 c'=[654-] */
+ for( ; ptr < end ; ptr+=4) {
+ uint32_t k1 = c>>8;
+ c = READ_UINT32(ptr);
+ k1 |= c<<24;
+ DOBLOCK(h1, k1);
+ }
+ }
+#endif /*UNALIGNED_SAFE*/
+
+ /* Advance over whole 32-bit chunks, possibly leaving 1..3 bytes */
+ len -= len/4*4;
+
+ /* Append any remaining bytes into carry */
+ DOBYTES(len, h1, c, n, ptr, len);
+
+ /* Copy out new running hash and carry */
+ *ph1 = h1;
+ *pcarry = (c & ~0xff) | n;
+}
+
+/*---------------------------------------------------------------------------*/
+
+/* Finalize a hash. To match the original Murmur3A the total_length must be provided */
+uint32_t PMurHash32_Result(uint32_t h, uint32_t carry, uint32_t total_length)
+{
+ uint32_t k1;
+ int n = carry & 3;
+ if(n) {
+ k1 = carry >> (4-n)*8;
+ k1 *= C1; k1 = ROTL32(k1,15); k1 *= C2; h ^= k1;
+ }
+ h ^= total_length;
+
+ /* fmix */
+ h ^= h >> 16;
+ h *= 0x85ebca6b;
+ h ^= h >> 13;
+ h *= 0xc2b2ae35;
+ h ^= h >> 16;
+
+ return h;
+}
+
+/*---------------------------------------------------------------------------*/
+
+/* Murmur3A compatable all-at-once */
+uint32_t PMurHash32(uint32_t seed, const void *key, int len)
+{
+ uint32_t h1=seed, carry=0;
+ PMurHash32_Process(&h1, &carry, key, len);
+ return PMurHash32_Result(h1, carry, len);
+}
+
+/*---------------------------------------------------------------------------*/
+
+/* Provide an API suitable for smhasher */
+void PMurHash32_test(const void *key, int len, uint32_t seed, void *out)
+{
+ uint32_t h1=seed, carry=0;
+ const uint8_t *ptr = (uint8_t*)key;
+ const uint8_t *end = ptr + len;
+
+#if 0 /* Exercise the progressive processing */
+ while(ptr < end) {
+ //const uint8_t *mid = ptr + rand()%(end-ptr)+1;
+ const uint8_t *mid = ptr + (rand()&0xF);
+ mid = mid<end?mid:end;
+ PMurHash32_Process(&h1, &carry, ptr, mid-ptr);
+ ptr = mid;
+ }
+#else
+ PMurHash32_Process(&h1, &carry, ptr, (int)(end-ptr));
+#endif
+ h1 = PMurHash32_Result(h1, carry, len);
+ *(uint32_t*)out = h1;
+}
+}
+
+/*---------------------------------------------------------------------------*/
diff --git a/src/3rdparty/angle/src/common/third_party/smhasher/src/PMurHash.h b/src/3rdparty/angle/src/common/third_party/smhasher/src/PMurHash.h
new file mode 100644
index 0000000000..57c56c538d
--- /dev/null
+++ b/src/3rdparty/angle/src/common/third_party/smhasher/src/PMurHash.h
@@ -0,0 +1,59 @@
+/*-----------------------------------------------------------------------------
+ * MurmurHash3 was written by Austin Appleby, and is placed in the public
+ * domain.
+ *
+ * This implementation was written by Shane Day, and is also public domain.
+ *
+ * This is a portable ANSI C implementation of MurmurHash3_x86_32 (Murmur3A)
+ * with support for progressive processing.
+ */
+
+/* ------------------------------------------------------------------------- */
+/* Determine what native type to use for uint32_t */
+
+/* We can't use the name 'uint32_t' here because it will conflict with
+ * any version provided by the system headers or application. */
+
+/* First look for special cases */
+#if defined(_MSC_VER)
+ #define MH_UINT32 unsigned long
+#endif
+
+/* If the compiler says it's C99 then take its word for it */
+#if !defined(MH_UINT32) && ( \
+ defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L )
+ #include <stdint.h>
+ #define MH_UINT32 uint32_t
+#endif
+
+/* Otherwise try testing against max value macros from limit.h */
+#if !defined(MH_UINT32)
+ #include <limits.h>
+ #if (USHRT_MAX == 0xffffffffUL)
+ #define MH_UINT32 unsigned short
+ #elif (UINT_MAX == 0xffffffffUL)
+ #define MH_UINT32 unsigned int
+ #elif (ULONG_MAX == 0xffffffffUL)
+ #define MH_UINT32 unsigned long
+ #endif
+#endif
+
+#if !defined(MH_UINT32)
+ #error Unable to determine type name for unsigned 32-bit int
+#endif
+
+/* I'm yet to work on a platform where 'unsigned char' is not 8 bits */
+#define MH_UINT8 unsigned char
+
+
+/* ------------------------------------------------------------------------- */
+/* Prototypes */
+
+namespace angle
+{
+void PMurHash32_Process(MH_UINT32 *ph1, MH_UINT32 *pcarry, const void *key, int len);
+MH_UINT32 PMurHash32_Result(MH_UINT32 h1, MH_UINT32 carry, MH_UINT32 total_length);
+MH_UINT32 PMurHash32(MH_UINT32 seed, const void *key, int len);
+
+void PMurHash32_test(const void *key, int len, MH_UINT32 seed, void *out);
+}
diff --git a/src/3rdparty/angle/src/common/tls.cpp b/src/3rdparty/angle/src/common/tls.cpp
index cb1b32d325..10a10252f4 100644
--- a/src/3rdparty/angle/src/common/tls.cpp
+++ b/src/3rdparty/angle/src/common/tls.cpp
@@ -56,7 +56,7 @@ TLSIndex CreateTLSIndex()
#elif defined(ANGLE_PLATFORM_POSIX)
// Create global pool key
- if ((pthread_key_create(&index, NULL)) != 0)
+ if ((pthread_key_create(&index, nullptr)) != 0)
{
index = TLS_INVALID_INDEX;
}
@@ -133,7 +133,7 @@ void *GetTLSValue(TLSIndex index)
assert(index != TLS_INVALID_INDEX && "GetTLSValue(): Invalid TLS Index");
if (index == TLS_INVALID_INDEX)
{
- return NULL;
+ return nullptr;
}
#ifdef ANGLE_PLATFORM_WINDOWS
diff --git a/src/3rdparty/angle/src/common/uniform_type_info_autogen.cpp b/src/3rdparty/angle/src/common/uniform_type_info_autogen.cpp
new file mode 100644
index 0000000000..9c199128a4
--- /dev/null
+++ b/src/3rdparty/angle/src/common/uniform_type_info_autogen.cpp
@@ -0,0 +1,275 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_uniform_type_table.py.
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Uniform type info table:
+// Metadata about a particular uniform format, indexed by GL type.
+
+#include <array>
+#include "common/utilities.h"
+
+using namespace angle;
+
+namespace gl
+{
+
+namespace
+{
+constexpr std::array<UniformTypeInfo, 59> kInfoTable = {
+ {{GL_NONE, GL_NONE, GL_NONE, GL_NONE, GL_NONE, 0, 0, 0, 0, 0 * 0, 0 * 0, false, false, false},
+ {GL_BOOL, GL_BOOL, GL_NONE, GL_NONE, GL_NONE, 1, 1, 1, sizeof(GLint), sizeof(GLint) * 4,
+ sizeof(GLint) * 1, false, false, false},
+ {GL_BOOL_VEC2, GL_BOOL, GL_NONE, GL_NONE, GL_BOOL_VEC2, 1, 2, 2, sizeof(GLint),
+ sizeof(GLint) * 4, sizeof(GLint) * 2, false, false, false},
+ {GL_BOOL_VEC3, GL_BOOL, GL_NONE, GL_NONE, GL_BOOL_VEC3, 1, 3, 3, sizeof(GLint),
+ sizeof(GLint) * 4, sizeof(GLint) * 3, false, false, false},
+ {GL_BOOL_VEC4, GL_BOOL, GL_NONE, GL_NONE, GL_BOOL_VEC4, 1, 4, 4, sizeof(GLint),
+ sizeof(GLint) * 4, sizeof(GLint) * 4, false, false, false},
+ {GL_FLOAT, GL_FLOAT, GL_NONE, GL_NONE, GL_BOOL, 1, 1, 1, sizeof(GLfloat), sizeof(GLfloat) * 4,
+ sizeof(GLfloat) * 1, false, false, false},
+ {GL_FLOAT_MAT2, GL_FLOAT, GL_NONE, GL_FLOAT_MAT2, GL_NONE, 2, 2, 4, sizeof(GLfloat),
+ sizeof(GLfloat) * 8, sizeof(GLfloat) * 4, false, true, false},
+ {GL_FLOAT_MAT2x3, GL_FLOAT, GL_NONE, GL_FLOAT_MAT3x2, GL_NONE, 3, 2, 6, sizeof(GLfloat),
+ sizeof(GLfloat) * 12, sizeof(GLfloat) * 6, false, true, false},
+ {GL_FLOAT_MAT2x4, GL_FLOAT, GL_NONE, GL_FLOAT_MAT4x2, GL_NONE, 4, 2, 8, sizeof(GLfloat),
+ sizeof(GLfloat) * 16, sizeof(GLfloat) * 8, false, true, false},
+ {GL_FLOAT_MAT3, GL_FLOAT, GL_NONE, GL_FLOAT_MAT3, GL_NONE, 3, 3, 9, sizeof(GLfloat),
+ sizeof(GLfloat) * 12, sizeof(GLfloat) * 9, false, true, false},
+ {GL_FLOAT_MAT3x2, GL_FLOAT, GL_NONE, GL_FLOAT_MAT2x3, GL_NONE, 2, 3, 6, sizeof(GLfloat),
+ sizeof(GLfloat) * 8, sizeof(GLfloat) * 6, false, true, false},
+ {GL_FLOAT_MAT3x4, GL_FLOAT, GL_NONE, GL_FLOAT_MAT4x3, GL_NONE, 4, 3, 12, sizeof(GLfloat),
+ sizeof(GLfloat) * 16, sizeof(GLfloat) * 12, false, true, false},
+ {GL_FLOAT_MAT4, GL_FLOAT, GL_NONE, GL_FLOAT_MAT4, GL_NONE, 4, 4, 16, sizeof(GLfloat),
+ sizeof(GLfloat) * 16, sizeof(GLfloat) * 16, false, true, false},
+ {GL_FLOAT_MAT4x2, GL_FLOAT, GL_NONE, GL_FLOAT_MAT2x4, GL_NONE, 2, 4, 8, sizeof(GLfloat),
+ sizeof(GLfloat) * 8, sizeof(GLfloat) * 8, false, true, false},
+ {GL_FLOAT_MAT4x3, GL_FLOAT, GL_NONE, GL_FLOAT_MAT3x4, GL_NONE, 3, 4, 12, sizeof(GLfloat),
+ sizeof(GLfloat) * 12, sizeof(GLfloat) * 12, false, true, false},
+ {GL_FLOAT_VEC2, GL_FLOAT, GL_NONE, GL_NONE, GL_BOOL_VEC2, 1, 2, 2, sizeof(GLfloat),
+ sizeof(GLfloat) * 4, sizeof(GLfloat) * 2, false, false, false},
+ {GL_FLOAT_VEC3, GL_FLOAT, GL_NONE, GL_NONE, GL_BOOL_VEC3, 1, 3, 3, sizeof(GLfloat),
+ sizeof(GLfloat) * 4, sizeof(GLfloat) * 3, false, false, false},
+ {GL_FLOAT_VEC4, GL_FLOAT, GL_NONE, GL_NONE, GL_BOOL_VEC4, 1, 4, 4, sizeof(GLfloat),
+ sizeof(GLfloat) * 4, sizeof(GLfloat) * 4, false, false, false},
+ {GL_IMAGE_2D, GL_INT, GL_TEXTURE_2D, GL_NONE, GL_NONE, 1, 1, 1, sizeof(GLint),
+ sizeof(GLint) * 4, sizeof(GLint) * 1, false, false, true},
+ {GL_IMAGE_2D_ARRAY, GL_INT, GL_TEXTURE_2D_ARRAY, GL_NONE, GL_NONE, 1, 1, 1, sizeof(GLint),
+ sizeof(GLint) * 4, sizeof(GLint) * 1, false, false, true},
+ {GL_IMAGE_3D, GL_INT, GL_TEXTURE_3D, GL_NONE, GL_NONE, 1, 1, 1, sizeof(GLint),
+ sizeof(GLint) * 4, sizeof(GLint) * 1, false, false, true},
+ {GL_IMAGE_CUBE, GL_INT, GL_TEXTURE_CUBE_MAP, GL_NONE, GL_NONE, 1, 1, 1, sizeof(GLint),
+ sizeof(GLint) * 4, sizeof(GLint) * 1, false, false, true},
+ {GL_INT, GL_INT, GL_NONE, GL_NONE, GL_BOOL, 1, 1, 1, sizeof(GLint), sizeof(GLint) * 4,
+ sizeof(GLint) * 1, false, false, false},
+ {GL_INT_IMAGE_2D, GL_INT, GL_TEXTURE_2D, GL_NONE, GL_NONE, 1, 1, 1, sizeof(GLint),
+ sizeof(GLint) * 4, sizeof(GLint) * 1, false, false, true},
+ {GL_INT_IMAGE_2D_ARRAY, GL_INT, GL_TEXTURE_2D_ARRAY, GL_NONE, GL_NONE, 1, 1, 1, sizeof(GLint),
+ sizeof(GLint) * 4, sizeof(GLint) * 1, false, false, true},
+ {GL_INT_IMAGE_3D, GL_INT, GL_TEXTURE_3D, GL_NONE, GL_NONE, 1, 1, 1, sizeof(GLint),
+ sizeof(GLint) * 4, sizeof(GLint) * 1, false, false, true},
+ {GL_INT_IMAGE_CUBE, GL_INT, GL_TEXTURE_CUBE_MAP, GL_NONE, GL_NONE, 1, 1, 1, sizeof(GLint),
+ sizeof(GLint) * 4, sizeof(GLint) * 1, false, false, true},
+ {GL_INT_SAMPLER_2D, GL_INT, GL_TEXTURE_2D, GL_NONE, GL_NONE, 1, 1, 1, sizeof(GLint),
+ sizeof(GLint) * 4, sizeof(GLint) * 1, true, false, false},
+ {GL_INT_SAMPLER_2D_ARRAY, GL_INT, GL_TEXTURE_2D_ARRAY, GL_NONE, GL_NONE, 1, 1, 1,
+ sizeof(GLint), sizeof(GLint) * 4, sizeof(GLint) * 1, true, false, false},
+ {GL_INT_SAMPLER_2D_MULTISAMPLE, GL_INT, GL_TEXTURE_2D_MULTISAMPLE, GL_NONE, GL_NONE, 1, 1, 1,
+ sizeof(GLint), sizeof(GLint) * 4, sizeof(GLint) * 1, true, false, false},
+ {GL_INT_SAMPLER_3D, GL_INT, GL_TEXTURE_3D, GL_NONE, GL_NONE, 1, 1, 1, sizeof(GLint),
+ sizeof(GLint) * 4, sizeof(GLint) * 1, true, false, false},
+ {GL_INT_SAMPLER_CUBE, GL_INT, GL_TEXTURE_CUBE_MAP, GL_NONE, GL_NONE, 1, 1, 1, sizeof(GLint),
+ sizeof(GLint) * 4, sizeof(GLint) * 1, true, false, false},
+ {GL_INT_VEC2, GL_INT, GL_NONE, GL_NONE, GL_BOOL_VEC2, 1, 2, 2, sizeof(GLint),
+ sizeof(GLint) * 4, sizeof(GLint) * 2, false, false, false},
+ {GL_INT_VEC3, GL_INT, GL_NONE, GL_NONE, GL_BOOL_VEC3, 1, 3, 3, sizeof(GLint),
+ sizeof(GLint) * 4, sizeof(GLint) * 3, false, false, false},
+ {GL_INT_VEC4, GL_INT, GL_NONE, GL_NONE, GL_BOOL_VEC4, 1, 4, 4, sizeof(GLint),
+ sizeof(GLint) * 4, sizeof(GLint) * 4, false, false, false},
+ {GL_SAMPLER_2D, GL_INT, GL_TEXTURE_2D, GL_NONE, GL_NONE, 1, 1, 1, sizeof(GLint),
+ sizeof(GLint) * 4, sizeof(GLint) * 1, true, false, false},
+ {GL_SAMPLER_2D_ARRAY, GL_INT, GL_TEXTURE_2D_ARRAY, GL_NONE, GL_NONE, 1, 1, 1, sizeof(GLint),
+ sizeof(GLint) * 4, sizeof(GLint) * 1, true, false, false},
+ {GL_SAMPLER_2D_ARRAY_SHADOW, GL_INT, GL_TEXTURE_2D_ARRAY, GL_NONE, GL_NONE, 1, 1, 1,
+ sizeof(GLint), sizeof(GLint) * 4, sizeof(GLint) * 1, true, false, false},
+ {GL_SAMPLER_2D_MULTISAMPLE, GL_INT, GL_TEXTURE_2D_MULTISAMPLE, GL_NONE, GL_NONE, 1, 1, 1,
+ sizeof(GLint), sizeof(GLint) * 4, sizeof(GLint) * 1, true, false, false},
+ {GL_SAMPLER_2D_RECT_ANGLE, GL_INT, GL_TEXTURE_2D, GL_NONE, GL_NONE, 1, 1, 1, sizeof(GLint),
+ sizeof(GLint) * 4, sizeof(GLint) * 1, true, false, false},
+ {GL_SAMPLER_2D_SHADOW, GL_INT, GL_TEXTURE_2D, GL_NONE, GL_NONE, 1, 1, 1, sizeof(GLint),
+ sizeof(GLint) * 4, sizeof(GLint) * 1, true, false, false},
+ {GL_SAMPLER_3D, GL_INT, GL_TEXTURE_3D, GL_NONE, GL_NONE, 1, 1, 1, sizeof(GLint),
+ sizeof(GLint) * 4, sizeof(GLint) * 1, true, false, false},
+ {GL_SAMPLER_CUBE, GL_INT, GL_TEXTURE_CUBE_MAP, GL_NONE, GL_NONE, 1, 1, 1, sizeof(GLint),
+ sizeof(GLint) * 4, sizeof(GLint) * 1, true, false, false},
+ {GL_SAMPLER_CUBE_SHADOW, GL_INT, GL_TEXTURE_CUBE_MAP, GL_NONE, GL_NONE, 1, 1, 1, sizeof(GLint),
+ sizeof(GLint) * 4, sizeof(GLint) * 1, true, false, false},
+ {GL_SAMPLER_EXTERNAL_OES, GL_INT, GL_TEXTURE_EXTERNAL_OES, GL_NONE, GL_NONE, 1, 1, 1,
+ sizeof(GLint), sizeof(GLint) * 4, sizeof(GLint) * 1, true, false, false},
+ {GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_NONE, GL_NONE, GL_BOOL, 1, 1, 1, sizeof(GLuint),
+ sizeof(GLuint) * 4, sizeof(GLuint) * 1, false, false, false},
+ {GL_UNSIGNED_INT_ATOMIC_COUNTER, GL_UNSIGNED_INT, GL_NONE, GL_NONE, GL_NONE, 1, 1, 1,
+ sizeof(GLuint), sizeof(GLuint) * 4, sizeof(GLuint) * 1, false, false, false},
+ {GL_UNSIGNED_INT_IMAGE_2D, GL_UNSIGNED_INT, GL_TEXTURE_2D, GL_NONE, GL_NONE, 1, 1, 1,
+ sizeof(GLuint), sizeof(GLuint) * 4, sizeof(GLuint) * 1, false, false, true},
+ {GL_UNSIGNED_INT_IMAGE_2D_ARRAY, GL_UNSIGNED_INT, GL_TEXTURE_2D_ARRAY, GL_NONE, GL_NONE, 1, 1,
+ 1, sizeof(GLuint), sizeof(GLuint) * 4, sizeof(GLuint) * 1, false, false, true},
+ {GL_UNSIGNED_INT_IMAGE_3D, GL_UNSIGNED_INT, GL_TEXTURE_3D, GL_NONE, GL_NONE, 1, 1, 1,
+ sizeof(GLuint), sizeof(GLuint) * 4, sizeof(GLuint) * 1, false, false, true},
+ {GL_UNSIGNED_INT_IMAGE_CUBE, GL_UNSIGNED_INT, GL_TEXTURE_CUBE_MAP, GL_NONE, GL_NONE, 1, 1, 1,
+ sizeof(GLuint), sizeof(GLuint) * 4, sizeof(GLuint) * 1, false, false, true},
+ {GL_UNSIGNED_INT_SAMPLER_2D, GL_UNSIGNED_INT, GL_TEXTURE_2D, GL_NONE, GL_NONE, 1, 1, 1,
+ sizeof(GLuint), sizeof(GLuint) * 4, sizeof(GLuint) * 1, true, false, false},
+ {GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, GL_UNSIGNED_INT, GL_TEXTURE_2D_ARRAY, GL_NONE, GL_NONE, 1,
+ 1, 1, sizeof(GLuint), sizeof(GLuint) * 4, sizeof(GLuint) * 1, true, false, false},
+ {GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, GL_UNSIGNED_INT, GL_TEXTURE_2D_MULTISAMPLE, GL_NONE,
+ GL_NONE, 1, 1, 1, sizeof(GLuint), sizeof(GLuint) * 4, sizeof(GLuint) * 1, true, false, false},
+ {GL_UNSIGNED_INT_SAMPLER_3D, GL_UNSIGNED_INT, GL_TEXTURE_3D, GL_NONE, GL_NONE, 1, 1, 1,
+ sizeof(GLuint), sizeof(GLuint) * 4, sizeof(GLuint) * 1, true, false, false},
+ {GL_UNSIGNED_INT_SAMPLER_CUBE, GL_UNSIGNED_INT, GL_TEXTURE_CUBE_MAP, GL_NONE, GL_NONE, 1, 1, 1,
+ sizeof(GLuint), sizeof(GLuint) * 4, sizeof(GLuint) * 1, true, false, false},
+ {GL_UNSIGNED_INT_VEC2, GL_UNSIGNED_INT, GL_NONE, GL_NONE, GL_BOOL_VEC2, 1, 2, 2,
+ sizeof(GLuint), sizeof(GLuint) * 4, sizeof(GLuint) * 2, false, false, false},
+ {GL_UNSIGNED_INT_VEC3, GL_UNSIGNED_INT, GL_NONE, GL_NONE, GL_BOOL_VEC3, 1, 3, 3,
+ sizeof(GLuint), sizeof(GLuint) * 4, sizeof(GLuint) * 3, false, false, false},
+ {GL_UNSIGNED_INT_VEC4, GL_UNSIGNED_INT, GL_NONE, GL_NONE, GL_BOOL_VEC4, 1, 4, 4,
+ sizeof(GLuint), sizeof(GLuint) * 4, sizeof(GLuint) * 4, false, false, false}}};
+
+size_t GetTypeInfoIndex(GLenum uniformType)
+{
+ switch (uniformType)
+ {
+ case GL_NONE:
+ return 0;
+ case GL_BOOL:
+ return 1;
+ case GL_BOOL_VEC2:
+ return 2;
+ case GL_BOOL_VEC3:
+ return 3;
+ case GL_BOOL_VEC4:
+ return 4;
+ case GL_FLOAT:
+ return 5;
+ case GL_FLOAT_MAT2:
+ return 6;
+ case GL_FLOAT_MAT2x3:
+ return 7;
+ case GL_FLOAT_MAT2x4:
+ return 8;
+ case GL_FLOAT_MAT3:
+ return 9;
+ case GL_FLOAT_MAT3x2:
+ return 10;
+ case GL_FLOAT_MAT3x4:
+ return 11;
+ case GL_FLOAT_MAT4:
+ return 12;
+ case GL_FLOAT_MAT4x2:
+ return 13;
+ case GL_FLOAT_MAT4x3:
+ return 14;
+ case GL_FLOAT_VEC2:
+ return 15;
+ case GL_FLOAT_VEC3:
+ return 16;
+ case GL_FLOAT_VEC4:
+ return 17;
+ case GL_IMAGE_2D:
+ return 18;
+ case GL_IMAGE_2D_ARRAY:
+ return 19;
+ case GL_IMAGE_3D:
+ return 20;
+ case GL_IMAGE_CUBE:
+ return 21;
+ case GL_INT:
+ return 22;
+ case GL_INT_IMAGE_2D:
+ return 23;
+ case GL_INT_IMAGE_2D_ARRAY:
+ return 24;
+ case GL_INT_IMAGE_3D:
+ return 25;
+ case GL_INT_IMAGE_CUBE:
+ return 26;
+ case GL_INT_SAMPLER_2D:
+ return 27;
+ case GL_INT_SAMPLER_2D_ARRAY:
+ return 28;
+ case GL_INT_SAMPLER_2D_MULTISAMPLE:
+ return 29;
+ case GL_INT_SAMPLER_3D:
+ return 30;
+ case GL_INT_SAMPLER_CUBE:
+ return 31;
+ case GL_INT_VEC2:
+ return 32;
+ case GL_INT_VEC3:
+ return 33;
+ case GL_INT_VEC4:
+ return 34;
+ case GL_SAMPLER_2D:
+ return 35;
+ case GL_SAMPLER_2D_ARRAY:
+ return 36;
+ case GL_SAMPLER_2D_ARRAY_SHADOW:
+ return 37;
+ case GL_SAMPLER_2D_MULTISAMPLE:
+ return 38;
+ case GL_SAMPLER_2D_RECT_ANGLE:
+ return 39;
+ case GL_SAMPLER_2D_SHADOW:
+ return 40;
+ case GL_SAMPLER_3D:
+ return 41;
+ case GL_SAMPLER_CUBE:
+ return 42;
+ case GL_SAMPLER_CUBE_SHADOW:
+ return 43;
+ case GL_SAMPLER_EXTERNAL_OES:
+ return 44;
+ case GL_UNSIGNED_INT:
+ return 45;
+ case GL_UNSIGNED_INT_ATOMIC_COUNTER:
+ return 46;
+ case GL_UNSIGNED_INT_IMAGE_2D:
+ return 47;
+ case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
+ return 48;
+ case GL_UNSIGNED_INT_IMAGE_3D:
+ return 49;
+ case GL_UNSIGNED_INT_IMAGE_CUBE:
+ return 50;
+ case GL_UNSIGNED_INT_SAMPLER_2D:
+ return 51;
+ case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+ return 52;
+ case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
+ return 53;
+ case GL_UNSIGNED_INT_SAMPLER_3D:
+ return 54;
+ case GL_UNSIGNED_INT_SAMPLER_CUBE:
+ return 55;
+ case GL_UNSIGNED_INT_VEC2:
+ return 56;
+ case GL_UNSIGNED_INT_VEC3:
+ return 57;
+ case GL_UNSIGNED_INT_VEC4:
+ return 58;
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+} // anonymous namespace
+
+const UniformTypeInfo &GetUniformTypeInfo(GLenum uniformType)
+{
+ ASSERT(kInfoTable[GetTypeInfoIndex(uniformType)].type == uniformType);
+ return kInfoTable[GetTypeInfoIndex(uniformType)];
+}
+
+} // namespace gl
diff --git a/src/3rdparty/angle/src/common/utilities.cpp b/src/3rdparty/angle/src/common/utilities.cpp
index 2ab913b10f..6dae9cc51f 100644
--- a/src/3rdparty/angle/src/common/utilities.cpp
+++ b/src/3rdparty/angle/src/common/utilities.cpp
@@ -124,24 +124,42 @@ GLenum VariableComponentType(GLenum type)
return GL_FLOAT;
case GL_INT:
case GL_SAMPLER_2D:
+ case GL_SAMPLER_2D_RECT_ANGLE:
case GL_SAMPLER_3D:
case GL_SAMPLER_CUBE:
case GL_SAMPLER_2D_ARRAY:
+ case GL_SAMPLER_EXTERNAL_OES:
+ case GL_SAMPLER_2D_MULTISAMPLE:
case GL_INT_SAMPLER_2D:
case GL_INT_SAMPLER_3D:
case GL_INT_SAMPLER_CUBE:
case GL_INT_SAMPLER_2D_ARRAY:
+ case GL_INT_SAMPLER_2D_MULTISAMPLE:
case GL_UNSIGNED_INT_SAMPLER_2D:
case GL_UNSIGNED_INT_SAMPLER_3D:
case GL_UNSIGNED_INT_SAMPLER_CUBE:
case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
case GL_SAMPLER_2D_SHADOW:
case GL_SAMPLER_CUBE_SHADOW:
case GL_SAMPLER_2D_ARRAY_SHADOW:
case GL_INT_VEC2:
case GL_INT_VEC3:
case GL_INT_VEC4:
- return GL_INT;
+ case GL_IMAGE_2D:
+ case GL_INT_IMAGE_2D:
+ case GL_UNSIGNED_INT_IMAGE_2D:
+ case GL_IMAGE_3D:
+ case GL_INT_IMAGE_3D:
+ case GL_UNSIGNED_INT_IMAGE_3D:
+ case GL_IMAGE_2D_ARRAY:
+ case GL_INT_IMAGE_2D_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
+ case GL_IMAGE_CUBE:
+ case GL_INT_IMAGE_CUBE:
+ case GL_UNSIGNED_INT_IMAGE_CUBE:
+ case GL_UNSIGNED_INT_ATOMIC_COUNTER:
+ return GL_INT;
case GL_UNSIGNED_INT:
case GL_UNSIGNED_INT_VEC2:
case GL_UNSIGNED_INT_VEC3:
@@ -211,7 +229,6 @@ int VariableRowCount(GLenum type)
switch (type)
{
case GL_NONE:
- case GL_STRUCT_ANGLEX:
return 0;
case GL_BOOL:
case GL_FLOAT:
@@ -234,19 +251,35 @@ int VariableRowCount(GLenum type)
case GL_SAMPLER_CUBE:
case GL_SAMPLER_2D_ARRAY:
case GL_SAMPLER_EXTERNAL_OES:
- case GL_SAMPLER_2D_RECT_ARB:
+ case GL_SAMPLER_2D_RECT_ANGLE:
+ case GL_SAMPLER_2D_MULTISAMPLE:
case GL_INT_SAMPLER_2D:
case GL_INT_SAMPLER_3D:
case GL_INT_SAMPLER_CUBE:
case GL_INT_SAMPLER_2D_ARRAY:
+ case GL_INT_SAMPLER_2D_MULTISAMPLE:
case GL_UNSIGNED_INT_SAMPLER_2D:
case GL_UNSIGNED_INT_SAMPLER_3D:
case GL_UNSIGNED_INT_SAMPLER_CUBE:
case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
case GL_SAMPLER_2D_SHADOW:
case GL_SAMPLER_CUBE_SHADOW:
case GL_SAMPLER_2D_ARRAY_SHADOW:
- return 1;
+ case GL_IMAGE_2D:
+ case GL_INT_IMAGE_2D:
+ case GL_UNSIGNED_INT_IMAGE_2D:
+ case GL_IMAGE_2D_ARRAY:
+ case GL_INT_IMAGE_2D_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
+ case GL_IMAGE_3D:
+ case GL_INT_IMAGE_3D:
+ case GL_UNSIGNED_INT_IMAGE_3D:
+ case GL_IMAGE_CUBE:
+ case GL_INT_IMAGE_CUBE:
+ case GL_UNSIGNED_INT_IMAGE_CUBE:
+ case GL_UNSIGNED_INT_ATOMIC_COUNTER:
+ return 1;
case GL_FLOAT_MAT2:
case GL_FLOAT_MAT3x2:
case GL_FLOAT_MAT4x2:
@@ -271,7 +304,6 @@ int VariableColumnCount(GLenum type)
switch (type)
{
case GL_NONE:
- case GL_STRUCT_ANGLEX:
return 0;
case GL_BOOL:
case GL_FLOAT:
@@ -281,20 +313,36 @@ int VariableColumnCount(GLenum type)
case GL_SAMPLER_3D:
case GL_SAMPLER_CUBE:
case GL_SAMPLER_2D_ARRAY:
+ case GL_SAMPLER_2D_MULTISAMPLE:
case GL_INT_SAMPLER_2D:
case GL_INT_SAMPLER_3D:
case GL_INT_SAMPLER_CUBE:
case GL_INT_SAMPLER_2D_ARRAY:
+ case GL_INT_SAMPLER_2D_MULTISAMPLE:
case GL_SAMPLER_EXTERNAL_OES:
- case GL_SAMPLER_2D_RECT_ARB:
+ case GL_SAMPLER_2D_RECT_ANGLE:
case GL_UNSIGNED_INT_SAMPLER_2D:
case GL_UNSIGNED_INT_SAMPLER_3D:
case GL_UNSIGNED_INT_SAMPLER_CUBE:
case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
case GL_SAMPLER_2D_SHADOW:
case GL_SAMPLER_CUBE_SHADOW:
case GL_SAMPLER_2D_ARRAY_SHADOW:
- return 1;
+ case GL_IMAGE_2D:
+ case GL_INT_IMAGE_2D:
+ case GL_UNSIGNED_INT_IMAGE_2D:
+ case GL_IMAGE_3D:
+ case GL_INT_IMAGE_3D:
+ case GL_UNSIGNED_INT_IMAGE_3D:
+ case GL_IMAGE_2D_ARRAY:
+ case GL_INT_IMAGE_2D_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
+ case GL_IMAGE_CUBE:
+ case GL_INT_IMAGE_CUBE:
+ case GL_UNSIGNED_INT_IMAGE_CUBE:
+ case GL_UNSIGNED_INT_ATOMIC_COUNTER:
+ return 1;
case GL_BOOL_VEC2:
case GL_FLOAT_VEC2:
case GL_INT_VEC2:
@@ -334,14 +382,19 @@ bool IsSamplerType(GLenum type)
case GL_SAMPLER_3D:
case GL_SAMPLER_CUBE:
case GL_SAMPLER_2D_ARRAY:
+ case GL_SAMPLER_EXTERNAL_OES:
+ case GL_SAMPLER_2D_MULTISAMPLE:
+ case GL_SAMPLER_2D_RECT_ANGLE:
case GL_INT_SAMPLER_2D:
case GL_INT_SAMPLER_3D:
case GL_INT_SAMPLER_CUBE:
case GL_INT_SAMPLER_2D_ARRAY:
+ case GL_INT_SAMPLER_2D_MULTISAMPLE:
case GL_UNSIGNED_INT_SAMPLER_2D:
case GL_UNSIGNED_INT_SAMPLER_3D:
case GL_UNSIGNED_INT_SAMPLER_CUBE:
case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
case GL_SAMPLER_2D_SHADOW:
case GL_SAMPLER_CUBE_SHADOW:
case GL_SAMPLER_2D_ARRAY_SHADOW:
@@ -351,6 +404,38 @@ bool IsSamplerType(GLenum type)
return false;
}
+bool IsImageType(GLenum type)
+{
+ switch (type)
+ {
+ case GL_IMAGE_2D:
+ case GL_INT_IMAGE_2D:
+ case GL_UNSIGNED_INT_IMAGE_2D:
+ case GL_IMAGE_3D:
+ case GL_INT_IMAGE_3D:
+ case GL_UNSIGNED_INT_IMAGE_3D:
+ case GL_IMAGE_2D_ARRAY:
+ case GL_INT_IMAGE_2D_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
+ case GL_IMAGE_CUBE:
+ case GL_INT_IMAGE_CUBE:
+ case GL_UNSIGNED_INT_IMAGE_CUBE:
+ return true;
+ }
+ return false;
+}
+
+bool IsAtomicCounterType(GLenum type)
+{
+ return type == GL_UNSIGNED_INT_ATOMIC_COUNTER;
+}
+
+bool IsOpaqueType(GLenum type)
+{
+ // ESSL 3.10 section 4.1.7 defines opaque types as: samplers, images and atomic counters.
+ return IsImageType(type) || IsSamplerType(type) || IsAtomicCounterType(type);
+}
+
GLenum SamplerTypeToTextureType(GLenum samplerType)
{
switch (samplerType)
@@ -361,6 +446,9 @@ GLenum SamplerTypeToTextureType(GLenum samplerType)
case GL_SAMPLER_2D_SHADOW:
return GL_TEXTURE_2D;
+ case GL_SAMPLER_EXTERNAL_OES:
+ return GL_TEXTURE_EXTERNAL_OES;
+
case GL_SAMPLER_CUBE:
case GL_INT_SAMPLER_CUBE:
case GL_UNSIGNED_INT_SAMPLER_CUBE:
@@ -378,6 +466,14 @@ GLenum SamplerTypeToTextureType(GLenum samplerType)
case GL_UNSIGNED_INT_SAMPLER_3D:
return GL_TEXTURE_3D;
+ case GL_SAMPLER_2D_MULTISAMPLE:
+ case GL_INT_SAMPLER_2D_MULTISAMPLE:
+ case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
+ return GL_TEXTURE_2D_MULTISAMPLE;
+
+ case GL_SAMPLER_2D_RECT_ANGLE:
+ return GL_TEXTURE_RECTANGLE_ANGLE;
+
default:
UNREACHABLE();
return 0;
@@ -531,6 +627,21 @@ bool IsTriangleMode(GLenum drawMode)
return false;
}
+bool IsIntegerFormat(GLenum unsizedFormat)
+{
+ switch (unsizedFormat)
+ {
+ case GL_RGBA_INTEGER:
+ case GL_RGB_INTEGER:
+ case GL_RG_INTEGER:
+ case GL_RED_INTEGER:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
// [OpenGL ES SL 3.00.4] Section 11 p. 120
// Vertex Outs/Fragment Ins packing priorities
int VariableSortOrder(GLenum type)
@@ -586,21 +697,37 @@ int VariableSortOrder(GLenum type)
case GL_SAMPLER_2D:
case GL_SAMPLER_CUBE:
case GL_SAMPLER_EXTERNAL_OES:
- case GL_SAMPLER_2D_RECT_ARB:
+ case GL_SAMPLER_2D_RECT_ANGLE:
case GL_SAMPLER_2D_ARRAY:
+ case GL_SAMPLER_2D_MULTISAMPLE:
case GL_SAMPLER_3D:
case GL_INT_SAMPLER_2D:
case GL_INT_SAMPLER_3D:
case GL_INT_SAMPLER_CUBE:
case GL_INT_SAMPLER_2D_ARRAY:
+ case GL_INT_SAMPLER_2D_MULTISAMPLE:
case GL_UNSIGNED_INT_SAMPLER_2D:
case GL_UNSIGNED_INT_SAMPLER_3D:
case GL_UNSIGNED_INT_SAMPLER_CUBE:
case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
case GL_SAMPLER_2D_SHADOW:
case GL_SAMPLER_2D_ARRAY_SHADOW:
case GL_SAMPLER_CUBE_SHADOW:
- return 6;
+ case GL_IMAGE_2D:
+ case GL_INT_IMAGE_2D:
+ case GL_UNSIGNED_INT_IMAGE_2D:
+ case GL_IMAGE_3D:
+ case GL_INT_IMAGE_3D:
+ case GL_UNSIGNED_INT_IMAGE_3D:
+ case GL_IMAGE_2D_ARRAY:
+ case GL_INT_IMAGE_2D_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
+ case GL_IMAGE_CUBE:
+ case GL_INT_IMAGE_CUBE:
+ case GL_UNSIGNED_INT_IMAGE_CUBE:
+ case GL_UNSIGNED_INT_ATOMIC_COUNTER:
+ return 6;
default:
UNREACHABLE();
@@ -608,51 +735,128 @@ int VariableSortOrder(GLenum type)
}
}
-std::string ParseUniformName(const std::string &name, size_t *outSubscript)
+std::string ParseResourceName(const std::string &name, std::vector<unsigned int> *outSubscripts)
{
- // Strip any trailing array operator and retrieve the subscript
- size_t open = name.find_last_of('[');
- size_t close = name.find_last_of(']');
- bool hasIndex = (open != std::string::npos) && (close == name.length() - 1);
- if (!hasIndex)
+ if (outSubscripts)
{
- if (outSubscript)
+ outSubscripts->clear();
+ }
+ // Strip any trailing array indexing operators and retrieve the subscripts.
+ size_t baseNameLength = name.length();
+ bool hasIndex = true;
+ while (hasIndex)
+ {
+ size_t open = name.find_last_of('[', baseNameLength - 1);
+ size_t close = name.find_last_of(']', baseNameLength - 1);
+ hasIndex = (open != std::string::npos) && (close == baseNameLength - 1);
+ if (hasIndex)
{
- *outSubscript = GL_INVALID_INDEX;
+ baseNameLength = open;
+ if (outSubscripts)
+ {
+ int index = atoi(name.substr(open + 1).c_str());
+ if (index >= 0)
+ {
+ outSubscripts->push_back(index);
+ }
+ else
+ {
+ outSubscripts->push_back(GL_INVALID_INDEX);
+ }
+ }
}
- return name;
}
- if (outSubscript)
+ return name.substr(0, baseNameLength);
+}
+
+unsigned int ArraySizeProduct(const std::vector<unsigned int> &arraySizes)
+{
+ unsigned int arraySizeProduct = 1u;
+ for (unsigned int arraySize : arraySizes)
+ {
+ arraySizeProduct *= arraySize;
+ }
+ return arraySizeProduct;
+}
+
+unsigned int ParseArrayIndex(const std::string &name, size_t *nameLengthWithoutArrayIndexOut)
+{
+ ASSERT(nameLengthWithoutArrayIndexOut != nullptr);
+
+ // Strip any trailing array operator and retrieve the subscript
+ size_t open = name.find_last_of('[');
+ if (open != std::string::npos && name.back() == ']')
{
- int index = atoi(name.substr(open + 1).c_str());
- if (index >= 0)
+ bool indexIsValidDecimalNumber = true;
+ for (size_t i = open + 1; i < name.length() - 1u; ++i)
{
- *outSubscript = index;
+ if (!isdigit(name[i]))
+ {
+ indexIsValidDecimalNumber = false;
+ break;
+ }
}
- else
+ if (indexIsValidDecimalNumber)
{
- *outSubscript = GL_INVALID_INDEX;
+ errno = 0; // reset global error flag.
+ unsigned long subscript =
+ strtoul(name.c_str() + open + 1, /*endptr*/ nullptr, /*radix*/ 10);
+
+ // Check if resulting integer is out-of-range or conversion error.
+ if ((subscript <= static_cast<unsigned long>(UINT_MAX)) &&
+ !(subscript == ULONG_MAX && errno == ERANGE) && !(errno != 0 && subscript == 0))
+ {
+ *nameLengthWithoutArrayIndexOut = open;
+ return static_cast<unsigned int>(subscript);
+ }
}
}
- return name.substr(0, open);
+ *nameLengthWithoutArrayIndexOut = name.length();
+ return GL_INVALID_INDEX;
}
-unsigned int ParseAndStripArrayIndex(std::string *name)
+const char *GetGenericErrorMessage(GLenum error)
{
- unsigned int subscript = GL_INVALID_INDEX;
-
- // Strip any trailing array operator and retrieve the subscript
- size_t open = name->find_last_of('[');
- size_t close = name->find_last_of(']');
- if (open != std::string::npos && close == name->length() - 1)
+ switch (error)
{
- subscript = atoi(name->c_str() + open + 1);
- name->erase(open);
+ case GL_NO_ERROR:
+ return "";
+ case GL_INVALID_ENUM:
+ return "Invalid enum.";
+ case GL_INVALID_VALUE:
+ return "Invalid value.";
+ case GL_INVALID_OPERATION:
+ return "Invalid operation.";
+ case GL_STACK_OVERFLOW:
+ return "Stack overflow.";
+ case GL_STACK_UNDERFLOW:
+ return "Stack underflow.";
+ case GL_OUT_OF_MEMORY:
+ return "Out of memory.";
+ case GL_INVALID_FRAMEBUFFER_OPERATION:
+ return "Invalid framebuffer operation.";
+ default:
+ UNREACHABLE();
+ return "Unknown error.";
}
+}
- return subscript;
+unsigned int ElementTypeSize(GLenum elementType)
+{
+ switch (elementType)
+ {
+ case GL_UNSIGNED_BYTE:
+ return sizeof(GLubyte);
+ case GL_UNSIGNED_SHORT:
+ return sizeof(GLushort);
+ case GL_UNSIGNED_INT:
+ return sizeof(GLuint);
+ default:
+ UNREACHABLE();
+ return 0;
+ }
}
} // namespace gl
@@ -710,8 +914,53 @@ bool IsRenderbufferTarget(EGLenum target)
{
return target == EGL_GL_RENDERBUFFER_KHR;
}
+
+const char *GetGenericErrorMessage(EGLint error)
+{
+ switch (error)
+ {
+ case EGL_SUCCESS:
+ return "";
+ case EGL_NOT_INITIALIZED:
+ return "Not initialized.";
+ case EGL_BAD_ACCESS:
+ return "Bad access.";
+ case EGL_BAD_ALLOC:
+ return "Bad allocation.";
+ case EGL_BAD_ATTRIBUTE:
+ return "Bad attribute.";
+ case EGL_BAD_CONFIG:
+ return "Bad config.";
+ case EGL_BAD_CONTEXT:
+ return "Bad context.";
+ case EGL_BAD_CURRENT_SURFACE:
+ return "Bad current surface.";
+ case EGL_BAD_DISPLAY:
+ return "Bad display.";
+ case EGL_BAD_MATCH:
+ return "Bad match.";
+ case EGL_BAD_NATIVE_WINDOW:
+ return "Bad native window.";
+ case EGL_BAD_PARAMETER:
+ return "Bad parameter.";
+ case EGL_BAD_SURFACE:
+ return "Bad surface.";
+ case EGL_CONTEXT_LOST:
+ return "Context lost.";
+ case EGL_BAD_STREAM_KHR:
+ return "Bad stream.";
+ case EGL_BAD_STATE_KHR:
+ return "Bad state.";
+ case EGL_BAD_DEVICE_EXT:
+ return "Bad device.";
+ default:
+ UNREACHABLE();
+ return "Unknown error.";
+ }
}
+} // namespace egl
+
namespace egl_gl
{
GLenum EGLCubeMapTargetToGLCubeMapTarget(EGLenum eglTarget)
@@ -748,7 +997,26 @@ GLuint EGLClientBufferToGLObjectHandle(EGLClientBuffer buffer)
{
return static_cast<GLuint>(reinterpret_cast<uintptr_t>(buffer));
}
+} // namespace egl_gl
+
+namespace gl_egl
+{
+EGLenum GLComponentTypeToEGLColorComponentType(GLenum glComponentType)
+{
+ switch (glComponentType)
+ {
+ case GL_FLOAT:
+ return EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT;
+
+ case GL_UNSIGNED_NORMALIZED:
+ return EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
+
+ default:
+ UNREACHABLE();
+ return EGL_NONE;
+ }
}
+} // namespace gl_egl
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
std::string getTempPath()
diff --git a/src/3rdparty/angle/src/common/utilities.h b/src/3rdparty/angle/src/common/utilities.h
index dc09011a26..f2f9c63d0e 100644
--- a/src/3rdparty/angle/src/common/utilities.h
+++ b/src/3rdparty/angle/src/common/utilities.h
@@ -12,9 +12,10 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include "angle_gl.h"
-#include <string>
#include <math.h>
+#include <string>
+#include <vector>
+#include "angle_gl.h"
#include "common/mathutil.h"
@@ -26,10 +27,12 @@ GLenum VariableComponentType(GLenum type);
size_t VariableComponentSize(GLenum type);
size_t VariableInternalSize(GLenum type);
size_t VariableExternalSize(GLenum type);
-GLenum VariableBoolVectorType(GLenum type);
int VariableRowCount(GLenum type);
int VariableColumnCount(GLenum type);
bool IsSamplerType(GLenum type);
+bool IsImageType(GLenum type);
+bool IsAtomicCounterType(GLenum type);
+bool IsOpaqueType(GLenum type);
GLenum SamplerTypeToTextureType(GLenum samplerType);
bool IsMatrixType(GLenum type);
GLenum TransposeMatrixType(GLenum type);
@@ -37,6 +40,7 @@ int VariableRegisterCount(GLenum type);
int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix);
int MatrixComponentCount(GLenum type, bool isRowMajorMatrix);
int VariableSortOrder(GLenum type);
+GLenum VariableBoolVectorType(GLenum type);
int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize);
@@ -46,9 +50,12 @@ bool IsCubeMapTextureTarget(GLenum target);
size_t CubeMapTextureTargetToLayerIndex(GLenum target);
GLenum LayerIndexToCubeMapTextureTarget(size_t index);
-// Parse the base uniform name and array index. Returns the base name of the uniform. outSubscript is
-// set to GL_INVALID_INDEX if the provided name is not an array or the array index is invalid.
-std::string ParseUniformName(const std::string &name, size_t *outSubscript);
+// Parse the base resource name and array indices. Returns the base name of the resource.
+// If the provided name doesn't index an array, the outSubscripts vector will be empty.
+// If the provided name indexes an array, the outSubscripts vector will contain indices with
+// outermost array indices in the back. If an array index is invalid, GL_INVALID_INDEX is added to
+// outSubscripts.
+std::string ParseResourceName(const std::string &name, std::vector<unsigned int> *outSubscripts);
// Find the range of index values in the provided indices pointer. Primitive restart indices are
// only counted in the range if primitive restart is disabled.
@@ -61,14 +68,71 @@ IndexRange ComputeIndexRange(GLenum indexType,
GLuint GetPrimitiveRestartIndex(GLenum indexType);
bool IsTriangleMode(GLenum drawMode);
+bool IsIntegerFormat(GLenum unsizedFormat);
-// [OpenGL ES 3.0.2] Section 2.3.1 page 14
-// Data Conversion For State-Setting Commands
-// Floating-point values are rounded to the nearest integer, instead of truncated, as done by static_cast.
-template <typename outT> outT iround(GLfloat value) { return static_cast<outT>(value > 0.0f ? floor(value + 0.5f) : ceil(value - 0.5f)); }
-template <typename outT> outT uiround(GLfloat value) { return static_cast<outT>(value + 0.5f); }
+// Returns the product of the sizes in the vector, or 1 if the vector is empty. Doesn't currently
+// perform overflow checks.
+unsigned int ArraySizeProduct(const std::vector<unsigned int> &arraySizes);
-unsigned int ParseAndStripArrayIndex(std::string *name);
+// Return the array index at the end of name, and write the length of name before the final array
+// index into nameLengthWithoutArrayIndexOut. In case name doesn't include an array index, return
+// GL_INVALID_INDEX and write the length of the original string.
+unsigned int ParseArrayIndex(const std::string &name, size_t *nameLengthWithoutArrayIndexOut);
+
+struct UniformTypeInfo final : angle::NonCopyable
+{
+ constexpr UniformTypeInfo(GLenum type,
+ GLenum componentType,
+ GLenum samplerTextureType,
+ GLenum transposedMatrixType,
+ GLenum boolVectorType,
+ int rowCount,
+ int columnCount,
+ int componentCount,
+ size_t componentSize,
+ size_t internalSize,
+ size_t externalSize,
+ bool isSampler,
+ bool isMatrixType,
+ bool isImageType)
+ : type(type),
+ componentType(componentType),
+ samplerTextureType(samplerTextureType),
+ transposedMatrixType(transposedMatrixType),
+ boolVectorType(boolVectorType),
+ rowCount(rowCount),
+ columnCount(columnCount),
+ componentCount(componentCount),
+ componentSize(componentSize),
+ internalSize(internalSize),
+ externalSize(externalSize),
+ isSampler(isSampler),
+ isMatrixType(isMatrixType),
+ isImageType(isImageType)
+ {
+ }
+
+ GLenum type;
+ GLenum componentType;
+ GLenum samplerTextureType;
+ GLenum transposedMatrixType;
+ GLenum boolVectorType;
+ int rowCount;
+ int columnCount;
+ int componentCount;
+ size_t componentSize;
+ size_t internalSize;
+ size_t externalSize;
+ bool isSampler;
+ bool isMatrixType;
+ bool isImageType;
+};
+
+const UniformTypeInfo &GetUniformTypeInfo(GLenum uniformType);
+
+const char *GetGenericErrorMessage(GLenum error);
+
+unsigned int ElementTypeSize(GLenum elementType);
} // namespace gl
@@ -81,7 +145,9 @@ size_t CubeMapTextureTargetToLayerIndex(EGLenum target);
EGLenum LayerIndexToCubeMapTextureTarget(size_t index);
bool IsTextureTarget(EGLenum target);
bool IsRenderbufferTarget(EGLenum target);
-}
+
+const char *GetGenericErrorMessage(EGLint error);
+} // namespace egl
namespace egl_gl
{
@@ -90,6 +156,11 @@ GLenum EGLImageTargetToGLTextureTarget(EGLenum eglTarget);
GLuint EGLClientBufferToGLObjectHandle(EGLClientBuffer buffer);
}
+namespace gl_egl
+{
+EGLenum GLComponentTypeToEGLColorComponentType(GLenum glComponentType);
+} // namespace gl_egl
+
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
std::string getTempPath();
void writeFile(const char* path, const void* data, size_t size);
diff --git a/src/3rdparty/angle/src/common/vector_utils.h b/src/3rdparty/angle/src/common/vector_utils.h
new file mode 100644
index 0000000000..9f5bee1a4a
--- /dev/null
+++ b/src/3rdparty/angle/src/common/vector_utils.h
@@ -0,0 +1,523 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// vector_utils.h: Utility classes implementing various vector operations
+
+#ifndef COMMON_VECTOR_UTILS_H_
+#define COMMON_VECTOR_UTILS_H_
+
+#include <cmath>
+#include <cstddef>
+#include <ostream>
+#include <type_traits>
+
+namespace angle
+{
+
+template <size_t Dimension, typename Type>
+class Vector;
+
+using Vector2 = Vector<2, float>;
+using Vector3 = Vector<3, float>;
+using Vector4 = Vector<4, float>;
+
+using Vector2I = Vector<2, int>;
+using Vector3I = Vector<3, int>;
+using Vector4I = Vector<4, int>;
+
+using Vector2U = Vector<2, unsigned int>;
+using Vector3U = Vector<3, unsigned int>;
+using Vector4U = Vector<4, unsigned int>;
+
+template <size_t Dimension, typename Type>
+class VectorBase
+{
+ public:
+ using VectorN = Vector<Dimension, Type>;
+
+ // Constructors
+ VectorBase() = default;
+ explicit VectorBase(Type element);
+
+ template <typename Type2>
+ VectorBase(const VectorBase<Dimension, Type2> &other);
+
+ template <typename Arg1, typename Arg2, typename... Args>
+ VectorBase(const Arg1 &arg1, const Arg2 &arg2, const Args &... args);
+
+ // Access the vector backing storage directly
+ const Type *data() const { return mData; }
+ Type *data() { return mData; }
+ constexpr size_t size() const { return Dimension; }
+
+ // Load or store the pointer from / to raw data
+ static VectorN Load(const Type *source);
+ static void Store(const VectorN &source, Type *destination);
+
+ // Index the vector
+ Type &operator[](size_t i) { return mData[i]; }
+ const Type &operator[](size_t i) const { return mData[i]; }
+
+ // Basic arithmetic operations
+ VectorN operator+() const;
+ VectorN operator-() const;
+ VectorN operator+(const VectorN &other) const;
+ VectorN operator-(const VectorN &other) const;
+ VectorN operator*(const VectorN &other) const;
+ VectorN operator/(const VectorN &other) const;
+ VectorN operator*(Type other) const;
+ VectorN operator/(Type other) const;
+ friend VectorN operator*(Type a, const VectorN &b) { return b * a; }
+
+ // Compound arithmetic operations
+ VectorN &operator+=(const VectorN &other);
+ VectorN &operator-=(const VectorN &other);
+ VectorN &operator*=(const VectorN &other);
+ VectorN &operator/=(const VectorN &other);
+ VectorN &operator*=(Type other);
+ VectorN &operator/=(Type other);
+
+ // Comparison operators
+ bool operator==(const VectorN &other) const;
+ bool operator!=(const VectorN &other) const;
+
+ // Other arithmetic operations
+ Type length() const;
+ Type lengthSquared() const;
+ Type dot(const VectorBase<Dimension, Type> &other) const;
+ VectorN normalized() const;
+
+ protected:
+ template <size_t CurrentIndex, size_t OtherDimension, typename OtherType, typename... Args>
+ void initWithList(const Vector<OtherDimension, OtherType> &arg1, const Args &... args);
+
+ // Some old compilers consider this function an alternative for initWithList(Vector)
+ // when the variant above is more precise. Use SFINAE on the return value to hide
+ // this variant for non-arithmetic types. The return value is still void.
+ template <size_t CurrentIndex, typename OtherType, typename... Args>
+ typename std::enable_if<std::is_arithmetic<OtherType>::value>::type initWithList(
+ OtherType arg1,
+ const Args &... args);
+
+ template <size_t CurrentIndex>
+ void initWithList() const;
+
+ template <size_t Dimension2, typename Type2>
+ friend class VectorBase;
+
+ Type mData[Dimension];
+};
+
+template <size_t Dimension, typename Type>
+std::ostream &operator<<(std::ostream &ostream, const VectorBase<Dimension, Type> &vector);
+
+template <typename Type>
+class Vector<2, Type> : public VectorBase<2, Type>
+{
+ public:
+ // Import the constructors defined in VectorBase
+ using VectorBase<2, Type>::VectorBase;
+
+ // Element shorthands
+ Type &x() { return this->mData[0]; }
+ Type &y() { return this->mData[1]; }
+
+ const Type &x() const { return this->mData[0]; }
+ const Type &y() const { return this->mData[1]; }
+};
+
+template <typename Type>
+std::ostream &operator<<(std::ostream &ostream, const Vector<2, Type> &vector);
+
+template <typename Type>
+class Vector<3, Type> : public VectorBase<3, Type>
+{
+ public:
+ // Import the constructors defined in VectorBase
+ using VectorBase<3, Type>::VectorBase;
+
+ // Additional operations
+ Vector<3, Type> cross(const Vector<3, Type> &other) const;
+
+ // Element shorthands
+ Type &x() { return this->mData[0]; }
+ Type &y() { return this->mData[1]; }
+ Type &z() { return this->mData[2]; }
+
+ const Type &x() const { return this->mData[0]; }
+ const Type &y() const { return this->mData[1]; }
+ const Type &z() const { return this->mData[2]; }
+};
+
+template <typename Type>
+std::ostream &operator<<(std::ostream &ostream, const Vector<3, Type> &vector);
+
+template <typename Type>
+class Vector<4, Type> : public VectorBase<4, Type>
+{
+ public:
+ // Import the constructors defined in VectorBase
+ using VectorBase<4, Type>::VectorBase;
+
+ // Element shorthands
+ Type &x() { return this->mData[0]; }
+ Type &y() { return this->mData[1]; }
+ Type &z() { return this->mData[2]; }
+ Type &w() { return this->mData[3]; }
+
+ const Type &x() const { return this->mData[0]; }
+ const Type &y() const { return this->mData[1]; }
+ const Type &z() const { return this->mData[2]; }
+ const Type &w() const { return this->mData[3]; }
+};
+
+template <typename Type>
+std::ostream &operator<<(std::ostream &ostream, const Vector<4, Type> &vector);
+
+// Implementation of constructors and misc operations
+
+template <size_t Dimension, typename Type>
+VectorBase<Dimension, Type>::VectorBase(Type element)
+{
+ for (size_t i = 0; i < Dimension; ++i)
+ {
+ mData[i] = element;
+ }
+}
+
+template <size_t Dimension, typename Type>
+template <typename Type2>
+VectorBase<Dimension, Type>::VectorBase(const VectorBase<Dimension, Type2> &other)
+{
+ for (size_t i = 0; i < Dimension; ++i)
+ {
+ mData[i] = static_cast<Type>(other.mData[i]);
+ }
+}
+
+// Ideally we would like to have only two constructors:
+// - a scalar constructor that takes Type as a parameter
+// - a compound constructor
+// However if we define the compound constructor for when it has a single arguments, then calling
+// Vector2(0.0) will be ambiguous. To solve this we take advantage of there being a single compound
+// constructor with a single argument, which is the copy constructor. We end up with three
+// constructors:
+// - the scalar constructor
+// - the copy constructor
+// - the compound constructor for two or more arguments, hence the arg1, and arg2 here.
+template <size_t Dimension, typename Type>
+template <typename Arg1, typename Arg2, typename... Args>
+VectorBase<Dimension, Type>::VectorBase(const Arg1 &arg1, const Arg2 &arg2, const Args &... args)
+{
+ initWithList<0>(arg1, arg2, args...);
+}
+
+template <size_t Dimension, typename Type>
+template <size_t CurrentIndex, size_t OtherDimension, typename OtherType, typename... Args>
+void VectorBase<Dimension, Type>::initWithList(const Vector<OtherDimension, OtherType> &arg1,
+ const Args &... args)
+{
+ static_assert(CurrentIndex + OtherDimension <= Dimension,
+ "Too much data in the vector constructor.");
+ for (size_t i = 0; i < OtherDimension; ++i)
+ {
+ mData[CurrentIndex + i] = static_cast<Type>(arg1.mData[i]);
+ }
+ initWithList<CurrentIndex + OtherDimension>(args...);
+}
+
+template <size_t Dimension, typename Type>
+template <size_t CurrentIndex, typename OtherType, typename... Args>
+typename std::enable_if<std::is_arithmetic<OtherType>::value>::type
+VectorBase<Dimension, Type>::initWithList(OtherType arg1, const Args &... args)
+{
+ static_assert(CurrentIndex + 1 <= Dimension, "Too much data in the vector constructor.");
+ mData[CurrentIndex] = static_cast<Type>(arg1);
+ initWithList<CurrentIndex + 1>(args...);
+}
+
+template <size_t Dimension, typename Type>
+template <size_t CurrentIndex>
+void VectorBase<Dimension, Type>::initWithList() const
+{
+ static_assert(CurrentIndex == Dimension, "Not enough data in the vector constructor.");
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> VectorBase<Dimension, Type>::Load(const Type *source)
+{
+ Vector<Dimension, Type> result;
+ for (size_t i = 0; i < Dimension; ++i)
+ {
+ result.mData[i] = source[i];
+ }
+ return result;
+}
+
+template <size_t Dimension, typename Type>
+void VectorBase<Dimension, Type>::Store(const Vector<Dimension, Type> &source, Type *destination)
+{
+ for (size_t i = 0; i < Dimension; ++i)
+ {
+ destination[i] = source.mData[i];
+ }
+}
+
+// Implementation of basic arithmetic operations
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> VectorBase<Dimension, Type>::operator+() const
+{
+ Vector<Dimension, Type> result;
+ for (size_t i = 0; i < Dimension; ++i)
+ {
+ result.mData[i] = +mData[i];
+ }
+ return result;
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> VectorBase<Dimension, Type>::operator-() const
+{
+ Vector<Dimension, Type> result;
+ for (size_t i = 0; i < Dimension; ++i)
+ {
+ result.mData[i] = -mData[i];
+ }
+ return result;
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> VectorBase<Dimension, Type>::operator+(
+ const Vector<Dimension, Type> &other) const
+{
+ Vector<Dimension, Type> result;
+ for (size_t i = 0; i < Dimension; ++i)
+ {
+ result.mData[i] = mData[i] + other.mData[i];
+ }
+ return result;
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> VectorBase<Dimension, Type>::operator-(
+ const Vector<Dimension, Type> &other) const
+{
+ Vector<Dimension, Type> result;
+ for (size_t i = 0; i < Dimension; ++i)
+ {
+ result.mData[i] = mData[i] - other.mData[i];
+ }
+ return result;
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> VectorBase<Dimension, Type>::operator*(
+ const Vector<Dimension, Type> &other) const
+{
+ Vector<Dimension, Type> result;
+ for (size_t i = 0; i < Dimension; ++i)
+ {
+ result.mData[i] = mData[i] * other.mData[i];
+ }
+ return result;
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> VectorBase<Dimension, Type>::operator/(
+ const Vector<Dimension, Type> &other) const
+{
+ Vector<Dimension, Type> result;
+ for (size_t i = 0; i < Dimension; ++i)
+ {
+ result.mData[i] = mData[i] / other.mData[i];
+ }
+ return result;
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> VectorBase<Dimension, Type>::operator*(Type other) const
+{
+ Vector<Dimension, Type> result;
+ for (size_t i = 0; i < Dimension; ++i)
+ {
+ result.mData[i] = mData[i] * other;
+ }
+ return result;
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> VectorBase<Dimension, Type>::operator/(Type other) const
+{
+ Vector<Dimension, Type> result;
+ for (size_t i = 0; i < Dimension; ++i)
+ {
+ result.mData[i] = mData[i] / other;
+ }
+ return result;
+}
+
+// Implementation of compound arithmetic operations
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> &VectorBase<Dimension, Type>::operator+=(
+ const Vector<Dimension, Type> &other)
+{
+ for (size_t i = 0; i < Dimension; ++i)
+ {
+ mData[i] += other.mData[i];
+ }
+ return *reinterpret_cast<Vector<Dimension, Type> *>(this);
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> &VectorBase<Dimension, Type>::operator-=(
+ const Vector<Dimension, Type> &other)
+{
+ for (size_t i = 0; i < Dimension; ++i)
+ {
+ mData[i] -= other.mData[i];
+ }
+ return *reinterpret_cast<Vector<Dimension, Type> *>(this);
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> &VectorBase<Dimension, Type>::operator*=(
+ const Vector<Dimension, Type> &other)
+{
+ for (size_t i = 0; i < Dimension; ++i)
+ {
+ mData[i] *= other.mData[i];
+ }
+ return *reinterpret_cast<Vector<Dimension, Type> *>(this);
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> &VectorBase<Dimension, Type>::operator/=(
+ const Vector<Dimension, Type> &other)
+{
+ for (size_t i = 0; i < Dimension; ++i)
+ {
+ mData[i] /= other.mData[i];
+ }
+ return *reinterpret_cast<Vector<Dimension, Type> *>(this);
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> &VectorBase<Dimension, Type>::operator*=(Type other)
+{
+ for (size_t i = 0; i < Dimension; ++i)
+ {
+ mData[i] *= other;
+ }
+ return *reinterpret_cast<Vector<Dimension, Type> *>(this);
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> &VectorBase<Dimension, Type>::operator/=(Type other)
+{
+ for (size_t i = 0; i < Dimension; ++i)
+ {
+ mData[i] /= other;
+ }
+ return *reinterpret_cast<Vector<Dimension, Type> *>(this);
+}
+
+// Implementation of comparison operators
+template <size_t Dimension, typename Type>
+bool VectorBase<Dimension, Type>::operator==(const Vector<Dimension, Type> &other) const
+{
+ for (size_t i = 0; i < Dimension; ++i)
+ {
+ if (mData[i] != other.mData[i])
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+template <size_t Dimension, typename Type>
+bool VectorBase<Dimension, Type>::operator!=(const Vector<Dimension, Type> &other) const
+{
+ return !(*this == other);
+}
+
+// Implementation of other arithmetic operations
+template <size_t Dimension, typename Type>
+Type VectorBase<Dimension, Type>::length() const
+{
+ static_assert(std::is_floating_point<Type>::value,
+ "VectorN::length is only defined for floating point vectors");
+ return std::sqrt(lengthSquared());
+}
+
+template <size_t Dimension, typename Type>
+Type VectorBase<Dimension, Type>::lengthSquared() const
+{
+ return dot(*this);
+}
+
+template <size_t Dimension, typename Type>
+Type VectorBase<Dimension, Type>::dot(const VectorBase<Dimension, Type> &other) const
+{
+ Type sum = Type();
+ for (size_t i = 0; i < Dimension; ++i)
+ {
+ sum += mData[i] * other.mData[i];
+ }
+ return sum;
+}
+
+template <size_t Dimension, typename Type>
+std::ostream &operator<<(std::ostream &ostream, const VectorBase<Dimension, Type> &vector)
+{
+ ostream << "[ ";
+ for (size_t elementIdx = 0; elementIdx < Dimension; elementIdx++)
+ {
+ if (elementIdx > 0)
+ {
+ ostream << ", ";
+ }
+ ostream << vector.data()[elementIdx];
+ }
+ ostream << " ]";
+ return ostream;
+}
+
+template <size_t Dimension, typename Type>
+Vector<Dimension, Type> VectorBase<Dimension, Type>::normalized() const
+{
+ static_assert(std::is_floating_point<Type>::value,
+ "VectorN::normalized is only defined for floating point vectors");
+ return *this / length();
+}
+
+template <typename Type>
+std::ostream &operator<<(std::ostream &ostream, const Vector<2, Type> &vector)
+{
+ return ostream << static_cast<const VectorBase<2, Type> &>(vector);
+}
+
+template <typename Type>
+Vector<3, Type> Vector<3, Type>::cross(const Vector<3, Type> &other) const
+{
+ return Vector<3, Type>(y() * other.z() - z() * other.y(), z() * other.x() - x() * other.z(),
+ x() * other.y() - y() * other.x());
+}
+
+template <typename Type>
+std::ostream &operator<<(std::ostream &ostream, const Vector<3, Type> &vector)
+{
+ return ostream << static_cast<const VectorBase<3, Type> &>(vector);
+}
+
+template <typename Type>
+std::ostream &operator<<(std::ostream &ostream, const Vector<4, Type> &vector)
+{
+ return ostream << static_cast<const VectorBase<4, Type> &>(vector);
+}
+
+} // namespace angle
+
+#endif // COMMON_VECTOR_UTILS_H_
diff --git a/src/3rdparty/angle/src/compiler/fuzz/translator_fuzzer.cpp b/src/3rdparty/angle/src/compiler/fuzz/translator_fuzzer.cpp
new file mode 100644
index 0000000000..910af8be6f
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/fuzz/translator_fuzzer.cpp
@@ -0,0 +1,179 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// translator_fuzzer.cpp: A libfuzzer fuzzer for the shader translator.
+
+#include <cstddef>
+#include <cstdint>
+#include <iostream>
+#include <memory>
+#include <unordered_map>
+
+#include "angle_gl.h"
+#include "compiler/translator/Compiler.h"
+#include "compiler/translator/util.h"
+
+using namespace sh;
+
+struct TranslatorCacheKey
+{
+ bool operator==(const TranslatorCacheKey &other) const
+ {
+ return type == other.type && spec == other.spec && output == other.output;
+ }
+
+ uint32_t type = 0;
+ uint32_t spec = 0;
+ uint32_t output = 0;
+};
+
+namespace std
+{
+
+template <>
+struct hash<TranslatorCacheKey>
+{
+ std::size_t operator()(const TranslatorCacheKey &k) const
+ {
+ return (hash<uint32_t>()(k.type) << 1) ^ (hash<uint32_t>()(k.spec) >> 1) ^
+ hash<uint32_t>()(k.output);
+ }
+};
+} // namespace std
+
+struct TCompilerDeleter
+{
+ void operator()(TCompiler *compiler) const { DeleteCompiler(compiler); }
+};
+
+using UniqueTCompiler = std::unique_ptr<TCompiler, TCompilerDeleter>;
+
+static std::unordered_map<TranslatorCacheKey, UniqueTCompiler> translators;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ // Reserve some size for future compile options
+ const size_t kHeaderSize = 128;
+
+ if (size <= kHeaderSize)
+ {
+ return 0;
+ }
+
+ // Make sure the rest of data will be a valid C string so that we don't have to copy it.
+ if (data[size - 1] != 0)
+ {
+ return 0;
+ }
+
+ uint32_t type = *reinterpret_cast<const uint32_t *>(data);
+ uint32_t spec = *reinterpret_cast<const uint32_t *>(data + 4);
+ uint32_t output = *reinterpret_cast<const uint32_t *>(data + 8);
+ uint64_t options = *reinterpret_cast<const uint64_t *>(data + 12);
+
+ if (type != GL_FRAGMENT_SHADER && type != GL_VERTEX_SHADER)
+ {
+ return 0;
+ }
+
+ if (spec != SH_GLES2_SPEC && type != SH_WEBGL_SPEC && spec != SH_GLES3_SPEC &&
+ spec != SH_WEBGL2_SPEC)
+ {
+ return 0;
+ }
+
+ ShShaderOutput shaderOutput = static_cast<ShShaderOutput>(output);
+ if (!(IsOutputGLSL(shaderOutput) || IsOutputESSL(shaderOutput)) &&
+ (options & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER) != 0u)
+ {
+ // This compiler option is only available in ESSL and GLSL.
+ return 0;
+ }
+
+ std::vector<uint32_t> validOutputs;
+ validOutputs.push_back(SH_ESSL_OUTPUT);
+ validOutputs.push_back(SH_GLSL_COMPATIBILITY_OUTPUT);
+ validOutputs.push_back(SH_GLSL_130_OUTPUT);
+ validOutputs.push_back(SH_GLSL_140_OUTPUT);
+ validOutputs.push_back(SH_GLSL_150_CORE_OUTPUT);
+ validOutputs.push_back(SH_GLSL_330_CORE_OUTPUT);
+ validOutputs.push_back(SH_GLSL_400_CORE_OUTPUT);
+ validOutputs.push_back(SH_GLSL_410_CORE_OUTPUT);
+ validOutputs.push_back(SH_GLSL_420_CORE_OUTPUT);
+ validOutputs.push_back(SH_GLSL_430_CORE_OUTPUT);
+ validOutputs.push_back(SH_GLSL_440_CORE_OUTPUT);
+ validOutputs.push_back(SH_GLSL_450_CORE_OUTPUT);
+ validOutputs.push_back(SH_HLSL_3_0_OUTPUT);
+ validOutputs.push_back(SH_HLSL_4_1_OUTPUT);
+ validOutputs.push_back(SH_HLSL_4_0_FL9_3_OUTPUT);
+ bool found = false;
+ for (auto valid : validOutputs)
+ {
+ found = found || (valid == output);
+ }
+ if (!found)
+ {
+ return 0;
+ }
+
+ size -= kHeaderSize;
+ data += kHeaderSize;
+
+ if (!sh::Initialize())
+ {
+ return 0;
+ }
+
+ TranslatorCacheKey key;
+ key.type = type;
+ key.spec = spec;
+ key.output = output;
+
+ if (translators.find(key) == translators.end())
+ {
+ UniqueTCompiler translator(
+ ConstructCompiler(type, static_cast<ShShaderSpec>(spec), shaderOutput));
+
+ if (translator == nullptr)
+ {
+ return 0;
+ }
+
+ ShBuiltInResources resources;
+ sh::InitBuiltInResources(&resources);
+
+ // Enable all the extensions to have more coverage
+ resources.OES_standard_derivatives = 1;
+ resources.OES_EGL_image_external = 1;
+ resources.OES_EGL_image_external_essl3 = 1;
+ resources.NV_EGL_stream_consumer_external = 1;
+ resources.ARB_texture_rectangle = 1;
+ resources.EXT_blend_func_extended = 1;
+ resources.EXT_draw_buffers = 1;
+ resources.EXT_frag_depth = 1;
+ resources.EXT_shader_texture_lod = 1;
+ resources.WEBGL_debug_shader_precision = 1;
+ resources.EXT_shader_framebuffer_fetch = 1;
+ resources.NV_shader_framebuffer_fetch = 1;
+ resources.ARM_shader_framebuffer_fetch = 1;
+ resources.EXT_YUV_target = 1;
+ resources.MaxDualSourceDrawBuffers = 1;
+
+ if (!translator->Init(resources))
+ {
+ return 0;
+ }
+
+ translators[key] = std::move(translator);
+ }
+
+ auto &translator = translators[key];
+
+ const char *shaderStrings[] = {reinterpret_cast<const char *>(data)};
+ translator->compile(shaderStrings, 1, options);
+
+ return 0;
+}
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp
index 68c6e9cea4..c89bc9fa76 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp
+++ b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp
@@ -4,9 +4,9 @@
// found in the LICENSE file.
//
-#include "DiagnosticsBase.h"
+#include "compiler/preprocessor/DiagnosticsBase.h"
-#include <cassert>
+#include "common/debug.h"
namespace pp
{
@@ -15,122 +15,128 @@ Diagnostics::~Diagnostics()
{
}
-void Diagnostics::report(ID id,
- const SourceLocation &loc,
- const std::string &text)
+void Diagnostics::report(ID id, const SourceLocation &loc, const std::string &text)
{
- // TODO(alokp): Keep a count of errors and warnings.
print(id, loc, text);
}
-Diagnostics::Severity Diagnostics::severity(ID id)
+bool Diagnostics::isError(ID id)
{
if ((id > PP_ERROR_BEGIN) && (id < PP_ERROR_END))
- return PP_ERROR;
+ return true;
if ((id > PP_WARNING_BEGIN) && (id < PP_WARNING_END))
- return PP_WARNING;
+ return false;
- assert(false);
- return PP_ERROR;
+ UNREACHABLE();
+ return true;
}
-std::string Diagnostics::message(ID id)
+const char *Diagnostics::message(ID id)
{
switch (id)
{
- // Errors begin.
- case PP_INTERNAL_ERROR:
- return "internal error";
- case PP_OUT_OF_MEMORY:
- return "out of memory";
- case PP_INVALID_CHARACTER:
- return "invalid character";
- case PP_INVALID_NUMBER:
- return "invalid number";
- case PP_INTEGER_OVERFLOW:
- return "integer overflow";
- case PP_FLOAT_OVERFLOW:
- return "float overflow";
- case PP_TOKEN_TOO_LONG:
- return "token too long";
- case PP_INVALID_EXPRESSION:
- return "invalid expression";
- case PP_DIVISION_BY_ZERO:
- return "division by zero";
- case PP_EOF_IN_COMMENT:
- return "unexpected end of file found in comment";
- case PP_UNEXPECTED_TOKEN:
- return "unexpected token";
- case PP_DIRECTIVE_INVALID_NAME:
- return "invalid directive name";
- case PP_MACRO_NAME_RESERVED:
- return "macro name is reserved";
- case PP_MACRO_REDEFINED:
- return "macro redefined";
- case PP_MACRO_PREDEFINED_REDEFINED:
- return "predefined macro redefined";
- case PP_MACRO_PREDEFINED_UNDEFINED:
- return "predefined macro undefined";
- case PP_MACRO_UNTERMINATED_INVOCATION:
- return "unterminated macro invocation";
- case PP_MACRO_TOO_FEW_ARGS:
- return "Not enough arguments for macro";
- case PP_MACRO_TOO_MANY_ARGS:
- return "Too many arguments for macro";
- case PP_MACRO_DUPLICATE_PARAMETER_NAMES:
- return "duplicate macro parameter name";
- case PP_CONDITIONAL_ENDIF_WITHOUT_IF:
- return "unexpected #endif found without a matching #if";
- case PP_CONDITIONAL_ELSE_WITHOUT_IF:
- return "unexpected #else found without a matching #if";
- case PP_CONDITIONAL_ELSE_AFTER_ELSE:
- return "unexpected #else found after another #else";
- case PP_CONDITIONAL_ELIF_WITHOUT_IF:
- return "unexpected #elif found without a matching #if";
- case PP_CONDITIONAL_ELIF_AFTER_ELSE:
- return "unexpected #elif found after #else";
- case PP_CONDITIONAL_UNTERMINATED:
- return "unexpected end of file found in conditional block";
- case PP_INVALID_EXTENSION_NAME:
- return "invalid extension name";
- case PP_INVALID_EXTENSION_BEHAVIOR:
- return "invalid extension behavior";
- case PP_INVALID_EXTENSION_DIRECTIVE:
- return "invalid extension directive";
- case PP_INVALID_VERSION_NUMBER:
- return "invalid version number";
- case PP_INVALID_VERSION_DIRECTIVE:
- return "invalid version directive";
- case PP_VERSION_NOT_FIRST_STATEMENT:
- return "#version directive must occur before anything else, "
- "except for comments and white space";
- case PP_VERSION_NOT_FIRST_LINE_ESSL3:
- return "#version directive must occur on the first line of the shader";
- case PP_INVALID_LINE_NUMBER:
- return "invalid line number";
- case PP_INVALID_FILE_NUMBER:
- return "invalid file number";
- case PP_INVALID_LINE_DIRECTIVE:
- return "invalid line directive";
- case PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL3:
- return "extension directive must occur before any non-preprocessor tokens in ESSL3";
- // Errors end.
- // Warnings begin.
- case PP_EOF_IN_DIRECTIVE:
- return "unexpected end of file found in directive";
- case PP_CONDITIONAL_UNEXPECTED_TOKEN:
- return "unexpected token after conditional expression";
- case PP_UNRECOGNIZED_PRAGMA:
- return "unrecognized pragma";
- case PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL1:
- return "extension directive should occur before any non-preprocessor tokens";
- case PP_WARNING_MACRO_NAME_RESERVED:
- return "macro name with a double underscore is reserved - unintented behavior is possible";
- // Warnings end.
- default:
- assert(false);
- return "";
+ // Errors begin.
+ case PP_INTERNAL_ERROR:
+ return "internal error";
+ case PP_OUT_OF_MEMORY:
+ return "out of memory";
+ case PP_INVALID_CHARACTER:
+ return "invalid character";
+ case PP_INVALID_NUMBER:
+ return "invalid number";
+ case PP_INTEGER_OVERFLOW:
+ return "integer overflow";
+ case PP_FLOAT_OVERFLOW:
+ return "float overflow";
+ case PP_TOKEN_TOO_LONG:
+ return "token too long";
+ case PP_INVALID_EXPRESSION:
+ return "invalid expression";
+ case PP_DIVISION_BY_ZERO:
+ return "division by zero";
+ case PP_EOF_IN_COMMENT:
+ return "unexpected end of file found in comment";
+ case PP_UNEXPECTED_TOKEN:
+ return "unexpected token";
+ case PP_DIRECTIVE_INVALID_NAME:
+ return "invalid directive name";
+ case PP_MACRO_NAME_RESERVED:
+ return "macro name is reserved";
+ case PP_MACRO_REDEFINED:
+ return "macro redefined";
+ case PP_MACRO_PREDEFINED_REDEFINED:
+ return "predefined macro redefined";
+ case PP_MACRO_PREDEFINED_UNDEFINED:
+ return "predefined macro undefined";
+ case PP_MACRO_UNTERMINATED_INVOCATION:
+ return "unterminated macro invocation";
+ case PP_MACRO_UNDEFINED_WHILE_INVOKED:
+ return "macro undefined while being invoked";
+ case PP_MACRO_TOO_FEW_ARGS:
+ return "Not enough arguments for macro";
+ case PP_MACRO_TOO_MANY_ARGS:
+ return "Too many arguments for macro";
+ case PP_MACRO_DUPLICATE_PARAMETER_NAMES:
+ return "duplicate macro parameter name";
+ case PP_MACRO_INVOCATION_CHAIN_TOO_DEEP:
+ return "macro invocation chain too deep";
+ case PP_CONDITIONAL_ENDIF_WITHOUT_IF:
+ return "unexpected #endif found without a matching #if";
+ case PP_CONDITIONAL_ELSE_WITHOUT_IF:
+ return "unexpected #else found without a matching #if";
+ case PP_CONDITIONAL_ELSE_AFTER_ELSE:
+ return "unexpected #else found after another #else";
+ case PP_CONDITIONAL_ELIF_WITHOUT_IF:
+ return "unexpected #elif found without a matching #if";
+ case PP_CONDITIONAL_ELIF_AFTER_ELSE:
+ return "unexpected #elif found after #else";
+ case PP_CONDITIONAL_UNTERMINATED:
+ return "unexpected end of file found in conditional block";
+ case PP_INVALID_EXTENSION_NAME:
+ return "invalid extension name";
+ case PP_INVALID_EXTENSION_BEHAVIOR:
+ return "invalid extension behavior";
+ case PP_INVALID_EXTENSION_DIRECTIVE:
+ return "invalid extension directive";
+ case PP_INVALID_VERSION_NUMBER:
+ return "invalid version number";
+ case PP_INVALID_VERSION_DIRECTIVE:
+ return "invalid version directive";
+ case PP_VERSION_NOT_FIRST_STATEMENT:
+ return "#version directive must occur before anything else, "
+ "except for comments and white space";
+ case PP_VERSION_NOT_FIRST_LINE_ESSL3:
+ return "#version directive must occur on the first line of the shader";
+ case PP_INVALID_LINE_NUMBER:
+ return "invalid line number";
+ case PP_INVALID_FILE_NUMBER:
+ return "invalid file number";
+ case PP_INVALID_LINE_DIRECTIVE:
+ return "invalid line directive";
+ case PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL3:
+ return "extension directive must occur before any non-preprocessor tokens in ESSL3";
+ case PP_UNDEFINED_SHIFT:
+ return "shift exponent is negative or undefined";
+ case PP_TOKENIZER_ERROR:
+ return "internal tokenizer error";
+ // Errors end.
+ // Warnings begin.
+ case PP_EOF_IN_DIRECTIVE:
+ return "unexpected end of file found in directive";
+ case PP_CONDITIONAL_UNEXPECTED_TOKEN:
+ return "unexpected token after conditional expression";
+ case PP_UNRECOGNIZED_PRAGMA:
+ return "unrecognized pragma";
+ case PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL1:
+ return "extension directive should occur before any non-preprocessor tokens";
+ case PP_WARNING_MACRO_NAME_RESERVED:
+ return "macro name with a double underscore is reserved - unintented behavior is "
+ "possible";
+ // Warnings end.
+ default:
+ UNREACHABLE();
+ return "";
}
}
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h
index d26c174f01..ea37614606 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h
@@ -19,11 +19,6 @@ struct SourceLocation;
class Diagnostics
{
public:
- enum Severity
- {
- PP_ERROR,
- PP_WARNING
- };
enum ID
{
PP_ERROR_BEGIN,
@@ -44,9 +39,11 @@ class Diagnostics
PP_MACRO_PREDEFINED_REDEFINED,
PP_MACRO_PREDEFINED_UNDEFINED,
PP_MACRO_UNTERMINATED_INVOCATION,
+ PP_MACRO_UNDEFINED_WHILE_INVOKED,
PP_MACRO_TOO_FEW_ARGS,
PP_MACRO_TOO_MANY_ARGS,
PP_MACRO_DUPLICATE_PARAMETER_NAMES,
+ PP_MACRO_INVOCATION_CHAIN_TOO_DEEP,
PP_CONDITIONAL_ENDIF_WITHOUT_IF,
PP_CONDITIONAL_ELSE_WITHOUT_IF,
PP_CONDITIONAL_ELSE_AFTER_ELSE,
@@ -65,6 +62,8 @@ class Diagnostics
PP_INVALID_FILE_NUMBER,
PP_INVALID_LINE_DIRECTIVE,
PP_NON_PP_TOKEN_BEFORE_EXTENSION_ESSL3,
+ PP_UNDEFINED_SHIFT,
+ PP_TOKENIZER_ERROR,
PP_ERROR_END,
PP_WARNING_BEGIN,
@@ -80,12 +79,10 @@ class Diagnostics
void report(ID id, const SourceLocation &loc, const std::string &text);
protected:
- Severity severity(ID id);
- std::string message(ID id);
+ bool isError(ID id);
+ const char *message(ID id);
- virtual void print(ID id,
- const SourceLocation &loc,
- const std::string &text) = 0;
+ virtual void print(ID id, const SourceLocation &loc, const std::string &text) = 0;
};
} // namespace pp
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.cpp b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.cpp
index ef35c6ed50..049dae9071 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.cpp
+++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.cpp
@@ -4,7 +4,7 @@
// found in the LICENSE file.
//
-#include "DirectiveHandlerBase.h"
+#include "compiler/preprocessor/DirectiveHandlerBase.h"
namespace pp
{
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h
index cf67895764..6c81d015f5 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h
@@ -23,8 +23,7 @@ class DirectiveHandler
public:
virtual ~DirectiveHandler();
- virtual void handleError(const SourceLocation &loc,
- const std::string &msg) = 0;
+ virtual void handleError(const SourceLocation &loc, const std::string &msg) = 0;
// Handle pragma of form: #pragma name[(value)]
virtual void handlePragma(const SourceLocation &loc,
@@ -36,8 +35,7 @@ class DirectiveHandler
const std::string &name,
const std::string &behavior) = 0;
- virtual void handleVersion(const SourceLocation &loc,
- int version) = 0;
+ virtual void handleVersion(const SourceLocation &loc, int version) = 0;
};
} // namespace pp
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp
index 2faa331378..f6c5763990 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp
+++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp
@@ -4,21 +4,22 @@
// found in the LICENSE file.
//
-#include "DirectiveParser.h"
+#include "compiler/preprocessor/DirectiveParser.h"
#include <algorithm>
-#include <cassert>
#include <cstdlib>
#include <sstream>
-#include "DiagnosticsBase.h"
-#include "DirectiveHandlerBase.h"
-#include "ExpressionParser.h"
-#include "MacroExpander.h"
-#include "Token.h"
-#include "Tokenizer.h"
+#include "common/debug.h"
+#include "compiler/preprocessor/DiagnosticsBase.h"
+#include "compiler/preprocessor/DirectiveHandlerBase.h"
+#include "compiler/preprocessor/ExpressionParser.h"
+#include "compiler/preprocessor/MacroExpander.h"
+#include "compiler/preprocessor/Token.h"
+#include "compiler/preprocessor/Tokenizer.h"
-namespace {
+namespace
+{
enum DirectiveType
{
DIRECTIVE_NONE,
@@ -39,19 +40,19 @@ enum DirectiveType
DirectiveType getDirective(const pp::Token *token)
{
- const char kDirectiveDefine[] = "define";
- const char kDirectiveUndef[] = "undef";
- const char kDirectiveIf[] = "if";
- const char kDirectiveIfdef[] = "ifdef";
- const char kDirectiveIfndef[] = "ifndef";
- const char kDirectiveElse[] = "else";
- const char kDirectiveElif[] = "elif";
- const char kDirectiveEndif[] = "endif";
- const char kDirectiveError[] = "error";
- const char kDirectivePragma[] = "pragma";
+ const char kDirectiveDefine[] = "define";
+ const char kDirectiveUndef[] = "undef";
+ const char kDirectiveIf[] = "if";
+ const char kDirectiveIfdef[] = "ifdef";
+ const char kDirectiveIfndef[] = "ifndef";
+ const char kDirectiveElse[] = "else";
+ const char kDirectiveElif[] = "elif";
+ const char kDirectiveEndif[] = "endif";
+ const char kDirectiveError[] = "error";
+ const char kDirectivePragma[] = "pragma";
const char kDirectiveExtension[] = "extension";
- const char kDirectiveVersion[] = "version";
- const char kDirectiveLine[] = "line";
+ const char kDirectiveVersion[] = "version";
+ const char kDirectiveLine[] = "line";
if (token->type != pp::Token::IDENTIFIER)
return DIRECTIVE_NONE;
@@ -90,15 +91,15 @@ bool isConditionalDirective(DirectiveType directive)
{
switch (directive)
{
- case DIRECTIVE_IF:
- case DIRECTIVE_IFDEF:
- case DIRECTIVE_IFNDEF:
- case DIRECTIVE_ELSE:
- case DIRECTIVE_ELIF:
- case DIRECTIVE_ENDIF:
- return true;
- default:
- return false;
+ case DIRECTIVE_IF:
+ case DIRECTIVE_IFDEF:
+ case DIRECTIVE_IFNDEF:
+ case DIRECTIVE_ELSE:
+ case DIRECTIVE_ELIF:
+ case DIRECTIVE_ENDIF:
+ return true;
+ default:
+ return false;
}
}
@@ -110,7 +111,7 @@ bool isEOD(const pp::Token *token)
void skipUntilEOD(pp::Lexer *lexer, pp::Token *token)
{
- while(!isEOD(token))
+ while (!isEOD(token))
{
lexer->lex(token);
}
@@ -118,8 +119,8 @@ void skipUntilEOD(pp::Lexer *lexer, pp::Token *token)
bool isMacroNameReserved(const std::string &name)
{
- // Names prefixed with "GL_" are reserved.
- return (name.substr(0, 3) == "GL_");
+ // Names prefixed with "GL_" and the name "defined" are reserved.
+ return name == "defined" || (name.substr(0, 3) == "GL_");
}
bool hasDoubleUnderscores(const std::string &name)
@@ -127,11 +128,10 @@ bool hasDoubleUnderscores(const std::string &name)
return (name.find("__") != std::string::npos);
}
-bool isMacroPredefined(const std::string &name,
- const pp::MacroSet &macroSet)
+bool isMacroPredefined(const std::string &name, const pp::MacroSet &macroSet)
{
pp::MacroSet::const_iterator iter = macroSet.find(name);
- return iter != macroSet.end() ? iter->second.predefined : false;
+ return iter != macroSet.end() ? iter->second->predefined : false;
}
} // namespace anonymous
@@ -139,17 +139,83 @@ bool isMacroPredefined(const std::string &name,
namespace pp
{
+class DefinedParser : public Lexer
+{
+ public:
+ DefinedParser(Lexer *lexer, const MacroSet *macroSet, Diagnostics *diagnostics)
+ : mLexer(lexer), mMacroSet(macroSet), mDiagnostics(diagnostics)
+ {
+ }
+
+ protected:
+ void lex(Token *token) override
+ {
+ const char kDefined[] = "defined";
+
+ mLexer->lex(token);
+ if (token->type != Token::IDENTIFIER)
+ return;
+ if (token->text != kDefined)
+ return;
+
+ bool paren = false;
+ mLexer->lex(token);
+ if (token->type == '(')
+ {
+ paren = true;
+ mLexer->lex(token);
+ }
+
+ if (token->type != Token::IDENTIFIER)
+ {
+ mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text);
+ skipUntilEOD(mLexer, token);
+ return;
+ }
+ MacroSet::const_iterator iter = mMacroSet->find(token->text);
+ std::string expression = iter != mMacroSet->end() ? "1" : "0";
+
+ if (paren)
+ {
+ mLexer->lex(token);
+ if (token->type != ')')
+ {
+ mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location,
+ token->text);
+ skipUntilEOD(mLexer, token);
+ return;
+ }
+ }
+
+ // We have a valid defined operator.
+ // Convert the current token into a CONST_INT token.
+ token->type = Token::CONST_INT;
+ token->text = expression;
+ }
+
+ private:
+ Lexer *mLexer;
+ const MacroSet *mMacroSet;
+ Diagnostics *mDiagnostics;
+};
+
DirectiveParser::DirectiveParser(Tokenizer *tokenizer,
MacroSet *macroSet,
Diagnostics *diagnostics,
- DirectiveHandler *directiveHandler)
+ DirectiveHandler *directiveHandler,
+ int maxMacroExpansionDepth)
: mPastFirstStatement(false),
mSeenNonPreprocessorToken(false),
mTokenizer(tokenizer),
mMacroSet(macroSet),
mDiagnostics(diagnostics),
mDirectiveHandler(directiveHandler),
- mShaderVersion(100)
+ mShaderVersion(100),
+ mMaxMacroExpansionDepth(maxMacroExpansionDepth)
+{
+}
+
+DirectiveParser::~DirectiveParser()
{
}
@@ -174,21 +240,20 @@ void DirectiveParser::lex(Token *token)
if (!mConditionalStack.empty())
{
const ConditionalBlock &block = mConditionalStack.back();
- mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNTERMINATED,
- block.location, block.type);
+ mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNTERMINATED, block.location,
+ block.type);
}
break;
}
- }
- while (skipping() || (token->type == '\n'));
+ } while (skipping() || (token->type == '\n'));
mPastFirstStatement = true;
}
void DirectiveParser::parseDirective(Token *token)
{
- assert(token->type == Token::PP_HASH);
+ ASSERT(token->type == Token::PP_HASH);
mTokenizer->lex(token);
if (isEOD(token))
@@ -207,86 +272,83 @@ void DirectiveParser::parseDirective(Token *token)
return;
}
- switch(directive)
+ switch (directive)
{
- case DIRECTIVE_NONE:
- mDiagnostics->report(Diagnostics::PP_DIRECTIVE_INVALID_NAME,
- token->location, token->text);
- skipUntilEOD(mTokenizer, token);
- break;
- case DIRECTIVE_DEFINE:
- parseDefine(token);
- break;
- case DIRECTIVE_UNDEF:
- parseUndef(token);
- break;
- case DIRECTIVE_IF:
- parseIf(token);
- break;
- case DIRECTIVE_IFDEF:
- parseIfdef(token);
- break;
- case DIRECTIVE_IFNDEF:
- parseIfndef(token);
- break;
- case DIRECTIVE_ELSE:
- parseElse(token);
- break;
- case DIRECTIVE_ELIF:
- parseElif(token);
- break;
- case DIRECTIVE_ENDIF:
- parseEndif(token);
- break;
- case DIRECTIVE_ERROR:
- parseError(token);
- break;
- case DIRECTIVE_PRAGMA:
- parsePragma(token);
- break;
- case DIRECTIVE_EXTENSION:
- parseExtension(token);
- break;
- case DIRECTIVE_VERSION:
- parseVersion(token);
- break;
- case DIRECTIVE_LINE:
- parseLine(token);
- break;
- default:
- assert(false);
- break;
+ case DIRECTIVE_NONE:
+ mDiagnostics->report(Diagnostics::PP_DIRECTIVE_INVALID_NAME, token->location,
+ token->text);
+ skipUntilEOD(mTokenizer, token);
+ break;
+ case DIRECTIVE_DEFINE:
+ parseDefine(token);
+ break;
+ case DIRECTIVE_UNDEF:
+ parseUndef(token);
+ break;
+ case DIRECTIVE_IF:
+ parseIf(token);
+ break;
+ case DIRECTIVE_IFDEF:
+ parseIfdef(token);
+ break;
+ case DIRECTIVE_IFNDEF:
+ parseIfndef(token);
+ break;
+ case DIRECTIVE_ELSE:
+ parseElse(token);
+ break;
+ case DIRECTIVE_ELIF:
+ parseElif(token);
+ break;
+ case DIRECTIVE_ENDIF:
+ parseEndif(token);
+ break;
+ case DIRECTIVE_ERROR:
+ parseError(token);
+ break;
+ case DIRECTIVE_PRAGMA:
+ parsePragma(token);
+ break;
+ case DIRECTIVE_EXTENSION:
+ parseExtension(token);
+ break;
+ case DIRECTIVE_VERSION:
+ parseVersion(token);
+ break;
+ case DIRECTIVE_LINE:
+ parseLine(token);
+ break;
+ default:
+ UNREACHABLE();
+ break;
}
skipUntilEOD(mTokenizer, token);
if (token->type == Token::LAST)
{
- mDiagnostics->report(Diagnostics::PP_EOF_IN_DIRECTIVE,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_EOF_IN_DIRECTIVE, token->location, token->text);
}
}
void DirectiveParser::parseDefine(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_DEFINE);
+ ASSERT(getDirective(token) == DIRECTIVE_DEFINE);
mTokenizer->lex(token);
if (token->type != Token::IDENTIFIER)
{
- mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text);
return;
}
if (isMacroPredefined(token->text, *mMacroSet))
{
- mDiagnostics->report(Diagnostics::PP_MACRO_PREDEFINED_REDEFINED,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_MACRO_PREDEFINED_REDEFINED, token->location,
+ token->text);
return;
}
if (isMacroNameReserved(token->text))
{
- mDiagnostics->report(Diagnostics::PP_MACRO_NAME_RESERVED,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_MACRO_NAME_RESERVED, token->location, token->text);
return;
}
// Using double underscores is allowed, but may result in unintended
@@ -300,39 +362,37 @@ void DirectiveParser::parseDefine(Token *token)
token->text);
}
- Macro macro;
- macro.type = Macro::kTypeObj;
- macro.name = token->text;
+ std::shared_ptr<Macro> macro = std::make_shared<Macro>();
+ macro->type = Macro::kTypeObj;
+ macro->name = token->text;
mTokenizer->lex(token);
if (token->type == '(' && !token->hasLeadingSpace())
{
// Function-like macro. Collect arguments.
- macro.type = Macro::kTypeFunc;
+ macro->type = Macro::kTypeFunc;
do
{
mTokenizer->lex(token);
if (token->type != Token::IDENTIFIER)
break;
- if (std::find(macro.parameters.begin(), macro.parameters.end(), token->text) != macro.parameters.end())
+ if (std::find(macro->parameters.begin(), macro->parameters.end(), token->text) !=
+ macro->parameters.end())
{
mDiagnostics->report(Diagnostics::PP_MACRO_DUPLICATE_PARAMETER_NAMES,
token->location, token->text);
return;
}
- macro.parameters.push_back(token->text);
+ macro->parameters.push_back(token->text);
mTokenizer->lex(token); // Get ','.
- }
- while (token->type == ',');
+ } while (token->type == ',');
if (token->type != ')')
{
- mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
- token->location,
- token->text);
+ mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text);
return;
}
mTokenizer->lex(token); // Get ')'.
@@ -344,47 +404,51 @@ void DirectiveParser::parseDefine(Token *token)
// list. Resetting it also allows us to reuse Token::equals() to
// compare macros.
token->location = SourceLocation();
- macro.replacements.push_back(*token);
+ macro->replacements.push_back(*token);
mTokenizer->lex(token);
}
- if (!macro.replacements.empty())
+ if (!macro->replacements.empty())
{
// Whitespace preceding the replacement list is not considered part of
// the replacement list for either form of macro.
- macro.replacements.front().setHasLeadingSpace(false);
+ macro->replacements.front().setHasLeadingSpace(false);
}
// Check for macro redefinition.
- MacroSet::const_iterator iter = mMacroSet->find(macro.name);
- if (iter != mMacroSet->end() && !macro.equals(iter->second))
+ MacroSet::const_iterator iter = mMacroSet->find(macro->name);
+ if (iter != mMacroSet->end() && !macro->equals(*iter->second))
{
- mDiagnostics->report(Diagnostics::PP_MACRO_REDEFINED,
- token->location,
- macro.name);
+ mDiagnostics->report(Diagnostics::PP_MACRO_REDEFINED, token->location, macro->name);
return;
}
- mMacroSet->insert(std::make_pair(macro.name, macro));
+ mMacroSet->insert(std::make_pair(macro->name, macro));
}
void DirectiveParser::parseUndef(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_UNDEF);
+ ASSERT(getDirective(token) == DIRECTIVE_UNDEF);
mTokenizer->lex(token);
if (token->type != Token::IDENTIFIER)
{
- mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text);
return;
}
MacroSet::iterator iter = mMacroSet->find(token->text);
if (iter != mMacroSet->end())
{
- if (iter->second.predefined)
+ if (iter->second->predefined)
{
- mDiagnostics->report(Diagnostics::PP_MACRO_PREDEFINED_UNDEFINED,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_MACRO_PREDEFINED_UNDEFINED, token->location,
+ token->text);
+ return;
+ }
+ else if (iter->second->expansionCount > 0)
+ {
+ mDiagnostics->report(Diagnostics::PP_MACRO_UNDEFINED_WHILE_INVOKED, token->location,
+ token->text);
+ return;
}
else
{
@@ -395,38 +459,37 @@ void DirectiveParser::parseUndef(Token *token)
mTokenizer->lex(token);
if (!isEOD(token))
{
- mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text);
skipUntilEOD(mTokenizer, token);
}
}
void DirectiveParser::parseIf(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_IF);
+ ASSERT(getDirective(token) == DIRECTIVE_IF);
parseConditionalIf(token);
}
void DirectiveParser::parseIfdef(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_IFDEF);
+ ASSERT(getDirective(token) == DIRECTIVE_IFDEF);
parseConditionalIf(token);
}
void DirectiveParser::parseIfndef(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_IFNDEF);
+ ASSERT(getDirective(token) == DIRECTIVE_IFNDEF);
parseConditionalIf(token);
}
void DirectiveParser::parseElse(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_ELSE);
+ ASSERT(getDirective(token) == DIRECTIVE_ELSE);
if (mConditionalStack.empty())
{
- mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELSE_WITHOUT_IF,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELSE_WITHOUT_IF, token->location,
+ token->text);
skipUntilEOD(mTokenizer, token);
return;
}
@@ -440,34 +503,34 @@ void DirectiveParser::parseElse(Token *token)
}
if (block.foundElseGroup)
{
- mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELSE_AFTER_ELSE,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELSE_AFTER_ELSE, token->location,
+ token->text);
skipUntilEOD(mTokenizer, token);
return;
}
- block.foundElseGroup = true;
- block.skipGroup = block.foundValidGroup;
+ block.foundElseGroup = true;
+ block.skipGroup = block.foundValidGroup;
block.foundValidGroup = true;
// Check if there are extra tokens after #else.
mTokenizer->lex(token);
if (!isEOD(token))
{
- mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, token->location,
+ token->text);
skipUntilEOD(mTokenizer, token);
}
}
void DirectiveParser::parseElif(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_ELIF);
+ ASSERT(getDirective(token) == DIRECTIVE_ELIF);
if (mConditionalStack.empty())
{
- mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELIF_WITHOUT_IF,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELIF_WITHOUT_IF, token->location,
+ token->text);
skipUntilEOD(mTokenizer, token);
return;
}
@@ -481,8 +544,8 @@ void DirectiveParser::parseElif(Token *token)
}
if (block.foundElseGroup)
{
- mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELIF_AFTER_ELSE,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ELIF_AFTER_ELSE, token->location,
+ token->text);
skipUntilEOD(mTokenizer, token);
return;
}
@@ -495,19 +558,19 @@ void DirectiveParser::parseElif(Token *token)
return;
}
- int expression = parseExpressionIf(token);
- block.skipGroup = expression == 0;
+ int expression = parseExpressionIf(token);
+ block.skipGroup = expression == 0;
block.foundValidGroup = expression != 0;
}
void DirectiveParser::parseEndif(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_ENDIF);
+ ASSERT(getDirective(token) == DIRECTIVE_ENDIF);
if (mConditionalStack.empty())
{
- mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ENDIF_WITHOUT_IF,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_CONDITIONAL_ENDIF_WITHOUT_IF, token->location,
+ token->text);
skipUntilEOD(mTokenizer, token);
return;
}
@@ -518,15 +581,15 @@ void DirectiveParser::parseEndif(Token *token)
mTokenizer->lex(token);
if (!isEOD(token))
{
- mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, token->location,
+ token->text);
skipUntilEOD(mTokenizer, token);
}
}
void DirectiveParser::parseError(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_ERROR);
+ ASSERT(getDirective(token) == DIRECTIVE_ERROR);
std::ostringstream stream;
mTokenizer->lex(token);
@@ -541,7 +604,7 @@ void DirectiveParser::parseError(Token *token)
// Parses pragma of form: #pragma name[(value)].
void DirectiveParser::parsePragma(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_PRAGMA);
+ ASSERT(getDirective(token) == DIRECTIVE_PRAGMA);
enum State
{
@@ -563,25 +626,25 @@ void DirectiveParser::parsePragma(Token *token)
}
while ((token->type != '\n') && (token->type != Token::LAST))
{
- switch(state++)
+ switch (state++)
{
- case PRAGMA_NAME:
- name = token->text;
- valid = valid && (token->type == Token::IDENTIFIER);
- break;
- case LEFT_PAREN:
- valid = valid && (token->type == '(');
- break;
- case PRAGMA_VALUE:
- value = token->text;
- valid = valid && (token->type == Token::IDENTIFIER);
- break;
- case RIGHT_PAREN:
- valid = valid && (token->type == ')');
- break;
- default:
- valid = false;
- break;
+ case PRAGMA_NAME:
+ name = token->text;
+ valid = valid && (token->type == Token::IDENTIFIER);
+ break;
+ case LEFT_PAREN:
+ valid = valid && (token->type == '(');
+ break;
+ case PRAGMA_VALUE:
+ value = token->text;
+ valid = valid && (token->type == Token::IDENTIFIER);
+ break;
+ case RIGHT_PAREN:
+ valid = valid && (token->type == ')');
+ break;
+ default:
+ valid = false;
+ break;
}
mTokenizer->lex(token);
}
@@ -591,8 +654,7 @@ void DirectiveParser::parsePragma(Token *token)
(state == RIGHT_PAREN + 1)); // With value.
if (!valid)
{
- mDiagnostics->report(Diagnostics::PP_UNRECOGNIZED_PRAGMA,
- token->location, name);
+ mDiagnostics->report(Diagnostics::PP_UNRECOGNIZED_PRAGMA, token->location, name);
}
else if (state > PRAGMA_NAME) // Do not notify for empty pragma.
{
@@ -602,7 +664,7 @@ void DirectiveParser::parsePragma(Token *token)
void DirectiveParser::parseExtension(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_EXTENSION);
+ ASSERT(getDirective(token) == DIRECTIVE_EXTENSION);
enum State
{
@@ -620,47 +682,49 @@ void DirectiveParser::parseExtension(Token *token)
{
switch (state++)
{
- case EXT_NAME:
- if (valid && (token->type != Token::IDENTIFIER))
- {
- mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_NAME,
- token->location, token->text);
- valid = false;
- }
- if (valid) name = token->text;
- break;
- case COLON:
- if (valid && (token->type != ':'))
- {
- mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
- token->location, token->text);
- valid = false;
- }
- break;
- case EXT_BEHAVIOR:
- if (valid && (token->type != Token::IDENTIFIER))
- {
- mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_BEHAVIOR,
- token->location, token->text);
- valid = false;
- }
- if (valid) behavior = token->text;
- break;
- default:
- if (valid)
- {
- mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
- token->location, token->text);
- valid = false;
- }
- break;
+ case EXT_NAME:
+ if (valid && (token->type != Token::IDENTIFIER))
+ {
+ mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_NAME, token->location,
+ token->text);
+ valid = false;
+ }
+ if (valid)
+ name = token->text;
+ break;
+ case COLON:
+ if (valid && (token->type != ':'))
+ {
+ mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location,
+ token->text);
+ valid = false;
+ }
+ break;
+ case EXT_BEHAVIOR:
+ if (valid && (token->type != Token::IDENTIFIER))
+ {
+ mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_BEHAVIOR,
+ token->location, token->text);
+ valid = false;
+ }
+ if (valid)
+ behavior = token->text;
+ break;
+ default:
+ if (valid)
+ {
+ mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location,
+ token->text);
+ valid = false;
+ }
+ break;
}
mTokenizer->lex(token);
}
if (valid && (state != EXT_BEHAVIOR + 1))
{
- mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_DIRECTIVE,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_INVALID_EXTENSION_DIRECTIVE, token->location,
+ token->text);
valid = false;
}
if (valid && mSeenNonPreprocessorToken)
@@ -683,12 +747,12 @@ void DirectiveParser::parseExtension(Token *token)
void DirectiveParser::parseVersion(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_VERSION);
+ ASSERT(getDirective(token) == DIRECTIVE_VERSION);
if (mPastFirstStatement)
{
- mDiagnostics->report(Diagnostics::PP_VERSION_NOT_FIRST_STATEMENT,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_VERSION_NOT_FIRST_STATEMENT, token->location,
+ token->text);
skipUntilEOD(mTokenizer, token);
return;
}
@@ -700,47 +764,47 @@ void DirectiveParser::parseVersion(Token *token)
VERSION_ENDLINE
};
- bool valid = true;
+ bool valid = true;
int version = 0;
- int state = VERSION_NUMBER;
+ int state = VERSION_NUMBER;
mTokenizer->lex(token);
while (valid && (token->type != '\n') && (token->type != Token::LAST))
{
switch (state)
{
- case VERSION_NUMBER:
- if (token->type != Token::CONST_INT)
- {
- mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_NUMBER,
- token->location, token->text);
- valid = false;
- }
- if (valid && !token->iValue(&version))
- {
- mDiagnostics->report(Diagnostics::PP_INTEGER_OVERFLOW,
- token->location, token->text);
- valid = false;
- }
- if (valid)
- {
- state = (version < 300) ? VERSION_ENDLINE : VERSION_PROFILE;
- }
- break;
- case VERSION_PROFILE:
- if (token->type != Token::IDENTIFIER || token->text != "es")
- {
- mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_DIRECTIVE,
- token->location, token->text);
+ case VERSION_NUMBER:
+ if (token->type != Token::CONST_INT)
+ {
+ mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_NUMBER, token->location,
+ token->text);
+ valid = false;
+ }
+ if (valid && !token->iValue(&version))
+ {
+ mDiagnostics->report(Diagnostics::PP_INTEGER_OVERFLOW, token->location,
+ token->text);
+ valid = false;
+ }
+ if (valid)
+ {
+ state = (version < 300) ? VERSION_ENDLINE : VERSION_PROFILE;
+ }
+ break;
+ case VERSION_PROFILE:
+ if (token->type != Token::IDENTIFIER || token->text != "es")
+ {
+ mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_DIRECTIVE, token->location,
+ token->text);
+ valid = false;
+ }
+ state = VERSION_ENDLINE;
+ break;
+ default:
+ mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location,
+ token->text);
valid = false;
- }
- state = VERSION_ENDLINE;
- break;
- default:
- mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
- token->location, token->text);
- valid = false;
- break;
+ break;
}
mTokenizer->lex(token);
@@ -748,15 +812,15 @@ void DirectiveParser::parseVersion(Token *token)
if (valid && (state != VERSION_ENDLINE))
{
- mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_DIRECTIVE,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_DIRECTIVE, token->location,
+ token->text);
valid = false;
}
if (valid && version >= 300 && token->location.line > 1)
{
- mDiagnostics->report(Diagnostics::PP_VERSION_NOT_FIRST_LINE_ESSL3,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_VERSION_NOT_FIRST_LINE_ESSL3, token->location,
+ token->text);
valid = false;
}
@@ -770,13 +834,13 @@ void DirectiveParser::parseVersion(Token *token)
void DirectiveParser::parseLine(Token *token)
{
- assert(getDirective(token) == DIRECTIVE_LINE);
+ ASSERT(getDirective(token) == DIRECTIVE_LINE);
- bool valid = true;
+ bool valid = true;
bool parsedFileNumber = false;
int line = 0, file = 0;
- MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, false);
+ MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, mMaxMacroExpansionDepth);
// Lex the first token after "#line" so we can check it for EOD.
macroExpander.lex(token);
@@ -814,8 +878,8 @@ void DirectiveParser::parseLine(Token *token)
{
if (valid)
{
- mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location,
+ token->text);
valid = false;
}
skipUntilEOD(mTokenizer, token);
@@ -835,14 +899,14 @@ bool DirectiveParser::skipping() const
if (mConditionalStack.empty())
return false;
- const ConditionalBlock& block = mConditionalStack.back();
+ const ConditionalBlock &block = mConditionalStack.back();
return block.skipBlock || block.skipGroup;
}
void DirectiveParser::parseConditionalIf(Token *token)
{
ConditionalBlock block;
- block.type = token->text;
+ block.type = token->text;
block.location = token->location;
if (skipping())
@@ -861,20 +925,20 @@ void DirectiveParser::parseConditionalIf(Token *token)
int expression = 0;
switch (directive)
{
- case DIRECTIVE_IF:
- expression = parseExpressionIf(token);
- break;
- case DIRECTIVE_IFDEF:
- expression = parseExpressionIfdef(token);
- break;
- case DIRECTIVE_IFNDEF:
- expression = parseExpressionIfdef(token) == 0 ? 1 : 0;
- break;
- default:
- assert(false);
- break;
+ case DIRECTIVE_IF:
+ expression = parseExpressionIf(token);
+ break;
+ case DIRECTIVE_IFDEF:
+ expression = parseExpressionIfdef(token);
+ break;
+ case DIRECTIVE_IFNDEF:
+ expression = parseExpressionIfdef(token) == 0 ? 1 : 0;
+ break;
+ default:
+ UNREACHABLE();
+ break;
}
- block.skipGroup = expression == 0;
+ block.skipGroup = expression == 0;
block.foundValidGroup = expression != 0;
}
mConditionalStack.push_back(block);
@@ -882,16 +946,16 @@ void DirectiveParser::parseConditionalIf(Token *token)
int DirectiveParser::parseExpressionIf(Token *token)
{
- assert((getDirective(token) == DIRECTIVE_IF) ||
- (getDirective(token) == DIRECTIVE_ELIF));
+ ASSERT((getDirective(token) == DIRECTIVE_IF) || (getDirective(token) == DIRECTIVE_ELIF));
- MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics, true);
+ DefinedParser definedParser(mTokenizer, mMacroSet, mDiagnostics);
+ MacroExpander macroExpander(&definedParser, mMacroSet, mDiagnostics, mMaxMacroExpansionDepth);
ExpressionParser expressionParser(&macroExpander, mDiagnostics);
int expression = 0;
ExpressionParser::ErrorSettings errorSettings;
errorSettings.integerLiteralsMustFit32BitSignedRange = false;
- errorSettings.unexpectedIdentifier = Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN;
+ errorSettings.unexpectedIdentifier = Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN;
bool valid = true;
expressionParser.parse(token, &expression, false, errorSettings, &valid);
@@ -899,8 +963,8 @@ int DirectiveParser::parseExpressionIf(Token *token)
// Check if there are tokens after #if expression.
if (!isEOD(token))
{
- mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, token->location,
+ token->text);
skipUntilEOD(mTokenizer, token);
}
@@ -909,27 +973,25 @@ int DirectiveParser::parseExpressionIf(Token *token)
int DirectiveParser::parseExpressionIfdef(Token *token)
{
- assert((getDirective(token) == DIRECTIVE_IFDEF) ||
- (getDirective(token) == DIRECTIVE_IFNDEF));
+ ASSERT((getDirective(token) == DIRECTIVE_IFDEF) || (getDirective(token) == DIRECTIVE_IFNDEF));
mTokenizer->lex(token);
if (token->type != Token::IDENTIFIER)
{
- mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location, token->text);
skipUntilEOD(mTokenizer, token);
return 0;
}
MacroSet::const_iterator iter = mMacroSet->find(token->text);
- int expression = iter != mMacroSet->end() ? 1 : 0;
+ int expression = iter != mMacroSet->end() ? 1 : 0;
// Check if there are tokens after #ifdef expression.
mTokenizer->lex(token);
if (!isEOD(token))
{
- mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN,
- token->location, token->text);
+ mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNEXPECTED_TOKEN, token->location,
+ token->text);
skipUntilEOD(mTokenizer, token);
}
return expression;
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h
index 2888e289ce..29c30a8239 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h
@@ -7,10 +7,9 @@
#ifndef COMPILER_PREPROCESSOR_DIRECTIVEPARSER_H_
#define COMPILER_PREPROCESSOR_DIRECTIVEPARSER_H_
-#include "Lexer.h"
-#include "Macro.h"
-#include "pp_utils.h"
-#include "SourceLocation.h"
+#include "compiler/preprocessor/Lexer.h"
+#include "compiler/preprocessor/Macro.h"
+#include "compiler/preprocessor/SourceLocation.h"
namespace pp
{
@@ -25,13 +24,13 @@ class DirectiveParser : public Lexer
DirectiveParser(Tokenizer *tokenizer,
MacroSet *macroSet,
Diagnostics *diagnostics,
- DirectiveHandler *directiveHandler);
+ DirectiveHandler *directiveHandler,
+ int maxMacroExpansionDepth);
+ ~DirectiveParser() override;
void lex(Token *token) override;
private:
- PP_DISALLOW_COPY_AND_ASSIGN(DirectiveParser);
-
void parseDirective(Token *token);
void parseDefine(Token *token);
void parseUndef(Token *token);
@@ -62,22 +61,21 @@ class DirectiveParser : public Lexer
bool foundElseGroup;
ConditionalBlock()
- : skipBlock(false),
- skipGroup(false),
- foundValidGroup(false),
- foundElseGroup(false)
+ : skipBlock(false), skipGroup(false), foundValidGroup(false), foundElseGroup(false)
{
}
};
bool mPastFirstStatement;
- bool mSeenNonPreprocessorToken; // Tracks if a non-preprocessor token has been seen yet. Some macros, such as
- // #extension must be declared before all shader code.
+ bool mSeenNonPreprocessorToken; // Tracks if a non-preprocessor token has been seen yet. Some
+ // macros, such as
+ // #extension must be declared before all shader code.
std::vector<ConditionalBlock> mConditionalStack;
Tokenizer *mTokenizer;
MacroSet *mMacroSet;
Diagnostics *mDiagnostics;
DirectiveHandler *mDirectiveHandler;
int mShaderVersion;
+ int mMaxMacroExpansionDepth;
};
} // namespace pp
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h
index 841c67b61c..0f2901b878 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h
@@ -7,8 +7,8 @@
#ifndef COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_
#define COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_
-#include "DiagnosticsBase.h"
-#include "pp_utils.h"
+#include "common/angleutils.h"
+#include "compiler/preprocessor/DiagnosticsBase.h"
namespace pp
{
@@ -16,7 +16,7 @@ namespace pp
class Lexer;
struct Token;
-class ExpressionParser
+class ExpressionParser : angle::NonCopyable
{
public:
struct ErrorSettings
@@ -34,8 +34,6 @@ class ExpressionParser
bool *valid);
private:
- PP_DISALLOW_COPY_AND_ASSIGN(ExpressionParser);
-
Lexer *mLexer;
Diagnostics *mDiagnostics;
};
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y
index 7b5d9e9cee..68d7cc3958 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y
+++ b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y
@@ -41,17 +41,15 @@ WHICH GENERATES THE GLSL ES preprocessor expression parser.
#include <cassert>
#include <sstream>
+#include <stdint.h>
#include "DiagnosticsBase.h"
#include "Lexer.h"
#include "Token.h"
+#include "common/mathutil.h"
-#if defined(_MSC_VER)
-typedef __int64 YYSTYPE;
-#else
-#include <stdint.h>
-typedef intmax_t YYSTYPE;
-#endif // _MSC_VER
+typedef int32_t YYSTYPE;
+typedef uint32_t UNSIGNED_TYPE;
#define YYENABLE_NLS 0
#define YYLTYPE_IS_TRIVIAL 1
@@ -196,16 +194,57 @@ expression
$$ = $1 < $3;
}
| expression TOK_OP_RIGHT expression {
- $$ = $1 >> $3;
+ if ($3 < 0 || $3 > 31)
+ {
+ if (!context->isIgnoringErrors())
+ {
+ std::ostringstream stream;
+ stream << $1 << " >> " << $3;
+ std::string text = stream.str();
+ context->diagnostics->report(pp::Diagnostics::PP_UNDEFINED_SHIFT,
+ context->token->location,
+ text.c_str());
+ *(context->valid) = false;
+ }
+ $$ = static_cast<YYSTYPE>(0);
+ }
+ else if ($1 < 0)
+ {
+ // Logical shift right.
+ $$ = static_cast<YYSTYPE>(static_cast<UNSIGNED_TYPE>($1) >> $3);
+ }
+ else
+ {
+ $$ = $1 >> $3;
+ }
}
| expression TOK_OP_LEFT expression {
- $$ = $1 << $3;
+ if ($3 < 0 || $3 > 31)
+ {
+ if (!context->isIgnoringErrors())
+ {
+ std::ostringstream stream;
+ stream << $1 << " << " << $3;
+ std::string text = stream.str();
+ context->diagnostics->report(pp::Diagnostics::PP_UNDEFINED_SHIFT,
+ context->token->location,
+ text.c_str());
+ *(context->valid) = false;
+ }
+ $$ = static_cast<YYSTYPE>(0);
+ }
+ else
+ {
+ // Logical shift left. Casting to unsigned is needed to ensure there's no signed integer
+ // overflow, which some tools treat as an error.
+ $$ = static_cast<YYSTYPE>(static_cast<UNSIGNED_TYPE>($1) << $3);
+ }
}
| expression '-' expression {
- $$ = $1 - $3;
+ $$ = gl::WrappingDiff<YYSTYPE>($1, $3);
}
| expression '+' expression {
- $$ = $1 + $3;
+ $$ = gl::WrappingSum<YYSTYPE>($1, $3);
}
| expression '%' expression {
if ($3 == 0)
@@ -222,6 +261,12 @@ expression
}
$$ = static_cast<YYSTYPE>(0);
}
+ else if (($1 == std::numeric_limits<YYSTYPE>::min()) && ($3 == -1))
+ {
+ // Check for the special case where the minimum representable number is
+ // divided by -1. If left alone this has undefined results.
+ $$ = 0;
+ }
else
{
$$ = $1 % $3;
@@ -242,13 +287,20 @@ expression
}
$$ = static_cast<YYSTYPE>(0);
}
+ else if (($1 == std::numeric_limits<YYSTYPE>::min()) && ($3 == -1))
+ {
+ // Check for the special case where the minimum representable number is
+ // divided by -1. If left alone this leads to integer overflow in C++, which
+ // has undefined results.
+ $$ = std::numeric_limits<YYSTYPE>::max();
+ }
else
{
$$ = $1 / $3;
}
}
| expression '*' expression {
- $$ = $1 * $3;
+ $$ = gl::WrappingMul($1, $3);
}
| '!' expression %prec TOK_UNARY {
$$ = ! $2;
@@ -257,7 +309,16 @@ expression
$$ = ~ $2;
}
| '-' expression %prec TOK_UNARY {
- $$ = - $2;
+ // Check for negation of minimum representable integer to prevent undefined signed int
+ // overflow.
+ if ($2 == std::numeric_limits<YYSTYPE>::min())
+ {
+ $$ = std::numeric_limits<YYSTYPE>::min();
+ }
+ else
+ {
+ $$ = -$2;
+ }
}
| '+' expression %prec TOK_UNARY {
$$ = + $2;
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Input.cpp b/src/3rdparty/angle/src/compiler/preprocessor/Input.cpp
index 5541d46f72..0f2327b823 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Input.cpp
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Input.cpp
@@ -4,12 +4,13 @@
// found in the LICENSE file.
//
-#include "Input.h"
+#include "compiler/preprocessor/Input.h"
#include <algorithm>
-#include <cassert>
#include <cstring>
+#include "common/debug.h"
+
namespace pp
{
@@ -17,9 +18,12 @@ Input::Input() : mCount(0), mString(0)
{
}
-Input::Input(size_t count, const char *const string[], const int length[]) :
- mCount(count),
- mString(string)
+Input::~Input()
+{
+}
+
+Input::Input(size_t count, const char *const string[], const int length[])
+ : mCount(count), mString(string)
{
mLength.reserve(mCount);
for (size_t i = 0; i < mCount; ++i)
@@ -32,7 +36,7 @@ Input::Input(size_t count, const char *const string[], const int length[]) :
const char *Input::skipChar()
{
// This function should only be called when there is a character to skip.
- assert(mReadLoc.cIndex < mLength[mReadLoc.sIndex]);
+ ASSERT(mReadLoc.cIndex < mLength[mReadLoc.sIndex]);
++mReadLoc.cIndex;
if (mReadLoc.cIndex == mLength[mReadLoc.sIndex])
{
@@ -61,6 +65,11 @@ size_t Input::read(char *buf, size_t maxSize, int *lineNo)
{
// Line continuation of backslash + newline.
skipChar();
+ // Fake an EOF if the line number would overflow.
+ if (*lineNo == INT_MAX)
+ {
+ return 0;
+ }
++(*lineNo);
}
else if (c != nullptr && (*c) == '\r')
@@ -71,6 +80,11 @@ size_t Input::read(char *buf, size_t maxSize, int *lineNo)
{
skipChar();
}
+ // Fake an EOF if the line number would overflow.
+ if (*lineNo == INT_MAX)
+ {
+ return 0;
+ }
++(*lineNo);
}
else
@@ -86,7 +100,7 @@ size_t Input::read(char *buf, size_t maxSize, int *lineNo)
while ((nRead < maxRead) && (mReadLoc.sIndex < mCount))
{
size_t size = mLength[mReadLoc.sIndex] - mReadLoc.cIndex;
- size = std::min(size, maxSize);
+ size = std::min(size, maxSize);
for (size_t i = 0; i < size; ++i)
{
// Stop if a possible line continuation is encountered.
@@ -94,7 +108,7 @@ size_t Input::read(char *buf, size_t maxSize, int *lineNo)
// and increments line number if necessary.
if (*(mString[mReadLoc.sIndex] + mReadLoc.cIndex + i) == '\\')
{
- size = i;
+ size = i;
maxRead = nRead + size; // Stop reading right before the backslash.
}
}
@@ -113,4 +127,3 @@ size_t Input::read(char *buf, size_t maxSize, int *lineNo)
}
} // namespace pp
-
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Input.h b/src/3rdparty/angle/src/compiler/preprocessor/Input.h
index a1de7ddd86..8c7c7ee19e 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Input.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Input.h
@@ -7,7 +7,7 @@
#ifndef COMPILER_PREPROCESSOR_INPUT_H_
#define COMPILER_PREPROCESSOR_INPUT_H_
-#include <stddef.h>
+#include <cstddef>
#include <vector>
namespace pp
@@ -18,20 +18,12 @@ class Input
{
public:
Input();
+ ~Input();
Input(size_t count, const char *const string[], const int length[]);
- size_t count() const
- {
- return mCount;
- }
- const char *string(size_t index) const
- {
- return mString[index];
- }
- size_t length(size_t index) const
- {
- return mLength[index];
- }
+ size_t count() const { return mCount; }
+ const char *string(size_t index) const { return mString[index]; }
+ size_t length(size_t index) const { return mLength[index]; }
size_t read(char *buf, size_t maxSize, int *lineNo);
@@ -40,11 +32,7 @@ class Input
size_t sIndex; // String index;
size_t cIndex; // Char index.
- Location()
- : sIndex(0),
- cIndex(0)
- {
- }
+ Location() : sIndex(0), cIndex(0) {}
};
const Location &readLoc() const { return mReadLoc; }
@@ -55,7 +43,7 @@ class Input
// Input.
size_t mCount;
- const char * const *mString;
+ const char *const *mString;
std::vector<size_t> mLength;
Location mReadLoc;
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Lexer.cpp b/src/3rdparty/angle/src/compiler/preprocessor/Lexer.cpp
index 7c663ee761..89cb3cf44e 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Lexer.cpp
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Lexer.cpp
@@ -4,7 +4,7 @@
// found in the LICENSE file.
//
-#include "Lexer.h"
+#include "compiler/preprocessor/Lexer.h"
namespace pp
{
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h b/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h
index 990dc5e21d..775bc0a202 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h
@@ -7,12 +7,14 @@
#ifndef COMPILER_PREPROCESSOR_LEXER_H_
#define COMPILER_PREPROCESSOR_LEXER_H_
+#include "common/angleutils.h"
+
namespace pp
{
struct Token;
-class Lexer
+class Lexer : angle::NonCopyable
{
public:
virtual ~Lexer();
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Macro.cpp b/src/3rdparty/angle/src/compiler/preprocessor/Macro.cpp
index 4c4d5fd2e2..52e2312fe6 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Macro.cpp
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Macro.cpp
@@ -4,40 +4,41 @@
// found in the LICENSE file.
//
-#include "Macro.h"
+#include "compiler/preprocessor/Macro.h"
-#include <sstream>
-
-#include "Token.h"
+#include "common/angleutils.h"
+#include "compiler/preprocessor/Token.h"
namespace pp
{
+Macro::Macro() : predefined(false), disabled(false), expansionCount(0), type(kTypeObj)
+{
+}
+
+Macro::~Macro()
+{
+}
+
bool Macro::equals(const Macro &other) const
{
- return (type == other.type) &&
- (name == other.name) &&
- (parameters == other.parameters) &&
+ return (type == other.type) && (name == other.name) && (parameters == other.parameters) &&
(replacements == other.replacements);
}
void PredefineMacro(MacroSet *macroSet, const char *name, int value)
{
- std::ostringstream stream;
- stream << value;
-
Token token;
token.type = Token::CONST_INT;
- token.text = stream.str();
+ token.text = ToString(value);
- Macro macro;
- macro.predefined = true;
- macro.type = Macro::kTypeObj;
- macro.name = name;
- macro.replacements.push_back(token);
+ std::shared_ptr<Macro> macro = std::make_shared<Macro>();
+ macro->predefined = true;
+ macro->type = Macro::kTypeObj;
+ macro->name = name;
+ macro->replacements.push_back(token);
(*macroSet)[name] = macro;
}
} // namespace pp
-
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Macro.h b/src/3rdparty/angle/src/compiler/preprocessor/Macro.h
index 31ee22c26a..c42e172ef9 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Macro.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Macro.h
@@ -8,6 +8,7 @@
#define COMPILER_PREPROCESSOR_MACRO_H_
#include <map>
+#include <memory>
#include <string>
#include <vector>
@@ -26,16 +27,13 @@ struct Macro
typedef std::vector<std::string> Parameters;
typedef std::vector<Token> Replacements;
- Macro()
- : predefined(false),
- disabled(false),
- type(kTypeObj)
- {
- }
+ Macro();
+ ~Macro();
bool equals(const Macro &other) const;
bool predefined;
mutable bool disabled;
+ mutable int expansionCount;
Type type;
std::string name;
@@ -43,7 +41,7 @@ struct Macro
Replacements replacements;
};
-typedef std::map<std::string, Macro> MacroSet;
+typedef std::map<std::string, std::shared_ptr<Macro>> MacroSet;
void PredefineMacro(MacroSet *macroSet, const char *name, int value);
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp
index e878ee345a..d88d3a6853 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp
+++ b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp
@@ -4,20 +4,25 @@
// found in the LICENSE file.
//
-#include "MacroExpander.h"
+#include "compiler/preprocessor/MacroExpander.h"
#include <algorithm>
-#include <sstream>
-#include "DiagnosticsBase.h"
-#include "Token.h"
+#include "common/debug.h"
+#include "compiler/preprocessor/DiagnosticsBase.h"
+#include "compiler/preprocessor/Token.h"
namespace pp
{
+namespace
+{
+
+const size_t kMaxContextTokens = 10000;
+
class TokenLexer : public Lexer
{
- public:
+ public:
typedef std::vector<Token> TokenVector;
TokenLexer(TokenVector *tokens)
@@ -39,26 +44,61 @@ class TokenLexer : public Lexer
}
}
- private:
- PP_DISALLOW_COPY_AND_ASSIGN(TokenLexer);
-
+ private:
TokenVector mTokens;
TokenVector::const_iterator mIter;
};
+} // anonymous namespace
+
+class MacroExpander::ScopedMacroReenabler final : angle::NonCopyable
+{
+ public:
+ ScopedMacroReenabler(MacroExpander *expander);
+ ~ScopedMacroReenabler();
+
+ private:
+ MacroExpander *mExpander;
+};
+
+MacroExpander::ScopedMacroReenabler::ScopedMacroReenabler(MacroExpander *expander)
+ : mExpander(expander)
+{
+ mExpander->mDeferReenablingMacros = true;
+}
+
+MacroExpander::ScopedMacroReenabler::~ScopedMacroReenabler()
+{
+ mExpander->mDeferReenablingMacros = false;
+ for (auto macro : mExpander->mMacrosToReenable)
+ {
+ // Copying the string here by using substr is a check for use-after-free. It detects
+ // use-after-free more reliably than just toggling the disabled flag.
+ ASSERT(macro->name.substr() != "");
+ macro->disabled = false;
+ }
+ mExpander->mMacrosToReenable.clear();
+}
+
MacroExpander::MacroExpander(Lexer *lexer,
MacroSet *macroSet,
Diagnostics *diagnostics,
- bool parseDefined)
- : mLexer(lexer), mMacroSet(macroSet), mDiagnostics(diagnostics), mParseDefined(parseDefined)
+ int allowedMacroExpansionDepth)
+ : mLexer(lexer),
+ mMacroSet(macroSet),
+ mDiagnostics(diagnostics),
+ mTotalTokensInContexts(0),
+ mAllowedMacroExpansionDepth(allowedMacroExpansionDepth),
+ mDeferReenablingMacros(false)
{
}
MacroExpander::~MacroExpander()
{
- for (std::size_t i = 0; i < mContextStack.size(); ++i)
+ ASSERT(mMacrosToReenable.empty());
+ for (MacroContext *context : mContextStack)
{
- delete mContextStack[i];
+ delete context;
}
}
@@ -66,54 +106,11 @@ void MacroExpander::lex(Token *token)
{
while (true)
{
- const char kDefined[] = "defined";
-
getToken(token);
if (token->type != Token::IDENTIFIER)
break;
- // Defined operator is parsed here since it may be generated by macro expansion.
- // Defined operator produced by macro expansion has undefined behavior according to C++
- // spec, which the GLSL spec references (see C++14 draft spec section 16.1.4), but this
- // behavior is needed for passing dEQP tests, which enforce stricter compatibility between
- // implementations.
- if (mParseDefined && token->text == kDefined)
- {
- bool paren = false;
- getToken(token);
- if (token->type == '(')
- {
- paren = true;
- getToken(token);
- }
- if (token->type != Token::IDENTIFIER)
- {
- mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location,
- token->text);
- break;
- }
- auto iter = mMacroSet->find(token->text);
- std::string expression = iter != mMacroSet->end() ? "1" : "0";
-
- if (paren)
- {
- getToken(token);
- if (token->type != ')')
- {
- mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, token->location,
- token->text);
- break;
- }
- }
-
- // We have a valid defined operator.
- // Convert the current token into a CONST_INT token.
- token->type = Token::CONST_INT;
- token->text = expression;
- break;
- }
-
if (token->expansionDisabled())
break;
@@ -121,17 +118,22 @@ void MacroExpander::lex(Token *token)
if (iter == mMacroSet->end())
break;
- const Macro& macro = iter->second;
- if (macro.disabled)
+ std::shared_ptr<Macro> macro = iter->second;
+ if (macro->disabled)
{
// If a particular token is not expanded, it is never expanded.
token->setExpansionDisabled(true);
break;
}
- if ((macro.type == Macro::kTypeFunc) && !isNextTokenLeftParen())
+
+ // Bump the expansion count before peeking if the next token is a '('
+ // otherwise there could be a #undef of the macro before the next token.
+ macro->expansionCount++;
+ if ((macro->type == Macro::kTypeFunc) && !isNextTokenLeftParen())
{
// If the token immediately after the macro name is not a '(',
// this macro should not be expanded.
+ macro->expansionCount--;
break;
}
@@ -160,6 +162,7 @@ void MacroExpander::getToken(Token *token)
}
else
{
+ ASSERT(mTotalTokensInContexts == 0);
mLexer->lex(token);
}
}
@@ -170,11 +173,11 @@ void MacroExpander::ungetToken(const Token &token)
{
MacroContext *context = mContextStack.back();
context->unget();
- assert(context->replacements[context->index] == token);
+ ASSERT(context->replacements[context->index] == token);
}
else
{
- assert(!mReserveToken.get());
+ ASSERT(!mReserveToken.get());
mReserveToken.reset(new Token(token));
}
}
@@ -190,37 +193,48 @@ bool MacroExpander::isNextTokenLeftParen()
return lparen;
}
-bool MacroExpander::pushMacro(const Macro &macro, const Token &identifier)
+bool MacroExpander::pushMacro(std::shared_ptr<Macro> macro, const Token &identifier)
{
- assert(!macro.disabled);
- assert(!identifier.expansionDisabled());
- assert(identifier.type == Token::IDENTIFIER);
- assert(identifier.text == macro.name);
+ ASSERT(!macro->disabled);
+ ASSERT(!identifier.expansionDisabled());
+ ASSERT(identifier.type == Token::IDENTIFIER);
+ ASSERT(identifier.text == macro->name);
std::vector<Token> replacements;
- if (!expandMacro(macro, identifier, &replacements))
+ if (!expandMacro(*macro, identifier, &replacements))
return false;
// Macro is disabled for expansion until it is popped off the stack.
- macro.disabled = true;
+ macro->disabled = true;
MacroContext *context = new MacroContext;
- context->macro = &macro;
+ context->macro = macro;
context->replacements.swap(replacements);
mContextStack.push_back(context);
+ mTotalTokensInContexts += context->replacements.size();
return true;
}
void MacroExpander::popMacro()
{
- assert(!mContextStack.empty());
+ ASSERT(!mContextStack.empty());
MacroContext *context = mContextStack.back();
mContextStack.pop_back();
- assert(context->empty());
- assert(context->macro->disabled);
- context->macro->disabled = false;
+ ASSERT(context->empty());
+ ASSERT(context->macro->disabled);
+ ASSERT(context->macro->expansionCount > 0);
+ if (mDeferReenablingMacros)
+ {
+ mMacrosToReenable.push_back(context->macro);
+ }
+ else
+ {
+ context->macro->disabled = false;
+ }
+ context->macro->expansionCount--;
+ mTotalTokensInContexts -= context->replacements.size();
delete context;
}
@@ -237,33 +251,28 @@ bool MacroExpander::expandMacro(const Macro &macro,
SourceLocation replacementLocation = identifier.location;
if (macro.type == Macro::kTypeObj)
{
- replacements->assign(macro.replacements.begin(),
- macro.replacements.end());
+ replacements->assign(macro.replacements.begin(), macro.replacements.end());
if (macro.predefined)
{
const char kLine[] = "__LINE__";
const char kFile[] = "__FILE__";
- assert(replacements->size() == 1);
- Token& repl = replacements->front();
+ ASSERT(replacements->size() == 1);
+ Token &repl = replacements->front();
if (macro.name == kLine)
{
- std::ostringstream stream;
- stream << identifier.location.line;
- repl.text = stream.str();
+ repl.text = ToString(identifier.location.line);
}
else if (macro.name == kFile)
{
- std::ostringstream stream;
- stream << identifier.location.file;
- repl.text = stream.str();
+ repl.text = ToString(identifier.location.file);
}
}
}
else
{
- assert(macro.type == Macro::kTypeFunc);
+ ASSERT(macro.type == Macro::kTypeFunc);
std::vector<MacroArg> args;
args.reserve(macro.parameters.size());
if (!collectMacroArgs(macro, identifier, &args, &replacementLocation))
@@ -274,7 +283,7 @@ bool MacroExpander::expandMacro(const Macro &macro,
for (std::size_t i = 0; i < replacements->size(); ++i)
{
- Token& repl = replacements->at(i);
+ Token &repl = replacements->at(i);
if (i == 0)
{
// The first token in the replacement list inherits the padding
@@ -294,45 +303,52 @@ bool MacroExpander::collectMacroArgs(const Macro &macro,
{
Token token;
getToken(&token);
- assert(token.type == '(');
+ ASSERT(token.type == '(');
args->push_back(MacroArg());
- for (int openParens = 1; openParens != 0; )
+
+ // Defer reenabling macros until args collection is finished to avoid the possibility of
+ // infinite recursion. Otherwise infinite recursion might happen when expanding the args after
+ // macros have been popped from the context stack when parsing the args.
+ ScopedMacroReenabler deferReenablingMacros(this);
+
+ int openParens = 1;
+ while (openParens != 0)
{
getToken(&token);
if (token.type == Token::LAST)
{
- mDiagnostics->report(Diagnostics::PP_MACRO_UNTERMINATED_INVOCATION,
- identifier.location, identifier.text);
+ mDiagnostics->report(Diagnostics::PP_MACRO_UNTERMINATED_INVOCATION, identifier.location,
+ identifier.text);
// Do not lose EOF token.
ungetToken(token);
return false;
}
- bool isArg = false; // True if token is part of the current argument.
+ bool isArg = false; // True if token is part of the current argument.
switch (token.type)
{
- case '(':
- ++openParens;
- isArg = true;
- break;
- case ')':
- --openParens;
- isArg = openParens != 0;
- *closingParenthesisLocation = token.location;
- break;
- case ',':
- // The individual arguments are separated by comma tokens, but
- // the comma tokens between matching inner parentheses do not
- // seperate arguments.
- if (openParens == 1)
- args->push_back(MacroArg());
- isArg = openParens != 1;
- break;
- default:
- isArg = true;
- break;
+ case '(':
+ ++openParens;
+ isArg = true;
+ break;
+ case ')':
+ --openParens;
+ isArg = openParens != 0;
+ *closingParenthesisLocation = token.location;
+ break;
+ case ',':
+ // The individual arguments are separated by comma tokens, but
+ // the comma tokens between matching inner parentheses do not
+ // seperate arguments.
+ if (openParens == 1)
+ args->push_back(MacroArg());
+ isArg = openParens != 1;
+ break;
+ default:
+ isArg = true;
+ break;
}
if (isArg)
{
@@ -353,9 +369,9 @@ bool MacroExpander::collectMacroArgs(const Macro &macro,
// Validate the number of arguments.
if (args->size() != params.size())
{
- Diagnostics::ID id = args->size() < macro.parameters.size() ?
- Diagnostics::PP_MACRO_TOO_FEW_ARGS :
- Diagnostics::PP_MACRO_TOO_MANY_ARGS;
+ Diagnostics::ID id = args->size() < macro.parameters.size()
+ ? Diagnostics::PP_MACRO_TOO_FEW_ARGS
+ : Diagnostics::PP_MACRO_TOO_MANY_ARGS;
mDiagnostics->report(id, identifier.location, identifier.text);
return false;
}
@@ -363,11 +379,17 @@ bool MacroExpander::collectMacroArgs(const Macro &macro,
// Pre-expand each argument before substitution.
// This step expands each argument individually before they are
// inserted into the macro body.
- for (std::size_t i = 0; i < args->size(); ++i)
+ size_t numTokens = 0;
+ for (auto &arg : *args)
{
- MacroArg &arg = args->at(i);
TokenLexer lexer(&arg);
- MacroExpander expander(&lexer, mMacroSet, mDiagnostics, mParseDefined);
+ if (mAllowedMacroExpansionDepth < 1)
+ {
+ mDiagnostics->report(Diagnostics::PP_MACRO_INVOCATION_CHAIN_TOO_DEEP, token.location,
+ token.text);
+ return false;
+ }
+ MacroExpander expander(&lexer, mMacroSet, mDiagnostics, mAllowedMacroExpansionDepth - 1);
arg.clear();
expander.lex(&token);
@@ -375,6 +397,12 @@ bool MacroExpander::collectMacroArgs(const Macro &macro,
{
arg.push_back(token);
expander.lex(&token);
+ numTokens++;
+ if (numTokens + mTotalTokensInContexts > kMaxContextTokens)
+ {
+ mDiagnostics->report(Diagnostics::PP_OUT_OF_MEMORY, token.location, token.text);
+ return false;
+ }
}
}
return true;
@@ -386,6 +414,14 @@ void MacroExpander::replaceMacroParams(const Macro &macro,
{
for (std::size_t i = 0; i < macro.replacements.size(); ++i)
{
+ if (!replacements->empty() &&
+ replacements->size() + mTotalTokensInContexts > kMaxContextTokens)
+ {
+ const Token &token = replacements->back();
+ mDiagnostics->report(Diagnostics::PP_OUT_OF_MEMORY, token.location, token.text);
+ return;
+ }
+
const Token &repl = macro.replacements[i];
if (repl.type != Token::IDENTIFIER)
{
@@ -396,15 +432,15 @@ void MacroExpander::replaceMacroParams(const Macro &macro,
// TODO(alokp): Optimize this.
// There is no need to search for macro params every time.
// The param index can be cached with the replacement token.
- Macro::Parameters::const_iterator iter = std::find(
- macro.parameters.begin(), macro.parameters.end(), repl.text);
+ Macro::Parameters::const_iterator iter =
+ std::find(macro.parameters.begin(), macro.parameters.end(), repl.text);
if (iter == macro.parameters.end())
{
replacements->push_back(repl);
continue;
}
- std::size_t iArg = std::distance(macro.parameters.begin(), iter);
+ std::size_t iArg = std::distance(macro.parameters.begin(), iter);
const MacroArg &arg = args[iArg];
if (arg.empty())
{
@@ -418,5 +454,28 @@ void MacroExpander::replaceMacroParams(const Macro &macro,
}
}
-} // namespace pp
+MacroExpander::MacroContext::MacroContext() : macro(0), index(0)
+{
+}
+MacroExpander::MacroContext::~MacroContext()
+{
+}
+
+bool MacroExpander::MacroContext::empty() const
+{
+ return index == replacements.size();
+}
+
+const Token &MacroExpander::MacroContext::get()
+{
+ return replacements[index++];
+}
+
+void MacroExpander::MacroContext::unget()
+{
+ ASSERT(index > 0);
+ --index;
+}
+
+} // namespace pp
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h
index dc870f626f..fae7676fb0 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h
@@ -7,13 +7,11 @@
#ifndef COMPILER_PREPROCESSOR_MACROEXPANDER_H_
#define COMPILER_PREPROCESSOR_MACROEXPANDER_H_
-#include <cassert>
#include <memory>
#include <vector>
-#include "Lexer.h"
-#include "Macro.h"
-#include "pp_utils.h"
+#include "compiler/preprocessor/Lexer.h"
+#include "compiler/preprocessor/Macro.h"
namespace pp
{
@@ -24,24 +22,23 @@ struct SourceLocation;
class MacroExpander : public Lexer
{
public:
- MacroExpander(Lexer *lexer, MacroSet *macroSet, Diagnostics *diagnostics, bool parseDefined);
+ MacroExpander(Lexer *lexer,
+ MacroSet *macroSet,
+ Diagnostics *diagnostics,
+ int allowedMacroExpansionDepth);
~MacroExpander() override;
void lex(Token *token) override;
private:
- PP_DISALLOW_COPY_AND_ASSIGN(MacroExpander);
-
void getToken(Token *token);
void ungetToken(const Token &token);
bool isNextTokenLeftParen();
- bool pushMacro(const Macro &macro, const Token &identifier);
+ bool pushMacro(std::shared_ptr<Macro> macro, const Token &identifier);
void popMacro();
- bool expandMacro(const Macro &macro,
- const Token &identifier,
- std::vector<Token> *replacements);
+ bool expandMacro(const Macro &macro, const Token &identifier, std::vector<Token> *replacements);
typedef std::vector<Token> MacroArg;
bool collectMacroArgs(const Macro &macro,
@@ -54,37 +51,31 @@ class MacroExpander : public Lexer
struct MacroContext
{
- const Macro *macro;
+ MacroContext();
+ ~MacroContext();
+ bool empty() const;
+ const Token &get();
+ void unget();
+
+ std::shared_ptr<Macro> macro;
std::size_t index;
std::vector<Token> replacements;
-
- MacroContext()
- : macro(0),
- index(0)
- {
- }
- bool empty() const
- {
- return index == replacements.size();
- }
- const Token &get()
- {
- return replacements[index++];
- }
- void unget()
- {
- assert(index > 0);
- --index;
- }
};
Lexer *mLexer;
MacroSet *mMacroSet;
Diagnostics *mDiagnostics;
- bool mParseDefined;
std::unique_ptr<Token> mReserveToken;
std::vector<MacroContext *> mContextStack;
+ size_t mTotalTokensInContexts;
+
+ int mAllowedMacroExpansionDepth;
+
+ bool mDeferReenablingMacros;
+ std::vector<std::shared_ptr<Macro>> mMacrosToReenable;
+
+ class ScopedMacroReenabler;
};
} // namespace pp
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp
index aeb9c46f9d..349c7b06c7 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp
@@ -4,16 +4,15 @@
// found in the LICENSE file.
//
-#include "Preprocessor.h"
+#include "compiler/preprocessor/Preprocessor.h"
-#include <cassert>
-
-#include "DiagnosticsBase.h"
-#include "DirectiveParser.h"
-#include "Macro.h"
-#include "MacroExpander.h"
-#include "Token.h"
-#include "Tokenizer.h"
+#include "common/debug.h"
+#include "compiler/preprocessor/DiagnosticsBase.h"
+#include "compiler/preprocessor/DirectiveParser.h"
+#include "compiler/preprocessor/Macro.h"
+#include "compiler/preprocessor/MacroExpander.h"
+#include "compiler/preprocessor/Token.h"
+#include "compiler/preprocessor/Tokenizer.h"
namespace pp
{
@@ -26,19 +25,26 @@ struct PreprocessorImpl
DirectiveParser directiveParser;
MacroExpander macroExpander;
- PreprocessorImpl(Diagnostics *diag, DirectiveHandler *directiveHandler)
+ PreprocessorImpl(Diagnostics *diag,
+ DirectiveHandler *directiveHandler,
+ const PreprocessorSettings &settings)
: diagnostics(diag),
tokenizer(diag),
- directiveParser(&tokenizer, &macroSet, diag, directiveHandler),
- macroExpander(&directiveParser, &macroSet, diag, false)
+ directiveParser(&tokenizer,
+ &macroSet,
+ diag,
+ directiveHandler,
+ settings.maxMacroExpansionDepth),
+ macroExpander(&directiveParser, &macroSet, diag, settings.maxMacroExpansionDepth)
{
}
};
Preprocessor::Preprocessor(Diagnostics *diagnostics,
- DirectiveHandler *directiveHandler)
+ DirectiveHandler *directiveHandler,
+ const PreprocessorSettings &settings)
{
- mImpl = new PreprocessorImpl(diagnostics, directiveHandler);
+ mImpl = new PreprocessorImpl(diagnostics, directiveHandler, settings);
}
Preprocessor::~Preprocessor()
@@ -46,9 +52,7 @@ Preprocessor::~Preprocessor()
delete mImpl;
}
-bool Preprocessor::init(size_t count,
- const char * const string[],
- const int length[])
+bool Preprocessor::init(size_t count, const char *const string[], const int length[])
{
static const int kDefaultGLSLVersion = 100;
@@ -74,23 +78,23 @@ void Preprocessor::lex(Token *token)
mImpl->macroExpander.lex(token);
switch (token->type)
{
- // We should not be returning internal preprocessing tokens.
- // Convert preprocessing tokens to compiler tokens or report
- // diagnostics.
- case Token::PP_HASH:
- assert(false);
- break;
- case Token::PP_NUMBER:
- mImpl->diagnostics->report(Diagnostics::PP_INVALID_NUMBER,
- token->location, token->text);
- break;
- case Token::PP_OTHER:
- mImpl->diagnostics->report(Diagnostics::PP_INVALID_CHARACTER,
- token->location, token->text);
- break;
- default:
- validToken = true;
- break;
+ // We should not be returning internal preprocessing tokens.
+ // Convert preprocessing tokens to compiler tokens or report
+ // diagnostics.
+ case Token::PP_HASH:
+ UNREACHABLE();
+ break;
+ case Token::PP_NUMBER:
+ mImpl->diagnostics->report(Diagnostics::PP_INVALID_NUMBER, token->location,
+ token->text);
+ break;
+ case Token::PP_OTHER:
+ mImpl->diagnostics->report(Diagnostics::PP_INVALID_CHARACTER, token->location,
+ token->text);
+ break;
+ default:
+ validToken = true;
+ break;
}
}
}
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h
index fe25daa123..2fe504f7f9 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h
@@ -7,9 +7,9 @@
#ifndef COMPILER_PREPROCESSOR_PREPROCESSOR_H_
#define COMPILER_PREPROCESSOR_PREPROCESSOR_H_
-#include <stddef.h>
+#include <cstddef>
-#include "pp_utils.h"
+#include "common/angleutils.h"
namespace pp
{
@@ -19,10 +19,18 @@ class DirectiveHandler;
struct PreprocessorImpl;
struct Token;
-class Preprocessor
+struct PreprocessorSettings : private angle::NonCopyable
+{
+ PreprocessorSettings() : maxMacroExpansionDepth(1000) {}
+ int maxMacroExpansionDepth;
+};
+
+class Preprocessor : angle::NonCopyable
{
public:
- Preprocessor(Diagnostics *diagnostics, DirectiveHandler *directiveHandler);
+ Preprocessor(Diagnostics *diagnostics,
+ DirectiveHandler *directiveHandler,
+ const PreprocessorSettings &settings);
~Preprocessor();
// count: specifies the number of elements in the string and length arrays.
@@ -34,7 +42,7 @@ class Preprocessor
// Each element in the length array may contain the length of the
// corresponding string or a value less than 0 to indicate that the string
// is null terminated.
- bool init(size_t count, const char * const string[], const int length[]);
+ bool init(size_t count, const char *const string[], const int length[]);
// Adds a pre-defined macro.
void predefineMacro(const char *name, int value);
@@ -44,8 +52,6 @@ class Preprocessor
void setMaxTokenSize(size_t maxTokenSize);
private:
- PP_DISALLOW_COPY_AND_ASSIGN(Preprocessor);
-
PreprocessorImpl *mImpl;
};
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h b/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h
index af8a8d5d19..51908a3b4b 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h
@@ -12,16 +12,8 @@ namespace pp
struct SourceLocation
{
- SourceLocation()
- : file(0),
- line(0)
- {
- }
- SourceLocation(int f, int l)
- : file(f),
- line(l)
- {
- }
+ SourceLocation() : file(0), line(0) {}
+ SourceLocation(int f, int l) : file(f), line(l) {}
bool equals(const SourceLocation &other) const
{
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Token.cpp b/src/3rdparty/angle/src/compiler/preprocessor/Token.cpp
index d102654747..ce0ce94f49 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Token.cpp
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Token.cpp
@@ -4,28 +4,25 @@
// found in the LICENSE file.
//
-#include "Token.h"
+#include "compiler/preprocessor/Token.h"
-#include <cassert>
-
-#include "numeric_lex.h"
+#include "common/debug.h"
+#include "compiler/preprocessor/numeric_lex.h"
namespace pp
{
void Token::reset()
{
- type = 0;
- flags = 0;
+ type = 0;
+ flags = 0;
location = SourceLocation();
text.clear();
}
bool Token::equals(const Token &other) const
{
- return (type == other.type) &&
- (flags == other.flags) &&
- (location == other.location) &&
+ return (type == other.type) && (flags == other.flags) && (location == other.location) &&
(text == other.text);
}
@@ -55,19 +52,19 @@ void Token::setExpansionDisabled(bool disable)
bool Token::iValue(int *value) const
{
- assert(type == CONST_INT);
+ ASSERT(type == CONST_INT);
return numeric_lex_int(text, value);
}
bool Token::uValue(unsigned int *value) const
{
- assert(type == CONST_INT);
+ ASSERT(type == CONST_INT);
return numeric_lex_int(text, value);
}
bool Token::fValue(float *value) const
{
- assert(type == CONST_FLOAT);
+ ASSERT(type == CONST_FLOAT);
return numeric_lex_float(text, value);
}
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Token.h b/src/3rdparty/angle/src/compiler/preprocessor/Token.h
index 347c47e307..26732ab64d 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Token.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Token.h
@@ -10,7 +10,7 @@
#include <ostream>
#include <string>
-#include "SourceLocation.h"
+#include "compiler/preprocessor/SourceLocation.h"
namespace pp
{
@@ -19,7 +19,9 @@ struct Token
{
enum Type
{
- LAST = 0, // EOF.
+ // Calling this ERROR causes a conflict with wingdi.h
+ GOT_ERROR = -1,
+ LAST = 0, // EOF.
IDENTIFIER = 258,
@@ -62,33 +64,20 @@ struct Token
EXPANSION_DISABLED = 1 << 2
};
- Token()
- : type(0),
- flags(0)
- {
- }
+ Token() : type(0), flags(0) {}
void reset();
bool equals(const Token &other) const;
// Returns true if this is the first token on line.
// It disregards any leading whitespace.
- bool atStartOfLine() const
- {
- return (flags & AT_START_OF_LINE) != 0;
- }
+ bool atStartOfLine() const { return (flags & AT_START_OF_LINE) != 0; }
void setAtStartOfLine(bool start);
- bool hasLeadingSpace() const
- {
- return (flags & HAS_LEADING_SPACE) != 0;
- }
+ bool hasLeadingSpace() const { return (flags & HAS_LEADING_SPACE) != 0; }
void setHasLeadingSpace(bool space);
- bool expansionDisabled() const
- {
- return (flags & EXPANSION_DISABLED) != 0;
- }
+ bool expansionDisabled() const { return (flags & EXPANSION_DISABLED) != 0; }
void setExpansionDisabled(bool disable);
// Converts text into numeric value for CONST_INT and CONST_FLOAT token.
@@ -113,7 +102,7 @@ inline bool operator!=(const Token &lhs, const Token &rhs)
return !lhs.equals(rhs);
}
-extern std::ostream &operator<<(std::ostream &out, const Token &token);
+std::ostream &operator<<(std::ostream &out, const Token &token);
} // namepsace pp
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h
index 49e64fa209..af4fd7ce7b 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h
@@ -7,9 +7,9 @@
#ifndef COMPILER_PREPROCESSOR_TOKENIZER_H_
#define COMPILER_PREPROCESSOR_TOKENIZER_H_
-#include "Input.h"
-#include "Lexer.h"
-#include "pp_utils.h"
+#include "common/angleutils.h"
+#include "compiler/preprocessor/Input.h"
+#include "compiler/preprocessor/Lexer.h"
namespace pp
{
@@ -34,9 +34,9 @@ class Tokenizer : public Lexer
};
Tokenizer(Diagnostics *diagnostics);
- ~Tokenizer();
+ ~Tokenizer() override;
- bool init(size_t count, const char * const string[], const int length[]);
+ bool init(size_t count, const char *const string[], const int length[]);
void setFileNumber(int file);
void setLineNumber(int line);
@@ -45,13 +45,12 @@ class Tokenizer : public Lexer
void lex(Token *token) override;
private:
- PP_DISALLOW_COPY_AND_ASSIGN(Tokenizer);
bool initScanner();
void destroyScanner();
- void *mHandle; // Scanner handle.
- Context mContext; // Scanner extra.
- size_t mMaxTokenSize; // Maximum token size
+ void *mHandle; // Scanner handle.
+ Context mContext; // Scanner extra.
+ size_t mMaxTokenSize; // Maximum token size
};
} // namespace pp
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l
index d316da88b1..096812d45f 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l
@@ -27,10 +27,10 @@ IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh.
#pragma warning(disable: 4005)
#endif
-#include "Tokenizer.h"
+#include "compiler/preprocessor/Tokenizer.h"
-#include "DiagnosticsBase.h"
-#include "Token.h"
+#include "compiler/preprocessor/DiagnosticsBase.h"
+#include "compiler/preprocessor/Token.h"
#if defined(__GNUC__)
// Triggered by the auto-generated yy_fatal_error function.
@@ -110,7 +110,14 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
"/*" { BEGIN(COMMENT); }
<COMMENT>[^*\r\n]+
<COMMENT>"*"
-<COMMENT>{NEWLINE} { ++yylineno; }
+<COMMENT>{NEWLINE} {
+ if (yylineno == INT_MAX)
+ {
+ *yylval = "Integer overflow on line number";
+ return pp::Token::GOT_ERROR;
+ }
+ ++yylineno;
+}
<COMMENT>"*/" {
yyextra->leadingSpace = true;
BEGIN(INITIAL);
@@ -237,13 +244,16 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
[ \t\v\f]+ { yyextra->leadingSpace = true; }
{NEWLINE} {
+ if (yylineno == INT_MAX)
+ {
+ *yylval = "Integer overflow on line number";
+ return pp::Token::GOT_ERROR;
+ }
++yylineno;
yylval->assign(1, '\n');
return '\n';
}
-\\{NEWLINE} { ++yylineno; }
-
. {
yylval->assign(1, yytext[0]);
return pp::Token::PP_OTHER;
@@ -267,11 +277,17 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
yylloc->line = yylineno;
yylval->clear();
- if (YY_START == COMMENT)
+ // Line number overflows fake EOFs to exit early, check for this case.
+ if (yylineno == INT_MAX) {
+ yyextra->diagnostics->report(pp::Diagnostics::PP_TOKENIZER_ERROR,
+ pp::SourceLocation(yyfileno, yylineno),
+ "Integer overflow on line number");
+ }
+ else if (YY_START == COMMENT)
{
yyextra->diagnostics->report(pp::Diagnostics::PP_EOF_IN_COMMENT,
pp::SourceLocation(yyfileno, yylineno),
- "");
+ "EOF while in a comment");
}
yyterminate();
}
@@ -280,9 +296,7 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
namespace pp {
-Tokenizer::Tokenizer(Diagnostics *diagnostics)
- : mHandle(0),
- mMaxTokenSize(256)
+Tokenizer::Tokenizer(Diagnostics *diagnostics) : mHandle(nullptr), mMaxTokenSize(256)
{
mContext.diagnostics = diagnostics;
}
@@ -320,7 +334,18 @@ void Tokenizer::setMaxTokenSize(size_t maxTokenSize)
void Tokenizer::lex(Token *token)
{
- token->type = yylex(&token->text, &token->location, mHandle);
+ int tokenType = yylex(&token->text, &token->location, mHandle);
+
+ if (tokenType == Token::GOT_ERROR)
+ {
+ mContext.diagnostics->report(Diagnostics::PP_TOKENIZER_ERROR, token->location, token->text);
+ token->type = Token::LAST;
+ }
+ else
+ {
+ token->type = tokenType;
+ }
+
if (token->text.size() > mMaxTokenSize)
{
mContext.diagnostics->report(Diagnostics::PP_TOKEN_TOO_LONG,
@@ -339,7 +364,7 @@ void Tokenizer::lex(Token *token)
bool Tokenizer::initScanner()
{
- if ((mHandle == NULL) && yylex_init_extra(&mContext, &mHandle))
+ if ((mHandle == nullptr) && yylex_init_extra(&mContext, &mHandle))
return false;
yyrestart(0, mHandle);
@@ -348,11 +373,11 @@ bool Tokenizer::initScanner()
void Tokenizer::destroyScanner()
{
- if (mHandle == NULL)
+ if (mHandle == nullptr)
return;
yylex_destroy(mHandle);
- mHandle = NULL;
+ mHandle = nullptr;
}
} // namespace pp
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h b/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h
index b32e42253f..6ea779ab8f 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h
@@ -9,15 +9,15 @@
#ifndef COMPILER_PREPROCESSOR_NUMERICLEX_H_
#define COMPILER_PREPROCESSOR_NUMERICLEX_H_
+#include <cmath>
#include <sstream>
-namespace pp {
+namespace pp
+{
inline std::ios::fmtflags numeric_base_int(const std::string &str)
{
- if ((str.size() >= 2) &&
- (str[0] == '0') &&
- (str[1] == 'x' || str[1] == 'X'))
+ if ((str.size() >= 2) && (str[0] == '0') && (str[1] == 'x' || str[1] == 'X'))
{
return std::ios::hex;
}
@@ -33,7 +33,7 @@ inline std::ios::fmtflags numeric_base_int(const std::string &str)
// of the correct form. They can only fail if the parsed value is too big,
// in which case false is returned.
-template<typename IntType>
+template <typename IntType>
bool numeric_lex_int(const std::string &str, IntType *value)
{
std::istringstream stream(str);
@@ -45,7 +45,7 @@ bool numeric_lex_int(const std::string &str, IntType *value)
return !stream.fail();
}
-template<typename FloatType>
+template <typename FloatType>
bool numeric_lex_float(const std::string &str, FloatType *value)
{
// On 64-bit Intel Android, istringstream is broken. Until this is fixed in
@@ -63,10 +63,10 @@ bool numeric_lex_float(const std::string &str, FloatType *value)
stream.imbue(std::locale::classic());
stream >> (*value);
- return !stream.fail();
+ return !stream.fail() && std::isfinite(*value);
#endif
}
-} // namespace pp.
+} // namespace pp.
-#endif // COMPILER_PREPROCESSOR_NUMERICLEX_H_
+#endif // COMPILER_PREPROCESSOR_NUMERICLEX_H_
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/pp_utils.h b/src/3rdparty/angle/src/compiler/preprocessor/pp_utils.h
deleted file mode 100644
index 9fba9385c5..0000000000
--- a/src/3rdparty/angle/src/compiler/preprocessor/pp_utils.h
+++ /dev/null
@@ -1,18 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// pp_utils.h: Common preprocessor utilities
-
-#ifndef COMPILER_PREPROCESSOR_PPUTILS_H_
-#define COMPILER_PREPROCESSOR_PPUTILS_H_
-
-// A macro to disallow the copy constructor and operator= functions
-// This must be used in the private: declarations for a class.
-#define PP_DISALLOW_COPY_AND_ASSIGN(TypeName) \
- TypeName(const TypeName &); \
- void operator=(const TypeName &)
-
-#endif // COMPILER_PREPROCESSOR_PPUTILS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.cpp
index 31bfae9966..b04fc28259 100644
--- a/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.cpp
@@ -9,8 +9,12 @@
#include "compiler/translator/ASTMetadataHLSL.h"
#include "compiler/translator/CallDAG.h"
+#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/SymbolTable.h"
+namespace sh
+{
+
namespace
{
@@ -29,9 +33,22 @@ class PullGradient : public TIntermTraverser
mDag(dag)
{
ASSERT(index < metadataList->size());
+
+ // ESSL 100 builtin gradient functions
+ mGradientBuiltinFunctions.insert("texture2D");
+ mGradientBuiltinFunctions.insert("texture2DProj");
+ mGradientBuiltinFunctions.insert("textureCube");
+
+ // ESSL 300 builtin gradient functions
+ mGradientBuiltinFunctions.insert("texture");
+ mGradientBuiltinFunctions.insert("textureProj");
+ mGradientBuiltinFunctions.insert("textureOffset");
+ mGradientBuiltinFunctions.insert("textureProjOffset");
+
+ // ESSL 310 doesn't add builtin gradient functions
}
- void traverse(TIntermAggregate *node)
+ void traverse(TIntermFunctionDefinition *node)
{
node->traverse(this);
ASSERT(mParents.empty());
@@ -59,7 +76,7 @@ class PullGradient : public TIntermTraverser
ASSERT(mParents.back() == node);
mParents.pop_back();
// A control flow's using a gradient means its parents are too.
- if (mMetadata->mControlFlowsContainingGradient.count(node)> 0 && !mParents.empty())
+ if (mMetadata->mControlFlowsContainingGradient.count(node) > 0 && !mParents.empty())
{
mMetadata->mControlFlowsContainingGradient.insert(mParents.back());
}
@@ -72,9 +89,9 @@ class PullGradient : public TIntermTraverser
return true;
}
- bool visitSelection(Visit visit, TIntermSelection *selection) override
+ bool visitIfElse(Visit visit, TIntermIfElse *ifElse) override
{
- visitControlFlow(visit, selection);
+ visitControlFlow(visit, ifElse);
return true;
}
@@ -84,11 +101,12 @@ class PullGradient : public TIntermTraverser
{
switch (node->getOp())
{
- case EOpDFdx:
- case EOpDFdy:
- onGradient();
- default:
- break;
+ case EOpDFdx:
+ case EOpDFdy:
+ case EOpFwidth:
+ onGradient();
+ default:
+ break;
}
}
@@ -99,28 +117,22 @@ class PullGradient : public TIntermTraverser
{
if (visit == PreVisit)
{
- if (node->getOp() == EOpFunctionCall)
+ if (node->getOp() == EOpCallFunctionInAST)
{
- if (node->isUserDefined())
- {
- size_t calleeIndex = mDag.findIndex(node);
- ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex);
- UNUSED_ASSERTION_VARIABLE(mIndex);
+ size_t calleeIndex = mDag.findIndex(node->getFunctionSymbolInfo());
+ ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex);
- if ((*mMetadataList)[calleeIndex].mUsesGradient) {
- onGradient();
- }
+ if ((*mMetadataList)[calleeIndex].mUsesGradient)
+ {
+ onGradient();
}
- else
+ }
+ else if (node->getOp() == EOpCallBuiltInFunction)
+ {
+ if (mGradientBuiltinFunctions.find(node->getFunctionSymbolInfo()->getName()) !=
+ mGradientBuiltinFunctions.end())
{
- TString name = TFunction::unmangleName(node->getName());
-
- if (name == "texture2D" ||
- name == "texture2DProj" ||
- name == "textureCube")
- {
- onGradient();
- }
+ onGradient();
}
}
}
@@ -136,7 +148,10 @@ class PullGradient : public TIntermTraverser
// Contains a stack of the control flow nodes that are parents of the node being
// currently visited. It is used to mark control flows using a gradient.
- std::vector<TIntermNode*> mParents;
+ std::vector<TIntermNode *> mParents;
+
+ // A list of builtin functions that use gradients
+ std::set<TString> mGradientBuiltinFunctions;
};
// Traverses the AST of a function definition to compute the the discontinuous loops
@@ -157,7 +172,7 @@ class PullComputeDiscontinuousAndGradientLoops : public TIntermTraverser
{
}
- void traverse(TIntermAggregate *node)
+ void traverse(TIntermFunctionDefinition *node)
{
node->traverse(this);
ASSERT(mLoopsAndSwitches.empty());
@@ -196,7 +211,7 @@ class PullComputeDiscontinuousAndGradientLoops : public TIntermTraverser
return true;
}
- bool visitSelection(Visit visit, TIntermSelection *node) override
+ bool visitIfElse(Visit visit, TIntermIfElse *node) override
{
if (visit == PreVisit)
{
@@ -222,7 +237,7 @@ class PullComputeDiscontinuousAndGradientLoops : public TIntermTraverser
{
switch (node->getFlowOp())
{
- case EOpBreak:
+ case EOpBreak:
{
ASSERT(!mLoopsAndSwitches.empty());
TIntermLoop *loop = mLoopsAndSwitches.back()->getAsLoopNode();
@@ -232,11 +247,11 @@ class PullComputeDiscontinuousAndGradientLoops : public TIntermTraverser
}
}
break;
- case EOpContinue:
+ case EOpContinue:
{
ASSERT(!mLoopsAndSwitches.empty());
TIntermLoop *loop = nullptr;
- size_t i = mLoopsAndSwitches.size();
+ size_t i = mLoopsAndSwitches.size();
while (loop == nullptr && i > 0)
{
--i;
@@ -246,23 +261,23 @@ class PullComputeDiscontinuousAndGradientLoops : public TIntermTraverser
mMetadata->mDiscontinuousLoops.insert(loop);
}
break;
- case EOpKill:
- case EOpReturn:
- // A return or discard jumps out of all the enclosing loops
- if (!mLoopsAndSwitches.empty())
- {
- for (TIntermNode *intermNode : mLoopsAndSwitches)
+ case EOpKill:
+ case EOpReturn:
+ // A return or discard jumps out of all the enclosing loops
+ if (!mLoopsAndSwitches.empty())
{
- TIntermLoop *loop = intermNode->getAsLoopNode();
- if (loop)
+ for (TIntermNode *intermNode : mLoopsAndSwitches)
{
- mMetadata->mDiscontinuousLoops.insert(loop);
+ TIntermLoop *loop = intermNode->getAsLoopNode();
+ if (loop)
+ {
+ mMetadata->mDiscontinuousLoops.insert(loop);
+ }
}
}
- }
- break;
- default:
- UNREACHABLE();
+ break;
+ default:
+ UNREACHABLE();
}
}
@@ -271,18 +286,14 @@ class PullComputeDiscontinuousAndGradientLoops : public TIntermTraverser
bool visitAggregate(Visit visit, TIntermAggregate *node) override
{
- if (visit == PreVisit && node->getOp() == EOpFunctionCall)
+ if (visit == PreVisit && node->getOp() == EOpCallFunctionInAST)
{
- if (node->isUserDefined())
- {
- size_t calleeIndex = mDag.findIndex(node);
- ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex);
- UNUSED_ASSERTION_VARIABLE(mIndex);
+ size_t calleeIndex = mDag.findIndex(node->getFunctionSymbolInfo());
+ ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex);
- if ((*mMetadataList)[calleeIndex].mHasGradientLoopInCallGraph)
- {
- onGradientLoop();
- }
+ if ((*mMetadataList)[calleeIndex].mHasGradientLoopInCallGraph)
+ {
+ onGradientLoop();
}
}
@@ -309,8 +320,8 @@ class PullComputeDiscontinuousAndGradientLoops : public TIntermTraverser
size_t mIndex;
const CallDAG &mDag;
- std::vector<TIntermNode*> mLoopsAndSwitches;
- std::vector<TIntermSelection*> mIfs;
+ std::vector<TIntermNode *> mLoopsAndSwitches;
+ std::vector<TIntermIfElse *> mIfs;
};
// Tags all the functions called in a discontinuous loop
@@ -327,7 +338,7 @@ class PushDiscontinuousLoops : public TIntermTraverser
{
}
- void traverse(TIntermAggregate *node)
+ void traverse(TIntermFunctionDefinition *node)
{
node->traverse(this);
ASSERT(mNestedDiscont == (mMetadata->mCalledInDiscontinuousLoop ? 1 : 0));
@@ -353,18 +364,17 @@ class PushDiscontinuousLoops : public TIntermTraverser
{
switch (node->getOp())
{
- case EOpFunctionCall:
- if (visit == PreVisit && node->isUserDefined() && mNestedDiscont > 0)
- {
- size_t calleeIndex = mDag.findIndex(node);
- ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex);
- UNUSED_ASSERTION_VARIABLE(mIndex);
+ case EOpCallFunctionInAST:
+ if (visit == PreVisit && mNestedDiscont > 0)
+ {
+ size_t calleeIndex = mDag.findIndex(node->getFunctionSymbolInfo());
+ ASSERT(calleeIndex != CallDAG::InvalidIndex && calleeIndex < mIndex);
- (*mMetadataList)[calleeIndex].mCalledInDiscontinuousLoop = true;
- }
- break;
- default:
- break;
+ (*mMetadataList)[calleeIndex].mCalledInDiscontinuousLoop = true;
+ }
+ break;
+ default:
+ break;
}
return true;
}
@@ -377,7 +387,6 @@ class PushDiscontinuousLoops : public TIntermTraverser
int mNestedDiscont;
};
-
}
bool ASTMetadataHLSL::hasGradientInCallGraph(TIntermLoop *node)
@@ -385,7 +394,7 @@ bool ASTMetadataHLSL::hasGradientInCallGraph(TIntermLoop *node)
return mControlFlowsContainingGradient.count(node) > 0;
}
-bool ASTMetadataHLSL::hasGradientLoop(TIntermSelection *node)
+bool ASTMetadataHLSL::hasGradientLoop(TIntermIfElse *node)
{
return mIfsContainingGradientLoop.count(node) > 0;
}
@@ -449,3 +458,5 @@ MetadataList CreateASTMetadataHLSL(TIntermNode *root, const CallDAG &callDag)
return metadataList;
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.h b/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.h
index 39e671e3e0..550a522b86 100644
--- a/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/ASTMetadataHLSL.h
@@ -12,9 +12,12 @@
#include <set>
#include <vector>
+namespace sh
+{
+
class CallDAG;
class TIntermNode;
-class TIntermSelection;
+class TIntermIfElse;
class TIntermLoop;
struct ASTMetadataHLSL
@@ -30,21 +33,21 @@ struct ASTMetadataHLSL
// Here "something uses a gradient" means here that it either contains a
// gradient operation, or a call to a function that uses a gradient.
bool hasGradientInCallGraph(TIntermLoop *node);
- bool hasGradientLoop(TIntermSelection *node);
+ bool hasGradientLoop(TIntermIfElse *node);
// Does the function use a gradient.
bool mUsesGradient;
// Even if usesGradient is true, some control flow might not use a gradient
// so we store the set of all gradient-using control flows.
- std::set<TIntermNode*> mControlFlowsContainingGradient;
+ std::set<TIntermNode *> mControlFlowsContainingGradient;
// Remember information about the discontinuous loops and which functions
// are called in such loops.
bool mCalledInDiscontinuousLoop;
bool mHasGradientLoopInCallGraph;
- std::set<TIntermLoop*> mDiscontinuousLoops;
- std::set<TIntermSelection *> mIfsContainingGradientLoop;
+ std::set<TIntermLoop *> mDiscontinuousLoops;
+ std::set<TIntermIfElse *> mIfsContainingGradientLoop;
// Will we need to generate a Lod0 version of the function.
bool mNeedsLod0;
@@ -55,4 +58,6 @@ typedef std::vector<ASTMetadataHLSL> MetadataList;
// Return the AST analysis result, in the order defined by the call DAG
MetadataList CreateASTMetadataHLSL(TIntermNode *root, const CallDAG &callDag);
-#endif // COMPILER_TRANSLATOR_ASTMETADATAHLSL_H_
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_ASTMETADATAHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.cpp b/src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.cpp
new file mode 100644
index 0000000000..6a05104233
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.cpp
@@ -0,0 +1,59 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/AddAndTrueToLoopCondition.h"
+
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
+
+namespace
+{
+
+// An AST traverser that rewrites for and while loops by replacing "condition" with
+// "condition && true" to work around condition bug on Intel Mac.
+class AddAndTrueToLoopConditionTraverser : public TIntermTraverser
+{
+ public:
+ AddAndTrueToLoopConditionTraverser() : TIntermTraverser(true, false, false) {}
+
+ bool visitLoop(Visit, TIntermLoop *loop) override
+ {
+ // do-while loop doesn't have this bug.
+ if (loop->getType() != ELoopFor && loop->getType() != ELoopWhile)
+ {
+ return true;
+ }
+
+ // For loop may not have a condition.
+ if (loop->getCondition() == nullptr)
+ {
+ return true;
+ }
+
+ // Constant true.
+ TConstantUnion *trueConstant = new TConstantUnion();
+ trueConstant->setBConst(true);
+ TIntermTyped *trueValue = new TIntermConstantUnion(trueConstant, TType(EbtBool));
+
+ // CONDITION && true.
+ TIntermBinary *andOp = new TIntermBinary(EOpLogicalAnd, loop->getCondition(), trueValue);
+ loop->setCondition(andOp);
+
+ return true;
+ }
+};
+
+} // anonymous namespace
+
+void AddAndTrueToLoopCondition(TIntermNode *root)
+{
+ AddAndTrueToLoopConditionTraverser traverser;
+ root->traverse(&traverser);
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.h b/src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.h
new file mode 100644
index 0000000000..34debe0ed9
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/AddAndTrueToLoopCondition.h
@@ -0,0 +1,20 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Rewrite condition in for and while loops to work around driver bug on Intel Mac.
+
+#ifndef COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_
+#define COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_
+
+class TIntermNode;
+namespace sh
+{
+
+void AddAndTrueToLoopCondition(TIntermNode *root);
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.cpp b/src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.cpp
new file mode 100644
index 0000000000..4dfe60c0bc
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.cpp
@@ -0,0 +1,58 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// AddDefaultReturnStatements.cpp: Add default return statements to functions that do not end in a
+// return.
+//
+
+#include "compiler/translator/AddDefaultReturnStatements.h"
+
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/util.h"
+
+namespace sh
+{
+
+namespace
+{
+
+bool NeedsReturnStatement(TIntermFunctionDefinition *node, TType *returnType)
+{
+ *returnType = node->getFunctionPrototype()->getType();
+ if (returnType->getBasicType() == EbtVoid)
+ {
+ return false;
+ }
+
+ TIntermBlock *bodyNode = node->getBody();
+ TIntermBranch *returnNode = bodyNode->getSequence()->back()->getAsBranchNode();
+ if (returnNode != nullptr && returnNode->getFlowOp() == EOpReturn)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+} // anonymous namespace
+
+void AddDefaultReturnStatements(TIntermBlock *root)
+{
+ TType returnType;
+ for (TIntermNode *node : *root->getSequence())
+ {
+ TIntermFunctionDefinition *definition = node->getAsFunctionDefinition();
+ if (definition != nullptr && NeedsReturnStatement(definition, &returnType))
+ {
+ TIntermBranch *branch = new TIntermBranch(EOpReturn, CreateZeroNode(returnType));
+
+ TIntermBlock *bodyNode = definition->getBody();
+ bodyNode->getSequence()->push_back(branch);
+ }
+ }
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.h b/src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.h
new file mode 100644
index 0000000000..40a70ad8c2
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/AddDefaultReturnStatements.h
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// AddDefaultReturnStatements.h: Add default return statements to functions that do not end in a
+// return.
+//
+
+#ifndef COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_
+#define COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_
+
+class TIntermBlock;
+
+namespace sh
+{
+
+void AddDefaultReturnStatements(TIntermBlock *root);
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp b/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
index 510ade84c1..17721fb0dc 100644
--- a/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
@@ -3,17 +3,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// The ArrayReturnValueToOutParameter function changes return values of an array type to out parameters in
-// function definitions, prototypes, and call sites.
+// The ArrayReturnValueToOutParameter function changes return values of an array type to out
+// parameters in function definitions, prototypes, and call sites.
#include "compiler/translator/ArrayReturnValueToOutParameter.h"
-#include "compiler/translator/IntermNode.h"
+#include <map>
+
+#include "compiler/translator/IntermTraverse.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
namespace
{
-void CopyAggregateChildren(TIntermAggregate *from, TIntermAggregate *to)
+void CopyAggregateChildren(TIntermAggregateBase *from, TIntermAggregateBase *to)
{
const TIntermSequence *fromSequence = from->getSequence();
for (size_t ii = 0; ii < fromSequence->size(); ++ii)
@@ -22,156 +28,153 @@ void CopyAggregateChildren(TIntermAggregate *from, TIntermAggregate *to)
}
}
-TIntermSymbol *CreateReturnValueSymbol(const TType &type)
+TIntermSymbol *CreateReturnValueSymbol(const TSymbolUniqueId &id, const TType &type)
{
- TIntermSymbol *node = new TIntermSymbol(0, "angle_return", type);
+ TIntermSymbol *node = new TIntermSymbol(id, "angle_return", type);
node->setInternal(true);
+ node->getTypePointer()->setQualifier(EvqOut);
return node;
}
-TIntermSymbol *CreateReturnValueOutSymbol(const TType &type)
+TIntermAggregate *CreateReplacementCall(TIntermAggregate *originalCall,
+ TIntermTyped *returnValueTarget)
{
- TType outType(type);
- outType.setQualifier(EvqOut);
- return CreateReturnValueSymbol(outType);
-}
-
-TIntermAggregate *CreateReplacementCall(TIntermAggregate *originalCall, TIntermTyped *returnValueTarget)
-{
- TIntermAggregate *replacementCall = new TIntermAggregate(EOpFunctionCall);
- replacementCall->setType(TType(EbtVoid));
- replacementCall->setUserDefined();
- replacementCall->setNameObj(originalCall->getNameObj());
- replacementCall->setFunctionId(originalCall->getFunctionId());
- replacementCall->setLine(originalCall->getLine());
- TIntermSequence *replacementParameters = replacementCall->getSequence();
- TIntermSequence *originalParameters = originalCall->getSequence();
- for (auto &param : *originalParameters)
+ TIntermSequence *replacementArguments = new TIntermSequence();
+ TIntermSequence *originalArguments = originalCall->getSequence();
+ for (auto &arg : *originalArguments)
{
- replacementParameters->push_back(param);
+ replacementArguments->push_back(arg);
}
- replacementParameters->push_back(returnValueTarget);
+ replacementArguments->push_back(returnValueTarget);
+ TIntermAggregate *replacementCall = TIntermAggregate::CreateFunctionCall(
+ TType(EbtVoid), originalCall->getFunctionSymbolInfo()->getId(),
+ originalCall->getFunctionSymbolInfo()->getNameObj(), replacementArguments);
+ replacementCall->setLine(originalCall->getLine());
return replacementCall;
}
class ArrayReturnValueToOutParameterTraverser : private TIntermTraverser
{
public:
- static void apply(TIntermNode *root, unsigned int *temporaryIndex);
+ static void apply(TIntermNode *root, TSymbolTable *symbolTable);
+
private:
- ArrayReturnValueToOutParameterTraverser();
+ ArrayReturnValueToOutParameterTraverser(TSymbolTable *symbolTable);
+ bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override;
+ bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
bool visitBranch(Visit visit, TIntermBranch *node) override;
bool visitBinary(Visit visit, TIntermBinary *node) override;
- bool mInFunctionWithArrayReturnValue;
+ // Set when traversal is inside a function with array return value.
+ TIntermFunctionDefinition *mFunctionWithArrayReturnValue;
+
+ // Map from function symbol ids to array return value ids.
+ std::map<int, TSymbolUniqueId *> mReturnValueIds;
};
-void ArrayReturnValueToOutParameterTraverser::apply(TIntermNode *root, unsigned int *temporaryIndex)
+void ArrayReturnValueToOutParameterTraverser::apply(TIntermNode *root, TSymbolTable *symbolTable)
{
- ArrayReturnValueToOutParameterTraverser arrayReturnValueToOutParam;
- arrayReturnValueToOutParam.useTemporaryIndex(temporaryIndex);
+ ArrayReturnValueToOutParameterTraverser arrayReturnValueToOutParam(symbolTable);
root->traverse(&arrayReturnValueToOutParam);
arrayReturnValueToOutParam.updateTree();
}
-ArrayReturnValueToOutParameterTraverser::ArrayReturnValueToOutParameterTraverser()
- : TIntermTraverser(true, false, true),
- mInFunctionWithArrayReturnValue(false)
+ArrayReturnValueToOutParameterTraverser::ArrayReturnValueToOutParameterTraverser(
+ TSymbolTable *symbolTable)
+ : TIntermTraverser(true, false, true, symbolTable), mFunctionWithArrayReturnValue(nullptr)
{
}
-bool ArrayReturnValueToOutParameterTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
+bool ArrayReturnValueToOutParameterTraverser::visitFunctionDefinition(
+ Visit visit,
+ TIntermFunctionDefinition *node)
+{
+ if (node->getFunctionPrototype()->isArray() && visit == PreVisit)
+ {
+ // Replacing the function header is done on visitFunctionPrototype().
+ mFunctionWithArrayReturnValue = node;
+ }
+ if (visit == PostVisit)
+ {
+ mFunctionWithArrayReturnValue = nullptr;
+ }
+ return true;
+}
+
+bool ArrayReturnValueToOutParameterTraverser::visitFunctionPrototype(Visit visit,
+ TIntermFunctionPrototype *node)
{
- if (visit == PreVisit)
+ if (visit == PreVisit && node->isArray())
{
- if (node->isArray())
+ // Replace the whole prototype node with another node that has the out parameter
+ // added. Also set the function to return void.
+ TIntermFunctionPrototype *replacement =
+ new TIntermFunctionPrototype(TType(EbtVoid), node->getFunctionSymbolInfo()->getId());
+ CopyAggregateChildren(node, replacement);
+ const TSymbolUniqueId &functionId = node->getFunctionSymbolInfo()->getId();
+ if (mReturnValueIds.find(functionId.get()) == mReturnValueIds.end())
{
- if (node->getOp() == EOpFunction)
- {
- // Replace the parameters child node of the function definition with another node
- // that has the out parameter added.
- // Also set the function to return void.
-
- TIntermAggregate *params = node->getSequence()->front()->getAsAggregate();
- ASSERT(params != nullptr && params->getOp() == EOpParameters);
-
- TIntermAggregate *replacementParams = new TIntermAggregate;
- replacementParams->setOp(EOpParameters);
- CopyAggregateChildren(params, replacementParams);
- replacementParams->getSequence()->push_back(CreateReturnValueOutSymbol(node->getType()));
- replacementParams->setLine(params->getLine());
-
- mReplacements.push_back(NodeUpdateEntry(node, params, replacementParams, false));
-
- node->setType(TType(EbtVoid));
-
- mInFunctionWithArrayReturnValue = true;
- }
- else if (node->getOp() == EOpPrototype)
- {
- // Replace the whole prototype node with another node that has the out parameter added.
- TIntermAggregate *replacement = new TIntermAggregate;
- replacement->setOp(EOpPrototype);
- CopyAggregateChildren(node, replacement);
- replacement->getSequence()->push_back(CreateReturnValueOutSymbol(node->getType()));
- replacement->setUserDefined();
- replacement->setNameObj(node->getNameObj());
- replacement->setFunctionId(node->getFunctionId());
- replacement->setLine(node->getLine());
- replacement->setType(TType(EbtVoid));
-
- mReplacements.push_back(NodeUpdateEntry(getParentNode(), node, replacement, false));
- }
- else if (node->getOp() == EOpFunctionCall)
- {
- // Handle call sites where the returned array is not assigned.
- // Examples where f() is a function returning an array:
- // 1. f();
- // 2. another_array == f();
- // 3. another_function(f());
- // 4. return f();
- // Cases 2 to 4 are already converted to simpler cases by SeparateExpressionsReturningArrays, so we
- // only need to worry about the case where a function call returning an array forms an expression by
- // itself.
- TIntermAggregate *parentAgg = getParentNode()->getAsAggregate();
- if (parentAgg != nullptr && parentAgg->getOp() == EOpSequence)
- {
- nextTemporaryIndex();
- TIntermSequence replacements;
- replacements.push_back(createTempDeclaration(node->getType()));
- TIntermSymbol *returnSymbol = createTempSymbol(node->getType());
- replacements.push_back(CreateReplacementCall(node, returnSymbol));
- mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(parentAgg, node, replacements));
- }
- return false;
- }
+ mReturnValueIds[functionId.get()] = new TSymbolUniqueId(mSymbolTable);
}
+ replacement->getSequence()->push_back(
+ CreateReturnValueSymbol(*mReturnValueIds[functionId.get()], node->getType()));
+ *replacement->getFunctionSymbolInfo() = *node->getFunctionSymbolInfo();
+ replacement->setLine(node->getLine());
+
+ queueReplacement(replacement, OriginalNode::IS_DROPPED);
}
- else if (visit == PostVisit)
+ return false;
+}
+
+bool ArrayReturnValueToOutParameterTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+ ASSERT(!node->isArray() || node->getOp() != EOpCallInternalRawFunction);
+ if (visit == PreVisit && node->isArray() && node->getOp() == EOpCallFunctionInAST)
{
- if (node->getOp() == EOpFunction)
+ // Handle call sites where the returned array is not assigned.
+ // Examples where f() is a function returning an array:
+ // 1. f();
+ // 2. another_array == f();
+ // 3. another_function(f());
+ // 4. return f();
+ // Cases 2 to 4 are already converted to simpler cases by
+ // SeparateExpressionsReturningArrays, so we only need to worry about the case where a
+ // function call returning an array forms an expression by itself.
+ TIntermBlock *parentBlock = getParentNode()->getAsBlock();
+ if (parentBlock)
{
- mInFunctionWithArrayReturnValue = false;
+ nextTemporaryId();
+ TIntermSequence replacements;
+ replacements.push_back(createTempDeclaration(node->getType()));
+ TIntermSymbol *returnSymbol = createTempSymbol(node->getType());
+ replacements.push_back(CreateReplacementCall(node, returnSymbol));
+ mMultiReplacements.push_back(
+ NodeReplaceWithMultipleEntry(parentBlock, node, replacements));
}
+ return false;
}
return true;
}
bool ArrayReturnValueToOutParameterTraverser::visitBranch(Visit visit, TIntermBranch *node)
{
- if (mInFunctionWithArrayReturnValue && node->getFlowOp() == EOpReturn)
+ if (mFunctionWithArrayReturnValue && node->getFlowOp() == EOpReturn)
{
// Instead of returning a value, assign to the out parameter and then return.
TIntermSequence replacements;
- TIntermBinary *replacementAssignment = new TIntermBinary(EOpAssign);
TIntermTyped *expression = node->getExpression();
ASSERT(expression != nullptr);
- replacementAssignment->setLeft(CreateReturnValueSymbol(expression->getType()));
- replacementAssignment->setRight(node->getExpression());
- replacementAssignment->setType(expression->getType());
+ const TSymbolUniqueId &functionId =
+ mFunctionWithArrayReturnValue->getFunctionSymbolInfo()->getId();
+ ASSERT(mReturnValueIds.find(functionId.get()) != mReturnValueIds.end());
+ const TSymbolUniqueId &returnValueId = *mReturnValueIds[functionId.get()];
+ TIntermSymbol *returnValueSymbol =
+ CreateReturnValueSymbol(returnValueId, expression->getType());
+ TIntermBinary *replacementAssignment =
+ new TIntermBinary(EOpAssign, returnValueSymbol, expression);
replacementAssignment->setLine(expression->getLine());
replacements.push_back(replacementAssignment);
@@ -179,7 +182,8 @@ bool ArrayReturnValueToOutParameterTraverser::visitBranch(Visit visit, TIntermBr
replacementBranch->setLine(node->getLine());
replacements.push_back(replacementBranch);
- mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(getParentNode()->getAsAggregate(), node, replacements));
+ mMultiReplacements.push_back(
+ NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(), node, replacements));
}
return false;
}
@@ -189,18 +193,21 @@ bool ArrayReturnValueToOutParameterTraverser::visitBinary(Visit visit, TIntermBi
if (node->getOp() == EOpAssign && node->getLeft()->isArray())
{
TIntermAggregate *rightAgg = node->getRight()->getAsAggregate();
- if (rightAgg != nullptr && rightAgg->getOp() == EOpFunctionCall && rightAgg->isUserDefined())
+ ASSERT(rightAgg == nullptr || rightAgg->getOp() != EOpCallInternalRawFunction);
+ if (rightAgg != nullptr && rightAgg->getOp() == EOpCallFunctionInAST)
{
TIntermAggregate *replacementCall = CreateReplacementCall(rightAgg, node->getLeft());
- mReplacements.push_back(NodeUpdateEntry(getParentNode(), node, replacementCall, false));
+ queueReplacement(replacementCall, OriginalNode::IS_DROPPED);
}
}
return false;
}
-} // namespace
+} // namespace
-void ArrayReturnValueToOutParameter(TIntermNode *root, unsigned int *temporaryIndex)
+void ArrayReturnValueToOutParameter(TIntermNode *root, TSymbolTable *symbolTable)
{
- ArrayReturnValueToOutParameterTraverser::apply(root, temporaryIndex);
+ ArrayReturnValueToOutParameterTraverser::apply(root, symbolTable);
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h b/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h
index 983e203e62..469c7a3b14 100644
--- a/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h
+++ b/src/3rdparty/angle/src/compiler/translator/ArrayReturnValueToOutParameter.h
@@ -3,14 +3,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// The ArrayReturnValueToOutParameter function changes return values of an array type to out parameters in
-// function definitions, prototypes and call sites.
+// The ArrayReturnValueToOutParameter function changes return values of an array type to out
+// parameters in function definitions, prototypes and call sites.
#ifndef COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
#define COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
+namespace sh
+{
+
class TIntermNode;
+class TSymbolTable;
+
+void ArrayReturnValueToOutParameter(TIntermNode *root, TSymbolTable *symbolTable);
-void ArrayReturnValueToOutParameter(TIntermNode *root, unsigned int *temporaryIndex);
+} // namespace sh
#endif // COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/BaseTypes.h b/src/3rdparty/angle/src/compiler/translator/BaseTypes.h
index 0ed6d0e62f..b2070f3baf 100644
--- a/src/3rdparty/angle/src/compiler/translator/BaseTypes.h
+++ b/src/3rdparty/angle/src/compiler/translator/BaseTypes.h
@@ -7,7 +7,14 @@
#ifndef COMPILER_TRANSLATOR_BASETYPES_H_
#define COMPILER_TRANSLATOR_BASETYPES_H_
+#include <algorithm>
+#include <array>
+
#include "common/debug.h"
+#include "GLSLANG/ShaderLang.h"
+
+namespace sh
+{
//
// Precision qualifiers
@@ -24,14 +31,18 @@ enum TPrecision
EbpLast
};
-inline const char* getPrecisionString(TPrecision p)
+inline const char *getPrecisionString(TPrecision p)
{
- switch(p)
+ switch (p)
{
- case EbpHigh: return "highp"; break;
- case EbpMedium: return "mediump"; break;
- case EbpLow: return "lowp"; break;
- default: return "mediump"; break; // Safest fallback
+ case EbpHigh:
+ return "highp";
+ case EbpMedium:
+ return "mediump";
+ case EbpLow:
+ return "lowp";
+ default:
+ return "mediump"; // Safest fallback
}
}
@@ -54,69 +65,243 @@ enum TBasicType
EbtIVec, // non type: represents ivec2, ivec3, and ivec4
EbtUVec, // non type: represents uvec2, uvec3, and uvec4
EbtBVec, // non type: represents bvec2, bvec3, and bvec4
+ EbtYuvCscStandardEXT, // Only valid if EXT_YUV_target exists.
EbtGuardSamplerBegin, // non type: see implementation of IsSampler()
EbtSampler2D,
EbtSampler3D,
EbtSamplerCube,
EbtSampler2DArray,
- EbtSamplerExternalOES, // Only valid if OES_EGL_image_external exists.
- EbtSampler2DRect, // Only valid if GL_ARB_texture_rectangle exists.
+ EbtSamplerExternalOES, // Only valid if OES_EGL_image_external exists.
+ EbtSamplerExternal2DY2YEXT, // Only valid if GL_EXT_YUV_target exists.
+ EbtSampler2DRect, // Only valid if GL_ARB_texture_rectangle exists.
+ EbtSampler2DMS,
EbtISampler2D,
EbtISampler3D,
EbtISamplerCube,
EbtISampler2DArray,
+ EbtISampler2DMS,
EbtUSampler2D,
EbtUSampler3D,
EbtUSamplerCube,
EbtUSampler2DArray,
+ EbtUSampler2DMS,
EbtSampler2DShadow,
EbtSamplerCubeShadow,
EbtSampler2DArrayShadow,
- EbtGuardSamplerEnd, // non type: see implementation of IsSampler()
- EbtGSampler2D, // non type: represents sampler2D, isampler2D, and usampler2D
- EbtGSampler3D, // non type: represents sampler3D, isampler3D, and usampler3D
- EbtGSamplerCube, // non type: represents samplerCube, isamplerCube, and usamplerCube
- EbtGSampler2DArray, // non type: represents sampler2DArray, isampler2DArray, and usampler2DArray
+ EbtGuardSamplerEnd, // non type: see implementation of IsSampler()
+ EbtGSampler2D, // non type: represents sampler2D, isampler2D, and usampler2D
+ EbtGSampler3D, // non type: represents sampler3D, isampler3D, and usampler3D
+ EbtGSamplerCube, // non type: represents samplerCube, isamplerCube, and usamplerCube
+ EbtGSampler2DArray, // non type: represents sampler2DArray, isampler2DArray, and
+ // usampler2DArray
+ EbtGSampler2DMS, // non type: represents sampler2DMS, isampler2DMS, and usampler2DMS
+
+ // images
+ EbtGuardImageBegin,
+ EbtImage2D,
+ EbtIImage2D,
+ EbtUImage2D,
+ EbtImage3D,
+ EbtIImage3D,
+ EbtUImage3D,
+ EbtImage2DArray,
+ EbtIImage2DArray,
+ EbtUImage2DArray,
+ EbtImageCube,
+ EbtIImageCube,
+ EbtUImageCube,
+ EbtGuardImageEnd,
+
+ EbtGuardGImageBegin,
+ EbtGImage2D, // non type: represents image2D, uimage2D, iimage2D
+ EbtGImage3D, // non type: represents image3D, uimage3D, iimage3D
+ EbtGImage2DArray, // non type: represents image2DArray, uimage2DArray, iimage2DArray
+ EbtGImageCube, // non type: represents imageCube, uimageCube, iimageCube
+ EbtGuardGImageEnd,
+
EbtStruct,
EbtInterfaceBlock,
- EbtAddress, // should be deprecated??
+ EbtAddress, // should be deprecated??
+
+ EbtAtomicCounter,
// end of list
EbtLast
};
-const char* getBasicString(TBasicType t);
+inline TBasicType convertGImageToFloatImage(TBasicType type)
+{
+ switch (type)
+ {
+ case EbtGImage2D:
+ return EbtImage2D;
+ case EbtGImage3D:
+ return EbtImage3D;
+ case EbtGImage2DArray:
+ return EbtImage2DArray;
+ case EbtGImageCube:
+ return EbtImageCube;
+ default:
+ UNREACHABLE();
+ }
+ return EbtLast;
+}
+
+inline TBasicType convertGImageToIntImage(TBasicType type)
+{
+ switch (type)
+ {
+ case EbtGImage2D:
+ return EbtIImage2D;
+ case EbtGImage3D:
+ return EbtIImage3D;
+ case EbtGImage2DArray:
+ return EbtIImage2DArray;
+ case EbtGImageCube:
+ return EbtIImageCube;
+ default:
+ UNREACHABLE();
+ }
+ return EbtLast;
+}
+
+inline TBasicType convertGImageToUnsignedImage(TBasicType type)
+{
+ switch (type)
+ {
+ case EbtGImage2D:
+ return EbtUImage2D;
+ case EbtGImage3D:
+ return EbtUImage3D;
+ case EbtGImage2DArray:
+ return EbtUImage2DArray;
+ case EbtGImageCube:
+ return EbtUImageCube;
+ default:
+ UNREACHABLE();
+ }
+ return EbtLast;
+}
+
+const char *getBasicString(TBasicType t);
inline bool IsSampler(TBasicType type)
{
return type > EbtGuardSamplerBegin && type < EbtGuardSamplerEnd;
}
+inline bool IsImage(TBasicType type)
+{
+ return type > EbtGuardImageBegin && type < EbtGuardImageEnd;
+}
+
+inline bool IsGImage(TBasicType type)
+{
+ return type > EbtGuardGImageBegin && type < EbtGuardGImageEnd;
+}
+
+inline bool IsAtomicCounter(TBasicType type)
+{
+ return type == EbtAtomicCounter;
+}
+
+inline bool IsOpaqueType(TBasicType type)
+{
+ return IsSampler(type) || IsImage(type) || IsAtomicCounter(type);
+}
+
inline bool IsIntegerSampler(TBasicType type)
{
switch (type)
{
- case EbtISampler2D:
- case EbtISampler3D:
- case EbtISamplerCube:
- case EbtISampler2DArray:
- case EbtUSampler2D:
- case EbtUSampler3D:
- case EbtUSamplerCube:
- case EbtUSampler2DArray:
- return true;
- case EbtSampler2D:
- case EbtSampler3D:
- case EbtSamplerCube:
- case EbtSamplerExternalOES:
- case EbtSampler2DRect:
- case EbtSampler2DArray:
- case EbtSampler2DShadow:
- case EbtSamplerCubeShadow:
- case EbtSampler2DArrayShadow:
- return false;
- default:
- assert(!IsSampler(type));
+ case EbtISampler2D:
+ case EbtISampler3D:
+ case EbtISamplerCube:
+ case EbtISampler2DArray:
+ case EbtISampler2DMS:
+ case EbtUSampler2D:
+ case EbtUSampler3D:
+ case EbtUSamplerCube:
+ case EbtUSampler2DArray:
+ case EbtUSampler2DMS:
+ return true;
+ case EbtSampler2D:
+ case EbtSampler3D:
+ case EbtSamplerCube:
+ case EbtSamplerExternalOES:
+ case EbtSamplerExternal2DY2YEXT:
+ case EbtSampler2DRect:
+ case EbtSampler2DArray:
+ case EbtSampler2DShadow:
+ case EbtSamplerCubeShadow:
+ case EbtSampler2DArrayShadow:
+ case EbtSampler2DMS:
+ return false;
+ default:
+ assert(!IsSampler(type));
+ }
+
+ return false;
+}
+
+inline bool IsSampler2DMS(TBasicType type)
+{
+ switch (type)
+ {
+ case EbtSampler2DMS:
+ case EbtISampler2DMS:
+ case EbtUSampler2DMS:
+ return true;
+ default:
+ return false;
+ }
+}
+
+inline bool IsFloatImage(TBasicType type)
+{
+ switch (type)
+ {
+ case EbtImage2D:
+ case EbtImage3D:
+ case EbtImage2DArray:
+ case EbtImageCube:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+inline bool IsIntegerImage(TBasicType type)
+{
+
+ switch (type)
+ {
+ case EbtIImage2D:
+ case EbtIImage3D:
+ case EbtIImage2DArray:
+ case EbtIImageCube:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+inline bool IsUnsignedImage(TBasicType type)
+{
+
+ switch (type)
+ {
+ case EbtUImage2D:
+ case EbtUImage3D:
+ case EbtUImage2DArray:
+ case EbtUImageCube:
+ return true;
+ default:
+ break;
}
return false;
@@ -126,27 +311,31 @@ inline bool IsSampler2D(TBasicType type)
{
switch (type)
{
- case EbtSampler2D:
- case EbtISampler2D:
- case EbtUSampler2D:
- case EbtSampler2DArray:
- case EbtISampler2DArray:
- case EbtUSampler2DArray:
- case EbtSampler2DRect:
- case EbtSamplerExternalOES:
- case EbtSampler2DShadow:
- case EbtSampler2DArrayShadow:
- return true;
- case EbtSampler3D:
- case EbtISampler3D:
- case EbtUSampler3D:
- case EbtISamplerCube:
- case EbtUSamplerCube:
- case EbtSamplerCube:
- case EbtSamplerCubeShadow:
- return false;
- default:
- assert(!IsSampler(type));
+ case EbtSampler2D:
+ case EbtISampler2D:
+ case EbtUSampler2D:
+ case EbtSampler2DArray:
+ case EbtISampler2DArray:
+ case EbtUSampler2DArray:
+ case EbtSampler2DRect:
+ case EbtSamplerExternalOES:
+ case EbtSamplerExternal2DY2YEXT:
+ case EbtSampler2DShadow:
+ case EbtSampler2DArrayShadow:
+ case EbtSampler2DMS:
+ case EbtISampler2DMS:
+ case EbtUSampler2DMS:
+ return true;
+ case EbtSampler3D:
+ case EbtISampler3D:
+ case EbtUSampler3D:
+ case EbtISamplerCube:
+ case EbtUSamplerCube:
+ case EbtSamplerCube:
+ case EbtSamplerCubeShadow:
+ return false;
+ default:
+ assert(!IsSampler(type));
}
return false;
@@ -156,27 +345,31 @@ inline bool IsSamplerCube(TBasicType type)
{
switch (type)
{
- case EbtSamplerCube:
- case EbtISamplerCube:
- case EbtUSamplerCube:
- case EbtSamplerCubeShadow:
- return true;
- case EbtSampler2D:
- case EbtSampler3D:
- case EbtSamplerExternalOES:
- case EbtSampler2DRect:
- case EbtSampler2DArray:
- case EbtISampler2D:
- case EbtISampler3D:
- case EbtISampler2DArray:
- case EbtUSampler2D:
- case EbtUSampler3D:
- case EbtUSampler2DArray:
- case EbtSampler2DShadow:
- case EbtSampler2DArrayShadow:
- return false;
- default:
- assert(!IsSampler(type));
+ case EbtSamplerCube:
+ case EbtISamplerCube:
+ case EbtUSamplerCube:
+ case EbtSamplerCubeShadow:
+ return true;
+ case EbtSampler2D:
+ case EbtSampler3D:
+ case EbtSamplerExternalOES:
+ case EbtSamplerExternal2DY2YEXT:
+ case EbtSampler2DRect:
+ case EbtSampler2DArray:
+ case EbtSampler2DMS:
+ case EbtISampler2D:
+ case EbtISampler3D:
+ case EbtISampler2DArray:
+ case EbtISampler2DMS:
+ case EbtUSampler2D:
+ case EbtUSampler3D:
+ case EbtUSampler2DArray:
+ case EbtUSampler2DMS:
+ case EbtSampler2DShadow:
+ case EbtSampler2DArrayShadow:
+ return false;
+ default:
+ assert(!IsSampler(type));
}
return false;
@@ -186,27 +379,31 @@ inline bool IsSampler3D(TBasicType type)
{
switch (type)
{
- case EbtSampler3D:
- case EbtISampler3D:
- case EbtUSampler3D:
- return true;
- case EbtSampler2D:
- case EbtSamplerCube:
- case EbtSamplerExternalOES:
- case EbtSampler2DRect:
- case EbtSampler2DArray:
- case EbtISampler2D:
- case EbtISamplerCube:
- case EbtISampler2DArray:
- case EbtUSampler2D:
- case EbtUSamplerCube:
- case EbtUSampler2DArray:
- case EbtSampler2DShadow:
- case EbtSamplerCubeShadow:
- case EbtSampler2DArrayShadow:
- return false;
- default:
- assert(!IsSampler(type));
+ case EbtSampler3D:
+ case EbtISampler3D:
+ case EbtUSampler3D:
+ return true;
+ case EbtSampler2D:
+ case EbtSamplerCube:
+ case EbtSamplerExternalOES:
+ case EbtSamplerExternal2DY2YEXT:
+ case EbtSampler2DRect:
+ case EbtSampler2DArray:
+ case EbtSampler2DMS:
+ case EbtISampler2D:
+ case EbtISamplerCube:
+ case EbtISampler2DArray:
+ case EbtISampler2DMS:
+ case EbtUSampler2D:
+ case EbtUSamplerCube:
+ case EbtUSampler2DArray:
+ case EbtUSampler2DMS:
+ case EbtSampler2DShadow:
+ case EbtSamplerCubeShadow:
+ case EbtSampler2DArrayShadow:
+ return false;
+ default:
+ assert(!IsSampler(type));
}
return false;
@@ -216,27 +413,31 @@ inline bool IsSamplerArray(TBasicType type)
{
switch (type)
{
- case EbtSampler2DArray:
- case EbtISampler2DArray:
- case EbtUSampler2DArray:
- case EbtSampler2DArrayShadow:
- return true;
- case EbtSampler2D:
- case EbtISampler2D:
- case EbtUSampler2D:
- case EbtSampler2DRect:
- case EbtSamplerExternalOES:
- case EbtSampler3D:
- case EbtISampler3D:
- case EbtUSampler3D:
- case EbtISamplerCube:
- case EbtUSamplerCube:
- case EbtSamplerCube:
- case EbtSampler2DShadow:
- case EbtSamplerCubeShadow:
- return false;
- default:
- assert(!IsSampler(type));
+ case EbtSampler2DArray:
+ case EbtISampler2DArray:
+ case EbtUSampler2DArray:
+ case EbtSampler2DArrayShadow:
+ return true;
+ case EbtSampler2D:
+ case EbtISampler2D:
+ case EbtUSampler2D:
+ case EbtSampler2DRect:
+ case EbtSamplerExternalOES:
+ case EbtSamplerExternal2DY2YEXT:
+ case EbtSampler3D:
+ case EbtISampler3D:
+ case EbtUSampler3D:
+ case EbtISamplerCube:
+ case EbtUSamplerCube:
+ case EbtSamplerCube:
+ case EbtSampler2DShadow:
+ case EbtSamplerCubeShadow:
+ case EbtSampler2DMS:
+ case EbtISampler2DMS:
+ case EbtUSampler2DMS:
+ return false;
+ default:
+ assert(!IsSampler(type));
}
return false;
@@ -246,27 +447,131 @@ inline bool IsShadowSampler(TBasicType type)
{
switch (type)
{
- case EbtSampler2DShadow:
- case EbtSamplerCubeShadow:
- case EbtSampler2DArrayShadow:
- return true;
- case EbtISampler2D:
- case EbtISampler3D:
- case EbtISamplerCube:
- case EbtISampler2DArray:
- case EbtUSampler2D:
- case EbtUSampler3D:
- case EbtUSamplerCube:
- case EbtUSampler2DArray:
- case EbtSampler2D:
- case EbtSampler3D:
- case EbtSamplerCube:
- case EbtSamplerExternalOES:
- case EbtSampler2DRect:
- case EbtSampler2DArray:
- return false;
- default:
- assert(!IsSampler(type));
+ case EbtSampler2DShadow:
+ case EbtSamplerCubeShadow:
+ case EbtSampler2DArrayShadow:
+ return true;
+ case EbtISampler2D:
+ case EbtISampler3D:
+ case EbtISamplerCube:
+ case EbtISampler2DArray:
+ case EbtISampler2DMS:
+ case EbtUSampler2D:
+ case EbtUSampler3D:
+ case EbtUSamplerCube:
+ case EbtUSampler2DArray:
+ case EbtUSampler2DMS:
+ case EbtSampler2D:
+ case EbtSampler3D:
+ case EbtSamplerCube:
+ case EbtSamplerExternalOES:
+ case EbtSamplerExternal2DY2YEXT:
+ case EbtSampler2DRect:
+ case EbtSampler2DArray:
+ case EbtSampler2DMS:
+ return false;
+ default:
+ assert(!IsSampler(type));
+ }
+
+ return false;
+}
+
+inline bool IsImage2D(TBasicType type)
+{
+ switch (type)
+ {
+ case EbtImage2D:
+ case EbtIImage2D:
+ case EbtUImage2D:
+ return true;
+ case EbtImage3D:
+ case EbtIImage3D:
+ case EbtUImage3D:
+ case EbtImage2DArray:
+ case EbtIImage2DArray:
+ case EbtUImage2DArray:
+ case EbtImageCube:
+ case EbtIImageCube:
+ case EbtUImageCube:
+ return false;
+ default:
+ assert(!IsImage(type));
+ }
+
+ return false;
+}
+
+inline bool IsImage3D(TBasicType type)
+{
+ switch (type)
+ {
+ case EbtImage3D:
+ case EbtIImage3D:
+ case EbtUImage3D:
+ return true;
+ case EbtImage2D:
+ case EbtIImage2D:
+ case EbtUImage2D:
+ case EbtImage2DArray:
+ case EbtIImage2DArray:
+ case EbtUImage2DArray:
+ case EbtImageCube:
+ case EbtIImageCube:
+ case EbtUImageCube:
+ return false;
+ default:
+ assert(!IsImage(type));
+ }
+
+ return false;
+}
+
+inline bool IsImage2DArray(TBasicType type)
+{
+ switch (type)
+ {
+ case EbtImage2DArray:
+ case EbtIImage2DArray:
+ case EbtUImage2DArray:
+ return true;
+ case EbtImage2D:
+ case EbtIImage2D:
+ case EbtUImage2D:
+ case EbtImage3D:
+ case EbtIImage3D:
+ case EbtUImage3D:
+ case EbtImageCube:
+ case EbtIImageCube:
+ case EbtUImageCube:
+ return false;
+ default:
+ assert(!IsImage(type));
+ }
+
+ return false;
+}
+
+inline bool IsImageCube(TBasicType type)
+{
+ switch (type)
+ {
+ case EbtImageCube:
+ case EbtIImageCube:
+ case EbtUImageCube:
+ return true;
+ case EbtImage2D:
+ case EbtIImage2D:
+ case EbtUImage2D:
+ case EbtImage3D:
+ case EbtIImage3D:
+ case EbtUImage3D:
+ case EbtImage2DArray:
+ case EbtIImage2DArray:
+ case EbtUImage2DArray:
+ return false;
+ default:
+ assert(!IsImage(type));
}
return false;
@@ -279,7 +584,7 @@ inline bool IsInteger(TBasicType type)
inline bool SupportsPrecision(TBasicType type)
{
- return type == EbtFloat || type == EbtInt || type == EbtUInt || IsSampler(type);
+ return type == EbtFloat || type == EbtInt || type == EbtUInt || IsOpaqueType(type);
}
//
@@ -297,6 +602,7 @@ enum TQualifier
EvqVaryingIn, // readonly, fragment shaders only
EvqVaryingOut, // vertex shaders only read/write
EvqUniform, // Readonly, vertex and fragment
+ EvqBuffer, // read/write, vertex, fragment and compute shader
EvqVertexIn, // Vertex shader input
EvqFragmentOut, // Fragment shader output
@@ -311,6 +617,7 @@ enum TQualifier
// built-ins read by vertex shader
EvqInstanceID,
+ EvqVertexID,
// built-ins written by vertex shader
EvqPosition,
@@ -331,24 +638,77 @@ enum TQualifier
EvqSecondaryFragColorEXT, // EXT_blend_func_extended
EvqSecondaryFragDataEXT, // EXT_blend_func_extended
+ EvqViewIDOVR, // OVR_multiview
+ EvqViewportIndex, // gl_ViewportIndex
+
// built-ins written by the shader_framebuffer_fetch extension(s)
EvqLastFragColor,
EvqLastFragData,
// GLSL ES 3.0 vertex output and fragment input
- EvqSmooth, // Incomplete qualifier, smooth is the default
- EvqFlat, // Incomplete qualifier
- EvqSmoothOut = EvqSmooth,
- EvqFlatOut = EvqFlat,
+ EvqSmooth, // Incomplete qualifier, smooth is the default
+ EvqFlat, // Incomplete qualifier
+ EvqCentroid, // Incomplete qualifier
+ EvqSmoothOut,
+ EvqFlatOut,
EvqCentroidOut, // Implies smooth
EvqSmoothIn,
EvqFlatIn,
EvqCentroidIn, // Implies smooth
+ // GLSL ES 3.1 compute shader special variables
+ EvqShared,
+ EvqComputeIn,
+ EvqNumWorkGroups,
+ EvqWorkGroupSize,
+ EvqWorkGroupID,
+ EvqLocalInvocationID,
+ EvqGlobalInvocationID,
+ EvqLocalInvocationIndex,
+
+ // GLSL ES 3.1 memory qualifiers
+ EvqReadOnly,
+ EvqWriteOnly,
+ EvqCoherent,
+ EvqRestrict,
+ EvqVolatile,
+
+ // GLSL ES 3.1 extension OES_geometry_shader qualifiers
+ EvqGeometryIn,
+ EvqGeometryOut,
+ EvqPerVertexIn, // gl_in
+ EvqPrimitiveIDIn, // gl_PrimitiveIDIn
+ EvqInvocationID, // gl_InvocationID
+ EvqPrimitiveID, // gl_PrimitiveID
+ EvqLayer, // gl_Layer
+
// end of list
EvqLast
};
+inline bool IsQualifierUnspecified(TQualifier qualifier)
+{
+ return (qualifier == EvqTemporary || qualifier == EvqGlobal);
+}
+
+enum TLayoutImageInternalFormat
+{
+ EiifUnspecified,
+ EiifRGBA32F,
+ EiifRGBA16F,
+ EiifR32F,
+ EiifRGBA32UI,
+ EiifRGBA16UI,
+ EiifRGBA8UI,
+ EiifR32UI,
+ EiifRGBA32I,
+ EiifRGBA16I,
+ EiifRGBA8I,
+ EiifR32I,
+ EiifRGBA8,
+ EiifRGBA8_SNORM
+};
+
enum TLayoutMatrixPacking
{
EmpUnspecified,
@@ -361,36 +721,165 @@ enum TLayoutBlockStorage
EbsUnspecified,
EbsShared,
EbsPacked,
- EbsStd140
+ EbsStd140,
+ EbsStd430
+};
+
+enum TYuvCscStandardEXT
+{
+ EycsUndefined,
+ EycsItu601,
+ EycsItu601FullRange,
+ EycsItu709
+};
+
+enum TLayoutPrimitiveType
+{
+ EptUndefined,
+ EptPoints,
+ EptLines,
+ EptLinesAdjacency,
+ EptTriangles,
+ EptTrianglesAdjacency,
+ EptLineStrip,
+ EptTriangleStrip
};
struct TLayoutQualifier
{
+ // Must have a trivial default constructor since it is used in YYSTYPE.
+ TLayoutQualifier() = default;
+
+ constexpr static TLayoutQualifier Create() { return TLayoutQualifier(0); }
+
+ bool isEmpty() const
+ {
+ return location == -1 && binding == -1 && offset == -1 && numViews == -1 && yuv == false &&
+ matrixPacking == EmpUnspecified && blockStorage == EbsUnspecified &&
+ !localSize.isAnyValueSet() && imageInternalFormat == EiifUnspecified &&
+ primitiveType == EptUndefined && invocations == 0 && maxVertices == -1;
+ }
+
+ bool isCombinationValid() const
+ {
+ bool workSizeSpecified = localSize.isAnyValueSet();
+ bool numViewsSet = (numViews != -1);
+ bool geometryShaderSpecified =
+ (primitiveType != EptUndefined) || (invocations != 0) || (maxVertices != -1);
+ bool otherLayoutQualifiersSpecified =
+ (location != -1 || binding != -1 || matrixPacking != EmpUnspecified ||
+ blockStorage != EbsUnspecified || imageInternalFormat != EiifUnspecified);
+
+ // we can have either the work group size specified, or number of views,
+ // or yuv layout qualifier, or the other layout qualifiers.
+ return (workSizeSpecified ? 1 : 0) + (numViewsSet ? 1 : 0) + (yuv ? 1 : 0) +
+ (otherLayoutQualifiersSpecified ? 1 : 0) + (geometryShaderSpecified ? 1 : 0) <=
+ 1;
+ }
+
+ bool isLocalSizeEqual(const sh::WorkGroupSize &localSizeIn) const
+ {
+ return localSize.isWorkGroupSizeMatching(localSizeIn);
+ }
+
int location;
+ unsigned int locationsSpecified;
TLayoutMatrixPacking matrixPacking;
TLayoutBlockStorage blockStorage;
- static TLayoutQualifier create()
- {
- TLayoutQualifier layoutQualifier;
+ // Compute shader layout qualifiers.
+ sh::WorkGroupSize localSize;
+
+ int binding;
+ int offset;
+
+ // Image format layout qualifier
+ TLayoutImageInternalFormat imageInternalFormat;
+
+ // OVR_multiview num_views.
+ int numViews;
+
+ // EXT_YUV_target yuv layout qualifier.
+ bool yuv;
- layoutQualifier.location = -1;
- layoutQualifier.matrixPacking = EmpUnspecified;
- layoutQualifier.blockStorage = EbsUnspecified;
+ // OES_geometry_shader layout qualifiers.
+ TLayoutPrimitiveType primitiveType;
+ int invocations;
+ int maxVertices;
- return layoutQualifier;
+ private:
+ explicit constexpr TLayoutQualifier(int /*placeholder*/)
+ : location(-1),
+ locationsSpecified(0),
+ matrixPacking(EmpUnspecified),
+ blockStorage(EbsUnspecified),
+ localSize(-1),
+ binding(-1),
+ offset(-1),
+ imageInternalFormat(EiifUnspecified),
+ numViews(-1),
+ yuv(false),
+ primitiveType(EptUndefined),
+ invocations(0),
+ maxVertices(-1)
+ {
}
+};
+
+struct TMemoryQualifier
+{
+ // Must have a trivial default constructor since it is used in YYSTYPE.
+ TMemoryQualifier() = default;
bool isEmpty() const
{
- return location == -1 && matrixPacking == EmpUnspecified && blockStorage == EbsUnspecified;
+ return !readonly && !writeonly && !coherent && !restrictQualifier && !volatileQualifier;
+ }
+
+ constexpr static TMemoryQualifier Create() { return TMemoryQualifier(0); }
+
+ // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
+ // An image can be qualified as both readonly and writeonly. It still can be can be used with
+ // imageSize().
+ bool readonly;
+ bool writeonly;
+ bool coherent;
+
+ // restrict and volatile are reserved keywords in C/C++
+ bool restrictQualifier;
+ bool volatileQualifier;
+
+ private:
+ explicit constexpr TMemoryQualifier(int /*placeholder*/)
+ : readonly(false),
+ writeonly(false),
+ coherent(false),
+ restrictQualifier(false),
+ volatileQualifier(false)
+ {
}
};
+inline const char *getWorkGroupSizeString(size_t dimension)
+{
+ switch (dimension)
+ {
+ case 0u:
+ return "local_size_x";
+ case 1u:
+ return "local_size_y";
+ case 2u:
+ return "local_size_z";
+ default:
+ UNREACHABLE();
+ return "dimension out of bounds";
+ }
+}
+
//
-// This is just for debug print out, carried along with the definitions above.
+// This is just for debug and error message print out, carried along with the definitions above.
//
-inline const char* getQualifierString(TQualifier q)
+inline const char *getQualifierString(TQualifier q)
{
// clang-format off
switch(q)
@@ -402,6 +891,7 @@ inline const char* getQualifierString(TQualifier q)
case EvqVaryingIn: return "varying";
case EvqVaryingOut: return "varying";
case EvqUniform: return "uniform";
+ case EvqBuffer: return "buffer";
case EvqVertexIn: return "in";
case EvqFragmentOut: return "out";
case EvqVertexOut: return "out";
@@ -411,6 +901,7 @@ inline const char* getQualifierString(TQualifier q)
case EvqInOut: return "inout";
case EvqConstReadOnly: return "const";
case EvqInstanceID: return "InstanceID";
+ case EvqVertexID: return "VertexID";
case EvqPosition: return "Position";
case EvqPointSize: return "PointSize";
case EvqFragCoord: return "FragCoord";
@@ -422,54 +913,161 @@ inline const char* getQualifierString(TQualifier q)
case EvqFragDepth: return "FragDepth";
case EvqSecondaryFragColorEXT: return "SecondaryFragColorEXT";
case EvqSecondaryFragDataEXT: return "SecondaryFragDataEXT";
+ case EvqViewIDOVR: return "ViewIDOVR";
+ case EvqViewportIndex: return "ViewportIndex";
+ case EvqLayer: return "Layer";
case EvqLastFragColor: return "LastFragColor";
case EvqLastFragData: return "LastFragData";
case EvqSmoothOut: return "smooth out";
- case EvqCentroidOut: return "centroid out";
+ case EvqCentroidOut: return "smooth centroid out";
case EvqFlatOut: return "flat out";
case EvqSmoothIn: return "smooth in";
case EvqFlatIn: return "flat in";
- case EvqCentroidIn: return "centroid in";
+ case EvqCentroidIn: return "smooth centroid in";
+ case EvqCentroid: return "centroid";
+ case EvqFlat: return "flat";
+ case EvqSmooth: return "smooth";
+ case EvqShared: return "shared";
+ case EvqComputeIn: return "in";
+ case EvqNumWorkGroups: return "NumWorkGroups";
+ case EvqWorkGroupSize: return "WorkGroupSize";
+ case EvqWorkGroupID: return "WorkGroupID";
+ case EvqLocalInvocationID: return "LocalInvocationID";
+ case EvqGlobalInvocationID: return "GlobalInvocationID";
+ case EvqLocalInvocationIndex: return "LocalInvocationIndex";
+ case EvqReadOnly: return "readonly";
+ case EvqWriteOnly: return "writeonly";
+ case EvqGeometryIn: return "in";
+ case EvqGeometryOut: return "out";
+ case EvqPerVertexIn: return "gl_in";
default: UNREACHABLE(); return "unknown qualifier";
}
// clang-format on
}
-inline const char* getMatrixPackingString(TLayoutMatrixPacking mpq)
+inline const char *getMatrixPackingString(TLayoutMatrixPacking mpq)
{
switch (mpq)
{
- case EmpUnspecified: return "mp_unspecified";
- case EmpRowMajor: return "row_major";
- case EmpColumnMajor: return "column_major";
- default: UNREACHABLE(); return "unknown matrix packing";
+ case EmpUnspecified:
+ return "mp_unspecified";
+ case EmpRowMajor:
+ return "row_major";
+ case EmpColumnMajor:
+ return "column_major";
+ default:
+ UNREACHABLE();
+ return "unknown matrix packing";
}
}
-inline const char* getBlockStorageString(TLayoutBlockStorage bsq)
+inline const char *getBlockStorageString(TLayoutBlockStorage bsq)
{
switch (bsq)
{
- case EbsUnspecified: return "bs_unspecified";
- case EbsShared: return "shared";
- case EbsPacked: return "packed";
- case EbsStd140: return "std140";
- default: UNREACHABLE(); return "unknown block storage";
+ case EbsUnspecified:
+ return "bs_unspecified";
+ case EbsShared:
+ return "shared";
+ case EbsPacked:
+ return "packed";
+ case EbsStd140:
+ return "std140";
+ case EbsStd430:
+ return "std430";
+ default:
+ UNREACHABLE();
+ return "unknown block storage";
}
}
-inline const char* getInterpolationString(TQualifier q)
+inline const char *getImageInternalFormatString(TLayoutImageInternalFormat iifq)
{
- switch(q)
+ switch (iifq)
+ {
+ case EiifRGBA32F:
+ return "rgba32f";
+ case EiifRGBA16F:
+ return "rgba16f";
+ case EiifR32F:
+ return "r32f";
+ case EiifRGBA32UI:
+ return "rgba32ui";
+ case EiifRGBA16UI:
+ return "rgba16ui";
+ case EiifRGBA8UI:
+ return "rgba8ui";
+ case EiifR32UI:
+ return "r32ui";
+ case EiifRGBA32I:
+ return "rgba32i";
+ case EiifRGBA16I:
+ return "rgba16i";
+ case EiifRGBA8I:
+ return "rgba8i";
+ case EiifR32I:
+ return "r32i";
+ case EiifRGBA8:
+ return "rgba8";
+ case EiifRGBA8_SNORM:
+ return "rgba8_snorm";
+ default:
+ UNREACHABLE();
+ return "unknown internal image format";
+ }
+}
+
+inline TYuvCscStandardEXT getYuvCscStandardEXT(const std::string &str)
+{
+ if (str == "itu_601")
+ return EycsItu601;
+ else if (str == "itu_601_full_range")
+ return EycsItu601FullRange;
+ else if (str == "itu_709")
+ return EycsItu709;
+ return EycsUndefined;
+}
+
+inline const char *getYuvCscStandardEXTString(TYuvCscStandardEXT ycsq)
+{
+ switch (ycsq)
+ {
+ case EycsItu601:
+ return "itu_601";
+ case EycsItu601FullRange:
+ return "itu_601_full_range";
+ case EycsItu709:
+ return "itu_709";
+ default:
+ UNREACHABLE();
+ return "unknown color space conversion standard";
+ }
+}
+
+inline const char *getGeometryShaderPrimitiveTypeString(TLayoutPrimitiveType primitiveType)
+{
+ switch (primitiveType)
{
- case EvqSmoothOut: return "smooth"; break;
- case EvqCentroidOut: return "centroid"; break;
- case EvqFlatOut: return "flat"; break;
- case EvqSmoothIn: return "smooth"; break;
- case EvqCentroidIn: return "centroid"; break;
- case EvqFlatIn: return "flat"; break;
- default: UNREACHABLE(); return "unknown interpolation";
+ case EptPoints:
+ return "points";
+ case EptLines:
+ return "lines";
+ case EptTriangles:
+ return "triangles";
+ case EptLinesAdjacency:
+ return "lines_adjacency";
+ case EptTrianglesAdjacency:
+ return "triangles_adjacency";
+ case EptLineStrip:
+ return "line_strip";
+ case EptTriangleStrip:
+ return "triangle_strip";
+ default:
+ UNREACHABLE();
+ return "unknown geometry shader primitive type";
}
}
-#endif // COMPILER_TRANSLATOR_BASETYPES_H_
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_BASETYPES_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp b/src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp
new file mode 100644
index 0000000000..d6a1e025de
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp
@@ -0,0 +1,107 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// BreakVariableAliasingInInnerLoops.h: To optimize simple assignments, the HLSL compiler frontend
+// may record a variable as aliasing another. Sometimes the alias information gets garbled
+// so we work around this issue by breaking the aliasing chain in inner loops.
+
+#include "BreakVariableAliasingInInnerLoops.h"
+
+#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/IntermTraverse.h"
+
+// A HLSL compiler developer gave us more details on the root cause and the workaround needed:
+// The root problem is that if the HLSL compiler is applying aliasing information even on
+// incomplete simulations (in this case, a single pass). The bug is triggered by an assignment
+// that comes from a series of assignments, possibly with swizzled or ternary operators with
+// known conditionals, where the source is before the loop.
+// So, a workaround is to add a +0 term to variables the first time they are assigned to in
+// an inner loop (if they are declared in an outside scope, otherwise there is no need).
+// This will break the aliasing chain.
+
+// For simplicity here we add a +0 to any assignment that is in at least two nested loops. Because
+// the bug only shows up with swizzles, and ternary assignment, whole array or whole structure
+// assignment don't need a workaround.
+
+namespace sh
+{
+
+namespace
+{
+
+class AliasingBreaker : public TIntermTraverser
+{
+ public:
+ AliasingBreaker() : TIntermTraverser(true, false, true) {}
+
+ protected:
+ bool visitBinary(Visit visit, TIntermBinary *binary)
+ {
+ if (visit != PreVisit)
+ {
+ return false;
+ }
+
+ if (mLoopLevel < 2 || !binary->isAssignment())
+ {
+ return true;
+ }
+
+ TIntermTyped *B = binary->getRight();
+ TType type = B->getType();
+
+ if (!type.isScalar() && !type.isVector() && !type.isMatrix())
+ {
+ return true;
+ }
+
+ if (type.isArray() || IsSampler(type.getBasicType()))
+ {
+ return true;
+ }
+
+ // We have a scalar / vector / matrix assignment with loop depth 2.
+ // Transform it from
+ // A = B
+ // to
+ // A = (B + typeof<B>(0));
+
+ TIntermBinary *bPlusZero = new TIntermBinary(EOpAdd, B, CreateZeroNode(type));
+ bPlusZero->setLine(B->getLine());
+
+ binary->replaceChildNode(B, bPlusZero);
+
+ return true;
+ }
+
+ bool visitLoop(Visit visit, TIntermLoop *loop)
+ {
+ if (visit == PreVisit)
+ {
+ mLoopLevel++;
+ }
+ else
+ {
+ ASSERT(mLoopLevel > 0);
+ mLoopLevel--;
+ }
+
+ return true;
+ }
+
+ private:
+ int mLoopLevel = 0;
+};
+
+} // anonymous namespace
+
+void BreakVariableAliasingInInnerLoops(TIntermNode *root)
+{
+ AliasingBreaker breaker;
+ root->traverse(&breaker);
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.h b/src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.h
new file mode 100644
index 0000000000..b1d906f919
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/BreakVariableAliasingInInnerLoops.h
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// BreakVariableAliasingInInnerLoops.h: To optimize simple assignments, the HLSL compiler frontend
+// may record a variable as aliasing another. Sometimes the alias information gets garbled
+// so we work around this issue by breaking the aliasing chain in inner loops.
+
+#ifndef COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_
+#define COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_
+
+class TIntermNode;
+
+namespace sh
+{
+
+void BreakVariableAliasingInInnerLoops(TIntermNode *root);
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp
index 0c7f149ee6..905e634fd1 100644
--- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp
@@ -4,16 +4,20 @@
// found in the LICENSE file.
//
-#include "angle_gl.h"
#include "compiler/translator/BuiltInFunctionEmulator.h"
+#include "angle_gl.h"
+#include "compiler/translator/Cache.h"
+#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/SymbolTable.h"
+namespace sh
+{
+
class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTraverser
{
public:
BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator &emulator)
- : TIntermTraverser(true, false, false),
- mEmulator(emulator)
+ : TIntermTraverser(true, false, false), mEmulator(emulator)
{
}
@@ -21,7 +25,8 @@ class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTr
{
if (visit == PreVisit)
{
- bool needToEmulate = mEmulator.SetFunctionCalled(node->getOp(), node->getOperand()->getType());
+ bool needToEmulate =
+ mEmulator.setFunctionCalled(node->getOp(), node->getOperand()->getType());
if (needToEmulate)
node->setUseEmulatedFunction();
}
@@ -32,48 +37,23 @@ class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTr
{
if (visit == PreVisit)
{
- // Here we handle all the built-in functions instead of the ones we
+ // Here we handle all the built-in functions mapped to ops, not just the ones that are
// currently identified as problematic.
- switch (node->getOp())
+ if (node->isConstructor() || node->isFunctionCall())
{
- case EOpLessThan:
- case EOpGreaterThan:
- case EOpLessThanEqual:
- case EOpGreaterThanEqual:
- case EOpVectorEqual:
- case EOpVectorNotEqual:
- case EOpMod:
- case EOpPow:
- case EOpAtan:
- case EOpMin:
- case EOpMax:
- case EOpClamp:
- case EOpMix:
- case EOpStep:
- case EOpSmoothStep:
- case EOpDistance:
- case EOpDot:
- case EOpCross:
- case EOpFaceForward:
- case EOpReflect:
- case EOpRefract:
- case EOpOuterProduct:
- case EOpMul:
- break;
- default:
- return true;
+ return true;
}
const TIntermSequence &sequence = *(node->getSequence());
- bool needToEmulate = false;
- // Right now we only handle built-in functions with two or three parameters.
+ bool needToEmulate = false;
+ // Right now we only handle built-in functions with two to four parameters.
if (sequence.size() == 2)
{
TIntermTyped *param1 = sequence[0]->getAsTyped();
TIntermTyped *param2 = sequence[1]->getAsTyped();
if (!param1 || !param2)
return true;
- needToEmulate = mEmulator.SetFunctionCalled(
- node->getOp(), param1->getType(), param2->getType());
+ needToEmulate = mEmulator.setFunctionCalled(node->getOp(), param1->getType(),
+ param2->getType());
}
else if (sequence.size() == 3)
{
@@ -82,8 +62,20 @@ class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTr
TIntermTyped *param3 = sequence[2]->getAsTyped();
if (!param1 || !param2 || !param3)
return true;
- needToEmulate = mEmulator.SetFunctionCalled(
- node->getOp(), param1->getType(), param2->getType(), param3->getType());
+ needToEmulate = mEmulator.setFunctionCalled(node->getOp(), param1->getType(),
+ param2->getType(), param3->getType());
+ }
+ else if (sequence.size() == 4)
+ {
+ TIntermTyped *param1 = sequence[0]->getAsTyped();
+ TIntermTyped *param2 = sequence[1]->getAsTyped();
+ TIntermTyped *param3 = sequence[2]->getAsTyped();
+ TIntermTyped *param4 = sequence[3]->getAsTyped();
+ if (!param1 || !param2 || !param3 || !param4)
+ return true;
+ needToEmulate =
+ mEmulator.setFunctionCalled(node->getOp(), param1->getType(), param2->getType(),
+ param3->getType(), param4->getType());
}
else
{
@@ -101,130 +93,245 @@ class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTr
};
BuiltInFunctionEmulator::BuiltInFunctionEmulator()
-{}
+{
+}
-void BuiltInFunctionEmulator::addEmulatedFunction(TOperator op, const TType *param,
- const char *emulatedFunctionDefinition)
+FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
+ const TType *param,
+ const char *emulatedFunctionDefinition)
{
- mEmulatedFunctions[FunctionId(op, param)] = std::string(emulatedFunctionDefinition);
+ FunctionId id(op, param);
+ mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
+ return id;
}
-void BuiltInFunctionEmulator::addEmulatedFunction(TOperator op, const TType *param1, const TType *param2,
- const char *emulatedFunctionDefinition)
+FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
+ const TType *param1,
+ const TType *param2,
+ const char *emulatedFunctionDefinition)
{
- mEmulatedFunctions[FunctionId(op, param1, param2)] = std::string(emulatedFunctionDefinition);
+ FunctionId id(op, param1, param2);
+ mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
+ return id;
}
-void BuiltInFunctionEmulator::addEmulatedFunction(TOperator op, const TType *param1, const TType *param2,
- const TType *param3, const char *emulatedFunctionDefinition)
+FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
+ const FunctionId &dependency,
+ TOperator op,
+ const TType *param1,
+ const TType *param2,
+ const char *emulatedFunctionDefinition)
{
- mEmulatedFunctions[FunctionId(op, param1, param2, param3)] = std::string(emulatedFunctionDefinition);
+ FunctionId id(op, param1, param2);
+ mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
+ mFunctionDependencies[id] = dependency;
+ return id;
}
-bool BuiltInFunctionEmulator::IsOutputEmpty() const
+FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
+ const TType *param1,
+ const TType *param2,
+ const TType *param3,
+ const char *emulatedFunctionDefinition)
+{
+ FunctionId id(op, param1, param2, param3);
+ mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
+ return id;
+}
+
+FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
+ const TType *param1,
+ const TType *param2,
+ const TType *param3,
+ const TType *param4,
+ const char *emulatedFunctionDefinition)
+{
+ FunctionId id(op, param1, param2, param3, param4);
+ mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
+ return id;
+}
+
+FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
+ const FunctionId &dependency,
+ TOperator op,
+ const TType *param1,
+ const TType *param2,
+ const TType *param3,
+ const TType *param4,
+ const char *emulatedFunctionDefinition)
+{
+ FunctionId id(op, param1, param2, param3, param4);
+ mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
+ mFunctionDependencies[id] = dependency;
+ return id;
+}
+
+bool BuiltInFunctionEmulator::isOutputEmpty() const
{
return (mFunctions.size() == 0);
}
-void BuiltInFunctionEmulator::OutputEmulatedFunctions(TInfoSinkBase &out) const
+void BuiltInFunctionEmulator::outputEmulatedFunctions(TInfoSinkBase &out) const
{
- for (size_t i = 0; i < mFunctions.size(); ++i)
+ for (const auto &function : mFunctions)
{
- out << mEmulatedFunctions.find(mFunctions[i])->second << "\n\n";
+ const char *body = findEmulatedFunction(function);
+ ASSERT(body);
+ out << body;
+ out << "\n\n";
}
}
-bool BuiltInFunctionEmulator::SetFunctionCalled(TOperator op, const TType &param)
+bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op, const TType &param)
{
- return SetFunctionCalled(FunctionId(op, &param));
+ return setFunctionCalled(FunctionId(op, &param));
}
-bool BuiltInFunctionEmulator::SetFunctionCalled(TOperator op, const TType &param1, const TType &param2)
+bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
+ const TType &param1,
+ const TType &param2)
{
- return SetFunctionCalled(FunctionId(op, &param1, &param2));
+ return setFunctionCalled(FunctionId(op, &param1, &param2));
}
-bool BuiltInFunctionEmulator::SetFunctionCalled(TOperator op,
- const TType &param1, const TType &param2, const TType &param3)
+bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
+ const TType &param1,
+ const TType &param2,
+ const TType &param3)
{
- return SetFunctionCalled(FunctionId(op, &param1, &param2, &param3));
+ return setFunctionCalled(FunctionId(op, &param1, &param2, &param3));
}
-bool BuiltInFunctionEmulator::SetFunctionCalled(const FunctionId &functionId)
+bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
+ const TType &param1,
+ const TType &param2,
+ const TType &param3,
+ const TType &param4)
{
- if (mEmulatedFunctions.find(functionId) != mEmulatedFunctions.end())
+ return setFunctionCalled(FunctionId(op, &param1, &param2, &param3, &param4));
+}
+
+const char *BuiltInFunctionEmulator::findEmulatedFunction(const FunctionId &functionId) const
+{
+ for (const auto &queryFunction : mQueryFunctions)
{
- for (size_t i = 0; i < mFunctions.size(); ++i)
+ const char *result = queryFunction(functionId);
+ if (result)
{
- if (mFunctions[i] == functionId)
- return true;
+ return result;
}
- // Copy the functionId if it needs to be stored, to make sure that the TType pointers inside
- // remain valid and constant.
- mFunctions.push_back(functionId.getCopy());
- return true;
}
- return false;
+
+ const auto &result = mEmulatedFunctions.find(functionId);
+ if (result != mEmulatedFunctions.end())
+ {
+ return result->second.c_str();
+ }
+
+ return nullptr;
+}
+
+bool BuiltInFunctionEmulator::setFunctionCalled(const FunctionId &functionId)
+{
+ if (!findEmulatedFunction(functionId))
+ {
+ return false;
+ }
+
+ for (size_t i = 0; i < mFunctions.size(); ++i)
+ {
+ if (mFunctions[i] == functionId)
+ return true;
+ }
+ // If the function depends on another, mark the dependency as called.
+ auto dependency = mFunctionDependencies.find(functionId);
+ if (dependency != mFunctionDependencies.end())
+ {
+ setFunctionCalled((*dependency).second);
+ }
+ // Copy the functionId if it needs to be stored, to make sure that the TType pointers inside
+ // remain valid and constant.
+ mFunctions.push_back(functionId.getCopy());
+ return true;
}
-void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation(TIntermNode *root)
+void BuiltInFunctionEmulator::markBuiltInFunctionsForEmulation(TIntermNode *root)
{
ASSERT(root);
- if (mEmulatedFunctions.empty())
+ if (mEmulatedFunctions.empty() && mQueryFunctions.empty())
return;
BuiltInFunctionEmulationMarker marker(*this);
root->traverse(&marker);
}
-void BuiltInFunctionEmulator::Cleanup()
+void BuiltInFunctionEmulator::cleanup()
{
mFunctions.clear();
+ mFunctionDependencies.clear();
+}
+
+void BuiltInFunctionEmulator::addFunctionMap(BuiltinQueryFunc queryFunc)
+{
+ mQueryFunctions.push_back(queryFunc);
+}
+
+// static
+void BuiltInFunctionEmulator::WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name)
+{
+ ASSERT(name[strlen(name) - 1] != '(');
+ out << name << "_emu";
}
-//static
-TString BuiltInFunctionEmulator::GetEmulatedFunctionName(
- const TString &name)
+FunctionId::FunctionId()
+ : mOp(EOpNull),
+ mParam1(TCache::getType(EbtVoid)),
+ mParam2(TCache::getType(EbtVoid)),
+ mParam3(TCache::getType(EbtVoid)),
+ mParam4(TCache::getType(EbtVoid))
{
- ASSERT(name[name.length() - 1] == '(');
- return "webgl_" + name.substr(0, name.length() - 1) + "_emu(";
}
-BuiltInFunctionEmulator::FunctionId::FunctionId(TOperator op, const TType *param)
+FunctionId::FunctionId(TOperator op, const TType *param)
: mOp(op),
mParam1(param),
- mParam2(new TType(EbtVoid)),
- mParam3(new TType(EbtVoid))
+ mParam2(TCache::getType(EbtVoid)),
+ mParam3(TCache::getType(EbtVoid)),
+ mParam4(TCache::getType(EbtVoid))
{
}
-BuiltInFunctionEmulator::FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2)
+FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2)
: mOp(op),
mParam1(param1),
mParam2(param2),
- mParam3(new TType(EbtVoid))
+ mParam3(TCache::getType(EbtVoid)),
+ mParam4(TCache::getType(EbtVoid))
{
}
-BuiltInFunctionEmulator::FunctionId::FunctionId(TOperator op,
- const TType *param1, const TType *param2, const TType *param3)
- : mOp(op),
- mParam1(param1),
- mParam2(param2),
- mParam3(param3)
+FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3)
+ : mOp(op), mParam1(param1), mParam2(param2), mParam3(param3), mParam4(TCache::getType(EbtVoid))
{
}
-bool BuiltInFunctionEmulator::FunctionId::operator==(const BuiltInFunctionEmulator::FunctionId &other) const
+FunctionId::FunctionId(TOperator op,
+ const TType *param1,
+ const TType *param2,
+ const TType *param3,
+ const TType *param4)
+ : mOp(op), mParam1(param1), mParam2(param2), mParam3(param3), mParam4(param4)
{
- return (mOp == other.mOp &&
- *mParam1 == *other.mParam1 &&
- *mParam2 == *other.mParam2 &&
- *mParam3 == *other.mParam3);
}
-bool BuiltInFunctionEmulator::FunctionId::operator<(const BuiltInFunctionEmulator::FunctionId &other) const
+bool FunctionId::operator==(const FunctionId &other) const
+{
+ return (mOp == other.mOp && *mParam1 == *other.mParam1 && *mParam2 == *other.mParam2 &&
+ *mParam3 == *other.mParam3 && *mParam4 == *other.mParam4);
+}
+
+bool FunctionId::operator<(const FunctionId &other) const
{
if (mOp != other.mOp)
return mOp < other.mOp;
@@ -233,11 +340,16 @@ bool BuiltInFunctionEmulator::FunctionId::operator<(const BuiltInFunctionEmulato
if (*mParam2 != *other.mParam2)
return *mParam2 < *other.mParam2;
if (*mParam3 != *other.mParam3)
- return *mParam3 < *other.mParam3;
- return false; // all fields are equal
+ return *mParam3 < *other.mParam3;
+ if (*mParam4 != *other.mParam4)
+ return *mParam4 < *other.mParam4;
+ return false; // all fields are equal
}
-BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::FunctionId::getCopy() const
+FunctionId FunctionId::getCopy() const
{
- return FunctionId(mOp, new TType(*mParam1), new TType(*mParam2), new TType(*mParam3));
+ return FunctionId(mOp, new TType(*mParam1), new TType(*mParam2), new TType(*mParam3),
+ new TType(*mParam4));
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h
index 6976edfd57..5f15f66224 100644
--- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h
+++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h
@@ -9,77 +9,175 @@
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/ParamType.h"
+
+namespace sh
+{
+
+struct MiniFunctionId
+{
+ constexpr MiniFunctionId(TOperator op = EOpNull,
+ ParamType paramType1 = ParamType::Void,
+ ParamType paramType2 = ParamType::Void,
+ ParamType paramType3 = ParamType::Void,
+ ParamType paramType4 = ParamType::Void)
+ : op(op),
+ paramType1(paramType1),
+ paramType2(paramType2),
+ paramType3(paramType3),
+ paramType4(paramType4)
+ {
+ }
+
+ TOperator op;
+ ParamType paramType1;
+ ParamType paramType2;
+ ParamType paramType3;
+ ParamType paramType4;
+};
+
+class FunctionId final
+{
+ public:
+ FunctionId();
+ FunctionId(TOperator op, const TType *param);
+ FunctionId(TOperator op, const TType *param1, const TType *param2);
+ FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3);
+ FunctionId(TOperator op,
+ const TType *param1,
+ const TType *param2,
+ const TType *param3,
+ const TType *param4);
+
+ FunctionId(const FunctionId &) = default;
+ FunctionId &operator=(const FunctionId &) = default;
+
+ bool operator==(const FunctionId &other) const;
+ bool operator<(const FunctionId &other) const;
+
+ FunctionId getCopy() const;
+
+ private:
+ friend bool operator==(const MiniFunctionId &miniId, const FunctionId &functionId);
+ TOperator mOp;
+
+ // The memory that these TType objects use is freed by PoolAllocator. The
+ // BuiltInFunctionEmulator's lifetime can extend until after the memory pool is freed, but
+ // that's not an issue since this class never destructs these objects.
+ const TType *mParam1;
+ const TType *mParam2;
+ const TType *mParam3;
+ const TType *mParam4;
+};
+
+inline bool operator==(ParamType paramType, const TType *type)
+{
+ return SameParamType(paramType, type->getBasicType(), type->getNominalSize(),
+ type->getSecondarySize());
+}
+
+inline bool operator==(const MiniFunctionId &miniId, const FunctionId &functionId)
+{
+ return miniId.op == functionId.mOp && miniId.paramType1 == functionId.mParam1 &&
+ miniId.paramType2 == functionId.mParam2 && miniId.paramType3 == functionId.mParam3 &&
+ miniId.paramType4 == functionId.mParam4;
+}
+
+using BuiltinQueryFunc = const char *(const FunctionId &);
//
-// This class decides which built-in functions need to be replaced with the
-// emulated ones.
-// It can be used to work around driver bugs or implement functions that are
-// not natively implemented on a specific platform.
+// This class decides which built-in functions need to be replaced with the emulated ones. It can be
+// used to work around driver bugs or implement functions that are not natively implemented on a
+// specific platform.
//
class BuiltInFunctionEmulator
{
public:
BuiltInFunctionEmulator();
- void MarkBuiltInFunctionsForEmulation(TIntermNode *root);
+ void markBuiltInFunctionsForEmulation(TIntermNode *root);
- void Cleanup();
+ void cleanup();
- // "name(" becomes "webgl_name_emu(".
- static TString GetEmulatedFunctionName(const TString &name);
+ // "name" gets written as "name_emu".
+ static void WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name);
- bool IsOutputEmpty() const;
+ bool isOutputEmpty() const;
- // Output function emulation definition. This should be before any other
- // shader source.
- void OutputEmulatedFunctions(TInfoSinkBase &out) const;
+ // Output function emulation definition. This should be before any other shader source.
+ void outputEmulatedFunctions(TInfoSinkBase &out) const;
// Add functions that need to be emulated.
- void addEmulatedFunction(TOperator op, const TType *param, const char *emulatedFunctionDefinition);
- void addEmulatedFunction(TOperator op, const TType *param1, const TType *param2,
- const char *emulatedFunctionDefinition);
- void addEmulatedFunction(TOperator op, const TType *param1, const TType *param2, const TType *param3,
- const char *emulatedFunctionDefinition);
+ FunctionId addEmulatedFunction(TOperator op,
+ const TType *param,
+ const char *emulatedFunctionDefinition);
+ FunctionId addEmulatedFunction(TOperator op,
+ const TType *param1,
+ const TType *param2,
+ const char *emulatedFunctionDefinition);
+ FunctionId addEmulatedFunction(TOperator op,
+ const TType *param1,
+ const TType *param2,
+ const TType *param3,
+ const char *emulatedFunctionDefinition);
+ FunctionId addEmulatedFunction(TOperator op,
+ const TType *param1,
+ const TType *param2,
+ const TType *param3,
+ const TType *param4,
+ const char *emulatedFunctionDefinition);
+
+ FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency,
+ TOperator op,
+ const TType *param1,
+ const TType *param2,
+ const char *emulatedFunctionDefinition);
+ FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency,
+ TOperator op,
+ const TType *param1,
+ const TType *param2,
+ const TType *param3,
+ const TType *param4,
+ const char *emulatedFunctionDefinition);
+
+ void addFunctionMap(BuiltinQueryFunc queryFunc);
private:
class BuiltInFunctionEmulationMarker;
- // Records that a function is called by the shader and might need to be
- // emulated. If the function is not in mEmulatedFunctions, this becomes a
- // no-op. Returns true if the function call needs to be replaced with an
- // emulated one.
- bool SetFunctionCalled(TOperator op, const TType &param);
- bool SetFunctionCalled(TOperator op, const TType &param1, const TType &param2);
- bool SetFunctionCalled(TOperator op, const TType &param1, const TType &param2, const TType &param3);
-
- class FunctionId {
- public:
- FunctionId(TOperator op, const TType *param);
- FunctionId(TOperator op, const TType *param1, const TType *param2);
- FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3);
-
- bool operator==(const FunctionId &other) const;
- bool operator<(const FunctionId &other) const;
-
- FunctionId getCopy() const;
- private:
- TOperator mOp;
-
- // The memory that these TType objects use is freed by PoolAllocator. The BuiltInFunctionEmulator's lifetime
- // can extend until after the memory pool is freed, but that's not an issue since this class never destructs
- // these objects.
- const TType *mParam1;
- const TType *mParam2;
- const TType *mParam3;
- };
-
- bool SetFunctionCalled(const FunctionId &functionId);
+ // Records that a function is called by the shader and might need to be emulated. If the
+ // function is not in mEmulatedFunctions, this becomes a no-op. Returns true if the function
+ // call needs to be replaced with an emulated one.
+ bool setFunctionCalled(TOperator op, const TType &param);
+ bool setFunctionCalled(TOperator op, const TType &param1, const TType &param2);
+ bool setFunctionCalled(TOperator op,
+ const TType &param1,
+ const TType &param2,
+ const TType &param3);
+ bool setFunctionCalled(TOperator op,
+ const TType &param1,
+ const TType &param2,
+ const TType &param3,
+ const TType &param4);
+
+ bool setFunctionCalled(const FunctionId &functionId);
+
+ const char *findEmulatedFunction(const FunctionId &functionId) const;
// Map from function id to emulated function definition
std::map<FunctionId, std::string> mEmulatedFunctions;
+ // Map from dependent functions to their dependencies. This structure allows each function to
+ // have at most one dependency.
+ std::map<FunctionId, FunctionId> mFunctionDependencies;
+
// Called function ids
std::vector<FunctionId> mFunctions;
+
+ // Constexpr function tables.
+ std::vector<BuiltinQueryFunc *> mQueryFunctions;
};
+} // namespace sh
+
#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp
index 098560d110..27ee04da35 100644
--- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp
@@ -11,47 +11,147 @@
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/VersionGLSL.h"
-void InitBuiltInFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, sh::GLenum shaderType)
+namespace sh
{
- // we use macros here instead of function definitions to work around more GLSL
- // compiler bugs, in particular on NVIDIA hardware on Mac OSX. Macros are
- // problematic because if the argument has side-effects they will be repeatedly
- // evaluated. This is unlikely to show up in real shaders, but is something to
- // consider.
+
+void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
+ sh::GLenum shaderType)
+{
+ if (shaderType == GL_VERTEX_SHADER)
+ {
+ const TType *int1 = TCache::getType(EbtInt);
+ emu->addEmulatedFunction(EOpAbs, int1, "int abs_emu(int x) { return x * sign(x); }");
+ }
+}
+
+void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
+ int targetGLSLVersion)
+{
+ // isnan() is supported since GLSL 1.3.
+ if (targetGLSLVersion < GLSL_VERSION_130)
+ return;
const TType *float1 = TCache::getType(EbtFloat);
const TType *float2 = TCache::getType(EbtFloat, 2);
const TType *float3 = TCache::getType(EbtFloat, 3);
const TType *float4 = TCache::getType(EbtFloat, 4);
- if (shaderType == GL_FRAGMENT_SHADER)
+ // !(x > 0.0 || x < 0.0 || x == 0.0) will be optimized and always equal to false.
+ emu->addEmulatedFunction(
+ EOpIsNan, float1,
+ "bool isnan_emu(float x) { return (x > 0.0 || x < 0.0) ? false : x != 0.0; }");
+ emu->addEmulatedFunction(
+ EOpIsNan, float2,
+ "bvec2 isnan_emu(vec2 x)\n"
+ "{\n"
+ " bvec2 isnan;\n"
+ " for (int i = 0; i < 2; i++)\n"
+ " {\n"
+ " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
+ " }\n"
+ " return isnan;\n"
+ "}\n");
+ emu->addEmulatedFunction(
+ EOpIsNan, float3,
+ "bvec3 isnan_emu(vec3 x)\n"
+ "{\n"
+ " bvec3 isnan;\n"
+ " for (int i = 0; i < 3; i++)\n"
+ " {\n"
+ " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
+ " }\n"
+ " return isnan;\n"
+ "}\n");
+ emu->addEmulatedFunction(
+ EOpIsNan, float4,
+ "bvec4 isnan_emu(vec4 x)\n"
+ "{\n"
+ " bvec4 isnan;\n"
+ " for (int i = 0; i < 4; i++)\n"
+ " {\n"
+ " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
+ " }\n"
+ " return isnan;\n"
+ "}\n");
+}
+
+void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu)
+{
+ const TType *float1 = TCache::getType(EbtFloat);
+ auto floatFuncId = emu->addEmulatedFunction(
+ EOpAtan, float1, float1,
+ "emu_precision float atan_emu(emu_precision float y, emu_precision "
+ "float x)\n"
+ "{\n"
+ " if (x > 0.0) return atan(y / x);\n"
+ " else if (x < 0.0 && y >= 0.0) return atan(y / x) + 3.14159265;\n"
+ " else if (x < 0.0 && y < 0.0) return atan(y / x) - 3.14159265;\n"
+ " else return 1.57079632 * sign(y);\n"
+ "}\n");
+ for (int dim = 2; dim <= 4; ++dim)
{
- emu->addEmulatedFunction(EOpCos, float1, "webgl_emu_precision float webgl_cos_emu(webgl_emu_precision float a) { return cos(a); }");
- emu->addEmulatedFunction(EOpCos, float2, "webgl_emu_precision vec2 webgl_cos_emu(webgl_emu_precision vec2 a) { return cos(a); }");
- emu->addEmulatedFunction(EOpCos, float3, "webgl_emu_precision vec3 webgl_cos_emu(webgl_emu_precision vec3 a) { return cos(a); }");
- emu->addEmulatedFunction(EOpCos, float4, "webgl_emu_precision vec4 webgl_cos_emu(webgl_emu_precision vec4 a) { return cos(a); }");
+ const TType *floatVec = TCache::getType(EbtFloat, static_cast<unsigned char>(dim));
+ std::stringstream ss;
+ ss << "emu_precision vec" << dim << " atan_emu(emu_precision vec" << dim
+ << " y, emu_precision vec" << dim << " x)\n"
+ << "{\n"
+ " return vec"
+ << dim << "(";
+ for (int i = 0; i < dim; ++i)
+ {
+ ss << "atan_emu(y[" << i << "], x[" << i << "])";
+ if (i < dim - 1)
+ {
+ ss << ", ";
+ }
+ }
+ ss << ");\n"
+ "}\n";
+ emu->addEmulatedFunctionWithDependency(floatFuncId, EOpAtan, floatVec, floatVec,
+ ss.str().c_str());
}
- emu->addEmulatedFunction(EOpDistance, float1, float1, "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))");
- emu->addEmulatedFunction(EOpDot, float1, float1, "#define webgl_dot_emu(x, y) ((x) * (y))");
- emu->addEmulatedFunction(EOpLength, float1, "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))");
- emu->addEmulatedFunction(EOpNormalize, float1, "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))");
- emu->addEmulatedFunction(EOpReflect, float1, float1, "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))");
}
// Emulate built-in functions missing from GLSL 1.30 and higher
-void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator *emu, sh::GLenum shaderType,
+void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator *emu,
+ sh::GLenum shaderType,
int targetGLSLVersion)
{
+ // Emulate packUnorm2x16 and unpackUnorm2x16 (GLSL 4.10)
+ if (targetGLSLVersion < GLSL_VERSION_410)
+ {
+ const TType *float2 = TCache::getType(EbtFloat, 2);
+ const TType *uint1 = TCache::getType(EbtUInt);
+
+ // clang-format off
+ emu->addEmulatedFunction(EOpPackUnorm2x16, float2,
+ "uint packUnorm2x16_emu(vec2 v)\n"
+ "{\n"
+ " int x = int(round(clamp(v.x, 0.0, 1.0) * 65535.0));\n"
+ " int y = int(round(clamp(v.y, 0.0, 1.0) * 65535.0));\n"
+ " return uint((y << 16) | (x & 0xFFFF));\n"
+ "}\n");
+
+ emu->addEmulatedFunction(EOpUnpackUnorm2x16, uint1,
+ "vec2 unpackUnorm2x16_emu(uint u)\n"
+ "{\n"
+ " float x = float(u & 0xFFFFu) / 65535.0;\n"
+ " float y = float(u >> 16) / 65535.0;\n"
+ " return vec2(x, y);\n"
+ "}\n");
+ // clang-format on
+ }
+
// Emulate packSnorm2x16, packHalf2x16, unpackSnorm2x16, and unpackHalf2x16 (GLSL 4.20)
// by using floatBitsToInt, floatBitsToUint, intBitsToFloat, and uintBitsToFloat (GLSL 3.30).
if (targetGLSLVersion >= GLSL_VERSION_330 && targetGLSLVersion < GLSL_VERSION_420)
{
const TType *float2 = TCache::getType(EbtFloat, 2);
- const TType *uint1 = TCache::getType(EbtUInt);
+ const TType *uint1 = TCache::getType(EbtUInt);
// clang-format off
emu->addEmulatedFunction(EOpPackSnorm2x16, float2,
- "uint webgl_packSnorm2x16_emu(vec2 v)\n"
+ "uint packSnorm2x16_emu(vec2 v)\n"
"{\n"
" #if defined(GL_ARB_shading_language_packing)\n"
" return packSnorm2x16(v);\n"
@@ -63,28 +163,28 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
"}\n");
emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1,
"#if !defined(GL_ARB_shading_language_packing)\n"
- " float webgl_fromSnorm(uint x)\n"
+ " float fromSnorm(uint x)\n"
" {\n"
" int xi = (int(x) & 0x7FFF) - (int(x) & 0x8000);\n"
" return clamp(float(xi) / 32767.0, -1.0, 1.0);\n"
" }\n"
"#endif\n"
"\n"
- "vec2 webgl_unpackSnorm2x16_emu(uint u)\n"
+ "vec2 unpackSnorm2x16_emu(uint u)\n"
"{\n"
" #if defined(GL_ARB_shading_language_packing)\n"
" return unpackSnorm2x16(u);\n"
" #else\n"
" uint y = (u >> 16);\n"
" uint x = u;\n"
- " return vec2(webgl_fromSnorm(x), webgl_fromSnorm(y));\n"
+ " return vec2(fromSnorm(x), fromSnorm(y));\n"
" #endif\n"
"}\n");
- // Functions uint webgl_f32tof16(float val) and float webgl_f16tof32(uint val) are
+ // Functions uint f32tof16(float val) and float f16tof32(uint val) are
// based on the OpenGL redbook Appendix Session "Floating-Point Formats Used in OpenGL".
emu->addEmulatedFunction(EOpPackHalf2x16, float2,
"#if !defined(GL_ARB_shading_language_packing)\n"
- " uint webgl_f32tof16(float val)\n"
+ " uint f32tof16(float val)\n"
" {\n"
" uint f32 = floatBitsToUint(val);\n"
" uint f16 = 0u;\n"
@@ -119,19 +219,19 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
" }\n"
"#endif\n"
"\n"
- "uint webgl_packHalf2x16_emu(vec2 v)\n"
+ "uint packHalf2x16_emu(vec2 v)\n"
"{\n"
" #if defined(GL_ARB_shading_language_packing)\n"
" return packHalf2x16(v);\n"
" #else\n"
- " uint x = webgl_f32tof16(v.x);\n"
- " uint y = webgl_f32tof16(v.y);\n"
+ " uint x = f32tof16(v.x);\n"
+ " uint y = f32tof16(v.y);\n"
" return (y << 16) | x;\n"
" #endif\n"
"}\n");
emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1,
"#if !defined(GL_ARB_shading_language_packing)\n"
- " float webgl_f16tof32(uint val)\n"
+ " float f16tof32(uint val)\n"
" {\n"
" uint sign = (val & 0x8000u) << 16;\n"
" int exponent = int((val & 0x7C00u) >> 10);\n"
@@ -155,7 +255,9 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
" float scale;\n"
" if(exponent < 0)\n"
" {\n"
- " scale = 1.0 / (1 << -exponent);\n"
+ " // The negative unary operator is buggy on OSX.\n"
+ " // Work around this by using abs instead.\n"
+ " scale = 1.0 / (1 << abs(exponent));\n"
" }\n"
" else\n"
" {\n"
@@ -174,16 +276,18 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
" }\n"
"#endif\n"
"\n"
- "vec2 webgl_unpackHalf2x16_emu(uint u)\n"
+ "vec2 unpackHalf2x16_emu(uint u)\n"
"{\n"
" #if defined(GL_ARB_shading_language_packing)\n"
" return unpackHalf2x16(u);\n"
" #else\n"
" uint y = (u >> 16);\n"
" uint x = u & 0xFFFFu;\n"
- " return vec2(webgl_f16tof32(x), webgl_f16tof32(y));\n"
+ " return vec2(f16tof32(x), f16tof32(y));\n"
" #endif\n"
"}\n");
// clang-format on
}
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h
index 56242598af..e1b4779bd5 100644
--- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h
@@ -9,17 +9,32 @@
#include "GLSLANG/ShaderLang.h"
+namespace sh
+{
class BuiltInFunctionEmulator;
//
-// This is only a workaround for OpenGL driver bugs, and isn't needed in general.
+// This works around bug in Intel Mac drivers.
//
-void InitBuiltInFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu, sh::GLenum shaderType);
+void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
+ sh::GLenum shaderType);
+
+//
+// This works around isnan() bug in Intel Mac drivers
+//
+void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
+ int targetGLSLVersion);
+//
+// This works around atan(y, x) bug in NVIDIA drivers.
+//
+void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu);
//
// This function is emulating built-in functions missing from GLSL 1.30 and higher.
//
-void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator *emu, sh::GLenum shaderType,
+void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator *emu,
+ sh::GLenum shaderType,
int targetGLSLVersion);
+} // namespace sh
#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp
index 50e15cbc28..e78d86d00a 100644
--- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp
@@ -8,434 +8,177 @@
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/VersionGLSL.h"
-void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
+namespace sh
+{
+
+// Defined in emulated_builtin_functions_hlsl_autogen.cpp.
+const char *FindHLSLFunction(const FunctionId &functionID);
+
+void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu,
+ int targetGLSLVersion)
{
+ if (targetGLSLVersion < GLSL_VERSION_130)
+ return;
+
TType *float1 = new TType(EbtFloat);
TType *float2 = new TType(EbtFloat, 2);
TType *float3 = new TType(EbtFloat, 3);
TType *float4 = new TType(EbtFloat, 4);
- emu->addEmulatedFunction(EOpMod, float1, float1,
- "float webgl_mod_emu(float x, float y)\n"
- "{\n"
- " return x - y * floor(x / y);\n"
- "}\n"
- "\n");
- emu->addEmulatedFunction(EOpMod, float2, float2,
- "float2 webgl_mod_emu(float2 x, float2 y)\n"
- "{\n"
- " return x - y * floor(x / y);\n"
- "}\n"
- "\n");
- emu->addEmulatedFunction(EOpMod, float2, float1,
- "float2 webgl_mod_emu(float2 x, float y)\n"
- "{\n"
- " return x - y * floor(x / y);\n"
- "}\n"
- "\n");
- emu->addEmulatedFunction(EOpMod, float3, float3,
- "float3 webgl_mod_emu(float3 x, float3 y)\n"
- "{\n"
- " return x - y * floor(x / y);\n"
- "}\n"
- "\n");
- emu->addEmulatedFunction(EOpMod, float3, float1,
- "float3 webgl_mod_emu(float3 x, float y)\n"
- "{\n"
- " return x - y * floor(x / y);\n"
- "}\n"
- "\n");
- emu->addEmulatedFunction(EOpMod, float4, float4,
- "float4 webgl_mod_emu(float4 x, float4 y)\n"
- "{\n"
- " return x - y * floor(x / y);\n"
- "}\n"
- "\n");
- emu->addEmulatedFunction(EOpMod, float4, float1,
- "float4 webgl_mod_emu(float4 x, float y)\n"
- "{\n"
- " return x - y * floor(x / y);\n"
- "}\n"
- "\n");
+ emu->addEmulatedFunction(EOpIsNan, float1,
+ "bool isnan_emu(float x)\n"
+ "{\n"
+ " return (x > 0.0 || x < 0.0) ? false : x != 0.0;\n"
+ "}\n"
+ "\n");
- emu->addEmulatedFunction(EOpFaceForward, float1, float1, float1,
- "float webgl_faceforward_emu(float N, float I, float Nref)\n"
+ emu->addEmulatedFunction(
+ EOpIsNan, float2,
+ "bool2 isnan_emu(float2 x)\n"
"{\n"
- " if(dot(Nref, I) >= 0)\n"
+ " bool2 isnan;\n"
+ " for (int i = 0; i < 2; i++)\n"
" {\n"
- " return -N;\n"
+ " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
" }\n"
- " else\n"
- " {\n"
- " return N;\n"
- " }\n"
- "}\n"
- "\n");
- emu->addEmulatedFunction(EOpFaceForward, float2, float2, float2,
- "float2 webgl_faceforward_emu(float2 N, float2 I, float2 Nref)\n"
- "{\n"
- " if(dot(Nref, I) >= 0)\n"
- " {\n"
- " return -N;\n"
- " }\n"
- " else\n"
- " {\n"
- " return N;\n"
- " }\n"
- "}\n"
- "\n");
- emu->addEmulatedFunction(EOpFaceForward, float3, float3, float3,
- "float3 webgl_faceforward_emu(float3 N, float3 I, float3 Nref)\n"
+ " return isnan;\n"
+ "}\n");
+
+ emu->addEmulatedFunction(
+ EOpIsNan, float3,
+ "bool3 isnan_emu(float3 x)\n"
"{\n"
- " if(dot(Nref, I) >= 0)\n"
+ " bool3 isnan;\n"
+ " for (int i = 0; i < 3; i++)\n"
" {\n"
- " return -N;\n"
+ " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
" }\n"
- " else\n"
- " {\n"
- " return N;\n"
- " }\n"
- "}\n"
- "\n");
- emu->addEmulatedFunction(EOpFaceForward, float4, float4, float4,
- "float4 webgl_faceforward_emu(float4 N, float4 I, float4 Nref)\n"
+ " return isnan;\n"
+ "}\n");
+
+ emu->addEmulatedFunction(
+ EOpIsNan, float4,
+ "bool4 isnan_emu(float4 x)\n"
"{\n"
- " if(dot(Nref, I) >= 0)\n"
- " {\n"
- " return -N;\n"
- " }\n"
- " else\n"
+ " bool4 isnan;\n"
+ " for (int i = 0; i < 4; i++)\n"
" {\n"
- " return N;\n"
+ " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
" }\n"
- "}\n"
- "\n");
-
- emu->addEmulatedFunction(EOpAtan, float1, float1,
- "float webgl_atan_emu(float y, float x)\n"
- "{\n"
- " if(x == 0 && y == 0) x = 1;\n" // Avoid producing a NaN
- " return atan2(y, x);\n"
- "}\n");
- emu->addEmulatedFunction(EOpAtan, float2, float2,
- "float2 webgl_atan_emu(float2 y, float2 x)\n"
- "{\n"
- " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
- " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
- " return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n"
- "}\n");
- emu->addEmulatedFunction(EOpAtan, float3, float3,
- "float3 webgl_atan_emu(float3 y, float3 x)\n"
- "{\n"
- " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
- " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
- " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
- " return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n"
- "}\n");
- emu->addEmulatedFunction(EOpAtan, float4, float4,
- "float4 webgl_atan_emu(float4 y, float4 x)\n"
- "{\n"
- " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
- " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
- " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
- " if(x[3] == 0 && y[3] == 0) x[3] = 1;\n"
- " return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]), atan2(y[3], x[3]));\n"
- "}\n");
-
- emu->addEmulatedFunction(EOpAsinh, float1,
- "float webgl_asinh_emu(in float x) {\n"
- " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
- "}\n");
- emu->addEmulatedFunction(EOpAsinh, float2,
- "float2 webgl_asinh_emu(in float2 x) {\n"
- " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
- "}\n");
- emu->addEmulatedFunction(EOpAsinh, float3,
- "float3 webgl_asinh_emu(in float3 x) {\n"
- " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
- "}\n");
- emu->addEmulatedFunction(EOpAsinh, float4,
- "float4 webgl_asinh_emu(in float4 x) {\n"
- " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
- "}\n");
-
- emu->addEmulatedFunction(EOpAcosh, float1,
- "float webgl_acosh_emu(in float x) {\n"
- " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
- "}\n");
- emu->addEmulatedFunction(EOpAcosh, float2,
- "float2 webgl_acosh_emu(in float2 x) {\n"
- " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
- "}\n");
- emu->addEmulatedFunction(EOpAcosh, float3,
- "float3 webgl_acosh_emu(in float3 x) {\n"
- " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
- "}\n");
- emu->addEmulatedFunction(EOpAcosh, float4,
- "float4 webgl_acosh_emu(in float4 x) {\n"
- " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
- "}\n");
-
- emu->addEmulatedFunction(EOpAtanh, float1,
- "float webgl_atanh_emu(in float x) {\n"
- " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
- "}\n");
- emu->addEmulatedFunction(EOpAtanh, float2,
- "float2 webgl_atanh_emu(in float2 x) {\n"
- " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
+ " return isnan;\n"
"}\n");
- emu->addEmulatedFunction(EOpAtanh, float3,
- "float3 webgl_atanh_emu(in float3 x) {\n"
- " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
- "}\n");
- emu->addEmulatedFunction(EOpAtanh, float4,
- "float4 webgl_atanh_emu(in float4 x) {\n"
- " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
- "}\n");
-
- emu->addEmulatedFunction(EOpRoundEven, float1,
- "float webgl_roundEven_emu(in float x) {\n"
- " return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);\n"
- "}\n");
- emu->addEmulatedFunction(EOpRoundEven, float2,
- "float2 webgl_roundEven_emu(in float2 x) {\n"
- " float2 v;\n"
- " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n"
- " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
- " return v;\n"
- "}\n");
- emu->addEmulatedFunction(EOpRoundEven, float3,
- "float3 webgl_roundEven_emu(in float3 x) {\n"
- " float3 v;\n"
- " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n"
- " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
- " v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n"
- " return v;\n"
- "}\n");
- emu->addEmulatedFunction(EOpRoundEven, float4,
- "float4 webgl_roundEven_emu(in float4 x) {\n"
- " float4 v;\n"
- " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n"
- " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
- " v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n"
- " v[3] = (frac(x[3]) == 0.5 && trunc(x[3]) % 2.0 == 0.0) ? trunc(x[3]) : round(x[3]);\n"
- " return v;\n"
- "}\n");
-
- emu->addEmulatedFunction(EOpPackSnorm2x16, float2,
- "int webgl_toSnorm(in float x) {\n"
- " return int(round(clamp(x, -1.0, 1.0) * 32767.0));\n"
- "}\n"
- "\n"
- "uint webgl_packSnorm2x16_emu(in float2 v) {\n"
- " int x = webgl_toSnorm(v.x);\n"
- " int y = webgl_toSnorm(v.y);\n"
- " return (asuint(y) << 16) | (asuint(x) & 0xffffu);\n"
- "}\n");
- emu->addEmulatedFunction(EOpPackUnorm2x16, float2,
- "uint webgl_toUnorm(in float x) {\n"
- " return uint(round(clamp(x, 0.0, 1.0) * 65535.0));\n"
- "}\n"
- "\n"
- "uint webgl_packUnorm2x16_emu(in float2 v) {\n"
- " uint x = webgl_toUnorm(v.x);\n"
- " uint y = webgl_toUnorm(v.y);\n"
- " return (y << 16) | x;\n"
- "}\n");
- emu->addEmulatedFunction(EOpPackHalf2x16, float2,
- "uint webgl_packHalf2x16_emu(in float2 v) {\n"
- " uint x = f32tof16(v.x);\n"
- " uint y = f32tof16(v.y);\n"
- " return (y << 16) | x;\n"
- "}\n");
-
- TType *uint1 = new TType(EbtUInt);
-
- emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1,
- "float webgl_fromSnorm(in uint x) {\n"
- " int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);\n"
- " return clamp(float(xi) / 32767.0, -1.0, 1.0);\n"
- "}\n"
- "\n"
- "float2 webgl_unpackSnorm2x16_emu(in uint u) {\n"
- " uint y = (u >> 16);\n"
- " uint x = u;\n"
- " return float2(webgl_fromSnorm(x), webgl_fromSnorm(y));\n"
- "}\n");
- emu->addEmulatedFunction(EOpUnpackUnorm2x16, uint1,
- "float webgl_fromUnorm(in uint x) {\n"
- " return float(x) / 65535.0;\n"
- "}\n"
- "\n"
- "float2 webgl_unpackUnorm2x16_emu(in uint u) {\n"
- " uint y = (u >> 16);\n"
- " uint x = u & 0xffffu;\n"
- " return float2(webgl_fromUnorm(x), webgl_fromUnorm(y));\n"
- "}\n");
- emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1,
- "float2 webgl_unpackHalf2x16_emu(in uint u) {\n"
- " uint y = (u >> 16);\n"
- " uint x = u & 0xffffu;\n"
- " return float2(f16tof32(x), f16tof32(y));\n"
- "}\n");
-
- // The matrix resulting from outer product needs to be transposed
- // (matrices are stored as transposed to simplify element access in HLSL).
- // So the function should return transpose(c * r) where c is a column vector
- // and r is a row vector. This can be simplified by using the following
- // formula:
- // transpose(c * r) = transpose(r) * transpose(c)
- // transpose(r) and transpose(c) are in a sense free, since to get the
- // transpose of r, we simply can build a column matrix out of the original
- // vector instead of a row matrix.
- emu->addEmulatedFunction(EOpOuterProduct, float2, float2,
- "float2x2 webgl_outerProduct_emu(in float2 c, in float2 r) {\n"
- " return mul(float2x1(r), float1x2(c));\n"
- "}\n");
- emu->addEmulatedFunction(EOpOuterProduct, float3, float3,
- "float3x3 webgl_outerProduct_emu(in float3 c, in float3 r) {\n"
- " return mul(float3x1(r), float1x3(c));\n"
- "}\n");
- emu->addEmulatedFunction(EOpOuterProduct, float4, float4,
- "float4x4 webgl_outerProduct_emu(in float4 c, in float4 r) {\n"
- " return mul(float4x1(r), float1x4(c));\n"
- "}\n");
-
- emu->addEmulatedFunction(EOpOuterProduct, float3, float2,
- "float2x3 webgl_outerProduct_emu(in float3 c, in float2 r) {\n"
- " return mul(float2x1(r), float1x3(c));\n"
- "}\n");
- emu->addEmulatedFunction(EOpOuterProduct, float2, float3,
- "float3x2 webgl_outerProduct_emu(in float2 c, in float3 r) {\n"
- " return mul(float3x1(r), float1x2(c));\n"
- "}\n");
- emu->addEmulatedFunction(EOpOuterProduct, float4, float2,
- "float2x4 webgl_outerProduct_emu(in float4 c, in float2 r) {\n"
- " return mul(float2x1(r), float1x4(c));\n"
- "}\n");
- emu->addEmulatedFunction(EOpOuterProduct, float2, float4,
- "float4x2 webgl_outerProduct_emu(in float2 c, in float4 r) {\n"
- " return mul(float4x1(r), float1x2(c));\n"
- "}\n");
- emu->addEmulatedFunction(EOpOuterProduct, float4, float3,
- "float3x4 webgl_outerProduct_emu(in float4 c, in float3 r) {\n"
- " return mul(float3x1(r), float1x4(c));\n"
- "}\n");
- emu->addEmulatedFunction(EOpOuterProduct, float3, float4,
- "float4x3 webgl_outerProduct_emu(in float3 c, in float4 r) {\n"
- " return mul(float4x1(r), float1x3(c));\n"
- "}\n");
-
- TType *mat2 = new TType(EbtFloat, 2, 2);
- TType *mat3 = new TType(EbtFloat, 3, 3);
- TType *mat4 = new TType(EbtFloat, 4, 4);
-
- // Remember here that the parameter matrix is actually the transpose
- // of the matrix that we're trying to invert, and the resulting matrix
- // should also be the transpose of the inverse.
-
- // When accessing the parameter matrix with m[a][b] it can be thought of so
- // that a is the column and b is the row of the matrix that we're inverting.
-
- // We calculate the inverse as the adjugate matrix divided by the
- // determinant of the matrix being inverted. However, as the result needs
- // to be transposed, we actually use of the transpose of the adjugate matrix
- // which happens to be the cofactor matrix. That's stored in "cof".
-
- // We don't need to care about divide-by-zero since results are undefined
- // for singular or poorly-conditioned matrices.
-
- emu->addEmulatedFunction(EOpInverse, mat2,
- "float2x2 webgl_inverse_emu(in float2x2 m) {\n"
- " float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };\n"
- " return cof / determinant(transpose(m));\n"
- "}\n");
-
- // cofAB is the cofactor for column A and row B.
-
- emu->addEmulatedFunction(EOpInverse, mat3,
- "float3x3 webgl_inverse_emu(in float3x3 m) {\n"
- " float cof00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];\n"
- " float cof01 = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]);\n"
- " float cof02 = m[1][0] * m[2][1] - m[2][0] * m[1][1];\n"
- " float cof10 = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]);\n"
- " float cof11 = m[0][0] * m[2][2] - m[2][0] * m[0][2];\n"
- " float cof12 = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]);\n"
- " float cof20 = m[0][1] * m[1][2] - m[1][1] * m[0][2];\n"
- " float cof21 = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]);\n"
- " float cof22 = m[0][0] * m[1][1] - m[1][0] * m[0][1];\n"
- " float3x3 cof = { cof00, cof10, cof20, cof01, cof11, cof21, cof02, cof12, cof22 };\n"
- " return cof / determinant(transpose(m));\n"
- "}\n");
-
- emu->addEmulatedFunction(EOpInverse, mat4,
- "float4x4 webgl_inverse_emu(in float4x4 m) {\n"
- " float cof00 = m[1][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[1][3] + m[3][1] * m[1][2] * m[2][3]"
- " - m[1][1] * m[3][2] * m[2][3] - m[2][1] * m[1][2] * m[3][3] - m[3][1] * m[2][2] * m[1][3];\n"
- " float cof01 = -(m[1][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[1][3] + m[3][0] * m[1][2] * m[2][3]"
- " - m[1][0] * m[3][2] * m[2][3] - m[2][0] * m[1][2] * m[3][3] - m[3][0] * m[2][2] * m[1][3]);\n"
- " float cof02 = m[1][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[1][3] + m[3][0] * m[1][1] * m[2][3]"
- " - m[1][0] * m[3][1] * m[2][3] - m[2][0] * m[1][1] * m[3][3] - m[3][0] * m[2][1] * m[1][3];\n"
- " float cof03 = -(m[1][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[1][2] + m[3][0] * m[1][1] * m[2][2]"
- " - m[1][0] * m[3][1] * m[2][2] - m[2][0] * m[1][1] * m[3][2] - m[3][0] * m[2][1] * m[1][2]);\n"
- " float cof10 = -(m[0][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[0][3] + m[3][1] * m[0][2] * m[2][3]"
- " - m[0][1] * m[3][2] * m[2][3] - m[2][1] * m[0][2] * m[3][3] - m[3][1] * m[2][2] * m[0][3]);\n"
- " float cof11 = m[0][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[0][3] + m[3][0] * m[0][2] * m[2][3]"
- " - m[0][0] * m[3][2] * m[2][3] - m[2][0] * m[0][2] * m[3][3] - m[3][0] * m[2][2] * m[0][3];\n"
- " float cof12 = -(m[0][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[0][3] + m[3][0] * m[0][1] * m[2][3]"
- " - m[0][0] * m[3][1] * m[2][3] - m[2][0] * m[0][1] * m[3][3] - m[3][0] * m[2][1] * m[0][3]);\n"
- " float cof13 = m[0][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[0][2] + m[3][0] * m[0][1] * m[2][2]"
- " - m[0][0] * m[3][1] * m[2][2] - m[2][0] * m[0][1] * m[3][2] - m[3][0] * m[2][1] * m[0][2];\n"
- " float cof20 = m[0][1] * m[1][2] * m[3][3] + m[1][1] * m[3][2] * m[0][3] + m[3][1] * m[0][2] * m[1][3]"
- " - m[0][1] * m[3][2] * m[1][3] - m[1][1] * m[0][2] * m[3][3] - m[3][1] * m[1][2] * m[0][3];\n"
- " float cof21 = -(m[0][0] * m[1][2] * m[3][3] + m[1][0] * m[3][2] * m[0][3] + m[3][0] * m[0][2] * m[1][3]"
- " - m[0][0] * m[3][2] * m[1][3] - m[1][0] * m[0][2] * m[3][3] - m[3][0] * m[1][2] * m[0][3]);\n"
- " float cof22 = m[0][0] * m[1][1] * m[3][3] + m[1][0] * m[3][1] * m[0][3] + m[3][0] * m[0][1] * m[1][3]"
- " - m[0][0] * m[3][1] * m[1][3] - m[1][0] * m[0][1] * m[3][3] - m[3][0] * m[1][1] * m[0][3];\n"
- " float cof23 = -(m[0][0] * m[1][1] * m[3][2] + m[1][0] * m[3][1] * m[0][2] + m[3][0] * m[0][1] * m[1][2]"
- " - m[0][0] * m[3][1] * m[1][2] - m[1][0] * m[0][1] * m[3][2] - m[3][0] * m[1][1] * m[0][2]);\n"
- " float cof30 = -(m[0][1] * m[1][2] * m[2][3] + m[1][1] * m[2][2] * m[0][3] + m[2][1] * m[0][2] * m[1][3]"
- " - m[0][1] * m[2][2] * m[1][3] - m[1][1] * m[0][2] * m[2][3] - m[2][1] * m[1][2] * m[0][3]);\n"
- " float cof31 = m[0][0] * m[1][2] * m[2][3] + m[1][0] * m[2][2] * m[0][3] + m[2][0] * m[0][2] * m[1][3]"
- " - m[0][0] * m[2][2] * m[1][3] - m[1][0] * m[0][2] * m[2][3] - m[2][0] * m[1][2] * m[0][3];\n"
- " float cof32 = -(m[0][0] * m[1][1] * m[2][3] + m[1][0] * m[2][1] * m[0][3] + m[2][0] * m[0][1] * m[1][3]"
- " - m[0][0] * m[2][1] * m[1][3] - m[1][0] * m[0][1] * m[2][3] - m[2][0] * m[1][1] * m[0][3]);\n"
- " float cof33 = m[0][0] * m[1][1] * m[2][2] + m[1][0] * m[2][1] * m[0][2] + m[2][0] * m[0][1] * m[1][2]"
- " - m[0][0] * m[2][1] * m[1][2] - m[1][0] * m[0][1] * m[2][2] - m[2][0] * m[1][1] * m[0][2];\n"
- " float4x4 cof = { cof00, cof10, cof20, cof30, cof01, cof11, cof21, cof31,"
- " cof02, cof12, cof22, cof32, cof03, cof13, cof23, cof33 };\n"
- " return cof / determinant(transpose(m));\n"
- "}\n");
-
- TType *bool1 = new TType(EbtBool);
- TType *bool2 = new TType(EbtBool, 2);
- TType *bool3 = new TType(EbtBool, 3);
- TType *bool4 = new TType(EbtBool, 4);
+}
- // Emulate ESSL3 variant of mix that takes last argument as boolean vector.
- // genType mix (genType x, genType y, genBType a): Selects which vector each returned component comes from.
- // For a component of 'a' that is false, the corresponding component of 'x' is returned.For a component of 'a' that is true,
- // the corresponding component of 'y' is returned.
- emu->addEmulatedFunction(EOpMix, float1, float1, bool1,
- "float webgl_mix_emu(float x, float y, bool a)\n"
- "{\n"
- " return a ? y : x;\n"
+void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
+{
+ TType *int1 = new TType(EbtInt);
+ TType *int2 = new TType(EbtInt, 2);
+ TType *int3 = new TType(EbtInt, 3);
+ TType *int4 = new TType(EbtInt, 4);
+ TType *uint1 = new TType(EbtUInt);
+ TType *uint2 = new TType(EbtUInt, 2);
+ TType *uint3 = new TType(EbtUInt, 3);
+ TType *uint4 = new TType(EbtUInt, 4);
+
+ emu->addFunctionMap(FindHLSLFunction);
+
+ // (a + b2^16) * (c + d2^16) = ac + (ad + bc) * 2^16 + bd * 2^32
+ // Also note that below, a * d + ((a * c) >> 16) is guaranteed not to overflow, because:
+ // a <= 0xffff, d <= 0xffff, ((a * c) >> 16) <= 0xffff and 0xffff * 0xffff + 0xffff = 0xffff0000
+ FunctionId umulExtendedUint1 = emu->addEmulatedFunction(
+ EOpUmulExtended, uint1, uint1, uint1, uint1,
+ "void umulExtended_emu(uint x, uint y, out uint msb, out uint lsb)\n"
+ "{\n"
+ " lsb = x * y;\n"
+ " uint a = (x & 0xffffu);\n"
+ " uint b = (x >> 16);\n"
+ " uint c = (y & 0xffffu);\n"
+ " uint d = (y >> 16);\n"
+ " uint ad = a * d + ((a * c) >> 16);\n"
+ " uint bc = b * c;\n"
+ " uint carry = uint(ad > (0xffffffffu - bc));\n"
+ " msb = ((ad + bc) >> 16) + (carry << 16) + b * d;\n"
+ "}\n");
+ emu->addEmulatedFunctionWithDependency(
+ umulExtendedUint1, EOpUmulExtended, uint2, uint2, uint2, uint2,
+ "void umulExtended_emu(uint2 x, uint2 y, out uint2 msb, out uint2 lsb)\n"
+ "{\n"
+ " umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
+ " umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
+ "}\n");
+ emu->addEmulatedFunctionWithDependency(
+ umulExtendedUint1, EOpUmulExtended, uint3, uint3, uint3, uint3,
+ "void umulExtended_emu(uint3 x, uint3 y, out uint3 msb, out uint3 lsb)\n"
+ "{\n"
+ " umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
+ " umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
+ " umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
+ "}\n");
+ emu->addEmulatedFunctionWithDependency(
+ umulExtendedUint1, EOpUmulExtended, uint4, uint4, uint4, uint4,
+ "void umulExtended_emu(uint4 x, uint4 y, out uint4 msb, out uint4 lsb)\n"
+ "{\n"
+ " umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
+ " umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
+ " umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
+ " umulExtended_emu(x.w, y.w, msb.w, lsb.w);\n"
+ "}\n");
+
+ // The imul emulation does two's complement negation on the lsb and msb manually in case the
+ // result needs to be negative.
+ // TODO(oetuaho): Note that this code doesn't take one edge case into account, where x or y is
+ // -2^31. abs(-2^31) is undefined.
+ FunctionId imulExtendedInt1 = emu->addEmulatedFunctionWithDependency(
+ umulExtendedUint1, EOpImulExtended, int1, int1, int1, int1,
+ "void imulExtended_emu(int x, int y, out int msb, out int lsb)\n"
+ "{\n"
+ " uint unsignedMsb;\n"
+ " uint unsignedLsb;\n"
+ " bool negative = (x < 0) != (y < 0);\n"
+ " umulExtended_emu(uint(abs(x)), uint(abs(y)), unsignedMsb, unsignedLsb);\n"
+ " lsb = asint(unsignedLsb);\n"
+ " msb = asint(unsignedMsb);\n"
+ " if (negative)\n"
+ " {\n"
+ " lsb = ~lsb;\n"
+ " msb = ~msb;\n"
+ " if (lsb == 0xffffffff)\n"
+ " {\n"
+ " lsb = 0;\n"
+ " msb += 1;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " lsb += 1;\n"
+ " }\n"
+ " }\n"
"}\n");
- emu->addEmulatedFunction(EOpMix, float2, float2, bool2,
- "float2 webgl_mix_emu(float2 x, float2 y, bool2 a)\n"
+ emu->addEmulatedFunctionWithDependency(
+ imulExtendedInt1, EOpImulExtended, int2, int2, int2, int2,
+ "void imulExtended_emu(int2 x, int2 y, out int2 msb, out int2 lsb)\n"
"{\n"
- " return a ? y : x;\n"
+ " imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
+ " imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
"}\n");
- emu->addEmulatedFunction(EOpMix, float3, float3, bool3,
- "float3 webgl_mix_emu(float3 x, float3 y, bool3 a)\n"
+ emu->addEmulatedFunctionWithDependency(
+ imulExtendedInt1, EOpImulExtended, int3, int3, int3, int3,
+ "void imulExtended_emu(int3 x, int3 y, out int3 msb, out int3 lsb)\n"
"{\n"
- " return a ? y : x;\n"
+ " imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
+ " imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
+ " imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
"}\n");
- emu->addEmulatedFunction(EOpMix, float4, float4, bool4,
- "float4 webgl_mix_emu(float4 x, float4 y, bool4 a)\n"
+ emu->addEmulatedFunctionWithDependency(
+ imulExtendedInt1, EOpImulExtended, int4, int4, int4, int4,
+ "void imulExtended_emu(int4 x, int4 y, out int4 msb, out int4 lsb)\n"
"{\n"
- " return a ? y : x;\n"
+ " imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
+ " imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
+ " imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
+ " imulExtended_emu(x.w, y.w, msb.w, lsb.w);\n"
"}\n");
-
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h
index 4c45a93dc4..48da73f58e 100644
--- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h
@@ -9,8 +9,19 @@
#include "GLSLANG/ShaderLang.h"
+namespace sh
+{
+
class BuiltInFunctionEmulator;
void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu);
+//
+// This works around isnan() bug on some Intel drivers.
+//
+void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu,
+ int targetGLSLVersion);
+
+} // namespace sh
+
#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/Cache.cpp b/src/3rdparty/angle/src/compiler/translator/Cache.cpp
index 57a43700ca..417e82403a 100644
--- a/src/3rdparty/angle/src/compiler/translator/Cache.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/Cache.cpp
@@ -12,21 +12,20 @@
#include "common/debug.h"
#include "compiler/translator/Cache.h"
+namespace sh
+{
+
namespace
{
class TScopedAllocator : angle::NonCopyable
{
public:
- TScopedAllocator(TPoolAllocator *allocator)
- : mPreviousAllocator(GetGlobalPoolAllocator())
+ TScopedAllocator(TPoolAllocator *allocator) : mPreviousAllocator(GetGlobalPoolAllocator())
{
SetGlobalPoolAllocator(allocator);
}
- ~TScopedAllocator()
- {
- SetGlobalPoolAllocator(mPreviousAllocator);
- }
+ ~TScopedAllocator() { SetGlobalPoolAllocator(mPreviousAllocator); }
private:
TPoolAllocator *mPreviousAllocator;
@@ -40,28 +39,28 @@ TCache::TypeKey::TypeKey(TBasicType basicType,
unsigned char primarySize,
unsigned char secondarySize)
{
- static_assert(sizeof(components) <= sizeof(value),
- "TypeKey::value is too small");
+ static_assert(sizeof(components) <= sizeof(value), "TypeKey::value is too small");
const size_t MaxEnumValue = std::numeric_limits<EnumComponentType>::max();
- UNUSED_ASSERTION_VARIABLE(MaxEnumValue);
// TODO: change to static_assert() once we deprecate MSVC 2013 support
- ASSERT(MaxEnumValue >= EbtLast &&
- MaxEnumValue >= EbpLast &&
- MaxEnumValue >= EvqLast &&
+ ASSERT(MaxEnumValue >= EbtLast && MaxEnumValue >= EbpLast && MaxEnumValue >= EvqLast &&
"TypeKey::EnumComponentType is too small");
- value = 0;
- components.basicType = static_cast<EnumComponentType>(basicType);
- components.precision = static_cast<EnumComponentType>(precision);
- components.qualifier = static_cast<EnumComponentType>(qualifier);
- components.primarySize = primarySize;
+ value = 0;
+ components.basicType = static_cast<EnumComponentType>(basicType);
+ components.precision = static_cast<EnumComponentType>(precision);
+ components.qualifier = static_cast<EnumComponentType>(qualifier);
+ components.primarySize = primarySize;
components.secondarySize = secondarySize;
}
TCache *TCache::sCache = nullptr;
+TCache::TCache()
+{
+}
+
void TCache::initialize()
{
if (sCache == nullptr)
@@ -81,8 +80,7 @@ const TType *TCache::getType(TBasicType basicType,
unsigned char primarySize,
unsigned char secondarySize)
{
- TypeKey key(basicType, precision, qualifier,
- primarySize, secondarySize);
+ TypeKey key(basicType, precision, qualifier, primarySize, secondarySize);
auto it = sCache->mTypes.find(key);
if (it != sCache->mTypes.end())
{
@@ -91,10 +89,11 @@ const TType *TCache::getType(TBasicType basicType,
TScopedAllocator scopedAllocator(&sCache->mAllocator);
- TType *type = new TType(basicType, precision, qualifier,
- primarySize, secondarySize);
+ TType *type = new TType(basicType, precision, qualifier, primarySize, secondarySize);
type->realize();
sCache->mTypes.insert(std::make_pair(key, type));
return type;
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/Cache.h b/src/3rdparty/angle/src/compiler/translator/Cache.h
index 1d2abb77e1..a182b07f51 100644
--- a/src/3rdparty/angle/src/compiler/translator/Cache.h
+++ b/src/3rdparty/angle/src/compiler/translator/Cache.h
@@ -16,33 +16,31 @@
#include "compiler/translator/Types.h"
#include "compiler/translator/PoolAlloc.h"
+namespace sh
+{
+
class TCache
{
public:
-
static void initialize();
static void destroy();
- static const TType *getType(TBasicType basicType,
- TPrecision precision)
+ static const TType *getType(TBasicType basicType, TPrecision precision)
{
- return getType(basicType, precision, EvqTemporary,
- 1, 1);
+ return getType(basicType, precision, EvqTemporary, 1, 1);
}
static const TType *getType(TBasicType basicType,
- unsigned char primarySize = 1,
+ unsigned char primarySize = 1,
unsigned char secondarySize = 1)
{
- return getType(basicType, EbpUndefined, EvqGlobal,
- primarySize, secondarySize);
+ return getType(basicType, EbpUndefined, EvqGlobal, primarySize, secondarySize);
}
static const TType *getType(TBasicType basicType,
TQualifier qualifier,
- unsigned char primarySize = 1,
+ unsigned char primarySize = 1,
unsigned char secondarySize = 1)
{
- return getType(basicType, EbpUndefined, qualifier,
- primarySize, secondarySize);
+ return getType(basicType, EbpUndefined, qualifier, primarySize, secondarySize);
}
static const TType *getType(TBasicType basicType,
TPrecision precision,
@@ -51,12 +49,9 @@ class TCache
unsigned char secondarySize);
private:
- TCache()
- {
- }
+ TCache();
- union TypeKey
- {
+ union TypeKey {
TypeKey(TBasicType basicType,
TPrecision precision,
TQualifier qualifier,
@@ -74,12 +69,9 @@ class TCache
} components;
uint64_t value;
- bool operator < (const TypeKey &other) const
- {
- return value < other.value;
- }
+ bool operator<(const TypeKey &other) const { return value < other.value; }
};
- typedef std::map<TypeKey, const TType*> TypeMap;
+ typedef std::map<TypeKey, const TType *> TypeMap;
TypeMap mTypes;
TPoolAllocator mAllocator;
@@ -87,4 +79,6 @@ class TCache
static TCache *sCache;
};
+} // namespace sh
+
#endif // COMPILER_TRANSLATOR_CACHE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/CallDAG.cpp b/src/3rdparty/angle/src/compiler/translator/CallDAG.cpp
index 10f0eb937c..5f54e80898 100644
--- a/src/3rdparty/angle/src/compiler/translator/CallDAG.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/CallDAG.cpp
@@ -9,16 +9,22 @@
// order.
#include "compiler/translator/CallDAG.h"
-#include "compiler/translator/InfoSink.h"
+
+#include "compiler/translator/Diagnostics.h"
+#include "compiler/translator/IntermTraverse.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
// The CallDAGCreator does all the processing required to create the CallDAG
// structure so that the latter contains only the necessary variables.
class CallDAG::CallDAGCreator : public TIntermTraverser
{
public:
- CallDAGCreator(TInfoSinkBase *info)
+ CallDAGCreator(TDiagnostics *diagnostics)
: TIntermTraverser(true, false, true),
- mCreationInfo(info),
+ mDiagnostics(diagnostics),
mCurrentFunction(nullptr),
mCurrentIndex(0)
{
@@ -35,7 +41,6 @@ class CallDAG::CallDAGCreator : public TIntermTraverser
InitResult result = assignIndicesInternal(&it.second);
if (result != INITDAG_SUCCESS)
{
- *mCreationInfo << "\n";
return result;
}
}
@@ -44,6 +49,7 @@ class CallDAG::CallDAGCreator : public TIntermTraverser
skipped++;
}
}
+
ASSERT(mFunctions.size() == mCurrentIndex + skipped);
return INITDAG_SUCCESS;
}
@@ -75,147 +81,196 @@ class CallDAG::CallDAGCreator : public TIntermTraverser
record.callees.push_back(static_cast<int>(callee->index));
}
- (*idToIndex)[data.node->getFunctionId()] = static_cast<int>(data.index);
+ (*idToIndex)[data.node->getFunctionSymbolInfo()->getId().get()] =
+ static_cast<int>(data.index);
}
}
private:
-
struct CreatorFunctionData
{
- CreatorFunctionData()
- : node(nullptr),
- index(0),
- indexAssigned(false),
- visiting(false)
- {
- }
+ CreatorFunctionData() : node(nullptr), index(0), indexAssigned(false), visiting(false) {}
- std::set<CreatorFunctionData*> callees;
- TIntermAggregate *node;
+ std::set<CreatorFunctionData *> callees;
+ TIntermFunctionDefinition *node;
TString name;
size_t index;
bool indexAssigned;
bool visiting;
};
- // Aggregates the AST node for each function as well as the name of the functions called by it
- bool visitAggregate(Visit visit, TIntermAggregate *node) override
+ bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override
{
- switch (node->getOp())
+ // Create the record if need be and remember the node.
+ if (visit == PreVisit)
{
- case EOpPrototype:
- if (visit == PreVisit)
+ auto it = mFunctions.find(node->getFunctionSymbolInfo()->getId().get());
+
+ if (it == mFunctions.end())
{
- // Function declaration, create an empty record.
- auto& record = mFunctions[node->getName()];
- record.name = node->getName();
+ mCurrentFunction = &mFunctions[node->getFunctionSymbolInfo()->getId().get()];
+ mCurrentFunction->name = node->getFunctionSymbolInfo()->getName();
}
- break;
- case EOpFunction:
+ else
{
- // Function definition, create the record if need be and remember the node.
- if (visit == PreVisit)
- {
- auto it = mFunctions.find(node->getName());
+ mCurrentFunction = &it->second;
+ ASSERT(mCurrentFunction->name == node->getFunctionSymbolInfo()->getName());
+ }
- if (it == mFunctions.end())
- {
- mCurrentFunction = &mFunctions[node->getName()];
- }
- else
- {
- mCurrentFunction = &it->second;
- }
+ mCurrentFunction->node = node;
+ }
+ else if (visit == PostVisit)
+ {
+ mCurrentFunction = nullptr;
+ }
+ return true;
+ }
- mCurrentFunction->node = node;
- mCurrentFunction->name = node->getName();
+ bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override
+ {
+ ASSERT(visit == PreVisit);
+ if (mCurrentFunction != nullptr)
+ {
+ return false;
+ }
- }
- else if (visit == PostVisit)
- {
- mCurrentFunction = nullptr;
- }
- break;
- }
- case EOpFunctionCall:
+ // Function declaration, create an empty record.
+ auto &record = mFunctions[node->getFunctionSymbolInfo()->getId().get()];
+ record.name = node->getFunctionSymbolInfo()->getName();
+
+ // No need to traverse the parameters.
+ return false;
+ }
+
+ // Aggregates the AST node for each function as well as the name of the functions called by it
+ bool visitAggregate(Visit visit, TIntermAggregate *node) override
+ {
+ if (visit == PreVisit && node->getOp() == EOpCallFunctionInAST)
+ {
+ // Function call, add the callees
+ auto it = mFunctions.find(node->getFunctionSymbolInfo()->getId().get());
+ ASSERT(it != mFunctions.end());
+
+ // We might be traversing the initializer of a global variable. Even though function
+ // calls in global scope are forbidden by the parser, some subsequent AST
+ // transformations can add them to emulate particular features.
+ if (mCurrentFunction)
{
- // Function call, add the callees
- if (visit == PreVisit)
- {
- // Do not handle calls to builtin functions
- if (node->isUserDefined())
- {
- auto it = mFunctions.find(node->getName());
- ASSERT(it != mFunctions.end());
-
- // We might be in a top-level function call to set a global variable
- if (mCurrentFunction)
- {
- mCurrentFunction->callees.insert(&it->second);
- }
- }
- }
- break;
+ mCurrentFunction->callees.insert(&it->second);
}
- default:
- break;
}
return true;
}
// Recursively assigns indices to a sub DAG
- InitResult assignIndicesInternal(CreatorFunctionData *function)
+ InitResult assignIndicesInternal(CreatorFunctionData *root)
{
- ASSERT(function);
+ // Iterative implementation of the index assignment algorithm. A recursive version
+ // would be prettier but since the CallDAG creation runs before the limiting of the
+ // call depth, we might get stack overflows (computation of the call depth uses the
+ // CallDAG).
- if (!function->node)
- {
- *mCreationInfo << "Undefined function '" << function->name
- << ")' used in the following call chain:";
- return INITDAG_UNDEFINED;
- }
+ ASSERT(root);
- if (function->indexAssigned)
+ if (root->indexAssigned)
{
return INITDAG_SUCCESS;
}
- if (function->visiting)
+ // If we didn't have to detect recursion, functionsToProcess could be a simple queue
+ // in which we add the function being processed's callees. However in order to detect
+ // recursion we need to know which functions we are currently visiting. For that reason
+ // functionsToProcess will look like a concatenation of segments of the form
+ // [F visiting = true, subset of F callees with visiting = false] and the following
+ // segment (if any) will be start with a callee of F.
+ // This way we can remember when we started visiting a function, to put visiting back
+ // to false.
+ TVector<CreatorFunctionData *> functionsToProcess;
+ functionsToProcess.push_back(root);
+
+ InitResult result = INITDAG_SUCCESS;
+
+ std::stringstream errorStream;
+
+ while (!functionsToProcess.empty())
{
- if (mCreationInfo)
+ CreatorFunctionData *function = functionsToProcess.back();
+
+ if (function->visiting)
+ {
+ function->visiting = false;
+ function->index = mCurrentIndex++;
+ function->indexAssigned = true;
+
+ functionsToProcess.pop_back();
+ continue;
+ }
+
+ if (!function->node)
+ {
+ errorStream << "Undefined function '" << function->name
+ << ")' used in the following call chain:";
+ result = INITDAG_UNDEFINED;
+ break;
+ }
+
+ if (function->indexAssigned)
+ {
+ functionsToProcess.pop_back();
+ continue;
+ }
+
+ function->visiting = true;
+
+ for (auto callee : function->callees)
+ {
+ functionsToProcess.push_back(callee);
+
+ // Check if the callee is already being visited after pushing it so that it appears
+ // in the chain printed in the info log.
+ if (callee->visiting)
+ {
+ errorStream << "Recursive function call in the following call chain:";
+ result = INITDAG_RECURSION;
+ break;
+ }
+ }
+
+ if (result != INITDAG_SUCCESS)
{
- *mCreationInfo << "Recursive function call in the following call chain:" << function->name;
+ break;
}
- return INITDAG_RECURSION;
}
- function->visiting = true;
- for (auto &callee : function->callees)
+ // The call chain is made of the function we were visiting when the error was detected.
+ if (result != INITDAG_SUCCESS)
{
- InitResult result = assignIndicesInternal(callee);
- if (result != INITDAG_SUCCESS)
+ bool first = true;
+ for (auto function : functionsToProcess)
{
- // We know that there is an issue with the call chain in the AST,
- // print the link of the chain we were processing.
- if (mCreationInfo)
+ if (function->visiting)
{
- *mCreationInfo << " <- " << function->name << ")";
+ if (!first)
+ {
+ errorStream << " -> ";
+ }
+ errorStream << function->name << ")";
+ first = false;
}
- return result;
+ }
+ if (mDiagnostics)
+ {
+ std::string errorStr = errorStream.str();
+ mDiagnostics->globalError(errorStr.c_str());
}
}
- function->index = mCurrentIndex++;
- function->indexAssigned = true;
-
- function->visiting = false;
- return INITDAG_SUCCESS;
+ return result;
}
- TInfoSinkBase *mCreationInfo;
+ TDiagnostics *mDiagnostics;
- std::map<TString, CreatorFunctionData> mFunctions;
+ std::map<int, CreatorFunctionData> mFunctions;
CreatorFunctionData *mCurrentFunction;
size_t mCurrentIndex;
};
@@ -232,13 +287,9 @@ CallDAG::~CallDAG()
const size_t CallDAG::InvalidIndex = std::numeric_limits<size_t>::max();
-size_t CallDAG::findIndex(const TIntermAggregate *function) const
+size_t CallDAG::findIndex(const TFunctionSymbolInfo *functionInfo) const
{
- TOperator op = function->getOp();
- ASSERT(op == EOpPrototype || op == EOpFunction || op == EOpFunctionCall);
- UNUSED_ASSERTION_VARIABLE(op);
-
- auto it = mFunctionIdToIndex.find(function->getFunctionId());
+ auto it = mFunctionIdToIndex.find(functionInfo->getId().get());
if (it == mFunctionIdToIndex.end())
{
@@ -258,7 +309,7 @@ const CallDAG::Record &CallDAG::getRecordFromIndex(size_t index) const
const CallDAG::Record &CallDAG::getRecord(const TIntermAggregate *function) const
{
- size_t index = findIndex(function);
+ size_t index = findIndex(function->getFunctionSymbolInfo());
ASSERT(index != InvalidIndex && index < mRecords.size());
return mRecords[index];
}
@@ -274,9 +325,9 @@ void CallDAG::clear()
mFunctionIdToIndex.clear();
}
-CallDAG::InitResult CallDAG::init(TIntermNode *root, TInfoSinkBase *info)
+CallDAG::InitResult CallDAG::init(TIntermNode *root, TDiagnostics *diagnostics)
{
- CallDAGCreator creator(info);
+ CallDAGCreator creator(diagnostics);
// Creates the mapping of functions to callees
root->traverse(&creator);
@@ -291,3 +342,5 @@ CallDAG::InitResult CallDAG::init(TIntermNode *root, TInfoSinkBase *info)
creator.fillDataStructures(&mRecords, &mFunctionIdToIndex);
return INITDAG_SUCCESS;
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/CallDAG.h b/src/3rdparty/angle/src/compiler/translator/CallDAG.h
index 06c377db00..155081c9a2 100644
--- a/src/3rdparty/angle/src/compiler/translator/CallDAG.h
+++ b/src/3rdparty/angle/src/compiler/translator/CallDAG.h
@@ -14,8 +14,9 @@
#include <map>
#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/VariableInfo.h"
+namespace sh
+{
// The translator needs to analyze the the graph of the function calls
// to run checks and analyses; since in GLSL recursion is not allowed
@@ -24,7 +25,7 @@
// can be reused by multiple analyses.
//
// It stores a vector of function records, with one record per function.
-// Records are accessed by index but a mangled function name can be converted
+// Records are accessed by index but a function symbol id can be converted
// to the index of the corresponding record. The records mostly contain the
// AST node of the function and the indices of the function's callees.
//
@@ -41,7 +42,7 @@ class CallDAG : angle::NonCopyable
struct Record
{
std::string name;
- TIntermAggregate *node;
+ TIntermFunctionDefinition *node;
std::vector<int> callees;
};
@@ -53,11 +54,11 @@ class CallDAG : angle::NonCopyable
};
// Returns INITDAG_SUCCESS if it was able to create the DAG, otherwise prints
- // the initialization error in info, if present.
- InitResult init(TIntermNode *root, TInfoSinkBase *info);
+ // the initialization error in diagnostics, if present.
+ InitResult init(TIntermNode *root, TDiagnostics *diagnostics);
// Returns InvalidIndex if the function wasn't found
- size_t findIndex(const TIntermAggregate *function) const;
+ size_t findIndex(const TFunctionSymbolInfo *functionInfo) const;
const Record &getRecordFromIndex(size_t index) const;
const Record &getRecord(const TIntermAggregate *function) const;
@@ -65,6 +66,7 @@ class CallDAG : angle::NonCopyable
void clear();
const static size_t InvalidIndex;
+
private:
std::vector<Record> mRecords;
std::map<int, int> mFunctionIdToIndex;
@@ -72,4 +74,6 @@ class CallDAG : angle::NonCopyable
class CallDAGCreator;
};
+} // namespace sh
+
#endif // COMPILER_TRANSLATOR_CALLDAG_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ClampPointSize.cpp b/src/3rdparty/angle/src/compiler/translator/ClampPointSize.cpp
new file mode 100644
index 0000000000..8598a137f5
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/ClampPointSize.cpp
@@ -0,0 +1,47 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ClampPointSize.cpp: Limit the value that is written to gl_PointSize.
+//
+
+#include "compiler/translator/ClampPointSize.h"
+
+#include "compiler/translator/FindSymbolNode.h"
+#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/RunAtTheEndOfShader.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+void ClampPointSize(TIntermBlock *root, float maxPointSize, TSymbolTable *symbolTable)
+{
+ // Only clamp gl_PointSize if it's used in the shader.
+ if (!FindSymbolNode(root, TString("gl_PointSize"), EbtFloat))
+ {
+ return;
+ }
+
+ TIntermSymbol *pointSizeNode = ReferenceBuiltInVariable("gl_PointSize", *symbolTable, 100);
+
+ TConstantUnion *maxPointSizeConstant = new TConstantUnion();
+ maxPointSizeConstant->setFConst(maxPointSize);
+ TIntermConstantUnion *maxPointSizeNode =
+ new TIntermConstantUnion(maxPointSizeConstant, TType(EbtFloat, EbpHigh, EvqConst));
+
+ // min(gl_PointSize, maxPointSize)
+ TIntermSequence *minArguments = new TIntermSequence();
+ minArguments->push_back(pointSizeNode->deepCopy());
+ minArguments->push_back(maxPointSizeNode);
+ TIntermTyped *clampedPointSize =
+ CreateBuiltInFunctionCallNode("min", minArguments, *symbolTable, 100);
+
+ // gl_PointSize = min(gl_PointSize, maxPointSize)
+ TIntermBinary *assignPointSize = new TIntermBinary(EOpAssign, pointSizeNode, clampedPointSize);
+
+ RunAtTheEndOfShader(root, assignPointSize, symbolTable);
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ClampPointSize.h b/src/3rdparty/angle/src/compiler/translator/ClampPointSize.h
new file mode 100644
index 0000000000..0c71ae6b0d
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/ClampPointSize.h
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ClampPointSize.h: Limit the value that is written to gl_PointSize.
+//
+
+#ifndef COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_
+#define COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_
+
+namespace sh
+{
+
+class TIntermBlock;
+class TSymbolTable;
+
+void ClampPointSize(TIntermBlock *root, float maxPointSize, TSymbolTable *symbolTable);
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp b/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp
index f099bccf15..3e25cc2339 100644
--- a/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp
@@ -6,71 +6,70 @@
#ifdef ANGLE_ENABLE_ESSL
#include "compiler/translator/TranslatorESSL.h"
-#endif
+#endif // ANGLE_ENABLE_ESSL
#ifdef ANGLE_ENABLE_GLSL
#include "compiler/translator/TranslatorGLSL.h"
-#endif
+#endif // ANGLE_ENABLE_GLSL
#ifdef ANGLE_ENABLE_HLSL
#include "compiler/translator/TranslatorHLSL.h"
-#endif // ANGLE_ENABLE_HLSL
+#endif // ANGLE_ENABLE_HLSL
+
+#ifdef ANGLE_ENABLE_VULKAN
+#include "compiler/translator/TranslatorVulkan.h"
+#endif // ANGLE_ENABLE_VULKAN
+
+#include "compiler/translator/util.h"
+
+namespace sh
+{
//
// This function must be provided to create the actual
// compile object used by higher level code. It returns
// a subclass of TCompiler.
//
-TCompiler* ConstructCompiler(
- sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
+TCompiler *ConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
{
- switch (output) {
- case SH_ESSL_OUTPUT:
#ifdef ANGLE_ENABLE_ESSL
+ if (IsOutputESSL(output))
+ {
return new TranslatorESSL(type, spec);
-#else
- // This compiler is not supported in this
- // configuration. Return NULL per the ShConstructCompiler API.
- return nullptr;
-#endif // ANGLE_ENABLE_ESSL
- case SH_GLSL_130_OUTPUT:
- case SH_GLSL_140_OUTPUT:
- case SH_GLSL_150_CORE_OUTPUT:
- case SH_GLSL_330_CORE_OUTPUT:
- case SH_GLSL_400_CORE_OUTPUT:
- case SH_GLSL_410_CORE_OUTPUT:
- case SH_GLSL_420_CORE_OUTPUT:
- case SH_GLSL_430_CORE_OUTPUT:
- case SH_GLSL_440_CORE_OUTPUT:
- case SH_GLSL_450_CORE_OUTPUT:
- case SH_GLSL_COMPATIBILITY_OUTPUT:
+ }
+#endif // ANGLE_ENABLE_ESSL
+
#ifdef ANGLE_ENABLE_GLSL
+ if (IsOutputGLSL(output))
+ {
return new TranslatorGLSL(type, spec, output);
-#else
- // This compiler is not supported in this
- // configuration. Return NULL per the ShConstructCompiler API.
- return nullptr;
-#endif // ANGLE_ENABLE_GLSL
- case SH_HLSL_3_0_OUTPUT:
- case SH_HLSL_4_1_OUTPUT:
- case SH_HLSL_4_0_FL9_3_OUTPUT:
+ }
+#endif // ANGLE_ENABLE_GLSL
+
#ifdef ANGLE_ENABLE_HLSL
+ if (IsOutputHLSL(output))
+ {
return new TranslatorHLSL(type, spec, output);
-#else
- // This compiler is not supported in this
- // configuration. Return NULL per the ShConstructCompiler API.
- return nullptr;
-#endif // ANGLE_ENABLE_HLSL
- default:
- // Unknown format. Return NULL per the ShConstructCompiler API.
- return nullptr;
}
+#endif // ANGLE_ENABLE_HLSL
+
+#ifdef ANGLE_ENABLE_VULKAN
+ if (IsOutputVulkan(output))
+ {
+ return new TranslatorVulkan(type, spec);
+ }
+#endif // ANGLE_ENABLE_VULKAN
+
+ // Unsupported compiler or unknown format. Return nullptr per the sh::ConstructCompiler API.
+ return nullptr;
}
//
// Delete the compiler made by ConstructCompiler
//
-void DeleteCompiler(TCompiler* compiler)
+void DeleteCompiler(TCompiler *compiler)
{
- delete compiler;
+ SafeDelete(compiler);
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/CollectVariables.cpp b/src/3rdparty/angle/src/compiler/translator/CollectVariables.cpp
new file mode 100644
index 0000000000..bd8cbc971a
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/CollectVariables.cpp
@@ -0,0 +1,869 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// CollectVariables.cpp: Collect lists of shader interface variables based on the AST.
+
+#include "compiler/translator/CollectVariables.h"
+
+#include "angle_gl.h"
+#include "common/utilities.h"
+#include "compiler/translator/HashNames.h"
+#include "compiler/translator/IntermTraverse.h"
+#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/util.h"
+
+namespace sh
+{
+
+namespace
+{
+
+BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage)
+{
+ switch (blockStorage)
+ {
+ case EbsPacked:
+ return BLOCKLAYOUT_PACKED;
+ case EbsShared:
+ return BLOCKLAYOUT_SHARED;
+ case EbsStd140:
+ return BLOCKLAYOUT_STD140;
+ case EbsStd430:
+ return BLOCKLAYOUT_STD430;
+ default:
+ UNREACHABLE();
+ return BLOCKLAYOUT_SHARED;
+ }
+}
+
+// TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks.
+BlockType GetBlockType(TQualifier qualifier)
+{
+ switch (qualifier)
+ {
+ case EvqUniform:
+ return BlockType::BLOCK_UNIFORM;
+ case EvqBuffer:
+ return BlockType::BLOCK_BUFFER;
+ case EvqPerVertexIn:
+ return BlockType::BLOCK_IN;
+ default:
+ UNREACHABLE();
+ return BlockType::BLOCK_UNIFORM;
+ }
+}
+
+template <class VarT>
+VarT *FindVariable(const TString &name, std::vector<VarT> *infoList)
+{
+ // TODO(zmo): optimize this function.
+ for (size_t ii = 0; ii < infoList->size(); ++ii)
+ {
+ if ((*infoList)[ii].name.c_str() == name)
+ return &((*infoList)[ii]);
+ }
+
+ return nullptr;
+}
+
+// Note that this shouldn't be called for interface blocks - static use information is collected for
+// individual fields in case of interface blocks.
+void MarkStaticallyUsed(ShaderVariable *variable)
+{
+ if (!variable->staticUse)
+ {
+ if (variable->isStruct())
+ {
+ // Conservatively assume all fields are statically used as well.
+ for (auto &field : variable->fields)
+ {
+ MarkStaticallyUsed(&field);
+ }
+ }
+ variable->staticUse = true;
+ }
+}
+
+ShaderVariable *FindVariableInInterfaceBlock(const TString &name,
+ const TInterfaceBlock *interfaceBlock,
+ std::vector<InterfaceBlock> *infoList)
+{
+ ASSERT(interfaceBlock);
+ InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), infoList);
+ ASSERT(namedBlock);
+
+ // Set static use on the parent interface block here
+ namedBlock->staticUse = true;
+ return FindVariable(name, &namedBlock->fields);
+}
+
+// Traverses the intermediate tree to collect all attributes, uniforms, varyings, fragment outputs,
+// and interface blocks.
+class CollectVariablesTraverser : public TIntermTraverser
+{
+ public:
+ CollectVariablesTraverser(std::vector<Attribute> *attribs,
+ std::vector<OutputVariable> *outputVariables,
+ std::vector<Uniform> *uniforms,
+ std::vector<Varying> *inputVaryings,
+ std::vector<Varying> *outputVaryings,
+ std::vector<InterfaceBlock> *uniformBlocks,
+ std::vector<InterfaceBlock> *shaderStorageBlocks,
+ std::vector<InterfaceBlock> *inBlocks,
+ ShHashFunction64 hashFunction,
+ TSymbolTable *symbolTable,
+ int shaderVersion,
+ GLenum shaderType,
+ const TExtensionBehavior &extensionBehavior);
+
+ void visitSymbol(TIntermSymbol *symbol) override;
+ bool visitDeclaration(Visit, TIntermDeclaration *node) override;
+ bool visitBinary(Visit visit, TIntermBinary *binaryNode) override;
+
+ private:
+ std::string getMappedName(const TName &name) const;
+
+ void setCommonVariableProperties(const TType &type,
+ const TName &name,
+ ShaderVariable *variableOut) const;
+
+ Attribute recordAttribute(const TIntermSymbol &variable) const;
+ OutputVariable recordOutputVariable(const TIntermSymbol &variable) const;
+ Varying recordVarying(const TIntermSymbol &variable) const;
+ void recordInterfaceBlock(const TType &interfaceBlockType,
+ InterfaceBlock *interfaceBlock) const;
+ Uniform recordUniform(const TIntermSymbol &variable) const;
+
+ void setBuiltInInfoFromSymbolTable(const char *name, ShaderVariable *info);
+
+ void recordBuiltInVaryingUsed(const char *name,
+ bool *addedFlag,
+ std::vector<Varying> *varyings);
+ void recordBuiltInFragmentOutputUsed(const char *name, bool *addedFlag);
+ void recordBuiltInAttributeUsed(const char *name, bool *addedFlag);
+ InterfaceBlock *recordGLInUsed(const TType &glInType);
+ InterfaceBlock *findNamedInterfaceBlock(const TString &name) const;
+
+ std::vector<Attribute> *mAttribs;
+ std::vector<OutputVariable> *mOutputVariables;
+ std::vector<Uniform> *mUniforms;
+ std::vector<Varying> *mInputVaryings;
+ std::vector<Varying> *mOutputVaryings;
+ std::vector<InterfaceBlock> *mUniformBlocks;
+ std::vector<InterfaceBlock> *mShaderStorageBlocks;
+ std::vector<InterfaceBlock> *mInBlocks;
+
+ std::map<std::string, InterfaceBlockField *> mInterfaceBlockFields;
+
+ // Shader uniforms
+ bool mDepthRangeAdded;
+
+ // Vertex Shader builtins
+ bool mInstanceIDAdded;
+ bool mVertexIDAdded;
+ bool mPointSizeAdded;
+
+ // Vertex Shader and Geometry Shader builtins
+ bool mPositionAdded;
+
+ // Fragment Shader builtins
+ bool mPointCoordAdded;
+ bool mFrontFacingAdded;
+ bool mFragCoordAdded;
+ bool mLastFragDataAdded;
+ bool mFragColorAdded;
+ bool mFragDataAdded;
+ bool mFragDepthEXTAdded;
+ bool mFragDepthAdded;
+ bool mSecondaryFragColorEXTAdded;
+ bool mSecondaryFragDataEXTAdded;
+
+ // Geometry Shader builtins
+ bool mPerVertexInAdded;
+ bool mPrimitiveIDInAdded;
+ bool mInvocationIDAdded;
+
+ // Geometry Shader and Fragment Shader builtins
+ bool mPrimitiveIDAdded;
+ bool mLayerAdded;
+
+ ShHashFunction64 mHashFunction;
+
+ int mShaderVersion;
+ GLenum mShaderType;
+ const TExtensionBehavior &mExtensionBehavior;
+};
+
+CollectVariablesTraverser::CollectVariablesTraverser(
+ std::vector<sh::Attribute> *attribs,
+ std::vector<sh::OutputVariable> *outputVariables,
+ std::vector<sh::Uniform> *uniforms,
+ std::vector<sh::Varying> *inputVaryings,
+ std::vector<sh::Varying> *outputVaryings,
+ std::vector<sh::InterfaceBlock> *uniformBlocks,
+ std::vector<sh::InterfaceBlock> *shaderStorageBlocks,
+ std::vector<sh::InterfaceBlock> *inBlocks,
+ ShHashFunction64 hashFunction,
+ TSymbolTable *symbolTable,
+ int shaderVersion,
+ GLenum shaderType,
+ const TExtensionBehavior &extensionBehavior)
+ : TIntermTraverser(true, false, false, symbolTable),
+ mAttribs(attribs),
+ mOutputVariables(outputVariables),
+ mUniforms(uniforms),
+ mInputVaryings(inputVaryings),
+ mOutputVaryings(outputVaryings),
+ mUniformBlocks(uniformBlocks),
+ mShaderStorageBlocks(shaderStorageBlocks),
+ mInBlocks(inBlocks),
+ mDepthRangeAdded(false),
+ mInstanceIDAdded(false),
+ mVertexIDAdded(false),
+ mPointSizeAdded(false),
+ mPositionAdded(false),
+ mPointCoordAdded(false),
+ mFrontFacingAdded(false),
+ mFragCoordAdded(false),
+ mLastFragDataAdded(false),
+ mFragColorAdded(false),
+ mFragDataAdded(false),
+ mFragDepthEXTAdded(false),
+ mFragDepthAdded(false),
+ mSecondaryFragColorEXTAdded(false),
+ mSecondaryFragDataEXTAdded(false),
+ mPerVertexInAdded(false),
+ mPrimitiveIDInAdded(false),
+ mInvocationIDAdded(false),
+ mPrimitiveIDAdded(false),
+ mLayerAdded(false),
+ mHashFunction(hashFunction),
+ mShaderVersion(shaderVersion),
+ mShaderType(shaderType),
+ mExtensionBehavior(extensionBehavior)
+{
+}
+
+std::string CollectVariablesTraverser::getMappedName(const TName &name) const
+{
+ return HashName(name, mHashFunction, nullptr).c_str();
+}
+
+void CollectVariablesTraverser::setBuiltInInfoFromSymbolTable(const char *name,
+ ShaderVariable *info)
+{
+ TVariable *symbolTableVar =
+ reinterpret_cast<TVariable *>(mSymbolTable->findBuiltIn(name, mShaderVersion));
+ ASSERT(symbolTableVar);
+ const TType &type = symbolTableVar->getType();
+
+ info->name = name;
+ info->mappedName = name;
+ info->type = GLVariableType(type);
+ info->precision = GLVariablePrecision(type);
+ if (auto *arraySizes = type.getArraySizes())
+ {
+ info->arraySizes.assign(arraySizes->begin(), arraySizes->end());
+ }
+}
+
+void CollectVariablesTraverser::recordBuiltInVaryingUsed(const char *name,
+ bool *addedFlag,
+ std::vector<Varying> *varyings)
+{
+ ASSERT(varyings);
+ if (!(*addedFlag))
+ {
+ Varying info;
+ setBuiltInInfoFromSymbolTable(name, &info);
+ info.staticUse = true;
+ info.isInvariant = mSymbolTable->isVaryingInvariant(name);
+ varyings->push_back(info);
+ (*addedFlag) = true;
+ }
+}
+
+void CollectVariablesTraverser::recordBuiltInFragmentOutputUsed(const char *name, bool *addedFlag)
+{
+ if (!(*addedFlag))
+ {
+ OutputVariable info;
+ setBuiltInInfoFromSymbolTable(name, &info);
+ info.staticUse = true;
+ mOutputVariables->push_back(info);
+ (*addedFlag) = true;
+ }
+}
+
+void CollectVariablesTraverser::recordBuiltInAttributeUsed(const char *name, bool *addedFlag)
+{
+ if (!(*addedFlag))
+ {
+ Attribute info;
+ setBuiltInInfoFromSymbolTable(name, &info);
+ info.staticUse = true;
+ info.location = -1;
+ mAttribs->push_back(info);
+ (*addedFlag) = true;
+ }
+}
+
+InterfaceBlock *CollectVariablesTraverser::recordGLInUsed(const TType &glInType)
+{
+ if (!mPerVertexInAdded)
+ {
+ ASSERT(glInType.getQualifier() == EvqPerVertexIn);
+ InterfaceBlock info;
+ recordInterfaceBlock(glInType, &info);
+ info.staticUse = true;
+
+ mPerVertexInAdded = true;
+ mInBlocks->push_back(info);
+ return &mInBlocks->back();
+ }
+ else
+ {
+ return FindVariable("gl_PerVertex", mInBlocks);
+ }
+}
+
+// We want to check whether a uniform/varying is statically used
+// because we only count the used ones in packing computing.
+// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
+// toward varying counting if they are statically used in a fragment
+// shader.
+void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
+{
+ ASSERT(symbol != nullptr);
+
+ if (symbol->getName().isInternal())
+ {
+ // Internal variables are not collected.
+ return;
+ }
+
+ ShaderVariable *var = nullptr;
+ const TString &symbolName = symbol->getName().getString();
+
+ if (IsVaryingIn(symbol->getQualifier()))
+ {
+ var = FindVariable(symbolName, mInputVaryings);
+ }
+ else if (IsVaryingOut(symbol->getQualifier()))
+ {
+ var = FindVariable(symbolName, mOutputVaryings);
+ }
+ else if (symbol->getType().getBasicType() == EbtInterfaceBlock)
+ {
+ UNREACHABLE();
+ }
+ else if (symbolName == "gl_DepthRange")
+ {
+ ASSERT(symbol->getQualifier() == EvqUniform);
+
+ if (!mDepthRangeAdded)
+ {
+ Uniform info;
+ const char kName[] = "gl_DepthRange";
+ info.name = kName;
+ info.mappedName = kName;
+ info.type = GL_NONE;
+ info.precision = GL_NONE;
+ info.staticUse = true;
+
+ ShaderVariable nearInfo(GL_FLOAT);
+ const char kNearName[] = "near";
+ nearInfo.name = kNearName;
+ nearInfo.mappedName = kNearName;
+ nearInfo.precision = GL_HIGH_FLOAT;
+ nearInfo.staticUse = true;
+
+ ShaderVariable farInfo(GL_FLOAT);
+ const char kFarName[] = "far";
+ farInfo.name = kFarName;
+ farInfo.mappedName = kFarName;
+ farInfo.precision = GL_HIGH_FLOAT;
+ farInfo.staticUse = true;
+
+ ShaderVariable diffInfo(GL_FLOAT);
+ const char kDiffName[] = "diff";
+ diffInfo.name = kDiffName;
+ diffInfo.mappedName = kDiffName;
+ diffInfo.precision = GL_HIGH_FLOAT;
+ diffInfo.staticUse = true;
+
+ info.fields.push_back(nearInfo);
+ info.fields.push_back(farInfo);
+ info.fields.push_back(diffInfo);
+
+ mUniforms->push_back(info);
+ mDepthRangeAdded = true;
+ }
+ }
+ else
+ {
+ switch (symbol->getQualifier())
+ {
+ case EvqAttribute:
+ case EvqVertexIn:
+ var = FindVariable(symbolName, mAttribs);
+ break;
+ case EvqFragmentOut:
+ var = FindVariable(symbolName, mOutputVariables);
+ break;
+ case EvqUniform:
+ {
+ const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
+ if (interfaceBlock)
+ {
+ var = FindVariableInInterfaceBlock(symbolName, interfaceBlock, mUniformBlocks);
+ }
+ else
+ {
+ var = FindVariable(symbolName, mUniforms);
+ }
+
+ // It's an internal error to reference an undefined user uniform
+ ASSERT(symbolName.compare(0, 3, "gl_") != 0 || var);
+ }
+ break;
+ case EvqBuffer:
+ {
+ const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
+ var =
+ FindVariableInInterfaceBlock(symbolName, interfaceBlock, mShaderStorageBlocks);
+ }
+ break;
+ case EvqFragCoord:
+ recordBuiltInVaryingUsed("gl_FragCoord", &mFragCoordAdded, mInputVaryings);
+ return;
+ case EvqFrontFacing:
+ recordBuiltInVaryingUsed("gl_FrontFacing", &mFrontFacingAdded, mInputVaryings);
+ return;
+ case EvqPointCoord:
+ recordBuiltInVaryingUsed("gl_PointCoord", &mPointCoordAdded, mInputVaryings);
+ return;
+ case EvqInstanceID:
+ // Whenever the SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW option is set,
+ // gl_InstanceID is added inside expressions to initialize ViewID_OVR and
+ // InstanceID. gl_InstanceID is not added to the symbol table for ESSL1 shaders
+ // which makes it necessary to populate the type information explicitly instead of
+ // extracting it from the symbol table.
+ if (!mInstanceIDAdded)
+ {
+ Attribute info;
+ const char kName[] = "gl_InstanceID";
+ info.name = kName;
+ info.mappedName = kName;
+ info.type = GL_INT;
+ info.precision = GL_HIGH_INT; // Defined by spec.
+ info.staticUse = true;
+ info.location = -1;
+ mAttribs->push_back(info);
+ mInstanceIDAdded = true;
+ }
+ return;
+ case EvqVertexID:
+ recordBuiltInAttributeUsed("gl_VertexID", &mVertexIDAdded);
+ return;
+ case EvqPosition:
+ recordBuiltInVaryingUsed("gl_Position", &mPositionAdded, mOutputVaryings);
+ return;
+ case EvqPointSize:
+ recordBuiltInVaryingUsed("gl_PointSize", &mPointSizeAdded, mOutputVaryings);
+ return;
+ case EvqLastFragData:
+ recordBuiltInVaryingUsed("gl_LastFragData", &mLastFragDataAdded, mInputVaryings);
+ return;
+ case EvqFragColor:
+ recordBuiltInFragmentOutputUsed("gl_FragColor", &mFragColorAdded);
+ return;
+ case EvqFragData:
+ if (!mFragDataAdded)
+ {
+ OutputVariable info;
+ setBuiltInInfoFromSymbolTable("gl_FragData", &info);
+ if (!IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers))
+ {
+ ASSERT(info.arraySizes.size() == 1u);
+ info.arraySizes.back() = 1u;
+ }
+ info.staticUse = true;
+ mOutputVariables->push_back(info);
+ mFragDataAdded = true;
+ }
+ return;
+ case EvqFragDepthEXT:
+ recordBuiltInFragmentOutputUsed("gl_FragDepthEXT", &mFragDepthEXTAdded);
+ return;
+ case EvqFragDepth:
+ recordBuiltInFragmentOutputUsed("gl_FragDepth", &mFragDepthAdded);
+ return;
+ case EvqSecondaryFragColorEXT:
+ recordBuiltInFragmentOutputUsed("gl_SecondaryFragColorEXT",
+ &mSecondaryFragColorEXTAdded);
+ return;
+ case EvqSecondaryFragDataEXT:
+ recordBuiltInFragmentOutputUsed("gl_SecondaryFragDataEXT",
+ &mSecondaryFragDataEXTAdded);
+ return;
+ case EvqInvocationID:
+ recordBuiltInVaryingUsed("gl_InvocationID", &mInvocationIDAdded, mInputVaryings);
+ break;
+ case EvqPrimitiveIDIn:
+ recordBuiltInVaryingUsed("gl_PrimitiveIDIn", &mPrimitiveIDInAdded, mInputVaryings);
+ break;
+ case EvqPrimitiveID:
+ if (mShaderType == GL_GEOMETRY_SHADER_OES)
+ {
+ recordBuiltInVaryingUsed("gl_PrimitiveID", &mPrimitiveIDAdded, mOutputVaryings);
+ }
+ else
+ {
+ ASSERT(mShaderType == GL_FRAGMENT_SHADER);
+ recordBuiltInVaryingUsed("gl_PrimitiveID", &mPrimitiveIDAdded, mInputVaryings);
+ }
+ break;
+ case EvqLayer:
+ if (mShaderType == GL_GEOMETRY_SHADER_OES)
+ {
+ recordBuiltInVaryingUsed("gl_Layer", &mLayerAdded, mOutputVaryings);
+ }
+ else if (mShaderType == GL_FRAGMENT_SHADER)
+ {
+ recordBuiltInVaryingUsed("gl_Layer", &mLayerAdded, mInputVaryings);
+ }
+ else
+ {
+ ASSERT(mShaderType == GL_VERTEX_SHADER &&
+ IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview));
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (var)
+ {
+ MarkStaticallyUsed(var);
+ }
+}
+
+void CollectVariablesTraverser::setCommonVariableProperties(const TType &type,
+ const TName &name,
+ ShaderVariable *variableOut) const
+{
+ ASSERT(variableOut);
+
+ const TStructure *structure = type.getStruct();
+
+ if (!structure)
+ {
+ variableOut->type = GLVariableType(type);
+ variableOut->precision = GLVariablePrecision(type);
+ }
+ else
+ {
+ // Structures use a NONE type that isn't exposed outside ANGLE.
+ variableOut->type = GL_NONE;
+ variableOut->structName = structure->name().c_str();
+
+ const TFieldList &fields = structure->fields();
+
+ for (TField *field : fields)
+ {
+ // Regardless of the variable type (uniform, in/out etc.) its fields are always plain
+ // ShaderVariable objects.
+ ShaderVariable fieldVariable;
+ setCommonVariableProperties(*field->type(), TName(field->name()), &fieldVariable);
+ variableOut->fields.push_back(fieldVariable);
+ }
+ }
+ variableOut->name = name.getString().c_str();
+ variableOut->mappedName = getMappedName(name);
+
+ if (auto *arraySizes = type.getArraySizes())
+ {
+ variableOut->arraySizes.assign(arraySizes->begin(), arraySizes->end());
+ }
+}
+
+Attribute CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variable) const
+{
+ const TType &type = variable.getType();
+ ASSERT(!type.getStruct());
+
+ Attribute attribute;
+ setCommonVariableProperties(type, variable.getName(), &attribute);
+
+ attribute.location = type.getLayoutQualifier().location;
+ return attribute;
+}
+
+OutputVariable CollectVariablesTraverser::recordOutputVariable(const TIntermSymbol &variable) const
+{
+ const TType &type = variable.getType();
+ ASSERT(!type.getStruct());
+
+ OutputVariable outputVariable;
+ setCommonVariableProperties(type, variable.getName(), &outputVariable);
+
+ outputVariable.location = type.getLayoutQualifier().location;
+ return outputVariable;
+}
+
+Varying CollectVariablesTraverser::recordVarying(const TIntermSymbol &variable) const
+{
+ const TType &type = variable.getType();
+
+ Varying varying;
+ setCommonVariableProperties(type, variable.getName(), &varying);
+ varying.location = type.getLayoutQualifier().location;
+
+ switch (type.getQualifier())
+ {
+ case EvqVaryingIn:
+ case EvqVaryingOut:
+ case EvqVertexOut:
+ case EvqSmoothOut:
+ case EvqFlatOut:
+ case EvqCentroidOut:
+ case EvqGeometryOut:
+ if (mSymbolTable->isVaryingInvariant(std::string(variable.getSymbol().c_str())) ||
+ type.isInvariant())
+ {
+ varying.isInvariant = true;
+ }
+ break;
+ default:
+ break;
+ }
+
+ varying.interpolation = GetInterpolationType(type.getQualifier());
+ return varying;
+}
+
+// TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks.
+void CollectVariablesTraverser::recordInterfaceBlock(const TType &interfaceBlockType,
+ InterfaceBlock *interfaceBlock) const
+{
+ ASSERT(interfaceBlockType.getBasicType() == EbtInterfaceBlock);
+ ASSERT(interfaceBlock);
+
+ const TInterfaceBlock *blockType = interfaceBlockType.getInterfaceBlock();
+ ASSERT(blockType);
+
+ interfaceBlock->name = blockType->name().c_str();
+ interfaceBlock->mappedName = getMappedName(TName(blockType->name()));
+ interfaceBlock->instanceName =
+ (blockType->hasInstanceName() ? blockType->instanceName().c_str() : "");
+ ASSERT(!interfaceBlockType.isArrayOfArrays()); // Disallowed by GLSL ES 3.10 section 4.3.9
+ interfaceBlock->arraySize = interfaceBlockType.isArray() ? interfaceBlockType.getOutermostArraySize() : 0;
+
+ interfaceBlock->blockType = GetBlockType(interfaceBlockType.getQualifier());
+ if (interfaceBlock->blockType == BlockType::BLOCK_UNIFORM ||
+ interfaceBlock->blockType == BlockType::BLOCK_BUFFER)
+ {
+ interfaceBlock->isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor);
+ interfaceBlock->binding = blockType->blockBinding();
+ interfaceBlock->layout = GetBlockLayoutType(blockType->blockStorage());
+ }
+
+ // Gather field information
+ for (const TField *field : blockType->fields())
+ {
+ const TType &fieldType = *field->type();
+
+ InterfaceBlockField fieldVariable;
+ setCommonVariableProperties(fieldType, TName(field->name()), &fieldVariable);
+ fieldVariable.isRowMajorLayout =
+ (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
+ interfaceBlock->fields.push_back(fieldVariable);
+ }
+}
+
+Uniform CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) const
+{
+ Uniform uniform;
+ setCommonVariableProperties(variable.getType(), variable.getName(), &uniform);
+ uniform.binding = variable.getType().getLayoutQualifier().binding;
+ uniform.location = variable.getType().getLayoutQualifier().location;
+ uniform.offset = variable.getType().getLayoutQualifier().offset;
+ return uniform;
+}
+
+bool CollectVariablesTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
+{
+ const TIntermSequence &sequence = *(node->getSequence());
+ ASSERT(!sequence.empty());
+
+ const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
+ TQualifier qualifier = typedNode.getQualifier();
+
+ bool isShaderVariable = qualifier == EvqAttribute || qualifier == EvqVertexIn ||
+ qualifier == EvqFragmentOut || qualifier == EvqUniform ||
+ IsVarying(qualifier);
+
+ if (typedNode.getBasicType() != EbtInterfaceBlock && !isShaderVariable)
+ {
+ return true;
+ }
+
+ for (TIntermNode *variableNode : sequence)
+ {
+ // The only case in which the sequence will not contain a TIntermSymbol node is
+ // initialization. It will contain a TInterBinary node in that case. Since attributes,
+ // uniforms, varyings, outputs and interface blocks cannot be initialized in a shader, we
+ // must have only TIntermSymbol nodes in the sequence in the cases we are interested in.
+ const TIntermSymbol &variable = *variableNode->getAsSymbolNode();
+ if (variable.getName().isInternal())
+ {
+ // Internal variables are not collected.
+ continue;
+ }
+
+ // TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks.
+ if (typedNode.getBasicType() == EbtInterfaceBlock)
+ {
+ InterfaceBlock interfaceBlock;
+ recordInterfaceBlock(variable.getType(), &interfaceBlock);
+
+ switch (qualifier)
+ {
+ case EvqUniform:
+ mUniformBlocks->push_back(interfaceBlock);
+ break;
+ case EvqBuffer:
+ mShaderStorageBlocks->push_back(interfaceBlock);
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ else
+ {
+ switch (qualifier)
+ {
+ case EvqAttribute:
+ case EvqVertexIn:
+ mAttribs->push_back(recordAttribute(variable));
+ break;
+ case EvqFragmentOut:
+ mOutputVariables->push_back(recordOutputVariable(variable));
+ break;
+ case EvqUniform:
+ mUniforms->push_back(recordUniform(variable));
+ break;
+ default:
+ if (IsVaryingIn(qualifier))
+ {
+ mInputVaryings->push_back(recordVarying(variable));
+ }
+ else
+ {
+ ASSERT(IsVaryingOut(qualifier));
+ mOutputVaryings->push_back(recordVarying(variable));
+ }
+ break;
+ }
+ }
+ }
+
+ // None of the recorded variables can have initializers, so we don't need to traverse the
+ // declarators.
+ return false;
+}
+
+// TODO(jiawei.shao@intel.com): add search on mInBlocks and mOutBlocks when implementing
+// GL_OES_shader_io_blocks.
+InterfaceBlock *CollectVariablesTraverser::findNamedInterfaceBlock(const TString &blockName) const
+{
+ InterfaceBlock *namedBlock = FindVariable(blockName, mUniformBlocks);
+ if (!namedBlock)
+ {
+ namedBlock = FindVariable(blockName, mShaderStorageBlocks);
+ }
+ return namedBlock;
+}
+
+bool CollectVariablesTraverser::visitBinary(Visit, TIntermBinary *binaryNode)
+{
+ if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
+ {
+ // NOTE: we do not determine static use for individual blocks of an array
+ TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
+ ASSERT(blockNode);
+
+ TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
+ ASSERT(constantUnion);
+
+ InterfaceBlock *namedBlock = nullptr;
+
+ bool traverseIndexExpression = false;
+ TIntermBinary *interfaceIndexingNode = blockNode->getAsBinaryNode();
+ if (interfaceIndexingNode)
+ {
+ TIntermTyped *interfaceNode = interfaceIndexingNode->getLeft()->getAsTyped();
+ ASSERT(interfaceNode);
+
+ const TType &interfaceType = interfaceNode->getType();
+ if (interfaceType.getQualifier() == EvqPerVertexIn)
+ {
+ namedBlock = recordGLInUsed(interfaceType);
+ ASSERT(namedBlock);
+
+ // We need to continue traversing to collect useful variables in the index
+ // expression of gl_in.
+ traverseIndexExpression = true;
+ }
+ }
+
+ const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
+ if (!namedBlock)
+ {
+ namedBlock = findNamedInterfaceBlock(interfaceBlock->name());
+ }
+ ASSERT(namedBlock);
+ namedBlock->staticUse = true;
+ unsigned int fieldIndex = static_cast<unsigned int>(constantUnion->getIConst(0));
+ ASSERT(fieldIndex < namedBlock->fields.size());
+ namedBlock->fields[fieldIndex].staticUse = true;
+
+ if (traverseIndexExpression)
+ {
+ ASSERT(interfaceIndexingNode);
+ interfaceIndexingNode->getRight()->traverse(this);
+ }
+ return false;
+ }
+
+ return true;
+}
+
+} // anonymous namespace
+
+void CollectVariables(TIntermBlock *root,
+ std::vector<Attribute> *attributes,
+ std::vector<OutputVariable> *outputVariables,
+ std::vector<Uniform> *uniforms,
+ std::vector<Varying> *inputVaryings,
+ std::vector<Varying> *outputVaryings,
+ std::vector<InterfaceBlock> *uniformBlocks,
+ std::vector<InterfaceBlock> *shaderStorageBlocks,
+ std::vector<InterfaceBlock> *inBlocks,
+ ShHashFunction64 hashFunction,
+ TSymbolTable *symbolTable,
+ int shaderVersion,
+ GLenum shaderType,
+ const TExtensionBehavior &extensionBehavior)
+{
+ CollectVariablesTraverser collect(attributes, outputVariables, uniforms, inputVaryings,
+ outputVaryings, uniformBlocks, shaderStorageBlocks, inBlocks,
+ hashFunction, symbolTable, shaderVersion, shaderType,
+ extensionBehavior);
+ root->traverse(&collect);
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/CollectVariables.h b/src/3rdparty/angle/src/compiler/translator/CollectVariables.h
new file mode 100644
index 0000000000..4d0d1192e0
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/CollectVariables.h
@@ -0,0 +1,37 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// CollectVariables.h: Collect lists of shader interface variables based on the AST.
+
+#ifndef COMPILER_TRANSLATOR_COLLECTVARIABLES_H_
+#define COMPILER_TRANSLATOR_COLLECTVARIABLES_H_
+
+#include <GLSLANG/ShaderLang.h>
+
+#include "compiler/translator/ExtensionBehavior.h"
+
+namespace sh
+{
+
+class TIntermBlock;
+class TSymbolTable;
+
+void CollectVariables(TIntermBlock *root,
+ std::vector<Attribute> *attributes,
+ std::vector<OutputVariable> *outputVariables,
+ std::vector<Uniform> *uniforms,
+ std::vector<Varying> *inputVaryings,
+ std::vector<Varying> *outputVaryings,
+ std::vector<InterfaceBlock> *uniformBlocks,
+ std::vector<InterfaceBlock> *shaderStorageBlocks,
+ std::vector<InterfaceBlock> *inBlocks,
+ ShHashFunction64 hashFunction,
+ TSymbolTable *symbolTable,
+ int shaderVersion,
+ GLenum shaderType,
+ const TExtensionBehavior &extensionBehavior);
+}
+
+#endif // COMPILER_TRANSLATOR_COLLECTVARIABLES_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/Common.h b/src/3rdparty/angle/src/compiler/translator/Common.h
index 60223232af..cb3a680d85 100644
--- a/src/3rdparty/angle/src/compiler/translator/Common.h
+++ b/src/3rdparty/angle/src/compiler/translator/Common.h
@@ -10,15 +10,21 @@
#include <map>
#include <sstream>
#include <string>
+#include <unordered_map>
#include <vector>
#include <limits>
#include <stdio.h>
#include "common/angleutils.h"
#include "common/debug.h"
+#include "common/third_party/smhasher/src/PMurHash.h"
#include "compiler/translator/PoolAlloc.h"
-struct TSourceLoc {
+namespace sh
+{
+
+struct TSourceLoc
+{
int first_file;
int first_line;
int last_file;
@@ -29,25 +35,25 @@ struct TSourceLoc {
// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme.
//
#define POOL_ALLOCATOR_NEW_DELETE() \
- void* operator new(size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \
- void* operator new(size_t, void *_Where) { return (_Where); } \
- void operator delete(void*) { } \
- void operator delete(void *, void *) { } \
- void* operator new[](size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \
- void* operator new[](size_t, void *_Where) { return (_Where); } \
- void operator delete[](void*) { } \
- void operator delete[](void *, void *) { }
+ void *operator new(size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \
+ void *operator new(size_t, void *_Where) { return (_Where); } \
+ void operator delete(void *) {} \
+ void operator delete(void *, void *) {} \
+ void *operator new[](size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \
+ void *operator new[](size_t, void *_Where) { return (_Where); } \
+ void operator delete[](void *) {} \
+ void operator delete[](void *, void *) {}
//
// Pool version of string.
//
typedef pool_allocator<char> TStringAllocator;
-typedef std::basic_string <char, std::char_traits<char>, TStringAllocator> TString;
+typedef std::basic_string<char, std::char_traits<char>, TStringAllocator> TString;
typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream;
-inline TString* NewPoolTString(const char* s)
+inline TString *NewPoolTString(const char *s)
{
- void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TString));
- return new(memory) TString(s);
+ void *memory = GetGlobalPoolAllocator()->allocate(sizeof(TString));
+ return new (memory) TString(s);
}
//
@@ -64,21 +70,44 @@ template <class T>
class TVector : public std::vector<T, pool_allocator<T>>
{
public:
+ POOL_ALLOCATOR_NEW_DELETE();
+
typedef typename std::vector<T, pool_allocator<T>>::size_type size_type;
TVector() : std::vector<T, pool_allocator<T>>() {}
TVector(const pool_allocator<T> &a) : std::vector<T, pool_allocator<T>>(a) {}
TVector(size_type i) : std::vector<T, pool_allocator<T>>(i) {}
};
+template <class K, class D, class H = std::hash<K>, class CMP = std::equal_to<K>>
+class TUnorderedMap : public std::unordered_map<K, D, H, CMP, pool_allocator<std::pair<const K, D>>>
+{
+ public:
+ POOL_ALLOCATOR_NEW_DELETE();
+ typedef pool_allocator<std::pair<const K, D>> tAllocator;
+
+ TUnorderedMap() : std::unordered_map<K, D, H, CMP, tAllocator>() {}
+ // use correct two-stage name lookup supported in gcc 3.4 and above
+ TUnorderedMap(const tAllocator &a)
+ : std::unordered_map<K, D, H, CMP, tAllocator>(
+ std::unordered_map<K, D, H, CMP, tAllocator>::key_compare(),
+ a)
+ {
+ }
+};
+
template <class K, class D, class CMP = std::less<K>>
class TMap : public std::map<K, D, CMP, pool_allocator<std::pair<const K, D>>>
{
public:
+ POOL_ALLOCATOR_NEW_DELETE();
typedef pool_allocator<std::pair<const K, D>> tAllocator;
TMap() : std::map<K, D, CMP, tAllocator>() {}
// use correct two-stage name lookup supported in gcc 3.4 and above
- TMap(const tAllocator& a) : std::map<K, D, CMP, tAllocator>(std::map<K, D, CMP, tAllocator>::key_compare(), a) {}
+ TMap(const tAllocator &a)
+ : std::map<K, D, CMP, tAllocator>(std::map<K, D, CMP, tAllocator>::key_compare(), a)
+ {
+ }
};
// Integer to TString conversion
@@ -92,4 +121,18 @@ inline TString str(T i)
return buffer;
}
-#endif // COMPILER_TRANSLATOR_COMMON_H_
+} // namespace sh
+
+namespace std
+{
+template <>
+struct hash<sh::TString>
+{
+ size_t operator()(const sh::TString &s) const
+ {
+ return angle::PMurHash32(0, s.data(), static_cast<int>(s.length()));
+ }
+};
+} // namespace std
+
+#endif // COMPILER_TRANSLATOR_COMMON_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp
index 18524ce569..2f411cb58c 100644
--- a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp
@@ -4,91 +4,193 @@
// found in the LICENSE file.
//
-#include "compiler/translator/Cache.h"
#include "compiler/translator/Compiler.h"
+
+#include <sstream>
+
+#include "angle_gl.h"
+#include "common/utilities.h"
+#include "compiler/translator/AddAndTrueToLoopCondition.h"
+#include "compiler/translator/Cache.h"
#include "compiler/translator/CallDAG.h"
-#include "compiler/translator/ForLoopUnroll.h"
+#include "compiler/translator/ClampPointSize.h"
+#include "compiler/translator/CollectVariables.h"
+#include "compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h"
+#include "compiler/translator/DeferGlobalInitializers.h"
+#include "compiler/translator/EmulateGLFragColorBroadcast.h"
+#include "compiler/translator/EmulatePrecision.h"
#include "compiler/translator/Initialize.h"
-#include "compiler/translator/InitializeParseContext.h"
#include "compiler/translator/InitializeVariables.h"
+#include "compiler/translator/IntermNodePatternMatcher.h"
+#include "compiler/translator/IsASTDepthBelowLimit.h"
+#include "compiler/translator/OutputTree.h"
#include "compiler/translator/ParseContext.h"
-#include "compiler/translator/PruneEmptyDeclarations.h"
+#include "compiler/translator/PruneNoOps.h"
#include "compiler/translator/RegenerateStructNames.h"
+#include "compiler/translator/RemoveArrayLengthMethod.h"
+#include "compiler/translator/RemoveEmptySwitchStatements.h"
+#include "compiler/translator/RemoveInvariantDeclaration.h"
+#include "compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h"
#include "compiler/translator/RemovePow.h"
-#include "compiler/translator/RenameFunction.h"
+#include "compiler/translator/RemoveUnreferencedVariables.h"
#include "compiler/translator/RewriteDoWhile.h"
#include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h"
+#include "compiler/translator/SeparateDeclarations.h"
+#include "compiler/translator/SimplifyLoopConditions.h"
+#include "compiler/translator/SplitSequenceOperator.h"
#include "compiler/translator/UnfoldShortCircuitAST.h"
+#include "compiler/translator/UseInterfaceBlockFields.h"
#include "compiler/translator/ValidateLimitations.h"
+#include "compiler/translator/ValidateMaxParameters.h"
#include "compiler/translator/ValidateOutputs.h"
+#include "compiler/translator/ValidateVaryingLocations.h"
#include "compiler/translator/VariablePacker.h"
-#include "compiler/translator/depgraph/DependencyGraph.h"
-#include "compiler/translator/depgraph/DependencyGraphOutput.h"
-#include "compiler/translator/timing/RestrictFragmentShaderTiming.h"
-#include "compiler/translator/timing/RestrictVertexShaderTiming.h"
+#include "compiler/translator/VectorizeVectorScalarArithmetic.h"
+#include "compiler/translator/util.h"
#include "third_party/compiler/ArrayBoundsClamper.h"
-#include "angle_gl.h"
-#include "common/utilities.h"
+
+namespace sh
+{
+
+namespace
+{
+
+#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
+void DumpFuzzerCase(char const *const *shaderStrings,
+ size_t numStrings,
+ uint32_t type,
+ uint32_t spec,
+ uint32_t output,
+ uint64_t options)
+{
+ static int fileIndex = 0;
+
+ std::ostringstream o;
+ o << "corpus/" << fileIndex++ << ".sample";
+ std::string s = o.str();
+
+ // Must match the input format of the fuzzer
+ FILE *f = fopen(s.c_str(), "w");
+ fwrite(&type, sizeof(type), 1, f);
+ fwrite(&spec, sizeof(spec), 1, f);
+ fwrite(&output, sizeof(output), 1, f);
+ fwrite(&options, sizeof(options), 1, f);
+
+ char zero[128 - 20] = {0};
+ fwrite(&zero, 128 - 20, 1, f);
+
+ for (size_t i = 0; i < numStrings; i++)
+ {
+ fwrite(shaderStrings[i], sizeof(char), strlen(shaderStrings[i]), f);
+ }
+ fwrite(&zero, 1, 1, f);
+
+ fclose(f);
+}
+#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
+} // anonymous namespace
bool IsWebGLBasedSpec(ShShaderSpec spec)
{
- return (spec == SH_WEBGL_SPEC ||
- spec == SH_CSS_SHADERS_SPEC ||
- spec == SH_WEBGL2_SPEC);
+ return (spec == SH_WEBGL_SPEC || spec == SH_WEBGL2_SPEC || spec == SH_WEBGL3_SPEC);
}
bool IsGLSL130OrNewer(ShShaderOutput output)
{
- return (output == SH_GLSL_130_OUTPUT ||
- output == SH_GLSL_140_OUTPUT ||
- output == SH_GLSL_150_CORE_OUTPUT ||
- output == SH_GLSL_330_CORE_OUTPUT ||
- output == SH_GLSL_400_CORE_OUTPUT ||
- output == SH_GLSL_410_CORE_OUTPUT ||
- output == SH_GLSL_420_CORE_OUTPUT ||
- output == SH_GLSL_430_CORE_OUTPUT ||
- output == SH_GLSL_440_CORE_OUTPUT ||
- output == SH_GLSL_450_CORE_OUTPUT);
+ return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
+ output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
+ output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT ||
+ output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
+ output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
+}
+
+bool IsGLSL420OrNewer(ShShaderOutput output)
+{
+ return (output == SH_GLSL_420_CORE_OUTPUT || output == SH_GLSL_430_CORE_OUTPUT ||
+ output == SH_GLSL_440_CORE_OUTPUT || output == SH_GLSL_450_CORE_OUTPUT);
+}
+
+bool IsGLSL410OrOlder(ShShaderOutput output)
+{
+ return (output == SH_GLSL_130_OUTPUT || output == SH_GLSL_140_OUTPUT ||
+ output == SH_GLSL_150_CORE_OUTPUT || output == SH_GLSL_330_CORE_OUTPUT ||
+ output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT);
+}
+
+bool RemoveInvariant(sh::GLenum shaderType,
+ int shaderVersion,
+ ShShaderOutput outputType,
+ ShCompileOptions compileOptions)
+{
+ if ((compileOptions & SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT) == 0 &&
+ shaderType == GL_FRAGMENT_SHADER && IsGLSL420OrNewer(outputType))
+ return true;
+
+ if ((compileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0 &&
+ shaderVersion >= 300 && shaderType == GL_VERTEX_SHADER)
+ return true;
+
+ return false;
}
size_t GetGlobalMaxTokenSize(ShShaderSpec spec)
{
- // WebGL defines a max token legnth of 256, while ES2 leaves max token
+ // WebGL defines a max token length of 256, while ES2 leaves max token
// size undefined. ES3 defines a max size of 1024 characters.
switch (spec)
{
- case SH_WEBGL_SPEC:
- case SH_CSS_SHADERS_SPEC:
- return 256;
- default:
- return 1024;
+ case SH_WEBGL_SPEC:
+ return 256;
+ default:
+ return 1024;
}
}
-namespace {
+int GetMaxUniformVectorsForShaderType(GLenum shaderType, const ShBuiltInResources &resources)
+{
+ switch (shaderType)
+ {
+ case GL_VERTEX_SHADER:
+ return resources.MaxVertexUniformVectors;
+ case GL_FRAGMENT_SHADER:
+ return resources.MaxFragmentUniformVectors;
+
+ // TODO (jiawei.shao@intel.com): check if we need finer-grained component counting
+ case GL_COMPUTE_SHADER:
+ return resources.MaxComputeUniformComponents / 4;
+ case GL_GEOMETRY_SHADER_OES:
+ return resources.MaxGeometryUniformComponents / 4;
+ default:
+ UNREACHABLE();
+ return -1;
+ }
+}
+
+namespace
+{
class TScopedPoolAllocator
{
public:
- TScopedPoolAllocator(TPoolAllocator* allocator) : mAllocator(allocator)
+ TScopedPoolAllocator(TPoolAllocator *allocator) : mAllocator(allocator)
{
mAllocator->push();
SetGlobalPoolAllocator(mAllocator);
}
~TScopedPoolAllocator()
{
- SetGlobalPoolAllocator(NULL);
+ SetGlobalPoolAllocator(nullptr);
mAllocator->pop();
}
private:
- TPoolAllocator* mAllocator;
+ TPoolAllocator *mAllocator;
};
class TScopedSymbolTableLevel
{
public:
- TScopedSymbolTableLevel(TSymbolTable* table) : mTable(table)
+ TScopedSymbolTableLevel(TSymbolTable *table) : mTable(table)
{
ASSERT(mTable->atBuiltInLevel());
mTable->push();
@@ -100,23 +202,25 @@ class TScopedSymbolTableLevel
}
private:
- TSymbolTable* mTable;
+ TSymbolTable *mTable;
};
int MapSpecToShaderVersion(ShShaderSpec spec)
{
switch (spec)
{
- case SH_GLES2_SPEC:
- case SH_WEBGL_SPEC:
- case SH_CSS_SHADERS_SPEC:
- return 100;
- case SH_GLES3_SPEC:
- case SH_WEBGL2_SPEC:
- return 300;
- default:
- UNREACHABLE();
- return 0;
+ case SH_GLES2_SPEC:
+ case SH_WEBGL_SPEC:
+ return 100;
+ case SH_GLES3_SPEC:
+ case SH_WEBGL2_SPEC:
+ return 300;
+ case SH_GLES3_1_SPEC:
+ case SH_WEBGL3_SPEC:
+ return 310;
+ default:
+ UNREACHABLE();
+ return 0;
}
}
@@ -130,22 +234,31 @@ TShHandleBase::TShHandleBase()
TShHandleBase::~TShHandleBase()
{
- SetGlobalPoolAllocator(NULL);
+ SetGlobalPoolAllocator(nullptr);
allocator.popAll();
}
TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
- : shaderType(type),
+ : variablesCollected(false),
+ mGLPositionInitialized(false),
+ shaderType(type),
shaderSpec(spec),
outputType(output),
maxUniformVectors(0),
maxExpressionComplexity(0),
maxCallStackDepth(0),
+ maxFunctionParameters(0),
fragmentPrecisionHigh(false),
clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
builtInFunctionEmulator(),
- mSourcePath(NULL),
- mTemporaryIndex(0)
+ mDiagnostics(infoSink.info),
+ mSourcePath(nullptr),
+ mComputeShaderLocalSizeDeclared(false),
+ mComputeShaderLocalSize(1),
+ mGeometryShaderMaxVertices(-1),
+ mGeometryShaderInvocations(0),
+ mGeometryShaderInputPrimitiveType(EptUndefined),
+ mGeometryShaderOutputPrimitiveType(EptUndefined)
{
}
@@ -153,7 +266,7 @@ TCompiler::~TCompiler()
{
}
-bool TCompiler::shouldRunLoopAndIndexingValidation(int compileOptions) const
+bool TCompiler::shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const
{
// If compiling an ESSL 1.00 shader for WebGL, or if its been requested through the API,
// validate loop and indexing as well (to verify that the shader only uses minimal functionality
@@ -162,14 +275,15 @@ bool TCompiler::shouldRunLoopAndIndexingValidation(int compileOptions) const
(compileOptions & SH_VALIDATE_LOOP_INDEXING);
}
-bool TCompiler::Init(const ShBuiltInResources& resources)
+bool TCompiler::Init(const ShBuiltInResources &resources)
{
shaderVersion = 100;
- maxUniformVectors = (shaderType == GL_VERTEX_SHADER) ?
- resources.MaxVertexUniformVectors :
- resources.MaxFragmentUniformVectors;
+
+ maxUniformVectors = GetMaxUniformVectorsForShaderType(shaderType, resources);
+
maxExpressionComplexity = resources.MaxExpressionComplexity;
- maxCallStackDepth = resources.MaxCallStackDepth;
+ maxCallStackDepth = resources.MaxCallStackDepth;
+ maxFunctionParameters = resources.MaxFunctionParameters;
SetGlobalPoolAllocator(&allocator);
@@ -187,15 +301,16 @@ bool TCompiler::Init(const ShBuiltInResources& resources)
return true;
}
-TIntermNode *TCompiler::compileTreeForTesting(const char* const shaderStrings[],
- size_t numStrings, int compileOptions)
+TIntermBlock *TCompiler::compileTreeForTesting(const char *const shaderStrings[],
+ size_t numStrings,
+ ShCompileOptions compileOptions)
{
return compileTreeImpl(shaderStrings, numStrings, compileOptions);
}
-TIntermNode *TCompiler::compileTreeImpl(const char *const shaderStrings[],
- size_t numStrings,
- const int compileOptions)
+TIntermBlock *TCompiler::compileTreeImpl(const char *const shaderStrings[],
+ size_t numStrings,
+ const ShCompileOptions compileOptions)
{
clearResults();
@@ -213,191 +328,347 @@ TIntermNode *TCompiler::compileTreeImpl(const char *const shaderStrings[],
++firstSource;
}
- TIntermediate intermediate(infoSink);
- TParseContext parseContext(symbolTable, extensionBehavior, intermediate, shaderType, shaderSpec,
- compileOptions, true, infoSink, getResources());
+ TParseContext parseContext(symbolTable, extensionBehavior, shaderType, shaderSpec,
+ compileOptions, true, &mDiagnostics, getResources());
parseContext.setFragmentPrecisionHighOnESSL1(fragmentPrecisionHigh);
- SetGlobalParseContext(&parseContext);
// We preserve symbols at the built-in level from compile-to-compile.
// Start pushing the user-defined symbols at global level.
TScopedSymbolTableLevel scopedSymbolLevel(&symbolTable);
// Parse shader.
- bool success =
- (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr, &parseContext) == 0) &&
- (parseContext.getTreeRoot() != nullptr);
+ if (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], nullptr,
+ &parseContext) != 0)
+ {
+ return nullptr;
+ }
+
+ if (parseContext.getTreeRoot() == nullptr)
+ {
+ return nullptr;
+ }
+
+ setASTMetadata(parseContext);
+
+ if (MapSpecToShaderVersion(shaderSpec) < shaderVersion)
+ {
+ mDiagnostics.globalError("unsupported shader version");
+ return nullptr;
+ }
+ TIntermBlock *root = parseContext.getTreeRoot();
+ if (!checkAndSimplifyAST(root, parseContext, compileOptions))
+ {
+ return nullptr;
+ }
+
+ return root;
+}
+
+void TCompiler::setASTMetadata(const TParseContext &parseContext)
+{
shaderVersion = parseContext.getShaderVersion();
- if (success && MapSpecToShaderVersion(shaderSpec) < shaderVersion)
+
+ mPragma = parseContext.pragma();
+ symbolTable.setGlobalInvariant(mPragma.stdgl.invariantAll);
+
+ mComputeShaderLocalSizeDeclared = parseContext.isComputeShaderLocalSizeDeclared();
+ mComputeShaderLocalSize = parseContext.getComputeShaderLocalSize();
+
+ mNumViews = parseContext.getNumViews();
+
+ // Highp might have been auto-enabled based on shader version
+ fragmentPrecisionHigh = parseContext.getFragmentPrecisionHigh();
+
+ if (shaderType == GL_GEOMETRY_SHADER_OES)
{
- infoSink.info.prefix(EPrefixError);
- infoSink.info << "unsupported shader version";
- success = false;
+ mGeometryShaderInputPrimitiveType = parseContext.getGeometryShaderInputPrimitiveType();
+ mGeometryShaderOutputPrimitiveType = parseContext.getGeometryShaderOutputPrimitiveType();
+ mGeometryShaderMaxVertices = parseContext.getGeometryShaderMaxVertices();
+ mGeometryShaderInvocations = parseContext.getGeometryShaderInvocations();
}
+}
- TIntermNode *root = nullptr;
+bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
+ const TParseContext &parseContext,
+ ShCompileOptions compileOptions)
+{
+ // Disallow expressions deemed too complex.
+ if ((compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY) && !limitExpressionComplexity(root))
+ {
+ return false;
+ }
- if (success)
+ // We prune no-ops to work around driver bugs and to keep AST processing and output simple.
+ // The following kinds of no-ops are pruned:
+ // 1. Empty declarations "int;".
+ // 2. Literal statements: "1.0;". The ESSL output doesn't define a default precision
+ // for float, so float literal statements would end up with no precision which is
+ // invalid ESSL.
+ // After this empty declarations are not allowed in the AST.
+ PruneNoOps(root);
+
+ // In case the last case inside a switch statement is a certain type of no-op, GLSL
+ // compilers in drivers may not accept it. In this case we clean up the dead code from the
+ // end of switch statements. This is also required because PruneNoOps may have left switch
+ // statements that only contained an empty declaration inside the final case in an invalid
+ // state. Relies on that PruneNoOps has already been run.
+ RemoveNoOpCasesFromEndOfSwitchStatements(root, &symbolTable);
+
+ // Remove empty switch statements - this makes output simpler.
+ RemoveEmptySwitchStatements(root);
+
+ // Create the function DAG and check there is no recursion
+ if (!initCallDag(root))
{
- mPragma = parseContext.pragma();
- if (mPragma.stdgl.invariantAll)
- {
- symbolTable.setGlobalInvariant();
- }
+ return false;
+ }
- root = parseContext.getTreeRoot();
- root = intermediate.postProcess(root);
+ if ((compileOptions & SH_LIMIT_CALL_STACK_DEPTH) && !checkCallDepth())
+ {
+ return false;
+ }
- // Highp might have been auto-enabled based on shader version
- fragmentPrecisionHigh = parseContext.getFragmentPrecisionHigh();
+ // Checks which functions are used and if "main" exists
+ functionMetadata.clear();
+ functionMetadata.resize(mCallDag.size());
+ if (!tagUsedFunctions())
+ {
+ return false;
+ }
- // Disallow expressions deemed too complex.
- if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY))
- success = limitExpressionComplexity(root);
+ if (!(compileOptions & SH_DONT_PRUNE_UNUSED_FUNCTIONS))
+ {
+ pruneUnusedFunctions(root);
+ }
- // Create the function DAG and check there is no recursion
- if (success)
- success = initCallDag(root);
+ if (shaderVersion >= 310 && !ValidateVaryingLocations(root, &mDiagnostics, shaderType))
+ {
+ return false;
+ }
- if (success && (compileOptions & SH_LIMIT_CALL_STACK_DEPTH))
- success = checkCallDepth();
+ if (shaderVersion >= 300 && shaderType == GL_FRAGMENT_SHADER &&
+ !ValidateOutputs(root, getExtensionBehavior(), compileResources.MaxDrawBuffers,
+ &mDiagnostics))
+ {
+ return false;
+ }
- // Checks which functions are used and if "main" exists
- if (success)
- {
- functionMetadata.clear();
- functionMetadata.resize(mCallDag.size());
- success = tagUsedFunctions();
- }
+ if (shouldRunLoopAndIndexingValidation(compileOptions) &&
+ !ValidateLimitations(root, shaderType, &symbolTable, shaderVersion, &mDiagnostics))
+ {
+ return false;
+ }
- if (success && !(compileOptions & SH_DONT_PRUNE_UNUSED_FUNCTIONS))
- success = pruneUnusedFunctions(root);
+ // Fail compilation if precision emulation not supported.
+ if (getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision &&
+ !EmulatePrecision::SupportedInLanguage(outputType))
+ {
+ mDiagnostics.globalError("Precision emulation not supported for this output type.");
+ return false;
+ }
- // Prune empty declarations to work around driver bugs and to keep declaration output simple.
- if (success)
- PruneEmptyDeclarations(root);
+ // Clamping uniform array bounds needs to happen after validateLimitations pass.
+ if (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS)
+ {
+ arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
+ }
- if (success && shaderVersion == 300 && shaderType == GL_FRAGMENT_SHADER)
- success = validateOutputs(root);
+ if ((compileOptions & SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW) &&
+ parseContext.isExtensionEnabled(TExtension::OVR_multiview) &&
+ getShaderType() != GL_COMPUTE_SHADER)
+ {
+ DeclareAndInitBuiltinsForInstancedMultiview(root, mNumViews, shaderType, compileOptions,
+ outputType, &symbolTable);
+ }
- if (success && shouldRunLoopAndIndexingValidation(compileOptions))
- success = validateLimitations(root);
+ // This pass might emit short circuits so keep it before the short circuit unfolding
+ if (compileOptions & SH_REWRITE_DO_WHILE_LOOPS)
+ RewriteDoWhile(root, &symbolTable);
- if (success && (compileOptions & SH_TIMING_RESTRICTIONS))
- success = enforceTimingRestrictions(root, (compileOptions & SH_DEPENDENCY_GRAPH) != 0);
+ if (compileOptions & SH_ADD_AND_TRUE_TO_LOOP_CONDITION)
+ sh::AddAndTrueToLoopCondition(root);
- if (success && shaderSpec == SH_CSS_SHADERS_SPEC)
- rewriteCSSShader(root);
+ if (compileOptions & SH_UNFOLD_SHORT_CIRCUIT)
+ {
+ UnfoldShortCircuitAST unfoldShortCircuit;
+ root->traverse(&unfoldShortCircuit);
+ unfoldShortCircuit.updateTree();
+ }
- // Unroll for-loop markup needs to happen after validateLimitations pass.
- if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX))
- {
- ForLoopUnrollMarker marker(ForLoopUnrollMarker::kIntegerIndex,
- shouldRunLoopAndIndexingValidation(compileOptions));
- root->traverse(&marker);
- }
- if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX))
- {
- ForLoopUnrollMarker marker(ForLoopUnrollMarker::kSamplerArrayIndex,
- shouldRunLoopAndIndexingValidation(compileOptions));
- root->traverse(&marker);
- if (marker.samplerArrayIndexIsFloatLoopIndex())
- {
- infoSink.info.prefix(EPrefixError);
- infoSink.info << "sampler array index is float loop index";
- success = false;
- }
- }
+ if (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT)
+ {
+ RemovePow(root);
+ }
- // Built-in function emulation needs to happen after validateLimitations pass.
- if (success)
- {
- initBuiltInFunctionEmulator(&builtInFunctionEmulator, compileOptions);
- builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root);
- }
+ if (compileOptions & SH_REGENERATE_STRUCT_NAMES)
+ {
+ RegenerateStructNames gen(&symbolTable, shaderVersion);
+ root->traverse(&gen);
+ }
- // Clamping uniform array bounds needs to happen after validateLimitations pass.
- if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
- arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
+ if (shaderType == GL_FRAGMENT_SHADER && shaderVersion == 100 &&
+ compileResources.EXT_draw_buffers && compileResources.MaxDrawBuffers > 1 &&
+ IsExtensionEnabled(extensionBehavior, TExtension::EXT_draw_buffers))
+ {
+ EmulateGLFragColorBroadcast(root, compileResources.MaxDrawBuffers, &outputVariables,
+ &symbolTable, shaderVersion);
+ }
- // gl_Position is always written in compatibility output mode
- if (success && shaderType == GL_VERTEX_SHADER &&
- ((compileOptions & SH_INIT_GL_POSITION) ||
- (outputType == SH_GLSL_COMPATIBILITY_OUTPUT)))
- initializeGLPosition(root);
+ // Split multi declarations and remove calls to array length().
+ // Note that SimplifyLoopConditions needs to be run before any other AST transformations
+ // that may need to generate new statements from loop conditions or loop expressions.
+ SimplifyLoopConditions(
+ root,
+ IntermNodePatternMatcher::kMultiDeclaration | IntermNodePatternMatcher::kArrayLengthMethod,
+ &getSymbolTable(), getShaderVersion());
- // This pass might emit short circuits so keep it before the short circuit unfolding
- if (success && (compileOptions & SH_REWRITE_DO_WHILE_LOOPS))
- RewriteDoWhile(root, getTemporaryIndex());
+ // Note that separate declarations need to be run before other AST transformations that
+ // generate new statements from expressions.
+ SeparateDeclarations(root);
- if (success && (compileOptions & SH_UNFOLD_SHORT_CIRCUIT))
- {
- UnfoldShortCircuitAST unfoldShortCircuit;
- root->traverse(&unfoldShortCircuit);
- unfoldShortCircuit.updateTree();
- }
+ SplitSequenceOperator(root, IntermNodePatternMatcher::kArrayLengthMethod, &getSymbolTable(),
+ getShaderVersion());
+
+ RemoveArrayLengthMethod(root);
+
+ RemoveUnreferencedVariables(root, &symbolTable);
- if (success && (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT))
+ // Built-in function emulation needs to happen after validateLimitations pass.
+ // TODO(jmadill): Remove global pool allocator.
+ GetGlobalPoolAllocator()->lock();
+ initBuiltInFunctionEmulator(&builtInFunctionEmulator, compileOptions);
+ GetGlobalPoolAllocator()->unlock();
+ builtInFunctionEmulator.markBuiltInFunctionsForEmulation(root);
+
+ if (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS)
+ {
+ ScalarizeVecAndMatConstructorArgs(root, shaderType, fragmentPrecisionHigh, &symbolTable);
+ }
+
+ if (shouldCollectVariables(compileOptions))
+ {
+ ASSERT(!variablesCollected);
+ CollectVariables(root, &attributes, &outputVariables, &uniforms, &inputVaryings,
+ &outputVaryings, &uniformBlocks, &shaderStorageBlocks, &inBlocks,
+ hashFunction, &symbolTable, shaderVersion, shaderType, extensionBehavior);
+ collectInterfaceBlocks();
+ variablesCollected = true;
+ if (compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS)
{
- RemovePow(root);
+ useAllMembersInUnusedStandardAndSharedBlocks(root);
}
-
- if (success && shouldCollectVariables(compileOptions))
+ if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS)
{
- collectVariables(root);
- if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS)
+ // Returns true if, after applying the packing rules in the GLSL ES 1.00.17 spec
+ // Appendix A, section 7, the shader does not use too many uniforms.
+ if (!CheckVariablesInPackingLimits(maxUniformVectors, uniforms))
{
- success = enforcePackingRestrictions();
- if (!success)
- {
- infoSink.info.prefix(EPrefixError);
- infoSink.info << "too many uniforms";
- }
+ mDiagnostics.globalError("too many uniforms");
+ return false;
}
- if (success && shaderType == GL_VERTEX_SHADER &&
- (compileOptions & SH_INIT_VARYINGS_WITHOUT_STATIC_USE))
- initializeVaryingsWithoutStaticUse(root);
}
-
- if (success && (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS))
+ if (compileOptions & SH_INIT_OUTPUT_VARIABLES)
{
- ScalarizeVecAndMatConstructorArgs scalarizer(
- shaderType, fragmentPrecisionHigh);
- root->traverse(&scalarizer);
+ initializeOutputVariables(root);
}
+ }
+
+ // Removing invariant declarations must be done after collecting variables.
+ // Otherwise, built-in invariant declarations don't apply.
+ if (RemoveInvariant(shaderType, shaderVersion, outputType, compileOptions))
+ {
+ RemoveInvariantDeclaration(root);
+ }
+
+ // gl_Position is always written in compatibility output mode.
+ // It may have been already initialized among other output variables, in that case we don't
+ // need to initialize it twice.
+ if (shaderType == GL_VERTEX_SHADER && !mGLPositionInitialized &&
+ ((compileOptions & SH_INIT_GL_POSITION) || (outputType == SH_GLSL_COMPATIBILITY_OUTPUT)))
+ {
+ initializeGLPosition(root);
+ mGLPositionInitialized = true;
+ }
+
+ // DeferGlobalInitializers needs to be run before other AST transformations that generate new
+ // statements from expressions. But it's fine to run DeferGlobalInitializers after the above
+ // SplitSequenceOperator and RemoveArrayLengthMethod since they only have an effect on the AST
+ // on ESSL >= 3.00, and the initializers that need to be deferred can only exist in ESSL < 3.00.
+ bool initializeLocalsAndGlobals =
+ (compileOptions & SH_INITIALIZE_UNINITIALIZED_LOCALS) && !IsOutputHLSL(getOutputType());
+ bool canUseLoopsToInitialize = !(compileOptions & SH_DONT_USE_LOOPS_TO_INITIALIZE_VARIABLES);
+ DeferGlobalInitializers(root, initializeLocalsAndGlobals, canUseLoopsToInitialize, &symbolTable);
- if (success && (compileOptions & SH_REGENERATE_STRUCT_NAMES))
+ if (initializeLocalsAndGlobals)
+ {
+ // Initialize uninitialized local variables.
+ // In some cases initializing can generate extra statements in the parent block, such as
+ // when initializing nameless structs or initializing arrays in ESSL 1.00. In that case
+ // we need to first simplify loop conditions. We've already separated declarations
+ // earlier, which is also required. If we don't follow the Appendix A limitations, loop
+ // init statements can declare arrays or nameless structs and have multiple
+ // declarations.
+
+ if (!shouldRunLoopAndIndexingValidation(compileOptions))
{
- RegenerateStructNames gen(symbolTable, shaderVersion);
- root->traverse(&gen);
+ SimplifyLoopConditions(root,
+ IntermNodePatternMatcher::kArrayDeclaration |
+ IntermNodePatternMatcher::kNamelessStructDeclaration,
+ &getSymbolTable(), getShaderVersion());
}
+
+ InitializeUninitializedLocals(root, getShaderVersion(), canUseLoopsToInitialize,
+ &getSymbolTable());
}
- SetGlobalParseContext(NULL);
- if (success)
- return root;
+ if (getShaderType() == GL_VERTEX_SHADER && (compileOptions & SH_CLAMP_POINT_SIZE))
+ {
+ ClampPointSize(root, compileResources.MaxPointSize, &getSymbolTable());
+ }
- return NULL;
+ if (compileOptions & SH_REWRITE_VECTOR_SCALAR_ARITHMETIC)
+ {
+ VectorizeVectorScalarArithmetic(root, &getSymbolTable());
+ }
+
+ return true;
}
-bool TCompiler::compile(const char* const shaderStrings[],
- size_t numStrings, int compileOptions)
+bool TCompiler::compile(const char *const shaderStrings[],
+ size_t numStrings,
+ ShCompileOptions compileOptionsIn)
{
+#if defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
+ DumpFuzzerCase(shaderStrings, numStrings, shaderType, shaderSpec, outputType, compileOptionsIn);
+#endif // defined(ANGLE_ENABLE_FUZZER_CORPUS_OUTPUT)
+
if (numStrings == 0)
return true;
+ ShCompileOptions compileOptions = compileOptionsIn;
+
+ // Apply key workarounds.
+ if (shouldFlattenPragmaStdglInvariantAll())
+ {
+ // This should be harmless to do in all cases, but for the moment, do it only conditionally.
+ compileOptions |= SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL;
+ }
+
TScopedPoolAllocator scopedAlloc(&allocator);
- TIntermNode *root = compileTreeImpl(shaderStrings, numStrings, compileOptions);
+ TIntermBlock *root = compileTreeImpl(shaderStrings, numStrings, compileOptions);
if (root)
{
if (compileOptions & SH_INTERMEDIATE_TREE)
- TIntermediate::outputTree(root, infoSink.info);
+ OutputTree(root, infoSink.info);
if (compileOptions & SH_OBJECT_CODE)
- translate(root, compileOptions);
+ {
+ PerformanceDiagnostics perfDiagnostics(&mDiagnostics);
+ translate(root, compileOptions, &perfDiagnostics);
+ }
// The IntermNode tree doesn't need to be deleted here, since the
// memory will be freed in a big chunk by the PoolAllocator.
@@ -408,37 +679,38 @@ bool TCompiler::compile(const char* const shaderStrings[],
bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
{
+ if (resources.MaxDrawBuffers < 1)
+ {
+ return false;
+ }
+ if (resources.EXT_blend_func_extended && resources.MaxDualSourceDrawBuffers < 1)
+ {
+ return false;
+ }
+
compileResources = resources;
setResourceString();
- assert(symbolTable.isEmpty());
- symbolTable.push(); // COMMON_BUILTINS
- symbolTable.push(); // ESSL1_BUILTINS
- symbolTable.push(); // ESSL3_BUILTINS
-
- TPublicType integer;
- integer.type = EbtInt;
- integer.primarySize = 1;
- integer.secondarySize = 1;
- integer.array = false;
-
- TPublicType floatingPoint;
- floatingPoint.type = EbtFloat;
- floatingPoint.primarySize = 1;
- floatingPoint.secondarySize = 1;
- floatingPoint.array = false;
-
- switch(shaderType)
- {
- case GL_FRAGMENT_SHADER:
- symbolTable.setDefaultPrecision(integer, EbpMedium);
- break;
- case GL_VERTEX_SHADER:
- symbolTable.setDefaultPrecision(integer, EbpHigh);
- symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
- break;
- default:
- assert(false && "Language not supported");
+ ASSERT(symbolTable.isEmpty());
+ symbolTable.push(); // COMMON_BUILTINS
+ symbolTable.push(); // ESSL1_BUILTINS
+ symbolTable.push(); // ESSL3_BUILTINS
+ symbolTable.push(); // ESSL3_1_BUILTINS
+ symbolTable.push(); // GLSL_BUILTINS
+
+ switch (shaderType)
+ {
+ case GL_FRAGMENT_SHADER:
+ symbolTable.setDefaultPrecision(EbtInt, EbpMedium);
+ break;
+ case GL_VERTEX_SHADER:
+ case GL_COMPUTE_SHADER:
+ case GL_GEOMETRY_SHADER_OES:
+ symbolTable.setDefaultPrecision(EbtInt, EbpHigh);
+ symbolTable.setDefaultPrecision(EbtFloat, EbpHigh);
+ break;
+ default:
+ UNREACHABLE();
}
// Set defaults for sampler types that have default precision, even those that are
// only available if an extension exists.
@@ -447,9 +719,13 @@ bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
initSamplerDefaultPrecision(EbtSamplerCube);
// SamplerExternalOES is specified in the extension to have default precision.
initSamplerDefaultPrecision(EbtSamplerExternalOES);
+ // SamplerExternal2DY2YEXT is specified in the extension to have default precision.
+ initSamplerDefaultPrecision(EbtSamplerExternal2DY2YEXT);
// It isn't specified whether Sampler2DRect has default precision.
initSamplerDefaultPrecision(EbtSampler2DRect);
+ symbolTable.setDefaultPrecision(EbtAtomicCounter, EbpHigh);
+
InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable);
IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable);
@@ -460,87 +736,149 @@ bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
void TCompiler::initSamplerDefaultPrecision(TBasicType samplerType)
{
ASSERT(samplerType > EbtGuardSamplerBegin && samplerType < EbtGuardSamplerEnd);
- TPublicType sampler;
- sampler.primarySize = 1;
- sampler.secondarySize = 1;
- sampler.array = false;
- sampler.type = samplerType;
- symbolTable.setDefaultPrecision(sampler, EbpLow);
+ symbolTable.setDefaultPrecision(samplerType, EbpLow);
}
void TCompiler::setResourceString()
{
std::ostringstream strstream;
+
+ // clang-format off
strstream << ":MaxVertexAttribs:" << compileResources.MaxVertexAttribs
- << ":MaxVertexUniformVectors:" << compileResources.MaxVertexUniformVectors
- << ":MaxVaryingVectors:" << compileResources.MaxVaryingVectors
- << ":MaxVertexTextureImageUnits:" << compileResources.MaxVertexTextureImageUnits
- << ":MaxCombinedTextureImageUnits:" << compileResources.MaxCombinedTextureImageUnits
- << ":MaxTextureImageUnits:" << compileResources.MaxTextureImageUnits
- << ":MaxFragmentUniformVectors:" << compileResources.MaxFragmentUniformVectors
- << ":MaxDrawBuffers:" << compileResources.MaxDrawBuffers
- << ":OES_standard_derivatives:" << compileResources.OES_standard_derivatives
- << ":OES_EGL_image_external:" << compileResources.OES_EGL_image_external
- << ":ARB_texture_rectangle:" << compileResources.ARB_texture_rectangle
- << ":EXT_draw_buffers:" << compileResources.EXT_draw_buffers
- << ":FragmentPrecisionHigh:" << compileResources.FragmentPrecisionHigh
- << ":MaxExpressionComplexity:" << compileResources.MaxExpressionComplexity
- << ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth
- << ":EXT_blend_func_extended:" << compileResources.EXT_blend_func_extended
- << ":EXT_frag_depth:" << compileResources.EXT_frag_depth
- << ":EXT_shader_texture_lod:" << compileResources.EXT_shader_texture_lod
- << ":EXT_shader_framebuffer_fetch:" << compileResources.EXT_shader_framebuffer_fetch
- << ":NV_shader_framebuffer_fetch:" << compileResources.NV_shader_framebuffer_fetch
- << ":ARM_shader_framebuffer_fetch:" << compileResources.ARM_shader_framebuffer_fetch
- << ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors
- << ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors
- << ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset
- << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset
- << ":MaxDualSourceDrawBuffers:" << compileResources.MaxDualSourceDrawBuffers
- << ":NV_draw_buffers:" << compileResources.NV_draw_buffers
- << ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision;
+ << ":MaxVertexUniformVectors:" << compileResources.MaxVertexUniformVectors
+ << ":MaxVaryingVectors:" << compileResources.MaxVaryingVectors
+ << ":MaxVertexTextureImageUnits:" << compileResources.MaxVertexTextureImageUnits
+ << ":MaxCombinedTextureImageUnits:" << compileResources.MaxCombinedTextureImageUnits
+ << ":MaxTextureImageUnits:" << compileResources.MaxTextureImageUnits
+ << ":MaxFragmentUniformVectors:" << compileResources.MaxFragmentUniformVectors
+ << ":MaxDrawBuffers:" << compileResources.MaxDrawBuffers
+ << ":OES_standard_derivatives:" << compileResources.OES_standard_derivatives
+ << ":OES_EGL_image_external:" << compileResources.OES_EGL_image_external
+ << ":OES_EGL_image_external_essl3:" << compileResources.OES_EGL_image_external_essl3
+ << ":NV_EGL_stream_consumer_external:" << compileResources.NV_EGL_stream_consumer_external
+ << ":ARB_texture_rectangle:" << compileResources.ARB_texture_rectangle
+ << ":EXT_draw_buffers:" << compileResources.EXT_draw_buffers
+ << ":FragmentPrecisionHigh:" << compileResources.FragmentPrecisionHigh
+ << ":MaxExpressionComplexity:" << compileResources.MaxExpressionComplexity
+ << ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth
+ << ":MaxFunctionParameters:" << compileResources.MaxFunctionParameters
+ << ":EXT_blend_func_extended:" << compileResources.EXT_blend_func_extended
+ << ":EXT_frag_depth:" << compileResources.EXT_frag_depth
+ << ":EXT_shader_texture_lod:" << compileResources.EXT_shader_texture_lod
+ << ":EXT_shader_framebuffer_fetch:" << compileResources.EXT_shader_framebuffer_fetch
+ << ":NV_shader_framebuffer_fetch:" << compileResources.NV_shader_framebuffer_fetch
+ << ":ARM_shader_framebuffer_fetch:" << compileResources.ARM_shader_framebuffer_fetch
+ << ":OVR_multiview:" << compileResources.OVR_multiview
+ << ":EXT_YUV_target:" << compileResources.EXT_YUV_target
+ << ":OES_geometry_shader:" << compileResources.OES_geometry_shader
+ << ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors
+ << ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors
+ << ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset
+ << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset
+ << ":MaxDualSourceDrawBuffers:" << compileResources.MaxDualSourceDrawBuffers
+ << ":MaxViewsOVR:" << compileResources.MaxViewsOVR
+ << ":NV_draw_buffers:" << compileResources.NV_draw_buffers
+ << ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision
+ << ":MinProgramTextureGatherOffset:" << compileResources.MinProgramTextureGatherOffset
+ << ":MaxProgramTextureGatherOffset:" << compileResources.MaxProgramTextureGatherOffset
+ << ":MaxImageUnits:" << compileResources.MaxImageUnits
+ << ":MaxVertexImageUniforms:" << compileResources.MaxVertexImageUniforms
+ << ":MaxFragmentImageUniforms:" << compileResources.MaxFragmentImageUniforms
+ << ":MaxComputeImageUniforms:" << compileResources.MaxComputeImageUniforms
+ << ":MaxCombinedImageUniforms:" << compileResources.MaxCombinedImageUniforms
+ << ":MaxCombinedShaderOutputResources:" << compileResources.MaxCombinedShaderOutputResources
+ << ":MaxComputeWorkGroupCountX:" << compileResources.MaxComputeWorkGroupCount[0]
+ << ":MaxComputeWorkGroupCountY:" << compileResources.MaxComputeWorkGroupCount[1]
+ << ":MaxComputeWorkGroupCountZ:" << compileResources.MaxComputeWorkGroupCount[2]
+ << ":MaxComputeWorkGroupSizeX:" << compileResources.MaxComputeWorkGroupSize[0]
+ << ":MaxComputeWorkGroupSizeY:" << compileResources.MaxComputeWorkGroupSize[1]
+ << ":MaxComputeWorkGroupSizeZ:" << compileResources.MaxComputeWorkGroupSize[2]
+ << ":MaxComputeUniformComponents:" << compileResources.MaxComputeUniformComponents
+ << ":MaxComputeTextureImageUnits:" << compileResources.MaxComputeTextureImageUnits
+ << ":MaxComputeAtomicCounters:" << compileResources.MaxComputeAtomicCounters
+ << ":MaxComputeAtomicCounterBuffers:" << compileResources.MaxComputeAtomicCounterBuffers
+ << ":MaxVertexAtomicCounters:" << compileResources.MaxVertexAtomicCounters
+ << ":MaxFragmentAtomicCounters:" << compileResources.MaxFragmentAtomicCounters
+ << ":MaxCombinedAtomicCounters:" << compileResources.MaxCombinedAtomicCounters
+ << ":MaxAtomicCounterBindings:" << compileResources.MaxAtomicCounterBindings
+ << ":MaxVertexAtomicCounterBuffers:" << compileResources.MaxVertexAtomicCounterBuffers
+ << ":MaxFragmentAtomicCounterBuffers:" << compileResources.MaxFragmentAtomicCounterBuffers
+ << ":MaxCombinedAtomicCounterBuffers:" << compileResources.MaxCombinedAtomicCounterBuffers
+ << ":MaxAtomicCounterBufferSize:" << compileResources.MaxAtomicCounterBufferSize
+ << ":MaxGeometryUniformComponents:" << compileResources.MaxGeometryUniformComponents
+ << ":MaxGeometryUniformBlocks:" << compileResources.MaxGeometryUniformBlocks
+ << ":MaxGeometryInputComponents:" << compileResources.MaxGeometryInputComponents
+ << ":MaxGeometryOutputComponents:" << compileResources.MaxGeometryOutputComponents
+ << ":MaxGeometryOutputVertices:" << compileResources.MaxGeometryOutputVertices
+ << ":MaxGeometryTotalOutputComponents:" << compileResources.MaxGeometryTotalOutputComponents
+ << ":MaxGeometryTextureImageUnits:" << compileResources.MaxGeometryTextureImageUnits
+ << ":MaxGeometryAtomicCounterBuffers:" << compileResources.MaxGeometryAtomicCounterBuffers
+ << ":MaxGeometryAtomicCounters:" << compileResources.MaxGeometryAtomicCounters
+ << ":MaxGeometryShaderStorageBlocks:" << compileResources.MaxGeometryShaderStorageBlocks
+ << ":MaxGeometryShaderInvocations:" << compileResources.MaxGeometryShaderInvocations
+ << ":MaxGeometryImageUniforms:" << compileResources.MaxGeometryImageUniforms;
+ // clang-format on
builtInResourcesString = strstream.str();
}
+void TCompiler::collectInterfaceBlocks()
+{
+ ASSERT(interfaceBlocks.empty());
+ interfaceBlocks.reserve(uniformBlocks.size() + shaderStorageBlocks.size() + inBlocks.size());
+ interfaceBlocks.insert(interfaceBlocks.end(), uniformBlocks.begin(), uniformBlocks.end());
+ interfaceBlocks.insert(interfaceBlocks.end(), shaderStorageBlocks.begin(),
+ shaderStorageBlocks.end());
+ interfaceBlocks.insert(interfaceBlocks.end(), inBlocks.begin(), inBlocks.end());
+}
+
void TCompiler::clearResults()
{
arrayBoundsClamper.Cleanup();
infoSink.info.erase();
infoSink.obj.erase();
infoSink.debug.erase();
+ mDiagnostics.resetErrorCount();
attributes.clear();
outputVariables.clear();
uniforms.clear();
- expandedUniforms.clear();
- varyings.clear();
+ inputVaryings.clear();
+ outputVaryings.clear();
interfaceBlocks.clear();
+ uniformBlocks.clear();
+ shaderStorageBlocks.clear();
+ inBlocks.clear();
+ variablesCollected = false;
+ mGLPositionInitialized = false;
+
+ mNumViews = -1;
- builtInFunctionEmulator.Cleanup();
+ mGeometryShaderInputPrimitiveType = EptUndefined;
+ mGeometryShaderOutputPrimitiveType = EptUndefined;
+ mGeometryShaderInvocations = 0;
+ mGeometryShaderMaxVertices = -1;
+
+ builtInFunctionEmulator.cleanup();
nameMap.clear();
- mSourcePath = NULL;
- mTemporaryIndex = 0;
+ mSourcePath = nullptr;
}
bool TCompiler::initCallDag(TIntermNode *root)
{
mCallDag.clear();
- switch (mCallDag.init(root, &infoSink.info))
+ switch (mCallDag.init(root, &mDiagnostics))
{
- case CallDAG::INITDAG_SUCCESS:
- return true;
- case CallDAG::INITDAG_RECURSION:
- infoSink.info.prefix(EPrefixError);
- infoSink.info << "Function recursion detected";
- return false;
- case CallDAG::INITDAG_UNDEFINED:
- infoSink.info.prefix(EPrefixError);
- infoSink.info << "Unimplemented function detected";
- return false;
+ case CallDAG::INITDAG_SUCCESS:
+ return true;
+ case CallDAG::INITDAG_RECURSION:
+ case CallDAG::INITDAG_UNDEFINED:
+ // Error message has already been written out.
+ ASSERT(mDiagnostics.numErrors() > 0);
+ return false;
}
UNREACHABLE();
@@ -553,7 +891,7 @@ bool TCompiler::checkCallDepth()
for (size_t i = 0; i < mCallDag.size(); i++)
{
- int depth = 0;
+ int depth = 0;
auto &record = mCallDag.getRecordFromIndex(i);
for (auto &calleeIndex : record.callees)
@@ -566,19 +904,19 @@ bool TCompiler::checkCallDepth()
if (depth >= maxCallStackDepth)
{
// Trace back the function chain to have a meaningful info log.
- infoSink.info.prefix(EPrefixError);
- infoSink.info << "Call stack too deep (larger than " << maxCallStackDepth
- << ") with the following call chain: " << record.name;
+ std::stringstream errorStream;
+ errorStream << "Call stack too deep (larger than " << maxCallStackDepth
+ << ") with the following call chain: " << record.name;
int currentFunction = static_cast<int>(i);
- int currentDepth = depth;
+ int currentDepth = depth;
while (currentFunction != -1)
{
- infoSink.info << " -> " << mCallDag.getRecordFromIndex(currentFunction).name;
+ errorStream << " -> " << mCallDag.getRecordFromIndex(currentFunction).name;
int nextFunction = -1;
- for (auto& calleeIndex : mCallDag.getRecordFromIndex(currentFunction).callees)
+ for (auto &calleeIndex : mCallDag.getRecordFromIndex(currentFunction).callees)
{
if (depths[calleeIndex] == currentDepth - 1)
{
@@ -590,6 +928,9 @@ bool TCompiler::checkCallDepth()
currentFunction = nextFunction;
}
+ std::string errorStr = errorStream.str();
+ mDiagnostics.globalError(errorStr.c_str());
+
return false;
}
}
@@ -602,15 +943,14 @@ bool TCompiler::tagUsedFunctions()
// Search from main, starting from the end of the DAG as it usually is the root.
for (size_t i = mCallDag.size(); i-- > 0;)
{
- if (mCallDag.getRecordFromIndex(i).name == "main(")
+ if (mCallDag.getRecordFromIndex(i).name == "main")
{
internalTagUsedFunction(i);
return true;
}
}
- infoSink.info.prefix(EPrefixError);
- infoSink.info << "Missing main()\n";
+ mDiagnostics.globalError("Missing main()");
return false;
}
@@ -634,30 +974,35 @@ class TCompiler::UnusedPredicate
{
public:
UnusedPredicate(const CallDAG *callDag, const std::vector<FunctionMetadata> *metadatas)
- : mCallDag(callDag),
- mMetadatas(metadatas)
+ : mCallDag(callDag), mMetadatas(metadatas)
{
}
- bool operator ()(TIntermNode *node)
+ bool operator()(TIntermNode *node)
{
- const TIntermAggregate *asAggregate = node->getAsAggregate();
+ const TIntermFunctionPrototype *asFunctionPrototype = node->getAsFunctionPrototypeNode();
+ const TIntermFunctionDefinition *asFunctionDefinition = node->getAsFunctionDefinition();
+
+ const TFunctionSymbolInfo *functionInfo = nullptr;
- if (asAggregate == nullptr)
+ if (asFunctionDefinition)
{
- return false;
+ functionInfo = asFunctionDefinition->getFunctionSymbolInfo();
}
-
- if (!(asAggregate->getOp() == EOpFunction || asAggregate->getOp() == EOpPrototype))
+ else if (asFunctionPrototype)
+ {
+ functionInfo = asFunctionPrototype->getFunctionSymbolInfo();
+ }
+ if (functionInfo == nullptr)
{
return false;
}
- size_t callDagIndex = mCallDag->findIndex(asAggregate);
+ size_t callDagIndex = mCallDag->findIndex(functionInfo);
if (callDagIndex == CallDAG::InvalidIndex)
{
// This happens only for unimplemented prototypes which are thus unused
- ASSERT(asAggregate->getOp() == EOpPrototype);
+ ASSERT(asFunctionPrototype);
return true;
}
@@ -670,157 +1015,97 @@ class TCompiler::UnusedPredicate
const std::vector<FunctionMetadata> *mMetadatas;
};
-bool TCompiler::pruneUnusedFunctions(TIntermNode *root)
+void TCompiler::pruneUnusedFunctions(TIntermBlock *root)
{
- TIntermAggregate *rootNode = root->getAsAggregate();
- ASSERT(rootNode != nullptr);
-
UnusedPredicate isUnused(&mCallDag, &functionMetadata);
- TIntermSequence *sequence = rootNode->getSequence();
+ TIntermSequence *sequence = root->getSequence();
if (!sequence->empty())
{
- sequence->erase(std::remove_if(sequence->begin(), sequence->end(), isUnused), sequence->end());
+ sequence->erase(std::remove_if(sequence->begin(), sequence->end(), isUnused),
+ sequence->end());
}
-
- return true;
-}
-
-bool TCompiler::validateOutputs(TIntermNode* root)
-{
- ValidateOutputs validateOutputs(getExtensionBehavior(), compileResources.MaxDrawBuffers);
- root->traverse(&validateOutputs);
- return (validateOutputs.validateAndCountErrors(infoSink.info) == 0);
-}
-
-void TCompiler::rewriteCSSShader(TIntermNode* root)
-{
- RenameFunction renamer("main(", "css_main(");
- root->traverse(&renamer);
}
-bool TCompiler::validateLimitations(TIntermNode* root)
+bool TCompiler::limitExpressionComplexity(TIntermBlock *root)
{
- ValidateLimitations validate(shaderType, &infoSink.info);
- root->traverse(&validate);
- return validate.numErrors() == 0;
-}
-
-bool TCompiler::enforceTimingRestrictions(TIntermNode* root, bool outputGraph)
-{
- if (shaderSpec != SH_WEBGL_SPEC)
+ if (!IsASTDepthBelowLimit(root, maxExpressionComplexity))
{
- infoSink.info << "Timing restrictions must be enforced under the WebGL spec.";
+ mDiagnostics.globalError("Expression too complex.");
return false;
}
- if (shaderType == GL_FRAGMENT_SHADER)
- {
- TDependencyGraph graph(root);
-
- // Output any errors first.
- bool success = enforceFragmentShaderTimingRestrictions(graph);
-
- // Then, output the dependency graph.
- if (outputGraph)
- {
- TDependencyGraphOutput output(infoSink.info);
- output.outputAllSpanningTrees(graph);
- }
-
- return success;
- }
- else
- {
- return enforceVertexShaderTimingRestrictions(root);
- }
-}
-
-bool TCompiler::limitExpressionComplexity(TIntermNode* root)
-{
- TMaxDepthTraverser traverser(maxExpressionComplexity+1);
- root->traverse(&traverser);
-
- if (traverser.getMaxDepth() > maxExpressionComplexity)
+ if (!ValidateMaxParameters(root, maxFunctionParameters))
{
- infoSink.info << "Expression too complex.";
+ mDiagnostics.globalError("Function has too many parameters.");
return false;
}
return true;
}
-bool TCompiler::enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph)
+bool TCompiler::shouldCollectVariables(ShCompileOptions compileOptions)
{
- RestrictFragmentShaderTiming restrictor(infoSink.info);
- restrictor.enforceRestrictions(graph);
- return restrictor.numErrors() == 0;
+ return (compileOptions & SH_VARIABLES) != 0;
}
-bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root)
+bool TCompiler::wereVariablesCollected() const
{
- RestrictVertexShaderTiming restrictor(infoSink.info);
- restrictor.enforceRestrictions(root);
- return restrictor.numErrors() == 0;
+ return variablesCollected;
}
-void TCompiler::collectVariables(TIntermNode* root)
+void TCompiler::initializeGLPosition(TIntermBlock *root)
{
- sh::CollectVariables collect(&attributes,
- &outputVariables,
- &uniforms,
- &varyings,
- &interfaceBlocks,
- hashFunction,
- symbolTable);
- root->traverse(&collect);
-
- // This is for enforcePackingRestriction().
- sh::ExpandUniforms(uniforms, &expandedUniforms);
+ InitVariableList list;
+ sh::ShaderVariable var(GL_FLOAT_VEC4);
+ var.name = "gl_Position";
+ list.push_back(var);
+ InitializeVariables(root, list, &symbolTable, shaderVersion, extensionBehavior, false);
}
-bool TCompiler::enforcePackingRestrictions()
+void TCompiler::useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root)
{
- VariablePacker packer;
- return packer.CheckVariablesWithinPackingLimits(maxUniformVectors, expandedUniforms);
-}
+ sh::InterfaceBlockList list;
-void TCompiler::initializeGLPosition(TIntermNode* root)
-{
- InitializeVariables::InitVariableInfoList variables;
- InitializeVariables::InitVariableInfo var(
- "gl_Position", TType(EbtFloat, EbpUndefined, EvqPosition, 4));
- variables.push_back(var);
- InitializeVariables initializer(variables);
- root->traverse(&initializer);
+ for (auto block : uniformBlocks)
+ {
+ if (!block.staticUse &&
+ (block.layout == sh::BLOCKLAYOUT_STD140 || block.layout == sh::BLOCKLAYOUT_SHARED))
+ {
+ list.push_back(block);
+ }
+ }
+
+ sh::UseInterfaceBlockFields(root, list, symbolTable);
}
-void TCompiler::initializeVaryingsWithoutStaticUse(TIntermNode* root)
+void TCompiler::initializeOutputVariables(TIntermBlock *root)
{
- InitializeVariables::InitVariableInfoList variables;
- for (size_t ii = 0; ii < varyings.size(); ++ii)
+ InitVariableList list;
+ if (shaderType == GL_VERTEX_SHADER || shaderType == GL_GEOMETRY_SHADER_OES)
{
- const sh::Varying& varying = varyings[ii];
- if (varying.staticUse)
- continue;
- unsigned char primarySize = static_cast<unsigned char>(gl::VariableColumnCount(varying.type));
- unsigned char secondarySize = static_cast<unsigned char>(gl::VariableRowCount(varying.type));
- TType type(EbtFloat, EbpUndefined, EvqVaryingOut, primarySize, secondarySize, varying.isArray());
- TString name = varying.name.c_str();
- if (varying.isArray())
+ for (auto var : outputVaryings)
{
- type.setArraySize(varying.arraySize);
- name = name.substr(0, name.find_first_of('['));
+ list.push_back(var);
+ if (var.name == "gl_Position")
+ {
+ ASSERT(!mGLPositionInitialized);
+ mGLPositionInitialized = true;
+ }
}
-
- InitializeVariables::InitVariableInfo var(name, type);
- variables.push_back(var);
}
- InitializeVariables initializer(variables);
- root->traverse(&initializer);
+ else
+ {
+ ASSERT(shaderType == GL_FRAGMENT_SHADER);
+ for (auto var : outputVariables)
+ {
+ list.push_back(var);
+ }
+ }
+ InitializeVariables(root, list, &symbolTable, shaderVersion, extensionBehavior, false);
}
-const TExtensionBehavior& TCompiler::getExtensionBehavior() const
+const TExtensionBehavior &TCompiler::getExtensionBehavior() const
{
return extensionBehavior;
}
@@ -830,12 +1115,12 @@ const char *TCompiler::getSourcePath() const
return mSourcePath;
}
-const ShBuiltInResources& TCompiler::getResources() const
+const ShBuiltInResources &TCompiler::getResources() const
{
return compileResources;
}
-const ArrayBoundsClamper& TCompiler::getArrayBoundsClamper() const
+const ArrayBoundsClamper &TCompiler::getArrayBoundsClamper() const
{
return arrayBoundsClamper;
}
@@ -845,14 +1130,40 @@ ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const
return clampingStrategy;
}
-const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const
+const BuiltInFunctionEmulator &TCompiler::getBuiltInFunctionEmulator() const
{
return builtInFunctionEmulator;
}
-void TCompiler::writePragma()
+void TCompiler::writePragma(ShCompileOptions compileOptions)
+{
+ if (!(compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL))
+ {
+ TInfoSinkBase &sink = infoSink.obj;
+ if (mPragma.stdgl.invariantAll)
+ sink << "#pragma STDGL invariant(all)\n";
+ }
+}
+
+bool TCompiler::isVaryingDefined(const char *varyingName)
{
- TInfoSinkBase &sink = infoSink.obj;
- if (mPragma.stdgl.invariantAll)
- sink << "#pragma STDGL invariant(all)\n";
+ ASSERT(variablesCollected);
+ for (size_t ii = 0; ii < inputVaryings.size(); ++ii)
+ {
+ if (inputVaryings[ii].name == varyingName)
+ {
+ return true;
+ }
+ }
+ for (size_t ii = 0; ii < outputVaryings.size(); ++ii)
+ {
+ if (outputVaryings[ii].name == varyingName)
+ {
+ return true;
+ }
+ }
+
+ return false;
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.h b/src/3rdparty/angle/src/compiler/translator/Compiler.h
index c00a8f97aa..753cfb8e7b 100644
--- a/src/3rdparty/angle/src/compiler/translator/Compiler.h
+++ b/src/3rdparty/angle/src/compiler/translator/Compiler.h
@@ -14,25 +14,29 @@
// This should not be included by driver code.
//
+#include <GLSLANG/ShaderVars.h>
+
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/CallDAG.h"
+#include "compiler/translator/Diagnostics.h"
#include "compiler/translator/ExtensionBehavior.h"
#include "compiler/translator/HashNames.h"
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/Pragma.h"
#include "compiler/translator/SymbolTable.h"
-#include "compiler/translator/VariableInfo.h"
#include "third_party/compiler/ArrayBoundsClamper.h"
+namespace sh
+{
+
class TCompiler;
-class TDependencyGraph;
+class TParseContext;
#ifdef ANGLE_ENABLE_HLSL
class TranslatorHLSL;
-#endif // ANGLE_ENABLE_HLSL
+#endif // ANGLE_ENABLE_HLSL
//
-// Helper function to identify specs that are based on the WebGL spec,
-// like the CSS Shaders spec.
+// Helper function to identify specs that are based on the WebGL spec.
//
bool IsWebGLBasedSpec(ShShaderSpec spec);
@@ -40,20 +44,31 @@ bool IsWebGLBasedSpec(ShShaderSpec spec);
// Helper function to check if the shader type is GLSL.
//
bool IsGLSL130OrNewer(ShShaderOutput output);
+bool IsGLSL420OrNewer(ShShaderOutput output);
+bool IsGLSL410OrOlder(ShShaderOutput output);
+
+//
+// Helper function to check if the invariant qualifier can be removed.
+//
+bool RemoveInvariant(sh::GLenum shaderType,
+ int shaderVersion,
+ ShShaderOutput outputType,
+ ShCompileOptions compileOptions);
//
// The base class used to back handles returned to the driver.
//
-class TShHandleBase {
-public:
+class TShHandleBase
+{
+ public:
TShHandleBase();
virtual ~TShHandleBase();
- virtual TCompiler* getAsCompiler() { return 0; }
+ virtual TCompiler *getAsCompiler() { return 0; }
#ifdef ANGLE_ENABLE_HLSL
- virtual TranslatorHLSL* getAsTranslatorHLSL() { return 0; }
-#endif // ANGLE_ENABLE_HLSL
+ virtual TranslatorHLSL *getAsTranslatorHLSL() { return 0; }
+#endif // ANGLE_ENABLE_HLSL
-protected:
+ protected:
// Memory allocator. Allocates and tracks memory required by the compiler.
// Deallocates all memory when compiler is destructed.
TPoolAllocator allocator;
@@ -70,20 +85,26 @@ class TCompiler : public TShHandleBase
~TCompiler() override;
TCompiler *getAsCompiler() override { return this; }
- bool Init(const ShBuiltInResources& resources);
+ bool Init(const ShBuiltInResources &resources);
// compileTreeForTesting should be used only when tests require access to
// the AST. Users of this function need to manually manage the global pool
- // allocator. Returns NULL whenever there are compilation errors.
- TIntermNode *compileTreeForTesting(const char* const shaderStrings[],
- size_t numStrings, int compileOptions);
+ // allocator. Returns nullptr whenever there are compilation errors.
+ TIntermBlock *compileTreeForTesting(const char *const shaderStrings[],
+ size_t numStrings,
+ ShCompileOptions compileOptions);
- bool compile(const char* const shaderStrings[],
- size_t numStrings, int compileOptions);
+ bool compile(const char *const shaderStrings[],
+ size_t numStrings,
+ ShCompileOptions compileOptions);
// Get results of the last compilation.
int getShaderVersion() const { return shaderVersion; }
- TInfoSink& getInfoSink() { return infoSink; }
+ TInfoSink &getInfoSink() { return infoSink; }
+
+ bool isComputeShaderLocalSizeDeclared() const { return mComputeShaderLocalSizeDeclared; }
+ const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; }
+ int getNumViews() const { return mNumViews; }
// Clears the results from the previous compilation.
void clearResults();
@@ -91,86 +112,94 @@ class TCompiler : public TShHandleBase
const std::vector<sh::Attribute> &getAttributes() const { return attributes; }
const std::vector<sh::OutputVariable> &getOutputVariables() const { return outputVariables; }
const std::vector<sh::Uniform> &getUniforms() const { return uniforms; }
- const std::vector<sh::Varying> &getVaryings() const { return varyings; }
+ const std::vector<sh::Varying> &getInputVaryings() const { return inputVaryings; }
+ const std::vector<sh::Varying> &getOutputVaryings() const { return outputVaryings; }
const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const { return interfaceBlocks; }
+ const std::vector<sh::InterfaceBlock> &getUniformBlocks() const { return uniformBlocks; }
+ const std::vector<sh::InterfaceBlock> &getShaderStorageBlocks() const
+ {
+ return shaderStorageBlocks;
+ }
+ const std::vector<sh::InterfaceBlock> &getInBlocks() const { return inBlocks; }
ShHashFunction64 getHashFunction() const { return hashFunction; }
- NameMap& getNameMap() { return nameMap; }
- TSymbolTable& getSymbolTable() { return symbolTable; }
+ NameMap &getNameMap() { return nameMap; }
+ TSymbolTable &getSymbolTable() { return symbolTable; }
ShShaderSpec getShaderSpec() const { return shaderSpec; }
ShShaderOutput getOutputType() const { return outputType; }
const std::string &getBuiltInResourcesString() const { return builtInResourcesString; }
- bool shouldRunLoopAndIndexingValidation(int compileOptions) const;
+ bool shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const;
// Get the resources set by InitBuiltInSymbolTable
- const ShBuiltInResources& getResources() const;
+ const ShBuiltInResources &getResources() const;
+
+ int getGeometryShaderMaxVertices() const { return mGeometryShaderMaxVertices; }
+ int getGeometryShaderInvocations() const { return mGeometryShaderInvocations; }
+ TLayoutPrimitiveType getGeometryShaderInputPrimitiveType() const
+ {
+ return mGeometryShaderInputPrimitiveType;
+ }
+ TLayoutPrimitiveType getGeometryShaderOutputPrimitiveType() const
+ {
+ return mGeometryShaderOutputPrimitiveType;
+ }
- protected:
sh::GLenum getShaderType() const { return shaderType; }
+
+ protected:
// Initialize symbol-table with built-in symbols.
- bool InitBuiltInSymbolTable(const ShBuiltInResources& resources);
+ bool InitBuiltInSymbolTable(const ShBuiltInResources &resources);
// Compute the string representation of the built-in resources
void setResourceString();
// Return false if the call depth is exceeded.
bool checkCallDepth();
- // Returns true if a program has no conflicting or missing fragment outputs
- bool validateOutputs(TIntermNode* root);
- // Rewrites a shader's intermediate tree according to the CSS Shaders spec.
- void rewriteCSSShader(TIntermNode* root);
- // Returns true if the given shader does not exceed the minimum
- // functionality mandated in GLSL 1.0 spec Appendix A.
- bool validateLimitations(TIntermNode* root);
- // Collect info for all attribs, uniforms, varyings.
- void collectVariables(TIntermNode* root);
// Add emulated functions to the built-in function emulator.
- virtual void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions) {};
- // Translate to object code.
- virtual void translate(TIntermNode *root, int compileOptions) = 0;
- // Returns true if, after applying the packing rules in the GLSL 1.017 spec
- // Appendix A, section 7, the shader does not use too many uniforms.
- bool enforcePackingRestrictions();
- // Insert statements to initialize varyings without static use in the beginning
- // of main(). It is to work around a Mac driver where such varyings in a vertex
- // shader may be optimized out incorrectly at compile time, causing a link failure.
- // This function should only be applied to vertex shaders.
- void initializeVaryingsWithoutStaticUse(TIntermNode* root);
+ virtual void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu,
+ ShCompileOptions compileOptions){};
+ // Translate to object code. May generate performance warnings through the diagnostics.
+ virtual void translate(TIntermBlock *root,
+ ShCompileOptions compileOptions,
+ PerformanceDiagnostics *perfDiagnostics) = 0;
+ // Insert statements to reference all members in unused uniform blocks with standard and shared
+ // layout. This is to work around a Mac driver that treats unused standard/shared
+ // uniform blocks as inactive.
+ void useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root);
+ // Insert statements to initialize output variables in the beginning of main().
+ // This is to avoid undefined behaviors.
+ void initializeOutputVariables(TIntermBlock *root);
// Insert gl_Position = vec4(0,0,0,0) to the beginning of main().
// It is to work around a Linux driver bug where missing this causes compile failure
// while spec says it is allowed.
// This function should only be applied to vertex shaders.
- void initializeGLPosition(TIntermNode* root);
- // Returns true if the shader passes the restrictions that aim to prevent timing attacks.
- bool enforceTimingRestrictions(TIntermNode* root, bool outputGraph);
- // Returns true if the shader does not use samplers.
- bool enforceVertexShaderTimingRestrictions(TIntermNode* root);
- // Returns true if the shader does not use sampler dependent values to affect control
- // flow or in operations whose time can depend on the input values.
- bool enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph);
+ void initializeGLPosition(TIntermBlock *root);
// Return true if the maximum expression complexity is below the limit.
- bool limitExpressionComplexity(TIntermNode* root);
+ bool limitExpressionComplexity(TIntermBlock *root);
// Get built-in extensions with default behavior.
- const TExtensionBehavior& getExtensionBehavior() const;
+ const TExtensionBehavior &getExtensionBehavior() const;
const char *getSourcePath() const;
- const TPragma& getPragma() const { return mPragma; }
- void writePragma();
- unsigned int *getTemporaryIndex() { return &mTemporaryIndex; }
+ const TPragma &getPragma() const { return mPragma; }
+ void writePragma(ShCompileOptions compileOptions);
+ // Relies on collectVariables having been called.
+ bool isVaryingDefined(const char *varyingName);
- const ArrayBoundsClamper& getArrayBoundsClamper() const;
+ const ArrayBoundsClamper &getArrayBoundsClamper() const;
ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const;
- const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const;
+ const BuiltInFunctionEmulator &getBuiltInFunctionEmulator() const;
+ virtual bool shouldFlattenPragmaStdglInvariantAll() = 0;
+ virtual bool shouldCollectVariables(ShCompileOptions compileOptions);
+
+ bool wereVariablesCollected() const;
std::vector<sh::Attribute> attributes;
std::vector<sh::OutputVariable> outputVariables;
std::vector<sh::Uniform> uniforms;
- std::vector<sh::ShaderVariable> expandedUniforms;
- std::vector<sh::Varying> varyings;
+ std::vector<sh::Varying> inputVaryings;
+ std::vector<sh::Varying> outputVaryings;
std::vector<sh::InterfaceBlock> interfaceBlocks;
-
- virtual bool shouldCollectVariables(int compileOptions)
- {
- return (compileOptions & SH_VARIABLES) != 0;
- }
+ std::vector<sh::InterfaceBlock> uniformBlocks;
+ std::vector<sh::InterfaceBlock> shaderStorageBlocks;
+ std::vector<sh::InterfaceBlock> inBlocks;
private:
// Creates the function call DAG for further analysis, returning false if there is a recursion
@@ -181,13 +210,28 @@ class TCompiler : public TShHandleBase
void initSamplerDefaultPrecision(TBasicType samplerType);
+ void collectInterfaceBlocks();
+
+ bool variablesCollected;
+
+ bool mGLPositionInitialized;
+
// Removes unused function declarations and prototypes from the AST
class UnusedPredicate;
- bool pruneUnusedFunctions(TIntermNode *root);
+ void pruneUnusedFunctions(TIntermBlock *root);
+
+ TIntermBlock *compileTreeImpl(const char *const shaderStrings[],
+ size_t numStrings,
+ const ShCompileOptions compileOptions);
- TIntermNode *compileTreeImpl(const char *const shaderStrings[],
- size_t numStrings,
- const int compileOptions);
+ // Fetches and stores shader metadata that is not stored within the AST itself, such as shader
+ // version.
+ void setASTMetadata(const TParseContext &parseContext);
+
+ // Does checks that need to be run after parsing is complete and returns true if they pass.
+ bool checkAndSimplifyAST(TIntermBlock *root,
+ const TParseContext &parseContext,
+ ShCompileOptions compileOptions);
sh::GLenum shaderType;
ShShaderSpec shaderSpec;
@@ -195,10 +239,7 @@ class TCompiler : public TShHandleBase
struct FunctionMetadata
{
- FunctionMetadata()
- : used(false)
- {
- }
+ FunctionMetadata() : used(false) {}
bool used;
};
@@ -208,6 +249,7 @@ class TCompiler : public TShHandleBase
int maxUniformVectors;
int maxExpressionComplexity;
int maxCallStackDepth;
+ int maxFunctionParameters;
ShBuiltInResources compileResources;
std::string builtInResourcesString;
@@ -225,16 +267,28 @@ class TCompiler : public TShHandleBase
// Results of compilation.
int shaderVersion;
- TInfoSink infoSink; // Output sink.
- const char *mSourcePath; // Path of source file or NULL
+ TInfoSink infoSink; // Output sink.
+ TDiagnostics mDiagnostics;
+ const char *mSourcePath; // Path of source file or NULL
+
+ // compute shader local group size
+ bool mComputeShaderLocalSizeDeclared;
+ sh::WorkGroupSize mComputeShaderLocalSize;
+
+ // GL_OVR_multiview num_views.
+ int mNumViews;
+
+ // geometry shader parameters.
+ int mGeometryShaderMaxVertices;
+ int mGeometryShaderInvocations;
+ TLayoutPrimitiveType mGeometryShaderInputPrimitiveType;
+ TLayoutPrimitiveType mGeometryShaderOutputPrimitiveType;
// name hashing.
ShHashFunction64 hashFunction;
NameMap nameMap;
TPragma mPragma;
-
- unsigned int mTemporaryIndex;
};
//
@@ -246,8 +300,9 @@ class TCompiler : public TShHandleBase
// destroy the machine dependent objects, which contain the
// above machine independent information.
//
-TCompiler* ConstructCompiler(
- sh::GLenum type, ShShaderSpec spec, ShShaderOutput output);
-void DeleteCompiler(TCompiler*);
+TCompiler *ConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output);
+void DeleteCompiler(TCompiler *);
+
+} // namespace sh
-#endif // COMPILER_TRANSLATOR_COMPILER_H_
+#endif // COMPILER_TRANSLATOR_COMPILER_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ConstantUnion.cpp b/src/3rdparty/angle/src/compiler/translator/ConstantUnion.cpp
new file mode 100644
index 0000000000..7004aedee3
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/ConstantUnion.cpp
@@ -0,0 +1,681 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ConstantUnion: Constant folding helper class.
+
+#include "compiler/translator/ConstantUnion.h"
+
+#include "common/mathutil.h"
+#include "compiler/translator/Diagnostics.h"
+
+namespace sh
+{
+
+namespace
+{
+
+float CheckedSum(float lhs, float rhs, TDiagnostics *diag, const TSourceLoc &line)
+{
+ float result = lhs + rhs;
+ if (gl::isNaN(result) && !gl::isNaN(lhs) && !gl::isNaN(rhs))
+ {
+ diag->warning(line, "Constant folded undefined addition generated NaN", "+");
+ }
+ else if (gl::isInf(result) && !gl::isInf(lhs) && !gl::isInf(rhs))
+ {
+ diag->warning(line, "Constant folded addition overflowed to infinity", "+");
+ }
+ return result;
+}
+
+float CheckedDiff(float lhs, float rhs, TDiagnostics *diag, const TSourceLoc &line)
+{
+ float result = lhs - rhs;
+ if (gl::isNaN(result) && !gl::isNaN(lhs) && !gl::isNaN(rhs))
+ {
+ diag->warning(line, "Constant folded undefined subtraction generated NaN", "-");
+ }
+ else if (gl::isInf(result) && !gl::isInf(lhs) && !gl::isInf(rhs))
+ {
+ diag->warning(line, "Constant folded subtraction overflowed to infinity", "-");
+ }
+ return result;
+}
+
+float CheckedMul(float lhs, float rhs, TDiagnostics *diag, const TSourceLoc &line)
+{
+ float result = lhs * rhs;
+ if (gl::isNaN(result) && !gl::isNaN(lhs) && !gl::isNaN(rhs))
+ {
+ diag->warning(line, "Constant folded undefined multiplication generated NaN", "*");
+ }
+ else if (gl::isInf(result) && !gl::isInf(lhs) && !gl::isInf(rhs))
+ {
+ diag->warning(line, "Constant folded multiplication overflowed to infinity", "*");
+ }
+ return result;
+}
+
+bool IsValidShiftOffset(const TConstantUnion &rhs)
+{
+ return (rhs.getType() == EbtInt && (rhs.getIConst() >= 0 && rhs.getIConst() <= 31)) ||
+ (rhs.getType() == EbtUInt && rhs.getUConst() <= 31u);
+}
+
+} // anonymous namespace
+
+TConstantUnion::TConstantUnion()
+{
+ iConst = 0;
+ type = EbtVoid;
+}
+
+int TConstantUnion::getIConst() const
+{
+ ASSERT(type == EbtInt);
+ return iConst;
+}
+
+unsigned int TConstantUnion::getUConst() const
+{
+ ASSERT(type == EbtUInt);
+ return uConst;
+}
+
+float TConstantUnion::getFConst() const
+{
+ ASSERT(type == EbtFloat);
+ return fConst;
+}
+
+bool TConstantUnion::getBConst() const
+{
+ ASSERT(type == EbtBool);
+ return bConst;
+}
+
+TYuvCscStandardEXT TConstantUnion::getYuvCscStandardEXTConst() const
+{
+ ASSERT(type == EbtYuvCscStandardEXT);
+ return yuvCscStandardEXTConst;
+}
+
+bool TConstantUnion::cast(TBasicType newType, const TConstantUnion &constant)
+{
+ switch (newType)
+ {
+ case EbtFloat:
+ switch (constant.type)
+ {
+ case EbtInt:
+ setFConst(static_cast<float>(constant.getIConst()));
+ break;
+ case EbtUInt:
+ setFConst(static_cast<float>(constant.getUConst()));
+ break;
+ case EbtBool:
+ setFConst(static_cast<float>(constant.getBConst()));
+ break;
+ case EbtFloat:
+ setFConst(static_cast<float>(constant.getFConst()));
+ break;
+ default:
+ return false;
+ }
+ break;
+ case EbtInt:
+ switch (constant.type)
+ {
+ case EbtInt:
+ setIConst(static_cast<int>(constant.getIConst()));
+ break;
+ case EbtUInt:
+ setIConst(static_cast<int>(constant.getUConst()));
+ break;
+ case EbtBool:
+ setIConst(static_cast<int>(constant.getBConst()));
+ break;
+ case EbtFloat:
+ setIConst(static_cast<int>(constant.getFConst()));
+ break;
+ default:
+ return false;
+ }
+ break;
+ case EbtUInt:
+ switch (constant.type)
+ {
+ case EbtInt:
+ setUConst(static_cast<unsigned int>(constant.getIConst()));
+ break;
+ case EbtUInt:
+ setUConst(static_cast<unsigned int>(constant.getUConst()));
+ break;
+ case EbtBool:
+ setUConst(static_cast<unsigned int>(constant.getBConst()));
+ break;
+ case EbtFloat:
+ setUConst(static_cast<unsigned int>(constant.getFConst()));
+ break;
+ default:
+ return false;
+ }
+ break;
+ case EbtBool:
+ switch (constant.type)
+ {
+ case EbtInt:
+ setBConst(constant.getIConst() != 0);
+ break;
+ case EbtUInt:
+ setBConst(constant.getUConst() != 0);
+ break;
+ case EbtBool:
+ setBConst(constant.getBConst());
+ break;
+ case EbtFloat:
+ setBConst(constant.getFConst() != 0.0f);
+ break;
+ default:
+ return false;
+ }
+ break;
+ case EbtStruct: // Struct fields don't get cast
+ switch (constant.type)
+ {
+ case EbtInt:
+ setIConst(constant.getIConst());
+ break;
+ case EbtUInt:
+ setUConst(constant.getUConst());
+ break;
+ case EbtBool:
+ setBConst(constant.getBConst());
+ break;
+ case EbtFloat:
+ setFConst(constant.getFConst());
+ break;
+ default:
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool TConstantUnion::operator==(const int i) const
+{
+ return i == iConst;
+}
+
+bool TConstantUnion::operator==(const unsigned int u) const
+{
+ return u == uConst;
+}
+
+bool TConstantUnion::operator==(const float f) const
+{
+ return f == fConst;
+}
+
+bool TConstantUnion::operator==(const bool b) const
+{
+ return b == bConst;
+}
+
+bool TConstantUnion::operator==(const TYuvCscStandardEXT s) const
+{
+ return s == yuvCscStandardEXTConst;
+}
+
+bool TConstantUnion::operator==(const TConstantUnion &constant) const
+{
+ if (constant.type != type)
+ return false;
+
+ switch (type)
+ {
+ case EbtInt:
+ return constant.iConst == iConst;
+ case EbtUInt:
+ return constant.uConst == uConst;
+ case EbtFloat:
+ return constant.fConst == fConst;
+ case EbtBool:
+ return constant.bConst == bConst;
+ case EbtYuvCscStandardEXT:
+ return constant.yuvCscStandardEXTConst == yuvCscStandardEXTConst;
+ default:
+ return false;
+ }
+}
+
+bool TConstantUnion::operator!=(const int i) const
+{
+ return !operator==(i);
+}
+
+bool TConstantUnion::operator!=(const unsigned int u) const
+{
+ return !operator==(u);
+}
+
+bool TConstantUnion::operator!=(const float f) const
+{
+ return !operator==(f);
+}
+
+bool TConstantUnion::operator!=(const bool b) const
+{
+ return !operator==(b);
+}
+
+bool TConstantUnion::operator!=(const TYuvCscStandardEXT s) const
+{
+ return !operator==(s);
+}
+
+bool TConstantUnion::operator!=(const TConstantUnion &constant) const
+{
+ return !operator==(constant);
+}
+
+bool TConstantUnion::operator>(const TConstantUnion &constant) const
+{
+ ASSERT(type == constant.type);
+ switch (type)
+ {
+ case EbtInt:
+ return iConst > constant.iConst;
+ case EbtUInt:
+ return uConst > constant.uConst;
+ case EbtFloat:
+ return fConst > constant.fConst;
+ default:
+ return false; // Invalid operation, handled at semantic analysis
+ }
+}
+
+bool TConstantUnion::operator<(const TConstantUnion &constant) const
+{
+ ASSERT(type == constant.type);
+ switch (type)
+ {
+ case EbtInt:
+ return iConst < constant.iConst;
+ case EbtUInt:
+ return uConst < constant.uConst;
+ case EbtFloat:
+ return fConst < constant.fConst;
+ default:
+ return false; // Invalid operation, handled at semantic analysis
+ }
+}
+
+// static
+TConstantUnion TConstantUnion::add(const TConstantUnion &lhs,
+ const TConstantUnion &rhs,
+ TDiagnostics *diag,
+ const TSourceLoc &line)
+{
+ TConstantUnion returnValue;
+ ASSERT(lhs.type == rhs.type);
+ switch (lhs.type)
+ {
+ case EbtInt:
+ returnValue.setIConst(gl::WrappingSum<int>(lhs.iConst, rhs.iConst));
+ break;
+ case EbtUInt:
+ returnValue.setUConst(gl::WrappingSum<unsigned int>(lhs.uConst, rhs.uConst));
+ break;
+ case EbtFloat:
+ returnValue.setFConst(CheckedSum(lhs.fConst, rhs.fConst, diag, line));
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return returnValue;
+}
+
+// static
+TConstantUnion TConstantUnion::sub(const TConstantUnion &lhs,
+ const TConstantUnion &rhs,
+ TDiagnostics *diag,
+ const TSourceLoc &line)
+{
+ TConstantUnion returnValue;
+ ASSERT(lhs.type == rhs.type);
+ switch (lhs.type)
+ {
+ case EbtInt:
+ returnValue.setIConst(gl::WrappingDiff<int>(lhs.iConst, rhs.iConst));
+ break;
+ case EbtUInt:
+ returnValue.setUConst(gl::WrappingDiff<unsigned int>(lhs.uConst, rhs.uConst));
+ break;
+ case EbtFloat:
+ returnValue.setFConst(CheckedDiff(lhs.fConst, rhs.fConst, diag, line));
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return returnValue;
+}
+
+// static
+TConstantUnion TConstantUnion::mul(const TConstantUnion &lhs,
+ const TConstantUnion &rhs,
+ TDiagnostics *diag,
+ const TSourceLoc &line)
+{
+ TConstantUnion returnValue;
+ ASSERT(lhs.type == rhs.type);
+ switch (lhs.type)
+ {
+ case EbtInt:
+ returnValue.setIConst(gl::WrappingMul(lhs.iConst, rhs.iConst));
+ break;
+ case EbtUInt:
+ // Unsigned integer math in C++ is defined to be done in modulo 2^n, so we rely on that
+ // to implement wrapping multiplication.
+ returnValue.setUConst(lhs.uConst * rhs.uConst);
+ break;
+ case EbtFloat:
+ returnValue.setFConst(CheckedMul(lhs.fConst, rhs.fConst, diag, line));
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return returnValue;
+}
+
+TConstantUnion TConstantUnion::operator%(const TConstantUnion &constant) const
+{
+ TConstantUnion returnValue;
+ ASSERT(type == constant.type);
+ switch (type)
+ {
+ case EbtInt:
+ returnValue.setIConst(iConst % constant.iConst);
+ break;
+ case EbtUInt:
+ returnValue.setUConst(uConst % constant.uConst);
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return returnValue;
+}
+
+// static
+TConstantUnion TConstantUnion::rshift(const TConstantUnion &lhs,
+ const TConstantUnion &rhs,
+ TDiagnostics *diag,
+ const TSourceLoc &line)
+{
+ TConstantUnion returnValue;
+ ASSERT(lhs.type == EbtInt || lhs.type == EbtUInt);
+ ASSERT(rhs.type == EbtInt || rhs.type == EbtUInt);
+ if (!IsValidShiftOffset(rhs))
+ {
+ diag->warning(line, "Undefined shift (operand out of range)", ">>");
+ switch (lhs.type)
+ {
+ case EbtInt:
+ returnValue.setIConst(0);
+ break;
+ case EbtUInt:
+ returnValue.setUConst(0u);
+ break;
+ default:
+ UNREACHABLE();
+ }
+ return returnValue;
+ }
+
+ switch (lhs.type)
+ {
+ case EbtInt:
+ {
+ unsigned int shiftOffset = 0;
+ switch (rhs.type)
+ {
+ case EbtInt:
+ shiftOffset = static_cast<unsigned int>(rhs.iConst);
+ break;
+ case EbtUInt:
+ shiftOffset = rhs.uConst;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ if (shiftOffset > 0)
+ {
+ // ESSL 3.00.6 section 5.9: "If E1 is a signed integer, the right-shift will extend
+ // the sign bit." In C++ shifting negative integers is undefined, so we implement
+ // extending the sign bit manually.
+ int lhsSafe = lhs.iConst;
+ if (lhsSafe == std::numeric_limits<int>::min())
+ {
+ // The min integer needs special treatment because only bit it has set is the
+ // sign bit, which we clear later to implement safe right shift of negative
+ // numbers.
+ lhsSafe = -0x40000000;
+ --shiftOffset;
+ }
+ if (shiftOffset > 0)
+ {
+ bool extendSignBit = false;
+ if (lhsSafe < 0)
+ {
+ extendSignBit = true;
+ // Clear the sign bit so that bitshift right is defined in C++.
+ lhsSafe &= 0x7fffffff;
+ ASSERT(lhsSafe > 0);
+ }
+ returnValue.setIConst(lhsSafe >> shiftOffset);
+
+ // Manually fill in the extended sign bit if necessary.
+ if (extendSignBit)
+ {
+ int extendedSignBit = static_cast<int>(0xffffffffu << (31 - shiftOffset));
+ returnValue.setIConst(returnValue.getIConst() | extendedSignBit);
+ }
+ }
+ else
+ {
+ returnValue.setIConst(lhsSafe);
+ }
+ }
+ else
+ {
+ returnValue.setIConst(lhs.iConst);
+ }
+ break;
+ }
+ case EbtUInt:
+ switch (rhs.type)
+ {
+ case EbtInt:
+ returnValue.setUConst(lhs.uConst >> rhs.iConst);
+ break;
+ case EbtUInt:
+ returnValue.setUConst(lhs.uConst >> rhs.uConst);
+ break;
+ default:
+ UNREACHABLE();
+ }
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+ return returnValue;
+}
+
+// static
+TConstantUnion TConstantUnion::lshift(const TConstantUnion &lhs,
+ const TConstantUnion &rhs,
+ TDiagnostics *diag,
+ const TSourceLoc &line)
+{
+ TConstantUnion returnValue;
+ ASSERT(lhs.type == EbtInt || lhs.type == EbtUInt);
+ ASSERT(rhs.type == EbtInt || rhs.type == EbtUInt);
+ if (!IsValidShiftOffset(rhs))
+ {
+ diag->warning(line, "Undefined shift (operand out of range)", "<<");
+ switch (lhs.type)
+ {
+ case EbtInt:
+ returnValue.setIConst(0);
+ break;
+ case EbtUInt:
+ returnValue.setUConst(0u);
+ break;
+ default:
+ UNREACHABLE();
+ }
+ return returnValue;
+ }
+
+ switch (lhs.type)
+ {
+ case EbtInt:
+ switch (rhs.type)
+ {
+ // Cast to unsigned integer before shifting, since ESSL 3.00.6 section 5.9 says that
+ // lhs is "interpreted as a bit pattern". This also avoids the possibility of signed
+ // integer overflow or undefined shift of a negative integer.
+ case EbtInt:
+ returnValue.setIConst(
+ static_cast<int>(static_cast<uint32_t>(lhs.iConst) << rhs.iConst));
+ break;
+ case EbtUInt:
+ returnValue.setIConst(
+ static_cast<int>(static_cast<uint32_t>(lhs.iConst) << rhs.uConst));
+ break;
+ default:
+ UNREACHABLE();
+ }
+ break;
+
+ case EbtUInt:
+ switch (rhs.type)
+ {
+ case EbtInt:
+ returnValue.setUConst(lhs.uConst << rhs.iConst);
+ break;
+ case EbtUInt:
+ returnValue.setUConst(lhs.uConst << rhs.uConst);
+ break;
+ default:
+ UNREACHABLE();
+ }
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+ return returnValue;
+}
+
+TConstantUnion TConstantUnion::operator&(const TConstantUnion &constant) const
+{
+ TConstantUnion returnValue;
+ ASSERT(constant.type == EbtInt || constant.type == EbtUInt);
+ switch (type)
+ {
+ case EbtInt:
+ returnValue.setIConst(iConst & constant.iConst);
+ break;
+ case EbtUInt:
+ returnValue.setUConst(uConst & constant.uConst);
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return returnValue;
+}
+
+TConstantUnion TConstantUnion::operator|(const TConstantUnion &constant) const
+{
+ TConstantUnion returnValue;
+ ASSERT(type == constant.type);
+ switch (type)
+ {
+ case EbtInt:
+ returnValue.setIConst(iConst | constant.iConst);
+ break;
+ case EbtUInt:
+ returnValue.setUConst(uConst | constant.uConst);
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return returnValue;
+}
+
+TConstantUnion TConstantUnion::operator^(const TConstantUnion &constant) const
+{
+ TConstantUnion returnValue;
+ ASSERT(type == constant.type);
+ switch (type)
+ {
+ case EbtInt:
+ returnValue.setIConst(iConst ^ constant.iConst);
+ break;
+ case EbtUInt:
+ returnValue.setUConst(uConst ^ constant.uConst);
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return returnValue;
+}
+
+TConstantUnion TConstantUnion::operator&&(const TConstantUnion &constant) const
+{
+ TConstantUnion returnValue;
+ ASSERT(type == constant.type);
+ switch (type)
+ {
+ case EbtBool:
+ returnValue.setBConst(bConst && constant.bConst);
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return returnValue;
+}
+
+TConstantUnion TConstantUnion::operator||(const TConstantUnion &constant) const
+{
+ TConstantUnion returnValue;
+ ASSERT(type == constant.type);
+ switch (type)
+ {
+ case EbtBool:
+ returnValue.setBConst(bConst || constant.bConst);
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return returnValue;
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h b/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h
index a86d27f3ff..c1b3db9070 100644
--- a/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h
+++ b/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h
@@ -9,340 +9,109 @@
#include <assert.h>
+#include "compiler/translator/Common.h"
#include "compiler/translator/BaseTypes.h"
-class TConstantUnion {
-public:
- POOL_ALLOCATOR_NEW_DELETE();
- TConstantUnion()
- {
- iConst = 0;
- type = EbtVoid;
- }
-
- bool cast(TBasicType newType, const TConstantUnion &constant)
- {
- switch (newType)
- {
- case EbtFloat:
- switch (constant.type)
- {
- case EbtInt: setFConst(static_cast<float>(constant.getIConst())); break;
- case EbtUInt: setFConst(static_cast<float>(constant.getUConst())); break;
- case EbtBool: setFConst(static_cast<float>(constant.getBConst())); break;
- case EbtFloat: setFConst(static_cast<float>(constant.getFConst())); break;
- default: return false;
- }
- break;
- case EbtInt:
- switch (constant.type)
- {
- case EbtInt: setIConst(static_cast<int>(constant.getIConst())); break;
- case EbtUInt: setIConst(static_cast<int>(constant.getUConst())); break;
- case EbtBool: setIConst(static_cast<int>(constant.getBConst())); break;
- case EbtFloat: setIConst(static_cast<int>(constant.getFConst())); break;
- default: return false;
- }
- break;
- case EbtUInt:
- switch (constant.type)
- {
- case EbtInt: setUConst(static_cast<unsigned int>(constant.getIConst())); break;
- case EbtUInt: setUConst(static_cast<unsigned int>(constant.getUConst())); break;
- case EbtBool: setUConst(static_cast<unsigned int>(constant.getBConst())); break;
- case EbtFloat: setUConst(static_cast<unsigned int>(constant.getFConst())); break;
- default: return false;
- }
- break;
- case EbtBool:
- switch (constant.type)
- {
- case EbtInt: setBConst(constant.getIConst() != 0); break;
- case EbtUInt: setBConst(constant.getUConst() != 0); break;
- case EbtBool: setBConst(constant.getBConst()); break;
- case EbtFloat: setBConst(constant.getFConst() != 0.0f); break;
- default: return false;
- }
- break;
- case EbtStruct: // Struct fields don't get cast
- switch (constant.type)
- {
- case EbtInt: setIConst(constant.getIConst()); break;
- case EbtUInt: setUConst(constant.getUConst()); break;
- case EbtBool: setBConst(constant.getBConst()); break;
- case EbtFloat: setFConst(constant.getFConst()); break;
- default: return false;
- }
- break;
- default:
- return false;
- }
-
- return true;
- }
-
- void setIConst(int i) {iConst = i; type = EbtInt; }
- void setUConst(unsigned int u) { uConst = u; type = EbtUInt; }
- void setFConst(float f) {fConst = f; type = EbtFloat; }
- void setBConst(bool b) {bConst = b; type = EbtBool; }
-
- int getIConst() const { return iConst; }
- unsigned int getUConst() const { return uConst; }
- float getFConst() const { return fConst; }
- bool getBConst() const { return bConst; }
+namespace sh
+{
- bool operator==(const int i) const
- {
- return i == iConst;
- }
-
- bool operator==(const unsigned int u) const
- {
- return u == uConst;
- }
-
- bool operator==(const float f) const
- {
- return f == fConst;
- }
+class TDiagnostics;
- bool operator==(const bool b) const
- {
- return b == bConst;
- }
-
- bool operator==(const TConstantUnion& constant) const
- {
- if (constant.type != type)
- return false;
+class TConstantUnion
+{
+ public:
+ POOL_ALLOCATOR_NEW_DELETE();
+ TConstantUnion();
- switch (type) {
- case EbtInt:
- return constant.iConst == iConst;
- case EbtUInt:
- return constant.uConst == uConst;
- case EbtFloat:
- return constant.fConst == fConst;
- case EbtBool:
- return constant.bConst == bConst;
- default:
- return false;
- }
- }
+ bool cast(TBasicType newType, const TConstantUnion &constant);
- bool operator!=(const int i) const
+ void setIConst(int i)
{
- return !operator==(i);
+ iConst = i;
+ type = EbtInt;
}
-
- bool operator!=(const unsigned int u) const
+ void setUConst(unsigned int u)
{
- return !operator==(u);
+ uConst = u;
+ type = EbtUInt;
}
-
- bool operator!=(const float f) const
+ void setFConst(float f)
{
- return !operator==(f);
+ fConst = f;
+ type = EbtFloat;
}
-
- bool operator!=(const bool b) const
+ void setBConst(bool b)
{
- return !operator==(b);
+ bConst = b;
+ type = EbtBool;
}
- bool operator!=(const TConstantUnion& constant) const
+ void setYuvCscStandardEXTConst(TYuvCscStandardEXT s)
{
- return !operator==(constant);
- }
-
- bool operator>(const TConstantUnion& constant) const
- {
- assert(type == constant.type);
- switch (type) {
- case EbtInt:
- return iConst > constant.iConst;
- case EbtUInt:
- return uConst > constant.uConst;
- case EbtFloat:
- return fConst > constant.fConst;
- default:
- return false; // Invalid operation, handled at semantic analysis
- }
- }
-
- bool operator<(const TConstantUnion& constant) const
- {
- assert(type == constant.type);
- switch (type) {
- case EbtInt:
- return iConst < constant.iConst;
- case EbtUInt:
- return uConst < constant.uConst;
- case EbtFloat:
- return fConst < constant.fConst;
- default:
- return false; // Invalid operation, handled at semantic analysis
- }
- }
-
- TConstantUnion operator+(const TConstantUnion& constant) const
- {
- TConstantUnion returnValue;
- assert(type == constant.type);
- switch (type) {
- case EbtInt: returnValue.setIConst(iConst + constant.iConst); break;
- case EbtUInt: returnValue.setUConst(uConst + constant.uConst); break;
- case EbtFloat: returnValue.setFConst(fConst + constant.fConst); break;
- default: assert(false && "Default missing");
- }
-
- return returnValue;
- }
-
- TConstantUnion operator-(const TConstantUnion& constant) const
- {
- TConstantUnion returnValue;
- assert(type == constant.type);
- switch (type) {
- case EbtInt: returnValue.setIConst(iConst - constant.iConst); break;
- case EbtUInt: returnValue.setUConst(uConst - constant.uConst); break;
- case EbtFloat: returnValue.setFConst(fConst - constant.fConst); break;
- default: assert(false && "Default missing");
- }
-
- return returnValue;
- }
-
- TConstantUnion operator*(const TConstantUnion& constant) const
- {
- TConstantUnion returnValue;
- assert(type == constant.type);
- switch (type) {
- case EbtInt: returnValue.setIConst(iConst * constant.iConst); break;
- case EbtUInt: returnValue.setUConst(uConst * constant.uConst); break;
- case EbtFloat: returnValue.setFConst(fConst * constant.fConst); break;
- default: assert(false && "Default missing");
- }
-
- return returnValue;
- }
-
- TConstantUnion operator%(const TConstantUnion& constant) const
- {
- TConstantUnion returnValue;
- assert(type == constant.type);
- switch (type) {
- case EbtInt: returnValue.setIConst(iConst % constant.iConst); break;
- case EbtUInt: returnValue.setUConst(uConst % constant.uConst); break;
- default: assert(false && "Default missing");
- }
-
- return returnValue;
- }
-
- TConstantUnion operator>>(const TConstantUnion& constant) const
- {
- TConstantUnion returnValue;
- assert(type == constant.type);
- switch (type) {
- case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break;
- case EbtUInt: returnValue.setUConst(uConst >> constant.uConst); break;
- default: assert(false && "Default missing");
- }
-
- return returnValue;
- }
-
- TConstantUnion operator<<(const TConstantUnion& constant) const
- {
- TConstantUnion returnValue;
- // The signedness of the second parameter might be different, but we
- // don't care, since the result is undefined if the second parameter is
- // negative, and aliasing should not be a problem with unions.
- assert(constant.type == EbtInt || constant.type == EbtUInt);
- switch (type) {
- case EbtInt: returnValue.setIConst(iConst << constant.iConst); break;
- case EbtUInt: returnValue.setUConst(uConst << constant.uConst); break;
- default: assert(false && "Default missing");
- }
-
- return returnValue;
- }
-
- TConstantUnion operator&(const TConstantUnion& constant) const
- {
- TConstantUnion returnValue;
- assert(constant.type == EbtInt || constant.type == EbtUInt);
- switch (type) {
- case EbtInt: returnValue.setIConst(iConst & constant.iConst); break;
- case EbtUInt: returnValue.setUConst(uConst & constant.uConst); break;
- default: assert(false && "Default missing");
- }
-
- return returnValue;
- }
-
- TConstantUnion operator|(const TConstantUnion& constant) const
- {
- TConstantUnion returnValue;
- assert(type == constant.type);
- switch (type) {
- case EbtInt: returnValue.setIConst(iConst | constant.iConst); break;
- case EbtUInt: returnValue.setUConst(uConst | constant.uConst); break;
- default: assert(false && "Default missing");
- }
-
- return returnValue;
- }
-
- TConstantUnion operator^(const TConstantUnion& constant) const
- {
- TConstantUnion returnValue;
- assert(type == constant.type);
- switch (type) {
- case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break;
- case EbtUInt: returnValue.setUConst(uConst ^ constant.uConst); break;
- default: assert(false && "Default missing");
- }
-
- return returnValue;
- }
-
- TConstantUnion operator&&(const TConstantUnion& constant) const
- {
- TConstantUnion returnValue;
- assert(type == constant.type);
- switch (type) {
- case EbtBool: returnValue.setBConst(bConst && constant.bConst); break;
- default: assert(false && "Default missing");
- }
-
- return returnValue;
- }
-
- TConstantUnion operator||(const TConstantUnion& constant) const
- {
- TConstantUnion returnValue;
- assert(type == constant.type);
- switch (type) {
- case EbtBool: returnValue.setBConst(bConst || constant.bConst); break;
- default: assert(false && "Default missing");
- }
-
- return returnValue;
- }
+ yuvCscStandardEXTConst = s;
+ type = EbtYuvCscStandardEXT;
+ }
+
+ int getIConst() const;
+ unsigned int getUConst() const;
+ float getFConst() const;
+ bool getBConst() const;
+ TYuvCscStandardEXT getYuvCscStandardEXTConst() const;
+
+ bool operator==(const int i) const;
+ bool operator==(const unsigned int u) const;
+ bool operator==(const float f) const;
+ bool operator==(const bool b) const;
+ bool operator==(const TYuvCscStandardEXT s) const;
+ bool operator==(const TConstantUnion &constant) const;
+ bool operator!=(const int i) const;
+ bool operator!=(const unsigned int u) const;
+ bool operator!=(const float f) const;
+ bool operator!=(const bool b) const;
+ bool operator!=(const TYuvCscStandardEXT s) const;
+ bool operator!=(const TConstantUnion &constant) const;
+ bool operator>(const TConstantUnion &constant) const;
+ bool operator<(const TConstantUnion &constant) const;
+ static TConstantUnion add(const TConstantUnion &lhs,
+ const TConstantUnion &rhs,
+ TDiagnostics *diag,
+ const TSourceLoc &line);
+ static TConstantUnion sub(const TConstantUnion &lhs,
+ const TConstantUnion &rhs,
+ TDiagnostics *diag,
+ const TSourceLoc &line);
+ static TConstantUnion mul(const TConstantUnion &lhs,
+ const TConstantUnion &rhs,
+ TDiagnostics *diag,
+ const TSourceLoc &line);
+ TConstantUnion operator%(const TConstantUnion &constant) const;
+ static TConstantUnion rshift(const TConstantUnion &lhs,
+ const TConstantUnion &rhs,
+ TDiagnostics *diag,
+ const TSourceLoc &line);
+ static TConstantUnion lshift(const TConstantUnion &lhs,
+ const TConstantUnion &rhs,
+ TDiagnostics *diag,
+ const TSourceLoc &line);
+ TConstantUnion operator&(const TConstantUnion &constant) const;
+ TConstantUnion operator|(const TConstantUnion &constant) const;
+ TConstantUnion operator^(const TConstantUnion &constant) const;
+ TConstantUnion operator&&(const TConstantUnion &constant) const;
+ TConstantUnion operator||(const TConstantUnion &constant) const;
TBasicType getType() const { return type; }
-private:
-
- union {
- int iConst; // used for ivec, scalar ints
- unsigned int uConst; // used for uvec, scalar uints
- bool bConst; // used for bvec, scalar bools
- float fConst; // used for vec, mat, scalar floats
- } ;
+ private:
+ union {
+ int iConst; // used for ivec, scalar ints
+ unsigned int uConst; // used for uvec, scalar uints
+ bool bConst; // used for bvec, scalar bools
+ float fConst; // used for vec, mat, scalar floats
+ TYuvCscStandardEXT yuvCscStandardEXTConst;
+ };
TBasicType type;
};
-#endif // COMPILER_TRANSLATOR_CONSTANTUNION_H_
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_CONSTANTUNION_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp b/src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp
new file mode 100644
index 0000000000..ce9828f1f9
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp
@@ -0,0 +1,221 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Applies the necessary AST transformations to support multiview rendering through instancing.
+// Check the header file For more information.
+//
+
+#include "compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h"
+
+#include "compiler/translator/FindMain.h"
+#include "compiler/translator/InitializeVariables.h"
+#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/IntermTraverse.h"
+#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/util.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class ReplaceVariableTraverser : public TIntermTraverser
+{
+ public:
+ ReplaceVariableTraverser(const TString &symbolName, TIntermSymbol *newSymbol)
+ : TIntermTraverser(true, false, false), mSymbolName(symbolName), mNewSymbol(newSymbol)
+ {
+ }
+
+ void visitSymbol(TIntermSymbol *node) override
+ {
+ TName &name = node->getName();
+ if (name.getString() == mSymbolName)
+ {
+ queueReplacement(mNewSymbol->deepCopy(), OriginalNode::IS_DROPPED);
+ }
+ }
+
+ private:
+ TString mSymbolName;
+ TIntermSymbol *mNewSymbol;
+};
+
+TIntermSymbol *CreateGLInstanceIDSymbol(const TSymbolTable &symbolTable)
+{
+ return ReferenceBuiltInVariable("gl_InstanceID", symbolTable, 300);
+}
+
+// Adds the InstanceID and ViewID_OVR initializers to the end of the initializers' sequence.
+void InitializeViewIDAndInstanceID(TIntermTyped *viewIDSymbol,
+ TIntermTyped *instanceIDSymbol,
+ unsigned numberOfViews,
+ const TSymbolTable &symbolTable,
+ TIntermSequence *initializers)
+{
+ // Create an unsigned numberOfViews node.
+ TConstantUnion *numberOfViewsUnsignedConstant = new TConstantUnion();
+ numberOfViewsUnsignedConstant->setUConst(numberOfViews);
+ TIntermConstantUnion *numberOfViewsUint =
+ new TIntermConstantUnion(numberOfViewsUnsignedConstant, TType(EbtUInt, EbpHigh, EvqConst));
+
+ // Create a uint(gl_InstanceID) node.
+ TIntermSequence *glInstanceIDSymbolCastArguments = new TIntermSequence();
+ glInstanceIDSymbolCastArguments->push_back(CreateGLInstanceIDSymbol(symbolTable));
+ TIntermAggregate *glInstanceIDAsUint = TIntermAggregate::CreateConstructor(
+ TType(EbtUInt, EbpHigh, EvqTemporary), glInstanceIDSymbolCastArguments);
+
+ // Create a uint(gl_InstanceID) / numberOfViews node.
+ TIntermBinary *normalizedInstanceID =
+ new TIntermBinary(EOpDiv, glInstanceIDAsUint, numberOfViewsUint);
+
+ // Create an int(uint(gl_InstanceID) / numberOfViews) node.
+ TIntermSequence *normalizedInstanceIDCastArguments = new TIntermSequence();
+ normalizedInstanceIDCastArguments->push_back(normalizedInstanceID);
+ TIntermAggregate *normalizedInstanceIDAsInt = TIntermAggregate::CreateConstructor(
+ TType(EbtInt, EbpHigh, EvqTemporary), normalizedInstanceIDCastArguments);
+
+ // Create an InstanceID = int(uint(gl_InstanceID) / numberOfViews) node.
+ TIntermBinary *instanceIDInitializer =
+ new TIntermBinary(EOpAssign, instanceIDSymbol->deepCopy(), normalizedInstanceIDAsInt);
+ initializers->push_back(instanceIDInitializer);
+
+ // Create a uint(gl_InstanceID) % numberOfViews node.
+ TIntermBinary *normalizedViewID =
+ new TIntermBinary(EOpIMod, glInstanceIDAsUint->deepCopy(), numberOfViewsUint->deepCopy());
+
+ // Create a ViewID_OVR = uint(gl_InstanceID) % numberOfViews node.
+ TIntermBinary *viewIDInitializer =
+ new TIntermBinary(EOpAssign, viewIDSymbol->deepCopy(), normalizedViewID);
+ initializers->push_back(viewIDInitializer);
+}
+
+// Replaces every occurrence of a symbol with the name specified in symbolName with newSymbolNode.
+void ReplaceSymbol(TIntermBlock *root, const TString &symbolName, TIntermSymbol *newSymbolNode)
+{
+ ReplaceVariableTraverser traverser(symbolName, newSymbolNode);
+ root->traverse(&traverser);
+ traverser.updateTree();
+}
+
+void DeclareGlobalVariable(TIntermBlock *root, TIntermTyped *typedNode)
+{
+ TIntermSequence *globalSequence = root->getSequence();
+ TIntermDeclaration *declaration = new TIntermDeclaration();
+ declaration->appendDeclarator(typedNode->deepCopy());
+ globalSequence->insert(globalSequence->begin(), declaration);
+}
+
+// Adds a branch to write int(ViewID_OVR) to either gl_ViewportIndex or gl_Layer. The branch is
+// added to the end of the initializers' sequence.
+void SelectViewIndexInVertexShader(TIntermTyped *viewIDSymbol,
+ TIntermTyped *multiviewBaseViewLayerIndexSymbol,
+ TIntermSequence *initializers,
+ const TSymbolTable &symbolTable)
+{
+ // Create an int(ViewID_OVR) node.
+ TIntermSequence *viewIDSymbolCastArguments = new TIntermSequence();
+ viewIDSymbolCastArguments->push_back(viewIDSymbol);
+ TIntermAggregate *viewIDAsInt = TIntermAggregate::CreateConstructor(
+ TType(EbtInt, EbpHigh, EvqTemporary), viewIDSymbolCastArguments);
+
+ // Create a gl_ViewportIndex node.
+ TIntermSymbol *viewportIndexSymbol =
+ ReferenceBuiltInVariable("gl_ViewportIndex", symbolTable, 0);
+
+ // Create a { gl_ViewportIndex = int(ViewID_OVR) } node.
+ TIntermBlock *viewportIndexInitializerInBlock = new TIntermBlock();
+ viewportIndexInitializerInBlock->appendStatement(
+ new TIntermBinary(EOpAssign, viewportIndexSymbol, viewIDAsInt));
+
+ // Create a gl_Layer node.
+ TIntermSymbol *layerSymbol = ReferenceBuiltInVariable("gl_Layer", symbolTable, 0);
+
+ // Create an int(ViewID_OVR) + multiviewBaseViewLayerIndex node
+ TIntermBinary *sumOfViewIDAndBaseViewIndex =
+ new TIntermBinary(EOpAdd, viewIDAsInt->deepCopy(), multiviewBaseViewLayerIndexSymbol);
+
+ // Create a { gl_Layer = int(ViewID_OVR) + multiviewBaseViewLayerIndex } node.
+ TIntermBlock *layerInitializerInBlock = new TIntermBlock();
+ layerInitializerInBlock->appendStatement(
+ new TIntermBinary(EOpAssign, layerSymbol, sumOfViewIDAndBaseViewIndex));
+
+ // Create a node to compare whether the base view index uniform is less than zero.
+ TIntermBinary *multiviewBaseViewLayerIndexZeroComparison =
+ new TIntermBinary(EOpLessThan, multiviewBaseViewLayerIndexSymbol->deepCopy(),
+ CreateZeroNode(TType(EbtInt, EbpHigh, EvqConst)));
+
+ // Create an if-else statement to select the code path.
+ TIntermIfElse *multiviewBranch =
+ new TIntermIfElse(multiviewBaseViewLayerIndexZeroComparison,
+ viewportIndexInitializerInBlock, layerInitializerInBlock);
+
+ initializers->push_back(multiviewBranch);
+}
+
+} // namespace
+
+void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root,
+ unsigned numberOfViews,
+ GLenum shaderType,
+ ShCompileOptions compileOptions,
+ ShShaderOutput shaderOutput,
+ TSymbolTable *symbolTable)
+{
+ ASSERT(shaderType == GL_VERTEX_SHADER || shaderType == GL_FRAGMENT_SHADER);
+
+ TQualifier viewIDQualifier = (shaderType == GL_VERTEX_SHADER) ? EvqFlatOut : EvqFlatIn;
+ TIntermSymbol *viewIDSymbol = new TIntermSymbol(symbolTable->nextUniqueId(), "ViewID_OVR",
+ TType(EbtUInt, EbpHigh, viewIDQualifier));
+ viewIDSymbol->setInternal(true);
+
+ DeclareGlobalVariable(root, viewIDSymbol);
+ ReplaceSymbol(root, "gl_ViewID_OVR", viewIDSymbol);
+ if (shaderType == GL_VERTEX_SHADER)
+ {
+ // Replacing gl_InstanceID with InstanceID should happen before adding the initializers of
+ // InstanceID and ViewID.
+ TIntermSymbol *instanceIDSymbol = new TIntermSymbol(
+ symbolTable->nextUniqueId(), "InstanceID", TType(EbtInt, EbpHigh, EvqGlobal));
+ instanceIDSymbol->setInternal(true);
+ DeclareGlobalVariable(root, instanceIDSymbol);
+ ReplaceSymbol(root, "gl_InstanceID", instanceIDSymbol);
+
+ TIntermSequence *initializers = new TIntermSequence();
+ InitializeViewIDAndInstanceID(viewIDSymbol, instanceIDSymbol, numberOfViews, *symbolTable,
+ initializers);
+
+ // The AST transformation which adds the expression to select the viewport index should
+ // be done only for the GLSL and ESSL output.
+ const bool selectView = (compileOptions & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER) != 0u;
+ // Assert that if the view is selected in the vertex shader, then the output is
+ // either GLSL or ESSL.
+ ASSERT(!selectView || IsOutputGLSL(shaderOutput) || IsOutputESSL(shaderOutput));
+ if (selectView)
+ {
+ // Add a uniform to switch between side-by-side and layered rendering.
+ TIntermSymbol *multiviewBaseViewLayerIndexSymbol =
+ new TIntermSymbol(symbolTable->nextUniqueId(), "multiviewBaseViewLayerIndex",
+ TType(EbtInt, EbpHigh, EvqUniform));
+ multiviewBaseViewLayerIndexSymbol->setInternal(true);
+ DeclareGlobalVariable(root, multiviewBaseViewLayerIndexSymbol);
+
+ // Setting a value to gl_ViewportIndex or gl_Layer should happen after ViewID_OVR's
+ // initialization.
+ SelectViewIndexInVertexShader(viewIDSymbol->deepCopy(),
+ multiviewBaseViewLayerIndexSymbol->deepCopy(),
+ initializers, *symbolTable);
+ }
+
+ // Insert initializers at the beginning of main().
+ TIntermBlock *initializersBlock = new TIntermBlock();
+ initializersBlock->getSequence()->swap(*initializers);
+ TIntermBlock *mainBody = FindMainBody(root);
+ mainBody->getSequence()->insert(mainBody->getSequence()->begin(), initializersBlock);
+ }
+}
+
+} // namespace sh \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h b/src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h
new file mode 100644
index 0000000000..b4ab05fd0e
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h
@@ -0,0 +1,48 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Regardless of the shader type, the following AST transformations are applied:
+// - Add declaration of View_ID_OVR.
+// - Replace every occurrence of gl_ViewID_OVR with ViewID_OVR, mark ViewID_OVR as internal and
+// declare it as a flat varying.
+//
+// If the shader type is a vertex shader, the following AST transformations are applied:
+// - Replace every occurrence of gl_InstanceID with InstanceID, mark InstanceID as internal and set
+// its qualifier to EvqTemporary.
+// - Add initializers of ViewID_OVR and InstanceID to the beginning of the body of main. The pass
+// should be executed before any variables get collected so that usage of gl_InstanceID is recorded.
+// - If the output is ESSL or GLSL and the SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is
+// enabled, the expression
+// "if (multiviewBaseViewLayerIndex < 0) {
+// gl_ViewportIndex = int(ViewID_OVR);
+// } else {
+// gl_Layer = int(ViewID_OVR) + multiviewBaseViewLayerIndex;
+// }"
+// is added after ViewID and InstanceID are initialized. Also, MultiviewRenderPath is added as a
+// uniform.
+//
+
+#ifndef COMPILER_TRANSLATOR_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_
+#define COMPILER_TRANSLATOR_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_
+
+#include "GLSLANG/ShaderLang.h"
+#include "angle_gl.h"
+
+namespace sh
+{
+
+class TIntermBlock;
+class TSymbolTable;
+
+void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root,
+ unsigned numberOfViews,
+ GLenum shaderType,
+ ShCompileOptions compileOptions,
+ ShShaderOutput shaderOutput,
+ TSymbolTable *symbolTable);
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.cpp b/src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.cpp
new file mode 100644
index 0000000000..67d51ea87b
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.cpp
@@ -0,0 +1,147 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DeferGlobalInitializers is an AST traverser that moves global initializers into a separate
+// function that is called in the beginning of main(). This enables initialization of globals with
+// uniforms or non-constant globals, as allowed by the WebGL spec. Some initializers referencing
+// non-constants may need to be unfolded into if statements in HLSL - this kind of steps should be
+// done after DeferGlobalInitializers is run. Note that it's important that the function definition
+// is at the end of the shader, as some globals may be declared after main().
+//
+// It can also initialize all uninitialized globals.
+//
+
+#include "compiler/translator/DeferGlobalInitializers.h"
+
+#include "compiler/translator/FindMain.h"
+#include "compiler/translator/InitializeVariables.h"
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+namespace
+{
+
+void GetDeferredInitializers(TIntermDeclaration *declaration,
+ bool initializeUninitializedGlobals,
+ bool canUseLoopsToInitialize,
+ TIntermSequence *deferredInitializersOut,
+ TSymbolTable *symbolTable)
+{
+ // SeparateDeclarations should have already been run.
+ ASSERT(declaration->getSequence()->size() == 1);
+
+ TIntermNode *declarator = declaration->getSequence()->back();
+ TIntermBinary *init = declarator->getAsBinaryNode();
+ if (init)
+ {
+ TIntermSymbol *symbolNode = init->getLeft()->getAsSymbolNode();
+ ASSERT(symbolNode);
+ TIntermTyped *expression = init->getRight();
+
+ if ((expression->getQualifier() != EvqConst ||
+ (expression->getAsConstantUnion() == nullptr &&
+ !expression->isConstructorWithOnlyConstantUnionParameters())))
+ {
+ // For variables which are not constant, defer their real initialization until
+ // after we initialize uniforms.
+ // Deferral is done also in any cases where the variable has not been constant
+ // folded, since otherwise there's a chance that HLSL output will generate extra
+ // statements from the initializer expression.
+
+ // Change const global to a regular global if its initialization is deferred.
+ // This can happen if ANGLE has not been able to fold the constant expression used
+ // as an initializer.
+ ASSERT(symbolNode->getQualifier() == EvqConst ||
+ symbolNode->getQualifier() == EvqGlobal);
+ if (symbolNode->getQualifier() == EvqConst)
+ {
+ symbolNode->getTypePointer()->setQualifier(EvqGlobal);
+ }
+
+ TIntermBinary *deferredInit =
+ new TIntermBinary(EOpAssign, symbolNode->deepCopy(), init->getRight());
+ deferredInitializersOut->push_back(deferredInit);
+
+ // Remove the initializer from the global scope and just declare the global instead.
+ declaration->replaceChildNode(init, symbolNode);
+ }
+ }
+ else if (initializeUninitializedGlobals)
+ {
+ TIntermSymbol *symbolNode = declarator->getAsSymbolNode();
+ ASSERT(symbolNode);
+
+ // Ignore ANGLE internal variables.
+ if (symbolNode->getName().isInternal())
+ return;
+
+ if (symbolNode->getQualifier() == EvqGlobal && symbolNode->getSymbol() != "")
+ {
+ TIntermSequence *initCode =
+ CreateInitCode(symbolNode, canUseLoopsToInitialize, symbolTable);
+ deferredInitializersOut->insert(deferredInitializersOut->end(), initCode->begin(),
+ initCode->end());
+ }
+ }
+}
+
+void InsertInitCallToMain(TIntermBlock *root,
+ TIntermSequence *deferredInitializers,
+ TSymbolTable *symbolTable)
+{
+ TIntermBlock *initGlobalsBlock = new TIntermBlock();
+ initGlobalsBlock->getSequence()->swap(*deferredInitializers);
+
+ TSymbolUniqueId initGlobalsFunctionId(symbolTable);
+
+ const char *kInitGlobalsFunctionName = "initGlobals";
+
+ TIntermFunctionPrototype *initGlobalsFunctionPrototype =
+ CreateInternalFunctionPrototypeNode(TType(), kInitGlobalsFunctionName, initGlobalsFunctionId);
+ root->getSequence()->insert(root->getSequence()->begin(), initGlobalsFunctionPrototype);
+ TIntermFunctionDefinition *initGlobalsFunctionDefinition = CreateInternalFunctionDefinitionNode(
+ TType(), kInitGlobalsFunctionName, initGlobalsBlock, initGlobalsFunctionId);
+ root->appendStatement(initGlobalsFunctionDefinition);
+
+ TIntermAggregate *initGlobalsCall = CreateInternalFunctionCallNode(
+ TType(), kInitGlobalsFunctionName, initGlobalsFunctionId, new TIntermSequence());
+
+ TIntermBlock *mainBody = FindMainBody(root);
+ mainBody->getSequence()->insert(mainBody->getSequence()->begin(), initGlobalsCall);
+}
+
+} // namespace
+
+void DeferGlobalInitializers(TIntermBlock *root,
+ bool initializeUninitializedGlobals,
+ bool canUseLoopsToInitialize,
+ TSymbolTable *symbolTable)
+{
+ TIntermSequence *deferredInitializers = new TIntermSequence();
+
+ // Loop over all global statements and process the declarations. This is simpler than using a
+ // traverser.
+ for (TIntermNode *statement : *root->getSequence())
+ {
+ TIntermDeclaration *declaration = statement->getAsDeclarationNode();
+ if (declaration)
+ {
+ GetDeferredInitializers(declaration, initializeUninitializedGlobals,
+ canUseLoopsToInitialize, deferredInitializers, symbolTable);
+ }
+ }
+
+ // Add the function with initialization and the call to that.
+ if (!deferredInitializers->empty())
+ {
+ InsertInitCallToMain(root, deferredInitializers, symbolTable);
+ }
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.h b/src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.h
new file mode 100644
index 0000000000..86930a585f
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/DeferGlobalInitializers.h
@@ -0,0 +1,32 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DeferGlobalInitializers is an AST traverser that moves global initializers into a separate
+// function that is called in the beginning of main(). This enables initialization of globals with
+// uniforms or non-constant globals, as allowed by the WebGL spec. Some initializers referencing
+// non-constants may need to be unfolded into if statements in HLSL - this kind of steps should be
+// done after DeferGlobalInitializers is run. Note that it's important that the function definition
+// is at the end of the shader, as some globals may be declared after main().
+//
+// It can also initialize all uninitialized globals.
+//
+
+#ifndef COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_
+#define COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_
+
+namespace sh
+{
+
+class TIntermBlock;
+class TSymbolTable;
+
+void DeferGlobalInitializers(TIntermBlock *root,
+ bool initializeUninitializedGlobals,
+ bool canUseLoopsToInitialize,
+ TSymbolTable *symbolTable);
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.cpp b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.cpp
deleted file mode 100644
index 0dc5d22709..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.cpp
+++ /dev/null
@@ -1,185 +0,0 @@
-//
-// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/translator/DetectCallDepth.h"
-#include "compiler/translator/InfoSink.h"
-
-DetectCallDepth::FunctionNode::FunctionNode(const TString& fname)
- : name(fname),
- visit(PreVisit)
-{
-}
-
-const TString& DetectCallDepth::FunctionNode::getName() const
-{
- return name;
-}
-
-void DetectCallDepth::FunctionNode::addCallee(
- DetectCallDepth::FunctionNode* callee)
-{
- for (size_t i = 0; i < callees.size(); ++i) {
- if (callees[i] == callee)
- return;
- }
- callees.push_back(callee);
-}
-
-int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDepth, int depth)
-{
- ASSERT(visit == PreVisit);
- ASSERT(detectCallDepth);
-
- int retMaxDepth = depth;
- visit = InVisit;
- for (size_t i = 0; i < callees.size(); ++i) {
- switch (callees[i]->visit) {
- case InVisit:
- // cycle detected, i.e., recursion detected.
- return kInfiniteCallDepth;
- case PostVisit:
- break;
- case PreVisit: {
- // Check before we recurse so we don't go too depth
- if (detectCallDepth->checkExceedsMaxDepth(depth))
- return depth;
- int callDepth = callees[i]->detectCallDepth(detectCallDepth, depth + 1);
- // Check after we recurse so we can exit immediately and provide info.
- if (detectCallDepth->checkExceedsMaxDepth(callDepth)) {
- detectCallDepth->getInfoSink().info << "<-" << callees[i]->getName();
- return callDepth;
- }
- retMaxDepth = std::max(callDepth, retMaxDepth);
- break;
- }
- default:
- UNREACHABLE();
- break;
- }
- }
- visit = PostVisit;
- return retMaxDepth;
-}
-
-void DetectCallDepth::FunctionNode::reset()
-{
- visit = PreVisit;
-}
-
-DetectCallDepth::DetectCallDepth(TInfoSink& infoSink, bool limitCallStackDepth, int maxCallStackDepth)
- : TIntermTraverser(true, false, true, false),
- currentFunction(NULL),
- infoSink(infoSink),
- maxDepth(limitCallStackDepth ? maxCallStackDepth : FunctionNode::kInfiniteCallDepth)
-{
-}
-
-DetectCallDepth::~DetectCallDepth()
-{
- for (size_t i = 0; i < functions.size(); ++i)
- delete functions[i];
-}
-
-bool DetectCallDepth::visitAggregate(Visit visit, TIntermAggregate* node)
-{
- switch (node->getOp())
- {
- case EOpPrototype:
- // Function declaration.
- // Don't add FunctionNode here because node->getName() is the
- // unmangled function name.
- break;
- case EOpFunction: {
- // Function definition.
- if (visit == PreVisit) {
- currentFunction = findFunctionByName(node->getName());
- if (currentFunction == NULL) {
- currentFunction = new FunctionNode(node->getName());
- functions.push_back(currentFunction);
- }
- } else if (visit == PostVisit) {
- currentFunction = NULL;
- }
- break;
- }
- case EOpFunctionCall: {
- // Function call.
- if (visit == PreVisit) {
- FunctionNode* func = findFunctionByName(node->getName());
- if (func == NULL) {
- func = new FunctionNode(node->getName());
- functions.push_back(func);
- }
- if (currentFunction)
- currentFunction->addCallee(func);
- }
- break;
- }
- default:
- break;
- }
- return true;
-}
-
-bool DetectCallDepth::checkExceedsMaxDepth(int depth)
-{
- return depth >= maxDepth;
-}
-
-void DetectCallDepth::resetFunctionNodes()
-{
- for (size_t i = 0; i < functions.size(); ++i) {
- functions[i]->reset();
- }
-}
-
-DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepthForFunction(FunctionNode* func)
-{
- currentFunction = NULL;
- resetFunctionNodes();
-
- int maxCallDepth = func->detectCallDepth(this, 1);
-
- if (maxCallDepth == FunctionNode::kInfiniteCallDepth)
- return kErrorRecursion;
-
- if (maxCallDepth >= maxDepth)
- return kErrorMaxDepthExceeded;
-
- return kErrorNone;
-}
-
-DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepth()
-{
- if (maxDepth != FunctionNode::kInfiniteCallDepth) {
- // Check all functions because the driver may fail on them
- // TODO: Before detectingRecursion, strip unused functions.
- for (size_t i = 0; i < functions.size(); ++i) {
- ErrorCode error = detectCallDepthForFunction(functions[i]);
- if (error != kErrorNone)
- return error;
- }
- } else {
- FunctionNode* main = findFunctionByName("main(");
- if (main == NULL)
- return kErrorMissingMain;
-
- return detectCallDepthForFunction(main);
- }
-
- return kErrorNone;
-}
-
-DetectCallDepth::FunctionNode* DetectCallDepth::findFunctionByName(
- const TString& name)
-{
- for (size_t i = 0; i < functions.size(); ++i) {
- if (functions[i]->getName() == name)
- return functions[i];
- }
- return NULL;
-}
-
diff --git a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h
deleted file mode 100644
index 8dd1391e67..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h
+++ /dev/null
@@ -1,78 +0,0 @@
-//
-// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_TRANSLATOR_DETECTCALLDEPTH_H_
-#define COMPILER_TRANSLATOR_DETECTCALLDEPTH_H_
-
-#include <limits.h>
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/VariableInfo.h"
-
-class TInfoSink;
-
-// Traverses intermediate tree to detect function recursion.
-class DetectCallDepth : public TIntermTraverser {
-public:
- enum ErrorCode {
- kErrorMissingMain,
- kErrorRecursion,
- kErrorMaxDepthExceeded,
- kErrorNone
- };
-
- DetectCallDepth(TInfoSink& infoSync, bool limitCallStackDepth, int maxCallStackDepth);
- ~DetectCallDepth();
-
- virtual bool visitAggregate(Visit, TIntermAggregate*);
-
- bool checkExceedsMaxDepth(int depth);
-
- ErrorCode detectCallDepth();
-
-private:
- class FunctionNode {
- public:
- static const int kInfiniteCallDepth = INT_MAX;
-
- FunctionNode(const TString& fname);
-
- const TString& getName() const;
-
- // If a function is already in the callee list, this becomes a no-op.
- void addCallee(FunctionNode* callee);
-
- // Returns kInifinityCallDepth if recursive function calls are detected.
- int detectCallDepth(DetectCallDepth* detectCallDepth, int depth);
-
- // Reset state.
- void reset();
-
- private:
- // mangled function name is unique.
- TString name;
-
- // functions that are directly called by this function.
- TVector<FunctionNode*> callees;
-
- Visit visit;
- };
-
- ErrorCode detectCallDepthForFunction(FunctionNode* func);
- FunctionNode* findFunctionByName(const TString& name);
- void resetFunctionNodes();
-
- TInfoSink& getInfoSink() { return infoSink; }
-
- TVector<FunctionNode*> functions;
- FunctionNode* currentFunction;
- TInfoSink& infoSink;
- int maxDepth;
-
- DetectCallDepth(const DetectCallDepth&);
- void operator=(const DetectCallDepth&);
-};
-
-#endif // COMPILER_TRANSLATOR_DETECTCALLDEPTH_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.cpp b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.cpp
deleted file mode 100644
index f98d32b2b7..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.cpp
+++ /dev/null
@@ -1,191 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Contains analysis utilities for dealing with HLSL's lack of support for
-// the use of intrinsic functions which (implicitly or explicitly) compute
-// gradients of functions with discontinuities.
-//
-
-#include "compiler/translator/DetectDiscontinuity.h"
-
-#include "compiler/translator/ParseContext.h"
-
-namespace sh
-{
-
-// Detect Loop Discontinuity
-
-bool DetectLoopDiscontinuity::traverse(TIntermNode *node)
-{
- mLoopDepth = 0;
- mLoopDiscontinuity = false;
- node->traverse(this);
- return mLoopDiscontinuity;
-}
-
-bool DetectLoopDiscontinuity::visitLoop(Visit visit, TIntermLoop *loop)
-{
- if (visit == PreVisit)
- {
- ++mLoopDepth;
- }
- else if (visit == PostVisit)
- {
- --mLoopDepth;
- }
-
- return true;
-}
-
-bool DetectLoopDiscontinuity::visitBranch(Visit visit, TIntermBranch *node)
-{
- if (mLoopDiscontinuity)
- {
- return false;
- }
-
- if (!mLoopDepth)
- {
- return true;
- }
-
- switch (node->getFlowOp())
- {
- case EOpKill:
- break;
- case EOpBreak:
- case EOpContinue:
- case EOpReturn:
- mLoopDiscontinuity = true;
- break;
- default: UNREACHABLE();
- }
-
- return !mLoopDiscontinuity;
-}
-
-bool DetectLoopDiscontinuity::visitAggregate(Visit visit, TIntermAggregate *node)
-{
- return !mLoopDiscontinuity;
-}
-
-bool containsLoopDiscontinuity(TIntermNode *node)
-{
- DetectLoopDiscontinuity detectLoopDiscontinuity;
- return detectLoopDiscontinuity.traverse(node);
-}
-
-// Detect Any Loop
-
-bool DetectAnyLoop::traverse(TIntermNode *node)
-{
- mHasLoop = false;
- node->traverse(this);
- return mHasLoop;
-}
-
-bool DetectAnyLoop::visitLoop(Visit visit, TIntermLoop *loop)
-{
- mHasLoop = true;
- return false;
-}
-
-// The following definitions stop all traversal when we have found a loop
-bool DetectAnyLoop::visitBinary(Visit, TIntermBinary *)
-{
- return !mHasLoop;
-}
-
-bool DetectAnyLoop::visitUnary(Visit, TIntermUnary *)
-{
- return !mHasLoop;
-}
-
-bool DetectAnyLoop::visitSelection(Visit, TIntermSelection *)
-{
- return !mHasLoop;
-}
-
-bool DetectAnyLoop::visitAggregate(Visit, TIntermAggregate *)
-{
- return !mHasLoop;
-}
-
-bool DetectAnyLoop::visitBranch(Visit, TIntermBranch *)
-{
- return !mHasLoop;
-}
-
-bool containsAnyLoop(TIntermNode *node)
-{
- DetectAnyLoop detectAnyLoop;
- return detectAnyLoop.traverse(node);
-}
-
-// Detect Gradient Operation
-
-bool DetectGradientOperation::traverse(TIntermNode *node)
-{
- mGradientOperation = false;
- node->traverse(this);
- return mGradientOperation;
-}
-
-bool DetectGradientOperation::visitUnary(Visit visit, TIntermUnary *node)
-{
- if (mGradientOperation)
- {
- return false;
- }
-
- switch (node->getOp())
- {
- case EOpDFdx:
- case EOpDFdy:
- mGradientOperation = true;
- default:
- break;
- }
-
- return !mGradientOperation;
-}
-
-bool DetectGradientOperation::visitAggregate(Visit visit, TIntermAggregate *node)
-{
- if (mGradientOperation)
- {
- return false;
- }
-
- if (node->getOp() == EOpFunctionCall)
- {
- if (!node->isUserDefined())
- {
- TString name = TFunction::unmangleName(node->getName());
-
- if (name == "texture2D" ||
- name == "texture2DProj" ||
- name == "textureCube")
- {
- mGradientOperation = true;
- }
- }
- else
- {
- // When a user defined function is called, we have to
- // conservatively assume it to contain gradient operations
- mGradientOperation = true;
- }
- }
-
- return !mGradientOperation;
-}
-
-bool containsGradientOperation(TIntermNode *node)
-{
- DetectGradientOperation detectGradientOperation;
- return detectGradientOperation.traverse(node);
-}
-}
diff --git a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h
deleted file mode 100644
index 623be13533..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h
+++ /dev/null
@@ -1,71 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Contains analysis utilities for dealing with HLSL's lack of support for
-// the use of intrinsic functions which (implicitly or explicitly) compute
-// gradients of functions with discontinuities.
-//
-
-#ifndef COMPILER_TRANSLATOR_DETECTDISCONTINUITY_H_
-#define COMPILER_TRANSLATOR_DETECTDISCONTINUITY_H_
-
-#include "compiler/translator/IntermNode.h"
-
-namespace sh
-{
-// Checks whether a loop can run for a variable number of iterations
-class DetectLoopDiscontinuity : public TIntermTraverser
-{
- public:
- bool traverse(TIntermNode *node);
-
- protected:
- bool visitBranch(Visit visit, TIntermBranch *node);
- bool visitLoop(Visit visit, TIntermLoop *loop);
- bool visitAggregate(Visit visit, TIntermAggregate *node);
-
- int mLoopDepth;
- bool mLoopDiscontinuity;
-};
-
-bool containsLoopDiscontinuity(TIntermNode *node);
-
-// Checks for the existence of any loop
-class DetectAnyLoop : public TIntermTraverser
-{
-public:
- bool traverse(TIntermNode *node);
-
-protected:
- bool visitBinary(Visit, TIntermBinary *);
- bool visitUnary(Visit, TIntermUnary *);
- bool visitSelection(Visit, TIntermSelection *);
- bool visitAggregate(Visit, TIntermAggregate *);
- bool visitLoop(Visit, TIntermLoop *);
- bool visitBranch(Visit, TIntermBranch *);
-
- bool mHasLoop;
-};
-
-bool containsAnyLoop(TIntermNode *node);
-
-// Checks for intrinsic functions which compute gradients
-class DetectGradientOperation : public TIntermTraverser
-{
- public:
- bool traverse(TIntermNode *node);
-
- protected:
- bool visitUnary(Visit visit, TIntermUnary *node);
- bool visitAggregate(Visit visit, TIntermAggregate *node);
-
- bool mGradientOperation;
-};
-
-bool containsGradientOperation(TIntermNode *node);
-
-}
-
-#endif // COMPILER_TRANSLATOR_DETECTDISCONTINUITY_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp b/src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp
index 593137fb0a..1744e5ab3e 100644
--- a/src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp
@@ -7,13 +7,15 @@
#include "compiler/translator/Diagnostics.h"
#include "common/debug.h"
-#include "compiler/translator/InfoSink.h"
#include "compiler/preprocessor/SourceLocation.h"
+#include "compiler/translator/Common.h"
+#include "compiler/translator/InfoSink.h"
+
+namespace sh
+{
-TDiagnostics::TDiagnostics(TInfoSink& infoSink) :
- mInfoSink(infoSink),
- mNumErrors(0),
- mNumWarnings(0)
+TDiagnostics::TDiagnostics(TInfoSinkBase &infoSink)
+ : mInfoSink(infoSink), mNumErrors(0), mNumWarnings(0)
{
}
@@ -22,37 +24,82 @@ TDiagnostics::~TDiagnostics()
}
void TDiagnostics::writeInfo(Severity severity,
- const pp::SourceLocation& loc,
- const std::string& reason,
- const std::string& token,
- const std::string& extra)
+ const pp::SourceLocation &loc,
+ const char *reason,
+ const char *token)
{
- TPrefixType prefix = EPrefixNone;
switch (severity)
{
- case PP_ERROR:
- ++mNumErrors;
- prefix = EPrefixError;
- break;
- case PP_WARNING:
- ++mNumWarnings;
- prefix = EPrefixWarning;
- break;
- default:
- UNREACHABLE();
- break;
+ case SH_ERROR:
+ ++mNumErrors;
+ break;
+ case SH_WARNING:
+ ++mNumWarnings;
+ break;
+ default:
+ UNREACHABLE();
+ break;
}
- TInfoSinkBase& sink = mInfoSink.info;
/* VC++ format: file(linenum) : error #: 'token' : extrainfo */
- sink.prefix(prefix);
- sink.location(loc.file, loc.line);
- sink << "'" << token << "' : " << reason << " " << extra << "\n";
+ mInfoSink.prefix(severity);
+ mInfoSink.location(loc.file, loc.line);
+ mInfoSink << "'" << token << "' : " << reason << "\n";
}
-void TDiagnostics::print(ID id,
- const pp::SourceLocation& loc,
- const std::string& text)
+void TDiagnostics::globalError(const char *message)
{
- writeInfo(severity(id), loc, message(id), text, "");
+ ++mNumErrors;
+ mInfoSink.prefix(SH_ERROR);
+ mInfoSink << message << "\n";
}
+
+void TDiagnostics::error(const pp::SourceLocation &loc, const char *reason, const char *token)
+{
+ writeInfo(SH_ERROR, loc, reason, token);
+}
+
+void TDiagnostics::warning(const pp::SourceLocation &loc, const char *reason, const char *token)
+{
+ writeInfo(SH_WARNING, loc, reason, token);
+}
+
+void TDiagnostics::error(const TSourceLoc &loc, const char *reason, const char *token)
+{
+ pp::SourceLocation srcLoc;
+ srcLoc.file = loc.first_file;
+ srcLoc.line = loc.first_line;
+ error(srcLoc, reason, token);
+}
+
+void TDiagnostics::warning(const TSourceLoc &loc, const char *reason, const char *token)
+{
+ pp::SourceLocation srcLoc;
+ srcLoc.file = loc.first_file;
+ srcLoc.line = loc.first_line;
+ warning(srcLoc, reason, token);
+}
+
+void TDiagnostics::print(ID id, const pp::SourceLocation &loc, const std::string &text)
+{
+ writeInfo(isError(id) ? SH_ERROR : SH_WARNING, loc, message(id), text.c_str());
+}
+
+void TDiagnostics::resetErrorCount()
+{
+ mNumErrors = 0;
+ mNumWarnings = 0;
+}
+
+PerformanceDiagnostics::PerformanceDiagnostics(TDiagnostics *diagnostics)
+ : mDiagnostics(diagnostics)
+{
+ ASSERT(diagnostics);
+}
+
+void PerformanceDiagnostics::warning(const TSourceLoc &loc, const char *reason, const char *token)
+{
+ mDiagnostics->warning(loc, reason, token);
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/Diagnostics.h b/src/3rdparty/angle/src/compiler/translator/Diagnostics.h
index bc26e4584f..55b88991df 100644
--- a/src/3rdparty/angle/src/compiler/translator/Diagnostics.h
+++ b/src/3rdparty/angle/src/compiler/translator/Diagnostics.h
@@ -9,33 +9,59 @@
#include "common/angleutils.h"
#include "compiler/preprocessor/DiagnosticsBase.h"
+#include "compiler/translator/Severity.h"
-class TInfoSink;
+namespace sh
+{
+
+class TInfoSinkBase;
+struct TSourceLoc;
class TDiagnostics : public pp::Diagnostics, angle::NonCopyable
{
public:
- TDiagnostics(TInfoSink& infoSink);
+ TDiagnostics(TInfoSinkBase &infoSink);
~TDiagnostics() override;
- TInfoSink& infoSink() { return mInfoSink; }
-
int numErrors() const { return mNumErrors; }
int numWarnings() const { return mNumWarnings; }
- void writeInfo(Severity severity,
- const pp::SourceLocation& loc,
- const std::string& reason,
- const std::string& token,
- const std::string& extra);
+ void error(const pp::SourceLocation &loc, const char *reason, const char *token);
+ void warning(const pp::SourceLocation &loc, const char *reason, const char *token);
+
+ void error(const TSourceLoc &loc, const char *reason, const char *token);
+ void warning(const TSourceLoc &loc, const char *reason, const char *token);
+
+ void globalError(const char *message);
+
+ void resetErrorCount();
protected:
+ void writeInfo(Severity severity,
+ const pp::SourceLocation &loc,
+ const char *reason,
+ const char *token);
+
void print(ID id, const pp::SourceLocation &loc, const std::string &text) override;
private:
- TInfoSink& mInfoSink;
+ TInfoSinkBase &mInfoSink;
int mNumErrors;
int mNumWarnings;
};
+// Diagnostics wrapper to use when the code is only allowed to generate warnings.
+class PerformanceDiagnostics : public angle::NonCopyable
+{
+ public:
+ PerformanceDiagnostics(TDiagnostics *diagnostics);
+
+ void warning(const TSourceLoc &loc, const char *reason, const char *token);
+
+ private:
+ TDiagnostics *mDiagnostics;
+};
+
+} // namespace sh
+
#endif // COMPILER_TRANSLATOR_DIAGNOSTICS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp
index ff8a69efa5..485e66670c 100644
--- a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp
@@ -12,17 +12,24 @@
#include "common/debug.h"
#include "compiler/translator/Diagnostics.h"
-static TBehavior getBehavior(const std::string& str)
+namespace sh
+{
+
+static TBehavior getBehavior(const std::string &str)
{
const char kRequire[] = "require";
- const char kEnable[] = "enable";
+ const char kEnable[] = "enable";
const char kDisable[] = "disable";
- const char kWarn[] = "warn";
-
- if (str == kRequire) return EBhRequire;
- else if (str == kEnable) return EBhEnable;
- else if (str == kDisable) return EBhDisable;
- else if (str == kWarn) return EBhWarn;
+ const char kWarn[] = "warn";
+
+ if (str == kRequire)
+ return EBhRequire;
+ else if (str == kEnable)
+ return EBhEnable;
+ else if (str == kDisable)
+ return EBhDisable;
+ else if (str == kWarn)
+ return EBhWarn;
return EBhUndefined;
}
@@ -43,30 +50,29 @@ TDirectiveHandler::~TDirectiveHandler()
{
}
-void TDirectiveHandler::handleError(const pp::SourceLocation& loc,
- const std::string& msg)
+void TDirectiveHandler::handleError(const pp::SourceLocation &loc, const std::string &msg)
{
- mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, msg, "", "");
+ mDiagnostics.error(loc, msg.c_str(), "");
}
-void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc,
- const std::string& name,
- const std::string& value,
+void TDirectiveHandler::handlePragma(const pp::SourceLocation &loc,
+ const std::string &name,
+ const std::string &value,
bool stdgl)
{
if (stdgl)
{
const char kInvariant[] = "invariant";
- const char kAll[] = "all";
+ const char kAll[] = "all";
if (name == kInvariant && value == kAll)
{
if (mShaderVersion == 300 && mShaderType == GL_FRAGMENT_SHADER)
{
// ESSL 3.00.4 section 4.6.1
- mDiagnostics.writeInfo(
- pp::Diagnostics::PP_ERROR, loc,
- "#pragma STDGL invariant(all) can not be used in fragment shader", name, value);
+ mDiagnostics.error(
+ loc, "#pragma STDGL invariant(all) can not be used in fragment shader",
+ name.c_str());
}
mPragma.stdgl.invariantAll = true;
}
@@ -77,30 +83,39 @@ void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc,
}
else
{
- const char kOptimize[] = "optimize";
- const char kDebug[] = "debug";
+ const char kOptimize[] = "optimize";
+ const char kDebug[] = "debug";
const char kDebugShaderPrecision[] = "webgl_debug_shader_precision";
- const char kOn[] = "on";
- const char kOff[] = "off";
+ const char kOn[] = "on";
+ const char kOff[] = "off";
bool invalidValue = false;
if (name == kOptimize)
{
- if (value == kOn) mPragma.optimize = true;
- else if (value == kOff) mPragma.optimize = false;
- else invalidValue = true;
+ if (value == kOn)
+ mPragma.optimize = true;
+ else if (value == kOff)
+ mPragma.optimize = false;
+ else
+ invalidValue = true;
}
else if (name == kDebug)
{
- if (value == kOn) mPragma.debug = true;
- else if (value == kOff) mPragma.debug = false;
- else invalidValue = true;
+ if (value == kOn)
+ mPragma.debug = true;
+ else if (value == kOff)
+ mPragma.debug = false;
+ else
+ invalidValue = true;
}
else if (name == kDebugShaderPrecision && mDebugShaderPrecisionSupported)
{
- if (value == kOn) mPragma.debugShaderPrecision = true;
- else if (value == kOff) mPragma.debugShaderPrecision = false;
- else invalidValue = true;
+ if (value == kOn)
+ mPragma.debugShaderPrecision = true;
+ else if (value == kOff)
+ mPragma.debugShaderPrecision = false;
+ else
+ invalidValue = true;
}
else
{
@@ -110,24 +125,21 @@ void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc,
if (invalidValue)
{
- mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
- "invalid pragma value", value,
- "'on' or 'off' expected");
+ mDiagnostics.error(loc, "invalid pragma value - 'on' or 'off' expected", value.c_str());
}
}
}
-void TDirectiveHandler::handleExtension(const pp::SourceLocation& loc,
- const std::string& name,
- const std::string& behavior)
+void TDirectiveHandler::handleExtension(const pp::SourceLocation &loc,
+ const std::string &name,
+ const std::string &behavior)
{
const char kExtAll[] = "all";
TBehavior behaviorVal = getBehavior(behavior);
if (behaviorVal == EBhUndefined)
{
- mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
- "behavior", name, "invalid");
+ mDiagnostics.error(loc, "behavior invalid", name.c_str());
return;
}
@@ -135,15 +147,11 @@ void TDirectiveHandler::handleExtension(const pp::SourceLocation& loc,
{
if (behaviorVal == EBhRequire)
{
- mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
- "extension", name,
- "cannot have 'require' behavior");
+ mDiagnostics.error(loc, "extension cannot have 'require' behavior", name.c_str());
}
else if (behaviorVal == EBhEnable)
{
- mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
- "extension", name,
- "cannot have 'enable' behavior");
+ mDiagnostics.error(loc, "extension cannot have 'enable' behavior", name.c_str());
}
else
{
@@ -154,36 +162,32 @@ void TDirectiveHandler::handleExtension(const pp::SourceLocation& loc,
return;
}
- TExtensionBehavior::iterator iter = mExtensionBehavior.find(name);
+ TExtensionBehavior::iterator iter = mExtensionBehavior.find(GetExtensionByName(name.c_str()));
if (iter != mExtensionBehavior.end())
{
iter->second = behaviorVal;
return;
}
- pp::Diagnostics::Severity severity = pp::Diagnostics::PP_ERROR;
- switch (behaviorVal) {
- case EBhRequire:
- severity = pp::Diagnostics::PP_ERROR;
- break;
- case EBhEnable:
- case EBhWarn:
- case EBhDisable:
- severity = pp::Diagnostics::PP_WARNING;
- break;
- default:
- UNREACHABLE();
- break;
+ switch (behaviorVal)
+ {
+ case EBhRequire:
+ mDiagnostics.error(loc, "extension is not supported", name.c_str());
+ break;
+ case EBhEnable:
+ case EBhWarn:
+ case EBhDisable:
+ mDiagnostics.warning(loc, "extension is not supported", name.c_str());
+ break;
+ default:
+ UNREACHABLE();
+ break;
}
- mDiagnostics.writeInfo(severity, loc,
- "extension", name, "is not supported");
}
-void TDirectiveHandler::handleVersion(const pp::SourceLocation& loc,
- int version)
+void TDirectiveHandler::handleVersion(const pp::SourceLocation &loc, int version)
{
- if (version == 100 ||
- version == 300)
+ if (version == 100 || version == 300 || version == 310)
{
mShaderVersion = version;
}
@@ -192,7 +196,8 @@ void TDirectiveHandler::handleVersion(const pp::SourceLocation& loc,
std::stringstream stream;
stream << version;
std::string str = stream.str();
- mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
- "version number", str, "not supported");
+ mDiagnostics.error(loc, "version number not supported", str.c_str());
}
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h
index 00eb49114e..8e8cb9bbf6 100644
--- a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h
+++ b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h
@@ -13,6 +13,8 @@
#include "compiler/preprocessor/DirectiveHandlerBase.h"
#include "GLSLANG/ShaderLang.h"
+namespace sh
+{
class TDiagnostics;
class TDirectiveHandler : public pp::DirectiveHandler, angle::NonCopyable
@@ -25,8 +27,8 @@ class TDirectiveHandler : public pp::DirectiveHandler, angle::NonCopyable
bool debugShaderPrecisionSupported);
~TDirectiveHandler() override;
- const TPragma& pragma() const { return mPragma; }
- const TExtensionBehavior& extensionBehavior() const { return mExtensionBehavior; }
+ const TPragma &pragma() const { return mPragma; }
+ const TExtensionBehavior &extensionBehavior() const { return mExtensionBehavior; }
void handleError(const pp::SourceLocation &loc, const std::string &msg) override;
@@ -43,11 +45,13 @@ class TDirectiveHandler : public pp::DirectiveHandler, angle::NonCopyable
private:
TPragma mPragma;
- TExtensionBehavior& mExtensionBehavior;
- TDiagnostics& mDiagnostics;
- int& mShaderVersion;
+ TExtensionBehavior &mExtensionBehavior;
+ TDiagnostics &mDiagnostics;
+ int &mShaderVersion;
sh::GLenum mShaderType;
bool mDebugShaderPrecisionSupported;
};
+} // namespace sh
+
#endif // COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.cpp b/src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.cpp
new file mode 100644
index 0000000000..189ea341eb
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.cpp
@@ -0,0 +1,129 @@
+//
+// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// gl_FragColor needs to broadcast to all color buffers in ES2 if
+// GL_EXT_draw_buffers is explicitly enabled in a fragment shader.
+//
+// We emulate this by replacing all gl_FragColor with gl_FragData[0], and in the end
+// of main() function, assigning gl_FragData[1], ..., gl_FragData[maxDrawBuffers-1]
+// with gl_FragData[0].
+//
+
+#include "compiler/translator/EmulateGLFragColorBroadcast.h"
+
+#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/IntermTraverse.h"
+#include "compiler/translator/RunAtTheEndOfShader.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class GLFragColorBroadcastTraverser : public TIntermTraverser
+{
+ public:
+ GLFragColorBroadcastTraverser(int maxDrawBuffers, TSymbolTable *symbolTable, int shaderVersion)
+ : TIntermTraverser(true, false, false, symbolTable),
+ mGLFragColorUsed(false),
+ mMaxDrawBuffers(maxDrawBuffers),
+ mShaderVersion(shaderVersion)
+ {
+ }
+
+ void broadcastGLFragColor(TIntermBlock *root);
+
+ bool isGLFragColorUsed() const { return mGLFragColorUsed; }
+
+ protected:
+ void visitSymbol(TIntermSymbol *node) override;
+
+ TIntermBinary *constructGLFragDataNode(int index) const;
+ TIntermBinary *constructGLFragDataAssignNode(int index) const;
+
+ private:
+ bool mGLFragColorUsed;
+ int mMaxDrawBuffers;
+ const int mShaderVersion;
+};
+
+TIntermBinary *GLFragColorBroadcastTraverser::constructGLFragDataNode(int index) const
+{
+ TIntermSymbol *symbol =
+ ReferenceBuiltInVariable(TString("gl_FragData"), *mSymbolTable, mShaderVersion);
+ TIntermTyped *indexNode = CreateIndexNode(index);
+
+ TIntermBinary *binary = new TIntermBinary(EOpIndexDirect, symbol, indexNode);
+ return binary;
+}
+
+TIntermBinary *GLFragColorBroadcastTraverser::constructGLFragDataAssignNode(int index) const
+{
+ TIntermTyped *fragDataIndex = constructGLFragDataNode(index);
+ TIntermTyped *fragDataZero = constructGLFragDataNode(0);
+
+ return new TIntermBinary(EOpAssign, fragDataIndex, fragDataZero);
+}
+
+void GLFragColorBroadcastTraverser::visitSymbol(TIntermSymbol *node)
+{
+ if (node->getSymbol() == "gl_FragColor")
+ {
+ queueReplacement(constructGLFragDataNode(0), OriginalNode::IS_DROPPED);
+ mGLFragColorUsed = true;
+ }
+}
+
+void GLFragColorBroadcastTraverser::broadcastGLFragColor(TIntermBlock *root)
+{
+ ASSERT(mMaxDrawBuffers > 1);
+ if (!mGLFragColorUsed)
+ {
+ return;
+ }
+
+ TIntermBlock *broadcastBlock = new TIntermBlock();
+ // Now insert statements
+ // gl_FragData[1] = gl_FragData[0];
+ // ...
+ // gl_FragData[maxDrawBuffers - 1] = gl_FragData[0];
+ for (int colorIndex = 1; colorIndex < mMaxDrawBuffers; ++colorIndex)
+ {
+ broadcastBlock->appendStatement(constructGLFragDataAssignNode(colorIndex));
+ }
+ RunAtTheEndOfShader(root, broadcastBlock, mSymbolTable);
+}
+
+} // namespace anonymous
+
+void EmulateGLFragColorBroadcast(TIntermBlock *root,
+ int maxDrawBuffers,
+ std::vector<sh::OutputVariable> *outputVariables,
+ TSymbolTable *symbolTable,
+ int shaderVersion)
+{
+ ASSERT(maxDrawBuffers > 1);
+ GLFragColorBroadcastTraverser traverser(maxDrawBuffers, symbolTable, shaderVersion);
+ root->traverse(&traverser);
+ if (traverser.isGLFragColorUsed())
+ {
+ traverser.updateTree();
+ traverser.broadcastGLFragColor(root);
+ for (auto &var : *outputVariables)
+ {
+ if (var.name == "gl_FragColor")
+ {
+ // TODO(zmo): Find a way to keep the original variable information.
+ var.name = "gl_FragData";
+ var.mappedName = "gl_FragData";
+ var.arraySizes.push_back(maxDrawBuffers);
+ ASSERT(var.arraySizes.size() == 1u);
+ }
+ }
+ }
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.h b/src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.h
new file mode 100644
index 0000000000..e652b7e07e
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/EmulateGLFragColorBroadcast.h
@@ -0,0 +1,31 @@
+//
+// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Emulate gl_FragColor broadcast behaviors in ES2 where
+// GL_EXT_draw_buffers is explicitly enabled in a fragment shader.
+//
+
+#ifndef COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_
+#define COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_
+
+#include <vector>
+
+namespace sh
+{
+struct OutputVariable;
+class TIntermBlock;
+class TSymbolTable;
+
+// Replace all gl_FragColor with gl_FragData[0], and in the end of main() function,
+// assign gl_FragData[1] ... gl_FragData[maxDrawBuffers - 1] with gl_FragData[0].
+// If gl_FragColor is in outputVariables, it is replaced by gl_FragData.
+void EmulateGLFragColorBroadcast(TIntermBlock *root,
+ int maxDrawBuffers,
+ std::vector<OutputVariable> *outputVariables,
+ TSymbolTable *symbolTable,
+ int shaderVersion);
+}
+
+#endif // COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp b/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp
index 4a7fa54155..ba09fd77df 100644
--- a/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp
@@ -6,88 +6,206 @@
#include "compiler/translator/EmulatePrecision.h"
-namespace
-{
+#include <memory>
-static void writeVectorPrecisionEmulationHelpers(
- TInfoSinkBase& sink, ShShaderOutput outputLanguage, unsigned int size)
+namespace sh
{
- std::stringstream vecTypeStrStr;
- if (outputLanguage == SH_ESSL_OUTPUT)
- vecTypeStrStr << "highp ";
- vecTypeStrStr << "vec" << size;
- std::string vecType = vecTypeStrStr.str();
- sink <<
- vecType << " angle_frm(in " << vecType << " v) {\n"
- " v = clamp(v, -65504.0, 65504.0);\n"
- " " << vecType << " exponent = floor(log2(abs(v) + 1e-30)) - 10.0;\n"
- " bvec" << size << " isNonZero = greaterThanEqual(exponent, vec" << size << "(-25.0));\n"
- " v = v * exp2(-exponent);\n"
- " v = sign(v) * floor(abs(v));\n"
- " return v * exp2(exponent) * vec" << size << "(isNonZero);\n"
- "}\n";
+namespace
+{
- sink <<
- vecType << " angle_frl(in " << vecType << " v) {\n"
- " v = clamp(v, -2.0, 2.0);\n"
- " v = v * 256.0;\n"
- " v = sign(v) * floor(abs(v));\n"
- " return v * 0.00390625;\n"
- "}\n";
-}
+class RoundingHelperWriter : angle::NonCopyable
+{
+ public:
+ static RoundingHelperWriter *createHelperWriter(const ShShaderOutput outputLanguage);
+
+ void writeCommonRoundingHelpers(TInfoSinkBase &sink, const int shaderVersion);
+ void writeCompoundAssignmentHelper(TInfoSinkBase &sink,
+ const char *lType,
+ const char *rType,
+ const char *opStr,
+ const char *opNameStr);
+
+ virtual ~RoundingHelperWriter() {}
+
+ protected:
+ RoundingHelperWriter(const ShShaderOutput outputLanguage) : mOutputLanguage(outputLanguage) {}
+ RoundingHelperWriter() = delete;
+
+ const ShShaderOutput mOutputLanguage;
+
+ private:
+ virtual std::string getTypeString(const char *glslType) = 0;
+ virtual void writeFloatRoundingHelpers(TInfoSinkBase &sink) = 0;
+ virtual void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) = 0;
+ virtual void writeMatrixRoundingHelper(TInfoSinkBase &sink,
+ const unsigned int columns,
+ const unsigned int rows,
+ const char *functionName) = 0;
+};
+
+class RoundingHelperWriterGLSL : public RoundingHelperWriter
+{
+ public:
+ RoundingHelperWriterGLSL(const ShShaderOutput outputLanguage)
+ : RoundingHelperWriter(outputLanguage)
+ {
+ }
-static void writeMatrixPrecisionEmulationHelper(
- TInfoSinkBase& sink, ShShaderOutput outputLanguage, unsigned int size, const char *functionName)
+ private:
+ std::string getTypeString(const char *glslType) override;
+ void writeFloatRoundingHelpers(TInfoSinkBase &sink) override;
+ void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) override;
+ void writeMatrixRoundingHelper(TInfoSinkBase &sink,
+ const unsigned int columns,
+ const unsigned int rows,
+ const char *functionName) override;
+};
+
+class RoundingHelperWriterESSL : public RoundingHelperWriterGLSL
{
- std::stringstream matTypeStrStr;
- if (outputLanguage == SH_ESSL_OUTPUT)
- matTypeStrStr << "highp ";
- matTypeStrStr << "mat" << size;
- std::string matType = matTypeStrStr.str();
+ public:
+ RoundingHelperWriterESSL(const ShShaderOutput outputLanguage)
+ : RoundingHelperWriterGLSL(outputLanguage)
+ {
+ }
- sink << matType << " " << functionName << "(in " << matType << " m) {\n"
- " " << matType << " rounded;\n";
+ private:
+ std::string getTypeString(const char *glslType) override;
+};
- for (unsigned int i = 0; i < size; ++i)
+class RoundingHelperWriterHLSL : public RoundingHelperWriter
+{
+ public:
+ RoundingHelperWriterHLSL(const ShShaderOutput outputLanguage)
+ : RoundingHelperWriter(outputLanguage)
{
- sink << " rounded[" << i << "] = " << functionName << "(m[" << i << "]);\n";
}
- sink << " return rounded;\n"
- "}\n";
+ private:
+ std::string getTypeString(const char *glslType) override;
+ void writeFloatRoundingHelpers(TInfoSinkBase &sink) override;
+ void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) override;
+ void writeMatrixRoundingHelper(TInfoSinkBase &sink,
+ const unsigned int columns,
+ const unsigned int rows,
+ const char *functionName) override;
+};
+
+RoundingHelperWriter *RoundingHelperWriter::createHelperWriter(const ShShaderOutput outputLanguage)
+{
+ ASSERT(EmulatePrecision::SupportedInLanguage(outputLanguage));
+ switch (outputLanguage)
+ {
+ case SH_HLSL_4_1_OUTPUT:
+ return new RoundingHelperWriterHLSL(outputLanguage);
+ case SH_ESSL_OUTPUT:
+ return new RoundingHelperWriterESSL(outputLanguage);
+ default:
+ return new RoundingHelperWriterGLSL(outputLanguage);
+ }
}
-static void writeCommonPrecisionEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput outputLanguage)
+void RoundingHelperWriter::writeCommonRoundingHelpers(TInfoSinkBase &sink, const int shaderVersion)
{
// Write the angle_frm functions that round floating point numbers to
// half precision, and angle_frl functions that round them to minimum lowp
// precision.
+ writeFloatRoundingHelpers(sink);
+ writeVectorRoundingHelpers(sink, 2);
+ writeVectorRoundingHelpers(sink, 3);
+ writeVectorRoundingHelpers(sink, 4);
+ if (shaderVersion > 100)
+ {
+ for (unsigned int columns = 2; columns <= 4; ++columns)
+ {
+ for (unsigned int rows = 2; rows <= 4; ++rows)
+ {
+ writeMatrixRoundingHelper(sink, columns, rows, "angle_frm");
+ writeMatrixRoundingHelper(sink, columns, rows, "angle_frl");
+ }
+ }
+ }
+ else
+ {
+ for (unsigned int size = 2; size <= 4; ++size)
+ {
+ writeMatrixRoundingHelper(sink, size, size, "angle_frm");
+ writeMatrixRoundingHelper(sink, size, size, "angle_frl");
+ }
+ }
+}
+
+void RoundingHelperWriter::writeCompoundAssignmentHelper(TInfoSinkBase &sink,
+ const char *lType,
+ const char *rType,
+ const char *opStr,
+ const char *opNameStr)
+{
+ std::string lTypeStr = getTypeString(lType);
+ std::string rTypeStr = getTypeString(rType);
+
+ // Note that y should be passed through angle_frm at the function call site,
+ // but x can't be passed through angle_frm there since it is an inout parameter.
+ // So only pass x and the result through angle_frm here.
+ // clang-format off
+ sink <<
+ lTypeStr << " angle_compound_" << opNameStr << "_frm(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n"
+ " x = angle_frm(angle_frm(x) " << opStr << " y);\n"
+ " return x;\n"
+ "}\n";
+ sink <<
+ lTypeStr << " angle_compound_" << opNameStr << "_frl(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n"
+ " x = angle_frl(angle_frl(x) " << opStr << " y);\n"
+ " return x;\n"
+ "}\n";
+ // clang-format on
+}
+
+std::string RoundingHelperWriterGLSL::getTypeString(const char *glslType)
+{
+ return glslType;
+}
+
+std::string RoundingHelperWriterESSL::getTypeString(const char *glslType)
+{
+ std::stringstream typeStrStr;
+ typeStrStr << "highp " << glslType;
+ return typeStrStr.str();
+}
+
+void RoundingHelperWriterGLSL::writeFloatRoundingHelpers(TInfoSinkBase &sink)
+{
// Unoptimized version of angle_frm for single floats:
//
- // int webgl_maxNormalExponent(in int exponentBits) {
+ // int webgl_maxNormalExponent(in int exponentBits)
+ // {
// int possibleExponents = int(exp2(float(exponentBits)));
// int exponentBias = possibleExponents / 2 - 1;
// int allExponentBitsOne = possibleExponents - 1;
// return (allExponentBitsOne - 1) - exponentBias;
// }
//
- // float angle_frm(in float x) {
+ // float angle_frm(in float x)
+ // {
// int mantissaBits = 10;
// int exponentBits = 5;
// float possibleMantissas = exp2(float(mantissaBits));
// float mantissaMax = 2.0 - 1.0 / possibleMantissas;
// int maxNE = webgl_maxNormalExponent(exponentBits);
// float max = exp2(float(maxNE)) * mantissaMax;
- // if (x > max) {
+ // if (x > max)
+ // {
// return max;
// }
- // if (x < -max) {
+ // if (x < -max)
+ // {
// return -max;
// }
// float exponent = floor(log2(abs(x)));
- // if (abs(x) == 0.0 || exponent < -float(maxNE)) {
+ // if (abs(x) == 0.0 || exponent < -float(maxNE))
+ // {
// return 0.0 * sign(x)
// }
// x = x * exp2(-(exponent - float(mantissaBits)));
@@ -109,140 +227,215 @@ static void writeCommonPrecisionEmulationHelpers(TInfoSinkBase& sink, ShShaderOu
// numbers will be flushed to zero either way (2^-15 is the smallest
// normal positive number), this does not introduce any error.
- std::string floatType = "float";
- if (outputLanguage == SH_ESSL_OUTPUT)
- floatType = "highp float";
+ std::string floatType = getTypeString("float");
+
+ // clang-format off
+ sink <<
+ floatType << " angle_frm(in " << floatType << " x) {\n"
+ " x = clamp(x, -65504.0, 65504.0);\n"
+ " " << floatType << " exponent = floor(log2(abs(x) + 1e-30)) - 10.0;\n"
+ " bool isNonZero = (exponent >= -25.0);\n"
+ " x = x * exp2(-exponent);\n"
+ " x = sign(x) * floor(abs(x));\n"
+ " return x * exp2(exponent) * float(isNonZero);\n"
+ "}\n";
+
+ sink <<
+ floatType << " angle_frl(in " << floatType << " x) {\n"
+ " x = clamp(x, -2.0, 2.0);\n"
+ " x = x * 256.0;\n"
+ " x = sign(x) * floor(abs(x));\n"
+ " return x * 0.00390625;\n"
+ "}\n";
+ // clang-format on
+}
+
+void RoundingHelperWriterGLSL::writeVectorRoundingHelpers(TInfoSinkBase &sink,
+ const unsigned int size)
+{
+ std::stringstream vecTypeStrStr;
+ vecTypeStrStr << "vec" << size;
+ std::string vecType = getTypeString(vecTypeStrStr.str().c_str());
+ // clang-format off
sink <<
- floatType << " angle_frm(in " << floatType << " x) {\n"
- " x = clamp(x, -65504.0, 65504.0);\n"
- " " << floatType << " exponent = floor(log2(abs(x) + 1e-30)) - 10.0;\n"
- " bool isNonZero = (exponent >= -25.0);\n"
- " x = x * exp2(-exponent);\n"
- " x = sign(x) * floor(abs(x));\n"
- " return x * exp2(exponent) * float(isNonZero);\n"
- "}\n";
+ vecType << " angle_frm(in " << vecType << " v) {\n"
+ " v = clamp(v, -65504.0, 65504.0);\n"
+ " " << vecType << " exponent = floor(log2(abs(v) + 1e-30)) - 10.0;\n"
+ " bvec" << size << " isNonZero = greaterThanEqual(exponent, vec" << size << "(-25.0));\n"
+ " v = v * exp2(-exponent);\n"
+ " v = sign(v) * floor(abs(v));\n"
+ " return v * exp2(exponent) * vec" << size << "(isNonZero);\n"
+ "}\n";
sink <<
- floatType << " angle_frl(in " << floatType << " x) {\n"
- " x = clamp(x, -2.0, 2.0);\n"
- " x = x * 256.0;\n"
- " x = sign(x) * floor(abs(x));\n"
- " return x * 0.00390625;\n"
- "}\n";
+ vecType << " angle_frl(in " << vecType << " v) {\n"
+ " v = clamp(v, -2.0, 2.0);\n"
+ " v = v * 256.0;\n"
+ " v = sign(v) * floor(abs(v));\n"
+ " return v * 0.00390625;\n"
+ "}\n";
+ // clang-format on
+}
- writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 2);
- writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 3);
- writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 4);
- for (unsigned int size = 2; size <= 4; ++size)
+void RoundingHelperWriterGLSL::writeMatrixRoundingHelper(TInfoSinkBase &sink,
+ const unsigned int columns,
+ const unsigned int rows,
+ const char *functionName)
+{
+ std::stringstream matTypeStrStr;
+ matTypeStrStr << "mat" << columns;
+ if (rows != columns)
{
- writeMatrixPrecisionEmulationHelper(sink, outputLanguage, size, "angle_frm");
- writeMatrixPrecisionEmulationHelper(sink, outputLanguage, size, "angle_frl");
+ matTypeStrStr << "x" << rows;
+ }
+ std::string matType = getTypeString(matTypeStrStr.str().c_str());
+
+ sink << matType << " " << functionName << "(in " << matType << " m) {\n"
+ << " " << matType << " rounded;\n";
+
+ for (unsigned int i = 0; i < columns; ++i)
+ {
+ sink << " rounded[" << i << "] = " << functionName << "(m[" << i << "]);\n";
}
+
+ sink << " return rounded;\n"
+ "}\n";
}
-static void writeCompoundAssignmentPrecisionEmulation(
- TInfoSinkBase& sink, ShShaderOutput outputLanguage,
- const char *lType, const char *rType, const char *opStr, const char *opNameStr)
+static const char *GetHLSLTypeStr(const char *floatTypeStr)
{
- std::string lTypeStr = lType;
- std::string rTypeStr = rType;
- if (outputLanguage == SH_ESSL_OUTPUT)
+ if (strcmp(floatTypeStr, "float") == 0)
+ {
+ return "float";
+ }
+ if (strcmp(floatTypeStr, "vec2") == 0)
+ {
+ return "float2";
+ }
+ if (strcmp(floatTypeStr, "vec3") == 0)
+ {
+ return "float3";
+ }
+ if (strcmp(floatTypeStr, "vec4") == 0)
+ {
+ return "float4";
+ }
+ if (strcmp(floatTypeStr, "mat2") == 0)
+ {
+ return "float2x2";
+ }
+ if (strcmp(floatTypeStr, "mat3") == 0)
{
- std::stringstream lTypeStrStr;
- lTypeStrStr << "highp " << lType;
- lTypeStr = lTypeStrStr.str();
- std::stringstream rTypeStrStr;
- rTypeStrStr << "highp " << rType;
- rTypeStr = rTypeStrStr.str();
+ return "float3x3";
}
+ if (strcmp(floatTypeStr, "mat4") == 0)
+ {
+ return "float4x4";
+ }
+ if (strcmp(floatTypeStr, "mat2x3") == 0)
+ {
+ return "float2x3";
+ }
+ if (strcmp(floatTypeStr, "mat2x4") == 0)
+ {
+ return "float2x4";
+ }
+ if (strcmp(floatTypeStr, "mat3x2") == 0)
+ {
+ return "float3x2";
+ }
+ if (strcmp(floatTypeStr, "mat3x4") == 0)
+ {
+ return "float3x4";
+ }
+ if (strcmp(floatTypeStr, "mat4x2") == 0)
+ {
+ return "float4x2";
+ }
+ if (strcmp(floatTypeStr, "mat4x3") == 0)
+ {
+ return "float4x3";
+ }
+ UNREACHABLE();
+ return nullptr;
+}
- // Note that y should be passed through angle_frm at the function call site,
- // but x can't be passed through angle_frm there since it is an inout parameter.
- // So only pass x and the result through angle_frm here.
+std::string RoundingHelperWriterHLSL::getTypeString(const char *glslType)
+{
+ return GetHLSLTypeStr(glslType);
+}
+
+void RoundingHelperWriterHLSL::writeFloatRoundingHelpers(TInfoSinkBase &sink)
+{
+ // In HLSL scalars are the same as 1-vectors.
+ writeVectorRoundingHelpers(sink, 1);
+}
+
+void RoundingHelperWriterHLSL::writeVectorRoundingHelpers(TInfoSinkBase &sink,
+ const unsigned int size)
+{
+ std::stringstream vecTypeStrStr;
+ vecTypeStrStr << "float" << size;
+ std::string vecType = vecTypeStrStr.str();
+
+ // clang-format off
sink <<
- lTypeStr << " angle_compound_" << opNameStr << "_frm(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n"
- " x = angle_frm(angle_frm(x) " << opStr << " y);\n"
- " return x;\n"
- "}\n";
+ vecType << " angle_frm(" << vecType << " v) {\n"
+ " v = clamp(v, -65504.0, 65504.0);\n"
+ " " << vecType << " exponent = floor(log2(abs(v) + 1e-30)) - 10.0;\n"
+ " bool" << size << " isNonZero = exponent < -25.0;\n"
+ " v = v * exp2(-exponent);\n"
+ " v = sign(v) * floor(abs(v));\n"
+ " return v * exp2(exponent) * (float" << size << ")(isNonZero);\n"
+ "}\n";
+
sink <<
- lTypeStr << " angle_compound_" << opNameStr << "_frl(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n"
- " x = angle_frl(angle_frm(x) " << opStr << " y);\n"
- " return x;\n"
- "}\n";
+ vecType << " angle_frl(" << vecType << " v) {\n"
+ " v = clamp(v, -2.0, 2.0);\n"
+ " v = v * 256.0;\n"
+ " v = sign(v) * floor(abs(v));\n"
+ " return v * 0.00390625;\n"
+ "}\n";
+ // clang-format on
}
-const char *getFloatTypeStr(const TType& type)
+void RoundingHelperWriterHLSL::writeMatrixRoundingHelper(TInfoSinkBase &sink,
+ const unsigned int columns,
+ const unsigned int rows,
+ const char *functionName)
{
- switch (type.getNominalSize())
+ std::stringstream matTypeStrStr;
+ matTypeStrStr << "float" << columns << "x" << rows;
+ std::string matType = matTypeStrStr.str();
+
+ sink << matType << " " << functionName << "(" << matType << " m) {\n"
+ << " " << matType << " rounded;\n";
+
+ for (unsigned int i = 0; i < columns; ++i)
{
- case 1:
- return "float";
- case 2:
- switch(type.getSecondarySize())
- {
- case 1:
- return "vec2";
- case 2:
- return "mat2";
- case 3:
- return "mat2x3";
- case 4:
- return "mat2x4";
- default:
- UNREACHABLE();
- return NULL;
- }
- case 3:
- switch(type.getSecondarySize())
- {
- case 1:
- return "vec3";
- case 2:
- return "mat3x2";
- case 3:
- return "mat3";
- case 4:
- return "mat3x4";
- default:
- UNREACHABLE();
- return NULL;
- }
- case 4:
- switch(type.getSecondarySize())
- {
- case 1:
- return "vec4";
- case 2:
- return "mat4x2";
- case 3:
- return "mat4x3";
- case 4:
- return "mat4";
- default:
- UNREACHABLE();
- return NULL;
- }
- default:
- UNREACHABLE();
- return NULL;
+ sink << " rounded[" << i << "] = " << functionName << "(m[" << i << "]);\n";
}
+
+ sink << " return rounded;\n"
+ "}\n";
}
bool canRoundFloat(const TType &type)
{
- return type.getBasicType() == EbtFloat && !type.isNonSquareMatrix() && !type.isArray() &&
- (type.getPrecision() == EbpLow || type.getPrecision() == EbpMedium);
+ return type.getBasicType() == EbtFloat && !type.isArray() &&
+ (type.getPrecision() == EbpLow || type.getPrecision() == EbpMedium);
}
-TIntermAggregate *createInternalFunctionCallNode(TString name, TIntermNode *child)
+TIntermAggregate *createInternalFunctionCallNode(const TType &type,
+ TString name,
+ TIntermSequence *arguments)
{
- TIntermAggregate *callNode = new TIntermAggregate();
- callNode->setOp(EOpFunctionCall);
- TName nameObj(TFunction::mangleName(name));
+ TName nameObj(name);
nameObj.setInternal(true);
- callNode->setNameObj(nameObj);
- callNode->getSequence()->push_back(child);
+ TIntermAggregate *callNode =
+ TIntermAggregate::Create(type, EOpCallInternalRawFunction, arguments);
+ callNode->getFunctionSymbolInfo()->setNameObj(nameObj);
return callNode;
}
@@ -252,63 +445,92 @@ TIntermAggregate *createRoundingFunctionCallNode(TIntermTyped *roundedChild)
if (roundedChild->getPrecision() == EbpMedium)
roundFunctionName = "angle_frm";
else
- roundFunctionName = "angle_frl";
- return createInternalFunctionCallNode(roundFunctionName, roundedChild);
+ roundFunctionName = "angle_frl";
+ TIntermSequence *arguments = new TIntermSequence();
+ arguments->push_back(roundedChild);
+ TIntermAggregate *callNode =
+ createInternalFunctionCallNode(roundedChild->getType(), roundFunctionName, arguments);
+ callNode->getFunctionSymbolInfo()->setKnownToNotHaveSideEffects(true);
+ return callNode;
}
-TIntermAggregate *createCompoundAssignmentFunctionCallNode(TIntermTyped *left, TIntermTyped *right, const char *opNameStr)
+TIntermAggregate *createCompoundAssignmentFunctionCallNode(TIntermTyped *left,
+ TIntermTyped *right,
+ const char *opNameStr)
{
std::stringstream strstr;
if (left->getPrecision() == EbpMedium)
strstr << "angle_compound_" << opNameStr << "_frm";
else
strstr << "angle_compound_" << opNameStr << "_frl";
- TString functionName = strstr.str().c_str();
- TIntermAggregate *callNode = createInternalFunctionCallNode(functionName, left);
- callNode->getSequence()->push_back(right);
- return callNode;
+ TString functionName = strstr.str().c_str();
+ TIntermSequence *arguments = new TIntermSequence();
+ arguments->push_back(left);
+ arguments->push_back(right);
+ return createInternalFunctionCallNode(left->getType(), functionName, arguments);
}
-bool parentUsesResult(TIntermNode* parent, TIntermNode* node)
+bool ParentUsesResult(TIntermNode *parent, TIntermTyped *node)
{
if (!parent)
{
return false;
}
- TIntermAggregate *aggParent = parent->getAsAggregate();
- // If the parent's op is EOpSequence, the result is not assigned anywhere,
+ TIntermBlock *blockParent = parent->getAsBlock();
+ // If the parent is a block, the result is not assigned anywhere,
// so rounding it is not needed. In particular, this can avoid a lot of
// unnecessary rounding of unused return values of assignment.
- if (aggParent && aggParent->getOp() == EOpSequence)
+ if (blockParent)
{
return false;
}
- if (aggParent && aggParent->getOp() == EOpComma && (aggParent->getSequence()->back() != node))
+ TIntermBinary *binaryParent = parent->getAsBinaryNode();
+ if (binaryParent && binaryParent->getOp() == EOpComma && (binaryParent->getRight() != node))
{
return false;
}
return true;
}
+bool ParentConstructorTakesCareOfRounding(TIntermNode *parent, TIntermTyped *node)
+{
+ if (!parent)
+ {
+ return false;
+ }
+ TIntermAggregate *parentConstructor = parent->getAsAggregate();
+ if (!parentConstructor || parentConstructor->getOp() != EOpConstruct)
+ {
+ return false;
+ }
+ if (parentConstructor->getPrecision() != node->getPrecision())
+ {
+ return false;
+ }
+ return canRoundFloat(parentConstructor->getType());
+}
+
} // namespace anonymous
-EmulatePrecision::EmulatePrecision(const TSymbolTable &symbolTable, int shaderVersion)
+EmulatePrecision::EmulatePrecision(TSymbolTable *symbolTable, int shaderVersion)
: TLValueTrackingTraverser(true, true, true, symbolTable, shaderVersion),
mDeclaringVariables(false)
-{}
+{
+}
void EmulatePrecision::visitSymbol(TIntermSymbol *node)
{
- if (canRoundFloat(node->getType()) && !mDeclaringVariables && !isLValueRequiredHere())
+ TIntermNode *parent = getParentNode();
+ if (canRoundFloat(node->getType()) && ParentUsesResult(parent, node) &&
+ !ParentConstructorTakesCareOfRounding(parent, node) && !mDeclaringVariables &&
+ !isLValueRequiredHere())
{
- TIntermNode *parent = getParentNode();
TIntermNode *replacement = createRoundingFunctionCallNode(node);
- mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
+ queueReplacement(replacement, OriginalNode::BECOMES_CHILD);
}
}
-
bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node)
{
bool visitChildren = true;
@@ -319,189 +541,211 @@ bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node)
if (op == EOpInitialize && visit == InVisit)
mDeclaringVariables = false;
- if ((op == EOpIndexDirectStruct || op == EOpVectorSwizzle) && visit == InVisit)
+ if ((op == EOpIndexDirectStruct) && visit == InVisit)
visitChildren = false;
if (visit != PreVisit)
return visitChildren;
- const TType& type = node->getType();
- bool roundFloat = canRoundFloat(type);
-
- if (roundFloat) {
- switch (op) {
- // Math operators that can result in a float may need to apply rounding to the return
- // value. Note that in the case of assignment, the rounding is applied to its return
- // value here, not the value being assigned.
- case EOpAssign:
- case EOpAdd:
- case EOpSub:
- case EOpMul:
- case EOpDiv:
- case EOpVectorTimesScalar:
- case EOpVectorTimesMatrix:
- case EOpMatrixTimesVector:
- case EOpMatrixTimesScalar:
- case EOpMatrixTimesMatrix:
- {
- TIntermNode *parent = getParentNode();
- if (!parentUsesResult(parent, node))
+ const TType &type = node->getType();
+ bool roundFloat = canRoundFloat(type);
+
+ if (roundFloat)
+ {
+ switch (op)
+ {
+ // Math operators that can result in a float may need to apply rounding to the return
+ // value. Note that in the case of assignment, the rounding is applied to its return
+ // value here, not the value being assigned.
+ case EOpAssign:
+ case EOpAdd:
+ case EOpSub:
+ case EOpMul:
+ case EOpDiv:
+ case EOpVectorTimesScalar:
+ case EOpVectorTimesMatrix:
+ case EOpMatrixTimesVector:
+ case EOpMatrixTimesScalar:
+ case EOpMatrixTimesMatrix:
{
+ TIntermNode *parent = getParentNode();
+ if (!ParentUsesResult(parent, node) ||
+ ParentConstructorTakesCareOfRounding(parent, node))
+ {
+ break;
+ }
+ TIntermNode *replacement = createRoundingFunctionCallNode(node);
+ queueReplacement(replacement, OriginalNode::BECOMES_CHILD);
break;
}
- TIntermNode *replacement = createRoundingFunctionCallNode(node);
- mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
- break;
- }
- // Compound assignment cases need to replace the operator with a function call.
- case EOpAddAssign:
- {
- mEmulateCompoundAdd.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType())));
- TIntermNode *parent = getParentNode();
- TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "add");
- mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false));
- break;
- }
- case EOpSubAssign:
- {
- mEmulateCompoundSub.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType())));
- TIntermNode *parent = getParentNode();
- TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "sub");
- mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false));
- break;
- }
- case EOpMulAssign:
- case EOpVectorTimesMatrixAssign:
- case EOpVectorTimesScalarAssign:
- case EOpMatrixTimesScalarAssign:
- case EOpMatrixTimesMatrixAssign:
- {
- mEmulateCompoundMul.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType())));
- TIntermNode *parent = getParentNode();
- TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "mul");
- mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false));
- break;
- }
- case EOpDivAssign:
- {
- mEmulateCompoundDiv.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType())));
- TIntermNode *parent = getParentNode();
- TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "div");
- mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false));
- break;
- }
- default:
- // The rest of the binary operations should not need precision emulation.
- break;
+ // Compound assignment cases need to replace the operator with a function call.
+ case EOpAddAssign:
+ {
+ mEmulateCompoundAdd.insert(
+ TypePair(type.getBuiltInTypeNameString(),
+ node->getRight()->getType().getBuiltInTypeNameString()));
+ TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(
+ node->getLeft(), node->getRight(), "add");
+ queueReplacement(replacement, OriginalNode::IS_DROPPED);
+ break;
+ }
+ case EOpSubAssign:
+ {
+ mEmulateCompoundSub.insert(
+ TypePair(type.getBuiltInTypeNameString(),
+ node->getRight()->getType().getBuiltInTypeNameString()));
+ TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(
+ node->getLeft(), node->getRight(), "sub");
+ queueReplacement(replacement, OriginalNode::IS_DROPPED);
+ break;
+ }
+ case EOpMulAssign:
+ case EOpVectorTimesMatrixAssign:
+ case EOpVectorTimesScalarAssign:
+ case EOpMatrixTimesScalarAssign:
+ case EOpMatrixTimesMatrixAssign:
+ {
+ mEmulateCompoundMul.insert(
+ TypePair(type.getBuiltInTypeNameString(),
+ node->getRight()->getType().getBuiltInTypeNameString()));
+ TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(
+ node->getLeft(), node->getRight(), "mul");
+ queueReplacement(replacement, OriginalNode::IS_DROPPED);
+ break;
+ }
+ case EOpDivAssign:
+ {
+ mEmulateCompoundDiv.insert(
+ TypePair(type.getBuiltInTypeNameString(),
+ node->getRight()->getType().getBuiltInTypeNameString()));
+ TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(
+ node->getLeft(), node->getRight(), "div");
+ queueReplacement(replacement, OriginalNode::IS_DROPPED);
+ break;
+ }
+ default:
+ // The rest of the binary operations should not need precision emulation.
+ break;
}
}
return visitChildren;
}
+bool EmulatePrecision::visitDeclaration(Visit visit, TIntermDeclaration *node)
+{
+ // Variable or interface block declaration.
+ if (visit == PreVisit)
+ {
+ mDeclaringVariables = true;
+ }
+ else if (visit == InVisit)
+ {
+ mDeclaringVariables = true;
+ }
+ else
+ {
+ mDeclaringVariables = false;
+ }
+ return true;
+}
+
+bool EmulatePrecision::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node)
+{
+ return false;
+}
+
+bool EmulatePrecision::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node)
+{
+ return false;
+}
+
bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node)
{
- bool visitChildren = true;
+ if (visit != PreVisit)
+ return true;
switch (node->getOp())
{
- case EOpSequence:
- case EOpConstructStruct:
- case EOpFunction:
- break;
- case EOpPrototype:
- visitChildren = false;
- break;
- case EOpParameters:
- visitChildren = false;
- break;
- case EOpInvariantDeclaration:
- visitChildren = false;
- break;
- case EOpDeclaration:
- // Variable declaration.
- if (visit == PreVisit)
- {
- mDeclaringVariables = true;
- }
- else if (visit == InVisit)
- {
- mDeclaringVariables = true;
- }
- else
- {
- mDeclaringVariables = false;
- }
- break;
- case EOpFunctionCall:
- {
- // Function call.
- if (visit == PreVisit)
- {
- // User-defined function return values are not rounded, this relies on that
- // calculations producing the value were rounded.
+ case EOpCallInternalRawFunction:
+ case EOpCallFunctionInAST:
+ // User-defined function return values are not rounded. The calculations that produced
+ // the value inside the function definition should have been rounded.
+ break;
+ case EOpConstruct:
+ if (node->getBasicType() == EbtStruct)
+ {
+ break;
+ }
+ default:
TIntermNode *parent = getParentNode();
- if (canRoundFloat(node->getType()) && !isInFunctionMap(node) &&
- parentUsesResult(parent, node))
+ if (canRoundFloat(node->getType()) && ParentUsesResult(parent, node) &&
+ !ParentConstructorTakesCareOfRounding(parent, node))
{
TIntermNode *replacement = createRoundingFunctionCallNode(node);
- mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
+ queueReplacement(replacement, OriginalNode::BECOMES_CHILD);
}
- }
- break;
- }
- default:
- TIntermNode *parent = getParentNode();
- if (canRoundFloat(node->getType()) && visit == PreVisit && parentUsesResult(parent, node))
- {
- TIntermNode *replacement = createRoundingFunctionCallNode(node);
- mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
- }
- break;
+ break;
}
- return visitChildren;
+ return true;
}
bool EmulatePrecision::visitUnary(Visit visit, TIntermUnary *node)
{
switch (node->getOp())
{
- case EOpNegative:
- case EOpVectorLogicalNot:
- case EOpLogicalNot:
- case EOpPostIncrement:
- case EOpPostDecrement:
- case EOpPreIncrement:
- case EOpPreDecrement:
- break;
- default:
- if (canRoundFloat(node->getType()) && visit == PreVisit)
- {
- TIntermNode *parent = getParentNode();
- TIntermNode *replacement = createRoundingFunctionCallNode(node);
- mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
- }
- break;
+ case EOpNegative:
+ case EOpLogicalNot:
+ case EOpPostIncrement:
+ case EOpPostDecrement:
+ case EOpPreIncrement:
+ case EOpPreDecrement:
+ case EOpLogicalNotComponentWise:
+ break;
+ default:
+ if (canRoundFloat(node->getType()) && visit == PreVisit)
+ {
+ TIntermNode *replacement = createRoundingFunctionCallNode(node);
+ queueReplacement(replacement, OriginalNode::BECOMES_CHILD);
+ }
+ break;
}
return true;
}
-void EmulatePrecision::writeEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput outputLanguage)
+void EmulatePrecision::writeEmulationHelpers(TInfoSinkBase &sink,
+ const int shaderVersion,
+ const ShShaderOutput outputLanguage)
{
- // Other languages not yet supported
- ASSERT(outputLanguage == SH_GLSL_COMPATIBILITY_OUTPUT ||
- IsGLSL130OrNewer(outputLanguage) ||
- outputLanguage == SH_ESSL_OUTPUT);
- writeCommonPrecisionEmulationHelpers(sink, outputLanguage);
+ std::unique_ptr<RoundingHelperWriter> roundingHelperWriter(
+ RoundingHelperWriter::createHelperWriter(outputLanguage));
+
+ roundingHelperWriter->writeCommonRoundingHelpers(sink, shaderVersion);
EmulationSet::const_iterator it;
for (it = mEmulateCompoundAdd.begin(); it != mEmulateCompoundAdd.end(); it++)
- writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "+", "add");
+ roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "+", "add");
for (it = mEmulateCompoundSub.begin(); it != mEmulateCompoundSub.end(); it++)
- writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "-", "sub");
+ roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "-", "sub");
for (it = mEmulateCompoundDiv.begin(); it != mEmulateCompoundDiv.end(); it++)
- writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "/", "div");
+ roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "/", "div");
for (it = mEmulateCompoundMul.begin(); it != mEmulateCompoundMul.end(); it++)
- writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "*", "mul");
+ roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "*", "mul");
+}
+
+// static
+bool EmulatePrecision::SupportedInLanguage(const ShShaderOutput outputLanguage)
+{
+ switch (outputLanguage)
+ {
+ case SH_HLSL_4_1_OUTPUT:
+ case SH_ESSL_OUTPUT:
+ return true;
+ default:
+ // Other languages not yet supported
+ return (outputLanguage == SH_GLSL_COMPATIBILITY_OUTPUT ||
+ sh::IsGLSL130OrNewer(outputLanguage));
+ }
}
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h b/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h
index 08177b3414..8044465410 100644
--- a/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h
+++ b/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h
@@ -7,34 +7,43 @@
#ifndef COMPILER_TRANSLATOR_EMULATE_PRECISION_H_
#define COMPILER_TRANSLATOR_EMULATE_PRECISION_H_
+#include "GLSLANG/ShaderLang.h"
#include "common/angleutils.h"
#include "compiler/translator/Compiler.h"
#include "compiler/translator/InfoSink.h"
-#include "compiler/translator/IntermNode.h"
-#include "GLSLANG/ShaderLang.h"
+#include "compiler/translator/IntermTraverse.h"
// This class gathers all compound assignments from the AST and can then write
// the functions required for their precision emulation. This way there is no
// need to write a huge number of variations of the emulated compound assignment
// to every translated shader with emulation enabled.
+namespace sh
+{
+
class EmulatePrecision : public TLValueTrackingTraverser
{
public:
- EmulatePrecision(const TSymbolTable &symbolTable, int shaderVersion);
+ EmulatePrecision(TSymbolTable *symbolTable, int shaderVersion);
void visitSymbol(TIntermSymbol *node) override;
bool visitBinary(Visit visit, TIntermBinary *node) override;
bool visitUnary(Visit visit, TIntermUnary *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
+ bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override;
+ bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
+ bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override;
+
+ void writeEmulationHelpers(TInfoSinkBase &sink,
+ const int shaderVersion,
+ const ShShaderOutput outputLanguage);
- void writeEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput outputLanguage);
+ static bool SupportedInLanguage(const ShShaderOutput outputLanguage);
private:
struct TypePair
{
- TypePair(const char *l, const char *r)
- : lType(l), rType(r) { }
+ TypePair(const char *l, const char *r) : lType(l), rType(r) {}
const char *lType;
const char *rType;
@@ -42,7 +51,7 @@ class EmulatePrecision : public TLValueTrackingTraverser
struct TypePairComparator
{
- bool operator() (const TypePair& l, const TypePair& r) const
+ bool operator()(const TypePair &l, const TypePair &r) const
{
if (l.lType == r.lType)
return l.rType < r.rType;
@@ -59,4 +68,6 @@ class EmulatePrecision : public TLValueTrackingTraverser
bool mDeclaringVariables;
};
+} // namespace sh
+
#endif // COMPILER_TRANSLATOR_EMULATE_PRECISION_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.cpp b/src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.cpp
new file mode 100644
index 0000000000..f17dd73657
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.cpp
@@ -0,0 +1,153 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Implementation of the integer pow expressions HLSL bug workaround.
+// See header for more info.
+
+#include "compiler/translator/ExpandIntegerPowExpressions.h"
+
+#include <cmath>
+#include <cstdlib>
+
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class Traverser : public TIntermTraverser
+{
+ public:
+ static void Apply(TIntermNode *root, TSymbolTable *symbolTable);
+
+ private:
+ Traverser(TSymbolTable *symbolTable);
+ bool visitAggregate(Visit visit, TIntermAggregate *node) override;
+ void nextIteration();
+
+ bool mFound = false;
+};
+
+// static
+void Traverser::Apply(TIntermNode *root, TSymbolTable *symbolTable)
+{
+ Traverser traverser(symbolTable);
+ do
+ {
+ traverser.nextIteration();
+ root->traverse(&traverser);
+ if (traverser.mFound)
+ {
+ traverser.updateTree();
+ }
+ } while (traverser.mFound);
+}
+
+Traverser::Traverser(TSymbolTable *symbolTable) : TIntermTraverser(true, false, false, symbolTable)
+{
+}
+
+void Traverser::nextIteration()
+{
+ mFound = false;
+ nextTemporaryId();
+}
+
+bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+ if (mFound)
+ {
+ return false;
+ }
+
+ // Test 0: skip non-pow operators.
+ if (node->getOp() != EOpPow)
+ {
+ return true;
+ }
+
+ const TIntermSequence *sequence = node->getSequence();
+ ASSERT(sequence->size() == 2u);
+ const TIntermConstantUnion *constantNode = sequence->at(1)->getAsConstantUnion();
+
+ // Test 1: check for a single constant.
+ if (!constantNode || constantNode->getNominalSize() != 1)
+ {
+ return true;
+ }
+
+ const TConstantUnion *constant = constantNode->getUnionArrayPointer();
+
+ TConstantUnion asFloat;
+ asFloat.cast(EbtFloat, *constant);
+
+ float value = asFloat.getFConst();
+
+ // Test 2: value is in the problematic range.
+ if (value < -5.0f || value > 9.0f)
+ {
+ return true;
+ }
+
+ // Test 3: value is integer or pretty close to an integer.
+ float absval = std::abs(value);
+ float frac = absval - std::round(absval);
+ if (frac > 0.0001f)
+ {
+ return true;
+ }
+
+ // Test 4: skip -1, 0, and 1
+ int exponent = static_cast<int>(value);
+ int n = std::abs(exponent);
+ if (n < 2)
+ {
+ return true;
+ }
+
+ // Potential problem case detected, apply workaround.
+ nextTemporaryId();
+
+ TIntermTyped *lhs = sequence->at(0)->getAsTyped();
+ ASSERT(lhs);
+
+ TIntermDeclaration *init = createTempInitDeclaration(lhs);
+ TIntermTyped *current = createTempSymbol(lhs->getType());
+
+ insertStatementInParentBlock(init);
+
+ // Create a chain of n-1 multiples.
+ for (int i = 1; i < n; ++i)
+ {
+ TIntermBinary *mul = new TIntermBinary(EOpMul, current, createTempSymbol(lhs->getType()));
+ mul->setLine(node->getLine());
+ current = mul;
+ }
+
+ // For negative pow, compute the reciprocal of the positive pow.
+ if (exponent < 0)
+ {
+ TConstantUnion *oneVal = new TConstantUnion();
+ oneVal->setFConst(1.0f);
+ TIntermConstantUnion *oneNode = new TIntermConstantUnion(oneVal, node->getType());
+ TIntermBinary *div = new TIntermBinary(EOpDiv, oneNode, current);
+ current = div;
+ }
+
+ queueReplacement(current, OriginalNode::IS_DROPPED);
+ mFound = true;
+ return false;
+}
+
+} // anonymous namespace
+
+void ExpandIntegerPowExpressions(TIntermNode *root, TSymbolTable *symbolTable)
+{
+ Traverser::Apply(root, symbolTable);
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.h b/src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.h
new file mode 100644
index 0000000000..0074e5d663
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/ExpandIntegerPowExpressions.h
@@ -0,0 +1,29 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This mutating tree traversal works around a bug in the HLSL compiler optimizer with "pow" that
+// manifests under the following conditions:
+//
+// - If pow() has a literal exponent value
+// - ... and this value is integer or within 10e-6 of an integer
+// - ... and it is in {-4, -3, -2, 2, 3, 4, 5, 6, 7, 8}
+//
+// The workaround is to replace the pow with a series of multiplies.
+// See http://anglebug.com/851
+
+#ifndef COMPILER_TRANSLATOR_EXPANDINTEGERPOWEXPRESSIONS_H_
+#define COMPILER_TRANSLATOR_EXPANDINTEGERPOWEXPRESSIONS_H_
+
+namespace sh
+{
+
+class TIntermNode;
+class TSymbolTable;
+
+void ExpandIntegerPowExpressions(TIntermNode *root, TSymbolTable *symbolTable);
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_EXPANDINTEGERPOWEXPRESSIONS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.cpp b/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.cpp
new file mode 100644
index 0000000000..3f910b9050
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.cpp
@@ -0,0 +1,96 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ExtensionBehavior.cpp: Extension name enumeration and data structures for storing extension
+// behavior.
+
+#include "compiler/translator/ExtensionBehavior.h"
+
+#include "common/debug.h"
+
+#include <string.h>
+
+#define LIST_EXTENSIONS(OP) \
+ OP(ARB_texture_rectangle) \
+ OP(ARM_shader_framebuffer_fetch) \
+ OP(EXT_blend_func_extended) \
+ OP(EXT_draw_buffers) \
+ OP(EXT_frag_depth) \
+ OP(EXT_geometry_shader) \
+ OP(EXT_shader_framebuffer_fetch) \
+ OP(EXT_shader_texture_lod) \
+ OP(EXT_YUV_target) \
+ OP(NV_EGL_stream_consumer_external) \
+ OP(NV_shader_framebuffer_fetch) \
+ OP(OES_EGL_image_external) \
+ OP(OES_EGL_image_external_essl3) \
+ OP(OES_geometry_shader) \
+ OP(OES_standard_derivatives) \
+ OP(OVR_multiview)
+
+namespace sh
+{
+
+#define RETURN_EXTENSION_NAME_CASE(ext) \
+ case TExtension::ext: \
+ return "GL_" #ext;
+
+const char *GetExtensionNameString(TExtension extension)
+{
+ switch (extension)
+ {
+ LIST_EXTENSIONS(RETURN_EXTENSION_NAME_CASE)
+ default:
+ UNREACHABLE();
+ return "";
+ }
+}
+
+#define RETURN_EXTENSION_IF_NAME_MATCHES(ext) \
+ if (strcmp(extWithoutGLPrefix, #ext) == 0) \
+ { \
+ return TExtension::ext; \
+ }
+
+TExtension GetExtensionByName(const char *extension)
+{
+ // If first characters of the extension don't equal "GL_", early out.
+ if (strncmp(extension, "GL_", 3) != 0)
+ {
+ return TExtension::UNDEFINED;
+ }
+ const char *extWithoutGLPrefix = extension + 3;
+
+ LIST_EXTENSIONS(RETURN_EXTENSION_IF_NAME_MATCHES)
+
+ return TExtension::UNDEFINED;
+}
+
+const char *GetBehaviorString(TBehavior b)
+{
+ switch (b)
+ {
+ case EBhRequire:
+ return "require";
+ case EBhEnable:
+ return "enable";
+ case EBhWarn:
+ return "warn";
+ case EBhDisable:
+ return "disable";
+ default:
+ return nullptr;
+ }
+}
+
+bool IsExtensionEnabled(const TExtensionBehavior &extBehavior, TExtension extension)
+{
+ ASSERT(extension != TExtension::UNDEFINED);
+ auto iter = extBehavior.find(extension);
+ return iter != extBehavior.end() &&
+ (iter->second == EBhEnable || iter->second == EBhRequire || iter->second == EBhWarn);
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h b/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h
index 782c1c9217..09cc03f10f 100644
--- a/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h
+++ b/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h
@@ -3,41 +3,58 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
+// ExtensionBehavior.h: Extension name enumeration and data structures for storing extension
+// behavior.
#ifndef COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_
#define COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_
#include <map>
-#include <string>
-typedef enum
+namespace sh
+{
+
+enum class TExtension
+{
+ UNDEFINED, // Special value used to indicate no extension.
+
+ ARB_texture_rectangle,
+ ARM_shader_framebuffer_fetch,
+ EXT_blend_func_extended,
+ EXT_draw_buffers,
+ EXT_frag_depth,
+ EXT_geometry_shader,
+ EXT_shader_framebuffer_fetch,
+ EXT_shader_texture_lod,
+ EXT_YUV_target,
+ NV_EGL_stream_consumer_external,
+ NV_shader_framebuffer_fetch,
+ OES_EGL_image_external,
+ OES_EGL_image_external_essl3,
+ OES_geometry_shader,
+ OES_standard_derivatives,
+ OVR_multiview
+};
+
+enum TBehavior
{
EBhRequire,
EBhEnable,
EBhWarn,
EBhDisable,
EBhUndefined
-} TBehavior;
+};
-inline const char* getBehaviorString(TBehavior b)
-{
- switch(b)
- {
- case EBhRequire: return "require";
- case EBhEnable: return "enable";
- case EBhWarn: return "warn";
- case EBhDisable: return "disable";
- default: return NULL;
- }
-}
-
-// Mapping between extension name and behavior.
-typedef std::map<std::string, TBehavior> TExtensionBehavior;
-
-inline bool IsExtensionEnabled(const TExtensionBehavior &extBehavior, const char *extension)
-{
- auto iter = extBehavior.find(extension);
- return iter != extBehavior.end() && (iter->second == EBhEnable || iter->second == EBhRequire);
-}
+const char *GetExtensionNameString(TExtension extension);
+TExtension GetExtensionByName(const char *extension);
+
+const char *GetBehaviorString(TBehavior b);
+
+// Mapping between extension id and behavior.
+typedef std::map<TExtension, TBehavior> TExtensionBehavior;
+
+bool IsExtensionEnabled(const TExtensionBehavior &extBehavior, TExtension extension);
+
+} // namespace sh
-#endif // COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_
+#endif // COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.cpp
index d7f45f7eef..5b5dc580e9 100644
--- a/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.cpp
@@ -10,6 +10,9 @@
#include "compiler/translator/VersionGLSL.h"
+namespace sh
+{
+
TExtensionGLSL::TExtensionGLSL(ShShaderOutput output)
: TIntermTraverser(true, false, false), mTargetVersion(ShaderOutputTypeToGLSLVersion(output))
{
@@ -98,3 +101,5 @@ void TExtensionGLSL::checkOperator(TIntermOperator *node)
break;
}
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.h b/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.h
index 6bb84d612d..a1b9cb2225 100644
--- a/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/ExtensionGLSL.h
@@ -12,7 +12,10 @@
#include <set>
#include <string>
-#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
// Traverses the intermediate tree to determine which GLSL extensions are required
// to support the shader.
@@ -36,4 +39,6 @@ class TExtensionGLSL : public TIntermTraverser
std::set<std::string> mRequiredExtensions;
};
+} // namespace sh
+
#endif // COMPILER_TRANSLATOR_EXTENSIONGLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/FindMain.cpp b/src/3rdparty/angle/src/compiler/translator/FindMain.cpp
new file mode 100644
index 0000000000..7417fbac8a
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/FindMain.cpp
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FindMain.cpp: Find the main() function definition in a given AST.
+
+#include "compiler/translator/FindMain.h"
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+TIntermFunctionDefinition *FindMain(TIntermBlock *root)
+{
+ for (TIntermNode *node : *root->getSequence())
+ {
+ TIntermFunctionDefinition *nodeFunction = node->getAsFunctionDefinition();
+ if (nodeFunction != nullptr && nodeFunction->getFunctionSymbolInfo()->isMain())
+ {
+ return nodeFunction;
+ }
+ }
+ return nullptr;
+}
+
+TIntermBlock *FindMainBody(TIntermBlock *root)
+{
+ TIntermFunctionDefinition *main = FindMain(root);
+ ASSERT(main != nullptr);
+ TIntermBlock *mainBody = main->getBody();
+ ASSERT(mainBody != nullptr);
+ return mainBody;
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/FindMain.h b/src/3rdparty/angle/src/compiler/translator/FindMain.h
new file mode 100644
index 0000000000..bf2c45d871
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/FindMain.h
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FindMain.h: Adds functions to get the main function definition and its body.
+
+#ifndef COMPILER_TRANSLATOR_FINDMAIN_H_
+#define COMPILER_TRANSLATOR_FINDMAIN_H_
+
+namespace sh
+{
+
+class TIntermBlock;
+class TIntermFunctionDefinition;
+
+TIntermFunctionDefinition *FindMain(TIntermBlock *root);
+TIntermBlock *FindMainBody(TIntermBlock *root);
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_FINDMAIN_H_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/FindSymbolNode.cpp b/src/3rdparty/angle/src/compiler/translator/FindSymbolNode.cpp
new file mode 100644
index 0000000000..a2a10f128d
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/FindSymbolNode.cpp
@@ -0,0 +1,58 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// FindSymbol.cpp:
+// Utility for finding a symbol node inside an AST tree.
+
+#include "compiler/translator/FindSymbolNode.h"
+
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class SymbolFinder : public TIntermTraverser
+{
+ public:
+ SymbolFinder(const TString &symbolName, TBasicType basicType)
+ : TIntermTraverser(true, false, false),
+ mSymbolName(symbolName),
+ mNodeFound(nullptr),
+ mBasicType(basicType)
+ {
+ }
+
+ void visitSymbol(TIntermSymbol *node)
+ {
+ if (node->getBasicType() == mBasicType && node->getSymbol() == mSymbolName)
+ {
+ mNodeFound = node;
+ }
+ }
+
+ bool isFound() const { return mNodeFound != nullptr; }
+ const TIntermSymbol *getNode() const { return mNodeFound; }
+
+ private:
+ TString mSymbolName;
+ TIntermSymbol *mNodeFound;
+ TBasicType mBasicType;
+};
+
+} // anonymous namespace
+
+const TIntermSymbol *FindSymbolNode(TIntermNode *root,
+ const TString &symbolName,
+ TBasicType basicType)
+{
+ SymbolFinder finder(symbolName, basicType);
+ root->traverse(&finder);
+ return finder.getNode();
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/FindSymbolNode.h b/src/3rdparty/angle/src/compiler/translator/FindSymbolNode.h
new file mode 100644
index 0000000000..08dfb9a222
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/FindSymbolNode.h
@@ -0,0 +1,27 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// FindSymbolNode.h:
+// Utility for finding a symbol node inside an AST tree.
+
+#ifndef COMPILER_TRANSLATOR_FIND_SYMBOL_H_
+#define COMPILER_TRANSLATOR_FIND_SYMBOL_H_
+
+#include "compiler/translator/BaseTypes.h"
+#include "compiler/translator/Common.h"
+
+namespace sh
+{
+
+class TIntermNode;
+class TIntermSymbol;
+
+const TIntermSymbol *FindSymbolNode(TIntermNode *root,
+ const TString &symbolName,
+ TBasicType basicType);
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_FIND_SYMBOL_H_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.cpp b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.cpp
index a751b768b7..fba837f55c 100644
--- a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.cpp
@@ -3,75 +3,73 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
+// FlagStd140Structs.cpp: Find structs in std140 blocks, where the padding added in the translator
+// conflicts with the "natural" unpadded type.
#include "compiler/translator/FlagStd140Structs.h"
+#include "compiler/translator/IntermTraverse.h"
+
namespace sh
{
-bool FlagStd140Structs::visitBinary(Visit visit, TIntermBinary *binaryNode)
+namespace
{
- if (binaryNode->getRight()->getBasicType() == EbtStruct)
- {
- switch (binaryNode->getOp())
- {
- case EOpIndexDirectInterfaceBlock:
- case EOpIndexDirectStruct:
- if (isInStd140InterfaceBlock(binaryNode->getLeft()))
- {
- mFlaggedNodes.push_back(binaryNode);
- }
- break;
-
- default: break;
- }
- return false;
- }
- if (binaryNode->getOp() == EOpIndexDirectStruct)
- {
- return false;
- }
+class FlagStd140StructsTraverser : public TIntermTraverser
+{
+ public:
+ FlagStd140StructsTraverser() : TIntermTraverser(true, false, false) {}
- return visit == PreVisit;
-}
+ const std::vector<MappedStruct> getMappedStructs() const { return mMappedStructs; }
+
+ protected:
+ bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
+
+ private:
+ void mapBlockStructMembers(TIntermSymbol *blockDeclarator, TInterfaceBlock *block);
+
+ std::vector<MappedStruct> mMappedStructs;
+};
-void FlagStd140Structs::visitSymbol(TIntermSymbol *symbol)
+void FlagStd140StructsTraverser::mapBlockStructMembers(TIntermSymbol *blockDeclarator,
+ TInterfaceBlock *block)
{
- if (isInStd140InterfaceBlock(symbol) && symbol->getBasicType() == EbtStruct)
+ for (auto *field : block->fields())
{
- mFlaggedNodes.push_back(symbol);
+ if (field->type()->getBasicType() == EbtStruct)
+ {
+ MappedStruct mappedStruct;
+ mappedStruct.blockDeclarator = blockDeclarator;
+ mappedStruct.field = field;
+ mMappedStructs.push_back(mappedStruct);
+ }
}
}
-bool FlagStd140Structs::isInStd140InterfaceBlock(TIntermTyped *node) const
+bool FlagStd140StructsTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node)
{
- TIntermBinary *binaryNode = node->getAsBinaryNode();
-
- if (binaryNode)
- {
- return isInStd140InterfaceBlock(binaryNode->getLeft());
- }
-
- const TType &type = node->getType();
-
- // determine if we are in the standard layout
- const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
- if (interfaceBlock)
+ TIntermTyped *declarator = node->getSequence()->back()->getAsTyped();
+ if (declarator->getBasicType() == EbtInterfaceBlock)
{
- return (interfaceBlock->blockStorage() == EbsStd140);
+ TInterfaceBlock *block = declarator->getType().getInterfaceBlock();
+ if (block->blockStorage() == EbsStd140)
+ {
+ mapBlockStructMembers(declarator->getAsSymbolNode(), block);
+ }
}
-
return false;
}
-std::vector<TIntermTyped *> FlagStd140ValueStructs(TIntermNode *node)
+} // anonymous namespace
+
+std::vector<MappedStruct> FlagStd140Structs(TIntermNode *node)
{
- FlagStd140Structs flaggingTraversal;
+ FlagStd140StructsTraverser flaggingTraversal;
node->traverse(&flaggingTraversal);
- return flaggingTraversal.getFlaggedNodes();
+ return flaggingTraversal.getMappedStructs();
}
-}
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h
index cfcd775af7..f548d8b6ed 100644
--- a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h
+++ b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h
@@ -3,41 +3,28 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
+// FlagStd140Structs.h: Find structs in std140 blocks, where the padding added in the translator
+// conflicts with the "natural" unpadded type.
#ifndef COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_
#define COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_
-#include "compiler/translator/IntermNode.h"
+#include <vector>
namespace sh
{
-// This class finds references to nested structs of std140 blocks that access
-// the nested struct "by value", where the padding added in the translator
-// conflicts with the "natural" unpadded type.
-class FlagStd140Structs : public TIntermTraverser
-{
- public:
-
- FlagStd140Structs()
- : TIntermTraverser(true, false, false)
- {
- }
-
- const std::vector<TIntermTyped *> getFlaggedNodes() const { return mFlaggedNodes; }
+class TField;
+class TIntermNode;
+class TIntermSymbol;
- protected:
- bool visitBinary(Visit visit, TIntermBinary *binaryNode) override;
- void visitSymbol(TIntermSymbol *symbol) override;
-
- private:
- bool isInStd140InterfaceBlock(TIntermTyped *node) const;
-
- std::vector<TIntermTyped *> mFlaggedNodes;
+struct MappedStruct
+{
+ TIntermSymbol *blockDeclarator;
+ TField *field;
};
-std::vector<TIntermTyped *> FlagStd140ValueStructs(TIntermNode *node);
-
+std::vector<MappedStruct> FlagStd140Structs(TIntermNode *node);
}
-#endif // COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_
+#endif // COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.cpp b/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.cpp
deleted file mode 100644
index 4cc1c26a13..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/translator/ForLoopUnroll.h"
-
-#include "compiler/translator/ValidateLimitations.h"
-#include "angle_gl.h"
-
-bool ForLoopUnrollMarker::visitBinary(Visit, TIntermBinary *node)
-{
- if (mUnrollCondition != kSamplerArrayIndex)
- return true;
-
- // If a sampler array index is also the loop index,
- // 1) if the index type is integer, mark the loop for unrolling;
- // 2) if the index type if float, set a flag to later fail compile.
- switch (node->getOp())
- {
- case EOpIndexIndirect:
- if (node->getLeft() != NULL && node->getRight() != NULL && node->getLeft()->getAsSymbolNode())
- {
- TIntermSymbol *symbol = node->getLeft()->getAsSymbolNode();
- if (IsSampler(symbol->getBasicType()) && symbol->isArray() && !mLoopStack.empty())
- {
- mVisitSamplerArrayIndexNodeInsideLoop = true;
- node->getRight()->traverse(this);
- mVisitSamplerArrayIndexNodeInsideLoop = false;
- // We have already visited all the children.
- return false;
- }
- }
- break;
- default:
- break;
- }
- return true;
-}
-
-bool ForLoopUnrollMarker::visitLoop(Visit, TIntermLoop *node)
-{
- bool canBeUnrolled = mHasRunLoopValidation;
- if (!mHasRunLoopValidation)
- {
- canBeUnrolled = ValidateLimitations::IsLimitedForLoop(node);
- }
- if (mUnrollCondition == kIntegerIndex && canBeUnrolled)
- {
- // Check if loop index type is integer.
- // This is called after ValidateLimitations pass, so the loop has the limited form specified
- // in ESSL 1.00 appendix A.
- TIntermSequence *declSeq = node->getInit()->getAsAggregate()->getSequence();
- TIntermSymbol *symbol = (*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode();
- if (symbol->getBasicType() == EbtInt)
- node->setUnrollFlag(true);
- }
-
- TIntermNode *body = node->getBody();
- if (body != nullptr)
- {
- if (canBeUnrolled)
- {
- mLoopStack.push(node);
- body->traverse(this);
- mLoopStack.pop();
- }
- else
- {
- body->traverse(this);
- }
- }
- // The loop is fully processed - no need to visit children.
- return false;
-}
-
-void ForLoopUnrollMarker::visitSymbol(TIntermSymbol* symbol)
-{
- if (!mVisitSamplerArrayIndexNodeInsideLoop)
- return;
- TIntermLoop *loop = mLoopStack.findLoop(symbol);
- if (loop)
- {
- switch (symbol->getBasicType())
- {
- case EbtFloat:
- mSamplerArrayIndexIsFloatLoopIndex = true;
- break;
- case EbtInt:
- loop->setUnrollFlag(true);
- break;
- default:
- UNREACHABLE();
- }
- }
-}
diff --git a/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h b/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h
deleted file mode 100644
index 9c49ecad33..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_TRANSLATOR_FORLOOPUNROLL_H_
-#define COMPILER_TRANSLATOR_FORLOOPUNROLL_H_
-
-#include "compiler/translator/LoopInfo.h"
-
-// This class detects for-loops that needs to be unrolled.
-// Currently we support two unroll conditions:
-// 1) kForLoopWithIntegerIndex: unroll if the index type is integer.
-// 2) kForLoopWithSamplerArrayIndex: unroll where a sampler array index
-// is also the loop integer index, and reject and fail a compile
-// where a sampler array index is also the loop float index.
-class ForLoopUnrollMarker : public TIntermTraverser
-{
- public:
- enum UnrollCondition
- {
- kIntegerIndex,
- kSamplerArrayIndex
- };
-
- ForLoopUnrollMarker(UnrollCondition condition, bool hasRunLoopValidation)
- : TIntermTraverser(true, false, false),
- mUnrollCondition(condition),
- mSamplerArrayIndexIsFloatLoopIndex(false),
- mVisitSamplerArrayIndexNodeInsideLoop(false),
- mHasRunLoopValidation(hasRunLoopValidation)
- {
- }
-
- bool visitBinary(Visit, TIntermBinary *node) override;
- bool visitLoop(Visit, TIntermLoop *node) override;
- void visitSymbol(TIntermSymbol *node) override;
-
- bool samplerArrayIndexIsFloatLoopIndex() const
- {
- return mSamplerArrayIndexIsFloatLoopIndex;
- }
-
- private:
- UnrollCondition mUnrollCondition;
- TLoopStack mLoopStack;
- bool mSamplerArrayIndexIsFloatLoopIndex;
- bool mVisitSamplerArrayIndexNodeInsideLoop;
- bool mHasRunLoopValidation;
-};
-
-#endif // COMPILER_TRANSLATOR_FORLOOPUNROLL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/HashNames.cpp b/src/3rdparty/angle/src/compiler/translator/HashNames.cpp
new file mode 100644
index 0000000000..6bc90faf94
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/HashNames.cpp
@@ -0,0 +1,72 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/HashNames.h"
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+namespace
+{
+
+// GLSL ES 3.00.6 section 3.9: the maximum length of an identifier is 1024 characters.
+static const unsigned int kESSLMaxIdentifierLength = 1024u;
+
+static const char *kHashedNamePrefix = "webgl_";
+
+// Can't prefix with just _ because then we might introduce a double underscore, which is not safe
+// in GLSL (ESSL 3.00.6 section 3.8: All identifiers containing a double underscore are reserved for
+// use by the underlying implementation). u is short for user-defined.
+static const char *kUnhashedNamePrefix = "_u";
+static const unsigned int kUnhashedNamePrefixLength = 2u;
+
+TString HashName(const TString &name, ShHashFunction64 hashFunction)
+{
+ ASSERT(!name.empty());
+ ASSERT(hashFunction);
+ khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length());
+ TStringStream stream;
+ stream << kHashedNamePrefix << std::hex << number;
+ TString hashedName = stream.str();
+ return hashedName;
+}
+
+} // anonymous namespace
+
+TString HashName(const TName &name, ShHashFunction64 hashFunction, NameMap *nameMap)
+{
+ if (name.getString().empty() || name.isInternal())
+ {
+ return name.getString();
+ }
+ if (hashFunction == nullptr)
+ {
+ if (name.getString().length() + kUnhashedNamePrefixLength > kESSLMaxIdentifierLength)
+ {
+ // If the identifier length is already close to the limit, we can't prefix it. This is
+ // not a problem since there are no builtins or ANGLE's internal variables that would
+ // have as long names and could conflict.
+ return name.getString();
+ }
+ return kUnhashedNamePrefix + name.getString();
+ }
+ if (nameMap)
+ {
+ NameMap::const_iterator it = nameMap->find(name.getString().c_str());
+ if (it != nameMap->end())
+ return it->second.c_str();
+ }
+ TString hashedName = HashName(name.getString(), hashFunction);
+ if (nameMap)
+ {
+ (*nameMap)[name.getString().c_str()] = hashedName.c_str();
+ }
+ return hashedName;
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/HashNames.h b/src/3rdparty/angle/src/compiler/translator/HashNames.h
index 09c959f9da..28e861b309 100644
--- a/src/3rdparty/angle/src/compiler/translator/HashNames.h
+++ b/src/3rdparty/angle/src/compiler/translator/HashNames.h
@@ -9,10 +9,20 @@
#include <map>
-#include "compiler/translator/IntermNode.h"
+#include "GLSLANG/ShaderLang.h"
+#include "compiler/translator/Common.h"
-#define HASHED_NAME_PREFIX "webgl_"
+namespace sh
+{
typedef std::map<TPersistString, TPersistString> NameMap;
+class TName;
+
+// Hash user-defined name for GLSL output, with special handling for internal names.
+// The nameMap parameter is optional and is used to cache hashed names if set.
+TString HashName(const TName &name, ShHashFunction64 hashFunction, NameMap *nameMap);
+
+} // namespace sh
+
#endif // COMPILER_TRANSLATOR_HASHNAMES_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.cpp
new file mode 100644
index 0000000000..40b5e1f1e2
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.cpp
@@ -0,0 +1,304 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ImageFunctionHLSL: Class for writing implementations of ESSL image functions into HLSL output.
+//
+
+#include "compiler/translator/ImageFunctionHLSL.h"
+#include "compiler/translator/UtilsHLSL.h"
+
+namespace sh
+{
+
+// static
+void ImageFunctionHLSL::OutputImageFunctionArgumentList(
+ TInfoSinkBase &out,
+ const ImageFunctionHLSL::ImageFunction &imageFunction)
+{
+ if (imageFunction.readonly)
+ {
+ out << TextureString(imageFunction.image, imageFunction.imageInternalFormat) << " tex";
+ }
+ else
+ {
+ out << RWTextureString(imageFunction.image, imageFunction.imageInternalFormat) << " tex";
+ }
+
+ if (imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::LOAD ||
+ imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::STORE)
+ {
+ switch (imageFunction.image)
+ {
+ case EbtImage2D:
+ case EbtIImage2D:
+ case EbtUImage2D:
+ out << ", int2 p";
+ break;
+ case EbtImage3D:
+ case EbtIImage3D:
+ case EbtUImage3D:
+ case EbtImageCube:
+ case EbtIImageCube:
+ case EbtUImageCube:
+ case EbtImage2DArray:
+ case EbtIImage2DArray:
+ case EbtUImage2DArray:
+ out << ", int3 p";
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ if (imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::STORE)
+ {
+ switch (imageFunction.image)
+ {
+ case EbtImage2D:
+ case EbtImage3D:
+ case EbtImageCube:
+ case EbtImage2DArray:
+ out << ", float4 data";
+ break;
+ case EbtIImage2D:
+ case EbtIImage3D:
+ case EbtIImageCube:
+ case EbtIImage2DArray:
+ out << ", int4 data";
+ break;
+ case EbtUImage2D:
+ case EbtUImage3D:
+ case EbtUImageCube:
+ case EbtUImage2DArray:
+ out << ", uint4 data";
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ }
+}
+
+// static
+void ImageFunctionHLSL::OutputImageSizeFunctionBody(
+ TInfoSinkBase &out,
+ const ImageFunctionHLSL::ImageFunction &imageFunction,
+ const TString &imageReference)
+{
+ if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) ||
+ IsImageCube(imageFunction.image))
+ {
+ // "depth" stores either the number of layers in an array texture or 3D depth
+ out << " uint width; uint height; uint depth;\n"
+ << " " << imageReference << ".GetDimensions(width, height, depth);\n";
+ }
+ else if (IsImage2D(imageFunction.image))
+ {
+ out << " uint width; uint height;\n"
+ << " " << imageReference << ".GetDimensions(width, height);\n";
+ }
+ else
+ UNREACHABLE();
+
+ if (strcmp(imageFunction.getReturnType(), "int3") == 0)
+ {
+ out << " return int3(width, height, depth);\n";
+ }
+ else
+ {
+ out << " return int2(width, height);\n";
+ }
+}
+
+// static
+void ImageFunctionHLSL::OutputImageLoadFunctionBody(
+ TInfoSinkBase &out,
+ const ImageFunctionHLSL::ImageFunction &imageFunction,
+ const TString &imageReference)
+{
+ if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) ||
+ IsImageCube(imageFunction.image))
+ {
+ out << " return " << imageReference << "[uint3(p.x, p.y, p.z)];\n";
+ }
+ else if (IsImage2D(imageFunction.image))
+ {
+ out << " return " << imageReference << "[uint2(p.x, p.y)];\n";
+ }
+ else
+ UNREACHABLE();
+}
+
+// static
+void ImageFunctionHLSL::OutputImageStoreFunctionBody(
+ TInfoSinkBase &out,
+ const ImageFunctionHLSL::ImageFunction &imageFunction,
+ const TString &imageReference)
+{
+ if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) ||
+ IsImage2D(imageFunction.image) || IsImageCube(imageFunction.image))
+ {
+ out << " " << imageReference << "[p] = data;\n";
+ }
+ else
+ UNREACHABLE();
+}
+
+TString ImageFunctionHLSL::ImageFunction::name() const
+{
+ TString name = "gl_image";
+ if (readonly)
+ {
+ name += TextureTypeSuffix(image, imageInternalFormat);
+ }
+ else
+ {
+ name += RWTextureTypeSuffix(image, imageInternalFormat);
+ }
+
+ switch (method)
+ {
+ case Method::SIZE:
+ name += "Size";
+ break;
+ case Method::LOAD:
+ name += "Load";
+ break;
+ case Method::STORE:
+ name += "Store";
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return name;
+}
+
+const char *ImageFunctionHLSL::ImageFunction::getReturnType() const
+{
+ if (method == ImageFunction::Method::SIZE)
+ {
+ switch (image)
+ {
+ case EbtImage2D:
+ case EbtIImage2D:
+ case EbtUImage2D:
+ case EbtImageCube:
+ case EbtIImageCube:
+ case EbtUImageCube:
+ return "int2";
+ case EbtImage3D:
+ case EbtIImage3D:
+ case EbtUImage3D:
+ case EbtImage2DArray:
+ case EbtIImage2DArray:
+ case EbtUImage2DArray:
+ return "int3";
+ default:
+ UNREACHABLE();
+ }
+ }
+ else if (method == ImageFunction::Method::LOAD)
+ {
+ switch (image)
+ {
+ case EbtImage2D:
+ case EbtImage3D:
+ case EbtImageCube:
+ case EbtImage2DArray:
+ return "float4";
+ case EbtIImage2D:
+ case EbtIImage3D:
+ case EbtIImageCube:
+ case EbtIImage2DArray:
+ return "int4";
+ case EbtUImage2D:
+ case EbtUImage3D:
+ case EbtUImageCube:
+ case EbtUImage2DArray:
+ return "uint4";
+ default:
+ UNREACHABLE();
+ }
+ }
+ else if (method == ImageFunction::Method::STORE)
+ {
+ return "void";
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ return "";
+}
+
+bool ImageFunctionHLSL::ImageFunction::operator<(const ImageFunction &rhs) const
+{
+ return std::tie(image, imageInternalFormat, readonly, method) <
+ std::tie(rhs.image, rhs.imageInternalFormat, rhs.readonly, rhs.method);
+}
+
+TString ImageFunctionHLSL::useImageFunction(const TString &name,
+ const TBasicType &type,
+ TLayoutImageInternalFormat imageInternalFormat,
+ bool readonly)
+{
+ ASSERT(IsImage(type));
+ ImageFunction imageFunction;
+ imageFunction.image = type;
+ imageFunction.imageInternalFormat = imageInternalFormat;
+ imageFunction.readonly = readonly;
+
+ if (name == "imageSize")
+ {
+ imageFunction.method = ImageFunction::Method::SIZE;
+ }
+ else if (name == "imageLoad")
+ {
+ imageFunction.method = ImageFunction::Method::LOAD;
+ }
+ else if (name == "imageStore")
+ {
+ imageFunction.method = ImageFunction::Method::STORE;
+ }
+ else
+ UNREACHABLE();
+
+ mUsesImage.insert(imageFunction);
+ return imageFunction.name();
+}
+
+void ImageFunctionHLSL::imageFunctionHeader(TInfoSinkBase &out)
+{
+ for (const ImageFunction &imageFunction : mUsesImage)
+ {
+ // Function header
+ out << imageFunction.getReturnType() << " " << imageFunction.name() << "(";
+
+ OutputImageFunctionArgumentList(out, imageFunction);
+
+ out << ")\n"
+ "{\n";
+
+ TString imageReference("tex");
+
+ if (imageFunction.method == ImageFunction::Method::SIZE)
+ {
+ OutputImageSizeFunctionBody(out, imageFunction, imageReference);
+ }
+ else if (imageFunction.method == ImageFunction::Method::LOAD)
+ {
+ OutputImageLoadFunctionBody(out, imageFunction, imageReference);
+ }
+ else
+ {
+ OutputImageStoreFunctionBody(out, imageFunction, imageReference);
+ }
+
+ out << "}\n"
+ "\n";
+ }
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.h b/src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.h
new file mode 100644
index 0000000000..9db17a6bbf
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/ImageFunctionHLSL.h
@@ -0,0 +1,76 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ImageFunctionHLSL: Class for writing implementations of ESSL image functions into HLSL output.
+//
+
+#ifndef COMPILER_TRANSLATOR_IMAGEFUNCTIONHLSL_H_
+#define COMPILER_TRANSLATOR_IMAGEFUNCTIONHLSL_H_
+
+#include <set>
+
+#include "GLSLANG/ShaderLang.h"
+#include "compiler/translator/BaseTypes.h"
+#include "compiler/translator/Common.h"
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/Types.h"
+
+namespace sh
+{
+
+class ImageFunctionHLSL final : angle::NonCopyable
+{
+ public:
+ // Returns the name of the image function implementation to caller.
+ // The name that's passed in is the name of the GLSL image function that it should implement.
+ TString useImageFunction(const TString &name,
+ const TBasicType &type,
+ TLayoutImageInternalFormat imageInternalFormat,
+ bool readonly);
+
+ void imageFunctionHeader(TInfoSinkBase &out);
+
+ private:
+ struct ImageFunction
+ {
+ // See ESSL 3.10.4 section 8.12 for reference about what the different methods below do.
+ enum class Method
+ {
+ SIZE,
+ LOAD,
+ STORE
+ };
+
+ TString name() const;
+
+ bool operator<(const ImageFunction &rhs) const;
+
+ const char *getReturnType() const;
+
+ TBasicType image;
+ TLayoutImageInternalFormat imageInternalFormat;
+ bool readonly;
+ Method method;
+ };
+
+ static void OutputImageFunctionArgumentList(
+ TInfoSinkBase &out,
+ const ImageFunctionHLSL::ImageFunction &imageFunction);
+ static void OutputImageSizeFunctionBody(TInfoSinkBase &out,
+ const ImageFunctionHLSL::ImageFunction &imageFunction,
+ const TString &imageReference);
+ static void OutputImageLoadFunctionBody(TInfoSinkBase &out,
+ const ImageFunctionHLSL::ImageFunction &imageFunction,
+ const TString &imageReference);
+ static void OutputImageStoreFunctionBody(TInfoSinkBase &out,
+ const ImageFunctionHLSL::ImageFunction &imageFunction,
+ const TString &imageReference);
+ using ImageFunctionSet = std::set<ImageFunction>;
+ ImageFunctionSet mUsesImage;
+};
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_IMAGEFUNCTIONHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/InfoSink.cpp b/src/3rdparty/angle/src/compiler/translator/InfoSink.cpp
index cd59658ff7..db26aa67e8 100644
--- a/src/3rdparty/angle/src/compiler/translator/InfoSink.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/InfoSink.cpp
@@ -6,32 +6,27 @@
#include "compiler/translator/InfoSink.h"
-void TInfoSinkBase::prefix(TPrefixType p) {
- switch(p) {
- case EPrefixNone:
- break;
- case EPrefixWarning:
+namespace sh
+{
+
+void TInfoSinkBase::prefix(Severity severity)
+{
+ switch (severity)
+ {
+ case SH_WARNING:
sink.append("WARNING: ");
break;
- case EPrefixError:
+ case SH_ERROR:
sink.append("ERROR: ");
break;
- case EPrefixInternalError:
- sink.append("INTERNAL ERROR: ");
- break;
- case EPrefixUnimplemented:
- sink.append("UNIMPLEMENTED: ");
- break;
- case EPrefixNote:
- sink.append("NOTE: ");
- break;
default:
sink.append("UNKOWN ERROR: ");
break;
}
}
-void TInfoSinkBase::location(int file, int line) {
+void TInfoSinkBase::location(int file, int line)
+{
TPersistStringStream stream;
if (line)
stream << file << ":" << line;
@@ -42,13 +37,4 @@ void TInfoSinkBase::location(int file, int line) {
sink.append(stream.str());
}
-void TInfoSinkBase::location(const TSourceLoc& loc) {
- location(loc.first_file, loc.first_line);
-}
-
-void TInfoSinkBase::message(TPrefixType p, const TSourceLoc& loc, const char* m) {
- prefix(p);
- location(loc);
- sink.append(m);
- sink.append("\n");
-}
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/InfoSink.h b/src/3rdparty/angle/src/compiler/translator/InfoSink.h
index f47fafa8ee..2705f48d59 100644
--- a/src/3rdparty/angle/src/compiler/translator/InfoSink.h
+++ b/src/3rdparty/angle/src/compiler/translator/InfoSink.h
@@ -10,38 +10,32 @@
#include <math.h>
#include <stdlib.h>
#include "compiler/translator/Common.h"
+#include "compiler/translator/Severity.h"
+
+namespace sh
+{
// Returns the fractional part of the given floating-point number.
-inline float fractionalPart(float f) {
- float intPart = 0.0f;
- return modff(f, &intPart);
+inline float fractionalPart(float f)
+{
+ float intPart = 0.0f;
+ return modff(f, &intPart);
}
//
-// TPrefixType is used to centralize how info log messages start.
-// See below.
-//
-enum TPrefixType {
- EPrefixNone,
- EPrefixWarning,
- EPrefixError,
- EPrefixInternalError,
- EPrefixUnimplemented,
- EPrefixNote
-};
-
-//
// Encapsulate info logs for all objects that have them.
//
// The methods are a general set of tools for getting a variety of
// messages and types inserted into the log.
//
-class TInfoSinkBase {
-public:
+class TInfoSinkBase
+{
+ public:
TInfoSinkBase() {}
template <typename T>
- TInfoSinkBase& operator<<(const T& t) {
+ TInfoSinkBase &operator<<(const T &t)
+ {
TPersistStringStream stream;
stream << t;
sink.append(stream.str());
@@ -49,33 +43,41 @@ public:
}
// Override << operator for specific types. It is faster to append strings
// and characters directly to the sink.
- TInfoSinkBase& operator<<(char c) {
+ TInfoSinkBase &operator<<(char c)
+ {
sink.append(1, c);
return *this;
}
- TInfoSinkBase& operator<<(const char* str) {
+ TInfoSinkBase &operator<<(const char *str)
+ {
sink.append(str);
return *this;
}
- TInfoSinkBase& operator<<(const TPersistString& str) {
+ TInfoSinkBase &operator<<(const TPersistString &str)
+ {
sink.append(str);
return *this;
}
- TInfoSinkBase& operator<<(const TString& str) {
+ TInfoSinkBase &operator<<(const TString &str)
+ {
sink.append(str.c_str());
return *this;
}
// Make sure floats are written with correct precision.
- TInfoSinkBase& operator<<(float f) {
+ TInfoSinkBase &operator<<(float f)
+ {
// Make sure that at least one decimal point is written. If a number
// does not have a fractional part, the default precision format does
// not write the decimal portion which gets interpreted as integer by
// the compiler.
TPersistStringStream stream;
- if (fractionalPart(f) == 0.0f) {
+ if (fractionalPart(f) == 0.0f)
+ {
stream.precision(1);
stream << std::showpoint << std::fixed << f;
- } else {
+ }
+ else
+ {
stream.unsetf(std::ios::fixed);
stream.unsetf(std::ios::scientific);
stream.precision(8);
@@ -85,8 +87,9 @@ public:
return *this;
}
// Write boolean values as their names instead of integral value.
- TInfoSinkBase& operator<<(bool b) {
- const char* str = b ? "true" : "false";
+ TInfoSinkBase &operator<<(bool b)
+ {
+ const char *str = b ? "true" : "false";
sink.append(str);
return *this;
}
@@ -94,23 +97,24 @@ public:
void erase() { sink.clear(); }
int size() { return static_cast<int>(sink.size()); }
- const TPersistString& str() const { return sink; }
- const char* c_str() const { return sink.c_str(); }
+ const TPersistString &str() const { return sink; }
+ const char *c_str() const { return sink.c_str(); }
- void prefix(TPrefixType p);
+ void prefix(Severity severity);
void location(int file, int line);
- void location(const TSourceLoc& loc);
- void message(TPrefixType p, const TSourceLoc& loc, const char* m);
-private:
+ private:
TPersistString sink;
};
-class TInfoSink {
-public:
+class TInfoSink
+{
+ public:
TInfoSinkBase info;
TInfoSinkBase debug;
TInfoSinkBase obj;
};
-#endif // COMPILER_TRANSLATOR_INFOSINK_H_
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_INFOSINK_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/Initialize.cpp b/src/3rdparty/angle/src/compiler/translator/Initialize.cpp
index 2f51aada7f..6f8baee96b 100644
--- a/src/3rdparty/angle/src/compiler/translator/Initialize.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/Initialize.cpp
@@ -6,7 +6,7 @@
//
// Create symbols that declare built-in definitions, add built-ins that
-// cannot be expressed in the files, and establish mappings between
+// cannot be expressed in the files, and establish mappings between
// built-in functions and operators.
//
@@ -16,18 +16,25 @@
#include "compiler/translator/IntermNode.h"
#include "angle_gl.h"
-void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable)
+namespace sh
{
- const TType *float1 = TCache::getType(EbtFloat);
- const TType *float2 = TCache::getType(EbtFloat, 2);
- const TType *float3 = TCache::getType(EbtFloat, 3);
- const TType *float4 = TCache::getType(EbtFloat, 4);
- const TType *int1 = TCache::getType(EbtInt);
- const TType *int2 = TCache::getType(EbtInt, 2);
- const TType *int3 = TCache::getType(EbtInt, 3);
- const TType *uint1 = TCache::getType(EbtUInt);
- const TType *bool1 = TCache::getType(EbtBool);
- const TType *genType = TCache::getType(EbtGenType);
+
+void InsertBuiltInFunctions(sh::GLenum type,
+ ShShaderSpec spec,
+ const ShBuiltInResources &resources,
+ TSymbolTable &symbolTable)
+{
+ const TType *voidType = TCache::getType(EbtVoid);
+ const TType *float1 = TCache::getType(EbtFloat);
+ const TType *float2 = TCache::getType(EbtFloat, 2);
+ const TType *float3 = TCache::getType(EbtFloat, 3);
+ const TType *float4 = TCache::getType(EbtFloat, 4);
+ const TType *int1 = TCache::getType(EbtInt);
+ const TType *int2 = TCache::getType(EbtInt, 2);
+ const TType *int3 = TCache::getType(EbtInt, 3);
+ const TType *uint1 = TCache::getType(EbtUInt);
+ const TType *bool1 = TCache::getType(EbtBool);
+ const TType *genType = TCache::getType(EbtGenType);
const TType *genIType = TCache::getType(EbtGenIType);
const TType *genUType = TCache::getType(EbtGenUType);
const TType *genBType = TCache::getType(EbtGenBType);
@@ -35,113 +42,117 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
//
// Angle and Trigonometric Functions.
//
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpRadians, genType, "radians", genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpDegrees, genType, "degrees", genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSin, genType, "sin", genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpCos, genType, "cos", genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpTan, genType, "tan", genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAsin, genType, "asin", genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAcos, genType, "acos", genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAtan, genType, "atan", genType, genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAtan, genType, "atan", genType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpSinh, genType, "sinh", genType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpCosh, genType, "cosh", genType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTanh, genType, "tanh", genType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAsinh, genType, "asinh", genType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAcosh, genType, "acosh", genType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAtanh, genType, "atanh", genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpRadians, genType, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpDegrees, genType, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSin, genType, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpCos, genType, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpTan, genType, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAsin, genType, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAcos, genType, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAtan, genType, genType, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAtan, genType, genType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpSinh, genType, genType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpCosh, genType, genType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTanh, genType, genType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpAsinh, genType, genType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpAcosh, genType, genType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpAtanh, genType, genType);
//
// Exponential Functions.
//
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpPow, genType, "pow", genType, genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpExp, genType, "exp", genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLog, genType, "log", genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpExp2, genType, "exp2", genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLog2, genType, "log2", genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSqrt, genType, "sqrt", genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpInverseSqrt, genType, "inversesqrt", genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpPow, genType, genType, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpExp, genType, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLog, genType, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpExp2, genType, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLog2, genType, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSqrt, genType, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpInverseSqrt, genType, genType);
//
// Common Functions.
//
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAbs, genType, "abs", genType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAbs, genIType, "abs", genIType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSign, genType, "sign", genType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpSign, genIType, "sign", genIType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpFloor, genType, "floor", genType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTrunc, genType, "trunc", genType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpRound, genType, "round", genType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpRoundEven, genType, "roundEven", genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpCeil, genType, "ceil", genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpFract, genType, "fract", genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMod, genType, "mod", genType, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMod, genType, "mod", genType, genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMin, genType, "min", genType, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMin, genType, "min", genType, genType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genIType, "min", genIType, genIType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genIType, "min", genIType, int1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genUType, "min", genUType, genUType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genUType, "min", genUType, uint1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMax, genType, "max", genType, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMax, genType, "max", genType, genType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genIType, "max", genIType, genIType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genIType, "max", genIType, int1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genUType, "max", genUType, genUType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genUType, "max", genUType, uint1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpClamp, genType, "clamp", genType, float1, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpClamp, genType, "clamp", genType, genType, genType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genIType, "clamp", genIType, int1, int1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genIType, "clamp", genIType, genIType, genIType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genUType, "clamp", genUType, uint1, uint1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genUType, "clamp", genUType, genUType, genUType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMix, genType, "mix", genType, genType, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMix, genType, "mix", genType, genType, genType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMix, genType, "mix", genType, genType, genBType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpStep, genType, "step", genType, genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpStep, genType, "step", float1, genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSmoothStep, genType, "smoothstep", genType, genType, genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSmoothStep, genType, "smoothstep", float1, float1, genType);
-
- const TType *outFloat1 = TCache::getType(EbtFloat, EvqOut);
- const TType *outFloat2 = TCache::getType(EbtFloat, EvqOut, 2);
- const TType *outFloat3 = TCache::getType(EbtFloat, EvqOut, 3);
- const TType *outFloat4 = TCache::getType(EbtFloat, EvqOut, 4);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpModf, float1, "modf", float1, outFloat1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpModf, float2, "modf", float2, outFloat2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpModf, float3, "modf", float3, outFloat3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpModf, float4, "modf", float4, outFloat4);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpIsNan, genBType, "isnan", genType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpIsInf, genBType, "isinf", genType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpFloatBitsToInt, genIType, "floatBitsToInt", genType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpFloatBitsToUint, genUType, "floatBitsToUint", genType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpIntBitsToFloat, genType, "intBitsToFloat", genIType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUintBitsToFloat, genType, "uintBitsToFloat", genUType);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpPackSnorm2x16, uint1, "packSnorm2x16", float2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpPackUnorm2x16, uint1, "packUnorm2x16", float2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpPackHalf2x16, uint1, "packHalf2x16", float2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUnpackSnorm2x16, float2, "unpackSnorm2x16", uint1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUnpackUnorm2x16, float2, "unpackUnorm2x16", uint1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUnpackHalf2x16, float2, "unpackHalf2x16", uint1);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAbs, genType, genType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpAbs, genIType, genIType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSign, genType, genType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpSign, genIType, genIType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpFloor, genType, genType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTrunc, genType, genType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpRound, genType, genType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpRoundEven, genType, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpCeil, genType, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpFract, genType, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMod, genType, genType, float1);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMod, genType, genType, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMin, genType, genType, float1);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMin, genType, genType, genType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMin, genIType, genIType, genIType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMin, genIType, genIType, int1);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMin, genUType, genUType, genUType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMin, genUType, genUType, uint1);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMax, genType, genType, float1);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMax, genType, genType, genType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMax, genIType, genIType, genIType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMax, genIType, genIType, int1);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMax, genUType, genUType, genUType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMax, genUType, genUType, uint1);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpClamp, genType, genType, float1, float1);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpClamp, genType, genType, genType, genType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpClamp, genIType, genIType, int1, int1);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpClamp, genIType, genIType, genIType, genIType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpClamp, genUType, genUType, uint1, uint1);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpClamp, genUType, genUType, genUType, genUType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMix, genType, genType, genType, float1);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMix, genType, genType, genType, genType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMix, genType, genType, genType, genBType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpStep, genType, genType, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpStep, genType, float1, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSmoothStep, genType, genType, genType, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpSmoothStep, genType, float1, float1, genType);
+
+ const TType *outGenType = TCache::getType(EbtGenType, EvqOut);
+ const TType *outGenIType = TCache::getType(EbtGenIType, EvqOut);
+
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpModf, genType, genType, outGenType);
+
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpIsNan, genBType, genType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpIsInf, genBType, genType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpFloatBitsToInt, genIType, genType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpFloatBitsToUint, genUType, genType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpIntBitsToFloat, genType, genIType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpUintBitsToFloat, genType, genUType);
+
+ symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFrexp, genType, genType, outGenIType);
+ symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpLdexp, genType, genType, genIType);
+
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpPackSnorm2x16, uint1, float2);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpPackUnorm2x16, uint1, float2);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpPackHalf2x16, uint1, float2);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpUnpackSnorm2x16, float2, uint1);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpUnpackUnorm2x16, float2, uint1);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpUnpackHalf2x16, float2, uint1);
+
+ symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpPackUnorm4x8, uint1, float4);
+ symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpPackSnorm4x8, uint1, float4);
+ symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUnpackUnorm4x8, float4, uint1);
+ symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUnpackSnorm4x8, float4, uint1);
//
// Geometric Functions.
//
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLength, float1, "length", genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpDistance, float1, "distance", genType, genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpDot, float1, "dot", genType, genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpCross, float3, "cross", float3, float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpNormalize, genType, "normalize", genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpFaceForward, genType, "faceforward", genType, genType, genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpReflect, genType, "reflect", genType, genType);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpRefract, genType, "refract", genType, genType, float1);
-
- const TType *mat2 = TCache::getType(EbtFloat, 2, 2);
- const TType *mat3 = TCache::getType(EbtFloat, 3, 3);
- const TType *mat4 = TCache::getType(EbtFloat, 4, 4);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLength, float1, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpDistance, float1, genType, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpDot, float1, genType, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpCross, float3, float3, float3);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpNormalize, genType, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpFaceforward, genType, genType, genType,
+ genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpReflect, genType, genType, genType);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpRefract, genType, genType, genType, float1);
+
+ const TType *mat2 = TCache::getType(EbtFloat, 2, 2);
+ const TType *mat3 = TCache::getType(EbtFloat, 3, 3);
+ const TType *mat4 = TCache::getType(EbtFloat, 4, 4);
const TType *mat2x3 = TCache::getType(EbtFloat, 2, 3);
const TType *mat3x2 = TCache::getType(EbtFloat, 3, 2);
const TType *mat2x4 = TCache::getType(EbtFloat, 2, 4);
@@ -152,45 +163,45 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
//
// Matrix Functions.
//
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMul, mat2, "matrixCompMult", mat2, mat2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMul, mat3, "matrixCompMult", mat3, mat3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMul, mat4, "matrixCompMult", mat4, mat4);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat2x3, "matrixCompMult", mat2x3, mat2x3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat3x2, "matrixCompMult", mat3x2, mat3x2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat2x4, "matrixCompMult", mat2x4, mat2x4);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat4x2, "matrixCompMult", mat4x2, mat4x2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat3x4, "matrixCompMult", mat3x4, mat3x4);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat4x3, "matrixCompMult", mat4x3, mat4x3);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat2, "outerProduct", float2, float2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat3, "outerProduct", float3, float3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat4, "outerProduct", float4, float4);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat2x3, "outerProduct", float3, float2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat3x2, "outerProduct", float2, float3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat2x4, "outerProduct", float4, float2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat4x2, "outerProduct", float2, float4);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat3x4, "outerProduct", float4, float3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat4x3, "outerProduct", float3, float4);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat2, "transpose", mat2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat3, "transpose", mat3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat4, "transpose", mat4);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat2x3, "transpose", mat3x2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat3x2, "transpose", mat2x3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat2x4, "transpose", mat4x2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat4x2, "transpose", mat2x4);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat3x4, "transpose", mat4x3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat4x3, "transpose", mat3x4);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDeterminant, float1, "determinant", mat2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDeterminant, float1, "determinant", mat3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDeterminant, float1, "determinant", mat4);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpInverse, mat2, "inverse", mat2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpInverse, mat3, "inverse", mat3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpInverse, mat4, "inverse", mat4);
-
- const TType *vec = TCache::getType(EbtVec);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMulMatrixComponentWise, mat2, mat2, mat2);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMulMatrixComponentWise, mat3, mat3, mat3);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpMulMatrixComponentWise, mat4, mat4, mat4);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat2x3, mat2x3, mat2x3);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat3x2, mat3x2, mat3x2);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat2x4, mat2x4, mat2x4);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat4x2, mat4x2, mat4x2);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat3x4, mat3x4, mat3x4);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpMulMatrixComponentWise, mat4x3, mat4x3, mat4x3);
+
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat2, float2, float2);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat3, float3, float3);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat4, float4, float4);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat2x3, float3, float2);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat3x2, float2, float3);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat2x4, float4, float2);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat4x2, float2, float4);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat3x4, float4, float3);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpOuterProduct, mat4x3, float3, float4);
+
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat2, mat2);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat3, mat3);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat4, mat4);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat2x3, mat3x2);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat3x2, mat2x3);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat2x4, mat4x2);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat4x2, mat2x4);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat3x4, mat4x3);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpTranspose, mat4x3, mat3x4);
+
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDeterminant, float1, mat2);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDeterminant, float1, mat3);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDeterminant, float1, mat4);
+
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpInverse, mat2, mat2);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpInverse, mat3, mat3);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpInverse, mat4, mat4);
+
+ const TType *vec = TCache::getType(EbtVec);
const TType *ivec = TCache::getType(EbtIVec);
const TType *uvec = TCache::getType(EbtUVec);
const TType *bvec = TCache::getType(EbtBVec);
@@ -198,31 +209,62 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
//
// Vector relational functions.
//
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThan, bvec, "lessThan", vec, vec);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThan, bvec, "lessThan", ivec, ivec);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpLessThan, bvec, "lessThan", uvec, uvec);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThanEqual, bvec, "lessThanEqual", vec, vec);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThanEqual, bvec, "lessThanEqual", ivec, ivec);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpLessThanEqual, bvec, "lessThanEqual", uvec, uvec);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThan, bvec, "greaterThan", vec, vec);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThan, bvec, "greaterThan", ivec, ivec);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpGreaterThan, bvec, "greaterThan", uvec, uvec);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThanEqual, bvec, "greaterThanEqual", vec, vec);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThanEqual, bvec, "greaterThanEqual", ivec, ivec);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpGreaterThanEqual, bvec, "greaterThanEqual", uvec, uvec);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorEqual, bvec, "equal", vec, vec);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorEqual, bvec, "equal", ivec, ivec);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpVectorEqual, bvec, "equal", uvec, uvec);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorEqual, bvec, "equal", bvec, bvec);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", vec, vec);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", ivec, ivec);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", uvec, uvec);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", bvec, bvec);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAny, bool1, "any", bvec);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAll, bool1, "all", bvec);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorLogicalNot, bvec, "not", bvec);
-
- const TType *sampler2D = TCache::getType(EbtSampler2D);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLessThanComponentWise, bvec, vec, vec);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLessThanComponentWise, bvec, ivec, ivec);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpLessThanComponentWise, bvec, uvec, uvec);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLessThanEqualComponentWise, bvec, vec, vec);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLessThanEqualComponentWise, bvec, ivec, ivec);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpLessThanEqualComponentWise, bvec, uvec, uvec);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpGreaterThanComponentWise, bvec, vec, vec);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpGreaterThanComponentWise, bvec, ivec, ivec);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpGreaterThanComponentWise, bvec, uvec, uvec);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpGreaterThanEqualComponentWise, bvec, vec, vec);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpGreaterThanEqualComponentWise, bvec, ivec,
+ ivec);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpGreaterThanEqualComponentWise, bvec, uvec, uvec);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpEqualComponentWise, bvec, vec, vec);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpEqualComponentWise, bvec, ivec, ivec);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpEqualComponentWise, bvec, uvec, uvec);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpEqualComponentWise, bvec, bvec, bvec);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpNotEqualComponentWise, bvec, vec, vec);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpNotEqualComponentWise, bvec, ivec, ivec);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpNotEqualComponentWise, bvec, uvec, uvec);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpNotEqualComponentWise, bvec, bvec, bvec);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAny, bool1, bvec);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpAll, bool1, bvec);
+ symbolTable.insertBuiltInOp(COMMON_BUILTINS, EOpLogicalNotComponentWise, bvec, bvec);
+
+ //
+ // Integer functions
+ //
+ const TType *outGenUType = TCache::getType(EbtGenUType, EvqOut);
+
+ symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldExtract, genIType, genIType, int1,
+ int1);
+ symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldExtract, genUType, genUType, int1,
+ int1);
+ symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldInsert, genIType, genIType, genIType,
+ int1, int1);
+ symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldInsert, genUType, genUType, genUType,
+ int1, int1);
+ symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldReverse, genIType, genIType);
+ symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitfieldReverse, genUType, genUType);
+ symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitCount, genIType, genIType);
+ symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpBitCount, genIType, genUType);
+ symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFindLSB, genIType, genIType);
+ symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFindLSB, genIType, genUType);
+ symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFindMSB, genIType, genIType);
+ symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpFindMSB, genIType, genUType);
+ symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUaddCarry, genUType, genUType, genUType,
+ outGenUType);
+ symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUsubBorrow, genUType, genUType, genUType,
+ outGenUType);
+ symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpUmulExtended, voidType, genUType, genUType,
+ outGenUType, outGenUType);
+ symbolTable.insertBuiltInOp(ESSL3_1_BUILTINS, EOpImulExtended, voidType, genIType, genIType,
+ outGenIType, outGenIType);
+
+ const TType *sampler2D = TCache::getType(EbtSampler2D);
const TType *samplerCube = TCache::getType(EbtSamplerCube);
//
@@ -233,13 +275,15 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float4);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCube", samplerCube, float3);
- if (resources.OES_EGL_image_external)
+ if (resources.OES_EGL_image_external || resources.NV_EGL_stream_consumer_external)
{
const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", samplerExternalOES, float2);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", samplerExternalOES, float3);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", samplerExternalOES, float4);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", samplerExternalOES,
+ float3);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", samplerExternalOES,
+ float4);
}
if (resources.ARB_texture_rectangle)
@@ -247,8 +291,10 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
const TType *sampler2DRect = TCache::getType(EbtSampler2DRect);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DRect", sampler2DRect, float2);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DRectProj", sampler2DRect, float3);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DRectProj", sampler2DRect, float4);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DRectProj", sampler2DRect,
+ float3);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DRectProj", sampler2DRect,
+ float4);
}
if (resources.EXT_shader_texture_lod)
@@ -256,49 +302,68 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
/* The *Grad* variants are new to both vertex and fragment shaders; the fragment
* shader specific pieces are added separately below.
*/
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DGradEXT", sampler2D, float2, float2, float2);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DProjGradEXT", sampler2D, float3, float2, float2);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DProjGradEXT", sampler2D, float4, float2, float2);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "textureCubeGradEXT", samplerCube, float3, float3, float3);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4,
+ "texture2DGradEXT", sampler2D, float2, float2, float2);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4,
+ "texture2DProjGradEXT", sampler2D, float3, float2, float2);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4,
+ "texture2DProjGradEXT", sampler2D, float4, float2, float2);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4,
+ "textureCubeGradEXT", samplerCube, float3, float3, float3);
}
if (type == GL_FRAGMENT_SHADER)
{
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", sampler2D, float2, float1);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float3, float1);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float4, float1);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCube", samplerCube, float3, float1);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float3,
+ float1);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float4,
+ float1);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCube", samplerCube, float3,
+ float1);
if (resources.OES_standard_derivatives)
{
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, EOpDFdx, "GL_OES_standard_derivatives", genType, "dFdx", genType);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, EOpDFdy, "GL_OES_standard_derivatives", genType, "dFdy", genType);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, EOpFwidth, "GL_OES_standard_derivatives", genType, "fwidth", genType);
+ symbolTable.insertBuiltInOp(ESSL1_BUILTINS, EOpDFdx,
+ TExtension::OES_standard_derivatives, genType, genType);
+ symbolTable.insertBuiltInOp(ESSL1_BUILTINS, EOpDFdy,
+ TExtension::OES_standard_derivatives, genType, genType);
+ symbolTable.insertBuiltInOp(ESSL1_BUILTINS, EOpFwidth,
+ TExtension::OES_standard_derivatives, genType, genType);
}
if (resources.EXT_shader_texture_lod)
{
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DLodEXT", sampler2D, float2, float1);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DProjLodEXT", sampler2D, float3, float1);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DProjLodEXT", sampler2D, float4, float1);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "textureCubeLodEXT", samplerCube, float3, float1);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4,
+ "texture2DLodEXT", sampler2D, float2, float1);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4,
+ "texture2DProjLodEXT", sampler2D, float3, float1);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4,
+ "texture2DProjLodEXT", sampler2D, float4, float1);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, TExtension::EXT_shader_texture_lod, float4,
+ "textureCubeLodEXT", samplerCube, float3, float1);
}
}
if (type == GL_VERTEX_SHADER)
{
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DLod", sampler2D, float2, float1);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLod", sampler2D, float3, float1);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLod", sampler2D, float4, float1);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCubeLod", samplerCube, float3, float1);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DLod", sampler2D, float2,
+ float1);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLod", sampler2D, float3,
+ float1);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLod", sampler2D, float4,
+ float1);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCubeLod", samplerCube, float3,
+ float1);
}
const TType *gvec4 = TCache::getType(EbtGVec4);
- const TType *gsampler2D = TCache::getType(EbtGSampler2D);
- const TType *gsamplerCube = TCache::getType(EbtGSamplerCube);
- const TType *gsampler3D = TCache::getType(EbtGSampler3D);
+ const TType *gsampler2D = TCache::getType(EbtGSampler2D);
+ const TType *gsamplerCube = TCache::getType(EbtGSamplerCube);
+ const TType *gsampler3D = TCache::getType(EbtGSampler3D);
const TType *gsampler2DArray = TCache::getType(EbtGSampler2DArray);
+ const TType *gsampler2DMS = TCache::getType(EbtGSampler2DMS);
//
// Texture Functions for GLSL ES 3.0
@@ -315,32 +380,91 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsamplerCube, float3, float1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler2DArray, float3, float1);
+ if (resources.OES_EGL_image_external_essl3)
+ {
+ const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES);
+
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "texture", samplerExternalOES, float2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "textureProj", samplerExternalOES,
+ float3);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "textureProj", samplerExternalOES,
+ float4);
+ }
+
+ if (resources.EXT_YUV_target)
+ {
+ const TType *samplerExternal2DY2YEXT = TCache::getType(EbtSamplerExternal2DY2YEXT);
+
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "texture",
+ samplerExternal2DY2YEXT, float2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "textureProj",
+ samplerExternal2DY2YEXT, float3);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "textureProj",
+ samplerExternal2DY2YEXT, float4);
+
+ const TType *yuvCscStandardEXT = TCache::getType(EbtYuvCscStandardEXT);
+
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float3, "rgb_2_yuv",
+ float3, yuvCscStandardEXT);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float3, "yuv_2_rgb",
+ float3, yuvCscStandardEXT);
+ }
+
if (type == GL_FRAGMENT_SHADER)
{
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2D, float2, float1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler3D, float3, float1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsamplerCube, float3, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2DArray, float3, float1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2DArray, float3,
+ float1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float3, float1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float4, float1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler3D, float4, float1);
+
+ if (resources.OES_EGL_image_external_essl3)
+ {
+ const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES);
+
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "texture", samplerExternalOES, float2,
+ float1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "textureProj", samplerExternalOES,
+ float3, float1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "textureProj", samplerExternalOES,
+ float4, float1);
+ }
+
+ if (resources.EXT_YUV_target)
+ {
+ const TType *samplerExternal2DY2YEXT = TCache::getType(EbtSamplerExternal2DY2YEXT);
+
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "texture",
+ samplerExternal2DY2YEXT, float2, float1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4,
+ "textureProj", samplerExternal2DY2YEXT, float3, float1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4,
+ "textureProj", samplerExternal2DY2YEXT, float4, float1);
+ }
}
- const TType *sampler2DShadow = TCache::getType(EbtSampler2DShadow);
- const TType *samplerCubeShadow = TCache::getType(EbtSamplerCubeShadow);
+ const TType *sampler2DShadow = TCache::getType(EbtSampler2DShadow);
+ const TType *samplerCubeShadow = TCache::getType(EbtSamplerCubeShadow);
const TType *sampler2DArrayShadow = TCache::getType(EbtSampler2DArrayShadow);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", sampler2DShadow, float3);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", samplerCubeShadow, float4);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", sampler2DArrayShadow, float4);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProj", sampler2DShadow, float4);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureLod", sampler2DShadow, float3, float1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureLod", sampler2DShadow, float3,
+ float1);
if (type == GL_FRAGMENT_SHADER)
{
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", sampler2DShadow, float3, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", samplerCubeShadow, float4, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProj", sampler2DShadow, float4, float1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", sampler2DShadow, float3,
+ float1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", samplerCubeShadow, float4,
+ float1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProj", sampler2DShadow, float4,
+ float1);
}
symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", gsampler2D, int1);
@@ -350,135 +474,398 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", sampler2DShadow, int1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", samplerCubeShadow, int1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, int3, "textureSize", sampler2DArrayShadow, int1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", gsampler2DMS);
+
+ if (resources.OES_EGL_image_external_essl3)
+ {
+ const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES);
+
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", samplerExternalOES, int1);
+ }
+
+ if (resources.EXT_YUV_target)
+ {
+ const TType *samplerExternal2DY2YEXT = TCache::getType(EbtSamplerExternal2DY2YEXT);
+
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, int2, "textureSize",
+ samplerExternal2DY2YEXT, int1);
+ }
if (type == GL_FRAGMENT_SHADER)
{
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDFdx, genType, "dFdx", genType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDFdy, genType, "dFdy", genType);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpFwidth, genType, "fwidth", genType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDFdx, genType, genType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpDFdy, genType, genType);
+ symbolTable.insertBuiltInOp(ESSL3_BUILTINS, EOpFwidth, genType, genType);
}
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2D, float2, int2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler3D, float3, int3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureOffset", sampler2DShadow, float3, int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2DArray, float3, int2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureOffset", sampler2DShadow, float3,
+ int2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2DArray, float3,
+ int2);
if (type == GL_FRAGMENT_SHADER)
{
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2D, float2, int2, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler3D, float3, int3, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureOffset", sampler2DShadow, float3, int2, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2DArray, float3, int2, float1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2D, float2, int2,
+ float1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler3D, float3, int3,
+ float1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureOffset", sampler2DShadow, float3,
+ int2, float1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2DArray, float3,
+ int2, float1);
}
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float3, int2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float4, int2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler3D, float4, int3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjOffset", sampler2DShadow, float4, int2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjOffset", sampler2DShadow, float4,
+ int2);
if (type == GL_FRAGMENT_SHADER)
{
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float3, int2, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float4, int2, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler3D, float4, int3, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjOffset", sampler2DShadow, float4, int2, float1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float3,
+ int2, float1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float4,
+ int2, float1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler3D, float4,
+ int3, float1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjOffset", sampler2DShadow,
+ float4, int2, float1);
}
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLodOffset", gsampler2D, float2, float1, int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLodOffset", gsampler3D, float3, float1, int3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureLodOffset", sampler2DShadow, float3, float1, int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLodOffset", gsampler2DArray, float3, float1, int2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLodOffset", gsampler2D, float2, float1,
+ int2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLodOffset", gsampler3D, float3, float1,
+ int3);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureLodOffset", sampler2DShadow, float3,
+ float1, int2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLodOffset", gsampler2DArray, float3,
+ float1, int2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLod", gsampler2D, float3, float1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLod", gsampler2D, float4, float1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLod", gsampler3D, float4, float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjLod", sampler2DShadow, float4, float1);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLodOffset", gsampler2D, float3, float1, int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLodOffset", gsampler2D, float4, float1, int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLodOffset", gsampler3D, float4, float1, int3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjLodOffset", sampler2DShadow, float4, float1, int2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjLod", sampler2DShadow, float4,
+ float1);
+
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLodOffset", gsampler2D, float3,
+ float1, int2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLodOffset", gsampler2D, float4,
+ float1, int2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLodOffset", gsampler3D, float4,
+ float1, int3);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjLodOffset", sampler2DShadow,
+ float4, float1, int2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetch", gsampler2D, int2, int1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetch", gsampler3D, int3, int1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetch", gsampler2DArray, int3, int1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler2D, int2, int1, int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler3D, int3, int1, int3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler2DArray, int3, int1, int2);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsampler2D, float2, float2, float2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsampler3D, float3, float3, float3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsamplerCube, float3, float3, float3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGrad", sampler2DShadow, float3, float2, float2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGrad", samplerCubeShadow, float4, float3, float3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsampler2DArray, float3, float2, float2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGrad", sampler2DArrayShadow, float4, float2, float2);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGradOffset", gsampler2D, float2, float2, float2, int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGradOffset", gsampler3D, float3, float3, float3, int3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGradOffset", sampler2DShadow, float3, float2, float2, int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGradOffset", gsampler2DArray, float3, float2, float2, int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGradOffset", sampler2DArrayShadow, float4, float2, float2, int2);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGrad", gsampler2D, float3, float2, float2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGrad", gsampler2D, float4, float2, float2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGrad", gsampler3D, float4, float3, float3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjGrad", sampler2DShadow, float4, float2, float2);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGradOffset", gsampler2D, float3, float2, float2, int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGradOffset", gsampler2D, float4, float2, float2, int2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGradOffset", gsampler3D, float4, float3, float3, int3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjGradOffset", sampler2DShadow, float4, float2, float2, int2);
+ if (resources.OES_EGL_image_external_essl3)
+ {
+ const TType *samplerExternalOES = TCache::getType(EbtSamplerExternalOES);
+
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "texelFetch", samplerExternalOES, int2,
+ int1);
+ }
+
+ if (resources.EXT_YUV_target)
+ {
+ const TType *samplerExternal2DY2YEXT = TCache::getType(EbtSamplerExternal2DY2YEXT);
+
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, TExtension::EXT_YUV_target, float4, "texelFetch",
+ samplerExternal2DY2YEXT, int2, int1);
+ }
+
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler2D, int2, int1,
+ int2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler3D, int3, int1,
+ int3);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler2DArray, int3,
+ int1, int2);
+
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsampler2D, float2, float2,
+ float2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsampler3D, float3, float3,
+ float3);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsamplerCube, float3, float3,
+ float3);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGrad", sampler2DShadow, float3,
+ float2, float2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGrad", samplerCubeShadow, float4,
+ float3, float3);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsampler2DArray, float3, float2,
+ float2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGrad", sampler2DArrayShadow, float4,
+ float2, float2);
+
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGradOffset", gsampler2D, float2,
+ float2, float2, int2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGradOffset", gsampler3D, float3,
+ float3, float3, int3);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGradOffset", sampler2DShadow, float3,
+ float2, float2, int2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGradOffset", gsampler2DArray, float3,
+ float2, float2, int2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGradOffset", sampler2DArrayShadow,
+ float4, float2, float2, int2);
+
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGrad", gsampler2D, float3, float2,
+ float2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGrad", gsampler2D, float4, float2,
+ float2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGrad", gsampler3D, float4, float3,
+ float3);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjGrad", sampler2DShadow, float4,
+ float2, float2);
+
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGradOffset", gsampler2D, float3,
+ float2, float2, int2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGradOffset", gsampler2D, float4,
+ float2, float2, int2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGradOffset", gsampler3D, float4,
+ float3, float3, int3);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjGradOffset", sampler2DShadow,
+ float4, float2, float2, int2);
+
+ const TType *atomicCounter = TCache::getType(EbtAtomicCounter);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicCounter", atomicCounter);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicCounterIncrement", atomicCounter);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicCounterDecrement", atomicCounter);
+
+ // Insert all atomic memory functions
+ const TType *int1InOut = TCache::getType(EbtInt, EvqInOut);
+ const TType *uint1InOut = TCache::getType(EbtUInt, EvqInOut);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicAdd", uint1InOut, uint1);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicAdd", int1InOut, int1);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicMin", uint1InOut, uint1);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicMin", int1InOut, int1);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicMax", uint1InOut, uint1);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicMax", int1InOut, int1);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicAnd", uint1InOut, uint1);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicAnd", int1InOut, int1);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicOr", uint1InOut, uint1);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicOr", int1InOut, int1);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicXor", uint1InOut, uint1);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicXor", int1InOut, int1);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicExchange", uint1InOut, uint1);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicExchange", int1InOut, int1);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicCompSwap", uint1InOut, uint1, uint1);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int1, "atomicCompSwap", int1InOut, int1, int1);
+
+ const TType *gimage2D = TCache::getType(EbtGImage2D);
+ const TType *gimage3D = TCache::getType(EbtGImage3D);
+ const TType *gimage2DArray = TCache::getType(EbtGImage2DArray);
+ const TType *gimageCube = TCache::getType(EbtGImageCube);
+
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimage2D, int2, gvec4);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimage3D, int3, gvec4);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimage2DArray, int3, gvec4);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, voidType, "imageStore", gimageCube, int3, gvec4);
+
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimage2D, int2);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimage3D, int3);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimage2DArray, int3);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "imageLoad", gimageCube, int3);
+
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int2, "imageSize", gimage2D);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int3, "imageSize", gimage3D);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int3, "imageSize", gimage2DArray);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, int2, "imageSize", gimageCube);
+
+ symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrier, voidType,
+ "memoryBarrier");
+ symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrierAtomicCounter,
+ voidType, "memoryBarrierAtomicCounter");
+ symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrierBuffer,
+ voidType, "memoryBarrierBuffer");
+ symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrierImage, voidType,
+ "memoryBarrierImage");
+
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "texelFetch", gsampler2DMS, int2, int1);
+
+ // Insert all variations of textureGather.
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGather", gsampler2D, float2);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGather", gsampler2D, float2, int1);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGather", gsampler2DArray, float3);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGather", gsampler2DArray, float3,
+ int1);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGather", gsamplerCube, float3);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGather", gsamplerCube, float3, int1);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGather", sampler2DShadow, float2);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGather", sampler2DShadow, float2,
+ float1);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGather", sampler2DArrayShadow,
+ float3);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGather", sampler2DArrayShadow,
+ float3, float1);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGather", samplerCubeShadow, float3);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGather", samplerCubeShadow, float3,
+ float1);
+
+ // Insert all variations of textureGatherOffset.
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGatherOffset", gsampler2D, float2,
+ int2);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGatherOffset", gsampler2D, float2,
+ int2, int1);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGatherOffset", gsampler2DArray,
+ float3, int2);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, gvec4, "textureGatherOffset", gsampler2DArray,
+ float3, int2, int1);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGatherOffset", sampler2DShadow,
+ float2, float1, int2);
+ symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, float4, "textureGatherOffset", sampler2DArrayShadow,
+ float3, float1, int2);
+
+ if (type == GL_COMPUTE_SHADER)
+ {
+ symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpBarrier, voidType,
+ "barrier");
+ symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpMemoryBarrierShared,
+ voidType, "memoryBarrierShared");
+ symbolTable.insertBuiltInFunctionNoParameters(ESSL3_1_BUILTINS, EOpGroupMemoryBarrier,
+ voidType, "groupMemoryBarrier");
+ }
+
+ if (type == GL_GEOMETRY_SHADER_OES)
+ {
+ TExtension extension = TExtension::OES_geometry_shader;
+ symbolTable.insertBuiltInFunctionNoParametersExt(ESSL3_1_BUILTINS, extension, EOpEmitVertex,
+ voidType, "EmitVertex");
+ symbolTable.insertBuiltInFunctionNoParametersExt(ESSL3_1_BUILTINS, extension,
+ EOpEndPrimitive, voidType, "EndPrimitive");
+ }
//
// Depth range in window coordinates
//
- TFieldList *fields = NewPoolTFieldList();
+ TFieldList *fields = NewPoolTFieldList();
TSourceLoc zeroSourceLoc = {0, 0, 0, 0};
- TField *near = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("near"), zeroSourceLoc);
- TField *far = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("far"), zeroSourceLoc);
- TField *diff = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("diff"), zeroSourceLoc);
+ auto highpFloat1 = new TType(EbtFloat, EbpHigh, EvqGlobal, 1);
+ TField *near = new TField(highpFloat1, NewPoolTString("near"), zeroSourceLoc);
+ TField *far = new TField(highpFloat1, NewPoolTString("far"), zeroSourceLoc);
+ TField *diff = new TField(highpFloat1, NewPoolTString("diff"), zeroSourceLoc);
fields->push_back(near);
fields->push_back(far);
fields->push_back(diff);
- TStructure *depthRangeStruct = new TStructure(NewPoolTString("gl_DepthRangeParameters"), fields);
- TVariable *depthRangeParameters = new TVariable(&depthRangeStruct->name(), depthRangeStruct, true);
- symbolTable.insert(COMMON_BUILTINS, depthRangeParameters);
- TVariable *depthRange = new TVariable(NewPoolTString("gl_DepthRange"), TType(depthRangeStruct));
- depthRange->setQualifier(EvqUniform);
- symbolTable.insert(COMMON_BUILTINS, depthRange);
+ TStructure *depthRangeStruct =
+ new TStructure(&symbolTable, NewPoolTString("gl_DepthRangeParameters"), fields);
+ symbolTable.insertStructType(COMMON_BUILTINS, depthRangeStruct);
+ TType depthRangeType(depthRangeStruct);
+ depthRangeType.setQualifier(EvqUniform);
+ symbolTable.insertVariable(COMMON_BUILTINS, "gl_DepthRange", depthRangeType);
//
// Implementation dependent built-in constants.
//
- symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexAttribs", resources.MaxVertexAttribs);
- symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexUniformVectors", resources.MaxVertexUniformVectors);
- symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexTextureImageUnits", resources.MaxVertexTextureImageUnits);
- symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxCombinedTextureImageUnits", resources.MaxCombinedTextureImageUnits);
- symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxTextureImageUnits", resources.MaxTextureImageUnits);
- symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxFragmentUniformVectors", resources.MaxFragmentUniformVectors);
-
- symbolTable.insertConstInt(ESSL1_BUILTINS, "gl_MaxVaryingVectors", resources.MaxVaryingVectors);
-
- if (spec != SH_CSS_SHADERS_SPEC)
+ symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexAttribs", resources.MaxVertexAttribs,
+ EbpMedium);
+ symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexUniformVectors",
+ resources.MaxVertexUniformVectors, EbpMedium);
+ symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexTextureImageUnits",
+ resources.MaxVertexTextureImageUnits, EbpMedium);
+ symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxCombinedTextureImageUnits",
+ resources.MaxCombinedTextureImageUnits, EbpMedium);
+ symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxTextureImageUnits",
+ resources.MaxTextureImageUnits, EbpMedium);
+ symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxFragmentUniformVectors",
+ resources.MaxFragmentUniformVectors, EbpMedium);
+
+ symbolTable.insertConstInt(ESSL1_BUILTINS, "gl_MaxVaryingVectors", resources.MaxVaryingVectors,
+ EbpMedium);
+
+ symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxDrawBuffers", resources.MaxDrawBuffers,
+ EbpMedium);
+ if (resources.EXT_blend_func_extended)
{
- symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxDrawBuffers", resources.MaxDrawBuffers);
- if (resources.EXT_blend_func_extended)
- {
- symbolTable.insertConstIntExt(COMMON_BUILTINS, "GL_EXT_blend_func_extended",
- "gl_MaxDualSourceDrawBuffersEXT",
- resources.MaxDualSourceDrawBuffers);
- }
+ symbolTable.insertConstIntExt(COMMON_BUILTINS, TExtension::EXT_blend_func_extended,
+ "gl_MaxDualSourceDrawBuffersEXT",
+ resources.MaxDualSourceDrawBuffers, EbpMedium);
}
- symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxVertexOutputVectors", resources.MaxVertexOutputVectors);
- symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxFragmentInputVectors", resources.MaxFragmentInputVectors);
- symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MinProgramTexelOffset", resources.MinProgramTexelOffset);
- symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxProgramTexelOffset", resources.MaxProgramTexelOffset);
+ symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxVertexOutputVectors",
+ resources.MaxVertexOutputVectors, EbpMedium);
+ symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxFragmentInputVectors",
+ resources.MaxFragmentInputVectors, EbpMedium);
+ symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MinProgramTexelOffset",
+ resources.MinProgramTexelOffset, EbpMedium);
+ symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxProgramTexelOffset",
+ resources.MaxProgramTexelOffset, EbpMedium);
+
+ symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxImageUnits", resources.MaxImageUnits,
+ EbpMedium);
+ symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxVertexImageUniforms",
+ resources.MaxVertexImageUniforms, EbpMedium);
+ symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxFragmentImageUniforms",
+ resources.MaxFragmentImageUniforms, EbpMedium);
+ symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeImageUniforms",
+ resources.MaxComputeImageUniforms, EbpMedium);
+ symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxCombinedImageUniforms",
+ resources.MaxCombinedImageUniforms, EbpMedium);
+
+ symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxCombinedShaderOutputResources",
+ resources.MaxCombinedShaderOutputResources, EbpMedium);
+
+ symbolTable.insertConstIvec3(ESSL3_1_BUILTINS, "gl_MaxComputeWorkGroupCount",
+ resources.MaxComputeWorkGroupCount, EbpHigh);
+ symbolTable.insertConstIvec3(ESSL3_1_BUILTINS, "gl_MaxComputeWorkGroupSize",
+ resources.MaxComputeWorkGroupSize, EbpHigh);
+ symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeUniformComponents",
+ resources.MaxComputeUniformComponents, EbpMedium);
+ symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeTextureImageUnits",
+ resources.MaxComputeTextureImageUnits, EbpMedium);
+
+ symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeAtomicCounters",
+ resources.MaxComputeAtomicCounters, EbpMedium);
+ symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxComputeAtomicCounterBuffers",
+ resources.MaxComputeAtomicCounterBuffers, EbpMedium);
+
+ symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxVertexAtomicCounters",
+ resources.MaxVertexAtomicCounters, EbpMedium);
+ symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxFragmentAtomicCounters",
+ resources.MaxFragmentAtomicCounters, EbpMedium);
+ symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxCombinedAtomicCounters",
+ resources.MaxCombinedAtomicCounters, EbpMedium);
+ symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxAtomicCounterBindings",
+ resources.MaxAtomicCounterBindings, EbpMedium);
+
+ symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxVertexAtomicCounterBuffers",
+ resources.MaxVertexAtomicCounterBuffers, EbpMedium);
+ symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxFragmentAtomicCounterBuffers",
+ resources.MaxFragmentAtomicCounterBuffers, EbpMedium);
+ symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxCombinedAtomicCounterBuffers",
+ resources.MaxCombinedAtomicCounterBuffers, EbpMedium);
+ symbolTable.insertConstInt(ESSL3_1_BUILTINS, "gl_MaxAtomicCounterBufferSize",
+ resources.MaxAtomicCounterBufferSize, EbpMedium);
+
+ if (resources.OES_geometry_shader)
+ {
+ TExtension ext = TExtension::OES_geometry_shader;
+ symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryInputComponents",
+ resources.MaxGeometryInputComponents, EbpMedium);
+ symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryOutputComponents",
+ resources.MaxGeometryOutputComponents, EbpMedium);
+ symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryImageUniforms",
+ resources.MaxGeometryImageUniforms, EbpMedium);
+ symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryTextureImageUnits",
+ resources.MaxGeometryTextureImageUnits, EbpMedium);
+ symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryOutputVertices",
+ resources.MaxGeometryOutputVertices, EbpMedium);
+ symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryTotalOutputComponents",
+ resources.MaxGeometryTotalOutputComponents, EbpMedium);
+ symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryUniformComponents",
+ resources.MaxGeometryUniformComponents, EbpMedium);
+ symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryAtomicCounters",
+ resources.MaxGeometryAtomicCounters, EbpMedium);
+ symbolTable.insertConstIntExt(ESSL3_1_BUILTINS, ext, "gl_MaxGeometryAtomicCounterBuffers",
+ resources.MaxGeometryAtomicCounterBuffers, EbpMedium);
+ }
}
-void IdentifyBuiltIns(sh::GLenum type, ShShaderSpec spec,
+void IdentifyBuiltIns(sh::GLenum type,
+ ShShaderSpec spec,
const ShBuiltInResources &resources,
TSymbolTable &symbolTable)
{
@@ -486,136 +873,263 @@ void IdentifyBuiltIns(sh::GLenum type, ShShaderSpec spec,
// Insert some special built-in variables that are not in
// the built-in header files.
//
+
+ if (resources.OVR_multiview && type != GL_COMPUTE_SHADER)
+ {
+ symbolTable.insertVariableExt(ESSL3_BUILTINS, TExtension::OVR_multiview, "gl_ViewID_OVR",
+ TType(EbtUInt, EbpHigh, EvqViewIDOVR, 1));
+
+ // ESSL 1.00 doesn't have unsigned integers, so gl_ViewID_OVR is a signed integer in ESSL
+ // 1.00. This is specified in the WEBGL_multiview spec.
+ symbolTable.insertVariableExt(ESSL1_BUILTINS, TExtension::OVR_multiview, "gl_ViewID_OVR",
+ TType(EbtInt, EbpHigh, EvqViewIDOVR, 1));
+ }
+
switch (type)
{
- case GL_FRAGMENT_SHADER:
- symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FragCoord"),
- TType(EbtFloat, EbpMedium, EvqFragCoord, 4)));
- symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FrontFacing"),
- TType(EbtBool, EbpUndefined, EvqFrontFacing, 1)));
- symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointCoord"),
- TType(EbtFloat, EbpMedium, EvqPointCoord, 2)));
-
- //
- // In CSS Shaders, gl_FragColor, gl_FragData, and gl_MaxDrawBuffers are not available.
- // Instead, css_MixColor and css_ColorMatrix are available.
- //
- if (spec != SH_CSS_SHADERS_SPEC)
+ case GL_FRAGMENT_SHADER:
{
- symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragColor"),
- TType(EbtFloat, EbpMedium, EvqFragColor, 4)));
- TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, 1, true);
- fragData.setArraySize(resources.MaxDrawBuffers);
- symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragData"), fragData));
+ symbolTable.insertVariable(COMMON_BUILTINS, "gl_FragCoord",
+ TType(EbtFloat, EbpMedium, EvqFragCoord, 4));
+ symbolTable.insertVariable(COMMON_BUILTINS, "gl_FrontFacing",
+ TType(EbtBool, EbpUndefined, EvqFrontFacing, 1));
+ symbolTable.insertVariable(COMMON_BUILTINS, "gl_PointCoord",
+ TType(EbtFloat, EbpMedium, EvqPointCoord, 2));
+
+ symbolTable.insertVariable(ESSL1_BUILTINS, "gl_FragColor",
+ TType(EbtFloat, EbpMedium, EvqFragColor, 4));
+ TType fragData(EbtFloat, EbpMedium, EvqFragData, 4);
+ if (spec != SH_WEBGL2_SPEC && spec != SH_WEBGL3_SPEC)
+ {
+ fragData.makeArray(resources.MaxDrawBuffers);
+ }
+ else
+ {
+ fragData.makeArray(1u);
+ }
+ symbolTable.insertVariable(ESSL1_BUILTINS, "gl_FragData", fragData);
if (resources.EXT_blend_func_extended)
{
- symbolTable.insert(
- ESSL1_BUILTINS, "GL_EXT_blend_func_extended",
- new TVariable(NewPoolTString("gl_SecondaryFragColorEXT"),
- TType(EbtFloat, EbpMedium, EvqSecondaryFragColorEXT, 4)));
- TType secondaryFragData(EbtFloat, EbpMedium, EvqSecondaryFragDataEXT, 4, 1, true);
- secondaryFragData.setArraySize(resources.MaxDualSourceDrawBuffers);
- symbolTable.insert(
- ESSL1_BUILTINS, "GL_EXT_blend_func_extended",
- new TVariable(NewPoolTString("gl_SecondaryFragDataEXT"), secondaryFragData));
+ symbolTable.insertVariableExt(
+ ESSL1_BUILTINS, TExtension::EXT_blend_func_extended, "gl_SecondaryFragColorEXT",
+ TType(EbtFloat, EbpMedium, EvqSecondaryFragColorEXT, 4));
+ TType secondaryFragData(EbtFloat, EbpMedium, EvqSecondaryFragDataEXT, 4, 1);
+ secondaryFragData.makeArray(resources.MaxDualSourceDrawBuffers);
+ symbolTable.insertVariableExt(ESSL1_BUILTINS, TExtension::EXT_blend_func_extended,
+ "gl_SecondaryFragDataEXT", secondaryFragData);
}
if (resources.EXT_frag_depth)
{
- symbolTable.insert(
- ESSL1_BUILTINS, "GL_EXT_frag_depth",
- new TVariable(
- NewPoolTString("gl_FragDepthEXT"),
- TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium,
- EvqFragDepthEXT, 1)));
+ symbolTable.insertVariableExt(
+ ESSL1_BUILTINS, TExtension::EXT_frag_depth, "gl_FragDepthEXT",
+ TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium,
+ EvqFragDepthEXT, 1));
}
- symbolTable.insert(ESSL3_BUILTINS,
- new TVariable(NewPoolTString("gl_FragDepth"),
- TType(EbtFloat, EbpHigh, EvqFragDepth, 1)));
+ symbolTable.insertVariable(ESSL3_BUILTINS, "gl_FragDepth",
+ TType(EbtFloat, EbpHigh, EvqFragDepth, 1));
if (resources.EXT_shader_framebuffer_fetch || resources.NV_shader_framebuffer_fetch)
{
- TType lastFragData(EbtFloat, EbpMedium, EvqLastFragData, 4, 1, true);
- lastFragData.setArraySize(resources.MaxDrawBuffers);
+ TType lastFragData(EbtFloat, EbpMedium, EvqLastFragData, 4, 1);
+ lastFragData.makeArray(resources.MaxDrawBuffers);
if (resources.EXT_shader_framebuffer_fetch)
{
- symbolTable.insert(ESSL1_BUILTINS, "GL_EXT_shader_framebuffer_fetch",
- new TVariable(NewPoolTString("gl_LastFragData"), lastFragData));
+ symbolTable.insertVariableExt(ESSL1_BUILTINS,
+ TExtension::EXT_shader_framebuffer_fetch,
+ "gl_LastFragData", lastFragData);
}
else if (resources.NV_shader_framebuffer_fetch)
{
- symbolTable.insert(ESSL1_BUILTINS, "GL_NV_shader_framebuffer_fetch",
- new TVariable(NewPoolTString("gl_LastFragColor"),
- TType(EbtFloat, EbpMedium, EvqLastFragColor, 4)));
- symbolTable.insert(ESSL1_BUILTINS, "GL_NV_shader_framebuffer_fetch",
- new TVariable(NewPoolTString("gl_LastFragData"), lastFragData));
+ symbolTable.insertVariableExt(
+ ESSL1_BUILTINS, TExtension::NV_shader_framebuffer_fetch, "gl_LastFragColor",
+ TType(EbtFloat, EbpMedium, EvqLastFragColor, 4));
+ symbolTable.insertVariableExt(ESSL1_BUILTINS,
+ TExtension::NV_shader_framebuffer_fetch,
+ "gl_LastFragData", lastFragData);
}
}
else if (resources.ARM_shader_framebuffer_fetch)
{
- symbolTable.insert(ESSL1_BUILTINS, "GL_ARM_shader_framebuffer_fetch",
- new TVariable(NewPoolTString("gl_LastFragColorARM"),
- TType(EbtFloat, EbpMedium, EvqLastFragColor, 4)));
+ symbolTable.insertVariableExt(
+ ESSL1_BUILTINS, TExtension::ARM_shader_framebuffer_fetch, "gl_LastFragColorARM",
+ TType(EbtFloat, EbpMedium, EvqLastFragColor, 4));
+ }
+
+ if (resources.OES_geometry_shader)
+ {
+ TExtension extension = TExtension::OES_geometry_shader;
+ symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_PrimitiveID",
+ TType(EbtInt, EbpHigh, EvqPrimitiveID, 1));
+ symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_Layer",
+ TType(EbtInt, EbpHigh, EvqLayer, 1));
}
+
+ break;
}
- else
+ case GL_VERTEX_SHADER:
{
- symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_MixColor"),
- TType(EbtFloat, EbpMedium, EvqGlobal, 4)));
- symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_ColorMatrix"),
- TType(EbtFloat, EbpMedium, EvqGlobal, 4, 4)));
+ symbolTable.insertVariable(COMMON_BUILTINS, "gl_Position",
+ TType(EbtFloat, EbpHigh, EvqPosition, 4));
+ symbolTable.insertVariable(COMMON_BUILTINS, "gl_PointSize",
+ TType(EbtFloat, EbpMedium, EvqPointSize, 1));
+ symbolTable.insertVariable(ESSL3_BUILTINS, "gl_InstanceID",
+ TType(EbtInt, EbpHigh, EvqInstanceID, 1));
+ symbolTable.insertVariable(ESSL3_BUILTINS, "gl_VertexID",
+ TType(EbtInt, EbpHigh, EvqVertexID, 1));
+
+ // For internal use by ANGLE - not exposed to the parser.
+ symbolTable.insertVariable(GLSL_BUILTINS, "gl_ViewportIndex",
+ TType(EbtInt, EbpHigh, EvqViewportIndex));
+ // gl_Layer exists in other shader stages in ESSL, but not in vertex shader so far.
+ symbolTable.insertVariable(GLSL_BUILTINS, "gl_Layer", TType(EbtInt, EbpHigh, EvqLayer));
+ break;
+ }
+ case GL_COMPUTE_SHADER:
+ {
+ symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_NumWorkGroups",
+ TType(EbtUInt, EbpUndefined, EvqNumWorkGroups, 3));
+ symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_WorkGroupSize",
+ TType(EbtUInt, EbpUndefined, EvqWorkGroupSize, 3));
+ symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_WorkGroupID",
+ TType(EbtUInt, EbpUndefined, EvqWorkGroupID, 3));
+ symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_LocalInvocationID",
+ TType(EbtUInt, EbpUndefined, EvqLocalInvocationID, 3));
+ symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_GlobalInvocationID",
+ TType(EbtUInt, EbpUndefined, EvqGlobalInvocationID, 3));
+ symbolTable.insertVariable(ESSL3_1_BUILTINS, "gl_LocalInvocationIndex",
+ TType(EbtUInt, EbpUndefined, EvqLocalInvocationIndex, 1));
+ break;
}
- break;
-
- case GL_VERTEX_SHADER:
- symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_Position"),
- TType(EbtFloat, EbpHigh, EvqPosition, 4)));
- symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointSize"),
- TType(EbtFloat, EbpMedium, EvqPointSize, 1)));
- symbolTable.insert(ESSL3_BUILTINS, new TVariable(NewPoolTString("gl_InstanceID"),
- TType(EbtInt, EbpHigh, EvqInstanceID, 1)));
- break;
-
- default:
- assert(false && "Language not supported");
+ case GL_GEOMETRY_SHADER_OES:
+ {
+ TExtension extension = TExtension::OES_geometry_shader;
+
+ // Add built-in interface block gl_PerVertex and the built-in array gl_in.
+ // TODO(jiawei.shao@intel.com): implement GL_OES_geometry_point_size.
+ const TString *glPerVertexString = NewPoolTString("gl_PerVertex");
+ symbolTable.insertInterfaceBlockNameExt(ESSL3_1_BUILTINS, extension, glPerVertexString);
+
+ TFieldList *fieldList = NewPoolTFieldList();
+ TSourceLoc zeroSourceLoc = {0, 0, 0, 0};
+ TField *glPositionField = new TField(new TType(EbtFloat, EbpHigh, EvqPosition, 4),
+ NewPoolTString("gl_Position"), zeroSourceLoc);
+ fieldList->push_back(glPositionField);
+
+ TInterfaceBlock *glInBlock = new TInterfaceBlock(
+ glPerVertexString, fieldList, NewPoolTString("gl_in"), TLayoutQualifier::Create());
+
+ // The array size of gl_in is undefined until we get a valid input primitive
+ // declaration.
+ TType glInType(glInBlock, EvqPerVertexIn, TLayoutQualifier::Create());
+ glInType.makeArray(0u);
+ symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_in", glInType);
+
+ TType glPositionType(EbtFloat, EbpHigh, EvqPosition, 4);
+ glPositionType.setInterfaceBlock(new TInterfaceBlock(
+ glPerVertexString, fieldList, nullptr, TLayoutQualifier::Create()));
+ symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_Position",
+ glPositionType);
+ symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_PrimitiveIDIn",
+ TType(EbtInt, EbpHigh, EvqPrimitiveIDIn, 1));
+ symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_InvocationID",
+ TType(EbtInt, EbpHigh, EvqInvocationID, 1));
+ symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_PrimitiveID",
+ TType(EbtInt, EbpHigh, EvqPrimitiveID, 1));
+ symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_Layer",
+ TType(EbtInt, EbpHigh, EvqLayer, 1));
+
+ break;
+ }
+ default:
+ UNREACHABLE();
}
}
-void InitExtensionBehavior(const ShBuiltInResources& resources,
- TExtensionBehavior& extBehavior)
+void InitExtensionBehavior(const ShBuiltInResources &resources, TExtensionBehavior &extBehavior)
{
if (resources.OES_standard_derivatives)
- extBehavior["GL_OES_standard_derivatives"] = EBhUndefined;
+ {
+ extBehavior[TExtension::OES_standard_derivatives] = EBhUndefined;
+ }
if (resources.OES_EGL_image_external)
- extBehavior["GL_OES_EGL_image_external"] = EBhUndefined;
+ {
+ extBehavior[TExtension::OES_EGL_image_external] = EBhUndefined;
+ }
+ if (resources.OES_EGL_image_external_essl3)
+ {
+ extBehavior[TExtension::OES_EGL_image_external_essl3] = EBhUndefined;
+ }
+ if (resources.NV_EGL_stream_consumer_external)
+ {
+ extBehavior[TExtension::NV_EGL_stream_consumer_external] = EBhUndefined;
+ }
if (resources.ARB_texture_rectangle)
- extBehavior["GL_ARB_texture_rectangle"] = EBhUndefined;
+ {
+ // Special: ARB_texture_rectangle extension does not follow the standard for #extension
+ // directives - it is enabled by default. An extension directive may still disable it.
+ extBehavior[TExtension::ARB_texture_rectangle] = EBhEnable;
+ }
if (resources.EXT_blend_func_extended)
- extBehavior["GL_EXT_blend_func_extended"] = EBhUndefined;
+ {
+ extBehavior[TExtension::EXT_blend_func_extended] = EBhUndefined;
+ }
if (resources.EXT_draw_buffers)
- extBehavior["GL_EXT_draw_buffers"] = EBhUndefined;
+ {
+ extBehavior[TExtension::EXT_draw_buffers] = EBhUndefined;
+ }
if (resources.EXT_frag_depth)
- extBehavior["GL_EXT_frag_depth"] = EBhUndefined;
+ {
+ extBehavior[TExtension::EXT_frag_depth] = EBhUndefined;
+ }
if (resources.EXT_shader_texture_lod)
- extBehavior["GL_EXT_shader_texture_lod"] = EBhUndefined;
+ {
+ extBehavior[TExtension::EXT_shader_texture_lod] = EBhUndefined;
+ }
if (resources.EXT_shader_framebuffer_fetch)
- extBehavior["GL_EXT_shader_framebuffer_fetch"] = EBhUndefined;
+ {
+ extBehavior[TExtension::EXT_shader_framebuffer_fetch] = EBhUndefined;
+ }
if (resources.NV_shader_framebuffer_fetch)
- extBehavior["GL_NV_shader_framebuffer_fetch"] = EBhUndefined;
+ {
+ extBehavior[TExtension::NV_shader_framebuffer_fetch] = EBhUndefined;
+ }
if (resources.ARM_shader_framebuffer_fetch)
- extBehavior["GL_ARM_shader_framebuffer_fetch"] = EBhUndefined;
+ {
+ extBehavior[TExtension::ARM_shader_framebuffer_fetch] = EBhUndefined;
+ }
+ if (resources.OVR_multiview)
+ {
+ extBehavior[TExtension::OVR_multiview] = EBhUndefined;
+ }
+ if (resources.EXT_YUV_target)
+ {
+ extBehavior[TExtension::EXT_YUV_target] = EBhUndefined;
+ }
+ if (resources.OES_geometry_shader)
+ {
+ extBehavior[TExtension::OES_geometry_shader] = EBhUndefined;
+ extBehavior[TExtension::EXT_geometry_shader] = EBhUndefined;
+ }
}
void ResetExtensionBehavior(TExtensionBehavior &extBehavior)
{
- for (auto ext_iter = extBehavior.begin();
- ext_iter != extBehavior.end();
- ++ext_iter)
+ for (auto &ext : extBehavior)
{
- ext_iter->second = EBhUndefined;
+ if (ext.first == TExtension::ARB_texture_rectangle)
+ {
+ ext.second = EBhEnable;
+ }
+ else
+ {
+ ext.second = EBhUndefined;
+ }
}
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/Initialize.h b/src/3rdparty/angle/src/compiler/translator/Initialize.h
index c43ce3417a..2e61218a0f 100644
--- a/src/3rdparty/angle/src/compiler/translator/Initialize.h
+++ b/src/3rdparty/angle/src/compiler/translator/Initialize.h
@@ -11,14 +11,21 @@
#include "compiler/translator/Compiler.h"
#include "compiler/translator/SymbolTable.h"
-void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &table);
+namespace sh
+{
-void IdentifyBuiltIns(sh::GLenum type, ShShaderSpec spec,
- const ShBuiltInResources& resources,
- TSymbolTable& symbolTable);
+void InsertBuiltInFunctions(sh::GLenum type,
+ ShShaderSpec spec,
+ const ShBuiltInResources &resources,
+ TSymbolTable &table);
-void InitExtensionBehavior(const ShBuiltInResources& resources,
- TExtensionBehavior& extensionBehavior);
+void IdentifyBuiltIns(sh::GLenum type,
+ ShShaderSpec spec,
+ const ShBuiltInResources &resources,
+ TSymbolTable &symbolTable);
+
+void InitExtensionBehavior(const ShBuiltInResources &resources,
+ TExtensionBehavior &extensionBehavior);
// Resets the behavior of the extensions listed in |extensionBehavior| to the
// undefined state. These extensions will only be those initially supported in
@@ -26,4 +33,6 @@ void InitExtensionBehavior(const ShBuiltInResources& resources,
// extensions will remain unsupported.
void ResetExtensionBehavior(TExtensionBehavior &extensionBehavior);
-#endif // COMPILER_TRANSLATOR_INITIALIZE_H_
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_INITIALIZE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp b/src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp
index 713965389f..43c215f52b 100644
--- a/src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp
@@ -7,24 +7,22 @@
#include "compiler/translator/Cache.h"
#include "compiler/translator/InitializeDll.h"
#include "compiler/translator/InitializeGlobals.h"
-#include "compiler/translator/InitializeParseContext.h"
#include "common/platform.h"
#include <assert.h>
+namespace sh
+{
+
bool InitProcess()
{
- if (!InitializePoolIndex()) {
+ if (!InitializePoolIndex())
+ {
assert(0 && "InitProcess(): Failed to initalize global pool");
return false;
}
- if (!InitializeParseContextIndex()) {
- assert(0 && "InitProcess(): Failed to initalize parse context");
- return false;
- }
-
TCache::initialize();
return true;
@@ -32,7 +30,8 @@ bool InitProcess()
void DetachProcess()
{
- FreeParseContextIndex();
FreePoolIndex();
TCache::destroy();
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeDll.h b/src/3rdparty/angle/src/compiler/translator/InitializeDll.h
index 4c400760f6..87f7251470 100644
--- a/src/3rdparty/angle/src/compiler/translator/InitializeDll.h
+++ b/src/3rdparty/angle/src/compiler/translator/InitializeDll.h
@@ -6,8 +6,10 @@
#ifndef COMPILER_TRANSLATOR_INITIALIZEDLL_H_
#define COMPILER_TRANSLATOR_INITIALIZEDLL_H_
+namespace sh
+{
bool InitProcess();
void DetachProcess();
+} // namespace sh
-#endif // COMPILER_TRANSLATOR_INITIALIZEDLL_H_
-
+#endif // COMPILER_TRANSLATOR_INITIALIZEDLL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h b/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h
index 8c65cb28da..9a67ed0e04 100644
--- a/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h
+++ b/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h
@@ -10,4 +10,4 @@
bool InitializePoolIndex();
void FreePoolIndex();
-#endif // COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_
+#endif // COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.cpp b/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.cpp
deleted file mode 100644
index c35cedb348..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/translator/InitializeParseContext.h"
-
-#include "common/tls.h"
-
-#include <assert.h>
-
-TLSIndex GlobalParseContextIndex = TLS_INVALID_INDEX;
-
-bool InitializeParseContextIndex()
-{
- assert(GlobalParseContextIndex == TLS_INVALID_INDEX);
-
- GlobalParseContextIndex = CreateTLSIndex();
- return GlobalParseContextIndex != TLS_INVALID_INDEX;
-}
-
-void FreeParseContextIndex()
-{
- assert(GlobalParseContextIndex != TLS_INVALID_INDEX);
-
- DestroyTLSIndex(GlobalParseContextIndex);
- GlobalParseContextIndex = TLS_INVALID_INDEX;
-}
-
-void SetGlobalParseContext(TParseContext* context)
-{
- assert(GlobalParseContextIndex != TLS_INVALID_INDEX);
- SetTLSValue(GlobalParseContextIndex, context);
-}
-
-TParseContext* GetGlobalParseContext()
-{
- assert(GlobalParseContextIndex != TLS_INVALID_INDEX);
- return static_cast<TParseContext*>(GetTLSValue(GlobalParseContextIndex));
-}
-
diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.h b/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.h
deleted file mode 100644
index 70dac702e2..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.h
+++ /dev/null
@@ -1,17 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_TRANSLATOR_INITIALIZEPARSECONTEXT_H_
-#define COMPILER_TRANSLATOR_INITIALIZEPARSECONTEXT_H_
-
-bool InitializeParseContextIndex();
-void FreeParseContextIndex();
-
-class TParseContext;
-extern void SetGlobalParseContext(TParseContext* context);
-extern TParseContext* GetGlobalParseContext();
-
-#endif // COMPILER_TRANSLATOR_INITIALIZEPARSECONTEXT_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp
index 86d3e6bc83..aa1a042fac 100644
--- a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp
@@ -6,112 +6,285 @@
#include "compiler/translator/InitializeVariables.h"
+#include "angle_gl.h"
#include "common/debug.h"
+#include "compiler/translator/FindMain.h"
+#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/IntermTraverse.h"
+#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/util.h"
+
+namespace sh
+{
namespace
{
-TIntermConstantUnion *constructFloatConstUnionNode(const TType &type)
+void AddArrayZeroInitSequence(const TIntermTyped *initializedNode,
+ bool canUseLoopsToInitialize,
+ TIntermSequence *initSequenceOut,
+ TSymbolTable *symbolTable);
+
+void AddStructZeroInitSequence(const TIntermTyped *initializedNode,
+ bool canUseLoopsToInitialize,
+ TIntermSequence *initSequenceOut,
+ TSymbolTable *symbolTable);
+
+TIntermBinary *CreateZeroInitAssignment(const TIntermTyped *initializedNode)
{
- TType myType = type;
- unsigned char size = static_cast<unsigned char>(myType.getNominalSize());
- if (myType.isMatrix())
- size *= size;
- TConstantUnion *u = new TConstantUnion[size];
- for (int ii = 0; ii < size; ++ii)
- u[ii].setFConst(0.0f);
-
- myType.clearArrayness();
- myType.setQualifier(EvqConst);
- TIntermConstantUnion *node = new TIntermConstantUnion(u, myType);
- return node;
+ TIntermTyped *zero = CreateZeroNode(initializedNode->getType());
+ return new TIntermBinary(EOpAssign, initializedNode->deepCopy(), zero);
}
-TIntermConstantUnion *constructIndexNode(int index)
+void AddZeroInitSequence(const TIntermTyped *initializedNode,
+ bool canUseLoopsToInitialize,
+ TIntermSequence *initSequenceOut,
+ TSymbolTable *symbolTable)
{
- TConstantUnion *u = new TConstantUnion[1];
- u[0].setIConst(index);
+ if (initializedNode->isArray())
+ {
+ AddArrayZeroInitSequence(initializedNode, canUseLoopsToInitialize, initSequenceOut,
+ symbolTable);
+ }
+ else if (initializedNode->getType().isStructureContainingArrays() ||
+ initializedNode->getType().isNamelessStruct())
+ {
+ AddStructZeroInitSequence(initializedNode, canUseLoopsToInitialize, initSequenceOut,
+ symbolTable);
+ }
+ else
+ {
+ initSequenceOut->push_back(CreateZeroInitAssignment(initializedNode));
+ }
+}
- TType type(EbtInt, EbpUndefined, EvqConst, 1);
- TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
- return node;
+void AddStructZeroInitSequence(const TIntermTyped *initializedNode,
+ bool canUseLoopsToInitialize,
+ TIntermSequence *initSequenceOut,
+ TSymbolTable *symbolTable)
+{
+ ASSERT(initializedNode->getBasicType() == EbtStruct);
+ const TStructure *structType = initializedNode->getType().getStruct();
+ for (int i = 0; i < static_cast<int>(structType->fields().size()); ++i)
+ {
+ TIntermBinary *element = new TIntermBinary(EOpIndexDirectStruct,
+ initializedNode->deepCopy(), CreateIndexNode(i));
+ // Structs can't be defined inside structs, so the type of a struct field can't be a
+ // nameless struct.
+ ASSERT(!element->getType().isNamelessStruct());
+ AddZeroInitSequence(element, canUseLoopsToInitialize, initSequenceOut, symbolTable);
+ }
}
-} // namespace anonymous
+void AddArrayZeroInitStatementList(const TIntermTyped *initializedNode,
+ bool canUseLoopsToInitialize,
+ TIntermSequence *initSequenceOut,
+ TSymbolTable *symbolTable)
+{
+ for (unsigned int i = 0; i < initializedNode->getOutermostArraySize(); ++i)
+ {
+ TIntermBinary *element =
+ new TIntermBinary(EOpIndexDirect, initializedNode->deepCopy(), CreateIndexNode(i));
+ AddZeroInitSequence(element, canUseLoopsToInitialize, initSequenceOut, symbolTable);
+ }
+}
-bool InitializeVariables::visitAggregate(Visit visit, TIntermAggregate *node)
+void AddArrayZeroInitForLoop(const TIntermTyped *initializedNode,
+ TIntermSequence *initSequenceOut,
+ TSymbolTable *symbolTable)
{
- bool visitChildren = !mCodeInserted;
- switch (node->getOp())
+ ASSERT(initializedNode->isArray());
+ TSymbolUniqueId indexSymbol(symbolTable);
+
+ TIntermSymbol *indexSymbolNode = CreateTempSymbolNode(indexSymbol, TType(EbtInt), EvqTemporary);
+ TIntermDeclaration *indexInit =
+ CreateTempInitDeclarationNode(indexSymbol, CreateZeroNode(TType(EbtInt)), EvqTemporary);
+ TIntermConstantUnion *arraySizeNode = CreateIndexNode(initializedNode->getOutermostArraySize());
+ TIntermBinary *indexSmallerThanSize =
+ new TIntermBinary(EOpLessThan, indexSymbolNode->deepCopy(), arraySizeNode);
+ TIntermUnary *indexIncrement = new TIntermUnary(EOpPreIncrement, indexSymbolNode->deepCopy());
+
+ TIntermBlock *forLoopBody = new TIntermBlock();
+ TIntermSequence *forLoopBodySeq = forLoopBody->getSequence();
+
+ TIntermBinary *element = new TIntermBinary(EOpIndexIndirect, initializedNode->deepCopy(),
+ indexSymbolNode->deepCopy());
+ AddZeroInitSequence(element, true, forLoopBodySeq, symbolTable);
+
+ TIntermLoop *forLoop =
+ new TIntermLoop(ELoopFor, indexInit, indexSmallerThanSize, indexIncrement, forLoopBody);
+ initSequenceOut->push_back(forLoop);
+}
+
+void AddArrayZeroInitSequence(const TIntermTyped *initializedNode,
+ bool canUseLoopsToInitialize,
+ TIntermSequence *initSequenceOut,
+ TSymbolTable *symbolTable)
+{
+ // The array elements are assigned one by one to keep the AST compatible with ESSL 1.00 which
+ // doesn't have array assignment. We'll do this either with a for loop or just a list of
+ // statements assigning to each array index. Note that it is important to have the array init in
+ // the right order to workaround http://crbug.com/709317
+ bool isSmallArray = initializedNode->getOutermostArraySize() <= 1u ||
+ (initializedNode->getBasicType() != EbtStruct &&
+ !initializedNode->getType().isArrayOfArrays() &&
+ initializedNode->getOutermostArraySize() <= 3u);
+ if (initializedNode->getQualifier() == EvqFragData ||
+ initializedNode->getQualifier() == EvqFragmentOut || isSmallArray ||
+ !canUseLoopsToInitialize)
+ {
+ // Fragment outputs should not be indexed by non-constant indices.
+ // Also it doesn't make sense to use loops to initialize very small arrays.
+ AddArrayZeroInitStatementList(initializedNode, canUseLoopsToInitialize, initSequenceOut,
+ symbolTable);
+ }
+ else
{
- case EOpSequence:
- break;
- case EOpFunction:
- {
- // Function definition.
- ASSERT(visit == PreVisit);
- if (node->getName() == "main(")
+ AddArrayZeroInitForLoop(initializedNode, initSequenceOut, symbolTable);
+ }
+}
+
+void InsertInitCode(TIntermSequence *mainBody,
+ const InitVariableList &variables,
+ TSymbolTable *symbolTable,
+ int shaderVersion,
+ const TExtensionBehavior &extensionBehavior,
+ bool canUseLoopsToInitialize)
+{
+ for (const auto &var : variables)
+ {
+ TString name = TString(var.name.c_str());
+ size_t pos = name.find_last_of('[');
+ if (pos != TString::npos)
{
- TIntermSequence *sequence = node->getSequence();
- ASSERT((sequence->size() == 1) || (sequence->size() == 2));
- TIntermAggregate *body = NULL;
- if (sequence->size() == 1)
- {
- body = new TIntermAggregate(EOpSequence);
- sequence->push_back(body);
- }
- else
+ name = name.substr(0, pos);
+ }
+
+ TIntermTyped *initializedSymbol = nullptr;
+ if (var.isBuiltIn())
+ {
+ initializedSymbol = ReferenceBuiltInVariable(name, *symbolTable, shaderVersion);
+ if (initializedSymbol->getQualifier() == EvqFragData &&
+ !IsExtensionEnabled(extensionBehavior, TExtension::EXT_draw_buffers))
{
- body = (*sequence)[1]->getAsAggregate();
+ // If GL_EXT_draw_buffers is disabled, only the 0th index of gl_FragData can be
+ // written to.
+ // TODO(oetuaho): This is a bit hacky and would be better to remove, if we came up
+ // with a good way to do it. Right now "gl_FragData" in symbol table is initialized
+ // to have the array size of MaxDrawBuffers, and the initialization happens before
+ // the shader sets the extensions it is using.
+ initializedSymbol =
+ new TIntermBinary(EOpIndexDirect, initializedSymbol, CreateIndexNode(0));
}
- ASSERT(body);
- insertInitCode(body->getSequence());
- mCodeInserted = true;
}
- break;
- }
- default:
- visitChildren = false;
- break;
+ else
+ {
+ initializedSymbol = ReferenceGlobalVariable(name, *symbolTable);
+ }
+ ASSERT(initializedSymbol != nullptr);
+
+ TIntermSequence *initCode =
+ CreateInitCode(initializedSymbol, canUseLoopsToInitialize, symbolTable);
+ mainBody->insert(mainBody->begin(), initCode->begin(), initCode->end());
}
- return visitChildren;
}
-void InitializeVariables::insertInitCode(TIntermSequence *sequence)
+class InitializeLocalsTraverser : public TIntermTraverser
{
- for (size_t ii = 0; ii < mVariables.size(); ++ii)
+ public:
+ InitializeLocalsTraverser(int shaderVersion,
+ TSymbolTable *symbolTable,
+ bool canUseLoopsToInitialize)
+ : TIntermTraverser(true, false, false, symbolTable),
+ mShaderVersion(shaderVersion),
+ mCanUseLoopsToInitialize(canUseLoopsToInitialize)
{
- const InitVariableInfo &varInfo = mVariables[ii];
+ }
- if (varInfo.type.isArray())
+ protected:
+ bool visitDeclaration(Visit visit, TIntermDeclaration *node) override
+ {
+ for (TIntermNode *declarator : *node->getSequence())
{
- for (int index = varInfo.type.getArraySize() - 1; index >= 0; --index)
+ if (!mInGlobalScope && !declarator->getAsBinaryNode())
{
- TIntermBinary *assign = new TIntermBinary(EOpAssign);
- sequence->insert(sequence->begin(), assign);
-
- TIntermBinary *indexDirect = new TIntermBinary(EOpIndexDirect);
- TIntermSymbol *symbol = new TIntermSymbol(0, varInfo.name, varInfo.type);
- indexDirect->setLeft(symbol);
- TIntermConstantUnion *indexNode = constructIndexNode(index);
- indexDirect->setRight(indexNode);
-
- assign->setLeft(indexDirect);
+ TIntermSymbol *symbol = declarator->getAsSymbolNode();
+ ASSERT(symbol);
+ if (symbol->getSymbol() == "")
+ {
+ continue;
+ }
- TIntermConstantUnion *zeroConst = constructFloatConstUnionNode(varInfo.type);
- assign->setRight(zeroConst);
+ // Arrays may need to be initialized one element at a time, since ESSL 1.00 does not
+ // support array constructors or assigning arrays.
+ bool arrayConstructorUnavailable =
+ (symbol->isArray() || symbol->getType().isStructureContainingArrays()) &&
+ mShaderVersion == 100;
+ // Nameless struct constructors can't be referred to, so they also need to be
+ // initialized one element at a time.
+ // TODO(oetuaho): Check if it makes sense to initialize using a loop, even if we
+ // could use an initializer. It could at least reduce code size for very large
+ // arrays, but could hurt runtime performance.
+ if (arrayConstructorUnavailable || symbol->getType().isNamelessStruct())
+ {
+ // SimplifyLoopConditions should have been run so the parent node of this node
+ // should not be a loop.
+ ASSERT(getParentNode()->getAsLoopNode() == nullptr);
+ // SeparateDeclarations should have already been run, so we don't need to worry
+ // about further declarators in this declaration depending on the effects of
+ // this declarator.
+ ASSERT(node->getSequence()->size() == 1);
+ insertStatementsInParentBlock(
+ TIntermSequence(),
+ *CreateInitCode(symbol, mCanUseLoopsToInitialize, mSymbolTable));
+ }
+ else
+ {
+ TIntermBinary *init =
+ new TIntermBinary(EOpInitialize, symbol, CreateZeroNode(symbol->getType()));
+ queueReplacementWithParent(node, symbol, init, OriginalNode::BECOMES_CHILD);
+ }
}
}
- else
- {
- TIntermBinary *assign = new TIntermBinary(EOpAssign);
- sequence->insert(sequence->begin(), assign);
- TIntermSymbol *symbol = new TIntermSymbol(0, varInfo.name, varInfo.type);
- assign->setLeft(symbol);
- TIntermConstantUnion *zeroConst = constructFloatConstUnionNode(varInfo.type);
- assign->setRight(zeroConst);
- }
-
+ return false;
}
+
+ private:
+ int mShaderVersion;
+ bool mCanUseLoopsToInitialize;
+};
+
+} // namespace anonymous
+
+TIntermSequence *CreateInitCode(const TIntermTyped *initializedSymbol,
+ bool canUseLoopsToInitialize,
+ TSymbolTable *symbolTable)
+{
+ TIntermSequence *initCode = new TIntermSequence();
+ AddZeroInitSequence(initializedSymbol, canUseLoopsToInitialize, initCode, symbolTable);
+ return initCode;
+}
+
+void InitializeUninitializedLocals(TIntermBlock *root,
+ int shaderVersion,
+ bool canUseLoopsToInitialize,
+ TSymbolTable *symbolTable)
+{
+ InitializeLocalsTraverser traverser(shaderVersion, symbolTable, canUseLoopsToInitialize);
+ root->traverse(&traverser);
+ traverser.updateTree();
+}
+
+void InitializeVariables(TIntermBlock *root,
+ const InitVariableList &vars,
+ TSymbolTable *symbolTable,
+ int shaderVersion,
+ const TExtensionBehavior &extensionBehavior,
+ bool canUseLoopsToInitialize)
+{
+ TIntermBlock *body = FindMainBody(root);
+ InsertInitCode(body->getSequence(), vars, symbolTable, shaderVersion, extensionBehavior,
+ canUseLoopsToInitialize);
}
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h
index 2a141ec91c..1a7b3c0f24 100644
--- a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h
+++ b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h
@@ -7,45 +7,47 @@
#ifndef COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_
#define COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_
+#include <GLSLANG/ShaderLang.h>
+
+#include "compiler/translator/ExtensionBehavior.h"
#include "compiler/translator/IntermNode.h"
-class InitializeVariables : public TIntermTraverser
+namespace sh
{
- public:
- struct InitVariableInfo
- {
- TString name;
- TType type;
-
- InitVariableInfo(const TString &_name, const TType &_type)
- : name(_name),
- type(_type)
- {
- }
- };
- typedef TVector<InitVariableInfo> InitVariableInfoList;
-
- InitializeVariables(const InitVariableInfoList &vars)
- : TIntermTraverser(true, false, false),
- mVariables(vars),
- mCodeInserted(false)
- {
- }
-
- protected:
- bool visitBinary(Visit, TIntermBinary *node) override { return false; }
- bool visitUnary(Visit, TIntermUnary *node) override { return false; }
- bool visitSelection(Visit, TIntermSelection *node) override { return false; }
- bool visitLoop(Visit, TIntermLoop *node) override { return false; }
- bool visitBranch(Visit, TIntermBranch *node) override { return false; }
-
- bool visitAggregate(Visit visit, TIntermAggregate *node) override;
-
- private:
- void insertInitCode(TIntermSequence *sequence);
-
- InitVariableInfoList mVariables;
- bool mCodeInserted;
-};
+class TSymbolTable;
+
+typedef std::vector<sh::ShaderVariable> InitVariableList;
+
+// For all of the functions below: If canUseLoopsToInitialize is set, for loops are used instead of
+// a large number of initializers where it can make sense, such as for initializing large arrays.
+
+// Return a sequence of assignment operations to initialize "initializedSymbol". initializedSymbol
+// may be an array, struct or any combination of these, as long as it contains only basic types.
+TIntermSequence *CreateInitCode(const TIntermTyped *initializedSymbol,
+ bool canUseLoopsToInitialize,
+ TSymbolTable *symbolTable);
+
+// Initialize all uninitialized local variables, so that undefined behavior is avoided.
+void InitializeUninitializedLocals(TIntermBlock *root,
+ int shaderVersion,
+ bool canUseLoopsToInitialize,
+ TSymbolTable *symbolTable);
+
+// This function can initialize all the types that CreateInitCode is able to initialize. All
+// variables must be globals which can be found in the symbol table. For now it is used for the
+// following two scenarios:
+// 1. Initializing gl_Position;
+// 2. Initializing output variables referred to in the shader source.
+// Note: The type of each lvalue in an initializer is retrieved from the symbol table. gl_FragData
+// requires special handling because the number of indices which can be initialized is determined by
+// enabled extensions.
+void InitializeVariables(TIntermBlock *root,
+ const InitVariableList &vars,
+ TSymbolTable *symbolTable,
+ int shaderVersion,
+ const TExtensionBehavior &extensionBehavior,
+ bool canUseLoopsToInitialize);
+
+} // namespace sh
#endif // COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp
index 2a92860088..a57ffcb4bc 100644
--- a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp
@@ -17,14 +17,18 @@
#include "common/mathutil.h"
#include "common/matrix_utils.h"
-#include "compiler/translator/HashNames.h"
+#include "compiler/translator/Diagnostics.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/util.h"
+
+namespace sh
+{
namespace
{
-const float kPi = 3.14159265358979323846f;
+const float kPi = 3.14159265358979323846f;
const float kDegreesToRadiansMultiplier = kPi / 180.0f;
const float kRadiansToDegreesMultiplier = 180.0f / kPi;
@@ -33,72 +37,40 @@ TPrecision GetHigherPrecision(TPrecision left, TPrecision right)
return left > right ? left : right;
}
-bool ValidateMultiplication(TOperator op, const TType &left, const TType &right)
-{
- switch (op)
- {
- case EOpMul:
- case EOpMulAssign:
- return left.getNominalSize() == right.getNominalSize() &&
- left.getSecondarySize() == right.getSecondarySize();
- case EOpVectorTimesScalar:
- case EOpVectorTimesScalarAssign:
- return true;
- case EOpVectorTimesMatrix:
- return left.getNominalSize() == right.getRows();
- case EOpVectorTimesMatrixAssign:
- return left.getNominalSize() == right.getRows() &&
- left.getNominalSize() == right.getCols();
- case EOpMatrixTimesVector:
- return left.getCols() == right.getNominalSize();
- case EOpMatrixTimesScalar:
- case EOpMatrixTimesScalarAssign:
- return true;
- case EOpMatrixTimesMatrix:
- return left.getCols() == right.getRows();
- case EOpMatrixTimesMatrixAssign:
- return left.getCols() == right.getCols() &&
- left.getRows() == right.getRows();
-
- default:
- UNREACHABLE();
- return false;
- }
-}
-
TConstantUnion *Vectorize(const TConstantUnion &constant, size_t size)
{
TConstantUnion *constUnion = new TConstantUnion[size];
for (unsigned int i = 0; i < size; ++i)
- constUnion[i] = constant;
+ constUnion[i] = constant;
return constUnion;
}
-void UndefinedConstantFoldingError(const TSourceLoc &loc, TOperator op, TBasicType basicType,
- TInfoSink &infoSink, TConstantUnion *result)
+void UndefinedConstantFoldingError(const TSourceLoc &loc,
+ TOperator op,
+ TBasicType basicType,
+ TDiagnostics *diagnostics,
+ TConstantUnion *result)
{
- std::stringstream constantFoldingErrorStream;
- constantFoldingErrorStream << "'" << GetOperatorString(op)
- << "' operation result is undefined for the values passed in";
- infoSink.info.message(EPrefixWarning, loc, constantFoldingErrorStream.str().c_str());
+ diagnostics->warning(loc, "operation result is undefined for the values passed in",
+ GetOperatorString(op));
switch (basicType)
{
- case EbtFloat :
- result->setFConst(0.0f);
- break;
- case EbtInt:
- result->setIConst(0);
- break;
- case EbtUInt:
- result->setUConst(0u);
- break;
- case EbtBool:
- result->setBConst(false);
- break;
- default:
- break;
+ case EbtFloat:
+ result->setFConst(0.0f);
+ break;
+ case EbtInt:
+ result->setIConst(0);
+ break;
+ case EbtUInt:
+ result->setUConst(0u);
+ break;
+ case EbtBool:
+ result->setBConst(false);
+ break;
+ default:
+ break;
}
}
@@ -123,7 +95,7 @@ float VectorDotProduct(const TConstantUnion *paramArray1,
return result;
}
-TIntermTyped *CreateFoldedNode(TConstantUnion *constArray,
+TIntermTyped *CreateFoldedNode(const TConstantUnion *constArray,
const TIntermTyped *originalNode,
TQualifier qualifier)
{
@@ -145,8 +117,9 @@ angle::Matrix<float> GetMatrix(const TConstantUnion *paramArray,
for (size_t i = 0; i < rows * cols; i++)
elements.push_back(paramArray[i].getFConst());
// Transpose is used since the Matrix constructor expects arguments in row-major order,
- // whereas the paramArray is in column-major order.
- return angle::Matrix<float>(elements, rows, cols).transpose();
+ // whereas the paramArray is in column-major order. Rows/cols parameters are also flipped below
+ // so that the created matrix will have the expected dimensions after the transpose.
+ return angle::Matrix<float>(elements, cols, rows).transpose();
}
angle::Matrix<float> GetMatrix(const TConstantUnion *paramArray, const unsigned int &size)
@@ -163,7 +136,7 @@ void SetUnionArrayFromMatrix(const angle::Matrix<float> &m, TConstantUnion *resu
{
// Transpose is used since the input Matrix is in row-major order,
// whereas the actual result should be in column-major order.
- angle::Matrix<float> result = m.transpose();
+ angle::Matrix<float> result = m.transpose();
std::vector<float> resultElements = result.elements();
for (size_t i = 0; i < resultElements.size(); i++)
resultArray[i].setFConst(resultElements[i]);
@@ -171,7 +144,6 @@ void SetUnionArrayFromMatrix(const angle::Matrix<float> &m, TConstantUnion *resu
} // namespace anonymous
-
////////////////////////////////////////////////////////////////
//
// Member functions of the nodes used for building the tree.
@@ -181,90 +153,214 @@ void SetUnionArrayFromMatrix(const angle::Matrix<float> &m, TConstantUnion *resu
void TIntermTyped::setTypePreservePrecision(const TType &t)
{
TPrecision precision = getPrecision();
- mType = t;
+ mType = t;
ASSERT(mType.getBasicType() != EbtBool || precision == EbpUndefined);
mType.setPrecision(precision);
}
#define REPLACE_IF_IS(node, type, original, replacement) \
- if (node == original) { \
- node = static_cast<type *>(replacement); \
- return true; \
+ if (node == original) \
+ { \
+ node = static_cast<type *>(replacement); \
+ return true; \
}
-bool TIntermLoop::replaceChildNode(
- TIntermNode *original, TIntermNode *replacement)
+bool TIntermLoop::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{
+ ASSERT(original != nullptr); // This risks replacing multiple children.
REPLACE_IF_IS(mInit, TIntermNode, original, replacement);
REPLACE_IF_IS(mCond, TIntermTyped, original, replacement);
REPLACE_IF_IS(mExpr, TIntermTyped, original, replacement);
- REPLACE_IF_IS(mBody, TIntermAggregate, original, replacement);
+ REPLACE_IF_IS(mBody, TIntermBlock, original, replacement);
return false;
}
-bool TIntermBranch::replaceChildNode(
- TIntermNode *original, TIntermNode *replacement)
+bool TIntermBranch::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{
REPLACE_IF_IS(mExpression, TIntermTyped, original, replacement);
return false;
}
-bool TIntermBinary::replaceChildNode(
- TIntermNode *original, TIntermNode *replacement)
+bool TIntermSwizzle::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
+{
+ ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType());
+ REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement);
+ return false;
+}
+
+bool TIntermBinary::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{
REPLACE_IF_IS(mLeft, TIntermTyped, original, replacement);
REPLACE_IF_IS(mRight, TIntermTyped, original, replacement);
return false;
}
-bool TIntermUnary::replaceChildNode(
- TIntermNode *original, TIntermNode *replacement)
+bool TIntermUnary::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{
+ ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType());
REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement);
return false;
}
-bool TIntermAggregate::replaceChildNode(
- TIntermNode *original, TIntermNode *replacement)
+bool TIntermInvariantDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
+{
+ REPLACE_IF_IS(mSymbol, TIntermSymbol, original, replacement);
+ return false;
+}
+
+bool TIntermFunctionDefinition::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
+{
+ REPLACE_IF_IS(mPrototype, TIntermFunctionPrototype, original, replacement);
+ REPLACE_IF_IS(mBody, TIntermBlock, original, replacement);
+ return false;
+}
+
+bool TIntermAggregate::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
+{
+ return replaceChildNodeInternal(original, replacement);
+}
+
+bool TIntermBlock::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{
- for (size_t ii = 0; ii < mSequence.size(); ++ii)
+ return replaceChildNodeInternal(original, replacement);
+}
+
+bool TIntermFunctionPrototype::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
+{
+ return replaceChildNodeInternal(original, replacement);
+}
+
+bool TIntermDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
+{
+ return replaceChildNodeInternal(original, replacement);
+}
+
+bool TIntermAggregateBase::replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement)
+{
+ for (size_t ii = 0; ii < getSequence()->size(); ++ii)
{
- REPLACE_IF_IS(mSequence[ii], TIntermNode, original, replacement);
+ REPLACE_IF_IS((*getSequence())[ii], TIntermNode, original, replacement);
}
return false;
}
-bool TIntermAggregate::replaceChildNodeWithMultiple(TIntermNode *original, TIntermSequence replacements)
+bool TIntermAggregateBase::replaceChildNodeWithMultiple(TIntermNode *original,
+ const TIntermSequence &replacements)
{
- for (auto it = mSequence.begin(); it < mSequence.end(); ++it)
+ for (auto it = getSequence()->begin(); it < getSequence()->end(); ++it)
{
if (*it == original)
{
- it = mSequence.erase(it);
- mSequence.insert(it, replacements.begin(), replacements.end());
+ it = getSequence()->erase(it);
+ getSequence()->insert(it, replacements.begin(), replacements.end());
return true;
}
}
return false;
}
-bool TIntermAggregate::insertChildNodes(TIntermSequence::size_type position, TIntermSequence insertions)
+bool TIntermAggregateBase::insertChildNodes(TIntermSequence::size_type position,
+ const TIntermSequence &insertions)
{
- if (position > mSequence.size())
+ if (position > getSequence()->size())
{
return false;
}
- auto it = mSequence.begin() + position;
- mSequence.insert(it, insertions.begin(), insertions.end());
+ auto it = getSequence()->begin() + position;
+ getSequence()->insert(it, insertions.begin(), insertions.end());
return true;
}
+TIntermAggregate *TIntermAggregate::CreateFunctionCall(const TFunction &func,
+ TIntermSequence *arguments)
+{
+ TIntermAggregate *callNode =
+ new TIntermAggregate(func.getReturnType(), EOpCallFunctionInAST, arguments);
+ callNode->getFunctionSymbolInfo()->setFromFunction(func);
+ return callNode;
+}
+
+TIntermAggregate *TIntermAggregate::CreateFunctionCall(const TType &type,
+ const TSymbolUniqueId &id,
+ const TName &name,
+ TIntermSequence *arguments)
+{
+ TIntermAggregate *callNode = new TIntermAggregate(type, EOpCallFunctionInAST, arguments);
+ callNode->getFunctionSymbolInfo()->setId(id);
+ callNode->getFunctionSymbolInfo()->setNameObj(name);
+ return callNode;
+}
+
+TIntermAggregate *TIntermAggregate::CreateBuiltInFunctionCall(const TFunction &func,
+ TIntermSequence *arguments)
+{
+ TIntermAggregate *callNode =
+ new TIntermAggregate(func.getReturnType(), EOpCallBuiltInFunction, arguments);
+ callNode->getFunctionSymbolInfo()->setFromFunction(func);
+ // Note that name needs to be set before texture function type is determined.
+ callNode->setBuiltInFunctionPrecision();
+ return callNode;
+}
+
+TIntermAggregate *TIntermAggregate::CreateConstructor(const TType &type,
+ TIntermSequence *arguments)
+{
+ return new TIntermAggregate(type, EOpConstruct, arguments);
+}
+
+TIntermAggregate *TIntermAggregate::Create(const TType &type,
+ TOperator op,
+ TIntermSequence *arguments)
+{
+ TIntermAggregate *node = new TIntermAggregate(type, op, arguments);
+ ASSERT(op != EOpCallFunctionInAST); // Should use CreateFunctionCall
+ ASSERT(op != EOpCallBuiltInFunction); // Should use CreateBuiltInFunctionCall
+ ASSERT(!node->isConstructor()); // Should use CreateConstructor
+ return node;
+}
+
+TIntermAggregate::TIntermAggregate(const TType &type, TOperator op, TIntermSequence *arguments)
+ : TIntermOperator(op), mUseEmulatedFunction(false), mGotPrecisionFromChildren(false)
+{
+ if (arguments != nullptr)
+ {
+ mArguments.swap(*arguments);
+ }
+ setTypePrecisionAndQualifier(type);
+}
+
+void TIntermAggregate::setTypePrecisionAndQualifier(const TType &type)
+{
+ setType(type);
+ mType.setQualifier(EvqTemporary);
+ if (!isFunctionCall())
+ {
+ if (isConstructor())
+ {
+ // Structs should not be precision qualified, the individual members may be.
+ // Built-in types on the other hand should be precision qualified.
+ if (getBasicType() != EbtStruct)
+ {
+ setPrecisionFromChildren();
+ }
+ }
+ else
+ {
+ setPrecisionForBuiltInOp();
+ }
+ if (areChildrenConstQualified())
+ {
+ mType.setQualifier(EvqConst);
+ }
+ }
+}
+
bool TIntermAggregate::areChildrenConstQualified()
{
- for (TIntermNode *&child : mSequence)
+ for (TIntermNode *&arg : mArguments)
{
- TIntermTyped *typed = child->getAsTyped();
- if (typed && typed->getQualifier() != EvqConst)
+ TIntermTyped *typedArg = arg->getAsTyped();
+ if (typedArg && typedArg->getQualifier() != EvqConst)
{
return false;
}
@@ -281,9 +377,9 @@ void TIntermAggregate::setPrecisionFromChildren()
return;
}
- TPrecision precision = EbpUndefined;
- TIntermSequence::iterator childIter = mSequence.begin();
- while (childIter != mSequence.end())
+ TPrecision precision = EbpUndefined;
+ TIntermSequence::iterator childIter = mArguments.begin();
+ while (childIter != mArguments.end())
{
TIntermTyped *typed = (*childIter)->getAsTyped();
if (typed)
@@ -293,51 +389,149 @@ void TIntermAggregate::setPrecisionFromChildren()
mType.setPrecision(precision);
}
+void TIntermAggregate::setPrecisionForBuiltInOp()
+{
+ ASSERT(!isConstructor());
+ ASSERT(!isFunctionCall());
+ if (!setPrecisionForSpecialBuiltInOp())
+ {
+ setPrecisionFromChildren();
+ }
+}
+
+bool TIntermAggregate::setPrecisionForSpecialBuiltInOp()
+{
+ switch (mOp)
+ {
+ case EOpBitfieldExtract:
+ mType.setPrecision(mArguments[0]->getAsTyped()->getPrecision());
+ mGotPrecisionFromChildren = true;
+ return true;
+ case EOpBitfieldInsert:
+ mType.setPrecision(GetHigherPrecision(mArguments[0]->getAsTyped()->getPrecision(),
+ mArguments[1]->getAsTyped()->getPrecision()));
+ mGotPrecisionFromChildren = true;
+ return true;
+ case EOpUaddCarry:
+ case EOpUsubBorrow:
+ mType.setPrecision(EbpHigh);
+ return true;
+ default:
+ return false;
+ }
+}
+
void TIntermAggregate::setBuiltInFunctionPrecision()
{
// All built-ins returning bool should be handled as ops, not functions.
ASSERT(getBasicType() != EbtBool);
+ ASSERT(mOp == EOpCallBuiltInFunction);
TPrecision precision = EbpUndefined;
- TIntermSequence::iterator childIter = mSequence.begin();
- while (childIter != mSequence.end())
+ for (TIntermNode *arg : mArguments)
{
- TIntermTyped *typed = (*childIter)->getAsTyped();
+ TIntermTyped *typed = arg->getAsTyped();
// ESSL spec section 8: texture functions get their precision from the sampler.
if (typed && IsSampler(typed->getBasicType()))
{
precision = typed->getPrecision();
break;
}
- ++childIter;
}
// ESSL 3.0 spec section 8: textureSize always gets highp precision.
// All other functions that take a sampler are assumed to be texture functions.
- if (mName.getString().find("textureSize") == 0)
+ if (mFunctionInfo.getName().find("textureSize") == 0)
mType.setPrecision(EbpHigh);
else
mType.setPrecision(precision);
}
-bool TIntermSelection::replaceChildNode(
- TIntermNode *original, TIntermNode *replacement)
+TString TIntermAggregate::getSymbolTableMangledName() const
+{
+ ASSERT(!isConstructor());
+ switch (mOp)
+ {
+ case EOpCallInternalRawFunction:
+ case EOpCallBuiltInFunction:
+ case EOpCallFunctionInAST:
+ return TFunction::GetMangledNameFromCall(mFunctionInfo.getName(), mArguments);
+ default:
+ TString opString = GetOperatorString(mOp);
+ return TFunction::GetMangledNameFromCall(opString, mArguments);
+ }
+}
+
+bool TIntermAggregate::hasSideEffects() const
+{
+ if (isFunctionCall() && mFunctionInfo.isKnownToNotHaveSideEffects())
+ {
+ for (TIntermNode *arg : mArguments)
+ {
+ if (arg->getAsTyped()->hasSideEffects())
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ // Conservatively assume most aggregate operators have side-effects
+ return true;
+}
+
+void TIntermBlock::appendStatement(TIntermNode *statement)
+{
+ // Declaration nodes with no children can appear if it was an empty declaration or if all the
+ // declarators just added constants to the symbol table instead of generating code. We still
+ // need to add the declaration to the AST in that case because it might be relevant to the
+ // validity of switch/case.
+ if (statement != nullptr)
+ {
+ mStatements.push_back(statement);
+ }
+}
+
+void TIntermFunctionPrototype::appendParameter(TIntermSymbol *parameter)
+{
+ ASSERT(parameter != nullptr);
+ mParameters.push_back(parameter);
+}
+
+void TIntermDeclaration::appendDeclarator(TIntermTyped *declarator)
+{
+ ASSERT(declarator != nullptr);
+ ASSERT(declarator->getAsSymbolNode() != nullptr ||
+ (declarator->getAsBinaryNode() != nullptr &&
+ declarator->getAsBinaryNode()->getOp() == EOpInitialize));
+ ASSERT(mDeclarators.empty() ||
+ declarator->getType().sameNonArrayType(mDeclarators.back()->getAsTyped()->getType()));
+ mDeclarators.push_back(declarator);
+}
+
+bool TIntermTernary::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{
REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
- REPLACE_IF_IS(mTrueBlock, TIntermNode, original, replacement);
- REPLACE_IF_IS(mFalseBlock, TIntermNode, original, replacement);
+ REPLACE_IF_IS(mTrueExpression, TIntermTyped, original, replacement);
+ REPLACE_IF_IS(mFalseExpression, TIntermTyped, original, replacement);
return false;
}
-bool TIntermSwitch::replaceChildNode(
- TIntermNode *original, TIntermNode *replacement)
+bool TIntermIfElse::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
+{
+ REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
+ REPLACE_IF_IS(mTrueBlock, TIntermBlock, original, replacement);
+ REPLACE_IF_IS(mFalseBlock, TIntermBlock, original, replacement);
+ return false;
+}
+
+bool TIntermSwitch::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{
REPLACE_IF_IS(mInit, TIntermTyped, original, replacement);
- REPLACE_IF_IS(mStatementList, TIntermAggregate, original, replacement);
+ REPLACE_IF_IS(mStatementList, TIntermBlock, original, replacement);
+ ASSERT(mStatementList);
return false;
}
-bool TIntermCase::replaceChildNode(
- TIntermNode *original, TIntermNode *replacement)
+bool TIntermCase::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{
REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
return false;
@@ -351,28 +545,104 @@ TIntermTyped::TIntermTyped(const TIntermTyped &node) : TIntermNode(), mType(node
mLine = node.mLine;
}
+bool TIntermTyped::isConstructorWithOnlyConstantUnionParameters()
+{
+ TIntermAggregate *constructor = getAsAggregate();
+ if (!constructor || !constructor->isConstructor())
+ {
+ return false;
+ }
+ for (TIntermNode *&node : *constructor->getSequence())
+ {
+ if (!node->getAsConstantUnion())
+ return false;
+ }
+ return true;
+}
+
TIntermConstantUnion::TIntermConstantUnion(const TIntermConstantUnion &node) : TIntermTyped(node)
{
mUnionArrayPointer = node.mUnionArrayPointer;
}
+void TFunctionSymbolInfo::setFromFunction(const TFunction &function)
+{
+ setName(function.getName());
+ setId(TSymbolUniqueId(function));
+}
+
+TFunctionSymbolInfo::TFunctionSymbolInfo(const TSymbolUniqueId &id)
+ : mId(new TSymbolUniqueId(id)), mKnownToNotHaveSideEffects(false)
+{
+}
+
+TFunctionSymbolInfo::TFunctionSymbolInfo(const TFunctionSymbolInfo &info)
+ : mName(info.mName), mId(nullptr), mKnownToNotHaveSideEffects(info.mKnownToNotHaveSideEffects)
+{
+ if (info.mId)
+ {
+ mId = new TSymbolUniqueId(*info.mId);
+ }
+}
+
+TFunctionSymbolInfo &TFunctionSymbolInfo::operator=(const TFunctionSymbolInfo &info)
+{
+ mName = info.mName;
+ if (info.mId)
+ {
+ mId = new TSymbolUniqueId(*info.mId);
+ }
+ else
+ {
+ mId = nullptr;
+ }
+ return *this;
+}
+
+void TFunctionSymbolInfo::setId(const TSymbolUniqueId &id)
+{
+ mId = new TSymbolUniqueId(id);
+}
+
+const TSymbolUniqueId &TFunctionSymbolInfo::getId() const
+{
+ ASSERT(mId);
+ return *mId;
+}
+
TIntermAggregate::TIntermAggregate(const TIntermAggregate &node)
: TIntermOperator(node),
- mName(node.mName),
- mUserDefined(node.mUserDefined),
- mFunctionId(node.mFunctionId),
mUseEmulatedFunction(node.mUseEmulatedFunction),
- mGotPrecisionFromChildren(node.mGotPrecisionFromChildren)
+ mGotPrecisionFromChildren(node.mGotPrecisionFromChildren),
+ mFunctionInfo(node.mFunctionInfo)
{
- for (TIntermNode *child : node.mSequence)
+ for (TIntermNode *arg : node.mArguments)
{
- TIntermTyped *typedChild = child->getAsTyped();
- ASSERT(typedChild != nullptr);
- TIntermTyped *childCopy = typedChild->deepCopy();
- mSequence.push_back(childCopy);
+ TIntermTyped *typedArg = arg->getAsTyped();
+ ASSERT(typedArg != nullptr);
+ TIntermTyped *argCopy = typedArg->deepCopy();
+ mArguments.push_back(argCopy);
}
}
+TIntermAggregate *TIntermAggregate::shallowCopy() const
+{
+ TIntermSequence *copySeq = new TIntermSequence();
+ copySeq->insert(copySeq->begin(), getSequence()->begin(), getSequence()->end());
+ TIntermAggregate *copyNode = new TIntermAggregate(mType, mOp, copySeq);
+ *copyNode->getFunctionSymbolInfo() = mFunctionInfo;
+ copyNode->setLine(mLine);
+ return copyNode;
+}
+
+TIntermSwizzle::TIntermSwizzle(const TIntermSwizzle &node) : TIntermTyped(node)
+{
+ TIntermTyped *operandCopy = node.mOperand->deepCopy();
+ ASSERT(operandCopy != nullptr);
+ mOperand = operandCopy;
+ mSwizzleOffsets = node.mSwizzleOffsets;
+}
+
TIntermBinary::TIntermBinary(const TIntermBinary &node)
: TIntermOperator(node), mAddIndexClamp(node.mAddIndexClamp)
{
@@ -391,106 +661,141 @@ TIntermUnary::TIntermUnary(const TIntermUnary &node)
mOperand = operandCopy;
}
-TIntermSelection::TIntermSelection(const TIntermSelection &node) : TIntermTyped(node)
+TIntermTernary::TIntermTernary(const TIntermTernary &node) : TIntermTyped(node)
{
- // Only supported for ternary nodes, not if statements.
- TIntermTyped *trueTyped = node.mTrueBlock->getAsTyped();
- TIntermTyped *falseTyped = node.mFalseBlock->getAsTyped();
- ASSERT(trueTyped != nullptr);
- ASSERT(falseTyped != nullptr);
TIntermTyped *conditionCopy = node.mCondition->deepCopy();
- TIntermTyped *trueCopy = trueTyped->deepCopy();
- TIntermTyped *falseCopy = falseTyped->deepCopy();
+ TIntermTyped *trueCopy = node.mTrueExpression->deepCopy();
+ TIntermTyped *falseCopy = node.mFalseExpression->deepCopy();
ASSERT(conditionCopy != nullptr && trueCopy != nullptr && falseCopy != nullptr);
- mCondition = conditionCopy;
- mTrueBlock = trueCopy;
- mFalseBlock = falseCopy;
+ mCondition = conditionCopy;
+ mTrueExpression = trueCopy;
+ mFalseExpression = falseCopy;
}
-//
-// Say whether or not an operation node changes the value of a variable.
-//
bool TIntermOperator::isAssignment() const
{
- switch (mOp)
- {
- case EOpPostIncrement:
- case EOpPostDecrement:
- case EOpPreIncrement:
- case EOpPreDecrement:
- case EOpAssign:
- case EOpAddAssign:
- case EOpSubAssign:
- case EOpMulAssign:
- case EOpVectorTimesMatrixAssign:
- case EOpVectorTimesScalarAssign:
- case EOpMatrixTimesScalarAssign:
- case EOpMatrixTimesMatrixAssign:
- case EOpDivAssign:
- case EOpIModAssign:
- case EOpBitShiftLeftAssign:
- case EOpBitShiftRightAssign:
- case EOpBitwiseAndAssign:
- case EOpBitwiseXorAssign:
- case EOpBitwiseOrAssign:
- return true;
- default:
- return false;
- }
+ return IsAssignment(mOp);
}
bool TIntermOperator::isMultiplication() const
{
switch (mOp)
{
- case EOpMul:
- case EOpMatrixTimesMatrix:
- case EOpMatrixTimesVector:
- case EOpMatrixTimesScalar:
- case EOpVectorTimesMatrix:
- case EOpVectorTimesScalar:
- return true;
- default:
- return false;
+ case EOpMul:
+ case EOpMatrixTimesMatrix:
+ case EOpMatrixTimesVector:
+ case EOpMatrixTimesScalar:
+ case EOpVectorTimesMatrix:
+ case EOpVectorTimesScalar:
+ return true;
+ default:
+ return false;
}
}
-//
-// returns true if the operator is for one of the constructors
-//
bool TIntermOperator::isConstructor() const
{
+ return (mOp == EOpConstruct);
+}
+
+bool TIntermOperator::isFunctionCall() const
+{
switch (mOp)
{
- case EOpConstructVec2:
- case EOpConstructVec3:
- case EOpConstructVec4:
- case EOpConstructMat2:
- case EOpConstructMat2x3:
- case EOpConstructMat2x4:
- case EOpConstructMat3x2:
- case EOpConstructMat3:
- case EOpConstructMat3x4:
- case EOpConstructMat4x2:
- case EOpConstructMat4x3:
- case EOpConstructMat4:
- case EOpConstructFloat:
- case EOpConstructIVec2:
- case EOpConstructIVec3:
- case EOpConstructIVec4:
- case EOpConstructInt:
- case EOpConstructUVec2:
- case EOpConstructUVec3:
- case EOpConstructUVec4:
- case EOpConstructUInt:
- case EOpConstructBVec2:
- case EOpConstructBVec3:
- case EOpConstructBVec4:
- case EOpConstructBool:
- case EOpConstructStruct:
- return true;
- default:
- return false;
+ case EOpCallFunctionInAST:
+ case EOpCallBuiltInFunction:
+ case EOpCallInternalRawFunction:
+ return true;
+ default:
+ return false;
+ }
+}
+
+TOperator TIntermBinary::GetMulOpBasedOnOperands(const TType &left, const TType &right)
+{
+ if (left.isMatrix())
+ {
+ if (right.isMatrix())
+ {
+ return EOpMatrixTimesMatrix;
+ }
+ else
+ {
+ if (right.isVector())
+ {
+ return EOpMatrixTimesVector;
+ }
+ else
+ {
+ return EOpMatrixTimesScalar;
+ }
+ }
+ }
+ else
+ {
+ if (right.isMatrix())
+ {
+ if (left.isVector())
+ {
+ return EOpVectorTimesMatrix;
+ }
+ else
+ {
+ return EOpMatrixTimesScalar;
+ }
+ }
+ else
+ {
+ // Neither operand is a matrix.
+ if (left.isVector() == right.isVector())
+ {
+ // Leave as component product.
+ return EOpMul;
+ }
+ else
+ {
+ return EOpVectorTimesScalar;
+ }
+ }
+ }
+}
+
+TOperator TIntermBinary::GetMulAssignOpBasedOnOperands(const TType &left, const TType &right)
+{
+ if (left.isMatrix())
+ {
+ if (right.isMatrix())
+ {
+ return EOpMatrixTimesMatrixAssign;
+ }
+ else
+ {
+ // right should be scalar, but this may not be validated yet.
+ return EOpMatrixTimesScalarAssign;
+ }
+ }
+ else
+ {
+ if (right.isMatrix())
+ {
+ // Left should be a vector, but this may not be validated yet.
+ return EOpVectorTimesMatrixAssign;
+ }
+ else
+ {
+ // Neither operand is a matrix.
+ if (left.isVector() == right.isVector())
+ {
+ // Leave as component product.
+ return EOpMulAssign;
+ }
+ else
+ {
+ // left should be vector and right should be scalar, but this may not be validated
+ // yet.
+ return EOpVectorTimesScalarAssign;
+ }
+ }
}
}
@@ -498,70 +803,281 @@ bool TIntermOperator::isConstructor() const
// Make sure the type of a unary operator is appropriate for its
// combination of operation and operand type.
//
-void TIntermUnary::promote(const TType *funcReturnType)
+void TIntermUnary::promote()
{
+ if (mOp == EOpArrayLength)
+ {
+ // Special case: the qualifier of .length() doesn't depend on the operand qualifier.
+ setType(TType(EbtInt, EbpUndefined, EvqConst));
+ return;
+ }
+
+ TQualifier resultQualifier = EvqTemporary;
+ if (mOperand->getQualifier() == EvqConst)
+ resultQualifier = EvqConst;
+
+ unsigned char operandPrimarySize =
+ static_cast<unsigned char>(mOperand->getType().getNominalSize());
switch (mOp)
{
- case EOpFloatBitsToInt:
- case EOpFloatBitsToUint:
- case EOpIntBitsToFloat:
- case EOpUintBitsToFloat:
- case EOpPackSnorm2x16:
- case EOpPackUnorm2x16:
- case EOpPackHalf2x16:
- case EOpUnpackSnorm2x16:
- case EOpUnpackUnorm2x16:
- mType.setPrecision(EbpHigh);
- break;
- case EOpUnpackHalf2x16:
- mType.setPrecision(EbpMedium);
- break;
- default:
- setType(mOperand->getType());
+ case EOpFloatBitsToInt:
+ setType(TType(EbtInt, EbpHigh, resultQualifier, operandPrimarySize));
+ break;
+ case EOpFloatBitsToUint:
+ setType(TType(EbtUInt, EbpHigh, resultQualifier, operandPrimarySize));
+ break;
+ case EOpIntBitsToFloat:
+ case EOpUintBitsToFloat:
+ setType(TType(EbtFloat, EbpHigh, resultQualifier, operandPrimarySize));
+ break;
+ case EOpPackSnorm2x16:
+ case EOpPackUnorm2x16:
+ case EOpPackHalf2x16:
+ case EOpPackUnorm4x8:
+ case EOpPackSnorm4x8:
+ setType(TType(EbtUInt, EbpHigh, resultQualifier));
+ break;
+ case EOpUnpackSnorm2x16:
+ case EOpUnpackUnorm2x16:
+ setType(TType(EbtFloat, EbpHigh, resultQualifier, 2));
+ break;
+ case EOpUnpackHalf2x16:
+ setType(TType(EbtFloat, EbpMedium, resultQualifier, 2));
+ break;
+ case EOpUnpackUnorm4x8:
+ case EOpUnpackSnorm4x8:
+ setType(TType(EbtFloat, EbpMedium, resultQualifier, 4));
+ break;
+ case EOpAny:
+ case EOpAll:
+ setType(TType(EbtBool, EbpUndefined, resultQualifier));
+ break;
+ case EOpLength:
+ case EOpDeterminant:
+ setType(TType(EbtFloat, mOperand->getType().getPrecision(), resultQualifier));
+ break;
+ case EOpTranspose:
+ setType(TType(EbtFloat, mOperand->getType().getPrecision(), resultQualifier,
+ static_cast<unsigned char>(mOperand->getType().getRows()),
+ static_cast<unsigned char>(mOperand->getType().getCols())));
+ break;
+ case EOpIsInf:
+ case EOpIsNan:
+ setType(TType(EbtBool, EbpUndefined, resultQualifier, operandPrimarySize));
+ break;
+ case EOpBitfieldReverse:
+ setType(TType(mOperand->getBasicType(), EbpHigh, resultQualifier, operandPrimarySize));
+ break;
+ case EOpBitCount:
+ setType(TType(EbtInt, EbpLow, resultQualifier, operandPrimarySize));
+ break;
+ case EOpFindLSB:
+ setType(TType(EbtInt, EbpLow, resultQualifier, operandPrimarySize));
+ break;
+ case EOpFindMSB:
+ setType(TType(EbtInt, EbpLow, resultQualifier, operandPrimarySize));
+ break;
+ default:
+ setType(mOperand->getType());
+ mType.setQualifier(resultQualifier);
+ break;
+ }
+}
+
+TIntermSwizzle::TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets)
+ : TIntermTyped(TType(EbtFloat, EbpUndefined)),
+ mOperand(operand),
+ mSwizzleOffsets(swizzleOffsets)
+{
+ ASSERT(mSwizzleOffsets.size() <= 4);
+ promote();
+}
+
+TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand)
+ : TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false)
+{
+ promote();
+}
+
+TIntermBinary::TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right)
+ : TIntermOperator(op), mLeft(left), mRight(right), mAddIndexClamp(false)
+{
+ promote();
+}
+
+TIntermInvariantDeclaration::TIntermInvariantDeclaration(TIntermSymbol *symbol, const TSourceLoc &line)
+ : TIntermNode(), mSymbol(symbol)
+{
+ ASSERT(symbol);
+ setLine(line);
+}
+
+TIntermTernary::TIntermTernary(TIntermTyped *cond,
+ TIntermTyped *trueExpression,
+ TIntermTyped *falseExpression)
+ : TIntermTyped(trueExpression->getType()),
+ mCondition(cond),
+ mTrueExpression(trueExpression),
+ mFalseExpression(falseExpression)
+{
+ getTypePointer()->setQualifier(
+ TIntermTernary::DetermineQualifier(cond, trueExpression, falseExpression));
+}
+
+TIntermLoop::TIntermLoop(TLoopType type,
+ TIntermNode *init,
+ TIntermTyped *cond,
+ TIntermTyped *expr,
+ TIntermBlock *body)
+ : mType(type), mInit(init), mCond(cond), mExpr(expr), mBody(body)
+{
+ // Declaration nodes with no children can appear if all the declarators just added constants to
+ // the symbol table instead of generating code. They're no-ops so don't add them to the tree.
+ if (mInit && mInit->getAsDeclarationNode() &&
+ mInit->getAsDeclarationNode()->getSequence()->empty())
+ {
+ mInit = nullptr;
+ }
+}
+
+TIntermIfElse::TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlock *falseB)
+ : TIntermNode(), mCondition(cond), mTrueBlock(trueB), mFalseBlock(falseB)
+{
+ // Prune empty false blocks so that there won't be unnecessary operations done on it.
+ if (mFalseBlock && mFalseBlock->getSequence()->empty())
+ {
+ mFalseBlock = nullptr;
+ }
+}
+
+TIntermSwitch::TIntermSwitch(TIntermTyped *init, TIntermBlock *statementList)
+ : TIntermNode(), mInit(init), mStatementList(statementList)
+{
+ ASSERT(mStatementList);
+}
+
+void TIntermSwitch::setStatementList(TIntermBlock *statementList)
+{
+ ASSERT(statementList);
+ mStatementList = statementList;
+}
+
+// static
+TQualifier TIntermTernary::DetermineQualifier(TIntermTyped *cond,
+ TIntermTyped *trueExpression,
+ TIntermTyped *falseExpression)
+{
+ if (cond->getQualifier() == EvqConst && trueExpression->getQualifier() == EvqConst &&
+ falseExpression->getQualifier() == EvqConst)
+ {
+ return EvqConst;
}
+ return EvqTemporary;
+}
- if (funcReturnType != nullptr)
+TIntermTyped *TIntermTernary::fold()
+{
+ if (mCondition->getAsConstantUnion())
{
- if (funcReturnType->getBasicType() == EbtBool)
+ if (mCondition->getAsConstantUnion()->getBConst(0))
{
- // Bool types should not have precision.
- setType(*funcReturnType);
+ mTrueExpression->getTypePointer()->setQualifier(mType.getQualifier());
+ return mTrueExpression;
}
else
{
- // Precision of the node has been set based on the operand.
- setTypePreservePrecision(*funcReturnType);
+ mFalseExpression->getTypePointer()->setQualifier(mType.getQualifier());
+ return mFalseExpression;
}
}
+ return this;
+}
+void TIntermSwizzle::promote()
+{
+ TQualifier resultQualifier = EvqTemporary;
if (mOperand->getQualifier() == EvqConst)
- mType.setQualifier(EvqConst);
- else
- mType.setQualifier(EvqTemporary);
+ resultQualifier = EvqConst;
+
+ auto numFields = mSwizzleOffsets.size();
+ setType(TType(mOperand->getBasicType(), mOperand->getPrecision(), resultQualifier,
+ static_cast<unsigned char>(numFields)));
}
-//
-// Establishes the type of the resultant operation, as well as
-// makes the operator the correct one for the operands.
-//
-// For lots of operations it should already be established that the operand
-// combination is valid, but returns false if operator can't work on operands.
-//
-bool TIntermBinary::promote(TInfoSink &infoSink)
+bool TIntermSwizzle::hasDuplicateOffsets() const
{
- ASSERT(mLeft->isArray() == mRight->isArray());
+ int offsetCount[4] = {0u, 0u, 0u, 0u};
+ for (const auto offset : mSwizzleOffsets)
+ {
+ offsetCount[offset]++;
+ if (offsetCount[offset] > 1)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool TIntermSwizzle::offsetsMatch(int offset) const
+{
+ return mSwizzleOffsets.size() == 1 && mSwizzleOffsets[0] == offset;
+}
+
+void TIntermSwizzle::writeOffsetsAsXYZW(TInfoSinkBase *out) const
+{
+ for (const int offset : mSwizzleOffsets)
+ {
+ switch (offset)
+ {
+ case 0:
+ *out << "x";
+ break;
+ case 1:
+ *out << "y";
+ break;
+ case 2:
+ *out << "z";
+ break;
+ case 3:
+ *out << "w";
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+}
+
+TQualifier TIntermBinary::GetCommaQualifier(int shaderVersion,
+ const TIntermTyped *left,
+ const TIntermTyped *right)
+{
+ // ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression.
+ if (shaderVersion >= 300 || left->getQualifier() != EvqConst ||
+ right->getQualifier() != EvqConst)
+ {
+ return EvqTemporary;
+ }
+ return EvqConst;
+}
+
+// Establishes the type of the result of the binary operation.
+void TIntermBinary::promote()
+{
+ ASSERT(!isMultiplication() ||
+ mOp == GetMulOpBasedOnOperands(mLeft->getType(), mRight->getType()));
+
+ // Comma is handled as a special case. Note that the comma node qualifier depends on the shader
+ // version and so is not being set here.
+ if (mOp == EOpComma)
+ {
+ setType(mRight->getType());
+ return;
+ }
- //
// Base assumption: just make the type the same as the left
// operand. Then only deviations from this need be coded.
- //
setType(mLeft->getType());
- // The result gets promoted to the highest precision.
- TPrecision higherPrecision = GetHigherPrecision(
- mLeft->getPrecision(), mRight->getPrecision());
- getTypePointer()->setPrecision(higherPrecision);
-
TQualifier resultQualifier = EvqConst;
// Binary operations results in temporary variables unless both
// operands are const.
@@ -571,8 +1087,56 @@ bool TIntermBinary::promote(TInfoSink &infoSink)
getTypePointer()->setQualifier(EvqTemporary);
}
- const int nominalSize =
- std::max(mLeft->getNominalSize(), mRight->getNominalSize());
+ // Handle indexing ops.
+ switch (mOp)
+ {
+ case EOpIndexDirect:
+ case EOpIndexIndirect:
+ if (mLeft->isArray())
+ {
+ mType.toArrayElementType();
+ }
+ else if (mLeft->isMatrix())
+ {
+ setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier,
+ static_cast<unsigned char>(mLeft->getRows())));
+ }
+ else if (mLeft->isVector())
+ {
+ setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier));
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ return;
+ case EOpIndexDirectStruct:
+ {
+ const TFieldList &fields = mLeft->getType().getStruct()->fields();
+ const int i = mRight->getAsConstantUnion()->getIConst(0);
+ setType(*fields[i]->type());
+ getTypePointer()->setQualifier(resultQualifier);
+ return;
+ }
+ case EOpIndexDirectInterfaceBlock:
+ {
+ const TFieldList &fields = mLeft->getType().getInterfaceBlock()->fields();
+ const int i = mRight->getAsConstantUnion()->getIConst(0);
+ setType(*fields[i]->type());
+ getTypePointer()->setQualifier(resultQualifier);
+ return;
+ }
+ default:
+ break;
+ }
+
+ ASSERT(mLeft->isArray() == mRight->isArray());
+
+ // The result gets promoted to the highest precision.
+ TPrecision higherPrecision = GetHigherPrecision(mLeft->getPrecision(), mRight->getPrecision());
+ getTypePointer()->setPrecision(higherPrecision);
+
+ const int nominalSize = std::max(mLeft->getNominalSize(), mRight->getNominalSize());
//
// All scalars or structs. Code after this test assumes this case is removed!
@@ -581,316 +1145,319 @@ bool TIntermBinary::promote(TInfoSink &infoSink)
{
switch (mOp)
{
- //
- // Promote to conditional
- //
- case EOpEqual:
- case EOpNotEqual:
- case EOpLessThan:
- case EOpGreaterThan:
- case EOpLessThanEqual:
- case EOpGreaterThanEqual:
- setType(TType(EbtBool, EbpUndefined));
- break;
+ //
+ // Promote to conditional
+ //
+ case EOpEqual:
+ case EOpNotEqual:
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ setType(TType(EbtBool, EbpUndefined, resultQualifier));
+ break;
- //
- // And and Or operate on conditionals
- //
- case EOpLogicalAnd:
- case EOpLogicalXor:
- case EOpLogicalOr:
- ASSERT(mLeft->getBasicType() == EbtBool && mRight->getBasicType() == EbtBool);
- setType(TType(EbtBool, EbpUndefined));
- break;
+ //
+ // And and Or operate on conditionals
+ //
+ case EOpLogicalAnd:
+ case EOpLogicalXor:
+ case EOpLogicalOr:
+ ASSERT(mLeft->getBasicType() == EbtBool && mRight->getBasicType() == EbtBool);
+ setType(TType(EbtBool, EbpUndefined, resultQualifier));
+ break;
- default:
- break;
+ default:
+ break;
}
- return true;
+ return;
}
// If we reach here, at least one of the operands is vector or matrix.
// The other operand could be a scalar, vector, or matrix.
- // Can these two operands be combined?
- //
TBasicType basicType = mLeft->getBasicType();
+
switch (mOp)
{
- case EOpMul:
- if (!mLeft->isMatrix() && mRight->isMatrix())
- {
- if (mLeft->isVector())
- {
- mOp = EOpVectorTimesMatrix;
- setType(TType(basicType, higherPrecision, resultQualifier,
- static_cast<unsigned char>(mRight->getCols()), 1));
- }
- else
+ case EOpMul:
+ break;
+ case EOpMatrixTimesScalar:
+ if (mRight->isMatrix())
{
- mOp = EOpMatrixTimesScalar;
setType(TType(basicType, higherPrecision, resultQualifier,
static_cast<unsigned char>(mRight->getCols()),
static_cast<unsigned char>(mRight->getRows())));
}
- }
- else if (mLeft->isMatrix() && !mRight->isMatrix())
- {
- if (mRight->isVector())
- {
- mOp = EOpMatrixTimesVector;
- setType(TType(basicType, higherPrecision, resultQualifier,
- static_cast<unsigned char>(mLeft->getRows()), 1));
- }
- else
- {
- mOp = EOpMatrixTimesScalar;
- }
- }
- else if (mLeft->isMatrix() && mRight->isMatrix())
- {
- mOp = EOpMatrixTimesMatrix;
+ break;
+ case EOpMatrixTimesVector:
+ setType(TType(basicType, higherPrecision, resultQualifier,
+ static_cast<unsigned char>(mLeft->getRows()), 1));
+ break;
+ case EOpMatrixTimesMatrix:
setType(TType(basicType, higherPrecision, resultQualifier,
static_cast<unsigned char>(mRight->getCols()),
static_cast<unsigned char>(mLeft->getRows())));
+ break;
+ case EOpVectorTimesScalar:
+ setType(TType(basicType, higherPrecision, resultQualifier,
+ static_cast<unsigned char>(nominalSize), 1));
+ break;
+ case EOpVectorTimesMatrix:
+ setType(TType(basicType, higherPrecision, resultQualifier,
+ static_cast<unsigned char>(mRight->getCols()), 1));
+ break;
+ case EOpMulAssign:
+ case EOpVectorTimesScalarAssign:
+ case EOpVectorTimesMatrixAssign:
+ case EOpMatrixTimesScalarAssign:
+ case EOpMatrixTimesMatrixAssign:
+ ASSERT(mOp == GetMulAssignOpBasedOnOperands(mLeft->getType(), mRight->getType()));
+ break;
+ case EOpAssign:
+ case EOpInitialize:
+ ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
+ (mLeft->getSecondarySize() == mRight->getSecondarySize()));
+ break;
+ case EOpAdd:
+ case EOpSub:
+ case EOpDiv:
+ case EOpIMod:
+ case EOpBitShiftLeft:
+ case EOpBitShiftRight:
+ case EOpBitwiseAnd:
+ case EOpBitwiseXor:
+ case EOpBitwiseOr:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpDivAssign:
+ case EOpIModAssign:
+ case EOpBitShiftLeftAssign:
+ case EOpBitShiftRightAssign:
+ case EOpBitwiseAndAssign:
+ case EOpBitwiseXorAssign:
+ case EOpBitwiseOrAssign:
+ {
+ const int secondarySize =
+ std::max(mLeft->getSecondarySize(), mRight->getSecondarySize());
+ setType(TType(basicType, higherPrecision, resultQualifier,
+ static_cast<unsigned char>(nominalSize),
+ static_cast<unsigned char>(secondarySize)));
+ ASSERT(!mLeft->isArray() && !mRight->isArray());
+ break;
}
- else if (!mLeft->isMatrix() && !mRight->isMatrix())
- {
- if (mLeft->isVector() && mRight->isVector())
- {
- // leave as component product
- }
- else if (mLeft->isVector() || mRight->isVector())
- {
- mOp = EOpVectorTimesScalar;
- setType(TType(basicType, higherPrecision, resultQualifier,
- static_cast<unsigned char>(nominalSize), 1));
- }
- }
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(),
- "Missing elses");
- return false;
- }
+ case EOpEqual:
+ case EOpNotEqual:
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
+ (mLeft->getSecondarySize() == mRight->getSecondarySize()));
+ setType(TType(EbtBool, EbpUndefined, resultQualifier));
+ break;
- if (!ValidateMultiplication(mOp, mLeft->getType(), mRight->getType()))
- {
- return false;
- }
- break;
+ case EOpIndexDirect:
+ case EOpIndexIndirect:
+ case EOpIndexDirectInterfaceBlock:
+ case EOpIndexDirectStruct:
+ // These ops should be already fully handled.
+ UNREACHABLE();
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+const TConstantUnion *TIntermConstantUnion::foldIndexing(int index)
+{
+ if (isArray())
+ {
+ ASSERT(index < static_cast<int>(getType().getOutermostArraySize()));
+ TType arrayElementType = getType();
+ arrayElementType.toArrayElementType();
+ size_t arrayElementSize = arrayElementType.getObjectSize();
+ return &mUnionArrayPointer[arrayElementSize * index];
+ }
+ else if (isMatrix())
+ {
+ ASSERT(index < getType().getCols());
+ int size = getType().getRows();
+ return &mUnionArrayPointer[size * index];
+ }
+ else if (isVector())
+ {
+ ASSERT(index < getType().getNominalSize());
+ return &mUnionArrayPointer[index];
+ }
+ else
+ {
+ UNREACHABLE();
+ return nullptr;
+ }
+}
- case EOpMulAssign:
- if (!mLeft->isMatrix() && mRight->isMatrix())
+TIntermTyped *TIntermSwizzle::fold()
+{
+ TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
+ if (operandConstant == nullptr)
+ {
+ return this;
+ }
+
+ TConstantUnion *constArray = new TConstantUnion[mSwizzleOffsets.size()];
+ for (size_t i = 0; i < mSwizzleOffsets.size(); ++i)
+ {
+ constArray[i] = *operandConstant->foldIndexing(mSwizzleOffsets.at(i));
+ }
+ return CreateFoldedNode(constArray, this, mType.getQualifier());
+}
+
+TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics)
+{
+ TIntermConstantUnion *leftConstant = mLeft->getAsConstantUnion();
+ TIntermConstantUnion *rightConstant = mRight->getAsConstantUnion();
+ switch (mOp)
+ {
+ case EOpComma:
{
- if (mLeft->isVector())
+ if (mLeft->hasSideEffects())
{
- mOp = EOpVectorTimesMatrixAssign;
- }
- else
- {
- return false;
+ return this;
}
+ mRight->getTypePointer()->setQualifier(mType.getQualifier());
+ return mRight;
}
- else if (mLeft->isMatrix() && !mRight->isMatrix())
+ case EOpIndexDirect:
{
- if (mRight->isVector())
+ if (leftConstant == nullptr || rightConstant == nullptr)
{
- return false;
+ return this;
}
- else
+ int index = rightConstant->getIConst(0);
+
+ const TConstantUnion *constArray = leftConstant->foldIndexing(index);
+ if (!constArray)
{
- mOp = EOpMatrixTimesScalarAssign;
+ return this;
}
+ return CreateFoldedNode(constArray, this, mType.getQualifier());
}
- else if (mLeft->isMatrix() && mRight->isMatrix())
+ case EOpIndexDirectStruct:
{
- mOp = EOpMatrixTimesMatrixAssign;
- setType(TType(basicType, higherPrecision, resultQualifier,
- static_cast<unsigned char>(mRight->getCols()),
- static_cast<unsigned char>(mLeft->getRows())));
- }
- else if (!mLeft->isMatrix() && !mRight->isMatrix())
- {
- if (mLeft->isVector() && mRight->isVector())
+ if (leftConstant == nullptr || rightConstant == nullptr)
{
- // leave as component product
+ return this;
}
- else if (mLeft->isVector() || mRight->isVector())
+ const TFieldList &fields = mLeft->getType().getStruct()->fields();
+ size_t index = static_cast<size_t>(rightConstant->getIConst(0));
+
+ size_t previousFieldsSize = 0;
+ for (size_t i = 0; i < index; ++i)
{
- if (!mLeft->isVector())
- return false;
- mOp = EOpVectorTimesScalarAssign;
- setType(TType(basicType, higherPrecision, resultQualifier,
- static_cast<unsigned char>(mLeft->getNominalSize()), 1));
+ previousFieldsSize += fields[i]->type()->getObjectSize();
}
- }
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(),
- "Missing elses");
- return false;
- }
-
- if (!ValidateMultiplication(mOp, mLeft->getType(), mRight->getType()))
- {
- return false;
- }
- break;
-
- case EOpAssign:
- case EOpInitialize:
- // No more additional checks are needed.
- ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
- (mLeft->getSecondarySize() == mRight->getSecondarySize()));
- break;
- case EOpAdd:
- case EOpSub:
- case EOpDiv:
- case EOpIMod:
- case EOpBitShiftLeft:
- case EOpBitShiftRight:
- case EOpBitwiseAnd:
- case EOpBitwiseXor:
- case EOpBitwiseOr:
- case EOpAddAssign:
- case EOpSubAssign:
- case EOpDivAssign:
- case EOpIModAssign:
- case EOpBitShiftLeftAssign:
- case EOpBitShiftRightAssign:
- case EOpBitwiseAndAssign:
- case EOpBitwiseXorAssign:
- case EOpBitwiseOrAssign:
- if ((mLeft->isMatrix() && mRight->isVector()) ||
- (mLeft->isVector() && mRight->isMatrix()))
- {
- return false;
- }
-
- // Are the sizes compatible?
- if (mLeft->getNominalSize() != mRight->getNominalSize() ||
- mLeft->getSecondarySize() != mRight->getSecondarySize())
- {
- // If the nominal sizes of operands do not match:
- // One of them must be a scalar.
- if (!mLeft->isScalar() && !mRight->isScalar())
- return false;
- // In the case of compound assignment other than multiply-assign,
- // the right side needs to be a scalar. Otherwise a vector/matrix
- // would be assigned to a scalar. A scalar can't be shifted by a
- // vector either.
- if (!mRight->isScalar() &&
- (isAssignment() ||
- mOp == EOpBitShiftLeft ||
- mOp == EOpBitShiftRight))
- return false;
+ const TConstantUnion *constArray = leftConstant->getUnionArrayPointer();
+ return CreateFoldedNode(constArray + previousFieldsSize, this, mType.getQualifier());
}
-
+ case EOpIndexIndirect:
+ case EOpIndexDirectInterfaceBlock:
+ // Can never be constant folded.
+ return this;
+ default:
{
- const int secondarySize = std::max(
- mLeft->getSecondarySize(), mRight->getSecondarySize());
- setType(TType(basicType, higherPrecision, resultQualifier,
- static_cast<unsigned char>(nominalSize),
- static_cast<unsigned char>(secondarySize)));
- if (mLeft->isArray())
+ if (leftConstant == nullptr || rightConstant == nullptr)
{
- ASSERT(mLeft->getArraySize() == mRight->getArraySize());
- mType.setArraySize(mLeft->getArraySize());
+ return this;
+ }
+ TConstantUnion *constArray =
+ leftConstant->foldBinary(mOp, rightConstant, diagnostics, mLeft->getLine());
+ if (!constArray)
+ {
+ return this;
}
- }
- break;
-
- case EOpEqual:
- case EOpNotEqual:
- case EOpLessThan:
- case EOpGreaterThan:
- case EOpLessThanEqual:
- case EOpGreaterThanEqual:
- ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
- (mLeft->getSecondarySize() == mRight->getSecondarySize()));
- setType(TType(EbtBool, EbpUndefined));
- break;
- default:
- return false;
+ // Nodes may be constant folded without being qualified as constant.
+ return CreateFoldedNode(constArray, this, mType.getQualifier());
+ }
}
- return true;
}
-TIntermTyped *TIntermBinary::fold(TInfoSink &infoSink)
+TIntermTyped *TIntermUnary::fold(TDiagnostics *diagnostics)
{
- TIntermConstantUnion *leftConstant = mLeft->getAsConstantUnion();
- TIntermConstantUnion *rightConstant = mRight->getAsConstantUnion();
- if (leftConstant == nullptr || rightConstant == nullptr)
- {
- return nullptr;
- }
- TConstantUnion *constArray = leftConstant->foldBinary(mOp, rightConstant, infoSink);
+ TConstantUnion *constArray = nullptr;
- // Nodes may be constant folded without being qualified as constant.
- TQualifier resultQualifier = EvqConst;
- if (mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst)
+ if (mOp == EOpArrayLength)
{
- resultQualifier = EvqTemporary;
+ // The size of runtime-sized arrays may only be determined at runtime.
+ if (mOperand->hasSideEffects() || mOperand->getType().isUnsizedArray())
+ {
+ return this;
+ }
+ constArray = new TConstantUnion[1];
+ constArray->setIConst(mOperand->getOutermostArraySize());
}
- return CreateFoldedNode(constArray, this, resultQualifier);
-}
-
-TIntermTyped *TIntermUnary::fold(TInfoSink &infoSink)
-{
- TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
- if (operandConstant == nullptr)
+ else
{
- return nullptr;
- }
+ TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
+ if (operandConstant == nullptr)
+ {
+ return this;
+ }
- TConstantUnion *constArray = nullptr;
- switch (mOp)
+ switch (mOp)
+ {
+ case EOpAny:
+ case EOpAll:
+ case EOpLength:
+ case EOpTranspose:
+ case EOpDeterminant:
+ case EOpInverse:
+ case EOpPackSnorm2x16:
+ case EOpUnpackSnorm2x16:
+ case EOpPackUnorm2x16:
+ case EOpUnpackUnorm2x16:
+ case EOpPackHalf2x16:
+ case EOpUnpackHalf2x16:
+ case EOpPackUnorm4x8:
+ case EOpPackSnorm4x8:
+ case EOpUnpackUnorm4x8:
+ case EOpUnpackSnorm4x8:
+ constArray = operandConstant->foldUnaryNonComponentWise(mOp);
+ break;
+ default:
+ constArray = operandConstant->foldUnaryComponentWise(mOp, diagnostics);
+ break;
+ }
+ }
+ if (constArray == nullptr)
{
- case EOpAny:
- case EOpAll:
- case EOpLength:
- case EOpTranspose:
- case EOpDeterminant:
- case EOpInverse:
- case EOpPackSnorm2x16:
- case EOpUnpackSnorm2x16:
- case EOpPackUnorm2x16:
- case EOpUnpackUnorm2x16:
- case EOpPackHalf2x16:
- case EOpUnpackHalf2x16:
- constArray = operandConstant->foldUnaryWithDifferentReturnType(mOp, infoSink);
- break;
- default:
- constArray = operandConstant->foldUnaryWithSameReturnType(mOp, infoSink);
- break;
+ return this;
}
// Nodes may be constant folded without being qualified as constant.
- TQualifier resultQualifier = mOperand->getQualifier() == EvqConst ? EvqConst : EvqTemporary;
- return CreateFoldedNode(constArray, this, resultQualifier);
+ return CreateFoldedNode(constArray, this, mType.getQualifier());
}
-TIntermTyped *TIntermAggregate::fold(TInfoSink &infoSink)
+TIntermTyped *TIntermAggregate::fold(TDiagnostics *diagnostics)
{
// Make sure that all params are constant before actual constant folding.
for (auto *param : *getSequence())
{
if (param->getAsConstantUnion() == nullptr)
{
- return nullptr;
+ return this;
}
}
TConstantUnion *constArray = nullptr;
if (isConstructor())
- constArray = TIntermConstantUnion::FoldAggregateConstructor(this, infoSink);
+ constArray = TIntermConstantUnion::FoldAggregateConstructor(this);
else
- constArray = TIntermConstantUnion::FoldAggregateBuiltIn(this, infoSink);
+ constArray = TIntermConstantUnion::FoldAggregateBuiltIn(this, diagnostics);
// Nodes may be constant folded without being qualified as constant.
- TQualifier resultQualifier = areChildrenConstQualified() ? EvqConst : EvqTemporary;
- return CreateFoldedNode(constArray, this, resultQualifier);
+ return CreateFoldedNode(constArray, this, getQualifier());
}
//
@@ -899,15 +1466,15 @@ TIntermTyped *TIntermAggregate::fold(TInfoSink &infoSink)
//
// Returns the constant value to keep using or nullptr.
//
-TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op, TIntermConstantUnion *rightNode, TInfoSink &infoSink)
+TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op,
+ TIntermConstantUnion *rightNode,
+ TDiagnostics *diagnostics,
+ const TSourceLoc &line)
{
const TConstantUnion *leftArray = getUnionArrayPointer();
const TConstantUnion *rightArray = rightNode->getUnionArrayPointer();
- if (!leftArray)
- return nullptr;
- if (!rightArray)
- return nullptr;
+ ASSERT(leftArray && rightArray);
size_t objectSize = getType().getObjectSize();
@@ -919,48 +1486,45 @@ TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op, TIntermConstantUn
else if (rightNode->getType().getObjectSize() > 1 && objectSize == 1)
{
// for a case like float f = 1.2 + vec4(2, 3, 4, 5);
- leftArray = Vectorize(*getUnionArrayPointer(), rightNode->getType().getObjectSize());
+ leftArray = Vectorize(*getUnionArrayPointer(), rightNode->getType().getObjectSize());
objectSize = rightNode->getType().getObjectSize();
}
TConstantUnion *resultArray = nullptr;
- switch(op)
+ switch (op)
{
- case EOpAdd:
- resultArray = new TConstantUnion[objectSize];
- for (size_t i = 0; i < objectSize; i++)
- resultArray[i] = leftArray[i] + rightArray[i];
- break;
- case EOpSub:
- resultArray = new TConstantUnion[objectSize];
- for (size_t i = 0; i < objectSize; i++)
- resultArray[i] = leftArray[i] - rightArray[i];
- break;
+ case EOpAdd:
+ resultArray = new TConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; i++)
+ resultArray[i] =
+ TConstantUnion::add(leftArray[i], rightArray[i], diagnostics, line);
+ break;
+ case EOpSub:
+ resultArray = new TConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; i++)
+ resultArray[i] =
+ TConstantUnion::sub(leftArray[i], rightArray[i], diagnostics, line);
+ break;
- case EOpMul:
- case EOpVectorTimesScalar:
- case EOpMatrixTimesScalar:
- resultArray = new TConstantUnion[objectSize];
- for (size_t i = 0; i < objectSize; i++)
- resultArray[i] = leftArray[i] * rightArray[i];
- break;
+ case EOpMul:
+ case EOpVectorTimesScalar:
+ case EOpMatrixTimesScalar:
+ resultArray = new TConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; i++)
+ resultArray[i] =
+ TConstantUnion::mul(leftArray[i], rightArray[i], diagnostics, line);
+ break;
- case EOpMatrixTimesMatrix:
+ case EOpMatrixTimesMatrix:
{
- if (getType().getBasicType() != EbtFloat ||
- rightNode->getBasicType() != EbtFloat)
- {
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Constant Folding cannot be done for matrix multiply");
- return nullptr;
- }
+ // TODO(jmadll): This code should check for overflows.
+ ASSERT(getType().getBasicType() == EbtFloat && rightNode->getBasicType() == EbtFloat);
- const int leftCols = getCols();
- const int leftRows = getRows();
- const int rightCols = rightNode->getType().getCols();
- const int rightRows = rightNode->getType().getRows();
+ const int leftCols = getCols();
+ const int leftRows = getRows();
+ const int rightCols = rightNode->getType().getCols();
+ const int rightRows = rightNode->getType().getRows();
const int resultCols = rightCols;
const int resultRows = leftRows;
@@ -975,94 +1539,155 @@ TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op, TIntermConstantUn
resultArray[resultRows * column + row].setFConst(
resultArray[resultRows * column + row].getFConst() +
leftArray[i * leftRows + row].getFConst() *
- rightArray[column * rightRows + i].getFConst());
+ rightArray[column * rightRows + i].getFConst());
}
}
}
}
break;
- case EOpDiv:
- case EOpIMod:
+ case EOpDiv:
+ case EOpIMod:
{
resultArray = new TConstantUnion[objectSize];
for (size_t i = 0; i < objectSize; i++)
{
switch (getType().getBasicType())
{
- case EbtFloat:
- if (rightArray[i] == 0.0f)
- {
- infoSink.info.message(EPrefixWarning, getLine(),
- "Divide by zero error during constant folding");
- resultArray[i].setFConst(leftArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX);
- }
- else
+ case EbtFloat:
{
ASSERT(op == EOpDiv);
- resultArray[i].setFConst(leftArray[i].getFConst() / rightArray[i].getFConst());
- }
- break;
-
- case EbtInt:
- if (rightArray[i] == 0)
- {
- infoSink.info.message(EPrefixWarning, getLine(),
- "Divide by zero error during constant folding");
- resultArray[i].setIConst(INT_MAX);
- }
- else
- {
- if (op == EOpDiv)
+ float dividend = leftArray[i].getFConst();
+ float divisor = rightArray[i].getFConst();
+ if (divisor == 0.0f)
+ {
+ if (dividend == 0.0f)
+ {
+ diagnostics->warning(
+ getLine(),
+ "Zero divided by zero during constant folding generated NaN",
+ "/");
+ resultArray[i].setFConst(std::numeric_limits<float>::quiet_NaN());
+ }
+ else
+ {
+ diagnostics->warning(getLine(),
+ "Divide by zero during constant folding", "/");
+ bool negativeResult =
+ std::signbit(dividend) != std::signbit(divisor);
+ resultArray[i].setFConst(
+ negativeResult ? -std::numeric_limits<float>::infinity()
+ : std::numeric_limits<float>::infinity());
+ }
+ }
+ else if (gl::isInf(dividend) && gl::isInf(divisor))
{
- resultArray[i].setIConst(leftArray[i].getIConst() / rightArray[i].getIConst());
+ diagnostics->warning(getLine(),
+ "Infinity divided by infinity during constant "
+ "folding generated NaN",
+ "/");
+ resultArray[i].setFConst(std::numeric_limits<float>::quiet_NaN());
}
else
{
- ASSERT(op == EOpIMod);
- resultArray[i].setIConst(leftArray[i].getIConst() % rightArray[i].getIConst());
+ float result = dividend / divisor;
+ if (!gl::isInf(dividend) && gl::isInf(result))
+ {
+ diagnostics->warning(
+ getLine(), "Constant folded division overflowed to infinity",
+ "/");
+ }
+ resultArray[i].setFConst(result);
}
+ break;
}
- break;
+ case EbtInt:
+ if (rightArray[i] == 0)
+ {
+ diagnostics->warning(
+ getLine(), "Divide by zero error during constant folding", "/");
+ resultArray[i].setIConst(INT_MAX);
+ }
+ else
+ {
+ int lhs = leftArray[i].getIConst();
+ int divisor = rightArray[i].getIConst();
+ if (op == EOpDiv)
+ {
+ // Check for the special case where the minimum representable number
+ // is
+ // divided by -1. If left alone this leads to integer overflow in
+ // C++.
+ // ESSL 3.00.6 section 4.1.3 Integers:
+ // "However, for the case where the minimum representable value is
+ // divided by -1, it is allowed to return either the minimum
+ // representable value or the maximum representable value."
+ if (lhs == -0x7fffffff - 1 && divisor == -1)
+ {
+ resultArray[i].setIConst(0x7fffffff);
+ }
+ else
+ {
+ resultArray[i].setIConst(lhs / divisor);
+ }
+ }
+ else
+ {
+ ASSERT(op == EOpIMod);
+ if (lhs < 0 || divisor < 0)
+ {
+ // ESSL 3.00.6 section 5.9: Results of modulus are undefined
+ // when
+ // either one of the operands is negative.
+ diagnostics->warning(getLine(),
+ "Negative modulus operator operand "
+ "encountered during constant folding",
+ "%");
+ resultArray[i].setIConst(0);
+ }
+ else
+ {
+ resultArray[i].setIConst(lhs % divisor);
+ }
+ }
+ }
+ break;
- case EbtUInt:
- if (rightArray[i] == 0)
- {
- infoSink.info.message(EPrefixWarning, getLine(),
- "Divide by zero error during constant folding");
- resultArray[i].setUConst(UINT_MAX);
- }
- else
- {
- if (op == EOpDiv)
+ case EbtUInt:
+ if (rightArray[i] == 0)
{
- resultArray[i].setUConst(leftArray[i].getUConst() / rightArray[i].getUConst());
+ diagnostics->warning(
+ getLine(), "Divide by zero error during constant folding", "/");
+ resultArray[i].setUConst(UINT_MAX);
}
else
{
- ASSERT(op == EOpIMod);
- resultArray[i].setUConst(leftArray[i].getUConst() % rightArray[i].getUConst());
+ if (op == EOpDiv)
+ {
+ resultArray[i].setUConst(leftArray[i].getUConst() /
+ rightArray[i].getUConst());
+ }
+ else
+ {
+ ASSERT(op == EOpIMod);
+ resultArray[i].setUConst(leftArray[i].getUConst() %
+ rightArray[i].getUConst());
+ }
}
- }
- break;
+ break;
- default:
- infoSink.info.message(EPrefixInternalError, getLine(),
- "Constant folding cannot be done for \"/\"");
- return nullptr;
+ default:
+ UNREACHABLE();
+ return nullptr;
}
}
}
break;
- case EOpMatrixTimesVector:
+ case EOpMatrixTimesVector:
{
- if (rightNode->getBasicType() != EbtFloat)
- {
- infoSink.info.message(EPrefixInternalError, getLine(),
- "Constant Folding cannot be done for matrix times vector");
- return nullptr;
- }
+ // TODO(jmadll): This code should check for overflows.
+ ASSERT(rightNode->getBasicType() == EbtFloat);
const int matrixCols = getCols();
const int matrixRows = getRows();
@@ -1074,22 +1699,19 @@ TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op, TIntermConstantUn
resultArray[matrixRow].setFConst(0.0f);
for (int col = 0; col < matrixCols; col++)
{
- resultArray[matrixRow].setFConst(resultArray[matrixRow].getFConst() +
- leftArray[col * matrixRows + matrixRow].getFConst() *
- rightArray[col].getFConst());
+ resultArray[matrixRow].setFConst(
+ resultArray[matrixRow].getFConst() +
+ leftArray[col * matrixRows + matrixRow].getFConst() *
+ rightArray[col].getFConst());
}
}
}
break;
- case EOpVectorTimesMatrix:
+ case EOpVectorTimesMatrix:
{
- if (getType().getBasicType() != EbtFloat)
- {
- infoSink.info.message(EPrefixInternalError, getLine(),
- "Constant Folding cannot be done for vector times matrix");
- return nullptr;
- }
+ // TODO(jmadll): This code should check for overflows.
+ ASSERT(getType().getBasicType() == EbtFloat);
const int matrixCols = rightNode->getType().getCols();
const int matrixRows = rightNode->getType().getRows();
@@ -1101,15 +1723,16 @@ TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op, TIntermConstantUn
resultArray[matrixCol].setFConst(0.0f);
for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
{
- resultArray[matrixCol].setFConst(resultArray[matrixCol].getFConst() +
- leftArray[matrixRow].getFConst() *
- rightArray[matrixCol * matrixRows + matrixRow].getFConst());
+ resultArray[matrixCol].setFConst(
+ resultArray[matrixCol].getFConst() +
+ leftArray[matrixRow].getFConst() *
+ rightArray[matrixCol * matrixRows + matrixRow].getFConst());
}
}
}
break;
- case EOpLogicalAnd:
+ case EOpLogicalAnd:
{
resultArray = new TConstantUnion[objectSize];
for (size_t i = 0; i < objectSize; i++)
@@ -1119,7 +1742,7 @@ TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op, TIntermConstantUn
}
break;
- case EOpLogicalOr:
+ case EOpLogicalOr:
{
resultArray = new TConstantUnion[objectSize];
for (size_t i = 0; i < objectSize; i++)
@@ -1129,79 +1752,74 @@ TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op, TIntermConstantUn
}
break;
- case EOpLogicalXor:
+ case EOpLogicalXor:
{
+ ASSERT(getType().getBasicType() == EbtBool);
resultArray = new TConstantUnion[objectSize];
for (size_t i = 0; i < objectSize; i++)
{
- switch (getType().getBasicType())
- {
- case EbtBool:
- resultArray[i].setBConst(leftArray[i] != rightArray[i]);
- break;
- default:
- UNREACHABLE();
- break;
- }
+ resultArray[i].setBConst(leftArray[i] != rightArray[i]);
}
}
break;
- case EOpBitwiseAnd:
- resultArray = new TConstantUnion[objectSize];
- for (size_t i = 0; i < objectSize; i++)
- resultArray[i] = leftArray[i] & rightArray[i];
- break;
- case EOpBitwiseXor:
- resultArray = new TConstantUnion[objectSize];
- for (size_t i = 0; i < objectSize; i++)
- resultArray[i] = leftArray[i] ^ rightArray[i];
- break;
- case EOpBitwiseOr:
- resultArray = new TConstantUnion[objectSize];
- for (size_t i = 0; i < objectSize; i++)
- resultArray[i] = leftArray[i] | rightArray[i];
- break;
- case EOpBitShiftLeft:
- resultArray = new TConstantUnion[objectSize];
- for (size_t i = 0; i < objectSize; i++)
- resultArray[i] = leftArray[i] << rightArray[i];
- break;
- case EOpBitShiftRight:
- resultArray = new TConstantUnion[objectSize];
- for (size_t i = 0; i < objectSize; i++)
- resultArray[i] = leftArray[i] >> rightArray[i];
- break;
+ case EOpBitwiseAnd:
+ resultArray = new TConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; i++)
+ resultArray[i] = leftArray[i] & rightArray[i];
+ break;
+ case EOpBitwiseXor:
+ resultArray = new TConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; i++)
+ resultArray[i] = leftArray[i] ^ rightArray[i];
+ break;
+ case EOpBitwiseOr:
+ resultArray = new TConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; i++)
+ resultArray[i] = leftArray[i] | rightArray[i];
+ break;
+ case EOpBitShiftLeft:
+ resultArray = new TConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; i++)
+ resultArray[i] =
+ TConstantUnion::lshift(leftArray[i], rightArray[i], diagnostics, line);
+ break;
+ case EOpBitShiftRight:
+ resultArray = new TConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; i++)
+ resultArray[i] =
+ TConstantUnion::rshift(leftArray[i], rightArray[i], diagnostics, line);
+ break;
- case EOpLessThan:
- ASSERT(objectSize == 1);
- resultArray = new TConstantUnion[1];
- resultArray->setBConst(*leftArray < *rightArray);
- break;
+ case EOpLessThan:
+ ASSERT(objectSize == 1);
+ resultArray = new TConstantUnion[1];
+ resultArray->setBConst(*leftArray < *rightArray);
+ break;
- case EOpGreaterThan:
- ASSERT(objectSize == 1);
- resultArray = new TConstantUnion[1];
- resultArray->setBConst(*leftArray > *rightArray);
- break;
+ case EOpGreaterThan:
+ ASSERT(objectSize == 1);
+ resultArray = new TConstantUnion[1];
+ resultArray->setBConst(*leftArray > *rightArray);
+ break;
- case EOpLessThanEqual:
- ASSERT(objectSize == 1);
- resultArray = new TConstantUnion[1];
- resultArray->setBConst(!(*leftArray > *rightArray));
- break;
+ case EOpLessThanEqual:
+ ASSERT(objectSize == 1);
+ resultArray = new TConstantUnion[1];
+ resultArray->setBConst(!(*leftArray > *rightArray));
+ break;
- case EOpGreaterThanEqual:
- ASSERT(objectSize == 1);
- resultArray = new TConstantUnion[1];
- resultArray->setBConst(!(*leftArray < *rightArray));
- break;
+ case EOpGreaterThanEqual:
+ ASSERT(objectSize == 1);
+ resultArray = new TConstantUnion[1];
+ resultArray->setBConst(!(*leftArray < *rightArray));
+ break;
- case EOpEqual:
- case EOpNotEqual:
+ case EOpEqual:
+ case EOpNotEqual:
{
resultArray = new TConstantUnion[1];
- bool equal = true;
+ bool equal = true;
for (size_t i = 0; i < objectSize; i++)
{
if (leftArray[i] != rightArray[i])
@@ -1221,38 +1839,29 @@ TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op, TIntermConstantUn
}
break;
- default:
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Invalid operator for constant folding");
- return nullptr;
+ default:
+ UNREACHABLE();
+ return nullptr;
}
return resultArray;
}
-//
-// The fold functions see if an operation on a constant can be done in place,
-// without generating run-time code.
-//
-// Returns the constant value to keep using or nullptr.
-//
-TConstantUnion *TIntermConstantUnion::foldUnaryWithDifferentReturnType(TOperator op, TInfoSink &infoSink)
+// The fold functions do operations on a constant at GLSL compile time, without generating run-time
+// code. Returns the constant value to keep using. Nullptr should not be returned.
+TConstantUnion *TIntermConstantUnion::foldUnaryNonComponentWise(TOperator op)
{
- //
- // Do operations where the return type has a different number of components compared to the operand type.
- //
+ // Do operations where the return type may have a different number of components compared to the
+ // operand type.
const TConstantUnion *operandArray = getUnionArrayPointer();
- if (!operandArray)
- return nullptr;
+ ASSERT(operandArray);
- size_t objectSize = getType().getObjectSize();
+ size_t objectSize = getType().getObjectSize();
TConstantUnion *resultArray = nullptr;
switch (op)
{
- case EOpAny:
- if (getType().getBasicType() == EbtBool)
- {
+ case EOpAny:
+ ASSERT(getType().getBasicType() == EbtBool);
resultArray = new TConstantUnion();
resultArray->setBConst(false);
for (size_t i = 0; i < objectSize; i++)
@@ -1264,16 +1873,9 @@ TConstantUnion *TIntermConstantUnion::foldUnaryWithDifferentReturnType(TOperator
}
}
break;
- }
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- }
- case EOpAll:
- if (getType().getBasicType() == EbtBool)
- {
+ case EOpAll:
+ ASSERT(getType().getBasicType() == EbtBool);
resultArray = new TConstantUnion();
resultArray->setBConst(true);
for (size_t i = 0; i < objectSize; i++)
@@ -1285,89 +1887,55 @@ TConstantUnion *TIntermConstantUnion::foldUnaryWithDifferentReturnType(TOperator
}
}
break;
- }
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- }
- case EOpLength:
- if (getType().getBasicType() == EbtFloat)
- {
+ case EOpLength:
+ ASSERT(getType().getBasicType() == EbtFloat);
resultArray = new TConstantUnion();
resultArray->setFConst(VectorLength(operandArray, objectSize));
break;
- }
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- }
- case EOpTranspose:
- if (getType().getBasicType() == EbtFloat)
+ case EOpTranspose:
{
+ ASSERT(getType().getBasicType() == EbtFloat);
resultArray = new TConstantUnion[objectSize];
angle::Matrix<float> result =
- GetMatrix(operandArray, getType().getNominalSize(), getType().getSecondarySize()).transpose();
+ GetMatrix(operandArray, getType().getRows(), getType().getCols()).transpose();
SetUnionArrayFromMatrix(result, resultArray);
break;
}
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- }
- case EOpDeterminant:
- if (getType().getBasicType() == EbtFloat)
+ case EOpDeterminant:
{
+ ASSERT(getType().getBasicType() == EbtFloat);
unsigned int size = getType().getNominalSize();
ASSERT(size >= 2 && size <= 4);
resultArray = new TConstantUnion();
resultArray->setFConst(GetMatrix(operandArray, size).determinant());
break;
}
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- }
- case EOpInverse:
- if (getType().getBasicType() == EbtFloat)
+ case EOpInverse:
{
+ ASSERT(getType().getBasicType() == EbtFloat);
unsigned int size = getType().getNominalSize();
ASSERT(size >= 2 && size <= 4);
- resultArray = new TConstantUnion[objectSize];
+ resultArray = new TConstantUnion[objectSize];
angle::Matrix<float> result = GetMatrix(operandArray, size).inverse();
SetUnionArrayFromMatrix(result, resultArray);
break;
}
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- }
- case EOpPackSnorm2x16:
- if (getType().getBasicType() == EbtFloat)
- {
+ case EOpPackSnorm2x16:
+ ASSERT(getType().getBasicType() == EbtFloat);
ASSERT(getType().getNominalSize() == 2);
resultArray = new TConstantUnion();
- resultArray->setUConst(gl::packSnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
+ resultArray->setUConst(
+ gl::packSnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
break;
- }
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- }
- case EOpUnpackSnorm2x16:
- if (getType().getBasicType() == EbtUInt)
+ case EOpUnpackSnorm2x16:
{
+ ASSERT(getType().getBasicType() == EbtUInt);
resultArray = new TConstantUnion[2];
float f1, f2;
gl::unpackSnorm2x16(operandArray[0].getUConst(), &f1, &f2);
@@ -1375,29 +1943,18 @@ TConstantUnion *TIntermConstantUnion::foldUnaryWithDifferentReturnType(TOperator
resultArray[1].setFConst(f2);
break;
}
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- }
- case EOpPackUnorm2x16:
- if (getType().getBasicType() == EbtFloat)
- {
+ case EOpPackUnorm2x16:
+ ASSERT(getType().getBasicType() == EbtFloat);
ASSERT(getType().getNominalSize() == 2);
resultArray = new TConstantUnion();
- resultArray->setUConst(gl::packUnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
+ resultArray->setUConst(
+ gl::packUnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
break;
- }
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- }
- case EOpUnpackUnorm2x16:
- if (getType().getBasicType() == EbtUInt)
+ case EOpUnpackUnorm2x16:
{
+ ASSERT(getType().getBasicType() == EbtUInt);
resultArray = new TConstantUnion[2];
float f1, f2;
gl::unpackUnorm2x16(operandArray[0].getUConst(), &f1, &f2);
@@ -1405,29 +1962,18 @@ TConstantUnion *TIntermConstantUnion::foldUnaryWithDifferentReturnType(TOperator
resultArray[1].setFConst(f2);
break;
}
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- }
- case EOpPackHalf2x16:
- if (getType().getBasicType() == EbtFloat)
- {
+ case EOpPackHalf2x16:
+ ASSERT(getType().getBasicType() == EbtFloat);
ASSERT(getType().getNominalSize() == 2);
resultArray = new TConstantUnion();
- resultArray->setUConst(gl::packHalf2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
+ resultArray->setUConst(
+ gl::packHalf2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
break;
- }
- else
- {
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- }
- case EOpUnpackHalf2x16:
- if (getType().getBasicType() == EbtUInt)
+ case EOpUnpackHalf2x16:
{
+ ASSERT(getType().getBasicType() == EbtUInt);
resultArray = new TConstantUnion[2];
float f1, f2;
gl::unpackHalf2x16(operandArray[0].getUConst(), &f1, &f2);
@@ -1435,274 +1981,301 @@ TConstantUnion *TIntermConstantUnion::foldUnaryWithDifferentReturnType(TOperator
resultArray[1].setFConst(f2);
break;
}
- else
+
+ case EOpPackUnorm4x8:
{
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
+ ASSERT(getType().getBasicType() == EbtFloat);
+ resultArray = new TConstantUnion();
+ resultArray->setUConst(
+ gl::PackUnorm4x8(operandArray[0].getFConst(), operandArray[1].getFConst(),
+ operandArray[2].getFConst(), operandArray[3].getFConst()));
+ break;
+ }
+ case EOpPackSnorm4x8:
+ {
+ ASSERT(getType().getBasicType() == EbtFloat);
+ resultArray = new TConstantUnion();
+ resultArray->setUConst(
+ gl::PackSnorm4x8(operandArray[0].getFConst(), operandArray[1].getFConst(),
+ operandArray[2].getFConst(), operandArray[3].getFConst()));
+ break;
+ }
+ case EOpUnpackUnorm4x8:
+ {
+ ASSERT(getType().getBasicType() == EbtUInt);
+ resultArray = new TConstantUnion[4];
+ float f[4];
+ gl::UnpackUnorm4x8(operandArray[0].getUConst(), f);
+ for (size_t i = 0; i < 4; ++i)
+ {
+ resultArray[i].setFConst(f[i]);
+ }
+ break;
+ }
+ case EOpUnpackSnorm4x8:
+ {
+ ASSERT(getType().getBasicType() == EbtUInt);
+ resultArray = new TConstantUnion[4];
+ float f[4];
+ gl::UnpackSnorm4x8(operandArray[0].getUConst(), f);
+ for (size_t i = 0; i < 4; ++i)
+ {
+ resultArray[i].setFConst(f[i]);
+ }
+ break;
}
- break;
- default:
- break;
+ default:
+ UNREACHABLE();
+ break;
}
return resultArray;
}
-TConstantUnion *TIntermConstantUnion::foldUnaryWithSameReturnType(TOperator op, TInfoSink &infoSink)
+TConstantUnion *TIntermConstantUnion::foldUnaryComponentWise(TOperator op,
+ TDiagnostics *diagnostics)
{
- //
- // Do unary operations where the return type is the same as operand type.
- //
+ // Do unary operations where each component of the result is computed based on the corresponding
+ // component of the operand. Also folds normalize, though the divisor in that case takes all
+ // components into account.
const TConstantUnion *operandArray = getUnionArrayPointer();
- if (!operandArray)
- return nullptr;
+ ASSERT(operandArray);
size_t objectSize = getType().getObjectSize();
TConstantUnion *resultArray = new TConstantUnion[objectSize];
for (size_t i = 0; i < objectSize; i++)
{
- switch(op)
+ switch (op)
{
- case EOpNegative:
- switch (getType().getBasicType())
- {
- case EbtFloat:
- resultArray[i].setFConst(-operandArray[i].getFConst());
- break;
- case EbtInt:
- resultArray[i].setIConst(-operandArray[i].getIConst());
- break;
- case EbtUInt:
- resultArray[i].setUConst(static_cast<unsigned int>(
- -static_cast<int>(operandArray[i].getUConst())));
+ case EOpNegative:
+ switch (getType().getBasicType())
+ {
+ case EbtFloat:
+ resultArray[i].setFConst(-operandArray[i].getFConst());
+ break;
+ case EbtInt:
+ if (operandArray[i] == std::numeric_limits<int>::min())
+ {
+ // The minimum representable integer doesn't have a positive
+ // counterpart, rather the negation overflows and in ESSL is supposed to
+ // wrap back to the minimum representable integer. Make sure that we
+ // don't actually let the negation overflow, which has undefined
+ // behavior in C++.
+ resultArray[i].setIConst(std::numeric_limits<int>::min());
+ }
+ else
+ {
+ resultArray[i].setIConst(-operandArray[i].getIConst());
+ }
+ break;
+ case EbtUInt:
+ if (operandArray[i] == 0x80000000u)
+ {
+ resultArray[i].setUConst(0x80000000u);
+ }
+ else
+ {
+ resultArray[i].setUConst(static_cast<unsigned int>(
+ -static_cast<int>(operandArray[i].getUConst())));
+ }
+ break;
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
break;
- default:
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Unary operation not folded into constant");
- return nullptr;
- }
- break;
- case EOpPositive:
- switch (getType().getBasicType())
- {
- case EbtFloat:
- resultArray[i].setFConst(operandArray[i].getFConst());
- break;
- case EbtInt:
- resultArray[i].setIConst(operandArray[i].getIConst());
- break;
- case EbtUInt:
- resultArray[i].setUConst(static_cast<unsigned int>(
- static_cast<int>(operandArray[i].getUConst())));
+ case EOpPositive:
+ switch (getType().getBasicType())
+ {
+ case EbtFloat:
+ resultArray[i].setFConst(operandArray[i].getFConst());
+ break;
+ case EbtInt:
+ resultArray[i].setIConst(operandArray[i].getIConst());
+ break;
+ case EbtUInt:
+ resultArray[i].setUConst(static_cast<unsigned int>(
+ static_cast<int>(operandArray[i].getUConst())));
+ break;
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
break;
- default:
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Unary operation not folded into constant");
- return nullptr;
- }
- break;
- case EOpLogicalNot:
- // this code is written for possible future use,
- // will not get executed currently
- switch (getType().getBasicType())
- {
- case EbtBool:
- resultArray[i].setBConst(!operandArray[i].getBConst());
+ case EOpLogicalNot:
+ switch (getType().getBasicType())
+ {
+ case EbtBool:
+ resultArray[i].setBConst(!operandArray[i].getBConst());
+ break;
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
break;
- default:
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Unary operation not folded into constant");
- return nullptr;
- }
- break;
- case EOpBitwiseNot:
- switch (getType().getBasicType())
- {
- case EbtInt:
- resultArray[i].setIConst(~operandArray[i].getIConst());
- break;
- case EbtUInt:
- resultArray[i].setUConst(~operandArray[i].getUConst());
+ case EOpBitwiseNot:
+ switch (getType().getBasicType())
+ {
+ case EbtInt:
+ resultArray[i].setIConst(~operandArray[i].getIConst());
+ break;
+ case EbtUInt:
+ resultArray[i].setUConst(~operandArray[i].getUConst());
+ break;
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
break;
- default:
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Unary operation not folded into constant");
- return nullptr;
- }
- break;
- case EOpRadians:
- if (getType().getBasicType() == EbtFloat)
- {
+ case EOpRadians:
+ ASSERT(getType().getBasicType() == EbtFloat);
resultArray[i].setFConst(kDegreesToRadiansMultiplier * operandArray[i].getFConst());
break;
- }
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Unary operation not folded into constant");
- return nullptr;
- case EOpDegrees:
- if (getType().getBasicType() == EbtFloat)
- {
+ case EOpDegrees:
+ ASSERT(getType().getBasicType() == EbtFloat);
resultArray[i].setFConst(kRadiansToDegreesMultiplier * operandArray[i].getFConst());
break;
- }
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Unary operation not folded into constant");
- return nullptr;
-
- case EOpSin:
- if (!foldFloatTypeUnary(operandArray[i], &sinf, infoSink, &resultArray[i]))
- return nullptr;
- break;
-
- case EOpCos:
- if (!foldFloatTypeUnary(operandArray[i], &cosf, infoSink, &resultArray[i]))
- return nullptr;
- break;
- case EOpTan:
- if (!foldFloatTypeUnary(operandArray[i], &tanf, infoSink, &resultArray[i]))
- return nullptr;
- break;
+ case EOpSin:
+ foldFloatTypeUnary(operandArray[i], &sinf, &resultArray[i]);
+ break;
- case EOpAsin:
- // For asin(x), results are undefined if |x| > 1, we are choosing to set result to 0.
- if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) > 1.0f)
- UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
- else if (!foldFloatTypeUnary(operandArray[i], &asinf, infoSink, &resultArray[i]))
- return nullptr;
- break;
+ case EOpCos:
+ foldFloatTypeUnary(operandArray[i], &cosf, &resultArray[i]);
+ break;
- case EOpAcos:
- // For acos(x), results are undefined if |x| > 1, we are choosing to set result to 0.
- if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) > 1.0f)
- UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
- else if (!foldFloatTypeUnary(operandArray[i], &acosf, infoSink, &resultArray[i]))
- return nullptr;
- break;
+ case EOpTan:
+ foldFloatTypeUnary(operandArray[i], &tanf, &resultArray[i]);
+ break;
- case EOpAtan:
- if (!foldFloatTypeUnary(operandArray[i], &atanf, infoSink, &resultArray[i]))
- return nullptr;
- break;
+ case EOpAsin:
+ // For asin(x), results are undefined if |x| > 1, we are choosing to set result to
+ // 0.
+ if (fabsf(operandArray[i].getFConst()) > 1.0f)
+ UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
+ diagnostics, &resultArray[i]);
+ else
+ foldFloatTypeUnary(operandArray[i], &asinf, &resultArray[i]);
+ break;
- case EOpSinh:
- if (!foldFloatTypeUnary(operandArray[i], &sinhf, infoSink, &resultArray[i]))
- return nullptr;
- break;
+ case EOpAcos:
+ // For acos(x), results are undefined if |x| > 1, we are choosing to set result to
+ // 0.
+ if (fabsf(operandArray[i].getFConst()) > 1.0f)
+ UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
+ diagnostics, &resultArray[i]);
+ else
+ foldFloatTypeUnary(operandArray[i], &acosf, &resultArray[i]);
+ break;
- case EOpCosh:
- if (!foldFloatTypeUnary(operandArray[i], &coshf, infoSink, &resultArray[i]))
- return nullptr;
- break;
+ case EOpAtan:
+ foldFloatTypeUnary(operandArray[i], &atanf, &resultArray[i]);
+ break;
- case EOpTanh:
- if (!foldFloatTypeUnary(operandArray[i], &tanhf, infoSink, &resultArray[i]))
- return nullptr;
- break;
+ case EOpSinh:
+ foldFloatTypeUnary(operandArray[i], &sinhf, &resultArray[i]);
+ break;
- case EOpAsinh:
- if (!foldFloatTypeUnary(operandArray[i], &asinhf, infoSink, &resultArray[i]))
- return nullptr;
- break;
+ case EOpCosh:
+ foldFloatTypeUnary(operandArray[i], &coshf, &resultArray[i]);
+ break;
- case EOpAcosh:
- // For acosh(x), results are undefined if x < 1, we are choosing to set result to 0.
- if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() < 1.0f)
- UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
- else if (!foldFloatTypeUnary(operandArray[i], &acoshf, infoSink, &resultArray[i]))
- return nullptr;
- break;
+ case EOpTanh:
+ foldFloatTypeUnary(operandArray[i], &tanhf, &resultArray[i]);
+ break;
- case EOpAtanh:
- // For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to 0.
- if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) >= 1.0f)
- UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
- else if (!foldFloatTypeUnary(operandArray[i], &atanhf, infoSink, &resultArray[i]))
- return nullptr;
- break;
+ case EOpAsinh:
+ foldFloatTypeUnary(operandArray[i], &asinhf, &resultArray[i]);
+ break;
- case EOpAbs:
- switch (getType().getBasicType())
- {
- case EbtFloat:
- resultArray[i].setFConst(fabsf(operandArray[i].getFConst()));
+ case EOpAcosh:
+ // For acosh(x), results are undefined if x < 1, we are choosing to set result to 0.
+ if (operandArray[i].getFConst() < 1.0f)
+ UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
+ diagnostics, &resultArray[i]);
+ else
+ foldFloatTypeUnary(operandArray[i], &acoshf, &resultArray[i]);
break;
- case EbtInt:
- resultArray[i].setIConst(abs(operandArray[i].getIConst()));
+
+ case EOpAtanh:
+ // For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to
+ // 0.
+ if (fabsf(operandArray[i].getFConst()) >= 1.0f)
+ UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
+ diagnostics, &resultArray[i]);
+ else
+ foldFloatTypeUnary(operandArray[i], &atanhf, &resultArray[i]);
break;
- default:
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Unary operation not folded into constant");
- return nullptr;
- }
- break;
- case EOpSign:
- switch (getType().getBasicType())
- {
- case EbtFloat:
+ case EOpAbs:
+ switch (getType().getBasicType())
{
- float fConst = operandArray[i].getFConst();
- float fResult = 0.0f;
- if (fConst > 0.0f)
- fResult = 1.0f;
- else if (fConst < 0.0f)
- fResult = -1.0f;
- resultArray[i].setFConst(fResult);
+ case EbtFloat:
+ resultArray[i].setFConst(fabsf(operandArray[i].getFConst()));
+ break;
+ case EbtInt:
+ resultArray[i].setIConst(abs(operandArray[i].getIConst()));
+ break;
+ default:
+ UNREACHABLE();
+ return nullptr;
}
break;
- case EbtInt:
+
+ case EOpSign:
+ switch (getType().getBasicType())
{
- int iConst = operandArray[i].getIConst();
- int iResult = 0;
- if (iConst > 0)
- iResult = 1;
- else if (iConst < 0)
- iResult = -1;
- resultArray[i].setIConst(iResult);
+ case EbtFloat:
+ {
+ float fConst = operandArray[i].getFConst();
+ float fResult = 0.0f;
+ if (fConst > 0.0f)
+ fResult = 1.0f;
+ else if (fConst < 0.0f)
+ fResult = -1.0f;
+ resultArray[i].setFConst(fResult);
+ break;
+ }
+ case EbtInt:
+ {
+ int iConst = operandArray[i].getIConst();
+ int iResult = 0;
+ if (iConst > 0)
+ iResult = 1;
+ else if (iConst < 0)
+ iResult = -1;
+ resultArray[i].setIConst(iResult);
+ break;
+ }
+ default:
+ UNREACHABLE();
+ return nullptr;
}
break;
- default:
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Unary operation not folded into constant");
- return nullptr;
- }
- break;
- case EOpFloor:
- if (!foldFloatTypeUnary(operandArray[i], &floorf, infoSink, &resultArray[i]))
- return nullptr;
- break;
+ case EOpFloor:
+ foldFloatTypeUnary(operandArray[i], &floorf, &resultArray[i]);
+ break;
- case EOpTrunc:
- if (!foldFloatTypeUnary(operandArray[i], &truncf, infoSink, &resultArray[i]))
- return nullptr;
- break;
+ case EOpTrunc:
+ foldFloatTypeUnary(operandArray[i], &truncf, &resultArray[i]);
+ break;
- case EOpRound:
- if (!foldFloatTypeUnary(operandArray[i], &roundf, infoSink, &resultArray[i]))
- return nullptr;
- break;
+ case EOpRound:
+ foldFloatTypeUnary(operandArray[i], &roundf, &resultArray[i]);
+ break;
- case EOpRoundEven:
- if (getType().getBasicType() == EbtFloat)
+ case EOpRoundEven:
{
+ ASSERT(getType().getBasicType() == EbtFloat);
float x = operandArray[i].getFConst();
float result;
float fractPart = modff(x, &result);
@@ -1713,197 +2286,226 @@ TConstantUnion *TIntermConstantUnion::foldUnaryWithSameReturnType(TOperator op,
resultArray[i].setFConst(result);
break;
}
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Unary operation not folded into constant");
- return nullptr;
- case EOpCeil:
- if (!foldFloatTypeUnary(operandArray[i], &ceilf, infoSink, &resultArray[i]))
- return nullptr;
- break;
+ case EOpCeil:
+ foldFloatTypeUnary(operandArray[i], &ceilf, &resultArray[i]);
+ break;
- case EOpFract:
- if (getType().getBasicType() == EbtFloat)
+ case EOpFract:
{
+ ASSERT(getType().getBasicType() == EbtFloat);
float x = operandArray[i].getFConst();
resultArray[i].setFConst(x - floorf(x));
break;
}
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Unary operation not folded into constant");
- return nullptr;
- case EOpIsNan:
- if (getType().getBasicType() == EbtFloat)
- {
+ case EOpIsNan:
+ ASSERT(getType().getBasicType() == EbtFloat);
resultArray[i].setBConst(gl::isNaN(operandArray[0].getFConst()));
break;
- }
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- case EOpIsInf:
- if (getType().getBasicType() == EbtFloat)
- {
+ case EOpIsInf:
+ ASSERT(getType().getBasicType() == EbtFloat);
resultArray[i].setBConst(gl::isInf(operandArray[0].getFConst()));
break;
- }
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- case EOpFloatBitsToInt:
- if (getType().getBasicType() == EbtFloat)
- {
+ case EOpFloatBitsToInt:
+ ASSERT(getType().getBasicType() == EbtFloat);
resultArray[i].setIConst(gl::bitCast<int32_t>(operandArray[0].getFConst()));
break;
- }
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- case EOpFloatBitsToUint:
- if (getType().getBasicType() == EbtFloat)
- {
+ case EOpFloatBitsToUint:
+ ASSERT(getType().getBasicType() == EbtFloat);
resultArray[i].setUConst(gl::bitCast<uint32_t>(operandArray[0].getFConst()));
break;
- }
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- case EOpIntBitsToFloat:
- if (getType().getBasicType() == EbtInt)
- {
+ case EOpIntBitsToFloat:
+ ASSERT(getType().getBasicType() == EbtInt);
resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getIConst()));
break;
- }
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- case EOpUintBitsToFloat:
- if (getType().getBasicType() == EbtUInt)
- {
+ case EOpUintBitsToFloat:
+ ASSERT(getType().getBasicType() == EbtUInt);
resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getUConst()));
break;
- }
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- case EOpExp:
- if (!foldFloatTypeUnary(operandArray[i], &expf, infoSink, &resultArray[i]))
- return nullptr;
- break;
+ case EOpExp:
+ foldFloatTypeUnary(operandArray[i], &expf, &resultArray[i]);
+ break;
- case EOpLog:
- // For log(x), results are undefined if x <= 0, we are choosing to set result to 0.
- if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() <= 0.0f)
- UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
- else if (!foldFloatTypeUnary(operandArray[i], &logf, infoSink, &resultArray[i]))
- return nullptr;
- break;
+ case EOpLog:
+ // For log(x), results are undefined if x <= 0, we are choosing to set result to 0.
+ if (operandArray[i].getFConst() <= 0.0f)
+ UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
+ diagnostics, &resultArray[i]);
+ else
+ foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]);
+ break;
- case EOpExp2:
- if (!foldFloatTypeUnary(operandArray[i], &exp2f, infoSink, &resultArray[i]))
- return nullptr;
- break;
+ case EOpExp2:
+ foldFloatTypeUnary(operandArray[i], &exp2f, &resultArray[i]);
+ break;
- case EOpLog2:
- // For log2(x), results are undefined if x <= 0, we are choosing to set result to 0.
- // And log2f is not available on some plarforms like old android, so just using log(x)/log(2) here.
- if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() <= 0.0f)
- UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
- else if (!foldFloatTypeUnary(operandArray[i], &logf, infoSink, &resultArray[i]))
- return nullptr;
- else
- resultArray[i].setFConst(resultArray[i].getFConst() / logf(2.0f));
- break;
+ case EOpLog2:
+ // For log2(x), results are undefined if x <= 0, we are choosing to set result to 0.
+ // And log2f is not available on some plarforms like old android, so just using
+ // log(x)/log(2) here.
+ if (operandArray[i].getFConst() <= 0.0f)
+ UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
+ diagnostics, &resultArray[i]);
+ else
+ {
+ foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]);
+ resultArray[i].setFConst(resultArray[i].getFConst() / logf(2.0f));
+ }
+ break;
- case EOpSqrt:
- // For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0.
- if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() < 0.0f)
- UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
- else if (!foldFloatTypeUnary(operandArray[i], &sqrtf, infoSink, &resultArray[i]))
- return nullptr;
- break;
+ case EOpSqrt:
+ // For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0.
+ if (operandArray[i].getFConst() < 0.0f)
+ UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
+ diagnostics, &resultArray[i]);
+ else
+ foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]);
+ break;
- case EOpInverseSqrt:
- // There is no stdlib built-in function equavalent for GLES built-in inversesqrt(),
- // so getting the square root first using builtin function sqrt() and then taking its inverse.
- // Also, for inversesqrt(x), results are undefined if x <= 0, we are choosing to set result to 0.
- if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() <= 0.0f)
- UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
- else if (!foldFloatTypeUnary(operandArray[i], &sqrtf, infoSink, &resultArray[i]))
- return nullptr;
- else
- resultArray[i].setFConst(1.0f / resultArray[i].getFConst());
- break;
+ case EOpInverseSqrt:
+ // There is no stdlib built-in function equavalent for GLES built-in inversesqrt(),
+ // so getting the square root first using builtin function sqrt() and then taking
+ // its inverse.
+ // Also, for inversesqrt(x), results are undefined if x <= 0, we are choosing to set
+ // result to 0.
+ if (operandArray[i].getFConst() <= 0.0f)
+ UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
+ diagnostics, &resultArray[i]);
+ else
+ {
+ foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]);
+ resultArray[i].setFConst(1.0f / resultArray[i].getFConst());
+ }
+ break;
- case EOpVectorLogicalNot:
- if (getType().getBasicType() == EbtBool)
- {
+ case EOpLogicalNotComponentWise:
+ ASSERT(getType().getBasicType() == EbtBool);
resultArray[i].setBConst(!operandArray[i].getBConst());
break;
- }
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Unary operation not folded into constant");
- return nullptr;
- case EOpNormalize:
- if (getType().getBasicType() == EbtFloat)
+ case EOpNormalize:
{
- float x = operandArray[i].getFConst();
+ ASSERT(getType().getBasicType() == EbtFloat);
+ float x = operandArray[i].getFConst();
float length = VectorLength(operandArray, objectSize);
if (length)
resultArray[i].setFConst(x / length);
else
- UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink,
- &resultArray[i]);
+ UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
+ diagnostics, &resultArray[i]);
break;
}
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
-
- case EOpDFdx:
- case EOpDFdy:
- case EOpFwidth:
- if (getType().getBasicType() == EbtFloat)
+ case EOpBitfieldReverse:
+ {
+ uint32_t value;
+ if (getType().getBasicType() == EbtInt)
+ {
+ value = static_cast<uint32_t>(operandArray[i].getIConst());
+ }
+ else
+ {
+ ASSERT(getType().getBasicType() == EbtUInt);
+ value = operandArray[i].getUConst();
+ }
+ uint32_t result = gl::BitfieldReverse(value);
+ if (getType().getBasicType() == EbtInt)
+ {
+ resultArray[i].setIConst(static_cast<int32_t>(result));
+ }
+ else
+ {
+ resultArray[i].setUConst(result);
+ }
+ break;
+ }
+ case EOpBitCount:
+ {
+ uint32_t value;
+ if (getType().getBasicType() == EbtInt)
+ {
+ value = static_cast<uint32_t>(operandArray[i].getIConst());
+ }
+ else
+ {
+ ASSERT(getType().getBasicType() == EbtUInt);
+ value = operandArray[i].getUConst();
+ }
+ int result = gl::BitCount(value);
+ resultArray[i].setIConst(result);
+ break;
+ }
+ case EOpFindLSB:
+ {
+ uint32_t value;
+ if (getType().getBasicType() == EbtInt)
+ {
+ value = static_cast<uint32_t>(operandArray[i].getIConst());
+ }
+ else
+ {
+ ASSERT(getType().getBasicType() == EbtUInt);
+ value = operandArray[i].getUConst();
+ }
+ resultArray[i].setIConst(gl::FindLSB(value));
+ break;
+ }
+ case EOpFindMSB:
{
+ uint32_t value;
+ if (getType().getBasicType() == EbtInt)
+ {
+ int intValue = operandArray[i].getIConst();
+ value = static_cast<uint32_t>(intValue);
+ if (intValue < 0)
+ {
+ // Look for zero instead of one in value. This also handles the intValue ==
+ // -1 special case, where the return value needs to be -1.
+ value = ~value;
+ }
+ }
+ else
+ {
+ ASSERT(getType().getBasicType() == EbtUInt);
+ value = operandArray[i].getUConst();
+ }
+ resultArray[i].setIConst(gl::FindMSB(value));
+ break;
+ }
+ case EOpDFdx:
+ case EOpDFdy:
+ case EOpFwidth:
+ ASSERT(getType().getBasicType() == EbtFloat);
// Derivatives of constant arguments should be 0.
resultArray[i].setFConst(0.0f);
break;
- }
- infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
- return nullptr;
- default:
- return nullptr;
+ default:
+ return nullptr;
}
}
return resultArray;
}
-bool TIntermConstantUnion::foldFloatTypeUnary(const TConstantUnion &parameter, FloatTypeUnaryFunc builtinFunc,
- TInfoSink &infoSink, TConstantUnion *result) const
+void TIntermConstantUnion::foldFloatTypeUnary(const TConstantUnion &parameter,
+ FloatTypeUnaryFunc builtinFunc,
+ TConstantUnion *result) const
{
ASSERT(builtinFunc);
- if (getType().getBasicType() == EbtFloat)
- {
- result->setFConst(builtinFunc(parameter.getFConst()));
- return true;
- }
-
- infoSink.info.message(
- EPrefixInternalError, getLine(),
- "Unary operation not folded into constant");
- return false;
+ ASSERT(getType().getBasicType() == EbtFloat);
+ result->setFConst(builtinFunc(parameter.getFConst()));
}
// static
-TConstantUnion *TIntermConstantUnion::FoldAggregateConstructor(TIntermAggregate *aggregate,
- TInfoSink &infoSink)
+TConstantUnion *TIntermConstantUnion::FoldAggregateConstructor(TIntermAggregate *aggregate)
{
ASSERT(aggregate->getSequence()->size() > 0u);
size_t resultSize = aggregate->getType().getObjectSize();
@@ -1958,7 +2560,7 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateConstructor(TIntermAggregate
int argumentCols = argumentConstant->getType().getCols();
int argumentRows = argumentConstant->getType().getRows();
int resultCols = aggregate->getType().getCols();
- int resultRows = aggregate->getType().getRows();
+ int resultRows = aggregate->getType().getRows();
for (int col = 0; col < resultCols; ++col)
{
for (int row = 0; row < resultRows; ++row)
@@ -2001,664 +2603,728 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateConstructor(TIntermAggregate
return resultArray;
}
+bool TIntermAggregate::CanFoldAggregateBuiltInOp(TOperator op)
+{
+ switch (op)
+ {
+ case EOpAtan:
+ case EOpPow:
+ case EOpMod:
+ case EOpMin:
+ case EOpMax:
+ case EOpClamp:
+ case EOpMix:
+ case EOpStep:
+ case EOpSmoothStep:
+ case EOpLdexp:
+ case EOpMulMatrixComponentWise:
+ case EOpOuterProduct:
+ case EOpEqualComponentWise:
+ case EOpNotEqualComponentWise:
+ case EOpLessThanComponentWise:
+ case EOpLessThanEqualComponentWise:
+ case EOpGreaterThanComponentWise:
+ case EOpGreaterThanEqualComponentWise:
+ case EOpDistance:
+ case EOpDot:
+ case EOpCross:
+ case EOpFaceforward:
+ case EOpReflect:
+ case EOpRefract:
+ case EOpBitfieldExtract:
+ case EOpBitfieldInsert:
+ return true;
+ default:
+ return false;
+ }
+}
+
// static
-TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *aggregate, TInfoSink &infoSink)
+TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *aggregate,
+ TDiagnostics *diagnostics)
{
- TOperator op = aggregate->getOp();
- TIntermSequence *sequence = aggregate->getSequence();
- unsigned int paramsCount = static_cast<unsigned int>(sequence->size());
- std::vector<const TConstantUnion *> unionArrays(paramsCount);
- std::vector<size_t> objectSizes(paramsCount);
+ TOperator op = aggregate->getOp();
+ TIntermSequence *arguments = aggregate->getSequence();
+ unsigned int argsCount = static_cast<unsigned int>(arguments->size());
+ std::vector<const TConstantUnion *> unionArrays(argsCount);
+ std::vector<size_t> objectSizes(argsCount);
size_t maxObjectSize = 0;
TBasicType basicType = EbtVoid;
TSourceLoc loc;
- for (unsigned int i = 0; i < paramsCount; i++)
+ for (unsigned int i = 0; i < argsCount; i++)
{
- TIntermConstantUnion *paramConstant = (*sequence)[i]->getAsConstantUnion();
- ASSERT(paramConstant != nullptr); // Should be checked already.
+ TIntermConstantUnion *argConstant = (*arguments)[i]->getAsConstantUnion();
+ ASSERT(argConstant != nullptr); // Should be checked already.
if (i == 0)
{
- basicType = paramConstant->getType().getBasicType();
- loc = paramConstant->getLine();
+ basicType = argConstant->getType().getBasicType();
+ loc = argConstant->getLine();
}
- unionArrays[i] = paramConstant->getUnionArrayPointer();
- objectSizes[i] = paramConstant->getType().getObjectSize();
+ unionArrays[i] = argConstant->getUnionArrayPointer();
+ objectSizes[i] = argConstant->getType().getObjectSize();
if (objectSizes[i] > maxObjectSize)
maxObjectSize = objectSizes[i];
}
- if (!(*sequence)[0]->getAsTyped()->isMatrix())
+ if (!(*arguments)[0]->getAsTyped()->isMatrix() && aggregate->getOp() != EOpOuterProduct)
{
- for (unsigned int i = 0; i < paramsCount; i++)
+ for (unsigned int i = 0; i < argsCount; i++)
if (objectSizes[i] != maxObjectSize)
unionArrays[i] = Vectorize(*unionArrays[i], maxObjectSize);
}
TConstantUnion *resultArray = nullptr;
- if (paramsCount == 2)
+
+ switch (op)
{
- //
- // Binary built-in
- //
- switch (op)
+ case EOpAtan:
{
- case EOpAtan:
+ ASSERT(basicType == EbtFloat);
+ resultArray = new TConstantUnion[maxObjectSize];
+ for (size_t i = 0; i < maxObjectSize; i++)
{
- if (basicType == EbtFloat)
- {
- resultArray = new TConstantUnion[maxObjectSize];
- for (size_t i = 0; i < maxObjectSize; i++)
- {
- float y = unionArrays[0][i].getFConst();
- float x = unionArrays[1][i].getFConst();
- // Results are undefined if x and y are both 0.
- if (x == 0.0f && y == 0.0f)
- UndefinedConstantFoldingError(loc, op, basicType, infoSink, &resultArray[i]);
- else
- resultArray[i].setFConst(atan2f(y, x));
- }
- }
+ float y = unionArrays[0][i].getFConst();
+ float x = unionArrays[1][i].getFConst();
+ // Results are undefined if x and y are both 0.
+ if (x == 0.0f && y == 0.0f)
+ UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]);
else
- UNREACHABLE();
+ resultArray[i].setFConst(atan2f(y, x));
}
break;
+ }
- case EOpPow:
+ case EOpPow:
+ {
+ ASSERT(basicType == EbtFloat);
+ resultArray = new TConstantUnion[maxObjectSize];
+ for (size_t i = 0; i < maxObjectSize; i++)
{
- if (basicType == EbtFloat)
- {
- resultArray = new TConstantUnion[maxObjectSize];
- for (size_t i = 0; i < maxObjectSize; i++)
- {
- float x = unionArrays[0][i].getFConst();
- float y = unionArrays[1][i].getFConst();
- // Results are undefined if x < 0.
- // Results are undefined if x = 0 and y <= 0.
- if (x < 0.0f)
- UndefinedConstantFoldingError(loc, op, basicType, infoSink, &resultArray[i]);
- else if (x == 0.0f && y <= 0.0f)
- UndefinedConstantFoldingError(loc, op, basicType, infoSink, &resultArray[i]);
- else
- resultArray[i].setFConst(powf(x, y));
- }
- }
+ float x = unionArrays[0][i].getFConst();
+ float y = unionArrays[1][i].getFConst();
+ // Results are undefined if x < 0.
+ // Results are undefined if x = 0 and y <= 0.
+ if (x < 0.0f)
+ UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]);
+ else if (x == 0.0f && y <= 0.0f)
+ UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]);
else
- UNREACHABLE();
+ resultArray[i].setFConst(powf(x, y));
}
break;
+ }
- case EOpMod:
+ case EOpMod:
+ {
+ ASSERT(basicType == EbtFloat);
+ resultArray = new TConstantUnion[maxObjectSize];
+ for (size_t i = 0; i < maxObjectSize; i++)
{
- if (basicType == EbtFloat)
- {
- resultArray = new TConstantUnion[maxObjectSize];
- for (size_t i = 0; i < maxObjectSize; i++)
- {
- float x = unionArrays[0][i].getFConst();
- float y = unionArrays[1][i].getFConst();
- resultArray[i].setFConst(x - y * floorf(x / y));
- }
- }
- else
- UNREACHABLE();
+ float x = unionArrays[0][i].getFConst();
+ float y = unionArrays[1][i].getFConst();
+ resultArray[i].setFConst(x - y * floorf(x / y));
}
break;
+ }
- case EOpMin:
+ case EOpMin:
+ {
+ resultArray = new TConstantUnion[maxObjectSize];
+ for (size_t i = 0; i < maxObjectSize; i++)
{
- resultArray = new TConstantUnion[maxObjectSize];
- for (size_t i = 0; i < maxObjectSize; i++)
+ switch (basicType)
{
- switch (basicType)
- {
- case EbtFloat:
- resultArray[i].setFConst(std::min(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst()));
+ case EbtFloat:
+ resultArray[i].setFConst(
+ std::min(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst()));
break;
- case EbtInt:
- resultArray[i].setIConst(std::min(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst()));
+ case EbtInt:
+ resultArray[i].setIConst(
+ std::min(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst()));
break;
- case EbtUInt:
- resultArray[i].setUConst(std::min(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst()));
+ case EbtUInt:
+ resultArray[i].setUConst(
+ std::min(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst()));
break;
- default:
+ default:
UNREACHABLE();
break;
- }
}
}
break;
+ }
- case EOpMax:
+ case EOpMax:
+ {
+ resultArray = new TConstantUnion[maxObjectSize];
+ for (size_t i = 0; i < maxObjectSize; i++)
{
- resultArray = new TConstantUnion[maxObjectSize];
- for (size_t i = 0; i < maxObjectSize; i++)
+ switch (basicType)
{
- switch (basicType)
- {
- case EbtFloat:
- resultArray[i].setFConst(std::max(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst()));
+ case EbtFloat:
+ resultArray[i].setFConst(
+ std::max(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst()));
break;
- case EbtInt:
- resultArray[i].setIConst(std::max(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst()));
+ case EbtInt:
+ resultArray[i].setIConst(
+ std::max(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst()));
break;
- case EbtUInt:
- resultArray[i].setUConst(std::max(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst()));
+ case EbtUInt:
+ resultArray[i].setUConst(
+ std::max(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst()));
break;
- default:
+ default:
UNREACHABLE();
break;
- }
}
}
break;
+ }
- case EOpStep:
- {
- if (basicType == EbtFloat)
- {
- resultArray = new TConstantUnion[maxObjectSize];
- for (size_t i = 0; i < maxObjectSize; i++)
- resultArray[i].setFConst(unionArrays[1][i].getFConst() < unionArrays[0][i].getFConst() ? 0.0f : 1.0f);
- }
- else
- UNREACHABLE();
- }
+ case EOpStep:
+ {
+ ASSERT(basicType == EbtFloat);
+ resultArray = new TConstantUnion[maxObjectSize];
+ for (size_t i = 0; i < maxObjectSize; i++)
+ resultArray[i].setFConst(
+ unionArrays[1][i].getFConst() < unionArrays[0][i].getFConst() ? 0.0f : 1.0f);
break;
+ }
- case EOpLessThan:
+ case EOpLessThanComponentWise:
+ {
+ resultArray = new TConstantUnion[maxObjectSize];
+ for (size_t i = 0; i < maxObjectSize; i++)
{
- resultArray = new TConstantUnion[maxObjectSize];
- for (size_t i = 0; i < maxObjectSize; i++)
+ switch (basicType)
{
- switch (basicType)
- {
- case EbtFloat:
- resultArray[i].setBConst(unionArrays[0][i].getFConst() < unionArrays[1][i].getFConst());
+ case EbtFloat:
+ resultArray[i].setBConst(unionArrays[0][i].getFConst() <
+ unionArrays[1][i].getFConst());
break;
- case EbtInt:
- resultArray[i].setBConst(unionArrays[0][i].getIConst() < unionArrays[1][i].getIConst());
+ case EbtInt:
+ resultArray[i].setBConst(unionArrays[0][i].getIConst() <
+ unionArrays[1][i].getIConst());
break;
- case EbtUInt:
- resultArray[i].setBConst(unionArrays[0][i].getUConst() < unionArrays[1][i].getUConst());
+ case EbtUInt:
+ resultArray[i].setBConst(unionArrays[0][i].getUConst() <
+ unionArrays[1][i].getUConst());
break;
- default:
+ default:
UNREACHABLE();
break;
- }
}
}
break;
+ }
- case EOpLessThanEqual:
+ case EOpLessThanEqualComponentWise:
+ {
+ resultArray = new TConstantUnion[maxObjectSize];
+ for (size_t i = 0; i < maxObjectSize; i++)
{
- resultArray = new TConstantUnion[maxObjectSize];
- for (size_t i = 0; i < maxObjectSize; i++)
+ switch (basicType)
{
- switch (basicType)
- {
- case EbtFloat:
- resultArray[i].setBConst(unionArrays[0][i].getFConst() <= unionArrays[1][i].getFConst());
+ case EbtFloat:
+ resultArray[i].setBConst(unionArrays[0][i].getFConst() <=
+ unionArrays[1][i].getFConst());
break;
- case EbtInt:
- resultArray[i].setBConst(unionArrays[0][i].getIConst() <= unionArrays[1][i].getIConst());
+ case EbtInt:
+ resultArray[i].setBConst(unionArrays[0][i].getIConst() <=
+ unionArrays[1][i].getIConst());
break;
- case EbtUInt:
- resultArray[i].setBConst(unionArrays[0][i].getUConst() <= unionArrays[1][i].getUConst());
+ case EbtUInt:
+ resultArray[i].setBConst(unionArrays[0][i].getUConst() <=
+ unionArrays[1][i].getUConst());
break;
- default:
+ default:
UNREACHABLE();
break;
- }
}
}
break;
+ }
- case EOpGreaterThan:
+ case EOpGreaterThanComponentWise:
+ {
+ resultArray = new TConstantUnion[maxObjectSize];
+ for (size_t i = 0; i < maxObjectSize; i++)
{
- resultArray = new TConstantUnion[maxObjectSize];
- for (size_t i = 0; i < maxObjectSize; i++)
+ switch (basicType)
{
- switch (basicType)
- {
- case EbtFloat:
- resultArray[i].setBConst(unionArrays[0][i].getFConst() > unionArrays[1][i].getFConst());
+ case EbtFloat:
+ resultArray[i].setBConst(unionArrays[0][i].getFConst() >
+ unionArrays[1][i].getFConst());
break;
- case EbtInt:
- resultArray[i].setBConst(unionArrays[0][i].getIConst() > unionArrays[1][i].getIConst());
+ case EbtInt:
+ resultArray[i].setBConst(unionArrays[0][i].getIConst() >
+ unionArrays[1][i].getIConst());
break;
- case EbtUInt:
- resultArray[i].setBConst(unionArrays[0][i].getUConst() > unionArrays[1][i].getUConst());
+ case EbtUInt:
+ resultArray[i].setBConst(unionArrays[0][i].getUConst() >
+ unionArrays[1][i].getUConst());
break;
- default:
+ default:
UNREACHABLE();
break;
- }
}
}
break;
-
- case EOpGreaterThanEqual:
+ }
+ case EOpGreaterThanEqualComponentWise:
+ {
+ resultArray = new TConstantUnion[maxObjectSize];
+ for (size_t i = 0; i < maxObjectSize; i++)
{
- resultArray = new TConstantUnion[maxObjectSize];
- for (size_t i = 0; i < maxObjectSize; i++)
+ switch (basicType)
{
- switch (basicType)
- {
- case EbtFloat:
- resultArray[i].setBConst(unionArrays[0][i].getFConst() >= unionArrays[1][i].getFConst());
+ case EbtFloat:
+ resultArray[i].setBConst(unionArrays[0][i].getFConst() >=
+ unionArrays[1][i].getFConst());
break;
- case EbtInt:
- resultArray[i].setBConst(unionArrays[0][i].getIConst() >= unionArrays[1][i].getIConst());
+ case EbtInt:
+ resultArray[i].setBConst(unionArrays[0][i].getIConst() >=
+ unionArrays[1][i].getIConst());
break;
- case EbtUInt:
- resultArray[i].setBConst(unionArrays[0][i].getUConst() >= unionArrays[1][i].getUConst());
+ case EbtUInt:
+ resultArray[i].setBConst(unionArrays[0][i].getUConst() >=
+ unionArrays[1][i].getUConst());
break;
- default:
+ default:
UNREACHABLE();
break;
- }
}
}
- break;
+ }
+ break;
- case EOpVectorEqual:
+ case EOpEqualComponentWise:
+ {
+ resultArray = new TConstantUnion[maxObjectSize];
+ for (size_t i = 0; i < maxObjectSize; i++)
{
- resultArray = new TConstantUnion[maxObjectSize];
- for (size_t i = 0; i < maxObjectSize; i++)
+ switch (basicType)
{
- switch (basicType)
- {
- case EbtFloat:
- resultArray[i].setBConst(unionArrays[0][i].getFConst() == unionArrays[1][i].getFConst());
+ case EbtFloat:
+ resultArray[i].setBConst(unionArrays[0][i].getFConst() ==
+ unionArrays[1][i].getFConst());
break;
- case EbtInt:
- resultArray[i].setBConst(unionArrays[0][i].getIConst() == unionArrays[1][i].getIConst());
+ case EbtInt:
+ resultArray[i].setBConst(unionArrays[0][i].getIConst() ==
+ unionArrays[1][i].getIConst());
break;
- case EbtUInt:
- resultArray[i].setBConst(unionArrays[0][i].getUConst() == unionArrays[1][i].getUConst());
+ case EbtUInt:
+ resultArray[i].setBConst(unionArrays[0][i].getUConst() ==
+ unionArrays[1][i].getUConst());
break;
- case EbtBool:
- resultArray[i].setBConst(unionArrays[0][i].getBConst() == unionArrays[1][i].getBConst());
+ case EbtBool:
+ resultArray[i].setBConst(unionArrays[0][i].getBConst() ==
+ unionArrays[1][i].getBConst());
break;
- default:
+ default:
UNREACHABLE();
break;
- }
}
}
break;
+ }
- case EOpVectorNotEqual:
+ case EOpNotEqualComponentWise:
+ {
+ resultArray = new TConstantUnion[maxObjectSize];
+ for (size_t i = 0; i < maxObjectSize; i++)
{
- resultArray = new TConstantUnion[maxObjectSize];
- for (size_t i = 0; i < maxObjectSize; i++)
+ switch (basicType)
{
- switch (basicType)
- {
- case EbtFloat:
- resultArray[i].setBConst(unionArrays[0][i].getFConst() != unionArrays[1][i].getFConst());
+ case EbtFloat:
+ resultArray[i].setBConst(unionArrays[0][i].getFConst() !=
+ unionArrays[1][i].getFConst());
break;
- case EbtInt:
- resultArray[i].setBConst(unionArrays[0][i].getIConst() != unionArrays[1][i].getIConst());
+ case EbtInt:
+ resultArray[i].setBConst(unionArrays[0][i].getIConst() !=
+ unionArrays[1][i].getIConst());
break;
- case EbtUInt:
- resultArray[i].setBConst(unionArrays[0][i].getUConst() != unionArrays[1][i].getUConst());
+ case EbtUInt:
+ resultArray[i].setBConst(unionArrays[0][i].getUConst() !=
+ unionArrays[1][i].getUConst());
break;
- case EbtBool:
- resultArray[i].setBConst(unionArrays[0][i].getBConst() != unionArrays[1][i].getBConst());
+ case EbtBool:
+ resultArray[i].setBConst(unionArrays[0][i].getBConst() !=
+ unionArrays[1][i].getBConst());
break;
- default:
+ default:
UNREACHABLE();
break;
- }
}
}
break;
+ }
- case EOpDistance:
- if (basicType == EbtFloat)
+ case EOpDistance:
+ {
+ ASSERT(basicType == EbtFloat);
+ TConstantUnion *distanceArray = new TConstantUnion[maxObjectSize];
+ resultArray = new TConstantUnion();
+ for (size_t i = 0; i < maxObjectSize; i++)
{
- TConstantUnion *distanceArray = new TConstantUnion[maxObjectSize];
- resultArray = new TConstantUnion();
- for (size_t i = 0; i < maxObjectSize; i++)
- {
- float x = unionArrays[0][i].getFConst();
- float y = unionArrays[1][i].getFConst();
- distanceArray[i].setFConst(x - y);
- }
- resultArray->setFConst(VectorLength(distanceArray, maxObjectSize));
+ float x = unionArrays[0][i].getFConst();
+ float y = unionArrays[1][i].getFConst();
+ distanceArray[i].setFConst(x - y);
}
- else
- UNREACHABLE();
+ resultArray->setFConst(VectorLength(distanceArray, maxObjectSize));
break;
+ }
- case EOpDot:
-
- if (basicType == EbtFloat)
- {
- resultArray = new TConstantUnion();
- resultArray->setFConst(VectorDotProduct(unionArrays[0], unionArrays[1], maxObjectSize));
- }
- else
- UNREACHABLE();
+ case EOpDot:
+ ASSERT(basicType == EbtFloat);
+ resultArray = new TConstantUnion();
+ resultArray->setFConst(VectorDotProduct(unionArrays[0], unionArrays[1], maxObjectSize));
break;
- case EOpCross:
- if (basicType == EbtFloat && maxObjectSize == 3)
- {
- resultArray = new TConstantUnion[maxObjectSize];
- float x0 = unionArrays[0][0].getFConst();
- float x1 = unionArrays[0][1].getFConst();
- float x2 = unionArrays[0][2].getFConst();
- float y0 = unionArrays[1][0].getFConst();
- float y1 = unionArrays[1][1].getFConst();
- float y2 = unionArrays[1][2].getFConst();
- resultArray[0].setFConst(x1 * y2 - y1 * x2);
- resultArray[1].setFConst(x2 * y0 - y2 * x0);
- resultArray[2].setFConst(x0 * y1 - y0 * x1);
- }
- else
- UNREACHABLE();
+ case EOpCross:
+ {
+ ASSERT(basicType == EbtFloat && maxObjectSize == 3);
+ resultArray = new TConstantUnion[maxObjectSize];
+ float x0 = unionArrays[0][0].getFConst();
+ float x1 = unionArrays[0][1].getFConst();
+ float x2 = unionArrays[0][2].getFConst();
+ float y0 = unionArrays[1][0].getFConst();
+ float y1 = unionArrays[1][1].getFConst();
+ float y2 = unionArrays[1][2].getFConst();
+ resultArray[0].setFConst(x1 * y2 - y1 * x2);
+ resultArray[1].setFConst(x2 * y0 - y2 * x0);
+ resultArray[2].setFConst(x0 * y1 - y0 * x1);
break;
+ }
- case EOpReflect:
- if (basicType == EbtFloat)
+ case EOpReflect:
+ {
+ ASSERT(basicType == EbtFloat);
+ // genType reflect (genType I, genType N) :
+ // For the incident vector I and surface orientation N, returns the reflection
+ // direction:
+ // I - 2 * dot(N, I) * N.
+ resultArray = new TConstantUnion[maxObjectSize];
+ float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
+ for (size_t i = 0; i < maxObjectSize; i++)
{
- // genType reflect (genType I, genType N) :
- // For the incident vector I and surface orientation N, returns the reflection direction:
- // I - 2 * dot(N, I) * N.
- resultArray = new TConstantUnion[maxObjectSize];
- float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
- for (size_t i = 0; i < maxObjectSize; i++)
- {
- float result = unionArrays[0][i].getFConst() -
- 2.0f * dotProduct * unionArrays[1][i].getFConst();
- resultArray[i].setFConst(result);
- }
+ float result = unionArrays[0][i].getFConst() -
+ 2.0f * dotProduct * unionArrays[1][i].getFConst();
+ resultArray[i].setFConst(result);
}
- else
- UNREACHABLE();
break;
+ }
- case EOpMul:
- if (basicType == EbtFloat && (*sequence)[0]->getAsTyped()->isMatrix() &&
- (*sequence)[1]->getAsTyped()->isMatrix())
- {
- // Perform component-wise matrix multiplication.
- resultArray = new TConstantUnion[maxObjectSize];
- int size = (*sequence)[0]->getAsTyped()->getNominalSize();
- angle::Matrix<float> result =
- GetMatrix(unionArrays[0], size).compMult(GetMatrix(unionArrays[1], size));
- SetUnionArrayFromMatrix(result, resultArray);
- }
- else
- UNREACHABLE();
+ case EOpMulMatrixComponentWise:
+ {
+ ASSERT(basicType == EbtFloat && (*arguments)[0]->getAsTyped()->isMatrix() &&
+ (*arguments)[1]->getAsTyped()->isMatrix());
+ // Perform component-wise matrix multiplication.
+ resultArray = new TConstantUnion[maxObjectSize];
+ int size = (*arguments)[0]->getAsTyped()->getNominalSize();
+ angle::Matrix<float> result =
+ GetMatrix(unionArrays[0], size).compMult(GetMatrix(unionArrays[1], size));
+ SetUnionArrayFromMatrix(result, resultArray);
break;
+ }
- case EOpOuterProduct:
- if (basicType == EbtFloat)
- {
- size_t numRows = (*sequence)[0]->getAsTyped()->getType().getObjectSize();
- size_t numCols = (*sequence)[1]->getAsTyped()->getType().getObjectSize();
- resultArray = new TConstantUnion[numRows * numCols];
- angle::Matrix<float> result =
- GetMatrix(unionArrays[0], 1, static_cast<int>(numCols))
- .outerProduct(GetMatrix(unionArrays[1], static_cast<int>(numRows), 1));
- SetUnionArrayFromMatrix(result, resultArray);
- }
- else
- UNREACHABLE();
+ case EOpOuterProduct:
+ {
+ ASSERT(basicType == EbtFloat);
+ size_t numRows = (*arguments)[0]->getAsTyped()->getType().getObjectSize();
+ size_t numCols = (*arguments)[1]->getAsTyped()->getType().getObjectSize();
+ resultArray = new TConstantUnion[numRows * numCols];
+ angle::Matrix<float> result =
+ GetMatrix(unionArrays[0], static_cast<int>(numRows), 1)
+ .outerProduct(GetMatrix(unionArrays[1], 1, static_cast<int>(numCols)));
+ SetUnionArrayFromMatrix(result, resultArray);
break;
-
- default:
- UNREACHABLE();
- // TODO: Add constant folding support for other built-in operations that take 2 parameters and not handled above.
- return nullptr;
}
- }
- else if (paramsCount == 3)
- {
- //
- // Ternary built-in
- //
- switch (op)
+
+ case EOpClamp:
{
- case EOpClamp:
+ resultArray = new TConstantUnion[maxObjectSize];
+ for (size_t i = 0; i < maxObjectSize; i++)
{
- resultArray = new TConstantUnion[maxObjectSize];
- for (size_t i = 0; i < maxObjectSize; i++)
+ switch (basicType)
{
- switch (basicType)
+ case EbtFloat:
{
- case EbtFloat:
- {
- float x = unionArrays[0][i].getFConst();
- float min = unionArrays[1][i].getFConst();
- float max = unionArrays[2][i].getFConst();
- // Results are undefined if min > max.
- if (min > max)
- UndefinedConstantFoldingError(loc, op, basicType, infoSink, &resultArray[i]);
- else
- resultArray[i].setFConst(gl::clamp(x, min, max));
- }
+ float x = unionArrays[0][i].getFConst();
+ float min = unionArrays[1][i].getFConst();
+ float max = unionArrays[2][i].getFConst();
+ // Results are undefined if min > max.
+ if (min > max)
+ UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
+ &resultArray[i]);
+ else
+ resultArray[i].setFConst(gl::clamp(x, min, max));
break;
- case EbtInt:
- {
- int x = unionArrays[0][i].getIConst();
- int min = unionArrays[1][i].getIConst();
- int max = unionArrays[2][i].getIConst();
- // Results are undefined if min > max.
- if (min > max)
- UndefinedConstantFoldingError(loc, op, basicType, infoSink, &resultArray[i]);
- else
- resultArray[i].setIConst(gl::clamp(x, min, max));
- }
+ }
+
+ case EbtInt:
+ {
+ int x = unionArrays[0][i].getIConst();
+ int min = unionArrays[1][i].getIConst();
+ int max = unionArrays[2][i].getIConst();
+ // Results are undefined if min > max.
+ if (min > max)
+ UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
+ &resultArray[i]);
+ else
+ resultArray[i].setIConst(gl::clamp(x, min, max));
break;
- case EbtUInt:
- {
- unsigned int x = unionArrays[0][i].getUConst();
- unsigned int min = unionArrays[1][i].getUConst();
- unsigned int max = unionArrays[2][i].getUConst();
- // Results are undefined if min > max.
- if (min > max)
- UndefinedConstantFoldingError(loc, op, basicType, infoSink, &resultArray[i]);
- else
- resultArray[i].setUConst(gl::clamp(x, min, max));
- }
+ }
+ case EbtUInt:
+ {
+ unsigned int x = unionArrays[0][i].getUConst();
+ unsigned int min = unionArrays[1][i].getUConst();
+ unsigned int max = unionArrays[2][i].getUConst();
+ // Results are undefined if min > max.
+ if (min > max)
+ UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
+ &resultArray[i]);
+ else
+ resultArray[i].setUConst(gl::clamp(x, min, max));
break;
- default:
+ }
+ default:
UNREACHABLE();
break;
- }
}
}
break;
+ }
- case EOpMix:
+ case EOpMix:
+ {
+ ASSERT(basicType == EbtFloat);
+ resultArray = new TConstantUnion[maxObjectSize];
+ for (size_t i = 0; i < maxObjectSize; i++)
{
- if (basicType == EbtFloat)
+ float x = unionArrays[0][i].getFConst();
+ float y = unionArrays[1][i].getFConst();
+ TBasicType type = (*arguments)[2]->getAsTyped()->getType().getBasicType();
+ if (type == EbtFloat)
{
- resultArray = new TConstantUnion[maxObjectSize];
- for (size_t i = 0; i < maxObjectSize; i++)
- {
- float x = unionArrays[0][i].getFConst();
- float y = unionArrays[1][i].getFConst();
- TBasicType type = (*sequence)[2]->getAsTyped()->getType().getBasicType();
- if (type == EbtFloat)
- {
- // Returns the linear blend of x and y, i.e., x * (1 - a) + y * a.
- float a = unionArrays[2][i].getFConst();
- resultArray[i].setFConst(x * (1.0f - a) + y * a);
- }
- else // 3rd parameter is EbtBool
- {
- ASSERT(type == EbtBool);
- // Selects which vector each returned component comes from.
- // For a component of a that is false, the corresponding component of x is returned.
- // For a component of a that is true, the corresponding component of y is returned.
- bool a = unionArrays[2][i].getBConst();
- resultArray[i].setFConst(a ? y : x);
- }
- }
+ // Returns the linear blend of x and y, i.e., x * (1 - a) + y * a.
+ float a = unionArrays[2][i].getFConst();
+ resultArray[i].setFConst(x * (1.0f - a) + y * a);
+ }
+ else // 3rd parameter is EbtBool
+ {
+ ASSERT(type == EbtBool);
+ // Selects which vector each returned component comes from.
+ // For a component of a that is false, the corresponding component of x is
+ // returned.
+ // For a component of a that is true, the corresponding component of y is
+ // returned.
+ bool a = unionArrays[2][i].getBConst();
+ resultArray[i].setFConst(a ? y : x);
}
- else
- UNREACHABLE();
}
break;
+ }
- case EOpSmoothStep:
+ case EOpSmoothStep:
+ {
+ ASSERT(basicType == EbtFloat);
+ resultArray = new TConstantUnion[maxObjectSize];
+ for (size_t i = 0; i < maxObjectSize; i++)
{
- if (basicType == EbtFloat)
+ float edge0 = unionArrays[0][i].getFConst();
+ float edge1 = unionArrays[1][i].getFConst();
+ float x = unionArrays[2][i].getFConst();
+ // Results are undefined if edge0 >= edge1.
+ if (edge0 >= edge1)
{
- resultArray = new TConstantUnion[maxObjectSize];
- for (size_t i = 0; i < maxObjectSize; i++)
- {
- float edge0 = unionArrays[0][i].getFConst();
- float edge1 = unionArrays[1][i].getFConst();
- float x = unionArrays[2][i].getFConst();
- // Results are undefined if edge0 >= edge1.
- if (edge0 >= edge1)
- {
- UndefinedConstantFoldingError(loc, op, basicType, infoSink, &resultArray[i]);
- }
- else
- {
- // Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth
- // Hermite interpolation between 0 and 1 when edge0 < x < edge1.
- float t = gl::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
- resultArray[i].setFConst(t * t * (3.0f - 2.0f * t));
- }
- }
+ UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]);
}
else
- UNREACHABLE();
+ {
+ // Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth
+ // Hermite interpolation between 0 and 1 when edge0 < x < edge1.
+ float t = gl::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
+ resultArray[i].setFConst(t * t * (3.0f - 2.0f * t));
+ }
}
break;
+ }
- case EOpFaceForward:
- if (basicType == EbtFloat)
+ case EOpLdexp:
+ {
+ resultArray = new TConstantUnion[maxObjectSize];
+ for (size_t i = 0; i < maxObjectSize; i++)
{
- // genType faceforward(genType N, genType I, genType Nref) :
- // If dot(Nref, I) < 0 return N, otherwise return -N.
- resultArray = new TConstantUnion[maxObjectSize];
- float dotProduct = VectorDotProduct(unionArrays[2], unionArrays[1], maxObjectSize);
- for (size_t i = 0; i < maxObjectSize; i++)
+ float x = unionArrays[0][i].getFConst();
+ int exp = unionArrays[1][i].getIConst();
+ if (exp > 128)
{
- if (dotProduct < 0)
- resultArray[i].setFConst(unionArrays[0][i].getFConst());
- else
- resultArray[i].setFConst(-unionArrays[0][i].getFConst());
+ UndefinedConstantFoldingError(loc, op, basicType, diagnostics, &resultArray[i]);
}
- }
- else
- UNREACHABLE();
- break;
-
- case EOpRefract:
- if (basicType == EbtFloat)
- {
- // genType refract(genType I, genType N, float eta) :
- // For the incident vector I and surface normal N, and the ratio of indices of refraction eta,
- // return the refraction vector. The result is computed by
- // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
- // if (k < 0.0)
- // return genType(0.0)
- // else
- // return eta * I - (eta * dot(N, I) + sqrt(k)) * N
- resultArray = new TConstantUnion[maxObjectSize];
- float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
- for (size_t i = 0; i < maxObjectSize; i++)
+ else
{
- float eta = unionArrays[2][i].getFConst();
- float k = 1.0f - eta * eta * (1.0f - dotProduct * dotProduct);
- if (k < 0.0f)
- resultArray[i].setFConst(0.0f);
- else
- resultArray[i].setFConst(eta * unionArrays[0][i].getFConst() -
- (eta * dotProduct + sqrtf(k)) * unionArrays[1][i].getFConst());
+ resultArray[i].setFConst(gl::Ldexp(x, exp));
}
}
- else
- UNREACHABLE();
break;
-
- default:
- UNREACHABLE();
- // TODO: Add constant folding support for other built-in operations that take 3 parameters and not handled above.
- return nullptr;
}
- }
- return resultArray;
-}
-// static
-TString TIntermTraverser::hash(const TString &name, ShHashFunction64 hashFunction)
-{
- if (hashFunction == NULL || name.empty())
- return name;
- khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length());
- TStringStream stream;
- stream << HASHED_NAME_PREFIX << std::hex << number;
- TString hashedName = stream.str();
- return hashedName;
-}
+ case EOpFaceforward:
+ {
+ ASSERT(basicType == EbtFloat);
+ // genType faceforward(genType N, genType I, genType Nref) :
+ // If dot(Nref, I) < 0 return N, otherwise return -N.
+ resultArray = new TConstantUnion[maxObjectSize];
+ float dotProduct = VectorDotProduct(unionArrays[2], unionArrays[1], maxObjectSize);
+ for (size_t i = 0; i < maxObjectSize; i++)
+ {
+ if (dotProduct < 0)
+ resultArray[i].setFConst(unionArrays[0][i].getFConst());
+ else
+ resultArray[i].setFConst(-unionArrays[0][i].getFConst());
+ }
+ break;
+ }
-void TIntermTraverser::updateTree()
-{
- for (size_t ii = 0; ii < mInsertions.size(); ++ii)
- {
- const NodeInsertMultipleEntry &insertion = mInsertions[ii];
- ASSERT(insertion.parent);
- if (!insertion.insertionsAfter.empty())
+ case EOpRefract:
{
- bool inserted = insertion.parent->insertChildNodes(insertion.position + 1,
- insertion.insertionsAfter);
- ASSERT(inserted);
- UNUSED_ASSERTION_VARIABLE(inserted);
+ ASSERT(basicType == EbtFloat);
+ // genType refract(genType I, genType N, float eta) :
+ // For the incident vector I and surface normal N, and the ratio of indices of
+ // refraction eta,
+ // return the refraction vector. The result is computed by
+ // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
+ // if (k < 0.0)
+ // return genType(0.0)
+ // else
+ // return eta * I - (eta * dot(N, I) + sqrt(k)) * N
+ resultArray = new TConstantUnion[maxObjectSize];
+ float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
+ for (size_t i = 0; i < maxObjectSize; i++)
+ {
+ float eta = unionArrays[2][i].getFConst();
+ float k = 1.0f - eta * eta * (1.0f - dotProduct * dotProduct);
+ if (k < 0.0f)
+ resultArray[i].setFConst(0.0f);
+ else
+ resultArray[i].setFConst(eta * unionArrays[0][i].getFConst() -
+ (eta * dotProduct + sqrtf(k)) *
+ unionArrays[1][i].getFConst());
+ }
+ break;
}
- if (!insertion.insertionsBefore.empty())
+ case EOpBitfieldExtract:
{
- bool inserted =
- insertion.parent->insertChildNodes(insertion.position, insertion.insertionsBefore);
- ASSERT(inserted);
- UNUSED_ASSERTION_VARIABLE(inserted);
+ resultArray = new TConstantUnion[maxObjectSize];
+ for (size_t i = 0; i < maxObjectSize; ++i)
+ {
+ int offset = unionArrays[1][0].getIConst();
+ int bits = unionArrays[2][0].getIConst();
+ if (bits == 0)
+ {
+ if (aggregate->getBasicType() == EbtInt)
+ {
+ resultArray[i].setIConst(0);
+ }
+ else
+ {
+ ASSERT(aggregate->getBasicType() == EbtUInt);
+ resultArray[i].setUConst(0);
+ }
+ }
+ else if (offset < 0 || bits < 0 || offset >= 32 || bits > 32 || offset + bits > 32)
+ {
+ UndefinedConstantFoldingError(loc, op, aggregate->getBasicType(), diagnostics,
+ &resultArray[i]);
+ }
+ else
+ {
+ // bits can be 32 here, so we need to avoid bit shift overflow.
+ uint32_t maskMsb = 1u << (bits - 1);
+ uint32_t mask = ((maskMsb - 1u) | maskMsb) << offset;
+ if (aggregate->getBasicType() == EbtInt)
+ {
+ uint32_t value = static_cast<uint32_t>(unionArrays[0][i].getIConst());
+ uint32_t resultUnsigned = (value & mask) >> offset;
+ if ((resultUnsigned & maskMsb) != 0)
+ {
+ // The most significant bits (from bits+1 to the most significant bit)
+ // should be set to 1.
+ uint32_t higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;
+ resultUnsigned |= higherBitsMask;
+ }
+ resultArray[i].setIConst(static_cast<int32_t>(resultUnsigned));
+ }
+ else
+ {
+ ASSERT(aggregate->getBasicType() == EbtUInt);
+ uint32_t value = unionArrays[0][i].getUConst();
+ resultArray[i].setUConst((value & mask) >> offset);
+ }
+ }
+ }
+ break;
}
- }
- for (size_t ii = 0; ii < mReplacements.size(); ++ii)
- {
- const NodeUpdateEntry &replacement = mReplacements[ii];
- ASSERT(replacement.parent);
- bool replaced = replacement.parent->replaceChildNode(
- replacement.original, replacement.replacement);
- ASSERT(replaced);
- UNUSED_ASSERTION_VARIABLE(replaced);
-
- if (!replacement.originalBecomesChildOfReplacement)
+ case EOpBitfieldInsert:
{
- // In AST traversing, a parent is visited before its children.
- // After we replace a node, if its immediate child is to
- // be replaced, we need to make sure we don't update the replaced
- // node; instead, we update the replacement node.
- for (size_t jj = ii + 1; jj < mReplacements.size(); ++jj)
+ resultArray = new TConstantUnion[maxObjectSize];
+ for (size_t i = 0; i < maxObjectSize; ++i)
{
- NodeUpdateEntry &replacement2 = mReplacements[jj];
- if (replacement2.parent == replacement.original)
- replacement2.parent = replacement.replacement;
+ int offset = unionArrays[2][0].getIConst();
+ int bits = unionArrays[3][0].getIConst();
+ if (bits == 0)
+ {
+ if (aggregate->getBasicType() == EbtInt)
+ {
+ int32_t base = unionArrays[0][i].getIConst();
+ resultArray[i].setIConst(base);
+ }
+ else
+ {
+ ASSERT(aggregate->getBasicType() == EbtUInt);
+ uint32_t base = unionArrays[0][i].getUConst();
+ resultArray[i].setUConst(base);
+ }
+ }
+ else if (offset < 0 || bits < 0 || offset >= 32 || bits > 32 || offset + bits > 32)
+ {
+ UndefinedConstantFoldingError(loc, op, aggregate->getBasicType(), diagnostics,
+ &resultArray[i]);
+ }
+ else
+ {
+ // bits can be 32 here, so we need to avoid bit shift overflow.
+ uint32_t maskMsb = 1u << (bits - 1);
+ uint32_t insertMask = ((maskMsb - 1u) | maskMsb) << offset;
+ uint32_t baseMask = ~insertMask;
+ if (aggregate->getBasicType() == EbtInt)
+ {
+ uint32_t base = static_cast<uint32_t>(unionArrays[0][i].getIConst());
+ uint32_t insert = static_cast<uint32_t>(unionArrays[1][i].getIConst());
+ uint32_t resultUnsigned =
+ (base & baseMask) | ((insert << offset) & insertMask);
+ resultArray[i].setIConst(static_cast<int32_t>(resultUnsigned));
+ }
+ else
+ {
+ ASSERT(aggregate->getBasicType() == EbtUInt);
+ uint32_t base = unionArrays[0][i].getUConst();
+ uint32_t insert = unionArrays[1][i].getUConst();
+ resultArray[i].setUConst((base & baseMask) |
+ ((insert << offset) & insertMask));
+ }
+ }
}
+ break;
}
- }
- for (size_t ii = 0; ii < mMultiReplacements.size(); ++ii)
- {
- const NodeReplaceWithMultipleEntry &replacement = mMultiReplacements[ii];
- ASSERT(replacement.parent);
- bool replaced = replacement.parent->replaceChildNodeWithMultiple(
- replacement.original, replacement.replacements);
- ASSERT(replaced);
- UNUSED_ASSERTION_VARIABLE(replaced);
- }
- mInsertions.clear();
- mReplacements.clear();
- mMultiReplacements.clear();
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+ return resultArray;
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.h b/src/3rdparty/angle/src/compiler/translator/IntermNode.h
index ad500e2b1f..2170916201 100644
--- a/src/3rdparty/angle/src/compiler/translator/IntermNode.h
+++ b/src/3rdparty/angle/src/compiler/translator/IntermNode.h
@@ -25,14 +25,27 @@
#include "compiler/translator/Common.h"
#include "compiler/translator/ConstantUnion.h"
#include "compiler/translator/Operator.h"
+#include "compiler/translator/SymbolUniqueId.h"
#include "compiler/translator/Types.h"
+namespace sh
+{
+
+class TDiagnostics;
+
class TIntermTraverser;
class TIntermAggregate;
+class TIntermBlock;
+class TIntermInvariantDeclaration;
+class TIntermDeclaration;
+class TIntermFunctionPrototype;
+class TIntermFunctionDefinition;
+class TIntermSwizzle;
class TIntermBinary;
class TIntermUnary;
class TIntermConstantUnion;
-class TIntermSelection;
+class TIntermTernary;
+class TIntermIfElse;
class TIntermSwitch;
class TIntermCase;
class TIntermTyped;
@@ -41,8 +54,10 @@ class TIntermLoop;
class TInfoSink;
class TInfoSinkBase;
class TIntermRaw;
+class TIntermBranch;
class TSymbolTable;
+class TFunction;
// Encapsulate an identifier string and track whether it is coming from the original shader code
// (not internal) or from ANGLE (internal). Usually internal names shouldn't be decorated or hashed.
@@ -79,7 +94,7 @@ class TIntermNode : angle::NonCopyable
mLine.first_file = mLine.last_file = 0;
mLine.first_line = mLine.last_line = 0;
}
- virtual ~TIntermNode() { }
+ virtual ~TIntermNode() {}
const TSourceLoc &getLine() const { return mLine; }
void setLine(const TSourceLoc &l) { mLine = l; }
@@ -87,20 +102,27 @@ class TIntermNode : angle::NonCopyable
virtual void traverse(TIntermTraverser *) = 0;
virtual TIntermTyped *getAsTyped() { return 0; }
virtual TIntermConstantUnion *getAsConstantUnion() { return 0; }
+ virtual TIntermFunctionDefinition *getAsFunctionDefinition() { return nullptr; }
virtual TIntermAggregate *getAsAggregate() { return 0; }
+ virtual TIntermBlock *getAsBlock() { return nullptr; }
+ virtual TIntermFunctionPrototype *getAsFunctionPrototypeNode() { return nullptr; }
+ virtual TIntermInvariantDeclaration *getAsInvariantDeclarationNode() { return nullptr; }
+ virtual TIntermDeclaration *getAsDeclarationNode() { return nullptr; }
+ virtual TIntermSwizzle *getAsSwizzleNode() { return nullptr; }
virtual TIntermBinary *getAsBinaryNode() { return 0; }
virtual TIntermUnary *getAsUnaryNode() { return 0; }
- virtual TIntermSelection *getAsSelectionNode() { return 0; }
+ virtual TIntermTernary *getAsTernaryNode() { return nullptr; }
+ virtual TIntermIfElse *getAsIfElseNode() { return nullptr; }
virtual TIntermSwitch *getAsSwitchNode() { return 0; }
virtual TIntermCase *getAsCaseNode() { return 0; }
virtual TIntermSymbol *getAsSymbolNode() { return 0; }
virtual TIntermLoop *getAsLoopNode() { return 0; }
virtual TIntermRaw *getAsRawNode() { return 0; }
+ virtual TIntermBranch *getAsBranchNode() { return 0; }
// Replace a child node. Return true if |original| is a child
// node and it is replaced; otherwise, return false.
- virtual bool replaceChildNode(
- TIntermNode *original, TIntermNode *replacement) = 0;
+ virtual bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) = 0;
protected:
TSourceLoc mLine;
@@ -121,12 +143,15 @@ struct TIntermNodePair
class TIntermTyped : public TIntermNode
{
public:
- TIntermTyped(const TType &t) : mType(t) { }
+ TIntermTyped(const TType &t) : mType(t) {}
virtual TIntermTyped *deepCopy() const = 0;
TIntermTyped *getAsTyped() override { return this; }
+ // True if executing the expression represented by this node affects state, like values of
+ // variables. False if the executing the expression only computes its return value without
+ // affecting state. May return true conservatively.
virtual bool hasSideEffects() const = 0;
void setType(const TType &t) { mType = t; }
@@ -137,6 +162,7 @@ class TIntermTyped : public TIntermNode
TBasicType getBasicType() const { return mType.getBasicType(); }
TQualifier getQualifier() const { return mType.getQualifier(); }
TPrecision getPrecision() const { return mType.getPrecision(); }
+ TMemoryQualifier getMemoryQualifier() const { return mType.getMemoryQualifier(); }
int getCols() const { return mType.getCols(); }
int getRows() const { return mType.getRows(); }
int getNominalSize() const { return mType.getNominalSize(); }
@@ -144,14 +170,16 @@ class TIntermTyped : public TIntermNode
bool isInterfaceBlock() const { return mType.isInterfaceBlock(); }
bool isMatrix() const { return mType.isMatrix(); }
- bool isArray() const { return mType.isArray(); }
+ bool isArray() const { return mType.isArray(); }
bool isVector() const { return mType.isVector(); }
bool isScalar() const { return mType.isScalar(); }
bool isScalarInt() const { return mType.isScalarInt(); }
const char *getBasicString() const { return mType.getBasicString(); }
TString getCompleteString() const { return mType.getCompleteString(); }
- int getArraySize() const { return mType.getArraySize(); }
+ unsigned int getOutermostArraySize() const { return mType.getOutermostArraySize(); }
+
+ bool isConstructorWithOnlyConstantUnionParameters();
protected:
TType mType;
@@ -176,10 +204,7 @@ class TIntermLoop : public TIntermNode
TIntermNode *init,
TIntermTyped *cond,
TIntermTyped *expr,
- TIntermAggregate *body)
- : mType(type), mInit(init), mCond(cond), mExpr(expr), mBody(body), mUnrollFlag(false)
- {
- }
+ TIntermBlock *body);
TIntermLoop *getAsLoopNode() override { return this; }
void traverse(TIntermTraverser *it) override;
@@ -189,19 +214,19 @@ class TIntermLoop : public TIntermNode
TIntermNode *getInit() { return mInit; }
TIntermTyped *getCondition() { return mCond; }
TIntermTyped *getExpression() { return mExpr; }
- TIntermAggregate *getBody() { return mBody; }
+ TIntermBlock *getBody() { return mBody; }
- void setUnrollFlag(bool flag) { mUnrollFlag = flag; }
- bool getUnrollFlag() const { return mUnrollFlag; }
+ void setInit(TIntermNode *init) { mInit = init; }
+ void setCondition(TIntermTyped *condition) { mCond = condition; }
+ void setExpression(TIntermTyped *expression) { mExpr = expression; }
+ void setBody(TIntermBlock *body) { mBody = body; }
protected:
TLoopType mType;
- TIntermNode *mInit; // for-loop initialization
- TIntermTyped *mCond; // loop exit condition
- TIntermTyped *mExpr; // for-loop expression
- TIntermAggregate *mBody; // loop body
-
- bool mUnrollFlag; // Whether the loop should be unrolled or not.
+ TIntermNode *mInit; // for-loop initialization
+ TIntermTyped *mCond; // loop exit condition
+ TIntermTyped *mExpr; // for-loop expression
+ TIntermBlock *mBody; // loop body
};
//
@@ -210,17 +235,16 @@ class TIntermLoop : public TIntermNode
class TIntermBranch : public TIntermNode
{
public:
- TIntermBranch(TOperator op, TIntermTyped *e)
- : mFlowOp(op),
- mExpression(e) { }
+ TIntermBranch(TOperator op, TIntermTyped *e) : mFlowOp(op), mExpression(e) {}
void traverse(TIntermTraverser *it) override;
+ TIntermBranch *getAsBranchNode() override { return this; }
bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
TOperator getFlowOp() { return mFlowOp; }
- TIntermTyped* getExpression() { return mExpression; }
+ TIntermTyped *getExpression() { return mExpression; }
-protected:
+ protected:
TOperator mFlowOp;
TIntermTyped *mExpression; // non-zero except for "return exp;" statements
};
@@ -234,7 +258,7 @@ class TIntermSymbol : public TIntermTyped
// if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym.
// If sym comes from per process globalpoolallocator, then it causes increased memory usage
// per compile it is essential to use "symbol = sym" to assign to symbol
- TIntermSymbol(int id, const TString &symbol, const TType &type)
+ TIntermSymbol(const TSymbolUniqueId &id, const TString &symbol, const TType &type)
: TIntermTyped(type), mId(id), mSymbol(symbol)
{
}
@@ -243,11 +267,10 @@ class TIntermSymbol : public TIntermTyped
bool hasSideEffects() const override { return false; }
- int getId() const { return mId; }
+ int getId() const { return mId.get(); }
const TString &getSymbol() const { return mSymbol.getString(); }
const TName &getName() const { return mSymbol; }
-
- void setId(int newId) { mId = newId; }
+ TName &getName() { return mSymbol; }
void setInternal(bool internal) { mSymbol.setInternal(internal); }
@@ -256,7 +279,7 @@ class TIntermSymbol : public TIntermTyped
bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; }
protected:
- int mId;
+ const TSymbolUniqueId mId;
TName mSymbol;
private:
@@ -269,9 +292,7 @@ class TIntermSymbol : public TIntermTyped
class TIntermRaw : public TIntermTyped
{
public:
- TIntermRaw(const TType &type, const TString &rawText)
- : TIntermTyped(type),
- mRawText(rawText) { }
+ TIntermRaw(const TType &type, const TString &rawText) : TIntermTyped(type), mRawText(rawText) {}
TIntermRaw(const TIntermRaw &) = delete;
TIntermTyped *deepCopy() const override
@@ -305,6 +326,7 @@ class TIntermConstantUnion : public TIntermTyped
TIntermConstantUnion(const TConstantUnion *unionPointer, const TType &type)
: TIntermTyped(type), mUnionArrayPointer(unionPointer)
{
+ ASSERT(unionPointer);
}
TIntermTyped *deepCopy() const override { return new TIntermConstantUnion(*this); }
@@ -332,6 +354,7 @@ class TIntermConstantUnion : public TIntermTyped
void replaceConstantUnion(const TConstantUnion *safeConstantUnion)
{
+ ASSERT(safeConstantUnion);
// Previous union pointer freed on pool deallocation.
mUnionArrayPointer = safeConstantUnion;
}
@@ -340,21 +363,27 @@ class TIntermConstantUnion : public TIntermTyped
void traverse(TIntermTraverser *it) override;
bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; }
- TConstantUnion *foldBinary(TOperator op, TIntermConstantUnion *rightNode, TInfoSink &infoSink);
- TConstantUnion *foldUnaryWithDifferentReturnType(TOperator op, TInfoSink &infoSink);
- TConstantUnion *foldUnaryWithSameReturnType(TOperator op, TInfoSink &infoSink);
+ TConstantUnion *foldBinary(TOperator op,
+ TIntermConstantUnion *rightNode,
+ TDiagnostics *diagnostics,
+ const TSourceLoc &line);
+ const TConstantUnion *foldIndexing(int index);
+ TConstantUnion *foldUnaryNonComponentWise(TOperator op);
+ TConstantUnion *foldUnaryComponentWise(TOperator op, TDiagnostics *diagnostics);
- static TConstantUnion *FoldAggregateConstructor(TIntermAggregate *aggregate,
- TInfoSink &infoSink);
- static TConstantUnion *FoldAggregateBuiltIn(TIntermAggregate *aggregate, TInfoSink &infoSink);
+ static TConstantUnion *FoldAggregateConstructor(TIntermAggregate *aggregate);
+ static TConstantUnion *FoldAggregateBuiltIn(TIntermAggregate *aggregate,
+ TDiagnostics *diagnostics);
protected:
// Same data may be shared between multiple constant unions, so it can't be modified.
const TConstantUnion *mUnionArrayPointer;
private:
- typedef float(*FloatTypeUnaryFunc) (float);
- bool foldFloatTypeUnary(const TConstantUnion &parameter, FloatTypeUnaryFunc builtinFunc, TInfoSink &infoSink, TConstantUnion *result) const;
+ typedef float (*FloatTypeUnaryFunc)(float);
+ void foldFloatTypeUnary(const TConstantUnion &parameter,
+ FloatTypeUnaryFunc builtinFunc,
+ TConstantUnion *result) const;
TIntermConstantUnion(const TIntermConstantUnion &node); // Note: not deleted, just private!
};
@@ -366,25 +395,57 @@ class TIntermOperator : public TIntermTyped
{
public:
TOperator getOp() const { return mOp; }
- void setOp(TOperator op) { mOp = op; }
bool isAssignment() const;
bool isMultiplication() const;
bool isConstructor() const;
+ // Returns true for calls mapped to EOpCall*, false for built-ins that have their own specific
+ // ops.
+ bool isFunctionCall() const;
+
bool hasSideEffects() const override { return isAssignment(); }
protected:
- TIntermOperator(TOperator op)
- : TIntermTyped(TType(EbtFloat, EbpUndefined)),
- mOp(op) {}
- TIntermOperator(TOperator op, const TType &type)
- : TIntermTyped(type),
- mOp(op) {}
+ TIntermOperator(TOperator op) : TIntermTyped(TType(EbtFloat, EbpUndefined)), mOp(op) {}
+ TIntermOperator(TOperator op, const TType &type) : TIntermTyped(type), mOp(op) {}
TIntermOperator(const TIntermOperator &) = default;
- TOperator mOp;
+ const TOperator mOp;
+};
+
+// Node for vector swizzles.
+class TIntermSwizzle : public TIntermTyped
+{
+ public:
+ // This constructor determines the type of the node based on the operand.
+ TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets);
+
+ TIntermTyped *deepCopy() const override { return new TIntermSwizzle(*this); }
+
+ TIntermSwizzle *getAsSwizzleNode() override { return this; };
+ void traverse(TIntermTraverser *it) override;
+ bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
+
+ bool hasSideEffects() const override { return mOperand->hasSideEffects(); }
+
+ TIntermTyped *getOperand() { return mOperand; }
+ void writeOffsetsAsXYZW(TInfoSinkBase *out) const;
+
+ bool hasDuplicateOffsets() const;
+ bool offsetsMatch(int offset) const;
+
+ TIntermTyped *fold();
+
+ protected:
+ TIntermTyped *mOperand;
+ TVector<int> mSwizzleOffsets;
+
+ private:
+ void promote();
+
+ TIntermSwizzle(const TIntermSwizzle &node); // Note: not deleted, just private!
};
//
@@ -393,12 +454,17 @@ class TIntermOperator : public TIntermTyped
class TIntermBinary : public TIntermOperator
{
public:
- TIntermBinary(TOperator op)
- : TIntermOperator(op),
- mAddIndexClamp(false) {}
+ // This constructor determines the type of the binary node based on the operands and op.
+ TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right);
TIntermTyped *deepCopy() const override { return new TIntermBinary(*this); }
+ static TOperator GetMulOpBasedOnOperands(const TType &left, const TType &right);
+ static TOperator GetMulAssignOpBasedOnOperands(const TType &left, const TType &right);
+ static TQualifier GetCommaQualifier(int shaderVersion,
+ const TIntermTyped *left,
+ const TIntermTyped *right);
+
TIntermBinary *getAsBinaryNode() override { return this; };
void traverse(TIntermTraverser *it) override;
bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
@@ -408,24 +474,23 @@ class TIntermBinary : public TIntermOperator
return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects();
}
- void setLeft(TIntermTyped *node) { mLeft = node; }
- void setRight(TIntermTyped *node) { mRight = node; }
TIntermTyped *getLeft() const { return mLeft; }
TIntermTyped *getRight() const { return mRight; }
- bool promote(TInfoSink &);
- TIntermTyped *fold(TInfoSink &infoSink);
+ TIntermTyped *fold(TDiagnostics *diagnostics);
void setAddIndexClamp() { mAddIndexClamp = true; }
bool getAddIndexClamp() { return mAddIndexClamp; }
protected:
- TIntermTyped* mLeft;
- TIntermTyped* mRight;
+ TIntermTyped *mLeft;
+ TIntermTyped *mRight;
// If set to true, wrap any EOpIndexIndirect with a clamp to bounds.
bool mAddIndexClamp;
private:
+ void promote();
+
TIntermBinary(const TIntermBinary &node); // Note: not deleted, just private!
};
@@ -435,14 +500,7 @@ class TIntermBinary : public TIntermOperator
class TIntermUnary : public TIntermOperator
{
public:
- TIntermUnary(TOperator op, const TType &type)
- : TIntermOperator(op, type),
- mOperand(NULL),
- mUseEmulatedFunction(false) {}
- TIntermUnary(TOperator op)
- : TIntermOperator(op),
- mOperand(NULL),
- mUseEmulatedFunction(false) {}
+ TIntermUnary(TOperator op, TIntermTyped *operand);
TIntermTyped *deepCopy() const override { return new TIntermUnary(*this); }
@@ -452,10 +510,8 @@ class TIntermUnary : public TIntermOperator
bool hasSideEffects() const override { return isAssignment() || mOperand->hasSideEffects(); }
- void setOperand(TIntermTyped *operand) { mOperand = operand; }
TIntermTyped *getOperand() { return mOperand; }
- void promote(const TType *funcReturnType);
- TIntermTyped *fold(TInfoSink &infoSink);
+ TIntermTyped *fold(TDiagnostics *diagnostics);
void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
@@ -468,495 +524,394 @@ class TIntermUnary : public TIntermOperator
bool mUseEmulatedFunction;
private:
+ void promote();
+
TIntermUnary(const TIntermUnary &node); // note: not deleted, just private!
};
+class TFunctionSymbolInfo
+{
+ public:
+ POOL_ALLOCATOR_NEW_DELETE();
+ TFunctionSymbolInfo(const TSymbolUniqueId &id);
+ TFunctionSymbolInfo() : mId(nullptr), mKnownToNotHaveSideEffects(false) {}
+
+ TFunctionSymbolInfo(const TFunctionSymbolInfo &info);
+ TFunctionSymbolInfo &operator=(const TFunctionSymbolInfo &info);
+
+ void setFromFunction(const TFunction &function);
+
+ void setNameObj(const TName &name) { mName = name; }
+ const TName &getNameObj() const { return mName; }
+
+ const TString &getName() const { return mName.getString(); }
+ void setName(const TString &name) { mName.setString(name); }
+ bool isMain() const { return mName.getString() == "main"; }
+
+ void setKnownToNotHaveSideEffects(bool knownToNotHaveSideEffects)
+ {
+ mKnownToNotHaveSideEffects = knownToNotHaveSideEffects;
+ }
+ bool isKnownToNotHaveSideEffects() const { return mKnownToNotHaveSideEffects; }
+
+ void setId(const TSymbolUniqueId &functionId);
+ const TSymbolUniqueId &getId() const;
+
+ bool isImageFunction() const
+ {
+ return getName() == "imageSize" || getName() == "imageLoad" || getName() == "imageStore";
+ }
+
+ private:
+ TName mName;
+ TSymbolUniqueId *mId;
+ bool mKnownToNotHaveSideEffects;
+};
+
typedef TVector<TIntermNode *> TIntermSequence;
typedef TVector<int> TQualifierList;
//
+// This is just to help yacc.
+//
+struct TIntermFunctionCallOrMethod
+{
+ TIntermSequence *arguments;
+ TIntermNode *thisNode;
+};
+
+// Interface for node classes that have an arbitrarily sized set of children.
+class TIntermAggregateBase
+{
+ public:
+ virtual ~TIntermAggregateBase() {}
+
+ virtual TIntermSequence *getSequence() = 0;
+ virtual const TIntermSequence *getSequence() const = 0;
+
+ bool replaceChildNodeWithMultiple(TIntermNode *original, const TIntermSequence &replacements);
+ bool insertChildNodes(TIntermSequence::size_type position, const TIntermSequence &insertions);
+
+ protected:
+ TIntermAggregateBase() {}
+
+ bool replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement);
+};
+
+//
// Nodes that operate on an arbitrary sized set of children.
//
-class TIntermAggregate : public TIntermOperator
+class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase
{
public:
- TIntermAggregate()
- : TIntermOperator(EOpNull),
- mUserDefined(false),
- mUseEmulatedFunction(false),
- mGotPrecisionFromChildren(false)
- {
- }
- TIntermAggregate(TOperator op)
- : TIntermOperator(op),
- mUseEmulatedFunction(false),
- mGotPrecisionFromChildren(false)
- {
- }
- ~TIntermAggregate() { }
+ static TIntermAggregate *CreateFunctionCall(const TFunction &func, TIntermSequence *arguments);
+
+ // If using this, ensure that there's a consistent function definition with the same symbol id
+ // added to the AST.
+ static TIntermAggregate *CreateFunctionCall(const TType &type,
+ const TSymbolUniqueId &id,
+ const TName &name,
+ TIntermSequence *arguments);
+
+ static TIntermAggregate *CreateBuiltInFunctionCall(const TFunction &func,
+ TIntermSequence *arguments);
+ static TIntermAggregate *CreateConstructor(const TType &type,
+ TIntermSequence *arguments);
+ static TIntermAggregate *Create(const TType &type, TOperator op, TIntermSequence *arguments);
+ ~TIntermAggregate() {}
// Note: only supported for nodes that can be a part of an expression.
TIntermTyped *deepCopy() const override { return new TIntermAggregate(*this); }
+ TIntermAggregate *shallowCopy() const;
+
TIntermAggregate *getAsAggregate() override { return this; }
void traverse(TIntermTraverser *it) override;
bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
- bool replaceChildNodeWithMultiple(TIntermNode *original, TIntermSequence replacements);
- bool insertChildNodes(TIntermSequence::size_type position, TIntermSequence insertions);
- // Conservatively assume function calls and other aggregate operators have side-effects
- bool hasSideEffects() const override { return true; }
- TIntermTyped *fold(TInfoSink &infoSink);
- TIntermSequence *getSequence() { return &mSequence; }
+ bool hasSideEffects() const override;
- void setNameObj(const TName &name) { mName = name; }
- const TName &getNameObj() const { return mName; }
-
- void setName(const TString &name) { mName.setString(name); }
- const TString &getName() const { return mName.getString(); }
+ static bool CanFoldAggregateBuiltInOp(TOperator op);
+ TIntermTyped *fold(TDiagnostics *diagnostics);
- void setUserDefined() { mUserDefined = true; }
- bool isUserDefined() const { return mUserDefined; }
+ TIntermSequence *getSequence() override { return &mArguments; }
+ const TIntermSequence *getSequence() const override { return &mArguments; }
- void setFunctionId(int functionId) { mFunctionId = functionId; }
- int getFunctionId() const { return mFunctionId; }
+ TString getSymbolTableMangledName() const;
void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
- bool areChildrenConstQualified();
- void setPrecisionFromChildren();
- void setBuiltInFunctionPrecision();
-
// Returns true if changing parameter precision may affect the return value.
bool gotPrecisionFromChildren() const { return mGotPrecisionFromChildren; }
+ TFunctionSymbolInfo *getFunctionSymbolInfo() { return &mFunctionInfo; }
+ const TFunctionSymbolInfo *getFunctionSymbolInfo() const { return &mFunctionInfo; }
+
protected:
- TIntermSequence mSequence;
- TName mName;
- bool mUserDefined; // used for user defined function names
- int mFunctionId;
+ TIntermSequence mArguments;
// If set to true, replace the built-in function call with an emulated one
- // to work around driver bugs.
+ // to work around driver bugs. Only for calls mapped to ops other than EOpCall*.
bool mUseEmulatedFunction;
bool mGotPrecisionFromChildren;
+ TFunctionSymbolInfo mFunctionInfo;
+
private:
+ TIntermAggregate(const TType &type, TOperator op, TIntermSequence *arguments);
+
TIntermAggregate(const TIntermAggregate &node); // note: not deleted, just private!
+
+ void setTypePrecisionAndQualifier(const TType &type);
+
+ bool areChildrenConstQualified();
+
+ void setPrecisionFromChildren();
+
+ void setPrecisionForBuiltInOp();
+
+ // Returns true if precision was set according to special rules for this built-in.
+ bool setPrecisionForSpecialBuiltInOp();
+
+ // Used for built-in functions under EOpCallBuiltInFunction. The function name in the symbol
+ // info needs to be set before calling this.
+ void setBuiltInFunctionPrecision();
};
-//
-// For if tests.
-//
-class TIntermSelection : public TIntermTyped
+// A list of statements. Either the root node which contains declarations and function definitions,
+// or a block that can be marked with curly braces {}.
+class TIntermBlock : public TIntermNode, public TIntermAggregateBase
{
public:
- TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB)
- : TIntermTyped(TType(EbtVoid, EbpUndefined)),
- mCondition(cond),
- mTrueBlock(trueB),
- mFalseBlock(falseB) {}
- TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB,
- const TType &type)
- : TIntermTyped(type),
- mCondition(cond),
- mTrueBlock(trueB),
- mFalseBlock(falseB) {}
-
- // Note: only supported for ternary operator nodes.
- TIntermTyped *deepCopy() const override { return new TIntermSelection(*this); }
+ TIntermBlock() : TIntermNode() {}
+ ~TIntermBlock() {}
+ TIntermBlock *getAsBlock() override { return this; }
void traverse(TIntermTraverser *it) override;
bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
- // Conservatively assume selections have side-effects
- bool hasSideEffects() const override { return true; }
+ // Only intended for initially building the block.
+ void appendStatement(TIntermNode *statement);
- bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
- TIntermNode *getCondition() const { return mCondition; }
- TIntermNode *getTrueBlock() const { return mTrueBlock; }
- TIntermNode *getFalseBlock() const { return mFalseBlock; }
- TIntermSelection *getAsSelectionNode() override { return this; }
+ TIntermSequence *getSequence() override { return &mStatements; }
+ const TIntermSequence *getSequence() const override { return &mStatements; }
protected:
- TIntermTyped *mCondition;
- TIntermNode *mTrueBlock;
- TIntermNode *mFalseBlock;
-
- private:
- TIntermSelection(const TIntermSelection &node); // Note: not deleted, just private!
+ TIntermSequence mStatements;
};
-//
-// Switch statement.
-//
-class TIntermSwitch : public TIntermNode
+// Function prototype. May be in the AST either as a function prototype declaration or as a part of
+// a function definition. The type of the node is the function return type.
+class TIntermFunctionPrototype : public TIntermTyped, public TIntermAggregateBase
{
public:
- TIntermSwitch(TIntermTyped *init, TIntermAggregate *statementList)
- : TIntermNode(),
- mInit(init),
- mStatementList(statementList)
+ // TODO(oetuaho@nvidia.com): See if TFunctionSymbolInfo could be added to constructor
+ // parameters.
+ TIntermFunctionPrototype(const TType &type, const TSymbolUniqueId &id)
+ : TIntermTyped(type), mFunctionInfo(id)
{
}
+ ~TIntermFunctionPrototype() {}
+ TIntermFunctionPrototype *getAsFunctionPrototypeNode() override { return this; }
void traverse(TIntermTraverser *it) override;
- bool replaceChildNode(
- TIntermNode *original, TIntermNode *replacement) override;
+ bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
- TIntermSwitch *getAsSwitchNode() override { return this; }
+ TIntermTyped *deepCopy() const override
+ {
+ UNREACHABLE();
+ return nullptr;
+ }
+ bool hasSideEffects() const override
+ {
+ UNREACHABLE();
+ return true;
+ }
- TIntermTyped *getInit() { return mInit; }
- TIntermAggregate *getStatementList() { return mStatementList; }
- void setStatementList(TIntermAggregate *statementList) { mStatementList = statementList; }
+ // Only intended for initially building the declaration.
+ void appendParameter(TIntermSymbol *parameter);
+
+ TIntermSequence *getSequence() override { return &mParameters; }
+ const TIntermSequence *getSequence() const override { return &mParameters; }
+
+ TFunctionSymbolInfo *getFunctionSymbolInfo() { return &mFunctionInfo; }
+ const TFunctionSymbolInfo *getFunctionSymbolInfo() const { return &mFunctionInfo; }
protected:
- TIntermTyped *mInit;
- TIntermAggregate *mStatementList;
+ TIntermSequence mParameters;
+
+ TFunctionSymbolInfo mFunctionInfo;
};
-//
-// Case label.
-//
-class TIntermCase : public TIntermNode
+// Node for function definitions. The prototype child node stores the function header including
+// parameters, and the body child node stores the function body.
+class TIntermFunctionDefinition : public TIntermNode
{
public:
- TIntermCase(TIntermTyped *condition)
- : TIntermNode(),
- mCondition(condition)
+ TIntermFunctionDefinition(TIntermFunctionPrototype *prototype, TIntermBlock *body)
+ : TIntermNode(), mPrototype(prototype), mBody(body)
{
+ ASSERT(prototype != nullptr);
+ ASSERT(body != nullptr);
}
+ TIntermFunctionDefinition *getAsFunctionDefinition() override { return this; }
void traverse(TIntermTraverser *it) override;
- bool replaceChildNode(
- TIntermNode *original, TIntermNode *replacement) override;
+ bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
- TIntermCase *getAsCaseNode() override { return this; }
+ TIntermFunctionPrototype *getFunctionPrototype() const { return mPrototype; }
+ TIntermBlock *getBody() const { return mBody; }
- bool hasCondition() const { return mCondition != nullptr; }
- TIntermTyped *getCondition() const { return mCondition; }
+ const TFunctionSymbolInfo *getFunctionSymbolInfo() const
+ {
+ return mPrototype->getFunctionSymbolInfo();
+ }
- protected:
- TIntermTyped *mCondition;
+ private:
+ TIntermFunctionPrototype *mPrototype;
+ TIntermBlock *mBody;
};
-enum Visit
+// Struct, interface block or variable declaration. Can contain multiple variable declarators.
+class TIntermDeclaration : public TIntermNode, public TIntermAggregateBase
{
- PreVisit,
- InVisit,
- PostVisit
+ public:
+ TIntermDeclaration() : TIntermNode() {}
+ ~TIntermDeclaration() {}
+
+ TIntermDeclaration *getAsDeclarationNode() override { return this; }
+ void traverse(TIntermTraverser *it) override;
+ bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
+
+ // Only intended for initially building the declaration.
+ // The declarator node should be either TIntermSymbol or TIntermBinary with op set to
+ // EOpInitialize.
+ void appendDeclarator(TIntermTyped *declarator);
+
+ TIntermSequence *getSequence() override { return &mDeclarators; }
+ const TIntermSequence *getSequence() const override { return &mDeclarators; }
+ protected:
+ TIntermSequence mDeclarators;
};
-//
-// For traversing the tree. User should derive from this class overriding the visit functions,
-// and then pass an object of the subclass to a traverse method of a node.
-//
-// The traverse*() functions may also be overridden do other bookkeeping on the tree to provide
-// contextual information to the visit functions, such as whether the node is the target of an
-// assignment.
-//
-// When using this, just fill in the methods for nodes you want visited.
-// Return false from a pre-visit to skip visiting that node's subtree.
-//
-class TIntermTraverser : angle::NonCopyable
+// Specialized declarations for attributing invariance.
+class TIntermInvariantDeclaration : public TIntermNode
{
public:
- POOL_ALLOCATOR_NEW_DELETE();
- TIntermTraverser(bool preVisit, bool inVisit, bool postVisit)
- : preVisit(preVisit),
- inVisit(inVisit),
- postVisit(postVisit),
- mDepth(0),
- mMaxDepth(0),
- mTemporaryIndex(nullptr)
- {
- }
- virtual ~TIntermTraverser() {}
-
- virtual void visitSymbol(TIntermSymbol *node) {}
- virtual void visitRaw(TIntermRaw *node) {}
- virtual void visitConstantUnion(TIntermConstantUnion *node) {}
- virtual bool visitBinary(Visit visit, TIntermBinary *node) { return true; }
- virtual bool visitUnary(Visit visit, TIntermUnary *node) { return true; }
- virtual bool visitSelection(Visit visit, TIntermSelection *node) { return true; }
- virtual bool visitSwitch(Visit visit, TIntermSwitch *node) { return true; }
- virtual bool visitCase(Visit visit, TIntermCase *node) { return true; }
- virtual bool visitAggregate(Visit visit, TIntermAggregate *node) { return true; }
- virtual bool visitLoop(Visit visit, TIntermLoop *node) { return true; }
- virtual bool visitBranch(Visit visit, TIntermBranch *node) { return true; }
-
- // The traverse functions contain logic for iterating over the children of the node
- // and calling the visit functions in the appropriate places. They also track some
- // context that may be used by the visit functions.
- virtual void traverseSymbol(TIntermSymbol *node);
- virtual void traverseRaw(TIntermRaw *node);
- virtual void traverseConstantUnion(TIntermConstantUnion *node);
- virtual void traverseBinary(TIntermBinary *node);
- virtual void traverseUnary(TIntermUnary *node);
- virtual void traverseSelection(TIntermSelection *node);
- virtual void traverseSwitch(TIntermSwitch *node);
- virtual void traverseCase(TIntermCase *node);
- virtual void traverseAggregate(TIntermAggregate *node);
- virtual void traverseLoop(TIntermLoop *node);
- virtual void traverseBranch(TIntermBranch *node);
-
- int getMaxDepth() const { return mMaxDepth; }
-
- // Return the original name if hash function pointer is NULL;
- // otherwise return the hashed name.
- static TString hash(const TString &name, ShHashFunction64 hashFunction);
-
- // If traversers need to replace nodes, they can add the replacements in
- // mReplacements/mMultiReplacements during traversal and the user of the traverser should call
- // this function after traversal to perform them.
- void updateTree();
-
- // Start creating temporary symbols from the given temporary symbol index + 1.
- void useTemporaryIndex(unsigned int *temporaryIndex);
+ TIntermInvariantDeclaration(TIntermSymbol *symbol, const TSourceLoc &line);
- protected:
- void incrementDepth(TIntermNode *current)
- {
- mDepth++;
- mMaxDepth = std::max(mMaxDepth, mDepth);
- mPath.push_back(current);
- }
+ virtual TIntermInvariantDeclaration *getAsInvariantDeclarationNode() override { return this; }
- void decrementDepth()
- {
- mDepth--;
- mPath.pop_back();
- }
+ TIntermSymbol *getSymbol() { return mSymbol; }
- TIntermNode *getParentNode()
- {
- return mPath.size() == 0 ? NULL : mPath.back();
- }
+ void traverse(TIntermTraverser *it) override;
+ bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
- void pushParentBlock(TIntermAggregate *node);
- void incrementParentBlockPos();
- void popParentBlock();
+ private:
+ TIntermSymbol *mSymbol;
+};
- bool parentNodeIsBlock()
- {
- return !mParentBlockStack.empty() && getParentNode() == mParentBlockStack.back().node;
- }
+// For ternary operators like a ? b : c.
+class TIntermTernary : public TIntermTyped
+{
+ public:
+ TIntermTernary(TIntermTyped *cond, TIntermTyped *trueExpression, TIntermTyped *falseExpression);
- const bool preVisit;
- const bool inVisit;
- const bool postVisit;
+ void traverse(TIntermTraverser *it) override;
+ bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
- int mDepth;
- int mMaxDepth;
+ TIntermTyped *getCondition() const { return mCondition; }
+ TIntermTyped *getTrueExpression() const { return mTrueExpression; }
+ TIntermTyped *getFalseExpression() const { return mFalseExpression; }
+ TIntermTernary *getAsTernaryNode() override { return this; }
- // All the nodes from root to the current node's parent during traversing.
- TVector<TIntermNode *> mPath;
+ TIntermTyped *deepCopy() const override { return new TIntermTernary(*this); }
- // To replace a single node with another on the parent node
- struct NodeUpdateEntry
- {
- NodeUpdateEntry(TIntermNode *_parent,
- TIntermNode *_original,
- TIntermNode *_replacement,
- bool _originalBecomesChildOfReplacement)
- : parent(_parent),
- original(_original),
- replacement(_replacement),
- originalBecomesChildOfReplacement(_originalBecomesChildOfReplacement) {}
-
- TIntermNode *parent;
- TIntermNode *original;
- TIntermNode *replacement;
- bool originalBecomesChildOfReplacement;
- };
-
- // To replace a single node with multiple nodes on the parent aggregate node
- struct NodeReplaceWithMultipleEntry
- {
- NodeReplaceWithMultipleEntry(TIntermAggregate *_parent, TIntermNode *_original, TIntermSequence _replacements)
- : parent(_parent),
- original(_original),
- replacements(_replacements)
- {
- }
-
- TIntermAggregate *parent;
- TIntermNode *original;
- TIntermSequence replacements;
- };
-
- // To insert multiple nodes on the parent aggregate node
- struct NodeInsertMultipleEntry
+ bool hasSideEffects() const override
{
- NodeInsertMultipleEntry(TIntermAggregate *_parent,
- TIntermSequence::size_type _position,
- TIntermSequence _insertionsBefore,
- TIntermSequence _insertionsAfter)
- : parent(_parent),
- position(_position),
- insertionsBefore(_insertionsBefore),
- insertionsAfter(_insertionsAfter)
- {
- }
-
- TIntermAggregate *parent;
- TIntermSequence::size_type position;
- TIntermSequence insertionsBefore;
- TIntermSequence insertionsAfter;
- };
-
- // During traversing, save all the changes that need to happen into
- // mReplacements/mMultiReplacements, then do them by calling updateTree().
- // Multi replacements are processed after single replacements.
- std::vector<NodeUpdateEntry> mReplacements;
- std::vector<NodeReplaceWithMultipleEntry> mMultiReplacements;
- std::vector<NodeInsertMultipleEntry> mInsertions;
-
- // Helper to insert statements in the parent block (sequence) of the node currently being traversed.
- // The statements will be inserted before the node being traversed once updateTree is called.
- // Should only be called during PreVisit or PostVisit from sequence nodes.
- // Note that inserting more than one set of nodes to the same parent node on a single updateTree call is not
- // supported.
- void insertStatementsInParentBlock(const TIntermSequence &insertions);
-
- // Same as above, but supports simultaneous insertion of statements before and after the node
- // currently being traversed.
- void insertStatementsInParentBlock(const TIntermSequence &insertionsBefore,
- const TIntermSequence &insertionsAfter);
-
- // Helper to create a temporary symbol node with the given qualifier.
- TIntermSymbol *createTempSymbol(const TType &type, TQualifier qualifier);
- // Helper to create a temporary symbol node.
- TIntermSymbol *createTempSymbol(const TType &type);
- // Create a node that declares but doesn't initialize a temporary symbol.
- TIntermAggregate *createTempDeclaration(const TType &type);
- // Create a node that initializes the current temporary symbol with initializer having the given qualifier.
- TIntermAggregate *createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier);
- // Create a node that initializes the current temporary symbol with initializer.
- TIntermAggregate *createTempInitDeclaration(TIntermTyped *initializer);
- // Create a node that assigns rightNode to the current temporary symbol.
- TIntermBinary *createTempAssignment(TIntermTyped *rightNode);
- // Increment temporary symbol index.
- void nextTemporaryIndex();
+ return mCondition->hasSideEffects() || mTrueExpression->hasSideEffects() ||
+ mFalseExpression->hasSideEffects();
+ }
+
+ TIntermTyped *fold();
private:
- struct ParentBlock
- {
- ParentBlock(TIntermAggregate *nodeIn, TIntermSequence::size_type posIn)
- : node(nodeIn),
- pos(posIn)
- {
- }
-
- TIntermAggregate *node;
- TIntermSequence::size_type pos;
- };
- // All the code blocks from the root to the current node's parent during traversal.
- std::vector<ParentBlock> mParentBlockStack;
-
- unsigned int *mTemporaryIndex;
+ TIntermTernary(const TIntermTernary &node); // Note: not deleted, just private!
+
+ static TQualifier DetermineQualifier(TIntermTyped *cond,
+ TIntermTyped *trueExpression,
+ TIntermTyped *falseExpression);
+
+ TIntermTyped *mCondition;
+ TIntermTyped *mTrueExpression;
+ TIntermTyped *mFalseExpression;
};
-// Traverser parent class that tracks where a node is a destination of a write operation and so is
-// required to be an l-value.
-class TLValueTrackingTraverser : public TIntermTraverser
+class TIntermIfElse : public TIntermNode
{
public:
- TLValueTrackingTraverser(bool preVisit,
- bool inVisit,
- bool postVisit,
- const TSymbolTable &symbolTable,
- int shaderVersion)
- : TIntermTraverser(preVisit, inVisit, postVisit),
- mOperatorRequiresLValue(false),
- mInFunctionCallOutParameter(false),
- mSymbolTable(symbolTable),
- mShaderVersion(shaderVersion)
- {
- }
- virtual ~TLValueTrackingTraverser() {}
+ TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlock *falseB);
- void traverseBinary(TIntermBinary *node) override;
- void traverseUnary(TIntermUnary *node) override;
- void traverseAggregate(TIntermAggregate *node) override;
+ void traverse(TIntermTraverser *it) override;
+ bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
- protected:
- bool isLValueRequiredHere() const
- {
- return mOperatorRequiresLValue || mInFunctionCallOutParameter;
- }
+ TIntermTyped *getCondition() const { return mCondition; }
+ TIntermBlock *getTrueBlock() const { return mTrueBlock; }
+ TIntermBlock *getFalseBlock() const { return mFalseBlock; }
+ TIntermIfElse *getAsIfElseNode() override { return this; }
- // Return true if the prototype or definition of the function being called has been encountered
- // during traversal.
- bool isInFunctionMap(const TIntermAggregate *callNode) const;
+ protected:
+ TIntermTyped *mCondition;
+ TIntermBlock *mTrueBlock;
+ TIntermBlock *mFalseBlock;
+};
- private:
- // Track whether an l-value is required in the node that is currently being traversed by the
- // surrounding operator.
- // Use isLValueRequiredHere to check all conditions which require an l-value.
- void setOperatorRequiresLValue(bool lValueRequired)
- {
- mOperatorRequiresLValue = lValueRequired;
- }
- bool operatorRequiresLValue() const { return mOperatorRequiresLValue; }
+//
+// Switch statement.
+//
+class TIntermSwitch : public TIntermNode
+{
+ public:
+ TIntermSwitch(TIntermTyped *init, TIntermBlock *statementList);
- // Add a function encountered during traversal to the function map.
- void addToFunctionMap(const TName &name, TIntermSequence *paramSequence);
+ void traverse(TIntermTraverser *it) override;
+ bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
- // Return the parameters sequence from the function definition or prototype.
- TIntermSequence *getFunctionParameters(const TIntermAggregate *callNode);
+ TIntermSwitch *getAsSwitchNode() override { return this; }
- // Track whether an l-value is required inside a function call.
- void setInFunctionCallOutParameter(bool inOutParameter);
- bool isInFunctionCallOutParameter() const;
+ TIntermTyped *getInit() { return mInit; }
+ TIntermBlock *getStatementList() { return mStatementList; }
- bool mOperatorRequiresLValue;
- bool mInFunctionCallOutParameter;
+ // Must be called with a non-null statementList.
+ void setStatementList(TIntermBlock *statementList);
- struct TNameComparator
- {
- bool operator()(const TName &a, const TName &b) const
- {
- int compareResult = a.getString().compare(b.getString());
- if (compareResult != 0)
- return compareResult < 0;
- // Internal functions may have same names as non-internal functions.
- return !a.isInternal() && b.isInternal();
- }
- };
-
- // Map from mangled function names to their parameter sequences
- TMap<TName, TIntermSequence *, TNameComparator> mFunctionMap;
-
- const TSymbolTable &mSymbolTable;
- const int mShaderVersion;
+ protected:
+ TIntermTyped *mInit;
+ TIntermBlock *mStatementList;
};
//
-// For traversing the tree, and computing max depth.
-// Takes a maximum depth limit to prevent stack overflow.
+// Case label.
//
-class TMaxDepthTraverser : public TIntermTraverser
+class TIntermCase : public TIntermNode
{
public:
- POOL_ALLOCATOR_NEW_DELETE();
- TMaxDepthTraverser(int depthLimit)
- : TIntermTraverser(true, true, false),
- mDepthLimit(depthLimit) { }
+ TIntermCase(TIntermTyped *condition) : TIntermNode(), mCondition(condition) {}
- bool visitBinary(Visit, TIntermBinary *) override { return depthCheck(); }
- bool visitUnary(Visit, TIntermUnary *) override { return depthCheck(); }
- bool visitSelection(Visit, TIntermSelection *) override { return depthCheck(); }
- bool visitAggregate(Visit, TIntermAggregate *) override { return depthCheck(); }
- bool visitLoop(Visit, TIntermLoop *) override { return depthCheck(); }
- bool visitBranch(Visit, TIntermBranch *) override { return depthCheck(); }
+ void traverse(TIntermTraverser *it) override;
+ bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
- protected:
- bool depthCheck() const { return mMaxDepth < mDepthLimit; }
+ TIntermCase *getAsCaseNode() override { return this; }
- int mDepthLimit;
+ bool hasCondition() const { return mCondition != nullptr; }
+ TIntermTyped *getCondition() const { return mCondition; }
+
+ protected:
+ TIntermTyped *mCondition;
};
+} // namespace sh
+
#endif // COMPILER_TRANSLATOR_INTERMNODE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.cpp b/src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.cpp
new file mode 100644
index 0000000000..567e8f7440
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.cpp
@@ -0,0 +1,157 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// IntermNodePatternMatcher is a helper class for matching node trees to given patterns.
+// It can be used whenever the same checks for certain node structures are common to multiple AST
+// traversers.
+//
+
+#include "compiler/translator/IntermNodePatternMatcher.h"
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+IntermNodePatternMatcher::IntermNodePatternMatcher(const unsigned int mask) : mMask(mask)
+{
+}
+
+// static
+bool IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(TIntermBinary *node)
+{
+ return node->getOp() == EOpIndexIndirect && !node->getLeft()->isArray() &&
+ node->getLeft()->getBasicType() != EbtStruct;
+}
+
+bool IntermNodePatternMatcher::matchInternal(TIntermBinary *node, TIntermNode *parentNode)
+{
+ if ((mMask & kExpressionReturningArray) != 0)
+ {
+ if (node->isArray() && node->getOp() == EOpAssign && parentNode != nullptr &&
+ !parentNode->getAsBlock())
+ {
+ return true;
+ }
+ }
+
+ if ((mMask & kUnfoldedShortCircuitExpression) != 0)
+ {
+ if (node->getRight()->hasSideEffects() &&
+ (node->getOp() == EOpLogicalOr || node->getOp() == EOpLogicalAnd))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool IntermNodePatternMatcher::match(TIntermUnary *node)
+{
+ if ((mMask & kArrayLengthMethod) != 0)
+ {
+ if (node->getOp() == EOpArrayLength)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool IntermNodePatternMatcher::match(TIntermBinary *node, TIntermNode *parentNode)
+{
+ // L-value tracking information is needed to check for dynamic indexing in L-value.
+ // Traversers that don't track l-values can still use this class and match binary nodes with
+ // this variation of this method if they don't need to check for dynamic indexing in l-values.
+ ASSERT((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) == 0);
+ return matchInternal(node, parentNode);
+}
+
+bool IntermNodePatternMatcher::match(TIntermBinary *node,
+ TIntermNode *parentNode,
+ bool isLValueRequiredHere)
+{
+ if (matchInternal(node, parentNode))
+ {
+ return true;
+ }
+ if ((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) != 0)
+ {
+ if (isLValueRequiredHere && IsDynamicIndexingOfVectorOrMatrix(node))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool IntermNodePatternMatcher::match(TIntermAggregate *node, TIntermNode *parentNode)
+{
+ if ((mMask & kExpressionReturningArray) != 0)
+ {
+ if (parentNode != nullptr)
+ {
+ TIntermBinary *parentBinary = parentNode->getAsBinaryNode();
+ bool parentIsAssignment =
+ (parentBinary != nullptr &&
+ (parentBinary->getOp() == EOpAssign || parentBinary->getOp() == EOpInitialize));
+
+ if (node->getType().isArray() && !parentIsAssignment &&
+ (node->isConstructor() || node->isFunctionCall()) && !parentNode->getAsBlock())
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool IntermNodePatternMatcher::match(TIntermTernary *node)
+{
+ if ((mMask & kUnfoldedShortCircuitExpression) != 0)
+ {
+ return true;
+ }
+ return false;
+}
+
+bool IntermNodePatternMatcher::match(TIntermDeclaration *node)
+{
+ if ((mMask & kMultiDeclaration) != 0)
+ {
+ if (node->getSequence()->size() > 1)
+ {
+ return true;
+ }
+ }
+ if ((mMask & kArrayDeclaration) != 0)
+ {
+ if (node->getSequence()->front()->getAsTyped()->getType().isStructureContainingArrays())
+ {
+ return true;
+ }
+ // Need to check from all declarators whether they are arrays since that may vary between
+ // declarators.
+ for (TIntermNode *declarator : *node->getSequence())
+ {
+ if (declarator->getAsTyped()->isArray())
+ {
+ return true;
+ }
+ }
+ }
+ if ((mMask & kNamelessStructDeclaration) != 0)
+ {
+ TIntermTyped *declarator = node->getSequence()->front()->getAsTyped();
+ if (declarator->getBasicType() == EbtStruct &&
+ declarator->getType().getStruct()->name() == "")
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.h b/src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.h
new file mode 100644
index 0000000000..997fc2ef10
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/IntermNodePatternMatcher.h
@@ -0,0 +1,75 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// IntermNodePatternMatcher is a helper class for matching node trees to given patterns.
+// It can be used whenever the same checks for certain node structures are common to multiple AST
+// traversers.
+//
+
+#ifndef COMPILER_TRANSLATOR_INTERMNODEPATTERNMATCHER_H_
+#define COMPILER_TRANSLATOR_INTERMNODEPATTERNMATCHER_H_
+
+namespace sh
+{
+
+class TIntermAggregate;
+class TIntermBinary;
+class TIntermDeclaration;
+class TIntermNode;
+class TIntermTernary;
+class TIntermUnary;
+
+class IntermNodePatternMatcher
+{
+ public:
+ static bool IsDynamicIndexingOfVectorOrMatrix(TIntermBinary *node);
+
+ enum PatternType
+ {
+ // Matches expressions that are unfolded to if statements by UnfoldShortCircuitToIf
+ kUnfoldedShortCircuitExpression = 0x0001,
+
+ // Matches expressions that return arrays with the exception of simple statements where a
+ // constructor or function call result is assigned.
+ kExpressionReturningArray = 0x0001 << 1,
+
+ // Matches dynamic indexing of vectors or matrices in l-values.
+ kDynamicIndexingOfVectorOrMatrixInLValue = 0x0001 << 2,
+
+ // Matches declarations with more than one declared variables.
+ kMultiDeclaration = 0x0001 << 3,
+
+ // Matches declarations of arrays.
+ kArrayDeclaration = 0x0001 << 4,
+
+ // Matches declarations of structs where the struct type does not have a name.
+ kNamelessStructDeclaration = 0x0001 << 5,
+
+ // Matches array length() method.
+ kArrayLengthMethod = 0x0001 << 6
+ };
+ IntermNodePatternMatcher(const unsigned int mask);
+
+ bool match(TIntermUnary *node);
+
+ bool match(TIntermBinary *node, TIntermNode *parentNode);
+
+ // Use this version for checking binary node matches in case you're using flag
+ // kDynamicIndexingOfVectorOrMatrixInLValue.
+ bool match(TIntermBinary *node, TIntermNode *parentNode, bool isLValueRequiredHere);
+
+ bool match(TIntermAggregate *node, TIntermNode *parentNode);
+ bool match(TIntermTernary *node);
+ bool match(TIntermDeclaration *node);
+
+ private:
+ const unsigned int mMask;
+
+ bool matchInternal(TIntermBinary *node, TIntermNode *parentNode);
+};
+
+} // namespace sh
+
+#endif
diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode_util.cpp b/src/3rdparty/angle/src/compiler/translator/IntermNode_util.cpp
new file mode 100644
index 0000000000..9f1f596c43
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/IntermNode_util.cpp
@@ -0,0 +1,254 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// IntermNode_util.cpp: High-level utilities for creating AST nodes and node hierarchies. Mostly
+// meant to be used in AST transforms.
+
+#include "compiler/translator/IntermNode_util.h"
+
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+namespace
+{
+
+TName GetInternalFunctionName(const char *name)
+{
+ TString nameStr(name);
+ TName nameObj(nameStr);
+ nameObj.setInternal(true);
+ return nameObj;
+}
+
+const TFunction *LookUpBuiltInFunction(const TString &name,
+ const TIntermSequence *arguments,
+ const TSymbolTable &symbolTable,
+ int shaderVersion)
+{
+ TString mangledName = TFunction::GetMangledNameFromCall(name, *arguments);
+ TSymbol *symbol = symbolTable.findBuiltIn(mangledName, shaderVersion);
+ if (symbol)
+ {
+ ASSERT(symbol->isFunction());
+ return static_cast<const TFunction *>(symbol);
+ }
+ return nullptr;
+}
+
+} // anonymous namespace
+
+TIntermFunctionPrototype *CreateInternalFunctionPrototypeNode(const TType &returnType,
+ const char *name,
+ const TSymbolUniqueId &functionId)
+{
+ TIntermFunctionPrototype *functionNode = new TIntermFunctionPrototype(returnType, functionId);
+ functionNode->getFunctionSymbolInfo()->setNameObj(GetInternalFunctionName(name));
+ return functionNode;
+}
+
+TIntermFunctionDefinition *CreateInternalFunctionDefinitionNode(const TType &returnType,
+ const char *name,
+ TIntermBlock *functionBody,
+ const TSymbolUniqueId &functionId)
+{
+ TIntermFunctionPrototype *prototypeNode =
+ CreateInternalFunctionPrototypeNode(returnType, name, functionId);
+ return new TIntermFunctionDefinition(prototypeNode, functionBody);
+}
+
+TIntermAggregate *CreateInternalFunctionCallNode(const TType &returnType,
+ const char *name,
+ const TSymbolUniqueId &functionId,
+ TIntermSequence *arguments)
+{
+ TIntermAggregate *functionNode = TIntermAggregate::CreateFunctionCall(
+ returnType, functionId, GetInternalFunctionName(name), arguments);
+ return functionNode;
+}
+
+TIntermTyped *CreateZeroNode(const TType &type)
+{
+ TType constType(type);
+ constType.setQualifier(EvqConst);
+
+ if (!type.isArray() && type.getBasicType() != EbtStruct)
+ {
+ size_t size = constType.getObjectSize();
+ TConstantUnion *u = new TConstantUnion[size];
+ for (size_t i = 0; i < size; ++i)
+ {
+ switch (type.getBasicType())
+ {
+ case EbtFloat:
+ u[i].setFConst(0.0f);
+ break;
+ case EbtInt:
+ u[i].setIConst(0);
+ break;
+ case EbtUInt:
+ u[i].setUConst(0u);
+ break;
+ case EbtBool:
+ u[i].setBConst(false);
+ break;
+ default:
+ // CreateZeroNode is called by ParseContext that keeps parsing even when an
+ // error occurs, so it is possible for CreateZeroNode to be called with
+ // non-basic types. This happens only on error condition but CreateZeroNode
+ // needs to return a value with the correct type to continue the typecheck.
+ // That's why we handle non-basic type by setting whatever value, we just need
+ // the type to be right.
+ u[i].setIConst(42);
+ break;
+ }
+ }
+
+ TIntermConstantUnion *node = new TIntermConstantUnion(u, constType);
+ return node;
+ }
+
+ if (type.getBasicType() == EbtVoid)
+ {
+ // Void array. This happens only on error condition, similarly to the case above. We don't
+ // have a constructor operator for void, so this needs special handling. We'll end up with a
+ // value without the array type, but that should not be a problem.
+ while (constType.isArray())
+ {
+ constType.toArrayElementType();
+ }
+ return CreateZeroNode(constType);
+ }
+
+ TIntermSequence *arguments = new TIntermSequence();
+
+ if (type.isArray())
+ {
+ TType elementType(type);
+ elementType.toArrayElementType();
+
+ size_t arraySize = type.getOutermostArraySize();
+ for (size_t i = 0; i < arraySize; ++i)
+ {
+ arguments->push_back(CreateZeroNode(elementType));
+ }
+ }
+ else
+ {
+ ASSERT(type.getBasicType() == EbtStruct);
+
+ const TStructure *structure = type.getStruct();
+ for (const auto &field : structure->fields())
+ {
+ arguments->push_back(CreateZeroNode(*field->type()));
+ }
+ }
+
+ return TIntermAggregate::CreateConstructor(constType, arguments);
+}
+
+TIntermConstantUnion *CreateIndexNode(int index)
+{
+ TConstantUnion *u = new TConstantUnion[1];
+ u[0].setIConst(index);
+
+ TType type(EbtInt, EbpUndefined, EvqConst, 1);
+ TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
+ return node;
+}
+
+TIntermConstantUnion *CreateBoolNode(bool value)
+{
+ TConstantUnion *u = new TConstantUnion[1];
+ u[0].setBConst(value);
+
+ TType type(EbtBool, EbpUndefined, EvqConst, 1);
+ TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
+ return node;
+}
+
+TIntermSymbol *CreateTempSymbolNode(const TSymbolUniqueId &id,
+ const TType &type,
+ TQualifier qualifier)
+{
+ TInfoSinkBase symbolNameOut;
+ symbolNameOut << "s" << id.get();
+ TString symbolName = symbolNameOut.c_str();
+
+ TIntermSymbol *node = new TIntermSymbol(id, symbolName, type);
+ node->setInternal(true);
+
+ ASSERT(qualifier == EvqTemporary || qualifier == EvqConst || qualifier == EvqGlobal);
+ node->getTypePointer()->setQualifier(qualifier);
+
+ // TODO(oetuaho): Might be useful to sanitize layout qualifier etc. on the type of the created
+ // symbol. This might need to be done in other places as well.
+ return node;
+}
+
+TIntermDeclaration *CreateTempInitDeclarationNode(const TSymbolUniqueId &id,
+ TIntermTyped *initializer,
+ TQualifier qualifier)
+{
+ ASSERT(initializer != nullptr);
+ TIntermSymbol *tempSymbol = CreateTempSymbolNode(id, initializer->getType(), qualifier);
+ TIntermDeclaration *tempDeclaration = new TIntermDeclaration();
+ TIntermBinary *tempInit = new TIntermBinary(EOpInitialize, tempSymbol, initializer);
+ tempDeclaration->appendDeclarator(tempInit);
+ return tempDeclaration;
+}
+
+TIntermBlock *EnsureBlock(TIntermNode *node)
+{
+ if (node == nullptr)
+ return nullptr;
+ TIntermBlock *blockNode = node->getAsBlock();
+ if (blockNode != nullptr)
+ return blockNode;
+
+ blockNode = new TIntermBlock();
+ blockNode->setLine(node->getLine());
+ blockNode->appendStatement(node);
+ return blockNode;
+}
+
+TIntermSymbol *ReferenceGlobalVariable(const TString &name, const TSymbolTable &symbolTable)
+{
+ TVariable *var = reinterpret_cast<TVariable *>(symbolTable.findGlobal(name));
+ ASSERT(var);
+ return new TIntermSymbol(var->getUniqueId(), name, var->getType());
+}
+
+TIntermSymbol *ReferenceBuiltInVariable(const TString &name,
+ const TSymbolTable &symbolTable,
+ int shaderVersion)
+{
+ const TVariable *var =
+ reinterpret_cast<const TVariable *>(symbolTable.findBuiltIn(name, shaderVersion, true));
+ ASSERT(var);
+ return new TIntermSymbol(var->getUniqueId(), name, var->getType());
+}
+
+TIntermTyped *CreateBuiltInFunctionCallNode(const TString &name,
+ TIntermSequence *arguments,
+ const TSymbolTable &symbolTable,
+ int shaderVersion)
+{
+ const TFunction *fn = LookUpBuiltInFunction(name, arguments, symbolTable, shaderVersion);
+ ASSERT(fn);
+ TOperator op = fn->getBuiltInOp();
+ if (op != EOpNull)
+ {
+ if (arguments->size() == 1)
+ {
+ return new TIntermUnary(op, arguments->at(0)->getAsTyped());
+ }
+ return TIntermAggregate::Create(fn->getReturnType(), op, arguments);
+ }
+ return TIntermAggregate::CreateBuiltInFunctionCall(*fn, arguments);
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode_util.h b/src/3rdparty/angle/src/compiler/translator/IntermNode_util.h
new file mode 100644
index 0000000000..6f3b0674f0
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/IntermNode_util.h
@@ -0,0 +1,60 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// IntermNode_util.h: High-level utilities for creating AST nodes and node hierarchies. Mostly meant
+// to be used in AST transforms.
+
+#ifndef COMPILER_TRANSLATOR_INTERMNODEUTIL_H_
+#define COMPILER_TRANSLATOR_INTERMNODEUTIL_H_
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+TIntermFunctionPrototype *CreateInternalFunctionPrototypeNode(const TType &returnType,
+ const char *name,
+ const TSymbolUniqueId &functionId);
+TIntermFunctionDefinition *CreateInternalFunctionDefinitionNode(const TType &returnType,
+ const char *name,
+ TIntermBlock *functionBody,
+ const TSymbolUniqueId &functionId);
+TIntermAggregate *CreateInternalFunctionCallNode(const TType &returnType,
+ const char *name,
+ const TSymbolUniqueId &functionId,
+ TIntermSequence *arguments);
+
+TIntermTyped *CreateZeroNode(const TType &type);
+TIntermConstantUnion *CreateIndexNode(int index);
+TIntermConstantUnion *CreateBoolNode(bool value);
+
+TIntermSymbol *CreateTempSymbolNode(const TSymbolUniqueId &id,
+ const TType &type,
+ TQualifier qualifier);
+TIntermDeclaration *CreateTempInitDeclarationNode(const TSymbolUniqueId &id,
+ TIntermTyped *initializer,
+ TQualifier qualifier);
+
+// If the input node is nullptr, return nullptr.
+// If the input node is a block node, return it.
+// If the input node is not a block node, put it inside a block node and return that.
+TIntermBlock *EnsureBlock(TIntermNode *node);
+
+// Should be called from inside Compiler::compileTreeImpl() where the global level is in scope.
+TIntermSymbol *ReferenceGlobalVariable(const TString &name, const TSymbolTable &symbolTable);
+
+// Note: this can access desktop GLSL built-ins that are hidden from the parser.
+TIntermSymbol *ReferenceBuiltInVariable(const TString &name,
+ const TSymbolTable &symbolTable,
+ int shaderVersion);
+
+TIntermTyped *CreateBuiltInFunctionCallNode(const TString &name,
+ TIntermSequence *arguments,
+ const TSymbolTable &symbolTable,
+ int shaderVersion);
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_INTERMNODEUTIL_H_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp
index 7b588ca5a3..6c25c6c35a 100644
--- a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp
@@ -4,10 +4,15 @@
// found in the LICENSE file.
//
-#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermTraverse.h"
+
#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/IntermNode_util.h"
#include "compiler/translator/SymbolTable.h"
+namespace sh
+{
+
void TIntermSymbol::traverse(TIntermTraverser *it)
{
it->traverseSymbol(this);
@@ -23,6 +28,11 @@ void TIntermConstantUnion::traverse(TIntermTraverser *it)
it->traverseConstantUnion(this);
}
+void TIntermSwizzle::traverse(TIntermTraverser *it)
+{
+ it->traverseSwizzle(this);
+}
+
void TIntermBinary::traverse(TIntermTraverser *it)
{
it->traverseBinary(this);
@@ -33,9 +43,14 @@ void TIntermUnary::traverse(TIntermTraverser *it)
it->traverseUnary(this);
}
-void TIntermSelection::traverse(TIntermTraverser *it)
+void TIntermTernary::traverse(TIntermTraverser *it)
+{
+ it->traverseTernary(this);
+}
+
+void TIntermIfElse::traverse(TIntermTraverser *it)
{
- it->traverseSelection(this);
+ it->traverseIfElse(this);
}
void TIntermSwitch::traverse(TIntermTraverser *it)
@@ -48,6 +63,31 @@ void TIntermCase::traverse(TIntermTraverser *it)
it->traverseCase(this);
}
+void TIntermFunctionDefinition::traverse(TIntermTraverser *it)
+{
+ it->traverseFunctionDefinition(this);
+}
+
+void TIntermBlock::traverse(TIntermTraverser *it)
+{
+ it->traverseBlock(this);
+}
+
+void TIntermInvariantDeclaration::traverse(TIntermTraverser *it)
+{
+ it->traverseInvariantDeclaration(this);
+}
+
+void TIntermDeclaration::traverse(TIntermTraverser *it)
+{
+ it->traverseDeclaration(this);
+}
+
+void TIntermFunctionPrototype::traverse(TIntermTraverser *it)
+{
+ it->traverseFunctionPrototype(this);
+}
+
void TIntermAggregate::traverse(TIntermTraverser *it)
{
it->traverseAggregate(this);
@@ -63,7 +103,35 @@ void TIntermBranch::traverse(TIntermTraverser *it)
it->traverseBranch(this);
}
-void TIntermTraverser::pushParentBlock(TIntermAggregate *node)
+TIntermTraverser::TIntermTraverser(bool preVisit,
+ bool inVisit,
+ bool postVisit,
+ TSymbolTable *symbolTable)
+ : preVisit(preVisit),
+ inVisit(inVisit),
+ postVisit(postVisit),
+ mDepth(-1),
+ mMaxDepth(0),
+ mInGlobalScope(true),
+ mSymbolTable(symbolTable),
+ mTemporaryId(nullptr)
+{
+}
+
+TIntermTraverser::~TIntermTraverser()
+{
+}
+
+const TIntermBlock *TIntermTraverser::getParentBlock() const
+{
+ if (!mParentBlockStack.empty())
+ {
+ return mParentBlockStack.back().node;
+ }
+ return nullptr;
+}
+
+void TIntermTraverser::pushParentBlock(TIntermBlock *node)
{
mParentBlockStack.push_back(ParentBlock(node, 0));
}
@@ -89,23 +157,32 @@ void TIntermTraverser::insertStatementsInParentBlock(const TIntermSequence &inse
const TIntermSequence &insertionsAfter)
{
ASSERT(!mParentBlockStack.empty());
- NodeInsertMultipleEntry insert(mParentBlockStack.back().node, mParentBlockStack.back().pos,
- insertionsBefore, insertionsAfter);
+ ParentBlock &parentBlock = mParentBlockStack.back();
+ if (mPath.back() == parentBlock.node)
+ {
+ ASSERT(mParentBlockStack.size() >= 2u);
+ // The current node is a block node, so the parent block is not the topmost one in the block
+ // stack, but the one below that.
+ parentBlock = mParentBlockStack.at(mParentBlockStack.size() - 2u);
+ }
+ NodeInsertMultipleEntry insert(parentBlock.node, parentBlock.pos, insertionsBefore,
+ insertionsAfter);
mInsertions.push_back(insert);
}
-TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type, TQualifier qualifier)
+void TIntermTraverser::insertStatementInParentBlock(TIntermNode *statement)
{
- // Each traversal uses at most one temporary variable, so the index stays the same within a single traversal.
- TInfoSinkBase symbolNameOut;
- ASSERT(mTemporaryIndex != nullptr);
- symbolNameOut << "s" << (*mTemporaryIndex);
- TString symbolName = symbolNameOut.c_str();
+ TIntermSequence insertions;
+ insertions.push_back(statement);
+ insertStatementsInParentBlock(insertions);
+}
- TIntermSymbol *node = new TIntermSymbol(0, symbolName, type);
- node->setInternal(true);
- node->getTypePointer()->setQualifier(qualifier);
- return node;
+TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type, TQualifier qualifier)
+{
+ ASSERT(mTemporaryId != nullptr);
+ // nextTemporaryId() needs to be called when the code wants to start using another temporary
+ // symbol.
+ return CreateTempSymbolNode(*mTemporaryId, type, qualifier);
}
TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type)
@@ -113,27 +190,22 @@ TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type)
return createTempSymbol(type, EvqTemporary);
}
-TIntermAggregate *TIntermTraverser::createTempDeclaration(const TType &type)
+TIntermDeclaration *TIntermTraverser::createTempDeclaration(const TType &type)
{
- TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
- tempDeclaration->getSequence()->push_back(createTempSymbol(type));
+ ASSERT(mTemporaryId != nullptr);
+ TIntermDeclaration *tempDeclaration = new TIntermDeclaration();
+ tempDeclaration->appendDeclarator(CreateTempSymbolNode(*mTemporaryId, type, EvqTemporary));
return tempDeclaration;
}
-TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier)
+TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer,
+ TQualifier qualifier)
{
- ASSERT(initializer != nullptr);
- TIntermSymbol *tempSymbol = createTempSymbol(initializer->getType(), qualifier);
- TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
- TIntermBinary *tempInit = new TIntermBinary(EOpInitialize);
- tempInit->setLeft(tempSymbol);
- tempInit->setRight(initializer);
- tempInit->setType(tempSymbol->getType());
- tempDeclaration->getSequence()->push_back(tempInit);
- return tempDeclaration;
+ ASSERT(mTemporaryId != nullptr);
+ return CreateTempInitDeclarationNode(*mTemporaryId, initializer, qualifier);
}
-TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
+TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
{
return createTempInitDeclaration(initializer, EvqTemporary);
}
@@ -142,39 +214,38 @@ TIntermBinary *TIntermTraverser::createTempAssignment(TIntermTyped *rightNode)
{
ASSERT(rightNode != nullptr);
TIntermSymbol *tempSymbol = createTempSymbol(rightNode->getType());
- TIntermBinary *assignment = new TIntermBinary(EOpAssign);
- assignment->setLeft(tempSymbol);
- assignment->setRight(rightNode);
- assignment->setType(tempSymbol->getType());
+ TIntermBinary *assignment = new TIntermBinary(EOpAssign, tempSymbol, rightNode);
return assignment;
}
-void TIntermTraverser::useTemporaryIndex(unsigned int *temporaryIndex)
+void TIntermTraverser::nextTemporaryId()
{
- mTemporaryIndex = temporaryIndex;
-}
-
-void TIntermTraverser::nextTemporaryIndex()
-{
- ASSERT(mTemporaryIndex != nullptr);
- ++(*mTemporaryIndex);
+ ASSERT(mSymbolTable);
+ if (!mTemporaryId)
+ {
+ mTemporaryId = new TSymbolUniqueId(mSymbolTable);
+ return;
+ }
+ *mTemporaryId = TSymbolUniqueId(mSymbolTable);
}
-void TLValueTrackingTraverser::addToFunctionMap(const TName &name, TIntermSequence *paramSequence)
+void TLValueTrackingTraverser::addToFunctionMap(const TSymbolUniqueId &id,
+ TIntermSequence *paramSequence)
{
- mFunctionMap[name] = paramSequence;
+ mFunctionMap[id.get()] = paramSequence;
}
bool TLValueTrackingTraverser::isInFunctionMap(const TIntermAggregate *callNode) const
{
- ASSERT(callNode->getOp() == EOpFunctionCall);
- return (mFunctionMap.find(callNode->getNameObj()) != mFunctionMap.end());
+ ASSERT(callNode->getOp() == EOpCallFunctionInAST);
+ return (mFunctionMap.find(callNode->getFunctionSymbolInfo()->getId().get()) !=
+ mFunctionMap.end());
}
TIntermSequence *TLValueTrackingTraverser::getFunctionParameters(const TIntermAggregate *callNode)
{
ASSERT(isInFunctionMap(callNode));
- return mFunctionMap[callNode->getNameObj()];
+ return mFunctionMap[callNode->getFunctionSymbolInfo()->getId().get()];
}
void TLValueTrackingTraverser::setInFunctionCallOutParameter(bool inOutParameter)
@@ -203,19 +274,41 @@ bool TLValueTrackingTraverser::isInFunctionCallOutParameter() const
//
void TIntermTraverser::traverseSymbol(TIntermSymbol *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
visitSymbol(node);
}
void TIntermTraverser::traverseConstantUnion(TIntermConstantUnion *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
visitConstantUnion(node);
}
+void TIntermTraverser::traverseSwizzle(TIntermSwizzle *node)
+{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
+ bool visit = true;
+
+ if (preVisit)
+ visit = visitSwizzle(PreVisit, node);
+
+ if (visit)
+ {
+ node->getOperand()->traverse(this);
+ }
+
+ if (visit && postVisit)
+ visitSwizzle(PostVisit, node);
+}
+
//
// Traverse a binary node.
//
void TIntermTraverser::traverseBinary(TIntermBinary *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
//
@@ -229,8 +322,6 @@ void TIntermTraverser::traverseBinary(TIntermBinary *node)
//
if (visit)
{
- incrementDepth(node);
-
if (node->getLeft())
node->getLeft()->traverse(this);
@@ -239,8 +330,6 @@ void TIntermTraverser::traverseBinary(TIntermBinary *node)
if (visit && node->getRight())
node->getRight()->traverse(this);
-
- decrementDepth();
}
//
@@ -253,6 +342,8 @@ void TIntermTraverser::traverseBinary(TIntermBinary *node)
void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
//
@@ -266,8 +357,6 @@ void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node)
//
if (visit)
{
- incrementDepth(node);
-
// Some binary operations like indexing can be inside an expression which must be an
// l-value.
bool parentOperatorRequiresLValue = operatorRequiresLValue();
@@ -302,8 +391,6 @@ void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node)
setOperatorRequiresLValue(parentOperatorRequiresLValue);
setInFunctionCallOutParameter(parentInFunctionCallOutParameter);
-
- decrementDepth();
}
//
@@ -319,6 +406,8 @@ void TLValueTrackingTraverser::traverseBinary(TIntermBinary *node)
//
void TIntermTraverser::traverseUnary(TIntermUnary *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
@@ -326,11 +415,7 @@ void TIntermTraverser::traverseUnary(TIntermUnary *node)
if (visit)
{
- incrementDepth(node);
-
node->getOperand()->traverse(this);
-
- decrementDepth();
}
if (visit && postVisit)
@@ -339,6 +424,8 @@ void TIntermTraverser::traverseUnary(TIntermUnary *node)
void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
@@ -346,8 +433,6 @@ void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node)
if (visit)
{
- incrementDepth(node);
-
ASSERT(!operatorRequiresLValue());
switch (node->getOp())
{
@@ -364,153 +449,362 @@ void TLValueTrackingTraverser::traverseUnary(TIntermUnary *node)
node->getOperand()->traverse(this);
setOperatorRequiresLValue(false);
-
- decrementDepth();
}
if (visit && postVisit)
visitUnary(PostVisit, node);
}
-//
-// Traverse an aggregate node. Same comments in binary node apply here.
-//
-void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
+// Traverse a function definition node.
+void TIntermTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node)
{
- bool visit = true;
+ ScopedNodeInTraversalPath addToPath(this, node);
- TIntermSequence *sequence = node->getSequence();
+ bool visit = true;
if (preVisit)
- visit = visitAggregate(PreVisit, node);
+ visit = visitFunctionDefinition(PreVisit, node);
if (visit)
{
- incrementDepth(node);
+ mInGlobalScope = false;
+
+ node->getFunctionPrototype()->traverse(this);
+ if (inVisit)
+ visit = visitFunctionDefinition(InVisit, node);
+ node->getBody()->traverse(this);
+
+ mInGlobalScope = true;
+ }
- if (node->getOp() == EOpSequence)
- pushParentBlock(node);
+ if (visit && postVisit)
+ visitFunctionDefinition(PostVisit, node);
+}
+// Traverse a block node.
+void TIntermTraverser::traverseBlock(TIntermBlock *node)
+{
+ ScopedNodeInTraversalPath addToPath(this, node);
+ pushParentBlock(node);
+
+ bool visit = true;
+
+ TIntermSequence *sequence = node->getSequence();
+
+ if (preVisit)
+ visit = visitBlock(PreVisit, node);
+
+ if (visit)
+ {
for (auto *child : *sequence)
{
child->traverse(this);
if (visit && inVisit)
{
if (child != sequence->back())
- visit = visitAggregate(InVisit, node);
+ visit = visitBlock(InVisit, node);
}
- if (node->getOp() == EOpSequence)
- incrementParentBlockPos();
+ incrementParentBlockPos();
}
+ }
+
+ if (visit && postVisit)
+ visitBlock(PostVisit, node);
- if (node->getOp() == EOpSequence)
- popParentBlock();
+ popParentBlock();
+}
- decrementDepth();
+void TIntermTraverser::traverseInvariantDeclaration(TIntermInvariantDeclaration *node)
+{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
+ bool visit = true;
+
+ if (preVisit)
+ {
+ visit = visitInvariantDeclaration(PreVisit, node);
+ }
+
+ if (visit)
+ {
+ node->getSymbol()->traverse(this);
+ if (postVisit)
+ {
+ visitInvariantDeclaration(PostVisit, node);
+ }
+ }
+}
+
+// Traverse a declaration node.
+void TIntermTraverser::traverseDeclaration(TIntermDeclaration *node)
+{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
+ bool visit = true;
+
+ TIntermSequence *sequence = node->getSequence();
+
+ if (preVisit)
+ visit = visitDeclaration(PreVisit, node);
+
+ if (visit)
+ {
+ for (auto *child : *sequence)
+ {
+ child->traverse(this);
+ if (visit && inVisit)
+ {
+ if (child != sequence->back())
+ visit = visitDeclaration(InVisit, node);
+ }
+ }
}
if (visit && postVisit)
- visitAggregate(PostVisit, node);
+ visitDeclaration(PostVisit, node);
}
-void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
+void TIntermTraverser::traverseFunctionPrototype(TIntermFunctionPrototype *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
TIntermSequence *sequence = node->getSequence();
- switch (node->getOp())
+
+ if (preVisit)
+ visit = visitFunctionPrototype(PreVisit, node);
+
+ if (visit)
{
- case EOpFunction:
+ for (auto *child : *sequence)
{
- TIntermAggregate *params = sequence->front()->getAsAggregate();
- ASSERT(params != nullptr);
- ASSERT(params->getOp() == EOpParameters);
- addToFunctionMap(node->getNameObj(), params->getSequence());
- break;
+ child->traverse(this);
+ if (visit && inVisit)
+ {
+ if (child != sequence->back())
+ visit = visitFunctionPrototype(InVisit, node);
+ }
}
- case EOpPrototype:
- addToFunctionMap(node->getNameObj(), sequence);
- break;
- default:
- break;
}
+ if (visit && postVisit)
+ visitFunctionPrototype(PostVisit, node);
+}
+
+// Traverse an aggregate node. Same comments in binary node apply here.
+void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
+{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
+ bool visit = true;
+
+ TIntermSequence *sequence = node->getSequence();
+
if (preVisit)
visit = visitAggregate(PreVisit, node);
if (visit)
{
- bool inFunctionMap = false;
- if (node->getOp() == EOpFunctionCall)
+ for (auto *child : *sequence)
{
- inFunctionMap = isInFunctionMap(node);
- if (!inFunctionMap)
+ child->traverse(this);
+ if (visit && inVisit)
{
- // The function is not user-defined - it is likely built-in texture function.
- // Assume that those do not have out parameters.
- setInFunctionCallOutParameter(false);
+ if (child != sequence->back())
+ visit = visitAggregate(InVisit, node);
}
}
+ }
- incrementDepth(node);
+ if (visit && postVisit)
+ visitAggregate(PostVisit, node);
+}
- if (inFunctionMap)
+bool TIntermTraverser::CompareInsertion(const NodeInsertMultipleEntry &a,
+ const NodeInsertMultipleEntry &b)
+{
+ if (a.parent != b.parent)
+ {
+ return a.parent > b.parent;
+ }
+ return a.position > b.position;
+}
+
+void TIntermTraverser::updateTree()
+{
+ // Sort the insertions so that insertion position is decreasing. This way multiple insertions to
+ // the same parent node are handled correctly.
+ std::sort(mInsertions.begin(), mInsertions.end(), CompareInsertion);
+ for (size_t ii = 0; ii < mInsertions.size(); ++ii)
+ {
+ // We can't know here what the intended ordering of two insertions to the same position is,
+ // so it is not supported.
+ ASSERT(ii == 0 || mInsertions[ii].position != mInsertions[ii - 1].position ||
+ mInsertions[ii].parent != mInsertions[ii - 1].parent);
+ const NodeInsertMultipleEntry &insertion = mInsertions[ii];
+ ASSERT(insertion.parent);
+ if (!insertion.insertionsAfter.empty())
{
- TIntermSequence *params = getFunctionParameters(node);
- TIntermSequence::iterator paramIter = params->begin();
- for (auto *child : *sequence)
+ bool inserted = insertion.parent->insertChildNodes(insertion.position + 1,
+ insertion.insertionsAfter);
+ ASSERT(inserted);
+ }
+ if (!insertion.insertionsBefore.empty())
+ {
+ bool inserted =
+ insertion.parent->insertChildNodes(insertion.position, insertion.insertionsBefore);
+ ASSERT(inserted);
+ }
+ }
+ for (size_t ii = 0; ii < mReplacements.size(); ++ii)
+ {
+ const NodeUpdateEntry &replacement = mReplacements[ii];
+ ASSERT(replacement.parent);
+ bool replaced =
+ replacement.parent->replaceChildNode(replacement.original, replacement.replacement);
+ ASSERT(replaced);
+
+ if (!replacement.originalBecomesChildOfReplacement)
+ {
+ // In AST traversing, a parent is visited before its children.
+ // After we replace a node, if its immediate child is to
+ // be replaced, we need to make sure we don't update the replaced
+ // node; instead, we update the replacement node.
+ for (size_t jj = ii + 1; jj < mReplacements.size(); ++jj)
{
- ASSERT(paramIter != params->end());
- TQualifier qualifier = (*paramIter)->getAsTyped()->getQualifier();
- setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
+ NodeUpdateEntry &replacement2 = mReplacements[jj];
+ if (replacement2.parent == replacement.original)
+ replacement2.parent = replacement.replacement;
+ }
+ }
+ }
+ for (size_t ii = 0; ii < mMultiReplacements.size(); ++ii)
+ {
+ const NodeReplaceWithMultipleEntry &replacement = mMultiReplacements[ii];
+ ASSERT(replacement.parent);
+ bool replaced = replacement.parent->replaceChildNodeWithMultiple(replacement.original,
+ replacement.replacements);
+ ASSERT(replaced);
+ }
- child->traverse(this);
- if (visit && inVisit)
+ clearReplacementQueue();
+}
+
+void TIntermTraverser::clearReplacementQueue()
+{
+ mReplacements.clear();
+ mMultiReplacements.clear();
+ mInsertions.clear();
+}
+
+void TIntermTraverser::queueReplacement(TIntermNode *replacement, OriginalNode originalStatus)
+{
+ queueReplacementWithParent(getParentNode(), mPath.back(), replacement, originalStatus);
+}
+
+void TIntermTraverser::queueReplacementWithParent(TIntermNode *parent,
+ TIntermNode *original,
+ TIntermNode *replacement,
+ OriginalNode originalStatus)
+{
+ bool originalBecomesChild = (originalStatus == OriginalNode::BECOMES_CHILD);
+ mReplacements.push_back(NodeUpdateEntry(parent, original, replacement, originalBecomesChild));
+}
+
+TLValueTrackingTraverser::TLValueTrackingTraverser(bool preVisit,
+ bool inVisit,
+ bool postVisit,
+ TSymbolTable *symbolTable,
+ int shaderVersion)
+ : TIntermTraverser(preVisit, inVisit, postVisit, symbolTable),
+ mOperatorRequiresLValue(false),
+ mInFunctionCallOutParameter(false),
+ mShaderVersion(shaderVersion)
+{
+ ASSERT(symbolTable);
+}
+
+void TLValueTrackingTraverser::traverseFunctionPrototype(TIntermFunctionPrototype *node)
+{
+ TIntermSequence *sequence = node->getSequence();
+ addToFunctionMap(node->getFunctionSymbolInfo()->getId(), sequence);
+
+ TIntermTraverser::traverseFunctionPrototype(node);
+}
+
+void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
+{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
+ bool visit = true;
+
+ TIntermSequence *sequence = node->getSequence();
+
+ if (preVisit)
+ visit = visitAggregate(PreVisit, node);
+
+ if (visit)
+ {
+ if (node->getOp() == EOpCallFunctionInAST)
+ {
+ if (isInFunctionMap(node))
+ {
+ TIntermSequence *params = getFunctionParameters(node);
+ TIntermSequence::iterator paramIter = params->begin();
+ for (auto *child : *sequence)
{
- if (child != sequence->back())
- visit = visitAggregate(InVisit, node);
+ ASSERT(paramIter != params->end());
+ TQualifier qualifier = (*paramIter)->getAsTyped()->getQualifier();
+ setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
+
+ child->traverse(this);
+ if (visit && inVisit)
+ {
+ if (child != sequence->back())
+ visit = visitAggregate(InVisit, node);
+ }
+
+ ++paramIter;
+ }
+ }
+ else
+ {
+ // The node might not be in the function map in case we're in the middle of
+ // transforming the AST, and have inserted function call nodes without inserting the
+ // function definitions yet.
+ setInFunctionCallOutParameter(false);
+ for (auto *child : *sequence)
+ {
+ child->traverse(this);
+ if (visit && inVisit)
+ {
+ if (child != sequence->back())
+ visit = visitAggregate(InVisit, node);
+ }
}
-
- ++paramIter;
}
setInFunctionCallOutParameter(false);
}
else
{
- if (node->getOp() == EOpSequence)
- pushParentBlock(node);
-
// Find the built-in function corresponding to this op so that we can determine the
// in/out qualifiers of its parameters.
TFunction *builtInFunc = nullptr;
- TString opString = GetOperatorString(node->getOp());
- if (!node->isConstructor() && !opString.empty())
+ if (!node->isFunctionCall() && !node->isConstructor())
{
- // The return type doesn't affect the mangled name of the function, which is used
- // to look it up from the symbol table.
- TType dummyReturnType;
- TFunction call(&opString, &dummyReturnType, node->getOp());
- for (auto *child : *sequence)
- {
- TType *paramType = child->getAsTyped()->getTypePointer();
- TConstParameter p(paramType);
- call.addParameter(p);
- }
-
- TSymbol *sym = mSymbolTable.findBuiltIn(call.getMangledName(), mShaderVersion);
- if (sym != nullptr && sym->isFunction())
- {
- builtInFunc = static_cast<TFunction *>(sym);
- ASSERT(builtInFunc->getParamCount() == sequence->size());
- }
+ builtInFunc = static_cast<TFunction *>(
+ mSymbolTable->findBuiltIn(node->getSymbolTableMangledName(), mShaderVersion));
}
size_t paramIndex = 0;
for (auto *child : *sequence)
{
+ // This assumes that raw functions called with
+ // EOpCallInternalRawFunction don't have out parameters.
TQualifier qualifier = EvqIn;
if (builtInFunc != nullptr)
qualifier = builtInFunc->getParam(paramIndex).type->getQualifier();
@@ -523,19 +817,11 @@ void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
visit = visitAggregate(InVisit, node);
}
- if (node->getOp() == EOpSequence)
- incrementParentBlockPos();
-
++paramIndex;
}
setInFunctionCallOutParameter(false);
-
- if (node->getOp() == EOpSequence)
- popParentBlock();
}
-
- decrementDepth();
}
if (visit && postVisit)
@@ -543,28 +829,51 @@ void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
}
//
-// Traverse a selection node. Same comments in binary node apply here.
+// Traverse a ternary node. Same comments in binary node apply here.
//
-void TIntermTraverser::traverseSelection(TIntermSelection *node)
+void TIntermTraverser::traverseTernary(TIntermTernary *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
- visit = visitSelection(PreVisit, node);
+ visit = visitTernary(PreVisit, node);
+
+ if (visit)
+ {
+ node->getCondition()->traverse(this);
+ if (node->getTrueExpression())
+ node->getTrueExpression()->traverse(this);
+ if (node->getFalseExpression())
+ node->getFalseExpression()->traverse(this);
+ }
+
+ if (visit && postVisit)
+ visitTernary(PostVisit, node);
+}
+
+// Traverse an if-else node. Same comments in binary node apply here.
+void TIntermTraverser::traverseIfElse(TIntermIfElse *node)
+{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
+ bool visit = true;
+
+ if (preVisit)
+ visit = visitIfElse(PreVisit, node);
if (visit)
{
- incrementDepth(node);
node->getCondition()->traverse(this);
if (node->getTrueBlock())
node->getTrueBlock()->traverse(this);
if (node->getFalseBlock())
node->getFalseBlock()->traverse(this);
- decrementDepth();
}
if (visit && postVisit)
- visitSelection(PostVisit, node);
+ visitIfElse(PostVisit, node);
}
//
@@ -572,6 +881,8 @@ void TIntermTraverser::traverseSelection(TIntermSelection *node)
//
void TIntermTraverser::traverseSwitch(TIntermSwitch *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
@@ -579,13 +890,11 @@ void TIntermTraverser::traverseSwitch(TIntermSwitch *node)
if (visit)
{
- incrementDepth(node);
node->getInit()->traverse(this);
if (inVisit)
visit = visitSwitch(InVisit, node);
if (visit && node->getStatementList())
node->getStatementList()->traverse(this);
- decrementDepth();
}
if (visit && postVisit)
@@ -597,13 +906,17 @@ void TIntermTraverser::traverseSwitch(TIntermSwitch *node)
//
void TIntermTraverser::traverseCase(TIntermCase *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
visit = visitCase(PreVisit, node);
if (visit && node->getCondition())
+ {
node->getCondition()->traverse(this);
+ }
if (visit && postVisit)
visitCase(PostVisit, node);
@@ -614,6 +927,8 @@ void TIntermTraverser::traverseCase(TIntermCase *node)
//
void TIntermTraverser::traverseLoop(TIntermLoop *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
@@ -621,8 +936,6 @@ void TIntermTraverser::traverseLoop(TIntermLoop *node)
if (visit)
{
- incrementDepth(node);
-
if (node->getInit())
node->getInit()->traverse(this);
@@ -634,8 +947,6 @@ void TIntermTraverser::traverseLoop(TIntermLoop *node)
if (node->getExpression())
node->getExpression()->traverse(this);
-
- decrementDepth();
}
if (visit && postVisit)
@@ -647,6 +958,8 @@ void TIntermTraverser::traverseLoop(TIntermLoop *node)
//
void TIntermTraverser::traverseBranch(TIntermBranch *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
+
bool visit = true;
if (preVisit)
@@ -654,9 +967,7 @@ void TIntermTraverser::traverseBranch(TIntermBranch *node)
if (visit && node->getExpression())
{
- incrementDepth(node);
node->getExpression()->traverse(this);
- decrementDepth();
}
if (visit && postVisit)
@@ -665,5 +976,8 @@ void TIntermTraverser::traverseBranch(TIntermBranch *node)
void TIntermTraverser::traverseRaw(TIntermRaw *node)
{
+ ScopedNodeInTraversalPath addToPath(this, node);
visitRaw(node);
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.h b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.h
new file mode 100644
index 0000000000..f0300b586b
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.h
@@ -0,0 +1,355 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// IntermTraverse.h : base classes for AST traversers that walk the AST and
+// also have the ability to transform it by replacing nodes.
+
+#ifndef COMPILER_TRANSLATOR_INTERMTRAVERSE_H_
+#define COMPILER_TRANSLATOR_INTERMTRAVERSE_H_
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+class TSymbolTable;
+class TSymbolUniqueId;
+
+enum Visit
+{
+ PreVisit,
+ InVisit,
+ PostVisit
+};
+
+// For traversing the tree. User should derive from this class overriding the visit functions,
+// and then pass an object of the subclass to a traverse method of a node.
+//
+// The traverse*() functions may also be overridden to do other bookkeeping on the tree to provide
+// contextual information to the visit functions, such as whether the node is the target of an
+// assignment. This is complex to maintain and so should only be done in special cases.
+//
+// When using this, just fill in the methods for nodes you want visited.
+// Return false from a pre-visit to skip visiting that node's subtree.
+class TIntermTraverser : angle::NonCopyable
+{
+ public:
+ POOL_ALLOCATOR_NEW_DELETE();
+ TIntermTraverser(bool preVisit,
+ bool inVisit,
+ bool postVisit,
+ TSymbolTable *symbolTable = nullptr);
+ virtual ~TIntermTraverser();
+
+ virtual void visitSymbol(TIntermSymbol *node) {}
+ virtual void visitRaw(TIntermRaw *node) {}
+ virtual void visitConstantUnion(TIntermConstantUnion *node) {}
+ virtual bool visitSwizzle(Visit visit, TIntermSwizzle *node) { return true; }
+ virtual bool visitBinary(Visit visit, TIntermBinary *node) { return true; }
+ virtual bool visitUnary(Visit visit, TIntermUnary *node) { return true; }
+ virtual bool visitTernary(Visit visit, TIntermTernary *node) { return true; }
+ virtual bool visitIfElse(Visit visit, TIntermIfElse *node) { return true; }
+ virtual bool visitSwitch(Visit visit, TIntermSwitch *node) { return true; }
+ virtual bool visitCase(Visit visit, TIntermCase *node) { return true; }
+ virtual bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node)
+ {
+ return true;
+ }
+ virtual bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
+ {
+ return true;
+ }
+ virtual bool visitAggregate(Visit visit, TIntermAggregate *node) { return true; }
+ virtual bool visitBlock(Visit visit, TIntermBlock *node) { return true; }
+ virtual bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node)
+ {
+ return true;
+ }
+ virtual bool visitDeclaration(Visit visit, TIntermDeclaration *node) { return true; }
+ virtual bool visitLoop(Visit visit, TIntermLoop *node) { return true; }
+ virtual bool visitBranch(Visit visit, TIntermBranch *node) { return true; }
+
+ // The traverse functions contain logic for iterating over the children of the node
+ // and calling the visit functions in the appropriate places. They also track some
+ // context that may be used by the visit functions.
+ virtual void traverseSymbol(TIntermSymbol *node);
+ virtual void traverseRaw(TIntermRaw *node);
+ virtual void traverseConstantUnion(TIntermConstantUnion *node);
+ virtual void traverseSwizzle(TIntermSwizzle *node);
+ virtual void traverseBinary(TIntermBinary *node);
+ virtual void traverseUnary(TIntermUnary *node);
+ virtual void traverseTernary(TIntermTernary *node);
+ virtual void traverseIfElse(TIntermIfElse *node);
+ virtual void traverseSwitch(TIntermSwitch *node);
+ virtual void traverseCase(TIntermCase *node);
+ virtual void traverseFunctionPrototype(TIntermFunctionPrototype *node);
+ virtual void traverseFunctionDefinition(TIntermFunctionDefinition *node);
+ virtual void traverseAggregate(TIntermAggregate *node);
+ virtual void traverseBlock(TIntermBlock *node);
+ virtual void traverseInvariantDeclaration(TIntermInvariantDeclaration *node);
+ virtual void traverseDeclaration(TIntermDeclaration *node);
+ virtual void traverseLoop(TIntermLoop *node);
+ virtual void traverseBranch(TIntermBranch *node);
+
+ int getMaxDepth() const { return mMaxDepth; }
+
+ // If traversers need to replace nodes, they can add the replacements in
+ // mReplacements/mMultiReplacements during traversal and the user of the traverser should call
+ // this function after traversal to perform them.
+ void updateTree();
+
+ protected:
+ // Should only be called from traverse*() functions
+ void incrementDepth(TIntermNode *current)
+ {
+ mDepth++;
+ mMaxDepth = std::max(mMaxDepth, mDepth);
+ mPath.push_back(current);
+ }
+
+ // Should only be called from traverse*() functions
+ void decrementDepth()
+ {
+ mDepth--;
+ mPath.pop_back();
+ }
+
+ // RAII helper for incrementDepth/decrementDepth
+ class ScopedNodeInTraversalPath
+ {
+ public:
+ ScopedNodeInTraversalPath(TIntermTraverser *traverser, TIntermNode *current)
+ : mTraverser(traverser)
+ {
+ mTraverser->incrementDepth(current);
+ }
+ ~ScopedNodeInTraversalPath() { mTraverser->decrementDepth(); }
+
+ private:
+ TIntermTraverser *mTraverser;
+ };
+
+ TIntermNode *getParentNode() { return mPath.size() <= 1 ? nullptr : mPath[mPath.size() - 2u]; }
+
+ // Return the nth ancestor of the node being traversed. getAncestorNode(0) == getParentNode()
+ TIntermNode *getAncestorNode(unsigned int n)
+ {
+ if (mPath.size() > n + 1u)
+ {
+ return mPath[mPath.size() - n - 2u];
+ }
+ return nullptr;
+ }
+
+ const TIntermBlock *getParentBlock() const;
+
+ void pushParentBlock(TIntermBlock *node);
+ void incrementParentBlockPos();
+ void popParentBlock();
+
+ // To replace a single node with multiple nodes in the parent aggregate. May be used with blocks
+ // but also with other nodes like declarations.
+ struct NodeReplaceWithMultipleEntry
+ {
+ NodeReplaceWithMultipleEntry(TIntermAggregateBase *_parent,
+ TIntermNode *_original,
+ TIntermSequence _replacements)
+ : parent(_parent), original(_original), replacements(_replacements)
+ {
+ }
+
+ TIntermAggregateBase *parent;
+ TIntermNode *original;
+ TIntermSequence replacements;
+ };
+
+ // Helper to insert statements in the parent block of the node currently being traversed.
+ // The statements will be inserted before the node being traversed once updateTree is called.
+ // Should only be called during PreVisit or PostVisit if called from block nodes.
+ // Note that two insertions to the same position in the same block are not supported.
+ void insertStatementsInParentBlock(const TIntermSequence &insertions);
+
+ // Same as above, but supports simultaneous insertion of statements before and after the node
+ // currently being traversed.
+ void insertStatementsInParentBlock(const TIntermSequence &insertionsBefore,
+ const TIntermSequence &insertionsAfter);
+
+ // Helper to insert a single statement.
+ void insertStatementInParentBlock(TIntermNode *statement);
+
+ // Helper to create a temporary symbol node with the given qualifier.
+ TIntermSymbol *createTempSymbol(const TType &type, TQualifier qualifier);
+ // Helper to create a temporary symbol node.
+ TIntermSymbol *createTempSymbol(const TType &type);
+ // Create a node that declares but doesn't initialize a temporary symbol.
+ TIntermDeclaration *createTempDeclaration(const TType &type);
+ // Create a node that initializes the current temporary symbol with initializer. The symbol will
+ // have the given qualifier.
+ TIntermDeclaration *createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier);
+ // Create a node that initializes the current temporary symbol with initializer.
+ TIntermDeclaration *createTempInitDeclaration(TIntermTyped *initializer);
+ // Create a node that assigns rightNode to the current temporary symbol.
+ TIntermBinary *createTempAssignment(TIntermTyped *rightNode);
+ // Increment temporary symbol index.
+ void nextTemporaryId();
+
+ enum class OriginalNode
+ {
+ BECOMES_CHILD,
+ IS_DROPPED
+ };
+
+ void clearReplacementQueue();
+
+ // Replace the node currently being visited with replacement.
+ void queueReplacement(TIntermNode *replacement, OriginalNode originalStatus);
+ // Explicitly specify a node to replace with replacement.
+ void queueReplacementWithParent(TIntermNode *parent,
+ TIntermNode *original,
+ TIntermNode *replacement,
+ OriginalNode originalStatus);
+
+ const bool preVisit;
+ const bool inVisit;
+ const bool postVisit;
+
+ int mDepth;
+ int mMaxDepth;
+
+ bool mInGlobalScope;
+
+ // During traversing, save all the changes that need to happen into
+ // mReplacements/mMultiReplacements, then do them by calling updateTree().
+ // Multi replacements are processed after single replacements.
+ std::vector<NodeReplaceWithMultipleEntry> mMultiReplacements;
+
+ TSymbolTable *mSymbolTable;
+
+ private:
+ // To insert multiple nodes into the parent block.
+ struct NodeInsertMultipleEntry
+ {
+ NodeInsertMultipleEntry(TIntermBlock *_parent,
+ TIntermSequence::size_type _position,
+ TIntermSequence _insertionsBefore,
+ TIntermSequence _insertionsAfter)
+ : parent(_parent),
+ position(_position),
+ insertionsBefore(_insertionsBefore),
+ insertionsAfter(_insertionsAfter)
+ {
+ }
+
+ TIntermBlock *parent;
+ TIntermSequence::size_type position;
+ TIntermSequence insertionsBefore;
+ TIntermSequence insertionsAfter;
+ };
+
+ static bool CompareInsertion(const NodeInsertMultipleEntry &a,
+ const NodeInsertMultipleEntry &b);
+
+ // To replace a single node with another on the parent node
+ struct NodeUpdateEntry
+ {
+ NodeUpdateEntry(TIntermNode *_parent,
+ TIntermNode *_original,
+ TIntermNode *_replacement,
+ bool _originalBecomesChildOfReplacement)
+ : parent(_parent),
+ original(_original),
+ replacement(_replacement),
+ originalBecomesChildOfReplacement(_originalBecomesChildOfReplacement)
+ {
+ }
+
+ TIntermNode *parent;
+ TIntermNode *original;
+ TIntermNode *replacement;
+ bool originalBecomesChildOfReplacement;
+ };
+
+ struct ParentBlock
+ {
+ ParentBlock(TIntermBlock *nodeIn, TIntermSequence::size_type posIn)
+ : node(nodeIn), pos(posIn)
+ {
+ }
+
+ TIntermBlock *node;
+ TIntermSequence::size_type pos;
+ };
+
+ std::vector<NodeInsertMultipleEntry> mInsertions;
+ std::vector<NodeUpdateEntry> mReplacements;
+
+ // All the nodes from root to the current node during traversing.
+ TVector<TIntermNode *> mPath;
+
+ // All the code blocks from the root to the current node's parent during traversal.
+ std::vector<ParentBlock> mParentBlockStack;
+
+ TSymbolUniqueId *mTemporaryId;
+};
+
+// Traverser parent class that tracks where a node is a destination of a write operation and so is
+// required to be an l-value.
+class TLValueTrackingTraverser : public TIntermTraverser
+{
+ public:
+ TLValueTrackingTraverser(bool preVisit,
+ bool inVisit,
+ bool postVisit,
+ TSymbolTable *symbolTable,
+ int shaderVersion);
+ virtual ~TLValueTrackingTraverser() {}
+
+ void traverseBinary(TIntermBinary *node) final;
+ void traverseUnary(TIntermUnary *node) final;
+ void traverseFunctionPrototype(TIntermFunctionPrototype *node) final;
+ void traverseAggregate(TIntermAggregate *node) final;
+
+ protected:
+ bool isLValueRequiredHere() const
+ {
+ return mOperatorRequiresLValue || mInFunctionCallOutParameter;
+ }
+
+ private:
+ // Track whether an l-value is required in the node that is currently being traversed by the
+ // surrounding operator.
+ // Use isLValueRequiredHere to check all conditions which require an l-value.
+ void setOperatorRequiresLValue(bool lValueRequired)
+ {
+ mOperatorRequiresLValue = lValueRequired;
+ }
+ bool operatorRequiresLValue() const { return mOperatorRequiresLValue; }
+
+ // Add a function encountered during traversal to the function map.
+ void addToFunctionMap(const TSymbolUniqueId &id, TIntermSequence *paramSequence);
+
+ // Return true if the prototype or definition of the function being called has been encountered
+ // during traversal.
+ bool isInFunctionMap(const TIntermAggregate *callNode) const;
+
+ // Return the parameters sequence from the function definition or prototype.
+ TIntermSequence *getFunctionParameters(const TIntermAggregate *callNode);
+
+ // Track whether an l-value is required inside a function call.
+ void setInFunctionCallOutParameter(bool inOutParameter);
+ bool isInFunctionCallOutParameter() const;
+
+ bool mOperatorRequiresLValue;
+ bool mInFunctionCallOutParameter;
+
+ // Map from function symbol id values to their parameter sequences
+ TMap<int, TIntermSequence *> mFunctionMap;
+
+ const int mShaderVersion;
+};
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_INTERMTRAVERSE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp
deleted file mode 100644
index 0adb7212b7..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp
+++ /dev/null
@@ -1,508 +0,0 @@
-//
-// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-//
-// Build the intermediate representation.
-//
-
-#include <float.h>
-#include <limits.h>
-#include <algorithm>
-
-#include "compiler/translator/Intermediate.h"
-#include "compiler/translator/SymbolTable.h"
-
-////////////////////////////////////////////////////////////////////////////
-//
-// First set of functions are to help build the intermediate representation.
-// These functions are not member functions of the nodes.
-// They are called from parser productions.
-//
-/////////////////////////////////////////////////////////////////////////////
-
-//
-// Add a terminal node for an identifier in an expression.
-//
-// Returns the added node.
-//
-TIntermSymbol *TIntermediate::addSymbol(
- int id, const TString &name, const TType &type, const TSourceLoc &line)
-{
- TIntermSymbol *node = new TIntermSymbol(id, name, type);
- node->setLine(line);
-
- return node;
-}
-
-//
-// Connect two nodes with a new parent that does a binary operation on the nodes.
-//
-// Returns the added node.
-//
-TIntermTyped *TIntermediate::addBinaryMath(
- TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
-{
- //
- // Need a new node holding things together then. Make
- // one and promote it to the right type.
- //
- TIntermBinary *node = new TIntermBinary(op);
- node->setLine(line);
-
- node->setLeft(left);
- node->setRight(right);
- if (!node->promote(mInfoSink))
- return NULL;
-
- // See if we can fold constants.
- TIntermTyped *foldedNode = node->fold(mInfoSink);
- if (foldedNode)
- return foldedNode;
-
- return node;
-}
-
-//
-// Connect two nodes through an assignment.
-//
-// Returns the added node.
-//
-TIntermTyped *TIntermediate::addAssign(
- TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
-{
- if (left->getType().getStruct() || right->getType().getStruct())
- {
- if (left->getType() != right->getType())
- {
- return NULL;
- }
- }
-
- TIntermBinary *node = new TIntermBinary(op);
- node->setLine(line);
-
- node->setLeft(left);
- node->setRight(right);
- if (!node->promote(mInfoSink))
- return NULL;
-
- return node;
-}
-
-//
-// Connect two nodes through an index operator, where the left node is the base
-// of an array or struct, and the right node is a direct or indirect offset.
-//
-// Returns the added node.
-// The caller should set the type of the returned node.
-//
-TIntermTyped *TIntermediate::addIndex(
- TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &line)
-{
- TIntermBinary *node = new TIntermBinary(op);
- node->setLine(line);
- node->setLeft(base);
- node->setRight(index);
-
- // caller should set the type
-
- return node;
-}
-
-//
-// Add one node as the parent of another that it operates on.
-//
-// Returns the added node.
-//
-TIntermTyped *TIntermediate::addUnaryMath(
- TOperator op, TIntermTyped *child, const TSourceLoc &line, const TType *funcReturnType)
-{
- //
- // Make a new node for the operator.
- //
- TIntermUnary *node = new TIntermUnary(op);
- node->setLine(line);
- node->setOperand(child);
- node->promote(funcReturnType);
-
- TIntermTyped *foldedNode = node->fold(mInfoSink);
- if (foldedNode)
- return foldedNode;
-
- return node;
-}
-
-//
-// This is the safe way to change the operator on an aggregate, as it
-// does lots of error checking and fixing. Especially for establishing
-// a function call's operation on it's set of parameters. Sequences
-// of instructions are also aggregates, but they just direnctly set
-// their operator to EOpSequence.
-//
-// Returns an aggregate node, which could be the one passed in if
-// it was already an aggregate but no operator was set.
-//
-TIntermAggregate *TIntermediate::setAggregateOperator(
- TIntermNode *node, TOperator op, const TSourceLoc &line)
-{
- TIntermAggregate *aggNode;
-
- //
- // Make sure we have an aggregate. If not turn it into one.
- //
- if (node)
- {
- aggNode = node->getAsAggregate();
- if (aggNode == NULL || aggNode->getOp() != EOpNull)
- {
- //
- // Make an aggregate containing this node.
- //
- aggNode = new TIntermAggregate();
- aggNode->getSequence()->push_back(node);
- }
- }
- else
- {
- aggNode = new TIntermAggregate();
- }
-
- //
- // Set the operator.
- //
- aggNode->setOp(op);
- aggNode->setLine(line);
-
- return aggNode;
-}
-
-//
-// Safe way to combine two nodes into an aggregate. Works with null pointers,
-// a node that's not a aggregate yet, etc.
-//
-// Returns the resulting aggregate, unless 0 was passed in for
-// both existing nodes.
-//
-TIntermAggregate *TIntermediate::growAggregate(
- TIntermNode *left, TIntermNode *right, const TSourceLoc &line)
-{
- if (left == NULL && right == NULL)
- return NULL;
-
- TIntermAggregate *aggNode = NULL;
- if (left)
- aggNode = left->getAsAggregate();
- if (!aggNode || aggNode->getOp() != EOpNull)
- {
- aggNode = new TIntermAggregate;
- if (left)
- aggNode->getSequence()->push_back(left);
- }
-
- if (right)
- aggNode->getSequence()->push_back(right);
-
- aggNode->setLine(line);
-
- return aggNode;
-}
-
-//
-// Turn an existing node into an aggregate.
-//
-// Returns an aggregate, unless NULL was passed in for the existing node.
-//
-TIntermAggregate *TIntermediate::makeAggregate(
- TIntermNode *node, const TSourceLoc &line)
-{
- if (node == NULL)
- return NULL;
-
- TIntermAggregate *aggNode = new TIntermAggregate;
- aggNode->getSequence()->push_back(node);
-
- aggNode->setLine(line);
-
- return aggNode;
-}
-
-// If the input node is nullptr, return nullptr.
-// If the input node is a sequence (block) node, return it.
-// If the input node is not a sequence node, put it inside a sequence node and return that.
-TIntermAggregate *TIntermediate::ensureSequence(TIntermNode *node)
-{
- if (node == nullptr)
- return nullptr;
- TIntermAggregate *aggNode = node->getAsAggregate();
- if (aggNode != nullptr && aggNode->getOp() == EOpSequence)
- return aggNode;
-
- aggNode = makeAggregate(node, node->getLine());
- aggNode->setOp(EOpSequence);
- return aggNode;
-}
-
-//
-// For "if" test nodes. There are three children; a condition,
-// a true path, and a false path. The two paths are in the
-// nodePair.
-//
-// Returns the selection node created.
-//
-TIntermNode *TIntermediate::addSelection(
- TIntermTyped *cond, TIntermNodePair nodePair, const TSourceLoc &line)
-{
- //
- // For compile time constant selections, prune the code and
- // test now.
- //
-
- if (cond->getAsConstantUnion())
- {
- if (cond->getAsConstantUnion()->getBConst(0) == true)
- {
- return nodePair.node1 ? setAggregateOperator(
- nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
- }
- else
- {
- return nodePair.node2 ? setAggregateOperator(
- nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
- }
- }
-
- TIntermSelection *node = new TIntermSelection(
- cond, ensureSequence(nodePair.node1), ensureSequence(nodePair.node2));
- node->setLine(line);
-
- return node;
-}
-
-TIntermTyped *TIntermediate::addComma(TIntermTyped *left,
- TIntermTyped *right,
- const TSourceLoc &line,
- int shaderVersion)
-{
- TQualifier resultQualifier = EvqConst;
- // ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression.
- if (shaderVersion >= 300 || left->getQualifier() != EvqConst ||
- right->getQualifier() != EvqConst)
- {
- resultQualifier = EvqTemporary;
- }
-
- TIntermTyped *commaNode = nullptr;
- if (!left->hasSideEffects())
- {
- commaNode = right;
- }
- else
- {
- commaNode = growAggregate(left, right, line);
- commaNode->getAsAggregate()->setOp(EOpComma);
- commaNode->setType(right->getType());
- }
- commaNode->getTypePointer()->setQualifier(resultQualifier);
- return commaNode;
-}
-
-//
-// For "?:" test nodes. There are three children; a condition,
-// a true path, and a false path. The two paths are specified
-// as separate parameters.
-//
-// Returns the selection node created, or one of trueBlock and falseBlock if the expression could be folded.
-//
-TIntermTyped *TIntermediate::addSelection(TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock,
- const TSourceLoc &line)
-{
- TQualifier resultQualifier = EvqTemporary;
- if (cond->getQualifier() == EvqConst && trueBlock->getQualifier() == EvqConst &&
- falseBlock->getQualifier() == EvqConst)
- {
- resultQualifier = EvqConst;
- }
- // Note that the node resulting from here can be a constant union without being qualified as
- // constant.
- if (cond->getAsConstantUnion())
- {
- if (cond->getAsConstantUnion()->getBConst(0))
- {
- trueBlock->getTypePointer()->setQualifier(resultQualifier);
- return trueBlock;
- }
- else
- {
- falseBlock->getTypePointer()->setQualifier(resultQualifier);
- return falseBlock;
- }
- }
-
- //
- // Make a selection node.
- //
- TIntermSelection *node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
- node->getTypePointer()->setQualifier(resultQualifier);
- node->setLine(line);
-
- return node;
-}
-
-TIntermSwitch *TIntermediate::addSwitch(
- TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line)
-{
- TIntermSwitch *node = new TIntermSwitch(init, statementList);
- node->setLine(line);
-
- return node;
-}
-
-TIntermCase *TIntermediate::addCase(
- TIntermTyped *condition, const TSourceLoc &line)
-{
- TIntermCase *node = new TIntermCase(condition);
- node->setLine(line);
-
- return node;
-}
-
-//
-// Constant terminal nodes. Has a union that contains bool, float or int constants
-//
-// Returns the constant union node created.
-//
-
-TIntermConstantUnion *TIntermediate::addConstantUnion(const TConstantUnion *constantUnion,
- const TType &type,
- const TSourceLoc &line)
-{
- TIntermConstantUnion *node = new TIntermConstantUnion(constantUnion, type);
- node->setLine(line);
-
- return node;
-}
-
-TIntermTyped *TIntermediate::addSwizzle(
- TVectorFields &fields, const TSourceLoc &line)
-{
-
- TIntermAggregate *node = new TIntermAggregate(EOpSequence);
-
- node->setLine(line);
- TIntermConstantUnion *constIntNode;
- TIntermSequence *sequenceVector = node->getSequence();
- TConstantUnion *unionArray;
-
- for (int i = 0; i < fields.num; i++)
- {
- unionArray = new TConstantUnion[1];
- unionArray->setIConst(fields.offsets[i]);
- constIntNode = addConstantUnion(
- unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
- sequenceVector->push_back(constIntNode);
- }
-
- return node;
-}
-
-//
-// Create loop nodes.
-//
-TIntermNode *TIntermediate::addLoop(
- TLoopType type, TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr,
- TIntermNode *body, const TSourceLoc &line)
-{
- TIntermNode *node = new TIntermLoop(type, init, cond, expr, ensureSequence(body));
- node->setLine(line);
-
- return node;
-}
-
-//
-// Add branches.
-//
-TIntermBranch* TIntermediate::addBranch(
- TOperator branchOp, const TSourceLoc &line)
-{
- return addBranch(branchOp, 0, line);
-}
-
-TIntermBranch* TIntermediate::addBranch(
- TOperator branchOp, TIntermTyped *expression, const TSourceLoc &line)
-{
- TIntermBranch *node = new TIntermBranch(branchOp, expression);
- node->setLine(line);
-
- return node;
-}
-
-//
-// This is to be executed once the final root is put on top by the parsing
-// process.
-//
-TIntermAggregate *TIntermediate::postProcess(TIntermNode *root)
-{
- if (root == nullptr)
- return nullptr;
-
- //
- // Finish off the top level sequence, if any
- //
- TIntermAggregate *aggRoot = root->getAsAggregate();
- if (aggRoot != nullptr && aggRoot->getOp() == EOpNull)
- {
- aggRoot->setOp(EOpSequence);
- }
- else if (aggRoot == nullptr || aggRoot->getOp() != EOpSequence)
- {
- aggRoot = new TIntermAggregate(EOpSequence);
- aggRoot->setLine(root->getLine());
- aggRoot->getSequence()->push_back(root);
- }
-
- return aggRoot;
-}
-
-TIntermTyped *TIntermediate::foldAggregateBuiltIn(TIntermAggregate *aggregate)
-{
- switch (aggregate->getOp())
- {
- case EOpAtan:
- case EOpPow:
- case EOpMod:
- case EOpMin:
- case EOpMax:
- case EOpClamp:
- case EOpMix:
- case EOpStep:
- case EOpSmoothStep:
- case EOpMul:
- case EOpOuterProduct:
- case EOpLessThan:
- case EOpLessThanEqual:
- case EOpGreaterThan:
- case EOpGreaterThanEqual:
- case EOpVectorEqual:
- case EOpVectorNotEqual:
- case EOpDistance:
- case EOpDot:
- case EOpCross:
- case EOpFaceForward:
- case EOpReflect:
- case EOpRefract:
- return aggregate->fold(mInfoSink);
- default:
- // TODO: Add support for folding array constructors
- if (aggregate->isConstructor() && !aggregate->isArray())
- {
- return aggregate->fold(mInfoSink);
- }
- // Constant folding not supported for the built-in.
- return nullptr;
- }
-
- return nullptr;
-}
diff --git a/src/3rdparty/angle/src/compiler/translator/Intermediate.h b/src/3rdparty/angle/src/compiler/translator/Intermediate.h
deleted file mode 100644
index f723fc7648..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/Intermediate.h
+++ /dev/null
@@ -1,75 +0,0 @@
-//
-// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_TRANSLATOR_INTERMEDIATE_H_
-#define COMPILER_TRANSLATOR_INTERMEDIATE_H_
-
-#include "compiler/translator/IntermNode.h"
-
-struct TVectorFields
-{
- int offsets[4];
- int num;
-};
-
-//
-// Set of helper functions to help parse and build the tree.
-//
-class TInfoSink;
-class TIntermediate
-{
- public:
- POOL_ALLOCATOR_NEW_DELETE();
- TIntermediate(TInfoSink &i)
- : mInfoSink(i) { }
-
- TIntermSymbol *addSymbol(
- int id, const TString &, const TType &, const TSourceLoc &);
- TIntermTyped *addBinaryMath(
- TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &);
- TIntermTyped *addAssign(
- TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &);
- TIntermTyped *addIndex(
- TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &);
- TIntermTyped *addUnaryMath(
- TOperator op, TIntermTyped *child, const TSourceLoc &line, const TType *funcReturnType);
- TIntermAggregate *growAggregate(
- TIntermNode *left, TIntermNode *right, const TSourceLoc &);
- TIntermAggregate *makeAggregate(TIntermNode *node, const TSourceLoc &);
- TIntermAggregate *ensureSequence(TIntermNode *node);
- TIntermAggregate *setAggregateOperator(TIntermNode *, TOperator, const TSourceLoc &);
- TIntermNode *addSelection(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &);
- TIntermTyped *addSelection(TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock,
- const TSourceLoc &line);
- TIntermSwitch *addSwitch(
- TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line);
- TIntermCase *addCase(
- TIntermTyped *condition, const TSourceLoc &line);
- TIntermTyped *addComma(TIntermTyped *left,
- TIntermTyped *right,
- const TSourceLoc &line,
- int shaderVersion);
- TIntermConstantUnion *addConstantUnion(const TConstantUnion *constantUnion,
- const TType &type,
- const TSourceLoc &line);
- TIntermNode *addLoop(TLoopType, TIntermNode *, TIntermTyped *, TIntermTyped *,
- TIntermNode *, const TSourceLoc &);
- TIntermBranch *addBranch(TOperator, const TSourceLoc &);
- TIntermBranch *addBranch(TOperator, TIntermTyped *, const TSourceLoc &);
- TIntermTyped *addSwizzle(TVectorFields &, const TSourceLoc &);
- TIntermAggregate *postProcess(TIntermNode *root);
-
- static void outputTree(TIntermNode *, TInfoSinkBase &);
-
- TIntermTyped *foldAggregateBuiltIn(TIntermAggregate *aggregate);
-
- private:
- void operator=(TIntermediate &); // prevent assignments
-
- TInfoSink & mInfoSink;
-};
-
-#endif // COMPILER_TRANSLATOR_INTERMEDIATE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.cpp b/src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.cpp
new file mode 100644
index 0000000000..aaad4f3c68
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.cpp
@@ -0,0 +1,51 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/IsASTDepthBelowLimit.h"
+
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
+
+namespace
+{
+
+// Traverse the tree and compute max depth. Takes a maximum depth limit to prevent stack overflow.
+class MaxDepthTraverser : public TIntermTraverser
+{
+ public:
+ MaxDepthTraverser(int depthLimit) : TIntermTraverser(true, true, false), mDepthLimit(depthLimit)
+ {
+ }
+
+ bool visitBinary(Visit, TIntermBinary *) override { return depthCheck(); }
+ bool visitUnary(Visit, TIntermUnary *) override { return depthCheck(); }
+ bool visitTernary(Visit, TIntermTernary *) override { return depthCheck(); }
+ bool visitSwizzle(Visit, TIntermSwizzle *) override { return depthCheck(); }
+ bool visitIfElse(Visit, TIntermIfElse *) override { return depthCheck(); }
+ bool visitAggregate(Visit, TIntermAggregate *) override { return depthCheck(); }
+ bool visitBlock(Visit, TIntermBlock *) override { return depthCheck(); }
+ bool visitLoop(Visit, TIntermLoop *) override { return depthCheck(); }
+ bool visitBranch(Visit, TIntermBranch *) override { return depthCheck(); }
+
+ protected:
+ bool depthCheck() const { return mMaxDepth < mDepthLimit; }
+
+ int mDepthLimit;
+};
+
+} // anonymous namespace
+
+bool IsASTDepthBelowLimit(TIntermNode *root, int maxDepth)
+{
+ MaxDepthTraverser traverser(maxDepth + 1);
+ root->traverse(&traverser);
+
+ return traverser.getMaxDepth() <= maxDepth;
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.h b/src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.h
new file mode 100644
index 0000000000..ef2f02c974
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/IsASTDepthBelowLimit.h
@@ -0,0 +1,20 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// IsASTDepthBelowLimit: Check whether AST depth is below a specific limit.
+
+#ifndef COMPILER_TRANSLATOR_ISASTDEPTHBELOWLIMIT_H_
+#define COMPILER_TRANSLATOR_ISASTDEPTHBELOWLIMIT_H_
+
+namespace sh
+{
+
+class TIntermNode;
+
+bool IsASTDepthBelowLimit(TIntermNode *root, int maxDepth);
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_ISASTDEPTHBELOWLIMIT_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/LoopInfo.cpp b/src/3rdparty/angle/src/compiler/translator/LoopInfo.cpp
deleted file mode 100644
index d931a18a23..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/LoopInfo.cpp
+++ /dev/null
@@ -1,211 +0,0 @@
-//
-// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/translator/LoopInfo.h"
-
-namespace
-{
-
-int EvaluateIntConstant(TIntermConstantUnion *node)
-{
- ASSERT(node && node->getUnionArrayPointer());
- return node->getIConst(0);
-}
-
-int GetLoopIntIncrement(TIntermLoop *node)
-{
- TIntermNode *expr = node->getExpression();
- // for expression has one of the following forms:
- // loop_index++
- // loop_index--
- // loop_index += constant_expression
- // loop_index -= constant_expression
- // ++loop_index
- // --loop_index
- // The last two forms are not specified in the spec, but I am assuming
- // its an oversight.
- TIntermUnary *unOp = expr->getAsUnaryNode();
- TIntermBinary *binOp = unOp ? NULL : expr->getAsBinaryNode();
-
- TOperator op = EOpNull;
- TIntermConstantUnion *incrementNode = NULL;
- if (unOp)
- {
- op = unOp->getOp();
- }
- else if (binOp)
- {
- op = binOp->getOp();
- ASSERT(binOp->getRight());
- incrementNode = binOp->getRight()->getAsConstantUnion();
- ASSERT(incrementNode);
- }
-
- int increment = 0;
- // The operator is one of: ++ -- += -=.
- switch (op)
- {
- case EOpPostIncrement:
- case EOpPreIncrement:
- ASSERT(unOp && !binOp);
- increment = 1;
- break;
- case EOpPostDecrement:
- case EOpPreDecrement:
- ASSERT(unOp && !binOp);
- increment = -1;
- break;
- case EOpAddAssign:
- ASSERT(!unOp && binOp);
- increment = EvaluateIntConstant(incrementNode);
- break;
- case EOpSubAssign:
- ASSERT(!unOp && binOp);
- increment = - EvaluateIntConstant(incrementNode);
- break;
- default:
- UNREACHABLE();
- }
-
- return increment;
-}
-
-} // namespace anonymous
-
-TLoopIndexInfo::TLoopIndexInfo()
- : mId(-1),
- mType(EbtVoid),
- mInitValue(0),
- mStopValue(0),
- mIncrementValue(0),
- mOp(EOpNull),
- mCurrentValue(0)
-{
-}
-
-void TLoopIndexInfo::fillInfo(TIntermLoop *node)
-{
- if (node == NULL)
- return;
-
- // Here we assume all the operations are valid, because the loop node is
- // already validated in ValidateLimitations.
- TIntermSequence *declSeq =
- node->getInit()->getAsAggregate()->getSequence();
- TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode();
- TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode();
-
- mId = symbol->getId();
- mType = symbol->getBasicType();
-
- if (mType == EbtInt)
- {
- TIntermConstantUnion* initNode = declInit->getRight()->getAsConstantUnion();
- mInitValue = EvaluateIntConstant(initNode);
- mCurrentValue = mInitValue;
- mIncrementValue = GetLoopIntIncrement(node);
-
- TIntermBinary* binOp = node->getCondition()->getAsBinaryNode();
- mStopValue = EvaluateIntConstant(
- binOp->getRight()->getAsConstantUnion());
- mOp = binOp->getOp();
- }
-}
-
-bool TLoopIndexInfo::satisfiesLoopCondition() const
-{
- // Relational operator is one of: > >= < <= == or !=.
- switch (mOp)
- {
- case EOpEqual:
- return (mCurrentValue == mStopValue);
- case EOpNotEqual:
- return (mCurrentValue != mStopValue);
- case EOpLessThan:
- return (mCurrentValue < mStopValue);
- case EOpGreaterThan:
- return (mCurrentValue > mStopValue);
- case EOpLessThanEqual:
- return (mCurrentValue <= mStopValue);
- case EOpGreaterThanEqual:
- return (mCurrentValue >= mStopValue);
- default:
- UNREACHABLE();
- return false;
- }
-}
-
-TLoopInfo::TLoopInfo()
- : loop(NULL)
-{
-}
-
-TLoopInfo::TLoopInfo(TIntermLoop *node)
- : loop(node)
-{
- index.fillInfo(node);
-}
-
-TIntermLoop *TLoopStack::findLoop(TIntermSymbol *symbol)
-{
- if (!symbol)
- return NULL;
- for (iterator iter = begin(); iter != end(); ++iter)
- {
- if (iter->index.getId() == symbol->getId())
- return iter->loop;
- }
- return NULL;
-}
-
-TLoopIndexInfo *TLoopStack::getIndexInfo(TIntermSymbol *symbol)
-{
- if (!symbol)
- return NULL;
- for (iterator iter = begin(); iter != end(); ++iter)
- {
- if (iter->index.getId() == symbol->getId())
- return &(iter->index);
- }
- return NULL;
-}
-
-void TLoopStack::step()
-{
- ASSERT(!empty());
- rbegin()->index.step();
-}
-
-bool TLoopStack::satisfiesLoopCondition()
-{
- ASSERT(!empty());
- return rbegin()->index.satisfiesLoopCondition();
-}
-
-bool TLoopStack::needsToReplaceSymbolWithValue(TIntermSymbol *symbol)
-{
- TIntermLoop *loop = findLoop(symbol);
- return loop && loop->getUnrollFlag();
-}
-
-int TLoopStack::getLoopIndexValue(TIntermSymbol *symbol)
-{
- TLoopIndexInfo *info = getIndexInfo(symbol);
- ASSERT(info);
- return info->getCurrentValue();
-}
-
-void TLoopStack::push(TIntermLoop *loop)
-{
- TLoopInfo info(loop);
- push_back(info);
-}
-
-void TLoopStack::pop()
-{
- pop_back();
-}
-
diff --git a/src/3rdparty/angle/src/compiler/translator/LoopInfo.h b/src/3rdparty/angle/src/compiler/translator/LoopInfo.h
deleted file mode 100644
index ec73fd0fa5..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/LoopInfo.h
+++ /dev/null
@@ -1,80 +0,0 @@
-//
-// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_TRANSLATOR_LOOPINFO_H_
-#define COMPILER_TRANSLATOR_LOOPINFO_H_
-
-#include "compiler/translator/IntermNode.h"
-
-class TLoopIndexInfo
-{
- public:
- TLoopIndexInfo();
-
- // If type is EbtInt, fill all fields of the structure with info
- // extracted from a loop node.
- // If type is not EbtInt, only fill id and type.
- void fillInfo(TIntermLoop *node);
-
- int getId() const { return mId; }
- void setId(int id) { mId = id; }
- TBasicType getType() const { return mType; }
- void setType(TBasicType type) { mType = type; }
- int getCurrentValue() const { return mCurrentValue; }
-
- void step() { mCurrentValue += mIncrementValue; }
-
- // Check if the current value satisfies the loop condition.
- bool satisfiesLoopCondition() const;
-
- private:
- int mId;
- TBasicType mType; // Either EbtInt or EbtFloat
-
- // Below fields are only valid if the index's type is int.
- int mInitValue;
- int mStopValue;
- int mIncrementValue;
- TOperator mOp;
- int mCurrentValue;
-};
-
-struct TLoopInfo
-{
- TLoopIndexInfo index;
- TIntermLoop *loop;
-
- TLoopInfo();
- TLoopInfo(TIntermLoop *node);
-};
-
-class TLoopStack : public TVector<TLoopInfo>
-{
- public:
- // Search loop stack for a loop whose index matches the input symbol.
- TIntermLoop *findLoop(TIntermSymbol *symbol);
-
- // Find the loop index info in the loop stack by the input symbol.
- TLoopIndexInfo *getIndexInfo(TIntermSymbol *symbol);
-
- // Update the currentValue for the next loop iteration.
- void step();
-
- // Return false if loop condition is no longer satisfied.
- bool satisfiesLoopCondition();
-
- // Check if the symbol is the index of a loop that's unrolled.
- bool needsToReplaceSymbolWithValue(TIntermSymbol *symbol);
-
- // Return the current value of a given loop index symbol.
- int getLoopIndexValue(TIntermSymbol *symbol);
-
- void push(TIntermLoop *info);
- void pop();
-};
-
-#endif // COMPILER_TRANSLATOR_LOOPINFO_H_
-
diff --git a/src/3rdparty/angle/src/compiler/translator/MMap.h b/src/3rdparty/angle/src/compiler/translator/MMap.h
deleted file mode 100644
index fca843992b..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/MMap.h
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_TRANSLATOR_MMAP_H_
-#define COMPILER_TRANSLATOR_MMAP_H_
-
-//
-// Encapsulate memory mapped files
-//
-
-class TMMap {
-public:
- TMMap(const char* fileName) :
- fSize(-1), // -1 is the error value returned by GetFileSize()
- fp(NULL),
- fBuff(0) // 0 is the error value returned by MapViewOfFile()
- {
- if ((fp = fopen(fileName, "r")) == NULL)
- return;
- char c = getc(fp);
- fSize = 0;
- while (c != EOF) {
- fSize++;
- c = getc(fp);
- }
- if (c == EOF)
- fSize++;
- rewind(fp);
- fBuff = (char*)malloc(sizeof(char) * fSize);
- int count = 0;
- c = getc(fp);
- while (c != EOF) {
- fBuff[count++] = c;
- c = getc(fp);
- }
- fBuff[count++] = c;
- }
-
- char* getData() { return fBuff; }
- int getSize() { return fSize; }
-
- ~TMMap() {
- if (fp != NULL)
- fclose(fp);
- }
-
-private:
- int fSize; // size of file to map in
- FILE *fp;
- char* fBuff; // the actual data;
-};
-
-#endif // COMPILER_TRANSLATOR_MMAP_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/NodeSearch.h b/src/3rdparty/angle/src/compiler/translator/NodeSearch.h
index b13b1baabb..af86b8bde4 100644
--- a/src/3rdparty/angle/src/compiler/translator/NodeSearch.h
+++ b/src/3rdparty/angle/src/compiler/translator/NodeSearch.h
@@ -9,7 +9,7 @@
#ifndef COMPILER_TRANSLATOR_NODESEARCH_H_
#define COMPILER_TRANSLATOR_NODESEARCH_H_
-#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermTraverse.h"
namespace sh
{
@@ -18,10 +18,7 @@ template <class Parent>
class NodeSearchTraverser : public TIntermTraverser
{
public:
- NodeSearchTraverser()
- : TIntermTraverser(true, false, false),
- mFound(false)
- {}
+ NodeSearchTraverser() : TIntermTraverser(true, false, false), mFound(false) {}
bool found() const { return mFound; }
@@ -43,17 +40,17 @@ class FindDiscard : public NodeSearchTraverser<FindDiscard>
{
switch (node->getFlowOp())
{
- case EOpKill:
- mFound = true;
- break;
+ case EOpKill:
+ mFound = true;
+ break;
- default: break;
+ default:
+ break;
}
return !mFound;
}
};
-
}
-#endif // COMPILER_TRANSLATOR_NODESEARCH_H_
+#endif // COMPILER_TRANSLATOR_NODESEARCH_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/Operator.cpp b/src/3rdparty/angle/src/compiler/translator/Operator.cpp
index 20e47f290e..7a2156611a 100644
--- a/src/3rdparty/angle/src/compiler/translator/Operator.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/Operator.cpp
@@ -10,192 +10,376 @@ const char *GetOperatorString(TOperator op)
{
switch (op)
{
- // Note: ops from EOpNull to EOpPrototype can't be handled here.
-
- case EOpNegative: return "-";
- case EOpPositive: return "+";
- case EOpLogicalNot: return "!";
- case EOpVectorLogicalNot: return "not";
- case EOpBitwiseNot: return "~";
-
- case EOpPostIncrement: return "++";
- case EOpPostDecrement: return "--";
- case EOpPreIncrement: return "++";
- case EOpPreDecrement: return "--";
-
- case EOpAdd: return "+";
- case EOpSub: return "-";
- case EOpMul: return "*";
- case EOpDiv: return "/";
- case EOpIMod: return "%";
- case EOpEqual: return "==";
- case EOpNotEqual: return "!=";
- case EOpVectorEqual: return "equal";
- case EOpVectorNotEqual: return "notEqual";
- case EOpLessThan: return "<";
- case EOpGreaterThan: return ">";
- case EOpLessThanEqual: return "<=";
- case EOpGreaterThanEqual: return ">=";
- case EOpComma: return ",";
-
- // Fall-through.
- case EOpVectorTimesScalar:
- case EOpVectorTimesMatrix:
- case EOpMatrixTimesVector:
- case EOpMatrixTimesScalar: return "*";
-
- case EOpLogicalOr: return "||";
- case EOpLogicalXor: return "^^";
- case EOpLogicalAnd: return "&&";
-
- case EOpBitShiftLeft: return "<<";
- case EOpBitShiftRight: return ">>";
-
- case EOpBitwiseAnd: return "&";
- case EOpBitwiseXor: return "^";
- case EOpBitwiseOr: return "|";
-
- // Fall-through.
- case EOpIndexDirect:
- case EOpIndexIndirect: return "[]";
-
- case EOpIndexDirectStruct:
- case EOpIndexDirectInterfaceBlock: return ".";
-
- case EOpVectorSwizzle: return ".";
-
- case EOpRadians: return "radians";
- case EOpDegrees: return "degrees";
- case EOpSin: return "sin";
- case EOpCos: return "cos";
- case EOpTan: return "tan";
- case EOpAsin: return "asin";
- case EOpAcos: return "acos";
- case EOpAtan: return "atan";
-
- case EOpSinh: return "sinh";
- case EOpCosh: return "cosh";
- case EOpTanh: return "tanh";
- case EOpAsinh: return "asinh";
- case EOpAcosh: return "acosh";
- case EOpAtanh: return "atanh";
-
- case EOpPow: return "pow";
- case EOpExp: return "exp";
- case EOpLog: return "log";
- case EOpExp2: return "exp2";
- case EOpLog2: return "log2";
- case EOpSqrt: return "sqrt";
- case EOpInverseSqrt: return "inversesqrt";
-
- case EOpAbs: return "abs";
- case EOpSign: return "sign";
- case EOpFloor: return "floor";
- case EOpTrunc: return "trunc";
- case EOpRound: return "round";
- case EOpRoundEven: return "roundEven";
- case EOpCeil: return "ceil";
- case EOpFract: return "fract";
- case EOpMod: return "mod";
- case EOpModf: return "modf";
- case EOpMin: return "min";
- case EOpMax: return "max";
- case EOpClamp: return "clamp";
- case EOpMix: return "mix";
- case EOpStep: return "step";
- case EOpSmoothStep: return "smoothstep";
- case EOpIsNan: return "isnan";
- case EOpIsInf: return "isinf";
-
- case EOpFloatBitsToInt: return "floatBitsToInt";
- case EOpFloatBitsToUint: return "floatBitsToUint";
- case EOpIntBitsToFloat: return "intBitsToFloat";
- case EOpUintBitsToFloat: return "uintBitsToFloat";
-
- case EOpPackSnorm2x16: return "packSnorm2x16";
- case EOpPackUnorm2x16: return "packUnorm2x16";
- case EOpPackHalf2x16: return "packHalf2x16";
- case EOpUnpackSnorm2x16: return "unpackSnorm2x16";
- case EOpUnpackUnorm2x16: return "unpackUnorm2x16";
- case EOpUnpackHalf2x16: return "unpackHalf2x16";
-
- case EOpLength: return "length";
- case EOpDistance: return "distance";
- case EOpDot: return "dot";
- case EOpCross: return "cross";
- case EOpNormalize: return "normalize";
- case EOpFaceForward: return "faceforward";
- case EOpReflect: return "reflect";
- case EOpRefract: return "refract";
-
- case EOpDFdx: return "dFdx";
- case EOpDFdy: return "dFdy";
- case EOpFwidth: return "fwidth";
-
- case EOpMatrixTimesMatrix: return "*";
-
- case EOpOuterProduct: return "outerProduct";
- case EOpTranspose: return "transpose";
- case EOpDeterminant: return "determinant";
- case EOpInverse: return "inverse";
-
- case EOpAny: return "any";
- case EOpAll: return "all";
-
- case EOpKill: return "kill";
- case EOpReturn: return "return";
- case EOpBreak: return "break";
- case EOpContinue: return "continue";
-
- case EOpConstructInt: return "int";
- case EOpConstructUInt: return "uint";
- case EOpConstructBool: return "bool";
- case EOpConstructFloat: return "float";
- case EOpConstructVec2: return "vec2";
- case EOpConstructVec3: return "vec3";
- case EOpConstructVec4: return "vec4";
- case EOpConstructBVec2: return "bvec2";
- case EOpConstructBVec3: return "bvec3";
- case EOpConstructBVec4: return "bvec4";
- case EOpConstructIVec2: return "ivec2";
- case EOpConstructIVec3: return "ivec3";
- case EOpConstructIVec4: return "ivec4";
- case EOpConstructUVec2: return "uvec2";
- case EOpConstructUVec3: return "uvec3";
- case EOpConstructUVec4: return "uvec4";
- case EOpConstructMat2: return "mat2";
- case EOpConstructMat2x3: return "mat2x3";
- case EOpConstructMat2x4: return "mat2x4";
- case EOpConstructMat3x2: return "mat3x2";
- case EOpConstructMat3: return "mat3";
- case EOpConstructMat3x4: return "mat3x4";
- case EOpConstructMat4x2: return "mat4x2";
- case EOpConstructMat4x3: return "mat4x3";
- case EOpConstructMat4: return "mat4";
- // Note: EOpConstructStruct can't be handled here
-
- case EOpAssign: return "=";
- case EOpInitialize: return "=";
- case EOpAddAssign: return "+=";
- case EOpSubAssign: return "-=";
-
- // Fall-through.
- case EOpMulAssign:
- case EOpVectorTimesMatrixAssign:
- case EOpVectorTimesScalarAssign:
- case EOpMatrixTimesScalarAssign:
- case EOpMatrixTimesMatrixAssign: return "*=";
-
- case EOpDivAssign: return "/=";
- case EOpIModAssign: return "%=";
- case EOpBitShiftLeftAssign: return "<<=";
- case EOpBitShiftRightAssign: return ">>=";
- case EOpBitwiseAndAssign: return "&=";
- case EOpBitwiseXorAssign: return "^=";
- case EOpBitwiseOrAssign: return "|=";
-
- default: break;
+ // Note: EOpNull and EOpCall* can't be handled here.
+
+ case EOpNegative:
+ return "-";
+ case EOpPositive:
+ return "+";
+ case EOpLogicalNot:
+ return "!";
+ case EOpBitwiseNot:
+ return "~";
+
+ case EOpPostIncrement:
+ return "++";
+ case EOpPostDecrement:
+ return "--";
+ case EOpPreIncrement:
+ return "++";
+ case EOpPreDecrement:
+ return "--";
+
+ case EOpArrayLength:
+ return ".length()";
+
+ case EOpAdd:
+ return "+";
+ case EOpSub:
+ return "-";
+ case EOpMul:
+ return "*";
+ case EOpDiv:
+ return "/";
+ case EOpIMod:
+ return "%";
+
+ case EOpEqual:
+ return "==";
+ case EOpNotEqual:
+ return "!=";
+ case EOpLessThan:
+ return "<";
+ case EOpGreaterThan:
+ return ">";
+ case EOpLessThanEqual:
+ return "<=";
+ case EOpGreaterThanEqual:
+ return ">=";
+
+ case EOpEqualComponentWise:
+ return "equal";
+ case EOpNotEqualComponentWise:
+ return "notEqual";
+ case EOpLessThanComponentWise:
+ return "lessThan";
+ case EOpGreaterThanComponentWise:
+ return "greaterThan";
+ case EOpLessThanEqualComponentWise:
+ return "lessThanEqual";
+ case EOpGreaterThanEqualComponentWise:
+ return "greaterThanEqual";
+
+ case EOpComma:
+ return ",";
+
+ // Fall-through.
+ case EOpVectorTimesScalar:
+ case EOpVectorTimesMatrix:
+ case EOpMatrixTimesVector:
+ case EOpMatrixTimesScalar:
+ case EOpMatrixTimesMatrix:
+ return "*";
+
+ case EOpLogicalOr:
+ return "||";
+ case EOpLogicalXor:
+ return "^^";
+ case EOpLogicalAnd:
+ return "&&";
+
+ case EOpBitShiftLeft:
+ return "<<";
+ case EOpBitShiftRight:
+ return ">>";
+
+ case EOpBitwiseAnd:
+ return "&";
+ case EOpBitwiseXor:
+ return "^";
+ case EOpBitwiseOr:
+ return "|";
+
+ // Fall-through.
+ case EOpIndexDirect:
+ case EOpIndexIndirect:
+ return "[]";
+
+ case EOpIndexDirectStruct:
+ case EOpIndexDirectInterfaceBlock:
+ return ".";
+
+ case EOpRadians:
+ return "radians";
+ case EOpDegrees:
+ return "degrees";
+ case EOpSin:
+ return "sin";
+ case EOpCos:
+ return "cos";
+ case EOpTan:
+ return "tan";
+ case EOpAsin:
+ return "asin";
+ case EOpAcos:
+ return "acos";
+ case EOpAtan:
+ return "atan";
+
+ case EOpSinh:
+ return "sinh";
+ case EOpCosh:
+ return "cosh";
+ case EOpTanh:
+ return "tanh";
+ case EOpAsinh:
+ return "asinh";
+ case EOpAcosh:
+ return "acosh";
+ case EOpAtanh:
+ return "atanh";
+
+ case EOpPow:
+ return "pow";
+ case EOpExp:
+ return "exp";
+ case EOpLog:
+ return "log";
+ case EOpExp2:
+ return "exp2";
+ case EOpLog2:
+ return "log2";
+ case EOpSqrt:
+ return "sqrt";
+ case EOpInverseSqrt:
+ return "inversesqrt";
+
+ case EOpAbs:
+ return "abs";
+ case EOpSign:
+ return "sign";
+ case EOpFloor:
+ return "floor";
+ case EOpTrunc:
+ return "trunc";
+ case EOpRound:
+ return "round";
+ case EOpRoundEven:
+ return "roundEven";
+ case EOpCeil:
+ return "ceil";
+ case EOpFract:
+ return "fract";
+ case EOpMod:
+ return "mod";
+ case EOpModf:
+ return "modf";
+ case EOpMin:
+ return "min";
+ case EOpMax:
+ return "max";
+ case EOpClamp:
+ return "clamp";
+ case EOpMix:
+ return "mix";
+ case EOpStep:
+ return "step";
+ case EOpSmoothStep:
+ return "smoothstep";
+ case EOpIsNan:
+ return "isnan";
+ case EOpIsInf:
+ return "isinf";
+
+ case EOpFloatBitsToInt:
+ return "floatBitsToInt";
+ case EOpFloatBitsToUint:
+ return "floatBitsToUint";
+ case EOpIntBitsToFloat:
+ return "intBitsToFloat";
+ case EOpUintBitsToFloat:
+ return "uintBitsToFloat";
+
+ case EOpFrexp:
+ return "frexp";
+ case EOpLdexp:
+ return "ldexp";
+
+ case EOpPackSnorm2x16:
+ return "packSnorm2x16";
+ case EOpPackUnorm2x16:
+ return "packUnorm2x16";
+ case EOpPackHalf2x16:
+ return "packHalf2x16";
+ case EOpUnpackSnorm2x16:
+ return "unpackSnorm2x16";
+ case EOpUnpackUnorm2x16:
+ return "unpackUnorm2x16";
+ case EOpUnpackHalf2x16:
+ return "unpackHalf2x16";
+
+ case EOpPackUnorm4x8:
+ return "packUnorm4x8";
+ case EOpPackSnorm4x8:
+ return "packSnorm4x8";
+ case EOpUnpackUnorm4x8:
+ return "unpackUnorm4x8";
+ case EOpUnpackSnorm4x8:
+ return "unpackSnorm4x8";
+
+ case EOpLength:
+ return "length";
+ case EOpDistance:
+ return "distance";
+ case EOpDot:
+ return "dot";
+ case EOpCross:
+ return "cross";
+ case EOpNormalize:
+ return "normalize";
+ case EOpFaceforward:
+ return "faceforward";
+ case EOpReflect:
+ return "reflect";
+ case EOpRefract:
+ return "refract";
+
+ case EOpDFdx:
+ return "dFdx";
+ case EOpDFdy:
+ return "dFdy";
+ case EOpFwidth:
+ return "fwidth";
+
+ case EOpMulMatrixComponentWise:
+ return "matrixCompMult";
+ case EOpOuterProduct:
+ return "outerProduct";
+ case EOpTranspose:
+ return "transpose";
+ case EOpDeterminant:
+ return "determinant";
+ case EOpInverse:
+ return "inverse";
+
+ case EOpAny:
+ return "any";
+ case EOpAll:
+ return "all";
+ case EOpLogicalNotComponentWise:
+ return "not";
+
+ case EOpBitfieldExtract:
+ return "bitfieldExtract";
+ case EOpBitfieldInsert:
+ return "bitfieldInsert";
+ case EOpBitfieldReverse:
+ return "bitfieldReverse";
+ case EOpBitCount:
+ return "bitCount";
+ case EOpFindLSB:
+ return "findLSB";
+ case EOpFindMSB:
+ return "findMSB";
+ case EOpUaddCarry:
+ return "uaddCarry";
+ case EOpUsubBorrow:
+ return "usubBorrow";
+ case EOpUmulExtended:
+ return "umulExtended";
+ case EOpImulExtended:
+ return "imulExtended";
+
+ case EOpKill:
+ return "kill";
+ case EOpReturn:
+ return "return";
+ case EOpBreak:
+ return "break";
+ case EOpContinue:
+ return "continue";
+
+ case EOpAssign:
+ return "=";
+ case EOpInitialize:
+ return "=";
+ case EOpAddAssign:
+ return "+=";
+ case EOpSubAssign:
+ return "-=";
+
+ // Fall-through.
+ case EOpMulAssign:
+ case EOpVectorTimesMatrixAssign:
+ case EOpVectorTimesScalarAssign:
+ case EOpMatrixTimesScalarAssign:
+ case EOpMatrixTimesMatrixAssign:
+ return "*=";
+
+ case EOpDivAssign:
+ return "/=";
+ case EOpIModAssign:
+ return "%=";
+ case EOpBitShiftLeftAssign:
+ return "<<=";
+ case EOpBitShiftRightAssign:
+ return ">>=";
+ case EOpBitwiseAndAssign:
+ return "&=";
+ case EOpBitwiseXorAssign:
+ return "^=";
+ case EOpBitwiseOrAssign:
+ return "|=";
+ case EOpBarrier:
+ return "barrier";
+ case EOpMemoryBarrier:
+ return "memoryBarrier";
+ case EOpMemoryBarrierAtomicCounter:
+ return "memoryBarrierAtomicCounter";
+ case EOpMemoryBarrierBuffer:
+ return "memoryBarrierBuffer";
+ case EOpMemoryBarrierImage:
+ return "memoryBarrierImage";
+ case EOpMemoryBarrierShared:
+ return "memoryBarrierShared";
+ case EOpGroupMemoryBarrier:
+ return "groupMemoryBarrier";
+
+ case EOpEmitVertex:
+ return "EmitVertex";
+ case EOpEndPrimitive:
+ return "EndPrimitive";
+ default:
+ break;
}
return "";
}
+bool IsAssignment(TOperator op)
+{
+ switch (op)
+ {
+ case EOpPostIncrement:
+ case EOpPostDecrement:
+ case EOpPreIncrement:
+ case EOpPreDecrement:
+ case EOpAssign:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpMulAssign:
+ case EOpVectorTimesMatrixAssign:
+ case EOpVectorTimesScalarAssign:
+ case EOpMatrixTimesScalarAssign:
+ case EOpMatrixTimesMatrixAssign:
+ case EOpDivAssign:
+ case EOpIModAssign:
+ case EOpBitShiftLeftAssign:
+ case EOpBitShiftRightAssign:
+ case EOpBitwiseAndAssign:
+ case EOpBitwiseXorAssign:
+ case EOpBitwiseOrAssign:
+ return true;
+ default:
+ return false;
+ }
+} \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/Operator.h b/src/3rdparty/angle/src/compiler/translator/Operator.h
index b0efb8f48b..72f3dbf3f6 100644
--- a/src/3rdparty/angle/src/compiler/translator/Operator.h
+++ b/src/3rdparty/angle/src/compiler/translator/Operator.h
@@ -12,15 +12,21 @@
//
enum TOperator
{
- EOpNull, // if in a node, should only mean a node is still being built
- EOpSequence, // denotes a list of statements, or parameters, etc.
- EOpFunctionCall,
- EOpFunction, // For function definition
- EOpParameters, // an aggregate listing the parameters to a function
+ EOpNull, // if in a node, should only mean a node is still being built
- EOpDeclaration,
- EOpInvariantDeclaration, // Specialized declarations for attributing invariance
- EOpPrototype,
+ // Call a function defined in the AST. This might be a user-defined function or a function
+ // inserted by an AST transformation.
+ EOpCallFunctionInAST,
+
+ // Call an internal helper function with a raw implementation - the implementation can't be
+ // subject to AST transformations. Raw functions have a few constraints to keep them compatible
+ // with AST traversers:
+ // * They should not return arrays.
+ // * They should not have out parameters.
+ EOpCallInternalRawFunction,
+
+ // Call a built-in function like a texture or image function.
+ EOpCallBuiltInFunction,
//
// Unary operators
@@ -29,7 +35,6 @@ enum TOperator
EOpNegative,
EOpPositive,
EOpLogicalNot,
- EOpVectorLogicalNot,
EOpBitwiseNot,
EOpPostIncrement,
@@ -37,8 +42,11 @@ enum TOperator
EOpPreIncrement,
EOpPreDecrement,
+ EOpArrayLength,
+
//
- // binary operations
+ // binary operations (ones with special GLSL syntax are used in TIntermBinary nodes, others in
+ // TIntermAggregate nodes)
//
EOpAdd,
@@ -46,20 +54,28 @@ enum TOperator
EOpMul,
EOpDiv,
EOpIMod,
+
EOpEqual,
EOpNotEqual,
- EOpVectorEqual,
- EOpVectorNotEqual,
EOpLessThan,
EOpGreaterThan,
EOpLessThanEqual,
EOpGreaterThanEqual,
+
+ EOpEqualComponentWise,
+ EOpNotEqualComponentWise,
+ EOpLessThanComponentWise,
+ EOpLessThanEqualComponentWise,
+ EOpGreaterThanComponentWise,
+ EOpGreaterThanEqualComponentWise,
+
EOpComma,
EOpVectorTimesScalar,
EOpVectorTimesMatrix,
EOpMatrixTimesVector,
EOpMatrixTimesScalar,
+ EOpMatrixTimesMatrix,
EOpLogicalOr,
EOpLogicalXor,
@@ -77,10 +93,8 @@ enum TOperator
EOpIndexDirectStruct,
EOpIndexDirectInterfaceBlock,
- EOpVectorSwizzle,
-
//
- // Built-in functions potentially mapped to operators
+ // Built-in functions mapped to operators (either unary or with multiple parameters)
//
EOpRadians,
@@ -131,6 +145,9 @@ enum TOperator
EOpIntBitsToFloat,
EOpUintBitsToFloat,
+ EOpFrexp,
+ EOpLdexp,
+
EOpPackSnorm2x16,
EOpPackUnorm2x16,
EOpPackHalf2x16,
@@ -138,21 +155,25 @@ enum TOperator
EOpUnpackUnorm2x16,
EOpUnpackHalf2x16,
+ EOpPackUnorm4x8,
+ EOpPackSnorm4x8,
+ EOpUnpackUnorm4x8,
+ EOpUnpackSnorm4x8,
+
EOpLength,
EOpDistance,
EOpDot,
EOpCross,
EOpNormalize,
- EOpFaceForward,
+ EOpFaceforward,
EOpReflect,
EOpRefract,
- EOpDFdx, // Fragment only, OES_standard_derivatives extension
- EOpDFdy, // Fragment only, OES_standard_derivatives extension
- EOpFwidth, // Fragment only, OES_standard_derivatives extension
-
- EOpMatrixTimesMatrix,
+ EOpDFdx, // Fragment only, OES_standard_derivatives extension
+ EOpDFdy, // Fragment only, OES_standard_derivatives extension
+ EOpFwidth, // Fragment only, OES_standard_derivatives extension
+ EOpMulMatrixComponentWise,
EOpOuterProduct,
EOpTranspose,
EOpDeterminant,
@@ -160,46 +181,33 @@ enum TOperator
EOpAny,
EOpAll,
+ EOpLogicalNotComponentWise,
+
+ EOpBitfieldExtract,
+ EOpBitfieldInsert,
+ EOpBitfieldReverse,
+ EOpBitCount,
+ EOpFindLSB,
+ EOpFindMSB,
+ EOpUaddCarry,
+ EOpUsubBorrow,
+ EOpUmulExtended,
+ EOpImulExtended,
//
// Branch
//
- EOpKill, // Fragment only
+ EOpKill, // Fragment only
EOpReturn,
EOpBreak,
EOpContinue,
//
- // Constructors
+ // Constructor
//
- EOpConstructInt,
- EOpConstructUInt,
- EOpConstructBool,
- EOpConstructFloat,
- EOpConstructVec2,
- EOpConstructVec3,
- EOpConstructVec4,
- EOpConstructBVec2,
- EOpConstructBVec3,
- EOpConstructBVec4,
- EOpConstructIVec2,
- EOpConstructIVec3,
- EOpConstructIVec4,
- EOpConstructUVec2,
- EOpConstructUVec3,
- EOpConstructUVec4,
- EOpConstructMat2,
- EOpConstructMat2x3,
- EOpConstructMat2x4,
- EOpConstructMat3x2,
- EOpConstructMat3,
- EOpConstructMat3x4,
- EOpConstructMat4x2,
- EOpConstructMat4x3,
- EOpConstructMat4,
- EOpConstructStruct,
+ EOpConstruct,
//
// moves
@@ -222,10 +230,26 @@ enum TOperator
EOpBitShiftRightAssign,
EOpBitwiseAndAssign,
EOpBitwiseXorAssign,
- EOpBitwiseOrAssign
+ EOpBitwiseOrAssign,
+
+ // barriers
+ EOpBarrier,
+ EOpMemoryBarrier,
+ EOpMemoryBarrierAtomicCounter,
+ EOpMemoryBarrierBuffer,
+ EOpMemoryBarrierImage,
+ EOpMemoryBarrierShared,
+ EOpGroupMemoryBarrier,
+
+ // Geometry only
+ EOpEmitVertex,
+ EOpEndPrimitive
};
// Returns the string corresponding to the operator in GLSL
-const char* GetOperatorString(TOperator op);
+const char *GetOperatorString(TOperator op);
+
+// Say whether or not a binary or unary operation changes the value of a variable.
+bool IsAssignment(TOperator op);
#endif // COMPILER_TRANSLATOR_OPERATOR_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp
index 77e0a8fb37..50626c91c0 100644
--- a/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp
@@ -6,20 +6,27 @@
#include "compiler/translator/OutputESSL.h"
+namespace sh
+{
+
TOutputESSL::TOutputESSL(TInfoSinkBase &objSink,
ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction,
NameMap &nameMap,
- TSymbolTable &symbolTable,
+ TSymbolTable *symbolTable,
+ sh::GLenum shaderType,
int shaderVersion,
- bool forceHighp)
+ bool forceHighp,
+ ShCompileOptions compileOptions)
: TOutputGLSLBase(objSink,
clampingStrategy,
hashFunction,
nameMap,
symbolTable,
+ shaderType,
shaderVersion,
- SH_ESSL_OUTPUT),
+ SH_ESSL_OUTPUT,
+ compileOptions),
mForceHighp(forceHighp)
{
}
@@ -29,10 +36,12 @@ bool TOutputESSL::writeVariablePrecision(TPrecision precision)
if (precision == EbpUndefined)
return false;
- TInfoSinkBase& out = objSink();
+ TInfoSinkBase &out = objSink();
if (mForceHighp)
out << getPrecisionString(EbpHigh);
else
out << getPrecisionString(precision);
return true;
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputESSL.h b/src/3rdparty/angle/src/compiler/translator/OutputESSL.h
index c5a963499e..e0c7bf2ae6 100644
--- a/src/3rdparty/angle/src/compiler/translator/OutputESSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/OutputESSL.h
@@ -9,22 +9,29 @@
#include "compiler/translator/OutputGLSLBase.h"
+namespace sh
+{
+
class TOutputESSL : public TOutputGLSLBase
{
-public:
- TOutputESSL(TInfoSinkBase& objSink,
+ public:
+ TOutputESSL(TInfoSinkBase &objSink,
ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction,
- NameMap& nameMap,
- TSymbolTable& symbolTable,
+ NameMap &nameMap,
+ TSymbolTable *symbolTable,
+ sh::GLenum shaderType,
int shaderVersion,
- bool forceHighp);
+ bool forceHighp,
+ ShCompileOptions compileOptions);
-protected:
- bool writeVariablePrecision(TPrecision precision) override;
+ protected:
+ bool writeVariablePrecision(TPrecision precision) override;
-private:
+ private:
bool mForceHighp;
};
+} // namespace sh
+
#endif // COMPILER_TRANSLATOR_OUTPUTESSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp
index 431425020a..1bad05dab9 100644
--- a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp
@@ -6,20 +6,29 @@
#include "compiler/translator/OutputGLSL.h"
-TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink,
+#include "compiler/translator/Compiler.h"
+
+namespace sh
+{
+
+TOutputGLSL::TOutputGLSL(TInfoSinkBase &objSink,
ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction,
- NameMap& nameMap,
- TSymbolTable& symbolTable,
+ NameMap &nameMap,
+ TSymbolTable *symbolTable,
+ sh::GLenum shaderType,
int shaderVersion,
- ShShaderOutput output)
+ ShShaderOutput output,
+ ShCompileOptions compileOptions)
: TOutputGLSLBase(objSink,
clampingStrategy,
hashFunction,
nameMap,
symbolTable,
+ shaderType,
shaderVersion,
- output)
+ output,
+ compileOptions)
{
}
@@ -30,18 +39,18 @@ bool TOutputGLSL::writeVariablePrecision(TPrecision)
void TOutputGLSL::visitSymbol(TIntermSymbol *node)
{
- TInfoSinkBase& out = objSink();
+ TInfoSinkBase &out = objSink();
const TString &symbol = node->getSymbol();
if (symbol == "gl_FragDepthEXT")
{
out << "gl_FragDepth";
}
- else if (symbol == "gl_FragColor" && IsGLSL130OrNewer(getShaderOutput()))
+ else if (symbol == "gl_FragColor" && sh::IsGLSL130OrNewer(getShaderOutput()))
{
out << "webgl_FragColor";
}
- else if (symbol == "gl_FragData" && IsGLSL130OrNewer(getShaderOutput()))
+ else if (symbol == "gl_FragData" && sh::IsGLSL130OrNewer(getShaderOutput()))
{
out << "webgl_FragData";
}
@@ -59,44 +68,43 @@ void TOutputGLSL::visitSymbol(TIntermSymbol *node)
}
}
-TString TOutputGLSL::translateTextureFunction(TString &name)
+TString TOutputGLSL::translateTextureFunction(const TString &name)
{
- static const char *simpleRename[] = {
- "texture2DLodEXT", "texture2DLod",
- "texture2DProjLodEXT", "texture2DProjLod",
- "textureCubeLodEXT", "textureCubeLod",
- "texture2DGradEXT", "texture2DGradARB",
- "texture2DProjGradEXT", "texture2DProjGradARB",
- "textureCubeGradEXT", "textureCubeGradARB",
- NULL, NULL
- };
+ static const char *simpleRename[] = {"texture2DLodEXT",
+ "texture2DLod",
+ "texture2DProjLodEXT",
+ "texture2DProjLod",
+ "textureCubeLodEXT",
+ "textureCubeLod",
+ "texture2DGradEXT",
+ "texture2DGradARB",
+ "texture2DProjGradEXT",
+ "texture2DProjGradARB",
+ "textureCubeGradEXT",
+ "textureCubeGradARB",
+ nullptr,
+ nullptr};
static const char *legacyToCoreRename[] = {
- "texture2D", "texture",
- "texture2DProj", "textureProj",
- "texture2DLod", "textureLod",
- "texture2DProjLod", "textureProjLod",
- "texture2DRect", "texture",
- "textureCube", "texture",
+ "texture2D", "texture", "texture2DProj", "textureProj", "texture2DLod", "textureLod",
+ "texture2DProjLod", "textureProjLod", "texture2DRect", "texture", "textureCube", "texture",
"textureCubeLod", "textureLod",
// Extensions
- "texture2DLodEXT", "textureLod",
- "texture2DProjLodEXT", "textureProjLod",
- "textureCubeLodEXT", "textureLod",
- "texture2DGradEXT", "textureGrad",
- "texture2DProjGradEXT", "textureProjGrad",
- "textureCubeGradEXT", "textureGrad",
- NULL, NULL
- };
- const char **mapping = (IsGLSL130OrNewer(getShaderOutput())) ?
- legacyToCoreRename : simpleRename;
+ "texture2DLodEXT", "textureLod", "texture2DProjLodEXT", "textureProjLod",
+ "textureCubeLodEXT", "textureLod", "texture2DGradEXT", "textureGrad",
+ "texture2DProjGradEXT", "textureProjGrad", "textureCubeGradEXT", "textureGrad", nullptr,
+ nullptr};
+ const char **mapping =
+ (sh::IsGLSL130OrNewer(getShaderOutput())) ? legacyToCoreRename : simpleRename;
- for (int i = 0; mapping[i] != NULL; i += 2)
+ for (int i = 0; mapping[i] != nullptr; i += 2)
{
if (name == mapping[i])
{
- return mapping[i+1];
+ return mapping[i + 1];
}
}
return name;
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h
index 9b1aca4eab..c80abec1a6 100644
--- a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h
@@ -9,21 +9,28 @@
#include "compiler/translator/OutputGLSLBase.h"
+namespace sh
+{
+
class TOutputGLSL : public TOutputGLSLBase
{
public:
- TOutputGLSL(TInfoSinkBase& objSink,
+ TOutputGLSL(TInfoSinkBase &objSink,
ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction,
- NameMap& nameMap,
- TSymbolTable& symbolTable,
+ NameMap &nameMap,
+ TSymbolTable *symbolTable,
+ sh::GLenum shaderType,
int shaderVersion,
- ShShaderOutput output);
+ ShShaderOutput output,
+ ShCompileOptions compileOptions);
protected:
bool writeVariablePrecision(TPrecision) override;
void visitSymbol(TIntermSymbol *node) override;
- TString translateTextureFunction(TString &name) override;
+ TString translateTextureFunction(const TString &name) override;
};
+} // namespace sh
+
#endif // COMPILER_TRANSLATOR_OUTPUTGLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp
index f048b050b7..edaf2ebebf 100644
--- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp
@@ -6,32 +6,33 @@
#include "compiler/translator/OutputGLSLBase.h"
+#include "angle_gl.h"
#include "common/debug.h"
+#include "common/mathutil.h"
+#include "compiler/translator/Compiler.h"
+#include "compiler/translator/util.h"
#include <cfloat>
-namespace
+namespace sh
{
-TString arrayBrackets(const TType &type)
+
+namespace
{
- ASSERT(type.isArray());
- TInfoSinkBase out;
- out << "[" << type.getArraySize() << "]";
- return TString(out.c_str());
-}
bool isSingleStatement(TIntermNode *node)
{
- if (const TIntermAggregate *aggregate = node->getAsAggregate())
+ if (node->getAsFunctionDefinition())
+ {
+ return false;
+ }
+ else if (node->getAsBlock())
{
- return (aggregate->getOp() != EOpFunction) &&
- (aggregate->getOp() != EOpSequence);
+ return false;
}
- else if (const TIntermSelection *selection = node->getAsSelectionNode())
+ else if (node->getAsIfElseNode())
{
- // Ternary operators are usually part of an assignment operator.
- // This handles those rare cases in which they are all by themselves.
- return selection->usesTernaryOperator();
+ return false;
}
else if (node->getAsLoopNode())
{
@@ -48,29 +49,79 @@ bool isSingleStatement(TIntermNode *node)
return true;
}
+class CommaSeparatedListItemPrefixGenerator
+{
+ public:
+ CommaSeparatedListItemPrefixGenerator() : mFirst(true) {}
+ private:
+ bool mFirst;
+
+ friend TInfoSinkBase &operator<<(TInfoSinkBase &out,
+ CommaSeparatedListItemPrefixGenerator &gen);
+};
+
+TInfoSinkBase &operator<<(TInfoSinkBase &out, CommaSeparatedListItemPrefixGenerator &gen)
+{
+ if (gen.mFirst)
+ {
+ gen.mFirst = false;
+ }
+ else
+ {
+ out << ", ";
+ }
+ return out;
+}
+
} // namespace
TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink,
ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction,
NameMap &nameMap,
- TSymbolTable &symbolTable,
+ TSymbolTable *symbolTable,
+ sh::GLenum shaderType,
int shaderVersion,
- ShShaderOutput output)
- : TIntermTraverser(true, true, true),
+ ShShaderOutput output,
+ ShCompileOptions compileOptions)
+ : TIntermTraverser(true, true, true, symbolTable),
mObjSink(objSink),
- mDeclaringVariables(false),
+ mDeclaringVariable(false),
mClampingStrategy(clampingStrategy),
mHashFunction(hashFunction),
mNameMap(nameMap),
- mSymbolTable(symbolTable),
+ mShaderType(shaderType),
mShaderVersion(shaderVersion),
- mOutput(output)
+ mOutput(output),
+ mCompileOptions(compileOptions)
+{
+}
+
+void TOutputGLSLBase::writeInvariantQualifier(const TType &type)
{
+ if (!sh::RemoveInvariant(mShaderType, mShaderVersion, mOutput, mCompileOptions))
+ {
+ TInfoSinkBase &out = objSink();
+ out << "invariant ";
+ }
}
-void TOutputGLSLBase::writeTriplet(
- Visit visit, const char *preStr, const char *inStr, const char *postStr)
+void TOutputGLSLBase::writeFloat(TInfoSinkBase &out, float f)
+{
+ if ((gl::isInf(f) || gl::isNaN(f)) && mShaderVersion >= 300)
+ {
+ out << "uintBitsToFloat(" << gl::bitCast<uint32_t>(f) << "u)";
+ }
+ else
+ {
+ out << std::min(FLT_MAX, std::max(-FLT_MAX, f));
+ }
+}
+
+void TOutputGLSLBase::writeTriplet(Visit visit,
+ const char *preStr,
+ const char *inStr,
+ const char *postStr)
{
TInfoSinkBase &out = objSink();
if (visit == PreVisit && preStr)
@@ -81,69 +132,181 @@ void TOutputGLSLBase::writeTriplet(
out << postStr;
}
-void TOutputGLSLBase::writeBuiltInFunctionTriplet(
- Visit visit, const char *preStr, bool useEmulatedFunction)
+void TOutputGLSLBase::writeBuiltInFunctionTriplet(Visit visit,
+ TOperator op,
+ bool useEmulatedFunction)
{
- TString preString = useEmulatedFunction ?
- BuiltInFunctionEmulator::GetEmulatedFunctionName(preStr) : preStr;
- writeTriplet(visit, preString.c_str(), ", ", ")");
+ TInfoSinkBase &out = objSink();
+ if (visit == PreVisit)
+ {
+ const char *opStr(GetOperatorString(op));
+ if (useEmulatedFunction)
+ {
+ BuiltInFunctionEmulator::WriteEmulatedFunctionName(out, opStr);
+ }
+ else
+ {
+ out << opStr;
+ }
+ out << "(";
+ }
+ else
+ {
+ writeTriplet(visit, nullptr, ", ", ")");
+ }
}
-void TOutputGLSLBase::writeLayoutQualifier(const TType &type)
+void TOutputGLSLBase::writeLayoutQualifier(TIntermTyped *variable)
{
- if (type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqVertexIn)
+ const TType &type = variable->getType();
+
+ if (!NeedsToWriteLayoutQualifier(type))
+ {
+ return;
+ }
+
+ TInfoSinkBase &out = objSink();
+ const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier();
+ out << "layout(";
+
+ CommaSeparatedListItemPrefixGenerator listItemPrefix;
+
+ if (type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqVertexIn ||
+ IsVarying(type.getQualifier()))
{
- const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier();
if (layoutQualifier.location >= 0)
{
- TInfoSinkBase &out = objSink();
- out << "layout(location = " << layoutQualifier.location << ") ";
+ out << listItemPrefix << "location = " << layoutQualifier.location;
+ }
+ }
+
+ if (type.getQualifier() == EvqFragmentOut)
+ {
+ if (layoutQualifier.yuv == true)
+ {
+ out << listItemPrefix << "yuv";
+ }
+ }
+
+ if (IsOpaqueType(type.getBasicType()))
+ {
+ if (layoutQualifier.binding >= 0)
+ {
+ out << listItemPrefix << "binding = " << layoutQualifier.binding;
+ }
+ }
+
+ if (IsImage(type.getBasicType()))
+ {
+ if (layoutQualifier.imageInternalFormat != EiifUnspecified)
+ {
+ ASSERT(type.getQualifier() == EvqTemporary || type.getQualifier() == EvqUniform);
+ out << listItemPrefix
+ << getImageInternalFormatString(layoutQualifier.imageInternalFormat);
}
}
+
+ if (IsAtomicCounter(type.getBasicType()))
+ {
+ out << listItemPrefix << "offset = " << layoutQualifier.offset;
+ }
+
+ out << ") ";
+}
+
+const char *TOutputGLSLBase::mapQualifierToString(TQualifier qualifier)
+{
+ if (sh::IsGLSL410OrOlder(mOutput) && mShaderVersion >= 300 &&
+ (mCompileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0)
+ {
+ switch (qualifier)
+ {
+ // The return string is consistent with sh::getQualifierString() from
+ // BaseTypes.h minus the "centroid" keyword.
+ case EvqCentroid:
+ return "";
+ case EvqCentroidIn:
+ return "smooth in";
+ case EvqCentroidOut:
+ return "smooth out";
+ default:
+ break;
+ }
+ }
+ if (sh::IsGLSL130OrNewer(mOutput))
+ {
+ switch (qualifier)
+ {
+ case EvqAttribute:
+ return "in";
+ case EvqVaryingIn:
+ return "in";
+ case EvqVaryingOut:
+ return "out";
+ default:
+ break;
+ }
+ }
+ return sh::getQualifierString(qualifier);
}
void TOutputGLSLBase::writeVariableType(const TType &type)
{
- TInfoSinkBase &out = objSink();
+ TQualifier qualifier = type.getQualifier();
+ TInfoSinkBase &out = objSink();
if (type.isInvariant())
{
- out << "invariant ";
+ writeInvariantQualifier(type);
}
if (type.getBasicType() == EbtInterfaceBlock)
{
TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
declareInterfaceBlockLayout(interfaceBlock);
}
- TQualifier qualifier = type.getQualifier();
if (qualifier != EvqTemporary && qualifier != EvqGlobal)
{
- if (IsGLSL130OrNewer(mOutput))
+ const char *qualifierString = mapQualifierToString(qualifier);
+ if (qualifierString && qualifierString[0] != '\0')
{
- switch (qualifier)
- {
- case EvqAttribute:
- out << "in ";
- break;
- case EvqVaryingIn:
- out << "in ";
- break;
- case EvqVaryingOut:
- out << "out ";
- break;
- default:
- out << type.getQualifierString() << " ";
- break;
- }
- }
- else
- {
- out << type.getQualifierString() << " ";
+ out << qualifierString << " ";
}
}
+
+ const TMemoryQualifier &memoryQualifier = type.getMemoryQualifier();
+ if (memoryQualifier.readonly)
+ {
+ ASSERT(IsImage(type.getBasicType()));
+ out << "readonly ";
+ }
+
+ if (memoryQualifier.writeonly)
+ {
+ ASSERT(IsImage(type.getBasicType()));
+ out << "writeonly ";
+ }
+
+ if (memoryQualifier.coherent)
+ {
+ ASSERT(IsImage(type.getBasicType()));
+ out << "coherent ";
+ }
+
+ if (memoryQualifier.restrictQualifier)
+ {
+ ASSERT(IsImage(type.getBasicType()));
+ out << "restrict ";
+ }
+
+ if (memoryQualifier.volatileQualifier)
+ {
+ ASSERT(IsImage(type.getBasicType()));
+ out << "volatile ";
+ }
+
// Declare the struct if we have not done so already.
if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct()))
{
- TStructure *structure = type.getStruct();
+ const TStructure *structure = type.getStruct();
declareStruct(structure);
@@ -168,20 +331,18 @@ void TOutputGLSLBase::writeVariableType(const TType &type)
void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence &args)
{
TInfoSinkBase &out = objSink();
- for (TIntermSequence::const_iterator iter = args.begin();
- iter != args.end(); ++iter)
+ for (TIntermSequence::const_iterator iter = args.begin(); iter != args.end(); ++iter)
{
const TIntermSymbol *arg = (*iter)->getAsSymbolNode();
- ASSERT(arg != NULL);
+ ASSERT(arg != nullptr);
const TType &type = arg->getType();
writeVariableType(type);
- const TString &name = arg->getSymbol();
- if (!name.empty())
- out << " " << hashName(name);
+ if (!arg->getName().getString().empty())
+ out << " " << hashName(arg->getName());
if (type.isArray())
- out << arrayBrackets(type);
+ out << ArrayString(type);
// Put a comma if this is not the last argument.
if (iter != args.end() - 1)
@@ -189,21 +350,21 @@ void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence &args)
}
}
-const TConstantUnion *TOutputGLSLBase::writeConstantUnion(
- const TType &type, const TConstantUnion *pConstUnion)
+const TConstantUnion *TOutputGLSLBase::writeConstantUnion(const TType &type,
+ const TConstantUnion *pConstUnion)
{
TInfoSinkBase &out = objSink();
if (type.getBasicType() == EbtStruct)
{
const TStructure *structure = type.getStruct();
- out << hashName(structure->name()) << "(";
+ out << hashName(TName(structure->name())) << "(";
const TFieldList &fields = structure->fields();
for (size_t i = 0; i < fields.size(); ++i)
{
const TType *fieldType = fields[i]->type();
- ASSERT(fieldType != NULL);
+ ASSERT(fieldType != nullptr);
pConstUnion = writeConstantUnion(*fieldType, pConstUnion);
if (i != fields.size() - 1)
out << ", ";
@@ -212,7 +373,7 @@ const TConstantUnion *TOutputGLSLBase::writeConstantUnion(
}
else
{
- size_t size = type.getObjectSize();
+ size_t size = type.getObjectSize();
bool writeType = size > 1;
if (writeType)
out << getTypeName(type) << "(";
@@ -220,19 +381,23 @@ const TConstantUnion *TOutputGLSLBase::writeConstantUnion(
{
switch (pConstUnion->getType())
{
- case EbtFloat:
- out << std::min(FLT_MAX, std::max(-FLT_MAX, pConstUnion->getFConst()));
- break;
- case EbtInt:
- out << pConstUnion->getIConst();
- break;
- case EbtUInt:
- out << pConstUnion->getUConst() << "u";
- break;
- case EbtBool:
- out << pConstUnion->getBConst();
- break;
- default: UNREACHABLE();
+ case EbtFloat:
+ writeFloat(out, pConstUnion->getFConst());
+ break;
+ case EbtInt:
+ out << pConstUnion->getIConst();
+ break;
+ case EbtUInt:
+ out << pConstUnion->getUConst() << "u";
+ break;
+ case EbtBool:
+ out << pConstUnion->getBConst();
+ break;
+ case EbtYuvCscStandardEXT:
+ out << getYuvCscStandardEXTString(pConstUnion->getYuvCscStandardEXTConst());
+ break;
+ default:
+ UNREACHABLE();
}
if (i != size - 1)
out << ", ";
@@ -243,20 +408,20 @@ const TConstantUnion *TOutputGLSLBase::writeConstantUnion(
return pConstUnion;
}
-void TOutputGLSLBase::writeConstructorTriplet(Visit visit, const TType &type, const char *constructorBaseType)
+void TOutputGLSLBase::writeConstructorTriplet(Visit visit, const TType &type)
{
TInfoSinkBase &out = objSink();
if (visit == PreVisit)
{
if (type.isArray())
{
- out << constructorBaseType;
- out << arrayBrackets(type);
+ out << getTypeName(type);
+ out << ArrayString(type);
out << "(";
}
else
{
- out << constructorBaseType << "(";
+ out << getTypeName(type) << "(";
}
}
else
@@ -268,13 +433,10 @@ void TOutputGLSLBase::writeConstructorTriplet(Visit visit, const TType &type, co
void TOutputGLSLBase::visitSymbol(TIntermSymbol *node)
{
TInfoSinkBase &out = objSink();
- if (mLoopUnrollStack.needsToReplaceSymbolWithValue(node))
- out << mLoopUnrollStack.getLoopIndexValue(node);
- else
- out << hashVariableName(node->getSymbol());
+ out << hashVariableName(node->getName());
- if (mDeclaringVariables && node->getType().isArray())
- out << arrayBrackets(node->getType());
+ if (mDeclaringVariable && node->getType().isArray())
+ out << ArrayString(node->getType());
}
void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion *node)
@@ -282,241 +444,246 @@ void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion *node)
writeConstantUnion(node->getType(), node->getUnionArrayPointer());
}
+bool TOutputGLSLBase::visitSwizzle(Visit visit, TIntermSwizzle *node)
+{
+ TInfoSinkBase &out = objSink();
+ if (visit == PostVisit)
+ {
+ out << ".";
+ node->writeOffsetsAsXYZW(&out);
+ }
+ return true;
+}
+
bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
{
bool visitChildren = true;
TInfoSinkBase &out = objSink();
switch (node->getOp())
{
- case EOpInitialize:
- if (visit == InVisit)
- {
- out << " = ";
- // RHS of initialize is not being declared.
- mDeclaringVariables = false;
- }
- break;
- case EOpAssign:
- writeTriplet(visit, "(", " = ", ")");
- break;
- case EOpAddAssign:
- writeTriplet(visit, "(", " += ", ")");
- break;
- case EOpSubAssign:
- writeTriplet(visit, "(", " -= ", ")");
- break;
- case EOpDivAssign:
- writeTriplet(visit, "(", " /= ", ")");
- break;
- case EOpIModAssign:
- writeTriplet(visit, "(", " %= ", ")");
- break;
- // Notice the fall-through.
- case EOpMulAssign:
- case EOpVectorTimesMatrixAssign:
- case EOpVectorTimesScalarAssign:
- case EOpMatrixTimesScalarAssign:
- case EOpMatrixTimesMatrixAssign:
- writeTriplet(visit, "(", " *= ", ")");
- break;
- case EOpBitShiftLeftAssign:
- writeTriplet(visit, "(", " <<= ", ")");
- break;
- case EOpBitShiftRightAssign:
- writeTriplet(visit, "(", " >>= ", ")");
- break;
- case EOpBitwiseAndAssign:
- writeTriplet(visit, "(", " &= ", ")");
- break;
- case EOpBitwiseXorAssign:
- writeTriplet(visit, "(", " ^= ", ")");
- break;
- case EOpBitwiseOrAssign:
- writeTriplet(visit, "(", " |= ", ")");
- break;
-
- case EOpIndexDirect:
- writeTriplet(visit, NULL, "[", "]");
- break;
- case EOpIndexIndirect:
- if (node->getAddIndexClamp())
- {
+ case EOpComma:
+ writeTriplet(visit, "(", ", ", ")");
+ break;
+ case EOpInitialize:
if (visit == InVisit)
{
- if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC)
- out << "[int(clamp(float(";
- else
- out << "[webgl_int_clamp(";
+ out << " = ";
+ // RHS of initialize is not being declared.
+ mDeclaringVariable = false;
}
- else if (visit == PostVisit)
- {
- int maxSize;
- TIntermTyped *left = node->getLeft();
- TType leftType = left->getType();
+ break;
+ case EOpAssign:
+ writeTriplet(visit, "(", " = ", ")");
+ break;
+ case EOpAddAssign:
+ writeTriplet(visit, "(", " += ", ")");
+ break;
+ case EOpSubAssign:
+ writeTriplet(visit, "(", " -= ", ")");
+ break;
+ case EOpDivAssign:
+ writeTriplet(visit, "(", " /= ", ")");
+ break;
+ case EOpIModAssign:
+ writeTriplet(visit, "(", " %= ", ")");
+ break;
+ // Notice the fall-through.
+ case EOpMulAssign:
+ case EOpVectorTimesMatrixAssign:
+ case EOpVectorTimesScalarAssign:
+ case EOpMatrixTimesScalarAssign:
+ case EOpMatrixTimesMatrixAssign:
+ writeTriplet(visit, "(", " *= ", ")");
+ break;
+ case EOpBitShiftLeftAssign:
+ writeTriplet(visit, "(", " <<= ", ")");
+ break;
+ case EOpBitShiftRightAssign:
+ writeTriplet(visit, "(", " >>= ", ")");
+ break;
+ case EOpBitwiseAndAssign:
+ writeTriplet(visit, "(", " &= ", ")");
+ break;
+ case EOpBitwiseXorAssign:
+ writeTriplet(visit, "(", " ^= ", ")");
+ break;
+ case EOpBitwiseOrAssign:
+ writeTriplet(visit, "(", " |= ", ")");
+ break;
- if (left->isArray())
+ case EOpIndexDirect:
+ writeTriplet(visit, nullptr, "[", "]");
+ break;
+ case EOpIndexIndirect:
+ if (node->getAddIndexClamp())
+ {
+ if (visit == InVisit)
{
- // The shader will fail validation if the array length is not > 0.
- maxSize = leftType.getArraySize() - 1;
+ if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC)
+ out << "[int(clamp(float(";
+ else
+ out << "[webgl_int_clamp(";
}
- else
+ else if (visit == PostVisit)
{
- maxSize = leftType.getNominalSize() - 1;
+ TIntermTyped *left = node->getLeft();
+ TType leftType = left->getType();
+
+ if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC)
+ out << "), 0.0, float(";
+ else
+ out << ", 0, ";
+
+ if (leftType.isUnsizedArray())
+ {
+ // For runtime-sized arrays in ESSL 3.10 we need to call the length method
+ // to get the length to clamp against. See ESSL 3.10 section 4.1.9. Note
+ // that a runtime-sized array expression is guaranteed not to have side
+ // effects, so it's fine to add the expression to the output twice.
+ ASSERT(mShaderVersion >= 310);
+ ASSERT(!left->hasSideEffects());
+ left->traverse(this);
+ out << ".length() - 1";
+ }
+ else
+ {
+ int maxSize;
+ if (leftType.isArray())
+ {
+ maxSize = static_cast<int>(leftType.getOutermostArraySize()) - 1;
+ }
+ else
+ {
+ maxSize = leftType.getNominalSize() - 1;
+ }
+ out << maxSize;
+ }
+ if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC)
+ out << ")))]";
+ else
+ out << ")]";
}
-
- if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC)
- out << "), 0.0, float(" << maxSize << ")))]";
- else
- out << ", 0, " << maxSize << ")]";
}
- }
- else
- {
- writeTriplet(visit, NULL, "[", "]");
- }
- break;
- case EOpIndexDirectStruct:
- if (visit == InVisit)
- {
- // Here we are writing out "foo.bar", where "foo" is struct
- // and "bar" is field. In AST, it is represented as a binary
- // node, where left child represents "foo" and right child "bar".
- // The node itself represents ".". The struct field "bar" is
- // actually stored as an index into TStructure::fields.
- out << ".";
- const TStructure *structure = node->getLeft()->getType().getStruct();
- const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
- const TField *field = structure->fields()[index->getIConst(0)];
-
- TString fieldName = field->name();
- if (!mSymbolTable.findBuiltIn(structure->name(), mShaderVersion))
- fieldName = hashName(fieldName);
-
- out << fieldName;
- visitChildren = false;
- }
- break;
- case EOpIndexDirectInterfaceBlock:
- if (visit == InVisit)
- {
- out << ".";
- const TInterfaceBlock *interfaceBlock = node->getLeft()->getType().getInterfaceBlock();
- const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
- const TField *field = interfaceBlock->fields()[index->getIConst(0)];
-
- TString fieldName = field->name();
- ASSERT(!mSymbolTable.findBuiltIn(interfaceBlock->name(), mShaderVersion));
- fieldName = hashName(fieldName);
-
- out << fieldName;
- visitChildren = false;
- }
- break;
- case EOpVectorSwizzle:
- if (visit == InVisit)
- {
- out << ".";
- TIntermAggregate *rightChild = node->getRight()->getAsAggregate();
- TIntermSequence *sequence = rightChild->getSequence();
- for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); ++sit)
+ else
+ {
+ writeTriplet(visit, nullptr, "[", "]");
+ }
+ break;
+ case EOpIndexDirectStruct:
+ if (visit == InVisit)
{
- TIntermConstantUnion *element = (*sit)->getAsConstantUnion();
- ASSERT(element->getBasicType() == EbtInt);
- ASSERT(element->getNominalSize() == 1);
- const TConstantUnion& data = element->getUnionArrayPointer()[0];
- ASSERT(data.getType() == EbtInt);
- switch (data.getIConst())
+ // Here we are writing out "foo.bar", where "foo" is struct
+ // and "bar" is field. In AST, it is represented as a binary
+ // node, where left child represents "foo" and right child "bar".
+ // The node itself represents ".". The struct field "bar" is
+ // actually stored as an index into TStructure::fields.
+ out << ".";
+ const TStructure *structure = node->getLeft()->getType().getStruct();
+ const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
+ const TField *field = structure->fields()[index->getIConst(0)];
+
+ TString fieldName = field->name();
+ if (!mSymbolTable->findBuiltIn(structure->name(), mShaderVersion))
+ fieldName = hashName(TName(fieldName));
+
+ out << fieldName;
+ visitChildren = false;
+ }
+ break;
+ case EOpIndexDirectInterfaceBlock:
+ if (visit == InVisit)
+ {
+ out << ".";
+ const TInterfaceBlock *interfaceBlock =
+ node->getLeft()->getType().getInterfaceBlock();
+ const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
+ const TField *field = interfaceBlock->fields()[index->getIConst(0)];
+
+ TString fieldName = field->name();
+ if (!mSymbolTable->findBuiltIn(interfaceBlock->name(), mShaderVersion))
{
- case 0:
- out << "x";
- break;
- case 1:
- out << "y";
- break;
- case 2:
- out << "z";
- break;
- case 3:
- out << "w";
- break;
- default:
- UNREACHABLE();
+ fieldName = hashName(TName(fieldName));
}
+ else
+ {
+ ASSERT(interfaceBlock->name() == "gl_PerVertex");
+ }
+
+ out << fieldName;
+ visitChildren = false;
}
- visitChildren = false;
- }
- break;
-
- case EOpAdd:
- writeTriplet(visit, "(", " + ", ")");
- break;
- case EOpSub:
- writeTriplet(visit, "(", " - ", ")");
- break;
- case EOpMul:
- writeTriplet(visit, "(", " * ", ")");
- break;
- case EOpDiv:
- writeTriplet(visit, "(", " / ", ")");
- break;
- case EOpIMod:
- writeTriplet(visit, "(", " % ", ")");
- break;
- case EOpBitShiftLeft:
- writeTriplet(visit, "(", " << ", ")");
- break;
- case EOpBitShiftRight:
- writeTriplet(visit, "(", " >> ", ")");
- break;
- case EOpBitwiseAnd:
- writeTriplet(visit, "(", " & ", ")");
- break;
- case EOpBitwiseXor:
- writeTriplet(visit, "(", " ^ ", ")");
- break;
- case EOpBitwiseOr:
- writeTriplet(visit, "(", " | ", ")");
- break;
-
- case EOpEqual:
- writeTriplet(visit, "(", " == ", ")");
- break;
- case EOpNotEqual:
- writeTriplet(visit, "(", " != ", ")");
- break;
- case EOpLessThan:
- writeTriplet(visit, "(", " < ", ")");
- break;
- case EOpGreaterThan:
- writeTriplet(visit, "(", " > ", ")");
- break;
- case EOpLessThanEqual:
- writeTriplet(visit, "(", " <= ", ")");
- break;
- case EOpGreaterThanEqual:
- writeTriplet(visit, "(", " >= ", ")");
- break;
-
- // Notice the fall-through.
- case EOpVectorTimesScalar:
- case EOpVectorTimesMatrix:
- case EOpMatrixTimesVector:
- case EOpMatrixTimesScalar:
- case EOpMatrixTimesMatrix:
- writeTriplet(visit, "(", " * ", ")");
- break;
-
- case EOpLogicalOr:
- writeTriplet(visit, "(", " || ", ")");
- break;
- case EOpLogicalXor:
- writeTriplet(visit, "(", " ^^ ", ")");
- break;
- case EOpLogicalAnd:
- writeTriplet(visit, "(", " && ", ")");
- break;
- default:
- UNREACHABLE();
+ break;
+
+ case EOpAdd:
+ writeTriplet(visit, "(", " + ", ")");
+ break;
+ case EOpSub:
+ writeTriplet(visit, "(", " - ", ")");
+ break;
+ case EOpMul:
+ writeTriplet(visit, "(", " * ", ")");
+ break;
+ case EOpDiv:
+ writeTriplet(visit, "(", " / ", ")");
+ break;
+ case EOpIMod:
+ writeTriplet(visit, "(", " % ", ")");
+ break;
+ case EOpBitShiftLeft:
+ writeTriplet(visit, "(", " << ", ")");
+ break;
+ case EOpBitShiftRight:
+ writeTriplet(visit, "(", " >> ", ")");
+ break;
+ case EOpBitwiseAnd:
+ writeTriplet(visit, "(", " & ", ")");
+ break;
+ case EOpBitwiseXor:
+ writeTriplet(visit, "(", " ^ ", ")");
+ break;
+ case EOpBitwiseOr:
+ writeTriplet(visit, "(", " | ", ")");
+ break;
+
+ case EOpEqual:
+ writeTriplet(visit, "(", " == ", ")");
+ break;
+ case EOpNotEqual:
+ writeTriplet(visit, "(", " != ", ")");
+ break;
+ case EOpLessThan:
+ writeTriplet(visit, "(", " < ", ")");
+ break;
+ case EOpGreaterThan:
+ writeTriplet(visit, "(", " > ", ")");
+ break;
+ case EOpLessThanEqual:
+ writeTriplet(visit, "(", " <= ", ")");
+ break;
+ case EOpGreaterThanEqual:
+ writeTriplet(visit, "(", " >= ", ")");
+ break;
+
+ // Notice the fall-through.
+ case EOpVectorTimesScalar:
+ case EOpVectorTimesMatrix:
+ case EOpMatrixTimesVector:
+ case EOpMatrixTimesScalar:
+ case EOpMatrixTimesMatrix:
+ writeTriplet(visit, "(", " * ", ")");
+ break;
+
+ case EOpLogicalOr:
+ writeTriplet(visit, "(", " || ", ")");
+ break;
+ case EOpLogicalXor:
+ writeTriplet(visit, "(", " ^^ ", ")");
+ break;
+ case EOpLogicalAnd:
+ writeTriplet(visit, "(", " && ", ")");
+ break;
+ default:
+ UNREACHABLE();
}
return visitChildren;
@@ -529,237 +696,148 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node)
switch (node->getOp())
{
- case EOpNegative: preString = "(-"; break;
- case EOpPositive: preString = "(+"; break;
- case EOpVectorLogicalNot: preString = "not("; break;
- case EOpLogicalNot: preString = "(!"; break;
- case EOpBitwiseNot: preString = "(~"; break;
-
- case EOpPostIncrement: preString = "("; postString = "++)"; break;
- case EOpPostDecrement: preString = "("; postString = "--)"; break;
- case EOpPreIncrement: preString = "(++"; break;
- case EOpPreDecrement: preString = "(--"; break;
-
- case EOpRadians:
- preString = "radians(";
- break;
- case EOpDegrees:
- preString = "degrees(";
- break;
- case EOpSin:
- preString = "sin(";
- break;
- case EOpCos:
- preString = "cos(";
- break;
- case EOpTan:
- preString = "tan(";
- break;
- case EOpAsin:
- preString = "asin(";
- break;
- case EOpAcos:
- preString = "acos(";
- break;
- case EOpAtan:
- preString = "atan(";
- break;
-
- case EOpSinh:
- preString = "sinh(";
- break;
- case EOpCosh:
- preString = "cosh(";
- break;
- case EOpTanh:
- preString = "tanh(";
- break;
- case EOpAsinh:
- preString = "asinh(";
- break;
- case EOpAcosh:
- preString = "acosh(";
- break;
- case EOpAtanh:
- preString = "atanh(";
- break;
-
- case EOpExp:
- preString = "exp(";
- break;
- case EOpLog:
- preString = "log(";
- break;
- case EOpExp2:
- preString = "exp2(";
- break;
- case EOpLog2:
- preString = "log2(";
- break;
- case EOpSqrt:
- preString = "sqrt(";
- break;
- case EOpInverseSqrt:
- preString = "inversesqrt(";
- break;
-
- case EOpAbs:
- preString = "abs(";
- break;
- case EOpSign:
- preString = "sign(";
- break;
- case EOpFloor:
- preString = "floor(";
- break;
- case EOpTrunc:
- preString = "trunc(";
- break;
- case EOpRound:
- preString = "round(";
- break;
- case EOpRoundEven:
- preString = "roundEven(";
- break;
- case EOpCeil:
- preString = "ceil(";
- break;
- case EOpFract:
- preString = "fract(";
- break;
- case EOpIsNan:
- preString = "isnan(";
- break;
- case EOpIsInf:
- preString = "isinf(";
- break;
-
- case EOpFloatBitsToInt:
- preString = "floatBitsToInt(";
- break;
- case EOpFloatBitsToUint:
- preString = "floatBitsToUint(";
- break;
- case EOpIntBitsToFloat:
- preString = "intBitsToFloat(";
- break;
- case EOpUintBitsToFloat:
- preString = "uintBitsToFloat(";
- break;
-
- case EOpPackSnorm2x16:
- preString = "packSnorm2x16(";
- break;
- case EOpPackUnorm2x16:
- preString = "packUnorm2x16(";
- break;
- case EOpPackHalf2x16:
- preString = "packHalf2x16(";
- break;
- case EOpUnpackSnorm2x16:
- preString = "unpackSnorm2x16(";
- break;
- case EOpUnpackUnorm2x16:
- preString = "unpackUnorm2x16(";
- break;
- case EOpUnpackHalf2x16:
- preString = "unpackHalf2x16(";
- break;
-
- case EOpLength:
- preString = "length(";
- break;
- case EOpNormalize:
- preString = "normalize(";
- break;
-
- case EOpDFdx:
- preString = "dFdx(";
- break;
- case EOpDFdy:
- preString = "dFdy(";
- break;
- case EOpFwidth:
- preString = "fwidth(";
- break;
-
- case EOpTranspose:
- preString = "transpose(";
- break;
- case EOpDeterminant:
- preString = "determinant(";
- break;
- case EOpInverse:
- preString = "inverse(";
- break;
-
- case EOpAny:
- preString = "any(";
- break;
- case EOpAll:
- preString = "all(";
- break;
-
- default:
- UNREACHABLE();
+ case EOpNegative:
+ preString = "(-";
+ break;
+ case EOpPositive:
+ preString = "(+";
+ break;
+ case EOpLogicalNot:
+ preString = "(!";
+ break;
+ case EOpBitwiseNot:
+ preString = "(~";
+ break;
+
+ case EOpPostIncrement:
+ preString = "(";
+ postString = "++)";
+ break;
+ case EOpPostDecrement:
+ preString = "(";
+ postString = "--)";
+ break;
+ case EOpPreIncrement:
+ preString = "(++";
+ break;
+ case EOpPreDecrement:
+ preString = "(--";
+ break;
+ case EOpArrayLength:
+ preString = "((";
+ postString = ").length())";
+ break;
+
+ case EOpRadians:
+ case EOpDegrees:
+ case EOpSin:
+ case EOpCos:
+ case EOpTan:
+ case EOpAsin:
+ case EOpAcos:
+ case EOpAtan:
+ case EOpSinh:
+ case EOpCosh:
+ case EOpTanh:
+ case EOpAsinh:
+ case EOpAcosh:
+ case EOpAtanh:
+ case EOpExp:
+ case EOpLog:
+ case EOpExp2:
+ case EOpLog2:
+ case EOpSqrt:
+ case EOpInverseSqrt:
+ case EOpAbs:
+ case EOpSign:
+ case EOpFloor:
+ case EOpTrunc:
+ case EOpRound:
+ case EOpRoundEven:
+ case EOpCeil:
+ case EOpFract:
+ case EOpIsNan:
+ case EOpIsInf:
+ case EOpFloatBitsToInt:
+ case EOpFloatBitsToUint:
+ case EOpIntBitsToFloat:
+ case EOpUintBitsToFloat:
+ case EOpPackSnorm2x16:
+ case EOpPackUnorm2x16:
+ case EOpPackHalf2x16:
+ case EOpUnpackSnorm2x16:
+ case EOpUnpackUnorm2x16:
+ case EOpUnpackHalf2x16:
+ case EOpPackUnorm4x8:
+ case EOpPackSnorm4x8:
+ case EOpUnpackUnorm4x8:
+ case EOpUnpackSnorm4x8:
+ case EOpLength:
+ case EOpNormalize:
+ case EOpDFdx:
+ case EOpDFdy:
+ case EOpFwidth:
+ case EOpTranspose:
+ case EOpDeterminant:
+ case EOpInverse:
+ case EOpAny:
+ case EOpAll:
+ case EOpLogicalNotComponentWise:
+ case EOpBitfieldReverse:
+ case EOpBitCount:
+ case EOpFindLSB:
+ case EOpFindMSB:
+ writeBuiltInFunctionTriplet(visit, node->getOp(), node->getUseEmulatedFunction());
+ return true;
+ default:
+ UNREACHABLE();
}
- if (visit == PreVisit && node->getUseEmulatedFunction())
- preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preString);
- writeTriplet(visit, preString.c_str(), NULL, postString.c_str());
+ writeTriplet(visit, preString.c_str(), nullptr, postString.c_str());
return true;
}
-bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection *node)
+bool TOutputGLSLBase::visitTernary(Visit visit, TIntermTernary *node)
{
TInfoSinkBase &out = objSink();
+ // Notice two brackets at the beginning and end. The outer ones
+ // encapsulate the whole ternary expression. This preserves the
+ // order of precedence when ternary expressions are used in a
+ // compound expression, i.e., c = 2 * (a < b ? 1 : 2).
+ out << "((";
+ node->getCondition()->traverse(this);
+ out << ") ? (";
+ node->getTrueExpression()->traverse(this);
+ out << ") : (";
+ node->getFalseExpression()->traverse(this);
+ out << "))";
+ return false;
+}
- if (node->usesTernaryOperator())
- {
- // Notice two brackets at the beginning and end. The outer ones
- // encapsulate the whole ternary expression. This preserves the
- // order of precedence when ternary expressions are used in a
- // compound expression, i.e., c = 2 * (a < b ? 1 : 2).
- out << "((";
- node->getCondition()->traverse(this);
- out << ") ? (";
- node->getTrueBlock()->traverse(this);
- out << ") : (";
- node->getFalseBlock()->traverse(this);
- out << "))";
- }
- else
- {
- out << "if (";
- node->getCondition()->traverse(this);
- out << ")\n";
+bool TOutputGLSLBase::visitIfElse(Visit visit, TIntermIfElse *node)
+{
+ TInfoSinkBase &out = objSink();
- incrementDepth(node);
- visitCodeBlock(node->getTrueBlock());
+ out << "if (";
+ node->getCondition()->traverse(this);
+ out << ")\n";
- if (node->getFalseBlock())
- {
- out << "else\n";
- visitCodeBlock(node->getFalseBlock());
- }
- decrementDepth();
+ visitCodeBlock(node->getTrueBlock());
+
+ if (node->getFalseBlock())
+ {
+ out << "else\n";
+ visitCodeBlock(node->getFalseBlock());
}
return false;
}
bool TOutputGLSLBase::visitSwitch(Visit visit, TIntermSwitch *node)
{
- if (node->getStatementList())
- {
- writeTriplet(visit, "switch (", ") ", nullptr);
- // The curly braces get written when visiting the statementList aggregate
- }
- else
- {
- // No statementList, so it won't output curly braces
- writeTriplet(visit, "switch (", ") {", "}\n");
- }
+ ASSERT(node->getStatementList());
+ writeTriplet(visit, "switch (", ") ", nullptr);
+ // The curly braces get written when visiting the statementList aggregate
return true;
}
@@ -778,369 +856,208 @@ bool TOutputGLSLBase::visitCase(Visit visit, TIntermCase *node)
}
}
-bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
+bool TOutputGLSLBase::visitBlock(Visit visit, TIntermBlock *node)
{
- bool visitChildren = true;
TInfoSinkBase &out = objSink();
- bool useEmulatedFunction = (visit == PreVisit && node->getUseEmulatedFunction());
- switch (node->getOp())
+ // Scope the blocks except when at the global scope.
+ if (mDepth > 0)
{
- case EOpSequence:
- // Scope the sequences except when at the global scope.
- if (mDepth > 0)
- {
- out << "{\n";
- }
+ out << "{\n";
+ }
- incrementDepth(node);
- for (TIntermSequence::const_iterator iter = node->getSequence()->begin();
- iter != node->getSequence()->end(); ++iter)
- {
- TIntermNode *curNode = *iter;
- ASSERT(curNode != NULL);
- curNode->traverse(this);
+ for (TIntermSequence::const_iterator iter = node->getSequence()->begin();
+ iter != node->getSequence()->end(); ++iter)
+ {
+ TIntermNode *curNode = *iter;
+ ASSERT(curNode != nullptr);
+ curNode->traverse(this);
- if (isSingleStatement(curNode))
- out << ";\n";
- }
- decrementDepth();
+ if (isSingleStatement(curNode))
+ out << ";\n";
+ }
- // Scope the sequences except when at the global scope.
- if (mDepth > 0)
- {
- out << "}\n";
- }
- visitChildren = false;
- break;
- case EOpPrototype:
- // Function declaration.
- ASSERT(visit == PreVisit);
- {
- const TType &type = node->getType();
- writeVariableType(type);
- if (type.isArray())
- out << arrayBrackets(type);
- }
+ // Scope the blocks except when at the global scope.
+ if (mDepth > 0)
+ {
+ out << "}\n";
+ }
+ return false;
+}
- out << " " << hashFunctionNameIfNeeded(node->getNameObj());
+bool TOutputGLSLBase::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
+{
+ TIntermFunctionPrototype *prototype = node->getFunctionPrototype();
+ prototype->traverse(this);
+ visitCodeBlock(node->getBody());
- out << "(";
- writeFunctionParameters(*(node->getSequence()));
- out << ")";
+ // Fully processed; no need to visit children.
+ return false;
+}
- visitChildren = false;
- break;
- case EOpFunction: {
- // Function definition.
- ASSERT(visit == PreVisit);
- {
- const TType &type = node->getType();
- writeVariableType(type);
- if (type.isArray())
- out << arrayBrackets(type);
- }
+bool TOutputGLSLBase::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node)
+{
+ TInfoSinkBase &out = objSink();
+ ASSERT(visit == PreVisit);
+ const TIntermSymbol *symbol = node->getSymbol();
+ out << "invariant " << hashVariableName(symbol->getName());
+ return false;
+}
+
+bool TOutputGLSLBase::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node)
+{
+ TInfoSinkBase &out = objSink();
+ ASSERT(visit == PreVisit);
- out << " " << hashFunctionNameIfNeeded(node->getNameObj());
+ const TType &type = node->getType();
+ writeVariableType(type);
+ if (type.isArray())
+ out << ArrayString(type);
+
+ out << " " << hashFunctionNameIfNeeded(*node->getFunctionSymbolInfo());
+
+ out << "(";
+ writeFunctionParameters(*(node->getSequence()));
+ out << ")";
+
+ return false;
+}
+
+bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+ bool visitChildren = true;
+ TInfoSinkBase &out = objSink();
+ switch (node->getOp())
+ {
+ case EOpCallFunctionInAST:
+ case EOpCallInternalRawFunction:
+ case EOpCallBuiltInFunction:
+ // Function call.
+ if (visit == PreVisit)
+ {
+ if (node->getOp() == EOpCallBuiltInFunction)
+ {
+ out << translateTextureFunction(node->getFunctionSymbolInfo()->getName());
+ }
+ else
+ {
+ out << hashFunctionNameIfNeeded(*node->getFunctionSymbolInfo());
+ }
+ out << "(";
+ }
+ else if (visit == InVisit)
+ out << ", ";
+ else
+ out << ")";
+ break;
+ case EOpConstruct:
+ writeConstructorTriplet(visit, node->getType());
+ break;
- incrementDepth(node);
- // Function definition node contains one or two children nodes
- // representing function parameters and function body. The latter
- // is not present in case of empty function bodies.
+ case EOpEqualComponentWise:
+ case EOpNotEqualComponentWise:
+ case EOpLessThanComponentWise:
+ case EOpGreaterThanComponentWise:
+ case EOpLessThanEqualComponentWise:
+ case EOpGreaterThanEqualComponentWise:
+ case EOpMod:
+ case EOpModf:
+ case EOpPow:
+ case EOpAtan:
+ case EOpMin:
+ case EOpMax:
+ case EOpClamp:
+ case EOpMix:
+ case EOpStep:
+ case EOpSmoothStep:
+ case EOpFrexp:
+ case EOpLdexp:
+ case EOpDistance:
+ case EOpDot:
+ case EOpCross:
+ case EOpFaceforward:
+ case EOpReflect:
+ case EOpRefract:
+ case EOpMulMatrixComponentWise:
+ case EOpOuterProduct:
+ case EOpBitfieldExtract:
+ case EOpBitfieldInsert:
+ case EOpUaddCarry:
+ case EOpUsubBorrow:
+ case EOpUmulExtended:
+ case EOpImulExtended:
+ case EOpBarrier:
+ case EOpMemoryBarrier:
+ case EOpMemoryBarrierAtomicCounter:
+ case EOpMemoryBarrierBuffer:
+ case EOpMemoryBarrierImage:
+ case EOpMemoryBarrierShared:
+ case EOpGroupMemoryBarrier:
+ case EOpEmitVertex:
+ case EOpEndPrimitive:
+ writeBuiltInFunctionTriplet(visit, node->getOp(), node->getUseEmulatedFunction());
+ break;
+ default:
+ UNREACHABLE();
+ }
+ return visitChildren;
+}
+
+bool TOutputGLSLBase::visitDeclaration(Visit visit, TIntermDeclaration *node)
+{
+ TInfoSinkBase &out = objSink();
+
+ // Variable declaration.
+ if (visit == PreVisit)
+ {
const TIntermSequence &sequence = *(node->getSequence());
- ASSERT((sequence.size() == 1) || (sequence.size() == 2));
- TIntermSequence::const_iterator seqIter = sequence.begin();
-
- // Traverse function parameters.
- TIntermAggregate *params = (*seqIter)->getAsAggregate();
- ASSERT(params != NULL);
- ASSERT(params->getOp() == EOpParameters);
- params->traverse(this);
-
- // Traverse function body.
- TIntermAggregate *body = ++seqIter != sequence.end() ?
- (*seqIter)->getAsAggregate() : NULL;
- visitCodeBlock(body);
- decrementDepth();
-
- // Fully processed; no need to visit children.
- visitChildren = false;
- break;
- }
- case EOpFunctionCall:
- // Function call.
- if (visit == PreVisit)
- out << hashFunctionNameIfNeeded(node->getNameObj()) << "(";
- else if (visit == InVisit)
- out << ", ";
- else
- out << ")";
- break;
- case EOpParameters:
- // Function parameters.
- ASSERT(visit == PreVisit);
- out << "(";
- writeFunctionParameters(*(node->getSequence()));
- out << ")";
- visitChildren = false;
- break;
- case EOpDeclaration:
- // Variable declaration.
- if (visit == PreVisit)
+ TIntermTyped *variable = sequence.front()->getAsTyped();
+ writeLayoutQualifier(variable);
+ writeVariableType(variable->getType());
+ if (variable->getAsSymbolNode() == nullptr ||
+ !variable->getAsSymbolNode()->getSymbol().empty())
{
- const TIntermSequence &sequence = *(node->getSequence());
- const TIntermTyped *variable = sequence.front()->getAsTyped();
- writeLayoutQualifier(variable->getType());
- writeVariableType(variable->getType());
out << " ";
- mDeclaringVariables = true;
- }
- else if (visit == InVisit)
- {
- out << ", ";
- mDeclaringVariables = true;
- }
- else
- {
- mDeclaringVariables = false;
- }
- break;
- case EOpInvariantDeclaration:
- // Invariant declaration.
- ASSERT(visit == PreVisit);
- {
- const TIntermSequence *sequence = node->getSequence();
- ASSERT(sequence && sequence->size() == 1);
- const TIntermSymbol *symbol = sequence->front()->getAsSymbolNode();
- ASSERT(symbol);
- out << "invariant " << hashVariableName(symbol->getSymbol());
- }
- visitChildren = false;
- break;
- case EOpConstructFloat:
- writeConstructorTriplet(visit, node->getType(), "float");
- break;
- case EOpConstructVec2:
- writeConstructorTriplet(visit, node->getType(), "vec2");
- break;
- case EOpConstructVec3:
- writeConstructorTriplet(visit, node->getType(), "vec3");
- break;
- case EOpConstructVec4:
- writeConstructorTriplet(visit, node->getType(), "vec4");
- break;
- case EOpConstructBool:
- writeConstructorTriplet(visit, node->getType(), "bool");
- break;
- case EOpConstructBVec2:
- writeConstructorTriplet(visit, node->getType(), "bvec2");
- break;
- case EOpConstructBVec3:
- writeConstructorTriplet(visit, node->getType(), "bvec3");
- break;
- case EOpConstructBVec4:
- writeConstructorTriplet(visit, node->getType(), "bvec4");
- break;
- case EOpConstructInt:
- writeConstructorTriplet(visit, node->getType(), "int");
- break;
- case EOpConstructIVec2:
- writeConstructorTriplet(visit, node->getType(), "ivec2");
- break;
- case EOpConstructIVec3:
- writeConstructorTriplet(visit, node->getType(), "ivec3");
- break;
- case EOpConstructIVec4:
- writeConstructorTriplet(visit, node->getType(), "ivec4");
- break;
- case EOpConstructUInt:
- writeConstructorTriplet(visit, node->getType(), "uint");
- break;
- case EOpConstructUVec2:
- writeConstructorTriplet(visit, node->getType(), "uvec2");
- break;
- case EOpConstructUVec3:
- writeConstructorTriplet(visit, node->getType(), "uvec3");
- break;
- case EOpConstructUVec4:
- writeConstructorTriplet(visit, node->getType(), "uvec4");
- break;
- case EOpConstructMat2:
- writeConstructorTriplet(visit, node->getType(), "mat2");
- break;
- case EOpConstructMat2x3:
- writeConstructorTriplet(visit, node->getType(), "mat2x3");
- break;
- case EOpConstructMat2x4:
- writeConstructorTriplet(visit, node->getType(), "mat2x4");
- break;
- case EOpConstructMat3x2:
- writeConstructorTriplet(visit, node->getType(), "mat3x2");
- break;
- case EOpConstructMat3:
- writeConstructorTriplet(visit, node->getType(), "mat3");
- break;
- case EOpConstructMat3x4:
- writeConstructorTriplet(visit, node->getType(), "mat3x4");
- break;
- case EOpConstructMat4x2:
- writeConstructorTriplet(visit, node->getType(), "mat4x2");
- break;
- case EOpConstructMat4x3:
- writeConstructorTriplet(visit, node->getType(), "mat4x3");
- break;
- case EOpConstructMat4:
- writeConstructorTriplet(visit, node->getType(), "mat4");
- break;
- case EOpConstructStruct:
- {
- const TType &type = node->getType();
- ASSERT(type.getBasicType() == EbtStruct);
- TString constructorName = hashName(type.getStruct()->name());
- writeConstructorTriplet(visit, node->getType(), constructorName.c_str());
- break;
}
-
- case EOpOuterProduct:
- writeBuiltInFunctionTriplet(visit, "outerProduct(", useEmulatedFunction);
- break;
-
- case EOpLessThan:
- writeBuiltInFunctionTriplet(visit, "lessThan(", useEmulatedFunction);
- break;
- case EOpGreaterThan:
- writeBuiltInFunctionTriplet(visit, "greaterThan(", useEmulatedFunction);
- break;
- case EOpLessThanEqual:
- writeBuiltInFunctionTriplet(visit, "lessThanEqual(", useEmulatedFunction);
- break;
- case EOpGreaterThanEqual:
- writeBuiltInFunctionTriplet(visit, "greaterThanEqual(", useEmulatedFunction);
- break;
- case EOpVectorEqual:
- writeBuiltInFunctionTriplet(visit, "equal(", useEmulatedFunction);
- break;
- case EOpVectorNotEqual:
- writeBuiltInFunctionTriplet(visit, "notEqual(", useEmulatedFunction);
- break;
- case EOpComma:
- writeTriplet(visit, "(", ", ", ")");
- break;
-
- case EOpMod:
- writeBuiltInFunctionTriplet(visit, "mod(", useEmulatedFunction);
- break;
- case EOpModf:
- writeBuiltInFunctionTriplet(visit, "modf(", useEmulatedFunction);
- break;
- case EOpPow:
- writeBuiltInFunctionTriplet(visit, "pow(", useEmulatedFunction);
- break;
- case EOpAtan:
- writeBuiltInFunctionTriplet(visit, "atan(", useEmulatedFunction);
- break;
- case EOpMin:
- writeBuiltInFunctionTriplet(visit, "min(", useEmulatedFunction);
- break;
- case EOpMax:
- writeBuiltInFunctionTriplet(visit, "max(", useEmulatedFunction);
- break;
- case EOpClamp:
- writeBuiltInFunctionTriplet(visit, "clamp(", useEmulatedFunction);
- break;
- case EOpMix:
- writeBuiltInFunctionTriplet(visit, "mix(", useEmulatedFunction);
- break;
- case EOpStep:
- writeBuiltInFunctionTriplet(visit, "step(", useEmulatedFunction);
- break;
- case EOpSmoothStep:
- writeBuiltInFunctionTriplet(visit, "smoothstep(", useEmulatedFunction);
- break;
- case EOpDistance:
- writeBuiltInFunctionTriplet(visit, "distance(", useEmulatedFunction);
- break;
- case EOpDot:
- writeBuiltInFunctionTriplet(visit, "dot(", useEmulatedFunction);
- break;
- case EOpCross:
- writeBuiltInFunctionTriplet(visit, "cross(", useEmulatedFunction);
- break;
- case EOpFaceForward:
- writeBuiltInFunctionTriplet(visit, "faceforward(", useEmulatedFunction);
- break;
- case EOpReflect:
- writeBuiltInFunctionTriplet(visit, "reflect(", useEmulatedFunction);
- break;
- case EOpRefract:
- writeBuiltInFunctionTriplet(visit, "refract(", useEmulatedFunction);
- break;
- case EOpMul:
- writeBuiltInFunctionTriplet(visit, "matrixCompMult(", useEmulatedFunction);
- break;
-
- default:
+ mDeclaringVariable = true;
+ }
+ else if (visit == InVisit)
+ {
UNREACHABLE();
}
- return visitChildren;
+ else
+ {
+ mDeclaringVariable = false;
+ }
+ return true;
}
bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node)
{
TInfoSinkBase &out = objSink();
- incrementDepth(node);
-
TLoopType loopType = node->getType();
- // Only for loops can be unrolled
- ASSERT(!node->getUnrollFlag() || loopType == ELoopFor);
-
if (loopType == ELoopFor) // for loop
{
- if (!node->getUnrollFlag())
- {
- out << "for (";
- if (node->getInit())
- node->getInit()->traverse(this);
- out << "; ";
+ out << "for (";
+ if (node->getInit())
+ node->getInit()->traverse(this);
+ out << "; ";
- if (node->getCondition())
- node->getCondition()->traverse(this);
- out << "; ";
+ if (node->getCondition())
+ node->getCondition()->traverse(this);
+ out << "; ";
- if (node->getExpression())
- node->getExpression()->traverse(this);
- out << ")\n";
+ if (node->getExpression())
+ node->getExpression()->traverse(this);
+ out << ")\n";
- visitCodeBlock(node->getBody());
- }
- else
- {
- // Need to put a one-iteration loop here to handle break.
- TIntermSequence *declSeq =
- node->getInit()->getAsAggregate()->getSequence();
- TIntermSymbol *indexSymbol =
- (*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode();
- TString name = hashVariableName(indexSymbol->getSymbol());
- out << "for (int " << name << " = 0; "
- << name << " < 1; "
- << "++" << name << ")\n";
-
- out << "{\n";
- mLoopUnrollStack.push(node);
- while (mLoopUnrollStack.satisfiesLoopCondition())
- {
- visitCodeBlock(node->getBody());
- mLoopUnrollStack.step();
- }
- mLoopUnrollStack.pop();
- out << "}\n";
- }
+ visitCodeBlock(node->getBody());
}
else if (loopType == ELoopWhile) // while loop
{
out << "while (";
- ASSERT(node->getCondition() != NULL);
+ ASSERT(node->getCondition() != nullptr);
node->getCondition()->traverse(this);
out << ")\n";
@@ -1154,13 +1071,11 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node)
visitCodeBlock(node->getBody());
out << "while (";
- ASSERT(node->getCondition() != NULL);
+ ASSERT(node->getCondition() != nullptr);
node->getCondition()->traverse(this);
out << ");\n";
}
- decrementDepth();
-
// No need to visit children. They have been already processed in
// this function.
return false;
@@ -1170,29 +1085,29 @@ bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch *node)
{
switch (node->getFlowOp())
{
- case EOpKill:
- writeTriplet(visit, "discard", NULL, NULL);
- break;
- case EOpBreak:
- writeTriplet(visit, "break", NULL, NULL);
- break;
- case EOpContinue:
- writeTriplet(visit, "continue", NULL, NULL);
- break;
- case EOpReturn:
- writeTriplet(visit, "return ", NULL, NULL);
- break;
- default:
- UNREACHABLE();
+ case EOpKill:
+ writeTriplet(visit, "discard", nullptr, nullptr);
+ break;
+ case EOpBreak:
+ writeTriplet(visit, "break", nullptr, nullptr);
+ break;
+ case EOpContinue:
+ writeTriplet(visit, "continue", nullptr, nullptr);
+ break;
+ case EOpReturn:
+ writeTriplet(visit, "return ", nullptr, nullptr);
+ break;
+ default:
+ UNREACHABLE();
}
return true;
}
-void TOutputGLSLBase::visitCodeBlock(TIntermNode *node)
+void TOutputGLSLBase::visitCodeBlock(TIntermBlock *node)
{
TInfoSinkBase &out = objSink();
- if (node != NULL)
+ if (node != nullptr)
{
node->traverse(this);
// Single statements not part of a sequence need to be terminated
@@ -1208,76 +1123,41 @@ void TOutputGLSLBase::visitCodeBlock(TIntermNode *node)
TString TOutputGLSLBase::getTypeName(const TType &type)
{
- TInfoSinkBase out;
- if (type.isMatrix())
- {
- out << "mat";
- out << type.getNominalSize();
- if (type.getSecondarySize() != type.getNominalSize())
- {
- out << "x" << type.getSecondarySize();
- }
- }
- else if (type.isVector())
- {
- switch (type.getBasicType())
- {
- case EbtFloat:
- out << "vec";
- break;
- case EbtInt:
- out << "ivec";
- break;
- case EbtBool:
- out << "bvec";
- break;
- case EbtUInt:
- out << "uvec";
- break;
- default:
- UNREACHABLE();
- }
- out << type.getNominalSize();
- }
- else
- {
- if (type.getBasicType() == EbtStruct)
- out << hashName(type.getStruct()->name());
- else
- out << type.getBasicString();
- }
- return TString(out.c_str());
+ return GetTypeName(type, mHashFunction, &mNameMap);
}
-TString TOutputGLSLBase::hashName(const TString &name)
+TString TOutputGLSLBase::hashName(const TName &name)
{
- if (mHashFunction == NULL || name.empty())
- return name;
- NameMap::const_iterator it = mNameMap.find(name.c_str());
- if (it != mNameMap.end())
- return it->second.c_str();
- TString hashedName = TIntermTraverser::hash(name, mHashFunction);
- mNameMap[name.c_str()] = hashedName.c_str();
- return hashedName;
+ return HashName(name, mHashFunction, &mNameMap);
}
-TString TOutputGLSLBase::hashVariableName(const TString &name)
+TString TOutputGLSLBase::hashVariableName(const TName &name)
{
- if (mSymbolTable.findBuiltIn(name, mShaderVersion) != NULL)
- return name;
+ if (mSymbolTable->findBuiltIn(name.getString(), mShaderVersion) != nullptr ||
+ name.getString().substr(0, 3) == "gl_")
+ {
+ if (mCompileOptions & SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM &&
+ name.getString() == "gl_ViewID_OVR")
+ {
+ TName uniformName(TString("ViewID_OVR"));
+ uniformName.setInternal(true);
+ return hashName(uniformName);
+ }
+ return name.getString();
+ }
return hashName(name);
}
-TString TOutputGLSLBase::hashFunctionNameIfNeeded(const TName &mangledName)
+TString TOutputGLSLBase::hashFunctionNameIfNeeded(const TFunctionSymbolInfo &info)
{
- TString mangledStr = mangledName.getString();
- TString name = TFunction::unmangleName(mangledStr);
- if (mSymbolTable.findBuiltIn(mangledStr, mShaderVersion) != nullptr || name == "main")
- return translateTextureFunction(name);
- if (mangledName.isInternal())
- return name;
+ if (info.isMain())
+ {
+ return info.getName();
+ }
else
- return hashName(name);
+ {
+ return hashName(info.getNameObj());
+ }
}
bool TOutputGLSLBase::structDeclared(const TStructure *structure) const
@@ -1295,16 +1175,16 @@ void TOutputGLSLBase::declareStruct(const TStructure *structure)
{
TInfoSinkBase &out = objSink();
- out << "struct " << hashName(structure->name()) << "{\n";
+ out << "struct " << hashName(TName(structure->name())) << "{\n";
const TFieldList &fields = structure->fields();
for (size_t i = 0; i < fields.size(); ++i)
{
const TField *field = fields[i];
if (writeVariablePrecision(field->type()->getPrecision()))
out << " ";
- out << getTypeName(*field->type()) << " " << hashName(field->name());
+ out << getTypeName(*field->type()) << " " << hashName(TName(field->name()));
if (field->type()->isArray())
- out << arrayBrackets(*field->type());
+ out << ArrayString(*field->type());
out << ";\n";
}
out << "}";
@@ -1332,6 +1212,10 @@ void TOutputGLSLBase::declareInterfaceBlockLayout(const TInterfaceBlock *interfa
out << "std140";
break;
+ case EbsStd430:
+ out << "std430";
+ break;
+
default:
UNREACHABLE();
break;
@@ -1339,6 +1223,12 @@ void TOutputGLSLBase::declareInterfaceBlockLayout(const TInterfaceBlock *interfa
out << ", ";
+ if (interfaceBlock->blockBinding() > 0)
+ {
+ out << "binding = " << interfaceBlock->blockBinding();
+ out << ", ";
+ }
+
switch (interfaceBlock->matrixPacking())
{
case EmpUnspecified:
@@ -1363,17 +1253,105 @@ void TOutputGLSLBase::declareInterfaceBlock(const TInterfaceBlock *interfaceBloc
{
TInfoSinkBase &out = objSink();
- out << hashName(interfaceBlock->name()) << "{\n";
+ out << hashName(TName(interfaceBlock->name())) << "{\n";
const TFieldList &fields = interfaceBlock->fields();
for (size_t i = 0; i < fields.size(); ++i)
{
const TField *field = fields[i];
if (writeVariablePrecision(field->type()->getPrecision()))
out << " ";
- out << getTypeName(*field->type()) << " " << hashName(field->name());
+ out << getTypeName(*field->type()) << " " << hashName(TName(field->name()));
if (field->type()->isArray())
- out << arrayBrackets(*field->type());
+ out << ArrayString(*field->type());
out << ";\n";
}
out << "}";
}
+
+void WriteGeometryShaderLayoutQualifiers(TInfoSinkBase &out,
+ sh::TLayoutPrimitiveType inputPrimitive,
+ int invocations,
+ sh::TLayoutPrimitiveType outputPrimitive,
+ int maxVertices)
+{
+ // Omit 'invocations = 1'
+ if (inputPrimitive != EptUndefined || invocations > 1)
+ {
+ out << "layout (";
+
+ if (inputPrimitive != EptUndefined)
+ {
+ out << getGeometryShaderPrimitiveTypeString(inputPrimitive);
+ }
+
+ if (invocations > 1)
+ {
+ if (inputPrimitive != EptUndefined)
+ {
+ out << ", ";
+ }
+ out << "invocations = " << invocations;
+ }
+ out << ") in;\n";
+ }
+
+ if (outputPrimitive != EptUndefined || maxVertices != -1)
+ {
+ out << "layout (";
+
+ if (outputPrimitive != EptUndefined)
+ {
+ out << getGeometryShaderPrimitiveTypeString(outputPrimitive);
+ }
+
+ if (maxVertices != -1)
+ {
+ if (outputPrimitive != EptUndefined)
+ {
+ out << ", ";
+ }
+ out << "max_vertices = " << maxVertices;
+ }
+ out << ") out;\n";
+ }
+}
+
+// If SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS is enabled, layout qualifiers are spilled whenever
+// variables with specified layout qualifiers are copied. Additional checks are needed against the
+// type and storage qualifier of the variable to verify that layout qualifiers have to be outputted.
+// TODO (mradev): Fix layout qualifier spilling in ScalarizeVecAndMatConstructorArgs and remove
+// NeedsToWriteLayoutQualifier.
+bool NeedsToWriteLayoutQualifier(const TType &type)
+{
+ if (type.getBasicType() == EbtInterfaceBlock)
+ {
+ return false;
+ }
+
+ const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier();
+
+ if ((type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqVertexIn ||
+ IsVarying(type.getQualifier())) &&
+ layoutQualifier.location >= 0)
+ {
+ return true;
+ }
+
+ if (type.getQualifier() == EvqFragmentOut && layoutQualifier.yuv == true)
+ {
+ return true;
+ }
+
+ if (IsOpaqueType(type.getBasicType()) && layoutQualifier.binding != -1)
+ {
+ return true;
+ }
+
+ if (IsImage(type.getBasicType()) && layoutQualifier.imageInternalFormat != EiifUnspecified)
+ {
+ return true;
+ }
+ return false;
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h
index 2ae82d15b2..592a310be4 100644
--- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h
+++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h
@@ -9,9 +9,12 @@
#include <set>
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/LoopInfo.h"
-#include "compiler/translator/ParseContext.h"
+#include "compiler/translator/HashNames.h"
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
class TOutputGLSLBase : public TIntermTraverser
{
@@ -20,48 +23,58 @@ class TOutputGLSLBase : public TIntermTraverser
ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction,
NameMap &nameMap,
- TSymbolTable& symbolTable,
+ TSymbolTable *symbolTable,
+ sh::GLenum shaderType,
int shaderVersion,
- ShShaderOutput output);
+ ShShaderOutput output,
+ ShCompileOptions compileOptions);
+
+ ShShaderOutput getShaderOutput() const { return mOutput; }
- ShShaderOutput getShaderOutput() const
- {
- return mOutput;
- }
+ // Return the original name if hash function pointer is NULL;
+ // otherwise return the hashed name. Has special handling for internal names, which are not
+ // hashed.
+ TString hashName(const TName &name);
protected:
TInfoSinkBase &objSink() { return mObjSink; }
+ void writeFloat(TInfoSinkBase &out, float f);
void writeTriplet(Visit visit, const char *preStr, const char *inStr, const char *postStr);
- void writeLayoutQualifier(const TType &type);
+ virtual void writeLayoutQualifier(TIntermTyped *variable);
+ void writeInvariantQualifier(const TType &type);
void writeVariableType(const TType &type);
virtual bool writeVariablePrecision(TPrecision precision) = 0;
void writeFunctionParameters(const TIntermSequence &args);
const TConstantUnion *writeConstantUnion(const TType &type, const TConstantUnion *pConstUnion);
- void writeConstructorTriplet(Visit visit, const TType &type, const char *constructorBaseType);
+ void writeConstructorTriplet(Visit visit, const TType &type);
TString getTypeName(const TType &type);
void visitSymbol(TIntermSymbol *node) override;
void visitConstantUnion(TIntermConstantUnion *node) override;
+ bool visitSwizzle(Visit visit, TIntermSwizzle *node) override;
bool visitBinary(Visit visit, TIntermBinary *node) override;
bool visitUnary(Visit visit, TIntermUnary *node) override;
- bool visitSelection(Visit visit, TIntermSelection *node) override;
+ bool visitTernary(Visit visit, TIntermTernary *node) override;
+ bool visitIfElse(Visit visit, TIntermIfElse *node) override;
bool visitSwitch(Visit visit, TIntermSwitch *node) override;
bool visitCase(Visit visit, TIntermCase *node) override;
+ bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override;
+ bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
+ bool visitBlock(Visit visit, TIntermBlock *node) override;
+ bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override;
+ bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
bool visitLoop(Visit visit, TIntermLoop *node) override;
bool visitBranch(Visit visit, TIntermBranch *node) override;
- void visitCodeBlock(TIntermNode *node);
+ void visitCodeBlock(TIntermBlock *node);
- // Return the original name if hash function pointer is NULL;
- // otherwise return the hashed name.
- TString hashName(const TString &name);
// Same as hashName(), but without hashing built-in variables.
- TString hashVariableName(const TString &name);
- // Same as hashName(), but without hashing built-in functions and with unmangling.
- TString hashFunctionNameIfNeeded(const TName &mangledName);
+ TString hashVariableName(const TName &name);
+ // Same as hashName(), but without hashing internal functions or "main".
+ TString hashFunctionNameIfNeeded(const TFunctionSymbolInfo &info);
// Used to translate function names for differences between ESSL and GLSL
- virtual TString translateTextureFunction(TString &name) { return name; }
+ virtual TString translateTextureFunction(const TString &name) { return name; }
private:
bool structDeclared(const TStructure *structure) const;
@@ -70,17 +83,16 @@ class TOutputGLSLBase : public TIntermTraverser
void declareInterfaceBlockLayout(const TInterfaceBlock *interfaceBlock);
void declareInterfaceBlock(const TInterfaceBlock *interfaceBlock);
- void writeBuiltInFunctionTriplet(Visit visit, const char *preStr, bool useEmulatedFunction);
+ void writeBuiltInFunctionTriplet(Visit visit, TOperator op, bool useEmulatedFunction);
+
+ const char *mapQualifierToString(TQualifier qialifier);
TInfoSinkBase &mObjSink;
- bool mDeclaringVariables;
+ bool mDeclaringVariable;
// This set contains all the ids of the structs from every scope.
std::set<int> mDeclaredStructs;
- // Stack of loops that need to be unrolled.
- TLoopStack mLoopUnrollStack;
-
ShArrayIndexClampingStrategy mClampingStrategy;
// name hashing.
@@ -88,11 +100,23 @@ class TOutputGLSLBase : public TIntermTraverser
NameMap &mNameMap;
- TSymbolTable &mSymbolTable;
+ sh::GLenum mShaderType;
const int mShaderVersion;
ShShaderOutput mOutput;
+
+ ShCompileOptions mCompileOptions;
};
+void WriteGeometryShaderLayoutQualifiers(TInfoSinkBase &out,
+ sh::TLayoutPrimitiveType inputPrimitive,
+ int invocations,
+ sh::TLayoutPrimitiveType outputPrimitive,
+ int maxVertices);
+
+bool NeedsToWriteLayoutQualifier(const TType &type);
+
+} // namespace sh
+
#endif // COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp
index 253b96696c..d5ff761430 100644
--- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp
@@ -15,33 +15,95 @@
#include "common/utilities.h"
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
-#include "compiler/translator/FlagStd140Structs.h"
+#include "compiler/translator/ImageFunctionHLSL.h"
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/NodeSearch.h"
#include "compiler/translator/RemoveSwitchFallThrough.h"
#include "compiler/translator/SearchSymbol.h"
#include "compiler/translator/StructureHLSL.h"
+#include "compiler/translator/TextureFunctionHLSL.h"
#include "compiler/translator/TranslatorHLSL.h"
#include "compiler/translator/UniformHLSL.h"
#include "compiler/translator/UtilsHLSL.h"
#include "compiler/translator/blocklayout.h"
#include "compiler/translator/util.h"
+namespace sh
+{
+
namespace
{
-bool IsSequence(TIntermNode *node)
+TString ArrayHelperFunctionName(const char *prefix, const TType &type)
+{
+ TStringStream fnName;
+ fnName << prefix << "_";
+ if (type.isArray())
+ {
+ for (unsigned int arraySize : *type.getArraySizes())
+ {
+ fnName << arraySize << "_";
+ }
+ }
+ fnName << TypeString(type);
+ return fnName.str();
+}
+
+bool IsDeclarationWrittenOut(TIntermDeclaration *node)
+{
+ TIntermSequence *sequence = node->getSequence();
+ TIntermTyped *variable = (*sequence)[0]->getAsTyped();
+ ASSERT(sequence->size() == 1);
+ ASSERT(variable);
+ return (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal ||
+ variable->getQualifier() == EvqConst);
+}
+
+bool IsInStd140InterfaceBlock(TIntermTyped *node)
+{
+ TIntermBinary *binaryNode = node->getAsBinaryNode();
+
+ if (binaryNode)
+ {
+ return IsInStd140InterfaceBlock(binaryNode->getLeft());
+ }
+
+ const TType &type = node->getType();
+
+ // determine if we are in the standard layout
+ const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
+ if (interfaceBlock)
+ {
+ return (interfaceBlock->blockStorage() == EbsStd140);
+ }
+
+ return false;
+}
+
+} // anonymous namespace
+
+void OutputHLSL::writeFloat(TInfoSinkBase &out, float f)
{
- return node->getAsAggregate() != nullptr && node->getAsAggregate()->getOp() == EOpSequence;
+ // This is known not to work for NaN on all drivers but make the best effort to output NaNs
+ // regardless.
+ if ((gl::isInf(f) || gl::isNaN(f)) && mShaderVersion >= 300 &&
+ mOutputType == SH_HLSL_4_1_OUTPUT)
+ {
+ out << "asfloat(" << gl::bitCast<uint32_t>(f) << "u)";
+ }
+ else
+ {
+ out << std::min(FLT_MAX, std::max(-FLT_MAX, f));
+ }
}
-void WriteSingleConstant(TInfoSinkBase &out, const TConstantUnion *const constUnion)
+void OutputHLSL::writeSingleConstant(TInfoSinkBase &out, const TConstantUnion *const constUnion)
{
ASSERT(constUnion != nullptr);
switch (constUnion->getType())
{
case EbtFloat:
- out << std::min(FLT_MAX, std::max(-FLT_MAX, constUnion->getFConst()));
+ writeFloat(out, constUnion->getFConst());
break;
case EbtInt:
out << constUnion->getIConst();
@@ -57,14 +119,14 @@ void WriteSingleConstant(TInfoSinkBase &out, const TConstantUnion *const constUn
}
}
-const TConstantUnion *WriteConstantUnionArray(TInfoSinkBase &out,
- const TConstantUnion *const constUnion,
- const size_t size)
+const TConstantUnion *OutputHLSL::writeConstantUnionArray(TInfoSinkBase &out,
+ const TConstantUnion *const constUnion,
+ const size_t size)
{
const TConstantUnion *constUnionIterated = constUnion;
for (size_t i = 0; i < size; i++, constUnionIterated++)
{
- WriteSingleConstant(out, constUnionIterated);
+ writeSingleConstant(out, constUnionIterated);
if (i != size - 1)
{
@@ -74,71 +136,17 @@ const TConstantUnion *WriteConstantUnionArray(TInfoSinkBase &out,
return constUnionIterated;
}
-} // namespace
-
-namespace sh
-{
-
-TString OutputHLSL::TextureFunction::name() const
-{
- TString name = "gl_texture";
-
- // We need to include full the sampler type in the function name to make the signature unique
- // on D3D11, where samplers are passed to texture functions as indices.
- name += TextureTypeSuffix(this->sampler);
-
- if (proj)
- {
- name += "Proj";
- }
-
- if (offset)
- {
- name += "Offset";
- }
-
- switch(method)
- {
- case IMPLICIT: break;
- case BIAS: break; // Extra parameter makes the signature unique
- case LOD: name += "Lod"; break;
- case LOD0: name += "Lod0"; break;
- case LOD0BIAS: name += "Lod0"; break; // Extra parameter makes the signature unique
- case SIZE: name += "Size"; break;
- case FETCH: name += "Fetch"; break;
- case GRAD: name += "Grad"; break;
- default: UNREACHABLE();
- }
-
- return name + "(";
-}
-
-bool OutputHLSL::TextureFunction::operator<(const TextureFunction &rhs) const
-{
- if (sampler < rhs.sampler) return true;
- if (sampler > rhs.sampler) return false;
-
- if (coords < rhs.coords) return true;
- if (coords > rhs.coords) return false;
-
- if (!proj && rhs.proj) return true;
- if (proj && !rhs.proj) return false;
-
- if (!offset && rhs.offset) return true;
- if (offset && !rhs.offset) return false;
-
- if (method < rhs.method) return true;
- if (method > rhs.method) return false;
-
- return false;
-}
-
-OutputHLSL::OutputHLSL(sh::GLenum shaderType, int shaderVersion,
- const TExtensionBehavior &extensionBehavior,
- const char *sourcePath, ShShaderOutput outputType,
- int numRenderTargets, const std::vector<Uniform> &uniforms,
- int compileOptions)
- : TIntermTraverser(true, true, true),
+OutputHLSL::OutputHLSL(sh::GLenum shaderType,
+ int shaderVersion,
+ const TExtensionBehavior &extensionBehavior,
+ const char *sourcePath,
+ ShShaderOutput outputType,
+ int numRenderTargets,
+ const std::vector<Uniform> &uniforms,
+ ShCompileOptions compileOptions,
+ TSymbolTable *symbolTable,
+ PerformanceDiagnostics *perfDiagnostics)
+ : TIntermTraverser(true, true, true, symbolTable),
mShaderType(shaderType),
mShaderVersion(shaderVersion),
mExtensionBehavior(extensionBehavior),
@@ -146,51 +154,66 @@ OutputHLSL::OutputHLSL(sh::GLenum shaderType, int shaderVersion,
mOutputType(outputType),
mCompileOptions(compileOptions),
mNumRenderTargets(numRenderTargets),
- mCurrentFunctionMetadata(nullptr)
+ mCurrentFunctionMetadata(nullptr),
+ mPerfDiagnostics(perfDiagnostics)
{
mInsideFunction = false;
- mUsesFragColor = false;
- mUsesFragData = false;
- mUsesDepthRange = false;
- mUsesFragCoord = false;
- mUsesPointCoord = false;
- mUsesFrontFacing = false;
- mUsesPointSize = false;
- mUsesInstanceID = false;
- mUsesFragDepth = false;
- mUsesXor = false;
- mUsesDiscardRewriting = false;
- mUsesNestedBreak = false;
+ mUsesFragColor = false;
+ mUsesFragData = false;
+ mUsesDepthRange = false;
+ mUsesFragCoord = false;
+ mUsesPointCoord = false;
+ mUsesFrontFacing = false;
+ mUsesPointSize = false;
+ mUsesInstanceID = false;
+ mHasMultiviewExtensionEnabled =
+ IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview);
+ mUsesViewID = false;
+ mUsesVertexID = false;
+ mUsesFragDepth = false;
+ mUsesNumWorkGroups = false;
+ mUsesWorkGroupID = false;
+ mUsesLocalInvocationID = false;
+ mUsesGlobalInvocationID = false;
+ mUsesLocalInvocationIndex = false;
+ mUsesXor = false;
+ mUsesDiscardRewriting = false;
+ mUsesNestedBreak = false;
mRequiresIEEEStrictCompiling = false;
mUniqueIndex = 0;
- mOutputLod0Function = false;
+ mOutputLod0Function = false;
mInsideDiscontinuousLoop = false;
- mNestedLoopDepth = 0;
+ mNestedLoopDepth = 0;
- mExcessiveLoopIndex = NULL;
+ mExcessiveLoopIndex = nullptr;
- mStructureHLSL = new StructureHLSL;
- mUniformHLSL = new UniformHLSL(mStructureHLSL, outputType, uniforms);
+ mStructureHLSL = new StructureHLSL;
+ mUniformHLSL = new UniformHLSL(shaderType, mStructureHLSL, outputType, uniforms);
+ mTextureFunctionHLSL = new TextureFunctionHLSL;
+ mImageFunctionHLSL = new ImageFunctionHLSL;
if (mOutputType == SH_HLSL_3_0_OUTPUT)
{
// Fragment shaders need dx_DepthRange, dx_ViewCoords and dx_DepthFront.
- // Vertex shaders need a slightly different set: dx_DepthRange, dx_ViewCoords and dx_ViewAdjust.
+ // Vertex shaders need a slightly different set: dx_DepthRange, dx_ViewCoords and
+ // dx_ViewAdjust.
// In both cases total 3 uniform registers need to be reserved.
mUniformHLSL->reserveUniformRegisters(3);
}
// Reserve registers for the default uniform block and driver constants
- mUniformHLSL->reserveInterfaceBlockRegisters(2);
+ mUniformHLSL->reserveUniformBlockRegisters(2);
}
OutputHLSL::~OutputHLSL()
{
SafeDelete(mStructureHLSL);
SafeDelete(mUniformHLSL);
+ SafeDelete(mTextureFunctionHLSL);
+ SafeDelete(mImageFunctionHLSL);
for (auto &eqFunction : mStructEqualityFunctions)
{
SafeDelete(eqFunction);
@@ -203,71 +226,48 @@ OutputHLSL::~OutputHLSL()
void OutputHLSL::output(TIntermNode *treeRoot, TInfoSinkBase &objSink)
{
- const std::vector<TIntermTyped*> &flaggedStructs = FlagStd140ValueStructs(treeRoot);
- makeFlaggedStructMaps(flaggedStructs);
-
BuiltInFunctionEmulator builtInFunctionEmulator;
InitBuiltInFunctionEmulatorForHLSL(&builtInFunctionEmulator);
- builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(treeRoot);
+ if ((mCompileOptions & SH_EMULATE_ISNAN_FLOAT_FUNCTION) != 0)
+ {
+ InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(&builtInFunctionEmulator,
+ mShaderVersion);
+ }
+
+ builtInFunctionEmulator.markBuiltInFunctionsForEmulation(treeRoot);
// Now that we are done changing the AST, do the analyses need for HLSL generation
- CallDAG::InitResult success = mCallDag.init(treeRoot, &objSink);
+ CallDAG::InitResult success = mCallDag.init(treeRoot, nullptr);
ASSERT(success == CallDAG::INITDAG_SUCCESS);
- UNUSED_ASSERTION_VARIABLE(success);
mASTMetadataList = CreateASTMetadataHLSL(treeRoot, mCallDag);
+ const std::vector<MappedStruct> std140Structs = FlagStd140Structs(treeRoot);
+ // TODO(oetuaho): The std140Structs could be filtered based on which ones actually get used in
+ // the shader code. When we add shader storage blocks we might also consider an alternative
+ // solution, since the struct mapping won't work very well for shader storage blocks.
+
// Output the body and footer first to determine what has to go in the header
mInfoSinkStack.push(&mBody);
treeRoot->traverse(this);
mInfoSinkStack.pop();
mInfoSinkStack.push(&mFooter);
- if (!mDeferredGlobalInitializers.empty())
- {
- writeDeferredGlobalInitializers(mFooter);
- }
mInfoSinkStack.pop();
mInfoSinkStack.push(&mHeader);
- header(mHeader, &builtInFunctionEmulator);
+ header(mHeader, std140Structs, &builtInFunctionEmulator);
mInfoSinkStack.pop();
objSink << mHeader.c_str();
objSink << mBody.c_str();
objSink << mFooter.c_str();
- builtInFunctionEmulator.Cleanup();
-}
-
-void OutputHLSL::makeFlaggedStructMaps(const std::vector<TIntermTyped *> &flaggedStructs)
-{
- for (unsigned int structIndex = 0; structIndex < flaggedStructs.size(); structIndex++)
- {
- TIntermTyped *flaggedNode = flaggedStructs[structIndex];
-
- TInfoSinkBase structInfoSink;
- mInfoSinkStack.push(&structInfoSink);
-
- // This will mark the necessary block elements as referenced
- flaggedNode->traverse(this);
-
- TString structName(structInfoSink.c_str());
- mInfoSinkStack.pop();
-
- mFlaggedStructOriginalNames[flaggedNode] = structName;
-
- for (size_t pos = structName.find('.'); pos != std::string::npos; pos = structName.find('.'))
- {
- structName.erase(pos, 1);
- }
-
- mFlaggedStructMappedNames[flaggedNode] = "map" + structName;
- }
+ builtInFunctionEmulator.cleanup();
}
-const std::map<std::string, unsigned int> &OutputHLSL::getInterfaceBlockRegisterMap() const
+const std::map<std::string, unsigned int> &OutputHLSL::getUniformBlockRegisterMap() const
{
- return mUniformHLSL->getInterfaceBlockRegisterMap();
+ return mUniformHLSL->getUniformBlockRegisterMap();
}
const std::map<std::string, unsigned int> &OutputHLSL::getUniformRegisterMap() const
@@ -275,95 +275,161 @@ const std::map<std::string, unsigned int> &OutputHLSL::getUniformRegisterMap() c
return mUniformHLSL->getUniformRegisterMap();
}
-int OutputHLSL::vectorSize(const TType &type) const
-{
- int elementSize = type.isMatrix() ? type.getCols() : 1;
- int arraySize = type.isArray() ? type.getArraySize() : 1;
-
- return elementSize * arraySize;
-}
-
-TString OutputHLSL::structInitializerString(int indent, const TStructure &structure, const TString &rhsStructName)
+TString OutputHLSL::structInitializerString(int indent,
+ const TType &type,
+ const TString &name) const
{
TString init;
- TString preIndentString;
- TString fullIndentString;
+ TString indentString;
+ for (int spaces = 0; spaces < indent; spaces++)
+ {
+ indentString += " ";
+ }
- for (int spaces = 0; spaces < (indent * 4); spaces++)
+ if (type.isArray())
{
- preIndentString += ' ';
+ init += indentString + "{\n";
+ for (unsigned int arrayIndex = 0u; arrayIndex < type.getOutermostArraySize(); ++arrayIndex)
+ {
+ TStringStream indexedString;
+ indexedString << name << "[" << arrayIndex << "]";
+ TType elementType = type;
+ elementType.toArrayElementType();
+ init += structInitializerString(indent + 1, elementType, indexedString.str());
+ if (arrayIndex < type.getOutermostArraySize() - 1)
+ {
+ init += ",";
+ }
+ init += "\n";
+ }
+ init += indentString + "}";
}
+ else if (type.getBasicType() == EbtStruct)
+ {
+ init += indentString + "{\n";
+ const TStructure &structure = *type.getStruct();
+ const TFieldList &fields = structure.fields();
+ for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
+ {
+ const TField &field = *fields[fieldIndex];
+ const TString &fieldName = name + "." + Decorate(field.name());
+ const TType &fieldType = *field.type();
- for (int spaces = 0; spaces < ((indent+1) * 4); spaces++)
+ init += structInitializerString(indent + 1, fieldType, fieldName);
+ if (fieldIndex < fields.size() - 1)
+ {
+ init += ",";
+ }
+ init += "\n";
+ }
+ init += indentString + "}";
+ }
+ else
{
- fullIndentString += ' ';
+ init += indentString + name;
}
- init += preIndentString + "{\n";
+ return init;
+}
+
+TString OutputHLSL::generateStructMapping(const std::vector<MappedStruct> &std140Structs) const
+{
+ TString mappedStructs;
- const TFieldList &fields = structure.fields();
- for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
+ for (auto &mappedStruct : std140Structs)
{
- const TField &field = *fields[fieldIndex];
- const TString &fieldName = rhsStructName + "." + Decorate(field.name());
- const TType &fieldType = *field.type();
-
- if (fieldType.getStruct())
+ TInterfaceBlock *interfaceBlock =
+ mappedStruct.blockDeclarator->getType().getInterfaceBlock();
+ const TString &interfaceBlockName = interfaceBlock->name();
+ const TName &instanceName = mappedStruct.blockDeclarator->getName();
+ if (mReferencedUniformBlocks.count(interfaceBlockName) == 0 &&
+ (instanceName.getString() == "" ||
+ mReferencedUniformBlocks.count(instanceName.getString()) == 0))
{
- init += structInitializerString(indent + 1, *fieldType.getStruct(), fieldName);
+ continue;
}
- else
+
+ unsigned int instanceCount = 1u;
+ bool isInstanceArray = mappedStruct.blockDeclarator->isArray();
+ if (isInstanceArray)
{
- init += fullIndentString + fieldName + ",\n";
+ instanceCount = mappedStruct.blockDeclarator->getOutermostArraySize();
}
- }
- init += preIndentString + "}" + (indent == 0 ? ";" : ",") + "\n";
+ for (unsigned int instanceArrayIndex = 0; instanceArrayIndex < instanceCount;
+ ++instanceArrayIndex)
+ {
+ TString originalName;
+ TString mappedName("map");
- return init;
+ if (instanceName.getString() != "")
+ {
+ unsigned int instanceStringArrayIndex = GL_INVALID_INDEX;
+ if (isInstanceArray)
+ instanceStringArrayIndex = instanceArrayIndex;
+ TString instanceString = mUniformHLSL->uniformBlockInstanceString(
+ *interfaceBlock, instanceStringArrayIndex);
+ originalName += instanceString;
+ mappedName += instanceString;
+ originalName += ".";
+ mappedName += "_";
+ }
+
+ TString fieldName = Decorate(mappedStruct.field->name());
+ originalName += fieldName;
+ mappedName += fieldName;
+
+ TType *structType = mappedStruct.field->type();
+ mappedStructs +=
+ "static " + Decorate(structType->getStruct()->name()) + " " + mappedName;
+
+ if (structType->isArray())
+ {
+ mappedStructs += ArrayString(*mappedStruct.field->type());
+ }
+
+ mappedStructs += " =\n";
+ mappedStructs += structInitializerString(0, *structType, originalName);
+ mappedStructs += ";\n";
+ }
+ }
+ return mappedStructs;
}
-void OutputHLSL::header(TInfoSinkBase &out, const BuiltInFunctionEmulator *builtInFunctionEmulator)
+void OutputHLSL::header(TInfoSinkBase &out,
+ const std::vector<MappedStruct> &std140Structs,
+ const BuiltInFunctionEmulator *builtInFunctionEmulator) const
{
TString varyings;
TString attributes;
- TString flaggedStructs;
+ TString mappedStructs = generateStructMapping(std140Structs);
- for (std::map<TIntermTyped*, TString>::const_iterator flaggedStructIt = mFlaggedStructMappedNames.begin(); flaggedStructIt != mFlaggedStructMappedNames.end(); flaggedStructIt++)
+ for (ReferencedSymbols::const_iterator varying = mReferencedVaryings.begin();
+ varying != mReferencedVaryings.end(); varying++)
{
- TIntermTyped *structNode = flaggedStructIt->first;
- const TString &mappedName = flaggedStructIt->second;
- const TStructure &structure = *structNode->getType().getStruct();
- const TString &originalName = mFlaggedStructOriginalNames[structNode];
-
- flaggedStructs += "static " + Decorate(structure.name()) + " " + mappedName + " =\n";
- flaggedStructs += structInitializerString(0, structure, originalName);
- flaggedStructs += "\n";
- }
-
- for (ReferencedSymbols::const_iterator varying = mReferencedVaryings.begin(); varying != mReferencedVaryings.end(); varying++)
- {
- const TType &type = varying->second->getType();
+ const TType &type = varying->second->getType();
const TString &name = varying->second->getSymbol();
// Program linking depends on this exact format
- varyings += "static " + InterpolationString(type.getQualifier()) + " " + TypeString(type) + " " +
- Decorate(name) + ArrayString(type) + " = " + initializer(type) + ";\n";
+ varyings += "static " + InterpolationString(type.getQualifier()) + " " + TypeString(type) +
+ " " + Decorate(name) + ArrayString(type) + " = " + initializer(type) + ";\n";
}
- for (ReferencedSymbols::const_iterator attribute = mReferencedAttributes.begin(); attribute != mReferencedAttributes.end(); attribute++)
+ for (ReferencedSymbols::const_iterator attribute = mReferencedAttributes.begin();
+ attribute != mReferencedAttributes.end(); attribute++)
{
- const TType &type = attribute->second->getType();
+ const TType &type = attribute->second->getType();
const TString &name = attribute->second->getSymbol();
- attributes += "static " + TypeString(type) + " " + Decorate(name) + ArrayString(type) + " = " + initializer(type) + ";\n";
+ attributes += "static " + TypeString(type) + " " + Decorate(name) + ArrayString(type) +
+ " = " + initializer(type) + ";\n";
}
out << mStructureHLSL->structsHeader();
- mUniformHLSL->uniformsHeader(out, mOutputType, mReferencedUniforms);
- out << mUniformHLSL->interfaceBlocksHeader(mReferencedInterfaceBlocks);
+ mUniformHLSL->uniformsHeader(out, mOutputType, mReferencedUniforms, mSymbolTable);
+ out << mUniformHLSL->uniformBlocksHeader(mReferencedUniformBlocks);
if (!mEqualityFunctions.empty())
{
@@ -415,22 +481,24 @@ void OutputHLSL::header(TInfoSinkBase &out, const BuiltInFunctionEmulator *built
if (mShaderType == GL_FRAGMENT_SHADER)
{
- TExtensionBehavior::const_iterator iter = mExtensionBehavior.find("GL_EXT_draw_buffers");
- const bool usingMRTExtension = (iter != mExtensionBehavior.end() && (iter->second == EBhEnable || iter->second == EBhRequire));
+ const bool usingMRTExtension =
+ IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers);
out << "// Varyings\n";
- out << varyings;
+ out << varyings;
out << "\n";
if (mShaderVersion >= 300)
{
- for (ReferencedSymbols::const_iterator outputVariableIt = mReferencedOutputVariables.begin(); outputVariableIt != mReferencedOutputVariables.end(); outputVariableIt++)
+ for (ReferencedSymbols::const_iterator outputVariableIt =
+ mReferencedOutputVariables.begin();
+ outputVariableIt != mReferencedOutputVariables.end(); outputVariableIt++)
{
const TString &variableName = outputVariableIt->first;
- const TType &variableType = outputVariableIt->second->getType();
+ const TType &variableType = outputVariableIt->second->getType();
- out << "static " + TypeString(variableType) + " out_" + variableName + ArrayString(variableType) +
- " = " + initializer(variableType) + ";\n";
+ out << "static " + TypeString(variableType) + " out_" + variableName +
+ ArrayString(variableType) + " = " + initializer(variableType) + ";\n";
}
}
else
@@ -438,7 +506,7 @@ void OutputHLSL::header(TInfoSinkBase &out, const BuiltInFunctionEmulator *built
const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1;
out << "static float4 gl_Color[" << numColorValues << "] =\n"
- "{\n";
+ "{\n";
for (unsigned int i = 0; i < numColorValues; i++)
{
out << " float4(0, 0, 0, 0)";
@@ -512,6 +580,18 @@ void OutputHLSL::header(TInfoSinkBase &out, const BuiltInFunctionEmulator *built
out << " float2 dx_ViewScale : packoffset(c3);\n";
}
+ if (mHasMultiviewExtensionEnabled)
+ {
+ // We have to add a value which we can use to keep track of which multi-view code
+ // path is to be selected in the GS.
+ out << " float multiviewSelectViewportIndex : packoffset(c3.z);\n";
+ }
+
+ if (mOutputType == SH_HLSL_4_1_OUTPUT)
+ {
+ mUniformHLSL->samplerMetadataUniforms(out, "c4");
+ }
+
out << "};\n";
}
else
@@ -536,15 +616,16 @@ void OutputHLSL::header(TInfoSinkBase &out, const BuiltInFunctionEmulator *built
if (mUsesDepthRange)
{
- out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n"
+ out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, "
+ "dx_DepthRange.y, dx_DepthRange.z};\n"
"\n";
}
- if (!flaggedStructs.empty())
+ if (!mappedStructs.empty())
{
- out << "// Std140 Structures accessed by value\n";
+ out << "// Structures from std140 blocks with padding removed\n";
out << "\n";
- out << flaggedStructs;
+ out << mappedStructs;
out << "\n";
}
@@ -563,10 +644,10 @@ void OutputHLSL::header(TInfoSinkBase &out, const BuiltInFunctionEmulator *built
out << "#define GL_USES_FRAG_DATA\n";
}
}
- else // Vertex shader
+ else if (mShaderType == GL_VERTEX_SHADER)
{
out << "// Attributes\n";
- out << attributes;
+ out << attributes;
out << "\n"
"static float4 gl_Position = float4(0, 0, 0, 0);\n";
@@ -580,9 +661,14 @@ void OutputHLSL::header(TInfoSinkBase &out, const BuiltInFunctionEmulator *built
out << "static int gl_InstanceID;";
}
+ if (mUsesVertexID)
+ {
+ out << "static int gl_VertexID;";
+ }
+
out << "\n"
"// Varyings\n";
- out << varyings;
+ out << varyings;
out << "\n";
if (mUsesDepthRange)
@@ -599,7 +685,7 @@ void OutputHLSL::header(TInfoSinkBase &out, const BuiltInFunctionEmulator *built
if (mOutputType == SH_HLSL_4_1_OUTPUT || mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
{
out << "cbuffer DriverConstants : register(b1)\n"
- "{\n";
+ "{\n";
if (mUsesDepthRange)
{
@@ -614,6 +700,18 @@ void OutputHLSL::header(TInfoSinkBase &out, const BuiltInFunctionEmulator *built
out << " float2 dx_ViewCoords : packoffset(c2);\n";
out << " float2 dx_ViewScale : packoffset(c3);\n";
+ if (mHasMultiviewExtensionEnabled)
+ {
+ // We have to add a value which we can use to keep track of which multi-view code
+ // path is to be selected in the GS.
+ out << " float multiviewSelectViewportIndex : packoffset(c3.z);\n";
+ }
+
+ if (mOutputType == SH_HLSL_4_1_OUTPUT)
+ {
+ mUniformHLSL->samplerMetadataUniforms(out, "c4");
+ }
+
out << "};\n"
"\n";
}
@@ -631,740 +729,62 @@ void OutputHLSL::header(TInfoSinkBase &out, const BuiltInFunctionEmulator *built
if (mUsesDepthRange)
{
- out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n"
+ out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, "
+ "dx_DepthRange.y, dx_DepthRange.z};\n"
"\n";
}
- if (!flaggedStructs.empty())
+ if (!mappedStructs.empty())
{
- out << "// Std140 Structures accessed by value\n";
+ out << "// Structures from std140 blocks with padding removed\n";
out << "\n";
- out << flaggedStructs;
+ out << mappedStructs;
out << "\n";
}
}
-
- for (TextureFunctionSet::const_iterator textureFunction = mUsesTexture.begin(); textureFunction != mUsesTexture.end(); textureFunction++)
+ else // Compute shader
{
- // Return type
- if (textureFunction->method == TextureFunction::SIZE)
- {
- switch(textureFunction->sampler)
- {
- case EbtSampler2D: out << "int2 "; break;
- case EbtSampler3D: out << "int3 "; break;
- case EbtSamplerCube: out << "int2 "; break;
- case EbtSampler2DArray: out << "int3 "; break;
- case EbtISampler2D: out << "int2 "; break;
- case EbtISampler3D: out << "int3 "; break;
- case EbtISamplerCube: out << "int2 "; break;
- case EbtISampler2DArray: out << "int3 "; break;
- case EbtUSampler2D: out << "int2 "; break;
- case EbtUSampler3D: out << "int3 "; break;
- case EbtUSamplerCube: out << "int2 "; break;
- case EbtUSampler2DArray: out << "int3 "; break;
- case EbtSampler2DShadow: out << "int2 "; break;
- case EbtSamplerCubeShadow: out << "int2 "; break;
- case EbtSampler2DArrayShadow: out << "int3 "; break;
- default: UNREACHABLE();
- }
- }
- else // Sampling function
- {
- switch(textureFunction->sampler)
- {
- case EbtSampler2D: out << "float4 "; break;
- case EbtSampler3D: out << "float4 "; break;
- case EbtSamplerCube: out << "float4 "; break;
- case EbtSampler2DArray: out << "float4 "; break;
- case EbtISampler2D: out << "int4 "; break;
- case EbtISampler3D: out << "int4 "; break;
- case EbtISamplerCube: out << "int4 "; break;
- case EbtISampler2DArray: out << "int4 "; break;
- case EbtUSampler2D: out << "uint4 "; break;
- case EbtUSampler3D: out << "uint4 "; break;
- case EbtUSamplerCube: out << "uint4 "; break;
- case EbtUSampler2DArray: out << "uint4 "; break;
- case EbtSampler2DShadow: out << "float "; break;
- case EbtSamplerCubeShadow: out << "float "; break;
- case EbtSampler2DArrayShadow: out << "float "; break;
- default: UNREACHABLE();
- }
- }
-
- // Function name
- out << textureFunction->name();
-
- // Argument list
- int hlslCoords = 4;
-
- if (mOutputType == SH_HLSL_3_0_OUTPUT)
- {
- switch(textureFunction->sampler)
- {
- case EbtSampler2D: out << "sampler2D s"; hlslCoords = 2; break;
- case EbtSamplerCube: out << "samplerCUBE s"; hlslCoords = 3; break;
- default: UNREACHABLE();
- }
-
- switch(textureFunction->method)
- {
- case TextureFunction::IMPLICIT: break;
- case TextureFunction::BIAS: hlslCoords = 4; break;
- case TextureFunction::LOD: hlslCoords = 4; break;
- case TextureFunction::LOD0: hlslCoords = 4; break;
- case TextureFunction::LOD0BIAS: hlslCoords = 4; break;
- default: UNREACHABLE();
- }
- }
- else
- {
- hlslCoords = HLSLTextureCoordsCount(textureFunction->sampler);
- if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
- {
- out << TextureString(textureFunction->sampler) << " x, "
- << SamplerString(textureFunction->sampler) << " s";
- }
- else
- {
- ASSERT(mOutputType == SH_HLSL_4_1_OUTPUT);
- out << "const uint samplerIndex";
- }
- }
-
- if (textureFunction->method == TextureFunction::FETCH) // Integer coordinates
- {
- switch(textureFunction->coords)
- {
- case 2: out << ", int2 t"; break;
- case 3: out << ", int3 t"; break;
- default: UNREACHABLE();
- }
- }
- else // Floating-point coordinates (except textureSize)
- {
- switch(textureFunction->coords)
- {
- case 1: out << ", int lod"; break; // textureSize()
- case 2: out << ", float2 t"; break;
- case 3: out << ", float3 t"; break;
- case 4: out << ", float4 t"; break;
- default: UNREACHABLE();
- }
- }
+ ASSERT(mShaderType == GL_COMPUTE_SHADER);
- if (textureFunction->method == TextureFunction::GRAD)
- {
- switch(textureFunction->sampler)
- {
- case EbtSampler2D:
- case EbtISampler2D:
- case EbtUSampler2D:
- case EbtSampler2DArray:
- case EbtISampler2DArray:
- case EbtUSampler2DArray:
- case EbtSampler2DShadow:
- case EbtSampler2DArrayShadow:
- out << ", float2 ddx, float2 ddy";
- break;
- case EbtSampler3D:
- case EbtISampler3D:
- case EbtUSampler3D:
- case EbtSamplerCube:
- case EbtISamplerCube:
- case EbtUSamplerCube:
- case EbtSamplerCubeShadow:
- out << ", float3 ddx, float3 ddy";
- break;
- default: UNREACHABLE();
- }
- }
-
- switch(textureFunction->method)
+ out << "cbuffer DriverConstants : register(b1)\n"
+ "{\n";
+ if (mUsesNumWorkGroups)
{
- case TextureFunction::IMPLICIT: break;
- case TextureFunction::BIAS: break; // Comes after the offset parameter
- case TextureFunction::LOD: out << ", float lod"; break;
- case TextureFunction::LOD0: break;
- case TextureFunction::LOD0BIAS: break; // Comes after the offset parameter
- case TextureFunction::SIZE: break;
- case TextureFunction::FETCH: out << ", int mip"; break;
- case TextureFunction::GRAD: break;
- default: UNREACHABLE();
+ out << " uint3 gl_NumWorkGroups : packoffset(c0);\n";
}
+ ASSERT(mOutputType == SH_HLSL_4_1_OUTPUT);
+ mUniformHLSL->samplerMetadataUniforms(out, "c1");
+ out << "};\n";
- if (textureFunction->offset)
+ // Follow built-in variables would be initialized in
+ // DynamicHLSL::generateComputeShaderLinkHLSL, if they
+ // are used in compute shader.
+ if (mUsesWorkGroupID)
{
- switch(textureFunction->sampler)
- {
- case EbtSampler2D: out << ", int2 offset"; break;
- case EbtSampler3D: out << ", int3 offset"; break;
- case EbtSampler2DArray: out << ", int2 offset"; break;
- case EbtISampler2D: out << ", int2 offset"; break;
- case EbtISampler3D: out << ", int3 offset"; break;
- case EbtISampler2DArray: out << ", int2 offset"; break;
- case EbtUSampler2D: out << ", int2 offset"; break;
- case EbtUSampler3D: out << ", int3 offset"; break;
- case EbtUSampler2DArray: out << ", int2 offset"; break;
- case EbtSampler2DShadow: out << ", int2 offset"; break;
- case EbtSampler2DArrayShadow: out << ", int2 offset"; break;
- default: UNREACHABLE();
- }
+ out << "static uint3 gl_WorkGroupID = uint3(0, 0, 0);\n";
}
- if (textureFunction->method == TextureFunction::BIAS ||
- textureFunction->method == TextureFunction::LOD0BIAS)
+ if (mUsesLocalInvocationID)
{
- out << ", float bias";
+ out << "static uint3 gl_LocalInvocationID = uint3(0, 0, 0);\n";
}
- out << ")\n"
- "{\n";
-
- // In some cases we use a variable to store the texture/sampler objects, but to work around
- // a D3D11 compiler bug related to discard inside a loop that is conditional on texture
- // sampling we need to call the function directly on a reference to the array. The bug was
- // found using dEQP-GLES3.functional.shaders.discard*loop_texture* tests.
- TString textureReference("x");
- TString samplerReference("s");
- if (mOutputType == SH_HLSL_4_1_OUTPUT)
+ if (mUsesGlobalInvocationID)
{
- TString suffix = TextureGroupSuffix(textureFunction->sampler);
- if (TextureGroup(textureFunction->sampler) == HLSL_TEXTURE_2D)
- {
- textureReference = TString("textures") + suffix + "[samplerIndex]";
- samplerReference = TString("samplers") + suffix + "[samplerIndex]";
- }
- else
- {
- out << " const uint textureIndex = samplerIndex - textureIndexOffset" << suffix
- << ";\n";
- textureReference = TString("textures") + suffix + "[textureIndex]";
- out << " const uint samplerArrayIndex = samplerIndex - samplerIndexOffset"
- << suffix << ";\n";
- samplerReference = TString("samplers") + suffix + "[samplerArrayIndex]";
- }
+ out << "static uint3 gl_GlobalInvocationID = uint3(0, 0, 0);\n";
}
- if (textureFunction->method == TextureFunction::SIZE)
+ if (mUsesLocalInvocationIndex)
{
- if (IsSampler2D(textureFunction->sampler) || IsSamplerCube(textureFunction->sampler))
- {
- if (IsSamplerArray(textureFunction->sampler))
- {
- out << " uint width; uint height; uint layers; uint numberOfLevels;\n"
- << " " << textureReference
- << ".GetDimensions(lod, width, height, layers, numberOfLevels);\n";
- }
- else
- {
- out << " uint width; uint height; uint numberOfLevels;\n"
- << " " << textureReference
- << ".GetDimensions(lod, width, height, numberOfLevels);\n";
- }
- }
- else if (IsSampler3D(textureFunction->sampler))
- {
- out << " uint width; uint height; uint depth; uint numberOfLevels;\n"
- << " " << textureReference
- << ".GetDimensions(lod, width, height, depth, numberOfLevels);\n";
- }
- else UNREACHABLE();
-
- switch(textureFunction->sampler)
- {
- case EbtSampler2D: out << " return int2(width, height);"; break;
- case EbtSampler3D: out << " return int3(width, height, depth);"; break;
- case EbtSamplerCube: out << " return int2(width, height);"; break;
- case EbtSampler2DArray: out << " return int3(width, height, layers);"; break;
- case EbtISampler2D: out << " return int2(width, height);"; break;
- case EbtISampler3D: out << " return int3(width, height, depth);"; break;
- case EbtISamplerCube: out << " return int2(width, height);"; break;
- case EbtISampler2DArray: out << " return int3(width, height, layers);"; break;
- case EbtUSampler2D: out << " return int2(width, height);"; break;
- case EbtUSampler3D: out << " return int3(width, height, depth);"; break;
- case EbtUSamplerCube: out << " return int2(width, height);"; break;
- case EbtUSampler2DArray: out << " return int3(width, height, layers);"; break;
- case EbtSampler2DShadow: out << " return int2(width, height);"; break;
- case EbtSamplerCubeShadow: out << " return int2(width, height);"; break;
- case EbtSampler2DArrayShadow: out << " return int3(width, height, layers);"; break;
- default: UNREACHABLE();
- }
- }
- else
- {
- if (IsIntegerSampler(textureFunction->sampler) && IsSamplerCube(textureFunction->sampler))
- {
- out << " float width; float height; float layers; float levels;\n";
-
- out << " uint mip = 0;\n";
-
- out << " " << textureReference
- << ".GetDimensions(mip, width, height, layers, levels);\n";
-
- out << " bool xMajor = abs(t.x) > abs(t.y) && abs(t.x) > abs(t.z);\n";
- out << " bool yMajor = abs(t.y) > abs(t.z) && abs(t.y) > abs(t.x);\n";
- out << " bool zMajor = abs(t.z) > abs(t.x) && abs(t.z) > abs(t.y);\n";
- out << " bool negative = (xMajor && t.x < 0.0f) || (yMajor && t.y < 0.0f) || (zMajor && t.z < 0.0f);\n";
-
- // FACE_POSITIVE_X = 000b
- // FACE_NEGATIVE_X = 001b
- // FACE_POSITIVE_Y = 010b
- // FACE_NEGATIVE_Y = 011b
- // FACE_POSITIVE_Z = 100b
- // FACE_NEGATIVE_Z = 101b
- out << " int face = (int)negative + (int)yMajor * 2 + (int)zMajor * 4;\n";
-
- out << " float u = xMajor ? -t.z : (yMajor && t.y < 0.0f ? -t.x : t.x);\n";
- out << " float v = yMajor ? t.z : (negative ? t.y : -t.y);\n";
- out << " float m = xMajor ? t.x : (yMajor ? t.y : t.z);\n";
-
- out << " t.x = (u * 0.5f / m) + 0.5f;\n";
- out << " t.y = (v * 0.5f / m) + 0.5f;\n";
-
- // Mip level computation.
- if (textureFunction->method == TextureFunction::IMPLICIT)
- {
- out << " float2 tSized = float2(t.x * width, t.y * height);\n"
- " float2 dx = ddx(tSized);\n"
- " float2 dy = ddy(tSized);\n"
- " float lod = 0.5f * log2(max(dot(dx, dx), dot(dy, dy)));\n"
- " mip = uint(min(max(round(lod), 0), levels - 1));\n"
- << " " << textureReference
- << ".GetDimensions(mip, width, height, layers, levels);\n";
- }
- }
- else if (IsIntegerSampler(textureFunction->sampler) &&
- textureFunction->method != TextureFunction::FETCH)
- {
- if (IsSampler2D(textureFunction->sampler))
- {
- if (IsSamplerArray(textureFunction->sampler))
- {
- out << " float width; float height; float layers; float levels;\n";
-
- if (textureFunction->method == TextureFunction::LOD0)
- {
- out << " uint mip = 0;\n";
- }
- else if (textureFunction->method == TextureFunction::LOD0BIAS)
- {
- out << " uint mip = bias;\n";
- }
- else
- {
-
- out << " " << textureReference
- << ".GetDimensions(0, width, height, layers, levels);\n";
- if (textureFunction->method == TextureFunction::IMPLICIT ||
- textureFunction->method == TextureFunction::BIAS)
- {
- out << " float2 tSized = float2(t.x * width, t.y * height);\n"
- " float dx = length(ddx(tSized));\n"
- " float dy = length(ddy(tSized));\n"
- " float lod = log2(max(dx, dy));\n";
-
- if (textureFunction->method == TextureFunction::BIAS)
- {
- out << " lod += bias;\n";
- }
- }
- else if (textureFunction->method == TextureFunction::GRAD)
- {
- out << " float lod = log2(max(length(ddx), length(ddy)));\n";
- }
-
- out << " uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
- }
-
- out << " " << textureReference
- << ".GetDimensions(mip, width, height, layers, levels);\n";
- }
- else
- {
- out << " float width; float height; float levels;\n";
-
- if (textureFunction->method == TextureFunction::LOD0)
- {
- out << " uint mip = 0;\n";
- }
- else if (textureFunction->method == TextureFunction::LOD0BIAS)
- {
- out << " uint mip = bias;\n";
- }
- else
- {
- out << " " << textureReference
- << ".GetDimensions(0, width, height, levels);\n";
-
- if (textureFunction->method == TextureFunction::IMPLICIT ||
- textureFunction->method == TextureFunction::BIAS)
- {
- out << " float2 tSized = float2(t.x * width, t.y * height);\n"
- " float dx = length(ddx(tSized));\n"
- " float dy = length(ddy(tSized));\n"
- " float lod = log2(max(dx, dy));\n";
-
- if (textureFunction->method == TextureFunction::BIAS)
- {
- out << " lod += bias;\n";
- }
- }
- else if (textureFunction->method == TextureFunction::GRAD)
- {
- out << " float lod = log2(max(length(ddx), length(ddy)));\n";
- }
-
- out << " uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
- }
-
- out << " " << textureReference
- << ".GetDimensions(mip, width, height, levels);\n";
- }
- }
- else if (IsSampler3D(textureFunction->sampler))
- {
- out << " float width; float height; float depth; float levels;\n";
-
- if (textureFunction->method == TextureFunction::LOD0)
- {
- out << " uint mip = 0;\n";
- }
- else if (textureFunction->method == TextureFunction::LOD0BIAS)
- {
- out << " uint mip = bias;\n";
- }
- else
- {
- out << " " << textureReference
- << ".GetDimensions(0, width, height, depth, levels);\n";
-
- if (textureFunction->method == TextureFunction::IMPLICIT ||
- textureFunction->method == TextureFunction::BIAS)
- {
- out << " float3 tSized = float3(t.x * width, t.y * height, t.z * "
- "depth);\n"
- " float dx = length(ddx(tSized));\n"
- " float dy = length(ddy(tSized));\n"
- " float lod = log2(max(dx, dy));\n";
-
- if (textureFunction->method == TextureFunction::BIAS)
- {
- out << " lod += bias;\n";
- }
- }
- else if (textureFunction->method == TextureFunction::GRAD)
- {
- out << " float lod = log2(max(length(ddx), length(ddy)));\n";
- }
-
- out << " uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
- }
-
- out << " " << textureReference
- << ".GetDimensions(mip, width, height, depth, levels);\n";
- }
- else UNREACHABLE();
- }
-
- out << " return ";
-
- // HLSL intrinsic
- if (mOutputType == SH_HLSL_3_0_OUTPUT)
- {
- switch(textureFunction->sampler)
- {
- case EbtSampler2D: out << "tex2D"; break;
- case EbtSamplerCube: out << "texCUBE"; break;
- default: UNREACHABLE();
- }
-
- switch(textureFunction->method)
- {
- case TextureFunction::IMPLICIT:
- out << "(" << samplerReference << ", ";
- break;
- case TextureFunction::BIAS:
- out << "bias(" << samplerReference << ", ";
- break;
- case TextureFunction::LOD:
- out << "lod(" << samplerReference << ", ";
- break;
- case TextureFunction::LOD0:
- out << "lod(" << samplerReference << ", ";
- break;
- case TextureFunction::LOD0BIAS:
- out << "lod(" << samplerReference << ", ";
- break;
- default: UNREACHABLE();
- }
- }
- else if (mOutputType == SH_HLSL_4_1_OUTPUT || mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
- {
- if (textureFunction->method == TextureFunction::GRAD)
- {
- if (IsIntegerSampler(textureFunction->sampler))
- {
- out << "" << textureReference << ".Load(";
- }
- else if (IsShadowSampler(textureFunction->sampler))
- {
- out << "" << textureReference << ".SampleCmpLevelZero(" << samplerReference
- << ", ";
- }
- else
- {
- out << "" << textureReference << ".SampleGrad(" << samplerReference << ", ";
- }
- }
- else if (IsIntegerSampler(textureFunction->sampler) ||
- textureFunction->method == TextureFunction::FETCH)
- {
- out << "" << textureReference << ".Load(";
- }
- else if (IsShadowSampler(textureFunction->sampler))
- {
- switch(textureFunction->method)
- {
- case TextureFunction::IMPLICIT:
- out << "" << textureReference << ".SampleCmp(" << samplerReference
- << ", ";
- break;
- case TextureFunction::BIAS:
- out << "" << textureReference << ".SampleCmp(" << samplerReference
- << ", ";
- break;
- case TextureFunction::LOD:
- out << "" << textureReference << ".SampleCmp(" << samplerReference
- << ", ";
- break;
- case TextureFunction::LOD0:
- out << "" << textureReference << ".SampleCmpLevelZero("
- << samplerReference << ", ";
- break;
- case TextureFunction::LOD0BIAS:
- out << "" << textureReference << ".SampleCmpLevelZero("
- << samplerReference << ", ";
- break;
- default: UNREACHABLE();
- }
- }
- else
- {
- switch(textureFunction->method)
- {
- case TextureFunction::IMPLICIT:
- out << "" << textureReference << ".Sample(" << samplerReference << ", ";
- break;
- case TextureFunction::BIAS:
- out << "" << textureReference << ".SampleBias(" << samplerReference
- << ", ";
- break;
- case TextureFunction::LOD:
- out << "" << textureReference << ".SampleLevel(" << samplerReference
- << ", ";
- break;
- case TextureFunction::LOD0:
- out << "" << textureReference << ".SampleLevel(" << samplerReference
- << ", ";
- break;
- case TextureFunction::LOD0BIAS:
- out << "" << textureReference << ".SampleLevel(" << samplerReference
- << ", ";
- break;
- default: UNREACHABLE();
- }
- }
- }
- else UNREACHABLE();
-
- // Integer sampling requires integer addresses
- TString addressx = "";
- TString addressy = "";
- TString addressz = "";
- TString close = "";
-
- if (IsIntegerSampler(textureFunction->sampler) ||
- textureFunction->method == TextureFunction::FETCH)
- {
- switch(hlslCoords)
- {
- case 2: out << "int3("; break;
- case 3: out << "int4("; break;
- default: UNREACHABLE();
- }
-
- // Convert from normalized floating-point to integer
- if (textureFunction->method != TextureFunction::FETCH)
- {
- addressx = "int(floor(width * frac((";
- addressy = "int(floor(height * frac((";
-
- if (IsSamplerArray(textureFunction->sampler))
- {
- addressz = "int(max(0, min(layers - 1, floor(0.5 + ";
- }
- else if (IsSamplerCube(textureFunction->sampler))
- {
- addressz = "((((";
- }
- else
- {
- addressz = "int(floor(depth * frac((";
- }
-
- close = "))))";
- }
- }
- else
- {
- switch(hlslCoords)
- {
- case 2: out << "float2("; break;
- case 3: out << "float3("; break;
- case 4: out << "float4("; break;
- default: UNREACHABLE();
- }
- }
-
- TString proj = ""; // Only used for projected textures
-
- if (textureFunction->proj)
- {
- switch(textureFunction->coords)
- {
- case 3: proj = " / t.z"; break;
- case 4: proj = " / t.w"; break;
- default: UNREACHABLE();
- }
- }
-
- out << addressx + ("t.x" + proj) + close + ", " + addressy + ("t.y" + proj) + close;
-
- if (mOutputType == SH_HLSL_3_0_OUTPUT)
- {
- if (hlslCoords >= 3)
- {
- if (textureFunction->coords < 3)
- {
- out << ", 0";
- }
- else
- {
- out << ", t.z" + proj;
- }
- }
-
- if (hlslCoords == 4)
- {
- switch(textureFunction->method)
- {
- case TextureFunction::BIAS: out << ", bias"; break;
- case TextureFunction::LOD: out << ", lod"; break;
- case TextureFunction::LOD0: out << ", 0"; break;
- case TextureFunction::LOD0BIAS: out << ", bias"; break;
- default: UNREACHABLE();
- }
- }
-
- out << "));\n";
- }
- else if (mOutputType == SH_HLSL_4_1_OUTPUT || mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
- {
- if (hlslCoords >= 3)
- {
- if (IsIntegerSampler(textureFunction->sampler) && IsSamplerCube(textureFunction->sampler))
- {
- out << ", face";
- }
- else
- {
- out << ", " + addressz + ("t.z" + proj) + close;
- }
- }
-
- if (textureFunction->method == TextureFunction::GRAD)
- {
- if (IsIntegerSampler(textureFunction->sampler))
- {
- out << ", mip)";
- }
- else if (IsShadowSampler(textureFunction->sampler))
- {
- // Compare value
- if (textureFunction->proj)
- {
- // According to ESSL 3.00.4 sec 8.8 p95 on textureProj:
- // The resulting third component of P' in the shadow forms is used as Dref
- out << "), t.z" << proj;
- }
- else
- {
- switch(textureFunction->coords)
- {
- case 3: out << "), t.z"; break;
- case 4: out << "), t.w"; break;
- default: UNREACHABLE();
- }
- }
- }
- else
- {
- out << "), ddx, ddy";
- }
- }
- else if (IsIntegerSampler(textureFunction->sampler) ||
- textureFunction->method == TextureFunction::FETCH)
- {
- out << ", mip)";
- }
- else if (IsShadowSampler(textureFunction->sampler))
- {
- // Compare value
- if (textureFunction->proj)
- {
- // According to ESSL 3.00.4 sec 8.8 p95 on textureProj:
- // The resulting third component of P' in the shadow forms is used as Dref
- out << "), t.z" << proj;
- }
- else
- {
- switch(textureFunction->coords)
- {
- case 3: out << "), t.z"; break;
- case 4: out << "), t.w"; break;
- default: UNREACHABLE();
- }
- }
- }
- else
- {
- switch(textureFunction->method)
- {
- case TextureFunction::IMPLICIT: out << ")"; break;
- case TextureFunction::BIAS: out << "), bias"; break;
- case TextureFunction::LOD: out << "), lod"; break;
- case TextureFunction::LOD0: out << "), 0"; break;
- case TextureFunction::LOD0BIAS: out << "), bias"; break;
- default: UNREACHABLE();
- }
- }
-
- if (textureFunction->offset)
- {
- out << ", offset";
- }
-
- out << ");";
- }
- else UNREACHABLE();
+ out << "static uint gl_LocalInvocationIndex = uint(0);\n";
}
-
- out << "\n"
- "}\n"
- "\n";
}
+ bool getDimensionsIgnoresBaseLevel =
+ (mCompileOptions & SH_HLSL_GET_DIMENSIONS_IGNORES_BASE_LEVEL) != 0;
+ mTextureFunctionHLSL->textureFunctionHeader(out, mOutputType, getDimensionsIgnoresBaseLevel);
+ mImageFunctionHLSL->imageFunctionHeader(out);
+
if (mUsesFragCoord)
{
out << "#define GL_USES_FRAG_COORD\n";
@@ -1385,6 +805,16 @@ void OutputHLSL::header(TInfoSinkBase &out, const BuiltInFunctionEmulator *built
out << "#define GL_USES_POINT_SIZE\n";
}
+ if (mHasMultiviewExtensionEnabled)
+ {
+ out << "#define GL_ANGLE_MULTIVIEW_ENABLED\n";
+ }
+
+ if (mUsesViewID)
+ {
+ out << "#define GL_USES_VIEW_ID\n";
+ }
+
if (mUsesFragDepth)
{
out << "#define GL_USES_FRAG_DEPTH\n";
@@ -1395,6 +825,31 @@ void OutputHLSL::header(TInfoSinkBase &out, const BuiltInFunctionEmulator *built
out << "#define GL_USES_DEPTH_RANGE\n";
}
+ if (mUsesNumWorkGroups)
+ {
+ out << "#define GL_USES_NUM_WORK_GROUPS\n";
+ }
+
+ if (mUsesWorkGroupID)
+ {
+ out << "#define GL_USES_WORK_GROUP_ID\n";
+ }
+
+ if (mUsesLocalInvocationID)
+ {
+ out << "#define GL_USES_LOCAL_INVOCATION_ID\n";
+ }
+
+ if (mUsesGlobalInvocationID)
+ {
+ out << "#define GL_USES_GLOBAL_INVOCATION_ID\n";
+ }
+
+ if (mUsesLocalInvocationIndex)
+ {
+ out << "#define GL_USES_LOCAL_INVOCATION_INDEX\n";
+ }
+
if (mUsesXor)
{
out << "bool xor(bool p, bool q)\n"
@@ -1404,7 +859,7 @@ void OutputHLSL::header(TInfoSinkBase &out, const BuiltInFunctionEmulator *built
"\n";
}
- builtInFunctionEmulator->OutputEmulatedFunctions(out);
+ builtInFunctionEmulator->outputEmulatedFunctions(out);
}
void OutputHLSL::visitSymbol(TIntermSymbol *node)
@@ -1412,10 +867,9 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node)
TInfoSinkBase &out = getInfoSink();
// Handle accessing std140 structs by value
- if (mFlaggedStructMappedNames.count(node) > 0)
+ if (IsInStd140InterfaceBlock(node) && node->getBasicType() == EbtStruct)
{
- out << mFlaggedStructMappedNames[node];
- return;
+ out << "map";
}
TString name = node->getSymbol();
@@ -1427,25 +881,25 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node)
}
else
{
+ const TType &nodeType = node->getType();
TQualifier qualifier = node->getQualifier();
+ ensureStructDefined(nodeType);
+
if (qualifier == EvqUniform)
{
- const TType &nodeType = node->getType();
const TInterfaceBlock *interfaceBlock = nodeType.getInterfaceBlock();
if (interfaceBlock)
{
- mReferencedInterfaceBlocks[interfaceBlock->name()] = node;
+ mReferencedUniformBlocks[interfaceBlock->name()] = node;
}
else
{
mReferencedUniforms[name] = node;
}
- ensureStructDefined(nodeType);
-
- out << DecorateUniform(name, nodeType);
+ out << DecorateVariableIfNeeded(node->getName());
}
else if (qualifier == EvqAttribute || qualifier == EvqVertexIn)
{
@@ -1456,6 +910,10 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node)
{
mReferencedVaryings[name] = node;
out << Decorate(name);
+ if (name == "ViewID_OVR")
+ {
+ mUsesViewID = true;
+ }
}
else if (qualifier == EvqFragmentOut)
{
@@ -1497,14 +955,44 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node)
mUsesInstanceID = true;
out << name;
}
+ else if (qualifier == EvqVertexID)
+ {
+ mUsesVertexID = true;
+ out << name;
+ }
else if (name == "gl_FragDepthEXT" || name == "gl_FragDepth")
{
mUsesFragDepth = true;
out << "gl_Depth";
}
+ else if (qualifier == EvqNumWorkGroups)
+ {
+ mUsesNumWorkGroups = true;
+ out << name;
+ }
+ else if (qualifier == EvqWorkGroupID)
+ {
+ mUsesWorkGroupID = true;
+ out << name;
+ }
+ else if (qualifier == EvqLocalInvocationID)
+ {
+ mUsesLocalInvocationID = true;
+ out << name;
+ }
+ else if (qualifier == EvqGlobalInvocationID)
+ {
+ mUsesGlobalInvocationID = true;
+ out << name;
+ }
+ else if (qualifier == EvqLocalInvocationIndex)
+ {
+ mUsesLocalInvocationIndex = true;
+ out << name;
+ }
else
{
- out << DecorateIfNeeded(node->getName());
+ out << DecorateVariableIfNeeded(node->getName());
}
}
}
@@ -1553,315 +1041,372 @@ void OutputHLSL::outputEqual(Visit visit, const TType &type, TOperator op, TInfo
}
}
-bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
+void OutputHLSL::outputAssign(Visit visit, const TType &type, TInfoSinkBase &out)
{
- TInfoSinkBase &out = getInfoSink();
-
- // Handle accessing std140 structs by value
- if (mFlaggedStructMappedNames.count(node) > 0)
+ if (type.isArray())
{
- out << mFlaggedStructMappedNames[node];
- return false;
+ const TString &functionName = addArrayAssignmentFunction(type);
+ outputTriplet(out, visit, (functionName + "(").c_str(), ", ", ")");
+ }
+ else
+ {
+ outputTriplet(out, visit, "(", " = ", ")");
}
+}
- switch (node->getOp())
+bool OutputHLSL::ancestorEvaluatesToSamplerInStruct()
+{
+ for (unsigned int n = 0u; getAncestorNode(n) != nullptr; ++n)
{
- case EOpAssign:
- if (node->getLeft()->isArray())
+ TIntermNode *ancestor = getAncestorNode(n);
+ const TIntermBinary *ancestorBinary = ancestor->getAsBinaryNode();
+ if (ancestorBinary == nullptr)
{
- TIntermAggregate *rightAgg = node->getRight()->getAsAggregate();
- if (rightAgg != nullptr && rightAgg->isConstructor())
+ return false;
+ }
+ switch (ancestorBinary->getOp())
+ {
+ case EOpIndexDirectStruct:
{
- const TString &functionName = addArrayConstructIntoFunction(node->getType());
- out << functionName << "(";
- node->getLeft()->traverse(this);
- TIntermSequence *seq = rightAgg->getSequence();
- for (auto &arrayElement : *seq)
+ const TStructure *structure = ancestorBinary->getLeft()->getType().getStruct();
+ const TIntermConstantUnion *index =
+ ancestorBinary->getRight()->getAsConstantUnion();
+ const TField *field = structure->fields()[index->getIConst(0)];
+ if (IsSampler(field->type()->getBasicType()))
{
- out << ", ";
- arrayElement->traverse(this);
+ return true;
}
- out << ")";
- return false;
+ break;
}
- // ArrayReturnValueToOutParameter should have eliminated expressions where a function call is assigned.
- ASSERT(rightAgg == nullptr || rightAgg->getOp() != EOpFunctionCall);
-
- const TString &functionName = addArrayAssignmentFunction(node->getType());
- outputTriplet(out, visit, (functionName + "(").c_str(), ", ", ")");
- }
- else
- {
- outputTriplet(out, visit, "(", " = ", ")");
- }
- break;
- case EOpInitialize:
- if (visit == PreVisit)
- {
- // GLSL allows to write things like "float x = x;" where a new variable x is defined
- // and the value of an existing variable x is assigned. HLSL uses C semantics (the
- // new variable is created before the assignment is evaluated), so we need to convert
- // this to "float t = x, x = t;".
-
- TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode();
- ASSERT(symbolNode);
- TIntermTyped *expression = node->getRight();
-
- // TODO (jmadill): do a 'deep' scan to know if an expression is statically const
- if (symbolNode->getQualifier() == EvqGlobal && expression->getQualifier() != EvqConst)
- {
- // For variables which are not constant, defer their real initialization until
- // after we initialize uniforms.
- TIntermBinary *deferredInit = new TIntermBinary(EOpAssign);
- deferredInit->setLeft(node->getLeft());
- deferredInit->setRight(node->getRight());
- deferredInit->setType(node->getType());
- mDeferredGlobalInitializers.push_back(deferredInit);
- const TString &initString = initializer(node->getType());
- node->setRight(new TIntermRaw(node->getType(), initString));
- }
- else if (writeSameSymbolInitializer(out, symbolNode, expression))
- {
- // Skip initializing the rest of the expression
+ case EOpIndexDirect:
+ break;
+ default:
+ // Returning a sampler from indirect indexing is not supported.
return false;
+ }
+ }
+ return false;
+}
+
+bool OutputHLSL::visitSwizzle(Visit visit, TIntermSwizzle *node)
+{
+ TInfoSinkBase &out = getInfoSink();
+ if (visit == PostVisit)
+ {
+ out << ".";
+ node->writeOffsetsAsXYZW(&out);
+ }
+ return true;
+}
+
+bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
+{
+ TInfoSinkBase &out = getInfoSink();
+
+ switch (node->getOp())
+ {
+ case EOpComma:
+ outputTriplet(out, visit, "(", ", ", ")");
+ break;
+ case EOpAssign:
+ if (node->isArray())
+ {
+ TIntermAggregate *rightAgg = node->getRight()->getAsAggregate();
+ if (rightAgg != nullptr && rightAgg->isConstructor())
+ {
+ const TString &functionName = addArrayConstructIntoFunction(node->getType());
+ out << functionName << "(";
+ node->getLeft()->traverse(this);
+ TIntermSequence *seq = rightAgg->getSequence();
+ for (auto &arrayElement : *seq)
+ {
+ out << ", ";
+ arrayElement->traverse(this);
+ }
+ out << ")";
+ return false;
+ }
+ // ArrayReturnValueToOutParameter should have eliminated expressions where a
+ // function call is assigned.
+ ASSERT(rightAgg == nullptr);
}
- else if (writeConstantInitialization(out, symbolNode, expression))
+ outputAssign(visit, node->getType(), out);
+ break;
+ case EOpInitialize:
+ if (visit == PreVisit)
+ {
+ TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode();
+ ASSERT(symbolNode);
+ TIntermTyped *expression = node->getRight();
+
+ // Global initializers must be constant at this point.
+ ASSERT(symbolNode->getQualifier() != EvqGlobal ||
+ canWriteAsHLSLLiteral(expression));
+
+ // GLSL allows to write things like "float x = x;" where a new variable x is defined
+ // and the value of an existing variable x is assigned. HLSL uses C semantics (the
+ // new variable is created before the assignment is evaluated), so we need to
+ // convert
+ // this to "float t = x, x = t;".
+ if (writeSameSymbolInitializer(out, symbolNode, expression))
+ {
+ // Skip initializing the rest of the expression
+ return false;
+ }
+ else if (writeConstantInitialization(out, symbolNode, expression))
+ {
+ return false;
+ }
+ }
+ else if (visit == InVisit)
{
- return false;
+ out << " = ";
}
- }
- else if (visit == InVisit)
- {
- out << " = ";
- }
- break;
- case EOpAddAssign:
- outputTriplet(out, visit, "(", " += ", ")");
- break;
- case EOpSubAssign:
- outputTriplet(out, visit, "(", " -= ", ")");
- break;
- case EOpMulAssign:
- outputTriplet(out, visit, "(", " *= ", ")");
- break;
- case EOpVectorTimesScalarAssign:
- outputTriplet(out, visit, "(", " *= ", ")");
- break;
- case EOpMatrixTimesScalarAssign:
- outputTriplet(out, visit, "(", " *= ", ")");
- break;
- case EOpVectorTimesMatrixAssign:
- if (visit == PreVisit)
- {
- out << "(";
- }
- else if (visit == InVisit)
- {
- out << " = mul(";
- node->getLeft()->traverse(this);
- out << ", transpose(";
- }
- else
- {
- out << ")))";
- }
- break;
- case EOpMatrixTimesMatrixAssign:
- if (visit == PreVisit)
- {
- out << "(";
- }
- else if (visit == InVisit)
- {
- out << " = transpose(mul(transpose(";
- node->getLeft()->traverse(this);
- out << "), transpose(";
- }
- else
+ break;
+ case EOpAddAssign:
+ outputTriplet(out, visit, "(", " += ", ")");
+ break;
+ case EOpSubAssign:
+ outputTriplet(out, visit, "(", " -= ", ")");
+ break;
+ case EOpMulAssign:
+ outputTriplet(out, visit, "(", " *= ", ")");
+ break;
+ case EOpVectorTimesScalarAssign:
+ outputTriplet(out, visit, "(", " *= ", ")");
+ break;
+ case EOpMatrixTimesScalarAssign:
+ outputTriplet(out, visit, "(", " *= ", ")");
+ break;
+ case EOpVectorTimesMatrixAssign:
+ if (visit == PreVisit)
+ {
+ out << "(";
+ }
+ else if (visit == InVisit)
+ {
+ out << " = mul(";
+ node->getLeft()->traverse(this);
+ out << ", transpose(";
+ }
+ else
+ {
+ out << ")))";
+ }
+ break;
+ case EOpMatrixTimesMatrixAssign:
+ if (visit == PreVisit)
+ {
+ out << "(";
+ }
+ else if (visit == InVisit)
+ {
+ out << " = transpose(mul(transpose(";
+ node->getLeft()->traverse(this);
+ out << "), transpose(";
+ }
+ else
+ {
+ out << "))))";
+ }
+ break;
+ case EOpDivAssign:
+ outputTriplet(out, visit, "(", " /= ", ")");
+ break;
+ case EOpIModAssign:
+ outputTriplet(out, visit, "(", " %= ", ")");
+ break;
+ case EOpBitShiftLeftAssign:
+ outputTriplet(out, visit, "(", " <<= ", ")");
+ break;
+ case EOpBitShiftRightAssign:
+ outputTriplet(out, visit, "(", " >>= ", ")");
+ break;
+ case EOpBitwiseAndAssign:
+ outputTriplet(out, visit, "(", " &= ", ")");
+ break;
+ case EOpBitwiseXorAssign:
+ outputTriplet(out, visit, "(", " ^= ", ")");
+ break;
+ case EOpBitwiseOrAssign:
+ outputTriplet(out, visit, "(", " |= ", ")");
+ break;
+ case EOpIndexDirect:
{
- out << "))))";
- }
- break;
- case EOpDivAssign:
- outputTriplet(out, visit, "(", " /= ", ")");
- break;
- case EOpIModAssign:
- outputTriplet(out, visit, "(", " %= ", ")");
- break;
- case EOpBitShiftLeftAssign:
- outputTriplet(out, visit, "(", " <<= ", ")");
- break;
- case EOpBitShiftRightAssign:
- outputTriplet(out, visit, "(", " >>= ", ")");
- break;
- case EOpBitwiseAndAssign:
- outputTriplet(out, visit, "(", " &= ", ")");
- break;
- case EOpBitwiseXorAssign:
- outputTriplet(out, visit, "(", " ^= ", ")");
- break;
- case EOpBitwiseOrAssign:
- outputTriplet(out, visit, "(", " |= ", ")");
- break;
- case EOpIndexDirect:
- {
- const TType& leftType = node->getLeft()->getType();
+ const TType &leftType = node->getLeft()->getType();
if (leftType.isInterfaceBlock())
{
if (visit == PreVisit)
{
- TInterfaceBlock* interfaceBlock = leftType.getInterfaceBlock();
+ TInterfaceBlock *interfaceBlock = leftType.getInterfaceBlock();
const int arrayIndex = node->getRight()->getAsConstantUnion()->getIConst(0);
- mReferencedInterfaceBlocks[interfaceBlock->instanceName()] = node->getLeft()->getAsSymbolNode();
- out << mUniformHLSL->interfaceBlockInstanceString(*interfaceBlock, arrayIndex);
+ mReferencedUniformBlocks[interfaceBlock->instanceName()] =
+ node->getLeft()->getAsSymbolNode();
+ out << mUniformHLSL->uniformBlockInstanceString(*interfaceBlock, arrayIndex);
return false;
}
}
+ else if (ancestorEvaluatesToSamplerInStruct())
+ {
+ // All parts of an expression that access a sampler in a struct need to use _ as
+ // separator to access the sampler variable that has been moved out of the struct.
+ outputTriplet(out, visit, "", "_", "");
+ }
else
{
outputTriplet(out, visit, "", "[", "]");
}
}
break;
- case EOpIndexIndirect:
- // We do not currently support indirect references to interface blocks
- ASSERT(node->getLeft()->getBasicType() != EbtInterfaceBlock);
- outputTriplet(out, visit, "", "[", "]");
- break;
- case EOpIndexDirectStruct:
- if (visit == InVisit)
+ case EOpIndexIndirect:
+ // We do not currently support indirect references to interface blocks
+ ASSERT(node->getLeft()->getBasicType() != EbtInterfaceBlock);
+ outputTriplet(out, visit, "", "[", "]");
+ break;
+ case EOpIndexDirectStruct:
{
- const TStructure* structure = node->getLeft()->getType().getStruct();
- const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion();
- const TField* field = structure->fields()[index->getIConst(0)];
- out << "." + DecorateField(field->name(), *structure);
+ const TStructure *structure = node->getLeft()->getType().getStruct();
+ const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
+ const TField *field = structure->fields()[index->getIConst(0)];
- return false;
- }
- break;
- case EOpIndexDirectInterfaceBlock:
- if (visit == InVisit)
- {
- const TInterfaceBlock* interfaceBlock = node->getLeft()->getType().getInterfaceBlock();
- const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion();
- const TField* field = interfaceBlock->fields()[index->getIConst(0)];
- out << "." + Decorate(field->name());
+ // In cases where indexing returns a sampler, we need to access the sampler variable
+ // that has been moved out of the struct.
+ bool indexingReturnsSampler = IsSampler(field->type()->getBasicType());
+ if (visit == PreVisit && indexingReturnsSampler)
+ {
+ // Samplers extracted from structs have "angle" prefix to avoid name conflicts.
+ // This prefix is only output at the beginning of the indexing expression, which
+ // may have multiple parts.
+ out << "angle";
+ }
+ if (!indexingReturnsSampler)
+ {
+ // All parts of an expression that access a sampler in a struct need to use _ as
+ // separator to access the sampler variable that has been moved out of the struct.
+ indexingReturnsSampler = ancestorEvaluatesToSamplerInStruct();
+ }
+ if (visit == InVisit)
+ {
+ if (indexingReturnsSampler)
+ {
+ out << "_" + field->name();
+ }
+ else
+ {
+ out << "." + DecorateField(field->name(), *structure);
+ }
- return false;
+ return false;
+ }
}
break;
- case EOpVectorSwizzle:
- if (visit == InVisit)
+ case EOpIndexDirectInterfaceBlock:
{
- out << ".";
-
- TIntermAggregate *swizzle = node->getRight()->getAsAggregate();
-
- if (swizzle)
+ bool structInStd140Block =
+ node->getBasicType() == EbtStruct && IsInStd140InterfaceBlock(node->getLeft());
+ if (visit == PreVisit && structInStd140Block)
{
- TIntermSequence *sequence = swizzle->getSequence();
-
- for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++)
+ out << "map";
+ }
+ if (visit == InVisit)
+ {
+ const TInterfaceBlock *interfaceBlock =
+ node->getLeft()->getType().getInterfaceBlock();
+ const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
+ const TField *field = interfaceBlock->fields()[index->getIConst(0)];
+ if (structInStd140Block)
{
- TIntermConstantUnion *element = (*sit)->getAsConstantUnion();
-
- if (element)
- {
- int i = element->getIConst(0);
-
- switch (i)
- {
- case 0: out << "x"; break;
- case 1: out << "y"; break;
- case 2: out << "z"; break;
- case 3: out << "w"; break;
- default: UNREACHABLE();
- }
- }
- else UNREACHABLE();
+ out << "_";
}
- }
- else UNREACHABLE();
+ else
+ {
+ out << ".";
+ }
+ out << Decorate(field->name());
- return false; // Fully processed
+ return false;
+ }
+ break;
}
- break;
- case EOpAdd:
- outputTriplet(out, visit, "(", " + ", ")");
- break;
- case EOpSub:
- outputTriplet(out, visit, "(", " - ", ")");
- break;
- case EOpMul:
- outputTriplet(out, visit, "(", " * ", ")");
- break;
- case EOpDiv:
- outputTriplet(out, visit, "(", " / ", ")");
- break;
- case EOpIMod:
- outputTriplet(out, visit, "(", " % ", ")");
- break;
- case EOpBitShiftLeft:
- outputTriplet(out, visit, "(", " << ", ")");
- break;
- case EOpBitShiftRight:
- outputTriplet(out, visit, "(", " >> ", ")");
- break;
- case EOpBitwiseAnd:
- outputTriplet(out, visit, "(", " & ", ")");
- break;
- case EOpBitwiseXor:
- outputTriplet(out, visit, "(", " ^ ", ")");
- break;
- case EOpBitwiseOr:
- outputTriplet(out, visit, "(", " | ", ")");
- break;
- case EOpEqual:
- case EOpNotEqual:
- outputEqual(visit, node->getLeft()->getType(), node->getOp(), out);
- break;
- case EOpLessThan:
- outputTriplet(out, visit, "(", " < ", ")");
- break;
- case EOpGreaterThan:
- outputTriplet(out, visit, "(", " > ", ")");
- break;
- case EOpLessThanEqual:
- outputTriplet(out, visit, "(", " <= ", ")");
- break;
- case EOpGreaterThanEqual:
- outputTriplet(out, visit, "(", " >= ", ")");
- break;
- case EOpVectorTimesScalar:
- outputTriplet(out, visit, "(", " * ", ")");
- break;
- case EOpMatrixTimesScalar:
- outputTriplet(out, visit, "(", " * ", ")");
- break;
- case EOpVectorTimesMatrix:
- outputTriplet(out, visit, "mul(", ", transpose(", "))");
- break;
- case EOpMatrixTimesVector:
- outputTriplet(out, visit, "mul(transpose(", "), ", ")");
- break;
- case EOpMatrixTimesMatrix:
- outputTriplet(out, visit, "transpose(mul(transpose(", "), transpose(", ")))");
- break;
- case EOpLogicalOr:
- // HLSL doesn't short-circuit ||, so we assume that || affected by short-circuiting have been unfolded.
- ASSERT(!node->getRight()->hasSideEffects());
- outputTriplet(out, visit, "(", " || ", ")");
- return true;
- case EOpLogicalXor:
- mUsesXor = true;
- outputTriplet(out, visit, "xor(", ", ", ")");
- break;
- case EOpLogicalAnd:
- // HLSL doesn't short-circuit &&, so we assume that && affected by short-circuiting have been unfolded.
- ASSERT(!node->getRight()->hasSideEffects());
- outputTriplet(out, visit, "(", " && ", ")");
- return true;
- default: UNREACHABLE();
+ case EOpAdd:
+ outputTriplet(out, visit, "(", " + ", ")");
+ break;
+ case EOpSub:
+ outputTriplet(out, visit, "(", " - ", ")");
+ break;
+ case EOpMul:
+ outputTriplet(out, visit, "(", " * ", ")");
+ break;
+ case EOpDiv:
+ outputTriplet(out, visit, "(", " / ", ")");
+ break;
+ case EOpIMod:
+ outputTriplet(out, visit, "(", " % ", ")");
+ break;
+ case EOpBitShiftLeft:
+ outputTriplet(out, visit, "(", " << ", ")");
+ break;
+ case EOpBitShiftRight:
+ outputTriplet(out, visit, "(", " >> ", ")");
+ break;
+ case EOpBitwiseAnd:
+ outputTriplet(out, visit, "(", " & ", ")");
+ break;
+ case EOpBitwiseXor:
+ outputTriplet(out, visit, "(", " ^ ", ")");
+ break;
+ case EOpBitwiseOr:
+ outputTriplet(out, visit, "(", " | ", ")");
+ break;
+ case EOpEqual:
+ case EOpNotEqual:
+ outputEqual(visit, node->getLeft()->getType(), node->getOp(), out);
+ break;
+ case EOpLessThan:
+ outputTriplet(out, visit, "(", " < ", ")");
+ break;
+ case EOpGreaterThan:
+ outputTriplet(out, visit, "(", " > ", ")");
+ break;
+ case EOpLessThanEqual:
+ outputTriplet(out, visit, "(", " <= ", ")");
+ break;
+ case EOpGreaterThanEqual:
+ outputTriplet(out, visit, "(", " >= ", ")");
+ break;
+ case EOpVectorTimesScalar:
+ outputTriplet(out, visit, "(", " * ", ")");
+ break;
+ case EOpMatrixTimesScalar:
+ outputTriplet(out, visit, "(", " * ", ")");
+ break;
+ case EOpVectorTimesMatrix:
+ outputTriplet(out, visit, "mul(", ", transpose(", "))");
+ break;
+ case EOpMatrixTimesVector:
+ outputTriplet(out, visit, "mul(transpose(", "), ", ")");
+ break;
+ case EOpMatrixTimesMatrix:
+ outputTriplet(out, visit, "transpose(mul(transpose(", "), transpose(", ")))");
+ break;
+ case EOpLogicalOr:
+ // HLSL doesn't short-circuit ||, so we assume that || affected by short-circuiting have
+ // been unfolded.
+ ASSERT(!node->getRight()->hasSideEffects());
+ outputTriplet(out, visit, "(", " || ", ")");
+ return true;
+ case EOpLogicalXor:
+ mUsesXor = true;
+ outputTriplet(out, visit, "xor(", ", ", ")");
+ break;
+ case EOpLogicalAnd:
+ // HLSL doesn't short-circuit &&, so we assume that && affected by short-circuiting have
+ // been unfolded.
+ ASSERT(!node->getRight()->hasSideEffects());
+ outputTriplet(out, visit, "(", " && ", ")");
+ return true;
+ default:
+ UNREACHABLE();
}
return true;
@@ -1879,9 +1424,6 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
case EOpPositive:
outputTriplet(out, visit, "(+", "", ")");
break;
- case EOpVectorLogicalNot:
- outputTriplet(out, visit, "(!", "", ")");
- break;
case EOpLogicalNot:
outputTriplet(out, visit, "(!", "", ")");
break;
@@ -1933,542 +1475,516 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
case EOpTanh:
outputTriplet(out, visit, "tanh(", "", ")");
break;
- case EOpAsinh:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "asinh(");
- break;
- case EOpAcosh:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "acosh(");
- break;
- case EOpAtanh:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "atanh(");
- break;
- case EOpExp:
- outputTriplet(out, visit, "exp(", "", ")");
- break;
- case EOpLog:
- outputTriplet(out, visit, "log(", "", ")");
- break;
- case EOpExp2:
- outputTriplet(out, visit, "exp2(", "", ")");
- break;
- case EOpLog2:
- outputTriplet(out, visit, "log2(", "", ")");
- break;
- case EOpSqrt:
- outputTriplet(out, visit, "sqrt(", "", ")");
- break;
- case EOpInverseSqrt:
- outputTriplet(out, visit, "rsqrt(", "", ")");
- break;
- case EOpAbs:
- outputTriplet(out, visit, "abs(", "", ")");
- break;
- case EOpSign:
- outputTriplet(out, visit, "sign(", "", ")");
- break;
- case EOpFloor:
- outputTriplet(out, visit, "floor(", "", ")");
- break;
- case EOpTrunc:
- outputTriplet(out, visit, "trunc(", "", ")");
- break;
- case EOpRound:
- outputTriplet(out, visit, "round(", "", ")");
- break;
- case EOpRoundEven:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "roundEven(");
- break;
- case EOpCeil:
- outputTriplet(out, visit, "ceil(", "", ")");
- break;
- case EOpFract:
- outputTriplet(out, visit, "frac(", "", ")");
- break;
- case EOpIsNan:
- outputTriplet(out, visit, "isnan(", "", ")");
- mRequiresIEEEStrictCompiling = true;
- break;
- case EOpIsInf:
- outputTriplet(out, visit, "isinf(", "", ")");
- break;
- case EOpFloatBitsToInt:
- outputTriplet(out, visit, "asint(", "", ")");
- break;
- case EOpFloatBitsToUint:
- outputTriplet(out, visit, "asuint(", "", ")");
- break;
- case EOpIntBitsToFloat:
- outputTriplet(out, visit, "asfloat(", "", ")");
- break;
- case EOpUintBitsToFloat:
- outputTriplet(out, visit, "asfloat(", "", ")");
- break;
- case EOpPackSnorm2x16:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "packSnorm2x16(");
- break;
- case EOpPackUnorm2x16:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "packUnorm2x16(");
- break;
- case EOpPackHalf2x16:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "packHalf2x16(");
- break;
- case EOpUnpackSnorm2x16:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "unpackSnorm2x16(");
- break;
- case EOpUnpackUnorm2x16:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "unpackUnorm2x16(");
- break;
- case EOpUnpackHalf2x16:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "unpackHalf2x16(");
- break;
- case EOpLength:
- outputTriplet(out, visit, "length(", "", ")");
- break;
- case EOpNormalize:
- outputTriplet(out, visit, "normalize(", "", ")");
- break;
- case EOpDFdx:
- if(mInsideDiscontinuousLoop || mOutputLod0Function)
- {
- outputTriplet(out, visit, "(", "", ", 0.0)");
- }
- else
- {
- outputTriplet(out, visit, "ddx(", "", ")");
- }
- break;
- case EOpDFdy:
- if(mInsideDiscontinuousLoop || mOutputLod0Function)
- {
- outputTriplet(out, visit, "(", "", ", 0.0)");
- }
- else
+ case EOpAsinh:
+ case EOpAcosh:
+ case EOpAtanh:
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(out, visit, node->getOp());
+ break;
+ case EOpExp:
+ outputTriplet(out, visit, "exp(", "", ")");
+ break;
+ case EOpLog:
+ outputTriplet(out, visit, "log(", "", ")");
+ break;
+ case EOpExp2:
+ outputTriplet(out, visit, "exp2(", "", ")");
+ break;
+ case EOpLog2:
+ outputTriplet(out, visit, "log2(", "", ")");
+ break;
+ case EOpSqrt:
+ outputTriplet(out, visit, "sqrt(", "", ")");
+ break;
+ case EOpInverseSqrt:
+ outputTriplet(out, visit, "rsqrt(", "", ")");
+ break;
+ case EOpAbs:
+ outputTriplet(out, visit, "abs(", "", ")");
+ break;
+ case EOpSign:
+ outputTriplet(out, visit, "sign(", "", ")");
+ break;
+ case EOpFloor:
+ outputTriplet(out, visit, "floor(", "", ")");
+ break;
+ case EOpTrunc:
+ outputTriplet(out, visit, "trunc(", "", ")");
+ break;
+ case EOpRound:
+ outputTriplet(out, visit, "round(", "", ")");
+ break;
+ case EOpRoundEven:
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(out, visit, node->getOp());
+ break;
+ case EOpCeil:
+ outputTriplet(out, visit, "ceil(", "", ")");
+ break;
+ case EOpFract:
+ outputTriplet(out, visit, "frac(", "", ")");
+ break;
+ case EOpIsNan:
+ if (node->getUseEmulatedFunction())
+ writeEmulatedFunctionTriplet(out, visit, node->getOp());
+ else
+ outputTriplet(out, visit, "isnan(", "", ")");
+ mRequiresIEEEStrictCompiling = true;
+ break;
+ case EOpIsInf:
+ outputTriplet(out, visit, "isinf(", "", ")");
+ break;
+ case EOpFloatBitsToInt:
+ outputTriplet(out, visit, "asint(", "", ")");
+ break;
+ case EOpFloatBitsToUint:
+ outputTriplet(out, visit, "asuint(", "", ")");
+ break;
+ case EOpIntBitsToFloat:
+ outputTriplet(out, visit, "asfloat(", "", ")");
+ break;
+ case EOpUintBitsToFloat:
+ outputTriplet(out, visit, "asfloat(", "", ")");
+ break;
+ case EOpPackSnorm2x16:
+ case EOpPackUnorm2x16:
+ case EOpPackHalf2x16:
+ case EOpUnpackSnorm2x16:
+ case EOpUnpackUnorm2x16:
+ case EOpUnpackHalf2x16:
+ case EOpPackUnorm4x8:
+ case EOpPackSnorm4x8:
+ case EOpUnpackUnorm4x8:
+ case EOpUnpackSnorm4x8:
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(out, visit, node->getOp());
+ break;
+ case EOpLength:
+ outputTriplet(out, visit, "length(", "", ")");
+ break;
+ case EOpNormalize:
+ outputTriplet(out, visit, "normalize(", "", ")");
+ break;
+ case EOpDFdx:
+ if (mInsideDiscontinuousLoop || mOutputLod0Function)
+ {
+ outputTriplet(out, visit, "(", "", ", 0.0)");
+ }
+ else
+ {
+ outputTriplet(out, visit, "ddx(", "", ")");
+ }
+ break;
+ case EOpDFdy:
+ if (mInsideDiscontinuousLoop || mOutputLod0Function)
+ {
+ outputTriplet(out, visit, "(", "", ", 0.0)");
+ }
+ else
+ {
+ outputTriplet(out, visit, "ddy(", "", ")");
+ }
+ break;
+ case EOpFwidth:
+ if (mInsideDiscontinuousLoop || mOutputLod0Function)
+ {
+ outputTriplet(out, visit, "(", "", ", 0.0)");
+ }
+ else
+ {
+ outputTriplet(out, visit, "fwidth(", "", ")");
+ }
+ break;
+ case EOpTranspose:
+ outputTriplet(out, visit, "transpose(", "", ")");
+ break;
+ case EOpDeterminant:
+ outputTriplet(out, visit, "determinant(transpose(", "", "))");
+ break;
+ case EOpInverse:
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(out, visit, node->getOp());
+ break;
+
+ case EOpAny:
+ outputTriplet(out, visit, "any(", "", ")");
+ break;
+ case EOpAll:
+ outputTriplet(out, visit, "all(", "", ")");
+ break;
+ case EOpLogicalNotComponentWise:
+ outputTriplet(out, visit, "(!", "", ")");
+ break;
+ case EOpBitfieldReverse:
+ outputTriplet(out, visit, "reversebits(", "", ")");
+ break;
+ case EOpBitCount:
+ outputTriplet(out, visit, "countbits(", "", ")");
+ break;
+ case EOpFindLSB:
+ // Note that it's unclear from the HLSL docs what this returns for 0, but this is tested
+ // in GLSLTest and results are consistent with GL.
+ outputTriplet(out, visit, "firstbitlow(", "", ")");
+ break;
+ case EOpFindMSB:
+ // Note that it's unclear from the HLSL docs what this returns for 0 or -1, but this is
+ // tested in GLSLTest and results are consistent with GL.
+ outputTriplet(out, visit, "firstbithigh(", "", ")");
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return true;
+}
+
+TString OutputHLSL::samplerNamePrefixFromStruct(TIntermTyped *node)
+{
+ if (node->getAsSymbolNode())
+ {
+ return node->getAsSymbolNode()->getSymbol();
+ }
+ TIntermBinary *nodeBinary = node->getAsBinaryNode();
+ switch (nodeBinary->getOp())
+ {
+ case EOpIndexDirect:
{
- outputTriplet(out, visit, "ddy(", "", ")");
+ int index = nodeBinary->getRight()->getAsConstantUnion()->getIConst(0);
+
+ TInfoSinkBase prefixSink;
+ prefixSink << samplerNamePrefixFromStruct(nodeBinary->getLeft()) << "_" << index;
+ return TString(prefixSink.c_str());
}
- break;
- case EOpFwidth:
- if(mInsideDiscontinuousLoop || mOutputLod0Function)
+ case EOpIndexDirectStruct:
{
- outputTriplet(out, visit, "(", "", ", 0.0)");
+ const TStructure *s = nodeBinary->getLeft()->getAsTyped()->getType().getStruct();
+ int index = nodeBinary->getRight()->getAsConstantUnion()->getIConst(0);
+ const TField *field = s->fields()[index];
+
+ TInfoSinkBase prefixSink;
+ prefixSink << samplerNamePrefixFromStruct(nodeBinary->getLeft()) << "_"
+ << field->name();
+ return TString(prefixSink.c_str());
}
- else
+ default:
+ UNREACHABLE();
+ return TString("");
+ }
+}
+
+bool OutputHLSL::visitBlock(Visit visit, TIntermBlock *node)
+{
+ TInfoSinkBase &out = getInfoSink();
+
+ if (mInsideFunction)
+ {
+ outputLineDirective(out, node->getLine().first_line);
+ out << "{\n";
+ }
+
+ for (TIntermNode *statement : *node->getSequence())
+ {
+ outputLineDirective(out, statement->getLine().first_line);
+
+ statement->traverse(this);
+
+ // Don't output ; after case labels, they're terminated by :
+ // This is needed especially since outputting a ; after a case statement would turn empty
+ // case statements into non-empty case statements, disallowing fall-through from them.
+ // Also the output code is clearer if we don't output ; after statements where it is not
+ // needed:
+ // * if statements
+ // * switch statements
+ // * blocks
+ // * function definitions
+ // * loops (do-while loops output the semicolon in VisitLoop)
+ // * declarations that don't generate output.
+ if (statement->getAsCaseNode() == nullptr && statement->getAsIfElseNode() == nullptr &&
+ statement->getAsBlock() == nullptr && statement->getAsLoopNode() == nullptr &&
+ statement->getAsSwitchNode() == nullptr &&
+ statement->getAsFunctionDefinition() == nullptr &&
+ (statement->getAsDeclarationNode() == nullptr ||
+ IsDeclarationWrittenOut(statement->getAsDeclarationNode())) &&
+ statement->getAsInvariantDeclarationNode() == nullptr)
{
- outputTriplet(out, visit, "fwidth(", "", ")");
+ out << ";\n";
}
- break;
- case EOpTranspose:
- outputTriplet(out, visit, "transpose(", "", ")");
- break;
- case EOpDeterminant:
- outputTriplet(out, visit, "determinant(transpose(", "", "))");
- break;
- case EOpInverse:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "inverse(");
- break;
+ }
- case EOpAny:
- outputTriplet(out, visit, "any(", "", ")");
- break;
- case EOpAll:
- outputTriplet(out, visit, "all(", "", ")");
- break;
- default: UNREACHABLE();
+ if (mInsideFunction)
+ {
+ outputLineDirective(out, node->getLine().last_line);
+ out << "}\n";
}
- return true;
+ return false;
}
-bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
+bool OutputHLSL::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
{
TInfoSinkBase &out = getInfoSink();
- switch (node->getOp())
+ ASSERT(mCurrentFunctionMetadata == nullptr);
+
+ size_t index = mCallDag.findIndex(node->getFunctionSymbolInfo());
+ ASSERT(index != CallDAG::InvalidIndex);
+ mCurrentFunctionMetadata = &mASTMetadataList[index];
+
+ out << TypeString(node->getFunctionPrototype()->getType()) << " ";
+
+ TIntermSequence *parameters = node->getFunctionPrototype()->getSequence();
+
+ if (node->getFunctionSymbolInfo()->isMain())
{
- case EOpSequence:
- {
- if (mInsideFunction)
- {
- outputLineDirective(out, node->getLine().first_line);
- out << "{\n";
- }
+ out << "gl_main(";
+ }
+ else
+ {
+ out << DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj())
+ << DisambiguateFunctionName(parameters) << (mOutputLod0Function ? "Lod0(" : "(");
+ }
- for (TIntermSequence::iterator sit = node->getSequence()->begin(); sit != node->getSequence()->end(); sit++)
- {
- outputLineDirective(out, (*sit)->getLine().first_line);
+ for (unsigned int i = 0; i < parameters->size(); i++)
+ {
+ TIntermSymbol *symbol = (*parameters)[i]->getAsSymbolNode();
- (*sit)->traverse(this);
+ if (symbol)
+ {
+ ensureStructDefined(symbol->getType());
- // Don't output ; after case labels, they're terminated by :
- // This is needed especially since outputting a ; after a case statement would turn empty
- // case statements into non-empty case statements, disallowing fall-through from them.
- // Also no need to output ; after selection (if) statements or sequences. This is done just
- // for code clarity.
- TIntermSelection *asSelection = (*sit)->getAsSelectionNode();
- ASSERT(asSelection == nullptr || !asSelection->usesTernaryOperator());
- if ((*sit)->getAsCaseNode() == nullptr && asSelection == nullptr && !IsSequence(*sit))
- out << ";\n";
- }
+ out << argumentString(symbol);
- if (mInsideFunction)
+ if (i < parameters->size() - 1)
{
- outputLineDirective(out, node->getLine().last_line);
- out << "}\n";
+ out << ", ";
}
-
- return false;
}
- case EOpDeclaration:
- if (visit == PreVisit)
- {
- TIntermSequence *sequence = node->getSequence();
- TIntermTyped *variable = (*sequence)[0]->getAsTyped();
- ASSERT(sequence->size() == 1);
+ else
+ UNREACHABLE();
+ }
- if (variable &&
- (variable->getQualifier() == EvqTemporary ||
- variable->getQualifier() == EvqGlobal || variable->getQualifier() == EvqConst))
- {
- ensureStructDefined(variable->getType());
+ out << ")\n";
- if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration
- {
- if (!mInsideFunction)
- {
- out << "static ";
- }
+ mInsideFunction = true;
+ // The function body node will output braces.
+ node->getBody()->traverse(this);
+ mInsideFunction = false;
- out << TypeString(variable->getType()) + " ";
+ mCurrentFunctionMetadata = nullptr;
- TIntermSymbol *symbol = variable->getAsSymbolNode();
+ bool needsLod0 = mASTMetadataList[index].mNeedsLod0;
+ if (needsLod0 && !mOutputLod0Function && mShaderType == GL_FRAGMENT_SHADER)
+ {
+ ASSERT(!node->getFunctionSymbolInfo()->isMain());
+ mOutputLod0Function = true;
+ node->traverse(this);
+ mOutputLod0Function = false;
+ }
- if (symbol)
- {
- symbol->traverse(this);
- out << ArrayString(symbol->getType());
- out << " = " + initializer(symbol->getType());
- }
- else
- {
- variable->traverse(this);
- }
- }
- else if (variable->getAsSymbolNode() && variable->getAsSymbolNode()->getSymbol() == "") // Type (struct) declaration
- {
- // Already added to constructor map
- }
- else UNREACHABLE();
- }
- else if (variable && IsVaryingOut(variable->getQualifier()))
- {
- for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++)
- {
- TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
+ return false;
+}
- if (symbol)
- {
- // Vertex (output) varyings which are declared but not written to should still be declared to allow successful linking
- mReferencedVaryings[symbol->getSymbol()] = symbol;
- }
- else
- {
- (*sit)->traverse(this);
- }
- }
- }
+bool OutputHLSL::visitDeclaration(Visit visit, TIntermDeclaration *node)
+{
+ if (visit == PreVisit)
+ {
+ TIntermSequence *sequence = node->getSequence();
+ TIntermTyped *variable = (*sequence)[0]->getAsTyped();
+ ASSERT(sequence->size() == 1);
+ ASSERT(variable);
- return false;
- }
- else if (visit == InVisit)
- {
- out << ", ";
- }
- break;
- case EOpInvariantDeclaration:
- // Do not do any translation
- return false;
- case EOpPrototype:
- if (visit == PreVisit)
+ if (IsDeclarationWrittenOut(node))
{
- size_t index = mCallDag.findIndex(node);
- // Skip the prototype if it is not implemented (and thus not used)
- if (index == CallDAG::InvalidIndex)
- {
- return false;
- }
+ TInfoSinkBase &out = getInfoSink();
+ ensureStructDefined(variable->getType());
- TString name = DecorateFunctionIfNeeded(node->getNameObj());
- out << TypeString(node->getType()) << " " << name
- << (mOutputLod0Function ? "Lod0(" : "(");
+ if (!variable->getAsSymbolNode() ||
+ variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration
+ {
+ if (!mInsideFunction)
+ {
+ out << "static ";
+ }
- TIntermSequence *arguments = node->getSequence();
+ out << TypeString(variable->getType()) + " ";
- for (unsigned int i = 0; i < arguments->size(); i++)
- {
- TIntermSymbol *symbol = (*arguments)[i]->getAsSymbolNode();
+ TIntermSymbol *symbol = variable->getAsSymbolNode();
if (symbol)
{
- out << argumentString(symbol);
-
- if (i < arguments->size() - 1)
- {
- out << ", ";
- }
+ symbol->traverse(this);
+ out << ArrayString(symbol->getType());
+ out << " = " + initializer(symbol->getType());
+ }
+ else
+ {
+ variable->traverse(this);
}
- else UNREACHABLE();
}
-
- out << ");\n";
-
- // Also prototype the Lod0 variant if needed
- bool needsLod0 = mASTMetadataList[index].mNeedsLod0;
- if (needsLod0 && !mOutputLod0Function && mShaderType == GL_FRAGMENT_SHADER)
+ else if (variable->getAsSymbolNode() &&
+ variable->getAsSymbolNode()->getSymbol() == "") // Type (struct) declaration
{
- mOutputLod0Function = true;
- node->traverse(this);
- mOutputLod0Function = false;
+ ASSERT(variable->getBasicType() == EbtStruct);
+ // ensureStructDefined has already been called.
}
-
- return false;
+ else
+ UNREACHABLE();
}
- break;
- case EOpComma:
- outputTriplet(out, visit, "(", ", ", ")");
- break;
- case EOpFunction:
+ else if (IsVaryingOut(variable->getQualifier()))
{
- ASSERT(mCurrentFunctionMetadata == nullptr);
- TString name = TFunction::unmangleName(node->getNameObj().getString());
+ TIntermSymbol *symbol = variable->getAsSymbolNode();
+ ASSERT(symbol); // Varying declarations can't have initializers.
- size_t index = mCallDag.findIndex(node);
- ASSERT(index != CallDAG::InvalidIndex);
- mCurrentFunctionMetadata = &mASTMetadataList[index];
+ // Vertex outputs which are declared but not written to should still be declared to
+ // allow successful linking.
+ mReferencedVaryings[symbol->getSymbol()] = symbol;
+ }
+ }
+ return false;
+}
- out << TypeString(node->getType()) << " ";
+bool OutputHLSL::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node)
+{
+ // Do not do any translation
+ return false;
+}
- if (name == "main")
- {
- out << "gl_main(";
- }
- else
- {
- out << DecorateFunctionIfNeeded(node->getNameObj())
- << (mOutputLod0Function ? "Lod0(" : "(");
- }
+bool OutputHLSL::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node)
+{
+ TInfoSinkBase &out = getInfoSink();
- TIntermSequence *sequence = node->getSequence();
- TIntermSequence *arguments = (*sequence)[0]->getAsAggregate()->getSequence();
+ ASSERT(visit == PreVisit);
+ size_t index = mCallDag.findIndex(node->getFunctionSymbolInfo());
+ // Skip the prototype if it is not implemented (and thus not used)
+ if (index == CallDAG::InvalidIndex)
+ {
+ return false;
+ }
- for (unsigned int i = 0; i < arguments->size(); i++)
- {
- TIntermSymbol *symbol = (*arguments)[i]->getAsSymbolNode();
+ TIntermSequence *arguments = node->getSequence();
- if (symbol)
- {
- ensureStructDefined(symbol->getType());
+ TString name = DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj());
+ out << TypeString(node->getType()) << " " << name << DisambiguateFunctionName(arguments)
+ << (mOutputLod0Function ? "Lod0(" : "(");
- out << argumentString(symbol);
+ for (unsigned int i = 0; i < arguments->size(); i++)
+ {
+ TIntermSymbol *symbol = (*arguments)[i]->getAsSymbolNode();
+ ASSERT(symbol != nullptr);
- if (i < arguments->size() - 1)
- {
- out << ", ";
- }
- }
- else UNREACHABLE();
- }
+ out << argumentString(symbol);
- out << ")\n";
+ if (i < arguments->size() - 1)
+ {
+ out << ", ";
+ }
+ }
- if (sequence->size() > 1)
- {
- mInsideFunction = true;
- TIntermNode *body = (*sequence)[1];
- // The function body node will output braces.
- ASSERT(IsSequence(body));
- body->traverse(this);
- mInsideFunction = false;
- }
- else
- {
- out << "{}\n";
- }
+ out << ");\n";
- mCurrentFunctionMetadata = nullptr;
+ // Also prototype the Lod0 variant if needed
+ bool needsLod0 = mASTMetadataList[index].mNeedsLod0;
+ if (needsLod0 && !mOutputLod0Function && mShaderType == GL_FRAGMENT_SHADER)
+ {
+ mOutputLod0Function = true;
+ node->traverse(this);
+ mOutputLod0Function = false;
+ }
- bool needsLod0 = mASTMetadataList[index].mNeedsLod0;
- if (needsLod0 && !mOutputLod0Function && mShaderType == GL_FRAGMENT_SHADER)
- {
- ASSERT(name != "main");
- mOutputLod0Function = true;
- node->traverse(this);
- mOutputLod0Function = false;
- }
+ return false;
+}
- return false;
- }
- break;
- case EOpFunctionCall:
+bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+ TInfoSinkBase &out = getInfoSink();
+
+ switch (node->getOp())
+ {
+ case EOpCallBuiltInFunction:
+ case EOpCallFunctionInAST:
+ case EOpCallInternalRawFunction:
{
TIntermSequence *arguments = node->getSequence();
bool lod0 = mInsideDiscontinuousLoop || mOutputLod0Function;
- if (node->isUserDefined())
+ if (node->getOp() == EOpCallFunctionInAST)
{
if (node->isArray())
{
UNIMPLEMENTED();
}
- size_t index = mCallDag.findIndex(node);
+ size_t index = mCallDag.findIndex(node->getFunctionSymbolInfo());
ASSERT(index != CallDAG::InvalidIndex);
lod0 &= mASTMetadataList[index].mNeedsLod0;
- out << DecorateFunctionIfNeeded(node->getNameObj()) << (lod0 ? "Lod0(" : "(");
+ out << DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj());
+ out << DisambiguateFunctionName(node->getSequence());
+ out << (lod0 ? "Lod0(" : "(");
+ }
+ else if (node->getOp() == EOpCallInternalRawFunction)
+ {
+ // This path is used for internal functions that don't have their definitions in the
+ // AST, such as precision emulation functions.
+ out << DecorateFunctionIfNeeded(node->getFunctionSymbolInfo()->getNameObj()) << "(";
+ }
+ else if (node->getFunctionSymbolInfo()->isImageFunction())
+ {
+ TString name = node->getFunctionSymbolInfo()->getName();
+ TType type = (*arguments)[0]->getAsTyped()->getType();
+ TString imageFunctionName = mImageFunctionHLSL->useImageFunction(
+ name, type.getBasicType(), type.getLayoutQualifier().imageInternalFormat,
+ type.getMemoryQualifier().readonly);
+ out << imageFunctionName << "(";
}
else
{
- TString name = TFunction::unmangleName(node->getNameObj().getString());
+ const TString &name = node->getFunctionSymbolInfo()->getName();
TBasicType samplerType = (*arguments)[0]->getAsTyped()->getType().getBasicType();
-
- TextureFunction textureFunction;
- textureFunction.sampler = samplerType;
- textureFunction.coords = (*arguments)[1]->getAsTyped()->getNominalSize();
- textureFunction.method = TextureFunction::IMPLICIT;
- textureFunction.proj = false;
- textureFunction.offset = false;
-
- if (name == "texture2D" || name == "textureCube" || name == "texture")
- {
- textureFunction.method = TextureFunction::IMPLICIT;
- }
- else if (name == "texture2DProj" || name == "textureProj")
- {
- textureFunction.method = TextureFunction::IMPLICIT;
- textureFunction.proj = true;
- }
- else if (name == "texture2DLod" || name == "textureCubeLod" || name == "textureLod" ||
- name == "texture2DLodEXT" || name == "textureCubeLodEXT")
- {
- textureFunction.method = TextureFunction::LOD;
- }
- else if (name == "texture2DProjLod" || name == "textureProjLod" || name == "texture2DProjLodEXT")
- {
- textureFunction.method = TextureFunction::LOD;
- textureFunction.proj = true;
- }
- else if (name == "textureSize")
- {
- textureFunction.method = TextureFunction::SIZE;
- }
- else if (name == "textureOffset")
- {
- textureFunction.method = TextureFunction::IMPLICIT;
- textureFunction.offset = true;
- }
- else if (name == "textureProjOffset")
- {
- textureFunction.method = TextureFunction::IMPLICIT;
- textureFunction.offset = true;
- textureFunction.proj = true;
- }
- else if (name == "textureLodOffset")
- {
- textureFunction.method = TextureFunction::LOD;
- textureFunction.offset = true;
- }
- else if (name == "textureProjLodOffset")
- {
- textureFunction.method = TextureFunction::LOD;
- textureFunction.proj = true;
- textureFunction.offset = true;
- }
- else if (name == "texelFetch")
+ int coords = 0; // textureSize(gsampler2DMS) doesn't have a second argument.
+ if (arguments->size() > 1)
{
- textureFunction.method = TextureFunction::FETCH;
+ coords = (*arguments)[1]->getAsTyped()->getNominalSize();
}
- else if (name == "texelFetchOffset")
- {
- textureFunction.method = TextureFunction::FETCH;
- textureFunction.offset = true;
- }
- else if (name == "textureGrad" || name == "texture2DGradEXT")
- {
- textureFunction.method = TextureFunction::GRAD;
- }
- else if (name == "textureGradOffset")
- {
- textureFunction.method = TextureFunction::GRAD;
- textureFunction.offset = true;
- }
- else if (name == "textureProjGrad" || name == "texture2DProjGradEXT" || name == "textureCubeGradEXT")
- {
- textureFunction.method = TextureFunction::GRAD;
- textureFunction.proj = true;
- }
- else if (name == "textureProjGradOffset")
- {
- textureFunction.method = TextureFunction::GRAD;
- textureFunction.proj = true;
- textureFunction.offset = true;
- }
- else UNREACHABLE();
+ TString textureFunctionName = mTextureFunctionHLSL->useTextureFunction(
+ name, samplerType, coords, arguments->size(), lod0, mShaderType);
+ out << textureFunctionName << "(";
+ }
- if (textureFunction.method == TextureFunction::IMPLICIT) // Could require lod 0 or have a bias argument
+ for (TIntermSequence::iterator arg = arguments->begin(); arg != arguments->end(); arg++)
+ {
+ TIntermTyped *typedArg = (*arg)->getAsTyped();
+ if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT && IsSampler(typedArg->getBasicType()))
{
- unsigned int mandatoryArgumentCount = 2; // All functions have sampler and coordinate arguments
-
- if (textureFunction.offset)
- {
- mandatoryArgumentCount++;
- }
+ out << "texture_";
+ (*arg)->traverse(this);
+ out << ", sampler_";
+ }
- bool bias = (arguments->size() > mandatoryArgumentCount); // Bias argument is optional
+ (*arg)->traverse(this);
- if (lod0 || mShaderType == GL_VERTEX_SHADER)
+ if (typedArg->getType().isStructureContainingSamplers())
+ {
+ const TType &argType = typedArg->getType();
+ TVector<TIntermSymbol *> samplerSymbols;
+ TString structName = samplerNamePrefixFromStruct(typedArg);
+ argType.createSamplerSymbols("angle_" + structName, "", &samplerSymbols,
+ nullptr, mSymbolTable);
+ for (const TIntermSymbol *sampler : samplerSymbols)
{
- if (bias)
+ if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
{
- textureFunction.method = TextureFunction::LOD0BIAS;
+ out << ", texture_" << sampler->getSymbol();
+ out << ", sampler_" << sampler->getSymbol();
}
else
{
- textureFunction.method = TextureFunction::LOD0;
+ // In case of HLSL 4.1+, this symbol is the sampler index, and in case
+ // of D3D9, it's the sampler variable.
+ out << ", " + sampler->getSymbol();
}
}
- else if (bias)
- {
- textureFunction.method = TextureFunction::BIAS;
- }
- }
-
- mUsesTexture.insert(textureFunction);
-
- out << textureFunction.name();
- }
-
- for (TIntermSequence::iterator arg = arguments->begin(); arg != arguments->end(); arg++)
- {
- if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT &&
- IsSampler((*arg)->getAsTyped()->getBasicType()))
- {
- out << "texture_";
- (*arg)->traverse(this);
- out << ", sampler_";
}
- (*arg)->traverse(this);
-
if (arg < arguments->end() - 1)
{
out << ", ";
@@ -2479,160 +1995,79 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
return false;
}
- break;
- case EOpParameters:
- outputTriplet(out, visit, "(", ", ", ")\n{\n");
- break;
- case EOpConstructFloat:
- outputConstructor(out, visit, node->getType(), "vec1", node->getSequence());
- break;
- case EOpConstructVec2:
- outputConstructor(out, visit, node->getType(), "vec2", node->getSequence());
- break;
- case EOpConstructVec3:
- outputConstructor(out, visit, node->getType(), "vec3", node->getSequence());
- break;
- case EOpConstructVec4:
- outputConstructor(out, visit, node->getType(), "vec4", node->getSequence());
- break;
- case EOpConstructBool:
- outputConstructor(out, visit, node->getType(), "bvec1", node->getSequence());
- break;
- case EOpConstructBVec2:
- outputConstructor(out, visit, node->getType(), "bvec2", node->getSequence());
- break;
- case EOpConstructBVec3:
- outputConstructor(out, visit, node->getType(), "bvec3", node->getSequence());
- break;
- case EOpConstructBVec4:
- outputConstructor(out, visit, node->getType(), "bvec4", node->getSequence());
- break;
- case EOpConstructInt:
- outputConstructor(out, visit, node->getType(), "ivec1", node->getSequence());
- break;
- case EOpConstructIVec2:
- outputConstructor(out, visit, node->getType(), "ivec2", node->getSequence());
- break;
- case EOpConstructIVec3:
- outputConstructor(out, visit, node->getType(), "ivec3", node->getSequence());
- break;
- case EOpConstructIVec4:
- outputConstructor(out, visit, node->getType(), "ivec4", node->getSequence());
- break;
- case EOpConstructUInt:
- outputConstructor(out, visit, node->getType(), "uvec1", node->getSequence());
- break;
- case EOpConstructUVec2:
- outputConstructor(out, visit, node->getType(), "uvec2", node->getSequence());
- break;
- case EOpConstructUVec3:
- outputConstructor(out, visit, node->getType(), "uvec3", node->getSequence());
+ case EOpConstruct:
+ outputConstructor(out, visit, node);
break;
- case EOpConstructUVec4:
- outputConstructor(out, visit, node->getType(), "uvec4", node->getSequence());
- break;
- case EOpConstructMat2:
- outputConstructor(out, visit, node->getType(), "mat2", node->getSequence());
- break;
- case EOpConstructMat2x3:
- outputConstructor(out, visit, node->getType(), "mat2x3", node->getSequence());
- break;
- case EOpConstructMat2x4:
- outputConstructor(out, visit, node->getType(), "mat2x4", node->getSequence());
+ case EOpEqualComponentWise:
+ outputTriplet(out, visit, "(", " == ", ")");
break;
- case EOpConstructMat3x2:
- outputConstructor(out, visit, node->getType(), "mat3x2", node->getSequence());
+ case EOpNotEqualComponentWise:
+ outputTriplet(out, visit, "(", " != ", ")");
break;
- case EOpConstructMat3:
- outputConstructor(out, visit, node->getType(), "mat3", node->getSequence());
+ case EOpLessThanComponentWise:
+ outputTriplet(out, visit, "(", " < ", ")");
break;
- case EOpConstructMat3x4:
- outputConstructor(out, visit, node->getType(), "mat3x4", node->getSequence());
+ case EOpGreaterThanComponentWise:
+ outputTriplet(out, visit, "(", " > ", ")");
break;
- case EOpConstructMat4x2:
- outputConstructor(out, visit, node->getType(), "mat4x2", node->getSequence());
+ case EOpLessThanEqualComponentWise:
+ outputTriplet(out, visit, "(", " <= ", ")");
break;
- case EOpConstructMat4x3:
- outputConstructor(out, visit, node->getType(), "mat4x3", node->getSequence());
+ case EOpGreaterThanEqualComponentWise:
+ outputTriplet(out, visit, "(", " >= ", ")");
break;
- case EOpConstructMat4:
- outputConstructor(out, visit, node->getType(), "mat4", node->getSequence());
+ case EOpMod:
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(out, visit, node->getOp());
break;
- case EOpConstructStruct:
- {
- if (node->getType().isArray())
- {
- UNIMPLEMENTED();
- }
- const TString &structName = StructNameString(*node->getType().getStruct());
- mStructureHLSL->addConstructor(node->getType(), structName, node->getSequence());
- outputTriplet(out, visit, (structName + "_ctor(").c_str(), ", ", ")");
- }
- break;
- case EOpLessThan:
- outputTriplet(out, visit, "(", " < ", ")");
+ case EOpModf:
+ outputTriplet(out, visit, "modf(", ", ", ")");
break;
- case EOpGreaterThan:
- outputTriplet(out, visit, "(", " > ", ")");
+ case EOpPow:
+ outputTriplet(out, visit, "pow(", ", ", ")");
break;
- case EOpLessThanEqual:
- outputTriplet(out, visit, "(", " <= ", ")");
+ case EOpAtan:
+ ASSERT(node->getSequence()->size() == 2); // atan(x) is a unary operator
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(out, visit, node->getOp());
break;
- case EOpGreaterThanEqual:
- outputTriplet(out, visit, "(", " >= ", ")");
+ case EOpMin:
+ outputTriplet(out, visit, "min(", ", ", ")");
break;
- case EOpVectorEqual:
- outputTriplet(out, visit, "(", " == ", ")");
+ case EOpMax:
+ outputTriplet(out, visit, "max(", ", ", ")");
break;
- case EOpVectorNotEqual:
- outputTriplet(out, visit, "(", " != ", ")");
+ case EOpClamp:
+ outputTriplet(out, visit, "clamp(", ", ", ")");
break;
- case EOpMod:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "mod(");
- break;
- case EOpModf:
- outputTriplet(out, visit, "modf(", ", ", ")");
- break;
- case EOpPow:
- outputTriplet(out, visit, "pow(", ", ", ")");
- break;
- case EOpAtan:
- ASSERT(node->getSequence()->size() == 2); // atan(x) is a unary operator
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "atan(");
- break;
- case EOpMin:
- outputTriplet(out, visit, "min(", ", ", ")");
- break;
- case EOpMax:
- outputTriplet(out, visit, "max(", ", ", ")");
- break;
- case EOpClamp:
- outputTriplet(out, visit, "clamp(", ", ", ")");
- break;
- case EOpMix:
+ case EOpMix:
{
TIntermTyped *lastParamNode = (*(node->getSequence()))[2]->getAsTyped();
if (lastParamNode->getType().getBasicType() == EbtBool)
{
- // There is no HLSL equivalent for ESSL3 built-in "genType mix (genType x, genType y, genBType a)",
+ // There is no HLSL equivalent for ESSL3 built-in "genType mix (genType x, genType
+ // y, genBType a)",
// so use emulated version.
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "mix(");
+ writeEmulatedFunctionTriplet(out, visit, node->getOp());
}
else
{
outputTriplet(out, visit, "lerp(", ", ", ")");
}
+ break;
}
- break;
case EOpStep:
outputTriplet(out, visit, "step(", ", ", ")");
break;
case EOpSmoothStep:
outputTriplet(out, visit, "smoothstep(", ", ", ")");
break;
+ case EOpFrexp:
+ case EOpLdexp:
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(out, visit, node->getOp());
+ break;
case EOpDistance:
outputTriplet(out, visit, "distance(", ", ", ")");
break;
@@ -2642,30 +2077,40 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpCross:
outputTriplet(out, visit, "cross(", ", ", ")");
break;
- case EOpFaceForward:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "faceforward(");
- break;
- case EOpReflect:
- outputTriplet(out, visit, "reflect(", ", ", ")");
- break;
- case EOpRefract:
- outputTriplet(out, visit, "refract(", ", ", ")");
- break;
- case EOpOuterProduct:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "outerProduct(");
- break;
- case EOpMul:
- outputTriplet(out, visit, "(", " * ", ")");
- break;
- default: UNREACHABLE();
+ case EOpFaceforward:
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(out, visit, node->getOp());
+ break;
+ case EOpReflect:
+ outputTriplet(out, visit, "reflect(", ", ", ")");
+ break;
+ case EOpRefract:
+ outputTriplet(out, visit, "refract(", ", ", ")");
+ break;
+ case EOpOuterProduct:
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(out, visit, node->getOp());
+ break;
+ case EOpMulMatrixComponentWise:
+ outputTriplet(out, visit, "(", " * ", ")");
+ break;
+ case EOpBitfieldExtract:
+ case EOpBitfieldInsert:
+ case EOpUaddCarry:
+ case EOpUsubBorrow:
+ case EOpUmulExtended:
+ case EOpImulExtended:
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(out, visit, node->getOp());
+ break;
+ default:
+ UNREACHABLE();
}
return true;
}
-void OutputHLSL::writeSelection(TInfoSinkBase &out, TIntermSelection *node)
+void OutputHLSL::writeIfElse(TInfoSinkBase &out, TIntermIfElse *node)
{
out << "if (";
@@ -2680,8 +2125,6 @@ void OutputHLSL::writeSelection(TInfoSinkBase &out, TIntermSelection *node)
if (node->getTrueBlock())
{
// The trueBlock child node will output braces.
- ASSERT(IsSequence(node->getTrueBlock()));
-
node->getTrueBlock()->traverse(this);
// Detect true discard
@@ -2702,9 +2145,7 @@ void OutputHLSL::writeSelection(TInfoSinkBase &out, TIntermSelection *node)
outputLineDirective(out, node->getFalseBlock()->getLine().first_line);
- // Either this is "else if" or the falseBlock child node will output braces.
- ASSERT(IsSequence(node->getFalseBlock()) || node->getFalseBlock()->getAsSelectionNode() != nullptr);
-
+ // The falseBlock child node will output braces.
node->getFalseBlock()->traverse(this);
outputLineDirective(out, node->getFalseBlock()->getLine().first_line);
@@ -2720,18 +2161,19 @@ void OutputHLSL::writeSelection(TInfoSinkBase &out, TIntermSelection *node)
}
}
-bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
+bool OutputHLSL::visitTernary(Visit, TIntermTernary *)
{
- TInfoSinkBase &out = getInfoSink();
+ // Ternary ops should have been already converted to something else in the AST. HLSL ternary
+ // operator doesn't short-circuit, so it's not the same as the GLSL ternary operator.
+ UNREACHABLE();
+ return false;
+}
- ASSERT(!node->usesTernaryOperator());
+bool OutputHLSL::visitIfElse(Visit visit, TIntermIfElse *node)
+{
+ TInfoSinkBase &out = getInfoSink();
- if (!mInsideFunction)
- {
- // This is part of unfolded global initialization.
- mDeferredGlobalInitializers.push_back(node);
- return false;
- }
+ ASSERT(mInsideFunction);
// D3D errors when there is a gradient operation in a loop in an unflattened if.
if (mShaderType == GL_FRAGMENT_SHADER && mCurrentFunctionMetadata->hasGradientLoop(node))
@@ -2739,7 +2181,7 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
out << "FLATTEN ";
}
- writeSelection(out, node);
+ writeIfElse(out, node);
return false;
}
@@ -2748,17 +2190,13 @@ bool OutputHLSL::visitSwitch(Visit visit, TIntermSwitch *node)
{
TInfoSinkBase &out = getInfoSink();
- if (node->getStatementList())
- {
- node->setStatementList(RemoveSwitchFallThrough::removeFallThrough(node->getStatementList()));
- outputTriplet(out, visit, "switch (", ") ", "");
- // The curly braces get written when visiting the statementList aggregate
- }
- else
+ ASSERT(node->getStatementList());
+ if (visit == PreVisit)
{
- // No statementList, so it won't output curly braces
- outputTriplet(out, visit, "switch (", ") {", "}\n");
+ node->setStatementList(RemoveSwitchFallThrough(node->getStatementList(), mPerfDiagnostics));
}
+ outputTriplet(out, visit, "switch (", ") ", "");
+ // The curly braces get written when visiting the statementList block.
return true;
}
@@ -2789,8 +2227,8 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
mNestedLoopDepth++;
bool wasDiscontinuous = mInsideDiscontinuousLoop;
- mInsideDiscontinuousLoop = mInsideDiscontinuousLoop ||
- mCurrentFunctionMetadata->mDiscontinuousLoops.count(node) > 0;
+ mInsideDiscontinuousLoop =
+ mInsideDiscontinuousLoop || mCurrentFunctionMetadata->mDiscontinuousLoops.count(node) > 0;
TInfoSinkBase &out = getInfoSink();
@@ -2843,7 +2281,6 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
if (node->getBody())
{
// The loop body node will output braces.
- ASSERT(IsSequence(node->getBody()));
node->getBody()->traverse(this);
}
else
@@ -2858,11 +2295,11 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
if (node->getType() == ELoopDoWhile)
{
outputLineDirective(out, node->getCondition()->getLine().first_line);
- out << "while(\n";
+ out << "while (";
node->getCondition()->traverse(this);
- out << ");";
+ out << ");\n";
}
out << "}\n";
@@ -2875,89 +2312,47 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node)
{
- TInfoSinkBase &out = getInfoSink();
-
- switch (node->getFlowOp())
+ if (visit == PreVisit)
{
- case EOpKill:
- outputTriplet(out, visit, "discard;\n", "", "");
- break;
- case EOpBreak:
- if (visit == PreVisit)
- {
- if (mNestedLoopDepth > 1)
- {
- mUsesNestedBreak = true;
- }
-
- if (mExcessiveLoopIndex)
- {
- out << "{Break";
- mExcessiveLoopIndex->traverse(this);
- out << " = true; break;}\n";
- }
- else
- {
- out << "break;\n";
- }
- }
- break;
- case EOpContinue:
- outputTriplet(out, visit, "continue;\n", "", "");
- break;
- case EOpReturn:
- if (visit == PreVisit)
- {
- if (node->getExpression())
- {
- out << "return ";
- }
- else
- {
- out << "return;\n";
- }
- }
- else if (visit == PostVisit)
- {
- if (node->getExpression())
- {
- out << ";\n";
- }
- }
- break;
- default: UNREACHABLE();
- }
-
- return true;
-}
+ TInfoSinkBase &out = getInfoSink();
-bool OutputHLSL::isSingleStatement(TIntermNode *node)
-{
- TIntermAggregate *aggregate = node->getAsAggregate();
-
- if (aggregate)
- {
- if (aggregate->getOp() == EOpSequence)
+ switch (node->getFlowOp())
{
- return false;
- }
- else if (aggregate->getOp() == EOpDeclaration)
- {
- // Declaring multiple comma-separated variables must be considered multiple statements
- // because each individual declaration has side effects which are visible in the next.
- return false;
- }
- else
- {
- for (TIntermSequence::iterator sit = aggregate->getSequence()->begin(); sit != aggregate->getSequence()->end(); sit++)
- {
- if (!isSingleStatement(*sit))
+ case EOpKill:
+ out << "discard";
+ break;
+ case EOpBreak:
+ if (mNestedLoopDepth > 1)
{
- return false;
+ mUsesNestedBreak = true;
}
- }
- return true;
+ if (mExcessiveLoopIndex)
+ {
+ out << "{Break";
+ mExcessiveLoopIndex->traverse(this);
+ out << " = true; break;}\n";
+ }
+ else
+ {
+ out << "break";
+ }
+ break;
+ case EOpContinue:
+ out << "continue";
+ break;
+ case EOpReturn:
+ if (node->getExpression())
+ {
+ out << "return ";
+ }
+ else
+ {
+ out << "return";
+ }
+ break;
+ default:
+ UNREACHABLE();
}
}
@@ -2965,28 +2360,29 @@ bool OutputHLSL::isSingleStatement(TIntermNode *node)
}
// Handle loops with more than 254 iterations (unsupported by D3D9) by splitting them
-// (The D3D documentation says 255 iterations, but the compiler complains at anything more than 254).
+// (The D3D documentation says 255 iterations, but the compiler complains at anything more than
+// 254).
bool OutputHLSL::handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node)
{
const int MAX_LOOP_ITERATIONS = 254;
// Parse loops of the form:
// for(int index = initial; index [comparator] limit; index += increment)
- TIntermSymbol *index = NULL;
+ TIntermSymbol *index = nullptr;
TOperator comparator = EOpNull;
- int initial = 0;
- int limit = 0;
- int increment = 0;
+ int initial = 0;
+ int limit = 0;
+ int increment = 0;
// Parse index name and intial value
if (node->getInit())
{
- TIntermAggregate *init = node->getInit()->getAsAggregate();
+ TIntermDeclaration *init = node->getInit()->getAsDeclarationNode();
if (init)
{
TIntermSequence *sequence = init->getSequence();
- TIntermTyped *variable = (*sequence)[0]->getAsTyped();
+ TIntermTyped *variable = (*sequence)[0]->getAsTyped();
if (variable && variable->getQualifier() == EvqTemporary)
{
@@ -2994,14 +2390,14 @@ bool OutputHLSL::handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node)
if (assign->getOp() == EOpInitialize)
{
- TIntermSymbol *symbol = assign->getLeft()->getAsSymbolNode();
+ TIntermSymbol *symbol = assign->getLeft()->getAsSymbolNode();
TIntermConstantUnion *constant = assign->getRight()->getAsConstantUnion();
if (symbol && constant)
{
if (constant->getBasicType() == EbtInt && constant->isScalar())
{
- index = symbol;
+ index = symbol;
initial = constant->getIConst(0);
}
}
@@ -3011,7 +2407,7 @@ bool OutputHLSL::handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node)
}
// Parse comparator and limit value
- if (index != NULL && node->getCondition())
+ if (index != nullptr && node->getCondition())
{
TIntermBinary *test = node->getCondition()->getAsBinaryNode();
@@ -3024,21 +2420,21 @@ bool OutputHLSL::handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node)
if (constant->getBasicType() == EbtInt && constant->isScalar())
{
comparator = test->getOp();
- limit = constant->getIConst(0);
+ limit = constant->getIConst(0);
}
}
}
}
// Parse increment
- if (index != NULL && comparator != EOpNull && node->getExpression())
+ if (index != nullptr && comparator != EOpNull && node->getExpression())
{
TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode();
- TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode();
+ TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode();
if (binaryTerminal)
{
- TOperator op = binaryTerminal->getOp();
+ TOperator op = binaryTerminal->getOp();
TIntermConstantUnion *constant = binaryTerminal->getRight()->getAsConstantUnion();
if (constant)
@@ -3049,9 +2445,14 @@ bool OutputHLSL::handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node)
switch (op)
{
- case EOpAddAssign: increment = value; break;
- case EOpSubAssign: increment = -value; break;
- default: UNIMPLEMENTED();
+ case EOpAddAssign:
+ increment = value;
+ break;
+ case EOpSubAssign:
+ increment = -value;
+ break;
+ default:
+ UNIMPLEMENTED();
}
}
}
@@ -3062,16 +2463,25 @@ bool OutputHLSL::handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node)
switch (op)
{
- case EOpPostIncrement: increment = 1; break;
- case EOpPostDecrement: increment = -1; break;
- case EOpPreIncrement: increment = 1; break;
- case EOpPreDecrement: increment = -1; break;
- default: UNIMPLEMENTED();
+ case EOpPostIncrement:
+ increment = 1;
+ break;
+ case EOpPostDecrement:
+ increment = -1;
+ break;
+ case EOpPreIncrement:
+ increment = 1;
+ break;
+ case EOpPreDecrement:
+ increment = -1;
+ break;
+ default:
+ UNIMPLEMENTED();
}
}
}
- if (index != NULL && comparator != EOpNull && increment != 0)
+ if (index != nullptr && comparator != EOpNull && increment != 0)
{
if (comparator == EOpLessThanEqual)
{
@@ -3085,11 +2495,11 @@ bool OutputHLSL::handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node)
if (iterations <= MAX_LOOP_ITERATIONS)
{
- return false; // Not an excessive loop
+ return false; // Not an excessive loop
}
TIntermSymbol *restoreIndex = mExcessiveLoopIndex;
- mExcessiveLoopIndex = index;
+ mExcessiveLoopIndex = index;
out << "{int ";
index->traverse(this);
@@ -3111,13 +2521,14 @@ bool OutputHLSL::handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node)
out << ") {\n";
}
- if (iterations <= MAX_LOOP_ITERATIONS) // Last loop fragment
+ if (iterations <= MAX_LOOP_ITERATIONS) // Last loop fragment
{
- mExcessiveLoopIndex = NULL; // Stops setting the Break flag
+ mExcessiveLoopIndex = nullptr; // Stops setting the Break flag
}
// for(int index = initial; index < clampedLimit; index += increment)
- const char *unroll = mCurrentFunctionMetadata->hasGradientInCallGraph(node) ? "LOOP" : "";
+ const char *unroll =
+ mCurrentFunctionMetadata->hasGradientInCallGraph(node) ? "LOOP" : "";
out << unroll << " for(";
index->traverse(this);
@@ -3163,10 +2574,11 @@ bool OutputHLSL::handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node)
return true;
}
- else UNIMPLEMENTED();
+ else
+ UNIMPLEMENTED();
}
- return false; // Not handled as an excessive loop
+ return false; // Not handled as an excessive loop
}
void OutputHLSL::outputTriplet(TInfoSinkBase &out,
@@ -3218,7 +2630,7 @@ TString OutputHLSL::argumentString(const TIntermSymbol *symbol)
}
else
{
- nameStr = DecorateIfNeeded(name);
+ nameStr = DecorateVariableIfNeeded(name);
}
if (IsSampler(type.getBasicType()))
@@ -3238,7 +2650,44 @@ TString OutputHLSL::argumentString(const TIntermSymbol *symbol)
}
}
- return QualifierString(qualifier) + " " + TypeString(type) + " " + nameStr + ArrayString(type);
+ TStringStream argString;
+ argString << QualifierString(qualifier) << " " << TypeString(type) << " " << nameStr
+ << ArrayString(type);
+
+ // If the structure parameter contains samplers, they need to be passed into the function as
+ // separate parameters. HLSL doesn't natively support samplers in structs.
+ if (type.isStructureContainingSamplers())
+ {
+ ASSERT(qualifier != EvqOut && qualifier != EvqInOut);
+ TVector<TIntermSymbol *> samplerSymbols;
+ type.createSamplerSymbols("angle" + nameStr, "", &samplerSymbols, nullptr, mSymbolTable);
+ for (const TIntermSymbol *sampler : samplerSymbols)
+ {
+ const TType &samplerType = sampler->getType();
+ if (mOutputType == SH_HLSL_4_1_OUTPUT)
+ {
+ argString << ", const uint " << sampler->getSymbol() << ArrayString(samplerType);
+ }
+ else if (mOutputType == SH_HLSL_4_0_FL9_3_OUTPUT)
+ {
+ ASSERT(IsSampler(samplerType.getBasicType()));
+ argString << ", " << QualifierString(qualifier) << " "
+ << TextureString(samplerType.getBasicType()) << " texture_"
+ << sampler->getSymbol() << ArrayString(samplerType) << ", "
+ << QualifierString(qualifier) << " "
+ << SamplerString(samplerType.getBasicType()) << " sampler_"
+ << sampler->getSymbol() << ArrayString(samplerType);
+ }
+ else
+ {
+ ASSERT(IsSampler(samplerType.getBasicType()));
+ argString << ", " << QualifierString(qualifier) << " " << TypeString(samplerType)
+ << " " << sampler->getSymbol() << ArrayString(samplerType);
+ }
+ }
+ }
+
+ return argString.str();
}
TString OutputHLSL::initializer(const TType &type)
@@ -3259,22 +2708,24 @@ TString OutputHLSL::initializer(const TType &type)
return "{" + string + "}";
}
-void OutputHLSL::outputConstructor(TInfoSinkBase &out,
- Visit visit,
- const TType &type,
- const char *name,
- const TIntermSequence *parameters)
+void OutputHLSL::outputConstructor(TInfoSinkBase &out, Visit visit, TIntermAggregate *node)
{
- if (type.isArray())
- {
- UNIMPLEMENTED();
- }
+ // Array constructors should have been already pruned from the code.
+ ASSERT(!node->getType().isArray());
if (visit == PreVisit)
{
- mStructureHLSL->addConstructor(type, name, parameters);
-
- out << name << "(";
+ TString constructorName;
+ if (node->getBasicType() == EbtStruct)
+ {
+ constructorName = mStructureHLSL->addStructConstructor(*node->getType().getStruct());
+ }
+ else
+ {
+ constructorName =
+ mStructureHLSL->addBuiltInConstructor(node->getType(), node->getSequence());
+ }
+ out << constructorName << "(";
}
else if (visit == InVisit)
{
@@ -3292,12 +2743,12 @@ const TConstantUnion *OutputHLSL::writeConstantUnion(TInfoSinkBase &out,
{
const TConstantUnion *constUnionIterated = constUnion;
- const TStructure* structure = type.getStruct();
+ const TStructure *structure = type.getStruct();
if (structure)
{
- out << StructNameString(*structure) + "_ctor(";
+ out << mStructureHLSL->addStructConstructor(*structure) << "(";
- const TFieldList& fields = structure->fields();
+ const TFieldList &fields = structure->fields();
for (size_t i = 0; i < fields.size(); i++)
{
@@ -3314,14 +2765,14 @@ const TConstantUnion *OutputHLSL::writeConstantUnion(TInfoSinkBase &out,
}
else
{
- size_t size = type.getObjectSize();
+ size_t size = type.getObjectSize();
bool writeType = size > 1;
if (writeType)
{
out << TypeString(type) << "(";
}
- constUnionIterated = WriteConstantUnionArray(out, constUnionIterated, size);
+ constUnionIterated = writeConstantUnionArray(out, constUnionIterated, size);
if (writeType)
{
out << ")";
@@ -3331,13 +2782,23 @@ const TConstantUnion *OutputHLSL::writeConstantUnion(TInfoSinkBase &out,
return constUnionIterated;
}
-void OutputHLSL::writeEmulatedFunctionTriplet(TInfoSinkBase &out, Visit visit, const char *preStr)
+void OutputHLSL::writeEmulatedFunctionTriplet(TInfoSinkBase &out, Visit visit, TOperator op)
{
- TString preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preStr);
- outputTriplet(out, visit, preString.c_str(), ", ", ")");
+ if (visit == PreVisit)
+ {
+ const char *opStr = GetOperatorString(op);
+ BuiltInFunctionEmulator::WriteEmulatedFunctionName(out, opStr);
+ out << "(";
+ }
+ else
+ {
+ outputTriplet(out, visit, nullptr, ", ", ")");
+ }
}
-bool OutputHLSL::writeSameSymbolInitializer(TInfoSinkBase &out, TIntermSymbol *symbolNode, TIntermTyped *expression)
+bool OutputHLSL::writeSameSymbolInitializer(TInfoSinkBase &out,
+ TIntermSymbol *symbolNode,
+ TIntermTyped *expression)
{
sh::SearchSymbol searchSymbol(symbolNode->getSymbol());
expression->traverse(&searchSymbol);
@@ -3362,52 +2823,40 @@ bool OutputHLSL::canWriteAsHLSLLiteral(TIntermTyped *expression)
{
// We support writing constant unions and constructors that only take constant unions as
// parameters as HLSL literals.
- if (expression->getAsConstantUnion())
- {
- return true;
- }
- if (expression->getQualifier() != EvqConst || !expression->getAsAggregate() ||
- !expression->getAsAggregate()->isConstructor())
- {
- return false;
- }
- TIntermAggregate *constructor = expression->getAsAggregate();
- for (TIntermNode *&node : *constructor->getSequence())
- {
- if (!node->getAsConstantUnion())
- return false;
- }
- return true;
+ return !expression->getType().isArrayOfArrays() &&
+ (expression->getAsConstantUnion() ||
+ expression->isConstructorWithOnlyConstantUnionParameters());
}
bool OutputHLSL::writeConstantInitialization(TInfoSinkBase &out,
TIntermSymbol *symbolNode,
- TIntermTyped *expression)
+ TIntermTyped *initializer)
{
- if (canWriteAsHLSLLiteral(expression))
+ if (canWriteAsHLSLLiteral(initializer))
{
symbolNode->traverse(this);
- if (expression->getType().isArray())
+ ASSERT(!symbolNode->getType().isArrayOfArrays());
+ if (symbolNode->getType().isArray())
{
- out << "[" << expression->getType().getArraySize() << "]";
+ out << "[" << symbolNode->getType().getOutermostArraySize() << "]";
}
out << " = {";
- if (expression->getAsConstantUnion())
+ if (initializer->getAsConstantUnion())
{
- TIntermConstantUnion *nodeConst = expression->getAsConstantUnion();
+ TIntermConstantUnion *nodeConst = initializer->getAsConstantUnion();
const TConstantUnion *constUnion = nodeConst->getUnionArrayPointer();
- WriteConstantUnionArray(out, constUnion, nodeConst->getType().getObjectSize());
+ writeConstantUnionArray(out, constUnion, nodeConst->getType().getObjectSize());
}
else
{
- TIntermAggregate *constructor = expression->getAsAggregate();
+ TIntermAggregate *constructor = initializer->getAsAggregate();
ASSERT(constructor != nullptr);
for (TIntermNode *&node : *constructor->getSequence())
{
TIntermConstantUnion *nodeConst = node->getAsConstantUnion();
ASSERT(nodeConst);
const TConstantUnion *constUnion = nodeConst->getUnionArrayPointer();
- WriteConstantUnionArray(out, constUnion, nodeConst->getType().getObjectSize());
+ writeConstantUnionArray(out, constUnion, nodeConst->getType().getObjectSize());
if (node != constructor->getSequence()->back())
{
out << ", ";
@@ -3420,47 +2869,6 @@ bool OutputHLSL::writeConstantInitialization(TInfoSinkBase &out,
return false;
}
-void OutputHLSL::writeDeferredGlobalInitializers(TInfoSinkBase &out)
-{
- out << "#define ANGLE_USES_DEFERRED_INIT\n"
- << "\n"
- << "void initializeDeferredGlobals()\n"
- << "{\n";
-
- for (const auto &deferredGlobal : mDeferredGlobalInitializers)
- {
- TIntermBinary *binary = deferredGlobal->getAsBinaryNode();
- TIntermSelection *selection = deferredGlobal->getAsSelectionNode();
- if (binary != nullptr)
- {
- TIntermSymbol *symbol = binary->getLeft()->getAsSymbolNode();
- TIntermTyped *expression = binary->getRight();
- ASSERT(symbol);
- ASSERT(symbol->getQualifier() == EvqGlobal && expression->getQualifier() != EvqConst);
-
- out << " " << Decorate(symbol->getSymbol()) << " = ";
-
- if (!writeSameSymbolInitializer(out, symbol, expression))
- {
- ASSERT(mInfoSinkStack.top() == &out);
- expression->traverse(this);
- }
- out << ";\n";
- }
- else if (selection != nullptr)
- {
- writeSelection(out, selection);
- }
- else
- {
- UNREACHABLE();
- }
- }
-
- out << "}\n"
- << "\n";
-}
-
TString OutputHLSL::addStructEqualityFunction(const TStructure &structure)
{
const TFieldList &fields = structure.fields();
@@ -3476,18 +2884,19 @@ TString OutputHLSL::addStructEqualityFunction(const TStructure &structure)
const TString &structNameString = StructNameString(structure);
StructEqualityFunction *function = new StructEqualityFunction();
- function->structure = &structure;
- function->functionName = "angle_eq_" + structNameString;
+ function->structure = &structure;
+ function->functionName = "angle_eq_" + structNameString;
TInfoSinkBase fnOut;
- fnOut << "bool " << function->functionName << "(" << structNameString << " a, " << structNameString + " b)\n"
+ fnOut << "bool " << function->functionName << "(" << structNameString << " a, "
+ << structNameString + " b)\n"
<< "{\n"
" return ";
for (size_t i = 0; i < fields.size(); i++)
{
- const TField *field = fields[i];
+ const TField *field = fields[i];
const TType *fieldType = field->type();
const TString &fieldNameA = "a." + Decorate(field->name());
@@ -3507,7 +2916,8 @@ TString OutputHLSL::addStructEqualityFunction(const TStructure &structure)
fnOut << ")";
}
- fnOut << ";\n" << "}\n";
+ fnOut << ";\n"
+ << "}\n";
function->functionDefinition = fnOut.c_str();
@@ -3517,7 +2927,7 @@ TString OutputHLSL::addStructEqualityFunction(const TStructure &structure)
return function->functionName;
}
-TString OutputHLSL::addArrayEqualityFunction(const TType& type)
+TString OutputHLSL::addArrayEqualityFunction(const TType &type)
{
for (const auto &eqFunction : mArrayEqualityFunctions)
{
@@ -3527,33 +2937,31 @@ TString OutputHLSL::addArrayEqualityFunction(const TType& type)
}
}
- const TString &typeName = TypeString(type);
+ TType elementType(type);
+ elementType.toArrayElementType();
ArrayHelperFunction *function = new ArrayHelperFunction();
- function->type = type;
-
- TInfoSinkBase fnNameOut;
- fnNameOut << "angle_eq_" << type.getArraySize() << "_" << typeName;
- function->functionName = fnNameOut.c_str();
+ function->type = type;
- TType nonArrayType = type;
- nonArrayType.clearArrayness();
+ function->functionName = ArrayHelperFunctionName("angle_eq", type);
TInfoSinkBase fnOut;
- fnOut << "bool " << function->functionName << "("
- << typeName << " a[" << type.getArraySize() << "], "
- << typeName << " b[" << type.getArraySize() << "])\n"
+ const TString &typeName = TypeString(type);
+ fnOut << "bool " << function->functionName << "(" << typeName << " a" << ArrayString(type)
+ << ", " << typeName << " b" << ArrayString(type) << ")\n"
<< "{\n"
- " for (int i = 0; i < " << type.getArraySize() << "; ++i)\n"
+ " for (int i = 0; i < "
+ << type.getOutermostArraySize()
+ << "; ++i)\n"
" {\n"
" if (";
- outputEqual(PreVisit, nonArrayType, EOpNotEqual, fnOut);
+ outputEqual(PreVisit, elementType, EOpNotEqual, fnOut);
fnOut << "a[i]";
- outputEqual(InVisit, nonArrayType, EOpNotEqual, fnOut);
+ outputEqual(InVisit, elementType, EOpNotEqual, fnOut);
fnOut << "b[i]";
- outputEqual(PostVisit, nonArrayType, EOpNotEqual, fnOut);
+ outputEqual(PostVisit, elementType, EOpNotEqual, fnOut);
fnOut << ") { return false; }\n"
" }\n"
@@ -3568,7 +2976,7 @@ TString OutputHLSL::addArrayEqualityFunction(const TType& type)
return function->functionName;
}
-TString OutputHLSL::addArrayAssignmentFunction(const TType& type)
+TString OutputHLSL::addArrayAssignmentFunction(const TType &type)
{
for (const auto &assignFunction : mArrayAssignmentFunctions)
{
@@ -3578,26 +2986,35 @@ TString OutputHLSL::addArrayAssignmentFunction(const TType& type)
}
}
- const TString &typeName = TypeString(type);
+ TType elementType(type);
+ elementType.toArrayElementType();
ArrayHelperFunction function;
function.type = type;
- TInfoSinkBase fnNameOut;
- fnNameOut << "angle_assign_" << type.getArraySize() << "_" << typeName;
- function.functionName = fnNameOut.c_str();
+ function.functionName = ArrayHelperFunctionName("angle_assign", type);
TInfoSinkBase fnOut;
- fnOut << "void " << function.functionName << "(out "
- << typeName << " a[" << type.getArraySize() << "], "
- << typeName << " b[" << type.getArraySize() << "])\n"
- << "{\n"
- " for (int i = 0; i < " << type.getArraySize() << "; ++i)\n"
- " {\n"
- " a[i] = b[i];\n"
- " }\n"
- "}\n";
+ const TString &typeName = TypeString(type);
+ fnOut << "void " << function.functionName << "(out " << typeName << " a" << ArrayString(type)
+ << ", " << typeName << " b" << ArrayString(type) << ")\n"
+ << "{\n"
+ " for (int i = 0; i < "
+ << type.getOutermostArraySize()
+ << "; ++i)\n"
+ " {\n"
+ " ";
+
+ outputAssign(PreVisit, elementType, fnOut);
+ fnOut << "a[i]";
+ outputAssign(InVisit, elementType, fnOut);
+ fnOut << "b[i]";
+ outputAssign(PostVisit, elementType, fnOut);
+
+ fnOut << ";\n"
+ " }\n"
+ "}\n";
function.functionDefinition = fnOut.c_str();
@@ -3606,7 +3023,7 @@ TString OutputHLSL::addArrayAssignmentFunction(const TType& type)
return function.functionName;
}
-TString OutputHLSL::addArrayConstructIntoFunction(const TType& type)
+TString OutputHLSL::addArrayConstructIntoFunction(const TType &type)
{
for (const auto &constructIntoFunction : mArrayConstructIntoFunctions)
{
@@ -3616,29 +3033,34 @@ TString OutputHLSL::addArrayConstructIntoFunction(const TType& type)
}
}
- const TString &typeName = TypeString(type);
+ TType elementType(type);
+ elementType.toArrayElementType();
ArrayHelperFunction function;
function.type = type;
- TInfoSinkBase fnNameOut;
- fnNameOut << "angle_construct_into_" << type.getArraySize() << "_" << typeName;
- function.functionName = fnNameOut.c_str();
+ function.functionName = ArrayHelperFunctionName("angle_construct_into", type);
TInfoSinkBase fnOut;
- fnOut << "void " << function.functionName << "(out "
- << typeName << " a[" << type.getArraySize() << "]";
- for (int i = 0; i < type.getArraySize(); ++i)
+ const TString &typeName = TypeString(type);
+ fnOut << "void " << function.functionName << "(out " << typeName << " a" << ArrayString(type);
+ for (unsigned int i = 0u; i < type.getOutermostArraySize(); ++i)
{
- fnOut << ", " << typeName << " b" << i;
+ fnOut << ", " << typeName << " b" << i << ArrayString(elementType);
}
fnOut << ")\n"
"{\n";
- for (int i = 0; i < type.getArraySize(); ++i)
+ for (unsigned int i = 0u; i < type.getOutermostArraySize(); ++i)
{
- fnOut << " a[" << i << "] = b" << i << ";\n";
+ fnOut << " ";
+ outputAssign(PreVisit, elementType, fnOut);
+ fnOut << "a[" << i << "]";
+ outputAssign(InVisit, elementType, fnOut);
+ fnOut << "b" << i;
+ outputAssign(PostVisit, elementType, fnOut);
+ fnOut << ";\n";
}
fnOut << "}\n";
@@ -3651,14 +3073,12 @@ TString OutputHLSL::addArrayConstructIntoFunction(const TType& type)
void OutputHLSL::ensureStructDefined(const TType &type)
{
- TStructure *structure = type.getStruct();
-
+ const TStructure *structure = type.getStruct();
if (structure)
{
- mStructureHLSL->addConstructor(type, StructNameString(*structure), nullptr);
+ ASSERT(type.getBasicType() == EbtStruct);
+ mStructureHLSL->ensureStructDefined(*structure);
}
}
-
-
-}
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h
index 8756d0ba4c..014f4f5002 100644
--- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h
@@ -8,67 +8,94 @@
#define COMPILER_TRANSLATOR_OUTPUTHLSL_H_
#include <list>
-#include <set>
#include <map>
#include <stack>
#include "angle_gl.h"
#include "compiler/translator/ASTMetadataHLSL.h"
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/ParseContext.h"
+#include "compiler/translator/Compiler.h"
+#include "compiler/translator/FlagStd140Structs.h"
+#include "compiler/translator/IntermTraverse.h"
class BuiltInFunctionEmulator;
namespace sh
{
-class UnfoldShortCircuit;
class StructureHLSL;
+class TextureFunctionHLSL;
+class TSymbolTable;
+class ImageFunctionHLSL;
+class UnfoldShortCircuit;
class UniformHLSL;
-typedef std::map<TString, TIntermSymbol*> ReferencedSymbols;
+typedef std::map<TString, TIntermSymbol *> ReferencedSymbols;
class OutputHLSL : public TIntermTraverser
{
public:
- OutputHLSL(sh::GLenum shaderType, int shaderVersion,
- const TExtensionBehavior &extensionBehavior,
- const char *sourcePath, ShShaderOutput outputType,
- int numRenderTargets, const std::vector<Uniform> &uniforms,
- int compileOptions);
+ OutputHLSL(sh::GLenum shaderType,
+ int shaderVersion,
+ const TExtensionBehavior &extensionBehavior,
+ const char *sourcePath,
+ ShShaderOutput outputType,
+ int numRenderTargets,
+ const std::vector<Uniform> &uniforms,
+ ShCompileOptions compileOptions,
+ TSymbolTable *symbolTable,
+ PerformanceDiagnostics *perfDiagnostics);
~OutputHLSL();
void output(TIntermNode *treeRoot, TInfoSinkBase &objSink);
- const std::map<std::string, unsigned int> &getInterfaceBlockRegisterMap() const;
+ const std::map<std::string, unsigned int> &getUniformBlockRegisterMap() const;
const std::map<std::string, unsigned int> &getUniformRegisterMap() const;
static TString initializer(const TType &type);
- TInfoSinkBase &getInfoSink() { ASSERT(!mInfoSinkStack.empty()); return *mInfoSinkStack.top(); }
+ TInfoSinkBase &getInfoSink()
+ {
+ ASSERT(!mInfoSinkStack.empty());
+ return *mInfoSinkStack.top();
+ }
static bool canWriteAsHLSLLiteral(TIntermTyped *expression);
protected:
- void header(TInfoSinkBase &out, const BuiltInFunctionEmulator *builtInFunctionEmulator);
+ void header(TInfoSinkBase &out,
+ const std::vector<MappedStruct> &std140Structs,
+ const BuiltInFunctionEmulator *builtInFunctionEmulator) const;
+
+ void writeFloat(TInfoSinkBase &out, float f);
+ void writeSingleConstant(TInfoSinkBase &out, const TConstantUnion *const constUnion);
+ const TConstantUnion *writeConstantUnionArray(TInfoSinkBase &out,
+ const TConstantUnion *const constUnion,
+ const size_t size);
// Visit AST nodes and output their code to the body stream
- void visitSymbol(TIntermSymbol*);
- void visitRaw(TIntermRaw*);
- void visitConstantUnion(TIntermConstantUnion*);
- bool visitBinary(Visit visit, TIntermBinary*);
- bool visitUnary(Visit visit, TIntermUnary*);
- bool visitSelection(Visit visit, TIntermSelection*);
- bool visitSwitch(Visit visit, TIntermSwitch *);
- bool visitCase(Visit visit, TIntermCase *);
- bool visitAggregate(Visit visit, TIntermAggregate*);
- bool visitLoop(Visit visit, TIntermLoop*);
- bool visitBranch(Visit visit, TIntermBranch*);
-
- bool isSingleStatement(TIntermNode *node);
+ void visitSymbol(TIntermSymbol *) override;
+ void visitRaw(TIntermRaw *) override;
+ void visitConstantUnion(TIntermConstantUnion *) override;
+ bool visitSwizzle(Visit visit, TIntermSwizzle *node) override;
+ bool visitBinary(Visit visit, TIntermBinary *) override;
+ bool visitUnary(Visit visit, TIntermUnary *) override;
+ bool visitTernary(Visit visit, TIntermTernary *) override;
+ bool visitIfElse(Visit visit, TIntermIfElse *) override;
+ bool visitSwitch(Visit visit, TIntermSwitch *) override;
+ bool visitCase(Visit visit, TIntermCase *) override;
+ bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override;
+ bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
+ bool visitAggregate(Visit visit, TIntermAggregate *) override;
+ bool visitBlock(Visit visit, TIntermBlock *node) override;
+ bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override;
+ bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
+ bool visitLoop(Visit visit, TIntermLoop *) override;
+ bool visitBranch(Visit visit, TIntermBranch *) override;
+
bool handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node);
- // Emit one of three strings depending on traverse phase. Called with literal strings so using const char* instead of TString.
+ // Emit one of three strings depending on traverse phase. Called with literal strings so using
+ // const char* instead of TString.
void outputTriplet(TInfoSinkBase &out,
Visit visit,
const char *preString,
@@ -76,32 +103,28 @@ class OutputHLSL : public TIntermTraverser
const char *postString);
void outputLineDirective(TInfoSinkBase &out, int line);
TString argumentString(const TIntermSymbol *symbol);
- int vectorSize(const TType &type) const;
-
- // Emit constructor. Called with literal names so using const char* instead of TString.
- void outputConstructor(TInfoSinkBase &out,
- Visit visit,
- const TType &type,
- const char *name,
- const TIntermSequence *parameters);
+
+ void outputConstructor(TInfoSinkBase &out, Visit visit, TIntermAggregate *node);
const TConstantUnion *writeConstantUnion(TInfoSinkBase &out,
const TType &type,
const TConstantUnion *constUnion);
void outputEqual(Visit visit, const TType &type, TOperator op, TInfoSinkBase &out);
+ void outputAssign(Visit visit, const TType &type, TInfoSinkBase &out);
- void writeEmulatedFunctionTriplet(TInfoSinkBase &out, Visit visit, const char *preStr);
- void makeFlaggedStructMaps(const std::vector<TIntermTyped *> &flaggedStructs);
+ void writeEmulatedFunctionTriplet(TInfoSinkBase &out, Visit visit, TOperator op);
- // Returns true if it found a 'same symbol' initializer (initializer that references the variable it's initting)
- bool writeSameSymbolInitializer(TInfoSinkBase &out, TIntermSymbol *symbolNode, TIntermTyped *expression);
+ // Returns true if it found a 'same symbol' initializer (initializer that references the
+ // variable it's initting)
+ bool writeSameSymbolInitializer(TInfoSinkBase &out,
+ TIntermSymbol *symbolNode,
+ TIntermTyped *expression);
// Returns true if variable initializer could be written using literal {} notation.
bool writeConstantInitialization(TInfoSinkBase &out,
TIntermSymbol *symbolNode,
TIntermTyped *expression);
- void writeDeferredGlobalInitializers(TInfoSinkBase &out);
- void writeSelection(TInfoSinkBase &out, TIntermSelection *node);
+ void writeIfElse(TInfoSinkBase &out, TIntermIfElse *node);
// Returns the function name
TString addStructEqualityFunction(const TStructure &structure);
@@ -117,7 +140,7 @@ class OutputHLSL : public TIntermTraverser
const TExtensionBehavior &mExtensionBehavior;
const char *mSourcePath;
const ShShaderOutput mOutputType;
- int mCompileOptions;
+ ShCompileOptions mCompileOptions;
bool mInsideFunction;
@@ -126,49 +149,23 @@ class OutputHLSL : public TIntermTraverser
TInfoSinkBase mBody;
TInfoSinkBase mFooter;
- // A stack is useful when we want to traverse in the header, or in helper functions, but not always
- // write to the body. Instead use an InfoSink stack to keep our current state intact.
+ // A stack is useful when we want to traverse in the header, or in helper functions, but not
+ // always write to the body. Instead use an InfoSink stack to keep our current state intact.
// TODO (jmadill): Just passing an InfoSink in function parameters would be simpler.
std::stack<TInfoSinkBase *> mInfoSinkStack;
ReferencedSymbols mReferencedUniforms;
- ReferencedSymbols mReferencedInterfaceBlocks;
+ ReferencedSymbols mReferencedUniformBlocks;
ReferencedSymbols mReferencedAttributes;
ReferencedSymbols mReferencedVaryings;
ReferencedSymbols mReferencedOutputVariables;
StructureHLSL *mStructureHLSL;
UniformHLSL *mUniformHLSL;
-
- struct TextureFunction
- {
- enum Method
- {
- IMPLICIT, // Mipmap LOD determined implicitly (standard lookup)
- BIAS,
- LOD,
- LOD0,
- LOD0BIAS,
- SIZE, // textureSize()
- FETCH,
- GRAD
- };
-
- TBasicType sampler;
- int coords;
- bool proj;
- bool offset;
- Method method;
-
- TString name() const;
-
- bool operator<(const TextureFunction &rhs) const;
- };
-
- typedef std::set<TextureFunction> TextureFunctionSet;
+ TextureFunctionHLSL *mTextureFunctionHLSL;
+ ImageFunctionHLSL *mImageFunctionHLSL;
// Parameters determining what goes in the header output
- TextureFunctionSet mUsesTexture;
bool mUsesFragColor;
bool mUsesFragData;
bool mUsesDepthRange;
@@ -177,16 +174,23 @@ class OutputHLSL : public TIntermTraverser
bool mUsesFrontFacing;
bool mUsesPointSize;
bool mUsesInstanceID;
+ bool mHasMultiviewExtensionEnabled;
+ bool mUsesViewID;
+ bool mUsesVertexID;
bool mUsesFragDepth;
+ bool mUsesNumWorkGroups;
+ bool mUsesWorkGroupID;
+ bool mUsesLocalInvocationID;
+ bool mUsesGlobalInvocationID;
+ bool mUsesLocalInvocationIndex;
bool mUsesXor;
bool mUsesDiscardRewriting;
bool mUsesNestedBreak;
bool mRequiresIEEEStrictCompiling;
-
int mNumRenderTargets;
- int mUniqueIndex; // For creating unique names
+ int mUniqueIndex; // For creating unique names
CallDAG mCallDag;
MetadataList mASTMetadataList;
@@ -197,15 +201,7 @@ class OutputHLSL : public TIntermTraverser
TIntermSymbol *mExcessiveLoopIndex;
- TString structInitializerString(int indent, const TStructure &structure, const TString &rhsStructName);
-
- std::map<TIntermTyped*, TString> mFlaggedStructMappedNames;
- std::map<TIntermTyped*, TString> mFlaggedStructOriginalNames;
-
- // Some initializers may have been unfolded into if statements, thus we can't evaluate all initializers
- // at global static scope in HLSL. Instead, we can initialize these static globals inside a helper function.
- // This also enables initialization of globals with uniforms.
- TIntermSequence mDeferredGlobalInitializers;
+ TString structInitializerString(int indent, const TType &type, const TString &name) const;
struct HelperFunction
{
@@ -219,28 +215,34 @@ class OutputHLSL : public TIntermTraverser
// which we add the functions, since nested structures call each other recursively, and
// structure equality functions may need to call array equality functions and vice versa.
// The ownership of the pointers is maintained by the type-specific arrays.
- std::vector<HelperFunction*> mEqualityFunctions;
+ std::vector<HelperFunction *> mEqualityFunctions;
struct StructEqualityFunction : public HelperFunction
{
const TStructure *structure;
};
- std::vector<StructEqualityFunction*> mStructEqualityFunctions;
+ std::vector<StructEqualityFunction *> mStructEqualityFunctions;
struct ArrayHelperFunction : public HelperFunction
{
TType type;
};
- std::vector<ArrayHelperFunction*> mArrayEqualityFunctions;
+ std::vector<ArrayHelperFunction *> mArrayEqualityFunctions;
std::vector<ArrayHelperFunction> mArrayAssignmentFunctions;
- // The construct-into functions are functions that fill an N-element array passed as an out parameter
- // with the other N parameters of the function. This is used to work around that arrays can't be
- // return values in HLSL.
+ // The construct-into functions are functions that fill an N-element array passed as an out
+ // parameter with the other N parameters of the function. This is used to work around that
+ // arrays can't be return values in HLSL.
std::vector<ArrayHelperFunction> mArrayConstructIntoFunctions;
-};
+ PerformanceDiagnostics *mPerfDiagnostics;
+
+ private:
+ TString generateStructMapping(const std::vector<MappedStruct> &std140Structs) const;
+ TString samplerNamePrefixFromStruct(TIntermTyped *node);
+ bool ancestorEvaluatesToSamplerInStruct();
+};
}
-#endif // COMPILER_TRANSLATOR_OUTPUTHLSL_H_
+#endif // COMPILER_TRANSLATOR_OUTPUTHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputTree.cpp b/src/3rdparty/angle/src/compiler/translator/OutputTree.cpp
new file mode 100644
index 0000000000..25e8298af3
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/OutputTree.cpp
@@ -0,0 +1,682 @@
+//
+// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/IntermTraverse.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+namespace
+{
+
+void OutputFunction(TInfoSinkBase &out, const char *str, TFunctionSymbolInfo *info)
+{
+ const char *internal = info->getNameObj().isInternal() ? " (internal function)" : "";
+ out << str << internal << ": " << info->getNameObj().getString() << " (symbol id "
+ << info->getId().get() << ")";
+}
+
+// Two purposes:
+// 1. Show an example of how to iterate tree. Functions can also directly call traverse() on
+// children themselves to have finer grained control over the process than shown here, though
+// that's not recommended if it can be avoided.
+// 2. Print out a text based description of the tree.
+
+// The traverser subclass is used to carry along data from node to node in the traversal.
+class TOutputTraverser : public TIntermTraverser
+{
+ public:
+ TOutputTraverser(TInfoSinkBase &out) : TIntermTraverser(true, false, false), mOut(out) {}
+
+ protected:
+ void visitSymbol(TIntermSymbol *) override;
+ void visitConstantUnion(TIntermConstantUnion *) override;
+ bool visitSwizzle(Visit visit, TIntermSwizzle *node) override;
+ bool visitBinary(Visit visit, TIntermBinary *) override;
+ bool visitUnary(Visit visit, TIntermUnary *) override;
+ bool visitTernary(Visit visit, TIntermTernary *node) override;
+ bool visitIfElse(Visit visit, TIntermIfElse *node) override;
+ bool visitSwitch(Visit visit, TIntermSwitch *node) override;
+ bool visitCase(Visit visit, TIntermCase *node) override;
+ bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override;
+ bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
+ bool visitAggregate(Visit visit, TIntermAggregate *) override;
+ bool visitBlock(Visit visit, TIntermBlock *) override;
+ bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override;
+ bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
+ bool visitLoop(Visit visit, TIntermLoop *) override;
+ bool visitBranch(Visit visit, TIntermBranch *) override;
+
+ TInfoSinkBase &mOut;
+};
+
+//
+// Helper functions for printing, not part of traversing.
+//
+void OutputTreeText(TInfoSinkBase &out, TIntermNode *node, const int depth)
+{
+ int i;
+
+ out.location(node->getLine().first_file, node->getLine().first_line);
+
+ for (i = 0; i < depth; ++i)
+ out << " ";
+}
+
+//
+// The rest of the file are the traversal functions. The last one
+// is the one that starts the traversal.
+//
+// Return true from interior nodes to have the external traversal
+// continue on to children. If you process children yourself,
+// return false.
+//
+
+void TOutputTraverser::visitSymbol(TIntermSymbol *node)
+{
+ OutputTreeText(mOut, node, mDepth);
+
+ mOut << "'" << node->getSymbol() << "' ";
+ mOut << "(symbol id " << node->getId() << ") ";
+ mOut << "(" << node->getCompleteString() << ")";
+ mOut << "\n";
+}
+
+bool TOutputTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node)
+{
+ OutputTreeText(mOut, node, mDepth);
+ mOut << "vector swizzle (";
+ node->writeOffsetsAsXYZW(&mOut);
+ mOut << ")";
+
+ mOut << " (" << node->getCompleteString() << ")";
+ mOut << "\n";
+ return true;
+}
+
+bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
+{
+ OutputTreeText(mOut, node, mDepth);
+
+ switch (node->getOp())
+ {
+ case EOpComma:
+ mOut << "comma";
+ break;
+ case EOpAssign:
+ mOut << "move second child to first child";
+ break;
+ case EOpInitialize:
+ mOut << "initialize first child with second child";
+ break;
+ case EOpAddAssign:
+ mOut << "add second child into first child";
+ break;
+ case EOpSubAssign:
+ mOut << "subtract second child into first child";
+ break;
+ case EOpMulAssign:
+ mOut << "multiply second child into first child";
+ break;
+ case EOpVectorTimesMatrixAssign:
+ mOut << "matrix mult second child into first child";
+ break;
+ case EOpVectorTimesScalarAssign:
+ mOut << "vector scale second child into first child";
+ break;
+ case EOpMatrixTimesScalarAssign:
+ mOut << "matrix scale second child into first child";
+ break;
+ case EOpMatrixTimesMatrixAssign:
+ mOut << "matrix mult second child into first child";
+ break;
+ case EOpDivAssign:
+ mOut << "divide second child into first child";
+ break;
+ case EOpIModAssign:
+ mOut << "modulo second child into first child";
+ break;
+ case EOpBitShiftLeftAssign:
+ mOut << "bit-wise shift first child left by second child";
+ break;
+ case EOpBitShiftRightAssign:
+ mOut << "bit-wise shift first child right by second child";
+ break;
+ case EOpBitwiseAndAssign:
+ mOut << "bit-wise and second child into first child";
+ break;
+ case EOpBitwiseXorAssign:
+ mOut << "bit-wise xor second child into first child";
+ break;
+ case EOpBitwiseOrAssign:
+ mOut << "bit-wise or second child into first child";
+ break;
+
+ case EOpIndexDirect:
+ mOut << "direct index";
+ break;
+ case EOpIndexIndirect:
+ mOut << "indirect index";
+ break;
+ case EOpIndexDirectStruct:
+ mOut << "direct index for structure";
+ break;
+ case EOpIndexDirectInterfaceBlock:
+ mOut << "direct index for interface block";
+ break;
+
+ case EOpAdd:
+ mOut << "add";
+ break;
+ case EOpSub:
+ mOut << "subtract";
+ break;
+ case EOpMul:
+ mOut << "component-wise multiply";
+ break;
+ case EOpDiv:
+ mOut << "divide";
+ break;
+ case EOpIMod:
+ mOut << "modulo";
+ break;
+ case EOpBitShiftLeft:
+ mOut << "bit-wise shift left";
+ break;
+ case EOpBitShiftRight:
+ mOut << "bit-wise shift right";
+ break;
+ case EOpBitwiseAnd:
+ mOut << "bit-wise and";
+ break;
+ case EOpBitwiseXor:
+ mOut << "bit-wise xor";
+ break;
+ case EOpBitwiseOr:
+ mOut << "bit-wise or";
+ break;
+
+ case EOpEqual:
+ mOut << "Compare Equal";
+ break;
+ case EOpNotEqual:
+ mOut << "Compare Not Equal";
+ break;
+ case EOpLessThan:
+ mOut << "Compare Less Than";
+ break;
+ case EOpGreaterThan:
+ mOut << "Compare Greater Than";
+ break;
+ case EOpLessThanEqual:
+ mOut << "Compare Less Than or Equal";
+ break;
+ case EOpGreaterThanEqual:
+ mOut << "Compare Greater Than or Equal";
+ break;
+
+ case EOpVectorTimesScalar:
+ mOut << "vector-scale";
+ break;
+ case EOpVectorTimesMatrix:
+ mOut << "vector-times-matrix";
+ break;
+ case EOpMatrixTimesVector:
+ mOut << "matrix-times-vector";
+ break;
+ case EOpMatrixTimesScalar:
+ mOut << "matrix-scale";
+ break;
+ case EOpMatrixTimesMatrix:
+ mOut << "matrix-multiply";
+ break;
+
+ case EOpLogicalOr:
+ mOut << "logical-or";
+ break;
+ case EOpLogicalXor:
+ mOut << "logical-xor";
+ break;
+ case EOpLogicalAnd:
+ mOut << "logical-and";
+ break;
+ default:
+ mOut << "<unknown op>";
+ }
+
+ mOut << " (" << node->getCompleteString() << ")";
+
+ mOut << "\n";
+
+ // Special handling for direct indexes. Because constant
+ // unions are not aware they are struct indexes, treat them
+ // here where we have that contextual knowledge.
+ if (node->getOp() == EOpIndexDirectStruct || node->getOp() == EOpIndexDirectInterfaceBlock)
+ {
+ node->getLeft()->traverse(this);
+
+ TIntermConstantUnion *intermConstantUnion = node->getRight()->getAsConstantUnion();
+ ASSERT(intermConstantUnion);
+
+ OutputTreeText(mOut, intermConstantUnion, mDepth + 1);
+
+ // The following code finds the field name from the constant union
+ const TConstantUnion *constantUnion = intermConstantUnion->getUnionArrayPointer();
+ const TStructure *structure = node->getLeft()->getType().getStruct();
+ const TInterfaceBlock *interfaceBlock = node->getLeft()->getType().getInterfaceBlock();
+ ASSERT(structure || interfaceBlock);
+
+ const TFieldList &fields = structure ? structure->fields() : interfaceBlock->fields();
+
+ const TField *field = fields[constantUnion->getIConst()];
+
+ mOut << constantUnion->getIConst() << " (field '" << field->name() << "')";
+
+ mOut << "\n";
+
+ return false;
+ }
+
+ return true;
+}
+
+bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
+{
+ OutputTreeText(mOut, node, mDepth);
+
+ switch (node->getOp())
+ {
+ // Give verbose names for ops that have special syntax and some built-in functions that are
+ // easy to confuse with others, but mostly use GLSL names for functions.
+ case EOpNegative:
+ mOut << "Negate value";
+ break;
+ case EOpPositive:
+ mOut << "Positive sign";
+ break;
+ case EOpLogicalNot:
+ mOut << "negation";
+ break;
+ case EOpBitwiseNot:
+ mOut << "bit-wise not";
+ break;
+
+ case EOpPostIncrement:
+ mOut << "Post-Increment";
+ break;
+ case EOpPostDecrement:
+ mOut << "Post-Decrement";
+ break;
+ case EOpPreIncrement:
+ mOut << "Pre-Increment";
+ break;
+ case EOpPreDecrement:
+ mOut << "Pre-Decrement";
+ break;
+
+ case EOpArrayLength:
+ mOut << "Array length";
+ break;
+
+ case EOpLogicalNotComponentWise:
+ mOut << "component-wise not";
+ break;
+
+ default:
+ mOut << GetOperatorString(node->getOp());
+ break;
+ }
+
+ mOut << " (" << node->getCompleteString() << ")";
+
+ mOut << "\n";
+
+ return true;
+}
+
+bool TOutputTraverser::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
+{
+ OutputTreeText(mOut, node, mDepth);
+ mOut << "Function Definition:\n";
+ mOut << "\n";
+ return true;
+}
+
+bool TOutputTraverser::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node)
+{
+ OutputTreeText(mOut, node, mDepth);
+ mOut << "Invariant Declaration:\n";
+ return true;
+}
+
+bool TOutputTraverser::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node)
+{
+ OutputTreeText(mOut, node, mDepth);
+ OutputFunction(mOut, "Function Prototype", node->getFunctionSymbolInfo());
+ mOut << " (" << node->getCompleteString() << ")";
+ mOut << "\n";
+
+ return true;
+}
+
+bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+ OutputTreeText(mOut, node, mDepth);
+
+ if (node->getOp() == EOpNull)
+ {
+ mOut.prefix(SH_ERROR);
+ mOut << "node is still EOpNull!\n";
+ return true;
+ }
+
+ // Give verbose names for some built-in functions that are easy to confuse with others, but
+ // mostly use GLSL names for functions.
+ switch (node->getOp())
+ {
+ case EOpCallFunctionInAST:
+ OutputFunction(mOut, "Call an user-defined function", node->getFunctionSymbolInfo());
+ break;
+ case EOpCallInternalRawFunction:
+ OutputFunction(mOut, "Call an internal function with raw implementation",
+ node->getFunctionSymbolInfo());
+ break;
+ case EOpCallBuiltInFunction:
+ OutputFunction(mOut, "Call a built-in function", node->getFunctionSymbolInfo());
+ break;
+
+ case EOpConstruct:
+ // The type of the constructor will be printed below.
+ mOut << "Construct";
+ break;
+
+ case EOpEqualComponentWise:
+ mOut << "component-wise equal";
+ break;
+ case EOpNotEqualComponentWise:
+ mOut << "component-wise not equal";
+ break;
+ case EOpLessThanComponentWise:
+ mOut << "component-wise less than";
+ break;
+ case EOpGreaterThanComponentWise:
+ mOut << "component-wise greater than";
+ break;
+ case EOpLessThanEqualComponentWise:
+ mOut << "component-wise less than or equal";
+ break;
+ case EOpGreaterThanEqualComponentWise:
+ mOut << "component-wise greater than or equal";
+ break;
+
+ case EOpDot:
+ mOut << "dot product";
+ break;
+ case EOpCross:
+ mOut << "cross product";
+ break;
+ case EOpMulMatrixComponentWise:
+ mOut << "component-wise multiply";
+ break;
+
+ default:
+ mOut << GetOperatorString(node->getOp());
+ break;
+ }
+
+ mOut << " (" << node->getCompleteString() << ")";
+
+ mOut << "\n";
+
+ return true;
+}
+
+bool TOutputTraverser::visitBlock(Visit visit, TIntermBlock *node)
+{
+ OutputTreeText(mOut, node, mDepth);
+ mOut << "Code block\n";
+
+ return true;
+}
+
+bool TOutputTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node)
+{
+ OutputTreeText(mOut, node, mDepth);
+ mOut << "Declaration\n";
+
+ return true;
+}
+
+bool TOutputTraverser::visitTernary(Visit visit, TIntermTernary *node)
+{
+ OutputTreeText(mOut, node, mDepth);
+
+ mOut << "Ternary selection";
+ mOut << " (" << node->getCompleteString() << ")\n";
+
+ ++mDepth;
+
+ OutputTreeText(mOut, node, mDepth);
+ mOut << "Condition\n";
+ node->getCondition()->traverse(this);
+
+ OutputTreeText(mOut, node, mDepth);
+ if (node->getTrueExpression())
+ {
+ mOut << "true case\n";
+ node->getTrueExpression()->traverse(this);
+ }
+ if (node->getFalseExpression())
+ {
+ OutputTreeText(mOut, node, mDepth);
+ mOut << "false case\n";
+ node->getFalseExpression()->traverse(this);
+ }
+
+ --mDepth;
+
+ return false;
+}
+
+bool TOutputTraverser::visitIfElse(Visit visit, TIntermIfElse *node)
+{
+ OutputTreeText(mOut, node, mDepth);
+
+ mOut << "If test\n";
+
+ ++mDepth;
+
+ OutputTreeText(mOut, node, mDepth);
+ mOut << "Condition\n";
+ node->getCondition()->traverse(this);
+
+ OutputTreeText(mOut, node, mDepth);
+ if (node->getTrueBlock())
+ {
+ mOut << "true case\n";
+ node->getTrueBlock()->traverse(this);
+ }
+ else
+ {
+ mOut << "true case is null\n";
+ }
+
+ if (node->getFalseBlock())
+ {
+ OutputTreeText(mOut, node, mDepth);
+ mOut << "false case\n";
+ node->getFalseBlock()->traverse(this);
+ }
+
+ --mDepth;
+
+ return false;
+}
+
+bool TOutputTraverser::visitSwitch(Visit visit, TIntermSwitch *node)
+{
+ OutputTreeText(mOut, node, mDepth);
+
+ mOut << "Switch\n";
+
+ return true;
+}
+
+bool TOutputTraverser::visitCase(Visit visit, TIntermCase *node)
+{
+ OutputTreeText(mOut, node, mDepth);
+
+ if (node->getCondition() == nullptr)
+ {
+ mOut << "Default\n";
+ }
+ else
+ {
+ mOut << "Case\n";
+ }
+
+ return true;
+}
+
+void TOutputTraverser::visitConstantUnion(TIntermConstantUnion *node)
+{
+ size_t size = node->getType().getObjectSize();
+
+ for (size_t i = 0; i < size; i++)
+ {
+ OutputTreeText(mOut, node, mDepth);
+ switch (node->getUnionArrayPointer()[i].getType())
+ {
+ case EbtBool:
+ if (node->getUnionArrayPointer()[i].getBConst())
+ mOut << "true";
+ else
+ mOut << "false";
+
+ mOut << " ("
+ << "const bool"
+ << ")";
+ mOut << "\n";
+ break;
+ case EbtFloat:
+ mOut << node->getUnionArrayPointer()[i].getFConst();
+ mOut << " (const float)\n";
+ break;
+ case EbtInt:
+ mOut << node->getUnionArrayPointer()[i].getIConst();
+ mOut << " (const int)\n";
+ break;
+ case EbtUInt:
+ mOut << node->getUnionArrayPointer()[i].getUConst();
+ mOut << " (const uint)\n";
+ break;
+ case EbtYuvCscStandardEXT:
+ mOut << getYuvCscStandardEXTString(
+ node->getUnionArrayPointer()[i].getYuvCscStandardEXTConst());
+ mOut << " (const yuvCscStandardEXT)\n";
+ break;
+ default:
+ mOut.prefix(SH_ERROR);
+ mOut << "Unknown constant\n";
+ break;
+ }
+ }
+}
+
+bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop *node)
+{
+ OutputTreeText(mOut, node, mDepth);
+
+ mOut << "Loop with condition ";
+ if (node->getType() == ELoopDoWhile)
+ mOut << "not ";
+ mOut << "tested first\n";
+
+ ++mDepth;
+
+ OutputTreeText(mOut, node, mDepth);
+ if (node->getCondition())
+ {
+ mOut << "Loop Condition\n";
+ node->getCondition()->traverse(this);
+ }
+ else
+ {
+ mOut << "No loop condition\n";
+ }
+
+ OutputTreeText(mOut, node, mDepth);
+ if (node->getBody())
+ {
+ mOut << "Loop Body\n";
+ node->getBody()->traverse(this);
+ }
+ else
+ {
+ mOut << "No loop body\n";
+ }
+
+ if (node->getExpression())
+ {
+ OutputTreeText(mOut, node, mDepth);
+ mOut << "Loop Terminal Expression\n";
+ node->getExpression()->traverse(this);
+ }
+
+ --mDepth;
+
+ return false;
+}
+
+bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch *node)
+{
+ OutputTreeText(mOut, node, mDepth);
+
+ switch (node->getFlowOp())
+ {
+ case EOpKill:
+ mOut << "Branch: Kill";
+ break;
+ case EOpBreak:
+ mOut << "Branch: Break";
+ break;
+ case EOpContinue:
+ mOut << "Branch: Continue";
+ break;
+ case EOpReturn:
+ mOut << "Branch: Return";
+ break;
+ default:
+ mOut << "Branch: Unknown Branch";
+ break;
+ }
+
+ if (node->getExpression())
+ {
+ mOut << " with expression\n";
+ ++mDepth;
+ node->getExpression()->traverse(this);
+ --mDepth;
+ }
+ else
+ {
+ mOut << "\n";
+ }
+
+ return false;
+}
+
+} // anonymous namespace
+
+void OutputTree(TIntermNode *root, TInfoSinkBase &out)
+{
+ TOutputTraverser it(out);
+ ASSERT(root);
+ root->traverse(&it);
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputTree.h b/src/3rdparty/angle/src/compiler/translator/OutputTree.h
new file mode 100644
index 0000000000..9f11989cb1
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/OutputTree.h
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Output the AST intermediate representation of the GLSL code.
+
+#ifndef COMPILER_TRANSLATOR_OUTPUTTREE_H_
+#define COMPILER_TRANSLATOR_OUTPUTTREE_H_
+
+namespace sh
+{
+
+class TIntermNode;
+class TInfoSinkBase;
+
+// Output the AST along with metadata.
+void OutputTree(TIntermNode *root, TInfoSinkBase &out);
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_OUTPUTTREE_H_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.cpp
new file mode 100644
index 0000000000..6d11deb898
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.cpp
@@ -0,0 +1,80 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// OutputVulkanGLSL:
+// Code that outputs shaders that fit GL_KHR_vulkan_glsl.
+// The shaders are then fed into glslang to spit out SPIR-V (libANGLE-side).
+// See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt
+//
+
+#include "compiler/translator/OutputVulkanGLSL.h"
+
+#include "compiler/translator/util.h"
+
+namespace sh
+{
+
+TOutputVulkanGLSL::TOutputVulkanGLSL(TInfoSinkBase &objSink,
+ ShArrayIndexClampingStrategy clampingStrategy,
+ ShHashFunction64 hashFunction,
+ NameMap &nameMap,
+ TSymbolTable *symbolTable,
+ sh::GLenum shaderType,
+ int shaderVersion,
+ ShShaderOutput output,
+ ShCompileOptions compileOptions)
+ : TOutputGLSL(objSink,
+ clampingStrategy,
+ hashFunction,
+ nameMap,
+ symbolTable,
+ shaderType,
+ shaderVersion,
+ output,
+ compileOptions)
+{
+}
+
+// TODO(jmadill): This is not complete.
+void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable)
+{
+ const TType &type = variable->getType();
+
+ bool needsCustomLayout =
+ (type.getQualifier() == EvqAttribute || type.getQualifier() == EvqFragmentOut ||
+ type.getQualifier() == EvqVertexIn || IsVarying(type.getQualifier()) ||
+ IsSampler(type.getBasicType()));
+
+ if (!NeedsToWriteLayoutQualifier(type) && !needsCustomLayout)
+ {
+ return;
+ }
+
+ TInfoSinkBase &out = objSink();
+ const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier();
+ out << "layout(";
+
+ // This isn't super clean, but it gets the job done.
+ // See corresponding code in GlslangWrapper.cpp.
+ // TODO(jmadill): Ensure declarations are separated.
+
+ TIntermSymbol *symbol = variable->getAsSymbolNode();
+ ASSERT(symbol);
+
+ if (needsCustomLayout)
+ {
+ out << "@@ LAYOUT-" << symbol->getName().getString() << " @@";
+ }
+
+ if (IsImage(type.getBasicType()) && layoutQualifier.imageInternalFormat != EiifUnspecified)
+ {
+ ASSERT(type.getQualifier() == EvqTemporary || type.getQualifier() == EvqUniform);
+ out << getImageInternalFormatString(layoutQualifier.imageInternalFormat);
+ }
+
+ out << ") ";
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.h
new file mode 100644
index 0000000000..6e5da8b53e
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/OutputVulkanGLSL.h
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// OutputVulkanGLSL:
+// Code that outputs shaders that fit GL_KHR_vulkan_glsl.
+// The shaders are then fed into glslang to spit out SPIR-V (libANGLE-side).
+// See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt
+//
+
+#include "compiler/translator/OutputGLSL.h"
+
+namespace sh
+{
+
+class TOutputVulkanGLSL : public TOutputGLSL
+{
+ public:
+ TOutputVulkanGLSL(TInfoSinkBase &objSink,
+ ShArrayIndexClampingStrategy clampingStrategy,
+ ShHashFunction64 hashFunction,
+ NameMap &nameMap,
+ TSymbolTable *symbolTable,
+ sh::GLenum shaderType,
+ int shaderVersion,
+ ShShaderOutput output,
+ ShCompileOptions compileOptions);
+
+ protected:
+ void writeLayoutQualifier(TIntermTyped *variable) override;
+};
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ParamType.h b/src/3rdparty/angle/src/compiler/translator/ParamType.h
new file mode 100644
index 0000000000..dddb4e9901
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/ParamType.h
@@ -0,0 +1,102 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ParamType:
+// Helper type for built-in function emulator tables. Defines types for parameters.
+
+#ifndef COMPILER_TRANSLATOR_PARAMTYPE_H_
+#define COMPILER_TRANSLATOR_PARAMTYPE_H_
+
+#include "common/angleutils.h"
+#include "compiler/translator/BaseTypes.h"
+
+namespace sh
+{
+
+enum class ParamType : uint8_t
+{
+ Void,
+ Bool1,
+ Bool2,
+ Bool3,
+ Bool4,
+ Float1,
+ Float2,
+ Float3,
+ Float4,
+ Int1,
+ Int2,
+ Int3,
+ Int4,
+ Mat2,
+ Mat3,
+ Mat4,
+ Uint1,
+ Uint2,
+ Uint3,
+ Uint4,
+ Last,
+};
+
+struct ParamTypeInfo
+{
+ ParamType self;
+ TBasicType basicType;
+ int primarySize;
+ int secondarySize;
+};
+
+constexpr ParamTypeInfo g_ParamTypeInfo[] = {
+ {ParamType::Void, EbtVoid, 1, 1}, {ParamType::Bool1, EbtBool, 1, 1},
+ {ParamType::Bool2, EbtBool, 2, 1}, {ParamType::Bool3, EbtBool, 3, 1},
+ {ParamType::Bool4, EbtBool, 4, 1}, {ParamType::Float1, EbtFloat, 1, 1},
+ {ParamType::Float2, EbtFloat, 2, 1}, {ParamType::Float3, EbtFloat, 3, 1},
+ {ParamType::Float4, EbtFloat, 4, 1}, {ParamType::Int1, EbtInt, 1, 1},
+ {ParamType::Int2, EbtInt, 2, 1}, {ParamType::Int3, EbtInt, 3, 1},
+ {ParamType::Int4, EbtInt, 4, 1}, {ParamType::Mat2, EbtFloat, 2, 2},
+ {ParamType::Mat3, EbtFloat, 3, 3}, {ParamType::Mat4, EbtFloat, 4, 4},
+ {ParamType::Uint1, EbtUInt, 1, 1}, {ParamType::Uint2, EbtUInt, 2, 1},
+ {ParamType::Uint3, EbtUInt, 3, 1}, {ParamType::Uint4, EbtUInt, 4, 1},
+};
+
+constexpr size_t ParamTypeIndex(ParamType paramType)
+{
+ return static_cast<size_t>(paramType);
+}
+
+constexpr size_t NumParamTypes()
+{
+ return ParamTypeIndex(ParamType::Last);
+}
+
+static_assert(ArraySize(g_ParamTypeInfo) == NumParamTypes(), "Invalid array size");
+
+constexpr TBasicType GetBasicType(ParamType paramType)
+{
+ return g_ParamTypeInfo[ParamTypeIndex(paramType)].basicType;
+}
+
+constexpr int GetPrimarySize(ParamType paramType)
+{
+ return g_ParamTypeInfo[ParamTypeIndex(paramType)].primarySize;
+}
+
+constexpr int GetSecondarySize(ParamType paramType)
+{
+ return g_ParamTypeInfo[ParamTypeIndex(paramType)].secondarySize;
+}
+
+constexpr bool SameParamType(ParamType paramType,
+ TBasicType basicType,
+ int primarySize,
+ int secondarySize)
+{
+ return GetBasicType(paramType) == basicType && primarySize == GetPrimarySize(paramType) &&
+ secondarySize == GetSecondarySize(paramType);
+}
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_PARAMTYPE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp
index 235351cf41..c97f91d781 100644
--- a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp
@@ -9,34 +9,252 @@
#include <stdarg.h>
#include <stdio.h>
+#include "common/mathutil.h"
#include "compiler/preprocessor/SourceLocation.h"
#include "compiler/translator/Cache.h"
-#include "compiler/translator/glslang.h"
-#include "compiler/translator/ValidateSwitch.h"
+#include "compiler/translator/IntermNode_util.h"
#include "compiler/translator/ValidateGlobalInitializer.h"
+#include "compiler/translator/ValidateSwitch.h"
+#include "compiler/translator/glslang.h"
#include "compiler/translator/util.h"
+namespace sh
+{
+
///////////////////////////////////////////////////////////////////////
//
// Sub- vector and matrix fields
//
////////////////////////////////////////////////////////////////////////
-//
-// Look at a '.' field selector string and change it into offsets
-// for a vector.
-//
-bool TParseContext::parseVectorFields(const TString &compString,
+namespace
+{
+
+const int kWebGLMaxStructNesting = 4;
+
+const std::array<const char *, 8> kAtomicBuiltin = {{"atomicAdd", "atomicMin", "atomicMax",
+ "atomicAnd", "atomicOr", "atomicXor",
+ "atomicExchange", "atomicCompSwap"}};
+
+bool IsAtomicBuiltin(const TString &name)
+{
+ for (size_t i = 0; i < kAtomicBuiltin.size(); ++i)
+ {
+ if (name.compare(kAtomicBuiltin[i]) == 0)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool ContainsSampler(const TStructure *structType);
+
+bool ContainsSampler(const TType &type)
+{
+ if (IsSampler(type.getBasicType()))
+ {
+ return true;
+ }
+ if (type.getBasicType() == EbtStruct)
+ {
+ return ContainsSampler(type.getStruct());
+ }
+
+ return false;
+}
+
+bool ContainsSampler(const TStructure *structType)
+{
+ for (const auto &field : structType->fields())
+ {
+ if (ContainsSampler(*field->type()))
+ return true;
+ }
+ return false;
+}
+
+// Get a token from an image argument to use as an error message token.
+const char *GetImageArgumentToken(TIntermTyped *imageNode)
+{
+ ASSERT(IsImage(imageNode->getBasicType()));
+ while (imageNode->getAsBinaryNode() &&
+ (imageNode->getAsBinaryNode()->getOp() == EOpIndexIndirect ||
+ imageNode->getAsBinaryNode()->getOp() == EOpIndexDirect))
+ {
+ imageNode = imageNode->getAsBinaryNode()->getLeft();
+ }
+ TIntermSymbol *imageSymbol = imageNode->getAsSymbolNode();
+ if (imageSymbol)
+ {
+ return imageSymbol->getSymbol().c_str();
+ }
+ return "image";
+}
+
+bool CanSetDefaultPrecisionOnType(const TPublicType &type)
+{
+ if (!SupportsPrecision(type.getBasicType()))
+ {
+ return false;
+ }
+ if (type.getBasicType() == EbtUInt)
+ {
+ // ESSL 3.00.4 section 4.5.4
+ return false;
+ }
+ if (type.isAggregate())
+ {
+ // Not allowed to set for aggregate types
+ return false;
+ }
+ return true;
+}
+
+// Map input primitive types to input array sizes in a geometry shader.
+GLuint GetGeometryShaderInputArraySize(TLayoutPrimitiveType primitiveType)
+{
+ switch (primitiveType)
+ {
+ case EptPoints:
+ return 1u;
+ case EptLines:
+ return 2u;
+ case EptTriangles:
+ return 3u;
+ case EptLinesAdjacency:
+ return 4u;
+ case EptTrianglesAdjacency:
+ return 6u;
+ default:
+ UNREACHABLE();
+ return 0u;
+ }
+}
+
+bool IsBufferOrSharedVariable(TIntermTyped *var)
+{
+ if (var->isInterfaceBlock() || var->getQualifier() == EvqBuffer ||
+ var->getQualifier() == EvqShared)
+ {
+ return true;
+ }
+ return false;
+}
+
+} // namespace
+
+// This tracks each binding point's current default offset for inheritance of subsequent
+// variables using the same binding, and keeps offsets unique and non overlapping.
+// See GLSL ES 3.1, section 4.4.6.
+class TParseContext::AtomicCounterBindingState
+{
+ public:
+ AtomicCounterBindingState() : mDefaultOffset(0) {}
+ // Inserts a new span and returns -1 if overlapping, else returns the starting offset of
+ // newly inserted span.
+ int insertSpan(int start, size_t length)
+ {
+ gl::RangeI newSpan(start, start + static_cast<int>(length));
+ for (const auto &span : mSpans)
+ {
+ if (newSpan.intersects(span))
+ {
+ return -1;
+ }
+ }
+ mSpans.push_back(newSpan);
+ mDefaultOffset = newSpan.high();
+ return start;
+ }
+ // Inserts a new span starting from the default offset.
+ int appendSpan(size_t length) { return insertSpan(mDefaultOffset, length); }
+ void setDefaultOffset(int offset) { mDefaultOffset = offset; }
+
+ private:
+ int mDefaultOffset;
+ std::vector<gl::RangeI> mSpans;
+};
+
+TParseContext::TParseContext(TSymbolTable &symt,
+ TExtensionBehavior &ext,
+ sh::GLenum type,
+ ShShaderSpec spec,
+ ShCompileOptions options,
+ bool checksPrecErrors,
+ TDiagnostics *diagnostics,
+ const ShBuiltInResources &resources)
+ : symbolTable(symt),
+ mDeferredNonEmptyDeclarationErrorCheck(false),
+ mShaderType(type),
+ mShaderSpec(spec),
+ mCompileOptions(options),
+ mShaderVersion(100),
+ mTreeRoot(nullptr),
+ mLoopNestingLevel(0),
+ mStructNestingLevel(0),
+ mSwitchNestingLevel(0),
+ mCurrentFunctionType(nullptr),
+ mFunctionReturnsValue(false),
+ mChecksPrecisionErrors(checksPrecErrors),
+ mFragmentPrecisionHighOnESSL1(false),
+ mDefaultUniformMatrixPacking(EmpColumnMajor),
+ mDefaultUniformBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared),
+ mDefaultBufferMatrixPacking(EmpColumnMajor),
+ mDefaultBufferBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared),
+ mDiagnostics(diagnostics),
+ mDirectiveHandler(ext,
+ *mDiagnostics,
+ mShaderVersion,
+ mShaderType,
+ resources.WEBGL_debug_shader_precision == 1),
+ mPreprocessor(mDiagnostics, &mDirectiveHandler, pp::PreprocessorSettings()),
+ mScanner(nullptr),
+ mUsesFragData(false),
+ mUsesFragColor(false),
+ mUsesSecondaryOutputs(false),
+ mMinProgramTexelOffset(resources.MinProgramTexelOffset),
+ mMaxProgramTexelOffset(resources.MaxProgramTexelOffset),
+ mMinProgramTextureGatherOffset(resources.MinProgramTextureGatherOffset),
+ mMaxProgramTextureGatherOffset(resources.MaxProgramTextureGatherOffset),
+ mComputeShaderLocalSizeDeclared(false),
+ mComputeShaderLocalSize(-1),
+ mNumViews(-1),
+ mMaxNumViews(resources.MaxViewsOVR),
+ mMaxImageUnits(resources.MaxImageUnits),
+ mMaxCombinedTextureImageUnits(resources.MaxCombinedTextureImageUnits),
+ mMaxUniformLocations(resources.MaxUniformLocations),
+ mMaxUniformBufferBindings(resources.MaxUniformBufferBindings),
+ mMaxAtomicCounterBindings(resources.MaxAtomicCounterBindings),
+ mMaxShaderStorageBufferBindings(resources.MaxShaderStorageBufferBindings),
+ mDeclaringFunction(false),
+ mGeometryShaderInputPrimitiveType(EptUndefined),
+ mGeometryShaderOutputPrimitiveType(EptUndefined),
+ mGeometryShaderInvocations(0),
+ mGeometryShaderMaxVertices(-1),
+ mMaxGeometryShaderInvocations(resources.MaxGeometryShaderInvocations),
+ mMaxGeometryShaderMaxVertices(resources.MaxGeometryOutputVertices),
+ mGeometryShaderInputArraySize(0u)
+{
+}
+
+TParseContext::~TParseContext()
+{
+}
+
+bool TParseContext::parseVectorFields(const TSourceLoc &line,
+ const TString &compString,
int vecSize,
- TVectorFields &fields,
- const TSourceLoc &line)
+ TVector<int> *fieldOffsets)
{
- fields.num = (int)compString.size();
- if (fields.num > 4)
+ ASSERT(fieldOffsets);
+ size_t fieldCount = compString.size();
+ if (fieldCount > 4u)
{
error(line, "illegal vector field selection", compString.c_str());
return false;
}
+ fieldOffsets->resize(fieldCount);
enum
{
@@ -45,57 +263,57 @@ bool TParseContext::parseVectorFields(const TString &compString,
estpq
} fieldSet[4];
- for (int i = 0; i < fields.num; ++i)
+ for (unsigned int i = 0u; i < fieldOffsets->size(); ++i)
{
switch (compString[i])
{
case 'x':
- fields.offsets[i] = 0;
+ (*fieldOffsets)[i] = 0;
fieldSet[i] = exyzw;
break;
case 'r':
- fields.offsets[i] = 0;
+ (*fieldOffsets)[i] = 0;
fieldSet[i] = ergba;
break;
case 's':
- fields.offsets[i] = 0;
+ (*fieldOffsets)[i] = 0;
fieldSet[i] = estpq;
break;
case 'y':
- fields.offsets[i] = 1;
+ (*fieldOffsets)[i] = 1;
fieldSet[i] = exyzw;
break;
case 'g':
- fields.offsets[i] = 1;
+ (*fieldOffsets)[i] = 1;
fieldSet[i] = ergba;
break;
case 't':
- fields.offsets[i] = 1;
+ (*fieldOffsets)[i] = 1;
fieldSet[i] = estpq;
break;
case 'z':
- fields.offsets[i] = 2;
+ (*fieldOffsets)[i] = 2;
fieldSet[i] = exyzw;
break;
case 'b':
- fields.offsets[i] = 2;
+ (*fieldOffsets)[i] = 2;
fieldSet[i] = ergba;
break;
case 'p':
- fields.offsets[i] = 2;
+ (*fieldOffsets)[i] = 2;
fieldSet[i] = estpq;
break;
case 'w':
- fields.offsets[i] = 3;
+ (*fieldOffsets)[i] = 3;
fieldSet[i] = exyzw;
break;
case 'a':
- fields.offsets[i] = 3;
+ (*fieldOffsets)[i] = 3;
fieldSet[i] = ergba;
break;
case 'q':
- fields.offsets[i] = 3;
+ (*fieldOffsets)[i] = 3;
fieldSet[i] = estpq;
break;
default:
@@ -104,9 +322,9 @@ bool TParseContext::parseVectorFields(const TString &compString,
}
}
- for (int i = 0; i < fields.num; ++i)
+ for (unsigned int i = 0u; i < fieldOffsets->size(); ++i)
{
- if (fields.offsets[i] >= vecSize)
+ if ((*fieldOffsets)[i] >= vecSize)
{
error(line, "vector field selection out of range", compString.c_str());
return false;
@@ -133,51 +351,30 @@ bool TParseContext::parseVectorFields(const TString &compString,
////////////////////////////////////////////////////////////////////////
//
-// Track whether errors have occurred.
-//
-void TParseContext::recover()
-{
-}
-
-//
// Used by flex/bison to output all syntax and parsing errors.
//
-void TParseContext::error(const TSourceLoc &loc,
- const char *reason,
- const char *token,
- const char *extraInfo)
+void TParseContext::error(const TSourceLoc &loc, const char *reason, const char *token)
{
- pp::SourceLocation srcLoc;
- srcLoc.file = loc.first_file;
- srcLoc.line = loc.first_line;
- mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, srcLoc, reason, token, extraInfo);
+ mDiagnostics->error(loc, reason, token);
}
-void TParseContext::warning(const TSourceLoc &loc,
- const char *reason,
- const char *token,
- const char *extraInfo)
+void TParseContext::warning(const TSourceLoc &loc, const char *reason, const char *token)
{
- pp::SourceLocation srcLoc;
- srcLoc.file = loc.first_file;
- srcLoc.line = loc.first_line;
- mDiagnostics.writeInfo(pp::Diagnostics::PP_WARNING, srcLoc, reason, token, extraInfo);
+ mDiagnostics->warning(loc, reason, token);
}
void TParseContext::outOfRangeError(bool isError,
const TSourceLoc &loc,
const char *reason,
- const char *token,
- const char *extraInfo)
+ const char *token)
{
if (isError)
{
- error(loc, reason, token, extraInfo);
- recover();
+ error(loc, reason, token);
}
else
{
- warning(loc, reason, token, extraInfo);
+ warning(loc, reason, token);
}
}
@@ -186,10 +383,10 @@ void TParseContext::outOfRangeError(bool isError,
//
void TParseContext::assignError(const TSourceLoc &line, const char *op, TString left, TString right)
{
- std::stringstream extraInfoStream;
- extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'";
- std::string extraInfo = extraInfoStream.str();
- error(line, "", op, extraInfo.c_str());
+ std::stringstream reasonStream;
+ reasonStream << "cannot convert from '" << right << "' to '" << left << "'";
+ std::string reason = reasonStream.str();
+ error(line, reason.c_str(), op);
}
//
@@ -197,11 +394,12 @@ void TParseContext::assignError(const TSourceLoc &line, const char *op, TString
//
void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, TString operand)
{
- std::stringstream extraInfoStream;
- extraInfoStream << "no operation '" << op << "' exists that takes an operand of type "
- << operand << " (or there is no acceptable conversion)";
- std::string extraInfo = extraInfoStream.str();
- error(line, " wrong operand type", op, extraInfo.c_str());
+ std::stringstream reasonStream;
+ reasonStream << "wrong operand type - no operation '" << op
+ << "' exists that takes an operand of type " << operand
+ << " (or there is no acceptable conversion)";
+ std::string reason = reasonStream.str();
+ error(line, reason.c_str(), op);
}
//
@@ -212,102 +410,85 @@ void TParseContext::binaryOpError(const TSourceLoc &line,
TString left,
TString right)
{
- std::stringstream extraInfoStream;
- extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '"
- << left << "' and a right operand of type '" << right
- << "' (or there is no acceptable conversion)";
- std::string extraInfo = extraInfoStream.str();
- error(line, " wrong operand types ", op, extraInfo.c_str());
+ std::stringstream reasonStream;
+ reasonStream << "wrong operand types - no operation '" << op
+ << "' exists that takes a left-hand operand of type '" << left
+ << "' and a right operand of type '" << right
+ << "' (or there is no acceptable conversion)";
+ std::string reason = reasonStream.str();
+ error(line, reason.c_str(), op);
}
-bool TParseContext::precisionErrorCheck(const TSourceLoc &line,
- TPrecision precision,
- TBasicType type)
+void TParseContext::checkPrecisionSpecified(const TSourceLoc &line,
+ TPrecision precision,
+ TBasicType type)
{
if (!mChecksPrecisionErrors)
- return false;
+ return;
+
+ if (precision != EbpUndefined && !SupportsPrecision(type))
+ {
+ error(line, "illegal type for precision qualifier", getBasicString(type));
+ }
+
if (precision == EbpUndefined)
{
switch (type)
{
case EbtFloat:
error(line, "No precision specified for (float)", "");
- return true;
+ return;
case EbtInt:
case EbtUInt:
UNREACHABLE(); // there's always a predeclared qualifier
error(line, "No precision specified (int)", "");
- return true;
+ return;
default:
- if (IsSampler(type))
+ if (IsOpaqueType(type))
{
- error(line, "No precision specified (sampler)", "");
- return true;
+ error(line, "No precision specified", getBasicString(type));
+ return;
}
}
}
- return false;
}
-//
// Both test and if necessary, spit out an error, to see if the node is really
// an l-value that can be operated on this way.
-//
-// Returns true if the was an error.
-//
-bool TParseContext::lValueErrorCheck(const TSourceLoc &line, const char *op, TIntermTyped *node)
+bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node)
{
- TIntermSymbol *symNode = node->getAsSymbolNode();
- TIntermBinary *binaryNode = node->getAsBinaryNode();
+ TIntermSymbol *symNode = node->getAsSymbolNode();
+ TIntermBinary *binaryNode = node->getAsBinaryNode();
+ TIntermSwizzle *swizzleNode = node->getAsSwizzleNode();
- if (binaryNode)
+ if (swizzleNode)
{
- bool errorReturn;
+ bool ok = checkCanBeLValue(line, op, swizzleNode->getOperand());
+ if (ok && swizzleNode->hasDuplicateOffsets())
+ {
+ error(line, " l-value of swizzle cannot have duplicate components", op);
+ return false;
+ }
+ return ok;
+ }
+ if (binaryNode)
+ {
switch (binaryNode->getOp())
{
case EOpIndexDirect:
case EOpIndexIndirect:
case EOpIndexDirectStruct:
case EOpIndexDirectInterfaceBlock:
- return lValueErrorCheck(line, op, binaryNode->getLeft());
- case EOpVectorSwizzle:
- errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft());
- if (!errorReturn)
- {
- int offset[4] = {0, 0, 0, 0};
-
- TIntermTyped *rightNode = binaryNode->getRight();
- TIntermAggregate *aggrNode = rightNode->getAsAggregate();
-
- for (TIntermSequence::iterator p = aggrNode->getSequence()->begin();
- p != aggrNode->getSequence()->end(); p++)
- {
- int value = (*p)->getAsTyped()->getAsConstantUnion()->getIConst(0);
- offset[value]++;
- if (offset[value] > 1)
- {
- error(line, " l-value of swizzle cannot have duplicate components", op);
-
- return true;
- }
- }
- }
-
- return errorReturn;
+ return checkCanBeLValue(line, op, binaryNode->getLeft());
default:
break;
}
error(line, " l-value required", op);
-
- return true;
+ return false;
}
- const char *symbol = 0;
- if (symNode != 0)
- symbol = symNode->getSymbol().c_str();
-
- const char *message = 0;
+ std::string message;
switch (node->getQualifier())
{
case EvqConst:
@@ -320,9 +501,11 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc &line, const char *op, TIn
message = "can't modify an attribute";
break;
case EvqFragmentIn:
- message = "can't modify an input";
- break;
case EvqVertexIn:
+ case EvqGeometryIn:
+ case EvqFlatIn:
+ case EvqSmoothIn:
+ case EvqCentroidIn:
message = "can't modify an input";
break;
case EvqUniform:
@@ -340,6 +523,51 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc &line, const char *op, TIn
case EvqPointCoord:
message = "can't modify gl_PointCoord";
break;
+ case EvqNumWorkGroups:
+ message = "can't modify gl_NumWorkGroups";
+ break;
+ case EvqWorkGroupSize:
+ message = "can't modify gl_WorkGroupSize";
+ break;
+ case EvqWorkGroupID:
+ message = "can't modify gl_WorkGroupID";
+ break;
+ case EvqLocalInvocationID:
+ message = "can't modify gl_LocalInvocationID";
+ break;
+ case EvqGlobalInvocationID:
+ message = "can't modify gl_GlobalInvocationID";
+ break;
+ case EvqLocalInvocationIndex:
+ message = "can't modify gl_LocalInvocationIndex";
+ break;
+ case EvqViewIDOVR:
+ message = "can't modify gl_ViewID_OVR";
+ break;
+ case EvqComputeIn:
+ message = "can't modify work group size variable";
+ break;
+ case EvqPerVertexIn:
+ message = "can't modify any member in gl_in";
+ break;
+ case EvqPrimitiveIDIn:
+ message = "can't modify gl_PrimitiveIDIn";
+ break;
+ case EvqInvocationID:
+ message = "can't modify gl_InvocationID";
+ break;
+ case EvqPrimitiveID:
+ if (mShaderType == GL_FRAGMENT_SHADER)
+ {
+ message = "can't modify gl_PrimitiveID in a fragment shader";
+ }
+ break;
+ case EvqLayer:
+ if (mShaderType == GL_FRAGMENT_SHADER)
+ {
+ message = "can't modify gl_Layer in a fragment shader";
+ }
+ break;
default:
//
// Type that can't be written to?
@@ -348,287 +576,270 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc &line, const char *op, TIn
{
message = "can't modify void";
}
- if (IsSampler(node->getBasicType()))
+ if (IsOpaqueType(node->getBasicType()))
{
- message = "can't modify a sampler";
+ message = "can't modify a variable with type ";
+ message += getBasicString(node->getBasicType());
+ }
+ else if (node->getMemoryQualifier().readonly)
+ {
+ message = "can't modify a readonly variable";
}
}
- if (message == 0 && binaryNode == 0 && symNode == 0)
+ if (message.empty() && binaryNode == 0 && symNode == 0)
{
- error(line, " l-value required", op);
+ error(line, "l-value required", op);
- return true;
+ return false;
}
//
// Everything else is okay, no error.
//
- if (message == 0)
- return false;
+ if (message.empty())
+ return true;
//
// If we get here, we have an error and a message.
//
if (symNode)
{
- std::stringstream extraInfoStream;
- extraInfoStream << "\"" << symbol << "\" (" << message << ")";
- std::string extraInfo = extraInfoStream.str();
- error(line, " l-value required", op, extraInfo.c_str());
+ const char *symbol = symNode->getSymbol().c_str();
+ std::stringstream reasonStream;
+ reasonStream << "l-value required (" << message << " \"" << symbol << "\")";
+ std::string reason = reasonStream.str();
+ error(line, reason.c_str(), op);
}
else
{
- std::stringstream extraInfoStream;
- extraInfoStream << "(" << message << ")";
- std::string extraInfo = extraInfoStream.str();
- error(line, " l-value required", op, extraInfo.c_str());
+ std::stringstream reasonStream;
+ reasonStream << "l-value required (" << message << ")";
+ std::string reason = reasonStream.str();
+ error(line, reason.c_str(), op);
}
- return true;
+ return false;
}
-//
// Both test, and if necessary spit out an error, to see if the node is really
// a constant.
-//
-// Returns true if the was an error.
-//
-bool TParseContext::constErrorCheck(TIntermTyped *node)
+void TParseContext::checkIsConst(TIntermTyped *node)
{
- if (node->getQualifier() == EvqConst)
- return false;
-
- error(node->getLine(), "constant expression required", "");
-
- return true;
+ if (node->getQualifier() != EvqConst)
+ {
+ error(node->getLine(), "constant expression required", "");
+ }
}
-//
// Both test, and if necessary spit out an error, to see if the node is really
// an integer.
-//
-// Returns true if the was an error.
-//
-bool TParseContext::integerErrorCheck(TIntermTyped *node, const char *token)
+void TParseContext::checkIsScalarInteger(TIntermTyped *node, const char *token)
{
- if (node->isScalarInt())
- return false;
-
- error(node->getLine(), "integer expression required", token);
-
- return true;
+ if (!node->isScalarInt())
+ {
+ error(node->getLine(), "integer expression required", token);
+ }
}
-//
// Both test, and if necessary spit out an error, to see if we are currently
// globally scoped.
-//
-// Returns true if the was an error.
-//
-bool TParseContext::globalErrorCheck(const TSourceLoc &line, bool global, const char *token)
+bool TParseContext::checkIsAtGlobalLevel(const TSourceLoc &line, const char *token)
{
- if (global)
+ if (!symbolTable.atGlobalLevel())
+ {
+ error(line, "only allowed at global scope", token);
return false;
-
- error(line, "only allowed at global scope", token);
-
+ }
return true;
}
-//
-// For now, keep it simple: if it starts "gl_", it's reserved, independent
-// of scope. Except, if the symbol table is at the built-in push-level,
-// which is when we are parsing built-ins.
-// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
-// webgl shader.
-//
-// Returns true if there was an error.
-//
-bool TParseContext::reservedErrorCheck(const TSourceLoc &line, const TString &identifier)
+// ESSL 3.00.5 sections 3.8 and 3.9.
+// If it starts "gl_" or contains two consecutive underscores, it's reserved.
+// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a webgl shader.
+bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const TString &identifier)
{
static const char *reservedErrMsg = "reserved built-in name";
- if (!symbolTable.atBuiltInLevel())
+ if (identifier.compare(0, 3, "gl_") == 0)
{
- if (identifier.compare(0, 3, "gl_") == 0)
- {
- error(line, reservedErrMsg, "gl_");
- return true;
- }
- if (IsWebGLBasedSpec(mShaderSpec))
+ error(line, reservedErrMsg, "gl_");
+ return false;
+ }
+ if (sh::IsWebGLBasedSpec(mShaderSpec))
+ {
+ if (identifier.compare(0, 6, "webgl_") == 0)
{
- if (identifier.compare(0, 6, "webgl_") == 0)
- {
- error(line, reservedErrMsg, "webgl_");
- return true;
- }
- if (identifier.compare(0, 7, "_webgl_") == 0)
- {
- error(line, reservedErrMsg, "_webgl_");
- return true;
- }
- if (mShaderSpec == SH_CSS_SHADERS_SPEC && identifier.compare(0, 4, "css_") == 0)
- {
- error(line, reservedErrMsg, "css_");
- return true;
- }
+ error(line, reservedErrMsg, "webgl_");
+ return false;
}
- if (identifier.find("__") != TString::npos)
+ if (identifier.compare(0, 7, "_webgl_") == 0)
{
- error(line,
- "identifiers containing two consecutive underscores (__) are reserved as "
- "possible future keywords",
- identifier.c_str());
- return true;
+ error(line, reservedErrMsg, "_webgl_");
+ return false;
}
}
-
- return false;
-}
-
-//
-// Make sure there is enough data provided to the constructor to build
-// something of the type of the constructor. Also returns the type of
-// the constructor.
-//
-// Returns true if there was an error in construction.
-//
-bool TParseContext::constructorErrorCheck(const TSourceLoc &line,
- TIntermNode *argumentsNode,
- TFunction &function,
- TOperator op,
- TType *type)
-{
- *type = function.getReturnType();
-
- bool constructingMatrix = false;
- switch (op)
+ if (identifier.find("__") != TString::npos)
{
- case EOpConstructMat2:
- case EOpConstructMat2x3:
- case EOpConstructMat2x4:
- case EOpConstructMat3x2:
- case EOpConstructMat3:
- case EOpConstructMat3x4:
- case EOpConstructMat4x2:
- case EOpConstructMat4x3:
- case EOpConstructMat4:
- constructingMatrix = true;
- break;
- default:
- break;
+ error(line,
+ "identifiers containing two consecutive underscores (__) are reserved as "
+ "possible future keywords",
+ identifier.c_str());
+ return false;
}
+ return true;
+}
- //
- // Note: It's okay to have too many components available, but not okay to have unused
- // arguments. 'full' will go to true when enough args have been seen. If we loop
- // again, there is an extra argument, so 'overfull' will become true.
- //
-
- size_t size = 0;
- bool constType = true;
- bool full = false;
- bool overFull = false;
- bool matrixInMatrix = false;
- bool arrayArg = false;
- for (size_t i = 0; i < function.getParamCount(); ++i)
+// Make sure the argument types are correct for constructing a specific type.
+bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
+ const TIntermSequence *arguments,
+ const TType &type)
+{
+ if (arguments->empty())
{
- const TConstParameter &param = function.getParam(i);
- size += param.type->getObjectSize();
-
- if (constructingMatrix && param.type->isMatrix())
- matrixInMatrix = true;
- if (full)
- overFull = true;
- if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
- full = true;
- if (param.type->getQualifier() != EvqConst)
- constType = false;
- if (param.type->isArray())
- arrayArg = true;
+ error(line, "constructor does not have any arguments", "constructor");
+ return false;
}
- if (constType)
- type->setQualifier(EvqConst);
-
- if (type->isArray())
+ for (TIntermNode *arg : *arguments)
{
- if (type->isUnsizedArray())
+ const TIntermTyped *argTyped = arg->getAsTyped();
+ ASSERT(argTyped != nullptr);
+ if (type.getBasicType() != EbtStruct && IsOpaqueType(argTyped->getBasicType()))
{
- type->setArraySize(static_cast<int>(function.getParamCount()));
+ std::string reason("cannot convert a variable with type ");
+ reason += getBasicString(argTyped->getBasicType());
+ error(line, reason.c_str(), "constructor");
+ return false;
}
- else if (static_cast<size_t>(type->getArraySize()) != function.getParamCount())
+ else if (argTyped->getMemoryQualifier().writeonly)
{
- error(line, "array constructor needs one argument per array element", "constructor");
- return true;
+ error(line, "cannot convert a variable with writeonly", "constructor");
+ return false;
+ }
+ if (argTyped->getBasicType() == EbtVoid)
+ {
+ error(line, "cannot convert a void", "constructor");
+ return false;
}
}
- if (arrayArg && op != EOpConstructStruct)
+ if (type.isArray())
{
- error(line, "constructing from a non-dereferenced array", "constructor");
- return true;
+ // The size of an unsized constructor should already have been determined.
+ ASSERT(!type.isUnsizedArray());
+ if (static_cast<size_t>(type.getOutermostArraySize()) != arguments->size())
+ {
+ error(line, "array constructor needs one argument per array element", "constructor");
+ return false;
+ }
+ // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
+ // the array.
+ for (TIntermNode *const &argNode : *arguments)
+ {
+ const TType &argType = argNode->getAsTyped()->getType();
+ if (mShaderVersion < 310 && argType.isArray())
+ {
+ error(line, "constructing from a non-dereferenced array", "constructor");
+ return false;
+ }
+ if (!argType.isElementTypeOf(type))
+ {
+ error(line, "Array constructor argument has an incorrect type", "constructor");
+ return false;
+ }
+ }
}
-
- if (matrixInMatrix && !type->isArray())
+ else if (type.getBasicType() == EbtStruct)
{
- if (function.getParamCount() != 1)
+ const TFieldList &fields = type.getStruct()->fields();
+ if (fields.size() != arguments->size())
{
- error(line, "constructing matrix from matrix can only take one argument",
+ error(line,
+ "Number of constructor parameters does not match the number of structure fields",
"constructor");
- return true;
+ return false;
}
- }
- if (overFull)
- {
- error(line, "too many arguments", "constructor");
- return true;
+ for (size_t i = 0; i < fields.size(); i++)
+ {
+ if (i >= arguments->size() ||
+ (*arguments)[i]->getAsTyped()->getType() != *fields[i]->type())
+ {
+ error(line, "Structure constructor arguments do not match structure fields",
+ "constructor");
+ return false;
+ }
+ }
}
-
- if (op == EOpConstructStruct && !type->isArray() &&
- type->getStruct()->fields().size() != function.getParamCount())
+ else
{
- error(line,
- "Number of constructor parameters does not match the number of structure fields",
- "constructor");
- return true;
- }
+ // We're constructing a scalar, vector, or matrix.
- if (!type->isMatrix() || !matrixInMatrix)
- {
- if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) ||
- (op == EOpConstructStruct && size < type->getObjectSize()))
+ // Note: It's okay to have too many components available, but not okay to have unused
+ // arguments. 'full' will go to true when enough args have been seen. If we loop again,
+ // there is an extra argument, so 'overFull' will become true.
+
+ size_t size = 0;
+ bool full = false;
+ bool overFull = false;
+ bool matrixArg = false;
+ for (TIntermNode *arg : *arguments)
{
- error(line, "not enough data provided for construction", "constructor");
- return true;
- }
- }
+ const TIntermTyped *argTyped = arg->getAsTyped();
+ ASSERT(argTyped != nullptr);
- if (argumentsNode == nullptr)
- {
- error(line, "constructor does not have any arguments", "constructor");
- return true;
- }
+ if (argTyped->getBasicType() == EbtStruct)
+ {
+ error(line, "a struct cannot be used as a constructor argument for this type",
+ "constructor");
+ return false;
+ }
+ if (argTyped->getType().isArray())
+ {
+ error(line, "constructing from a non-dereferenced array", "constructor");
+ return false;
+ }
+ if (argTyped->getType().isMatrix())
+ {
+ matrixArg = true;
+ }
- TIntermAggregate *argumentsAgg = argumentsNode->getAsAggregate();
- for (TIntermNode *&argNode : *argumentsAgg->getSequence())
- {
- TIntermTyped *argTyped = argNode->getAsTyped();
- ASSERT(argTyped != nullptr);
- if (op != EOpConstructStruct && IsSampler(argTyped->getBasicType()))
+ size += argTyped->getType().getObjectSize();
+ if (full)
+ {
+ overFull = true;
+ }
+ if (size >= type.getObjectSize())
+ {
+ full = true;
+ }
+ }
+
+ if (type.isMatrix() && matrixArg)
{
- error(line, "cannot convert a sampler", "constructor");
- return true;
+ if (arguments->size() != 1)
+ {
+ error(line, "constructing matrix from matrix can only take one argument",
+ "constructor");
+ return false;
+ }
}
- if (argTyped->getBasicType() == EbtVoid)
+ else
{
- error(line, "cannot convert a void", "constructor");
- return true;
+ if (size != 1 && size < type.getObjectSize())
+ {
+ error(line, "not enough data provided for construction", "constructor");
+ return false;
+ }
+ if (overFull)
+ {
+ error(line, "too many arguments", "constructor");
+ return false;
+ }
}
}
- return false;
+ return true;
}
// This function checks to see if a void variable has been declared and raise an error message for
@@ -636,126 +847,116 @@ bool TParseContext::constructorErrorCheck(const TSourceLoc &line,
//
// returns true in case of an error
//
-bool TParseContext::voidErrorCheck(const TSourceLoc &line,
+bool TParseContext::checkIsNonVoid(const TSourceLoc &line,
const TString &identifier,
const TBasicType &type)
{
if (type == EbtVoid)
{
error(line, "illegal use of type 'void'", identifier.c_str());
- return true;
+ return false;
}
- return false;
+ return true;
}
// This function checks to see if the node (for the expression) contains a scalar boolean expression
-// or not
-//
-// returns true in case of an error
-//
-bool TParseContext::boolErrorCheck(const TSourceLoc &line, const TIntermTyped *type)
+// or not.
+bool TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type)
{
- if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector())
+ if (type->getBasicType() != EbtBool || !type->isScalar())
{
error(line, "boolean expression expected", "");
- return true;
+ return false;
}
-
- return false;
+ return true;
}
// This function checks to see if the node (for the expression) contains a scalar boolean expression
-// or not
-//
-// returns true in case of an error
-//
-bool TParseContext::boolErrorCheck(const TSourceLoc &line, const TPublicType &pType)
+// or not.
+void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType)
{
- if (pType.type != EbtBool || pType.isAggregate())
+ if (pType.getBasicType() != EbtBool || pType.isAggregate())
{
error(line, "boolean expression expected", "");
- return true;
}
-
- return false;
}
-bool TParseContext::samplerErrorCheck(const TSourceLoc &line,
- const TPublicType &pType,
- const char *reason)
+bool TParseContext::checkIsNotOpaqueType(const TSourceLoc &line,
+ const TTypeSpecifierNonArray &pType,
+ const char *reason)
{
if (pType.type == EbtStruct)
{
- if (containsSampler(*pType.userDef))
+ if (ContainsSampler(pType.userDef))
{
- error(line, reason, getBasicString(pType.type), "(structure contains a sampler)");
-
- return true;
+ std::stringstream reasonStream;
+ reasonStream << reason << " (structure contains a sampler)";
+ std::string reasonStr = reasonStream.str();
+ error(line, reasonStr.c_str(), getBasicString(pType.type));
+ return false;
}
-
- return false;
+ // only samplers need to be checked from structs, since other opaque types can't be struct
+ // members.
+ return true;
}
- else if (IsSampler(pType.type))
+ else if (IsOpaqueType(pType.type))
{
error(line, reason, getBasicString(pType.type));
-
- return true;
+ return false;
}
- return false;
+ return true;
}
-bool TParseContext::locationDeclaratorListCheck(const TSourceLoc &line, const TPublicType &pType)
+void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line,
+ const TPublicType &pType)
{
if (pType.layoutQualifier.location != -1)
{
error(line, "location must only be specified for a single input or output variable",
"location");
- return true;
}
-
- return false;
}
-bool TParseContext::parameterSamplerErrorCheck(const TSourceLoc &line,
- TQualifier qualifier,
- const TType &type)
+void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location,
+ const TLayoutQualifier &layoutQualifier)
{
- if ((qualifier == EvqOut || qualifier == EvqInOut) && type.getBasicType() != EbtStruct &&
- IsSampler(type.getBasicType()))
+ if (layoutQualifier.location != -1)
{
- error(line, "samplers cannot be output parameters", type.getBasicString());
- return true;
+ const char *errorMsg = "invalid layout qualifier: only valid on program inputs and outputs";
+ if (mShaderVersion >= 310)
+ {
+ errorMsg =
+ "invalid layout qualifier: only valid on shader inputs, outputs, and uniforms";
+ }
+ error(location, errorMsg, "location");
}
-
- return false;
}
-bool TParseContext::containsSampler(const TType &type)
+void TParseContext::checkStd430IsForShaderStorageBlock(const TSourceLoc &location,
+ const TLayoutBlockStorage &blockStorage,
+ const TQualifier &qualifier)
{
- if (IsSampler(type.getBasicType()))
- return true;
-
- if (type.getBasicType() == EbtStruct || type.isInterfaceBlock())
+ if (blockStorage == EbsStd430 && qualifier != EvqBuffer)
{
- const TFieldList &fields = type.getStruct()->fields();
- for (unsigned int i = 0; i < fields.size(); ++i)
- {
- if (containsSampler(*fields[i]->type()))
- return true;
- }
+ error(location, "The std430 layout is supported only for shader storage blocks.", "std430");
}
+}
- return false;
+void TParseContext::checkOutParameterIsNotOpaqueType(const TSourceLoc &line,
+ TQualifier qualifier,
+ const TType &type)
+{
+ ASSERT(qualifier == EvqOut || qualifier == EvqInOut);
+ if (IsOpaqueType(type.getBasicType()))
+ {
+ error(line, "opaque types cannot be output parameters", type.getBasicString());
+ }
}
-//
// Do size checking for an array type's size.
-//
-// Returns true if there was an error.
-//
-bool TParseContext::arraySizeErrorCheck(const TSourceLoc &line, TIntermTyped *expr, int &size)
+unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr)
{
TIntermConstantUnion *constant = expr->getAsConstantUnion();
@@ -765,36 +966,32 @@ bool TParseContext::arraySizeErrorCheck(const TSourceLoc &line, TIntermTyped *ex
if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt())
{
error(line, "array size must be a constant integer expression", "");
- size = 1;
- return true;
+ return 1u;
}
- unsigned int unsignedSize = 0;
+ unsigned int size = 0u;
if (constant->getBasicType() == EbtUInt)
{
- unsignedSize = constant->getUConst(0);
- size = static_cast<int>(unsignedSize);
+ size = constant->getUConst(0);
}
else
{
- size = constant->getIConst(0);
+ int signedSize = constant->getIConst(0);
- if (size < 0)
+ if (signedSize < 0)
{
error(line, "array size must be non-negative", "");
- size = 1;
- return true;
+ return 1u;
}
- unsignedSize = static_cast<unsigned int>(size);
+ size = static_cast<unsigned int>(signedSize);
}
- if (size == 0)
+ if (size == 0u)
{
error(line, "array size must be greater than zero", "");
- size = 1;
- return true;
+ return 1u;
}
// The size of arrays is restricted here to prevent issues further down the
@@ -802,76 +999,80 @@ bool TParseContext::arraySizeErrorCheck(const TSourceLoc &line, TIntermTyped *ex
// 4096 registers so this should be reasonable even for aggressively optimizable code.
const unsigned int sizeLimit = 65536;
- if (unsignedSize > sizeLimit)
+ if (size > sizeLimit)
{
error(line, "array size too large", "");
- size = 1;
- return true;
+ return 1u;
}
- return false;
+ return size;
}
-//
// See if this qualifier can be an array.
-//
-// Returns true if there is an error.
-//
-bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc &line, const TPublicType &type)
+bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line,
+ const TPublicType &elementQualifier)
{
- if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqVertexIn) ||
- (type.qualifier == EvqConst && mShaderVersion < 300))
+ if ((elementQualifier.qualifier == EvqAttribute) ||
+ (elementQualifier.qualifier == EvqVertexIn) ||
+ (elementQualifier.qualifier == EvqConst && mShaderVersion < 300))
{
error(line, "cannot declare arrays of this qualifier",
- TType(type).getCompleteString().c_str());
- return true;
+ TType(elementQualifier).getQualifierString());
+ return false;
}
- return false;
+ return true;
}
-//
-// See if this type can be an array.
-//
-// Returns true if there is an error.
-//
-bool TParseContext::arrayTypeErrorCheck(const TSourceLoc &line, const TPublicType &type)
+// See if this element type can be formed into an array.
+bool TParseContext::checkArrayElementIsNotArray(const TSourceLoc &line,
+ const TPublicType &elementType)
{
- //
- // Can the type be an array?
- //
- if (type.array)
+ if (mShaderVersion < 310 && elementType.isArray())
{
- error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str());
- return true;
+ error(line, "cannot declare arrays of arrays",
+ TType(elementType).getCompleteString().c_str());
+ return false;
+ }
+ return true;
+}
+
+// Check if this qualified element type can be formed into an array. This is only called when array
+// brackets are associated with an identifier in a declaration, like this:
+// float a[2];
+// Similar checks are done in addFullySpecifiedType for array declarations where the array brackets
+// are associated with the type, like this:
+// float[2] a;
+bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
+ const TPublicType &elementType)
+{
+ if (!checkArrayElementIsNotArray(indexLocation, elementType))
+ {
+ return false;
}
// In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
// In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section
// 4.3.4).
- if (mShaderVersion >= 300 && type.type == EbtStruct && sh::IsVarying(type.qualifier))
+ if (mShaderVersion >= 300 && elementType.getBasicType() == EbtStruct &&
+ sh::IsVarying(elementType.qualifier))
{
- error(line, "cannot declare arrays of structs of this qualifier",
- TType(type).getCompleteString().c_str());
- return true;
+ error(indexLocation, "cannot declare arrays of structs of this qualifier",
+ TType(elementType).getCompleteString().c_str());
+ return false;
}
-
- return false;
+ return checkIsValidQualifierForArray(indexLocation, elementType);
}
-//
// Enforce non-initializer type/qualifier rules.
-//
-// Returns true if there was an error.
-//
-bool TParseContext::nonInitErrorCheck(const TSourceLoc &line,
- const TString &identifier,
- TPublicType *type)
+void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
+ const TString &identifier,
+ TType *type)
{
ASSERT(type != nullptr);
- if (type->qualifier == EvqConst)
+ if (type->getQualifier() == EvqConst)
{
// Make the qualifier make sense.
- type->qualifier = EvqTemporary;
+ type->setQualifier(EvqTemporary);
// Generate informative error messages for ESSL1.
// In ESSL3 arrays and structures containing arrays can be constant.
@@ -886,15 +1087,10 @@ bool TParseContext::nonInitErrorCheck(const TSourceLoc &line,
{
error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
}
-
- return true;
}
- if (type->isUnsizedArray())
- {
- error(line, "implicitly sized arrays need to be initialized", identifier.c_str());
- return true;
- }
- return false;
+ // This will make the type sized if it isn't sized yet.
+ checkIsNotUnsizedArray(line, "implicitly sized arrays need to be initialized",
+ identifier.c_str(), type);
}
// Do some simple checks that are shared between all variable declarations,
@@ -909,18 +1105,27 @@ bool TParseContext::declareVariable(const TSourceLoc &line,
{
ASSERT((*variable) == nullptr);
- bool needsReservedErrorCheck = true;
+ checkBindingIsValid(line, type);
+
+ bool needsReservedCheck = true;
// gl_LastFragData may be redeclared with a new precision qualifier
if (type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0)
{
const TVariable *maxDrawBuffers = static_cast<const TVariable *>(
symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion));
- if (type.getArraySize() == maxDrawBuffers->getConstPointer()->getIConst())
+ if (type.isArrayOfArrays())
+ {
+ error(line, "redeclaration of gl_LastFragData as an array of arrays",
+ identifier.c_str());
+ return false;
+ }
+ else if (static_cast<int>(type.getOutermostArraySize()) ==
+ maxDrawBuffers->getConstPointer()->getIConst())
{
if (TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
{
- needsReservedErrorCheck = extensionErrorCheck(line, builtInSymbol->getExtension());
+ needsReservedCheck = !checkCanUseExtension(line, builtInSymbol->getExtension());
}
}
else
@@ -931,77 +1136,237 @@ bool TParseContext::declareVariable(const TSourceLoc &line,
}
}
- if (needsReservedErrorCheck && reservedErrorCheck(line, identifier))
+ if (needsReservedCheck && !checkIsNotReserved(line, identifier))
return false;
- (*variable) = new TVariable(&identifier, type);
- if (!symbolTable.declare(*variable))
+ (*variable) = symbolTable.declareVariable(&identifier, type);
+ if (!(*variable))
{
error(line, "redefinition", identifier.c_str());
- *variable = nullptr;
return false;
}
- if (voidErrorCheck(line, identifier, type.getBasicType()))
+ if (!checkIsNonVoid(line, identifier, type.getBasicType()))
return false;
return true;
}
-bool TParseContext::paramErrorCheck(const TSourceLoc &line,
- TQualifier qualifier,
- TQualifier paramQualifier,
- TType *type)
+void TParseContext::checkIsParameterQualifierValid(
+ const TSourceLoc &line,
+ const TTypeQualifierBuilder &typeQualifierBuilder,
+ TType *type)
+{
+ // The only parameter qualifiers a parameter can have are in, out, inout or const.
+ TTypeQualifier typeQualifier = typeQualifierBuilder.getParameterTypeQualifier(mDiagnostics);
+
+ if (typeQualifier.qualifier == EvqOut || typeQualifier.qualifier == EvqInOut)
+ {
+ checkOutParameterIsNotOpaqueType(line, typeQualifier.qualifier, *type);
+ }
+
+ if (!IsImage(type->getBasicType()))
+ {
+ checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, line);
+ }
+ else
+ {
+ type->setMemoryQualifier(typeQualifier.memoryQualifier);
+ }
+
+ type->setQualifier(typeQualifier.qualifier);
+
+ if (typeQualifier.precision != EbpUndefined)
+ {
+ type->setPrecision(typeQualifier.precision);
+ }
+}
+
+template <size_t size>
+bool TParseContext::checkCanUseOneOfExtensions(const TSourceLoc &line,
+ const std::array<TExtension, size> &extensions)
{
- if (qualifier != EvqConst && qualifier != EvqTemporary)
+ ASSERT(!extensions.empty());
+ const TExtensionBehavior &extBehavior = extensionBehavior();
+
+ bool canUseWithWarning = false;
+ bool canUseWithoutWarning = false;
+
+ const char *errorMsgString = "";
+ TExtension errorMsgExtension = TExtension::UNDEFINED;
+
+ for (TExtension extension : extensions)
+ {
+ auto extIter = extBehavior.find(extension);
+ if (canUseWithWarning)
+ {
+ // We already have an extension that we can use, but with a warning.
+ // See if we can use the alternative extension without a warning.
+ if (extIter == extBehavior.end())
+ {
+ continue;
+ }
+ if (extIter->second == EBhEnable || extIter->second == EBhRequire)
+ {
+ canUseWithoutWarning = true;
+ break;
+ }
+ continue;
+ }
+ if (extIter == extBehavior.end())
+ {
+ errorMsgString = "extension is not supported";
+ errorMsgExtension = extension;
+ }
+ else if (extIter->second == EBhUndefined || extIter->second == EBhDisable)
+ {
+ errorMsgString = "extension is disabled";
+ errorMsgExtension = extension;
+ }
+ else if (extIter->second == EBhWarn)
+ {
+ errorMsgExtension = extension;
+ canUseWithWarning = true;
+ }
+ else
+ {
+ ASSERT(extIter->second == EBhEnable || extIter->second == EBhRequire);
+ canUseWithoutWarning = true;
+ break;
+ }
+ }
+
+ if (canUseWithoutWarning)
{
- error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier));
return true;
}
- if (qualifier == EvqConst && paramQualifier != EvqIn)
+ if (canUseWithWarning)
{
- error(line, "qualifier not allowed with ", getQualifierString(qualifier),
- getQualifierString(paramQualifier));
+ warning(line, "extension is being used", GetExtensionNameString(errorMsgExtension));
return true;
}
+ error(line, errorMsgString, GetExtensionNameString(errorMsgExtension));
+ return false;
+}
- if (qualifier == EvqConst)
- type->setQualifier(EvqConstReadOnly);
+template bool TParseContext::checkCanUseOneOfExtensions(
+ const TSourceLoc &line,
+ const std::array<TExtension, 1> &extensions);
+template bool TParseContext::checkCanUseOneOfExtensions(
+ const TSourceLoc &line,
+ const std::array<TExtension, 2> &extensions);
+template bool TParseContext::checkCanUseOneOfExtensions(
+ const TSourceLoc &line,
+ const std::array<TExtension, 3> &extensions);
+
+bool TParseContext::checkCanUseExtension(const TSourceLoc &line, TExtension extension)
+{
+ ASSERT(extension != TExtension::UNDEFINED);
+ ASSERT(extension != TExtension::EXT_geometry_shader);
+ if (extension == TExtension::OES_geometry_shader)
+ {
+ // OES_geometry_shader and EXT_geometry_shader are always interchangeable.
+ constexpr std::array<TExtension, 2u> extensions{
+ {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}};
+ return checkCanUseOneOfExtensions(line, extensions);
+ }
+ return checkCanUseOneOfExtensions(line, std::array<TExtension, 1u>{{extension}});
+}
+
+// ESSL 3.00.6 section 4.8 Empty Declarations: "The combinations of qualifiers that cause
+// compile-time or link-time errors are the same whether or not the declaration is empty".
+// This function implements all the checks that are done on qualifiers regardless of if the
+// declaration is empty.
+void TParseContext::declarationQualifierErrorCheck(const sh::TQualifier qualifier,
+ const sh::TLayoutQualifier &layoutQualifier,
+ const TSourceLoc &location)
+{
+ if (qualifier == EvqShared && !layoutQualifier.isEmpty())
+ {
+ error(location, "Shared memory declarations cannot have layout specified", "layout");
+ }
+
+ if (layoutQualifier.matrixPacking != EmpUnspecified)
+ {
+ error(location, "layout qualifier only valid for interface blocks",
+ getMatrixPackingString(layoutQualifier.matrixPacking));
+ return;
+ }
+
+ if (layoutQualifier.blockStorage != EbsUnspecified)
+ {
+ error(location, "layout qualifier only valid for interface blocks",
+ getBlockStorageString(layoutQualifier.blockStorage));
+ return;
+ }
+
+ if (qualifier == EvqFragmentOut)
+ {
+ if (layoutQualifier.location != -1 && layoutQualifier.yuv == true)
+ {
+ error(location, "invalid layout qualifier combination", "yuv");
+ return;
+ }
+ }
else
- type->setQualifier(paramQualifier);
+ {
+ checkYuvIsNotSpecified(location, layoutQualifier.yuv);
+ }
- return false;
+ // If multiview extension is enabled, "in" qualifier is allowed in the vertex shader in previous
+ // parsing steps. So it needs to be checked here.
+ if (isExtensionEnabled(TExtension::OVR_multiview) && mShaderVersion < 300 &&
+ qualifier == EvqVertexIn)
+ {
+ error(location, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
+ }
+
+ bool canHaveLocation = qualifier == EvqVertexIn || qualifier == EvqFragmentOut;
+ if (mShaderVersion >= 310)
+ {
+ canHaveLocation = canHaveLocation || qualifier == EvqUniform || IsVarying(qualifier);
+ // We're not checking whether the uniform location is in range here since that depends on
+ // the type of the variable.
+ // The type can only be fully determined for non-empty declarations.
+ }
+ if (!canHaveLocation)
+ {
+ checkLocationIsNotSpecified(location, layoutQualifier);
+ }
}
-bool TParseContext::extensionErrorCheck(const TSourceLoc &line, const TString &extension)
+void TParseContext::atomicCounterQualifierErrorCheck(const TPublicType &publicType,
+ const TSourceLoc &location)
{
- const TExtensionBehavior &extBehavior = extensionBehavior();
- TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
- if (iter == extBehavior.end())
+ if (publicType.precision != EbpHigh)
{
- error(line, "extension", extension.c_str(), "is not supported");
- return true;
+ error(location, "Can only be highp", "atomic counter");
}
- // In GLSL ES, an extension's default behavior is "disable".
- if (iter->second == EBhDisable || iter->second == EBhUndefined)
+ // dEQP enforces compile error if location is specified. See uniform_location.test.
+ if (publicType.layoutQualifier.location != -1)
{
- error(line, "extension", extension.c_str(), "is disabled");
- return true;
+ error(location, "location must not be set for atomic_uint", "layout");
}
- if (iter->second == EBhWarn)
+ if (publicType.layoutQualifier.binding == -1)
{
- warning(line, "extension", extension.c_str(), "is being used");
- return false;
+ error(location, "no binding specified", "atomic counter");
}
+}
- return false;
+void TParseContext::emptyDeclarationErrorCheck(const TType &type, const TSourceLoc &location)
+{
+ if (type.isUnsizedArray())
+ {
+ // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
+ // error. It is assumed that this applies to empty declarations as well.
+ error(location, "empty array declaration needs to specify a size", "");
+ }
}
-// These checks are common for all declarations starting a declarator list, and declarators that
-// follow an empty declaration.
-//
-bool TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType,
- const TSourceLoc &identifierLocation)
+// These checks are done for all declarations that are non-empty. They're done for non-empty
+// declarations starting a declarator list, and declarators that follow an empty declaration.
+void TParseContext::nonEmptyDeclarationErrorCheck(const TPublicType &publicType,
+ const TSourceLoc &identifierLocation)
{
switch (publicType.qualifier)
{
@@ -1010,105 +1375,363 @@ bool TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType,
case EvqAttribute:
case EvqVertexIn:
case EvqFragmentOut:
- if (publicType.type == EbtStruct)
+ case EvqComputeIn:
+ if (publicType.getBasicType() == EbtStruct)
{
error(identifierLocation, "cannot be used with a structure",
getQualifierString(publicType.qualifier));
- return true;
+ return;
}
-
+ break;
+ case EvqBuffer:
+ if (publicType.getBasicType() != EbtInterfaceBlock)
+ {
+ error(identifierLocation,
+ "cannot declare buffer variables at global scope(outside a block)",
+ getQualifierString(publicType.qualifier));
+ return;
+ }
+ break;
default:
break;
}
-
+ std::string reason(getBasicString(publicType.getBasicType()));
+ reason += "s must be uniform";
if (publicType.qualifier != EvqUniform &&
- samplerErrorCheck(identifierLocation, publicType, "samplers must be uniform"))
+ !checkIsNotOpaqueType(identifierLocation, publicType.typeSpecifierNonArray, reason.c_str()))
{
- return true;
+ return;
+ }
+
+ if ((publicType.qualifier != EvqTemporary && publicType.qualifier != EvqGlobal &&
+ publicType.qualifier != EvqConst) &&
+ publicType.getBasicType() == EbtYuvCscStandardEXT)
+ {
+ error(identifierLocation, "cannot be used with a yuvCscStandardEXT",
+ getQualifierString(publicType.qualifier));
+ return;
+ }
+
+ if (mShaderVersion >= 310 && publicType.qualifier == EvqUniform)
+ {
+ // Valid uniform declarations can't be unsized arrays since uniforms can't be initialized.
+ // But invalid shaders may still reach here with an unsized array declaration.
+ TType type(publicType);
+ if (!type.isUnsizedArray())
+ {
+ checkUniformLocationInRange(identifierLocation, type.getLocationCount(),
+ publicType.layoutQualifier);
+ }
}
// check for layout qualifier issues
const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
- if (layoutQualifier.matrixPacking != EmpUnspecified)
+ if (IsImage(publicType.getBasicType()))
{
- error(identifierLocation, "layout qualifier",
- getMatrixPackingString(layoutQualifier.matrixPacking),
- "only valid for interface blocks");
- return true;
+
+ switch (layoutQualifier.imageInternalFormat)
+ {
+ case EiifRGBA32F:
+ case EiifRGBA16F:
+ case EiifR32F:
+ case EiifRGBA8:
+ case EiifRGBA8_SNORM:
+ if (!IsFloatImage(publicType.getBasicType()))
+ {
+ error(identifierLocation,
+ "internal image format requires a floating image type",
+ getBasicString(publicType.getBasicType()));
+ return;
+ }
+ break;
+ case EiifRGBA32I:
+ case EiifRGBA16I:
+ case EiifRGBA8I:
+ case EiifR32I:
+ if (!IsIntegerImage(publicType.getBasicType()))
+ {
+ error(identifierLocation,
+ "internal image format requires an integer image type",
+ getBasicString(publicType.getBasicType()));
+ return;
+ }
+ break;
+ case EiifRGBA32UI:
+ case EiifRGBA16UI:
+ case EiifRGBA8UI:
+ case EiifR32UI:
+ if (!IsUnsignedImage(publicType.getBasicType()))
+ {
+ error(identifierLocation,
+ "internal image format requires an unsigned image type",
+ getBasicString(publicType.getBasicType()));
+ return;
+ }
+ break;
+ case EiifUnspecified:
+ error(identifierLocation, "layout qualifier", "No image internal format specified");
+ return;
+ default:
+ error(identifierLocation, "layout qualifier", "unrecognized token");
+ return;
+ }
+
+ // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
+ switch (layoutQualifier.imageInternalFormat)
+ {
+ case EiifR32F:
+ case EiifR32I:
+ case EiifR32UI:
+ break;
+ default:
+ if (!publicType.memoryQualifier.readonly && !publicType.memoryQualifier.writeonly)
+ {
+ error(identifierLocation, "layout qualifier",
+ "Except for images with the r32f, r32i and r32ui format qualifiers, "
+ "image variables must be qualified readonly and/or writeonly");
+ return;
+ }
+ break;
+ }
+ }
+ else
+ {
+ checkInternalFormatIsNotSpecified(identifierLocation, layoutQualifier.imageInternalFormat);
+ checkMemoryQualifierIsNotSpecified(publicType.memoryQualifier, identifierLocation);
}
- if (layoutQualifier.blockStorage != EbsUnspecified)
+ if (IsAtomicCounter(publicType.getBasicType()))
{
- error(identifierLocation, "layout qualifier",
- getBlockStorageString(layoutQualifier.blockStorage),
- "only valid for interface blocks");
- return true;
+ atomicCounterQualifierErrorCheck(publicType, identifierLocation);
}
+ else
+ {
+ checkOffsetIsNotSpecified(identifierLocation, layoutQualifier.offset);
+ }
+}
- if (publicType.qualifier != EvqVertexIn && publicType.qualifier != EvqFragmentOut &&
- layoutLocationErrorCheck(identifierLocation, publicType.layoutQualifier))
+void TParseContext::checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type)
+{
+ TLayoutQualifier layoutQualifier = type.getLayoutQualifier();
+ // Note that the ESSL 3.10 section 4.4.5 is not particularly clear on how the binding qualifier
+ // on arrays of arrays should be handled. We interpret the spec so that the binding value is
+ // incremented for each element of the innermost nested arrays. This is in line with how arrays
+ // of arrays of blocks are specified to behave in GLSL 4.50 and a conservative interpretation
+ // when it comes to which shaders are accepted by the compiler.
+ int arrayTotalElementCount = type.getArraySizeProduct();
+ if (IsImage(type.getBasicType()))
{
- return true;
+ checkImageBindingIsValid(identifierLocation, layoutQualifier.binding,
+ arrayTotalElementCount);
+ }
+ else if (IsSampler(type.getBasicType()))
+ {
+ checkSamplerBindingIsValid(identifierLocation, layoutQualifier.binding,
+ arrayTotalElementCount);
+ }
+ else if (IsAtomicCounter(type.getBasicType()))
+ {
+ checkAtomicCounterBindingIsValid(identifierLocation, layoutQualifier.binding);
+ }
+ else
+ {
+ ASSERT(!IsOpaqueType(type.getBasicType()));
+ checkBindingIsNotSpecified(identifierLocation, layoutQualifier.binding);
}
+}
- return false;
+void TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location,
+ const TString &layoutQualifierName,
+ int versionRequired)
+{
+
+ if (mShaderVersion < versionRequired)
+ {
+ error(location, "invalid layout qualifier: not supported", layoutQualifierName.c_str());
+ }
}
-bool TParseContext::layoutLocationErrorCheck(const TSourceLoc &location,
- const TLayoutQualifier &layoutQualifier)
+bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
+ const TLayoutQualifier &layoutQualifier)
{
- if (layoutQualifier.location != -1)
+ const sh::WorkGroupSize &localSize = layoutQualifier.localSize;
+ for (size_t i = 0u; i < localSize.size(); ++i)
{
- error(location, "invalid layout qualifier:", "location",
- "only valid on program inputs and outputs");
- return true;
+ if (localSize[i] != -1)
+ {
+ error(location,
+ "invalid layout qualifier: only valid when used with 'in' in a compute shader "
+ "global layout declaration",
+ getWorkGroupSizeString(i));
+ return false;
+ }
}
- return false;
+ return true;
+}
+
+void TParseContext::checkInternalFormatIsNotSpecified(const TSourceLoc &location,
+ TLayoutImageInternalFormat internalFormat)
+{
+ if (internalFormat != EiifUnspecified)
+ {
+ error(location, "invalid layout qualifier: only valid when used with images",
+ getImageInternalFormatString(internalFormat));
+ }
+}
+
+void TParseContext::checkBindingIsNotSpecified(const TSourceLoc &location, int binding)
+{
+ if (binding != -1)
+ {
+ error(location,
+ "invalid layout qualifier: only valid when used with opaque types or blocks",
+ "binding");
+ }
+}
+
+void TParseContext::checkOffsetIsNotSpecified(const TSourceLoc &location, int offset)
+{
+ if (offset != -1)
+ {
+ error(location, "invalid layout qualifier: only valid when used with atomic counters",
+ "offset");
+ }
+}
+
+void TParseContext::checkImageBindingIsValid(const TSourceLoc &location,
+ int binding,
+ int arrayTotalElementCount)
+{
+ // Expects arraySize to be 1 when setting binding for only a single variable.
+ if (binding >= 0 && binding + arrayTotalElementCount > mMaxImageUnits)
+ {
+ error(location, "image binding greater than gl_MaxImageUnits", "binding");
+ }
+}
+
+void TParseContext::checkSamplerBindingIsValid(const TSourceLoc &location,
+ int binding,
+ int arrayTotalElementCount)
+{
+ // Expects arraySize to be 1 when setting binding for only a single variable.
+ if (binding >= 0 && binding + arrayTotalElementCount > mMaxCombinedTextureImageUnits)
+ {
+ error(location, "sampler binding greater than maximum texture units", "binding");
+ }
+}
+
+void TParseContext::checkBlockBindingIsValid(const TSourceLoc &location,
+ const TQualifier &qualifier,
+ int binding,
+ int arraySize)
+{
+ int size = (arraySize == 0 ? 1 : arraySize);
+ if (qualifier == EvqUniform)
+ {
+ if (binding + size > mMaxUniformBufferBindings)
+ {
+ error(location, "uniform block binding greater than MAX_UNIFORM_BUFFER_BINDINGS",
+ "binding");
+ }
+ }
+ else if (qualifier == EvqBuffer)
+ {
+ if (binding + size > mMaxShaderStorageBufferBindings)
+ {
+ error(location,
+ "shader storage block binding greater than MAX_SHADER_STORAGE_BUFFER_BINDINGS",
+ "binding");
+ }
+ }
+}
+void TParseContext::checkAtomicCounterBindingIsValid(const TSourceLoc &location, int binding)
+{
+ if (binding >= mMaxAtomicCounterBindings)
+ {
+ error(location, "atomic counter binding greater than gl_MaxAtomicCounterBindings",
+ "binding");
+ }
+}
+
+void TParseContext::checkUniformLocationInRange(const TSourceLoc &location,
+ int objectLocationCount,
+ const TLayoutQualifier &layoutQualifier)
+{
+ int loc = layoutQualifier.location;
+ if (loc >= 0 && loc + objectLocationCount > mMaxUniformLocations)
+ {
+ error(location, "Uniform location out of range", "location");
+ }
+}
+
+void TParseContext::checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv)
+{
+ if (yuv != false)
+ {
+ error(location, "invalid layout qualifier: only valid on program outputs", "yuv");
+ }
}
-bool TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate,
- TIntermAggregate *aggregate)
+void TParseContext::functionCallRValueLValueErrorCheck(const TFunction *fnCandidate,
+ TIntermAggregate *fnCall)
{
for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
{
TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
+ TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
+ if (!IsImage(argument->getBasicType()) && (IsQualifierUnspecified(qual) || qual == EvqIn ||
+ qual == EvqInOut || qual == EvqConstReadOnly))
+ {
+ if (argument->getMemoryQualifier().writeonly)
+ {
+ error(argument->getLine(),
+ "Writeonly value cannot be passed for 'in' or 'inout' parameters.",
+ fnCall->getFunctionSymbolInfo()->getName().c_str());
+ return;
+ }
+ }
if (qual == EvqOut || qual == EvqInOut)
{
- TIntermTyped *node = (*(aggregate->getSequence()))[i]->getAsTyped();
- if (lValueErrorCheck(node->getLine(), "assign", node))
+ if (!checkCanBeLValue(argument->getLine(), "assign", argument))
{
- error(node->getLine(),
- "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
- recover();
- return true;
+ error(argument->getLine(),
+ "Constant value cannot be passed for 'out' or 'inout' parameters.",
+ fnCall->getFunctionSymbolInfo()->getName().c_str());
+ return;
}
}
}
- return false;
}
-void TParseContext::es3InvariantErrorCheck(const TQualifier qualifier,
- const TSourceLoc &invariantLocation)
+void TParseContext::checkInvariantVariableQualifier(bool invariant,
+ const TQualifier qualifier,
+ const TSourceLoc &invariantLocation)
{
- if (!sh::IsVaryingOut(qualifier) && qualifier != EvqFragmentOut)
+ if (!invariant)
+ return;
+
+ if (mShaderVersion < 300)
{
- error(invariantLocation, "Only out variables can be invariant.", "invariant");
- recover();
+ // input variables in the fragment shader can be also qualified as invariant
+ if (!sh::CanBeInvariantESSL1(qualifier))
+ {
+ error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
+ }
+ }
+ else
+ {
+ if (!sh::CanBeInvariantESSL3OrGreater(qualifier))
+ {
+ error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
+ }
}
}
-bool TParseContext::supportsExtension(const char *extension)
-{
- const TExtensionBehavior &extbehavior = extensionBehavior();
- TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
- return (iter != extbehavior.end());
-}
-
-bool TParseContext::isExtensionEnabled(const char *extension) const
+bool TParseContext::isExtensionEnabled(TExtension extension) const
{
- return ::IsExtensionEnabled(extensionBehavior(), extension);
+ return IsExtensionEnabled(extensionBehavior(), extension);
}
void TParseContext::handleExtensionDirective(const TSourceLoc &loc,
@@ -1132,6 +1755,32 @@ void TParseContext::handlePragmaDirective(const TSourceLoc &loc,
mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl);
}
+sh::WorkGroupSize TParseContext::getComputeShaderLocalSize() const
+{
+ sh::WorkGroupSize result(-1);
+ for (size_t i = 0u; i < result.size(); ++i)
+ {
+ if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1)
+ {
+ result[i] = 1;
+ }
+ else
+ {
+ result[i] = mComputeShaderLocalSize[i];
+ }
+ }
+ return result;
+}
+
+TIntermConstantUnion *TParseContext::addScalarLiteral(const TConstantUnion *constantUnion,
+ const TSourceLoc &line)
+{
+ TIntermConstantUnion *node = new TIntermConstantUnion(
+ constantUnion, TType(constantUnion->getType(), EbpUndefined, EvqConst));
+ node->setLine(line);
+ return node;
+}
+
/////////////////////////////////////////////////////////////////////////////////
//
// Non-Errors.
@@ -1142,70 +1791,64 @@ const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
const TString *name,
const TSymbol *symbol)
{
- const TVariable *variable = NULL;
-
if (!symbol)
{
error(location, "undeclared identifier", name->c_str());
- recover();
+ return nullptr;
}
- else if (!symbol->isVariable())
+
+ if (!symbol->isVariable())
{
error(location, "variable expected", name->c_str());
- recover();
+ return nullptr;
}
- else
- {
- variable = static_cast<const TVariable *>(symbol);
- if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) &&
- !variable->getExtension().empty() &&
- extensionErrorCheck(location, variable->getExtension()))
- {
- recover();
- }
+ const TVariable *variable = static_cast<const TVariable *>(symbol);
- // Reject shaders using both gl_FragData and gl_FragColor
- TQualifier qualifier = variable->getType().getQualifier();
- if (qualifier == EvqFragData || qualifier == EvqSecondaryFragDataEXT)
- {
- mUsesFragData = true;
- }
- else if (qualifier == EvqFragColor || qualifier == EvqSecondaryFragColorEXT)
- {
- mUsesFragColor = true;
- }
- if (qualifier == EvqSecondaryFragDataEXT || qualifier == EvqSecondaryFragColorEXT)
- {
- mUsesSecondaryOutputs = true;
- }
+ if (variable->getExtension() != TExtension::UNDEFINED)
+ {
+ checkCanUseExtension(location, variable->getExtension());
+ }
+
+ // Reject shaders using both gl_FragData and gl_FragColor
+ TQualifier qualifier = variable->getType().getQualifier();
+ if (qualifier == EvqFragData || qualifier == EvqSecondaryFragDataEXT)
+ {
+ mUsesFragData = true;
+ }
+ else if (qualifier == EvqFragColor || qualifier == EvqSecondaryFragColorEXT)
+ {
+ mUsesFragColor = true;
+ }
+ if (qualifier == EvqSecondaryFragDataEXT || qualifier == EvqSecondaryFragColorEXT)
+ {
+ mUsesSecondaryOutputs = true;
+ }
- // This validation is not quite correct - it's only an error to write to
- // both FragData and FragColor. For simplicity, and because users shouldn't
- // be rewarded for reading from undefined varaibles, return an error
- // if they are both referenced, rather than assigned.
- if (mUsesFragData && mUsesFragColor)
+ // This validation is not quite correct - it's only an error to write to
+ // both FragData and FragColor. For simplicity, and because users shouldn't
+ // be rewarded for reading from undefined varaibles, return an error
+ // if they are both referenced, rather than assigned.
+ if (mUsesFragData && mUsesFragColor)
+ {
+ const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
+ if (mUsesSecondaryOutputs)
{
- const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
- if (mUsesSecondaryOutputs)
- {
- errorMessage =
- "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
- " and (gl_FragColor, gl_SecondaryFragColorEXT)";
- }
- error(location, errorMessage, name->c_str());
- recover();
+ errorMessage =
+ "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
+ " and (gl_FragColor, gl_SecondaryFragColorEXT)";
}
+ error(location, errorMessage, name->c_str());
}
- if (!variable)
+ // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
+ if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
+ qualifier == EvqWorkGroupSize)
{
- TType type(EbtFloat, EbpUndefined);
- TVariable *fakeVariable = new TVariable(name, type);
- symbolTable.declare(fakeVariable);
- variable = fakeVariable;
+ error(location,
+ "It is an error to use gl_WorkGroupSize before declaring the local group size",
+ "gl_WorkGroupSize");
}
-
return variable;
}
@@ -1215,75 +1858,82 @@ TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
{
const TVariable *variable = getNamedVariable(location, name, symbol);
+ if (!variable)
+ {
+ TIntermTyped *node = CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
+ node->setLine(location);
+ return node;
+ }
+
+ const TType &variableType = variable->getType();
+ TIntermTyped *node = nullptr;
+
if (variable->getConstPointer())
{
const TConstantUnion *constArray = variable->getConstPointer();
- return intermediate.addConstantUnion(constArray, variable->getType(), location);
+ node = new TIntermConstantUnion(constArray, variableType);
}
- else
+ else if (variableType.getQualifier() == EvqWorkGroupSize && mComputeShaderLocalSizeDeclared)
{
- return intermediate.addSymbol(variable->getUniqueId(), variable->getName(),
- variable->getType(), location);
- }
-}
+ // gl_WorkGroupSize can be used to size arrays according to the ESSL 3.10.4 spec, so it
+ // needs to be added to the AST as a constant and not as a symbol.
+ sh::WorkGroupSize workGroupSize = getComputeShaderLocalSize();
+ TConstantUnion *constArray = new TConstantUnion[3];
+ for (size_t i = 0; i < 3; ++i)
+ {
+ constArray[i].setUConst(static_cast<unsigned int>(workGroupSize[i]));
+ }
-//
-// Look up a function name in the symbol table, and make sure it is a function.
-//
-// Return the function symbol if found, otherwise 0.
-//
-const TFunction *TParseContext::findFunction(const TSourceLoc &line,
- TFunction *call,
- int inputShaderVersion,
- bool *builtIn)
-{
- // First find by unmangled name to check whether the function name has been
- // hidden by a variable name or struct typename.
- // If a function is found, check for one with a matching argument list.
- const TSymbol *symbol = symbolTable.find(call->getName(), inputShaderVersion, builtIn);
- if (symbol == 0 || symbol->isFunction())
- {
- symbol = symbolTable.find(call->getMangledName(), inputShaderVersion, builtIn);
- }
+ ASSERT(variableType.getBasicType() == EbtUInt);
+ ASSERT(variableType.getObjectSize() == 3);
- if (symbol == 0)
- {
- error(line, "no matching overloaded function found", call->getName().c_str());
- return 0;
+ TType type(variableType);
+ type.setQualifier(EvqConst);
+ node = new TIntermConstantUnion(constArray, type);
}
+ else if ((mGeometryShaderInputPrimitiveType != EptUndefined) &&
+ (variableType.getQualifier() == EvqPerVertexIn))
+ {
+ ASSERT(mGeometryShaderInputArraySize > 0u);
- if (!symbol->isFunction())
+ node = new TIntermSymbol(variable->getUniqueId(), variable->getName(), variableType);
+ node->getTypePointer()->sizeOutermostUnsizedArray(mGeometryShaderInputArraySize);
+ }
+ else
{
- error(line, "function name expected", call->getName().c_str());
- return 0;
+ node = new TIntermSymbol(variable->getUniqueId(), variable->getName(), variableType);
}
-
- return static_cast<const TFunction *>(symbol);
+ ASSERT(node != nullptr);
+ node->setLine(location);
+ return node;
}
-//
// Initializers show up in several places in the grammar. Have one set of
// code to handle them here.
//
-// Returns true on error, false if no error
-//
+// Returns true on success.
bool TParseContext::executeInitializer(const TSourceLoc &line,
const TString &identifier,
- const TPublicType &pType,
+ TType type,
TIntermTyped *initializer,
- TIntermNode **intermNode)
+ TIntermBinary **initNode)
{
- ASSERT(intermNode != nullptr);
- TType type = TType(pType);
+ ASSERT(initNode != nullptr);
+ ASSERT(*initNode == nullptr);
TVariable *variable = nullptr;
if (type.isUnsizedArray())
{
- type.setArraySize(initializer->getArraySize());
+ // In case initializer is not an array or type has more dimensions than initializer, this
+ // will default to setting array sizes to 1. We have not checked yet whether the initializer
+ // actually is an array or not. Having a non-array initializer for an unsized array will
+ // result in an error later, so we don't generate an error message here.
+ auto *arraySizes = initializer->getType().getArraySizes();
+ type.sizeUnsizedArrays(arraySizes);
}
if (!declareVariable(line, identifier, type, &variable))
{
- return true;
+ return false;
}
bool globalInitWarning = false;
@@ -1293,7 +1943,7 @@ bool TParseContext::executeInitializer(const TSourceLoc &line,
// Error message does not completely match behavior with ESSL 1.00, but
// we want to steer developers towards only using constant expressions.
error(line, "global variable initializers must be constant expressions", "=");
- return true;
+ return false;
}
if (globalInitWarning)
{
@@ -1312,7 +1962,7 @@ bool TParseContext::executeInitializer(const TSourceLoc &line,
{
error(line, " cannot initialize this type of qualifier ",
variable->getType().getQualifierString());
- return true;
+ return false;
}
//
// test for and propagate constant
@@ -1322,19 +1972,20 @@ bool TParseContext::executeInitializer(const TSourceLoc &line,
{
if (qualifier != initializer->getType().getQualifier())
{
- std::stringstream extraInfoStream;
- extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
- std::string extraInfo = extraInfoStream.str();
- error(line, " assigning non-constant to", "=", extraInfo.c_str());
+ std::stringstream reasonStream;
+ reasonStream << "assigning non-constant to '" << variable->getType().getCompleteString()
+ << "'";
+ std::string reason = reasonStream.str();
+ error(line, reason.c_str(), "=");
variable->getType().setQualifier(EvqTemporary);
- return true;
+ return false;
}
if (type != initializer->getType())
{
error(line, " non-matching types for const initializer ",
variable->getType().getQualifierString());
variable->getType().setQualifier(EvqTemporary);
- return true;
+ return false;
}
// Save the constant folded value to the variable if possible. For example array
@@ -1345,8 +1996,8 @@ bool TParseContext::executeInitializer(const TSourceLoc &line,
if (initializer->getAsConstantUnion())
{
variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
- *intermNode = nullptr;
- return false;
+ ASSERT(*initNode == nullptr);
+ return true;
}
else if (initializer->getAsSymbolNode())
{
@@ -1358,84 +2009,220 @@ bool TParseContext::executeInitializer(const TSourceLoc &line,
if (constArray)
{
variable->shareConstPointer(constArray);
- *intermNode = nullptr;
- return false;
+ ASSERT(*initNode == nullptr);
+ return true;
}
}
}
- TIntermSymbol *intermSymbol = intermediate.addSymbol(
- variable->getUniqueId(), variable->getName(), variable->getType(), line);
- *intermNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
- if (*intermNode == nullptr)
+ TIntermSymbol *intermSymbol =
+ new TIntermSymbol(variable->getUniqueId(), variable->getName(), variable->getType());
+ intermSymbol->setLine(line);
+ *initNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
+ if (*initNode == nullptr)
{
assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
- return true;
+ return false;
}
- return false;
+ return true;
+}
+
+TIntermNode *TParseContext::addConditionInitializer(const TPublicType &pType,
+ const TString &identifier,
+ TIntermTyped *initializer,
+ const TSourceLoc &loc)
+{
+ checkIsScalarBool(loc, pType);
+ TIntermBinary *initNode = nullptr;
+ TType type(pType);
+ if (executeInitializer(loc, identifier, type, initializer, &initNode))
+ {
+ // The initializer is valid. The init condition needs to have a node - either the
+ // initializer node, or a constant node in case the initialized variable is const and won't
+ // be recorded in the AST.
+ if (initNode == nullptr)
+ {
+ return initializer;
+ }
+ else
+ {
+ TIntermDeclaration *declaration = new TIntermDeclaration();
+ declaration->appendDeclarator(initNode);
+ return declaration;
+ }
+ }
+ return nullptr;
+}
+
+TIntermNode *TParseContext::addLoop(TLoopType type,
+ TIntermNode *init,
+ TIntermNode *cond,
+ TIntermTyped *expr,
+ TIntermNode *body,
+ const TSourceLoc &line)
+{
+ TIntermNode *node = nullptr;
+ TIntermTyped *typedCond = nullptr;
+ if (cond)
+ {
+ typedCond = cond->getAsTyped();
+ }
+ if (cond == nullptr || typedCond)
+ {
+ if (type == ELoopDoWhile)
+ {
+ checkIsScalarBool(line, typedCond);
+ }
+ // In the case of other loops, it was checked before that the condition is a scalar boolean.
+ ASSERT(mDiagnostics->numErrors() > 0 || typedCond == nullptr ||
+ (typedCond->getBasicType() == EbtBool && !typedCond->isArray() &&
+ !typedCond->isVector()));
+
+ node = new TIntermLoop(type, init, typedCond, expr, EnsureBlock(body));
+ node->setLine(line);
+ return node;
+ }
+
+ ASSERT(type != ELoopDoWhile);
+
+ TIntermDeclaration *declaration = cond->getAsDeclarationNode();
+ ASSERT(declaration);
+ TIntermBinary *declarator = declaration->getSequence()->front()->getAsBinaryNode();
+ ASSERT(declarator->getLeft()->getAsSymbolNode());
+
+ // The condition is a declaration. In the AST representation we don't support declarations as
+ // loop conditions. Wrap the loop to a block that declares the condition variable and contains
+ // the loop.
+ TIntermBlock *block = new TIntermBlock();
+
+ TIntermDeclaration *declareCondition = new TIntermDeclaration();
+ declareCondition->appendDeclarator(declarator->getLeft()->deepCopy());
+ block->appendStatement(declareCondition);
+
+ TIntermBinary *conditionInit = new TIntermBinary(EOpAssign, declarator->getLeft()->deepCopy(),
+ declarator->getRight()->deepCopy());
+ TIntermLoop *loop = new TIntermLoop(type, init, conditionInit, expr, EnsureBlock(body));
+ block->appendStatement(loop);
+ loop->setLine(line);
+ block->setLine(line);
+ return block;
+}
+
+TIntermNode *TParseContext::addIfElse(TIntermTyped *cond,
+ TIntermNodePair code,
+ const TSourceLoc &loc)
+{
+ bool isScalarBool = checkIsScalarBool(loc, cond);
+
+ // For compile time constant conditions, prune the code now.
+ if (isScalarBool && cond->getAsConstantUnion())
+ {
+ if (cond->getAsConstantUnion()->getBConst(0) == true)
+ {
+ return EnsureBlock(code.node1);
+ }
+ else
+ {
+ return EnsureBlock(code.node2);
+ }
+ }
+
+ TIntermIfElse *node = new TIntermIfElse(cond, EnsureBlock(code.node1), EnsureBlock(code.node2));
+ node->setLine(loc);
+
+ return node;
+}
+
+void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier)
+{
+ checkPrecisionSpecified(typeSpecifier->getLine(), typeSpecifier->precision,
+ typeSpecifier->getBasicType());
+
+ if (mShaderVersion < 300 && typeSpecifier->isArray())
+ {
+ error(typeSpecifier->getLine(), "not supported", "first-class array");
+ typeSpecifier->clearArrayness();
+ }
}
-TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier,
- bool invariant,
- TLayoutQualifier layoutQualifier,
+TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
const TPublicType &typeSpecifier)
{
+ TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
+
TPublicType returnType = typeSpecifier;
- returnType.qualifier = qualifier;
- returnType.invariant = invariant;
- returnType.layoutQualifier = layoutQualifier;
+ returnType.qualifier = typeQualifier.qualifier;
+ returnType.invariant = typeQualifier.invariant;
+ returnType.layoutQualifier = typeQualifier.layoutQualifier;
+ returnType.memoryQualifier = typeQualifier.memoryQualifier;
+ returnType.precision = typeSpecifier.precision;
+
+ if (typeQualifier.precision != EbpUndefined)
+ {
+ returnType.precision = typeQualifier.precision;
+ }
+
+ checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision,
+ typeSpecifier.getBasicType());
+
+ checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier,
+ typeSpecifier.getLine());
+
+ checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier);
if (mShaderVersion < 300)
{
- if (typeSpecifier.array)
+ if (typeSpecifier.isArray())
{
- error(typeSpecifier.line, "not supported", "first-class array");
- recover();
+ error(typeSpecifier.getLine(), "not supported", "first-class array");
returnType.clearArrayness();
}
- if (qualifier == EvqAttribute &&
- (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
+ if (returnType.qualifier == EvqAttribute &&
+ (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
{
- error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
- recover();
+ error(typeSpecifier.getLine(), "cannot be bool or int",
+ getQualifierString(returnType.qualifier));
}
- if ((qualifier == EvqVaryingIn || qualifier == EvqVaryingOut) &&
- (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
+ if ((returnType.qualifier == EvqVaryingIn || returnType.qualifier == EvqVaryingOut) &&
+ (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
{
- error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
- recover();
+ error(typeSpecifier.getLine(), "cannot be bool or int",
+ getQualifierString(returnType.qualifier));
}
}
else
{
- if (!layoutQualifier.isEmpty())
+ if (!returnType.layoutQualifier.isEmpty())
{
- if (globalErrorCheck(typeSpecifier.line, symbolTable.atGlobalLevel(), "layout"))
- {
- recover();
- }
+ checkIsAtGlobalLevel(typeSpecifier.getLine(), "layout");
}
- if (sh::IsVarying(qualifier) || qualifier == EvqVertexIn || qualifier == EvqFragmentOut)
+ if (sh::IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn ||
+ returnType.qualifier == EvqFragmentOut)
{
- es3InputOutputTypeCheck(qualifier, typeSpecifier, typeSpecifier.line);
+ checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier,
+ typeSpecifier.getLine());
+ }
+ if (returnType.qualifier == EvqComputeIn)
+ {
+ error(typeSpecifier.getLine(), "'in' can be only used to specify the local group size",
+ "in");
}
}
return returnType;
}
-void TParseContext::es3InputOutputTypeCheck(const TQualifier qualifier,
- const TPublicType &type,
- const TSourceLoc &qualifierLocation)
+void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
+ const TPublicType &type,
+ const TSourceLoc &qualifierLocation)
{
// An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
- if (type.type == EbtBool)
+ if (type.getBasicType() == EbtBool)
{
error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
- recover();
}
// Specific restrictions apply for vertex shader inputs and fragment shader outputs.
@@ -1443,21 +2230,19 @@ void TParseContext::es3InputOutputTypeCheck(const TQualifier qualifier,
{
case EvqVertexIn:
// ESSL 3.00 section 4.3.4
- if (type.array)
+ if (type.isArray())
{
error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
- recover();
}
- // Vertex inputs with a struct type are disallowed in singleDeclarationErrorCheck
+ // Vertex inputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
return;
case EvqFragmentOut:
// ESSL 3.00 section 4.3.6
- if (type.isMatrix())
+ if (type.typeSpecifierNonArray.isMatrix())
{
error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
- recover();
}
- // Fragment outputs with a struct type are disallowed in singleDeclarationErrorCheck
+ // Fragment outputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
return;
default:
break;
@@ -1466,506 +2251,997 @@ void TParseContext::es3InputOutputTypeCheck(const TQualifier qualifier,
// Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
// restrictions.
bool typeContainsIntegers =
- (type.type == EbtInt || type.type == EbtUInt || type.isStructureContainingType(EbtInt) ||
- type.isStructureContainingType(EbtUInt));
+ (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt ||
+ type.isStructureContainingType(EbtInt) || type.isStructureContainingType(EbtUInt));
if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut)
{
error(qualifierLocation, "must use 'flat' interpolation here",
getQualifierString(qualifier));
- recover();
}
- if (type.type == EbtStruct)
+ if (type.getBasicType() == EbtStruct)
{
// ESSL 3.00 sections 4.3.4 and 4.3.6.
// These restrictions are only implied by the ESSL 3.00 spec, but
// the ESSL 3.10 spec lists these restrictions explicitly.
- if (type.array)
+ if (type.isArray())
{
error(qualifierLocation, "cannot be an array of structures",
getQualifierString(qualifier));
- recover();
}
if (type.isStructureContainingArrays())
{
error(qualifierLocation, "cannot be a structure containing an array",
getQualifierString(qualifier));
- recover();
}
if (type.isStructureContainingType(EbtStruct))
{
error(qualifierLocation, "cannot be a structure containing a structure",
getQualifierString(qualifier));
- recover();
}
if (type.isStructureContainingType(EbtBool))
{
error(qualifierLocation, "cannot be a structure containing a bool",
getQualifierString(qualifier));
- recover();
}
}
}
-TIntermAggregate *TParseContext::parseSingleDeclaration(TPublicType &publicType,
- const TSourceLoc &identifierOrTypeLocation,
- const TString &identifier)
+void TParseContext::checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier)
{
- TIntermSymbol *symbol =
- intermediate.addSymbol(0, identifier, TType(publicType), identifierOrTypeLocation);
+ if (qualifier.getType() == QtStorage)
+ {
+ const TStorageQualifierWrapper &storageQualifier =
+ static_cast<const TStorageQualifierWrapper &>(qualifier);
+ if (!declaringFunction() && storageQualifier.getQualifier() != EvqConst &&
+ !symbolTable.atGlobalLevel())
+ {
+ error(storageQualifier.getLine(),
+ "Local variables can only use the const storage qualifier.",
+ storageQualifier.getQualifierString().c_str());
+ }
+ }
+}
- bool emptyDeclaration = (identifier == "");
+void TParseContext::checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier,
+ const TSourceLoc &location)
+{
+ const std::string reason(
+ "Only allowed with shader storage blocks, variables declared within shader storage blocks "
+ "and variables declared as image types.");
+ if (memoryQualifier.readonly)
+ {
+ error(location, reason.c_str(), "readonly");
+ }
+ if (memoryQualifier.writeonly)
+ {
+ error(location, reason.c_str(), "writeonly");
+ }
+ if (memoryQualifier.coherent)
+ {
+ error(location, reason.c_str(), "coherent");
+ }
+ if (memoryQualifier.restrictQualifier)
+ {
+ error(location, reason.c_str(), "restrict");
+ }
+ if (memoryQualifier.volatileQualifier)
+ {
+ error(location, reason.c_str(), "volatile");
+ }
+}
+
+// Make sure there is no offset overlapping, and store the newly assigned offset to "type" in
+// intermediate tree.
+void TParseContext::checkAtomicCounterOffsetDoesNotOverlap(bool forceAppend,
+ const TSourceLoc &loc,
+ TType *type)
+{
+ if (!IsAtomicCounter(type->getBasicType()))
+ {
+ return;
+ }
+
+ const size_t size = type->isArray() ? kAtomicCounterArrayStride * type->getArraySizeProduct()
+ : kAtomicCounterSize;
+ TLayoutQualifier layoutQualifier = type->getLayoutQualifier();
+ auto &bindingState = mAtomicCounterBindingStates[layoutQualifier.binding];
+ int offset;
+ if (layoutQualifier.offset == -1 || forceAppend)
+ {
+ offset = bindingState.appendSpan(size);
+ }
+ else
+ {
+ offset = bindingState.insertSpan(layoutQualifier.offset, size);
+ }
+ if (offset == -1)
+ {
+ error(loc, "Offset overlapping", "atomic counter");
+ return;
+ }
+ layoutQualifier.offset = offset;
+ type->setLayoutQualifier(layoutQualifier);
+}
+
+void TParseContext::checkGeometryShaderInputAndSetArraySize(const TSourceLoc &location,
+ const char *token,
+ TType *type)
+{
+ if (IsGeometryShaderInput(mShaderType, type->getQualifier()))
+ {
+ if (type->isArray() && type->getOutermostArraySize() == 0u)
+ {
+ // Set size for the unsized geometry shader inputs if they are declared after a valid
+ // input primitive declaration.
+ if (mGeometryShaderInputPrimitiveType != EptUndefined)
+ {
+ ASSERT(mGeometryShaderInputArraySize > 0u);
+ type->sizeOutermostUnsizedArray(mGeometryShaderInputArraySize);
+ }
+ else
+ {
+ // [GLSL ES 3.2 SPEC Chapter 4.4.1.2]
+ // An input can be declared without an array size if there is a previous layout
+ // which specifies the size.
+ error(location,
+ "Missing a valid input primitive declaration before declaring an unsized "
+ "array input",
+ token);
+ }
+ }
+ else if (type->isArray())
+ {
+ setGeometryShaderInputArraySize(type->getOutermostArraySize(), location);
+ }
+ else
+ {
+ error(location, "Geometry shader input variable must be declared as an array", token);
+ }
+ }
+}
+
+TIntermDeclaration *TParseContext::parseSingleDeclaration(
+ TPublicType &publicType,
+ const TSourceLoc &identifierOrTypeLocation,
+ const TString &identifier)
+{
+ TType type(publicType);
+ if ((mCompileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) &&
+ mDirectiveHandler.pragma().stdgl.invariantAll)
+ {
+ TQualifier qualifier = type.getQualifier();
+
+ // The directive handler has already taken care of rejecting invalid uses of this pragma
+ // (for example, in ESSL 3.00 fragment shaders), so at this point, flatten it into all
+ // affected variable declarations:
+ //
+ // 1. Built-in special variables which are inputs to the fragment shader. (These are handled
+ // elsewhere, in TranslatorGLSL.)
+ //
+ // 2. Outputs from vertex shaders in ESSL 1.00 and 3.00 (EvqVaryingOut and EvqVertexOut). It
+ // is actually less likely that there will be bugs in the handling of ESSL 3.00 shaders, but
+ // the way this is currently implemented we have to enable this compiler option before
+ // parsing the shader and determining the shading language version it uses. If this were
+ // implemented as a post-pass, the workaround could be more targeted.
+ //
+ // 3. Inputs in ESSL 1.00 fragment shaders (EvqVaryingIn). This is somewhat in violation of
+ // the specification, but there are desktop OpenGL drivers that expect that this is the
+ // behavior of the #pragma when specified in ESSL 1.00 fragment shaders.
+ if (qualifier == EvqVaryingOut || qualifier == EvqVertexOut || qualifier == EvqVaryingIn)
+ {
+ type.setInvariant(true);
+ }
+ }
- mDeferredSingleDeclarationErrorCheck = emptyDeclaration;
+ checkGeometryShaderInputAndSetArraySize(identifierOrTypeLocation, identifier.c_str(), &type);
+ declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
+ identifierOrTypeLocation);
+
+ bool emptyDeclaration = (identifier == "");
+ mDeferredNonEmptyDeclarationErrorCheck = emptyDeclaration;
+
+ TIntermSymbol *symbol = nullptr;
if (emptyDeclaration)
{
- if (publicType.isUnsizedArray())
+ emptyDeclarationErrorCheck(type, identifierOrTypeLocation);
+ // In most cases we don't need to create a symbol node for an empty declaration.
+ // But if the empty declaration is declaring a struct type, the symbol node will store that.
+ if (type.getBasicType() == EbtStruct)
{
- // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
- // error. It is assumed that this applies to empty declarations as well.
- error(identifierOrTypeLocation, "empty array declaration needs to specify a size",
- identifier.c_str());
+ symbol = new TIntermSymbol(symbolTable.getEmptySymbolId(), "", type);
+ }
+ else if (IsAtomicCounter(publicType.getBasicType()))
+ {
+ setAtomicCounterBindingDefaultOffset(publicType, identifierOrTypeLocation);
}
}
else
{
- if (singleDeclarationErrorCheck(publicType, identifierOrTypeLocation))
- recover();
+ nonEmptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
- if (nonInitErrorCheck(identifierOrTypeLocation, identifier, &publicType))
- recover();
+ checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, &type);
+
+ checkAtomicCounterOffsetDoesNotOverlap(false, identifierOrTypeLocation, &type);
TVariable *variable = nullptr;
- if (!declareVariable(identifierOrTypeLocation, identifier, TType(publicType), &variable))
- recover();
+ declareVariable(identifierOrTypeLocation, identifier, type, &variable);
- if (variable && symbol)
- symbol->setId(variable->getUniqueId());
+ if (variable)
+ {
+ symbol = new TIntermSymbol(variable->getUniqueId(), identifier, type);
+ }
}
- return intermediate.makeAggregate(symbol, identifierOrTypeLocation);
+ TIntermDeclaration *declaration = new TIntermDeclaration();
+ declaration->setLine(identifierOrTypeLocation);
+ if (symbol)
+ {
+ symbol->setLine(identifierOrTypeLocation);
+ declaration->appendDeclarator(symbol);
+ }
+ return declaration;
}
-TIntermAggregate *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType,
- const TSourceLoc &identifierLocation,
- const TString &identifier,
- const TSourceLoc &indexLocation,
- TIntermTyped *indexExpression)
+TIntermDeclaration *TParseContext::parseSingleArrayDeclaration(
+ TPublicType &elementType,
+ const TSourceLoc &identifierLocation,
+ const TString &identifier,
+ const TSourceLoc &indexLocation,
+ const TVector<unsigned int> &arraySizes)
{
- mDeferredSingleDeclarationErrorCheck = false;
+ mDeferredNonEmptyDeclarationErrorCheck = false;
- if (singleDeclarationErrorCheck(publicType, identifierLocation))
- recover();
+ declarationQualifierErrorCheck(elementType.qualifier, elementType.layoutQualifier,
+ identifierLocation);
- if (nonInitErrorCheck(identifierLocation, identifier, &publicType))
- recover();
+ nonEmptyDeclarationErrorCheck(elementType, identifierLocation);
- if (arrayTypeErrorCheck(indexLocation, publicType) ||
- arrayQualifierErrorCheck(indexLocation, publicType))
- {
- recover();
- }
+ checkIsValidTypeAndQualifierForArray(indexLocation, elementType);
- TType arrayType(publicType);
+ TType arrayType(elementType);
+ arrayType.makeArrays(arraySizes);
- int size;
- if (arraySizeErrorCheck(identifierLocation, indexExpression, size))
- {
- recover();
- }
- // Make the type an array even if size check failed.
- // This ensures useless error messages regarding the variable's non-arrayness won't follow.
- arrayType.setArraySize(size);
+ checkGeometryShaderInputAndSetArraySize(indexLocation, identifier.c_str(), &arrayType);
+
+ checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &arrayType);
+
+ checkAtomicCounterOffsetDoesNotOverlap(false, identifierLocation, &arrayType);
TVariable *variable = nullptr;
- if (!declareVariable(identifierLocation, identifier, arrayType, &variable))
- recover();
+ declareVariable(identifierLocation, identifier, arrayType, &variable);
- TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
- if (variable && symbol)
- symbol->setId(variable->getUniqueId());
+ TIntermDeclaration *declaration = new TIntermDeclaration();
+ declaration->setLine(identifierLocation);
- return intermediate.makeAggregate(symbol, identifierLocation);
+ if (variable)
+ {
+ TIntermSymbol *symbol = new TIntermSymbol(variable->getUniqueId(), identifier, arrayType);
+ symbol->setLine(identifierLocation);
+ declaration->appendDeclarator(symbol);
+ }
+
+ return declaration;
}
-TIntermAggregate *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
- const TSourceLoc &identifierLocation,
- const TString &identifier,
- const TSourceLoc &initLocation,
- TIntermTyped *initializer)
+TIntermDeclaration *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
+ const TSourceLoc &identifierLocation,
+ const TString &identifier,
+ const TSourceLoc &initLocation,
+ TIntermTyped *initializer)
{
- mDeferredSingleDeclarationErrorCheck = false;
+ mDeferredNonEmptyDeclarationErrorCheck = false;
- if (singleDeclarationErrorCheck(publicType, identifierLocation))
- recover();
+ declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
+ identifierLocation);
- TIntermNode *intermNode = nullptr;
- if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
- {
- //
- // Build intermediate representation
- //
- return intermNode ? intermediate.makeAggregate(intermNode, initLocation) : nullptr;
- }
- else
+ nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
+
+ TIntermDeclaration *declaration = new TIntermDeclaration();
+ declaration->setLine(identifierLocation);
+
+ TIntermBinary *initNode = nullptr;
+ TType type(publicType);
+ if (executeInitializer(identifierLocation, identifier, type, initializer, &initNode))
{
- recover();
- return nullptr;
+ if (initNode)
+ {
+ declaration->appendDeclarator(initNode);
+ }
}
+ return declaration;
}
-TIntermAggregate *TParseContext::parseSingleArrayInitDeclaration(
- TPublicType &publicType,
+TIntermDeclaration *TParseContext::parseSingleArrayInitDeclaration(
+ TPublicType &elementType,
const TSourceLoc &identifierLocation,
const TString &identifier,
const TSourceLoc &indexLocation,
- TIntermTyped *indexExpression,
+ const TVector<unsigned int> &arraySizes,
const TSourceLoc &initLocation,
TIntermTyped *initializer)
{
- mDeferredSingleDeclarationErrorCheck = false;
+ mDeferredNonEmptyDeclarationErrorCheck = false;
- if (singleDeclarationErrorCheck(publicType, identifierLocation))
- recover();
+ declarationQualifierErrorCheck(elementType.qualifier, elementType.layoutQualifier,
+ identifierLocation);
- if (arrayTypeErrorCheck(indexLocation, publicType) ||
- arrayQualifierErrorCheck(indexLocation, publicType))
- {
- recover();
- }
+ nonEmptyDeclarationErrorCheck(elementType, identifierLocation);
- TPublicType arrayType(publicType);
+ checkIsValidTypeAndQualifierForArray(indexLocation, elementType);
- int size = 0;
- // If indexExpression is nullptr, then the array will eventually get its size implicitly from
- // the initializer.
- if (indexExpression != nullptr &&
- arraySizeErrorCheck(identifierLocation, indexExpression, size))
- {
- recover();
- }
- // Make the type an array even if size check failed.
- // This ensures useless error messages regarding the variable's non-arrayness won't follow.
- arrayType.setArraySize(size);
+ TType arrayType(elementType);
+ arrayType.makeArrays(arraySizes);
+
+ TIntermDeclaration *declaration = new TIntermDeclaration();
+ declaration->setLine(identifierLocation);
// initNode will correspond to the whole of "type b[n] = initializer".
- TIntermNode *initNode = nullptr;
- if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
+ TIntermBinary *initNode = nullptr;
+ if (executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
{
- return initNode ? intermediate.makeAggregate(initNode, initLocation) : nullptr;
- }
- else
- {
- recover();
- return nullptr;
+ if (initNode)
+ {
+ declaration->appendDeclarator(initNode);
+ }
}
+
+ return declaration;
}
-TIntermAggregate *TParseContext::parseInvariantDeclaration(const TSourceLoc &invariantLoc,
- const TSourceLoc &identifierLoc,
- const TString *identifier,
- const TSymbol *symbol)
+TIntermInvariantDeclaration *TParseContext::parseInvariantDeclaration(
+ const TTypeQualifierBuilder &typeQualifierBuilder,
+ const TSourceLoc &identifierLoc,
+ const TString *identifier,
+ const TSymbol *symbol)
{
- // invariant declaration
- if (globalErrorCheck(invariantLoc, symbolTable.atGlobalLevel(), "invariant varying"))
+ TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
+
+ if (!typeQualifier.invariant)
{
- recover();
+ error(identifierLoc, "Expected invariant", identifier->c_str());
+ return nullptr;
+ }
+ if (!checkIsAtGlobalLevel(identifierLoc, "invariant varying"))
+ {
+ return nullptr;
}
-
if (!symbol)
{
error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
- recover();
return nullptr;
}
- else
+ if (!IsQualifierUnspecified(typeQualifier.qualifier))
{
- const TString kGlFrontFacing("gl_FrontFacing");
- if (*identifier == kGlFrontFacing)
- {
- error(identifierLoc, "identifier should not be declared as invariant",
- identifier->c_str());
- recover();
- return nullptr;
- }
- symbolTable.addInvariantVarying(std::string(identifier->c_str()));
- const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
- ASSERT(variable);
- const TType &type = variable->getType();
- TIntermSymbol *intermSymbol =
- intermediate.addSymbol(variable->getUniqueId(), *identifier, type, identifierLoc);
+ error(identifierLoc, "invariant declaration specifies qualifier",
+ getQualifierString(typeQualifier.qualifier));
+ }
+ if (typeQualifier.precision != EbpUndefined)
+ {
+ error(identifierLoc, "invariant declaration specifies precision",
+ getPrecisionString(typeQualifier.precision));
+ }
+ if (!typeQualifier.layoutQualifier.isEmpty())
+ {
+ error(identifierLoc, "invariant declaration specifies layout", "'layout'");
+ }
- TIntermAggregate *aggregate = intermediate.makeAggregate(intermSymbol, identifierLoc);
- aggregate->setOp(EOpInvariantDeclaration);
- return aggregate;
+ const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
+ if (!variable)
+ {
+ return nullptr;
}
+ const TType &type = variable->getType();
+
+ checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(),
+ typeQualifier.line);
+ checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
+
+ symbolTable.addInvariantVarying(std::string(identifier->c_str()));
+
+ TIntermSymbol *intermSymbol = new TIntermSymbol(variable->getUniqueId(), *identifier, type);
+ intermSymbol->setLine(identifierLoc);
+
+ return new TIntermInvariantDeclaration(intermSymbol, identifierLoc);
}
-TIntermAggregate *TParseContext::parseDeclarator(TPublicType &publicType,
- TIntermAggregate *aggregateDeclaration,
- const TSourceLoc &identifierLocation,
- const TString &identifier)
+void TParseContext::parseDeclarator(TPublicType &publicType,
+ const TSourceLoc &identifierLocation,
+ const TString &identifier,
+ TIntermDeclaration *declarationOut)
{
// If the declaration starting this declarator list was empty (example: int,), some checks were
// not performed.
- if (mDeferredSingleDeclarationErrorCheck)
+ if (mDeferredNonEmptyDeclarationErrorCheck)
{
- if (singleDeclarationErrorCheck(publicType, identifierLocation))
- recover();
- mDeferredSingleDeclarationErrorCheck = false;
+ nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
+ mDeferredNonEmptyDeclarationErrorCheck = false;
}
- if (locationDeclaratorListCheck(identifierLocation, publicType))
- recover();
-
- if (nonInitErrorCheck(identifierLocation, identifier, &publicType))
- recover();
+ checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
TVariable *variable = nullptr;
- if (!declareVariable(identifierLocation, identifier, TType(publicType), &variable))
- recover();
+ TType type(publicType);
- TIntermSymbol *symbol =
- intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation);
- if (variable && symbol)
- symbol->setId(variable->getUniqueId());
+ checkGeometryShaderInputAndSetArraySize(identifierLocation, identifier.c_str(), &type);
- return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
+ checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &type);
+
+ checkAtomicCounterOffsetDoesNotOverlap(true, identifierLocation, &type);
+
+ declareVariable(identifierLocation, identifier, type, &variable);
+
+ if (variable)
+ {
+ TIntermSymbol *symbol = new TIntermSymbol(variable->getUniqueId(), identifier, type);
+ symbol->setLine(identifierLocation);
+ declarationOut->appendDeclarator(symbol);
+ }
}
-TIntermAggregate *TParseContext::parseArrayDeclarator(TPublicType &publicType,
- TIntermAggregate *aggregateDeclaration,
- const TSourceLoc &identifierLocation,
- const TString &identifier,
- const TSourceLoc &arrayLocation,
- TIntermTyped *indexExpression)
+void TParseContext::parseArrayDeclarator(TPublicType &elementType,
+ const TSourceLoc &identifierLocation,
+ const TString &identifier,
+ const TSourceLoc &arrayLocation,
+ const TVector<unsigned int> &arraySizes,
+ TIntermDeclaration *declarationOut)
{
// If the declaration starting this declarator list was empty (example: int,), some checks were
// not performed.
- if (mDeferredSingleDeclarationErrorCheck)
+ if (mDeferredNonEmptyDeclarationErrorCheck)
{
- if (singleDeclarationErrorCheck(publicType, identifierLocation))
- recover();
- mDeferredSingleDeclarationErrorCheck = false;
+ nonEmptyDeclarationErrorCheck(elementType, identifierLocation);
+ mDeferredNonEmptyDeclarationErrorCheck = false;
}
- if (locationDeclaratorListCheck(identifierLocation, publicType))
- recover();
-
- if (nonInitErrorCheck(identifierLocation, identifier, &publicType))
- recover();
+ checkDeclaratorLocationIsNotSpecified(identifierLocation, elementType);
- if (arrayTypeErrorCheck(arrayLocation, publicType) ||
- arrayQualifierErrorCheck(arrayLocation, publicType))
- {
- recover();
- }
- else
+ if (checkIsValidTypeAndQualifierForArray(arrayLocation, elementType))
{
- TType arrayType = TType(publicType);
- int size;
- if (arraySizeErrorCheck(arrayLocation, indexExpression, size))
- {
- recover();
- }
- arrayType.setArraySize(size);
+ TType arrayType(elementType);
+ arrayType.makeArrays(arraySizes);
- TVariable *variable = nullptr;
- if (!declareVariable(identifierLocation, identifier, arrayType, &variable))
- recover();
+ checkGeometryShaderInputAndSetArraySize(identifierLocation, identifier.c_str(), &arrayType);
- TIntermSymbol *symbol =
- intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
- if (variable && symbol)
- symbol->setId(variable->getUniqueId());
+ checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &arrayType);
- return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
- }
+ checkAtomicCounterOffsetDoesNotOverlap(true, identifierLocation, &arrayType);
- return nullptr;
+ TVariable *variable = nullptr;
+ declareVariable(identifierLocation, identifier, arrayType, &variable);
+
+ if (variable)
+ {
+ TIntermSymbol *symbol =
+ new TIntermSymbol(variable->getUniqueId(), identifier, arrayType);
+ symbol->setLine(identifierLocation);
+ declarationOut->appendDeclarator(symbol);
+ }
+ }
}
-TIntermAggregate *TParseContext::parseInitDeclarator(const TPublicType &publicType,
- TIntermAggregate *aggregateDeclaration,
- const TSourceLoc &identifierLocation,
- const TString &identifier,
- const TSourceLoc &initLocation,
- TIntermTyped *initializer)
+void TParseContext::parseInitDeclarator(const TPublicType &publicType,
+ const TSourceLoc &identifierLocation,
+ const TString &identifier,
+ const TSourceLoc &initLocation,
+ TIntermTyped *initializer,
+ TIntermDeclaration *declarationOut)
{
// If the declaration starting this declarator list was empty (example: int,), some checks were
// not performed.
- if (mDeferredSingleDeclarationErrorCheck)
+ if (mDeferredNonEmptyDeclarationErrorCheck)
{
- if (singleDeclarationErrorCheck(publicType, identifierLocation))
- recover();
- mDeferredSingleDeclarationErrorCheck = false;
+ nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
+ mDeferredNonEmptyDeclarationErrorCheck = false;
}
- if (locationDeclaratorListCheck(identifierLocation, publicType))
- recover();
+ checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
- TIntermNode *intermNode = nullptr;
- if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
+ TIntermBinary *initNode = nullptr;
+ TType type(publicType);
+ if (executeInitializer(identifierLocation, identifier, type, initializer, &initNode))
{
//
// build the intermediate representation
//
- if (intermNode)
+ if (initNode)
{
- return intermediate.growAggregate(aggregateDeclaration, intermNode, initLocation);
+ declarationOut->appendDeclarator(initNode);
}
- else
+ }
+}
+
+void TParseContext::parseArrayInitDeclarator(const TPublicType &elementType,
+ const TSourceLoc &identifierLocation,
+ const TString &identifier,
+ const TSourceLoc &indexLocation,
+ const TVector<unsigned int> &arraySizes,
+ const TSourceLoc &initLocation,
+ TIntermTyped *initializer,
+ TIntermDeclaration *declarationOut)
+{
+ // If the declaration starting this declarator list was empty (example: int,), some checks were
+ // not performed.
+ if (mDeferredNonEmptyDeclarationErrorCheck)
+ {
+ nonEmptyDeclarationErrorCheck(elementType, identifierLocation);
+ mDeferredNonEmptyDeclarationErrorCheck = false;
+ }
+
+ checkDeclaratorLocationIsNotSpecified(identifierLocation, elementType);
+
+ checkIsValidTypeAndQualifierForArray(indexLocation, elementType);
+
+ TType arrayType(elementType);
+ arrayType.makeArrays(arraySizes);
+
+ // initNode will correspond to the whole of "b[n] = initializer".
+ TIntermBinary *initNode = nullptr;
+ if (executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
+ {
+ if (initNode)
{
- return aggregateDeclaration;
+ declarationOut->appendDeclarator(initNode);
}
}
- else
+}
+
+TIntermNode *TParseContext::addEmptyStatement(const TSourceLoc &location)
+{
+ // It's simpler to parse an empty statement as a constant expression rather than having a
+ // different type of node just for empty statements, that will be pruned from the AST anyway.
+ TIntermNode *node = CreateZeroNode(TType(EbtInt, EbpMedium));
+ node->setLine(location);
+ return node;
+}
+
+void TParseContext::setAtomicCounterBindingDefaultOffset(const TPublicType &publicType,
+ const TSourceLoc &location)
+{
+ const TLayoutQualifier &layoutQualifier = publicType.layoutQualifier;
+ checkAtomicCounterBindingIsValid(location, layoutQualifier.binding);
+ if (layoutQualifier.binding == -1 || layoutQualifier.offset == -1)
{
- recover();
- return nullptr;
+ error(location, "Requires both binding and offset", "layout");
+ return;
}
+ mAtomicCounterBindingStates[layoutQualifier.binding].setDefaultOffset(layoutQualifier.offset);
}
-TIntermAggregate *TParseContext::parseArrayInitDeclarator(const TPublicType &publicType,
- TIntermAggregate *aggregateDeclaration,
- const TSourceLoc &identifierLocation,
- const TString &identifier,
- const TSourceLoc &indexLocation,
- TIntermTyped *indexExpression,
- const TSourceLoc &initLocation,
- TIntermTyped *initializer)
+void TParseContext::parseDefaultPrecisionQualifier(const TPrecision precision,
+ const TPublicType &type,
+ const TSourceLoc &loc)
{
- // If the declaration starting this declarator list was empty (example: int,), some checks were
- // not performed.
- if (mDeferredSingleDeclarationErrorCheck)
+ if ((precision == EbpHigh) && (getShaderType() == GL_FRAGMENT_SHADER) &&
+ !getFragmentPrecisionHigh())
{
- if (singleDeclarationErrorCheck(publicType, identifierLocation))
- recover();
- mDeferredSingleDeclarationErrorCheck = false;
+ error(loc, "precision is not supported in fragment shader", "highp");
}
- if (locationDeclaratorListCheck(identifierLocation, publicType))
- recover();
+ if (!CanSetDefaultPrecisionOnType(type))
+ {
+ error(loc, "illegal type argument for default precision qualifier",
+ getBasicString(type.getBasicType()));
+ return;
+ }
+ symbolTable.setDefaultPrecision(type.getBasicType(), precision);
+}
- if (arrayTypeErrorCheck(indexLocation, publicType) ||
- arrayQualifierErrorCheck(indexLocation, publicType))
+bool TParseContext::checkPrimitiveTypeMatchesTypeQualifier(const TTypeQualifier &typeQualifier)
+{
+ switch (typeQualifier.layoutQualifier.primitiveType)
{
- recover();
+ case EptLines:
+ case EptLinesAdjacency:
+ case EptTriangles:
+ case EptTrianglesAdjacency:
+ return typeQualifier.qualifier == EvqGeometryIn;
+
+ case EptLineStrip:
+ case EptTriangleStrip:
+ return typeQualifier.qualifier == EvqGeometryOut;
+
+ case EptPoints:
+ return true;
+
+ default:
+ UNREACHABLE();
+ return false;
}
+}
- TPublicType arrayType(publicType);
+void TParseContext::setGeometryShaderInputArraySize(unsigned int inputArraySize,
+ const TSourceLoc &line)
+{
+ if (mGeometryShaderInputArraySize == 0u)
+ {
+ mGeometryShaderInputArraySize = inputArraySize;
+ }
+ else if (mGeometryShaderInputArraySize != inputArraySize)
+ {
+ error(line,
+ "Array size or input primitive declaration doesn't match the size of earlier sized "
+ "array inputs.",
+ "layout");
+ }
+}
+
+bool TParseContext::parseGeometryShaderInputLayoutQualifier(const TTypeQualifier &typeQualifier)
+{
+ ASSERT(typeQualifier.qualifier == EvqGeometryIn);
+
+ const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier;
- int size = 0;
- // If indexExpression is nullptr, then the array will eventually get its size implicitly from
- // the initializer.
- if (indexExpression != nullptr &&
- arraySizeErrorCheck(identifierLocation, indexExpression, size))
+ if (layoutQualifier.maxVertices != -1)
{
- recover();
+ error(typeQualifier.line,
+ "max_vertices can only be declared in 'out' layout in a geometry shader", "layout");
+ return false;
}
- // Make the type an array even if size check failed.
- // This ensures useless error messages regarding the variable's non-arrayness won't follow.
- arrayType.setArraySize(size);
- // initNode will correspond to the whole of "b[n] = initializer".
- TIntermNode *initNode = nullptr;
- if (!executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
+ // Set mGeometryInputPrimitiveType if exists
+ if (layoutQualifier.primitiveType != EptUndefined)
{
- if (initNode)
+ if (!checkPrimitiveTypeMatchesTypeQualifier(typeQualifier))
+ {
+ error(typeQualifier.line, "invalid primitive type for 'in' layout", "layout");
+ return false;
+ }
+
+ if (mGeometryShaderInputPrimitiveType == EptUndefined)
{
- return intermediate.growAggregate(aggregateDeclaration, initNode, initLocation);
+ mGeometryShaderInputPrimitiveType = layoutQualifier.primitiveType;
+ setGeometryShaderInputArraySize(
+ GetGeometryShaderInputArraySize(mGeometryShaderInputPrimitiveType),
+ typeQualifier.line);
}
- else
+ else if (mGeometryShaderInputPrimitiveType != layoutQualifier.primitiveType)
{
- return aggregateDeclaration;
+ error(typeQualifier.line, "primitive doesn't match earlier input primitive declaration",
+ "layout");
+ return false;
}
}
- else
+
+ // Set mGeometryInvocations if exists
+ if (layoutQualifier.invocations > 0)
{
- recover();
- return nullptr;
+ if (mGeometryShaderInvocations == 0)
+ {
+ mGeometryShaderInvocations = layoutQualifier.invocations;
+ }
+ else if (mGeometryShaderInvocations != layoutQualifier.invocations)
+ {
+ error(typeQualifier.line, "invocations contradicts to the earlier declaration",
+ "layout");
+ return false;
+ }
}
+
+ return true;
}
-void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier)
+bool TParseContext::parseGeometryShaderOutputLayoutQualifier(const TTypeQualifier &typeQualifier)
{
- if (typeQualifier.qualifier != EvqUniform)
+ ASSERT(typeQualifier.qualifier == EvqGeometryOut);
+
+ const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier;
+
+ if (layoutQualifier.invocations > 0)
{
- error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier),
- "global layout must be uniform");
- recover();
- return;
+ error(typeQualifier.line,
+ "invocations can only be declared in 'in' layout in a geometry shader", "layout");
+ return false;
}
+ // Set mGeometryOutputPrimitiveType if exists
+ if (layoutQualifier.primitiveType != EptUndefined)
+ {
+ if (!checkPrimitiveTypeMatchesTypeQualifier(typeQualifier))
+ {
+ error(typeQualifier.line, "invalid primitive type for 'out' layout", "layout");
+ return false;
+ }
+
+ if (mGeometryShaderOutputPrimitiveType == EptUndefined)
+ {
+ mGeometryShaderOutputPrimitiveType = layoutQualifier.primitiveType;
+ }
+ else if (mGeometryShaderOutputPrimitiveType != layoutQualifier.primitiveType)
+ {
+ error(typeQualifier.line,
+ "primitive doesn't match earlier output primitive declaration", "layout");
+ return false;
+ }
+ }
+
+ // Set mGeometryMaxVertices if exists
+ if (layoutQualifier.maxVertices > -1)
+ {
+ if (mGeometryShaderMaxVertices == -1)
+ {
+ mGeometryShaderMaxVertices = layoutQualifier.maxVertices;
+ }
+ else if (mGeometryShaderMaxVertices != layoutQualifier.maxVertices)
+ {
+ error(typeQualifier.line, "max_vertices contradicts to the earlier declaration",
+ "layout");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder)
+{
+ TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
- ASSERT(!layoutQualifier.isEmpty());
- if (mShaderVersion < 300)
+ checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier,
+ typeQualifier.line);
+
+ // It should never be the case, but some strange parser errors can send us here.
+ if (layoutQualifier.isEmpty())
{
- error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 only", "layout");
- recover();
+ error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
return;
}
- if (layoutLocationErrorCheck(typeQualifier.line, typeQualifier.layoutQualifier))
+ if (!layoutQualifier.isCombinationValid())
{
- recover();
+ error(typeQualifier.line, "invalid layout qualifier combination", "layout");
return;
}
- if (layoutQualifier.matrixPacking != EmpUnspecified)
+ checkBindingIsNotSpecified(typeQualifier.line, layoutQualifier.binding);
+
+ checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
+
+ checkInternalFormatIsNotSpecified(typeQualifier.line, layoutQualifier.imageInternalFormat);
+
+ checkYuvIsNotSpecified(typeQualifier.line, layoutQualifier.yuv);
+
+ checkOffsetIsNotSpecified(typeQualifier.line, layoutQualifier.offset);
+
+ checkStd430IsForShaderStorageBlock(typeQualifier.line, layoutQualifier.blockStorage,
+ typeQualifier.qualifier);
+
+ if (typeQualifier.qualifier == EvqComputeIn)
{
- mDefaultMatrixPacking = layoutQualifier.matrixPacking;
+ if (mComputeShaderLocalSizeDeclared &&
+ !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize))
+ {
+ error(typeQualifier.line, "Work group size does not match the previous declaration",
+ "layout");
+ return;
+ }
+
+ if (mShaderVersion < 310)
+ {
+ error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
+ return;
+ }
+
+ if (!layoutQualifier.localSize.isAnyValueSet())
+ {
+ error(typeQualifier.line, "No local work group size specified", "layout");
+ return;
+ }
+
+ const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>(
+ symbolTable.findBuiltIn("gl_MaxComputeWorkGroupSize", mShaderVersion));
+
+ const TConstantUnion *maxComputeWorkGroupSizeData =
+ maxComputeWorkGroupSize->getConstPointer();
+
+ for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i)
+ {
+ if (layoutQualifier.localSize[i] != -1)
+ {
+ mComputeShaderLocalSize[i] = layoutQualifier.localSize[i];
+ const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst();
+ if (mComputeShaderLocalSize[i] < 1 ||
+ mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue)
+ {
+ std::stringstream reasonStream;
+ reasonStream << "invalid value: Value must be at least 1 and no greater than "
+ << maxComputeWorkGroupSizeValue;
+ const std::string &reason = reasonStream.str();
+
+ error(typeQualifier.line, reason.c_str(), getWorkGroupSizeString(i));
+ return;
+ }
+ }
+ }
+
+ mComputeShaderLocalSizeDeclared = true;
}
+ else if (typeQualifier.qualifier == EvqGeometryIn)
+ {
+ if (mShaderVersion < 310)
+ {
+ error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
+ return;
+ }
- if (layoutQualifier.blockStorage != EbsUnspecified)
+ if (!parseGeometryShaderInputLayoutQualifier(typeQualifier))
+ {
+ return;
+ }
+ }
+ else if (typeQualifier.qualifier == EvqGeometryOut)
+ {
+ if (mShaderVersion < 310)
+ {
+ error(typeQualifier.line, "out type qualifier supported in GLSL ES 3.10 only",
+ "layout");
+ return;
+ }
+
+ if (!parseGeometryShaderOutputLayoutQualifier(typeQualifier))
+ {
+ return;
+ }
+ }
+ else if (isExtensionEnabled(TExtension::OVR_multiview) &&
+ typeQualifier.qualifier == EvqVertexIn)
+ {
+ // This error is only specified in WebGL, but tightens unspecified behavior in the native
+ // specification.
+ if (mNumViews != -1 && layoutQualifier.numViews != mNumViews)
+ {
+ error(typeQualifier.line, "Number of views does not match the previous declaration",
+ "layout");
+ return;
+ }
+
+ if (layoutQualifier.numViews == -1)
+ {
+ error(typeQualifier.line, "No num_views specified", "layout");
+ return;
+ }
+
+ if (layoutQualifier.numViews > mMaxNumViews)
+ {
+ error(typeQualifier.line, "num_views greater than the value of GL_MAX_VIEWS_OVR",
+ "layout");
+ return;
+ }
+
+ mNumViews = layoutQualifier.numViews;
+ }
+ else
{
- mDefaultBlockStorage = layoutQualifier.blockStorage;
+ if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, layoutQualifier))
+ {
+ return;
+ }
+
+ if (typeQualifier.qualifier != EvqUniform && typeQualifier.qualifier != EvqBuffer)
+ {
+ error(typeQualifier.line, "invalid qualifier: global layout can only be set for blocks",
+ getQualifierString(typeQualifier.qualifier));
+ return;
+ }
+
+ if (mShaderVersion < 300)
+ {
+ error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and above",
+ "layout");
+ return;
+ }
+
+ checkLocationIsNotSpecified(typeQualifier.line, layoutQualifier);
+
+ if (layoutQualifier.matrixPacking != EmpUnspecified)
+ {
+ if (typeQualifier.qualifier == EvqUniform)
+ {
+ mDefaultUniformMatrixPacking = layoutQualifier.matrixPacking;
+ }
+ else if (typeQualifier.qualifier == EvqBuffer)
+ {
+ mDefaultBufferMatrixPacking = layoutQualifier.matrixPacking;
+ }
+ }
+
+ if (layoutQualifier.blockStorage != EbsUnspecified)
+ {
+ if (typeQualifier.qualifier == EvqUniform)
+ {
+ mDefaultUniformBlockStorage = layoutQualifier.blockStorage;
+ }
+ else if (typeQualifier.qualifier == EvqBuffer)
+ {
+ mDefaultBufferBlockStorage = layoutQualifier.blockStorage;
+ }
+ }
}
}
-TIntermAggregate *TParseContext::addFunctionPrototypeDeclaration(const TFunction &function,
- const TSourceLoc &location)
+TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction(
+ const TFunction &function,
+ const TSourceLoc &location,
+ bool insertParametersToSymbolTable)
{
- // Note: symbolTableFunction could be the same as function if this is the first declaration.
- // Either way the instance in the symbol table is used to track whether the function is declared
- // multiple times.
- TFunction *symbolTableFunction =
- static_cast<TFunction *>(symbolTable.find(function.getMangledName(), getShaderVersion()));
- if (symbolTableFunction->hasPrototypeDeclaration() && mShaderVersion == 100)
- {
- // ESSL 1.00.17 section 4.2.7.
- // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
- error(location, "duplicate function prototype declarations are not allowed", "function");
- recover();
- }
- symbolTableFunction->setHasPrototypeDeclaration();
+ checkIsNotReserved(location, function.getName());
- TIntermAggregate *prototype = new TIntermAggregate;
- prototype->setType(function.getReturnType());
- prototype->setName(function.getMangledName());
- prototype->setFunctionId(function.getUniqueId());
+ TIntermFunctionPrototype *prototype =
+ new TIntermFunctionPrototype(function.getReturnType(), TSymbolUniqueId(function));
+ // TODO(oetuaho@nvidia.com): Instead of converting the function information here, the node could
+ // point to the data that already exists in the symbol table.
+ prototype->getFunctionSymbolInfo()->setFromFunction(function);
+ prototype->setLine(location);
for (size_t i = 0; i < function.getParamCount(); i++)
{
const TConstParameter &param = function.getParam(i);
- if (param.name != 0)
- {
- TVariable variable(param.name, *param.type);
- TIntermSymbol *paramSymbol = intermediate.addSymbol(
- variable.getUniqueId(), variable.getName(), variable.getType(), location);
- prototype = intermediate.growAggregate(prototype, paramSymbol, location);
+ TIntermSymbol *symbol = nullptr;
+
+ // If the parameter has no name, it's not an error, just don't add it to symbol table (could
+ // be used for unused args).
+ if (param.name != nullptr)
+ {
+ // Insert the parameter in the symbol table.
+ if (insertParametersToSymbolTable)
+ {
+ TVariable *variable = symbolTable.declareVariable(param.name, *param.type);
+ if (variable)
+ {
+ symbol = new TIntermSymbol(variable->getUniqueId(), variable->getName(),
+ variable->getType());
+ }
+ else
+ {
+ error(location, "redefinition", param.name->c_str());
+ }
+ }
+ // Unsized type of a named parameter should have already been checked and sanitized.
+ ASSERT(!param.type->isUnsizedArray());
}
else
{
- TIntermSymbol *paramSymbol = intermediate.addSymbol(0, "", *param.type, location);
- prototype = intermediate.growAggregate(prototype, paramSymbol, location);
+ if (param.type->isUnsizedArray())
+ {
+ error(location, "function parameter array must be sized at compile time", "[]");
+ // We don't need to size the arrays since the parameter is unnamed and hence
+ // inaccessible.
+ }
}
+ if (!symbol)
+ {
+ // The parameter had no name or declaring the symbol failed - either way, add a nameless
+ // symbol.
+ symbol = new TIntermSymbol(symbolTable.getEmptySymbolId(), "", *param.type);
+ }
+ symbol->setLine(location);
+ prototype->appendParameter(symbol);
+ }
+ return prototype;
+}
+
+TIntermFunctionPrototype *TParseContext::addFunctionPrototypeDeclaration(
+ const TFunction &parsedFunction,
+ const TSourceLoc &location)
+{
+ // Note: function found from the symbol table could be the same as parsedFunction if this is the
+ // first declaration. Either way the instance in the symbol table is used to track whether the
+ // function is declared multiple times.
+ TFunction *function = static_cast<TFunction *>(
+ symbolTable.find(parsedFunction.getMangledName(), getShaderVersion()));
+ if (function->hasPrototypeDeclaration() && mShaderVersion == 100)
+ {
+ // ESSL 1.00.17 section 4.2.7.
+ // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
+ error(location, "duplicate function prototype declarations are not allowed", "function");
}
+ function->setHasPrototypeDeclaration();
- prototype->setOp(EOpPrototype);
+ TIntermFunctionPrototype *prototype =
+ createPrototypeNodeFromFunction(*function, location, false);
symbolTable.pop();
@@ -1973,135 +3249,80 @@ TIntermAggregate *TParseContext::addFunctionPrototypeDeclaration(const TFunction
{
// ESSL 3.00.4 section 4.2.4.
error(location, "local function prototype declarations are not allowed", "function");
- recover();
}
return prototype;
}
-TIntermAggregate *TParseContext::addFunctionDefinition(const TFunction &function,
- TIntermAggregate *functionPrototype,
- TIntermAggregate *functionBody,
- const TSourceLoc &location)
+TIntermFunctionDefinition *TParseContext::addFunctionDefinition(
+ TIntermFunctionPrototype *functionPrototype,
+ TIntermBlock *functionBody,
+ const TSourceLoc &location)
{
- //?? Check that all paths return a value if return type != void ?
- // May be best done as post process phase on intermediate code
+ // Check that non-void functions have at least one return statement.
if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
{
- error(location, "function does not return a value:", "", function.getName().c_str());
- recover();
+ error(location, "function does not return a value:",
+ functionPrototype->getFunctionSymbolInfo()->getName().c_str());
}
- TIntermAggregate *aggregate =
- intermediate.growAggregate(functionPrototype, functionBody, location);
- intermediate.setAggregateOperator(aggregate, EOpFunction, location);
- aggregate->setName(function.getMangledName().c_str());
- aggregate->setType(function.getReturnType());
- aggregate->setFunctionId(function.getUniqueId());
+ if (functionBody == nullptr)
+ {
+ functionBody = new TIntermBlock();
+ functionBody->setLine(location);
+ }
+ TIntermFunctionDefinition *functionNode =
+ new TIntermFunctionDefinition(functionPrototype, functionBody);
+ functionNode->setLine(location);
symbolTable.pop();
- return aggregate;
+ return functionNode;
}
-void TParseContext::parseFunctionPrototype(const TSourceLoc &location,
- TFunction *function,
- TIntermAggregate **aggregateOut)
+void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location,
+ TFunction **function,
+ TIntermFunctionPrototype **prototypeOut)
{
+ ASSERT(function);
+ ASSERT(*function);
const TSymbol *builtIn =
- symbolTable.findBuiltIn(function->getMangledName(), getShaderVersion());
+ symbolTable.findBuiltIn((*function)->getMangledName(), getShaderVersion());
if (builtIn)
{
- error(location, "built-in functions cannot be redefined", function->getName().c_str());
- recover();
+ error(location, "built-in functions cannot be redefined", (*function)->getName().c_str());
}
-
- TFunction *prevDec =
- static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
- //
- // Note: 'prevDec' could be 'function' if this is the first time we've seen function
- // as it would have just been put in the symbol table. Otherwise, we're looking up
- // an earlier occurance.
- //
- if (prevDec->isDefined())
+ else
{
- // Then this function already has a body.
- error(location, "function already has a body", function->getName().c_str());
- recover();
- }
- prevDec->setDefined();
- //
- // Overload the unique ID of the definition to be the same unique ID as the declaration.
- // Eventually we will probably want to have only a single definition and just swap the
- // arguments to be the definition's arguments.
- //
- function->setUniqueId(prevDec->getUniqueId());
+ TFunction *prevDec = static_cast<TFunction *>(
+ symbolTable.find((*function)->getMangledName(), getShaderVersion()));
- // Raise error message if main function takes any parameters or return anything other than void
- if (function->getName() == "main")
- {
- if (function->getParamCount() > 0)
+ // Note: 'prevDec' could be 'function' if this is the first time we've seen function as it
+ // would have just been put in the symbol table. Otherwise, we're looking up an earlier
+ // occurance.
+ if (*function != prevDec)
{
- error(location, "function cannot take any parameter(s)", function->getName().c_str());
- recover();
+ // Swap the parameters of the previous declaration to the parameters of the function
+ // definition (parameter names may differ).
+ prevDec->swapParameters(**function);
+
+ // The function definition will share the same symbol as any previous declaration.
+ *function = prevDec;
}
- if (function->getReturnType().getBasicType() != EbtVoid)
+
+ if ((*function)->isDefined())
{
- error(location, "", function->getReturnType().getBasicString(),
- "main function cannot return a value");
- recover();
+ error(location, "function already has a body", (*function)->getName().c_str());
}
+
+ (*function)->setDefined();
}
- //
- // Remember the return type for later checking for RETURN statements.
- //
- mCurrentFunctionType = &(prevDec->getReturnType());
+ // Remember the return type for later checking for return statements.
+ mCurrentFunctionType = &((*function)->getReturnType());
mFunctionReturnsValue = false;
- //
- // Insert parameters into the symbol table.
- // If the parameter has no name, it's not an error, just don't insert it
- // (could be used for unused args).
- //
- // Also, accumulate the list of parameters into the HIL, so lower level code
- // knows where to find parameters.
- //
- TIntermAggregate *paramNodes = new TIntermAggregate;
- for (size_t i = 0; i < function->getParamCount(); i++)
- {
- const TConstParameter &param = function->getParam(i);
- if (param.name != 0)
- {
- TVariable *variable = new TVariable(param.name, *param.type);
- //
- // Insert the parameters with name in the symbol table.
- //
- if (!symbolTable.declare(variable))
- {
- error(location, "redefinition", variable->getName().c_str());
- recover();
- paramNodes = intermediate.growAggregate(
- paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
- continue;
- }
-
- //
- // Add the parameter to the HIL
- //
- TIntermSymbol *symbol = intermediate.addSymbol(
- variable->getUniqueId(), variable->getName(), variable->getType(), location);
-
- paramNodes = intermediate.growAggregate(paramNodes, symbol, location);
- }
- else
- {
- paramNodes = intermediate.growAggregate(
- paramNodes, intermediate.addSymbol(0, "", *param.type, location), location);
- }
- }
- intermediate.setAggregateOperator(paramNodes, EOpParameters, location);
- *aggregateOut = paramNodes;
+ *prototypeOut = createPrototypeNodeFromFunction(**function, location, true);
setLoopNestingLevel(0);
}
@@ -2117,22 +3338,42 @@ TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TF
//
TFunction *prevDec =
static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
- if (prevDec)
+
+ for (size_t i = 0u; i < function->getParamCount(); ++i)
+ {
+ auto &param = function->getParam(i);
+ if (param.type->isStructSpecifier())
+ {
+ // ESSL 3.00.6 section 12.10.
+ error(location, "Function parameter type cannot be a structure definition",
+ function->getName().c_str());
+ }
+ }
+
+ if (getShaderVersion() >= 300 &&
+ symbolTable.hasUnmangledBuiltInForShaderVersion(function->getName().c_str(),
+ getShaderVersion()))
+ {
+ // With ESSL 3.00 and above, names of built-in functions cannot be redeclared as functions.
+ // Therefore overloading or redefining builtin functions is an error.
+ error(location, "Name of a built-in function cannot be redeclared as function",
+ function->getName().c_str());
+ }
+ else if (prevDec)
{
if (prevDec->getReturnType() != function->getReturnType())
{
- error(location, "overloaded functions must have the same return type",
+ error(location, "function must have the same return type in all of its declarations",
function->getReturnType().getBasicString());
- recover();
}
for (size_t i = 0; i < prevDec->getParamCount(); ++i)
{
if (prevDec->getParam(i).type->getQualifier() !=
function->getParam(i).type->getQualifier())
{
- error(location, "overloaded functions must have the same parameter qualifiers",
+ error(location,
+ "function must have the same parameter qualifiers in all of its declarations",
function->getParam(i).type->getQualifierString());
- recover();
}
}
}
@@ -2145,22 +3386,33 @@ TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TF
{
if (!prevSym->isFunction())
{
- error(location, "redefinition", function->getName().c_str(), "function");
- recover();
+ error(location, "redefinition of a function", function->getName().c_str());
}
}
else
{
// Insert the unmangled name to detect potential future redefinition as a variable.
- TFunction *newFunction =
- new TFunction(NewPoolTString(function->getName().c_str()), &function->getReturnType());
- symbolTable.getOuterLevel()->insertUnmangled(newFunction);
+ symbolTable.getOuterLevel()->insertUnmangled(function);
}
// We're at the inner scope level of the function's arguments and body statement.
// Add the function prototype to the surrounding scope instead.
symbolTable.getOuterLevel()->insert(function);
+ // Raise error message if main function takes any parameters or return anything other than void
+ if (function->getName() == "main")
+ {
+ if (function->getParamCount() > 0)
+ {
+ error(location, "function cannot take any parameter(s)", "main");
+ }
+ if (function->getReturnType().getBasicType() != EbtVoid)
+ {
+ error(location, "main function cannot return a value",
+ function->getReturnType().getBasicString());
+ }
+ }
+
//
// If this is a redeclaration, it could also be a definition, in which case, we want to use the
// variable names from this one, and not the one that's
@@ -2169,420 +3421,302 @@ TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TF
return function;
}
-TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn)
+TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
+ const TString *name,
+ const TSourceLoc &location)
{
- TPublicType publicType = publicTypeIn;
- if (publicType.isStructSpecifier)
+ if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary)
{
- error(publicType.line, "constructor can't be a structure definition",
- getBasicString(publicType.type));
- recover();
+ error(location, "no qualifiers allowed for function return",
+ getQualifierString(type.qualifier));
}
-
- TOperator op = EOpNull;
- if (publicType.userDef)
+ if (!type.layoutQualifier.isEmpty())
{
- op = EOpConstructStruct;
+ error(location, "no qualifiers allowed for function return", "layout");
}
- else
+ // make sure an opaque type is not involved as well...
+ std::string reason(getBasicString(type.getBasicType()));
+ reason += "s can't be function return values";
+ checkIsNotOpaqueType(location, type.typeSpecifierNonArray, reason.c_str());
+ if (mShaderVersion < 300)
{
- switch (publicType.type)
- {
- case EbtFloat:
- if (publicType.isMatrix())
- {
- switch (publicType.getCols())
- {
- case 2:
- switch (publicType.getRows())
- {
- case 2:
- op = EOpConstructMat2;
- break;
- case 3:
- op = EOpConstructMat2x3;
- break;
- case 4:
- op = EOpConstructMat2x4;
- break;
- }
- break;
- case 3:
- switch (publicType.getRows())
- {
- case 2:
- op = EOpConstructMat3x2;
- break;
- case 3:
- op = EOpConstructMat3;
- break;
- case 4:
- op = EOpConstructMat3x4;
- break;
- }
- break;
- case 4:
- switch (publicType.getRows())
- {
- case 2:
- op = EOpConstructMat4x2;
- break;
- case 3:
- op = EOpConstructMat4x3;
- break;
- case 4:
- op = EOpConstructMat4;
- break;
- }
- break;
- }
- }
- else
- {
- switch (publicType.getNominalSize())
- {
- case 1:
- op = EOpConstructFloat;
- break;
- case 2:
- op = EOpConstructVec2;
- break;
- case 3:
- op = EOpConstructVec3;
- break;
- case 4:
- op = EOpConstructVec4;
- break;
- }
- }
- break;
-
- case EbtInt:
- switch (publicType.getNominalSize())
- {
- case 1:
- op = EOpConstructInt;
- break;
- case 2:
- op = EOpConstructIVec2;
- break;
- case 3:
- op = EOpConstructIVec3;
- break;
- case 4:
- op = EOpConstructIVec4;
- break;
- }
- break;
+ // Array return values are forbidden, but there's also no valid syntax for declaring array
+ // return values in ESSL 1.00.
+ ASSERT(!type.isArray() || mDiagnostics->numErrors() > 0);
- case EbtUInt:
- switch (publicType.getNominalSize())
- {
- case 1:
- op = EOpConstructUInt;
- break;
- case 2:
- op = EOpConstructUVec2;
- break;
- case 3:
- op = EOpConstructUVec3;
- break;
- case 4:
- op = EOpConstructUVec4;
- break;
- }
- break;
-
- case EbtBool:
- switch (publicType.getNominalSize())
- {
- case 1:
- op = EOpConstructBool;
- break;
- case 2:
- op = EOpConstructBVec2;
- break;
- case 3:
- op = EOpConstructBVec3;
- break;
- case 4:
- op = EOpConstructBVec4;
- break;
- }
- break;
-
- default:
- break;
- }
-
- if (op == EOpNull)
+ if (type.isStructureContainingArrays())
{
- error(publicType.line, "cannot construct this type", getBasicString(publicType.type));
- recover();
- publicType.type = EbtFloat;
- op = EOpConstructFloat;
+ // ESSL 1.00.17 section 6.1 Function Definitions
+ error(location, "structures containing arrays can't be function return values",
+ TType(type).getCompleteString().c_str());
}
}
- TString tempString;
- const TType *type = new TType(publicType);
- return new TFunction(&tempString, type, op);
+ // Add the function as a prototype after parsing it (we do not support recursion)
+ return new TFunction(&symbolTable, name, new TType(type));
}
-// This function is used to test for the correctness of the parameters passed to various constructor
-// functions and also convert them to the right datatype if it is allowed and required.
-//
-// Returns 0 for an error or the constructed node (aggregate or typed) for no error.
-//
-TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments,
- TType *type,
- TOperator op,
- TFunction *fnCall,
- const TSourceLoc &line)
+TFunction *TParseContext::addNonConstructorFunc(const TString *name, const TSourceLoc &loc)
{
- TIntermAggregate *constructor = arguments->getAsAggregate();
- ASSERT(constructor != nullptr);
+ const TType *returnType = TCache::getType(EbtVoid, EbpUndefined);
+ return new TFunction(&symbolTable, name, returnType);
+}
- if (type->isArray())
- {
- // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
- // the array.
- TIntermSequence *args = constructor->getSequence();
- for (size_t i = 0; i < args->size(); i++)
- {
- const TType &argType = (*args)[i]->getAsTyped()->getType();
- // It has already been checked that the argument is not an array.
- ASSERT(!argType.isArray());
- if (!argType.sameElementType(*type))
- {
- error(line, "Array constructor argument has an incorrect type", "Error");
- recover();
- return nullptr;
- }
- }
- }
- else if (op == EOpConstructStruct)
+TFunction *TParseContext::addConstructorFunc(const TPublicType &publicType)
+{
+ if (mShaderVersion < 300 && publicType.isArray())
{
- const TFieldList &fields = type->getStruct()->fields();
- TIntermSequence *args = constructor->getSequence();
-
- for (size_t i = 0; i < fields.size(); i++)
- {
- if (i >= args->size() || (*args)[i]->getAsTyped()->getType() != *fields[i]->type())
- {
- error(line, "Structure constructor arguments do not match structure fields",
- "Error");
- recover();
-
- return 0;
- }
- }
+ error(publicType.getLine(), "array constructor supported in GLSL ES 3.00 and above only",
+ "[]");
}
-
- // Turn the argument list itself into a constructor
- constructor->setOp(op);
- constructor->setLine(line);
- ASSERT(constructor->isConstructor());
-
- // Need to set type before setPrecisionFromChildren() because bool doesn't have precision.
- constructor->setType(*type);
-
- // Structs should not be precision qualified, the individual members may be.
- // Built-in types on the other hand should be precision qualified.
- if (op != EOpConstructStruct)
+ if (publicType.isStructSpecifier())
{
- constructor->setPrecisionFromChildren();
- type->setPrecision(constructor->getPrecision());
+ error(publicType.getLine(), "constructor can't be a structure definition",
+ getBasicString(publicType.getBasicType()));
}
- TIntermTyped *constConstructor = intermediate.foldAggregateBuiltIn(constructor);
- if (constConstructor)
+ TType *type = new TType(publicType);
+ if (!type->canBeConstructed())
{
- return constConstructor;
+ error(publicType.getLine(), "cannot construct this type",
+ getBasicString(publicType.getBasicType()));
+ type->setBasicType(EbtFloat);
}
- return constructor;
+ return new TFunction(&symbolTable, nullptr, type, EOpConstruct);
}
-//
-// This function returns the tree representation for the vector field(s) being accessed from contant
-// vector.
-// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a
-// contant node is returned, else an aggregate node is returned (for v.xy). The input to this
-// function could either be the symbol node or it could be the intermediate tree representation of
-// accessing fields in a constant structure or column of a constant matrix.
-//
-TIntermTyped *TParseContext::addConstVectorNode(TVectorFields &fields,
- TIntermConstantUnion *node,
- const TSourceLoc &line,
- bool outOfRangeIndexIsError)
+void TParseContext::checkIsNotUnsizedArray(const TSourceLoc &line,
+ const char *errorMessage,
+ const char *token,
+ TType *arrayType)
{
- const TConstantUnion *unionArray = node->getUnionArrayPointer();
- ASSERT(unionArray);
-
- TConstantUnion *constArray = new TConstantUnion[fields.num];
-
- for (int i = 0; i < fields.num; i++)
+ if (arrayType->isUnsizedArray())
{
- if (fields.offsets[i] >= node->getType().getNominalSize())
- {
- std::stringstream extraInfoStream;
- extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'";
- std::string extraInfo = extraInfoStream.str();
- outOfRangeError(outOfRangeIndexIsError, line, "", "[", extraInfo.c_str());
- fields.offsets[i] = node->getType().getNominalSize() - 1;
- }
-
- constArray[i] = unionArray[fields.offsets[i]];
+ error(line, errorMessage, token);
+ arrayType->sizeUnsizedArrays(nullptr);
}
- return intermediate.addConstantUnion(constArray, node->getType(), line);
}
-//
-// This function returns the column being accessed from a constant matrix. The values are retrieved
-// from the symbol table and parse-tree is built for a vector (each column of a matrix is a vector).
-// The input to the function could either be a symbol node (m[0] where m is a constant matrix)that
-// represents a constant matrix or it could be the tree representation of the constant matrix
-// (s.m1[0] where s is a constant structure)
-//
-TIntermTyped *TParseContext::addConstMatrixNode(int index,
- TIntermConstantUnion *node,
- const TSourceLoc &line,
- bool outOfRangeIndexIsError)
+TParameter TParseContext::parseParameterDeclarator(TType *type,
+ const TString *name,
+ const TSourceLoc &nameLoc)
{
- if (index >= node->getType().getCols())
+ ASSERT(type);
+ checkIsNotUnsizedArray(nameLoc, "function parameter array must specify a size", name->c_str(),
+ type);
+ if (type->getBasicType() == EbtVoid)
{
- std::stringstream extraInfoStream;
- extraInfoStream << "matrix field selection out of range '" << index << "'";
- std::string extraInfo = extraInfoStream.str();
- outOfRangeError(outOfRangeIndexIsError, line, "", "[", extraInfo.c_str());
- index = node->getType().getCols() - 1;
+ error(nameLoc, "illegal use of type 'void'", name->c_str());
}
+ checkIsNotReserved(nameLoc, *name);
+ TParameter param = {name, type};
+ return param;
+}
- const TConstantUnion *unionArray = node->getUnionArrayPointer();
- int size = node->getType().getCols();
- return intermediate.addConstantUnion(&unionArray[size * index], node->getType(), line);
+TParameter TParseContext::parseParameterDeclarator(const TPublicType &publicType,
+ const TString *name,
+ const TSourceLoc &nameLoc)
+{
+ TType *type = new TType(publicType);
+ return parseParameterDeclarator(type, name, nameLoc);
}
-//
-// This function returns an element of an array accessed from a constant array. The values are
-// retrieved from the symbol table and parse-tree is built for the type of the element. The input
-// to the function could either be a symbol node (a[0] where a is a constant array)that represents a
-// constant array or it could be the tree representation of the constant array (s.a1[0] where s is a
-// constant structure)
-//
-TIntermTyped *TParseContext::addConstArrayNode(int index,
- TIntermConstantUnion *node,
- const TSourceLoc &line,
- bool outOfRangeIndexIsError)
+TParameter TParseContext::parseParameterArrayDeclarator(const TString *name,
+ const TSourceLoc &nameLoc,
+ const TVector<unsigned int> &arraySizes,
+ const TSourceLoc &arrayLoc,
+ TPublicType *elementType)
{
- TType arrayElementType = node->getType();
- arrayElementType.clearArrayness();
+ checkArrayElementIsNotArray(arrayLoc, *elementType);
+ TType *arrayType = new TType(*elementType);
+ arrayType->makeArrays(arraySizes);
+ return parseParameterDeclarator(arrayType, name, nameLoc);
+}
- if (index >= node->getType().getArraySize())
+bool TParseContext::checkUnsizedArrayConstructorArgumentDimensionality(TIntermSequence *arguments,
+ TType type,
+ const TSourceLoc &line)
+{
+ if (arguments->empty())
+ {
+ error(line, "implicitly sized array constructor must have at least one argument", "[]");
+ return false;
+ }
+ for (TIntermNode *arg : *arguments)
{
- std::stringstream extraInfoStream;
- extraInfoStream << "array field selection out of range '" << index << "'";
- std::string extraInfo = extraInfoStream.str();
- outOfRangeError(outOfRangeIndexIsError, line, "", "[", extraInfo.c_str());
- index = node->getType().getArraySize() - 1;
+ TIntermTyped *element = arg->getAsTyped();
+ ASSERT(element);
+ size_t dimensionalityFromElement = element->getType().getNumArraySizes() + 1u;
+ if (dimensionalityFromElement > type.getNumArraySizes())
+ {
+ error(line, "constructing from a non-dereferenced array", "constructor");
+ return false;
+ }
+ else if (dimensionalityFromElement < type.getNumArraySizes())
+ {
+ if (dimensionalityFromElement == 1u)
+ {
+ error(line, "implicitly sized array of arrays constructor argument is not an array",
+ "constructor");
+ }
+ else
+ {
+ error(line,
+ "implicitly sized array of arrays constructor argument dimensionality is too "
+ "low",
+ "constructor");
+ }
+ return false;
+ }
}
- size_t arrayElementSize = arrayElementType.getObjectSize();
- const TConstantUnion *unionArray = node->getUnionArrayPointer();
- return intermediate.addConstantUnion(&unionArray[arrayElementSize * index], node->getType(),
- line);
+ return true;
}
+// This function is used to test for the correctness of the parameters passed to various constructor
+// functions and also convert them to the right datatype if it is allowed and required.
//
-// This function returns the value of a particular field inside a constant structure from the symbol
-// table.
-// If there is an embedded/nested struct, it appropriately calls addConstStructNested or
-// addConstStructFromAggr function and returns the parse-tree with the values of the embedded/nested
-// struct.
+// Returns a node to add to the tree regardless of if an error was generated or not.
//
-TIntermTyped *TParseContext::addConstStruct(const TString &identifier,
- TIntermTyped *node,
+TIntermTyped *TParseContext::addConstructor(TIntermSequence *arguments,
+ TType type,
const TSourceLoc &line)
{
- const TFieldList &fields = node->getType().getStruct()->fields();
- size_t instanceSize = 0;
-
- for (size_t index = 0; index < fields.size(); ++index)
+ if (type.isUnsizedArray())
{
- if (fields[index]->name() == identifier)
+ if (!checkUnsizedArrayConstructorArgumentDimensionality(arguments, type, line))
{
- break;
+ type.sizeUnsizedArrays(nullptr);
+ return CreateZeroNode(type);
}
- else
+ TIntermTyped *firstElement = arguments->at(0)->getAsTyped();
+ ASSERT(firstElement);
+ if (type.getOutermostArraySize() == 0u)
+ {
+ type.sizeOutermostUnsizedArray(static_cast<unsigned int>(arguments->size()));
+ }
+ for (size_t i = 0; i < firstElement->getType().getNumArraySizes(); ++i)
{
- instanceSize += fields[index]->type()->getObjectSize();
+ if ((*type.getArraySizes())[i] == 0u)
+ {
+ type.setArraySize(i, (*firstElement->getType().getArraySizes())[i]);
+ }
}
+ ASSERT(!type.isUnsizedArray());
}
- TIntermTyped *typedNode;
- TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
- if (tempConstantNode)
+ if (!checkConstructorArguments(line, arguments, type))
{
- const TConstantUnion *constArray = tempConstantNode->getUnionArrayPointer();
-
- // type will be changed in the calling function
- typedNode = intermediate.addConstantUnion(constArray + instanceSize,
- tempConstantNode->getType(), line);
+ return CreateZeroNode(type);
}
- else
- {
- error(line, "Cannot offset into the structure", "Error");
- recover();
- return 0;
- }
+ TIntermAggregate *constructorNode = TIntermAggregate::CreateConstructor(type, arguments);
+ constructorNode->setLine(line);
- return typedNode;
+ // TODO(oetuaho@nvidia.com): Add support for folding array constructors.
+ if (!constructorNode->isArray())
+ {
+ return constructorNode->fold(mDiagnostics);
+ }
+ return constructorNode;
}
//
// Interface/uniform blocks
+// TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks.
//
-TIntermAggregate *TParseContext::addInterfaceBlock(const TPublicType &typeQualifier,
- const TSourceLoc &nameLine,
- const TString &blockName,
- TFieldList *fieldList,
- const TString *instanceName,
- const TSourceLoc &instanceLine,
- TIntermTyped *arrayIndex,
- const TSourceLoc &arrayIndexLine)
+TIntermDeclaration *TParseContext::addInterfaceBlock(
+ const TTypeQualifierBuilder &typeQualifierBuilder,
+ const TSourceLoc &nameLine,
+ const TString &blockName,
+ TFieldList *fieldList,
+ const TString *instanceName,
+ const TSourceLoc &instanceLine,
+ TIntermTyped *arrayIndex,
+ const TSourceLoc &arrayIndexLine)
{
- if (reservedErrorCheck(nameLine, blockName))
- recover();
+ checkIsNotReserved(nameLine, blockName);
+
+ TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
+
+ if (mShaderVersion < 310 && typeQualifier.qualifier != EvqUniform)
+ {
+ error(typeQualifier.line,
+ "invalid qualifier: interface blocks must be uniform in version lower than GLSL ES "
+ "3.10",
+ getQualifierString(typeQualifier.qualifier));
+ }
+ else if (typeQualifier.qualifier != EvqUniform && typeQualifier.qualifier != EvqBuffer)
+ {
+ error(typeQualifier.line, "invalid qualifier: interface blocks must be uniform or buffer",
+ getQualifierString(typeQualifier.qualifier));
+ }
- if (typeQualifier.qualifier != EvqUniform)
+ if (typeQualifier.invariant)
{
- error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier),
- "interface blocks must be uniform");
- recover();
+ error(typeQualifier.line, "invalid qualifier on interface block member", "invariant");
}
- TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
- if (layoutLocationErrorCheck(typeQualifier.line, blockLayoutQualifier))
+ if (typeQualifier.qualifier != EvqBuffer)
+ {
+ checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
+ }
+
+ // add array index
+ unsigned int arraySize = 0;
+ if (arrayIndex != nullptr)
{
- recover();
+ arraySize = checkIsValidArraySize(arrayIndexLine, arrayIndex);
}
+ if (mShaderVersion < 310)
+ {
+ checkBindingIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.binding);
+ }
+ else
+ {
+ checkBlockBindingIsValid(typeQualifier.line, typeQualifier.qualifier,
+ typeQualifier.layoutQualifier.binding, arraySize);
+ }
+
+ checkYuvIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.yuv);
+
+ TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
+ checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
+ checkStd430IsForShaderStorageBlock(typeQualifier.line, blockLayoutQualifier.blockStorage,
+ typeQualifier.qualifier);
+
if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
{
- blockLayoutQualifier.matrixPacking = mDefaultMatrixPacking;
+ if (typeQualifier.qualifier == EvqUniform)
+ {
+ blockLayoutQualifier.matrixPacking = mDefaultUniformMatrixPacking;
+ }
+ else if (typeQualifier.qualifier == EvqBuffer)
+ {
+ blockLayoutQualifier.matrixPacking = mDefaultBufferMatrixPacking;
+ }
}
if (blockLayoutQualifier.blockStorage == EbsUnspecified)
{
- blockLayoutQualifier.blockStorage = mDefaultBlockStorage;
+ if (typeQualifier.qualifier == EvqUniform)
+ {
+ blockLayoutQualifier.blockStorage = mDefaultUniformBlockStorage;
+ }
+ else if (typeQualifier.qualifier == EvqBuffer)
+ {
+ blockLayoutQualifier.blockStorage = mDefaultBufferBlockStorage;
+ }
}
- TSymbol *blockNameSymbol = new TInterfaceBlockName(&blockName);
- if (!symbolTable.declare(blockNameSymbol))
+ checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier);
+
+ checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat);
+
+ if (!symbolTable.declareInterfaceBlockName(&blockName))
{
- error(nameLine, "redefinition", blockName.c_str(), "interface block name");
- recover();
+ error(nameLine, "redefinition of an interface block name", blockName.c_str());
}
// check for sampler types and apply layout qualifiers
@@ -2590,38 +3724,53 @@ TIntermAggregate *TParseContext::addInterfaceBlock(const TPublicType &typeQualif
{
TField *field = (*fieldList)[memberIndex];
TType *fieldType = field->type();
- if (IsSampler(fieldType->getBasicType()))
+ if (IsOpaqueType(fieldType->getBasicType()))
{
- error(field->line(), "unsupported type", fieldType->getBasicString(),
- "sampler types are not allowed in interface blocks");
- recover();
+ std::string reason("unsupported type - ");
+ reason += fieldType->getBasicString();
+ reason += " types are not allowed in interface blocks";
+ error(field->line(), reason.c_str(), fieldType->getBasicString());
}
const TQualifier qualifier = fieldType->getQualifier();
switch (qualifier)
{
case EvqGlobal:
+ break;
case EvqUniform:
+ if (typeQualifier.qualifier == EvqBuffer)
+ {
+ error(field->line(), "invalid qualifier on shader storage block member",
+ getQualifierString(qualifier));
+ }
+ break;
+ case EvqBuffer:
+ if (typeQualifier.qualifier == EvqUniform)
+ {
+ error(field->line(), "invalid qualifier on uniform block member",
+ getQualifierString(qualifier));
+ }
break;
default:
error(field->line(), "invalid qualifier on interface block member",
getQualifierString(qualifier));
- recover();
break;
}
- // check layout qualifiers
- TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
- if (layoutLocationErrorCheck(field->line(), fieldLayoutQualifier))
+ if (fieldType->isInvariant())
{
- recover();
+ error(field->line(), "invalid qualifier on interface block member", "invariant");
}
+ // check layout qualifiers
+ TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
+ checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier);
+ checkBindingIsNotSpecified(field->line(), fieldLayoutQualifier.binding);
+
if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
{
- error(field->line(), "invalid layout qualifier:",
- getBlockStorageString(fieldLayoutQualifier.blockStorage), "cannot be used here");
- recover();
+ error(field->line(), "invalid layout qualifier: cannot be used here",
+ getBlockStorageString(fieldLayoutQualifier.blockStorage));
}
if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
@@ -2630,29 +3779,51 @@ TIntermAggregate *TParseContext::addInterfaceBlock(const TPublicType &typeQualif
}
else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct)
{
- warning(field->line(), "extraneous layout qualifier:",
- getMatrixPackingString(fieldLayoutQualifier.matrixPacking),
- "only has an effect on matrix types");
+ warning(field->line(),
+ "extraneous layout qualifier: only has an effect on matrix types",
+ getMatrixPackingString(fieldLayoutQualifier.matrixPacking));
}
fieldType->setLayoutQualifier(fieldLayoutQualifier);
- }
- // add array index
- int arraySize = 0;
- if (arrayIndex != NULL)
- {
- if (arraySizeErrorCheck(arrayIndexLine, arrayIndex, arraySize))
- recover();
+ if (mShaderVersion < 310 || memberIndex != fieldList->size() - 1u ||
+ typeQualifier.qualifier != EvqBuffer)
+ {
+ // ESSL 3.10 spec section 4.1.9 allows for runtime-sized arrays.
+ checkIsNotUnsizedArray(field->line(),
+ "array members of interface blocks must specify a size",
+ field->name().c_str(), field->type());
+ }
+
+ if (typeQualifier.qualifier == EvqBuffer)
+ {
+ // set memory qualifiers
+ // GLSL ES 3.10 session 4.9 [Memory Access Qualifiers]. When a block declaration is
+ // qualified with a memory qualifier, it is as if all of its members were declared with
+ // the same memory qualifier.
+ const TMemoryQualifier &blockMemoryQualifier = typeQualifier.memoryQualifier;
+ TMemoryQualifier fieldMemoryQualifier = fieldType->getMemoryQualifier();
+ fieldMemoryQualifier.readonly |= blockMemoryQualifier.readonly;
+ fieldMemoryQualifier.writeonly |= blockMemoryQualifier.writeonly;
+ fieldMemoryQualifier.coherent |= blockMemoryQualifier.coherent;
+ fieldMemoryQualifier.restrictQualifier |= blockMemoryQualifier.restrictQualifier;
+ fieldMemoryQualifier.volatileQualifier |= blockMemoryQualifier.volatileQualifier;
+ // TODO(jiajia.qin@intel.com): Decide whether if readonly and writeonly buffer variable
+ // is legal. See bug https://github.com/KhronosGroup/OpenGL-API/issues/7
+ fieldType->setMemoryQualifier(fieldMemoryQualifier);
+ }
}
TInterfaceBlock *interfaceBlock =
- new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
- TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier,
- arraySize);
+ new TInterfaceBlock(&blockName, fieldList, instanceName, blockLayoutQualifier);
+ TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier);
+ if (arrayIndex != nullptr)
+ {
+ interfaceBlockType.makeArray(arraySize);
+ }
TString symbolName = "";
- int symbolId = 0;
+ const TSymbolUniqueId *symbolId = nullptr;
if (!instanceName)
{
@@ -2665,60 +3836,64 @@ TIntermAggregate *TParseContext::addInterfaceBlock(const TPublicType &typeQualif
// set parent pointer of the field variable
fieldType->setInterfaceBlock(interfaceBlock);
- TVariable *fieldVariable = new TVariable(&field->name(), *fieldType);
- fieldVariable->setQualifier(typeQualifier.qualifier);
+ TVariable *fieldVariable = symbolTable.declareVariable(&field->name(), *fieldType);
- if (!symbolTable.declare(fieldVariable))
+ if (fieldVariable)
{
- error(field->line(), "redefinition", field->name().c_str(),
- "interface block member name");
- recover();
+ fieldVariable->setQualifier(typeQualifier.qualifier);
+ }
+ else
+ {
+ error(field->line(), "redefinition of an interface block member name",
+ field->name().c_str());
}
}
+ symbolId = &symbolTable.getEmptySymbolId();
}
else
{
- if (reservedErrorCheck(instanceLine, *instanceName))
- recover();
+ checkIsNotReserved(instanceLine, *instanceName);
// add a symbol for this interface block
- TVariable *instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
- instanceTypeDef->setQualifier(typeQualifier.qualifier);
-
- if (!symbolTable.declare(instanceTypeDef))
+ TVariable *instanceTypeDef = symbolTable.declareVariable(instanceName, interfaceBlockType);
+ if (instanceTypeDef)
{
- error(instanceLine, "redefinition", instanceName->c_str(),
- "interface block instance name");
- recover();
+ instanceTypeDef->setQualifier(typeQualifier.qualifier);
+ symbolId = &instanceTypeDef->getUniqueId();
}
-
- symbolId = instanceTypeDef->getUniqueId();
- symbolName = instanceTypeDef->getName();
+ else
+ {
+ error(instanceLine, "redefinition of an interface block instance name",
+ instanceName->c_str());
+ }
+ symbolName = *instanceName;
}
- TIntermAggregate *aggregate = intermediate.makeAggregate(
- intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line),
- nameLine);
- aggregate->setOp(EOpDeclaration);
+ TIntermDeclaration *declaration = nullptr;
+
+ if (symbolId)
+ {
+ TIntermSymbol *blockSymbol = new TIntermSymbol(*symbolId, symbolName, interfaceBlockType);
+ blockSymbol->setLine(typeQualifier.line);
+ declaration = new TIntermDeclaration();
+ declaration->appendDeclarator(blockSymbol);
+ declaration->setLine(nameLine);
+ }
exitStructDeclaration();
- return aggregate;
+ return declaration;
}
-bool TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier)
+void TParseContext::enterStructDeclaration(const TSourceLoc &line, const TString &identifier)
{
++mStructNestingLevel;
// Embedded structure definitions are not supported per GLSL ES spec.
- // They aren't allowed in GLSL either, but we need to detect this here
- // so we don't rely on the GLSL compiler to catch it.
+ // ESSL 1.00.17 section 10.9. ESSL 3.00.6 section 12.11.
if (mStructNestingLevel > 1)
{
- error(line, "", "Embedded struct definitions are not allowed");
- return true;
+ error(line, "Embedded struct definitions are not allowed", "struct");
}
-
- return false;
}
void TParseContext::exitStructDeclaration()
@@ -2726,22 +3901,16 @@ void TParseContext::exitStructDeclaration()
--mStructNestingLevel;
}
-namespace
-{
-const int kWebGLMaxStructNesting = 4;
-
-} // namespace
-
-bool TParseContext::structNestingErrorCheck(const TSourceLoc &line, const TField &field)
+void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field)
{
- if (!IsWebGLBasedSpec(mShaderSpec))
+ if (!sh::IsWebGLBasedSpec(mShaderSpec))
{
- return false;
+ return;
}
if (field.type()->getBasicType() != EbtStruct)
{
- return false;
+ return;
}
// We're already inside a structure definition at this point, so add
@@ -2752,11 +3921,9 @@ bool TParseContext::structNestingErrorCheck(const TSourceLoc &line, const TField
reasonStream << "Reference of struct type " << field.type()->getStruct()->name().c_str()
<< " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
std::string reason = reasonStream.str();
- error(line, reason.c_str(), field.name().c_str(), "");
- return true;
+ error(line, reason.c_str(), field.name().c_str());
+ return;
}
-
- return false;
}
//
@@ -2766,8 +3933,6 @@ TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
const TSourceLoc &location,
TIntermTyped *indexExpression)
{
- TIntermTyped *indexedExpression = NULL;
-
if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
{
if (baseExpression->getAsSymbolNode())
@@ -2779,7 +3944,18 @@ TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
{
error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
}
- recover();
+
+ return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
+ }
+
+ if (baseExpression->getQualifier() == EvqPerVertexIn)
+ {
+ ASSERT(mShaderType == GL_GEOMETRY_SHADER_OES);
+ if (mGeometryShaderInputPrimitiveType == EptUndefined)
+ {
+ error(location, "missing input primitive declaration before indexing gl_in.", "[");
+ return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
+ }
}
TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
@@ -2792,174 +3968,139 @@ TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
{
if (baseExpression->isInterfaceBlock())
{
- error(
- location, "", "[",
- "array indexes for interface blocks arrays must be constant integral expressions");
- recover();
+ // TODO(jiawei.shao@intel.com): implement GL_OES_shader_io_blocks.
+ switch (baseExpression->getQualifier())
+ {
+ case EvqPerVertexIn:
+ break;
+ case EvqUniform:
+ case EvqBuffer:
+ error(location,
+ "array indexes for uniform block arrays and shader storage block arrays "
+ "must be constant integral expressions",
+ "[");
+ break;
+ default:
+ // We can reach here only in error cases.
+ ASSERT(mDiagnostics->numErrors() > 0);
+ break;
+ }
}
else if (baseExpression->getQualifier() == EvqFragmentOut)
{
- error(location, "", "[",
- "array indexes for fragment outputs must be constant integral expressions");
- recover();
+ error(location,
+ "array indexes for fragment outputs must be constant integral expressions", "[");
}
else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
{
- error(location, "", "[", "array index for gl_FragData must be constant zero");
- recover();
+ error(location, "array index for gl_FragData must be constant zero", "[");
}
}
if (indexConstantUnion)
{
- // If the index is not qualified as constant, the behavior in the spec is undefined. This
- // applies even if ANGLE has been able to constant fold it (ANGLE may constant fold
- // expressions that are not constant expressions). The most compatible way to handle this
- // case is to report a warning instead of an error and force the index to be in the
- // correct range.
+ // If an out-of-range index is not qualified as constant, the behavior in the spec is
+ // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may
+ // constant fold expressions that are not constant expressions). The most compatible way to
+ // handle this case is to report a warning instead of an error and force the index to be in
+ // the correct range.
bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
- int index = indexConstantUnion->getIConst(0);
- if (index < 0)
+ int index = 0;
+ if (indexConstantUnion->getBasicType() == EbtInt)
{
- std::stringstream infoStream;
- infoStream << index;
- std::string info = infoStream.str();
- outOfRangeError(outOfRangeIndexIsError, location, "negative index", info.c_str());
- index = 0;
+ index = indexConstantUnion->getIConst(0);
}
- TIntermConstantUnion *baseConstantUnion = baseExpression->getAsConstantUnion();
- if (baseConstantUnion)
+ else if (indexConstantUnion->getBasicType() == EbtUInt)
{
- if (baseExpression->isArray())
- {
- // constant folding for array indexing
- indexedExpression =
- addConstArrayNode(index, baseConstantUnion, location, outOfRangeIndexIsError);
- }
- else if (baseExpression->isVector())
- {
- // constant folding for vector indexing
- TVectorFields fields;
- fields.num = 1;
- fields.offsets[0] =
- index; // need to do it this way because v.xy sends fields integer array
- indexedExpression =
- addConstVectorNode(fields, baseConstantUnion, location, outOfRangeIndexIsError);
- }
- else if (baseExpression->isMatrix())
- {
- // constant folding for matrix indexing
- indexedExpression =
- addConstMatrixNode(index, baseConstantUnion, location, outOfRangeIndexIsError);
- }
+ index = static_cast<int>(indexConstantUnion->getUConst(0));
}
- else
+
+ int safeIndex = -1;
+
+ if (index < 0)
{
- int safeIndex = -1;
+ outOfRangeError(outOfRangeIndexIsError, location, "index expression is negative", "[]");
+ safeIndex = 0;
+ }
+ if (!baseExpression->getType().isUnsizedArray())
+ {
if (baseExpression->isArray())
{
if (baseExpression->getQualifier() == EvqFragData && index > 0)
{
- if (mShaderSpec == SH_WEBGL2_SPEC)
+ if (!isExtensionEnabled(TExtension::EXT_draw_buffers))
{
- // Error has been already generated if index is not const.
- if (indexExpression->getQualifier() == EvqConst)
- {
- error(location, "", "[",
- "array index for gl_FragData must be constant zero");
- recover();
- }
- safeIndex = 0;
- }
- else if (!isExtensionEnabled("GL_EXT_draw_buffers"))
- {
- outOfRangeError(outOfRangeIndexIsError, location, "", "[",
+ outOfRangeError(outOfRangeIndexIsError, location,
"array index for gl_FragData must be zero when "
- "GL_EXT_draw_buffers is disabled");
+ "GL_EXT_draw_buffers is disabled",
+ "[]");
safeIndex = 0;
}
}
// Only do generic out-of-range check if similar error hasn't already been reported.
- if (safeIndex < 0 && index >= baseExpression->getType().getArraySize())
+ if (safeIndex < 0)
{
- std::stringstream extraInfoStream;
- extraInfoStream << "array index out of range '" << index << "'";
- std::string extraInfo = extraInfoStream.str();
- outOfRangeError(outOfRangeIndexIsError, location, "", "[", extraInfo.c_str());
- safeIndex = baseExpression->getType().getArraySize() - 1;
+ safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index,
+ baseExpression->getOutermostArraySize(),
+ "array index out of range");
}
}
- else if ((baseExpression->isVector() || baseExpression->isMatrix()) &&
- baseExpression->getType().getNominalSize() <= index)
+ else if (baseExpression->isMatrix())
+ {
+ safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index,
+ baseExpression->getType().getCols(),
+ "matrix field selection out of range");
+ }
+ else if (baseExpression->isVector())
{
- std::stringstream extraInfoStream;
- extraInfoStream << "field selection out of range '" << index << "'";
- std::string extraInfo = extraInfoStream.str();
- outOfRangeError(outOfRangeIndexIsError, location, "", "[", extraInfo.c_str());
- safeIndex = baseExpression->getType().getNominalSize() - 1;
+ safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index,
+ baseExpression->getType().getNominalSize(),
+ "vector field selection out of range");
}
+ ASSERT(safeIndex >= 0);
// Data of constant unions can't be changed, because it may be shared with other
// constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
// sanitized object.
- if (safeIndex != -1)
+ if (safeIndex != index || indexConstantUnion->getBasicType() != EbtInt)
{
TConstantUnion *safeConstantUnion = new TConstantUnion();
safeConstantUnion->setIConst(safeIndex);
indexConstantUnion->replaceConstantUnion(safeConstantUnion);
+ indexConstantUnion->getTypePointer()->setBasicType(EbtInt);
}
- indexedExpression =
- intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
+ TIntermBinary *node =
+ new TIntermBinary(EOpIndexDirect, baseExpression, indexExpression);
+ node->setLine(location);
+ return node->fold(mDiagnostics);
}
}
- else
- {
- indexedExpression =
- intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
- }
- if (indexedExpression == 0)
- {
- TConstantUnion *unionArray = new TConstantUnion[1];
- unionArray->setFConst(0.0f);
- indexedExpression =
- intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location);
- }
- else if (baseExpression->isArray())
- {
- TType indexedType = baseExpression->getType();
- indexedType.clearArrayness();
- indexedExpression->setType(indexedType);
- }
- else if (baseExpression->isMatrix())
- {
- indexedExpression->setType(TType(baseExpression->getBasicType(),
- baseExpression->getPrecision(), EvqTemporary,
- static_cast<unsigned char>(baseExpression->getRows())));
- }
- else if (baseExpression->isVector())
- {
- indexedExpression->setType(
- TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary));
- }
- else
- {
- indexedExpression->setType(baseExpression->getType());
- }
+ TIntermBinary *node = new TIntermBinary(EOpIndexIndirect, baseExpression, indexExpression);
+ node->setLine(location);
+ // Indirect indexing can never be constant folded.
+ return node;
+}
- if (baseExpression->getType().getQualifier() == EvqConst &&
- indexExpression->getType().getQualifier() == EvqConst)
- {
- indexedExpression->getTypePointer()->setQualifier(EvqConst);
- }
- else
+int TParseContext::checkIndexLessThan(bool outOfRangeIndexIsError,
+ const TSourceLoc &location,
+ int index,
+ int arraySize,
+ const char *reason)
+{
+ // Should not reach here with an unsized / runtime-sized array.
+ ASSERT(arraySize > 0);
+ if (index >= arraySize)
{
- indexedExpression->getTypePointer()->setQualifier(EvqTemporary);
+ std::stringstream reasonStream;
+ reasonStream << reason << " '" << index << "'";
+ std::string token = reasonStream.str();
+ outOfRangeError(outOfRangeIndexIsError, location, reason, "[]");
+ return arraySize - 1;
}
-
- return indexedExpression;
+ return index;
}
TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
@@ -2967,62 +4108,37 @@ TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre
const TString &fieldString,
const TSourceLoc &fieldLocation)
{
- TIntermTyped *indexedExpression = NULL;
-
if (baseExpression->isArray())
{
error(fieldLocation, "cannot apply dot operator to an array", ".");
- recover();
+ return baseExpression;
}
if (baseExpression->isVector())
{
- TVectorFields fields;
- if (!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields,
- fieldLocation))
+ TVector<int> fieldOffsets;
+ if (!parseVectorFields(fieldLocation, fieldString, baseExpression->getNominalSize(),
+ &fieldOffsets))
{
- fields.num = 1;
- fields.offsets[0] = 0;
- recover();
+ fieldOffsets.resize(1);
+ fieldOffsets[0] = 0;
}
+ TIntermSwizzle *node = new TIntermSwizzle(baseExpression, fieldOffsets);
+ node->setLine(dotLocation);
- if (baseExpression->getAsConstantUnion())
- {
- // constant folding for vector fields
- indexedExpression = addConstVectorNode(fields, baseExpression->getAsConstantUnion(),
- fieldLocation, true);
- }
- else
- {
- TIntermTyped *index = intermediate.addSwizzle(fields, fieldLocation);
- indexedExpression =
- intermediate.addIndex(EOpVectorSwizzle, baseExpression, index, dotLocation);
- }
- if (indexedExpression == nullptr)
- {
- recover();
- indexedExpression = baseExpression;
- }
- else
- {
- // Note that the qualifier set here will be corrected later.
- indexedExpression->setType(TType(baseExpression->getBasicType(),
- baseExpression->getPrecision(), EvqTemporary,
- (unsigned char)(fieldString).size()));
- }
+ return node->fold();
}
else if (baseExpression->getBasicType() == EbtStruct)
{
- bool fieldFound = false;
const TFieldList &fields = baseExpression->getType().getStruct()->fields();
if (fields.empty())
{
error(dotLocation, "structure has no fields", "Internal Error");
- recover();
- indexedExpression = baseExpression;
+ return baseExpression;
}
else
{
+ bool fieldFound = false;
unsigned int i;
for (i = 0; i < fields.size(); ++i)
{
@@ -3034,50 +4150,31 @@ TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre
}
if (fieldFound)
{
- if (baseExpression->getAsConstantUnion())
- {
- indexedExpression = addConstStruct(fieldString, baseExpression, dotLocation);
- if (indexedExpression == 0)
- {
- recover();
- indexedExpression = baseExpression;
- }
- else
- {
- indexedExpression->setType(*fields[i]->type());
- }
- }
- else
- {
- TConstantUnion *unionArray = new TConstantUnion[1];
- unionArray->setIConst(i);
- TIntermTyped *index = intermediate.addConstantUnion(
- unionArray, *fields[i]->type(), fieldLocation);
- indexedExpression = intermediate.addIndex(EOpIndexDirectStruct, baseExpression,
- index, dotLocation);
- indexedExpression->setType(*fields[i]->type());
- }
+ TIntermTyped *index = CreateIndexNode(i);
+ index->setLine(fieldLocation);
+ TIntermBinary *node =
+ new TIntermBinary(EOpIndexDirectStruct, baseExpression, index);
+ node->setLine(dotLocation);
+ return node->fold(mDiagnostics);
}
else
{
error(dotLocation, " no such field in structure", fieldString.c_str());
- recover();
- indexedExpression = baseExpression;
+ return baseExpression;
}
}
}
else if (baseExpression->isInterfaceBlock())
{
- bool fieldFound = false;
const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
if (fields.empty())
{
error(dotLocation, "interface block has no fields", "Internal Error");
- recover();
- indexedExpression = baseExpression;
+ return baseExpression;
}
else
{
+ bool fieldFound = false;
unsigned int i;
for (i = 0; i < fields.size(); ++i)
{
@@ -3089,19 +4186,18 @@ TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre
}
if (fieldFound)
{
- TConstantUnion *unionArray = new TConstantUnion[1];
- unionArray->setIConst(i);
- TIntermTyped *index =
- intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation);
- indexedExpression = intermediate.addIndex(EOpIndexDirectInterfaceBlock,
- baseExpression, index, dotLocation);
- indexedExpression->setType(*fields[i]->type());
+ TIntermTyped *index = CreateIndexNode(i);
+ index->setLine(fieldLocation);
+ TIntermBinary *node =
+ new TIntermBinary(EOpIndexDirectInterfaceBlock, baseExpression, index);
+ node->setLine(dotLocation);
+ // Indexing interface blocks can never be constant folded.
+ return node;
}
else
{
error(dotLocation, " no such field in interface block", fieldString.c_str());
- recover();
- indexedExpression = baseExpression;
+ return baseExpression;
}
}
}
@@ -3119,39 +4215,36 @@ TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre
"side",
fieldString.c_str());
}
- recover();
- indexedExpression = baseExpression;
- }
-
- if (baseExpression->getQualifier() == EvqConst)
- {
- indexedExpression->getTypePointer()->setQualifier(EvqConst);
- }
- else
- {
- indexedExpression->getTypePointer()->setQualifier(EvqTemporary);
+ return baseExpression;
}
-
- return indexedExpression;
}
TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
const TSourceLoc &qualifierTypeLine)
{
- TLayoutQualifier qualifier;
-
- qualifier.location = -1;
- qualifier.matrixPacking = EmpUnspecified;
- qualifier.blockStorage = EbsUnspecified;
+ TLayoutQualifier qualifier = TLayoutQualifier::Create();
if (qualifierType == "shared")
{
+ if (sh::IsWebGLBasedSpec(mShaderSpec))
+ {
+ error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "shared");
+ }
qualifier.blockStorage = EbsShared;
}
else if (qualifierType == "packed")
{
+ if (sh::IsWebGLBasedSpec(mShaderSpec))
+ {
+ error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "packed");
+ }
qualifier.blockStorage = EbsPacked;
}
+ else if (qualifierType == "std430")
+ {
+ checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+ qualifier.blockStorage = EbsStd430;
+ }
else if (qualifierType == "std140")
{
qualifier.blockStorage = EbsStd140;
@@ -3166,208 +4259,554 @@ TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierTyp
}
else if (qualifierType == "location")
{
- error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(),
- "location requires an argument");
- recover();
+ error(qualifierTypeLine, "invalid layout qualifier: location requires an argument",
+ qualifierType.c_str());
+ }
+ else if (qualifierType == "yuv" && mShaderType == GL_FRAGMENT_SHADER)
+ {
+ if (checkCanUseExtension(qualifierTypeLine, TExtension::EXT_YUV_target))
+ {
+ qualifier.yuv = true;
+ }
+ }
+ else if (qualifierType == "rgba32f")
+ {
+ checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+ qualifier.imageInternalFormat = EiifRGBA32F;
+ }
+ else if (qualifierType == "rgba16f")
+ {
+ checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+ qualifier.imageInternalFormat = EiifRGBA16F;
+ }
+ else if (qualifierType == "r32f")
+ {
+ checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+ qualifier.imageInternalFormat = EiifR32F;
+ }
+ else if (qualifierType == "rgba8")
+ {
+ checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+ qualifier.imageInternalFormat = EiifRGBA8;
+ }
+ else if (qualifierType == "rgba8_snorm")
+ {
+ checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+ qualifier.imageInternalFormat = EiifRGBA8_SNORM;
+ }
+ else if (qualifierType == "rgba32i")
+ {
+ checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+ qualifier.imageInternalFormat = EiifRGBA32I;
+ }
+ else if (qualifierType == "rgba16i")
+ {
+ checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+ qualifier.imageInternalFormat = EiifRGBA16I;
+ }
+ else if (qualifierType == "rgba8i")
+ {
+ checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+ qualifier.imageInternalFormat = EiifRGBA8I;
+ }
+ else if (qualifierType == "r32i")
+ {
+ checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+ qualifier.imageInternalFormat = EiifR32I;
+ }
+ else if (qualifierType == "rgba32ui")
+ {
+ checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+ qualifier.imageInternalFormat = EiifRGBA32UI;
+ }
+ else if (qualifierType == "rgba16ui")
+ {
+ checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+ qualifier.imageInternalFormat = EiifRGBA16UI;
+ }
+ else if (qualifierType == "rgba8ui")
+ {
+ checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+ qualifier.imageInternalFormat = EiifRGBA8UI;
+ }
+ else if (qualifierType == "r32ui")
+ {
+ checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+ qualifier.imageInternalFormat = EiifR32UI;
}
+ else if (qualifierType == "points" && mShaderType == GL_GEOMETRY_SHADER_OES &&
+ checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader))
+ {
+ checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+ qualifier.primitiveType = EptPoints;
+ }
+ else if (qualifierType == "lines" && mShaderType == GL_GEOMETRY_SHADER_OES &&
+ checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader))
+ {
+ checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+ qualifier.primitiveType = EptLines;
+ }
+ else if (qualifierType == "lines_adjacency" && mShaderType == GL_GEOMETRY_SHADER_OES &&
+ checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader))
+ {
+ checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+ qualifier.primitiveType = EptLinesAdjacency;
+ }
+ else if (qualifierType == "triangles" && mShaderType == GL_GEOMETRY_SHADER_OES &&
+ checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader))
+ {
+ checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+ qualifier.primitiveType = EptTriangles;
+ }
+ else if (qualifierType == "triangles_adjacency" && mShaderType == GL_GEOMETRY_SHADER_OES &&
+ checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader))
+ {
+ checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+ qualifier.primitiveType = EptTrianglesAdjacency;
+ }
+ else if (qualifierType == "line_strip" && mShaderType == GL_GEOMETRY_SHADER_OES &&
+ checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader))
+ {
+ checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+ qualifier.primitiveType = EptLineStrip;
+ }
+ else if (qualifierType == "triangle_strip" && mShaderType == GL_GEOMETRY_SHADER_OES &&
+ checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader))
+ {
+ checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+ qualifier.primitiveType = EptTriangleStrip;
+ }
+
else
{
error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
- recover();
}
return qualifier;
}
+void TParseContext::parseLocalSize(const TString &qualifierType,
+ const TSourceLoc &qualifierTypeLine,
+ int intValue,
+ const TSourceLoc &intValueLine,
+ const std::string &intValueString,
+ size_t index,
+ sh::WorkGroupSize *localSize)
+{
+ checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+ if (intValue < 1)
+ {
+ std::stringstream reasonStream;
+ reasonStream << "out of range: " << getWorkGroupSizeString(index) << " must be positive";
+ std::string reason = reasonStream.str();
+ error(intValueLine, reason.c_str(), intValueString.c_str());
+ }
+ (*localSize)[index] = intValue;
+}
+
+void TParseContext::parseNumViews(int intValue,
+ const TSourceLoc &intValueLine,
+ const std::string &intValueString,
+ int *numViews)
+{
+ // This error is only specified in WebGL, but tightens unspecified behavior in the native
+ // specification.
+ if (intValue < 1)
+ {
+ error(intValueLine, "out of range: num_views must be positive", intValueString.c_str());
+ }
+ *numViews = intValue;
+}
+
+void TParseContext::parseInvocations(int intValue,
+ const TSourceLoc &intValueLine,
+ const std::string &intValueString,
+ int *numInvocations)
+{
+ // Although SPEC isn't clear whether invocations can be less than 1, we add this limit because
+ // it doesn't make sense to accept invocations <= 0.
+ if (intValue < 1 || intValue > mMaxGeometryShaderInvocations)
+ {
+ error(intValueLine,
+ "out of range: invocations must be in the range of [1, "
+ "MAX_GEOMETRY_SHADER_INVOCATIONS_OES]",
+ intValueString.c_str());
+ }
+ else
+ {
+ *numInvocations = intValue;
+ }
+}
+
+void TParseContext::parseMaxVertices(int intValue,
+ const TSourceLoc &intValueLine,
+ const std::string &intValueString,
+ int *maxVertices)
+{
+ // Although SPEC isn't clear whether max_vertices can be less than 0, we add this limit because
+ // it doesn't make sense to accept max_vertices < 0.
+ if (intValue < 0 || intValue > mMaxGeometryShaderMaxVertices)
+ {
+ error(
+ intValueLine,
+ "out of range: max_vertices must be in the range of [0, gl_MaxGeometryOutputVertices]",
+ intValueString.c_str());
+ }
+ else
+ {
+ *maxVertices = intValue;
+ }
+}
+
TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType,
const TSourceLoc &qualifierTypeLine,
- const TString &intValueString,
int intValue,
const TSourceLoc &intValueLine)
{
- TLayoutQualifier qualifier;
+ TLayoutQualifier qualifier = TLayoutQualifier::Create();
- qualifier.location = -1;
- qualifier.matrixPacking = EmpUnspecified;
- qualifier.blockStorage = EbsUnspecified;
+ std::string intValueString = Str(intValue);
- if (qualifierType != "location")
+ if (qualifierType == "location")
+ {
+ // must check that location is non-negative
+ if (intValue < 0)
+ {
+ error(intValueLine, "out of range: location must be non-negative",
+ intValueString.c_str());
+ }
+ else
+ {
+ qualifier.location = intValue;
+ qualifier.locationsSpecified = 1;
+ }
+ }
+ else if (qualifierType == "binding")
{
- error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(),
- "only location may have arguments");
- recover();
+ checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
+ if (intValue < 0)
+ {
+ error(intValueLine, "out of range: binding must be non-negative",
+ intValueString.c_str());
+ }
+ else
+ {
+ qualifier.binding = intValue;
+ }
}
- else
+ else if (qualifierType == "offset")
{
- // must check that location is non-negative
+ checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
if (intValue < 0)
{
- error(intValueLine, "out of range:", intValueString.c_str(),
- "location must be non-negative");
- recover();
+ error(intValueLine, "out of range: offset must be non-negative",
+ intValueString.c_str());
}
else
{
- qualifier.location = intValue;
+ qualifier.offset = intValue;
+ }
+ }
+ else if (qualifierType == "local_size_x")
+ {
+ parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u,
+ &qualifier.localSize);
+ }
+ else if (qualifierType == "local_size_y")
+ {
+ parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u,
+ &qualifier.localSize);
+ }
+ else if (qualifierType == "local_size_z")
+ {
+ parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
+ &qualifier.localSize);
+ }
+ else if (qualifierType == "num_views" && mShaderType == GL_VERTEX_SHADER)
+ {
+ if (checkCanUseExtension(qualifierTypeLine, TExtension::OVR_multiview))
+ {
+ parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews);
}
}
+ else if (qualifierType == "invocations" && mShaderType == GL_GEOMETRY_SHADER_OES &&
+ checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader))
+ {
+ parseInvocations(intValue, intValueLine, intValueString, &qualifier.invocations);
+ }
+ else if (qualifierType == "max_vertices" && mShaderType == GL_GEOMETRY_SHADER_OES &&
+ checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader))
+ {
+ parseMaxVertices(intValue, intValueLine, intValueString, &qualifier.maxVertices);
+ }
+
+ else
+ {
+ error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
+ }
return qualifier;
}
-TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
- TLayoutQualifier rightQualifier)
+TTypeQualifierBuilder *TParseContext::createTypeQualifierBuilder(const TSourceLoc &loc)
{
- TLayoutQualifier joinedQualifier = leftQualifier;
+ return new TTypeQualifierBuilder(
+ new TStorageQualifierWrapper(symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary, loc),
+ mShaderVersion);
+}
+
+TStorageQualifierWrapper *TParseContext::parseGlobalStorageQualifier(TQualifier qualifier,
+ const TSourceLoc &loc)
+{
+ checkIsAtGlobalLevel(loc, getQualifierString(qualifier));
+ return new TStorageQualifierWrapper(qualifier, loc);
+}
- if (rightQualifier.location != -1)
+TStorageQualifierWrapper *TParseContext::parseVaryingQualifier(const TSourceLoc &loc)
+{
+ if (getShaderType() == GL_VERTEX_SHADER)
{
- joinedQualifier.location = rightQualifier.location;
+ return parseGlobalStorageQualifier(EvqVaryingOut, loc);
}
- if (rightQualifier.matrixPacking != EmpUnspecified)
+ return parseGlobalStorageQualifier(EvqVaryingIn, loc);
+}
+
+TStorageQualifierWrapper *TParseContext::parseInQualifier(const TSourceLoc &loc)
+{
+ if (declaringFunction())
{
- joinedQualifier.matrixPacking = rightQualifier.matrixPacking;
+ return new TStorageQualifierWrapper(EvqIn, loc);
}
- if (rightQualifier.blockStorage != EbsUnspecified)
+
+ switch (getShaderType())
{
- joinedQualifier.blockStorage = rightQualifier.blockStorage;
+ case GL_VERTEX_SHADER:
+ {
+ if (mShaderVersion < 300 && !isExtensionEnabled(TExtension::OVR_multiview))
+ {
+ error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
+ }
+ return new TStorageQualifierWrapper(EvqVertexIn, loc);
+ }
+ case GL_FRAGMENT_SHADER:
+ {
+ if (mShaderVersion < 300)
+ {
+ error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
+ }
+ return new TStorageQualifierWrapper(EvqFragmentIn, loc);
+ }
+ case GL_COMPUTE_SHADER:
+ {
+ return new TStorageQualifierWrapper(EvqComputeIn, loc);
+ }
+ case GL_GEOMETRY_SHADER_OES:
+ {
+ return new TStorageQualifierWrapper(EvqGeometryIn, loc);
+ }
+ default:
+ {
+ UNREACHABLE();
+ return new TStorageQualifierWrapper(EvqLast, loc);
+ }
}
-
- return joinedQualifier;
}
-TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpolationLoc,
- TQualifier interpolationQualifier,
- const TSourceLoc &storageLoc,
- TQualifier storageQualifier)
+TStorageQualifierWrapper *TParseContext::parseOutQualifier(const TSourceLoc &loc)
{
- TQualifier mergedQualifier = EvqSmoothIn;
-
- if (storageQualifier == EvqFragmentIn)
+ if (declaringFunction())
{
- if (interpolationQualifier == EvqSmooth)
- mergedQualifier = EvqSmoothIn;
- else if (interpolationQualifier == EvqFlat)
- mergedQualifier = EvqFlatIn;
- else
- UNREACHABLE();
+ return new TStorageQualifierWrapper(EvqOut, loc);
}
- else if (storageQualifier == EvqCentroidIn)
+ switch (getShaderType())
{
- if (interpolationQualifier == EvqSmooth)
- mergedQualifier = EvqCentroidIn;
- else if (interpolationQualifier == EvqFlat)
- mergedQualifier = EvqFlatIn;
- else
+ case GL_VERTEX_SHADER:
+ {
+ if (mShaderVersion < 300)
+ {
+ error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "out");
+ }
+ return new TStorageQualifierWrapper(EvqVertexOut, loc);
+ }
+ case GL_FRAGMENT_SHADER:
+ {
+ if (mShaderVersion < 300)
+ {
+ error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "out");
+ }
+ return new TStorageQualifierWrapper(EvqFragmentOut, loc);
+ }
+ case GL_COMPUTE_SHADER:
+ {
+ error(loc, "storage qualifier isn't supported in compute shaders", "out");
+ return new TStorageQualifierWrapper(EvqLast, loc);
+ }
+ case GL_GEOMETRY_SHADER_OES:
+ {
+ return new TStorageQualifierWrapper(EvqGeometryOut, loc);
+ }
+ default:
+ {
UNREACHABLE();
+ return new TStorageQualifierWrapper(EvqLast, loc);
+ }
}
- else if (storageQualifier == EvqVertexOut)
+}
+
+TStorageQualifierWrapper *TParseContext::parseInOutQualifier(const TSourceLoc &loc)
+{
+ if (!declaringFunction())
{
- if (interpolationQualifier == EvqSmooth)
- mergedQualifier = EvqSmoothOut;
- else if (interpolationQualifier == EvqFlat)
- mergedQualifier = EvqFlatOut;
- else
- UNREACHABLE();
+ error(loc, "invalid qualifier: can be only used with function parameters", "inout");
}
- else if (storageQualifier == EvqCentroidOut)
+ return new TStorageQualifierWrapper(EvqInOut, loc);
+}
+
+TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
+ TLayoutQualifier rightQualifier,
+ const TSourceLoc &rightQualifierLocation)
+{
+ return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation,
+ mDiagnostics);
+}
+
+TField *TParseContext::parseStructDeclarator(TString *identifier, const TSourceLoc &loc)
+{
+ checkIsNotReserved(loc, *identifier);
+ TType *type = new TType(EbtVoid, EbpUndefined);
+ return new TField(type, identifier, loc);
+}
+
+TField *TParseContext::parseStructArrayDeclarator(TString *identifier,
+ const TSourceLoc &loc,
+ const TVector<unsigned int> &arraySizes,
+ const TSourceLoc &arraySizeLoc)
+{
+ checkIsNotReserved(loc, *identifier);
+
+ TType *type = new TType(EbtVoid, EbpUndefined);
+ type->makeArrays(arraySizes);
+
+ return new TField(type, identifier, loc);
+}
+
+void TParseContext::checkDoesNotHaveDuplicateFieldName(const TFieldList::const_iterator begin,
+ const TFieldList::const_iterator end,
+ const TString &name,
+ const TSourceLoc &location)
+{
+ for (auto fieldIter = begin; fieldIter != end; ++fieldIter)
{
- if (interpolationQualifier == EvqSmooth)
- mergedQualifier = EvqCentroidOut;
- else if (interpolationQualifier == EvqFlat)
- mergedQualifier = EvqFlatOut;
- else
- UNREACHABLE();
+ if ((*fieldIter)->name() == name)
+ {
+ error(location, "duplicate field name in structure", name.c_str());
+ }
}
- else
- {
- error(interpolationLoc,
- "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier",
- getInterpolationString(interpolationQualifier));
- recover();
+}
- mergedQualifier = storageQualifier;
+TFieldList *TParseContext::addStructFieldList(TFieldList *fields, const TSourceLoc &location)
+{
+ for (TFieldList::const_iterator fieldIter = fields->begin(); fieldIter != fields->end();
+ ++fieldIter)
+ {
+ checkDoesNotHaveDuplicateFieldName(fields->begin(), fieldIter, (*fieldIter)->name(),
+ location);
}
-
- TPublicType type;
- type.setBasic(EbtVoid, mergedQualifier, storageLoc);
- return type;
+ return fields;
}
-TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
- TFieldList *fieldList)
+TFieldList *TParseContext::combineStructFieldLists(TFieldList *processedFields,
+ const TFieldList *newlyAddedFields,
+ const TSourceLoc &location)
{
- if (voidErrorCheck(typeSpecifier.line, (*fieldList)[0]->name(), typeSpecifier.type))
+ for (TField *field : *newlyAddedFields)
{
- recover();
+ checkDoesNotHaveDuplicateFieldName(processedFields->begin(), processedFields->end(),
+ field->name(), location);
+ processedFields->push_back(field);
}
+ return processedFields;
+}
+
+TFieldList *TParseContext::addStructDeclaratorListWithQualifiers(
+ const TTypeQualifierBuilder &typeQualifierBuilder,
+ TPublicType *typeSpecifier,
+ TFieldList *fieldList)
+{
+ TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
- for (unsigned int i = 0; i < fieldList->size(); ++i)
+ typeSpecifier->qualifier = typeQualifier.qualifier;
+ typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier;
+ typeSpecifier->memoryQualifier = typeQualifier.memoryQualifier;
+ typeSpecifier->invariant = typeQualifier.invariant;
+ if (typeQualifier.precision != EbpUndefined)
{
- //
- // Careful not to replace already known aspects of type, like array-ness
- //
- TType *type = (*fieldList)[i]->type();
- type->setBasicType(typeSpecifier.type);
- type->setPrimarySize(typeSpecifier.primarySize);
- type->setSecondarySize(typeSpecifier.secondarySize);
- type->setPrecision(typeSpecifier.precision);
- type->setQualifier(typeSpecifier.qualifier);
- type->setLayoutQualifier(typeSpecifier.layoutQualifier);
+ typeSpecifier->precision = typeQualifier.precision;
+ }
+ return addStructDeclaratorList(*typeSpecifier, fieldList);
+}
- // don't allow arrays of arrays
- if (type->isArray())
- {
- if (arrayTypeErrorCheck(typeSpecifier.line, typeSpecifier))
- recover();
- }
- if (typeSpecifier.array)
- type->setArraySize(typeSpecifier.arraySize);
- if (typeSpecifier.userDef)
+TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
+ TFieldList *declaratorList)
+{
+ checkPrecisionSpecified(typeSpecifier.getLine(), typeSpecifier.precision,
+ typeSpecifier.getBasicType());
+
+ checkIsNonVoid(typeSpecifier.getLine(), (*declaratorList)[0]->name(),
+ typeSpecifier.getBasicType());
+
+ checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier);
+
+ for (TField *declarator : *declaratorList)
+ {
+ // Don't allow arrays of arrays in ESSL < 3.10.
+ if (declarator->type()->isArray())
{
- type->setStruct(typeSpecifier.userDef->getStruct());
+ checkArrayElementIsNotArray(typeSpecifier.getLine(), typeSpecifier);
}
- if (structNestingErrorCheck(typeSpecifier.line, *(*fieldList)[i]))
+ auto *declaratorArraySizes = declarator->type()->getArraySizes();
+
+ TType *type = declarator->type();
+ *type = TType(typeSpecifier);
+ if (declaratorArraySizes != nullptr)
{
- recover();
+ for (unsigned int arraySize : *declaratorArraySizes)
+ {
+ type->makeArray(arraySize);
+ }
}
+
+ checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *declarator);
}
- return fieldList;
+ return declaratorList;
}
-TPublicType TParseContext::addStructure(const TSourceLoc &structLine,
- const TSourceLoc &nameLine,
- const TString *structName,
- TFieldList *fieldList)
+TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
+ const TSourceLoc &nameLine,
+ const TString *structName,
+ TFieldList *fieldList)
{
- TStructure *structure = new TStructure(structName, fieldList);
- TType *structureType = new TType(structure);
+ TStructure *structure = new TStructure(&symbolTable, structName, fieldList);
// Store a bool in the struct if we're at global scope, to allow us to
// skip the local struct scoping workaround in HLSL.
- structure->setUniqueId(TSymbolTable::nextUniqueId());
structure->setAtGlobalScope(symbolTable.atGlobalLevel());
if (!structName->empty())
{
- if (reservedErrorCheck(nameLine, *structName))
- {
- recover();
- }
- TVariable *userTypeDef = new TVariable(structName, *structureType, true);
- if (!symbolTable.declare(userTypeDef))
+ checkIsNotReserved(nameLine, *structName);
+ if (!symbolTable.declareStructType(structure))
{
- error(nameLine, "redefinition", structName->c_str(), "struct");
- recover();
+ error(nameLine, "redefinition of a struct", structName->c_str());
}
}
// ensure we do not specify any storage qualifiers on the struct members
for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
{
- const TField &field = *(*fieldList)[typeListIndex];
+ TField &field = *(*fieldList)[typeListIndex];
const TQualifier qualifier = field.type()->getQualifier();
switch (qualifier)
{
@@ -3377,22 +4816,37 @@ TPublicType TParseContext::addStructure(const TSourceLoc &structLine,
default:
error(field.line(), "invalid qualifier on struct member",
getQualifierString(qualifier));
- recover();
break;
}
+ if (field.type()->isInvariant())
+ {
+ error(field.line(), "invalid qualifier on struct member", "invariant");
+ }
+ // ESSL 3.10 section 4.1.8 -- atomic_uint or images are not allowed as structure member.
+ if (IsImage(field.type()->getBasicType()) || IsAtomicCounter(field.type()->getBasicType()))
+ {
+ error(field.line(), "disallowed type in struct", field.type()->getBasicString());
+ }
+
+ checkIsNotUnsizedArray(field.line(), "array members of structs must specify a size",
+ field.name().c_str(), field.type());
+
+ checkMemoryQualifierIsNotSpecified(field.type()->getMemoryQualifier(), field.line());
+
+ checkBindingIsNotSpecified(field.line(), field.type()->getLayoutQualifier().binding);
+
+ checkLocationIsNotSpecified(field.line(), field.type()->getLayoutQualifier());
}
- TPublicType publicType;
- publicType.setBasic(EbtStruct, EvqTemporary, structLine);
- publicType.userDef = structureType;
- publicType.isStructSpecifier = true;
+ TTypeSpecifierNonArray typeSpecifierNonArray;
+ typeSpecifierNonArray.initializeStruct(structure, true, structLine);
exitStructDeclaration();
- return publicType;
+ return typeSpecifierNonArray;
}
TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
- TIntermAggregate *statementList,
+ TIntermBlock *statementList,
const TSourceLoc &loc)
{
TBasicType switchType = init->getBasicType();
@@ -3401,26 +4855,18 @@ TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
{
error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
"switch");
- recover();
return nullptr;
}
- if (statementList)
+ ASSERT(statementList);
+ if (!ValidateSwitchStatementList(switchType, mShaderVersion, mDiagnostics, statementList, loc))
{
- if (!ValidateSwitch::validate(switchType, this, statementList, loc))
- {
- recover();
- return nullptr;
- }
- }
-
- TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc);
- if (node == nullptr)
- {
- error(loc, "erroneous switch statement", "switch");
- recover();
+ ASSERT(mDiagnostics->numErrors() > 0);
return nullptr;
}
+
+ TIntermSwitch *node = new TIntermSwitch(init, statementList);
+ node->setLine(loc);
return node;
}
@@ -3429,20 +4875,17 @@ TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &l
if (mSwitchNestingLevel == 0)
{
error(loc, "case labels need to be inside switch statements", "case");
- recover();
return nullptr;
}
if (condition == nullptr)
{
error(loc, "case label must have a condition", "case");
- recover();
return nullptr;
}
if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
condition->isMatrix() || condition->isArray() || condition->isVector())
{
error(condition->getLine(), "case label must be a scalar integer", "case");
- recover();
}
TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
// TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant
@@ -3451,15 +4894,9 @@ TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &l
if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
{
error(condition->getLine(), "case label must be constant", "case");
- recover();
- }
- TIntermCase *node = intermediate.addCase(condition, loc);
- if (node == nullptr)
- {
- error(loc, "erroneous case statement", "case");
- recover();
- return nullptr;
}
+ TIntermCase *node = new TIntermCase(condition);
+ node->setLine(loc);
return node;
}
@@ -3468,28 +4905,18 @@ TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
if (mSwitchNestingLevel == 0)
{
error(loc, "default labels need to be inside switch statements", "default");
- recover();
- return nullptr;
- }
- TIntermCase *node = intermediate.addCase(nullptr, loc);
- if (node == nullptr)
- {
- error(loc, "erroneous default statement", "default");
- recover();
return nullptr;
}
+ TIntermCase *node = new TIntermCase(nullptr);
+ node->setLine(loc);
return node;
}
TIntermTyped *TParseContext::createUnaryMath(TOperator op,
TIntermTyped *child,
- const TSourceLoc &loc,
- const TType *funcReturnType)
+ const TSourceLoc &loc)
{
- if (child == nullptr)
- {
- return nullptr;
- }
+ ASSERT(child != nullptr);
switch (op)
{
@@ -3497,6 +4924,7 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op,
if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
child->isVector())
{
+ unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
return nullptr;
}
break;
@@ -3504,6 +4932,7 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op,
if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
child->isMatrix() || child->isArray())
{
+ unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
return nullptr;
}
break;
@@ -3513,9 +4942,11 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op,
case EOpPreDecrement:
case EOpNegative:
case EOpPositive:
- if (child->getBasicType() == EbtStruct || child->getBasicType() == EbtBool ||
- child->isArray())
+ if (child->getBasicType() == EbtStruct || child->isInterfaceBlock() ||
+ child->getBasicType() == EbtBool || child->isArray() ||
+ IsOpaqueType(child->getBasicType()))
{
+ unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
return nullptr;
}
// Operators for built-ins are already type checked against their prototype.
@@ -3523,16 +4954,24 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op,
break;
}
- return intermediate.addUnaryMath(op, child, loc, funcReturnType);
+ if (child->getMemoryQualifier().writeonly)
+ {
+ unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
+ return nullptr;
+ }
+
+ TIntermUnary *node = new TIntermUnary(op, child);
+ node->setLine(loc);
+
+ return node->fold(mDiagnostics);
}
TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
{
- TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
+ ASSERT(op != EOpNull);
+ TIntermTyped *node = createUnaryMath(op, child, loc);
if (node == nullptr)
{
- unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
- recover();
return child;
}
return node;
@@ -3542,8 +4981,7 @@ TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
TIntermTyped *child,
const TSourceLoc &loc)
{
- if (lValueErrorCheck(loc, GetOperatorString(op), child))
- recover();
+ checkCanBeLValue(loc, GetOperatorString(op), child);
return addUnaryMath(op, child, loc);
}
@@ -3552,17 +4990,95 @@ bool TParseContext::binaryOpCommonCheck(TOperator op,
TIntermTyped *right,
const TSourceLoc &loc)
{
- if (left->isArray() || right->isArray())
+ // Check opaque types are not allowed to be operands in expressions other than array indexing
+ // and structure member selection.
+ if (IsOpaqueType(left->getBasicType()) || IsOpaqueType(right->getBasicType()))
{
- if (mShaderVersion < 300)
+ switch (op)
{
- error(loc, "Invalid operation for arrays", GetOperatorString(op));
- return false;
+ case EOpIndexDirect:
+ case EOpIndexIndirect:
+ break;
+ case EOpIndexDirectStruct:
+ UNREACHABLE();
+
+ default:
+ error(loc, "Invalid operation for variables with an opaque type",
+ GetOperatorString(op));
+ return false;
}
+ }
+
+ if (right->getMemoryQualifier().writeonly)
+ {
+ error(loc, "Invalid operation for variables with writeonly", GetOperatorString(op));
+ return false;
+ }
- if (left->isArray() != right->isArray())
+ if (left->getMemoryQualifier().writeonly)
+ {
+ switch (op)
{
- error(loc, "array / non-array mismatch", GetOperatorString(op));
+ case EOpAssign:
+ case EOpInitialize:
+ case EOpIndexDirect:
+ case EOpIndexIndirect:
+ case EOpIndexDirectStruct:
+ case EOpIndexDirectInterfaceBlock:
+ break;
+ default:
+ error(loc, "Invalid operation for variables with writeonly", GetOperatorString(op));
+ return false;
+ }
+ }
+
+ if (left->getType().getStruct() || right->getType().getStruct())
+ {
+ switch (op)
+ {
+ case EOpIndexDirectStruct:
+ ASSERT(left->getType().getStruct());
+ break;
+ case EOpEqual:
+ case EOpNotEqual:
+ case EOpAssign:
+ case EOpInitialize:
+ if (left->getType() != right->getType())
+ {
+ return false;
+ }
+ break;
+ default:
+ error(loc, "Invalid operation for structs", GetOperatorString(op));
+ return false;
+ }
+ }
+
+ if (left->isInterfaceBlock() || right->isInterfaceBlock())
+ {
+ switch (op)
+ {
+ case EOpIndexDirectInterfaceBlock:
+ ASSERT(left->getType().getInterfaceBlock());
+ break;
+ default:
+ error(loc, "Invalid operation for interface blocks", GetOperatorString(op));
+ return false;
+ }
+ }
+
+ if (left->isArray() != right->isArray())
+ {
+ error(loc, "array / non-array mismatch", GetOperatorString(op));
+ return false;
+ }
+
+ if (left->isArray())
+ {
+ ASSERT(right->isArray());
+ if (mShaderVersion < 300)
+ {
+ error(loc, "Invalid operation for arrays", GetOperatorString(op));
return false;
}
@@ -3578,7 +5094,7 @@ bool TParseContext::binaryOpCommonCheck(TOperator op,
return false;
}
// At this point, size of implicitly sized arrays should be resolved.
- if (left->getArraySize() != right->getArraySize())
+ if (*left->getType().getArraySizes() != *right->getType().getArraySizes())
{
error(loc, "array size mismatch", GetOperatorString(op));
return false;
@@ -3625,8 +5141,10 @@ bool TParseContext::binaryOpCommonCheck(TOperator op,
return false;
}
- // Check that type sizes match exactly on ops that require that.
- // Also check restrictions for structs that contain arrays or samplers.
+ // Check that:
+ // 1. Type sizes match exactly on ops that require that.
+ // 2. Restrictions for structs that contain arrays or samplers are respected.
+ // 3. Arithmetic op type dimensionality restrictions for ops other than multiply are respected.
switch (op)
{
case EOpAssign:
@@ -3650,15 +5168,65 @@ bool TParseContext::binaryOpCommonCheck(TOperator op,
GetOperatorString(op));
return false;
}
+
+ if ((left->getNominalSize() != right->getNominalSize()) ||
+ (left->getSecondarySize() != right->getSecondarySize()))
+ {
+ error(loc, "dimension mismatch", GetOperatorString(op));
+ return false;
+ }
+ break;
case EOpLessThan:
case EOpGreaterThan:
case EOpLessThanEqual:
case EOpGreaterThanEqual:
- if ((left->getNominalSize() != right->getNominalSize()) ||
- (left->getSecondarySize() != right->getSecondarySize()))
+ if (!left->isScalar() || !right->isScalar())
+ {
+ error(loc, "comparison operator only defined for scalars", GetOperatorString(op));
+ return false;
+ }
+ break;
+ case EOpAdd:
+ case EOpSub:
+ case EOpDiv:
+ case EOpIMod:
+ case EOpBitShiftLeft:
+ case EOpBitShiftRight:
+ case EOpBitwiseAnd:
+ case EOpBitwiseXor:
+ case EOpBitwiseOr:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpDivAssign:
+ case EOpIModAssign:
+ case EOpBitShiftLeftAssign:
+ case EOpBitShiftRightAssign:
+ case EOpBitwiseAndAssign:
+ case EOpBitwiseXorAssign:
+ case EOpBitwiseOrAssign:
+ if ((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix()))
{
return false;
}
+
+ // Are the sizes compatible?
+ if (left->getNominalSize() != right->getNominalSize() ||
+ left->getSecondarySize() != right->getSecondarySize())
+ {
+ // If the nominal sizes of operands do not match:
+ // One of them must be a scalar.
+ if (!left->isScalar() && !right->isScalar())
+ return false;
+
+ // In the case of compound assignment other than multiply-assign,
+ // the right side needs to be a scalar. Otherwise a vector/matrix
+ // would be assigned to a scalar. A scalar can't be shifted by a
+ // vector either.
+ if (!right->isScalar() &&
+ (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight))
+ return false;
+ }
+ break;
default:
break;
}
@@ -3666,6 +5234,49 @@ bool TParseContext::binaryOpCommonCheck(TOperator op,
return true;
}
+bool TParseContext::isMultiplicationTypeCombinationValid(TOperator op,
+ const TType &left,
+ const TType &right)
+{
+ switch (op)
+ {
+ case EOpMul:
+ case EOpMulAssign:
+ return left.getNominalSize() == right.getNominalSize() &&
+ left.getSecondarySize() == right.getSecondarySize();
+ case EOpVectorTimesScalar:
+ return true;
+ case EOpVectorTimesScalarAssign:
+ ASSERT(!left.isMatrix() && !right.isMatrix());
+ return left.isVector() && !right.isVector();
+ case EOpVectorTimesMatrix:
+ return left.getNominalSize() == right.getRows();
+ case EOpVectorTimesMatrixAssign:
+ ASSERT(!left.isMatrix() && right.isMatrix());
+ return left.isVector() && left.getNominalSize() == right.getRows() &&
+ left.getNominalSize() == right.getCols();
+ case EOpMatrixTimesVector:
+ return left.getCols() == right.getNominalSize();
+ case EOpMatrixTimesScalar:
+ return true;
+ case EOpMatrixTimesScalarAssign:
+ ASSERT(left.isMatrix() && !right.isMatrix());
+ return !right.isVector();
+ case EOpMatrixTimesMatrix:
+ return left.getCols() == right.getRows();
+ case EOpMatrixTimesMatrixAssign:
+ ASSERT(left.isMatrix() && right.isMatrix());
+ // We need to check two things:
+ // 1. The matrix multiplication step is valid.
+ // 2. The result will have the same number of columns as the lvalue.
+ return left.getCols() == right.getRows() && left.getCols() == right.getCols();
+
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
TIntermTyped *left,
TIntermTyped *right,
@@ -3678,52 +5289,61 @@ TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
{
case EOpEqual:
case EOpNotEqual:
- break;
case EOpLessThan:
case EOpGreaterThan:
case EOpLessThanEqual:
case EOpGreaterThanEqual:
- ASSERT(!left->isArray() && !right->isArray());
- if (left->isMatrix() || left->isVector() || left->getBasicType() == EbtStruct)
- {
- return nullptr;
- }
break;
case EOpLogicalOr:
case EOpLogicalXor:
case EOpLogicalAnd:
- ASSERT(!left->isArray() && !right->isArray());
- if (left->getBasicType() != EbtBool || left->isMatrix() || left->isVector())
+ ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
+ !right->getType().getStruct());
+ if (left->getBasicType() != EbtBool || !left->isScalar() || !right->isScalar())
{
return nullptr;
}
+ // Basic types matching should have been already checked.
+ ASSERT(right->getBasicType() == EbtBool);
break;
case EOpAdd:
case EOpSub:
case EOpDiv:
case EOpMul:
- ASSERT(!left->isArray() && !right->isArray());
- if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
+ ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
+ !right->getType().getStruct());
+ if (left->getBasicType() == EbtBool)
{
return nullptr;
}
break;
case EOpIMod:
- ASSERT(!left->isArray() && !right->isArray());
+ ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
+ !right->getType().getStruct());
// Note that this is only for the % operator, not for mod()
- if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool ||
- left->getBasicType() == EbtFloat)
+ if (left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
{
return nullptr;
}
break;
- // Note that for bitwise ops, type checking is done in promote() to
- // share code between ops and compound assignment
default:
break;
}
- return intermediate.addBinaryMath(op, left, right, loc);
+ if (op == EOpMul)
+ {
+ op = TIntermBinary::GetMulOpBasedOnOperands(left->getType(), right->getType());
+ if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
+ {
+ return nullptr;
+ }
+ }
+
+ TIntermBinary *node = new TIntermBinary(op, left, right);
+ node->setLine(loc);
+
+ // See if we can fold constants.
+ return node->fold(mDiagnostics);
}
TIntermTyped *TParseContext::addBinaryMath(TOperator op,
@@ -3736,7 +5356,6 @@ TIntermTyped *TParseContext::addBinaryMath(TOperator op,
{
binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
right->getCompleteString());
- recover();
return left;
}
return node;
@@ -3748,27 +5367,35 @@ TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
const TSourceLoc &loc)
{
TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
- if (node == 0)
+ if (node == nullptr)
{
binaryOpError(loc, GetOperatorString(op), left->getCompleteString(),
right->getCompleteString());
- recover();
- TConstantUnion *unionArray = new TConstantUnion[1];
- unionArray->setBConst(false);
- return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst),
- loc);
+ node = CreateBoolNode(false);
+ node->setLine(loc);
}
return node;
}
-TIntermTyped *TParseContext::createAssign(TOperator op,
- TIntermTyped *left,
- TIntermTyped *right,
- const TSourceLoc &loc)
+TIntermBinary *TParseContext::createAssign(TOperator op,
+ TIntermTyped *left,
+ TIntermTyped *right,
+ const TSourceLoc &loc)
{
if (binaryOpCommonCheck(op, left, right, loc))
{
- return intermediate.addAssign(op, left, right, loc);
+ if (op == EOpMulAssign)
+ {
+ op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType());
+ if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
+ {
+ return nullptr;
+ }
+ }
+ TIntermBinary *node = new TIntermBinary(op, left, right);
+ node->setLine(loc);
+
+ return node;
}
return nullptr;
}
@@ -3778,11 +5405,11 @@ TIntermTyped *TParseContext::addAssign(TOperator op,
TIntermTyped *right,
const TSourceLoc &loc)
{
+ checkCanBeLValue(loc, "assign", left);
TIntermTyped *node = createAssign(op, left, right, loc);
if (node == nullptr)
{
assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
- recover();
return left;
}
return node;
@@ -3792,7 +5419,22 @@ TIntermTyped *TParseContext::addComma(TIntermTyped *left,
TIntermTyped *right,
const TSourceLoc &loc)
{
- return intermediate.addComma(left, right, loc, mShaderVersion);
+ // WebGL2 section 5.26, the following results in an error:
+ // "Sequence operator applied to void, arrays, or structs containing arrays"
+ if (mShaderSpec == SH_WEBGL2_SPEC &&
+ (left->isArray() || left->getBasicType() == EbtVoid ||
+ left->getType().isStructureContainingArrays() || right->isArray() ||
+ right->getBasicType() == EbtVoid || right->getType().isStructureContainingArrays()))
+ {
+ error(loc,
+ "sequence operator is not allowed for void, arrays, or structs containing arrays",
+ ",");
+ }
+
+ TIntermBinary *commaNode = new TIntermBinary(EOpComma, left, right);
+ TQualifier resultQualifier = TIntermBinary::GetCommaQualifier(mShaderVersion, left, right);
+ commaNode->getTypePointer()->setQualifier(resultQualifier);
+ return commaNode->fold(mDiagnostics);
}
TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
@@ -3803,319 +5445,553 @@ TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
if (mLoopNestingLevel <= 0)
{
error(loc, "continue statement only allowed in loops", "");
- recover();
}
break;
case EOpBreak:
if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
{
error(loc, "break statement only allowed in loops and switch statements", "");
- recover();
}
break;
case EOpReturn:
if (mCurrentFunctionType->getBasicType() != EbtVoid)
{
error(loc, "non-void function must return a value", "return");
- recover();
+ }
+ break;
+ case EOpKill:
+ if (mShaderType != GL_FRAGMENT_SHADER)
+ {
+ error(loc, "discard supported in fragment shaders only", "discard");
}
break;
default:
- // No checks for discard
+ UNREACHABLE();
break;
}
- return intermediate.addBranch(op, loc);
+ return addBranch(op, nullptr, loc);
}
TIntermBranch *TParseContext::addBranch(TOperator op,
- TIntermTyped *returnValue,
+ TIntermTyped *expression,
const TSourceLoc &loc)
{
- ASSERT(op == EOpReturn);
- mFunctionReturnsValue = true;
- if (mCurrentFunctionType->getBasicType() == EbtVoid)
+ if (expression != nullptr)
{
- error(loc, "void function cannot return a value", "return");
- recover();
+ ASSERT(op == EOpReturn);
+ mFunctionReturnsValue = true;
+ if (mCurrentFunctionType->getBasicType() == EbtVoid)
+ {
+ error(loc, "void function cannot return a value", "return");
+ }
+ else if (*mCurrentFunctionType != expression->getType())
+ {
+ error(loc, "function return is not matching type:", "return");
+ }
}
- else if (*mCurrentFunctionType != returnValue->getType())
- {
- error(loc, "function return is not matching type:", "return");
- recover();
+ TIntermBranch *node = new TIntermBranch(op, expression);
+ node->setLine(loc);
+ return node;
+}
+
+void TParseContext::checkTextureGather(TIntermAggregate *functionCall)
+{
+ ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
+ const TString &name = functionCall->getFunctionSymbolInfo()->getName();
+ bool isTextureGather = (name == "textureGather");
+ bool isTextureGatherOffset = (name == "textureGatherOffset");
+ if (isTextureGather || isTextureGatherOffset)
+ {
+ TIntermNode *componentNode = nullptr;
+ TIntermSequence *arguments = functionCall->getSequence();
+ ASSERT(arguments->size() >= 2u && arguments->size() <= 4u);
+ const TIntermTyped *sampler = arguments->front()->getAsTyped();
+ ASSERT(sampler != nullptr);
+ switch (sampler->getBasicType())
+ {
+ case EbtSampler2D:
+ case EbtISampler2D:
+ case EbtUSampler2D:
+ case EbtSampler2DArray:
+ case EbtISampler2DArray:
+ case EbtUSampler2DArray:
+ if ((isTextureGather && arguments->size() == 3u) ||
+ (isTextureGatherOffset && arguments->size() == 4u))
+ {
+ componentNode = arguments->back();
+ }
+ break;
+ case EbtSamplerCube:
+ case EbtISamplerCube:
+ case EbtUSamplerCube:
+ ASSERT(!isTextureGatherOffset);
+ if (arguments->size() == 3u)
+ {
+ componentNode = arguments->back();
+ }
+ break;
+ case EbtSampler2DShadow:
+ case EbtSampler2DArrayShadow:
+ case EbtSamplerCubeShadow:
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ if (componentNode)
+ {
+ const TIntermConstantUnion *componentConstantUnion =
+ componentNode->getAsConstantUnion();
+ if (componentNode->getAsTyped()->getQualifier() != EvqConst || !componentConstantUnion)
+ {
+ error(functionCall->getLine(), "Texture component must be a constant expression",
+ name.c_str());
+ }
+ else
+ {
+ int component = componentConstantUnion->getIConst(0);
+ if (component < 0 || component > 3)
+ {
+ error(functionCall->getLine(), "Component must be in the range [0;3]",
+ name.c_str());
+ }
+ }
+ }
}
- return intermediate.addBranch(op, returnValue, loc);
}
void TParseContext::checkTextureOffsetConst(TIntermAggregate *functionCall)
{
- ASSERT(!functionCall->isUserDefined());
- const TString &name = functionCall->getName();
+ ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
+ const TString &name = functionCall->getFunctionSymbolInfo()->getName();
TIntermNode *offset = nullptr;
TIntermSequence *arguments = functionCall->getSequence();
- if (name.compare(0, 16, "texelFetchOffset") == 0 ||
- name.compare(0, 16, "textureLodOffset") == 0 ||
- name.compare(0, 20, "textureProjLodOffset") == 0 ||
- name.compare(0, 17, "textureGradOffset") == 0 ||
- name.compare(0, 21, "textureProjGradOffset") == 0)
+ bool useTextureGatherOffsetConstraints = false;
+ if (name == "texelFetchOffset" || name == "textureLodOffset" ||
+ name == "textureProjLodOffset" || name == "textureGradOffset" ||
+ name == "textureProjGradOffset")
{
offset = arguments->back();
}
- else if (name.compare(0, 13, "textureOffset") == 0 ||
- name.compare(0, 17, "textureProjOffset") == 0)
+ else if (name == "textureOffset" || name == "textureProjOffset")
{
// A bias parameter might follow the offset parameter.
ASSERT(arguments->size() >= 3);
offset = (*arguments)[2];
}
+ else if (name == "textureGatherOffset")
+ {
+ ASSERT(arguments->size() >= 3u);
+ const TIntermTyped *sampler = arguments->front()->getAsTyped();
+ ASSERT(sampler != nullptr);
+ switch (sampler->getBasicType())
+ {
+ case EbtSampler2D:
+ case EbtISampler2D:
+ case EbtUSampler2D:
+ case EbtSampler2DArray:
+ case EbtISampler2DArray:
+ case EbtUSampler2DArray:
+ offset = (*arguments)[2];
+ break;
+ case EbtSampler2DShadow:
+ case EbtSampler2DArrayShadow:
+ offset = (*arguments)[3];
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ useTextureGatherOffsetConstraints = true;
+ }
if (offset != nullptr)
{
TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
if (offset->getAsTyped()->getQualifier() != EvqConst || !offsetConstantUnion)
{
- TString unmangledName = TFunction::unmangleName(name);
error(functionCall->getLine(), "Texture offset must be a constant expression",
- unmangledName.c_str());
- recover();
+ name.c_str());
}
else
{
ASSERT(offsetConstantUnion->getBasicType() == EbtInt);
size_t size = offsetConstantUnion->getType().getObjectSize();
const TConstantUnion *values = offsetConstantUnion->getUnionArrayPointer();
+ int minOffsetValue = useTextureGatherOffsetConstraints ? mMinProgramTextureGatherOffset
+ : mMinProgramTexelOffset;
+ int maxOffsetValue = useTextureGatherOffsetConstraints ? mMaxProgramTextureGatherOffset
+ : mMaxProgramTexelOffset;
for (size_t i = 0u; i < size; ++i)
{
int offsetValue = values[i].getIConst();
- if (offsetValue > mMaxProgramTexelOffset || offsetValue < mMinProgramTexelOffset)
+ if (offsetValue > maxOffsetValue || offsetValue < minOffsetValue)
{
std::stringstream tokenStream;
tokenStream << offsetValue;
std::string token = tokenStream.str();
error(offset->getLine(), "Texture offset value out of valid range",
token.c_str());
- recover();
}
}
}
}
}
-TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
- TIntermNode *paramNode,
- TIntermNode *thisNode,
- const TSourceLoc &loc,
- bool *fatalError)
+void TParseContext::checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall)
{
- *fatalError = false;
- TOperator op = fnCall->getBuiltInOp();
- TIntermTyped *callNode = nullptr;
-
- if (thisNode != nullptr)
+ const TString &name = functionCall->getFunctionSymbolInfo()->getName();
+ if (IsAtomicBuiltin(name))
{
- TConstantUnion *unionArray = new TConstantUnion[1];
- int arraySize = 0;
- TIntermTyped *typedThis = thisNode->getAsTyped();
- if (fnCall->getName() != "length")
+ TIntermSequence *arguments = functionCall->getSequence();
+ TIntermTyped *memNode = (*arguments)[0]->getAsTyped();
+
+ if (IsBufferOrSharedVariable(memNode))
{
- error(loc, "invalid method", fnCall->getName().c_str());
- recover();
+ return;
}
- else if (paramNode != nullptr)
+
+ while (memNode->getAsBinaryNode())
{
- error(loc, "method takes no parameters", "length");
- recover();
+ memNode = memNode->getAsBinaryNode()->getLeft();
+ if (IsBufferOrSharedVariable(memNode))
+ {
+ return;
+ }
}
- else if (typedThis == nullptr || !typedThis->isArray())
+
+ error(memNode->getLine(),
+ "The value passed to the mem argument of an atomic memory function does not "
+ "correspond to a buffer or shared variable.",
+ functionCall->getFunctionSymbolInfo()->getName().c_str());
+ }
+}
+
+// GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
+void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall)
+{
+ ASSERT(functionCall->getOp() == EOpCallBuiltInFunction);
+ const TString &name = functionCall->getFunctionSymbolInfo()->getName();
+
+ if (name.compare(0, 5, "image") == 0)
+ {
+ TIntermSequence *arguments = functionCall->getSequence();
+ TIntermTyped *imageNode = (*arguments)[0]->getAsTyped();
+
+ const TMemoryQualifier &memoryQualifier = imageNode->getMemoryQualifier();
+
+ if (name.compare(5, 5, "Store") == 0)
{
- error(loc, "length can only be called on arrays", "length");
- recover();
+ if (memoryQualifier.readonly)
+ {
+ error(imageNode->getLine(),
+ "'imageStore' cannot be used with images qualified as 'readonly'",
+ GetImageArgumentToken(imageNode));
+ }
}
- else
+ else if (name.compare(5, 4, "Load") == 0)
{
- arraySize = typedThis->getArraySize();
- if (typedThis->getAsSymbolNode() == nullptr)
+ if (memoryQualifier.writeonly)
{
- // This code path can be hit with expressions like these:
- // (a = b).length()
- // (func()).length()
- // (int[3](0, 1, 2)).length()
- // ESSL 3.00 section 5.9 defines expressions so that this is not actually a valid
- // expression.
- // It allows "An array name with the length method applied" in contrast to GLSL 4.4
- // spec section 5.9 which allows "An array, vector or matrix expression with the
- // length method applied".
- error(loc, "length can only be called on array names, not on array expressions",
- "length");
- recover();
+ error(imageNode->getLine(),
+ "'imageLoad' cannot be used with images qualified as 'writeonly'",
+ GetImageArgumentToken(imageNode));
}
}
- unionArray->setIConst(arraySize);
- callNode =
- intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), loc);
}
- else if (op != EOpNull)
+}
+
+// GLSL ES 3.10 Revision 4, 13.51 Matching of Memory Qualifiers in Function Parameters
+void TParseContext::checkImageMemoryAccessForUserDefinedFunctions(
+ const TFunction *functionDefinition,
+ const TIntermAggregate *functionCall)
+{
+ ASSERT(functionCall->getOp() == EOpCallFunctionInAST);
+
+ const TIntermSequence &arguments = *functionCall->getSequence();
+
+ ASSERT(functionDefinition->getParamCount() == arguments.size());
+
+ for (size_t i = 0; i < arguments.size(); ++i)
{
- //
- // Then this should be a constructor.
- // Don't go through the symbol table for constructors.
- // Their parameters will be verified algorithmically.
- //
- TType type(EbtVoid, EbpUndefined); // use this to get the type back
- if (!constructorErrorCheck(loc, paramNode, *fnCall, op, &type))
- {
- //
- // It's a constructor, of type 'type'.
- //
- callNode = addConstructor(paramNode, &type, op, fnCall, loc);
- }
+ TIntermTyped *typedArgument = arguments[i]->getAsTyped();
+ const TType &functionArgumentType = typedArgument->getType();
+ const TType &functionParameterType = *functionDefinition->getParam(i).type;
+ ASSERT(functionArgumentType.getBasicType() == functionParameterType.getBasicType());
- if (callNode == nullptr)
+ if (IsImage(functionArgumentType.getBasicType()))
{
- recover();
- callNode = intermediate.setAggregateOperator(nullptr, op, loc);
+ const TMemoryQualifier &functionArgumentMemoryQualifier =
+ functionArgumentType.getMemoryQualifier();
+ const TMemoryQualifier &functionParameterMemoryQualifier =
+ functionParameterType.getMemoryQualifier();
+ if (functionArgumentMemoryQualifier.readonly &&
+ !functionParameterMemoryQualifier.readonly)
+ {
+ error(functionCall->getLine(),
+ "Function call discards the 'readonly' qualifier from image",
+ GetImageArgumentToken(typedArgument));
+ }
+
+ if (functionArgumentMemoryQualifier.writeonly &&
+ !functionParameterMemoryQualifier.writeonly)
+ {
+ error(functionCall->getLine(),
+ "Function call discards the 'writeonly' qualifier from image",
+ GetImageArgumentToken(typedArgument));
+ }
+
+ if (functionArgumentMemoryQualifier.coherent &&
+ !functionParameterMemoryQualifier.coherent)
+ {
+ error(functionCall->getLine(),
+ "Function call discards the 'coherent' qualifier from image",
+ GetImageArgumentToken(typedArgument));
+ }
+
+ if (functionArgumentMemoryQualifier.volatileQualifier &&
+ !functionParameterMemoryQualifier.volatileQualifier)
+ {
+ error(functionCall->getLine(),
+ "Function call discards the 'volatile' qualifier from image",
+ GetImageArgumentToken(typedArgument));
+ }
}
- callNode->setType(type);
+ }
+}
+
+TIntermSequence *TParseContext::createEmptyArgumentsList()
+{
+ return new TIntermSequence();
+}
+
+TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
+ TIntermSequence *arguments,
+ TIntermNode *thisNode,
+ const TSourceLoc &loc)
+{
+ if (thisNode != nullptr)
+ {
+ return addMethod(fnCall, arguments, thisNode, loc);
+ }
+
+ TOperator op = fnCall->getBuiltInOp();
+ if (op == EOpConstruct)
+ {
+ return addConstructor(arguments, fnCall->getReturnType(), loc);
}
else
{
- //
- // Not a constructor. Find it in the symbol table.
- //
- const TFunction *fnCandidate;
- bool builtIn;
- fnCandidate = findFunction(loc, fnCall, mShaderVersion, &builtIn);
- if (fnCandidate)
+ ASSERT(op == EOpNull);
+ return addNonConstructorFunctionCall(fnCall, arguments, loc);
+ }
+}
+
+TIntermTyped *TParseContext::addMethod(TFunction *fnCall,
+ TIntermSequence *arguments,
+ TIntermNode *thisNode,
+ const TSourceLoc &loc)
+{
+ TIntermTyped *typedThis = thisNode->getAsTyped();
+ // It's possible for the name pointer in the TFunction to be null in case it gets parsed as
+ // a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS
+ // mode after a dot, which makes type identifiers to be parsed as FIELD_SELECTION instead.
+ // So accessing fnCall->getName() below is safe.
+ if (fnCall->getName() != "length")
+ {
+ error(loc, "invalid method", fnCall->getName().c_str());
+ }
+ else if (!arguments->empty())
+ {
+ error(loc, "method takes no parameters", "length");
+ }
+ else if (typedThis == nullptr || !typedThis->isArray())
+ {
+ error(loc, "length can only be called on arrays", "length");
+ }
+ else if (typedThis->getQualifier() == EvqPerVertexIn &&
+ mGeometryShaderInputPrimitiveType == EptUndefined)
+ {
+ ASSERT(mShaderType == GL_GEOMETRY_SHADER_OES);
+ error(loc, "missing input primitive declaration before calling length on gl_in", "length");
+ }
+ else
+ {
+ TIntermUnary *node = new TIntermUnary(EOpArrayLength, typedThis);
+ node->setLine(loc);
+ return node->fold(mDiagnostics);
+ }
+ return CreateZeroNode(TType(EbtInt, EbpUndefined, EvqConst));
+}
+
+TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunction *fnCall,
+ TIntermSequence *arguments,
+ const TSourceLoc &loc)
+{
+ // First find by unmangled name to check whether the function name has been
+ // hidden by a variable name or struct typename.
+ // If a function is found, check for one with a matching argument list.
+ bool builtIn;
+ const TSymbol *symbol = symbolTable.find(fnCall->getName(), mShaderVersion, &builtIn);
+ if (symbol != nullptr && !symbol->isFunction())
+ {
+ error(loc, "function name expected", fnCall->getName().c_str());
+ }
+ else
+ {
+ symbol = symbolTable.find(TFunction::GetMangledNameFromCall(fnCall->getName(), *arguments),
+ mShaderVersion, &builtIn);
+ if (symbol == nullptr)
{
+ error(loc, "no matching overloaded function found", fnCall->getName().c_str());
+ }
+ else
+ {
+ const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);
//
// A declared function.
//
- if (builtIn && !fnCandidate->getExtension().empty() &&
- extensionErrorCheck(loc, fnCandidate->getExtension()))
+ if (builtIn && fnCandidate->getExtension() != TExtension::UNDEFINED)
{
- recover();
+ checkCanUseExtension(loc, fnCandidate->getExtension());
}
- op = fnCandidate->getBuiltInOp();
+ TOperator op = fnCandidate->getBuiltInOp();
if (builtIn && op != EOpNull)
{
- //
// A function call mapped to a built-in operation.
- //
if (fnCandidate->getParamCount() == 1)
{
- //
// Treat it like a built-in unary operator.
- //
- TIntermAggregate *paramAgg = paramNode->getAsAggregate();
- paramNode = paramAgg->getSequence()->front();
- callNode = createUnaryMath(op, paramNode->getAsTyped(), loc,
- &fnCandidate->getReturnType());
- if (callNode == nullptr)
- {
- std::stringstream extraInfoStream;
- extraInfoStream
- << "built in unary operator function. Type: "
- << static_cast<TIntermTyped *>(paramNode)->getCompleteString();
- std::string extraInfo = extraInfoStream.str();
- error(paramNode->getLine(), " wrong operand type", "Internal Error",
- extraInfo.c_str());
- *fatalError = true;
- return nullptr;
- }
+ TIntermNode *unaryParamNode = arguments->front();
+ TIntermTyped *callNode = createUnaryMath(op, unaryParamNode->getAsTyped(), loc);
+ ASSERT(callNode != nullptr);
+ return callNode;
}
else
{
- TIntermAggregate *aggregate =
- intermediate.setAggregateOperator(paramNode, op, loc);
- aggregate->setType(fnCandidate->getReturnType());
- aggregate->setPrecisionFromChildren();
- if (aggregate->areChildrenConstQualified())
- {
- aggregate->getTypePointer()->setQualifier(EvqConst);
- }
+ TIntermAggregate *callNode =
+ TIntermAggregate::Create(fnCandidate->getReturnType(), op, arguments);
+ callNode->setLine(loc);
// Some built-in functions have out parameters too.
- functionCallLValueErrorCheck(fnCandidate, aggregate);
+ functionCallRValueLValueErrorCheck(fnCandidate, callNode);
- // See if we can constant fold a built-in. Note that this may be possible even
- // if it is not const-qualified.
- TIntermTyped *foldedNode = intermediate.foldAggregateBuiltIn(aggregate);
- if (foldedNode)
+ if (TIntermAggregate::CanFoldAggregateBuiltInOp(callNode->getOp()))
{
- callNode = foldedNode;
+ // See if we can constant fold a built-in. Note that this may be possible
+ // even if it is not const-qualified.
+ return callNode->fold(mDiagnostics);
}
else
{
- callNode = aggregate;
+ return callNode;
}
}
}
else
{
// This is a real function call
- TIntermAggregate *aggregate =
- intermediate.setAggregateOperator(paramNode, EOpFunctionCall, loc);
- aggregate->setType(fnCandidate->getReturnType());
-
- // this is how we know whether the given function is a builtIn function or a user
- // defined function
- // if builtIn == false, it's a userDefined -> could be an overloaded
- // builtIn function also
- // if builtIn == true, it's definitely a builtIn function with EOpNull
- if (!builtIn)
- aggregate->setUserDefined();
- aggregate->setName(fnCandidate->getMangledName());
- aggregate->setFunctionId(fnCandidate->getUniqueId());
-
- // This needs to happen after the name is set
+ TIntermAggregate *callNode = nullptr;
+
+ // If builtIn == false, the function is user defined - could be an overloaded
+ // built-in as well.
+ // if builtIn == true, it's a builtIn function with no op associated with it.
+ // This needs to happen after the function info including name is set.
if (builtIn)
{
- aggregate->setBuiltInFunctionPrecision();
-
- checkTextureOffsetConst(aggregate);
+ callNode = TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate, arguments);
+ checkTextureOffsetConst(callNode);
+ checkTextureGather(callNode);
+ checkImageMemoryAccessForBuiltinFunctions(callNode);
+ checkAtomicMemoryBuiltinFunctions(callNode);
+ }
+ else
+ {
+ callNode = TIntermAggregate::CreateFunctionCall(*fnCandidate, arguments);
+ checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode);
}
- callNode = aggregate;
+ functionCallRValueLValueErrorCheck(fnCandidate, callNode);
- functionCallLValueErrorCheck(fnCandidate, aggregate);
+ callNode->setLine(loc);
+
+ return callNode;
}
}
- else
- {
- // error message was put out by findFunction()
- // Put on a dummy node for error recovery
- TConstantUnion *unionArray = new TConstantUnion[1];
- unionArray->setFConst(0.0f);
- callNode = intermediate.addConstantUnion(unionArray,
- TType(EbtFloat, EbpUndefined, EvqConst), loc);
- recover();
- }
}
- return callNode;
+
+ // Error message was already written. Put on a dummy node for error recovery.
+ return CreateZeroNode(TType(EbtFloat, EbpMedium, EvqConst));
}
TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
- TIntermTyped *trueBlock,
- TIntermTyped *falseBlock,
+ TIntermTyped *trueExpression,
+ TIntermTyped *falseExpression,
const TSourceLoc &loc)
{
- if (boolErrorCheck(loc, cond))
- recover();
+ if (!checkIsScalarBool(loc, cond))
+ {
+ return falseExpression;
+ }
- if (trueBlock->getType() != falseBlock->getType())
+ if (trueExpression->getType() != falseExpression->getType())
{
- binaryOpError(loc, ":", trueBlock->getCompleteString(), falseBlock->getCompleteString());
- recover();
- return falseBlock;
+ std::stringstream reasonStream;
+ reasonStream << "mismatching ternary operator operand types '"
+ << trueExpression->getCompleteString() << " and '"
+ << falseExpression->getCompleteString() << "'";
+ std::string reason = reasonStream.str();
+ error(loc, reason.c_str(), "?:");
+ return falseExpression;
+ }
+ if (IsOpaqueType(trueExpression->getBasicType()))
+ {
+ // ESSL 1.00 section 4.1.7
+ // ESSL 3.00.6 section 4.1.7
+ // Opaque/sampler types are not allowed in most types of expressions, including ternary.
+ // Note that structs containing opaque types don't need to be checked as structs are
+ // forbidden below.
+ error(loc, "ternary operator is not allowed for opaque types", "?:");
+ return falseExpression;
+ }
+
+ if (cond->getMemoryQualifier().writeonly || trueExpression->getMemoryQualifier().writeonly ||
+ falseExpression->getMemoryQualifier().writeonly)
+ {
+ error(loc, "ternary operator is not allowed for variables with writeonly", "?:");
+ return falseExpression;
}
- // ESSL1 sections 5.2 and 5.7:
- // ESSL3 section 5.7:
+
+ // ESSL 1.00.17 sections 5.2 and 5.7:
// Ternary operator is not among the operators allowed for structures/arrays.
- if (trueBlock->isArray() || trueBlock->getBasicType() == EbtStruct)
+ // ESSL 3.00.6 section 5.7:
+ // Ternary operator support is optional for arrays. No certainty that it works across all
+ // devices with struct either, so we err on the side of caution here. TODO (oetuaho@nvidia.com):
+ // Would be nice to make the spec and implementation agree completely here.
+ if (trueExpression->isArray() || trueExpression->getBasicType() == EbtStruct)
{
- error(loc, "ternary operator is not allowed for structures or arrays", ":");
- recover();
- return falseBlock;
+ error(loc, "ternary operator is not allowed for structures or arrays", "?:");
+ return falseExpression;
}
- return intermediate.addSelection(cond, trueBlock, falseBlock, loc);
+ if (trueExpression->getBasicType() == EbtInterfaceBlock)
+ {
+ error(loc, "ternary operator is not allowed for interface blocks", "?:");
+ return falseExpression;
+ }
+
+ // WebGL2 section 5.26, the following results in an error:
+ // "Ternary operator applied to void, arrays, or structs containing arrays"
+ if (mShaderSpec == SH_WEBGL2_SPEC && trueExpression->getBasicType() == EbtVoid)
+ {
+ error(loc, "ternary operator is not allowed for void", "?:");
+ return falseExpression;
+ }
+
+ // Note that the node resulting from here can be a constant union without being qualified as
+ // constant.
+ TIntermTernary *node = new TIntermTernary(cond, trueExpression, falseExpression);
+ node->setLine(loc);
+
+ return node->fold();
}
//
@@ -4128,7 +6004,7 @@ int PaParseStrings(size_t count,
const int length[],
TParseContext *context)
{
- if ((count == 0) || (string == NULL))
+ if ((count == 0) || (string == nullptr))
return 1;
if (glslang_initialize(context))
@@ -4142,3 +6018,5 @@ int PaParseStrings(size_t count,
return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.h b/src/3rdparty/angle/src/compiler/translator/ParseContext.h
index 1eaf1e5b42..8bfdbd5e3f 100644
--- a/src/3rdparty/angle/src/compiler/translator/ParseContext.h
+++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.h
@@ -9,10 +9,13 @@
#include "compiler/translator/Compiler.h"
#include "compiler/translator/Diagnostics.h"
#include "compiler/translator/DirectiveHandler.h"
-#include "compiler/translator/Intermediate.h"
#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/QualifierTypes.h"
#include "compiler/preprocessor/Preprocessor.h"
+namespace sh
+{
+
struct TMatrixFields
{
bool wholeRow;
@@ -30,44 +33,13 @@ class TParseContext : angle::NonCopyable
public:
TParseContext(TSymbolTable &symt,
TExtensionBehavior &ext,
- TIntermediate &interm,
sh::GLenum type,
ShShaderSpec spec,
- int options,
+ ShCompileOptions options,
bool checksPrecErrors,
- TInfoSink &is,
- const ShBuiltInResources &resources)
- : intermediate(interm),
- symbolTable(symt),
- mDeferredSingleDeclarationErrorCheck(false),
- mShaderType(type),
- mShaderSpec(spec),
- mShaderVersion(100),
- mTreeRoot(nullptr),
- mLoopNestingLevel(0),
- mStructNestingLevel(0),
- mSwitchNestingLevel(0),
- mCurrentFunctionType(nullptr),
- mFunctionReturnsValue(false),
- mChecksPrecisionErrors(checksPrecErrors),
- mFragmentPrecisionHighOnESSL1(false),
- mDefaultMatrixPacking(EmpColumnMajor),
- mDefaultBlockStorage(EbsShared),
- mDiagnostics(is),
- mDirectiveHandler(ext,
- mDiagnostics,
- mShaderVersion,
- mShaderType,
- resources.WEBGL_debug_shader_precision == 1),
- mPreprocessor(&mDiagnostics, &mDirectiveHandler),
- mScanner(nullptr),
- mUsesFragData(false),
- mUsesFragColor(false),
- mUsesSecondaryOutputs(false),
- mMinProgramTexelOffset(resources.MinProgramTexelOffset),
- mMaxProgramTexelOffset(resources.MaxProgramTexelOffset)
- {
- }
+ TDiagnostics *diagnostics,
+ const ShBuiltInResources &resources);
+ ~TParseContext();
const pp::Preprocessor &getPreprocessor() const { return mPreprocessor; }
pp::Preprocessor &getPreprocessor() { return mPreprocessor; }
@@ -76,23 +48,18 @@ class TParseContext : angle::NonCopyable
int getShaderVersion() const { return mShaderVersion; }
sh::GLenum getShaderType() const { return mShaderType; }
ShShaderSpec getShaderSpec() const { return mShaderSpec; }
- int numErrors() const { return mDiagnostics.numErrors(); }
- TInfoSink &infoSink() { return mDiagnostics.infoSink(); }
- void error(const TSourceLoc &loc, const char *reason, const char *token,
- const char *extraInfo="");
- void warning(const TSourceLoc &loc, const char *reason, const char *token,
- const char *extraInfo="");
+ int numErrors() const { return mDiagnostics->numErrors(); }
+ void error(const TSourceLoc &loc, const char *reason, const char *token);
+ void warning(const TSourceLoc &loc, const char *reason, const char *token);
// If isError is false, a warning will be reported instead.
void outOfRangeError(bool isError,
const TSourceLoc &loc,
const char *reason,
- const char *token,
- const char *extraInfo = "");
+ const char *token);
- void recover();
- TIntermNode *getTreeRoot() const { return mTreeRoot; }
- void setTreeRoot(TIntermNode *treeRoot) { mTreeRoot = treeRoot; }
+ TIntermBlock *getTreeRoot() const { return mTreeRoot; }
+ void setTreeRoot(TIntermBlock *treeRoot) { mTreeRoot = treeRoot; }
bool getFragmentPrecisionHigh() const
{
@@ -103,10 +70,7 @@ class TParseContext : angle::NonCopyable
mFragmentPrecisionHighOnESSL1 = fragmentPrecisionHigh;
}
- void setLoopNestingLevel(int loopNestintLevel)
- {
- mLoopNestingLevel = loopNestintLevel;
- }
+ void setLoopNestingLevel(int loopNestintLevel) { mLoopNestingLevel = loopNestintLevel; }
void incrLoopNestingLevel() { ++mLoopNestingLevel; }
void decrLoopNestingLevel() { --mLoopNestingLevel; }
@@ -114,279 +78,580 @@ class TParseContext : angle::NonCopyable
void incrSwitchNestingLevel() { ++mSwitchNestingLevel; }
void decrSwitchNestingLevel() { --mSwitchNestingLevel; }
+ bool isComputeShaderLocalSizeDeclared() const { return mComputeShaderLocalSizeDeclared; }
+ sh::WorkGroupSize getComputeShaderLocalSize() const;
+
+ int getNumViews() const { return mNumViews; }
+
+ void enterFunctionDeclaration() { mDeclaringFunction = true; }
+
+ void exitFunctionDeclaration() { mDeclaringFunction = false; }
+
+ bool declaringFunction() const { return mDeclaringFunction; }
+
+ TIntermConstantUnion *addScalarLiteral(const TConstantUnion *constantUnion,
+ const TSourceLoc &line);
+
// This method is guaranteed to succeed, even if no variable with 'name' exists.
- const TVariable *getNamedVariable(const TSourceLoc &location, const TString *name, const TSymbol *symbol);
+ const TVariable *getNamedVariable(const TSourceLoc &location,
+ const TString *name,
+ const TSymbol *symbol);
TIntermTyped *parseVariableIdentifier(const TSourceLoc &location,
const TString *name,
const TSymbol *symbol);
- bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc &line);
+ // Look at a '.' field selector string and change it into offsets for a vector.
+ bool parseVectorFields(const TSourceLoc &line,
+ const TString &compString,
+ int vecSize,
+ TVector<int> *fieldOffsets);
- bool reservedErrorCheck(const TSourceLoc &line, const TString &identifier);
void assignError(const TSourceLoc &line, const char *op, TString left, TString right);
void unaryOpError(const TSourceLoc &line, const char *op, TString operand);
void binaryOpError(const TSourceLoc &line, const char *op, TString left, TString right);
- bool precisionErrorCheck(const TSourceLoc &line, TPrecision precision, TBasicType type);
- bool lValueErrorCheck(const TSourceLoc &line, const char *op, TIntermTyped*);
- bool constErrorCheck(TIntermTyped *node);
- bool integerErrorCheck(TIntermTyped *node, const char *token);
- bool globalErrorCheck(const TSourceLoc &line, bool global, const char *token);
- bool constructorErrorCheck(const TSourceLoc &line,
- TIntermNode *argumentsNode,
- TFunction &function,
- TOperator op,
- TType *type);
- bool arraySizeErrorCheck(const TSourceLoc &line, TIntermTyped *expr, int &size);
- bool arrayQualifierErrorCheck(const TSourceLoc &line, const TPublicType &type);
- bool arrayTypeErrorCheck(const TSourceLoc &line, const TPublicType &type);
- bool voidErrorCheck(const TSourceLoc &line, const TString &identifier, const TBasicType &type);
- bool boolErrorCheck(const TSourceLoc&, const TIntermTyped*);
- bool boolErrorCheck(const TSourceLoc&, const TPublicType&);
- bool samplerErrorCheck(const TSourceLoc &line, const TPublicType &pType, const char *reason);
- bool locationDeclaratorListCheck(const TSourceLoc &line, const TPublicType &pType);
- bool parameterSamplerErrorCheck(const TSourceLoc &line, TQualifier qualifier, const TType &type);
- bool paramErrorCheck(const TSourceLoc &line, TQualifier qualifier, TQualifier paramQualifier, TType *type);
- bool extensionErrorCheck(const TSourceLoc &line, const TString&);
- bool singleDeclarationErrorCheck(const TPublicType &publicType, const TSourceLoc &identifierLocation);
- bool layoutLocationErrorCheck(const TSourceLoc &location, const TLayoutQualifier &layoutQualifier);
- bool functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *);
- void es3InvariantErrorCheck(const TQualifier qualifier, const TSourceLoc &invariantLocation);
- void es3InputOutputTypeCheck(const TQualifier qualifier,
- const TPublicType &type,
- const TSourceLoc &qualifierLocation);
+ // Check functions - the ones that return bool return false if an error was generated.
+
+ bool checkIsNotReserved(const TSourceLoc &line, const TString &identifier);
+ void checkPrecisionSpecified(const TSourceLoc &line, TPrecision precision, TBasicType type);
+ bool checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node);
+ void checkIsConst(TIntermTyped *node);
+ void checkIsScalarInteger(TIntermTyped *node, const char *token);
+ bool checkIsAtGlobalLevel(const TSourceLoc &line, const char *token);
+ bool checkConstructorArguments(const TSourceLoc &line,
+ const TIntermSequence *arguments,
+ const TType &type);
+
+ // Returns a sanitized array size to use (the size is at least 1).
+ unsigned int checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr);
+ bool checkIsValidQualifierForArray(const TSourceLoc &line, const TPublicType &elementQualifier);
+ bool checkArrayElementIsNotArray(const TSourceLoc &line, const TPublicType &elementType);
+ bool checkIsNonVoid(const TSourceLoc &line, const TString &identifier, const TBasicType &type);
+ bool checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type);
+ void checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType);
+ bool checkIsNotOpaqueType(const TSourceLoc &line,
+ const TTypeSpecifierNonArray &pType,
+ const char *reason);
+ void checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line, const TPublicType &pType);
+ void checkLocationIsNotSpecified(const TSourceLoc &location,
+ const TLayoutQualifier &layoutQualifier);
+ void checkStd430IsForShaderStorageBlock(const TSourceLoc &location,
+ const TLayoutBlockStorage &blockStorage,
+ const TQualifier &qualifier);
+ void checkIsParameterQualifierValid(const TSourceLoc &line,
+ const TTypeQualifierBuilder &typeQualifierBuilder,
+ TType *type);
+
+ // Check if at least one of the specified extensions can be used, and generate error/warning as
+ // appropriate according to the spec.
+ // This function is only needed for a few different small constant sizes of extension array, and
+ // we want to avoid unnecessary dynamic allocations. That's why checkCanUseOneOfExtensions is a
+ // template function rather than one taking a vector.
+ template <size_t size>
+ bool checkCanUseOneOfExtensions(const TSourceLoc &line,
+ const std::array<TExtension, size> &extensions);
+ bool checkCanUseExtension(const TSourceLoc &line, TExtension extension);
+
+ // Done for all declarations, whether empty or not.
+ void declarationQualifierErrorCheck(const sh::TQualifier qualifier,
+ const sh::TLayoutQualifier &layoutQualifier,
+ const TSourceLoc &location);
+ // Done for the first non-empty declarator in a declaration.
+ void nonEmptyDeclarationErrorCheck(const TPublicType &publicType,
+ const TSourceLoc &identifierLocation);
+ // Done only for empty declarations.
+ void emptyDeclarationErrorCheck(const TType &type, const TSourceLoc &location);
+
+ void checkLayoutQualifierSupported(const TSourceLoc &location,
+ const TString &layoutQualifierName,
+ int versionRequired);
+ bool checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
+ const TLayoutQualifier &layoutQualifier);
+ void functionCallRValueLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *fnCall);
+ void checkInvariantVariableQualifier(bool invariant,
+ const TQualifier qualifier,
+ const TSourceLoc &invariantLocation);
+ void checkInputOutputTypeIsValidES3(const TQualifier qualifier,
+ const TPublicType &type,
+ const TSourceLoc &qualifierLocation);
+ void checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier);
const TPragma &pragma() const { return mDirectiveHandler.pragma(); }
- const TExtensionBehavior &extensionBehavior() const { return mDirectiveHandler.extensionBehavior(); }
- bool supportsExtension(const char *extension);
- bool isExtensionEnabled(const char *extension) const;
+ const TExtensionBehavior &extensionBehavior() const
+ {
+ return mDirectiveHandler.extensionBehavior();
+ }
+
+ bool isExtensionEnabled(TExtension extension) const;
void handleExtensionDirective(const TSourceLoc &loc, const char *extName, const char *behavior);
- void handlePragmaDirective(const TSourceLoc &loc, const char *name, const char *value, bool stdgl);
+ void handlePragmaDirective(const TSourceLoc &loc,
+ const char *name,
+ const char *value,
+ bool stdgl);
- bool containsSampler(const TType &type);
- const TFunction* findFunction(
- const TSourceLoc &line, TFunction *pfnCall, int inputShaderVersion, bool *builtIn = 0);
+ // Returns true on success. *initNode may still be nullptr on success in case the initialization
+ // is not needed in the AST.
bool executeInitializer(const TSourceLoc &line,
const TString &identifier,
- const TPublicType &pType,
+ TType type,
TIntermTyped *initializer,
- TIntermNode **intermNode);
-
- TPublicType addFullySpecifiedType(TQualifier qualifier,
- bool invariant,
- TLayoutQualifier layoutQualifier,
+ TIntermBinary **initNode);
+ TIntermNode *addConditionInitializer(const TPublicType &pType,
+ const TString &identifier,
+ TIntermTyped *initializer,
+ const TSourceLoc &loc);
+ TIntermNode *addLoop(TLoopType type,
+ TIntermNode *init,
+ TIntermNode *cond,
+ TIntermTyped *expr,
+ TIntermNode *body,
+ const TSourceLoc &loc);
+
+ // For "if" test nodes. There are three children: a condition, a true path, and a false path.
+ // The two paths are in TIntermNodePair code.
+ TIntermNode *addIfElse(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &loc);
+
+ void addFullySpecifiedType(TPublicType *typeSpecifier);
+ TPublicType addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
const TPublicType &typeSpecifier);
- TIntermAggregate *parseSingleDeclaration(TPublicType &publicType,
- const TSourceLoc &identifierOrTypeLocation,
- const TString &identifier);
- TIntermAggregate *parseSingleArrayDeclaration(TPublicType &publicType,
- const TSourceLoc &identifierLocation,
- const TString &identifier,
- const TSourceLoc &indexLocation,
- TIntermTyped *indexExpression);
- TIntermAggregate *parseSingleInitDeclaration(const TPublicType &publicType,
- const TSourceLoc &identifierLocation,
- const TString &identifier,
- const TSourceLoc &initLocation,
- TIntermTyped *initializer);
+ TIntermDeclaration *parseSingleDeclaration(TPublicType &publicType,
+ const TSourceLoc &identifierOrTypeLocation,
+ const TString &identifier);
+ TIntermDeclaration *parseSingleArrayDeclaration(TPublicType &elementType,
+ const TSourceLoc &identifierLocation,
+ const TString &identifier,
+ const TSourceLoc &indexLocation,
+ const TVector<unsigned int> &arraySizes);
+ TIntermDeclaration *parseSingleInitDeclaration(const TPublicType &publicType,
+ const TSourceLoc &identifierLocation,
+ const TString &identifier,
+ const TSourceLoc &initLocation,
+ TIntermTyped *initializer);
// Parse a declaration like "type a[n] = initializer"
// Note that this does not apply to declarations like "type[n] a = initializer"
- TIntermAggregate *parseSingleArrayInitDeclaration(TPublicType &publicType,
- const TSourceLoc &identifierLocation,
- const TString &identifier,
- const TSourceLoc &indexLocation,
- TIntermTyped *indexExpression,
- const TSourceLoc &initLocation,
- TIntermTyped *initializer);
-
- TIntermAggregate *parseInvariantDeclaration(const TSourceLoc &invariantLoc,
- const TSourceLoc &identifierLoc,
- const TString *identifier,
- const TSymbol *symbol);
-
- TIntermAggregate *parseDeclarator(TPublicType &publicType,
- TIntermAggregate *aggregateDeclaration,
- const TSourceLoc &identifierLocation,
- const TString &identifier);
- TIntermAggregate *parseArrayDeclarator(TPublicType &publicType,
- TIntermAggregate *aggregateDeclaration,
- const TSourceLoc &identifierLocation,
- const TString &identifier,
- const TSourceLoc &arrayLocation,
- TIntermTyped *indexExpression);
- TIntermAggregate *parseInitDeclarator(const TPublicType &publicType,
- TIntermAggregate *aggregateDeclaration,
- const TSourceLoc &identifierLocation,
- const TString &identifier,
- const TSourceLoc &initLocation,
- TIntermTyped *initializer);
+ TIntermDeclaration *parseSingleArrayInitDeclaration(TPublicType &elementType,
+ const TSourceLoc &identifierLocation,
+ const TString &identifier,
+ const TSourceLoc &indexLocation,
+ const TVector<unsigned int> &arraySizes,
+ const TSourceLoc &initLocation,
+ TIntermTyped *initializer);
+
+ TIntermInvariantDeclaration *parseInvariantDeclaration(
+ const TTypeQualifierBuilder &typeQualifierBuilder,
+ const TSourceLoc &identifierLoc,
+ const TString *identifier,
+ const TSymbol *symbol);
+
+ void parseDeclarator(TPublicType &publicType,
+ const TSourceLoc &identifierLocation,
+ const TString &identifier,
+ TIntermDeclaration *declarationOut);
+ void parseArrayDeclarator(TPublicType &elementType,
+ const TSourceLoc &identifierLocation,
+ const TString &identifier,
+ const TSourceLoc &arrayLocation,
+ const TVector<unsigned int> &arraySizes,
+ TIntermDeclaration *declarationOut);
+ void parseInitDeclarator(const TPublicType &publicType,
+ const TSourceLoc &identifierLocation,
+ const TString &identifier,
+ const TSourceLoc &initLocation,
+ TIntermTyped *initializer,
+ TIntermDeclaration *declarationOut);
// Parse a declarator like "a[n] = initializer"
- TIntermAggregate *parseArrayInitDeclarator(const TPublicType &publicType,
- TIntermAggregate *aggregateDeclaration,
- const TSourceLoc &identifierLocation,
- const TString &identifier,
- const TSourceLoc &indexLocation,
- TIntermTyped *indexExpression,
- const TSourceLoc &initLocation,
- TIntermTyped *initializer);
-
- void parseGlobalLayoutQualifier(const TPublicType &typeQualifier);
- TIntermAggregate *addFunctionPrototypeDeclaration(const TFunction &function,
- const TSourceLoc &location);
- TIntermAggregate *addFunctionDefinition(const TFunction &function,
- TIntermAggregate *functionPrototype,
- TIntermAggregate *functionBody,
- const TSourceLoc &location);
- void parseFunctionPrototype(const TSourceLoc &location,
- TFunction *function,
- TIntermAggregate **aggregateOut);
- TFunction *parseFunctionDeclarator(const TSourceLoc &location,
- TFunction *function);
+ void parseArrayInitDeclarator(const TPublicType &elementType,
+ const TSourceLoc &identifierLocation,
+ const TString &identifier,
+ const TSourceLoc &indexLocation,
+ const TVector<unsigned int> &arraySizes,
+ const TSourceLoc &initLocation,
+ TIntermTyped *initializer,
+ TIntermDeclaration *declarationOut);
+
+ TIntermNode *addEmptyStatement(const TSourceLoc &location);
+
+ void parseDefaultPrecisionQualifier(const TPrecision precision,
+ const TPublicType &type,
+ const TSourceLoc &loc);
+ void parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder);
+
+ TIntermFunctionPrototype *addFunctionPrototypeDeclaration(const TFunction &parsedFunction,
+ const TSourceLoc &location);
+ TIntermFunctionDefinition *addFunctionDefinition(TIntermFunctionPrototype *functionPrototype,
+ TIntermBlock *functionBody,
+ const TSourceLoc &location);
+ void parseFunctionDefinitionHeader(const TSourceLoc &location,
+ TFunction **function,
+ TIntermFunctionPrototype **prototypeOut);
+ TFunction *parseFunctionDeclarator(const TSourceLoc &location, TFunction *function);
+ TFunction *parseFunctionHeader(const TPublicType &type,
+ const TString *name,
+ const TSourceLoc &location);
+ TFunction *addNonConstructorFunc(const TString *name, const TSourceLoc &loc);
TFunction *addConstructorFunc(const TPublicType &publicType);
- TIntermTyped *addConstructor(TIntermNode *arguments,
- TType *type,
- TOperator op,
- TFunction *fnCall,
- const TSourceLoc &line);
- TIntermTyped *addConstVectorNode(TVectorFields &fields,
- TIntermConstantUnion *node,
- const TSourceLoc &line,
- bool outOfRangeIndexIsError);
- TIntermTyped *addConstMatrixNode(int index,
- TIntermConstantUnion *node,
- const TSourceLoc &line,
- bool outOfRangeIndexIsError);
- TIntermTyped *addConstArrayNode(int index,
- TIntermConstantUnion *node,
- const TSourceLoc &line,
- bool outOfRangeIndexIsError);
- TIntermTyped *addConstStruct(
- const TString &identifier, TIntermTyped *node, const TSourceLoc& line);
+ TParameter parseParameterDeclarator(const TPublicType &publicType,
+ const TString *name,
+ const TSourceLoc &nameLoc);
+
+ TParameter parseParameterArrayDeclarator(const TString *name,
+ const TSourceLoc &nameLoc,
+ const TVector<unsigned int> &arraySizes,
+ const TSourceLoc &arrayLoc,
+ TPublicType *elementType);
+
TIntermTyped *addIndexExpression(TIntermTyped *baseExpression,
- const TSourceLoc& location,
+ const TSourceLoc &location,
TIntermTyped *indexExpression);
- TIntermTyped* addFieldSelectionExpression(TIntermTyped *baseExpression,
+ TIntermTyped *addFieldSelectionExpression(TIntermTyped *baseExpression,
const TSourceLoc &dotLocation,
const TString &fieldString,
const TSourceLoc &fieldLocation);
- TFieldList *addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList);
- TPublicType addStructure(const TSourceLoc &structLine,
- const TSourceLoc &nameLine,
- const TString *structName,
- TFieldList *fieldList);
+ // Parse declarator for a single field
+ TField *parseStructDeclarator(TString *identifier, const TSourceLoc &loc);
+ TField *parseStructArrayDeclarator(TString *identifier,
+ const TSourceLoc &loc,
+ const TVector<unsigned int> &arraySizes,
+ const TSourceLoc &arraySizeLoc);
- TIntermAggregate* addInterfaceBlock(const TPublicType &typeQualifier,
+ void checkDoesNotHaveDuplicateFieldName(const TFieldList::const_iterator begin,
+ const TFieldList::const_iterator end,
+ const TString &name,
+ const TSourceLoc &location);
+ TFieldList *addStructFieldList(TFieldList *fields, const TSourceLoc &location);
+ TFieldList *combineStructFieldLists(TFieldList *processedFields,
+ const TFieldList *newlyAddedFields,
+ const TSourceLoc &location);
+ TFieldList *addStructDeclaratorListWithQualifiers(
+ const TTypeQualifierBuilder &typeQualifierBuilder,
+ TPublicType *typeSpecifier,
+ TFieldList *fieldList);
+ TFieldList *addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList);
+ TTypeSpecifierNonArray addStructure(const TSourceLoc &structLine,
const TSourceLoc &nameLine,
- const TString &blockName,
- TFieldList *fieldList,
- const TString *instanceName,
- const TSourceLoc &instanceLine,
- TIntermTyped *arrayIndex,
- const TSourceLoc& arrayIndexLine);
-
- TLayoutQualifier parseLayoutQualifier(
- const TString &qualifierType, const TSourceLoc &qualifierTypeLine);
+ const TString *structName,
+ TFieldList *fieldList);
+
+ TIntermDeclaration *addInterfaceBlock(const TTypeQualifierBuilder &typeQualifierBuilder,
+ const TSourceLoc &nameLine,
+ const TString &blockName,
+ TFieldList *fieldList,
+ const TString *instanceName,
+ const TSourceLoc &instanceLine,
+ TIntermTyped *arrayIndex,
+ const TSourceLoc &arrayIndexLine);
+
+ void parseLocalSize(const TString &qualifierType,
+ const TSourceLoc &qualifierTypeLine,
+ int intValue,
+ const TSourceLoc &intValueLine,
+ const std::string &intValueString,
+ size_t index,
+ sh::WorkGroupSize *localSize);
+ void parseNumViews(int intValue,
+ const TSourceLoc &intValueLine,
+ const std::string &intValueString,
+ int *numViews);
+ void parseInvocations(int intValue,
+ const TSourceLoc &intValueLine,
+ const std::string &intValueString,
+ int *numInvocations);
+ void parseMaxVertices(int intValue,
+ const TSourceLoc &intValueLine,
+ const std::string &intValueString,
+ int *numMaxVertices);
+ TLayoutQualifier parseLayoutQualifier(const TString &qualifierType,
+ const TSourceLoc &qualifierTypeLine);
TLayoutQualifier parseLayoutQualifier(const TString &qualifierType,
const TSourceLoc &qualifierTypeLine,
- const TString &intValueString,
int intValue,
const TSourceLoc &intValueLine);
- TLayoutQualifier joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier rightQualifier);
- TPublicType joinInterpolationQualifiers(const TSourceLoc &interpolationLoc, TQualifier interpolationQualifier,
- const TSourceLoc &storageLoc, TQualifier storageQualifier);
+ TTypeQualifierBuilder *createTypeQualifierBuilder(const TSourceLoc &loc);
+ TStorageQualifierWrapper *parseGlobalStorageQualifier(TQualifier qualifier,
+ const TSourceLoc &loc);
+ TStorageQualifierWrapper *parseVaryingQualifier(const TSourceLoc &loc);
+ TStorageQualifierWrapper *parseInQualifier(const TSourceLoc &loc);
+ TStorageQualifierWrapper *parseOutQualifier(const TSourceLoc &loc);
+ TStorageQualifierWrapper *parseInOutQualifier(const TSourceLoc &loc);
+ TLayoutQualifier joinLayoutQualifiers(TLayoutQualifier leftQualifier,
+ TLayoutQualifier rightQualifier,
+ const TSourceLoc &rightQualifierLocation);
// Performs an error check for embedded struct declarations.
- // Returns true if an error was raised due to the declaration of
- // this struct.
- bool enterStructDeclaration(const TSourceLoc &line, const TString &identifier);
+ void enterStructDeclaration(const TSourceLoc &line, const TString &identifier);
void exitStructDeclaration();
- bool structNestingErrorCheck(const TSourceLoc &line, const TField &field);
+ void checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field);
- TIntermSwitch *addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &loc);
+ TIntermSwitch *addSwitch(TIntermTyped *init,
+ TIntermBlock *statementList,
+ const TSourceLoc &loc);
TIntermCase *addCase(TIntermTyped *condition, const TSourceLoc &loc);
TIntermCase *addDefault(const TSourceLoc &loc);
TIntermTyped *addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc);
TIntermTyped *addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &loc);
- TIntermTyped *addBinaryMath(
- TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
- TIntermTyped *addBinaryMathBooleanResult(
- TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
- TIntermTyped *addAssign(
- TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
+ TIntermTyped *addBinaryMath(TOperator op,
+ TIntermTyped *left,
+ TIntermTyped *right,
+ const TSourceLoc &loc);
+ TIntermTyped *addBinaryMathBooleanResult(TOperator op,
+ TIntermTyped *left,
+ TIntermTyped *right,
+ const TSourceLoc &loc);
+ TIntermTyped *addAssign(TOperator op,
+ TIntermTyped *left,
+ TIntermTyped *right,
+ const TSourceLoc &loc);
TIntermTyped *addComma(TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc);
- TIntermBranch *addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc);
+ TIntermBranch *addBranch(TOperator op, TIntermTyped *expression, const TSourceLoc &loc);
+ void checkTextureGather(TIntermAggregate *functionCall);
void checkTextureOffsetConst(TIntermAggregate *functionCall);
+ void checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall);
+ void checkImageMemoryAccessForUserDefinedFunctions(const TFunction *functionDefinition,
+ const TIntermAggregate *functionCall);
+ void checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall);
+ TIntermSequence *createEmptyArgumentsList();
+
+ // fnCall is only storing the built-in op, and function name or constructor type. arguments
+ // has the arguments.
TIntermTyped *addFunctionCallOrMethod(TFunction *fnCall,
- TIntermNode *paramNode,
+ TIntermSequence *arguments,
TIntermNode *thisNode,
- const TSourceLoc &loc,
- bool *fatalError);
+ const TSourceLoc &loc);
- TIntermTyped *addTernarySelection(
- TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &line);
+ TIntermTyped *addTernarySelection(TIntermTyped *cond,
+ TIntermTyped *trueExpression,
+ TIntermTyped *falseExpression,
+ const TSourceLoc &line);
- // TODO(jmadill): make these private
- TIntermediate &intermediate; // to hold and build a parse tree
+ int getGeometryShaderMaxVertices() const { return mGeometryShaderMaxVertices; }
+ int getGeometryShaderInvocations() const
+ {
+ return (mGeometryShaderInvocations > 0) ? mGeometryShaderInvocations : 1;
+ }
+ TLayoutPrimitiveType getGeometryShaderInputPrimitiveType() const
+ {
+ return mGeometryShaderInputPrimitiveType;
+ }
+ TLayoutPrimitiveType getGeometryShaderOutputPrimitiveType() const
+ {
+ return mGeometryShaderOutputPrimitiveType;
+ }
+
+ // TODO(jmadill): make this private
TSymbolTable &symbolTable; // symbol table that goes with the language currently being parsed
private:
- bool declareVariable(const TSourceLoc &line, const TString &identifier, const TType &type, TVariable **variable);
-
- bool nonInitErrorCheck(const TSourceLoc &line, const TString &identifier, TPublicType *type);
-
- TIntermTyped *addBinaryMathInternal(
- TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
- TIntermTyped *createAssign(
- TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
- // The funcReturnType parameter is expected to be non-null when the operation is a built-in function.
- // It is expected to be null for other unary operators.
- TIntermTyped *createUnaryMath(
- TOperator op, TIntermTyped *child, const TSourceLoc &loc, const TType *funcReturnType);
+ class AtomicCounterBindingState;
+ constexpr static size_t kAtomicCounterSize = 4;
+ // UNIFORM_ARRAY_STRIDE for atomic counter arrays is an implementation-dependent value which
+ // can be queried after a program is linked according to ES 3.10 section 7.7.1. This is
+ // controversial with the offset inheritance as described in ESSL 3.10 section 4.4.6. Currently
+ // we treat it as always 4 in favour of the original interpretation in
+ // "ARB_shader_atomic_counters".
+ // TODO(jie.a.chen@intel.com): Double check this once the spec vagueness is resolved.
+ // Note that there may be tests in AtomicCounter_test that will need to be updated as well.
+ constexpr static size_t kAtomicCounterArrayStride = 4;
+
+ // Returns a clamped index. If it prints out an error message, the token is "[]".
+ int checkIndexLessThan(bool outOfRangeIndexIsError,
+ const TSourceLoc &location,
+ int index,
+ int arraySize,
+ const char *reason);
+
+ bool declareVariable(const TSourceLoc &line,
+ const TString &identifier,
+ const TType &type,
+ TVariable **variable);
+
+ void checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
+ const TString &identifier,
+ TType *type);
+
+ TParameter parseParameterDeclarator(TType *type,
+ const TString *name,
+ const TSourceLoc &nameLoc);
+
+ bool checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
+ const TPublicType &elementType);
+ // Done for all atomic counter declarations, whether empty or not.
+ void atomicCounterQualifierErrorCheck(const TPublicType &publicType,
+ const TSourceLoc &location);
+
+ // Assumes that multiplication op has already been set based on the types.
+ bool isMultiplicationTypeCombinationValid(TOperator op, const TType &left, const TType &right);
+
+ void checkOutParameterIsNotOpaqueType(const TSourceLoc &line,
+ TQualifier qualifier,
+ const TType &type);
+
+ void checkInternalFormatIsNotSpecified(const TSourceLoc &location,
+ TLayoutImageInternalFormat internalFormat);
+ void checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier,
+ const TSourceLoc &location);
+ void checkAtomicCounterOffsetDoesNotOverlap(bool forceAppend,
+ const TSourceLoc &loc,
+ TType *type);
+ void checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type);
+ void checkBindingIsNotSpecified(const TSourceLoc &location, int binding);
+ void checkOffsetIsNotSpecified(const TSourceLoc &location, int offset);
+ void checkImageBindingIsValid(const TSourceLoc &location,
+ int binding,
+ int arrayTotalElementCount);
+ void checkSamplerBindingIsValid(const TSourceLoc &location,
+ int binding,
+ int arrayTotalElementCount);
+ void checkBlockBindingIsValid(const TSourceLoc &location,
+ const TQualifier &qualifier,
+ int binding,
+ int arraySize);
+ void checkAtomicCounterBindingIsValid(const TSourceLoc &location, int binding);
+
+ void checkUniformLocationInRange(const TSourceLoc &location,
+ int objectLocationCount,
+ const TLayoutQualifier &layoutQualifier);
+
+ void checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv);
+
+ bool checkUnsizedArrayConstructorArgumentDimensionality(TIntermSequence *arguments,
+ TType type,
+ const TSourceLoc &line);
+
+ // Will set the size of the outermost array according to geometry shader input layout.
+ void checkGeometryShaderInputAndSetArraySize(const TSourceLoc &location,
+ const char *token,
+ TType *type);
+
+ // Will size any unsized array type so unsized arrays won't need to be taken into account
+ // further along the line in parsing.
+ void checkIsNotUnsizedArray(const TSourceLoc &line,
+ const char *errorMessage,
+ const char *token,
+ TType *arrayType);
+
+ TIntermTyped *addBinaryMathInternal(TOperator op,
+ TIntermTyped *left,
+ TIntermTyped *right,
+ const TSourceLoc &loc);
+ TIntermBinary *createAssign(TOperator op,
+ TIntermTyped *left,
+ TIntermTyped *right,
+ const TSourceLoc &loc);
+ TIntermTyped *createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc);
+
+ TIntermTyped *addMethod(TFunction *fnCall,
+ TIntermSequence *arguments,
+ TIntermNode *thisNode,
+ const TSourceLoc &loc);
+ TIntermTyped *addConstructor(TIntermSequence *arguments,
+ TType type,
+ const TSourceLoc &line);
+ TIntermTyped *addNonConstructorFunctionCall(TFunction *fnCall,
+ TIntermSequence *arguments,
+ const TSourceLoc &loc);
// Return true if the checks pass
- bool binaryOpCommonCheck(
- TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
-
- // Set to true when the last/current declarator list was started with an empty declaration.
- bool mDeferredSingleDeclarationErrorCheck;
-
- sh::GLenum mShaderType; // vertex or fragment language (future: pack or unpack)
- ShShaderSpec mShaderSpec; // The language specification compiler conforms to - GLES2 or WebGL.
+ bool binaryOpCommonCheck(TOperator op,
+ TIntermTyped *left,
+ TIntermTyped *right,
+ const TSourceLoc &loc);
+
+ TIntermFunctionPrototype *createPrototypeNodeFromFunction(const TFunction &function,
+ const TSourceLoc &location,
+ bool insertParametersToSymbolTable);
+
+ void setAtomicCounterBindingDefaultOffset(const TPublicType &declaration,
+ const TSourceLoc &location);
+
+ bool checkPrimitiveTypeMatchesTypeQualifier(const TTypeQualifier &typeQualifier);
+ bool parseGeometryShaderInputLayoutQualifier(const TTypeQualifier &typeQualifier);
+ bool parseGeometryShaderOutputLayoutQualifier(const TTypeQualifier &typeQualifier);
+ void setGeometryShaderInputArraySize(unsigned int inputArraySize, const TSourceLoc &line);
+
+ // Set to true when the last/current declarator list was started with an empty declaration. The
+ // non-empty declaration error check will need to be performed if the empty declaration is
+ // followed by a declarator.
+ bool mDeferredNonEmptyDeclarationErrorCheck;
+
+ sh::GLenum mShaderType; // vertex or fragment language (future: pack or unpack)
+ ShShaderSpec mShaderSpec; // The language specification compiler conforms to - GLES2 or WebGL.
+ ShCompileOptions mCompileOptions; // Options passed to TCompiler
int mShaderVersion;
- TIntermNode *mTreeRoot; // root of parse tree being created
- int mLoopNestingLevel; // 0 if outside all loops
- int mStructNestingLevel; // incremented while parsing a struct declaration
- int mSwitchNestingLevel; // 0 if outside all switch statements
- const TType *mCurrentFunctionType; // the return type of the function that's currently being parsed
- bool mFunctionReturnsValue; // true if a non-void function has a return
- bool mChecksPrecisionErrors; // true if an error will be generated when a variable is declared without precision, explicit or implicit.
+ TIntermBlock *mTreeRoot; // root of parse tree being created
+ int mLoopNestingLevel; // 0 if outside all loops
+ int mStructNestingLevel; // incremented while parsing a struct declaration
+ int mSwitchNestingLevel; // 0 if outside all switch statements
+ const TType
+ *mCurrentFunctionType; // the return type of the function that's currently being parsed
+ bool mFunctionReturnsValue; // true if a non-void function has a return
+ bool mChecksPrecisionErrors; // true if an error will be generated when a variable is declared
+ // without precision, explicit or implicit.
bool mFragmentPrecisionHighOnESSL1; // true if highp precision is supported when compiling
// ESSL1.
- TLayoutMatrixPacking mDefaultMatrixPacking;
- TLayoutBlockStorage mDefaultBlockStorage;
+ TLayoutMatrixPacking mDefaultUniformMatrixPacking;
+ TLayoutBlockStorage mDefaultUniformBlockStorage;
+ TLayoutMatrixPacking mDefaultBufferMatrixPacking;
+ TLayoutBlockStorage mDefaultBufferBlockStorage;
TString mHashErrMsg;
- TDiagnostics mDiagnostics;
+ TDiagnostics *mDiagnostics;
TDirectiveHandler mDirectiveHandler;
pp::Preprocessor mPreprocessor;
void *mScanner;
- bool mUsesFragData; // track if we are using both gl_FragData and gl_FragColor
+ bool mUsesFragData; // track if we are using both gl_FragData and gl_FragColor
bool mUsesFragColor;
bool mUsesSecondaryOutputs; // Track if we are using either gl_SecondaryFragData or
// gl_Secondary FragColor or both.
int mMinProgramTexelOffset;
int mMaxProgramTexelOffset;
+
+ int mMinProgramTextureGatherOffset;
+ int mMaxProgramTextureGatherOffset;
+
+ // keep track of local group size declared in layout. It should be declared only once.
+ bool mComputeShaderLocalSizeDeclared;
+ sh::WorkGroupSize mComputeShaderLocalSize;
+ // keep track of number of views declared in layout.
+ int mNumViews;
+ int mMaxNumViews;
+ int mMaxImageUnits;
+ int mMaxCombinedTextureImageUnits;
+ int mMaxUniformLocations;
+ int mMaxUniformBufferBindings;
+ int mMaxAtomicCounterBindings;
+ int mMaxShaderStorageBufferBindings;
+
+ // keeps track whether we are declaring / defining a function
+ bool mDeclaringFunction;
+
+ // Track the state of each atomic counter binding.
+ std::map<int, AtomicCounterBindingState> mAtomicCounterBindingStates;
+
+ // Track the geometry shader global parameters declared in layout.
+ TLayoutPrimitiveType mGeometryShaderInputPrimitiveType;
+ TLayoutPrimitiveType mGeometryShaderOutputPrimitiveType;
+ int mGeometryShaderInvocations;
+ int mGeometryShaderMaxVertices;
+ int mMaxGeometryShaderInvocations;
+ int mMaxGeometryShaderMaxVertices;
+
+ // Track if all input array sizes are same and matches the latter input primitive declaration.
+ unsigned int mGeometryShaderInputArraySize;
};
-int PaParseStrings(
- size_t count, const char *const string[], const int length[], TParseContext *context);
+int PaParseStrings(size_t count,
+ const char *const string[],
+ const int length[],
+ TParseContext *context);
+
+} // namespace sh
-#endif // COMPILER_TRANSLATOR_PARSECONTEXT_H_
+#endif // COMPILER_TRANSLATOR_PARSECONTEXT_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp
index 887cb66504..0f1cd8b5c9 100644
--- a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp
@@ -6,16 +6,16 @@
#include "compiler/translator/PoolAlloc.h"
-#include "compiler/translator/InitializeGlobals.h"
-
-#include "common/platform.h"
-#include "common/angleutils.h"
-#include "common/tls.h"
-
#include <stdint.h>
#include <stdio.h>
#include <assert.h>
+#include "common/angleutils.h"
+#include "common/debug.h"
+#include "common/platform.h"
+#include "common/tls.h"
+#include "compiler/translator/InitializeGlobals.h"
+
TLSIndex PoolIndex = TLS_INVALID_INDEX;
bool InitializePoolIndex()
@@ -34,13 +34,13 @@ void FreePoolIndex()
PoolIndex = TLS_INVALID_INDEX;
}
-TPoolAllocator* GetGlobalPoolAllocator()
+TPoolAllocator *GetGlobalPoolAllocator()
{
assert(PoolIndex != TLS_INVALID_INDEX);
- return static_cast<TPoolAllocator*>(GetTLSValue(PoolIndex));
+ return static_cast<TPoolAllocator *>(GetTLSValue(PoolIndex));
}
-void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator)
+void SetGlobalPoolAllocator(TPoolAllocator *poolAllocator)
{
assert(PoolIndex != TLS_INVALID_INDEX);
SetTLSValue(PoolIndex, poolAllocator);
@@ -50,56 +50,66 @@ void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator)
// Implement the functionality of the TPoolAllocator class, which
// is documented in PoolAlloc.h.
//
-TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) :
- pageSize(growthIncrement),
- alignment(allocationAlignment),
- freeList(0),
- inUseList(0),
- numCalls(0),
- totalBytes(0)
+TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment)
+ : alignment(allocationAlignment),
+#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
+ pageSize(growthIncrement),
+ freeList(0),
+ inUseList(0),
+ numCalls(0),
+ totalBytes(0),
+#endif
+ mLocked(false)
{
//
- // Don't allow page sizes we know are smaller than all common
- // OS page sizes.
- //
- if (pageSize < 4*1024)
- pageSize = 4*1024;
-
- //
- // A large currentPageOffset indicates a new page needs to
- // be obtained to allocate memory.
- //
- currentPageOffset = pageSize;
-
- //
// Adjust alignment to be at least pointer aligned and
// power of 2.
//
- size_t minAlign = sizeof(void*);
+ size_t minAlign = sizeof(void *);
alignment &= ~(minAlign - 1);
if (alignment < minAlign)
alignment = minAlign;
- size_t a = 1;
+ size_t a = 1;
while (a < alignment)
a <<= 1;
- alignment = a;
+ alignment = a;
alignmentMask = a - 1;
+#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
+ //
+ // Don't allow page sizes we know are smaller than all common
+ // OS page sizes.
+ //
+ if (pageSize < 4 * 1024)
+ pageSize = 4 * 1024;
+
+ //
+ // A large currentPageOffset indicates a new page needs to
+ // be obtained to allocate memory.
+ //
+ currentPageOffset = pageSize;
+
//
// Align header skip
//
headerSkip = minAlign;
- if (headerSkip < sizeof(tHeader)) {
+ if (headerSkip < sizeof(tHeader))
+ {
headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask;
}
+#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
+ mStack.push_back({});
+#endif
}
TPoolAllocator::~TPoolAllocator()
{
- while (inUseList) {
- tHeader* next = inUseList->nextPage;
+#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
+ while (inUseList)
+ {
+ tHeader *next = inUseList->nextPage;
inUseList->~tHeader();
- delete [] reinterpret_cast<char*>(inUseList);
+ delete[] reinterpret_cast<char *>(inUseList);
inUseList = next;
}
@@ -107,11 +117,22 @@ TPoolAllocator::~TPoolAllocator()
// here, because we did it already when the block was
// placed into the free list.
//
- while (freeList) {
- tHeader* next = freeList->nextPage;
- delete [] reinterpret_cast<char*>(freeList);
+ while (freeList)
+ {
+ tHeader *next = freeList->nextPage;
+ delete[] reinterpret_cast<char *>(freeList);
freeList = next;
}
+#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
+ for (auto &allocs : mStack)
+ {
+ for (auto alloc : allocs)
+ {
+ free(alloc);
+ }
+ }
+ mStack.clear();
+#endif
}
// Support MSVC++ 6.0
@@ -120,28 +141,32 @@ const unsigned char TAllocation::guardBlockEndVal = 0xfe;
const unsigned char TAllocation::userDataFill = 0xcd;
#ifdef GUARD_BLOCKS
- const size_t TAllocation::guardBlockSize = 16;
+const size_t TAllocation::guardBlockSize = 16;
#else
- const size_t TAllocation::guardBlockSize = 0;
+const size_t TAllocation::guardBlockSize = 0;
#endif
//
// Check a single guard block for damage
//
-void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const
+void TAllocation::checkGuardBlock(unsigned char *blockMem,
+ unsigned char val,
+ const char *locText) const
{
#ifdef GUARD_BLOCKS
- for (size_t x = 0; x < guardBlockSize; x++) {
- if (blockMem[x] != val) {
+ for (size_t x = 0; x < guardBlockSize; x++)
+ {
+ if (blockMem[x] != val)
+ {
char assertMsg[80];
- // We don't print the assert message. It's here just to be helpful.
+// We don't print the assert message. It's here just to be helpful.
#if defined(_MSC_VER)
- snprintf(assertMsg, sizeof(assertMsg), "PoolAlloc: Damage %s %Iu byte allocation at 0x%p\n",
- locText, size, data());
+ snprintf(assertMsg, sizeof(assertMsg),
+ "PoolAlloc: Damage %s %Iu byte allocation at 0x%p\n", locText, size, data());
#else
- snprintf(assertMsg, sizeof(assertMsg), "PoolAlloc: Damage %s %zu byte allocation at 0x%p\n",
- locText, size, data());
+ snprintf(assertMsg, sizeof(assertMsg),
+ "PoolAlloc: Damage %s %zu byte allocation at 0x%p\n", locText, size, data());
#endif
assert(0 && "PoolAlloc: Damage in guard block");
}
@@ -149,17 +174,20 @@ void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, co
#endif
}
-
void TPoolAllocator::push()
{
- tAllocState state = { currentPageOffset, inUseList };
+#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
+ tAllocState state = {currentPageOffset, inUseList};
+
+ mStack.push_back(state);
- stack.push_back(state);
-
//
// Indicate there is no current page to allocate from.
//
currentPageOffset = pageSize;
+#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
+ mStack.push_back({});
+#endif
}
//
@@ -171,27 +199,37 @@ void TPoolAllocator::push()
//
void TPoolAllocator::pop()
{
- if (stack.size() < 1)
+ if (mStack.size() < 1)
return;
- tHeader* page = stack.back().page;
- currentPageOffset = stack.back().offset;
+#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
+ tHeader *page = mStack.back().page;
+ currentPageOffset = mStack.back().offset;
- while (inUseList != page) {
+ while (inUseList != page)
+ {
// invoke destructor to free allocation list
inUseList->~tHeader();
-
- tHeader* nextInUse = inUseList->nextPage;
+
+ tHeader *nextInUse = inUseList->nextPage;
if (inUseList->pageCount > 1)
- delete [] reinterpret_cast<char*>(inUseList);
- else {
+ delete[] reinterpret_cast<char *>(inUseList);
+ else
+ {
inUseList->nextPage = freeList;
- freeList = inUseList;
+ freeList = inUseList;
}
inUseList = nextInUse;
}
- stack.pop_back();
+ mStack.pop_back();
+#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
+ for (auto &alloc : mStack.back())
+ {
+ free(alloc);
+ }
+ mStack.pop_back();
+#endif
}
//
@@ -200,12 +238,15 @@ void TPoolAllocator::pop()
//
void TPoolAllocator::popAll()
{
- while (stack.size() > 0)
+ while (mStack.size() > 0)
pop();
}
-void* TPoolAllocator::allocate(size_t numBytes)
+void *TPoolAllocator::allocate(size_t numBytes)
{
+ ASSERT(!mLocked);
+
+#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
//
// Just keep some interesting statistics.
//
@@ -226,18 +267,20 @@ void* TPoolAllocator::allocate(size_t numBytes)
// Do the allocation, most likely case first, for efficiency.
// This step could be moved to be inline sometime.
//
- if (allocationSize <= pageSize - currentPageOffset) {
+ if (allocationSize <= pageSize - currentPageOffset)
+ {
//
// Safe to allocate from currentPageOffset.
//
- unsigned char* memory = reinterpret_cast<unsigned char *>(inUseList) + currentPageOffset;
+ unsigned char *memory = reinterpret_cast<unsigned char *>(inUseList) + currentPageOffset;
currentPageOffset += allocationSize;
currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask;
return initializeAllocation(inUseList, memory, numBytes);
}
- if (allocationSize > pageSize - headerSkip) {
+ if (allocationSize > pageSize - headerSkip)
+ {
//
// Do a multi-page allocation. Don't mix these with the others.
// The OS is efficient and allocating and free-ing multiple pages.
@@ -247,49 +290,71 @@ void* TPoolAllocator::allocate(size_t numBytes)
if (numBytesToAlloc < allocationSize)
return 0;
- tHeader* memory = reinterpret_cast<tHeader*>(::new char[numBytesToAlloc]);
+ tHeader *memory = reinterpret_cast<tHeader *>(::new char[numBytesToAlloc]);
if (memory == 0)
return 0;
// Use placement-new to initialize header
- new(memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize);
+ new (memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize);
inUseList = memory;
currentPageOffset = pageSize; // make next allocation come from a new page
// No guard blocks for multi-page allocations (yet)
- return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(memory) + headerSkip);
+ return reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(memory) + headerSkip);
}
//
// Need a simple page to allocate from.
//
- tHeader* memory;
- if (freeList) {
- memory = freeList;
+ tHeader *memory;
+ if (freeList)
+ {
+ memory = freeList;
freeList = freeList->nextPage;
- } else {
- memory = reinterpret_cast<tHeader*>(::new char[pageSize]);
+ }
+ else
+ {
+ memory = reinterpret_cast<tHeader *>(::new char[pageSize]);
if (memory == 0)
return 0;
}
// Use placement-new to initialize header
- new(memory) tHeader(inUseList, 1);
+ new (memory) tHeader(inUseList, 1);
inUseList = memory;
-
- unsigned char* ret = reinterpret_cast<unsigned char *>(inUseList) + headerSkip;
- currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask;
+
+ unsigned char *ret = reinterpret_cast<unsigned char *>(inUseList) + headerSkip;
+ currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask;
return initializeAllocation(inUseList, ret, numBytes);
+#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
+ void *alloc = malloc(numBytes + alignmentMask);
+ mStack.back().push_back(alloc);
+
+ intptr_t intAlloc = reinterpret_cast<intptr_t>(alloc);
+ intAlloc = (intAlloc + alignmentMask) & ~alignmentMask;
+ return reinterpret_cast<void *>(intAlloc);
+#endif
+}
+
+void TPoolAllocator::lock()
+{
+ ASSERT(!mLocked);
+ mLocked = true;
}
+void TPoolAllocator::unlock()
+{
+ ASSERT(mLocked);
+ mLocked = false;
+}
//
// Check all allocations in a list for damage by calling check on each.
//
void TAllocation::checkAllocList() const
{
- for (const TAllocation* alloc = this; alloc != 0; alloc = alloc->prevAlloc)
+ for (const TAllocation *alloc = this; alloc != 0; alloc = alloc->prevAlloc)
alloc->check();
}
diff --git a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h
index dab2926c90..ad63bc4cd6 100644
--- a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h
+++ b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h
@@ -13,8 +13,8 @@
//
// This header defines an allocator that can be used to efficiently
-// allocate a large number of small requests for heap memory, with the
-// intention that they are not individually deallocated, but rather
+// allocate a large number of small requests for heap memory, with the
+// intention that they are not individually deallocated, but rather
// collectively deallocated at one time.
//
// This simultaneously
@@ -38,53 +38,58 @@
// If we are using guard blocks, we must track each indivual
// allocation. If we aren't using guard blocks, these
// never get instantiated, so won't have any impact.
-//
-
-class TAllocation {
-public:
- TAllocation(size_t size, unsigned char* mem, TAllocation* prev = 0) :
- size(size), mem(mem), prevAlloc(prev) {
- // Allocations are bracketed:
- // [allocationHeader][initialGuardBlock][userData][finalGuardBlock]
- // This would be cleaner with if (guardBlockSize)..., but that
- // makes the compiler print warnings about 0 length memsets,
- // even with the if() protecting them.
+//
+
+class TAllocation
+{
+ public:
+ TAllocation(size_t size, unsigned char *mem, TAllocation *prev = 0)
+ : size(size), mem(mem), prevAlloc(prev)
+ {
+// Allocations are bracketed:
+// [allocationHeader][initialGuardBlock][userData][finalGuardBlock]
+// This would be cleaner with if (guardBlockSize)..., but that
+// makes the compiler print warnings about 0 length memsets,
+// even with the if() protecting them.
#ifdef GUARD_BLOCKS
memset(preGuard(), guardBlockBeginVal, guardBlockSize);
- memset(data(), userDataFill, size);
- memset(postGuard(), guardBlockEndVal, guardBlockSize);
+ memset(data(), userDataFill, size);
+ memset(postGuard(), guardBlockEndVal, guardBlockSize);
#endif
}
- void check() const {
- checkGuardBlock(preGuard(), guardBlockBeginVal, "before");
- checkGuardBlock(postGuard(), guardBlockEndVal, "after");
+ void check() const
+ {
+ checkGuardBlock(preGuard(), guardBlockBeginVal, "before");
+ checkGuardBlock(postGuard(), guardBlockEndVal, "after");
}
void checkAllocList() const;
// Return total size needed to accomodate user buffer of 'size',
// plus our tracking data.
- inline static size_t allocationSize(size_t size) {
+ inline static size_t allocationSize(size_t size)
+ {
return size + 2 * guardBlockSize + headerSize();
}
// Offset from surrounding buffer to get to user data buffer.
- inline static unsigned char* offsetAllocation(unsigned char* m) {
+ inline static unsigned char *offsetAllocation(unsigned char *m)
+ {
return m + guardBlockSize + headerSize();
}
-private:
- void checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const;
+ private:
+ void checkGuardBlock(unsigned char *blockMem, unsigned char val, const char *locText) const;
// Find offsets to pre and post guard blocks, and user data buffer
- unsigned char* preGuard() const { return mem + headerSize(); }
- unsigned char* data() const { return preGuard() + guardBlockSize; }
- unsigned char* postGuard() const { return data() + size; }
+ unsigned char *preGuard() const { return mem + headerSize(); }
+ unsigned char *data() const { return preGuard() + guardBlockSize; }
+ unsigned char *postGuard() const { return data() + size; }
- size_t size; // size of the user data area
- unsigned char* mem; // beginning of our allocation (pts to header)
- TAllocation* prevAlloc; // prior allocation in the chain
+ size_t size; // size of the user data area
+ unsigned char *mem; // beginning of our allocation (pts to header)
+ TAllocation *prevAlloc; // prior allocation in the chain
// Support MSVC++ 6.0
const static unsigned char guardBlockBeginVal;
@@ -101,7 +106,7 @@ private:
//
// There are several stacks. One is to track the pushing and popping
-// of the user, and not yet implemented. The others are simply a
+// of the user, and not yet implemented. The others are simply a
// repositories of free pages or used pages.
//
// Page stacks are linked together with a simple header at the beginning
@@ -110,12 +115,13 @@ private:
// re-use.
//
// The "page size" used is not, nor must it match, the underlying OS
-// page size. But, having it be about that size or equal to a set of
+// page size. But, having it be about that size or equal to a set of
// pages is likely most optimal.
//
-class TPoolAllocator {
-public:
- TPoolAllocator(int growthIncrement = 8*1024, int allocationAlignment = 16);
+class TPoolAllocator
+{
+ public:
+ TPoolAllocator(int growthIncrement = 8 * 1024, int allocationAlignment = 16);
//
// Don't call the destructor just to free up the memory, call pop()
@@ -143,7 +149,7 @@ public:
// Call allocate() to actually acquire memory. Returns 0 if no memory
// available, otherwise a properly aligned pointer to 'numBytes' of memory.
//
- void* allocate(size_t numBytes);
+ void *allocate(size_t numBytes);
//
// There is no deallocate. The point of this class is that
@@ -152,75 +158,92 @@ public:
// by calling pop(), and to not have to solve memory leak problems.
//
-protected:
+ // Catch unwanted allocations.
+ // TODO(jmadill): Remove this when we remove the global allocator.
+ void lock();
+ void unlock();
+
+ private:
+ size_t alignment; // all returned allocations will be aligned at
+ // this granularity, which will be a power of 2
+ size_t alignmentMask;
+
+#if !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
friend struct tHeader;
-
- struct tHeader {
- tHeader(tHeader* nextPage, size_t pageCount) :
- nextPage(nextPage),
- pageCount(pageCount)
+
+ struct tHeader
+ {
+ tHeader(tHeader *nextPage, size_t pageCount)
+ : nextPage(nextPage),
+ pageCount(pageCount)
#ifdef GUARD_BLOCKS
- , lastAllocation(0)
+ ,
+ lastAllocation(0)
#endif
- { }
+ {
+ }
- ~tHeader() {
+ ~tHeader()
+ {
#ifdef GUARD_BLOCKS
if (lastAllocation)
lastAllocation->checkAllocList();
#endif
}
- tHeader* nextPage;
+ tHeader *nextPage;
size_t pageCount;
#ifdef GUARD_BLOCKS
- TAllocation* lastAllocation;
+ TAllocation *lastAllocation;
#endif
};
- struct tAllocState {
+ struct tAllocState
+ {
size_t offset;
- tHeader* page;
+ tHeader *page;
};
typedef std::vector<tAllocState> tAllocStack;
// Track allocations if and only if we're using guard blocks
- void* initializeAllocation(tHeader* block, unsigned char* memory, size_t numBytes) {
+ void *initializeAllocation(tHeader *block, unsigned char *memory, size_t numBytes)
+ {
#ifdef GUARD_BLOCKS
- new(memory) TAllocation(numBytes, memory, block->lastAllocation);
- block->lastAllocation = reinterpret_cast<TAllocation*>(memory);
+ new (memory) TAllocation(numBytes, memory, block->lastAllocation);
+ block->lastAllocation = reinterpret_cast<TAllocation *>(memory);
#endif
// This is optimized entirely away if GUARD_BLOCKS is not defined.
return TAllocation::offsetAllocation(memory);
}
- size_t pageSize; // granularity of allocation from the OS
- size_t alignment; // all returned allocations will be aligned at
- // this granularity, which will be a power of 2
- size_t alignmentMask;
- size_t headerSkip; // amount of memory to skip to make room for the
- // header (basically, size of header, rounded
- // up to make it aligned
+ size_t pageSize; // granularity of allocation from the OS
+ size_t headerSkip; // amount of memory to skip to make room for the
+ // header (basically, size of header, rounded
+ // up to make it aligned
size_t currentPageOffset; // next offset in top of inUseList to allocate from
- tHeader* freeList; // list of popped memory
- tHeader* inUseList; // list of all memory currently being used
- tAllocStack stack; // stack of where to allocate from, to partition pool
-
- int numCalls; // just an interesting statistic
- size_t totalBytes; // just an interesting statistic
-private:
- TPoolAllocator& operator=(const TPoolAllocator&); // dont allow assignment operator
- TPoolAllocator(const TPoolAllocator&); // dont allow default copy constructor
-};
+ tHeader *freeList; // list of popped memory
+ tHeader *inUseList; // list of all memory currently being used
+ tAllocStack mStack; // stack of where to allocate from, to partition pool
+ int numCalls; // just an interesting statistic
+ size_t totalBytes; // just an interesting statistic
+
+#else // !defined(ANGLE_TRANSLATOR_DISABLE_POOL_ALLOC)
+ std::vector<std::vector<void *>> mStack;
+#endif
+
+ TPoolAllocator &operator=(const TPoolAllocator &); // dont allow assignment operator
+ TPoolAllocator(const TPoolAllocator &); // dont allow default copy constructor
+ bool mLocked;
+};
//
// There could potentially be many pools with pops happening at
// different times. But a simple use is to have a global pop
// with everyone using the same global allocator.
//
-extern TPoolAllocator* GetGlobalPoolAllocator();
-extern void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator);
+extern TPoolAllocator *GetGlobalPoolAllocator();
+extern void SetGlobalPoolAllocator(TPoolAllocator *poolAllocator);
//
// This STL compatible allocator is intended to be used as the allocator
@@ -229,63 +252,68 @@ extern void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator);
// It will use the pools for allocation, and not
// do any deallocation, but will still do destruction.
//
-template<class T>
-class pool_allocator {
-public:
+template <class T>
+class pool_allocator
+{
+ public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
- typedef T* pointer;
- typedef const T* const_pointer;
- typedef T& reference;
- typedef const T& const_reference;
+ typedef T *pointer;
+ typedef const T *const_pointer;
+ typedef T &reference;
+ typedef const T &const_reference;
typedef T value_type;
- template<class Other>
- struct rebind {
+ template <class Other>
+ struct rebind
+ {
typedef pool_allocator<Other> other;
};
pointer address(reference x) const { return &x; }
const_pointer address(const_reference x) const { return &x; }
- pool_allocator() { }
+ pool_allocator() {}
- template<class Other>
- pool_allocator(const pool_allocator<Other>& p) { }
+ template <class Other>
+ pool_allocator(const pool_allocator<Other> &p)
+ {
+ }
template <class Other>
- pool_allocator<T>& operator=(const pool_allocator<Other>& p) { return *this; }
+ pool_allocator<T> &operator=(const pool_allocator<Other> &p)
+ {
+ return *this;
+ }
#if defined(__SUNPRO_CC) && !defined(_RWSTD_ALLOCATOR)
// libCStd on some platforms have a different allocate/deallocate interface.
// Caller pre-bakes sizeof(T) into 'n' which is the number of bytes to be
// allocated, not the number of elements.
- void* allocate(size_type n) {
- return getAllocator().allocate(n);
- }
- void* allocate(size_type n, const void*) {
- return getAllocator().allocate(n);
- }
- void deallocate(void*, size_type) {}
+ void *allocate(size_type n) { return getAllocator().allocate(n); }
+ void *allocate(size_type n, const void *) { return getAllocator().allocate(n); }
+ void deallocate(void *, size_type) {}
#else
- pointer allocate(size_type n) {
+ pointer allocate(size_type n)
+ {
return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T)));
}
- pointer allocate(size_type n, const void*) {
+ pointer allocate(size_type n, const void *)
+ {
return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T)));
}
void deallocate(pointer, size_type) {}
#endif // _RWSTD_ALLOCATOR
- void construct(pointer p, const T& val) { new ((void *)p) T(val); }
+ void construct(pointer p, const T &val) { new ((void *)p) T(val); }
void destroy(pointer p) { p->T::~T(); }
- bool operator==(const pool_allocator& rhs) const { return true; }
- bool operator!=(const pool_allocator& rhs) const { return false; }
+ bool operator==(const pool_allocator &rhs) const { return true; }
+ bool operator!=(const pool_allocator &rhs) const { return false; }
size_type max_size() const { return static_cast<size_type>(-1) / sizeof(T); }
size_type max_size(int size) const { return static_cast<size_type>(-1) / size; }
- TPoolAllocator& getAllocator() const { return *GetGlobalPoolAllocator(); }
+ TPoolAllocator &getAllocator() const { return *GetGlobalPoolAllocator(); }
};
-#endif // COMPILER_TRANSLATOR_POOLALLOC_H_
+#endif // COMPILER_TRANSLATOR_POOLALLOC_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/Pragma.h b/src/3rdparty/angle/src/compiler/translator/Pragma.h
index 57b1134970..8c419fc17e 100644
--- a/src/3rdparty/angle/src/compiler/translator/Pragma.h
+++ b/src/3rdparty/angle/src/compiler/translator/Pragma.h
@@ -11,17 +11,16 @@ struct TPragma
{
struct STDGL
{
- STDGL() : invariantAll(false) { }
+ STDGL() : invariantAll(false) {}
bool invariantAll;
};
-
// By default optimization is turned on and debug is turned off.
// Precision emulation is turned on by default, but has no effect unless
// the extension is enabled.
- TPragma() : optimize(true), debug(false), debugShaderPrecision(true) { }
- TPragma(bool o, bool d) : optimize(o), debug(d), debugShaderPrecision(true) { }
+ TPragma() : optimize(true), debug(false), debugShaderPrecision(true) {}
+ TPragma(bool o, bool d) : optimize(o), debug(d), debugShaderPrecision(true) {}
bool optimize;
bool debug;
@@ -29,4 +28,4 @@ struct TPragma
STDGL stdgl;
};
-#endif // COMPILER_TRANSLATOR_PRAGMA_H_
+#endif // COMPILER_TRANSLATOR_PRAGMA_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/PruneEmptyDeclarations.cpp b/src/3rdparty/angle/src/compiler/translator/PruneEmptyDeclarations.cpp
deleted file mode 100644
index ef62dbfce7..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/PruneEmptyDeclarations.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-//
-// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// The PruneEmptyDeclarations function prunes unnecessary empty declarations and declarators from the AST.
-
-#include "compiler/translator/PruneEmptyDeclarations.h"
-
-#include "compiler/translator/IntermNode.h"
-
-namespace
-{
-
-class PruneEmptyDeclarationsTraverser : private TIntermTraverser
-{
- public:
- static void apply(TIntermNode *root);
- private:
- PruneEmptyDeclarationsTraverser();
- bool visitAggregate(Visit, TIntermAggregate *node) override;
-};
-
-void PruneEmptyDeclarationsTraverser::apply(TIntermNode *root)
-{
- PruneEmptyDeclarationsTraverser prune;
- root->traverse(&prune);
- prune.updateTree();
-}
-
-PruneEmptyDeclarationsTraverser::PruneEmptyDeclarationsTraverser()
- : TIntermTraverser(true, false, false)
-{
-}
-
-bool PruneEmptyDeclarationsTraverser::visitAggregate(Visit, TIntermAggregate *node)
-{
- if (node->getOp() == EOpDeclaration)
- {
- TIntermSequence *sequence = node->getSequence();
- if (sequence->size() >= 1)
- {
- TIntermSymbol *sym = sequence->front()->getAsSymbolNode();
- // Prune declarations without a variable name, unless it's an interface block declaration.
- if (sym != nullptr && sym->getSymbol() == "" && !sym->isInterfaceBlock())
- {
- if (sequence->size() > 1)
- {
- // Generate a replacement that will remove the empty declarator in the beginning of a declarator
- // list. Example of a declaration that will be changed:
- // float, a;
- // will be changed to
- // float a;
- // This applies also to struct declarations.
- TIntermSequence emptyReplacement;
- mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(node, sym, emptyReplacement));
- }
- else if (sym->getBasicType() != EbtStruct)
- {
- // Single struct declarations may just declare the struct type and no variables, so they should
- // not be pruned. All other single empty declarations can be pruned entirely. Example of an empty
- // declaration that will be pruned:
- // float;
- TIntermSequence emptyReplacement;
- TIntermAggregate *parentAgg = getParentNode()->getAsAggregate();
- ASSERT(parentAgg != nullptr);
- mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(parentAgg, node, emptyReplacement));
- }
- }
- }
- return false;
- }
- return true;
-}
-
-} // namespace
-
-void PruneEmptyDeclarations(TIntermNode *root)
-{
- PruneEmptyDeclarationsTraverser::apply(root);
-}
diff --git a/src/3rdparty/angle/src/compiler/translator/PruneEmptyDeclarations.h b/src/3rdparty/angle/src/compiler/translator/PruneEmptyDeclarations.h
deleted file mode 100644
index 122e830902..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/PruneEmptyDeclarations.h
+++ /dev/null
@@ -1,15 +0,0 @@
-//
-// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// The PruneEmptyDeclarations function prunes unnecessary empty declarations and declarators from the AST.
-
-#ifndef COMPILER_TRANSLATOR_PRUNEEMPTYDECLARATIONS_H_
-#define COMPILER_TRANSLATOR_PRUNEEMPTYDECLARATIONS_H_
-
-class TIntermNode;
-
-void PruneEmptyDeclarations(TIntermNode *root);
-
-#endif // COMPILER_TRANSLATOR_PRUNEEMPTYDECLARATIONS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/PruneNoOps.cpp b/src/3rdparty/angle/src/compiler/translator/PruneNoOps.cpp
new file mode 100644
index 0000000000..6c9a02cd1c
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/PruneNoOps.cpp
@@ -0,0 +1,156 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// PruneNoOps.cpp: The PruneNoOps function prunes:
+// 1. Empty declarations "int;". Empty declarators will be pruned as well, so for example:
+// int , a;
+// is turned into
+// int a;
+// 2. Literal statements: "1.0;". The ESSL output doesn't define a default precision for float,
+// so float literal statements would end up with no precision which is invalid ESSL.
+
+#include "compiler/translator/PruneNoOps.h"
+
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
+
+namespace
+{
+
+bool IsNoOp(TIntermNode *node)
+{
+ if (node->getAsConstantUnion() != nullptr)
+ {
+ return true;
+ }
+ bool isEmptyDeclaration = node->getAsDeclarationNode() != nullptr &&
+ node->getAsDeclarationNode()->getSequence()->empty();
+ if (isEmptyDeclaration)
+ {
+ return true;
+ }
+ return false;
+}
+
+class PruneNoOpsTraverser : private TIntermTraverser
+{
+ public:
+ static void apply(TIntermBlock *root);
+
+ private:
+ PruneNoOpsTraverser();
+ bool visitDeclaration(Visit, TIntermDeclaration *node) override;
+ bool visitBlock(Visit visit, TIntermBlock *node) override;
+ bool visitLoop(Visit visit, TIntermLoop *loop) override;
+};
+
+void PruneNoOpsTraverser::apply(TIntermBlock *root)
+{
+ PruneNoOpsTraverser prune;
+ root->traverse(&prune);
+ prune.updateTree();
+}
+
+PruneNoOpsTraverser::PruneNoOpsTraverser() : TIntermTraverser(true, false, false)
+{
+}
+
+bool PruneNoOpsTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
+{
+ TIntermSequence *sequence = node->getSequence();
+ if (sequence->size() >= 1)
+ {
+ TIntermSymbol *sym = sequence->front()->getAsSymbolNode();
+ // Prune declarations without a variable name, unless it's an interface block declaration.
+ if (sym != nullptr && sym->getSymbol() == "" && !sym->isInterfaceBlock())
+ {
+ if (sequence->size() > 1)
+ {
+ // Generate a replacement that will remove the empty declarator in the beginning of
+ // a declarator list. Example of a declaration that will be changed:
+ // float, a;
+ // will be changed to
+ // float a;
+ // This applies also to struct declarations.
+ TIntermSequence emptyReplacement;
+ mMultiReplacements.push_back(
+ NodeReplaceWithMultipleEntry(node, sym, emptyReplacement));
+ }
+ else if (sym->getBasicType() != EbtStruct)
+ {
+ // If there are entirely empty non-struct declarations, they result in
+ // TIntermDeclaration nodes without any children in the parsing stage. These are
+ // handled in visitBlock and visitLoop.
+ UNREACHABLE();
+ }
+ else if (sym->getType().getQualifier() != EvqGlobal &&
+ sym->getType().getQualifier() != EvqTemporary)
+ {
+ // Single struct declarations may just declare the struct type and no variables, so
+ // they should not be pruned. Here we handle an empty struct declaration with a
+ // qualifier, for example like this:
+ // const struct a { int i; };
+ // NVIDIA GL driver version 367.27 doesn't accept this kind of declarations, so we
+ // convert the declaration to a regular struct declaration. This is okay, since ESSL
+ // 1.00 spec section 4.1.8 says about structs that "The optional qualifiers only
+ // apply to any declarators, and are not part of the type being defined for name."
+
+ if (mInGlobalScope)
+ {
+ sym->getTypePointer()->setQualifier(EvqGlobal);
+ }
+ else
+ {
+ sym->getTypePointer()->setQualifier(EvqTemporary);
+ }
+ }
+ }
+ }
+ return false;
+}
+
+bool PruneNoOpsTraverser::visitBlock(Visit visit, TIntermBlock *node)
+{
+ TIntermSequence *statements = node->getSequence();
+
+ for (TIntermNode *statement : *statements)
+ {
+ if (IsNoOp(statement))
+ {
+ TIntermSequence emptyReplacement;
+ mMultiReplacements.push_back(
+ NodeReplaceWithMultipleEntry(node, statement, emptyReplacement));
+ }
+ }
+
+ return true;
+}
+
+bool PruneNoOpsTraverser::visitLoop(Visit visit, TIntermLoop *loop)
+{
+ TIntermTyped *expr = loop->getExpression();
+ if (expr != nullptr && IsNoOp(expr))
+ {
+ loop->setExpression(nullptr);
+ }
+ TIntermNode *init = loop->getInit();
+ if (init != nullptr && IsNoOp(init))
+ {
+ loop->setInit(nullptr);
+ }
+
+ return true;
+}
+
+} // namespace
+
+void PruneNoOps(TIntermBlock *root)
+{
+ PruneNoOpsTraverser::apply(root);
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/PruneNoOps.h b/src/3rdparty/angle/src/compiler/translator/PruneNoOps.h
new file mode 100644
index 0000000000..c421cecca4
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/PruneNoOps.h
@@ -0,0 +1,24 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// PruneNoOps.h: The PruneNoOps function prunes:
+// 1. Empty declarations "int;". Empty declarators will be pruned as well, so for example:
+// int , a;
+// is turned into
+// int a;
+// 2. Literal statements: "1.0;". The ESSL output doesn't define a default precision for float,
+// so float literal statements would end up with no precision which is invalid ESSL.
+
+#ifndef COMPILER_TRANSLATOR_PRUNENOOPS_H_
+#define COMPILER_TRANSLATOR_PRUNENOOPS_H_
+
+namespace sh
+{
+class TIntermBlock;
+
+void PruneNoOps(TIntermBlock *root);
+}
+
+#endif // COMPILER_TRANSLATOR_PRUNENOOPS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp
deleted file mode 100644
index 3d950aab5a..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/translator/IntermNode.h"
-
-class TAliveTraverser : public TIntermTraverser {
-public:
- TAliveTraverser(TQualifier q) : TIntermTraverser(true, false, false, true), found(false), qualifier(q)
- {
- }
-
- bool wasFound() { return found; }
-
-protected:
- bool found;
- TQualifier qualifier;
-
- void visitSymbol(TIntermSymbol*);
- bool visitSelection(Visit, TIntermSelection*);
-};
-
-//
-// Report whether or not a variable of the given qualifier type
-// is guaranteed written. Not always possible to determine if
-// it is written conditionally.
-//
-// ?? It does not do this well yet, this is just a place holder
-// that simply determines if it was reference at all, anywhere.
-//
-bool QualifierWritten(TIntermNode* node, TQualifier qualifier)
-{
- TAliveTraverser it(qualifier);
-
- if (node)
- node->traverse(&it);
-
- return it.wasFound();
-}
-
-void TAliveTraverser::visitSymbol(TIntermSymbol* node)
-{
- //
- // If it's what we're looking for, record it.
- //
- if (node->getQualifier() == qualifier)
- found = true;
-}
-
-bool TAliveTraverser::visitSelection(Visit, TIntermSelection*)
-{
- if (wasFound())
- return false;
-
- return true;
-}
diff --git a/src/3rdparty/angle/src/compiler/translator/QualifierAlive.h b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.h
deleted file mode 100644
index 3e4f18012a..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/QualifierAlive.h
+++ /dev/null
@@ -1,12 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_TRANSLATOR_QUALIFIERALIVE_H_
-#define COMPILER_TRANSLATOR_QUALIFIERALIVE_H_
-
-bool QualifierWritten(TIntermNode* root, TQualifier);
-
-#endif // COMPILER_TRANSLATOR_QUALIFIERALIVE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/QualifierTypes.cpp b/src/3rdparty/angle/src/compiler/translator/QualifierTypes.cpp
new file mode 100644
index 0000000000..f748175957
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/QualifierTypes.cpp
@@ -0,0 +1,784 @@
+//
+// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/QualifierTypes.h"
+
+#include "compiler/translator/Diagnostics.h"
+
+#include <algorithm>
+
+namespace sh
+{
+
+namespace
+{
+
+// GLSL ES 3.10 does not impose a strict order on type qualifiers and allows multiple layout
+// declarations.
+// GLSL ES 3.10 Revision 4, 4.10 Order of Qualification
+bool AreTypeQualifierChecksRelaxed(int shaderVersion)
+{
+ return shaderVersion >= 310;
+}
+
+bool IsScopeQualifier(TQualifier qualifier)
+{
+ return qualifier == EvqGlobal || qualifier == EvqTemporary;
+}
+
+bool IsScopeQualifierWrapper(const TQualifierWrapperBase *qualifier)
+{
+ if (qualifier->getType() != QtStorage)
+ return false;
+ const TStorageQualifierWrapper *storageQualifier =
+ static_cast<const TStorageQualifierWrapper *>(qualifier);
+ TQualifier q = storageQualifier->getQualifier();
+ return IsScopeQualifier(q);
+}
+
+// Returns true if the invariant for the qualifier sequence holds
+bool IsInvariantCorrect(const TTypeQualifierBuilder::QualifierSequence &qualifiers)
+{
+ // We should have at least one qualifier.
+ // The first qualifier always tells the scope.
+ return qualifiers.size() >= 1 && IsScopeQualifierWrapper(qualifiers[0]);
+}
+
+// Returns true if there are qualifiers which have been specified multiple times
+// If areQualifierChecksRelaxed is set to true, then layout qualifier repetition is allowed.
+bool HasRepeatingQualifiers(const TTypeQualifierBuilder::QualifierSequence &qualifiers,
+ bool areQualifierChecksRelaxed,
+ std::string *errorMessage)
+{
+ bool invariantFound = false;
+ bool precisionFound = false;
+ bool layoutFound = false;
+ bool interpolationFound = false;
+
+ unsigned int locationsSpecified = 0;
+ bool isOut = false;
+
+ // The iteration starts from one since the first qualifier only reveals the scope of the
+ // expression. It is inserted first whenever the sequence gets created.
+ for (size_t i = 1; i < qualifiers.size(); ++i)
+ {
+ switch (qualifiers[i]->getType())
+ {
+ case QtInvariant:
+ {
+ if (invariantFound)
+ {
+ *errorMessage = "The invariant qualifier specified multiple times.";
+ return true;
+ }
+ invariantFound = true;
+ break;
+ }
+ case QtPrecision:
+ {
+ if (precisionFound)
+ {
+ *errorMessage = "The precision qualifier specified multiple times.";
+ return true;
+ }
+ precisionFound = true;
+ break;
+ }
+ case QtLayout:
+ {
+ if (layoutFound && !areQualifierChecksRelaxed)
+ {
+ *errorMessage = "The layout qualifier specified multiple times.";
+ return true;
+ }
+ if (invariantFound && !areQualifierChecksRelaxed)
+ {
+ // This combination is not correct according to the syntax specified in the
+ // formal grammar in the ESSL 3.00 spec. In ESSL 3.10 the grammar does not have
+ // a similar restriction.
+ *errorMessage =
+ "The layout qualifier and invariant qualifier cannot coexist in the same "
+ "declaration according to the grammar.";
+ return true;
+ }
+ layoutFound = true;
+ const TLayoutQualifier &currentQualifier =
+ static_cast<const TLayoutQualifierWrapper *>(qualifiers[i])->getQualifier();
+ locationsSpecified += currentQualifier.locationsSpecified;
+ break;
+ }
+ case QtInterpolation:
+ {
+ // 'centroid' is treated as a storage qualifier
+ // 'flat centroid' will be squashed to 'flat'
+ // 'smooth centroid' will be squashed to 'centroid'
+ if (interpolationFound)
+ {
+ *errorMessage = "The interpolation qualifier specified multiple times.";
+ return true;
+ }
+ interpolationFound = true;
+ break;
+ }
+ case QtStorage:
+ {
+ // Go over all of the storage qualifiers up until the current one and check for
+ // repetitions.
+ TQualifier currentQualifier =
+ static_cast<const TStorageQualifierWrapper *>(qualifiers[i])->getQualifier();
+ if (currentQualifier == EvqVertexOut || currentQualifier == EvqFragmentOut)
+ {
+ isOut = true;
+ }
+ for (size_t j = 1; j < i; ++j)
+ {
+ if (qualifiers[j]->getType() == QtStorage)
+ {
+ const TStorageQualifierWrapper *previousQualifierWrapper =
+ static_cast<const TStorageQualifierWrapper *>(qualifiers[j]);
+ TQualifier previousQualifier = previousQualifierWrapper->getQualifier();
+ if (currentQualifier == previousQualifier)
+ {
+ *errorMessage = previousQualifierWrapper->getQualifierString().c_str();
+ *errorMessage += " specified multiple times";
+ return true;
+ }
+ }
+ }
+ break;
+ }
+ case QtMemory:
+ {
+ // Go over all of the memory qualifiers up until the current one and check for
+ // repetitions.
+ // Having both readonly and writeonly in a sequence is valid.
+ // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
+ TQualifier currentQualifier =
+ static_cast<const TMemoryQualifierWrapper *>(qualifiers[i])->getQualifier();
+ for (size_t j = 1; j < i; ++j)
+ {
+ if (qualifiers[j]->getType() == QtMemory)
+ {
+ const TMemoryQualifierWrapper *previousQualifierWrapper =
+ static_cast<const TMemoryQualifierWrapper *>(qualifiers[j]);
+ TQualifier previousQualifier = previousQualifierWrapper->getQualifier();
+ if (currentQualifier == previousQualifier)
+ {
+ *errorMessage = previousQualifierWrapper->getQualifierString().c_str();
+ *errorMessage += " specified multiple times";
+ return true;
+ }
+ }
+ }
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ if (locationsSpecified > 1 && isOut)
+ {
+ // GLSL ES 3.00.6 section 4.3.8.2 Output Layout Qualifiers
+ // GLSL ES 3.10 section 4.4.2 Output Layout Qualifiers
+ // "The qualifier may appear at most once within a declaration."
+ *errorMessage = "Output layout location specified multiple times.";
+ return true;
+ }
+
+ return false;
+}
+
+// GLSL ES 3.00_6, 4.7 Order of Qualification
+// The correct order of qualifiers is:
+// invariant-qualifier interpolation-qualifier storage-qualifier precision-qualifier
+// layout-qualifier has to be before storage-qualifier.
+bool AreQualifiersInOrder(const TTypeQualifierBuilder::QualifierSequence &qualifiers,
+ std::string *errorMessage)
+{
+ bool foundInterpolation = false;
+ bool foundStorage = false;
+ bool foundPrecision = false;
+ for (size_t i = 1; i < qualifiers.size(); ++i)
+ {
+ switch (qualifiers[i]->getType())
+ {
+ case QtInvariant:
+ if (foundInterpolation || foundStorage || foundPrecision)
+ {
+ *errorMessage = "The invariant qualifier has to be first in the expression.";
+ return false;
+ }
+ break;
+ case QtInterpolation:
+ if (foundStorage)
+ {
+ *errorMessage = "Storage qualifiers have to be after interpolation qualifiers.";
+ return false;
+ }
+ else if (foundPrecision)
+ {
+ *errorMessage =
+ "Precision qualifiers have to be after interpolation qualifiers.";
+ return false;
+ }
+ foundInterpolation = true;
+ break;
+ case QtLayout:
+ if (foundStorage)
+ {
+ *errorMessage = "Storage qualifiers have to be after layout qualifiers.";
+ return false;
+ }
+ else if (foundPrecision)
+ {
+ *errorMessage = "Precision qualifiers have to be after layout qualifiers.";
+ return false;
+ }
+ break;
+ case QtStorage:
+ if (foundPrecision)
+ {
+ *errorMessage = "Precision qualifiers have to be after storage qualifiers.";
+ return false;
+ }
+ foundStorage = true;
+ break;
+ case QtMemory:
+ if (foundPrecision)
+ {
+ *errorMessage = "Precision qualifiers have to be after memory qualifiers.";
+ return false;
+ }
+ break;
+ case QtPrecision:
+ foundPrecision = true;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ return true;
+}
+
+struct QualifierComparator
+{
+ bool operator()(const TQualifierWrapperBase *q1, const TQualifierWrapperBase *q2)
+ {
+ return q1->getRank() < q2->getRank();
+ }
+};
+
+void SortSequence(TTypeQualifierBuilder::QualifierSequence &qualifiers)
+{
+ // We need a stable sorting algorithm since the order of layout-qualifier declarations matter.
+ // The sorting starts from index 1, instead of 0, since the element at index 0 tells the scope
+ // and we always want it to be first.
+ std::stable_sort(qualifiers.begin() + 1, qualifiers.end(), QualifierComparator());
+}
+
+// Handles the joining of storage qualifiers for variables.
+bool JoinVariableStorageQualifier(TQualifier *joinedQualifier, TQualifier storageQualifier)
+{
+ switch (*joinedQualifier)
+ {
+ case EvqGlobal:
+ *joinedQualifier = storageQualifier;
+ break;
+ case EvqTemporary:
+ {
+ switch (storageQualifier)
+ {
+ case EvqConst:
+ *joinedQualifier = storageQualifier;
+ break;
+ default:
+ return false;
+ }
+ break;
+ }
+ case EvqSmooth:
+ {
+ switch (storageQualifier)
+ {
+ case EvqCentroid:
+ *joinedQualifier = EvqCentroid;
+ break;
+ case EvqVertexOut:
+ case EvqGeometryOut:
+ *joinedQualifier = EvqSmoothOut;
+ break;
+ case EvqFragmentIn:
+ case EvqGeometryIn:
+ *joinedQualifier = EvqSmoothIn;
+ break;
+ default:
+ return false;
+ }
+ break;
+ }
+ case EvqFlat:
+ {
+ switch (storageQualifier)
+ {
+ case EvqCentroid:
+ *joinedQualifier = EvqFlat;
+ break;
+ case EvqVertexOut:
+ case EvqGeometryOut:
+ *joinedQualifier = EvqFlatOut;
+ break;
+ case EvqFragmentIn:
+ case EvqGeometryIn:
+ *joinedQualifier = EvqFlatIn;
+ break;
+ default:
+ return false;
+ }
+ break;
+ }
+ case EvqCentroid:
+ {
+ switch (storageQualifier)
+ {
+ case EvqVertexOut:
+ case EvqGeometryOut:
+ *joinedQualifier = EvqCentroidOut;
+ break;
+ case EvqFragmentIn:
+ case EvqGeometryIn:
+ *joinedQualifier = EvqCentroidIn;
+ break;
+ default:
+ return false;
+ }
+ break;
+ }
+ default:
+ return false;
+ }
+ return true;
+}
+
+// Handles the joining of storage qualifiers for a parameter in a function.
+bool JoinParameterStorageQualifier(TQualifier *joinedQualifier, TQualifier storageQualifier)
+{
+ switch (*joinedQualifier)
+ {
+ case EvqTemporary:
+ *joinedQualifier = storageQualifier;
+ break;
+ case EvqConst:
+ {
+ switch (storageQualifier)
+ {
+ case EvqIn:
+ *joinedQualifier = EvqConstReadOnly;
+ break;
+ default:
+ return false;
+ }
+ break;
+ }
+ default:
+ return false;
+ }
+ return true;
+}
+
+bool JoinMemoryQualifier(TMemoryQualifier *joinedMemoryQualifier, TQualifier memoryQualifier)
+{
+ switch (memoryQualifier)
+ {
+ case EvqReadOnly:
+ joinedMemoryQualifier->readonly = true;
+ break;
+ case EvqWriteOnly:
+ joinedMemoryQualifier->writeonly = true;
+ break;
+ case EvqCoherent:
+ joinedMemoryQualifier->coherent = true;
+ break;
+ case EvqRestrict:
+ joinedMemoryQualifier->restrictQualifier = true;
+ break;
+ case EvqVolatile:
+ // Variables having the volatile qualifier are automatcally treated as coherent as well.
+ // GLSL ES 3.10, Revision 4, 4.9 Memory Access Qualifiers
+ joinedMemoryQualifier->volatileQualifier = true;
+ joinedMemoryQualifier->coherent = true;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ return true;
+}
+
+TTypeQualifier GetVariableTypeQualifierFromSortedSequence(
+ const TTypeQualifierBuilder::QualifierSequence &sortedSequence,
+ TDiagnostics *diagnostics)
+{
+ TTypeQualifier typeQualifier(
+ static_cast<const TStorageQualifierWrapper *>(sortedSequence[0])->getQualifier(),
+ sortedSequence[0]->getLine());
+ for (size_t i = 1; i < sortedSequence.size(); ++i)
+ {
+ const TQualifierWrapperBase *qualifier = sortedSequence[i];
+ bool isQualifierValid = false;
+ switch (qualifier->getType())
+ {
+ case QtInvariant:
+ isQualifierValid = true;
+ typeQualifier.invariant = true;
+ break;
+ case QtInterpolation:
+ {
+ switch (typeQualifier.qualifier)
+ {
+ case EvqGlobal:
+ isQualifierValid = true;
+ typeQualifier.qualifier =
+ static_cast<const TInterpolationQualifierWrapper *>(qualifier)
+ ->getQualifier();
+ break;
+ default:
+ isQualifierValid = false;
+ }
+ break;
+ }
+ case QtLayout:
+ {
+ const TLayoutQualifierWrapper *layoutQualifierWrapper =
+ static_cast<const TLayoutQualifierWrapper *>(qualifier);
+ isQualifierValid = true;
+ typeQualifier.layoutQualifier = sh::JoinLayoutQualifiers(
+ typeQualifier.layoutQualifier, layoutQualifierWrapper->getQualifier(),
+ layoutQualifierWrapper->getLine(), diagnostics);
+ break;
+ }
+ case QtStorage:
+ isQualifierValid = JoinVariableStorageQualifier(
+ &typeQualifier.qualifier,
+ static_cast<const TStorageQualifierWrapper *>(qualifier)->getQualifier());
+ break;
+ case QtPrecision:
+ isQualifierValid = true;
+ typeQualifier.precision =
+ static_cast<const TPrecisionQualifierWrapper *>(qualifier)->getQualifier();
+ ASSERT(typeQualifier.precision != EbpUndefined);
+ break;
+ case QtMemory:
+ isQualifierValid = JoinMemoryQualifier(
+ &typeQualifier.memoryQualifier,
+ static_cast<const TMemoryQualifierWrapper *>(qualifier)->getQualifier());
+ break;
+ default:
+ UNREACHABLE();
+ }
+ if (!isQualifierValid)
+ {
+ const TString &qualifierString = qualifier->getQualifierString();
+ diagnostics->error(qualifier->getLine(), "invalid qualifier combination",
+ qualifierString.c_str());
+ break;
+ }
+ }
+ return typeQualifier;
+}
+
+TTypeQualifier GetParameterTypeQualifierFromSortedSequence(
+ const TTypeQualifierBuilder::QualifierSequence &sortedSequence,
+ TDiagnostics *diagnostics)
+{
+ TTypeQualifier typeQualifier(EvqTemporary, sortedSequence[0]->getLine());
+ for (size_t i = 1; i < sortedSequence.size(); ++i)
+ {
+ const TQualifierWrapperBase *qualifier = sortedSequence[i];
+ bool isQualifierValid = false;
+ switch (qualifier->getType())
+ {
+ case QtInvariant:
+ case QtInterpolation:
+ case QtLayout:
+ break;
+ case QtMemory:
+ isQualifierValid = JoinMemoryQualifier(
+ &typeQualifier.memoryQualifier,
+ static_cast<const TMemoryQualifierWrapper *>(qualifier)->getQualifier());
+ break;
+ case QtStorage:
+ isQualifierValid = JoinParameterStorageQualifier(
+ &typeQualifier.qualifier,
+ static_cast<const TStorageQualifierWrapper *>(qualifier)->getQualifier());
+ break;
+ case QtPrecision:
+ isQualifierValid = true;
+ typeQualifier.precision =
+ static_cast<const TPrecisionQualifierWrapper *>(qualifier)->getQualifier();
+ ASSERT(typeQualifier.precision != EbpUndefined);
+ break;
+ default:
+ UNREACHABLE();
+ }
+ if (!isQualifierValid)
+ {
+ const TString &qualifierString = qualifier->getQualifierString();
+ diagnostics->error(qualifier->getLine(), "invalid parameter qualifier",
+ qualifierString.c_str());
+ break;
+ }
+ }
+
+ switch (typeQualifier.qualifier)
+ {
+ case EvqIn:
+ case EvqConstReadOnly: // const in
+ case EvqOut:
+ case EvqInOut:
+ break;
+ case EvqConst:
+ typeQualifier.qualifier = EvqConstReadOnly;
+ break;
+ case EvqTemporary:
+ // no qualifier has been specified, set it to EvqIn which is the default
+ typeQualifier.qualifier = EvqIn;
+ break;
+ default:
+ diagnostics->error(sortedSequence[0]->getLine(), "Invalid parameter qualifier ",
+ getQualifierString(typeQualifier.qualifier));
+ }
+ return typeQualifier;
+}
+} // namespace
+
+TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier,
+ TLayoutQualifier rightQualifier,
+ const TSourceLoc &rightQualifierLocation,
+ TDiagnostics *diagnostics)
+{
+ TLayoutQualifier joinedQualifier = leftQualifier;
+
+ if (rightQualifier.location != -1)
+ {
+ joinedQualifier.location = rightQualifier.location;
+ ++joinedQualifier.locationsSpecified;
+ }
+ if (rightQualifier.yuv != false)
+ {
+ joinedQualifier.yuv = rightQualifier.yuv;
+ }
+ if (rightQualifier.binding != -1)
+ {
+ joinedQualifier.binding = rightQualifier.binding;
+ }
+ if (rightQualifier.offset != -1)
+ {
+ joinedQualifier.offset = rightQualifier.offset;
+ }
+ if (rightQualifier.matrixPacking != EmpUnspecified)
+ {
+ joinedQualifier.matrixPacking = rightQualifier.matrixPacking;
+ }
+ if (rightQualifier.blockStorage != EbsUnspecified)
+ {
+ joinedQualifier.blockStorage = rightQualifier.blockStorage;
+ }
+
+ for (size_t i = 0u; i < rightQualifier.localSize.size(); ++i)
+ {
+ if (rightQualifier.localSize[i] != -1)
+ {
+ if (joinedQualifier.localSize[i] != -1 &&
+ joinedQualifier.localSize[i] != rightQualifier.localSize[i])
+ {
+ diagnostics->error(rightQualifierLocation,
+ "Cannot have multiple different work group size specifiers",
+ getWorkGroupSizeString(i));
+ }
+ joinedQualifier.localSize[i] = rightQualifier.localSize[i];
+ }
+ }
+
+ if (rightQualifier.numViews != -1)
+ {
+ joinedQualifier.numViews = rightQualifier.numViews;
+ }
+
+ if (rightQualifier.imageInternalFormat != EiifUnspecified)
+ {
+ joinedQualifier.imageInternalFormat = rightQualifier.imageInternalFormat;
+ }
+
+ if (rightQualifier.primitiveType != EptUndefined)
+ {
+ if (joinedQualifier.primitiveType != EptUndefined &&
+ joinedQualifier.primitiveType != rightQualifier.primitiveType)
+ {
+ diagnostics->error(rightQualifierLocation,
+ "Cannot have multiple different primitive specifiers",
+ getGeometryShaderPrimitiveTypeString(rightQualifier.primitiveType));
+ }
+ joinedQualifier.primitiveType = rightQualifier.primitiveType;
+ }
+
+ if (rightQualifier.invocations != 0)
+ {
+ if (joinedQualifier.invocations != 0 &&
+ joinedQualifier.invocations != rightQualifier.invocations)
+ {
+ diagnostics->error(rightQualifierLocation,
+ "Cannot have multiple different invocations specifiers",
+ "invocations");
+ }
+ joinedQualifier.invocations = rightQualifier.invocations;
+ }
+
+ if (rightQualifier.maxVertices != -1)
+ {
+ if (joinedQualifier.maxVertices != -1 &&
+ joinedQualifier.maxVertices != rightQualifier.maxVertices)
+ {
+ diagnostics->error(rightQualifierLocation,
+ "Cannot have multiple different max_vertices specifiers",
+ "max_vertices");
+ }
+ joinedQualifier.maxVertices = rightQualifier.maxVertices;
+ }
+
+ return joinedQualifier;
+}
+
+unsigned int TInvariantQualifierWrapper::getRank() const
+{
+ return 0u;
+}
+
+unsigned int TInterpolationQualifierWrapper::getRank() const
+{
+ return 1u;
+}
+
+unsigned int TLayoutQualifierWrapper::getRank() const
+{
+ return 2u;
+}
+
+unsigned int TStorageQualifierWrapper::getRank() const
+{
+ // Force the 'centroid' auxilary storage qualifier to be always first among all storage
+ // qualifiers.
+ if (mStorageQualifier == EvqCentroid)
+ {
+ return 3u;
+ }
+ else
+ {
+ return 4u;
+ }
+}
+
+unsigned int TMemoryQualifierWrapper::getRank() const
+{
+ return 4u;
+}
+
+unsigned int TPrecisionQualifierWrapper::getRank() const
+{
+ return 5u;
+}
+
+TTypeQualifier::TTypeQualifier(TQualifier scope, const TSourceLoc &loc)
+ : layoutQualifier(TLayoutQualifier::Create()),
+ memoryQualifier(TMemoryQualifier::Create()),
+ precision(EbpUndefined),
+ qualifier(scope),
+ invariant(false),
+ line(loc)
+{
+ ASSERT(IsScopeQualifier(qualifier));
+}
+
+TTypeQualifierBuilder::TTypeQualifierBuilder(const TStorageQualifierWrapper *scope,
+ int shaderVersion)
+ : mShaderVersion(shaderVersion)
+{
+ ASSERT(IsScopeQualifier(scope->getQualifier()));
+ mQualifiers.push_back(scope);
+}
+
+void TTypeQualifierBuilder::appendQualifier(const TQualifierWrapperBase *qualifier)
+{
+ mQualifiers.push_back(qualifier);
+}
+
+bool TTypeQualifierBuilder::checkSequenceIsValid(TDiagnostics *diagnostics) const
+{
+ bool areQualifierChecksRelaxed = AreTypeQualifierChecksRelaxed(mShaderVersion);
+ std::string errorMessage;
+ if (HasRepeatingQualifiers(mQualifiers, areQualifierChecksRelaxed, &errorMessage))
+ {
+ diagnostics->error(mQualifiers[0]->getLine(), errorMessage.c_str(), "qualifier sequence");
+ return false;
+ }
+
+ if (!areQualifierChecksRelaxed && !AreQualifiersInOrder(mQualifiers, &errorMessage))
+ {
+ diagnostics->error(mQualifiers[0]->getLine(), errorMessage.c_str(), "qualifier sequence");
+ return false;
+ }
+
+ return true;
+}
+
+TTypeQualifier TTypeQualifierBuilder::getParameterTypeQualifier(TDiagnostics *diagnostics) const
+{
+ ASSERT(IsInvariantCorrect(mQualifiers));
+ ASSERT(static_cast<const TStorageQualifierWrapper *>(mQualifiers[0])->getQualifier() ==
+ EvqTemporary);
+
+ if (!checkSequenceIsValid(diagnostics))
+ {
+ return TTypeQualifier(EvqTemporary, mQualifiers[0]->getLine());
+ }
+
+ // If the qualifier checks are relaxed, then it is easier to sort the qualifiers so
+ // that the order imposed by the GLSL ES 3.00 spec is kept. Then we can use the same code to
+ // combine the qualifiers.
+ if (AreTypeQualifierChecksRelaxed(mShaderVersion))
+ {
+ // Copy the qualifier sequence so that we can sort them.
+ QualifierSequence sortedQualifierSequence = mQualifiers;
+ SortSequence(sortedQualifierSequence);
+ return GetParameterTypeQualifierFromSortedSequence(sortedQualifierSequence, diagnostics);
+ }
+ return GetParameterTypeQualifierFromSortedSequence(mQualifiers, diagnostics);
+}
+
+TTypeQualifier TTypeQualifierBuilder::getVariableTypeQualifier(TDiagnostics *diagnostics) const
+{
+ ASSERT(IsInvariantCorrect(mQualifiers));
+
+ if (!checkSequenceIsValid(diagnostics))
+ {
+ return TTypeQualifier(
+ static_cast<const TStorageQualifierWrapper *>(mQualifiers[0])->getQualifier(),
+ mQualifiers[0]->getLine());
+ }
+
+ // If the qualifier checks are relaxed, then it is easier to sort the qualifiers so
+ // that the order imposed by the GLSL ES 3.00 spec is kept. Then we can use the same code to
+ // combine the qualifiers.
+ if (AreTypeQualifierChecksRelaxed(mShaderVersion))
+ {
+ // Copy the qualifier sequence so that we can sort them.
+ QualifierSequence sortedQualifierSequence = mQualifiers;
+ SortSequence(sortedQualifierSequence);
+ return GetVariableTypeQualifierFromSortedSequence(sortedQualifierSequence, diagnostics);
+ }
+ return GetVariableTypeQualifierFromSortedSequence(mQualifiers, diagnostics);
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/QualifierTypes.h b/src/3rdparty/angle/src/compiler/translator/QualifierTypes.h
new file mode 100644
index 0000000000..10bdeed89d
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/QualifierTypes.h
@@ -0,0 +1,191 @@
+//
+// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_QUALIFIER_TYPES_H_
+#define COMPILER_TRANSLATOR_QUALIFIER_TYPES_H_
+
+#include "common/angleutils.h"
+#include "compiler/translator/BaseTypes.h"
+#include "compiler/translator/Types.h"
+
+namespace sh
+{
+class TDiagnostics;
+
+TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier,
+ TLayoutQualifier rightQualifier,
+ const TSourceLoc &rightQualifierLocation,
+ TDiagnostics *diagnostics);
+
+enum TQualifierType
+{
+ QtInvariant,
+ QtInterpolation,
+ QtLayout,
+ QtStorage,
+ QtPrecision,
+ QtMemory
+};
+
+class TQualifierWrapperBase : angle::NonCopyable
+{
+ public:
+ POOL_ALLOCATOR_NEW_DELETE();
+ TQualifierWrapperBase(const TSourceLoc &line) : mLine(line) {}
+ virtual ~TQualifierWrapperBase(){};
+ virtual TQualifierType getType() const = 0;
+ virtual TString getQualifierString() const = 0;
+ virtual unsigned int getRank() const = 0;
+ const TSourceLoc &getLine() const { return mLine; }
+ private:
+ TSourceLoc mLine;
+};
+
+class TInvariantQualifierWrapper final : public TQualifierWrapperBase
+{
+ public:
+ TInvariantQualifierWrapper(const TSourceLoc &line) : TQualifierWrapperBase(line) {}
+ ~TInvariantQualifierWrapper() {}
+
+ TQualifierType getType() const { return QtInvariant; }
+ TString getQualifierString() const { return "invariant"; }
+ unsigned int getRank() const;
+};
+
+class TInterpolationQualifierWrapper final : public TQualifierWrapperBase
+{
+ public:
+ TInterpolationQualifierWrapper(TQualifier interpolationQualifier, const TSourceLoc &line)
+ : TQualifierWrapperBase(line), mInterpolationQualifier(interpolationQualifier)
+ {
+ }
+ ~TInterpolationQualifierWrapper() {}
+
+ TQualifierType getType() const { return QtInterpolation; }
+ TString getQualifierString() const { return sh::getQualifierString(mInterpolationQualifier); }
+ TQualifier getQualifier() const { return mInterpolationQualifier; }
+ unsigned int getRank() const;
+
+ private:
+ TQualifier mInterpolationQualifier;
+};
+
+class TLayoutQualifierWrapper final : public TQualifierWrapperBase
+{
+ public:
+ TLayoutQualifierWrapper(TLayoutQualifier layoutQualifier, const TSourceLoc &line)
+ : TQualifierWrapperBase(line), mLayoutQualifier(layoutQualifier)
+ {
+ }
+ ~TLayoutQualifierWrapper() {}
+
+ TQualifierType getType() const { return QtLayout; }
+ TString getQualifierString() const { return "layout"; }
+ const TLayoutQualifier &getQualifier() const { return mLayoutQualifier; }
+ unsigned int getRank() const;
+
+ private:
+ TLayoutQualifier mLayoutQualifier;
+};
+
+class TStorageQualifierWrapper final : public TQualifierWrapperBase
+{
+ public:
+ TStorageQualifierWrapper(TQualifier storageQualifier, const TSourceLoc &line)
+ : TQualifierWrapperBase(line), mStorageQualifier(storageQualifier)
+ {
+ }
+ ~TStorageQualifierWrapper() {}
+
+ TQualifierType getType() const { return QtStorage; }
+ TString getQualifierString() const { return sh::getQualifierString(mStorageQualifier); }
+ TQualifier getQualifier() const { return mStorageQualifier; }
+ unsigned int getRank() const;
+
+ private:
+ TQualifier mStorageQualifier;
+};
+
+class TPrecisionQualifierWrapper final : public TQualifierWrapperBase
+{
+ public:
+ TPrecisionQualifierWrapper(TPrecision precisionQualifier, const TSourceLoc &line)
+ : TQualifierWrapperBase(line), mPrecisionQualifier(precisionQualifier)
+ {
+ }
+ ~TPrecisionQualifierWrapper() {}
+
+ TQualifierType getType() const { return QtPrecision; }
+ TString getQualifierString() const { return sh::getPrecisionString(mPrecisionQualifier); }
+ TPrecision getQualifier() const { return mPrecisionQualifier; }
+ unsigned int getRank() const;
+
+ private:
+ TPrecision mPrecisionQualifier;
+};
+
+class TMemoryQualifierWrapper final : public TQualifierWrapperBase
+{
+ public:
+ TMemoryQualifierWrapper(TQualifier memoryQualifier, const TSourceLoc &line)
+ : TQualifierWrapperBase(line), mMemoryQualifier(memoryQualifier)
+ {
+ }
+ ~TMemoryQualifierWrapper() {}
+
+ TQualifierType getType() const { return QtMemory; }
+ TString getQualifierString() const { return sh::getQualifierString(mMemoryQualifier); }
+ TQualifier getQualifier() const { return mMemoryQualifier; }
+ unsigned int getRank() const;
+
+ private:
+ TQualifier mMemoryQualifier;
+};
+
+// TTypeQualifier tightly covers type_qualifier from the grammar
+struct TTypeQualifier
+{
+ // initializes all of the qualifiers and sets the scope
+ TTypeQualifier(TQualifier scope, const TSourceLoc &loc);
+
+ TLayoutQualifier layoutQualifier;
+ TMemoryQualifier memoryQualifier;
+ TPrecision precision;
+ TQualifier qualifier;
+ bool invariant;
+ TSourceLoc line;
+};
+
+// TTypeQualifierBuilder contains all of the qualifiers when type_qualifier gets parsed.
+// It is to be used to validate the qualifier sequence and build a TTypeQualifier from it.
+class TTypeQualifierBuilder : angle::NonCopyable
+{
+ public:
+ using QualifierSequence = TVector<const TQualifierWrapperBase *>;
+
+ public:
+ POOL_ALLOCATOR_NEW_DELETE();
+ TTypeQualifierBuilder(const TStorageQualifierWrapper *scope, int shaderVersion);
+ // Adds the passed qualifier to the end of the sequence.
+ void appendQualifier(const TQualifierWrapperBase *qualifier);
+ // Checks for the order of qualification and repeating qualifiers.
+ bool checkSequenceIsValid(TDiagnostics *diagnostics) const;
+ // Goes over the qualifier sequence and parses it to form a type qualifier for a function
+ // parameter.
+ // The returned object is initialized even if the parsing fails.
+ TTypeQualifier getParameterTypeQualifier(TDiagnostics *diagnostics) const;
+ // Goes over the qualifier sequence and parses it to form a type qualifier for a variable.
+ // The returned object is initialized even if the parsing fails.
+ TTypeQualifier getVariableTypeQualifier(TDiagnostics *diagnostics) const;
+
+ private:
+ QualifierSequence mQualifiers;
+ int mShaderVersion;
+};
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_QUALIFIER_TYPES_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.cpp b/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.cpp
index 14e88b749a..5233a29f19 100644
--- a/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.cpp
@@ -3,20 +3,24 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// During parsing, all constant expressions are folded to constant union nodes. The expressions that have been
-// folded may have had precision qualifiers, which should affect the precision of the consuming operation.
-// If the folded constant union nodes are written to output as such they won't have any precision qualifiers,
-// and their effect on the precision of the consuming operation is lost.
+// During parsing, all constant expressions are folded to constant union nodes. The expressions that
+// have been folded may have had precision qualifiers, which should affect the precision of the
+// consuming operation. If the folded constant union nodes are written to output as such they won't
+// have any precision qualifiers, and their effect on the precision of the consuming operation is
+// lost.
//
-// RecordConstantPrecision is an AST traverser that inspects the precision qualifiers of constants and hoists
-// the constants outside the containing expression as precision qualified named variables in case that is
-// required for correct precision propagation.
+// RecordConstantPrecision is an AST traverser that inspects the precision qualifiers of constants
+// and hoists the constants outside the containing expression as precision qualified named variables
+// in case that is required for correct precision propagation.
//
#include "compiler/translator/RecordConstantPrecision.h"
#include "compiler/translator/InfoSink.h"
-#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
namespace
{
@@ -24,7 +28,7 @@ namespace
class RecordConstantPrecisionTraverser : public TIntermTraverser
{
public:
- RecordConstantPrecisionTraverser();
+ RecordConstantPrecisionTraverser(TSymbolTable *symbolTable);
void visitConstantUnion(TIntermConstantUnion *node) override;
@@ -37,14 +41,18 @@ class RecordConstantPrecisionTraverser : public TIntermTraverser
bool mFoundHigherPrecisionConstant;
};
-RecordConstantPrecisionTraverser::RecordConstantPrecisionTraverser()
- : TIntermTraverser(true, false, true),
- mFoundHigherPrecisionConstant(false)
+RecordConstantPrecisionTraverser::RecordConstantPrecisionTraverser(TSymbolTable *symbolTable)
+ : TIntermTraverser(true, false, true, symbolTable), mFoundHigherPrecisionConstant(false)
{
}
bool RecordConstantPrecisionTraverser::operandAffectsParentOperationPrecision(TIntermTyped *operand)
{
+ if (getParentNode()->getAsCaseNode() || getParentNode()->getAsBlock())
+ {
+ return false;
+ }
+
const TIntermBinary *parentAsBinary = getParentNode()->getAsBinaryNode();
if (parentAsBinary != nullptr)
{
@@ -52,15 +60,15 @@ bool RecordConstantPrecisionTraverser::operandAffectsParentOperationPrecision(TI
// its precision has no effect.
switch (parentAsBinary->getOp())
{
- case EOpInitialize:
- case EOpAssign:
- case EOpIndexDirect:
- case EOpIndexDirectStruct:
- case EOpIndexDirectInterfaceBlock:
- case EOpIndexIndirect:
- return false;
- default:
- break;
+ case EOpInitialize:
+ case EOpAssign:
+ case EOpIndexDirect:
+ case EOpIndexDirectStruct:
+ case EOpIndexDirectInterfaceBlock:
+ case EOpIndexIndirect:
+ return false;
+ default:
+ break;
}
TIntermTyped *otherOperand = parentAsBinary->getRight();
@@ -68,9 +76,10 @@ bool RecordConstantPrecisionTraverser::operandAffectsParentOperationPrecision(TI
{
otherOperand = parentAsBinary->getLeft();
}
- // If the precision of the other child is at least as high as the precision of the constant, the precision of
- // the constant has no effect.
- if (otherOperand->getAsConstantUnion() == nullptr && otherOperand->getPrecision() >= operand->getPrecision())
+ // If the precision of the other child is at least as high as the precision of the constant,
+ // the precision of the constant has no effect.
+ if (otherOperand->getAsConstantUnion() == nullptr &&
+ otherOperand->getPrecision() >= operand->getPrecision())
{
return false;
}
@@ -92,14 +101,15 @@ bool RecordConstantPrecisionTraverser::operandAffectsParentOperationPrecision(TI
{
return false;
}
- // If the precision of operands does affect the result, but the precision of any of the other children
- // has a precision that's at least as high as the precision of the constant, the precision of the constant
- // has no effect.
+ // If the precision of operands does affect the result, but the precision of any of the
+ // other children has a precision that's at least as high as the precision of the constant,
+ // the precision of the constant has no effect.
TIntermSequence *parameters = parentAsAggregate->getSequence();
for (TIntermNode *parameter : *parameters)
{
const TIntermTyped *typedParameter = parameter->getAsTyped();
- if (parameter != operand && typedParameter != nullptr && parameter->getAsConstantUnion() == nullptr &&
+ if (parameter != operand && typedParameter != nullptr &&
+ parameter->getAsConstantUnion() == nullptr &&
typedParameter->getPrecision() >= operand->getPrecision())
{
return false;
@@ -114,37 +124,36 @@ void RecordConstantPrecisionTraverser::visitConstantUnion(TIntermConstantUnion *
if (mFoundHigherPrecisionConstant)
return;
- // If the constant has lowp or undefined precision, it can't increase the precision of consuming operations.
+ // If the constant has lowp or undefined precision, it can't increase the precision of consuming
+ // operations.
if (node->getPrecision() < EbpMedium)
return;
- // It's possible the node has no effect on the precision of the consuming expression, depending on the
- // consuming expression, and the precision of the other parameters of the expression.
+ // It's possible the node has no effect on the precision of the consuming expression, depending
+ // on the consuming expression, and the precision of the other parameters of the expression.
if (!operandAffectsParentOperationPrecision(node))
return;
- // Make the constant a precision-qualified named variable to make sure it affects the precision of the consuming
- // expression.
+ // Make the constant a precision-qualified named variable to make sure it affects the precision
+ // of the consuming expression.
TIntermSequence insertions;
insertions.push_back(createTempInitDeclaration(node, EvqConst));
insertStatementsInParentBlock(insertions);
- mReplacements.push_back(NodeUpdateEntry(getParentNode(), node, createTempSymbol(node->getType()), false));
+ queueReplacement(createTempSymbol(node->getType()), OriginalNode::IS_DROPPED);
mFoundHigherPrecisionConstant = true;
}
void RecordConstantPrecisionTraverser::nextIteration()
{
- nextTemporaryIndex();
+ nextTemporaryId();
mFoundHigherPrecisionConstant = false;
}
-} // namespace
+} // namespace
-void RecordConstantPrecision(TIntermNode *root, unsigned int *temporaryIndex)
+void RecordConstantPrecision(TIntermNode *root, TSymbolTable *symbolTable)
{
- RecordConstantPrecisionTraverser traverser;
- ASSERT(temporaryIndex != nullptr);
- traverser.useTemporaryIndex(temporaryIndex);
+ RecordConstantPrecisionTraverser traverser(symbolTable);
// Iterate as necessary, and reset the traverser between iterations.
do
{
@@ -152,6 +161,7 @@ void RecordConstantPrecision(TIntermNode *root, unsigned int *temporaryIndex)
root->traverse(&traverser);
if (traverser.foundHigherPrecisionConstant())
traverser.updateTree();
- }
- while (traverser.foundHigherPrecisionConstant());
+ } while (traverser.foundHigherPrecisionConstant());
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.h b/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.h
index 2cd401b418..f86c2a8693 100644
--- a/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.h
+++ b/src/3rdparty/angle/src/compiler/translator/RecordConstantPrecision.h
@@ -3,21 +3,26 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// During parsing, all constant expressions are folded to constant union nodes. The expressions that have been
-// folded may have had precision qualifiers, which should affect the precision of the consuming operation.
-// If the folded constant union nodes are written to output as such they won't have any precision qualifiers,
-// and their effect on the precision of the consuming operation is lost.
+// During parsing, all constant expressions are folded to constant union nodes. The expressions that
+// have been folded may have had precision qualifiers, which should affect the precision of the
+// consuming operation. If the folded constant union nodes are written to output as such they won't
+// have any precision qualifiers, and their effect on the precision of the consuming operation is
+// lost.
//
-// RecordConstantPrecision is an AST traverser that inspects the precision qualifiers of constants and hoists
-// the constants outside the containing expression as precision qualified named variables in case that is
-// required for correct precision propagation.
+// RecordConstantPrecision is an AST traverser that inspects the precision qualifiers of constants
+// and hoists the constants outside the containing expression as precision qualified named variables
+// in case that is required for correct precision propagation.
//
#ifndef COMPILER_TRANSLATOR_RECORDCONSTANTPRECISION_H_
#define COMPILER_TRANSLATOR_RECORDCONSTANTPRECISION_H_
+namespace sh
+{
class TIntermNode;
+class TSymbolTable;
-void RecordConstantPrecision(TIntermNode *root, unsigned int *temporaryIndex);
+void RecordConstantPrecision(TIntermNode *root, TSymbolTable *symbolTable);
+} // namespace sh
-#endif // COMPILER_TRANSLATOR_RECORDCONSTANTPRECISION_H_
+#endif // COMPILER_TRANSLATOR_RECORDCONSTANTPRECISION_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp
index 5e0db2ad26..55fb124a42 100644
--- a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp
@@ -7,6 +7,9 @@
#include "common/debug.h"
#include "compiler/translator/RegenerateStructNames.h"
+namespace sh
+{
+
void RegenerateStructNames::visitSymbol(TIntermSymbol *symbol)
{
ASSERT(symbol);
@@ -16,7 +19,7 @@ void RegenerateStructNames::visitSymbol(TIntermSymbol *symbol)
if (!userType)
return;
- if (mSymbolTable.findBuiltIn(userType->name(), mShaderVersion))
+ if (mSymbolTable->findBuiltIn(userType->name(), mShaderVersion))
{
// Built-in struct, do not touch it.
return;
@@ -53,30 +56,21 @@ void RegenerateStructNames::visitSymbol(TIntermSymbol *symbol)
return;
}
std::string id = Str(uniqueId);
- TString tmp = kPrefix + TString(id.c_str());
+ TString tmp = kPrefix + TString(id.c_str());
tmp += "_" + userType->name();
userType->setName(tmp);
}
-bool RegenerateStructNames::visitAggregate(Visit, TIntermAggregate *aggregate)
+bool RegenerateStructNames::visitBlock(Visit, TIntermBlock *block)
{
- ASSERT(aggregate);
- switch (aggregate->getOp())
+ ++mScopeDepth;
+ TIntermSequence &sequence = *(block->getSequence());
+ for (TIntermNode *node : sequence)
{
- case EOpSequence:
- ++mScopeDepth;
- {
- TIntermSequence &sequence = *(aggregate->getSequence());
- for (size_t ii = 0; ii < sequence.size(); ++ii)
- {
- TIntermNode *node = sequence[ii];
- ASSERT(node != NULL);
- node->traverse(this);
- }
- }
- --mScopeDepth;
- return false;
- default:
- return true;
+ node->traverse(this);
}
+ --mScopeDepth;
+ return false;
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h
index 3b98e5d709..293720b6a4 100644
--- a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h
+++ b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h
@@ -7,27 +7,29 @@
#ifndef COMPILER_TRANSLATOR_REGENERATESTRUCTNAMES_H_
#define COMPILER_TRANSLATOR_REGENERATESTRUCTNAMES_H_
-#include "compiler/translator/Intermediate.h"
+#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/SymbolTable.h"
#include <set>
+namespace sh
+{
+
class RegenerateStructNames : public TIntermTraverser
{
public:
- RegenerateStructNames(const TSymbolTable &symbolTable,
- int shaderVersion)
- : TIntermTraverser(true, false, false),
- mSymbolTable(symbolTable),
+ RegenerateStructNames(TSymbolTable *symbolTable, int shaderVersion)
+ : TIntermTraverser(true, false, false, symbolTable),
mShaderVersion(shaderVersion),
- mScopeDepth(0) {}
+ mScopeDepth(0)
+ {
+ }
protected:
void visitSymbol(TIntermSymbol *) override;
- bool visitAggregate(Visit, TIntermAggregate *) override;
+ bool visitBlock(Visit, TIntermBlock *block) override;
private:
- const TSymbolTable &mSymbolTable;
int mShaderVersion;
// Indicating the depth of the current scope.
@@ -38,4 +40,6 @@ class RegenerateStructNames : public TIntermTraverser
std::set<int> mDeclaredGlobalStructs;
};
+} // namespace sh
+
#endif // COMPILER_TRANSLATOR_REGENERATESTRUCTNAMES_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.cpp
new file mode 100644
index 0000000000..e9e6a17013
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.cpp
@@ -0,0 +1,83 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// RemoveArrayLengthMethod.cpp:
+// Fold array length expressions, including cases where the "this" node has side effects.
+// Example:
+// int i = (a = b).length();
+// int j = (func()).length();
+// becomes:
+// (a = b);
+// int i = <constant array length>;
+// func();
+// int j = <constant array length>;
+//
+// Must be run after SplitSequenceOperator, SimplifyLoopConditions and SeparateDeclarations steps
+// have been done to expressions containing calls of the array length method.
+//
+// Does nothing to length method calls done on runtime-sized arrays.
+
+#include "compiler/translator/RemoveArrayLengthMethod.h"
+
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class RemoveArrayLengthTraverser : public TIntermTraverser
+{
+ public:
+ RemoveArrayLengthTraverser() : TIntermTraverser(true, false, false), mFoundArrayLength(false) {}
+
+ bool visitUnary(Visit visit, TIntermUnary *node) override;
+
+ void nextIteration() { mFoundArrayLength = false; }
+
+ bool foundArrayLength() const { return mFoundArrayLength; }
+
+ private:
+ bool mFoundArrayLength;
+};
+
+bool RemoveArrayLengthTraverser::visitUnary(Visit visit, TIntermUnary *node)
+{
+ // The only case where we leave array length() in place is for runtime-sized arrays.
+ if (node->getOp() == EOpArrayLength && !node->getOperand()->getType().isUnsizedArray())
+ {
+ mFoundArrayLength = true;
+ if (!node->getOperand()->hasSideEffects())
+ {
+ queueReplacement(node->fold(nullptr), OriginalNode::IS_DROPPED);
+ return false;
+ }
+ insertStatementInParentBlock(node->getOperand()->deepCopy());
+ TConstantUnion *constArray = new TConstantUnion[1];
+ constArray->setIConst(node->getOperand()->getOutermostArraySize());
+ queueReplacement(new TIntermConstantUnion(constArray, node->getType()),
+ OriginalNode::IS_DROPPED);
+ return false;
+ }
+ return true;
+}
+
+} // anonymous namespace
+
+void RemoveArrayLengthMethod(TIntermBlock *root)
+{
+ RemoveArrayLengthTraverser traverser;
+ do
+ {
+ traverser.nextIteration();
+ root->traverse(&traverser);
+ if (traverser.foundArrayLength())
+ traverser.updateTree();
+ } while (traverser.foundArrayLength());
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.h b/src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.h
new file mode 100644
index 0000000000..3b2c6df824
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/RemoveArrayLengthMethod.h
@@ -0,0 +1,29 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// RemoveArrayLengthMethod.h:
+// Fold array length expressions, including cases where the "this" node has side effects.
+// Example:
+// int i = (a = b).length();
+// int j = (func()).length();
+// becomes:
+// (a = b);
+// int i = <constant array length>;
+// func();
+// int j = <constant array length>;
+//
+// Must be run after SplitSequenceOperator, SimplifyLoopConditions and SeparateDeclarations steps
+// have been done to expressions containing calls of the array length method.
+//
+// Does nothing to length method calls done on runtime-sized arrays.
+
+namespace sh
+{
+
+class TIntermBlock;
+
+void RemoveArrayLengthMethod(TIntermBlock *root);
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.cpp
index 74814f22a7..7766c1abc6 100644
--- a/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.cpp
@@ -9,14 +9,20 @@
#include "compiler/translator/RemoveDynamicIndexing.h"
+#include "compiler/translator/Diagnostics.h"
#include "compiler/translator/InfoSink.h"
-#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermNodePatternMatcher.h"
+#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/SymbolTable.h"
+namespace sh
+{
+
namespace
{
-TName GetIndexFunctionName(const TType &type, bool write)
+std::string GetIndexFunctionName(const TType &type, bool write)
{
TInfoSinkBase nameSink;
nameSink << "dyn_index_";
@@ -49,31 +55,29 @@ TName GetIndexFunctionName(const TType &type, bool write)
}
nameSink << type.getNominalSize();
}
- TString nameString = TFunction::mangleName(nameSink.c_str());
- TName name(nameString);
- name.setInternal(true);
- return name;
+ return nameSink.str();
}
-TIntermSymbol *CreateBaseSymbol(const TType &type, TQualifier qualifier)
+TIntermSymbol *CreateBaseSymbol(const TType &type, TQualifier qualifier, TSymbolTable *symbolTable)
{
- TIntermSymbol *symbol = new TIntermSymbol(0, "base", type);
+ TIntermSymbol *symbol = new TIntermSymbol(symbolTable->nextUniqueId(), "base", type);
symbol->setInternal(true);
symbol->getTypePointer()->setQualifier(qualifier);
return symbol;
}
-TIntermSymbol *CreateIndexSymbol()
+TIntermSymbol *CreateIndexSymbol(TSymbolTable *symbolTable)
{
- TIntermSymbol *symbol = new TIntermSymbol(0, "index", TType(EbtInt, EbpHigh));
+ TIntermSymbol *symbol =
+ new TIntermSymbol(symbolTable->nextUniqueId(), "index", TType(EbtInt, EbpHigh));
symbol->setInternal(true);
symbol->getTypePointer()->setQualifier(EvqIn);
return symbol;
}
-TIntermSymbol *CreateValueSymbol(const TType &type)
+TIntermSymbol *CreateValueSymbol(const TType &type, TSymbolTable *symbolTable)
{
- TIntermSymbol *symbol = new TIntermSymbol(0, "value", type);
+ TIntermSymbol *symbol = new TIntermSymbol(symbolTable->nextUniqueId(), "value", type);
symbol->setInternal(true);
symbol->getTypePointer()->setQualifier(EvqIn);
return symbol;
@@ -86,38 +90,14 @@ TIntermConstantUnion *CreateIntConstantNode(int i)
return new TIntermConstantUnion(constant, TType(EbtInt, EbpHigh));
}
-TIntermBinary *CreateIndexDirectBaseSymbolNode(const TType &indexedType,
- const TType &fieldType,
- const int index,
- TQualifier baseQualifier)
-{
- TIntermBinary *indexNode = new TIntermBinary(EOpIndexDirect);
- indexNode->setType(fieldType);
- TIntermSymbol *baseSymbol = CreateBaseSymbol(indexedType, baseQualifier);
- indexNode->setLeft(baseSymbol);
- indexNode->setRight(CreateIntConstantNode(index));
- return indexNode;
-}
-
-TIntermBinary *CreateAssignValueSymbolNode(TIntermTyped *targetNode, const TType &assignedValueType)
-{
- TIntermBinary *assignNode = new TIntermBinary(EOpAssign);
- assignNode->setType(assignedValueType);
- assignNode->setLeft(targetNode);
- assignNode->setRight(CreateValueSymbol(assignedValueType));
- return assignNode;
-}
-
TIntermTyped *EnsureSignedInt(TIntermTyped *node)
{
if (node->getBasicType() == EbtInt)
return node;
- TIntermAggregate *convertedNode = new TIntermAggregate(EOpConstructInt);
- convertedNode->setType(TType(EbtInt));
- convertedNode->getSequence()->push_back(node);
- convertedNode->setPrecisionFromChildren();
- return convertedNode;
+ TIntermSequence *arguments = new TIntermSequence();
+ arguments->push_back(node);
+ return TIntermAggregate::CreateConstructor(TType(EbtInt), arguments);
}
TType GetFieldType(const TType &indexedType)
@@ -177,7 +157,10 @@ TType GetFieldType(const TType &indexedType)
// base[1] = value;
// }
// Note that else is not used in above functions to avoid the RewriteElseBlocks transformation.
-TIntermAggregate *GetIndexFunctionDefinition(TType type, bool write)
+TIntermFunctionDefinition *GetIndexFunctionDefinition(TType type,
+ bool write,
+ const TSymbolUniqueId &functionId,
+ TSymbolTable *symbolTable)
{
ASSERT(!type.isArray());
// Conservatively use highp here, even if the indexed type is not highp. That way the code can't
@@ -185,11 +168,9 @@ TIntermAggregate *GetIndexFunctionDefinition(TType type, bool write)
// highp values are being indexed in the shader. For HLSL precision doesn't matter, but in
// principle this code could be used with multiple backends.
type.setPrecision(EbpHigh);
- TIntermAggregate *indexingFunction = new TIntermAggregate(EOpFunction);
- indexingFunction->setNameObj(GetIndexFunctionName(type, write));
TType fieldType = GetFieldType(type);
- int numCases = 0;
+ int numCases = 0;
if (type.isMatrix())
{
numCases = type.getCols();
@@ -198,41 +179,43 @@ TIntermAggregate *GetIndexFunctionDefinition(TType type, bool write)
{
numCases = type.getNominalSize();
}
- if (write)
- {
- indexingFunction->setType(TType(EbtVoid));
- }
- else
+
+ TType returnType(EbtVoid);
+ if (!write)
{
- indexingFunction->setType(fieldType);
+ returnType = fieldType;
}
- TIntermAggregate *paramsNode = new TIntermAggregate(EOpParameters);
- TQualifier baseQualifier = EvqInOut;
+ std::string functionName = GetIndexFunctionName(type, write);
+ TIntermFunctionPrototype *prototypeNode =
+ CreateInternalFunctionPrototypeNode(returnType, functionName.c_str(), functionId);
+
+ TQualifier baseQualifier = EvqInOut;
if (!write)
baseQualifier = EvqIn;
- TIntermSymbol *baseParam = CreateBaseSymbol(type, baseQualifier);
- paramsNode->getSequence()->push_back(baseParam);
- TIntermSymbol *indexParam = CreateIndexSymbol();
- paramsNode->getSequence()->push_back(indexParam);
+ TIntermSymbol *baseParam = CreateBaseSymbol(type, baseQualifier, symbolTable);
+ prototypeNode->getSequence()->push_back(baseParam);
+ TIntermSymbol *indexParam = CreateIndexSymbol(symbolTable);
+ prototypeNode->getSequence()->push_back(indexParam);
+ TIntermSymbol *valueParam = nullptr;
if (write)
{
- TIntermSymbol *valueParam = CreateValueSymbol(fieldType);
- paramsNode->getSequence()->push_back(valueParam);
+ valueParam = CreateValueSymbol(fieldType, symbolTable);
+ prototypeNode->getSequence()->push_back(valueParam);
}
- indexingFunction->getSequence()->push_back(paramsNode);
- TIntermAggregate *statementList = new TIntermAggregate(EOpSequence);
+ TIntermBlock *statementList = new TIntermBlock();
for (int i = 0; i < numCases; ++i)
{
TIntermCase *caseNode = new TIntermCase(CreateIntConstantNode(i));
statementList->getSequence()->push_back(caseNode);
TIntermBinary *indexNode =
- CreateIndexDirectBaseSymbolNode(type, fieldType, i, baseQualifier);
+ new TIntermBinary(EOpIndexDirect, baseParam->deepCopy(), CreateIndexNode(i));
if (write)
{
- TIntermBinary *assignNode = CreateAssignValueSymbolNode(indexNode, fieldType);
+ TIntermBinary *assignNode =
+ new TIntermBinary(EOpAssign, indexNode, valueParam->deepCopy());
statementList->getSequence()->push_back(assignNode);
TIntermBranch *returnNode = new TIntermBranch(EOpReturn, nullptr);
statementList->getSequence()->push_back(returnNode);
@@ -250,32 +233,33 @@ TIntermAggregate *GetIndexFunctionDefinition(TType type, bool write)
TIntermBranch *breakNode = new TIntermBranch(EOpBreak, nullptr);
statementList->getSequence()->push_back(breakNode);
- TIntermSwitch *switchNode = new TIntermSwitch(CreateIndexSymbol(), statementList);
+ TIntermSwitch *switchNode = new TIntermSwitch(indexParam->deepCopy(), statementList);
- TIntermAggregate *bodyNode = new TIntermAggregate(EOpSequence);
+ TIntermBlock *bodyNode = new TIntermBlock();
bodyNode->getSequence()->push_back(switchNode);
- TIntermBinary *cond = new TIntermBinary(EOpLessThan);
+ TIntermBinary *cond =
+ new TIntermBinary(EOpLessThan, indexParam->deepCopy(), CreateIntConstantNode(0));
cond->setType(TType(EbtBool, EbpUndefined));
- cond->setLeft(CreateIndexSymbol());
- cond->setRight(CreateIntConstantNode(0));
// Two blocks: one accesses (either reads or writes) the first element and returns,
// the other accesses the last element.
- TIntermAggregate *useFirstBlock = new TIntermAggregate(EOpSequence);
- TIntermAggregate *useLastBlock = new TIntermAggregate(EOpSequence);
+ TIntermBlock *useFirstBlock = new TIntermBlock();
+ TIntermBlock *useLastBlock = new TIntermBlock();
TIntermBinary *indexFirstNode =
- CreateIndexDirectBaseSymbolNode(type, fieldType, 0, baseQualifier);
+ new TIntermBinary(EOpIndexDirect, baseParam->deepCopy(), CreateIndexNode(0));
TIntermBinary *indexLastNode =
- CreateIndexDirectBaseSymbolNode(type, fieldType, numCases - 1, baseQualifier);
+ new TIntermBinary(EOpIndexDirect, baseParam->deepCopy(), CreateIndexNode(numCases - 1));
if (write)
{
- TIntermBinary *assignFirstNode = CreateAssignValueSymbolNode(indexFirstNode, fieldType);
+ TIntermBinary *assignFirstNode =
+ new TIntermBinary(EOpAssign, indexFirstNode, valueParam->deepCopy());
useFirstBlock->getSequence()->push_back(assignFirstNode);
TIntermBranch *returnNode = new TIntermBranch(EOpReturn, nullptr);
useFirstBlock->getSequence()->push_back(returnNode);
- TIntermBinary *assignLastNode = CreateAssignValueSymbolNode(indexLastNode, fieldType);
+ TIntermBinary *assignLastNode =
+ new TIntermBinary(EOpAssign, indexLastNode, valueParam->deepCopy());
useLastBlock->getSequence()->push_back(assignLastNode);
}
else
@@ -286,19 +270,21 @@ TIntermAggregate *GetIndexFunctionDefinition(TType type, bool write)
TIntermBranch *returnLastNode = new TIntermBranch(EOpReturn, indexLastNode);
useLastBlock->getSequence()->push_back(returnLastNode);
}
- TIntermSelection *ifNode = new TIntermSelection(cond, useFirstBlock, nullptr);
+ TIntermIfElse *ifNode = new TIntermIfElse(cond, useFirstBlock, nullptr);
bodyNode->getSequence()->push_back(ifNode);
bodyNode->getSequence()->push_back(useLastBlock);
- indexingFunction->getSequence()->push_back(bodyNode);
-
+ TIntermFunctionDefinition *indexingFunction =
+ new TIntermFunctionDefinition(prototypeNode, bodyNode);
return indexingFunction;
}
class RemoveDynamicIndexingTraverser : public TLValueTrackingTraverser
{
public:
- RemoveDynamicIndexingTraverser(const TSymbolTable &symbolTable, int shaderVersion);
+ RemoveDynamicIndexingTraverser(TSymbolTable *symbolTable,
+ int shaderVersion,
+ PerformanceDiagnostics *perfDiagnostics);
bool visitBinary(Visit visit, TIntermBinary *node) override;
@@ -309,10 +295,11 @@ class RemoveDynamicIndexingTraverser : public TLValueTrackingTraverser
bool usedTreeInsertion() const { return mUsedTreeInsertion; }
protected:
- // Sets of types that are indexed. Note that these can not store multiple variants
- // of the same type with different precisions - only one precision gets stored.
- std::set<TType> mIndexedVecAndMatrixTypes;
- std::set<TType> mWrittenVecAndMatrixTypes;
+ // Maps of types that are indexed to the indexing function ids used for them. Note that these
+ // can not store multiple variants of the same type with different precisions - only one
+ // precision gets stored.
+ std::map<TType, TSymbolUniqueId *> mIndexedVecAndMatrixTypes;
+ std::map<TType, TSymbolUniqueId *> mWrittenVecAndMatrixTypes;
bool mUsedTreeInsertion;
@@ -321,62 +308,74 @@ class RemoveDynamicIndexingTraverser : public TLValueTrackingTraverser
// V[j++][i]++.
// where V is an array of vectors, j++ will only be evaluated once.
bool mRemoveIndexSideEffectsInSubtree;
+
+ PerformanceDiagnostics *mPerfDiagnostics;
};
-RemoveDynamicIndexingTraverser::RemoveDynamicIndexingTraverser(const TSymbolTable &symbolTable,
- int shaderVersion)
+RemoveDynamicIndexingTraverser::RemoveDynamicIndexingTraverser(
+ TSymbolTable *symbolTable,
+ int shaderVersion,
+ PerformanceDiagnostics *perfDiagnostics)
: TLValueTrackingTraverser(true, false, false, symbolTable, shaderVersion),
mUsedTreeInsertion(false),
- mRemoveIndexSideEffectsInSubtree(false)
+ mRemoveIndexSideEffectsInSubtree(false),
+ mPerfDiagnostics(perfDiagnostics)
{
}
void RemoveDynamicIndexingTraverser::insertHelperDefinitions(TIntermNode *root)
{
- TIntermAggregate *rootAgg = root->getAsAggregate();
- ASSERT(rootAgg != nullptr && rootAgg->getOp() == EOpSequence);
+ TIntermBlock *rootBlock = root->getAsBlock();
+ ASSERT(rootBlock != nullptr);
TIntermSequence insertions;
- for (TType type : mIndexedVecAndMatrixTypes)
+ for (auto &type : mIndexedVecAndMatrixTypes)
{
- insertions.push_back(GetIndexFunctionDefinition(type, false));
+ insertions.push_back(
+ GetIndexFunctionDefinition(type.first, false, *type.second, mSymbolTable));
}
- for (TType type : mWrittenVecAndMatrixTypes)
+ for (auto &type : mWrittenVecAndMatrixTypes)
{
- insertions.push_back(GetIndexFunctionDefinition(type, true));
+ insertions.push_back(
+ GetIndexFunctionDefinition(type.first, true, *type.second, mSymbolTable));
}
- mInsertions.push_back(NodeInsertMultipleEntry(rootAgg, 0, insertions, TIntermSequence()));
+ rootBlock->insertChildNodes(0, insertions);
}
// Create a call to dyn_index_*() based on an indirect indexing op node
TIntermAggregate *CreateIndexFunctionCall(TIntermBinary *node,
- TIntermTyped *indexedNode,
- TIntermTyped *index)
+ TIntermTyped *index,
+ const TSymbolUniqueId &functionId)
{
ASSERT(node->getOp() == EOpIndexIndirect);
- TIntermAggregate *indexingCall = new TIntermAggregate(EOpFunctionCall);
+ TIntermSequence *arguments = new TIntermSequence();
+ arguments->push_back(node->getLeft());
+ arguments->push_back(index);
+
+ TType fieldType = GetFieldType(node->getLeft()->getType());
+ std::string functionName = GetIndexFunctionName(node->getLeft()->getType(), false);
+ TIntermAggregate *indexingCall =
+ CreateInternalFunctionCallNode(fieldType, functionName.c_str(), functionId, arguments);
indexingCall->setLine(node->getLine());
- indexingCall->setUserDefined();
- indexingCall->setNameObj(GetIndexFunctionName(indexedNode->getType(), false));
- indexingCall->getSequence()->push_back(indexedNode);
- indexingCall->getSequence()->push_back(index);
-
- TType fieldType = GetFieldType(indexedNode->getType());
- indexingCall->setType(fieldType);
+ indexingCall->getFunctionSymbolInfo()->setKnownToNotHaveSideEffects(true);
return indexingCall;
}
TIntermAggregate *CreateIndexedWriteFunctionCall(TIntermBinary *node,
TIntermTyped *index,
- TIntermTyped *writtenValue)
+ TIntermTyped *writtenValue,
+ const TSymbolUniqueId &functionId)
{
- // Deep copy the left node so that two pointers to the same node don't end up in the tree.
- TIntermNode *leftCopy = node->getLeft()->deepCopy();
- ASSERT(leftCopy != nullptr && leftCopy->getAsTyped() != nullptr);
+ ASSERT(node->getOp() == EOpIndexIndirect);
+ TIntermSequence *arguments = new TIntermSequence();
+ // Deep copy the child nodes so that two pointers to the same node don't end up in the tree.
+ arguments->push_back(node->getLeft()->deepCopy());
+ arguments->push_back(index->deepCopy());
+ arguments->push_back(writtenValue);
+
+ std::string functionName = GetIndexFunctionName(node->getLeft()->getType(), true);
TIntermAggregate *indexedWriteCall =
- CreateIndexFunctionCall(node, leftCopy->getAsTyped(), index);
- indexedWriteCall->setNameObj(GetIndexFunctionName(node->getLeft()->getType(), true));
- indexedWriteCall->setType(TType(EbtVoid));
- indexedWriteCall->getSequence()->push_back(writtenValue);
+ CreateInternalFunctionCallNode(TType(EbtVoid), functionName.c_str(), functionId, arguments);
+ indexedWriteCall->setLine(node->getLine());
return indexedWriteCall;
}
@@ -397,23 +396,40 @@ bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *nod
// Now v_expr[s0] can be safely executed several times without unintended side effects.
// Init the temp variable holding the index
- TIntermAggregate *initIndex = createTempInitDeclaration(node->getRight());
- TIntermSequence insertions;
- insertions.push_back(initIndex);
- insertStatementsInParentBlock(insertions);
+ TIntermDeclaration *initIndex = createTempInitDeclaration(node->getRight());
+ insertStatementInParentBlock(initIndex);
mUsedTreeInsertion = true;
// Replace the index with the temp variable
TIntermSymbol *tempIndex = createTempSymbol(node->getRight()->getType());
- NodeUpdateEntry replaceIndex(node, node->getRight(), tempIndex, false);
- mReplacements.push_back(replaceIndex);
+ queueReplacementWithParent(node, node->getRight(), tempIndex, OriginalNode::IS_DROPPED);
}
- else if (!node->getLeft()->isArray() && node->getLeft()->getBasicType() != EbtStruct)
+ else if (IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(node))
{
+ mPerfDiagnostics->warning(node->getLine(),
+ "Performance: dynamic indexing of vectors and "
+ "matrices is emulated and can be slow.",
+ "[]");
bool write = isLValueRequiredHere();
- TType type = node->getLeft()->getType();
- mIndexedVecAndMatrixTypes.insert(type);
+#if defined(ANGLE_ENABLE_ASSERTS)
+ // Make sure that IntermNodePatternMatcher is consistent with the slightly differently
+ // implemented checks in this traverser.
+ IntermNodePatternMatcher matcher(
+ IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue);
+ ASSERT(matcher.match(node, getParentNode(), isLValueRequiredHere()) == write);
+#endif
+
+ const TType &type = node->getLeft()->getType();
+ TSymbolUniqueId *indexingFunctionId = new TSymbolUniqueId(mSymbolTable);
+ if (mIndexedVecAndMatrixTypes.find(type) == mIndexedVecAndMatrixTypes.end())
+ {
+ mIndexedVecAndMatrixTypes[type] = indexingFunctionId;
+ }
+ else
+ {
+ indexingFunctionId = mIndexedVecAndMatrixTypes[type];
+ }
if (write)
{
@@ -432,10 +448,30 @@ bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *nod
mRemoveIndexSideEffectsInSubtree = true;
return true;
}
+
+ TIntermBinary *leftBinary = node->getLeft()->getAsBinaryNode();
+ if (leftBinary != nullptr &&
+ IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(leftBinary))
+ {
+ // This is a case like:
+ // mat2 m;
+ // m[a][b]++;
+ // Process the child node m[a] first.
+ return true;
+ }
+
// TODO(oetuaho@nvidia.com): This is not optimal if the expression using the value
// only writes it and doesn't need the previous value. http://anglebug.com/1116
- mWrittenVecAndMatrixTypes.insert(type);
+ TSymbolUniqueId *indexedWriteFunctionId = new TSymbolUniqueId(mSymbolTable);
+ if (mWrittenVecAndMatrixTypes.find(type) == mWrittenVecAndMatrixTypes.end())
+ {
+ mWrittenVecAndMatrixTypes[type] = indexedWriteFunctionId;
+ }
+ else
+ {
+ indexedWriteFunctionId = mWrittenVecAndMatrixTypes[type];
+ }
TType fieldType = GetFieldType(type);
TIntermSequence insertionsBefore;
@@ -443,28 +479,26 @@ bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *nod
// Store the index in a temporary signed int variable.
TIntermTyped *indexInitializer = EnsureSignedInt(node->getRight());
- TIntermAggregate *initIndex = createTempInitDeclaration(indexInitializer);
+ TIntermDeclaration *initIndex = createTempInitDeclaration(indexInitializer);
initIndex->setLine(node->getLine());
insertionsBefore.push_back(initIndex);
- TIntermAggregate *indexingCall = CreateIndexFunctionCall(
- node, node->getLeft(), createTempSymbol(indexInitializer->getType()));
-
- // Create a node for referring to the index after the nextTemporaryIndex() call
+ // Create a node for referring to the index after the nextTemporaryId() call
// below.
TIntermSymbol *tempIndex = createTempSymbol(indexInitializer->getType());
- nextTemporaryIndex(); // From now on, creating temporary symbols that refer to the
- // field value.
+ TIntermAggregate *indexingCall =
+ CreateIndexFunctionCall(node, tempIndex, *indexingFunctionId);
+
+ nextTemporaryId(); // From now on, creating temporary symbols that refer to the
+ // field value.
insertionsBefore.push_back(createTempInitDeclaration(indexingCall));
- TIntermAggregate *indexedWriteCall =
- CreateIndexedWriteFunctionCall(node, tempIndex, createTempSymbol(fieldType));
+ TIntermAggregate *indexedWriteCall = CreateIndexedWriteFunctionCall(
+ node, tempIndex, createTempSymbol(fieldType), *indexedWriteFunctionId);
insertionsAfter.push_back(indexedWriteCall);
insertStatementsInParentBlock(insertionsBefore, insertionsAfter);
- NodeUpdateEntry replaceIndex(getParentNode(), node, createTempSymbol(fieldType),
- false);
- mReplacements.push_back(replaceIndex);
+ queueReplacement(createTempSymbol(fieldType), OriginalNode::IS_DROPPED);
mUsedTreeInsertion = true;
}
else
@@ -476,9 +510,8 @@ bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *nod
// If the index_expr is unsigned, we'll convert it to signed.
ASSERT(!mRemoveIndexSideEffectsInSubtree);
TIntermAggregate *indexingCall = CreateIndexFunctionCall(
- node, node->getLeft(), EnsureSignedInt(node->getRight()));
- NodeUpdateEntry replaceIndex(getParentNode(), node, indexingCall, false);
- mReplacements.push_back(replaceIndex);
+ node, EnsureSignedInt(node->getRight()), *indexingFunctionId);
+ queueReplacement(indexingCall, OriginalNode::IS_DROPPED);
}
}
}
@@ -489,25 +522,29 @@ void RemoveDynamicIndexingTraverser::nextIteration()
{
mUsedTreeInsertion = false;
mRemoveIndexSideEffectsInSubtree = false;
- nextTemporaryIndex();
+ nextTemporaryId();
}
} // namespace
void RemoveDynamicIndexing(TIntermNode *root,
- unsigned int *temporaryIndex,
- const TSymbolTable &symbolTable,
- int shaderVersion)
+ TSymbolTable *symbolTable,
+ int shaderVersion,
+ PerformanceDiagnostics *perfDiagnostics)
{
- RemoveDynamicIndexingTraverser traverser(symbolTable, shaderVersion);
- ASSERT(temporaryIndex != nullptr);
- traverser.useTemporaryIndex(temporaryIndex);
+ RemoveDynamicIndexingTraverser traverser(symbolTable, shaderVersion, perfDiagnostics);
do
{
traverser.nextIteration();
root->traverse(&traverser);
traverser.updateTree();
} while (traverser.usedTreeInsertion());
+ // TODO(oetuaho@nvidia.com): It might be nicer to add the helper definitions also in the middle
+ // of traversal. Now the tree ends up in an inconsistent state in the middle, since there are
+ // function call nodes with no corresponding definition nodes. This needs special handling in
+ // TIntermLValueTrackingTraverser, and creates intricacies that are not easily apparent from a
+ // superficial reading of the code.
traverser.insertHelperDefinitions(root);
- traverser.updateTree();
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.h b/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.h
index ae3a93c9b1..543cf569a6 100644
--- a/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.h
+++ b/src/3rdparty/angle/src/compiler/translator/RemoveDynamicIndexing.h
@@ -10,12 +10,18 @@
#ifndef COMPILER_TRANSLATOR_REMOVEDYNAMICINDEXING_H_
#define COMPILER_TRANSLATOR_REMOVEDYNAMICINDEXING_H_
+namespace sh
+{
+
class TIntermNode;
class TSymbolTable;
+class PerformanceDiagnostics;
void RemoveDynamicIndexing(TIntermNode *root,
- unsigned int *temporaryIndex,
- const TSymbolTable &symbolTable,
- int shaderVersion);
+ TSymbolTable *symbolTable,
+ int shaderVersion,
+ PerformanceDiagnostics *perfDiagnostics);
+
+} // namespace sh
#endif // COMPILER_TRANSLATOR_REMOVEDYNAMICINDEXING_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.cpp
new file mode 100644
index 0000000000..b39c912e9c
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.cpp
@@ -0,0 +1,56 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// RemoveEmptySwitchStatements.cpp: Remove switch statements that have an empty statement list.
+
+#include "compiler/translator/RemoveEmptySwitchStatements.h"
+
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class RemoveEmptySwitchStatementsTraverser : public TIntermTraverser
+{
+ public:
+ RemoveEmptySwitchStatementsTraverser() : TIntermTraverser(true, false, false) {}
+
+ bool visitSwitch(Visit visit, TIntermSwitch *node);
+};
+
+bool RemoveEmptySwitchStatementsTraverser::visitSwitch(Visit visit, TIntermSwitch *node)
+{
+ if (node->getStatementList()->getSequence()->empty())
+ {
+ // Just output the init statement.
+ if (node->getInit()->hasSideEffects())
+ {
+ queueReplacement(node->getInit(), OriginalNode::IS_DROPPED);
+ }
+ else
+ {
+ TIntermSequence emptyReplacement;
+ ASSERT(getParentNode()->getAsBlock());
+ mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(),
+ node, emptyReplacement));
+ }
+ return false; // Nothing inside the child nodes to traverse.
+ }
+ return true;
+}
+
+} // anonymous namespace
+
+void RemoveEmptySwitchStatements(TIntermBlock *root)
+{
+ RemoveEmptySwitchStatementsTraverser traverser;
+ root->traverse(&traverser);
+ traverser.updateTree();
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.h b/src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.h
new file mode 100644
index 0000000000..1018a50d82
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/RemoveEmptySwitchStatements.h
@@ -0,0 +1,18 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// RemoveEmptySwitchStatements.h: Remove switch statements that have an empty statement list.
+
+#ifndef COMPILER_TRANSLATOR_REMOVEEMPTYSWITCHSTATEMENTS_H_
+#define COMPILER_TRANSLATOR_REMOVEEMPTYSWITCHSTATEMENTS_H_
+
+namespace sh
+{
+class TIntermBlock;
+
+void RemoveEmptySwitchStatements(TIntermBlock *root);
+}
+
+#endif // COMPILER_TRANSLATOR_REMOVEEMPTYSWITCHSTATEMENTS_H_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.cpp
new file mode 100644
index 0000000000..4b533dc7b5
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.cpp
@@ -0,0 +1,43 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/RemoveInvariantDeclaration.h"
+
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
+
+namespace
+{
+
+// An AST traverser that removes invariant declaration for input in fragment shader
+// when GLSL >= 4.20 and for output in vertex shader when GLSL < 4.2.
+class RemoveInvariantDeclarationTraverser : public TIntermTraverser
+{
+ public:
+ RemoveInvariantDeclarationTraverser() : TIntermTraverser(true, false, false) {}
+
+ private:
+ bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override
+ {
+ TIntermSequence emptyReplacement;
+ mMultiReplacements.push_back(
+ NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(), node, emptyReplacement));
+ return false;
+ }
+};
+
+} // anonymous namespace
+
+void RemoveInvariantDeclaration(TIntermNode *root)
+{
+ RemoveInvariantDeclarationTraverser traverser;
+ root->traverse(&traverser);
+ traverser.updateTree();
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.h b/src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.h
new file mode 100644
index 0000000000..cf9d4aa4c2
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/RemoveInvariantDeclaration.h
@@ -0,0 +1,18 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_REMOVEINVARIANTDECLARATION_H_
+#define COMPILER_TRANSLATOR_REMOVEINVARIANTDECLARATION_H_
+
+class TIntermNode;
+namespace sh
+{
+
+void RemoveInvariantDeclaration(TIntermNode *root);
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_REMOVEINVARIANTDECLARATION_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.cpp
new file mode 100644
index 0000000000..b86d64d7a3
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.cpp
@@ -0,0 +1,116 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// RemoveNoOpCasesFromEndOfSwitchStatements.cpp: Clean up cases from the end of a switch statement
+// that only contain no-ops.
+
+#include "compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h"
+
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/IntermTraverse.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+namespace
+{
+
+bool AreEmptyBlocks(TIntermSequence *statements, size_t i);
+
+bool IsEmptyBlock(TIntermNode *node)
+{
+ TIntermBlock *asBlock = node->getAsBlock();
+ if (asBlock)
+ {
+ if (asBlock->getSequence()->empty())
+ {
+ return true;
+ }
+ return AreEmptyBlocks(asBlock->getSequence(), 0u);
+ }
+ // Empty declarations should have already been pruned, otherwise they would need to be handled
+ // here. Note that declarations for struct types do contain a nameless child node.
+ ASSERT(node->getAsDeclarationNode() == nullptr ||
+ !node->getAsDeclarationNode()->getSequence()->empty());
+ // Pure literal statements should also already be pruned.
+ ASSERT(node->getAsConstantUnion() == nullptr);
+ return false;
+}
+
+// Return true if all statements in "statements" starting from index i consist only of empty blocks
+// and no-op statements. Returns true also if there are no statements.
+bool AreEmptyBlocks(TIntermSequence *statements, size_t i)
+{
+ for (; i < statements->size(); ++i)
+ {
+ if (!IsEmptyBlock(statements->at(i)))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+void RemoveNoOpCasesFromEndOfStatementList(TIntermBlock *statementList, TSymbolTable *symbolTable)
+{
+ TIntermSequence *statements = statementList->getSequence();
+
+ bool foundDeadCase = false;
+ do
+ {
+ if (statements->empty())
+ {
+ return;
+ }
+
+ // Find the last case label.
+ size_t i = statements->size();
+ while (i > 0u && !(*statements)[i - 1]->getAsCaseNode())
+ {
+ --i;
+ }
+ // Now i is the index of the first statement following the last label inside the switch
+ // statement.
+ ASSERT(i > 0u);
+
+ foundDeadCase = AreEmptyBlocks(statements, i);
+ if (foundDeadCase)
+ {
+ statements->erase(statements->begin() + (i - 1u), statements->end());
+ }
+ } while (foundDeadCase);
+}
+
+class RemoveNoOpCasesFromEndOfSwitchTraverser : public TIntermTraverser
+{
+ public:
+ RemoveNoOpCasesFromEndOfSwitchTraverser(TSymbolTable *symbolTable)
+ : TIntermTraverser(true, false, false, symbolTable)
+ {
+ }
+
+ bool visitSwitch(Visit visit, TIntermSwitch *node) override;
+};
+
+bool RemoveNoOpCasesFromEndOfSwitchTraverser::visitSwitch(Visit visit, TIntermSwitch *node)
+{
+ // Here we may mutate the statement list, but it's safe since traversal has not yet reached
+ // there.
+ RemoveNoOpCasesFromEndOfStatementList(node->getStatementList(), mSymbolTable);
+ // Handle also nested switch statements.
+ return true;
+}
+
+} // anonymous namespace
+
+void RemoveNoOpCasesFromEndOfSwitchStatements(TIntermBlock *root, TSymbolTable *symbolTable)
+{
+ RemoveNoOpCasesFromEndOfSwitchTraverser traverser(symbolTable);
+ root->traverse(&traverser);
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h b/src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h
new file mode 100644
index 0000000000..ebd75eb774
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h
@@ -0,0 +1,21 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// RemoveNoOpCasesFromEndOfSwitchStatements.h: Clean up cases from the end of a switch statement
+// that only contain no-ops.
+
+#ifndef COMPILER_TRANSLATOR_REMOVENOOPCASESFROMENDOFSWITCHSTATEMENTS_H_
+#define COMPILER_TRANSLATOR_REMOVENOOPCASESFROMENDOFSWITCHSTATEMENTS_H_
+
+namespace sh
+{
+class TIntermBlock;
+class TSymbolTable;
+
+void RemoveNoOpCasesFromEndOfSwitchStatements(TIntermBlock *root, TSymbolTable *symbolTable);
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_REMOVENOOPCASESFROMENDOFSWITCHSTATEMENTS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RemovePow.cpp b/src/3rdparty/angle/src/compiler/translator/RemovePow.cpp
index 6dbb48da9c..b2cdac55f0 100644
--- a/src/3rdparty/angle/src/compiler/translator/RemovePow.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/RemovePow.cpp
@@ -11,7 +11,10 @@
#include "compiler/translator/RemovePow.h"
#include "compiler/translator/InfoSink.h"
-#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
namespace
{
@@ -43,8 +46,7 @@ class RemovePowTraverser : public TIntermTraverser
};
RemovePowTraverser::RemovePowTraverser()
- : TIntermTraverser(true, false, false),
- mNeedAnotherIteration(false)
+ : TIntermTraverser(true, false, false), mNeedAnotherIteration(false)
{
}
@@ -52,31 +54,20 @@ bool RemovePowTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
{
if (IsProblematicPow(node))
{
- TInfoSink nullSink;
-
TIntermTyped *x = node->getSequence()->at(0)->getAsTyped();
TIntermTyped *y = node->getSequence()->at(1)->getAsTyped();
- TIntermUnary *log = new TIntermUnary(EOpLog2);
- log->setOperand(x);
+ TIntermUnary *log = new TIntermUnary(EOpLog2, x);
log->setLine(node->getLine());
- log->setType(x->getType());
- TIntermBinary *mul = new TIntermBinary(EOpMul);
- mul->setLeft(y);
- mul->setRight(log);
+ TOperator op = TIntermBinary::GetMulOpBasedOnOperands(y->getType(), log->getType());
+ TIntermBinary *mul = new TIntermBinary(op, y, log);
mul->setLine(node->getLine());
- bool valid = mul->promote(nullSink);
- UNUSED_ASSERTION_VARIABLE(valid);
- ASSERT(valid);
- TIntermUnary *exp = new TIntermUnary(EOpExp2);
- exp->setOperand(mul);
+ TIntermUnary *exp = new TIntermUnary(EOpExp2, mul);
exp->setLine(node->getLine());
- exp->setType(node->getType());
- NodeUpdateEntry replacePow(getParentNode(), node, exp, false);
- mReplacements.push_back(replacePow);
+ queueReplacement(exp, OriginalNode::IS_DROPPED);
// If the x parameter also needs to be replaced, we need to do that in another traversal,
// since it's parent node will change in a way that's not handled correctly by updateTree().
@@ -89,7 +80,7 @@ bool RemovePowTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
return true;
}
-} // namespace
+} // namespace
void RemovePow(TIntermNode *root)
{
@@ -100,6 +91,7 @@ void RemovePow(TIntermNode *root)
traverser.nextIteration();
root->traverse(&traverser);
traverser.updateTree();
- }
- while (traverser.needAnotherIteration());
+ } while (traverser.needAnotherIteration());
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RemovePow.h b/src/3rdparty/angle/src/compiler/translator/RemovePow.h
index 40f9d672b2..3cd84988a9 100644
--- a/src/3rdparty/angle/src/compiler/translator/RemovePow.h
+++ b/src/3rdparty/angle/src/compiler/translator/RemovePow.h
@@ -11,8 +11,11 @@
#ifndef COMPILER_TRANSLATOR_REMOVEPOW_H_
#define COMPILER_TRANSLATOR_REMOVEPOW_H_
+namespace sh
+{
class TIntermNode;
void RemovePow(TIntermNode *root);
+} // namespace sh
-#endif // COMPILER_TRANSLATOR_REMOVEPOW_H_
+#endif // COMPILER_TRANSLATOR_REMOVEPOW_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp
index b278b53436..dea949f448 100644
--- a/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp
@@ -3,36 +3,91 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
+// RemoveSwitchFallThrough.cpp: Remove fall-through from switch statements.
+// Note that it is unsafe to do further AST transformations on the AST generated
+// by this function. It leaves duplicate nodes in the AST making replacements
+// unreliable.
#include "compiler/translator/RemoveSwitchFallThrough.h"
-TIntermAggregate *RemoveSwitchFallThrough::removeFallThrough(TIntermAggregate *statementList)
+#include "compiler/translator/Diagnostics.h"
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class RemoveSwitchFallThroughTraverser : public TIntermTraverser
+{
+ public:
+ static TIntermBlock *removeFallThrough(TIntermBlock *statementList,
+ PerformanceDiagnostics *perfDiagnostics);
+
+ private:
+ RemoveSwitchFallThroughTraverser(TIntermBlock *statementList,
+ PerformanceDiagnostics *perfDiagnostics);
+
+ void visitSymbol(TIntermSymbol *node) override;
+ void visitConstantUnion(TIntermConstantUnion *node) override;
+ bool visitDeclaration(Visit, TIntermDeclaration *node) override;
+ bool visitBinary(Visit, TIntermBinary *node) override;
+ bool visitUnary(Visit, TIntermUnary *node) override;
+ bool visitTernary(Visit visit, TIntermTernary *node) override;
+ bool visitSwizzle(Visit, TIntermSwizzle *node) override;
+ bool visitIfElse(Visit visit, TIntermIfElse *node) override;
+ bool visitSwitch(Visit, TIntermSwitch *node) override;
+ bool visitCase(Visit, TIntermCase *node) override;
+ bool visitAggregate(Visit, TIntermAggregate *node) override;
+ bool visitBlock(Visit, TIntermBlock *node) override;
+ bool visitLoop(Visit, TIntermLoop *node) override;
+ bool visitBranch(Visit, TIntermBranch *node) override;
+
+ void outputSequence(TIntermSequence *sequence, size_t startIndex);
+ void handlePreviousCase();
+
+ TIntermBlock *mStatementList;
+ TIntermBlock *mStatementListOut;
+ bool mLastStatementWasBreak;
+ TIntermBlock *mPreviousCase;
+ std::vector<TIntermBlock *> mCasesSharingBreak;
+ PerformanceDiagnostics *mPerfDiagnostics;
+};
+
+TIntermBlock *RemoveSwitchFallThroughTraverser::removeFallThrough(
+ TIntermBlock *statementList,
+ PerformanceDiagnostics *perfDiagnostics)
{
- RemoveSwitchFallThrough rm(statementList);
+ RemoveSwitchFallThroughTraverser rm(statementList, perfDiagnostics);
ASSERT(statementList);
statementList->traverse(&rm);
- bool lastStatementWasBreak = rm.mLastStatementWasBreak;
- rm.mLastStatementWasBreak = true;
- rm.handlePreviousCase();
- if (!lastStatementWasBreak)
+ ASSERT(rm.mPreviousCase || statementList->getSequence()->empty());
+ if (!rm.mLastStatementWasBreak && rm.mPreviousCase)
{
+ // Make sure that there's a branch at the end of the final case inside the switch statement.
+ // This also ensures that any cases that fall through to the final case will get the break.
TIntermBranch *finalBreak = new TIntermBranch(EOpBreak, nullptr);
- rm.mStatementListOut->getSequence()->push_back(finalBreak);
+ rm.mPreviousCase->getSequence()->push_back(finalBreak);
+ rm.mLastStatementWasBreak = true;
}
+ rm.handlePreviousCase();
return rm.mStatementListOut;
}
-RemoveSwitchFallThrough::RemoveSwitchFallThrough(TIntermAggregate *statementList)
+RemoveSwitchFallThroughTraverser::RemoveSwitchFallThroughTraverser(
+ TIntermBlock *statementList,
+ PerformanceDiagnostics *perfDiagnostics)
: TIntermTraverser(true, false, false),
mStatementList(statementList),
mLastStatementWasBreak(false),
- mPreviousCase(nullptr)
+ mPreviousCase(nullptr),
+ mPerfDiagnostics(perfDiagnostics)
{
- mStatementListOut = new TIntermAggregate();
- mStatementListOut->setOp(EOpSequence);
+ mStatementListOut = new TIntermBlock();
}
-void RemoveSwitchFallThrough::visitSymbol(TIntermSymbol *node)
+void RemoveSwitchFallThroughTraverser::visitSymbol(TIntermSymbol *node)
{
// Note that this assumes that switch statements which don't begin by a case statement
// have already been weeded out in validation.
@@ -40,36 +95,57 @@ void RemoveSwitchFallThrough::visitSymbol(TIntermSymbol *node)
mLastStatementWasBreak = false;
}
-void RemoveSwitchFallThrough::visitConstantUnion(TIntermConstantUnion *node)
+void RemoveSwitchFallThroughTraverser::visitConstantUnion(TIntermConstantUnion *node)
+{
+ // Conditions of case labels are not traversed, so this is a constant statement like "0;".
+ // These are no-ops so there's no need to add them back to the statement list. Should have
+ // already been pruned out of the AST, in fact.
+ UNREACHABLE();
+}
+
+bool RemoveSwitchFallThroughTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
+{
+ mPreviousCase->getSequence()->push_back(node);
+ mLastStatementWasBreak = false;
+ return false;
+}
+
+bool RemoveSwitchFallThroughTraverser::visitBinary(Visit, TIntermBinary *node)
{
- // Conditions of case labels are not traversed, so this is some other constant
- // Could be just a statement like "0;"
mPreviousCase->getSequence()->push_back(node);
mLastStatementWasBreak = false;
+ return false;
}
-bool RemoveSwitchFallThrough::visitBinary(Visit, TIntermBinary *node)
+bool RemoveSwitchFallThroughTraverser::visitUnary(Visit, TIntermUnary *node)
{
mPreviousCase->getSequence()->push_back(node);
mLastStatementWasBreak = false;
return false;
}
-bool RemoveSwitchFallThrough::visitUnary(Visit, TIntermUnary *node)
+bool RemoveSwitchFallThroughTraverser::visitTernary(Visit, TIntermTernary *node)
{
mPreviousCase->getSequence()->push_back(node);
mLastStatementWasBreak = false;
return false;
}
-bool RemoveSwitchFallThrough::visitSelection(Visit, TIntermSelection *node)
+bool RemoveSwitchFallThroughTraverser::visitSwizzle(Visit, TIntermSwizzle *node)
{
mPreviousCase->getSequence()->push_back(node);
mLastStatementWasBreak = false;
return false;
}
-bool RemoveSwitchFallThrough::visitSwitch(Visit, TIntermSwitch *node)
+bool RemoveSwitchFallThroughTraverser::visitIfElse(Visit, TIntermIfElse *node)
+{
+ mPreviousCase->getSequence()->push_back(node);
+ mLastStatementWasBreak = false;
+ return false;
+}
+
+bool RemoveSwitchFallThroughTraverser::visitSwitch(Visit, TIntermSwitch *node)
{
mPreviousCase->getSequence()->push_back(node);
mLastStatementWasBreak = false;
@@ -77,7 +153,7 @@ bool RemoveSwitchFallThrough::visitSwitch(Visit, TIntermSwitch *node)
return false;
}
-void RemoveSwitchFallThrough::outputSequence(TIntermSequence *sequence, size_t startIndex)
+void RemoveSwitchFallThroughTraverser::outputSequence(TIntermSequence *sequence, size_t startIndex)
{
for (size_t i = startIndex; i < sequence->size(); ++i)
{
@@ -85,20 +161,16 @@ void RemoveSwitchFallThrough::outputSequence(TIntermSequence *sequence, size_t s
}
}
-void RemoveSwitchFallThrough::handlePreviousCase()
+void RemoveSwitchFallThroughTraverser::handlePreviousCase()
{
if (mPreviousCase)
mCasesSharingBreak.push_back(mPreviousCase);
if (mLastStatementWasBreak)
{
- bool labelsWithNoStatements = true;
for (size_t i = 0; i < mCasesSharingBreak.size(); ++i)
{
- if (mCasesSharingBreak.at(i)->getSequence()->size() > 1)
- {
- labelsWithNoStatements = false;
- }
- if (labelsWithNoStatements)
+ ASSERT(!mCasesSharingBreak.at(i)->getSequence()->empty());
+ if (mCasesSharingBreak.at(i)->getSequence()->size() == 1)
{
// Fall-through is allowed in case the label has no statements.
outputSequence(mCasesSharingBreak.at(i)->getSequence(), 0);
@@ -106,52 +178,93 @@ void RemoveSwitchFallThrough::handlePreviousCase()
else
{
// Include all the statements that this case can fall through under the same label.
+ if (mCasesSharingBreak.size() > i + 1u)
+ {
+ mPerfDiagnostics->warning(mCasesSharingBreak.at(i)->getLine(),
+ "Performance: non-empty fall-through cases in "
+ "switch statements generate extra code.",
+ "switch");
+ }
for (size_t j = i; j < mCasesSharingBreak.size(); ++j)
{
- size_t startIndex = j > i ? 1 : 0; // Add the label only from the first sequence.
+ size_t startIndex =
+ j > i ? 1 : 0; // Add the label only from the first sequence.
outputSequence(mCasesSharingBreak.at(j)->getSequence(), startIndex);
-
}
}
}
mCasesSharingBreak.clear();
}
mLastStatementWasBreak = false;
- mPreviousCase = nullptr;
+ mPreviousCase = nullptr;
}
-bool RemoveSwitchFallThrough::visitCase(Visit, TIntermCase *node)
+bool RemoveSwitchFallThroughTraverser::visitCase(Visit, TIntermCase *node)
{
handlePreviousCase();
- mPreviousCase = new TIntermAggregate();
- mPreviousCase->setOp(EOpSequence);
+ mPreviousCase = new TIntermBlock();
mPreviousCase->getSequence()->push_back(node);
+ mPreviousCase->setLine(node->getLine());
// Don't traverse the condition of the case statement
return false;
}
-bool RemoveSwitchFallThrough::visitAggregate(Visit, TIntermAggregate *node)
+bool RemoveSwitchFallThroughTraverser::visitAggregate(Visit, TIntermAggregate *node)
+{
+ mPreviousCase->getSequence()->push_back(node);
+ mLastStatementWasBreak = false;
+ return false;
+}
+
+bool DoesBlockAlwaysBreak(TIntermBlock *node)
+{
+ if (node->getSequence()->empty())
+ {
+ return false;
+ }
+
+ TIntermBlock *lastStatementAsBlock = node->getSequence()->back()->getAsBlock();
+ if (lastStatementAsBlock)
+ {
+ return DoesBlockAlwaysBreak(lastStatementAsBlock);
+ }
+
+ TIntermBranch *lastStatementAsBranch = node->getSequence()->back()->getAsBranchNode();
+ return lastStatementAsBranch != nullptr;
+}
+
+bool RemoveSwitchFallThroughTraverser::visitBlock(Visit, TIntermBlock *node)
{
if (node != mStatementList)
{
mPreviousCase->getSequence()->push_back(node);
- mLastStatementWasBreak = false;
+ mLastStatementWasBreak = DoesBlockAlwaysBreak(node);
return false;
}
return true;
}
-bool RemoveSwitchFallThrough::visitLoop(Visit, TIntermLoop *node)
+bool RemoveSwitchFallThroughTraverser::visitLoop(Visit, TIntermLoop *node)
{
mPreviousCase->getSequence()->push_back(node);
mLastStatementWasBreak = false;
return false;
}
-bool RemoveSwitchFallThrough::visitBranch(Visit, TIntermBranch *node)
+bool RemoveSwitchFallThroughTraverser::visitBranch(Visit, TIntermBranch *node)
{
mPreviousCase->getSequence()->push_back(node);
// TODO: Verify that accepting return or continue statements here doesn't cause problems.
mLastStatementWasBreak = true;
return false;
}
+
+} // anonymous namespace
+
+TIntermBlock *RemoveSwitchFallThrough(TIntermBlock *statementList,
+ PerformanceDiagnostics *perfDiagnostics)
+{
+ return RemoveSwitchFallThroughTraverser::removeFallThrough(statementList, perfDiagnostics);
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h b/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h
index db8699327c..7a3b1963f2 100644
--- a/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h
+++ b/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h
@@ -3,41 +3,25 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
+// RemoveSwitchFallThrough.h: Remove fall-through from switch statements.
+// Note that it is unsafe to do further AST transformations on the AST generated
+// by this function. It leaves duplicate nodes in the AST making replacements
+// unreliable.
#ifndef COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_
#define COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_
-#include "compiler/translator/IntermNode.h"
-
-class RemoveSwitchFallThrough : public TIntermTraverser
+namespace sh
{
- public:
- // When given a statementList from a switch AST node, return an updated
- // statementList that has fall-through removed.
- static TIntermAggregate *removeFallThrough(TIntermAggregate *statementList);
-
- private:
- RemoveSwitchFallThrough(TIntermAggregate *statementList);
- void visitSymbol(TIntermSymbol *node) override;
- void visitConstantUnion(TIntermConstantUnion *node) override;
- bool visitBinary(Visit, TIntermBinary *node) override;
- bool visitUnary(Visit, TIntermUnary *node) override;
- bool visitSelection(Visit visit, TIntermSelection *node) override;
- bool visitSwitch(Visit, TIntermSwitch *node) override;
- bool visitCase(Visit, TIntermCase *node) override;
- bool visitAggregate(Visit, TIntermAggregate *node) override;
- bool visitLoop(Visit, TIntermLoop *node) override;
- bool visitBranch(Visit, TIntermBranch *node) override;
+class TIntermBlock;
+class PerformanceDiagnostics;
- void outputSequence(TIntermSequence *sequence, size_t startIndex);
- void handlePreviousCase();
+// When given a statementList from a switch AST node, return an updated
+// statementList that has fall-through removed.
+TIntermBlock *RemoveSwitchFallThrough(TIntermBlock *statementList,
+ PerformanceDiagnostics *perfDiagnostics);
- TIntermAggregate *mStatementList;
- TIntermAggregate *mStatementListOut;
- bool mLastStatementWasBreak;
- TIntermAggregate *mPreviousCase;
- std::vector<TIntermAggregate *> mCasesSharingBreak;
-};
+} // namespace sh
-#endif // COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_
+#endif // COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.cpp
new file mode 100644
index 0000000000..74b5e73f71
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.cpp
@@ -0,0 +1,358 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// RemoveUnreferencedVariables.cpp:
+// Drop variables that are declared but never referenced in the AST. This avoids adding unnecessary
+// initialization code for them. Also removes unreferenced struct types.
+//
+
+#include "compiler/translator/RemoveUnreferencedVariables.h"
+
+#include "compiler/translator/IntermTraverse.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class CollectVariableRefCountsTraverser : public TIntermTraverser
+{
+ public:
+ CollectVariableRefCountsTraverser();
+
+ using RefCountMap = std::unordered_map<int, unsigned int>;
+ RefCountMap &getSymbolIdRefCounts() { return mSymbolIdRefCounts; }
+ RefCountMap &getStructIdRefCounts() { return mStructIdRefCounts; }
+
+ void visitSymbol(TIntermSymbol *node) override;
+ bool visitAggregate(Visit visit, TIntermAggregate *node) override;
+ bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override;
+
+ private:
+ void incrementStructTypeRefCount(const TType &type);
+
+ RefCountMap mSymbolIdRefCounts;
+
+ // Structure reference counts are counted from symbols, constructors, function calls, function
+ // return values and from interface block and structure fields. We need to track both function
+ // calls and function return values since there's a compiler option not to prune unused
+ // functions. The type of a constant union may also be a struct, but statements that are just a
+ // constant union are always pruned, and if the constant union is used somehow it will get
+ // counted by something else.
+ RefCountMap mStructIdRefCounts;
+};
+
+CollectVariableRefCountsTraverser::CollectVariableRefCountsTraverser()
+ : TIntermTraverser(true, false, false)
+{
+}
+
+void CollectVariableRefCountsTraverser::incrementStructTypeRefCount(const TType &type)
+{
+ if (type.isInterfaceBlock())
+ {
+ const auto *block = type.getInterfaceBlock();
+ ASSERT(block);
+
+ // We can end up incrementing ref counts of struct types referenced from an interface block
+ // multiple times for the same block. This doesn't matter, because interface blocks can't be
+ // pruned so we'll never do the reverse operation.
+ for (const auto &field : block->fields())
+ {
+ ASSERT(!field->type()->isInterfaceBlock());
+ incrementStructTypeRefCount(*field->type());
+ }
+ return;
+ }
+
+ const auto *structure = type.getStruct();
+ if (structure != nullptr)
+ {
+ auto structIter = mStructIdRefCounts.find(structure->uniqueId());
+ if (structIter == mStructIdRefCounts.end())
+ {
+ mStructIdRefCounts[structure->uniqueId()] = 1u;
+
+ for (const auto &field : structure->fields())
+ {
+ incrementStructTypeRefCount(*field->type());
+ }
+
+ return;
+ }
+ ++(structIter->second);
+ }
+}
+
+void CollectVariableRefCountsTraverser::visitSymbol(TIntermSymbol *node)
+{
+ incrementStructTypeRefCount(node->getType());
+
+ auto iter = mSymbolIdRefCounts.find(node->getId());
+ if (iter == mSymbolIdRefCounts.end())
+ {
+ mSymbolIdRefCounts[node->getId()] = 1u;
+ return;
+ }
+ ++(iter->second);
+}
+
+bool CollectVariableRefCountsTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+ // This tracks struct references in both function calls and constructors.
+ incrementStructTypeRefCount(node->getType());
+ return true;
+}
+
+bool CollectVariableRefCountsTraverser::visitFunctionPrototype(Visit visit,
+ TIntermFunctionPrototype *node)
+{
+ incrementStructTypeRefCount(node->getType());
+ return true;
+}
+
+// Traverser that removes all unreferenced variables on one traversal.
+class RemoveUnreferencedVariablesTraverser : public TIntermTraverser
+{
+ public:
+ RemoveUnreferencedVariablesTraverser(
+ CollectVariableRefCountsTraverser::RefCountMap *symbolIdRefCounts,
+ CollectVariableRefCountsTraverser::RefCountMap *structIdRefCounts,
+ TSymbolTable *symbolTable);
+
+ bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
+ void visitSymbol(TIntermSymbol *node) override;
+ bool visitAggregate(Visit visit, TIntermAggregate *node) override;
+
+ // Traverse loop and block nodes in reverse order. Note that this traverser does not track
+ // parent block positions, so insertStatementInParentBlock is unusable!
+ void traverseBlock(TIntermBlock *block) override;
+ void traverseLoop(TIntermLoop *loop) override;
+
+ private:
+ void removeVariableDeclaration(TIntermDeclaration *node, TIntermTyped *declarator);
+ void decrementStructTypeRefCount(const TType &type);
+
+ CollectVariableRefCountsTraverser::RefCountMap *mSymbolIdRefCounts;
+ CollectVariableRefCountsTraverser::RefCountMap *mStructIdRefCounts;
+ bool mRemoveReferences;
+};
+
+RemoveUnreferencedVariablesTraverser::RemoveUnreferencedVariablesTraverser(
+ CollectVariableRefCountsTraverser::RefCountMap *symbolIdRefCounts,
+ CollectVariableRefCountsTraverser::RefCountMap *structIdRefCounts,
+ TSymbolTable *symbolTable)
+ : TIntermTraverser(true, false, true, symbolTable),
+ mSymbolIdRefCounts(symbolIdRefCounts),
+ mStructIdRefCounts(structIdRefCounts),
+ mRemoveReferences(false)
+{
+}
+
+void RemoveUnreferencedVariablesTraverser::decrementStructTypeRefCount(const TType &type)
+{
+ auto *structure = type.getStruct();
+ if (structure != nullptr)
+ {
+ ASSERT(mStructIdRefCounts->find(structure->uniqueId()) != mStructIdRefCounts->end());
+ unsigned int structRefCount = --(*mStructIdRefCounts)[structure->uniqueId()];
+
+ if (structRefCount == 0)
+ {
+ for (const auto &field : structure->fields())
+ {
+ decrementStructTypeRefCount(*field->type());
+ }
+ }
+ }
+}
+
+void RemoveUnreferencedVariablesTraverser::removeVariableDeclaration(TIntermDeclaration *node,
+ TIntermTyped *declarator)
+{
+ if (declarator->getType().isStructSpecifier() && !declarator->getType().isNamelessStruct())
+ {
+ unsigned int structId = declarator->getType().getStruct()->uniqueId();
+ if ((*mStructIdRefCounts)[structId] > 1u)
+ {
+ // If this declaration declares a named struct type that is used elsewhere, we need to
+ // keep it. We can still change the declarator though so that it doesn't declare an
+ // unreferenced variable.
+
+ // Note that since we're not removing the entire declaration, the struct's reference
+ // count will end up being one less than the correct refcount. But since the struct
+ // declaration is kept, the incorrect refcount can't cause any other problems.
+
+ if (declarator->getAsSymbolNode() && declarator->getAsSymbolNode()->getSymbol().empty())
+ {
+ // Already an empty declaration - nothing to do.
+ return;
+ }
+ queueReplacementWithParent(node, declarator,
+ new TIntermSymbol(mSymbolTable->getEmptySymbolId(),
+ TString(""), declarator->getType()),
+ OriginalNode::IS_DROPPED);
+ return;
+ }
+ }
+
+ if (getParentNode()->getAsBlock())
+ {
+ TIntermSequence emptyReplacement;
+ mMultiReplacements.push_back(
+ NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(), node, emptyReplacement));
+ }
+ else
+ {
+ ASSERT(getParentNode()->getAsLoopNode());
+ queueReplacement(nullptr, OriginalNode::IS_DROPPED);
+ }
+}
+
+bool RemoveUnreferencedVariablesTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node)
+{
+ if (visit == PreVisit)
+ {
+ // SeparateDeclarations should have already been run.
+ ASSERT(node->getSequence()->size() == 1u);
+
+ TIntermTyped *declarator = node->getSequence()->back()->getAsTyped();
+ ASSERT(declarator);
+
+ // We can only remove variables that are not a part of the shader interface.
+ TQualifier qualifier = declarator->getQualifier();
+ if (qualifier != EvqTemporary && qualifier != EvqGlobal)
+ {
+ return true;
+ }
+
+ bool canRemoveVariable = false;
+ TIntermSymbol *symbolNode = declarator->getAsSymbolNode();
+ if (symbolNode != nullptr)
+ {
+ canRemoveVariable =
+ (*mSymbolIdRefCounts)[symbolNode->getId()] == 1u || symbolNode->getSymbol().empty();
+ }
+ TIntermBinary *initNode = declarator->getAsBinaryNode();
+ if (initNode != nullptr)
+ {
+ ASSERT(initNode->getLeft()->getAsSymbolNode());
+ int symbolId = initNode->getLeft()->getAsSymbolNode()->getId();
+ canRemoveVariable =
+ (*mSymbolIdRefCounts)[symbolId] == 1u && !initNode->getRight()->hasSideEffects();
+ }
+
+ if (canRemoveVariable)
+ {
+ removeVariableDeclaration(node, declarator);
+ mRemoveReferences = true;
+ }
+ return true;
+ }
+ ASSERT(visit == PostVisit);
+ mRemoveReferences = false;
+ return true;
+}
+
+void RemoveUnreferencedVariablesTraverser::visitSymbol(TIntermSymbol *node)
+{
+ if (mRemoveReferences)
+ {
+ ASSERT(mSymbolIdRefCounts->find(node->getId()) != mSymbolIdRefCounts->end());
+ --(*mSymbolIdRefCounts)[node->getId()];
+
+ decrementStructTypeRefCount(node->getType());
+ }
+}
+
+bool RemoveUnreferencedVariablesTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+ if (mRemoveReferences)
+ {
+ decrementStructTypeRefCount(node->getType());
+ }
+ return true;
+}
+
+void RemoveUnreferencedVariablesTraverser::traverseBlock(TIntermBlock *node)
+{
+ // We traverse blocks in reverse order. This way reference counts can be decremented when
+ // removing initializers, and variables that become unused when initializers are removed can be
+ // removed on the same traversal.
+
+ ScopedNodeInTraversalPath addToPath(this, node);
+
+ bool visit = true;
+
+ TIntermSequence *sequence = node->getSequence();
+
+ if (preVisit)
+ visit = visitBlock(PreVisit, node);
+
+ if (visit)
+ {
+ for (auto iter = sequence->rbegin(); iter != sequence->rend(); ++iter)
+ {
+ (*iter)->traverse(this);
+ if (visit && inVisit)
+ {
+ if ((iter + 1) != sequence->rend())
+ visit = visitBlock(InVisit, node);
+ }
+ }
+ }
+
+ if (visit && postVisit)
+ visitBlock(PostVisit, node);
+}
+
+void RemoveUnreferencedVariablesTraverser::traverseLoop(TIntermLoop *node)
+{
+ // We traverse loops in reverse order as well. The loop body gets traversed before the init
+ // node.
+
+ ScopedNodeInTraversalPath addToPath(this, node);
+
+ bool visit = true;
+
+ if (preVisit)
+ visit = visitLoop(PreVisit, node);
+
+ if (visit)
+ {
+ // We don't need to traverse loop expressions or conditions since they can't be declarations
+ // in the AST (loops which have a declaration in their condition get transformed in the
+ // parsing stage).
+ ASSERT(node->getExpression() == nullptr ||
+ node->getExpression()->getAsDeclarationNode() == nullptr);
+ ASSERT(node->getCondition() == nullptr ||
+ node->getCondition()->getAsDeclarationNode() == nullptr);
+
+ if (node->getBody())
+ node->getBody()->traverse(this);
+
+ if (node->getInit())
+ node->getInit()->traverse(this);
+ }
+
+ if (visit && postVisit)
+ visitLoop(PostVisit, node);
+}
+
+} // namespace
+
+void RemoveUnreferencedVariables(TIntermBlock *root, TSymbolTable *symbolTable)
+{
+ CollectVariableRefCountsTraverser collector;
+ root->traverse(&collector);
+ RemoveUnreferencedVariablesTraverser traverser(&collector.getSymbolIdRefCounts(),
+ &collector.getStructIdRefCounts(), symbolTable);
+ root->traverse(&traverser);
+ traverser.updateTree();
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.h b/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.h
new file mode 100644
index 0000000000..39c8327776
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/RemoveUnreferencedVariables.h
@@ -0,0 +1,24 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// RemoveUnreferencedVariables.h:
+// Drop variables that are declared but never referenced in the AST. This avoids adding unnecessary
+// initialization code for them. Also removes unreferenced struct types.
+//
+
+#ifndef COMPILER_TRANSLATOR_REMOVEUNREFERENCEDVARIABLES_H_
+#define COMPILER_TRANSLATOR_REMOVEUNREFERENCEDVARIABLES_H_
+
+namespace sh
+{
+
+class TIntermBlock;
+class TSymbolTable;
+
+void RemoveUnreferencedVariables(TIntermBlock *root, TSymbolTable *symbolTable);
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_REMOVEUNREFERENCEDVARIABLES_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RenameFunction.h b/src/3rdparty/angle/src/compiler/translator/RenameFunction.h
deleted file mode 100644
index fd6a365fea..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RenameFunction.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_TRANSLATOR_RENAMEFUNCTION_H_
-#define COMPILER_TRANSLATOR_RENAMEFUNCTION_H_
-
-#include "compiler/translator/IntermNode.h"
-
-//
-// Renames a function, including its declaration and any calls to it.
-//
-class RenameFunction : public TIntermTraverser
-{
-public:
- RenameFunction(const TString& oldFunctionName, const TString& newFunctionName)
- : TIntermTraverser(true, false, false)
- , mOldFunctionName(oldFunctionName)
- , mNewFunctionName(newFunctionName) {}
-
- bool visitAggregate(Visit visit, TIntermAggregate *node) override
- {
- TOperator op = node->getOp();
- if ((op == EOpFunction || op == EOpFunctionCall) && node->getName() == mOldFunctionName)
- node->setName(mNewFunctionName);
- return true;
- }
-
-private:
- const TString mOldFunctionName;
- const TString mNewFunctionName;
-};
-
-#endif // COMPILER_TRANSLATOR_RENAMEFUNCTION_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.cpp b/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.cpp
index 8347447546..dc3fb7a74e 100644
--- a/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.cpp
@@ -9,7 +9,10 @@
#include "compiler/translator/RewriteDoWhile.h"
-#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
namespace
{
@@ -41,17 +44,15 @@ namespace
class DoWhileRewriter : public TIntermTraverser
{
public:
- DoWhileRewriter() : TIntermTraverser(true, false, false) {}
+ DoWhileRewriter(TSymbolTable *symbolTable) : TIntermTraverser(true, false, false, symbolTable)
+ {
+ }
- bool visitAggregate(Visit, TIntermAggregate *node) override
+ bool visitBlock(Visit, TIntermBlock *node) override
{
- // A well-formed AST can only have do-while in EOpSequence which represent lists of
- // statements. By doing a prefix traversal we are able to replace the do-while in the
- // sequence directly as the content of the do-while will be traversed later.
- if (node->getOp() != EOpSequence)
- {
- return true;
- }
+ // A well-formed AST can only have do-while inside TIntermBlock. By doing a prefix traversal
+ // we are able to replace the do-while in the sequence directly as the content of the
+ // do-while will be traversed later.
TIntermSequence *statements = node->getSequence();
@@ -68,10 +69,13 @@ class DoWhileRewriter : public TIntermTraverser
continue;
}
+ // Found a loop to change.
+ nextTemporaryId();
+
TType boolType = TType(EbtBool);
// bool temp = false;
- TIntermAggregate *tempDeclaration = nullptr;
+ TIntermDeclaration *tempDeclaration = nullptr;
{
TConstantUnion *falseConstant = new TConstantUnion();
falseConstant->setBConst(false);
@@ -95,23 +99,22 @@ class DoWhileRewriter : public TIntermTraverser
// break;
// }
// }
- TIntermSelection *breakIf = nullptr;
+ TIntermIfElse *breakIf = nullptr;
{
TIntermBranch *breakStatement = new TIntermBranch(EOpBreak, nullptr);
- TIntermAggregate *breakBlock = new TIntermAggregate(EOpSequence);
+ TIntermBlock *breakBlock = new TIntermBlock();
breakBlock->getSequence()->push_back(breakStatement);
- TIntermUnary *negatedCondition = new TIntermUnary(EOpLogicalNot);
- negatedCondition->setOperand(loop->getCondition());
+ TIntermUnary *negatedCondition =
+ new TIntermUnary(EOpLogicalNot, loop->getCondition());
- TIntermSelection *innerIf =
- new TIntermSelection(negatedCondition, breakBlock, nullptr);
+ TIntermIfElse *innerIf = new TIntermIfElse(negatedCondition, breakBlock, nullptr);
- TIntermAggregate *innerIfBlock = new TIntermAggregate(EOpSequence);
+ TIntermBlock *innerIfBlock = new TIntermBlock();
innerIfBlock->getSequence()->push_back(innerIf);
- breakIf = new TIntermSelection(createTempSymbol(boolType), innerIfBlock, nullptr);
+ breakIf = new TIntermIfElse(createTempSymbol(boolType), innerIfBlock, nullptr);
}
// Assemble the replacement loops, reusing the do-while loop's body and inserting our
@@ -122,14 +125,10 @@ class DoWhileRewriter : public TIntermTraverser
trueConstant->setBConst(true);
TIntermTyped *trueValue = new TIntermConstantUnion(trueConstant, boolType);
- TIntermAggregate *body = nullptr;
- if (loop->getBody() != nullptr)
- {
- body = loop->getBody()->getAsAggregate();
- }
- else
+ TIntermBlock *body = loop->getBody();
+ if (body == nullptr)
{
- body = new TIntermAggregate(EOpSequence);
+ body = new TIntermBlock();
}
auto sequence = body->getSequence();
sequence->insert(sequence->begin(), assignTrue);
@@ -143,8 +142,6 @@ class DoWhileRewriter : public TIntermTraverser
replacement.push_back(newLoop);
node->replaceChildNodeWithMultiple(loop, replacement);
-
- nextTemporaryIndex();
}
return true;
}
@@ -152,12 +149,11 @@ class DoWhileRewriter : public TIntermTraverser
} // anonymous namespace
-void RewriteDoWhile(TIntermNode *root, unsigned int *temporaryIndex)
+void RewriteDoWhile(TIntermNode *root, TSymbolTable *symbolTable)
{
- ASSERT(temporaryIndex != 0);
-
- DoWhileRewriter rewriter;
- rewriter.useTemporaryIndex(temporaryIndex);
+ DoWhileRewriter rewriter(symbolTable);
root->traverse(&rewriter);
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.h b/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.h
index f6ec1caf06..e83bfc4b56 100644
--- a/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.h
+++ b/src/3rdparty/angle/src/compiler/translator/RewriteDoWhile.h
@@ -10,7 +10,14 @@
#ifndef COMPILER_TRANSLATOR_REWRITEDOWHILE_H_
#define COMPILER_TRANSLATOR_REWRITEDOWHILE_H_
+namespace sh
+{
+
class TIntermNode;
-void RewriteDoWhile(TIntermNode *root, unsigned int *temporaryIndex);
+class TSymbolTable;
+
+void RewriteDoWhile(TIntermNode *root, TSymbolTable *symbolTable);
+
+} // namespace sh
#endif // COMPILER_TRANSLATOR_REWRITEDOWHILE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp
index 52ede17434..ed1bfad8a8 100644
--- a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp
@@ -8,6 +8,9 @@
//
#include "compiler/translator/RewriteElseBlocks.h"
+
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermNode_util.h"
#include "compiler/translator/NodeSearch.h"
#include "compiler/translator/SymbolTable.h"
@@ -20,121 +23,98 @@ namespace
class ElseBlockRewriter : public TIntermTraverser
{
public:
- ElseBlockRewriter();
+ ElseBlockRewriter(TSymbolTable *symbolTable);
protected:
- bool visitAggregate(Visit visit, TIntermAggregate *aggregate) override;
+ bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *aggregate) override;
+ bool visitBlock(Visit visit, TIntermBlock *block) override;
private:
- const TType *mFunctionType;
+ TIntermNode *rewriteIfElse(TIntermIfElse *ifElse);
- TIntermNode *rewriteSelection(TIntermSelection *selection);
+ const TType *mFunctionType;
};
-TIntermUnary *MakeNewUnary(TOperator op, TIntermTyped *operand)
+ElseBlockRewriter::ElseBlockRewriter(TSymbolTable *symbolTable)
+ : TIntermTraverser(true, false, true, symbolTable), mFunctionType(nullptr)
{
- TIntermUnary *unary = new TIntermUnary(op, operand->getType());
- unary->setOperand(operand);
- return unary;
}
-ElseBlockRewriter::ElseBlockRewriter()
- : TIntermTraverser(true, false, true),
- mFunctionType(NULL)
-{}
+bool ElseBlockRewriter::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
+{
+ // Store the current function context (see comment below)
+ mFunctionType = ((visit == PreVisit) ? &node->getFunctionPrototype()->getType() : nullptr);
+ return true;
+}
-bool ElseBlockRewriter::visitAggregate(Visit visit, TIntermAggregate *node)
+bool ElseBlockRewriter::visitBlock(Visit visit, TIntermBlock *node)
{
- switch (node->getOp())
+ if (visit == PostVisit)
{
- case EOpSequence:
- if (visit == PostVisit)
+ for (size_t statementIndex = 0; statementIndex != node->getSequence()->size();
+ statementIndex++)
{
- for (size_t statementIndex = 0; statementIndex != node->getSequence()->size(); statementIndex++)
+ TIntermNode *statement = (*node->getSequence())[statementIndex];
+ TIntermIfElse *ifElse = statement->getAsIfElseNode();
+ if (ifElse && ifElse->getFalseBlock() != nullptr)
{
- TIntermNode *statement = (*node->getSequence())[statementIndex];
- TIntermSelection *selection = statement->getAsSelectionNode();
- if (selection && selection->getFalseBlock() != nullptr)
- {
- // Check for if / else if
- TIntermSelection *elseIfBranch = selection->getFalseBlock()->getAsSelectionNode();
- if (elseIfBranch)
- {
- selection->replaceChildNode(elseIfBranch, rewriteSelection(elseIfBranch));
- delete elseIfBranch;
- }
-
- (*node->getSequence())[statementIndex] = rewriteSelection(selection);
- delete selection;
- }
+ (*node->getSequence())[statementIndex] = rewriteIfElse(ifElse);
}
}
- break;
-
- case EOpFunction:
- // Store the current function context (see comment below)
- mFunctionType = ((visit == PreVisit) ? &node->getType() : NULL);
- break;
-
- default: break;
}
-
return true;
}
-TIntermNode *ElseBlockRewriter::rewriteSelection(TIntermSelection *selection)
+TIntermNode *ElseBlockRewriter::rewriteIfElse(TIntermIfElse *ifElse)
{
- ASSERT(selection != nullptr);
+ ASSERT(ifElse != nullptr);
- nextTemporaryIndex();
+ nextTemporaryId();
- TIntermTyped *typedCondition = selection->getCondition()->getAsTyped();
- TIntermAggregate *storeCondition = createTempInitDeclaration(typedCondition);
+ TIntermDeclaration *storeCondition = createTempInitDeclaration(ifElse->getCondition());
- TIntermSelection *falseBlock = nullptr;
+ TIntermBlock *falseBlock = nullptr;
TType boolType(EbtBool, EbpUndefined, EvqTemporary);
- if (selection->getFalseBlock())
+ if (ifElse->getFalseBlock())
{
- TIntermAggregate *negatedElse = nullptr;
+ TIntermBlock *negatedElse = nullptr;
// crbug.com/346463
// D3D generates error messages claiming a function has no return value, when rewriting
// an if-else clause that returns something non-void in a function. By appending dummy
// returns (that are unreachable) we can silence this compile error.
if (mFunctionType && mFunctionType->getBasicType() != EbtVoid)
{
- TString typeString = mFunctionType->getStruct() ? mFunctionType->getStruct()->name() :
- mFunctionType->getBasicString();
- TString rawText = "return (" + typeString + ")0";
- TIntermRaw *returnNode = new TIntermRaw(*mFunctionType, rawText);
- negatedElse = new TIntermAggregate(EOpSequence);
- negatedElse->getSequence()->push_back(returnNode);
+ TIntermNode *returnNode = new TIntermBranch(EOpReturn, CreateZeroNode(*mFunctionType));
+ negatedElse = new TIntermBlock();
+ negatedElse->appendStatement(returnNode);
}
TIntermSymbol *conditionSymbolElse = createTempSymbol(boolType);
- TIntermUnary *negatedCondition = MakeNewUnary(EOpLogicalNot, conditionSymbolElse);
- falseBlock = new TIntermSelection(negatedCondition,
- selection->getFalseBlock(), negatedElse);
+ TIntermUnary *negatedCondition = new TIntermUnary(EOpLogicalNot, conditionSymbolElse);
+ TIntermIfElse *falseIfElse =
+ new TIntermIfElse(negatedCondition, ifElse->getFalseBlock(), negatedElse);
+ falseBlock = EnsureBlock(falseIfElse);
}
TIntermSymbol *conditionSymbolSel = createTempSymbol(boolType);
- TIntermSelection *newSelection = new TIntermSelection(conditionSymbolSel, selection->getTrueBlock(), falseBlock);
+ TIntermIfElse *newIfElse =
+ new TIntermIfElse(conditionSymbolSel, ifElse->getTrueBlock(), falseBlock);
- TIntermAggregate *block = new TIntermAggregate(EOpSequence);
+ TIntermBlock *block = new TIntermBlock();
block->getSequence()->push_back(storeCondition);
- block->getSequence()->push_back(newSelection);
+ block->getSequence()->push_back(newIfElse);
return block;
}
-}
+} // anonymous namespace
-void RewriteElseBlocks(TIntermNode *node, unsigned int *temporaryIndex)
+void RewriteElseBlocks(TIntermNode *node, TSymbolTable *symbolTable)
{
- ElseBlockRewriter rewriter;
- rewriter.useTemporaryIndex(temporaryIndex);
+ ElseBlockRewriter rewriter(symbolTable);
node->traverse(&rewriter);
}
-}
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h
index 24a425e66d..2586b5405c 100644
--- a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h
+++ b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h
@@ -10,13 +10,13 @@
#ifndef COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_
#define COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_
-#include "compiler/translator/IntermNode.h"
-
namespace sh
{
-void RewriteElseBlocks(TIntermNode *node, unsigned int *temporaryIndex);
+class TIntermNode;
+class TSymbolTable;
+void RewriteElseBlocks(TIntermNode *node, TSymbolTable *symbolTable);
}
-#endif // COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_
+#endif // COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.cpp b/src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.cpp
new file mode 100644
index 0000000000..b602e0c923
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.cpp
@@ -0,0 +1,154 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Implementation of texelFetchOffset translation issue workaround.
+// See header for more info.
+
+#include "compiler/translator/RewriteTexelFetchOffset.h"
+
+#include "common/angleutils.h"
+#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/IntermTraverse.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class Traverser : public TIntermTraverser
+{
+ public:
+ static void Apply(TIntermNode *root, const TSymbolTable &symbolTable, int shaderVersion);
+
+ private:
+ Traverser(const TSymbolTable &symbolTable, int shaderVersion);
+ bool visitAggregate(Visit visit, TIntermAggregate *node) override;
+ void nextIteration();
+
+ const TSymbolTable *symbolTable;
+ const int shaderVersion;
+ bool mFound = false;
+};
+
+Traverser::Traverser(const TSymbolTable &symbolTable, int shaderVersion)
+ : TIntermTraverser(true, false, false), symbolTable(&symbolTable), shaderVersion(shaderVersion)
+{
+}
+
+// static
+void Traverser::Apply(TIntermNode *root, const TSymbolTable &symbolTable, int shaderVersion)
+{
+ Traverser traverser(symbolTable, shaderVersion);
+ do
+ {
+ traverser.nextIteration();
+ root->traverse(&traverser);
+ if (traverser.mFound)
+ {
+ traverser.updateTree();
+ }
+ } while (traverser.mFound);
+}
+
+void Traverser::nextIteration()
+{
+ mFound = false;
+}
+
+bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+ if (mFound)
+ {
+ return false;
+ }
+
+ // Decide if the node represents the call of texelFetchOffset.
+ if (node->getOp() != EOpCallBuiltInFunction)
+ {
+ return true;
+ }
+
+ if (node->getFunctionSymbolInfo()->getName() != "texelFetchOffset")
+ {
+ return true;
+ }
+
+ // Potential problem case detected, apply workaround.
+ const TIntermSequence *sequence = node->getSequence();
+ ASSERT(sequence->size() == 4u);
+
+ // Decide if the sampler is a 2DArray sampler. In that case position is ivec3 and offset is
+ // ivec2.
+ bool is2DArray = sequence->at(1)->getAsTyped()->getNominalSize() == 3 &&
+ sequence->at(3)->getAsTyped()->getNominalSize() == 2;
+
+ // Create new node that represents the call of function texelFetch.
+ // Its argument list will be: texelFetch(sampler, Position+offset, lod).
+
+ TIntermSequence *texelFetchArguments = new TIntermSequence();
+
+ // sampler
+ texelFetchArguments->push_back(sequence->at(0));
+
+ // Position
+ TIntermTyped *texCoordNode = sequence->at(1)->getAsTyped();
+ ASSERT(texCoordNode);
+
+ // offset
+ TIntermTyped *offsetNode = nullptr;
+ ASSERT(sequence->at(3)->getAsTyped());
+ if (is2DArray)
+ {
+ // For 2DArray samplers, Position is ivec3 and offset is ivec2;
+ // So offset must be converted into an ivec3 before being added to Position.
+ TIntermSequence *constructOffsetIvecArguments = new TIntermSequence();
+ constructOffsetIvecArguments->push_back(sequence->at(3)->getAsTyped());
+
+ TIntermTyped *zeroNode = CreateZeroNode(TType(EbtInt));
+ constructOffsetIvecArguments->push_back(zeroNode);
+
+ offsetNode = TIntermAggregate::CreateConstructor(texCoordNode->getType(),
+ constructOffsetIvecArguments);
+ offsetNode->setLine(texCoordNode->getLine());
+ }
+ else
+ {
+ offsetNode = sequence->at(3)->getAsTyped();
+ }
+
+ // Position+offset
+ TIntermBinary *add = new TIntermBinary(EOpAdd, texCoordNode, offsetNode);
+ add->setLine(texCoordNode->getLine());
+ texelFetchArguments->push_back(add);
+
+ // lod
+ texelFetchArguments->push_back(sequence->at(2));
+
+ ASSERT(texelFetchArguments->size() == 3u);
+
+ TIntermTyped *texelFetchNode = CreateBuiltInFunctionCallNode("texelFetch", texelFetchArguments,
+ *symbolTable, shaderVersion);
+ texelFetchNode->setLine(node->getLine());
+
+ // Replace the old node by this new node.
+ queueReplacement(texelFetchNode, OriginalNode::IS_DROPPED);
+ mFound = true;
+ return false;
+}
+
+} // anonymous namespace
+
+void RewriteTexelFetchOffset(TIntermNode *root, const TSymbolTable &symbolTable, int shaderVersion)
+{
+ // texelFetchOffset is only valid in GLSL 3.0 and later.
+ if (shaderVersion < 300)
+ return;
+
+ Traverser::Apply(root, symbolTable, shaderVersion);
+}
+
+} // namespace sh \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.h b/src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.h
new file mode 100644
index 0000000000..694d709f8e
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/RewriteTexelFetchOffset.h
@@ -0,0 +1,28 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This mutating tree traversal works around an issue on the translation
+// from texelFetchOffset into HLSL function Load on INTEL drivers. It
+// works by translating texelFetchOffset into texelFetch:
+//
+// - From: texelFetchOffset(sampler, Position, lod, offset)
+// - To: texelFetch(sampler, Position+offset, lod)
+//
+// See http://anglebug.com/1469
+
+#ifndef COMPILER_TRANSLATOR_REWRITE_TEXELFETCHOFFSET_H_
+#define COMPILER_TRANSLATOR_REWRITE_TEXELFETCHOFFSET_H_
+
+class TIntermNode;
+class TSymbolTable;
+
+namespace sh
+{
+
+void RewriteTexelFetchOffset(TIntermNode *root, const TSymbolTable &symbolTable, int shaderVersion);
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_REWRITE_TEXELFETCHOFFSET_H_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.cpp b/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.cpp
new file mode 100644
index 0000000000..696a49536c
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.cpp
@@ -0,0 +1,94 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/RewriteUnaryMinusOperatorFloat.h"
+
+#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class Traverser : public TIntermTraverser
+{
+ public:
+ static void Apply(TIntermNode *root);
+
+ private:
+ Traverser();
+ bool visitUnary(Visit visit, TIntermUnary *node) override;
+ void nextIteration();
+
+ bool mFound = false;
+};
+
+// static
+void Traverser::Apply(TIntermNode *root)
+{
+ Traverser traverser;
+ do
+ {
+ traverser.nextIteration();
+ root->traverse(&traverser);
+ if (traverser.mFound)
+ {
+ traverser.updateTree();
+ }
+ } while (traverser.mFound);
+}
+
+Traverser::Traverser() : TIntermTraverser(true, false, false)
+{
+}
+
+void Traverser::nextIteration()
+{
+ mFound = false;
+}
+
+bool Traverser::visitUnary(Visit visit, TIntermUnary *node)
+{
+ if (mFound)
+ {
+ return false;
+ }
+
+ // Detect if the current operator is unary minus operator.
+ if (node->getOp() != EOpNegative)
+ {
+ return true;
+ }
+
+ // Detect if the current operand is a float variable.
+ TIntermTyped *fValue = node->getOperand();
+ if (!fValue->getType().isScalarFloat())
+ {
+ return true;
+ }
+
+ // 0.0 - float
+ TIntermTyped *zero = CreateZeroNode(fValue->getType());
+ zero->setLine(fValue->getLine());
+ TIntermBinary *sub = new TIntermBinary(EOpSub, zero, fValue);
+ sub->setLine(fValue->getLine());
+
+ queueReplacement(sub, OriginalNode::IS_DROPPED);
+
+ mFound = true;
+ return false;
+}
+
+} // anonymous namespace
+
+void RewriteUnaryMinusOperatorFloat(TIntermNode *root)
+{
+ Traverser::Apply(root);
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.h b/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.h
new file mode 100644
index 0000000000..ccbfbcbd9e
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorFloat.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Rewrite "-float" to "0.0 - float" to work around unary minus operator on float issue on Intel Mac
+// OSX 10.11.
+
+#ifndef COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORFLOAT_H_
+#define COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORFLOAT_H_
+
+class TIntermNode;
+namespace sh
+{
+
+void RewriteUnaryMinusOperatorFloat(TIntermNode *root);
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORFLOAT_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp b/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp
new file mode 100644
index 0000000000..fe2ef948b4
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp
@@ -0,0 +1,112 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Implementation of evaluating unary integer variable bug workaround.
+// See header for more info.
+
+#include "compiler/translator/RewriteUnaryMinusOperatorInt.h"
+
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class Traverser : public TIntermTraverser
+{
+ public:
+ static void Apply(TIntermNode *root);
+
+ private:
+ Traverser();
+ bool visitUnary(Visit visit, TIntermUnary *node) override;
+ void nextIteration();
+
+ bool mFound = false;
+};
+
+// static
+void Traverser::Apply(TIntermNode *root)
+{
+ Traverser traverser;
+ do
+ {
+ traverser.nextIteration();
+ root->traverse(&traverser);
+ if (traverser.mFound)
+ {
+ traverser.updateTree();
+ }
+ } while (traverser.mFound);
+}
+
+Traverser::Traverser() : TIntermTraverser(true, false, false)
+{
+}
+
+void Traverser::nextIteration()
+{
+ mFound = false;
+}
+
+bool Traverser::visitUnary(Visit visit, TIntermUnary *node)
+{
+ if (mFound)
+ {
+ return false;
+ }
+
+ // Decide if the current unary operator is unary minus.
+ if (node->getOp() != EOpNegative)
+ {
+ return true;
+ }
+
+ // Decide if the current operand is an integer variable.
+ TIntermTyped *opr = node->getOperand();
+ if (!opr->getType().isScalarInt())
+ {
+ return true;
+ }
+
+ // Potential problem case detected, apply workaround: -(int) -> ~(int) + 1.
+ // ~(int)
+ TIntermUnary *bitwiseNot = new TIntermUnary(EOpBitwiseNot, opr);
+ bitwiseNot->setLine(opr->getLine());
+
+ // Constant 1 (or 1u)
+ TConstantUnion *one = new TConstantUnion();
+ if (opr->getType().getBasicType() == EbtInt)
+ {
+ one->setIConst(1);
+ }
+ else
+ {
+ one->setUConst(1u);
+ }
+ TIntermConstantUnion *oneNode = new TIntermConstantUnion(one, opr->getType());
+ oneNode->getTypePointer()->setQualifier(EvqConst);
+ oneNode->setLine(opr->getLine());
+
+ // ~(int) + 1
+ TIntermBinary *add = new TIntermBinary(EOpAdd, bitwiseNot, oneNode);
+ add->setLine(opr->getLine());
+
+ queueReplacement(add, OriginalNode::IS_DROPPED);
+
+ mFound = true;
+ return false;
+}
+
+} // anonymous namespace
+
+void RewriteUnaryMinusOperatorInt(TIntermNode *root)
+{
+ Traverser::Apply(root);
+}
+
+} // namespace sh \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.h b/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.h
new file mode 100644
index 0000000000..50f0c442a7
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/RewriteUnaryMinusOperatorInt.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This mutating tree traversal works around a bug on evaluating unary
+// integer variable on Intel D3D driver. It works by rewriting -(int) to
+// ~(int) + 1 when evaluating unary integer variables.
+
+#ifndef COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORINT_H_
+#define COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORINT_H_
+
+class TIntermNode;
+namespace sh
+{
+
+void RewriteUnaryMinusOperatorInt(TIntermNode *root);
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_REWRITEUNARYMINUSOPERATORINT_H_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.cpp b/src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.cpp
new file mode 100644
index 0000000000..3c4209c539
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.cpp
@@ -0,0 +1,112 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// RunAtTheEndOfShader.cpp: Add code to be run at the end of the shader. In case main() contains a
+// return statement, this is done by replacing the main() function with another function that calls
+// the old main, like this:
+//
+// void main() { body }
+// =>
+// void main0() { body }
+// void main()
+// {
+// main0();
+// codeToRun
+// }
+//
+// This way the code will get run even if the return statement inside main is executed.
+//
+
+#include "compiler/translator/RunAtTheEndOfShader.h"
+
+#include "compiler/translator/FindMain.h"
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/IntermTraverse.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class ContainsReturnTraverser : public TIntermTraverser
+{
+ public:
+ ContainsReturnTraverser() : TIntermTraverser(true, false, false), mContainsReturn(false) {}
+
+ bool visitBranch(Visit visit, TIntermBranch *node) override
+ {
+ if (node->getFlowOp() == EOpReturn)
+ {
+ mContainsReturn = true;
+ }
+ return false;
+ }
+
+ bool containsReturn() { return mContainsReturn; }
+
+ private:
+ bool mContainsReturn;
+};
+
+bool ContainsReturn(TIntermNode *node)
+{
+ ContainsReturnTraverser traverser;
+ node->traverse(&traverser);
+ return traverser.containsReturn();
+}
+
+void WrapMainAndAppend(TIntermBlock *root,
+ TIntermFunctionDefinition *main,
+ TIntermNode *codeToRun,
+ TSymbolTable *symbolTable)
+{
+ // Replace main() with main0() with the same body.
+ TSymbolUniqueId oldMainId(symbolTable);
+ std::stringstream oldMainName;
+ oldMainName << "main" << oldMainId.get();
+ TIntermFunctionDefinition *oldMain = CreateInternalFunctionDefinitionNode(
+ TType(EbtVoid), oldMainName.str().c_str(), main->getBody(), oldMainId);
+
+ bool replaced = root->replaceChildNode(main, oldMain);
+ ASSERT(replaced);
+
+ // void main()
+ TIntermFunctionPrototype *newMainProto = new TIntermFunctionPrototype(
+ TType(EbtVoid), main->getFunctionPrototype()->getFunctionSymbolInfo()->getId());
+ newMainProto->getFunctionSymbolInfo()->setName("main");
+
+ // {
+ // main0();
+ // codeToRun
+ // }
+ TIntermBlock *newMainBody = new TIntermBlock();
+ TIntermAggregate *oldMainCall = CreateInternalFunctionCallNode(
+ TType(EbtVoid), oldMainName.str().c_str(), oldMainId, new TIntermSequence());
+ newMainBody->appendStatement(oldMainCall);
+ newMainBody->appendStatement(codeToRun);
+
+ // Add the new main() to the root node.
+ TIntermFunctionDefinition *newMain = new TIntermFunctionDefinition(newMainProto, newMainBody);
+ root->appendStatement(newMain);
+}
+
+} // anonymous namespace
+
+void RunAtTheEndOfShader(TIntermBlock *root, TIntermNode *codeToRun, TSymbolTable *symbolTable)
+{
+ TIntermFunctionDefinition *main = FindMain(root);
+ if (!ContainsReturn(main))
+ {
+ main->getBody()->appendStatement(codeToRun);
+ return;
+ }
+
+ WrapMainAndAppend(root, main, codeToRun, symbolTable);
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.h b/src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.h
new file mode 100644
index 0000000000..ed94c28dae
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/RunAtTheEndOfShader.h
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// RunAtTheEndOfShader.h: Add code to be run at the end of the shader.
+//
+
+#ifndef COMPILER_TRANSLATOR_RUNATTHEENDOFSHADER_H_
+#define COMPILER_TRANSLATOR_RUNATTHEENDOFSHADER_H_
+
+namespace sh
+{
+
+class TIntermBlock;
+class TIntermNode;
+class TSymbolTable;
+
+void RunAtTheEndOfShader(TIntermBlock *root, TIntermNode *codeToRun, TSymbolTable *symbolTable);
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_RUNATTHEENDOFSHADER_H_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp
index 775c5d8710..746c16e2e6 100644
--- a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp
@@ -3,6 +3,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
+// Scalarize vector and matrix constructor args, so that vectors built from components don't have
+// matrix arguments, and matrices built from components don't have vector arguments. This avoids
+// driver bugs around vector and matrix constructors.
+//
#include "common/debug.h"
#include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h"
@@ -11,6 +15,11 @@
#include "angle_gl.h"
#include "common/angleutils.h"
+#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
namespace
{
@@ -37,140 +46,93 @@ bool ContainsVectorNode(const TIntermSequence &sequence)
return false;
}
-TIntermConstantUnion *ConstructIndexNode(int index)
+TIntermBinary *ConstructVectorIndexBinaryNode(TIntermSymbol *symbolNode, int index)
{
- TConstantUnion *u = new TConstantUnion[1];
- u[0].setIConst(index);
-
- TType type(EbtInt, EbpUndefined, EvqConst, 1);
- TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
- return node;
+ return new TIntermBinary(EOpIndexDirect, symbolNode, CreateIndexNode(index));
}
-TIntermBinary *ConstructVectorIndexBinaryNode(TIntermSymbol *symbolNode, int index)
+TIntermBinary *ConstructMatrixIndexBinaryNode(TIntermSymbol *symbolNode, int colIndex, int rowIndex)
{
- TIntermBinary *binary = new TIntermBinary(EOpIndexDirect);
- binary->setLeft(symbolNode);
- TIntermConstantUnion *indexNode = ConstructIndexNode(index);
- binary->setRight(indexNode);
- return binary;
+ TIntermBinary *colVectorNode = ConstructVectorIndexBinaryNode(symbolNode, colIndex);
+
+ return new TIntermBinary(EOpIndexDirect, colVectorNode, CreateIndexNode(rowIndex));
}
-TIntermBinary *ConstructMatrixIndexBinaryNode(
- TIntermSymbol *symbolNode, int colIndex, int rowIndex)
+class ScalarizeArgsTraverser : public TIntermTraverser
{
- TIntermBinary *colVectorNode =
- ConstructVectorIndexBinaryNode(symbolNode, colIndex);
+ public:
+ ScalarizeArgsTraverser(sh::GLenum shaderType,
+ bool fragmentPrecisionHigh,
+ TSymbolTable *symbolTable)
+ : TIntermTraverser(true, false, false, symbolTable),
+ mShaderType(shaderType),
+ mFragmentPrecisionHigh(fragmentPrecisionHigh)
+ {
+ }
- TIntermBinary *binary = new TIntermBinary(EOpIndexDirect);
- binary->setLeft(colVectorNode);
- TIntermConstantUnion *rowIndexNode = ConstructIndexNode(rowIndex);
- binary->setRight(rowIndexNode);
- return binary;
-}
+ protected:
+ bool visitAggregate(Visit visit, TIntermAggregate *node) override;
+ bool visitBlock(Visit visit, TIntermBlock *node) override;
-} // namespace anonymous
+ private:
+ void scalarizeArgs(TIntermAggregate *aggregate, bool scalarizeVector, bool scalarizeMatrix);
+
+ // If we have the following code:
+ // mat4 m(0);
+ // vec4 v(1, m);
+ // We will rewrite to:
+ // mat4 m(0);
+ // mat4 s0 = m;
+ // vec4 v(1, s0[0][0], s0[0][1], s0[0][2]);
+ // This function is to create nodes for "mat4 s0 = m;" and insert it to the code sequence. This
+ // way the possible side effects of the constructor argument will only be evaluated once.
+ void createTempVariable(TIntermTyped *original);
-bool ScalarizeVecAndMatConstructorArgs::visitAggregate(Visit visit, TIntermAggregate *node)
+ std::vector<TIntermSequence> mBlockStack;
+
+ sh::GLenum mShaderType;
+ bool mFragmentPrecisionHigh;
+};
+
+bool ScalarizeArgsTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
{
- if (visit == PreVisit)
+ if (visit == PreVisit && node->getOp() == EOpConstruct)
{
- switch (node->getOp())
- {
- case EOpSequence:
- mSequenceStack.push_back(TIntermSequence());
- {
- for (TIntermSequence::const_iterator iter = node->getSequence()->begin();
- iter != node->getSequence()->end(); ++iter)
- {
- TIntermNode *child = *iter;
- ASSERT(child != NULL);
- child->traverse(this);
- mSequenceStack.back().push_back(child);
- }
- }
- if (mSequenceStack.back().size() > node->getSequence()->size())
- {
- node->getSequence()->clear();
- *(node->getSequence()) = mSequenceStack.back();
- }
- mSequenceStack.pop_back();
- return false;
- case EOpConstructVec2:
- case EOpConstructVec3:
- case EOpConstructVec4:
- case EOpConstructBVec2:
- case EOpConstructBVec3:
- case EOpConstructBVec4:
- case EOpConstructIVec2:
- case EOpConstructIVec3:
- case EOpConstructIVec4:
- if (ContainsMatrixNode(*(node->getSequence())))
- scalarizeArgs(node, false, true);
- break;
- case EOpConstructMat2:
- case EOpConstructMat2x3:
- case EOpConstructMat2x4:
- case EOpConstructMat3x2:
- case EOpConstructMat3:
- case EOpConstructMat3x4:
- case EOpConstructMat4x2:
- case EOpConstructMat4x3:
- case EOpConstructMat4:
- if (ContainsVectorNode(*(node->getSequence())))
- scalarizeArgs(node, true, false);
- break;
- default:
- break;
- }
+ if (node->getType().isVector() && ContainsMatrixNode(*(node->getSequence())))
+ scalarizeArgs(node, false, true);
+ else if (node->getType().isMatrix() && ContainsVectorNode(*(node->getSequence())))
+ scalarizeArgs(node, true, false);
}
return true;
}
-void ScalarizeVecAndMatConstructorArgs::scalarizeArgs(
- TIntermAggregate *aggregate, bool scalarizeVector, bool scalarizeMatrix)
+bool ScalarizeArgsTraverser::visitBlock(Visit visit, TIntermBlock *node)
{
- ASSERT(aggregate);
- int size = 0;
- switch (aggregate->getOp())
+ mBlockStack.push_back(TIntermSequence());
+ {
+ for (TIntermNode *child : *node->getSequence())
+ {
+ ASSERT(child != nullptr);
+ child->traverse(this);
+ mBlockStack.back().push_back(child);
+ }
+ }
+ if (mBlockStack.back().size() > node->getSequence()->size())
{
- case EOpConstructVec2:
- case EOpConstructBVec2:
- case EOpConstructIVec2:
- size = 2;
- break;
- case EOpConstructVec3:
- case EOpConstructBVec3:
- case EOpConstructIVec3:
- size = 3;
- break;
- case EOpConstructVec4:
- case EOpConstructBVec4:
- case EOpConstructIVec4:
- case EOpConstructMat2:
- size = 4;
- break;
- case EOpConstructMat2x3:
- case EOpConstructMat3x2:
- size = 6;
- break;
- case EOpConstructMat2x4:
- case EOpConstructMat4x2:
- size = 8;
- break;
- case EOpConstructMat3:
- size = 9;
- break;
- case EOpConstructMat3x4:
- case EOpConstructMat4x3:
- size = 12;
- break;
- case EOpConstructMat4:
- size = 16;
- break;
- default:
- break;
+ node->getSequence()->clear();
+ *(node->getSequence()) = mBlockStack.back();
}
+ mBlockStack.pop_back();
+ return false;
+}
+
+void ScalarizeArgsTraverser::scalarizeArgs(TIntermAggregate *aggregate,
+ bool scalarizeVector,
+ bool scalarizeMatrix)
+{
+ ASSERT(aggregate);
+ ASSERT(!aggregate->isArray());
+ int size = static_cast<int>(aggregate->getType().getObjectSize());
TIntermSequence *sequence = aggregate->getSequence();
TIntermSequence original(*sequence);
sequence->clear();
@@ -179,12 +141,10 @@ void ScalarizeVecAndMatConstructorArgs::scalarizeArgs(
ASSERT(size > 0);
TIntermTyped *node = original[ii]->getAsTyped();
ASSERT(node);
- TString varName = createTempVariable(node);
+ createTempVariable(node);
if (node->isScalar())
{
- TIntermSymbol *symbolNode =
- new TIntermSymbol(-1, varName, node->getType());
- sequence->push_back(symbolNode);
+ sequence->push_back(createTempSymbol(node->getType()));
size--;
}
else if (node->isVector())
@@ -195,17 +155,14 @@ void ScalarizeVecAndMatConstructorArgs::scalarizeArgs(
size -= repeat;
for (int index = 0; index < repeat; ++index)
{
- TIntermSymbol *symbolNode =
- new TIntermSymbol(-1, varName, node->getType());
- TIntermBinary *newNode = ConstructVectorIndexBinaryNode(
- symbolNode, index);
+ TIntermSymbol *symbolNode = createTempSymbol(node->getType());
+ TIntermBinary *newNode = ConstructVectorIndexBinaryNode(symbolNode, index);
sequence->push_back(newNode);
}
}
else
{
- TIntermSymbol *symbolNode =
- new TIntermSymbol(-1, varName, node->getType());
+ TIntermSymbol *symbolNode = createTempSymbol(node->getType());
sequence->push_back(symbolNode);
size -= node->getNominalSize();
}
@@ -220,10 +177,9 @@ void ScalarizeVecAndMatConstructorArgs::scalarizeArgs(
size -= repeat;
while (repeat > 0)
{
- TIntermSymbol *symbolNode =
- new TIntermSymbol(-1, varName, node->getType());
- TIntermBinary *newNode = ConstructMatrixIndexBinaryNode(
- symbolNode, colIndex, rowIndex);
+ TIntermSymbol *symbolNode = createTempSymbol(node->getType());
+ TIntermBinary *newNode =
+ ConstructMatrixIndexBinaryNode(symbolNode, colIndex, rowIndex);
sequence->push_back(newNode);
rowIndex++;
if (rowIndex >= node->getRows())
@@ -236,8 +192,7 @@ void ScalarizeVecAndMatConstructorArgs::scalarizeArgs(
}
else
{
- TIntermSymbol *symbolNode =
- new TIntermSymbol(-1, varName, node->getType());
+ TIntermSymbol *symbolNode = createTempSymbol(node->getType());
sequence->push_back(symbolNode);
size -= node->getCols() * node->getRows();
}
@@ -245,51 +200,39 @@ void ScalarizeVecAndMatConstructorArgs::scalarizeArgs(
}
}
-TString ScalarizeVecAndMatConstructorArgs::createTempVariable(TIntermTyped *original)
+void ScalarizeArgsTraverser::createTempVariable(TIntermTyped *original)
{
- TString tempVarName = "_webgl_tmp_";
- if (original->isScalar())
- {
- tempVarName += "scalar_";
- }
- else if (original->isVector())
- {
- tempVarName += "vec_";
- }
- else
- {
- ASSERT(original->isMatrix());
- tempVarName += "mat_";
- }
- tempVarName += Str(mTempVarCount).c_str();
- mTempVarCount++;
-
ASSERT(original);
- TType type = original->getType();
- type.setQualifier(EvqTemporary);
+ nextTemporaryId();
+ TIntermDeclaration *decl = createTempInitDeclaration(original);
- if (mShaderType == GL_FRAGMENT_SHADER &&
- type.getBasicType() == EbtFloat &&
+ TType type = original->getType();
+ if (mShaderType == GL_FRAGMENT_SHADER && type.getBasicType() == EbtFloat &&
type.getPrecision() == EbpUndefined)
{
// We use the highest available precision for the temporary variable
// to avoid computing the actual precision using the rules defined
// in GLSL ES 1.0 Section 4.5.2.
- type.setPrecision(mFragmentPrecisionHigh ? EbpHigh : EbpMedium);
+ TIntermBinary *init = decl->getSequence()->at(0)->getAsBinaryNode();
+ init->getTypePointer()->setPrecision(mFragmentPrecisionHigh ? EbpHigh : EbpMedium);
+ init->getLeft()->getTypePointer()->setPrecision(mFragmentPrecisionHigh ? EbpHigh
+ : EbpMedium);
}
- TIntermBinary *init = new TIntermBinary(EOpInitialize);
- TIntermSymbol *symbolNode = new TIntermSymbol(-1, tempVarName, type);
- init->setLeft(symbolNode);
- init->setRight(original);
- init->setType(type);
-
- TIntermAggregate *decl = new TIntermAggregate(EOpDeclaration);
- decl->getSequence()->push_back(init);
-
- ASSERT(mSequenceStack.size() > 0);
- TIntermSequence &sequence = mSequenceStack.back();
+ ASSERT(mBlockStack.size() > 0);
+ TIntermSequence &sequence = mBlockStack.back();
sequence.push_back(decl);
+}
+
+} // namespace anonymous
- return tempVarName;
+void ScalarizeVecAndMatConstructorArgs(TIntermBlock *root,
+ sh::GLenum shaderType,
+ bool fragmentPrecisionHigh,
+ TSymbolTable *symbolTable)
+{
+ ScalarizeArgsTraverser scalarizer(shaderType, fragmentPrecisionHigh, symbolTable);
+ root->traverse(&scalarizer);
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h
index d7553be23b..b8f782d1ec 100644
--- a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h
+++ b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h
@@ -3,46 +3,25 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
+// Scalarize vector and matrix constructor args, so that vectors built from components don't have
+// matrix arguments, and matrices built from components don't have vector arguments. This avoids
+// driver bugs around vector and matrix constructors.
+//
#ifndef COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_
#define COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_
-#include "compiler/translator/IntermNode.h"
+#include "GLSLANG/ShaderLang.h"
-class ScalarizeVecAndMatConstructorArgs : public TIntermTraverser
+namespace sh
{
- public:
- ScalarizeVecAndMatConstructorArgs(sh::GLenum shaderType,
- bool fragmentPrecisionHigh)
- : TIntermTraverser(true, false, false),
- mTempVarCount(0),
- mShaderType(shaderType),
- mFragmentPrecisionHigh(fragmentPrecisionHigh) {}
-
- protected:
- bool visitAggregate(Visit visit, TIntermAggregate *node) override;
-
- private:
- void scalarizeArgs(TIntermAggregate *aggregate,
- bool scalarizeVector, bool scalarizeMatrix);
-
- // If we have the following code:
- // mat4 m(0);
- // vec4 v(1, m);
- // We will rewrite to:
- // mat4 m(0);
- // mat4 _webgl_tmp_mat_0 = m;
- // vec4 v(1, _webgl_tmp_mat_0[0][0], _webgl_tmp_mat_0[0][1], _webgl_tmp_mat_0[0][2]);
- // This function is to create nodes for "mat4 _webgl_tmp_mat_0 = m;" and insert it to
- // the code sequence.
- // Return the temporary variable name.
- TString createTempVariable(TIntermTyped *original);
-
- std::vector<TIntermSequence> mSequenceStack;
- int mTempVarCount;
-
- sh::GLenum mShaderType;
- bool mFragmentPrecisionHigh;
-};
+class TIntermBlock;
+class TSymbolTable;
+
+void ScalarizeVecAndMatConstructorArgs(TIntermBlock *root,
+ sh::GLenum shaderType,
+ bool fragmentPrecisionHigh,
+ TSymbolTable *symbolTable);
+} // namespace sh
#endif // COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp
index cccd4d3ff0..34c644d028 100644
--- a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp
@@ -13,8 +13,7 @@
namespace sh
{
SearchSymbol::SearchSymbol(const TString &symbol)
- : TIntermTraverser(true, false, false),
- mSymbol(symbol)
+ : TIntermTraverser(true, false, false), mSymbol(symbol)
{
match = false;
}
diff --git a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h
index 1e5e1700d1..b8379e041f 100644
--- a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h
+++ b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h
@@ -9,7 +9,7 @@
#ifndef COMPILER_TRANSLATOR_SEARCHSYMBOL_H_
#define COMPILER_TRANSLATOR_SEARCHSYMBOL_H_
-#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/ParseContext.h"
namespace sh
@@ -30,4 +30,4 @@ class SearchSymbol : public TIntermTraverser
};
}
-#endif // COMPILER_TRANSLATOR_SEARCHSYMBOL_H_
+#endif // COMPILER_TRANSLATOR_SEARCHSYMBOL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.cpp b/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.cpp
index de9050cd80..fe25823e38 100644
--- a/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.cpp
@@ -3,7 +3,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// The SeparateArrayInitialization function splits each array initialization into a declaration and an assignment.
+// The SeparateArrayInitialization function splits each array initialization into a declaration and
+// an assignment.
// Example:
// type[n] a = initializer;
// will effectively become
@@ -20,6 +21,9 @@
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/OutputHLSL.h"
+namespace sh
+{
+
namespace
{
@@ -27,9 +31,10 @@ class SeparateArrayInitTraverser : private TIntermTraverser
{
public:
static void apply(TIntermNode *root);
+
private:
SeparateArrayInitTraverser();
- bool visitAggregate(Visit, TIntermAggregate *node) override;
+ bool visitDeclaration(Visit, TIntermDeclaration *node) override;
};
void SeparateArrayInitTraverser::apply(TIntermNode *root)
@@ -39,54 +44,49 @@ void SeparateArrayInitTraverser::apply(TIntermNode *root)
separateInit.updateTree();
}
-SeparateArrayInitTraverser::SeparateArrayInitTraverser()
- : TIntermTraverser(true, false, false)
+SeparateArrayInitTraverser::SeparateArrayInitTraverser() : TIntermTraverser(true, false, false)
{
}
-bool SeparateArrayInitTraverser::visitAggregate(Visit, TIntermAggregate *node)
+bool SeparateArrayInitTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
{
- if (node->getOp() == EOpDeclaration)
+ TIntermSequence *sequence = node->getSequence();
+ TIntermBinary *initNode = sequence->back()->getAsBinaryNode();
+ if (initNode != nullptr && initNode->getOp() == EOpInitialize)
{
- TIntermSequence *sequence = node->getSequence();
- TIntermBinary *initNode = sequence->back()->getAsBinaryNode();
- if (initNode != nullptr && initNode->getOp() == EOpInitialize)
+ TIntermTyped *initializer = initNode->getRight();
+ if (initializer->isArray() && !sh::OutputHLSL::canWriteAsHLSLLiteral(initializer))
{
- TIntermTyped *initializer = initNode->getRight();
- if (initializer->isArray() && !sh::OutputHLSL::canWriteAsHLSLLiteral(initializer))
- {
- // We rely on that array declarations have been isolated to single declarations.
- ASSERT(sequence->size() == 1);
- TIntermTyped *symbol = initNode->getLeft();
- TIntermAggregate *parentAgg = getParentNode()->getAsAggregate();
- ASSERT(parentAgg != nullptr);
-
- TIntermSequence replacements;
-
- TIntermAggregate *replacementDeclaration = new TIntermAggregate;
- replacementDeclaration->setOp(EOpDeclaration);
- replacementDeclaration->getSequence()->push_back(symbol);
- replacementDeclaration->setLine(symbol->getLine());
- replacements.push_back(replacementDeclaration);
-
- TIntermBinary *replacementAssignment = new TIntermBinary(EOpAssign);
- replacementAssignment->setLeft(symbol);
- replacementAssignment->setRight(initializer);
- replacementAssignment->setType(initializer->getType());
- replacementAssignment->setLine(symbol->getLine());
- replacements.push_back(replacementAssignment);
-
- mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(parentAgg, node, replacements));
- }
+ // We rely on that array declarations have been isolated to single declarations.
+ ASSERT(sequence->size() == 1);
+ TIntermTyped *symbol = initNode->getLeft();
+ TIntermBlock *parentBlock = getParentNode()->getAsBlock();
+ ASSERT(parentBlock != nullptr);
+
+ TIntermSequence replacements;
+
+ TIntermDeclaration *replacementDeclaration = new TIntermDeclaration();
+ replacementDeclaration->appendDeclarator(symbol);
+ replacementDeclaration->setLine(symbol->getLine());
+ replacements.push_back(replacementDeclaration);
+
+ TIntermBinary *replacementAssignment =
+ new TIntermBinary(EOpAssign, symbol, initializer);
+ replacementAssignment->setLine(symbol->getLine());
+ replacements.push_back(replacementAssignment);
+
+ mMultiReplacements.push_back(
+ NodeReplaceWithMultipleEntry(parentBlock, node, replacements));
}
- return false;
}
- return true;
+ return false;
}
-} // namespace
+} // namespace
void SeparateArrayInitialization(TIntermNode *root)
{
SeparateArrayInitTraverser::apply(root);
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.h b/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.h
index d16357a3af..3a9bb55dd1 100644
--- a/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.h
+++ b/src/3rdparty/angle/src/compiler/translator/SeparateArrayInitialization.h
@@ -3,7 +3,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// The SeparateArrayInitialization function splits each array initialization into a declaration and an assignment.
+// The SeparateArrayInitialization function splits each array initialization into a declaration and
+// an assignment.
// Example:
// type[n] a = initializer;
// will effectively become
@@ -18,8 +19,11 @@
#ifndef COMPILER_TRANSLATOR_SEPARATEARRAYINITIALIZATION_H_
#define COMPILER_TRANSLATOR_SEPARATEARRAYINITIALIZATION_H_
+namespace sh
+{
class TIntermNode;
void SeparateArrayInitialization(TIntermNode *root);
+} // namespace sh
#endif // COMPILER_TRANSLATOR_SEPARATEARRAYINITIALIZATION_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.cpp b/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.cpp
index d33747f85b..9a066075c0 100644
--- a/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.cpp
@@ -5,8 +5,8 @@
//
// The SeparateDeclarations function processes declarations, so that in the end each declaration
// contains only one declarator.
-// This is useful as an intermediate step when initialization needs to be separated from declaration,
-// or when things need to be unfolded out of the initializer.
+// This is useful as an intermediate step when initialization needs to be separated from
+// declaration, or when things need to be unfolded out of the initializer.
// Example:
// int a[1] = int[1](1), b[1] = int[1](2);
// gets transformed when run through this class into the AST equivalent of:
@@ -15,7 +15,10 @@
#include "compiler/translator/SeparateDeclarations.h"
-#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
namespace
{
@@ -24,9 +27,10 @@ class SeparateDeclarationsTraverser : private TIntermTraverser
{
public:
static void apply(TIntermNode *root);
+
private:
SeparateDeclarationsTraverser();
- bool visitAggregate(Visit, TIntermAggregate *node) override;
+ bool visitDeclaration(Visit, TIntermDeclaration *node) override;
};
void SeparateDeclarationsTraverser::apply(TIntermNode *root)
@@ -41,37 +45,35 @@ SeparateDeclarationsTraverser::SeparateDeclarationsTraverser()
{
}
-bool SeparateDeclarationsTraverser::visitAggregate(Visit, TIntermAggregate *node)
+bool SeparateDeclarationsTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
{
- if (node->getOp() == EOpDeclaration)
+ TIntermSequence *sequence = node->getSequence();
+ if (sequence->size() > 1)
{
- TIntermSequence *sequence = node->getSequence();
- if (sequence->size() > 1)
- {
- TIntermAggregate *parentAgg = getParentNode()->getAsAggregate();
- ASSERT(parentAgg != nullptr);
+ TIntermBlock *parentBlock = getParentNode()->getAsBlock();
+ ASSERT(parentBlock != nullptr);
- TIntermSequence replacementDeclarations;
- for (size_t ii = 0; ii < sequence->size(); ++ii)
- {
- TIntermAggregate *replacementDeclaration = new TIntermAggregate;
-
- replacementDeclaration->setOp(EOpDeclaration);
- replacementDeclaration->getSequence()->push_back(sequence->at(ii));
- replacementDeclaration->setLine(sequence->at(ii)->getLine());
- replacementDeclarations.push_back(replacementDeclaration);
- }
+ TIntermSequence replacementDeclarations;
+ for (size_t ii = 0; ii < sequence->size(); ++ii)
+ {
+ TIntermDeclaration *replacementDeclaration = new TIntermDeclaration();
- mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(parentAgg, node, replacementDeclarations));
+ replacementDeclaration->appendDeclarator(sequence->at(ii)->getAsTyped());
+ replacementDeclaration->setLine(sequence->at(ii)->getLine());
+ replacementDeclarations.push_back(replacementDeclaration);
}
- return false;
+
+ mMultiReplacements.push_back(
+ NodeReplaceWithMultipleEntry(parentBlock, node, replacementDeclarations));
}
- return true;
+ return false;
}
-} // namespace
+} // namespace
void SeparateDeclarations(TIntermNode *root)
{
SeparateDeclarationsTraverser::apply(root);
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.h b/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.h
index 77913ab8bb..8142faea1c 100644
--- a/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.h
+++ b/src/3rdparty/angle/src/compiler/translator/SeparateDeclarations.h
@@ -5,8 +5,8 @@
//
// The SeparateDeclarations function processes declarations, so that in the end each declaration
// contains only one declarator.
-// This is useful as an intermediate step when initialization needs to be separated from declaration,
-// or when things need to be unfolded out of the initializer.
+// This is useful as an intermediate step when initialization needs to be separated from
+// declaration, or when things need to be unfolded out of the initializer.
// Example:
// int a[1] = int[1](1), b[1] = int[1](2);
// gets transformed when run through this class into the AST equivalent of:
@@ -16,8 +16,11 @@
#ifndef COMPILER_TRANSLATOR_SEPARATEDECLARATIONS_H_
#define COMPILER_TRANSLATOR_SEPARATEDECLARATIONS_H_
+namespace sh
+{
class TIntermNode;
void SeparateDeclarations(TIntermNode *root);
+} // namespace sh
#endif // COMPILER_TRANSLATOR_SEPARATEDECLARATIONS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp b/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp
index e8e1a21d9c..01d627937c 100644
--- a/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.cpp
@@ -3,15 +3,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// SeparateExpressionsReturningArrays splits array-returning expressions that are not array names from more complex
-// expressions, assigning them to a temporary variable a#.
+// SeparateExpressionsReturningArrays splits array-returning expressions that are not array names
+// from more complex expressions, assigning them to a temporary variable a#.
// Examples where a, b and c are all arrays:
// (a = b) == (a = c) is split into a = b; type[n] a1 = a; a = c; type[n] a2 = a; a1 == a2;
// type d = type[n](...)[i]; is split into type[n] a1 = type[n](...); type d = a1[i];
#include "compiler/translator/SeparateExpressionsReturningArrays.h"
-#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermNodePatternMatcher.h"
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
namespace
{
@@ -20,7 +24,7 @@ namespace
class SeparateExpressionsTraverser : public TIntermTraverser
{
public:
- SeparateExpressionsTraverser();
+ SeparateExpressionsTraverser(TSymbolTable *symbolTable);
bool visitBinary(Visit visit, TIntermBinary *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
@@ -29,14 +33,17 @@ class SeparateExpressionsTraverser : public TIntermTraverser
bool foundArrayExpression() const { return mFoundArrayExpression; }
protected:
- // Marked to true once an operation that needs to be hoisted out of the expression has been found.
- // After that, no more AST updates are performed on that traversal.
+ // Marked to true once an operation that needs to be hoisted out of the expression has been
+ // found. After that, no more AST updates are performed on that traversal.
bool mFoundArrayExpression;
+
+ IntermNodePatternMatcher mPatternToSeparateMatcher;
};
-SeparateExpressionsTraverser::SeparateExpressionsTraverser()
- : TIntermTraverser(true, false, false),
- mFoundArrayExpression(false)
+SeparateExpressionsTraverser::SeparateExpressionsTraverser(TSymbolTable *symbolTable)
+ : TIntermTraverser(true, false, false, symbolTable),
+ mFoundArrayExpression(false),
+ mPatternToSeparateMatcher(IntermNodePatternMatcher::kExpressionReturningArray)
{
}
@@ -45,27 +52,7 @@ SeparateExpressionsTraverser::SeparateExpressionsTraverser()
// and also needs to be replaced in its original location by a different node.
TIntermBinary *CopyAssignmentNode(TIntermBinary *node)
{
- TIntermBinary *copyNode = new TIntermBinary(node->getOp());
- copyNode->setLeft(node->getLeft());
- copyNode->setRight(node->getRight());
- copyNode->setType(node->getType());
- return copyNode;
-}
-
-// Performs a shallow copy of a constructor/function call node.
-TIntermAggregate *CopyAggregateNode(TIntermAggregate *node)
-{
- TIntermAggregate *copyNode = new TIntermAggregate(node->getOp());
- TIntermSequence *copySeq = copyNode->getSequence();
- copySeq->insert(copySeq->begin(), node->getSequence()->begin(), node->getSequence()->end());
- copyNode->setType(node->getType());
- copyNode->setFunctionId(node->getFunctionId());
- if (node->isUserDefined())
- {
- copyNode->setUserDefined();
- }
- copyNode->setNameObj(node->getNameObj());
- return copyNode;
+ return new TIntermBinary(node->getOp(), node->getLeft(), node->getRight());
}
bool SeparateExpressionsTraverser::visitBinary(Visit visit, TIntermBinary *node)
@@ -73,90 +60,59 @@ bool SeparateExpressionsTraverser::visitBinary(Visit visit, TIntermBinary *node)
if (mFoundArrayExpression)
return false;
- // Early return if the expression is not an array or if we're not inside a complex expression.
- if (!node->getType().isArray() || parentNodeIsBlock())
+ // Return if the expression is not an array or if we're not inside a complex expression.
+ if (!mPatternToSeparateMatcher.match(node, getParentNode()))
return true;
- switch (node->getOp())
- {
- case EOpAssign:
- {
- mFoundArrayExpression = true;
-
- TIntermSequence insertions;
- insertions.push_back(CopyAssignmentNode(node));
- // TODO(oetuaho): In some cases it would be more optimal to not add the temporary node, but just use the
- // original target of the assignment. Care must be taken so that this doesn't happen when the same array
- // symbol is a target of assignment more than once in one expression.
- insertions.push_back(createTempInitDeclaration(node->getLeft()));
- insertStatementsInParentBlock(insertions);
-
- NodeUpdateEntry replaceVariable(getParentNode(), node, createTempSymbol(node->getType()), false);
- mReplacements.push_back(replaceVariable);
- }
- return false;
- default:
- return true;
- }
+ ASSERT(node->getOp() == EOpAssign);
+
+ mFoundArrayExpression = true;
+
+ TIntermSequence insertions;
+ insertions.push_back(CopyAssignmentNode(node));
+ // TODO(oetuaho): In some cases it would be more optimal to not add the temporary node, but just
+ // use the original target of the assignment. Care must be taken so that this doesn't happen
+ // when the same array symbol is a target of assignment more than once in one expression.
+ insertions.push_back(createTempInitDeclaration(node->getLeft()));
+ insertStatementsInParentBlock(insertions);
+
+ queueReplacement(createTempSymbol(node->getType()), OriginalNode::IS_DROPPED);
+
+ return false;
}
bool SeparateExpressionsTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
{
if (mFoundArrayExpression)
- return false; // No need to traverse further
-
- if (getParentNode() != nullptr)
- {
- TIntermBinary *parentBinary = getParentNode()->getAsBinaryNode();
- bool parentIsAssignment = (parentBinary != nullptr &&
- (parentBinary->getOp() == EOpAssign || parentBinary->getOp() == EOpInitialize));
-
- if (!node->getType().isArray() || parentNodeIsBlock() || parentIsAssignment)
- return true;
-
- if (node->isConstructor())
- {
- mFoundArrayExpression = true;
+ return false; // No need to traverse further
- TIntermSequence insertions;
- insertions.push_back(createTempInitDeclaration(CopyAggregateNode(node)));
- insertStatementsInParentBlock(insertions);
+ if (!mPatternToSeparateMatcher.match(node, getParentNode()))
+ return true;
- NodeUpdateEntry replaceVariable(getParentNode(), node, createTempSymbol(node->getType()), false);
- mReplacements.push_back(replaceVariable);
+ ASSERT(node->isConstructor() || node->getOp() == EOpCallFunctionInAST);
- return false;
- }
- else if (node->getOp() == EOpFunctionCall)
- {
- mFoundArrayExpression = true;
+ mFoundArrayExpression = true;
- TIntermSequence insertions;
- insertions.push_back(createTempInitDeclaration(CopyAggregateNode(node)));
- insertStatementsInParentBlock(insertions);
+ TIntermSequence insertions;
+ insertions.push_back(createTempInitDeclaration(node->shallowCopy()));
+ insertStatementsInParentBlock(insertions);
- NodeUpdateEntry replaceVariable(getParentNode(), node, createTempSymbol(node->getType()), false);
- mReplacements.push_back(replaceVariable);
+ queueReplacement(createTempSymbol(node->getType()), OriginalNode::IS_DROPPED);
- return false;
- }
- }
- return true;
+ return false;
}
void SeparateExpressionsTraverser::nextIteration()
{
mFoundArrayExpression = false;
- nextTemporaryIndex();
+ nextTemporaryId();
}
-} // namespace
+} // namespace
-void SeparateExpressionsReturningArrays(TIntermNode *root, unsigned int *temporaryIndex)
+void SeparateExpressionsReturningArrays(TIntermNode *root, TSymbolTable *symbolTable)
{
- SeparateExpressionsTraverser traverser;
- ASSERT(temporaryIndex != nullptr);
- traverser.useTemporaryIndex(temporaryIndex);
+ SeparateExpressionsTraverser traverser(symbolTable);
// Separate one expression at a time, and reset the traverser between iterations.
do
{
@@ -164,6 +120,7 @@ void SeparateExpressionsReturningArrays(TIntermNode *root, unsigned int *tempora
root->traverse(&traverser);
if (traverser.foundArrayExpression())
traverser.updateTree();
- }
- while (traverser.foundArrayExpression());
+ } while (traverser.foundArrayExpression());
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.h b/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.h
index b178ebb3ec..f8eb438748 100644
--- a/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.h
+++ b/src/3rdparty/angle/src/compiler/translator/SeparateExpressionsReturningArrays.h
@@ -3,8 +3,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// SeparateExpressionsReturningArrays splits array-returning expressions that are not array names from more complex
-// expressions, assigning them to a temporary variable a#.
+// SeparateExpressionsReturningArrays splits array-returning expressions that are not array names
+// from more complex expressions, assigning them to a temporary variable a#.
// Examples where a, b and c are all arrays:
// (a = b) == (a = c) is split into a = b; type[n] a1 = a; a = c; type[n] a2 = a; a1 == a2;
// type d = type[n](...)[i]; is split into type[n] a1 = type[n](...); type d = a1[i];
@@ -12,8 +12,12 @@
#ifndef COMPILER_TRANSLATOR_SEPARATEEXPRESSIONSRETURNINGARRAYS_H_
#define COMPILER_TRANSLATOR_SEPARATEEXPRESSIONSRETURNINGARRAYS_H_
+namespace sh
+{
class TIntermNode;
+class TSymbolTable;
-void SeparateExpressionsReturningArrays(TIntermNode *root, unsigned int *temporaryIndex);
+void SeparateExpressionsReturningArrays(TIntermNode *root, TSymbolTable *symbolTable);
+} // namespace sh
-#endif // COMPILER_TRANSLATOR_SEPARATEEXPRESSIONSRETURNINGARRAYS_H_
+#endif // COMPILER_TRANSLATOR_SEPARATEEXPRESSIONSRETURNINGARRAYS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/Severity.h b/src/3rdparty/angle/src/compiler/translator/Severity.h
new file mode 100644
index 0000000000..47808a16a7
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/Severity.h
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_SEVERITY_H_
+#define COMPILER_TRANSLATOR_SEVERITY_H_
+
+namespace sh
+{
+
+// Severity is used to classify info log messages.
+enum Severity
+{
+ SH_WARNING,
+ SH_ERROR
+};
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_SEVERITY_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp
index e257f93e48..eeb13f2ec0 100644
--- a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp
@@ -16,10 +16,13 @@
#include "compiler/translator/length_limits.h"
#ifdef ANGLE_ENABLE_HLSL
#include "compiler/translator/TranslatorHLSL.h"
-#endif // ANGLE_ENABLE_HLSL
+#endif // ANGLE_ENABLE_HLSL
#include "compiler/translator/VariablePacker.h"
#include "angle_gl.h"
+namespace sh
+{
+
namespace
{
@@ -34,70 +37,109 @@ template <typename VarT>
const std::vector<VarT> *GetVariableList(const TCompiler *compiler);
template <>
-const std::vector<sh::Uniform> *GetVariableList(const TCompiler *compiler)
+const std::vector<Uniform> *GetVariableList(const TCompiler *compiler)
{
return &compiler->getUniforms();
}
template <>
-const std::vector<sh::Varying> *GetVariableList(const TCompiler *compiler)
+const std::vector<Varying> *GetVariableList(const TCompiler *compiler)
{
- return &compiler->getVaryings();
+ switch (compiler->getShaderType())
+ {
+ case GL_VERTEX_SHADER:
+ return &compiler->getOutputVaryings();
+ case GL_FRAGMENT_SHADER:
+ return &compiler->getInputVaryings();
+ case GL_COMPUTE_SHADER:
+ ASSERT(compiler->getOutputVaryings().empty() && compiler->getInputVaryings().empty());
+ return &compiler->getOutputVaryings();
+ // Since geometry shaders have both input and output varyings, we shouldn't call GetVaryings
+ // on a geometry shader.
+ default:
+ return nullptr;
+ }
}
template <>
-const std::vector<sh::Attribute> *GetVariableList(const TCompiler *compiler)
+const std::vector<Attribute> *GetVariableList(const TCompiler *compiler)
{
return &compiler->getAttributes();
}
template <>
-const std::vector<sh::OutputVariable> *GetVariableList(const TCompiler *compiler)
+const std::vector<OutputVariable> *GetVariableList(const TCompiler *compiler)
{
return &compiler->getOutputVariables();
}
template <>
-const std::vector<sh::InterfaceBlock> *GetVariableList(const TCompiler *compiler)
+const std::vector<InterfaceBlock> *GetVariableList(const TCompiler *compiler)
{
return &compiler->getInterfaceBlocks();
}
-template <typename VarT>
-const std::vector<VarT> *GetShaderVariables(const ShHandle handle)
+TCompiler *GetCompilerFromHandle(ShHandle handle)
{
if (!handle)
{
- return NULL;
+ return nullptr;
}
- TShHandleBase* base = static_cast<TShHandleBase*>(handle);
- TCompiler* compiler = base->getAsCompiler();
+ TShHandleBase *base = static_cast<TShHandleBase *>(handle);
+ return base->getAsCompiler();
+}
+
+template <typename VarT>
+const std::vector<VarT> *GetShaderVariables(const ShHandle handle)
+{
+ TCompiler *compiler = GetCompilerFromHandle(handle);
if (!compiler)
{
- return NULL;
+ return nullptr;
}
return GetVariableList<VarT>(compiler);
}
-TCompiler *GetCompilerFromHandle(ShHandle handle)
-{
- if (!handle)
- return NULL;
- TShHandleBase *base = static_cast<TShHandleBase *>(handle);
- return base->getAsCompiler();
-}
-
#ifdef ANGLE_ENABLE_HLSL
TranslatorHLSL *GetTranslatorHLSLFromHandle(ShHandle handle)
{
if (!handle)
- return NULL;
+ return nullptr;
TShHandleBase *base = static_cast<TShHandleBase *>(handle);
return base->getAsTranslatorHLSL();
}
-#endif // ANGLE_ENABLE_HLSL
+#endif // ANGLE_ENABLE_HLSL
+
+GLenum GetGeometryShaderPrimitiveTypeEnum(sh::TLayoutPrimitiveType primitiveType)
+{
+ switch (primitiveType)
+ {
+ case EptPoints:
+ return GL_POINTS;
+ case EptLines:
+ return GL_LINES;
+ case EptLinesAdjacency:
+ return GL_LINES_ADJACENCY_EXT;
+ case EptTriangles:
+ return GL_TRIANGLES;
+ case EptTrianglesAdjacency:
+ return GL_TRIANGLES_ADJACENCY_EXT;
+
+ case EptLineStrip:
+ return GL_LINE_STRIP;
+ case EptTriangleStrip:
+ return GL_TRIANGLE_STRIP;
+
+ case EptUndefined:
+ return GL_INVALID_VALUE;
+
+ default:
+ UNREACHABLE();
+ return GL_INVALID_VALUE;
+ }
+}
} // anonymous namespace
@@ -105,7 +147,7 @@ TranslatorHLSL *GetTranslatorHLSLFromHandle(ShHandle handle)
// Driver must call this first, once, before doing any other compiler operations.
// Subsequent calls to this function are no-op.
//
-bool ShInitialize()
+bool Initialize()
{
if (!isInitialized)
{
@@ -117,7 +159,7 @@ bool ShInitialize()
//
// Cleanup symbol tables
//
-bool ShFinalize()
+bool Finalize()
{
if (isInitialized)
{
@@ -130,33 +172,38 @@ bool ShFinalize()
//
// Initialize built-in resources with minimum expected values.
//
-void ShInitBuiltInResources(ShBuiltInResources* resources)
+void InitBuiltInResources(ShBuiltInResources *resources)
{
// Make comparable.
memset(resources, 0, sizeof(*resources));
// Constants.
- resources->MaxVertexAttribs = 8;
- resources->MaxVertexUniformVectors = 128;
- resources->MaxVaryingVectors = 8;
- resources->MaxVertexTextureImageUnits = 0;
+ resources->MaxVertexAttribs = 8;
+ resources->MaxVertexUniformVectors = 128;
+ resources->MaxVaryingVectors = 8;
+ resources->MaxVertexTextureImageUnits = 0;
resources->MaxCombinedTextureImageUnits = 8;
- resources->MaxTextureImageUnits = 8;
- resources->MaxFragmentUniformVectors = 16;
- resources->MaxDrawBuffers = 1;
+ resources->MaxTextureImageUnits = 8;
+ resources->MaxFragmentUniformVectors = 16;
+ resources->MaxDrawBuffers = 1;
// Extensions.
- resources->OES_standard_derivatives = 0;
- resources->OES_EGL_image_external = 0;
- resources->ARB_texture_rectangle = 0;
- resources->EXT_blend_func_extended = 0;
- resources->EXT_draw_buffers = 0;
- resources->EXT_frag_depth = 0;
- resources->EXT_shader_texture_lod = 0;
- resources->WEBGL_debug_shader_precision = 0;
- resources->EXT_shader_framebuffer_fetch = 0;
- resources->NV_shader_framebuffer_fetch = 0;
- resources->ARM_shader_framebuffer_fetch = 0;
+ resources->OES_standard_derivatives = 0;
+ resources->OES_EGL_image_external = 0;
+ resources->OES_EGL_image_external_essl3 = 0;
+ resources->NV_EGL_stream_consumer_external = 0;
+ resources->ARB_texture_rectangle = 0;
+ resources->EXT_blend_func_extended = 0;
+ resources->EXT_draw_buffers = 0;
+ resources->EXT_frag_depth = 0;
+ resources->EXT_shader_texture_lod = 0;
+ resources->WEBGL_debug_shader_precision = 0;
+ resources->EXT_shader_framebuffer_fetch = 0;
+ resources->NV_shader_framebuffer_fetch = 0;
+ resources->ARM_shader_framebuffer_fetch = 0;
+ resources->OVR_multiview = 0;
+ resources->EXT_YUV_target = 0;
+ resources->OES_geometry_shader = 0;
resources->NV_draw_buffers = 0;
@@ -164,63 +211,125 @@ void ShInitBuiltInResources(ShBuiltInResources* resources)
resources->FragmentPrecisionHigh = 0;
// GLSL ES 3.0 constants.
- resources->MaxVertexOutputVectors = 16;
+ resources->MaxVertexOutputVectors = 16;
resources->MaxFragmentInputVectors = 15;
- resources->MinProgramTexelOffset = -8;
- resources->MaxProgramTexelOffset = 7;
+ resources->MinProgramTexelOffset = -8;
+ resources->MaxProgramTexelOffset = 7;
// Extensions constants.
resources->MaxDualSourceDrawBuffers = 0;
+ resources->MaxViewsOVR = 4;
+
// Disable name hashing by default.
- resources->HashFunction = NULL;
+ resources->HashFunction = nullptr;
resources->ArrayIndexClampingStrategy = SH_CLAMP_WITH_CLAMP_INTRINSIC;
resources->MaxExpressionComplexity = 256;
- resources->MaxCallStackDepth = 256;
+ resources->MaxCallStackDepth = 256;
+ resources->MaxFunctionParameters = 1024;
+
+ // ES 3.1 Revision 4, 7.2 Built-in Constants
+
+ // ES 3.1, Revision 4, 8.13 Texture minification
+ // "The value of MIN_PROGRAM_TEXTURE_GATHER_OFFSET must be less than or equal to the value of
+ // MIN_PROGRAM_TEXEL_OFFSET. The value of MAX_PROGRAM_TEXTURE_GATHER_OFFSET must be greater than
+ // or equal to the value of MAX_PROGRAM_TEXEL_OFFSET"
+ resources->MinProgramTextureGatherOffset = -8;
+ resources->MaxProgramTextureGatherOffset = 7;
+
+ resources->MaxImageUnits = 4;
+ resources->MaxVertexImageUniforms = 0;
+ resources->MaxFragmentImageUniforms = 0;
+ resources->MaxComputeImageUniforms = 4;
+ resources->MaxCombinedImageUniforms = 4;
+
+ resources->MaxUniformLocations = 1024;
+
+ resources->MaxCombinedShaderOutputResources = 4;
+
+ resources->MaxComputeWorkGroupCount[0] = 65535;
+ resources->MaxComputeWorkGroupCount[1] = 65535;
+ resources->MaxComputeWorkGroupCount[2] = 65535;
+ resources->MaxComputeWorkGroupSize[0] = 128;
+ resources->MaxComputeWorkGroupSize[1] = 128;
+ resources->MaxComputeWorkGroupSize[2] = 64;
+ resources->MaxComputeUniformComponents = 512;
+ resources->MaxComputeTextureImageUnits = 16;
+
+ resources->MaxComputeAtomicCounters = 8;
+ resources->MaxComputeAtomicCounterBuffers = 1;
+
+ resources->MaxVertexAtomicCounters = 0;
+ resources->MaxFragmentAtomicCounters = 0;
+ resources->MaxCombinedAtomicCounters = 8;
+ resources->MaxAtomicCounterBindings = 1;
+
+ resources->MaxVertexAtomicCounterBuffers = 0;
+ resources->MaxFragmentAtomicCounterBuffers = 0;
+ resources->MaxCombinedAtomicCounterBuffers = 1;
+ resources->MaxAtomicCounterBufferSize = 32;
+
+ resources->MaxUniformBufferBindings = 32;
+ resources->MaxShaderStorageBufferBindings = 4;
+
+ resources->MaxGeometryUniformComponents = 1024;
+ resources->MaxGeometryUniformBlocks = 12;
+ resources->MaxGeometryInputComponents = 64;
+ resources->MaxGeometryOutputComponents = 64;
+ resources->MaxGeometryOutputVertices = 256;
+ resources->MaxGeometryTotalOutputComponents = 1024;
+ resources->MaxGeometryTextureImageUnits = 16;
+ resources->MaxGeometryAtomicCounterBuffers = 0;
+ resources->MaxGeometryAtomicCounters = 0;
+ resources->MaxGeometryShaderStorageBlocks = 0;
+ resources->MaxGeometryShaderInvocations = 32;
+ resources->MaxGeometryImageUniforms = 0;
}
//
// Driver calls these to create and destroy compiler objects.
//
-ShHandle ShConstructCompiler(sh::GLenum type, ShShaderSpec spec,
- ShShaderOutput output,
- const ShBuiltInResources* resources)
+ShHandle ConstructCompiler(sh::GLenum type,
+ ShShaderSpec spec,
+ ShShaderOutput output,
+ const ShBuiltInResources *resources)
{
- TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output));
+ TShHandleBase *base = static_cast<TShHandleBase *>(ConstructCompiler(type, spec, output));
if (base == nullptr)
{
return 0;
}
- TCompiler* compiler = base->getAsCompiler();
+ TCompiler *compiler = base->getAsCompiler();
if (compiler == nullptr)
{
return 0;
}
// Generate built-in symbol table.
- if (!compiler->Init(*resources)) {
- ShDestruct(base);
+ if (!compiler->Init(*resources))
+ {
+ Destruct(base);
return 0;
}
- return reinterpret_cast<void*>(base);
+ return reinterpret_cast<void *>(base);
}
-void ShDestruct(ShHandle handle)
+void Destruct(ShHandle handle)
{
if (handle == 0)
return;
- TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+ TShHandleBase *base = static_cast<TShHandleBase *>(handle);
if (base->getAsCompiler())
DeleteCompiler(base->getAsCompiler());
}
-const std::string &ShGetBuiltInResourcesString(const ShHandle handle)
+const std::string &GetBuiltInResourcesString(const ShHandle handle)
{
TCompiler *compiler = GetCompilerFromHandle(handle);
ASSERT(compiler);
@@ -234,11 +343,10 @@ const std::string &ShGetBuiltInResourcesString(const ShHandle handle)
// Return: The return value of ShCompile is really boolean, indicating
// success or failure.
//
-bool ShCompile(
- const ShHandle handle,
- const char *const shaderStrings[],
- size_t numStrings,
- int compileOptions)
+bool Compile(const ShHandle handle,
+ const char *const shaderStrings[],
+ size_t numStrings,
+ ShCompileOptions compileOptions)
{
TCompiler *compiler = GetCompilerFromHandle(handle);
ASSERT(compiler);
@@ -246,23 +354,23 @@ bool ShCompile(
return compiler->compile(shaderStrings, numStrings, compileOptions);
}
-void ShClearResults(const ShHandle handle)
+void ClearResults(const ShHandle handle)
{
TCompiler *compiler = GetCompilerFromHandle(handle);
ASSERT(compiler);
compiler->clearResults();
}
-int ShGetShaderVersion(const ShHandle handle)
+int GetShaderVersion(const ShHandle handle)
{
- TCompiler* compiler = GetCompilerFromHandle(handle);
+ TCompiler *compiler = GetCompilerFromHandle(handle);
ASSERT(compiler);
return compiler->getShaderVersion();
}
-ShShaderOutput ShGetShaderOutputType(const ShHandle handle)
+ShShaderOutput GetShaderOutputType(const ShHandle handle)
{
- TCompiler* compiler = GetCompilerFromHandle(handle);
+ TCompiler *compiler = GetCompilerFromHandle(handle);
ASSERT(compiler);
return compiler->getOutputType();
}
@@ -270,7 +378,7 @@ ShShaderOutput ShGetShaderOutputType(const ShHandle handle)
//
// Return any compiler log of messages for the application.
//
-const std::string &ShGetInfoLog(const ShHandle handle)
+const std::string &GetInfoLog(const ShHandle handle)
{
TCompiler *compiler = GetCompilerFromHandle(handle);
ASSERT(compiler);
@@ -282,7 +390,7 @@ const std::string &ShGetInfoLog(const ShHandle handle)
//
// Return any object code.
//
-const std::string &ShGetObjectCode(const ShHandle handle)
+const std::string &GetObjectCode(const ShHandle handle)
{
TCompiler *compiler = GetCompilerFromHandle(handle);
ASSERT(compiler);
@@ -291,58 +399,107 @@ const std::string &ShGetObjectCode(const ShHandle handle)
return infoSink.obj.str();
}
-const std::map<std::string, std::string> *ShGetNameHashingMap(
- const ShHandle handle)
+const std::map<std::string, std::string> *GetNameHashingMap(const ShHandle handle)
{
TCompiler *compiler = GetCompilerFromHandle(handle);
ASSERT(compiler);
return &(compiler->getNameMap());
}
-const std::vector<sh::Uniform> *ShGetUniforms(const ShHandle handle)
+const std::vector<Uniform> *GetUniforms(const ShHandle handle)
{
- return GetShaderVariables<sh::Uniform>(handle);
+ return GetShaderVariables<Uniform>(handle);
}
-const std::vector<sh::Varying> *ShGetVaryings(const ShHandle handle)
+const std::vector<Varying> *GetInputVaryings(const ShHandle handle)
{
- return GetShaderVariables<sh::Varying>(handle);
+ TCompiler *compiler = GetCompilerFromHandle(handle);
+ if (compiler == nullptr)
+ {
+ return nullptr;
+ }
+ return &compiler->getInputVaryings();
}
-const std::vector<sh::Attribute> *ShGetAttributes(const ShHandle handle)
+const std::vector<Varying> *GetOutputVaryings(const ShHandle handle)
{
- return GetShaderVariables<sh::Attribute>(handle);
+ TCompiler *compiler = GetCompilerFromHandle(handle);
+ if (compiler == nullptr)
+ {
+ return nullptr;
+ }
+ return &compiler->getOutputVaryings();
}
-const std::vector<sh::OutputVariable> *ShGetOutputVariables(const ShHandle handle)
+const std::vector<Varying> *GetVaryings(const ShHandle handle)
{
- return GetShaderVariables<sh::OutputVariable>(handle);
+ return GetShaderVariables<Varying>(handle);
}
-const std::vector<sh::InterfaceBlock> *ShGetInterfaceBlocks(const ShHandle handle)
+const std::vector<Attribute> *GetAttributes(const ShHandle handle)
{
- return GetShaderVariables<sh::InterfaceBlock>(handle);
+ return GetShaderVariables<Attribute>(handle);
}
-bool ShCheckVariablesWithinPackingLimits(
- int maxVectors, ShVariableInfo *varInfoArray, size_t varInfoArraySize)
+const std::vector<OutputVariable> *GetOutputVariables(const ShHandle handle)
{
- if (varInfoArraySize == 0)
- return true;
- ASSERT(varInfoArray);
- std::vector<sh::ShaderVariable> variables;
- for (size_t ii = 0; ii < varInfoArraySize; ++ii)
- {
- sh::ShaderVariable var(varInfoArray[ii].type, varInfoArray[ii].size);
- variables.push_back(var);
- }
- VariablePacker packer;
- return packer.CheckVariablesWithinPackingLimits(maxVectors, variables);
+ return GetShaderVariables<OutputVariable>(handle);
}
-bool ShGetInterfaceBlockRegister(const ShHandle handle,
- const std::string &interfaceBlockName,
- unsigned int *indexOut)
+const std::vector<InterfaceBlock> *GetInterfaceBlocks(const ShHandle handle)
+{
+ return GetShaderVariables<InterfaceBlock>(handle);
+}
+
+const std::vector<InterfaceBlock> *GetUniformBlocks(const ShHandle handle)
+{
+ ASSERT(handle);
+ TShHandleBase *base = static_cast<TShHandleBase *>(handle);
+ TCompiler *compiler = base->getAsCompiler();
+ ASSERT(compiler);
+
+ return &compiler->getUniformBlocks();
+}
+
+const std::vector<InterfaceBlock> *GetShaderStorageBlocks(const ShHandle handle)
+{
+ ASSERT(handle);
+ TShHandleBase *base = static_cast<TShHandleBase *>(handle);
+ TCompiler *compiler = base->getAsCompiler();
+ ASSERT(compiler);
+
+ return &compiler->getShaderStorageBlocks();
+}
+
+WorkGroupSize GetComputeShaderLocalGroupSize(const ShHandle handle)
+{
+ ASSERT(handle);
+
+ TShHandleBase *base = static_cast<TShHandleBase *>(handle);
+ TCompiler *compiler = base->getAsCompiler();
+ ASSERT(compiler);
+
+ return compiler->getComputeShaderLocalSize();
+}
+
+int GetVertexShaderNumViews(const ShHandle handle)
+{
+ ASSERT(handle);
+ TShHandleBase *base = static_cast<TShHandleBase *>(handle);
+ TCompiler *compiler = base->getAsCompiler();
+ ASSERT(compiler);
+
+ return compiler->getNumViews();
+}
+
+bool CheckVariablesWithinPackingLimits(int maxVectors, const std::vector<ShaderVariable> &variables)
+{
+ return CheckVariablesInPackingLimits(maxVectors, variables);
+}
+
+bool GetUniformBlockRegister(const ShHandle handle,
+ const std::string &uniformBlockName,
+ unsigned int *indexOut)
{
#ifdef ANGLE_ENABLE_HLSL
ASSERT(indexOut);
@@ -350,35 +507,72 @@ bool ShGetInterfaceBlockRegister(const ShHandle handle,
TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
ASSERT(translator);
- if (!translator->hasInterfaceBlock(interfaceBlockName))
+ if (!translator->hasUniformBlock(uniformBlockName))
{
return false;
}
- *indexOut = translator->getInterfaceBlockRegister(interfaceBlockName);
+ *indexOut = translator->getUniformBlockRegister(uniformBlockName);
return true;
#else
return false;
-#endif // ANGLE_ENABLE_HLSL
+#endif // ANGLE_ENABLE_HLSL
}
-bool ShGetUniformRegister(const ShHandle handle,
- const std::string &uniformName,
- unsigned int *indexOut)
+const std::map<std::string, unsigned int> *GetUniformRegisterMap(const ShHandle handle)
{
#ifdef ANGLE_ENABLE_HLSL
- ASSERT(indexOut);
TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
ASSERT(translator);
- if (!translator->hasUniform(uniformName))
- {
- return false;
- }
-
- *indexOut = translator->getUniformRegister(uniformName);
- return true;
+ return translator->getUniformRegisterMap();
#else
- return false;
-#endif // ANGLE_ENABLE_HLSL
+ return nullptr;
+#endif // ANGLE_ENABLE_HLSL
+}
+
+GLenum GetGeometryShaderInputPrimitiveType(const ShHandle handle)
+{
+ ASSERT(handle);
+
+ TShHandleBase *base = static_cast<TShHandleBase *>(handle);
+ TCompiler *compiler = base->getAsCompiler();
+ ASSERT(compiler);
+
+ return GetGeometryShaderPrimitiveTypeEnum(compiler->getGeometryShaderInputPrimitiveType());
+}
+
+GLenum GetGeometryShaderOutputPrimitiveType(const ShHandle handle)
+{
+ ASSERT(handle);
+
+ TShHandleBase *base = static_cast<TShHandleBase *>(handle);
+ TCompiler *compiler = base->getAsCompiler();
+ ASSERT(compiler);
+
+ return GetGeometryShaderPrimitiveTypeEnum(compiler->getGeometryShaderOutputPrimitiveType());
}
+
+int GetGeometryShaderInvocations(const ShHandle handle)
+{
+ ASSERT(handle);
+
+ TShHandleBase *base = static_cast<TShHandleBase *>(handle);
+ TCompiler *compiler = base->getAsCompiler();
+ ASSERT(compiler);
+
+ return compiler->getGeometryShaderInvocations();
+}
+
+int GetGeometryShaderMaxVertices(const ShHandle handle)
+{
+ ASSERT(handle);
+
+ TShHandleBase *base = static_cast<TShHandleBase *>(handle);
+ TCompiler *compiler = base->getAsCompiler();
+ ASSERT(compiler);
+
+ return compiler->getGeometryShaderMaxVertices();
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp
index 8f931b9bdd..4ab574e935 100644
--- a/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp
@@ -10,6 +10,7 @@
#include <GLSLANG/ShaderLang.h>
#include "common/debug.h"
+#include "common/utilities.h"
namespace sh
{
@@ -21,7 +22,6 @@ InterpolationType GetNonAuxiliaryInterpolationType(InterpolationType interpolati
{
return (interpolation == INTERPOLATION_CENTROID ? INTERPOLATION_SMOOTH : interpolation);
}
-
}
// The ES 3.0 spec is not clear on this point, but the ES 3.1 spec, and discussion
// on Khronos.org, clarifies that a smooth/flat mismatch produces a link error,
@@ -32,55 +32,58 @@ bool InterpolationTypesMatch(InterpolationType a, InterpolationType b)
}
ShaderVariable::ShaderVariable()
- : type(0),
- precision(0),
- arraySize(0),
- staticUse(false)
-{}
+ : type(0), precision(0), flattenedOffsetInParentArrays(0), staticUse(false)
+{
+}
+
+ShaderVariable::ShaderVariable(GLenum typeIn)
+ : type(typeIn), precision(0), flattenedOffsetInParentArrays(0), staticUse(false)
+{
+}
ShaderVariable::ShaderVariable(GLenum typeIn, unsigned int arraySizeIn)
- : type(typeIn),
- precision(0),
- arraySize(arraySizeIn),
- staticUse(false)
-{}
+ : type(typeIn), precision(0), flattenedOffsetInParentArrays(0), staticUse(false)
+{
+ ASSERT(arraySizeIn != 0);
+ arraySizes.push_back(arraySizeIn);
+}
ShaderVariable::~ShaderVariable()
-{}
+{
+}
ShaderVariable::ShaderVariable(const ShaderVariable &other)
: type(other.type),
precision(other.precision),
name(other.name),
mappedName(other.mappedName),
- arraySize(other.arraySize),
+ arraySizes(other.arraySizes),
+ flattenedOffsetInParentArrays(other.flattenedOffsetInParentArrays),
staticUse(other.staticUse),
fields(other.fields),
structName(other.structName)
-{}
+{
+}
ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other)
{
- type = other.type;
- precision = other.precision;
- name = other.name;
+ type = other.type;
+ precision = other.precision;
+ name = other.name;
mappedName = other.mappedName;
- arraySize = other.arraySize;
- staticUse = other.staticUse;
- fields = other.fields;
+ arraySizes = other.arraySizes;
+ staticUse = other.staticUse;
+ flattenedOffsetInParentArrays = other.flattenedOffsetInParentArrays;
+ fields = other.fields;
structName = other.structName;
return *this;
}
bool ShaderVariable::operator==(const ShaderVariable &other) const
{
- if (type != other.type ||
- precision != other.precision ||
- name != other.name ||
- mappedName != other.mappedName ||
- arraySize != other.arraySize ||
- staticUse != other.staticUse ||
- fields.size() != other.fields.size() ||
+ if (type != other.type || precision != other.precision || name != other.name ||
+ mappedName != other.mappedName || arraySizes != other.arraySizes ||
+ staticUse != other.staticUse || fields.size() != other.fields.size() ||
structName != other.structName)
{
return false;
@@ -93,9 +96,52 @@ bool ShaderVariable::operator==(const ShaderVariable &other) const
return true;
}
-bool ShaderVariable::findInfoByMappedName(
- const std::string &mappedFullName,
- const ShaderVariable **leafVar, std::string *originalFullName) const
+void ShaderVariable::setArraySize(unsigned int size)
+{
+ arraySizes.clear();
+ if (size != 0)
+ {
+ arraySizes.push_back(size);
+ }
+}
+
+unsigned int ShaderVariable::getArraySizeProduct() const
+{
+ return gl::ArraySizeProduct(arraySizes);
+}
+
+void ShaderVariable::indexIntoArray(unsigned int arrayIndex)
+{
+ ASSERT(isArray());
+ flattenedOffsetInParentArrays =
+ arrayIndex + getOutermostArraySize() * flattenedOffsetInParentArrays;
+ arraySizes.pop_back();
+}
+
+unsigned int ShaderVariable::getNestedArraySize(unsigned int arrayNestingIndex) const
+{
+ ASSERT(arraySizes.size() > arrayNestingIndex);
+ return arraySizes[arraySizes.size() - 1u - arrayNestingIndex];
+}
+
+unsigned int ShaderVariable::getBasicTypeElementCount() const
+{
+ // GLES 3.1 Nov 2016 section 7.3.1.1 page 77 specifies that a separate entry should be generated
+ // for each array element when dealing with an array of arrays or an array of structs.
+ ASSERT(!isArrayOfArrays());
+ ASSERT(!isStruct() || !isArray());
+
+ // GLES 3.1 Nov 2016 page 82.
+ if (isArray())
+ {
+ return getOutermostArraySize();
+ }
+ return 1u;
+}
+
+bool ShaderVariable::findInfoByMappedName(const std::string &mappedFullName,
+ const ShaderVariable **leafVar,
+ std::string *originalFullName) const
{
ASSERT(leafVar && originalFullName);
// There are three cases:
@@ -110,7 +156,7 @@ bool ShaderVariable::findInfoByMappedName(
if (mappedFullName != this->mappedName)
return false;
*originalFullName = this->name;
- *leafVar = this;
+ *leafVar = this;
return true;
}
else
@@ -131,13 +177,13 @@ bool ShaderVariable::findInfoByMappedName(
if (closePos + 1 == mappedFullName.size())
{
*originalFullName = originalName;
- *leafVar = this;
+ *leafVar = this;
return true;
}
else
{
// In the form of 'a[0].b', so after ']', '.' is expected.
- if (mappedFullName[closePos + 1] != '.')
+ if (mappedFullName[closePos + 1] != '.')
return false;
remaining = mappedFullName.substr(closePos + 2); // Skip "]."
}
@@ -149,14 +195,13 @@ bool ShaderVariable::findInfoByMappedName(
}
for (size_t ii = 0; ii < this->fields.size(); ++ii)
{
- const ShaderVariable *fieldVar = NULL;
+ const ShaderVariable *fieldVar = nullptr;
std::string originalFieldName;
- bool found = fields[ii].findInfoByMappedName(
- remaining, &fieldVar, &originalFieldName);
+ bool found = fields[ii].findInfoByMappedName(remaining, &fieldVar, &originalFieldName);
if (found)
{
*originalFullName = originalName + "." + originalFieldName;
- *leafVar = fieldVar;
+ *leafVar = fieldVar;
return true;
}
}
@@ -164,24 +209,33 @@ bool ShaderVariable::findInfoByMappedName(
}
}
-bool ShaderVariable::isSameVariableAtLinkTime(
- const ShaderVariable &other, bool matchPrecision) const
+bool ShaderVariable::isBuiltIn() const
+{
+ return (name.size() >= 4 && name[0] == 'g' && name[1] == 'l' && name[2] == '_');
+}
+
+bool ShaderVariable::isSameVariableAtLinkTime(const ShaderVariable &other,
+ bool matchPrecision,
+ bool matchName) const
{
if (type != other.type)
return false;
if (matchPrecision && precision != other.precision)
return false;
- if (name != other.name)
+ if (matchName && name != other.name)
return false;
- ASSERT(mappedName == other.mappedName);
- if (arraySize != other.arraySize)
+ ASSERT(!matchName || mappedName == other.mappedName);
+ if (arraySizes != other.arraySizes)
return false;
if (fields.size() != other.fields.size())
return false;
+
+ // [OpenGL ES 3.1 SPEC Chapter 7.4.1]
+ // Variables declared as structures are considered to match in type if and only if structure
+ // members match in name, type, qualification, and declaration order.
for (size_t ii = 0; ii < fields.size(); ++ii)
{
- if (!fields[ii].isSameVariableAtLinkTime(other.fields[ii],
- matchPrecision))
+ if (!fields[ii].isSameVariableAtLinkTime(other.fields[ii], matchPrecision, true))
{
return false;
}
@@ -191,53 +245,75 @@ bool ShaderVariable::isSameVariableAtLinkTime(
return true;
}
-Uniform::Uniform()
-{}
+Uniform::Uniform() : binding(-1), offset(-1)
+{
+}
Uniform::~Uniform()
-{}
+{
+}
Uniform::Uniform(const Uniform &other)
- : ShaderVariable(other)
-{}
+ : VariableWithLocation(other), binding(other.binding), offset(other.offset)
+{
+}
Uniform &Uniform::operator=(const Uniform &other)
{
- ShaderVariable::operator=(other);
+ VariableWithLocation::operator=(other);
+ binding = other.binding;
+ offset = other.offset;
return *this;
}
bool Uniform::operator==(const Uniform &other) const
{
- return ShaderVariable::operator==(other);
+ return VariableWithLocation::operator==(other) && binding == other.binding &&
+ offset == other.offset;
}
bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const
{
- return ShaderVariable::isSameVariableAtLinkTime(other, true);
+ // Enforce a consistent match.
+ // https://cvs.khronos.org/bugzilla/show_bug.cgi?id=16261
+ if (binding != -1 && other.binding != -1 && binding != other.binding)
+ {
+ return false;
+ }
+ if (location != -1 && other.location != -1 && location != other.location)
+ {
+ return false;
+ }
+ if (offset != other.offset)
+ {
+ return false;
+ }
+ return VariableWithLocation::isSameVariableAtLinkTime(other, true, true);
}
-InterfaceVariable::InterfaceVariable() : location(-1)
-{}
+VariableWithLocation::VariableWithLocation() : location(-1)
+{
+}
-InterfaceVariable::~InterfaceVariable()
-{}
+VariableWithLocation::~VariableWithLocation()
+{
+}
-InterfaceVariable::InterfaceVariable(const InterfaceVariable &other)
+VariableWithLocation::VariableWithLocation(const VariableWithLocation &other)
: ShaderVariable(other), location(other.location)
-{}
+{
+}
-InterfaceVariable &InterfaceVariable::operator=(const InterfaceVariable &other)
+VariableWithLocation &VariableWithLocation::operator=(const VariableWithLocation &other)
{
ShaderVariable::operator=(other);
- location = other.location;
+ location = other.location;
return *this;
}
-bool InterfaceVariable::operator==(const InterfaceVariable &other) const
+bool VariableWithLocation::operator==(const VariableWithLocation &other) const
{
- return (ShaderVariable::operator==(other) &&
- location == other.location);
+ return (ShaderVariable::operator==(other) && location == other.location);
}
Attribute::Attribute()
@@ -248,19 +324,19 @@ Attribute::~Attribute()
{
}
-Attribute::Attribute(const Attribute &other) : InterfaceVariable(other)
+Attribute::Attribute(const Attribute &other) : VariableWithLocation(other)
{
}
Attribute &Attribute::operator=(const Attribute &other)
{
- InterfaceVariable::operator=(other);
+ VariableWithLocation::operator=(other);
return *this;
}
bool Attribute::operator==(const Attribute &other) const
{
- return InterfaceVariable::operator==(other);
+ return VariableWithLocation::operator==(other);
}
OutputVariable::OutputVariable()
@@ -271,79 +347,79 @@ OutputVariable::~OutputVariable()
{
}
-OutputVariable::OutputVariable(const OutputVariable &other) : InterfaceVariable(other)
+OutputVariable::OutputVariable(const OutputVariable &other) : VariableWithLocation(other)
{
}
OutputVariable &OutputVariable::operator=(const OutputVariable &other)
{
- InterfaceVariable::operator=(other);
+ VariableWithLocation::operator=(other);
return *this;
}
bool OutputVariable::operator==(const OutputVariable &other) const
{
- return InterfaceVariable::operator==(other);
+ return VariableWithLocation::operator==(other);
}
-InterfaceBlockField::InterfaceBlockField()
- : isRowMajorLayout(false)
-{}
+InterfaceBlockField::InterfaceBlockField() : isRowMajorLayout(false)
+{
+}
InterfaceBlockField::~InterfaceBlockField()
-{}
+{
+}
InterfaceBlockField::InterfaceBlockField(const InterfaceBlockField &other)
- : ShaderVariable(other),
- isRowMajorLayout(other.isRowMajorLayout)
-{}
+ : ShaderVariable(other), isRowMajorLayout(other.isRowMajorLayout)
+{
+}
InterfaceBlockField &InterfaceBlockField::operator=(const InterfaceBlockField &other)
{
ShaderVariable::operator=(other);
- isRowMajorLayout = other.isRowMajorLayout;
+ isRowMajorLayout = other.isRowMajorLayout;
return *this;
}
bool InterfaceBlockField::operator==(const InterfaceBlockField &other) const
{
- return (ShaderVariable::operator==(other) &&
- isRowMajorLayout == other.isRowMajorLayout);
+ return (ShaderVariable::operator==(other) && isRowMajorLayout == other.isRowMajorLayout);
}
bool InterfaceBlockField::isSameInterfaceBlockFieldAtLinkTime(
const InterfaceBlockField &other) const
{
- return (ShaderVariable::isSameVariableAtLinkTime(other, true) &&
+ return (ShaderVariable::isSameVariableAtLinkTime(other, true, true) &&
isRowMajorLayout == other.isRowMajorLayout);
}
-Varying::Varying()
- : interpolation(INTERPOLATION_SMOOTH),
- isInvariant(false)
-{}
+Varying::Varying() : interpolation(INTERPOLATION_SMOOTH), isInvariant(false)
+{
+}
Varying::~Varying()
-{}
+{
+}
Varying::Varying(const Varying &other)
- : ShaderVariable(other),
+ : VariableWithLocation(other),
interpolation(other.interpolation),
isInvariant(other.isInvariant)
-{}
+{
+}
Varying &Varying::operator=(const Varying &other)
{
- ShaderVariable::operator=(other);
- interpolation = other.interpolation;
- isInvariant = other.isInvariant;
+ VariableWithLocation::operator=(other);
+ interpolation = other.interpolation;
+ isInvariant = other.isInvariant;
return *this;
}
bool Varying::operator==(const Varying &other) const
{
- return (ShaderVariable::operator==(other) &&
- interpolation == other.interpolation &&
+ return (VariableWithLocation::operator==(other) && interpolation == other.interpolation &&
isInvariant == other.isInvariant);
}
@@ -354,20 +430,26 @@ bool Varying::isSameVaryingAtLinkTime(const Varying &other) const
bool Varying::isSameVaryingAtLinkTime(const Varying &other, int shaderVersion) const
{
- return (ShaderVariable::isSameVariableAtLinkTime(other, false) &&
- interpolation == other.interpolation &&
- (shaderVersion >= 300 || isInvariant == other.isInvariant));
+ return (ShaderVariable::isSameVariableAtLinkTime(other, false, false) &&
+ InterpolationTypesMatch(interpolation, other.interpolation) &&
+ (shaderVersion >= 300 || isInvariant == other.isInvariant) &&
+ (location == other.location) &&
+ (name == other.name || (shaderVersion >= 310 && location >= 0)));
}
InterfaceBlock::InterfaceBlock()
: arraySize(0),
layout(BLOCKLAYOUT_PACKED),
isRowMajorLayout(false),
- staticUse(false)
-{}
+ binding(-1),
+ staticUse(false),
+ blockType(BlockType::BLOCK_UNIFORM)
+{
+}
InterfaceBlock::~InterfaceBlock()
-{}
+{
+}
InterfaceBlock::InterfaceBlock(const InterfaceBlock &other)
: name(other.name),
@@ -376,20 +458,25 @@ InterfaceBlock::InterfaceBlock(const InterfaceBlock &other)
arraySize(other.arraySize),
layout(other.layout),
isRowMajorLayout(other.isRowMajorLayout),
+ binding(other.binding),
staticUse(other.staticUse),
+ blockType(other.blockType),
fields(other.fields)
-{}
+{
+}
InterfaceBlock &InterfaceBlock::operator=(const InterfaceBlock &other)
{
- name = other.name;
- mappedName = other.mappedName;
- instanceName = other.instanceName;
- arraySize = other.arraySize;
- layout = other.layout;
+ name = other.name;
+ mappedName = other.mappedName;
+ instanceName = other.instanceName;
+ arraySize = other.arraySize;
+ layout = other.layout;
isRowMajorLayout = other.isRowMajorLayout;
- staticUse = other.staticUse;
- fields = other.fields;
+ binding = other.binding;
+ staticUse = other.staticUse;
+ blockType = other.blockType;
+ fields = other.fields;
return *this;
}
@@ -398,4 +485,102 @@ std::string InterfaceBlock::fieldPrefix() const
return instanceName.empty() ? "" : name;
}
+std::string InterfaceBlock::fieldMappedPrefix() const
+{
+ return instanceName.empty() ? "" : mappedName;
+}
+
+bool InterfaceBlock::isSameInterfaceBlockAtLinkTime(const InterfaceBlock &other) const
+{
+ if (name != other.name || mappedName != other.mappedName || arraySize != other.arraySize ||
+ layout != other.layout || isRowMajorLayout != other.isRowMajorLayout ||
+ binding != other.binding || blockType != other.blockType ||
+ fields.size() != other.fields.size())
+ {
+ return false;
+ }
+
+ for (size_t fieldIndex = 0; fieldIndex < fields.size(); ++fieldIndex)
+ {
+ if (!fields[fieldIndex].isSameInterfaceBlockFieldAtLinkTime(other.fields[fieldIndex]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool InterfaceBlock::isBuiltIn() const
+{
+ return (name.size() >= 4 && name[0] == 'g' && name[1] == 'l' && name[2] == '_');
+}
+
+void WorkGroupSize::fill(int fillValue)
+{
+ localSizeQualifiers[0] = fillValue;
+ localSizeQualifiers[1] = fillValue;
+ localSizeQualifiers[2] = fillValue;
+}
+
+void WorkGroupSize::setLocalSize(int localSizeX, int localSizeY, int localSizeZ)
+{
+ localSizeQualifiers[0] = localSizeX;
+ localSizeQualifiers[1] = localSizeY;
+ localSizeQualifiers[2] = localSizeZ;
+}
+
+// check that if one of them is less than 1, then all of them are.
+// Or if one is positive, then all of them are positive.
+bool WorkGroupSize::isLocalSizeValid() const
+{
+ return (
+ (localSizeQualifiers[0] < 1 && localSizeQualifiers[1] < 1 && localSizeQualifiers[2] < 1) ||
+ (localSizeQualifiers[0] > 0 && localSizeQualifiers[1] > 0 && localSizeQualifiers[2] > 0));
+}
+
+bool WorkGroupSize::isAnyValueSet() const
+{
+ return localSizeQualifiers[0] > 0 || localSizeQualifiers[1] > 0 || localSizeQualifiers[2] > 0;
+}
+
+bool WorkGroupSize::isDeclared() const
+{
+ bool localSizeDeclared = localSizeQualifiers[0] > 0;
+ ASSERT(isLocalSizeValid());
+ return localSizeDeclared;
+}
+
+bool WorkGroupSize::isWorkGroupSizeMatching(const WorkGroupSize &right) const
+{
+ for (size_t i = 0u; i < size(); ++i)
+ {
+ bool result = (localSizeQualifiers[i] == right.localSizeQualifiers[i] ||
+ (localSizeQualifiers[i] == 1 && right.localSizeQualifiers[i] == -1) ||
+ (localSizeQualifiers[i] == -1 && right.localSizeQualifiers[i] == 1));
+ if (!result)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+int &WorkGroupSize::operator[](size_t index)
+{
+ ASSERT(index < size());
+ return localSizeQualifiers[index];
+}
+
+int WorkGroupSize::operator[](size_t index) const
+{
+ ASSERT(index < size());
+ return localSizeQualifiers[index];
+}
+
+size_t WorkGroupSize::size() const
+{
+ return 3u;
+}
+
} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.cpp b/src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.cpp
deleted file mode 100644
index ac5eb67070..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-//
-// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/translator/SimplifyArrayAssignment.h"
-
-bool SimplifyArrayAssignment::visitBinary(Visit visit, TIntermBinary *node)
-{
- switch (node->getOp())
- {
- case EOpAssign:
- {
- TIntermNode *parent = getParentNode();
- if (node->getLeft()->isArray() && parent != nullptr)
- {
- TIntermAggregate *parentAgg = parent->getAsAggregate();
- if (parentAgg != nullptr && parentAgg->getOp() == EOpSequence)
- {
- // This case is fine, the result of the assignment is not used.
- break;
- }
-
- // The result of the assignment needs to be stored into a temporary variable,
- // the assignment needs to be replaced with a reference to the temporary variable,
- // and the temporary variable needs to finally be assigned to the target variable.
-
- // This also needs to interact correctly with unfolding short circuiting operators.
- UNIMPLEMENTED();
- }
- }
- break;
- default:
- break;
- }
- return true;
-}
diff --git a/src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.h b/src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.h
deleted file mode 100644
index 247eb88d72..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.h
+++ /dev/null
@@ -1,25 +0,0 @@
-//
-// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// SimplifyArrayAssignment is an AST traverser to replace statements where
-// the return value of array assignment is used with statements where
-// the return value of array assignment is not used.
-//
-
-#ifndef COMPILER_TRANSLATOR_SIMPLIFYARRAYASSIGNMENT_H_
-#define COMPILER_TRANSLATOR_SIMPLIFYARRAYASSIGNMENT_H_
-
-#include "common/angleutils.h"
-#include "compiler/translator/IntermNode.h"
-
-class SimplifyArrayAssignment : public TIntermTraverser
-{
- public:
- SimplifyArrayAssignment() { }
-
- virtual bool visitBinary(Visit visit, TIntermBinary *node);
-};
-
-#endif // COMPILER_TRANSLATOR_SIMPLIFYARRAYASSIGNMENT_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.cpp b/src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.cpp
new file mode 100644
index 0000000000..9704046839
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.cpp
@@ -0,0 +1,300 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// SimplifyLoopConditions is an AST traverser that converts loop conditions and loop expressions
+// to regular statements inside the loop. This way further transformations that generate statements
+// from loop conditions and loop expressions work correctly.
+//
+
+#include "compiler/translator/SimplifyLoopConditions.h"
+
+#include "compiler/translator/IntermNodePatternMatcher.h"
+#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class SimplifyLoopConditionsTraverser : public TLValueTrackingTraverser
+{
+ public:
+ SimplifyLoopConditionsTraverser(unsigned int conditionsToSimplifyMask,
+ TSymbolTable *symbolTable,
+ int shaderVersion);
+
+ void traverseLoop(TIntermLoop *node) override;
+
+ bool visitUnary(Visit visit, TIntermUnary *node) override;
+ bool visitBinary(Visit visit, TIntermBinary *node) override;
+ bool visitAggregate(Visit visit, TIntermAggregate *node) override;
+ bool visitTernary(Visit visit, TIntermTernary *node) override;
+ bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
+
+ bool foundLoopToChange() const { return mFoundLoopToChange; }
+
+ protected:
+ // Marked to true once an operation that needs to be hoisted out of a loop expression has been
+ // found.
+ bool mFoundLoopToChange;
+ bool mInsideLoopInitConditionOrExpression;
+ IntermNodePatternMatcher mConditionsToSimplify;
+};
+
+SimplifyLoopConditionsTraverser::SimplifyLoopConditionsTraverser(
+ unsigned int conditionsToSimplifyMask,
+ TSymbolTable *symbolTable,
+ int shaderVersion)
+ : TLValueTrackingTraverser(true, false, false, symbolTable, shaderVersion),
+ mFoundLoopToChange(false),
+ mInsideLoopInitConditionOrExpression(false),
+ mConditionsToSimplify(conditionsToSimplifyMask)
+{
+}
+
+// If we're inside a loop initialization, condition, or expression, we check for expressions that
+// should be moved out of the loop condition or expression. If one is found, the loop is
+// transformed.
+// If we're not inside loop initialization, condition, or expression, we only need to traverse nodes
+// that may contain loops.
+
+bool SimplifyLoopConditionsTraverser::visitUnary(Visit visit, TIntermUnary *node)
+{
+ if (!mInsideLoopInitConditionOrExpression)
+ return false;
+
+ if (mFoundLoopToChange)
+ return false; // Already decided to change this loop.
+
+ mFoundLoopToChange = mConditionsToSimplify.match(node);
+ return !mFoundLoopToChange;
+}
+
+bool SimplifyLoopConditionsTraverser::visitBinary(Visit visit, TIntermBinary *node)
+{
+ if (!mInsideLoopInitConditionOrExpression)
+ return false;
+
+ if (mFoundLoopToChange)
+ return false; // Already decided to change this loop.
+
+ mFoundLoopToChange = mConditionsToSimplify.match(node, getParentNode(), isLValueRequiredHere());
+ return !mFoundLoopToChange;
+}
+
+bool SimplifyLoopConditionsTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+ if (!mInsideLoopInitConditionOrExpression)
+ return false;
+
+ if (mFoundLoopToChange)
+ return false; // Already decided to change this loop.
+
+ mFoundLoopToChange = mConditionsToSimplify.match(node, getParentNode());
+ return !mFoundLoopToChange;
+}
+
+bool SimplifyLoopConditionsTraverser::visitTernary(Visit visit, TIntermTernary *node)
+{
+ if (!mInsideLoopInitConditionOrExpression)
+ return false;
+
+ if (mFoundLoopToChange)
+ return false; // Already decided to change this loop.
+
+ mFoundLoopToChange = mConditionsToSimplify.match(node);
+ return !mFoundLoopToChange;
+}
+
+bool SimplifyLoopConditionsTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node)
+{
+ if (!mInsideLoopInitConditionOrExpression)
+ return false;
+
+ if (mFoundLoopToChange)
+ return false; // Already decided to change this loop.
+
+ mFoundLoopToChange = mConditionsToSimplify.match(node);
+ return !mFoundLoopToChange;
+}
+
+void SimplifyLoopConditionsTraverser::traverseLoop(TIntermLoop *node)
+{
+ // Mark that we're inside a loop condition or expression, and determine if the loop needs to be
+ // transformed.
+
+ ScopedNodeInTraversalPath addToPath(this, node);
+
+ mInsideLoopInitConditionOrExpression = true;
+ mFoundLoopToChange = false;
+
+ if (!mFoundLoopToChange && node->getInit())
+ {
+ node->getInit()->traverse(this);
+ }
+
+ if (!mFoundLoopToChange && node->getCondition())
+ {
+ node->getCondition()->traverse(this);
+ }
+
+ if (!mFoundLoopToChange && node->getExpression())
+ {
+ node->getExpression()->traverse(this);
+ }
+
+ mInsideLoopInitConditionOrExpression = false;
+
+ if (mFoundLoopToChange)
+ {
+ nextTemporaryId();
+
+ // Replace the loop condition with a boolean variable that's updated on each iteration.
+ TLoopType loopType = node->getType();
+ if (loopType == ELoopWhile)
+ {
+ // Transform:
+ // while (expr) { body; }
+ // into
+ // bool s0 = expr;
+ // while (s0) { { body; } s0 = expr; }
+ TIntermSequence tempInitSeq;
+ tempInitSeq.push_back(createTempInitDeclaration(node->getCondition()->deepCopy()));
+ insertStatementsInParentBlock(tempInitSeq);
+
+ TIntermBlock *newBody = new TIntermBlock();
+ if (node->getBody())
+ {
+ newBody->getSequence()->push_back(node->getBody());
+ }
+ newBody->getSequence()->push_back(
+ createTempAssignment(node->getCondition()->deepCopy()));
+
+ // Can't use queueReplacement to replace old body, since it may have been nullptr.
+ // It's safe to do the replacements in place here - the new body will still be
+ // traversed, but that won't create any problems.
+ node->setBody(newBody);
+ node->setCondition(createTempSymbol(node->getCondition()->getType()));
+ }
+ else if (loopType == ELoopDoWhile)
+ {
+ // Transform:
+ // do {
+ // body;
+ // } while (expr);
+ // into
+ // bool s0 = true;
+ // do {
+ // { body; }
+ // s0 = expr;
+ // } while (s0);
+ TIntermSequence tempInitSeq;
+ tempInitSeq.push_back(createTempInitDeclaration(CreateBoolNode(true)));
+ insertStatementsInParentBlock(tempInitSeq);
+
+ TIntermBlock *newBody = new TIntermBlock();
+ if (node->getBody())
+ {
+ newBody->getSequence()->push_back(node->getBody());
+ }
+ newBody->getSequence()->push_back(
+ createTempAssignment(node->getCondition()->deepCopy()));
+
+ // Can't use queueReplacement to replace old body, since it may have been nullptr.
+ // It's safe to do the replacements in place here - the new body will still be
+ // traversed, but that won't create any problems.
+ node->setBody(newBody);
+ node->setCondition(createTempSymbol(node->getCondition()->getType()));
+ }
+ else if (loopType == ELoopFor)
+ {
+ // Move the loop condition inside the loop.
+ // Transform:
+ // for (init; expr; exprB) { body; }
+ // into
+ // {
+ // init;
+ // bool s0 = expr;
+ // while (s0) {
+ // { body; }
+ // exprB;
+ // s0 = expr;
+ // }
+ // }
+ TIntermBlock *loopScope = new TIntermBlock();
+ TIntermSequence *loopScopeSequence = loopScope->getSequence();
+
+ // Insert "init;"
+ if (node->getInit())
+ {
+ loopScopeSequence->push_back(node->getInit());
+ }
+
+ // Insert "bool s0 = expr;" if applicable, "bool s0 = true;" otherwise
+ TIntermTyped *conditionInitializer = nullptr;
+ if (node->getCondition())
+ {
+ conditionInitializer = node->getCondition()->deepCopy();
+ }
+ else
+ {
+ conditionInitializer = CreateBoolNode(true);
+ }
+ loopScopeSequence->push_back(createTempInitDeclaration(conditionInitializer));
+
+ // Insert "{ body; }" in the while loop
+ TIntermBlock *whileLoopBody = new TIntermBlock();
+ if (node->getBody())
+ {
+ whileLoopBody->getSequence()->push_back(node->getBody());
+ }
+ // Insert "exprB;" in the while loop
+ if (node->getExpression())
+ {
+ whileLoopBody->getSequence()->push_back(node->getExpression());
+ }
+ // Insert "s0 = expr;" in the while loop
+ if (node->getCondition())
+ {
+ whileLoopBody->getSequence()->push_back(
+ createTempAssignment(node->getCondition()->deepCopy()));
+ }
+
+ // Create "while(s0) { whileLoopBody }"
+ TIntermLoop *whileLoop = new TIntermLoop(
+ ELoopWhile, nullptr, createTempSymbol(conditionInitializer->getType()), nullptr,
+ whileLoopBody);
+ loopScope->getSequence()->push_back(whileLoop);
+ queueReplacement(loopScope, OriginalNode::IS_DROPPED);
+
+ // After this the old body node will be traversed and loops inside it may be
+ // transformed. This is fine, since the old body node will still be in the AST after the
+ // transformation that's queued here, and transforming loops inside it doesn't need to
+ // know the exact post-transform path to it.
+ }
+ }
+
+ mFoundLoopToChange = false;
+
+ // We traverse the body of the loop even if the loop is transformed.
+ if (node->getBody())
+ node->getBody()->traverse(this);
+}
+
+} // namespace
+
+void SimplifyLoopConditions(TIntermNode *root,
+ unsigned int conditionsToSimplifyMask,
+ TSymbolTable *symbolTable,
+ int shaderVersion)
+{
+ SimplifyLoopConditionsTraverser traverser(conditionsToSimplifyMask, symbolTable, shaderVersion);
+ root->traverse(&traverser);
+ traverser.updateTree();
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.h b/src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.h
new file mode 100644
index 0000000000..d8f95cd2c8
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/SimplifyLoopConditions.h
@@ -0,0 +1,25 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// SimplifyLoopConditions is an AST traverser that converts loop conditions and loop expressions
+// to regular statements inside the loop. This way further transformations that generate statements
+// from loop conditions and loop expressions work correctly.
+//
+
+#ifndef COMPILER_TRANSLATOR_SIMPLIFYLOOPCONDITIONS_H_
+#define COMPILER_TRANSLATOR_SIMPLIFYLOOPCONDITIONS_H_
+
+namespace sh
+{
+class TIntermNode;
+class TSymbolTable;
+
+void SimplifyLoopConditions(TIntermNode *root,
+ unsigned int conditionsToSimplify,
+ TSymbolTable *symbolTable,
+ int shaderVersion);
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_SIMPLIFYLOOPCONDITIONS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.cpp b/src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.cpp
new file mode 100644
index 0000000000..5df3154560
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.cpp
@@ -0,0 +1,171 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// SplitSequenceOperator is an AST traverser that detects sequence operator expressions that
+// go through further AST transformations that generate statements, and splits them so that
+// possible side effects of earlier parts of the sequence operator expression are guaranteed to be
+// evaluated before the latter parts of the sequence operator expression are evaluated.
+//
+
+#include "compiler/translator/SplitSequenceOperator.h"
+
+#include "compiler/translator/IntermNodePatternMatcher.h"
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class SplitSequenceOperatorTraverser : public TLValueTrackingTraverser
+{
+ public:
+ SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask,
+ TSymbolTable *symbolTable,
+ int shaderVersion);
+
+ bool visitUnary(Visit visit, TIntermUnary *node) override;
+ bool visitBinary(Visit visit, TIntermBinary *node) override;
+ bool visitAggregate(Visit visit, TIntermAggregate *node) override;
+ bool visitTernary(Visit visit, TIntermTernary *node) override;
+
+ void nextIteration();
+ bool foundExpressionToSplit() const { return mFoundExpressionToSplit; }
+
+ protected:
+ // Marked to true once an operation that needs to be hoisted out of the expression has been
+ // found. After that, no more AST updates are performed on that traversal.
+ bool mFoundExpressionToSplit;
+ int mInsideSequenceOperator;
+
+ IntermNodePatternMatcher mPatternToSplitMatcher;
+};
+
+SplitSequenceOperatorTraverser::SplitSequenceOperatorTraverser(unsigned int patternsToSplitMask,
+ TSymbolTable *symbolTable,
+ int shaderVersion)
+ : TLValueTrackingTraverser(true, false, true, symbolTable, shaderVersion),
+ mFoundExpressionToSplit(false),
+ mInsideSequenceOperator(0),
+ mPatternToSplitMatcher(patternsToSplitMask)
+{
+}
+
+void SplitSequenceOperatorTraverser::nextIteration()
+{
+ mFoundExpressionToSplit = false;
+ mInsideSequenceOperator = 0;
+ nextTemporaryId();
+}
+
+bool SplitSequenceOperatorTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+ if (mFoundExpressionToSplit)
+ return false;
+
+ if (mInsideSequenceOperator > 0 && visit == PreVisit)
+ {
+ // Detect expressions that need to be simplified
+ mFoundExpressionToSplit = mPatternToSplitMatcher.match(node, getParentNode());
+ return !mFoundExpressionToSplit;
+ }
+
+ return true;
+}
+
+bool SplitSequenceOperatorTraverser::visitUnary(Visit visit, TIntermUnary *node)
+{
+ if (mFoundExpressionToSplit)
+ return false;
+
+ if (mInsideSequenceOperator > 0 && visit == PreVisit)
+ {
+ // Detect expressions that need to be simplified
+ mFoundExpressionToSplit = mPatternToSplitMatcher.match(node);
+ return !mFoundExpressionToSplit;
+ }
+
+ return true;
+}
+
+bool SplitSequenceOperatorTraverser::visitBinary(Visit visit, TIntermBinary *node)
+{
+ if (node->getOp() == EOpComma)
+ {
+ if (visit == PreVisit)
+ {
+ if (mFoundExpressionToSplit)
+ {
+ return false;
+ }
+ mInsideSequenceOperator++;
+ }
+ else if (visit == PostVisit)
+ {
+ // Split sequence operators starting from the outermost one to preserve correct
+ // execution order.
+ if (mFoundExpressionToSplit && mInsideSequenceOperator == 1)
+ {
+ // Move the left side operand into a separate statement in the parent block.
+ TIntermSequence insertions;
+ insertions.push_back(node->getLeft());
+ insertStatementsInParentBlock(insertions);
+ // Replace the comma node with its right side operand.
+ queueReplacement(node->getRight(), OriginalNode::IS_DROPPED);
+ }
+ mInsideSequenceOperator--;
+ }
+ return true;
+ }
+
+ if (mFoundExpressionToSplit)
+ return false;
+
+ if (mInsideSequenceOperator > 0 && visit == PreVisit)
+ {
+ // Detect expressions that need to be simplified
+ mFoundExpressionToSplit =
+ mPatternToSplitMatcher.match(node, getParentNode(), isLValueRequiredHere());
+ return !mFoundExpressionToSplit;
+ }
+
+ return true;
+}
+
+bool SplitSequenceOperatorTraverser::visitTernary(Visit visit, TIntermTernary *node)
+{
+ if (mFoundExpressionToSplit)
+ return false;
+
+ if (mInsideSequenceOperator > 0 && visit == PreVisit)
+ {
+ // Detect expressions that need to be simplified
+ mFoundExpressionToSplit = mPatternToSplitMatcher.match(node);
+ return !mFoundExpressionToSplit;
+ }
+
+ return true;
+}
+
+} // namespace
+
+void SplitSequenceOperator(TIntermNode *root,
+ int patternsToSplitMask,
+ TSymbolTable *symbolTable,
+ int shaderVersion)
+{
+ SplitSequenceOperatorTraverser traverser(patternsToSplitMask, symbolTable, shaderVersion);
+ // Separate one expression at a time, and reset the traverser between iterations.
+ do
+ {
+ traverser.nextIteration();
+ root->traverse(&traverser);
+ if (traverser.foundExpressionToSplit())
+ traverser.updateTree();
+ } while (traverser.foundExpressionToSplit());
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.h b/src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.h
new file mode 100644
index 0000000000..8f1a766775
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/SplitSequenceOperator.h
@@ -0,0 +1,28 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// SplitSequenceOperator is an AST traverser that detects sequence operator expressions that
+// go through further AST transformations that generate statements, and splits them so that
+// possible side effects of earlier parts of the sequence operator expression are guaranteed to be
+// evaluated before the latter parts of the sequence operator expression are evaluated.
+//
+
+#ifndef COMPILER_TRANSLATOR_SPLITSEQUENCEOPERATOR_H_
+#define COMPILER_TRANSLATOR_SPLITSEQUENCEOPERATOR_H_
+
+namespace sh
+{
+
+class TIntermNode;
+class TSymbolTable;
+
+void SplitSequenceOperator(TIntermNode *root,
+ int patternsToSplitMask,
+ TSymbolTable *symbolTable,
+ int shaderVersion);
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_SPLITSEQUENCEOPERATOR_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp
index fd1a29c1cd..61a9431ceb 100644
--- a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp
@@ -4,7 +4,7 @@
// found in the LICENSE file.
//
// StructureHLSL.cpp:
-// Definitions of methods for HLSL translation of GLSL structures.
+// HLSL translation of GLSL constructors and structures.
//
#include "compiler/translator/StructureHLSL.h"
@@ -17,23 +17,94 @@
namespace sh
{
+namespace
+{
+
+TString Define(const TStructure &structure,
+ bool useHLSLRowMajorPacking,
+ bool useStd140Packing,
+ Std140PaddingHelper *padHelper)
+{
+ const TFieldList &fields = structure.fields();
+ const bool isNameless = (structure.name() == "");
+ const TString &structName =
+ QualifiedStructNameString(structure, useHLSLRowMajorPacking, useStd140Packing);
+ const TString declareString = (isNameless ? "struct" : "struct " + structName);
+
+ TString string;
+ string += declareString +
+ "\n"
+ "{\n";
+
+ for (const TField *field : fields)
+ {
+ const TType &fieldType = *field->type();
+ if (!IsSampler(fieldType.getBasicType()))
+ {
+ const TStructure *fieldStruct = fieldType.getStruct();
+ const TString &fieldTypeString =
+ fieldStruct ? QualifiedStructNameString(*fieldStruct, useHLSLRowMajorPacking,
+ useStd140Packing)
+ : TypeString(fieldType);
+
+ if (padHelper)
+ {
+ string += padHelper->prePaddingString(fieldType);
+ }
+
+ string += " " + fieldTypeString + " " + DecorateField(field->name(), structure) +
+ ArrayString(fieldType) + ";\n";
+
+ if (padHelper)
+ {
+ string += padHelper->postPaddingString(fieldType, useHLSLRowMajorPacking);
+ }
+ }
+ }
+
+ // Nameless structs do not finish with a semicolon and newline, to leave room for an instance
+ // variable
+ string += (isNameless ? "} " : "};\n");
+
+ return string;
+}
+
+TString WriteParameterList(const std::vector<TType> &parameters)
+{
+ TString parameterList;
+ for (size_t parameter = 0u; parameter < parameters.size(); parameter++)
+ {
+ const TType &paramType = parameters[parameter];
+
+ parameterList += TypeString(paramType) + " x" + str(parameter) + ArrayString(paramType);
+
+ if (parameter < parameters.size() - 1u)
+ {
+ parameterList += ", ";
+ }
+ }
+ return parameterList;
+}
+
+} // anonymous namespace
+
Std140PaddingHelper::Std140PaddingHelper(const std::map<TString, int> &structElementIndexes,
unsigned *uniqueCounter)
- : mPaddingCounter(uniqueCounter),
- mElementIndex(0),
- mStructElementIndexes(&structElementIndexes)
-{}
+ : mPaddingCounter(uniqueCounter), mElementIndex(0), mStructElementIndexes(&structElementIndexes)
+{
+}
Std140PaddingHelper::Std140PaddingHelper(const Std140PaddingHelper &other)
: mPaddingCounter(other.mPaddingCounter),
mElementIndex(other.mElementIndex),
mStructElementIndexes(other.mStructElementIndexes)
-{}
+{
+}
Std140PaddingHelper &Std140PaddingHelper::operator=(const Std140PaddingHelper &other)
{
- mPaddingCounter = other.mPaddingCounter;
- mElementIndex = other.mElementIndex;
+ mPaddingCounter = other.mPaddingCounter;
+ mElementIndex = other.mElementIndex;
mStructElementIndexes = other.mStructElementIndexes;
return *this;
}
@@ -53,7 +124,7 @@ int Std140PaddingHelper::prePadding(const TType &type)
return 0;
}
- const GLenum glType = GLVariableType(type);
+ const GLenum glType = GLVariableType(type);
const int numComponents = gl::VariableComponentCount(glType);
if (numComponents >= 4)
@@ -70,9 +141,9 @@ int Std140PaddingHelper::prePadding(const TType &type)
return 0;
}
- const int alignment = numComponents == 3 ? 4 : numComponents;
+ const int alignment = numComponents == 3 ? 4 : numComponents;
const int paddingOffset = (mElementIndex % alignment);
- const int paddingCount = (paddingOffset != 0 ? (alignment - paddingOffset) : 0);
+ const int paddingCount = (paddingOffset != 0 ? (alignment - paddingOffset) : 0);
mElementIndex += paddingCount;
mElementIndex += numComponents;
@@ -102,25 +173,26 @@ TString Std140PaddingHelper::postPaddingString(const TType &type, bool useHLSLRo
return "";
}
- int numComponents = 0;
- TStructure *structure = type.getStruct();
+ int numComponents = 0;
+ const TStructure *structure = type.getStruct();
if (type.isMatrix())
{
- // This method can also be called from structureString, which does not use layout qualifiers.
+ // This method can also be called from structureString, which does not use layout
+ // qualifiers.
// Thus, use the method parameter for determining the matrix packing.
//
// Note HLSL row major packing corresponds to GL API column-major, and vice-versa, since we
// wish to always transpose GL matrices to play well with HLSL's matrix array indexing.
//
const bool isRowMajorMatrix = !useHLSLRowMajorPacking;
- const GLenum glType = GLVariableType(type);
- numComponents = gl::MatrixComponentCount(glType, isRowMajorMatrix);
+ const GLenum glType = GLVariableType(type);
+ numComponents = gl::MatrixComponentCount(glType, isRowMajorMatrix);
}
else if (structure)
{
- const TString &structName = QualifiedStructNameString(*structure,
- useHLSLRowMajorPacking, true);
+ const TString &structName =
+ QualifiedStructNameString(*structure, useHLSLRowMajorPacking, true);
numComponents = mStructElementIndexes->find(structName)->second;
if (numComponents == 0)
@@ -131,7 +203,7 @@ TString Std140PaddingHelper::postPaddingString(const TType &type, bool useHLSLRo
else
{
const GLenum glType = GLVariableType(type);
- numComponents = gl::VariableComponentCount(glType);
+ numComponents = gl::VariableComponentCount(glType);
}
TString padding;
@@ -142,178 +214,183 @@ TString Std140PaddingHelper::postPaddingString(const TType &type, bool useHLSLRo
return padding;
}
-StructureHLSL::StructureHLSL()
- : mUniquePaddingCounter(0)
-{}
+StructureHLSL::StructureHLSL() : mUniquePaddingCounter(0)
+{
+}
Std140PaddingHelper StructureHLSL::getPaddingHelper()
{
return Std140PaddingHelper(mStd140StructElementIndexes, &mUniquePaddingCounter);
}
-TString StructureHLSL::defineQualified(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing)
+TString StructureHLSL::defineQualified(const TStructure &structure,
+ bool useHLSLRowMajorPacking,
+ bool useStd140Packing)
{
if (useStd140Packing)
{
Std140PaddingHelper padHelper = getPaddingHelper();
- return define(structure, useHLSLRowMajorPacking, useStd140Packing, &padHelper);
+ return Define(structure, useHLSLRowMajorPacking, useStd140Packing, &padHelper);
}
else
{
- return define(structure, useHLSLRowMajorPacking, useStd140Packing, NULL);
+ return Define(structure, useHLSLRowMajorPacking, useStd140Packing, nullptr);
}
}
TString StructureHLSL::defineNameless(const TStructure &structure)
{
- return define(structure, false, false, NULL);
+ return Define(structure, false, false, nullptr);
}
-TString StructureHLSL::define(const TStructure &structure, bool useHLSLRowMajorPacking,
- bool useStd140Packing, Std140PaddingHelper *padHelper)
+StructureHLSL::DefinedStructs::iterator StructureHLSL::defineVariants(const TStructure &structure,
+ const TString &name)
{
- const TFieldList &fields = structure.fields();
- const bool isNameless = (structure.name() == "");
- const TString &structName = QualifiedStructNameString(structure, useHLSLRowMajorPacking,
- useStd140Packing);
- const TString declareString = (isNameless ? "struct" : "struct " + structName);
+ ASSERT(mDefinedStructs.find(name) == mDefinedStructs.end());
- TString string;
- string += declareString + "\n"
- "{\n";
-
- for (unsigned int i = 0; i < fields.size(); i++)
+ for (const TField *field : structure.fields())
{
- const TField &field = *fields[i];
- const TType &fieldType = *field.type();
- const TStructure *fieldStruct = fieldType.getStruct();
- const TString &fieldTypeString = fieldStruct ?
- QualifiedStructNameString(*fieldStruct, useHLSLRowMajorPacking,
- useStd140Packing) :
- TypeString(fieldType);
-
- if (padHelper)
+ const TType *fieldType = field->type();
+ if (fieldType->getBasicType() == EbtStruct)
{
- string += padHelper->prePaddingString(fieldType);
- }
-
- string += " " + fieldTypeString + " " + DecorateField(field.name(), structure) + ArrayString(fieldType) + ";\n";
-
- if (padHelper)
- {
- string += padHelper->postPaddingString(fieldType, useHLSLRowMajorPacking);
+ ensureStructDefined(*fieldType->getStruct());
}
}
- // Nameless structs do not finish with a semicolon and newline, to leave room for an instance variable
- string += (isNameless ? "} " : "};\n");
-
- return string;
+ DefinedStructs::iterator addedStruct =
+ mDefinedStructs.insert(std::make_pair(name, new TStructProperties())).first;
+ // Add element index
+ storeStd140ElementIndex(structure, false);
+ storeStd140ElementIndex(structure, true);
+
+ const TString &structString = defineQualified(structure, false, false);
+
+ ASSERT(std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structString) ==
+ mStructDeclarations.end());
+ // Add row-major packed struct for interface blocks
+ TString rowMajorString = "#pragma pack_matrix(row_major)\n" +
+ defineQualified(structure, true, false) +
+ "#pragma pack_matrix(column_major)\n";
+
+ TString std140String = defineQualified(structure, false, true);
+ TString std140RowMajorString = "#pragma pack_matrix(row_major)\n" +
+ defineQualified(structure, true, true) +
+ "#pragma pack_matrix(column_major)\n";
+
+ mStructDeclarations.push_back(structString);
+ mStructDeclarations.push_back(rowMajorString);
+ mStructDeclarations.push_back(std140String);
+ mStructDeclarations.push_back(std140RowMajorString);
+ return addedStruct;
}
-void StructureHLSL::addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters)
+void StructureHLSL::ensureStructDefined(const TStructure &structure)
{
+ const TString name = StructNameString(structure);
if (name == "")
{
- return; // Nameless structures don't have constructors
+ return; // Nameless structures are not defined
}
-
- if (type.getStruct() && mStructNames.find(name) != mStructNames.end())
+ if (mDefinedStructs.find(name) == mDefinedStructs.end())
{
- return; // Already added
+ defineVariants(structure, name);
}
+}
- TType ctorType = type;
- ctorType.clearArrayness();
- ctorType.setPrecision(EbpHigh);
- ctorType.setQualifier(EvqTemporary);
-
- typedef std::vector<TType> ParameterArray;
- ParameterArray ctorParameters;
-
- const TStructure* structure = type.getStruct();
- if (structure)
- {
- mStructNames.insert(name);
-
- // Add element index
- storeStd140ElementIndex(*structure, false);
- storeStd140ElementIndex(*structure, true);
-
- const TString &structString = defineQualified(*structure, false, false);
-
- if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structString) == mStructDeclarations.end())
- {
- // Add row-major packed struct for interface blocks
- TString rowMajorString = "#pragma pack_matrix(row_major)\n" +
- defineQualified(*structure, true, false) +
- "#pragma pack_matrix(column_major)\n";
-
- TString std140String = defineQualified(*structure, false, true);
- TString std140RowMajorString = "#pragma pack_matrix(row_major)\n" +
- defineQualified(*structure, true, true) +
- "#pragma pack_matrix(column_major)\n";
-
- mStructDeclarations.push_back(structString);
- mStructDeclarations.push_back(rowMajorString);
- mStructDeclarations.push_back(std140String);
- mStructDeclarations.push_back(std140RowMajorString);
- }
+TString StructureHLSL::addStructConstructor(const TStructure &structure)
+{
+ const TString name = StructNameString(structure);
- const TFieldList &fields = structure->fields();
- for (unsigned int i = 0; i < fields.size(); i++)
- {
- ctorParameters.push_back(*fields[i]->type());
- }
- }
- else if (parameters)
+ if (name == "")
{
- for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++)
- {
- ctorParameters.push_back((*parameter)->getAsTyped()->getType());
- }
+ return TString(); // Nameless structures don't have constructors
}
- else UNREACHABLE();
-
- TString constructor;
- if (ctorType.getStruct())
+ auto definedStruct = mDefinedStructs.find(name);
+ if (definedStruct == mDefinedStructs.end())
{
- constructor += name + " " + name + "_ctor(";
+ definedStruct = defineVariants(structure, name);
}
- else // Built-in type
+ const TString constructorFunctionName = TString(name) + "_ctor";
+ TString *constructor = &definedStruct->second->constructor;
+ if (!constructor->empty())
{
- constructor += TypeString(ctorType) + " " + name + "(";
+ return constructorFunctionName; // Already added
}
+ *constructor += name + " " + constructorFunctionName + "(";
- for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++)
+ std::vector<TType> ctorParameters;
+ const TFieldList &fields = structure.fields();
+ for (const TField *field : fields)
{
- const TType &paramType = ctorParameters[parameter];
-
- constructor += TypeString(paramType) + " x" + str(parameter) + ArrayString(paramType);
-
- if (parameter < ctorParameters.size() - 1)
+ const TType *fieldType = field->type();
+ if (!IsSampler(fieldType->getBasicType()))
{
- constructor += ", ";
+ ctorParameters.push_back(*fieldType);
}
}
+ // Structs that have sampler members should not have constructor calls, and otherwise structs
+ // are guaranteed to be non-empty by the grammar. Structs can't contain empty declarations
+ // either.
+ ASSERT(!ctorParameters.empty());
+
+ *constructor += WriteParameterList(ctorParameters);
- constructor += ")\n"
- "{\n";
+ *constructor +=
+ ")\n"
+ "{\n"
+ " " +
+ name + " structure = { ";
- if (ctorType.getStruct())
+ for (size_t parameterIndex = 0u; parameterIndex < ctorParameters.size(); ++parameterIndex)
{
- constructor += " " + name + " structure = {";
+ *constructor += "x" + str(parameterIndex);
+ if (parameterIndex < ctorParameters.size() - 1u)
+ {
+ *constructor += ", ";
+ }
}
- else
+ *constructor +=
+ "};\n"
+ " return structure;\n"
+ "}\n";
+
+ return constructorFunctionName;
+}
+
+TString StructureHLSL::addBuiltInConstructor(const TType &type, const TIntermSequence *parameters)
+{
+ ASSERT(!type.isArray());
+ ASSERT(type.getStruct() == nullptr);
+ ASSERT(parameters);
+
+ TType ctorType = type;
+ ctorType.setPrecision(EbpHigh);
+ ctorType.setQualifier(EvqTemporary);
+
+ const TString constructorFunctionName =
+ TString(type.getBuiltInTypeNameString()) + "_ctor" + DisambiguateFunctionName(parameters);
+ TString constructor = TypeString(ctorType) + " " + constructorFunctionName + "(";
+
+ std::vector<TType> ctorParameters;
+ for (auto parameter : *parameters)
{
- constructor += " return " + TypeString(ctorType) + "(";
+ const TType &paramType = parameter->getAsTyped()->getType();
+ ASSERT(!paramType.isArray());
+ ctorParameters.push_back(paramType);
}
+ constructor += WriteParameterList(ctorParameters);
+
+ constructor +=
+ ")\n"
+ "{\n"
+ " return " +
+ TypeString(ctorType) + "(";
if (ctorType.isMatrix() && ctorParameters.size() == 1)
{
- int rows = ctorType.getRows();
- int cols = ctorType.getCols();
+ int rows = ctorType.getRows();
+ int cols = ctorType.getCols();
const TType &parameter = ctorParameters[0];
if (parameter.isScalar())
@@ -355,7 +432,8 @@ void StructureHLSL::addConstructor(const TType &type, const TString &name, const
}
else
{
- ASSERT(rows == 2 && cols == 2 && parameter.isVector() && parameter.getNominalSize() == 4);
+ ASSERT(rows == 2 && cols == 2 && parameter.isVector() &&
+ parameter.getNominalSize() == 4);
constructor += "x0";
}
@@ -367,20 +445,13 @@ void StructureHLSL::addConstructor(const TType &type, const TString &name, const
while (remainingComponents > 0)
{
- const TType &parameter = ctorParameters[parameterIndex];
+ const TType &parameter = ctorParameters[parameterIndex];
const size_t parameterSize = parameter.getObjectSize();
- bool moreParameters = parameterIndex + 1 < ctorParameters.size();
+ bool moreParameters = parameterIndex + 1 < ctorParameters.size();
constructor += "x" + str(parameterIndex);
- if (ctorType.getStruct())
- {
- ASSERT(remainingComponents == parameterSize || moreParameters);
- ASSERT(parameterSize <= remainingComponents);
-
- remainingComponents -= parameterSize;
- }
- else if (parameter.isScalar())
+ if (parameter.isScalar())
{
remainingComponents -= parameter.getObjectSize();
}
@@ -395,16 +466,26 @@ void StructureHLSL::addConstructor(const TType &type, const TString &name, const
{
switch (remainingComponents)
{
- case 1: constructor += ".x"; break;
- case 2: constructor += ".xy"; break;
- case 3: constructor += ".xyz"; break;
- case 4: constructor += ".xyzw"; break;
- default: UNREACHABLE();
+ case 1:
+ constructor += ".x";
+ break;
+ case 2:
+ constructor += ".xy";
+ break;
+ case 3:
+ constructor += ".xyz";
+ break;
+ case 4:
+ constructor += ".xyzw";
+ break;
+ default:
+ UNREACHABLE();
}
remainingComponents = 0;
}
- else UNREACHABLE();
+ else
+ UNREACHABLE();
}
else if (parameter.isMatrix())
{
@@ -417,10 +498,17 @@ void StructureHLSL::addConstructor(const TType &type, const TString &name, const
{
switch (remainingComponents)
{
- case 1: constructor += ".x"; break;
- case 2: constructor += ".xy"; break;
- case 3: constructor += ".xyz"; break;
- default: UNREACHABLE();
+ case 1:
+ constructor += ".x";
+ break;
+ case 2:
+ constructor += ".xy";
+ break;
+ case 3:
+ constructor += ".xyz";
+ break;
+ default:
+ UNREACHABLE();
}
remainingComponents = 0;
@@ -438,7 +526,10 @@ void StructureHLSL::addConstructor(const TType &type, const TString &name, const
column++;
}
}
- else UNREACHABLE();
+ else
+ {
+ UNREACHABLE();
+ }
if (moreParameters)
{
@@ -452,53 +543,52 @@ void StructureHLSL::addConstructor(const TType &type, const TString &name, const
}
}
- if (ctorType.getStruct())
- {
- constructor += "};\n"
- " return structure;\n"
- "}\n";
- }
- else
- {
- constructor += ");\n"
- "}\n";
- }
+ constructor +=
+ ");\n"
+ "}\n";
- mConstructors.insert(constructor);
+ mBuiltInConstructors.insert(constructor);
+
+ return constructorFunctionName;
}
std::string StructureHLSL::structsHeader() const
{
TInfoSinkBase out;
- for (size_t structIndex = 0; structIndex < mStructDeclarations.size(); structIndex++)
+ for (auto &declaration : mStructDeclarations)
+ {
+ out << declaration;
+ }
+
+ for (auto &structure : mDefinedStructs)
{
- out << mStructDeclarations[structIndex];
+ out << structure.second->constructor;
}
- for (Constructors::const_iterator constructor = mConstructors.begin();
- constructor != mConstructors.end();
- constructor++)
+ for (auto &constructor : mBuiltInConstructors)
{
- out << *constructor;
+ out << constructor;
}
return out.str();
}
-void StructureHLSL::storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking)
+void StructureHLSL::storeStd140ElementIndex(const TStructure &structure,
+ bool useHLSLRowMajorPacking)
{
Std140PaddingHelper padHelper = getPaddingHelper();
- const TFieldList &fields = structure.fields();
+ const TFieldList &fields = structure.fields();
- for (unsigned int i = 0; i < fields.size(); i++)
+ for (const TField *field : fields)
{
- padHelper.prePadding(*fields[i]->type());
+ padHelper.prePadding(*field->type());
}
- // Add remaining element index to the global map, for use with nested structs in standard layouts
+ // Add remaining element index to the global map, for use with nested structs in standard
+ // layouts
const TString &structName = QualifiedStructNameString(structure, useHLSLRowMajorPacking, true);
mStd140StructElementIndexes[structName] = padHelper.elementIndex();
}
-}
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h
index cffe2a41ae..daced8f8d1 100644
--- a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h
@@ -4,7 +4,7 @@
// found in the LICENSE file.
//
// StructureHLSL.h:
-// Interfaces of methods for HLSL translation of GLSL structures.
+// HLSL translation of GLSL constructors and structures.
//
#ifndef COMPILER_TRANSLATOR_STRUCTUREHLSL_H_
@@ -49,11 +49,14 @@ class StructureHLSL : angle::NonCopyable
public:
StructureHLSL();
- void addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters);
- std::string structsHeader() const;
+ // Returns the name of the constructor function.
+ TString addStructConstructor(const TStructure &structure);
+ TString addBuiltInConstructor(const TType &type, const TIntermSequence *parameters);
- TString defineQualified(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing);
static TString defineNameless(const TStructure &structure);
+ void ensureStructDefined(const TStructure &structure);
+
+ std::string structsHeader() const;
Std140PaddingHelper getPaddingHelper();
@@ -62,20 +65,34 @@ class StructureHLSL : angle::NonCopyable
std::map<TString, int> mStd140StructElementIndexes;
- typedef std::set<TString> StructNames;
- StructNames mStructNames;
+ struct TStructProperties : public angle::NonCopyable
+ {
+ POOL_ALLOCATOR_NEW_DELETE();
+
+ TStructProperties() {}
- typedef std::set<TString> Constructors;
- Constructors mConstructors;
+ // Constructor is an empty string in case the struct doesn't have a constructor yet.
+ TString constructor;
+ };
+ // Map from struct name to struct properties.
+ typedef std::map<TString, TStructProperties *> DefinedStructs;
+ DefinedStructs mDefinedStructs;
+
+ // Struct declarations need to be kept in a vector instead of having them inside mDefinedStructs
+ // since maintaining the original order is necessary for nested structs.
typedef std::vector<TString> StructDeclarations;
StructDeclarations mStructDeclarations;
+ typedef std::set<TString> BuiltInConstructors;
+ BuiltInConstructors mBuiltInConstructors;
+
void storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking);
- static TString define(const TStructure &structure, bool useHLSLRowMajorPacking,
- bool useStd140Packing, Std140PaddingHelper *padHelper);
+ TString defineQualified(const TStructure &structure,
+ bool useHLSLRowMajorPacking,
+ bool useStd140Packing);
+ DefinedStructs::iterator defineVariants(const TStructure &structure, const TString &name);
};
-
}
-#endif // COMPILER_TRANSLATOR_STRUCTUREHLSL_H_
+#endif // COMPILER_TRANSLATOR_STRUCTUREHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp b/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp
index dc8f8e3b6b..6c38461469 100644
--- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp
@@ -3,45 +3,87 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-
-//
-// Symbol table for parsing. Most functionaliy and main ideas
-// are documented in the header file.
+// Symbol table for parsing. The design principles and most of the functionality are documented in
+// the header file.
//
#if defined(_MSC_VER)
-#pragma warning(disable: 4718)
+#pragma warning(disable : 4718)
#endif
#include "compiler/translator/SymbolTable.h"
+
#include "compiler/translator/Cache.h"
+#include "compiler/translator/IntermNode.h"
#include <stdio.h>
#include <algorithm>
-int TSymbolTable::uniqueIdCounter = 0;
+namespace sh
+{
+
+namespace
+{
+
+static const char kFunctionMangledNameSeparator = '(';
+
+} // anonymous namespace
+
+TSymbol::TSymbol(TSymbolTable *symbolTable, const TString *n)
+ : uniqueId(symbolTable->nextUniqueId()), name(n), extension(TExtension::UNDEFINED)
+{
+}
//
// Functions have buried pointers to delete.
//
TFunction::~TFunction()
{
+ clearParameters();
+}
+
+void TFunction::clearParameters()
+{
for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
delete (*i).type;
+ parameters.clear();
+ mangledName = nullptr;
+}
+
+void TFunction::swapParameters(const TFunction &parametersSource)
+{
+ clearParameters();
+ for (auto parameter : parametersSource.parameters)
+ {
+ addParameter(parameter);
+ }
}
const TString *TFunction::buildMangledName() const
{
- std::string newName = mangleName(getName()).c_str();
+ std::string newName = getName().c_str();
+ newName += kFunctionMangledNameSeparator;
for (const auto &p : parameters)
{
- newName += p.type->getMangledName().c_str();
+ newName += p.type->getMangledName();
}
-
return NewPoolTString(newName.c_str());
}
+const TString &TFunction::GetMangledNameFromCall(const TString &functionName,
+ const TIntermSequence &arguments)
+{
+ std::string newName = functionName.c_str();
+ newName += kFunctionMangledNameSeparator;
+
+ for (TIntermNode *argument : arguments)
+ {
+ newName += argument->getAsTyped()->getType().getMangledName();
+ }
+ return *NewPoolTString(newName.c_str());
+}
+
//
// Symbol table levels are a map of pointers to symbols that have to be deleted.
//
@@ -53,8 +95,6 @@ TSymbolTableLevel::~TSymbolTableLevel()
bool TSymbolTableLevel::insert(TSymbol *symbol)
{
- symbol->setUniqueId(TSymbolTable::nextUniqueId());
-
// returning true means symbol was added to the table
tInsertResult result = level.insert(tLevelPair(symbol->getMangledName(), symbol));
@@ -63,8 +103,6 @@ bool TSymbolTableLevel::insert(TSymbol *symbol)
bool TSymbolTableLevel::insertUnmangled(TFunction *function)
{
- function->setUniqueId(TSymbolTable::nextUniqueId());
-
// returning true means symbol was added to the table
tInsertResult result = level.insert(tLevelPair(function->getName(), function));
@@ -80,22 +118,27 @@ TSymbol *TSymbolTableLevel::find(const TString &name) const
return (*it).second;
}
-TSymbol *TSymbolTable::find(const TString &name, int shaderVersion,
- bool *builtIn, bool *sameScope) const
+TSymbol *TSymbolTable::find(const TString &name,
+ int shaderVersion,
+ bool *builtIn,
+ bool *sameScope) const
{
int level = currentLevel();
TSymbol *symbol;
do
{
- if (level == ESSL3_BUILTINS && shaderVersion != 300)
+ if (level == GLSL_BUILTINS)
+ level--;
+ if (level == ESSL3_1_BUILTINS && shaderVersion != 310)
+ level--;
+ if (level == ESSL3_BUILTINS && shaderVersion < 300)
level--;
if (level == ESSL1_BUILTINS && shaderVersion != 100)
level--;
symbol = table[level]->find(name);
- }
- while (symbol == 0 && --level >= 0);
+ } while (symbol == 0 && --level >= 0);
if (builtIn)
*builtIn = (level <= LAST_BUILTIN_LEVEL);
@@ -105,12 +148,28 @@ TSymbol *TSymbolTable::find(const TString &name, int shaderVersion,
return symbol;
}
-TSymbol *TSymbolTable::findBuiltIn(
- const TString &name, int shaderVersion) const
+TSymbol *TSymbolTable::findGlobal(const TString &name) const
+{
+ ASSERT(table.size() > GLOBAL_LEVEL);
+ return table[GLOBAL_LEVEL]->find(name);
+}
+
+TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion) const
+{
+ return findBuiltIn(name, shaderVersion, false);
+}
+
+TSymbol *TSymbolTable::findBuiltIn(const TString &name,
+ int shaderVersion,
+ bool includeGLSLBuiltins) const
{
for (int level = LAST_BUILTIN_LEVEL; level >= 0; level--)
{
- if (level == ESSL3_BUILTINS && shaderVersion != 300)
+ if (level == GLSL_BUILTINS && !includeGLSLBuiltins)
+ level--;
+ if (level == ESSL3_1_BUILTINS && shaderVersion != 310)
+ level--;
+ if (level == ESSL3_BUILTINS && shaderVersion < 300)
level--;
if (level == ESSL1_BUILTINS && shaderVersion != 100)
level--;
@@ -121,7 +180,7 @@ TSymbol *TSymbolTable::findBuiltIn(
return symbol;
}
- return 0;
+ return nullptr;
}
TSymbolTable::~TSymbolTable()
@@ -135,7 +194,8 @@ bool IsGenType(const TType *type)
if (type)
{
TBasicType basicType = type->getBasicType();
- return basicType == EbtGenType || basicType == EbtGenIType || basicType == EbtGenUType || basicType == EbtGenBType;
+ return basicType == EbtGenType || basicType == EbtGenIType || basicType == EbtGenUType ||
+ basicType == EbtGenBType;
}
return false;
@@ -146,7 +206,8 @@ bool IsVecType(const TType *type)
if (type)
{
TBasicType basicType = type->getBasicType();
- return basicType == EbtVec || basicType == EbtIVec || basicType == EbtUVec || basicType == EbtBVec;
+ return basicType == EbtVec || basicType == EbtIVec || basicType == EbtUVec ||
+ basicType == EbtBVec;
}
return false;
@@ -163,13 +224,19 @@ const TType *SpecificType(const TType *type, int size)
ASSERT(!IsVecType(type));
- switch(type->getBasicType())
+ switch (type->getBasicType())
{
- case EbtGenType: return TCache::getType(EbtFloat, static_cast<unsigned char>(size));
- case EbtGenIType: return TCache::getType(EbtInt, static_cast<unsigned char>(size));
- case EbtGenUType: return TCache::getType(EbtUInt, static_cast<unsigned char>(size));
- case EbtGenBType: return TCache::getType(EbtBool, static_cast<unsigned char>(size));
- default: return type;
+ case EbtGenType:
+ return TCache::getType(EbtFloat, type->getQualifier(),
+ static_cast<unsigned char>(size));
+ case EbtGenIType:
+ return TCache::getType(EbtInt, type->getQualifier(), static_cast<unsigned char>(size));
+ case EbtGenUType:
+ return TCache::getType(EbtUInt, type->getQualifier(), static_cast<unsigned char>(size));
+ case EbtGenBType:
+ return TCache::getType(EbtBool, type->getQualifier(), static_cast<unsigned char>(size));
+ default:
+ return type;
}
}
@@ -184,65 +251,232 @@ const TType *VectorType(const TType *type, int size)
ASSERT(!IsGenType(type));
- switch(type->getBasicType())
+ switch (type->getBasicType())
+ {
+ case EbtVec:
+ return TCache::getType(EbtFloat, static_cast<unsigned char>(size));
+ case EbtIVec:
+ return TCache::getType(EbtInt, static_cast<unsigned char>(size));
+ case EbtUVec:
+ return TCache::getType(EbtUInt, static_cast<unsigned char>(size));
+ case EbtBVec:
+ return TCache::getType(EbtBool, static_cast<unsigned char>(size));
+ default:
+ return type;
+ }
+}
+
+TVariable *TSymbolTable::declareVariable(const TString *name, const TType &type)
+{
+ return insertVariable(currentLevel(), name, type);
+}
+
+TVariable *TSymbolTable::declareStructType(TStructure *str)
+{
+ return insertStructType(currentLevel(), str);
+}
+
+TInterfaceBlockName *TSymbolTable::declareInterfaceBlockName(const TString *name)
+{
+ TInterfaceBlockName *blockNameSymbol = new TInterfaceBlockName(this, name);
+ if (insert(currentLevel(), blockNameSymbol))
+ {
+ return blockNameSymbol;
+ }
+ return nullptr;
+}
+
+TInterfaceBlockName *TSymbolTable::insertInterfaceBlockNameExt(ESymbolLevel level,
+ TExtension ext,
+ const TString *name)
+{
+ TInterfaceBlockName *blockNameSymbol = new TInterfaceBlockName(this, name);
+ if (insert(level, ext, blockNameSymbol))
+ {
+ return blockNameSymbol;
+ }
+ return nullptr;
+}
+
+TVariable *TSymbolTable::insertVariable(ESymbolLevel level, const char *name, const TType &type)
+{
+ return insertVariable(level, NewPoolTString(name), type);
+}
+
+TVariable *TSymbolTable::insertVariable(ESymbolLevel level, const TString *name, const TType &type)
+{
+ TVariable *var = new TVariable(this, name, type);
+ if (insert(level, var))
+ {
+ // Do lazy initialization for struct types, so we allocate to the current scope.
+ if (var->getType().getBasicType() == EbtStruct)
+ {
+ var->getType().realize();
+ }
+ return var;
+ }
+ return nullptr;
+}
+
+TVariable *TSymbolTable::insertVariableExt(ESymbolLevel level,
+ TExtension ext,
+ const char *name,
+ const TType &type)
+{
+ TVariable *var = new TVariable(this, NewPoolTString(name), type);
+ if (insert(level, ext, var))
+ {
+ if (var->getType().getBasicType() == EbtStruct)
+ {
+ var->getType().realize();
+ }
+ return var;
+ }
+ return nullptr;
+}
+
+TVariable *TSymbolTable::insertStructType(ESymbolLevel level, TStructure *str)
+{
+ TVariable *var = new TVariable(this, &str->name(), TType(str), true);
+ if (insert(level, var))
{
- case EbtVec: return TCache::getType(EbtFloat, static_cast<unsigned char>(size));
- case EbtIVec: return TCache::getType(EbtInt, static_cast<unsigned char>(size));
- case EbtUVec: return TCache::getType(EbtUInt, static_cast<unsigned char>(size));
- case EbtBVec: return TCache::getType(EbtBool, static_cast<unsigned char>(size));
- default: return type;
+ var->getType().realize();
+ return var;
}
+ return nullptr;
}
-void TSymbolTable::insertBuiltIn(ESymbolLevel level, TOperator op, const char *ext, const TType *rvalue, const char *name,
- const TType *ptype1, const TType *ptype2, const TType *ptype3, const TType *ptype4, const TType *ptype5)
+void TSymbolTable::insertBuiltIn(ESymbolLevel level,
+ TOperator op,
+ TExtension ext,
+ const TType *rvalue,
+ const char *name,
+ const TType *ptype1,
+ const TType *ptype2,
+ const TType *ptype3,
+ const TType *ptype4,
+ const TType *ptype5)
{
if (ptype1->getBasicType() == EbtGSampler2D)
{
+ insertUnmangledBuiltInName(name, level);
bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name, TCache::getType(EbtSampler2D), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name, TCache::getType(EbtISampler2D), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name, TCache::getType(EbtUSampler2D), ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name,
+ TCache::getType(EbtSampler2D), ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name,
+ TCache::getType(EbtISampler2D), ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name,
+ TCache::getType(EbtUSampler2D), ptype2, ptype3, ptype4, ptype5);
}
else if (ptype1->getBasicType() == EbtGSampler3D)
{
+ insertUnmangledBuiltInName(name, level);
bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name, TCache::getType(EbtSampler3D), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name, TCache::getType(EbtISampler3D), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name, TCache::getType(EbtUSampler3D), ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name,
+ TCache::getType(EbtSampler3D), ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name,
+ TCache::getType(EbtISampler3D), ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name,
+ TCache::getType(EbtUSampler3D), ptype2, ptype3, ptype4, ptype5);
}
else if (ptype1->getBasicType() == EbtGSamplerCube)
{
+ insertUnmangledBuiltInName(name, level);
bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name, TCache::getType(EbtSamplerCube), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name, TCache::getType(EbtISamplerCube), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name, TCache::getType(EbtUSamplerCube), ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name,
+ TCache::getType(EbtSamplerCube), ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name,
+ TCache::getType(EbtISamplerCube), ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name,
+ TCache::getType(EbtUSamplerCube), ptype2, ptype3, ptype4, ptype5);
}
else if (ptype1->getBasicType() == EbtGSampler2DArray)
{
+ insertUnmangledBuiltInName(name, level);
bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name, TCache::getType(EbtSampler2DArray), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name, TCache::getType(EbtISampler2DArray), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name, TCache::getType(EbtUSampler2DArray), ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name,
+ TCache::getType(EbtSampler2DArray), ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name,
+ TCache::getType(EbtISampler2DArray), ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name,
+ TCache::getType(EbtUSampler2DArray), ptype2, ptype3, ptype4, ptype5);
}
- else if (IsGenType(rvalue) || IsGenType(ptype1) || IsGenType(ptype2) || IsGenType(ptype3))
+ else if (ptype1->getBasicType() == EbtGSampler2DMS)
{
- ASSERT(!ptype4 && !ptype5);
- insertBuiltIn(level, op, ext, SpecificType(rvalue, 1), name, SpecificType(ptype1, 1), SpecificType(ptype2, 1), SpecificType(ptype3, 1));
- insertBuiltIn(level, op, ext, SpecificType(rvalue, 2), name, SpecificType(ptype1, 2), SpecificType(ptype2, 2), SpecificType(ptype3, 2));
- insertBuiltIn(level, op, ext, SpecificType(rvalue, 3), name, SpecificType(ptype1, 3), SpecificType(ptype2, 3), SpecificType(ptype3, 3));
- insertBuiltIn(level, op, ext, SpecificType(rvalue, 4), name, SpecificType(ptype1, 4), SpecificType(ptype2, 4), SpecificType(ptype3, 4));
+ insertUnmangledBuiltInName(name, level);
+ bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
+ insertBuiltIn(level, gvec4 ? TCache::getType(EbtFloat, 4) : rvalue, name,
+ TCache::getType(EbtSampler2DMS), ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, gvec4 ? TCache::getType(EbtInt, 4) : rvalue, name,
+ TCache::getType(EbtISampler2DMS), ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, gvec4 ? TCache::getType(EbtUInt, 4) : rvalue, name,
+ TCache::getType(EbtUSampler2DMS), ptype2, ptype3, ptype4, ptype5);
+ }
+ else if (IsGImage(ptype1->getBasicType()))
+ {
+ insertUnmangledBuiltInName(name, level);
+
+ const TType *floatType = TCache::getType(EbtFloat, 4);
+ const TType *intType = TCache::getType(EbtInt, 4);
+ const TType *unsignedType = TCache::getType(EbtUInt, 4);
+
+ const TType *floatImage =
+ TCache::getType(convertGImageToFloatImage(ptype1->getBasicType()));
+ const TType *intImage = TCache::getType(convertGImageToIntImage(ptype1->getBasicType()));
+ const TType *unsignedImage =
+ TCache::getType(convertGImageToUnsignedImage(ptype1->getBasicType()));
+
+ // GLSL ES 3.10, Revision 4, 8.12 Image Functions
+ if (rvalue->getBasicType() == EbtGVec4)
+ {
+ // imageLoad
+ insertBuiltIn(level, floatType, name, floatImage, ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, intType, name, intImage, ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, unsignedType, name, unsignedImage, ptype2, ptype3, ptype4, ptype5);
+ }
+ else if (rvalue->getBasicType() == EbtVoid)
+ {
+ // imageStore
+ insertBuiltIn(level, rvalue, name, floatImage, ptype2, floatType, ptype4, ptype5);
+ insertBuiltIn(level, rvalue, name, intImage, ptype2, intType, ptype4, ptype5);
+ insertBuiltIn(level, rvalue, name, unsignedImage, ptype2, unsignedType, ptype4, ptype5);
+ }
+ else
+ {
+ // imageSize
+ insertBuiltIn(level, rvalue, name, floatImage, ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, rvalue, name, intImage, ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, rvalue, name, unsignedImage, ptype2, ptype3, ptype4, ptype5);
+ }
+ }
+ else if (IsGenType(rvalue) || IsGenType(ptype1) || IsGenType(ptype2) || IsGenType(ptype3) ||
+ IsGenType(ptype4))
+ {
+ ASSERT(!ptype5);
+ insertUnmangledBuiltInName(name, level);
+ insertBuiltIn(level, op, ext, SpecificType(rvalue, 1), name, SpecificType(ptype1, 1),
+ SpecificType(ptype2, 1), SpecificType(ptype3, 1), SpecificType(ptype4, 1));
+ insertBuiltIn(level, op, ext, SpecificType(rvalue, 2), name, SpecificType(ptype1, 2),
+ SpecificType(ptype2, 2), SpecificType(ptype3, 2), SpecificType(ptype4, 2));
+ insertBuiltIn(level, op, ext, SpecificType(rvalue, 3), name, SpecificType(ptype1, 3),
+ SpecificType(ptype2, 3), SpecificType(ptype3, 3), SpecificType(ptype4, 3));
+ insertBuiltIn(level, op, ext, SpecificType(rvalue, 4), name, SpecificType(ptype1, 4),
+ SpecificType(ptype2, 4), SpecificType(ptype3, 4), SpecificType(ptype4, 4));
}
else if (IsVecType(rvalue) || IsVecType(ptype1) || IsVecType(ptype2) || IsVecType(ptype3))
{
ASSERT(!ptype4 && !ptype5);
- insertBuiltIn(level, op, ext, VectorType(rvalue, 2), name, VectorType(ptype1, 2), VectorType(ptype2, 2), VectorType(ptype3, 2));
- insertBuiltIn(level, op, ext, VectorType(rvalue, 3), name, VectorType(ptype1, 3), VectorType(ptype2, 3), VectorType(ptype3, 3));
- insertBuiltIn(level, op, ext, VectorType(rvalue, 4), name, VectorType(ptype1, 4), VectorType(ptype2, 4), VectorType(ptype3, 4));
+ insertUnmangledBuiltInName(name, level);
+ insertBuiltIn(level, op, ext, VectorType(rvalue, 2), name, VectorType(ptype1, 2),
+ VectorType(ptype2, 2), VectorType(ptype3, 2));
+ insertBuiltIn(level, op, ext, VectorType(rvalue, 3), name, VectorType(ptype1, 3),
+ VectorType(ptype2, 3), VectorType(ptype3, 3));
+ insertBuiltIn(level, op, ext, VectorType(rvalue, 4), name, VectorType(ptype1, 4),
+ VectorType(ptype2, 4), VectorType(ptype3, 4));
}
else
{
- TFunction *function = new TFunction(NewPoolTString(name), rvalue, op, ext);
+ TFunction *function = new TFunction(this, NewPoolTString(name), rvalue, op, ext);
function->addParameter(TConstParameter(ptype1));
@@ -266,10 +500,61 @@ void TSymbolTable::insertBuiltIn(ESymbolLevel level, TOperator op, const char *e
function->addParameter(TConstParameter(ptype5));
}
+ ASSERT(hasUnmangledBuiltInAtLevel(name, level));
insert(level, function);
}
}
+void TSymbolTable::insertBuiltInOp(ESymbolLevel level,
+ TOperator op,
+ const TType *rvalue,
+ const TType *ptype1,
+ const TType *ptype2,
+ const TType *ptype3,
+ const TType *ptype4,
+ const TType *ptype5)
+{
+ const char *name = GetOperatorString(op);
+ ASSERT(strlen(name) > 0);
+ insertUnmangledBuiltInName(name, level);
+ insertBuiltIn(level, op, TExtension::UNDEFINED, rvalue, name, ptype1, ptype2, ptype3, ptype4,
+ ptype5);
+}
+
+void TSymbolTable::insertBuiltInOp(ESymbolLevel level,
+ TOperator op,
+ TExtension ext,
+ const TType *rvalue,
+ const TType *ptype1,
+ const TType *ptype2,
+ const TType *ptype3,
+ const TType *ptype4,
+ const TType *ptype5)
+{
+ const char *name = GetOperatorString(op);
+ insertUnmangledBuiltInName(name, level);
+ insertBuiltIn(level, op, ext, rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
+}
+
+void TSymbolTable::insertBuiltInFunctionNoParameters(ESymbolLevel level,
+ TOperator op,
+ const TType *rvalue,
+ const char *name)
+{
+ insertUnmangledBuiltInName(name, level);
+ insert(level, new TFunction(this, NewPoolTString(name), rvalue, op));
+}
+
+void TSymbolTable::insertBuiltInFunctionNoParametersExt(ESymbolLevel level,
+ TExtension ext,
+ TOperator op,
+ const TType *rvalue,
+ const char *name)
+{
+ insertUnmangledBuiltInName(name, level);
+ insert(level, new TFunction(this, NewPoolTString(name), rvalue, op, ext));
+}
+
TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const
{
if (!SupportsPrecision(type))
@@ -279,7 +564,7 @@ TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const
TBasicType baseType = (type == EbtUInt) ? EbtInt : type;
int level = static_cast<int>(precisionStack.size()) - 1;
- assert(level >= 0); // Just to be safe. Should not happen.
+ assert(level >= 0); // Just to be safe. Should not happen.
// If we dont find anything we return this. Some types don't have predefined default precision.
TPrecision prec = EbpUndefined;
while (level >= 0)
@@ -294,3 +579,44 @@ TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const
}
return prec;
}
+
+void TSymbolTable::insertUnmangledBuiltInName(const char *name, ESymbolLevel level)
+{
+ ASSERT(level >= 0 && level < static_cast<ESymbolLevel>(table.size()));
+ table[level]->insertUnmangledBuiltInName(std::string(name));
+}
+
+bool TSymbolTable::hasUnmangledBuiltInAtLevel(const char *name, ESymbolLevel level)
+{
+ ASSERT(level >= 0 && level < static_cast<ESymbolLevel>(table.size()));
+ return table[level]->hasUnmangledBuiltIn(std::string(name));
+}
+
+bool TSymbolTable::hasUnmangledBuiltInForShaderVersion(const char *name, int shaderVersion)
+{
+ ASSERT(static_cast<ESymbolLevel>(table.size()) > LAST_BUILTIN_LEVEL);
+
+ for (int level = LAST_BUILTIN_LEVEL; level >= 0; --level)
+ {
+ if (level == ESSL3_1_BUILTINS && shaderVersion != 310)
+ {
+ --level;
+ }
+ if (level == ESSL3_BUILTINS && shaderVersion < 300)
+ {
+ --level;
+ }
+ if (level == ESSL1_BUILTINS && shaderVersion != 100)
+ {
+ --level;
+ }
+
+ if (table[level]->hasUnmangledBuiltIn(name))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h
index 2706149e3c..5d792ec188 100644
--- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h
+++ b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h
@@ -18,7 +18,7 @@
// so that symbol table lookups are never ambiguous. This allows
// a simpler symbol table structure.
//
-// * Pushing and popping of scope, so symbol table will really be a stack
+// * Pushing and popping of scope, so symbol table will really be a stack
// of symbol tables. Searched from the top, with new inserts going into
// the top.
//
@@ -30,111 +30,78 @@
// are tracked in the intermediate representation, not the symbol table.
//
+#include <array>
#include <assert.h>
#include <set>
#include "common/angleutils.h"
+#include "compiler/translator/ExtensionBehavior.h"
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/SymbolUniqueId.h"
+
+namespace sh
+{
// Symbol base class. (Can build functions or variables out of these...)
class TSymbol : angle::NonCopyable
{
public:
POOL_ALLOCATOR_NEW_DELETE();
- TSymbol(const TString *n)
- : uniqueId(0),
- name(n)
- {
- }
+ TSymbol(TSymbolTable *symbolTable, const TString *n);
+
virtual ~TSymbol()
{
// don't delete name, it's from the pool
}
- const TString &getName() const
- {
- return *name;
- }
- virtual const TString &getMangledName() const
- {
- return getName();
- }
- virtual bool isFunction() const
- {
- return false;
- }
- virtual bool isVariable() const
- {
- return false;
- }
- void setUniqueId(int id)
- {
- uniqueId = id;
- }
- int getUniqueId() const
- {
- return uniqueId;
- }
- void relateToExtension(const TString &ext)
- {
- extension = ext;
- }
- const TString &getExtension() const
- {
- return extension;
- }
+ const TString &getName() const { return *name; }
+ virtual const TString &getMangledName() const { return getName(); }
+ virtual bool isFunction() const { return false; }
+ virtual bool isVariable() const { return false; }
+ const TSymbolUniqueId &getUniqueId() const { return uniqueId; }
+ void relateToExtension(TExtension ext) { extension = ext; }
+ TExtension getExtension() const { return extension; }
private:
- int uniqueId; // For real comparing during code generation
+ const TSymbolUniqueId uniqueId;
const TString *name;
- TString extension;
+ TExtension extension;
};
-// Variable class, meaning a symbol that's not a function.
-//
-// There could be a separate class heirarchy for Constant variables;
-// Only one of int, bool, or float, (or none) is correct for
-// any particular use, but it's easy to do this way, and doesn't
-// seem worth having separate classes, and "getConst" can't simply return
-// different values for different types polymorphically, so this is
-// just simple and pragmatic.
+// Variable, meaning a symbol that's not a function.
+//
+// May store the value of a constant variable of any type (float, int, bool or struct).
class TVariable : public TSymbol
{
public:
- TVariable(const TString *name, const TType &t, bool uT = false)
- : TSymbol(name),
- type(t),
- userType(uT),
- unionArray(0)
- {
- }
~TVariable() override {}
bool isVariable() const override { return true; }
- TType &getType()
- {
- return type;
- }
- const TType &getType() const
- {
- return type;
- }
- bool isUserType() const
- {
- return userType;
- }
- void setQualifier(TQualifier qualifier)
- {
- type.setQualifier(qualifier);
- }
+ TType &getType() { return type; }
+ const TType &getType() const { return type; }
+ bool isUserType() const { return userType; }
+ void setQualifier(TQualifier qualifier) { type.setQualifier(qualifier); }
const TConstantUnion *getConstPointer() const { return unionArray; }
void shareConstPointer(const TConstantUnion *constArray) { unionArray = constArray; }
private:
+ friend class TSymbolTable;
+
+ TVariable(TSymbolTable *symbolTable,
+ const TString *name,
+ const TType &t,
+ bool isUserTypeDefinition = false)
+ : TSymbol(symbolTable, name), type(t), userType(isUserTypeDefinition), unionArray(0)
+ {
+ }
+
TType type;
+
+ // Set to true if this represents a struct type, as opposed to a variable.
bool userType;
+
// we are assuming that Pool Allocator will free the memory
// allocated to unionArray when this object is destroyed.
const TConstantUnion *unionArray;
@@ -143,34 +110,18 @@ class TVariable : public TSymbol
// Immutable version of TParameter.
struct TConstParameter
{
- TConstParameter()
- : name(nullptr),
- type(nullptr)
- {
- }
- explicit TConstParameter(const TString *n)
- : name(n),
- type(nullptr)
- {
- }
- explicit TConstParameter(const TType *t)
- : name(nullptr),
- type(t)
- {
- }
- TConstParameter(const TString *n, const TType *t)
- : name(n),
- type(t)
- {
- }
+ TConstParameter() : name(nullptr), type(nullptr) {}
+ explicit TConstParameter(const TString *n) : name(n), type(nullptr) {}
+ explicit TConstParameter(const TType *t) : name(nullptr), type(t) {}
+ TConstParameter(const TString *n, const TType *t) : name(n), type(t) {}
// Both constructor arguments must be const.
- TConstParameter(TString *n, TType *t) = delete;
+ TConstParameter(TString *n, TType *t) = delete;
TConstParameter(const TString *n, TType *t) = delete;
TConstParameter(TString *n, const TType *t) = delete;
- const TString *name;
- const TType *type;
+ const TString *const name;
+ const TType *const type;
};
// The function sub-class of symbols and the parser will need to
@@ -183,25 +134,26 @@ struct TParameter
TConstParameter turnToConst()
{
const TString *constName = name;
- const TType *constType = type;
- name = nullptr;
- type = nullptr;
+ const TType *constType = type;
+ name = nullptr;
+ type = nullptr;
return TConstParameter(constName, constType);
}
- TString *name;
+ const TString *name;
TType *type;
};
-// The function sub-class of a symbol.
+// The function sub-class of a symbol.
class TFunction : public TSymbol
{
public:
- TFunction(const TString *name,
+ TFunction(TSymbolTable *symbolTable,
+ const TString *name,
const TType *retType,
- TOperator tOp = EOpNull,
- const char *ext = "")
- : TSymbol(name),
+ TOperator tOp = EOpNull,
+ TExtension ext = TExtension::UNDEFINED)
+ : TSymbol(symbolTable, name),
returnType(retType),
mangledName(nullptr),
op(tOp),
@@ -213,21 +165,14 @@ class TFunction : public TSymbol
~TFunction() override;
bool isFunction() const override { return true; }
- static TString mangleName(const TString &name)
- {
- return name + '(';
- }
- static TString unmangleName(const TString &mangledName)
- {
- return TString(mangledName.c_str(), mangledName.find_first_of('('));
- }
-
void addParameter(const TConstParameter &p)
{
parameters.push_back(p);
mangledName = nullptr;
}
+ void swapParameters(const TFunction &parametersSource);
+
const TString &getMangledName() const override
{
if (mangledName == nullptr)
@@ -236,31 +181,25 @@ class TFunction : public TSymbol
}
return *mangledName;
}
- const TType &getReturnType() const
- {
- return *returnType;
- }
- TOperator getBuiltInOp() const
- {
- return op;
- }
+ static const TString &GetMangledNameFromCall(const TString &functionName,
+ const TIntermSequence &arguments);
+
+ const TType &getReturnType() const { return *returnType; }
+
+ TOperator getBuiltInOp() const { return op; }
void setDefined() { defined = true; }
bool isDefined() { return defined; }
void setHasPrototypeDeclaration() { mHasPrototypeDeclaration = true; }
bool hasPrototypeDeclaration() const { return mHasPrototypeDeclaration; }
- size_t getParamCount() const
- {
- return parameters.size();
- }
- const TConstParameter &getParam(size_t i) const
- {
- return parameters[i];
- }
+ size_t getParamCount() const { return parameters.size(); }
+ const TConstParameter &getParam(size_t i) const { return parameters[i]; }
private:
+ void clearParameters();
+
const TString *buildMangledName() const;
typedef TVector<TConstParameter> TParamList;
@@ -276,12 +215,11 @@ class TFunction : public TSymbol
class TInterfaceBlockName : public TSymbol
{
public:
- TInterfaceBlockName(const TString *name)
- : TSymbol(name)
- {
- }
+ virtual ~TInterfaceBlockName() {}
- virtual ~TInterfaceBlockName()
+ private:
+ friend class TSymbolTable;
+ TInterfaceBlockName(TSymbolTable *symbolTable, const TString *name) : TSymbol(symbolTable, name)
{
}
};
@@ -289,14 +227,12 @@ class TInterfaceBlockName : public TSymbol
class TSymbolTableLevel
{
public:
- typedef TMap<TString, TSymbol *> tLevel;
+ typedef TUnorderedMap<TString, TSymbol *> tLevel;
typedef tLevel::const_iterator const_iterator;
typedef const tLevel::value_type tLevelPair;
typedef std::pair<tLevel::iterator, bool> tInsertResult;
- TSymbolTableLevel()
- {
- }
+ TSymbolTableLevel() : mGlobalInvariant(false) {}
~TSymbolTableLevel();
bool insert(TSymbol *symbol);
@@ -306,25 +242,52 @@ class TSymbolTableLevel
TSymbol *find(const TString &name) const;
+ void addInvariantVarying(const std::string &name) { mInvariantVaryings.insert(name); }
+
+ bool isVaryingInvariant(const std::string &name)
+ {
+ return (mGlobalInvariant || mInvariantVaryings.count(name) > 0);
+ }
+
+ void setGlobalInvariant(bool invariant) { mGlobalInvariant = invariant; }
+
+ void insertUnmangledBuiltInName(const std::string &name)
+ {
+ mUnmangledBuiltInNames.insert(name);
+ }
+
+ bool hasUnmangledBuiltIn(const std::string &name)
+ {
+ return mUnmangledBuiltInNames.count(name) > 0;
+ }
+
protected:
tLevel level;
+ std::set<std::string> mInvariantVaryings;
+ bool mGlobalInvariant;
+
+ private:
+ std::set<std::string> mUnmangledBuiltInNames;
};
// Define ESymbolLevel as int rather than an enum since level can go
// above GLOBAL_LEVEL and cause atBuiltInLevel() to fail if the
// compiler optimizes the >= of the last element to ==.
typedef int ESymbolLevel;
-const int COMMON_BUILTINS = 0;
-const int ESSL1_BUILTINS = 1;
-const int ESSL3_BUILTINS = 2;
-const int LAST_BUILTIN_LEVEL = ESSL3_BUILTINS;
-const int GLOBAL_LEVEL = 3;
+const int COMMON_BUILTINS = 0;
+const int ESSL1_BUILTINS = 1;
+const int ESSL3_BUILTINS = 2;
+const int ESSL3_1_BUILTINS = 3;
+// GLSL_BUILTINS are desktop GLSL builtins that don't exist in ESSL but are used to implement
+// features in ANGLE's GLSL backend. They're not visible to the parser.
+const int GLSL_BUILTINS = 4;
+const int LAST_BUILTIN_LEVEL = GLSL_BUILTINS;
+const int GLOBAL_LEVEL = 5;
class TSymbolTable : angle::NonCopyable
{
public:
- TSymbolTable()
- : mGlobalInvariant(false)
+ TSymbolTable() : mUniqueIdCounter(0), mEmptySymbolId(this)
{
// The symbol table cannot be used until push() is called, but
// the lack of an initial call to push() can be used to detect
@@ -336,18 +299,9 @@ class TSymbolTable : angle::NonCopyable
// When the symbol table is initialized with the built-ins, there should
// 'push' calls, so that built-ins are at level 0 and the shader
// globals are at level 1.
- bool isEmpty() const
- {
- return table.empty();
- }
- bool atBuiltInLevel() const
- {
- return currentLevel() <= LAST_BUILTIN_LEVEL;
- }
- bool atGlobalLevel() const
- {
- return currentLevel() <= GLOBAL_LEVEL;
- }
+ bool isEmpty() const { return table.empty(); }
+ bool atBuiltInLevel() const { return currentLevel() <= LAST_BUILTIN_LEVEL; }
+ bool atGlobalLevel() const { return currentLevel() == GLOBAL_LEVEL; }
void push()
{
table.push_back(new TSymbolTableLevel);
@@ -363,87 +317,159 @@ class TSymbolTable : angle::NonCopyable
precisionStack.pop_back();
}
- bool declare(TSymbol *symbol)
- {
- return insert(currentLevel(), symbol);
- }
-
- bool insert(ESymbolLevel level, TSymbol *symbol)
- {
- return table[level]->insert(symbol);
- }
-
- bool insert(ESymbolLevel level, const char *ext, TSymbol *symbol)
- {
- symbol->relateToExtension(ext);
- return table[level]->insert(symbol);
- }
-
- bool insertConstInt(ESymbolLevel level, const char *name, int value)
+ // The declare* entry points are used when parsing and declare symbols at the current scope.
+ // They return the created symbol in case the declaration was successful, and nullptr if the
+ // declaration failed due to redefinition.
+ TVariable *declareVariable(const TString *name, const TType &type);
+ TVariable *declareStructType(TStructure *str);
+ TInterfaceBlockName *declareInterfaceBlockName(const TString *name);
+
+ // The insert* entry points are used when initializing the symbol table with built-ins.
+ // They return the created symbol in case the declaration was successful, and nullptr if the
+ // declaration failed due to redefinition.
+ TVariable *insertVariable(ESymbolLevel level, const char *name, const TType &type);
+ TVariable *insertVariableExt(ESymbolLevel level,
+ TExtension ext,
+ const char *name,
+ const TType &type);
+ TVariable *insertStructType(ESymbolLevel level, TStructure *str);
+ TInterfaceBlockName *insertInterfaceBlockNameExt(ESymbolLevel level,
+ TExtension ext,
+ const TString *name);
+
+ bool insertConstInt(ESymbolLevel level, const char *name, int value, TPrecision precision)
{
- TVariable *constant = new TVariable(
- NewPoolTString(name), TType(EbtInt, EbpUndefined, EvqConst, 1));
+ TVariable *constant =
+ new TVariable(this, NewPoolTString(name), TType(EbtInt, precision, EvqConst, 1));
TConstantUnion *unionArray = new TConstantUnion[1];
unionArray[0].setIConst(value);
constant->shareConstPointer(unionArray);
return insert(level, constant);
}
- bool insertConstIntExt(ESymbolLevel level, const char *ext, const char *name, int value)
+ bool insertConstIntExt(ESymbolLevel level,
+ TExtension ext,
+ const char *name,
+ int value,
+ TPrecision precision)
{
TVariable *constant =
- new TVariable(NewPoolTString(name), TType(EbtInt, EbpUndefined, EvqConst, 1));
+ new TVariable(this, NewPoolTString(name), TType(EbtInt, precision, EvqConst, 1));
TConstantUnion *unionArray = new TConstantUnion[1];
unionArray[0].setIConst(value);
constant->shareConstPointer(unionArray);
return insert(level, ext, constant);
}
- void insertBuiltIn(ESymbolLevel level, TOperator op, const char *ext, const TType *rvalue, const char *name,
- const TType *ptype1, const TType *ptype2 = 0, const TType *ptype3 = 0, const TType *ptype4 = 0, const TType *ptype5 = 0);
-
- void insertBuiltIn(ESymbolLevel level, const TType *rvalue, const char *name,
- const TType *ptype1, const TType *ptype2 = 0, const TType *ptype3 = 0, const TType *ptype4 = 0, const TType *ptype5 = 0)
+ bool insertConstIvec3(ESymbolLevel level,
+ const char *name,
+ const std::array<int, 3> &values,
+ TPrecision precision)
{
- insertBuiltIn(level, EOpNull, "", rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
- }
+ TVariable *constantIvec3 =
+ new TVariable(this, NewPoolTString(name), TType(EbtInt, precision, EvqConst, 3));
- void insertBuiltIn(ESymbolLevel level, const char *ext, const TType *rvalue, const char *name,
- const TType *ptype1, const TType *ptype2 = 0, const TType *ptype3 = 0, const TType *ptype4 = 0, const TType *ptype5 = 0)
- {
+ TConstantUnion *unionArray = new TConstantUnion[3];
+ for (size_t index = 0u; index < 3u; ++index)
+ {
+ unionArray[index].setIConst(values[index]);
+ }
+ constantIvec3->shareConstPointer(unionArray);
+
+ return insert(level, constantIvec3);
+ }
+
+ void insertBuiltIn(ESymbolLevel level,
+ TOperator op,
+ TExtension ext,
+ const TType *rvalue,
+ const char *name,
+ const TType *ptype1,
+ const TType *ptype2 = 0,
+ const TType *ptype3 = 0,
+ const TType *ptype4 = 0,
+ const TType *ptype5 = 0);
+
+ void insertBuiltIn(ESymbolLevel level,
+ const TType *rvalue,
+ const char *name,
+ const TType *ptype1,
+ const TType *ptype2 = 0,
+ const TType *ptype3 = 0,
+ const TType *ptype4 = 0,
+ const TType *ptype5 = 0)
+ {
+ insertUnmangledBuiltInName(name, level);
+ insertBuiltIn(level, EOpNull, TExtension::UNDEFINED, rvalue, name, ptype1, ptype2, ptype3,
+ ptype4, ptype5);
+ }
+
+ void insertBuiltIn(ESymbolLevel level,
+ TExtension ext,
+ const TType *rvalue,
+ const char *name,
+ const TType *ptype1,
+ const TType *ptype2 = 0,
+ const TType *ptype3 = 0,
+ const TType *ptype4 = 0,
+ const TType *ptype5 = 0)
+ {
+ insertUnmangledBuiltInName(name, level);
insertBuiltIn(level, EOpNull, ext, rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
}
- void insertBuiltIn(ESymbolLevel level, TOperator op, const TType *rvalue, const char *name,
- const TType *ptype1, const TType *ptype2 = 0, const TType *ptype3 = 0, const TType *ptype4 = 0, const TType *ptype5 = 0)
- {
- insertBuiltIn(level, op, "", rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
- }
+ void insertBuiltInOp(ESymbolLevel level,
+ TOperator op,
+ const TType *rvalue,
+ const TType *ptype1,
+ const TType *ptype2 = 0,
+ const TType *ptype3 = 0,
+ const TType *ptype4 = 0,
+ const TType *ptype5 = 0);
+
+ void insertBuiltInOp(ESymbolLevel level,
+ TOperator op,
+ TExtension ext,
+ const TType *rvalue,
+ const TType *ptype1,
+ const TType *ptype2 = 0,
+ const TType *ptype3 = 0,
+ const TType *ptype4 = 0,
+ const TType *ptype5 = 0);
+
+ void insertBuiltInFunctionNoParameters(ESymbolLevel level,
+ TOperator op,
+ const TType *rvalue,
+ const char *name);
+
+ void insertBuiltInFunctionNoParametersExt(ESymbolLevel level,
+ TExtension ext,
+ TOperator op,
+ const TType *rvalue,
+ const char *name);
+
+ TSymbol *find(const TString &name,
+ int shaderVersion,
+ bool *builtIn = nullptr,
+ bool *sameScope = nullptr) const;
+
+ TSymbol *findGlobal(const TString &name) const;
- TSymbol *find(const TString &name, int shaderVersion,
- bool *builtIn = NULL, bool *sameScope = NULL) const;
TSymbol *findBuiltIn(const TString &name, int shaderVersion) const;
-
+
+ TSymbol *findBuiltIn(const TString &name, int shaderVersion, bool includeGLSLBuiltins) const;
+
TSymbolTableLevel *getOuterLevel()
{
assert(currentLevel() >= 1);
return table[currentLevel() - 1];
}
- void dump(TInfoSink &infoSink) const;
-
- bool setDefaultPrecision(const TPublicType &type, TPrecision prec)
+ void setDefaultPrecision(TBasicType type, TPrecision prec)
{
- if (!SupportsPrecision(type.type))
- return false;
- if (type.type == EbtUInt)
- return false; // ESSL 3.00.4 section 4.5.4
- if (type.isAggregate())
- return false; // Not allowed to set for aggregate types
int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
// Uses map operator [], overwrites the current value
- (*precisionStack[indexOfLastElement])[type.type] = prec;
- return true;
+ (*precisionStack[indexOfLastElement])[type] = prec;
}
// Searches down the precisionStack for a precision qualifier
@@ -454,7 +480,8 @@ class TSymbolTable : angle::NonCopyable
// "invariant varying_name;".
void addInvariantVarying(const std::string &originalName)
{
- mInvariantVaryings.insert(originalName);
+ ASSERT(atGlobalLevel());
+ table[currentLevel()]->addInvariantVarying(originalName);
}
// If this returns false, the varying could still be invariant
// if it is set as invariant during the varying variable
@@ -462,32 +489,57 @@ class TSymbolTable : angle::NonCopyable
// variable's type, not here.
bool isVaryingInvariant(const std::string &originalName) const
{
- return (mGlobalInvariant ||
- mInvariantVaryings.count(originalName) > 0);
+ ASSERT(atGlobalLevel());
+ return table[currentLevel()]->isVaryingInvariant(originalName);
}
- void setGlobalInvariant() { mGlobalInvariant = true; }
- bool getGlobalInvariant() const { return mGlobalInvariant; }
-
- static int nextUniqueId()
+ void setGlobalInvariant(bool invariant)
{
- return ++uniqueIdCounter;
+ ASSERT(atGlobalLevel());
+ table[currentLevel()]->setGlobalInvariant(invariant);
}
+ const TSymbolUniqueId nextUniqueId() { return TSymbolUniqueId(this); }
+
+ // The empty symbol id is shared between all empty string ("") symbols. They are used in the
+ // AST for unused function parameters and struct type declarations that don't declare a
+ // variable, for example.
+ const TSymbolUniqueId &getEmptySymbolId() { return mEmptySymbolId; }
+
+ // Checks whether there is a built-in accessible by a shader with the specified version.
+ bool hasUnmangledBuiltInForShaderVersion(const char *name, int shaderVersion);
+
private:
- ESymbolLevel currentLevel() const
+ friend class TSymbolUniqueId;
+ int nextUniqueIdValue() { return ++mUniqueIdCounter; }
+
+ ESymbolLevel currentLevel() const { return static_cast<ESymbolLevel>(table.size() - 1); }
+
+ TVariable *insertVariable(ESymbolLevel level, const TString *name, const TType &type);
+
+ bool insert(ESymbolLevel level, TSymbol *symbol) { return table[level]->insert(symbol); }
+
+ bool insert(ESymbolLevel level, TExtension ext, TSymbol *symbol)
{
- return static_cast<ESymbolLevel>(table.size() - 1);
+ symbol->relateToExtension(ext);
+ return table[level]->insert(symbol);
}
+ // Used to insert unmangled functions to check redeclaration of built-ins in ESSL 3.00 and
+ // above.
+ void insertUnmangledBuiltInName(const char *name, ESymbolLevel level);
+
+ bool hasUnmangledBuiltInAtLevel(const char *name, ESymbolLevel level);
+
std::vector<TSymbolTableLevel *> table;
typedef TMap<TBasicType, TPrecision> PrecisionStackLevel;
- std::vector< PrecisionStackLevel *> precisionStack;
+ std::vector<PrecisionStackLevel *> precisionStack;
- std::set<std::string> mInvariantVaryings;
- bool mGlobalInvariant;
+ int mUniqueIdCounter;
- static int uniqueIdCounter;
+ const TSymbolUniqueId mEmptySymbolId;
};
-#endif // COMPILER_TRANSLATOR_SYMBOLTABLE_H_
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_SYMBOLTABLE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.cpp b/src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.cpp
new file mode 100644
index 0000000000..2a68ae3e70
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.cpp
@@ -0,0 +1,28 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// SymbolUniqueId.cpp: Encapsulates a unique id for a symbol.
+
+#include "compiler/translator/SymbolUniqueId.h"
+
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+TSymbolUniqueId::TSymbolUniqueId(TSymbolTable *symbolTable) : mId(symbolTable->nextUniqueIdValue())
+{
+}
+
+TSymbolUniqueId::TSymbolUniqueId(const TSymbol &symbol) : mId(symbol.getUniqueId().get())
+{
+}
+
+int TSymbolUniqueId::get() const
+{
+ return mId;
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.h b/src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.h
new file mode 100644
index 0000000000..4bd5604246
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/SymbolUniqueId.h
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// SymbolUniqueId.h: Encapsulates a unique id for a symbol.
+
+#ifndef COMPILER_TRANSLATOR_SYMBOLUNIQUEID_H_
+#define COMPILER_TRANSLATOR_SYMBOLUNIQUEID_H_
+
+#include "compiler/translator/Common.h"
+
+namespace sh
+{
+
+class TSymbolTable;
+class TSymbol;
+
+class TSymbolUniqueId
+{
+ public:
+ POOL_ALLOCATOR_NEW_DELETE();
+ explicit TSymbolUniqueId(TSymbolTable *symbolTable);
+ explicit TSymbolUniqueId(const TSymbol &symbol);
+ TSymbolUniqueId(const TSymbolUniqueId &) = default;
+ TSymbolUniqueId &operator=(const TSymbolUniqueId &) = default;
+
+ int get() const;
+
+ private:
+ int mId;
+};
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_SYMBOLUNIQUEID_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.cpp
new file mode 100644
index 0000000000..d2b65a6c56
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.cpp
@@ -0,0 +1,1322 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// TextureFunctionHLSL: Class for writing implementations of ESSL texture functions into HLSL
+// output. Some of the implementations are straightforward and just call the HLSL equivalent of the
+// ESSL texture function, others do more work to emulate ESSL texture sampling or size query
+// behavior.
+//
+
+#include "compiler/translator/TextureFunctionHLSL.h"
+
+#include "compiler/translator/UtilsHLSL.h"
+
+namespace sh
+{
+
+namespace
+{
+
+void OutputIntTexCoordWrap(TInfoSinkBase &out,
+ const char *wrapMode,
+ const char *size,
+ const TString &texCoord,
+ const TString &texCoordOffset,
+ const char *texCoordOutName)
+{
+ // GLES 3.0.4 table 3.22 specifies how the wrap modes work. We don't use the formulas verbatim
+ // but rather use equivalent formulas that map better to HLSL.
+ out << "int " << texCoordOutName << ";\n";
+ out << "float " << texCoordOutName << "Offset = " << texCoord << " + float(" << texCoordOffset
+ << ") / " << size << ";\n";
+
+ // CLAMP_TO_EDGE
+ out << "if (" << wrapMode << " == 1)\n";
+ out << "{\n";
+ out << " " << texCoordOutName << " = clamp(int(floor(" << size << " * " << texCoordOutName
+ << "Offset)), 0, int(" << size << ") - 1);\n";
+ out << "}\n";
+
+ // MIRRORED_REPEAT
+ out << "else if (" << wrapMode << " == 3)\n";
+ out << "{\n";
+ out << " float coordWrapped = 1.0 - abs(frac(abs(" << texCoordOutName
+ << "Offset) * 0.5) * 2.0 - 1.0);\n";
+ out << " " << texCoordOutName << " = int(floor(" << size << " * coordWrapped));\n";
+ out << "}\n";
+
+ // REPEAT
+ out << "else\n";
+ out << "{\n";
+ out << " " << texCoordOutName << " = int(floor(" << size << " * frac(" << texCoordOutName
+ << "Offset)));\n";
+ out << "}\n";
+}
+
+void OutputIntTexCoordWraps(TInfoSinkBase &out,
+ const TextureFunctionHLSL::TextureFunction &textureFunction,
+ TString *texCoordX,
+ TString *texCoordY,
+ TString *texCoordZ)
+{
+ // Convert from normalized floating-point to integer
+ out << "int wrapS = samplerMetadata[samplerIndex].wrapModes & 0x3;\n";
+ if (textureFunction.offset)
+ {
+ OutputIntTexCoordWrap(out, "wrapS", "width", *texCoordX, "offset.x", "tix");
+ }
+ else
+ {
+ OutputIntTexCoordWrap(out, "wrapS", "width", *texCoordX, "0", "tix");
+ }
+ *texCoordX = "tix";
+ out << "int wrapT = (samplerMetadata[samplerIndex].wrapModes >> 2) & 0x3;\n";
+ if (textureFunction.offset)
+ {
+ OutputIntTexCoordWrap(out, "wrapT", "height", *texCoordY, "offset.y", "tiy");
+ }
+ else
+ {
+ OutputIntTexCoordWrap(out, "wrapT", "height", *texCoordY, "0", "tiy");
+ }
+ *texCoordY = "tiy";
+
+ if (IsSamplerArray(textureFunction.sampler))
+ {
+ *texCoordZ = "int(max(0, min(layers - 1, floor(0.5 + t.z))))";
+ }
+ else if (!IsSamplerCube(textureFunction.sampler) && !IsSampler2D(textureFunction.sampler))
+ {
+ out << "int wrapR = (samplerMetadata[samplerIndex].wrapModes >> 4) & 0x3;\n";
+ if (textureFunction.offset)
+ {
+ OutputIntTexCoordWrap(out, "wrapR", "depth", *texCoordZ, "offset.z", "tiz");
+ }
+ else
+ {
+ OutputIntTexCoordWrap(out, "wrapR", "depth", *texCoordZ, "0", "tiz");
+ }
+ *texCoordZ = "tiz";
+ }
+}
+
+void OutputHLSL4SampleFunctionPrefix(TInfoSinkBase &out,
+ const TextureFunctionHLSL::TextureFunction &textureFunction,
+ const TString &textureReference,
+ const TString &samplerReference)
+{
+ out << textureReference;
+ if (IsIntegerSampler(textureFunction.sampler) ||
+ textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH)
+ {
+ out << ".Load(";
+ return;
+ }
+
+ if (IsShadowSampler(textureFunction.sampler))
+ {
+ switch (textureFunction.method)
+ {
+ case TextureFunctionHLSL::TextureFunction::IMPLICIT:
+ case TextureFunctionHLSL::TextureFunction::BIAS:
+ case TextureFunctionHLSL::TextureFunction::LOD:
+ out << ".SampleCmp(";
+ break;
+ case TextureFunctionHLSL::TextureFunction::LOD0:
+ case TextureFunctionHLSL::TextureFunction::LOD0BIAS:
+ case TextureFunctionHLSL::TextureFunction::GRAD:
+ out << ".SampleCmpLevelZero(";
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ else
+ {
+ switch (textureFunction.method)
+ {
+ case TextureFunctionHLSL::TextureFunction::IMPLICIT:
+ out << ".Sample(";
+ break;
+ case TextureFunctionHLSL::TextureFunction::BIAS:
+ out << ".SampleBias(";
+ break;
+ case TextureFunctionHLSL::TextureFunction::LOD:
+ case TextureFunctionHLSL::TextureFunction::LOD0:
+ case TextureFunctionHLSL::TextureFunction::LOD0BIAS:
+ out << ".SampleLevel(";
+ break;
+ case TextureFunctionHLSL::TextureFunction::GRAD:
+ out << ".SampleGrad(";
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ out << samplerReference << ", ";
+}
+
+const char *GetSamplerCoordinateTypeString(
+ const TextureFunctionHLSL::TextureFunction &textureFunction,
+ int hlslCoords)
+{
+ if (IsIntegerSampler(textureFunction.sampler) ||
+ textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH)
+ {
+ switch (hlslCoords)
+ {
+ case 2:
+ if (textureFunction.sampler == EbtSampler2DMS ||
+ textureFunction.sampler == EbtISampler2DMS ||
+ textureFunction.sampler == EbtUSampler2DMS)
+ return "int2";
+ else
+ return "int3";
+ case 3:
+ return "int4";
+ default:
+ UNREACHABLE();
+ }
+ }
+ else
+ {
+ switch (hlslCoords)
+ {
+ case 2:
+ return "float2";
+ case 3:
+ return "float3";
+ case 4:
+ return "float4";
+ default:
+ UNREACHABLE();
+ }
+ }
+ return "";
+}
+
+int GetHLSLCoordCount(const TextureFunctionHLSL::TextureFunction &textureFunction,
+ ShShaderOutput outputType)
+{
+ if (outputType == SH_HLSL_3_0_OUTPUT)
+ {
+ int hlslCoords = 2;
+ switch (textureFunction.sampler)
+ {
+ case EbtSampler2D:
+ case EbtSamplerExternalOES:
+ case EbtSampler2DMS:
+ hlslCoords = 2;
+ break;
+ case EbtSamplerCube:
+ hlslCoords = 3;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ switch (textureFunction.method)
+ {
+ case TextureFunctionHLSL::TextureFunction::IMPLICIT:
+ case TextureFunctionHLSL::TextureFunction::GRAD:
+ return hlslCoords;
+ case TextureFunctionHLSL::TextureFunction::BIAS:
+ case TextureFunctionHLSL::TextureFunction::LOD:
+ case TextureFunctionHLSL::TextureFunction::LOD0:
+ case TextureFunctionHLSL::TextureFunction::LOD0BIAS:
+ return 4;
+ default:
+ UNREACHABLE();
+ }
+ }
+ else
+ {
+ switch (textureFunction.sampler)
+ {
+ case EbtSampler2D:
+ return 2;
+ case EbtSampler2DMS:
+ return 2;
+ case EbtSampler3D:
+ return 3;
+ case EbtSamplerCube:
+ return 3;
+ case EbtSampler2DArray:
+ return 3;
+ case EbtSamplerExternalOES:
+ return 2;
+ case EbtISampler2D:
+ return 2;
+ case EbtISampler2DMS:
+ return 2;
+ case EbtISampler3D:
+ return 3;
+ case EbtISamplerCube:
+ return 3;
+ case EbtISampler2DArray:
+ return 3;
+ case EbtUSampler2D:
+ return 2;
+ case EbtUSampler2DMS:
+ return 2;
+ case EbtUSampler3D:
+ return 3;
+ case EbtUSamplerCube:
+ return 3;
+ case EbtUSampler2DArray:
+ return 3;
+ case EbtSampler2DShadow:
+ return 2;
+ case EbtSamplerCubeShadow:
+ return 3;
+ case EbtSampler2DArrayShadow:
+ return 3;
+ default:
+ UNREACHABLE();
+ }
+ }
+ return 0;
+}
+
+void OutputTextureFunctionArgumentList(TInfoSinkBase &out,
+ const TextureFunctionHLSL::TextureFunction &textureFunction,
+ const ShShaderOutput outputType)
+{
+ if (outputType == SH_HLSL_3_0_OUTPUT)
+ {
+ switch (textureFunction.sampler)
+ {
+ case EbtSampler2D:
+ case EbtSamplerExternalOES:
+ out << "sampler2D s";
+ break;
+ case EbtSamplerCube:
+ out << "samplerCUBE s";
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ else
+ {
+ if (outputType == SH_HLSL_4_0_FL9_3_OUTPUT)
+ {
+ out << TextureString(textureFunction.sampler) << " x, "
+ << SamplerString(textureFunction.sampler) << " s";
+ }
+ else
+ {
+ ASSERT(outputType == SH_HLSL_4_1_OUTPUT);
+ // A bug in the D3D compiler causes some nested sampling operations to fail.
+ // See http://anglebug.com/1923
+ // TODO(jmadill): Reinstate the const keyword when possible.
+ out << /*"const"*/ "uint samplerIndex";
+ }
+ }
+
+ if (textureFunction.method ==
+ TextureFunctionHLSL::TextureFunction::FETCH) // Integer coordinates
+ {
+ switch (textureFunction.coords)
+ {
+ case 2:
+ out << ", int2 t";
+ break;
+ case 3:
+ out << ", int3 t";
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ else // Floating-point coordinates (except textureSize)
+ {
+ switch (textureFunction.coords)
+ {
+ case 0:
+ break; // textureSize(gSampler2DMS sampler)
+ case 1:
+ out << ", int lod";
+ break; // textureSize()
+ case 2:
+ out << ", float2 t";
+ break;
+ case 3:
+ out << ", float3 t";
+ break;
+ case 4:
+ out << ", float4 t";
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
+ {
+ switch (textureFunction.sampler)
+ {
+ case EbtSampler2D:
+ case EbtISampler2D:
+ case EbtUSampler2D:
+ case EbtSampler2DArray:
+ case EbtISampler2DArray:
+ case EbtUSampler2DArray:
+ case EbtSampler2DShadow:
+ case EbtSampler2DArrayShadow:
+ case EbtSamplerExternalOES:
+ out << ", float2 ddx, float2 ddy";
+ break;
+ case EbtSampler3D:
+ case EbtISampler3D:
+ case EbtUSampler3D:
+ case EbtSamplerCube:
+ case EbtISamplerCube:
+ case EbtUSamplerCube:
+ case EbtSamplerCubeShadow:
+ out << ", float3 ddx, float3 ddy";
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ switch (textureFunction.method)
+ {
+ case TextureFunctionHLSL::TextureFunction::IMPLICIT:
+ break;
+ case TextureFunctionHLSL::TextureFunction::BIAS:
+ break; // Comes after the offset parameter
+ case TextureFunctionHLSL::TextureFunction::LOD:
+ out << ", float lod";
+ break;
+ case TextureFunctionHLSL::TextureFunction::LOD0:
+ break;
+ case TextureFunctionHLSL::TextureFunction::LOD0BIAS:
+ break; // Comes after the offset parameter
+ case TextureFunctionHLSL::TextureFunction::SIZE:
+ break;
+ case TextureFunctionHLSL::TextureFunction::FETCH:
+ if (textureFunction.sampler == EbtSampler2DMS ||
+ textureFunction.sampler == EbtISampler2DMS ||
+ textureFunction.sampler == EbtUSampler2DMS)
+ out << ", int index";
+ else
+ out << ", int mip";
+ break;
+ case TextureFunctionHLSL::TextureFunction::GRAD:
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ if (textureFunction.offset)
+ {
+ switch (textureFunction.sampler)
+ {
+ case EbtSampler3D:
+ case EbtISampler3D:
+ case EbtUSampler3D:
+ out << ", int3 offset";
+ break;
+ case EbtSampler2D:
+ case EbtSampler2DArray:
+ case EbtISampler2D:
+ case EbtISampler2DArray:
+ case EbtUSampler2D:
+ case EbtUSampler2DArray:
+ case EbtSampler2DShadow:
+ case EbtSampler2DArrayShadow:
+ case EbtSampler2DMS:
+ case EbtISampler2DMS:
+ case EbtUSampler2DMS:
+ case EbtSamplerExternalOES:
+ out << ", int2 offset";
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS ||
+ textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS)
+ {
+ out << ", float bias";
+ }
+}
+
+void GetTextureReference(TInfoSinkBase &out,
+ const TextureFunctionHLSL::TextureFunction &textureFunction,
+ const ShShaderOutput outputType,
+ TString *textureReference,
+ TString *samplerReference)
+{
+ if (outputType == SH_HLSL_4_1_OUTPUT)
+ {
+ TString suffix = TextureGroupSuffix(textureFunction.sampler);
+ if (TextureGroup(textureFunction.sampler) == HLSL_TEXTURE_2D)
+ {
+ *textureReference = TString("textures") + suffix + "[samplerIndex]";
+ *samplerReference = TString("samplers") + suffix + "[samplerIndex]";
+ }
+ else
+ {
+ out << " const uint textureIndex = samplerIndex - textureIndexOffset" << suffix
+ << ";\n";
+ *textureReference = TString("textures") + suffix + "[textureIndex]";
+ out << " const uint samplerArrayIndex = samplerIndex - samplerIndexOffset" << suffix
+ << ";\n";
+ *samplerReference = TString("samplers") + suffix + "[samplerArrayIndex]";
+ }
+ }
+ else
+ {
+ *textureReference = "x";
+ *samplerReference = "s";
+ }
+}
+
+void OutputTextureSizeFunctionBody(TInfoSinkBase &out,
+ const TextureFunctionHLSL::TextureFunction &textureFunction,
+ const TString &textureReference,
+ bool getDimensionsIgnoresBaseLevel)
+{
+ if (IsSampler2DMS(textureFunction.sampler))
+ {
+ out << " uint width; uint height; uint samples;\n"
+ << " " << textureReference << ".GetDimensions(width, height, samples);\n";
+ }
+ else
+ {
+ if (getDimensionsIgnoresBaseLevel)
+ {
+ out << " int baseLevel = samplerMetadata[samplerIndex].baseLevel;\n";
+ }
+ else
+ {
+ out << " int baseLevel = 0;\n";
+ }
+
+ if (IsSampler3D(textureFunction.sampler) || IsSamplerArray(textureFunction.sampler) ||
+ (IsIntegerSampler(textureFunction.sampler) && IsSamplerCube(textureFunction.sampler)))
+ {
+ // "depth" stores either the number of layers in an array texture or 3D depth
+ out << " uint width; uint height; uint depth; uint numberOfLevels;\n"
+ << " " << textureReference
+ << ".GetDimensions(baseLevel, width, height, depth, numberOfLevels);\n"
+ << " width = max(width >> lod, 1);\n"
+ << " height = max(height >> lod, 1);\n";
+
+ if (!IsSamplerArray(textureFunction.sampler))
+ {
+ out << " depth = max(depth >> lod, 1);\n";
+ }
+ }
+ else if (IsSampler2D(textureFunction.sampler) || IsSamplerCube(textureFunction.sampler))
+ {
+ out << " uint width; uint height; uint numberOfLevels;\n"
+ << " " << textureReference
+ << ".GetDimensions(baseLevel, width, height, numberOfLevels);\n"
+ << " width = max(width >> lod, 1);\n"
+ << " height = max(height >> lod, 1);\n";
+ }
+ else
+ UNREACHABLE();
+ }
+
+ if (strcmp(textureFunction.getReturnType(), "int3") == 0)
+ {
+ out << " return int3(width, height, depth);\n";
+ }
+ else
+ {
+ out << " return int2(width, height);\n";
+ }
+}
+
+void ProjectTextureCoordinates(const TextureFunctionHLSL::TextureFunction &textureFunction,
+ TString *texCoordX,
+ TString *texCoordY,
+ TString *texCoordZ)
+{
+ if (textureFunction.proj)
+ {
+ TString proj("");
+ switch (textureFunction.coords)
+ {
+ case 3:
+ proj = " / t.z";
+ break;
+ case 4:
+ proj = " / t.w";
+ break;
+ default:
+ UNREACHABLE();
+ }
+ *texCoordX = "(" + *texCoordX + proj + ")";
+ *texCoordY = "(" + *texCoordY + proj + ")";
+ *texCoordZ = "(" + *texCoordZ + proj + ")";
+ }
+}
+
+void OutputIntegerTextureSampleFunctionComputations(
+ TInfoSinkBase &out,
+ const TextureFunctionHLSL::TextureFunction &textureFunction,
+ const ShShaderOutput outputType,
+ const TString &textureReference,
+ TString *texCoordX,
+ TString *texCoordY,
+ TString *texCoordZ)
+{
+ if (!IsIntegerSampler(textureFunction.sampler))
+ {
+ return;
+ }
+ if (IsSamplerCube(textureFunction.sampler))
+ {
+ out << " float width; float height; float layers; float levels;\n";
+
+ out << " uint mip = 0;\n";
+
+ out << " " << textureReference
+ << ".GetDimensions(mip, width, height, layers, levels);\n";
+
+ out << " bool xMajor = abs(t.x) > abs(t.y) && abs(t.x) > abs(t.z);\n";
+ out << " bool yMajor = abs(t.y) > abs(t.z) && abs(t.y) > abs(t.x);\n";
+ out << " bool zMajor = abs(t.z) > abs(t.x) && abs(t.z) > abs(t.y);\n";
+ out << " bool negative = (xMajor && t.x < 0.0f) || (yMajor && t.y < 0.0f) || "
+ "(zMajor && t.z < 0.0f);\n";
+
+ // FACE_POSITIVE_X = 000b
+ // FACE_NEGATIVE_X = 001b
+ // FACE_POSITIVE_Y = 010b
+ // FACE_NEGATIVE_Y = 011b
+ // FACE_POSITIVE_Z = 100b
+ // FACE_NEGATIVE_Z = 101b
+ out << " int face = (int)negative + (int)yMajor * 2 + (int)zMajor * 4;\n";
+
+ out << " float u = xMajor ? -t.z : (yMajor && t.y < 0.0f ? -t.x : t.x);\n";
+ out << " float v = yMajor ? t.z : (negative ? t.y : -t.y);\n";
+ out << " float m = xMajor ? t.x : (yMajor ? t.y : t.z);\n";
+
+ out << " t.x = (u * 0.5f / m) + 0.5f;\n";
+ out << " t.y = (v * 0.5f / m) + 0.5f;\n";
+
+ // Mip level computation.
+ if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT ||
+ textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD ||
+ textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
+ {
+ if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT)
+ {
+ out << " float2 tSized = float2(t.x * width, t.y * height);\n"
+ " float2 dx = ddx(tSized);\n"
+ " float2 dy = ddy(tSized);\n"
+ " float lod = 0.5f * log2(max(dot(dx, dx), dot(dy, dy)));\n";
+ }
+ else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
+ {
+ // ESSL 3.00.6 spec section 8.8: "For the cube version, the partial
+ // derivatives of P are assumed to be in the coordinate system used before
+ // texture coordinates are projected onto the appropriate cube face."
+ // ddx[0] and ddy[0] are the derivatives of t.x passed into the function
+ // ddx[1] and ddy[1] are the derivatives of t.y passed into the function
+ // ddx[2] and ddy[2] are the derivatives of t.z passed into the function
+ // Determine the derivatives of u, v and m
+ out << " float dudx = xMajor ? ddx[2] : (yMajor && t.y < 0.0f ? -ddx[0] "
+ ": ddx[0]);\n"
+ " float dudy = xMajor ? ddy[2] : (yMajor && t.y < 0.0f ? -ddy[0] "
+ ": ddy[0]);\n"
+ " float dvdx = yMajor ? ddx[2] : (negative ? ddx[1] : -ddx[1]);\n"
+ " float dvdy = yMajor ? ddy[2] : (negative ? ddy[1] : -ddy[1]);\n"
+ " float dmdx = xMajor ? ddx[0] : (yMajor ? ddx[1] : ddx[2]);\n"
+ " float dmdy = xMajor ? ddy[0] : (yMajor ? ddy[1] : ddy[2]);\n";
+ // Now determine the derivatives of the face coordinates, using the
+ // derivatives calculated above.
+ // d / dx (u(x) * 0.5 / m(x) + 0.5)
+ // = 0.5 * (m(x) * u'(x) - u(x) * m'(x)) / m(x)^2
+ out << " float dfacexdx = 0.5f * (m * dudx - u * dmdx) / (m * m);\n"
+ " float dfaceydx = 0.5f * (m * dvdx - v * dmdx) / (m * m);\n"
+ " float dfacexdy = 0.5f * (m * dudy - u * dmdy) / (m * m);\n"
+ " float dfaceydy = 0.5f * (m * dvdy - v * dmdy) / (m * m);\n"
+ " float2 sizeVec = float2(width, height);\n"
+ " float2 faceddx = float2(dfacexdx, dfaceydx) * sizeVec;\n"
+ " float2 faceddy = float2(dfacexdy, dfaceydy) * sizeVec;\n";
+ // Optimization: instead of: log2(max(length(faceddx), length(faceddy)))
+ // we compute: log2(max(length(faceddx)^2, length(faceddy)^2)) / 2
+ out << " float lengthfaceddx2 = dot(faceddx, faceddx);\n"
+ " float lengthfaceddy2 = dot(faceddy, faceddy);\n"
+ " float lod = log2(max(lengthfaceddx2, lengthfaceddy2)) * 0.5f;\n";
+ }
+ out << " mip = uint(min(max(round(lod), 0), levels - 1));\n"
+ << " " << textureReference
+ << ".GetDimensions(mip, width, height, layers, levels);\n";
+ }
+
+ // Convert from normalized floating-point to integer
+ *texCoordX = "int(floor(width * frac(" + *texCoordX + ")))";
+ *texCoordY = "int(floor(height * frac(" + *texCoordY + ")))";
+ *texCoordZ = "face";
+ }
+ else if (textureFunction.method != TextureFunctionHLSL::TextureFunction::FETCH)
+ {
+ if (IsSampler2D(textureFunction.sampler))
+ {
+ if (IsSamplerArray(textureFunction.sampler))
+ {
+ out << " float width; float height; float layers; float levels;\n";
+
+ if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0)
+ {
+ out << " uint mip = 0;\n";
+ }
+ else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS)
+ {
+ out << " uint mip = bias;\n";
+ }
+ else
+ {
+
+ out << " " << textureReference
+ << ".GetDimensions(0, width, height, layers, levels);\n";
+ if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT ||
+ textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
+ {
+ out << " float2 tSized = float2(t.x * width, t.y * height);\n"
+ " float dx = length(ddx(tSized));\n"
+ " float dy = length(ddy(tSized));\n"
+ " float lod = log2(max(dx, dy));\n";
+
+ if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
+ {
+ out << " lod += bias;\n";
+ }
+ }
+ else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
+ {
+ out << " float2 sizeVec = float2(width, height);\n"
+ " float2 sizeDdx = ddx * sizeVec;\n"
+ " float2 sizeDdy = ddy * sizeVec;\n"
+ " float lod = log2(max(dot(sizeDdx, sizeDdx), "
+ "dot(sizeDdy, sizeDdy))) * 0.5f;\n";
+ }
+
+ out << " uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
+ }
+
+ out << " " << textureReference
+ << ".GetDimensions(mip, width, height, layers, levels);\n";
+ }
+ else
+ {
+ out << " float width; float height; float levels;\n";
+
+ if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0)
+ {
+ out << " uint mip = 0;\n";
+ }
+ else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS)
+ {
+ out << " uint mip = bias;\n";
+ }
+ else
+ {
+ out << " " << textureReference
+ << ".GetDimensions(0, width, height, levels);\n";
+
+ if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT ||
+ textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
+ {
+ out << " float2 tSized = float2(t.x * width, t.y * height);\n"
+ " float dx = length(ddx(tSized));\n"
+ " float dy = length(ddy(tSized));\n"
+ " float lod = log2(max(dx, dy));\n";
+
+ if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
+ {
+ out << " lod += bias;\n";
+ }
+ }
+ else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
+ {
+ out << " float2 sizeVec = float2(width, height);\n"
+ " float2 sizeDdx = ddx * sizeVec;\n"
+ " float2 sizeDdy = ddy * sizeVec;\n"
+ " float lod = log2(max(dot(sizeDdx, sizeDdx), "
+ "dot(sizeDdy, sizeDdy))) * 0.5f;\n";
+ }
+
+ out << " uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
+ }
+
+ out << " " << textureReference
+ << ".GetDimensions(mip, width, height, levels);\n";
+ }
+ }
+ else if (IsSampler3D(textureFunction.sampler))
+ {
+ out << " float width; float height; float depth; float levels;\n";
+
+ if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0)
+ {
+ out << " uint mip = 0;\n";
+ }
+ else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS)
+ {
+ out << " uint mip = bias;\n";
+ }
+ else
+ {
+ out << " " << textureReference
+ << ".GetDimensions(0, width, height, depth, levels);\n";
+
+ if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT ||
+ textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
+ {
+ out << " float3 tSized = float3(t.x * width, t.y * height, t.z * depth);\n"
+ " float dx = length(ddx(tSized));\n"
+ " float dy = length(ddy(tSized));\n"
+ " float lod = log2(max(dx, dy));\n";
+
+ if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
+ {
+ out << " lod += bias;\n";
+ }
+ }
+ else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
+ {
+ out << " float3 sizeVec = float3(width, height, depth);\n"
+ " float3 sizeDdx = ddx * sizeVec;\n"
+ " float3 sizeDdy = ddy * sizeVec;\n"
+ " float lod = log2(max(dot(sizeDdx, sizeDdx), dot(sizeDdy, "
+ "sizeDdy))) * 0.5f;\n";
+ }
+
+ out << " uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
+ }
+
+ out << " " << textureReference
+ << ".GetDimensions(mip, width, height, depth, levels);\n";
+ }
+ else
+ UNREACHABLE();
+
+ OutputIntTexCoordWraps(out, textureFunction, texCoordX, texCoordY, texCoordZ);
+ }
+}
+
+void OutputTextureSampleFunctionReturnStatement(
+ TInfoSinkBase &out,
+ const TextureFunctionHLSL::TextureFunction &textureFunction,
+ const ShShaderOutput outputType,
+ const TString &textureReference,
+ const TString &samplerReference,
+ const TString &texCoordX,
+ const TString &texCoordY,
+ const TString &texCoordZ)
+{
+ out << " return ";
+
+ // HLSL intrinsic
+ if (outputType == SH_HLSL_3_0_OUTPUT)
+ {
+ switch (textureFunction.sampler)
+ {
+ case EbtSampler2D:
+ case EbtSamplerExternalOES:
+ out << "tex2D";
+ break;
+ case EbtSamplerCube:
+ out << "texCUBE";
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ switch (textureFunction.method)
+ {
+ case TextureFunctionHLSL::TextureFunction::IMPLICIT:
+ out << "(" << samplerReference << ", ";
+ break;
+ case TextureFunctionHLSL::TextureFunction::BIAS:
+ out << "bias(" << samplerReference << ", ";
+ break;
+ case TextureFunctionHLSL::TextureFunction::LOD:
+ out << "lod(" << samplerReference << ", ";
+ break;
+ case TextureFunctionHLSL::TextureFunction::LOD0:
+ out << "lod(" << samplerReference << ", ";
+ break;
+ case TextureFunctionHLSL::TextureFunction::LOD0BIAS:
+ out << "lod(" << samplerReference << ", ";
+ break;
+ case TextureFunctionHLSL::TextureFunction::GRAD:
+ out << "grad(" << samplerReference << ", ";
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ else if (outputType == SH_HLSL_4_1_OUTPUT || outputType == SH_HLSL_4_0_FL9_3_OUTPUT)
+ {
+ OutputHLSL4SampleFunctionPrefix(out, textureFunction, textureReference, samplerReference);
+ }
+ else
+ UNREACHABLE();
+
+ const int hlslCoords = GetHLSLCoordCount(textureFunction, outputType);
+
+ out << GetSamplerCoordinateTypeString(textureFunction, hlslCoords) << "(" << texCoordX << ", "
+ << texCoordY;
+
+ if (outputType == SH_HLSL_3_0_OUTPUT)
+ {
+ if (hlslCoords >= 3)
+ {
+ if (textureFunction.coords < 3)
+ {
+ out << ", 0";
+ }
+ else
+ {
+ out << ", " << texCoordZ;
+ }
+ }
+
+ if (hlslCoords == 4)
+ {
+ switch (textureFunction.method)
+ {
+ case TextureFunctionHLSL::TextureFunction::BIAS:
+ out << ", bias";
+ break;
+ case TextureFunctionHLSL::TextureFunction::LOD:
+ out << ", lod";
+ break;
+ case TextureFunctionHLSL::TextureFunction::LOD0:
+ out << ", 0";
+ break;
+ case TextureFunctionHLSL::TextureFunction::LOD0BIAS:
+ out << ", bias";
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ out << ")";
+ }
+ else if (outputType == SH_HLSL_4_1_OUTPUT || outputType == SH_HLSL_4_0_FL9_3_OUTPUT)
+ {
+ if (hlslCoords >= 3)
+ {
+ ASSERT(!IsIntegerSampler(textureFunction.sampler) ||
+ !IsSamplerCube(textureFunction.sampler) || texCoordZ == "face");
+ out << ", " << texCoordZ;
+ }
+
+ if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
+ {
+ if (IsIntegerSampler(textureFunction.sampler))
+ {
+ out << ", mip)";
+ }
+ else if (IsShadowSampler(textureFunction.sampler))
+ {
+ // Compare value
+ if (textureFunction.proj)
+ {
+ // According to ESSL 3.00.4 sec 8.8 p95 on textureProj:
+ // The resulting third component of P' in the shadow forms is used as
+ // Dref
+ out << "), " << texCoordZ;
+ }
+ else
+ {
+ switch (textureFunction.coords)
+ {
+ case 3:
+ out << "), t.z";
+ break;
+ case 4:
+ out << "), t.w";
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ }
+ else
+ {
+ out << "), ddx, ddy";
+ }
+ }
+ else if (IsIntegerSampler(textureFunction.sampler) ||
+ textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH)
+ {
+ if (textureFunction.sampler == EbtSampler2DMS ||
+ textureFunction.sampler == EbtISampler2DMS ||
+ textureFunction.sampler == EbtUSampler2DMS)
+ out << "), index";
+ else
+ out << ", mip)";
+ }
+ else if (IsShadowSampler(textureFunction.sampler))
+ {
+ // Compare value
+ if (textureFunction.proj)
+ {
+ // According to ESSL 3.00.4 sec 8.8 p95 on textureProj:
+ // The resulting third component of P' in the shadow forms is used as Dref
+ out << "), " << texCoordZ;
+ }
+ else
+ {
+ switch (textureFunction.coords)
+ {
+ case 3:
+ out << "), t.z";
+ break;
+ case 4:
+ out << "), t.w";
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ }
+ else
+ {
+ switch (textureFunction.method)
+ {
+ case TextureFunctionHLSL::TextureFunction::IMPLICIT:
+ out << ")";
+ break;
+ case TextureFunctionHLSL::TextureFunction::BIAS:
+ out << "), bias";
+ break;
+ case TextureFunctionHLSL::TextureFunction::LOD:
+ out << "), lod";
+ break;
+ case TextureFunctionHLSL::TextureFunction::LOD0:
+ out << "), 0";
+ break;
+ case TextureFunctionHLSL::TextureFunction::LOD0BIAS:
+ out << "), bias";
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ if (textureFunction.offset &&
+ (!IsIntegerSampler(textureFunction.sampler) ||
+ textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH))
+ {
+ out << ", offset";
+ }
+ }
+ else
+ UNREACHABLE();
+
+ out << ");\n"; // Close the sample function call and return statement
+}
+
+} // Anonymous namespace
+
+TString TextureFunctionHLSL::TextureFunction::name() const
+{
+ TString name = "gl_texture";
+
+ // We need to include full the sampler type in the function name to make the signature unique
+ // on D3D11, where samplers are passed to texture functions as indices.
+ name += TextureTypeSuffix(this->sampler);
+
+ if (proj)
+ {
+ name += "Proj";
+ }
+
+ if (offset)
+ {
+ name += "Offset";
+ }
+
+ switch (method)
+ {
+ case IMPLICIT:
+ break;
+ case BIAS:
+ break; // Extra parameter makes the signature unique
+ case LOD:
+ name += "Lod";
+ break;
+ case LOD0:
+ name += "Lod0";
+ break;
+ case LOD0BIAS:
+ name += "Lod0";
+ break; // Extra parameter makes the signature unique
+ case SIZE:
+ name += "Size";
+ break;
+ case FETCH:
+ name += "Fetch";
+ break;
+ case GRAD:
+ name += "Grad";
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return name;
+}
+
+const char *TextureFunctionHLSL::TextureFunction::getReturnType() const
+{
+ if (method == TextureFunction::SIZE)
+ {
+ switch (sampler)
+ {
+ case EbtSampler2D:
+ case EbtISampler2D:
+ case EbtUSampler2D:
+ case EbtSampler2DShadow:
+ case EbtSamplerCube:
+ case EbtISamplerCube:
+ case EbtUSamplerCube:
+ case EbtSamplerCubeShadow:
+ case EbtSamplerExternalOES:
+ case EbtSampler2DMS:
+ case EbtISampler2DMS:
+ case EbtUSampler2DMS:
+ return "int2";
+ case EbtSampler3D:
+ case EbtISampler3D:
+ case EbtUSampler3D:
+ case EbtSampler2DArray:
+ case EbtISampler2DArray:
+ case EbtUSampler2DArray:
+ case EbtSampler2DArrayShadow:
+ return "int3";
+ default:
+ UNREACHABLE();
+ }
+ }
+ else // Sampling function
+ {
+ switch (sampler)
+ {
+ case EbtSampler2D:
+ case EbtSampler2DMS:
+ case EbtSampler3D:
+ case EbtSamplerCube:
+ case EbtSampler2DArray:
+ case EbtSamplerExternalOES:
+ return "float4";
+ case EbtISampler2D:
+ case EbtISampler2DMS:
+ case EbtISampler3D:
+ case EbtISamplerCube:
+ case EbtISampler2DArray:
+ return "int4";
+ case EbtUSampler2D:
+ case EbtUSampler2DMS:
+ case EbtUSampler3D:
+ case EbtUSamplerCube:
+ case EbtUSampler2DArray:
+ return "uint4";
+ case EbtSampler2DShadow:
+ case EbtSamplerCubeShadow:
+ case EbtSampler2DArrayShadow:
+ return "float";
+ default:
+ UNREACHABLE();
+ }
+ }
+ return "";
+}
+
+bool TextureFunctionHLSL::TextureFunction::operator<(const TextureFunction &rhs) const
+{
+ return std::tie(sampler, coords, proj, offset, method) <
+ std::tie(rhs.sampler, rhs.coords, rhs.proj, rhs.offset, rhs.method);
+}
+
+TString TextureFunctionHLSL::useTextureFunction(const TString &name,
+ TBasicType samplerType,
+ int coords,
+ size_t argumentCount,
+ bool lod0,
+ sh::GLenum shaderType)
+{
+ TextureFunction textureFunction;
+ textureFunction.sampler = samplerType;
+ textureFunction.coords = coords;
+ textureFunction.method = TextureFunction::IMPLICIT;
+ textureFunction.proj = false;
+ textureFunction.offset = false;
+
+ if (name == "texture2D" || name == "textureCube" || name == "texture")
+ {
+ textureFunction.method = TextureFunction::IMPLICIT;
+ }
+ else if (name == "texture2DProj" || name == "textureProj")
+ {
+ textureFunction.method = TextureFunction::IMPLICIT;
+ textureFunction.proj = true;
+ }
+ else if (name == "texture2DLod" || name == "textureCubeLod" || name == "textureLod" ||
+ name == "texture2DLodEXT" || name == "textureCubeLodEXT")
+ {
+ textureFunction.method = TextureFunction::LOD;
+ }
+ else if (name == "texture2DProjLod" || name == "textureProjLod" ||
+ name == "texture2DProjLodEXT")
+ {
+ textureFunction.method = TextureFunction::LOD;
+ textureFunction.proj = true;
+ }
+ else if (name == "textureSize")
+ {
+ textureFunction.method = TextureFunction::SIZE;
+ }
+ else if (name == "textureOffset")
+ {
+ textureFunction.method = TextureFunction::IMPLICIT;
+ textureFunction.offset = true;
+ }
+ else if (name == "textureProjOffset")
+ {
+ textureFunction.method = TextureFunction::IMPLICIT;
+ textureFunction.offset = true;
+ textureFunction.proj = true;
+ }
+ else if (name == "textureLodOffset")
+ {
+ textureFunction.method = TextureFunction::LOD;
+ textureFunction.offset = true;
+ }
+ else if (name == "textureProjLodOffset")
+ {
+ textureFunction.method = TextureFunction::LOD;
+ textureFunction.proj = true;
+ textureFunction.offset = true;
+ }
+ else if (name == "texelFetch")
+ {
+ textureFunction.method = TextureFunction::FETCH;
+ }
+ else if (name == "texelFetchOffset")
+ {
+ textureFunction.method = TextureFunction::FETCH;
+ textureFunction.offset = true;
+ }
+ else if (name == "textureGrad" || name == "texture2DGradEXT")
+ {
+ textureFunction.method = TextureFunction::GRAD;
+ }
+ else if (name == "textureGradOffset")
+ {
+ textureFunction.method = TextureFunction::GRAD;
+ textureFunction.offset = true;
+ }
+ else if (name == "textureProjGrad" || name == "texture2DProjGradEXT" ||
+ name == "textureCubeGradEXT")
+ {
+ textureFunction.method = TextureFunction::GRAD;
+ textureFunction.proj = true;
+ }
+ else if (name == "textureProjGradOffset")
+ {
+ textureFunction.method = TextureFunction::GRAD;
+ textureFunction.proj = true;
+ textureFunction.offset = true;
+ }
+ else
+ UNREACHABLE();
+
+ if (textureFunction.method ==
+ TextureFunction::IMPLICIT) // Could require lod 0 or have a bias argument
+ {
+ size_t mandatoryArgumentCount = 2; // All functions have sampler and coordinate arguments
+
+ if (textureFunction.offset)
+ {
+ mandatoryArgumentCount++;
+ }
+
+ bool bias = (argumentCount > mandatoryArgumentCount); // Bias argument is optional
+
+ if (lod0 || shaderType == GL_VERTEX_SHADER)
+ {
+ if (bias)
+ {
+ textureFunction.method = TextureFunction::LOD0BIAS;
+ }
+ else
+ {
+ textureFunction.method = TextureFunction::LOD0;
+ }
+ }
+ else if (bias)
+ {
+ textureFunction.method = TextureFunction::BIAS;
+ }
+ }
+
+ mUsesTexture.insert(textureFunction);
+ return textureFunction.name();
+}
+
+void TextureFunctionHLSL::textureFunctionHeader(TInfoSinkBase &out,
+ const ShShaderOutput outputType,
+ bool getDimensionsIgnoresBaseLevel)
+{
+ for (const TextureFunction &textureFunction : mUsesTexture)
+ {
+ // Function header
+ out << textureFunction.getReturnType() << " " << textureFunction.name() << "(";
+
+ OutputTextureFunctionArgumentList(out, textureFunction, outputType);
+
+ out << ")\n"
+ "{\n";
+
+ // In some cases we use a variable to store the texture/sampler objects, but to work around
+ // a D3D11 compiler bug related to discard inside a loop that is conditional on texture
+ // sampling we need to call the function directly on references to the texture and sampler
+ // arrays. The bug was found using dEQP-GLES3.functional.shaders.discard*loop_texture*
+ // tests.
+ TString textureReference;
+ TString samplerReference;
+ GetTextureReference(out, textureFunction, outputType, &textureReference, &samplerReference);
+
+ if (textureFunction.method == TextureFunction::SIZE)
+ {
+ OutputTextureSizeFunctionBody(out, textureFunction, textureReference,
+ getDimensionsIgnoresBaseLevel);
+ }
+ else
+ {
+ TString texCoordX("t.x");
+ TString texCoordY("t.y");
+ TString texCoordZ("t.z");
+ ProjectTextureCoordinates(textureFunction, &texCoordX, &texCoordY, &texCoordZ);
+ OutputIntegerTextureSampleFunctionComputations(out, textureFunction, outputType,
+ textureReference, &texCoordX, &texCoordY,
+ &texCoordZ);
+ OutputTextureSampleFunctionReturnStatement(out, textureFunction, outputType,
+ textureReference, samplerReference,
+ texCoordX, texCoordY, texCoordZ);
+ }
+
+ out << "}\n"
+ "\n";
+ }
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.h b/src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.h
new file mode 100644
index 0000000000..68bf8c0898
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/TextureFunctionHLSL.h
@@ -0,0 +1,76 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// TextureFunctionHLSL: Class for writing implementations of ESSL texture functions into HLSL
+// output. Some of the implementations are straightforward and just call the HLSL equivalent of the
+// ESSL texture function, others do more work to emulate ESSL texture sampling or size query
+// behavior.
+//
+
+#ifndef COMPILER_TRANSLATOR_TEXTUREFUNCTIONHLSL_H_
+#define COMPILER_TRANSLATOR_TEXTUREFUNCTIONHLSL_H_
+
+#include <set>
+
+#include "compiler/translator/BaseTypes.h"
+#include "compiler/translator/Common.h"
+#include "compiler/translator/InfoSink.h"
+#include "GLSLANG/ShaderLang.h"
+
+namespace sh
+{
+
+class TextureFunctionHLSL final : angle::NonCopyable
+{
+ public:
+ struct TextureFunction
+ {
+ // See ESSL 3.00.6 section 8.8 for reference about what the different methods below do.
+ enum Method
+ {
+ IMPLICIT, // Mipmap LOD determined implicitly (standard lookup)
+ BIAS,
+ LOD,
+ LOD0,
+ LOD0BIAS,
+ SIZE, // textureSize()
+ FETCH,
+ GRAD
+ };
+
+ TString name() const;
+
+ bool operator<(const TextureFunction &rhs) const;
+
+ const char *getReturnType() const;
+
+ TBasicType sampler;
+ int coords;
+ bool proj;
+ bool offset;
+ Method method;
+ };
+
+ // Returns the name of the texture function implementation to call.
+ // The name that's passed in is the name of the GLSL texture function that it should implement.
+ TString useTextureFunction(const TString &name,
+ TBasicType samplerType,
+ int coords,
+ size_t argumentCount,
+ bool lod0,
+ sh::GLenum shaderType);
+
+ void textureFunctionHeader(TInfoSinkBase &out,
+ const ShShaderOutput outputType,
+ bool getDimensionsIgnoresBaseLevel);
+
+ private:
+ typedef std::set<TextureFunction> TextureFunctionSet;
+ TextureFunctionSet mUsesTexture;
+};
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_TEXTUREFUNCTIONHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp
index 76d006fd11..23c967f944 100644
--- a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp
@@ -12,21 +12,28 @@
#include "compiler/translator/OutputESSL.h"
#include "angle_gl.h"
+namespace sh
+{
+
TranslatorESSL::TranslatorESSL(sh::GLenum type, ShShaderSpec spec)
: TCompiler(type, spec, SH_ESSL_OUTPUT)
{
}
-void TranslatorESSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions)
+void TranslatorESSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu,
+ ShCompileOptions compileOptions)
{
- if (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS)
+ if (compileOptions & SH_EMULATE_ATAN2_FLOAT_FUNCTION)
{
- InitBuiltInFunctionEmulatorForGLSLWorkarounds(emu, getShaderType());
+ InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(emu);
}
}
-void TranslatorESSL::translate(TIntermNode *root, int) {
- TInfoSinkBase& sink = getInfoSink().obj;
+void TranslatorESSL::translate(TIntermBlock *root,
+ ShCompileOptions compileOptions,
+ PerformanceDiagnostics * /*perfDiagnostics*/)
+{
+ TInfoSinkBase &sink = getInfoSink().obj;
int shaderVer = getShaderVersion();
if (shaderVer > 100)
@@ -34,69 +41,144 @@ void TranslatorESSL::translate(TIntermNode *root, int) {
sink << "#version " << shaderVer << " es\n";
}
- writePragma();
-
// Write built-in extension behaviors.
- writeExtensionBehavior();
+ writeExtensionBehavior(compileOptions);
- bool precisionEmulation = getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision;
+ // Write pragmas after extensions because some drivers consider pragmas
+ // like non-preprocessor tokens.
+ writePragma(compileOptions);
+
+ bool precisionEmulation =
+ getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision;
if (precisionEmulation)
{
- EmulatePrecision emulatePrecision(getSymbolTable(), shaderVer);
+ EmulatePrecision emulatePrecision(&getSymbolTable(), shaderVer);
root->traverse(&emulatePrecision);
emulatePrecision.updateTree();
- emulatePrecision.writeEmulationHelpers(sink, SH_ESSL_OUTPUT);
+ emulatePrecision.writeEmulationHelpers(sink, shaderVer, SH_ESSL_OUTPUT);
}
- RecordConstantPrecision(root, getTemporaryIndex());
+ RecordConstantPrecision(root, &getSymbolTable());
// Write emulated built-in functions if needed.
- if (!getBuiltInFunctionEmulator().IsOutputEmpty())
+ if (!getBuiltInFunctionEmulator().isOutputEmpty())
{
sink << "// BEGIN: Generated code for built-in function emulation\n\n";
if (getShaderType() == GL_FRAGMENT_SHADER)
{
sink << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n"
- << "#define webgl_emu_precision highp\n"
+ << "#define emu_precision highp\n"
<< "#else\n"
- << "#define webgl_emu_precision mediump\n"
+ << "#define emu_precision mediump\n"
<< "#endif\n\n";
}
else
{
- sink << "#define webgl_emu_precision highp\n";
+ sink << "#define emu_precision highp\n";
}
- getBuiltInFunctionEmulator().OutputEmulatedFunctions(sink);
+ getBuiltInFunctionEmulator().outputEmulatedFunctions(sink);
sink << "// END: Generated code for built-in function emulation\n\n";
}
// Write array bounds clamping emulation if needed.
getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
+ if (getShaderType() == GL_COMPUTE_SHADER && isComputeShaderLocalSizeDeclared())
+ {
+ const sh::WorkGroupSize &localSize = getComputeShaderLocalSize();
+ sink << "layout (local_size_x=" << localSize[0] << ", local_size_y=" << localSize[1]
+ << ", local_size_z=" << localSize[2] << ") in;\n";
+ }
+
+ if (getShaderType() == GL_GEOMETRY_SHADER_OES)
+ {
+ WriteGeometryShaderLayoutQualifiers(
+ sink, getGeometryShaderInputPrimitiveType(), getGeometryShaderInvocations(),
+ getGeometryShaderOutputPrimitiveType(), getGeometryShaderMaxVertices());
+ }
+
// Write translated shader.
TOutputESSL outputESSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(),
- getSymbolTable(), shaderVer, precisionEmulation);
+ &getSymbolTable(), getShaderType(), shaderVer, precisionEmulation,
+ compileOptions);
+
+ if (compileOptions & SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM)
+ {
+ TName uniformName(TString("ViewID_OVR"));
+ uniformName.setInternal(true);
+ sink << "highp uniform int " << outputESSL.hashName(uniformName) << ";\n";
+ }
+
root->traverse(&outputESSL);
}
-void TranslatorESSL::writeExtensionBehavior() {
- TInfoSinkBase& sink = getInfoSink().obj;
- const TExtensionBehavior& extBehavior = getExtensionBehavior();
- for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
- iter != extBehavior.end(); ++iter) {
- if (iter->second != EBhUndefined) {
- if (getResources().NV_shader_framebuffer_fetch && iter->first == "GL_EXT_shader_framebuffer_fetch") {
+bool TranslatorESSL::shouldFlattenPragmaStdglInvariantAll()
+{
+ // Not necessary when translating to ESSL.
+ return false;
+}
+
+void TranslatorESSL::writeExtensionBehavior(ShCompileOptions compileOptions)
+{
+ TInfoSinkBase &sink = getInfoSink().obj;
+ const TExtensionBehavior &extBehavior = getExtensionBehavior();
+ const bool isMultiviewExtEmulated =
+ (compileOptions &
+ (SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM | SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW |
+ SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER)) != 0u;
+ for (TExtensionBehavior::const_iterator iter = extBehavior.begin(); iter != extBehavior.end();
+ ++iter)
+ {
+ if (iter->second != EBhUndefined)
+ {
+ const bool isMultiview = (iter->first == TExtension::OVR_multiview);
+ if (getResources().NV_shader_framebuffer_fetch &&
+ iter->first == TExtension::EXT_shader_framebuffer_fetch)
+ {
sink << "#extension GL_NV_shader_framebuffer_fetch : "
- << getBehaviorString(iter->second) << "\n";
- } else if (getResources().NV_draw_buffers && iter->first == "GL_EXT_draw_buffers") {
- sink << "#extension GL_NV_draw_buffers : "
- << getBehaviorString(iter->second) << "\n";
- } else {
- sink << "#extension " << iter->first << " : "
- << getBehaviorString(iter->second) << "\n";
+ << GetBehaviorString(iter->second) << "\n";
+ }
+ else if (getResources().NV_draw_buffers && iter->first == TExtension::EXT_draw_buffers)
+ {
+ sink << "#extension GL_NV_draw_buffers : " << GetBehaviorString(iter->second)
+ << "\n";
+ }
+ else if (isMultiview && isMultiviewExtEmulated)
+ {
+ if (getShaderType() == GL_VERTEX_SHADER &&
+ (compileOptions & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER) != 0u)
+ {
+ // Emit the NV_viewport_array2 extension in a vertex shader if the
+ // SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set and the
+ // OVR_multiview(2) extension is requested.
+ sink << "#extension GL_NV_viewport_array2 : require\n";
+ }
+ }
+ else if (iter->first == TExtension::OES_geometry_shader)
+ {
+ sink << "#ifdef GL_OES_geometry_shader\n"
+ << "#extension GL_OES_geometry_shader : " << GetBehaviorString(iter->second)
+ << "\n"
+ << "#elif defined GL_EXT_geometry_shader\n"
+ << "#extension GL_EXT_geometry_shader : " << GetBehaviorString(iter->second)
+ << "\n";
+ if (iter->second == EBhRequire)
+ {
+ sink << "#else\n"
+ << "#error \"No geometry shader extensions available.\" // Only generate "
+ "this if the extension is \"required\"\n";
+ }
+ sink << "#endif\n";
+ }
+ else
+ {
+ sink << "#extension " << GetExtensionNameString(iter->first) << " : "
+ << GetBehaviorString(iter->second) << "\n";
}
}
}
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h
index 2cc61074d4..24dc738513 100644
--- a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h
@@ -9,18 +9,27 @@
#include "compiler/translator/Compiler.h"
+namespace sh
+{
+
class TranslatorESSL : public TCompiler
{
public:
TranslatorESSL(sh::GLenum type, ShShaderSpec spec);
protected:
- void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions) override;
+ void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu,
+ ShCompileOptions compileOptions) override;
- void translate(TIntermNode *root, int compileOptions) override;
+ void translate(TIntermBlock *root,
+ ShCompileOptions compileOptions,
+ PerformanceDiagnostics *perfDiagnostics) override;
+ bool shouldFlattenPragmaStdglInvariantAll() override;
private:
- void writeExtensionBehavior();
+ void writeExtensionBehavior(ShCompileOptions compileOptions);
};
+} // namespace sh
+
#endif // COMPILER_TRANSLATOR_TRANSLATORESSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp
index 05e9eb310b..a14e69e5d5 100644
--- a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp
@@ -11,53 +11,116 @@
#include "compiler/translator/EmulatePrecision.h"
#include "compiler/translator/ExtensionGLSL.h"
#include "compiler/translator/OutputGLSL.h"
+#include "compiler/translator/RewriteTexelFetchOffset.h"
+#include "compiler/translator/RewriteUnaryMinusOperatorFloat.h"
#include "compiler/translator/VersionGLSL.h"
-TranslatorGLSL::TranslatorGLSL(sh::GLenum type,
- ShShaderSpec spec,
- ShShaderOutput output)
- : TCompiler(type, spec, output) {
+namespace sh
+{
+
+TranslatorGLSL::TranslatorGLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
+ : TCompiler(type, spec, output)
+{
}
-void TranslatorGLSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions)
+void TranslatorGLSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu,
+ ShCompileOptions compileOptions)
{
- if (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS)
+ if (compileOptions & SH_EMULATE_ABS_INT_FUNCTION)
+ {
+ InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(emu, getShaderType());
+ }
+
+ if (compileOptions & SH_EMULATE_ISNAN_FLOAT_FUNCTION)
{
- InitBuiltInFunctionEmulatorForGLSLWorkarounds(emu, getShaderType());
+ InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(emu, getShaderVersion());
+ }
+
+ if (compileOptions & SH_EMULATE_ATAN2_FLOAT_FUNCTION)
+ {
+ InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(emu);
}
int targetGLSLVersion = ShaderOutputTypeToGLSLVersion(getOutputType());
InitBuiltInFunctionEmulatorForGLSLMissingFunctions(emu, getShaderType(), targetGLSLVersion);
}
-void TranslatorGLSL::translate(TIntermNode *root, int compileOptions)
+void TranslatorGLSL::translate(TIntermBlock *root,
+ ShCompileOptions compileOptions,
+ PerformanceDiagnostics * /*perfDiagnostics*/)
{
- TInfoSinkBase& sink = getInfoSink().obj;
+ TInfoSinkBase &sink = getInfoSink().obj;
// Write GLSL version.
writeVersion(root);
- writePragma();
-
// Write extension behaviour as needed
- writeExtensionBehavior(root);
+ writeExtensionBehavior(root, compileOptions);
+
+ // Write pragmas after extensions because some drivers consider pragmas
+ // like non-preprocessor tokens.
+ writePragma(compileOptions);
+
+ // If flattening the global invariant pragma, write invariant declarations for built-in
+ // variables. It should be harmless to do this twice in the case that the shader also explicitly
+ // did this. However, it's important to emit invariant qualifiers only for those built-in
+ // variables that are actually used, to avoid affecting the behavior of the shader.
+ if ((compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) != 0 &&
+ getPragma().stdgl.invariantAll &&
+ !sh::RemoveInvariant(getShaderType(), getShaderVersion(), getOutputType(), compileOptions))
+ {
+ ASSERT(wereVariablesCollected());
+
+ switch (getShaderType())
+ {
+ case GL_VERTEX_SHADER:
+ sink << "invariant gl_Position;\n";
- bool precisionEmulation = getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision;
+ // gl_PointSize should be declared invariant in both ESSL 1.00 and 3.00 fragment
+ // shaders if it's statically referenced.
+ conditionallyOutputInvariantDeclaration("gl_PointSize");
+ break;
+ case GL_FRAGMENT_SHADER:
+ // The preprocessor will reject this pragma if it's used in ESSL 3.00 fragment
+ // shaders, so we can use simple logic to determine whether to declare these
+ // variables invariant.
+ conditionallyOutputInvariantDeclaration("gl_FragCoord");
+ conditionallyOutputInvariantDeclaration("gl_PointCoord");
+ break;
+ default:
+ // Currently not reached, but leave this in for future expansion.
+ ASSERT(false);
+ break;
+ }
+ }
+
+ if ((compileOptions & SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH) != 0)
+ {
+ sh::RewriteTexelFetchOffset(root, getSymbolTable(), getShaderVersion());
+ }
+
+ if ((compileOptions & SH_REWRITE_FLOAT_UNARY_MINUS_OPERATOR) != 0)
+ {
+ sh::RewriteUnaryMinusOperatorFloat(root);
+ }
+
+ bool precisionEmulation =
+ getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision;
if (precisionEmulation)
{
- EmulatePrecision emulatePrecision(getSymbolTable(), getShaderVersion());
+ EmulatePrecision emulatePrecision(&getSymbolTable(), getShaderVersion());
root->traverse(&emulatePrecision);
emulatePrecision.updateTree();
- emulatePrecision.writeEmulationHelpers(sink, getOutputType());
+ emulatePrecision.writeEmulationHelpers(sink, getShaderVersion(), getOutputType());
}
// Write emulated built-in functions if needed.
- if (!getBuiltInFunctionEmulator().IsOutputEmpty())
+ if (!getBuiltInFunctionEmulator().isOutputEmpty())
{
sink << "// BEGIN: Generated code for built-in function emulation\n\n";
- sink << "#define webgl_emu_precision\n\n";
- getBuiltInFunctionEmulator().OutputEmulatedFunctions(sink);
+ sink << "#define emu_precision\n\n";
+ getBuiltInFunctionEmulator().outputEmulatedFunctions(sink);
sink << "// END: Generated code for built-in function emulation\n\n";
}
@@ -69,7 +132,7 @@ void TranslatorGLSL::translate(TIntermNode *root, int compileOptions)
if (getShaderType() == GL_FRAGMENT_SHADER)
{
const bool mayHaveESSL1SecondaryOutputs =
- IsExtensionEnabled(getExtensionBehavior(), "GL_EXT_blend_func_extended") &&
+ IsExtensionEnabled(getExtensionBehavior(), TExtension::EXT_blend_func_extended) &&
getShaderVersion() == 100;
const bool declareGLFragmentOutputs = IsGLSL130OrNewer(getOutputType());
@@ -132,17 +195,48 @@ void TranslatorGLSL::translate(TIntermNode *root, int compileOptions)
}
}
+ if (getShaderType() == GL_COMPUTE_SHADER && isComputeShaderLocalSizeDeclared())
+ {
+ const sh::WorkGroupSize &localSize = getComputeShaderLocalSize();
+ sink << "layout (local_size_x=" << localSize[0] << ", local_size_y=" << localSize[1]
+ << ", local_size_z=" << localSize[2] << ") in;\n";
+ }
+
+ if (getShaderType() == GL_GEOMETRY_SHADER_OES)
+ {
+ WriteGeometryShaderLayoutQualifiers(
+ sink, getGeometryShaderInputPrimitiveType(), getGeometryShaderInvocations(),
+ getGeometryShaderOutputPrimitiveType(), getGeometryShaderMaxVertices());
+ }
+
// Write translated shader.
- TOutputGLSL outputGLSL(sink,
- getArrayIndexClampingStrategy(),
- getHashFunction(),
- getNameMap(),
- getSymbolTable(),
- getShaderVersion(),
- getOutputType());
+ TOutputGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(),
+ &getSymbolTable(), getShaderType(), getShaderVersion(), getOutputType(),
+ compileOptions);
+
+ if (compileOptions & SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM)
+ {
+ TName uniformName(TString("ViewID_OVR"));
+ uniformName.setInternal(true);
+ sink << "uniform int " << outputGLSL.hashName(uniformName) << ";\n";
+ }
+
root->traverse(&outputGLSL);
}
+bool TranslatorGLSL::shouldFlattenPragmaStdglInvariantAll()
+{
+ // Required when outputting to any GLSL version greater than 1.20, but since ANGLE doesn't
+ // translate to that version, return true for the next higher version.
+ return IsGLSL130OrNewer(getOutputType());
+}
+
+bool TranslatorGLSL::shouldCollectVariables(ShCompileOptions compileOptions)
+{
+ return (compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) ||
+ TCompiler::shouldCollectVariables(compileOptions);
+}
+
void TranslatorGLSL::writeVersion(TIntermNode *root)
{
TVersionGLSL versionGLSL(getShaderType(), getPragma(), getOutputType());
@@ -152,15 +246,15 @@ void TranslatorGLSL::writeVersion(TIntermNode *root)
// If there is no version directive in the shader, 110 is implied.
if (version > 110)
{
- TInfoSinkBase& sink = getInfoSink().obj;
+ TInfoSinkBase &sink = getInfoSink().obj;
sink << "#version " << version << "\n";
}
}
-void TranslatorGLSL::writeExtensionBehavior(TIntermNode *root)
+void TranslatorGLSL::writeExtensionBehavior(TIntermNode *root, ShCompileOptions compileOptions)
{
- TInfoSinkBase& sink = getInfoSink().obj;
- const TExtensionBehavior& extBehavior = getExtensionBehavior();
+ TInfoSinkBase &sink = getInfoSink().obj;
+ const TExtensionBehavior &extBehavior = getExtensionBehavior();
for (const auto &iter : extBehavior)
{
if (iter.second == EBhUndefined)
@@ -168,21 +262,58 @@ void TranslatorGLSL::writeExtensionBehavior(TIntermNode *root)
continue;
}
- // For GLSL output, we don't need to emit most extensions explicitly,
- // but some we need to translate.
- if (iter.first == "GL_EXT_shader_texture_lod")
+ if (getOutputType() == SH_GLSL_COMPATIBILITY_OUTPUT)
+ {
+ // For GLSL output, we don't need to emit most extensions explicitly,
+ // but some we need to translate in GL compatibility profile.
+ if (iter.first == TExtension::EXT_shader_texture_lod)
+ {
+ sink << "#extension GL_ARB_shader_texture_lod : " << GetBehaviorString(iter.second)
+ << "\n";
+ }
+
+ if (iter.first == TExtension::EXT_draw_buffers)
+ {
+ sink << "#extension GL_ARB_draw_buffers : " << GetBehaviorString(iter.second)
+ << "\n";
+ }
+
+ if (iter.first == TExtension::OES_geometry_shader)
+ {
+ sink << "#extension GL_ARB_geometry_shader4 : " << GetBehaviorString(iter.second)
+ << "\n";
+ }
+ }
+
+ const bool isMultiview = (iter.first == TExtension::OVR_multiview);
+ if (isMultiview && getShaderType() == GL_VERTEX_SHADER &&
+ (compileOptions & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER) != 0u)
{
- sink << "#extension GL_ARB_shader_texture_lod : " << getBehaviorString(iter.second)
- << "\n";
+ // Emit the NV_viewport_array2 extension in a vertex shader if the
+ // SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set and the OVR_multiview(2)
+ // extension is requested.
+ sink << "#extension GL_NV_viewport_array2 : require\n";
}
}
// GLSL ES 3 explicit location qualifiers need to use an extension before GLSL 330
- if (getShaderVersion() >= 300 && getOutputType() < SH_GLSL_330_CORE_OUTPUT)
+ if (getShaderVersion() >= 300 && getOutputType() < SH_GLSL_330_CORE_OUTPUT &&
+ getShaderType() != GL_COMPUTE_SHADER)
{
sink << "#extension GL_ARB_explicit_attrib_location : require\n";
}
+ // Need to enable gpu_shader5 to have index constant sampler array indexing
+ if (getOutputType() != SH_ESSL_OUTPUT && getOutputType() < SH_GLSL_400_CORE_OUTPUT &&
+ getShaderVersion() == 100)
+ {
+ // Don't use "require" on to avoid breaking WebGL 1 on drivers that silently
+ // support index constant sampler array indexing, but don't have the extension or
+ // on drivers that don't have the extension at all as it would break WebGL 1 for
+ // some users.
+ sink << "#extension GL_ARB_gpu_shader5 : enable\n";
+ }
+
TExtensionGLSL extensionGLSL(getOutputType());
root->traverse(&extensionGLSL);
@@ -195,3 +326,14 @@ void TranslatorGLSL::writeExtensionBehavior(TIntermNode *root)
sink << "#extension " << ext << " : require\n";
}
}
+
+void TranslatorGLSL::conditionallyOutputInvariantDeclaration(const char *builtinVaryingName)
+{
+ if (isVaryingDefined(builtinVaryingName))
+ {
+ TInfoSinkBase &sink = getInfoSink().obj;
+ sink << "invariant " << builtinVaryingName << ";\n";
+ }
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h
index 4f07b21980..982d0e5ddc 100644
--- a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h
@@ -9,19 +9,30 @@
#include "compiler/translator/Compiler.h"
+namespace sh
+{
+
class TranslatorGLSL : public TCompiler
{
public:
TranslatorGLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output);
protected:
- void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions) override;
+ void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu,
+ ShCompileOptions compileOptions) override;
- void translate(TIntermNode *root, int compileOptions) override;
+ void translate(TIntermBlock *root,
+ ShCompileOptions compileOptions,
+ PerformanceDiagnostics *perfDiagnostics) override;
+ bool shouldFlattenPragmaStdglInvariantAll() override;
+ bool shouldCollectVariables(ShCompileOptions compileOptions) override;
private:
void writeVersion(TIntermNode *root);
- void writeExtensionBehavior(TIntermNode *root);
+ void writeExtensionBehavior(TIntermNode *root, ShCompileOptions compileOptions);
+ void conditionallyOutputInvariantDeclaration(const char *builtinVaryingName);
};
+} // namespace sh
+
#endif // COMPILER_TRANSLATOR_TRANSLATORGLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp
index c5d18d21bf..091a649cfc 100644
--- a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp
@@ -6,79 +6,156 @@
#include "compiler/translator/TranslatorHLSL.h"
+#include "compiler/translator/AddDefaultReturnStatements.h"
#include "compiler/translator/ArrayReturnValueToOutParameter.h"
+#include "compiler/translator/BreakVariableAliasingInInnerLoops.h"
+#include "compiler/translator/EmulatePrecision.h"
+#include "compiler/translator/ExpandIntegerPowExpressions.h"
+#include "compiler/translator/IntermNodePatternMatcher.h"
#include "compiler/translator/OutputHLSL.h"
#include "compiler/translator/RemoveDynamicIndexing.h"
+#include "compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h"
#include "compiler/translator/RewriteElseBlocks.h"
+#include "compiler/translator/RewriteTexelFetchOffset.h"
+#include "compiler/translator/RewriteUnaryMinusOperatorInt.h"
#include "compiler/translator/SeparateArrayInitialization.h"
#include "compiler/translator/SeparateDeclarations.h"
#include "compiler/translator/SeparateExpressionsReturningArrays.h"
+#include "compiler/translator/SimplifyLoopConditions.h"
+#include "compiler/translator/SplitSequenceOperator.h"
#include "compiler/translator/UnfoldShortCircuitToIf.h"
+#include "compiler/translator/WrapSwitchStatementsInBlocks.h"
+
+namespace sh
+{
TranslatorHLSL::TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
: TCompiler(type, spec, output)
{
}
-void TranslatorHLSL::translate(TIntermNode *root, int compileOptions)
+void TranslatorHLSL::translate(TIntermBlock *root,
+ ShCompileOptions compileOptions,
+ PerformanceDiagnostics *perfDiagnostics)
{
const ShBuiltInResources &resources = getResources();
- int numRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1;
+ int numRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1;
+
+ sh::AddDefaultReturnStatements(root);
- SeparateDeclarations(root);
+ // Note that SimplifyLoopConditions needs to be run before any other AST transformations that
+ // may need to generate new statements from loop conditions or loop expressions.
+ // Note that SeparateDeclarations has already been run in TCompiler::compileTreeImpl().
+ SimplifyLoopConditions(root,
+ IntermNodePatternMatcher::kExpressionReturningArray |
+ IntermNodePatternMatcher::kUnfoldedShortCircuitExpression |
+ IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue,
+ &getSymbolTable(), getShaderVersion());
+
+ SplitSequenceOperator(root,
+ IntermNodePatternMatcher::kExpressionReturningArray |
+ IntermNodePatternMatcher::kUnfoldedShortCircuitExpression |
+ IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue,
+ &getSymbolTable(), getShaderVersion());
// Note that SeparateDeclarations needs to be run before UnfoldShortCircuitToIf.
- UnfoldShortCircuitToIf(root, getTemporaryIndex());
+ UnfoldShortCircuitToIf(root, &getSymbolTable());
- SeparateExpressionsReturningArrays(root, getTemporaryIndex());
+ SeparateExpressionsReturningArrays(root, &getSymbolTable());
// Note that SeparateDeclarations needs to be run before SeparateArrayInitialization.
SeparateArrayInitialization(root);
// HLSL doesn't support arrays as return values, we'll need to make functions that have an array
// as a return value to use an out parameter to transfer the array data instead.
- ArrayReturnValueToOutParameter(root, getTemporaryIndex());
+ ArrayReturnValueToOutParameter(root, &getSymbolTable());
if (!shouldRunLoopAndIndexingValidation(compileOptions))
{
// HLSL doesn't support dynamic indexing of vectors and matrices.
- RemoveDynamicIndexing(root, getTemporaryIndex(), getSymbolTable(), getShaderVersion());
+ RemoveDynamicIndexing(root, &getSymbolTable(), getShaderVersion(), perfDiagnostics);
}
// Work around D3D9 bug that would manifest in vertex shaders with selection blocks which
// use a vertex attribute as a condition, and some related computation in the else block.
if (getOutputType() == SH_HLSL_3_0_OUTPUT && getShaderType() == GL_VERTEX_SHADER)
{
- sh::RewriteElseBlocks(root, getTemporaryIndex());
+ sh::RewriteElseBlocks(root, &getSymbolTable());
+ }
+
+ // Work around an HLSL compiler frontend aliasing optimization bug.
+ // TODO(cwallez) The date is 2016-08-25, Microsoft said the bug would be fixed
+ // in the next release of d3dcompiler.dll, it would be nice to detect the DLL
+ // version and only apply the workaround if it is too old.
+ sh::BreakVariableAliasingInInnerLoops(root);
+
+ // WrapSwitchStatementsInBlocks should be called after any AST transformations that might
+ // introduce variable declarations inside the main scope of any switch statement.
+ if (WrapSwitchStatementsInBlocks(root))
+ {
+ // The WrapSwitchStatementsInBlocks step might introduce new no-op cases to the end of
+ // switch statements, so make sure to clean up the AST.
+ RemoveNoOpCasesFromEndOfSwitchStatements(root, &getSymbolTable());
+ }
+
+ bool precisionEmulation =
+ getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision;
+
+ if (precisionEmulation)
+ {
+ EmulatePrecision emulatePrecision(&getSymbolTable(), getShaderVersion());
+ root->traverse(&emulatePrecision);
+ emulatePrecision.updateTree();
+ emulatePrecision.writeEmulationHelpers(getInfoSink().obj, getShaderVersion(),
+ getOutputType());
+ }
+
+ if ((compileOptions & SH_EXPAND_SELECT_HLSL_INTEGER_POW_EXPRESSIONS) != 0)
+ {
+ sh::ExpandIntegerPowExpressions(root, &getSymbolTable());
+ }
+
+ if ((compileOptions & SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH) != 0)
+ {
+ sh::RewriteTexelFetchOffset(root, getSymbolTable(), getShaderVersion());
+ }
+
+ if (((compileOptions & SH_REWRITE_INTEGER_UNARY_MINUS_OPERATOR) != 0) &&
+ getShaderType() == GL_VERTEX_SHADER)
+ {
+ sh::RewriteUnaryMinusOperatorInt(root);
}
sh::OutputHLSL outputHLSL(getShaderType(), getShaderVersion(), getExtensionBehavior(),
- getSourcePath(), getOutputType(), numRenderTargets, getUniforms(), compileOptions);
+ getSourcePath(), getOutputType(), numRenderTargets, getUniforms(),
+ compileOptions, &getSymbolTable(), perfDiagnostics);
outputHLSL.output(root, getInfoSink().obj);
- mInterfaceBlockRegisterMap = outputHLSL.getInterfaceBlockRegisterMap();
- mUniformRegisterMap = outputHLSL.getUniformRegisterMap();
+ mUniformBlockRegisterMap = outputHLSL.getUniformBlockRegisterMap();
+ mUniformRegisterMap = outputHLSL.getUniformRegisterMap();
}
-bool TranslatorHLSL::hasInterfaceBlock(const std::string &interfaceBlockName) const
+bool TranslatorHLSL::shouldFlattenPragmaStdglInvariantAll()
{
- return (mInterfaceBlockRegisterMap.count(interfaceBlockName) > 0);
+ // Not necessary when translating to HLSL.
+ return false;
}
-unsigned int TranslatorHLSL::getInterfaceBlockRegister(const std::string &interfaceBlockName) const
+bool TranslatorHLSL::hasUniformBlock(const std::string &uniformBlockName) const
{
- ASSERT(hasInterfaceBlock(interfaceBlockName));
- return mInterfaceBlockRegisterMap.find(interfaceBlockName)->second;
+ return (mUniformBlockRegisterMap.count(uniformBlockName) > 0);
}
-bool TranslatorHLSL::hasUniform(const std::string &uniformName) const
+unsigned int TranslatorHLSL::getUniformBlockRegister(const std::string &uniformBlockName) const
{
- return (mUniformRegisterMap.count(uniformName) > 0);
+ ASSERT(hasUniformBlock(uniformBlockName));
+ return mUniformBlockRegisterMap.find(uniformBlockName)->second;
}
-unsigned int TranslatorHLSL::getUniformRegister(const std::string &uniformName) const
+const std::map<std::string, unsigned int> *TranslatorHLSL::getUniformRegisterMap() const
{
- ASSERT(hasUniform(uniformName));
- return mUniformRegisterMap.find(uniformName)->second;
+ return &mUniformRegisterMap;
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h
index 907d816744..d7005a603c 100644
--- a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h
@@ -9,26 +9,33 @@
#include "compiler/translator/Compiler.h"
+namespace sh
+{
+
class TranslatorHLSL : public TCompiler
{
public:
TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output);
TranslatorHLSL *getAsTranslatorHLSL() override { return this; }
- bool hasInterfaceBlock(const std::string &interfaceBlockName) const;
- unsigned int getInterfaceBlockRegister(const std::string &interfaceBlockName) const;
+ bool hasUniformBlock(const std::string &interfaceBlockName) const;
+ unsigned int getUniformBlockRegister(const std::string &interfaceBlockName) const;
- bool hasUniform(const std::string &uniformName) const;
- unsigned int getUniformRegister(const std::string &uniformName) const;
+ const std::map<std::string, unsigned int> *getUniformRegisterMap() const;
protected:
- void translate(TIntermNode *root, int compileOptions) override;
+ void translate(TIntermBlock *root,
+ ShCompileOptions compileOptions,
+ PerformanceDiagnostics *perfDiagnostics) override;
+ bool shouldFlattenPragmaStdglInvariantAll() override;
// collectVariables needs to be run always so registers can be assigned.
- bool shouldCollectVariables(int compileOptions) override { return true; }
+ bool shouldCollectVariables(ShCompileOptions compileOptions) override { return true; }
- std::map<std::string, unsigned int> mInterfaceBlockRegisterMap;
+ std::map<std::string, unsigned int> mUniformBlockRegisterMap;
std::map<std::string, unsigned int> mUniformRegisterMap;
};
+} // namespace sh
+
#endif // COMPILER_TRANSLATOR_TRANSLATORHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.cpp
new file mode 100644
index 0000000000..0fe2a21f90
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.cpp
@@ -0,0 +1,173 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// TranslatorVulkan:
+// A GLSL-based translator that outputs shaders that fit GL_KHR_vulkan_glsl.
+// The shaders are then fed into glslang to spit out SPIR-V (libANGLE-side).
+// See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt
+//
+
+#include "compiler/translator/TranslatorVulkan.h"
+
+#include "angle_gl.h"
+#include "common/utilities.h"
+#include "compiler/translator/OutputVulkanGLSL.h"
+#include "compiler/translator/util.h"
+
+namespace sh
+{
+
+class DeclareDefaultUniformsTraverser : public TIntermTraverser
+{
+ public:
+ DeclareDefaultUniformsTraverser(TInfoSinkBase *sink,
+ ShHashFunction64 hashFunction,
+ NameMap *nameMap)
+ : TIntermTraverser(true, true, true),
+ mSink(sink),
+ mHashFunction(hashFunction),
+ mNameMap(nameMap),
+ mInDefaultUniform(false)
+ {
+ }
+
+ bool visitDeclaration(Visit visit, TIntermDeclaration *node) override
+ {
+ const TIntermSequence &sequence = *(node->getSequence());
+
+ // TODO(jmadill): Compound declarations.
+ ASSERT(sequence.size() == 1);
+
+ TIntermTyped *variable = sequence.front()->getAsTyped();
+ const TType &type = variable->getType();
+ bool isUniform = (type.getQualifier() == EvqUniform) && !IsOpaqueType(type.getBasicType());
+
+ if (visit == PreVisit)
+ {
+ if (isUniform)
+ {
+ (*mSink) << " " << GetTypeName(type, mHashFunction, mNameMap) << " ";
+ mInDefaultUniform = true;
+ }
+ }
+ else if (visit == InVisit)
+ {
+ mInDefaultUniform = isUniform;
+ }
+ else if (visit == PostVisit)
+ {
+ if (isUniform)
+ {
+ (*mSink) << ";\n";
+
+ // Remove the uniform declaration from the tree so it isn't parsed again.
+ TIntermSequence emptyReplacement;
+ mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(
+ getParentNode()->getAsBlock(), node, emptyReplacement));
+ }
+
+ mInDefaultUniform = false;
+ }
+ return true;
+ }
+
+ void visitSymbol(TIntermSymbol *symbol) override
+ {
+ if (mInDefaultUniform)
+ {
+ const TName &name = symbol->getName();
+ ASSERT(name.getString().substr(0, 3) != "gl_");
+ (*mSink) << HashName(name, mHashFunction, mNameMap);
+ }
+ }
+
+ private:
+ TInfoSinkBase *mSink;
+ ShHashFunction64 mHashFunction;
+ NameMap *mNameMap;
+ bool mInDefaultUniform;
+};
+
+TranslatorVulkan::TranslatorVulkan(sh::GLenum type, ShShaderSpec spec)
+ : TCompiler(type, spec, SH_GLSL_450_CORE_OUTPUT)
+{
+}
+
+void TranslatorVulkan::translate(TIntermBlock *root,
+ ShCompileOptions compileOptions,
+ PerformanceDiagnostics * /*perfDiagnostics*/)
+{
+ TInfoSinkBase &sink = getInfoSink().obj;
+
+ sink << "#version 450 core\n";
+
+ // Write out default uniforms into a uniform block assigned to a specific set/binding.
+ int defaultUniformCount = 0;
+ for (const auto &uniform : getUniforms())
+ {
+ if (!uniform.isBuiltIn() && uniform.staticUse && !gl::IsOpaqueType(uniform.type))
+ {
+ ++defaultUniformCount;
+ }
+ }
+
+ if (defaultUniformCount > 0)
+ {
+ sink << "\nlayout(@@ DEFAULT-UNIFORMS-SET-BINDING @@) uniform defaultUniforms\n{\n";
+
+ DeclareDefaultUniformsTraverser defaultTraverser(&sink, getHashFunction(), &getNameMap());
+ root->traverse(&defaultTraverser);
+ defaultTraverser.updateTree();
+
+ sink << "};\n";
+ }
+
+ // Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData
+ // if it's core profile shaders and they are used.
+ if (getShaderType() == GL_FRAGMENT_SHADER)
+ {
+ bool hasGLFragColor = false;
+ bool hasGLFragData = false;
+
+ for (const auto &outputVar : outputVariables)
+ {
+ if (outputVar.name == "gl_FragColor")
+ {
+ ASSERT(!hasGLFragColor);
+ hasGLFragColor = true;
+ continue;
+ }
+ else if (outputVar.name == "gl_FragData")
+ {
+ ASSERT(!hasGLFragData);
+ hasGLFragData = true;
+ continue;
+ }
+ }
+ ASSERT(!(hasGLFragColor && hasGLFragData));
+ if (hasGLFragColor)
+ {
+ sink << "layout(location = 0) out vec4 webgl_FragColor;\n";
+ }
+ if (hasGLFragData)
+ {
+ sink << "layout(location = 0) out vec4 webgl_FragData[gl_MaxDrawBuffers];\n";
+ }
+ }
+
+ // Write translated shader.
+ TOutputVulkanGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(),
+ getNameMap(), &getSymbolTable(), getShaderType(),
+ getShaderVersion(), getOutputType(), compileOptions);
+ root->traverse(&outputGLSL);
+}
+
+bool TranslatorVulkan::shouldFlattenPragmaStdglInvariantAll()
+{
+ // Not necessary.
+ return false;
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.h b/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.h
new file mode 100644
index 0000000000..ef67b15ae1
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/TranslatorVulkan.h
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// TranslatorVulkan:
+// A GLSL-based translator that outputs shaders that fit GL_KHR_vulkan_glsl.
+// The shaders are then fed into glslang to spit out SPIR-V (libANGLE-side).
+// See: https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt
+//
+
+#ifndef COMPILER_TRANSLATOR_TRANSLATORVULKAN_H_
+#define COMPILER_TRANSLATOR_TRANSLATORVULKAN_H_
+
+#include "compiler/translator/Compiler.h"
+
+namespace sh
+{
+
+class TranslatorVulkan : public TCompiler
+{
+ public:
+ TranslatorVulkan(sh::GLenum type, ShShaderSpec spec);
+
+ protected:
+ void translate(TIntermBlock *root,
+ ShCompileOptions compileOptions,
+ PerformanceDiagnostics *perfDiagnostics) override;
+ bool shouldFlattenPragmaStdglInvariantAll() override;
+};
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_TRANSLATORVULKAN_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/Types.cpp b/src/3rdparty/angle/src/compiler/translator/Types.cpp
index 87fdfe0d54..530ffe3aeb 100644
--- a/src/3rdparty/angle/src/compiler/translator/Types.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/Types.cpp
@@ -5,58 +5,394 @@
//
#if defined(_MSC_VER)
-#pragma warning(disable: 4718)
+#pragma warning(disable : 4718)
#endif
#include "compiler/translator/Types.h"
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/SymbolTable.h"
#include <algorithm>
#include <climits>
-const char* getBasicString(TBasicType t)
+namespace sh
+{
+
+const char *getBasicString(TBasicType t)
{
switch (t)
{
- case EbtVoid: return "void"; break;
- case EbtFloat: return "float"; break;
- case EbtInt: return "int"; break;
- case EbtUInt: return "uint"; break;
- case EbtBool: return "bool"; break;
- case EbtSampler2D: return "sampler2D"; break;
- case EbtSampler3D: return "sampler3D"; break;
- case EbtSamplerCube: return "samplerCube"; break;
- case EbtSamplerExternalOES: return "samplerExternalOES"; break;
- case EbtSampler2DRect: return "sampler2DRect"; break;
- case EbtSampler2DArray: return "sampler2DArray"; break;
- case EbtISampler2D: return "isampler2D"; break;
- case EbtISampler3D: return "isampler3D"; break;
- case EbtISamplerCube: return "isamplerCube"; break;
- case EbtISampler2DArray: return "isampler2DArray"; break;
- case EbtUSampler2D: return "usampler2D"; break;
- case EbtUSampler3D: return "usampler3D"; break;
- case EbtUSamplerCube: return "usamplerCube"; break;
- case EbtUSampler2DArray: return "usampler2DArray"; break;
- case EbtSampler2DShadow: return "sampler2DShadow"; break;
- case EbtSamplerCubeShadow: return "samplerCubeShadow"; break;
- case EbtSampler2DArrayShadow: return "sampler2DArrayShadow"; break;
- case EbtStruct: return "structure"; break;
- case EbtInterfaceBlock: return "interface block"; break;
- default: UNREACHABLE(); return "unknown type";
+ case EbtVoid:
+ return "void";
+ case EbtFloat:
+ return "float";
+ case EbtInt:
+ return "int";
+ case EbtUInt:
+ return "uint";
+ case EbtBool:
+ return "bool";
+ case EbtYuvCscStandardEXT:
+ return "yuvCscStandardEXT";
+ case EbtSampler2D:
+ return "sampler2D";
+ case EbtSampler3D:
+ return "sampler3D";
+ case EbtSamplerCube:
+ return "samplerCube";
+ case EbtSamplerExternalOES:
+ return "samplerExternalOES";
+ case EbtSamplerExternal2DY2YEXT:
+ return "__samplerExternal2DY2YEXT";
+ case EbtSampler2DRect:
+ return "sampler2DRect";
+ case EbtSampler2DArray:
+ return "sampler2DArray";
+ case EbtSampler2DMS:
+ return "sampler2DMS";
+ case EbtISampler2D:
+ return "isampler2D";
+ case EbtISampler3D:
+ return "isampler3D";
+ case EbtISamplerCube:
+ return "isamplerCube";
+ case EbtISampler2DArray:
+ return "isampler2DArray";
+ case EbtISampler2DMS:
+ return "isampler2DMS";
+ case EbtUSampler2D:
+ return "usampler2D";
+ case EbtUSampler3D:
+ return "usampler3D";
+ case EbtUSamplerCube:
+ return "usamplerCube";
+ case EbtUSampler2DArray:
+ return "usampler2DArray";
+ case EbtUSampler2DMS:
+ return "usampler2DMS";
+ case EbtSampler2DShadow:
+ return "sampler2DShadow";
+ case EbtSamplerCubeShadow:
+ return "samplerCubeShadow";
+ case EbtSampler2DArrayShadow:
+ return "sampler2DArrayShadow";
+ case EbtStruct:
+ return "structure";
+ case EbtInterfaceBlock:
+ return "interface block";
+ case EbtImage2D:
+ return "image2D";
+ case EbtIImage2D:
+ return "iimage2D";
+ case EbtUImage2D:
+ return "uimage2D";
+ case EbtImage3D:
+ return "image3D";
+ case EbtIImage3D:
+ return "iimage3D";
+ case EbtUImage3D:
+ return "uimage3D";
+ case EbtImage2DArray:
+ return "image2DArray";
+ case EbtIImage2DArray:
+ return "iimage2DArray";
+ case EbtUImage2DArray:
+ return "uimage2DArray";
+ case EbtImageCube:
+ return "imageCube";
+ case EbtIImageCube:
+ return "iimageCube";
+ case EbtUImageCube:
+ return "uimageCube";
+ case EbtAtomicCounter:
+ return "atomic_uint";
+ default:
+ UNREACHABLE();
+ return "unknown type";
}
}
+// TType implementation.
+TType::TType()
+ : type(EbtVoid),
+ precision(EbpUndefined),
+ qualifier(EvqGlobal),
+ invariant(false),
+ memoryQualifier(TMemoryQualifier::Create()),
+ layoutQualifier(TLayoutQualifier::Create()),
+ primarySize(0),
+ secondarySize(0),
+ mArraySizes(nullptr),
+ mInterfaceBlock(nullptr),
+ mStructure(nullptr),
+ mIsStructSpecifier(false),
+ mMangledName(nullptr)
+{
+}
+
+TType::TType(TBasicType t, unsigned char ps, unsigned char ss)
+ : type(t),
+ precision(EbpUndefined),
+ qualifier(EvqGlobal),
+ invariant(false),
+ memoryQualifier(TMemoryQualifier::Create()),
+ layoutQualifier(TLayoutQualifier::Create()),
+ primarySize(ps),
+ secondarySize(ss),
+ mArraySizes(nullptr),
+ mInterfaceBlock(nullptr),
+ mStructure(nullptr),
+ mIsStructSpecifier(false),
+ mMangledName(nullptr)
+{
+}
+
+TType::TType(TBasicType t, TPrecision p, TQualifier q, unsigned char ps, unsigned char ss)
+ : type(t),
+ precision(p),
+ qualifier(q),
+ invariant(false),
+ memoryQualifier(TMemoryQualifier::Create()),
+ layoutQualifier(TLayoutQualifier::Create()),
+ primarySize(ps),
+ secondarySize(ss),
+ mArraySizes(nullptr),
+ mInterfaceBlock(nullptr),
+ mStructure(nullptr),
+ mIsStructSpecifier(false),
+ mMangledName(nullptr)
+{
+}
+
TType::TType(const TPublicType &p)
- : type(p.type), precision(p.precision), qualifier(p.qualifier), invariant(p.invariant),
- layoutQualifier(p.layoutQualifier), primarySize(p.primarySize), secondarySize(p.secondarySize),
- array(p.array), arraySize(p.arraySize), interfaceBlock(0), structure(0)
+ : type(p.getBasicType()),
+ precision(p.precision),
+ qualifier(p.qualifier),
+ invariant(p.invariant),
+ memoryQualifier(p.memoryQualifier),
+ layoutQualifier(p.layoutQualifier),
+ primarySize(p.getPrimarySize()),
+ secondarySize(p.getSecondarySize()),
+ mArraySizes(nullptr),
+ mInterfaceBlock(nullptr),
+ mStructure(nullptr),
+ mIsStructSpecifier(false),
+ mMangledName(nullptr)
{
- if (p.userDef)
- structure = p.userDef->getStruct();
+ ASSERT(primarySize <= 4);
+ ASSERT(secondarySize <= 4);
+ if (p.isArray())
+ {
+ mArraySizes = new TVector<unsigned int>(*p.arraySizes);
+ }
+ if (p.getUserDef())
+ {
+ mStructure = p.getUserDef();
+ mIsStructSpecifier = p.isStructSpecifier();
+ }
}
-bool TStructure::equals(const TStructure &other) const
+TType::TType(TStructure *userDef)
+ : type(EbtStruct),
+ precision(EbpUndefined),
+ qualifier(EvqTemporary),
+ invariant(false),
+ memoryQualifier(TMemoryQualifier::Create()),
+ layoutQualifier(TLayoutQualifier::Create()),
+ primarySize(1),
+ secondarySize(1),
+ mArraySizes(nullptr),
+ mInterfaceBlock(nullptr),
+ mStructure(userDef),
+ mIsStructSpecifier(false),
+ mMangledName(nullptr)
{
- return (uniqueId() == other.uniqueId());
+}
+
+TType::TType(TInterfaceBlock *interfaceBlockIn,
+ TQualifier qualifierIn,
+ TLayoutQualifier layoutQualifierIn)
+ : type(EbtInterfaceBlock),
+ precision(EbpUndefined),
+ qualifier(qualifierIn),
+ invariant(false),
+ memoryQualifier(TMemoryQualifier::Create()),
+ layoutQualifier(layoutQualifierIn),
+ primarySize(1),
+ secondarySize(1),
+ mArraySizes(nullptr),
+ mInterfaceBlock(interfaceBlockIn),
+ mStructure(0),
+ mIsStructSpecifier(false),
+ mMangledName(nullptr)
+{
+}
+
+TType::TType(const TType &t)
+ : type(t.type),
+ precision(t.precision),
+ qualifier(t.qualifier),
+ invariant(t.invariant),
+ memoryQualifier(t.memoryQualifier),
+ layoutQualifier(t.layoutQualifier),
+ primarySize(t.primarySize),
+ secondarySize(t.secondarySize),
+ mArraySizes(t.mArraySizes ? new TVector<unsigned int>(*t.mArraySizes) : nullptr),
+ mInterfaceBlock(t.mInterfaceBlock),
+ mStructure(t.mStructure),
+ mIsStructSpecifier(t.mIsStructSpecifier),
+ mMangledName(t.mMangledName)
+{
+}
+
+TType &TType::operator=(const TType &t)
+{
+ type = t.type;
+ precision = t.precision;
+ qualifier = t.qualifier;
+ invariant = t.invariant;
+ memoryQualifier = t.memoryQualifier;
+ layoutQualifier = t.layoutQualifier;
+ primarySize = t.primarySize;
+ secondarySize = t.secondarySize;
+ mArraySizes = t.mArraySizes ? new TVector<unsigned int>(*t.mArraySizes) : nullptr;
+ mInterfaceBlock = t.mInterfaceBlock;
+ mStructure = t.mStructure;
+ mIsStructSpecifier = t.mIsStructSpecifier;
+ mMangledName = t.mMangledName;
+ return *this;
+}
+
+bool TType::canBeConstructed() const
+{
+ switch (type)
+ {
+ case EbtFloat:
+ case EbtInt:
+ case EbtUInt:
+ case EbtBool:
+ case EbtStruct:
+ return true;
+ default:
+ return false;
+ }
+}
+
+const char *TType::getBuiltInTypeNameString() const
+{
+ if (isMatrix())
+ {
+ switch (getCols())
+ {
+ case 2:
+ switch (getRows())
+ {
+ case 2:
+ return "mat2";
+ case 3:
+ return "mat2x3";
+ case 4:
+ return "mat2x4";
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+ case 3:
+ switch (getRows())
+ {
+ case 2:
+ return "mat3x2";
+ case 3:
+ return "mat3";
+ case 4:
+ return "mat3x4";
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+ case 4:
+ switch (getRows())
+ {
+ case 2:
+ return "mat4x2";
+ case 3:
+ return "mat4x3";
+ case 4:
+ return "mat4";
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+ }
+ if (isVector())
+ {
+ switch (getBasicType())
+ {
+ case EbtFloat:
+ switch (getNominalSize())
+ {
+ case 2:
+ return "vec2";
+ case 3:
+ return "vec3";
+ case 4:
+ return "vec4";
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+ case EbtInt:
+ switch (getNominalSize())
+ {
+ case 2:
+ return "ivec2";
+ case 3:
+ return "ivec3";
+ case 4:
+ return "ivec4";
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+ case EbtBool:
+ switch (getNominalSize())
+ {
+ case 2:
+ return "bvec2";
+ case 3:
+ return "bvec3";
+ case 4:
+ return "bvec4";
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+ case EbtUInt:
+ switch (getNominalSize())
+ {
+ case 2:
+ return "uvec2";
+ case 3:
+ return "uvec3";
+ case 4:
+ return "uvec4";
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+ }
+ ASSERT(getBasicType() != EbtStruct);
+ ASSERT(getBasicType() != EbtInterfaceBlock);
+ return getBasicString();
}
TString TType::getCompleteString() const
@@ -69,8 +405,14 @@ TString TType::getCompleteString() const
stream << getQualifierString() << " ";
if (precision != EbpUndefined)
stream << getPrecisionString() << " ";
- if (array)
- stream << "array[" << getArraySize() << "] of ";
+ if (mArraySizes)
+ {
+ for (auto arraySizeIter = mArraySizes->rbegin(); arraySizeIter != mArraySizes->rend();
+ ++arraySizeIter)
+ {
+ stream << "array[" << (*arraySizeIter) << "] of ";
+ }
+ }
if (isMatrix())
stream << getCols() << "X" << getRows() << " matrix of ";
else if (isVector())
@@ -83,7 +425,7 @@ TString TType::getCompleteString() const
//
// Recursively generate mangled names.
//
-TString TType::buildMangledName() const
+const char *TType::buildMangledName() const
{
TString mangledName;
if (isMatrix())
@@ -93,78 +435,132 @@ TString TType::buildMangledName() const
switch (type)
{
- case EbtFloat:
- mangledName += 'f';
- break;
- case EbtInt:
- mangledName += 'i';
- break;
- case EbtUInt:
- mangledName += 'u';
- break;
- case EbtBool:
- mangledName += 'b';
- break;
- case EbtSampler2D:
- mangledName += "s2";
- break;
- case EbtSampler3D:
- mangledName += "s3";
- break;
- case EbtSamplerCube:
- mangledName += "sC";
- break;
- case EbtSampler2DArray:
- mangledName += "s2a";
- break;
- case EbtSamplerExternalOES:
- mangledName += "sext";
- break;
- case EbtSampler2DRect:
- mangledName += "s2r";
- break;
- case EbtISampler2D:
- mangledName += "is2";
- break;
- case EbtISampler3D:
- mangledName += "is3";
- break;
- case EbtISamplerCube:
- mangledName += "isC";
- break;
- case EbtISampler2DArray:
- mangledName += "is2a";
- break;
- case EbtUSampler2D:
- mangledName += "us2";
- break;
- case EbtUSampler3D:
- mangledName += "us3";
- break;
- case EbtUSamplerCube:
- mangledName += "usC";
- break;
- case EbtUSampler2DArray:
- mangledName += "us2a";
- break;
- case EbtSampler2DShadow:
- mangledName += "s2s";
- break;
- case EbtSamplerCubeShadow:
- mangledName += "sCs";
- break;
- case EbtSampler2DArrayShadow:
- mangledName += "s2as";
- break;
- case EbtStruct:
- mangledName += structure->mangledName();
- break;
- case EbtInterfaceBlock:
- mangledName += interfaceBlock->mangledName();
- break;
- default:
- // EbtVoid, EbtAddress and non types
- break;
+ case EbtFloat:
+ mangledName += 'f';
+ break;
+ case EbtInt:
+ mangledName += 'i';
+ break;
+ case EbtUInt:
+ mangledName += 'u';
+ break;
+ case EbtBool:
+ mangledName += 'b';
+ break;
+ case EbtYuvCscStandardEXT:
+ mangledName += "ycs";
+ break;
+ case EbtSampler2D:
+ mangledName += "s2";
+ break;
+ case EbtSampler3D:
+ mangledName += "s3";
+ break;
+ case EbtSamplerCube:
+ mangledName += "sC";
+ break;
+ case EbtSampler2DArray:
+ mangledName += "s2a";
+ break;
+ case EbtSamplerExternalOES:
+ mangledName += "sext";
+ break;
+ case EbtSamplerExternal2DY2YEXT:
+ mangledName += "sext2y2y";
+ break;
+ case EbtSampler2DRect:
+ mangledName += "s2r";
+ break;
+ case EbtSampler2DMS:
+ mangledName += "s2ms";
+ break;
+ case EbtISampler2D:
+ mangledName += "is2";
+ break;
+ case EbtISampler3D:
+ mangledName += "is3";
+ break;
+ case EbtISamplerCube:
+ mangledName += "isC";
+ break;
+ case EbtISampler2DArray:
+ mangledName += "is2a";
+ break;
+ case EbtISampler2DMS:
+ mangledName += "is2ms";
+ break;
+ case EbtUSampler2D:
+ mangledName += "us2";
+ break;
+ case EbtUSampler3D:
+ mangledName += "us3";
+ break;
+ case EbtUSamplerCube:
+ mangledName += "usC";
+ break;
+ case EbtUSampler2DArray:
+ mangledName += "us2a";
+ break;
+ case EbtUSampler2DMS:
+ mangledName += "us2ms";
+ break;
+ case EbtSampler2DShadow:
+ mangledName += "s2s";
+ break;
+ case EbtSamplerCubeShadow:
+ mangledName += "sCs";
+ break;
+ case EbtSampler2DArrayShadow:
+ mangledName += "s2as";
+ break;
+ case EbtImage2D:
+ mangledName += "im2";
+ break;
+ case EbtIImage2D:
+ mangledName += "iim2";
+ break;
+ case EbtUImage2D:
+ mangledName += "uim2";
+ break;
+ case EbtImage3D:
+ mangledName += "im3";
+ break;
+ case EbtIImage3D:
+ mangledName += "iim3";
+ break;
+ case EbtUImage3D:
+ mangledName += "uim3";
+ break;
+ case EbtImage2DArray:
+ mangledName += "im2a";
+ break;
+ case EbtIImage2DArray:
+ mangledName += "iim2a";
+ break;
+ case EbtUImage2DArray:
+ mangledName += "uim2a";
+ break;
+ case EbtImageCube:
+ mangledName += "imc";
+ break;
+ case EbtIImageCube:
+ mangledName += "iimc";
+ break;
+ case EbtUImageCube:
+ mangledName += "uimc";
+ break;
+ case EbtAtomicCounter:
+ mangledName += "ac";
+ break;
+ case EbtStruct:
+ mangledName += mStructure->mangledName();
+ break;
+ case EbtInterfaceBlock:
+ mangledName += mInterfaceBlock->mangledName();
+ break;
+ default:
+ // EbtVoid, EbtAddress and non types
+ break;
}
if (isMatrix())
@@ -178,15 +574,25 @@ TString TType::buildMangledName() const
mangledName += static_cast<char>('0' + getNominalSize());
}
- if (isArray())
+ if (mArraySizes)
{
- char buf[20];
- snprintf(buf, sizeof(buf), "%d", arraySize);
- mangledName += '[';
- mangledName += buf;
- mangledName += ']';
+ for (unsigned int arraySize : *mArraySizes)
+ {
+ char buf[20];
+ snprintf(buf, sizeof(buf), "%d", arraySize);
+ mangledName += '[';
+ mangledName += buf;
+ mangledName += ']';
+ }
}
- return mangledName;
+
+ mangledName += ';';
+
+ // Copy string contents into a pool-allocated buffer, so we never need to call delete.
+ size_t requiredSize = mangledName.size() + 1;
+ char *buffer = reinterpret_cast<char *>(GetGlobalPoolAllocator()->allocate(requiredSize));
+ memcpy(buffer, mangledName.c_str(), requiredSize);
+ return buffer;
}
size_t TType::getObjectSize() const
@@ -194,23 +600,265 @@ size_t TType::getObjectSize() const
size_t totalSize;
if (getBasicType() == EbtStruct)
- totalSize = structure->objectSize();
+ totalSize = mStructure->objectSize();
else
totalSize = primarySize * secondarySize;
- if (isArray())
+ if (totalSize == 0)
+ return 0;
+
+ if (mArraySizes)
{
- // TODO: getArraySize() returns an int, not a size_t
- size_t currentArraySize = getArraySize();
- if (currentArraySize > INT_MAX / totalSize)
- totalSize = INT_MAX;
- else
- totalSize *= currentArraySize;
+ for (size_t arraySize : *mArraySizes)
+ {
+ if (arraySize > INT_MAX / totalSize)
+ totalSize = INT_MAX;
+ else
+ totalSize *= arraySize;
+ }
}
return totalSize;
}
+int TType::getLocationCount() const
+{
+ int count = 1;
+
+ if (getBasicType() == EbtStruct)
+ {
+ count = mStructure->getLocationCount();
+ }
+
+ if (count == 0)
+ {
+ return 0;
+ }
+
+ if (mArraySizes)
+ {
+ for (unsigned int arraySize : *mArraySizes)
+ {
+ if (arraySize > static_cast<unsigned int>(std::numeric_limits<int>::max() / count))
+ {
+ count = std::numeric_limits<int>::max();
+ }
+ else
+ {
+ count *= static_cast<int>(arraySize);
+ }
+ }
+ }
+
+ return count;
+}
+
+unsigned int TType::getArraySizeProduct() const
+{
+ if (!mArraySizes)
+ return 1u;
+
+ unsigned int product = 1u;
+
+ for (unsigned int arraySize : *mArraySizes)
+ {
+ product *= arraySize;
+ }
+ return product;
+}
+
+bool TType::isUnsizedArray() const
+{
+ if (!mArraySizes)
+ return false;
+
+ for (unsigned int arraySize : *mArraySizes)
+ {
+ if (arraySize == 0u)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool TType::sameNonArrayType(const TType &right) const
+{
+ return (type == right.type && primarySize == right.primarySize &&
+ secondarySize == right.secondarySize && mStructure == right.mStructure);
+}
+
+bool TType::isElementTypeOf(const TType &arrayType) const
+{
+ if (!sameNonArrayType(arrayType))
+ {
+ return false;
+ }
+ if (arrayType.getNumArraySizes() != getNumArraySizes() + 1u)
+ {
+ return false;
+ }
+ if (isArray())
+ {
+ for (size_t i = 0; i < mArraySizes->size(); ++i)
+ {
+ if ((*mArraySizes)[i] != (*arrayType.mArraySizes)[i])
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+void TType::sizeUnsizedArrays(const TVector<unsigned int> *newArraySizes)
+{
+ size_t newArraySizesSize = newArraySizes ? newArraySizes->size() : 0;
+ for (size_t i = 0u; i < getNumArraySizes(); ++i)
+ {
+ if ((*mArraySizes)[i] == 0)
+ {
+ if (i < newArraySizesSize)
+ {
+ ASSERT(newArraySizes != nullptr);
+ (*mArraySizes)[i] = (*newArraySizes)[i];
+ }
+ else
+ {
+ (*mArraySizes)[i] = 1u;
+ }
+ }
+ }
+ invalidateMangledName();
+}
+
+void TType::sizeOutermostUnsizedArray(unsigned int arraySize)
+{
+ ASSERT(isArray());
+ ASSERT(mArraySizes->back() == 0u);
+ mArraySizes->back() = arraySize;
+}
+
+void TType::setBasicType(TBasicType t)
+{
+ if (type != t)
+ {
+ type = t;
+ invalidateMangledName();
+ }
+}
+
+void TType::setPrimarySize(unsigned char ps)
+{
+ if (primarySize != ps)
+ {
+ ASSERT(ps <= 4);
+ primarySize = ps;
+ invalidateMangledName();
+ }
+}
+
+void TType::setSecondarySize(unsigned char ss)
+{
+ if (secondarySize != ss)
+ {
+ ASSERT(ss <= 4);
+ secondarySize = ss;
+ invalidateMangledName();
+ }
+}
+
+void TType::makeArray(unsigned int s)
+{
+ if (!mArraySizes)
+ mArraySizes = new TVector<unsigned int>();
+
+ mArraySizes->push_back(s);
+ invalidateMangledName();
+}
+
+void TType::makeArrays(const TVector<unsigned int> &sizes)
+{
+ if (!mArraySizes)
+ mArraySizes = new TVector<unsigned int>();
+
+ mArraySizes->insert(mArraySizes->end(), sizes.begin(), sizes.end());
+ invalidateMangledName();
+}
+
+void TType::setArraySize(size_t arrayDimension, unsigned int s)
+{
+ ASSERT(mArraySizes != nullptr);
+ ASSERT(arrayDimension < mArraySizes->size());
+ if (mArraySizes->at(arrayDimension) != s)
+ {
+ (*mArraySizes)[arrayDimension] = s;
+ invalidateMangledName();
+ }
+}
+
+void TType::toArrayElementType()
+{
+ ASSERT(mArraySizes != nullptr);
+ if (mArraySizes->size() > 0)
+ {
+ mArraySizes->pop_back();
+ invalidateMangledName();
+ }
+}
+
+void TType::setInterfaceBlock(TInterfaceBlock *interfaceBlockIn)
+{
+ if (mInterfaceBlock != interfaceBlockIn)
+ {
+ mInterfaceBlock = interfaceBlockIn;
+ invalidateMangledName();
+ }
+}
+
+void TType::setStruct(TStructure *s)
+{
+ if (mStructure != s)
+ {
+ mStructure = s;
+ invalidateMangledName();
+ }
+}
+
+const char *TType::getMangledName() const
+{
+ if (mMangledName == nullptr)
+ {
+ mMangledName = buildMangledName();
+ }
+
+ return mMangledName;
+}
+
+void TType::realize()
+{
+ getMangledName();
+}
+
+void TType::invalidateMangledName()
+{
+ mMangledName = nullptr;
+}
+
+// TStructure implementation.
+TStructure::TStructure(TSymbolTable *symbolTable, const TString *name, TFieldList *fields)
+ : TFieldListCollection(name, fields),
+ mDeepestNesting(0),
+ mUniqueId(symbolTable->nextUniqueId()),
+ mAtGlobalScope(false)
+{
+}
+
+bool TStructure::equals(const TStructure &other) const
+{
+ return (uniqueId() == other.uniqueId());
+}
+
bool TStructure::containsArrays() const
{
for (size_t i = 0; i < mFields->size(); ++i)
@@ -244,6 +892,66 @@ bool TStructure::containsSamplers() const
return false;
}
+void TType::createSamplerSymbols(const TString &namePrefix,
+ const TString &apiNamePrefix,
+ TVector<TIntermSymbol *> *outputSymbols,
+ TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames,
+ TSymbolTable *symbolTable) const
+{
+ if (isStructureContainingSamplers())
+ {
+ if (isArray())
+ {
+ TType elementType(*this);
+ elementType.toArrayElementType();
+ for (unsigned int arrayIndex = 0u; arrayIndex < getOutermostArraySize(); ++arrayIndex)
+ {
+ TStringStream elementName;
+ elementName << namePrefix << "_" << arrayIndex;
+ TStringStream elementApiName;
+ elementApiName << apiNamePrefix << "[" << arrayIndex << "]";
+ elementType.createSamplerSymbols(elementName.str(), elementApiName.str(),
+ outputSymbols, outputSymbolsToAPINames,
+ symbolTable);
+ }
+ }
+ else
+ {
+ mStructure->createSamplerSymbols(namePrefix, apiNamePrefix, outputSymbols,
+ outputSymbolsToAPINames, symbolTable);
+ }
+ return;
+ }
+
+ ASSERT(IsSampler(type));
+ TIntermSymbol *symbol = new TIntermSymbol(symbolTable->nextUniqueId(), namePrefix, *this);
+ outputSymbols->push_back(symbol);
+ if (outputSymbolsToAPINames)
+ {
+ (*outputSymbolsToAPINames)[symbol] = apiNamePrefix;
+ }
+}
+
+void TStructure::createSamplerSymbols(const TString &namePrefix,
+ const TString &apiNamePrefix,
+ TVector<TIntermSymbol *> *outputSymbols,
+ TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames,
+ TSymbolTable *symbolTable) const
+{
+ ASSERT(containsSamplers());
+ for (auto &field : *mFields)
+ {
+ const TType *fieldType = field->type();
+ if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers())
+ {
+ TString fieldName = namePrefix + "_" + field->name();
+ TString fieldApiName = apiNamePrefix + "." + field->name();
+ fieldType->createSamplerSymbols(fieldName, fieldApiName, outputSymbols,
+ outputSymbolsToAPINames, symbolTable);
+ }
+ }
+}
+
TString TFieldListCollection::buildMangledName(const TString &mangledNamePrefix) const
{
TString mangledName(mangledNamePrefix);
@@ -259,9 +967,9 @@ TString TFieldListCollection::buildMangledName(const TString &mangledNamePrefix)
size_t TFieldListCollection::calculateObjectSize() const
{
size_t size = 0;
- for (size_t i = 0; i < mFields->size(); ++i)
+ for (const TField *field : *mFields)
{
- size_t fieldSize = (*mFields)[i]->type()->getObjectSize();
+ size_t fieldSize = field->type()->getObjectSize();
if (fieldSize > INT_MAX - size)
size = INT_MAX;
else
@@ -270,6 +978,24 @@ size_t TFieldListCollection::calculateObjectSize() const
return size;
}
+int TFieldListCollection::getLocationCount() const
+{
+ int count = 0;
+ for (const TField *field : *mFields)
+ {
+ int fieldCount = field->type()->getLocationCount();
+ if (fieldCount > std::numeric_limits<int>::max() - count)
+ {
+ count = std::numeric_limits<int>::max();
+ }
+ else
+ {
+ count += fieldCount;
+ }
+ }
+ return count;
+}
+
int TStructure::calculateDeepestNesting() const
{
int maxNesting = 0;
@@ -277,3 +1003,70 @@ int TStructure::calculateDeepestNesting() const
maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting());
return 1 + maxNesting;
}
+
+// TPublicType implementation.
+void TPublicType::initialize(const TTypeSpecifierNonArray &typeSpecifier, TQualifier q)
+{
+ typeSpecifierNonArray = typeSpecifier;
+ layoutQualifier = TLayoutQualifier::Create();
+ memoryQualifier = TMemoryQualifier::Create();
+ qualifier = q;
+ invariant = false;
+ precision = EbpUndefined;
+ arraySizes = nullptr;
+}
+
+void TPublicType::initializeBasicType(TBasicType basicType)
+{
+ typeSpecifierNonArray.type = basicType;
+ typeSpecifierNonArray.primarySize = 1;
+ typeSpecifierNonArray.secondarySize = 1;
+ layoutQualifier = TLayoutQualifier::Create();
+ memoryQualifier = TMemoryQualifier::Create();
+ qualifier = EvqTemporary;
+ invariant = false;
+ precision = EbpUndefined;
+ arraySizes = nullptr;
+}
+
+bool TPublicType::isStructureContainingArrays() const
+{
+ if (!typeSpecifierNonArray.userDef)
+ {
+ return false;
+ }
+
+ return typeSpecifierNonArray.userDef->containsArrays();
+}
+
+bool TPublicType::isStructureContainingType(TBasicType t) const
+{
+ if (!typeSpecifierNonArray.userDef)
+ {
+ return false;
+ }
+
+ return typeSpecifierNonArray.userDef->containsType(t);
+}
+
+void TPublicType::setArraySizes(TVector<unsigned int> *sizes)
+{
+ arraySizes = sizes;
+}
+
+bool TPublicType::isArray() const
+{
+ return arraySizes && !arraySizes->empty();
+}
+
+void TPublicType::clearArrayness()
+{
+ arraySizes = nullptr;
+}
+
+bool TPublicType::isAggregate() const
+{
+ return isArray() || typeSpecifierNonArray.isMatrix() || typeSpecifierNonArray.isVector();
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/Types.h b/src/3rdparty/angle/src/compiler/translator/Types.h
index c2968dceba..7dc84c5b1c 100644
--- a/src/3rdparty/angle/src/compiler/translator/Types.h
+++ b/src/3rdparty/angle/src/compiler/translator/Types.h
@@ -12,41 +12,33 @@
#include "compiler/translator/BaseTypes.h"
#include "compiler/translator/Common.h"
+#include "compiler/translator/SymbolUniqueId.h"
+
+namespace sh
+{
struct TPublicType;
class TType;
class TSymbol;
+class TIntermSymbol;
+class TSymbolTable;
class TField : angle::NonCopyable
{
public:
POOL_ALLOCATOR_NEW_DELETE();
TField(TType *type, TString *name, const TSourceLoc &line)
- : mType(type),
- mName(name),
- mLine(line)
+ : mType(type), mName(name), mLine(line)
{
}
// TODO(alokp): We should only return const type.
// Fix it by tweaking grammar.
- TType *type()
- {
- return mType;
- }
- const TType *type() const
- {
- return mType;
- }
+ TType *type() { return mType; }
+ const TType *type() const { return mType; }
- const TString &name() const
- {
- return *mName;
- }
- const TSourceLoc &line() const
- {
- return mLine;
- }
+ const TString &name() const { return *mName; }
+ const TSourceLoc &line() const { return mLine; }
private:
TType *mType;
@@ -58,33 +50,28 @@ typedef TVector<TField *> TFieldList;
inline TFieldList *NewPoolTFieldList()
{
void *memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList));
- return new(memory) TFieldList;
+ return new (memory) TFieldList;
}
class TFieldListCollection : angle::NonCopyable
{
public:
- const TString &name() const
- {
- return *mName;
- }
- const TFieldList &fields() const
- {
- return *mFields;
- }
+ const TString &name() const { return *mName; }
+ const TFieldList &fields() const { return *mFields; }
size_t objectSize() const
{
if (mObjectSize == 0)
mObjectSize = calculateObjectSize();
return mObjectSize;
- };
+ }
+
+ // How many locations the field list consumes as a uniform.
+ int getLocationCount() const;
protected:
TFieldListCollection(const TString *name, TFieldList *fields)
- : mName(name),
- mFields(fields),
- mObjectSize(0)
+ : mName(name), mFields(fields), mObjectSize(0)
{
}
TString buildMangledName(const TString &mangledNamePrefix) const;
@@ -102,13 +89,7 @@ class TStructure : public TFieldListCollection
{
public:
POOL_ALLOCATOR_NEW_DELETE();
- TStructure(const TString *name, TFieldList *fields)
- : TFieldListCollection(name, fields),
- mDeepestNesting(0),
- mUniqueId(0),
- mAtGlobalScope(false)
- {
- }
+ TStructure(TSymbolTable *symbolTable, const TString *name, TFieldList *fields);
int deepestNesting() const
{
@@ -120,28 +101,19 @@ class TStructure : public TFieldListCollection
bool containsType(TBasicType t) const;
bool containsSamplers() const;
- bool equals(const TStructure &other) const;
+ void createSamplerSymbols(const TString &namePrefix,
+ const TString &apiNamePrefix,
+ TVector<TIntermSymbol *> *outputSymbols,
+ TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames,
+ TSymbolTable *symbolTable) const;
- void setUniqueId(int uniqueId)
- {
- mUniqueId = uniqueId;
- }
+ bool equals(const TStructure &other) const;
- int uniqueId() const
- {
- ASSERT(mUniqueId != 0);
- return mUniqueId;
- }
+ int uniqueId() const { return mUniqueId.get(); }
- void setAtGlobalScope(bool atGlobalScope)
- {
- mAtGlobalScope = atGlobalScope;
- }
+ void setAtGlobalScope(bool atGlobalScope) { mAtGlobalScope = atGlobalScope; }
- bool atGlobalScope() const
- {
- return mAtGlobalScope;
- }
+ bool atGlobalScope() const { return mAtGlobalScope; }
const TString &mangledName() const
{
@@ -158,13 +130,13 @@ class TStructure : public TFieldListCollection
void setName(const TString &name)
{
TString *mutableName = const_cast<TString *>(mName);
- *mutableName = name;
+ *mutableName = name;
}
int calculateDeepestNesting() const;
mutable int mDeepestNesting;
- int mUniqueId;
+ const TSymbolUniqueId mUniqueId;
bool mAtGlobalScope;
};
@@ -172,40 +144,23 @@ class TInterfaceBlock : public TFieldListCollection
{
public:
POOL_ALLOCATOR_NEW_DELETE();
- TInterfaceBlock(const TString *name, TFieldList *fields, const TString *instanceName,
- int arraySize, const TLayoutQualifier &layoutQualifier)
+ TInterfaceBlock(const TString *name,
+ TFieldList *fields,
+ const TString *instanceName,
+ const TLayoutQualifier &layoutQualifier)
: TFieldListCollection(name, fields),
mInstanceName(instanceName),
- mArraySize(arraySize),
mBlockStorage(layoutQualifier.blockStorage),
- mMatrixPacking(layoutQualifier.matrixPacking)
+ mMatrixPacking(layoutQualifier.matrixPacking),
+ mBinding(layoutQualifier.binding)
{
}
- const TString &instanceName() const
- {
- return *mInstanceName;
- }
- bool hasInstanceName() const
- {
- return mInstanceName != NULL;
- }
- bool isArray() const
- {
- return mArraySize > 0;
- }
- int arraySize() const
- {
- return mArraySize;
- }
- TLayoutBlockStorage blockStorage() const
- {
- return mBlockStorage;
- }
- TLayoutMatrixPacking matrixPacking() const
- {
- return mMatrixPacking;
- }
+ const TString &instanceName() const { return *mInstanceName; }
+ bool hasInstanceName() const { return mInstanceName != nullptr; }
+ TLayoutBlockStorage blockStorage() const { return mBlockStorage; }
+ TLayoutMatrixPacking matrixPacking() const { return mMatrixPacking; }
+ int blockBinding() const { return mBinding; }
const TString &mangledName() const
{
if (mMangledName.empty())
@@ -214,10 +169,10 @@ class TInterfaceBlock : public TFieldListCollection
}
private:
- const TString *mInstanceName; // for interface block instance names
- int mArraySize; // 0 if not an array
+ const TString *mInstanceName; // for interface block instance names
TLayoutBlockStorage mBlockStorage;
TLayoutMatrixPacking mMatrixPacking;
+ int mBinding;
};
//
@@ -227,101 +182,42 @@ class TType
{
public:
POOL_ALLOCATOR_NEW_DELETE();
- TType()
- : type(EbtVoid), precision(EbpUndefined), qualifier(EvqGlobal), invariant(false),
- layoutQualifier(TLayoutQualifier::create()),
- primarySize(0), secondarySize(0), array(false), arraySize(0),
- interfaceBlock(nullptr), structure(nullptr)
- {
- }
- TType(TBasicType t, unsigned char ps = 1, unsigned char ss = 1)
- : type(t), precision(EbpUndefined), qualifier(EvqGlobal), invariant(false),
- layoutQualifier(TLayoutQualifier::create()),
- primarySize(ps), secondarySize(ss), array(false), arraySize(0),
- interfaceBlock(0), structure(0)
- {
- }
- TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary,
- unsigned char ps = 1, unsigned char ss = 1, bool a = false)
- : type(t), precision(p), qualifier(q), invariant(false),
- layoutQualifier(TLayoutQualifier::create()),
- primarySize(ps), secondarySize(ss), array(a), arraySize(0),
- interfaceBlock(0), structure(0)
- {
- }
+ TType();
+ explicit TType(TBasicType t, unsigned char ps = 1, unsigned char ss = 1);
+ TType(TBasicType t,
+ TPrecision p,
+ TQualifier q = EvqTemporary,
+ unsigned char ps = 1,
+ unsigned char ss = 1);
explicit TType(const TPublicType &p);
- TType(TStructure *userDef, TPrecision p = EbpUndefined)
- : type(EbtStruct), precision(p), qualifier(EvqTemporary), invariant(false),
- layoutQualifier(TLayoutQualifier::create()),
- primarySize(1), secondarySize(1), array(false), arraySize(0),
- interfaceBlock(0), structure(userDef)
- {
- }
- TType(TInterfaceBlock *interfaceBlockIn, TQualifier qualifierIn,
- TLayoutQualifier layoutQualifierIn, int arraySizeIn)
- : type(EbtInterfaceBlock), precision(EbpUndefined), qualifier(qualifierIn),
- invariant(false), layoutQualifier(layoutQualifierIn),
- primarySize(1), secondarySize(1), array(arraySizeIn > 0), arraySize(arraySizeIn),
- interfaceBlock(interfaceBlockIn), structure(0)
- {
- }
+ explicit TType(TStructure *userDef);
+ TType(TInterfaceBlock *interfaceBlockIn,
+ TQualifier qualifierIn,
+ TLayoutQualifier layoutQualifierIn);
+ TType(const TType &t);
+ TType &operator=(const TType &t);
- TType(const TType &) = default;
- TType &operator=(const TType &) = default;
+ TBasicType getBasicType() const { return type; }
+ void setBasicType(TBasicType t);
- TBasicType getBasicType() const
- {
- return type;
- }
- void setBasicType(TBasicType t)
- {
- if (type != t)
- {
- type = t;
- invalidateMangledName();
- }
- }
+ TPrecision getPrecision() const { return precision; }
+ void setPrecision(TPrecision p) { precision = p; }
- TPrecision getPrecision() const
- {
- return precision;
- }
- void setPrecision(TPrecision p)
- {
- precision = p;
- }
+ TQualifier getQualifier() const { return qualifier; }
+ void setQualifier(TQualifier q) { qualifier = q; }
- TQualifier getQualifier() const
- {
- return qualifier;
- }
- void setQualifier(TQualifier q)
- {
- qualifier = q;
- }
+ bool isInvariant() const { return invariant; }
- bool isInvariant() const
- {
- return invariant;
- }
+ void setInvariant(bool i) { invariant = i; }
- TLayoutQualifier getLayoutQualifier() const
- {
- return layoutQualifier;
- }
- void setLayoutQualifier(TLayoutQualifier lq)
- {
- layoutQualifier = lq;
- }
+ TMemoryQualifier getMemoryQualifier() const { return memoryQualifier; }
+ void setMemoryQualifier(const TMemoryQualifier &mq) { memoryQualifier = mq; }
- int getNominalSize() const
- {
- return primarySize;
- }
- int getSecondarySize() const
- {
- return secondarySize;
- }
+ TLayoutQualifier getLayoutQualifier() const { return layoutQualifier; }
+ void setLayoutQualifier(TLayoutQualifier lq) { layoutQualifier = lq; }
+
+ int getNominalSize() const { return primarySize; }
+ int getSecondarySize() const { return secondarySize; }
int getCols() const
{
ASSERT(isMatrix());
@@ -332,139 +228,82 @@ class TType
ASSERT(isMatrix());
return secondarySize;
}
- void setPrimarySize(unsigned char ps)
- {
- if (primarySize != ps)
- {
- primarySize = ps;
- invalidateMangledName();
- }
- }
- void setSecondarySize(unsigned char ss)
- {
- if (secondarySize != ss)
- {
- secondarySize = ss;
- invalidateMangledName();
- }
- }
+ void setPrimarySize(unsigned char ps);
+ void setSecondarySize(unsigned char ss);
// Full size of single instance of type
size_t getObjectSize() const;
- bool isMatrix() const
- {
- return primarySize > 1 && secondarySize > 1;
- }
- bool isNonSquareMatrix() const
- {
- return isMatrix() && primarySize != secondarySize;
- }
- bool isArray() const
- {
- return array;
- }
- bool isUnsizedArray() const
- {
- return array && arraySize == 0;
- }
- int getArraySize() const
- {
- return arraySize;
- }
- void setArraySize(int s)
- {
- if (!array || arraySize != s)
- {
- array = true;
- arraySize = s;
- invalidateMangledName();
- }
- }
- void clearArrayness()
- {
- if (array)
- {
- array = false;
- arraySize = 0;
- invalidateMangledName();
- }
- }
+ // Get how many locations this type consumes as a uniform.
+ int getLocationCount() const;
- TInterfaceBlock *getInterfaceBlock() const
- {
- return interfaceBlock;
- }
- void setInterfaceBlock(TInterfaceBlock *interfaceBlockIn)
- {
- if (interfaceBlock != interfaceBlockIn)
- {
- interfaceBlock = interfaceBlockIn;
- invalidateMangledName();
- }
- }
- bool isInterfaceBlock() const
- {
- return type == EbtInterfaceBlock;
+ bool isMatrix() const { return primarySize > 1 && secondarySize > 1; }
+ bool isNonSquareMatrix() const { return isMatrix() && primarySize != secondarySize; }
+ bool isArray() const { return mArraySizes != nullptr && !mArraySizes->empty(); }
+ bool isArrayOfArrays() const { return isArray() && mArraySizes->size() > 1u; }
+ size_t getNumArraySizes() const { return isArray() ? mArraySizes->size() : 0; }
+ const TVector<unsigned int> *getArraySizes() const { return mArraySizes; }
+ unsigned int getArraySizeProduct() const;
+ bool isUnsizedArray() const;
+ unsigned int getOutermostArraySize() const {
+ ASSERT(isArray());
+ return mArraySizes->back();
}
+ void makeArray(unsigned int s);
- bool isVector() const
- {
- return primarySize > 1 && secondarySize == 1;
- }
+ // sizes contain new outermost array sizes.
+ void makeArrays(const TVector<unsigned int> &sizes);
+ // Here, the array dimension value 0 corresponds to the innermost array.
+ void setArraySize(size_t arrayDimension, unsigned int s);
+
+ // Will set unsized array sizes according to newArraySizes. In case there are more
+ // unsized arrays than there are sizes in newArraySizes, defaults to setting any
+ // remaining array sizes to 1.
+ void sizeUnsizedArrays(const TVector<unsigned int> *newArraySizes);
+
+ // Will size the outermost array according to arraySize.
+ void sizeOutermostUnsizedArray(unsigned int arraySize);
+
+ // Note that the array element type might still be an array type in GLSL ES version >= 3.10.
+ void toArrayElementType();
+
+ TInterfaceBlock *getInterfaceBlock() const { return mInterfaceBlock; }
+ void setInterfaceBlock(TInterfaceBlock *interfaceBlockIn);
+ bool isInterfaceBlock() const { return type == EbtInterfaceBlock; }
+
+ bool isVector() const { return primarySize > 1 && secondarySize == 1; }
bool isScalar() const
{
- return primarySize == 1 && secondarySize == 1 && !structure;
- }
- bool isScalarInt() const
- {
- return isScalar() && (type == EbtInt || type == EbtUInt);
+ return primarySize == 1 && secondarySize == 1 && !mStructure && !isArray();
}
+ bool isScalarFloat() const { return isScalar() && type == EbtFloat; }
+ bool isScalarInt() const { return isScalar() && (type == EbtInt || type == EbtUInt); }
- TStructure *getStruct() const
- {
- return structure;
- }
- void setStruct(TStructure *s)
- {
- if (structure != s)
- {
- structure = s;
- invalidateMangledName();
- }
- }
+ bool canBeConstructed() const;
- const TString &getMangledName() const
- {
- if (mangled.empty())
- {
- mangled = buildMangledName();
- mangled += ';';
- }
+ TStructure *getStruct() { return mStructure; }
+ const TStructure *getStruct() const { return mStructure; }
+ void setStruct(TStructure *s);
- return mangled;
- }
+ const char *getMangledName() const;
+
+ bool sameNonArrayType(const TType &right) const;
+
+ // Returns true if arrayType is an array made of this type.
+ bool isElementTypeOf(const TType &arrayType) const;
- bool sameElementType(const TType &right) const
- {
- return type == right.type &&
- primarySize == right.primarySize &&
- secondarySize == right.secondarySize &&
- structure == right.structure;
- }
bool operator==(const TType &right) const
{
- return type == right.type &&
- primarySize == right.primarySize &&
- secondarySize == right.secondarySize &&
- array == right.array && (!array || arraySize == right.arraySize) &&
- structure == right.structure;
+ size_t numArraySizesL = getNumArraySizes();
+ size_t numArraySizesR = right.getNumArraySizes();
+ bool arraySizesEqual = numArraySizesL == numArraySizesR &&
+ (numArraySizesL == 0 || *mArraySizes == *right.mArraySizes);
+ return type == right.type && primarySize == right.primarySize &&
+ secondarySize == right.secondarySize && arraySizesEqual &&
+ mStructure == right.mStructure;
// don't check the qualifier, it's not ever what's being sought after
}
- bool operator!=(const TType &right) const
- {
- return !operator==(right);
- }
+ bool operator!=(const TType &right) const { return !operator==(right); }
bool operator<(const TType &right) const
{
if (type != right.type)
@@ -473,28 +312,28 @@ class TType
return primarySize < right.primarySize;
if (secondarySize != right.secondarySize)
return secondarySize < right.secondarySize;
- if (array != right.array)
- return array < right.array;
- if (arraySize != right.arraySize)
- return arraySize < right.arraySize;
- if (structure != right.structure)
- return structure < right.structure;
+ size_t numArraySizesL = getNumArraySizes();
+ size_t numArraySizesR = right.getNumArraySizes();
+ if (numArraySizesL != numArraySizesR)
+ return numArraySizesL < numArraySizesR;
+ for (size_t i = 0; i < numArraySizesL; ++i)
+ {
+ if ((*mArraySizes)[i] != (*right.mArraySizes)[i])
+ return (*mArraySizes)[i] < (*right.mArraySizes)[i];
+ }
+ if (mStructure != right.mStructure)
+ return mStructure < right.mStructure;
return false;
}
- const char *getBasicString() const
- {
- return ::getBasicString(type);
- }
- const char *getPrecisionString() const
- {
- return ::getPrecisionString(precision);
- }
- const char *getQualifierString() const
- {
- return ::getQualifierString(qualifier);
- }
+ const char *getBasicString() const { return sh::getBasicString(type); }
+
+ const char *getPrecisionString() const { return sh::getPrecisionString(precision); }
+ const char *getQualifierString() const { return sh::getQualifierString(qualifier); }
+
+ const char *getBuiltInTypeNameString() const;
+
TString getCompleteString() const;
// If this type is a struct, returns the deepest struct nesting of
@@ -509,176 +348,162 @@ class TType
// For type "nesting2", this method would return 2 -- the number
// of structures through which indirection must occur to reach the
// deepest field (nesting2.field1.position).
- int getDeepestStructNesting() const
- {
- return structure ? structure->deepestNesting() : 0;
- }
+ int getDeepestStructNesting() const { return mStructure ? mStructure->deepestNesting() : 0; }
+
+ bool isNamelessStruct() const { return mStructure && mStructure->name() == ""; }
bool isStructureContainingArrays() const
{
- return structure ? structure->containsArrays() : false;
+ return mStructure ? mStructure->containsArrays() : false;
}
bool isStructureContainingType(TBasicType t) const
{
- return structure ? structure->containsType(t) : false;
+ return mStructure ? mStructure->containsType(t) : false;
}
bool isStructureContainingSamplers() const
{
- return structure ? structure->containsSamplers() : false;
+ return mStructure ? mStructure->containsSamplers() : false;
}
+ bool isStructSpecifier() const { return mIsStructSpecifier; }
+
+ void createSamplerSymbols(const TString &namePrefix,
+ const TString &apiNamePrefix,
+ TVector<TIntermSymbol *> *outputSymbols,
+ TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames,
+ TSymbolTable *symbolTable) const;
+
// Initializes all lazily-initialized members.
- void realize()
- {
- getMangledName();
- }
+ void realize();
private:
- void invalidateMangledName() { mangled = ""; }
- TString buildMangledName() const;
- size_t getStructSize() const;
+ void invalidateMangledName();
+ const char *buildMangledName() const;
TBasicType type;
TPrecision precision;
TQualifier qualifier;
bool invariant;
+ TMemoryQualifier memoryQualifier;
TLayoutQualifier layoutQualifier;
- unsigned char primarySize; // size of vector or cols matrix
- unsigned char secondarySize; // rows of a matrix
- bool array;
- int arraySize;
+ unsigned char primarySize; // size of vector or cols matrix
+ unsigned char secondarySize; // rows of a matrix
+
+ // Used to make an array type. Outermost array size is stored at the end of the vector. Having 0
+ // in this vector means an unsized array.
+ TVector<unsigned int> *mArraySizes;
- // 0 unless this is an interface block, or interface block member variable
- TInterfaceBlock *interfaceBlock;
+ // This is set only in the following two cases:
+ // 1) Represents an interface block.
+ // 2) Represents the member variable of an unnamed interface block.
+ // It's nullptr also for members of named interface blocks.
+ TInterfaceBlock *mInterfaceBlock;
// 0 unless this is a struct
- TStructure *structure;
+ TStructure *mStructure;
+ bool mIsStructSpecifier;
- mutable TString mangled;
+ mutable const char *mMangledName;
};
-//
-// This is a workaround for a problem with the yacc stack, It can't have
-// types that it thinks have non-trivial constructors. It should
-// just be used while recognizing the grammar, not anything else. Pointers
-// could be used, but also trying to avoid lots of memory management overhead.
-//
-// Not as bad as it looks, there is no actual assumption that the fields
-// match up or are name the same or anything like that.
-//
-struct TPublicType
+// TTypeSpecifierNonArray stores all of the necessary fields for type_specifier_nonarray from the
+// grammar
+struct TTypeSpecifierNonArray
{
TBasicType type;
- TLayoutQualifier layoutQualifier;
- TQualifier qualifier;
- bool invariant;
- TPrecision precision;
- unsigned char primarySize; // size of vector or cols of matrix
- unsigned char secondarySize; // rows of matrix
- bool array;
- int arraySize;
- TType *userDef;
+ unsigned char primarySize; // size of vector or cols of matrix
+ unsigned char secondarySize; // rows of matrix
+ TStructure *userDef;
TSourceLoc line;
// true if the type was defined by a struct specifier rather than a reference to a type name.
bool isStructSpecifier;
- void setBasic(TBasicType bt, TQualifier q, const TSourceLoc &ln)
+ void initialize(TBasicType aType, const TSourceLoc &aLine)
{
- type = bt;
- layoutQualifier = TLayoutQualifier::create();
- qualifier = q;
- invariant = false;
- precision = EbpUndefined;
- primarySize = 1;
- secondarySize = 1;
- array = false;
- arraySize = 0;
- userDef = 0;
- line = ln;
+ ASSERT(aType != EbtStruct);
+ type = aType;
+ primarySize = 1;
+ secondarySize = 1;
+ userDef = nullptr;
+ line = aLine;
isStructSpecifier = false;
}
- void setAggregate(unsigned char size)
+ void initializeStruct(TStructure *aUserDef, bool aIsStructSpecifier, const TSourceLoc &aLine)
{
- primarySize = size;
+ type = EbtStruct;
+ primarySize = 1;
+ secondarySize = 1;
+ userDef = aUserDef;
+ line = aLine;
+ isStructSpecifier = aIsStructSpecifier;
}
- void setMatrix(unsigned char c, unsigned char r)
- {
- ASSERT(c > 1 && r > 1 && c <= 4 && r <= 4);
- primarySize = c;
- secondarySize = r;
- }
+ void setAggregate(unsigned char size) { primarySize = size; }
- bool isUnsizedArray() const
- {
- return array && arraySize == 0;
- }
- void setArraySize(int s)
- {
- array = true;
- arraySize = s;
- }
- void clearArrayness()
+ void setMatrix(unsigned char columns, unsigned char rows)
{
- array = false;
- arraySize = 0;
+ ASSERT(columns > 1 && rows > 1 && columns <= 4 && rows <= 4);
+ primarySize = columns;
+ secondarySize = rows;
}
- bool isStructureContainingArrays() const
- {
- if (!userDef)
- {
- return false;
- }
+ bool isMatrix() const { return primarySize > 1 && secondarySize > 1; }
- return userDef->isStructureContainingArrays();
- }
+ bool isVector() const { return primarySize > 1 && secondarySize == 1; }
+};
- bool isStructureContainingType(TBasicType t) const
- {
- if (!userDef)
- {
- return false;
- }
+//
+// This is a workaround for a problem with the yacc stack, It can't have
+// types that it thinks have non-trivial constructors. It should
+// just be used while recognizing the grammar, not anything else. Pointers
+// could be used, but also trying to avoid lots of memory management overhead.
+//
+// Not as bad as it looks, there is no actual assumption that the fields
+// match up or are name the same or anything like that.
+//
+struct TPublicType
+{
+ // Must have a trivial default constructor since it is used in YYSTYPE.
+ TPublicType() = default;
- return userDef->isStructureContainingType(t);
- }
+ void initialize(const TTypeSpecifierNonArray &typeSpecifier, TQualifier q);
+ void initializeBasicType(TBasicType basicType);
- bool isMatrix() const
- {
- return primarySize > 1 && secondarySize > 1;
- }
+ TBasicType getBasicType() const { return typeSpecifierNonArray.type; }
+ void setBasicType(TBasicType basicType) { typeSpecifierNonArray.type = basicType; }
- bool isVector() const
- {
- return primarySize > 1 && secondarySize == 1;
- }
+ unsigned char getPrimarySize() const { return typeSpecifierNonArray.primarySize; }
+ unsigned char getSecondarySize() const { return typeSpecifierNonArray.secondarySize; }
- int getCols() const
- {
- ASSERT(isMatrix());
- return primarySize;
- }
+ TStructure *getUserDef() const { return typeSpecifierNonArray.userDef; }
+ const TSourceLoc &getLine() const { return typeSpecifierNonArray.line; }
- int getRows() const
- {
- ASSERT(isMatrix());
- return secondarySize;
- }
+ bool isStructSpecifier() const { return typeSpecifierNonArray.isStructSpecifier; }
- int getNominalSize() const
- {
- return primarySize;
- }
+ bool isStructureContainingArrays() const;
+ bool isStructureContainingType(TBasicType t) const;
+ void setArraySizes(TVector<unsigned int> *sizes);
+ bool isArray() const;
+ void clearArrayness();
+ bool isAggregate() const;
- bool isAggregate() const
- {
- return array || isMatrix() || isVector();
- }
+ TTypeSpecifierNonArray typeSpecifierNonArray;
+ TLayoutQualifier layoutQualifier;
+ TMemoryQualifier memoryQualifier;
+ TQualifier qualifier;
+ bool invariant;
+ TPrecision precision;
+
+ // Either nullptr or empty in case the type is not an array. The last element is the outermost
+ // array size. Note that due to bison restrictions, copies of the public type created by the
+ // copy constructor share the same arraySizes pointer.
+ const TVector<unsigned int> *arraySizes;
};
-#endif // COMPILER_TRANSLATOR_TYPES_H_
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_TYPES_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp
deleted file mode 100644
index f79f9dd7fb..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp
+++ /dev/null
@@ -1,185 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// UnfoldShortCircuit is an AST traverser to output short-circuiting operators as if-else statements.
-// The results are assigned to s# temporaries, which are used by the main translator instead of
-// the original expression.
-//
-
-#include "compiler/translator/UnfoldShortCircuit.h"
-
-#include "compiler/translator/InfoSink.h"
-#include "compiler/translator/OutputHLSL.h"
-#include "compiler/translator/UtilsHLSL.h"
-
-namespace sh
-{
-UnfoldShortCircuit::UnfoldShortCircuit(OutputHLSL *outputHLSL) : mOutputHLSL(outputHLSL)
-{
- mTemporaryIndex = 0;
-}
-
-void UnfoldShortCircuit::traverse(TIntermNode *node)
-{
- int rewindIndex = mTemporaryIndex;
- node->traverse(this);
- mTemporaryIndex = rewindIndex;
-}
-
-bool UnfoldShortCircuit::visitBinary(Visit visit, TIntermBinary *node)
-{
- TInfoSinkBase &out = mOutputHLSL->getInfoSink();
-
- // If our right node doesn't have side effects, we know we don't need to unfold this
- // expression: there will be no short-circuiting side effects to avoid
- // (note: unfolding doesn't depend on the left node -- it will always be evaluated)
- if (!node->getRight()->hasSideEffects())
- {
- return true;
- }
-
- switch (node->getOp())
- {
- case EOpLogicalOr:
- // "x || y" is equivalent to "x ? true : y", which unfolds to "bool s; if(x) s = true; else s = y;",
- // and then further simplifies down to "bool s = x; if(!s) s = y;".
- {
- int i = mTemporaryIndex;
-
- out << "bool s" << i << ";\n";
-
- out << "{\n";
-
- mTemporaryIndex = i + 1;
- node->getLeft()->traverse(this);
- out << "s" << i << " = ";
- mTemporaryIndex = i + 1;
- node->getLeft()->traverse(mOutputHLSL);
- out << ";\n";
- out << "if (!s" << i << ")\n"
- "{\n";
- mTemporaryIndex = i + 1;
- node->getRight()->traverse(this);
- out << " s" << i << " = ";
- mTemporaryIndex = i + 1;
- node->getRight()->traverse(mOutputHLSL);
- out << ";\n"
- "}\n";
-
- out << "}\n";
-
- mTemporaryIndex = i + 1;
- }
- return false;
- case EOpLogicalAnd:
- // "x && y" is equivalent to "x ? y : false", which unfolds to "bool s; if(x) s = y; else s = false;",
- // and then further simplifies down to "bool s = x; if(s) s = y;".
- {
- int i = mTemporaryIndex;
-
- out << "bool s" << i << ";\n";
-
- out << "{\n";
-
- mTemporaryIndex = i + 1;
- node->getLeft()->traverse(this);
- out << "s" << i << " = ";
- mTemporaryIndex = i + 1;
- node->getLeft()->traverse(mOutputHLSL);
- out << ";\n";
- out << "if (s" << i << ")\n"
- "{\n";
- mTemporaryIndex = i + 1;
- node->getRight()->traverse(this);
- out << " s" << i << " = ";
- mTemporaryIndex = i + 1;
- node->getRight()->traverse(mOutputHLSL);
- out << ";\n"
- "}\n";
-
- out << "}\n";
-
- mTemporaryIndex = i + 1;
- }
- return false;
- default:
- return true;
- }
-}
-
-bool UnfoldShortCircuit::visitSelection(Visit visit, TIntermSelection *node)
-{
- TInfoSinkBase &out = mOutputHLSL->getInfoSink();
-
- // Unfold "b ? x : y" into "type s; if(b) s = x; else s = y;"
- if (node->usesTernaryOperator())
- {
- int i = mTemporaryIndex;
-
- out << TypeString(node->getType()) << " s" << i << ";\n";
-
- out << "{\n";
-
- mTemporaryIndex = i + 1;
- node->getCondition()->traverse(this);
- out << "if (";
- mTemporaryIndex = i + 1;
- node->getCondition()->traverse(mOutputHLSL);
- out << ")\n"
- "{\n";
- mTemporaryIndex = i + 1;
- node->getTrueBlock()->traverse(this);
- out << " s" << i << " = ";
- mTemporaryIndex = i + 1;
- node->getTrueBlock()->traverse(mOutputHLSL);
- out << ";\n"
- "}\n"
- "else\n"
- "{\n";
- mTemporaryIndex = i + 1;
- node->getFalseBlock()->traverse(this);
- out << " s" << i << " = ";
- mTemporaryIndex = i + 1;
- node->getFalseBlock()->traverse(mOutputHLSL);
- out << ";\n"
- "}\n";
-
- out << "}\n";
-
- mTemporaryIndex = i + 1;
- }
-
- return false;
-}
-
-bool UnfoldShortCircuit::visitLoop(Visit visit, TIntermLoop *node)
-{
- int rewindIndex = mTemporaryIndex;
-
- if (node->getInit())
- {
- node->getInit()->traverse(this);
- }
-
- if (node->getCondition())
- {
- node->getCondition()->traverse(this);
- }
-
- if (node->getExpression())
- {
- node->getExpression()->traverse(this);
- }
-
- mTemporaryIndex = rewindIndex;
-
- return false;
-}
-
-int UnfoldShortCircuit::getNextTemporaryIndex()
-{
- return mTemporaryIndex++;
-}
-}
diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h
deleted file mode 100644
index eaceb0a0b3..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// UnfoldShortCircuit is an AST traverser to output short-circuiting operators as if-else statements
-//
-
-#ifndef COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_
-#define COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_
-
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/ParseContext.h"
-
-namespace sh
-{
-class OutputHLSL;
-
-class UnfoldShortCircuit : public TIntermTraverser
-{
- public:
- UnfoldShortCircuit(OutputHLSL *outputHLSL);
-
- void traverse(TIntermNode *node);
- bool visitBinary(Visit visit, TIntermBinary*);
- bool visitSelection(Visit visit, TIntermSelection *node);
- bool visitLoop(Visit visit, TIntermLoop *node);
-
- int getNextTemporaryIndex();
-
- protected:
- OutputHLSL *const mOutputHLSL;
-
- int mTemporaryIndex;
-};
-}
-
-#endif // COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp
index e50bf202ef..4e4653bbe5 100644
--- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp
@@ -6,52 +6,54 @@
#include "compiler/translator/UnfoldShortCircuitAST.h"
+namespace sh
+{
+
namespace
{
// "x || y" is equivalent to "x ? true : y".
-TIntermSelection *UnfoldOR(TIntermTyped *x, TIntermTyped *y)
+TIntermTernary *UnfoldOR(TIntermTyped *x, TIntermTyped *y)
{
- const TType boolType(EbtBool, EbpUndefined);
TConstantUnion *u = new TConstantUnion;
u->setBConst(true);
- TIntermConstantUnion *trueNode = new TIntermConstantUnion(
- u, TType(EbtBool, EbpUndefined, EvqConst, 1));
- return new TIntermSelection(x, trueNode, y, boolType);
+ TIntermConstantUnion *trueNode =
+ new TIntermConstantUnion(u, TType(EbtBool, EbpUndefined, EvqConst, 1));
+ return new TIntermTernary(x, trueNode, y);
}
// "x && y" is equivalent to "x ? y : false".
-TIntermSelection *UnfoldAND(TIntermTyped *x, TIntermTyped *y)
+TIntermTernary *UnfoldAND(TIntermTyped *x, TIntermTyped *y)
{
- const TType boolType(EbtBool, EbpUndefined);
TConstantUnion *u = new TConstantUnion;
u->setBConst(false);
- TIntermConstantUnion *falseNode = new TIntermConstantUnion(
- u, TType(EbtBool, EbpUndefined, EvqConst, 1));
- return new TIntermSelection(x, y, falseNode, boolType);
+ TIntermConstantUnion *falseNode =
+ new TIntermConstantUnion(u, TType(EbtBool, EbpUndefined, EvqConst, 1));
+ return new TIntermTernary(x, y, falseNode);
}
} // namespace anonymous
bool UnfoldShortCircuitAST::visitBinary(Visit visit, TIntermBinary *node)
{
- TIntermSelection *replacement = NULL;
+ TIntermTernary *replacement = nullptr;
switch (node->getOp())
{
- case EOpLogicalOr:
- replacement = UnfoldOR(node->getLeft(), node->getRight());
- break;
- case EOpLogicalAnd:
- replacement = UnfoldAND(node->getLeft(), node->getRight());
- break;
- default:
- break;
+ case EOpLogicalOr:
+ replacement = UnfoldOR(node->getLeft(), node->getRight());
+ break;
+ case EOpLogicalAnd:
+ replacement = UnfoldAND(node->getLeft(), node->getRight());
+ break;
+ default:
+ break;
}
if (replacement)
{
- mReplacements.push_back(
- NodeUpdateEntry(getParentNode(), node, replacement, false));
+ queueReplacement(replacement, OriginalNode::IS_DROPPED);
}
return true;
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h
index b92a4e9152..7f377e6f15 100644
--- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h
+++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h
@@ -11,7 +11,10 @@
#define COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUITAST_H_
#include "common/angleutils.h"
-#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
// This traverser identifies all the short circuit binary nodes that need to
// be replaced, and creates the corresponding replacement nodes. However,
@@ -20,12 +23,11 @@
class UnfoldShortCircuitAST : public TIntermTraverser
{
public:
- UnfoldShortCircuitAST()
- : TIntermTraverser(true, false, false)
- {
- }
+ UnfoldShortCircuitAST() : TIntermTraverser(true, false, false) {}
bool visitBinary(Visit visit, TIntermBinary *) override;
};
+} // namespace sh
+
#endif // COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUITAST_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.cpp b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.cpp
index be23b524d7..774f1fc704 100644
--- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.cpp
@@ -3,14 +3,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// UnfoldShortCircuitToIf is an AST traverser to convert short-circuiting operators to if-else statements.
+// UnfoldShortCircuitToIf is an AST traverser to convert short-circuiting operators to if-else
+// statements.
// The results are assigned to s# temporaries, which are used by the main translator instead of
// the original expression.
//
#include "compiler/translator/UnfoldShortCircuitToIf.h"
-#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermNodePatternMatcher.h"
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
namespace
{
@@ -19,44 +24,26 @@ namespace
class UnfoldShortCircuitTraverser : public TIntermTraverser
{
public:
- UnfoldShortCircuitTraverser();
+ UnfoldShortCircuitTraverser(TSymbolTable *symbolTable);
bool visitBinary(Visit visit, TIntermBinary *node) override;
- bool visitAggregate(Visit visit, TIntermAggregate *node) override;
- bool visitSelection(Visit visit, TIntermSelection *node) override;
- bool visitLoop(Visit visit, TIntermLoop *node) override;
+ bool visitTernary(Visit visit, TIntermTernary *node) override;
void nextIteration();
bool foundShortCircuit() const { return mFoundShortCircuit; }
protected:
- // Check if the traversal is inside a loop condition or expression, in which case the unfolded
- // expression needs to be copied inside the loop. Returns true if the copying is done, in which
- // case no further unfolding should be done on the same traversal.
- // The parameters are the node that will be unfolded to multiple statements and so can't remain
- // inside a loop condition, and its parent.
- bool copyLoopConditionOrExpression(TIntermNode *parent, TIntermTyped *node);
-
// Marked to true once an operation that needs to be unfolded has been found.
// After that, no more unfolding is performed on that traversal.
bool mFoundShortCircuit;
- // Set to the loop node while a loop condition or expression is being traversed.
- TIntermLoop *mParentLoop;
- // Parent of the loop node while a loop condition or expression is being traversed.
- TIntermNode *mLoopParent;
-
- bool mInLoopCondition;
- bool mInLoopExpression;
+ IntermNodePatternMatcher mPatternToUnfoldMatcher;
};
-UnfoldShortCircuitTraverser::UnfoldShortCircuitTraverser()
- : TIntermTraverser(true, false, true),
+UnfoldShortCircuitTraverser::UnfoldShortCircuitTraverser(TSymbolTable *symbolTable)
+ : TIntermTraverser(true, false, true, symbolTable),
mFoundShortCircuit(false),
- mParentLoop(nullptr),
- mLoopParent(nullptr),
- mInLoopCondition(false),
- mInLoopExpression(false)
+ mPatternToUnfoldMatcher(IntermNodePatternMatcher::kUnfoldedShortCircuitExpression)
{
}
@@ -64,19 +51,23 @@ bool UnfoldShortCircuitTraverser::visitBinary(Visit visit, TIntermBinary *node)
{
if (mFoundShortCircuit)
return false;
+
+ if (visit != PreVisit)
+ return true;
+
+ if (!mPatternToUnfoldMatcher.match(node, getParentNode()))
+ return true;
+
// If our right node doesn't have side effects, we know we don't need to unfold this
// expression: there will be no short-circuiting side effects to avoid
// (note: unfolding doesn't depend on the left node -- it will always be evaluated)
- if (!node->getRight()->hasSideEffects())
- {
- return true;
- }
+ ASSERT(node->getRight()->hasSideEffects());
+
+ mFoundShortCircuit = true;
switch (node->getOp())
{
- case EOpLogicalOr:
- mFoundShortCircuit = true;
- if (!copyLoopConditionOrExpression(getParentNode(), node))
+ case EOpLogicalOr:
{
// "x || y" is equivalent to "x ? true : y", which unfolds to "bool s; if(x) s = true;
// else s = y;",
@@ -88,24 +79,21 @@ bool UnfoldShortCircuitTraverser::visitBinary(Visit visit, TIntermBinary *node)
ASSERT(node->getLeft()->getType() == boolType);
insertions.push_back(createTempInitDeclaration(node->getLeft()));
- TIntermAggregate *assignRightBlock = new TIntermAggregate(EOpSequence);
+ TIntermBlock *assignRightBlock = new TIntermBlock();
ASSERT(node->getRight()->getType() == boolType);
assignRightBlock->getSequence()->push_back(createTempAssignment(node->getRight()));
- TIntermUnary *notTempSymbol = new TIntermUnary(EOpLogicalNot, boolType);
- notTempSymbol->setOperand(createTempSymbol(boolType));
- TIntermSelection *ifNode = new TIntermSelection(notTempSymbol, assignRightBlock, nullptr);
+ TIntermUnary *notTempSymbol =
+ new TIntermUnary(EOpLogicalNot, createTempSymbol(boolType));
+ TIntermIfElse *ifNode = new TIntermIfElse(notTempSymbol, assignRightBlock, nullptr);
insertions.push_back(ifNode);
insertStatementsInParentBlock(insertions);
- NodeUpdateEntry replaceVariable(getParentNode(), node, createTempSymbol(boolType), false);
- mReplacements.push_back(replaceVariable);
+ queueReplacement(createTempSymbol(boolType), OriginalNode::IS_DROPPED);
+ return false;
}
- return false;
- case EOpLogicalAnd:
- mFoundShortCircuit = true;
- if (!copyLoopConditionOrExpression(getParentNode(), node))
+ case EOpLogicalAnd:
{
// "x && y" is equivalent to "x ? y : false", which unfolds to "bool s; if(x) s = y;
// else s = false;",
@@ -116,246 +104,75 @@ bool UnfoldShortCircuitTraverser::visitBinary(Visit visit, TIntermBinary *node)
ASSERT(node->getLeft()->getType() == boolType);
insertions.push_back(createTempInitDeclaration(node->getLeft()));
- TIntermAggregate *assignRightBlock = new TIntermAggregate(EOpSequence);
+ TIntermBlock *assignRightBlock = new TIntermBlock();
ASSERT(node->getRight()->getType() == boolType);
assignRightBlock->getSequence()->push_back(createTempAssignment(node->getRight()));
- TIntermSelection *ifNode = new TIntermSelection(createTempSymbol(boolType), assignRightBlock, nullptr);
+ TIntermIfElse *ifNode =
+ new TIntermIfElse(createTempSymbol(boolType), assignRightBlock, nullptr);
insertions.push_back(ifNode);
insertStatementsInParentBlock(insertions);
- NodeUpdateEntry replaceVariable(getParentNode(), node, createTempSymbol(boolType), false);
- mReplacements.push_back(replaceVariable);
+ queueReplacement(createTempSymbol(boolType), OriginalNode::IS_DROPPED);
+ return false;
}
- return false;
- default:
- return true;
+ default:
+ UNREACHABLE();
+ return true;
}
}
-bool UnfoldShortCircuitTraverser::visitSelection(Visit visit, TIntermSelection *node)
+bool UnfoldShortCircuitTraverser::visitTernary(Visit visit, TIntermTernary *node)
{
if (mFoundShortCircuit)
return false;
- // Unfold "b ? x : y" into "type s; if(b) s = x; else s = y;"
- if (visit == PreVisit && node->usesTernaryOperator())
- {
- mFoundShortCircuit = true;
- if (!copyLoopConditionOrExpression(getParentNode(), node))
- {
- TIntermSequence insertions;
-
- TIntermSymbol *tempSymbol = createTempSymbol(node->getType());
- TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
- tempDeclaration->getSequence()->push_back(tempSymbol);
- insertions.push_back(tempDeclaration);
-
- TIntermAggregate *trueBlock = new TIntermAggregate(EOpSequence);
- TIntermBinary *trueAssignment =
- createTempAssignment(node->getTrueBlock()->getAsTyped());
- trueBlock->getSequence()->push_back(trueAssignment);
-
- TIntermAggregate *falseBlock = new TIntermAggregate(EOpSequence);
- TIntermBinary *falseAssignment =
- createTempAssignment(node->getFalseBlock()->getAsTyped());
- falseBlock->getSequence()->push_back(falseAssignment);
-
- TIntermSelection *ifNode =
- new TIntermSelection(node->getCondition()->getAsTyped(), trueBlock, falseBlock);
- insertions.push_back(ifNode);
-
- insertStatementsInParentBlock(insertions);
-
- TIntermSymbol *ternaryResult = createTempSymbol(node->getType());
- NodeUpdateEntry replaceVariable(getParentNode(), node, ternaryResult, false);
- mReplacements.push_back(replaceVariable);
- }
- return false;
- }
-
- return true;
-}
-
-bool UnfoldShortCircuitTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
-{
- if (visit == PreVisit && mFoundShortCircuit)
- return false; // No need to traverse further
+ if (visit != PreVisit)
+ return true;
- if (node->getOp() == EOpComma)
- {
- ASSERT(visit != PreVisit || !mFoundShortCircuit);
+ if (!mPatternToUnfoldMatcher.match(node))
+ return true;
- if (visit == PostVisit && mFoundShortCircuit)
- {
- // We can be sure that we arrived here because there was a short-circuiting operator
- // inside the sequence operator since we only start traversing the sequence operator in
- // case a short-circuiting operator has not been found so far.
- // We need to unfold the sequence (comma) operator, otherwise the evaluation order of
- // statements would be messed up by unfolded operations inside.
- // Don't do any other unfolding on this round of traversal.
- mReplacements.clear();
- mMultiReplacements.clear();
- mInsertions.clear();
-
- if (!copyLoopConditionOrExpression(getParentNode(), node))
- {
- TIntermSequence insertions;
- TIntermSequence *seq = node->getSequence();
-
- TIntermSequence::size_type i = 0;
- ASSERT(!seq->empty());
- while (i < seq->size() - 1)
- {
- TIntermTyped *child = (*seq)[i]->getAsTyped();
- insertions.push_back(child);
- ++i;
- }
-
- insertStatementsInParentBlock(insertions);
-
- NodeUpdateEntry replaceVariable(getParentNode(), node, (*seq)[i], false);
- mReplacements.push_back(replaceVariable);
- }
- }
- }
- return true;
-}
+ mFoundShortCircuit = true;
-bool UnfoldShortCircuitTraverser::visitLoop(Visit visit, TIntermLoop *node)
-{
- if (visit == PreVisit)
- {
- if (mFoundShortCircuit)
- return false; // No need to traverse further
-
- mLoopParent = getParentNode();
- mParentLoop = node;
- incrementDepth(node);
+ // Unfold "b ? x : y" into "type s; if(b) s = x; else s = y;"
+ TIntermSequence insertions;
- if (node->getInit())
- {
- node->getInit()->traverse(this);
- if (mFoundShortCircuit)
- {
- decrementDepth();
- return false;
- }
- }
+ TIntermDeclaration *tempDeclaration = createTempDeclaration(node->getType());
+ insertions.push_back(tempDeclaration);
- if (node->getCondition())
- {
- mInLoopCondition = true;
- node->getCondition()->traverse(this);
- mInLoopCondition = false;
-
- if (mFoundShortCircuit)
- {
- decrementDepth();
- return false;
- }
- }
+ TIntermBlock *trueBlock = new TIntermBlock();
+ TIntermBinary *trueAssignment = createTempAssignment(node->getTrueExpression());
+ trueBlock->getSequence()->push_back(trueAssignment);
- if (node->getExpression())
- {
- mInLoopExpression = true;
- node->getExpression()->traverse(this);
- mInLoopExpression = false;
-
- if (mFoundShortCircuit)
- {
- decrementDepth();
- return false;
- }
- }
+ TIntermBlock *falseBlock = new TIntermBlock();
+ TIntermBinary *falseAssignment = createTempAssignment(node->getFalseExpression());
+ falseBlock->getSequence()->push_back(falseAssignment);
- if (node->getBody())
- node->getBody()->traverse(this);
+ TIntermIfElse *ifNode =
+ new TIntermIfElse(node->getCondition()->getAsTyped(), trueBlock, falseBlock);
+ insertions.push_back(ifNode);
- decrementDepth();
- }
- return false;
-}
+ insertStatementsInParentBlock(insertions);
-bool UnfoldShortCircuitTraverser::copyLoopConditionOrExpression(TIntermNode *parent,
- TIntermTyped *node)
-{
- if (mInLoopCondition)
- {
- mReplacements.push_back(
- NodeUpdateEntry(parent, node, createTempSymbol(node->getType()), false));
- TIntermAggregate *body = mParentLoop->getBody();
- TIntermSequence empty;
- if (mParentLoop->getType() == ELoopDoWhile)
- {
- // Declare the temporary variable before the loop.
- TIntermSequence insertionsBeforeLoop;
- insertionsBeforeLoop.push_back(createTempDeclaration(node->getType()));
- insertStatementsInParentBlock(insertionsBeforeLoop);
-
- // Move a part of do-while loop condition to inside the loop.
- TIntermSequence insertionsInLoop;
- insertionsInLoop.push_back(createTempAssignment(node));
- mInsertions.push_back(NodeInsertMultipleEntry(body, body->getSequence()->size() - 1,
- empty, insertionsInLoop));
- }
- else
- {
- // The loop initializer expression and one copy of the part of the loop condition are
- // executed before the loop. They need to be in a new scope.
- TIntermAggregate *loopScope = new TIntermAggregate(EOpSequence);
-
- TIntermNode *initializer = mParentLoop->getInit();
- if (initializer != nullptr)
- {
- // Move the initializer to the newly created outer scope, so that condition can
- // depend on it.
- mReplacements.push_back(NodeUpdateEntry(mParentLoop, initializer, nullptr, false));
- loopScope->getSequence()->push_back(initializer);
- }
-
- loopScope->getSequence()->push_back(createTempInitDeclaration(node));
- loopScope->getSequence()->push_back(mParentLoop);
- mReplacements.push_back(NodeUpdateEntry(mLoopParent, mParentLoop, loopScope, true));
-
- // The second copy of the part of the loop condition is executed inside the loop.
- TIntermSequence insertionsInLoop;
- insertionsInLoop.push_back(createTempAssignment(node->deepCopy()));
- mInsertions.push_back(NodeInsertMultipleEntry(body, body->getSequence()->size() - 1,
- empty, insertionsInLoop));
- }
- return true;
- }
+ TIntermSymbol *ternaryResult = createTempSymbol(node->getType());
+ queueReplacement(ternaryResult, OriginalNode::IS_DROPPED);
- if (mInLoopExpression)
- {
- TIntermTyped *movedExpression = mParentLoop->getExpression();
- mReplacements.push_back(NodeUpdateEntry(mParentLoop, movedExpression, nullptr, false));
- TIntermAggregate *body = mParentLoop->getBody();
- TIntermSequence empty;
- TIntermSequence insertions;
- insertions.push_back(movedExpression);
- mInsertions.push_back(
- NodeInsertMultipleEntry(body, body->getSequence()->size() - 1, empty, insertions));
- return true;
- }
return false;
}
void UnfoldShortCircuitTraverser::nextIteration()
{
mFoundShortCircuit = false;
- nextTemporaryIndex();
+ nextTemporaryId();
}
-} // namespace
+} // namespace
-void UnfoldShortCircuitToIf(TIntermNode *root, unsigned int *temporaryIndex)
+void UnfoldShortCircuitToIf(TIntermNode *root, TSymbolTable *symbolTable)
{
- UnfoldShortCircuitTraverser traverser;
- ASSERT(temporaryIndex != nullptr);
- traverser.useTemporaryIndex(temporaryIndex);
+ UnfoldShortCircuitTraverser traverser(symbolTable);
// Unfold one operator at a time, and reset the traverser between iterations.
do
{
@@ -363,6 +180,7 @@ void UnfoldShortCircuitToIf(TIntermNode *root, unsigned int *temporaryIndex)
root->traverse(&traverser);
if (traverser.foundShortCircuit())
traverser.updateTree();
- }
- while (traverser.foundShortCircuit());
+ } while (traverser.foundShortCircuit());
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.h
index 0fe37b7140..37dd83a8cf 100644
--- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.h
+++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitToIf.h
@@ -3,7 +3,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// UnfoldShortCircuitToIf is an AST traverser to convert short-circuiting operators to if-else statements.
+// UnfoldShortCircuitToIf is an AST traverser to convert short-circuiting operators to if-else
+// statements.
// The results are assigned to s# temporaries, which are used by the main translator instead of
// the original expression.
//
@@ -11,8 +12,14 @@
#ifndef COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_
#define COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_
+namespace sh
+{
+
class TIntermNode;
+class TSymbolTable;
+
+void UnfoldShortCircuitToIf(TIntermNode *root, TSymbolTable *symbolTable);
-void UnfoldShortCircuitToIf(TIntermNode *root, unsigned int *temporaryIndex);
+} // namespace sh
-#endif // COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_
+#endif // COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp
index 20961c44c1..9f18509438 100644
--- a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp
@@ -4,7 +4,7 @@
// found in the LICENSE file.
//
// UniformHLSL.cpp:
-// Methods for GLSL to HLSL translation for uniforms and interface blocks.
+// Methods for GLSL to HLSL translation for uniforms and uniform blocks.
//
#include "compiler/translator/UniformHLSL.h"
@@ -18,6 +18,9 @@
namespace sh
{
+namespace
+{
+
static const char *UniformRegisterPrefix(const TType &type)
{
if (IsSampler(type.getBasicType()))
@@ -32,22 +35,23 @@ static const char *UniformRegisterPrefix(const TType &type)
static TString InterfaceBlockFieldTypeString(const TField &field, TLayoutBlockStorage blockStorage)
{
- const TType &fieldType = *field.type();
+ const TType &fieldType = *field.type();
const TLayoutMatrixPacking matrixPacking = fieldType.getLayoutQualifier().matrixPacking;
ASSERT(matrixPacking != EmpUnspecified);
- TStructure *structure = fieldType.getStruct();
+ const TStructure *structure = fieldType.getStruct();
if (fieldType.isMatrix())
{
// Use HLSL row-major packing for GLSL column-major matrices
- const TString &matrixPackString = (matrixPacking == EmpRowMajor ? "column_major" : "row_major");
+ const TString &matrixPackString =
+ (matrixPacking == EmpRowMajor ? "column_major" : "row_major");
return matrixPackString + " " + TypeString(fieldType);
}
else if (structure)
{
// Use HLSL row-major packing for GLSL column-major matrices
return QualifiedStructNameString(*structure, matrixPacking == EmpColumnMajor,
- blockStorage == EbsStd140);
+ blockStorage == EbsStd140);
}
else
{
@@ -60,23 +64,58 @@ static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock)
return DecoratePrivate(interfaceBlock.name()) + "_type";
}
-UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType, const std::vector<Uniform> &uniforms)
+void OutputSamplerIndexArrayInitializer(TInfoSinkBase &out,
+ const TType &type,
+ unsigned int startIndex)
+{
+ out << "{";
+ TType elementType(type);
+ elementType.toArrayElementType();
+ for (unsigned int i = 0u; i < type.getOutermostArraySize(); ++i)
+ {
+ if (i > 0u)
+ {
+ out << ", ";
+ }
+ if (elementType.isArray())
+ {
+ OutputSamplerIndexArrayInitializer(out, elementType,
+ startIndex + i * elementType.getArraySizeProduct());
+ }
+ else
+ {
+ out << (startIndex + i);
+ }
+ }
+ out << "}";
+}
+
+} // anonymous namespace
+
+UniformHLSL::UniformHLSL(sh::GLenum shaderType,
+ StructureHLSL *structureHLSL,
+ ShShaderOutput outputType,
+ const std::vector<Uniform> &uniforms)
: mUniformRegister(0),
- mInterfaceBlockRegister(0),
- mSamplerRegister(0),
+ mUniformBlockRegister(0),
+ mTextureRegister(0),
+ mRWTextureRegister(0),
+ mSamplerCount(0),
+ mShaderType(shaderType),
mStructureHLSL(structureHLSL),
mOutputType(outputType),
mUniforms(uniforms)
-{}
+{
+}
void UniformHLSL::reserveUniformRegisters(unsigned int registerCount)
{
mUniformRegister = registerCount;
}
-void UniformHLSL::reserveInterfaceBlockRegisters(unsigned int registerCount)
+void UniformHLSL::reserveUniformBlockRegisters(unsigned int registerCount)
{
- mInterfaceBlockRegister = registerCount;
+ mUniformBlockRegister = registerCount;
}
const Uniform *UniformHLSL::findUniformByName(const TString &name) const
@@ -89,46 +128,78 @@ const Uniform *UniformHLSL::findUniformByName(const TString &name) const
}
}
- UNREACHABLE();
- return NULL;
+ return nullptr;
}
-unsigned int UniformHLSL::declareUniformAndAssignRegister(const TType &type,
- const TString &name,
- unsigned int *registerCount)
+unsigned int UniformHLSL::assignUniformRegister(const TType &type,
+ const TString &name,
+ unsigned int *outRegisterCount)
{
- unsigned int registerIndex = (IsSampler(type.getBasicType()) ? mSamplerRegister : mUniformRegister);
-
+ unsigned int registerIndex;
const Uniform *uniform = findUniformByName(name);
ASSERT(uniform);
+ if (IsSampler(type.getBasicType()) ||
+ (IsImage(type.getBasicType()) && type.getMemoryQualifier().readonly))
+ {
+ registerIndex = mTextureRegister;
+ }
+ else if (IsImage(type.getBasicType()))
+ {
+ registerIndex = mRWTextureRegister;
+ }
+ else
+ {
+ registerIndex = mUniformRegister;
+ }
+
mUniformRegisterMap[uniform->name] = registerIndex;
- ASSERT(registerCount);
- *registerCount = HLSLVariableRegisterCount(*uniform, mOutputType);
+ unsigned int registerCount = HLSLVariableRegisterCount(*uniform, mOutputType);
- if (gl::IsSamplerType(uniform->type))
+ if (IsSampler(type.getBasicType()) ||
+ (IsImage(type.getBasicType()) && type.getMemoryQualifier().readonly))
{
- mSamplerRegister += *registerCount;
+ mTextureRegister += registerCount;
+ }
+ else if (IsImage(type.getBasicType()))
+ {
+ mRWTextureRegister += registerCount;
}
else
{
- mUniformRegister += *registerCount;
+ mUniformRegister += registerCount;
+ }
+ if (outRegisterCount)
+ {
+ *outRegisterCount = registerCount;
}
-
return registerIndex;
}
-unsigned int UniformHLSL::declareUniformAndAssignRegister(const TType &type, const TString &name)
+unsigned int UniformHLSL::assignSamplerInStructUniformRegister(const TType &type,
+ const TString &name,
+ unsigned int *outRegisterCount)
{
- unsigned int registerCount;
- return declareUniformAndAssignRegister(type, name, &registerCount);
+ // Sampler that is a field of a uniform structure.
+ ASSERT(IsSampler(type.getBasicType()));
+ unsigned int registerIndex = mTextureRegister;
+ mUniformRegisterMap[std::string(name.c_str())] = registerIndex;
+ unsigned int registerCount = type.isArray() ? type.getArraySizeProduct() : 1u;
+ mTextureRegister += registerCount;
+ if (outRegisterCount)
+ {
+ *outRegisterCount = registerCount;
+ }
+ return registerIndex;
}
-void UniformHLSL::outputHLSLSamplerUniformGroup(TInfoSinkBase &out,
- const HLSLTextureSamplerGroup textureGroup,
- const TVector<const TIntermSymbol *> &group,
- unsigned int *groupTextureRegisterIndex)
+void UniformHLSL::outputHLSLSamplerUniformGroup(
+ TInfoSinkBase &out,
+ const HLSLTextureGroup textureGroup,
+ const TVector<const TIntermSymbol *> &group,
+ const TMap<const TIntermSymbol *, TString> &samplerInStructSymbolsToAPINames,
+ unsigned int *groupTextureRegisterIndex)
{
if (group.empty())
{
@@ -140,24 +211,33 @@ void UniformHLSL::outputHLSLSamplerUniformGroup(TInfoSinkBase &out,
const TType &type = uniform->getType();
const TString &name = uniform->getSymbol();
unsigned int registerCount;
- unsigned int samplerArrayIndex =
- declareUniformAndAssignRegister(type, name, &registerCount);
+
+ // The uniform might be just a regular sampler or one extracted from a struct.
+ unsigned int samplerArrayIndex = 0u;
+ const Uniform *uniformByName = findUniformByName(name);
+ if (uniformByName)
+ {
+ samplerArrayIndex = assignUniformRegister(type, name, &registerCount);
+ }
+ else
+ {
+ ASSERT(samplerInStructSymbolsToAPINames.find(uniform) !=
+ samplerInStructSymbolsToAPINames.end());
+ samplerArrayIndex = assignSamplerInStructUniformRegister(
+ type, samplerInStructSymbolsToAPINames.at(uniform), &registerCount);
+ }
groupRegisterCount += registerCount;
+
if (type.isArray())
{
- out << "static const uint " << DecorateIfNeeded(uniform->getName()) << ArrayString(type)
- << " = {";
- for (int i = 0; i < type.getArraySize(); ++i)
- {
- if (i > 0)
- out << ", ";
- out << (samplerArrayIndex + i);
- }
- out << "};\n";
+ out << "static const uint " << DecorateVariableIfNeeded(uniform->getName())
+ << ArrayString(type) << " = ";
+ OutputSamplerIndexArrayInitializer(out, type, samplerArrayIndex);
+ out << ";\n";
}
else
{
- out << "static const uint " << DecorateIfNeeded(uniform->getName()) << " = "
+ out << "static const uint " << DecorateVariableIfNeeded(uniform->getName()) << " = "
<< samplerArrayIndex << ";\n";
}
}
@@ -179,9 +259,88 @@ void UniformHLSL::outputHLSLSamplerUniformGroup(TInfoSinkBase &out,
*groupTextureRegisterIndex += groupRegisterCount;
}
+void UniformHLSL::outputHLSL4_0_FL9_3Sampler(TInfoSinkBase &out,
+ const TType &type,
+ const TName &name,
+ const unsigned int registerIndex)
+{
+ out << "uniform " << SamplerString(type.getBasicType()) << " sampler_"
+ << DecorateVariableIfNeeded(name) << ArrayString(type) << " : register(s"
+ << str(registerIndex) << ");\n";
+ out << "uniform " << TextureString(type.getBasicType()) << " texture_"
+ << DecorateVariableIfNeeded(name) << ArrayString(type) << " : register(t"
+ << str(registerIndex) << ");\n";
+}
+
+void UniformHLSL::outputHLSL4_1_FL11Texture(TInfoSinkBase &out,
+ const TType &type,
+ const TName &name,
+ const unsigned int registerIndex)
+{
+ // TODO(xinghua.cao@intel.com): if image2D variable is bound on one layer of Texture3D or
+ // Texture2DArray. Translate this variable to HLSL Texture3D object or HLSL Texture2DArray
+ // object, or create a temporary Texture2D to save content of the layer and bind the
+ // temporary Texture2D to image2D variable.
+ out << "uniform "
+ << TextureString(type.getBasicType(), type.getLayoutQualifier().imageInternalFormat) << " "
+ << DecorateVariableIfNeeded(name) << ArrayString(type) << " : register(t"
+ << str(registerIndex) << ");\n";
+ return;
+}
+
+void UniformHLSL::outputHLSL4_1_FL11RWTexture(TInfoSinkBase &out,
+ const TType &type,
+ const TName &name,
+ const unsigned int registerIndex)
+{
+ // TODO(xinghua.cao@intel.com): if image2D variable is bound on one layer of Texture3D or
+ // Texture2DArray. Translate this variable to HLSL RWTexture3D object or HLSL RWTexture2DArray
+ // object, or create a temporary Texture2D to save content of the layer and bind the
+ // temporary Texture2D to image2D variable.
+ if (mShaderType == GL_COMPUTE_SHADER)
+ {
+ out << "uniform "
+ << RWTextureString(type.getBasicType(), type.getLayoutQualifier().imageInternalFormat)
+ << " " << DecorateVariableIfNeeded(name) << ArrayString(type) << " : register(u"
+ << str(registerIndex) << ");\n";
+ }
+ else
+ {
+ // TODO(xinghua.cao@intel.com): Support images in vertex shader and fragment shader,
+ // which are needed to sync binding value when linking program.
+ }
+ return;
+}
+
+void UniformHLSL::outputUniform(TInfoSinkBase &out,
+ const TType &type,
+ const TName &name,
+ const unsigned int registerIndex)
+{
+ const TStructure *structure = type.getStruct();
+ // If this is a nameless struct, we need to use its full definition, rather than its (empty)
+ // name.
+ // TypeString() will invoke defineNameless in this case; qualifier prefixes are unnecessary for
+ // nameless structs in ES, as nameless structs cannot be used anywhere that layout qualifiers
+ // are permitted.
+ const TString &typeName = ((structure && !structure->name().empty())
+ ? QualifiedStructNameString(*structure, false, false)
+ : TypeString(type));
+
+ const TString &registerString =
+ TString("register(") + UniformRegisterPrefix(type) + str(registerIndex) + ")";
+
+ out << "uniform " << typeName << " ";
+
+ out << DecorateVariableIfNeeded(name);
+
+ out << ArrayString(type) << " : " << registerString << ";\n";
+}
+
void UniformHLSL::uniformsHeader(TInfoSinkBase &out,
ShShaderOutput outputType,
- const ReferencedSymbols &referencedUniforms)
+ const ReferencedSymbols &referencedUniforms,
+ TSymbolTable *symbolTable)
{
if (!referencedUniforms.empty())
{
@@ -190,45 +349,69 @@ void UniformHLSL::uniformsHeader(TInfoSinkBase &out,
// In the case of HLSL 4, sampler uniforms need to be grouped by type before the code is
// written. They are grouped based on the combination of the HLSL texture type and
// HLSL sampler type, enumerated in HLSLTextureSamplerGroup.
- TVector<TVector<const TIntermSymbol *>> groupedSamplerUniforms;
- groupedSamplerUniforms.resize(HLSL_TEXTURE_MAX + 1);
+ TVector<TVector<const TIntermSymbol *>> groupedSamplerUniforms(HLSL_TEXTURE_MAX + 1);
+ TMap<const TIntermSymbol *, TString> samplerInStructSymbolsToAPINames;
+ TVector<const TIntermSymbol *> imageUniformsHLSL41Output;
for (auto &uniformIt : referencedUniforms)
{
// Output regular uniforms. Group sampler uniforms by type.
const TIntermSymbol &uniform = *uniformIt.second;
- const TType &type = uniform.getType();
- const TString &name = uniform.getSymbol();
+ const TType &type = uniform.getType();
+ const TName &name = uniform.getName();
if (outputType == SH_HLSL_4_1_OUTPUT && IsSampler(type.getBasicType()))
{
- HLSLTextureSamplerGroup group = TextureGroup(type.getBasicType());
+ HLSLTextureGroup group = TextureGroup(type.getBasicType());
groupedSamplerUniforms[group].push_back(&uniform);
}
else if (outputType == SH_HLSL_4_0_FL9_3_OUTPUT && IsSampler(type.getBasicType()))
{
- unsigned int registerIndex = declareUniformAndAssignRegister(type, name);
- out << "uniform " << SamplerString(type.getBasicType()) << " sampler_"
- << DecorateUniform(name, type) << ArrayString(type) << " : register(s"
- << str(registerIndex) << ");\n";
- out << "uniform " << TextureString(type.getBasicType()) << " texture_"
- << DecorateUniform(name, type) << ArrayString(type) << " : register(t"
- << str(registerIndex) << ");\n";
+ unsigned int registerIndex = assignUniformRegister(type, name.getString(), nullptr);
+ outputHLSL4_0_FL9_3Sampler(out, type, name, registerIndex);
+ }
+ else if (outputType == SH_HLSL_4_1_OUTPUT && IsImage(type.getBasicType()))
+ {
+ imageUniformsHLSL41Output.push_back(&uniform);
}
else
{
- unsigned int registerIndex = declareUniformAndAssignRegister(type, name);
- const TStructure *structure = type.getStruct();
- // If this is a nameless struct, we need to use its full definition, rather than its (empty) name.
- // TypeString() will invoke defineNameless in this case; qualifier prefixes are unnecessary for
- // nameless structs in ES, as nameless structs cannot be used anywhere that layout qualifiers are
- // permitted.
- const TString &typeName = ((structure && !structure->name().empty()) ?
- QualifiedStructNameString(*structure, false, false) : TypeString(type));
-
- const TString &registerString = TString("register(") + UniformRegisterPrefix(type) + str(registerIndex) + ")";
-
- out << "uniform " << typeName << " " << DecorateUniform(name, type) << ArrayString(type)
- << " : " << registerString << ";\n";
+ if (type.isStructureContainingSamplers())
+ {
+ TVector<TIntermSymbol *> samplerSymbols;
+ TMap<TIntermSymbol *, TString> symbolsToAPINames;
+ type.createSamplerSymbols("angle_" + name.getString(), name.getString(),
+ &samplerSymbols, &symbolsToAPINames, symbolTable);
+ for (TIntermSymbol *sampler : samplerSymbols)
+ {
+ const TType &samplerType = sampler->getType();
+
+ // Will use angle_ prefix instead of regular prefix.
+ sampler->setInternal(true);
+ const TName &samplerName = sampler->getName();
+
+ if (outputType == SH_HLSL_4_1_OUTPUT)
+ {
+ HLSLTextureGroup group = TextureGroup(samplerType.getBasicType());
+ groupedSamplerUniforms[group].push_back(sampler);
+ samplerInStructSymbolsToAPINames[sampler] = symbolsToAPINames[sampler];
+ }
+ else if (outputType == SH_HLSL_4_0_FL9_3_OUTPUT)
+ {
+ unsigned int registerIndex = assignSamplerInStructUniformRegister(
+ samplerType, symbolsToAPINames[sampler], nullptr);
+ outputHLSL4_0_FL9_3Sampler(out, samplerType, samplerName, registerIndex);
+ }
+ else
+ {
+ ASSERT(outputType == SH_HLSL_3_0_OUTPUT);
+ unsigned int registerIndex = assignSamplerInStructUniformRegister(
+ samplerType, symbolsToAPINames[sampler], nullptr);
+ outputUniform(out, samplerType, samplerName, registerIndex);
+ }
+ }
+ }
+ unsigned int registerIndex = assignUniformRegister(type, name.getString(), nullptr);
+ outputUniform(out, type, name, registerIndex);
}
}
@@ -239,70 +422,114 @@ void UniformHLSL::uniformsHeader(TInfoSinkBase &out,
ASSERT(HLSL_TEXTURE_MIN == HLSL_TEXTURE_2D);
for (int groupId = HLSL_TEXTURE_MIN; groupId < HLSL_TEXTURE_MAX; ++groupId)
{
- outputHLSLSamplerUniformGroup(out, HLSLTextureSamplerGroup(groupId),
- groupedSamplerUniforms[groupId],
- &groupTextureRegisterIndex);
+ outputHLSLSamplerUniformGroup(
+ out, HLSLTextureGroup(groupId), groupedSamplerUniforms[groupId],
+ samplerInStructSymbolsToAPINames, &groupTextureRegisterIndex);
+ }
+ mSamplerCount = groupTextureRegisterIndex;
+
+ for (const TIntermSymbol *image : imageUniformsHLSL41Output)
+ {
+ const TType &type = image->getType();
+ const TName &name = image->getName();
+ unsigned int registerIndex = assignUniformRegister(type, name.getString(), nullptr);
+ if (type.getMemoryQualifier().readonly)
+ {
+ outputHLSL4_1_FL11Texture(out, type, name, registerIndex);
+ }
+ else
+ {
+ outputHLSL4_1_FL11RWTexture(out, type, name, registerIndex);
+ }
}
}
}
-TString UniformHLSL::interfaceBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks)
+void UniformHLSL::samplerMetadataUniforms(TInfoSinkBase &out, const char *reg)
+{
+ // If mSamplerCount is 0 the shader doesn't use any textures for samplers.
+ if (mSamplerCount > 0)
+ {
+ out << " struct SamplerMetadata\n"
+ " {\n"
+ " int baseLevel;\n"
+ " int internalFormatBits;\n"
+ " int wrapModes;\n"
+ " int padding;\n"
+ " };\n"
+ " SamplerMetadata samplerMetadata["
+ << mSamplerCount << "] : packoffset(" << reg << ");\n";
+ }
+}
+
+TString UniformHLSL::uniformBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks)
{
TString interfaceBlocks;
for (ReferencedSymbols::const_iterator interfaceBlockIt = referencedInterfaceBlocks.begin();
interfaceBlockIt != referencedInterfaceBlocks.end(); interfaceBlockIt++)
{
- const TType &nodeType = interfaceBlockIt->second->getType();
+ const TType &nodeType = interfaceBlockIt->second->getType();
const TInterfaceBlock &interfaceBlock = *nodeType.getInterfaceBlock();
- unsigned int arraySize = static_cast<unsigned int>(interfaceBlock.arraySize());
- unsigned int activeRegister = mInterfaceBlockRegister;
+ // nodeType.isInterfaceBlock() == false means the node is a field of a uniform block which
+ // doesn't have instance name, so this block cannot be an array.
+ unsigned int interfaceBlockArraySize = 0u;
+ if (nodeType.isInterfaceBlock() && nodeType.isArray())
+ {
+ interfaceBlockArraySize = nodeType.getOutermostArraySize();
+ }
+ unsigned int activeRegister = mUniformBlockRegister;
- mInterfaceBlockRegisterMap[interfaceBlock.name().c_str()] = activeRegister;
- mInterfaceBlockRegister += std::max(1u, arraySize);
+ mUniformBlockRegisterMap[interfaceBlock.name().c_str()] = activeRegister;
+ mUniformBlockRegister += std::max(1u, interfaceBlockArraySize);
// FIXME: interface block field names
if (interfaceBlock.hasInstanceName())
{
- interfaceBlocks += interfaceBlockStructString(interfaceBlock);
+ interfaceBlocks += uniformBlockStructString(interfaceBlock);
}
- if (arraySize > 0)
+ if (interfaceBlockArraySize > 0)
{
- for (unsigned int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++)
+ for (unsigned int arrayIndex = 0; arrayIndex < interfaceBlockArraySize; arrayIndex++)
{
- interfaceBlocks += interfaceBlockString(interfaceBlock, activeRegister + arrayIndex, arrayIndex);
+ interfaceBlocks +=
+ uniformBlockString(interfaceBlock, activeRegister + arrayIndex, arrayIndex);
}
}
else
{
- interfaceBlocks += interfaceBlockString(interfaceBlock, activeRegister, GL_INVALID_INDEX);
+ interfaceBlocks += uniformBlockString(interfaceBlock, activeRegister, GL_INVALID_INDEX);
}
}
- return (interfaceBlocks.empty() ? "" : ("// Interface Blocks\n\n" + interfaceBlocks));
+ return (interfaceBlocks.empty() ? "" : ("// Uniform Blocks\n\n" + interfaceBlocks));
}
-TString UniformHLSL::interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex)
+TString UniformHLSL::uniformBlockString(const TInterfaceBlock &interfaceBlock,
+ unsigned int registerIndex,
+ unsigned int arrayIndex)
{
- const TString &arrayIndexString = (arrayIndex != GL_INVALID_INDEX ? Decorate(str(arrayIndex)) : "");
+ const TString &arrayIndexString =
+ (arrayIndex != GL_INVALID_INDEX ? Decorate(str(arrayIndex)) : "");
const TString &blockName = interfaceBlock.name() + arrayIndexString;
TString hlsl;
- hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) + ")\n"
+ hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) +
+ ")\n"
"{\n";
if (interfaceBlock.hasInstanceName())
{
hlsl += " " + InterfaceBlockStructName(interfaceBlock) + " " +
- interfaceBlockInstanceString(interfaceBlock, arrayIndex) + ";\n";
+ uniformBlockInstanceString(interfaceBlock, arrayIndex) + ";\n";
}
else
{
const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage();
- hlsl += interfaceBlockMembersString(interfaceBlock, blockStorage);
+ hlsl += uniformBlockMembersString(interfaceBlock, blockStorage);
}
hlsl += "};\n\n";
@@ -310,13 +537,14 @@ TString UniformHLSL::interfaceBlockString(const TInterfaceBlock &interfaceBlock,
return hlsl;
}
-TString UniformHLSL::interfaceBlockInstanceString(const TInterfaceBlock& interfaceBlock, unsigned int arrayIndex)
+TString UniformHLSL::uniformBlockInstanceString(const TInterfaceBlock &interfaceBlock,
+ unsigned int arrayIndex)
{
if (!interfaceBlock.hasInstanceName())
{
return "";
}
- else if (interfaceBlock.isArray())
+ else if (arrayIndex != GL_INVALID_INDEX)
{
return DecoratePrivate(interfaceBlock.instanceName()) + "_" + str(arrayIndex);
}
@@ -326,7 +554,8 @@ TString UniformHLSL::interfaceBlockInstanceString(const TInterfaceBlock& interfa
}
}
-TString UniformHLSL::interfaceBlockMembersString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage)
+TString UniformHLSL::uniformBlockMembersString(const TInterfaceBlock &interfaceBlock,
+ TLayoutBlockStorage blockStorage)
{
TString hlsl;
@@ -334,7 +563,7 @@ TString UniformHLSL::interfaceBlockMembersString(const TInterfaceBlock &interfac
for (unsigned int typeIndex = 0; typeIndex < interfaceBlock.fields().size(); typeIndex++)
{
- const TField &field = *interfaceBlock.fields()[typeIndex];
+ const TField &field = *interfaceBlock.fields()[typeIndex];
const TType &fieldType = *field.type();
if (blockStorage == EbsStd140)
@@ -343,13 +572,15 @@ TString UniformHLSL::interfaceBlockMembersString(const TInterfaceBlock &interfac
hlsl += padHelper.prePaddingString(fieldType);
}
- hlsl += " " + InterfaceBlockFieldTypeString(field, blockStorage) +
- " " + Decorate(field.name()) + ArrayString(fieldType) + ";\n";
+ hlsl += " " + InterfaceBlockFieldTypeString(field, blockStorage) + " " +
+ Decorate(field.name()) + ArrayString(fieldType) + ";\n";
- // must pad out after matrices and arrays, where HLSL usually allows itself room to pack stuff
+ // must pad out after matrices and arrays, where HLSL usually allows itself room to pack
+ // stuff
if (blockStorage == EbsStd140)
{
- const bool useHLSLRowMajorPacking = (fieldType.getLayoutQualifier().matrixPacking == EmpColumnMajor);
+ const bool useHLSLRowMajorPacking =
+ (fieldType.getLayoutQualifier().matrixPacking == EmpColumnMajor);
hlsl += padHelper.postPaddingString(fieldType, useHLSLRowMajorPacking);
}
}
@@ -357,14 +588,13 @@ TString UniformHLSL::interfaceBlockMembersString(const TInterfaceBlock &interfac
return hlsl;
}
-TString UniformHLSL::interfaceBlockStructString(const TInterfaceBlock &interfaceBlock)
+TString UniformHLSL::uniformBlockStructString(const TInterfaceBlock &interfaceBlock)
{
const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage();
- return "struct " + InterfaceBlockStructName(interfaceBlock) + "\n"
+ return "struct " + InterfaceBlockStructName(interfaceBlock) +
+ "\n"
"{\n" +
- interfaceBlockMembersString(interfaceBlock, blockStorage) +
- "};\n\n";
+ uniformBlockMembersString(interfaceBlock, blockStorage) + "};\n\n";
}
-
}
diff --git a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h
index 0f51f349bb..8784e50533 100644
--- a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h
@@ -4,7 +4,7 @@
// found in the LICENSE file.
//
// UniformHLSL.h:
-// Methods for GLSL to HLSL translation for uniforms and interface blocks.
+// Methods for GLSL to HLSL translation for uniforms and uniform blocks.
//
#ifndef COMPILER_TRANSLATOR_UNIFORMHLSL_H_
@@ -16,29 +16,35 @@
namespace sh
{
class StructureHLSL;
+class TSymbolTable;
class UniformHLSL : angle::NonCopyable
{
public:
- UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType, const std::vector<Uniform> &uniforms);
+ UniformHLSL(sh::GLenum shaderType,
+ StructureHLSL *structureHLSL,
+ ShShaderOutput outputType,
+ const std::vector<Uniform> &uniforms);
void reserveUniformRegisters(unsigned int registerCount);
- void reserveInterfaceBlockRegisters(unsigned int registerCount);
- void outputHLSLSamplerUniformGroup(TInfoSinkBase &out,
- const HLSLTextureSamplerGroup textureGroup,
- const TVector<const TIntermSymbol *> &group,
- unsigned int *groupTextureRegisterIndex);
+ void reserveUniformBlockRegisters(unsigned int registerCount);
void uniformsHeader(TInfoSinkBase &out,
ShShaderOutput outputType,
- const ReferencedSymbols &referencedUniforms);
- TString interfaceBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks);
+ const ReferencedSymbols &referencedUniforms,
+ TSymbolTable *symbolTable);
+
+ // Must be called after uniformsHeader
+ void samplerMetadataUniforms(TInfoSinkBase &out, const char *reg);
+
+ TString uniformBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks);
// Used for direct index references
- static TString interfaceBlockInstanceString(const TInterfaceBlock& interfaceBlock, unsigned int arrayIndex);
+ static TString uniformBlockInstanceString(const TInterfaceBlock &interfaceBlock,
+ unsigned int arrayIndex);
- const std::map<std::string, unsigned int> &getInterfaceBlockRegisterMap() const
+ const std::map<std::string, unsigned int> &getUniformBlockRegisterMap() const
{
- return mInterfaceBlockRegisterMap;
+ return mUniformBlockRegisterMap;
}
const std::map<std::string, unsigned int> &getUniformRegisterMap() const
{
@@ -46,28 +52,59 @@ class UniformHLSL : angle::NonCopyable
}
private:
- TString interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex);
- TString interfaceBlockMembersString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage);
- TString interfaceBlockStructString(const TInterfaceBlock &interfaceBlock);
+ TString uniformBlockString(const TInterfaceBlock &interfaceBlock,
+ unsigned int registerIndex,
+ unsigned int arrayIndex);
+ TString uniformBlockMembersString(const TInterfaceBlock &interfaceBlock,
+ TLayoutBlockStorage blockStorage);
+ TString uniformBlockStructString(const TInterfaceBlock &interfaceBlock);
const Uniform *findUniformByName(const TString &name) const;
+ void outputHLSL4_0_FL9_3Sampler(TInfoSinkBase &out,
+ const TType &type,
+ const TName &name,
+ const unsigned int registerIndex);
+ void outputHLSL4_1_FL11Texture(TInfoSinkBase &out,
+ const TType &type,
+ const TName &name,
+ const unsigned int registerIndex);
+ void outputHLSL4_1_FL11RWTexture(TInfoSinkBase &out,
+ const TType &type,
+ const TName &name,
+ const unsigned int registerIndex);
+ void outputUniform(TInfoSinkBase &out,
+ const TType &type,
+ const TName &name,
+ const unsigned int registerIndex);
+
// Returns the uniform's register index
- unsigned int declareUniformAndAssignRegister(const TType &type,
- const TString &name,
- unsigned int *registerCount);
- unsigned int declareUniformAndAssignRegister(const TType &type, const TString &name);
+ unsigned int assignUniformRegister(const TType &type,
+ const TString &name,
+ unsigned int *outRegisterCount);
+ unsigned int assignSamplerInStructUniformRegister(const TType &type,
+ const TString &name,
+ unsigned int *outRegisterCount);
+
+ void outputHLSLSamplerUniformGroup(
+ TInfoSinkBase &out,
+ const HLSLTextureGroup textureGroup,
+ const TVector<const TIntermSymbol *> &group,
+ const TMap<const TIntermSymbol *, TString> &samplerInStructSymbolsToAPINames,
+ unsigned int *groupTextureRegisterIndex);
unsigned int mUniformRegister;
- unsigned int mInterfaceBlockRegister;
- unsigned int mSamplerRegister;
+ unsigned int mUniformBlockRegister;
+ unsigned int mTextureRegister;
+ unsigned int mRWTextureRegister;
+ unsigned int mSamplerCount;
+ sh::GLenum mShaderType;
StructureHLSL *mStructureHLSL;
ShShaderOutput mOutputType;
const std::vector<Uniform> &mUniforms;
- std::map<std::string, unsigned int> mInterfaceBlockRegisterMap;
+ std::map<std::string, unsigned int> mUniformBlockRegisterMap;
std::map<std::string, unsigned int> mUniformRegisterMap;
};
-
}
-#endif // COMPILER_TRANSLATOR_UNIFORMHLSL_H_
+#endif // COMPILER_TRANSLATOR_UNIFORMHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.cpp b/src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.cpp
new file mode 100644
index 0000000000..40bd42afad
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.cpp
@@ -0,0 +1,105 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// UseInterfaceBlockFields.cpp: insert statements to reference all members in InterfaceBlock list at
+// the beginning of main. This is to work around a Mac driver that treats unused standard/shared
+// uniform blocks as inactive.
+
+#include "compiler/translator/UseInterfaceBlockFields.h"
+
+#include "compiler/translator/FindMain.h"
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermNode_util.h"
+#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/util.h"
+
+namespace sh
+{
+
+namespace
+{
+
+void AddNodeUseStatements(TIntermTyped *node, TIntermSequence *sequence)
+{
+ if (node->isArray())
+ {
+ for (unsigned int i = 0u; i < node->getOutermostArraySize(); ++i)
+ {
+ TIntermBinary *element =
+ new TIntermBinary(EOpIndexDirect, node->deepCopy(), CreateIndexNode(i));
+ AddNodeUseStatements(element, sequence);
+ }
+ }
+ else
+ {
+ sequence->insert(sequence->begin(), node);
+ }
+}
+
+void AddFieldUseStatements(const ShaderVariable &var,
+ TIntermSequence *sequence,
+ const TSymbolTable &symbolTable)
+{
+ TString name = TString(var.name.c_str());
+ ASSERT(name.find_last_of('[') == TString::npos);
+ TIntermSymbol *symbol = ReferenceGlobalVariable(name, symbolTable);
+ AddNodeUseStatements(symbol, sequence);
+}
+
+void InsertUseCode(const InterfaceBlock &block, TIntermTyped *blockNode, TIntermSequence *sequence)
+{
+ for (unsigned int i = 0; i < block.fields.size(); ++i)
+ {
+ TIntermBinary *element = new TIntermBinary(EOpIndexDirectInterfaceBlock,
+ blockNode->deepCopy(), CreateIndexNode(i));
+ sequence->insert(sequence->begin(), element);
+ }
+}
+
+void InsertUseCode(TIntermSequence *sequence,
+ const InterfaceBlockList &blocks,
+ const TSymbolTable &symbolTable)
+{
+ for (const auto &block : blocks)
+ {
+ if (block.instanceName.empty())
+ {
+ for (const auto &var : block.fields)
+ {
+ AddFieldUseStatements(var, sequence, symbolTable);
+ }
+ }
+ else if (block.arraySize > 0u)
+ {
+ TString name(block.instanceName.c_str());
+ TIntermSymbol *arraySymbol = ReferenceGlobalVariable(name, symbolTable);
+ for (unsigned int i = 0u; i < block.arraySize; ++i)
+ {
+ TIntermBinary *elementSymbol =
+ new TIntermBinary(EOpIndexDirect, arraySymbol->deepCopy(), CreateIndexNode(i));
+ InsertUseCode(block, elementSymbol, sequence);
+ }
+ }
+ else
+ {
+ TString name(block.instanceName.c_str());
+ TIntermSymbol *blockSymbol = ReferenceGlobalVariable(name, symbolTable);
+ InsertUseCode(block, blockSymbol, sequence);
+ }
+ }
+}
+
+} // namespace anonymous
+
+void UseInterfaceBlockFields(TIntermBlock *root,
+ const InterfaceBlockList &blocks,
+ const TSymbolTable &symbolTable)
+{
+ TIntermBlock *mainBody = FindMainBody(root);
+ InsertUseCode(mainBody->getSequence(), blocks, symbolTable);
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.h b/src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.h
new file mode 100644
index 0000000000..3e2a4815d4
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/UseInterfaceBlockFields.h
@@ -0,0 +1,30 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// UseInterfaceBlockFields.h: insert statements to reference all members in InterfaceBlock list at
+// the beginning of main. This is to work around a Mac driver that treats unused standard/shared
+// uniform blocks as inactive.
+
+#ifndef COMPILER_TRANSLATOR_USEINTERFACEBLOCKFIELDS_H_
+#define COMPILER_TRANSLATOR_USEINTERFACEBLOCKFIELDS_H_
+
+#include <GLSLANG/ShaderLang.h>
+
+namespace sh
+{
+
+class TIntermBlock;
+class TSymbolTable;
+
+using InterfaceBlockList = std::vector<sh::InterfaceBlock>;
+
+void UseInterfaceBlockFields(TIntermBlock *root,
+ const InterfaceBlockList &blocks,
+ const TSymbolTable &symbolTable);
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_USEINTERFACEBLOCKFIELDS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp
index 404ccee75d..8a77f0049a 100644
--- a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp
@@ -27,7 +27,7 @@ TString SamplerString(const TBasicType type)
}
}
-TString SamplerString(HLSLTextureSamplerGroup type)
+TString SamplerString(HLSLTextureGroup type)
{
if (type >= HLSL_COMPARISON_SAMPLER_GROUP_BEGIN && type <= HLSL_COMPARISON_SAMPLER_GROUP_END)
{
@@ -39,7 +39,8 @@ TString SamplerString(HLSLTextureSamplerGroup type)
}
}
-HLSLTextureSamplerGroup TextureGroup(const TBasicType type)
+HLSLTextureGroup TextureGroup(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
+
{
switch (type)
{
@@ -53,6 +54,8 @@ HLSLTextureSamplerGroup TextureGroup(const TBasicType type)
return HLSL_TEXTURE_2D_ARRAY;
case EbtSampler3D:
return HLSL_TEXTURE_3D;
+ case EbtSampler2DMS:
+ return HLSL_TEXTURE_2D_MS;
case EbtISampler2D:
return HLSL_TEXTURE_2D_INT4;
case EbtISampler3D:
@@ -61,6 +64,8 @@ HLSLTextureSamplerGroup TextureGroup(const TBasicType type)
return HLSL_TEXTURE_2D_ARRAY_INT4;
case EbtISampler2DArray:
return HLSL_TEXTURE_2D_ARRAY_INT4;
+ case EbtISampler2DMS:
+ return HLSL_TEXTURE_2D_MS_INT4;
case EbtUSampler2D:
return HLSL_TEXTURE_2D_UINT4;
case EbtUSampler3D:
@@ -69,42 +74,196 @@ HLSLTextureSamplerGroup TextureGroup(const TBasicType type)
return HLSL_TEXTURE_2D_ARRAY_UINT4;
case EbtUSampler2DArray:
return HLSL_TEXTURE_2D_ARRAY_UINT4;
+ case EbtUSampler2DMS:
+ return HLSL_TEXTURE_2D_MS_UINT4;
case EbtSampler2DShadow:
return HLSL_TEXTURE_2D_COMPARISON;
case EbtSamplerCubeShadow:
return HLSL_TEXTURE_CUBE_COMPARISON;
case EbtSampler2DArrayShadow:
return HLSL_TEXTURE_2D_ARRAY_COMPARISON;
+ case EbtImage2D:
+ {
+ switch (imageInternalFormat)
+ {
+ case EiifRGBA32F:
+ case EiifRGBA16F:
+ case EiifR32F:
+ return HLSL_TEXTURE_2D;
+ case EiifRGBA8:
+ return HLSL_TEXTURE_2D_UNORM;
+ case EiifRGBA8_SNORM:
+ return HLSL_TEXTURE_2D_SNORM;
+ default:
+ UNREACHABLE();
+ }
+ }
+ case EbtIImage2D:
+ {
+ switch (imageInternalFormat)
+ {
+ case EiifRGBA32I:
+ case EiifRGBA16I:
+ case EiifRGBA8I:
+ case EiifR32I:
+ return HLSL_TEXTURE_2D_INT4;
+ default:
+ UNREACHABLE();
+ }
+ }
+ case EbtUImage2D:
+ {
+ switch (imageInternalFormat)
+ {
+
+ case EiifRGBA32UI:
+ case EiifRGBA16UI:
+ case EiifRGBA8UI:
+ case EiifR32UI:
+ return HLSL_TEXTURE_2D_UINT4;
+ default:
+ UNREACHABLE();
+ }
+ }
+ case EbtImage3D:
+ {
+ switch (imageInternalFormat)
+ {
+ case EiifRGBA32F:
+ case EiifRGBA16F:
+ case EiifR32F:
+ return HLSL_TEXTURE_3D;
+ case EiifRGBA8:
+ return HLSL_TEXTURE_3D_UNORM;
+ case EiifRGBA8_SNORM:
+ return HLSL_TEXTURE_3D_SNORM;
+ default:
+ UNREACHABLE();
+ }
+ }
+ case EbtIImage3D:
+ {
+ switch (imageInternalFormat)
+ {
+ case EiifRGBA32I:
+ case EiifRGBA16I:
+ case EiifRGBA8I:
+ case EiifR32I:
+ return HLSL_TEXTURE_3D_INT4;
+ default:
+ UNREACHABLE();
+ }
+ }
+ case EbtUImage3D:
+ {
+ switch (imageInternalFormat)
+ {
+ case EiifRGBA32UI:
+ case EiifRGBA16UI:
+ case EiifRGBA8UI:
+ case EiifR32UI:
+ return HLSL_TEXTURE_3D_UINT4;
+ default:
+ UNREACHABLE();
+ }
+ }
+ case EbtImage2DArray:
+ case EbtImageCube:
+ {
+ switch (imageInternalFormat)
+ {
+ case EiifRGBA32F:
+ case EiifRGBA16F:
+ case EiifR32F:
+ return HLSL_TEXTURE_2D_ARRAY;
+ case EiifRGBA8:
+ return HLSL_TEXTURE_2D_ARRAY_UNORN;
+ case EiifRGBA8_SNORM:
+ return HLSL_TEXTURE_2D_ARRAY_SNORM;
+ default:
+ UNREACHABLE();
+ }
+ }
+ case EbtIImage2DArray:
+ case EbtIImageCube:
+ {
+ switch (imageInternalFormat)
+ {
+ case EiifRGBA32I:
+ case EiifRGBA16I:
+ case EiifRGBA8I:
+ case EiifR32I:
+ return HLSL_TEXTURE_2D_ARRAY_INT4;
+ default:
+ UNREACHABLE();
+ }
+ }
+ case EbtUImage2DArray:
+ case EbtUImageCube:
+ {
+ switch (imageInternalFormat)
+ {
+ case EiifRGBA32UI:
+ case EiifRGBA16UI:
+ case EiifRGBA8UI:
+ case EiifR32UI:
+ return HLSL_TEXTURE_2D_ARRAY_UINT4;
+ default:
+ UNREACHABLE();
+ }
+ }
default:
UNREACHABLE();
}
return HLSL_TEXTURE_UNKNOWN;
}
-TString TextureString(const HLSLTextureSamplerGroup type)
+TString TextureString(const HLSLTextureGroup textureGroup)
{
- switch (type)
+ switch (textureGroup)
{
case HLSL_TEXTURE_2D:
- return "Texture2D";
+ return "Texture2D<float4>";
case HLSL_TEXTURE_CUBE:
- return "TextureCube";
+ return "TextureCube<float4>";
case HLSL_TEXTURE_2D_ARRAY:
- return "Texture2DArray";
+ return "Texture2DArray<float4>";
case HLSL_TEXTURE_3D:
- return "Texture3D";
+ return "Texture3D<float4>";
+ case HLSL_TEXTURE_2D_UNORM:
+ return "Texture2D<unorm float4>";
+ case HLSL_TEXTURE_CUBE_UNORM:
+ return "TextureCube<unorm float4>";
+ case HLSL_TEXTURE_2D_ARRAY_UNORN:
+ return "Texture2DArray<unorm float4>";
+ case HLSL_TEXTURE_3D_UNORM:
+ return "Texture3D<unorm float4>";
+ case HLSL_TEXTURE_2D_SNORM:
+ return "Texture2D<snorm float4>";
+ case HLSL_TEXTURE_CUBE_SNORM:
+ return "TextureCube<snorm float4>";
+ case HLSL_TEXTURE_2D_ARRAY_SNORM:
+ return "Texture2DArray<snorm float4>";
+ case HLSL_TEXTURE_3D_SNORM:
+ return "Texture3D<snorm float4>";
+ case HLSL_TEXTURE_2D_MS:
+ return "Texture2DMS<float4>";
case HLSL_TEXTURE_2D_INT4:
return "Texture2D<int4>";
case HLSL_TEXTURE_3D_INT4:
return "Texture3D<int4>";
case HLSL_TEXTURE_2D_ARRAY_INT4:
return "Texture2DArray<int4>";
+ case HLSL_TEXTURE_2D_MS_INT4:
+ return "Texture2DMS<int4>";
case HLSL_TEXTURE_2D_UINT4:
return "Texture2D<uint4>";
case HLSL_TEXTURE_3D_UINT4:
return "Texture3D<uint4>";
case HLSL_TEXTURE_2D_ARRAY_UINT4:
return "Texture2DArray<uint4>";
+ case HLSL_TEXTURE_2D_MS_UINT4:
+ return "Texture2DMS<uint4>";
case HLSL_TEXTURE_2D_COMPARISON:
return "Texture2D";
case HLSL_TEXTURE_CUBE_COMPARISON:
@@ -115,15 +274,15 @@ TString TextureString(const HLSLTextureSamplerGroup type)
UNREACHABLE();
}
- return "<unknown texture type>";
+ return "<unknown read texture type>";
}
-TString TextureString(const TBasicType type)
+TString TextureString(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
{
- return TextureString(TextureGroup(type));
+ return TextureString(TextureGroup(type, imageInternalFormat));
}
-TString TextureGroupSuffix(const HLSLTextureSamplerGroup type)
+TString TextureGroupSuffix(const HLSLTextureGroup type)
{
switch (type)
{
@@ -135,18 +294,40 @@ TString TextureGroupSuffix(const HLSLTextureSamplerGroup type)
return "2DArray";
case HLSL_TEXTURE_3D:
return "3D";
+ case HLSL_TEXTURE_2D_UNORM:
+ return "2D_unorm_float4_";
+ case HLSL_TEXTURE_CUBE_UNORM:
+ return "Cube_unorm_float4_";
+ case HLSL_TEXTURE_2D_ARRAY_UNORN:
+ return "2DArray_unorm_float4_";
+ case HLSL_TEXTURE_3D_UNORM:
+ return "3D_unorm_float4_";
+ case HLSL_TEXTURE_2D_SNORM:
+ return "2D_snorm_float4_";
+ case HLSL_TEXTURE_CUBE_SNORM:
+ return "Cube_snorm_float4_";
+ case HLSL_TEXTURE_2D_ARRAY_SNORM:
+ return "2DArray_snorm_float4_";
+ case HLSL_TEXTURE_3D_SNORM:
+ return "3D_snorm_float4_";
+ case HLSL_TEXTURE_2D_MS:
+ return "2DMS";
case HLSL_TEXTURE_2D_INT4:
return "2D_int4_";
case HLSL_TEXTURE_3D_INT4:
return "3D_int4_";
case HLSL_TEXTURE_2D_ARRAY_INT4:
return "2DArray_int4_";
+ case HLSL_TEXTURE_2D_MS_INT4:
+ return "2DMS_int4_";
case HLSL_TEXTURE_2D_UINT4:
return "2D_uint4_";
case HLSL_TEXTURE_3D_UINT4:
return "3D_uint4_";
case HLSL_TEXTURE_2D_ARRAY_UINT4:
return "2DArray_uint4_";
+ case HLSL_TEXTURE_2D_MS_UINT4:
+ return "2DMS_uint4_";
case HLSL_TEXTURE_2D_COMPARISON:
return "2D_comparison";
case HLSL_TEXTURE_CUBE_COMPARISON:
@@ -160,12 +341,12 @@ TString TextureGroupSuffix(const HLSLTextureSamplerGroup type)
return "<unknown texture type>";
}
-TString TextureGroupSuffix(const TBasicType type)
+TString TextureGroupSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
{
- return TextureGroupSuffix(TextureGroup(type));
+ return TextureGroupSuffix(TextureGroup(type, imageInternalFormat));
}
-TString TextureTypeSuffix(const TBasicType type)
+TString TextureTypeSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
{
switch (type)
{
@@ -173,20 +354,340 @@ TString TextureTypeSuffix(const TBasicType type)
return "Cube_int4_";
case EbtUSamplerCube:
return "Cube_uint4_";
+ case EbtSamplerExternalOES:
+ return "_External";
+ case EbtImageCube:
+ {
+ switch (imageInternalFormat)
+ {
+ case EiifRGBA32F:
+ case EiifRGBA16F:
+ case EiifR32F:
+ return "Cube_float4_";
+ case EiifRGBA8:
+ return "Cube_unorm_float4_";
+ case EiifRGBA8_SNORM:
+ return "Cube_snorm_float4_";
+ default:
+ UNREACHABLE();
+ }
+ }
+ case EbtIImageCube:
+ {
+ switch (imageInternalFormat)
+ {
+ case EiifRGBA32I:
+ case EiifRGBA16I:
+ case EiifRGBA8I:
+ case EiifR32I:
+ return "Cube_int4_";
+ default:
+ UNREACHABLE();
+ }
+ }
+ case EbtUImageCube:
+ {
+ switch (imageInternalFormat)
+ {
+ case EiifRGBA32UI:
+ case EiifRGBA16UI:
+ case EiifRGBA8UI:
+ case EiifR32UI:
+ return "Cube_uint4_";
+ default:
+ UNREACHABLE();
+ }
+ }
default:
// All other types are identified by their group suffix
- return TextureGroupSuffix(type);
+ return TextureGroupSuffix(type, imageInternalFormat);
+ }
+}
+
+HLSLRWTextureGroup RWTextureGroup(const TBasicType type,
+ TLayoutImageInternalFormat imageInternalFormat)
+
+{
+ switch (type)
+ {
+ case EbtImage2D:
+ {
+ switch (imageInternalFormat)
+ {
+ case EiifRGBA32F:
+ case EiifRGBA16F:
+ case EiifR32F:
+ return HLSL_RWTEXTURE_2D_FLOAT4;
+ case EiifRGBA8:
+ return HLSL_RWTEXTURE_2D_UNORM;
+ case EiifRGBA8_SNORM:
+ return HLSL_RWTEXTURE_2D_SNORM;
+ default:
+ UNREACHABLE();
+ }
+ }
+ case EbtIImage2D:
+ {
+ switch (imageInternalFormat)
+ {
+ case EiifRGBA32I:
+ case EiifRGBA16I:
+ case EiifRGBA8I:
+ case EiifR32I:
+ return HLSL_RWTEXTURE_2D_INT4;
+ default:
+ UNREACHABLE();
+ }
+ }
+ case EbtUImage2D:
+ {
+ switch (imageInternalFormat)
+ {
+
+ case EiifRGBA32UI:
+ case EiifRGBA16UI:
+ case EiifRGBA8UI:
+ case EiifR32UI:
+ return HLSL_RWTEXTURE_2D_UINT4;
+ default:
+ UNREACHABLE();
+ }
+ }
+ case EbtImage3D:
+ {
+ switch (imageInternalFormat)
+ {
+ case EiifRGBA32F:
+ case EiifRGBA16F:
+ case EiifR32F:
+ return HLSL_RWTEXTURE_3D_FLOAT4;
+ case EiifRGBA8:
+ return HLSL_RWTEXTURE_3D_UNORM;
+ case EiifRGBA8_SNORM:
+ return HLSL_RWTEXTURE_3D_SNORM;
+ default:
+ UNREACHABLE();
+ }
+ }
+ case EbtIImage3D:
+ {
+ switch (imageInternalFormat)
+ {
+ case EiifRGBA32I:
+ case EiifRGBA16I:
+ case EiifRGBA8I:
+ case EiifR32I:
+ return HLSL_RWTEXTURE_3D_INT4;
+ default:
+ UNREACHABLE();
+ }
+ }
+ case EbtUImage3D:
+ {
+ switch (imageInternalFormat)
+ {
+ case EiifRGBA32UI:
+ case EiifRGBA16UI:
+ case EiifRGBA8UI:
+ case EiifR32UI:
+ return HLSL_RWTEXTURE_3D_UINT4;
+ default:
+ UNREACHABLE();
+ }
+ }
+ case EbtImage2DArray:
+ case EbtImageCube:
+ {
+ switch (imageInternalFormat)
+ {
+ case EiifRGBA32F:
+ case EiifRGBA16F:
+ case EiifR32F:
+ return HLSL_RWTEXTURE_2D_ARRAY_FLOAT4;
+ case EiifRGBA8:
+ return HLSL_RWTEXTURE_2D_ARRAY_UNORN;
+ case EiifRGBA8_SNORM:
+ return HLSL_RWTEXTURE_2D_ARRAY_SNORM;
+ default:
+ UNREACHABLE();
+ }
+ }
+ case EbtIImage2DArray:
+ case EbtIImageCube:
+ {
+ switch (imageInternalFormat)
+ {
+ case EiifRGBA32I:
+ case EiifRGBA16I:
+ case EiifRGBA8I:
+ case EiifR32I:
+ return HLSL_RWTEXTURE_2D_ARRAY_INT4;
+ default:
+ UNREACHABLE();
+ }
+ }
+ case EbtUImage2DArray:
+ case EbtUImageCube:
+ {
+ switch (imageInternalFormat)
+ {
+ case EiifRGBA32UI:
+ case EiifRGBA16UI:
+ case EiifRGBA8UI:
+ case EiifR32UI:
+ return HLSL_RWTEXTURE_2D_ARRAY_UINT4;
+ default:
+ UNREACHABLE();
+ }
+ }
+ default:
+ UNREACHABLE();
}
+ return HLSL_RWTEXTURE_UNKNOWN;
}
-TString DecorateUniform(const TString &string, const TType &type)
+TString RWTextureString(const HLSLRWTextureGroup RWTextureGroup)
{
- if (type.getBasicType() == EbtSamplerExternalOES)
+ switch (RWTextureGroup)
{
- return "ex_" + string;
+ case HLSL_RWTEXTURE_2D_FLOAT4:
+ return "RWTexture2D<float4>";
+ case HLSL_RWTEXTURE_2D_ARRAY_FLOAT4:
+ return "RWTexture2DArray<float4>";
+ case HLSL_RWTEXTURE_3D_FLOAT4:
+ return "RWTexture3D<float4>";
+ case HLSL_RWTEXTURE_2D_UNORM:
+ return "RWTexture2D<unorm float4>";
+ case HLSL_RWTEXTURE_2D_ARRAY_UNORN:
+ return "RWTexture2DArray<unorm float4>";
+ case HLSL_RWTEXTURE_3D_UNORM:
+ return "RWTexture3D<unorm float4>";
+ case HLSL_RWTEXTURE_2D_SNORM:
+ return "RWTexture2D<snorm float4>";
+ case HLSL_RWTEXTURE_2D_ARRAY_SNORM:
+ return "RWTexture2DArray<snorm float4>";
+ case HLSL_RWTEXTURE_3D_SNORM:
+ return "RWTexture3D<snorm float4>";
+ case HLSL_RWTEXTURE_2D_UINT4:
+ return "RWTexture2D<uint4>";
+ case HLSL_RWTEXTURE_2D_ARRAY_UINT4:
+ return "RWTexture2DArray<uint4>";
+ case HLSL_RWTEXTURE_3D_UINT4:
+ return "RWTexture3D<uint4>";
+ case HLSL_RWTEXTURE_2D_INT4:
+ return "RWTexture2D<int4>";
+ case HLSL_RWTEXTURE_2D_ARRAY_INT4:
+ return "RWTexture2DArray<int4>";
+ case HLSL_RWTEXTURE_3D_INT4:
+ return "RWTexture3D<int4>";
+ default:
+ UNREACHABLE();
}
- return Decorate(string);
+ return "<unknown read and write texture type>";
+}
+
+TString RWTextureString(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
+{
+ return RWTextureString(RWTextureGroup(type, imageInternalFormat));
+}
+
+TString RWTextureGroupSuffix(const HLSLRWTextureGroup type)
+{
+ switch (type)
+ {
+ case HLSL_RWTEXTURE_2D_FLOAT4:
+ return "RW2D_float4_";
+ case HLSL_RWTEXTURE_2D_ARRAY_FLOAT4:
+ return "RW2DArray_float4_";
+ case HLSL_RWTEXTURE_3D_FLOAT4:
+ return "RW3D_float4_";
+ case HLSL_RWTEXTURE_2D_UNORM:
+ return "RW2D_unorm_float4_";
+ case HLSL_RWTEXTURE_2D_ARRAY_UNORN:
+ return "RW2DArray_unorm_float4_";
+ case HLSL_RWTEXTURE_3D_UNORM:
+ return "RW3D_unorm_float4_";
+ case HLSL_RWTEXTURE_2D_SNORM:
+ return "RW2D_snorm_float4_";
+ case HLSL_RWTEXTURE_2D_ARRAY_SNORM:
+ return "RW2DArray_snorm_float4_";
+ case HLSL_RWTEXTURE_3D_SNORM:
+ return "RW3D_snorm_float4_";
+ case HLSL_RWTEXTURE_2D_UINT4:
+ return "RW2D_uint4_";
+ case HLSL_RWTEXTURE_2D_ARRAY_UINT4:
+ return "RW2DArray_uint4_";
+ case HLSL_RWTEXTURE_3D_UINT4:
+ return "RW3D_uint4_";
+ case HLSL_RWTEXTURE_2D_INT4:
+ return "RW2D_int4_";
+ case HLSL_RWTEXTURE_2D_ARRAY_INT4:
+ return "RW2DArray_int4_";
+ case HLSL_RWTEXTURE_3D_INT4:
+ return "RW3D_int4_";
+ default:
+ UNREACHABLE();
+ }
+
+ return "<unknown read and write resource>";
+}
+
+TString RWTextureGroupSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
+{
+ return RWTextureGroupSuffix(RWTextureGroup(type, imageInternalFormat));
+}
+
+TString RWTextureTypeSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat)
+{
+ switch (type)
+ {
+ case EbtImageCube:
+ {
+ switch (imageInternalFormat)
+ {
+ case EiifRGBA32F:
+ case EiifRGBA16F:
+ case EiifR32F:
+ return "RWCube_float4_";
+ case EiifRGBA8:
+ return "RWCube_unorm_float4_";
+ case EiifRGBA8_SNORM:
+ return "RWCube_unorm_float4_";
+ default:
+ UNREACHABLE();
+ }
+ }
+ case EbtIImageCube:
+ {
+ switch (imageInternalFormat)
+ {
+ case EiifRGBA32I:
+ case EiifRGBA16I:
+ case EiifRGBA8I:
+ case EiifR32I:
+ return "RWCube_int4_";
+ default:
+ UNREACHABLE();
+ }
+ }
+ case EbtUImageCube:
+ {
+ switch (imageInternalFormat)
+ {
+ case EiifRGBA32UI:
+ case EiifRGBA16UI:
+ case EiifRGBA8UI:
+ case EiifR32UI:
+ return "RWCube_uint4_";
+ default:
+ UNREACHABLE();
+ }
+ }
+ default:
+ // All other types are identified by their group suffix
+ return TextureGroupSuffix(type, imageInternalFormat);
+ }
}
TString DecorateField(const TString &string, const TStructure &structure)
@@ -214,10 +715,13 @@ TString Decorate(const TString &string)
return string;
}
-TString DecorateIfNeeded(const TName &name)
+TString DecorateVariableIfNeeded(const TName &name)
{
if (name.isInternal())
{
+ // The name should not have a prefix reserved for user-defined variables or functions.
+ ASSERT(name.getString().compare(0, 2, "f_") != 0);
+ ASSERT(name.getString().compare(0, 1, "_") != 0);
return name.getString();
}
else
@@ -230,25 +734,29 @@ TString DecorateFunctionIfNeeded(const TName &name)
{
if (name.isInternal())
{
- return TFunction::unmangleName(name.getString());
- }
- else
- {
- return Decorate(TFunction::unmangleName(name.getString()));
+ // The name should not have a prefix reserved for user-defined variables or functions.
+ ASSERT(name.getString().compare(0, 2, "f_") != 0);
+ ASSERT(name.getString().compare(0, 1, "_") != 0);
+ return name.getString();
}
+ ASSERT(name.getString().compare(0, 3, "gl_") != 0);
+ // Add an additional f prefix to functions so that they're always disambiguated from variables.
+ // This is necessary in the corner case where a variable declaration hides a function that it
+ // uses in its initializer.
+ return "f_" + name.getString();
}
TString TypeString(const TType &type)
{
- const TStructure* structure = type.getStruct();
+ const TStructure *structure = type.getStruct();
if (structure)
{
- const TString& typeName = structure->name();
+ const TString &typeName = structure->name();
if (typeName != "")
{
return StructNameString(*structure);
}
- else // Nameless structure, define in place
+ else // Nameless structure, define in place
{
return StructureHLSL::defineNameless(*structure);
}
@@ -263,55 +771,73 @@ TString TypeString(const TType &type)
{
switch (type.getBasicType())
{
- case EbtFloat:
- switch (type.getNominalSize())
- {
- case 1: return "float";
- case 2: return "float2";
- case 3: return "float3";
- case 4: return "float4";
- }
- case EbtInt:
- switch (type.getNominalSize())
- {
- case 1: return "int";
- case 2: return "int2";
- case 3: return "int3";
- case 4: return "int4";
- }
- case EbtUInt:
- switch (type.getNominalSize())
- {
- case 1: return "uint";
- case 2: return "uint2";
- case 3: return "uint3";
- case 4: return "uint4";
- }
- case EbtBool:
- switch (type.getNominalSize())
- {
- case 1: return "bool";
- case 2: return "bool2";
- case 3: return "bool3";
- case 4: return "bool4";
- }
- case EbtVoid:
- return "void";
- case EbtSampler2D:
- case EbtISampler2D:
- case EbtUSampler2D:
- case EbtSampler2DArray:
- case EbtISampler2DArray:
- case EbtUSampler2DArray:
- return "sampler2D";
- case EbtSamplerCube:
- case EbtISamplerCube:
- case EbtUSamplerCube:
- return "samplerCUBE";
- case EbtSamplerExternalOES:
- return "sampler2D";
- default:
- break;
+ case EbtFloat:
+ switch (type.getNominalSize())
+ {
+ case 1:
+ return "float";
+ case 2:
+ return "float2";
+ case 3:
+ return "float3";
+ case 4:
+ return "float4";
+ }
+ case EbtInt:
+ switch (type.getNominalSize())
+ {
+ case 1:
+ return "int";
+ case 2:
+ return "int2";
+ case 3:
+ return "int3";
+ case 4:
+ return "int4";
+ }
+ case EbtUInt:
+ switch (type.getNominalSize())
+ {
+ case 1:
+ return "uint";
+ case 2:
+ return "uint2";
+ case 3:
+ return "uint3";
+ case 4:
+ return "uint4";
+ }
+ case EbtBool:
+ switch (type.getNominalSize())
+ {
+ case 1:
+ return "bool";
+ case 2:
+ return "bool2";
+ case 3:
+ return "bool3";
+ case 4:
+ return "bool4";
+ }
+ case EbtVoid:
+ return "void";
+ case EbtSampler2D:
+ case EbtISampler2D:
+ case EbtUSampler2D:
+ case EbtSampler2DArray:
+ case EbtISampler2DArray:
+ case EbtUSampler2DArray:
+ return "sampler2D";
+ case EbtSamplerCube:
+ case EbtISamplerCube:
+ case EbtUSamplerCube:
+ return "samplerCUBE";
+ case EbtSamplerExternalOES:
+ return "sampler2D";
+ case EbtAtomicCounter:
+ return "atomic_uint";
+ default:
+ break;
}
}
@@ -336,7 +862,8 @@ TString StructNameString(const TStructure &structure)
return "ss" + str(structure.uniqueId()) + "_" + structure.name();
}
-TString QualifiedStructNameString(const TStructure &structure, bool useHLSLRowMajorPacking,
+TString QualifiedStructNameString(const TStructure &structure,
+ bool useHLSLRowMajorPacking,
bool useStd140Packing)
{
if (structure.name() == "")
@@ -366,17 +893,28 @@ TString InterpolationString(TQualifier qualifier)
{
switch (qualifier)
{
- case EvqVaryingIn: return "";
- case EvqFragmentIn: return "";
- case EvqSmoothIn: return "linear";
- case EvqFlatIn: return "nointerpolation";
- case EvqCentroidIn: return "centroid";
- case EvqVaryingOut: return "";
- case EvqVertexOut: return "";
- case EvqSmoothOut: return "linear";
- case EvqFlatOut: return "nointerpolation";
- case EvqCentroidOut: return "centroid";
- default: UNREACHABLE();
+ case EvqVaryingIn:
+ return "";
+ case EvqFragmentIn:
+ return "";
+ case EvqSmoothIn:
+ return "linear";
+ case EvqFlatIn:
+ return "nointerpolation";
+ case EvqCentroidIn:
+ return "centroid";
+ case EvqVaryingOut:
+ return "";
+ case EvqVertexOut:
+ return "";
+ case EvqSmoothOut:
+ return "linear";
+ case EvqFlatOut:
+ return "nointerpolation";
+ case EvqCentroidOut:
+ return "centroid";
+ default:
+ UNREACHABLE();
}
return "";
@@ -386,53 +924,47 @@ TString QualifierString(TQualifier qualifier)
{
switch (qualifier)
{
- case EvqIn: return "in";
- case EvqOut: return "inout"; // 'out' results in an HLSL error if not all fields are written, for GLSL it's undefined
- case EvqInOut: return "inout";
- case EvqConstReadOnly: return "const";
- default: UNREACHABLE();
+ case EvqIn:
+ return "in";
+ case EvqOut:
+ return "inout"; // 'out' results in an HLSL error if not all fields are written, for
+ // GLSL it's undefined
+ case EvqInOut:
+ return "inout";
+ case EvqConstReadOnly:
+ return "const";
+ default:
+ UNREACHABLE();
}
return "";
}
-int HLSLTextureCoordsCount(const TBasicType samplerType)
+TString DisambiguateFunctionName(const TIntermSequence *parameters)
{
- switch (samplerType)
+ TString disambiguatingString;
+ for (auto parameter : *parameters)
{
- case EbtSampler2D:
- return 2;
- case EbtSampler3D:
- return 3;
- case EbtSamplerCube:
- return 3;
- case EbtSampler2DArray:
- return 3;
- case EbtISampler2D:
- return 2;
- case EbtISampler3D:
- return 3;
- case EbtISamplerCube:
- return 3;
- case EbtISampler2DArray:
- return 3;
- case EbtUSampler2D:
- return 2;
- case EbtUSampler3D:
- return 3;
- case EbtUSamplerCube:
- return 3;
- case EbtUSampler2DArray:
- return 3;
- case EbtSampler2DShadow:
- return 2;
- case EbtSamplerCubeShadow:
- return 3;
- case EbtSampler2DArrayShadow:
- return 3;
- default:
- UNREACHABLE();
+ const TType &paramType = parameter->getAsTyped()->getType();
+ // Parameter types are only added to function names if they are ambiguous according to the
+ // native HLSL compiler. Other parameter types are not added to function names to avoid
+ // making function names longer.
+ if (paramType.getObjectSize() == 4 && paramType.getBasicType() == EbtFloat)
+ {
+ // Disambiguation is needed for float2x2 and float4 parameters. These are the only
+ // built-in types that HLSL thinks are identical. float2x3 and float3x2 are different
+ // types, for example.
+ disambiguatingString += "_" + TypeString(paramType);
+ }
+ else if (paramType.getBasicType() == EbtStruct)
+ {
+ // Disambiguation is needed for struct parameters, since HLSL thinks that structs with
+ // the same fields but a different name are identical.
+ ASSERT(paramType.getStruct()->name() != "");
+ disambiguatingString += "_" + TypeString(paramType);
+ }
}
- return 0;
-}
+ return disambiguatingString;
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h
index 42444e3a56..daeec8de41 100644
--- a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h
@@ -11,6 +11,7 @@
#define COMPILER_TRANSLATOR_UTILSHLSL_H_
#include <vector>
+#include "compiler/translator/IntermNode.h"
#include "compiler/translator/Types.h"
#include "angle_gl.h"
@@ -20,22 +21,33 @@ class TName;
namespace sh
{
-// Unique combinations of HLSL Texture type and HLSL Sampler type.
-enum HLSLTextureSamplerGroup
+// HLSL Texture type for GLSL sampler type and readonly image type.
+enum HLSLTextureGroup
{
- // Regular samplers
+ // read resources
HLSL_TEXTURE_2D,
HLSL_TEXTURE_MIN = HLSL_TEXTURE_2D,
HLSL_TEXTURE_CUBE,
HLSL_TEXTURE_2D_ARRAY,
HLSL_TEXTURE_3D,
+ HLSL_TEXTURE_2D_UNORM,
+ HLSL_TEXTURE_CUBE_UNORM,
+ HLSL_TEXTURE_2D_ARRAY_UNORN,
+ HLSL_TEXTURE_3D_UNORM,
+ HLSL_TEXTURE_2D_SNORM,
+ HLSL_TEXTURE_CUBE_SNORM,
+ HLSL_TEXTURE_2D_ARRAY_SNORM,
+ HLSL_TEXTURE_3D_SNORM,
+ HLSL_TEXTURE_2D_MS,
HLSL_TEXTURE_2D_INT4,
HLSL_TEXTURE_3D_INT4,
HLSL_TEXTURE_2D_ARRAY_INT4,
+ HLSL_TEXTURE_2D_MS_INT4,
HLSL_TEXTURE_2D_UINT4,
HLSL_TEXTURE_3D_UINT4,
HLSL_TEXTURE_2D_ARRAY_UINT4,
+ HLSL_TEXTURE_2D_MS_UINT4,
// Comparison samplers
@@ -50,29 +62,68 @@ enum HLSLTextureSamplerGroup
HLSL_TEXTURE_MAX = HLSL_TEXTURE_UNKNOWN
};
-HLSLTextureSamplerGroup TextureGroup(const TBasicType type);
-TString TextureString(const HLSLTextureSamplerGroup type);
-TString TextureString(const TBasicType type);
-TString TextureGroupSuffix(const HLSLTextureSamplerGroup type);
-TString TextureGroupSuffix(const TBasicType type);
-TString TextureTypeSuffix(const TBasicType type);
+// HLSL RWTexture type for GLSL read and write image type.
+enum HLSLRWTextureGroup
+{
+ // read/write resource
+ HLSL_RWTEXTURE_2D_FLOAT4,
+ HLSL_RWTEXTURE_MIN = HLSL_RWTEXTURE_2D_FLOAT4,
+ HLSL_RWTEXTURE_2D_ARRAY_FLOAT4,
+ HLSL_RWTEXTURE_3D_FLOAT4,
+ HLSL_RWTEXTURE_2D_UNORM,
+ HLSL_RWTEXTURE_2D_ARRAY_UNORN,
+ HLSL_RWTEXTURE_3D_UNORM,
+ HLSL_RWTEXTURE_2D_SNORM,
+ HLSL_RWTEXTURE_2D_ARRAY_SNORM,
+ HLSL_RWTEXTURE_3D_SNORM,
+ HLSL_RWTEXTURE_2D_UINT4,
+ HLSL_RWTEXTURE_2D_ARRAY_UINT4,
+ HLSL_RWTEXTURE_3D_UINT4,
+ HLSL_RWTEXTURE_2D_INT4,
+ HLSL_RWTEXTURE_2D_ARRAY_INT4,
+ HLSL_RWTEXTURE_3D_INT4,
+
+ HLSL_RWTEXTURE_UNKNOWN,
+ HLSL_RWTEXTURE_MAX = HLSL_RWTEXTURE_UNKNOWN
+};
+
+HLSLTextureGroup TextureGroup(const TBasicType type,
+ TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified);
+TString TextureString(const HLSLTextureGroup textureGroup);
+TString TextureString(const TBasicType type,
+ TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified);
+TString TextureGroupSuffix(const HLSLTextureGroup type);
+TString TextureGroupSuffix(const TBasicType type,
+ TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified);
+TString TextureTypeSuffix(const TBasicType type,
+ TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified);
+HLSLRWTextureGroup RWTextureGroup(const TBasicType type,
+ TLayoutImageInternalFormat imageInternalFormat);
+TString RWTextureString(const HLSLRWTextureGroup textureGroup);
+TString RWTextureString(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat);
+TString RWTextureGroupSuffix(const HLSLRWTextureGroup type);
+TString RWTextureGroupSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat);
+TString RWTextureTypeSuffix(const TBasicType type, TLayoutImageInternalFormat imageInternalFormat);
+
TString SamplerString(const TBasicType type);
-TString SamplerString(HLSLTextureSamplerGroup type);
-// Prepends an underscore to avoid naming clashes
+TString SamplerString(HLSLTextureGroup type);
+
+// Adds a prefix to user-defined names to avoid naming clashes.
TString Decorate(const TString &string);
-TString DecorateIfNeeded(const TName &name);
-// Decorates and also unmangles the function name
+TString DecorateVariableIfNeeded(const TName &name);
TString DecorateFunctionIfNeeded(const TName &name);
-TString DecorateUniform(const TString &string, const TType &type);
TString DecorateField(const TString &string, const TStructure &structure);
TString DecoratePrivate(const TString &privateText);
TString TypeString(const TType &type);
TString StructNameString(const TStructure &structure);
-TString QualifiedStructNameString(const TStructure &structure, bool useHLSLRowMajorPacking,
+TString QualifiedStructNameString(const TStructure &structure,
+ bool useHLSLRowMajorPacking,
bool useStd140Packing);
TString InterpolationString(TQualifier qualifier);
TString QualifierString(TQualifier qualifier);
-int HLSLTextureCoordsCount(const TBasicType samplerType);
+// Parameters may need to be included in function names to disambiguate between overloaded
+// functions.
+TString DisambiguateFunctionName(const TIntermSequence *parameters);
}
-#endif // COMPILER_TRANSLATOR_UTILSHLSL_H_
+#endif // COMPILER_TRANSLATOR_UTILSHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.cpp
index 2461b6a438..492972b60d 100644
--- a/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.cpp
@@ -6,8 +6,12 @@
#include "compiler/translator/ValidateGlobalInitializer.h"
+#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/ParseContext.h"
+namespace sh
+{
+
namespace
{
@@ -32,7 +36,8 @@ class ValidateGlobalInitializerTraverser : public TIntermTraverser
void ValidateGlobalInitializerTraverser::visitSymbol(TIntermSymbol *node)
{
- const TSymbol *sym = mContext->symbolTable.find(node->getSymbol(), mContext->getShaderVersion());
+ const TSymbol *sym =
+ mContext->symbolTable.find(node->getSymbol(), mContext->getShaderVersion());
if (sym->isVariable())
{
// ESSL 1.00 section 4.3 (or ESSL 3.00 section 4.3):
@@ -40,33 +45,36 @@ void ValidateGlobalInitializerTraverser::visitSymbol(TIntermSymbol *node)
const TVariable *var = static_cast<const TVariable *>(sym);
switch (var->getType().getQualifier())
{
- case EvqConst:
- break;
- case EvqGlobal:
- case EvqTemporary:
- case EvqUniform:
- // We allow these cases to be compatible with legacy ESSL 1.00 content.
- // Implement stricter rules for ESSL 3.00 since there's no legacy content to deal with.
- if (mContext->getShaderVersion() >= 300)
- {
+ case EvqConst:
+ break;
+ case EvqGlobal:
+ case EvqTemporary:
+ case EvqUniform:
+ // We allow these cases to be compatible with legacy ESSL 1.00 content.
+ // Implement stricter rules for ESSL 3.00 since there's no legacy content to deal
+ // with.
+ if (mContext->getShaderVersion() >= 300)
+ {
+ mIsValid = false;
+ }
+ else
+ {
+ mIssueWarning = true;
+ }
+ break;
+ default:
mIsValid = false;
- }
- else
- {
- mIssueWarning = true;
- }
- break;
- default:
- mIsValid = false;
}
}
}
bool ValidateGlobalInitializerTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
{
- // Disallow calls to user-defined functions and texture lookup functions in global variable initializers.
- // This is done simply by disabling all function calls - built-in math functions don't use EOpFunctionCall.
- if (node->getOp() == EOpFunctionCall)
+ // Disallow calls to user-defined functions and texture lookup functions in global variable
+ // initializers.
+ // This is done simply by disabling all function calls - built-in math functions don't use
+ // the function call ops.
+ if (node->isFunctionCall())
{
mIsValid = false;
}
@@ -92,16 +100,15 @@ bool ValidateGlobalInitializerTraverser::visitUnary(Visit visit, TIntermUnary *n
}
ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser(const TParseContext *context)
- : TIntermTraverser(true, false, false),
- mContext(context),
- mIsValid(true),
- mIssueWarning(false)
+ : TIntermTraverser(true, false, false), mContext(context), mIsValid(true), mIssueWarning(false)
{
}
-} // namespace
+} // namespace
-bool ValidateGlobalInitializer(TIntermTyped *initializer, const TParseContext *context, bool *warning)
+bool ValidateGlobalInitializer(TIntermTyped *initializer,
+ const TParseContext *context,
+ bool *warning)
{
ValidateGlobalInitializerTraverser validate(context);
initializer->traverse(&validate);
@@ -110,3 +117,4 @@ bool ValidateGlobalInitializer(TIntermTyped *initializer, const TParseContext *c
return validate.isValid();
}
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.h b/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.h
index c3d2a47eba..2e7570667a 100644
--- a/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.h
+++ b/src/3rdparty/angle/src/compiler/translator/ValidateGlobalInitializer.h
@@ -7,10 +7,17 @@
#ifndef COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_
#define COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_
+namespace sh
+{
+
class TIntermTyped;
class TParseContext;
// Returns true if the initializer is valid.
-bool ValidateGlobalInitializer(TIntermTyped *initializer, const TParseContext *context, bool *warning);
+bool ValidateGlobalInitializer(TIntermTyped *initializer,
+ const TParseContext *context,
+ bool *warning);
+
+} // namespace sh
-#endif // COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_
+#endif // COMPILER_TRANSLATOR_VALIDATEGLOBALINITIALIZER_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp
index ba8cdd0aa8..941f79ae51 100644
--- a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp
@@ -5,14 +5,29 @@
//
#include "compiler/translator/ValidateLimitations.h"
-#include "compiler/translator/InfoSink.h"
-#include "compiler/translator/InitializeParseContext.h"
-#include "compiler/translator/ParseContext.h"
+
#include "angle_gl.h"
+#include "compiler/translator/Diagnostics.h"
+#include "compiler/translator/IntermTraverse.h"
+#include "compiler/translator/ParseContext.h"
+
+namespace sh
+{
namespace
{
+int GetLoopSymbolId(TIntermLoop *loop)
+{
+ // Here we assume all the operations are valid, because the loop node is
+ // already validated before this call.
+ TIntermSequence *declSeq = loop->getInit()->getAsDeclarationNode()->getSequence();
+ TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode();
+ TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode();
+
+ return symbol->getId();
+}
+
// Traverses a node to check if it represents a constant index expression.
// Definition:
// constant-index-expressions are a superset of constant-expressions.
@@ -25,10 +40,8 @@ namespace
class ValidateConstIndexExpr : public TIntermTraverser
{
public:
- ValidateConstIndexExpr(TLoopStack& stack)
- : TIntermTraverser(true, false, false),
- mValid(true),
- mLoopStack(stack)
+ ValidateConstIndexExpr(const std::vector<int> &loopSymbols)
+ : TIntermTraverser(true, false, false), mValid(true), mLoopSymbolIds(loopSymbols)
{
}
@@ -41,93 +54,93 @@ class ValidateConstIndexExpr : public TIntermTraverser
// constant index expression.
if (mValid)
{
- mValid = (symbol->getQualifier() == EvqConst) ||
- (mLoopStack.findLoop(symbol));
+ bool isLoopSymbol = std::find(mLoopSymbolIds.begin(), mLoopSymbolIds.end(),
+ symbol->getId()) != mLoopSymbolIds.end();
+ mValid = (symbol->getQualifier() == EvqConst) || isLoopSymbol;
}
}
private:
bool mValid;
- TLoopStack& mLoopStack;
+ const std::vector<int> mLoopSymbolIds;
};
-} // namespace anonymous
+// Traverses intermediate tree to ensure that the shader does not exceed the
+// minimum functionality mandated in GLSL 1.0 spec, Appendix A.
+class ValidateLimitationsTraverser : public TLValueTrackingTraverser
+{
+ public:
+ ValidateLimitationsTraverser(sh::GLenum shaderType,
+ TSymbolTable *symbolTable,
+ int shaderVersion,
+ TDiagnostics *diagnostics);
-ValidateLimitations::ValidateLimitations(sh::GLenum shaderType, TInfoSinkBase *sink)
- : TIntermTraverser(true, false, false),
+ void visitSymbol(TIntermSymbol *node) override;
+ bool visitBinary(Visit, TIntermBinary *) override;
+ bool visitLoop(Visit, TIntermLoop *) override;
+
+ private:
+ void error(TSourceLoc loc, const char *reason, const char *token);
+
+ bool withinLoopBody() const;
+ bool isLoopIndex(TIntermSymbol *symbol);
+ bool validateLoopType(TIntermLoop *node);
+
+ bool validateForLoopHeader(TIntermLoop *node);
+ // If valid, return the index symbol id; Otherwise, return -1.
+ int validateForLoopInit(TIntermLoop *node);
+ bool validateForLoopCond(TIntermLoop *node, int indexSymbolId);
+ bool validateForLoopExpr(TIntermLoop *node, int indexSymbolId);
+
+ // Returns true if indexing does not exceed the minimum functionality
+ // mandated in GLSL 1.0 spec, Appendix A, Section 5.
+ bool isConstExpr(TIntermNode *node);
+ bool isConstIndexExpr(TIntermNode *node);
+ bool validateIndexing(TIntermBinary *node);
+
+ sh::GLenum mShaderType;
+ TDiagnostics *mDiagnostics;
+ std::vector<int> mLoopSymbolIds;
+};
+
+ValidateLimitationsTraverser::ValidateLimitationsTraverser(sh::GLenum shaderType,
+ TSymbolTable *symbolTable,
+ int shaderVersion,
+ TDiagnostics *diagnostics)
+ : TLValueTrackingTraverser(true, false, false, symbolTable, shaderVersion),
mShaderType(shaderType),
- mSink(sink),
- mNumErrors(0),
- mValidateIndexing(true),
- mValidateInnerLoops(true)
+ mDiagnostics(diagnostics)
{
+ ASSERT(diagnostics);
}
-// static
-bool ValidateLimitations::IsLimitedForLoop(TIntermLoop *loop)
+void ValidateLimitationsTraverser::visitSymbol(TIntermSymbol *node)
{
- // The shader type doesn't matter in this case.
- ValidateLimitations validate(GL_FRAGMENT_SHADER, nullptr);
- validate.mValidateIndexing = false;
- validate.mValidateInnerLoops = false;
- if (!validate.validateLoopType(loop))
- return false;
- if (!validate.validateForLoopHeader(loop))
- return false;
- TIntermNode *body = loop->getBody();
- if (body != nullptr)
+ if (isLoopIndex(node) && isLValueRequiredHere())
{
- validate.mLoopStack.push(loop);
- body->traverse(&validate);
- validate.mLoopStack.pop();
+ error(node->getLine(),
+ "Loop index cannot be statically assigned to within the body of the loop",
+ node->getSymbol().c_str());
}
- return (validate.mNumErrors == 0);
}
-bool ValidateLimitations::visitBinary(Visit, TIntermBinary *node)
+bool ValidateLimitationsTraverser::visitBinary(Visit, TIntermBinary *node)
{
- // Check if loop index is modified in the loop body.
- validateOperation(node, node->getLeft());
-
// Check indexing.
switch (node->getOp())
{
- case EOpIndexDirect:
- case EOpIndexIndirect:
- if (mValidateIndexing)
- validateIndexing(node);
- break;
- default:
- break;
- }
- return true;
-}
-
-bool ValidateLimitations::visitUnary(Visit, TIntermUnary *node)
-{
- // Check if loop index is modified in the loop body.
- validateOperation(node, node->getOperand());
-
- return true;
-}
-
-bool ValidateLimitations::visitAggregate(Visit, TIntermAggregate *node)
-{
- switch (node->getOp()) {
- case EOpFunctionCall:
- validateFunctionCall(node);
- break;
- default:
- break;
+ case EOpIndexDirect:
+ case EOpIndexIndirect:
+ validateIndexing(node);
+ break;
+ default:
+ break;
}
return true;
}
-bool ValidateLimitations::visitLoop(Visit, TIntermLoop *node)
+bool ValidateLimitationsTraverser::visitLoop(Visit, TIntermLoop *node)
{
- if (!mValidateInnerLoops)
- return true;
-
if (!validateLoopType(node))
return false;
@@ -135,53 +148,45 @@ bool ValidateLimitations::visitLoop(Visit, TIntermLoop *node)
return false;
TIntermNode *body = node->getBody();
- if (body != NULL)
+ if (body != nullptr)
{
- mLoopStack.push(node);
+ mLoopSymbolIds.push_back(GetLoopSymbolId(node));
body->traverse(this);
- mLoopStack.pop();
+ mLoopSymbolIds.pop_back();
}
// The loop is fully processed - no need to visit children.
return false;
}
-void ValidateLimitations::error(TSourceLoc loc,
- const char *reason, const char *token)
+void ValidateLimitationsTraverser::error(TSourceLoc loc, const char *reason, const char *token)
{
- if (mSink)
- {
- mSink->prefix(EPrefixError);
- mSink->location(loc);
- (*mSink) << "'" << token << "' : " << reason << "\n";
- }
- ++mNumErrors;
+ mDiagnostics->error(loc, reason, token);
}
-bool ValidateLimitations::withinLoopBody() const
+bool ValidateLimitationsTraverser::withinLoopBody() const
{
- return !mLoopStack.empty();
+ return !mLoopSymbolIds.empty();
}
-bool ValidateLimitations::isLoopIndex(TIntermSymbol *symbol)
+bool ValidateLimitationsTraverser::isLoopIndex(TIntermSymbol *symbol)
{
- return mLoopStack.findLoop(symbol) != NULL;
+ return std::find(mLoopSymbolIds.begin(), mLoopSymbolIds.end(), symbol->getId()) !=
+ mLoopSymbolIds.end();
}
-bool ValidateLimitations::validateLoopType(TIntermLoop *node)
+bool ValidateLimitationsTraverser::validateLoopType(TIntermLoop *node)
{
TLoopType type = node->getType();
if (type == ELoopFor)
return true;
// Reject while and do-while loops.
- error(node->getLine(),
- "This type of loop is not allowed",
- type == ELoopWhile ? "while" : "do");
+ error(node->getLine(), "This type of loop is not allowed", type == ELoopWhile ? "while" : "do");
return false;
}
-bool ValidateLimitations::validateForLoopHeader(TIntermLoop *node)
+bool ValidateLimitationsTraverser::validateForLoopHeader(TIntermLoop *node)
{
ASSERT(node->getType() == ELoopFor);
@@ -200,10 +205,10 @@ bool ValidateLimitations::validateForLoopHeader(TIntermLoop *node)
return true;
}
-int ValidateLimitations::validateForLoopInit(TIntermLoop *node)
+int ValidateLimitationsTraverser::validateForLoopInit(TIntermLoop *node)
{
TIntermNode *init = node->getInit();
- if (init == NULL)
+ if (init == nullptr)
{
error(node->getLine(), "Missing init declaration", "for");
return -1;
@@ -213,8 +218,8 @@ int ValidateLimitations::validateForLoopInit(TIntermLoop *node)
// init-declaration has the form:
// type-specifier identifier = constant-expression
//
- TIntermAggregate *decl = init->getAsAggregate();
- if ((decl == NULL) || (decl->getOp() != EOpDeclaration))
+ TIntermDeclaration *decl = init->getAsDeclarationNode();
+ if (decl == nullptr)
{
error(init->getLine(), "Invalid init declaration", "for");
return -1;
@@ -227,29 +232,28 @@ int ValidateLimitations::validateForLoopInit(TIntermLoop *node)
return -1;
}
TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode();
- if ((declInit == NULL) || (declInit->getOp() != EOpInitialize))
+ if ((declInit == nullptr) || (declInit->getOp() != EOpInitialize))
{
error(decl->getLine(), "Invalid init declaration", "for");
return -1;
}
TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode();
- if (symbol == NULL)
+ if (symbol == nullptr)
{
error(declInit->getLine(), "Invalid init declaration", "for");
return -1;
}
// The loop index has type int or float.
TBasicType type = symbol->getBasicType();
- if ((type != EbtInt) && (type != EbtUInt) && (type != EbtFloat)) {
- error(symbol->getLine(),
- "Invalid type for loop index", getBasicString(type));
+ if ((type != EbtInt) && (type != EbtUInt) && (type != EbtFloat))
+ {
+ error(symbol->getLine(), "Invalid type for loop index", getBasicString(type));
return -1;
}
// The loop index is initialized with constant expression.
if (!isConstExpr(declInit->getRight()))
{
- error(declInit->getLine(),
- "Loop index cannot be initialized with non-constant expression",
+ error(declInit->getLine(), "Loop index cannot be initialized with non-constant expression",
symbol->getSymbol().c_str());
return -1;
}
@@ -257,11 +261,10 @@ int ValidateLimitations::validateForLoopInit(TIntermLoop *node)
return symbol->getId();
}
-bool ValidateLimitations::validateForLoopCond(TIntermLoop *node,
- int indexSymbolId)
+bool ValidateLimitationsTraverser::validateForLoopCond(TIntermLoop *node, int indexSymbolId)
{
TIntermNode *cond = node->getCondition();
- if (cond == NULL)
+ if (cond == nullptr)
{
error(node->getLine(), "Missing condition", "for");
return false;
@@ -271,45 +274,42 @@ bool ValidateLimitations::validateForLoopCond(TIntermLoop *node,
// loop_index relational_operator constant_expression
//
TIntermBinary *binOp = cond->getAsBinaryNode();
- if (binOp == NULL)
+ if (binOp == nullptr)
{
error(node->getLine(), "Invalid condition", "for");
return false;
}
// Loop index should be to the left of relational operator.
TIntermSymbol *symbol = binOp->getLeft()->getAsSymbolNode();
- if (symbol == NULL)
+ if (symbol == nullptr)
{
error(binOp->getLine(), "Invalid condition", "for");
return false;
}
if (symbol->getId() != indexSymbolId)
{
- error(symbol->getLine(),
- "Expected loop index", symbol->getSymbol().c_str());
+ error(symbol->getLine(), "Expected loop index", symbol->getSymbol().c_str());
return false;
}
// Relational operator is one of: > >= < <= == or !=.
switch (binOp->getOp())
{
- case EOpEqual:
- case EOpNotEqual:
- case EOpLessThan:
- case EOpGreaterThan:
- case EOpLessThanEqual:
- case EOpGreaterThanEqual:
- break;
- default:
- error(binOp->getLine(),
- "Invalid relational operator",
- GetOperatorString(binOp->getOp()));
- break;
+ case EOpEqual:
+ case EOpNotEqual:
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ break;
+ default:
+ error(binOp->getLine(), "Invalid relational operator",
+ GetOperatorString(binOp->getOp()));
+ break;
}
// Loop index must be compared with a constant.
if (!isConstExpr(binOp->getRight()))
{
- error(binOp->getLine(),
- "Loop index cannot be compared with non-constant expression",
+ error(binOp->getLine(), "Loop index cannot be compared with non-constant expression",
symbol->getSymbol().c_str());
return false;
}
@@ -317,11 +317,10 @@ bool ValidateLimitations::validateForLoopCond(TIntermLoop *node,
return true;
}
-bool ValidateLimitations::validateForLoopExpr(TIntermLoop *node,
- int indexSymbolId)
+bool ValidateLimitationsTraverser::validateForLoopExpr(TIntermLoop *node, int indexSymbolId)
{
TIntermNode *expr = node->getExpression();
- if (expr == NULL)
+ if (expr == nullptr)
{
error(node->getLine(), "Missing expression", "for");
return false;
@@ -336,60 +335,58 @@ bool ValidateLimitations::validateForLoopExpr(TIntermLoop *node,
// --loop_index
// The last two forms are not specified in the spec, but I am assuming
// its an oversight.
- TIntermUnary *unOp = expr->getAsUnaryNode();
- TIntermBinary *binOp = unOp ? NULL : expr->getAsBinaryNode();
+ TIntermUnary *unOp = expr->getAsUnaryNode();
+ TIntermBinary *binOp = unOp ? nullptr : expr->getAsBinaryNode();
- TOperator op = EOpNull;
- TIntermSymbol *symbol = NULL;
- if (unOp != NULL)
+ TOperator op = EOpNull;
+ TIntermSymbol *symbol = nullptr;
+ if (unOp != nullptr)
{
- op = unOp->getOp();
+ op = unOp->getOp();
symbol = unOp->getOperand()->getAsSymbolNode();
}
- else if (binOp != NULL)
+ else if (binOp != nullptr)
{
- op = binOp->getOp();
+ op = binOp->getOp();
symbol = binOp->getLeft()->getAsSymbolNode();
}
// The operand must be loop index.
- if (symbol == NULL)
+ if (symbol == nullptr)
{
error(expr->getLine(), "Invalid expression", "for");
return false;
}
if (symbol->getId() != indexSymbolId)
{
- error(symbol->getLine(),
- "Expected loop index", symbol->getSymbol().c_str());
+ error(symbol->getLine(), "Expected loop index", symbol->getSymbol().c_str());
return false;
}
// The operator is one of: ++ -- += -=.
switch (op)
{
- case EOpPostIncrement:
- case EOpPostDecrement:
- case EOpPreIncrement:
- case EOpPreDecrement:
- ASSERT((unOp != NULL) && (binOp == NULL));
- break;
- case EOpAddAssign:
- case EOpSubAssign:
- ASSERT((unOp == NULL) && (binOp != NULL));
- break;
- default:
- error(expr->getLine(), "Invalid operator", GetOperatorString(op));
- return false;
+ case EOpPostIncrement:
+ case EOpPostDecrement:
+ case EOpPreIncrement:
+ case EOpPreDecrement:
+ ASSERT((unOp != nullptr) && (binOp == nullptr));
+ break;
+ case EOpAddAssign:
+ case EOpSubAssign:
+ ASSERT((unOp == nullptr) && (binOp != nullptr));
+ break;
+ default:
+ error(expr->getLine(), "Invalid operator", GetOperatorString(op));
+ return false;
}
// Loop index must be incremented/decremented with a constant.
- if (binOp != NULL)
+ if (binOp != nullptr)
{
if (!isConstExpr(binOp->getRight()))
{
- error(binOp->getLine(),
- "Loop index cannot be modified by non-constant expression",
+ error(binOp->getLine(), "Loop index cannot be modified by non-constant expression",
symbol->getSymbol().c_str());
return false;
}
@@ -398,95 +395,31 @@ bool ValidateLimitations::validateForLoopExpr(TIntermLoop *node,
return true;
}
-bool ValidateLimitations::validateFunctionCall(TIntermAggregate *node)
-{
- ASSERT(node->getOp() == EOpFunctionCall);
-
- // If not within loop body, there is nothing to check.
- if (!withinLoopBody())
- return true;
-
- // List of param indices for which loop indices are used as argument.
- typedef std::vector<size_t> ParamIndex;
- ParamIndex pIndex;
- TIntermSequence *params = node->getSequence();
- for (TIntermSequence::size_type i = 0; i < params->size(); ++i)
- {
- TIntermSymbol *symbol = (*params)[i]->getAsSymbolNode();
- if (symbol && isLoopIndex(symbol))
- pIndex.push_back(i);
- }
- // If none of the loop indices are used as arguments,
- // there is nothing to check.
- if (pIndex.empty())
- return true;
-
- bool valid = true;
- TSymbolTable& symbolTable = GetGlobalParseContext()->symbolTable;
- TSymbol* symbol = symbolTable.find(node->getName(), GetGlobalParseContext()->getShaderVersion());
- ASSERT(symbol && symbol->isFunction());
- TFunction *function = static_cast<TFunction *>(symbol);
- for (ParamIndex::const_iterator i = pIndex.begin();
- i != pIndex.end(); ++i)
- {
- const TConstParameter &param = function->getParam(*i);
- TQualifier qual = param.type->getQualifier();
- if ((qual == EvqOut) || (qual == EvqInOut))
- {
- error((*params)[*i]->getLine(),
- "Loop index cannot be used as argument to a function out or inout parameter",
- (*params)[*i]->getAsSymbolNode()->getSymbol().c_str());
- valid = false;
- }
- }
-
- return valid;
-}
-
-bool ValidateLimitations::validateOperation(TIntermOperator *node,
- TIntermNode* operand)
-{
- // Check if loop index is modified in the loop body.
- if (!withinLoopBody() || !node->isAssignment())
- return true;
-
- TIntermSymbol *symbol = operand->getAsSymbolNode();
- if (symbol && isLoopIndex(symbol))
- {
- error(node->getLine(),
- "Loop index cannot be statically assigned to within the body of the loop",
- symbol->getSymbol().c_str());
- }
- return true;
-}
-
-bool ValidateLimitations::isConstExpr(TIntermNode *node)
+bool ValidateLimitationsTraverser::isConstExpr(TIntermNode *node)
{
ASSERT(node != nullptr);
return node->getAsConstantUnion() != nullptr && node->getAsTyped()->getQualifier() == EvqConst;
}
-bool ValidateLimitations::isConstIndexExpr(TIntermNode *node)
+bool ValidateLimitationsTraverser::isConstIndexExpr(TIntermNode *node)
{
- ASSERT(node != NULL);
+ ASSERT(node != nullptr);
- ValidateConstIndexExpr validate(mLoopStack);
+ ValidateConstIndexExpr validate(mLoopSymbolIds);
node->traverse(&validate);
return validate.isValid();
}
-bool ValidateLimitations::validateIndexing(TIntermBinary *node)
+bool ValidateLimitationsTraverser::validateIndexing(TIntermBinary *node)
{
- ASSERT((node->getOp() == EOpIndexDirect) ||
- (node->getOp() == EOpIndexIndirect));
+ ASSERT((node->getOp() == EOpIndexDirect) || (node->getOp() == EOpIndexIndirect));
- bool valid = true;
+ bool valid = true;
TIntermTyped *index = node->getRight();
// The index expession must be a constant-index-expression unless
// the operand is a uniform in a vertex shader.
TIntermTyped *operand = node->getLeft();
- bool skip = (mShaderType == GL_VERTEX_SHADER) &&
- (operand->getQualifier() == EvqUniform);
+ bool skip = (mShaderType == GL_VERTEX_SHADER) && (operand->getQualifier() == EvqUniform);
if (!skip && !isConstIndexExpr(index))
{
error(index->getLine(), "Index expression must be constant", "[]");
@@ -495,3 +428,17 @@ bool ValidateLimitations::validateIndexing(TIntermBinary *node)
return valid;
}
+} // namespace anonymous
+
+bool ValidateLimitations(TIntermNode *root,
+ GLenum shaderType,
+ TSymbolTable *symbolTable,
+ int shaderVersion,
+ TDiagnostics *diagnostics)
+{
+ ValidateLimitationsTraverser validate(shaderType, symbolTable, shaderVersion, diagnostics);
+ root->traverse(&validate);
+ return diagnostics->numErrors() == 0;
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h
index 666e38ff5c..9149b8c216 100644
--- a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h
+++ b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h
@@ -8,56 +8,20 @@
#define COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_
#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/LoopInfo.h"
-class TInfoSinkBase;
-
-// Traverses intermediate tree to ensure that the shader does not exceed the
-// minimum functionality mandated in GLSL 1.0 spec, Appendix A.
-class ValidateLimitations : public TIntermTraverser
+namespace sh
{
- public:
- ValidateLimitations(sh::GLenum shaderType, TInfoSinkBase *sink);
-
- int numErrors() const { return mNumErrors; }
-
- bool visitBinary(Visit, TIntermBinary *) override;
- bool visitUnary(Visit, TIntermUnary *) override;
- bool visitAggregate(Visit, TIntermAggregate *) override;
- bool visitLoop(Visit, TIntermLoop *) override;
-
- static bool IsLimitedForLoop(TIntermLoop *node);
-
- private:
- void error(TSourceLoc loc, const char *reason, const char *token);
-
- bool withinLoopBody() const;
- bool isLoopIndex(TIntermSymbol *symbol);
- bool validateLoopType(TIntermLoop *node);
-
- bool validateForLoopHeader(TIntermLoop *node);
- // If valid, return the index symbol id; Otherwise, return -1.
- int validateForLoopInit(TIntermLoop *node);
- bool validateForLoopCond(TIntermLoop *node, int indexSymbolId);
- bool validateForLoopExpr(TIntermLoop *node, int indexSymbolId);
- // Returns true if none of the loop indices is used as the argument to
- // the given function out or inout parameter.
- bool validateFunctionCall(TIntermAggregate *node);
- bool validateOperation(TIntermOperator *node, TIntermNode *operand);
+class TDiagnostics;
- // Returns true if indexing does not exceed the minimum functionality
- // mandated in GLSL 1.0 spec, Appendix A, Section 5.
- bool isConstExpr(TIntermNode *node);
- bool isConstIndexExpr(TIntermNode *node);
- bool validateIndexing(TIntermBinary *node);
+// Returns true if the given shader does not exceed the minimum functionality mandated in GLSL ES
+// 1.00 spec Appendix A.
+bool ValidateLimitations(TIntermNode *root,
+ GLenum shaderType,
+ TSymbolTable *symbolTable,
+ int shaderVersion,
+ TDiagnostics *diagnostics);
- sh::GLenum mShaderType;
- TInfoSinkBase *mSink;
- int mNumErrors;
- TLoopStack mLoopStack;
- bool mValidateIndexing;
- bool mValidateInnerLoops;
-};
+} // namespace sh
-#endif // COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_
+#endif // COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.cpp
new file mode 100644
index 0000000000..9dccbf413f
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.cpp
@@ -0,0 +1,29 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ValidateMaxParameters checks if function definitions have more than a set number of parameters.
+
+#include "compiler/translator/ValidateMaxParameters.h"
+
+#include "compiler/translator/IntermNode.h"
+
+namespace sh
+{
+
+bool ValidateMaxParameters(TIntermBlock *root, unsigned int maxParameters)
+{
+ for (TIntermNode *node : *root->getSequence())
+ {
+ TIntermFunctionDefinition *definition = node->getAsFunctionDefinition();
+ if (definition != nullptr &&
+ definition->getFunctionPrototype()->getSequence()->size() > maxParameters)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.h b/src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.h
new file mode 100644
index 0000000000..dec7597da4
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/ValidateMaxParameters.h
@@ -0,0 +1,21 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ValidateMaxParameters checks if function definitions have more than a set number of parameters.
+
+#ifndef COMPILER_TRANSLATOR_VALIDATEMAXPARAMETERS_H_
+#define COMPILER_TRANSLATOR_VALIDATEMAXPARAMETERS_H_
+
+namespace sh
+{
+
+class TIntermBlock;
+
+// Return true if valid.
+bool ValidateMaxParameters(TIntermBlock *root, unsigned int maxParameters);
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_VALIDATEMAXPARAMETERS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp
index cd37aeacd1..26f0e81ba7 100644
--- a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp
@@ -3,64 +3,101 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
+// ValidateOutputs validates fragment shader outputs. It checks for conflicting locations,
+// out-of-range locations, that locations are specified when using multiple outputs, and YUV output
+// validity.
#include "compiler/translator/ValidateOutputs.h"
+
+#include <set>
+
#include "compiler/translator/InfoSink.h"
-#include "compiler/translator/InitializeParseContext.h"
+#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/ParseContext.h"
+namespace sh
+{
+
namespace
{
-void error(int *errorCount, TInfoSinkBase &sink, const TIntermSymbol &symbol, const char *reason)
+void error(const TIntermSymbol &symbol, const char *reason, TDiagnostics *diagnostics)
{
- sink.prefix(EPrefixError);
- sink.location(symbol.getLine());
- sink << "'" << symbol.getSymbol() << "' : " << reason << "\n";
- (*errorCount)++;
+ diagnostics->error(symbol.getLine(), reason, symbol.getSymbol().c_str());
}
-} // namespace
+class ValidateOutputsTraverser : public TIntermTraverser
+{
+ public:
+ ValidateOutputsTraverser(const TExtensionBehavior &extBehavior, int maxDrawBuffers);
+
+ void validate(TDiagnostics *diagnostics) const;
+
+ void visitSymbol(TIntermSymbol *) override;
-ValidateOutputs::ValidateOutputs(const TExtensionBehavior &extBehavior, int maxDrawBuffers)
+ private:
+ int mMaxDrawBuffers;
+ bool mAllowUnspecifiedOutputLocationResolution;
+ bool mUsesFragDepth;
+
+ typedef std::vector<TIntermSymbol *> OutputVector;
+ OutputVector mOutputs;
+ OutputVector mUnspecifiedLocationOutputs;
+ OutputVector mYuvOutputs;
+ std::set<std::string> mVisitedSymbols;
+};
+
+ValidateOutputsTraverser::ValidateOutputsTraverser(const TExtensionBehavior &extBehavior,
+ int maxDrawBuffers)
: TIntermTraverser(true, false, false),
mMaxDrawBuffers(maxDrawBuffers),
mAllowUnspecifiedOutputLocationResolution(
- IsExtensionEnabled(extBehavior, "GL_EXT_blend_func_extended"))
+ IsExtensionEnabled(extBehavior, TExtension::EXT_blend_func_extended)),
+ mUsesFragDepth(false)
{
}
-void ValidateOutputs::visitSymbol(TIntermSymbol *symbol)
+void ValidateOutputsTraverser::visitSymbol(TIntermSymbol *symbol)
{
- TString name = symbol->getSymbol();
+ TString name = symbol->getSymbol();
TQualifier qualifier = symbol->getQualifier();
- if (mVisitedSymbols.count(name) == 1)
+ if (mVisitedSymbols.count(name.c_str()) == 1)
return;
- mVisitedSymbols.insert(name);
+ mVisitedSymbols.insert(name.c_str());
if (qualifier == EvqFragmentOut)
{
- if (symbol->getType().getLayoutQualifier().location == -1)
+ if (symbol->getType().getLayoutQualifier().location != -1)
{
- mUnspecifiedLocationOutputs.push_back(symbol);
+ mOutputs.push_back(symbol);
+ }
+ else if (symbol->getType().getLayoutQualifier().yuv == true)
+ {
+ mYuvOutputs.push_back(symbol);
}
else
{
- mOutputs.push_back(symbol);
+ mUnspecifiedLocationOutputs.push_back(symbol);
}
}
+ else if (qualifier == EvqFragDepth || qualifier == EvqFragDepthEXT)
+ {
+ mUsesFragDepth = true;
+ }
}
-int ValidateOutputs::validateAndCountErrors(TInfoSinkBase &sink) const
+void ValidateOutputsTraverser::validate(TDiagnostics *diagnostics) const
{
+ ASSERT(diagnostics);
OutputVector validOutputs(mMaxDrawBuffers);
- int errorCount = 0;
for (const auto &symbol : mOutputs)
{
const TType &type = symbol->getType();
- const size_t elementCount = static_cast<size_t>(type.isArray() ? type.getArraySize() : 1);
+ ASSERT(!type.isArrayOfArrays()); // Disallowed in GLSL ES 3.10 section 4.3.6.
+ const size_t elementCount =
+ static_cast<size_t>(type.isArray() ? type.getOutermostArraySize() : 1u);
const size_t location = static_cast<size_t>(type.getLayoutQualifier().location);
ASSERT(type.getLayoutQualifier().location != -1);
@@ -75,7 +112,7 @@ int ValidateOutputs::validateAndCountErrors(TInfoSinkBase &sink) const
std::stringstream strstr;
strstr << "conflicting output locations with previously defined output '"
<< validOutputs[offsetLocation]->getSymbol() << "'";
- error(&errorCount, sink, *symbol, strstr.str().c_str());
+ error(*symbol, strstr.str().c_str(), diagnostics);
}
else
{
@@ -87,9 +124,10 @@ int ValidateOutputs::validateAndCountErrors(TInfoSinkBase &sink) const
{
if (elementCount > 0)
{
- error(&errorCount, sink, *symbol,
+ error(*symbol,
elementCount > 1 ? "output array locations would exceed MAX_DRAW_BUFFERS"
- : "output location must be < MAX_DRAW_BUFFERS");
+ : "output location must be < MAX_DRAW_BUFFERS",
+ diagnostics);
}
}
}
@@ -100,9 +138,37 @@ int ValidateOutputs::validateAndCountErrors(TInfoSinkBase &sink) const
{
for (const auto &symbol : mUnspecifiedLocationOutputs)
{
- error(&errorCount, sink, *symbol,
- "must explicitly specify all locations when using multiple fragment outputs");
+ error(*symbol,
+ "must explicitly specify all locations when using multiple fragment outputs",
+ diagnostics);
}
}
- return errorCount;
+
+ if (!mYuvOutputs.empty() && (mYuvOutputs.size() > 1 || mUsesFragDepth || !mOutputs.empty() ||
+ !mUnspecifiedLocationOutputs.empty()))
+ {
+ for (const auto &symbol : mYuvOutputs)
+ {
+ error(*symbol,
+ "not allowed to specify yuv qualifier when using depth or multiple color "
+ "fragment outputs",
+ diagnostics);
+ }
+ }
+}
+
+} // anonymous namespace
+
+bool ValidateOutputs(TIntermBlock *root,
+ const TExtensionBehavior &extBehavior,
+ int maxDrawBuffers,
+ TDiagnostics *diagnostics)
+{
+ ValidateOutputsTraverser validateOutputs(extBehavior, maxDrawBuffers);
+ root->traverse(&validateOutputs);
+ int numErrorsBefore = diagnostics->numErrors();
+ validateOutputs.validate(diagnostics);
+ return (diagnostics->numErrors() == numErrorsBefore);
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h
index 06f63994cd..e41ccd990c 100644
--- a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h
+++ b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h
@@ -3,34 +3,28 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
+// ValidateOutputs validates fragment shader outputs. It checks for conflicting locations,
+// out-of-range locations, that locations are specified when using multiple outputs, and YUV output
+// validity.
+//
#ifndef COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_
#define COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_
#include "compiler/translator/ExtensionBehavior.h"
-#include "compiler/translator/IntermNode.h"
-
-#include <set>
-class TInfoSinkBase;
-
-class ValidateOutputs : public TIntermTraverser
+namespace sh
{
- public:
- ValidateOutputs(const TExtensionBehavior &extBehavior, int maxDrawBuffers);
-
- int validateAndCountErrors(TInfoSinkBase &sink) const;
- void visitSymbol(TIntermSymbol *) override;
+class TIntermBlock;
+class TDiagnostics;
- private:
- int mMaxDrawBuffers;
- bool mAllowUnspecifiedOutputLocationResolution;
+// Returns true if the shader has no conflicting or otherwise erroneous fragment outputs.
+bool ValidateOutputs(TIntermBlock *root,
+ const TExtensionBehavior &extBehavior,
+ int maxDrawBuffers,
+ TDiagnostics *diagnostics);
- typedef std::vector<TIntermSymbol *> OutputVector;
- OutputVector mOutputs;
- OutputVector mUnspecifiedLocationOutputs;
- std::set<TString> mVisitedSymbols;
-};
+} // namespace sh
-#endif // COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_
+#endif // COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp
index 9a4ed33632..9f7a264e58 100644
--- a/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp
@@ -6,21 +6,76 @@
#include "compiler/translator/ValidateSwitch.h"
-#include "compiler/translator/ParseContext.h"
+#include "compiler/translator/Diagnostics.h"
+#include "compiler/translator/IntermTraverse.h"
-bool ValidateSwitch::validate(TBasicType switchType, TParseContext *context,
- TIntermAggregate *statementList, const TSourceLoc &loc)
+namespace sh
{
- ValidateSwitch validate(switchType, context);
+
+namespace
+{
+
+class ValidateSwitch : public TIntermTraverser
+{
+ public:
+ static bool validate(TBasicType switchType,
+ int shaderVersion,
+ TDiagnostics *diagnostics,
+ TIntermBlock *statementList,
+ const TSourceLoc &loc);
+
+ void visitSymbol(TIntermSymbol *) override;
+ void visitConstantUnion(TIntermConstantUnion *) override;
+ bool visitDeclaration(Visit, TIntermDeclaration *) override;
+ bool visitBlock(Visit, TIntermBlock *) override;
+ bool visitBinary(Visit, TIntermBinary *) override;
+ bool visitUnary(Visit, TIntermUnary *) override;
+ bool visitTernary(Visit, TIntermTernary *) override;
+ bool visitSwizzle(Visit, TIntermSwizzle *) override;
+ bool visitIfElse(Visit visit, TIntermIfElse *) override;
+ bool visitSwitch(Visit, TIntermSwitch *) override;
+ bool visitCase(Visit, TIntermCase *node) override;
+ bool visitAggregate(Visit, TIntermAggregate *) override;
+ bool visitLoop(Visit visit, TIntermLoop *) override;
+ bool visitBranch(Visit, TIntermBranch *) override;
+
+ private:
+ ValidateSwitch(TBasicType switchType, int shaderVersion, TDiagnostics *context);
+
+ bool validateInternal(const TSourceLoc &loc);
+
+ TBasicType mSwitchType;
+ int mShaderVersion;
+ TDiagnostics *mDiagnostics;
+ bool mCaseTypeMismatch;
+ bool mFirstCaseFound;
+ bool mStatementBeforeCase;
+ bool mLastStatementWasCase;
+ int mControlFlowDepth;
+ bool mCaseInsideControlFlow;
+ int mDefaultCount;
+ std::set<int> mCasesSigned;
+ std::set<unsigned int> mCasesUnsigned;
+ bool mDuplicateCases;
+};
+
+bool ValidateSwitch::validate(TBasicType switchType,
+ int shaderVersion,
+ TDiagnostics *diagnostics,
+ TIntermBlock *statementList,
+ const TSourceLoc &loc)
+{
+ ValidateSwitch validate(switchType, shaderVersion, diagnostics);
ASSERT(statementList);
statementList->traverse(&validate);
return validate.validateInternal(loc);
}
-ValidateSwitch::ValidateSwitch(TBasicType switchType, TParseContext *context)
+ValidateSwitch::ValidateSwitch(TBasicType switchType, int shaderVersion, TDiagnostics *diagnostics)
: TIntermTraverser(true, false, true),
mSwitchType(switchType),
- mContext(context),
+ mShaderVersion(shaderVersion),
+ mDiagnostics(diagnostics),
mCaseTypeMismatch(false),
mFirstCaseFound(false),
mStatementBeforeCase(false),
@@ -29,13 +84,14 @@ ValidateSwitch::ValidateSwitch(TBasicType switchType, TParseContext *context)
mCaseInsideControlFlow(false),
mDefaultCount(0),
mDuplicateCases(false)
-{}
+{
+}
void ValidateSwitch::visitSymbol(TIntermSymbol *)
{
if (!mFirstCaseFound)
mStatementBeforeCase = true;
- mLastStatementWasCase = false;
+ mLastStatementWasCase = false;
}
void ValidateSwitch::visitConstantUnion(TIntermConstantUnion *)
@@ -44,14 +100,33 @@ void ValidateSwitch::visitConstantUnion(TIntermConstantUnion *)
// Could be just a statement like "0;"
if (!mFirstCaseFound)
mStatementBeforeCase = true;
- mLastStatementWasCase = false;
+ mLastStatementWasCase = false;
+}
+
+bool ValidateSwitch::visitDeclaration(Visit, TIntermDeclaration *)
+{
+ if (!mFirstCaseFound)
+ mStatementBeforeCase = true;
+ mLastStatementWasCase = false;
+ return true;
+}
+
+bool ValidateSwitch::visitBlock(Visit, TIntermBlock *)
+{
+ if (getParentNode() != nullptr)
+ {
+ if (!mFirstCaseFound)
+ mStatementBeforeCase = true;
+ mLastStatementWasCase = false;
+ }
+ return true;
}
bool ValidateSwitch::visitBinary(Visit, TIntermBinary *)
{
if (!mFirstCaseFound)
mStatementBeforeCase = true;
- mLastStatementWasCase = false;
+ mLastStatementWasCase = false;
return true;
}
@@ -59,11 +134,27 @@ bool ValidateSwitch::visitUnary(Visit, TIntermUnary *)
{
if (!mFirstCaseFound)
mStatementBeforeCase = true;
- mLastStatementWasCase = false;
+ mLastStatementWasCase = false;
+ return true;
+}
+
+bool ValidateSwitch::visitTernary(Visit, TIntermTernary *)
+{
+ if (!mFirstCaseFound)
+ mStatementBeforeCase = true;
+ mLastStatementWasCase = false;
+ return true;
+}
+
+bool ValidateSwitch::visitSwizzle(Visit, TIntermSwizzle *)
+{
+ if (!mFirstCaseFound)
+ mStatementBeforeCase = true;
+ mLastStatementWasCase = false;
return true;
}
-bool ValidateSwitch::visitSelection(Visit visit, TIntermSelection *)
+bool ValidateSwitch::visitIfElse(Visit visit, TIntermIfElse *)
{
if (visit == PreVisit)
++mControlFlowDepth;
@@ -71,7 +162,7 @@ bool ValidateSwitch::visitSelection(Visit visit, TIntermSelection *)
--mControlFlowDepth;
if (!mFirstCaseFound)
mStatementBeforeCase = true;
- mLastStatementWasCase = false;
+ mLastStatementWasCase = false;
return true;
}
@@ -79,7 +170,7 @@ bool ValidateSwitch::visitSwitch(Visit, TIntermSwitch *)
{
if (!mFirstCaseFound)
mStatementBeforeCase = true;
- mLastStatementWasCase = false;
+ mLastStatementWasCase = false;
// Don't go into nested switch statements
return false;
}
@@ -89,17 +180,17 @@ bool ValidateSwitch::visitCase(Visit, TIntermCase *node)
const char *nodeStr = node->hasCondition() ? "case" : "default";
if (mControlFlowDepth > 0)
{
- mContext->error(node->getLine(), "label statement nested inside control flow", nodeStr);
+ mDiagnostics->error(node->getLine(), "label statement nested inside control flow", nodeStr);
mCaseInsideControlFlow = true;
}
- mFirstCaseFound = true;
+ mFirstCaseFound = true;
mLastStatementWasCase = true;
if (!node->hasCondition())
{
++mDefaultCount;
if (mDefaultCount > 1)
{
- mContext->error(node->getLine(), "duplicate default label", nodeStr);
+ mDiagnostics->error(node->getLine(), "duplicate default label", nodeStr);
}
}
else
@@ -113,8 +204,9 @@ bool ValidateSwitch::visitCase(Visit, TIntermCase *node)
TBasicType conditionType = condition->getBasicType();
if (conditionType != mSwitchType)
{
- mContext->error(condition->getLine(),
- "case label type does not match switch init-expression type", nodeStr);
+ mDiagnostics->error(condition->getLine(),
+ "case label type does not match switch init-expression type",
+ nodeStr);
mCaseTypeMismatch = true;
}
@@ -123,7 +215,7 @@ bool ValidateSwitch::visitCase(Visit, TIntermCase *node)
int iConst = condition->getIConst(0);
if (mCasesSigned.find(iConst) != mCasesSigned.end())
{
- mContext->error(condition->getLine(), "duplicate case label", nodeStr);
+ mDiagnostics->error(condition->getLine(), "duplicate case label", nodeStr);
mDuplicateCases = true;
}
else
@@ -136,7 +228,7 @@ bool ValidateSwitch::visitCase(Visit, TIntermCase *node)
unsigned int uConst = condition->getUConst(0);
if (mCasesUnsigned.find(uConst) != mCasesUnsigned.end())
{
- mContext->error(condition->getLine(), "duplicate case label", nodeStr);
+ mDiagnostics->error(condition->getLine(), "duplicate case label", nodeStr);
mDuplicateCases = true;
}
else
@@ -158,7 +250,7 @@ bool ValidateSwitch::visitAggregate(Visit visit, TIntermAggregate *)
// This is not the statementList node, but some other node.
if (!mFirstCaseFound)
mStatementBeforeCase = true;
- mLastStatementWasCase = false;
+ mLastStatementWasCase = false;
}
return true;
}
@@ -171,7 +263,7 @@ bool ValidateSwitch::visitLoop(Visit visit, TIntermLoop *)
--mControlFlowDepth;
if (!mFirstCaseFound)
mStatementBeforeCase = true;
- mLastStatementWasCase = false;
+ mLastStatementWasCase = false;
return true;
}
@@ -179,7 +271,7 @@ bool ValidateSwitch::visitBranch(Visit, TIntermBranch *)
{
if (!mFirstCaseFound)
mStatementBeforeCase = true;
- mLastStatementWasCase = false;
+ mLastStatementWasCase = false;
return true;
}
@@ -187,14 +279,41 @@ bool ValidateSwitch::validateInternal(const TSourceLoc &loc)
{
if (mStatementBeforeCase)
{
- mContext->error(loc,
- "statement before the first label", "switch");
+ mDiagnostics->error(loc, "statement before the first label", "switch");
}
+ bool lastStatementWasCaseError = false;
if (mLastStatementWasCase)
{
- mContext->error(loc,
- "no statement between the last label and the end of the switch statement", "switch");
+ if (mShaderVersion == 300)
+ {
+ lastStatementWasCaseError = true;
+ // This error has been proposed to be made optional in GLSL ES 3.00, but dEQP tests
+ // still require it.
+ mDiagnostics->error(
+ loc, "no statement between the last label and the end of the switch statement",
+ "switch");
+ }
+ else
+ {
+ // The error has been removed from GLSL ES 3.10.
+ mDiagnostics->warning(
+ loc, "no statement between the last label and the end of the switch statement",
+ "switch");
+ }
}
- return !mStatementBeforeCase && !mLastStatementWasCase && !mCaseInsideControlFlow &&
- !mCaseTypeMismatch && mDefaultCount <= 1 && !mDuplicateCases;
+ return !mStatementBeforeCase && !lastStatementWasCaseError && !mCaseInsideControlFlow &&
+ !mCaseTypeMismatch && mDefaultCount <= 1 && !mDuplicateCases;
+}
+
+} // anonymous namespace
+
+bool ValidateSwitchStatementList(TBasicType switchType,
+ int shaderVersion,
+ TDiagnostics *diagnostics,
+ TIntermBlock *statementList,
+ const TSourceLoc &loc)
+{
+ return ValidateSwitch::validate(switchType, shaderVersion, diagnostics, statementList, loc);
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h b/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h
index ddbefc5619..2d2dd70f78 100644
--- a/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h
+++ b/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h
@@ -7,46 +7,22 @@
#ifndef COMPILER_TRANSLATOR_VALIDATESWITCH_H_
#define COMPILER_TRANSLATOR_VALIDATESWITCH_H_
-#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/BaseTypes.h"
+#include "compiler/translator/Common.h"
-class TParseContext;
-
-class ValidateSwitch : public TIntermTraverser
+namespace sh
{
- public:
- // Check for errors and output messages any remaining errors on the context.
- // Returns true if there are no errors.
- static bool validate(TBasicType switchType, TParseContext *context,
- TIntermAggregate *statementList, const TSourceLoc &loc);
-
- void visitSymbol(TIntermSymbol *) override;
- void visitConstantUnion(TIntermConstantUnion *) override;
- bool visitBinary(Visit, TIntermBinary *) override;
- bool visitUnary(Visit, TIntermUnary *) override;
- bool visitSelection(Visit visit, TIntermSelection *) override;
- bool visitSwitch(Visit, TIntermSwitch *) override;
- bool visitCase(Visit, TIntermCase *node) override;
- bool visitAggregate(Visit, TIntermAggregate *) override;
- bool visitLoop(Visit visit, TIntermLoop *) override;
- bool visitBranch(Visit, TIntermBranch *) override;
-
- private:
- ValidateSwitch(TBasicType switchType, TParseContext *context);
+class TDiagnostics;
+class TIntermBlock;
- bool validateInternal(const TSourceLoc &loc);
+// Check for errors and output error messages on the context.
+// Returns true if there are no errors.
+bool ValidateSwitchStatementList(TBasicType switchType,
+ int shaderVersion,
+ TDiagnostics *diagnostics,
+ TIntermBlock *statementList,
+ const TSourceLoc &loc);
- TBasicType mSwitchType;
- TParseContext *mContext;
- bool mCaseTypeMismatch;
- bool mFirstCaseFound;
- bool mStatementBeforeCase;
- bool mLastStatementWasCase;
- int mControlFlowDepth;
- bool mCaseInsideControlFlow;
- int mDefaultCount;
- std::set<int> mCasesSigned;
- std::set<unsigned int> mCasesUnsigned;
- bool mDuplicateCases;
-};
+} // namespace sh
-#endif // COMPILER_TRANSLATOR_VALIDATESWITCH_H_
+#endif // COMPILER_TRANSLATOR_VALIDATESWITCH_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.cpp
new file mode 100644
index 0000000000..9c36fcea78
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.cpp
@@ -0,0 +1,174 @@
+//
+// Copyright (c) 2002-2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// The ValidateVaryingLocations function checks if there exists location conflicts on shader
+// varyings.
+//
+
+#include "ValidateVaryingLocations.h"
+
+#include "compiler/translator/Diagnostics.h"
+#include "compiler/translator/IntermTraverse.h"
+#include "compiler/translator/util.h"
+
+namespace sh
+{
+
+namespace
+{
+
+void error(const TIntermSymbol &symbol, const char *reason, TDiagnostics *diagnostics)
+{
+ diagnostics->error(symbol.getLine(), reason, symbol.getSymbol().c_str());
+}
+
+int GetLocationCount(const TIntermSymbol *varying, bool ignoreVaryingArraySize)
+{
+ const auto &varyingType = varying->getType();
+ if (varyingType.getStruct() != nullptr)
+ {
+ ASSERT(!varyingType.isArray());
+ int totalLocation = 0;
+ for (const auto *field : varyingType.getStruct()->fields())
+ {
+ const auto *fieldType = field->type();
+ ASSERT(fieldType->getStruct() == nullptr && !fieldType->isArray());
+
+ totalLocation += fieldType->getSecondarySize();
+ }
+ return totalLocation;
+ }
+ // [GL_OES_shader_io_blocks SPEC Chapter 4.4.1]
+ // Geometry shader inputs, tessellation control shader inputs and outputs, and tessellation
+ // evaluation inputs all have an additional level of arrayness relative to other shader inputs
+ // and outputs. This outer array level is removed from the type before considering how many
+ // locations the type consumes.
+ else if (ignoreVaryingArraySize)
+ {
+ // Array-of-arrays cannot be inputs or outputs of a geometry shader.
+ // (GL_OES_geometry_shader SPEC issues(5))
+ ASSERT(!varyingType.isArrayOfArrays());
+ return varyingType.getSecondarySize();
+ }
+ else
+ {
+ return varyingType.getSecondarySize() * static_cast<int>(varyingType.getArraySizeProduct());
+ }
+}
+
+using VaryingVector = std::vector<const TIntermSymbol *>;
+
+void ValidateShaderInterface(TDiagnostics *diagnostics,
+ VaryingVector &varyingVector,
+ bool ignoreVaryingArraySize)
+{
+ // Location conflicts can only happen when there are two or more varyings in varyingVector.
+ if (varyingVector.size() <= 1)
+ {
+ return;
+ }
+
+ std::map<int, const TIntermSymbol *> locationMap;
+ for (const TIntermSymbol *varying : varyingVector)
+ {
+ const int location = varying->getType().getLayoutQualifier().location;
+ ASSERT(location >= 0);
+
+ const int elementCount = GetLocationCount(varying, ignoreVaryingArraySize);
+ for (int elementIndex = 0; elementIndex < elementCount; ++elementIndex)
+ {
+ const int offsetLocation = location + elementIndex;
+ if (locationMap.find(offsetLocation) != locationMap.end())
+ {
+ std::stringstream strstr;
+ strstr << "'" << varying->getSymbol()
+ << "' conflicting location with previously defined '"
+ << locationMap[offsetLocation]->getSymbol() << "'";
+ error(*varying, strstr.str().c_str(), diagnostics);
+ }
+ else
+ {
+ locationMap[offsetLocation] = varying;
+ }
+ }
+ }
+}
+
+class ValidateVaryingLocationsTraverser : public TIntermTraverser
+{
+ public:
+ ValidateVaryingLocationsTraverser(GLenum shaderType);
+ void validate(TDiagnostics *diagnostics);
+
+ private:
+ bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
+ bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
+
+ VaryingVector mInputVaryingsWithLocation;
+ VaryingVector mOutputVaryingsWithLocation;
+ GLenum mShaderType;
+};
+
+ValidateVaryingLocationsTraverser::ValidateVaryingLocationsTraverser(GLenum shaderType)
+ : TIntermTraverser(true, false, false), mShaderType(shaderType)
+{
+}
+
+bool ValidateVaryingLocationsTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node)
+{
+ const TIntermSequence &sequence = *(node->getSequence());
+ ASSERT(!sequence.empty());
+
+ const TIntermSymbol *symbol = sequence.front()->getAsSymbolNode();
+ if (symbol == nullptr)
+ {
+ return false;
+ }
+
+ // Collect varyings that have explicit 'location' qualifiers.
+ const TQualifier qualifier = symbol->getQualifier();
+ if (symbol->getType().getLayoutQualifier().location != -1)
+ {
+ if (IsVaryingIn(qualifier))
+ {
+ mInputVaryingsWithLocation.push_back(symbol);
+ }
+ else if (IsVaryingOut(qualifier))
+ {
+ mOutputVaryingsWithLocation.push_back(symbol);
+ }
+ }
+
+ return false;
+}
+
+bool ValidateVaryingLocationsTraverser::visitFunctionDefinition(Visit visit,
+ TIntermFunctionDefinition *node)
+{
+ // We stop traversing function definitions because varyings cannot be defined in a function.
+ return false;
+}
+
+void ValidateVaryingLocationsTraverser::validate(TDiagnostics *diagnostics)
+{
+ ASSERT(diagnostics);
+
+ ValidateShaderInterface(diagnostics, mInputVaryingsWithLocation,
+ mShaderType == GL_GEOMETRY_SHADER_OES);
+ ValidateShaderInterface(diagnostics, mOutputVaryingsWithLocation, false);
+}
+
+} // anonymous namespace
+
+bool ValidateVaryingLocations(TIntermBlock *root, TDiagnostics *diagnostics, GLenum shaderType)
+{
+ ValidateVaryingLocationsTraverser varyingValidator(shaderType);
+ root->traverse(&varyingValidator);
+ int numErrorsBefore = diagnostics->numErrors();
+ varyingValidator.validate(diagnostics);
+ return (diagnostics->numErrors() == numErrorsBefore);
+}
+
+} // namespace sh \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.h b/src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.h
new file mode 100644
index 0000000000..1e53977c68
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/ValidateVaryingLocations.h
@@ -0,0 +1,25 @@
+//
+// Copyright (c) 2002-2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// The ValidateVaryingLocations function checks if there exists location conflicts on shader
+// varyings.
+//
+
+#ifndef COMPILER_TRANSLATOR_VALIDATEVARYINGLOCATIONS_H_
+#define COMPILER_TRANSLATOR_VALIDATEVARYINGLOCATIONS_H_
+
+#include "GLSLANG/ShaderVars.h"
+
+namespace sh
+{
+
+class TIntermBlock;
+class TDiagnostics;
+
+bool ValidateVaryingLocations(TIntermBlock *root, TDiagnostics *diagnostics, GLenum shaderType);
+
+} // namespace sh
+
+#endif \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp
deleted file mode 100644
index 3b6aa6a68e..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp
+++ /dev/null
@@ -1,673 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "angle_gl.h"
-#include "compiler/translator/SymbolTable.h"
-#include "compiler/translator/VariableInfo.h"
-#include "compiler/translator/util.h"
-#include "common/utilities.h"
-
-namespace sh
-{
-
-namespace
-{
-
-BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage)
-{
- switch (blockStorage)
- {
- case EbsPacked: return BLOCKLAYOUT_PACKED;
- case EbsShared: return BLOCKLAYOUT_SHARED;
- case EbsStd140: return BLOCKLAYOUT_STANDARD;
- default: UNREACHABLE(); return BLOCKLAYOUT_SHARED;
- }
-}
-
-void ExpandUserDefinedVariable(const ShaderVariable &variable,
- const std::string &name,
- const std::string &mappedName,
- bool markStaticUse,
- std::vector<ShaderVariable> *expanded);
-
-void ExpandVariable(const ShaderVariable &variable,
- const std::string &name,
- const std::string &mappedName,
- bool markStaticUse,
- std::vector<ShaderVariable> *expanded)
-{
- if (variable.isStruct())
- {
- if (variable.isArray())
- {
- for (unsigned int elementIndex = 0; elementIndex < variable.elementCount();
- elementIndex++)
- {
- std::string lname = name + ::ArrayString(elementIndex);
- std::string lmappedName = mappedName + ::ArrayString(elementIndex);
- ExpandUserDefinedVariable(variable, lname, lmappedName, markStaticUse, expanded);
- }
- }
- else
- {
- ExpandUserDefinedVariable(variable, name, mappedName, markStaticUse, expanded);
- }
- }
- else
- {
- ShaderVariable expandedVar = variable;
-
- expandedVar.name = name;
- expandedVar.mappedName = mappedName;
-
- // Mark all expanded fields as used if the parent is used
- if (markStaticUse)
- {
- expandedVar.staticUse = true;
- }
-
- if (expandedVar.isArray())
- {
- expandedVar.name += "[0]";
- expandedVar.mappedName += "[0]";
- }
-
- expanded->push_back(expandedVar);
- }
-}
-
-void ExpandUserDefinedVariable(const ShaderVariable &variable,
- const std::string &name,
- const std::string &mappedName,
- bool markStaticUse,
- std::vector<ShaderVariable> *expanded)
-{
- ASSERT(variable.isStruct());
-
- const std::vector<ShaderVariable> &fields = variable.fields;
-
- for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
- {
- const ShaderVariable &field = fields[fieldIndex];
- ExpandVariable(field,
- name + "." + field.name,
- mappedName + "." + field.mappedName,
- markStaticUse,
- expanded);
- }
-}
-
-template <class VarT>
-VarT *FindVariable(const TString &name,
- std::vector<VarT> *infoList)
-{
- // TODO(zmo): optimize this function.
- for (size_t ii = 0; ii < infoList->size(); ++ii)
- {
- if ((*infoList)[ii].name.c_str() == name)
- return &((*infoList)[ii]);
- }
-
- return NULL;
-}
-
-}
-
-CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
- std::vector<sh::OutputVariable> *outputVariables,
- std::vector<sh::Uniform> *uniforms,
- std::vector<sh::Varying> *varyings,
- std::vector<sh::InterfaceBlock> *interfaceBlocks,
- ShHashFunction64 hashFunction,
- const TSymbolTable &symbolTable)
- : TIntermTraverser(true, false, false),
- mAttribs(attribs),
- mOutputVariables(outputVariables),
- mUniforms(uniforms),
- mVaryings(varyings),
- mInterfaceBlocks(interfaceBlocks),
- mDepthRangeAdded(false),
- mPointCoordAdded(false),
- mFrontFacingAdded(false),
- mFragCoordAdded(false),
- mInstanceIDAdded(false),
- mPositionAdded(false),
- mPointSizeAdded(false),
- mLastFragDataAdded(false),
- mFragColorAdded(false),
- mFragDataAdded(false),
- mFragDepthEXTAdded(false),
- mFragDepthAdded(false),
- mSecondaryFragColorEXTAdded(false),
- mSecondaryFragDataEXTAdded(false),
- mHashFunction(hashFunction),
- mSymbolTable(symbolTable)
-{
-}
-
-// We want to check whether a uniform/varying is statically used
-// because we only count the used ones in packing computing.
-// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
-// toward varying counting if they are statically used in a fragment
-// shader.
-void CollectVariables::visitSymbol(TIntermSymbol *symbol)
-{
- ASSERT(symbol != NULL);
- ShaderVariable *var = NULL;
- const TString &symbolName = symbol->getSymbol();
-
- if (IsVarying(symbol->getQualifier()))
- {
- var = FindVariable(symbolName, mVaryings);
- }
- else if (symbol->getType().getBasicType() == EbtInterfaceBlock)
- {
- UNREACHABLE();
- }
- else if (symbolName == "gl_DepthRange")
- {
- ASSERT(symbol->getQualifier() == EvqUniform);
-
- if (!mDepthRangeAdded)
- {
- Uniform info;
- const char kName[] = "gl_DepthRange";
- info.name = kName;
- info.mappedName = kName;
- info.type = GL_STRUCT_ANGLEX;
- info.arraySize = 0;
- info.precision = GL_NONE;
- info.staticUse = true;
-
- ShaderVariable nearInfo;
- const char kNearName[] = "near";
- nearInfo.name = kNearName;
- nearInfo.mappedName = kNearName;
- nearInfo.type = GL_FLOAT;
- nearInfo.arraySize = 0;
- nearInfo.precision = GL_HIGH_FLOAT;
- nearInfo.staticUse = true;
-
- ShaderVariable farInfo;
- const char kFarName[] = "far";
- farInfo.name = kFarName;
- farInfo.mappedName = kFarName;
- farInfo.type = GL_FLOAT;
- farInfo.arraySize = 0;
- farInfo.precision = GL_HIGH_FLOAT;
- farInfo.staticUse = true;
-
- ShaderVariable diffInfo;
- const char kDiffName[] = "diff";
- diffInfo.name = kDiffName;
- diffInfo.mappedName = kDiffName;
- diffInfo.type = GL_FLOAT;
- diffInfo.arraySize = 0;
- diffInfo.precision = GL_HIGH_FLOAT;
- diffInfo.staticUse = true;
-
- info.fields.push_back(nearInfo);
- info.fields.push_back(farInfo);
- info.fields.push_back(diffInfo);
-
- mUniforms->push_back(info);
- mDepthRangeAdded = true;
- }
- }
- else
- {
- switch (symbol->getQualifier())
- {
- case EvqAttribute:
- case EvqVertexIn:
- var = FindVariable(symbolName, mAttribs);
- break;
- case EvqFragmentOut:
- var = FindVariable(symbolName, mOutputVariables);
- break;
- case EvqUniform:
- {
- const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
- if (interfaceBlock)
- {
- InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
- ASSERT(namedBlock);
- var = FindVariable(symbolName, &namedBlock->fields);
-
- // Set static use on the parent interface block here
- namedBlock->staticUse = true;
- }
- else
- {
- var = FindVariable(symbolName, mUniforms);
- }
-
- // It's an internal error to reference an undefined user uniform
- ASSERT(symbolName.compare(0, 3, "gl_") != 0 || var);
- }
- break;
- case EvqFragCoord:
- if (!mFragCoordAdded)
- {
- Varying info;
- const char kName[] = "gl_FragCoord";
- info.name = kName;
- info.mappedName = kName;
- info.type = GL_FLOAT_VEC4;
- info.arraySize = 0;
- info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
- info.staticUse = true;
- info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
- mVaryings->push_back(info);
- mFragCoordAdded = true;
- }
- return;
- case EvqFrontFacing:
- if (!mFrontFacingAdded)
- {
- Varying info;
- const char kName[] = "gl_FrontFacing";
- info.name = kName;
- info.mappedName = kName;
- info.type = GL_BOOL;
- info.arraySize = 0;
- info.precision = GL_NONE;
- info.staticUse = true;
- info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
- mVaryings->push_back(info);
- mFrontFacingAdded = true;
- }
- return;
- case EvqPointCoord:
- if (!mPointCoordAdded)
- {
- Varying info;
- const char kName[] = "gl_PointCoord";
- info.name = kName;
- info.mappedName = kName;
- info.type = GL_FLOAT_VEC2;
- info.arraySize = 0;
- info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
- info.staticUse = true;
- info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
- mVaryings->push_back(info);
- mPointCoordAdded = true;
- }
- return;
- case EvqInstanceID:
- if (!mInstanceIDAdded)
- {
- Attribute info;
- const char kName[] = "gl_InstanceID";
- info.name = kName;
- info.mappedName = kName;
- info.type = GL_INT;
- info.arraySize = 0;
- info.precision = GL_HIGH_INT; // Defined by spec.
- info.staticUse = true;
- info.location = -1;
- mAttribs->push_back(info);
- mInstanceIDAdded = true;
- }
- return;
- case EvqPosition:
- if (!mPositionAdded)
- {
- Varying info;
- const char kName[] = "gl_Position";
- info.name = kName;
- info.mappedName = kName;
- info.type = GL_FLOAT_VEC4;
- info.arraySize = 0;
- info.precision = GL_HIGH_FLOAT; // Defined by spec.
- info.staticUse = true;
- info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
- mVaryings->push_back(info);
- mPositionAdded = true;
- }
- return;
- case EvqPointSize:
- if (!mPointSizeAdded)
- {
- Varying info;
- const char kName[] = "gl_PointSize";
- info.name = kName;
- info.mappedName = kName;
- info.type = GL_FLOAT;
- info.arraySize = 0;
- info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
- info.staticUse = true;
- info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
- mVaryings->push_back(info);
- mPointSizeAdded = true;
- }
- return;
- case EvqLastFragData:
- if (!mLastFragDataAdded)
- {
- Varying info;
- const char kName[] = "gl_LastFragData";
- info.name = kName;
- info.mappedName = kName;
- info.type = GL_FLOAT_VEC4;
- info.arraySize = static_cast<const TVariable*>(mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))->getConstPointer()->getIConst();
- info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
- info.staticUse = true;
- info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
- mVaryings->push_back(info);
- mLastFragDataAdded = true;
- }
- return;
- case EvqFragColor:
- if (!mFragColorAdded)
- {
- OutputVariable info;
- const char kName[] = "gl_FragColor";
- info.name = kName;
- info.mappedName = kName;
- info.type = GL_FLOAT_VEC4;
- info.arraySize = 0;
- info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
- info.staticUse = true;
- mOutputVariables->push_back(info);
- mFragColorAdded = true;
- }
- return;
- case EvqFragData:
- if (!mFragDataAdded)
- {
- OutputVariable info;
- const char kName[] = "gl_FragData";
- info.name = kName;
- info.mappedName = kName;
- info.type = GL_FLOAT_VEC4;
- info.arraySize = static_cast<const TVariable *>(
- mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))
- ->getConstPointer()
- ->getIConst();
- info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
- info.staticUse = true;
- mOutputVariables->push_back(info);
- mFragDataAdded = true;
- }
- return;
- case EvqFragDepthEXT:
- if (!mFragDepthEXTAdded)
- {
- OutputVariable info;
- const char kName[] = "gl_FragDepthEXT";
- info.name = kName;
- info.mappedName = kName;
- info.type = GL_FLOAT;
- info.arraySize = 0;
- info.precision =
- GLVariablePrecision(static_cast<const TVariable *>(
- mSymbolTable.findBuiltIn("gl_FragDepthEXT", 100))
- ->getType());
- info.staticUse = true;
- mOutputVariables->push_back(info);
- mFragDepthEXTAdded = true;
- }
- return;
- case EvqFragDepth:
- if (!mFragDepthAdded)
- {
- OutputVariable info;
- const char kName[] = "gl_FragDepth";
- info.name = kName;
- info.mappedName = kName;
- info.type = GL_FLOAT;
- info.arraySize = 0;
- info.precision = GL_HIGH_FLOAT;
- info.staticUse = true;
- mOutputVariables->push_back(info);
- mFragDepthAdded = true;
- }
- return;
- case EvqSecondaryFragColorEXT:
- if (!mSecondaryFragColorEXTAdded)
- {
- OutputVariable info;
- const char kName[] = "gl_SecondaryFragColorEXT";
- info.name = kName;
- info.mappedName = kName;
- info.type = GL_FLOAT_VEC4;
- info.arraySize = 0;
- info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
- info.staticUse = true;
- mOutputVariables->push_back(info);
- mSecondaryFragColorEXTAdded = true;
- }
- return;
- case EvqSecondaryFragDataEXT:
- if (!mSecondaryFragDataEXTAdded)
- {
- OutputVariable info;
- const char kName[] = "gl_SecondaryFragDataEXT";
- info.name = kName;
- info.mappedName = kName;
- info.type = GL_FLOAT_VEC4;
-
- const TVariable *maxDualSourceDrawBuffersVar = static_cast<const TVariable *>(
- mSymbolTable.findBuiltIn("gl_MaxDualSourceDrawBuffersEXT", 100));
- info.arraySize = maxDualSourceDrawBuffersVar->getConstPointer()->getIConst();
- info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
- info.staticUse = true;
- mOutputVariables->push_back(info);
- mSecondaryFragDataEXTAdded = true;
- }
- return;
- default:
- break;
- }
- }
- if (var)
- {
- var->staticUse = true;
- }
-}
-
-class NameHashingTraverser : public GetVariableTraverser
-{
- public:
- NameHashingTraverser(ShHashFunction64 hashFunction,
- const TSymbolTable &symbolTable)
- : GetVariableTraverser(symbolTable),
- mHashFunction(hashFunction)
- {}
-
- private:
- void visitVariable(ShaderVariable *variable) override
- {
- TString stringName = TString(variable->name.c_str());
- variable->mappedName = TIntermTraverser::hash(stringName, mHashFunction).c_str();
- }
-
- ShHashFunction64 mHashFunction;
-};
-
-// Attributes, which cannot have struct fields, are a special case
-template <>
-void CollectVariables::visitVariable(const TIntermSymbol *variable,
- std::vector<Attribute> *infoList) const
-{
- ASSERT(variable);
- const TType &type = variable->getType();
- ASSERT(!type.getStruct());
-
- Attribute attribute;
-
- attribute.type = GLVariableType(type);
- attribute.precision = GLVariablePrecision(type);
- attribute.name = variable->getSymbol().c_str();
- attribute.arraySize = static_cast<unsigned int>(type.getArraySize());
- attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
- attribute.location = variable->getType().getLayoutQualifier().location;
-
- infoList->push_back(attribute);
-}
-
-template <>
-void CollectVariables::visitVariable(const TIntermSymbol *variable,
- std::vector<OutputVariable> *infoList) const
-{
- ASSERT(variable);
- const TType &type = variable->getType();
- ASSERT(!type.getStruct());
-
- OutputVariable attribute;
-
- attribute.type = GLVariableType(type);
- attribute.precision = GLVariablePrecision(type);
- attribute.name = variable->getSymbol().c_str();
- attribute.arraySize = static_cast<unsigned int>(type.getArraySize());
- attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
- attribute.location = variable->getType().getLayoutQualifier().location;
-
- infoList->push_back(attribute);
-}
-
-template <>
-void CollectVariables::visitVariable(const TIntermSymbol *variable,
- std::vector<InterfaceBlock> *infoList) const
-{
- InterfaceBlock interfaceBlock;
- const TInterfaceBlock *blockType = variable->getType().getInterfaceBlock();
- ASSERT(blockType);
-
- interfaceBlock.name = blockType->name().c_str();
- interfaceBlock.mappedName =
- TIntermTraverser::hash(blockType->name().c_str(), mHashFunction).c_str();
- interfaceBlock.instanceName = (blockType->hasInstanceName() ? blockType->instanceName().c_str() : "");
- interfaceBlock.arraySize = variable->getArraySize();
- interfaceBlock.isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor);
- interfaceBlock.layout = GetBlockLayoutType(blockType->blockStorage());
-
- // Gather field information
- for (const TField *field : blockType->fields())
- {
- const TType &fieldType = *field->type();
-
- NameHashingTraverser traverser(mHashFunction, mSymbolTable);
- traverser.traverse(fieldType, field->name(), &interfaceBlock.fields);
-
- interfaceBlock.fields.back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
- }
-
- infoList->push_back(interfaceBlock);
-}
-
-template <typename VarT>
-void CollectVariables::visitVariable(const TIntermSymbol *variable,
- std::vector<VarT> *infoList) const
-{
- NameHashingTraverser traverser(mHashFunction, mSymbolTable);
- traverser.traverse(variable->getType(), variable->getSymbol(), infoList);
-}
-
-template <typename VarT>
-void CollectVariables::visitInfoList(const TIntermSequence &sequence,
- std::vector<VarT> *infoList) const
-{
- for (size_t seqIndex = 0; seqIndex < sequence.size(); seqIndex++)
- {
- const TIntermSymbol *variable = sequence[seqIndex]->getAsSymbolNode();
- // The only case in which the sequence will not contain a
- // TIntermSymbol node is initialization. It will contain a
- // TInterBinary node in that case. Since attributes, uniforms,
- // and varyings cannot be initialized in a shader, we must have
- // only TIntermSymbol nodes in the sequence.
- ASSERT(variable != NULL);
- visitVariable(variable, infoList);
- }
-}
-
-bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node)
-{
- bool visitChildren = true;
-
- switch (node->getOp())
- {
- case EOpDeclaration:
- {
- const TIntermSequence &sequence = *(node->getSequence());
- ASSERT(!sequence.empty());
-
- const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
- TQualifier qualifier = typedNode.getQualifier();
-
- if (typedNode.getBasicType() == EbtInterfaceBlock)
- {
- visitInfoList(sequence, mInterfaceBlocks);
- visitChildren = false;
- }
- else if (qualifier == EvqAttribute || qualifier == EvqVertexIn ||
- qualifier == EvqFragmentOut || qualifier == EvqUniform ||
- IsVarying(qualifier))
- {
- switch (qualifier)
- {
- case EvqAttribute:
- case EvqVertexIn:
- visitInfoList(sequence, mAttribs);
- break;
- case EvqFragmentOut:
- visitInfoList(sequence, mOutputVariables);
- break;
- case EvqUniform:
- visitInfoList(sequence, mUniforms);
- break;
- default:
- visitInfoList(sequence, mVaryings);
- break;
- }
-
- visitChildren = false;
- }
- break;
- }
- default: break;
- }
-
- return visitChildren;
-}
-
-bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode)
-{
- if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
- {
- // NOTE: we do not determine static use for individual blocks of an array
- TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
- ASSERT(blockNode);
-
- TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
- ASSERT(constantUnion);
-
- const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
- InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
- ASSERT(namedBlock);
- namedBlock->staticUse = true;
-
- unsigned int fieldIndex = constantUnion->getUConst(0);
- ASSERT(fieldIndex < namedBlock->fields.size());
- namedBlock->fields[fieldIndex].staticUse = true;
- return false;
- }
-
- return true;
-}
-
-void ExpandUniforms(const std::vector<Uniform> &compact,
- std::vector<ShaderVariable> *expanded)
-{
- for (size_t variableIndex = 0; variableIndex < compact.size(); variableIndex++)
- {
- const ShaderVariable &variable = compact[variableIndex];
- ExpandVariable(variable, variable.name, variable.mappedName, variable.staticUse, expanded);
- }
-}
-
-}
diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.h b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h
deleted file mode 100644
index 9498e9b3a0..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/VariableInfo.h
+++ /dev/null
@@ -1,77 +0,0 @@
-//
-// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_TRANSLATOR_VARIABLEINFO_H_
-#define COMPILER_TRANSLATOR_VARIABLEINFO_H_
-
-#include <GLSLANG/ShaderLang.h>
-
-#include "compiler/translator/IntermNode.h"
-
-class TSymbolTable;
-
-namespace sh
-{
-
-// Traverses intermediate tree to collect all attributes, uniforms, varyings.
-class CollectVariables : public TIntermTraverser
-{
- public:
- CollectVariables(std::vector<Attribute> *attribs,
- std::vector<OutputVariable> *outputVariables,
- std::vector<Uniform> *uniforms,
- std::vector<Varying> *varyings,
- std::vector<InterfaceBlock> *interfaceBlocks,
- ShHashFunction64 hashFunction,
- const TSymbolTable &symbolTable);
-
- void visitSymbol(TIntermSymbol *symbol) override;
- bool visitAggregate(Visit, TIntermAggregate *node) override;
- bool visitBinary(Visit visit, TIntermBinary *binaryNode) override;
-
- private:
- template <typename VarT>
- void visitVariable(const TIntermSymbol *variable, std::vector<VarT> *infoList) const;
-
- template <typename VarT>
- void visitInfoList(const TIntermSequence &sequence, std::vector<VarT> *infoList) const;
-
- std::vector<Attribute> *mAttribs;
- std::vector<OutputVariable> *mOutputVariables;
- std::vector<Uniform> *mUniforms;
- std::vector<Varying> *mVaryings;
- std::vector<InterfaceBlock> *mInterfaceBlocks;
-
- std::map<std::string, InterfaceBlockField *> mInterfaceBlockFields;
-
- bool mDepthRangeAdded;
- bool mPointCoordAdded;
- bool mFrontFacingAdded;
- bool mFragCoordAdded;
-
- bool mInstanceIDAdded;
- bool mPositionAdded;
- bool mPointSizeAdded;
- bool mLastFragDataAdded;
- bool mFragColorAdded;
- bool mFragDataAdded;
- bool mFragDepthEXTAdded;
- bool mFragDepthAdded;
- bool mSecondaryFragColorEXTAdded;
- bool mSecondaryFragDataEXTAdded;
-
- ShHashFunction64 mHashFunction;
-
- const TSymbolTable &mSymbolTable;
-};
-
-// Expand struct uniforms to flattened lists of split variables
-void ExpandUniforms(const std::vector<Uniform> &compact,
- std::vector<ShaderVariable> *expanded);
-
-}
-
-#endif // COMPILER_TRANSLATOR_VARIABLEINFO_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp b/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp
index e69052162a..6dd396ff02 100644
--- a/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp
@@ -3,6 +3,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
+// Check whether variables fit within packing limits according to the packing rules from the GLSL ES
+// 1.00.17 spec, Appendix A, section 7.
#include <algorithm>
@@ -11,259 +13,401 @@
#include "compiler/translator/VariablePacker.h"
#include "common/utilities.h"
-int VariablePacker::GetNumComponentsPerRow(sh::GLenum type)
+namespace sh
{
- switch (type)
+
+namespace
+{
+
+// Expand the variable so that struct variables are split into their individual fields.
+// Will not set the mappedName or staticUse fields on the expanded variables.
+void ExpandVariable(const ShaderVariable &variable,
+ const std::string &name,
+ std::vector<ShaderVariable> *expanded);
+
+void ExpandStructVariable(const ShaderVariable &variable,
+ const std::string &name,
+ std::vector<ShaderVariable> *expanded)
+{
+ ASSERT(variable.isStruct());
+
+ const std::vector<ShaderVariable> &fields = variable.fields;
+
+ for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
{
- case GL_FLOAT_MAT4:
- case GL_FLOAT_MAT2:
- case GL_FLOAT_MAT2x4:
- case GL_FLOAT_MAT3x4:
- case GL_FLOAT_MAT4x2:
- case GL_FLOAT_MAT4x3:
- case GL_FLOAT_VEC4:
- case GL_INT_VEC4:
- case GL_BOOL_VEC4:
- case GL_UNSIGNED_INT_VEC4:
- return 4;
- case GL_FLOAT_MAT3:
- case GL_FLOAT_MAT2x3:
- case GL_FLOAT_MAT3x2:
- case GL_FLOAT_VEC3:
- case GL_INT_VEC3:
- case GL_BOOL_VEC3:
- case GL_UNSIGNED_INT_VEC3:
- return 3;
- case GL_FLOAT_VEC2:
- case GL_INT_VEC2:
- case GL_BOOL_VEC2:
- case GL_UNSIGNED_INT_VEC2:
- return 2;
- default:
- ASSERT(gl::VariableComponentCount(type) == 1);
- return 1;
+ const ShaderVariable &field = fields[fieldIndex];
+ ExpandVariable(field, name + "." + field.name, expanded);
}
}
-int VariablePacker::GetNumRows(sh::GLenum type)
+void ExpandStructArrayVariable(const ShaderVariable &variable,
+ unsigned int arrayNestingIndex,
+ const std::string &name,
+ std::vector<ShaderVariable> *expanded)
{
- switch (type)
+ // Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the
+ // innermost.
+ const unsigned int currentArraySize = variable.getNestedArraySize(arrayNestingIndex);
+ for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement)
{
- case GL_FLOAT_MAT4:
- case GL_FLOAT_MAT2x4:
- case GL_FLOAT_MAT3x4:
- case GL_FLOAT_MAT4x3:
- case GL_FLOAT_MAT4x2:
- return 4;
- case GL_FLOAT_MAT3:
- case GL_FLOAT_MAT2x3:
- case GL_FLOAT_MAT3x2:
- return 3;
- case GL_FLOAT_MAT2:
- return 2;
- default:
- ASSERT(gl::VariableRowCount(type) == 1);
- return 1;
+ const std::string elementName = name + ArrayString(arrayElement);
+ if (arrayNestingIndex + 1u < variable.arraySizes.size())
+ {
+ ExpandStructArrayVariable(variable, arrayNestingIndex + 1u, elementName, expanded);
+ }
+ else
+ {
+ ExpandStructVariable(variable, elementName, expanded);
+ }
}
}
+void ExpandVariable(const ShaderVariable &variable,
+ const std::string &name,
+ std::vector<ShaderVariable> *expanded)
+{
+ if (variable.isStruct())
+ {
+ if (variable.isArray())
+ {
+ ExpandStructArrayVariable(variable, 0u, name, expanded);
+ }
+ else
+ {
+ ExpandStructVariable(variable, name, expanded);
+ }
+ }
+ else
+ {
+ ShaderVariable expandedVar = variable;
+ expandedVar.name = name;
+
+ expanded->push_back(expandedVar);
+ }
+}
+
+int GetVariablePackingRows(const ShaderVariable &variable)
+{
+ return GetTypePackingRows(variable.type) * variable.getArraySizeProduct();
+}
+
+class VariablePacker
+{
+ public:
+ bool checkExpandedVariablesWithinPackingLimits(unsigned int maxVectors,
+ std::vector<sh::ShaderVariable> *variables);
+
+ private:
+ static const int kNumColumns = 4;
+ static const unsigned kColumnMask = (1 << kNumColumns) - 1;
+
+ unsigned makeColumnFlags(int column, int numComponentsPerRow);
+ void fillColumns(int topRow, int numRows, int column, int numComponentsPerRow);
+ bool searchColumn(int column, int numRows, int *destRow, int *destSize);
+
+ int topNonFullRow_;
+ int bottomNonFullRow_;
+ int maxRows_;
+ std::vector<unsigned> rows_;
+};
+
struct TVariableInfoComparer
{
bool operator()(const sh::ShaderVariable &lhs, const sh::ShaderVariable &rhs) const
{
int lhsSortOrder = gl::VariableSortOrder(lhs.type);
int rhsSortOrder = gl::VariableSortOrder(rhs.type);
- if (lhsSortOrder != rhsSortOrder) {
+ if (lhsSortOrder != rhsSortOrder)
+ {
return lhsSortOrder < rhsSortOrder;
}
// Sort by largest first.
- return lhs.arraySize > rhs.arraySize;
+ return lhs.getArraySizeProduct() > rhs.getArraySizeProduct();
}
};
unsigned VariablePacker::makeColumnFlags(int column, int numComponentsPerRow)
{
- return ((kColumnMask << (kNumColumns - numComponentsPerRow)) &
- kColumnMask) >> column;
+ return ((kColumnMask << (kNumColumns - numComponentsPerRow)) & kColumnMask) >> column;
}
void VariablePacker::fillColumns(int topRow, int numRows, int column, int numComponentsPerRow)
{
unsigned columnFlags = makeColumnFlags(column, numComponentsPerRow);
- for (int r = 0; r < numRows; ++r) {
+ for (int r = 0; r < numRows; ++r)
+ {
int row = topRow + r;
ASSERT((rows_[row] & columnFlags) == 0);
rows_[row] |= columnFlags;
}
}
-bool VariablePacker::searchColumn(int column, int numRows, int* destRow, int* destSize)
+bool VariablePacker::searchColumn(int column, int numRows, int *destRow, int *destSize)
{
ASSERT(destRow);
- for (; topNonFullRow_ < maxRows_ && rows_[topNonFullRow_] == kColumnMask;
- ++topNonFullRow_) {
+ for (; topNonFullRow_ < maxRows_ && rows_[topNonFullRow_] == kColumnMask; ++topNonFullRow_)
+ {
}
- for (; bottomNonFullRow_ >= 0 && rows_[bottomNonFullRow_] == kColumnMask;
- --bottomNonFullRow_) {
+ for (; bottomNonFullRow_ >= 0 && rows_[bottomNonFullRow_] == kColumnMask; --bottomNonFullRow_)
+ {
}
- if (bottomNonFullRow_ - topNonFullRow_ + 1 < numRows) {
+ if (bottomNonFullRow_ - topNonFullRow_ + 1 < numRows)
+ {
return false;
}
unsigned columnFlags = makeColumnFlags(column, 1);
- int topGoodRow = 0;
- int smallestGoodTop = -1;
+ int topGoodRow = 0;
+ int smallestGoodTop = -1;
int smallestGoodSize = maxRows_ + 1;
- int bottomRow = bottomNonFullRow_ + 1;
- bool found = false;
- for (int row = topNonFullRow_; row <= bottomRow; ++row) {
+ int bottomRow = bottomNonFullRow_ + 1;
+ bool found = false;
+ for (int row = topNonFullRow_; row <= bottomRow; ++row)
+ {
bool rowEmpty = row < bottomRow ? ((rows_[row] & columnFlags) == 0) : false;
- if (rowEmpty) {
- if (!found) {
+ if (rowEmpty)
+ {
+ if (!found)
+ {
topGoodRow = row;
- found = true;
+ found = true;
}
- } else {
- if (found) {
+ }
+ else
+ {
+ if (found)
+ {
int size = row - topGoodRow;
- if (size >= numRows && size < smallestGoodSize) {
+ if (size >= numRows && size < smallestGoodSize)
+ {
smallestGoodSize = size;
- smallestGoodTop = topGoodRow;
+ smallestGoodTop = topGoodRow;
}
}
found = false;
}
}
- if (smallestGoodTop < 0) {
+ if (smallestGoodTop < 0)
+ {
return false;
}
*destRow = smallestGoodTop;
- if (destSize) {
+ if (destSize)
+ {
*destSize = smallestGoodSize;
}
return true;
}
-template <typename VarT>
-bool VariablePacker::CheckVariablesWithinPackingLimits(unsigned int maxVectors,
- const std::vector<VarT> &in_variables)
+bool VariablePacker::checkExpandedVariablesWithinPackingLimits(
+ unsigned int maxVectors,
+ std::vector<sh::ShaderVariable> *variables)
{
ASSERT(maxVectors > 0);
- maxRows_ = maxVectors;
- topNonFullRow_ = 0;
+ maxRows_ = maxVectors;
+ topNonFullRow_ = 0;
bottomNonFullRow_ = maxRows_ - 1;
- std::vector<VarT> variables(in_variables);
// Check whether each variable fits in the available vectors.
- for (size_t i = 0; i < variables.size(); i++) {
- const sh::ShaderVariable &variable = variables[i];
- if (variable.elementCount() > maxVectors / GetNumRows(variable.type)) {
+ for (const sh::ShaderVariable &variable : *variables)
+ {
+ // Structs should have been expanded before reaching here.
+ ASSERT(!variable.isStruct());
+ if (variable.getArraySizeProduct() > maxVectors / GetTypePackingRows(variable.type))
+ {
return false;
}
}
// As per GLSL 1.017 Appendix A, Section 7 variables are packed in specific
// order by type, then by size of array, largest first.
- std::sort(variables.begin(), variables.end(), TVariableInfoComparer());
+ std::sort(variables->begin(), variables->end(), TVariableInfoComparer());
rows_.clear();
rows_.resize(maxVectors, 0);
// Packs the 4 column variables.
size_t ii = 0;
- for (; ii < variables.size(); ++ii) {
- const sh::ShaderVariable &variable = variables[ii];
- if (GetNumComponentsPerRow(variable.type) != 4) {
+ for (; ii < variables->size(); ++ii)
+ {
+ const sh::ShaderVariable &variable = (*variables)[ii];
+ if (GetTypePackingComponentsPerRow(variable.type) != 4)
+ {
break;
}
- topNonFullRow_ += GetNumRows(variable.type) * variable.elementCount();
+ topNonFullRow_ += GetVariablePackingRows(variable);
}
- if (topNonFullRow_ > maxRows_) {
+ if (topNonFullRow_ > maxRows_)
+ {
return false;
}
// Packs the 3 column variables.
int num3ColumnRows = 0;
- for (; ii < variables.size(); ++ii) {
- const sh::ShaderVariable &variable = variables[ii];
- if (GetNumComponentsPerRow(variable.type) != 3) {
+ for (; ii < variables->size(); ++ii)
+ {
+ const sh::ShaderVariable &variable = (*variables)[ii];
+ if (GetTypePackingComponentsPerRow(variable.type) != 3)
+ {
break;
}
- num3ColumnRows += GetNumRows(variable.type) * variable.elementCount();
+ num3ColumnRows += GetVariablePackingRows(variable);
}
- if (topNonFullRow_ + num3ColumnRows > maxRows_) {
+ if (topNonFullRow_ + num3ColumnRows > maxRows_)
+ {
return false;
}
fillColumns(topNonFullRow_, num3ColumnRows, 0, 3);
// Packs the 2 column variables.
- int top2ColumnRow = topNonFullRow_ + num3ColumnRows;
- int twoColumnRowsAvailable = maxRows_ - top2ColumnRow;
+ int top2ColumnRow = topNonFullRow_ + num3ColumnRows;
+ int twoColumnRowsAvailable = maxRows_ - top2ColumnRow;
int rowsAvailableInColumns01 = twoColumnRowsAvailable;
int rowsAvailableInColumns23 = twoColumnRowsAvailable;
- for (; ii < variables.size(); ++ii) {
- const sh::ShaderVariable &variable = variables[ii];
- if (GetNumComponentsPerRow(variable.type) != 2) {
+ for (; ii < variables->size(); ++ii)
+ {
+ const sh::ShaderVariable &variable = (*variables)[ii];
+ if (GetTypePackingComponentsPerRow(variable.type) != 2)
+ {
break;
}
- int numRows = GetNumRows(variable.type) * variable.elementCount();
- if (numRows <= rowsAvailableInColumns01) {
+ int numRows = GetVariablePackingRows(variable);
+ if (numRows <= rowsAvailableInColumns01)
+ {
rowsAvailableInColumns01 -= numRows;
- } else if (numRows <= rowsAvailableInColumns23) {
+ }
+ else if (numRows <= rowsAvailableInColumns23)
+ {
rowsAvailableInColumns23 -= numRows;
- } else {
+ }
+ else
+ {
return false;
}
}
- int numRowsUsedInColumns01 =
- twoColumnRowsAvailable - rowsAvailableInColumns01;
- int numRowsUsedInColumns23 =
- twoColumnRowsAvailable - rowsAvailableInColumns23;
+ int numRowsUsedInColumns01 = twoColumnRowsAvailable - rowsAvailableInColumns01;
+ int numRowsUsedInColumns23 = twoColumnRowsAvailable - rowsAvailableInColumns23;
fillColumns(top2ColumnRow, numRowsUsedInColumns01, 0, 2);
- fillColumns(maxRows_ - numRowsUsedInColumns23, numRowsUsedInColumns23,
- 2, 2);
+ fillColumns(maxRows_ - numRowsUsedInColumns23, numRowsUsedInColumns23, 2, 2);
// Packs the 1 column variables.
- for (; ii < variables.size(); ++ii) {
- const sh::ShaderVariable &variable = variables[ii];
- ASSERT(1 == GetNumComponentsPerRow(variable.type));
- int numRows = GetNumRows(variable.type) * variable.elementCount();
+ for (; ii < variables->size(); ++ii)
+ {
+ const sh::ShaderVariable &variable = (*variables)[ii];
+ ASSERT(1 == GetTypePackingComponentsPerRow(variable.type));
+ int numRows = GetVariablePackingRows(variable);
int smallestColumn = -1;
- int smallestSize = maxRows_ + 1;
- int topRow = -1;
- for (int column = 0; column < kNumColumns; ++column) {
- int row = 0;
+ int smallestSize = maxRows_ + 1;
+ int topRow = -1;
+ for (int column = 0; column < kNumColumns; ++column)
+ {
+ int row = 0;
int size = 0;
- if (searchColumn(column, numRows, &row, &size)) {
- if (size < smallestSize) {
- smallestSize = size;
+ if (searchColumn(column, numRows, &row, &size))
+ {
+ if (size < smallestSize)
+ {
+ smallestSize = size;
smallestColumn = column;
- topRow = row;
+ topRow = row;
}
}
}
- if (smallestColumn < 0) {
+ if (smallestColumn < 0)
+ {
return false;
}
fillColumns(topRow, numRows, smallestColumn, 1);
}
- ASSERT(variables.size() == ii);
+ ASSERT(variables->size() == ii);
return true;
}
-// Instantiate all possible variable packings
-template bool VariablePacker::CheckVariablesWithinPackingLimits(unsigned int, const std::vector<sh::ShaderVariable> &);
-template bool VariablePacker::CheckVariablesWithinPackingLimits(unsigned int, const std::vector<sh::Attribute> &);
-template bool VariablePacker::CheckVariablesWithinPackingLimits(unsigned int, const std::vector<sh::Uniform> &);
-template bool VariablePacker::CheckVariablesWithinPackingLimits(unsigned int, const std::vector<sh::Varying> &);
+} // anonymous namespace
+
+int GetTypePackingComponentsPerRow(sh::GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT_MAT4:
+ case GL_FLOAT_MAT2:
+ case GL_FLOAT_MAT2x4:
+ case GL_FLOAT_MAT3x4:
+ case GL_FLOAT_MAT4x2:
+ case GL_FLOAT_MAT4x3:
+ case GL_FLOAT_VEC4:
+ case GL_INT_VEC4:
+ case GL_BOOL_VEC4:
+ case GL_UNSIGNED_INT_VEC4:
+ return 4;
+ case GL_FLOAT_MAT3:
+ case GL_FLOAT_MAT2x3:
+ case GL_FLOAT_MAT3x2:
+ case GL_FLOAT_VEC3:
+ case GL_INT_VEC3:
+ case GL_BOOL_VEC3:
+ case GL_UNSIGNED_INT_VEC3:
+ return 3;
+ case GL_FLOAT_VEC2:
+ case GL_INT_VEC2:
+ case GL_BOOL_VEC2:
+ case GL_UNSIGNED_INT_VEC2:
+ return 2;
+ default:
+ ASSERT(gl::VariableComponentCount(type) == 1);
+ return 1;
+ }
+}
+
+int GetTypePackingRows(sh::GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT_MAT4:
+ case GL_FLOAT_MAT2x4:
+ case GL_FLOAT_MAT3x4:
+ case GL_FLOAT_MAT4x3:
+ case GL_FLOAT_MAT4x2:
+ return 4;
+ case GL_FLOAT_MAT3:
+ case GL_FLOAT_MAT2x3:
+ case GL_FLOAT_MAT3x2:
+ return 3;
+ case GL_FLOAT_MAT2:
+ return 2;
+ default:
+ ASSERT(gl::VariableRowCount(type) == 1);
+ return 1;
+ }
+}
+
+template <typename T>
+bool CheckVariablesInPackingLimits(unsigned int maxVectors, const std::vector<T> &variables)
+{
+ VariablePacker packer;
+ std::vector<sh::ShaderVariable> expandedVariables;
+ for (const ShaderVariable &variable : variables)
+ {
+ ExpandVariable(variable, variable.name, &expandedVariables);
+ }
+ return packer.checkExpandedVariablesWithinPackingLimits(maxVectors, &expandedVariables);
+}
+
+template bool CheckVariablesInPackingLimits<ShaderVariable>(
+ unsigned int maxVectors,
+ const std::vector<ShaderVariable> &variables);
+template bool CheckVariablesInPackingLimits<Uniform>(unsigned int maxVectors,
+ const std::vector<Uniform> &variables);
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/VariablePacker.h b/src/3rdparty/angle/src/compiler/translator/VariablePacker.h
index 9c80eea618..36b2104cd0 100644
--- a/src/3rdparty/angle/src/compiler/translator/VariablePacker.h
+++ b/src/3rdparty/angle/src/compiler/translator/VariablePacker.h
@@ -3,39 +3,30 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
+// Check whether variables fit within packing limits according to the packing rules from the GLSL ES
+// 1.00.17 spec, Appendix A, section 7.
#ifndef COMPILER_TRANSLATOR_VARIABLEPACKER_H_
#define COMPILER_TRANSLATOR_VARIABLEPACKER_H_
#include <vector>
-#include "compiler/translator/VariableInfo.h"
-class VariablePacker {
- public:
- // Returns true if the passed in variables pack in maxVectors following
- // the packing rules from the GLSL 1.017 spec, Appendix A, section 7.
- template <typename VarT>
- bool CheckVariablesWithinPackingLimits(unsigned int maxVectors,
- const std::vector<VarT> &in_variables);
+#include <GLSLANG/ShaderLang.h>
- // Gets how many components in a row a data type takes.
- static int GetNumComponentsPerRow(sh::GLenum type);
+namespace sh
+{
- // Gets how many rows a data type takes.
- static int GetNumRows(sh::GLenum type);
+// Gets how many components in a row a data type takes.
+int GetTypePackingComponentsPerRow(sh::GLenum type);
- private:
- static const int kNumColumns = 4;
- static const unsigned kColumnMask = (1 << kNumColumns) - 1;
+// Gets how many rows a data type takes.
+int GetTypePackingRows(sh::GLenum type);
- unsigned makeColumnFlags(int column, int numComponentsPerRow);
- void fillColumns(int topRow, int numRows, int column, int numComponentsPerRow);
- bool searchColumn(int column, int numRows, int* destRow, int* destSize);
+// Returns true if the passed in variables pack in maxVectors.
+// T should be ShaderVariable or one of the subclasses of ShaderVariable.
+template <typename T>
+bool CheckVariablesInPackingLimits(unsigned int maxVectors, const std::vector<T> &variables);
- int topNonFullRow_;
- int bottomNonFullRow_;
- int maxRows_;
- std::vector<unsigned> rows_;
-};
+} // namespace sh
-#endif // COMPILER_TRANSLATOR_VARIABLEPACKER_H_
+#endif // COMPILER_TRANSLATOR_VARIABLEPACKER_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp b/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp
new file mode 100644
index 0000000000..1e79a60991
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp
@@ -0,0 +1,284 @@
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// VectorizeVectorScalarArithmetic.cpp: Turn some arithmetic operations that operate on a float
+// vector-scalar pair into vector-vector operations. This is done recursively. Some scalar binary
+// operations inside vector constructors are also turned into vector operations.
+//
+// This is targeted to work around a bug in NVIDIA OpenGL drivers that was reproducible on NVIDIA
+// driver version 387.92. It works around the most common occurrences of the bug.
+
+#include "compiler/translator/VectorizeVectorScalarArithmetic.h"
+
+#include <set>
+
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class VectorizeVectorScalarArithmeticTraverser : public TIntermTraverser
+{
+ public:
+ VectorizeVectorScalarArithmeticTraverser(TSymbolTable *symbolTable)
+ : TIntermTraverser(true, false, false, symbolTable), mReplaced(false)
+ {
+ }
+
+ bool didReplaceScalarsWithVectors() { return mReplaced; }
+ void nextIteration()
+ {
+ mReplaced = false;
+ mModifiedBlocks.clear();
+ }
+
+ protected:
+ bool visitBinary(Visit visit, TIntermBinary *node) override;
+ bool visitAggregate(Visit visit, TIntermAggregate *node) override;
+
+ private:
+ // These helpers should only be called from visitAggregate when visiting a constructor.
+ // argBinary is the only argument of the constructor.
+ void replaceMathInsideConstructor(TIntermAggregate *node, TIntermBinary *argBinary);
+ void replaceAssignInsideConstructor(const TIntermAggregate *node,
+ const TIntermBinary *argBinary);
+
+ static TIntermTyped *Vectorize(TIntermTyped *node,
+ TType vectorType,
+ TIntermTraverser::OriginalNode *originalNodeFate);
+
+ bool mReplaced;
+ std::set<const TIntermBlock *> mModifiedBlocks;
+};
+
+TIntermTyped *VectorizeVectorScalarArithmeticTraverser::Vectorize(
+ TIntermTyped *node,
+ TType vectorType,
+ TIntermTraverser::OriginalNode *originalNodeFate)
+{
+ ASSERT(node->isScalar());
+ vectorType.setQualifier(EvqTemporary);
+ TIntermSequence vectorConstructorArgs;
+ vectorConstructorArgs.push_back(node);
+ TIntermAggregate *vectorized =
+ TIntermAggregate::CreateConstructor(vectorType, &vectorConstructorArgs);
+ TIntermTyped *vectorizedFolded = vectorized->fold(nullptr);
+ if (originalNodeFate != nullptr)
+ {
+ if (vectorizedFolded != vectorized)
+ {
+ *originalNodeFate = OriginalNode::IS_DROPPED;
+ }
+ else
+ {
+ *originalNodeFate = OriginalNode::BECOMES_CHILD;
+ }
+ }
+ return vectorizedFolded;
+}
+
+bool VectorizeVectorScalarArithmeticTraverser::visitBinary(Visit /*visit*/, TIntermBinary *node)
+{
+ TIntermTyped *left = node->getLeft();
+ TIntermTyped *right = node->getRight();
+ ASSERT(left);
+ ASSERT(right);
+ switch (node->getOp())
+ {
+ case EOpAdd:
+ case EOpAddAssign:
+ // Only these specific ops are necessary to turn into vector ops.
+ break;
+ default:
+ return true;
+ }
+ if (node->getBasicType() != EbtFloat)
+ {
+ // Only float ops have reproduced the bug.
+ return true;
+ }
+ if (left->isScalar() && right->isVector())
+ {
+ ASSERT(!node->isAssignment());
+ ASSERT(!right->isArray());
+ OriginalNode originalNodeFate;
+ TIntermTyped *leftVectorized = Vectorize(left, right->getType(), &originalNodeFate);
+ queueReplacementWithParent(node, left, leftVectorized, originalNodeFate);
+ mReplaced = true;
+ // Don't replace more nodes in the same subtree on this traversal. However, nodes elsewhere
+ // in the tree may still be replaced.
+ return false;
+ }
+ else if (left->isVector() && right->isScalar())
+ {
+ OriginalNode originalNodeFate;
+ TIntermTyped *rightVectorized = Vectorize(right, left->getType(), &originalNodeFate);
+ queueReplacementWithParent(node, right, rightVectorized, originalNodeFate);
+ mReplaced = true;
+ // Don't replace more nodes in the same subtree on this traversal. However, nodes elsewhere
+ // in the tree may still be replaced.
+ return false;
+ }
+ return true;
+}
+
+void VectorizeVectorScalarArithmeticTraverser::replaceMathInsideConstructor(
+ TIntermAggregate *node,
+ TIntermBinary *argBinary)
+{
+ // Turn:
+ // a * b
+ // into:
+ // gvec(a) * gvec(b)
+
+ TIntermTyped *left = argBinary->getLeft();
+ TIntermTyped *right = argBinary->getRight();
+ ASSERT(left->isScalar() && right->isScalar());
+
+ TType leftVectorizedType = left->getType();
+ leftVectorizedType.setPrimarySize(static_cast<unsigned char>(node->getType().getNominalSize()));
+ TIntermTyped *leftVectorized = Vectorize(left, leftVectorizedType, nullptr);
+ TType rightVectorizedType = right->getType();
+ rightVectorizedType.setPrimarySize(
+ static_cast<unsigned char>(node->getType().getNominalSize()));
+ TIntermTyped *rightVectorized = Vectorize(right, rightVectorizedType, nullptr);
+
+ TIntermBinary *newArg = new TIntermBinary(argBinary->getOp(), leftVectorized, rightVectorized);
+ queueReplacementWithParent(node, argBinary, newArg, OriginalNode::IS_DROPPED);
+}
+
+void VectorizeVectorScalarArithmeticTraverser::replaceAssignInsideConstructor(
+ const TIntermAggregate *node,
+ const TIntermBinary *argBinary)
+{
+ // Turn:
+ // gvec(a *= b);
+ // into:
+ // // This is inserted into the parent block:
+ // gvec s0 = gvec(a);
+ //
+ // // This goes where the gvec constructor used to be:
+ // ((s0 *= b, a = s0.x), s0);
+
+ TIntermTyped *left = argBinary->getLeft();
+ TIntermTyped *right = argBinary->getRight();
+ ASSERT(left->isScalar() && right->isScalar());
+ ASSERT(!left->hasSideEffects());
+
+ TType vecType = node->getType();
+ vecType.setQualifier(EvqTemporary);
+
+ nextTemporaryId();
+ // gvec s0 = gvec(a);
+ // s0 is called "tempAssignmentTarget" below.
+ TIntermTyped *tempAssignmentTargetInitializer = Vectorize(left->deepCopy(), vecType, nullptr);
+ TIntermDeclaration *tempAssignmentTargetDeclaration =
+ createTempInitDeclaration(tempAssignmentTargetInitializer);
+
+ // s0 *= b
+ TOperator compoundAssignmentOp = argBinary->getOp();
+ if (compoundAssignmentOp == EOpMulAssign)
+ {
+ compoundAssignmentOp = EOpVectorTimesScalarAssign;
+ }
+ TIntermBinary *replacementCompoundAssignment =
+ new TIntermBinary(compoundAssignmentOp, createTempSymbol(vecType), right->deepCopy());
+
+ // s0.x
+ TVector<int> swizzleXOffset;
+ swizzleXOffset.push_back(0);
+ TIntermSwizzle *tempAssignmentTargetX =
+ new TIntermSwizzle(createTempSymbol(vecType), swizzleXOffset);
+ // a = s0.x
+ TIntermBinary *replacementAssignBackToTarget =
+ new TIntermBinary(EOpAssign, left->deepCopy(), tempAssignmentTargetX);
+
+ // s0 *= b, a = s0.x
+ TIntermBinary *replacementSequenceLeft =
+ new TIntermBinary(EOpComma, replacementCompoundAssignment, replacementAssignBackToTarget);
+ // (s0 *= b, a = s0.x), s0
+ TIntermBinary *replacementSequence =
+ new TIntermBinary(EOpComma, replacementSequenceLeft, createTempSymbol(vecType));
+
+ insertStatementInParentBlock(tempAssignmentTargetDeclaration);
+ queueReplacement(replacementSequence, OriginalNode::IS_DROPPED);
+}
+
+bool VectorizeVectorScalarArithmeticTraverser::visitAggregate(Visit /*visit*/,
+ TIntermAggregate *node)
+{
+ // Transform scalar binary expressions inside vector constructors.
+ if (!node->isConstructor() || !node->isVector() || node->getSequence()->size() != 1)
+ {
+ return true;
+ }
+ TIntermTyped *argument = node->getSequence()->back()->getAsTyped();
+ ASSERT(argument);
+ if (!argument->isScalar() || argument->getBasicType() != EbtFloat)
+ {
+ return true;
+ }
+ TIntermBinary *argBinary = argument->getAsBinaryNode();
+ if (!argBinary)
+ {
+ return true;
+ }
+
+ // Only specific ops are necessary to change.
+ switch (argBinary->getOp())
+ {
+ case EOpMul:
+ case EOpDiv:
+ {
+ replaceMathInsideConstructor(node, argBinary);
+ mReplaced = true;
+ // Don't replace more nodes in the same subtree on this traversal. However, nodes
+ // elsewhere in the tree may still be replaced.
+ return false;
+ }
+ case EOpMulAssign:
+ case EOpDivAssign:
+ {
+ // The case where the left side has side effects is too complicated to deal with, so we
+ // leave that be.
+ if (!argBinary->getLeft()->hasSideEffects())
+ {
+ const TIntermBlock *parentBlock = getParentBlock();
+ // We can't do more than one insertion to the same block on the same traversal.
+ if (mModifiedBlocks.find(parentBlock) == mModifiedBlocks.end())
+ {
+ replaceAssignInsideConstructor(node, argBinary);
+ mModifiedBlocks.insert(parentBlock);
+ mReplaced = true;
+ // Don't replace more nodes in the same subtree on this traversal.
+ // However, nodes elsewhere in the tree may still be replaced.
+ return false;
+ }
+ }
+ break;
+ }
+ default:
+ return true;
+ }
+ return true;
+}
+
+} // anonymous namespace
+
+void VectorizeVectorScalarArithmetic(TIntermBlock *root, TSymbolTable *symbolTable)
+{
+ VectorizeVectorScalarArithmeticTraverser traverser(symbolTable);
+ do
+ {
+ traverser.nextIteration();
+ root->traverse(&traverser);
+ traverser.updateTree();
+ } while (traverser.didReplaceScalarsWithVectors());
+}
+
+} // namespace sh \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.h b/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.h
new file mode 100644
index 0000000000..69f092e039
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/VectorizeVectorScalarArithmetic.h
@@ -0,0 +1,25 @@
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// VectorizeVectorScalarArithmetic.h: Turn some arithmetic operations that operate on a float
+// vector-scalar pair into vector-vector operations. This is done recursively. Some scalar binary
+// operations inside vector constructors are also turned into vector operations.
+//
+// This is targeted to work around a bug in NVIDIA OpenGL drivers that was reproducible on NVIDIA
+// driver version 387.92. It works around the most common occurrences of the bug.
+
+#ifndef COMPILER_TRANSLATOR_VECTORIZEVECTORSCALARARITHMETIC_H_
+#define COMPILER_TRANSLATOR_VECTORIZEVECTORSCALARARITHMETIC_H_
+
+namespace sh
+{
+
+class TIntermBlock;
+class TSymbolTable;
+
+void VectorizeVectorScalarArithmetic(TIntermBlock *root, TSymbolTable *symbolTable);
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_VECTORIZEVECTORSCALARARITHMETIC_H_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp
index c8718daa10..81688765b8 100644
--- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp
@@ -6,22 +6,40 @@
#include "compiler/translator/VersionGLSL.h"
+#include "angle_gl.h"
+
+namespace sh
+{
+
int ShaderOutputTypeToGLSLVersion(ShShaderOutput output)
{
switch (output)
{
- case SH_GLSL_130_OUTPUT: return GLSL_VERSION_130;
- case SH_GLSL_140_OUTPUT: return GLSL_VERSION_140;
- case SH_GLSL_150_CORE_OUTPUT: return GLSL_VERSION_150;
- case SH_GLSL_330_CORE_OUTPUT: return GLSL_VERSION_330;
- case SH_GLSL_400_CORE_OUTPUT: return GLSL_VERSION_400;
- case SH_GLSL_410_CORE_OUTPUT: return GLSL_VERSION_410;
- case SH_GLSL_420_CORE_OUTPUT: return GLSL_VERSION_420;
- case SH_GLSL_430_CORE_OUTPUT: return GLSL_VERSION_430;
- case SH_GLSL_440_CORE_OUTPUT: return GLSL_VERSION_440;
- case SH_GLSL_450_CORE_OUTPUT: return GLSL_VERSION_450;
- case SH_GLSL_COMPATIBILITY_OUTPUT: return GLSL_VERSION_110;
- default: UNREACHABLE(); return 0;
+ case SH_GLSL_130_OUTPUT:
+ return GLSL_VERSION_130;
+ case SH_GLSL_140_OUTPUT:
+ return GLSL_VERSION_140;
+ case SH_GLSL_150_CORE_OUTPUT:
+ return GLSL_VERSION_150;
+ case SH_GLSL_330_CORE_OUTPUT:
+ return GLSL_VERSION_330;
+ case SH_GLSL_400_CORE_OUTPUT:
+ return GLSL_VERSION_400;
+ case SH_GLSL_410_CORE_OUTPUT:
+ return GLSL_VERSION_410;
+ case SH_GLSL_420_CORE_OUTPUT:
+ return GLSL_VERSION_420;
+ case SH_GLSL_430_CORE_OUTPUT:
+ return GLSL_VERSION_430;
+ case SH_GLSL_440_CORE_OUTPUT:
+ return GLSL_VERSION_440;
+ case SH_GLSL_450_CORE_OUTPUT:
+ return GLSL_VERSION_450;
+ case SH_GLSL_COMPATIBILITY_OUTPUT:
+ return GLSL_VERSION_110;
+ default:
+ UNREACHABLE();
+ return 0;
}
}
@@ -42,9 +60,7 @@ int ShaderOutputTypeToGLSLVersion(ShShaderOutput output)
// GLSL 1.2 relaxed the restriction on arrays, section 5.8: "Variables that
// are built-in types, entire structures or arrays... are all l-values."
//
-TVersionGLSL::TVersionGLSL(sh::GLenum type,
- const TPragma &pragma,
- ShShaderOutput output)
+TVersionGLSL::TVersionGLSL(sh::GLenum type, const TPragma &pragma, ShShaderOutput output)
: TIntermTraverser(true, false, false)
{
mVersion = ShaderOutputTypeToGLSLVersion(output);
@@ -52,6 +68,10 @@ TVersionGLSL::TVersionGLSL(sh::GLenum type,
{
ensureVersionIsAtLeast(GLSL_VERSION_120);
}
+ if (type == GL_COMPUTE_SHADER)
+ {
+ ensureVersionIsAtLeast(GLSL_VERSION_430);
+ }
}
void TVersionGLSL::visitSymbol(TIntermSymbol *node)
@@ -62,75 +82,57 @@ void TVersionGLSL::visitSymbol(TIntermSymbol *node)
}
}
-bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate *node)
+bool TVersionGLSL::visitDeclaration(Visit, TIntermDeclaration *node)
+{
+ const TIntermSequence &sequence = *(node->getSequence());
+ if (sequence.front()->getAsTyped()->getType().isInvariant())
+ {
+ ensureVersionIsAtLeast(GLSL_VERSION_120);
+ }
+ return true;
+}
+
+bool TVersionGLSL::visitInvariantDeclaration(Visit, TIntermInvariantDeclaration *node)
{
- bool visitChildren = true;
+ ensureVersionIsAtLeast(GLSL_VERSION_120);
+ return true;
+}
- switch (node->getOp())
+bool TVersionGLSL::visitFunctionPrototype(Visit, TIntermFunctionPrototype *node)
+{
+ const TIntermSequence &params = *(node->getSequence());
+ for (TIntermSequence::const_iterator iter = params.begin(); iter != params.end(); ++iter)
{
- case EOpSequence:
- // We need to visit sequence children to get to global or inner scope.
- visitChildren = true;
- break;
- case EOpDeclaration:
+ const TIntermTyped *param = (*iter)->getAsTyped();
+ if (param->isArray())
{
- const TIntermSequence &sequence = *(node->getSequence());
- if (sequence.front()->getAsTyped()->getType().isInvariant())
+ TQualifier qualifier = param->getQualifier();
+ if ((qualifier == EvqOut) || (qualifier == EvqInOut))
{
ensureVersionIsAtLeast(GLSL_VERSION_120);
+ break;
}
- break;
}
- case EOpInvariantDeclaration:
- ensureVersionIsAtLeast(GLSL_VERSION_120);
- break;
- case EOpParameters:
- {
- const TIntermSequence &params = *(node->getSequence());
- for (TIntermSequence::const_iterator iter = params.begin();
- iter != params.end(); ++iter)
- {
- const TIntermTyped *param = (*iter)->getAsTyped();
- if (param->isArray())
- {
- TQualifier qualifier = param->getQualifier();
- if ((qualifier == EvqOut) || (qualifier == EvqInOut))
- {
- ensureVersionIsAtLeast(GLSL_VERSION_120);
- break;
- }
- }
- }
- // Fully processed. No need to visit children.
- visitChildren = false;
- break;
- }
- case EOpConstructMat2:
- case EOpConstructMat2x3:
- case EOpConstructMat2x4:
- case EOpConstructMat3x2:
- case EOpConstructMat3:
- case EOpConstructMat3x4:
- case EOpConstructMat4x2:
- case EOpConstructMat4x3:
- case EOpConstructMat4:
+ }
+ // Fully processed. No need to visit children.
+ return false;
+}
+
+bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate *node)
+{
+ if (node->getOp() == EOpConstruct && node->getType().isMatrix())
+ {
+ const TIntermSequence &sequence = *(node->getSequence());
+ if (sequence.size() == 1)
{
- const TIntermSequence &sequence = *(node->getSequence());
- if (sequence.size() == 1)
+ TIntermTyped *typed = sequence.front()->getAsTyped();
+ if (typed && typed->isMatrix())
{
- TIntermTyped *typed = sequence.front()->getAsTyped();
- if (typed && typed->isMatrix())
- {
- ensureVersionIsAtLeast(GLSL_VERSION_120);
- }
+ ensureVersionIsAtLeast(GLSL_VERSION_120);
}
- break;
}
- default:
- break;
}
-
- return visitChildren;
+ return true;
}
void TVersionGLSL::ensureVersionIsAtLeast(int version)
@@ -138,3 +140,4 @@ void TVersionGLSL::ensureVersionIsAtLeast(int version)
mVersion = std::max(version, mVersion);
}
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h
index c41069d42d..8b82eb9615 100644
--- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h
@@ -7,10 +7,13 @@
#ifndef COMPILER_TRANSLATOR_VERSIONGLSL_H_
#define COMPILER_TRANSLATOR_VERSIONGLSL_H_
-#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/Pragma.h"
+namespace sh
+{
+
static const int GLSL_VERSION_110 = 110;
static const int GLSL_VERSION_120 = 120;
static const int GLSL_VERSION_130 = 130;
@@ -56,8 +59,11 @@ class TVersionGLSL : public TIntermTraverser
// Else 110 is returned.
int getVersion() const { return mVersion; }
- void visitSymbol(TIntermSymbol *) override;
- bool visitAggregate(Visit, TIntermAggregate *) override;
+ void visitSymbol(TIntermSymbol *node) override;
+ bool visitAggregate(Visit, TIntermAggregate *node) override;
+ bool visitInvariantDeclaration(Visit, TIntermInvariantDeclaration *node) override;
+ bool visitFunctionPrototype(Visit, TIntermFunctionPrototype *node) override;
+ bool visitDeclaration(Visit, TIntermDeclaration *node) override;
private:
void ensureVersionIsAtLeast(int version);
@@ -65,4 +71,6 @@ class TVersionGLSL : public TIntermTraverser
int mVersion;
};
+} // namespace sh
+
#endif // COMPILER_TRANSLATOR_VERSIONGLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.cpp b/src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.cpp
new file mode 100644
index 0000000000..85a11c998d
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.cpp
@@ -0,0 +1,132 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// WrapSwitchStatementsInBlocks.cpp: Wrap switch statements in blocks and declare all switch-scoped
+// variables there to make the AST compatible with HLSL output.
+//
+// switch (init)
+// {
+// case 0:
+// float f;
+// default:
+// f = 1.0;
+// }
+//
+// becomes
+//
+// {
+// float f;
+// switch (init)
+// {
+// case 0:
+// default:
+// f = 1.0;
+// }
+// }
+
+#include "compiler/translator/WrapSwitchStatementsInBlocks.h"
+
+#include "compiler/translator/IntermNode.h"
+#include "compiler/translator/IntermTraverse.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class WrapSwitchStatementsInBlocksTraverser : public TIntermTraverser
+{
+ public:
+ WrapSwitchStatementsInBlocksTraverser() : TIntermTraverser(true, false, false), mDidWrap(false)
+ {
+ }
+
+ bool visitSwitch(Visit visit, TIntermSwitch *node) override;
+
+ bool didWrap() const { return mDidWrap; }
+
+ private:
+ bool mDidWrap;
+};
+
+bool WrapSwitchStatementsInBlocksTraverser::visitSwitch(Visit, TIntermSwitch *node)
+{
+ std::vector<TIntermDeclaration *> declarations;
+ TIntermSequence *statementList = node->getStatementList()->getSequence();
+ for (TIntermNode *statement : *statementList)
+ {
+ TIntermDeclaration *asDeclaration = statement->getAsDeclarationNode();
+ if (asDeclaration)
+ {
+ declarations.push_back(asDeclaration);
+ }
+ }
+ if (declarations.empty())
+ {
+ // We don't need to wrap the switch if it doesn't contain declarations as its direct
+ // descendants.
+ return true;
+ }
+
+ TIntermBlock *wrapperBlock = new TIntermBlock();
+ for (TIntermDeclaration *declaration : declarations)
+ {
+ // SeparateDeclarations should have already been run.
+ ASSERT(declaration->getSequence()->size() == 1);
+
+ TIntermDeclaration *declarationInBlock = new TIntermDeclaration();
+ TIntermSymbol *declaratorAsSymbol = declaration->getSequence()->at(0)->getAsSymbolNode();
+ if (declaratorAsSymbol)
+ {
+ // This is a simple declaration like: "float f;"
+ // Remove the declaration from inside the switch and put it in the wrapping block.
+ TIntermSequence emptyReplacement;
+ mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(
+ node->getStatementList(), declaration, emptyReplacement));
+
+ declarationInBlock->appendDeclarator(declaratorAsSymbol->deepCopy());
+ }
+ else
+ {
+ // This is an init declaration like: "float f = 0.0;"
+ // Change the init declaration inside the switch into an assignment and put a plain
+ // declaration in the wrapping block.
+ TIntermBinary *declaratorAsBinary =
+ declaration->getSequence()->at(0)->getAsBinaryNode();
+ ASSERT(declaratorAsBinary);
+
+ TIntermBinary *initAssignment = new TIntermBinary(
+ EOpAssign, declaratorAsBinary->getLeft(), declaratorAsBinary->getRight());
+
+ queueReplacementWithParent(node->getStatementList(), declaration, initAssignment,
+ OriginalNode::IS_DROPPED);
+
+ declarationInBlock->appendDeclarator(declaratorAsBinary->getLeft()->deepCopy());
+ }
+ wrapperBlock->appendStatement(declarationInBlock);
+ }
+
+ wrapperBlock->appendStatement(node);
+ queueReplacement(wrapperBlock, OriginalNode::BECOMES_CHILD);
+ mDidWrap = true;
+
+ // Should be fine to process multiple switch statements, even nesting ones in the same
+ // traversal.
+ return true;
+}
+
+} // anonymous namespace
+
+// Wrap switch statements in the AST into blocks when needed.
+bool WrapSwitchStatementsInBlocks(TIntermBlock *root)
+{
+ WrapSwitchStatementsInBlocksTraverser traverser;
+ root->traverse(&traverser);
+ traverser.updateTree();
+ return traverser.didWrap();
+}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.h b/src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.h
new file mode 100644
index 0000000000..bc0179926d
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/WrapSwitchStatementsInBlocks.h
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// WrapSwitchStatementsInBlocks.h: Wrap switch statements in blocks and declare all switch-scoped
+// variables there to make the AST compatible with HLSL output.
+
+#ifndef COMPILER_TRANSLATOR_WRAPSWITCHSTATEMENTSINBLOCKS_H_
+#define COMPILER_TRANSLATOR_WRAPSWITCHSTATEMENTSINBLOCKS_H_
+
+namespace sh
+{
+
+class TIntermBlock;
+
+// Wrap switch statements in the AST into blocks when needed. Returns true if the AST was changed.
+bool WrapSwitchStatementsInBlocks(TIntermBlock *root);
+
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_WRAPSWITCHSTATEMENTSINBLOCKS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/blocklayout.cpp b/src/3rdparty/angle/src/compiler/translator/blocklayout.cpp
index ba6322848e..fd8c450c20 100644
--- a/src/3rdparty/angle/src/compiler/translator/blocklayout.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/blocklayout.cpp
@@ -15,24 +15,105 @@
namespace sh
{
-BlockLayoutEncoder::BlockLayoutEncoder()
- : mCurrentOffset(0)
+namespace
{
+bool IsRowMajorLayout(const InterfaceBlockField &var)
+{
+ return var.isRowMajorLayout;
+}
+
+bool IsRowMajorLayout(const ShaderVariable &var)
+{
+ return false;
+}
+
+template <typename VarT>
+void GetUniformBlockStructMemberInfo(const std::vector<VarT> &fields,
+ const std::string &fieldName,
+ sh::BlockLayoutEncoder *encoder,
+ bool inRowMajorLayout,
+ BlockLayoutMap *blockInfoOut)
+{
+ encoder->enterAggregateType();
+ GetUniformBlockInfo(fields, fieldName, encoder, inRowMajorLayout, blockInfoOut);
+ encoder->exitAggregateType();
+}
+
+template <typename VarT>
+void GetUniformBlockStructArrayMemberInfo(const VarT &field,
+ unsigned int arrayNestingIndex,
+ const std::string &arrayName,
+ sh::BlockLayoutEncoder *encoder,
+ bool inRowMajorLayout,
+ BlockLayoutMap *blockInfoOut)
+{
+ // Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the
+ // innermost.
+ const unsigned int currentArraySize = field.getNestedArraySize(arrayNestingIndex);
+ for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement)
+ {
+ const std::string elementName = arrayName + ArrayString(arrayElement);
+ if (arrayNestingIndex + 1u < field.arraySizes.size())
+ {
+ GetUniformBlockStructArrayMemberInfo(field, arrayNestingIndex + 1u, elementName,
+ encoder, inRowMajorLayout, blockInfoOut);
+ }
+ else
+ {
+ GetUniformBlockStructMemberInfo(field.fields, elementName, encoder, inRowMajorLayout,
+ blockInfoOut);
+ }
+ }
}
-BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix)
+template <typename VarT>
+void GetUniformBlockArrayOfArraysMemberInfo(const VarT &field,
+ unsigned int arrayNestingIndex,
+ const std::string &arrayName,
+ sh::BlockLayoutEncoder *encoder,
+ bool inRowMajorLayout,
+ BlockLayoutMap *blockInfoOut)
+{
+ const unsigned int currentArraySize = field.getNestedArraySize(arrayNestingIndex);
+ for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement)
+ {
+ const std::string elementName = arrayName + ArrayString(arrayElement);
+ if (arrayNestingIndex + 2u < field.arraySizes.size())
+ {
+ GetUniformBlockArrayOfArraysMemberInfo(field, arrayNestingIndex + 1u, elementName,
+ encoder, inRowMajorLayout, blockInfoOut);
+ }
+ else
+ {
+ std::vector<unsigned int> innermostArraySize(
+ 1u, field.getNestedArraySize(arrayNestingIndex + 1u));
+ (*blockInfoOut)[elementName] =
+ encoder->encodeType(field.type, innermostArraySize, inRowMajorLayout);
+ }
+ }
+}
+
+} // anonymous namespace
+
+BlockLayoutEncoder::BlockLayoutEncoder() : mCurrentOffset(0)
+{
+}
+
+BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type,
+ const std::vector<unsigned int> &arraySizes,
+ bool isRowMajorMatrix)
{
int arrayStride;
int matrixStride;
- getBlockLayoutInfo(type, arraySize, isRowMajorMatrix, &arrayStride, &matrixStride);
+ getBlockLayoutInfo(type, arraySizes, isRowMajorMatrix, &arrayStride, &matrixStride);
const BlockMemberInfo memberInfo(static_cast<int>(mCurrentOffset * BytesPerComponent),
static_cast<int>(arrayStride * BytesPerComponent),
static_cast<int>(matrixStride * BytesPerComponent),
isRowMajorMatrix);
- advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride);
+ advanceOffset(type, arraySizes, isRowMajorMatrix, arrayStride, matrixStride);
return memberInfo;
}
@@ -68,48 +149,56 @@ void Std140BlockEncoder::exitAggregateType()
nextRegister();
}
-void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut)
+void Std140BlockEncoder::getBlockLayoutInfo(GLenum type,
+ const std::vector<unsigned int> &arraySizes,
+ bool isRowMajorMatrix,
+ int *arrayStrideOut,
+ int *matrixStrideOut)
{
// We assume we are only dealing with 4 byte components (no doubles or half-words currently)
ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent);
size_t baseAlignment = 0;
- int matrixStride = 0;
- int arrayStride = 0;
+ int matrixStride = 0;
+ int arrayStride = 0;
if (gl::IsMatrixType(type))
{
baseAlignment = ComponentsPerRegister;
- matrixStride = ComponentsPerRegister;
+ matrixStride = ComponentsPerRegister;
- if (arraySize > 0)
+ if (!arraySizes.empty())
{
const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
- arrayStride = ComponentsPerRegister * numRegisters;
+ arrayStride = ComponentsPerRegister * numRegisters;
}
}
- else if (arraySize > 0)
+ else if (!arraySizes.empty())
{
baseAlignment = ComponentsPerRegister;
- arrayStride = ComponentsPerRegister;
+ arrayStride = ComponentsPerRegister;
}
else
{
const int numComponents = gl::VariableComponentCount(type);
- baseAlignment = (numComponents == 3 ? 4u : static_cast<size_t>(numComponents));
+ baseAlignment = (numComponents == 3 ? 4u : static_cast<size_t>(numComponents));
}
mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment);
*matrixStrideOut = matrixStride;
- *arrayStrideOut = arrayStride;
+ *arrayStrideOut = arrayStride;
}
-void Std140BlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride)
+void Std140BlockEncoder::advanceOffset(GLenum type,
+ const std::vector<unsigned int> &arraySizes,
+ bool isRowMajorMatrix,
+ int arrayStride,
+ int matrixStride)
{
- if (arraySize > 0)
+ if (!arraySizes.empty())
{
- mCurrentOffset += arrayStride * arraySize;
+ mCurrentOffset += arrayStride * gl::ArraySizeProduct(arraySizes);
}
else if (gl::IsMatrixType(type))
{
@@ -123,4 +212,70 @@ void Std140BlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool
}
}
+template <typename VarT>
+void GetUniformBlockInfo(const std::vector<VarT> &fields,
+ const std::string &prefix,
+ sh::BlockLayoutEncoder *encoder,
+ bool inRowMajorLayout,
+ BlockLayoutMap *blockInfoOut)
+{
+ for (const VarT &field : fields)
+ {
+ // Skip samplers. On Vulkan we use this for the default uniform block, so samplers may be
+ // included.
+ if (gl::IsSamplerType(field.type))
+ {
+ continue;
+ }
+
+ const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
+
+ if (field.isStruct())
+ {
+ bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field));
+
+ if (field.isArray())
+ {
+ GetUniformBlockStructArrayMemberInfo(field, 0u, fieldName, encoder, rowMajorLayout,
+ blockInfoOut);
+ }
+ else
+ {
+ GetUniformBlockStructMemberInfo(field.fields, fieldName, encoder, rowMajorLayout,
+ blockInfoOut);
+ }
+ }
+ else if (field.isArrayOfArrays())
+ {
+ bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout);
+ GetUniformBlockArrayOfArraysMemberInfo(field, 0u, fieldName, encoder, isRowMajorMatrix,
+ blockInfoOut);
+ }
+ else
+ {
+ bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout);
+ (*blockInfoOut)[fieldName] =
+ encoder->encodeType(field.type, field.arraySizes, isRowMajorMatrix);
+ }
+ }
}
+
+template void GetUniformBlockInfo(const std::vector<InterfaceBlockField> &,
+ const std::string &,
+ sh::BlockLayoutEncoder *,
+ bool,
+ BlockLayoutMap *);
+
+template void GetUniformBlockInfo(const std::vector<Uniform> &,
+ const std::string &,
+ sh::BlockLayoutEncoder *,
+ bool,
+ BlockLayoutMap *);
+
+template void GetUniformBlockInfo(const std::vector<ShaderVariable> &,
+ const std::string &,
+ sh::BlockLayoutEncoder *,
+ bool,
+ BlockLayoutMap *);
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/blocklayout.h b/src/3rdparty/angle/src/compiler/translator/blocklayout.h
index dd5fe07376..2b7acf4e60 100644
--- a/src/3rdparty/angle/src/compiler/translator/blocklayout.h
+++ b/src/3rdparty/angle/src/compiler/translator/blocklayout.h
@@ -11,6 +11,7 @@
#define COMMON_BLOCKLAYOUT_H_
#include <cstddef>
+#include <map>
#include <vector>
#include "angle_gl.h"
@@ -24,42 +25,64 @@ struct Uniform;
struct Varying;
struct InterfaceBlock;
-struct COMPILER_EXPORT BlockMemberInfo
+struct BlockMemberInfo
{
- BlockMemberInfo() : offset(-1), arrayStride(-1), matrixStride(-1), isRowMajorMatrix(false) {}
+ BlockMemberInfo()
+ : offset(-1),
+ arrayStride(-1),
+ matrixStride(-1),
+ isRowMajorMatrix(false),
+ topLevelArrayStride(-1)
+ {
+ }
BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix)
: offset(offset),
arrayStride(arrayStride),
matrixStride(matrixStride),
- isRowMajorMatrix(isRowMajorMatrix)
- {}
+ isRowMajorMatrix(isRowMajorMatrix),
+ topLevelArrayStride(-1)
+ {
+ }
- static BlockMemberInfo getDefaultBlockInfo()
+ BlockMemberInfo(int offset,
+ int arrayStride,
+ int matrixStride,
+ bool isRowMajorMatrix,
+ int topLevelArrayStride)
+ : offset(offset),
+ arrayStride(arrayStride),
+ matrixStride(matrixStride),
+ isRowMajorMatrix(isRowMajorMatrix),
+ topLevelArrayStride(topLevelArrayStride)
{
- return BlockMemberInfo(-1, -1, -1, false);
}
+ static BlockMemberInfo getDefaultBlockInfo() { return BlockMemberInfo(-1, -1, -1, false, -1); }
+
int offset;
int arrayStride;
int matrixStride;
bool isRowMajorMatrix;
+ int topLevelArrayStride; // Only used for shader storage block members.
};
-class COMPILER_EXPORT BlockLayoutEncoder
+class BlockLayoutEncoder
{
public:
BlockLayoutEncoder();
virtual ~BlockLayoutEncoder() {}
- BlockMemberInfo encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix);
+ BlockMemberInfo encodeType(GLenum type,
+ const std::vector<unsigned int> &arraySizes,
+ bool isRowMajorMatrix);
size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; }
virtual void enterAggregateType() = 0;
- virtual void exitAggregateType() = 0;
+ virtual void exitAggregateType() = 0;
- static const size_t BytesPerComponent = 4u;
+ static const size_t BytesPerComponent = 4u;
static const unsigned int ComponentsPerRegister = 4u;
static size_t getBlockRegister(const BlockMemberInfo &info);
@@ -70,14 +93,22 @@ class COMPILER_EXPORT BlockLayoutEncoder
void nextRegister();
- virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) = 0;
- virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) = 0;
+ virtual void getBlockLayoutInfo(GLenum type,
+ const std::vector<unsigned int> &arraySizes,
+ bool isRowMajorMatrix,
+ int *arrayStrideOut,
+ int *matrixStrideOut) = 0;
+ virtual void advanceOffset(GLenum type,
+ const std::vector<unsigned int> &arraySizes,
+ bool isRowMajorMatrix,
+ int arrayStride,
+ int matrixStride) = 0;
};
// Block layout according to the std140 block layout
// See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification
-class COMPILER_EXPORT Std140BlockEncoder : public BlockLayoutEncoder
+class Std140BlockEncoder : public BlockLayoutEncoder
{
public:
Std140BlockEncoder();
@@ -87,17 +118,27 @@ class COMPILER_EXPORT Std140BlockEncoder : public BlockLayoutEncoder
protected:
void getBlockLayoutInfo(GLenum type,
- unsigned int arraySize,
+ const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix,
int *arrayStrideOut,
int *matrixStrideOut) override;
void advanceOffset(GLenum type,
- unsigned int arraySize,
+ const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix,
int arrayStride,
int matrixStride) override;
};
-}
+using BlockLayoutMap = std::map<std::string, BlockMemberInfo>;
+
+// Only valid to call with ShaderVariable, InterfaceBlockField and Uniform.
+template <typename VarT>
+void GetUniformBlockInfo(const std::vector<VarT> &fields,
+ const std::string &prefix,
+ sh::BlockLayoutEncoder *encoder,
+ bool inRowMajorLayout,
+ BlockLayoutMap *blockLayoutMap);
+
+} // namespace sh
-#endif // COMMON_BLOCKLAYOUT_H_
+#endif // COMMON_BLOCKLAYOUT_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp
index 43119248eb..867821f1ea 100644
--- a/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp
@@ -15,9 +15,8 @@
namespace sh
{
-HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy)
- : mEncoderStrategy(strategy),
- mTransposeMatrices(false)
+HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy, bool transposeMatrices)
+ : mEncoderStrategy(strategy), mTransposeMatrices(transposeMatrices)
{
}
@@ -30,7 +29,11 @@ void HLSLBlockEncoder::exitAggregateType()
{
}
-void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut)
+void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn,
+ const std::vector<unsigned int> &arraySizes,
+ bool isRowMajorMatrix,
+ int *arrayStrideOut,
+ int *matrixStrideOut)
{
GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn);
@@ -38,14 +41,12 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn, unsigned int arraySize,
ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent);
int matrixStride = 0;
- int arrayStride = 0;
+ int arrayStride = 0;
// if variables are not to be packed, or we're about to
// pack a matrix or array, skip to the start of the next
// register
- if (!isPacked() ||
- gl::IsMatrixType(type) ||
- arraySize > 0)
+ if (!isPacked() || gl::IsMatrixType(type) || !arraySizes.empty())
{
nextRegister();
}
@@ -54,13 +55,13 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn, unsigned int arraySize,
{
matrixStride = ComponentsPerRegister;
- if (arraySize > 0)
+ if (!arraySizes.empty())
{
const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
- arrayStride = ComponentsPerRegister * numRegisters;
+ arrayStride = ComponentsPerRegister * numRegisters;
}
}
- else if (arraySize > 0)
+ else if (!arraySizes.empty())
{
arrayStride = ComponentsPerRegister;
}
@@ -74,22 +75,26 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn, unsigned int arraySize,
}
*matrixStrideOut = matrixStride;
- *arrayStrideOut = arrayStride;
+ *arrayStrideOut = arrayStride;
}
-void HLSLBlockEncoder::advanceOffset(GLenum typeIn, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride)
+void HLSLBlockEncoder::advanceOffset(GLenum typeIn,
+ const std::vector<unsigned int> &arraySizes,
+ bool isRowMajorMatrix,
+ int arrayStride,
+ int matrixStride)
{
GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn);
- if (arraySize > 0)
+ if (!arraySizes.empty())
{
- mCurrentOffset += arrayStride * (arraySize - 1);
+ mCurrentOffset += arrayStride * (gl::ArraySizeProduct(arraySizes) - 1);
}
if (gl::IsMatrixType(type))
{
ASSERT(matrixStride == ComponentsPerRegister);
- const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
+ const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
const int numComponents = gl::MatrixComponentCount(type, isRowMajorMatrix);
mCurrentOffset += ComponentsPerRegister * (numRegisters - 1);
mCurrentOffset += numComponents;
@@ -109,7 +114,8 @@ void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters)
mCurrentOffset += (numRegisters * ComponentsPerRegister);
}
-HLSLBlockEncoder::HLSLBlockEncoderStrategy HLSLBlockEncoder::GetStrategyFor(ShShaderOutput outputType)
+HLSLBlockEncoder::HLSLBlockEncoderStrategy HLSLBlockEncoder::GetStrategyFor(
+ ShShaderOutput outputType)
{
switch (outputType)
{
@@ -129,7 +135,7 @@ void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *
{
if (variable.isStruct())
{
- for (size_t arrayElement = 0; arrayElement < variable.elementCount(); arrayElement++)
+ for (size_t arrayElement = 0; arrayElement < variable.getArraySizeProduct(); arrayElement++)
{
encoder->enterAggregateType();
@@ -144,28 +150,17 @@ void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *
else
{
// We operate only on varyings and uniforms, which do not have matrix layout qualifiers
- encoder->encodeType(variable.type, variable.arraySize, false);
+ encoder->encodeType(variable.type, variable.arraySizes, false);
}
}
-unsigned int HLSLVariableRegisterCount(const Varying &variable, bool transposeMatrices)
-{
- HLSLBlockEncoder encoder(HLSLBlockEncoder::ENCODE_PACKED);
- encoder.setTransposeMatrices(transposeMatrices);
- HLSLVariableRegisterCount(variable, &encoder);
-
- const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
- return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) / registerBytes);
-}
-
unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType)
{
- HLSLBlockEncoder encoder(HLSLBlockEncoder::GetStrategyFor(outputType));
- encoder.setTransposeMatrices(true);
+ HLSLBlockEncoder encoder(HLSLBlockEncoder::GetStrategyFor(outputType), true);
HLSLVariableRegisterCount(variable, &encoder);
const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
- return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) / registerBytes);
-}
-
+ return static_cast<unsigned int>(rx::roundUp<size_t>(encoder.getBlockSize(), registerBytes) /
+ registerBytes);
}
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h b/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h
index c61cb1ae57..8f4a51a906 100644
--- a/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h
@@ -24,7 +24,7 @@ namespace sh
// The strategy should be ENCODE_LOOSE for D3D9 constant blocks, and ENCODE_PACKED
// for everything else (D3D10+ constant blocks and all attributes/varyings).
-class COMPILER_EXPORT HLSLBlockEncoder : public BlockLayoutEncoder
+class HLSLBlockEncoder : public BlockLayoutEncoder
{
public:
enum HLSLBlockEncoderStrategy
@@ -33,30 +33,36 @@ class COMPILER_EXPORT HLSLBlockEncoder : public BlockLayoutEncoder
ENCODE_LOOSE
};
- HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy);
+ HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy, bool transposeMatrices);
- virtual void enterAggregateType();
- virtual void exitAggregateType();
+ void enterAggregateType() override;
+ void exitAggregateType() override;
void skipRegisters(unsigned int numRegisters);
bool isPacked() const { return mEncoderStrategy == ENCODE_PACKED; }
- void setTransposeMatrices(bool enabled) { mTransposeMatrices = enabled; }
static HLSLBlockEncoderStrategy GetStrategyFor(ShShaderOutput outputType);
protected:
- virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut);
- virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride);
+ void getBlockLayoutInfo(GLenum type,
+ const std::vector<unsigned int> &arraySizes,
+ bool isRowMajorMatrix,
+ int *arrayStrideOut,
+ int *matrixStrideOut) override;
+ void advanceOffset(GLenum type,
+ const std::vector<unsigned int> &arraySizes,
+ bool isRowMajorMatrix,
+ int arrayStride,
+ int matrixStride) override;
HLSLBlockEncoderStrategy mEncoderStrategy;
bool mTransposeMatrices;
};
-// This method returns the number of used registers for a ShaderVariable. It is dependent on the HLSLBlockEncoder
-// class to count the number of used registers in a struct (which are individually packed according to the same rules).
-COMPILER_EXPORT unsigned int HLSLVariableRegisterCount(const Varying &variable, bool transposeMatrices);
-COMPILER_EXPORT unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType);
-
+// This method returns the number of used registers for a ShaderVariable. It is dependent on the
+// HLSLBlockEncoder class to count the number of used registers in a struct (which are individually
+// packed according to the same rules).
+unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType);
}
-#endif // COMMON_BLOCKLAYOUTHLSL_H_
+#endif // COMMON_BLOCKLAYOUTHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/compilerdebug.cpp b/src/3rdparty/angle/src/compiler/translator/compilerdebug.cpp
deleted file mode 100644
index 10cbe43b8d..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/compilerdebug.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// debug.cpp: Debugging utilities.
-
-#include "compiler/translator/compilerdebug.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-
-#include "compiler/translator/InitializeParseContext.h"
-#include "compiler/translator/ParseContext.h"
-
-#ifdef TRACE_ENABLED
-static const int kTraceBufferLen = 1024;
-
-extern "C" {
-void Trace(const char *format, ...) {
- if (!format) return;
-
- TParseContext* parseContext = GetGlobalParseContext();
- if (parseContext) {
- char buf[kTraceBufferLen];
- va_list args;
- va_start(args, format);
- vsnprintf(buf, kTraceBufferLen, format, args);
- va_end(args);
-
- parseContext->trace(buf);
- }
-}
-} // extern "C"
-#endif // TRACE_ENABLED
-
diff --git a/src/3rdparty/angle/src/compiler/translator/compilerdebug.h b/src/3rdparty/angle/src/compiler/translator/compilerdebug.h
deleted file mode 100644
index 84a12ad2f8..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/compilerdebug.h
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// debug.h: Debugging utilities.
-
-#ifndef COMPILER_TRANSLATOR_COMPILERDEBUG_H_
-#define COMPILER_TRANSLATOR_COMPILERDEBUG_H_
-
-#include <assert.h>
-
-#ifdef _DEBUG
-#define TRACE_ENABLED // define to enable debug message tracing
-#endif // _DEBUG
-
-// Outputs text to the debug log
-#ifdef TRACE_ENABLED
-
-#ifdef __cplusplus
-extern "C" {
-#endif // __cplusplus
-void Trace(const char* format, ...);
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-#else // TRACE_ENABLED
-
-#define Trace(...) ((void)0)
-
-#endif // TRACE_ENABLED
-
-// A macro asserting a condition and outputting failures to the debug log
-#define ASSERT(expression) do { \
- if(!(expression)) \
- Trace("Assert failed: %s(%d): "#expression"\n", __FUNCTION__, __LINE__); \
- assert(expression); \
-} while(0)
-
-#define UNIMPLEMENTED() do { \
- Trace("Unimplemented invoked: %s(%d)\n", __FUNCTION__, __LINE__); \
- assert(false); \
-} while(0)
-
-#define UNREACHABLE() do { \
- Trace("Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__); \
- assert(false); \
-} while(0)
-
-#endif // COMPILER_TRANSLATOR_COMPILERDEBUG_H_
-
diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.cpp b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.cpp
deleted file mode 100644
index 4dee0dbd2e..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/translator/depgraph/DependencyGraph.h"
-#include "compiler/translator/depgraph/DependencyGraphBuilder.h"
-
-TDependencyGraph::TDependencyGraph(TIntermNode* intermNode)
-{
- TDependencyGraphBuilder::build(intermNode, this);
-}
-
-TDependencyGraph::~TDependencyGraph()
-{
- for (TGraphNodeVector::const_iterator iter = mAllNodes.begin(); iter != mAllNodes.end(); ++iter)
- {
- TGraphNode* node = *iter;
- delete node;
- }
-}
-
-TGraphArgument* TDependencyGraph::createArgument(TIntermAggregate* intermFunctionCall,
- int argumentNumber)
-{
- TGraphArgument* argument = new TGraphArgument(intermFunctionCall, argumentNumber);
- mAllNodes.push_back(argument);
- return argument;
-}
-
-TGraphFunctionCall* TDependencyGraph::createFunctionCall(TIntermAggregate* intermFunctionCall)
-{
- TGraphFunctionCall* functionCall = new TGraphFunctionCall(intermFunctionCall);
- mAllNodes.push_back(functionCall);
- if (functionCall->getIntermFunctionCall()->isUserDefined())
- mUserDefinedFunctionCalls.push_back(functionCall);
- return functionCall;
-}
-
-TGraphSymbol* TDependencyGraph::getOrCreateSymbol(TIntermSymbol* intermSymbol)
-{
- TSymbolIdMap::const_iterator iter = mSymbolIdMap.find(intermSymbol->getId());
-
- TGraphSymbol* symbol = NULL;
-
- if (iter != mSymbolIdMap.end()) {
- TSymbolIdPair pair = *iter;
- symbol = pair.second;
- } else {
- symbol = new TGraphSymbol(intermSymbol);
- mAllNodes.push_back(symbol);
-
- TSymbolIdPair pair(intermSymbol->getId(), symbol);
- mSymbolIdMap.insert(pair);
-
- // We save all sampler symbols in a collection, so we can start graph traversals from them quickly.
- if (IsSampler(intermSymbol->getBasicType()))
- mSamplerSymbols.push_back(symbol);
- }
-
- return symbol;
-}
-
-TGraphSelection* TDependencyGraph::createSelection(TIntermSelection* intermSelection)
-{
- TGraphSelection* selection = new TGraphSelection(intermSelection);
- mAllNodes.push_back(selection);
- return selection;
-}
-
-TGraphLoop* TDependencyGraph::createLoop(TIntermLoop* intermLoop)
-{
- TGraphLoop* loop = new TGraphLoop(intermLoop);
- mAllNodes.push_back(loop);
- return loop;
-}
-
-TGraphLogicalOp* TDependencyGraph::createLogicalOp(TIntermBinary* intermLogicalOp)
-{
- TGraphLogicalOp* logicalOp = new TGraphLogicalOp(intermLogicalOp);
- mAllNodes.push_back(logicalOp);
- return logicalOp;
-}
-
-const char* TGraphLogicalOp::getOpString() const
-{
- const char* opString = NULL;
- switch (getIntermLogicalOp()->getOp()) {
- case EOpLogicalAnd: opString = "and"; break;
- case EOpLogicalOr: opString = "or"; break;
- default: opString = "unknown"; break;
- }
- return opString;
-}
diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h
deleted file mode 100644
index 2f7f7b9ab8..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h
+++ /dev/null
@@ -1,199 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPH_H_
-#define COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPH_H_
-
-#include "compiler/translator/IntermNode.h"
-
-#include <set>
-#include <stack>
-
-class TGraphNode;
-class TGraphParentNode;
-class TGraphArgument;
-class TGraphFunctionCall;
-class TGraphSymbol;
-class TGraphSelection;
-class TGraphLoop;
-class TGraphLogicalOp;
-class TDependencyGraphTraverser;
-class TDependencyGraphOutput;
-
-typedef std::set<TGraphNode*> TGraphNodeSet;
-typedef std::vector<TGraphNode*> TGraphNodeVector;
-typedef std::vector<TGraphSymbol*> TGraphSymbolVector;
-typedef std::vector<TGraphFunctionCall*> TFunctionCallVector;
-
-//
-// Base class for all dependency graph nodes.
-//
-class TGraphNode {
-public:
- TGraphNode(TIntermNode* node) : intermNode(node) {}
- virtual ~TGraphNode() {}
- virtual void traverse(TDependencyGraphTraverser* graphTraverser);
-protected:
- TIntermNode* intermNode;
-};
-
-//
-// Base class for dependency graph nodes that may have children.
-//
-class TGraphParentNode : public TGraphNode {
-public:
- TGraphParentNode(TIntermNode* node) : TGraphNode(node) {}
- ~TGraphParentNode() override {}
- void addDependentNode(TGraphNode* node) { if (node != this) mDependentNodes.insert(node); }
- void traverse(TDependencyGraphTraverser *graphTraverser) override;
-
-private:
- TGraphNodeSet mDependentNodes;
-};
-
-//
-// Handle function call arguments.
-//
-class TGraphArgument : public TGraphParentNode {
-public:
- TGraphArgument(TIntermAggregate* intermFunctionCall, int argumentNumber)
- : TGraphParentNode(intermFunctionCall)
- , mArgumentNumber(argumentNumber) {}
- ~TGraphArgument() override {}
- const TIntermAggregate* getIntermFunctionCall() const { return intermNode->getAsAggregate(); }
- int getArgumentNumber() const { return mArgumentNumber; }
- void traverse(TDependencyGraphTraverser *graphTraverser) override;
-
-private:
- int mArgumentNumber;
-};
-
-//
-// Handle function calls.
-//
-class TGraphFunctionCall : public TGraphParentNode {
-public:
- TGraphFunctionCall(TIntermAggregate* intermFunctionCall)
- : TGraphParentNode(intermFunctionCall) {}
- ~TGraphFunctionCall() override {}
- const TIntermAggregate* getIntermFunctionCall() const { return intermNode->getAsAggregate(); }
- void traverse(TDependencyGraphTraverser *graphTraverser) override;
-};
-
-//
-// Handle symbols.
-//
-class TGraphSymbol : public TGraphParentNode {
-public:
- TGraphSymbol(TIntermSymbol* intermSymbol) : TGraphParentNode(intermSymbol) {}
- ~TGraphSymbol() override {}
- const TIntermSymbol* getIntermSymbol() const { return intermNode->getAsSymbolNode(); }
- void traverse(TDependencyGraphTraverser *graphTraverser) override;
-};
-
-//
-// Handle if statements and ternary operators.
-//
-class TGraphSelection : public TGraphNode {
-public:
- TGraphSelection(TIntermSelection* intermSelection) : TGraphNode(intermSelection) {}
- ~TGraphSelection() override {}
- const TIntermSelection* getIntermSelection() const { return intermNode->getAsSelectionNode(); }
- void traverse(TDependencyGraphTraverser *graphTraverser) override;
-};
-
-//
-// Handle for, do-while, and while loops.
-//
-class TGraphLoop : public TGraphNode {
-public:
- TGraphLoop(TIntermLoop* intermLoop) : TGraphNode(intermLoop) {}
- ~TGraphLoop() override {}
- const TIntermLoop* getIntermLoop() const { return intermNode->getAsLoopNode(); }
- void traverse(TDependencyGraphTraverser *graphTraverser) override;
-};
-
-//
-// Handle logical and, or.
-//
-class TGraphLogicalOp : public TGraphNode {
-public:
- TGraphLogicalOp(TIntermBinary* intermLogicalOp) : TGraphNode(intermLogicalOp) {}
- ~TGraphLogicalOp() override {}
- const TIntermBinary* getIntermLogicalOp() const { return intermNode->getAsBinaryNode(); }
- const char* getOpString() const;
- void traverse(TDependencyGraphTraverser *graphTraverser) override;
-};
-
-//
-// A dependency graph of symbols, function calls, conditions etc.
-//
-// This class provides an interface to the entry points of the dependency graph.
-//
-// Dependency graph nodes should be created by using one of the provided "create..." methods.
-// This class (and nobody else) manages the memory of the created nodes.
-// Nodes may not be removed after being added, so all created nodes will exist while the
-// TDependencyGraph instance exists.
-//
-class TDependencyGraph {
-public:
- TDependencyGraph(TIntermNode* intermNode);
- ~TDependencyGraph();
- const TGraphNodeVector &allNodes() const { return mAllNodes; }
- const TGraphSymbolVector &samplerSymbols() const { return mSamplerSymbols; }
- const TFunctionCallVector &userDefinedFunctionCalls() const
- {
- return mUserDefinedFunctionCalls;
- }
-
- TGraphArgument* createArgument(TIntermAggregate* intermFunctionCall, int argumentNumber);
- TGraphFunctionCall* createFunctionCall(TIntermAggregate* intermFunctionCall);
- TGraphSymbol* getOrCreateSymbol(TIntermSymbol* intermSymbol);
- TGraphSelection* createSelection(TIntermSelection* intermSelection);
- TGraphLoop* createLoop(TIntermLoop* intermLoop);
- TGraphLogicalOp* createLogicalOp(TIntermBinary* intermLogicalOp);
-private:
- typedef TMap<int, TGraphSymbol*> TSymbolIdMap;
- typedef std::pair<int, TGraphSymbol*> TSymbolIdPair;
-
- TGraphNodeVector mAllNodes;
- TGraphSymbolVector mSamplerSymbols;
- TFunctionCallVector mUserDefinedFunctionCalls;
- TSymbolIdMap mSymbolIdMap;
-};
-
-//
-// For traversing the dependency graph. Users should derive from this,
-// put their traversal specific data in it, and then pass it to a
-// traverse method.
-//
-// When using this, just fill in the methods for nodes you want visited.
-//
-class TDependencyGraphTraverser : angle::NonCopyable {
-public:
- TDependencyGraphTraverser() : mDepth(0) {}
- virtual ~TDependencyGraphTraverser() {}
-
- virtual void visitSymbol(TGraphSymbol* symbol) {};
- virtual void visitArgument(TGraphArgument* selection) {};
- virtual void visitFunctionCall(TGraphFunctionCall* functionCall) {};
- virtual void visitSelection(TGraphSelection* selection) {};
- virtual void visitLoop(TGraphLoop* loop) {};
- virtual void visitLogicalOp(TGraphLogicalOp* logicalOp) {};
-
- int getDepth() const { return mDepth; }
- void incrementDepth() { ++mDepth; }
- void decrementDepth() { --mDepth; }
-
- void clearVisited() { mVisited.clear(); }
- void markVisited(TGraphNode* node) { mVisited.insert(node); }
- bool isVisited(TGraphNode* node) const { return mVisited.find(node) != mVisited.end(); }
-private:
- int mDepth;
- TGraphNodeSet mVisited;
-};
-
-#endif // COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPH_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp
deleted file mode 100644
index 1aeb822d51..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp
+++ /dev/null
@@ -1,255 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/translator/depgraph/DependencyGraphBuilder.h"
-
-void TDependencyGraphBuilder::build(TIntermNode *node, TDependencyGraph *graph)
-{
- TDependencyGraphBuilder builder(graph);
- builder.build(node);
-}
-
-bool TDependencyGraphBuilder::visitAggregate(
- Visit visit, TIntermAggregate *intermAggregate)
-{
- switch (intermAggregate->getOp())
- {
- case EOpFunction:
- visitFunctionDefinition(intermAggregate);
- break;
- case EOpFunctionCall:
- visitFunctionCall(intermAggregate);
- break;
- default:
- visitAggregateChildren(intermAggregate);
- break;
- }
- return false;
-}
-
-void TDependencyGraphBuilder::visitFunctionDefinition(
- TIntermAggregate *intermAggregate)
-{
- // Currently, we do not support user defined functions.
- if (intermAggregate->getName() != "main(")
- return;
-
- visitAggregateChildren(intermAggregate);
-}
-
-// Takes an expression like "f(x)" and creates a dependency graph like
-// "x -> argument 0 -> function call".
-void TDependencyGraphBuilder::visitFunctionCall(
- TIntermAggregate *intermFunctionCall)
-{
- TGraphFunctionCall *functionCall =
- mGraph->createFunctionCall(intermFunctionCall);
-
- // Run through the function call arguments.
- int argumentNumber = 0;
- TIntermSequence *intermArguments = intermFunctionCall->getSequence();
- for (TIntermSequence::const_iterator iter = intermArguments->begin();
- iter != intermArguments->end();
- ++iter, ++argumentNumber)
- {
- TNodeSetMaintainer nodeSetMaintainer(this);
-
- TIntermNode *intermArgument = *iter;
- intermArgument->traverse(this);
-
- if (TParentNodeSet *argumentNodes = mNodeSets.getTopSet())
- {
- TGraphArgument *argument = mGraph->createArgument(
- intermFunctionCall, argumentNumber);
- connectMultipleNodesToSingleNode(argumentNodes, argument);
- argument->addDependentNode(functionCall);
- }
- }
-
- // Push the leftmost symbol of this function call into the current set of
- // dependent symbols to represent the result of this function call.
- // Thus, an expression like "y = f(x)" will yield a dependency graph like
- // "x -> argument 0 -> function call -> y".
- // This line essentially passes the function call node back up to an earlier
- // visitAssignment call, which will create the connection "function call -> y".
- mNodeSets.insertIntoTopSet(functionCall);
-}
-
-void TDependencyGraphBuilder::visitAggregateChildren(
- TIntermAggregate *intermAggregate)
-{
- TIntermSequence *sequence = intermAggregate->getSequence();
- for (TIntermSequence::const_iterator iter = sequence->begin();
- iter != sequence->end(); ++iter)
- {
- TIntermNode *intermChild = *iter;
- intermChild->traverse(this);
- }
-}
-
-void TDependencyGraphBuilder::visitSymbol(TIntermSymbol *intermSymbol)
-{
- // Push this symbol into the set of dependent symbols for the current
- // assignment or condition that we are traversing.
- TGraphSymbol *symbol = mGraph->getOrCreateSymbol(intermSymbol);
- mNodeSets.insertIntoTopSet(symbol);
-
- // If this symbol is the current leftmost symbol under an assignment, replace
- // the previous leftmost symbol with this symbol.
- if (!mLeftmostSymbols.empty() && mLeftmostSymbols.top() != &mRightSubtree)
- {
- mLeftmostSymbols.pop();
- mLeftmostSymbols.push(symbol);
- }
-}
-
-bool TDependencyGraphBuilder::visitBinary(Visit visit, TIntermBinary *intermBinary)
-{
- TOperator op = intermBinary->getOp();
- if (op == EOpInitialize || intermBinary->isAssignment())
- visitAssignment(intermBinary);
- else if (op == EOpLogicalAnd || op == EOpLogicalOr)
- visitLogicalOp(intermBinary);
- else
- visitBinaryChildren(intermBinary);
-
- return false;
-}
-
-void TDependencyGraphBuilder::visitAssignment(TIntermBinary *intermAssignment)
-{
- TIntermTyped *intermLeft = intermAssignment->getLeft();
- if (!intermLeft)
- return;
-
- TGraphSymbol *leftmostSymbol = NULL;
-
- {
- TNodeSetMaintainer nodeSetMaintainer(this);
-
- {
- TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mLeftSubtree);
- intermLeft->traverse(this);
- leftmostSymbol = mLeftmostSymbols.top();
-
- // After traversing the left subtree of this assignment, we should
- // have found a real leftmost symbol, and the leftmost symbol should
- // not be a placeholder.
- ASSERT(leftmostSymbol != &mLeftSubtree);
- ASSERT(leftmostSymbol != &mRightSubtree);
- }
-
- if (TIntermTyped *intermRight = intermAssignment->getRight())
- {
- TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree);
- intermRight->traverse(this);
- }
-
- if (TParentNodeSet *assignmentNodes = mNodeSets.getTopSet())
- connectMultipleNodesToSingleNode(assignmentNodes, leftmostSymbol);
- }
-
- // Push the leftmost symbol of this assignment into the current set of dependent
- // symbols to represent the result of this assignment.
- // An expression like "a = (b = c)" will yield a dependency graph like
- // "c -> b -> a".
- // This line essentially passes the leftmost symbol of the nested assignment
- // ("b" in this example) back up to the earlier visitAssignment call for the
- // outer assignment, which will create the connection "b -> a".
- mNodeSets.insertIntoTopSet(leftmostSymbol);
-}
-
-void TDependencyGraphBuilder::visitLogicalOp(TIntermBinary *intermLogicalOp)
-{
- if (TIntermTyped *intermLeft = intermLogicalOp->getLeft())
- {
- TNodeSetPropagatingMaintainer nodeSetMaintainer(this);
-
- intermLeft->traverse(this);
- if (TParentNodeSet *leftNodes = mNodeSets.getTopSet())
- {
- TGraphLogicalOp *logicalOp = mGraph->createLogicalOp(intermLogicalOp);
- connectMultipleNodesToSingleNode(leftNodes, logicalOp);
- }
- }
-
- if (TIntermTyped *intermRight = intermLogicalOp->getRight())
- {
- TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree);
- intermRight->traverse(this);
- }
-}
-
-void TDependencyGraphBuilder::visitBinaryChildren(TIntermBinary *intermBinary)
-{
- if (TIntermTyped *intermLeft = intermBinary->getLeft())
- intermLeft->traverse(this);
-
- if (TIntermTyped *intermRight = intermBinary->getRight())
- {
- TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree);
- intermRight->traverse(this);
- }
-}
-
-bool TDependencyGraphBuilder::visitSelection(
- Visit visit, TIntermSelection *intermSelection)
-{
- if (TIntermNode *intermCondition = intermSelection->getCondition())
- {
- TNodeSetMaintainer nodeSetMaintainer(this);
-
- intermCondition->traverse(this);
- if (TParentNodeSet *conditionNodes = mNodeSets.getTopSet())
- {
- TGraphSelection *selection = mGraph->createSelection(intermSelection);
- connectMultipleNodesToSingleNode(conditionNodes, selection);
- }
- }
-
- if (TIntermNode *intermTrueBlock = intermSelection->getTrueBlock())
- intermTrueBlock->traverse(this);
-
- if (TIntermNode *intermFalseBlock = intermSelection->getFalseBlock())
- intermFalseBlock->traverse(this);
-
- return false;
-}
-
-bool TDependencyGraphBuilder::visitLoop(Visit visit, TIntermLoop *intermLoop)
-{
- if (TIntermTyped *intermCondition = intermLoop->getCondition())
- {
- TNodeSetMaintainer nodeSetMaintainer(this);
-
- intermCondition->traverse(this);
- if (TParentNodeSet *conditionNodes = mNodeSets.getTopSet())
- {
- TGraphLoop *loop = mGraph->createLoop(intermLoop);
- connectMultipleNodesToSingleNode(conditionNodes, loop);
- }
- }
-
- if (TIntermNode* intermBody = intermLoop->getBody())
- intermBody->traverse(this);
-
- if (TIntermTyped *intermExpression = intermLoop->getExpression())
- intermExpression->traverse(this);
-
- return false;
-}
-
-
-void TDependencyGraphBuilder::connectMultipleNodesToSingleNode(
- TParentNodeSet *nodes, TGraphNode *node) const
-{
- for (TParentNodeSet::const_iterator iter = nodes->begin();
- iter != nodes->end(); ++iter)
- {
- TGraphParentNode *currentNode = *iter;
- currentNode->addDependentNode(node);
- }
-}
diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h
deleted file mode 100644
index c7b54f66b7..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h
+++ /dev/null
@@ -1,199 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHBUILDER_H_
-#define COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHBUILDER_H_
-
-#include "compiler/translator/depgraph/DependencyGraph.h"
-
-//
-// Creates a dependency graph of symbols, function calls, conditions etc. by
-// traversing a intermediate tree.
-//
-class TDependencyGraphBuilder : public TIntermTraverser
-{
- public:
- static void build(TIntermNode *node, TDependencyGraph *graph);
-
- void visitSymbol(TIntermSymbol *) override;
- bool visitBinary(Visit visit, TIntermBinary *) override;
- bool visitSelection(Visit visit, TIntermSelection *) override;
- bool visitAggregate(Visit visit, TIntermAggregate *) override;
- bool visitLoop(Visit visit, TIntermLoop *) override;
-
- private:
- typedef std::stack<TGraphSymbol *> TSymbolStack;
- typedef std::set<TGraphParentNode *> TParentNodeSet;
-
- //
- // For collecting the dependent nodes of assignments, conditions, etc.
- // while traversing the intermediate tree.
- //
- // This data structure is stack of sets. Each set contains dependency graph
- // parent nodes.
- //
- class TNodeSetStack
- {
- public:
- TNodeSetStack() {};
- ~TNodeSetStack() { clear(); }
-
- // This should only be called after a pushSet.
- // Returns NULL if the top set is empty.
- TParentNodeSet *getTopSet() const
- {
- ASSERT(!mNodeSets.empty());
- TParentNodeSet *topSet = mNodeSets.top();
- return !topSet->empty() ? topSet : NULL;
- }
-
- void pushSet() { mNodeSets.push(new TParentNodeSet()); }
- void popSet()
- {
- ASSERT(!mNodeSets.empty());
- delete mNodeSets.top();
- mNodeSets.pop();
- }
-
- // Pops the top set and adds its contents to the new top set.
- // This should only be called after a pushSet.
- // If there is no set below the top set, the top set is just deleted.
- void popSetIntoNext()
- {
- ASSERT(!mNodeSets.empty());
- TParentNodeSet *oldTopSet = mNodeSets.top();
- mNodeSets.pop();
-
- if (!mNodeSets.empty())
- {
- TParentNodeSet *newTopSet = mNodeSets.top();
- newTopSet->insert(oldTopSet->begin(), oldTopSet->end());
- }
-
- delete oldTopSet;
- }
-
- // Does nothing if there is no top set.
- // This can be called when there is no top set if we are visiting
- // symbols that are not under an assignment or condition.
- // We don't need to track those symbols.
- void insertIntoTopSet(TGraphParentNode *node)
- {
- if (mNodeSets.empty())
- return;
-
- mNodeSets.top()->insert(node);
- }
-
- void clear()
- {
- while (!mNodeSets.empty())
- popSet();
- }
-
- private:
- typedef std::stack<TParentNodeSet *> TParentNodeSetStack;
-
- TParentNodeSetStack mNodeSets;
- };
-
- //
- // An instance of this class pushes a new node set when instantiated.
- // When the instance goes out of scope, it and pops the node set.
- //
- class TNodeSetMaintainer : angle::NonCopyable
- {
- public:
- TNodeSetMaintainer(TDependencyGraphBuilder *factory)
- : mSets(factory->mNodeSets)
- {
- mSets.pushSet();
- }
- ~TNodeSetMaintainer() { mSets.popSet(); }
- protected:
- TNodeSetStack &mSets;
- };
-
- //
- // An instance of this class pushes a new node set when instantiated.
- // When the instance goes out of scope, it and pops the top node set and adds
- // its contents to the new top node set.
- //
- class TNodeSetPropagatingMaintainer : angle::NonCopyable
- {
- public:
- TNodeSetPropagatingMaintainer(TDependencyGraphBuilder *factory)
- : mSets(factory->mNodeSets)
- {
- mSets.pushSet();
- }
- ~TNodeSetPropagatingMaintainer() { mSets.popSetIntoNext(); }
- protected:
- TNodeSetStack &mSets;
- };
-
- //
- // An instance of this class keeps track of the leftmost symbol while we're
- // exploring an assignment.
- // It will push the placeholder symbol kLeftSubtree when instantiated under a
- // left subtree, and kRightSubtree under a right subtree.
- // When it goes out of scope, it will pop the leftmost symbol at the top of the
- // scope.
- // During traversal, the TDependencyGraphBuilder will replace kLeftSubtree with
- // a real symbol.
- // kRightSubtree will never be replaced by a real symbol because we are tracking
- // the leftmost symbol.
- //
- class TLeftmostSymbolMaintainer : angle::NonCopyable
- {
- public:
- TLeftmostSymbolMaintainer(
- TDependencyGraphBuilder *factory, TGraphSymbol &subtree)
- : mLeftmostSymbols(factory->mLeftmostSymbols)
- {
- mNeedsPlaceholderSymbol =
- mLeftmostSymbols.empty() || mLeftmostSymbols.top() != &subtree;
- if (mNeedsPlaceholderSymbol)
- mLeftmostSymbols.push(&subtree);
- }
-
- ~TLeftmostSymbolMaintainer()
- {
- if (mNeedsPlaceholderSymbol)
- mLeftmostSymbols.pop();
- }
-
- protected:
- TSymbolStack& mLeftmostSymbols;
- bool mNeedsPlaceholderSymbol;
- };
-
- TDependencyGraphBuilder(TDependencyGraph *graph)
- : TIntermTraverser(true, false, false),
- mLeftSubtree(NULL),
- mRightSubtree(NULL),
- mGraph(graph) {}
- void build(TIntermNode *intermNode) { intermNode->traverse(this); }
-
- void connectMultipleNodesToSingleNode(
- TParentNodeSet *nodes, TGraphNode *node) const;
-
- void visitAssignment(TIntermBinary *);
- void visitLogicalOp(TIntermBinary *);
- void visitBinaryChildren(TIntermBinary *);
- void visitFunctionDefinition(TIntermAggregate *);
- void visitFunctionCall(TIntermAggregate *intermFunctionCall);
- void visitAggregateChildren(TIntermAggregate *);
-
- TGraphSymbol mLeftSubtree;
- TGraphSymbol mRightSubtree;
-
- TDependencyGraph *mGraph;
- TNodeSetStack mNodeSets;
- TSymbolStack mLeftmostSymbols;
-};
-
-#endif // COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHBUILDER_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.cpp b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.cpp
deleted file mode 100644
index 32a2f30141..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/translator/depgraph/DependencyGraphOutput.h"
-
-void TDependencyGraphOutput::outputIndentation()
-{
- for (int i = 0; i < getDepth(); ++i)
- mSink << " ";
-}
-
-void TDependencyGraphOutput::visitArgument(TGraphArgument* parameter)
-{
- outputIndentation();
- mSink << "argument " << parameter->getArgumentNumber() << " of call to "
- << parameter->getIntermFunctionCall()->getName() << "\n";
-}
-
-void TDependencyGraphOutput::visitFunctionCall(TGraphFunctionCall* functionCall)
-{
- outputIndentation();
- mSink << "function call " << functionCall->getIntermFunctionCall()->getName() << "\n";
-}
-
-void TDependencyGraphOutput::visitSymbol(TGraphSymbol* symbol)
-{
- outputIndentation();
- mSink << symbol->getIntermSymbol()->getSymbol() << " (symbol id: "
- << symbol->getIntermSymbol()->getId() << ")\n";
-}
-
-void TDependencyGraphOutput::visitSelection(TGraphSelection* selection)
-{
- outputIndentation();
- mSink << "selection\n";
-}
-
-void TDependencyGraphOutput::visitLoop(TGraphLoop* loop)
-{
- outputIndentation();
- mSink << "loop condition\n";
-}
-
-void TDependencyGraphOutput::visitLogicalOp(TGraphLogicalOp* logicalOp)
-{
- outputIndentation();
- mSink << "logical " << logicalOp->getOpString() << "\n";
-}
-
-void TDependencyGraphOutput::outputAllSpanningTrees(TDependencyGraph& graph)
-{
- mSink << "\n";
-
- for (auto symbol : graph.allNodes())
- {
- mSink << "--- Dependency graph spanning tree ---\n";
- clearVisited();
- symbol->traverse(this);
- mSink << "\n";
- }
-}
diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h
deleted file mode 100644
index b201e0a671..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHOUTPUT_H_
-#define COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHOUTPUT_H_
-
-#include "compiler/translator/depgraph/DependencyGraph.h"
-#include "compiler/translator/InfoSink.h"
-
-class TDependencyGraphOutput : public TDependencyGraphTraverser
-{
- public:
- TDependencyGraphOutput(TInfoSinkBase& sink) : mSink(sink) {}
- void visitSymbol(TGraphSymbol* symbol) override;
- void visitArgument(TGraphArgument* parameter) override;
- void visitFunctionCall(TGraphFunctionCall* functionCall) override;
- void visitSelection(TGraphSelection* selection) override;
- void visitLoop(TGraphLoop* loop) override;
- void visitLogicalOp(TGraphLogicalOp* logicalOp) override;
-
- void outputAllSpanningTrees(TDependencyGraph& graph);
- private:
- void outputIndentation();
-
- TInfoSinkBase& mSink;
-};
-
-#endif // COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHOUTPUT_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphTraverse.cpp b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphTraverse.cpp
deleted file mode 100644
index 197fde97e2..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphTraverse.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/translator/depgraph/DependencyGraph.h"
-
-// These methods do a breadth-first traversal through the graph and mark visited nodes.
-
-void TGraphNode::traverse(TDependencyGraphTraverser* graphTraverser)
-{
- graphTraverser->markVisited(this);
-}
-
-void TGraphParentNode::traverse(TDependencyGraphTraverser* graphTraverser)
-{
- TGraphNode::traverse(graphTraverser);
-
- graphTraverser->incrementDepth();
-
- // Visit the parent node's children.
- for (TGraphNodeSet::const_iterator iter = mDependentNodes.begin();
- iter != mDependentNodes.end();
- ++iter)
- {
- TGraphNode* node = *iter;
- if (!graphTraverser->isVisited(node))
- node->traverse(graphTraverser);
- }
-
- graphTraverser->decrementDepth();
-}
-
-void TGraphArgument::traverse(TDependencyGraphTraverser* graphTraverser)
-{
- graphTraverser->visitArgument(this);
- TGraphParentNode::traverse(graphTraverser);
-}
-
-void TGraphFunctionCall::traverse(TDependencyGraphTraverser* graphTraverser)
-{
- graphTraverser->visitFunctionCall(this);
- TGraphParentNode::traverse(graphTraverser);
-}
-
-void TGraphSymbol::traverse(TDependencyGraphTraverser* graphTraverser)
-{
- graphTraverser->visitSymbol(this);
- TGraphParentNode::traverse(graphTraverser);
-}
-
-void TGraphSelection::traverse(TDependencyGraphTraverser* graphTraverser)
-{
- graphTraverser->visitSelection(this);
- TGraphNode::traverse(graphTraverser);
-}
-
-void TGraphLoop::traverse(TDependencyGraphTraverser* graphTraverser)
-{
- graphTraverser->visitLoop(this);
- TGraphNode::traverse(graphTraverser);
-}
-
-void TGraphLogicalOp::traverse(TDependencyGraphTraverser* graphTraverser)
-{
- graphTraverser->visitLogicalOp(this);
- TGraphNode::traverse(graphTraverser);
-}
diff --git a/src/3rdparty/angle/src/compiler/translator/emulated_builtin_function_data_hlsl.json b/src/3rdparty/angle/src/compiler/translator/emulated_builtin_function_data_hlsl.json
new file mode 100644
index 0000000000..32e500fe67
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/emulated_builtin_function_data_hlsl.json
@@ -0,0 +1,1382 @@
+[
+ {
+ "op":"mod",
+ "return_type":"float",
+ "args":[
+ "float x",
+ "float y"
+ ],
+ "body":[
+ "return x - y * floor(x / y);"
+ ]
+ },
+ {
+ "op":"mod",
+ "return_type":"float2",
+ "args":[
+ "float2 x",
+ "float2 y"
+ ],
+ "body":[
+ "return x - y * floor(x / y);"
+ ]
+ },
+ {
+ "op":"mod",
+ "return_type":"float2",
+ "args":[
+ "float2 x",
+ "float y"
+ ],
+ "body":[
+ "return x - y * floor(x / y);"
+ ]
+ },
+ {
+ "op":"mod",
+ "return_type":"float3",
+ "args":[
+ "float3 x",
+ "float3 y"
+ ],
+ "body":[
+ "return x - y * floor(x / y);"
+ ]
+ },
+ {
+ "op":"mod",
+ "return_type":"float3",
+ "args":[
+ "float3 x",
+ "float y"
+ ],
+ "body":[
+ "return x - y * floor(x / y);"
+ ]
+ },
+ {
+ "op":"mod",
+ "return_type":"float4",
+ "args":[
+ "float4 x",
+ "float4 y"
+ ],
+ "body":[
+ "return x - y * floor(x / y);"
+ ]
+ },
+ {
+ "op":"mod",
+ "return_type":"float4",
+ "args":[
+ "float4 x",
+ "float y"
+ ],
+ "body":[
+ "return x - y * floor(x / y);"
+ ]
+ },
+ {
+ "op":"frexp",
+ "return_type":"float",
+ "args":[
+ "float x",
+ "out int exp"
+ ],
+ "body":[
+ "float fexp;",
+ "float mantissa = frexp(abs(x), fexp) * sign(x);",
+ "exp = int(fexp);",
+ "return mantissa;"
+ ]
+ },
+ {
+ "op":"frexp",
+ "return_type":"float2",
+ "args":[
+ "float2 x",
+ "out int2 exp"
+ ],
+ "body":[
+ "float2 fexp;",
+ "float2 mantissa = frexp(abs(x), fexp) * sign(x);",
+ "exp = int2(fexp);",
+ "return mantissa;"
+ ]
+ },
+ {
+ "op":"frexp",
+ "return_type":"float3",
+ "args":[
+ "float3 x",
+ "out int3 exp"
+ ],
+ "body":[
+ "float3 fexp;",
+ "float3 mantissa = frexp(abs(x), fexp) * sign(x);",
+ "exp = int3(fexp);",
+ "return mantissa;"
+ ]
+ },
+ {
+ "op":"frexp",
+ "return_type":"float4",
+ "args":[
+ "float4 x",
+ "out int4 exp"
+ ],
+ "body":[
+ "float4 fexp;",
+ "float4 mantissa = frexp(abs(x), fexp) * sign(x);",
+ "exp = int4(fexp);",
+ "return mantissa;"
+ ]
+ },
+ {
+ "op":"ldexp",
+ "return_type":"float",
+ "args":[
+ "float x",
+ "int exp"
+ ],
+ "body":[
+ "return ldexp(x, float(exp));"
+ ]
+ },
+ {
+ "op":"ldexp",
+ "return_type":"float2",
+ "args":[
+ "float2 x",
+ "int2 exp"
+ ],
+ "body":[
+ "return ldexp(x, float2(exp));"
+ ]
+ },
+ {
+ "op":"ldexp",
+ "return_type":"float3",
+ "args":[
+ "float3 x",
+ "int3 exp"
+ ],
+ "body":[
+ "return ldexp(x, float3(exp));"
+ ]
+ },
+ {
+ "op":"ldexp",
+ "return_type":"float4",
+ "args":[
+ "float4 x",
+ "int4 exp"
+ ],
+ "body":[
+ "return ldexp(x, float4(exp));"
+ ]
+ },
+ {
+ "op":"faceforward",
+ "return_type":"float",
+ "args":[
+ "float N",
+ "float I",
+ "float Nref"
+ ],
+ "body":[
+ "if(dot(Nref, I) >= 0)",
+ "{",
+ " return -N;",
+ "}",
+ "else",
+ "{",
+ " return N;",
+ "}"
+ ]
+ },
+ {
+ "op":"faceforward",
+ "return_type":"float2",
+ "args":[
+ "float2 N",
+ "float2 I",
+ "float2 Nref"
+ ],
+ "body":[
+ "if(dot(Nref, I) >= 0)",
+ "{",
+ " return -N;",
+ "}",
+ "else",
+ "{",
+ " return N;",
+ "}"
+ ]
+ },
+ {
+ "op":"faceforward",
+ "return_type":"float3",
+ "args":[
+ "float3 N",
+ "float3 I",
+ "float3 Nref"
+ ],
+ "body":[
+ "if(dot(Nref, I) >= 0)",
+ "{",
+ " return -N;",
+ "}",
+ "else",
+ "{",
+ " return N;",
+ "}"
+ ]
+ },
+ {
+ "op":"faceforward",
+ "return_type":"float4",
+ "args":[
+ "float4 N",
+ "float4 I",
+ "float4 Nref"
+ ],
+ "body":[
+ "if(dot(Nref, I) >= 0)",
+ "{",
+ " return -N;",
+ "}",
+ "else",
+ "{",
+ " return N;",
+ "}"
+ ]
+ },
+ {
+ "op":"atan",
+ "return_type":"float",
+ "args":[
+ "float y",
+ "float x"
+ ],
+ "body":[
+ "if(x == 0 && y == 0) x = 1;",
+ "return atan2(y, x);"
+ ]
+ },
+ {
+ "op":"atan",
+ "return_type":"float2",
+ "args":[
+ "float2 y",
+ "float2 x"
+ ],
+ "body":[
+ "if(x[0] == 0 && y[0] == 0) x[0] = 1;",
+ "if(x[1] == 0 && y[1] == 0) x[1] = 1;",
+ "return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));"
+ ]
+ },
+ {
+ "op":"atan",
+ "return_type":"float3",
+ "args":[
+ "float3 y",
+ "float3 x"
+ ],
+ "body":[
+ "if(x[0] == 0 && y[0] == 0) x[0] = 1;",
+ "if(x[1] == 0 && y[1] == 0) x[1] = 1;",
+ "if(x[2] == 0 && y[2] == 0) x[2] = 1;",
+ "return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));"
+ ]
+ },
+ {
+ "op":"atan",
+ "return_type":"float4",
+ "args":[
+ "float4 y",
+ "float4 x"
+ ],
+ "body":[
+ "if(x[0] == 0 && y[0] == 0) x[0] = 1;",
+ "if(x[1] == 0 && y[1] == 0) x[1] = 1;",
+ "if(x[2] == 0 && y[2] == 0) x[2] = 1;",
+ "if(x[3] == 0 && y[3] == 0) x[3] = 1;",
+ "return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], ",
+ "x[2]), atan2(y[3], x[3]));"
+ ]
+ },
+ {
+ "op":"asinh",
+ "return_type":"float",
+ "args":[
+ "in float x"
+ ],
+ "body":[
+ "return log(x + sqrt(pow(x, 2.0) + 1.0));"
+ ]
+ },
+ {
+ "op":"asinh",
+ "return_type":"float2",
+ "args":[
+ "in float2 x"
+ ],
+ "body":[
+ "return log(x + sqrt(pow(x, 2.0) + 1.0));"
+ ]
+ },
+ {
+ "op":"asinh",
+ "return_type":"float3",
+ "args":[
+ "in float3 x"
+ ],
+ "body":[
+ "return log(x + sqrt(pow(x, 2.0) + 1.0));"
+ ]
+ },
+ {
+ "op":"asinh",
+ "return_type":"float4",
+ "args":[
+ "in float4 x"
+ ],
+ "body":[
+ "return log(x + sqrt(pow(x, 2.0) + 1.0));"
+ ]
+ },
+ {
+ "op":"acosh",
+ "return_type":"float",
+ "args":[
+ "in float x"
+ ],
+ "body":[
+ "return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));"
+ ]
+ },
+ {
+ "op":"acosh",
+ "return_type":"float2",
+ "args":[
+ "in float2 x"
+ ],
+ "body":[
+ "return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));"
+ ]
+ },
+ {
+ "op":"acosh",
+ "return_type":"float3",
+ "args":[
+ "in float3 x"
+ ],
+ "body":[
+ "return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));"
+ ]
+ },
+ {
+ "op":"acosh",
+ "return_type":"float4",
+ "args":[
+ "in float4 x"
+ ],
+ "body":[
+ "return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));"
+ ]
+ },
+ {
+ "op":"atanh",
+ "return_type":"float",
+ "args":[
+ "in float x"
+ ],
+ "body":[
+ "return 0.5 * log((1.0 + x) / (1.0 - x));"
+ ]
+ },
+ {
+ "op":"atanh",
+ "return_type":"float2",
+ "args":[
+ "in float2 x"
+ ],
+ "body":[
+ "return 0.5 * log((1.0 + x) / (1.0 - x));"
+ ]
+ },
+ {
+ "op":"atanh",
+ "return_type":"float3",
+ "args":[
+ "in float3 x"
+ ],
+ "body":[
+ "return 0.5 * log((1.0 + x) / (1.0 - x));"
+ ]
+ },
+ {
+ "op":"atanh",
+ "return_type":"float4",
+ "args":[
+ "in float4 x"
+ ],
+ "body":[
+ "return 0.5 * log((1.0 + x) / (1.0 - x));"
+ ]
+ },
+ {
+ "op":"roundEven",
+ "return_type":"float",
+ "args":[
+ "in float x"
+ ],
+ "body":[
+ "return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);"
+ ]
+ },
+ {
+ "op":"roundEven",
+ "return_type":"float2",
+ "args":[
+ "in float2 x"
+ ],
+ "body":[
+ "float2 v;",
+ "v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);",
+ "v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);",
+ "return v;"
+ ]
+ },
+ {
+ "op":"roundEven",
+ "return_type":"float3",
+ "args":[
+ "in float3 x"
+ ],
+ "body":[
+ "float3 v;",
+ "v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);",
+ "v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);",
+ "v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);",
+ "return v;"
+ ]
+ },
+ {
+ "op":"roundEven",
+ "return_type":"float4",
+ "args":[
+ "in float4 x"
+ ],
+ "body":[
+ "float4 v;",
+ "v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);",
+ "v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);",
+ "v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);",
+ "v[3] = (frac(x[3]) == 0.5 && trunc(x[3]) % 2.0 == 0.0) ? trunc(x[3]) : round(x[3]);",
+ "return v;"
+ ]
+ },
+ {
+ "op":"packSnorm2x16",
+ "return_type":"uint",
+ "args":[
+ "in float2 v"
+ ],
+ "helper":[
+ "int webgl_toSnorm16(in float x) {",
+ " return int(round(clamp(x, -1.0, 1.0) * 32767.0));",
+ "}"
+ ],
+ "body":[
+ "int x = webgl_toSnorm16(v.x);",
+ "int y = webgl_toSnorm16(v.y);",
+ "return (asuint(y) << 16) | (asuint(x) & 0xffffu);"
+ ]
+ },
+ {
+ "op":"packUnorm2x16",
+ "return_type":"uint",
+ "args":[
+ "in float2 v"
+ ],
+ "helper":[
+ "uint webgl_toUnorm16(in float x) {",
+ " return uint(round(clamp(x, 0.0, 1.0) * 65535.0));",
+ "}"
+ ],
+ "body":[
+ "uint x = webgl_toUnorm16(v.x);",
+ "uint y = webgl_toUnorm16(v.y);",
+ "return (y << 16) | x;"
+ ]
+ },
+ {
+ "op":"packHalf2x16",
+ "return_type":"uint",
+ "args":[
+ "in float2 v"
+ ],
+ "body":[
+ "uint x = f32tof16(v.x);",
+ "uint y = f32tof16(v.y);",
+ "return (y << 16) | x;"
+ ]
+ },
+ {
+ "op":"unpackSnorm2x16",
+ "return_type":"float2",
+ "args":[
+ "in uint u"
+ ],
+ "helper":[
+ "float webgl_fromSnorm16(in uint x) {",
+ " int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);",
+ " return clamp(float(xi) / 32767.0, -1.0, 1.0);",
+ "}"
+ ],
+ "body":[
+ "uint y = (u >> 16);",
+ "uint x = u;",
+ "return float2(webgl_fromSnorm16(x), webgl_fromSnorm16(y));"
+ ]
+ },
+ {
+ "op":"unpackUnorm2x16",
+ "return_type":"float2",
+ "args":[
+ "in uint u"
+ ],
+ "helper":[
+ "float webgl_fromUnorm16(in uint x) {",
+ " return float(x) / 65535.0;",
+ "}"
+ ],
+ "body":[
+ "uint y = (u >> 16);",
+ "uint x = u & 0xffffu;",
+ "return float2(webgl_fromUnorm16(x), webgl_fromUnorm16(y));"
+ ]
+ },
+ {
+ "op":"unpackHalf2x16",
+ "return_type":"float2",
+ "args":[
+ "in uint u"
+ ],
+ "body":[
+ "uint y = (u >> 16);",
+ "uint x = u & 0xffffu;",
+ "return float2(f16tof32(x), f16tof32(y));"
+ ]
+ },
+ {
+ "op":"packSnorm4x8",
+ "return_type":"uint",
+ "args":[
+ "in float4 v"
+ ],
+ "helper":[
+ "int webgl_toSnorm8(in float x) {",
+ " return int(round(clamp(x, -1.0, 1.0) * 127.0));",
+ "}"
+ ],
+ "body":[
+ "int x = webgl_toSnorm8(v.x);",
+ "int y = webgl_toSnorm8(v.y);",
+ "int z = webgl_toSnorm8(v.z);",
+ "int w = webgl_toSnorm8(v.w);",
+ "return ((asuint(w) & 0xffu) << 24) | ((asuint(z) & 0xffu) << 16) ",
+ "| ((asuint(y) & 0xffu) << 8) | (asuint(x) & 0xffu);"
+ ]
+ },
+ {
+ "op":"packUnorm4x8",
+ "return_type":"uint",
+ "args":[
+ "in float4 v"
+ ],
+ "helper":[
+ "uint webgl_toUnorm8(in float x) {",
+ " return uint(round(clamp(x, 0.0, 1.0) * 255.0));",
+ "}"
+ ],
+ "body":[
+ "uint x = webgl_toUnorm8(v.x);",
+ "uint y = webgl_toUnorm8(v.y);",
+ "uint z = webgl_toUnorm8(v.z);",
+ "uint w = webgl_toUnorm8(v.w);",
+ "return (w << 24) | (z << 16) | (y << 8) | x;"
+ ]
+ },
+ {
+ "op":"unpackSnorm4x8",
+ "return_type":"float4",
+ "args":[
+ "in uint u"
+ ],
+ "helper":[
+ "float webgl_fromSnorm8(in uint x) {",
+ " int xi = asint(x & 0x7fu) - asint(x & 0x80u);",
+ " return clamp(float(xi) / 127.0, -1.0, 1.0);",
+ "}"
+ ],
+ "body":[
+ "uint w = (u >> 24);",
+ "uint z = (u >> 16);",
+ "uint y = (u >> 8);",
+ "uint x = u;",
+ "return float4(webgl_fromSnorm8(x), webgl_fromSnorm8(y), ",
+ "webgl_fromSnorm8(z), webgl_fromSnorm8(w));"
+ ]
+ },
+ {
+ "op":"unpackUnorm4x8",
+ "return_type":"float4",
+ "args":[
+ "in uint u"
+ ],
+ "helper":[
+ "float webgl_fromUnorm8(in uint x) {",
+ " return float(x) / 255.0;",
+ "}"
+ ],
+ "body":[
+ "uint w = (u >> 24) & 0xffu;",
+ "uint z = (u >> 16) & 0xffu;",
+ "uint y = (u >> 8) & 0xffu;",
+ "uint x = u & 0xffu;",
+ "return float4(webgl_fromUnorm8(x), webgl_fromUnorm8(y), ",
+ "webgl_fromUnorm8(z), webgl_fromUnorm8(w));"
+ ]
+ },
+ {
+ "comment":[
+ "The matrix resulting from outer product needs to be transposed",
+ "(matrices are stored as transposed to simplify element access in HLSL).",
+ "So the function should return transpose(c * r) where c is a column vector",
+ "and r is a row vector. This can be simplified by using the following",
+ "formula:",
+ "transpose(c * r) = transpose(r) * transpose(c)",
+ "transpose(r) and transpose(c) are in a sense free, since to get the",
+ "transpose of r, we simply can build a column matrix out of the original",
+ "vector instead of a row matrix."
+ ],
+ "op":"outerProduct",
+ "return_type":"float2x2",
+ "args":[
+ "in float2 c",
+ "in float2 r"
+ ],
+ "body":[
+ "return mul(float2x1(r), float1x2(c));"
+ ]
+ },
+ {
+ "op":"outerProduct",
+ "return_type":"float3x3",
+ "args":[
+ "in float3 c",
+ "in float3 r"
+ ],
+ "body":[
+ "return mul(float3x1(r), float1x3(c));"
+ ]
+ },
+ {
+ "op":"outerProduct",
+ "return_type":"float4x4",
+ "args":[
+ "in float4 c",
+ "in float4 r"
+ ],
+ "body":[
+ "return mul(float4x1(r), float1x4(c));"
+ ]
+ },
+ {
+ "op":"outerProduct",
+ "return_type":"float2x3",
+ "args":[
+ "in float3 c",
+ "in float2 r"
+ ],
+ "body":[
+ "return mul(float2x1(r), float1x3(c));"
+ ]
+ },
+ {
+ "op":"outerProduct",
+ "return_type":"float3x2",
+ "args":[
+ "in float2 c",
+ "in float3 r"
+ ],
+ "body":[
+ "return mul(float3x1(r), float1x2(c));"
+ ]
+ },
+ {
+ "op":"outerProduct",
+ "return_type":"float2x4",
+ "args":[
+ "in float4 c",
+ "in float2 r"
+ ],
+ "body":[
+ "return mul(float2x1(r), float1x4(c));"
+ ]
+ },
+ {
+ "op":"outerProduct",
+ "return_type":"float4x2",
+ "args":[
+ "in float2 c",
+ "in float4 r"
+ ],
+ "body":[
+ "return mul(float4x1(r), float1x2(c));"
+ ]
+ },
+ {
+ "op":"outerProduct",
+ "return_type":"float3x4",
+ "args":[
+ "in float4 c",
+ "in float3 r"
+ ],
+ "body":[
+ "return mul(float3x1(r), float1x4(c));"
+ ]
+ },
+ {
+ "op":"outerProduct",
+ "return_type":"float4x3",
+ "args":[
+ "in float3 c",
+ "in float4 r"
+ ],
+ "body":[
+ "return mul(float4x1(r), float1x3(c));"
+ ]
+ },
+ {
+ "comment":[
+ "Remember here that the parameter matrix is actually the transpose",
+ "of the matrix that we're trying to invert, and the resulting matrix",
+ "should also be the transpose of the inverse.",
+ "When accessing the parameter matrix with m[a][b] it can be thought of so",
+ "that a is the column and b is the row of the matrix that we're inverting.",
+ "We calculate the inverse as the adjugate matrix divided by the",
+ "determinant of the matrix being inverted. However, as the result needs",
+ "to be transposed, we actually use of the transpose of the adjugate matrix",
+ "which happens to be the cofactor matrix. That's stored in 'cof'.",
+ "We don't need to care about divide-by-zero since results are undefined",
+ "for singular or poorly-conditioned matrices."
+ ],
+ "op":"inverse",
+ "return_type":"float2x2",
+ "args":[
+ "in float2x2 m"
+ ],
+ "body":[
+ "float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };",
+ "return cof / determinant(transpose(m));"
+ ]
+ },
+ {
+ "comment":[
+ "cofAB is the cofactor for column A and row B."
+ ],
+ "op":"inverse",
+ "return_type":"float3x3",
+ "args":[
+ "in float3x3 m"
+ ],
+ "body":[
+ "float cof00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];",
+ "float cof01 = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]);",
+ "float cof02 = m[1][0] * m[2][1] - m[2][0] * m[1][1];",
+ "float cof10 = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]);",
+ "float cof11 = m[0][0] * m[2][2] - m[2][0] * m[0][2];",
+ "float cof12 = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]);",
+ "float cof20 = m[0][1] * m[1][2] - m[1][1] * m[0][2];",
+ "float cof21 = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]);",
+ "float cof22 = m[0][0] * m[1][1] - m[1][0] * m[0][1];",
+ "float3x3 cof = { cof00, cof10, cof20, cof01, cof11, cof21, cof02, cof12, cof22 };",
+ "return cof / determinant(transpose(m));"
+ ]
+ },
+ {
+ "op":"inverse",
+ "return_type":"float4x4",
+ "args":[
+ "in float4x4 m"
+ ],
+ "body":[
+ "float cof00 = m[1][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[1][3] + m[3][1] * ",
+ "m[1][2] * m[2][3]",
+ " - m[1][1] * m[3][2] * m[2][3] - m[2][1] * m[1][2] * m[3][3] - m[3][1] * m[2][2] * ",
+ "m[1][3];",
+ "float cof01 = -(m[1][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[1][3] + m[3][0] * ",
+ "m[1][2] * m[2][3]",
+ " - m[1][0] * m[3][2] * m[2][3] - m[2][0] * m[1][2] * m[3][3] - m[3][0] * m[2][2] * ",
+ "m[1][3]);",
+ "float cof02 = m[1][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[1][3] + m[3][0] * ",
+ "m[1][1] * m[2][3]",
+ " - m[1][0] * m[3][1] * m[2][3] - m[2][0] * m[1][1] * m[3][3] - m[3][0] * m[2][1] * ",
+ "m[1][3];",
+ "float cof03 = -(m[1][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[1][2] + m[3][0] * ",
+ "m[1][1] * m[2][2]",
+ " - m[1][0] * m[3][1] * m[2][2] - m[2][0] * m[1][1] * m[3][2] - m[3][0] * m[2][1] * ",
+ "m[1][2]);",
+ "float cof10 = -(m[0][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[0][3] + m[3][1] * ",
+ "m[0][2] * m[2][3]",
+ " - m[0][1] * m[3][2] * m[2][3] - m[2][1] * m[0][2] * m[3][3] - m[3][1] * m[2][2] * ",
+ "m[0][3]);",
+ "float cof11 = m[0][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[0][3] + m[3][0] * ",
+ "m[0][2] * m[2][3]",
+ " - m[0][0] * m[3][2] * m[2][3] - m[2][0] * m[0][2] * m[3][3] - m[3][0] * m[2][2] * ",
+ "m[0][3];",
+ "float cof12 = -(m[0][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[0][3] + m[3][0] * ",
+ "m[0][1] * m[2][3]",
+ " - m[0][0] * m[3][1] * m[2][3] - m[2][0] * m[0][1] * m[3][3] - m[3][0] * m[2][1] * ",
+ "m[0][3]);",
+ "float cof13 = m[0][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[0][2] + m[3][0] * ",
+ "m[0][1] * m[2][2]",
+ " - m[0][0] * m[3][1] * m[2][2] - m[2][0] * m[0][1] * m[3][2] - m[3][0] * m[2][1] * ",
+ "m[0][2];",
+ "float cof20 = m[0][1] * m[1][2] * m[3][3] + m[1][1] * m[3][2] * m[0][3] + m[3][1] * ",
+ "m[0][2] * m[1][3]",
+ " - m[0][1] * m[3][2] * m[1][3] - m[1][1] * m[0][2] * m[3][3] - m[3][1] * m[1][2] * ",
+ "m[0][3];",
+ "float cof21 = -(m[0][0] * m[1][2] * m[3][3] + m[1][0] * m[3][2] * m[0][3] + m[3][0] * ",
+ "m[0][2] * m[1][3]",
+ " - m[0][0] * m[3][2] * m[1][3] - m[1][0] * m[0][2] * m[3][3] - m[3][0] * m[1][2] * ",
+ "m[0][3]);",
+ "float cof22 = m[0][0] * m[1][1] * m[3][3] + m[1][0] * m[3][1] * m[0][3] + m[3][0] * ",
+ "m[0][1] * m[1][3]",
+ " - m[0][0] * m[3][1] * m[1][3] - m[1][0] * m[0][1] * m[3][3] - m[3][0] * m[1][1] * ",
+ "m[0][3];",
+ "float cof23 = -(m[0][0] * m[1][1] * m[3][2] + m[1][0] * m[3][1] * m[0][2] + m[3][0] * ",
+ "m[0][1] * m[1][2]",
+ " - m[0][0] * m[3][1] * m[1][2] - m[1][0] * m[0][1] * m[3][2] - m[3][0] * m[1][1] * ",
+ "m[0][2]);",
+ "float cof30 = -(m[0][1] * m[1][2] * m[2][3] + m[1][1] * m[2][2] * m[0][3] + m[2][1] * ",
+ "m[0][2] * m[1][3]",
+ " - m[0][1] * m[2][2] * m[1][3] - m[1][1] * m[0][2] * m[2][3] - m[2][1] * m[1][2] * ",
+ "m[0][3]);",
+ "float cof31 = m[0][0] * m[1][2] * m[2][3] + m[1][0] * m[2][2] * m[0][3] + m[2][0] * ",
+ "m[0][2] * m[1][3]",
+ " - m[0][0] * m[2][2] * m[1][3] - m[1][0] * m[0][2] * m[2][3] - m[2][0] * m[1][2] * ",
+ "m[0][3];",
+ "float cof32 = -(m[0][0] * m[1][1] * m[2][3] + m[1][0] * m[2][1] * m[0][3] + m[2][0] * ",
+ "m[0][1] * m[1][3]",
+ " - m[0][0] * m[2][1] * m[1][3] - m[1][0] * m[0][1] * m[2][3] - m[2][0] * m[1][1] * ",
+ "m[0][3]);",
+ "float cof33 = m[0][0] * m[1][1] * m[2][2] + m[1][0] * m[2][1] * m[0][2] + m[2][0] * ",
+ "m[0][1] * m[1][2]",
+ " - m[0][0] * m[2][1] * m[1][2] - m[1][0] * m[0][1] * m[2][2] - m[2][0] * m[1][1] * ",
+ "m[0][2];",
+ "float4x4 cof = { cof00, cof10, cof20, cof30, cof01, cof11, cof21, cof31,",
+ " cof02, cof12, cof22, cof32, cof03, cof13, cof23, cof33 };",
+ "return cof / determinant(transpose(m));"
+ ]
+ },
+ {
+ "comment":[
+ "Emulate ESSL3 variant of mix that takes last argument as boolean vector.",
+ "genType mix(genType x, genType y, genBType a): Selects which vector each returned component",
+ "comes from. For a component of 'a' that is false, the corresponding component of 'x' is",
+ "returned. For a component of 'a' that is true, the corresponding component of 'y' is returned."
+ ],
+ "op":"mix",
+ "return_type":"float",
+ "args":[
+ "float x",
+ "float y",
+ "bool a"
+ ],
+ "body":[
+ "return a ? y : x;"
+ ]
+ },
+ {
+ "op":"mix",
+ "return_type":"float2",
+ "args":[
+ "float2 x",
+ "float2 y",
+ "bool2 a"
+ ],
+ "body":[
+ "return a ? y : x;"
+ ]
+ },
+ {
+ "op":"mix",
+ "return_type":"float3",
+ "args":[
+ "float3 x",
+ "float3 y",
+ "bool3 a"
+ ],
+ "body":[
+ "return a ? y : x;"
+ ]
+ },
+ {
+ "op":"mix",
+ "return_type":"float4",
+ "args":[
+ "float4 x",
+ "float4 y",
+ "bool4 a"
+ ],
+ "body":[
+ "return a ? y : x;"
+ ]
+ },
+ {
+ "op":"bitfieldExtract",
+ "return_type":"uint",
+ "args":[
+ "uint value",
+ "int offset",
+ "int bits"
+ ],
+ "body":[
+ "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
+ "{",
+ " return 0u;",
+ "}",
+ "uint maskMsb = (1u << (bits - 1));",
+ "uint mask = ((maskMsb - 1u) | maskMsb) << offset;",
+ "return (value & mask) >> offset;"
+ ]
+ },
+ {
+ "op":"bitfieldExtract",
+ "return_type":"uint2",
+ "args":[
+ "uint2 value",
+ "int offset",
+ "int bits"
+ ],
+ "body":[
+ "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
+ "{",
+ " return uint2(0u, 0u);",
+ "}",
+ "uint maskMsb = (1u << (bits - 1));",
+ "uint mask = ((maskMsb - 1u) | maskMsb) << offset;",
+ "return (value & mask) >> offset;"
+ ]
+ },
+ {
+ "op":"bitfieldExtract",
+ "return_type":"uint3",
+ "args":[
+ "uint3 value",
+ "int offset",
+ "int bits"
+ ],
+ "body":[
+ "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
+ "{",
+ " return uint3(0u, 0u, 0u);",
+ "}",
+ "uint maskMsb = (1u << (bits - 1));",
+ "uint mask = ((maskMsb - 1u) | maskMsb) << offset;",
+ "return (value & mask) >> offset;"
+ ]
+ },
+ {
+ "op":"bitfieldExtract",
+ "return_type":"uint4",
+ "args":[
+ "uint4 value",
+ "int offset",
+ "int bits"
+ ],
+ "body":[
+ "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
+ "{",
+ " return uint4(0u, 0u, 0u, 0u);",
+ "}",
+ "uint maskMsb = (1u << (bits - 1));",
+ "uint mask = ((maskMsb - 1u) | maskMsb) << offset;",
+ "return (value & mask) >> offset;"
+ ]
+ },
+ {
+ "op":"bitfieldExtract",
+ "return_type":"int",
+ "args":[
+ "int value",
+ "int offset",
+ "int bits"
+ ],
+ "body":[
+ "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
+ "{",
+ " return 0;",
+ "}",
+ "uint maskMsb = (1u << (bits - 1));",
+ "uint mask = ((maskMsb - 1u) | maskMsb) << offset;",
+ "uint resultUnsigned = (asuint(value) & mask) >> offset;",
+ "if (bits != 32 && (resultUnsigned & maskMsb) != 0)",
+ "{",
+ " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;",
+ " resultUnsigned |= higherBitsMask;",
+ "}",
+ "return asint(resultUnsigned);"
+ ]
+ },
+ {
+ "op":"bitfieldExtract",
+ "return_type":"int2",
+ "args":[
+ "int2 value",
+ "int offset",
+ "int bits"
+ ],
+ "body":[
+ "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
+ "{",
+ " return int2(0, 0);",
+ "}",
+ "uint maskMsb = (1u << (bits - 1));",
+ "uint mask = ((maskMsb - 1u) | maskMsb) << offset;",
+ "uint2 resultUnsigned = (asuint(value) & mask) >> offset;",
+ "if (bits != 32)",
+ "{",
+ " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;",
+ " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;",
+ "}",
+ "return asint(resultUnsigned);"
+ ]
+ },
+ {
+ "op":"bitfieldExtract",
+ "return_type":"int3",
+ "args":[
+ "int3 value",
+ "int offset",
+ "int bits"
+ ],
+ "body":[
+ "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
+ "{",
+ " return int3(0, 0, 0);",
+ "}",
+ "uint maskMsb = (1u << (bits - 1));",
+ "uint mask = ((maskMsb - 1u) | maskMsb) << offset;",
+ "uint3 resultUnsigned = (asuint(value) & mask) >> offset;",
+ "if (bits != 32)",
+ "{",
+ " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;",
+ " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;",
+ "}",
+ "return asint(resultUnsigned);"
+ ]
+ },
+ {
+ "op":"bitfieldExtract",
+ "return_type":"int4",
+ "args":[
+ "int4 value",
+ "int offset",
+ "int bits"
+ ],
+ "body":[
+ "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
+ "{",
+ " return int4(0, 0, 0, 0);",
+ "}",
+ "uint maskMsb = (1u << (bits - 1));",
+ "uint mask = ((maskMsb - 1u) | maskMsb) << offset;",
+ "uint4 resultUnsigned = (asuint(value) & mask) >> offset;",
+ "if (bits != 32)",
+ "{",
+ " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;",
+ " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;",
+ "}",
+ "return asint(resultUnsigned);"
+ ]
+ },
+ {
+ "op":"bitfieldInsert",
+ "return_type":"uint",
+ "args":[
+ "uint base",
+ "uint insert",
+ "int offset",
+ "int bits"
+ ],
+ "body":[
+ "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
+ "{",
+ " return base;",
+ "}",
+ "uint maskMsb = (1u << (bits - 1));",
+ "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;",
+ "uint baseMask = ~insertMask;",
+ "return (base & baseMask) | ((insert << offset) & insertMask);"
+ ]
+ },
+ {
+ "op":"bitfieldInsert",
+ "return_type":"uint2",
+ "args":[
+ "uint2 base",
+ "uint2 insert",
+ "int offset",
+ "int bits"
+ ],
+ "body":[
+ "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
+ "{",
+ " return base;",
+ "}",
+ "uint maskMsb = (1u << (bits - 1));",
+ "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;",
+ "uint baseMask = ~insertMask;",
+ "return (base & baseMask) | ((insert << offset) & insertMask);"
+ ]
+ },
+ {
+ "op":"bitfieldInsert",
+ "return_type":"uint3",
+ "args":[
+ "uint3 base",
+ "uint3 insert",
+ "int offset",
+ "int bits"
+ ],
+ "body":[
+ "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
+ "{",
+ " return base;",
+ "}",
+ "uint maskMsb = (1u << (bits - 1));",
+ "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;",
+ "uint baseMask = ~insertMask;",
+ "return (base & baseMask) | ((insert << offset) & insertMask);"
+ ]
+ },
+ {
+ "op":"bitfieldInsert",
+ "return_type":"uint4",
+ "args":[
+ "uint4 base",
+ "uint4 insert",
+ "int offset",
+ "int bits"
+ ],
+ "body":[
+ "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
+ "{",
+ " return base;",
+ "}",
+ "uint maskMsb = (1u << (bits - 1));",
+ "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;",
+ "uint baseMask = ~insertMask;",
+ "return (base & baseMask) | ((insert << offset) & insertMask);"
+ ]
+ },
+ {
+ "op":"bitfieldInsert",
+ "return_type":"int",
+ "args":[
+ "int base",
+ "int insert",
+ "int offset",
+ "int bits"
+ ],
+ "body":[
+ "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
+ "{",
+ " return base;",
+ "}",
+ "uint maskMsb = (1u << (bits - 1));",
+ "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;",
+ "uint baseMask = ~insertMask;",
+ "uint resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & ",
+ " insertMask);",
+ "return asint(resultUnsigned);"
+ ]
+ },
+ {
+ "op":"bitfieldInsert",
+ "return_type":"int2",
+ "args":[
+ "int2 base",
+ "int2 insert",
+ "int offset",
+ "int bits"
+ ],
+ "body":[
+ "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
+ "{",
+ " return base;",
+ "}",
+ "uint maskMsb = (1u << (bits - 1));",
+ "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;",
+ "uint baseMask = ~insertMask;",
+ "uint2 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & ",
+ " insertMask);",
+ "return asint(resultUnsigned);"
+ ]
+ },
+ {
+ "op":"bitfieldInsert",
+ "return_type":"int3",
+ "args":[
+ "int3 base",
+ "int3 insert",
+ "int offset",
+ "int bits"
+ ],
+ "body":[
+ "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
+ "{",
+ " return base;",
+ "}",
+ "uint maskMsb = (1u << (bits - 1));",
+ "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;",
+ "uint baseMask = ~insertMask;",
+ "uint3 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & ",
+ " insertMask);",
+ "return asint(resultUnsigned);"
+ ]
+ },
+ {
+ "op":"bitfieldInsert",
+ "return_type":"int4",
+ "args":[
+ "int4 base",
+ "int4 insert",
+ "int offset",
+ "int bits"
+ ],
+ "body":[
+ "if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)",
+ "{",
+ " return base;",
+ "}",
+ "uint maskMsb = (1u << (bits - 1));",
+ "uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;",
+ "uint baseMask = ~insertMask;",
+ "uint4 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & ",
+ "insertMask);",
+ "return asint(resultUnsigned);"
+ ]
+ },
+ {
+ "op":"uaddCarry",
+ "return_type":"uint",
+ "args":[
+ "uint x",
+ "uint y",
+ "out uint carry"
+ ],
+ "body":[
+ "carry = uint(x > (0xffffffffu - y));",
+ "return x + y;"
+ ]
+ },
+ {
+ "op":"uaddCarry",
+ "return_type":"uint2",
+ "args":[
+ "uint2 x",
+ "uint2 y",
+ "out uint2 carry"
+ ],
+ "body":[
+ "carry = uint2(x > (0xffffffffu - y));",
+ "return x + y;"
+ ]
+ },
+ {
+ "op":"uaddCarry",
+ "return_type":"uint3",
+ "args":[
+ "uint3 x",
+ "uint3 y",
+ "out uint3 carry"
+ ],
+ "body":[
+ "carry = uint3(x > (0xffffffffu - y));",
+ "return x + y;"
+ ]
+ },
+ {
+ "op":"uaddCarry",
+ "return_type":"uint4",
+ "args":[
+ "uint4 x",
+ "uint4 y",
+ "out uint4 carry"
+ ],
+ "body":[
+ "carry = uint4(x > (0xffffffffu - y));",
+ "return x + y;"
+ ]
+ },
+ {
+ "op":"usubBorrow",
+ "return_type":"uint",
+ "args":[
+ "uint x",
+ "uint y",
+ "out uint borrow"
+ ],
+ "body":[
+ "borrow = uint(x < y);",
+ "return x - y;"
+ ]
+ },
+ {
+ "op":"usubBorrow",
+ "return_type":"uint2",
+ "args":[
+ "uint2 x",
+ "uint2 y",
+ "out uint2 borrow"
+ ],
+ "body":[
+ "borrow = uint2(x < y);",
+ "return x - y;"
+ ]
+ },
+ {
+ "op":"usubBorrow",
+ "return_type":"uint3",
+ "args":[
+ "uint3 x",
+ "uint3 y",
+ "out uint3 borrow"
+ ],
+ "body":[
+ "borrow = uint3(x < y);",
+ "return x - y;"
+ ]
+ },
+ {
+ "op":"usubBorrow",
+ "return_type":"uint4",
+ "args":[
+ "uint4 x",
+ "uint4 y",
+ "out uint4 borrow"
+ ],
+ "body":[
+ "borrow = uint4(x < y);",
+ "return x - y;"
+ ]
+ }
+]
diff --git a/src/3rdparty/angle/src/compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp b/src/3rdparty/angle/src/compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp
new file mode 100644
index 0000000000..288da5e0f5
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp
@@ -0,0 +1,859 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_emulated_builtin_function_tables.py using data from
+// emulated_builtin_function_data_hlsl.json.
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// emulated_builtin_functions_hlsl:
+// HLSL code for emulating GLSL builtin functions not present in HLSL.
+
+#include "compiler/translator/BuiltInFunctionEmulator.h"
+
+namespace sh
+{
+
+namespace
+{
+
+struct FunctionPair
+{
+ constexpr FunctionPair(const MiniFunctionId &idIn, const char *bodyIn) : id(idIn), body(bodyIn)
+ {
+ }
+
+ MiniFunctionId id;
+ const char *body;
+};
+
+constexpr FunctionPair g_hlslFunctions[] = {
+ {{EOpMod, ParamType::Float1, ParamType::Float1},
+ "float mod_emu(float x, float y)\n"
+ "{\n"
+ " return x - y * floor(x / y);\n"
+ "}\n"},
+ {{EOpMod, ParamType::Float2, ParamType::Float2},
+ "float2 mod_emu(float2 x, float2 y)\n"
+ "{\n"
+ " return x - y * floor(x / y);\n"
+ "}\n"},
+ {{EOpMod, ParamType::Float2, ParamType::Float1},
+ "float2 mod_emu(float2 x, float y)\n"
+ "{\n"
+ " return x - y * floor(x / y);\n"
+ "}\n"},
+ {{EOpMod, ParamType::Float3, ParamType::Float3},
+ "float3 mod_emu(float3 x, float3 y)\n"
+ "{\n"
+ " return x - y * floor(x / y);\n"
+ "}\n"},
+ {{EOpMod, ParamType::Float3, ParamType::Float1},
+ "float3 mod_emu(float3 x, float y)\n"
+ "{\n"
+ " return x - y * floor(x / y);\n"
+ "}\n"},
+ {{EOpMod, ParamType::Float4, ParamType::Float4},
+ "float4 mod_emu(float4 x, float4 y)\n"
+ "{\n"
+ " return x - y * floor(x / y);\n"
+ "}\n"},
+ {{EOpMod, ParamType::Float4, ParamType::Float1},
+ "float4 mod_emu(float4 x, float y)\n"
+ "{\n"
+ " return x - y * floor(x / y);\n"
+ "}\n"},
+ {{EOpFrexp, ParamType::Float1, ParamType::Int1},
+ "float frexp_emu(float x, out int exp)\n"
+ "{\n"
+ " float fexp;\n"
+ " float mantissa = frexp(abs(x), fexp) * sign(x);\n"
+ " exp = int(fexp);\n"
+ " return mantissa;\n"
+ "}\n"},
+ {{EOpFrexp, ParamType::Float2, ParamType::Int2},
+ "float2 frexp_emu(float2 x, out int2 exp)\n"
+ "{\n"
+ " float2 fexp;\n"
+ " float2 mantissa = frexp(abs(x), fexp) * sign(x);\n"
+ " exp = int2(fexp);\n"
+ " return mantissa;\n"
+ "}\n"},
+ {{EOpFrexp, ParamType::Float3, ParamType::Int3},
+ "float3 frexp_emu(float3 x, out int3 exp)\n"
+ "{\n"
+ " float3 fexp;\n"
+ " float3 mantissa = frexp(abs(x), fexp) * sign(x);\n"
+ " exp = int3(fexp);\n"
+ " return mantissa;\n"
+ "}\n"},
+ {{EOpFrexp, ParamType::Float4, ParamType::Int4},
+ "float4 frexp_emu(float4 x, out int4 exp)\n"
+ "{\n"
+ " float4 fexp;\n"
+ " float4 mantissa = frexp(abs(x), fexp) * sign(x);\n"
+ " exp = int4(fexp);\n"
+ " return mantissa;\n"
+ "}\n"},
+ {{EOpLdexp, ParamType::Float1, ParamType::Int1},
+ "float ldexp_emu(float x, int exp)\n"
+ "{\n"
+ " return ldexp(x, float(exp));\n"
+ "}\n"},
+ {{EOpLdexp, ParamType::Float2, ParamType::Int2},
+ "float2 ldexp_emu(float2 x, int2 exp)\n"
+ "{\n"
+ " return ldexp(x, float2(exp));\n"
+ "}\n"},
+ {{EOpLdexp, ParamType::Float3, ParamType::Int3},
+ "float3 ldexp_emu(float3 x, int3 exp)\n"
+ "{\n"
+ " return ldexp(x, float3(exp));\n"
+ "}\n"},
+ {{EOpLdexp, ParamType::Float4, ParamType::Int4},
+ "float4 ldexp_emu(float4 x, int4 exp)\n"
+ "{\n"
+ " return ldexp(x, float4(exp));\n"
+ "}\n"},
+ {{EOpFaceforward, ParamType::Float1, ParamType::Float1, ParamType::Float1},
+ "float faceforward_emu(float N, float I, float Nref)\n"
+ "{\n"
+ " if(dot(Nref, I) >= 0)\n"
+ " {\n"
+ " return -N;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " return N;\n"
+ " }\n"
+ "}\n"},
+ {{EOpFaceforward, ParamType::Float2, ParamType::Float2, ParamType::Float2},
+ "float2 faceforward_emu(float2 N, float2 I, float2 Nref)\n"
+ "{\n"
+ " if(dot(Nref, I) >= 0)\n"
+ " {\n"
+ " return -N;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " return N;\n"
+ " }\n"
+ "}\n"},
+ {{EOpFaceforward, ParamType::Float3, ParamType::Float3, ParamType::Float3},
+ "float3 faceforward_emu(float3 N, float3 I, float3 Nref)\n"
+ "{\n"
+ " if(dot(Nref, I) >= 0)\n"
+ " {\n"
+ " return -N;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " return N;\n"
+ " }\n"
+ "}\n"},
+ {{EOpFaceforward, ParamType::Float4, ParamType::Float4, ParamType::Float4},
+ "float4 faceforward_emu(float4 N, float4 I, float4 Nref)\n"
+ "{\n"
+ " if(dot(Nref, I) >= 0)\n"
+ " {\n"
+ " return -N;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " return N;\n"
+ " }\n"
+ "}\n"},
+ {{EOpAtan, ParamType::Float1, ParamType::Float1},
+ "float atan_emu(float y, float x)\n"
+ "{\n"
+ " if(x == 0 && y == 0) x = 1;\n"
+ " return atan2(y, x);\n"
+ "}\n"},
+ {{EOpAtan, ParamType::Float2, ParamType::Float2},
+ "float2 atan_emu(float2 y, float2 x)\n"
+ "{\n"
+ " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
+ " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
+ " return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n"
+ "}\n"},
+ {{EOpAtan, ParamType::Float3, ParamType::Float3},
+ "float3 atan_emu(float3 y, float3 x)\n"
+ "{\n"
+ " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
+ " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
+ " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
+ " return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n"
+ "}\n"},
+ {{EOpAtan, ParamType::Float4, ParamType::Float4},
+ "float4 atan_emu(float4 y, float4 x)\n"
+ "{\n"
+ " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
+ " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
+ " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
+ " if(x[3] == 0 && y[3] == 0) x[3] = 1;\n"
+ " return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], \n"
+ " x[2]), atan2(y[3], x[3]));\n"
+ "}\n"},
+ {{EOpAsinh, ParamType::Float1},
+ "float asinh_emu(in float x)\n"
+ "{\n"
+ " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
+ "}\n"},
+ {{EOpAsinh, ParamType::Float2},
+ "float2 asinh_emu(in float2 x)\n"
+ "{\n"
+ " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
+ "}\n"},
+ {{EOpAsinh, ParamType::Float3},
+ "float3 asinh_emu(in float3 x)\n"
+ "{\n"
+ " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
+ "}\n"},
+ {{EOpAsinh, ParamType::Float4},
+ "float4 asinh_emu(in float4 x)\n"
+ "{\n"
+ " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
+ "}\n"},
+ {{EOpAcosh, ParamType::Float1},
+ "float acosh_emu(in float x)\n"
+ "{\n"
+ " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
+ "}\n"},
+ {{EOpAcosh, ParamType::Float2},
+ "float2 acosh_emu(in float2 x)\n"
+ "{\n"
+ " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
+ "}\n"},
+ {{EOpAcosh, ParamType::Float3},
+ "float3 acosh_emu(in float3 x)\n"
+ "{\n"
+ " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
+ "}\n"},
+ {{EOpAcosh, ParamType::Float4},
+ "float4 acosh_emu(in float4 x)\n"
+ "{\n"
+ " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
+ "}\n"},
+ {{EOpAtanh, ParamType::Float1},
+ "float atanh_emu(in float x)\n"
+ "{\n"
+ " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
+ "}\n"},
+ {{EOpAtanh, ParamType::Float2},
+ "float2 atanh_emu(in float2 x)\n"
+ "{\n"
+ " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
+ "}\n"},
+ {{EOpAtanh, ParamType::Float3},
+ "float3 atanh_emu(in float3 x)\n"
+ "{\n"
+ " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
+ "}\n"},
+ {{EOpAtanh, ParamType::Float4},
+ "float4 atanh_emu(in float4 x)\n"
+ "{\n"
+ " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
+ "}\n"},
+ {{EOpRoundEven, ParamType::Float1},
+ "float roundEven_emu(in float x)\n"
+ "{\n"
+ " return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);\n"
+ "}\n"},
+ {{EOpRoundEven, ParamType::Float2},
+ "float2 roundEven_emu(in float2 x)\n"
+ "{\n"
+ " float2 v;\n"
+ " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n"
+ " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
+ " return v;\n"
+ "}\n"},
+ {{EOpRoundEven, ParamType::Float3},
+ "float3 roundEven_emu(in float3 x)\n"
+ "{\n"
+ " float3 v;\n"
+ " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n"
+ " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
+ " v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n"
+ " return v;\n"
+ "}\n"},
+ {{EOpRoundEven, ParamType::Float4},
+ "float4 roundEven_emu(in float4 x)\n"
+ "{\n"
+ " float4 v;\n"
+ " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n"
+ " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
+ " v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n"
+ " v[3] = (frac(x[3]) == 0.5 && trunc(x[3]) % 2.0 == 0.0) ? trunc(x[3]) : round(x[3]);\n"
+ " return v;\n"
+ "}\n"},
+ {{EOpPackSnorm2x16, ParamType::Float2},
+ "int webgl_toSnorm16(in float x) {\n"
+ " return int(round(clamp(x, -1.0, 1.0) * 32767.0));\n"
+ "}\n"
+ "uint packSnorm2x16_emu(in float2 v)\n"
+ "{\n"
+ " int x = webgl_toSnorm16(v.x);\n"
+ " int y = webgl_toSnorm16(v.y);\n"
+ " return (asuint(y) << 16) | (asuint(x) & 0xffffu);\n"
+ "}\n"},
+ {{EOpPackUnorm2x16, ParamType::Float2},
+ "uint webgl_toUnorm16(in float x) {\n"
+ " return uint(round(clamp(x, 0.0, 1.0) * 65535.0));\n"
+ "}\n"
+ "uint packUnorm2x16_emu(in float2 v)\n"
+ "{\n"
+ " uint x = webgl_toUnorm16(v.x);\n"
+ " uint y = webgl_toUnorm16(v.y);\n"
+ " return (y << 16) | x;\n"
+ "}\n"},
+ {{EOpPackHalf2x16, ParamType::Float2},
+ "uint packHalf2x16_emu(in float2 v)\n"
+ "{\n"
+ " uint x = f32tof16(v.x);\n"
+ " uint y = f32tof16(v.y);\n"
+ " return (y << 16) | x;\n"
+ "}\n"},
+ {{EOpUnpackSnorm2x16, ParamType::Uint1},
+ "float webgl_fromSnorm16(in uint x) {\n"
+ " int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);\n"
+ " return clamp(float(xi) / 32767.0, -1.0, 1.0);\n"
+ "}\n"
+ "float2 unpackSnorm2x16_emu(in uint u)\n"
+ "{\n"
+ " uint y = (u >> 16);\n"
+ " uint x = u;\n"
+ " return float2(webgl_fromSnorm16(x), webgl_fromSnorm16(y));\n"
+ "}\n"},
+ {{EOpUnpackUnorm2x16, ParamType::Uint1},
+ "float webgl_fromUnorm16(in uint x) {\n"
+ " return float(x) / 65535.0;\n"
+ "}\n"
+ "float2 unpackUnorm2x16_emu(in uint u)\n"
+ "{\n"
+ " uint y = (u >> 16);\n"
+ " uint x = u & 0xffffu;\n"
+ " return float2(webgl_fromUnorm16(x), webgl_fromUnorm16(y));\n"
+ "}\n"},
+ {{EOpUnpackHalf2x16, ParamType::Uint1},
+ "float2 unpackHalf2x16_emu(in uint u)\n"
+ "{\n"
+ " uint y = (u >> 16);\n"
+ " uint x = u & 0xffffu;\n"
+ " return float2(f16tof32(x), f16tof32(y));\n"
+ "}\n"},
+ {{EOpPackSnorm4x8, ParamType::Float4},
+ "int webgl_toSnorm8(in float x) {\n"
+ " return int(round(clamp(x, -1.0, 1.0) * 127.0));\n"
+ "}\n"
+ "uint packSnorm4x8_emu(in float4 v)\n"
+ "{\n"
+ " int x = webgl_toSnorm8(v.x);\n"
+ " int y = webgl_toSnorm8(v.y);\n"
+ " int z = webgl_toSnorm8(v.z);\n"
+ " int w = webgl_toSnorm8(v.w);\n"
+ " return ((asuint(w) & 0xffu) << 24) | ((asuint(z) & 0xffu) << 16) \n"
+ " | ((asuint(y) & 0xffu) << 8) | (asuint(x) & 0xffu);\n"
+ "}\n"},
+ {{EOpPackUnorm4x8, ParamType::Float4},
+ "uint webgl_toUnorm8(in float x) {\n"
+ " return uint(round(clamp(x, 0.0, 1.0) * 255.0));\n"
+ "}\n"
+ "uint packUnorm4x8_emu(in float4 v)\n"
+ "{\n"
+ " uint x = webgl_toUnorm8(v.x);\n"
+ " uint y = webgl_toUnorm8(v.y);\n"
+ " uint z = webgl_toUnorm8(v.z);\n"
+ " uint w = webgl_toUnorm8(v.w);\n"
+ " return (w << 24) | (z << 16) | (y << 8) | x;\n"
+ "}\n"},
+ {{EOpUnpackSnorm4x8, ParamType::Uint1},
+ "float webgl_fromSnorm8(in uint x) {\n"
+ " int xi = asint(x & 0x7fu) - asint(x & 0x80u);\n"
+ " return clamp(float(xi) / 127.0, -1.0, 1.0);\n"
+ "}\n"
+ "float4 unpackSnorm4x8_emu(in uint u)\n"
+ "{\n"
+ " uint w = (u >> 24);\n"
+ " uint z = (u >> 16);\n"
+ " uint y = (u >> 8);\n"
+ " uint x = u;\n"
+ " return float4(webgl_fromSnorm8(x), webgl_fromSnorm8(y), \n"
+ " webgl_fromSnorm8(z), webgl_fromSnorm8(w));\n"
+ "}\n"},
+ {{EOpUnpackUnorm4x8, ParamType::Uint1},
+ "float webgl_fromUnorm8(in uint x) {\n"
+ " return float(x) / 255.0;\n"
+ "}\n"
+ "float4 unpackUnorm4x8_emu(in uint u)\n"
+ "{\n"
+ " uint w = (u >> 24) & 0xffu;\n"
+ " uint z = (u >> 16) & 0xffu;\n"
+ " uint y = (u >> 8) & 0xffu;\n"
+ " uint x = u & 0xffu;\n"
+ " return float4(webgl_fromUnorm8(x), webgl_fromUnorm8(y), \n"
+ " webgl_fromUnorm8(z), webgl_fromUnorm8(w));\n"
+ "}\n"},
+ // The matrix resulting from outer product needs to be transposed
+ // (matrices are stored as transposed to simplify element access in HLSL).
+ // So the function should return transpose(c * r) where c is a column vector
+ // and r is a row vector. This can be simplified by using the following
+ // formula:
+ // transpose(c * r) = transpose(r) * transpose(c)
+ // transpose(r) and transpose(c) are in a sense free, since to get the
+ // transpose of r, we simply can build a column matrix out of the original
+ // vector instead of a row matrix.
+ {{EOpOuterProduct, ParamType::Float2, ParamType::Float2},
+ "float2x2 outerProduct_emu(in float2 c, in float2 r)\n"
+ "{\n"
+ " return mul(float2x1(r), float1x2(c));\n"
+ "}\n"},
+ {{EOpOuterProduct, ParamType::Float3, ParamType::Float3},
+ "float3x3 outerProduct_emu(in float3 c, in float3 r)\n"
+ "{\n"
+ " return mul(float3x1(r), float1x3(c));\n"
+ "}\n"},
+ {{EOpOuterProduct, ParamType::Float4, ParamType::Float4},
+ "float4x4 outerProduct_emu(in float4 c, in float4 r)\n"
+ "{\n"
+ " return mul(float4x1(r), float1x4(c));\n"
+ "}\n"},
+ {{EOpOuterProduct, ParamType::Float3, ParamType::Float2},
+ "float2x3 outerProduct_emu(in float3 c, in float2 r)\n"
+ "{\n"
+ " return mul(float2x1(r), float1x3(c));\n"
+ "}\n"},
+ {{EOpOuterProduct, ParamType::Float2, ParamType::Float3},
+ "float3x2 outerProduct_emu(in float2 c, in float3 r)\n"
+ "{\n"
+ " return mul(float3x1(r), float1x2(c));\n"
+ "}\n"},
+ {{EOpOuterProduct, ParamType::Float4, ParamType::Float2},
+ "float2x4 outerProduct_emu(in float4 c, in float2 r)\n"
+ "{\n"
+ " return mul(float2x1(r), float1x4(c));\n"
+ "}\n"},
+ {{EOpOuterProduct, ParamType::Float2, ParamType::Float4},
+ "float4x2 outerProduct_emu(in float2 c, in float4 r)\n"
+ "{\n"
+ " return mul(float4x1(r), float1x2(c));\n"
+ "}\n"},
+ {{EOpOuterProduct, ParamType::Float4, ParamType::Float3},
+ "float3x4 outerProduct_emu(in float4 c, in float3 r)\n"
+ "{\n"
+ " return mul(float3x1(r), float1x4(c));\n"
+ "}\n"},
+ {{EOpOuterProduct, ParamType::Float3, ParamType::Float4},
+ "float4x3 outerProduct_emu(in float3 c, in float4 r)\n"
+ "{\n"
+ " return mul(float4x1(r), float1x3(c));\n"
+ "}\n"},
+ // Remember here that the parameter matrix is actually the transpose
+ // of the matrix that we're trying to invert, and the resulting matrix
+ // should also be the transpose of the inverse.
+ // When accessing the parameter matrix with m[a][b] it can be thought of so
+ // that a is the column and b is the row of the matrix that we're inverting.
+ // We calculate the inverse as the adjugate matrix divided by the
+ // determinant of the matrix being inverted. However, as the result needs
+ // to be transposed, we actually use of the transpose of the adjugate matrix
+ // which happens to be the cofactor matrix. That's stored in 'cof'.
+ // We don't need to care about divide-by-zero since results are undefined
+ // for singular or poorly-conditioned matrices.
+ {{EOpInverse, ParamType::Mat2},
+ "float2x2 inverse_emu(in float2x2 m)\n"
+ "{\n"
+ " float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };\n"
+ " return cof / determinant(transpose(m));\n"
+ "}\n"},
+ // cofAB is the cofactor for column A and row B.
+ {{EOpInverse, ParamType::Mat3},
+ "float3x3 inverse_emu(in float3x3 m)\n"
+ "{\n"
+ " float cof00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];\n"
+ " float cof01 = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]);\n"
+ " float cof02 = m[1][0] * m[2][1] - m[2][0] * m[1][1];\n"
+ " float cof10 = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]);\n"
+ " float cof11 = m[0][0] * m[2][2] - m[2][0] * m[0][2];\n"
+ " float cof12 = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]);\n"
+ " float cof20 = m[0][1] * m[1][2] - m[1][1] * m[0][2];\n"
+ " float cof21 = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]);\n"
+ " float cof22 = m[0][0] * m[1][1] - m[1][0] * m[0][1];\n"
+ " float3x3 cof = { cof00, cof10, cof20, cof01, cof11, cof21, cof02, cof12, cof22 };\n"
+ " return cof / determinant(transpose(m));\n"
+ "}\n"},
+ {{EOpInverse, ParamType::Mat4},
+ "float4x4 inverse_emu(in float4x4 m)\n"
+ "{\n"
+ " float cof00 = m[1][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[1][3] + m[3][1] * \n"
+ " m[1][2] * m[2][3]\n"
+ " - m[1][1] * m[3][2] * m[2][3] - m[2][1] * m[1][2] * m[3][3] - m[3][1] * m[2][2] * \n"
+ " m[1][3];\n"
+ " float cof01 = -(m[1][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[1][3] + m[3][0] * \n"
+ " m[1][2] * m[2][3]\n"
+ " - m[1][0] * m[3][2] * m[2][3] - m[2][0] * m[1][2] * m[3][3] - m[3][0] * m[2][2] * \n"
+ " m[1][3]);\n"
+ " float cof02 = m[1][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[1][3] + m[3][0] * \n"
+ " m[1][1] * m[2][3]\n"
+ " - m[1][0] * m[3][1] * m[2][3] - m[2][0] * m[1][1] * m[3][3] - m[3][0] * m[2][1] * \n"
+ " m[1][3];\n"
+ " float cof03 = -(m[1][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[1][2] + m[3][0] * \n"
+ " m[1][1] * m[2][2]\n"
+ " - m[1][0] * m[3][1] * m[2][2] - m[2][0] * m[1][1] * m[3][2] - m[3][0] * m[2][1] * \n"
+ " m[1][2]);\n"
+ " float cof10 = -(m[0][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[0][3] + m[3][1] * \n"
+ " m[0][2] * m[2][3]\n"
+ " - m[0][1] * m[3][2] * m[2][3] - m[2][1] * m[0][2] * m[3][3] - m[3][1] * m[2][2] * \n"
+ " m[0][3]);\n"
+ " float cof11 = m[0][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[0][3] + m[3][0] * \n"
+ " m[0][2] * m[2][3]\n"
+ " - m[0][0] * m[3][2] * m[2][3] - m[2][0] * m[0][2] * m[3][3] - m[3][0] * m[2][2] * \n"
+ " m[0][3];\n"
+ " float cof12 = -(m[0][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[0][3] + m[3][0] * \n"
+ " m[0][1] * m[2][3]\n"
+ " - m[0][0] * m[3][1] * m[2][3] - m[2][0] * m[0][1] * m[3][3] - m[3][0] * m[2][1] * \n"
+ " m[0][3]);\n"
+ " float cof13 = m[0][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[0][2] + m[3][0] * \n"
+ " m[0][1] * m[2][2]\n"
+ " - m[0][0] * m[3][1] * m[2][2] - m[2][0] * m[0][1] * m[3][2] - m[3][0] * m[2][1] * \n"
+ " m[0][2];\n"
+ " float cof20 = m[0][1] * m[1][2] * m[3][3] + m[1][1] * m[3][2] * m[0][3] + m[3][1] * \n"
+ " m[0][2] * m[1][3]\n"
+ " - m[0][1] * m[3][2] * m[1][3] - m[1][1] * m[0][2] * m[3][3] - m[3][1] * m[1][2] * \n"
+ " m[0][3];\n"
+ " float cof21 = -(m[0][0] * m[1][2] * m[3][3] + m[1][0] * m[3][2] * m[0][3] + m[3][0] * \n"
+ " m[0][2] * m[1][3]\n"
+ " - m[0][0] * m[3][2] * m[1][3] - m[1][0] * m[0][2] * m[3][3] - m[3][0] * m[1][2] * \n"
+ " m[0][3]);\n"
+ " float cof22 = m[0][0] * m[1][1] * m[3][3] + m[1][0] * m[3][1] * m[0][3] + m[3][0] * \n"
+ " m[0][1] * m[1][3]\n"
+ " - m[0][0] * m[3][1] * m[1][3] - m[1][0] * m[0][1] * m[3][3] - m[3][0] * m[1][1] * \n"
+ " m[0][3];\n"
+ " float cof23 = -(m[0][0] * m[1][1] * m[3][2] + m[1][0] * m[3][1] * m[0][2] + m[3][0] * \n"
+ " m[0][1] * m[1][2]\n"
+ " - m[0][0] * m[3][1] * m[1][2] - m[1][0] * m[0][1] * m[3][2] - m[3][0] * m[1][1] * \n"
+ " m[0][2]);\n"
+ " float cof30 = -(m[0][1] * m[1][2] * m[2][3] + m[1][1] * m[2][2] * m[0][3] + m[2][1] * \n"
+ " m[0][2] * m[1][3]\n"
+ " - m[0][1] * m[2][2] * m[1][3] - m[1][1] * m[0][2] * m[2][3] - m[2][1] * m[1][2] * \n"
+ " m[0][3]);\n"
+ " float cof31 = m[0][0] * m[1][2] * m[2][3] + m[1][0] * m[2][2] * m[0][3] + m[2][0] * \n"
+ " m[0][2] * m[1][3]\n"
+ " - m[0][0] * m[2][2] * m[1][3] - m[1][0] * m[0][2] * m[2][3] - m[2][0] * m[1][2] * \n"
+ " m[0][3];\n"
+ " float cof32 = -(m[0][0] * m[1][1] * m[2][3] + m[1][0] * m[2][1] * m[0][3] + m[2][0] * \n"
+ " m[0][1] * m[1][3]\n"
+ " - m[0][0] * m[2][1] * m[1][3] - m[1][0] * m[0][1] * m[2][3] - m[2][0] * m[1][1] * \n"
+ " m[0][3]);\n"
+ " float cof33 = m[0][0] * m[1][1] * m[2][2] + m[1][0] * m[2][1] * m[0][2] + m[2][0] * \n"
+ " m[0][1] * m[1][2]\n"
+ " - m[0][0] * m[2][1] * m[1][2] - m[1][0] * m[0][1] * m[2][2] - m[2][0] * m[1][1] * \n"
+ " m[0][2];\n"
+ " float4x4 cof = { cof00, cof10, cof20, cof30, cof01, cof11, cof21, cof31,\n"
+ " cof02, cof12, cof22, cof32, cof03, cof13, cof23, cof33 };\n"
+ " return cof / determinant(transpose(m));\n"
+ "}\n"},
+ // Emulate ESSL3 variant of mix that takes last argument as boolean vector.
+ // genType mix(genType x, genType y, genBType a): Selects which vector each returned component
+ // comes from. For a component of 'a' that is false, the corresponding component of 'x' is
+ // returned. For a component of 'a' that is true, the corresponding component of 'y' is
+ // returned.
+ {{EOpMix, ParamType::Float1, ParamType::Float1, ParamType::Bool1},
+ "float mix_emu(float x, float y, bool a)\n"
+ "{\n"
+ " return a ? y : x;\n"
+ "}\n"},
+ {{EOpMix, ParamType::Float2, ParamType::Float2, ParamType::Bool2},
+ "float2 mix_emu(float2 x, float2 y, bool2 a)\n"
+ "{\n"
+ " return a ? y : x;\n"
+ "}\n"},
+ {{EOpMix, ParamType::Float3, ParamType::Float3, ParamType::Bool3},
+ "float3 mix_emu(float3 x, float3 y, bool3 a)\n"
+ "{\n"
+ " return a ? y : x;\n"
+ "}\n"},
+ {{EOpMix, ParamType::Float4, ParamType::Float4, ParamType::Bool4},
+ "float4 mix_emu(float4 x, float4 y, bool4 a)\n"
+ "{\n"
+ " return a ? y : x;\n"
+ "}\n"},
+ {{EOpBitfieldExtract, ParamType::Uint1, ParamType::Int1, ParamType::Int1},
+ "uint bitfieldExtract_emu(uint value, int offset, int bits)\n"
+ "{\n"
+ " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+ " {\n"
+ " return 0u;\n"
+ " }\n"
+ " uint maskMsb = (1u << (bits - 1));\n"
+ " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+ " return (value & mask) >> offset;\n"
+ "}\n"},
+ {{EOpBitfieldExtract, ParamType::Uint2, ParamType::Int1, ParamType::Int1},
+ "uint2 bitfieldExtract_emu(uint2 value, int offset, int bits)\n"
+ "{\n"
+ " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+ " {\n"
+ " return uint2(0u, 0u);\n"
+ " }\n"
+ " uint maskMsb = (1u << (bits - 1));\n"
+ " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+ " return (value & mask) >> offset;\n"
+ "}\n"},
+ {{EOpBitfieldExtract, ParamType::Uint3, ParamType::Int1, ParamType::Int1},
+ "uint3 bitfieldExtract_emu(uint3 value, int offset, int bits)\n"
+ "{\n"
+ " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+ " {\n"
+ " return uint3(0u, 0u, 0u);\n"
+ " }\n"
+ " uint maskMsb = (1u << (bits - 1));\n"
+ " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+ " return (value & mask) >> offset;\n"
+ "}\n"},
+ {{EOpBitfieldExtract, ParamType::Uint4, ParamType::Int1, ParamType::Int1},
+ "uint4 bitfieldExtract_emu(uint4 value, int offset, int bits)\n"
+ "{\n"
+ " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+ " {\n"
+ " return uint4(0u, 0u, 0u, 0u);\n"
+ " }\n"
+ " uint maskMsb = (1u << (bits - 1));\n"
+ " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+ " return (value & mask) >> offset;\n"
+ "}\n"},
+ {{EOpBitfieldExtract, ParamType::Int1, ParamType::Int1, ParamType::Int1},
+ "int bitfieldExtract_emu(int value, int offset, int bits)\n"
+ "{\n"
+ " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+ " {\n"
+ " return 0;\n"
+ " }\n"
+ " uint maskMsb = (1u << (bits - 1));\n"
+ " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+ " uint resultUnsigned = (asuint(value) & mask) >> offset;\n"
+ " if (bits != 32 && (resultUnsigned & maskMsb) != 0)\n"
+ " {\n"
+ " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n"
+ " resultUnsigned |= higherBitsMask;\n"
+ " }\n"
+ " return asint(resultUnsigned);\n"
+ "}\n"},
+ {{EOpBitfieldExtract, ParamType::Int2, ParamType::Int1, ParamType::Int1},
+ "int2 bitfieldExtract_emu(int2 value, int offset, int bits)\n"
+ "{\n"
+ " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+ " {\n"
+ " return int2(0, 0);\n"
+ " }\n"
+ " uint maskMsb = (1u << (bits - 1));\n"
+ " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+ " uint2 resultUnsigned = (asuint(value) & mask) >> offset;\n"
+ " if (bits != 32)\n"
+ " {\n"
+ " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n"
+ " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;\n"
+ " }\n"
+ " return asint(resultUnsigned);\n"
+ "}\n"},
+ {{EOpBitfieldExtract, ParamType::Int3, ParamType::Int1, ParamType::Int1},
+ "int3 bitfieldExtract_emu(int3 value, int offset, int bits)\n"
+ "{\n"
+ " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+ " {\n"
+ " return int3(0, 0, 0);\n"
+ " }\n"
+ " uint maskMsb = (1u << (bits - 1));\n"
+ " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+ " uint3 resultUnsigned = (asuint(value) & mask) >> offset;\n"
+ " if (bits != 32)\n"
+ " {\n"
+ " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n"
+ " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;\n"
+ " }\n"
+ " return asint(resultUnsigned);\n"
+ "}\n"},
+ {{EOpBitfieldExtract, ParamType::Int4, ParamType::Int1, ParamType::Int1},
+ "int4 bitfieldExtract_emu(int4 value, int offset, int bits)\n"
+ "{\n"
+ " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+ " {\n"
+ " return int4(0, 0, 0, 0);\n"
+ " }\n"
+ " uint maskMsb = (1u << (bits - 1));\n"
+ " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+ " uint4 resultUnsigned = (asuint(value) & mask) >> offset;\n"
+ " if (bits != 32)\n"
+ " {\n"
+ " uint higherBitsMask = ((1u << (32 - bits)) - 1u) << bits;\n"
+ " resultUnsigned |= ((resultUnsigned & maskMsb) >> (bits - 1)) * higherBitsMask;\n"
+ " }\n"
+ " return asint(resultUnsigned);\n"
+ "}\n"},
+ {{EOpBitfieldInsert, ParamType::Uint1, ParamType::Uint1, ParamType::Int1, ParamType::Int1},
+ "uint bitfieldInsert_emu(uint base, uint insert, int offset, int bits)\n"
+ "{\n"
+ " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+ " {\n"
+ " return base;\n"
+ " }\n"
+ " uint maskMsb = (1u << (bits - 1));\n"
+ " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+ " uint baseMask = ~insertMask;\n"
+ " return (base & baseMask) | ((insert << offset) & insertMask);\n"
+ "}\n"},
+ {{EOpBitfieldInsert, ParamType::Uint2, ParamType::Uint2, ParamType::Int1, ParamType::Int1},
+ "uint2 bitfieldInsert_emu(uint2 base, uint2 insert, int offset, int bits)\n"
+ "{\n"
+ " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+ " {\n"
+ " return base;\n"
+ " }\n"
+ " uint maskMsb = (1u << (bits - 1));\n"
+ " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+ " uint baseMask = ~insertMask;\n"
+ " return (base & baseMask) | ((insert << offset) & insertMask);\n"
+ "}\n"},
+ {{EOpBitfieldInsert, ParamType::Uint3, ParamType::Uint3, ParamType::Int1, ParamType::Int1},
+ "uint3 bitfieldInsert_emu(uint3 base, uint3 insert, int offset, int bits)\n"
+ "{\n"
+ " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+ " {\n"
+ " return base;\n"
+ " }\n"
+ " uint maskMsb = (1u << (bits - 1));\n"
+ " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+ " uint baseMask = ~insertMask;\n"
+ " return (base & baseMask) | ((insert << offset) & insertMask);\n"
+ "}\n"},
+ {{EOpBitfieldInsert, ParamType::Uint4, ParamType::Uint4, ParamType::Int1, ParamType::Int1},
+ "uint4 bitfieldInsert_emu(uint4 base, uint4 insert, int offset, int bits)\n"
+ "{\n"
+ " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+ " {\n"
+ " return base;\n"
+ " }\n"
+ " uint maskMsb = (1u << (bits - 1));\n"
+ " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+ " uint baseMask = ~insertMask;\n"
+ " return (base & baseMask) | ((insert << offset) & insertMask);\n"
+ "}\n"},
+ {{EOpBitfieldInsert, ParamType::Int1, ParamType::Int1, ParamType::Int1, ParamType::Int1},
+ "int bitfieldInsert_emu(int base, int insert, int offset, int bits)\n"
+ "{\n"
+ " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+ " {\n"
+ " return base;\n"
+ " }\n"
+ " uint maskMsb = (1u << (bits - 1));\n"
+ " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+ " uint baseMask = ~insertMask;\n"
+ " uint resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & \n"
+ " insertMask);\n"
+ " return asint(resultUnsigned);\n"
+ "}\n"},
+ {{EOpBitfieldInsert, ParamType::Int2, ParamType::Int2, ParamType::Int1, ParamType::Int1},
+ "int2 bitfieldInsert_emu(int2 base, int2 insert, int offset, int bits)\n"
+ "{\n"
+ " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+ " {\n"
+ " return base;\n"
+ " }\n"
+ " uint maskMsb = (1u << (bits - 1));\n"
+ " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+ " uint baseMask = ~insertMask;\n"
+ " uint2 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & \n"
+ " insertMask);\n"
+ " return asint(resultUnsigned);\n"
+ "}\n"},
+ {{EOpBitfieldInsert, ParamType::Int3, ParamType::Int3, ParamType::Int1, ParamType::Int1},
+ "int3 bitfieldInsert_emu(int3 base, int3 insert, int offset, int bits)\n"
+ "{\n"
+ " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+ " {\n"
+ " return base;\n"
+ " }\n"
+ " uint maskMsb = (1u << (bits - 1));\n"
+ " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+ " uint baseMask = ~insertMask;\n"
+ " uint3 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & \n"
+ " insertMask);\n"
+ " return asint(resultUnsigned);\n"
+ "}\n"},
+ {{EOpBitfieldInsert, ParamType::Int4, ParamType::Int4, ParamType::Int1, ParamType::Int1},
+ "int4 bitfieldInsert_emu(int4 base, int4 insert, int offset, int bits)\n"
+ "{\n"
+ " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
+ " {\n"
+ " return base;\n"
+ " }\n"
+ " uint maskMsb = (1u << (bits - 1));\n"
+ " uint insertMask = ((maskMsb - 1u) | maskMsb) << offset;\n"
+ " uint baseMask = ~insertMask;\n"
+ " uint4 resultUnsigned = (asuint(base) & baseMask) | ((asuint(insert) << offset) & \n"
+ " insertMask);\n"
+ " return asint(resultUnsigned);\n"
+ "}\n"},
+ {{EOpUaddCarry, ParamType::Uint1, ParamType::Uint1, ParamType::Uint1},
+ "uint uaddCarry_emu(uint x, uint y, out uint carry)\n"
+ "{\n"
+ " carry = uint(x > (0xffffffffu - y));\n"
+ " return x + y;\n"
+ "}\n"},
+ {{EOpUaddCarry, ParamType::Uint2, ParamType::Uint2, ParamType::Uint2},
+ "uint2 uaddCarry_emu(uint2 x, uint2 y, out uint2 carry)\n"
+ "{\n"
+ " carry = uint2(x > (0xffffffffu - y));\n"
+ " return x + y;\n"
+ "}\n"},
+ {{EOpUaddCarry, ParamType::Uint3, ParamType::Uint3, ParamType::Uint3},
+ "uint3 uaddCarry_emu(uint3 x, uint3 y, out uint3 carry)\n"
+ "{\n"
+ " carry = uint3(x > (0xffffffffu - y));\n"
+ " return x + y;\n"
+ "}\n"},
+ {{EOpUaddCarry, ParamType::Uint4, ParamType::Uint4, ParamType::Uint4},
+ "uint4 uaddCarry_emu(uint4 x, uint4 y, out uint4 carry)\n"
+ "{\n"
+ " carry = uint4(x > (0xffffffffu - y));\n"
+ " return x + y;\n"
+ "}\n"},
+ {{EOpUsubBorrow, ParamType::Uint1, ParamType::Uint1, ParamType::Uint1},
+ "uint usubBorrow_emu(uint x, uint y, out uint borrow)\n"
+ "{\n"
+ " borrow = uint(x < y);\n"
+ " return x - y;\n"
+ "}\n"},
+ {{EOpUsubBorrow, ParamType::Uint2, ParamType::Uint2, ParamType::Uint2},
+ "uint2 usubBorrow_emu(uint2 x, uint2 y, out uint2 borrow)\n"
+ "{\n"
+ " borrow = uint2(x < y);\n"
+ " return x - y;\n"
+ "}\n"},
+ {{EOpUsubBorrow, ParamType::Uint3, ParamType::Uint3, ParamType::Uint3},
+ "uint3 usubBorrow_emu(uint3 x, uint3 y, out uint3 borrow)\n"
+ "{\n"
+ " borrow = uint3(x < y);\n"
+ " return x - y;\n"
+ "}\n"},
+ {{EOpUsubBorrow, ParamType::Uint4, ParamType::Uint4, ParamType::Uint4},
+ "uint4 usubBorrow_emu(uint4 x, uint4 y, out uint4 borrow)\n"
+ "{\n"
+ " borrow = uint4(x < y);\n"
+ " return x - y;\n"
+ "}\n"},
+};
+} // anonymous namespace
+
+const char *FindHLSLFunction(const FunctionId &functionID)
+{
+ for (size_t index = 0; index < ArraySize(g_hlslFunctions); ++index)
+ {
+ const auto &function = g_hlslFunctions[index];
+ if (function.id == functionID)
+ {
+ return function.body;
+ }
+ }
+
+ return nullptr;
+}
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.h b/src/3rdparty/angle/src/compiler/translator/glslang.h
index 0555e96d45..e54c31ba3e 100644
--- a/src/3rdparty/angle/src/compiler/translator/glslang.h
+++ b/src/3rdparty/angle/src/compiler/translator/glslang.h
@@ -7,14 +7,18 @@
#ifndef COMPILER_TRANSLATOR_GLSLANG_H_
#define COMPILER_TRANSLATOR_GLSLANG_H_
+namespace sh
+{
class TParseContext;
-extern int glslang_initialize(TParseContext* context);
-extern int glslang_finalize(TParseContext* context);
+}
+
+extern int glslang_initialize(sh::TParseContext *context);
+extern int glslang_finalize(sh::TParseContext *context);
extern int glslang_scan(size_t count,
- const char* const string[],
+ const char *const string[],
const int length[],
- TParseContext* context);
-extern int glslang_parse(TParseContext* context);
+ sh::TParseContext *context);
+extern int glslang_parse(sh::TParseContext *context);
-#endif // COMPILER_TRANSLATOR_GLSLANG_H_
+#endif // COMPILER_TRANSLATOR_GLSLANG_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.l b/src/3rdparty/angle/src/compiler/translator/glslang.l
index d09358dd8a..858ffd96bb 100644
--- a/src/3rdparty/angle/src/compiler/translator/glslang.l
+++ b/src/3rdparty/angle/src/compiler/translator/glslang.l
@@ -22,6 +22,8 @@ WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp).
// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
+/* clang-format off */
+
// Ignore errors in auto-generated code.
#if defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wunused-function"
@@ -44,6 +46,9 @@ WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp).
#include "compiler/preprocessor/Token.h"
#include "compiler/translator/util.h"
#include "compiler/translator/length_limits.h"
+
+using namespace sh;
+
#include "glslang_tab.h"
/* windows only pragma */
@@ -71,10 +76,16 @@ static int reserved_word(yyscan_t yyscanner);
static int ES2_reserved_ES3_keyword(TParseContext *context, int token);
static int ES2_keyword_ES3_reserved(TParseContext *context, int token);
static int ES2_ident_ES3_keyword(TParseContext *context, int token);
+static int ES2_ident_ES3_keyword_multiview_keyword(TParseContext *context, int token);
+static int ES2_ident_ES3_reserved_ES3_1_keyword(TParseContext *context, int token);
+static int ES2_and_ES3_reserved_ES3_1_keyword(TParseContext *context, int token);
+static int ES2_and_ES3_ident_ES3_1_keyword(TParseContext *context, int token);
+static int ES3_extension_keyword_else_ident(TParseContext *context, TExtension extension, int token);
static int uint_constant(TParseContext *context);
static int int_constant(TParseContext *context);
static int float_constant(yyscan_t yyscanner);
static int floatsuffix_check(TParseContext* context);
+static int yuvcscstandardext_constant(TParseContext *context);
%}
%option noyywrap nounput never-interactive
@@ -103,6 +114,7 @@ O [0-7]
"attribute" { return ES2_keyword_ES3_reserved(context, ATTRIBUTE); }
"const" { return CONST_QUAL; }
"uniform" { return UNIFORM; }
+"buffer" { return ES2_and_ES3_ident_ES3_1_keyword(context, BUFFER); }
"varying" { return ES2_keyword_ES3_reserved(context, VARYING); }
"break" { return BREAK; }
@@ -124,6 +136,7 @@ O [0-7]
"in" { return IN_QUAL; }
"out" { return OUT_QUAL; }
"inout" { return INOUT_QUAL; }
+"shared" { return ES2_and_ES3_ident_ES3_1_keyword(context, SHARED); }
"float" { return FLOAT_TYPE; }
"int" { return INT_TYPE; }
@@ -171,29 +184,52 @@ O [0-7]
"sampler3DRect" { return ES2_reserved_ES3_keyword(context, SAMPLER3DRECT); }
"sampler2DRect" { return SAMPLER2DRECT; }
"sampler2DArray" { return ES2_ident_ES3_keyword(context, SAMPLER2DARRAY); }
+"sampler2DMS" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, SAMPLER2DMS); }
"isampler2D" { return ES2_ident_ES3_keyword(context, ISAMPLER2D); }
"isampler3D" { return ES2_ident_ES3_keyword(context, ISAMPLER3D); }
"isamplerCube" { return ES2_ident_ES3_keyword(context, ISAMPLERCUBE); }
"isampler2DArray" { return ES2_ident_ES3_keyword(context, ISAMPLER2DARRAY); }
+"isampler2DMS" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, ISAMPLER2DMS); }
"usampler2D" { return ES2_ident_ES3_keyword(context, USAMPLER2D); }
"usampler3D" { return ES2_ident_ES3_keyword(context, USAMPLER3D); }
"usamplerCube" { return ES2_ident_ES3_keyword(context, USAMPLERCUBE); }
"usampler2DArray" { return ES2_ident_ES3_keyword(context, USAMPLER2DARRAY); }
+"usampler2DMS" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, USAMPLER2DMS); }
"sampler2DShadow" { return ES2_reserved_ES3_keyword(context, SAMPLER2DSHADOW); }
"samplerCubeShadow" { return ES2_ident_ES3_keyword(context, SAMPLERCUBESHADOW); }
"sampler2DArrayShadow" { return ES2_ident_ES3_keyword(context, SAMPLER2DARRAYSHADOW); }
+"__samplerExternal2DY2YEXT" { return ES3_extension_keyword_else_ident(context, TExtension::EXT_YUV_target, SAMPLEREXTERNAL2DY2YEXT); }
"struct" { return STRUCT; }
-"layout" { return ES2_ident_ES3_keyword(context, LAYOUT); }
+"layout" { return ES2_ident_ES3_keyword_multiview_keyword(context, LAYOUT); }
+
+"yuvCscStandardEXT" { return ES3_extension_keyword_else_ident(context, TExtension::EXT_YUV_target, YUVCSCSTANDARDEXT); }
+"itu_601" { return yuvcscstandardext_constant(context); }
+"itu_601_full_range" { return yuvcscstandardext_constant(context); }
+"itu_709" { return yuvcscstandardext_constant(context); }
+
+"image2D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGE2D); }
+"iimage2D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGE2D); }
+"uimage2D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGE2D); }
+"image2DArray" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGE2DARRAY); }
+"iimage2DArray" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGE2DARRAY); }
+"uimage2DArray" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGE2DARRAY); }
+"image3D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGE3D); }
+"uimage3D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGE3D); }
+"iimage3D" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGE3D); }
+"iimageCube" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IIMAGECUBE); }
+"uimageCube" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, UIMAGECUBE); }
+"imageCube" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, IMAGECUBE); }
+"readonly" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, READONLY); }
+"writeonly" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, WRITEONLY); }
+"coherent" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, COHERENT); }
+"restrict" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, RESTRICT); }
+"volatile" { return ES2_and_ES3_reserved_ES3_1_keyword(context, VOLATILE); }
+"atomic_uint" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, ATOMICUINT); }
/* Reserved keywords for GLSL ES 3.00 that are not reserved for GLSL ES 1.00 */
-"coherent" |
-"restrict" |
-"readonly" |
-"writeonly" |
"resource" |
-"atomic_uint" |
"noperspective" |
"patch" |
"sample" |
@@ -204,23 +240,11 @@ O [0-7]
"filter" |
"image1D" |
-"image2D" |
-"image3D" |
-"imageCube" |
"iimage1D" |
-"iimage2D" |
-"iimage3D" |
-"iimageCube" |
"uimage1D" |
-"uimage2D" |
-"uimage3D" |
-"uimageCube" |
"image1DArray" |
-"image2DArray" |
"iimage1DArray" |
-"iimage2DArray" |
"uimage1DArray" |
-"uimage2DArray" |
"image1DShadow" |
"image2DShadow" |
"image1DArrayShadow" |
@@ -240,9 +264,6 @@ O [0-7]
"samplerBuffer" |
"isamplerBuffer" |
"usamplerBuffer" |
-"sampler2DMS" |
-"isampler2DMS" |
-"usampler2DMS" |
"sampler2DMSArray" |
"isampler2DMSArray" |
"usampler2DMSArray" {
@@ -278,7 +299,6 @@ O [0-7]
"inline" |
"noinline" |
-"volatile" |
"public" |
"static" |
"extern" |
@@ -390,6 +410,10 @@ O [0-7]
return FIELD_SELECTION;
}
<FIELDS>[ \t\v\f\r] {}
+<FIELDS>. {
+ yyextra->error(*yylloc, "Illegal character at fieldname start", yytext);
+ return 0;
+}
[ \t\v\n\f\r] { }
<*><<EOF>> { yyterminate(); }
@@ -431,8 +455,7 @@ int check_type(yyscan_t yyscanner) {
int reserved_word(yyscan_t yyscanner) {
struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
- yyextra->error(*yylloc, "Illegal use of reserved word", yytext, "");
- yyextra->recover();
+ yyextra->error(*yylloc, "Illegal use of reserved word", yytext);
return 0;
}
@@ -460,6 +483,24 @@ int ES2_keyword_ES3_reserved(TParseContext *context, int token)
return token;
}
+int ES2_ident_ES3_reserved_ES3_1_keyword(TParseContext *context, int token)
+{
+ struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+ yyscan_t yyscanner = (yyscan_t) context->getScanner();
+
+ if (context->getShaderVersion() < 300)
+ {
+ yylval->lex.string = NewPoolTString(yytext);
+ return check_type(yyscanner);
+ }
+ else if (context->getShaderVersion() == 300)
+ {
+ return reserved_word(yyscanner);
+ }
+
+ return token;
+}
+
int ES2_ident_ES3_keyword(TParseContext *context, int token)
{
struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
@@ -475,19 +516,76 @@ int ES2_ident_ES3_keyword(TParseContext *context, int token)
return token;
}
+int ES2_ident_ES3_keyword_multiview_keyword(TParseContext *context, int token)
+{
+ struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+ yyscan_t yyscanner = (yyscan_t) context->getScanner();
+
+ // not a reserved word in GLSL ES 1.00, so could be used as an identifier/type name
+ // except when multiview extension is enabled
+ if (context->getShaderVersion() < 300 && !context->isExtensionEnabled(TExtension::OVR_multiview))
+ {
+ yylval->lex.string = NewPoolTString(yytext);
+ return check_type(yyscanner);
+ }
+
+ return token;
+}
+
+int ES2_and_ES3_reserved_ES3_1_keyword(TParseContext *context, int token)
+{
+ yyscan_t yyscanner = (yyscan_t) context->getScanner();
+
+ if (context->getShaderVersion() < 310)
+ {
+ return reserved_word(yyscanner);
+ }
+
+ return token;
+}
+
+int ES2_and_ES3_ident_ES3_1_keyword(TParseContext *context, int token)
+{
+ struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+ yyscan_t yyscanner = (yyscan_t) context->getScanner();
+
+ // not a reserved word in GLSL ES 1.00 and GLSL ES 3.00, so could be used as an identifier/type name
+ if (context->getShaderVersion() < 310)
+ {
+ yylval->lex.string = NewPoolTString(yytext);
+ return check_type(yyscanner);
+ }
+
+ return token;
+}
+
+int ES3_extension_keyword_else_ident(TParseContext *context, TExtension extension, int token)
+{
+ struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+ yyscan_t yyscanner = (yyscan_t) context->getScanner();
+
+ // a reserved word in GLSL ES 3.00 with enabled extension, otherwise could be used as an identifier/type name
+ if (context->getShaderVersion() >= 300 && context->isExtensionEnabled(extension))
+ {
+ return token;
+ }
+
+ yylval->lex.string = NewPoolTString(yytext);
+ return check_type(yyscanner);
+}
+
int uint_constant(TParseContext *context)
{
struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
if (context->getShaderVersion() < 300)
{
- context->error(*yylloc, "Unsigned integers are unsupported prior to GLSL ES 3.00", yytext, "");
- context->recover();
+ context->error(*yylloc, "Unsigned integers are unsupported prior to GLSL ES 3.00", yytext);
return 0;
}
if (!atoi_clamp(yytext, &(yylval->lex.u)))
- yyextra->error(*yylloc, "Integer overflow", yytext, "");
+ yyextra->error(*yylloc, "Integer overflow", yytext);
return UINTCONSTANT;
}
@@ -499,21 +597,19 @@ int floatsuffix_check(TParseContext* context)
if (context->getShaderVersion() < 300)
{
context->error(*yylloc, "Floating-point suffix unsupported prior to GLSL ES 3.00", yytext);
- context->recover();
return 0;
}
std::string text = yytext;
text.resize(text.size() - 1);
if (!strtof_clamp(text, &(yylval->lex.f)))
- yyextra->warning(*yylloc, "Float overflow", yytext, "");
+ yyextra->warning(*yylloc, "Float overflow", yytext);
return(FLOATCONSTANT);
}
void yyerror(YYLTYPE* lloc, TParseContext* context, void *scanner, const char* reason) {
context->error(*lloc, reason, yyget_text(scanner));
- context->recover();
}
int int_constant(TParseContext *context) {
@@ -523,9 +619,9 @@ int int_constant(TParseContext *context) {
if (!atoi_clamp(yytext, &u))
{
if (context->getShaderVersion() >= 300)
- yyextra->error(*yylloc, "Integer overflow", yytext, "");
+ yyextra->error(*yylloc, "Integer overflow", yytext);
else
- yyextra->warning(*yylloc, "Integer overflow", yytext, "");
+ yyextra->warning(*yylloc, "Integer overflow", yytext);
}
yylval->lex.i = static_cast<int>(u);
return INTCONSTANT;
@@ -535,10 +631,26 @@ int float_constant(yyscan_t yyscanner) {
struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
if (!strtof_clamp(yytext, &(yylval->lex.f)))
- yyextra->warning(*yylloc, "Float overflow", yytext, "");
+ yyextra->warning(*yylloc, "Float overflow", yytext);
return FLOATCONSTANT;
}
+int yuvcscstandardext_constant(TParseContext *context)
+{
+ struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+ yyscan_t yyscanner = (yyscan_t) context->getScanner();
+
+ // a reserved word in GLSL ES 3.00 with enabled extension, otherwise could be used as an identifier/type name
+ if (context->getShaderVersion() >= 300 && context->isExtensionEnabled(TExtension::EXT_YUV_target))
+ {
+ yylval->lex.string = NewPoolTString(yytext);
+ return YUVCSCSTANDARDEXTCONSTANT;
+ }
+
+ yylval->lex.string = NewPoolTString(yytext);
+ return check_type(yyscanner);
+}
+
int glslang_initialize(TParseContext* context) {
yyscan_t scanner = NULL;
if (yylex_init_extra(context, &scanner))
@@ -574,13 +686,12 @@ int glslang_scan(size_t count, const char* const string[], const int length[],
const TExtensionBehavior& extBehavior = context->extensionBehavior();
for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
iter != extBehavior.end(); ++iter) {
- preprocessor->predefineMacro(iter->first.c_str(), 1);
+ preprocessor->predefineMacro(GetExtensionNameString(iter->first), 1);
}
if (context->getFragmentPrecisionHigh())
preprocessor->predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1);
- preprocessor->setMaxTokenSize(GetGlobalMaxTokenSize(context->getShaderSpec()));
+ preprocessor->setMaxTokenSize(sh::GetGlobalMaxTokenSize(context->getShaderSpec()));
return 0;
}
-
diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.y b/src/3rdparty/angle/src/compiler/translator/glslang.y
index aba2706311..3e506caac8 100644
--- a/src/3rdparty/angle/src/compiler/translator/glslang.y
+++ b/src/3rdparty/angle/src/compiler/translator/glslang.y
@@ -22,6 +22,8 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
+// clang-format off
+
// Ignore errors in auto-generated code.
#if defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wunused-function"
@@ -44,6 +46,8 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
#define YYENABLE_NLS 0
+using namespace sh;
+
%}
%expect 1 /* One shift reduce conflict because of if | else */
%parse-param {TParseContext* context}
@@ -70,22 +74,30 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
struct {
TOperator op;
union {
- TIntermNode* intermNode;
+ TIntermNode *intermNode;
TIntermNodePair nodePair;
- TIntermTyped* intermTypedNode;
- TIntermAggregate* intermAggregate;
- TIntermSwitch* intermSwitch;
- TIntermCase* intermCase;
+ TIntermFunctionCallOrMethod callOrMethodPair;
+ TIntermTyped *intermTypedNode;
+ TIntermAggregate *intermAggregate;
+ TIntermBlock *intermBlock;
+ TIntermDeclaration *intermDeclaration;
+ TIntermFunctionPrototype *intermFunctionPrototype;
+ TIntermSwitch *intermSwitch;
+ TIntermCase *intermCase;
};
union {
+ TVector<unsigned int> *arraySizes;
+ TTypeSpecifierNonArray typeSpecifierNonArray;
TPublicType type;
TPrecision precision;
TLayoutQualifier layoutQualifier;
TQualifier qualifier;
- TFunction* function;
+ TFunction *function;
TParameter param;
- TField* field;
- TFieldList* fieldList;
+ TField *field;
+ TFieldList *fieldList;
+ TQualifierWrapperBase *qualifierWrapper;
+ TTypeQualifierBuilder *typeQualifierBuilder;
};
} interm;
}
@@ -112,29 +124,37 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, cons
#define VERTEX_ONLY(S, L) { \
if (context->getShaderType() != GL_VERTEX_SHADER) { \
- context->error(L, " supported in vertex shaders only ", S); \
- context->recover(); \
+ context->error(L, " supported in vertex shaders only", S); \
} \
}
-#define FRAG_ONLY(S, L) { \
- if (context->getShaderType() != GL_FRAGMENT_SHADER) { \
- context->error(L, " supported in fragment shaders only ", S); \
- context->recover(); \
+#define COMPUTE_ONLY(S, L) { \
+ if (context->getShaderType() != GL_COMPUTE_SHADER) { \
+ context->error(L, " supported in compute shaders only", S); \
} \
}
#define ES2_ONLY(S, L) { \
if (context->getShaderVersion() != 100) { \
- context->error(L, " supported in GLSL ES 1.00 only ", S); \
- context->recover(); \
+ context->error(L, " supported in GLSL ES 1.00 only", S); \
+ } \
+}
+
+#define ES3_OR_NEWER(TOKEN, LINE, REASON) { \
+ if (context->getShaderVersion() < 300) { \
+ context->error(LINE, REASON " supported in GLSL ES 3.00 and above only", TOKEN); \
} \
}
-#define ES3_ONLY(TOKEN, LINE, REASON) { \
- if (context->getShaderVersion() != 300) { \
- context->error(LINE, REASON " supported in GLSL ES 3.00 only ", TOKEN); \
- context->recover(); \
+#define ES3_OR_NEWER_OR_MULTIVIEW(TOKEN, LINE, REASON) { \
+ if (context->getShaderVersion() < 300 && !context->isExtensionEnabled(TExtension::OVR_multiview)) { \
+ context->error(LINE, REASON " supported in GLSL ES 3.00 and above only", TOKEN); \
+ } \
+}
+
+#define ES3_1_ONLY(TOKEN, LINE, REASON) { \
+ if (context->getShaderVersion() != 310) { \
+ context->error(LINE, REASON " supported in GLSL ES 3.10 only", TOKEN); \
} \
}
%}
@@ -143,15 +163,22 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, cons
%token <lex> ATTRIBUTE CONST_QUAL BOOL_TYPE FLOAT_TYPE INT_TYPE UINT_TYPE
%token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT
%token <lex> BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4 UVEC2 UVEC3 UVEC4
-%token <lex> MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM VARYING
+%token <lex> MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM BUFFER VARYING
%token <lex> MATRIX2x3 MATRIX3x2 MATRIX2x4 MATRIX4x2 MATRIX3x4 MATRIX4x3
%token <lex> CENTROID FLAT SMOOTH
+%token <lex> READONLY WRITEONLY COHERENT RESTRICT VOLATILE SHARED
%token <lex> STRUCT VOID_TYPE WHILE
%token <lex> SAMPLER2D SAMPLERCUBE SAMPLER_EXTERNAL_OES SAMPLER2DRECT SAMPLER2DARRAY
%token <lex> ISAMPLER2D ISAMPLER3D ISAMPLERCUBE ISAMPLER2DARRAY
%token <lex> USAMPLER2D USAMPLER3D USAMPLERCUBE USAMPLER2DARRAY
+%token <lex> SAMPLER2DMS ISAMPLER2DMS USAMPLER2DMS
%token <lex> SAMPLER3D SAMPLER3DRECT SAMPLER2DSHADOW SAMPLERCUBESHADOW SAMPLER2DARRAYSHADOW
+%token <lex> SAMPLEREXTERNAL2DY2YEXT
+%token <lex> IMAGE2D IIMAGE2D UIMAGE2D IMAGE3D IIMAGE3D UIMAGE3D IMAGE2DARRAY IIMAGE2DARRAY UIMAGE2DARRAY
+%token <lex> IMAGECUBE IIMAGECUBE UIMAGECUBE
+%token <lex> ATOMICUINT
%token <lex> LAYOUT
+%token <lex> YUVCSCSTANDARDEXT YUVCSCSTANDARDEXTCONSTANT
%token <lex> IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT UINTCONSTANT BOOLCONSTANT
%token <lex> FIELD_SELECTION
@@ -166,7 +193,7 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, cons
%token <lex> LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION
%type <lex> identifier
-%type <interm> assignment_operator unary_operator
+%type <interm.op> assignment_operator unary_operator
%type <interm.intermTypedNode> variable_identifier primary_expression postfix_expression
%type <interm.intermTypedNode> expression integer_expression assignment_expression
%type <interm.intermTypedNode> unary_expression multiplicative_expression additive_expression
@@ -174,11 +201,12 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, cons
%type <interm.intermTypedNode> conditional_expression constant_expression
%type <interm.intermTypedNode> logical_or_expression logical_xor_expression logical_and_expression
%type <interm.intermTypedNode> shift_expression and_expression exclusive_or_expression inclusive_or_expression
-%type <interm.intermTypedNode> function_call initializer condition conditionopt
+%type <interm.intermTypedNode> function_call initializer
-%type <interm.intermNode> translation_unit function_definition
-%type <interm.intermNode> statement simple_statement
-%type <interm.intermAggregate> statement_list compound_statement compound_statement_no_new_scope
+%type <interm.intermNode> condition conditionopt
+%type <interm.intermBlock> translation_unit
+%type <interm.intermNode> function_definition statement simple_statement
+%type <interm.intermBlock> statement_list compound_statement_with_scope compound_statement_no_new_scope
%type <interm.intermNode> declaration_statement selection_statement expression_statement
%type <interm.intermNode> declaration external_declaration
%type <interm.intermNode> for_init_statement
@@ -188,14 +216,22 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, cons
%type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope statement_with_scope
%type <interm> single_declaration init_declarator_list
-%type <interm> parameter_declaration parameter_declarator parameter_type_specifier
-%type <interm.qualifier> parameter_qualifier parameter_type_qualifier
-%type <interm.layoutQualifier> layout_qualifier layout_qualifier_id_list layout_qualifier_id
+%type <interm.param> parameter_declaration parameter_declarator parameter_type_specifier
+%type <interm.layoutQualifier> layout_qualifier_id_list layout_qualifier_id
+
+// Note: array_specifier guaranteed to be non-null.
+%type <interm.arraySizes> array_specifier
+
+%type <interm.type> fully_specified_type type_specifier
%type <interm.precision> precision_qualifier
-%type <interm.type> type_qualifier fully_specified_type type_specifier storage_qualifier interpolation_qualifier
-%type <interm.type> type_specifier_no_prec type_specifier_nonarray
-%type <interm.type> struct_specifier
+%type <interm.layoutQualifier> layout_qualifier
+%type <interm.qualifier> interpolation_qualifier
+%type <interm.qualifierWrapper> storage_qualifier single_type_qualifier invariant_qualifier
+%type <interm.typeQualifierBuilder> type_qualifier
+
+%type <interm.typeSpecifierNonArray> type_specifier_nonarray struct_specifier
+%type <interm.type> type_specifier_no_prec
%type <interm.field> struct_declarator
%type <interm.fieldList> struct_declarator_list struct_declaration struct_declaration_list
%type <interm.function> function_header function_declarator function_identifier
@@ -229,22 +265,31 @@ primary_expression
| INTCONSTANT {
TConstantUnion *unionArray = new TConstantUnion[1];
unionArray->setIConst($1.i);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @1);
+ $$ = context->addScalarLiteral(unionArray, @1);
}
| UINTCONSTANT {
TConstantUnion *unionArray = new TConstantUnion[1];
unionArray->setUConst($1.u);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtUInt, EbpUndefined, EvqConst), @1);
+ $$ = context->addScalarLiteral(unionArray, @1);
}
| FLOATCONSTANT {
TConstantUnion *unionArray = new TConstantUnion[1];
unionArray->setFConst($1.f);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1);
+ $$ = context->addScalarLiteral(unionArray, @1);
}
| BOOLCONSTANT {
TConstantUnion *unionArray = new TConstantUnion[1];
unionArray->setBConst($1.b);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @1);
+ $$ = context->addScalarLiteral(unionArray, @1);
+ }
+ | YUVCSCSTANDARDEXTCONSTANT {
+ if (!context->checkCanUseExtension(@1, TExtension::EXT_YUV_target))
+ {
+ context->error(@1, "unsupported value", $1.string->c_str());
+ }
+ TConstantUnion *unionArray = new TConstantUnion[1];
+ unionArray->setYuvCscStandardEXTConst(getYuvCscStandardEXT($1.string->c_str()));
+ $$ = context->addScalarLiteral(unionArray, @1);
}
| LEFT_PAREN expression RIGHT_PAREN {
$$ = $2;
@@ -274,32 +319,26 @@ postfix_expression
integer_expression
: expression {
- if (context->integerErrorCheck($1, "[]"))
- context->recover();
+ context->checkIsScalarInteger($1, "[]");
$$ = $1;
}
;
function_call
: function_call_or_method {
- bool fatalError = false;
- $$ = context->addFunctionCallOrMethod($1.function, $1.nodePair.node1, $1.nodePair.node2, @1, &fatalError);
- if (fatalError)
- {
- YYERROR;
- }
+ $$ = context->addFunctionCallOrMethod($1.function, $1.callOrMethodPair.arguments, $1.callOrMethodPair.thisNode, @1);
}
;
function_call_or_method
: function_call_generic {
$$ = $1;
- $$.nodePair.node2 = nullptr;
+ $$.callOrMethodPair.thisNode = nullptr;
}
| postfix_expression DOT function_call_generic {
- ES3_ONLY("", @3, "methods");
+ ES3_OR_NEWER("", @3, "methods");
$$ = $3;
- $$.nodePair.node2 = $1;
+ $$.callOrMethodPair.thisNode = $1;
}
;
@@ -315,26 +354,23 @@ function_call_generic
function_call_header_no_parameters
: function_call_header VOID_TYPE {
$$.function = $1;
- $$.nodePair.node1 = nullptr;
+ $$.callOrMethodPair.arguments = context->createEmptyArgumentsList();
}
| function_call_header {
$$.function = $1;
- $$.nodePair.node1 = nullptr;
+ $$.callOrMethodPair.arguments = context->createEmptyArgumentsList();
}
;
function_call_header_with_parameters
: function_call_header assignment_expression {
- const TType *type = new TType($2->getType());
- $1->addParameter(TConstParameter(type));
+ $$.callOrMethodPair.arguments = context->createEmptyArgumentsList();
$$.function = $1;
- $$.nodePair.node1 = context->intermediate.makeAggregate($2, @2);
+ $$.callOrMethodPair.arguments->push_back($2);
}
| function_call_header_with_parameters COMMA assignment_expression {
- const TType *type = new TType($3->getType());
- $1.function->addParameter(TConstParameter(type));
$$.function = $1.function;
- $$.nodePair.node1 = context->intermediate.growAggregate($1.intermNode, $3, @2);
+ $$.callOrMethodPair.arguments->push_back($3);
}
;
@@ -348,24 +384,13 @@ function_call_header
function_identifier
: type_specifier_no_prec {
- if ($1.array) {
- ES3_ONLY("[]", @1, "array constructor");
- }
$$ = context->addConstructorFunc($1);
}
| IDENTIFIER {
- if (context->reservedErrorCheck(@1, *$1.string))
- context->recover();
- const TType *type = TCache::getType(EbtVoid, EbpUndefined);
- TFunction *function = new TFunction($1.string, type);
- $$ = function;
+ $$ = context->addNonConstructorFunc($1.string, @1);
}
| FIELD_SELECTION {
- if (context->reservedErrorCheck(@1, *$1.string))
- context->recover();
- const TType *type = TCache::getType(EbtVoid, EbpUndefined);
- TFunction *function = new TFunction($1.string, type);
- $$ = function;
+ $$ = context->addNonConstructorFunc($1.string, @1);
}
;
@@ -380,21 +405,18 @@ unary_expression
$$ = context->addUnaryMathLValue(EOpPreDecrement, $2, @1);
}
| unary_operator unary_expression {
- if ($1.op != EOpNull) {
- $$ = context->addUnaryMath($1.op, $2, @1);
- } else
- $$ = $2;
+ $$ = context->addUnaryMath($1, $2, @1);
}
;
// Grammar Note: No traditional style type casts.
unary_operator
- : PLUS { $$.op = EOpPositive; }
- | DASH { $$.op = EOpNegative; }
- | BANG { $$.op = EOpLogicalNot; }
+ : PLUS { $$ = EOpPositive; }
+ | DASH { $$ = EOpNegative; }
+ | BANG { $$ = EOpLogicalNot; }
| TILDE {
- ES3_ONLY("~", @$, "bit-wise operator");
- $$.op = EOpBitwiseNot;
+ ES3_OR_NEWER("~", @$, "bit-wise operator");
+ $$ = EOpBitwiseNot;
}
;
// Grammar Note: No '*' or '&' unary ops. Pointers are not supported.
@@ -408,7 +430,7 @@ multiplicative_expression
$$ = context->addBinaryMath(EOpDiv, $1, $3, @2);
}
| multiplicative_expression PERCENT unary_expression {
- ES3_ONLY("%", @2, "integer modulus operator");
+ ES3_OR_NEWER("%", @2, "integer modulus operator");
$$ = context->addBinaryMath(EOpIMod, $1, $3, @2);
}
;
@@ -426,11 +448,11 @@ additive_expression
shift_expression
: additive_expression { $$ = $1; }
| shift_expression LEFT_OP additive_expression {
- ES3_ONLY("<<", @2, "bit-wise operator");
+ ES3_OR_NEWER("<<", @2, "bit-wise operator");
$$ = context->addBinaryMath(EOpBitShiftLeft, $1, $3, @2);
}
| shift_expression RIGHT_OP additive_expression {
- ES3_ONLY(">>", @2, "bit-wise operator");
+ ES3_OR_NEWER(">>", @2, "bit-wise operator");
$$ = context->addBinaryMath(EOpBitShiftRight, $1, $3, @2);
}
;
@@ -464,7 +486,7 @@ equality_expression
and_expression
: equality_expression { $$ = $1; }
| and_expression AMPERSAND equality_expression {
- ES3_ONLY("&", @2, "bit-wise operator");
+ ES3_OR_NEWER("&", @2, "bit-wise operator");
$$ = context->addBinaryMath(EOpBitwiseAnd, $1, $3, @2);
}
;
@@ -472,7 +494,7 @@ and_expression
exclusive_or_expression
: and_expression { $$ = $1; }
| exclusive_or_expression CARET and_expression {
- ES3_ONLY("^", @2, "bit-wise operator");
+ ES3_OR_NEWER("^", @2, "bit-wise operator");
$$ = context->addBinaryMath(EOpBitwiseXor, $1, $3, @2);
}
;
@@ -480,7 +502,7 @@ exclusive_or_expression
inclusive_or_expression
: exclusive_or_expression { $$ = $1; }
| inclusive_or_expression VERTICAL_BAR exclusive_or_expression {
- ES3_ONLY("|", @2, "bit-wise operator");
+ ES3_OR_NEWER("|", @2, "bit-wise operator");
$$ = context->addBinaryMath(EOpBitwiseOr, $1, $3, @2);
}
;
@@ -516,41 +538,39 @@ conditional_expression
assignment_expression
: conditional_expression { $$ = $1; }
| unary_expression assignment_operator assignment_expression {
- if (context->lValueErrorCheck(@2, "assign", $1))
- context->recover();
- $$ = context->addAssign($2.op, $1, $3, @2);
+ $$ = context->addAssign($2, $1, $3, @2);
}
;
assignment_operator
- : EQUAL { $$.op = EOpAssign; }
- | MUL_ASSIGN { $$.op = EOpMulAssign; }
- | DIV_ASSIGN { $$.op = EOpDivAssign; }
+ : EQUAL { $$ = EOpAssign; }
+ | MUL_ASSIGN { $$ = EOpMulAssign; }
+ | DIV_ASSIGN { $$ = EOpDivAssign; }
| MOD_ASSIGN {
- ES3_ONLY("%=", @$, "integer modulus operator");
- $$.op = EOpIModAssign;
+ ES3_OR_NEWER("%=", @$, "integer modulus operator");
+ $$ = EOpIModAssign;
}
- | ADD_ASSIGN { $$.op = EOpAddAssign; }
- | SUB_ASSIGN { $$.op = EOpSubAssign; }
+ | ADD_ASSIGN { $$ = EOpAddAssign; }
+ | SUB_ASSIGN { $$ = EOpSubAssign; }
| LEFT_ASSIGN {
- ES3_ONLY("<<=", @$, "bit-wise operator");
- $$.op = EOpBitShiftLeftAssign;
+ ES3_OR_NEWER("<<=", @$, "bit-wise operator");
+ $$ = EOpBitShiftLeftAssign;
}
| RIGHT_ASSIGN {
- ES3_ONLY(">>=", @$, "bit-wise operator");
- $$.op = EOpBitShiftRightAssign;
+ ES3_OR_NEWER(">>=", @$, "bit-wise operator");
+ $$ = EOpBitShiftRightAssign;
}
| AND_ASSIGN {
- ES3_ONLY("&=", @$, "bit-wise operator");
- $$.op = EOpBitwiseAndAssign;
+ ES3_OR_NEWER("&=", @$, "bit-wise operator");
+ $$ = EOpBitwiseAndAssign;
}
| XOR_ASSIGN {
- ES3_ONLY("^=", @$, "bit-wise operator");
- $$.op = EOpBitwiseXorAssign;
+ ES3_OR_NEWER("^=", @$, "bit-wise operator");
+ $$ = EOpBitwiseXorAssign;
}
| OR_ASSIGN {
- ES3_ONLY("|=", @$, "bit-wise operator");
- $$.op = EOpBitwiseOrAssign;
+ ES3_OR_NEWER("|=", @$, "bit-wise operator");
+ $$ = EOpBitwiseOrAssign;
}
;
@@ -565,16 +585,14 @@ expression
constant_expression
: conditional_expression {
- if (context->constErrorCheck($1))
- context->recover();
+ context->checkIsConst($1);
$$ = $1;
}
;
enter_struct
: IDENTIFIER LEFT_BRACE {
- if (context->enterStructDeclaration(@1, *$1.string))
- context->recover();
+ context->enterStructDeclaration(@1, *$1.string);
$$ = $1;
}
;
@@ -584,43 +602,38 @@ declaration
$$ = context->addFunctionPrototypeDeclaration(*($1.function), @1);
}
| init_declarator_list SEMICOLON {
- TIntermAggregate *aggNode = $1.intermAggregate;
- if (aggNode && aggNode->getOp() == EOpNull)
- aggNode->setOp(EOpDeclaration);
- $$ = aggNode;
+ $$ = $1.intermDeclaration;
}
| PRECISION precision_qualifier type_specifier_no_prec SEMICOLON {
- if (($2 == EbpHigh) && (context->getShaderType() == GL_FRAGMENT_SHADER) && !context->getFragmentPrecisionHigh()) {
- context->error(@1, "precision is not supported in fragment shader", "highp");
- context->recover();
- }
- if (!context->symbolTable.setDefaultPrecision( $3, $2 )) {
- context->error(@1, "illegal type argument for default precision qualifier", getBasicString($3.type));
- context->recover();
- }
- $$ = 0;
+ context->parseDefaultPrecisionQualifier($2, $3, @1);
+ $$ = nullptr;
}
| type_qualifier enter_struct struct_declaration_list RIGHT_BRACE SEMICOLON {
- ES3_ONLY(getQualifierString($1.qualifier), @1, "interface blocks");
- $$ = context->addInterfaceBlock($1, @2, *$2.string, $3, NULL, @$, NULL, @$);
+ ES3_OR_NEWER($2.string->c_str(), @1, "interface blocks");
+ $$ = context->addInterfaceBlock(*$1, @2, *$2.string, $3, NULL, @$, NULL, @$);
}
| type_qualifier enter_struct struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON {
- ES3_ONLY(getQualifierString($1.qualifier), @1, "interface blocks");
- $$ = context->addInterfaceBlock($1, @2, *$2.string, $3, $5.string, @5, NULL, @$);
+ ES3_OR_NEWER($2.string->c_str(), @1, "interface blocks");
+ $$ = context->addInterfaceBlock(*$1, @2, *$2.string, $3, $5.string, @5, NULL, @$);
}
| type_qualifier enter_struct struct_declaration_list RIGHT_BRACE IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET SEMICOLON {
- ES3_ONLY(getQualifierString($1.qualifier), @1, "interface blocks");
- $$ = context->addInterfaceBlock($1, @2, *$2.string, $3, $5.string, @5, $7, @6);
+ ES3_OR_NEWER($2.string->c_str(), @1, "interface blocks");
+ $$ = context->addInterfaceBlock(*$1, @2, *$2.string, $3, $5.string, @5, $7, @6);
}
| type_qualifier SEMICOLON {
- context->parseGlobalLayoutQualifier($1);
- $$ = 0;
+ context->parseGlobalLayoutQualifier(*$1);
+ $$ = nullptr;
+ }
+ | type_qualifier IDENTIFIER SEMICOLON // e.g. to qualify an existing variable as invariant
+ {
+ $$ = context->parseInvariantDeclaration(*$1, @2, $2.string, $2.symbol);
}
;
function_prototype
: function_declarator RIGHT_PAREN {
$$.function = context->parseFunctionDeclarator(@2, $1);
+ context->exitFunctionDeclaration();
}
;
@@ -638,145 +651,69 @@ function_header_with_parameters
: function_header parameter_declaration {
// Add the parameter
$$ = $1;
- if ($2.param.type->getBasicType() != EbtVoid)
- $1->addParameter($2.param.turnToConst());
- else
- delete $2.param.type;
+ if ($2.type->getBasicType() != EbtVoid)
+ {
+ $1->addParameter($2.turnToConst());
+ }
}
| function_header_with_parameters COMMA parameter_declaration {
- //
+ $$ = $1;
// Only first parameter of one-parameter functions can be void
// The check for named parameters not being void is done in parameter_declarator
- //
- if ($3.param.type->getBasicType() == EbtVoid) {
- //
+ if ($3.type->getBasicType() == EbtVoid)
+ {
// This parameter > first is void
- //
- context->error(@2, "cannot be an argument type except for '(void)'", "void");
- context->recover();
- delete $3.param.type;
- } else {
- // Add the parameter
- $$ = $1;
- $1->addParameter($3.param.turnToConst());
+ context->error(@2, "cannot be a parameter type except for '(void)'", "void");
+ }
+ else
+ {
+ $1->addParameter($3.turnToConst());
}
}
;
function_header
: fully_specified_type IDENTIFIER LEFT_PAREN {
- if ($1.qualifier != EvqGlobal && $1.qualifier != EvqTemporary)
- {
- context->error(@2, "no qualifiers allowed for function return", getQualifierString($1.qualifier));
- context->recover();
- }
- if (!$1.layoutQualifier.isEmpty())
- {
- context->error(@2, "no qualifiers allowed for function return", "layout");
- context->recover();
- }
- // make sure a sampler is not involved as well...
- if (context->samplerErrorCheck(@2, $1, "samplers can't be function return values"))
- context->recover();
-
- // Add the function as a prototype after parsing it (we do not support recursion)
- TFunction *function;
- const TType *type = new TType($1);
- function = new TFunction($2.string, type);
- $$ = function;
-
+ $$ = context->parseFunctionHeader($1, $2.string, @2);
+
context->symbolTable.push();
+ context->enterFunctionDeclaration();
}
;
parameter_declarator
// Type + name
: type_specifier identifier {
- if ($1.type == EbtVoid) {
- context->error(@2, "illegal use of type 'void'", $2.string->c_str());
- context->recover();
- }
- if (context->reservedErrorCheck(@2, *$2.string))
- context->recover();
- TParameter param = {$2.string, new TType($1)};
- $$.param = param;
+ $$ = context->parseParameterDeclarator($1, $2.string, @2);
}
- | type_specifier identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
- // Check that we can make an array out of this type
- if (context->arrayTypeErrorCheck(@3, $1))
- context->recover();
-
- if (context->reservedErrorCheck(@2, *$2.string))
- context->recover();
-
- int size;
- if (context->arraySizeErrorCheck(@3, $4, size))
- context->recover();
- $1.setArraySize(size);
-
- TType* type = new TType($1);
- TParameter param = { $2.string, type };
- $$.param = param;
+ | type_specifier identifier array_specifier {
+ $$ = context->parseParameterArrayDeclarator($2.string, @2, *($3), @3, &$1);
}
;
parameter_declaration
- //
- // The only parameter qualifier a parameter can have are
- // IN_QUAL, OUT_QUAL, INOUT_QUAL, or CONST.
- //
-
- //
- // Type + name
- //
- : parameter_type_qualifier parameter_qualifier parameter_declarator {
- $$ = $3;
- if (context->paramErrorCheck(@3, $1, $2, $$.param.type))
- context->recover();
- }
- | parameter_qualifier parameter_declarator {
- $$ = $2;
- if (context->parameterSamplerErrorCheck(@2, $1, *$2.param.type))
- context->recover();
- if (context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type))
- context->recover();
- }
- //
- // Only type
- //
- | parameter_type_qualifier parameter_qualifier parameter_type_specifier {
- $$ = $3;
- if (context->paramErrorCheck(@3, $1, $2, $$.param.type))
- context->recover();
- }
- | parameter_qualifier parameter_type_specifier {
+ : type_qualifier parameter_declarator {
$$ = $2;
- if (context->parameterSamplerErrorCheck(@2, $1, *$2.param.type))
- context->recover();
- if (context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type))
- context->recover();
+ context->checkIsParameterQualifierValid(@2, *$1, $2.type);
}
- ;
-
-parameter_qualifier
- : /* empty */ {
- $$ = EvqIn;
- }
- | IN_QUAL {
- $$ = EvqIn;
+ | parameter_declarator {
+ $$ = $1;
+ $$.type->setQualifier(EvqIn);
}
- | OUT_QUAL {
- $$ = EvqOut;
+ | type_qualifier parameter_type_specifier {
+ $$ = $2;
+ context->checkIsParameterQualifierValid(@2, *$1, $2.type);
}
- | INOUT_QUAL {
- $$ = EvqInOut;
+ | parameter_type_specifier {
+ $$ = $1;
+ $$.type->setQualifier(EvqIn);
}
;
parameter_type_specifier
: type_specifier {
TParameter param = { 0, new TType($1) };
- $$.param = param;
+ $$ = param;
}
;
@@ -786,213 +723,164 @@ init_declarator_list
}
| init_declarator_list COMMA identifier {
$$ = $1;
- $$.intermAggregate = context->parseDeclarator($$.type, $1.intermAggregate, @3, *$3.string);
- }
- | init_declarator_list COMMA identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
- $$ = $1;
- $$.intermAggregate = context->parseArrayDeclarator($$.type, $1.intermAggregate, @3, *$3.string, @4, $5);
+ context->parseDeclarator($$.type, @3, *$3.string, $$.intermDeclaration);
}
- | init_declarator_list COMMA identifier LEFT_BRACKET RIGHT_BRACKET EQUAL initializer {
- ES3_ONLY("[]", @3, "implicitly sized array");
+ | init_declarator_list COMMA identifier array_specifier {
$$ = $1;
- $$.intermAggregate = context->parseArrayInitDeclarator($$.type, $1.intermAggregate, @3, *$3.string, @4, nullptr, @6, $7);
+ context->parseArrayDeclarator($$.type, @3, *$3.string, @4, *($4), $$.intermDeclaration);
}
- | init_declarator_list COMMA identifier LEFT_BRACKET constant_expression RIGHT_BRACKET EQUAL initializer {
- ES3_ONLY("=", @7, "first-class arrays (array initializer)");
+ | init_declarator_list COMMA identifier array_specifier EQUAL initializer {
+ ES3_OR_NEWER("=", @5, "first-class arrays (array initializer)");
$$ = $1;
- $$.intermAggregate = context->parseArrayInitDeclarator($$.type, $1.intermAggregate, @3, *$3.string, @4, $5, @7, $8);
+ context->parseArrayInitDeclarator($$.type, @3, *$3.string, @4, *($4), @5, $6, $$.intermDeclaration);
}
| init_declarator_list COMMA identifier EQUAL initializer {
$$ = $1;
- $$.intermAggregate = context->parseInitDeclarator($$.type, $1.intermAggregate, @3, *$3.string, @4, $5);
+ context->parseInitDeclarator($$.type, @3, *$3.string, @4, $5, $$.intermDeclaration);
}
;
single_declaration
: fully_specified_type {
$$.type = $1;
- $$.intermAggregate = context->parseSingleDeclaration($$.type, @1, "");
+ $$.intermDeclaration = context->parseSingleDeclaration($$.type, @1, "");
}
| fully_specified_type identifier {
$$.type = $1;
- $$.intermAggregate = context->parseSingleDeclaration($$.type, @2, *$2.string);
- }
- | fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
- $$.type = $1;
- $$.intermAggregate = context->parseSingleArrayDeclaration($$.type, @2, *$2.string, @3, $4);
+ $$.intermDeclaration = context->parseSingleDeclaration($$.type, @2, *$2.string);
}
- | fully_specified_type identifier LEFT_BRACKET RIGHT_BRACKET EQUAL initializer {
- ES3_ONLY("[]", @3, "implicitly sized array");
+ | fully_specified_type identifier array_specifier {
$$.type = $1;
- $$.intermAggregate = context->parseSingleArrayInitDeclaration($$.type, @2, *$2.string, @3, nullptr, @5, $6);
+ $$.intermDeclaration = context->parseSingleArrayDeclaration($$.type, @2, *$2.string, @3, *($3));
}
- | fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET EQUAL initializer {
- ES3_ONLY("=", @6, "first-class arrays (array initializer)");
+ | fully_specified_type identifier array_specifier EQUAL initializer {
+ ES3_OR_NEWER("[]", @3, "first-class arrays (array initializer)");
$$.type = $1;
- $$.intermAggregate = context->parseSingleArrayInitDeclaration($$.type, @2, *$2.string, @3, $4, @6, $7);
+ $$.intermDeclaration = context->parseSingleArrayInitDeclaration($$.type, @2, *$2.string, @3, *($3), @4, $5);
}
| fully_specified_type identifier EQUAL initializer {
$$.type = $1;
- $$.intermAggregate = context->parseSingleInitDeclaration($$.type, @2, *$2.string, @3, $4);
- }
- | INVARIANT IDENTIFIER {
- // $$.type is not used in invariant declarations.
- $$.intermAggregate = context->parseInvariantDeclaration(@1, @2, $2.string, $2.symbol);
+ $$.intermDeclaration = context->parseSingleInitDeclaration($$.type, @2, *$2.string, @3, $4);
}
;
fully_specified_type
: type_specifier {
+ context->addFullySpecifiedType(&$1);
$$ = $1;
-
- if ($1.array) {
- ES3_ONLY("[]", @1, "first-class-array");
- if (context->getShaderVersion() != 300) {
- $1.clearArrayness();
- }
- }
}
- | type_qualifier type_specifier {
- $$ = context->addFullySpecifiedType($1.qualifier, $1.invariant, $1.layoutQualifier, $2);
+ | type_qualifier type_specifier {
+ $$ = context->addFullySpecifiedType(*$1, $2);
}
;
interpolation_qualifier
: SMOOTH {
- $$.qualifier = EvqSmooth;
+ $$ = EvqSmooth;
}
| FLAT {
- $$.qualifier = EvqFlat;
- }
- ;
-
-parameter_type_qualifier
- : CONST_QUAL {
- $$ = EvqConst;
+ $$ = EvqFlat;
}
;
type_qualifier
- : ATTRIBUTE {
- VERTEX_ONLY("attribute", @1);
- ES2_ONLY("attribute", @1);
- if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "attribute"))
- context->recover();
- $$.setBasic(EbtVoid, EvqAttribute, @1);
- }
- | VARYING {
- ES2_ONLY("varying", @1);
- if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "varying"))
- context->recover();
- if (context->getShaderType() == GL_VERTEX_SHADER)
- $$.setBasic(EbtVoid, EvqVaryingOut, @1);
- else
- $$.setBasic(EbtVoid, EvqVaryingIn, @1);
+ : single_type_qualifier {
+ $$ = context->createTypeQualifierBuilder(@1);
+ $$->appendQualifier($1);
}
- | INVARIANT VARYING {
- ES2_ONLY("varying", @1);
- if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying"))
- context->recover();
- if (context->getShaderType() == GL_VERTEX_SHADER)
- $$.setBasic(EbtVoid, EvqVaryingOut, @1);
- else
- $$.setBasic(EbtVoid, EvqVaryingIn, @1);
- $$.invariant = true;
- }
- | storage_qualifier {
- if ($1.qualifier != EvqConst && !context->symbolTable.atGlobalLevel())
- {
- context->error(@1, "Local variables can only use the const storage qualifier.", getQualifierString($1.qualifier));
- context->recover();
- }
- $$.setBasic(EbtVoid, $1.qualifier, @1);
+ | type_qualifier single_type_qualifier {
+ $$ = $1;
+ $$->appendQualifier($2);
}
- | interpolation_qualifier storage_qualifier {
- $$ = context->joinInterpolationQualifiers(@1, $1.qualifier, @2, $2.qualifier);
+ ;
+
+invariant_qualifier
+ : INVARIANT {
+ // empty
}
- | interpolation_qualifier {
- context->error(@1, "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier", getInterpolationString($1.qualifier));
- context->recover();
-
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtVoid, qual, @1);
+ ;
+
+single_type_qualifier
+ : storage_qualifier {
+ context->checkLocalVariableConstStorageQualifier(*$1);
+ $$ = $1;
}
| layout_qualifier {
- $$.qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.layoutQualifier = $1;
+ context->checkIsAtGlobalLevel(@1, "layout");
+ $$ = new TLayoutQualifierWrapper($1, @1);
}
- | layout_qualifier storage_qualifier {
- $$.setBasic(EbtVoid, $2.qualifier, @2);
- $$.layoutQualifier = $1;
+ | precision_qualifier {
+ $$ = new TPrecisionQualifierWrapper($1, @1);
}
- | INVARIANT storage_qualifier {
- context->es3InvariantErrorCheck($2.qualifier, @1);
- $$.setBasic(EbtVoid, $2.qualifier, @2);
- $$.invariant = true;
+ | interpolation_qualifier {
+ $$ = new TInterpolationQualifierWrapper($1, @1);
}
- | INVARIANT interpolation_qualifier storage_qualifier {
- context->es3InvariantErrorCheck($3.qualifier, @1);
- $$ = context->joinInterpolationQualifiers(@2, $2.qualifier, @3, $3.qualifier);
- $$.invariant = true;
+ | invariant_qualifier {
+ context->checkIsAtGlobalLevel(@1, "invariant");
+ $$ = new TInvariantQualifierWrapper(@1);
}
;
+
storage_qualifier
- : CONST_QUAL {
- $$.qualifier = EvqConst;
+ :
+ ATTRIBUTE {
+ VERTEX_ONLY("attribute", @1);
+ ES2_ONLY("attribute", @1);
+ $$ = context->parseGlobalStorageQualifier(EvqAttribute, @1);
+ }
+ | VARYING {
+ ES2_ONLY("varying", @1);
+ $$ = context->parseVaryingQualifier(@1);
+ }
+ | CONST_QUAL {
+ $$ = new TStorageQualifierWrapper(EvqConst, @1);
}
| IN_QUAL {
- ES3_ONLY("in", @1, "storage qualifier");
- $$.qualifier = (context->getShaderType() == GL_FRAGMENT_SHADER) ? EvqFragmentIn : EvqVertexIn;
+ $$ = context->parseInQualifier(@1);
}
| OUT_QUAL {
- ES3_ONLY("out", @1, "storage qualifier");
- $$.qualifier = (context->getShaderType() == GL_FRAGMENT_SHADER) ? EvqFragmentOut : EvqVertexOut;
+ $$ = context->parseOutQualifier(@1);
}
- | CENTROID IN_QUAL {
- ES3_ONLY("centroid in", @1, "storage qualifier");
- if (context->getShaderType() == GL_VERTEX_SHADER)
- {
- context->error(@1, "invalid storage qualifier", "it is an error to use 'centroid in' in the vertex shader");
- context->recover();
- }
- $$.qualifier = (context->getShaderType() == GL_FRAGMENT_SHADER) ? EvqCentroidIn : EvqVertexIn;
+ | INOUT_QUAL {
+ $$ = context->parseInOutQualifier(@1);
}
- | CENTROID OUT_QUAL {
- ES3_ONLY("centroid out", @1, "storage qualifier");
- if (context->getShaderType() == GL_FRAGMENT_SHADER)
- {
- context->error(@1, "invalid storage qualifier", "it is an error to use 'centroid out' in the fragment shader");
- context->recover();
- }
- $$.qualifier = (context->getShaderType() == GL_FRAGMENT_SHADER) ? EvqFragmentOut : EvqCentroidOut;
+ | CENTROID {
+ ES3_OR_NEWER("centroid", @1, "storage qualifier");
+ $$ = new TStorageQualifierWrapper(EvqCentroid, @1);
}
| UNIFORM {
- if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "uniform"))
- context->recover();
- $$.qualifier = EvqUniform;
+ $$ = context->parseGlobalStorageQualifier(EvqUniform, @1);
+ }
+ | BUFFER {
+ ES3_1_ONLY("buffer", @1, "storage qualifier");
+ $$ = context->parseGlobalStorageQualifier(EvqBuffer, @1);
+ }
+ | READONLY {
+ $$ = new TMemoryQualifierWrapper(EvqReadOnly, @1);
+ }
+ | WRITEONLY {
+ $$ = new TMemoryQualifierWrapper(EvqWriteOnly, @1);
+ }
+ | COHERENT {
+ $$ = new TMemoryQualifierWrapper(EvqCoherent, @1);
+ }
+ | RESTRICT {
+ $$ = new TMemoryQualifierWrapper(EvqRestrict, @1);
+ }
+ | VOLATILE {
+ $$ = new TMemoryQualifierWrapper(EvqVolatile, @1);
+ }
+ | SHARED {
+ COMPUTE_ONLY("shared", @1);
+ $$ = context->parseGlobalStorageQualifier(EvqShared, @1);
}
;
type_specifier
: type_specifier_no_prec {
$$ = $1;
-
- if ($$.precision == EbpUndefined) {
- $$.precision = context->symbolTable.getDefaultPrecision($1.type);
- if (context->precisionErrorCheck(@1, $$.precision, $1.type)) {
- context->recover();
- }
- }
- }
- | precision_qualifier type_specifier_no_prec {
- $$ = $2;
- $$.precision = $1;
-
- if (!SupportsPrecision($2.type)) {
- context->error(@1, "illegal type for precision qualifier", getBasicString($2.type));
- context->recover();
- }
+ $$.precision = context->symbolTable.getDefaultPrecision($1.getBasicType());
}
;
@@ -1010,7 +898,7 @@ precision_qualifier
layout_qualifier
: LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN {
- ES3_ONLY("layout", @1, "qualifier");
+ ES3_OR_NEWER_OR_MULTIVIEW("layout", @1, "qualifier");
$$ = $3;
}
;
@@ -1020,7 +908,7 @@ layout_qualifier_id_list
$$ = $1;
}
| layout_qualifier_id_list COMMA layout_qualifier_id {
- $$ = context->joinLayoutQualifiers($1, $3);
+ $$ = context->joinLayoutQualifiers($1, $3, @3);
}
;
@@ -1029,279 +917,303 @@ layout_qualifier_id
$$ = context->parseLayoutQualifier(*$1.string, @1);
}
| IDENTIFIER EQUAL INTCONSTANT {
- $$ = context->parseLayoutQualifier(*$1.string, @1, *$3.string, $3.i, @3);
+ $$ = context->parseLayoutQualifier(*$1.string, @1, $3.i, @3);
}
| IDENTIFIER EQUAL UINTCONSTANT {
- $$ = context->parseLayoutQualifier(*$1.string, @1, *$3.string, $3.i, @3);
+ $$ = context->parseLayoutQualifier(*$1.string, @1, $3.i, @3);
+ }
+ | SHARED {
+ $$ = context->parseLayoutQualifier("shared", @1);
}
;
type_specifier_no_prec
: type_specifier_nonarray {
- $$ = $1;
+ $$.initialize($1, (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary));
+ }
+ | type_specifier_nonarray array_specifier {
+ $$.initialize($1, (context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary));
+ $$.setArraySizes($2);
+ }
+ ;
+
+array_specifier
+ : LEFT_BRACKET RIGHT_BRACKET {
+ ES3_OR_NEWER("[]", @1, "implicitly sized array");
+ $$ = new TVector<unsigned int>();
+ $$->push_back(0u);
}
- | type_specifier_nonarray LEFT_BRACKET RIGHT_BRACKET {
- ES3_ONLY("[]", @2, "implicitly sized array");
+ | LEFT_BRACKET constant_expression RIGHT_BRACKET {
+ $$ = new TVector<unsigned int>();
+ unsigned int size = context->checkIsValidArraySize(@1, $2);
+ // Make the type an array even if size check failed.
+ // This ensures useless error messages regarding a variable's non-arrayness won't follow.
+ $$->push_back(size);
+ }
+ | array_specifier LEFT_BRACKET RIGHT_BRACKET {
+ ES3_1_ONLY("[]", @2, "arrays of arrays");
$$ = $1;
- $$.setArraySize(0);
+ $$->insert($$->begin(), 0u);
}
- | type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET {
+ | array_specifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
+ ES3_1_ONLY("[]", @2, "arrays of arrays");
$$ = $1;
-
- if (context->arrayTypeErrorCheck(@2, $1))
- context->recover();
- else {
- int size;
- if (context->arraySizeErrorCheck(@2, $3, size))
- context->recover();
- $$.setArraySize(size);
- }
+ unsigned int size = context->checkIsValidArraySize(@2, $3);
+ // Make the type an array even if size check failed.
+ // This ensures useless error messages regarding a variable's non-arrayness won't follow.
+ $$->insert($$->begin(), size);
}
;
type_specifier_nonarray
: VOID_TYPE {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtVoid, qual, @1);
+ $$.initialize(EbtVoid, @1);
}
| FLOAT_TYPE {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtFloat, qual, @1);
+ $$.initialize(EbtFloat, @1);
}
| INT_TYPE {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtInt, qual, @1);
+ $$.initialize(EbtInt, @1);
}
| UINT_TYPE {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtUInt, qual, @1);
+ $$.initialize(EbtUInt, @1);
}
| BOOL_TYPE {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtBool, qual, @1);
+ $$.initialize(EbtBool, @1);
}
| VEC2 {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtFloat, qual, @1);
+ $$.initialize(EbtFloat, @1);
$$.setAggregate(2);
}
| VEC3 {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtFloat, qual, @1);
+ $$.initialize(EbtFloat, @1);
$$.setAggregate(3);
}
| VEC4 {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtFloat, qual, @1);
+ $$.initialize(EbtFloat, @1);
$$.setAggregate(4);
}
| BVEC2 {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtBool, qual, @1);
+ $$.initialize(EbtBool, @1);
$$.setAggregate(2);
}
| BVEC3 {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtBool, qual, @1);
+ $$.initialize(EbtBool, @1);
$$.setAggregate(3);
}
| BVEC4 {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtBool, qual, @1);
+ $$.initialize(EbtBool, @1);
$$.setAggregate(4);
}
| IVEC2 {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtInt, qual, @1);
+ $$.initialize(EbtInt, @1);
$$.setAggregate(2);
}
| IVEC3 {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtInt, qual, @1);
+ $$.initialize(EbtInt, @1);
$$.setAggregate(3);
}
| IVEC4 {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtInt, qual, @1);
+ $$.initialize(EbtInt, @1);
$$.setAggregate(4);
}
| UVEC2 {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtUInt, qual, @1);
+ $$.initialize(EbtUInt, @1);
$$.setAggregate(2);
}
| UVEC3 {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtUInt, qual, @1);
+ $$.initialize(EbtUInt, @1);
$$.setAggregate(3);
}
| UVEC4 {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtUInt, qual, @1);
+ $$.initialize(EbtUInt, @1);
$$.setAggregate(4);
}
| MATRIX2 {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtFloat, qual, @1);
+ $$.initialize(EbtFloat, @1);
$$.setMatrix(2, 2);
}
| MATRIX3 {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtFloat, qual, @1);
+ $$.initialize(EbtFloat, @1);
$$.setMatrix(3, 3);
}
| MATRIX4 {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtFloat, qual, @1);
+ $$.initialize(EbtFloat, @1);
$$.setMatrix(4, 4);
}
| MATRIX2x3 {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtFloat, qual, @1);
+ $$.initialize(EbtFloat, @1);
$$.setMatrix(2, 3);
}
| MATRIX3x2 {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtFloat, qual, @1);
+ $$.initialize(EbtFloat, @1);
$$.setMatrix(3, 2);
}
| MATRIX2x4 {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtFloat, qual, @1);
+ $$.initialize(EbtFloat, @1);
$$.setMatrix(2, 4);
}
| MATRIX4x2 {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtFloat, qual, @1);
+ $$.initialize(EbtFloat, @1);
$$.setMatrix(4, 2);
}
| MATRIX3x4 {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtFloat, qual, @1);
+ $$.initialize(EbtFloat, @1);
$$.setMatrix(3, 4);
}
| MATRIX4x3 {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtFloat, qual, @1);
+ $$.initialize(EbtFloat, @1);
$$.setMatrix(4, 3);
}
+ | YUVCSCSTANDARDEXT {
+ if (!context->checkCanUseExtension(@1, TExtension::EXT_YUV_target))
+ {
+ context->error(@1, "unsupported type", "yuvCscStandardEXT");
+ }
+ $$.initialize(EbtYuvCscStandardEXT, @1);
+ }
| SAMPLER2D {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtSampler2D, qual, @1);
+ $$.initialize(EbtSampler2D, @1);
}
| SAMPLER3D {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtSampler3D, qual, @1);
+ $$.initialize(EbtSampler3D, @1);
}
| SAMPLERCUBE {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtSamplerCube, qual, @1);
+ $$.initialize(EbtSamplerCube, @1);
}
| SAMPLER2DARRAY {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtSampler2DArray, qual, @1);
+ $$.initialize(EbtSampler2DArray, @1);
+ }
+ | SAMPLER2DMS {
+ $$.initialize(EbtSampler2DMS, @1);
}
| ISAMPLER2D {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtISampler2D, qual, @1);
+ $$.initialize(EbtISampler2D, @1);
}
| ISAMPLER3D {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtISampler3D, qual, @1);
+ $$.initialize(EbtISampler3D, @1);
}
| ISAMPLERCUBE {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtISamplerCube, qual, @1);
+ $$.initialize(EbtISamplerCube, @1);
}
| ISAMPLER2DARRAY {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtISampler2DArray, qual, @1);
+ $$.initialize(EbtISampler2DArray, @1);
+ }
+ | ISAMPLER2DMS {
+ $$.initialize(EbtISampler2DMS, @1);
}
| USAMPLER2D {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtUSampler2D, qual, @1);
+ $$.initialize(EbtUSampler2D, @1);
}
| USAMPLER3D {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtUSampler3D, qual, @1);
+ $$.initialize(EbtUSampler3D, @1);
}
| USAMPLERCUBE {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtUSamplerCube, qual, @1);
+ $$.initialize(EbtUSamplerCube, @1);
}
| USAMPLER2DARRAY {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtUSampler2DArray, qual, @1);
+ $$.initialize(EbtUSampler2DArray, @1);
+ }
+ | USAMPLER2DMS {
+ $$.initialize(EbtUSampler2DMS, @1);
}
| SAMPLER2DSHADOW {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtSampler2DShadow, qual, @1);
+ $$.initialize(EbtSampler2DShadow, @1);
}
| SAMPLERCUBESHADOW {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtSamplerCubeShadow, qual, @1);
+ $$.initialize(EbtSamplerCubeShadow, @1);
}
| SAMPLER2DARRAYSHADOW {
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtSampler2DArrayShadow, qual, @1);
+ $$.initialize(EbtSampler2DArrayShadow, @1);
}
| SAMPLER_EXTERNAL_OES {
- if (!context->supportsExtension("GL_OES_EGL_image_external")) {
+ constexpr std::array<TExtension, 3u> extensions{ { TExtension::NV_EGL_stream_consumer_external,
+ TExtension::OES_EGL_image_external_essl3,
+ TExtension::OES_EGL_image_external } };
+ if (!context->checkCanUseOneOfExtensions(@1, extensions))
+ {
context->error(@1, "unsupported type", "samplerExternalOES");
- context->recover();
}
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtSamplerExternalOES, qual, @1);
+ $$.initialize(EbtSamplerExternalOES, @1);
+ }
+ | SAMPLEREXTERNAL2DY2YEXT {
+ if (!context->checkCanUseExtension(@1, TExtension::EXT_YUV_target))
+ {
+ context->error(@1, "unsupported type", "__samplerExternal2DY2YEXT");
+ }
+ $$.initialize(EbtSamplerExternal2DY2YEXT, @1);
}
| SAMPLER2DRECT {
- if (!context->supportsExtension("GL_ARB_texture_rectangle")) {
+ if (!context->checkCanUseExtension(@1, TExtension::ARB_texture_rectangle))
+ {
context->error(@1, "unsupported type", "sampler2DRect");
- context->recover();
}
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtSampler2DRect, qual, @1);
+ $$.initialize(EbtSampler2DRect, @1);
}
| struct_specifier {
$$ = $1;
- $$.qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ }
+ | IMAGE2D {
+ $$.initialize(EbtImage2D, @1);
+ }
+ | IIMAGE2D {
+ $$.initialize(EbtIImage2D, @1);
+ }
+ | UIMAGE2D {
+ $$.initialize(EbtUImage2D, @1);
+ }
+ | IMAGE3D {
+ $$.initialize(EbtImage3D, @1);
+ }
+ | IIMAGE3D {
+ $$.initialize(EbtIImage3D, @1);
+ }
+ | UIMAGE3D {
+ $$.initialize(EbtUImage3D, @1);
+ }
+ | IMAGE2DARRAY {
+ $$.initialize(EbtImage2DArray, @1);
+ }
+ | IIMAGE2DARRAY {
+ $$.initialize(EbtIImage2DArray, @1);
+ }
+ | UIMAGE2DARRAY {
+ $$.initialize(EbtUImage2DArray, @1);
+ }
+ | IMAGECUBE {
+ $$.initialize(EbtImageCube, @1);
+ }
+ | IIMAGECUBE {
+ $$.initialize(EbtIImageCube, @1);
+ }
+ | UIMAGECUBE {
+ $$.initialize(EbtUImageCube, @1);
+ }
+ | ATOMICUINT {
+ $$.initialize(EbtAtomicCounter, @1);
}
| TYPE_NAME {
- //
- // This is for user defined type names. The lexical phase looked up the
- // type.
- //
+ // This is for user defined type names. The lexical phase looked up the type.
TType& structure = static_cast<TVariable*>($1.symbol)->getType();
- TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
- $$.setBasic(EbtStruct, qual, @1);
- $$.userDef = &structure;
+ $$.initializeStruct(structure.getStruct(), false, @1);
}
;
struct_specifier
- : STRUCT identifier LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
+ : STRUCT identifier LEFT_BRACE { context->enterStructDeclaration(@2, *$2.string); } struct_declaration_list RIGHT_BRACE {
$$ = context->addStructure(@1, @2, $2.string, $5);
}
- | STRUCT LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
+ | STRUCT LEFT_BRACE { context->enterStructDeclaration(@2, *$2.string); } struct_declaration_list RIGHT_BRACE {
$$ = context->addStructure(@1, @$, NewPoolTString(""), $4);
}
;
struct_declaration_list
: struct_declaration {
- $$ = $1;
+ $$ = context->addStructFieldList($1, @1);
}
| struct_declaration_list struct_declaration {
- $$ = $1;
- for (size_t i = 0; i < $2->size(); ++i) {
- TField* field = (*$2)[i];
- for (size_t j = 0; j < $$->size(); ++j) {
- if ((*$$)[j]->name() == field->name()) {
- context->error(@2, "duplicate field name in structure:", "struct", field->name().c_str());
- context->recover();
- }
- }
- $$->push_back(field);
- }
+ $$ = context->combineStructFieldLists($1, $2, @2);
}
;
@@ -1311,9 +1223,7 @@ struct_declaration
}
| type_qualifier type_specifier struct_declarator_list SEMICOLON {
// ES3 Only, but errors should be handled elsewhere
- $2.qualifier = $1.qualifier;
- $2.layoutQualifier = $1.layoutQualifier;
- $$ = context->addStructDeclaratorList($2, $3);
+ $$ = context->addStructDeclaratorListWithQualifiers(*$1, &$2, $3);
}
;
@@ -1329,23 +1239,10 @@ struct_declarator_list
struct_declarator
: identifier {
- if (context->reservedErrorCheck(@1, *$1.string))
- context->recover();
-
- TType* type = new TType(EbtVoid, EbpUndefined);
- $$ = new TField(type, $1.string, @1);
+ $$ = context->parseStructDeclarator($1.string, @1);
}
- | identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
- if (context->reservedErrorCheck(@1, *$1.string))
- context->recover();
-
- TType* type = new TType(EbtVoid, EbpUndefined);
- int size;
- if (context->arraySizeErrorCheck(@3, $3, size))
- context->recover();
- type->setArraySize(size);
-
- $$ = new TField(type, $1.string, @1);
+ | identifier array_specifier {
+ $$ = context->parseStructArrayDeclarator($1.string, @1, *($2), @2);
}
;
@@ -1358,8 +1255,8 @@ declaration_statement
;
statement
- : compound_statement { $$ = $1; }
- | simple_statement { $$ = $1; }
+ : compound_statement_with_scope { $$ = $1; }
+ | simple_statement { $$ = $1; }
;
// Grammar Note: Labeled statements for SWITCH only; 'goto' is not supported.
@@ -1374,13 +1271,13 @@ simple_statement
| jump_statement { $$ = $1; }
;
-compound_statement
- : LEFT_BRACE RIGHT_BRACE { $$ = 0; }
+compound_statement_with_scope
+ : LEFT_BRACE RIGHT_BRACE {
+ $$ = new TIntermBlock();
+ $$->setLine(@$);
+ }
| LEFT_BRACE { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE {
- if ($3 != 0) {
- $3->setOp(EOpSequence);
- $3->setLine(@$);
- }
+ $3->setLine(@$);
$$ = $3;
}
;
@@ -1396,38 +1293,36 @@ statement_with_scope
;
compound_statement_no_new_scope
- // Statement that doesn't create a new scope, for selection_statement, iteration_statement
+ // Statement that doesn't create a new scope for iteration_statement, function definition (scope is created for parameters)
: LEFT_BRACE RIGHT_BRACE {
- $$ = 0;
+ $$ = new TIntermBlock();
+ $$->setLine(@$);
}
| LEFT_BRACE statement_list RIGHT_BRACE {
- if ($2) {
- $2->setOp(EOpSequence);
- $2->setLine(@$);
- }
+ $2->setLine(@$);
$$ = $2;
}
;
statement_list
: statement {
- $$ = context->intermediate.makeAggregate($1, @$);
+ $$ = new TIntermBlock();
+ $$->appendStatement($1);
}
| statement_list statement {
- $$ = context->intermediate.growAggregate($1, $2, @$);
+ $$ = $1;
+ $$->appendStatement($2);
}
;
expression_statement
- : SEMICOLON { $$ = 0; }
- | expression SEMICOLON { $$ = static_cast<TIntermNode*>($1); }
+ : SEMICOLON { $$ = context->addEmptyStatement(@$); }
+ | expression SEMICOLON { $$ = $1; }
;
selection_statement
: IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement {
- if (context->boolErrorCheck(@1, $3))
- context->recover();
- $$ = context->intermediate.addSelection($3, $5, @1);
+ $$ = context->addIfElse($3, $5, @1);
}
;
@@ -1438,12 +1333,14 @@ selection_rest_statement
}
| statement_with_scope {
$$.node1 = $1;
- $$.node2 = 0;
+ $$.node2 = nullptr;
}
;
+// Note that we've diverged from the spec grammar here a bit for the sake of simplicity.
+// We're reusing compound_statement_with_scope instead of having separate rules for switch.
switch_statement
- : SWITCH LEFT_PAREN expression RIGHT_PAREN { context->incrSwitchNestingLevel(); } compound_statement {
+ : SWITCH LEFT_PAREN expression RIGHT_PAREN { context->incrSwitchNestingLevel(); } compound_statement_with_scope {
$$ = context->addSwitch($3, $6, @1);
context->decrSwitchNestingLevel();
}
@@ -1459,42 +1356,28 @@ case_label
;
condition
- // In 1996 c++ draft, conditions can include single declarations
: expression {
$$ = $1;
- if (context->boolErrorCheck($1->getLine(), $1))
- context->recover();
+ context->checkIsScalarBool($1->getLine(), $1);
}
| fully_specified_type identifier EQUAL initializer {
- TIntermNode *intermNode;
- if (context->boolErrorCheck(@2, $1))
- context->recover();
-
- if (!context->executeInitializer(@2, *$2.string, $1, $4, &intermNode))
- $$ = $4;
- else {
- context->recover();
- $$ = 0;
- }
+ $$ = context->addConditionInitializer($1, *$2.string, $4, @2);
}
;
iteration_statement
: WHILE LEFT_PAREN { context->symbolTable.push(); context->incrLoopNestingLevel(); } condition RIGHT_PAREN statement_no_new_scope {
context->symbolTable.pop();
- $$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, @1);
+ $$ = context->addLoop(ELoopWhile, 0, $4, 0, $6, @1);
context->decrLoopNestingLevel();
}
| DO { context->incrLoopNestingLevel(); } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
- if (context->boolErrorCheck(@8, $6))
- context->recover();
-
- $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, @4);
+ $$ = context->addLoop(ELoopDoWhile, 0, $6, 0, $3, @4);
context->decrLoopNestingLevel();
}
| FOR LEFT_PAREN { context->symbolTable.push(); context->incrLoopNestingLevel(); } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
context->symbolTable.pop();
- $$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), $7, @1);
+ $$ = context->addLoop(ELoopFor, $4, $5.node1, reinterpret_cast<TIntermTyped*>($5.node2), $7, @1);
context->decrLoopNestingLevel();
}
;
@@ -1513,7 +1396,7 @@ conditionopt
$$ = $1;
}
| /* May be null */ {
- $$ = 0;
+ $$ = nullptr;
}
;
@@ -1542,7 +1425,6 @@ jump_statement
$$ = context->addBranch(EOpReturn, $2, @1);
}
| DISCARD SEMICOLON {
- FRAG_ONLY("discard", @1);
$$ = context->addBranch(EOpKill, @1);
}
;
@@ -1551,12 +1433,13 @@ jump_statement
translation_unit
: external_declaration {
- $$ = $1;
+ $$ = new TIntermBlock();
+ $$->setLine(@$);
+ $$->appendStatement($1);
context->setTreeRoot($$);
}
| translation_unit external_declaration {
- $$ = context->intermediate.growAggregate($1, $2, @$);
- context->setTreeRoot($$);
+ $$->appendStatement($2);
}
;
@@ -1571,10 +1454,10 @@ external_declaration
function_definition
: function_prototype {
- context->parseFunctionPrototype(@1, $1.function, &$1.intermAggregate);
+ context->parseFunctionDefinitionHeader(@1, &($1.function), &($1.intermFunctionPrototype));
}
compound_statement_no_new_scope {
- $$ = context->addFunctionDefinition(*($1.function), $1.intermAggregate, $3, @1);
+ $$ = context->addFunctionDefinition($1.intermFunctionPrototype, $3, @1);
}
;
diff --git a/src/3rdparty/angle/src/compiler/translator/intermOut.cpp b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp
deleted file mode 100644
index 6dca547f08..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/intermOut.cpp
+++ /dev/null
@@ -1,626 +0,0 @@
-//
-// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/translator/Intermediate.h"
-#include "compiler/translator/SymbolTable.h"
-
-namespace
-{
-
-void OutputFunction(TInfoSinkBase &out, const char *str, TIntermAggregate *node)
-{
- const char *internal = node->getNameObj().isInternal() ? " (internal function)" : "";
- out << str << internal << ": " << node->getNameObj().getString();
-}
-
-//
-// Two purposes:
-// 1. Show an example of how to iterate tree. Functions can
-// also directly call Traverse() on children themselves to
-// have finer grained control over the process than shown here.
-// See the last function for how to get started.
-// 2. Print out a text based description of the tree.
-//
-
-//
-// Use this class to carry along data from node to node in
-// the traversal
-//
-class TOutputTraverser : public TIntermTraverser
-{
- public:
- TOutputTraverser(TInfoSinkBase &i)
- : TIntermTraverser(true, false, false),
- sink(i)
- {
- }
- TInfoSinkBase& sink;
-
- protected:
- void visitSymbol(TIntermSymbol *) override;
- void visitConstantUnion(TIntermConstantUnion *) override;
- bool visitBinary(Visit visit, TIntermBinary *) override;
- bool visitUnary(Visit visit, TIntermUnary *) override;
- bool visitSelection(Visit visit, TIntermSelection *) override;
- bool visitAggregate(Visit visit, TIntermAggregate *) override;
- bool visitLoop(Visit visit, TIntermLoop *) override;
- bool visitBranch(Visit visit, TIntermBranch *) override;
-};
-
-//
-// Helper functions for printing, not part of traversing.
-//
-void OutputTreeText(TInfoSinkBase &sink, TIntermNode *node, const int depth)
-{
- int i;
-
- sink.location(node->getLine());
-
- for (i = 0; i < depth; ++i)
- sink << " ";
-}
-
-} // namespace anonymous
-
-//
-// The rest of the file are the traversal functions. The last one
-// is the one that starts the traversal.
-//
-// Return true from interior nodes to have the external traversal
-// continue on to children. If you process children yourself,
-// return false.
-//
-
-void TOutputTraverser::visitSymbol(TIntermSymbol *node)
-{
- OutputTreeText(sink, node, mDepth);
-
- sink << "'" << node->getSymbol() << "' ";
- sink << "(" << node->getCompleteString() << ")\n";
-}
-
-bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
-{
- TInfoSinkBase& out = sink;
-
- OutputTreeText(out, node, mDepth);
-
- switch (node->getOp())
- {
- case EOpAssign:
- out << "move second child to first child";
- break;
- case EOpInitialize:
- out << "initialize first child with second child";
- break;
- case EOpAddAssign:
- out << "add second child into first child";
- break;
- case EOpSubAssign:
- out << "subtract second child into first child";
- break;
- case EOpMulAssign:
- out << "multiply second child into first child";
- break;
- case EOpVectorTimesMatrixAssign:
- out << "matrix mult second child into first child";
- break;
- case EOpVectorTimesScalarAssign:
- out << "vector scale second child into first child";
- break;
- case EOpMatrixTimesScalarAssign:
- out << "matrix scale second child into first child";
- break;
- case EOpMatrixTimesMatrixAssign:
- out << "matrix mult second child into first child";
- break;
- case EOpDivAssign:
- out << "divide second child into first child";
- break;
- case EOpIModAssign:
- out << "modulo second child into first child";
- break;
- case EOpBitShiftLeftAssign:
- out << "bit-wise shift first child left by second child";
- break;
- case EOpBitShiftRightAssign:
- out << "bit-wise shift first child right by second child";
- break;
- case EOpBitwiseAndAssign:
- out << "bit-wise and second child into first child";
- break;
- case EOpBitwiseXorAssign:
- out << "bit-wise xor second child into first child";
- break;
- case EOpBitwiseOrAssign:
- out << "bit-wise or second child into first child";
- break;
-
- case EOpIndexDirect:
- out << "direct index";
- break;
- case EOpIndexIndirect:
- out << "indirect index";
- break;
- case EOpIndexDirectStruct:
- out << "direct index for structure";
- break;
- case EOpIndexDirectInterfaceBlock:
- out << "direct index for interface block";
- break;
- case EOpVectorSwizzle:
- out << "vector swizzle";
- break;
-
- case EOpAdd:
- out << "add";
- break;
- case EOpSub:
- out << "subtract";
- break;
- case EOpMul:
- out << "component-wise multiply";
- break;
- case EOpDiv:
- out << "divide";
- break;
- case EOpIMod:
- out << "modulo";
- break;
- case EOpBitShiftLeft:
- out << "bit-wise shift left";
- break;
- case EOpBitShiftRight:
- out << "bit-wise shift right";
- break;
- case EOpBitwiseAnd:
- out << "bit-wise and";
- break;
- case EOpBitwiseXor:
- out << "bit-wise xor";
- break;
- case EOpBitwiseOr:
- out << "bit-wise or";
- break;
-
- case EOpEqual:
- out << "Compare Equal";
- break;
- case EOpNotEqual:
- out << "Compare Not Equal";
- break;
- case EOpLessThan:
- out << "Compare Less Than";
- break;
- case EOpGreaterThan:
- out << "Compare Greater Than";
- break;
- case EOpLessThanEqual:
- out << "Compare Less Than or Equal";
- break;
- case EOpGreaterThanEqual:
- out << "Compare Greater Than or Equal";
- break;
-
- case EOpVectorTimesScalar:
- out << "vector-scale";
- break;
- case EOpVectorTimesMatrix:
- out << "vector-times-matrix";
- break;
- case EOpMatrixTimesVector:
- out << "matrix-times-vector";
- break;
- case EOpMatrixTimesScalar:
- out << "matrix-scale";
- break;
- case EOpMatrixTimesMatrix:
- out << "matrix-multiply";
- break;
-
- case EOpLogicalOr:
- out << "logical-or";
- break;
- case EOpLogicalXor:
- out << "logical-xor";
- break;
- case EOpLogicalAnd:
- out << "logical-and";
- break;
- default:
- out << "<unknown op>";
- }
-
- out << " (" << node->getCompleteString() << ")";
-
- out << "\n";
-
- // Special handling for direct indexes. Because constant
- // unions are not aware they are struct indexes, treat them
- // here where we have that contextual knowledge.
- if (node->getOp() == EOpIndexDirectStruct ||
- node->getOp() == EOpIndexDirectInterfaceBlock)
- {
- mDepth++;
- node->getLeft()->traverse(this);
- mDepth--;
-
- TIntermConstantUnion *intermConstantUnion = node->getRight()->getAsConstantUnion();
- ASSERT(intermConstantUnion);
-
- OutputTreeText(out, intermConstantUnion, mDepth + 1);
-
- // The following code finds the field name from the constant union
- const TConstantUnion *constantUnion = intermConstantUnion->getUnionArrayPointer();
- const TStructure *structure = node->getLeft()->getType().getStruct();
- const TInterfaceBlock *interfaceBlock = node->getLeft()->getType().getInterfaceBlock();
- ASSERT(structure || interfaceBlock);
-
- const TFieldList &fields = structure ? structure->fields() : interfaceBlock->fields();
-
- const TField *field = fields[constantUnion->getIConst()];
-
- out << constantUnion->getIConst() << " (field '" << field->name() << "')";
-
- return false;
- }
-
- return true;
-}
-
-bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
-{
- TInfoSinkBase& out = sink;
-
- OutputTreeText(out, node, mDepth);
-
- switch (node->getOp())
- {
- case EOpNegative: out << "Negate value"; break;
- case EOpPositive: out << "Positive sign"; break;
- case EOpVectorLogicalNot:
- case EOpLogicalNot: out << "Negate conditional"; break;
- case EOpBitwiseNot: out << "bit-wise not"; break;
-
- case EOpPostIncrement: out << "Post-Increment"; break;
- case EOpPostDecrement: out << "Post-Decrement"; break;
- case EOpPreIncrement: out << "Pre-Increment"; break;
- case EOpPreDecrement: out << "Pre-Decrement"; break;
-
- case EOpRadians: out << "radians"; break;
- case EOpDegrees: out << "degrees"; break;
- case EOpSin: out << "sine"; break;
- case EOpCos: out << "cosine"; break;
- case EOpTan: out << "tangent"; break;
- case EOpAsin: out << "arc sine"; break;
- case EOpAcos: out << "arc cosine"; break;
- case EOpAtan: out << "arc tangent"; break;
-
- case EOpSinh: out << "hyperbolic sine"; break;
- case EOpCosh: out << "hyperbolic cosine"; break;
- case EOpTanh: out << "hyperbolic tangent"; break;
- case EOpAsinh: out << "arc hyperbolic sine"; break;
- case EOpAcosh: out << "arc hyperbolic cosine"; break;
- case EOpAtanh: out << "arc hyperbolic tangent"; break;
-
- case EOpExp: out << "exp"; break;
- case EOpLog: out << "log"; break;
- case EOpExp2: out << "exp2"; break;
- case EOpLog2: out << "log2"; break;
- case EOpSqrt: out << "sqrt"; break;
- case EOpInverseSqrt: out << "inverse sqrt"; break;
-
- case EOpAbs: out << "Absolute value"; break;
- case EOpSign: out << "Sign"; break;
- case EOpFloor: out << "Floor"; break;
- case EOpTrunc: out << "Truncate"; break;
- case EOpRound: out << "Round"; break;
- case EOpRoundEven: out << "Round half even"; break;
- case EOpCeil: out << "Ceiling"; break;
- case EOpFract: out << "Fraction"; break;
- case EOpIsNan: out << "Is not a number"; break;
- case EOpIsInf: out << "Is infinity"; break;
-
- case EOpFloatBitsToInt: out << "float bits to int"; break;
- case EOpFloatBitsToUint: out << "float bits to uint"; break;
- case EOpIntBitsToFloat: out << "int bits to float"; break;
- case EOpUintBitsToFloat: out << "uint bits to float"; break;
-
- case EOpPackSnorm2x16: out << "pack Snorm 2x16"; break;
- case EOpPackUnorm2x16: out << "pack Unorm 2x16"; break;
- case EOpPackHalf2x16: out << "pack half 2x16"; break;
-
- case EOpUnpackSnorm2x16: out << "unpack Snorm 2x16"; break;
- case EOpUnpackUnorm2x16: out << "unpack Unorm 2x16"; break;
- case EOpUnpackHalf2x16: out << "unpack half 2x16"; break;
-
- case EOpLength: out << "length"; break;
- case EOpNormalize: out << "normalize"; break;
- // case EOpDPdx: out << "dPdx"; break;
- // case EOpDPdy: out << "dPdy"; break;
- // case EOpFwidth: out << "fwidth"; break;
-
- case EOpDeterminant: out << "determinant"; break;
- case EOpTranspose: out << "transpose"; break;
- case EOpInverse: out << "inverse"; break;
-
- case EOpAny: out << "any"; break;
- case EOpAll: out << "all"; break;
-
- default:
- out.prefix(EPrefixError);
- out << "Bad unary op";
- }
-
- out << " (" << node->getCompleteString() << ")";
-
- out << "\n";
-
- return true;
-}
-
-bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
-{
- TInfoSinkBase &out = sink;
-
- if (node->getOp() == EOpNull)
- {
- out.prefix(EPrefixError);
- out << "node is still EOpNull!";
- return true;
- }
-
- OutputTreeText(out, node, mDepth);
-
- switch (node->getOp())
- {
- case EOpSequence: out << "Sequence\n"; return true;
- case EOpComma: out << "Comma\n"; return true;
- case EOpFunction: OutputFunction(out, "Function Definition", node); break;
- case EOpFunctionCall: OutputFunction(out, "Function Call", node); break;
- case EOpParameters: out << "Function Parameters: "; break;
- case EOpPrototype: OutputFunction(out, "Function Prototype", node); break;
-
- case EOpConstructFloat: out << "Construct float"; break;
- case EOpConstructVec2: out << "Construct vec2"; break;
- case EOpConstructVec3: out << "Construct vec3"; break;
- case EOpConstructVec4: out << "Construct vec4"; break;
- case EOpConstructBool: out << "Construct bool"; break;
- case EOpConstructBVec2: out << "Construct bvec2"; break;
- case EOpConstructBVec3: out << "Construct bvec3"; break;
- case EOpConstructBVec4: out << "Construct bvec4"; break;
- case EOpConstructInt: out << "Construct int"; break;
- case EOpConstructIVec2: out << "Construct ivec2"; break;
- case EOpConstructIVec3: out << "Construct ivec3"; break;
- case EOpConstructIVec4: out << "Construct ivec4"; break;
- case EOpConstructUInt: out << "Construct uint"; break;
- case EOpConstructUVec2: out << "Construct uvec2"; break;
- case EOpConstructUVec3: out << "Construct uvec3"; break;
- case EOpConstructUVec4: out << "Construct uvec4"; break;
- case EOpConstructMat2: out << "Construct mat2"; break;
- case EOpConstructMat2x3: out << "Construct mat2x3"; break;
- case EOpConstructMat2x4: out << "Construct mat2x4"; break;
- case EOpConstructMat3x2: out << "Construct mat3x2"; break;
- case EOpConstructMat3: out << "Construct mat3"; break;
- case EOpConstructMat3x4: out << "Construct mat3x4"; break;
- case EOpConstructMat4x2: out << "Construct mat4x2"; break;
- case EOpConstructMat4x3: out << "Construct mat4x3"; break;
- case EOpConstructMat4: out << "Construct mat4"; break;
- case EOpConstructStruct: out << "Construct structure"; break;
-
- case EOpLessThan: out << "Compare Less Than"; break;
- case EOpGreaterThan: out << "Compare Greater Than"; break;
- case EOpLessThanEqual: out << "Compare Less Than or Equal"; break;
- case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break;
- case EOpVectorEqual: out << "Equal"; break;
- case EOpVectorNotEqual: out << "NotEqual"; break;
-
- case EOpMod: out << "mod"; break;
- case EOpModf: out << "modf"; break;
- case EOpPow: out << "pow"; break;
-
- case EOpAtan: out << "arc tangent"; break;
-
- case EOpMin: out << "min"; break;
- case EOpMax: out << "max"; break;
- case EOpClamp: out << "clamp"; break;
- case EOpMix: out << "mix"; break;
- case EOpStep: out << "step"; break;
- case EOpSmoothStep: out << "smoothstep"; break;
-
- case EOpDistance: out << "distance"; break;
- case EOpDot: out << "dot-product"; break;
- case EOpCross: out << "cross-product"; break;
- case EOpFaceForward: out << "face-forward"; break;
- case EOpReflect: out << "reflect"; break;
- case EOpRefract: out << "refract"; break;
- case EOpMul: out << "component-wise multiply"; break;
-
- case EOpOuterProduct: out << "outer product"; break;
-
- case EOpDeclaration: out << "Declaration: "; break;
- case EOpInvariantDeclaration: out << "Invariant Declaration: "; break;
-
- default:
- out.prefix(EPrefixError);
- out << "Bad aggregation op";
- }
-
- if (node->getOp() != EOpSequence && node->getOp() != EOpParameters)
- out << " (" << node->getCompleteString() << ")";
-
- out << "\n";
-
- return true;
-}
-
-bool TOutputTraverser::visitSelection(Visit visit, TIntermSelection *node)
-{
- TInfoSinkBase &out = sink;
-
- OutputTreeText(out, node, mDepth);
-
- out << "Test condition and select";
- out << " (" << node->getCompleteString() << ")\n";
-
- ++mDepth;
-
- OutputTreeText(sink, node, mDepth);
- out << "Condition\n";
- node->getCondition()->traverse(this);
-
- OutputTreeText(sink, node, mDepth);
- if (node->getTrueBlock())
- {
- out << "true case\n";
- node->getTrueBlock()->traverse(this);
- }
- else
- {
- out << "true case is null\n";
- }
-
- if (node->getFalseBlock())
- {
- OutputTreeText(sink, node, mDepth);
- out << "false case\n";
- node->getFalseBlock()->traverse(this);
- }
-
- --mDepth;
-
- return false;
-}
-
-void TOutputTraverser::visitConstantUnion(TIntermConstantUnion *node)
-{
- TInfoSinkBase &out = sink;
-
- size_t size = node->getType().getObjectSize();
-
- for (size_t i = 0; i < size; i++)
- {
- OutputTreeText(out, node, mDepth);
- switch (node->getUnionArrayPointer()[i].getType())
- {
- case EbtBool:
- if (node->getUnionArrayPointer()[i].getBConst())
- out << "true";
- else
- out << "false";
-
- out << " (" << "const bool" << ")";
- out << "\n";
- break;
- case EbtFloat:
- out << node->getUnionArrayPointer()[i].getFConst();
- out << " (const float)\n";
- break;
- case EbtInt:
- out << node->getUnionArrayPointer()[i].getIConst();
- out << " (const int)\n";
- break;
- case EbtUInt:
- out << node->getUnionArrayPointer()[i].getUConst();
- out << " (const uint)\n";
- break;
- default:
- out.message(EPrefixInternalError, node->getLine(), "Unknown constant");
- break;
- }
- }
-}
-
-bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop *node)
-{
- TInfoSinkBase &out = sink;
-
- OutputTreeText(out, node, mDepth);
-
- out << "Loop with condition ";
- if (node->getType() == ELoopDoWhile)
- out << "not ";
- out << "tested first\n";
-
- ++mDepth;
-
- OutputTreeText(sink, node, mDepth);
- if (node->getCondition())
- {
- out << "Loop Condition\n";
- node->getCondition()->traverse(this);
- }
- else
- {
- out << "No loop condition\n";
- }
-
- OutputTreeText(sink, node, mDepth);
- if (node->getBody())
- {
- out << "Loop Body\n";
- node->getBody()->traverse(this);
- }
- else
- {
- out << "No loop body\n";
- }
-
- if (node->getExpression())
- {
- OutputTreeText(sink, node, mDepth);
- out << "Loop Terminal Expression\n";
- node->getExpression()->traverse(this);
- }
-
- --mDepth;
-
- return false;
-}
-
-bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch *node)
-{
- TInfoSinkBase &out = sink;
-
- OutputTreeText(out, node, mDepth);
-
- switch (node->getFlowOp())
- {
- case EOpKill: out << "Branch: Kill"; break;
- case EOpBreak: out << "Branch: Break"; break;
- case EOpContinue: out << "Branch: Continue"; break;
- case EOpReturn: out << "Branch: Return"; break;
- default: out << "Branch: Unknown Branch"; break;
- }
-
- if (node->getExpression())
- {
- out << " with expression\n";
- ++mDepth;
- node->getExpression()->traverse(this);
- --mDepth;
- }
- else
- {
- out << "\n";
- }
-
- return false;
-}
-
-//
-// This function is the one to call externally to start the traversal.
-// Individual functions can be initialized to 0 to skip processing of that
-// type of node. Its children will still be processed.
-//
-void TIntermediate::outputTree(TIntermNode *root, TInfoSinkBase &infoSink)
-{
- TOutputTraverser it(infoSink);
-
- ASSERT(root);
-
- root->traverse(&it);
-}
diff --git a/src/3rdparty/angle/src/compiler/translator/length_limits.h b/src/3rdparty/angle/src/compiler/translator/length_limits.h
index 88634381fa..fcda639d71 100644
--- a/src/3rdparty/angle/src/compiler/translator/length_limits.h
+++ b/src/3rdparty/angle/src/compiler/translator/length_limits.h
@@ -16,6 +16,11 @@
// These constants are factored out from the rest of the headers to
// make it easier to reference them from the compiler sources.
+namespace sh
+{
+
size_t GetGlobalMaxTokenSize(ShShaderSpec spec);
-#endif // COMPILER_TRANSLATOR_LENGTHLIMITS_H_
+} // namespace sh
+
+#endif // COMPILER_TRANSLATOR_LENGTHLIMITS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/parseConst.cpp b/src/3rdparty/angle/src/compiler/translator/parseConst.cpp
deleted file mode 100644
index 1897ed151c..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/parseConst.cpp
+++ /dev/null
@@ -1,264 +0,0 @@
-//
-// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/translator/ParseContext.h"
-
-//
-// Use this class to carry along data from node to node in
-// the traversal
-//
-class TConstTraverser : public TIntermTraverser
-{
- public:
- TConstTraverser(ConstantUnion *cUnion, bool singleConstParam,
- TOperator constructType, TInfoSink &sink, TType &t)
- : error(false),
- mIndex(0),
- mUnionArray(cUnion),
- mType(t),
- mConstructorType(constructType),
- mSingleConstantParam(singleConstParam),
- mInfoSink(sink),
- mSize(0),
- mIsDiagonalMatrixInit(false),
- mMatrixCols(0),
- mMatrixRows(0)
- {
- }
-
- bool error;
-
- protected:
- void visitSymbol(TIntermSymbol *);
- void visitConstantUnion(TIntermConstantUnion *);
- bool visitBinary(Visit visit, TIntermBinary *);
- bool visitUnary(Visit visit, TIntermUnary *);
- bool visitSelection(Visit visit, TIntermSelection *);
- bool visitAggregate(Visit visit, TIntermAggregate *);
- bool visitLoop(Visit visit, TIntermLoop *);
- bool visitBranch(Visit visit, TIntermBranch *);
-
- size_t mIndex;
- ConstantUnion *mUnionArray;
- TType mType;
- TOperator mConstructorType;
- bool mSingleConstantParam;
- TInfoSink &mInfoSink;
- size_t mSize; // size of the constructor ( 4 for vec4)
- bool mIsDiagonalMatrixInit;
- int mMatrixCols; // columns of the matrix
- int mMatrixRows; // rows of the matrix
-};
-
-//
-// The rest of the file are the traversal functions. The last one
-// is the one that starts the traversal.
-//
-// Return true from interior nodes to have the external traversal
-// continue on to children. If you process children yourself,
-// return false.
-//
-void TConstTraverser::visitSymbol(TIntermSymbol *node)
-{
- mInfoSink.info.message(EPrefixInternalError, node->getLine(),
- "Symbol Node found in constant constructor");
- return;
-}
-
-bool TConstTraverser::visitBinary(Visit visit, TIntermBinary *node)
-{
- TQualifier qualifier = node->getType().getQualifier();
-
- if (qualifier != EvqConst)
- {
- TString buf;
- buf.append("'constructor' : assigning non-constant to ");
- buf.append(mType.getCompleteString());
- mInfoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
- error = true;
- return false;
- }
-
- mInfoSink.info.message(EPrefixInternalError, node->getLine(),
- "Binary Node found in constant constructor");
- return false;
-}
-
-bool TConstTraverser::visitUnary(Visit visit, TIntermUnary *node)
-{
- TString buf;
- buf.append("'constructor' : assigning non-constant to ");
- buf.append(mType.getCompleteString());
- mInfoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
- error = true;
- return false;
-}
-
-bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
-{
- if (!node->isConstructor() && node->getOp() != EOpComma)
- {
- TString buf;
- buf.append("'constructor' : assigning non-constant to ");
- buf.append(mType.getCompleteString());
- mInfoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
- error = true;
- return false;
- }
-
- if (node->getSequence()->size() == 0)
- {
- error = true;
- return false;
- }
-
- bool flag = node->getSequence()->size() == 1 &&
- (*node->getSequence())[0]->getAsTyped()->getAsConstantUnion();
- if (flag)
- {
- mSingleConstantParam = true;
- mConstructorType = node->getOp();
- mSize = node->getType().getObjectSize();
-
- if (node->getType().isMatrix())
- {
- mIsDiagonalMatrixInit = true;
- mMatrixCols = node->getType().getCols();
- mMatrixRows = node->getType().getRows();
- }
- }
-
- for (TIntermSequence::iterator p = node->getSequence()->begin();
- p != node->getSequence()->end(); p++)
- {
- if (node->getOp() == EOpComma)
- mIndex = 0;
- (*p)->traverse(this);
- }
- if (flag)
- {
- mSingleConstantParam = false;
- mConstructorType = EOpNull;
- mSize = 0;
- mIsDiagonalMatrixInit = false;
- mMatrixCols = 0;
- mMatrixRows = 0;
- }
- return false;
-}
-
-bool TConstTraverser::visitSelection(Visit visit, TIntermSelection *node)
-{
- mInfoSink.info.message(EPrefixInternalError, node->getLine(),
- "Selection Node found in constant constructor");
- error = true;
- return false;
-}
-
-void TConstTraverser::visitConstantUnion(TIntermConstantUnion *node)
-{
- if (!node->getUnionArrayPointer())
- {
- // The constant was not initialized, this should already have been logged
- ASSERT(mInfoSink.info.size() != 0);
- return;
- }
-
- ConstantUnion *leftUnionArray = mUnionArray;
- size_t instanceSize = mType.getObjectSize();
- TBasicType basicType = mType.getBasicType();
-
- if (mIndex >= instanceSize)
- return;
-
- if (!mSingleConstantParam)
- {
- size_t objectSize = node->getType().getObjectSize();
- ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
- for (size_t i=0; i < objectSize; i++)
- {
- if (mIndex >= instanceSize)
- return;
- leftUnionArray[mIndex].cast(basicType, rightUnionArray[i]);
- mIndex++;
- }
- }
- else
- {
- size_t totalSize = mIndex + mSize;
- ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
- if (!mIsDiagonalMatrixInit)
- {
- int count = 0;
- for (size_t i = mIndex; i < totalSize; i++)
- {
- if (i >= instanceSize)
- return;
- leftUnionArray[i].cast(basicType, rightUnionArray[count]);
- mIndex++;
- if (node->getType().getObjectSize() > 1)
- count++;
- }
- }
- else
- {
- // for matrix diagonal constructors from a single scalar
- for (int i = 0, col = 0; col < mMatrixCols; col++)
- {
- for (int row = 0; row < mMatrixRows; row++, i++)
- {
- if (col == row)
- {
- leftUnionArray[i].cast(basicType, rightUnionArray[0]);
- }
- else
- {
- leftUnionArray[i].setFConst(0.0f);
- }
- mIndex++;
- }
- }
- }
- }
-}
-
-bool TConstTraverser::visitLoop(Visit visit, TIntermLoop *node)
-{
- mInfoSink.info.message(EPrefixInternalError, node->getLine(),
- "Loop Node found in constant constructor");
- error = true;
- return false;
-}
-
-bool TConstTraverser::visitBranch(Visit visit, TIntermBranch *node)
-{
- mInfoSink.info.message(EPrefixInternalError, node->getLine(),
- "Branch Node found in constant constructor");
- error = true;
- return false;
-}
-
-//
-// This function is the one to call externally to start the traversal.
-// Individual functions can be initialized to 0 to skip processing of that
-// type of node. It's children will still be processed.
-//
-bool TIntermediate::parseConstTree(
- const TSourceLoc &line, TIntermNode *root, ConstantUnion *unionArray,
- TOperator constructorType, TType t, bool singleConstantParam)
-{
- if (root == 0)
- return false;
-
- TConstTraverser it(unionArray, singleConstantParam, constructorType,
- mInfoSink, t);
-
- root->traverse(&it);
- if (it.error)
- return true;
- else
- return false;
-}
diff --git a/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp
deleted file mode 100644
index 790974a2bf..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/translator/InfoSink.h"
-#include "compiler/translator/ParseContext.h"
-#include "compiler/translator/depgraph/DependencyGraphOutput.h"
-#include "compiler/translator/timing/RestrictFragmentShaderTiming.h"
-
-RestrictFragmentShaderTiming::RestrictFragmentShaderTiming(TInfoSinkBase& sink)
- : mSink(sink)
- , mNumErrors(0)
-{
- // Sampling ops found only in fragment shaders.
- mSamplingOps.insert("texture2D(s21;vf2;f1;");
- mSamplingOps.insert("texture2DProj(s21;vf3;f1;");
- mSamplingOps.insert("texture2DProj(s21;vf4;f1;");
- mSamplingOps.insert("textureCube(sC1;vf3;f1;");
- // Sampling ops found in both vertex and fragment shaders.
- mSamplingOps.insert("texture2D(s21;vf2;");
- mSamplingOps.insert("texture2DProj(s21;vf3;");
- mSamplingOps.insert("texture2DProj(s21;vf4;");
- mSamplingOps.insert("textureCube(sC1;vf3;");
- // Sampling ops provided by OES_EGL_image_external.
- mSamplingOps.insert("texture2D(1;vf2;");
- mSamplingOps.insert("texture2DProj(1;vf3;");
- mSamplingOps.insert("texture2DProj(1;vf4;");
- // Sampling ops provided by ARB_texture_rectangle.
- mSamplingOps.insert("texture2DRect(1;vf2;");
- mSamplingOps.insert("texture2DRectProj(1;vf3;");
- mSamplingOps.insert("texture2DRectProj(1;vf4;");
- // Sampling ops provided by EXT_shader_texture_lod.
- mSamplingOps.insert("texture2DLodEXT(1;vf2;f1;");
- mSamplingOps.insert("texture2DProjLodEXT(1;vf3;f1;");
- mSamplingOps.insert("texture2DProjLodEXT(1;vf4;f1;");
- mSamplingOps.insert("textureCubeLodEXT(1;vf4;f1;");
- mSamplingOps.insert("texture2DGradEXT(1;vf2;vf2;vf2;");
- mSamplingOps.insert("texture2DProjGradEXT(1;vf3;vf2;vf2;");
- mSamplingOps.insert("texture2DProjGradEXT(1;vf4;vf2;vf2;");
- mSamplingOps.insert("textureCubeGradEXT(1;vf3;vf3;vf3;");
-}
-
-// FIXME(mvujovic): We do not know if the execution time of built-in operations like sin, pow, etc.
-// can vary based on the value of the input arguments. If so, we should restrict those as well.
-void RestrictFragmentShaderTiming::enforceRestrictions(const TDependencyGraph& graph)
-{
- mNumErrors = 0;
-
- // FIXME(mvujovic): The dependency graph does not support user defined function calls right now,
- // so we generate errors for them.
- validateUserDefinedFunctionCallUsage(graph);
-
- // Starting from each sampler, traverse the dependency graph and generate an error each time we
- // hit a node where sampler dependent values are not allowed.
- for (auto samplerSymbol : graph.samplerSymbols())
- {
- clearVisited();
- samplerSymbol->traverse(this);
- }
-}
-
-void RestrictFragmentShaderTiming::validateUserDefinedFunctionCallUsage(const TDependencyGraph& graph)
-{
- for (const auto* functionCall : graph.userDefinedFunctionCalls())
- {
- beginError(functionCall->getIntermFunctionCall());
- mSink << "A call to a user defined function is not permitted.\n";
- }
-}
-
-void RestrictFragmentShaderTiming::beginError(const TIntermNode* node)
-{
- ++mNumErrors;
- mSink.prefix(EPrefixError);
- mSink.location(node->getLine());
-}
-
-bool RestrictFragmentShaderTiming::isSamplingOp(const TIntermAggregate* intermFunctionCall) const
-{
- return !intermFunctionCall->isUserDefined() &&
- mSamplingOps.find(intermFunctionCall->getName()) != mSamplingOps.end();
-}
-
-void RestrictFragmentShaderTiming::visitArgument(TGraphArgument* parameter)
-{
- // Texture cache access time might leak sensitive information.
- // Thus, we restrict sampler dependent values from affecting the coordinate or LOD bias of a
- // sampling operation.
- if (isSamplingOp(parameter->getIntermFunctionCall())) {
- switch (parameter->getArgumentNumber()) {
- case 1:
- // Second argument (coord)
- beginError(parameter->getIntermFunctionCall());
- mSink << "An expression dependent on a sampler is not permitted to be the"
- << " coordinate argument of a sampling operation.\n";
- break;
- case 2:
- // Third argument (bias)
- beginError(parameter->getIntermFunctionCall());
- mSink << "An expression dependent on a sampler is not permitted to be the"
- << " bias argument of a sampling operation.\n";
- break;
- default:
- // First argument (sampler)
- break;
- }
- }
-}
-
-void RestrictFragmentShaderTiming::visitSelection(TGraphSelection* selection)
-{
- beginError(selection->getIntermSelection());
- mSink << "An expression dependent on a sampler is not permitted in a conditional statement.\n";
-}
-
-void RestrictFragmentShaderTiming::visitLoop(TGraphLoop* loop)
-{
- beginError(loop->getIntermLoop());
- mSink << "An expression dependent on a sampler is not permitted in a loop condition.\n";
-}
-
-void RestrictFragmentShaderTiming::visitLogicalOp(TGraphLogicalOp* logicalOp)
-{
- beginError(logicalOp->getIntermLogicalOp());
- mSink << "An expression dependent on a sampler is not permitted on the left hand side of a logical "
- << logicalOp->getOpString()
- << " operator.\n";
-}
diff --git a/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h
deleted file mode 100644
index b8c7e82956..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_TRANSLATOR_TIMING_RESTRICTFRAGMENTSHADERTIMING_H_
-#define COMPILER_TRANSLATOR_TIMING_RESTRICTFRAGMENTSHADERTIMING_H_
-
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/depgraph/DependencyGraph.h"
-
-class TInfoSinkBase;
-
-class RestrictFragmentShaderTiming : TDependencyGraphTraverser
-{
- public:
- RestrictFragmentShaderTiming(TInfoSinkBase &sink);
- void enforceRestrictions(const TDependencyGraph &graph);
- int numErrors() const { return mNumErrors; }
-
- void visitArgument(TGraphArgument *parameter) override;
- void visitSelection(TGraphSelection *selection) override;
- void visitLoop(TGraphLoop *loop) override;
- void visitLogicalOp(TGraphLogicalOp *logicalOp) override;
-
- private:
- void beginError(const TIntermNode *node);
- void validateUserDefinedFunctionCallUsage(const TDependencyGraph &graph);
- bool isSamplingOp(const TIntermAggregate *intermFunctionCall) const;
-
- TInfoSinkBase &mSink;
- int mNumErrors;
-
- typedef std::set<TString> StringSet;
- StringSet mSamplingOps;
-};
-
-#endif // COMPILER_TRANSLATOR_TIMING_RESTRICTFRAGMENTSHADERTIMING_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp
deleted file mode 100644
index 7c1208a298..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/translator/timing/RestrictVertexShaderTiming.h"
-
-void RestrictVertexShaderTiming::visitSymbol(TIntermSymbol* node)
-{
- if (IsSampler(node->getBasicType())) {
- ++mNumErrors;
- mSink.message(EPrefixError,
- node->getLine(),
- "Samplers are not permitted in vertex shaders.\n");
- }
-}
diff --git a/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h
deleted file mode 100644
index 23a8217722..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h
+++ /dev/null
@@ -1,32 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_TRANSLATOR_TIMING_RESTRICTVERTEXSHADERTIMING_H_
-#define COMPILER_TRANSLATOR_TIMING_RESTRICTVERTEXSHADERTIMING_H_
-
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/InfoSink.h"
-
-class TInfoSinkBase;
-
-class RestrictVertexShaderTiming : public TIntermTraverser {
-public:
- RestrictVertexShaderTiming(TInfoSinkBase& sink)
- : TIntermTraverser(true, false, false)
- , mSink(sink)
- , mNumErrors(0) {}
-
- void enforceRestrictions(TIntermNode* root) { root->traverse(this); }
- int numErrors() { return mNumErrors; }
-
- void visitSymbol(TIntermSymbol *) override;
-
-private:
- TInfoSinkBase& mSink;
- int mNumErrors;
-};
-
-#endif // COMPILER_TRANSLATOR_TIMING_RESTRICTVERTEXSHADERTIMING_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/util.cpp b/src/3rdparty/angle/src/compiler/translator/util.cpp
index 0131137206..9738370c47 100644
--- a/src/3rdparty/angle/src/compiler/translator/util.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/util.cpp
@@ -8,17 +8,9 @@
#include <limits>
+#include "common/utilities.h"
#include "compiler/preprocessor/numeric_lex.h"
#include "compiler/translator/SymbolTable.h"
-#include "common/utilities.h"
-
-bool strtof_clamp(const std::string &str, float *value)
-{
- bool success = pp::numeric_lex_float(str, value);
- if (!success)
- *value = std::numeric_limits<float>::max();
- return success;
-}
bool atoi_clamp(const char *str, unsigned int *value)
{
@@ -31,135 +23,392 @@ bool atoi_clamp(const char *str, unsigned int *value)
namespace sh
{
-GLenum GLVariableType(const TType &type)
+namespace
{
- if (type.getBasicType() == EbtFloat)
+
+bool IsInterpolationIn(TQualifier qualifier)
+{
+ switch (qualifier)
+ {
+ case EvqSmoothIn:
+ case EvqFlatIn:
+ case EvqCentroidIn:
+ return true;
+ default:
+ return false;
+ }
+}
+
+} // anonymous namespace
+
+float NumericLexFloat32OutOfRangeToInfinity(const std::string &str)
+{
+ // Parses a decimal string using scientific notation into a floating point number.
+ // Out-of-range values are converted to infinity. Values that are too small to be
+ // represented are converted to zero.
+
+ // The mantissa in decimal scientific notation. The magnitude of the mantissa integer does not
+ // matter.
+ unsigned int decimalMantissa = 0;
+ size_t i = 0;
+ bool decimalPointSeen = false;
+ bool nonZeroSeenInMantissa = false;
+
+ // The exponent offset reflects the position of the decimal point.
+ int exponentOffset = -1;
+ while (i < str.length())
{
- if (type.isScalar())
+ const char c = str[i];
+ if (c == 'e' || c == 'E')
{
- return GL_FLOAT;
+ break;
+ }
+ if (c == '.')
+ {
+ decimalPointSeen = true;
+ ++i;
+ continue;
+ }
+
+ unsigned int digit = static_cast<unsigned int>(c - '0');
+ ASSERT(digit < 10u);
+ if (digit != 0u)
+ {
+ nonZeroSeenInMantissa = true;
}
- else if (type.isVector())
+ if (nonZeroSeenInMantissa)
+ {
+ // Add bits to the mantissa until space runs out in 32-bit int. This should be
+ // enough precision to make the resulting binary mantissa accurate to 1 ULP.
+ if (decimalMantissa <= (std::numeric_limits<unsigned int>::max() - 9u) / 10u)
+ {
+ decimalMantissa = decimalMantissa * 10u + digit;
+ }
+ if (!decimalPointSeen)
+ {
+ ++exponentOffset;
+ }
+ }
+ else if (decimalPointSeen)
+ {
+ --exponentOffset;
+ }
+ ++i;
+ }
+ if (decimalMantissa == 0)
+ {
+ return 0.0f;
+ }
+ int exponent = 0;
+ if (i < str.length())
+ {
+ ASSERT(str[i] == 'e' || str[i] == 'E');
+ ++i;
+ bool exponentOutOfRange = false;
+ bool negativeExponent = false;
+ if (str[i] == '-')
+ {
+ negativeExponent = true;
+ ++i;
+ }
+ else if (str[i] == '+')
+ {
+ ++i;
+ }
+ while (i < str.length())
+ {
+ const char c = str[i];
+ unsigned int digit = static_cast<unsigned int>(c - '0');
+ ASSERT(digit < 10u);
+ if (exponent <= (std::numeric_limits<int>::max() - 9) / 10)
+ {
+ exponent = exponent * 10 + digit;
+ }
+ else
+ {
+ exponentOutOfRange = true;
+ }
+ ++i;
+ }
+ if (negativeExponent)
+ {
+ exponent = -exponent;
+ }
+ if (exponentOutOfRange)
+ {
+ if (negativeExponent)
+ {
+ return 0.0f;
+ }
+ else
+ {
+ return std::numeric_limits<float>::infinity();
+ }
+ }
+ }
+ // Do the calculation in 64-bit to avoid overflow.
+ long long exponentLong =
+ static_cast<long long>(exponent) + static_cast<long long>(exponentOffset);
+ if (exponentLong > std::numeric_limits<float>::max_exponent10)
+ {
+ return std::numeric_limits<float>::infinity();
+ }
+ else if (exponentLong < std::numeric_limits<float>::min_exponent10)
+ {
+ return 0.0f;
+ }
+ // The exponent is in range, so we need to actually evaluate the float.
+ exponent = static_cast<int>(exponentLong);
+ double value = decimalMantissa;
+
+ // Calculate the exponent offset to normalize the mantissa.
+ int normalizationExponentOffset = 0;
+ while (decimalMantissa >= 10u)
+ {
+ --normalizationExponentOffset;
+ decimalMantissa /= 10u;
+ }
+ // Apply the exponent.
+ value *= std::pow(10.0, static_cast<double>(exponent + normalizationExponentOffset));
+ if (value > static_cast<double>(std::numeric_limits<float>::max()))
+ {
+ return std::numeric_limits<float>::infinity();
+ }
+ if (value < static_cast<double>(std::numeric_limits<float>::min()))
+ {
+ return 0.0f;
+ }
+ return static_cast<float>(value);
+}
+
+bool strtof_clamp(const std::string &str, float *value)
+{
+ // Try the standard float parsing path first.
+ bool success = pp::numeric_lex_float(str, value);
+
+ // If the standard path doesn't succeed, take the path that can handle the following corner
+ // cases:
+ // 1. The decimal mantissa is very small but the exponent is very large, putting the resulting
+ // number inside the float range.
+ // 2. The decimal mantissa is very large but the exponent is very small, putting the resulting
+ // number inside the float range.
+ // 3. The value is out-of-range and should be evaluated as infinity.
+ // 4. The value is too small and should be evaluated as zero.
+ // See ESSL 3.00.6 section 4.1.4 for the relevant specification.
+ if (!success)
+ *value = NumericLexFloat32OutOfRangeToInfinity(str);
+ return !gl::isInf(*value);
+}
+
+GLenum GLVariableType(const TType &type)
+{
+ if (type.getBasicType() == EbtFloat)
+ {
+ if (type.isVector())
{
switch (type.getNominalSize())
{
- case 2: return GL_FLOAT_VEC2;
- case 3: return GL_FLOAT_VEC3;
- case 4: return GL_FLOAT_VEC4;
- default: UNREACHABLE();
+ case 2:
+ return GL_FLOAT_VEC2;
+ case 3:
+ return GL_FLOAT_VEC3;
+ case 4:
+ return GL_FLOAT_VEC4;
+ default:
+ UNREACHABLE();
}
}
else if (type.isMatrix())
{
switch (type.getCols())
{
- case 2:
- switch (type.getRows())
- {
- case 2: return GL_FLOAT_MAT2;
- case 3: return GL_FLOAT_MAT2x3;
- case 4: return GL_FLOAT_MAT2x4;
- default: UNREACHABLE();
- }
-
- case 3:
- switch (type.getRows())
- {
- case 2: return GL_FLOAT_MAT3x2;
- case 3: return GL_FLOAT_MAT3;
- case 4: return GL_FLOAT_MAT3x4;
- default: UNREACHABLE();
- }
-
- case 4:
- switch (type.getRows())
- {
- case 2: return GL_FLOAT_MAT4x2;
- case 3: return GL_FLOAT_MAT4x3;
- case 4: return GL_FLOAT_MAT4;
- default: UNREACHABLE();
- }
-
- default: UNREACHABLE();
+ case 2:
+ switch (type.getRows())
+ {
+ case 2:
+ return GL_FLOAT_MAT2;
+ case 3:
+ return GL_FLOAT_MAT2x3;
+ case 4:
+ return GL_FLOAT_MAT2x4;
+ default:
+ UNREACHABLE();
+ }
+
+ case 3:
+ switch (type.getRows())
+ {
+ case 2:
+ return GL_FLOAT_MAT3x2;
+ case 3:
+ return GL_FLOAT_MAT3;
+ case 4:
+ return GL_FLOAT_MAT3x4;
+ default:
+ UNREACHABLE();
+ }
+
+ case 4:
+ switch (type.getRows())
+ {
+ case 2:
+ return GL_FLOAT_MAT4x2;
+ case 3:
+ return GL_FLOAT_MAT4x3;
+ case 4:
+ return GL_FLOAT_MAT4;
+ default:
+ UNREACHABLE();
+ }
+
+ default:
+ UNREACHABLE();
}
}
- else UNREACHABLE();
+ else
+ {
+ return GL_FLOAT;
+ }
}
else if (type.getBasicType() == EbtInt)
{
- if (type.isScalar())
- {
- return GL_INT;
- }
- else if (type.isVector())
+ if (type.isVector())
{
switch (type.getNominalSize())
{
- case 2: return GL_INT_VEC2;
- case 3: return GL_INT_VEC3;
- case 4: return GL_INT_VEC4;
- default: UNREACHABLE();
+ case 2:
+ return GL_INT_VEC2;
+ case 3:
+ return GL_INT_VEC3;
+ case 4:
+ return GL_INT_VEC4;
+ default:
+ UNREACHABLE();
}
}
- else UNREACHABLE();
+ else
+ {
+ ASSERT(!type.isMatrix());
+ return GL_INT;
+ }
}
else if (type.getBasicType() == EbtUInt)
{
- if (type.isScalar())
- {
- return GL_UNSIGNED_INT;
- }
- else if (type.isVector())
+ if (type.isVector())
{
switch (type.getNominalSize())
{
- case 2: return GL_UNSIGNED_INT_VEC2;
- case 3: return GL_UNSIGNED_INT_VEC3;
- case 4: return GL_UNSIGNED_INT_VEC4;
- default: UNREACHABLE();
+ case 2:
+ return GL_UNSIGNED_INT_VEC2;
+ case 3:
+ return GL_UNSIGNED_INT_VEC3;
+ case 4:
+ return GL_UNSIGNED_INT_VEC4;
+ default:
+ UNREACHABLE();
}
}
- else UNREACHABLE();
+ else
+ {
+ ASSERT(!type.isMatrix());
+ return GL_UNSIGNED_INT;
+ }
}
else if (type.getBasicType() == EbtBool)
{
- if (type.isScalar())
- {
- return GL_BOOL;
- }
- else if (type.isVector())
+ if (type.isVector())
{
switch (type.getNominalSize())
{
- case 2: return GL_BOOL_VEC2;
- case 3: return GL_BOOL_VEC3;
- case 4: return GL_BOOL_VEC4;
- default: UNREACHABLE();
+ case 2:
+ return GL_BOOL_VEC2;
+ case 3:
+ return GL_BOOL_VEC3;
+ case 4:
+ return GL_BOOL_VEC4;
+ default:
+ UNREACHABLE();
}
}
- else UNREACHABLE();
+ else
+ {
+ ASSERT(!type.isMatrix());
+ return GL_BOOL;
+ }
}
switch (type.getBasicType())
{
- case EbtSampler2D: return GL_SAMPLER_2D;
- case EbtSampler3D: return GL_SAMPLER_3D;
- case EbtSamplerCube: return GL_SAMPLER_CUBE;
- case EbtSamplerExternalOES: return GL_SAMPLER_EXTERNAL_OES;
- case EbtSampler2DRect: return GL_SAMPLER_2D_RECT_ARB;
- case EbtSampler2DArray: return GL_SAMPLER_2D_ARRAY;
- case EbtISampler2D: return GL_INT_SAMPLER_2D;
- case EbtISampler3D: return GL_INT_SAMPLER_3D;
- case EbtISamplerCube: return GL_INT_SAMPLER_CUBE;
- case EbtISampler2DArray: return GL_INT_SAMPLER_2D_ARRAY;
- case EbtUSampler2D: return GL_UNSIGNED_INT_SAMPLER_2D;
- case EbtUSampler3D: return GL_UNSIGNED_INT_SAMPLER_3D;
- case EbtUSamplerCube: return GL_UNSIGNED_INT_SAMPLER_CUBE;
- case EbtUSampler2DArray: return GL_UNSIGNED_INT_SAMPLER_2D_ARRAY;
- case EbtSampler2DShadow: return GL_SAMPLER_2D_SHADOW;
- case EbtSamplerCubeShadow: return GL_SAMPLER_CUBE_SHADOW;
- case EbtSampler2DArrayShadow: return GL_SAMPLER_2D_ARRAY_SHADOW;
- default: UNREACHABLE();
+ case EbtSampler2D:
+ return GL_SAMPLER_2D;
+ case EbtSampler3D:
+ return GL_SAMPLER_3D;
+ case EbtSamplerCube:
+ return GL_SAMPLER_CUBE;
+ case EbtSamplerExternalOES:
+ return GL_SAMPLER_EXTERNAL_OES;
+ case EbtSamplerExternal2DY2YEXT:
+ return GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT;
+ case EbtSampler2DRect:
+ return GL_SAMPLER_2D_RECT_ANGLE;
+ case EbtSampler2DArray:
+ return GL_SAMPLER_2D_ARRAY;
+ case EbtSampler2DMS:
+ return GL_SAMPLER_2D_MULTISAMPLE;
+ case EbtISampler2D:
+ return GL_INT_SAMPLER_2D;
+ case EbtISampler3D:
+ return GL_INT_SAMPLER_3D;
+ case EbtISamplerCube:
+ return GL_INT_SAMPLER_CUBE;
+ case EbtISampler2DArray:
+ return GL_INT_SAMPLER_2D_ARRAY;
+ case EbtISampler2DMS:
+ return GL_INT_SAMPLER_2D_MULTISAMPLE;
+ case EbtUSampler2D:
+ return GL_UNSIGNED_INT_SAMPLER_2D;
+ case EbtUSampler3D:
+ return GL_UNSIGNED_INT_SAMPLER_3D;
+ case EbtUSamplerCube:
+ return GL_UNSIGNED_INT_SAMPLER_CUBE;
+ case EbtUSampler2DArray:
+ return GL_UNSIGNED_INT_SAMPLER_2D_ARRAY;
+ case EbtUSampler2DMS:
+ return GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE;
+ case EbtSampler2DShadow:
+ return GL_SAMPLER_2D_SHADOW;
+ case EbtSamplerCubeShadow:
+ return GL_SAMPLER_CUBE_SHADOW;
+ case EbtSampler2DArrayShadow:
+ return GL_SAMPLER_2D_ARRAY_SHADOW;
+ case EbtImage2D:
+ return GL_IMAGE_2D;
+ case EbtIImage2D:
+ return GL_INT_IMAGE_2D;
+ case EbtUImage2D:
+ return GL_UNSIGNED_INT_IMAGE_2D;
+ case EbtImage2DArray:
+ return GL_IMAGE_2D_ARRAY;
+ case EbtIImage2DArray:
+ return GL_INT_IMAGE_2D_ARRAY;
+ case EbtUImage2DArray:
+ return GL_UNSIGNED_INT_IMAGE_2D_ARRAY;
+ case EbtImage3D:
+ return GL_IMAGE_3D;
+ case EbtIImage3D:
+ return GL_INT_IMAGE_3D;
+ case EbtUImage3D:
+ return GL_UNSIGNED_INT_IMAGE_3D;
+ case EbtImageCube:
+ return GL_IMAGE_CUBE;
+ case EbtIImageCube:
+ return GL_INT_IMAGE_CUBE;
+ case EbtUImageCube:
+ return GL_UNSIGNED_INT_IMAGE_CUBE;
+ case EbtAtomicCounter:
+ return GL_UNSIGNED_INT_ATOMIC_COUNTER;
+ default:
+ UNREACHABLE();
}
return GL_NONE;
@@ -171,32 +420,32 @@ GLenum GLVariablePrecision(const TType &type)
{
switch (type.getPrecision())
{
- case EbpHigh:
- return GL_HIGH_FLOAT;
- case EbpMedium:
- return GL_MEDIUM_FLOAT;
- case EbpLow:
- return GL_LOW_FLOAT;
- case EbpUndefined:
- // Should be defined as the default precision by the parser
- default:
- UNREACHABLE();
+ case EbpHigh:
+ return GL_HIGH_FLOAT;
+ case EbpMedium:
+ return GL_MEDIUM_FLOAT;
+ case EbpLow:
+ return GL_LOW_FLOAT;
+ case EbpUndefined:
+ // Should be defined as the default precision by the parser
+ default:
+ UNREACHABLE();
}
}
else if (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt)
{
switch (type.getPrecision())
{
- case EbpHigh:
- return GL_HIGH_INT;
- case EbpMedium:
- return GL_MEDIUM_INT;
- case EbpLow:
- return GL_LOW_INT;
- case EbpUndefined:
- // Should be defined as the default precision by the parser
- default:
- UNREACHABLE();
+ case EbpHigh:
+ return GL_HIGH_INT;
+ case EbpMedium:
+ return GL_MEDIUM_INT;
+ case EbpLow:
+ return GL_LOW_INT;
+ case EbpUndefined:
+ // Should be defined as the default precision by the parser
+ default:
+ UNREACHABLE();
}
}
@@ -206,26 +455,46 @@ GLenum GLVariablePrecision(const TType &type)
TString ArrayString(const TType &type)
{
+ TStringStream arrayString;
if (!type.isArray())
+ return arrayString.str();
+
+ const TVector<unsigned int> &arraySizes = *type.getArraySizes();
+ for (auto arraySizeIter = arraySizes.rbegin(); arraySizeIter != arraySizes.rend();
+ ++arraySizeIter)
{
- return "";
+ arrayString << "[";
+ if (*arraySizeIter > 0)
+ {
+ arrayString << (*arraySizeIter);
+ }
+ arrayString << "]";
}
+ return arrayString.str();
+}
- return "[" + str(type.getArraySize()) + "]";
+TString GetTypeName(const TType &type, ShHashFunction64 hashFunction, NameMap *nameMap)
+{
+ if (type.getBasicType() == EbtStruct)
+ return HashName(TName(type.getStruct()->name()), hashFunction, nameMap);
+ else
+ return type.getBuiltInTypeNameString();
}
bool IsVaryingOut(TQualifier qualifier)
{
switch (qualifier)
{
- case EvqVaryingOut:
- case EvqSmoothOut:
- case EvqFlatOut:
- case EvqCentroidOut:
- case EvqVertexOut:
- return true;
-
- default: break;
+ case EvqVaryingOut:
+ case EvqSmoothOut:
+ case EvqFlatOut:
+ case EvqCentroidOut:
+ case EvqVertexOut:
+ case EvqGeometryOut:
+ return true;
+
+ default:
+ break;
}
return false;
@@ -235,14 +504,16 @@ bool IsVaryingIn(TQualifier qualifier)
{
switch (qualifier)
{
- case EvqVaryingIn:
- case EvqSmoothIn:
- case EvqFlatIn:
- case EvqCentroidIn:
- case EvqFragmentIn:
- return true;
-
- default: break;
+ case EvqVaryingIn:
+ case EvqSmoothIn:
+ case EvqFlatIn:
+ case EvqCentroidIn:
+ case EvqFragmentIn:
+ case EvqGeometryIn:
+ return true;
+
+ default:
+ break;
}
return false;
@@ -253,108 +524,191 @@ bool IsVarying(TQualifier qualifier)
return IsVaryingIn(qualifier) || IsVaryingOut(qualifier);
}
+bool IsGeometryShaderInput(GLenum shaderType, TQualifier qualifier)
+{
+ return (qualifier == EvqGeometryIn) ||
+ ((shaderType == GL_GEOMETRY_SHADER_OES) && IsInterpolationIn(qualifier));
+}
+
InterpolationType GetInterpolationType(TQualifier qualifier)
{
switch (qualifier)
{
- case EvqFlatIn:
- case EvqFlatOut:
- return INTERPOLATION_FLAT;
-
- case EvqSmoothIn:
- case EvqSmoothOut:
- case EvqVertexOut:
- case EvqFragmentIn:
- case EvqVaryingIn:
- case EvqVaryingOut:
- return INTERPOLATION_SMOOTH;
-
- case EvqCentroidIn:
- case EvqCentroidOut:
- return INTERPOLATION_CENTROID;
-
- default: UNREACHABLE();
- return INTERPOLATION_SMOOTH;
+ case EvqFlatIn:
+ case EvqFlatOut:
+ return INTERPOLATION_FLAT;
+
+ case EvqSmoothIn:
+ case EvqSmoothOut:
+ case EvqVertexOut:
+ case EvqFragmentIn:
+ case EvqVaryingIn:
+ case EvqVaryingOut:
+ case EvqGeometryIn:
+ case EvqGeometryOut:
+ return INTERPOLATION_SMOOTH;
+
+ case EvqCentroidIn:
+ case EvqCentroidOut:
+ return INTERPOLATION_CENTROID;
+
+ default:
+ UNREACHABLE();
+ return INTERPOLATION_SMOOTH;
+ }
+}
+
+TType GetShaderVariableBasicType(const sh::ShaderVariable &var)
+{
+ switch (var.type)
+ {
+ case GL_BOOL:
+ return TType(EbtBool);
+ case GL_BOOL_VEC2:
+ return TType(EbtBool, 2);
+ case GL_BOOL_VEC3:
+ return TType(EbtBool, 3);
+ case GL_BOOL_VEC4:
+ return TType(EbtBool, 4);
+ case GL_FLOAT:
+ return TType(EbtFloat);
+ case GL_FLOAT_VEC2:
+ return TType(EbtFloat, 2);
+ case GL_FLOAT_VEC3:
+ return TType(EbtFloat, 3);
+ case GL_FLOAT_VEC4:
+ return TType(EbtFloat, 4);
+ case GL_FLOAT_MAT2:
+ return TType(EbtFloat, 2, 2);
+ case GL_FLOAT_MAT3:
+ return TType(EbtFloat, 3, 3);
+ case GL_FLOAT_MAT4:
+ return TType(EbtFloat, 4, 4);
+ case GL_FLOAT_MAT2x3:
+ return TType(EbtFloat, 2, 3);
+ case GL_FLOAT_MAT2x4:
+ return TType(EbtFloat, 2, 4);
+ case GL_FLOAT_MAT3x2:
+ return TType(EbtFloat, 3, 2);
+ case GL_FLOAT_MAT3x4:
+ return TType(EbtFloat, 3, 4);
+ case GL_FLOAT_MAT4x2:
+ return TType(EbtFloat, 4, 2);
+ case GL_FLOAT_MAT4x3:
+ return TType(EbtFloat, 4, 3);
+ case GL_INT:
+ return TType(EbtInt);
+ case GL_INT_VEC2:
+ return TType(EbtInt, 2);
+ case GL_INT_VEC3:
+ return TType(EbtInt, 3);
+ case GL_INT_VEC4:
+ return TType(EbtInt, 4);
+ case GL_UNSIGNED_INT:
+ return TType(EbtUInt);
+ case GL_UNSIGNED_INT_VEC2:
+ return TType(EbtUInt, 2);
+ case GL_UNSIGNED_INT_VEC3:
+ return TType(EbtUInt, 3);
+ case GL_UNSIGNED_INT_VEC4:
+ return TType(EbtUInt, 4);
+ default:
+ UNREACHABLE();
+ return TType();
}
}
-GetVariableTraverser::GetVariableTraverser(const TSymbolTable &symbolTable)
- : mSymbolTable(symbolTable)
+// GLSL ES 1.0.17 4.6.1 The Invariant Qualifier
+bool CanBeInvariantESSL1(TQualifier qualifier)
{
+ return IsVaryingIn(qualifier) || IsVaryingOut(qualifier) ||
+ IsBuiltinOutputVariable(qualifier) ||
+ (IsBuiltinFragmentInputVariable(qualifier) && qualifier != EvqFrontFacing);
}
-template void GetVariableTraverser::setTypeSpecificInfo(
- const TType &type, const TString& name, InterfaceBlockField *variable);
-template void GetVariableTraverser::setTypeSpecificInfo(
- const TType &type, const TString& name, ShaderVariable *variable);
-template void GetVariableTraverser::setTypeSpecificInfo(
- const TType &type, const TString& name, Uniform *variable);
+// GLSL ES 3.00 Revision 6, 4.6.1 The Invariant Qualifier
+// GLSL ES 3.10 Revision 4, 4.8.1 The Invariant Qualifier
+bool CanBeInvariantESSL3OrGreater(TQualifier qualifier)
+{
+ return IsVaryingOut(qualifier) || qualifier == EvqFragmentOut ||
+ IsBuiltinOutputVariable(qualifier);
+}
-template<>
-void GetVariableTraverser::setTypeSpecificInfo(
- const TType &type, const TString& name, Varying *variable)
+bool IsBuiltinOutputVariable(TQualifier qualifier)
{
- ASSERT(variable);
- switch (type.getQualifier())
+ switch (qualifier)
{
- case EvqVaryingIn:
- case EvqVaryingOut:
- case EvqVertexOut:
- case EvqSmoothOut:
- case EvqFlatOut:
- case EvqCentroidOut:
- if (mSymbolTable.isVaryingInvariant(std::string(name.c_str())) || type.isInvariant())
- {
- variable->isInvariant = true;
- }
- break;
- default:
- break;
+ case EvqPosition:
+ case EvqPointSize:
+ case EvqFragDepth:
+ case EvqFragDepthEXT:
+ case EvqFragColor:
+ case EvqSecondaryFragColorEXT:
+ case EvqFragData:
+ case EvqSecondaryFragDataEXT:
+ return true;
+ default:
+ break;
}
-
- variable->interpolation = GetInterpolationType(type.getQualifier());
+ return false;
}
-template <typename VarT>
-void GetVariableTraverser::traverse(const TType &type,
- const TString &name,
- std::vector<VarT> *output)
+bool IsBuiltinFragmentInputVariable(TQualifier qualifier)
{
- const TStructure *structure = type.getStruct();
+ switch (qualifier)
+ {
+ case EvqFragCoord:
+ case EvqPointCoord:
+ case EvqFrontFacing:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
- VarT variable;
- variable.name = name.c_str();
- variable.arraySize = static_cast<unsigned int>(type.getArraySize());
+bool IsOutputESSL(ShShaderOutput output)
+{
+ return output == SH_ESSL_OUTPUT;
+}
- if (!structure)
+bool IsOutputGLSL(ShShaderOutput output)
+{
+ switch (output)
{
- variable.type = GLVariableType(type);
- variable.precision = GLVariablePrecision(type);
+ case SH_GLSL_130_OUTPUT:
+ case SH_GLSL_140_OUTPUT:
+ case SH_GLSL_150_CORE_OUTPUT:
+ case SH_GLSL_330_CORE_OUTPUT:
+ case SH_GLSL_400_CORE_OUTPUT:
+ case SH_GLSL_410_CORE_OUTPUT:
+ case SH_GLSL_420_CORE_OUTPUT:
+ case SH_GLSL_430_CORE_OUTPUT:
+ case SH_GLSL_440_CORE_OUTPUT:
+ case SH_GLSL_450_CORE_OUTPUT:
+ case SH_GLSL_COMPATIBILITY_OUTPUT:
+ return true;
+ default:
+ break;
}
- else
+ return false;
+}
+bool IsOutputHLSL(ShShaderOutput output)
+{
+ switch (output)
{
- // Note: this enum value is not exposed outside ANGLE
- variable.type = GL_STRUCT_ANGLEX;
- variable.structName = structure->name().c_str();
-
- const TFieldList &fields = structure->fields();
-
- for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
- {
- TField *field = fields[fieldIndex];
- traverse(*field->type(), field->name(), &variable.fields);
- }
+ case SH_HLSL_3_0_OUTPUT:
+ case SH_HLSL_4_1_OUTPUT:
+ case SH_HLSL_4_0_FL9_3_OUTPUT:
+ return true;
+ default:
+ break;
}
- setTypeSpecificInfo(type, name, &variable);
- visitVariable(&variable);
-
- ASSERT(output);
- output->push_back(variable);
+ return false;
}
-
-template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<InterfaceBlockField> *);
-template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<ShaderVariable> *);
-template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Uniform> *);
-template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Varying> *);
-
+bool IsOutputVulkan(ShShaderOutput output)
+{
+ return output == SH_GLSL_VULKAN_OUTPUT;
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/compiler/translator/util.h b/src/3rdparty/angle/src/compiler/translator/util.h
index ea7a35a352..6d6dc95b3b 100644
--- a/src/3rdparty/angle/src/compiler/translator/util.h
+++ b/src/3rdparty/angle/src/compiler/translator/util.h
@@ -12,54 +12,52 @@
#include "angle_gl.h"
#include <GLSLANG/ShaderLang.h>
+#include "compiler/translator/HashNames.h"
+#include "compiler/translator/Operator.h"
#include "compiler/translator/Types.h"
-// strtof_clamp is like strtof but
-// 1. it forces C locale, i.e. forcing '.' as decimal point.
-// 2. it clamps the value to -FLT_MAX or FLT_MAX if overflow happens.
-// Return false if overflow happens.
-bool strtof_clamp(const std::string &str, float *value);
-
// If overflow happens, clamp the value to UINT_MIN or UINT_MAX.
// Return false if overflow happens.
bool atoi_clamp(const char *str, unsigned int *value);
-class TSymbolTable;
-
namespace sh
{
+class TSymbolTable;
+
+float NumericLexFloat32OutOfRangeToInfinity(const std::string &str);
+
+// strtof_clamp is like strtof but
+// 1. it forces C locale, i.e. forcing '.' as decimal point.
+// 2. it sets the value to infinity if overflow happens.
+// 3. str should be guaranteed to be in the valid format for a floating point number as defined
+// by the grammar in the ESSL 3.00.6 spec section 4.1.4.
+// Return false if overflow happens.
+bool strtof_clamp(const std::string &str, float *value);
GLenum GLVariableType(const TType &type);
GLenum GLVariablePrecision(const TType &type);
bool IsVaryingIn(TQualifier qualifier);
bool IsVaryingOut(TQualifier qualifier);
bool IsVarying(TQualifier qualifier);
+bool IsGeometryShaderInput(GLenum shaderType, TQualifier qualifier);
InterpolationType GetInterpolationType(TQualifier qualifier);
-TString ArrayString(const TType &type);
-class GetVariableTraverser : angle::NonCopyable
-{
- public:
- GetVariableTraverser(const TSymbolTable &symbolTable);
- virtual ~GetVariableTraverser() {}
-
- template <typename VarT>
- void traverse(const TType &type, const TString &name, std::vector<VarT> *output);
-
- protected:
- // May be overloaded
- virtual void visitVariable(ShaderVariable *newVar) {}
+// Returns array brackets including size with outermost array size first, as specified in GLSL ES
+// 3.10 section 4.1.9.
+TString ArrayString(const TType &type);
- private:
- // Helper function called by traverse() to fill specific fields
- // for attributes/varyings/uniforms.
- template <typename VarT>
- void setTypeSpecificInfo(
- const TType &type, const TString &name, VarT *variable) {}
+TString GetTypeName(const TType &type, ShHashFunction64 hashFunction, NameMap *nameMap);
- const TSymbolTable &mSymbolTable;
-};
+TType GetShaderVariableBasicType(const sh::ShaderVariable &var);
-}
+bool IsBuiltinOutputVariable(TQualifier qualifier);
+bool IsBuiltinFragmentInputVariable(TQualifier qualifier);
+bool CanBeInvariantESSL1(TQualifier qualifier);
+bool CanBeInvariantESSL3OrGreater(TQualifier qualifier);
+bool IsOutputESSL(ShShaderOutput output);
+bool IsOutputGLSL(ShShaderOutput output);
+bool IsOutputHLSL(ShShaderOutput output);
+bool IsOutputVulkan(ShShaderOutput output);
+} // namespace sh
-#endif // COMPILER_TRANSLATOR_UTIL_H_
+#endif // COMPILER_TRANSLATOR_UTIL_H_
diff --git a/src/3rdparty/angle/src/gpu_info_util/SystemInfo.cpp b/src/3rdparty/angle/src/gpu_info_util/SystemInfo.cpp
new file mode 100644
index 0000000000..f8d744342d
--- /dev/null
+++ b/src/3rdparty/angle/src/gpu_info_util/SystemInfo.cpp
@@ -0,0 +1,171 @@
+//
+// Copyright (c) 2013-2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SystemInfo.cpp: implementation of the system-agnostic parts of SystemInfo.h
+
+#include "gpu_info_util/SystemInfo.h"
+
+#include <cstring>
+#include <sstream>
+
+#include "common/debug.h"
+#include "common/string_utils.h"
+
+namespace angle
+{
+
+GPUDeviceInfo::GPUDeviceInfo() = default;
+
+GPUDeviceInfo::~GPUDeviceInfo() = default;
+
+GPUDeviceInfo::GPUDeviceInfo(const GPUDeviceInfo &other) = default;
+
+SystemInfo::SystemInfo() = default;
+
+SystemInfo::~SystemInfo() = default;
+
+SystemInfo::SystemInfo(const SystemInfo &other) = default;
+
+bool IsAMD(VendorID vendorId)
+{
+ return vendorId == kVendorID_AMD;
+}
+
+bool IsIntel(VendorID vendorId)
+{
+ return vendorId == kVendorID_Intel;
+}
+
+bool IsNvidia(VendorID vendorId)
+{
+ return vendorId == kVendorID_Nvidia;
+}
+
+bool IsQualcomm(VendorID vendorId)
+{
+ return vendorId == kVendorID_Qualcomm;
+}
+
+bool ParseAMDBrahmaDriverVersion(const std::string &content, std::string *version)
+{
+ const size_t begin = content.find_first_of("0123456789");
+ if (begin == std::string::npos)
+ {
+ return false;
+ }
+
+ const size_t end = content.find_first_not_of("0123456789.", begin);
+ if (end == std::string::npos)
+ {
+ *version = content.substr(begin);
+ }
+ else
+ {
+ *version = content.substr(begin, end - begin);
+ }
+ return true;
+}
+
+bool ParseAMDCatalystDriverVersion(const std::string &content, std::string *version)
+{
+ std::istringstream stream(content);
+
+ std::string line;
+ while (std::getline(stream, line))
+ {
+ static const char kReleaseVersion[] = "ReleaseVersion=";
+ if (line.compare(0, std::strlen(kReleaseVersion), kReleaseVersion) != 0)
+ {
+ continue;
+ }
+
+ if (ParseAMDBrahmaDriverVersion(line, version))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool ParseMacMachineModel(const std::string &identifier,
+ std::string *type,
+ int32_t *major,
+ int32_t *minor)
+{
+ size_t numberLoc = identifier.find_first_of("0123456789");
+ if (numberLoc == std::string::npos)
+ {
+ return false;
+ }
+
+ size_t commaLoc = identifier.find(',', numberLoc);
+ if (commaLoc == std::string::npos || commaLoc >= identifier.size())
+ {
+ return false;
+ }
+
+ const char *numberPtr = &identifier[numberLoc];
+ const char *commaPtr = &identifier[commaLoc + 1];
+ char *endPtr = nullptr;
+
+ int32_t majorTmp = std::strtol(numberPtr, &endPtr, 10);
+ if (endPtr == numberPtr)
+ {
+ return false;
+ }
+
+ int32_t minorTmp = std::strtol(commaPtr, &endPtr, 10);
+ if (endPtr == commaPtr)
+ {
+ return false;
+ }
+
+ *major = majorTmp;
+ *minor = minorTmp;
+ *type = identifier.substr(0, numberLoc);
+
+ return true;
+}
+
+bool CMDeviceIDToDeviceAndVendorID(const std::string &id, uint32_t *vendorId, uint32_t *deviceId)
+{
+ unsigned int vendor = 0;
+ unsigned int device = 0;
+
+ bool success = id.length() >= 21 && HexStringToUInt(id.substr(8, 4), &vendor) &&
+ HexStringToUInt(id.substr(17, 4), &device);
+
+ *vendorId = vendor;
+ *deviceId = device;
+ return success;
+}
+
+void FindPrimaryGPU(SystemInfo *info)
+{
+ ASSERT(!info->gpus.empty());
+
+ // On dual-GPU systems we assume the non-Intel GPU is the primary one.
+ int primary = 0;
+ bool hasIntel = false;
+ for (size_t i = 0; i < info->gpus.size(); ++i)
+ {
+ if (IsIntel(info->gpus[i].vendorId))
+ {
+ hasIntel = true;
+ }
+ if (IsIntel(info->gpus[primary].vendorId))
+ {
+ primary = static_cast<int>(i);
+ }
+ }
+
+ // Assume that a combination of AMD or Nvidia with Intel means Optimus or AMD Switchable
+ info->primaryGPUIndex = primary;
+ info->isOptimus = hasIntel && IsNvidia(info->gpus[primary].vendorId);
+ info->isAMDSwitchable = hasIntel && IsAMD(info->gpus[primary].vendorId);
+}
+
+} // namespace angle
diff --git a/src/3rdparty/angle/src/gpu_info_util/SystemInfo.h b/src/3rdparty/angle/src/gpu_info_util/SystemInfo.h
new file mode 100644
index 0000000000..ada43f0a15
--- /dev/null
+++ b/src/3rdparty/angle/src/gpu_info_util/SystemInfo.h
@@ -0,0 +1,73 @@
+//
+// Copyright (c) 2013-2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SystemInfo.h: gathers information available without starting a GPU driver.
+
+#ifndef GPU_INFO_UTIL_SYSTEM_INFO_H_
+#define GPU_INFO_UTIL_SYSTEM_INFO_H_
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+namespace angle
+{
+
+using VendorID = uint32_t;
+using DeviceID = uint32_t;
+
+constexpr VendorID kVendorID_AMD = 0x1002;
+constexpr VendorID kVendorID_Intel = 0x8086;
+constexpr VendorID kVendorID_Nvidia = 0x10DE;
+constexpr VendorID kVendorID_Qualcomm = 0x5143;
+
+struct GPUDeviceInfo
+{
+ GPUDeviceInfo();
+ ~GPUDeviceInfo();
+
+ GPUDeviceInfo(const GPUDeviceInfo &other);
+
+ VendorID vendorId = 0;
+ DeviceID deviceId = 0;
+
+ std::string driverVendor;
+ std::string driverVersion;
+ std::string driverDate;
+};
+
+struct SystemInfo
+{
+ SystemInfo();
+ ~SystemInfo();
+
+ SystemInfo(const SystemInfo &other);
+
+ std::vector<GPUDeviceInfo> gpus;
+ int primaryGPUIndex = -1;
+ int activeGPUIndex = -1;
+
+ bool isOptimus = false;
+ bool isAMDSwitchable = false;
+
+ // Only available on macOS
+ std::string machineModelName;
+ std::string machineModelVersion;
+
+ // Only available on Windows, set even on failure.
+ std::string primaryDisplayDeviceId;
+};
+
+bool GetSystemInfo(SystemInfo *info);
+
+bool IsAMD(VendorID vendorId);
+bool IsIntel(VendorID vendorId);
+bool IsNvidia(VendorID vendorId);
+bool IsQualcomm(VendorID vendorId);
+
+} // namespace angle
+
+#endif // GPU_INFO_UTIL_SYSTEM_INFO_H_
diff --git a/src/3rdparty/angle/src/gpu_info_util/SystemInfo_internal.h b/src/3rdparty/angle/src/gpu_info_util/SystemInfo_internal.h
new file mode 100644
index 0000000000..d2f6124662
--- /dev/null
+++ b/src/3rdparty/angle/src/gpu_info_util/SystemInfo_internal.h
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2013-2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SystemInfo_internal.h: Functions used by the SystemInfo_* files and unittests
+
+#ifndef GPU_INFO_UTIL_SYSTEM_INFO_INTERNAL_H_
+#define GPU_INFO_UTIL_SYSTEM_INFO_INTERNAL_H_
+
+#include "gpu_info_util/SystemInfo.h"
+
+namespace angle
+{
+
+// Defined in SystemInfo_libpci when GPU_INFO_USE_LIBPCI is defined.
+bool GetPCIDevicesWithLibPCI(std::vector<GPUDeviceInfo> *devices);
+// Defined in SystemInfo_x11 when GPU_INFO_USE_X11 is defined.
+bool GetNvidiaDriverVersionWithXNVCtrl(std::string *version);
+
+// Target specific helper functions that can be compiled on all targets
+// Live in SystemInfo.cpp
+bool ParseAMDBrahmaDriverVersion(const std::string &content, std::string *version);
+bool ParseAMDCatalystDriverVersion(const std::string &content, std::string *version);
+bool ParseMacMachineModel(const std::string &identifier,
+ std::string *type,
+ int32_t *major,
+ int32_t *minor);
+bool CMDeviceIDToDeviceAndVendorID(const std::string &id, uint32_t *vendorId, uint32_t *deviceId);
+
+// In the case there are multiple GPUs, this finds the primary one and sets Optimus or AMD
+// Switchable
+void FindPrimaryGPU(SystemInfo *info);
+
+} // namespace angle
+
+#endif // GPU_INFO_UTIL_SYSTEM_INFO_INTERNAL_H_
diff --git a/src/3rdparty/angle/src/gpu_info_util/SystemInfo_libpci.cpp b/src/3rdparty/angle/src/gpu_info_util/SystemInfo_libpci.cpp
new file mode 100644
index 0000000000..07c72872ad
--- /dev/null
+++ b/src/3rdparty/angle/src/gpu_info_util/SystemInfo_libpci.cpp
@@ -0,0 +1,132 @@
+//
+// Copyright (c) 2013-2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SystemInfo_libpci.cpp: implementation of the libPCI-specific parts of SystemInfo.h
+
+#include "gpu_info_util/SystemInfo_internal.h"
+
+#include <dlfcn.h>
+#include <pci/pci.h>
+#include <unistd.h>
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+
+#if !defined(GPU_INFO_USE_LIBPCI)
+#error SystemInfo_libpci.cpp compiled without GPU_INFO_USE_LIBPCI
+#endif
+
+namespace angle
+{
+
+namespace
+{
+
+struct LibPCI : private angle::NonCopyable
+{
+ LibPCI()
+ {
+ if (access("/sys/bus/pci/", F_OK) != 0 && access("/sys/bs/pci_express/", F_OK) != 0)
+ {
+ return;
+ }
+
+ mHandle = dlopen("libpci.so.3", RTLD_LAZY);
+
+ if (mHandle == nullptr)
+ {
+ mHandle = dlopen("libpci.so", RTLD_LAZY);
+ }
+
+ if (mHandle == nullptr)
+ {
+ return;
+ }
+
+ mValid =
+ (Alloc = reinterpret_cast<decltype(Alloc)>(dlsym(mHandle, "pci_alloc"))) != nullptr &&
+ (Init = reinterpret_cast<decltype(Init)>(dlsym(mHandle, "pci_init"))) != nullptr &&
+ (Cleanup = reinterpret_cast<decltype(Cleanup)>(dlsym(mHandle, "pci_cleanup"))) !=
+ nullptr &&
+ (ScanBus = reinterpret_cast<decltype(ScanBus)>(dlsym(mHandle, "pci_scan_bus"))) !=
+ nullptr &&
+ (FillInfo = reinterpret_cast<decltype(FillInfo)>(dlsym(mHandle, "pci_fill_info"))) !=
+ nullptr &&
+ (LookupName = reinterpret_cast<decltype(LookupName)>(
+ dlsym(mHandle, "pci_lookup_name"))) != nullptr;
+ }
+
+ bool IsValid() const { return mValid; }
+
+ ~LibPCI()
+ {
+ if (mHandle != nullptr)
+ {
+ dlclose(mHandle);
+ }
+ }
+
+ decltype(&::pci_alloc) Alloc = nullptr;
+ decltype(&::pci_init) Init = nullptr;
+ decltype(&::pci_cleanup) Cleanup = nullptr;
+ decltype(&::pci_scan_bus) ScanBus = nullptr;
+ decltype(&::pci_fill_info) FillInfo = nullptr;
+ decltype(&::pci_lookup_name) LookupName = nullptr;
+
+ private:
+ void *mHandle = nullptr;
+ bool mValid = false;
+};
+
+} // anonymous namespace
+
+// Adds an entry per PCI GPU found and fills the device and vendor ID.
+bool GetPCIDevicesWithLibPCI(std::vector<GPUDeviceInfo> *devices)
+{
+ LibPCI pci;
+ if (!pci.IsValid())
+ {
+ return false;
+ }
+
+ pci_access *access = pci.Alloc();
+ ASSERT(access != nullptr);
+ pci.Init(access);
+ pci.ScanBus(access);
+
+ for (pci_dev *device = access->devices; device != nullptr; device = device->next)
+ {
+ pci.FillInfo(device, PCI_FILL_IDENT | PCI_FILL_CLASS);
+
+ // Skip non-GPU devices
+ switch (device->device_class)
+ {
+ case PCI_CLASS_DISPLAY_VGA:
+ case PCI_CLASS_DISPLAY_XGA:
+ case PCI_CLASS_DISPLAY_3D:
+ break;
+ default:
+ continue;
+ }
+
+ // Skip unknown devices
+ if (device->vendor_id == 0 || device->device_id == 0)
+ {
+ continue;
+ }
+
+ GPUDeviceInfo info;
+ info.vendorId = device->vendor_id;
+ info.deviceId = device->device_id;
+
+ devices->push_back(info);
+ }
+
+ pci.Cleanup(access);
+
+ return true;
+}
+}
diff --git a/src/3rdparty/angle/src/gpu_info_util/SystemInfo_linux.cpp b/src/3rdparty/angle/src/gpu_info_util/SystemInfo_linux.cpp
new file mode 100644
index 0000000000..98f000b069
--- /dev/null
+++ b/src/3rdparty/angle/src/gpu_info_util/SystemInfo_linux.cpp
@@ -0,0 +1,144 @@
+//
+// Copyright (c) 2013-2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SystemInfo_linux.cpp: implementation of the Linux-specific parts of SystemInfo.h
+
+#include "gpu_info_util/SystemInfo_internal.h"
+
+#include <cstring>
+#include <fstream>
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+
+namespace angle
+{
+
+namespace
+{
+
+bool ReadWholeFile(const char *filename, std::string *content)
+{
+ std::ifstream file(filename);
+
+ if (!file)
+ {
+ return false;
+ }
+
+ *content = std::string(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
+ return true;
+}
+
+// Scan /sys/module/amdgpu/version.
+bool GetAMDBrahmaDriverVersion(std::string *version)
+{
+ *version = "";
+ std::string content;
+
+ return ReadWholeFile("/sys/module/amdgpu/version", &content) &&
+ ParseAMDBrahmaDriverVersion(content, version);
+}
+
+// Scan /etc/ati/amdpcsdb.default for "ReleaseVersion".
+bool GetAMDCatalystDriverVersion(std::string *version)
+{
+ *version = "";
+ std::string content;
+
+ return ReadWholeFile("/etc/ati/amdpcsdb.default", &content) &&
+ ParseAMDCatalystDriverVersion(content, version);
+}
+
+} // anonymous namespace
+
+#if !defined(GPU_INFO_USE_X11)
+bool GetNvidiaDriverVersionWithXNVCtrl(std::string *version)
+{
+ return false;
+}
+#endif
+
+#if !defined(GPU_INFO_USE_LIBPCI)
+bool GetPCIDevicesWithLibPCI(std::vector<GPUDeviceInfo> *devices)
+{
+ return false;
+}
+#endif
+
+bool GetSystemInfo(SystemInfo *info)
+{
+ if (!GetPCIDevicesWithLibPCI(&(info->gpus)))
+ {
+ return false;
+ }
+
+ if (info->gpus.size() == 0)
+ {
+ return false;
+ }
+
+ FindPrimaryGPU(info);
+
+ for (size_t i = 0; i < info->gpus.size(); ++i)
+ {
+ GPUDeviceInfo *gpu = &info->gpus[i];
+
+ // New GPUs might be added inside this loop, don't query for their driver version again
+ if (!gpu->driverVendor.empty())
+ {
+ continue;
+ }
+
+ if (IsAMD(gpu->vendorId))
+ {
+ std::string version;
+ if (GetAMDBrahmaDriverVersion(&version))
+ {
+ gpu->driverVendor = "AMD (Brahma)";
+ gpu->driverVersion = std::move(version);
+ }
+ else if (GetAMDCatalystDriverVersion(&version))
+ {
+ gpu->driverVendor = "AMD (Catalyst)";
+ gpu->driverVersion = std::move(version);
+ }
+ }
+
+ if (IsNvidia(gpu->vendorId))
+ {
+ std::string version;
+ if (GetNvidiaDriverVersionWithXNVCtrl(&version))
+ {
+ gpu->driverVendor = "Nvidia";
+ gpu->driverVersion = std::move(version);
+ }
+ }
+
+ // In dual-GPU cases the PCI scan sometimes only gives us the Intel GPU.
+ // If we are able to query for the Nvidia driver version, it means there
+ // was hidden Nvidia GPU, so we add it to the list and make it primary.
+ if (IsIntel(gpu->vendorId) && info->gpus.size() == 1)
+ {
+ std::string version;
+ if (GetNvidiaDriverVersionWithXNVCtrl(&version))
+ {
+ GPUDeviceInfo nvidiaInfo;
+ nvidiaInfo.vendorId = kVendorID_Nvidia;
+ nvidiaInfo.deviceId = 0;
+ gpu->driverVendor = "Nvidia";
+ gpu->driverVersion = std::move(version);
+
+ info->gpus.emplace_back(std::move(nvidiaInfo));
+ info->isOptimus = true;
+ }
+ }
+ }
+
+ return true;
+}
+
+} // namespace angle
diff --git a/src/3rdparty/angle/src/gpu_info_util/SystemInfo_mac.mm b/src/3rdparty/angle/src/gpu_info_util/SystemInfo_mac.mm
new file mode 100644
index 0000000000..7a7a62d170
--- /dev/null
+++ b/src/3rdparty/angle/src/gpu_info_util/SystemInfo_mac.mm
@@ -0,0 +1,170 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SystemInfo_mac.cpp: implementation of the Mac-specific parts of SystemInfo.h
+
+#include "gpu_info_util/SystemInfo_internal.h"
+
+#import <Cocoa/Cocoa.h>
+#import <IOKit/IOKitLib.h>
+
+namespace angle
+{
+
+namespace
+{
+
+std::string GetMachineModel()
+{
+ io_service_t platformExpert = IOServiceGetMatchingService(
+ kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"));
+
+ if (platformExpert == IO_OBJECT_NULL)
+ {
+ return "";
+ }
+
+ CFDataRef modelData = static_cast<CFDataRef>(
+ IORegistryEntryCreateCFProperty(platformExpert, CFSTR("model"), kCFAllocatorDefault, 0));
+ if (modelData == nullptr)
+ {
+ IOObjectRelease(platformExpert);
+ return "";
+ }
+
+ std::string result = reinterpret_cast<const char *>(CFDataGetBytePtr(modelData));
+
+ IOObjectRelease(platformExpert);
+ CFRelease(modelData);
+
+ return result;
+}
+
+// Extracts one integer property from a registry entry.
+bool GetEntryProperty(io_registry_entry_t entry, CFStringRef name, uint32_t *value)
+{
+ *value = 0;
+
+ CFDataRef data = static_cast<CFDataRef>(
+ IORegistryEntrySearchCFProperty(entry, kIOServicePlane, name, kCFAllocatorDefault,
+ kIORegistryIterateRecursively | kIORegistryIterateParents));
+
+ if (data == nullptr)
+ {
+ return false;
+ }
+
+ const uint32_t *valuePtr = reinterpret_cast<const uint32_t *>(CFDataGetBytePtr(data));
+
+ if (valuePtr == nullptr)
+ {
+ CFRelease(data);
+ return false;
+ }
+
+ *value = *valuePtr;
+ CFRelease(data);
+ return true;
+}
+
+// CGDisplayIOServicePort is deprecated as of macOS 10.9, but has no replacement, see
+// https://crbug.com/650837
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+// Find the info of the current GPU.
+bool GetActiveGPU(VendorID *vendorId, DeviceID *deviceId)
+{
+ io_registry_entry_t port = CGDisplayIOServicePort(kCGDirectMainDisplay);
+
+ return GetEntryProperty(port, CFSTR("vendor-id"), vendorId) &&
+ GetEntryProperty(port, CFSTR("device-id"), deviceId);
+}
+
+#pragma clang diagnostic pop
+
+// Gathers the vendor and device IDs for the PCI GPUs
+bool GetPCIDevices(std::vector<GPUDeviceInfo> *devices)
+{
+ // matchDictionary will be consumed by IOServiceGetMatchingServices, no need to release it.
+ CFMutableDictionaryRef matchDictionary = IOServiceMatching("IOPCIDevice");
+
+ io_iterator_t entryIterator;
+ if (IOServiceGetMatchingServices(kIOMasterPortDefault, matchDictionary, &entryIterator) !=
+ kIOReturnSuccess)
+ {
+ return false;
+ }
+
+ io_registry_entry_t entry = IO_OBJECT_NULL;
+
+ while ((entry = IOIteratorNext(entryIterator)) != IO_OBJECT_NULL)
+ {
+ constexpr uint32_t kClassCodeDisplayVGA = 0x30000;
+ uint32_t classCode;
+ GPUDeviceInfo info;
+
+ if (GetEntryProperty(entry, CFSTR("class-code"), &classCode) &&
+ classCode == kClassCodeDisplayVGA &&
+ GetEntryProperty(entry, CFSTR("vendor-id"), &info.vendorId) &&
+ GetEntryProperty(entry, CFSTR("device-id"), &info.deviceId))
+ {
+ devices->push_back(info);
+ }
+
+ IOObjectRelease(entry);
+ }
+ IOObjectRelease(entryIterator);
+
+ return true;
+}
+
+} // anonymous namespace
+
+bool GetSystemInfo(SystemInfo *info)
+{
+ {
+ int32_t major = 0;
+ int32_t minor = 0;
+ ParseMacMachineModel(GetMachineModel(), &info->machineModelName, &major, &minor);
+ info->machineModelVersion = std::to_string(major) + "." + std::to_string(minor);
+ }
+
+ if (!GetPCIDevices(&(info->gpus)))
+ {
+ return false;
+ }
+
+ if (info->gpus.empty())
+ {
+ return false;
+ }
+
+ // Find the active GPU
+ {
+ VendorID activeVendor;
+ DeviceID activeDevice;
+ if (!GetActiveGPU(&activeVendor, &activeDevice))
+ {
+ return false;
+ }
+
+ for (size_t i = 0; i < info->gpus.size(); ++i)
+ {
+ if (info->gpus[i].vendorId == activeVendor && info->gpus[i].deviceId == activeDevice)
+ {
+ info->activeGPUIndex = i;
+ break;
+ }
+ }
+ }
+
+ FindPrimaryGPU(info);
+
+ return true;
+}
+
+} // namespace angle
diff --git a/src/3rdparty/angle/src/gpu_info_util/SystemInfo_win.cpp b/src/3rdparty/angle/src/gpu_info_util/SystemInfo_win.cpp
new file mode 100644
index 0000000000..041fdad34d
--- /dev/null
+++ b/src/3rdparty/angle/src/gpu_info_util/SystemInfo_win.cpp
@@ -0,0 +1,251 @@
+//
+// Copyright (c) 2013-2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SystemInfo_win.cpp: implementation of the Windows-specific parts of SystemInfo.h
+
+#include "gpu_info_util/SystemInfo_internal.h"
+
+#include "common/debug.h"
+#include "common/string_utils.h"
+
+// Windows.h needs to be included first
+#include <windows.h>
+
+#if defined(GPU_INFO_USE_SETUPAPI)
+// Remove parts of commctrl.h that have compile errors
+#define NOTOOLBAR
+#define NOTOOLTIPS
+#include <cfgmgr32.h>
+#include <setupapi.h>
+#elif defined(GPU_INFO_USE_DXGI)
+#include <dxgi.h>
+#include <d3d10.h>
+#else
+#error "SystemInfo_win needs at least GPU_INFO_USE_SETUPAPI or GPU_INFO_USE_DXGI defined"
+#endif
+
+#include <array>
+#include <sstream>
+
+namespace angle
+{
+
+namespace
+{
+
+// Returns the CM device ID of the primary GPU.
+std::string GetPrimaryDisplayDeviceId()
+{
+ DISPLAY_DEVICEA displayDevice;
+ displayDevice.cb = sizeof(DISPLAY_DEVICEA);
+
+ for (int i = 0; EnumDisplayDevicesA(nullptr, i, &displayDevice, 0); ++i)
+ {
+ if (displayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
+ {
+ return displayDevice.DeviceID;
+ }
+ }
+
+ return "";
+}
+
+#if defined(GPU_INFO_USE_SETUPAPI)
+
+std::string GetRegistryStringValue(HKEY key, const char *valueName)
+{
+ std::array<char, 255> value;
+ DWORD valueSize = sizeof(value);
+ if (RegQueryValueExA(key, valueName, nullptr, nullptr, reinterpret_cast<LPBYTE>(value.data()),
+ &valueSize) == ERROR_SUCCESS)
+ {
+ return value.data();
+ }
+ return "";
+}
+
+// Gathers information about the devices from the registry. The reason why we aren't using
+// a dedicated API such as DXGI is that we need information like the driver vendor and date.
+// DXGI doesn't provide a way to know the device registry key from an IDXGIAdapter.
+bool GetDevicesFromRegistry(std::vector<GPUDeviceInfo> *devices)
+{
+ // Display adapter class GUID from
+ // https://msdn.microsoft.com/en-us/library/windows/hardware/ff553426%28v=vs.85%29.aspx
+ GUID displayClass = {
+ 0x4d36e968, 0xe325, 0x11ce, {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}};
+
+ HDEVINFO deviceInfo = SetupDiGetClassDevsW(&displayClass, nullptr, nullptr, DIGCF_PRESENT);
+
+ if (deviceInfo == INVALID_HANDLE_VALUE)
+ {
+ return false;
+ }
+
+ // This iterates over the devices of the "Display adapter" class
+ DWORD deviceIndex = 0;
+ SP_DEVINFO_DATA deviceData;
+ deviceData.cbSize = sizeof(deviceData);
+ while (SetupDiEnumDeviceInfo(deviceInfo, deviceIndex++, &deviceData))
+ {
+ // The device and vendor IDs can be gathered directly, but information about the driver
+ // requires some registry digging
+ char fullDeviceID[MAX_DEVICE_ID_LEN];
+ if (CM_Get_Device_IDA(deviceData.DevInst, fullDeviceID, MAX_DEVICE_ID_LEN, 0) != CR_SUCCESS)
+ {
+ continue;
+ }
+
+ GPUDeviceInfo device;
+
+ if (!CMDeviceIDToDeviceAndVendorID(fullDeviceID, &device.vendorId, &device.deviceId))
+ {
+ continue;
+ }
+
+ // The driver key will end with something like {<displayClass>}/<4 digit number>.
+ std::array<WCHAR, 255> value;
+ if (!SetupDiGetDeviceRegistryPropertyW(deviceInfo, &deviceData, SPDRP_DRIVER, nullptr,
+ reinterpret_cast<PBYTE>(value.data()), sizeof(value),
+ nullptr))
+ {
+ continue;
+ }
+
+ std::wstring driverKey = L"System\\CurrentControlSet\\Control\\Class\\";
+ driverKey += value.data();
+
+ HKEY key;
+ if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, driverKey.c_str(), 0, KEY_QUERY_VALUE, &key) !=
+ ERROR_SUCCESS)
+ {
+ continue;
+ }
+
+ device.driverVersion = GetRegistryStringValue(key, "DriverVersion");
+ device.driverDate = GetRegistryStringValue(key, "DriverDate");
+ device.driverVendor = GetRegistryStringValue(key, "ProviderName");
+
+ RegCloseKey(key);
+
+ devices->push_back(device);
+ }
+
+ SetupDiDestroyDeviceInfoList(deviceInfo);
+
+ return true;
+}
+
+#elif defined(GPU_INFO_USE_DXGI)
+
+bool GetDevicesFromDXGI(std::vector<GPUDeviceInfo> *devices)
+{
+ IDXGIFactory *factory;
+ if (!SUCCEEDED(CreateDXGIFactory(__uuidof(IDXGIFactory), reinterpret_cast<void **>(&factory))))
+ {
+ return false;
+ }
+
+ UINT i = 0;
+ IDXGIAdapter *adapter = nullptr;
+ while (factory->EnumAdapters(i++, &adapter) != DXGI_ERROR_NOT_FOUND)
+ {
+ DXGI_ADAPTER_DESC desc;
+ adapter->GetDesc(&desc);
+
+ LARGE_INTEGER umdVersion;
+ if (adapter->CheckInterfaceSupport(__uuidof(ID3D10Device), &umdVersion) ==
+ DXGI_ERROR_UNSUPPORTED)
+ {
+ adapter->Release();
+ continue;
+ }
+
+ // The UMD driver version here is the same as in the registry except for the last number.
+ uint64_t intVersion = umdVersion.QuadPart;
+ std::ostringstream o;
+
+ const uint64_t kMask = 0xFF;
+ o << ((intVersion >> 48) & kMask) << ".";
+ o << ((intVersion >> 32) & kMask) << ".";
+ o << ((intVersion >> 16) & kMask) << ".";
+ o << (intVersion & kMask);
+
+ GPUDeviceInfo device;
+ device.vendorId = desc.VendorId;
+ device.deviceId = desc.DeviceId;
+ device.driverVersion = o.str();
+
+ devices->push_back(device);
+
+ adapter->Release();
+ }
+
+ factory->Release();
+
+ return true;
+}
+
+#else
+#error
+#endif
+
+} // anonymous namespace
+
+bool GetSystemInfo(SystemInfo *info)
+{
+ // Get the CM device ID first so that it is returned even in error cases.
+ info->primaryDisplayDeviceId = GetPrimaryDisplayDeviceId();
+
+#if defined(GPU_INFO_USE_SETUPAPI)
+ if (!GetDevicesFromRegistry(&info->gpus))
+ {
+ return false;
+ }
+#elif defined(GPU_INFO_USE_DXGI)
+ if (!GetDevicesFromDXGI(&info->gpus))
+ {
+ return false;
+ }
+#else
+#error
+#endif
+
+ if (info->gpus.size() == 0)
+ {
+ return false;
+ }
+
+ FindPrimaryGPU(info);
+
+ // Override the primary GPU index with what we gathered from EnumDisplayDevices
+ uint32_t primaryVendorId = 0;
+ uint32_t primaryDeviceId = 0;
+
+ if (!CMDeviceIDToDeviceAndVendorID(info->primaryDisplayDeviceId, &primaryVendorId,
+ &primaryDeviceId))
+ {
+ return false;
+ }
+
+ bool foundPrimary = false;
+ for (size_t i = 0; i < info->gpus.size(); ++i)
+ {
+ if (info->gpus[i].vendorId == primaryVendorId && info->gpus[i].deviceId == primaryDeviceId)
+ {
+ info->primaryGPUIndex = static_cast<int>(i);
+ foundPrimary = true;
+ }
+ }
+ ASSERT(foundPrimary);
+
+ // nvd3d9wrap.dll is loaded into all processes when Optimus is enabled.
+ HMODULE nvd3d9wrap = GetModuleHandleW(L"nvd3d9wrap.dll");
+ info->isOptimus = nvd3d9wrap != nullptr;
+
+ return true;
+}
+
+} // namespace angle
diff --git a/src/3rdparty/angle/src/gpu_info_util/SystemInfo_x11.cpp b/src/3rdparty/angle/src/gpu_info_util/SystemInfo_x11.cpp
new file mode 100644
index 0000000000..3513309f36
--- /dev/null
+++ b/src/3rdparty/angle/src/gpu_info_util/SystemInfo_x11.cpp
@@ -0,0 +1,53 @@
+//
+// Copyright (c) 2013-2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SystemInfo_x11.cpp: implementation of the X11-specific parts of SystemInfo.h
+
+#include "gpu_info_util/SystemInfo_internal.h"
+
+#include <X11/Xlib.h>
+
+#include "common/debug.h"
+#include "third_party/libXNVCtrl/NVCtrl.h"
+#include "third_party/libXNVCtrl/NVCtrlLib.h"
+
+#if !defined(GPU_INFO_USE_X11)
+#error SystemInfo_x11.cpp compiled without GPU_INFO_USE_X11
+#endif
+
+namespace angle
+{
+
+bool GetNvidiaDriverVersionWithXNVCtrl(std::string *version)
+{
+ *version = "";
+
+ int eventBase = 0;
+ int errorBase = 0;
+
+ Display *display = XOpenDisplay(nullptr);
+
+ if (XNVCTRLQueryExtension(display, &eventBase, &errorBase))
+ {
+ int screenCount = ScreenCount(display);
+ for (int screen = 0; screen < screenCount; ++screen)
+ {
+ char *buffer = nullptr;
+ if (XNVCTRLIsNvScreen(display, screen) &&
+ XNVCTRLQueryStringAttribute(display, screen, 0,
+ NV_CTRL_STRING_NVIDIA_DRIVER_VERSION, &buffer))
+ {
+ ASSERT(buffer != nullptr);
+ *version = buffer;
+ XFree(buffer);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+}
diff --git a/src/3rdparty/angle/src/id/commit.h b/src/3rdparty/angle/src/id/commit.h
deleted file mode 100644
index 0546412964..0000000000
--- a/src/3rdparty/angle/src/id/commit.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#define ANGLE_COMMIT_HASH "8613f4946861"
-#define ANGLE_COMMIT_HASH_SIZE 12
-#define ANGLE_COMMIT_DATE "2016-02-11 19:53:41 +0000"
diff --git a/src/3rdparty/angle/src/image_util/copyimage.cpp b/src/3rdparty/angle/src/image_util/copyimage.cpp
new file mode 100644
index 0000000000..cc07908158
--- /dev/null
+++ b/src/3rdparty/angle/src/image_util/copyimage.cpp
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// copyimage.cpp: Defines image copying functions
+
+#include "image_util/copyimage.h"
+
+namespace angle
+{
+
+void CopyBGRA8ToRGBA8(const uint8_t *source, uint8_t *dest)
+{
+ uint32_t argb = *reinterpret_cast<const uint32_t *>(source);
+ *reinterpret_cast<uint32_t *>(dest) = (argb & 0xFF00FF00) | // Keep alpha and green
+ (argb & 0x00FF0000) >> 16 | // Move red to blue
+ (argb & 0x000000FF) << 16; // Move blue to red
+}
+
+} // namespace angle
diff --git a/src/3rdparty/angle/src/image_util/copyimage.h b/src/3rdparty/angle/src/image_util/copyimage.h
new file mode 100644
index 0000000000..bc8c1390eb
--- /dev/null
+++ b/src/3rdparty/angle/src/image_util/copyimage.h
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// copyimage.h: Defines image copying functions
+
+#ifndef IMAGEUTIL_COPYIMAGE_H_
+#define IMAGEUTIL_COPYIMAGE_H_
+
+#include "common/Color.h"
+
+#include "image_util/imageformats.h"
+
+#include <stdint.h>
+
+namespace angle
+{
+
+template <typename sourceType, typename colorDataType>
+void ReadColor(const uint8_t *source, uint8_t *dest);
+
+template <typename destType, typename colorDataType>
+void WriteColor(const uint8_t *source, uint8_t *dest);
+
+template <typename sourceType, typename destType, typename colorDataType>
+void CopyPixel(const uint8_t *source, uint8_t *dest);
+
+void CopyBGRA8ToRGBA8(const uint8_t *source, uint8_t *dest);
+
+} // namespace angle
+
+#include "copyimage.inl"
+
+#endif // IMAGEUTIL_COPYIMAGE_H_
diff --git a/src/3rdparty/angle/src/image_util/copyimage.inl b/src/3rdparty/angle/src/image_util/copyimage.inl
new file mode 100644
index 0000000000..dbada81291
--- /dev/null
+++ b/src/3rdparty/angle/src/image_util/copyimage.inl
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// copyimage.inl: Defines image copying functions
+
+namespace angle
+{
+
+template <typename sourceType, typename colorDataType>
+inline void ReadColor(const uint8_t *source, uint8_t *dest)
+{
+ sourceType::readColor(reinterpret_cast<Color<colorDataType>*>(dest),
+ reinterpret_cast<const sourceType*>(source));
+}
+
+template <typename destType, typename colorDataType>
+inline void WriteColor(const uint8_t *source, uint8_t *dest)
+{
+ destType::writeColor(reinterpret_cast<destType*>(dest),
+ reinterpret_cast<const Color<colorDataType>*>(source));
+}
+
+template <typename sourceType, typename destType, typename colorDataType>
+inline void CopyPixel(const uint8_t *source, uint8_t *dest)
+{
+ colorDataType temp;
+ ReadColor<sourceType, colorDataType>(source, &temp);
+ WriteColor<destType, colorDataType>(&temp, dest);
+}
+
+} // namespace angle
diff --git a/src/3rdparty/angle/src/image_util/generatemip.h b/src/3rdparty/angle/src/image_util/generatemip.h
new file mode 100644
index 0000000000..a89db823b0
--- /dev/null
+++ b/src/3rdparty/angle/src/image_util/generatemip.h
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// generatemip.h: Defines the GenerateMip function, templated on the format
+// type of the image for which mip levels are being generated.
+
+#ifndef IMAGEUTIL_GENERATEMIP_H_
+#define IMAGEUTIL_GENERATEMIP_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace angle
+{
+
+template <typename T>
+inline void GenerateMip(size_t sourceWidth,
+ size_t sourceHeight,
+ size_t sourceDepth,
+ const uint8_t *sourceData,
+ size_t sourceRowPitch,
+ size_t sourceDepthPitch,
+ uint8_t *destData,
+ size_t destRowPitch,
+ size_t destDepthPitch);
+
+} // namespace angle
+
+#include "generatemip.inl"
+
+#endif // IMAGEUTIL_GENERATEMIP_H_
diff --git a/src/3rdparty/angle/src/image_util/generatemip.inl b/src/3rdparty/angle/src/image_util/generatemip.inl
new file mode 100644
index 0000000000..ddf510c749
--- /dev/null
+++ b/src/3rdparty/angle/src/image_util/generatemip.inl
@@ -0,0 +1,268 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// generatemip.inl: Defines the GenerateMip function, templated on the format
+// type of the image for which mip levels are being generated.
+
+#include "common/mathutil.h"
+
+#include "image_util/imageformats.h"
+
+namespace angle
+{
+
+namespace priv
+{
+
+template <typename T>
+static inline T *GetPixel(uint8_t *data, size_t x, size_t y, size_t z, size_t rowPitch, size_t depthPitch)
+{
+ return reinterpret_cast<T*>(data + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch));
+}
+
+template <typename T>
+static inline const T *GetPixel(const uint8_t *data, size_t x, size_t y, size_t z, size_t rowPitch, size_t depthPitch)
+{
+ return reinterpret_cast<const T*>(data + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch));
+}
+
+template <typename T>
+static void GenerateMip_Y(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+ const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+ size_t destWidth, size_t destHeight, size_t destDepth,
+ uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
+{
+ ASSERT(sourceWidth == 1);
+ ASSERT(sourceHeight > 1);
+ ASSERT(sourceDepth == 1);
+
+ for (size_t y = 0; y < destHeight; y++)
+ {
+ const T *src0 = GetPixel<T>(sourceData, 0, y * 2, 0, sourceRowPitch, sourceDepthPitch);
+ const T *src1 = GetPixel<T>(sourceData, 0, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch);
+ T *dst = GetPixel<T>(destData, 0, y, 0, destRowPitch, destDepthPitch);
+
+ T::average(dst, src0, src1);
+ }
+}
+
+template <typename T>
+static void GenerateMip_X(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+ const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+ size_t destWidth, size_t destHeight, size_t destDepth,
+ uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
+{
+ ASSERT(sourceWidth > 1);
+ ASSERT(sourceHeight == 1);
+ ASSERT(sourceDepth == 1);
+
+ for (size_t x = 0; x < destWidth; x++)
+ {
+ const T *src0 = GetPixel<T>(sourceData, x * 2, 0, 0, sourceRowPitch, sourceDepthPitch);
+ const T *src1 = GetPixel<T>(sourceData, x * 2 + 1, 0, 0, sourceRowPitch, sourceDepthPitch);
+ T *dst = GetPixel<T>(destData, x, 0, 0, destRowPitch, destDepthPitch);
+
+ T::average(dst, src0, src1);
+ }
+}
+
+template <typename T>
+static void GenerateMip_Z(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+ const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+ size_t destWidth, size_t destHeight, size_t destDepth,
+ uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
+{
+ ASSERT(sourceWidth == 1);
+ ASSERT(sourceHeight == 1);
+ ASSERT(sourceDepth > 1);
+
+ for (size_t z = 0; z < destDepth; z++)
+ {
+ const T *src0 = GetPixel<T>(sourceData, 0, 0, z * 2, sourceRowPitch, sourceDepthPitch);
+ const T *src1 = GetPixel<T>(sourceData, 0, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+ T *dst = GetPixel<T>(destData, 0, 0, z, destRowPitch, destDepthPitch);
+
+ T::average(dst, src0, src1);
+ }
+}
+
+template <typename T>
+static void GenerateMip_XY(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+ const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+ size_t destWidth, size_t destHeight, size_t destDepth,
+ uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
+{
+ ASSERT(sourceWidth > 1);
+ ASSERT(sourceHeight > 1);
+ ASSERT(sourceDepth == 1);
+
+ for (size_t y = 0; y < destHeight; y++)
+ {
+ for (size_t x = 0; x < destWidth; x++)
+ {
+ const T *src0 = GetPixel<T>(sourceData, x * 2, y * 2, 0, sourceRowPitch, sourceDepthPitch);
+ const T *src1 = GetPixel<T>(sourceData, x * 2, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch);
+ const T *src2 = GetPixel<T>(sourceData, x * 2 + 1, y * 2, 0, sourceRowPitch, sourceDepthPitch);
+ const T *src3 = GetPixel<T>(sourceData, x * 2 + 1, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch);
+ T *dst = GetPixel<T>(destData, x, y, 0, destRowPitch, destDepthPitch);
+
+ T tmp0, tmp1;
+
+ T::average(&tmp0, src0, src1);
+ T::average(&tmp1, src2, src3);
+ T::average(dst, &tmp0, &tmp1);
+ }
+ }
+}
+
+template <typename T>
+static void GenerateMip_YZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+ const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+ size_t destWidth, size_t destHeight, size_t destDepth,
+ uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
+{
+ ASSERT(sourceWidth == 1);
+ ASSERT(sourceHeight > 1);
+ ASSERT(sourceDepth > 1);
+
+ for (size_t z = 0; z < destDepth; z++)
+ {
+ for (size_t y = 0; y < destHeight; y++)
+ {
+ const T *src0 = GetPixel<T>(sourceData, 0, y * 2, z * 2, sourceRowPitch, sourceDepthPitch);
+ const T *src1 = GetPixel<T>(sourceData, 0, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+ const T *src2 = GetPixel<T>(sourceData, 0, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch);
+ const T *src3 = GetPixel<T>(sourceData, 0, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+ T *dst = GetPixel<T>(destData, 0, y, z, destRowPitch, destDepthPitch);
+
+ T tmp0, tmp1;
+
+ T::average(&tmp0, src0, src1);
+ T::average(&tmp1, src2, src3);
+ T::average(dst, &tmp0, &tmp1);
+ }
+ }
+}
+
+template <typename T>
+static void GenerateMip_XZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+ const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+ size_t destWidth, size_t destHeight, size_t destDepth,
+ uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
+{
+ ASSERT(sourceWidth > 1);
+ ASSERT(sourceHeight == 1);
+ ASSERT(sourceDepth > 1);
+
+ for (size_t z = 0; z < destDepth; z++)
+ {
+ for (size_t x = 0; x < destWidth; x++)
+ {
+ const T *src0 = GetPixel<T>(sourceData, x * 2, 0, z * 2, sourceRowPitch, sourceDepthPitch);
+ const T *src1 = GetPixel<T>(sourceData, x * 2, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+ const T *src2 = GetPixel<T>(sourceData, x * 2 + 1, 0, z * 2, sourceRowPitch, sourceDepthPitch);
+ const T *src3 = GetPixel<T>(sourceData, x * 2 + 1, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+ T *dst = GetPixel<T>(destData, x, 0, z, destRowPitch, destDepthPitch);
+
+ T tmp0, tmp1;
+
+ T::average(&tmp0, src0, src1);
+ T::average(&tmp1, src2, src3);
+ T::average(dst, &tmp0, &tmp1);
+ }
+ }
+}
+
+template <typename T>
+static void GenerateMip_XYZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+ const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+ size_t destWidth, size_t destHeight, size_t destDepth,
+ uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
+{
+ ASSERT(sourceWidth > 1);
+ ASSERT(sourceHeight > 1);
+ ASSERT(sourceDepth > 1);
+
+ for (size_t z = 0; z < destDepth; z++)
+ {
+ for (size_t y = 0; y < destHeight; y++)
+ {
+ for (size_t x = 0; x < destWidth; x++)
+ {
+ const T *src0 = GetPixel<T>(sourceData, x * 2, y * 2, z * 2, sourceRowPitch, sourceDepthPitch);
+ const T *src1 = GetPixel<T>(sourceData, x * 2, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+ const T *src2 = GetPixel<T>(sourceData, x * 2, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch);
+ const T *src3 = GetPixel<T>(sourceData, x * 2, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+ const T *src4 = GetPixel<T>(sourceData, x * 2 + 1, y * 2, z * 2, sourceRowPitch, sourceDepthPitch);
+ const T *src5 = GetPixel<T>(sourceData, x * 2 + 1, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+ const T *src6 = GetPixel<T>(sourceData, x * 2 + 1, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch);
+ const T *src7 = GetPixel<T>(sourceData, x * 2 + 1, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
+ T *dst = GetPixel<T>(destData, x, y, z, destRowPitch, destDepthPitch);
+
+ T tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
+
+ T::average(&tmp0, src0, src1);
+ T::average(&tmp1, src2, src3);
+ T::average(&tmp2, src4, src5);
+ T::average(&tmp3, src6, src7);
+
+ T::average(&tmp4, &tmp0, &tmp1);
+ T::average(&tmp5, &tmp2, &tmp3);
+
+ T::average(dst, &tmp4, &tmp5);
+ }
+ }
+ }
+}
+
+
+typedef void (*MipGenerationFunction)(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+ const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+ size_t destWidth, size_t destHeight, size_t destDepth,
+ uint8_t *destData, size_t destRowPitch, size_t destDepthPitch);
+
+template <typename T>
+static MipGenerationFunction GetMipGenerationFunction(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth)
+{
+ uint8_t index = ((sourceWidth > 1) ? 1 : 0) |
+ ((sourceHeight > 1) ? 2 : 0) |
+ ((sourceDepth > 1) ? 4 : 0);
+
+ switch (index)
+ {
+ case 0: return nullptr;
+ case 1: return GenerateMip_X<T>; // W x 1 x 1
+ case 2: return GenerateMip_Y<T>; // 1 x H x 1
+ case 3: return GenerateMip_XY<T>; // W x H x 1
+ case 4: return GenerateMip_Z<T>; // 1 x 1 x D
+ case 5: return GenerateMip_XZ<T>; // W x 1 x D
+ case 6: return GenerateMip_YZ<T>; // 1 x H x D
+ case 7: return GenerateMip_XYZ<T>; // W x H x D
+ }
+
+ UNREACHABLE();
+ return nullptr;
+}
+
+} // namespace priv
+
+template <typename T>
+inline void GenerateMip(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+ const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+ uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
+{
+ size_t mipWidth = std::max<size_t>(1, sourceWidth >> 1);
+ size_t mipHeight = std::max<size_t>(1, sourceHeight >> 1);
+ size_t mipDepth = std::max<size_t>(1, sourceDepth >> 1);
+
+ priv::MipGenerationFunction generationFunction = priv::GetMipGenerationFunction<T>(sourceWidth, sourceHeight, sourceDepth);
+ ASSERT(generationFunction != nullptr);
+
+ generationFunction(sourceWidth, sourceHeight, sourceDepth, sourceData, sourceRowPitch, sourceDepthPitch,
+ mipWidth, mipHeight, mipDepth, destData, destRowPitch, destDepthPitch);
+}
+
+} // namespace angle
diff --git a/src/3rdparty/angle/src/image_util/imageformats.cpp b/src/3rdparty/angle/src/image_util/imageformats.cpp
new file mode 100644
index 0000000000..a4c86945b6
--- /dev/null
+++ b/src/3rdparty/angle/src/image_util/imageformats.cpp
@@ -0,0 +1,1722 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// imageformats.cpp: Defines image format types with functions for mip generation
+// and copying.
+
+#include "image_util/imageformats.h"
+
+#include "common/mathutil.h"
+
+namespace angle
+{
+
+void L8::readColor(gl::ColorF *dst, const L8 *src)
+{
+ const float lum = gl::normalizedToFloat(src->L);
+ dst->red = lum;
+ dst->green = lum;
+ dst->blue = lum;
+ dst->alpha = 1.0f;
+}
+
+void L8::writeColor(L8 *dst, const gl::ColorF *src)
+{
+ dst->L = gl::floatToNormalized<uint8_t>(src->red);
+}
+
+void L8::average(L8 *dst, const L8 *src1, const L8 *src2)
+{
+ dst->L = gl::average(src1->L, src2->L);
+}
+
+void R8::readColor(gl::ColorUI *dst, const R8 *src)
+{
+ dst->red = src->R;
+ dst->green = 0;
+ dst->blue = 0;
+ dst->alpha = 1;
+}
+
+void R8::readColor(gl::ColorF *dst, const R8 *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = 0.0f;
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+}
+
+void R8::writeColor(R8 *dst, const gl::ColorUI *src)
+{
+ dst->R = static_cast<uint8_t>(src->red);
+}
+
+void R8::writeColor(R8 *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<uint8_t>(src->red);
+}
+
+void R8::average(R8 *dst, const R8 *src1, const R8 *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+}
+
+void A8::readColor(gl::ColorF *dst, const A8 *src)
+{
+ dst->red = 0.0f;
+ dst->green = 0.0f;
+ dst->blue = 0.0f;
+ dst->alpha = gl::normalizedToFloat(src->A);
+}
+
+void A8::writeColor(A8 *dst, const gl::ColorF *src)
+{
+ dst->A = gl::floatToNormalized<uint8_t>(src->alpha);
+}
+
+void A8::average(A8 *dst, const A8 *src1, const A8 *src2)
+{
+ dst->A = gl::average(src1->A, src2->A);
+}
+
+void L8A8::readColor(gl::ColorF *dst, const L8A8 *src)
+{
+ const float lum = gl::normalizedToFloat(src->L);
+ dst->red = lum;
+ dst->green = lum;
+ dst->blue = lum;
+ dst->alpha = gl::normalizedToFloat(src->A);
+}
+
+void L8A8::writeColor(L8A8 *dst, const gl::ColorF *src)
+{
+ dst->L = gl::floatToNormalized<uint8_t>(src->red);
+ dst->A = gl::floatToNormalized<uint8_t>(src->alpha);
+}
+
+void L8A8::average(L8A8 *dst, const L8A8 *src1, const L8A8 *src2)
+{
+ *(uint16_t *)dst = (((*(uint16_t *)src1 ^ *(uint16_t *)src2) & 0xFEFE) >> 1) +
+ (*(uint16_t *)src1 & *(uint16_t *)src2);
+}
+
+void A8L8::readColor(gl::ColorF *dst, const A8L8 *src)
+{
+ const float lum = gl::normalizedToFloat(src->L);
+ dst->red = lum;
+ dst->green = lum;
+ dst->blue = lum;
+ dst->alpha = gl::normalizedToFloat(src->A);
+}
+
+void A8L8::writeColor(A8L8 *dst, const gl::ColorF *src)
+{
+ dst->L = gl::floatToNormalized<uint8_t>(src->red);
+ dst->A = gl::floatToNormalized<uint8_t>(src->alpha);
+}
+
+void A8L8::average(A8L8 *dst, const A8L8 *src1, const A8L8 *src2)
+{
+ *(uint16_t *)dst = (((*(uint16_t *)src1 ^ *(uint16_t *)src2) & 0xFEFE) >> 1) +
+ (*(uint16_t *)src1 & *(uint16_t *)src2);
+}
+
+void R8G8::readColor(gl::ColorUI *dst, const R8G8 *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = 0;
+ dst->alpha = 1;
+}
+
+void R8G8::readColor(gl::ColorF *dst, const R8G8 *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+}
+
+void R8G8::writeColor(R8G8 *dst, const gl::ColorUI *src)
+{
+ dst->R = static_cast<uint8_t>(src->red);
+ dst->G = static_cast<uint8_t>(src->green);
+}
+
+void R8G8::writeColor(R8G8 *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<uint8_t>(src->red);
+ dst->G = gl::floatToNormalized<uint8_t>(src->green);
+}
+
+void R8G8::average(R8G8 *dst, const R8G8 *src1, const R8G8 *src2)
+{
+ *(uint16_t *)dst = (((*(uint16_t *)src1 ^ *(uint16_t *)src2) & 0xFEFE) >> 1) +
+ (*(uint16_t *)src1 & *(uint16_t *)src2);
+}
+
+void R8G8B8::readColor(gl::ColorUI *dst, const R8G8B8 *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->G;
+ dst->alpha = 1;
+}
+
+void R8G8B8::readColor(gl::ColorF *dst, const R8G8B8 *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = 1.0f;
+}
+
+void R8G8B8::writeColor(R8G8B8 *dst, const gl::ColorUI *src)
+{
+ dst->R = static_cast<uint8_t>(src->red);
+ dst->G = static_cast<uint8_t>(src->green);
+ dst->B = static_cast<uint8_t>(src->blue);
+}
+
+void R8G8B8::writeColor(R8G8B8 *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<uint8_t>(src->red);
+ dst->G = gl::floatToNormalized<uint8_t>(src->green);
+ dst->B = gl::floatToNormalized<uint8_t>(src->blue);
+}
+
+void R8G8B8::average(R8G8B8 *dst, const R8G8B8 *src1, const R8G8B8 *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+}
+
+void B8G8R8::readColor(gl::ColorUI *dst, const B8G8R8 *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->G;
+ dst->alpha = 1;
+}
+
+void B8G8R8::readColor(gl::ColorF *dst, const B8G8R8 *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = 1.0f;
+}
+
+void B8G8R8::writeColor(B8G8R8 *dst, const gl::ColorUI *src)
+{
+ dst->R = static_cast<uint8_t>(src->red);
+ dst->G = static_cast<uint8_t>(src->green);
+ dst->B = static_cast<uint8_t>(src->blue);
+}
+
+void B8G8R8::writeColor(B8G8R8 *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<uint8_t>(src->red);
+ dst->G = gl::floatToNormalized<uint8_t>(src->green);
+ dst->B = gl::floatToNormalized<uint8_t>(src->blue);
+}
+
+void B8G8R8::average(B8G8R8 *dst, const B8G8R8 *src1, const B8G8R8 *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+}
+
+void R5G6B5::readColor(gl::ColorF *dst, const R5G6B5 *src)
+{
+ dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 11>(src->RGB));
+ dst->green = gl::normalizedToFloat<6>(gl::getShiftedData<6, 5>(src->RGB));
+ dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->RGB));
+ dst->alpha = 1.0f;
+}
+
+void R5G6B5::writeColor(R5G6B5 *dst, const gl::ColorF *src)
+{
+ dst->RGB = gl::shiftData<5, 11>(gl::floatToNormalized<5, uint16_t>(src->red)) |
+ gl::shiftData<6, 5>(gl::floatToNormalized<6, uint16_t>(src->green)) |
+ gl::shiftData<5, 0>(gl::floatToNormalized<5, uint16_t>(src->blue));
+}
+
+void R5G6B5::average(R5G6B5 *dst, const R5G6B5 *src1, const R5G6B5 *src2)
+{
+ dst->RGB = gl::shiftData<5, 11>(gl::average(gl::getShiftedData<5, 11>(src1->RGB),
+ gl::getShiftedData<5, 11>(src2->RGB))) |
+ gl::shiftData<6, 5>(gl::average(gl::getShiftedData<6, 5>(src1->RGB),
+ gl::getShiftedData<6, 5>(src2->RGB))) |
+ gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->RGB),
+ gl::getShiftedData<5, 0>(src2->RGB)));
+}
+
+void B5G6R5::readColor(gl::ColorF *dst, const B5G6R5 *src)
+{
+ dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 11>(src->BGR));
+ dst->green = gl::normalizedToFloat<6>(gl::getShiftedData<6, 5>(src->BGR));
+ dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->BGR));
+ dst->alpha = 1.0f;
+}
+
+void B5G6R5::writeColor(B5G6R5 *dst, const gl::ColorF *src)
+{
+ dst->BGR = gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->blue)) |
+ gl::shiftData<6, 5>(gl::floatToNormalized<6, unsigned short>(src->green)) |
+ gl::shiftData<5, 11>(gl::floatToNormalized<5, unsigned short>(src->red));
+}
+
+void B5G6R5::average(B5G6R5 *dst, const B5G6R5 *src1, const B5G6R5 *src2)
+{
+ dst->BGR = gl::shiftData<5, 11>(gl::average(gl::getShiftedData<5, 11>(src1->BGR),
+ gl::getShiftedData<5, 11>(src2->BGR))) |
+ gl::shiftData<6, 5>(gl::average(gl::getShiftedData<6, 5>(src1->BGR),
+ gl::getShiftedData<6, 5>(src2->BGR))) |
+ gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->BGR),
+ gl::getShiftedData<5, 0>(src2->BGR)));
+}
+
+void A8R8G8B8::readColor(gl::ColorUI *dst, const A8R8G8B8 *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = src->A;
+}
+
+void A8R8G8B8::readColor(gl::ColorF *dst, const A8R8G8B8 *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = gl::normalizedToFloat(src->A);
+}
+
+void A8R8G8B8::writeColor(A8R8G8B8 *dst, const gl::ColorUI *src)
+{
+ dst->R = static_cast<uint8_t>(src->red);
+ dst->G = static_cast<uint8_t>(src->green);
+ dst->B = static_cast<uint8_t>(src->blue);
+ dst->A = static_cast<uint8_t>(src->alpha);
+}
+
+void A8R8G8B8::writeColor(A8R8G8B8 *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<uint8_t>(src->red);
+ dst->G = gl::floatToNormalized<uint8_t>(src->green);
+ dst->B = gl::floatToNormalized<uint8_t>(src->blue);
+ dst->A = gl::floatToNormalized<uint8_t>(src->alpha);
+}
+
+void A8R8G8B8::average(A8R8G8B8 *dst, const A8R8G8B8 *src1, const A8R8G8B8 *src2)
+{
+ *(uint32_t *)dst = (((*(uint32_t *)src1 ^ *(uint32_t *)src2) & 0xFEFEFEFE) >> 1) +
+ (*(uint32_t *)src1 & *(uint32_t *)src2);
+}
+
+void R8G8B8A8::readColor(gl::ColorUI *dst, const R8G8B8A8 *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = src->A;
+}
+
+void R8G8B8A8::readColor(gl::ColorF *dst, const R8G8B8A8 *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = gl::normalizedToFloat(src->A);
+}
+
+void R8G8B8A8::writeColor(R8G8B8A8 *dst, const gl::ColorUI *src)
+{
+ dst->R = static_cast<uint8_t>(src->red);
+ dst->G = static_cast<uint8_t>(src->green);
+ dst->B = static_cast<uint8_t>(src->blue);
+ dst->A = static_cast<uint8_t>(src->alpha);
+}
+
+void R8G8B8A8::writeColor(R8G8B8A8 *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<uint8_t>(src->red);
+ dst->G = gl::floatToNormalized<uint8_t>(src->green);
+ dst->B = gl::floatToNormalized<uint8_t>(src->blue);
+ dst->A = gl::floatToNormalized<uint8_t>(src->alpha);
+}
+
+void R8G8B8A8::average(R8G8B8A8 *dst, const R8G8B8A8 *src1, const R8G8B8A8 *src2)
+{
+ *(uint32_t *)dst = (((*(uint32_t *)src1 ^ *(uint32_t *)src2) & 0xFEFEFEFE) >> 1) +
+ (*(uint32_t *)src1 & *(uint32_t *)src2);
+}
+
+void R8G8B8A8SRGB::readColor(gl::ColorF *dst, const R8G8B8A8SRGB *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = gl::normalizedToFloat(src->A);
+}
+
+void R8G8B8A8SRGB::writeColor(R8G8B8A8SRGB *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<uint8_t>(src->red);
+ dst->G = gl::floatToNormalized<uint8_t>(src->green);
+ dst->B = gl::floatToNormalized<uint8_t>(src->blue);
+ dst->A = gl::floatToNormalized<uint8_t>(src->alpha);
+}
+
+void R8G8B8A8SRGB::average(R8G8B8A8SRGB *dst, const R8G8B8A8SRGB *src1, const R8G8B8A8SRGB *src2)
+{
+ dst->R =
+ gl::linearToSRGB(static_cast<uint8_t>((static_cast<uint16_t>(gl::sRGBToLinear(src1->R)) +
+ static_cast<uint16_t>(gl::sRGBToLinear(src2->R))) >>
+ 1));
+ dst->G =
+ gl::linearToSRGB(static_cast<uint8_t>((static_cast<uint16_t>(gl::sRGBToLinear(src1->G)) +
+ static_cast<uint16_t>(gl::sRGBToLinear(src2->G))) >>
+ 1));
+ dst->B =
+ gl::linearToSRGB(static_cast<uint8_t>((static_cast<uint16_t>(gl::sRGBToLinear(src1->B)) +
+ static_cast<uint16_t>(gl::sRGBToLinear(src2->B))) >>
+ 1));
+ dst->A = static_cast<uint8_t>(
+ (static_cast<uint16_t>(src1->A) + static_cast<uint16_t>(src2->A)) >> 1);
+}
+
+void B8G8R8A8::readColor(gl::ColorUI *dst, const B8G8R8A8 *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = src->A;
+}
+
+void B8G8R8A8::readColor(gl::ColorF *dst, const B8G8R8A8 *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = gl::normalizedToFloat(src->A);
+}
+
+void B8G8R8A8::writeColor(B8G8R8A8 *dst, const gl::ColorUI *src)
+{
+ dst->R = static_cast<uint8_t>(src->red);
+ dst->G = static_cast<uint8_t>(src->green);
+ dst->B = static_cast<uint8_t>(src->blue);
+ dst->A = static_cast<uint8_t>(src->alpha);
+}
+
+void B8G8R8A8::writeColor(B8G8R8A8 *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<uint8_t>(src->red);
+ dst->G = gl::floatToNormalized<uint8_t>(src->green);
+ dst->B = gl::floatToNormalized<uint8_t>(src->blue);
+ dst->A = gl::floatToNormalized<uint8_t>(src->alpha);
+}
+
+void B8G8R8A8::average(B8G8R8A8 *dst, const B8G8R8A8 *src1, const B8G8R8A8 *src2)
+{
+ *(uint32_t *)dst = (((*(uint32_t *)src1 ^ *(uint32_t *)src2) & 0xFEFEFEFE) >> 1) +
+ (*(uint32_t *)src1 & *(uint32_t *)src2);
+}
+
+void B8G8R8X8::readColor(gl::ColorUI *dst, const B8G8R8X8 *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = 1;
+}
+
+void B8G8R8X8::readColor(gl::ColorF *dst, const B8G8R8X8 *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = 1.0f;
+}
+
+void B8G8R8X8::writeColor(B8G8R8X8 *dst, const gl::ColorUI *src)
+{
+ dst->R = static_cast<uint8_t>(src->red);
+ dst->G = static_cast<uint8_t>(src->green);
+ dst->B = static_cast<uint8_t>(src->blue);
+ dst->X = 255;
+}
+
+void B8G8R8X8::writeColor(B8G8R8X8 *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<uint8_t>(src->red);
+ dst->G = gl::floatToNormalized<uint8_t>(src->green);
+ dst->B = gl::floatToNormalized<uint8_t>(src->blue);
+ dst->X = 255;
+}
+
+void B8G8R8X8::average(B8G8R8X8 *dst, const B8G8R8X8 *src1, const B8G8R8X8 *src2)
+{
+ *(uint32_t *)dst = (((*(uint32_t *)src1 ^ *(uint32_t *)src2) & 0xFEFEFEFE) >> 1) +
+ (*(uint32_t *)src1 & *(uint32_t *)src2);
+ dst->X = 255;
+}
+
+void A1R5G5B5::readColor(gl::ColorF *dst, const A1R5G5B5 *src)
+{
+ dst->alpha = gl::normalizedToFloat<1>(gl::getShiftedData<1, 15>(src->ARGB));
+ dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 10>(src->ARGB));
+ dst->green = gl::normalizedToFloat<5>(gl::getShiftedData<5, 5>(src->ARGB));
+ dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->ARGB));
+}
+
+void A1R5G5B5::writeColor(A1R5G5B5 *dst, const gl::ColorF *src)
+{
+ dst->ARGB = gl::shiftData<1, 15>(gl::floatToNormalized<1, uint16_t>(src->alpha)) |
+ gl::shiftData<5, 10>(gl::floatToNormalized<5, uint16_t>(src->red)) |
+ gl::shiftData<5, 5>(gl::floatToNormalized<5, uint16_t>(src->green)) |
+ gl::shiftData<5, 0>(gl::floatToNormalized<5, uint16_t>(src->blue));
+}
+
+void A1R5G5B5::average(A1R5G5B5 *dst, const A1R5G5B5 *src1, const A1R5G5B5 *src2)
+{
+ dst->ARGB = gl::shiftData<1, 15>(gl::average(gl::getShiftedData<1, 15>(src1->ARGB),
+ gl::getShiftedData<1, 15>(src2->ARGB))) |
+ gl::shiftData<5, 10>(gl::average(gl::getShiftedData<5, 10>(src1->ARGB),
+ gl::getShiftedData<5, 10>(src2->ARGB))) |
+ gl::shiftData<5, 5>(gl::average(gl::getShiftedData<5, 5>(src1->ARGB),
+ gl::getShiftedData<5, 5>(src2->ARGB))) |
+ gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->ARGB),
+ gl::getShiftedData<5, 0>(src2->ARGB)));
+}
+
+void R5G5B5A1::readColor(gl::ColorF *dst, const R5G5B5A1 *src)
+{
+ dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 11>(src->RGBA));
+ dst->green = gl::normalizedToFloat<5>(gl::getShiftedData<5, 6>(src->RGBA));
+ dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 1>(src->RGBA));
+ dst->alpha = gl::normalizedToFloat<1>(gl::getShiftedData<1, 0>(src->RGBA));
+}
+
+void R5G5B5A1::writeColor(R5G5B5A1 *dst, const gl::ColorF *src)
+{
+ dst->RGBA = gl::shiftData<5, 11>(gl::floatToNormalized<5, uint16_t>(src->red)) |
+ gl::shiftData<5, 6>(gl::floatToNormalized<5, uint16_t>(src->green)) |
+ gl::shiftData<5, 1>(gl::floatToNormalized<5, uint16_t>(src->blue)) |
+ gl::shiftData<1, 0>(gl::floatToNormalized<1, uint16_t>(src->alpha));
+}
+
+void R5G5B5A1::average(R5G5B5A1 *dst, const R5G5B5A1 *src1, const R5G5B5A1 *src2)
+{
+ dst->RGBA = gl::shiftData<5, 11>(gl::average(gl::getShiftedData<5, 11>(src1->RGBA),
+ gl::getShiftedData<5, 11>(src2->RGBA))) |
+ gl::shiftData<5, 6>(gl::average(gl::getShiftedData<5, 6>(src1->RGBA),
+ gl::getShiftedData<5, 6>(src2->RGBA))) |
+ gl::shiftData<5, 1>(gl::average(gl::getShiftedData<5, 1>(src1->RGBA),
+ gl::getShiftedData<5, 1>(src2->RGBA))) |
+ gl::shiftData<1, 0>(gl::average(gl::getShiftedData<1, 0>(src1->RGBA),
+ gl::getShiftedData<1, 0>(src2->RGBA)));
+}
+
+void R4G4B4A4::readColor(gl::ColorF *dst, const R4G4B4A4 *src)
+{
+ dst->red = gl::normalizedToFloat<4>(gl::getShiftedData<4, 12>(src->RGBA));
+ dst->green = gl::normalizedToFloat<4>(gl::getShiftedData<4, 8>(src->RGBA));
+ dst->blue = gl::normalizedToFloat<4>(gl::getShiftedData<4, 4>(src->RGBA));
+ dst->alpha = gl::normalizedToFloat<4>(gl::getShiftedData<4, 0>(src->RGBA));
+}
+
+void R4G4B4A4::writeColor(R4G4B4A4 *dst, const gl::ColorF *src)
+{
+ dst->RGBA = gl::shiftData<4, 12>(gl::floatToNormalized<4, uint16_t>(src->red)) |
+ gl::shiftData<4, 8>(gl::floatToNormalized<4, uint16_t>(src->green)) |
+ gl::shiftData<4, 4>(gl::floatToNormalized<4, uint16_t>(src->blue)) |
+ gl::shiftData<4, 0>(gl::floatToNormalized<4, uint16_t>(src->alpha));
+}
+
+void R4G4B4A4::average(R4G4B4A4 *dst, const R4G4B4A4 *src1, const R4G4B4A4 *src2)
+{
+ dst->RGBA = gl::shiftData<4, 12>(gl::average(gl::getShiftedData<4, 12>(src1->RGBA),
+ gl::getShiftedData<4, 12>(src2->RGBA))) |
+ gl::shiftData<4, 8>(gl::average(gl::getShiftedData<4, 8>(src1->RGBA),
+ gl::getShiftedData<4, 8>(src2->RGBA))) |
+ gl::shiftData<4, 4>(gl::average(gl::getShiftedData<4, 4>(src1->RGBA),
+ gl::getShiftedData<4, 4>(src2->RGBA))) |
+ gl::shiftData<4, 0>(gl::average(gl::getShiftedData<4, 0>(src1->RGBA),
+ gl::getShiftedData<4, 0>(src2->RGBA)));
+}
+
+void A4R4G4B4::readColor(gl::ColorF *dst, const A4R4G4B4 *src)
+{
+ dst->alpha = gl::normalizedToFloat<4>(gl::getShiftedData<4, 12>(src->ARGB));
+ dst->red = gl::normalizedToFloat<4>(gl::getShiftedData<4, 8>(src->ARGB));
+ dst->green = gl::normalizedToFloat<4>(gl::getShiftedData<4, 4>(src->ARGB));
+ dst->blue = gl::normalizedToFloat<4>(gl::getShiftedData<4, 0>(src->ARGB));
+}
+
+void A4R4G4B4::writeColor(A4R4G4B4 *dst, const gl::ColorF *src)
+{
+ dst->ARGB = gl::shiftData<4, 12>(gl::floatToNormalized<4, uint16_t>(src->alpha)) |
+ gl::shiftData<4, 8>(gl::floatToNormalized<4, uint16_t>(src->red)) |
+ gl::shiftData<4, 4>(gl::floatToNormalized<4, uint16_t>(src->green)) |
+ gl::shiftData<4, 0>(gl::floatToNormalized<4, uint16_t>(src->blue));
+}
+
+void A4R4G4B4::average(A4R4G4B4 *dst, const A4R4G4B4 *src1, const A4R4G4B4 *src2)
+{
+ dst->ARGB = gl::shiftData<4, 12>(gl::average(gl::getShiftedData<4, 12>(src1->ARGB),
+ gl::getShiftedData<4, 12>(src2->ARGB))) |
+ gl::shiftData<4, 8>(gl::average(gl::getShiftedData<4, 8>(src1->ARGB),
+ gl::getShiftedData<4, 8>(src2->ARGB))) |
+ gl::shiftData<4, 4>(gl::average(gl::getShiftedData<4, 4>(src1->ARGB),
+ gl::getShiftedData<4, 4>(src2->ARGB))) |
+ gl::shiftData<4, 0>(gl::average(gl::getShiftedData<4, 0>(src1->ARGB),
+ gl::getShiftedData<4, 0>(src2->ARGB)));
+}
+
+void R16::readColor(gl::ColorUI *dst, const R16 *src)
+{
+ dst->red = src->R;
+ dst->green = 0;
+ dst->blue = 0;
+ dst->alpha = 1;
+}
+
+void R16::readColor(gl::ColorF *dst, const R16 *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = 0.0f;
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+}
+
+void R16::writeColor(R16 *dst, const gl::ColorUI *src)
+{
+ dst->R = static_cast<uint16_t>(src->red);
+}
+
+void R16::writeColor(R16 *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<uint16_t>(src->red);
+}
+
+void R16::average(R16 *dst, const R16 *src1, const R16 *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+}
+
+void R16G16::readColor(gl::ColorUI *dst, const R16G16 *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = 0;
+ dst->alpha = 1;
+}
+
+void R16G16::readColor(gl::ColorF *dst, const R16G16 *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+}
+
+void R16G16::writeColor(R16G16 *dst, const gl::ColorUI *src)
+{
+ dst->R = static_cast<uint16_t>(src->red);
+ dst->G = static_cast<uint16_t>(src->green);
+}
+
+void R16G16::writeColor(R16G16 *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<uint16_t>(src->red);
+ dst->G = gl::floatToNormalized<uint16_t>(src->green);
+}
+
+void R16G16::average(R16G16 *dst, const R16G16 *src1, const R16G16 *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+}
+
+void R16G16B16::readColor(gl::ColorUI *dst, const R16G16B16 *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = 1;
+}
+
+void R16G16B16::readColor(gl::ColorF *dst, const R16G16B16 *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = 1.0f;
+}
+
+void R16G16B16::writeColor(R16G16B16 *dst, const gl::ColorUI *src)
+{
+ dst->R = static_cast<uint16_t>(src->red);
+ dst->G = static_cast<uint16_t>(src->green);
+ dst->B = static_cast<uint16_t>(src->blue);
+}
+
+void R16G16B16::writeColor(R16G16B16 *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<uint16_t>(src->red);
+ dst->G = gl::floatToNormalized<uint16_t>(src->green);
+ dst->B = gl::floatToNormalized<uint16_t>(src->blue);
+}
+
+void R16G16B16::average(R16G16B16 *dst, const R16G16B16 *src1, const R16G16B16 *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+}
+
+void R16G16B16A16::readColor(gl::ColorUI *dst, const R16G16B16A16 *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = src->A;
+}
+
+void R16G16B16A16::readColor(gl::ColorF *dst, const R16G16B16A16 *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = gl::normalizedToFloat(src->A);
+}
+
+void R16G16B16A16::writeColor(R16G16B16A16 *dst, const gl::ColorUI *src)
+{
+ dst->R = static_cast<uint16_t>(src->red);
+ dst->G = static_cast<uint16_t>(src->green);
+ dst->B = static_cast<uint16_t>(src->blue);
+ dst->A = static_cast<uint16_t>(src->alpha);
+}
+
+void R16G16B16A16::writeColor(R16G16B16A16 *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<uint16_t>(src->red);
+ dst->G = gl::floatToNormalized<uint16_t>(src->green);
+ dst->B = gl::floatToNormalized<uint16_t>(src->blue);
+ dst->A = gl::floatToNormalized<uint16_t>(src->alpha);
+}
+
+void R16G16B16A16::average(R16G16B16A16 *dst, const R16G16B16A16 *src1, const R16G16B16A16 *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ dst->A = gl::average(src1->A, src2->A);
+}
+
+void R32::readColor(gl::ColorUI *dst, const R32 *src)
+{
+ dst->red = src->R;
+ dst->green = 0;
+ dst->blue = 0;
+ dst->alpha = 1;
+}
+
+void R32::readColor(gl::ColorF *dst, const R32 *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = 0.0f;
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+}
+
+void R32::writeColor(R32 *dst, const gl::ColorUI *src)
+{
+ dst->R = static_cast<uint32_t>(src->red);
+}
+
+void R32::writeColor(R32 *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<uint32_t>(src->red);
+}
+
+void R32::average(R32 *dst, const R32 *src1, const R32 *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+}
+
+void R32G32::readColor(gl::ColorUI *dst, const R32G32 *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = 0;
+ dst->alpha = 1;
+}
+
+void R32G32::readColor(gl::ColorF *dst, const R32G32 *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+}
+
+void R32G32::writeColor(R32G32 *dst, const gl::ColorUI *src)
+{
+ dst->R = static_cast<uint32_t>(src->red);
+ dst->G = static_cast<uint32_t>(src->green);
+}
+
+void R32G32::writeColor(R32G32 *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<uint32_t>(src->red);
+ dst->G = gl::floatToNormalized<uint32_t>(src->green);
+}
+
+void R32G32::average(R32G32 *dst, const R32G32 *src1, const R32G32 *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+}
+
+void R32G32B32::readColor(gl::ColorUI *dst, const R32G32B32 *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = 1;
+}
+
+void R32G32B32::readColor(gl::ColorF *dst, const R32G32B32 *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = 1.0f;
+}
+
+void R32G32B32::writeColor(R32G32B32 *dst, const gl::ColorUI *src)
+{
+ dst->R = static_cast<uint32_t>(src->red);
+ dst->G = static_cast<uint32_t>(src->green);
+ dst->B = static_cast<uint32_t>(src->blue);
+}
+
+void R32G32B32::writeColor(R32G32B32 *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<uint32_t>(src->red);
+ dst->G = gl::floatToNormalized<uint32_t>(src->green);
+ dst->B = gl::floatToNormalized<uint32_t>(src->blue);
+}
+
+void R32G32B32::average(R32G32B32 *dst, const R32G32B32 *src1, const R32G32B32 *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+}
+
+void R32G32B32A32::readColor(gl::ColorUI *dst, const R32G32B32A32 *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = src->A;
+}
+
+void R32G32B32A32::readColor(gl::ColorF *dst, const R32G32B32A32 *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = gl::normalizedToFloat(src->A);
+}
+
+void R32G32B32A32::writeColor(R32G32B32A32 *dst, const gl::ColorUI *src)
+{
+ dst->R = static_cast<uint32_t>(src->red);
+ dst->G = static_cast<uint32_t>(src->green);
+ dst->B = static_cast<uint32_t>(src->blue);
+ dst->A = static_cast<uint32_t>(src->alpha);
+}
+
+void R32G32B32A32::writeColor(R32G32B32A32 *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<uint32_t>(src->red);
+ dst->G = gl::floatToNormalized<uint32_t>(src->green);
+ dst->B = gl::floatToNormalized<uint32_t>(src->blue);
+ dst->A = gl::floatToNormalized<uint32_t>(src->alpha);
+}
+
+void R32G32B32A32::average(R32G32B32A32 *dst, const R32G32B32A32 *src1, const R32G32B32A32 *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ dst->A = gl::average(src1->A, src2->A);
+}
+
+void R8S::readColor(gl::ColorI *dst, const R8S *src)
+{
+ dst->red = src->R;
+ dst->green = 0;
+ dst->blue = 0;
+ dst->alpha = 1;
+}
+
+void R8S::readColor(gl::ColorF *dst, const R8S *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = 0.0f;
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+}
+
+void R8S::writeColor(R8S *dst, const gl::ColorI *src)
+{
+ dst->R = static_cast<int8_t>(src->red);
+}
+
+void R8S::writeColor(R8S *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<int8_t>(src->red);
+}
+
+void R8S::average(R8S *dst, const R8S *src1, const R8S *src2)
+{
+ dst->R = static_cast<int8_t>(gl::average(src1->R, src2->R));
+}
+
+void R8G8S::readColor(gl::ColorI *dst, const R8G8S *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = 0;
+ dst->alpha = 1;
+}
+
+void R8G8S::readColor(gl::ColorF *dst, const R8G8S *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+}
+
+void R8G8S::writeColor(R8G8S *dst, const gl::ColorI *src)
+{
+ dst->R = static_cast<int8_t>(src->red);
+ dst->G = static_cast<int8_t>(src->green);
+}
+
+void R8G8S::writeColor(R8G8S *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<int8_t>(src->red);
+ dst->G = gl::floatToNormalized<int8_t>(src->green);
+}
+
+void R8G8S::average(R8G8S *dst, const R8G8S *src1, const R8G8S *src2)
+{
+ dst->R = static_cast<int8_t>(gl::average(src1->R, src2->R));
+ dst->G = static_cast<int8_t>(gl::average(src1->G, src2->G));
+}
+
+void R8G8B8S::readColor(gl::ColorI *dst, const R8G8B8S *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = 1;
+}
+
+void R8G8B8S::readColor(gl::ColorF *dst, const R8G8B8S *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = 1.0f;
+}
+
+void R8G8B8S::writeColor(R8G8B8S *dst, const gl::ColorI *src)
+{
+ dst->R = static_cast<int8_t>(src->red);
+ dst->G = static_cast<int8_t>(src->green);
+ dst->B = static_cast<int8_t>(src->blue);
+}
+
+void R8G8B8S::writeColor(R8G8B8S *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<int8_t>(src->red);
+ dst->G = gl::floatToNormalized<int8_t>(src->green);
+ dst->B = gl::floatToNormalized<int8_t>(src->blue);
+}
+
+void R8G8B8S::average(R8G8B8S *dst, const R8G8B8S *src1, const R8G8B8S *src2)
+{
+ dst->R = static_cast<int8_t>(gl::average(src1->R, src2->R));
+ dst->G = static_cast<int8_t>(gl::average(src1->G, src2->G));
+ dst->B = static_cast<int8_t>(gl::average(src1->B, src2->B));
+}
+
+void R8G8B8A8S::readColor(gl::ColorI *dst, const R8G8B8A8S *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = src->A;
+}
+
+void R8G8B8A8S::readColor(gl::ColorF *dst, const R8G8B8A8S *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = gl::normalizedToFloat(src->A);
+}
+
+void R8G8B8A8S::writeColor(R8G8B8A8S *dst, const gl::ColorI *src)
+{
+ dst->R = static_cast<int8_t>(src->red);
+ dst->G = static_cast<int8_t>(src->green);
+ dst->B = static_cast<int8_t>(src->blue);
+ dst->A = static_cast<int8_t>(src->alpha);
+}
+
+void R8G8B8A8S::writeColor(R8G8B8A8S *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<int8_t>(src->red);
+ dst->G = gl::floatToNormalized<int8_t>(src->green);
+ dst->B = gl::floatToNormalized<int8_t>(src->blue);
+ dst->A = gl::floatToNormalized<int8_t>(src->alpha);
+}
+
+void R8G8B8A8S::average(R8G8B8A8S *dst, const R8G8B8A8S *src1, const R8G8B8A8S *src2)
+{
+ dst->R = static_cast<int8_t>(gl::average(src1->R, src2->R));
+ dst->G = static_cast<int8_t>(gl::average(src1->G, src2->G));
+ dst->B = static_cast<int8_t>(gl::average(src1->B, src2->B));
+ dst->A = static_cast<int8_t>(gl::average(src1->A, src2->A));
+}
+
+void R16S::readColor(gl::ColorI *dst, const R16S *src)
+{
+ dst->red = src->R;
+ dst->green = 0;
+ dst->blue = 0;
+ dst->alpha = 1;
+}
+
+void R16S::readColor(gl::ColorF *dst, const R16S *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = 0.0f;
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+}
+
+void R16S::writeColor(R16S *dst, const gl::ColorI *src)
+{
+ dst->R = static_cast<int16_t>(src->red);
+}
+
+void R16S::writeColor(R16S *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<int16_t>(src->red);
+}
+
+void R16S::average(R16S *dst, const R16S *src1, const R16S *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+}
+
+void R16G16S::readColor(gl::ColorI *dst, const R16G16S *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = 0;
+ dst->alpha = 1;
+}
+
+void R16G16S::readColor(gl::ColorF *dst, const R16G16S *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+}
+
+void R16G16S::writeColor(R16G16S *dst, const gl::ColorI *src)
+{
+ dst->R = static_cast<int16_t>(src->red);
+ dst->G = static_cast<int16_t>(src->green);
+}
+
+void R16G16S::writeColor(R16G16S *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<int16_t>(src->red);
+ dst->G = gl::floatToNormalized<int16_t>(src->green);
+}
+
+void R16G16S::average(R16G16S *dst, const R16G16S *src1, const R16G16S *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+}
+
+void R16G16B16S::readColor(gl::ColorI *dst, const R16G16B16S *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = 1;
+}
+
+void R16G16B16S::readColor(gl::ColorF *dst, const R16G16B16S *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = 1.0f;
+}
+
+void R16G16B16S::writeColor(R16G16B16S *dst, const gl::ColorI *src)
+{
+ dst->R = static_cast<int16_t>(src->red);
+ dst->G = static_cast<int16_t>(src->green);
+ dst->B = static_cast<int16_t>(src->blue);
+}
+
+void R16G16B16S::writeColor(R16G16B16S *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<int16_t>(src->red);
+ dst->G = gl::floatToNormalized<int16_t>(src->green);
+ dst->B = gl::floatToNormalized<int16_t>(src->blue);
+}
+
+void R16G16B16S::average(R16G16B16S *dst, const R16G16B16S *src1, const R16G16B16S *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+}
+
+void R16G16B16A16S::readColor(gl::ColorI *dst, const R16G16B16A16S *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = src->A;
+}
+
+void R16G16B16A16S::readColor(gl::ColorF *dst, const R16G16B16A16S *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = gl::normalizedToFloat(src->A);
+}
+
+void R16G16B16A16S::writeColor(R16G16B16A16S *dst, const gl::ColorI *src)
+{
+ dst->R = static_cast<int16_t>(src->red);
+ dst->G = static_cast<int16_t>(src->green);
+ dst->B = static_cast<int16_t>(src->blue);
+ dst->A = static_cast<int16_t>(src->alpha);
+}
+
+void R16G16B16A16S::writeColor(R16G16B16A16S *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<int16_t>(src->red);
+ dst->G = gl::floatToNormalized<int16_t>(src->green);
+ dst->B = gl::floatToNormalized<int16_t>(src->blue);
+ dst->A = gl::floatToNormalized<int16_t>(src->alpha);
+}
+
+void R16G16B16A16S::average(R16G16B16A16S *dst,
+ const R16G16B16A16S *src1,
+ const R16G16B16A16S *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ dst->A = gl::average(src1->A, src2->A);
+}
+
+void R32S::readColor(gl::ColorI *dst, const R32S *src)
+{
+ dst->red = src->R;
+ dst->green = 0;
+ dst->blue = 0;
+ dst->alpha = 1;
+}
+
+void R32S::readColor(gl::ColorF *dst, const R32S *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = 0.0f;
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+}
+
+void R32S::writeColor(R32S *dst, const gl::ColorI *src)
+{
+ dst->R = static_cast<int32_t>(src->red);
+}
+
+void R32S::writeColor(R32S *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<int32_t>(src->red);
+}
+
+void R32S::average(R32S *dst, const R32S *src1, const R32S *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+}
+
+void R32G32S::readColor(gl::ColorI *dst, const R32G32S *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = 0;
+ dst->alpha = 1;
+}
+
+void R32G32S::readColor(gl::ColorF *dst, const R32G32S *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+}
+
+void R32G32S::writeColor(R32G32S *dst, const gl::ColorI *src)
+{
+ dst->R = static_cast<int32_t>(src->red);
+ dst->G = static_cast<int32_t>(src->green);
+}
+
+void R32G32S::writeColor(R32G32S *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<int32_t>(src->red);
+ dst->G = gl::floatToNormalized<int32_t>(src->green);
+}
+
+void R32G32S::average(R32G32S *dst, const R32G32S *src1, const R32G32S *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+}
+
+void R32G32B32S::readColor(gl::ColorI *dst, const R32G32B32S *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = 1;
+}
+
+void R32G32B32S::readColor(gl::ColorF *dst, const R32G32B32S *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = 1.0f;
+}
+
+void R32G32B32S::writeColor(R32G32B32S *dst, const gl::ColorI *src)
+{
+ dst->R = static_cast<int32_t>(src->red);
+ dst->G = static_cast<int32_t>(src->green);
+ dst->B = static_cast<int32_t>(src->blue);
+}
+
+void R32G32B32S::writeColor(R32G32B32S *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<int32_t>(src->red);
+ dst->G = gl::floatToNormalized<int32_t>(src->green);
+ dst->B = gl::floatToNormalized<int32_t>(src->blue);
+}
+
+void R32G32B32S::average(R32G32B32S *dst, const R32G32B32S *src1, const R32G32B32S *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+}
+
+void R32G32B32A32S::readColor(gl::ColorI *dst, const R32G32B32A32S *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = src->A;
+}
+
+void R32G32B32A32S::readColor(gl::ColorF *dst, const R32G32B32A32S *src)
+{
+ dst->red = gl::normalizedToFloat(src->R);
+ dst->green = gl::normalizedToFloat(src->G);
+ dst->blue = gl::normalizedToFloat(src->B);
+ dst->alpha = gl::normalizedToFloat(src->A);
+}
+
+void R32G32B32A32S::writeColor(R32G32B32A32S *dst, const gl::ColorI *src)
+{
+ dst->R = static_cast<int32_t>(src->red);
+ dst->G = static_cast<int32_t>(src->green);
+ dst->B = static_cast<int32_t>(src->blue);
+ dst->A = static_cast<int32_t>(src->alpha);
+}
+
+void R32G32B32A32S::writeColor(R32G32B32A32S *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<int32_t>(src->red);
+ dst->G = gl::floatToNormalized<int32_t>(src->green);
+ dst->B = gl::floatToNormalized<int32_t>(src->blue);
+ dst->A = gl::floatToNormalized<int32_t>(src->alpha);
+}
+
+void R32G32B32A32S::average(R32G32B32A32S *dst,
+ const R32G32B32A32S *src1,
+ const R32G32B32A32S *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ dst->A = gl::average(src1->A, src2->A);
+}
+
+void A16B16G16R16F::readColor(gl::ColorF *dst, const A16B16G16R16F *src)
+{
+ dst->red = gl::float16ToFloat32(src->R);
+ dst->green = gl::float16ToFloat32(src->G);
+ dst->blue = gl::float16ToFloat32(src->B);
+ dst->alpha = gl::float16ToFloat32(src->A);
+}
+
+void A16B16G16R16F::writeColor(A16B16G16R16F *dst, const gl::ColorF *src)
+{
+ dst->R = gl::float32ToFloat16(src->red);
+ dst->G = gl::float32ToFloat16(src->green);
+ dst->B = gl::float32ToFloat16(src->blue);
+ dst->A = gl::float32ToFloat16(src->alpha);
+}
+
+void A16B16G16R16F::average(A16B16G16R16F *dst,
+ const A16B16G16R16F *src1,
+ const A16B16G16R16F *src2)
+{
+ dst->R = gl::averageHalfFloat(src1->R, src2->R);
+ dst->G = gl::averageHalfFloat(src1->G, src2->G);
+ dst->B = gl::averageHalfFloat(src1->B, src2->B);
+ dst->A = gl::averageHalfFloat(src1->A, src2->A);
+}
+
+void R16G16B16A16F::readColor(gl::ColorF *dst, const R16G16B16A16F *src)
+{
+ dst->red = gl::float16ToFloat32(src->R);
+ dst->green = gl::float16ToFloat32(src->G);
+ dst->blue = gl::float16ToFloat32(src->B);
+ dst->alpha = gl::float16ToFloat32(src->A);
+}
+
+void R16G16B16A16F::writeColor(R16G16B16A16F *dst, const gl::ColorF *src)
+{
+ dst->R = gl::float32ToFloat16(src->red);
+ dst->G = gl::float32ToFloat16(src->green);
+ dst->B = gl::float32ToFloat16(src->blue);
+ dst->A = gl::float32ToFloat16(src->alpha);
+}
+
+void R16G16B16A16F::average(R16G16B16A16F *dst,
+ const R16G16B16A16F *src1,
+ const R16G16B16A16F *src2)
+{
+ dst->R = gl::averageHalfFloat(src1->R, src2->R);
+ dst->G = gl::averageHalfFloat(src1->G, src2->G);
+ dst->B = gl::averageHalfFloat(src1->B, src2->B);
+ dst->A = gl::averageHalfFloat(src1->A, src2->A);
+}
+
+void R16F::readColor(gl::ColorF *dst, const R16F *src)
+{
+ dst->red = gl::float16ToFloat32(src->R);
+ dst->green = 0.0f;
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+}
+
+void R16F::writeColor(R16F *dst, const gl::ColorF *src)
+{
+ dst->R = gl::float32ToFloat16(src->red);
+}
+
+void R16F::average(R16F *dst, const R16F *src1, const R16F *src2)
+{
+ dst->R = gl::averageHalfFloat(src1->R, src2->R);
+}
+
+void A16F::readColor(gl::ColorF *dst, const A16F *src)
+{
+ dst->red = 0.0f;
+ dst->green = 0.0f;
+ dst->blue = 0.0f;
+ dst->alpha = gl::float16ToFloat32(src->A);
+}
+
+void A16F::writeColor(A16F *dst, const gl::ColorF *src)
+{
+ dst->A = gl::float32ToFloat16(src->alpha);
+}
+
+void A16F::average(A16F *dst, const A16F *src1, const A16F *src2)
+{
+ dst->A = gl::averageHalfFloat(src1->A, src2->A);
+}
+
+void L16F::readColor(gl::ColorF *dst, const L16F *src)
+{
+ float lum = gl::float16ToFloat32(src->L);
+ dst->red = lum;
+ dst->green = lum;
+ dst->blue = lum;
+ dst->alpha = 1.0f;
+}
+
+void L16F::writeColor(L16F *dst, const gl::ColorF *src)
+{
+ dst->L = gl::float32ToFloat16(src->red);
+}
+
+void L16F::average(L16F *dst, const L16F *src1, const L16F *src2)
+{
+ dst->L = gl::averageHalfFloat(src1->L, src2->L);
+}
+
+void L16A16F::readColor(gl::ColorF *dst, const L16A16F *src)
+{
+ float lum = gl::float16ToFloat32(src->L);
+ dst->red = lum;
+ dst->green = lum;
+ dst->blue = lum;
+ dst->alpha = gl::float16ToFloat32(src->A);
+}
+
+void L16A16F::writeColor(L16A16F *dst, const gl::ColorF *src)
+{
+ dst->L = gl::float32ToFloat16(src->red);
+ dst->A = gl::float32ToFloat16(src->alpha);
+}
+
+void L16A16F::average(L16A16F *dst, const L16A16F *src1, const L16A16F *src2)
+{
+ dst->L = gl::averageHalfFloat(src1->L, src2->L);
+ dst->A = gl::averageHalfFloat(src1->A, src2->A);
+}
+
+void R16G16F::readColor(gl::ColorF *dst, const R16G16F *src)
+{
+ dst->red = gl::float16ToFloat32(src->R);
+ dst->green = gl::float16ToFloat32(src->G);
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+}
+
+void R16G16F::writeColor(R16G16F *dst, const gl::ColorF *src)
+{
+ dst->R = gl::float32ToFloat16(src->red);
+ dst->G = gl::float32ToFloat16(src->green);
+}
+
+void R16G16F::average(R16G16F *dst, const R16G16F *src1, const R16G16F *src2)
+{
+ dst->R = gl::averageHalfFloat(src1->R, src2->R);
+ dst->G = gl::averageHalfFloat(src1->G, src2->G);
+}
+
+void R16G16B16F::readColor(gl::ColorF *dst, const R16G16B16F *src)
+{
+ dst->red = gl::float16ToFloat32(src->R);
+ dst->green = gl::float16ToFloat32(src->G);
+ dst->blue = gl::float16ToFloat32(src->B);
+ dst->alpha = 1.0f;
+}
+
+void R16G16B16F::writeColor(R16G16B16F *dst, const gl::ColorF *src)
+{
+ dst->R = gl::float32ToFloat16(src->red);
+ dst->G = gl::float32ToFloat16(src->green);
+ dst->B = gl::float32ToFloat16(src->blue);
+}
+
+void R16G16B16F::average(R16G16B16F *dst, const R16G16B16F *src1, const R16G16B16F *src2)
+{
+ dst->R = gl::averageHalfFloat(src1->R, src2->R);
+ dst->G = gl::averageHalfFloat(src1->G, src2->G);
+ dst->B = gl::averageHalfFloat(src1->B, src2->B);
+}
+
+void A32B32G32R32F::readColor(gl::ColorF *dst, const A32B32G32R32F *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = src->A;
+}
+
+void A32B32G32R32F::writeColor(A32B32G32R32F *dst, const gl::ColorF *src)
+{
+ dst->R = src->red;
+ dst->G = src->green;
+ dst->B = src->blue;
+ dst->A = src->alpha;
+}
+
+void A32B32G32R32F::average(A32B32G32R32F *dst,
+ const A32B32G32R32F *src1,
+ const A32B32G32R32F *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ dst->A = gl::average(src1->A, src2->A);
+}
+
+void R32G32B32A32F::readColor(gl::ColorF *dst, const R32G32B32A32F *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = src->A;
+}
+
+void R32G32B32A32F::writeColor(R32G32B32A32F *dst, const gl::ColorF *src)
+{
+ dst->R = src->red;
+ dst->G = src->green;
+ dst->B = src->blue;
+ dst->A = src->alpha;
+}
+
+void R32G32B32A32F::average(R32G32B32A32F *dst,
+ const R32G32B32A32F *src1,
+ const R32G32B32A32F *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ dst->A = gl::average(src1->A, src2->A);
+}
+
+void R32F::readColor(gl::ColorF *dst, const R32F *src)
+{
+ dst->red = src->R;
+ dst->green = 0.0f;
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+}
+
+void R32F::writeColor(R32F *dst, const gl::ColorF *src)
+{
+ dst->R = src->red;
+}
+
+void R32F::average(R32F *dst, const R32F *src1, const R32F *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+}
+
+void A32F::readColor(gl::ColorF *dst, const A32F *src)
+{
+ dst->red = 0.0f;
+ dst->green = 0.0f;
+ dst->blue = 0.0f;
+ dst->alpha = src->A;
+}
+
+void A32F::writeColor(A32F *dst, const gl::ColorF *src)
+{
+ dst->A = src->alpha;
+}
+
+void A32F::average(A32F *dst, const A32F *src1, const A32F *src2)
+{
+ dst->A = gl::average(src1->A, src2->A);
+}
+
+void L32F::readColor(gl::ColorF *dst, const L32F *src)
+{
+ dst->red = src->L;
+ dst->green = src->L;
+ dst->blue = src->L;
+ dst->alpha = 1.0f;
+}
+
+void L32F::writeColor(L32F *dst, const gl::ColorF *src)
+{
+ dst->L = src->red;
+}
+
+void L32F::average(L32F *dst, const L32F *src1, const L32F *src2)
+{
+ dst->L = gl::average(src1->L, src2->L);
+}
+
+void L32A32F::readColor(gl::ColorF *dst, const L32A32F *src)
+{
+ dst->red = src->L;
+ dst->green = src->L;
+ dst->blue = src->L;
+ dst->alpha = src->A;
+}
+
+void L32A32F::writeColor(L32A32F *dst, const gl::ColorF *src)
+{
+ dst->L = src->red;
+ dst->A = src->alpha;
+}
+
+void L32A32F::average(L32A32F *dst, const L32A32F *src1, const L32A32F *src2)
+{
+ dst->L = gl::average(src1->L, src2->L);
+ dst->A = gl::average(src1->A, src2->A);
+}
+
+void R32G32F::readColor(gl::ColorF *dst, const R32G32F *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = 0.0f;
+ dst->alpha = 1.0f;
+}
+
+void R32G32F::writeColor(R32G32F *dst, const gl::ColorF *src)
+{
+ dst->R = src->red;
+ dst->G = src->green;
+}
+
+void R32G32F::average(R32G32F *dst, const R32G32F *src1, const R32G32F *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+}
+
+void R32G32B32F::readColor(gl::ColorF *dst, const R32G32B32F *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = 1.0f;
+}
+
+void R32G32B32F::writeColor(R32G32B32F *dst, const gl::ColorF *src)
+{
+ dst->R = src->red;
+ dst->G = src->green;
+ dst->B = src->blue;
+}
+
+void R32G32B32F::average(R32G32B32F *dst, const R32G32B32F *src1, const R32G32B32F *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+}
+
+void R10G10B10A2::readColor(gl::ColorUI *dst, const R10G10B10A2 *src)
+{
+ dst->red = src->R;
+ dst->green = src->G;
+ dst->blue = src->B;
+ dst->alpha = src->A;
+}
+
+void R10G10B10A2::readColor(gl::ColorF *dst, const R10G10B10A2 *src)
+{
+ dst->red = gl::normalizedToFloat<10>(src->R);
+ dst->green = gl::normalizedToFloat<10>(src->G);
+ dst->blue = gl::normalizedToFloat<10>(src->B);
+ dst->alpha = gl::normalizedToFloat<2>(src->A);
+}
+
+void R10G10B10A2::writeColor(R10G10B10A2 *dst, const gl::ColorUI *src)
+{
+ dst->R = static_cast<uint32_t>(src->red);
+ dst->G = static_cast<uint32_t>(src->green);
+ dst->B = static_cast<uint32_t>(src->blue);
+ dst->A = static_cast<uint32_t>(src->alpha);
+}
+
+void R10G10B10A2::writeColor(R10G10B10A2 *dst, const gl::ColorF *src)
+{
+ dst->R = gl::floatToNormalized<10, uint32_t>(src->red);
+ dst->G = gl::floatToNormalized<10, uint32_t>(src->green);
+ dst->B = gl::floatToNormalized<10, uint32_t>(src->blue);
+ dst->A = gl::floatToNormalized<2, uint32_t>(src->alpha);
+}
+
+void R10G10B10A2::average(R10G10B10A2 *dst, const R10G10B10A2 *src1, const R10G10B10A2 *src2)
+{
+ dst->R = gl::average(src1->R, src2->R);
+ dst->G = gl::average(src1->G, src2->G);
+ dst->B = gl::average(src1->B, src2->B);
+ dst->A = gl::average(src1->A, src2->A);
+}
+
+void R9G9B9E5::readColor(gl::ColorF *dst, const R9G9B9E5 *src)
+{
+ gl::convert999E5toRGBFloats(gl::bitCast<uint32_t>(*src), &dst->red, &dst->green, &dst->blue);
+ dst->alpha = 1.0f;
+}
+
+void R9G9B9E5::writeColor(R9G9B9E5 *dst, const gl::ColorF *src)
+{
+ *reinterpret_cast<uint32_t *>(dst) =
+ gl::convertRGBFloatsTo999E5(src->red, src->green, src->blue);
+}
+
+void R9G9B9E5::average(R9G9B9E5 *dst, const R9G9B9E5 *src1, const R9G9B9E5 *src2)
+{
+ float r1, g1, b1;
+ gl::convert999E5toRGBFloats(*reinterpret_cast<const uint32_t *>(src1), &r1, &g1, &b1);
+
+ float r2, g2, b2;
+ gl::convert999E5toRGBFloats(*reinterpret_cast<const uint32_t *>(src2), &r2, &g2, &b2);
+
+ *reinterpret_cast<uint32_t *>(dst) =
+ gl::convertRGBFloatsTo999E5(gl::average(r1, r2), gl::average(g1, g2), gl::average(b1, b2));
+}
+
+void R11G11B10F::readColor(gl::ColorF *dst, const R11G11B10F *src)
+{
+ dst->red = gl::float11ToFloat32(src->R);
+ dst->green = gl::float11ToFloat32(src->G);
+ dst->blue = gl::float10ToFloat32(src->B);
+ dst->alpha = 1.0f;
+}
+
+void R11G11B10F::writeColor(R11G11B10F *dst, const gl::ColorF *src)
+{
+ dst->R = gl::float32ToFloat11(src->red);
+ dst->G = gl::float32ToFloat11(src->green);
+ dst->B = gl::float32ToFloat10(src->blue);
+}
+
+void R11G11B10F::average(R11G11B10F *dst, const R11G11B10F *src1, const R11G11B10F *src2)
+{
+ dst->R = gl::averageFloat11(src1->R, src2->R);
+ dst->G = gl::averageFloat11(src1->G, src2->G);
+ dst->B = gl::averageFloat10(src1->B, src2->B);
+}
+
+} // namespace angle
diff --git a/src/3rdparty/angle/src/image_util/imageformats.h b/src/3rdparty/angle/src/image_util/imageformats.h
new file mode 100644
index 0000000000..65644cd8d9
--- /dev/null
+++ b/src/3rdparty/angle/src/image_util/imageformats.h
@@ -0,0 +1,700 @@
+//
+// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// imageformats.h: Defines image format types with functions for mip generation
+// and copying.
+
+#ifndef IMAGEUTIL_IMAGEFORMATS_H_
+#define IMAGEUTIL_IMAGEFORMATS_H_
+
+#include "common/Color.h"
+
+#include <cstdint>
+
+namespace angle
+{
+
+// Several structures share functionality for reading, writing or mipmapping but the layout
+// must match the texture format which the structure represents. If collapsing or typedefing
+// structs in this header, make sure the functionality and memory layout is exactly the same.
+
+struct L8
+{
+ uint8_t L;
+
+ static void readColor(gl::ColorF *dst, const L8 *src);
+ static void writeColor(L8 *dst, const gl::ColorF *src);
+ static void average(L8 *dst, const L8 *src1, const L8 *src2);
+};
+
+struct R8
+{
+ uint8_t R;
+
+ static void readColor(gl::ColorF *dst, const R8 *src);
+ static void readColor(gl::ColorUI *dst, const R8 *src);
+ static void writeColor(R8 *dst, const gl::ColorF *src);
+ static void writeColor(R8 *dst, const gl::ColorUI *src);
+ static void average(R8 *dst, const R8 *src1, const R8 *src2);
+};
+
+struct A8
+{
+ uint8_t A;
+
+ static void readColor(gl::ColorF *dst, const A8 *src);
+ static void writeColor(A8 *dst, const gl::ColorF *src);
+ static void average(A8 *dst, const A8 *src1, const A8 *src2);
+};
+
+struct L8A8
+{
+ uint8_t L;
+ uint8_t A;
+
+ static void readColor(gl::ColorF *dst, const L8A8 *src);
+ static void writeColor(L8A8 *dst, const gl::ColorF *src);
+ static void average(L8A8 *dst, const L8A8 *src1, const L8A8 *src2);
+};
+
+struct A8L8
+{
+ uint8_t A;
+ uint8_t L;
+
+ static void readColor(gl::ColorF *dst, const A8L8 *src);
+ static void writeColor(A8L8 *dst, const gl::ColorF *src);
+ static void average(A8L8 *dst, const A8L8 *src1, const A8L8 *src2);
+};
+
+struct R8G8
+{
+ uint8_t R;
+ uint8_t G;
+
+ static void readColor(gl::ColorF *dst, const R8G8 *src);
+ static void readColor(gl::ColorUI *dst, const R8G8 *src);
+ static void writeColor(R8G8 *dst, const gl::ColorF *src);
+ static void writeColor(R8G8 *dst, const gl::ColorUI *src);
+ static void average(R8G8 *dst, const R8G8 *src1, const R8G8 *src2);
+};
+
+struct R8G8B8
+{
+ uint8_t R;
+ uint8_t G;
+ uint8_t B;
+
+ static void readColor(gl::ColorF *dst, const R8G8B8 *src);
+ static void readColor(gl::ColorUI *dst, const R8G8B8 *src);
+ static void writeColor(R8G8B8 *dst, const gl::ColorF *src);
+ static void writeColor(R8G8B8 *dst, const gl::ColorUI *src);
+ static void average(R8G8B8 *dst, const R8G8B8 *src1, const R8G8B8 *src2);
+};
+
+struct B8G8R8
+{
+ uint8_t B;
+ uint8_t G;
+ uint8_t R;
+
+ static void readColor(gl::ColorF *dst, const B8G8R8 *src);
+ static void readColor(gl::ColorUI *dst, const B8G8R8 *src);
+ static void writeColor(B8G8R8 *dst, const gl::ColorF *src);
+ static void writeColor(B8G8R8 *dst, const gl::ColorUI *src);
+ static void average(B8G8R8 *dst, const B8G8R8 *src1, const B8G8R8 *src2);
+};
+
+struct R5G6B5
+{
+ // OpenGL ES 2.0.25 spec Section 3.6.2: "Components are packed with the first component in the
+ // most significant bits of the bitfield, and successive component occupying progressively less
+ // significant locations"
+ uint16_t RGB;
+
+ static void readColor(gl::ColorF *dst, const R5G6B5 *src);
+ static void writeColor(R5G6B5 *dst, const gl::ColorF *src);
+ static void average(R5G6B5 *dst, const R5G6B5 *src1, const R5G6B5 *src2);
+};
+
+struct B5G6R5
+{
+ uint16_t BGR;
+
+ static void readColor(gl::ColorF *dst, const B5G6R5 *src);
+ static void writeColor(B5G6R5 *dst, const gl::ColorF *src);
+ static void average(B5G6R5 *dst, const B5G6R5 *src1, const B5G6R5 *src2);
+};
+
+struct A8R8G8B8
+{
+ uint8_t A;
+ uint8_t R;
+ uint8_t G;
+ uint8_t B;
+
+ static void readColor(gl::ColorF *dst, const A8R8G8B8 *src);
+ static void readColor(gl::ColorUI *dst, const A8R8G8B8 *src);
+ static void writeColor(A8R8G8B8 *dst, const gl::ColorF *src);
+ static void writeColor(A8R8G8B8 *dst, const gl::ColorUI *src);
+ static void average(A8R8G8B8 *dst, const A8R8G8B8 *src1, const A8R8G8B8 *src2);
+};
+
+struct R8G8B8A8
+{
+ uint8_t R;
+ uint8_t G;
+ uint8_t B;
+ uint8_t A;
+
+ static void readColor(gl::ColorF *dst, const R8G8B8A8 *src);
+ static void readColor(gl::ColorUI *dst, const R8G8B8A8 *src);
+ static void writeColor(R8G8B8A8 *dst, const gl::ColorF *src);
+ static void writeColor(R8G8B8A8 *dst, const gl::ColorUI *src);
+ static void average(R8G8B8A8 *dst, const R8G8B8A8 *src1, const R8G8B8A8 *src2);
+};
+
+struct R8G8B8A8SRGB
+{
+ uint8_t R;
+ uint8_t G;
+ uint8_t B;
+ uint8_t A;
+
+ static void readColor(gl::ColorF *dst, const R8G8B8A8SRGB *src);
+ static void writeColor(R8G8B8A8SRGB *dst, const gl::ColorF *src);
+ static void average(R8G8B8A8SRGB *dst, const R8G8B8A8SRGB *src1, const R8G8B8A8SRGB *src2);
+};
+
+struct B8G8R8A8
+{
+ uint8_t B;
+ uint8_t G;
+ uint8_t R;
+ uint8_t A;
+
+ static void readColor(gl::ColorF *dst, const B8G8R8A8 *src);
+ static void readColor(gl::ColorUI *dst, const B8G8R8A8 *src);
+ static void writeColor(B8G8R8A8 *dst, const gl::ColorF *src);
+ static void writeColor(B8G8R8A8 *dst, const gl::ColorUI *src);
+ static void average(B8G8R8A8 *dst, const B8G8R8A8 *src1, const B8G8R8A8 *src2);
+};
+
+struct B8G8R8X8
+{
+ uint8_t B;
+ uint8_t G;
+ uint8_t R;
+ uint8_t X;
+
+ static void readColor(gl::ColorF *dst, const B8G8R8X8 *src);
+ static void readColor(gl::ColorUI *dst, const B8G8R8X8 *src);
+ static void writeColor(B8G8R8X8 *dst, const gl::ColorF *src);
+ static void writeColor(B8G8R8X8 *dst, const gl::ColorUI *src);
+ static void average(B8G8R8X8 *dst, const B8G8R8X8 *src1, const B8G8R8X8 *src2);
+};
+
+struct A1R5G5B5
+{
+ uint16_t ARGB;
+
+ static void readColor(gl::ColorF *dst, const A1R5G5B5 *src);
+ static void writeColor(A1R5G5B5 *dst, const gl::ColorF *src);
+ static void average(A1R5G5B5 *dst, const A1R5G5B5 *src1, const A1R5G5B5 *src2);
+};
+
+struct R5G5B5A1
+{
+ // OpenGL ES 2.0.25 spec Section 3.6.2: "Components are packed with the first component in the
+ // most significant
+ // bits of the bitfield, and successive component occupying progressively less significant
+ // locations"
+ uint16_t RGBA;
+
+ static void readColor(gl::ColorF *dst, const R5G5B5A1 *src);
+ static void writeColor(R5G5B5A1 *dst, const gl::ColorF *src);
+ static void average(R5G5B5A1 *dst, const R5G5B5A1 *src1, const R5G5B5A1 *src2);
+};
+
+struct R4G4B4A4
+{
+ // OpenGL ES 2.0.25 spec Section 3.6.2: "Components are packed with the first component in the
+ // most significant
+ // bits of the bitfield, and successive component occupying progressively less significant
+ // locations"
+ uint16_t RGBA;
+
+ static void readColor(gl::ColorF *dst, const R4G4B4A4 *src);
+ static void writeColor(R4G4B4A4 *dst, const gl::ColorF *src);
+ static void average(R4G4B4A4 *dst, const R4G4B4A4 *src1, const R4G4B4A4 *src2);
+};
+
+struct A4R4G4B4
+{
+ uint16_t ARGB;
+
+ static void readColor(gl::ColorF *dst, const A4R4G4B4 *src);
+ static void writeColor(A4R4G4B4 *dst, const gl::ColorF *src);
+ static void average(A4R4G4B4 *dst, const A4R4G4B4 *src1, const A4R4G4B4 *src2);
+};
+
+struct R16
+{
+ uint16_t R;
+
+ static void readColor(gl::ColorF *dst, const R16 *src);
+ static void readColor(gl::ColorUI *dst, const R16 *src);
+ static void writeColor(R16 *dst, const gl::ColorF *src);
+ static void writeColor(R16 *dst, const gl::ColorUI *src);
+ static void average(R16 *dst, const R16 *src1, const R16 *src2);
+};
+
+struct R16G16
+{
+ uint16_t R;
+ uint16_t G;
+
+ static void readColor(gl::ColorF *dst, const R16G16 *src);
+ static void readColor(gl::ColorUI *dst, const R16G16 *src);
+ static void writeColor(R16G16 *dst, const gl::ColorF *src);
+ static void writeColor(R16G16 *dst, const gl::ColorUI *src);
+ static void average(R16G16 *dst, const R16G16 *src1, const R16G16 *src2);
+};
+
+struct R16G16B16
+{
+ uint16_t R;
+ uint16_t G;
+ uint16_t B;
+
+ static void readColor(gl::ColorF *dst, const R16G16B16 *src);
+ static void readColor(gl::ColorUI *dst, const R16G16B16 *src);
+ static void writeColor(R16G16B16 *dst, const gl::ColorF *src);
+ static void writeColor(R16G16B16 *dst, const gl::ColorUI *src);
+ static void average(R16G16B16 *dst, const R16G16B16 *src1, const R16G16B16 *src2);
+};
+
+struct R16G16B16A16
+{
+ uint16_t R;
+ uint16_t G;
+ uint16_t B;
+ uint16_t A;
+
+ static void readColor(gl::ColorF *dst, const R16G16B16A16 *src);
+ static void readColor(gl::ColorUI *dst, const R16G16B16A16 *src);
+ static void writeColor(R16G16B16A16 *dst, const gl::ColorF *src);
+ static void writeColor(R16G16B16A16 *dst, const gl::ColorUI *src);
+ static void average(R16G16B16A16 *dst, const R16G16B16A16 *src1, const R16G16B16A16 *src2);
+};
+
+struct R32
+{
+ uint32_t R;
+
+ static void readColor(gl::ColorF *dst, const R32 *src);
+ static void readColor(gl::ColorUI *dst, const R32 *src);
+ static void writeColor(R32 *dst, const gl::ColorF *src);
+ static void writeColor(R32 *dst, const gl::ColorUI *src);
+ static void average(R32 *dst, const R32 *src1, const R32 *src2);
+};
+
+struct R32G32
+{
+ uint32_t R;
+ uint32_t G;
+
+ static void readColor(gl::ColorF *dst, const R32G32 *src);
+ static void readColor(gl::ColorUI *dst, const R32G32 *src);
+ static void writeColor(R32G32 *dst, const gl::ColorF *src);
+ static void writeColor(R32G32 *dst, const gl::ColorUI *src);
+ static void average(R32G32 *dst, const R32G32 *src1, const R32G32 *src2);
+};
+
+struct R32G32B32
+{
+ uint32_t R;
+ uint32_t G;
+ uint32_t B;
+
+ static void readColor(gl::ColorF *dst, const R32G32B32 *src);
+ static void readColor(gl::ColorUI *dst, const R32G32B32 *src);
+ static void writeColor(R32G32B32 *dst, const gl::ColorF *src);
+ static void writeColor(R32G32B32 *dst, const gl::ColorUI *src);
+ static void average(R32G32B32 *dst, const R32G32B32 *src1, const R32G32B32 *src2);
+};
+
+struct R32G32B32A32
+{
+ uint32_t R;
+ uint32_t G;
+ uint32_t B;
+ uint32_t A;
+
+ static void readColor(gl::ColorF *dst, const R32G32B32A32 *src);
+ static void readColor(gl::ColorUI *dst, const R32G32B32A32 *src);
+ static void writeColor(R32G32B32A32 *dst, const gl::ColorF *src);
+ static void writeColor(R32G32B32A32 *dst, const gl::ColorUI *src);
+ static void average(R32G32B32A32 *dst, const R32G32B32A32 *src1, const R32G32B32A32 *src2);
+};
+
+struct R8S
+{
+ int8_t R;
+
+ static void readColor(gl::ColorF *dst, const R8S *src);
+ static void readColor(gl::ColorI *dst, const R8S *src);
+ static void writeColor(R8S *dst, const gl::ColorF *src);
+ static void writeColor(R8S *dst, const gl::ColorI *src);
+ static void average(R8S *dst, const R8S *src1, const R8S *src2);
+};
+
+struct R8G8S
+{
+ int8_t R;
+ int8_t G;
+
+ static void readColor(gl::ColorF *dst, const R8G8S *src);
+ static void readColor(gl::ColorI *dst, const R8G8S *src);
+ static void writeColor(R8G8S *dst, const gl::ColorF *src);
+ static void writeColor(R8G8S *dst, const gl::ColorI *src);
+ static void average(R8G8S *dst, const R8G8S *src1, const R8G8S *src2);
+};
+
+struct R8G8B8S
+{
+ int8_t R;
+ int8_t G;
+ int8_t B;
+
+ static void readColor(gl::ColorF *dst, const R8G8B8S *src);
+ static void readColor(gl::ColorI *dst, const R8G8B8S *src);
+ static void writeColor(R8G8B8S *dst, const gl::ColorF *src);
+ static void writeColor(R8G8B8S *dst, const gl::ColorI *src);
+ static void average(R8G8B8S *dst, const R8G8B8S *src1, const R8G8B8S *src2);
+};
+
+struct R8G8B8A8S
+{
+ int8_t R;
+ int8_t G;
+ int8_t B;
+ int8_t A;
+
+ static void readColor(gl::ColorF *dst, const R8G8B8A8S *src);
+ static void readColor(gl::ColorI *dst, const R8G8B8A8S *src);
+ static void writeColor(R8G8B8A8S *dst, const gl::ColorF *src);
+ static void writeColor(R8G8B8A8S *dst, const gl::ColorI *src);
+ static void average(R8G8B8A8S *dst, const R8G8B8A8S *src1, const R8G8B8A8S *src2);
+};
+
+struct R16S
+{
+ int16_t R;
+
+ static void readColor(gl::ColorF *dst, const R16S *src);
+ static void readColor(gl::ColorI *dst, const R16S *src);
+ static void writeColor(R16S *dst, const gl::ColorF *src);
+ static void writeColor(R16S *dst, const gl::ColorI *src);
+ static void average(R16S *dst, const R16S *src1, const R16S *src2);
+};
+
+struct R16G16S
+{
+ int16_t R;
+ int16_t G;
+
+ static void readColor(gl::ColorF *dst, const R16G16S *src);
+ static void readColor(gl::ColorI *dst, const R16G16S *src);
+ static void writeColor(R16G16S *dst, const gl::ColorF *src);
+ static void writeColor(R16G16S *dst, const gl::ColorI *src);
+ static void average(R16G16S *dst, const R16G16S *src1, const R16G16S *src2);
+};
+
+struct R16G16B16S
+{
+ int16_t R;
+ int16_t G;
+ int16_t B;
+
+ static void readColor(gl::ColorF *dst, const R16G16B16S *src);
+ static void readColor(gl::ColorI *dst, const R16G16B16S *src);
+ static void writeColor(R16G16B16S *dst, const gl::ColorF *src);
+ static void writeColor(R16G16B16S *dst, const gl::ColorI *src);
+ static void average(R16G16B16S *dst, const R16G16B16S *src1, const R16G16B16S *src2);
+};
+
+struct R16G16B16A16S
+{
+ int16_t R;
+ int16_t G;
+ int16_t B;
+ int16_t A;
+
+ static void readColor(gl::ColorF *dst, const R16G16B16A16S *src);
+ static void readColor(gl::ColorI *dst, const R16G16B16A16S *src);
+ static void writeColor(R16G16B16A16S *dst, const gl::ColorF *src);
+ static void writeColor(R16G16B16A16S *dst, const gl::ColorI *src);
+ static void average(R16G16B16A16S *dst, const R16G16B16A16S *src1, const R16G16B16A16S *src2);
+};
+
+struct R32S
+{
+ int32_t R;
+
+ static void readColor(gl::ColorF *dst, const R32S *src);
+ static void readColor(gl::ColorI *dst, const R32S *src);
+ static void writeColor(R32S *dst, const gl::ColorF *src);
+ static void writeColor(R32S *dst, const gl::ColorI *src);
+ static void average(R32S *dst, const R32S *src1, const R32S *src2);
+};
+
+struct R32G32S
+{
+ int32_t R;
+ int32_t G;
+
+ static void readColor(gl::ColorF *dst, const R32G32S *src);
+ static void readColor(gl::ColorI *dst, const R32G32S *src);
+ static void writeColor(R32G32S *dst, const gl::ColorF *src);
+ static void writeColor(R32G32S *dst, const gl::ColorI *src);
+ static void average(R32G32S *dst, const R32G32S *src1, const R32G32S *src2);
+};
+
+struct R32G32B32S
+{
+ int32_t R;
+ int32_t G;
+ int32_t B;
+
+ static void readColor(gl::ColorF *dst, const R32G32B32S *src);
+ static void readColor(gl::ColorI *dst, const R32G32B32S *src);
+ static void writeColor(R32G32B32S *dst, const gl::ColorF *src);
+ static void writeColor(R32G32B32S *dst, const gl::ColorI *src);
+ static void average(R32G32B32S *dst, const R32G32B32S *src1, const R32G32B32S *src2);
+};
+
+struct R32G32B32A32S
+{
+ int32_t R;
+ int32_t G;
+ int32_t B;
+ int32_t A;
+
+ static void readColor(gl::ColorF *dst, const R32G32B32A32S *src);
+ static void readColor(gl::ColorI *dst, const R32G32B32A32S *src);
+ static void writeColor(R32G32B32A32S *dst, const gl::ColorF *src);
+ static void writeColor(R32G32B32A32S *dst, const gl::ColorI *src);
+ static void average(R32G32B32A32S *dst, const R32G32B32A32S *src1, const R32G32B32A32S *src2);
+};
+
+struct A16B16G16R16F
+{
+ uint16_t A;
+ uint16_t R;
+ uint16_t G;
+ uint16_t B;
+
+ static void readColor(gl::ColorF *dst, const A16B16G16R16F *src);
+ static void writeColor(A16B16G16R16F *dst, const gl::ColorF *src);
+ static void average(A16B16G16R16F *dst, const A16B16G16R16F *src1, const A16B16G16R16F *src2);
+};
+
+struct R16G16B16A16F
+{
+ uint16_t R;
+ uint16_t G;
+ uint16_t B;
+ uint16_t A;
+
+ static void readColor(gl::ColorF *dst, const R16G16B16A16F *src);
+ static void writeColor(R16G16B16A16F *dst, const gl::ColorF *src);
+ static void average(R16G16B16A16F *dst, const R16G16B16A16F *src1, const R16G16B16A16F *src2);
+};
+
+struct R16F
+{
+ uint16_t R;
+
+ static void readColor(gl::ColorF *dst, const R16F *src);
+ static void writeColor(R16F *dst, const gl::ColorF *src);
+ static void average(R16F *dst, const R16F *src1, const R16F *src2);
+};
+
+struct A16F
+{
+ uint16_t A;
+
+ static void readColor(gl::ColorF *dst, const A16F *src);
+ static void writeColor(A16F *dst, const gl::ColorF *src);
+ static void average(A16F *dst, const A16F *src1, const A16F *src2);
+};
+
+struct L16F
+{
+ uint16_t L;
+
+ static void readColor(gl::ColorF *dst, const L16F *src);
+ static void writeColor(L16F *dst, const gl::ColorF *src);
+ static void average(L16F *dst, const L16F *src1, const L16F *src2);
+};
+
+struct L16A16F
+{
+ uint16_t L;
+ uint16_t A;
+
+ static void readColor(gl::ColorF *dst, const L16A16F *src);
+ static void writeColor(L16A16F *dst, const gl::ColorF *src);
+ static void average(L16A16F *dst, const L16A16F *src1, const L16A16F *src2);
+};
+
+struct R16G16F
+{
+ uint16_t R;
+ uint16_t G;
+
+ static void readColor(gl::ColorF *dst, const R16G16F *src);
+ static void writeColor(R16G16F *dst, const gl::ColorF *src);
+ static void average(R16G16F *dst, const R16G16F *src1, const R16G16F *src2);
+};
+
+struct R16G16B16F
+{
+ uint16_t R;
+ uint16_t G;
+ uint16_t B;
+
+ static void readColor(gl::ColorF *dst, const R16G16B16F *src);
+ static void writeColor(R16G16B16F *dst, const gl::ColorF *src);
+ static void average(R16G16B16F *dst, const R16G16B16F *src1, const R16G16B16F *src2);
+};
+
+struct A32B32G32R32F
+{
+ float A;
+ float R;
+ float G;
+ float B;
+
+ static void readColor(gl::ColorF *dst, const A32B32G32R32F *src);
+ static void writeColor(A32B32G32R32F *dst, const gl::ColorF *src);
+ static void average(A32B32G32R32F *dst, const A32B32G32R32F *src1, const A32B32G32R32F *src2);
+};
+
+struct R32G32B32A32F
+{
+ float R;
+ float G;
+ float B;
+ float A;
+
+ static void readColor(gl::ColorF *dst, const R32G32B32A32F *src);
+ static void writeColor(R32G32B32A32F *dst, const gl::ColorF *src);
+ static void average(R32G32B32A32F *dst, const R32G32B32A32F *src1, const R32G32B32A32F *src2);
+};
+
+struct R32F
+{
+ float R;
+
+ static void readColor(gl::ColorF *dst, const R32F *src);
+ static void writeColor(R32F *dst, const gl::ColorF *src);
+ static void average(R32F *dst, const R32F *src1, const R32F *src2);
+};
+
+struct A32F
+{
+ float A;
+
+ static void readColor(gl::ColorF *dst, const A32F *src);
+ static void writeColor(A32F *dst, const gl::ColorF *src);
+ static void average(A32F *dst, const A32F *src1, const A32F *src2);
+};
+
+struct L32F
+{
+ float L;
+
+ static void readColor(gl::ColorF *dst, const L32F *src);
+ static void writeColor(L32F *dst, const gl::ColorF *src);
+ static void average(L32F *dst, const L32F *src1, const L32F *src2);
+};
+
+struct L32A32F
+{
+ float L;
+ float A;
+
+ static void readColor(gl::ColorF *dst, const L32A32F *src);
+ static void writeColor(L32A32F *dst, const gl::ColorF *src);
+ static void average(L32A32F *dst, const L32A32F *src1, const L32A32F *src2);
+};
+
+struct R32G32F
+{
+ float R;
+ float G;
+
+ static void readColor(gl::ColorF *dst, const R32G32F *src);
+ static void writeColor(R32G32F *dst, const gl::ColorF *src);
+ static void average(R32G32F *dst, const R32G32F *src1, const R32G32F *src2);
+};
+
+struct R32G32B32F
+{
+ float R;
+ float G;
+ float B;
+
+ static void readColor(gl::ColorF *dst, const R32G32B32F *src);
+ static void writeColor(R32G32B32F *dst, const gl::ColorF *src);
+ static void average(R32G32B32F *dst, const R32G32B32F *src1, const R32G32B32F *src2);
+};
+
+struct R10G10B10A2
+{
+ uint32_t R : 10;
+ uint32_t G : 10;
+ uint32_t B : 10;
+ uint32_t A : 2;
+
+ static void readColor(gl::ColorF *dst, const R10G10B10A2 *src);
+ static void readColor(gl::ColorUI *dst, const R10G10B10A2 *src);
+ static void writeColor(R10G10B10A2 *dst, const gl::ColorF *src);
+ static void writeColor(R10G10B10A2 *dst, const gl::ColorUI *src);
+ static void average(R10G10B10A2 *dst, const R10G10B10A2 *src1, const R10G10B10A2 *src2);
+};
+static_assert(sizeof(R10G10B10A2) == 4, "R10G10B10A2 struct not 32-bits.");
+
+struct R9G9B9E5
+{
+ uint32_t R : 9;
+ uint32_t G : 9;
+ uint32_t B : 9;
+ uint32_t E : 5;
+
+ static void readColor(gl::ColorF *dst, const R9G9B9E5 *src);
+ static void writeColor(R9G9B9E5 *dst, const gl::ColorF *src);
+ static void average(R9G9B9E5 *dst, const R9G9B9E5 *src1, const R9G9B9E5 *src2);
+};
+static_assert(sizeof(R9G9B9E5) == 4, "R9G9B9E5 struct not 32-bits.");
+
+struct R11G11B10F
+{
+ uint32_t R : 11;
+ uint32_t G : 11;
+ uint32_t B : 10;
+
+ static void readColor(gl::ColorF *dst, const R11G11B10F *src);
+ static void writeColor(R11G11B10F *dst, const gl::ColorF *src);
+ static void average(R11G11B10F *dst, const R11G11B10F *src1, const R11G11B10F *src2);
+};
+static_assert(sizeof(R11G11B10F) == 4, "R11G11B10F struct not 32-bits.");
+
+} // namespace angle
+
+#endif // IMAGEUTIL_IMAGEFORMATS_H_
diff --git a/src/3rdparty/angle/src/image_util/loadimage.cpp b/src/3rdparty/angle/src/image_util/loadimage.cpp
new file mode 100644
index 0000000000..56ad3b32e3
--- /dev/null
+++ b/src/3rdparty/angle/src/image_util/loadimage.cpp
@@ -0,0 +1,1323 @@
+//
+// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// angle_loadimage.cpp: Defines image loading functions.
+
+#include "image_util/loadimage.h"
+
+#include "common/mathutil.h"
+#include "common/platform.h"
+#include "image_util/imageformats.h"
+
+namespace angle
+{
+
+void LoadA8ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+#if defined(ANGLE_USE_SSE)
+ if (gl::supportsSSE2())
+ {
+ __m128i zeroWide = _mm_setzero_si128();
+
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint8_t *source =
+ priv::OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint32_t *dest = priv::OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch,
+ outputDepthPitch);
+
+ size_t x = 0;
+
+ // Make output writes aligned
+ for (; ((reinterpret_cast<intptr_t>(&dest[x]) & 0xF) != 0 && x < width); x++)
+ {
+ dest[x] = static_cast<uint32_t>(source[x]) << 24;
+ }
+
+ for (; x + 7 < width; x += 8)
+ {
+ __m128i sourceData =
+ _mm_loadl_epi64(reinterpret_cast<const __m128i *>(&source[x]));
+ // Interleave each byte to 16bit, make the lower byte to zero
+ sourceData = _mm_unpacklo_epi8(zeroWide, sourceData);
+ // Interleave each 16bit to 32bit, make the lower 16bit to zero
+ __m128i lo = _mm_unpacklo_epi16(zeroWide, sourceData);
+ __m128i hi = _mm_unpackhi_epi16(zeroWide, sourceData);
+
+ _mm_store_si128(reinterpret_cast<__m128i *>(&dest[x]), lo);
+ _mm_store_si128(reinterpret_cast<__m128i *>(&dest[x + 4]), hi);
+ }
+
+ // Handle the remainder
+ for (; x < width; x++)
+ {
+ dest[x] = static_cast<uint32_t>(source[x]) << 24;
+ }
+ }
+ }
+
+ return;
+ }
+#endif
+
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint8_t *source =
+ priv::OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint32_t *dest =
+ priv::OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[x] = static_cast<uint32_t>(source[x]) << 24;
+ }
+ }
+ }
+}
+
+void LoadA8ToBGRA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ // Same as loading to RGBA
+ LoadA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch);
+}
+
+void LoadA32FToRGBA32F(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const float *source =
+ priv::OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+ float *dest =
+ priv::OffsetDataPointer<float>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[4 * x + 0] = 0.0f;
+ dest[4 * x + 1] = 0.0f;
+ dest[4 * x + 2] = 0.0f;
+ dest[4 * x + 3] = source[x];
+ }
+ }
+ }
+}
+
+void LoadA16FToRGBA16F(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source =
+ priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint16_t *dest =
+ priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[4 * x + 0] = 0;
+ dest[4 * x + 1] = 0;
+ dest[4 * x + 2] = 0;
+ dest[4 * x + 3] = source[x];
+ }
+ }
+ }
+}
+
+void LoadL8ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint8_t *source =
+ priv::OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest =
+ priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint8_t sourceVal = source[x];
+ dest[4 * x + 0] = sourceVal;
+ dest[4 * x + 1] = sourceVal;
+ dest[4 * x + 2] = sourceVal;
+ dest[4 * x + 3] = 0xFF;
+ }
+ }
+ }
+}
+
+void LoadL8ToBGRA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ // Same as loading to RGBA
+ LoadL8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch);
+}
+
+void LoadL32FToRGBA32F(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const float *source =
+ priv::OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+ float *dest =
+ priv::OffsetDataPointer<float>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[4 * x + 0] = source[x];
+ dest[4 * x + 1] = source[x];
+ dest[4 * x + 2] = source[x];
+ dest[4 * x + 3] = 1.0f;
+ }
+ }
+ }
+}
+
+void LoadL16FToRGBA16F(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source =
+ priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint16_t *dest =
+ priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[4 * x + 0] = source[x];
+ dest[4 * x + 1] = source[x];
+ dest[4 * x + 2] = source[x];
+ dest[4 * x + 3] = gl::Float16One;
+ }
+ }
+ }
+}
+
+void LoadLA8ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint8_t *source =
+ priv::OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest =
+ priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[4 * x + 0] = source[2 * x + 0];
+ dest[4 * x + 1] = source[2 * x + 0];
+ dest[4 * x + 2] = source[2 * x + 0];
+ dest[4 * x + 3] = source[2 * x + 1];
+ }
+ }
+ }
+}
+
+void LoadLA8ToBGRA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ // Same as loading to RGBA
+ LoadLA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch);
+}
+
+void LoadLA32FToRGBA32F(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const float *source =
+ priv::OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+ float *dest =
+ priv::OffsetDataPointer<float>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[4 * x + 0] = source[2 * x + 0];
+ dest[4 * x + 1] = source[2 * x + 0];
+ dest[4 * x + 2] = source[2 * x + 0];
+ dest[4 * x + 3] = source[2 * x + 1];
+ }
+ }
+ }
+}
+
+void LoadLA16FToRGBA16F(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source =
+ priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint16_t *dest =
+ priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[4 * x + 0] = source[2 * x + 0];
+ dest[4 * x + 1] = source[2 * x + 0];
+ dest[4 * x + 2] = source[2 * x + 0];
+ dest[4 * x + 3] = source[2 * x + 1];
+ }
+ }
+ }
+}
+
+void LoadRGB8ToBGR565(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint8_t *source =
+ priv::OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint16_t *dest =
+ priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint8_t r8 = source[x * 3 + 0];
+ uint8_t g8 = source[x * 3 + 1];
+ uint8_t b8 = source[x * 3 + 2];
+ auto r5 = static_cast<uint16_t>(r8 >> 3);
+ auto g6 = static_cast<uint16_t>(g8 >> 2);
+ auto b5 = static_cast<uint16_t>(b8 >> 3);
+ dest[x] = (r5 << 11) | (g6 << 5) | b5;
+ }
+ }
+ }
+}
+
+void LoadRGB565ToBGR565(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source =
+ priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint16_t *dest =
+ priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ // The GL type RGB is packed with with red in the MSB, while the D3D11 type BGR
+ // is packed with red in the LSB
+ auto rgb = source[x];
+ uint16_t r5 = gl::getShiftedData<5, 11>(rgb);
+ uint16_t g6 = gl::getShiftedData<6, 5>(rgb);
+ uint16_t b5 = gl::getShiftedData<5, 0>(rgb);
+ dest[x] = (r5 << 11) | (g6 << 5) | b5;
+ }
+ }
+ }
+}
+
+void LoadRGB8ToBGRX8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint8_t *source =
+ priv::OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest =
+ priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[4 * x + 0] = source[x * 3 + 2];
+ dest[4 * x + 1] = source[x * 3 + 1];
+ dest[4 * x + 2] = source[x * 3 + 0];
+ dest[4 * x + 3] = 0xFF;
+ }
+ }
+ }
+}
+
+void LoadRG8ToBGRX8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint8_t *source =
+ priv::OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest =
+ priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[4 * x + 0] = 0x00;
+ dest[4 * x + 1] = source[x * 2 + 1];
+ dest[4 * x + 2] = source[x * 2 + 0];
+ dest[4 * x + 3] = 0xFF;
+ }
+ }
+ }
+}
+
+void LoadR8ToBGRX8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint8_t *source =
+ priv::OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest =
+ priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[4 * x + 0] = 0x00;
+ dest[4 * x + 1] = 0x00;
+ dest[4 * x + 2] = source[x];
+ dest[4 * x + 3] = 0xFF;
+ }
+ }
+ }
+}
+
+void LoadR5G6B5ToBGRA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source =
+ priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest =
+ priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint16_t rgb = source[x];
+ dest[4 * x + 0] =
+ static_cast<uint8_t>(((rgb & 0x001F) << 3) | ((rgb & 0x001F) >> 2));
+ dest[4 * x + 1] =
+ static_cast<uint8_t>(((rgb & 0x07E0) >> 3) | ((rgb & 0x07E0) >> 9));
+ dest[4 * x + 2] =
+ static_cast<uint8_t>(((rgb & 0xF800) >> 8) | ((rgb & 0xF800) >> 13));
+ dest[4 * x + 3] = 0xFF;
+ }
+ }
+ }
+}
+
+void LoadR5G6B5ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source =
+ priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest =
+ priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint16_t rgb = source[x];
+ dest[4 * x + 0] =
+ static_cast<uint8_t>(((rgb & 0xF800) >> 8) | ((rgb & 0xF800) >> 13));
+ dest[4 * x + 1] =
+ static_cast<uint8_t>(((rgb & 0x07E0) >> 3) | ((rgb & 0x07E0) >> 9));
+ dest[4 * x + 2] =
+ static_cast<uint8_t>(((rgb & 0x001F) << 3) | ((rgb & 0x001F) >> 2));
+ dest[4 * x + 3] = 0xFF;
+ }
+ }
+ }
+}
+
+void LoadRGBA8ToBGRA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+#if defined(ANGLE_USE_SSE)
+ if (gl::supportsSSE2())
+ {
+ __m128i brMask = _mm_set1_epi32(0x00ff00ff);
+
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint32_t *source =
+ priv::OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint32_t *dest = priv::OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch,
+ outputDepthPitch);
+
+ size_t x = 0;
+
+ // Make output writes aligned
+ for (; ((reinterpret_cast<intptr_t>(&dest[x]) & 15) != 0) && x < width; x++)
+ {
+ uint32_t rgba = source[x];
+ dest[x] = (ANGLE_ROTL(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
+ }
+
+ for (; x + 3 < width; x += 4)
+ {
+ __m128i sourceData =
+ _mm_loadu_si128(reinterpret_cast<const __m128i *>(&source[x]));
+ // Mask out g and a, which don't change
+ __m128i gaComponents = _mm_andnot_si128(brMask, sourceData);
+ // Mask out b and r
+ __m128i brComponents = _mm_and_si128(sourceData, brMask);
+ // Swap b and r
+ __m128i brSwapped = _mm_shufflehi_epi16(
+ _mm_shufflelo_epi16(brComponents, _MM_SHUFFLE(2, 3, 0, 1)),
+ _MM_SHUFFLE(2, 3, 0, 1));
+ __m128i result = _mm_or_si128(gaComponents, brSwapped);
+ _mm_store_si128(reinterpret_cast<__m128i *>(&dest[x]), result);
+ }
+
+ // Perform leftover writes
+ for (; x < width; x++)
+ {
+ uint32_t rgba = source[x];
+ dest[x] = (ANGLE_ROTL(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
+ }
+ }
+ }
+
+ return;
+ }
+#endif
+
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint32_t *source =
+ priv::OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint32_t *dest =
+ priv::OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint32_t rgba = source[x];
+ dest[x] = (ANGLE_ROTL(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
+ }
+ }
+ }
+}
+
+void LoadRGBA8ToBGRA4(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint32_t *source =
+ priv::OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint16_t *dest =
+ priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint32_t rgba8 = source[x];
+ auto r4 = static_cast<uint16_t>((rgba8 & 0x000000FF) >> 4);
+ auto g4 = static_cast<uint16_t>((rgba8 & 0x0000FF00) >> 12);
+ auto b4 = static_cast<uint16_t>((rgba8 & 0x00FF0000) >> 20);
+ auto a4 = static_cast<uint16_t>((rgba8 & 0xFF000000) >> 28);
+ dest[x] = (a4 << 12) | (r4 << 8) | (g4 << 4) | b4;
+ }
+ }
+ }
+}
+
+void LoadRGBA4ToARGB4(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source =
+ priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint16_t *dest =
+ priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[x] = ANGLE_ROTR16(source[x], 4);
+ }
+ }
+ }
+}
+
+void LoadRGBA4ToBGRA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source =
+ priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest =
+ priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint16_t rgba = source[x];
+ dest[4 * x + 0] =
+ static_cast<uint8_t>(((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4));
+ dest[4 * x + 1] =
+ static_cast<uint8_t>(((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8));
+ dest[4 * x + 2] =
+ static_cast<uint8_t>(((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12));
+ dest[4 * x + 3] =
+ static_cast<uint8_t>(((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0));
+ }
+ }
+ }
+}
+
+void LoadRGBA4ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source =
+ priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest =
+ priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint16_t rgba = source[x];
+ dest[4 * x + 0] =
+ static_cast<uint8_t>(((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12));
+ dest[4 * x + 1] =
+ static_cast<uint8_t>(((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8));
+ dest[4 * x + 2] =
+ static_cast<uint8_t>(((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4));
+ dest[4 * x + 3] =
+ static_cast<uint8_t>(((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0));
+ }
+ }
+ }
+}
+
+void LoadBGRA4ToBGRA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source =
+ priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest =
+ priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint16_t bgra = source[x];
+ dest[4 * x + 0] =
+ static_cast<uint8_t>(((bgra & 0xF000) >> 8) | ((bgra & 0xF000) >> 12));
+ dest[4 * x + 1] =
+ static_cast<uint8_t>(((bgra & 0x0F00) >> 4) | ((bgra & 0x0F00) >> 8));
+ dest[4 * x + 2] =
+ static_cast<uint8_t>(((bgra & 0x00F0) << 0) | ((bgra & 0x00F0) >> 4));
+ dest[4 * x + 3] =
+ static_cast<uint8_t>(((bgra & 0x000F) << 4) | ((bgra & 0x000F) >> 0));
+ }
+ }
+ }
+}
+
+void LoadRGBA8ToBGR5A1(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint32_t *source =
+ priv::OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint16_t *dest =
+ priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint32_t rgba8 = source[x];
+ auto r5 = static_cast<uint16_t>((rgba8 & 0x000000FF) >> 3);
+ auto g5 = static_cast<uint16_t>((rgba8 & 0x0000FF00) >> 11);
+ auto b5 = static_cast<uint16_t>((rgba8 & 0x00FF0000) >> 19);
+ auto a1 = static_cast<uint16_t>((rgba8 & 0xFF000000) >> 31);
+ dest[x] = (a1 << 15) | (r5 << 10) | (g5 << 5) | b5;
+ }
+ }
+ }
+}
+
+void LoadRGB10A2ToBGR5A1(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const R10G10B10A2 *source =
+ priv::OffsetDataPointer<R10G10B10A2>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint16_t *dest =
+ priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ R10G10B10A2 rgb10a2 = source[x];
+
+ uint16_t r5 = static_cast<uint16_t>(rgb10a2.R >> 5u);
+ uint16_t g5 = static_cast<uint16_t>(rgb10a2.G >> 5u);
+ uint16_t b5 = static_cast<uint16_t>(rgb10a2.B >> 5u);
+ uint16_t a1 = static_cast<uint16_t>(rgb10a2.A >> 1u);
+
+ dest[x] = (a1 << 15) | (r5 << 10) | (g5 << 5) | b5;
+ }
+ }
+ }
+}
+
+void LoadRGB5A1ToA1RGB5(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source =
+ priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint16_t *dest =
+ priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[x] = ANGLE_ROTR16(source[x], 1);
+ }
+ }
+ }
+}
+
+void LoadRGB5A1ToBGRA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source =
+ priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest =
+ priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint16_t rgba = source[x];
+ dest[4 * x + 0] =
+ static_cast<uint8_t>(((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3));
+ dest[4 * x + 1] =
+ static_cast<uint8_t>(((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8));
+ dest[4 * x + 2] =
+ static_cast<uint8_t>(((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13));
+ dest[4 * x + 3] = static_cast<uint8_t>((rgba & 0x0001) ? 0xFF : 0);
+ }
+ }
+ }
+}
+
+void LoadRGB5A1ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source =
+ priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest =
+ priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint16_t rgba = source[x];
+ dest[4 * x + 0] =
+ static_cast<uint8_t>(((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13));
+ dest[4 * x + 1] =
+ static_cast<uint8_t>(((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8));
+ dest[4 * x + 2] =
+ static_cast<uint8_t>(((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3));
+ dest[4 * x + 3] = static_cast<uint8_t>((rgba & 0x0001) ? 0xFF : 0);
+ }
+ }
+ }
+}
+
+void LoadBGR5A1ToBGRA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source =
+ priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest =
+ priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint16_t bgra = source[x];
+ dest[4 * x + 0] =
+ static_cast<uint8_t>(((bgra & 0xF800) >> 8) | ((bgra & 0xF800) >> 13));
+ dest[4 * x + 1] =
+ static_cast<uint8_t>(((bgra & 0x07C0) >> 3) | ((bgra & 0x07C0) >> 8));
+ dest[4 * x + 2] =
+ static_cast<uint8_t>(((bgra & 0x003E) << 2) | ((bgra & 0x003E) >> 3));
+ dest[4 * x + 3] = static_cast<uint8_t>((bgra & 0x0001) ? 0xFF : 0);
+ }
+ }
+ }
+}
+
+void LoadRGB10A2ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint32_t *source =
+ priv::OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest =
+ priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint32_t rgba = source[x];
+ dest[4 * x + 0] = static_cast<uint8_t>((rgba & 0x000003FF) >> 2);
+ dest[4 * x + 1] = static_cast<uint8_t>((rgba & 0x000FFC00) >> 12);
+ dest[4 * x + 2] = static_cast<uint8_t>((rgba & 0x3FF00000) >> 22);
+ dest[4 * x + 3] = static_cast<uint8_t>(((rgba & 0xC0000000) >> 30) * 0x55);
+ }
+ }
+ }
+}
+
+void LoadRGB16FToRGB9E5(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source =
+ priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint32_t *dest =
+ priv::OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[x] = gl::convertRGBFloatsTo999E5(gl::float16ToFloat32(source[x * 3 + 0]),
+ gl::float16ToFloat32(source[x * 3 + 1]),
+ gl::float16ToFloat32(source[x * 3 + 2]));
+ }
+ }
+ }
+}
+
+void LoadRGB32FToRGB9E5(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const float *source =
+ priv::OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint32_t *dest =
+ priv::OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[x] = gl::convertRGBFloatsTo999E5(source[x * 3 + 0], source[x * 3 + 1],
+ source[x * 3 + 2]);
+ }
+ }
+ }
+}
+
+void LoadRGB16FToRG11B10F(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint16_t *source =
+ priv::OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint32_t *dest =
+ priv::OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[x] = (gl::float32ToFloat11(gl::float16ToFloat32(source[x * 3 + 0])) << 0) |
+ (gl::float32ToFloat11(gl::float16ToFloat32(source[x * 3 + 1])) << 11) |
+ (gl::float32ToFloat10(gl::float16ToFloat32(source[x * 3 + 2])) << 22);
+ }
+ }
+ }
+}
+
+void LoadRGB32FToRG11B10F(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const float *source =
+ priv::OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint32_t *dest =
+ priv::OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[x] = (gl::float32ToFloat11(source[x * 3 + 0]) << 0) |
+ (gl::float32ToFloat11(source[x * 3 + 1]) << 11) |
+ (gl::float32ToFloat10(source[x * 3 + 2]) << 22);
+ }
+ }
+ }
+}
+
+void LoadG8R24ToR24G8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint32_t *source =
+ priv::OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint32_t *dest =
+ priv::OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ uint32_t d = source[x] >> 8;
+ uint8_t s = source[x] & 0xFF;
+ dest[x] = d | (s << 24);
+ }
+ }
+ }
+}
+
+void LoadD32FToD32F(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const float *source =
+ priv::OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+ float *dest =
+ priv::OffsetDataPointer<float>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[x] = gl::clamp01(source[x]);
+ }
+ }
+ }
+}
+
+void LoadD32FS8X24ToD32FS8X24(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const float *sourceDepth =
+ priv::OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+ const uint32_t *sourceStencil =
+ priv::OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch) + 1;
+ float *destDepth =
+ priv::OffsetDataPointer<float>(output, y, z, outputRowPitch, outputDepthPitch);
+ uint32_t *destStencil =
+ priv::OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch) +
+ 1;
+ for (size_t x = 0; x < width; x++)
+ {
+ destDepth[x * 2] = gl::clamp01(sourceDepth[x * 2]);
+ destStencil[x * 2] = sourceStencil[x * 2] & 0xFF000000;
+ }
+ }
+ }
+}
+
+void LoadRGB32FToRGBA16F(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const float *source =
+ priv::OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint16_t *dest =
+ priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[x * 4 + 0] = gl::float32ToFloat16(source[x * 3 + 0]);
+ dest[x * 4 + 1] = gl::float32ToFloat16(source[x * 3 + 1]);
+ dest[x * 4 + 2] = gl::float32ToFloat16(source[x * 3 + 2]);
+ dest[x * 4 + 3] = gl::Float16One;
+ }
+ }
+ }
+}
+
+void LoadR32ToR16(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint32_t *source =
+ priv::OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint16_t *dest =
+ priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[x] = source[x] >> 16;
+ }
+ }
+ }
+}
+
+void LoadR32ToR24G8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const uint32_t *source =
+ priv::OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint32_t *dest =
+ priv::OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
+
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[x] = source[x] >> 8;
+ }
+ }
+ }
+}
+
+} // namespace angle
diff --git a/src/3rdparty/angle/src/image_util/loadimage.h b/src/3rdparty/angle/src/image_util/loadimage.h
new file mode 100644
index 0000000000..3e8aac79c2
--- /dev/null
+++ b/src/3rdparty/angle/src/image_util/loadimage.h
@@ -0,0 +1,658 @@
+//
+// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// loadimage.h: Defines image loading functions
+
+#ifndef IMAGEUTIL_LOADIMAGE_H_
+#define IMAGEUTIL_LOADIMAGE_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace angle
+{
+
+void LoadA8ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadA8ToBGRA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadA32FToRGBA32F(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadA16FToRGBA16F(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadL8ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadL8ToBGRA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadL32FToRGBA32F(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadL16FToRGBA16F(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadLA8ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadLA8ToBGRA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadLA32FToRGBA32F(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadLA16FToRGBA16F(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadRGB8ToBGR565(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadRGB565ToBGR565(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadRGB8ToBGRX8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadRG8ToBGRX8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadR8ToBGRX8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadR5G6B5ToBGRA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadR5G6B5ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadRGBA8ToBGRA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadRGBA8ToBGRA4(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadRGBA4ToARGB4(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadRGBA4ToBGRA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadRGBA4ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadBGRA4ToBGRA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadRGBA8ToBGR5A1(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadRGB10A2ToBGR5A1(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadRGB5A1ToA1RGB5(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadRGB5A1ToBGRA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadRGB5A1ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadBGR5A1ToBGRA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadRGB10A2ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadRGB16FToRGB9E5(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadRGB32FToRGB9E5(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadRGB16FToRG11B10F(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadRGB32FToRG11B10F(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadG8R24ToR24G8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadD32FToD32F(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadD32FS8X24ToD32FS8X24(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+template <typename type, size_t componentCount>
+inline void LoadToNative(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+template <typename type, uint32_t fourthComponentBits>
+inline void LoadToNative3To4(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+template <size_t componentCount>
+inline void Load32FTo16F(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadRGB32FToRGBA16F(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+template <size_t blockWidth, size_t blockHeight, size_t blockSize>
+inline void LoadCompressedToNative(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadR32ToR16(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+template <typename type,
+ uint32_t firstBits,
+ uint32_t secondBits,
+ uint32_t thirdBits,
+ uint32_t fourthBits>
+inline void Initialize4ComponentData(size_t width,
+ size_t height,
+ size_t depth,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadR32ToR24G8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadETC1RGB8ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadETC1RGB8ToBC1(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadEACR11ToR8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadEACR11SToR8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadEACRG11ToRG8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadEACRG11SToRG8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadETC2RGB8ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadETC2RGB8ToBC1(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadETC2SRGB8ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadETC2SRGB8ToBC1(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadETC2RGB8A1ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadETC2RGB8A1ToBC1(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadETC2SRGB8A1ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadETC2SRGB8A1ToBC1(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadETC2RGBA8ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+void LoadETC2SRGBA8ToSRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+} // namespace angle
+
+#include "loadimage.inl"
+
+#endif // IMAGEUTIL_LOADIMAGE_H_
diff --git a/src/3rdparty/angle/src/image_util/loadimage.inl b/src/3rdparty/angle/src/image_util/loadimage.inl
new file mode 100644
index 0000000000..b8d590ca1b
--- /dev/null
+++ b/src/3rdparty/angle/src/image_util/loadimage.inl
@@ -0,0 +1,163 @@
+//
+// Copyright (c) 2014-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "common/mathutil.h"
+
+#include <string.h>
+
+namespace angle
+{
+
+namespace priv
+{
+
+template <typename T>
+inline T *OffsetDataPointer(uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch)
+{
+ return reinterpret_cast<T*>(data + (y * rowPitch) + (z * depthPitch));
+}
+
+template <typename T>
+inline const T *OffsetDataPointer(const uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch)
+{
+ return reinterpret_cast<const T*>(data + (y * rowPitch) + (z * depthPitch));
+}
+
+} // namespace priv
+
+template <typename type, size_t componentCount>
+inline void LoadToNative(size_t width, size_t height, size_t depth,
+ const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
+ uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
+{
+ const size_t rowSize = width * sizeof(type) * componentCount;
+ const size_t layerSize = rowSize * height;
+ const size_t imageSize = layerSize * depth;
+
+ if (layerSize == inputDepthPitch && layerSize == outputDepthPitch)
+ {
+ ASSERT(rowSize == inputRowPitch && rowSize == outputRowPitch);
+ memcpy(output, input, imageSize);
+ }
+ else if (rowSize == inputRowPitch && rowSize == outputRowPitch)
+ {
+ for (size_t z = 0; z < depth; z++)
+ {
+ const type *source = priv::OffsetDataPointer<type>(input, 0, z, inputRowPitch, inputDepthPitch);
+ type *dest = priv::OffsetDataPointer<type>(output, 0, z, outputRowPitch, outputDepthPitch);
+
+ memcpy(dest, source, layerSize);
+ }
+ }
+ else
+ {
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const type *source = priv::OffsetDataPointer<type>(input, y, z, inputRowPitch, inputDepthPitch);
+ type *dest = priv::OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch);
+ memcpy(dest, source, width * sizeof(type) * componentCount);
+ }
+ }
+ }
+}
+
+template <typename type, uint32_t fourthComponentBits>
+inline void LoadToNative3To4(size_t width, size_t height, size_t depth,
+ const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
+ uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
+{
+ const type fourthValue = gl::bitCast<type>(fourthComponentBits);
+
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const type *source = priv::OffsetDataPointer<type>(input, y, z, inputRowPitch, inputDepthPitch);
+ type *dest = priv::OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ dest[x * 4 + 0] = source[x * 3 + 0];
+ dest[x * 4 + 1] = source[x * 3 + 1];
+ dest[x * 4 + 2] = source[x * 3 + 2];
+ dest[x * 4 + 3] = fourthValue;
+ }
+ }
+ }
+}
+
+template <size_t componentCount>
+inline void Load32FTo16F(size_t width, size_t height, size_t depth,
+ const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
+ uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
+{
+ const size_t elementWidth = componentCount * width;
+
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ const float *source = priv::OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint16_t *dest = priv::OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+
+ for (size_t x = 0; x < elementWidth; x++)
+ {
+ dest[x] = gl::float32ToFloat16(source[x]);
+ }
+ }
+ }
+}
+
+template <size_t blockWidth, size_t blockHeight, size_t blockSize>
+inline void LoadCompressedToNative(size_t width, size_t height, size_t depth,
+ const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
+ uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
+{
+ const size_t columns = (width + (blockWidth - 1)) / blockWidth;
+ const size_t rows = (height + (blockHeight - 1)) / blockHeight;
+
+ for (size_t z = 0; z < depth; ++z)
+ {
+ for (size_t y = 0; y < rows; ++y)
+ {
+ const uint8_t *source = priv::OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
+ uint8_t *dest = priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+ memcpy(dest, source, columns * blockSize);
+ }
+ }
+}
+
+template <typename type, uint32_t firstBits, uint32_t secondBits, uint32_t thirdBits, uint32_t fourthBits>
+inline void Initialize4ComponentData(size_t width, size_t height, size_t depth,
+ uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
+{
+ type writeValues[4] =
+ {
+ gl::bitCast<type>(firstBits),
+ gl::bitCast<type>(secondBits),
+ gl::bitCast<type>(thirdBits),
+ gl::bitCast<type>(fourthBits),
+ };
+
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ type *destRow = priv::OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch);
+ for (size_t x = 0; x < width; x++)
+ {
+ type* destPixel = destRow + x * 4;
+
+ // This could potentially be optimized by generating an entire row of initialization
+ // data and copying row by row instead of pixel by pixel.
+ memcpy(destPixel, writeValues, sizeof(type) * 4);
+ }
+ }
+ }
+}
+
+} // namespace angle
diff --git a/src/3rdparty/angle/src/image_util/loadimage_etc.cpp b/src/3rdparty/angle/src/image_util/loadimage_etc.cpp
new file mode 100644
index 0000000000..67f73837c0
--- /dev/null
+++ b/src/3rdparty/angle/src/image_util/loadimage_etc.cpp
@@ -0,0 +1,1729 @@
+//
+// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// loadimage_etc.cpp: Decodes ETC and EAC encoded textures.
+
+#include "image_util/loadimage.h"
+
+#include "common/mathutil.h"
+
+#include "image_util/imageformats.h"
+
+namespace angle
+{
+namespace
+{
+
+using IntensityModifier = const int[4];
+
+// Table 3.17.2 sorted according to table 3.17.3
+// clang-format off
+static IntensityModifier intensityModifierDefault[] =
+{
+ { 2, 8, -2, -8 },
+ { 5, 17, -5, -17 },
+ { 9, 29, -9, -29 },
+ { 13, 42, -13, -42 },
+ { 18, 60, -18, -60 },
+ { 24, 80, -24, -80 },
+ { 33, 106, -33, -106 },
+ { 47, 183, -47, -183 },
+};
+// clang-format on
+
+// Table C.12, intensity modifier for non opaque punchthrough alpha
+// clang-format off
+static IntensityModifier intensityModifierNonOpaque[] =
+{
+ { 0, 8, 0, -8 },
+ { 0, 17, 0, -17 },
+ { 0, 29, 0, -29 },
+ { 0, 42, 0, -42 },
+ { 0, 60, 0, -60 },
+ { 0, 80, 0, -80 },
+ { 0, 106, 0, -106 },
+ { 0, 183, 0, -183 },
+};
+// clang-format on
+
+static const int kNumPixelsInBlock = 16;
+
+struct ETC2Block
+{
+ // Decodes unsigned single or dual channel block to bytes
+ void decodeAsSingleChannel(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ size_t destPixelStride,
+ size_t destRowPitch,
+ bool isSigned) const
+ {
+ for (size_t j = 0; j < 4 && (y + j) < h; j++)
+ {
+ uint8_t *row = dest + (j * destRowPitch);
+ for (size_t i = 0; i < 4 && (x + i) < w; i++)
+ {
+ uint8_t *pixel = row + (i * destPixelStride);
+ if (isSigned)
+ {
+ *pixel = clampSByte(getSingleChannel(i, j, isSigned));
+ }
+ else
+ {
+ *pixel = clampByte(getSingleChannel(i, j, isSigned));
+ }
+ }
+ }
+ }
+
+ // Decodes RGB block to rgba8
+ void decodeAsRGB(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ size_t destRowPitch,
+ const uint8_t alphaValues[4][4],
+ bool punchThroughAlpha) const
+ {
+ bool opaqueBit = u.idht.mode.idm.diffbit;
+ bool nonOpaquePunchThroughAlpha = punchThroughAlpha && !opaqueBit;
+ // Select mode
+ if (u.idht.mode.idm.diffbit || punchThroughAlpha)
+ {
+ const auto &block = u.idht.mode.idm.colors.diff;
+ int r = (block.R + block.dR);
+ int g = (block.G + block.dG);
+ int b = (block.B + block.dB);
+ if (r < 0 || r > 31)
+ {
+ decodeTBlock(dest, x, y, w, h, destRowPitch, alphaValues,
+ nonOpaquePunchThroughAlpha);
+ }
+ else if (g < 0 || g > 31)
+ {
+ decodeHBlock(dest, x, y, w, h, destRowPitch, alphaValues,
+ nonOpaquePunchThroughAlpha);
+ }
+ else if (b < 0 || b > 31)
+ {
+ decodePlanarBlock(dest, x, y, w, h, destRowPitch, alphaValues);
+ }
+ else
+ {
+ decodeDifferentialBlock(dest, x, y, w, h, destRowPitch, alphaValues,
+ nonOpaquePunchThroughAlpha);
+ }
+ }
+ else
+ {
+ decodeIndividualBlock(dest, x, y, w, h, destRowPitch, alphaValues,
+ nonOpaquePunchThroughAlpha);
+ }
+ }
+
+ // Transcodes RGB block to BC1
+ void transcodeAsBC1(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ const uint8_t alphaValues[4][4],
+ bool punchThroughAlpha) const
+ {
+ bool opaqueBit = u.idht.mode.idm.diffbit;
+ bool nonOpaquePunchThroughAlpha = punchThroughAlpha && !opaqueBit;
+ // Select mode
+ if (u.idht.mode.idm.diffbit || punchThroughAlpha)
+ {
+ const auto &block = u.idht.mode.idm.colors.diff;
+ int r = (block.R + block.dR);
+ int g = (block.G + block.dG);
+ int b = (block.B + block.dB);
+ if (r < 0 || r > 31)
+ {
+ transcodeTBlockToBC1(dest, x, y, w, h, alphaValues, nonOpaquePunchThroughAlpha);
+ }
+ else if (g < 0 || g > 31)
+ {
+ transcodeHBlockToBC1(dest, x, y, w, h, alphaValues, nonOpaquePunchThroughAlpha);
+ }
+ else if (b < 0 || b > 31)
+ {
+ transcodePlanarBlockToBC1(dest, x, y, w, h, alphaValues);
+ }
+ else
+ {
+ transcodeDifferentialBlockToBC1(dest, x, y, w, h, alphaValues,
+ nonOpaquePunchThroughAlpha);
+ }
+ }
+ else
+ {
+ transcodeIndividualBlockToBC1(dest, x, y, w, h, alphaValues,
+ nonOpaquePunchThroughAlpha);
+ }
+ }
+
+ private:
+ union {
+ // Individual, differential, H and T modes
+ struct
+ {
+ union {
+ // Individual and differential modes
+ struct
+ {
+ union {
+ struct // Individual colors
+ {
+ unsigned char R2 : 4;
+ unsigned char R1 : 4;
+ unsigned char G2 : 4;
+ unsigned char G1 : 4;
+ unsigned char B2 : 4;
+ unsigned char B1 : 4;
+ } indiv;
+ struct // Differential colors
+ {
+ signed char dR : 3;
+ unsigned char R : 5;
+ signed char dG : 3;
+ unsigned char G : 5;
+ signed char dB : 3;
+ unsigned char B : 5;
+ } diff;
+ } colors;
+ bool flipbit : 1;
+ bool diffbit : 1;
+ unsigned char cw2 : 3;
+ unsigned char cw1 : 3;
+ } idm;
+ // T mode
+ struct
+ {
+ // Byte 1
+ unsigned char TR1b : 2;
+ unsigned char TdummyB : 1;
+ unsigned char TR1a : 2;
+ unsigned char TdummyA : 3;
+ // Byte 2
+ unsigned char TB1 : 4;
+ unsigned char TG1 : 4;
+ // Byte 3
+ unsigned char TG2 : 4;
+ unsigned char TR2 : 4;
+ // Byte 4
+ unsigned char Tdb : 1;
+ bool Tflipbit : 1;
+ unsigned char Tda : 2;
+ unsigned char TB2 : 4;
+ } tm;
+ // H mode
+ struct
+ {
+ // Byte 1
+ unsigned char HG1a : 3;
+ unsigned char HR1 : 4;
+ unsigned char HdummyA : 1;
+ // Byte 2
+ unsigned char HB1b : 2;
+ unsigned char HdummyC : 1;
+ unsigned char HB1a : 1;
+ unsigned char HG1b : 1;
+ unsigned char HdummyB : 3;
+ // Byte 3
+ unsigned char HG2a : 3;
+ unsigned char HR2 : 4;
+ unsigned char HB1c : 1;
+ // Byte 4
+ unsigned char Hdb : 1;
+ bool Hflipbit : 1;
+ unsigned char Hda : 1;
+ unsigned char HB2 : 4;
+ unsigned char HG2b : 1;
+ } hm;
+ } mode;
+ unsigned char pixelIndexMSB[2];
+ unsigned char pixelIndexLSB[2];
+ } idht;
+ // planar mode
+ struct
+ {
+ // Byte 1
+ unsigned char GO1 : 1;
+ unsigned char RO : 6;
+ unsigned char PdummyA : 1;
+ // Byte 2
+ unsigned char BO1 : 1;
+ unsigned char GO2 : 6;
+ unsigned char PdummyB : 1;
+ // Byte 3
+ unsigned char BO3a : 2;
+ unsigned char PdummyD : 1;
+ unsigned char BO2 : 2;
+ unsigned char PdummyC : 3;
+ // Byte 4
+ unsigned char RH2 : 1;
+ bool Pflipbit : 1;
+ unsigned char RH1 : 5;
+ unsigned char BO3b : 1;
+ // Byte 5
+ unsigned char BHa : 1;
+ unsigned char GH : 7;
+ // Byte 6
+ unsigned char RVa : 3;
+ unsigned char BHb : 5;
+ // Byte 7
+ unsigned char GVa : 5;
+ unsigned char RVb : 3;
+ // Byte 8
+ unsigned char BV : 6;
+ unsigned char GVb : 2;
+ } pblk;
+ // Single channel block
+ struct
+ {
+ union {
+ unsigned char us;
+ signed char s;
+ } base_codeword;
+ unsigned char table_index : 4;
+ unsigned char multiplier : 4;
+ unsigned char mc1 : 2;
+ unsigned char mb : 3;
+ unsigned char ma : 3;
+ unsigned char mf1 : 1;
+ unsigned char me : 3;
+ unsigned char md : 3;
+ unsigned char mc2 : 1;
+ unsigned char mh : 3;
+ unsigned char mg : 3;
+ unsigned char mf2 : 2;
+ unsigned char mk1 : 2;
+ unsigned char mj : 3;
+ unsigned char mi : 3;
+ unsigned char mn1 : 1;
+ unsigned char mm : 3;
+ unsigned char ml : 3;
+ unsigned char mk2 : 1;
+ unsigned char mp : 3;
+ unsigned char mo : 3;
+ unsigned char mn2 : 2;
+ } scblk;
+ } u;
+
+ static unsigned char clampByte(int value)
+ {
+ return static_cast<unsigned char>(gl::clamp(value, 0, 255));
+ }
+
+ static signed char clampSByte(int value)
+ {
+ return static_cast<signed char>(gl::clamp(value, -128, 127));
+ }
+
+ static R8G8B8A8 createRGBA(int red, int green, int blue, int alpha)
+ {
+ R8G8B8A8 rgba;
+ rgba.R = clampByte(red);
+ rgba.G = clampByte(green);
+ rgba.B = clampByte(blue);
+ rgba.A = clampByte(alpha);
+ return rgba;
+ }
+
+ static R8G8B8A8 createRGBA(int red, int green, int blue)
+ {
+ return createRGBA(red, green, blue, 255);
+ }
+
+ static int extend_4to8bits(int x) { return (x << 4) | x; }
+ static int extend_5to8bits(int x) { return (x << 3) | (x >> 2); }
+ static int extend_6to8bits(int x) { return (x << 2) | (x >> 4); }
+ static int extend_7to8bits(int x) { return (x << 1) | (x >> 6); }
+
+ void decodeIndividualBlock(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ size_t destRowPitch,
+ const uint8_t alphaValues[4][4],
+ bool nonOpaquePunchThroughAlpha) const
+ {
+ const auto &block = u.idht.mode.idm.colors.indiv;
+ int r1 = extend_4to8bits(block.R1);
+ int g1 = extend_4to8bits(block.G1);
+ int b1 = extend_4to8bits(block.B1);
+ int r2 = extend_4to8bits(block.R2);
+ int g2 = extend_4to8bits(block.G2);
+ int b2 = extend_4to8bits(block.B2);
+ decodeIndividualOrDifferentialBlock(dest, x, y, w, h, destRowPitch, r1, g1, b1, r2, g2, b2,
+ alphaValues, nonOpaquePunchThroughAlpha);
+ }
+
+ void decodeDifferentialBlock(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ size_t destRowPitch,
+ const uint8_t alphaValues[4][4],
+ bool nonOpaquePunchThroughAlpha) const
+ {
+ const auto &block = u.idht.mode.idm.colors.diff;
+ int b1 = extend_5to8bits(block.B);
+ int g1 = extend_5to8bits(block.G);
+ int r1 = extend_5to8bits(block.R);
+ int r2 = extend_5to8bits(block.R + block.dR);
+ int g2 = extend_5to8bits(block.G + block.dG);
+ int b2 = extend_5to8bits(block.B + block.dB);
+ decodeIndividualOrDifferentialBlock(dest, x, y, w, h, destRowPitch, r1, g1, b1, r2, g2, b2,
+ alphaValues, nonOpaquePunchThroughAlpha);
+ }
+
+ void decodeIndividualOrDifferentialBlock(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ size_t destRowPitch,
+ int r1,
+ int g1,
+ int b1,
+ int r2,
+ int g2,
+ int b2,
+ const uint8_t alphaValues[4][4],
+ bool nonOpaquePunchThroughAlpha) const
+ {
+ const IntensityModifier *intensityModifier =
+ nonOpaquePunchThroughAlpha ? intensityModifierNonOpaque : intensityModifierDefault;
+
+ R8G8B8A8 subblockColors0[4];
+ R8G8B8A8 subblockColors1[4];
+ for (size_t modifierIdx = 0; modifierIdx < 4; modifierIdx++)
+ {
+ const int i1 = intensityModifier[u.idht.mode.idm.cw1][modifierIdx];
+ subblockColors0[modifierIdx] = createRGBA(r1 + i1, g1 + i1, b1 + i1);
+
+ const int i2 = intensityModifier[u.idht.mode.idm.cw2][modifierIdx];
+ subblockColors1[modifierIdx] = createRGBA(r2 + i2, g2 + i2, b2 + i2);
+ }
+
+ if (u.idht.mode.idm.flipbit)
+ {
+ uint8_t *curPixel = dest;
+ for (size_t j = 0; j < 2 && (y + j) < h; j++)
+ {
+ R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
+ for (size_t i = 0; i < 4 && (x + i) < w; i++)
+ {
+ row[i] = subblockColors0[getIndex(i, j)];
+ row[i].A = alphaValues[j][i];
+ }
+ curPixel += destRowPitch;
+ }
+ for (size_t j = 2; j < 4 && (y + j) < h; j++)
+ {
+ R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
+ for (size_t i = 0; i < 4 && (x + i) < w; i++)
+ {
+ row[i] = subblockColors1[getIndex(i, j)];
+ row[i].A = alphaValues[j][i];
+ }
+ curPixel += destRowPitch;
+ }
+ }
+ else
+ {
+ uint8_t *curPixel = dest;
+ for (size_t j = 0; j < 4 && (y + j) < h; j++)
+ {
+ R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
+ for (size_t i = 0; i < 2 && (x + i) < w; i++)
+ {
+ row[i] = subblockColors0[getIndex(i, j)];
+ row[i].A = alphaValues[j][i];
+ }
+ for (size_t i = 2; i < 4 && (x + i) < w; i++)
+ {
+ row[i] = subblockColors1[getIndex(i, j)];
+ row[i].A = alphaValues[j][i];
+ }
+ curPixel += destRowPitch;
+ }
+ }
+ if (nonOpaquePunchThroughAlpha)
+ {
+ decodePunchThroughAlphaBlock(dest, x, y, w, h, destRowPitch);
+ }
+ }
+
+ void decodeTBlock(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ size_t destRowPitch,
+ const uint8_t alphaValues[4][4],
+ bool nonOpaquePunchThroughAlpha) const
+ {
+ // Table C.8, distance index for T and H modes
+ const auto &block = u.idht.mode.tm;
+
+ int r1 = extend_4to8bits(block.TR1a << 2 | block.TR1b);
+ int g1 = extend_4to8bits(block.TG1);
+ int b1 = extend_4to8bits(block.TB1);
+ int r2 = extend_4to8bits(block.TR2);
+ int g2 = extend_4to8bits(block.TG2);
+ int b2 = extend_4to8bits(block.TB2);
+
+ static int distance[8] = {3, 6, 11, 16, 23, 32, 41, 64};
+ const int d = distance[block.Tda << 1 | block.Tdb];
+
+ const R8G8B8A8 paintColors[4] = {
+ createRGBA(r1, g1, b1), createRGBA(r2 + d, g2 + d, b2 + d), createRGBA(r2, g2, b2),
+ createRGBA(r2 - d, g2 - d, b2 - d),
+ };
+
+ uint8_t *curPixel = dest;
+ for (size_t j = 0; j < 4 && (y + j) < h; j++)
+ {
+ R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
+ for (size_t i = 0; i < 4 && (x + i) < w; i++)
+ {
+ row[i] = paintColors[getIndex(i, j)];
+ row[i].A = alphaValues[j][i];
+ }
+ curPixel += destRowPitch;
+ }
+
+ if (nonOpaquePunchThroughAlpha)
+ {
+ decodePunchThroughAlphaBlock(dest, x, y, w, h, destRowPitch);
+ }
+ }
+
+ void decodeHBlock(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ size_t destRowPitch,
+ const uint8_t alphaValues[4][4],
+ bool nonOpaquePunchThroughAlpha) const
+ {
+ // Table C.8, distance index for T and H modes
+ const auto &block = u.idht.mode.hm;
+
+ int r1 = extend_4to8bits(block.HR1);
+ int g1 = extend_4to8bits(block.HG1a << 1 | block.HG1b);
+ int b1 = extend_4to8bits(block.HB1a << 3 | block.HB1b << 1 | block.HB1c);
+ int r2 = extend_4to8bits(block.HR2);
+ int g2 = extend_4to8bits(block.HG2a << 1 | block.HG2b);
+ int b2 = extend_4to8bits(block.HB2);
+
+ static const int distance[8] = {3, 6, 11, 16, 23, 32, 41, 64};
+ const int orderingTrickBit =
+ ((r1 << 16 | g1 << 8 | b1) >= (r2 << 16 | g2 << 8 | b2) ? 1 : 0);
+ const int d = distance[(block.Hda << 2) | (block.Hdb << 1) | orderingTrickBit];
+
+ const R8G8B8A8 paintColors[4] = {
+ createRGBA(r1 + d, g1 + d, b1 + d), createRGBA(r1 - d, g1 - d, b1 - d),
+ createRGBA(r2 + d, g2 + d, b2 + d), createRGBA(r2 - d, g2 - d, b2 - d),
+ };
+
+ uint8_t *curPixel = dest;
+ for (size_t j = 0; j < 4 && (y + j) < h; j++)
+ {
+ R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
+ for (size_t i = 0; i < 4 && (x + i) < w; i++)
+ {
+ row[i] = paintColors[getIndex(i, j)];
+ row[i].A = alphaValues[j][i];
+ }
+ curPixel += destRowPitch;
+ }
+
+ if (nonOpaquePunchThroughAlpha)
+ {
+ decodePunchThroughAlphaBlock(dest, x, y, w, h, destRowPitch);
+ }
+ }
+
+ void decodePlanarBlock(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ size_t pitch,
+ const uint8_t alphaValues[4][4]) const
+ {
+ int ro = extend_6to8bits(u.pblk.RO);
+ int go = extend_7to8bits(u.pblk.GO1 << 6 | u.pblk.GO2);
+ int bo =
+ extend_6to8bits(u.pblk.BO1 << 5 | u.pblk.BO2 << 3 | u.pblk.BO3a << 1 | u.pblk.BO3b);
+ int rh = extend_6to8bits(u.pblk.RH1 << 1 | u.pblk.RH2);
+ int gh = extend_7to8bits(u.pblk.GH);
+ int bh = extend_6to8bits(u.pblk.BHa << 5 | u.pblk.BHb);
+ int rv = extend_6to8bits(u.pblk.RVa << 3 | u.pblk.RVb);
+ int gv = extend_7to8bits(u.pblk.GVa << 2 | u.pblk.GVb);
+ int bv = extend_6to8bits(u.pblk.BV);
+
+ uint8_t *curPixel = dest;
+ for (size_t j = 0; j < 4 && (y + j) < h; j++)
+ {
+ R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
+
+ int ry = static_cast<int>(j) * (rv - ro) + 2;
+ int gy = static_cast<int>(j) * (gv - go) + 2;
+ int by = static_cast<int>(j) * (bv - bo) + 2;
+ for (size_t i = 0; i < 4 && (x + i) < w; i++)
+ {
+ row[i] = createRGBA(((static_cast<int>(i) * (rh - ro) + ry) >> 2) + ro,
+ ((static_cast<int>(i) * (gh - go) + gy) >> 2) + go,
+ ((static_cast<int>(i) * (bh - bo) + by) >> 2) + bo,
+ alphaValues[j][i]);
+ }
+ curPixel += pitch;
+ }
+ }
+
+ // Index for individual, differential, H and T modes
+ size_t getIndex(size_t x, size_t y) const
+ {
+ size_t bitIndex = x * 4 + y;
+ size_t bitOffset = bitIndex & 7;
+ size_t lsb = (u.idht.pixelIndexLSB[1 - (bitIndex >> 3)] >> bitOffset) & 1;
+ size_t msb = (u.idht.pixelIndexMSB[1 - (bitIndex >> 3)] >> bitOffset) & 1;
+ return (msb << 1) | lsb;
+ }
+
+ void decodePunchThroughAlphaBlock(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ size_t destRowPitch) const
+ {
+ uint8_t *curPixel = dest;
+ for (size_t j = 0; j < 4 && (y + j) < h; j++)
+ {
+ R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
+ for (size_t i = 0; i < 4 && (x + i) < w; i++)
+ {
+ if (getIndex(i, j) == 2) // msb == 1 && lsb == 0
+ {
+ row[i] = createRGBA(0, 0, 0, 0);
+ }
+ }
+ curPixel += destRowPitch;
+ }
+ }
+
+ uint16_t RGB8ToRGB565(const R8G8B8A8 &rgba) const
+ {
+ return (static_cast<uint16_t>(rgba.R >> 3) << 11) |
+ (static_cast<uint16_t>(rgba.G >> 2) << 5) |
+ (static_cast<uint16_t>(rgba.B >> 3) << 0);
+ }
+
+ uint32_t matchBC1Bits(const int *pixelIndices,
+ const int *pixelIndexCounts,
+ const R8G8B8A8 *subblockColors,
+ size_t numColors,
+ const R8G8B8A8 &minColor,
+ const R8G8B8A8 &maxColor,
+ bool nonOpaquePunchThroughAlpha) const
+ {
+ // Project each pixel on the (maxColor, minColor) line to decide which
+ // BC1 code to assign to it.
+
+ uint8_t decodedColors[2][3] = {{maxColor.R, maxColor.G, maxColor.B},
+ {minColor.R, minColor.G, minColor.B}};
+
+ int direction[3];
+ for (int ch = 0; ch < 3; ch++)
+ {
+ direction[ch] = decodedColors[0][ch] - decodedColors[1][ch];
+ }
+
+ int stops[2];
+ for (int i = 0; i < 2; i++)
+ {
+ stops[i] = decodedColors[i][0] * direction[0] + decodedColors[i][1] * direction[1] +
+ decodedColors[i][2] * direction[2];
+ }
+
+ ASSERT(numColors <= kNumPixelsInBlock);
+
+ int encodedColors[kNumPixelsInBlock];
+ if (nonOpaquePunchThroughAlpha)
+ {
+ for (size_t i = 0; i < numColors; i++)
+ {
+ const int count = pixelIndexCounts[i];
+ if (count > 0)
+ {
+ // In non-opaque mode, 3 is for tranparent pixels.
+
+ if (0 == subblockColors[i].A)
+ {
+ encodedColors[i] = 3;
+ }
+ else
+ {
+ const R8G8B8A8 &pixel = subblockColors[i];
+ const int dot = pixel.R * direction[0] + pixel.G * direction[1] +
+ pixel.B * direction[2];
+ const int factor = gl::clamp(
+ static_cast<int>(
+ (static_cast<float>(dot - stops[1]) / (stops[0] - stops[1])) * 2 +
+ 0.5f),
+ 0, 2);
+ switch (factor)
+ {
+ case 0:
+ encodedColors[i] = 0;
+ break;
+ case 1:
+ encodedColors[i] = 2;
+ break;
+ case 2:
+ default:
+ encodedColors[i] = 1;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ for (size_t i = 0; i < numColors; i++)
+ {
+ const int count = pixelIndexCounts[i];
+ if (count > 0)
+ {
+ // In opaque mode, the code is from 0 to 3.
+
+ const R8G8B8A8 &pixel = subblockColors[i];
+ const int dot =
+ pixel.R * direction[0] + pixel.G * direction[1] + pixel.B * direction[2];
+ const int factor = gl::clamp(
+ static_cast<int>(
+ (static_cast<float>(dot - stops[1]) / (stops[0] - stops[1])) * 3 +
+ 0.5f),
+ 0, 3);
+ switch (factor)
+ {
+ case 0:
+ encodedColors[i] = 1;
+ break;
+ case 1:
+ encodedColors[i] = 3;
+ break;
+ case 2:
+ encodedColors[i] = 2;
+ break;
+ case 3:
+ default:
+ encodedColors[i] = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ uint32_t bits = 0;
+ for (int i = kNumPixelsInBlock - 1; i >= 0; i--)
+ {
+ bits <<= 2;
+ bits |= encodedColors[pixelIndices[i]];
+ }
+
+ return bits;
+ }
+
+ void packBC1(void *bc1,
+ const int *pixelIndices,
+ const int *pixelIndexCounts,
+ const R8G8B8A8 *subblockColors,
+ size_t numColors,
+ int minColorIndex,
+ int maxColorIndex,
+ bool nonOpaquePunchThroughAlpha) const
+ {
+ const R8G8B8A8 &minColor = subblockColors[minColorIndex];
+ const R8G8B8A8 &maxColor = subblockColors[maxColorIndex];
+
+ uint32_t bits;
+ uint16_t max16 = RGB8ToRGB565(maxColor);
+ uint16_t min16 = RGB8ToRGB565(minColor);
+ if (max16 != min16)
+ {
+ // Find the best BC1 code for each pixel
+ bits = matchBC1Bits(pixelIndices, pixelIndexCounts, subblockColors, numColors, minColor,
+ maxColor, nonOpaquePunchThroughAlpha);
+ }
+ else
+ {
+ // Same colors, BC1 index 0 is the color in both opaque and transparent mode
+ bits = 0;
+ // BC1 index 3 is transparent
+ if (nonOpaquePunchThroughAlpha)
+ {
+ for (int i = 0; i < kNumPixelsInBlock; i++)
+ {
+ if (0 == subblockColors[pixelIndices[i]].A)
+ {
+ bits |= (3 << (i * 2));
+ }
+ }
+ }
+ }
+
+ if (max16 < min16)
+ {
+ std::swap(max16, min16);
+
+ uint32_t xorMask = 0;
+ if (nonOpaquePunchThroughAlpha)
+ {
+ // In transparent mode switching the colors is doing the
+ // following code swap: 0 <-> 1. 0xA selects the second bit of
+ // each code, bits >> 1 selects the first bit of the code when
+ // the seconds bit is set (case 2 and 3). We invert all the
+ // non-selected bits, that is the first bit when the code is
+ // 0 or 1.
+ xorMask = ~((bits >> 1) | 0xAAAAAAAA);
+ }
+ else
+ {
+ // In opaque mode switching the two colors is doing the
+ // following code swaps: 0 <-> 1 and 2 <-> 3. This is
+ // equivalent to flipping the first bit of each code
+ // (5 = 0b0101)
+ xorMask = 0x55555555;
+ }
+ bits ^= xorMask;
+ }
+
+ struct BC1Block
+ {
+ uint16_t color0;
+ uint16_t color1;
+ uint32_t bits;
+ };
+
+ // Encode the opaqueness in the order of the two BC1 colors
+ BC1Block *dest = reinterpret_cast<BC1Block *>(bc1);
+ if (nonOpaquePunchThroughAlpha)
+ {
+ dest->color0 = min16;
+ dest->color1 = max16;
+ }
+ else
+ {
+ dest->color0 = max16;
+ dest->color1 = min16;
+ }
+ dest->bits = bits;
+ }
+
+ void transcodeIndividualBlockToBC1(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ const uint8_t alphaValues[4][4],
+ bool nonOpaquePunchThroughAlpha) const
+ {
+ const auto &block = u.idht.mode.idm.colors.indiv;
+ int r1 = extend_4to8bits(block.R1);
+ int g1 = extend_4to8bits(block.G1);
+ int b1 = extend_4to8bits(block.B1);
+ int r2 = extend_4to8bits(block.R2);
+ int g2 = extend_4to8bits(block.G2);
+ int b2 = extend_4to8bits(block.B2);
+ transcodeIndividualOrDifferentialBlockToBC1(dest, x, y, w, h, r1, g1, b1, r2, g2, b2,
+ alphaValues, nonOpaquePunchThroughAlpha);
+ }
+
+ void transcodeDifferentialBlockToBC1(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ const uint8_t alphaValues[4][4],
+ bool nonOpaquePunchThroughAlpha) const
+ {
+ const auto &block = u.idht.mode.idm.colors.diff;
+ int b1 = extend_5to8bits(block.B);
+ int g1 = extend_5to8bits(block.G);
+ int r1 = extend_5to8bits(block.R);
+ int r2 = extend_5to8bits(block.R + block.dR);
+ int g2 = extend_5to8bits(block.G + block.dG);
+ int b2 = extend_5to8bits(block.B + block.dB);
+ transcodeIndividualOrDifferentialBlockToBC1(dest, x, y, w, h, r1, g1, b1, r2, g2, b2,
+ alphaValues, nonOpaquePunchThroughAlpha);
+ }
+
+ void extractPixelIndices(int *pixelIndices,
+ int *pixelIndicesCounts,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ bool flipbit,
+ size_t subblockIdx) const
+ {
+ size_t dxBegin = 0;
+ size_t dxEnd = 4;
+ size_t dyBegin = subblockIdx * 2;
+ size_t dyEnd = dyBegin + 2;
+ if (!flipbit)
+ {
+ std::swap(dxBegin, dyBegin);
+ std::swap(dxEnd, dyEnd);
+ }
+
+ for (size_t j = dyBegin; j < dyEnd; j++)
+ {
+ int *row = &pixelIndices[j * 4];
+ for (size_t i = dxBegin; i < dxEnd; i++)
+ {
+ const size_t pixelIndex = subblockIdx * 4 + getIndex(i, j);
+ row[i] = static_cast<int>(pixelIndex);
+ pixelIndicesCounts[pixelIndex]++;
+ }
+ }
+ }
+
+ void selectEndPointPCA(const int *pixelIndexCounts,
+ const R8G8B8A8 *subblockColors,
+ size_t numColors,
+ int *minColorIndex,
+ int *maxColorIndex) const
+ {
+ // determine color distribution
+ int mu[3], min[3], max[3];
+ for (int ch = 0; ch < 3; ch++)
+ {
+ int muv = 0;
+ int minv = 255;
+ int maxv = 0;
+ for (size_t i = 0; i < numColors; i++)
+ {
+ const int count = pixelIndexCounts[i];
+ if (count > 0)
+ {
+ const auto &pixel = subblockColors[i];
+ if (pixel.A > 0)
+ {
+ // Non-transparent pixels
+ muv += (&pixel.R)[ch] * count;
+ minv = std::min<int>(minv, (&pixel.R)[ch]);
+ maxv = std::max<int>(maxv, (&pixel.R)[ch]);
+ }
+ }
+ }
+
+ mu[ch] = (muv + kNumPixelsInBlock / 2) / kNumPixelsInBlock;
+ min[ch] = minv;
+ max[ch] = maxv;
+ }
+
+ // determine covariance matrix
+ int cov[6] = {0, 0, 0, 0, 0, 0};
+ for (size_t i = 0; i < numColors; i++)
+ {
+ const int count = pixelIndexCounts[i];
+ if (count > 0)
+ {
+ const auto &pixel = subblockColors[i];
+ if (pixel.A > 0)
+ {
+ int r = pixel.R - mu[0];
+ int g = pixel.G - mu[1];
+ int b = pixel.B - mu[2];
+
+ cov[0] += r * r * count;
+ cov[1] += r * g * count;
+ cov[2] += r * b * count;
+ cov[3] += g * g * count;
+ cov[4] += g * b * count;
+ cov[5] += b * b * count;
+ }
+ }
+ }
+
+ // Power iteration algorithm to get the eigenvalues and eigenvector
+
+ // Starts with diagonal vector
+ float vfr = static_cast<float>(max[0] - min[0]);
+ float vfg = static_cast<float>(max[1] - min[1]);
+ float vfb = static_cast<float>(max[2] - min[2]);
+ float eigenvalue;
+
+ static const size_t kPowerIterations = 4;
+ for (size_t i = 0; i < kPowerIterations; i++)
+ {
+ float r = vfr * cov[0] + vfg * cov[1] + vfb * cov[2];
+ float g = vfr * cov[1] + vfg * cov[3] + vfb * cov[4];
+ float b = vfr * cov[2] + vfg * cov[4] + vfb * cov[5];
+
+ vfr = r;
+ vfg = g;
+ vfb = b;
+
+ eigenvalue = sqrt(r * r + g * g + b * b);
+ if (eigenvalue > 0)
+ {
+ float invNorm = 1.0f / eigenvalue;
+ vfr *= invNorm;
+ vfg *= invNorm;
+ vfb *= invNorm;
+ }
+ }
+
+ int vr, vg, vb;
+
+ static const float kDefaultLuminanceThreshold = 4.0f * 255;
+ static const float kQuantizeRange = 512.0f;
+ if (eigenvalue < kDefaultLuminanceThreshold) // too small, default to luminance
+ {
+ // Luminance weights defined by ITU-R Recommendation BT.601, scaled by 1000
+ vr = 299;
+ vg = 587;
+ vb = 114;
+ }
+ else
+ {
+ // From the eigenvalue and eigenvector, choose the axis to project
+ // colors on. When projecting colors we want to do integer computations
+ // for speed, so we normalize the eigenvector to the [0, 512] range.
+ float magn = std::max(std::max(std::abs(vfr), std::abs(vfg)), std::abs(vfb));
+ magn = kQuantizeRange / magn;
+ vr = static_cast<int>(vfr * magn);
+ vg = static_cast<int>(vfg * magn);
+ vb = static_cast<int>(vfb * magn);
+ }
+
+ // Pick colors at extreme points
+ int minD = INT_MAX;
+ int maxD = 0;
+ size_t minIndex = 0;
+ size_t maxIndex = 0;
+ for (size_t i = 0; i < numColors; i++)
+ {
+ const int count = pixelIndexCounts[i];
+ if (count > 0)
+ {
+ const auto &pixel = subblockColors[i];
+ if (pixel.A > 0)
+ {
+ int dot = pixel.R * vr + pixel.G * vg + pixel.B * vb;
+ if (dot < minD)
+ {
+ minD = dot;
+ minIndex = i;
+ }
+ if (dot > maxD)
+ {
+ maxD = dot;
+ maxIndex = i;
+ }
+ }
+ }
+ }
+
+ *minColorIndex = static_cast<int>(minIndex);
+ *maxColorIndex = static_cast<int>(maxIndex);
+ }
+
+ void transcodeIndividualOrDifferentialBlockToBC1(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ int r1,
+ int g1,
+ int b1,
+ int r2,
+ int g2,
+ int b2,
+ const uint8_t alphaValues[4][4],
+ bool nonOpaquePunchThroughAlpha) const
+ {
+ // A BC1 block has 2 endpoints, pixels is encoded as linear
+ // interpolations of them. A ETC1/ETC2 individual or differential block
+ // has 2 subblocks. Each subblock has one color and a modifier. We
+ // select axis by principal component analysis (PCA) to use as
+ // our two BC1 endpoints and then map pixels to BC1 by projecting on the
+ // line between the two endpoints and choosing the right fraction.
+
+ // The goal of this algorithm is make it faster than decode ETC to RGBs
+ // and then encode to BC. To achieve this, we only extract subblock
+ // colors, pixel indices, and counts of each pixel indices from ETC.
+ // With those information, we can only encode used subblock colors
+ // to BC1, and copy the bits to the right pixels.
+ // Fully decode and encode need to process 16 RGBA pixels. With this
+ // algorithm, it's 8 pixels at maximum for a individual or
+ // differential block. Saves us bandwidth and computations.
+
+ static const size_t kNumColors = 8;
+
+ const IntensityModifier *intensityModifier =
+ nonOpaquePunchThroughAlpha ? intensityModifierNonOpaque : intensityModifierDefault;
+
+ // Compute the colors that pixels can have in each subblock both for
+ // the decoding of the RGBA data and BC1 encoding
+ R8G8B8A8 subblockColors[kNumColors];
+ for (size_t modifierIdx = 0; modifierIdx < 4; modifierIdx++)
+ {
+ if (nonOpaquePunchThroughAlpha && (modifierIdx == 2))
+ {
+ // In ETC opaque punch through formats, individual and
+ // differential blocks take index 2 as transparent pixel.
+ // Thus we don't need to compute its color, just assign it
+ // as black.
+ subblockColors[modifierIdx] = createRGBA(0, 0, 0, 0);
+ subblockColors[4 + modifierIdx] = createRGBA(0, 0, 0, 0);
+ }
+ else
+ {
+ const int i1 = intensityModifier[u.idht.mode.idm.cw1][modifierIdx];
+ subblockColors[modifierIdx] = createRGBA(r1 + i1, g1 + i1, b1 + i1);
+
+ const int i2 = intensityModifier[u.idht.mode.idm.cw2][modifierIdx];
+ subblockColors[4 + modifierIdx] = createRGBA(r2 + i2, g2 + i2, b2 + i2);
+ }
+ }
+
+ int pixelIndices[kNumPixelsInBlock];
+ int pixelIndexCounts[kNumColors] = {0};
+ // Extract pixel indices from a ETC block.
+ for (size_t blockIdx = 0; blockIdx < 2; blockIdx++)
+ {
+ extractPixelIndices(pixelIndices, pixelIndexCounts, x, y, w, h, u.idht.mode.idm.flipbit,
+ blockIdx);
+ }
+
+ int minColorIndex, maxColorIndex;
+ selectEndPointPCA(pixelIndexCounts, subblockColors, kNumColors, &minColorIndex,
+ &maxColorIndex);
+
+ packBC1(dest, pixelIndices, pixelIndexCounts, subblockColors, kNumColors, minColorIndex,
+ maxColorIndex, nonOpaquePunchThroughAlpha);
+ }
+
+ void transcodeTBlockToBC1(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ const uint8_t alphaValues[4][4],
+ bool nonOpaquePunchThroughAlpha) const
+ {
+ static const size_t kNumColors = 4;
+
+ // Table C.8, distance index for T and H modes
+ const auto &block = u.idht.mode.tm;
+
+ int r1 = extend_4to8bits(block.TR1a << 2 | block.TR1b);
+ int g1 = extend_4to8bits(block.TG1);
+ int b1 = extend_4to8bits(block.TB1);
+ int r2 = extend_4to8bits(block.TR2);
+ int g2 = extend_4to8bits(block.TG2);
+ int b2 = extend_4to8bits(block.TB2);
+
+ static int distance[8] = {3, 6, 11, 16, 23, 32, 41, 64};
+ const int d = distance[block.Tda << 1 | block.Tdb];
+
+ // In ETC opaque punch through formats, index == 2 means transparent pixel.
+ // Thus we don't need to compute its color, just assign it as black.
+ const R8G8B8A8 paintColors[kNumColors] = {
+ createRGBA(r1, g1, b1), createRGBA(r2 + d, g2 + d, b2 + d),
+ nonOpaquePunchThroughAlpha ? createRGBA(0, 0, 0, 0) : createRGBA(r2, g2, b2),
+ createRGBA(r2 - d, g2 - d, b2 - d),
+ };
+
+ int pixelIndices[kNumPixelsInBlock];
+ int pixelIndexCounts[kNumColors] = {0};
+ for (size_t j = 0; j < 4; j++)
+ {
+ int *row = &pixelIndices[j * 4];
+ for (size_t i = 0; i < 4; i++)
+ {
+ const size_t pixelIndex = getIndex(i, j);
+ row[i] = static_cast<int>(pixelIndex);
+ pixelIndexCounts[pixelIndex]++;
+ }
+ }
+
+ int minColorIndex, maxColorIndex;
+ selectEndPointPCA(pixelIndexCounts, paintColors, kNumColors, &minColorIndex,
+ &maxColorIndex);
+
+ packBC1(dest, pixelIndices, pixelIndexCounts, paintColors, kNumColors, minColorIndex,
+ maxColorIndex, nonOpaquePunchThroughAlpha);
+ }
+
+ void transcodeHBlockToBC1(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ const uint8_t alphaValues[4][4],
+ bool nonOpaquePunchThroughAlpha) const
+ {
+ static const size_t kNumColors = 4;
+
+ // Table C.8, distance index for T and H modes
+ const auto &block = u.idht.mode.hm;
+
+ int r1 = extend_4to8bits(block.HR1);
+ int g1 = extend_4to8bits(block.HG1a << 1 | block.HG1b);
+ int b1 = extend_4to8bits(block.HB1a << 3 | block.HB1b << 1 | block.HB1c);
+ int r2 = extend_4to8bits(block.HR2);
+ int g2 = extend_4to8bits(block.HG2a << 1 | block.HG2b);
+ int b2 = extend_4to8bits(block.HB2);
+
+ static const int distance[8] = {3, 6, 11, 16, 23, 32, 41, 64};
+ const int orderingTrickBit =
+ ((r1 << 16 | g1 << 8 | b1) >= (r2 << 16 | g2 << 8 | b2) ? 1 : 0);
+ const int d = distance[(block.Hda << 2) | (block.Hdb << 1) | orderingTrickBit];
+
+ // In ETC opaque punch through formats, index == 2 means transparent pixel.
+ // Thus we don't need to compute its color, just assign it as black.
+ const R8G8B8A8 paintColors[kNumColors] = {
+ createRGBA(r1 + d, g1 + d, b1 + d), createRGBA(r1 - d, g1 - d, b1 - d),
+ nonOpaquePunchThroughAlpha ? createRGBA(0, 0, 0, 0)
+ : createRGBA(r2 + d, g2 + d, b2 + d),
+ createRGBA(r2 - d, g2 - d, b2 - d),
+ };
+
+ int pixelIndices[kNumPixelsInBlock];
+ int pixelIndexCounts[kNumColors] = {0};
+ for (size_t j = 0; j < 4; j++)
+ {
+ int *row = &pixelIndices[j * 4];
+ for (size_t i = 0; i < 4; i++)
+ {
+ const size_t pixelIndex = getIndex(i, j);
+ row[i] = static_cast<int>(pixelIndex);
+ pixelIndexCounts[pixelIndex]++;
+ }
+ }
+
+ int minColorIndex, maxColorIndex;
+ selectEndPointPCA(pixelIndexCounts, paintColors, kNumColors, &minColorIndex,
+ &maxColorIndex);
+
+ packBC1(dest, pixelIndices, pixelIndexCounts, paintColors, kNumColors, minColorIndex,
+ maxColorIndex, nonOpaquePunchThroughAlpha);
+ }
+
+ void transcodePlanarBlockToBC1(uint8_t *dest,
+ size_t x,
+ size_t y,
+ size_t w,
+ size_t h,
+ const uint8_t alphaValues[4][4]) const
+ {
+ static const size_t kNumColors = kNumPixelsInBlock;
+
+ R8G8B8A8 rgbaBlock[kNumColors];
+ decodePlanarBlock(reinterpret_cast<uint8_t *>(rgbaBlock), x, y, w, h, sizeof(R8G8B8A8) * 4,
+ alphaValues);
+
+ // Planar block doesn't have a color table, fill indices as full
+ int pixelIndices[kNumPixelsInBlock] = {0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15};
+ int pixelIndexCounts[kNumColors] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
+
+ int minColorIndex, maxColorIndex;
+ selectEndPointPCA(pixelIndexCounts, rgbaBlock, kNumColors, &minColorIndex, &maxColorIndex);
+
+ packBC1(dest, pixelIndices, pixelIndexCounts, rgbaBlock, kNumColors, minColorIndex,
+ maxColorIndex, false);
+ }
+
+ // Single channel utility functions
+ int getSingleChannel(size_t x, size_t y, bool isSigned) const
+ {
+ int codeword = isSigned ? u.scblk.base_codeword.s : u.scblk.base_codeword.us;
+ return codeword + getSingleChannelModifier(x, y) * u.scblk.multiplier;
+ }
+
+ int getSingleChannelIndex(size_t x, size_t y) const
+ {
+ ASSERT(x < 4 && y < 4);
+
+ // clang-format off
+ switch (x * 4 + y)
+ {
+ case 0: return u.scblk.ma;
+ case 1: return u.scblk.mb;
+ case 2: return u.scblk.mc1 << 1 | u.scblk.mc2;
+ case 3: return u.scblk.md;
+ case 4: return u.scblk.me;
+ case 5: return u.scblk.mf1 << 2 | u.scblk.mf2;
+ case 6: return u.scblk.mg;
+ case 7: return u.scblk.mh;
+ case 8: return u.scblk.mi;
+ case 9: return u.scblk.mj;
+ case 10: return u.scblk.mk1 << 1 | u.scblk.mk2;
+ case 11: return u.scblk.ml;
+ case 12: return u.scblk.mm;
+ case 13: return u.scblk.mn1 << 2 | u.scblk.mn2;
+ case 14: return u.scblk.mo;
+ case 15: return u.scblk.mp;
+ default: UNREACHABLE(); return 0;
+ }
+ // clang-format on
+ }
+
+ int getSingleChannelModifier(size_t x, size_t y) const
+ {
+ // clang-format off
+ static const int modifierTable[16][8] =
+ {
+ { -3, -6, -9, -15, 2, 5, 8, 14 },
+ { -3, -7, -10, -13, 2, 6, 9, 12 },
+ { -2, -5, -8, -13, 1, 4, 7, 12 },
+ { -2, -4, -6, -13, 1, 3, 5, 12 },
+ { -3, -6, -8, -12, 2, 5, 7, 11 },
+ { -3, -7, -9, -11, 2, 6, 8, 10 },
+ { -4, -7, -8, -11, 3, 6, 7, 10 },
+ { -3, -5, -8, -11, 2, 4, 7, 10 },
+ { -2, -6, -8, -10, 1, 5, 7, 9 },
+ { -2, -5, -8, -10, 1, 4, 7, 9 },
+ { -2, -4, -8, -10, 1, 3, 7, 9 },
+ { -2, -5, -7, -10, 1, 4, 6, 9 },
+ { -3, -4, -7, -10, 2, 3, 6, 9 },
+ { -1, -2, -3, -10, 0, 1, 2, 9 },
+ { -4, -6, -8, -9, 3, 5, 7, 8 },
+ { -3, -5, -7, -9, 2, 4, 6, 8 }
+ };
+ // clang-format on
+
+ return modifierTable[u.scblk.table_index][getSingleChannelIndex(x, y)];
+ }
+};
+
+// clang-format off
+static const uint8_t DefaultETCAlphaValues[4][4] =
+{
+ { 255, 255, 255, 255 },
+ { 255, 255, 255, 255 },
+ { 255, 255, 255, 255 },
+ { 255, 255, 255, 255 },
+};
+// clang-format on
+
+void LoadR11EACToR8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch,
+ bool isSigned)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y += 4)
+ {
+ const ETC2Block *sourceRow =
+ priv::OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
+ uint8_t *destRow =
+ priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+
+ for (size_t x = 0; x < width; x += 4)
+ {
+ const ETC2Block *sourceBlock = sourceRow + (x / 4);
+ uint8_t *destPixels = destRow + x;
+
+ sourceBlock->decodeAsSingleChannel(destPixels, x, y, width, height, 1,
+ outputRowPitch, isSigned);
+ }
+ }
+ }
+}
+
+void LoadRG11EACToRG8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch,
+ bool isSigned)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y += 4)
+ {
+ const ETC2Block *sourceRow =
+ priv::OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
+ uint8_t *destRow =
+ priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+
+ for (size_t x = 0; x < width; x += 4)
+ {
+ uint8_t *destPixelsRed = destRow + (x * 2);
+ const ETC2Block *sourceBlockRed = sourceRow + (x / 2);
+ sourceBlockRed->decodeAsSingleChannel(destPixelsRed, x, y, width, height, 2,
+ outputRowPitch, isSigned);
+
+ uint8_t *destPixelsGreen = destPixelsRed + 1;
+ const ETC2Block *sourceBlockGreen = sourceBlockRed + 1;
+ sourceBlockGreen->decodeAsSingleChannel(destPixelsGreen, x, y, width, height, 2,
+ outputRowPitch, isSigned);
+ }
+ }
+ }
+}
+
+void LoadETC2RGB8ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch,
+ bool punchthroughAlpha)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y += 4)
+ {
+ const ETC2Block *sourceRow =
+ priv::OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
+ uint8_t *destRow =
+ priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+
+ for (size_t x = 0; x < width; x += 4)
+ {
+ const ETC2Block *sourceBlock = sourceRow + (x / 4);
+ uint8_t *destPixels = destRow + (x * 4);
+
+ sourceBlock->decodeAsRGB(destPixels, x, y, width, height, outputRowPitch,
+ DefaultETCAlphaValues, punchthroughAlpha);
+ }
+ }
+ }
+}
+
+void LoadETC2RGB8ToBC1(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch,
+ bool punchthroughAlpha)
+{
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y += 4)
+ {
+ const ETC2Block *sourceRow =
+ priv::OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
+ uint8_t *destRow = priv::OffsetDataPointer<uint8_t>(output, y / 4, z, outputRowPitch,
+ outputDepthPitch);
+
+ for (size_t x = 0; x < width; x += 4)
+ {
+ const ETC2Block *sourceBlock = sourceRow + (x / 4);
+ uint8_t *destPixels = destRow + (x * 2);
+
+ sourceBlock->transcodeAsBC1(destPixels, x, y, width, height, DefaultETCAlphaValues,
+ punchthroughAlpha);
+ }
+ }
+ }
+}
+
+void LoadETC2RGBA8ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch,
+ bool srgb)
+{
+ uint8_t decodedAlphaValues[4][4];
+
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y += 4)
+ {
+ const ETC2Block *sourceRow =
+ priv::OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
+ uint8_t *destRow =
+ priv::OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
+
+ for (size_t x = 0; x < width; x += 4)
+ {
+ const ETC2Block *sourceBlockAlpha = sourceRow + (x / 2);
+ sourceBlockAlpha->decodeAsSingleChannel(
+ reinterpret_cast<uint8_t *>(decodedAlphaValues), x, y, width, height, 1, 4,
+ false);
+
+ uint8_t *destPixels = destRow + (x * 4);
+ const ETC2Block *sourceBlockRGB = sourceBlockAlpha + 1;
+ sourceBlockRGB->decodeAsRGB(destPixels, x, y, width, height, outputRowPitch,
+ decodedAlphaValues, false);
+ }
+ }
+ }
+}
+
+} // anonymous namespace
+
+void LoadETC1RGB8ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, false);
+}
+
+void LoadETC1RGB8ToBC1(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ LoadETC2RGB8ToBC1(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, false);
+}
+
+void LoadEACR11ToR8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ LoadR11EACToR8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, false);
+}
+
+void LoadEACR11SToR8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ LoadR11EACToR8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, true);
+}
+
+void LoadEACRG11ToRG8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ LoadRG11EACToRG8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, false);
+}
+
+void LoadEACRG11SToRG8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ LoadRG11EACToRG8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, true);
+}
+
+void LoadETC2RGB8ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, false);
+}
+
+void LoadETC2RGB8ToBC1(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ LoadETC2RGB8ToBC1(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, false);
+}
+
+void LoadETC2SRGB8ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, false);
+}
+
+void LoadETC2SRGB8ToBC1(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ LoadETC2RGB8ToBC1(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, false);
+}
+
+void LoadETC2RGB8A1ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, true);
+}
+
+void LoadETC2RGB8A1ToBC1(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ LoadETC2RGB8ToBC1(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, true);
+}
+
+void LoadETC2SRGB8A1ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, true);
+}
+
+void LoadETC2SRGB8A1ToBC1(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ LoadETC2RGB8ToBC1(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, true);
+}
+
+void LoadETC2RGBA8ToRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ LoadETC2RGBA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, false);
+}
+
+void LoadETC2SRGBA8ToSRGBA8(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ LoadETC2RGBA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
+ outputRowPitch, outputDepthPitch, true);
+}
+
+} // namespace angle
diff --git a/src/3rdparty/angle/src/libANGLE/AttributeMap.cpp b/src/3rdparty/angle/src/libANGLE/AttributeMap.cpp
index 651a012037..e10d3add7c 100644
--- a/src/3rdparty/angle/src/libANGLE/AttributeMap.cpp
+++ b/src/3rdparty/angle/src/libANGLE/AttributeMap.cpp
@@ -6,6 +6,8 @@
#include "libANGLE/AttributeMap.h"
+#include "common/debug.h"
+
namespace egl
{
@@ -13,33 +15,61 @@ AttributeMap::AttributeMap()
{
}
-AttributeMap::AttributeMap(const EGLint *attributes)
-{
- if (attributes)
- {
- for (const EGLint *curAttrib = attributes; curAttrib[0] != EGL_NONE; curAttrib += 2)
- {
- insert(curAttrib[0], curAttrib[1]);
- }
- }
-}
+AttributeMap::AttributeMap(const AttributeMap &other) = default;
-void AttributeMap::insert(EGLint key, EGLint value)
+AttributeMap::~AttributeMap() = default;
+
+void AttributeMap::insert(EGLAttrib key, EGLAttrib value)
{
mAttributes[key] = value;
}
-bool AttributeMap::contains(EGLint key) const
+bool AttributeMap::contains(EGLAttrib key) const
{
return (mAttributes.find(key) != mAttributes.end());
}
-EGLint AttributeMap::get(EGLint key, EGLint defaultValue) const
+EGLAttrib AttributeMap::get(EGLAttrib key) const
+{
+ auto iter = mAttributes.find(key);
+ ASSERT(iter != mAttributes.end());
+ return iter->second;
+}
+
+EGLAttrib AttributeMap::get(EGLAttrib key, EGLAttrib defaultValue) const
{
- std::map<EGLint, EGLint>::const_iterator iter = mAttributes.find(key);
+ auto iter = mAttributes.find(key);
return (mAttributes.find(key) != mAttributes.end()) ? iter->second : defaultValue;
}
+EGLint AttributeMap::getAsInt(EGLAttrib key) const
+{
+ return static_cast<EGLint>(get(key));
+}
+
+EGLint AttributeMap::getAsInt(EGLAttrib key, EGLint defaultValue) const
+{
+ return static_cast<EGLint>(get(key, static_cast<EGLAttrib>(defaultValue)));
+}
+
+bool AttributeMap::isEmpty() const
+{
+ return mAttributes.empty();
+}
+
+std::vector<EGLint> AttributeMap::toIntVector() const
+{
+ std::vector<EGLint> ret;
+ for (const auto &pair : mAttributes)
+ {
+ ret.push_back(static_cast<EGLint>(pair.first));
+ ret.push_back(static_cast<EGLint>(pair.second));
+ }
+ ret.push_back(EGL_NONE);
+
+ return ret;
+}
+
AttributeMap::const_iterator AttributeMap::begin() const
{
return mAttributes.begin();
@@ -50,4 +80,31 @@ AttributeMap::const_iterator AttributeMap::end() const
return mAttributes.end();
}
+// static
+AttributeMap AttributeMap::CreateFromIntArray(const EGLint *attributes)
+{
+ AttributeMap map;
+ if (attributes)
+ {
+ for (const EGLint *curAttrib = attributes; curAttrib[0] != EGL_NONE; curAttrib += 2)
+ {
+ map.insert(static_cast<EGLAttrib>(curAttrib[0]), static_cast<EGLAttrib>(curAttrib[1]));
+ }
+ }
+ return map;
+}
+
+// static
+AttributeMap AttributeMap::CreateFromAttribArray(const EGLAttrib *attributes)
+{
+ AttributeMap map;
+ if (attributes)
+ {
+ for (const EGLAttrib *curAttrib = attributes; curAttrib[0] != EGL_NONE; curAttrib += 2)
+ {
+ map.insert(curAttrib[0], curAttrib[1]);
+ }
+ }
+ return map;
+}
}
diff --git a/src/3rdparty/angle/src/libANGLE/AttributeMap.h b/src/3rdparty/angle/src/libANGLE/AttributeMap.h
index 56f1684415..eddc1b72d0 100644
--- a/src/3rdparty/angle/src/libANGLE/AttributeMap.h
+++ b/src/3rdparty/angle/src/libANGLE/AttributeMap.h
@@ -11,6 +11,7 @@
#include <EGL/egl.h>
#include <map>
+#include <vector>
namespace egl
{
@@ -19,19 +20,28 @@ class AttributeMap final
{
public:
AttributeMap();
- explicit AttributeMap(const EGLint *attributes);
+ AttributeMap(const AttributeMap &other);
+ ~AttributeMap();
- void insert(EGLint key, EGLint value);
- bool contains(EGLint key) const;
- EGLint get(EGLint key, EGLint defaultValue) const;
+ void insert(EGLAttrib key, EGLAttrib value);
+ bool contains(EGLAttrib key) const;
+ EGLAttrib get(EGLAttrib key) const;
+ EGLAttrib get(EGLAttrib key, EGLAttrib defaultValue) const;
+ EGLint getAsInt(EGLAttrib key) const;
+ EGLint getAsInt(EGLAttrib key, EGLint defaultValue) const;
+ bool isEmpty() const;
+ std::vector<EGLint> toIntVector() const;
- typedef std::map<EGLint, EGLint>::const_iterator const_iterator;
+ typedef std::map<EGLAttrib, EGLAttrib>::const_iterator const_iterator;
const_iterator begin() const;
const_iterator end() const;
+ static AttributeMap CreateFromIntArray(const EGLint *attributes);
+ static AttributeMap CreateFromAttribArray(const EGLAttrib *attributes);
+
private:
- std::map<EGLint, EGLint> mAttributes;
+ std::map<EGLAttrib, EGLAttrib> mAttributes;
};
}
diff --git a/src/3rdparty/angle/src/libANGLE/BinaryStream.h b/src/3rdparty/angle/src/libANGLE/BinaryStream.h
index 3e6ccc7446..3e4c0934cf 100644
--- a/src/3rdparty/angle/src/libANGLE/BinaryStream.h
+++ b/src/3rdparty/angle/src/libANGLE/BinaryStream.h
@@ -9,25 +9,13 @@
#ifndef LIBANGLE_BINARYSTREAM_H_
#define LIBANGLE_BINARYSTREAM_H_
-#include "common/angleutils.h"
-#include "common/mathutil.h"
-
#include <cstddef>
#include <string>
#include <vector>
#include <stdint.h>
-template <typename T>
-void StaticAssertIsFundamental()
-{
- // c++11 STL is not available on OSX or Android
-#if !defined(ANGLE_PLATFORM_APPLE) && !defined(ANGLE_PLATFORM_ANDROID)
- static_assert(std::is_fundamental<T>::value, "T must be a fundamental type.");
-#else
- union { T dummy; } dummy;
- static_cast<void>(dummy);
-#endif
-}
+#include "common/angleutils.h"
+#include "common/mathutil.h"
namespace gl
{
@@ -58,6 +46,16 @@ class BinaryInputStream : angle::NonCopyable
*outValue = readInt<IntT>();
}
+ template <class IntT, class VectorElementT>
+ void readIntVector(std::vector<VectorElementT> *param)
+ {
+ unsigned int size = readInt<unsigned int>();
+ for (unsigned int index = 0; index < size; ++index)
+ {
+ param->push_back(readInt<IntT>());
+ }
+ }
+
bool readBool()
{
int value = 0;
@@ -92,25 +90,31 @@ class BinaryInputStream : angle::NonCopyable
return;
}
- if (!rx::IsUnsignedAdditionSafe(mOffset, length) || mOffset + length > mLength)
+ angle::CheckedNumeric<size_t> checkedOffset(mOffset);
+ checkedOffset += length;
+
+ if (!checkedOffset.IsValid() || mOffset + length > mLength)
{
mError = true;
return;
}
v->assign(reinterpret_cast<const char *>(mData) + mOffset, length);
- mOffset += length;
+ mOffset = checkedOffset.ValueOrDie();
}
void skip(size_t length)
{
- if (!rx::IsUnsignedAdditionSafe(mOffset, length) || mOffset + length > mLength)
+ angle::CheckedNumeric<size_t> checkedOffset(mOffset);
+ checkedOffset += length;
+
+ if (!checkedOffset.IsValid() || mOffset + length > mLength)
{
mError = true;
return;
}
- mOffset += length;
+ mOffset = checkedOffset.ValueOrDie();
}
size_t offset() const
@@ -142,24 +146,27 @@ class BinaryInputStream : angle::NonCopyable
template <typename T>
void read(T *v, size_t num)
{
- StaticAssertIsFundamental<T>();
+ static_assert(std::is_fundamental<T>::value, "T must be a fundamental type.");
- if (!rx::IsUnsignedMultiplicationSafe(num, sizeof(T)))
+ angle::CheckedNumeric<size_t> checkedLength(num);
+ checkedLength *= sizeof(T);
+ if (!checkedLength.IsValid())
{
mError = true;
return;
}
- size_t length = num * sizeof(T);
+ angle::CheckedNumeric<size_t> checkedOffset(mOffset);
+ checkedOffset += checkedLength;
- if (!rx::IsUnsignedAdditionSafe(mOffset, length) || mOffset + length > mLength)
+ if (!checkedOffset.IsValid() || checkedOffset.ValueOrDie() > mLength)
{
mError = true;
return;
}
- memcpy(v, mData + mOffset, length);
- mOffset += length;
+ memcpy(v, mData + mOffset, checkedLength.ValueOrDie());
+ mOffset = checkedOffset.ValueOrDie();
}
template <typename T>
@@ -173,19 +180,42 @@ class BinaryInputStream : angle::NonCopyable
class BinaryOutputStream : angle::NonCopyable
{
public:
- BinaryOutputStream()
- {
- }
+ BinaryOutputStream();
+ ~BinaryOutputStream();
// writeInt also handles bool types
template <class IntT>
void writeInt(IntT param)
{
- ASSERT(rx::IsIntegerCastSafe<int>(param));
+ ASSERT(angle::IsValueInRangeForNumericType<int>(param));
int intValue = static_cast<int>(param);
write(&intValue, 1);
}
+ // Specialized writeInt for values that can also be exactly -1.
+ template <class UintT>
+ void writeIntOrNegOne(UintT param)
+ {
+ if (param == static_cast<UintT>(-1))
+ {
+ writeInt(-1);
+ }
+ else
+ {
+ writeInt(param);
+ }
+ }
+
+ template <class IntT>
+ void writeIntVector(std::vector<IntT> param)
+ {
+ writeInt(param.size());
+ for (IntT element : param)
+ {
+ writeIntOrNegOne(element);
+ }
+ }
+
void writeString(const std::string &v)
{
writeInt(v.length());
@@ -204,7 +234,7 @@ class BinaryOutputStream : angle::NonCopyable
const void* data() const
{
- return mData.size() ? &mData[0] : NULL;
+ return mData.size() ? &mData[0] : nullptr;
}
private:
@@ -213,12 +243,19 @@ class BinaryOutputStream : angle::NonCopyable
template <typename T>
void write(const T *v, size_t num)
{
- StaticAssertIsFundamental<T>();
+ static_assert(std::is_fundamental<T>::value, "T must be a fundamental type.");
const char *asBytes = reinterpret_cast<const char*>(v);
mData.insert(mData.end(), asBytes, asBytes + num * sizeof(T));
}
};
+
+inline BinaryOutputStream::BinaryOutputStream()
+{
}
+inline BinaryOutputStream::~BinaryOutputStream() = default;
+
+} // namespace gl
+
#endif // LIBANGLE_BINARYSTREAM_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Buffer.cpp b/src/3rdparty/angle/src/libANGLE/Buffer.cpp
index 589735c5a8..a1ebfc1acb 100644
--- a/src/3rdparty/angle/src/libANGLE/Buffer.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Buffer.cpp
@@ -9,123 +9,148 @@
// [OpenGL ES 2.0.24] section 2.9 page 21.
#include "libANGLE/Buffer.h"
+
+#include "libANGLE/Context.h"
#include "libANGLE/renderer/BufferImpl.h"
-#include "libANGLE/renderer/Renderer.h"
+#include "libANGLE/renderer/GLImplFactory.h"
namespace gl
{
-Buffer::Buffer(rx::BufferImpl *impl, GLuint id)
- : RefCountObject(id),
- mBuffer(impl),
- mLabel(),
- mUsage(GL_STATIC_DRAW),
+BufferState::BufferState()
+ : mLabel(),
+ mUsage(BufferUsage::StaticDraw),
mSize(0),
mAccessFlags(0),
mAccess(GL_WRITE_ONLY_OES),
mMapped(GL_FALSE),
- mMapPointer(NULL),
+ mMapPointer(nullptr),
mMapOffset(0),
mMapLength(0)
{
}
+BufferState::~BufferState()
+{
+}
+
+Buffer::Buffer(rx::GLImplFactory *factory, GLuint id)
+ : RefCountObject(id), mImpl(factory->createBuffer(mState))
+{
+}
+
Buffer::~Buffer()
{
- SafeDelete(mBuffer);
+ SafeDelete(mImpl);
+}
+
+Error Buffer::onDestroy(const Context *context)
+{
+ // In tests, mImpl might be null.
+ if (mImpl)
+ mImpl->destroy(context);
+ return NoError();
}
void Buffer::setLabel(const std::string &label)
{
- mLabel = label;
+ mState.mLabel = label;
}
const std::string &Buffer::getLabel() const
{
- return mLabel;
+ return mState.mLabel;
}
-Error Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
+Error Buffer::bufferData(const Context *context,
+ BufferBinding target,
+ const void *data,
+ GLsizeiptr size,
+ BufferUsage usage)
{
- gl::Error error = mBuffer->setData(data, size, usage);
- if (error.isError())
+ const void *dataForImpl = data;
+
+ // If we are using robust resource init, make sure the buffer starts cleared.
+ // Note: the Context is checked for nullptr because of some testing code.
+ // TODO(jmadill): Investigate lazier clearing.
+ if (context && context->getGLState().isRobustResourceInitEnabled() && !data && size > 0)
{
- return error;
+ angle::MemoryBuffer *scratchBuffer = nullptr;
+ ANGLE_TRY(context->getZeroFilledBuffer(static_cast<size_t>(size), &scratchBuffer));
+ dataForImpl = scratchBuffer->data();
}
+ ANGLE_TRY(mImpl->setData(context, target, dataForImpl, size, usage));
+
mIndexRangeCache.clear();
- mUsage = usage;
- mSize = size;
+ mState.mUsage = usage;
+ mState.mSize = size;
- return error;
+ return NoError();
}
-Error Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset)
+Error Buffer::bufferSubData(const Context *context,
+ BufferBinding target,
+ const void *data,
+ GLsizeiptr size,
+ GLintptr offset)
{
- gl::Error error = mBuffer->setSubData(data, size, offset);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mImpl->setSubData(context, target, data, size, offset));
mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset), static_cast<unsigned int>(size));
- return error;
+ return NoError();
}
-Error Buffer::copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size)
+Error Buffer::copyBufferSubData(const Context *context,
+ Buffer *source,
+ GLintptr sourceOffset,
+ GLintptr destOffset,
+ GLsizeiptr size)
{
- gl::Error error = mBuffer->copySubData(source->getImplementation(), sourceOffset, destOffset, size);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(
+ mImpl->copySubData(context, source->getImplementation(), sourceOffset, destOffset, size));
mIndexRangeCache.invalidateRange(static_cast<unsigned int>(destOffset), static_cast<unsigned int>(size));
- return error;
+ return NoError();
}
-Error Buffer::map(GLenum access)
+Error Buffer::map(const Context *context, GLenum access)
{
- ASSERT(!mMapped);
+ ASSERT(!mState.mMapped);
- Error error = mBuffer->map(access, &mMapPointer);
- if (error.isError())
- {
- mMapPointer = NULL;
- return error;
- }
+ mState.mMapPointer = nullptr;
+ ANGLE_TRY(mImpl->map(context, access, &mState.mMapPointer));
ASSERT(access == GL_WRITE_ONLY_OES);
- mMapped = GL_TRUE;
- mMapOffset = 0;
- mMapLength = mSize;
- mAccess = access;
- mAccessFlags = GL_MAP_WRITE_BIT;
+ mState.mMapped = GL_TRUE;
+ mState.mMapOffset = 0;
+ mState.mMapLength = mState.mSize;
+ mState.mAccess = access;
+ mState.mAccessFlags = GL_MAP_WRITE_BIT;
mIndexRangeCache.clear();
- return error;
+ return NoError();
}
-Error Buffer::mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access)
+Error Buffer::mapRange(const Context *context,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access)
{
- ASSERT(!mMapped);
- ASSERT(offset + length <= mSize);
+ ASSERT(!mState.mMapped);
+ ASSERT(offset + length <= mState.mSize);
- Error error = mBuffer->mapRange(offset, length, access, &mMapPointer);
- if (error.isError())
- {
- mMapPointer = NULL;
- return error;
- }
+ mState.mMapPointer = nullptr;
+ ANGLE_TRY(mImpl->mapRange(context, offset, length, access, &mState.mMapPointer));
- mMapped = GL_TRUE;
- mMapOffset = static_cast<GLint64>(offset);
- mMapLength = static_cast<GLint64>(length);
- mAccess = GL_WRITE_ONLY_OES;
- mAccessFlags = access;
+ mState.mMapped = GL_TRUE;
+ mState.mMapOffset = static_cast<GLint64>(offset);
+ mState.mMapLength = static_cast<GLint64>(length);
+ mState.mAccess = GL_WRITE_ONLY_OES;
+ mState.mAccessFlags = access;
// The OES_mapbuffer extension states that GL_WRITE_ONLY_OES is the only valid
// value for GL_BUFFER_ACCESS_OES because it was written against ES2. Since there is
@@ -137,28 +162,24 @@ Error Buffer::mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access)
mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset), static_cast<unsigned int>(length));
}
- return error;
+ return NoError();
}
-Error Buffer::unmap(GLboolean *result)
+Error Buffer::unmap(const Context *context, GLboolean *result)
{
- ASSERT(mMapped);
+ ASSERT(mState.mMapped);
- Error error = mBuffer->unmap(result);
- if (error.isError())
- {
- *result = GL_FALSE;
- return error;
- }
+ *result = GL_FALSE;
+ ANGLE_TRY(mImpl->unmap(context, result));
- mMapped = GL_FALSE;
- mMapPointer = NULL;
- mMapOffset = 0;
- mMapLength = 0;
- mAccess = GL_WRITE_ONLY_OES;
- mAccessFlags = 0;
+ mState.mMapped = GL_FALSE;
+ mState.mMapPointer = nullptr;
+ mState.mMapOffset = 0;
+ mState.mMapLength = 0;
+ mState.mAccess = GL_WRITE_ONLY_OES;
+ mState.mAccessFlags = 0;
- return error;
+ return NoError();
}
void Buffer::onTransformFeedback()
@@ -171,7 +192,8 @@ void Buffer::onPixelUnpack()
mIndexRangeCache.clear();
}
-Error Buffer::getIndexRange(GLenum type,
+Error Buffer::getIndexRange(const gl::Context *context,
+ GLenum type,
size_t offset,
size_t count,
bool primitiveRestartEnabled,
@@ -179,18 +201,15 @@ Error Buffer::getIndexRange(GLenum type,
{
if (mIndexRangeCache.findRange(type, offset, count, primitiveRestartEnabled, outRange))
{
- return gl::Error(GL_NO_ERROR);
+ return NoError();
}
- Error error = mBuffer->getIndexRange(type, offset, count, primitiveRestartEnabled, outRange);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(
+ mImpl->getIndexRange(context, type, offset, count, primitiveRestartEnabled, outRange));
mIndexRangeCache.addRange(type, offset, count, primitiveRestartEnabled, *outRange);
- return Error(GL_NO_ERROR);
+ return NoError();
}
-}
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/Buffer.h b/src/3rdparty/angle/src/libANGLE/Buffer.h
index 6c951ef586..86d4a9fd6f 100644
--- a/src/3rdparty/angle/src/libANGLE/Buffer.h
+++ b/src/3rdparty/angle/src/libANGLE/Buffer.h
@@ -15,69 +15,109 @@
#include "libANGLE/Debug.h"
#include "libANGLE/Error.h"
#include "libANGLE/IndexRangeCache.h"
+#include "libANGLE/PackedGLEnums.h"
#include "libANGLE/RefCountObject.h"
namespace rx
{
class BufferImpl;
+class GLImplFactory;
};
namespace gl
{
+class Buffer;
+class Context;
-class Buffer final : public RefCountObject, public LabeledObject
+class BufferState final : angle::NonCopyable
{
public:
- Buffer(rx::BufferImpl *impl, GLuint id);
- virtual ~Buffer();
+ BufferState();
+ ~BufferState();
- void setLabel(const std::string &label) override;
- const std::string &getLabel() const override;
+ const std::string &getLabel();
- Error bufferData(const void *data, GLsizeiptr size, GLenum usage);
- Error bufferSubData(const void *data, GLsizeiptr size, GLintptr offset);
- Error copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size);
- Error map(GLenum access);
- Error mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access);
- Error unmap(GLboolean *result);
-
- void onTransformFeedback();
- void onPixelUnpack();
-
- Error getIndexRange(GLenum type,
- size_t offset,
- size_t count,
- bool primitiveRestartEnabled,
- IndexRange *outRange) const;
-
- GLenum getUsage() const { return mUsage; }
+ BufferUsage getUsage() const { return mUsage; }
GLbitfield getAccessFlags() const { return mAccessFlags; }
GLenum getAccess() const { return mAccess; }
GLboolean isMapped() const { return mMapped; }
- GLvoid *getMapPointer() const { return mMapPointer; }
+ void *getMapPointer() const { return mMapPointer; }
GLint64 getMapOffset() const { return mMapOffset; }
GLint64 getMapLength() const { return mMapLength; }
GLint64 getSize() const { return mSize; }
- rx::BufferImpl *getImplementation() const { return mBuffer; }
-
private:
- rx::BufferImpl *mBuffer;
+ friend class Buffer;
std::string mLabel;
- GLenum mUsage;
+ BufferUsage mUsage;
GLint64 mSize;
GLbitfield mAccessFlags;
GLenum mAccess;
GLboolean mMapped;
- GLvoid *mMapPointer;
+ void *mMapPointer;
GLint64 mMapOffset;
GLint64 mMapLength;
+};
+
+class Buffer final : public RefCountObject, public LabeledObject
+{
+ public:
+ Buffer(rx::GLImplFactory *factory, GLuint id);
+ ~Buffer() override;
+ Error onDestroy(const Context *context) override;
+
+ void setLabel(const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ Error bufferData(const Context *context,
+ BufferBinding target,
+ const void *data,
+ GLsizeiptr size,
+ BufferUsage usage);
+ Error bufferSubData(const Context *context,
+ BufferBinding target,
+ const void *data,
+ GLsizeiptr size,
+ GLintptr offset);
+ Error copyBufferSubData(const Context *context,
+ Buffer *source,
+ GLintptr sourceOffset,
+ GLintptr destOffset,
+ GLsizeiptr size);
+ Error map(const Context *context, GLenum access);
+ Error mapRange(const Context *context, GLintptr offset, GLsizeiptr length, GLbitfield access);
+ Error unmap(const Context *context, GLboolean *result);
+
+ void onTransformFeedback();
+ void onPixelUnpack();
+
+ Error getIndexRange(const gl::Context *context,
+ GLenum type,
+ size_t offset,
+ size_t count,
+ bool primitiveRestartEnabled,
+ IndexRange *outRange) const;
+
+ BufferUsage getUsage() const { return mState.mUsage; }
+ GLbitfield getAccessFlags() const { return mState.mAccessFlags; }
+ GLenum getAccess() const { return mState.mAccess; }
+ GLboolean isMapped() const { return mState.mMapped; }
+ void *getMapPointer() const { return mState.mMapPointer; }
+ GLint64 getMapOffset() const { return mState.mMapOffset; }
+ GLint64 getMapLength() const { return mState.mMapLength; }
+ GLint64 getSize() const { return mState.mSize; }
+
+ rx::BufferImpl *getImplementation() const { return mImpl; }
+
+ private:
+ BufferState mState;
+ rx::BufferImpl *mImpl;
mutable IndexRangeCache mIndexRangeCache;
};
-}
+} // namespace gl
-#endif // LIBANGLE_BUFFER_H_
+#endif // LIBANGLE_BUFFER_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Caps.cpp b/src/3rdparty/angle/src/libANGLE/Caps.cpp
index 1eb54a1589..44da2bbe27 100644
--- a/src/3rdparty/angle/src/libANGLE/Caps.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Caps.cpp
@@ -5,9 +5,12 @@
//
#include "libANGLE/Caps.h"
+
#include "common/debug.h"
#include "common/angleutils.h"
+#include "libANGLE/formatutils.h"
+
#include "angle_gl.h"
#include <algorithm>
@@ -32,6 +35,10 @@ TextureCaps::TextureCaps()
{
}
+TextureCaps::TextureCaps(const TextureCaps &other) = default;
+
+TextureCaps::~TextureCaps() = default;
+
GLuint TextureCaps::getMaxSamples() const
{
return !sampleCounts.empty() ? *sampleCounts.rbegin() : 0;
@@ -56,40 +63,80 @@ GLuint TextureCaps::getNearestSamples(GLuint requestedSamples) const
return 0;
}
+TextureCaps GenerateMinimumTextureCaps(GLenum sizedInternalFormat,
+ const Version &clientVersion,
+ const Extensions &extensions)
+{
+ TextureCaps caps;
+
+ const InternalFormat &internalFormatInfo = GetSizedInternalFormatInfo(sizedInternalFormat);
+ caps.texturable = internalFormatInfo.textureSupport(clientVersion, extensions);
+ caps.renderable = internalFormatInfo.renderSupport(clientVersion, extensions);
+ caps.filterable = internalFormatInfo.filterSupport(clientVersion, extensions);
+
+ caps.sampleCounts.insert(0);
+ if (internalFormatInfo.isRequiredRenderbufferFormat(clientVersion))
+ {
+ if ((clientVersion.major >= 3 && clientVersion.minor >= 1) ||
+ (clientVersion.major >= 3 && internalFormatInfo.componentType != GL_UNSIGNED_INT &&
+ internalFormatInfo.componentType != GL_INT))
+ {
+ caps.sampleCounts.insert(4);
+ }
+ }
+
+ return caps;
+}
+
+TextureCapsMap::TextureCapsMap()
+{
+}
+
+TextureCapsMap::~TextureCapsMap()
+{
+}
+
void TextureCapsMap::insert(GLenum internalFormat, const TextureCaps &caps)
{
- mCapsMap[internalFormat] = caps;
+ angle::Format::ID formatID = angle::Format::InternalFormatToID(internalFormat);
+ get(formatID) = caps;
}
-void TextureCapsMap::remove(GLenum internalFormat)
+void TextureCapsMap::clear()
{
- InternalFormatToCapsMap::iterator i = mCapsMap.find(internalFormat);
- if (i != mCapsMap.end())
- {
- mCapsMap.erase(i);
- }
+ mFormatData.fill(TextureCaps());
}
const TextureCaps &TextureCapsMap::get(GLenum internalFormat) const
{
- static TextureCaps defaultUnsupportedTexture;
- InternalFormatToCapsMap::const_iterator iter = mCapsMap.find(internalFormat);
- return (iter != mCapsMap.end()) ? iter->second : defaultUnsupportedTexture;
+ angle::Format::ID formatID = angle::Format::InternalFormatToID(internalFormat);
+ return get(formatID);
}
-TextureCapsMap::const_iterator TextureCapsMap::begin() const
+const TextureCaps &TextureCapsMap::get(angle::Format::ID formatID) const
{
- return mCapsMap.begin();
+ return mFormatData[static_cast<size_t>(formatID)];
}
-TextureCapsMap::const_iterator TextureCapsMap::end() const
+TextureCaps &TextureCapsMap::get(angle::Format::ID formatID)
{
- return mCapsMap.end();
+ return mFormatData[static_cast<size_t>(formatID)];
}
-size_t TextureCapsMap::size() const
+void TextureCapsMap::set(angle::Format::ID formatID, const TextureCaps &caps)
{
- return mCapsMap.size();
+ get(formatID) = caps;
+}
+
+void InitMinimumTextureCapsMap(const Version &clientVersion,
+ const Extensions &extensions,
+ TextureCapsMap *capsMap)
+{
+ for (GLenum internalFormat : GetAllSizedInternalFormats())
+ {
+ capsMap->insert(internalFormat,
+ GenerateMinimumTextureCaps(internalFormat, clientVersion, extensions));
+ }
}
Extensions::Extensions()
@@ -111,23 +158,25 @@ Extensions::Extensions()
textureCompressionDXT1(false),
textureCompressionDXT3(false),
textureCompressionDXT5(false),
+ textureCompressionS3TCsRGB(false),
textureCompressionASTCHDR(false),
textureCompressionASTCLDR(false),
compressedETC1RGB8Texture(false),
+ sRGB(false),
depthTextures(false),
depth32(false),
textureStorage(false),
textureNPOT(false),
drawBuffers(false),
textureFilterAnisotropic(false),
- maxTextureAnisotropy(false),
+ maxTextureAnisotropy(0.0f),
occlusionQueryBoolean(false),
fence(false),
- timerQuery(false),
disjointTimerQuery(false),
queryCounterBitsTimeElapsed(0),
queryCounterBitsTimestamp(0),
robustness(false),
+ robustBufferAccessBehavior(false),
blendMinMax(false),
framebufferBlit(false),
framebufferMultisample(false),
@@ -135,10 +184,9 @@ Extensions::Extensions()
packReverseRowOrder(false),
standardDerivatives(false),
shaderTextureLOD(false),
- shaderFramebufferFetch(false),
- ARMshaderFramebufferFetch(false),
- NVshaderFramebufferFetch(false),
fragDepth(false),
+ multiview(false),
+ maxViews(1u),
textureUsage(false),
translatedShaderSource(false),
fboRenderMipmap(false),
@@ -147,6 +195,7 @@ Extensions::Extensions()
eglImage(false),
eglImageExternal(false),
eglImageExternalEssl3(false),
+ eglStreamConsumerExternal(false),
unpackSubimage(false),
packSubimage(false),
vertexArrayObject(false),
@@ -157,7 +206,31 @@ Extensions::Extensions()
maxLabelLength(0),
noError(false),
lossyETCDecode(false),
- colorBufferFloat(false)
+ bindUniformLocation(false),
+ syncQuery(false),
+ copyTexture(false),
+ copyCompressedTexture(false),
+ webglCompatibility(false),
+ requestExtension(false),
+ bindGeneratesResource(false),
+ robustClientMemory(false),
+ textureSRGBDecode(false),
+ sRGBWriteControl(false),
+ colorBufferFloatRGB(false),
+ colorBufferFloatRGBA(false),
+ colorBufferFloat(false),
+ multisampleCompatibility(false),
+ framebufferMixedSamples(false),
+ textureNorm16(false),
+ pathRendering(false),
+ surfacelessContext(false),
+ clientArrays(false),
+ robustResourceInitialization(false),
+ programCacheControl(false),
+ textureRectangle(false),
+ geometryShader(false),
+ maxGeometryOutputVertices(0),
+ maxGeometryShaderInvocations(0)
{
}
@@ -165,70 +238,13 @@ std::vector<std::string> Extensions::getStrings() const
{
std::vector<std::string> extensionStrings;
- // clang-format off
- // | Extension name | Supported flag | Output vector |
- InsertExtensionString("GL_OES_element_index_uint", elementIndexUint, &extensionStrings);
- InsertExtensionString("GL_OES_packed_depth_stencil", packedDepthStencil, &extensionStrings);
- InsertExtensionString("GL_OES_get_program_binary", getProgramBinary, &extensionStrings);
- InsertExtensionString("GL_OES_rgb8_rgba8", rgb8rgba8, &extensionStrings);
- InsertExtensionString("GL_EXT_texture_format_BGRA8888", textureFormatBGRA8888, &extensionStrings);
- InsertExtensionString("GL_EXT_read_format_bgra", readFormatBGRA, &extensionStrings);
- InsertExtensionString("GL_NV_pixel_buffer_object", pixelBufferObject, &extensionStrings);
- InsertExtensionString("GL_OES_mapbuffer", mapBuffer, &extensionStrings);
- InsertExtensionString("GL_EXT_map_buffer_range", mapBufferRange, &extensionStrings);
- InsertExtensionString("GL_EXT_color_buffer_half_float", colorBufferHalfFloat, &extensionStrings);
- InsertExtensionString("GL_OES_texture_half_float", textureHalfFloat, &extensionStrings);
- InsertExtensionString("GL_OES_texture_half_float_linear", textureHalfFloatLinear, &extensionStrings);
- InsertExtensionString("GL_OES_texture_float", textureFloat, &extensionStrings);
- InsertExtensionString("GL_OES_texture_float_linear", textureFloatLinear, &extensionStrings);
- InsertExtensionString("GL_EXT_texture_rg", textureRG, &extensionStrings);
- InsertExtensionString("GL_EXT_texture_compression_dxt1", textureCompressionDXT1, &extensionStrings);
- InsertExtensionString("GL_ANGLE_texture_compression_dxt3", textureCompressionDXT3, &extensionStrings);
- InsertExtensionString("GL_ANGLE_texture_compression_dxt5", textureCompressionDXT5, &extensionStrings);
- InsertExtensionString("GL_KHR_texture_compression_astc_hdr", textureCompressionASTCHDR, &extensionStrings);
- InsertExtensionString("GL_KHR_texture_compression_astc_ldr", textureCompressionASTCLDR, &extensionStrings);
- InsertExtensionString("GL_OES_compressed_ETC1_RGB8_texture", compressedETC1RGB8Texture, &extensionStrings);
- InsertExtensionString("GL_EXT_sRGB", sRGB, &extensionStrings);
- InsertExtensionString("GL_ANGLE_depth_texture", depthTextures, &extensionStrings);
- InsertExtensionString("GL_OES_depth32", depth32, &extensionStrings);
- InsertExtensionString("GL_EXT_texture_storage", textureStorage, &extensionStrings);
- InsertExtensionString("GL_OES_texture_npot", textureNPOT, &extensionStrings);
- InsertExtensionString("GL_EXT_draw_buffers", drawBuffers, &extensionStrings);
- InsertExtensionString("GL_EXT_texture_filter_anisotropic", textureFilterAnisotropic, &extensionStrings);
- InsertExtensionString("GL_EXT_occlusion_query_boolean", occlusionQueryBoolean, &extensionStrings);
- InsertExtensionString("GL_NV_fence", fence, &extensionStrings);
- InsertExtensionString("GL_ANGLE_timer_query", timerQuery, &extensionStrings);
- InsertExtensionString("GL_EXT_disjoint_timer_query", disjointTimerQuery, &extensionStrings);
- InsertExtensionString("GL_EXT_robustness", robustness, &extensionStrings);
- InsertExtensionString("GL_EXT_blend_minmax", blendMinMax, &extensionStrings);
- InsertExtensionString("GL_ANGLE_framebuffer_blit", framebufferBlit, &extensionStrings);
- InsertExtensionString("GL_ANGLE_framebuffer_multisample", framebufferMultisample, &extensionStrings);
- InsertExtensionString("GL_ANGLE_instanced_arrays", instancedArrays, &extensionStrings);
- InsertExtensionString("GL_ANGLE_pack_reverse_row_order", packReverseRowOrder, &extensionStrings);
- InsertExtensionString("GL_OES_standard_derivatives", standardDerivatives, &extensionStrings);
- InsertExtensionString("GL_EXT_shader_texture_lod", shaderTextureLOD, &extensionStrings);
- InsertExtensionString("GL_NV_shader_framebuffer_fetch", NVshaderFramebufferFetch, &extensionStrings);
- InsertExtensionString("GL_ARM_shader_framebuffer_fetch", ARMshaderFramebufferFetch, &extensionStrings);
- InsertExtensionString("GL_EXT_shader_framebuffer_fetch", shaderFramebufferFetch, &extensionStrings);
- InsertExtensionString("GL_EXT_frag_depth", fragDepth, &extensionStrings);
- InsertExtensionString("GL_ANGLE_texture_usage", textureUsage, &extensionStrings);
- InsertExtensionString("GL_ANGLE_translated_shader_source", translatedShaderSource, &extensionStrings);
- InsertExtensionString("GL_OES_fbo_render_mipmap", fboRenderMipmap, &extensionStrings);
- InsertExtensionString("GL_EXT_discard_framebuffer", discardFramebuffer, &extensionStrings);
- InsertExtensionString("GL_EXT_debug_marker", debugMarker, &extensionStrings);
- InsertExtensionString("GL_OES_EGL_image", eglImage, &extensionStrings);
- InsertExtensionString("GL_OES_EGL_image_external", eglImageExternal, &extensionStrings);
- InsertExtensionString("GL_OES_EGL_image_external_essl3", eglImageExternalEssl3, &extensionStrings);
- InsertExtensionString("GL_EXT_unpack_subimage", unpackSubimage, &extensionStrings);
- InsertExtensionString("GL_NV_pack_subimage", packSubimage, &extensionStrings);
- InsertExtensionString("GL_EXT_color_buffer_float", colorBufferFloat, &extensionStrings);
- InsertExtensionString("GL_OES_vertex_array_object", vertexArrayObject, &extensionStrings);
- InsertExtensionString("GL_KHR_debug", debug, &extensionStrings);
- // TODO(jmadill): Enable this when complete.
- //InsertExtensionString("GL_KHR_no_error", noError, &extensionStrings);
-
- InsertExtensionString("GL_ANGLE_lossy_etc_decode", lossyETCDecode, &extensionStrings);
- // clang-format on
+ for (const auto &extensionInfo : GetExtensionInfoMap())
+ {
+ if (this->*(extensionInfo.second.ExtensionsMember))
+ {
+ extensionStrings.push_back(extensionInfo.first);
+ }
+ }
return extensionStrings;
}
@@ -243,10 +259,14 @@ Limitations::Limitations()
{
}
-static bool GetFormatSupport(const TextureCapsMap &textureCaps, const std::vector<GLenum> &requiredFormats,
- bool requiresTexturing, bool requiresFiltering, bool requiresRendering)
+static bool GetFormatSupportBase(const TextureCapsMap &textureCaps,
+ const GLenum *requiredFormats,
+ size_t requiredFormatsSize,
+ bool requiresTexturing,
+ bool requiresFiltering,
+ bool requiresRendering)
{
- for (size_t i = 0; i < requiredFormats.size(); i++)
+ for (size_t i = 0; i < requiredFormatsSize; i++)
{
const TextureCaps &cap = textureCaps.get(requiredFormats[i]);
@@ -269,11 +289,23 @@ static bool GetFormatSupport(const TextureCapsMap &textureCaps, const std::vecto
return true;
}
+template <size_t N>
+static bool GetFormatSupport(const TextureCapsMap &textureCaps,
+ const GLenum (&requiredFormats)[N],
+ bool requiresTexturing,
+ bool requiresFiltering,
+ bool requiresRendering)
+{
+ return GetFormatSupportBase(textureCaps, requiredFormats, N, requiresTexturing,
+ requiresFiltering, requiresRendering);
+}
+
// Check for GL_OES_packed_depth_stencil
static bool DeterminePackedDepthStencilSupport(const TextureCapsMap &textureCaps)
{
- std::vector<GLenum> requiredFormats;
- requiredFormats.push_back(GL_DEPTH24_STENCIL8);
+ constexpr GLenum requiredFormats[] = {
+ GL_DEPTH24_STENCIL8,
+ };
return GetFormatSupport(textureCaps, requiredFormats, false, false, true);
}
@@ -281,9 +313,9 @@ static bool DeterminePackedDepthStencilSupport(const TextureCapsMap &textureCaps
// Checks for GL_OES_rgb8_rgba8 support
static bool DetermineRGB8AndRGBA8TextureSupport(const TextureCapsMap &textureCaps)
{
- std::vector<GLenum> requiredFormats;
- requiredFormats.push_back(GL_RGB8);
- requiredFormats.push_back(GL_RGBA8);
+ constexpr GLenum requiredFormats[] = {
+ GL_RGB8, GL_RGBA8,
+ };
return GetFormatSupport(textureCaps, requiredFormats, true, true, true);
}
@@ -291,8 +323,9 @@ static bool DetermineRGB8AndRGBA8TextureSupport(const TextureCapsMap &textureCap
// Checks for GL_EXT_texture_format_BGRA8888 support
static bool DetermineBGRA8TextureSupport(const TextureCapsMap &textureCaps)
{
- std::vector<GLenum> requiredFormats;
- requiredFormats.push_back(GL_BGRA8_EXT);
+ constexpr GLenum requiredFormats[] = {
+ GL_BGRA8_EXT,
+ };
return GetFormatSupport(textureCaps, requiredFormats, true, true, true);
}
@@ -300,11 +333,9 @@ static bool DetermineBGRA8TextureSupport(const TextureCapsMap &textureCaps)
// Checks for GL_OES_color_buffer_half_float support
static bool DetermineColorBufferHalfFloatSupport(const TextureCapsMap &textureCaps)
{
- std::vector<GLenum> requiredFormats;
- requiredFormats.push_back(GL_RGBA16F);
- requiredFormats.push_back(GL_RGB16F);
- requiredFormats.push_back(GL_RG16F);
- requiredFormats.push_back(GL_R16F);
+ constexpr GLenum requiredFormats[] = {
+ GL_RGBA16F, GL_RGB16F, GL_RG16F, GL_R16F,
+ };
return GetFormatSupport(textureCaps, requiredFormats, true, false, true);
}
@@ -312,19 +343,19 @@ static bool DetermineColorBufferHalfFloatSupport(const TextureCapsMap &textureCa
// Checks for GL_OES_texture_half_float support
static bool DetermineHalfFloatTextureSupport(const TextureCapsMap &textureCaps)
{
- std::vector<GLenum> requiredFormats;
- requiredFormats.push_back(GL_RGB16F);
- requiredFormats.push_back(GL_RGBA16F);
+ constexpr GLenum requiredFormats[] = {
+ GL_RGB16F, GL_RGBA16F,
+ };
- return GetFormatSupport(textureCaps, requiredFormats, true, false, true);
+ return GetFormatSupport(textureCaps, requiredFormats, true, false, false);
}
// Checks for GL_OES_texture_half_float_linear support
static bool DetermineHalfFloatTextureFilteringSupport(const TextureCapsMap &textureCaps)
{
- std::vector<GLenum> requiredFormats;
- requiredFormats.push_back(GL_RGB16F);
- requiredFormats.push_back(GL_RGBA16F);
+ constexpr GLenum requiredFormats[] = {
+ GL_RGB16F, GL_RGBA16F,
+ };
return DetermineHalfFloatTextureSupport(textureCaps) &&
GetFormatSupport(textureCaps, requiredFormats, true, true, false);
@@ -333,50 +364,65 @@ static bool DetermineHalfFloatTextureFilteringSupport(const TextureCapsMap &text
// Checks for GL_OES_texture_float support
static bool DetermineFloatTextureSupport(const TextureCapsMap &textureCaps)
{
- std::vector<GLenum> requiredFormats;
- requiredFormats.push_back(GL_RGB32F);
- requiredFormats.push_back(GL_RGBA32F);
+ constexpr GLenum requiredFormats[] = {
+ GL_RGB32F, GL_RGBA32F,
+ };
- return GetFormatSupport(textureCaps, requiredFormats, true, false, true);
+ return GetFormatSupport(textureCaps, requiredFormats, true, false, false);
}
// Checks for GL_OES_texture_float_linear support
static bool DetermineFloatTextureFilteringSupport(const TextureCapsMap &textureCaps)
{
- std::vector<GLenum> requiredFormats;
- requiredFormats.push_back(GL_RGB32F);
- requiredFormats.push_back(GL_RGBA32F);
+ constexpr GLenum requiredFormats[] = {
+ GL_RGB32F, GL_RGBA32F,
+ };
return DetermineFloatTextureSupport(textureCaps) &&
GetFormatSupport(textureCaps, requiredFormats, true, true, false);
}
// Checks for GL_EXT_texture_rg support
+static bool DetermineRGHalfFloatTextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_R16F, GL_RG16F,
+ };
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+}
+
+static bool DetermineRGFloatTextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_R32F, GL_RG32F,
+ };
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+}
+
static bool DetermineRGTextureSupport(const TextureCapsMap &textureCaps, bool checkHalfFloatFormats, bool checkFloatFormats)
{
- std::vector<GLenum> requiredFormats;
- requiredFormats.push_back(GL_R8);
- requiredFormats.push_back(GL_RG8);
- if (checkHalfFloatFormats)
+ if (checkHalfFloatFormats && !DetermineRGHalfFloatTextureSupport(textureCaps))
{
- requiredFormats.push_back(GL_R16F);
- requiredFormats.push_back(GL_RG16F);
+ return false;
}
- if (checkFloatFormats)
+
+ if (checkFloatFormats && !DetermineRGFloatTextureSupport(textureCaps))
{
- requiredFormats.push_back(GL_R32F);
- requiredFormats.push_back(GL_RG32F);
+ return false;
}
+ constexpr GLenum requiredFormats[] = {
+ GL_R8, GL_RG8,
+ };
return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
}
// Check for GL_EXT_texture_compression_dxt1
static bool DetermineDXT1TextureSupport(const TextureCapsMap &textureCaps)
{
- std::vector<GLenum> requiredFormats;
- requiredFormats.push_back(GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
- requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
+ };
return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
}
@@ -384,8 +430,9 @@ static bool DetermineDXT1TextureSupport(const TextureCapsMap &textureCaps)
// Check for GL_ANGLE_texture_compression_dxt3
static bool DetermineDXT3TextureSupport(const TextureCapsMap &textureCaps)
{
- std::vector<GLenum> requiredFormats;
- requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE);
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE,
+ };
return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
}
@@ -393,8 +440,20 @@ static bool DetermineDXT3TextureSupport(const TextureCapsMap &textureCaps)
// Check for GL_ANGLE_texture_compression_dxt5
static bool DetermineDXT5TextureSupport(const TextureCapsMap &textureCaps)
{
- std::vector<GLenum> requiredFormats;
- requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE);
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
+}
+
+// Check for GL_EXT_texture_compression_s3tc_srgb
+static bool DetermineS3TCsRGBTextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,
+ GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,
+ };
return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
}
@@ -402,35 +461,22 @@ static bool DetermineDXT5TextureSupport(const TextureCapsMap &textureCaps)
// Check for GL_KHR_texture_compression_astc_hdr and GL_KHR_texture_compression_astc_ldr
static bool DetermineASTCTextureSupport(const TextureCapsMap &textureCaps)
{
- std::vector<GLenum> requiredFormats;
- requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_4x4_KHR);
- requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_5x4_KHR);
- requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_5x5_KHR);
- requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_6x5_KHR);
- requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_6x6_KHR);
- requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_8x5_KHR);
- requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_8x6_KHR);
- requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_8x8_KHR);
- requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_10x5_KHR);
- requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_10x6_KHR);
- requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_10x8_KHR);
- requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_10x10_KHR);
- requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_12x10_KHR);
- requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_12x12_KHR);
- requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR);
- requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR);
- requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR);
- requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR);
- requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR);
- requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR);
- requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR);
- requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR);
- requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR);
- requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR);
- requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR);
- requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR);
- requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR);
- requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR);
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_RGBA_ASTC_4x4_KHR, GL_COMPRESSED_RGBA_ASTC_5x4_KHR,
+ GL_COMPRESSED_RGBA_ASTC_5x5_KHR, GL_COMPRESSED_RGBA_ASTC_6x5_KHR,
+ GL_COMPRESSED_RGBA_ASTC_6x6_KHR, GL_COMPRESSED_RGBA_ASTC_8x5_KHR,
+ GL_COMPRESSED_RGBA_ASTC_8x6_KHR, GL_COMPRESSED_RGBA_ASTC_8x8_KHR,
+ GL_COMPRESSED_RGBA_ASTC_10x5_KHR, GL_COMPRESSED_RGBA_ASTC_10x6_KHR,
+ GL_COMPRESSED_RGBA_ASTC_10x8_KHR, GL_COMPRESSED_RGBA_ASTC_10x10_KHR,
+ GL_COMPRESSED_RGBA_ASTC_12x10_KHR, GL_COMPRESSED_RGBA_ASTC_12x12_KHR,
+ GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR,
+ GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR,
+ GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR,
+ GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR,
+ GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR,
+ GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR,
+ GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR,
+ };
return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
}
@@ -438,8 +484,9 @@ static bool DetermineASTCTextureSupport(const TextureCapsMap &textureCaps)
// Check for GL_ETC1_RGB8_OES
static bool DetermineETC1RGB8TextureSupport(const TextureCapsMap &textureCaps)
{
- std::vector<GLenum> requiredFormats;
- requiredFormats.push_back(GL_ETC1_RGB8_OES);
+ constexpr GLenum requiredFormats[] = {
+ GL_ETC1_RGB8_OES,
+ };
return GetFormatSupport(textureCaps, requiredFormats, true, true, false);
}
@@ -447,12 +494,13 @@ static bool DetermineETC1RGB8TextureSupport(const TextureCapsMap &textureCaps)
// Check for GL_ANGLE_texture_compression_dxt5
static bool DetermineSRGBTextureSupport(const TextureCapsMap &textureCaps)
{
- std::vector<GLenum> requiredFilterFormats;
- requiredFilterFormats.push_back(GL_SRGB8);
- requiredFilterFormats.push_back(GL_SRGB8_ALPHA8);
+ constexpr GLenum requiredFilterFormats[] = {
+ GL_SRGB8, GL_SRGB8_ALPHA8,
+ };
- std::vector<GLenum> requiredRenderFormats;
- requiredRenderFormats.push_back(GL_SRGB8_ALPHA8);
+ constexpr GLenum requiredRenderFormats[] = {
+ GL_SRGB8_ALPHA8,
+ };
return GetFormatSupport(textureCaps, requiredFilterFormats, true, true, false) &&
GetFormatSupport(textureCaps, requiredRenderFormats, true, false, true);
@@ -461,10 +509,9 @@ static bool DetermineSRGBTextureSupport(const TextureCapsMap &textureCaps)
// Check for GL_ANGLE_depth_texture
static bool DetermineDepthTextureSupport(const TextureCapsMap &textureCaps)
{
- std::vector<GLenum> requiredFormats;
- requiredFormats.push_back(GL_DEPTH_COMPONENT16);
- requiredFormats.push_back(GL_DEPTH_COMPONENT32_OES);
- requiredFormats.push_back(GL_DEPTH24_STENCIL8_OES);
+ constexpr GLenum requiredFormats[] = {
+ GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT32_OES, GL_DEPTH24_STENCIL8_OES,
+ };
return GetFormatSupport(textureCaps, requiredFormats, true, true, true);
}
@@ -472,27 +519,59 @@ static bool DetermineDepthTextureSupport(const TextureCapsMap &textureCaps)
// Check for GL_OES_depth32
static bool DetermineDepth32Support(const TextureCapsMap &textureCaps)
{
- std::vector<GLenum> requiredFormats;
- requiredFormats.push_back(GL_DEPTH_COMPONENT32_OES);
+ constexpr GLenum requiredFormats[] = {
+ GL_DEPTH_COMPONENT32_OES,
+ };
return GetFormatSupport(textureCaps, requiredFormats, false, false, true);
}
+// Check for GL_CHROMIUM_color_buffer_float_rgb
+static bool DetermineColorBufferFloatRGBSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_RGB32F,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, false, true);
+}
+
+// Check for GL_CHROMIUM_color_buffer_float_rgba
+static bool DetermineColorBufferFloatRGBASupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_RGBA32F,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, false, true);
+}
+
// Check for GL_EXT_color_buffer_float
static bool DetermineColorBufferFloatSupport(const TextureCapsMap &textureCaps)
{
- std::vector<GLenum> requiredFormats;
- requiredFormats.push_back(GL_R16F);
- requiredFormats.push_back(GL_RG16F);
- requiredFormats.push_back(GL_RGBA16F);
- requiredFormats.push_back(GL_R32F);
- requiredFormats.push_back(GL_RG32F);
- requiredFormats.push_back(GL_RGBA32F);
- requiredFormats.push_back(GL_R11F_G11F_B10F);
+ constexpr GLenum requiredFormats[] = {
+ GL_R16F, GL_RG16F, GL_RGBA16F, GL_R32F, GL_RG32F, GL_RGBA32F, GL_R11F_G11F_B10F,
+ };
return GetFormatSupport(textureCaps, requiredFormats, true, false, true);
}
+// Check for GL_EXT_texture_norm16
+static bool DetermineTextureNorm16Support(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFilterFormats[] = {
+ GL_R16_EXT, GL_RG16_EXT, GL_RGB16_EXT, GL_RGBA16_EXT,
+ GL_R16_SNORM_EXT, GL_RG16_SNORM_EXT, GL_RGB16_SNORM_EXT, GL_RGBA16_SNORM_EXT,
+ };
+
+ constexpr GLenum requiredRenderFormats[] = {
+ GL_R16_EXT, GL_RG16_EXT, GL_RGBA16_EXT,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFilterFormats, true, true, false) &&
+ GetFormatSupport(textureCaps, requiredRenderFormats, true, false, true);
+}
+
void Extensions::setTextureExtensionSupport(const TextureCapsMap &textureCaps)
{
packedDepthStencil = DeterminePackedDepthStencilSupport(textureCaps);
@@ -507,47 +586,161 @@ void Extensions::setTextureExtensionSupport(const TextureCapsMap &textureCaps)
textureCompressionDXT1 = DetermineDXT1TextureSupport(textureCaps);
textureCompressionDXT3 = DetermineDXT3TextureSupport(textureCaps);
textureCompressionDXT5 = DetermineDXT5TextureSupport(textureCaps);
+ textureCompressionS3TCsRGB = DetermineS3TCsRGBTextureSupport(textureCaps);
textureCompressionASTCHDR = DetermineASTCTextureSupport(textureCaps);
textureCompressionASTCLDR = textureCompressionASTCHDR;
compressedETC1RGB8Texture = DetermineETC1RGB8TextureSupport(textureCaps);
sRGB = DetermineSRGBTextureSupport(textureCaps);
depthTextures = DetermineDepthTextureSupport(textureCaps);
depth32 = DetermineDepth32Support(textureCaps);
+ colorBufferFloatRGB = DetermineColorBufferFloatRGBSupport(textureCaps);
+ colorBufferFloatRGBA = DetermineColorBufferFloatRGBASupport(textureCaps);
colorBufferFloat = DetermineColorBufferFloatSupport(textureCaps);
+ textureNorm16 = DetermineTextureNorm16Support(textureCaps);
}
-TypePrecision::TypePrecision()
+const ExtensionInfoMap &GetExtensionInfoMap()
{
- range[0] = 0;
- range[1] = 0;
- precision = 0;
+ auto buildExtensionInfoMap = []() {
+ auto enableableExtension = [](ExtensionInfo::ExtensionBool member) {
+ ExtensionInfo info;
+ info.Requestable = true;
+ info.ExtensionsMember = member;
+ return info;
+ };
+
+ auto esOnlyExtension = [](ExtensionInfo::ExtensionBool member) {
+ ExtensionInfo info;
+ info.ExtensionsMember = member;
+ return info;
+ };
+
+ // clang-format off
+ ExtensionInfoMap map;
+ map["GL_OES_element_index_uint"] = enableableExtension(&Extensions::elementIndexUint);
+ map["GL_OES_packed_depth_stencil"] = esOnlyExtension(&Extensions::packedDepthStencil);
+ map["GL_OES_get_program_binary"] = enableableExtension(&Extensions::getProgramBinary);
+ map["GL_OES_rgb8_rgba8"] = enableableExtension(&Extensions::rgb8rgba8);
+ map["GL_EXT_texture_format_BGRA8888"] = enableableExtension(&Extensions::textureFormatBGRA8888);
+ map["GL_EXT_read_format_bgra"] = esOnlyExtension(&Extensions::readFormatBGRA);
+ map["GL_NV_pixel_buffer_object"] = enableableExtension(&Extensions::pixelBufferObject);
+ map["GL_OES_mapbuffer"] = enableableExtension(&Extensions::mapBuffer);
+ map["GL_EXT_map_buffer_range"] = enableableExtension(&Extensions::mapBufferRange);
+ map["GL_EXT_color_buffer_half_float"] = enableableExtension(&Extensions::colorBufferHalfFloat);
+ map["GL_OES_texture_half_float"] = enableableExtension(&Extensions::textureHalfFloat);
+ map["GL_OES_texture_half_float_linear"] = enableableExtension(&Extensions::textureHalfFloatLinear);
+ map["GL_OES_texture_float"] = enableableExtension(&Extensions::textureFloat);
+ map["GL_OES_texture_float_linear"] = enableableExtension(&Extensions::textureFloatLinear);
+ map["GL_EXT_texture_rg"] = enableableExtension(&Extensions::textureRG);
+ map["GL_EXT_texture_compression_dxt1"] = enableableExtension(&Extensions::textureCompressionDXT1);
+ map["GL_ANGLE_texture_compression_dxt3"] = enableableExtension(&Extensions::textureCompressionDXT3);
+ map["GL_ANGLE_texture_compression_dxt5"] = enableableExtension(&Extensions::textureCompressionDXT5);
+ map["GL_EXT_texture_compression_s3tc_srgb"] = enableableExtension(&Extensions::textureCompressionS3TCsRGB);
+ map["GL_KHR_texture_compression_astc_hdr"] = enableableExtension(&Extensions::textureCompressionASTCHDR);
+ map["GL_KHR_texture_compression_astc_ldr"] = enableableExtension(&Extensions::textureCompressionASTCLDR);
+ map["GL_OES_compressed_ETC1_RGB8_texture"] = enableableExtension(&Extensions::compressedETC1RGB8Texture);
+ map["GL_EXT_sRGB"] = enableableExtension(&Extensions::sRGB);
+ map["GL_ANGLE_depth_texture"] = esOnlyExtension(&Extensions::depthTextures);
+ map["GL_OES_depth32"] = esOnlyExtension(&Extensions::depth32);
+ map["GL_EXT_texture_storage"] = esOnlyExtension(&Extensions::textureStorage);
+ map["GL_OES_texture_npot"] = enableableExtension(&Extensions::textureNPOT);
+ map["GL_EXT_draw_buffers"] = enableableExtension(&Extensions::drawBuffers);
+ map["GL_EXT_texture_filter_anisotropic"] = enableableExtension(&Extensions::textureFilterAnisotropic);
+ map["GL_EXT_occlusion_query_boolean"] = enableableExtension(&Extensions::occlusionQueryBoolean);
+ map["GL_NV_fence"] = esOnlyExtension(&Extensions::fence);
+ map["GL_EXT_disjoint_timer_query"] = enableableExtension(&Extensions::disjointTimerQuery);
+ map["GL_EXT_robustness"] = esOnlyExtension(&Extensions::robustness);
+ map["GL_KHR_robust_buffer_access_behavior"] = esOnlyExtension(&Extensions::robustBufferAccessBehavior);
+ map["GL_EXT_blend_minmax"] = enableableExtension(&Extensions::blendMinMax);
+ map["GL_ANGLE_framebuffer_blit"] = enableableExtension(&Extensions::framebufferBlit);
+ map["GL_ANGLE_framebuffer_multisample"] = enableableExtension(&Extensions::framebufferMultisample);
+ map["GL_ANGLE_instanced_arrays"] = enableableExtension(&Extensions::instancedArrays);
+ map["GL_ANGLE_pack_reverse_row_order"] = enableableExtension(&Extensions::packReverseRowOrder);
+ map["GL_OES_standard_derivatives"] = enableableExtension(&Extensions::standardDerivatives);
+ map["GL_EXT_shader_texture_lod"] = enableableExtension(&Extensions::shaderTextureLOD);
+ map["GL_EXT_frag_depth"] = enableableExtension(&Extensions::fragDepth);
+ map["GL_ANGLE_multiview"] = enableableExtension(&Extensions::multiview);
+ map["GL_ANGLE_texture_usage"] = enableableExtension(&Extensions::textureUsage);
+ map["GL_ANGLE_translated_shader_source"] = esOnlyExtension(&Extensions::translatedShaderSource);
+ map["GL_OES_fbo_render_mipmap"] = enableableExtension(&Extensions::fboRenderMipmap);
+ map["GL_EXT_discard_framebuffer"] = esOnlyExtension(&Extensions::discardFramebuffer);
+ map["GL_EXT_debug_marker"] = esOnlyExtension(&Extensions::debugMarker);
+ map["GL_OES_EGL_image"] = esOnlyExtension(&Extensions::eglImage);
+ map["GL_OES_EGL_image_external"] = esOnlyExtension(&Extensions::eglImageExternal);
+ map["GL_OES_EGL_image_external_essl3"] = esOnlyExtension(&Extensions::eglImageExternalEssl3);
+ map["GL_NV_EGL_stream_consumer_external"] = esOnlyExtension(&Extensions::eglStreamConsumerExternal);
+ map["GL_EXT_unpack_subimage"] = enableableExtension(&Extensions::unpackSubimage);
+ map["GL_NV_pack_subimage"] = enableableExtension(&Extensions::packSubimage);
+ map["GL_EXT_color_buffer_float"] = enableableExtension(&Extensions::colorBufferFloat);
+ map["GL_OES_vertex_array_object"] = esOnlyExtension(&Extensions::vertexArrayObject);
+ map["GL_KHR_debug"] = esOnlyExtension(&Extensions::debug);
+ // TODO(jmadill): Enable this when complete.
+ //map["GL_KHR_no_error"] = esOnlyExtension(&Extensions::noError);
+ map["GL_ANGLE_lossy_etc_decode"] = enableableExtension(&Extensions::lossyETCDecode);
+ map["GL_CHROMIUM_bind_uniform_location"] = esOnlyExtension(&Extensions::bindUniformLocation);
+ map["GL_CHROMIUM_sync_query"] = enableableExtension(&Extensions::syncQuery);
+ map["GL_CHROMIUM_copy_texture"] = esOnlyExtension(&Extensions::copyTexture);
+ map["GL_CHROMIUM_copy_compressed_texture"] = esOnlyExtension(&Extensions::copyCompressedTexture);
+ map["GL_ANGLE_webgl_compatibility"] = esOnlyExtension(&Extensions::webglCompatibility);
+ map["GL_ANGLE_request_extension"] = esOnlyExtension(&Extensions::requestExtension);
+ map["GL_CHROMIUM_bind_generates_resource"] = esOnlyExtension(&Extensions::bindGeneratesResource);
+ map["GL_ANGLE_robust_client_memory"] = esOnlyExtension(&Extensions::robustClientMemory);
+ map["GL_EXT_texture_sRGB_decode"] = esOnlyExtension(&Extensions::textureSRGBDecode);
+ map["GL_EXT_sRGB_write_control"] = esOnlyExtension(&Extensions::sRGBWriteControl);
+ map["GL_CHROMIUM_color_buffer_float_rgb"] = enableableExtension(&Extensions::colorBufferFloatRGB);
+ map["GL_CHROMIUM_color_buffer_float_rgba"] = enableableExtension(&Extensions::colorBufferFloatRGBA);
+ map["GL_EXT_multisample_compatibility"] = esOnlyExtension(&Extensions::multisampleCompatibility);
+ map["GL_CHROMIUM_framebuffer_mixed_samples"] = esOnlyExtension(&Extensions::framebufferMixedSamples);
+ map["GL_EXT_texture_norm16"] = esOnlyExtension(&Extensions::textureNorm16);
+ map["GL_CHROMIUM_path_rendering"] = esOnlyExtension(&Extensions::pathRendering);
+ map["GL_OES_surfaceless_context"] = esOnlyExtension(&Extensions::surfacelessContext);
+ map["GL_ANGLE_client_arrays"] = esOnlyExtension(&Extensions::clientArrays);
+ map["GL_ANGLE_robust_resource_initialization"] = esOnlyExtension(&Extensions::robustResourceInitialization);
+ map["GL_ANGLE_program_cache_control"] = esOnlyExtension(&Extensions::programCacheControl);
+ map["GL_ANGLE_texture_rectangle"] = enableableExtension(&Extensions::textureRectangle);
+ map["GL_EXT_geometry_shader"] = enableableExtension(&Extensions::geometryShader);
+ // clang-format on
+
+ return map;
+ };
+
+ static const ExtensionInfoMap extensionInfo = buildExtensionInfoMap();
+ return extensionInfo;
}
+TypePrecision::TypePrecision() : range({{0, 0}}), precision(0)
+{
+}
+
+TypePrecision::TypePrecision(const TypePrecision &other) = default;
+
void TypePrecision::setIEEEFloat()
{
- range[0] = 127;
- range[1] = 127;
+ range = {{127, 127}};
precision = 23;
}
void TypePrecision::setTwosComplementInt(unsigned int bits)
{
- range[0] = GLint(bits) - 1;
- range[1] = GLint(bits) - 2;
+ range = {{static_cast<GLint>(bits) - 1, static_cast<GLint>(bits) - 2}};
precision = 0;
}
+void TypePrecision::setSimulatedFloat(unsigned int r, unsigned int p)
+{
+ range = {{static_cast<GLint>(r), static_cast<GLint>(r)}};
+ precision = static_cast<GLint>(p);
+}
+
void TypePrecision::setSimulatedInt(unsigned int r)
{
- range[0] = GLint(r);
- range[1] = GLint(r);
+ range = {{static_cast<GLint>(r), static_cast<GLint>(r)}};
precision = 0;
}
void TypePrecision::get(GLint *returnRange, GLint *returnPrecision) const
{
- returnRange[0] = range[0];
- returnRange[1] = range[1];
+ std::copy(range.begin(), range.end(), returnRange);
*returnPrecision = precision;
}
@@ -555,37 +748,77 @@ Caps::Caps()
: maxElementIndex(0),
max3DTextureSize(0),
max2DTextureSize(0),
+ maxRectangleTextureSize(0),
maxArrayTextureLayers(0),
maxLODBias(0),
maxCubeMapTextureSize(0),
maxRenderbufferSize(0),
+ minAliasedPointSize(0),
+ maxAliasedPointSize(0),
+ minAliasedLineWidth(0),
+ maxAliasedLineWidth(0),
+
+ // Table 20.40
maxDrawBuffers(0),
+ maxFramebufferWidth(0),
+ maxFramebufferHeight(0),
+ maxFramebufferSamples(0),
maxColorAttachments(0),
maxViewportWidth(0),
maxViewportHeight(0),
- minAliasedPointSize(0),
- maxAliasedPointSize(0),
- minAliasedLineWidth(0),
- // Table 6.29
+ maxSampleMaskWords(0),
+ maxColorTextureSamples(0),
+ maxDepthTextureSamples(0),
+ maxIntegerSamples(0),
+ maxServerWaitTimeout(0),
+
+ // Table 20.41
+ maxVertexAttribRelativeOffset(0),
+ maxVertexAttribBindings(0),
+ maxVertexAttribStride(0),
maxElementsIndices(0),
maxElementsVertices(0),
- maxServerWaitTimeout(0),
- // Table 6.31
+
+ // Table 20.43
maxVertexAttributes(0),
maxVertexUniformComponents(0),
maxVertexUniformVectors(0),
maxVertexUniformBlocks(0),
maxVertexOutputComponents(0),
maxVertexTextureImageUnits(0),
- // Table 6.32
+ maxVertexAtomicCounterBuffers(0),
+ maxVertexAtomicCounters(0),
+ maxVertexImageUniforms(0),
+ maxVertexShaderStorageBlocks(0),
+
+ // Table 20.44
maxFragmentUniformComponents(0),
maxFragmentUniformVectors(0),
maxFragmentUniformBlocks(0),
maxFragmentInputComponents(0),
maxTextureImageUnits(0),
+ maxFragmentAtomicCounterBuffers(0),
+ maxFragmentAtomicCounters(0),
+ maxFragmentImageUniforms(0),
+ maxFragmentShaderStorageBlocks(0),
+ minProgramTextureGatherOffset(0),
+ maxProgramTextureGatherOffset(0),
minProgramTexelOffset(0),
maxProgramTexelOffset(0),
- // Table 6.33
+
+ // Table 20.45
+ maxComputeWorkGroupInvocations(0),
+ maxComputeUniformBlocks(0),
+ maxComputeTextureImageUnits(0),
+ maxComputeSharedMemorySize(0),
+ maxComputeUniformComponents(0),
+ maxComputeAtomicCounterBuffers(0),
+ maxComputeAtomicCounters(0),
+ maxComputeImageUniforms(0),
+ maxCombinedComputeUniformComponents(0),
+ maxComputeShaderStorageBlocks(0),
+
+ // Table 20.46
maxUniformBufferBindings(0),
maxUniformBlockSize(0),
uniformBufferOffsetAlignment(0),
@@ -595,15 +828,233 @@ Caps::Caps()
maxVaryingComponents(0),
maxVaryingVectors(0),
maxCombinedTextureImageUnits(0),
- // Table 6.34
+ maxCombinedShaderOutputResources(0),
+
+ // Table 20.47
+ maxUniformLocations(0),
+ maxAtomicCounterBufferBindings(0),
+ maxAtomicCounterBufferSize(0),
+ maxCombinedAtomicCounterBuffers(0),
+ maxCombinedAtomicCounters(0),
+ maxImageUnits(0),
+ maxCombinedImageUniforms(0),
+ maxShaderStorageBufferBindings(0),
+ maxShaderStorageBlockSize(0),
+ maxCombinedShaderStorageBlocks(0),
+ shaderStorageBufferOffsetAlignment(0),
+
+ // Table 20.48
maxTransformFeedbackInterleavedComponents(0),
maxTransformFeedbackSeparateAttributes(0),
maxTransformFeedbackSeparateComponents(0),
- // Table 6.35
+
+ // Table 20.49
maxSamples(0)
{
+ for (size_t i = 0; i < 3; ++i)
+ {
+ maxComputeWorkGroupCount[i] = 0;
+ maxComputeWorkGroupSize[i] = 0;
+ }
}
+Caps::Caps(const Caps &other) = default;
+Caps::~Caps() = default;
+
+Caps GenerateMinimumCaps(const Version &clientVersion, const Extensions &extensions)
+{
+ Caps caps;
+
+ if (clientVersion >= Version(2, 0))
+ {
+ // Table 6.18
+ caps.max2DTextureSize = 64;
+ caps.maxCubeMapTextureSize = 16;
+ caps.maxViewportWidth = caps.max2DTextureSize;
+ caps.maxViewportHeight = caps.max2DTextureSize;
+ caps.minAliasedPointSize = 1;
+ caps.maxAliasedPointSize = 1;
+ caps.minAliasedLineWidth = 1;
+ caps.maxAliasedLineWidth = 1;
+
+ // Table 6.19
+ caps.vertexHighpFloat.setSimulatedFloat(62, 16);
+ caps.vertexMediumpFloat.setSimulatedFloat(14, 10);
+ caps.vertexLowpFloat.setSimulatedFloat(1, 8);
+ caps.vertexHighpInt.setSimulatedInt(16);
+ caps.vertexMediumpInt.setSimulatedInt(10);
+ caps.vertexLowpInt.setSimulatedInt(8);
+ caps.fragmentHighpFloat.setSimulatedFloat(62, 16);
+ caps.fragmentMediumpFloat.setSimulatedFloat(14, 10);
+ caps.fragmentLowpFloat.setSimulatedFloat(1, 8);
+ caps.fragmentHighpInt.setSimulatedInt(16);
+ caps.fragmentMediumpInt.setSimulatedInt(10);
+ caps.fragmentLowpInt.setSimulatedInt(8);
+
+ // Table 6.20
+ caps.maxVertexAttributes = 8;
+ caps.maxVertexUniformVectors = 128;
+ caps.maxVaryingVectors = 8;
+ caps.maxCombinedTextureImageUnits = 8;
+ caps.maxTextureImageUnits = 8;
+ caps.maxFragmentUniformVectors = 16;
+ caps.maxRenderbufferSize = 1;
+ }
+
+ if (clientVersion >= Version(3, 0))
+ {
+ // Table 6.28
+ caps.maxElementIndex = (1 << 24) - 1;
+ caps.max3DTextureSize = 256;
+ caps.max2DTextureSize = 2048;
+ caps.maxArrayTextureLayers = 256;
+ caps.maxLODBias = 2.0f;
+ caps.maxCubeMapTextureSize = 2048;
+ caps.maxRenderbufferSize = 2048;
+ caps.maxDrawBuffers = 4;
+ caps.maxColorAttachments = 4;
+ caps.maxViewportWidth = caps.max2DTextureSize;
+ caps.maxViewportHeight = caps.max2DTextureSize;
+
+ // Table 6.29
+ caps.compressedTextureFormats.push_back(GL_COMPRESSED_R11_EAC);
+ caps.compressedTextureFormats.push_back(GL_COMPRESSED_SIGNED_R11_EAC);
+ caps.compressedTextureFormats.push_back(GL_COMPRESSED_RG11_EAC);
+ caps.compressedTextureFormats.push_back(GL_COMPRESSED_SIGNED_RG11_EAC);
+ caps.compressedTextureFormats.push_back(GL_COMPRESSED_RGB8_ETC2);
+ caps.compressedTextureFormats.push_back(GL_COMPRESSED_SRGB8_ETC2);
+ caps.compressedTextureFormats.push_back(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2);
+ caps.compressedTextureFormats.push_back(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2);
+ caps.compressedTextureFormats.push_back(GL_COMPRESSED_RGBA8_ETC2_EAC);
+ caps.compressedTextureFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC);
+ caps.vertexHighpFloat.setIEEEFloat();
+ caps.vertexHighpInt.setTwosComplementInt(32);
+ caps.vertexMediumpInt.setTwosComplementInt(16);
+ caps.vertexLowpInt.setTwosComplementInt(8);
+ caps.fragmentHighpFloat.setIEEEFloat();
+ caps.fragmentHighpInt.setSimulatedInt(32);
+ caps.fragmentMediumpInt.setTwosComplementInt(16);
+ caps.fragmentLowpInt.setTwosComplementInt(8);
+ caps.maxServerWaitTimeout = 0;
+
+ // Table 6.31
+ caps.maxVertexAttributes = 16;
+ caps.maxVertexUniformComponents = 1024;
+ caps.maxVertexUniformVectors = 256;
+ caps.maxVertexUniformBlocks = 12;
+ caps.maxVertexOutputComponents = 64;
+ caps.maxVertexTextureImageUnits = 16;
+
+ // Table 6.32
+ caps.maxFragmentUniformComponents = 896;
+ caps.maxFragmentUniformVectors = 224;
+ caps.maxFragmentUniformBlocks = 12;
+ caps.maxFragmentInputComponents = 60;
+ caps.maxTextureImageUnits = 16;
+ caps.minProgramTexelOffset = -8;
+ caps.maxProgramTexelOffset = 7;
+
+ // Table 6.33
+ caps.maxUniformBufferBindings = 24;
+ caps.maxUniformBlockSize = 16384;
+ caps.uniformBufferOffsetAlignment = 256;
+ caps.maxCombinedUniformBlocks = 24;
+ caps.maxCombinedVertexUniformComponents =
+ caps.maxVertexUniformBlocks * (caps.maxUniformBlockSize / 4) +
+ caps.maxVertexUniformComponents;
+ caps.maxCombinedFragmentUniformComponents =
+ caps.maxFragmentUniformBlocks * (caps.maxUniformBlockSize / 4) +
+ caps.maxFragmentUniformComponents;
+ caps.maxVaryingComponents = 60;
+ caps.maxVaryingVectors = 15;
+ caps.maxCombinedTextureImageUnits = 32;
+
+ // Table 6.34
+ caps.maxTransformFeedbackInterleavedComponents = 64;
+ caps.maxTransformFeedbackSeparateAttributes = 4;
+ caps.maxTransformFeedbackSeparateComponents = 4;
+
+ // Table 3.35
+ caps.maxSamples = 4;
+ }
+
+ if (clientVersion >= Version(3, 1))
+ {
+ // Table 20.40
+ caps.maxFramebufferWidth = 2048;
+ caps.maxFramebufferHeight = 2048;
+ caps.maxFramebufferSamples = 4;
+ caps.maxSampleMaskWords = 1;
+ caps.maxColorTextureSamples = 1;
+ caps.maxDepthTextureSamples = 1;
+ caps.maxIntegerSamples = 1;
+
+ // Table 20.41
+ caps.maxVertexAttribRelativeOffset = 2047;
+ caps.maxVertexAttribBindings = 16;
+ caps.maxVertexAttribStride = 2048;
+
+ // Table 20.43
+ caps.maxVertexAtomicCounterBuffers = 0;
+ caps.maxVertexAtomicCounters = 0;
+ caps.maxVertexImageUniforms = 0;
+ caps.maxVertexShaderStorageBlocks = 0;
+
+ // Table 20.44
+ caps.maxFragmentUniformComponents = 1024;
+ caps.maxFragmentUniformVectors = 256;
+ caps.maxFragmentAtomicCounterBuffers = 0;
+ caps.maxFragmentAtomicCounters = 0;
+ caps.maxFragmentImageUniforms = 0;
+ caps.maxFragmentShaderStorageBlocks = 0;
+ caps.minProgramTextureGatherOffset = 0;
+ caps.maxProgramTextureGatherOffset = 0;
+
+ // Table 20.45
+ caps.maxComputeWorkGroupCount = {{65535, 65535, 65535}};
+ caps.maxComputeWorkGroupSize = {{128, 128, 64}};
+ caps.maxComputeWorkGroupInvocations = 12;
+ caps.maxComputeUniformBlocks = 12;
+ caps.maxComputeTextureImageUnits = 16;
+ caps.maxComputeSharedMemorySize = 16384;
+ caps.maxComputeUniformComponents = 1024;
+ caps.maxComputeAtomicCounterBuffers = 1;
+ caps.maxComputeAtomicCounters = 8;
+ caps.maxComputeImageUniforms = 4;
+ caps.maxCombinedComputeUniformComponents =
+ caps.maxComputeUniformBlocks * static_cast<GLuint>(caps.maxUniformBlockSize / 4) +
+ caps.maxComputeUniformComponents;
+ caps.maxComputeShaderStorageBlocks = 4;
+
+ // Table 20.46
+ caps.maxUniformBufferBindings = 36;
+ caps.maxCombinedFragmentUniformComponents =
+ caps.maxFragmentUniformBlocks * (caps.maxUniformBlockSize / 4) +
+ caps.maxFragmentUniformComponents;
+ caps.maxCombinedTextureImageUnits = 48;
+ caps.maxCombinedShaderOutputResources = 4;
+
+ // Table 20.47
+ caps.maxUniformLocations = 1024;
+ caps.maxAtomicCounterBufferBindings = 1;
+ caps.maxAtomicCounterBufferSize = 32;
+ caps.maxCombinedAtomicCounterBuffers = 1;
+ caps.maxCombinedAtomicCounters = 8;
+ caps.maxImageUnits = 4;
+ caps.maxCombinedImageUniforms = 4;
+ caps.maxShaderStorageBufferBindings = 4;
+ caps.maxShaderStorageBlockSize = 1 << 27;
+ caps.maxCombinedShaderStorageBlocks = 4;
+ caps.shaderStorageBufferOffsetAlignment = 256;
+ }
+
+ if (extensions.textureRectangle)
+ {
+ caps.maxRectangleTextureSize = 64;
+ }
+
+ return caps;
+}
}
namespace egl
@@ -617,6 +1068,7 @@ Caps::Caps()
DisplayExtensions::DisplayExtensions()
: createContextRobustness(false),
d3dShareHandleClientBuffer(false),
+ d3dTextureClientBuffer(false),
surfaceD3DTexture2DShareHandle(false),
querySurfacePointer(false),
windowFixedSize(false),
@@ -635,7 +1087,21 @@ DisplayExtensions::DisplayExtensions()
getAllProcAddresses(false),
flexibleSurfaceCompatibility(false),
directComposition(false),
- createContextNoError(false)
+ createContextNoError(false),
+ stream(false),
+ streamConsumerGLTexture(false),
+ streamConsumerGLTextureYUV(false),
+ streamProducerD3DTextureNV12(false),
+ createContextWebGLCompatibility(false),
+ createContextBindGeneratesResource(false),
+ getSyncValues(false),
+ swapBuffersWithDamage(false),
+ pixelFormatFloat(false),
+ surfacelessContext(false),
+ displayTextureShareGroup(false),
+ createContextClientArrays(false),
+ programCacheControl(false),
+ robustResourceInitialization(false)
{
}
@@ -644,29 +1110,44 @@ std::vector<std::string> DisplayExtensions::getStrings() const
std::vector<std::string> extensionStrings;
// clang-format off
- // | Extension name | Supported flag | Output vector |
- InsertExtensionString("EGL_EXT_create_context_robustness", createContextRobustness, &extensionStrings);
- InsertExtensionString("EGL_ANGLE_d3d_share_handle_client_buffer", d3dShareHandleClientBuffer, &extensionStrings);
- InsertExtensionString("EGL_ANGLE_surface_d3d_texture_2d_share_handle", surfaceD3DTexture2DShareHandle, &extensionStrings);
- InsertExtensionString("EGL_ANGLE_query_surface_pointer", querySurfacePointer, &extensionStrings);
- InsertExtensionString("EGL_ANGLE_window_fixed_size", windowFixedSize, &extensionStrings);
- InsertExtensionString("EGL_ANGLE_keyed_mutex", keyedMutex, &extensionStrings);
- InsertExtensionString("EGL_ANGLE_surface_orientation", surfaceOrientation, &extensionStrings);
- InsertExtensionString("EGL_ANGLE_direct_composition", directComposition, &extensionStrings);
- InsertExtensionString("EGL_NV_post_sub_buffer", postSubBuffer, &extensionStrings);
- InsertExtensionString("EGL_KHR_create_context", createContext, &extensionStrings);
- InsertExtensionString("EGL_EXT_device_query", deviceQuery, &extensionStrings);
- InsertExtensionString("EGL_KHR_image", image, &extensionStrings);
- InsertExtensionString("EGL_KHR_image_base", imageBase, &extensionStrings);
- InsertExtensionString("EGL_KHR_image_pixmap", imagePixmap, &extensionStrings);
- InsertExtensionString("EGL_KHR_gl_texture_2D_image", glTexture2DImage, &extensionStrings);
- InsertExtensionString("EGL_KHR_gl_texture_cubemap_image", glTextureCubemapImage, &extensionStrings);
- InsertExtensionString("EGL_KHR_gl_texture_3D_image", glTexture3DImage, &extensionStrings);
- InsertExtensionString("EGL_KHR_gl_renderbuffer_image", glRenderbufferImage, &extensionStrings);
- InsertExtensionString("EGL_KHR_get_all_proc_addresses", getAllProcAddresses, &extensionStrings);
- InsertExtensionString("EGL_ANGLE_flexible_surface_compatibility", flexibleSurfaceCompatibility, &extensionStrings);
+ // | Extension name | Supported flag | Output vector |
+ InsertExtensionString("EGL_EXT_create_context_robustness", createContextRobustness, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_d3d_share_handle_client_buffer", d3dShareHandleClientBuffer, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_d3d_texture_client_buffer", d3dTextureClientBuffer, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_surface_d3d_texture_2d_share_handle", surfaceD3DTexture2DShareHandle, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_query_surface_pointer", querySurfacePointer, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_window_fixed_size", windowFixedSize, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_keyed_mutex", keyedMutex, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_surface_orientation", surfaceOrientation, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_direct_composition", directComposition, &extensionStrings);
+ InsertExtensionString("EGL_NV_post_sub_buffer", postSubBuffer, &extensionStrings);
+ InsertExtensionString("EGL_KHR_create_context", createContext, &extensionStrings);
+ InsertExtensionString("EGL_EXT_device_query", deviceQuery, &extensionStrings);
+ InsertExtensionString("EGL_KHR_image", image, &extensionStrings);
+ InsertExtensionString("EGL_KHR_image_base", imageBase, &extensionStrings);
+ InsertExtensionString("EGL_KHR_image_pixmap", imagePixmap, &extensionStrings);
+ InsertExtensionString("EGL_KHR_gl_texture_2D_image", glTexture2DImage, &extensionStrings);
+ InsertExtensionString("EGL_KHR_gl_texture_cubemap_image", glTextureCubemapImage, &extensionStrings);
+ InsertExtensionString("EGL_KHR_gl_texture_3D_image", glTexture3DImage, &extensionStrings);
+ InsertExtensionString("EGL_KHR_gl_renderbuffer_image", glRenderbufferImage, &extensionStrings);
+ InsertExtensionString("EGL_KHR_get_all_proc_addresses", getAllProcAddresses, &extensionStrings);
+ InsertExtensionString("EGL_KHR_stream", stream, &extensionStrings);
+ InsertExtensionString("EGL_KHR_stream_consumer_gltexture", streamConsumerGLTexture, &extensionStrings);
+ InsertExtensionString("EGL_NV_stream_consumer_gltexture_yuv", streamConsumerGLTextureYUV, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_flexible_surface_compatibility", flexibleSurfaceCompatibility, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_stream_producer_d3d_texture_nv12", streamProducerD3DTextureNV12, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_create_context_webgl_compatibility", createContextWebGLCompatibility, &extensionStrings);
+ InsertExtensionString("EGL_CHROMIUM_create_context_bind_generates_resource", createContextBindGeneratesResource, &extensionStrings);
+ InsertExtensionString("EGL_CHROMIUM_sync_control", getSyncValues, &extensionStrings);
+ InsertExtensionString("EGL_EXT_swap_buffers_with_damage", swapBuffersWithDamage, &extensionStrings);
+ InsertExtensionString("EGL_EXT_pixel_format_float", pixelFormatFloat, &extensionStrings);
+ InsertExtensionString("EGL_KHR_surfaceless_context", surfacelessContext, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_display_texture_share_group", displayTextureShareGroup, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_create_context_client_arrays", createContextClientArrays, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_program_cache_control", programCacheControl, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_robust_resource_initialization", robustResourceInitialization, &extensionStrings);
// TODO(jmadill): Enable this when complete.
- //InsertExtensionString("KHR_create_context_no_error", createContextNoError, &extensionStrings);
+ //InsertExtensionString("KHR_create_context_no_error", createContextNoError, &extensionStrings);
// clang-format on
return extensionStrings;
@@ -694,6 +1175,7 @@ ClientExtensions::ClientExtensions()
platformANGLE(false),
platformANGLED3D(false),
platformANGLEOpenGL(false),
+ platformANGLEVulkan(false),
deviceCreation(false),
deviceCreationD3D11(false),
x11Visual(false),
@@ -702,6 +1184,8 @@ ClientExtensions::ClientExtensions()
{
}
+ClientExtensions::ClientExtensions(const ClientExtensions &other) = default;
+
std::vector<std::string> ClientExtensions::getStrings() const
{
std::vector<std::string> extensionStrings;
@@ -714,6 +1198,8 @@ std::vector<std::string> ClientExtensions::getStrings() const
InsertExtensionString("EGL_ANGLE_platform_angle", platformANGLE, &extensionStrings);
InsertExtensionString("EGL_ANGLE_platform_angle_d3d", platformANGLED3D, &extensionStrings);
InsertExtensionString("EGL_ANGLE_platform_angle_opengl", platformANGLEOpenGL, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_platform_angle_null", platformANGLENULL, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_platform_angle_vulkan", platformANGLEVulkan, &extensionStrings);
InsertExtensionString("EGL_ANGLE_device_creation", deviceCreation, &extensionStrings);
InsertExtensionString("EGL_ANGLE_device_creation_d3d11", deviceCreationD3D11, &extensionStrings);
InsertExtensionString("EGL_ANGLE_x11_visual", x11Visual, &extensionStrings);
@@ -724,4 +1210,4 @@ std::vector<std::string> ClientExtensions::getStrings() const
return extensionStrings;
}
-}
+} // namespace egl
diff --git a/src/3rdparty/angle/src/libANGLE/Caps.h b/src/3rdparty/angle/src/libANGLE/Caps.h
index d0e839a2ba..64bdf97112 100644
--- a/src/3rdparty/angle/src/libANGLE/Caps.h
+++ b/src/3rdparty/angle/src/libANGLE/Caps.h
@@ -8,21 +8,28 @@
#define LIBANGLE_CAPS_H_
#include "angle_gl.h"
+#include "libANGLE/Version.h"
#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/Format.h"
#include <map>
#include <set>
#include <string>
#include <vector>
+#include <array>
namespace gl
{
+struct Extensions;
+
typedef std::set<GLuint> SupportedSampleSet;
struct TextureCaps
{
TextureCaps();
+ TextureCaps(const TextureCaps &other);
+ ~TextureCaps();
// Supports for basic texturing: glTexImage, glTexSubImage, etc
bool texturable;
@@ -44,26 +51,37 @@ struct TextureCaps
GLuint getNearestSamples(GLuint requestedSamples) const;
};
-class TextureCapsMap
+TextureCaps GenerateMinimumTextureCaps(GLenum internalFormat,
+ const Version &clientVersion,
+ const Extensions &extensions);
+
+class TextureCapsMap final : angle::NonCopyable
{
public:
- typedef std::map<GLenum, TextureCaps>::const_iterator const_iterator;
+ TextureCapsMap();
+ ~TextureCapsMap();
+ // These methods are deprecated. Please use angle::Format for new features.
void insert(GLenum internalFormat, const TextureCaps &caps);
- void remove(GLenum internalFormat);
-
const TextureCaps &get(GLenum internalFormat) const;
- const_iterator begin() const;
- const_iterator end() const;
+ void clear();
- size_t size() const;
+ // Prefer using angle::Format methods.
+ const TextureCaps &get(angle::Format::ID formatID) const;
+ void set(angle::Format::ID formatID, const TextureCaps &caps);
private:
- typedef std::map<GLenum, TextureCaps> InternalFormatToCapsMap;
- InternalFormatToCapsMap mCapsMap;
+ TextureCaps &get(angle::Format::ID formatID);
+
+ // Indexed by angle::Format::ID
+ std::array<TextureCaps, angle::kNumANGLEFormats> mFormatData;
};
+void InitMinimumTextureCapsMap(const Version &clientVersion,
+ const Extensions &extensions,
+ TextureCapsMap *capsMap);
+
struct Extensions
{
Extensions();
@@ -87,6 +105,7 @@ struct Extensions
// GL_EXT_sRGB
// GL_ANGLE_depth_texture, GL_OES_depth32
// GL_EXT_color_buffer_float
+ // GL_EXT_texture_norm16
void setTextureExtensionSupport(const TextureCapsMap &textureCaps);
// ES2 Extension support
@@ -141,12 +160,18 @@ struct Extensions
bool textureRG;
// GL_EXT_texture_compression_dxt1, GL_ANGLE_texture_compression_dxt3 and GL_ANGLE_texture_compression_dxt5
- // Implies that TextureCaps for GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
+ // Implies that TextureCaps exist for GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
// GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE and GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE
bool textureCompressionDXT1;
bool textureCompressionDXT3;
bool textureCompressionDXT5;
+ // GL_EXT_texture_compression_s3tc_srgb
+ // Implies that TextureCaps exist for GL_COMPRESSED_SRGB_S3TC_DXT1_EXT,
+ // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, and
+ // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
+ bool textureCompressionS3TCsRGB;
+
// GL_KHR_texture_compression_astc_hdr
bool textureCompressionASTCHDR;
@@ -188,9 +213,6 @@ struct Extensions
// GL_NV_fence
bool fence;
- // GL_ANGLE_timer_query
- bool timerQuery;
-
// GL_EXT_disjoint_timer_query
bool disjointTimerQuery;
GLuint queryCounterBitsTimeElapsed;
@@ -199,6 +221,9 @@ struct Extensions
// GL_EXT_robustness
bool robustness;
+ // GL_KHR_robust_buffer_access_behavior
+ bool robustBufferAccessBehavior;
+
// GL_EXT_blend_minmax
bool blendMinMax;
@@ -220,18 +245,13 @@ struct Extensions
// GL_EXT_shader_texture_lod
bool shaderTextureLOD;
- // GL_EXT_shader_framebuffer_fetch
- bool shaderFramebufferFetch;
-
- // GL_ARM_shader_framebuffer_fetch
- bool ARMshaderFramebufferFetch;
-
- // GL_NV_shader_framebuffer_fetch
- bool NVshaderFramebufferFetch;
-
// GL_EXT_frag_depth
bool fragDepth;
+ // ANGLE_multiview
+ bool multiview;
+ GLuint maxViews;
+
// GL_ANGLE_texture_usage
bool textureUsage;
@@ -256,6 +276,9 @@ struct Extensions
// GL_OES_EGL_image_external_essl3
bool eglImageExternalEssl3;
+ // NV_EGL_stream_consumer_external
+ bool eglStreamConsumerExternal;
+
// EXT_unpack_subimage
bool unpackSubimage;
@@ -278,12 +301,98 @@ struct Extensions
// GL_ANGLE_lossy_etc_decode
bool lossyETCDecode;
+ // GL_CHROMIUM_bind_uniform_location
+ bool bindUniformLocation;
+
+ // GL_CHROMIUM_sync_query
+ bool syncQuery;
+
+ // GL_CHROMIUM_copy_texture
+ bool copyTexture;
+
+ // GL_CHROMIUM_copy_compressed_texture
+ bool copyCompressedTexture;
+
+ // GL_ANGLE_webgl_compatibility
+ bool webglCompatibility;
+
+ // GL_ANGLE_request_extension
+ bool requestExtension;
+
+ // GL_CHROMIUM_bind_generates_resource
+ bool bindGeneratesResource;
+
+ // GL_ANGLE_robust_client_memory
+ bool robustClientMemory;
+
+ // GL_EXT_texture_sRGB_decode
+ bool textureSRGBDecode;
+
+ // GL_EXT_sRGB_write_control
+ bool sRGBWriteControl;
+
+ // GL_CHROMIUM_color_buffer_float_rgb
+ bool colorBufferFloatRGB;
+
+ // GL_CHROMIUM_color_buffer_float_rgba
+ bool colorBufferFloatRGBA;
+
// ES3 Extension support
// GL_EXT_color_buffer_float
bool colorBufferFloat;
+
+ // GL_EXT_multisample_compatibility.
+ // written against ES 3.1 but can apply to earlier versions.
+ bool multisampleCompatibility;
+
+ // GL_CHROMIUM_framebuffer_mixed_samples
+ bool framebufferMixedSamples;
+
+ // GL_EXT_texture_norm16
+ // written against ES 3.1 but can apply to ES 3.0 as well.
+ bool textureNorm16;
+
+ // GL_CHROMIUM_path_rendering
+ bool pathRendering;
+
+ // GL_OES_surfaceless_context
+ bool surfacelessContext;
+
+ // GL_ANGLE_client_arrays
+ bool clientArrays;
+
+ // GL_ANGLE_robust_resource_initialization
+ bool robustResourceInitialization;
+
+ // GL_ANGLE_program_cache_control
+ bool programCacheControl;
+
+ // GL_ANGLE_texture_rectangle
+ bool textureRectangle;
+
+ // GL_EXT_geometry_shader
+ bool geometryShader;
+ // GL_EXT_geometry_shader (May 31, 2016) Table 20.43gs: Implementation dependent geometry shader
+ // limits
+ // TODO(jiawei.shao@intel.com): add all implementation dependent geometry shader limits.
+ GLuint maxGeometryOutputVertices;
+ GLuint maxGeometryShaderInvocations;
};
+struct ExtensionInfo
+{
+ // If this extension can be enabled with glRequestExtension (GL_ANGLE_request_extension)
+ bool Requestable = false;
+
+ // Pointer to a boolean member of the Extensions struct
+ typedef bool(Extensions::*ExtensionBool);
+ ExtensionBool ExtensionsMember = nullptr;
+};
+
+using ExtensionInfoMap = std::map<std::string, ExtensionInfo>;
+const ExtensionInfoMap &GetExtensionInfoMap();
+
struct Limitations
{
Limitations();
@@ -311,39 +420,57 @@ struct Limitations
struct TypePrecision
{
TypePrecision();
+ TypePrecision(const TypePrecision &other);
void setIEEEFloat();
void setTwosComplementInt(unsigned int bits);
+ void setSimulatedFloat(unsigned int range, unsigned int precision);
void setSimulatedInt(unsigned int range);
void get(GLint *returnRange, GLint *returnPrecision) const;
- GLint range[2];
+ std::array<GLint, 2> range;
GLint precision;
};
struct Caps
{
Caps();
+ Caps(const Caps &other);
+ ~Caps();
- // Table 6.28, implementation dependent values
+ // ES 3.1 (April 29, 2015) 20.39: implementation dependent values
GLuint64 maxElementIndex;
GLuint max3DTextureSize;
GLuint max2DTextureSize;
+ GLuint maxRectangleTextureSize;
GLuint maxArrayTextureLayers;
GLfloat maxLODBias;
GLuint maxCubeMapTextureSize;
GLuint maxRenderbufferSize;
- GLuint maxDrawBuffers;
- GLuint maxColorAttachments;
- GLuint maxViewportWidth;
- GLuint maxViewportHeight;
GLfloat minAliasedPointSize;
GLfloat maxAliasedPointSize;
GLfloat minAliasedLineWidth;
GLfloat maxAliasedLineWidth;
- // Table 6.29, implementation dependent values (cont.)
+ // ES 3.1 (April 29, 2015) 20.40: implementation dependent values (cont.)
+ GLuint maxDrawBuffers;
+ GLuint maxFramebufferWidth;
+ GLuint maxFramebufferHeight;
+ GLuint maxFramebufferSamples;
+ GLuint maxColorAttachments;
+ GLuint maxViewportWidth;
+ GLuint maxViewportHeight;
+ GLuint maxSampleMaskWords;
+ GLuint maxColorTextureSamples;
+ GLuint maxDepthTextureSamples;
+ GLuint maxIntegerSamples;
+ GLuint64 maxServerWaitTimeout;
+
+ // ES 3.1 (April 29, 2015) Table 20.41: Implementation dependent values (cont.)
+ GLint maxVertexAttribRelativeOffset;
+ GLuint maxVertexAttribBindings;
+ GLint maxVertexAttribStride;
GLuint maxElementsIndices;
GLuint maxElementsVertices;
std::vector<GLenum> compressedTextureFormats;
@@ -361,26 +488,49 @@ struct Caps
TypePrecision fragmentHighpInt;
TypePrecision fragmentMediumpInt;
TypePrecision fragmentLowpInt;
- GLuint64 maxServerWaitTimeout;
- // Table 6.31, implementation dependent vertex shader limits
+ // ES 3.1 (April 29, 2015) Table 20.43: Implementation dependent Vertex shader limits
GLuint maxVertexAttributes;
GLuint maxVertexUniformComponents;
GLuint maxVertexUniformVectors;
GLuint maxVertexUniformBlocks;
GLuint maxVertexOutputComponents;
GLuint maxVertexTextureImageUnits;
+ GLuint maxVertexAtomicCounterBuffers;
+ GLuint maxVertexAtomicCounters;
+ GLuint maxVertexImageUniforms;
+ GLuint maxVertexShaderStorageBlocks;
- // Table 6.32, implementation dependent fragment shader limits
+ // ES 3.1 (April 29, 2015) Table 20.44: Implementation dependent Fragment shader limits
GLuint maxFragmentUniformComponents;
GLuint maxFragmentUniformVectors;
GLuint maxFragmentUniformBlocks;
GLuint maxFragmentInputComponents;
GLuint maxTextureImageUnits;
+ GLuint maxFragmentAtomicCounterBuffers;
+ GLuint maxFragmentAtomicCounters;
+ GLuint maxFragmentImageUniforms;
+ GLuint maxFragmentShaderStorageBlocks;
+ GLint minProgramTextureGatherOffset;
+ GLuint maxProgramTextureGatherOffset;
GLint minProgramTexelOffset;
GLint maxProgramTexelOffset;
- // Table 6.33, implementation dependent aggregate shader limits
+ // ES 3.1 (April 29, 2015) Table 20.45: implementation dependent compute shader limits
+ std::array<GLuint, 3> maxComputeWorkGroupCount;
+ std::array<GLuint, 3> maxComputeWorkGroupSize;
+ GLuint maxComputeWorkGroupInvocations;
+ GLuint maxComputeUniformBlocks;
+ GLuint maxComputeTextureImageUnits;
+ GLuint maxComputeSharedMemorySize;
+ GLuint maxComputeUniformComponents;
+ GLuint maxComputeAtomicCounterBuffers;
+ GLuint maxComputeAtomicCounters;
+ GLuint maxComputeImageUniforms;
+ GLuint maxCombinedComputeUniformComponents;
+ GLuint maxComputeShaderStorageBlocks;
+
+ // ES 3.1 (April 29, 2015) Table 20.46: implementation dependent aggregate shader limits
GLuint maxUniformBufferBindings;
GLuint64 maxUniformBlockSize;
GLuint uniformBufferOffsetAlignment;
@@ -390,16 +540,31 @@ struct Caps
GLuint maxVaryingComponents;
GLuint maxVaryingVectors;
GLuint maxCombinedTextureImageUnits;
-
- // Table 6.34, implementation dependent transform feedback limits
+ GLuint maxCombinedShaderOutputResources;
+
+ // ES 3.1 (April 29, 2015) Table 20.47: implementation dependent aggregate shader limits (cont.)
+ GLuint maxUniformLocations;
+ GLuint maxAtomicCounterBufferBindings;
+ GLuint maxAtomicCounterBufferSize;
+ GLuint maxCombinedAtomicCounterBuffers;
+ GLuint maxCombinedAtomicCounters;
+ GLuint maxImageUnits;
+ GLuint maxCombinedImageUniforms;
+ GLuint maxShaderStorageBufferBindings;
+ GLuint64 maxShaderStorageBlockSize;
+ GLuint maxCombinedShaderStorageBlocks;
+ GLuint shaderStorageBufferOffsetAlignment;
+
+ // ES 3.1 (April 29, 2015) Table 20.48: implementation dependent transform feedback limits
GLuint maxTransformFeedbackInterleavedComponents;
GLuint maxTransformFeedbackSeparateAttributes;
GLuint maxTransformFeedbackSeparateComponents;
- // Table 6.35, Framebuffer Dependent Values
+ // ES 3.1 (April 29, 2015) Table 20.49: Framebuffer Dependent Values
GLuint maxSamples;
};
+Caps GenerateMinimumCaps(const Version &clientVersion, const Extensions &extensions);
}
namespace egl
@@ -426,6 +591,9 @@ struct DisplayExtensions
// EGL_ANGLE_d3d_share_handle_client_buffer
bool d3dShareHandleClientBuffer;
+ // EGL_ANGLE_d3d_texture_client_buffer
+ bool d3dTextureClientBuffer;
+
// EGL_ANGLE_surface_d3d_texture_2d_share_handle
bool surfaceD3DTexture2DShareHandle;
@@ -482,6 +650,48 @@ struct DisplayExtensions
// KHR_create_context_no_error
bool createContextNoError;
+
+ // EGL_KHR_stream
+ bool stream;
+
+ // EGL_KHR_stream_consumer_gltexture
+ bool streamConsumerGLTexture;
+
+ // EGL_NV_stream_consumer_gltexture_yuv
+ bool streamConsumerGLTextureYUV;
+
+ // EGL_ANGLE_stream_producer_d3d_texture_nv12
+ bool streamProducerD3DTextureNV12;
+
+ // EGL_ANGLE_create_context_webgl_compatibility
+ bool createContextWebGLCompatibility;
+
+ // EGL_CHROMIUM_create_context_bind_generates_resource
+ bool createContextBindGeneratesResource;
+
+ // EGL_CHROMIUM_get_sync_values
+ bool getSyncValues;
+
+ // EGL_EXT_swap_buffers_with_damage
+ bool swapBuffersWithDamage;
+
+ // EGL_EXT_pixel_format_float
+ bool pixelFormatFloat;
+
+ // EGL_KHR_surfaceless_context
+ bool surfacelessContext;
+
+ // EGL_ANGLE_display_texture_share_group
+ bool displayTextureShareGroup;
+
+ // EGL_ANGLE_create_context_client_arrays
+ bool createContextClientArrays;
+
+ // EGL_ANGLE_program_cache_control
+ bool programCacheControl;
+
+ // EGL_ANGLE_robust_resource_initialization
+ bool robustResourceInitialization;
};
struct DeviceExtensions
@@ -498,6 +708,7 @@ struct DeviceExtensions
struct ClientExtensions
{
ClientExtensions();
+ ClientExtensions(const ClientExtensions &other);
// Generate a vector of supported extension strings
std::vector<std::string> getStrings() const;
@@ -520,6 +731,12 @@ struct ClientExtensions
// EGL_ANGLE_platform_angle_opengl
bool platformANGLEOpenGL;
+ // EGL_ANGLE_platform_angle_null
+ bool platformANGLENULL;
+
+ // EGL_ANGLE_platform_angle_vulkan
+ bool platformANGLEVulkan;
+
// EGL_ANGLE_device_creation
bool deviceCreation;
@@ -536,6 +753,6 @@ struct ClientExtensions
bool clientGetAllProcAddresses;
};
-}
+} // namespace egl
#endif // LIBANGLE_CAPS_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Compiler.cpp b/src/3rdparty/angle/src/libANGLE/Compiler.cpp
index 348c41bef3..236c7e1fc2 100644
--- a/src/3rdparty/angle/src/libANGLE/Compiler.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Compiler.cpp
@@ -9,9 +9,9 @@
#include "libANGLE/Compiler.h"
#include "common/debug.h"
-#include "libANGLE/Data.h"
+#include "libANGLE/ContextState.h"
#include "libANGLE/renderer/CompilerImpl.h"
-#include "libANGLE/renderer/ImplFactory.h"
+#include "libANGLE/renderer/GLImplFactory.h"
namespace gl
{
@@ -19,26 +19,46 @@ namespace gl
namespace
{
-// Global count of active shader compiler handles. Needed to know when to call ShInitialize and
-// ShFinalize.
+// Global count of active shader compiler handles. Needed to know when to call sh::Initialize and
+// sh::Finalize.
size_t activeCompilerHandles = 0;
+ShShaderSpec SelectShaderSpec(GLint majorVersion, GLint minorVersion, bool isWebGL)
+{
+ if (majorVersion >= 3)
+ {
+ if (minorVersion == 1)
+ {
+ return isWebGL ? SH_WEBGL3_SPEC : SH_GLES3_1_SPEC;
+ }
+ else
+ {
+ return isWebGL ? SH_WEBGL2_SPEC : SH_GLES3_SPEC;
+ }
+ }
+ return isWebGL ? SH_WEBGL_SPEC : SH_GLES2_SPEC;
+}
+
} // anonymous namespace
-Compiler::Compiler(rx::ImplFactory *implFactory, const gl::Data &data)
+Compiler::Compiler(rx::GLImplFactory *implFactory, const ContextState &state)
: mImplementation(implFactory->createCompiler()),
- mSpec(data.clientVersion > 2 ? SH_GLES3_SPEC : SH_GLES2_SPEC),
+ mSpec(SelectShaderSpec(state.getClientMajorVersion(),
+ state.getClientMinorVersion(),
+ state.getExtensions().webglCompatibility)),
mOutputType(mImplementation->getTranslatorOutputType()),
mResources(),
mFragmentCompiler(nullptr),
- mVertexCompiler(nullptr)
+ mVertexCompiler(nullptr),
+ mComputeCompiler(nullptr),
+ mGeometryCompiler(nullptr)
{
- ASSERT(data.clientVersion == 2 || data.clientVersion == 3);
+ ASSERT(state.getClientMajorVersion() == 2 || state.getClientMajorVersion() == 3);
- const gl::Caps &caps = *data.caps;
- const gl::Extensions &extensions = *data.extensions;
+ const gl::Caps &caps = state.getCaps();
+ const gl::Extensions &extensions = state.getExtensions();
- ShInitBuiltInResources(&mResources);
+ sh::InitBuiltInResources(&mResources);
mResources.MaxVertexAttribs = caps.maxVertexAttributes;
mResources.MaxVertexUniformVectors = caps.maxVertexUniformVectors;
mResources.MaxVaryingVectors = caps.maxVaryingVectors;
@@ -50,30 +70,79 @@ Compiler::Compiler(rx::ImplFactory *implFactory, const gl::Data &data)
mResources.OES_standard_derivatives = extensions.standardDerivatives;
mResources.EXT_draw_buffers = extensions.drawBuffers;
mResources.EXT_shader_texture_lod = extensions.shaderTextureLOD;
- // TODO: disabled until the extension is actually supported.
- mResources.OES_EGL_image_external = 0;
+ mResources.OES_EGL_image_external = extensions.eglImageExternal;
+ mResources.OES_EGL_image_external_essl3 = extensions.eglImageExternalEssl3;
+ mResources.NV_EGL_stream_consumer_external = extensions.eglStreamConsumerExternal;
+ mResources.ARB_texture_rectangle = extensions.textureRectangle;
// TODO: use shader precision caps to determine if high precision is supported?
mResources.FragmentPrecisionHigh = 1;
mResources.EXT_frag_depth = extensions.fragDepth;
+ // OVR_multiview state
+ mResources.OVR_multiview = extensions.multiview;
+ mResources.MaxViewsOVR = extensions.maxViews;
+
// GLSL ES 3.0 constants
mResources.MaxVertexOutputVectors = caps.maxVertexOutputComponents / 4;
mResources.MaxFragmentInputVectors = caps.maxFragmentInputComponents / 4;
mResources.MinProgramTexelOffset = caps.minProgramTexelOffset;
mResources.MaxProgramTexelOffset = caps.maxProgramTexelOffset;
-}
-Compiler::~Compiler()
-{
- release();
- SafeDelete(mImplementation);
+ // GLSL ES 3.1 constants
+ mResources.MaxProgramTextureGatherOffset = caps.maxProgramTextureGatherOffset;
+ mResources.MinProgramTextureGatherOffset = caps.minProgramTextureGatherOffset;
+ mResources.MaxImageUnits = caps.maxImageUnits;
+ mResources.MaxVertexImageUniforms = caps.maxVertexImageUniforms;
+ mResources.MaxFragmentImageUniforms = caps.maxFragmentImageUniforms;
+ mResources.MaxComputeImageUniforms = caps.maxComputeImageUniforms;
+ mResources.MaxCombinedImageUniforms = caps.maxCombinedImageUniforms;
+ mResources.MaxCombinedShaderOutputResources = caps.maxCombinedShaderOutputResources;
+ mResources.MaxUniformLocations = caps.maxUniformLocations;
+
+ for (size_t index = 0u; index < 3u; ++index)
+ {
+ mResources.MaxComputeWorkGroupCount[index] = caps.maxComputeWorkGroupCount[index];
+ mResources.MaxComputeWorkGroupSize[index] = caps.maxComputeWorkGroupSize[index];
+ }
+
+ mResources.MaxComputeUniformComponents = caps.maxComputeUniformComponents;
+ mResources.MaxComputeTextureImageUnits = caps.maxComputeTextureImageUnits;
+
+ mResources.MaxComputeAtomicCounters = caps.maxComputeAtomicCounters;
+ mResources.MaxComputeAtomicCounterBuffers = caps.maxComputeAtomicCounterBuffers;
+
+ mResources.MaxVertexAtomicCounters = caps.maxVertexAtomicCounters;
+ mResources.MaxFragmentAtomicCounters = caps.maxFragmentAtomicCounters;
+ mResources.MaxCombinedAtomicCounters = caps.maxCombinedAtomicCounters;
+ mResources.MaxAtomicCounterBindings = caps.maxAtomicCounterBufferBindings;
+ mResources.MaxVertexAtomicCounterBuffers = caps.maxVertexAtomicCounterBuffers;
+ mResources.MaxFragmentAtomicCounterBuffers = caps.maxFragmentAtomicCounterBuffers;
+ mResources.MaxCombinedAtomicCounterBuffers = caps.maxCombinedAtomicCounterBuffers;
+ mResources.MaxAtomicCounterBufferSize = caps.maxAtomicCounterBufferSize;
+
+ mResources.MaxUniformBufferBindings = caps.maxUniformBufferBindings;
+ mResources.MaxShaderStorageBufferBindings = caps.maxShaderStorageBufferBindings;
+
+ // Needed by point size clamping workaround
+ mResources.MaxPointSize = caps.maxAliasedPointSize;
+
+ if (state.getClientMajorVersion() == 2 && !extensions.drawBuffers)
+ {
+ mResources.MaxDrawBuffers = 1;
+ }
+
+ // Geometry Shader constants
+ mResources.OES_geometry_shader = extensions.geometryShader;
+ // TODO(jiawei.shao@intel.com): initialize all implementation dependent geometry shader limits.
+ mResources.MaxGeometryOutputVertices = extensions.maxGeometryOutputVertices;
+ mResources.MaxGeometryShaderInvocations = extensions.maxGeometryShaderInvocations;
}
-Error Compiler::release()
+Compiler::~Compiler()
{
if (mFragmentCompiler)
{
- ShDestruct(mFragmentCompiler);
+ sh::Destruct(mFragmentCompiler);
mFragmentCompiler = nullptr;
ASSERT(activeCompilerHandles > 0);
@@ -82,21 +151,28 @@ Error Compiler::release()
if (mVertexCompiler)
{
- ShDestruct(mVertexCompiler);
+ sh::Destruct(mVertexCompiler);
mVertexCompiler = nullptr;
ASSERT(activeCompilerHandles > 0);
activeCompilerHandles--;
}
- if (activeCompilerHandles == 0)
+ if (mComputeCompiler)
{
- ShFinalize();
+ sh::Destruct(mComputeCompiler);
+ mComputeCompiler = nullptr;
+
+ ASSERT(activeCompilerHandles > 0);
+ activeCompilerHandles--;
}
- mImplementation->release();
+ if (activeCompilerHandles == 0)
+ {
+ sh::Finalize();
+ }
- return gl::Error(GL_NO_ERROR);
+ ANGLE_SWALLOW_ERR(mImplementation->release());
}
ShHandle Compiler::getCompilerHandle(GLenum type)
@@ -111,7 +187,12 @@ ShHandle Compiler::getCompilerHandle(GLenum type)
case GL_FRAGMENT_SHADER:
compiler = &mFragmentCompiler;
break;
-
+ case GL_COMPUTE_SHADER:
+ compiler = &mComputeCompiler;
+ break;
+ case GL_GEOMETRY_SHADER_EXT:
+ compiler = &mGeometryCompiler;
+ break;
default:
UNREACHABLE();
return nullptr;
@@ -121,14 +202,20 @@ ShHandle Compiler::getCompilerHandle(GLenum type)
{
if (activeCompilerHandles == 0)
{
- ShInitialize();
+ sh::Initialize();
}
- *compiler = ShConstructCompiler(type, mSpec, mOutputType, &mResources);
+ *compiler = sh::ConstructCompiler(type, mSpec, mOutputType, &mResources);
+ ASSERT(*compiler);
activeCompilerHandles++;
}
return *compiler;
}
+const std::string &Compiler::getBuiltinResourcesString(GLenum type)
+{
+ return sh::GetBuiltInResourcesString(getCompilerHandle(type));
+}
+
} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/Compiler.h b/src/3rdparty/angle/src/libANGLE/Compiler.h
index 8634e39a45..b7f7e9f31b 100644
--- a/src/3rdparty/angle/src/libANGLE/Compiler.h
+++ b/src/3rdparty/angle/src/libANGLE/Compiler.h
@@ -10,38 +10,40 @@
#ifndef LIBANGLE_COMPILER_H_
#define LIBANGLE_COMPILER_H_
-#include "libANGLE/Error.h"
#include "GLSLANG/ShaderLang.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
namespace rx
{
class CompilerImpl;
-class ImplFactory;
+class GLImplFactory;
}
namespace gl
{
-struct Data;
+class ContextState;
-class Compiler final : angle::NonCopyable
+class Compiler final : public RefCountObjectNoID
{
public:
- Compiler(rx::ImplFactory *implFactory, const Data &data);
- ~Compiler();
-
- Error release();
+ Compiler(rx::GLImplFactory *implFactory, const ContextState &data);
ShHandle getCompilerHandle(GLenum type);
ShShaderOutput getShaderOutputType() const { return mOutputType; }
+ const std::string &getBuiltinResourcesString(GLenum type);
private:
- rx::CompilerImpl *mImplementation;
+ ~Compiler() override;
+ std::unique_ptr<rx::CompilerImpl> mImplementation;
ShShaderSpec mSpec;
ShShaderOutput mOutputType;
ShBuiltInResources mResources;
ShHandle mFragmentCompiler;
ShHandle mVertexCompiler;
+ ShHandle mComputeCompiler;
+ ShHandle mGeometryCompiler;
};
} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/Config.cpp b/src/3rdparty/angle/src/libANGLE/Config.cpp
index d511df3a69..172c312ae0 100644
--- a/src/3rdparty/angle/src/libANGLE/Config.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Config.cpp
@@ -58,10 +58,27 @@ Config::Config()
transparentRedValue(0),
transparentGreenValue(0),
transparentBlueValue(0),
- optimalOrientation(0)
+ optimalOrientation(0),
+ colorComponentType(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT)
{
}
+Config::~Config()
+{
+}
+
+Config::Config(const Config &other) = default;
+
+Config &Config::operator=(const Config &other) = default;
+
+ConfigSet::ConfigSet() = default;
+
+ConfigSet::ConfigSet(const ConfigSet &other) = default;
+
+ConfigSet &ConfigSet::operator=(const ConfigSet &other) = default;
+
+ConfigSet::~ConfigSet() = default;
+
EGLint ConfigSet::add(const Config &config)
{
// Set the config's ID to a small number that starts at 1 ([EGL 1.5] section 3.4)
@@ -134,6 +151,10 @@ class ConfigSorter
static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG, "Unexpected EGL enum value.");
SORT(configCaveat);
+ static_assert(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT < EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
+ "Unexpected order of EGL enums.");
+ SORT(colorComponentType);
+
static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, "Unexpected EGL enum value.");
SORT(colorBufferType);
@@ -160,6 +181,7 @@ class ConfigSorter
}
private:
+
void scanForWantedComponents(const AttributeMap &attributeMap)
{
// [EGL 1.5] section 3.4.1.2 page 30
@@ -215,8 +237,13 @@ std::vector<const Config*> ConfigSet::filter(const AttributeMap &attributeMap) c
for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++)
{
- EGLint attributeKey = attribIter->first;
- EGLint attributeValue = attribIter->second;
+ EGLAttrib attributeKey = attribIter->first;
+ EGLAttrib attributeValue = attribIter->second;
+
+ if (attributeValue == EGL_DONT_CARE)
+ {
+ continue;
+ }
switch (attributeKey)
{
@@ -255,6 +282,9 @@ std::vector<const Config*> ConfigSet::filter(const AttributeMap &attributeMap) c
case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
match = config.optimalOrientation == attributeValue;
break;
+ case EGL_COLOR_COMPONENT_TYPE_EXT:
+ match = config.colorComponentType == static_cast<EGLenum>(attributeValue);
+ break;
default: UNREACHABLE();
}
diff --git a/src/3rdparty/angle/src/libANGLE/Config.h b/src/3rdparty/angle/src/libANGLE/Config.h
index 00f5673b59..f2fbe8b95a 100644
--- a/src/3rdparty/angle/src/libANGLE/Config.h
+++ b/src/3rdparty/angle/src/libANGLE/Config.h
@@ -27,6 +27,9 @@ namespace egl
struct Config
{
Config();
+ ~Config();
+ Config(const Config &other);
+ Config &operator=(const Config &other);
GLenum renderTargetFormat; // TODO(geofflang): remove this
GLenum depthStencilFormat; // TODO(geofflang): remove this
@@ -65,11 +68,17 @@ struct Config
EGLint transparentGreenValue; // Transparent green value
EGLint transparentBlueValue; // Transparent blue value
EGLint optimalOrientation; // Optimal window surface orientation
+ EGLenum colorComponentType; // Color component type
};
class ConfigSet
{
public:
+ ConfigSet();
+ ConfigSet(const ConfigSet &other);
+ ~ConfigSet();
+ ConfigSet &operator=(const ConfigSet &other);
+
EGLint add(const Config &config);
const Config &get(EGLint id) const;
@@ -83,7 +92,7 @@ class ConfigSet
std::vector<const Config*> filter(const AttributeMap &attributeMap) const;
private:
- typedef std::map<EGLint, const Config> ConfigMap;
+ typedef std::map<EGLint, Config> ConfigMap;
ConfigMap mConfigs;
};
diff --git a/src/3rdparty/angle/src/libANGLE/Constants.h b/src/3rdparty/angle/src/libANGLE/Constants.h
index dc8f9555b8..2fe921af38 100644
--- a/src/3rdparty/angle/src/libANGLE/Constants.h
+++ b/src/3rdparty/angle/src/libANGLE/Constants.h
@@ -9,36 +9,54 @@
#ifndef LIBANGLE_CONSTANTS_H_
#define LIBANGLE_CONSTANTS_H_
+#include "common/platform.h"
+
namespace gl
{
+// The binary cache is currently left disable by default, and the application can enable it.
+const size_t kDefaultMaxProgramCacheMemoryBytes = 0;
+
enum
{
- MAX_VERTEX_ATTRIBS = 16,
+ // Implementation upper limits, real maximums depend on the hardware
+ MAX_SAMPLE_MASK_WORDS = 2,
+
+ MAX_VERTEX_ATTRIBS = 16,
+ MAX_VERTEX_ATTRIB_BINDINGS = 16,
// Implementation upper limits, real maximums depend on the hardware
IMPLEMENTATION_MAX_VARYING_VECTORS = 32,
- IMPLEMENTATION_MAX_DRAW_BUFFERS = 8,
- IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS = IMPLEMENTATION_MAX_DRAW_BUFFERS + 2, // 2 extra for depth and/or stencil buffers
+ IMPLEMENTATION_MAX_DRAW_BUFFERS = 8,
+ IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS =
+ IMPLEMENTATION_MAX_DRAW_BUFFERS + 2, // 2 extra for depth and/or stencil buffers
- IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS = 16,
+ IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS = 16,
IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS = 16,
- IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS = IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS +
- IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS,
+ IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS =
+ IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS +
+ IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS,
IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS = 4,
+ // Maximum number of views which are supported by the implementation of ANGLE_multiview.
+ IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS = 4,
+
// These are the maximums the implementation can support
// The actual GL caps are limited by the device caps
// and should be queried from the Context
- IMPLEMENTATION_MAX_2D_TEXTURE_SIZE = 16384,
- IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE = 16384,
- IMPLEMENTATION_MAX_3D_TEXTURE_SIZE = 2048,
+ IMPLEMENTATION_MAX_2D_TEXTURE_SIZE = 16384,
+ IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE = 16384,
+ IMPLEMENTATION_MAX_3D_TEXTURE_SIZE = 2048,
IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS = 2048,
- IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15 // 1+log2 of MAX_TEXTURE_SIZE
-};
+ // 1+log2 of max of MAX_*_TEXTURE_SIZE
+ IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15,
+ // Limit active textures so we can use fast bitsets.
+ IMPLEMENTATION_MAX_SHADER_TEXTURES = 32,
+ IMPLEMENTATION_MAX_ACTIVE_TEXTURES = IMPLEMENTATION_MAX_SHADER_TEXTURES * 2,
+};
}
#endif // LIBANGLE_CONSTANTS_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Context.cpp b/src/3rdparty/angle/src/libANGLE/Context.cpp
index 26f2970068..f638beda58 100644
--- a/src/3rdparty/angle/src/libANGLE/Context.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Context.cpp
@@ -9,18 +9,24 @@
#include "libANGLE/Context.h"
+#include <string.h>
#include <iterator>
#include <sstream>
+#include <vector>
+#include "common/matrix_utils.h"
#include "common/platform.h"
#include "common/utilities.h"
+#include "common/version.h"
#include "libANGLE/Buffer.h"
#include "libANGLE/Compiler.h"
#include "libANGLE/Display.h"
#include "libANGLE/Fence.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Path.h"
#include "libANGLE/Program.h"
+#include "libANGLE/ProgramPipeline.h"
#include "libANGLE/Query.h"
#include "libANGLE/Renderbuffer.h"
#include "libANGLE/ResourceManager.h"
@@ -29,36 +35,97 @@
#include "libANGLE/Texture.h"
#include "libANGLE/TransformFeedback.h"
#include "libANGLE/VertexArray.h"
+#include "libANGLE/Workarounds.h"
#include "libANGLE/formatutils.h"
+#include "libANGLE/queryconversions.h"
+#include "libANGLE/queryutils.h"
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/EGLImplFactory.h"
+#include "libANGLE/renderer/Format.h"
#include "libANGLE/validationES.h"
-#include "libANGLE/renderer/Renderer.h"
namespace
{
+#define ANGLE_HANDLE_ERR(X) \
+ handleError(X); \
+ return;
+#define ANGLE_CONTEXT_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, ANGLE_HANDLE_ERR);
+
+template <typename T>
+std::vector<gl::Path *> GatherPaths(gl::PathManager &resourceManager,
+ GLsizei numPaths,
+ const void *paths,
+ GLuint pathBase)
+{
+ std::vector<gl::Path *> ret;
+ ret.reserve(numPaths);
+
+ const auto *nameArray = static_cast<const T *>(paths);
+
+ for (GLsizei i = 0; i < numPaths; ++i)
+ {
+ const GLuint pathName = nameArray[i] + pathBase;
+
+ ret.push_back(resourceManager.getPath(pathName));
+ }
+
+ return ret;
+}
+
+std::vector<gl::Path *> GatherPaths(gl::PathManager &resourceManager,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase)
+{
+ switch (pathNameType)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GatherPaths<GLubyte>(resourceManager, numPaths, paths, pathBase);
+
+ case GL_BYTE:
+ return GatherPaths<GLbyte>(resourceManager, numPaths, paths, pathBase);
+
+ case GL_UNSIGNED_SHORT:
+ return GatherPaths<GLushort>(resourceManager, numPaths, paths, pathBase);
+
+ case GL_SHORT:
+ return GatherPaths<GLshort>(resourceManager, numPaths, paths, pathBase);
+
+ case GL_UNSIGNED_INT:
+ return GatherPaths<GLuint>(resourceManager, numPaths, paths, pathBase);
+
+ case GL_INT:
+ return GatherPaths<GLint>(resourceManager, numPaths, paths, pathBase);
+ }
+
+ UNREACHABLE();
+ return std::vector<gl::Path *>();
+}
+
template <typename T>
-gl::Error GetQueryObjectParameter(gl::Context *context, GLuint id, GLenum pname, T *params)
+gl::Error GetQueryObjectParameter(gl::Query *query, GLenum pname, T *params)
{
- gl::Query *queryObject = context->getQuery(id, false, GL_NONE);
- ASSERT(queryObject != nullptr);
+ ASSERT(query != nullptr);
switch (pname)
{
case GL_QUERY_RESULT_EXT:
- return queryObject->getResult(params);
+ return query->getResult(params);
case GL_QUERY_RESULT_AVAILABLE_EXT:
{
bool available;
- gl::Error error = queryObject->isResultAvailable(&available);
+ gl::Error error = query->isResultAvailable(&available);
if (!error.isError())
{
- *params = static_cast<T>(available ? GL_TRUE : GL_FALSE);
+ *params = gl::CastFromStateValue<T>(pname, static_cast<GLuint>(available));
}
return error;
}
default:
UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION, "Unreachable Error");
+ return gl::InternalError() << "Unreachable Error";
}
}
@@ -69,7 +136,7 @@ void MarkTransformFeedbackBufferUsage(gl::TransformFeedback *transformFeedback)
for (size_t tfBufferIndex = 0; tfBufferIndex < transformFeedback->getIndexedBufferCount();
tfBufferIndex++)
{
- const OffsetBindingPointer<gl::Buffer> &buffer =
+ const gl::OffsetBindingPointer<gl::Buffer> &buffer =
transformFeedback->getIndexedBuffer(tfBufferIndex);
if (buffer.get() != nullptr)
{
@@ -80,15 +147,25 @@ void MarkTransformFeedbackBufferUsage(gl::TransformFeedback *transformFeedback)
}
// Attribute map queries.
-EGLint GetClientVersion(const egl::AttributeMap &attribs)
+EGLint GetClientMajorVersion(const egl::AttributeMap &attribs)
+{
+ return static_cast<EGLint>(attribs.get(EGL_CONTEXT_CLIENT_VERSION, 1));
+}
+
+EGLint GetClientMinorVersion(const egl::AttributeMap &attribs)
+{
+ return static_cast<EGLint>(attribs.get(EGL_CONTEXT_MINOR_VERSION, 0));
+}
+
+gl::Version GetClientVersion(const egl::AttributeMap &attribs)
{
- return attribs.get(EGL_CONTEXT_CLIENT_VERSION, 1);
+ return gl::Version(GetClientMajorVersion(attribs), GetClientMinorVersion(attribs));
}
GLenum GetResetStrategy(const egl::AttributeMap &attribs)
{
- EGLenum attrib = attribs.get(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT,
- EGL_NO_RESET_NOTIFICATION_EXT);
+ EGLAttrib attrib = attribs.get(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT,
+ EGL_NO_RESET_NOTIFICATION);
switch (attrib)
{
case EGL_NO_RESET_NOTIFICATION:
@@ -103,12 +180,15 @@ GLenum GetResetStrategy(const egl::AttributeMap &attribs)
bool GetRobustAccess(const egl::AttributeMap &attribs)
{
- return (attribs.get(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_FALSE) == EGL_TRUE);
+ return (attribs.get(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_FALSE) == EGL_TRUE) ||
+ ((attribs.get(EGL_CONTEXT_FLAGS_KHR, 0) & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) !=
+ 0);
}
bool GetDebug(const egl::AttributeMap &attribs)
{
- return (attribs.get(EGL_CONTEXT_OPENGL_DEBUG, EGL_FALSE) == EGL_TRUE);
+ return (attribs.get(EGL_CONTEXT_OPENGL_DEBUG, EGL_FALSE) == EGL_TRUE) ||
+ ((attribs.get(EGL_CONTEXT_FLAGS_KHR, 0) & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR) != 0);
}
bool GetNoError(const egl::AttributeMap &attribs)
@@ -116,504 +196,657 @@ bool GetNoError(const egl::AttributeMap &attribs)
return (attribs.get(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, EGL_FALSE) == EGL_TRUE);
}
+bool GetWebGLContext(const egl::AttributeMap &attribs)
+{
+ return (attribs.get(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE, EGL_FALSE) == EGL_TRUE);
+}
+
+bool GetBindGeneratesResource(const egl::AttributeMap &attribs)
+{
+ return (attribs.get(EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM, EGL_TRUE) == EGL_TRUE);
+}
+
+bool GetClientArraysEnabled(const egl::AttributeMap &attribs)
+{
+ return (attribs.get(EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE, EGL_TRUE) == EGL_TRUE);
+}
+
+bool GetRobustResourceInit(const egl::AttributeMap &attribs)
+{
+ return (attribs.get(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, EGL_FALSE) == EGL_TRUE);
+}
+
+std::string GetObjectLabelFromPointer(GLsizei length, const GLchar *label)
+{
+ std::string labelName;
+ if (label != nullptr)
+ {
+ size_t labelLength = length < 0 ? strlen(label) : length;
+ labelName = std::string(label, labelLength);
+ }
+ return labelName;
+}
+
+void GetObjectLabelBase(const std::string &objectLabel,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label)
+{
+ size_t writeLength = objectLabel.length();
+ if (label != nullptr && bufSize > 0)
+ {
+ writeLength = std::min(static_cast<size_t>(bufSize) - 1, objectLabel.length());
+ std::copy(objectLabel.begin(), objectLabel.begin() + writeLength, label);
+ label[writeLength] = '\0';
+ }
+
+ if (length != nullptr)
+ {
+ *length = static_cast<GLsizei>(writeLength);
+ }
+}
+
+template <typename CapT, typename MaxT>
+void LimitCap(CapT *cap, MaxT maximum)
+{
+ *cap = std::min(*cap, static_cast<CapT>(maximum));
+}
+
} // anonymous namespace
namespace gl
{
-Context::Context(const egl::Config *config,
+Context::Context(rx::EGLImplFactory *implFactory,
+ const egl::Config *config,
const Context *shareContext,
- rx::Renderer *renderer,
- const egl::AttributeMap &attribs)
- : ValidationContext(GetClientVersion(attribs),
- mState,
+ TextureManager *shareTextures,
+ MemoryProgramCache *memoryProgramCache,
+ const egl::AttributeMap &attribs,
+ const egl::DisplayExtensions &displayExtensions)
+
+ : ValidationContext(shareContext,
+ shareTextures,
+ GetClientVersion(attribs),
+ &mGLState,
mCaps,
mTextureCaps,
mExtensions,
- nullptr,
mLimitations,
GetNoError(attribs)),
- mCompiler(nullptr),
- mRenderer(renderer),
- mClientVersion(GetClientVersion(attribs)),
+ mImplementation(implFactory->createContext(mState)),
+ mCompiler(),
mConfig(config),
mClientType(EGL_OPENGL_ES_API),
mHasBeenCurrent(false),
mContextLost(false),
mResetStatus(GL_NO_ERROR),
+ mContextLostForced(false),
mResetStrategy(GetResetStrategy(attribs)),
mRobustAccess(GetRobustAccess(attribs)),
- mCurrentSurface(nullptr),
- mResourceManager(nullptr)
+ mCurrentSurface(static_cast<egl::Surface *>(EGL_NO_SURFACE)),
+ mCurrentDisplay(static_cast<egl::Display *>(EGL_NO_DISPLAY)),
+ mSurfacelessFramebuffer(nullptr),
+ mWebGLContext(GetWebGLContext(attribs)),
+ mMemoryProgramCache(memoryProgramCache),
+ mScratchBuffer(1000u),
+ mZeroFilledBuffer(1000u)
{
- ASSERT(!mRobustAccess); // Unimplemented
+ mImplementation->setMemoryProgramCache(memoryProgramCache);
- initCaps(mClientVersion);
+ bool robustResourceInit = GetRobustResourceInit(attribs);
+ initCaps(displayExtensions, robustResourceInit);
+ initWorkarounds();
- mState.initialize(mCaps, mExtensions, mClientVersion, GetDebug(attribs));
+ mGLState.initialize(this, GetDebug(attribs), GetBindGeneratesResource(attribs),
+ GetClientArraysEnabled(attribs), robustResourceInit,
+ mMemoryProgramCache != nullptr);
mFenceNVHandleAllocator.setBaseHandle(0);
- if (shareContext != NULL)
- {
- mResourceManager = shareContext->mResourceManager;
- mResourceManager->addRef();
- }
- else
- {
- mResourceManager = new ResourceManager(mRenderer);
- }
-
- mData.resourceManager = mResourceManager;
-
// [OpenGL ES 2.0.24] section 3.7 page 83:
- // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
+ // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have two-dimensional
// and cube map texture state vectors respectively associated with them.
// In order that access to these initial textures not be lost, they are treated as texture
// objects all of whose names are 0.
- Texture *zeroTexture2D = new Texture(mRenderer->createTexture(GL_TEXTURE_2D), 0, GL_TEXTURE_2D);
- mZeroTextures[GL_TEXTURE_2D].set(zeroTexture2D);
+ Texture *zeroTexture2D = new Texture(mImplementation.get(), 0, GL_TEXTURE_2D);
+ mZeroTextures[GL_TEXTURE_2D].set(this, zeroTexture2D);
- Texture *zeroTextureCube = new Texture(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), 0, GL_TEXTURE_CUBE_MAP);
- mZeroTextures[GL_TEXTURE_CUBE_MAP].set(zeroTextureCube);
+ Texture *zeroTextureCube = new Texture(mImplementation.get(), 0, GL_TEXTURE_CUBE_MAP);
+ mZeroTextures[GL_TEXTURE_CUBE_MAP].set(this, zeroTextureCube);
- if (mClientVersion >= 3)
+ if (getClientVersion() >= Version(3, 0))
{
// TODO: These could also be enabled via extension
- Texture *zeroTexture3D = new Texture(mRenderer->createTexture(GL_TEXTURE_3D), 0, GL_TEXTURE_3D);
- mZeroTextures[GL_TEXTURE_3D].set(zeroTexture3D);
+ Texture *zeroTexture3D = new Texture(mImplementation.get(), 0, GL_TEXTURE_3D);
+ mZeroTextures[GL_TEXTURE_3D].set(this, zeroTexture3D);
- Texture *zeroTexture2DArray = new Texture(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), 0, GL_TEXTURE_2D_ARRAY);
- mZeroTextures[GL_TEXTURE_2D_ARRAY].set(zeroTexture2DArray);
+ Texture *zeroTexture2DArray = new Texture(mImplementation.get(), 0, GL_TEXTURE_2D_ARRAY);
+ mZeroTextures[GL_TEXTURE_2D_ARRAY].set(this, zeroTexture2DArray);
}
+ if (getClientVersion() >= Version(3, 1))
+ {
+ Texture *zeroTexture2DMultisample =
+ new Texture(mImplementation.get(), 0, GL_TEXTURE_2D_MULTISAMPLE);
+ mZeroTextures[GL_TEXTURE_2D_MULTISAMPLE].set(this, zeroTexture2DMultisample);
- mState.initializeZeroTextures(mZeroTextures);
+ for (unsigned int i = 0; i < mCaps.maxAtomicCounterBufferBindings; i++)
+ {
+ bindBufferRange(BufferBinding::AtomicCounter, 0, i, 0, 0);
+ }
- bindVertexArray(0);
- bindArrayBuffer(0);
- bindElementArrayBuffer(0);
+ for (unsigned int i = 0; i < mCaps.maxShaderStorageBufferBindings; i++)
+ {
+ bindBufferRange(BufferBinding::ShaderStorage, i, 0, 0, 0);
+ }
+ }
- bindRenderbuffer(0);
+ const Extensions &nativeExtensions = mImplementation->getNativeExtensions();
+ if (nativeExtensions.textureRectangle)
+ {
+ Texture *zeroTextureRectangle =
+ new Texture(mImplementation.get(), 0, GL_TEXTURE_RECTANGLE_ANGLE);
+ mZeroTextures[GL_TEXTURE_RECTANGLE_ANGLE].set(this, zeroTextureRectangle);
+ }
- bindGenericUniformBuffer(0);
- for (unsigned int i = 0; i < mCaps.maxCombinedUniformBlocks; i++)
+ if (nativeExtensions.eglImageExternal || nativeExtensions.eglStreamConsumerExternal)
{
- bindIndexedUniformBuffer(0, i, 0, -1);
+ Texture *zeroTextureExternal =
+ new Texture(mImplementation.get(), 0, GL_TEXTURE_EXTERNAL_OES);
+ mZeroTextures[GL_TEXTURE_EXTERNAL_OES].set(this, zeroTextureExternal);
}
- bindCopyReadBuffer(0);
- bindCopyWriteBuffer(0);
- bindPixelPackBuffer(0);
- bindPixelUnpackBuffer(0);
+ mGLState.initializeZeroTextures(this, mZeroTextures);
- if (mClientVersion >= 3)
+ bindVertexArray(0);
+
+ if (getClientVersion() >= Version(3, 0))
{
// [OpenGL ES 3.0.2] section 2.14.1 pg 85:
// In the initial state, a default transform feedback object is bound and treated as
// a transform feedback object with a name of zero. That object is bound any time
// BindTransformFeedback is called with id of zero
- bindTransformFeedback(0);
+ bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
}
- mCompiler = new Compiler(mRenderer, getData());
-}
+ for (auto type : angle::AllEnums<BufferBinding>())
+ {
+ bindBuffer(type, 0);
+ }
-Context::~Context()
-{
- mState.reset();
+ bindRenderbuffer(GL_RENDERBUFFER, 0);
- for (auto framebuffer : mFramebufferMap)
+ for (unsigned int i = 0; i < mCaps.maxUniformBufferBindings; i++)
{
- // Default framebuffer are owned by their respective Surface
- if (framebuffer.second != nullptr && framebuffer.second->id() != 0)
- {
- SafeDelete(framebuffer.second);
- }
+ bindBufferRange(BufferBinding::Uniform, i, 0, 0, -1);
}
+ // Initialize dirty bit masks
+ mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_STATE);
+ mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_BUFFER_BINDING);
+ // No dirty objects.
+
+ // Readpixels uses the pack state and read FBO
+ mReadPixelsDirtyBits.set(State::DIRTY_BIT_PACK_STATE);
+ mReadPixelsDirtyBits.set(State::DIRTY_BIT_PACK_BUFFER_BINDING);
+ mReadPixelsDirtyObjects.set(State::DIRTY_OBJECT_READ_FRAMEBUFFER);
+
+ mClearDirtyBits.set(State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED);
+ mClearDirtyBits.set(State::DIRTY_BIT_SCISSOR_TEST_ENABLED);
+ mClearDirtyBits.set(State::DIRTY_BIT_SCISSOR);
+ mClearDirtyBits.set(State::DIRTY_BIT_VIEWPORT);
+ mClearDirtyBits.set(State::DIRTY_BIT_CLEAR_COLOR);
+ mClearDirtyBits.set(State::DIRTY_BIT_CLEAR_DEPTH);
+ mClearDirtyBits.set(State::DIRTY_BIT_CLEAR_STENCIL);
+ mClearDirtyBits.set(State::DIRTY_BIT_COLOR_MASK);
+ mClearDirtyBits.set(State::DIRTY_BIT_DEPTH_MASK);
+ mClearDirtyBits.set(State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
+ mClearDirtyBits.set(State::DIRTY_BIT_STENCIL_WRITEMASK_BACK);
+ mClearDirtyObjects.set(State::DIRTY_OBJECT_DRAW_FRAMEBUFFER);
+
+ mBlitDirtyBits.set(State::DIRTY_BIT_SCISSOR_TEST_ENABLED);
+ mBlitDirtyBits.set(State::DIRTY_BIT_SCISSOR);
+ mBlitDirtyBits.set(State::DIRTY_BIT_FRAMEBUFFER_SRGB);
+ mBlitDirtyObjects.set(State::DIRTY_OBJECT_READ_FRAMEBUFFER);
+ mBlitDirtyObjects.set(State::DIRTY_OBJECT_DRAW_FRAMEBUFFER);
+
+ handleError(mImplementation->initialize());
+}
+
+egl::Error Context::onDestroy(const egl::Display *display)
+{
for (auto fence : mFenceNVMap)
{
SafeDelete(fence.second);
}
+ mFenceNVMap.clear();
for (auto query : mQueryMap)
{
if (query.second != nullptr)
{
- query.second->release();
+ query.second->release(this);
}
}
+ mQueryMap.clear();
for (auto vertexArray : mVertexArrayMap)
{
- SafeDelete(vertexArray.second);
+ if (vertexArray.second)
+ {
+ vertexArray.second->onDestroy(this);
+ }
}
+ mVertexArrayMap.clear();
for (auto transformFeedback : mTransformFeedbackMap)
{
if (transformFeedback.second != nullptr)
{
- transformFeedback.second->release();
+ transformFeedback.second->release(this);
}
}
+ mTransformFeedbackMap.clear();
for (auto &zeroTexture : mZeroTextures)
{
- zeroTexture.second.set(NULL);
+ ANGLE_TRY(zeroTexture.second->onDestroy(this));
+ zeroTexture.second.set(this, nullptr);
}
mZeroTextures.clear();
- if (mCurrentSurface != nullptr)
- {
- releaseSurface();
- }
+ SafeDelete(mSurfacelessFramebuffer);
- if (mResourceManager)
- {
- mResourceManager->release();
- }
+ ANGLE_TRY(releaseSurface(display));
+ releaseShaderCompiler();
+
+ mGLState.reset(this);
- SafeDelete(mCompiler);
+ mState.mBuffers->release(this);
+ mState.mShaderPrograms->release(this);
+ mState.mTextures->release(this);
+ mState.mRenderbuffers->release(this);
+ mState.mSamplers->release(this);
+ mState.mSyncs->release(this);
+ mState.mPaths->release(this);
+ mState.mFramebuffers->release(this);
+ mState.mPipelines->release(this);
+
+ mImplementation->onDestroy(this);
+
+ return egl::NoError();
+}
+
+Context::~Context()
+{
}
-void Context::makeCurrent(egl::Surface *surface)
+egl::Error Context::makeCurrent(egl::Display *display, egl::Surface *surface)
{
- ASSERT(surface != nullptr);
+ mCurrentDisplay = display;
if (!mHasBeenCurrent)
{
initRendererString();
+ initVersionStrings();
initExtensionStrings();
- mState.setViewportParams(0, 0, surface->getWidth(), surface->getHeight());
- mState.setScissorParams(0, 0, surface->getWidth(), surface->getHeight());
+ int width = 0;
+ int height = 0;
+ if (surface != nullptr)
+ {
+ width = surface->getWidth();
+ height = surface->getHeight();
+ }
+
+ mGLState.setViewportParams(0, 0, width, height);
+ mGLState.setScissorParams(0, 0, width, height);
mHasBeenCurrent = true;
}
// TODO(jmadill): Rework this when we support ContextImpl
- mState.setAllDirtyBits();
+ mGLState.setAllDirtyBits();
+ mGLState.setAllDirtyObjects();
- if (mCurrentSurface)
+ ANGLE_TRY(releaseSurface(display));
+
+ Framebuffer *newDefault = nullptr;
+ if (surface != nullptr)
+ {
+ ANGLE_TRY(surface->setIsCurrent(this, true));
+ mCurrentSurface = surface;
+ newDefault = surface->getDefaultFramebuffer();
+ }
+ else
{
- releaseSurface();
+ if (mSurfacelessFramebuffer == nullptr)
+ {
+ mSurfacelessFramebuffer = new Framebuffer(mImplementation.get());
+ }
+
+ newDefault = mSurfacelessFramebuffer;
}
- surface->setIsCurrent(true);
- mCurrentSurface = surface;
// Update default framebuffer, the binding of the previous default
// framebuffer (or lack of) will have a nullptr.
{
- Framebuffer *newDefault = surface->getDefaultFramebuffer();
- if (mState.getReadFramebuffer() == nullptr)
+ if (mGLState.getReadFramebuffer() == nullptr)
{
- mState.setReadFramebufferBinding(newDefault);
+ mGLState.setReadFramebufferBinding(newDefault);
}
- if (mState.getDrawFramebuffer() == nullptr)
+ if (mGLState.getDrawFramebuffer() == nullptr)
{
- mState.setDrawFramebufferBinding(newDefault);
+ mGLState.setDrawFramebufferBinding(newDefault);
}
- mFramebufferMap[0] = newDefault;
+ mState.mFramebuffers->setDefaultFramebuffer(newDefault);
}
// Notify the renderer of a context switch
- mRenderer->onMakeCurrent(getData());
+ mImplementation->onMakeCurrent(this);
+ return egl::NoError();
}
-void Context::releaseSurface()
+egl::Error Context::releaseSurface(const egl::Display *display)
{
- ASSERT(mCurrentSurface != nullptr);
-
// Remove the default framebuffer
+ Framebuffer *currentDefault = nullptr;
+ if (mCurrentSurface != nullptr)
{
- Framebuffer *currentDefault = mCurrentSurface->getDefaultFramebuffer();
- if (mState.getReadFramebuffer() == currentDefault)
- {
- mState.setReadFramebufferBinding(nullptr);
- }
- if (mState.getDrawFramebuffer() == currentDefault)
- {
- mState.setDrawFramebufferBinding(nullptr);
- }
- mFramebufferMap.erase(0);
+ currentDefault = mCurrentSurface->getDefaultFramebuffer();
+ }
+ else if (mSurfacelessFramebuffer != nullptr)
+ {
+ currentDefault = mSurfacelessFramebuffer;
}
- mCurrentSurface->setIsCurrent(false);
- mCurrentSurface = nullptr;
-}
+ if (mGLState.getReadFramebuffer() == currentDefault)
+ {
+ mGLState.setReadFramebufferBinding(nullptr);
+ }
+ if (mGLState.getDrawFramebuffer() == currentDefault)
+ {
+ mGLState.setDrawFramebufferBinding(nullptr);
+ }
+ mState.mFramebuffers->setDefaultFramebuffer(nullptr);
-// NOTE: this function should not assume that this context is current!
-void Context::markContextLost()
-{
- if (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT)
- mResetStatus = GL_UNKNOWN_CONTEXT_RESET_EXT;
- mContextLost = true;
-}
+ if (mCurrentSurface)
+ {
+ ANGLE_TRY(mCurrentSurface->setIsCurrent(this, false));
+ mCurrentSurface = nullptr;
+ }
-bool Context::isContextLost()
-{
- return mContextLost;
+ return egl::NoError();
}
GLuint Context::createBuffer()
{
- return mResourceManager->createBuffer();
+ return mState.mBuffers->createBuffer();
}
GLuint Context::createProgram()
{
- return mResourceManager->createProgram();
+ return mState.mShaderPrograms->createProgram(mImplementation.get());
}
GLuint Context::createShader(GLenum type)
{
- return mResourceManager->createShader(mRenderer->getRendererLimitations(), type);
+ return mState.mShaderPrograms->createShader(mImplementation.get(), mLimitations, type);
}
GLuint Context::createTexture()
{
- return mResourceManager->createTexture();
+ return mState.mTextures->createTexture();
}
GLuint Context::createRenderbuffer()
{
- return mResourceManager->createRenderbuffer();
-}
-
-GLsync Context::createFenceSync()
-{
- GLuint handle = mResourceManager->createFenceSync();
-
- return reinterpret_cast<GLsync>(static_cast<uintptr_t>(handle));
-}
-
-GLuint Context::createVertexArray()
-{
- GLuint vertexArray = mVertexArrayHandleAllocator.allocate();
- mVertexArrayMap[vertexArray] = nullptr;
- return vertexArray;
-}
-
-GLuint Context::createSampler()
-{
- return mResourceManager->createSampler();
+ return mState.mRenderbuffers->createRenderbuffer();
}
-GLuint Context::createTransformFeedback()
+GLuint Context::createPaths(GLsizei range)
{
- GLuint transformFeedback = mTransformFeedbackAllocator.allocate();
- mTransformFeedbackMap[transformFeedback] = nullptr;
- return transformFeedback;
+ auto resultOrError = mState.mPaths->createPaths(mImplementation.get(), range);
+ if (resultOrError.isError())
+ {
+ handleError(resultOrError.getError());
+ return 0;
+ }
+ return resultOrError.getResult();
}
// Returns an unused framebuffer name
GLuint Context::createFramebuffer()
{
- GLuint handle = mFramebufferHandleAllocator.allocate();
-
- mFramebufferMap[handle] = NULL;
-
- return handle;
+ return mState.mFramebuffers->createFramebuffer();
}
GLuint Context::createFenceNV()
{
GLuint handle = mFenceNVHandleAllocator.allocate();
-
- mFenceNVMap[handle] = new FenceNV(mRenderer->createFenceNV());
-
+ mFenceNVMap.assign(handle, new FenceNV(mImplementation->createFenceNV()));
return handle;
}
-// Returns an unused query name
-GLuint Context::createQuery()
+GLuint Context::createProgramPipeline()
{
- GLuint handle = mQueryHandleAllocator.allocate();
-
- mQueryMap[handle] = NULL;
+ return mState.mPipelines->createProgramPipeline();
+}
- return handle;
+GLuint Context::createShaderProgramv(GLenum type, GLsizei count, const GLchar *const *strings)
+{
+ UNIMPLEMENTED();
+ return 0u;
}
void Context::deleteBuffer(GLuint buffer)
{
- if (mResourceManager->getBuffer(buffer))
+ if (mState.mBuffers->getBuffer(buffer))
{
detachBuffer(buffer);
}
- mResourceManager->deleteBuffer(buffer);
+ mState.mBuffers->deleteObject(this, buffer);
}
void Context::deleteShader(GLuint shader)
{
- mResourceManager->deleteShader(shader);
+ mState.mShaderPrograms->deleteShader(this, shader);
}
void Context::deleteProgram(GLuint program)
{
- mResourceManager->deleteProgram(program);
+ mState.mShaderPrograms->deleteProgram(this, program);
}
void Context::deleteTexture(GLuint texture)
{
- if (mResourceManager->getTexture(texture))
+ if (mState.mTextures->getTexture(texture))
{
detachTexture(texture);
}
- mResourceManager->deleteTexture(texture);
+ mState.mTextures->deleteObject(this, texture);
}
void Context::deleteRenderbuffer(GLuint renderbuffer)
{
- if (mResourceManager->getRenderbuffer(renderbuffer))
+ if (mState.mRenderbuffers->getRenderbuffer(renderbuffer))
{
detachRenderbuffer(renderbuffer);
}
- mResourceManager->deleteRenderbuffer(renderbuffer);
+ mState.mRenderbuffers->deleteObject(this, renderbuffer);
}
-void Context::deleteFenceSync(GLsync fenceSync)
+void Context::deleteSync(GLsync sync)
{
// The spec specifies the underlying Fence object is not deleted until all current
// wait commands finish. However, since the name becomes invalid, we cannot query the fence,
// and since our API is currently designed for being called from a single thread, we can delete
// the fence immediately.
- mResourceManager->deleteFenceSync(static_cast<GLuint>(reinterpret_cast<uintptr_t>(fenceSync)));
+ mState.mSyncs->deleteObject(this, static_cast<GLuint>(reinterpret_cast<uintptr_t>(sync)));
}
-void Context::deleteVertexArray(GLuint vertexArray)
+void Context::deleteProgramPipeline(GLuint pipeline)
{
- auto iter = mVertexArrayMap.find(vertexArray);
- if (iter != mVertexArrayMap.end())
+ if (mState.mPipelines->getProgramPipeline(pipeline))
{
- VertexArray *vertexArrayObject = iter->second;
- if (vertexArrayObject != nullptr)
- {
- detachVertexArray(vertexArray);
- delete vertexArrayObject;
- }
-
- mVertexArrayMap.erase(iter);
- mVertexArrayHandleAllocator.release(vertexArray);
+ detachProgramPipeline(pipeline);
}
+
+ mState.mPipelines->deleteObject(this, pipeline);
}
-void Context::deleteSampler(GLuint sampler)
+void Context::deletePaths(GLuint first, GLsizei range)
{
- if (mResourceManager->getSampler(sampler))
- {
- detachSampler(sampler);
- }
-
- mResourceManager->deleteSampler(sampler);
+ mState.mPaths->deletePaths(first, range);
}
-void Context::deleteTransformFeedback(GLuint transformFeedback)
+bool Context::hasPathData(GLuint path) const
{
- auto iter = mTransformFeedbackMap.find(transformFeedback);
- if (iter != mTransformFeedbackMap.end())
- {
- TransformFeedback *transformFeedbackObject = iter->second;
- if (transformFeedbackObject != nullptr)
- {
- detachTransformFeedback(transformFeedback);
- transformFeedbackObject->release();
- }
+ const auto *pathObj = mState.mPaths->getPath(path);
+ if (pathObj == nullptr)
+ return false;
- mTransformFeedbackMap.erase(iter);
- mTransformFeedbackAllocator.release(transformFeedback);
- }
+ return pathObj->hasPathData();
}
-void Context::deleteFramebuffer(GLuint framebuffer)
+bool Context::hasPath(GLuint path) const
{
- FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
+ return mState.mPaths->hasPath(path);
+}
- if (framebufferObject != mFramebufferMap.end())
- {
- detachFramebuffer(framebuffer);
+void Context::setPathCommands(GLuint path,
+ GLsizei numCommands,
+ const GLubyte *commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const void *coords)
+{
+ auto *pathObject = mState.mPaths->getPath(path);
- mFramebufferHandleAllocator.release(framebufferObject->first);
- delete framebufferObject->second;
- mFramebufferMap.erase(framebufferObject);
- }
+ handleError(pathObject->setCommands(numCommands, commands, numCoords, coordType, coords));
}
-void Context::deleteFenceNV(GLuint fence)
+void Context::setPathParameterf(GLuint path, GLenum pname, GLfloat value)
{
- FenceNVMap::iterator fenceObject = mFenceNVMap.find(fence);
+ auto *pathObj = mState.mPaths->getPath(path);
- if (fenceObject != mFenceNVMap.end())
+ switch (pname)
{
- mFenceNVHandleAllocator.release(fenceObject->first);
- delete fenceObject->second;
- mFenceNVMap.erase(fenceObject);
+ case GL_PATH_STROKE_WIDTH_CHROMIUM:
+ pathObj->setStrokeWidth(value);
+ break;
+ case GL_PATH_END_CAPS_CHROMIUM:
+ pathObj->setEndCaps(static_cast<GLenum>(value));
+ break;
+ case GL_PATH_JOIN_STYLE_CHROMIUM:
+ pathObj->setJoinStyle(static_cast<GLenum>(value));
+ break;
+ case GL_PATH_MITER_LIMIT_CHROMIUM:
+ pathObj->setMiterLimit(value);
+ break;
+ case GL_PATH_STROKE_BOUND_CHROMIUM:
+ pathObj->setStrokeBound(value);
+ break;
+ default:
+ UNREACHABLE();
+ break;
}
}
-void Context::deleteQuery(GLuint query)
+void Context::getPathParameterfv(GLuint path, GLenum pname, GLfloat *value) const
{
- QueryMap::iterator queryObject = mQueryMap.find(query);
- if (queryObject != mQueryMap.end())
+ const auto *pathObj = mState.mPaths->getPath(path);
+
+ switch (pname)
{
- mQueryHandleAllocator.release(queryObject->first);
- if (queryObject->second)
- {
- queryObject->second->release();
- }
- mQueryMap.erase(queryObject);
+ case GL_PATH_STROKE_WIDTH_CHROMIUM:
+ *value = pathObj->getStrokeWidth();
+ break;
+ case GL_PATH_END_CAPS_CHROMIUM:
+ *value = static_cast<GLfloat>(pathObj->getEndCaps());
+ break;
+ case GL_PATH_JOIN_STYLE_CHROMIUM:
+ *value = static_cast<GLfloat>(pathObj->getJoinStyle());
+ break;
+ case GL_PATH_MITER_LIMIT_CHROMIUM:
+ *value = pathObj->getMiterLimit();
+ break;
+ case GL_PATH_STROKE_BOUND_CHROMIUM:
+ *value = pathObj->getStrokeBound();
+ break;
+ default:
+ UNREACHABLE();
+ break;
}
}
-Buffer *Context::getBuffer(GLuint handle) const
+void Context::setPathStencilFunc(GLenum func, GLint ref, GLuint mask)
+{
+ mGLState.setPathStencilFunc(func, ref, mask);
+}
+
+void Context::deleteFramebuffer(GLuint framebuffer)
{
- return mResourceManager->getBuffer(handle);
+ if (mState.mFramebuffers->getFramebuffer(framebuffer))
+ {
+ detachFramebuffer(framebuffer);
+ }
+
+ mState.mFramebuffers->deleteObject(this, framebuffer);
}
-Shader *Context::getShader(GLuint handle) const
+void Context::deleteFenceNV(GLuint fence)
{
- return mResourceManager->getShader(handle);
+ FenceNV *fenceObject = nullptr;
+ if (mFenceNVMap.erase(fence, &fenceObject))
+ {
+ mFenceNVHandleAllocator.release(fence);
+ delete fenceObject;
+ }
}
-Program *Context::getProgram(GLuint handle) const
+Buffer *Context::getBuffer(GLuint handle) const
{
- return mResourceManager->getProgram(handle);
+ return mState.mBuffers->getBuffer(handle);
}
Texture *Context::getTexture(GLuint handle) const
{
- return mResourceManager->getTexture(handle);
+ return mState.mTextures->getTexture(handle);
}
Renderbuffer *Context::getRenderbuffer(GLuint handle) const
{
- return mResourceManager->getRenderbuffer(handle);
+ return mState.mRenderbuffers->getRenderbuffer(handle);
}
-FenceSync *Context::getFenceSync(GLsync handle) const
+Sync *Context::getSync(GLsync handle) const
{
- return mResourceManager->getFenceSync(static_cast<GLuint>(reinterpret_cast<uintptr_t>(handle)));
+ return mState.mSyncs->getSync(static_cast<GLuint>(reinterpret_cast<uintptr_t>(handle)));
}
VertexArray *Context::getVertexArray(GLuint handle) const
{
- auto vertexArray = mVertexArrayMap.find(handle);
- return (vertexArray != mVertexArrayMap.end()) ? vertexArray->second : nullptr;
+ return mVertexArrayMap.query(handle);
}
Sampler *Context::getSampler(GLuint handle) const
{
- return mResourceManager->getSampler(handle);
+ return mState.mSamplers->getSampler(handle);
}
TransformFeedback *Context::getTransformFeedback(GLuint handle) const
{
- auto iter = mTransformFeedbackMap.find(handle);
- return (iter != mTransformFeedbackMap.end()) ? iter->second : nullptr;
+ return mTransformFeedbackMap.query(handle);
+}
+
+ProgramPipeline *Context::getProgramPipeline(GLuint handle) const
+{
+ return mState.mPipelines->getProgramPipeline(handle);
}
LabeledObject *Context::getLabeledObject(GLenum identifier, GLuint name) const
@@ -648,31 +881,64 @@ LabeledObject *Context::getLabeledObject(GLenum identifier, GLuint name) const
LabeledObject *Context::getLabeledObjectFromPtr(const void *ptr) const
{
- return getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr)));
+ return getSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr)));
}
-bool Context::isSampler(GLuint samplerName) const
+void Context::objectLabel(GLenum identifier, GLuint name, GLsizei length, const GLchar *label)
+{
+ LabeledObject *object = getLabeledObject(identifier, name);
+ ASSERT(object != nullptr);
+
+ std::string labelName = GetObjectLabelFromPointer(length, label);
+ object->setLabel(labelName);
+
+ // TODO(jmadill): Determine if the object is dirty based on 'name'. Conservatively assume the
+ // specified object is active until we do this.
+ mGLState.setObjectDirty(identifier);
+}
+
+void Context::objectPtrLabel(const void *ptr, GLsizei length, const GLchar *label)
{
- return mResourceManager->isSampler(samplerName);
+ LabeledObject *object = getLabeledObjectFromPtr(ptr);
+ ASSERT(object != nullptr);
+
+ std::string labelName = GetObjectLabelFromPointer(length, label);
+ object->setLabel(labelName);
}
-void Context::bindArrayBuffer(unsigned int buffer)
+void Context::getObjectLabel(GLenum identifier,
+ GLuint name,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label) const
{
- mResourceManager->checkBufferAllocation(buffer);
+ LabeledObject *object = getLabeledObject(identifier, name);
+ ASSERT(object != nullptr);
- mState.setArrayBufferBinding(getBuffer(buffer));
+ const std::string &objectLabel = object->getLabel();
+ GetObjectLabelBase(objectLabel, bufSize, length, label);
}
-void Context::bindElementArrayBuffer(unsigned int buffer)
+void Context::getObjectPtrLabel(const void *ptr,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label) const
{
- mResourceManager->checkBufferAllocation(buffer);
+ LabeledObject *object = getLabeledObjectFromPtr(ptr);
+ ASSERT(object != nullptr);
- mState.getVertexArray()->setElementArrayBuffer(getBuffer(buffer));
+ const std::string &objectLabel = object->getLabel();
+ GetObjectLabelBase(objectLabel, bufSize, length, label);
+}
+
+bool Context::isSampler(GLuint samplerName) const
+{
+ return mState.mSamplers->isSampler(samplerName);
}
void Context::bindTexture(GLenum target, GLuint handle)
{
- Texture *texture = NULL;
+ Texture *texture = nullptr;
if (handle == 0)
{
@@ -680,156 +946,118 @@ void Context::bindTexture(GLenum target, GLuint handle)
}
else
{
- mResourceManager->checkTextureAllocation(handle, target);
- texture = getTexture(handle);
+ texture = mState.mTextures->checkTextureAllocation(mImplementation.get(), handle, target);
}
ASSERT(texture);
-
- mState.setSamplerTexture(target, texture);
+ mGLState.setSamplerTexture(this, target, texture);
}
void Context::bindReadFramebuffer(GLuint framebufferHandle)
{
- Framebuffer *framebuffer = checkFramebufferAllocation(framebufferHandle);
- mState.setReadFramebufferBinding(framebuffer);
+ Framebuffer *framebuffer = mState.mFramebuffers->checkFramebufferAllocation(
+ mImplementation.get(), mCaps, framebufferHandle);
+ mGLState.setReadFramebufferBinding(framebuffer);
}
void Context::bindDrawFramebuffer(GLuint framebufferHandle)
{
- Framebuffer *framebuffer = checkFramebufferAllocation(framebufferHandle);
- mState.setDrawFramebufferBinding(framebuffer);
+ Framebuffer *framebuffer = mState.mFramebuffers->checkFramebufferAllocation(
+ mImplementation.get(), mCaps, framebufferHandle);
+ mGLState.setDrawFramebufferBinding(framebuffer);
}
-void Context::bindRenderbuffer(GLuint renderbuffer)
+void Context::bindVertexArray(GLuint vertexArrayHandle)
{
- mResourceManager->checkRenderbufferAllocation(renderbuffer);
-
- mState.setRenderbufferBinding(getRenderbuffer(renderbuffer));
+ VertexArray *vertexArray = checkVertexArrayAllocation(vertexArrayHandle);
+ mGLState.setVertexArrayBinding(vertexArray);
}
-void Context::bindVertexArray(GLuint vertexArray)
+void Context::bindVertexBuffer(GLuint bindingIndex,
+ GLuint bufferHandle,
+ GLintptr offset,
+ GLsizei stride)
{
- checkVertexArrayAllocation(vertexArray);
-
- mState.setVertexArrayBinding(getVertexArray(vertexArray));
+ Buffer *buffer = mState.mBuffers->checkBufferAllocation(mImplementation.get(), bufferHandle);
+ mGLState.bindVertexBuffer(this, bindingIndex, buffer, offset, stride);
}
-void Context::bindSampler(GLuint textureUnit, GLuint sampler)
+void Context::bindSampler(GLuint textureUnit, GLuint samplerHandle)
{
ASSERT(textureUnit < mCaps.maxCombinedTextureImageUnits);
- mResourceManager->checkSamplerAllocation(sampler);
-
- mState.setSamplerBinding(textureUnit, getSampler(sampler));
-}
-
-void Context::bindGenericUniformBuffer(GLuint buffer)
-{
- mResourceManager->checkBufferAllocation(buffer);
-
- mState.setGenericUniformBufferBinding(getBuffer(buffer));
-}
-
-void Context::bindIndexedUniformBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size)
-{
- mResourceManager->checkBufferAllocation(buffer);
-
- mState.setIndexedUniformBufferBinding(index, getBuffer(buffer), offset, size);
+ Sampler *sampler =
+ mState.mSamplers->checkSamplerAllocation(mImplementation.get(), samplerHandle);
+ mGLState.setSamplerBinding(this, textureUnit, sampler);
}
-void Context::bindGenericTransformFeedbackBuffer(GLuint buffer)
+void Context::bindImageTexture(GLuint unit,
+ GLuint texture,
+ GLint level,
+ GLboolean layered,
+ GLint layer,
+ GLenum access,
+ GLenum format)
{
- mResourceManager->checkBufferAllocation(buffer);
-
- mState.getCurrentTransformFeedback()->bindGenericBuffer(getBuffer(buffer));
-}
-
-void Context::bindIndexedTransformFeedbackBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size)
-{
- mResourceManager->checkBufferAllocation(buffer);
-
- mState.getCurrentTransformFeedback()->bindIndexedBuffer(index, getBuffer(buffer), offset, size);
-}
-
-void Context::bindCopyReadBuffer(GLuint buffer)
-{
- mResourceManager->checkBufferAllocation(buffer);
-
- mState.setCopyReadBufferBinding(getBuffer(buffer));
-}
-
-void Context::bindCopyWriteBuffer(GLuint buffer)
-{
- mResourceManager->checkBufferAllocation(buffer);
-
- mState.setCopyWriteBufferBinding(getBuffer(buffer));
+ Texture *tex = mState.mTextures->getTexture(texture);
+ mGLState.setImageUnit(this, unit, tex, level, layered, layer, access, format);
}
-void Context::bindPixelPackBuffer(GLuint buffer)
+void Context::useProgram(GLuint program)
{
- mResourceManager->checkBufferAllocation(buffer);
-
- mState.setPixelPackBufferBinding(getBuffer(buffer));
+ mGLState.setProgram(this, getProgram(program));
}
-void Context::bindPixelUnpackBuffer(GLuint buffer)
+void Context::useProgramStages(GLuint pipeline, GLbitfield stages, GLuint program)
{
- mResourceManager->checkBufferAllocation(buffer);
-
- mState.setPixelUnpackBufferBinding(getBuffer(buffer));
+ UNIMPLEMENTED();
}
-void Context::useProgram(GLuint program)
+void Context::bindTransformFeedback(GLenum target, GLuint transformFeedbackHandle)
{
- mState.setProgram(getProgram(program));
+ ASSERT(target == GL_TRANSFORM_FEEDBACK);
+ TransformFeedback *transformFeedback =
+ checkTransformFeedbackAllocation(transformFeedbackHandle);
+ mGLState.setTransformFeedbackBinding(this, transformFeedback);
}
-void Context::bindTransformFeedback(GLuint transformFeedback)
+void Context::bindProgramPipeline(GLuint pipelineHandle)
{
- checkTransformFeedbackAllocation(transformFeedback);
-
- mState.setTransformFeedbackBinding(getTransformFeedback(transformFeedback));
+ ProgramPipeline *pipeline =
+ mState.mPipelines->checkProgramPipelineAllocation(mImplementation.get(), pipelineHandle);
+ mGLState.setProgramPipelineBinding(this, pipeline);
}
-Error Context::beginQuery(GLenum target, GLuint query)
+void Context::beginQuery(GLenum target, GLuint query)
{
Query *queryObject = getQuery(query, true, target);
ASSERT(queryObject);
// begin query
- Error error = queryObject->begin();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_CONTEXT_TRY(queryObject->begin());
// set query as active for specified target only if begin succeeded
- mState.setActiveQuery(target, queryObject);
-
- return Error(GL_NO_ERROR);
+ mGLState.setActiveQuery(this, target, queryObject);
}
-Error Context::endQuery(GLenum target)
+void Context::endQuery(GLenum target)
{
- Query *queryObject = mState.getActiveQuery(target);
+ Query *queryObject = mGLState.getActiveQuery(target);
ASSERT(queryObject);
- gl::Error error = queryObject->end();
+ handleError(queryObject->end());
// Always unbind the query, even if there was an error. This may delete the query object.
- mState.setActiveQuery(target, NULL);
-
- return error;
+ mGLState.setActiveQuery(this, target, nullptr);
}
-Error Context::queryCounter(GLuint id, GLenum target)
+void Context::queryCounter(GLuint id, GLenum target)
{
ASSERT(target == GL_TIMESTAMP_EXT);
Query *queryObject = getQuery(id, true, target);
ASSERT(queryObject);
- return queryObject->queryCounter();
+ handleError(queryObject->queryCounter());
}
void Context::getQueryiv(GLenum target, GLenum pname, GLint *params)
@@ -837,7 +1065,7 @@ void Context::getQueryiv(GLenum target, GLenum pname, GLint *params)
switch (pname)
{
case GL_CURRENT_QUERY_EXT:
- params[0] = getState().getActiveQueryId(target);
+ params[0] = mGLState.getActiveQueryId(target);
break;
case GL_QUERY_COUNTER_BITS_EXT:
switch (target)
@@ -860,763 +1088,992 @@ void Context::getQueryiv(GLenum target, GLenum pname, GLint *params)
}
}
-Error Context::getQueryObjectiv(GLuint id, GLenum pname, GLint *params)
+void Context::getQueryObjectiv(GLuint id, GLenum pname, GLint *params)
{
- return GetQueryObjectParameter(this, id, pname, params);
+ handleError(GetQueryObjectParameter(getQuery(id), pname, params));
}
-Error Context::getQueryObjectuiv(GLuint id, GLenum pname, GLuint *params)
+void Context::getQueryObjectuiv(GLuint id, GLenum pname, GLuint *params)
{
- return GetQueryObjectParameter(this, id, pname, params);
+ handleError(GetQueryObjectParameter(getQuery(id), pname, params));
}
-Error Context::getQueryObjecti64v(GLuint id, GLenum pname, GLint64 *params)
+void Context::getQueryObjecti64v(GLuint id, GLenum pname, GLint64 *params)
{
- return GetQueryObjectParameter(this, id, pname, params);
+ handleError(GetQueryObjectParameter(getQuery(id), pname, params));
}
-Error Context::getQueryObjectui64v(GLuint id, GLenum pname, GLuint64 *params)
+void Context::getQueryObjectui64v(GLuint id, GLenum pname, GLuint64 *params)
{
- return GetQueryObjectParameter(this, id, pname, params);
+ handleError(GetQueryObjectParameter(getQuery(id), pname, params));
}
-Framebuffer *Context::getFramebuffer(unsigned int handle) const
+Framebuffer *Context::getFramebuffer(GLuint handle) const
{
- auto framebufferIt = mFramebufferMap.find(handle);
- return ((framebufferIt == mFramebufferMap.end()) ? nullptr : framebufferIt->second);
+ return mState.mFramebuffers->getFramebuffer(handle);
}
-FenceNV *Context::getFenceNV(unsigned int handle)
+FenceNV *Context::getFenceNV(GLuint handle)
{
- FenceNVMap::iterator fence = mFenceNVMap.find(handle);
-
- if (fence == mFenceNVMap.end())
- {
- return NULL;
- }
- else
- {
- return fence->second;
- }
+ return mFenceNVMap.query(handle);
}
-Query *Context::getQuery(unsigned int handle, bool create, GLenum type)
+Query *Context::getQuery(GLuint handle, bool create, GLenum type)
{
- QueryMap::iterator query = mQueryMap.find(handle);
-
- if (query == mQueryMap.end())
+ if (!mQueryMap.contains(handle))
{
- return NULL;
+ return nullptr;
}
- else
+
+ Query *query = mQueryMap.query(handle);
+ if (!query && create)
{
- if (!query->second && create)
- {
- query->second = new Query(mRenderer->createQuery(type), handle);
- query->second->addRef();
- }
- return query->second;
+ query = new Query(mImplementation->createQuery(type), handle);
+ query->addRef();
+ mQueryMap.assign(handle, query);
}
+ return query;
}
Query *Context::getQuery(GLuint handle) const
{
- auto iter = mQueryMap.find(handle);
- return (iter != mQueryMap.end()) ? iter->second : nullptr;
+ return mQueryMap.query(handle);
}
Texture *Context::getTargetTexture(GLenum target) const
{
- ASSERT(ValidTextureTarget(this, target));
- return mState.getTargetTexture(target);
+ ASSERT(ValidTextureTarget(this, target) || ValidTextureExternalTarget(this, target));
+ return mGLState.getTargetTexture(target);
}
Texture *Context::getSamplerTexture(unsigned int sampler, GLenum type) const
{
- return mState.getSamplerTexture(sampler, type);
+ return mGLState.getSamplerTexture(sampler, type);
}
Compiler *Context::getCompiler() const
{
- return mCompiler;
+ if (mCompiler.get() == nullptr)
+ {
+ mCompiler.set(this, new Compiler(mImplementation.get(), mState));
+ }
+ return mCompiler.get();
}
-void Context::getBooleanv(GLenum pname, GLboolean *params)
+void Context::getBooleanvImpl(GLenum pname, GLboolean *params)
{
switch (pname)
{
- case GL_SHADER_COMPILER: *params = GL_TRUE; break;
- case GL_CONTEXT_ROBUST_ACCESS_EXT: *params = mRobustAccess ? GL_TRUE : GL_FALSE; break;
- default:
- mState.getBooleanv(pname, params);
- break;
+ case GL_SHADER_COMPILER:
+ *params = GL_TRUE;
+ break;
+ case GL_CONTEXT_ROBUST_ACCESS_EXT:
+ *params = mRobustAccess ? GL_TRUE : GL_FALSE;
+ break;
+ default:
+ mGLState.getBooleanv(pname, params);
+ break;
}
}
-void Context::getFloatv(GLenum pname, GLfloat *params)
+void Context::getFloatvImpl(GLenum pname, GLfloat *params)
{
// Queries about context capabilities and maximums are answered by Context.
// Queries about current GL state values are answered by State.
switch (pname)
{
- case GL_ALIASED_LINE_WIDTH_RANGE:
- params[0] = mCaps.minAliasedLineWidth;
- params[1] = mCaps.maxAliasedLineWidth;
- break;
- case GL_ALIASED_POINT_SIZE_RANGE:
- params[0] = mCaps.minAliasedPointSize;
- params[1] = mCaps.maxAliasedPointSize;
- break;
- case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
- ASSERT(mExtensions.textureFilterAnisotropic);
- *params = mExtensions.maxTextureAnisotropy;
- break;
- case GL_MAX_TEXTURE_LOD_BIAS:
- *params = mCaps.maxLODBias;
- break;
- default:
- mState.getFloatv(pname, params);
+ case GL_ALIASED_LINE_WIDTH_RANGE:
+ params[0] = mCaps.minAliasedLineWidth;
+ params[1] = mCaps.maxAliasedLineWidth;
+ break;
+ case GL_ALIASED_POINT_SIZE_RANGE:
+ params[0] = mCaps.minAliasedPointSize;
+ params[1] = mCaps.maxAliasedPointSize;
+ break;
+ case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
+ ASSERT(mExtensions.textureFilterAnisotropic);
+ *params = mExtensions.maxTextureAnisotropy;
+ break;
+ case GL_MAX_TEXTURE_LOD_BIAS:
+ *params = mCaps.maxLODBias;
+ break;
+
+ case GL_PATH_MODELVIEW_MATRIX_CHROMIUM:
+ case GL_PATH_PROJECTION_MATRIX_CHROMIUM:
+ {
+ ASSERT(mExtensions.pathRendering);
+ const GLfloat *m = mGLState.getPathRenderingMatrix(pname);
+ memcpy(params, m, 16 * sizeof(GLfloat));
+ }
break;
+
+ default:
+ mGLState.getFloatv(pname, params);
+ break;
}
}
-void Context::getIntegerv(GLenum pname, GLint *params)
+void Context::getIntegervImpl(GLenum pname, GLint *params)
{
// Queries about context capabilities and maximums are answered by Context.
// Queries about current GL state values are answered by State.
switch (pname)
{
- case GL_MAX_VERTEX_ATTRIBS: *params = mCaps.maxVertexAttributes; break;
- case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = mCaps.maxVertexUniformVectors; break;
- case GL_MAX_VERTEX_UNIFORM_COMPONENTS: *params = mCaps.maxVertexUniformComponents; break;
- case GL_MAX_VARYING_VECTORS: *params = mCaps.maxVaryingVectors; break;
- case GL_MAX_VARYING_COMPONENTS: *params = mCaps.maxVertexOutputComponents; break;
- case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = mCaps.maxCombinedTextureImageUnits; break;
- case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = mCaps.maxVertexTextureImageUnits; break;
- case GL_MAX_TEXTURE_IMAGE_UNITS: *params = mCaps.maxTextureImageUnits; break;
- case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = mCaps.maxFragmentUniformVectors; break;
- case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS: *params = mCaps.maxFragmentUniformComponents; break;
- case GL_MAX_RENDERBUFFER_SIZE: *params = mCaps.maxRenderbufferSize; break;
- case GL_MAX_COLOR_ATTACHMENTS_EXT: *params = mCaps.maxColorAttachments; break;
- case GL_MAX_DRAW_BUFFERS_EXT: *params = mCaps.maxDrawBuffers; break;
- //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE
- case GL_SUBPIXEL_BITS: *params = 4; break;
- case GL_MAX_TEXTURE_SIZE: *params = mCaps.max2DTextureSize; break;
- case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = mCaps.maxCubeMapTextureSize; break;
- case GL_MAX_3D_TEXTURE_SIZE: *params = mCaps.max3DTextureSize; break;
- case GL_MAX_ARRAY_TEXTURE_LAYERS: *params = mCaps.maxArrayTextureLayers; break;
- case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: *params = mCaps.uniformBufferOffsetAlignment; break;
- case GL_MAX_UNIFORM_BUFFER_BINDINGS: *params = mCaps.maxUniformBufferBindings; break;
- case GL_MAX_VERTEX_UNIFORM_BLOCKS: *params = mCaps.maxVertexUniformBlocks; break;
- case GL_MAX_FRAGMENT_UNIFORM_BLOCKS: *params = mCaps.maxFragmentUniformBlocks; break;
- case GL_MAX_COMBINED_UNIFORM_BLOCKS: *params = mCaps.maxCombinedTextureImageUnits; break;
- case GL_MAX_VERTEX_OUTPUT_COMPONENTS: *params = mCaps.maxVertexOutputComponents; break;
- case GL_MAX_FRAGMENT_INPUT_COMPONENTS: *params = mCaps.maxFragmentInputComponents; break;
- case GL_MIN_PROGRAM_TEXEL_OFFSET: *params = mCaps.minProgramTexelOffset; break;
- case GL_MAX_PROGRAM_TEXEL_OFFSET: *params = mCaps.maxProgramTexelOffset; break;
- case GL_MAJOR_VERSION: *params = mClientVersion; break;
- case GL_MINOR_VERSION: *params = 0; break;
- case GL_MAX_ELEMENTS_INDICES: *params = mCaps.maxElementsIndices; break;
- case GL_MAX_ELEMENTS_VERTICES: *params = mCaps.maxElementsVertices; break;
- case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: *params = mCaps.maxTransformFeedbackInterleavedComponents; break;
- case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: *params = mCaps.maxTransformFeedbackSeparateAttributes; break;
- case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: *params = mCaps.maxTransformFeedbackSeparateComponents; break;
- case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
- *params = static_cast<GLint>(mCaps.compressedTextureFormats.size());
- break;
- case GL_MAX_SAMPLES_ANGLE: *params = mCaps.maxSamples; break;
- case GL_MAX_VIEWPORT_DIMS:
+ case GL_MAX_VERTEX_ATTRIBS:
+ *params = mCaps.maxVertexAttributes;
+ break;
+ case GL_MAX_VERTEX_UNIFORM_VECTORS:
+ *params = mCaps.maxVertexUniformVectors;
+ break;
+ case GL_MAX_VERTEX_UNIFORM_COMPONENTS:
+ *params = mCaps.maxVertexUniformComponents;
+ break;
+ case GL_MAX_VARYING_VECTORS:
+ *params = mCaps.maxVaryingVectors;
+ break;
+ case GL_MAX_VARYING_COMPONENTS:
+ *params = mCaps.maxVertexOutputComponents;
+ break;
+ case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
+ *params = mCaps.maxCombinedTextureImageUnits;
+ break;
+ case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
+ *params = mCaps.maxVertexTextureImageUnits;
+ break;
+ case GL_MAX_TEXTURE_IMAGE_UNITS:
+ *params = mCaps.maxTextureImageUnits;
+ break;
+ case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
+ *params = mCaps.maxFragmentUniformVectors;
+ break;
+ case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:
+ *params = mCaps.maxFragmentUniformComponents;
+ break;
+ case GL_MAX_RENDERBUFFER_SIZE:
+ *params = mCaps.maxRenderbufferSize;
+ break;
+ case GL_MAX_COLOR_ATTACHMENTS_EXT:
+ *params = mCaps.maxColorAttachments;
+ break;
+ case GL_MAX_DRAW_BUFFERS_EXT:
+ *params = mCaps.maxDrawBuffers;
+ break;
+ // case GL_FRAMEBUFFER_BINDING: // now equivalent to
+ // GL_DRAW_FRAMEBUFFER_BINDING_ANGLE
+ case GL_SUBPIXEL_BITS:
+ *params = 4;
+ break;
+ case GL_MAX_TEXTURE_SIZE:
+ *params = mCaps.max2DTextureSize;
+ break;
+ case GL_MAX_RECTANGLE_TEXTURE_SIZE_ANGLE:
+ *params = mCaps.maxRectangleTextureSize;
+ break;
+ case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
+ *params = mCaps.maxCubeMapTextureSize;
+ break;
+ case GL_MAX_3D_TEXTURE_SIZE:
+ *params = mCaps.max3DTextureSize;
+ break;
+ case GL_MAX_ARRAY_TEXTURE_LAYERS:
+ *params = mCaps.maxArrayTextureLayers;
+ break;
+ case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
+ *params = mCaps.uniformBufferOffsetAlignment;
+ break;
+ case GL_MAX_UNIFORM_BUFFER_BINDINGS:
+ *params = mCaps.maxUniformBufferBindings;
+ break;
+ case GL_MAX_VERTEX_UNIFORM_BLOCKS:
+ *params = mCaps.maxVertexUniformBlocks;
+ break;
+ case GL_MAX_FRAGMENT_UNIFORM_BLOCKS:
+ *params = mCaps.maxFragmentUniformBlocks;
+ break;
+ case GL_MAX_COMBINED_UNIFORM_BLOCKS:
+ *params = mCaps.maxCombinedTextureImageUnits;
+ break;
+ case GL_MAX_VERTEX_OUTPUT_COMPONENTS:
+ *params = mCaps.maxVertexOutputComponents;
+ break;
+ case GL_MAX_FRAGMENT_INPUT_COMPONENTS:
+ *params = mCaps.maxFragmentInputComponents;
+ break;
+ case GL_MIN_PROGRAM_TEXEL_OFFSET:
+ *params = mCaps.minProgramTexelOffset;
+ break;
+ case GL_MAX_PROGRAM_TEXEL_OFFSET:
+ *params = mCaps.maxProgramTexelOffset;
+ break;
+ case GL_MAJOR_VERSION:
+ *params = getClientVersion().major;
+ break;
+ case GL_MINOR_VERSION:
+ *params = getClientVersion().minor;
+ break;
+ case GL_MAX_ELEMENTS_INDICES:
+ *params = mCaps.maxElementsIndices;
+ break;
+ case GL_MAX_ELEMENTS_VERTICES:
+ *params = mCaps.maxElementsVertices;
+ break;
+ case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS:
+ *params = mCaps.maxTransformFeedbackInterleavedComponents;
+ break;
+ case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
+ *params = mCaps.maxTransformFeedbackSeparateAttributes;
+ break;
+ case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS:
+ *params = mCaps.maxTransformFeedbackSeparateComponents;
+ break;
+ case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
+ *params = static_cast<GLint>(mCaps.compressedTextureFormats.size());
+ break;
+ case GL_MAX_SAMPLES_ANGLE:
+ *params = mCaps.maxSamples;
+ break;
+ case GL_MAX_VIEWPORT_DIMS:
{
params[0] = mCaps.maxViewportWidth;
params[1] = mCaps.maxViewportHeight;
}
break;
- case GL_COMPRESSED_TEXTURE_FORMATS:
- std::copy(mCaps.compressedTextureFormats.begin(), mCaps.compressedTextureFormats.end(), params);
- break;
- case GL_RESET_NOTIFICATION_STRATEGY_EXT:
- *params = mResetStrategy;
- break;
- case GL_NUM_SHADER_BINARY_FORMATS:
- *params = static_cast<GLint>(mCaps.shaderBinaryFormats.size());
- break;
- case GL_SHADER_BINARY_FORMATS:
- std::copy(mCaps.shaderBinaryFormats.begin(), mCaps.shaderBinaryFormats.end(), params);
- break;
- case GL_NUM_PROGRAM_BINARY_FORMATS:
- *params = static_cast<GLint>(mCaps.programBinaryFormats.size());
- break;
- case GL_PROGRAM_BINARY_FORMATS:
- std::copy(mCaps.programBinaryFormats.begin(), mCaps.programBinaryFormats.end(), params);
- break;
- case GL_NUM_EXTENSIONS:
- *params = static_cast<GLint>(mExtensionStrings.size());
- break;
+ case GL_COMPRESSED_TEXTURE_FORMATS:
+ std::copy(mCaps.compressedTextureFormats.begin(), mCaps.compressedTextureFormats.end(),
+ params);
+ break;
+ case GL_RESET_NOTIFICATION_STRATEGY_EXT:
+ *params = mResetStrategy;
+ break;
+ case GL_NUM_SHADER_BINARY_FORMATS:
+ *params = static_cast<GLint>(mCaps.shaderBinaryFormats.size());
+ break;
+ case GL_SHADER_BINARY_FORMATS:
+ std::copy(mCaps.shaderBinaryFormats.begin(), mCaps.shaderBinaryFormats.end(), params);
+ break;
+ case GL_NUM_PROGRAM_BINARY_FORMATS:
+ *params = static_cast<GLint>(mCaps.programBinaryFormats.size());
+ break;
+ case GL_PROGRAM_BINARY_FORMATS:
+ std::copy(mCaps.programBinaryFormats.begin(), mCaps.programBinaryFormats.end(), params);
+ break;
+ case GL_NUM_EXTENSIONS:
+ *params = static_cast<GLint>(mExtensionStrings.size());
+ break;
- // GL_KHR_debug
- case GL_MAX_DEBUG_MESSAGE_LENGTH:
- *params = mExtensions.maxDebugMessageLength;
- break;
- case GL_MAX_DEBUG_LOGGED_MESSAGES:
- *params = mExtensions.maxDebugLoggedMessages;
- break;
- case GL_MAX_DEBUG_GROUP_STACK_DEPTH:
- *params = mExtensions.maxDebugGroupStackDepth;
- break;
- case GL_MAX_LABEL_LENGTH:
- *params = mExtensions.maxLabelLength;
- break;
-
- // GL_EXT_disjoint_timer_query
- case GL_GPU_DISJOINT_EXT:
- *params = mRenderer->getGPUDisjoint();
- break;
-
- default:
- mState.getIntegerv(getData(), pname, params);
- break;
+ // GL_KHR_debug
+ case GL_MAX_DEBUG_MESSAGE_LENGTH:
+ *params = mExtensions.maxDebugMessageLength;
+ break;
+ case GL_MAX_DEBUG_LOGGED_MESSAGES:
+ *params = mExtensions.maxDebugLoggedMessages;
+ break;
+ case GL_MAX_DEBUG_GROUP_STACK_DEPTH:
+ *params = mExtensions.maxDebugGroupStackDepth;
+ break;
+ case GL_MAX_LABEL_LENGTH:
+ *params = mExtensions.maxLabelLength;
+ break;
+
+ // GL_ANGLE_multiview
+ case GL_MAX_VIEWS_ANGLE:
+ *params = mExtensions.maxViews;
+ break;
+
+ // GL_EXT_disjoint_timer_query
+ case GL_GPU_DISJOINT_EXT:
+ *params = mImplementation->getGPUDisjoint();
+ break;
+ case GL_MAX_FRAMEBUFFER_WIDTH:
+ *params = mCaps.maxFramebufferWidth;
+ break;
+ case GL_MAX_FRAMEBUFFER_HEIGHT:
+ *params = mCaps.maxFramebufferHeight;
+ break;
+ case GL_MAX_FRAMEBUFFER_SAMPLES:
+ *params = mCaps.maxFramebufferSamples;
+ break;
+ case GL_MAX_SAMPLE_MASK_WORDS:
+ *params = mCaps.maxSampleMaskWords;
+ break;
+ case GL_MAX_COLOR_TEXTURE_SAMPLES:
+ *params = mCaps.maxColorTextureSamples;
+ break;
+ case GL_MAX_DEPTH_TEXTURE_SAMPLES:
+ *params = mCaps.maxDepthTextureSamples;
+ break;
+ case GL_MAX_INTEGER_SAMPLES:
+ *params = mCaps.maxIntegerSamples;
+ break;
+ case GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET:
+ *params = mCaps.maxVertexAttribRelativeOffset;
+ break;
+ case GL_MAX_VERTEX_ATTRIB_BINDINGS:
+ *params = mCaps.maxVertexAttribBindings;
+ break;
+ case GL_MAX_VERTEX_ATTRIB_STRIDE:
+ *params = mCaps.maxVertexAttribStride;
+ break;
+ case GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS:
+ *params = mCaps.maxVertexAtomicCounterBuffers;
+ break;
+ case GL_MAX_VERTEX_ATOMIC_COUNTERS:
+ *params = mCaps.maxVertexAtomicCounters;
+ break;
+ case GL_MAX_VERTEX_IMAGE_UNIFORMS:
+ *params = mCaps.maxVertexImageUniforms;
+ break;
+ case GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS:
+ *params = mCaps.maxVertexShaderStorageBlocks;
+ break;
+ case GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS:
+ *params = mCaps.maxFragmentAtomicCounterBuffers;
+ break;
+ case GL_MAX_FRAGMENT_ATOMIC_COUNTERS:
+ *params = mCaps.maxFragmentAtomicCounters;
+ break;
+ case GL_MAX_FRAGMENT_IMAGE_UNIFORMS:
+ *params = mCaps.maxFragmentImageUniforms;
+ break;
+ case GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS:
+ *params = mCaps.maxFragmentShaderStorageBlocks;
+ break;
+ case GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET:
+ *params = mCaps.minProgramTextureGatherOffset;
+ break;
+ case GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET:
+ *params = mCaps.maxProgramTextureGatherOffset;
+ break;
+ case GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS:
+ *params = mCaps.maxComputeWorkGroupInvocations;
+ break;
+ case GL_MAX_COMPUTE_UNIFORM_BLOCKS:
+ *params = mCaps.maxComputeUniformBlocks;
+ break;
+ case GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS:
+ *params = mCaps.maxComputeTextureImageUnits;
+ break;
+ case GL_MAX_COMPUTE_SHARED_MEMORY_SIZE:
+ *params = mCaps.maxComputeSharedMemorySize;
+ break;
+ case GL_MAX_COMPUTE_UNIFORM_COMPONENTS:
+ *params = mCaps.maxComputeUniformComponents;
+ break;
+ case GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS:
+ *params = mCaps.maxComputeAtomicCounterBuffers;
+ break;
+ case GL_MAX_COMPUTE_ATOMIC_COUNTERS:
+ *params = mCaps.maxComputeAtomicCounters;
+ break;
+ case GL_MAX_COMPUTE_IMAGE_UNIFORMS:
+ *params = mCaps.maxComputeImageUniforms;
+ break;
+ case GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS:
+ *params = mCaps.maxCombinedComputeUniformComponents;
+ break;
+ case GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS:
+ *params = mCaps.maxComputeShaderStorageBlocks;
+ break;
+ case GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES:
+ *params = mCaps.maxCombinedShaderOutputResources;
+ break;
+ case GL_MAX_UNIFORM_LOCATIONS:
+ *params = mCaps.maxUniformLocations;
+ break;
+ case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS:
+ *params = mCaps.maxAtomicCounterBufferBindings;
+ break;
+ case GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE:
+ *params = mCaps.maxAtomicCounterBufferSize;
+ break;
+ case GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS:
+ *params = mCaps.maxCombinedAtomicCounterBuffers;
+ break;
+ case GL_MAX_COMBINED_ATOMIC_COUNTERS:
+ *params = mCaps.maxCombinedAtomicCounters;
+ break;
+ case GL_MAX_IMAGE_UNITS:
+ *params = mCaps.maxImageUnits;
+ break;
+ case GL_MAX_COMBINED_IMAGE_UNIFORMS:
+ *params = mCaps.maxCombinedImageUniforms;
+ break;
+ case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
+ *params = mCaps.maxShaderStorageBufferBindings;
+ break;
+ case GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS:
+ *params = mCaps.maxCombinedShaderStorageBlocks;
+ break;
+ case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
+ *params = mCaps.shaderStorageBufferOffsetAlignment;
+ break;
+ default:
+ mGLState.getIntegerv(this, pname, params);
+ break;
}
}
-void Context::getInteger64v(GLenum pname, GLint64 *params)
+void Context::getInteger64vImpl(GLenum pname, GLint64 *params)
{
// Queries about context capabilities and maximums are answered by Context.
// Queries about current GL state values are answered by State.
switch (pname)
{
- case GL_MAX_ELEMENT_INDEX:
- *params = mCaps.maxElementIndex;
- break;
- case GL_MAX_UNIFORM_BLOCK_SIZE:
- *params = mCaps.maxUniformBlockSize;
- break;
- case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS:
- *params = mCaps.maxCombinedVertexUniformComponents;
- break;
- case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS:
- *params = mCaps.maxCombinedFragmentUniformComponents;
- break;
- case GL_MAX_SERVER_WAIT_TIMEOUT:
- *params = mCaps.maxServerWaitTimeout;
- break;
+ case GL_MAX_ELEMENT_INDEX:
+ *params = mCaps.maxElementIndex;
+ break;
+ case GL_MAX_UNIFORM_BLOCK_SIZE:
+ *params = mCaps.maxUniformBlockSize;
+ break;
+ case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS:
+ *params = mCaps.maxCombinedVertexUniformComponents;
+ break;
+ case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS:
+ *params = mCaps.maxCombinedFragmentUniformComponents;
+ break;
+ case GL_MAX_SERVER_WAIT_TIMEOUT:
+ *params = mCaps.maxServerWaitTimeout;
+ break;
- // GL_EXT_disjoint_timer_query
- case GL_TIMESTAMP_EXT:
- *params = mRenderer->getTimestamp();
- break;
- default:
- UNREACHABLE();
- break;
+ // GL_EXT_disjoint_timer_query
+ case GL_TIMESTAMP_EXT:
+ *params = mImplementation->getTimestamp();
+ break;
+
+ case GL_MAX_SHADER_STORAGE_BLOCK_SIZE:
+ *params = mCaps.maxShaderStorageBlockSize;
+ break;
+ default:
+ UNREACHABLE();
+ break;
}
}
void Context::getPointerv(GLenum pname, void **params) const
{
- mState.getPointerv(pname, params);
+ mGLState.getPointerv(pname, params);
}
-bool Context::getIndexedIntegerv(GLenum target, GLuint index, GLint *data)
+void Context::getIntegeri_v(GLenum target, GLuint index, GLint *data)
{
// Queries about context capabilities and maximums are answered by Context.
// Queries about current GL state values are answered by State.
- // Indexed integer queries all refer to current state, so this function is a
- // mere passthrough.
- return mState.getIndexedIntegerv(target, index, data);
+
+ GLenum nativeType;
+ unsigned int numParams;
+ bool queryStatus = getIndexedQueryParameterInfo(target, &nativeType, &numParams);
+ ASSERT(queryStatus);
+
+ if (nativeType == GL_INT)
+ {
+ switch (target)
+ {
+ case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
+ ASSERT(index < 3u);
+ *data = mCaps.maxComputeWorkGroupCount[index];
+ break;
+ case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
+ ASSERT(index < 3u);
+ *data = mCaps.maxComputeWorkGroupSize[index];
+ break;
+ default:
+ mGLState.getIntegeri_v(target, index, data);
+ }
+ }
+ else
+ {
+ CastIndexedStateValues(this, nativeType, target, index, numParams, data);
+ }
}
-bool Context::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data)
+void Context::getInteger64i_v(GLenum target, GLuint index, GLint64 *data)
{
// Queries about context capabilities and maximums are answered by Context.
// Queries about current GL state values are answered by State.
- // Indexed integer queries all refer to current state, so this function is a
- // mere passthrough.
- return mState.getIndexedInteger64v(target, index, data);
-}
-bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
-{
- if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT)
+ GLenum nativeType;
+ unsigned int numParams;
+ bool queryStatus = getIndexedQueryParameterInfo(target, &nativeType, &numParams);
+ ASSERT(queryStatus);
+
+ if (nativeType == GL_INT_64_ANGLEX)
{
- *type = GL_INT;
- *numParams = 1;
- return true;
+ mGLState.getInteger64i_v(target, index, data);
}
-
- // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
- // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
- // to the fact that it is stored internally as a float, and so would require conversion
- // if returned from Context::getIntegerv. Since this conversion is already implemented
- // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
- // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
- // application.
- switch (pname)
+ else
{
- case GL_COMPRESSED_TEXTURE_FORMATS:
- {
- *type = GL_INT;
- *numParams = static_cast<unsigned int>(mCaps.compressedTextureFormats.size());
- }
- return true;
- case GL_PROGRAM_BINARY_FORMATS_OES:
- {
- *type = GL_INT;
- *numParams = static_cast<unsigned int>(mCaps.programBinaryFormats.size());
- }
- return true;
- case GL_SHADER_BINARY_FORMATS:
- {
- *type = GL_INT;
- *numParams = static_cast<unsigned int>(mCaps.shaderBinaryFormats.size());
- }
- return true;
-
- case GL_MAX_VERTEX_ATTRIBS:
- case GL_MAX_VERTEX_UNIFORM_VECTORS:
- case GL_MAX_VARYING_VECTORS:
- case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
- case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
- case GL_MAX_TEXTURE_IMAGE_UNITS:
- case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
- case GL_MAX_RENDERBUFFER_SIZE:
- case GL_MAX_COLOR_ATTACHMENTS_EXT:
- case GL_MAX_DRAW_BUFFERS_EXT:
- case GL_NUM_SHADER_BINARY_FORMATS:
- case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
- case GL_ARRAY_BUFFER_BINDING:
- //case GL_FRAMEBUFFER_BINDING: // equivalent to DRAW_FRAMEBUFFER_BINDING_ANGLE
- case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE:
- case GL_READ_FRAMEBUFFER_BINDING_ANGLE:
- case GL_RENDERBUFFER_BINDING:
- case GL_CURRENT_PROGRAM:
- case GL_PACK_ALIGNMENT:
- case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
- case GL_UNPACK_ALIGNMENT:
- case GL_GENERATE_MIPMAP_HINT:
- case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
- case GL_RED_BITS:
- case GL_GREEN_BITS:
- case GL_BLUE_BITS:
- case GL_ALPHA_BITS:
- case GL_DEPTH_BITS:
- case GL_STENCIL_BITS:
- case GL_ELEMENT_ARRAY_BUFFER_BINDING:
- case GL_CULL_FACE_MODE:
- case GL_FRONT_FACE:
- case GL_ACTIVE_TEXTURE:
- case GL_STENCIL_FUNC:
- case GL_STENCIL_VALUE_MASK:
- case GL_STENCIL_REF:
- case GL_STENCIL_FAIL:
- case GL_STENCIL_PASS_DEPTH_FAIL:
- case GL_STENCIL_PASS_DEPTH_PASS:
- case GL_STENCIL_BACK_FUNC:
- case GL_STENCIL_BACK_VALUE_MASK:
- case GL_STENCIL_BACK_REF:
- case GL_STENCIL_BACK_FAIL:
- case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
- case GL_STENCIL_BACK_PASS_DEPTH_PASS:
- case GL_DEPTH_FUNC:
- case GL_BLEND_SRC_RGB:
- case GL_BLEND_SRC_ALPHA:
- case GL_BLEND_DST_RGB:
- case GL_BLEND_DST_ALPHA:
- case GL_BLEND_EQUATION_RGB:
- case GL_BLEND_EQUATION_ALPHA:
- case GL_STENCIL_WRITEMASK:
- case GL_STENCIL_BACK_WRITEMASK:
- case GL_STENCIL_CLEAR_VALUE:
- case GL_SUBPIXEL_BITS:
- case GL_MAX_TEXTURE_SIZE:
- case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
- case GL_SAMPLE_BUFFERS:
- case GL_SAMPLES:
- case GL_IMPLEMENTATION_COLOR_READ_TYPE:
- case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
- case GL_TEXTURE_BINDING_2D:
- case GL_TEXTURE_BINDING_CUBE_MAP:
- case GL_RESET_NOTIFICATION_STRATEGY_EXT:
- case GL_NUM_PROGRAM_BINARY_FORMATS_OES:
- {
- *type = GL_INT;
- *numParams = 1;
- }
- return true;
- case GL_MAX_SAMPLES_ANGLE:
- {
- if (mExtensions.framebufferMultisample)
- {
- *type = GL_INT;
- *numParams = 1;
- }
- else
- {
- return false;
- }
- }
- return true;
- case GL_MAX_VIEWPORT_DIMS:
- {
- *type = GL_INT;
- *numParams = 2;
- }
- return true;
- case GL_VIEWPORT:
- case GL_SCISSOR_BOX:
- {
- *type = GL_INT;
- *numParams = 4;
- }
- return true;
- case GL_SHADER_COMPILER:
- case GL_SAMPLE_COVERAGE_INVERT:
- case GL_DEPTH_WRITEMASK:
- case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled,
- case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries.
- case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural
- case GL_SAMPLE_COVERAGE:
- case GL_SCISSOR_TEST:
- case GL_STENCIL_TEST:
- case GL_DEPTH_TEST:
- case GL_BLEND:
- case GL_DITHER:
- case GL_CONTEXT_ROBUST_ACCESS_EXT:
- {
- *type = GL_BOOL;
- *numParams = 1;
- }
- return true;
- case GL_COLOR_WRITEMASK:
- {
- *type = GL_BOOL;
- *numParams = 4;
- }
- return true;
- case GL_POLYGON_OFFSET_FACTOR:
- case GL_POLYGON_OFFSET_UNITS:
- case GL_SAMPLE_COVERAGE_VALUE:
- case GL_DEPTH_CLEAR_VALUE:
- case GL_LINE_WIDTH:
- {
- *type = GL_FLOAT;
- *numParams = 1;
- }
- return true;
- case GL_ALIASED_LINE_WIDTH_RANGE:
- case GL_ALIASED_POINT_SIZE_RANGE:
- case GL_DEPTH_RANGE:
- {
- *type = GL_FLOAT;
- *numParams = 2;
- }
- return true;
- case GL_COLOR_CLEAR_VALUE:
- case GL_BLEND_COLOR:
- {
- *type = GL_FLOAT;
- *numParams = 4;
- }
- return true;
- case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
- if (!mExtensions.maxTextureAnisotropy)
- {
- return false;
- }
- *type = GL_FLOAT;
- *numParams = 1;
- return true;
- case GL_TIMESTAMP_EXT:
- if (!mExtensions.disjointTimerQuery)
- {
- return false;
- }
- *type = GL_INT_64_ANGLEX;
- *numParams = 1;
- return true;
- case GL_GPU_DISJOINT_EXT:
- if (!mExtensions.disjointTimerQuery)
- {
- return false;
- }
- *type = GL_INT;
- *numParams = 1;
- return true;
- }
-
- if (mExtensions.debug)
- {
- switch (pname)
- {
- case GL_DEBUG_LOGGED_MESSAGES:
- case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH:
- case GL_DEBUG_GROUP_STACK_DEPTH:
- case GL_MAX_DEBUG_MESSAGE_LENGTH:
- case GL_MAX_DEBUG_LOGGED_MESSAGES:
- case GL_MAX_DEBUG_GROUP_STACK_DEPTH:
- case GL_MAX_LABEL_LENGTH:
- *type = GL_INT;
- *numParams = 1;
- return true;
-
- case GL_DEBUG_OUTPUT_SYNCHRONOUS:
- case GL_DEBUG_OUTPUT:
- *type = GL_BOOL;
- *numParams = 1;
- return true;
- }
+ CastIndexedStateValues(this, nativeType, target, index, numParams, data);
}
+}
- // Check for ES3.0+ parameter names which are also exposed as ES2 extensions
- switch (pname)
+void Context::getBooleani_v(GLenum target, GLuint index, GLboolean *data)
+{
+ // Queries about context capabilities and maximums are answered by Context.
+ // Queries about current GL state values are answered by State.
+
+ GLenum nativeType;
+ unsigned int numParams;
+ bool queryStatus = getIndexedQueryParameterInfo(target, &nativeType, &numParams);
+ ASSERT(queryStatus);
+
+ if (nativeType == GL_BOOL)
{
- case GL_PACK_ROW_LENGTH:
- case GL_PACK_SKIP_ROWS:
- case GL_PACK_SKIP_PIXELS:
- if ((mClientVersion < 3) && !mExtensions.packSubimage)
- {
- return false;
- }
- *type = GL_INT;
- *numParams = 1;
- return true;
- case GL_UNPACK_ROW_LENGTH:
- case GL_UNPACK_SKIP_ROWS:
- case GL_UNPACK_SKIP_PIXELS:
- if ((mClientVersion < 3) && !mExtensions.unpackSubimage)
- {
- return false;
- }
- *type = GL_INT;
- *numParams = 1;
- return true;
- case GL_VERTEX_ARRAY_BINDING:
- if ((mClientVersion < 3) && !mExtensions.vertexArrayObject)
- {
- return false;
- }
- *type = GL_INT;
- *numParams = 1;
- return true;
- case GL_PIXEL_PACK_BUFFER_BINDING:
- case GL_PIXEL_UNPACK_BUFFER_BINDING:
- if ((mClientVersion < 3) && !mExtensions.pixelBufferObject)
- {
- return false;
- }
- *type = GL_INT;
- *numParams = 1;
- return true;
+ mGLState.getBooleani_v(target, index, data);
}
-
- if (mClientVersion < 3)
+ else
{
- return false;
+ CastIndexedStateValues(this, nativeType, target, index, numParams, data);
}
+}
- // Check for ES3.0+ parameter names
- switch (pname)
- {
- case GL_MAX_UNIFORM_BUFFER_BINDINGS:
- case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
- case GL_UNIFORM_BUFFER_BINDING:
- case GL_TRANSFORM_FEEDBACK_BINDING:
- case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
- case GL_COPY_READ_BUFFER_BINDING:
- case GL_COPY_WRITE_BUFFER_BINDING:
- case GL_TEXTURE_BINDING_3D:
- case GL_TEXTURE_BINDING_2D_ARRAY:
- case GL_MAX_3D_TEXTURE_SIZE:
- case GL_MAX_ARRAY_TEXTURE_LAYERS:
- case GL_MAX_VERTEX_UNIFORM_BLOCKS:
- case GL_MAX_FRAGMENT_UNIFORM_BLOCKS:
- case GL_MAX_COMBINED_UNIFORM_BLOCKS:
- case GL_MAX_VERTEX_OUTPUT_COMPONENTS:
- case GL_MAX_FRAGMENT_INPUT_COMPONENTS:
- case GL_MAX_VARYING_COMPONENTS:
- case GL_MAX_VERTEX_UNIFORM_COMPONENTS:
- case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:
- case GL_MIN_PROGRAM_TEXEL_OFFSET:
- case GL_MAX_PROGRAM_TEXEL_OFFSET:
- case GL_NUM_EXTENSIONS:
- case GL_MAJOR_VERSION:
- case GL_MINOR_VERSION:
- case GL_MAX_ELEMENTS_INDICES:
- case GL_MAX_ELEMENTS_VERTICES:
- case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS:
- case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
- case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS:
- case GL_UNPACK_IMAGE_HEIGHT:
- case GL_UNPACK_SKIP_IMAGES:
- {
- *type = GL_INT;
- *numParams = 1;
- }
- return true;
+void Context::getBufferParameteriv(BufferBinding target, GLenum pname, GLint *params)
+{
+ Buffer *buffer = mGLState.getTargetBuffer(target);
+ QueryBufferParameteriv(buffer, pname, params);
+}
- case GL_MAX_ELEMENT_INDEX:
- case GL_MAX_UNIFORM_BLOCK_SIZE:
- case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS:
- case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS:
- case GL_MAX_SERVER_WAIT_TIMEOUT:
- {
- *type = GL_INT_64_ANGLEX;
- *numParams = 1;
- }
- return true;
+void Context::getFramebufferAttachmentParameteriv(GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLint *params)
+{
+ const Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
+ QueryFramebufferAttachmentParameteriv(framebuffer, attachment, pname, params);
+}
- case GL_TRANSFORM_FEEDBACK_ACTIVE:
- case GL_TRANSFORM_FEEDBACK_PAUSED:
- case GL_PRIMITIVE_RESTART_FIXED_INDEX:
- case GL_RASTERIZER_DISCARD:
- {
- *type = GL_BOOL;
- *numParams = 1;
- }
- return true;
+void Context::getRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+ Renderbuffer *renderbuffer = mGLState.getCurrentRenderbuffer();
+ QueryRenderbufferiv(this, renderbuffer, pname, params);
+}
- case GL_MAX_TEXTURE_LOD_BIAS:
- {
- *type = GL_FLOAT;
- *numParams = 1;
- }
- return true;
- }
+void Context::getTexParameterfv(GLenum target, GLenum pname, GLfloat *params)
+{
+ Texture *texture = getTargetTexture(target);
+ QueryTexParameterfv(texture, pname, params);
+}
- return false;
+void Context::getTexParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+ Texture *texture = getTargetTexture(target);
+ QueryTexParameteriv(texture, pname, params);
}
-bool Context::getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams)
+void Context::getTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params)
{
- if (mClientVersion < 3)
- {
- return false;
- }
+ Texture *texture =
+ getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+ QueryTexLevelParameteriv(texture, target, level, pname, params);
+}
- switch (target)
- {
- case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
- case GL_UNIFORM_BUFFER_BINDING:
- {
- *type = GL_INT;
- *numParams = 1;
- }
- return true;
- case GL_TRANSFORM_FEEDBACK_BUFFER_START:
- case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
- case GL_UNIFORM_BUFFER_START:
- case GL_UNIFORM_BUFFER_SIZE:
- {
- *type = GL_INT_64_ANGLEX;
- *numParams = 1;
- }
- }
+void Context::getTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat *params)
+{
+ Texture *texture =
+ getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+ QueryTexLevelParameterfv(texture, target, level, pname, params);
+}
- return false;
+void Context::texParameterf(GLenum target, GLenum pname, GLfloat param)
+{
+ Texture *texture = getTargetTexture(target);
+ SetTexParameterf(this, texture, pname, param);
+ onTextureChange(texture);
+}
+
+void Context::texParameterfv(GLenum target, GLenum pname, const GLfloat *params)
+{
+ Texture *texture = getTargetTexture(target);
+ SetTexParameterfv(this, texture, pname, params);
+ onTextureChange(texture);
+}
+
+void Context::texParameteri(GLenum target, GLenum pname, GLint param)
+{
+ Texture *texture = getTargetTexture(target);
+ SetTexParameteri(this, texture, pname, param);
+ onTextureChange(texture);
+}
+
+void Context::texParameteriv(GLenum target, GLenum pname, const GLint *params)
+{
+ Texture *texture = getTargetTexture(target);
+ SetTexParameteriv(this, texture, pname, params);
+ onTextureChange(texture);
+}
+
+void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
+{
+ ANGLE_CONTEXT_TRY(prepareForDraw());
+ ANGLE_CONTEXT_TRY(mImplementation->drawArrays(this, mode, first, count));
+ MarkTransformFeedbackBufferUsage(mGLState.getCurrentTransformFeedback());
+}
+
+void Context::drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
+{
+ ANGLE_CONTEXT_TRY(prepareForDraw());
+ ANGLE_CONTEXT_TRY(
+ mImplementation->drawArraysInstanced(this, mode, first, count, instanceCount));
+ MarkTransformFeedbackBufferUsage(mGLState.getCurrentTransformFeedback());
+}
+
+void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)
+{
+ ANGLE_CONTEXT_TRY(prepareForDraw());
+ ANGLE_CONTEXT_TRY(mImplementation->drawElements(this, mode, count, type, indices));
+}
+
+void Context::drawElementsInstanced(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei instances)
+{
+ ANGLE_CONTEXT_TRY(prepareForDraw());
+ ANGLE_CONTEXT_TRY(
+ mImplementation->drawElementsInstanced(this, mode, count, type, indices, instances));
+}
+
+void Context::drawRangeElements(GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const void *indices)
+{
+ ANGLE_CONTEXT_TRY(prepareForDraw());
+ ANGLE_CONTEXT_TRY(
+ mImplementation->drawRangeElements(this, mode, start, end, count, type, indices));
+}
+
+void Context::drawArraysIndirect(GLenum mode, const void *indirect)
+{
+ ANGLE_CONTEXT_TRY(prepareForDraw());
+ ANGLE_CONTEXT_TRY(mImplementation->drawArraysIndirect(this, mode, indirect));
+}
+
+void Context::drawElementsIndirect(GLenum mode, GLenum type, const void *indirect)
+{
+ ANGLE_CONTEXT_TRY(prepareForDraw());
+ ANGLE_CONTEXT_TRY(mImplementation->drawElementsIndirect(this, mode, type, indirect));
+}
+
+void Context::flush()
+{
+ handleError(mImplementation->flush(this));
+}
+
+void Context::finish()
+{
+ handleError(mImplementation->finish(this));
+}
+
+void Context::insertEventMarker(GLsizei length, const char *marker)
+{
+ ASSERT(mImplementation);
+ mImplementation->insertEventMarker(length, marker);
}
-Error Context::drawArrays(GLenum mode, GLint first, GLsizei count)
+void Context::pushGroupMarker(GLsizei length, const char *marker)
+{
+ ASSERT(mImplementation);
+ mImplementation->pushGroupMarker(length, marker);
+}
+
+void Context::popGroupMarker()
+{
+ ASSERT(mImplementation);
+ mImplementation->popGroupMarker();
+}
+
+void Context::bindUniformLocation(GLuint program, GLint location, const GLchar *name)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+
+ programObject->bindUniformLocation(location, name);
+}
+
+void Context::setCoverageModulation(GLenum components)
+{
+ mGLState.setCoverageModulation(components);
+}
+
+void Context::loadPathRenderingMatrix(GLenum matrixMode, const GLfloat *matrix)
+{
+ mGLState.loadPathRenderingMatrix(matrixMode, matrix);
+}
+
+void Context::loadPathRenderingIdentityMatrix(GLenum matrixMode)
+{
+ GLfloat I[16];
+ angle::Matrix<GLfloat>::setToIdentity(I);
+
+ mGLState.loadPathRenderingMatrix(matrixMode, I);
+}
+
+void Context::stencilFillPath(GLuint path, GLenum fillMode, GLuint mask)
{
+ const auto *pathObj = mState.mPaths->getPath(path);
+ if (!pathObj)
+ return;
+
+ // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
syncRendererState();
- Error error = mRenderer->drawArrays(getData(), mode, first, count);
- if (error.isError())
- {
- return error;
- }
- MarkTransformFeedbackBufferUsage(mState.getCurrentTransformFeedback());
+ mImplementation->stencilFillPath(pathObj, fillMode, mask);
+}
+
+void Context::stencilStrokePath(GLuint path, GLint reference, GLuint mask)
+{
+ const auto *pathObj = mState.mPaths->getPath(path);
+ if (!pathObj)
+ return;
+
+ // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+ syncRendererState();
- return Error(GL_NO_ERROR);
+ mImplementation->stencilStrokePath(pathObj, reference, mask);
}
-Error Context::drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
+void Context::coverFillPath(GLuint path, GLenum coverMode)
{
+ const auto *pathObj = mState.mPaths->getPath(path);
+ if (!pathObj)
+ return;
+
+ // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
syncRendererState();
- Error error = mRenderer->drawArraysInstanced(getData(), mode, first, count, instanceCount);
- if (error.isError())
- {
- return error;
- }
- MarkTransformFeedbackBufferUsage(mState.getCurrentTransformFeedback());
+ mImplementation->coverFillPath(pathObj, coverMode);
+}
+
+void Context::coverStrokePath(GLuint path, GLenum coverMode)
+{
+ const auto *pathObj = mState.mPaths->getPath(path);
+ if (!pathObj)
+ return;
- return Error(GL_NO_ERROR);
+ // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+ syncRendererState();
+
+ mImplementation->coverStrokePath(pathObj, coverMode);
}
-Error Context::drawElements(GLenum mode,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- const IndexRange &indexRange)
+void Context::stencilThenCoverFillPath(GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode)
{
+ const auto *pathObj = mState.mPaths->getPath(path);
+ if (!pathObj)
+ return;
+
+ // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
syncRendererState();
- return mRenderer->drawElements(getData(), mode, count, type, indices, indexRange);
+
+ mImplementation->stencilThenCoverFillPath(pathObj, fillMode, mask, coverMode);
}
-Error Context::drawElementsInstanced(GLenum mode,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- GLsizei instances,
- const IndexRange &indexRange)
+void Context::stencilThenCoverStrokePath(GLuint path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode)
{
+ const auto *pathObj = mState.mPaths->getPath(path);
+ if (!pathObj)
+ return;
+
+ // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
syncRendererState();
- return mRenderer->drawElementsInstanced(getData(), mode, count, type, indices, instances,
- indexRange);
+
+ mImplementation->stencilThenCoverStrokePath(pathObj, reference, mask, coverMode);
}
-Error Context::drawRangeElements(GLenum mode,
- GLuint start,
- GLuint end,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- const IndexRange &indexRange)
+void Context::coverFillPathInstanced(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
{
+ const auto &pathObjects = GatherPaths(*mState.mPaths, numPaths, pathNameType, paths, pathBase);
+
+ // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
syncRendererState();
- return mRenderer->drawRangeElements(getData(), mode, start, end, count, type, indices,
- indexRange);
+
+ mImplementation->coverFillPathInstanced(pathObjects, coverMode, transformType, transformValues);
}
-Error Context::flush()
+void Context::coverStrokePathInstanced(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
{
- return mRenderer->flush();
+ const auto &pathObjects = GatherPaths(*mState.mPaths, numPaths, pathNameType, paths, pathBase);
+
+ // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+ syncRendererState();
+
+ mImplementation->coverStrokePathInstanced(pathObjects, coverMode, transformType,
+ transformValues);
}
-Error Context::finish()
+void Context::stencilFillPathInstanced(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
{
- return mRenderer->finish();
+ const auto &pathObjects = GatherPaths(*mState.mPaths, numPaths, pathNameType, paths, pathBase);
+
+ // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+ syncRendererState();
+
+ mImplementation->stencilFillPathInstanced(pathObjects, fillMode, mask, transformType,
+ transformValues);
}
-void Context::insertEventMarker(GLsizei length, const char *marker)
+void Context::stencilStrokePathInstanced(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
{
- ASSERT(mRenderer);
- mRenderer->insertEventMarker(length, marker);
+ const auto &pathObjects = GatherPaths(*mState.mPaths, numPaths, pathNameType, paths, pathBase);
+
+ // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+ syncRendererState();
+
+ mImplementation->stencilStrokePathInstanced(pathObjects, reference, mask, transformType,
+ transformValues);
}
-void Context::pushGroupMarker(GLsizei length, const char *marker)
+void Context::stencilThenCoverFillPathInstanced(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
{
- ASSERT(mRenderer);
- mRenderer->pushGroupMarker(length, marker);
+ const auto &pathObjects = GatherPaths(*mState.mPaths, numPaths, pathNameType, paths, pathBase);
+
+ // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+ syncRendererState();
+
+ mImplementation->stencilThenCoverFillPathInstanced(pathObjects, coverMode, fillMode, mask,
+ transformType, transformValues);
}
-void Context::popGroupMarker()
+void Context::stencilThenCoverStrokePathInstanced(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ const auto &pathObjects = GatherPaths(*mState.mPaths, numPaths, pathNameType, paths, pathBase);
+
+ // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
+ syncRendererState();
+
+ mImplementation->stencilThenCoverStrokePathInstanced(pathObjects, coverMode, reference, mask,
+ transformType, transformValues);
+}
+
+void Context::bindFragmentInputLocation(GLuint program, GLint location, const GLchar *name)
+{
+ auto *programObject = getProgram(program);
+
+ programObject->bindFragmentInputLocation(location, name);
+}
+
+void Context::programPathFragmentInputGen(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs)
+{
+ auto *programObject = getProgram(program);
+
+ programObject->pathFragmentInputGen(this, location, genMode, components, coeffs);
+}
+
+GLuint Context::getProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar *name)
+{
+ const auto *programObject = getProgram(program);
+ return QueryProgramResourceIndex(programObject, programInterface, name);
+}
+
+void Context::getProgramResourceName(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name)
+{
+ const auto *programObject = getProgram(program);
+ QueryProgramResourceName(programObject, programInterface, index, bufSize, length, name);
+}
+
+GLint Context::getProgramResourceLocation(GLuint program,
+ GLenum programInterface,
+ const GLchar *name)
+{
+ const auto *programObject = getProgram(program);
+ return QueryProgramResourceLocation(programObject, programInterface, name);
+}
+
+void Context::getProgramResourceiv(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum *props,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ const auto *programObject = getProgram(program);
+ QueryProgramResourceiv(programObject, programInterface, index, propCount, props, bufSize,
+ length, params);
+}
+
+void Context::getProgramInterfaceiv(GLuint program,
+ GLenum programInterface,
+ GLenum pname,
+ GLint *params)
{
- ASSERT(mRenderer);
- mRenderer->popGroupMarker();
+ const auto *programObject = getProgram(program);
+ QueryProgramInterfaceiv(programObject, programInterface, pname, params);
}
-void Context::recordError(const Error &error)
+void Context::handleError(const Error &error)
{
if (error.isError())
{
- mErrors.insert(error.getCode());
-
- if (!error.getMessage().empty())
+ GLenum code = error.getCode();
+ mErrors.insert(code);
+ if (code == GL_OUT_OF_MEMORY && getWorkarounds().loseContextOnOutOfMemory)
{
- auto &debug = mState.getDebug();
- debug.insertMessage(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, error.getID(),
- GL_DEBUG_SEVERITY_HIGH, error.getMessage());
+ markContextLost();
}
+
+ ASSERT(!error.getMessage().empty());
+ mGLState.getDebug().insertMessage(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, error.getID(),
+ GL_DEBUG_SEVERITY_HIGH, error.getMessage());
}
}
@@ -1636,32 +2093,61 @@ GLenum Context::getError()
}
}
+// NOTE: this function should not assume that this context is current!
+void Context::markContextLost()
+{
+ if (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT)
+ {
+ mResetStatus = GL_UNKNOWN_CONTEXT_RESET_EXT;
+ mContextLostForced = true;
+ }
+ mContextLost = true;
+}
+
+bool Context::isContextLost()
+{
+ return mContextLost;
+}
+
GLenum Context::getResetStatus()
{
- //TODO(jmadill): needs MANGLE reworking
- if (mResetStatus == GL_NO_ERROR && !mContextLost)
+ // Even if the application doesn't want to know about resets, we want to know
+ // as it will allow us to skip all the calls.
+ if (mResetStrategy == GL_NO_RESET_NOTIFICATION_EXT)
{
- // mResetStatus will be set by the markContextLost callback
- // in the case a notification is sent
- if (mRenderer->testDeviceLost())
+ if (!mContextLost && mImplementation->getResetStatus() != GL_NO_ERROR)
{
- mRenderer->notifyDeviceLost();
+ mContextLost = true;
}
- }
- GLenum status = mResetStatus;
+ // EXT_robustness, section 2.6: If the reset notification behavior is
+ // NO_RESET_NOTIFICATION_EXT, then the implementation will never deliver notification of
+ // reset events, and GetGraphicsResetStatusEXT will always return NO_ERROR.
+ return GL_NO_ERROR;
+ }
- if (mResetStatus != GL_NO_ERROR)
+ // The GL_EXT_robustness spec says that if a reset is encountered, a reset
+ // status should be returned at least once, and GL_NO_ERROR should be returned
+ // once the device has finished resetting.
+ if (!mContextLost)
{
- ASSERT(mContextLost);
+ ASSERT(mResetStatus == GL_NO_ERROR);
+ mResetStatus = mImplementation->getResetStatus();
- if (mRenderer->testDeviceResettable())
+ if (mResetStatus != GL_NO_ERROR)
{
- mResetStatus = GL_NO_ERROR;
+ mContextLost = true;
}
}
+ else if (!mContextLostForced && mResetStatus != GL_NO_ERROR)
+ {
+ // If markContextLost was used to mark the context lost then
+ // assume that is not recoverable, and continue to report the
+ // lost reset status for the lifetime of this context.
+ mResetStatus = mImplementation->getResetStatus();
+ }
- return status;
+ return mResetStatus;
}
bool Context::isResetNotificationEnabled()
@@ -1681,73 +2167,57 @@ EGLenum Context::getClientType() const
EGLenum Context::getRenderBuffer() const
{
- auto framebufferIt = mFramebufferMap.find(0);
- if (framebufferIt != mFramebufferMap.end())
- {
- const Framebuffer *framebuffer = framebufferIt->second;
- const FramebufferAttachment *backAttachment = framebuffer->getAttachment(GL_BACK);
-
- ASSERT(backAttachment != nullptr);
- return backAttachment->getSurface()->getRenderBuffer();
- }
- else
+ const Framebuffer *framebuffer = mState.mFramebuffers->getFramebuffer(0);
+ if (framebuffer == nullptr)
{
return EGL_NONE;
}
-}
-void Context::checkVertexArrayAllocation(GLuint vertexArray)
-{
- // Only called after a prior call to Gen.
- if (!getVertexArray(vertexArray))
- {
- VertexArray *vertexArrayObject =
- new VertexArray(mRenderer, vertexArray, MAX_VERTEX_ATTRIBS);
- mVertexArrayMap[vertexArray] = vertexArrayObject;
- }
+ const FramebufferAttachment *backAttachment = framebuffer->getAttachment(GL_BACK);
+ ASSERT(backAttachment != nullptr);
+ return backAttachment->getSurface()->getRenderBuffer();
}
-void Context::checkTransformFeedbackAllocation(GLuint transformFeedback)
+VertexArray *Context::checkVertexArrayAllocation(GLuint vertexArrayHandle)
{
// Only called after a prior call to Gen.
- if (!getTransformFeedback(transformFeedback))
+ VertexArray *vertexArray = getVertexArray(vertexArrayHandle);
+ if (!vertexArray)
{
- TransformFeedback *transformFeedbackObject =
- new TransformFeedback(mRenderer->createTransformFeedback(), transformFeedback, mCaps);
- transformFeedbackObject->addRef();
- mTransformFeedbackMap[transformFeedback] = transformFeedbackObject;
+ vertexArray = new VertexArray(mImplementation.get(), vertexArrayHandle,
+ mCaps.maxVertexAttributes, mCaps.maxVertexAttribBindings);
+
+ mVertexArrayMap.assign(vertexArrayHandle, vertexArray);
}
+
+ return vertexArray;
}
-Framebuffer *Context::checkFramebufferAllocation(GLuint framebuffer)
+TransformFeedback *Context::checkTransformFeedbackAllocation(GLuint transformFeedbackHandle)
{
- // Can be called from Bind without a prior call to Gen.
- auto framebufferIt = mFramebufferMap.find(framebuffer);
- bool neverCreated = framebufferIt == mFramebufferMap.end();
- if (neverCreated || framebufferIt->second == nullptr)
+ // Only called after a prior call to Gen.
+ TransformFeedback *transformFeedback = getTransformFeedback(transformFeedbackHandle);
+ if (!transformFeedback)
{
- Framebuffer *newFBO = new Framebuffer(mCaps, mRenderer, framebuffer);
- if (neverCreated)
- {
- mFramebufferHandleAllocator.reserve(framebuffer);
- mFramebufferMap[framebuffer] = newFBO;
- return newFBO;
- }
-
- framebufferIt->second = newFBO;
+ transformFeedback =
+ new TransformFeedback(mImplementation.get(), transformFeedbackHandle, mCaps);
+ transformFeedback->addRef();
+ mTransformFeedbackMap.assign(transformFeedbackHandle, transformFeedback);
}
- return framebufferIt->second;
+ return transformFeedback;
}
bool Context::isVertexArrayGenerated(GLuint vertexArray)
{
- return mVertexArrayMap.find(vertexArray) != mVertexArrayMap.end();
+ ASSERT(mVertexArrayMap.contains(0));
+ return mVertexArrayMap.contains(vertexArray);
}
bool Context::isTransformFeedbackGenerated(GLuint transformFeedback)
{
- return mTransformFeedbackMap.find(transformFeedback) != mTransformFeedbackMap.end();
+ ASSERT(mTransformFeedbackMap.contains(0));
+ return mTransformFeedbackMap.contains(transformFeedback);
}
void Context::detachTexture(GLuint texture)
@@ -1756,7 +2226,7 @@ void Context::detachTexture(GLuint texture)
// allocation map management either here or in the resource manager at detach time.
// Zero textures are held by the Context, and we don't attempt to request them from
// the State.
- mState.detachTexture(mZeroTextures, texture);
+ mGLState.detachTexture(this, mZeroTextures, texture);
}
void Context::detachBuffer(GLuint buffer)
@@ -1769,7 +2239,7 @@ void Context::detachBuffer(GLuint buffer)
// Attachments to unbound container objects, such as
// deletion of a buffer attached to a vertex array object which is not bound to the context,
// are not affected and continue to act as references on the deleted object
- mState.detachBuffer(buffer);
+ mGLState.detachBuffer(this, buffer);
}
void Context::detachFramebuffer(GLuint framebuffer)
@@ -1779,15 +2249,16 @@ void Context::detachFramebuffer(GLuint framebuffer)
// to State at binding time.
// [OpenGL ES 2.0.24] section 4.4 page 107:
- // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
- // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
+ // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as
+ // though BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of
+ // zero.
- if (mState.removeReadFramebufferBinding(framebuffer) && framebuffer != 0)
+ if (mGLState.removeReadFramebufferBinding(framebuffer) && framebuffer != 0)
{
bindReadFramebuffer(0);
}
- if (mState.removeDrawFramebufferBinding(framebuffer) && framebuffer != 0)
+ if (mGLState.removeDrawFramebufferBinding(framebuffer) && framebuffer != 0)
{
bindDrawFramebuffer(0);
}
@@ -1795,7 +2266,7 @@ void Context::detachFramebuffer(GLuint framebuffer)
void Context::detachRenderbuffer(GLuint renderbuffer)
{
- mState.detachRenderbuffer(renderbuffer);
+ mGLState.detachRenderbuffer(this, renderbuffer);
}
void Context::detachVertexArray(GLuint vertexArray)
@@ -1807,7 +2278,7 @@ void Context::detachVertexArray(GLuint vertexArray)
// [OpenGL ES 3.0.2] section 2.10 page 43:
// If a vertex array object that is currently bound is deleted, the binding
// for that object reverts to zero and the default vertex array becomes current.
- if (mState.removeVertexArrayBinding(vertexArray))
+ if (mGLState.removeVertexArrayBinding(vertexArray))
{
bindVertexArray(0);
}
@@ -1815,151 +2286,188 @@ void Context::detachVertexArray(GLuint vertexArray)
void Context::detachTransformFeedback(GLuint transformFeedback)
{
- mState.detachTransformFeedback(transformFeedback);
+ // Transform feedback detachment is handled by Context, because 0 is a valid
+ // transform feedback, and a pointer to it must be passed from Context to State at
+ // binding time.
+
+ // The OpenGL specification doesn't mention what should happen when the currently bound
+ // transform feedback object is deleted. Since it is a container object, we treat it like
+ // VAOs and FBOs and set the current bound transform feedback back to 0.
+ if (mGLState.removeTransformFeedbackBinding(this, transformFeedback))
+ {
+ bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
+ }
}
void Context::detachSampler(GLuint sampler)
{
- mState.detachSampler(sampler);
+ mGLState.detachSampler(this, sampler);
}
-void Context::setVertexAttribDivisor(GLuint index, GLuint divisor)
+void Context::detachProgramPipeline(GLuint pipeline)
{
- mState.setVertexAttribDivisor(index, divisor);
+ mGLState.detachProgramPipeline(this, pipeline);
}
-void Context::samplerParameteri(GLuint sampler, GLenum pname, GLint param)
+void Context::vertexAttribDivisor(GLuint index, GLuint divisor)
{
- mResourceManager->checkSamplerAllocation(sampler);
+ mGLState.setVertexAttribDivisor(this, index, divisor);
+}
- Sampler *samplerObject = getSampler(sampler);
- ASSERT(samplerObject);
+void Context::samplerParameteri(GLuint sampler, GLenum pname, GLint param)
+{
+ Sampler *samplerObject =
+ mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler);
+ SetSamplerParameteri(samplerObject, pname, param);
+ mGLState.setObjectDirty(GL_SAMPLER);
+}
- // clang-format off
- switch (pname)
- {
- case GL_TEXTURE_MIN_FILTER: samplerObject->setMinFilter(static_cast<GLenum>(param)); break;
- case GL_TEXTURE_MAG_FILTER: samplerObject->setMagFilter(static_cast<GLenum>(param)); break;
- case GL_TEXTURE_WRAP_S: samplerObject->setWrapS(static_cast<GLenum>(param)); break;
- case GL_TEXTURE_WRAP_T: samplerObject->setWrapT(static_cast<GLenum>(param)); break;
- case GL_TEXTURE_WRAP_R: samplerObject->setWrapR(static_cast<GLenum>(param)); break;
- case GL_TEXTURE_MAX_ANISOTROPY_EXT: samplerObject->setMaxAnisotropy(std::min(static_cast<GLfloat>(param), getExtensions().maxTextureAnisotropy)); break;
- case GL_TEXTURE_MIN_LOD: samplerObject->setMinLod(static_cast<GLfloat>(param)); break;
- case GL_TEXTURE_MAX_LOD: samplerObject->setMaxLod(static_cast<GLfloat>(param)); break;
- case GL_TEXTURE_COMPARE_MODE: samplerObject->setCompareMode(static_cast<GLenum>(param)); break;
- case GL_TEXTURE_COMPARE_FUNC: samplerObject->setCompareFunc(static_cast<GLenum>(param)); break;
- default: UNREACHABLE(); break;
- }
- // clang-format on
+void Context::samplerParameteriv(GLuint sampler, GLenum pname, const GLint *param)
+{
+ Sampler *samplerObject =
+ mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler);
+ SetSamplerParameteriv(samplerObject, pname, param);
+ mGLState.setObjectDirty(GL_SAMPLER);
}
void Context::samplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
{
- mResourceManager->checkSamplerAllocation(sampler);
-
- Sampler *samplerObject = getSampler(sampler);
- ASSERT(samplerObject);
-
- // clang-format off
- switch (pname)
- {
- case GL_TEXTURE_MIN_FILTER: samplerObject->setMinFilter(uiround<GLenum>(param)); break;
- case GL_TEXTURE_MAG_FILTER: samplerObject->setMagFilter(uiround<GLenum>(param)); break;
- case GL_TEXTURE_WRAP_S: samplerObject->setWrapS(uiround<GLenum>(param)); break;
- case GL_TEXTURE_WRAP_T: samplerObject->setWrapT(uiround<GLenum>(param)); break;
- case GL_TEXTURE_WRAP_R: samplerObject->setWrapR(uiround<GLenum>(param)); break;
- case GL_TEXTURE_MAX_ANISOTROPY_EXT: samplerObject->setMaxAnisotropy(std::min(param, getExtensions().maxTextureAnisotropy)); break;
- case GL_TEXTURE_MIN_LOD: samplerObject->setMinLod(param); break;
- case GL_TEXTURE_MAX_LOD: samplerObject->setMaxLod(param); break;
- case GL_TEXTURE_COMPARE_MODE: samplerObject->setCompareMode(uiround<GLenum>(param)); break;
- case GL_TEXTURE_COMPARE_FUNC: samplerObject->setCompareFunc(uiround<GLenum>(param)); break;
- default: UNREACHABLE(); break;
- }
- // clang-format on
+ Sampler *samplerObject =
+ mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler);
+ SetSamplerParameterf(samplerObject, pname, param);
+ mGLState.setObjectDirty(GL_SAMPLER);
}
-GLint Context::getSamplerParameteri(GLuint sampler, GLenum pname)
+void Context::samplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *param)
{
- mResourceManager->checkSamplerAllocation(sampler);
-
- Sampler *samplerObject = getSampler(sampler);
- ASSERT(samplerObject);
-
- // clang-format off
- switch (pname)
- {
- case GL_TEXTURE_MIN_FILTER: return static_cast<GLint>(samplerObject->getMinFilter());
- case GL_TEXTURE_MAG_FILTER: return static_cast<GLint>(samplerObject->getMagFilter());
- case GL_TEXTURE_WRAP_S: return static_cast<GLint>(samplerObject->getWrapS());
- case GL_TEXTURE_WRAP_T: return static_cast<GLint>(samplerObject->getWrapT());
- case GL_TEXTURE_WRAP_R: return static_cast<GLint>(samplerObject->getWrapR());
- case GL_TEXTURE_MAX_ANISOTROPY_EXT: return static_cast<GLint>(samplerObject->getMaxAnisotropy());
- case GL_TEXTURE_MIN_LOD: return uiround<GLint>(samplerObject->getMinLod());
- case GL_TEXTURE_MAX_LOD: return uiround<GLint>(samplerObject->getMaxLod());
- case GL_TEXTURE_COMPARE_MODE: return static_cast<GLint>(samplerObject->getCompareMode());
- case GL_TEXTURE_COMPARE_FUNC: return static_cast<GLint>(samplerObject->getCompareFunc());
- default: UNREACHABLE(); return 0;
- }
- // clang-format on
+ Sampler *samplerObject =
+ mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler);
+ SetSamplerParameterfv(samplerObject, pname, param);
+ mGLState.setObjectDirty(GL_SAMPLER);
}
-GLfloat Context::getSamplerParameterf(GLuint sampler, GLenum pname)
+void Context::getSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
{
- mResourceManager->checkSamplerAllocation(sampler);
+ const Sampler *samplerObject =
+ mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler);
+ QuerySamplerParameteriv(samplerObject, pname, params);
+ mGLState.setObjectDirty(GL_SAMPLER);
+}
- Sampler *samplerObject = getSampler(sampler);
- ASSERT(samplerObject);
+void Context::getSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params)
+{
+ const Sampler *samplerObject =
+ mState.mSamplers->checkSamplerAllocation(mImplementation.get(), sampler);
+ QuerySamplerParameterfv(samplerObject, pname, params);
+ mGLState.setObjectDirty(GL_SAMPLER);
+}
- // clang-format off
- switch (pname)
- {
- case GL_TEXTURE_MIN_FILTER: return static_cast<GLfloat>(samplerObject->getMinFilter());
- case GL_TEXTURE_MAG_FILTER: return static_cast<GLfloat>(samplerObject->getMagFilter());
- case GL_TEXTURE_WRAP_S: return static_cast<GLfloat>(samplerObject->getWrapS());
- case GL_TEXTURE_WRAP_T: return static_cast<GLfloat>(samplerObject->getWrapT());
- case GL_TEXTURE_WRAP_R: return static_cast<GLfloat>(samplerObject->getWrapR());
- case GL_TEXTURE_MAX_ANISOTROPY_EXT: return samplerObject->getMaxAnisotropy();
- case GL_TEXTURE_MIN_LOD: return samplerObject->getMinLod();
- case GL_TEXTURE_MAX_LOD: return samplerObject->getMaxLod();
- case GL_TEXTURE_COMPARE_MODE: return static_cast<GLfloat>(samplerObject->getCompareMode());
- case GL_TEXTURE_COMPARE_FUNC: return static_cast<GLfloat>(samplerObject->getCompareFunc());
- default: UNREACHABLE(); return 0;
- }
- // clang-format on
+void Context::programParameteri(GLuint program, GLenum pname, GLint value)
+{
+ gl::Program *programObject = getProgram(program);
+ SetProgramParameteri(programObject, pname, value);
}
void Context::initRendererString()
{
std::ostringstream rendererString;
rendererString << "ANGLE (";
- rendererString << mRenderer->getRendererDescription();
+ rendererString << mImplementation->getRendererDescription();
rendererString << ")";
mRendererString = MakeStaticString(rendererString.str());
}
-const std::string &Context::getRendererString() const
+void Context::initVersionStrings()
{
- return mRendererString;
+ const Version &clientVersion = getClientVersion();
+
+ std::ostringstream versionString;
+ versionString << "OpenGL ES " << clientVersion.major << "." << clientVersion.minor << " (ANGLE "
+ << ANGLE_VERSION_STRING << ")";
+ mVersionString = MakeStaticString(versionString.str());
+
+ std::ostringstream shadingLanguageVersionString;
+ shadingLanguageVersionString << "OpenGL ES GLSL ES "
+ << (clientVersion.major == 2 ? 1 : clientVersion.major) << "."
+ << clientVersion.minor << "0 (ANGLE " << ANGLE_VERSION_STRING
+ << ")";
+ mShadingLanguageString = MakeStaticString(shadingLanguageVersionString.str());
}
void Context::initExtensionStrings()
{
- mExtensionStrings = mExtensions.getStrings();
+ auto mergeExtensionStrings = [](const std::vector<const char *> &strings) {
+ std::ostringstream combinedStringStream;
+ std::copy(strings.begin(), strings.end(),
+ std::ostream_iterator<const char *>(combinedStringStream, " "));
+ return MakeStaticString(combinedStringStream.str());
+ };
- std::ostringstream combinedStringStream;
- std::copy(mExtensionStrings.begin(), mExtensionStrings.end(), std::ostream_iterator<std::string>(combinedStringStream, " "));
- mExtensionString = combinedStringStream.str();
+ mExtensionStrings.clear();
+ for (const auto &extensionString : mExtensions.getStrings())
+ {
+ mExtensionStrings.push_back(MakeStaticString(extensionString));
+ }
+ mExtensionString = mergeExtensionStrings(mExtensionStrings);
+
+ const gl::Extensions &nativeExtensions = mImplementation->getNativeExtensions();
+
+ mRequestableExtensionStrings.clear();
+ for (const auto &extensionInfo : GetExtensionInfoMap())
+ {
+ if (extensionInfo.second.Requestable &&
+ !(mExtensions.*(extensionInfo.second.ExtensionsMember)) &&
+ nativeExtensions.*(extensionInfo.second.ExtensionsMember))
+ {
+ mRequestableExtensionStrings.push_back(MakeStaticString(extensionInfo.first));
+ }
+ }
+ mRequestableExtensionString = mergeExtensionStrings(mRequestableExtensionStrings);
}
-const std::string &Context::getExtensionString() const
+const GLubyte *Context::getString(GLenum name) const
{
- return mExtensionString;
+ switch (name)
+ {
+ case GL_VENDOR:
+ return reinterpret_cast<const GLubyte *>("Google Inc.");
+
+ case GL_RENDERER:
+ return reinterpret_cast<const GLubyte *>(mRendererString);
+
+ case GL_VERSION:
+ return reinterpret_cast<const GLubyte *>(mVersionString);
+
+ case GL_SHADING_LANGUAGE_VERSION:
+ return reinterpret_cast<const GLubyte *>(mShadingLanguageString);
+
+ case GL_EXTENSIONS:
+ return reinterpret_cast<const GLubyte *>(mExtensionString);
+
+ case GL_REQUESTABLE_EXTENSIONS_ANGLE:
+ return reinterpret_cast<const GLubyte *>(mRequestableExtensionString);
+
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
}
-const std::string &Context::getExtensionString(size_t idx) const
+const GLubyte *Context::getStringi(GLenum name, GLuint index) const
{
- return mExtensionStrings[idx];
+ switch (name)
+ {
+ case GL_EXTENSIONS:
+ return reinterpret_cast<const GLubyte *>(mExtensionStrings[index]);
+
+ case GL_REQUESTABLE_EXTENSIONS_ANGLE:
+ return reinterpret_cast<const GLubyte *>(mRequestableExtensionStrings[index]);
+
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
}
size_t Context::getExtensionStringCount() const
@@ -1967,26 +2475,117 @@ size_t Context::getExtensionStringCount() const
return mExtensionStrings.size();
}
-void Context::initCaps(GLuint clientVersion)
+bool Context::isExtensionRequestable(const char *name)
+{
+ const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
+ auto extension = extensionInfos.find(name);
+
+ const Extensions &nativeExtensions = mImplementation->getNativeExtensions();
+ return extension != extensionInfos.end() && extension->second.Requestable &&
+ nativeExtensions.*(extension->second.ExtensionsMember);
+}
+
+void Context::requestExtension(const char *name)
+{
+ const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
+ ASSERT(extensionInfos.find(name) != extensionInfos.end());
+ const auto &extension = extensionInfos.at(name);
+ ASSERT(extension.Requestable);
+ ASSERT(mImplementation->getNativeExtensions().*(extension.ExtensionsMember));
+
+ if (mExtensions.*(extension.ExtensionsMember))
+ {
+ // Extension already enabled
+ return;
+ }
+
+ mExtensions.*(extension.ExtensionsMember) = true;
+ updateCaps();
+ initExtensionStrings();
+
+ // Release the shader compiler so it will be re-created with the requested extensions enabled.
+ releaseShaderCompiler();
+
+ // Invalidate all textures and framebuffer. Some extensions make new formats renderable or
+ // sampleable.
+ mState.mTextures->signalAllTexturesDirty();
+ for (auto &zeroTexture : mZeroTextures)
+ {
+ zeroTexture.second->signalDirty(InitState::Initialized);
+ }
+
+ mState.mFramebuffers->invalidateFramebufferComplenessCache();
+}
+
+size_t Context::getRequestableExtensionStringCount() const
+{
+ return mRequestableExtensionStrings.size();
+}
+
+void Context::beginTransformFeedback(GLenum primitiveMode)
+{
+ TransformFeedback *transformFeedback = mGLState.getCurrentTransformFeedback();
+ ASSERT(transformFeedback != nullptr);
+ ASSERT(!transformFeedback->isPaused());
+
+ transformFeedback->begin(this, primitiveMode, mGLState.getProgram());
+}
+
+bool Context::hasActiveTransformFeedback(GLuint program) const
+{
+ for (auto pair : mTransformFeedbackMap)
+ {
+ if (pair.second != nullptr && pair.second->hasBoundProgram(program))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void Context::initCaps(const egl::DisplayExtensions &displayExtensions, bool robustResourceInit)
{
- mCaps = mRenderer->getRendererCaps();
+ mCaps = mImplementation->getNativeCaps();
- mExtensions = mRenderer->getRendererExtensions();
+ mExtensions = mImplementation->getNativeExtensions();
- mLimitations = mRenderer->getRendererLimitations();
+ mLimitations = mImplementation->getNativeLimitations();
- if (clientVersion < 3)
+ if (getClientVersion() < Version(3, 0))
{
// Disable ES3+ extensions
- mExtensions.colorBufferFloat = false;
+ mExtensions.colorBufferFloat = false;
+ mExtensions.eglImageExternalEssl3 = false;
+ mExtensions.textureNorm16 = false;
+ mExtensions.multiview = false;
+ mExtensions.maxViews = 1u;
}
- if (clientVersion > 2)
+ if (getClientVersion() < ES_3_1)
+ {
+ // Disable ES3.1+ extensions
+ mExtensions.geometryShader = false;
+ }
+
+ if (getClientVersion() > Version(2, 0))
{
// FIXME(geofflang): Don't support EXT_sRGB in non-ES2 contexts
- //mExtensions.sRGB = false;
+ // mExtensions.sRGB = false;
}
+ // Some extensions are always available because they are implemented in the GL layer.
+ mExtensions.bindUniformLocation = true;
+ mExtensions.vertexArrayObject = true;
+ mExtensions.bindGeneratesResource = true;
+ mExtensions.clientArrays = true;
+ mExtensions.requestExtension = true;
+
+ // Enable the no error extension if the context was created with the flag.
+ mExtensions.noError = mSkipValidation;
+
+ // Enable surfaceless to advertise we'll have the correct behavior when there is no default FBO
+ mExtensions.surfacelessContext = displayExtensions.surfacelessContext;
+
// Explicitly enable GL_KHR_debug
mExtensions.debug = true;
mExtensions.maxDebugMessageLength = 1024;
@@ -1994,64 +2593,186 @@ void Context::initCaps(GLuint clientVersion)
mExtensions.maxDebugGroupStackDepth = 1024;
mExtensions.maxLabelLength = 1024;
+ // Explicitly enable GL_ANGLE_robust_client_memory
+ mExtensions.robustClientMemory = true;
+
+ // Determine robust resource init availability from EGL.
+ mExtensions.robustResourceInitialization = robustResourceInit;
+
+ // mExtensions.robustBufferAccessBehavior is true only if robust access is true and the backend
+ // supports it.
+ mExtensions.robustBufferAccessBehavior =
+ mRobustAccess && mExtensions.robustBufferAccessBehavior;
+
+ // Enable the cache control query unconditionally.
+ mExtensions.programCacheControl = true;
+
// Apply implementation limits
- mCaps.maxVertexAttributes = std::min<GLuint>(mCaps.maxVertexAttributes, MAX_VERTEX_ATTRIBS);
- mCaps.maxVertexUniformBlocks = std::min<GLuint>(mCaps.maxVertexUniformBlocks, IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS);
- mCaps.maxVertexOutputComponents = std::min<GLuint>(mCaps.maxVertexOutputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4);
+ LimitCap(&mCaps.maxVertexAttributes, MAX_VERTEX_ATTRIBS);
+
+ if (getClientVersion() < ES_3_1)
+ {
+ mCaps.maxVertexAttribBindings = mCaps.maxVertexAttributes;
+ }
+ else
+ {
+ LimitCap(&mCaps.maxVertexAttribBindings, MAX_VERTEX_ATTRIB_BINDINGS);
+ }
- mCaps.maxFragmentInputComponents = std::min<GLuint>(mCaps.maxFragmentInputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4);
+ LimitCap(&mCaps.maxVertexUniformBlocks, IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS);
+ LimitCap(&mCaps.maxVertexOutputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4);
+ LimitCap(&mCaps.maxFragmentInputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4);
- mCaps.compressedTextureFormats.clear();
+ // Limit textures as well, so we can use fast bitsets with texture bindings.
+ LimitCap(&mCaps.maxCombinedTextureImageUnits, IMPLEMENTATION_MAX_ACTIVE_TEXTURES);
+ LimitCap(&mCaps.maxVertexTextureImageUnits, IMPLEMENTATION_MAX_ACTIVE_TEXTURES / 2);
+ LimitCap(&mCaps.maxTextureImageUnits, IMPLEMENTATION_MAX_ACTIVE_TEXTURES / 2);
+
+ mCaps.maxSampleMaskWords = std::min<GLuint>(mCaps.maxSampleMaskWords, MAX_SAMPLE_MASK_WORDS);
- const TextureCapsMap &rendererFormats = mRenderer->getRendererTextureCaps();
- for (TextureCapsMap::const_iterator i = rendererFormats.begin(); i != rendererFormats.end(); i++)
+ // WebGL compatibility
+ mExtensions.webglCompatibility = mWebGLContext;
+ for (const auto &extensionInfo : GetExtensionInfoMap())
{
- GLenum format = i->first;
- TextureCaps formatCaps = i->second;
+ // If this context is for WebGL, disable all enableable extensions
+ if (mWebGLContext && extensionInfo.second.Requestable)
+ {
+ mExtensions.*(extensionInfo.second.ExtensionsMember) = false;
+ }
+ }
+
+ // Generate texture caps
+ updateCaps();
+}
+
+void Context::updateCaps()
+{
+ mCaps.compressedTextureFormats.clear();
+ mTextureCaps.clear();
- const InternalFormat &formatInfo = GetInternalFormatInfo(format);
+ for (GLenum sizedInternalFormat : GetAllSizedInternalFormats())
+ {
+ TextureCaps formatCaps = mImplementation->getNativeTextureCaps().get(sizedInternalFormat);
+ const InternalFormat &formatInfo = GetSizedInternalFormatInfo(sizedInternalFormat);
// Update the format caps based on the client version and extensions.
// Caps are AND'd with the renderer caps because some core formats are still unsupported in
// ES3.
formatCaps.texturable =
- formatCaps.texturable && formatInfo.textureSupport(clientVersion, mExtensions);
+ formatCaps.texturable && formatInfo.textureSupport(getClientVersion(), mExtensions);
formatCaps.renderable =
- formatCaps.renderable && formatInfo.renderSupport(clientVersion, mExtensions);
+ formatCaps.renderable && formatInfo.renderSupport(getClientVersion(), mExtensions);
formatCaps.filterable =
- formatCaps.filterable && formatInfo.filterSupport(clientVersion, mExtensions);
+ formatCaps.filterable && formatInfo.filterSupport(getClientVersion(), mExtensions);
- // OpenGL ES does not support multisampling with integer formats
- if (!formatInfo.renderSupport || formatInfo.componentType == GL_INT || formatInfo.componentType == GL_UNSIGNED_INT)
+ // OpenGL ES does not support multisampling with non-rendererable formats
+ // OpenGL ES 3.0 or prior does not support multisampling with integer formats
+ if (!formatCaps.renderable ||
+ (getClientVersion() < ES_3_1 &&
+ (formatInfo.componentType == GL_INT || formatInfo.componentType == GL_UNSIGNED_INT)))
{
formatCaps.sampleCounts.clear();
}
+ else
+ {
+ // We may have limited the max samples for some required renderbuffer formats due to
+ // non-conformant formats. In this case MAX_SAMPLES needs to be lowered accordingly.
+ GLuint formatMaxSamples = formatCaps.getMaxSamples();
+
+ // GLES 3.0.5 section 4.4.2.2: "Implementations must support creation of renderbuffers
+ // in these required formats with up to the value of MAX_SAMPLES multisamples, with the
+ // exception of signed and unsigned integer formats."
+ if (formatInfo.componentType != GL_INT && formatInfo.componentType != GL_UNSIGNED_INT &&
+ formatInfo.isRequiredRenderbufferFormat(getClientVersion()))
+ {
+ ASSERT(getClientVersion() < ES_3_0 || formatMaxSamples >= 4);
+ mCaps.maxSamples = std::min(mCaps.maxSamples, formatMaxSamples);
+ }
+
+ // Handle GLES 3.1 MAX_*_SAMPLES values similarly to MAX_SAMPLES.
+ if (getClientVersion() >= ES_3_1)
+ {
+ // GLES 3.1 section 9.2.5: "Implementations must support creation of renderbuffers
+ // in these required formats with up to the value of MAX_SAMPLES multisamples, with
+ // the exception that the signed and unsigned integer formats are required only to
+ // support creation of renderbuffers with up to the value of MAX_INTEGER_SAMPLES
+ // multisamples, which must be at least one."
+ if (formatInfo.componentType == GL_INT ||
+ formatInfo.componentType == GL_UNSIGNED_INT)
+ {
+ mCaps.maxIntegerSamples = std::min(mCaps.maxIntegerSamples, formatMaxSamples);
+ }
+
+ // GLES 3.1 section 19.3.1.
+ if (formatCaps.texturable)
+ {
+ if (formatInfo.depthBits > 0)
+ {
+ mCaps.maxDepthTextureSamples =
+ std::min(mCaps.maxDepthTextureSamples, formatMaxSamples);
+ }
+ else if (formatInfo.redBits > 0)
+ {
+ mCaps.maxColorTextureSamples =
+ std::min(mCaps.maxColorTextureSamples, formatMaxSamples);
+ }
+ }
+ }
+ }
if (formatCaps.texturable && formatInfo.compressed)
{
- mCaps.compressedTextureFormats.push_back(format);
+ mCaps.compressedTextureFormats.push_back(sizedInternalFormat);
}
- mTextureCaps.insert(format, formatCaps);
+ mTextureCaps.insert(sizedInternalFormat, formatCaps);
+ }
+
+ // If program binary is disabled, blank out the memory cache pointer.
+ if (!mImplementation->getNativeExtensions().getProgramBinary)
+ {
+ mMemoryProgramCache = nullptr;
}
}
-void Context::syncRendererState()
+void Context::initWorkarounds()
+{
+ // Apply back-end workarounds.
+ mImplementation->applyNativeWorkarounds(&mWorkarounds);
+
+ // Lose the context upon out of memory error if the application is
+ // expecting to watch for those events.
+ mWorkarounds.loseContextOnOutOfMemory = (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT);
+}
+
+Error Context::prepareForDraw()
{
- const State::DirtyBits &dirtyBits = mState.getDirtyBits();
- mRenderer->syncState(mState, dirtyBits);
- mState.clearDirtyBits();
- mState.syncDirtyObjects();
+ syncRendererState();
+
+ if (isRobustResourceInitEnabled())
+ {
+ ANGLE_TRY(mGLState.clearUnclearedActiveTextures(this));
+ ANGLE_TRY(mGLState.getDrawFramebuffer()->ensureDrawAttachmentsInitialized(this));
+ }
+
+ return NoError();
}
-void Context::syncRendererState(const State::DirtyBits &bitMask)
+void Context::syncRendererState()
{
- const State::DirtyBits &dirtyBits = (mState.getDirtyBits() & bitMask);
- mRenderer->syncState(mState, dirtyBits);
- mState.clearDirtyBits(dirtyBits);
+ mGLState.syncDirtyObjects(this);
+ const State::DirtyBits &dirtyBits = mGLState.getDirtyBits();
+ mImplementation->syncState(this, dirtyBits);
+ mGLState.clearDirtyBits();
+}
- // TODO(jmadill): Filter objects by bitMask somehow?
- mState.syncDirtyObjects();
+void Context::syncRendererState(const State::DirtyBits &bitMask,
+ const State::DirtyObjects &objectMask)
+{
+ mGLState.syncDirtyObjects(this, objectMask);
+ const State::DirtyBits &dirtyBits = (mGLState.getDirtyBits() & bitMask);
+ mImplementation->syncState(this, dirtyBits);
+ mGLState.clearDirtyBits(dirtyBits);
}
void Context::blitFramebuffer(GLint srcX0,
@@ -2065,76 +2786,44 @@ void Context::blitFramebuffer(GLint srcX0,
GLbitfield mask,
GLenum filter)
{
- Framebuffer *readFramebuffer = mState.getReadFramebuffer();
- ASSERT(readFramebuffer);
-
- Framebuffer *drawFramebuffer = mState.getDrawFramebuffer();
+ Framebuffer *drawFramebuffer = mGLState.getDrawFramebuffer();
ASSERT(drawFramebuffer);
Rectangle srcArea(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0);
Rectangle dstArea(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0);
- syncRendererState(mState.blitStateBitMask());
+ syncStateForBlit();
- Error error = drawFramebuffer->blit(mState, srcArea, dstArea, mask, filter, readFramebuffer);
- if (error.isError())
- {
- recordError(error);
- return;
- }
+ handleError(drawFramebuffer->blit(this, srcArea, dstArea, mask, filter));
}
void Context::clear(GLbitfield mask)
{
- // Sync the clear state
- syncRendererState(mState.clearStateBitMask());
-
- Error error = mState.getDrawFramebuffer()->clear(mData, mask);
- if (error.isError())
- {
- recordError(error);
- }
+ syncStateForClear();
+ handleError(mGLState.getDrawFramebuffer()->clear(this, mask));
}
void Context::clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values)
{
- // Sync the clear state
- syncRendererState(mState.clearStateBitMask());
-
- Error error = mState.getDrawFramebuffer()->clearBufferfv(mData, buffer, drawbuffer, values);
- if (error.isError())
- {
- recordError(error);
- }
+ syncStateForClear();
+ handleError(mGLState.getDrawFramebuffer()->clearBufferfv(this, buffer, drawbuffer, values));
}
void Context::clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *values)
{
- // Sync the clear state
- syncRendererState(mState.clearStateBitMask());
-
- Error error = mState.getDrawFramebuffer()->clearBufferuiv(mData, buffer, drawbuffer, values);
- if (error.isError())
- {
- recordError(error);
- }
+ syncStateForClear();
+ handleError(mGLState.getDrawFramebuffer()->clearBufferuiv(this, buffer, drawbuffer, values));
}
void Context::clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values)
{
- // Sync the clear state
- syncRendererState(mState.clearStateBitMask());
-
- Error error = mState.getDrawFramebuffer()->clearBufferiv(mData, buffer, drawbuffer, values);
- if (error.isError())
- {
- recordError(error);
- }
+ syncStateForClear();
+ handleError(mGLState.getDrawFramebuffer()->clearBufferiv(this, buffer, drawbuffer, values));
}
void Context::clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
{
- Framebuffer *framebufferObject = mState.getDrawFramebuffer();
+ Framebuffer *framebufferObject = mGLState.getDrawFramebuffer();
ASSERT(framebufferObject);
// If a buffer is not present, the clear has no effect
@@ -2144,14 +2833,8 @@ void Context::clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLin
return;
}
- // Sync the clear state
- syncRendererState(mState.clearStateBitMask());
-
- Error error = framebufferObject->clearBufferfi(mData, buffer, drawbuffer, depth, stencil);
- if (error.isError())
- {
- recordError(error);
- }
+ syncStateForClear();
+ handleError(framebufferObject->clearBufferfi(this, buffer, drawbuffer, depth, stencil));
}
void Context::readPixels(GLint x,
@@ -2160,20 +2843,20 @@ void Context::readPixels(GLint x,
GLsizei height,
GLenum format,
GLenum type,
- GLvoid *pixels)
+ void *pixels)
{
- // Sync pack state
- syncRendererState(mState.packStateBitMask());
+ if (width == 0 || height == 0)
+ {
+ return;
+ }
- Framebuffer *framebufferObject = mState.getReadFramebuffer();
- ASSERT(framebufferObject);
+ syncStateForReadPixels();
+
+ Framebuffer *readFBO = mGLState.getReadFramebuffer();
+ ASSERT(readFBO);
Rectangle area(x, y, width, height);
- Error error = framebufferObject->readPixels(mState, area, format, type, pixels);
- if (error.isError())
- {
- recordError(error);
- }
+ handleError(readFBO->readPixels(this, area, format, type, pixels));
}
void Context::copyTexImage2D(GLenum target,
@@ -2186,18 +2869,14 @@ void Context::copyTexImage2D(GLenum target,
GLint border)
{
// Only sync the read FBO
- mState.syncDirtyObject(GL_READ_FRAMEBUFFER);
+ mGLState.syncDirtyObject(this, GL_READ_FRAMEBUFFER);
Rectangle sourceArea(x, y, width, height);
- const Framebuffer *framebuffer = mState.getReadFramebuffer();
+ Framebuffer *framebuffer = mGLState.getReadFramebuffer();
Texture *texture =
getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
- Error error = texture->copyImage(target, level, sourceArea, internalformat, framebuffer);
- if (error.isError())
- {
- recordError(error);
- }
+ handleError(texture->copyImage(this, target, level, sourceArea, internalformat, framebuffer));
}
void Context::copyTexSubImage2D(GLenum target,
@@ -2209,20 +2888,21 @@ void Context::copyTexSubImage2D(GLenum target,
GLsizei width,
GLsizei height)
{
+ if (width == 0 || height == 0)
+ {
+ return;
+ }
+
// Only sync the read FBO
- mState.syncDirtyObject(GL_READ_FRAMEBUFFER);
+ mGLState.syncDirtyObject(this, GL_READ_FRAMEBUFFER);
Offset destOffset(xoffset, yoffset, 0);
Rectangle sourceArea(x, y, width, height);
- const Framebuffer *framebuffer = mState.getReadFramebuffer();
+ Framebuffer *framebuffer = mGLState.getReadFramebuffer();
Texture *texture =
getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
- Error error = texture->copySubImage(target, level, destOffset, sourceArea, framebuffer);
- if (error.isError())
- {
- recordError(error);
- }
+ handleError(texture->copySubImage(this, target, level, destOffset, sourceArea, framebuffer));
}
void Context::copyTexSubImage3D(GLenum target,
@@ -2235,19 +2915,20 @@ void Context::copyTexSubImage3D(GLenum target,
GLsizei width,
GLsizei height)
{
+ if (width == 0 || height == 0)
+ {
+ return;
+ }
+
// Only sync the read FBO
- mState.syncDirtyObject(GL_READ_FRAMEBUFFER);
+ mGLState.syncDirtyObject(this, GL_READ_FRAMEBUFFER);
Offset destOffset(xoffset, yoffset, zoffset);
Rectangle sourceArea(x, y, width, height);
- const Framebuffer *framebuffer = mState.getReadFramebuffer();
- Texture *texture = getTargetTexture(target);
- Error error = texture->copySubImage(target, level, destOffset, sourceArea, framebuffer);
- if (error.isError())
- {
- recordError(error);
- }
+ Framebuffer *framebuffer = mGLState.getReadFramebuffer();
+ Texture *texture = getTargetTexture(target);
+ handleError(texture->copySubImage(this, target, level, destOffset, sourceArea, framebuffer));
}
void Context::framebufferTexture2D(GLenum target,
@@ -2256,7 +2937,7 @@ void Context::framebufferTexture2D(GLenum target,
GLuint texture,
GLint level)
{
- Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+ Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
ASSERT(framebuffer);
if (texture != 0)
@@ -2269,20 +2950,29 @@ void Context::framebufferTexture2D(GLenum target,
{
index = ImageIndex::Make2D(level);
}
+ else if (textarget == GL_TEXTURE_RECTANGLE_ANGLE)
+ {
+ index = ImageIndex::MakeRectangle(level);
+ }
+ else if (textarget == GL_TEXTURE_2D_MULTISAMPLE)
+ {
+ ASSERT(level == 0);
+ index = ImageIndex::Make2DMultisample();
+ }
else
{
ASSERT(IsCubeMapTextureTarget(textarget));
index = ImageIndex::MakeCube(textarget, level);
}
- framebuffer->setAttachment(GL_TEXTURE, attachment, index, textureObj);
+ framebuffer->setAttachment(this, GL_TEXTURE, attachment, index, textureObj);
}
else
{
- framebuffer->resetAttachment(attachment);
+ framebuffer->resetAttachment(this, attachment);
}
- mState.setObjectDirty(target);
+ mGLState.setObjectDirty(target);
}
void Context::framebufferRenderbuffer(GLenum target,
@@ -2290,21 +2980,22 @@ void Context::framebufferRenderbuffer(GLenum target,
GLenum renderbuffertarget,
GLuint renderbuffer)
{
- Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+ Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
ASSERT(framebuffer);
if (renderbuffer != 0)
{
Renderbuffer *renderbufferObject = getRenderbuffer(renderbuffer);
- framebuffer->setAttachment(GL_RENDERBUFFER, attachment, gl::ImageIndex::MakeInvalid(),
+
+ framebuffer->setAttachment(this, GL_RENDERBUFFER, attachment, gl::ImageIndex::MakeInvalid(),
renderbufferObject);
}
else
{
- framebuffer->resetAttachment(attachment);
+ framebuffer->resetAttachment(this, attachment);
}
- mState.setObjectDirty(target);
+ mGLState.setObjectDirty(target);
}
void Context::framebufferTextureLayer(GLenum target,
@@ -2313,7 +3004,7 @@ void Context::framebufferTextureLayer(GLenum target,
GLint level,
GLint layer)
{
- Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+ Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
ASSERT(framebuffer);
if (texture != 0)
@@ -2332,46 +3023,94 @@ void Context::framebufferTextureLayer(GLenum target,
index = ImageIndex::Make2DArray(level, layer);
}
- framebuffer->setAttachment(GL_TEXTURE, attachment, index, textureObject);
+ framebuffer->setAttachment(this, GL_TEXTURE, attachment, index, textureObject);
+ }
+ else
+ {
+ framebuffer->resetAttachment(this, attachment);
+ }
+
+ mGLState.setObjectDirty(target);
+}
+
+void Context::framebufferTextureMultiviewLayeredANGLE(GLenum target,
+ GLenum attachment,
+ GLuint texture,
+ GLint level,
+ GLint baseViewIndex,
+ GLsizei numViews)
+{
+ Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (texture != 0)
+ {
+ Texture *textureObj = getTexture(texture);
+
+ ImageIndex index = ImageIndex::Make2DArrayRange(level, baseViewIndex, numViews);
+ framebuffer->setAttachmentMultiviewLayered(this, GL_TEXTURE, attachment, index, textureObj,
+ numViews, baseViewIndex);
+ }
+ else
+ {
+ framebuffer->resetAttachment(this, attachment);
+ }
+
+ mGLState.setObjectDirty(target);
+}
+
+void Context::framebufferTextureMultiviewSideBySideANGLE(GLenum target,
+ GLenum attachment,
+ GLuint texture,
+ GLint level,
+ GLsizei numViews,
+ const GLint *viewportOffsets)
+{
+ Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (texture != 0)
+ {
+ Texture *textureObj = getTexture(texture);
+
+ ImageIndex index = ImageIndex::Make2D(level);
+ framebuffer->setAttachmentMultiviewSideBySide(this, GL_TEXTURE, attachment, index,
+ textureObj, numViews, viewportOffsets);
}
else
{
- framebuffer->resetAttachment(attachment);
+ framebuffer->resetAttachment(this, attachment);
}
- mState.setObjectDirty(target);
+ mGLState.setObjectDirty(target);
}
void Context::drawBuffers(GLsizei n, const GLenum *bufs)
{
- Framebuffer *framebuffer = mState.getDrawFramebuffer();
+ Framebuffer *framebuffer = mGLState.getDrawFramebuffer();
ASSERT(framebuffer);
framebuffer->setDrawBuffers(n, bufs);
- mState.setObjectDirty(GL_DRAW_FRAMEBUFFER);
+ mGLState.setObjectDirty(GL_DRAW_FRAMEBUFFER);
}
void Context::readBuffer(GLenum mode)
{
- Framebuffer *readFBO = mState.getReadFramebuffer();
+ Framebuffer *readFBO = mGLState.getReadFramebuffer();
readFBO->setReadBuffer(mode);
- mState.setObjectDirty(GL_READ_FRAMEBUFFER);
+ mGLState.setObjectDirty(GL_READ_FRAMEBUFFER);
}
void Context::discardFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments)
{
// Only sync the FBO
- mState.syncDirtyObject(target);
+ mGLState.syncDirtyObject(this, target);
- Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+ Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
ASSERT(framebuffer);
// The specification isn't clear what should be done when the framebuffer isn't complete.
// We leave it up to the framebuffer implementation to decide what to do.
- Error error = framebuffer->discard(numAttachments, attachments);
- if (error.isError())
- {
- recordError(error);
- }
+ handleError(framebuffer->discard(this, numAttachments, attachments));
}
void Context::invalidateFramebuffer(GLenum target,
@@ -2379,20 +3118,17 @@ void Context::invalidateFramebuffer(GLenum target,
const GLenum *attachments)
{
// Only sync the FBO
- mState.syncDirtyObject(target);
+ mGLState.syncDirtyObject(this, target);
- Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+ Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
ASSERT(framebuffer);
- if (framebuffer->checkStatus(mData) == GL_FRAMEBUFFER_COMPLETE)
+ if (framebuffer->checkStatus(this) != GL_FRAMEBUFFER_COMPLETE)
{
- Error error = framebuffer->invalidate(numAttachments, attachments);
- if (error.isError())
- {
- recordError(error);
- return;
- }
+ return;
}
+
+ handleError(framebuffer->invalidate(this, numAttachments, attachments));
}
void Context::invalidateSubFramebuffer(GLenum target,
@@ -2404,21 +3140,2419 @@ void Context::invalidateSubFramebuffer(GLenum target,
GLsizei height)
{
// Only sync the FBO
- mState.syncDirtyObject(target);
+ mGLState.syncDirtyObject(this, target);
- Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+ Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
ASSERT(framebuffer);
- if (framebuffer->checkStatus(mData) == GL_FRAMEBUFFER_COMPLETE)
+ if (framebuffer->checkStatus(this) != GL_FRAMEBUFFER_COMPLETE)
+ {
+ return;
+ }
+
+ Rectangle area(x, y, width, height);
+ handleError(framebuffer->invalidateSub(this, numAttachments, attachments, area));
+}
+
+void Context::texImage2D(GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ syncStateForTexImage();
+
+ Extents size(width, height, 1);
+ Texture *texture =
+ getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+ handleError(texture->setImage(this, mGLState.getUnpackState(), target, level, internalformat,
+ size, format, type, reinterpret_cast<const uint8_t *>(pixels)));
+}
+
+void Context::texImage3D(GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ syncStateForTexImage();
+
+ Extents size(width, height, depth);
+ Texture *texture = getTargetTexture(target);
+ handleError(texture->setImage(this, mGLState.getUnpackState(), target, level, internalformat,
+ size, format, type, reinterpret_cast<const uint8_t *>(pixels)));
+}
+
+void Context::texSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ // Zero sized uploads are valid but no-ops
+ if (width == 0 || height == 0)
+ {
+ return;
+ }
+
+ syncStateForTexImage();
+
+ Box area(xoffset, yoffset, 0, width, height, 1);
+ Texture *texture =
+ getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+ handleError(texture->setSubImage(this, mGLState.getUnpackState(), target, level, area, format,
+ type, reinterpret_cast<const uint8_t *>(pixels)));
+}
+
+void Context::texSubImage3D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ // Zero sized uploads are valid but no-ops
+ if (width == 0 || height == 0 || depth == 0)
+ {
+ return;
+ }
+
+ syncStateForTexImage();
+
+ Box area(xoffset, yoffset, zoffset, width, height, depth);
+ Texture *texture = getTargetTexture(target);
+ handleError(texture->setSubImage(this, mGLState.getUnpackState(), target, level, area, format,
+ type, reinterpret_cast<const uint8_t *>(pixels)));
+}
+
+void Context::compressedTexImage2D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ const void *data)
+{
+ syncStateForTexImage();
+
+ Extents size(width, height, 1);
+ Texture *texture =
+ getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+ handleError(texture->setCompressedImage(this, mGLState.getUnpackState(), target, level,
+ internalformat, size, imageSize,
+ reinterpret_cast<const uint8_t *>(data)));
+}
+
+void Context::compressedTexImage3D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ const void *data)
+{
+ syncStateForTexImage();
+
+ Extents size(width, height, depth);
+ Texture *texture = getTargetTexture(target);
+ handleError(texture->setCompressedImage(this, mGLState.getUnpackState(), target, level,
+ internalformat, size, imageSize,
+ reinterpret_cast<const uint8_t *>(data)));
+}
+
+void Context::compressedTexSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data)
+{
+ syncStateForTexImage();
+
+ Box area(xoffset, yoffset, 0, width, height, 1);
+ Texture *texture =
+ getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+ handleError(texture->setCompressedSubImage(this, mGLState.getUnpackState(), target, level, area,
+ format, imageSize,
+ reinterpret_cast<const uint8_t *>(data)));
+}
+
+void Context::compressedTexSubImage3D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data)
+{
+ // Zero sized uploads are valid but no-ops
+ if (width == 0 || height == 0)
+ {
+ return;
+ }
+
+ syncStateForTexImage();
+
+ Box area(xoffset, yoffset, zoffset, width, height, depth);
+ Texture *texture = getTargetTexture(target);
+ handleError(texture->setCompressedSubImage(this, mGLState.getUnpackState(), target, level, area,
+ format, imageSize,
+ reinterpret_cast<const uint8_t *>(data)));
+}
+
+void Context::generateMipmap(GLenum target)
+{
+ Texture *texture = getTargetTexture(target);
+ handleError(texture->generateMipmap(this));
+}
+
+void Context::copyTextureCHROMIUM(GLuint sourceId,
+ GLint sourceLevel,
+ GLenum destTarget,
+ GLuint destId,
+ GLint destLevel,
+ GLint internalFormat,
+ GLenum destType,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha)
+{
+ syncStateForTexImage();
+
+ gl::Texture *sourceTexture = getTexture(sourceId);
+ gl::Texture *destTexture = getTexture(destId);
+ handleError(destTexture->copyTexture(this, destTarget, destLevel, internalFormat, destType,
+ sourceLevel, ConvertToBool(unpackFlipY),
+ ConvertToBool(unpackPremultiplyAlpha),
+ ConvertToBool(unpackUnmultiplyAlpha), sourceTexture));
+}
+
+void Context::copySubTextureCHROMIUM(GLuint sourceId,
+ GLint sourceLevel,
+ GLenum destTarget,
+ GLuint destId,
+ GLint destLevel,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha)
+{
+ // Zero sized copies are valid but no-ops
+ if (width == 0 || height == 0)
{
- Rectangle area(x, y, width, height);
- Error error = framebuffer->invalidateSub(numAttachments, attachments, area);
- if (error.isError())
+ return;
+ }
+
+ syncStateForTexImage();
+
+ gl::Texture *sourceTexture = getTexture(sourceId);
+ gl::Texture *destTexture = getTexture(destId);
+ Offset offset(xoffset, yoffset, 0);
+ Rectangle area(x, y, width, height);
+ handleError(destTexture->copySubTexture(this, destTarget, destLevel, offset, sourceLevel, area,
+ ConvertToBool(unpackFlipY),
+ ConvertToBool(unpackPremultiplyAlpha),
+ ConvertToBool(unpackUnmultiplyAlpha), sourceTexture));
+}
+
+void Context::compressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId)
+{
+ syncStateForTexImage();
+
+ gl::Texture *sourceTexture = getTexture(sourceId);
+ gl::Texture *destTexture = getTexture(destId);
+ handleError(destTexture->copyCompressedTexture(this, sourceTexture));
+}
+
+void Context::getBufferPointerv(BufferBinding target, GLenum pname, void **params)
+{
+ Buffer *buffer = mGLState.getTargetBuffer(target);
+ ASSERT(buffer);
+
+ QueryBufferPointerv(buffer, pname, params);
+}
+
+void *Context::mapBuffer(BufferBinding target, GLenum access)
+{
+ Buffer *buffer = mGLState.getTargetBuffer(target);
+ ASSERT(buffer);
+
+ Error error = buffer->map(this, access);
+ if (error.isError())
+ {
+ handleError(error);
+ return nullptr;
+ }
+
+ return buffer->getMapPointer();
+}
+
+GLboolean Context::unmapBuffer(BufferBinding target)
+{
+ Buffer *buffer = mGLState.getTargetBuffer(target);
+ ASSERT(buffer);
+
+ GLboolean result;
+ Error error = buffer->unmap(this, &result);
+ if (error.isError())
+ {
+ handleError(error);
+ return GL_FALSE;
+ }
+
+ return result;
+}
+
+void *Context::mapBufferRange(BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access)
+{
+ Buffer *buffer = mGLState.getTargetBuffer(target);
+ ASSERT(buffer);
+
+ Error error = buffer->mapRange(this, offset, length, access);
+ if (error.isError())
+ {
+ handleError(error);
+ return nullptr;
+ }
+
+ return buffer->getMapPointer();
+}
+
+void Context::flushMappedBufferRange(BufferBinding /*target*/,
+ GLintptr /*offset*/,
+ GLsizeiptr /*length*/)
+{
+ // We do not currently support a non-trivial implementation of FlushMappedBufferRange
+}
+
+void Context::syncStateForReadPixels()
+{
+ syncRendererState(mReadPixelsDirtyBits, mReadPixelsDirtyObjects);
+}
+
+void Context::syncStateForTexImage()
+{
+ syncRendererState(mTexImageDirtyBits, mTexImageDirtyObjects);
+}
+
+void Context::syncStateForClear()
+{
+ syncRendererState(mClearDirtyBits, mClearDirtyObjects);
+}
+
+void Context::syncStateForBlit()
+{
+ syncRendererState(mBlitDirtyBits, mBlitDirtyObjects);
+}
+
+void Context::activeShaderProgram(GLuint pipeline, GLuint program)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::activeTexture(GLenum texture)
+{
+ mGLState.setActiveSampler(texture - GL_TEXTURE0);
+}
+
+void Context::blendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+{
+ mGLState.setBlendColor(clamp01(red), clamp01(green), clamp01(blue), clamp01(alpha));
+}
+
+void Context::blendEquation(GLenum mode)
+{
+ mGLState.setBlendEquation(mode, mode);
+}
+
+void Context::blendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
+{
+ mGLState.setBlendEquation(modeRGB, modeAlpha);
+}
+
+void Context::blendFunc(GLenum sfactor, GLenum dfactor)
+{
+ mGLState.setBlendFactors(sfactor, dfactor, sfactor, dfactor);
+}
+
+void Context::blendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+{
+ mGLState.setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+
+void Context::clearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+{
+ mGLState.setColorClearValue(red, green, blue, alpha);
+}
+
+void Context::clearDepthf(GLfloat depth)
+{
+ mGLState.setDepthClearValue(depth);
+}
+
+void Context::clearStencil(GLint s)
+{
+ mGLState.setStencilClearValue(s);
+}
+
+void Context::colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+{
+ mGLState.setColorMask(ConvertToBool(red), ConvertToBool(green), ConvertToBool(blue),
+ ConvertToBool(alpha));
+}
+
+void Context::cullFace(CullFaceMode mode)
+{
+ mGLState.setCullMode(mode);
+}
+
+void Context::depthFunc(GLenum func)
+{
+ mGLState.setDepthFunc(func);
+}
+
+void Context::depthMask(GLboolean flag)
+{
+ mGLState.setDepthMask(ConvertToBool(flag));
+}
+
+void Context::depthRangef(GLfloat zNear, GLfloat zFar)
+{
+ mGLState.setDepthRange(zNear, zFar);
+}
+
+void Context::disable(GLenum cap)
+{
+ mGLState.setEnableFeature(cap, false);
+}
+
+void Context::disableVertexAttribArray(GLuint index)
+{
+ mGLState.setEnableVertexAttribArray(index, false);
+}
+
+void Context::enable(GLenum cap)
+{
+ mGLState.setEnableFeature(cap, true);
+}
+
+void Context::enableVertexAttribArray(GLuint index)
+{
+ mGLState.setEnableVertexAttribArray(index, true);
+}
+
+void Context::frontFace(GLenum mode)
+{
+ mGLState.setFrontFace(mode);
+}
+
+void Context::hint(GLenum target, GLenum mode)
+{
+ switch (target)
+ {
+ case GL_GENERATE_MIPMAP_HINT:
+ mGLState.setGenerateMipmapHint(mode);
+ break;
+
+ case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
+ mGLState.setFragmentShaderDerivativeHint(mode);
+ break;
+
+ default:
+ UNREACHABLE();
+ return;
+ }
+}
+
+void Context::lineWidth(GLfloat width)
+{
+ mGLState.setLineWidth(width);
+}
+
+void Context::pixelStorei(GLenum pname, GLint param)
+{
+ switch (pname)
+ {
+ case GL_UNPACK_ALIGNMENT:
+ mGLState.setUnpackAlignment(param);
+ break;
+
+ case GL_PACK_ALIGNMENT:
+ mGLState.setPackAlignment(param);
+ break;
+
+ case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
+ mGLState.setPackReverseRowOrder(param != 0);
+ break;
+
+ case GL_UNPACK_ROW_LENGTH:
+ ASSERT((getClientMajorVersion() >= 3) || getExtensions().unpackSubimage);
+ mGLState.setUnpackRowLength(param);
+ break;
+
+ case GL_UNPACK_IMAGE_HEIGHT:
+ ASSERT(getClientMajorVersion() >= 3);
+ mGLState.setUnpackImageHeight(param);
+ break;
+
+ case GL_UNPACK_SKIP_IMAGES:
+ ASSERT(getClientMajorVersion() >= 3);
+ mGLState.setUnpackSkipImages(param);
+ break;
+
+ case GL_UNPACK_SKIP_ROWS:
+ ASSERT((getClientMajorVersion() >= 3) || getExtensions().unpackSubimage);
+ mGLState.setUnpackSkipRows(param);
+ break;
+
+ case GL_UNPACK_SKIP_PIXELS:
+ ASSERT((getClientMajorVersion() >= 3) || getExtensions().unpackSubimage);
+ mGLState.setUnpackSkipPixels(param);
+ break;
+
+ case GL_PACK_ROW_LENGTH:
+ ASSERT((getClientMajorVersion() >= 3) || getExtensions().packSubimage);
+ mGLState.setPackRowLength(param);
+ break;
+
+ case GL_PACK_SKIP_ROWS:
+ ASSERT((getClientMajorVersion() >= 3) || getExtensions().packSubimage);
+ mGLState.setPackSkipRows(param);
+ break;
+
+ case GL_PACK_SKIP_PIXELS:
+ ASSERT((getClientMajorVersion() >= 3) || getExtensions().packSubimage);
+ mGLState.setPackSkipPixels(param);
+ break;
+
+ default:
+ UNREACHABLE();
+ return;
+ }
+}
+
+void Context::polygonOffset(GLfloat factor, GLfloat units)
+{
+ mGLState.setPolygonOffsetParams(factor, units);
+}
+
+void Context::sampleCoverage(GLfloat value, GLboolean invert)
+{
+ mGLState.setSampleCoverageParams(clamp01(value), ConvertToBool(invert));
+}
+
+void Context::sampleMaski(GLuint maskNumber, GLbitfield mask)
+{
+ mGLState.setSampleMaskParams(maskNumber, mask);
+}
+
+void Context::scissor(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ mGLState.setScissorParams(x, y, width, height);
+}
+
+void Context::stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
+{
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
+ {
+ mGLState.setStencilParams(func, ref, mask);
+ }
+
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+ {
+ mGLState.setStencilBackParams(func, ref, mask);
+ }
+}
+
+void Context::stencilMaskSeparate(GLenum face, GLuint mask)
+{
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
+ {
+ mGLState.setStencilWritemask(mask);
+ }
+
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+ {
+ mGLState.setStencilBackWritemask(mask);
+ }
+}
+
+void Context::stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+{
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
+ {
+ mGLState.setStencilOperations(fail, zfail, zpass);
+ }
+
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+ {
+ mGLState.setStencilBackOperations(fail, zfail, zpass);
+ }
+}
+
+void Context::vertexAttrib1f(GLuint index, GLfloat x)
+{
+ GLfloat vals[4] = {x, 0, 0, 1};
+ mGLState.setVertexAttribf(index, vals);
+}
+
+void Context::vertexAttrib1fv(GLuint index, const GLfloat *values)
+{
+ GLfloat vals[4] = {values[0], 0, 0, 1};
+ mGLState.setVertexAttribf(index, vals);
+}
+
+void Context::vertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
+{
+ GLfloat vals[4] = {x, y, 0, 1};
+ mGLState.setVertexAttribf(index, vals);
+}
+
+void Context::vertexAttrib2fv(GLuint index, const GLfloat *values)
+{
+ GLfloat vals[4] = {values[0], values[1], 0, 1};
+ mGLState.setVertexAttribf(index, vals);
+}
+
+void Context::vertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
+{
+ GLfloat vals[4] = {x, y, z, 1};
+ mGLState.setVertexAttribf(index, vals);
+}
+
+void Context::vertexAttrib3fv(GLuint index, const GLfloat *values)
+{
+ GLfloat vals[4] = {values[0], values[1], values[2], 1};
+ mGLState.setVertexAttribf(index, vals);
+}
+
+void Context::vertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GLfloat vals[4] = {x, y, z, w};
+ mGLState.setVertexAttribf(index, vals);
+}
+
+void Context::vertexAttrib4fv(GLuint index, const GLfloat *values)
+{
+ mGLState.setVertexAttribf(index, values);
+}
+
+void Context::vertexAttribPointer(GLuint index,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLsizei stride,
+ const void *ptr)
+{
+ mGLState.setVertexAttribPointer(this, index, mGLState.getTargetBuffer(BufferBinding::Array),
+ size, type, ConvertToBool(normalized), false, stride, ptr);
+}
+
+void Context::vertexAttribFormat(GLuint attribIndex,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLuint relativeOffset)
+{
+ mGLState.setVertexAttribFormat(attribIndex, size, type, ConvertToBool(normalized), false,
+ relativeOffset);
+}
+
+void Context::vertexAttribIFormat(GLuint attribIndex,
+ GLint size,
+ GLenum type,
+ GLuint relativeOffset)
+{
+ mGLState.setVertexAttribFormat(attribIndex, size, type, false, true, relativeOffset);
+}
+
+void Context::vertexAttribBinding(GLuint attribIndex, GLuint bindingIndex)
+{
+ mGLState.setVertexAttribBinding(this, attribIndex, bindingIndex);
+}
+
+void Context::vertexBindingDivisor(GLuint bindingIndex, GLuint divisor)
+{
+ mGLState.setVertexBindingDivisor(bindingIndex, divisor);
+}
+
+void Context::viewport(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ mGLState.setViewportParams(x, y, width, height);
+}
+
+void Context::vertexAttribIPointer(GLuint index,
+ GLint size,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer)
+{
+ mGLState.setVertexAttribPointer(this, index, mGLState.getTargetBuffer(BufferBinding::Array),
+ size, type, false, true, stride, pointer);
+}
+
+void Context::vertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
+{
+ GLint vals[4] = {x, y, z, w};
+ mGLState.setVertexAttribi(index, vals);
+}
+
+void Context::vertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
+{
+ GLuint vals[4] = {x, y, z, w};
+ mGLState.setVertexAttribu(index, vals);
+}
+
+void Context::vertexAttribI4iv(GLuint index, const GLint *v)
+{
+ mGLState.setVertexAttribi(index, v);
+}
+
+void Context::vertexAttribI4uiv(GLuint index, const GLuint *v)
+{
+ mGLState.setVertexAttribu(index, v);
+}
+
+void Context::getVertexAttribiv(GLuint index, GLenum pname, GLint *params)
+{
+ const VertexAttribCurrentValueData &currentValues =
+ getGLState().getVertexAttribCurrentValue(index);
+ const VertexArray *vao = getGLState().getVertexArray();
+ QueryVertexAttribiv(vao->getVertexAttribute(index), vao->getBindingFromAttribIndex(index),
+ currentValues, pname, params);
+}
+
+void Context::getVertexAttribfv(GLuint index, GLenum pname, GLfloat *params)
+{
+ const VertexAttribCurrentValueData &currentValues =
+ getGLState().getVertexAttribCurrentValue(index);
+ const VertexArray *vao = getGLState().getVertexArray();
+ QueryVertexAttribfv(vao->getVertexAttribute(index), vao->getBindingFromAttribIndex(index),
+ currentValues, pname, params);
+}
+
+void Context::getVertexAttribIiv(GLuint index, GLenum pname, GLint *params)
+{
+ const VertexAttribCurrentValueData &currentValues =
+ getGLState().getVertexAttribCurrentValue(index);
+ const VertexArray *vao = getGLState().getVertexArray();
+ QueryVertexAttribIiv(vao->getVertexAttribute(index), vao->getBindingFromAttribIndex(index),
+ currentValues, pname, params);
+}
+
+void Context::getVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params)
+{
+ const VertexAttribCurrentValueData &currentValues =
+ getGLState().getVertexAttribCurrentValue(index);
+ const VertexArray *vao = getGLState().getVertexArray();
+ QueryVertexAttribIuiv(vao->getVertexAttribute(index), vao->getBindingFromAttribIndex(index),
+ currentValues, pname, params);
+}
+
+void Context::getVertexAttribPointerv(GLuint index, GLenum pname, void **pointer)
+{
+ const VertexAttribute &attrib = getGLState().getVertexArray()->getVertexAttribute(index);
+ QueryVertexAttribPointerv(attrib, pname, pointer);
+}
+
+void Context::debugMessageControl(GLenum source,
+ GLenum type,
+ GLenum severity,
+ GLsizei count,
+ const GLuint *ids,
+ GLboolean enabled)
+{
+ std::vector<GLuint> idVector(ids, ids + count);
+ mGLState.getDebug().setMessageControl(source, type, severity, std::move(idVector),
+ ConvertToBool(enabled));
+}
+
+void Context::debugMessageInsert(GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar *buf)
+{
+ std::string msg(buf, (length > 0) ? static_cast<size_t>(length) : strlen(buf));
+ mGLState.getDebug().insertMessage(source, type, id, severity, std::move(msg));
+}
+
+void Context::debugMessageCallback(GLDEBUGPROCKHR callback, const void *userParam)
+{
+ mGLState.getDebug().setCallback(callback, userParam);
+}
+
+GLuint Context::getDebugMessageLog(GLuint count,
+ GLsizei bufSize,
+ GLenum *sources,
+ GLenum *types,
+ GLuint *ids,
+ GLenum *severities,
+ GLsizei *lengths,
+ GLchar *messageLog)
+{
+ return static_cast<GLuint>(mGLState.getDebug().getMessages(count, bufSize, sources, types, ids,
+ severities, lengths, messageLog));
+}
+
+void Context::pushDebugGroup(GLenum source, GLuint id, GLsizei length, const GLchar *message)
+{
+ std::string msg(message, (length > 0) ? static_cast<size_t>(length) : strlen(message));
+ mGLState.getDebug().pushGroup(source, id, std::move(msg));
+ mImplementation->pushDebugGroup(source, id, length, message);
+}
+
+void Context::popDebugGroup()
+{
+ mGLState.getDebug().popGroup();
+ mImplementation->popDebugGroup();
+}
+
+void Context::bufferData(BufferBinding target, GLsizeiptr size, const void *data, BufferUsage usage)
+{
+ Buffer *buffer = mGLState.getTargetBuffer(target);
+ ASSERT(buffer);
+ handleError(buffer->bufferData(this, target, data, size, usage));
+}
+
+void Context::bufferSubData(BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr size,
+ const void *data)
+{
+ if (data == nullptr)
+ {
+ return;
+ }
+
+ Buffer *buffer = mGLState.getTargetBuffer(target);
+ ASSERT(buffer);
+ handleError(buffer->bufferSubData(this, target, data, size, offset));
+}
+
+void Context::attachShader(GLuint program, GLuint shader)
+{
+ Program *programObject = mState.mShaderPrograms->getProgram(program);
+ Shader *shaderObject = mState.mShaderPrograms->getShader(shader);
+ ASSERT(programObject && shaderObject);
+ programObject->attachShader(shaderObject);
+}
+
+const Workarounds &Context::getWorkarounds() const
+{
+ return mWorkarounds;
+}
+
+void Context::copyBufferSubData(BufferBinding readTarget,
+ BufferBinding writeTarget,
+ GLintptr readOffset,
+ GLintptr writeOffset,
+ GLsizeiptr size)
+{
+ // if size is zero, the copy is a successful no-op
+ if (size == 0)
+ {
+ return;
+ }
+
+ // TODO(jmadill): cache these.
+ Buffer *readBuffer = mGLState.getTargetBuffer(readTarget);
+ Buffer *writeBuffer = mGLState.getTargetBuffer(writeTarget);
+
+ handleError(writeBuffer->copyBufferSubData(this, readBuffer, readOffset, writeOffset, size));
+}
+
+void Context::bindAttribLocation(GLuint program, GLuint index, const GLchar *name)
+{
+ Program *programObject = getProgram(program);
+ // TODO(jmadill): Re-use this from the validation if possible.
+ ASSERT(programObject);
+ programObject->bindAttributeLocation(index, name);
+}
+
+void Context::bindBuffer(BufferBinding target, GLuint buffer)
+{
+ Buffer *bufferObject = mState.mBuffers->checkBufferAllocation(mImplementation.get(), buffer);
+ mGLState.setBufferBinding(this, target, bufferObject);
+}
+
+void Context::bindBufferBase(BufferBinding target, GLuint index, GLuint buffer)
+{
+ bindBufferRange(target, index, buffer, 0, 0);
+}
+
+void Context::bindBufferRange(BufferBinding target,
+ GLuint index,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizeiptr size)
+{
+ Buffer *bufferObject = mState.mBuffers->checkBufferAllocation(mImplementation.get(), buffer);
+ mGLState.setIndexedBufferBinding(this, target, index, bufferObject, offset, size);
+}
+
+void Context::bindFramebuffer(GLenum target, GLuint framebuffer)
+{
+ if (target == GL_READ_FRAMEBUFFER || target == GL_FRAMEBUFFER)
+ {
+ bindReadFramebuffer(framebuffer);
+ }
+
+ if (target == GL_DRAW_FRAMEBUFFER || target == GL_FRAMEBUFFER)
+ {
+ bindDrawFramebuffer(framebuffer);
+ }
+}
+
+void Context::bindRenderbuffer(GLenum target, GLuint renderbuffer)
+{
+ ASSERT(target == GL_RENDERBUFFER);
+ Renderbuffer *object =
+ mState.mRenderbuffers->checkRenderbufferAllocation(mImplementation.get(), renderbuffer);
+ mGLState.setRenderbufferBinding(this, object);
+}
+
+void Context::texStorage2DMultisample(GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedsamplelocations)
+{
+ Extents size(width, height, 1);
+ Texture *texture = getTargetTexture(target);
+ handleError(texture->setStorageMultisample(this, target, samples, internalformat, size,
+ ConvertToBool(fixedsamplelocations)));
+}
+
+void Context::getMultisamplefv(GLenum pname, GLuint index, GLfloat *val)
+{
+ // According to spec 3.1 Table 20.49: Framebuffer Dependent Values,
+ // the sample position should be queried by DRAW_FRAMEBUFFER.
+ mGLState.syncDirtyObject(this, GL_DRAW_FRAMEBUFFER);
+ const Framebuffer *framebuffer = mGLState.getDrawFramebuffer();
+
+ switch (pname)
+ {
+ case GL_SAMPLE_POSITION:
+ handleError(framebuffer->getSamplePosition(index, val));
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
+void Context::renderbufferStorage(GLenum target,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
+ GLenum convertedInternalFormat = getConvertedRenderbufferFormat(internalformat);
+
+ Renderbuffer *renderbuffer = mGLState.getCurrentRenderbuffer();
+ handleError(renderbuffer->setStorage(this, convertedInternalFormat, width, height));
+}
+
+void Context::renderbufferStorageMultisample(GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
+ GLenum convertedInternalFormat = getConvertedRenderbufferFormat(internalformat);
+
+ Renderbuffer *renderbuffer = mGLState.getCurrentRenderbuffer();
+ handleError(
+ renderbuffer->setStorageMultisample(this, samples, convertedInternalFormat, width, height));
+}
+
+void Context::getSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values)
+{
+ const Sync *syncObject = getSync(sync);
+ handleError(QuerySynciv(syncObject, pname, bufSize, length, values));
+}
+
+void Context::getFramebufferParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+ Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
+ QueryFramebufferParameteriv(framebuffer, pname, params);
+}
+
+void Context::framebufferParameteri(GLenum target, GLenum pname, GLint param)
+{
+ Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
+ SetFramebufferParameteri(framebuffer, pname, param);
+}
+
+Error Context::getScratchBuffer(size_t requstedSizeBytes,
+ angle::MemoryBuffer **scratchBufferOut) const
+{
+ if (!mScratchBuffer.get(requstedSizeBytes, scratchBufferOut))
+ {
+ return OutOfMemory() << "Failed to allocate internal buffer.";
+ }
+ return NoError();
+}
+
+Error Context::getZeroFilledBuffer(size_t requstedSizeBytes,
+ angle::MemoryBuffer **zeroBufferOut) const
+{
+ if (!mZeroFilledBuffer.getInitialized(requstedSizeBytes, zeroBufferOut, 0))
+ {
+ return OutOfMemory() << "Failed to allocate internal buffer.";
+ }
+ return NoError();
+}
+
+void Context::dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ)
+{
+ if (numGroupsX == 0u || numGroupsY == 0u || numGroupsZ == 0u)
+ {
+ return;
+ }
+
+ // TODO(jmadill): Dirty bits for compute.
+ if (isRobustResourceInitEnabled())
+ {
+ ANGLE_CONTEXT_TRY(mGLState.clearUnclearedActiveTextures(this));
+ }
+
+ handleError(mImplementation->dispatchCompute(this, numGroupsX, numGroupsY, numGroupsZ));
+}
+
+void Context::dispatchComputeIndirect(GLintptr indirect)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texStorage2D(GLenum target,
+ GLsizei levels,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height)
+{
+ Extents size(width, height, 1);
+ Texture *texture = getTargetTexture(target);
+ handleError(texture->setStorage(this, target, levels, internalFormat, size));
+}
+
+void Context::texStorage3D(GLenum target,
+ GLsizei levels,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth)
+{
+ Extents size(width, height, depth);
+ Texture *texture = getTargetTexture(target);
+ handleError(texture->setStorage(this, target, levels, internalFormat, size));
+}
+
+void Context::memoryBarrier(GLbitfield barriers)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::memoryBarrierByRegion(GLbitfield barriers)
+{
+ UNIMPLEMENTED();
+}
+
+GLenum Context::checkFramebufferStatus(GLenum target)
+{
+ Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ return framebuffer->checkStatus(this);
+}
+
+void Context::compileShader(GLuint shader)
+{
+ Shader *shaderObject = GetValidShader(this, shader);
+ if (!shaderObject)
+ {
+ return;
+ }
+ shaderObject->compile(this);
+}
+
+void Context::deleteBuffers(GLsizei n, const GLuint *buffers)
+{
+ for (int i = 0; i < n; i++)
+ {
+ deleteBuffer(buffers[i]);
+ }
+}
+
+void Context::deleteFramebuffers(GLsizei n, const GLuint *framebuffers)
+{
+ for (int i = 0; i < n; i++)
+ {
+ if (framebuffers[i] != 0)
+ {
+ deleteFramebuffer(framebuffers[i]);
+ }
+ }
+}
+
+void Context::deleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
+{
+ for (int i = 0; i < n; i++)
+ {
+ deleteRenderbuffer(renderbuffers[i]);
+ }
+}
+
+void Context::deleteTextures(GLsizei n, const GLuint *textures)
+{
+ for (int i = 0; i < n; i++)
+ {
+ if (textures[i] != 0)
{
- recordError(error);
+ deleteTexture(textures[i]);
+ }
+ }
+}
+
+void Context::detachShader(GLuint program, GLuint shader)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+
+ Shader *shaderObject = getShader(shader);
+ ASSERT(shaderObject);
+
+ programObject->detachShader(this, shaderObject);
+}
+
+void Context::genBuffers(GLsizei n, GLuint *buffers)
+{
+ for (int i = 0; i < n; i++)
+ {
+ buffers[i] = createBuffer();
+ }
+}
+
+void Context::genFramebuffers(GLsizei n, GLuint *framebuffers)
+{
+ for (int i = 0; i < n; i++)
+ {
+ framebuffers[i] = createFramebuffer();
+ }
+}
+
+void Context::genRenderbuffers(GLsizei n, GLuint *renderbuffers)
+{
+ for (int i = 0; i < n; i++)
+ {
+ renderbuffers[i] = createRenderbuffer();
+ }
+}
+
+void Context::genTextures(GLsizei n, GLuint *textures)
+{
+ for (int i = 0; i < n; i++)
+ {
+ textures[i] = createTexture();
+ }
+}
+
+void Context::getActiveAttrib(GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->getActiveAttribute(index, bufsize, length, size, type, name);
+}
+
+void Context::getActiveUniform(GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->getActiveUniform(index, bufsize, length, size, type, name);
+}
+
+void Context::getAttachedShaders(GLuint program, GLsizei maxcount, GLsizei *count, GLuint *shaders)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->getAttachedShaders(maxcount, count, shaders);
+}
+
+GLint Context::getAttribLocation(GLuint program, const GLchar *name)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ return programObject->getAttributeLocation(name);
+}
+
+void Context::getBooleanv(GLenum pname, GLboolean *params)
+{
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ getQueryParameterInfo(pname, &nativeType, &numParams);
+
+ if (nativeType == GL_BOOL)
+ {
+ getBooleanvImpl(pname, params);
+ }
+ else
+ {
+ CastStateValues(this, nativeType, pname, numParams, params);
+ }
+}
+
+void Context::getFloatv(GLenum pname, GLfloat *params)
+{
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ getQueryParameterInfo(pname, &nativeType, &numParams);
+
+ if (nativeType == GL_FLOAT)
+ {
+ getFloatvImpl(pname, params);
+ }
+ else
+ {
+ CastStateValues(this, nativeType, pname, numParams, params);
+ }
+}
+
+void Context::getIntegerv(GLenum pname, GLint *params)
+{
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ getQueryParameterInfo(pname, &nativeType, &numParams);
+
+ if (nativeType == GL_INT)
+ {
+ getIntegervImpl(pname, params);
+ }
+ else
+ {
+ CastStateValues(this, nativeType, pname, numParams, params);
+ }
+}
+
+void Context::getProgramiv(GLuint program, GLenum pname, GLint *params)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ QueryProgramiv(this, programObject, pname, params);
+}
+
+void Context::getProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei *length, GLchar *infolog)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->getInfoLog(bufsize, length, infolog);
+}
+
+void Context::getProgramPipelineInfoLog(GLuint pipeline,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *infoLog)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getShaderiv(GLuint shader, GLenum pname, GLint *params)
+{
+ Shader *shaderObject = getShader(shader);
+ ASSERT(shaderObject);
+ QueryShaderiv(this, shaderObject, pname, params);
+}
+
+void Context::getShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *infolog)
+{
+ Shader *shaderObject = getShader(shader);
+ ASSERT(shaderObject);
+ shaderObject->getInfoLog(this, bufsize, length, infolog);
+}
+
+void Context::getShaderPrecisionFormat(GLenum shadertype,
+ GLenum precisiontype,
+ GLint *range,
+ GLint *precision)
+{
+ // TODO(jmadill): Compute shaders.
+
+ switch (shadertype)
+ {
+ case GL_VERTEX_SHADER:
+ switch (precisiontype)
+ {
+ case GL_LOW_FLOAT:
+ mCaps.vertexLowpFloat.get(range, precision);
+ break;
+ case GL_MEDIUM_FLOAT:
+ mCaps.vertexMediumpFloat.get(range, precision);
+ break;
+ case GL_HIGH_FLOAT:
+ mCaps.vertexHighpFloat.get(range, precision);
+ break;
+
+ case GL_LOW_INT:
+ mCaps.vertexLowpInt.get(range, precision);
+ break;
+ case GL_MEDIUM_INT:
+ mCaps.vertexMediumpInt.get(range, precision);
+ break;
+ case GL_HIGH_INT:
+ mCaps.vertexHighpInt.get(range, precision);
+ break;
+
+ default:
+ UNREACHABLE();
+ return;
+ }
+ break;
+
+ case GL_FRAGMENT_SHADER:
+ switch (precisiontype)
+ {
+ case GL_LOW_FLOAT:
+ mCaps.fragmentLowpFloat.get(range, precision);
+ break;
+ case GL_MEDIUM_FLOAT:
+ mCaps.fragmentMediumpFloat.get(range, precision);
+ break;
+ case GL_HIGH_FLOAT:
+ mCaps.fragmentHighpFloat.get(range, precision);
+ break;
+
+ case GL_LOW_INT:
+ mCaps.fragmentLowpInt.get(range, precision);
+ break;
+ case GL_MEDIUM_INT:
+ mCaps.fragmentMediumpInt.get(range, precision);
+ break;
+ case GL_HIGH_INT:
+ mCaps.fragmentHighpInt.get(range, precision);
+ break;
+
+ default:
+ UNREACHABLE();
+ return;
+ }
+ break;
+
+ default:
+ UNREACHABLE();
return;
+ }
+}
+
+void Context::getShaderSource(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source)
+{
+ Shader *shaderObject = getShader(shader);
+ ASSERT(shaderObject);
+ shaderObject->getSource(bufsize, length, source);
+}
+
+void Context::getUniformfv(GLuint program, GLint location, GLfloat *params)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->getUniformfv(this, location, params);
+}
+
+void Context::getUniformiv(GLuint program, GLint location, GLint *params)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->getUniformiv(this, location, params);
+}
+
+GLint Context::getUniformLocation(GLuint program, const GLchar *name)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ return programObject->getUniformLocation(name);
+}
+
+GLboolean Context::isBuffer(GLuint buffer)
+{
+ if (buffer == 0)
+ {
+ return GL_FALSE;
+ }
+
+ return (getBuffer(buffer) ? GL_TRUE : GL_FALSE);
+}
+
+GLboolean Context::isEnabled(GLenum cap)
+{
+ return mGLState.getEnableFeature(cap);
+}
+
+GLboolean Context::isFramebuffer(GLuint framebuffer)
+{
+ if (framebuffer == 0)
+ {
+ return GL_FALSE;
+ }
+
+ return (getFramebuffer(framebuffer) ? GL_TRUE : GL_FALSE);
+}
+
+GLboolean Context::isProgram(GLuint program)
+{
+ if (program == 0)
+ {
+ return GL_FALSE;
+ }
+
+ return (getProgram(program) ? GL_TRUE : GL_FALSE);
+}
+
+GLboolean Context::isRenderbuffer(GLuint renderbuffer)
+{
+ if (renderbuffer == 0)
+ {
+ return GL_FALSE;
+ }
+
+ return (getRenderbuffer(renderbuffer) ? GL_TRUE : GL_FALSE);
+}
+
+GLboolean Context::isShader(GLuint shader)
+{
+ if (shader == 0)
+ {
+ return GL_FALSE;
+ }
+
+ return (getShader(shader) ? GL_TRUE : GL_FALSE);
+}
+
+GLboolean Context::isTexture(GLuint texture)
+{
+ if (texture == 0)
+ {
+ return GL_FALSE;
+ }
+
+ return (getTexture(texture) ? GL_TRUE : GL_FALSE);
+}
+
+void Context::linkProgram(GLuint program)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ handleError(programObject->link(this));
+ mGLState.onProgramExecutableChange(programObject);
+}
+
+void Context::releaseShaderCompiler()
+{
+ mCompiler.set(this, nullptr);
+}
+
+void Context::shaderBinary(GLsizei n,
+ const GLuint *shaders,
+ GLenum binaryformat,
+ const void *binary,
+ GLsizei length)
+{
+ // No binary shader formats are supported.
+ UNIMPLEMENTED();
+}
+
+void Context::shaderSource(GLuint shader,
+ GLsizei count,
+ const GLchar *const *string,
+ const GLint *length)
+{
+ Shader *shaderObject = getShader(shader);
+ ASSERT(shaderObject);
+ shaderObject->setSource(count, string, length);
+}
+
+void Context::stencilFunc(GLenum func, GLint ref, GLuint mask)
+{
+ stencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
+}
+
+void Context::stencilMask(GLuint mask)
+{
+ stencilMaskSeparate(GL_FRONT_AND_BACK, mask);
+}
+
+void Context::stencilOp(GLenum fail, GLenum zfail, GLenum zpass)
+{
+ stencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
+}
+
+void Context::uniform1f(GLint location, GLfloat x)
+{
+ Program *program = mGLState.getProgram();
+ program->setUniform1fv(location, 1, &x);
+}
+
+void Context::uniform1fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ Program *program = mGLState.getProgram();
+ program->setUniform1fv(location, count, v);
+}
+
+void Context::uniform1i(GLint location, GLint x)
+{
+ Program *program = mGLState.getProgram();
+ if (program->setUniform1iv(location, 1, &x) == Program::SetUniformResult::SamplerChanged)
+ {
+ mGLState.setObjectDirty(GL_PROGRAM);
+ }
+}
+
+void Context::uniform1iv(GLint location, GLsizei count, const GLint *v)
+{
+ Program *program = mGLState.getProgram();
+ if (program->setUniform1iv(location, count, v) == Program::SetUniformResult::SamplerChanged)
+ {
+ mGLState.setObjectDirty(GL_PROGRAM);
+ }
+}
+
+void Context::uniform2f(GLint location, GLfloat x, GLfloat y)
+{
+ GLfloat xy[2] = {x, y};
+ Program *program = mGLState.getProgram();
+ program->setUniform2fv(location, 1, xy);
+}
+
+void Context::uniform2fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ Program *program = mGLState.getProgram();
+ program->setUniform2fv(location, count, v);
+}
+
+void Context::uniform2i(GLint location, GLint x, GLint y)
+{
+ GLint xy[2] = {x, y};
+ Program *program = mGLState.getProgram();
+ program->setUniform2iv(location, 1, xy);
+}
+
+void Context::uniform2iv(GLint location, GLsizei count, const GLint *v)
+{
+ Program *program = mGLState.getProgram();
+ program->setUniform2iv(location, count, v);
+}
+
+void Context::uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
+{
+ GLfloat xyz[3] = {x, y, z};
+ Program *program = mGLState.getProgram();
+ program->setUniform3fv(location, 1, xyz);
+}
+
+void Context::uniform3fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ Program *program = mGLState.getProgram();
+ program->setUniform3fv(location, count, v);
+}
+
+void Context::uniform3i(GLint location, GLint x, GLint y, GLint z)
+{
+ GLint xyz[3] = {x, y, z};
+ Program *program = mGLState.getProgram();
+ program->setUniform3iv(location, 1, xyz);
+}
+
+void Context::uniform3iv(GLint location, GLsizei count, const GLint *v)
+{
+ Program *program = mGLState.getProgram();
+ program->setUniform3iv(location, count, v);
+}
+
+void Context::uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GLfloat xyzw[4] = {x, y, z, w};
+ Program *program = mGLState.getProgram();
+ program->setUniform4fv(location, 1, xyzw);
+}
+
+void Context::uniform4fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ Program *program = mGLState.getProgram();
+ program->setUniform4fv(location, count, v);
+}
+
+void Context::uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
+{
+ GLint xyzw[4] = {x, y, z, w};
+ Program *program = mGLState.getProgram();
+ program->setUniform4iv(location, 1, xyzw);
+}
+
+void Context::uniform4iv(GLint location, GLsizei count, const GLint *v)
+{
+ Program *program = mGLState.getProgram();
+ program->setUniform4iv(location, count, v);
+}
+
+void Context::uniformMatrix2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *program = mGLState.getProgram();
+ program->setUniformMatrix2fv(location, count, transpose, value);
+}
+
+void Context::uniformMatrix3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *program = mGLState.getProgram();
+ program->setUniformMatrix3fv(location, count, transpose, value);
+}
+
+void Context::uniformMatrix4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *program = mGLState.getProgram();
+ program->setUniformMatrix4fv(location, count, transpose, value);
+}
+
+void Context::validateProgram(GLuint program)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->validate(mCaps);
+}
+
+void Context::validateProgramPipeline(GLuint pipeline)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getProgramBinary(GLuint program,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject != nullptr);
+
+ handleError(programObject->saveBinary(this, binaryFormat, binary, bufSize, length));
+}
+
+void Context::programBinary(GLuint program, GLenum binaryFormat, const void *binary, GLsizei length)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject != nullptr);
+
+ handleError(programObject->loadBinary(this, binaryFormat, binary, length));
+}
+
+void Context::uniform1ui(GLint location, GLuint v0)
+{
+ Program *program = mGLState.getProgram();
+ program->setUniform1uiv(location, 1, &v0);
+}
+
+void Context::uniform2ui(GLint location, GLuint v0, GLuint v1)
+{
+ Program *program = mGLState.getProgram();
+ const GLuint xy[] = {v0, v1};
+ program->setUniform2uiv(location, 1, xy);
+}
+
+void Context::uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
+{
+ Program *program = mGLState.getProgram();
+ const GLuint xyz[] = {v0, v1, v2};
+ program->setUniform3uiv(location, 1, xyz);
+}
+
+void Context::uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+{
+ Program *program = mGLState.getProgram();
+ const GLuint xyzw[] = {v0, v1, v2, v3};
+ program->setUniform4uiv(location, 1, xyzw);
+}
+
+void Context::uniform1uiv(GLint location, GLsizei count, const GLuint *value)
+{
+ Program *program = mGLState.getProgram();
+ program->setUniform1uiv(location, count, value);
+}
+void Context::uniform2uiv(GLint location, GLsizei count, const GLuint *value)
+{
+ Program *program = mGLState.getProgram();
+ program->setUniform2uiv(location, count, value);
+}
+
+void Context::uniform3uiv(GLint location, GLsizei count, const GLuint *value)
+{
+ Program *program = mGLState.getProgram();
+ program->setUniform3uiv(location, count, value);
+}
+
+void Context::uniform4uiv(GLint location, GLsizei count, const GLuint *value)
+{
+ Program *program = mGLState.getProgram();
+ program->setUniform4uiv(location, count, value);
+}
+
+void Context::genQueries(GLsizei n, GLuint *ids)
+{
+ for (GLsizei i = 0; i < n; i++)
+ {
+ GLuint handle = mQueryHandleAllocator.allocate();
+ mQueryMap.assign(handle, nullptr);
+ ids[i] = handle;
+ }
+}
+
+void Context::deleteQueries(GLsizei n, const GLuint *ids)
+{
+ for (int i = 0; i < n; i++)
+ {
+ GLuint query = ids[i];
+
+ Query *queryObject = nullptr;
+ if (mQueryMap.erase(query, &queryObject))
+ {
+ mQueryHandleAllocator.release(query);
+ if (queryObject)
+ {
+ queryObject->release(this);
+ }
+ }
+ }
+}
+
+GLboolean Context::isQuery(GLuint id)
+{
+ return (getQuery(id, false, GL_NONE) != nullptr) ? GL_TRUE : GL_FALSE;
+}
+
+void Context::uniformMatrix2x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *program = mGLState.getProgram();
+ program->setUniformMatrix2x3fv(location, count, transpose, value);
+}
+
+void Context::uniformMatrix3x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *program = mGLState.getProgram();
+ program->setUniformMatrix3x2fv(location, count, transpose, value);
+}
+
+void Context::uniformMatrix2x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *program = mGLState.getProgram();
+ program->setUniformMatrix2x4fv(location, count, transpose, value);
+}
+
+void Context::uniformMatrix4x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *program = mGLState.getProgram();
+ program->setUniformMatrix4x2fv(location, count, transpose, value);
+}
+
+void Context::uniformMatrix3x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *program = mGLState.getProgram();
+ program->setUniformMatrix3x4fv(location, count, transpose, value);
+}
+
+void Context::uniformMatrix4x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *program = mGLState.getProgram();
+ program->setUniformMatrix4x3fv(location, count, transpose, value);
+}
+
+void Context::deleteVertexArrays(GLsizei n, const GLuint *arrays)
+{
+ for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
+ {
+ GLuint vertexArray = arrays[arrayIndex];
+
+ if (arrays[arrayIndex] != 0)
+ {
+ VertexArray *vertexArrayObject = nullptr;
+ if (mVertexArrayMap.erase(vertexArray, &vertexArrayObject))
+ {
+ if (vertexArrayObject != nullptr)
+ {
+ detachVertexArray(vertexArray);
+ vertexArrayObject->onDestroy(this);
+ }
+
+ mVertexArrayHandleAllocator.release(vertexArray);
+ }
}
}
}
+void Context::genVertexArrays(GLsizei n, GLuint *arrays)
+{
+ for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
+ {
+ GLuint vertexArray = mVertexArrayHandleAllocator.allocate();
+ mVertexArrayMap.assign(vertexArray, nullptr);
+ arrays[arrayIndex] = vertexArray;
+ }
+}
+
+bool Context::isVertexArray(GLuint array)
+{
+ if (array == 0)
+ {
+ return GL_FALSE;
+ }
+
+ VertexArray *vao = getVertexArray(array);
+ return (vao != nullptr ? GL_TRUE : GL_FALSE);
+}
+
+void Context::endTransformFeedback()
+{
+ TransformFeedback *transformFeedback = mGLState.getCurrentTransformFeedback();
+ transformFeedback->end(this);
+}
+
+void Context::transformFeedbackVaryings(GLuint program,
+ GLsizei count,
+ const GLchar *const *varyings,
+ GLenum bufferMode)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->setTransformFeedbackVaryings(count, varyings, bufferMode);
+}
+
+void Context::getTransformFeedbackVarying(GLuint program,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *size,
+ GLenum *type,
+ GLchar *name)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name);
+}
+
+void Context::deleteTransformFeedbacks(GLsizei n, const GLuint *ids)
+{
+ for (int i = 0; i < n; i++)
+ {
+ GLuint transformFeedback = ids[i];
+ if (transformFeedback == 0)
+ {
+ continue;
+ }
+
+ TransformFeedback *transformFeedbackObject = nullptr;
+ if (mTransformFeedbackMap.erase(transformFeedback, &transformFeedbackObject))
+ {
+ if (transformFeedbackObject != nullptr)
+ {
+ detachTransformFeedback(transformFeedback);
+ transformFeedbackObject->release(this);
+ }
+
+ mTransformFeedbackHandleAllocator.release(transformFeedback);
+ }
+ }
+}
+
+void Context::genTransformFeedbacks(GLsizei n, GLuint *ids)
+{
+ for (int i = 0; i < n; i++)
+ {
+ GLuint transformFeedback = mTransformFeedbackHandleAllocator.allocate();
+ mTransformFeedbackMap.assign(transformFeedback, nullptr);
+ ids[i] = transformFeedback;
+ }
+}
+
+bool Context::isTransformFeedback(GLuint id)
+{
+ if (id == 0)
+ {
+ // The 3.0.4 spec [section 6.1.11] states that if ID is zero, IsTransformFeedback
+ // returns FALSE
+ return GL_FALSE;
+ }
+
+ const TransformFeedback *transformFeedback = getTransformFeedback(id);
+ return ((transformFeedback != nullptr) ? GL_TRUE : GL_FALSE);
+}
+
+void Context::pauseTransformFeedback()
+{
+ TransformFeedback *transformFeedback = mGLState.getCurrentTransformFeedback();
+ transformFeedback->pause();
+}
+
+void Context::resumeTransformFeedback()
+{
+ TransformFeedback *transformFeedback = mGLState.getCurrentTransformFeedback();
+ transformFeedback->resume();
+}
+
+void Context::getUniformuiv(GLuint program, GLint location, GLuint *params)
+{
+ const Program *programObject = getProgram(program);
+ programObject->getUniformuiv(this, location, params);
+}
+
+GLint Context::getFragDataLocation(GLuint program, const GLchar *name)
+{
+ const Program *programObject = getProgram(program);
+ return programObject->getFragDataLocation(name);
+}
+
+void Context::getUniformIndices(GLuint program,
+ GLsizei uniformCount,
+ const GLchar *const *uniformNames,
+ GLuint *uniformIndices)
+{
+ const Program *programObject = getProgram(program);
+ if (!programObject->isLinked())
+ {
+ for (int uniformId = 0; uniformId < uniformCount; uniformId++)
+ {
+ uniformIndices[uniformId] = GL_INVALID_INDEX;
+ }
+ }
+ else
+ {
+ for (int uniformId = 0; uniformId < uniformCount; uniformId++)
+ {
+ uniformIndices[uniformId] = programObject->getUniformIndex(uniformNames[uniformId]);
+ }
+ }
+}
+
+void Context::getActiveUniformsiv(GLuint program,
+ GLsizei uniformCount,
+ const GLuint *uniformIndices,
+ GLenum pname,
+ GLint *params)
+{
+ const Program *programObject = getProgram(program);
+ for (int uniformId = 0; uniformId < uniformCount; uniformId++)
+ {
+ const GLuint index = uniformIndices[uniformId];
+ params[uniformId] = GetUniformResourceProperty(programObject, index, pname);
+ }
+}
+
+GLuint Context::getUniformBlockIndex(GLuint program, const GLchar *uniformBlockName)
+{
+ const Program *programObject = getProgram(program);
+ return programObject->getUniformBlockIndex(uniformBlockName);
+}
+
+void Context::getActiveUniformBlockiv(GLuint program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLint *params)
+{
+ const Program *programObject = getProgram(program);
+ QueryActiveUniformBlockiv(programObject, uniformBlockIndex, pname, params);
+}
+
+void Context::getActiveUniformBlockName(GLuint program,
+ GLuint uniformBlockIndex,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *uniformBlockName)
+{
+ const Program *programObject = getProgram(program);
+ programObject->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName);
+}
+
+void Context::uniformBlockBinding(GLuint program,
+ GLuint uniformBlockIndex,
+ GLuint uniformBlockBinding)
+{
+ Program *programObject = getProgram(program);
+ programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding);
+}
+
+GLsync Context::fenceSync(GLenum condition, GLbitfield flags)
+{
+ GLuint handle = mState.mSyncs->createSync(mImplementation.get());
+ GLsync syncHandle = reinterpret_cast<GLsync>(static_cast<uintptr_t>(handle));
+
+ Sync *syncObject = getSync(syncHandle);
+ Error error = syncObject->set(condition, flags);
+ if (error.isError())
+ {
+ deleteSync(syncHandle);
+ handleError(error);
+ return nullptr;
+ }
+
+ return syncHandle;
+}
+
+GLboolean Context::isSync(GLsync sync)
+{
+ return (getSync(sync) != nullptr);
+}
+
+GLenum Context::clientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
+{
+ Sync *syncObject = getSync(sync);
+
+ GLenum result = GL_WAIT_FAILED;
+ handleError(syncObject->clientWait(flags, timeout, &result));
+ return result;
+}
+
+void Context::waitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
+{
+ Sync *syncObject = getSync(sync);
+ handleError(syncObject->serverWait(flags, timeout));
+}
+
+void Context::getInteger64v(GLenum pname, GLint64 *params)
+{
+ GLenum nativeType = GL_NONE;
+ unsigned int numParams = 0;
+ getQueryParameterInfo(pname, &nativeType, &numParams);
+
+ if (nativeType == GL_INT_64_ANGLEX)
+ {
+ getInteger64vImpl(pname, params);
+ }
+ else
+ {
+ CastStateValues(this, nativeType, pname, numParams, params);
+ }
+}
+
+void Context::getBufferParameteri64v(BufferBinding target, GLenum pname, GLint64 *params)
+{
+ Buffer *buffer = mGLState.getTargetBuffer(target);
+ QueryBufferParameteri64v(buffer, pname, params);
+}
+
+void Context::genSamplers(GLsizei count, GLuint *samplers)
+{
+ for (int i = 0; i < count; i++)
+ {
+ samplers[i] = mState.mSamplers->createSampler();
+ }
+}
+
+void Context::deleteSamplers(GLsizei count, const GLuint *samplers)
+{
+ for (int i = 0; i < count; i++)
+ {
+ GLuint sampler = samplers[i];
+
+ if (mState.mSamplers->getSampler(sampler))
+ {
+ detachSampler(sampler);
+ }
+
+ mState.mSamplers->deleteObject(this, sampler);
+ }
+}
+
+void Context::getInternalformativ(GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLint *params)
+{
+ const TextureCaps &formatCaps = mTextureCaps.get(internalformat);
+ QueryInternalFormativ(formatCaps, pname, bufSize, params);
+}
+
+void Context::programUniform1i(GLuint program, GLint location, GLint v0)
+{
+ programUniform1iv(program, location, 1, &v0);
+}
+
+void Context::programUniform2i(GLuint program, GLint location, GLint v0, GLint v1)
+{
+ GLint xy[2] = {v0, v1};
+ programUniform2iv(program, location, 1, xy);
+}
+
+void Context::programUniform3i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2)
+{
+ GLint xyz[3] = {v0, v1, v2};
+ programUniform3iv(program, location, 1, xyz);
+}
+
+void Context::programUniform4i(GLuint program,
+ GLint location,
+ GLint v0,
+ GLint v1,
+ GLint v2,
+ GLint v3)
+{
+ GLint xyzw[4] = {v0, v1, v2, v3};
+ programUniform4iv(program, location, 1, xyzw);
+}
+
+void Context::programUniform1ui(GLuint program, GLint location, GLuint v0)
+{
+ programUniform1uiv(program, location, 1, &v0);
+}
+
+void Context::programUniform2ui(GLuint program, GLint location, GLuint v0, GLuint v1)
+{
+ GLuint xy[2] = {v0, v1};
+ programUniform2uiv(program, location, 1, xy);
+}
+
+void Context::programUniform3ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2)
+{
+ GLuint xyz[3] = {v0, v1, v2};
+ programUniform3uiv(program, location, 1, xyz);
+}
+
+void Context::programUniform4ui(GLuint program,
+ GLint location,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLuint xyzw[4] = {v0, v1, v2, v3};
+ programUniform4uiv(program, location, 1, xyzw);
+}
+
+void Context::programUniform1f(GLuint program, GLint location, GLfloat v0)
+{
+ programUniform1fv(program, location, 1, &v0);
+}
+
+void Context::programUniform2f(GLuint program, GLint location, GLfloat v0, GLfloat v1)
+{
+ GLfloat xy[2] = {v0, v1};
+ programUniform2fv(program, location, 1, xy);
+}
+
+void Context::programUniform3f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
+{
+ GLfloat xyz[3] = {v0, v1, v2};
+ programUniform3fv(program, location, 1, xyz);
+}
+
+void Context::programUniform4f(GLuint program,
+ GLint location,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2,
+ GLfloat v3)
+{
+ GLfloat xyzw[4] = {v0, v1, v2, v3};
+ programUniform4fv(program, location, 1, xyzw);
+}
+
+void Context::programUniform1iv(GLuint program, GLint location, GLsizei count, const GLint *value)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ if (programObject->setUniform1iv(location, count, value) ==
+ Program::SetUniformResult::SamplerChanged)
+ {
+ mGLState.setObjectDirty(GL_PROGRAM);
+ }
+}
+
+void Context::programUniform2iv(GLuint program, GLint location, GLsizei count, const GLint *value)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->setUniform2iv(location, count, value);
+}
+
+void Context::programUniform3iv(GLuint program, GLint location, GLsizei count, const GLint *value)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->setUniform3iv(location, count, value);
+}
+
+void Context::programUniform4iv(GLuint program, GLint location, GLsizei count, const GLint *value)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->setUniform4iv(location, count, value);
+}
+
+void Context::programUniform1uiv(GLuint program, GLint location, GLsizei count, const GLuint *value)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->setUniform1uiv(location, count, value);
+}
+
+void Context::programUniform2uiv(GLuint program, GLint location, GLsizei count, const GLuint *value)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->setUniform2uiv(location, count, value);
+}
+
+void Context::programUniform3uiv(GLuint program, GLint location, GLsizei count, const GLuint *value)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->setUniform3uiv(location, count, value);
+}
+
+void Context::programUniform4uiv(GLuint program, GLint location, GLsizei count, const GLuint *value)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->setUniform4uiv(location, count, value);
+}
+
+void Context::programUniform1fv(GLuint program, GLint location, GLsizei count, const GLfloat *value)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->setUniform1fv(location, count, value);
+}
+
+void Context::programUniform2fv(GLuint program, GLint location, GLsizei count, const GLfloat *value)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->setUniform2fv(location, count, value);
+}
+
+void Context::programUniform3fv(GLuint program, GLint location, GLsizei count, const GLfloat *value)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->setUniform3fv(location, count, value);
+}
+
+void Context::programUniform4fv(GLuint program, GLint location, GLsizei count, const GLfloat *value)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->setUniform4fv(location, count, value);
+}
+
+void Context::programUniformMatrix2fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->setUniformMatrix2fv(location, count, transpose, value);
+}
+
+void Context::programUniformMatrix3fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->setUniformMatrix3fv(location, count, transpose, value);
+}
+
+void Context::programUniformMatrix4fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->setUniformMatrix4fv(location, count, transpose, value);
+}
+
+void Context::programUniformMatrix2x3fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->setUniformMatrix2x3fv(location, count, transpose, value);
+}
+
+void Context::programUniformMatrix3x2fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->setUniformMatrix3x2fv(location, count, transpose, value);
+}
+
+void Context::programUniformMatrix2x4fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->setUniformMatrix2x4fv(location, count, transpose, value);
+}
+
+void Context::programUniformMatrix4x2fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->setUniformMatrix4x2fv(location, count, transpose, value);
+}
+
+void Context::programUniformMatrix3x4fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->setUniformMatrix3x4fv(location, count, transpose, value);
+}
+
+void Context::programUniformMatrix4x3fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *programObject = getProgram(program);
+ ASSERT(programObject);
+ programObject->setUniformMatrix4x3fv(location, count, transpose, value);
+}
+
+void Context::onTextureChange(const Texture *texture)
+{
+ // Conservatively assume all textures are dirty.
+ // TODO(jmadill): More fine-grained update.
+ mGLState.setObjectDirty(GL_TEXTURE);
+}
+
+void Context::genProgramPipelines(GLsizei count, GLuint *pipelines)
+{
+ for (int i = 0; i < count; i++)
+ {
+ pipelines[i] = createProgramPipeline();
+ }
+}
+
+void Context::deleteProgramPipelines(GLsizei count, const GLuint *pipelines)
+{
+ for (int i = 0; i < count; i++)
+ {
+ if (pipelines[i] != 0)
+ {
+ deleteProgramPipeline(pipelines[i]);
+ }
+ }
+}
+
+GLboolean Context::isProgramPipeline(GLuint pipeline)
+{
+ if (pipeline == 0)
+ {
+ return GL_FALSE;
+ }
+
+ return (getProgramPipeline(pipeline) ? GL_TRUE : GL_FALSE);
+}
+
} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/Context.h b/src/3rdparty/angle/src/libANGLE/Context.h
index 6b82eb7cb9..38c4e7b4d1 100644
--- a/src/3rdparty/angle/src/libANGLE/Context.h
+++ b/src/3rdparty/angle/src/libANGLE/Context.h
@@ -10,25 +10,28 @@
#ifndef LIBANGLE_CONTEXT_H_
#define LIBANGLE_CONTEXT_H_
+#include <set>
+#include <string>
+
+#include "angle_gl.h"
+#include "common/MemoryBuffer.h"
#include "common/angleutils.h"
-#include "libANGLE/RefCountObject.h"
#include "libANGLE/Caps.h"
#include "libANGLE/Constants.h"
-#include "libANGLE/Data.h"
+#include "libANGLE/ContextState.h"
#include "libANGLE/Error.h"
#include "libANGLE/HandleAllocator.h"
+#include "libANGLE/PackedGLEnums.h"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/ResourceMap.h"
#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/Workarounds.h"
#include "libANGLE/angletypes.h"
-#include "angle_gl.h"
-
-#include <string>
-#include <set>
-#include <map>
-
namespace rx
{
-class Renderer;
+class ContextImpl;
+class EGLImplFactory;
}
namespace egl
@@ -36,41 +39,44 @@ namespace egl
class AttributeMap;
class Surface;
struct Config;
+class Thread;
}
namespace gl
{
+class Buffer;
class Compiler;
-class Shader;
-class Program;
-class Texture;
-class Framebuffer;
-class Renderbuffer;
class FenceNV;
-class FenceSync;
+class Sync;
+class Framebuffer;
+class MemoryProgramCache;
+class Program;
class Query;
-class ResourceManager;
-class Buffer;
-struct VertexAttribute;
-class VertexArray;
+class Renderbuffer;
class Sampler;
+class Shader;
+class Texture;
class TransformFeedback;
+class VertexArray;
+struct VertexAttribute;
+class ProgramPipeline;
class Context final : public ValidationContext
{
public:
- Context(const egl::Config *config,
+ Context(rx::EGLImplFactory *implFactory,
+ const egl::Config *config,
const Context *shareContext,
- rx::Renderer *renderer,
- const egl::AttributeMap &attribs);
-
- virtual ~Context();
+ TextureManager *shareTextures,
+ MemoryProgramCache *memoryProgramCache,
+ const egl::AttributeMap &attribs,
+ const egl::DisplayExtensions &displayExtensions);
- void makeCurrent(egl::Surface *surface);
- void releaseSurface();
+ egl::Error onDestroy(const egl::Display *display);
+ ~Context() override;
- virtual void markContextLost();
- bool isContextLost();
+ egl::Error makeCurrent(egl::Display *display, egl::Surface *surface);
+ egl::Error releaseSurface(const egl::Display *display);
// These create and destroy methods are merely pass-throughs to
// ResourceManager, which owns these object types
@@ -79,18 +85,30 @@ class Context final : public ValidationContext
GLuint createProgram();
GLuint createTexture();
GLuint createRenderbuffer();
- GLuint createSampler();
- GLuint createTransformFeedback();
- GLsync createFenceSync();
+ GLuint createPaths(GLsizei range);
+ GLuint createProgramPipeline();
+ GLuint createShaderProgramv(GLenum type, GLsizei count, const GLchar *const *strings);
void deleteBuffer(GLuint buffer);
void deleteShader(GLuint shader);
void deleteProgram(GLuint program);
void deleteTexture(GLuint texture);
void deleteRenderbuffer(GLuint renderbuffer);
- void deleteSampler(GLuint sampler);
- void deleteTransformFeedback(GLuint transformFeedback);
- void deleteFenceSync(GLsync fenceSync);
+ void deletePaths(GLuint first, GLsizei range);
+ void deleteProgramPipeline(GLuint pipeline);
+
+ // CHROMIUM_path_rendering
+ bool hasPathData(GLuint path) const;
+ bool hasPath(GLuint path) const;
+ void setPathCommands(GLuint path,
+ GLsizei numCommands,
+ const GLubyte *commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const void *coords);
+ void setPathParameterf(GLuint path, GLenum pname, GLfloat value);
+ void getPathParameterfv(GLuint path, GLenum pname, GLfloat *value) const;
+ void setPathStencilFunc(GLenum func, GLint ref, GLuint mask);
// Framebuffers are owned by the Context, so these methods do not pass through
GLuint createFramebuffer();
@@ -100,54 +118,90 @@ class Context final : public ValidationContext
GLuint createFenceNV();
void deleteFenceNV(GLuint fence);
- // Queries are owned by the Context;
- GLuint createQuery();
- void deleteQuery(GLuint query);
-
- // Vertex arrays are owned by the Context
- GLuint createVertexArray();
- void deleteVertexArray(GLuint vertexArray);
-
- void bindArrayBuffer(GLuint buffer);
- void bindElementArrayBuffer(GLuint buffer);
void bindTexture(GLenum target, GLuint handle);
void bindReadFramebuffer(GLuint framebufferHandle);
void bindDrawFramebuffer(GLuint framebufferHandle);
- void bindRenderbuffer(GLuint renderbuffer);
- void bindVertexArray(GLuint vertexArray);
- void bindSampler(GLuint textureUnit, GLuint sampler);
- void bindGenericUniformBuffer(GLuint buffer);
- void bindIndexedUniformBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size);
- void bindGenericTransformFeedbackBuffer(GLuint buffer);
- void bindIndexedTransformFeedbackBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size);
- void bindCopyReadBuffer(GLuint buffer);
- void bindCopyWriteBuffer(GLuint buffer);
- void bindPixelPackBuffer(GLuint buffer);
- void bindPixelUnpackBuffer(GLuint buffer);
+ void bindVertexArray(GLuint vertexArrayHandle);
+ void bindVertexBuffer(GLuint bindingIndex,
+ GLuint bufferHandle,
+ GLintptr offset,
+ GLsizei stride);
+ void bindSampler(GLuint textureUnit, GLuint samplerHandle);
+ void bindImageTexture(GLuint unit,
+ GLuint texture,
+ GLint level,
+ GLboolean layered,
+ GLint layer,
+ GLenum access,
+ GLenum format);
void useProgram(GLuint program);
- void bindTransformFeedback(GLuint transformFeedback);
+ void useProgramStages(GLuint pipeline, GLbitfield stages, GLuint program);
+ void bindTransformFeedback(GLenum target, GLuint transformFeedbackHandle);
+ void bindProgramPipeline(GLuint pipelineHandle);
- Error beginQuery(GLenum target, GLuint query);
- Error endQuery(GLenum target);
- Error queryCounter(GLuint id, GLenum target);
+ void beginQuery(GLenum target, GLuint query);
+ void endQuery(GLenum target);
+ void queryCounter(GLuint id, GLenum target);
void getQueryiv(GLenum target, GLenum pname, GLint *params);
- Error getQueryObjectiv(GLuint id, GLenum pname, GLint *params);
- Error getQueryObjectuiv(GLuint id, GLenum pname, GLuint *params);
- Error getQueryObjecti64v(GLuint id, GLenum pname, GLint64 *params);
- Error getQueryObjectui64v(GLuint id, GLenum pname, GLuint64 *params);
-
- void setVertexAttribDivisor(GLuint index, GLuint divisor);
+ void getQueryObjectiv(GLuint id, GLenum pname, GLint *params);
+ void getQueryObjectuiv(GLuint id, GLenum pname, GLuint *params);
+ void getQueryObjecti64v(GLuint id, GLenum pname, GLint64 *params);
+ void getQueryObjectui64v(GLuint id, GLenum pname, GLuint64 *params);
+
+ void vertexAttribDivisor(GLuint index, GLuint divisor);
+ void vertexBindingDivisor(GLuint bindingIndex, GLuint divisor);
+
+ void getBufferParameteriv(BufferBinding target, GLenum pname, GLint *params);
+ void getFramebufferAttachmentParameteriv(GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLint *params);
+ void getRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params);
+
+ void getTexParameterfv(GLenum target, GLenum pname, GLfloat *params);
+ void getTexParameteriv(GLenum target, GLenum pname, GLint *params);
+ void getTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params);
+ void getTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat *params);
+ void texParameterf(GLenum target, GLenum pname, GLfloat param);
+ void texParameterfv(GLenum target, GLenum pname, const GLfloat *params);
+ void texParameteri(GLenum target, GLenum pname, GLint param);
+ void texParameteriv(GLenum target, GLenum pname, const GLint *params);
void samplerParameteri(GLuint sampler, GLenum pname, GLint param);
+ void samplerParameteriv(GLuint sampler, GLenum pname, const GLint *param);
void samplerParameterf(GLuint sampler, GLenum pname, GLfloat param);
- GLint getSamplerParameteri(GLuint sampler, GLenum pname);
- GLfloat getSamplerParameterf(GLuint sampler, GLenum pname);
+ void samplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *param);
+
+ void getSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params);
+ void getSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params);
+
+ void programParameteri(GLuint program, GLenum pname, GLint value);
+
+ GLuint getProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar *name);
+ void getProgramResourceName(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name);
+ GLint getProgramResourceLocation(GLuint program, GLenum programInterface, const GLchar *name);
+ void getProgramResourceiv(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum *props,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+
+ void getProgramInterfaceiv(GLuint program,
+ GLenum programInterface,
+ GLenum pname,
+ GLint *params);
Buffer *getBuffer(GLuint handle) const;
FenceNV *getFenceNV(GLuint handle);
- FenceSync *getFenceSync(GLsync handle) const;
- Shader *getShader(GLuint handle) const;
- Program *getProgram(GLuint handle) const;
+ Sync *getSync(GLsync handle) const;
Texture *getTexture(GLuint handle) const;
Framebuffer *getFramebuffer(GLuint handle) const;
Renderbuffer *getRenderbuffer(GLuint handle) const;
@@ -156,8 +210,16 @@ class Context final : public ValidationContext
Query *getQuery(GLuint handle, bool create, GLenum type);
Query *getQuery(GLuint handle) const;
TransformFeedback *getTransformFeedback(GLuint handle) const;
- LabeledObject *getLabeledObject(GLenum identifier, GLuint name) const;
- LabeledObject *getLabeledObjectFromPtr(const void *ptr) const;
+ ProgramPipeline *getProgramPipeline(GLuint handle) const;
+
+ void objectLabel(GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+ void objectPtrLabel(const void *ptr, GLsizei length, const GLchar *label);
+ void getObjectLabel(GLenum identifier,
+ GLuint name,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label) const;
+ void getObjectPtrLabel(const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label) const;
Texture *getTargetTexture(GLenum target) const;
Texture *getSamplerTexture(unsigned int sampler, GLenum type) const;
@@ -170,16 +232,108 @@ class Context final : public ValidationContext
bool isTransformFeedbackGenerated(GLuint vertexArray);
void getBooleanv(GLenum pname, GLboolean *params);
+ void getBooleanvImpl(GLenum pname, GLboolean *params);
void getFloatv(GLenum pname, GLfloat *params);
+ void getFloatvImpl(GLenum pname, GLfloat *params);
void getIntegerv(GLenum pname, GLint *params);
- void getInteger64v(GLenum pname, GLint64 *params);
+ void getIntegervImpl(GLenum pname, GLint *params);
+ void getInteger64vImpl(GLenum pname, GLint64 *params);
void getPointerv(GLenum pname, void **params) const;
-
- bool getIndexedIntegerv(GLenum target, GLuint index, GLint *data);
- bool getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data);
-
- bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams);
- bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams);
+ void getBooleani_v(GLenum target, GLuint index, GLboolean *data);
+ void getIntegeri_v(GLenum target, GLuint index, GLint *data);
+ void getInteger64i_v(GLenum target, GLuint index, GLint64 *data);
+
+ void activeShaderProgram(GLuint pipeline, GLuint program);
+ void activeTexture(GLenum texture);
+ void blendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+ void blendEquation(GLenum mode);
+ void blendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
+ void blendFunc(GLenum sfactor, GLenum dfactor);
+ void blendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+ void clearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+ void clearDepthf(GLfloat depth);
+ void clearStencil(GLint s);
+ void colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+ void cullFace(CullFaceMode mode);
+ void depthFunc(GLenum func);
+ void depthMask(GLboolean flag);
+ void depthRangef(GLfloat zNear, GLfloat zFar);
+ void disable(GLenum cap);
+ void disableVertexAttribArray(GLuint index);
+ void enable(GLenum cap);
+ void enableVertexAttribArray(GLuint index);
+ void frontFace(GLenum mode);
+ void hint(GLenum target, GLenum mode);
+ void lineWidth(GLfloat width);
+ void pixelStorei(GLenum pname, GLint param);
+ void polygonOffset(GLfloat factor, GLfloat units);
+ void sampleCoverage(GLfloat value, GLboolean invert);
+ void sampleMaski(GLuint maskNumber, GLbitfield mask);
+ void scissor(GLint x, GLint y, GLsizei width, GLsizei height);
+ void stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
+ void stencilMaskSeparate(GLenum face, GLuint mask);
+ void stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+ void vertexAttrib1f(GLuint index, GLfloat x);
+ void vertexAttrib1fv(GLuint index, const GLfloat *values);
+ void vertexAttrib2f(GLuint index, GLfloat x, GLfloat y);
+ void vertexAttrib2fv(GLuint index, const GLfloat *values);
+ void vertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z);
+ void vertexAttrib3fv(GLuint index, const GLfloat *values);
+ void vertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void vertexAttrib4fv(GLuint index, const GLfloat *values);
+ void vertexAttribFormat(GLuint attribIndex,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLuint relativeOffset);
+ void vertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type, GLuint relativeOffset);
+ void vertexAttribBinding(GLuint attribIndex, GLuint bindingIndex);
+ void vertexAttribPointer(GLuint index,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLsizei stride,
+ const void *ptr);
+ void vertexAttribIPointer(GLuint index,
+ GLint size,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer);
+ void viewport(GLint x, GLint y, GLsizei width, GLsizei height);
+
+ void vertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w);
+ void vertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+ void vertexAttribI4iv(GLuint index, const GLint *v);
+ void vertexAttribI4uiv(GLuint index, const GLuint *v);
+ void getVertexAttribiv(GLuint index, GLenum pname, GLint *params);
+ void getVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
+ void getVertexAttribIiv(GLuint index, GLenum pname, GLint *params);
+ void getVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params);
+ void getVertexAttribPointerv(GLuint index, GLenum pname, void **pointer);
+
+ void debugMessageControl(GLenum source,
+ GLenum type,
+ GLenum severity,
+ GLsizei count,
+ const GLuint *ids,
+ GLboolean enabled);
+ void debugMessageInsert(GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar *buf);
+ void debugMessageCallback(GLDEBUGPROCKHR callback, const void *userParam);
+ GLuint getDebugMessageLog(GLuint count,
+ GLsizei bufSize,
+ GLenum *sources,
+ GLenum *types,
+ GLuint *ids,
+ GLenum *severities,
+ GLsizei *lengths,
+ GLchar *messageLog);
+ void pushDebugGroup(GLenum source, GLuint id, GLsizei length, const GLchar *message);
+ void popDebugGroup();
void clear(GLbitfield mask);
void clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values);
@@ -187,27 +341,23 @@ class Context final : public ValidationContext
void clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values);
void clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
- Error drawArrays(GLenum mode, GLint first, GLsizei count);
- Error drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount);
-
- Error drawElements(GLenum mode,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- const IndexRange &indexRange);
- Error drawElementsInstanced(GLenum mode,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- GLsizei instances,
- const IndexRange &indexRange);
- Error drawRangeElements(GLenum mode,
- GLuint start,
- GLuint end,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- const IndexRange &indexRange);
+ void drawArrays(GLenum mode, GLint first, GLsizei count);
+ void drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount);
+
+ void drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices);
+ void drawElementsInstanced(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei instances);
+ void drawRangeElements(GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const void *indices);
+ void drawArraysIndirect(GLenum mode, const void *indirect);
+ void drawElementsIndirect(GLenum mode, GLenum type, const void *indirect);
void blitFramebuffer(GLint srcX0,
GLint srcY0,
@@ -226,7 +376,7 @@ class Context final : public ValidationContext
GLsizei height,
GLenum format,
GLenum type,
- GLvoid *pixels);
+ void *pixels);
void copyTexImage2D(GLenum target,
GLint level,
@@ -272,6 +422,18 @@ class Context final : public ValidationContext
GLuint texture,
GLint level,
GLint layer);
+ void framebufferTextureMultiviewLayeredANGLE(GLenum target,
+ GLenum attachment,
+ GLuint texture,
+ GLint level,
+ GLint baseViewIndex,
+ GLsizei numViews);
+ void framebufferTextureMultiviewSideBySideANGLE(GLenum target,
+ GLenum attachment,
+ GLuint texture,
+ GLint level,
+ GLsizei numViews,
+ const GLint *viewportOffsets);
void drawBuffers(GLsizei n, const GLenum *bufs);
void readBuffer(GLenum mode);
@@ -286,40 +448,596 @@ class Context final : public ValidationContext
GLsizei width,
GLsizei height);
- Error flush();
- Error finish();
+ void texImage2D(GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+ void texImage3D(GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+ void texSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+ void texSubImage3D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+ void compressedTexImage2D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ const void *data);
+ void compressedTexImage3D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ const void *data);
+ void compressedTexSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data);
+ void compressedTexSubImage3D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data);
+ void copyTextureCHROMIUM(GLuint sourceId,
+ GLint sourceLevel,
+ GLenum destTarget,
+ GLuint destId,
+ GLint destLevel,
+ GLint internalFormat,
+ GLenum destType,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha);
+ void copySubTextureCHROMIUM(GLuint sourceId,
+ GLint sourceLevel,
+ GLenum destTarget,
+ GLuint destId,
+ GLint destLevel,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha);
+ void compressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId);
+
+ void generateMipmap(GLenum target);
+
+ void flush();
+ void finish();
+
+ void getBufferPointerv(BufferBinding target, GLenum pname, void **params);
+ void *mapBuffer(BufferBinding target, GLenum access);
+ GLboolean unmapBuffer(BufferBinding target);
+ void *mapBufferRange(BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access);
+ void flushMappedBufferRange(BufferBinding target, GLintptr offset, GLsizeiptr length);
+
+ void beginTransformFeedback(GLenum primitiveMode);
+
+ bool hasActiveTransformFeedback(GLuint program) const;
void insertEventMarker(GLsizei length, const char *marker);
void pushGroupMarker(GLsizei length, const char *marker);
void popGroupMarker();
- void recordError(const Error &error) override;
+ void bindUniformLocation(GLuint program, GLint location, const GLchar *name);
+ void renderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+ void renderbufferStorageMultisample(GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+
+ void getSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+
+ // CHROMIUM_framebuffer_mixed_samples
+ void setCoverageModulation(GLenum components);
+
+ // CHROMIUM_path_rendering
+ void loadPathRenderingMatrix(GLenum matrixMode, const GLfloat *matrix);
+ void loadPathRenderingIdentityMatrix(GLenum matrixMode);
+ void stencilFillPath(GLuint path, GLenum fillMode, GLuint mask);
+ void stencilStrokePath(GLuint path, GLint reference, GLuint mask);
+ void coverFillPath(GLuint path, GLenum coverMode);
+ void coverStrokePath(GLuint path, GLenum coverMode);
+ void stencilThenCoverFillPath(GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode);
+ void stencilThenCoverStrokePath(GLuint path, GLint reference, GLuint mask, GLenum coverMode);
+ void coverFillPathInstanced(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ void coverStrokePathInstanced(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ void stencilFillPathInstanced(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBAse,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ void stencilStrokePathInstanced(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ void stencilThenCoverFillPathInstanced(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ void stencilThenCoverStrokePathInstanced(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ void bindFragmentInputLocation(GLuint program, GLint location, const GLchar *name);
+ void programPathFragmentInputGen(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs);
+
+ void bufferData(BufferBinding target, GLsizeiptr size, const void *data, BufferUsage usage);
+ void bufferSubData(BufferBinding target, GLintptr offset, GLsizeiptr size, const void *data);
+ void attachShader(GLuint program, GLuint shader);
+ void bindAttribLocation(GLuint program, GLuint index, const GLchar *name);
+ void bindBuffer(BufferBinding target, GLuint buffer);
+ void bindBufferBase(BufferBinding target, GLuint index, GLuint buffer);
+ void bindBufferRange(BufferBinding target,
+ GLuint index,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizeiptr size);
+ void bindFramebuffer(GLenum target, GLuint framebuffer);
+ void bindRenderbuffer(GLenum target, GLuint renderbuffer);
+
+ void texStorage2DMultisample(GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedsamplelocations);
+
+ void getMultisamplefv(GLenum pname, GLuint index, GLfloat *val);
+
+ void copyBufferSubData(BufferBinding readTarget,
+ BufferBinding writeTarget,
+ GLintptr readOffset,
+ GLintptr writeOffset,
+ GLsizeiptr size);
+
+ GLenum checkFramebufferStatus(GLenum target);
+ void compileShader(GLuint shader);
+ void deleteBuffers(GLsizei n, const GLuint *buffers);
+ void deleteFramebuffers(GLsizei n, const GLuint *framebuffers);
+ void deleteRenderbuffers(GLsizei n, const GLuint *renderbuffers);
+ void deleteTextures(GLsizei n, const GLuint *textures);
+ void detachShader(GLuint program, GLuint shader);
+ void genBuffers(GLsizei n, GLuint *buffers);
+ void genFramebuffers(GLsizei n, GLuint *framebuffers);
+ void genRenderbuffers(GLsizei n, GLuint *renderbuffers);
+ void genTextures(GLsizei n, GLuint *textures);
+ void getActiveAttrib(GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name);
+ void getActiveUniform(GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name);
+ void getAttachedShaders(GLuint program, GLsizei maxcount, GLsizei *count, GLuint *shaders);
+ GLint getAttribLocation(GLuint program, const GLchar *name);
+ void getProgramiv(GLuint program, GLenum pname, GLint *params);
+ void getProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *params);
+ void getProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei *length, GLchar *infolog);
+ void getProgramPipelineInfoLog(GLuint pipeline,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *infoLog);
+ void getShaderiv(GLuint shader, GLenum pname, GLint *params);
+ void getShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *infolog);
+ void getShaderPrecisionFormat(GLenum shadertype,
+ GLenum precisiontype,
+ GLint *range,
+ GLint *precision);
+ void getShaderSource(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source);
+ void getUniformfv(GLuint program, GLint location, GLfloat *params);
+ void getUniformiv(GLuint program, GLint location, GLint *params);
+ GLint getUniformLocation(GLuint program, const GLchar *name);
+ GLboolean isBuffer(GLuint buffer);
+ GLboolean isEnabled(GLenum cap);
+ GLboolean isFramebuffer(GLuint framebuffer);
+ GLboolean isProgram(GLuint program);
+ GLboolean isRenderbuffer(GLuint renderbuffer);
+ GLboolean isShader(GLuint shader);
+ GLboolean isTexture(GLuint texture);
+ void linkProgram(GLuint program);
+ void releaseShaderCompiler();
+ void shaderBinary(GLsizei n,
+ const GLuint *shaders,
+ GLenum binaryformat,
+ const void *binary,
+ GLsizei length);
+ void shaderSource(GLuint shader,
+ GLsizei count,
+ const GLchar *const *string,
+ const GLint *length);
+ void stencilFunc(GLenum func, GLint ref, GLuint mask);
+ void stencilMask(GLuint mask);
+ void stencilOp(GLenum fail, GLenum zfail, GLenum zpass);
+ void uniform1f(GLint location, GLfloat x);
+ void uniform1fv(GLint location, GLsizei count, const GLfloat *v);
+ void uniform1i(GLint location, GLint x);
+ void uniform1iv(GLint location, GLsizei count, const GLint *v);
+ void uniform2f(GLint location, GLfloat x, GLfloat y);
+ void uniform2fv(GLint location, GLsizei count, const GLfloat *v);
+ void uniform2i(GLint location, GLint x, GLint y);
+ void uniform2iv(GLint location, GLsizei count, const GLint *v);
+ void uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z);
+ void uniform3fv(GLint location, GLsizei count, const GLfloat *v);
+ void uniform3i(GLint location, GLint x, GLint y, GLint z);
+ void uniform3iv(GLint location, GLsizei count, const GLint *v);
+ void uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void uniform4fv(GLint location, GLsizei count, const GLfloat *v);
+ void uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w);
+ void uniform4iv(GLint location, GLsizei count, const GLint *v);
+ void uniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+ void uniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+ void uniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+ void validateProgram(GLuint program);
+ void validateProgramPipeline(GLuint pipeline);
+
+ void genQueries(GLsizei n, GLuint *ids);
+ void deleteQueries(GLsizei n, const GLuint *ids);
+ GLboolean isQuery(GLuint id);
+
+ void uniform1ui(GLint location, GLuint v0);
+ void uniform2ui(GLint location, GLuint v0, GLuint v1);
+ void uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2);
+ void uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+ void uniform1uiv(GLint location, GLsizei count, const GLuint *value);
+ void uniform2uiv(GLint location, GLsizei count, const GLuint *value);
+ void uniform3uiv(GLint location, GLsizei count, const GLuint *value);
+ void uniform4uiv(GLint location, GLsizei count, const GLuint *value);
+
+ void uniformMatrix2x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void uniformMatrix3x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void uniformMatrix2x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void uniformMatrix4x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void uniformMatrix3x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void uniformMatrix4x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+
+ void deleteVertexArrays(GLsizei n, const GLuint *arrays);
+ void genVertexArrays(GLsizei n, GLuint *arrays);
+ bool isVertexArray(GLuint array);
+
+ void endTransformFeedback();
+ void transformFeedbackVaryings(GLuint program,
+ GLsizei count,
+ const GLchar *const *varyings,
+ GLenum bufferMode);
+ void getTransformFeedbackVarying(GLuint program,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *size,
+ GLenum *type,
+ GLchar *name);
+
+ void deleteTransformFeedbacks(GLsizei n, const GLuint *ids);
+ void genTransformFeedbacks(GLsizei n, GLuint *ids);
+ bool isTransformFeedback(GLuint id);
+ void pauseTransformFeedback();
+ void resumeTransformFeedback();
+
+ void getProgramBinary(GLuint program,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary);
+ void programBinary(GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
+
+ void getUniformuiv(GLuint program, GLint location, GLuint *params);
+ GLint getFragDataLocation(GLuint program, const GLchar *name);
+ void getUniformIndices(GLuint program,
+ GLsizei uniformCount,
+ const GLchar *const *uniformNames,
+ GLuint *uniformIndices);
+ void getActiveUniformsiv(GLuint program,
+ GLsizei uniformCount,
+ const GLuint *uniformIndices,
+ GLenum pname,
+ GLint *params);
+ GLuint getUniformBlockIndex(GLuint program, const GLchar *uniformBlockName);
+ void getActiveUniformBlockiv(GLuint program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLint *params);
+ void getActiveUniformBlockName(GLuint program,
+ GLuint uniformBlockIndex,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *uniformBlockName);
+ void uniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+
+ GLsync fenceSync(GLenum condition, GLbitfield flags);
+ GLboolean isSync(GLsync sync);
+ void deleteSync(GLsync sync);
+ GLenum clientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout);
+ void waitSync(GLsync sync, GLbitfield flags, GLuint64 timeout);
+ void getInteger64v(GLenum pname, GLint64 *params);
+
+ void getBufferParameteri64v(BufferBinding target, GLenum pname, GLint64 *params);
+ void genSamplers(GLsizei count, GLuint *samplers);
+ void deleteSamplers(GLsizei count, const GLuint *samplers);
+ void getInternalformativ(GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLint *params);
+
+ void programUniform1i(GLuint program, GLint location, GLint v0);
+ void programUniform2i(GLuint program, GLint location, GLint v0, GLint v1);
+ void programUniform3i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+ void programUniform4i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+ void programUniform1ui(GLuint program, GLint location, GLuint v0);
+ void programUniform2ui(GLuint program, GLint location, GLuint v0, GLuint v1);
+ void programUniform3ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+ void programUniform4ui(GLuint program,
+ GLint location,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3);
+ void programUniform1f(GLuint program, GLint location, GLfloat v0);
+ void programUniform2f(GLuint program, GLint location, GLfloat v0, GLfloat v1);
+ void programUniform3f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+ void programUniform4f(GLuint program,
+ GLint location,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2,
+ GLfloat v3);
+ void programUniform1iv(GLuint program, GLint location, GLsizei count, const GLint *value);
+ void programUniform2iv(GLuint program, GLint location, GLsizei count, const GLint *value);
+ void programUniform3iv(GLuint program, GLint location, GLsizei count, const GLint *value);
+ void programUniform4iv(GLuint program, GLint location, GLsizei count, const GLint *value);
+ void programUniform1uiv(GLuint program, GLint location, GLsizei count, const GLuint *value);
+ void programUniform2uiv(GLuint program, GLint location, GLsizei count, const GLuint *value);
+ void programUniform3uiv(GLuint program, GLint location, GLsizei count, const GLuint *value);
+ void programUniform4uiv(GLuint program, GLint location, GLsizei count, const GLuint *value);
+ void programUniform1fv(GLuint program, GLint location, GLsizei count, const GLfloat *value);
+ void programUniform2fv(GLuint program, GLint location, GLsizei count, const GLfloat *value);
+ void programUniform3fv(GLuint program, GLint location, GLsizei count, const GLfloat *value);
+ void programUniform4fv(GLuint program, GLint location, GLsizei count, const GLfloat *value);
+
+ void programUniformMatrix2fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+
+ void programUniformMatrix3fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+
+ void programUniformMatrix4fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+
+ void programUniformMatrix2x3fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+
+ void programUniformMatrix3x2fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+
+ void programUniformMatrix2x4fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+
+ void programUniformMatrix4x2fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+
+ void programUniformMatrix3x4fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+
+ void programUniformMatrix4x3fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+
+ void deleteProgramPipelines(GLsizei n, const GLuint *pipelines);
+ void genProgramPipelines(GLsizei n, GLuint *pipelines);
+ GLboolean isProgramPipeline(GLuint pipeline);
+
+ // Consumes the error.
+ void handleError(const Error &error) override;
GLenum getError();
+ void markContextLost();
+ bool isContextLost();
GLenum getResetStatus();
- virtual bool isResetNotificationEnabled();
+ bool isResetNotificationEnabled();
const egl::Config *getConfig() const;
EGLenum getClientType() const;
EGLenum getRenderBuffer() const;
- const std::string &getRendererString() const;
+ const GLubyte *getString(GLenum name) const;
+ const GLubyte *getStringi(GLenum name, GLuint index) const;
- const std::string &getExtensionString() const;
- const std::string &getExtensionString(size_t idx) const;
size_t getExtensionStringCount() const;
- rx::Renderer *getRenderer() { return mRenderer; }
+ bool isExtensionRequestable(const char *name);
+ void requestExtension(const char *name);
+ size_t getRequestableExtensionStringCount() const;
- State &getState() { return mState; }
+ rx::ContextImpl *getImplementation() const { return mImplementation.get(); }
+ const Workarounds &getWorkarounds() const;
- void syncRendererState();
- void syncRendererState(const State::DirtyBits &bitMask);
+ void getFramebufferParameteriv(GLenum target, GLenum pname, GLint *params);
+ void framebufferParameteri(GLenum target, GLenum pname, GLint param);
+
+ Error getScratchBuffer(size_t requestedSizeBytes, angle::MemoryBuffer **scratchBufferOut) const;
+ Error getZeroFilledBuffer(size_t requstedSizeBytes, angle::MemoryBuffer **zeroBufferOut) const;
+
+ void dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ);
+ void dispatchComputeIndirect(GLintptr indirect);
+
+ MemoryProgramCache *getMemoryProgramCache() const { return mMemoryProgramCache; }
+
+ template <EntryPoint EP, typename... ParamsT>
+ void gatherParams(ParamsT &&... params);
+
+ void texStorage2D(GLenum target,
+ GLsizei levels,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height);
+ void texStorage3D(GLenum target,
+ GLsizei levels,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+
+ void memoryBarrier(GLbitfield barriers);
+ void memoryBarrierByRegion(GLbitfield barriers);
+
+ // Notification for a state change in a Texture.
+ void onTextureChange(const Texture *texture);
+
+ egl::Display *getCurrentDisplay() const { return mCurrentDisplay; }
+ egl::Surface *getCurrentDrawSurface() const { return mCurrentSurface; }
+ egl::Surface *getCurrentReadSurface() const { return mCurrentSurface; }
+
+ bool isRobustResourceInitEnabled() const { return mGLState.isRobustResourceInitEnabled(); }
private:
- void checkVertexArrayAllocation(GLuint vertexArray);
- void checkTransformFeedbackAllocation(GLuint transformFeedback);
- Framebuffer *checkFramebufferAllocation(GLuint framebufferHandle);
+ Error prepareForDraw();
+ void syncRendererState();
+ void syncRendererState(const State::DirtyBits &bitMask, const State::DirtyObjects &objectMask);
+ void syncStateForReadPixels();
+ void syncStateForTexImage();
+ void syncStateForClear();
+ void syncStateForBlit();
+ VertexArray *checkVertexArrayAllocation(GLuint vertexArrayHandle);
+ TransformFeedback *checkTransformFeedbackAllocation(GLuint transformFeedback);
void detachBuffer(GLuint buffer);
void detachTexture(GLuint texture);
@@ -328,11 +1046,20 @@ class Context final : public ValidationContext
void detachVertexArray(GLuint vertexArray);
void detachTransformFeedback(GLuint transformFeedback);
void detachSampler(GLuint sampler);
+ void detachProgramPipeline(GLuint pipeline);
void initRendererString();
+ void initVersionStrings();
void initExtensionStrings();
- void initCaps(GLuint clientVersion);
+ void initCaps(const egl::DisplayExtensions &displayExtensions, bool robustResourceInit);
+ void updateCaps();
+ void initWorkarounds();
+
+ LabeledObject *getLabeledObject(GLenum identifier, GLuint name) const;
+ LabeledObject *getLabeledObjectFromPtr(const void *ptr) const;
+
+ std::unique_ptr<rx::ContextImpl> mImplementation;
// Caps to use for validation
Caps mCaps;
@@ -340,42 +1067,35 @@ class Context final : public ValidationContext
Extensions mExtensions;
Limitations mLimitations;
- // Shader compiler
- Compiler *mCompiler;
-
- rx::Renderer *const mRenderer;
- State mState;
+ // Shader compiler. Lazily initialized hence the mutable value.
+ mutable BindingPointer<Compiler> mCompiler;
- int mClientVersion;
+ State mGLState;
const egl::Config *mConfig;
EGLenum mClientType;
TextureMap mZeroTextures;
- typedef std::map<GLuint, Framebuffer*> FramebufferMap;
- FramebufferMap mFramebufferMap;
- HandleAllocator mFramebufferHandleAllocator;
-
- typedef std::map<GLuint, FenceNV*> FenceNVMap;
- FenceNVMap mFenceNVMap;
+ ResourceMap<FenceNV> mFenceNVMap;
HandleAllocator mFenceNVHandleAllocator;
- typedef std::map<GLuint, Query*> QueryMap;
- QueryMap mQueryMap;
+ ResourceMap<Query> mQueryMap;
HandleAllocator mQueryHandleAllocator;
- typedef std::map<GLuint, VertexArray*> VertexArrayMap;
- VertexArrayMap mVertexArrayMap;
+ ResourceMap<VertexArray> mVertexArrayMap;
HandleAllocator mVertexArrayHandleAllocator;
- typedef std::map<GLuint, TransformFeedback*> TransformFeedbackMap;
- TransformFeedbackMap mTransformFeedbackMap;
- HandleAllocator mTransformFeedbackAllocator;
+ ResourceMap<TransformFeedback> mTransformFeedbackMap;
+ HandleAllocator mTransformFeedbackHandleAllocator;
- std::string mRendererString;
- std::string mExtensionString;
- std::vector<std::string> mExtensionStrings;
+ const char *mVersionString;
+ const char *mShadingLanguageString;
+ const char *mRendererString;
+ const char *mExtensionString;
+ std::vector<const char *> mExtensionStrings;
+ const char *mRequestableExtensionString;
+ std::vector<const char *> mRequestableExtensionStrings;
// Recorded errors
typedef std::set<GLenum> ErrorSet;
@@ -385,13 +1105,50 @@ class Context final : public ValidationContext
bool mHasBeenCurrent;
bool mContextLost;
GLenum mResetStatus;
+ bool mContextLostForced;
GLenum mResetStrategy;
bool mRobustAccess;
egl::Surface *mCurrentSurface;
-
- ResourceManager *mResourceManager;
+ egl::Display *mCurrentDisplay;
+ Framebuffer *mSurfacelessFramebuffer;
+ bool mWebGLContext;
+ MemoryProgramCache *mMemoryProgramCache;
+
+ State::DirtyBits mTexImageDirtyBits;
+ State::DirtyObjects mTexImageDirtyObjects;
+ State::DirtyBits mReadPixelsDirtyBits;
+ State::DirtyObjects mReadPixelsDirtyObjects;
+ State::DirtyBits mClearDirtyBits;
+ State::DirtyObjects mClearDirtyObjects;
+ State::DirtyBits mBlitDirtyBits;
+ State::DirtyObjects mBlitDirtyObjects;
+
+ Workarounds mWorkarounds;
+
+ // Not really a property of context state. The size and contexts change per-api-call.
+ mutable angle::ScratchBuffer mScratchBuffer;
+ mutable angle::ScratchBuffer mZeroFilledBuffer;
};
+template <EntryPoint EP, typename... ArgsT>
+ANGLE_INLINE void Context::gatherParams(ArgsT &&... args)
+{
+ static_assert(sizeof(EntryPointParamType<EP>) <= kParamsBufferSize,
+ "Params struct too large, please increase kParamsBufferSize.");
+
+ mSavedArgsType = &EntryPointParamType<EP>::TypeInfo;
+
+ // Skip doing any work for ParamsBase/Invalid type.
+ if (!EntryPointParamType<EP>::TypeInfo.isValid())
+ {
+ return;
+ }
+
+ EntryPointParamType<EP> *objBuffer =
+ reinterpret_cast<EntryPointParamType<EP> *>(mParamsBuffer.data());
+ EntryPointParamType<EP>::template Factory<EP>(objBuffer, this, std::forward<ArgsT>(args)...);
+}
+
} // namespace gl
-#endif // LIBANGLE_CONTEXT_H_
+#endif // LIBANGLE_CONTEXT_H_
diff --git a/src/3rdparty/angle/src/libANGLE/ContextState.cpp b/src/3rdparty/angle/src/libANGLE/ContextState.cpp
new file mode 100644
index 0000000000..d109cca76d
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/ContextState.cpp
@@ -0,0 +1,839 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Data.cpp: Container class for all GL relevant state, caps and objects
+
+#include "libANGLE/ContextState.h"
+
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/ResourceManager.h"
+
+namespace gl
+{
+
+namespace
+{
+
+template <typename T>
+using ContextStateMember = T *(ContextState::*);
+
+template <typename T>
+T *AllocateOrGetSharedResourceManager(const ContextState *shareContextState,
+ ContextStateMember<T> member)
+{
+ if (shareContextState)
+ {
+ T *resourceManager = (*shareContextState).*member;
+ resourceManager->addRef();
+ return resourceManager;
+ }
+ else
+ {
+ return new T();
+ }
+}
+
+TextureManager *AllocateOrGetSharedTextureManager(const ContextState *shareContextState,
+ TextureManager *shareTextures,
+ ContextStateMember<TextureManager> member)
+{
+ if (shareContextState)
+ {
+ TextureManager *textureManager = (*shareContextState).*member;
+ ASSERT(shareTextures == nullptr || textureManager == shareTextures);
+ textureManager->addRef();
+ return textureManager;
+ }
+ else if (shareTextures)
+ {
+ TextureManager *textureManager = shareTextures;
+ textureManager->addRef();
+ return textureManager;
+ }
+ else
+ {
+ return new TextureManager();
+ }
+}
+
+} // anonymous namespace
+
+ContextState::ContextState(ContextID contextIn,
+ const ContextState *shareContextState,
+ TextureManager *shareTextures,
+ const Version &clientVersion,
+ State *stateIn,
+ const Caps &capsIn,
+ const TextureCapsMap &textureCapsIn,
+ const Extensions &extensionsIn,
+ const Limitations &limitationsIn)
+ : mClientVersion(clientVersion),
+ mContext(contextIn),
+ mState(stateIn),
+ mCaps(capsIn),
+ mTextureCaps(textureCapsIn),
+ mExtensions(extensionsIn),
+ mLimitations(limitationsIn),
+ mBuffers(AllocateOrGetSharedResourceManager(shareContextState, &ContextState::mBuffers)),
+ mShaderPrograms(
+ AllocateOrGetSharedResourceManager(shareContextState, &ContextState::mShaderPrograms)),
+ mTextures(AllocateOrGetSharedTextureManager(shareContextState,
+ shareTextures,
+ &ContextState::mTextures)),
+ mRenderbuffers(
+ AllocateOrGetSharedResourceManager(shareContextState, &ContextState::mRenderbuffers)),
+ mSamplers(AllocateOrGetSharedResourceManager(shareContextState, &ContextState::mSamplers)),
+ mSyncs(AllocateOrGetSharedResourceManager(shareContextState, &ContextState::mSyncs)),
+ mPaths(AllocateOrGetSharedResourceManager(shareContextState, &ContextState::mPaths)),
+ mFramebuffers(new FramebufferManager()),
+ mPipelines(new ProgramPipelineManager())
+{
+}
+
+ContextState::~ContextState()
+{
+ // Handles are released by the Context.
+}
+
+bool ContextState::isWebGL() const
+{
+ return mExtensions.webglCompatibility;
+}
+
+bool ContextState::isWebGL1() const
+{
+ return (isWebGL() && mClientVersion.major == 2);
+}
+
+const TextureCaps &ContextState::getTextureCap(GLenum internalFormat) const
+{
+ return mTextureCaps.get(internalFormat);
+}
+
+ValidationContext::ValidationContext(const ValidationContext *shareContext,
+ TextureManager *shareTextures,
+ const Version &clientVersion,
+ State *state,
+ const Caps &caps,
+ const TextureCapsMap &textureCaps,
+ const Extensions &extensions,
+ const Limitations &limitations,
+ bool skipValidation)
+ : mState(reinterpret_cast<ContextID>(this),
+ shareContext ? &shareContext->mState : nullptr,
+ shareTextures,
+ clientVersion,
+ state,
+ caps,
+ textureCaps,
+ extensions,
+ limitations),
+ mSkipValidation(skipValidation),
+ mDisplayTextureShareGroup(shareTextures != nullptr)
+{
+}
+
+ValidationContext::~ValidationContext()
+{
+}
+
+bool ValidationContext::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
+{
+ // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
+ // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
+ // to the fact that it is stored internally as a float, and so would require conversion
+ // if returned from Context::getIntegerv. Since this conversion is already implemented
+ // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
+ // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
+ // application.
+ switch (pname)
+ {
+ case GL_COMPRESSED_TEXTURE_FORMATS:
+ {
+ *type = GL_INT;
+ *numParams = static_cast<unsigned int>(getCaps().compressedTextureFormats.size());
+ return true;
+ }
+ case GL_SHADER_BINARY_FORMATS:
+ {
+ *type = GL_INT;
+ *numParams = static_cast<unsigned int>(getCaps().shaderBinaryFormats.size());
+ return true;
+ }
+
+ case GL_MAX_VERTEX_ATTRIBS:
+ case GL_MAX_VERTEX_UNIFORM_VECTORS:
+ case GL_MAX_VARYING_VECTORS:
+ case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
+ case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
+ case GL_MAX_TEXTURE_IMAGE_UNITS:
+ case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
+ case GL_MAX_RENDERBUFFER_SIZE:
+ case GL_NUM_SHADER_BINARY_FORMATS:
+ case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
+ case GL_ARRAY_BUFFER_BINDING:
+ case GL_FRAMEBUFFER_BINDING:
+ case GL_RENDERBUFFER_BINDING:
+ case GL_CURRENT_PROGRAM:
+ case GL_PACK_ALIGNMENT:
+ case GL_UNPACK_ALIGNMENT:
+ case GL_GENERATE_MIPMAP_HINT:
+ case GL_RED_BITS:
+ case GL_GREEN_BITS:
+ case GL_BLUE_BITS:
+ case GL_ALPHA_BITS:
+ case GL_DEPTH_BITS:
+ case GL_STENCIL_BITS:
+ case GL_ELEMENT_ARRAY_BUFFER_BINDING:
+ case GL_CULL_FACE_MODE:
+ case GL_FRONT_FACE:
+ case GL_ACTIVE_TEXTURE:
+ case GL_STENCIL_FUNC:
+ case GL_STENCIL_VALUE_MASK:
+ case GL_STENCIL_REF:
+ case GL_STENCIL_FAIL:
+ case GL_STENCIL_PASS_DEPTH_FAIL:
+ case GL_STENCIL_PASS_DEPTH_PASS:
+ case GL_STENCIL_BACK_FUNC:
+ case GL_STENCIL_BACK_VALUE_MASK:
+ case GL_STENCIL_BACK_REF:
+ case GL_STENCIL_BACK_FAIL:
+ case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
+ case GL_STENCIL_BACK_PASS_DEPTH_PASS:
+ case GL_DEPTH_FUNC:
+ case GL_BLEND_SRC_RGB:
+ case GL_BLEND_SRC_ALPHA:
+ case GL_BLEND_DST_RGB:
+ case GL_BLEND_DST_ALPHA:
+ case GL_BLEND_EQUATION_RGB:
+ case GL_BLEND_EQUATION_ALPHA:
+ case GL_STENCIL_WRITEMASK:
+ case GL_STENCIL_BACK_WRITEMASK:
+ case GL_STENCIL_CLEAR_VALUE:
+ case GL_SUBPIXEL_BITS:
+ case GL_MAX_TEXTURE_SIZE:
+ case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
+ case GL_SAMPLE_BUFFERS:
+ case GL_SAMPLES:
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+ case GL_TEXTURE_BINDING_2D:
+ case GL_TEXTURE_BINDING_CUBE_MAP:
+ case GL_RESET_NOTIFICATION_STRATEGY_EXT:
+ {
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
+ {
+ if (!getExtensions().packReverseRowOrder)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ case GL_MAX_RECTANGLE_TEXTURE_SIZE_ANGLE:
+ case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
+ {
+ if (!getExtensions().textureRectangle)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ case GL_MAX_DRAW_BUFFERS_EXT:
+ case GL_MAX_COLOR_ATTACHMENTS_EXT:
+ {
+ if ((getClientMajorVersion() < 3) && !getExtensions().drawBuffers)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ case GL_MAX_VIEWPORT_DIMS:
+ {
+ *type = GL_INT;
+ *numParams = 2;
+ return true;
+ }
+ case GL_VIEWPORT:
+ case GL_SCISSOR_BOX:
+ {
+ *type = GL_INT;
+ *numParams = 4;
+ return true;
+ }
+ case GL_SHADER_COMPILER:
+ case GL_SAMPLE_COVERAGE_INVERT:
+ case GL_DEPTH_WRITEMASK:
+ case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled,
+ case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries.
+ case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as
+ // bool-natural
+ case GL_SAMPLE_COVERAGE:
+ case GL_SCISSOR_TEST:
+ case GL_STENCIL_TEST:
+ case GL_DEPTH_TEST:
+ case GL_BLEND:
+ case GL_DITHER:
+ case GL_CONTEXT_ROBUST_ACCESS_EXT:
+ {
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+ case GL_COLOR_WRITEMASK:
+ {
+ *type = GL_BOOL;
+ *numParams = 4;
+ return true;
+ }
+ case GL_POLYGON_OFFSET_FACTOR:
+ case GL_POLYGON_OFFSET_UNITS:
+ case GL_SAMPLE_COVERAGE_VALUE:
+ case GL_DEPTH_CLEAR_VALUE:
+ case GL_LINE_WIDTH:
+ {
+ *type = GL_FLOAT;
+ *numParams = 1;
+ return true;
+ }
+ case GL_ALIASED_LINE_WIDTH_RANGE:
+ case GL_ALIASED_POINT_SIZE_RANGE:
+ case GL_DEPTH_RANGE:
+ {
+ *type = GL_FLOAT;
+ *numParams = 2;
+ return true;
+ }
+ case GL_COLOR_CLEAR_VALUE:
+ case GL_BLEND_COLOR:
+ {
+ *type = GL_FLOAT;
+ *numParams = 4;
+ return true;
+ }
+ case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (!getExtensions().textureFilterAnisotropic)
+ {
+ return false;
+ }
+ *type = GL_FLOAT;
+ *numParams = 1;
+ return true;
+ case GL_TIMESTAMP_EXT:
+ if (!getExtensions().disjointTimerQuery)
+ {
+ return false;
+ }
+ *type = GL_INT_64_ANGLEX;
+ *numParams = 1;
+ return true;
+ case GL_GPU_DISJOINT_EXT:
+ if (!getExtensions().disjointTimerQuery)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_COVERAGE_MODULATION_CHROMIUM:
+ if (!getExtensions().framebufferMixedSamples)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_TEXTURE_BINDING_EXTERNAL_OES:
+ if (!getExtensions().eglStreamConsumerExternal && !getExtensions().eglImageExternal)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+
+ if (getExtensions().debug)
+ {
+ switch (pname)
+ {
+ case GL_DEBUG_LOGGED_MESSAGES:
+ case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH:
+ case GL_DEBUG_GROUP_STACK_DEPTH:
+ case GL_MAX_DEBUG_MESSAGE_LENGTH:
+ case GL_MAX_DEBUG_LOGGED_MESSAGES:
+ case GL_MAX_DEBUG_GROUP_STACK_DEPTH:
+ case GL_MAX_LABEL_LENGTH:
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+
+ case GL_DEBUG_OUTPUT_SYNCHRONOUS:
+ case GL_DEBUG_OUTPUT:
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (getExtensions().multisampleCompatibility)
+ {
+ switch (pname)
+ {
+ case GL_MULTISAMPLE_EXT:
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (getExtensions().pathRendering)
+ {
+ switch (pname)
+ {
+ case GL_PATH_MODELVIEW_MATRIX_CHROMIUM:
+ case GL_PATH_PROJECTION_MATRIX_CHROMIUM:
+ *type = GL_FLOAT;
+ *numParams = 16;
+ return true;
+ }
+ }
+
+ if (getExtensions().bindGeneratesResource)
+ {
+ switch (pname)
+ {
+ case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (getExtensions().clientArrays)
+ {
+ switch (pname)
+ {
+ case GL_CLIENT_ARRAYS_ANGLE:
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (getExtensions().sRGBWriteControl)
+ {
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_SRGB_EXT:
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (getExtensions().robustResourceInitialization &&
+ pname == GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE)
+ {
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+
+ if (getExtensions().programCacheControl && pname == GL_PROGRAM_CACHE_ENABLED_ANGLE)
+ {
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+
+ // Check for ES3.0+ parameter names which are also exposed as ES2 extensions
+ switch (pname)
+ {
+ // case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE // equivalent to FRAMEBUFFER_BINDING
+ case GL_READ_FRAMEBUFFER_BINDING_ANGLE:
+ if ((getClientMajorVersion() < 3) && !getExtensions().framebufferBlit)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+
+ case GL_NUM_PROGRAM_BINARY_FORMATS_OES:
+ if ((getClientMajorVersion() < 3) && !getExtensions().getProgramBinary)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+
+ case GL_PROGRAM_BINARY_FORMATS_OES:
+ if ((getClientMajorVersion() < 3) && !getExtensions().getProgramBinary)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = static_cast<unsigned int>(getCaps().programBinaryFormats.size());
+ return true;
+
+ case GL_PACK_ROW_LENGTH:
+ case GL_PACK_SKIP_ROWS:
+ case GL_PACK_SKIP_PIXELS:
+ if ((getClientMajorVersion() < 3) && !getExtensions().packSubimage)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_UNPACK_ROW_LENGTH:
+ case GL_UNPACK_SKIP_ROWS:
+ case GL_UNPACK_SKIP_PIXELS:
+ if ((getClientMajorVersion() < 3) && !getExtensions().unpackSubimage)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_VERTEX_ARRAY_BINDING:
+ if ((getClientMajorVersion() < 3) && !getExtensions().vertexArrayObject)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_PIXEL_PACK_BUFFER_BINDING:
+ case GL_PIXEL_UNPACK_BUFFER_BINDING:
+ if ((getClientMajorVersion() < 3) && !getExtensions().pixelBufferObject)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_MAX_SAMPLES:
+ {
+ static_assert(GL_MAX_SAMPLES_ANGLE == GL_MAX_SAMPLES,
+ "GL_MAX_SAMPLES_ANGLE not equal to GL_MAX_SAMPLES");
+ if ((getClientMajorVersion() < 3) && !getExtensions().framebufferMultisample)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+
+ case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
+ if ((getClientMajorVersion() < 3) && !getExtensions().standardDerivatives)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT)
+ {
+ if ((getClientVersion() < Version(3, 0)) && !getExtensions().drawBuffers)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+
+ if (getExtensions().multiview && pname == GL_MAX_VIEWS_ANGLE)
+ {
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+
+ if (getClientVersion() < Version(3, 0))
+ {
+ return false;
+ }
+
+ // Check for ES3.0+ parameter names
+ switch (pname)
+ {
+ case GL_MAX_UNIFORM_BUFFER_BINDINGS:
+ case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
+ case GL_UNIFORM_BUFFER_BINDING:
+ case GL_TRANSFORM_FEEDBACK_BINDING:
+ case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ case GL_COPY_READ_BUFFER_BINDING:
+ case GL_COPY_WRITE_BUFFER_BINDING:
+ case GL_SAMPLER_BINDING:
+ case GL_READ_BUFFER:
+ case GL_TEXTURE_BINDING_3D:
+ case GL_TEXTURE_BINDING_2D_ARRAY:
+ case GL_MAX_3D_TEXTURE_SIZE:
+ case GL_MAX_ARRAY_TEXTURE_LAYERS:
+ case GL_MAX_VERTEX_UNIFORM_BLOCKS:
+ case GL_MAX_FRAGMENT_UNIFORM_BLOCKS:
+ case GL_MAX_COMBINED_UNIFORM_BLOCKS:
+ case GL_MAX_VERTEX_OUTPUT_COMPONENTS:
+ case GL_MAX_FRAGMENT_INPUT_COMPONENTS:
+ case GL_MAX_VARYING_COMPONENTS:
+ case GL_MAX_VERTEX_UNIFORM_COMPONENTS:
+ case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:
+ case GL_MIN_PROGRAM_TEXEL_OFFSET:
+ case GL_MAX_PROGRAM_TEXEL_OFFSET:
+ case GL_NUM_EXTENSIONS:
+ case GL_MAJOR_VERSION:
+ case GL_MINOR_VERSION:
+ case GL_MAX_ELEMENTS_INDICES:
+ case GL_MAX_ELEMENTS_VERTICES:
+ case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS:
+ case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
+ case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS:
+ case GL_UNPACK_IMAGE_HEIGHT:
+ case GL_UNPACK_SKIP_IMAGES:
+ {
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+
+ case GL_MAX_ELEMENT_INDEX:
+ case GL_MAX_UNIFORM_BLOCK_SIZE:
+ case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS:
+ case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS:
+ case GL_MAX_SERVER_WAIT_TIMEOUT:
+ {
+ *type = GL_INT_64_ANGLEX;
+ *numParams = 1;
+ return true;
+ }
+
+ case GL_TRANSFORM_FEEDBACK_ACTIVE:
+ case GL_TRANSFORM_FEEDBACK_PAUSED:
+ case GL_PRIMITIVE_RESTART_FIXED_INDEX:
+ case GL_RASTERIZER_DISCARD:
+ {
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+
+ case GL_MAX_TEXTURE_LOD_BIAS:
+ {
+ *type = GL_FLOAT;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (getExtensions().requestExtension)
+ {
+ switch (pname)
+ {
+ case GL_NUM_REQUESTABLE_EXTENSIONS_ANGLE:
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (getClientVersion() < Version(3, 1))
+ {
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+ case GL_DRAW_INDIRECT_BUFFER_BINDING:
+ case GL_MAX_FRAMEBUFFER_WIDTH:
+ case GL_MAX_FRAMEBUFFER_HEIGHT:
+ case GL_MAX_FRAMEBUFFER_SAMPLES:
+ case GL_MAX_SAMPLE_MASK_WORDS:
+ case GL_MAX_COLOR_TEXTURE_SAMPLES:
+ case GL_MAX_DEPTH_TEXTURE_SAMPLES:
+ case GL_MAX_INTEGER_SAMPLES:
+ case GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET:
+ case GL_MAX_VERTEX_ATTRIB_BINDINGS:
+ case GL_MAX_VERTEX_ATTRIB_STRIDE:
+ case GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS:
+ case GL_MAX_VERTEX_ATOMIC_COUNTERS:
+ case GL_MAX_VERTEX_IMAGE_UNIFORMS:
+ case GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS:
+ case GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS:
+ case GL_MAX_FRAGMENT_ATOMIC_COUNTERS:
+ case GL_MAX_FRAGMENT_IMAGE_UNIFORMS:
+ case GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS:
+ case GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET:
+ case GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET:
+ case GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS:
+ case GL_MAX_COMPUTE_UNIFORM_BLOCKS:
+ case GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS:
+ case GL_MAX_COMPUTE_SHARED_MEMORY_SIZE:
+ case GL_MAX_COMPUTE_UNIFORM_COMPONENTS:
+ case GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS:
+ case GL_MAX_COMPUTE_ATOMIC_COUNTERS:
+ case GL_MAX_COMPUTE_IMAGE_UNIFORMS:
+ case GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS:
+ case GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS:
+ case GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES:
+ case GL_MAX_UNIFORM_LOCATIONS:
+ case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS:
+ case GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE:
+ case GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS:
+ case GL_MAX_COMBINED_ATOMIC_COUNTERS:
+ case GL_MAX_IMAGE_UNITS:
+ case GL_MAX_COMBINED_IMAGE_UNIFORMS:
+ case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
+ case GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS:
+ case GL_SHADER_STORAGE_BUFFER_BINDING:
+ case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
+ case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_MAX_SHADER_STORAGE_BLOCK_SIZE:
+ *type = GL_INT_64_ANGLEX;
+ *numParams = 1;
+ return true;
+ case GL_SAMPLE_MASK:
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+
+ return false;
+}
+
+bool ValidationContext::getIndexedQueryParameterInfo(GLenum target,
+ GLenum *type,
+ unsigned int *numParams)
+{
+ if (getClientVersion() < Version(3, 0))
+ {
+ return false;
+ }
+
+ switch (target)
+ {
+ case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ case GL_UNIFORM_BUFFER_BINDING:
+ {
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ case GL_TRANSFORM_FEEDBACK_BUFFER_START:
+ case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
+ case GL_UNIFORM_BUFFER_START:
+ case GL_UNIFORM_BUFFER_SIZE:
+ {
+ *type = GL_INT_64_ANGLEX;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (getClientVersion() < Version(3, 1))
+ {
+ return false;
+ }
+
+ switch (target)
+ {
+ case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
+ case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
+ case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+ case GL_SHADER_STORAGE_BUFFER_BINDING:
+ case GL_VERTEX_BINDING_BUFFER:
+ case GL_VERTEX_BINDING_DIVISOR:
+ case GL_VERTEX_BINDING_OFFSET:
+ case GL_VERTEX_BINDING_STRIDE:
+ case GL_SAMPLE_MASK_VALUE:
+ {
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ case GL_ATOMIC_COUNTER_BUFFER_START:
+ case GL_ATOMIC_COUNTER_BUFFER_SIZE:
+ case GL_SHADER_STORAGE_BUFFER_START:
+ case GL_SHADER_STORAGE_BUFFER_SIZE:
+ {
+ *type = GL_INT_64_ANGLEX;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+Program *ValidationContext::getProgram(GLuint handle) const
+{
+ return mState.mShaderPrograms->getProgram(handle);
+}
+
+Shader *ValidationContext::getShader(GLuint handle) const
+{
+ return mState.mShaderPrograms->getShader(handle);
+}
+
+bool ValidationContext::isTextureGenerated(GLuint texture) const
+{
+ return mState.mTextures->isHandleGenerated(texture);
+}
+
+bool ValidationContext::isBufferGenerated(GLuint buffer) const
+{
+ return mState.mBuffers->isHandleGenerated(buffer);
+}
+
+bool ValidationContext::isRenderbufferGenerated(GLuint renderbuffer) const
+{
+ return mState.mRenderbuffers->isHandleGenerated(renderbuffer);
+}
+
+bool ValidationContext::isFramebufferGenerated(GLuint framebuffer) const
+{
+ return mState.mFramebuffers->isHandleGenerated(framebuffer);
+}
+
+bool ValidationContext::isProgramPipelineGenerated(GLuint pipeline) const
+{
+ return mState.mPipelines->isHandleGenerated(pipeline);
+}
+
+bool ValidationContext::usingDisplayTextureShareGroup() const
+{
+ return mDisplayTextureShareGroup;
+}
+
+GLenum ValidationContext::getConvertedRenderbufferFormat(GLenum internalformat) const
+{
+ return mState.mExtensions.webglCompatibility && mState.mClientVersion.major == 2 &&
+ internalformat == GL_DEPTH_STENCIL
+ ? GL_DEPTH24_STENCIL8
+ : internalformat;
+}
+
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/ContextState.h b/src/3rdparty/angle/src/libANGLE/ContextState.h
new file mode 100644
index 0000000000..e6e9f4c6b0
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/ContextState.h
@@ -0,0 +1,164 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ContextState: Container class for all GL context state, caps and objects.
+
+#ifndef LIBANGLE_CONTEXTSTATE_H_
+#define LIBANGLE_CONTEXTSTATE_H_
+
+#include "common/MemoryBuffer.h"
+#include "common/angleutils.h"
+#include "libANGLE/State.h"
+#include "libANGLE/Version.h"
+#include "libANGLE/params.h"
+
+namespace gl
+{
+class BufferManager;
+class ContextState;
+class FramebufferManager;
+class PathManager;
+class ProgramPipelineManager;
+class RenderbufferManager;
+class SamplerManager;
+class ShaderProgramManager;
+class SyncManager;
+class TextureManager;
+class ValidationContext;
+
+static constexpr Version ES_2_0 = Version(2, 0);
+static constexpr Version ES_3_0 = Version(3, 0);
+static constexpr Version ES_3_1 = Version(3, 1);
+
+using ContextID = uintptr_t;
+
+class ContextState final : angle::NonCopyable
+{
+ public:
+ ContextState(ContextID context,
+ const ContextState *shareContextState,
+ TextureManager *shareTextures,
+ const Version &clientVersion,
+ State *state,
+ const Caps &caps,
+ const TextureCapsMap &textureCaps,
+ const Extensions &extensions,
+ const Limitations &limitations);
+ ~ContextState();
+
+ ContextID getContextID() const { return mContext; }
+ GLint getClientMajorVersion() const { return mClientVersion.major; }
+ GLint getClientMinorVersion() const { return mClientVersion.minor; }
+ const Version &getClientVersion() const { return mClientVersion; }
+ const State &getState() const { return *mState; }
+ const Caps &getCaps() const { return mCaps; }
+ const TextureCapsMap &getTextureCaps() const { return mTextureCaps; }
+ const Extensions &getExtensions() const { return mExtensions; }
+ const Limitations &getLimitations() const { return mLimitations; }
+
+ const TextureCaps &getTextureCap(GLenum internalFormat) const;
+
+ bool usingDisplayTextureShareGroup() const;
+
+ bool isWebGL() const;
+ bool isWebGL1() const;
+
+ private:
+ friend class Context;
+ friend class ValidationContext;
+
+ Version mClientVersion;
+ ContextID mContext;
+ State *mState;
+ const Caps &mCaps;
+ const TextureCapsMap &mTextureCaps;
+ const Extensions &mExtensions;
+ const Limitations &mLimitations;
+
+ BufferManager *mBuffers;
+ ShaderProgramManager *mShaderPrograms;
+ TextureManager *mTextures;
+ RenderbufferManager *mRenderbuffers;
+ SamplerManager *mSamplers;
+ SyncManager *mSyncs;
+ PathManager *mPaths;
+ FramebufferManager *mFramebuffers;
+ ProgramPipelineManager *mPipelines;
+};
+
+class ValidationContext : angle::NonCopyable
+{
+ public:
+ ValidationContext(const ValidationContext *shareContext,
+ TextureManager *shareTextures,
+ const Version &clientVersion,
+ State *state,
+ const Caps &caps,
+ const TextureCapsMap &textureCaps,
+ const Extensions &extensions,
+ const Limitations &limitations,
+ bool skipValidation);
+ virtual ~ValidationContext();
+
+ virtual void handleError(const Error &error) = 0;
+
+ const ContextState &getContextState() const { return mState; }
+ GLint getClientMajorVersion() const { return mState.getClientMajorVersion(); }
+ GLint getClientMinorVersion() const { return mState.getClientMinorVersion(); }
+ const Version &getClientVersion() const { return mState.getClientVersion(); }
+ const State &getGLState() const { return mState.getState(); }
+ const Caps &getCaps() const { return mState.getCaps(); }
+ const TextureCapsMap &getTextureCaps() const { return mState.getTextureCaps(); }
+ const Extensions &getExtensions() const { return mState.getExtensions(); }
+ const Limitations &getLimitations() const { return mState.getLimitations(); }
+ bool skipValidation() const { return mSkipValidation; }
+
+ // Specific methods needed for validation.
+ bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams);
+ bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams);
+
+ Program *getProgram(GLuint handle) const;
+ Shader *getShader(GLuint handle) const;
+
+ bool isTextureGenerated(GLuint texture) const;
+ bool isBufferGenerated(GLuint buffer) const;
+ bool isRenderbufferGenerated(GLuint renderbuffer) const;
+ bool isFramebufferGenerated(GLuint framebuffer) const;
+ bool isProgramPipelineGenerated(GLuint pipeline) const;
+
+ bool usingDisplayTextureShareGroup() const;
+
+ // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
+ GLenum getConvertedRenderbufferFormat(GLenum internalformat) const;
+
+ bool isWebGL() const { return mState.isWebGL(); }
+ bool isWebGL1() const { return mState.isWebGL1(); }
+
+ template <typename T>
+ const T &getParams() const;
+
+ protected:
+ ContextState mState;
+ bool mSkipValidation;
+ bool mDisplayTextureShareGroup;
+
+ // Caches entry point parameters and values re-used between layers.
+ mutable const ParamTypeInfo *mSavedArgsType;
+ static constexpr size_t kParamsBufferSize = 64u;
+ mutable std::array<uint8_t, kParamsBufferSize> mParamsBuffer;
+};
+
+template <typename T>
+const T &ValidationContext::getParams() const
+{
+ const T *params = reinterpret_cast<T *>(mParamsBuffer.data());
+ ASSERT(mSavedArgsType->hasDynamicType(T::TypeInfo));
+ return *params;
+}
+
+} // namespace gl
+
+#endif // LIBANGLE_CONTEXTSTATE_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Data.cpp b/src/3rdparty/angle/src/libANGLE/Data.cpp
deleted file mode 100644
index 83f04b5a0b..0000000000
--- a/src/3rdparty/angle/src/libANGLE/Data.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Data.cpp: Container class for all GL relevant state, caps and objects
-
-#include "libANGLE/Data.h"
-#include "libANGLE/ResourceManager.h"
-
-namespace gl
-{
-
-Data::Data(uintptr_t contextIn,
- GLint clientVersionIn,
- const State &stateIn,
- const Caps &capsIn,
- const TextureCapsMap &textureCapsIn,
- const Extensions &extensionsIn,
- const ResourceManager *resourceManagerIn,
- const Limitations &limitationsIn)
- : context(contextIn),
- clientVersion(clientVersionIn),
- state(&stateIn),
- caps(&capsIn),
- textureCaps(&textureCapsIn),
- extensions(&extensionsIn),
- resourceManager(resourceManagerIn),
- limitations(&limitationsIn)
-{}
-
-Data::~Data()
-{
-}
-
-ValidationContext::ValidationContext(GLint clientVersion,
- const State &state,
- const Caps &caps,
- const TextureCapsMap &textureCaps,
- const Extensions &extensions,
- const ResourceManager *resourceManager,
- const Limitations &limitations,
- bool skipValidation)
- : mData(reinterpret_cast<uintptr_t>(this),
- clientVersion,
- state,
- caps,
- textureCaps,
- extensions,
- resourceManager,
- limitations),
- mSkipValidation(skipValidation)
-{
-}
-} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/Data.h b/src/3rdparty/angle/src/libANGLE/Data.h
deleted file mode 100644
index f7230d74bc..0000000000
--- a/src/3rdparty/angle/src/libANGLE/Data.h
+++ /dev/null
@@ -1,72 +0,0 @@
-//
-// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Data.h: Container class for all GL relevant state, caps and objects
-
-#ifndef LIBANGLE_DATA_H_
-#define LIBANGLE_DATA_H_
-
-#include "common/angleutils.h"
-#include "libANGLE/State.h"
-
-namespace gl
-{
-
-struct Data final : public angle::NonCopyable
-{
- public:
- Data(uintptr_t context,
- GLint clientVersion,
- const State &state,
- const Caps &caps,
- const TextureCapsMap &textureCaps,
- const Extensions &extensions,
- const ResourceManager *resourceManager,
- const Limitations &limitations);
- ~Data();
-
- uintptr_t context;
- GLint clientVersion;
- const State *state;
- const Caps *caps;
- const TextureCapsMap *textureCaps;
- const Extensions *extensions;
- const ResourceManager *resourceManager;
- const Limitations *limitations;
-};
-
-class ValidationContext : angle::NonCopyable
-{
- public:
- ValidationContext(GLint clientVersion,
- const State &state,
- const Caps &caps,
- const TextureCapsMap &textureCaps,
- const Extensions &extensions,
- const ResourceManager *resourceManager,
- const Limitations &limitations,
- bool skipValidation);
- virtual ~ValidationContext() {}
-
- virtual void recordError(const Error &error) = 0;
-
- const Data &getData() const { return mData; }
- int getClientVersion() const { return mData.clientVersion; }
- const State &getState() const { return *mData.state; }
- const Caps &getCaps() const { return *mData.caps; }
- const TextureCapsMap &getTextureCaps() const { return *mData.textureCaps; }
- const Extensions &getExtensions() const { return *mData.extensions; }
- const Limitations &getLimitations() const { return *mData.limitations; }
- bool skipValidation() const { return mSkipValidation; }
-
- protected:
- Data mData;
- bool mSkipValidation;
-};
-
-}
-
-#endif // LIBANGLE_DATA_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Debug.cpp b/src/3rdparty/angle/src/libANGLE/Debug.cpp
index 30321f4160..96f30df98c 100644
--- a/src/3rdparty/angle/src/libANGLE/Debug.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Debug.cpp
@@ -16,6 +16,26 @@
namespace gl
{
+Debug::Control::Control()
+{
+}
+
+Debug::Control::~Control()
+{
+}
+
+Debug::Control::Control(const Control &other) = default;
+
+Debug::Group::Group()
+{
+}
+
+Debug::Group::~Group()
+{
+}
+
+Debug::Group::Group(const Group &other) = default;
+
Debug::Debug()
: mOutputEnabled(false),
mCallbackFunction(nullptr),
@@ -28,6 +48,10 @@ Debug::Debug()
pushDefaultGroup();
}
+Debug::~Debug()
+{
+}
+
void Debug::setMaxLoggedMessages(GLuint maxLoggedMessages)
{
mMaxLoggedMessages = maxLoggedMessages;
diff --git a/src/3rdparty/angle/src/libANGLE/Debug.h b/src/3rdparty/angle/src/libANGLE/Debug.h
index f545b815e4..2c15c25e9a 100644
--- a/src/3rdparty/angle/src/libANGLE/Debug.h
+++ b/src/3rdparty/angle/src/libANGLE/Debug.h
@@ -31,6 +31,7 @@ class Debug : angle::NonCopyable
{
public:
Debug();
+ ~Debug();
void setMaxLoggedMessages(GLuint maxLoggedMessages);
@@ -91,6 +92,10 @@ class Debug : angle::NonCopyable
struct Control
{
+ Control();
+ ~Control();
+ Control(const Control &other);
+
GLenum source;
GLenum type;
GLenum severity;
@@ -100,6 +105,10 @@ class Debug : angle::NonCopyable
struct Group
{
+ Group();
+ ~Group();
+ Group(const Group &other);
+
GLenum source;
GLuint id;
std::string message;
diff --git a/src/3rdparty/angle/src/libANGLE/Device.cpp b/src/3rdparty/angle/src/libANGLE/Device.cpp
index eb30b2023f..3ebf48b919 100644
--- a/src/3rdparty/angle/src/libANGLE/Device.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Device.cpp
@@ -45,33 +45,28 @@ static DeviceSet *GetDeviceSet()
// Static factory methods
egl::Error Device::CreateDevice(void *devicePointer, EGLint deviceType, Device **outDevice)
{
+ *outDevice = nullptr;
+
#if defined(ANGLE_ENABLE_D3D11)
if (deviceType == EGL_D3D11_DEVICE_ANGLE)
{
- rx::DeviceD3D *deviceD3D = new rx::DeviceD3D();
- egl::Error error = deviceD3D->initialize(devicePointer, deviceType, EGL_TRUE);
- if (error.isError())
- {
- *outDevice = nullptr;
- return error;
- }
-
- *outDevice = new Device(nullptr, deviceD3D);
+ std::unique_ptr<rx::DeviceD3D> deviceD3D(new rx::DeviceD3D());
+ ANGLE_TRY(deviceD3D->initialize(devicePointer, deviceType, EGL_TRUE));
+ *outDevice = new Device(nullptr, deviceD3D.release());
GetDeviceSet()->insert(*outDevice);
- return egl::Error(EGL_SUCCESS);
+ return NoError();
}
#endif
// Note that creating an EGL device from inputted D3D9 parameters isn't currently supported
- *outDevice = nullptr;
- return egl::Error(EGL_BAD_ATTRIBUTE);
+ return EglBadAttribute();
}
egl::Error Device::CreateDevice(Display *owningDisplay, rx::DeviceImpl *impl, Device **outDevice)
{
*outDevice = new Device(owningDisplay, impl);
GetDeviceSet()->insert(*outDevice);
- return egl::Error(EGL_SUCCESS);
+ return NoError();
}
bool Device::IsValidDevice(Device *device)
diff --git a/src/3rdparty/angle/src/libANGLE/Display.cpp b/src/3rdparty/angle/src/libANGLE/Display.cpp
index 486c74abc0..735b472787 100644
--- a/src/3rdparty/angle/src/libANGLE/Display.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Display.cpp
@@ -28,6 +28,8 @@
#include "libANGLE/histogram_macros.h"
#include "libANGLE/Image.h"
#include "libANGLE/Surface.h"
+#include "libANGLE/Stream.h"
+#include "libANGLE/ResourceManager.h"
#include "libANGLE/renderer/DisplayImpl.h"
#include "libANGLE/renderer/ImageImpl.h"
#include "third_party/trace_event/trace_event.h"
@@ -43,38 +45,34 @@
# include "libANGLE/renderer/gl/glx/DisplayGLX.h"
# elif defined(ANGLE_PLATFORM_APPLE)
# include "libANGLE/renderer/gl/cgl/DisplayCGL.h"
+# elif defined(ANGLE_USE_OZONE)
+# include "libANGLE/renderer/gl/egl/ozone/DisplayOzone.h"
+# elif defined(ANGLE_PLATFORM_ANDROID)
+# include "libANGLE/renderer/gl/egl/android/DisplayAndroid.h"
# else
# error Unsupported OpenGL platform.
# endif
#endif
-namespace egl
-{
+#if defined(ANGLE_ENABLE_NULL)
+#include "libANGLE/renderer/null/DisplayNULL.h"
+#endif // defined(ANGLE_ENABLE_NULL)
-namespace
-{
+#if defined(ANGLE_ENABLE_VULKAN)
+#if defined(ANGLE_PLATFORM_WINDOWS)
+#include "libANGLE/renderer/vulkan/win32/DisplayVkWin32.h"
+#elif defined(ANGLE_PLATFORM_LINUX)
+#include "libANGLE/renderer/vulkan/xcb/DisplayVkXcb.h"
+#else
+#error Unsupported Vulkan platform.
+#endif
+#endif // defined(ANGLE_ENABLE_VULKAN)
-class DefaultPlatform : public angle::Platform
+namespace egl
{
-public:
- DefaultPlatform() {}
- ~DefaultPlatform() override {}
-};
-DefaultPlatform *defaultPlatform = nullptr;
-
-void InitDefaultPlatformImpl()
+namespace
{
- if (ANGLEPlatformCurrent() == nullptr)
- {
- if (defaultPlatform == nullptr)
- {
- defaultPlatform = new DefaultPlatform();
- }
-
- ANGLEPlatformInitialize(defaultPlatform);
- }
-}
typedef std::map<EGLNativeWindowType, Surface*> WindowSurfaceMap;
// Get a map of all EGL window surfaces to validate that no window has more than one EGL surface
@@ -99,7 +97,7 @@ static DevicePlatformDisplayMap *GetDevicePlatformDisplayMap()
return &displays;
}
-rx::DisplayImpl *CreateDisplayFromDevice(Device *eglDevice)
+rx::DisplayImpl *CreateDisplayFromDevice(Device *eglDevice, const DisplayState &state)
{
rx::DisplayImpl *impl = nullptr;
@@ -107,7 +105,7 @@ rx::DisplayImpl *CreateDisplayFromDevice(Device *eglDevice)
{
#if defined(ANGLE_ENABLE_D3D11)
case EGL_D3D11_DEVICE_ANGLE:
- impl = new rx::DisplayD3D();
+ impl = new rx::DisplayD3D(state);
break;
#endif
#if defined(ANGLE_ENABLE_D3D9)
@@ -130,86 +128,162 @@ rx::DisplayImpl *CreateDisplayFromDevice(Device *eglDevice)
return impl;
}
-rx::DisplayImpl *CreateDisplayFromAttribs(const AttributeMap &attribMap)
+rx::DisplayImpl *CreateDisplayFromAttribs(const AttributeMap &attribMap, const DisplayState &state)
{
rx::DisplayImpl *impl = nullptr;
- EGLint displayType = attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
+ EGLAttrib displayType =
+ attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
switch (displayType)
{
- case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
+ case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
- // Default to D3D displays
- impl = new rx::DisplayD3D();
+ // Default to D3D displays
+ impl = new rx::DisplayD3D(state);
#elif defined(ANGLE_USE_X11)
- impl = new rx::DisplayGLX();
+ impl = new rx::DisplayGLX(state);
#elif defined(ANGLE_PLATFORM_APPLE)
- impl = new rx::DisplayCGL();
+ impl = new rx::DisplayCGL(state);
+#elif defined(ANGLE_USE_OZONE)
+ impl = new rx::DisplayOzone(state);
+#elif defined(ANGLE_PLATFORM_ANDROID)
+ impl = new rx::DisplayAndroid(state);
#else
- // No display available
- UNREACHABLE();
+ // No display available
+ UNREACHABLE();
#endif
- break;
+ break;
- case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
- case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
+ case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
+ case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
- impl = new rx::DisplayD3D();
+ impl = new rx::DisplayD3D(state);
#else
- // A D3D display was requested on a platform that doesn't support it
- UNREACHABLE();
+ // A D3D display was requested on a platform that doesn't support it
+ UNREACHABLE();
#endif
- break;
+ break;
- case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
+ case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
#if defined(ANGLE_ENABLE_OPENGL)
#if defined(ANGLE_PLATFORM_WINDOWS)
- impl = new rx::DisplayWGL();
+ impl = new rx::DisplayWGL(state);
#elif defined(ANGLE_USE_X11)
- impl = new rx::DisplayGLX();
+ impl = new rx::DisplayGLX(state);
#elif defined(ANGLE_PLATFORM_APPLE)
- impl = new rx::DisplayCGL();
+ impl = new rx::DisplayCGL(state);
+#elif defined(ANGLE_USE_OZONE)
+ // This might work but has never been tried, so disallow for now.
+ impl = nullptr;
+#elif defined(ANGLE_PLATFORM_ANDROID)
+ // No GL support on this platform, fail display creation.
+ impl = nullptr;
#else
#error Unsupported OpenGL platform.
#endif
#else
- UNREACHABLE();
-#endif
- break;
+ // No display available
+ UNREACHABLE();
+#endif // defined(ANGLE_ENABLE_OPENGL)
+ break;
+ case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
#if defined(ANGLE_ENABLE_OPENGL)
- case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
#if defined(ANGLE_PLATFORM_WINDOWS)
- impl = new rx::DisplayWGL();
+ impl = new rx::DisplayWGL(state);
#elif defined(ANGLE_USE_X11)
- impl = new rx::DisplayGLX();
+ impl = new rx::DisplayGLX(state);
+#elif defined(ANGLE_USE_OZONE)
+ impl = new rx::DisplayOzone(state);
+#elif defined(ANGLE_PLATFORM_ANDROID)
+ impl = new rx::DisplayAndroid(state);
#else
- // No GLES support on this platform, fail display creation.
- impl = nullptr;
+ // No GLES support on this platform, fail display creation.
+ impl = nullptr;
#endif
- break;
+#endif // defined(ANGLE_ENABLE_OPENGL)
+ break;
+
+ case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
+#if defined(ANGLE_ENABLE_VULKAN)
+#if defined(ANGLE_PLATFORM_WINDOWS)
+ impl = new rx::DisplayVkWin32(state);
+#elif defined(ANGLE_PLATFORM_LINUX)
+ impl = new rx::DisplayVkXcb(state);
+#else
+#error Unsupported Vulkan platform.
#endif
+#else
+ // No display available
+ UNREACHABLE();
+#endif // defined(ANGLE_ENABLE_VULKAN)
+ break;
- default:
- UNREACHABLE();
- break;
+ case EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE:
+#if defined(ANGLE_ENABLE_NULL)
+ impl = new rx::DisplayNULL(state);
+#else
+ // No display available
+ UNREACHABLE();
+#endif // defined(ANGLE_ENABLE_NULL)
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
}
return impl;
}
+void Display_logError(angle::PlatformMethods *platform, const char *errorMessage)
+{
+ gl::Trace(gl::LOG_ERR, errorMessage);
}
-Display *Display::GetDisplayFromAttribs(void *native_display, const AttributeMap &attribMap)
+void Display_logWarning(angle::PlatformMethods *platform, const char *warningMessage)
{
- // Initialize the global platform if not already
- InitDefaultPlatformImpl();
+ gl::Trace(gl::LOG_WARN, warningMessage);
+}
- Display *display = nullptr;
+void Display_logInfo(angle::PlatformMethods *platform, const char *infoMessage)
+{
+ // Uncomment to get info spam
+ // gl::Trace(gl::LOG_WARN, infoMessage);
+}
+
+void ANGLESetDefaultDisplayPlatform(angle::EGLDisplayType display)
+{
+ angle::PlatformMethods *platformMethods = ANGLEPlatformCurrent();
+ if (platformMethods->logError != angle::DefaultLogError)
+ {
+ // Don't reset pre-set Platform to Default
+ return;
+ }
+
+ ANGLEResetDisplayPlatform(display);
+ platformMethods->logError = Display_logError;
+ platformMethods->logWarning = Display_logWarning;
+ platformMethods->logInfo = Display_logInfo;
+}
+
+} // anonymous namespace
- EGLNativeDisplayType displayId = reinterpret_cast<EGLNativeDisplayType>(native_display);
+DisplayState::DisplayState()
+{
+}
+
+DisplayState::~DisplayState()
+{
+}
- ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
- ANGLEPlatformDisplayMap::const_iterator iter = displays->find(displayId);
+// static
+Display *Display::GetDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay,
+ const AttributeMap &attribMap)
+{
+ Display *display = nullptr;
+
+ ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
+ const auto &iter = displays->find(nativeDisplay);
if (iter != displays->end())
{
display = iter->second;
@@ -218,19 +292,19 @@ Display *Display::GetDisplayFromAttribs(void *native_display, const AttributeMap
if (display == nullptr)
{
// Validate the native display
- if (!Display::isValidNativeDisplay(displayId))
+ if (!Display::isValidNativeDisplay(nativeDisplay))
{
- return NULL;
+ return nullptr;
}
- display = new Display(EGL_PLATFORM_ANGLE_ANGLE, displayId, nullptr);
- displays->insert(std::make_pair(displayId, display));
+ display = new Display(EGL_PLATFORM_ANGLE_ANGLE, nativeDisplay, nullptr);
+ displays->insert(std::make_pair(nativeDisplay, display));
}
// Apply new attributes if the display is not initialized yet.
if (!display->isInitialized())
{
- rx::DisplayImpl *impl = CreateDisplayFromAttribs(attribMap);
+ rx::DisplayImpl *impl = CreateDisplayFromAttribs(attribMap, display->getState());
if (impl == nullptr)
{
// No valid display implementation for these attributes
@@ -243,15 +317,12 @@ Display *Display::GetDisplayFromAttribs(void *native_display, const AttributeMap
return display;
}
-Display *Display::GetDisplayFromDevice(void *native_display)
+// static
+Display *Display::GetDisplayFromDevice(Device *device, const AttributeMap &attribMap)
{
- // Initialize the global platform if not already
- InitDefaultPlatformImpl();
-
Display *display = nullptr;
- Device *eglDevice = reinterpret_cast<Device *>(native_display);
- ASSERT(Device::IsValidDevice(eglDevice));
+ ASSERT(Device::IsValidDevice(device));
ANGLEPlatformDisplayMap *anglePlatformDisplays = GetANGLEPlatformDisplayMap();
DevicePlatformDisplayMap *devicePlatformDisplays = GetDevicePlatformDisplayMap();
@@ -260,7 +331,7 @@ Display *Display::GetDisplayFromDevice(void *native_display)
for (auto &displayMapEntry : *anglePlatformDisplays)
{
egl::Display *iterDisplay = displayMapEntry.second;
- if (iterDisplay->getDevice() == eglDevice)
+ if (iterDisplay->getDevice() == device)
{
display = iterDisplay;
}
@@ -269,7 +340,7 @@ Display *Display::GetDisplayFromDevice(void *native_display)
if (display == nullptr)
{
// See if the eglDevice is in use by a Display created using the DEVICE platform
- DevicePlatformDisplayMap::const_iterator iter = devicePlatformDisplays->find(eglDevice);
+ const auto &iter = devicePlatformDisplays->find(device);
if (iter != devicePlatformDisplays->end())
{
display = iter->second;
@@ -279,15 +350,15 @@ Display *Display::GetDisplayFromDevice(void *native_display)
if (display == nullptr)
{
// Otherwise create a new Display
- display = new Display(EGL_PLATFORM_DEVICE_EXT, 0, eglDevice);
- devicePlatformDisplays->insert(std::make_pair(eglDevice, display));
+ display = new Display(EGL_PLATFORM_DEVICE_EXT, 0, device);
+ devicePlatformDisplays->insert(std::make_pair(device, display));
}
// Apply new attributes if the display is not initialized yet.
if (!display->isInitialized())
{
- rx::DisplayImpl *impl = CreateDisplayFromDevice(eglDevice);
- display->setAttributes(impl, egl::AttributeMap());
+ rx::DisplayImpl *impl = CreateDisplayFromDevice(device, display->getState());
+ display->setAttributes(impl, attribMap);
}
return display;
@@ -299,19 +370,26 @@ Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDe
mAttributeMap(),
mConfigSet(),
mContextSet(),
+ mStreamSet(),
mInitialized(false),
+ mDeviceLost(false),
mCaps(),
mDisplayExtensions(),
mDisplayExtensionString(),
mVendorString(),
mDevice(eglDevice),
- mPlatform(platform)
+ mPlatform(platform),
+ mTextureManager(nullptr),
+ mMemoryProgramCache(gl::kDefaultMaxProgramCacheMemoryBytes),
+ mGlobalTextureShareGroupUsers(0),
+ mProxyContext(this)
{
}
Display::~Display()
{
- terminate();
+ // TODO(jmadill): When is this called?
+ // terminate();
if (mPlatform == EGL_PLATFORM_ANGLE_ANGLE)
{
@@ -336,6 +414,8 @@ Display::~Display()
UNREACHABLE();
}
+ mProxyContext.reset(nullptr);
+
SafeDelete(mDevice);
SafeDelete(mImplementation);
}
@@ -353,8 +433,20 @@ void Display::setAttributes(rx::DisplayImpl *impl, const AttributeMap &attribMap
Error Display::initialize()
{
- // Re-initialize default platform if it's needed
- InitDefaultPlatformImpl();
+ // TODO(jmadill): Store Platform in Display and init here.
+ const angle::PlatformMethods *platformMethods =
+ reinterpret_cast<const angle::PlatformMethods *>(
+ mAttributeMap.get(EGL_PLATFORM_ANGLE_PLATFORM_METHODS_ANGLEX, 0));
+ if (platformMethods != nullptr)
+ {
+ *ANGLEPlatformCurrent() = *platformMethods;
+ }
+ else
+ {
+ ANGLESetDefaultDisplayPlatform(this);
+ }
+
+ gl::InitializeDebugAnnotations(&mAnnotator);
SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.DisplayInitializeMS");
TRACE_EVENT0("gpu.angle", "egl::Display::initialize");
@@ -363,17 +455,14 @@ Error Display::initialize()
if (isInitialized())
{
- return Error(EGL_SUCCESS);
+ return NoError();
}
Error error = mImplementation->initialize(this);
if (error.isError())
{
// Log extended error message here
- std::stringstream errorStream;
- errorStream << "ANGLE Display::initialize error " << error.getID() << ": "
- << error.getMessage();
- ANGLEPlatformCurrent()->logError(errorStream.str().c_str());
+ ERR() << "ANGLE Display::initialize error " << error.getID() << ": " << error.getMessage();
return error;
}
@@ -383,7 +472,7 @@ Error Display::initialize()
if (mConfigSet.size() == 0)
{
mImplementation->terminate();
- return Error(EGL_NOT_INITIALIZED);
+ return EglNotInitialized();
}
initDisplayExtensions();
@@ -395,17 +484,8 @@ Error Display::initialize()
if (mDisplayExtensions.deviceQuery)
{
rx::DeviceImpl *impl = nullptr;
- error = mImplementation->getDevice(&impl);
- if (error.isError())
- {
- return error;
- }
-
- error = Device::CreateDevice(this, impl, &mDevice);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mImplementation->getDevice(&impl));
+ ANGLE_TRY(Device::CreateDevice(this, impl, &mDevice));
}
else
{
@@ -419,28 +499,45 @@ Error Display::initialize()
ASSERT(mDevice != nullptr);
}
+ mProxyContext.reset(nullptr);
+ gl::Context *proxyContext = new gl::Context(mImplementation, nullptr, nullptr, nullptr, nullptr,
+ egl::AttributeMap(), mDisplayExtensions);
+ mProxyContext.reset(proxyContext);
+
mInitialized = true;
- return Error(EGL_SUCCESS);
+ return NoError();
}
-void Display::terminate()
+Error Display::terminate()
{
- makeCurrent(nullptr, nullptr, nullptr);
+ ANGLE_TRY(makeCurrent(nullptr, nullptr, nullptr));
+
+ mMemoryProgramCache.clear();
+
+ mProxyContext.reset(nullptr);
while (!mContextSet.empty())
{
- destroyContext(*mContextSet.begin());
+ ANGLE_TRY(destroyContext(*mContextSet.begin()));
}
+ // The global texture manager should be deleted with the last context that uses it.
+ ASSERT(mGlobalTextureShareGroupUsers == 0 && mTextureManager == nullptr);
+
while (!mImageSet.empty())
{
destroyImage(*mImageSet.begin());
}
- while (!mImplementation->getSurfaceSet().empty())
+ while (!mStreamSet.empty())
{
- destroySurface(*mImplementation->getSurfaceSet().begin());
+ destroyStream(*mStreamSet.begin());
+ }
+
+ while (!mState.surfaceSet.empty())
+ {
+ ANGLE_TRY(destroySurface(*mState.surfaceSet.begin()));
}
mConfigSet.clear();
@@ -454,9 +551,16 @@ void Display::terminate()
mImplementation->terminate();
+ mDeviceLost = false;
+
mInitialized = false;
- // Never de-init default platform.. terminate is not that final.
+ gl::UninitializeDebugAnnotations();
+
+ // TODO(jmadill): Store Platform in Display and deinit here.
+ ANGLEResetDisplayPlatform(this);
+
+ return NoError();
}
std::vector<const Config*> Display::getConfigs(const egl::AttributeMap &attribs) const
@@ -464,189 +568,100 @@ std::vector<const Config*> Display::getConfigs(const egl::AttributeMap &attribs)
return mConfigSet.filter(attribs);
}
-bool Display::getConfigAttrib(const Config *configuration, EGLint attribute, EGLint *value)
-{
- switch (attribute)
- {
- case EGL_BUFFER_SIZE: *value = configuration->bufferSize; break;
- case EGL_ALPHA_SIZE: *value = configuration->alphaSize; break;
- case EGL_BLUE_SIZE: *value = configuration->blueSize; break;
- case EGL_GREEN_SIZE: *value = configuration->greenSize; break;
- case EGL_RED_SIZE: *value = configuration->redSize; break;
- case EGL_DEPTH_SIZE: *value = configuration->depthSize; break;
- case EGL_STENCIL_SIZE: *value = configuration->stencilSize; break;
- case EGL_CONFIG_CAVEAT: *value = configuration->configCaveat; break;
- case EGL_CONFIG_ID: *value = configuration->configID; break;
- case EGL_LEVEL: *value = configuration->level; break;
- case EGL_NATIVE_RENDERABLE: *value = configuration->nativeRenderable; break;
- case EGL_NATIVE_VISUAL_ID: *value = configuration->nativeVisualID; break;
- case EGL_NATIVE_VISUAL_TYPE: *value = configuration->nativeVisualType; break;
- case EGL_SAMPLES: *value = configuration->samples; break;
- case EGL_SAMPLE_BUFFERS: *value = configuration->sampleBuffers; break;
- case EGL_SURFACE_TYPE: *value = configuration->surfaceType; break;
- case EGL_TRANSPARENT_TYPE: *value = configuration->transparentType; break;
- case EGL_TRANSPARENT_BLUE_VALUE: *value = configuration->transparentBlueValue; break;
- case EGL_TRANSPARENT_GREEN_VALUE: *value = configuration->transparentGreenValue; break;
- case EGL_TRANSPARENT_RED_VALUE: *value = configuration->transparentRedValue; break;
- case EGL_BIND_TO_TEXTURE_RGB: *value = configuration->bindToTextureRGB; break;
- case EGL_BIND_TO_TEXTURE_RGBA: *value = configuration->bindToTextureRGBA; break;
- case EGL_MIN_SWAP_INTERVAL: *value = configuration->minSwapInterval; break;
- case EGL_MAX_SWAP_INTERVAL: *value = configuration->maxSwapInterval; break;
- case EGL_LUMINANCE_SIZE: *value = configuration->luminanceSize; break;
- case EGL_ALPHA_MASK_SIZE: *value = configuration->alphaMaskSize; break;
- case EGL_COLOR_BUFFER_TYPE: *value = configuration->colorBufferType; break;
- case EGL_RENDERABLE_TYPE: *value = configuration->renderableType; break;
- case EGL_MATCH_NATIVE_PIXMAP: *value = false; UNIMPLEMENTED(); break;
- case EGL_CONFORMANT: *value = configuration->conformant; break;
- case EGL_MAX_PBUFFER_WIDTH: *value = configuration->maxPBufferWidth; break;
- case EGL_MAX_PBUFFER_HEIGHT: *value = configuration->maxPBufferHeight; break;
- case EGL_MAX_PBUFFER_PIXELS: *value = configuration->maxPBufferPixels; break;
-
- case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
- if (!getExtensions().surfaceOrientation)
- {
- return false;
- }
- *value = configuration->optimalOrientation;
- break;
-
- default:
- return false;
- }
-
- return true;
-}
-
-Error Display::createWindowSurface(const Config *configuration, EGLNativeWindowType window, const AttributeMap &attribs,
+Error Display::createWindowSurface(const Config *configuration,
+ EGLNativeWindowType window,
+ const AttributeMap &attribs,
Surface **outSurface)
{
if (mImplementation->testDeviceLost())
{
- Error error = restoreLostDevice();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(restoreLostDevice());
}
- rx::SurfaceImpl *surfaceImpl = mImplementation->createWindowSurface(configuration, window, attribs);
- ASSERT(surfaceImpl != nullptr);
-
- Error error = surfaceImpl->initialize();
- if (error.isError())
- {
- SafeDelete(surfaceImpl);
- return error;
- }
+ SurfacePointer surface(new WindowSurface(mImplementation, configuration, window, attribs),
+ this);
+ ANGLE_TRY(surface->initialize(this));
- Surface *surface = new Surface(surfaceImpl, EGL_WINDOW_BIT, configuration, attribs);
- mImplementation->getSurfaceSet().insert(surface);
+ ASSERT(outSurface != nullptr);
+ *outSurface = surface.release();
+ mState.surfaceSet.insert(*outSurface);
WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
ASSERT(windowSurfaces && windowSurfaces->find(window) == windowSurfaces->end());
- windowSurfaces->insert(std::make_pair(window, surface));
+ windowSurfaces->insert(std::make_pair(window, *outSurface));
- ASSERT(outSurface != nullptr);
- *outSurface = surface;
- return Error(EGL_SUCCESS);
+ return NoError();
}
-Error Display::createPbufferSurface(const Config *configuration, const AttributeMap &attribs, Surface **outSurface)
+Error Display::createPbufferSurface(const Config *configuration,
+ const AttributeMap &attribs,
+ Surface **outSurface)
{
ASSERT(isInitialized());
if (mImplementation->testDeviceLost())
{
- Error error = restoreLostDevice();
- if (error.isError())
- {
- return error;
- }
- }
-
- rx::SurfaceImpl *surfaceImpl = mImplementation->createPbufferSurface(configuration, attribs);
- ASSERT(surfaceImpl != nullptr);
-
- Error error = surfaceImpl->initialize();
- if (error.isError())
- {
- SafeDelete(surfaceImpl);
- return error;
+ ANGLE_TRY(restoreLostDevice());
}
- Surface *surface = new Surface(surfaceImpl, EGL_PBUFFER_BIT, configuration, attribs);
- mImplementation->getSurfaceSet().insert(surface);
+ SurfacePointer surface(new PbufferSurface(mImplementation, configuration, attribs), this);
+ ANGLE_TRY(surface->initialize(this));
ASSERT(outSurface != nullptr);
- *outSurface = surface;
- return Error(EGL_SUCCESS);
+ *outSurface = surface.release();
+ mState.surfaceSet.insert(*outSurface);
+
+ return NoError();
}
-Error Display::createPbufferFromClientBuffer(const Config *configuration, EGLClientBuffer shareHandle,
- const AttributeMap &attribs, Surface **outSurface)
+Error Display::createPbufferFromClientBuffer(const Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const AttributeMap &attribs,
+ Surface **outSurface)
{
ASSERT(isInitialized());
if (mImplementation->testDeviceLost())
{
- Error error = restoreLostDevice();
- if (error.isError())
- {
- return error;
- }
- }
-
- rx::SurfaceImpl *surfaceImpl = mImplementation->createPbufferFromClientBuffer(configuration, shareHandle, attribs);
- ASSERT(surfaceImpl != nullptr);
-
- Error error = surfaceImpl->initialize();
- if (error.isError())
- {
- SafeDelete(surfaceImpl);
- return error;
+ ANGLE_TRY(restoreLostDevice());
}
- Surface *surface = new Surface(surfaceImpl, EGL_PBUFFER_BIT, configuration, attribs);
- mImplementation->getSurfaceSet().insert(surface);
+ SurfacePointer surface(
+ new PbufferSurface(mImplementation, configuration, buftype, clientBuffer, attribs), this);
+ ANGLE_TRY(surface->initialize(this));
ASSERT(outSurface != nullptr);
- *outSurface = surface;
- return Error(EGL_SUCCESS);
+ *outSurface = surface.release();
+ mState.surfaceSet.insert(*outSurface);
+
+ return NoError();
}
-Error Display::createPixmapSurface(const Config *configuration, NativePixmapType nativePixmap, const AttributeMap &attribs,
+Error Display::createPixmapSurface(const Config *configuration,
+ NativePixmapType nativePixmap,
+ const AttributeMap &attribs,
Surface **outSurface)
{
ASSERT(isInitialized());
if (mImplementation->testDeviceLost())
{
- Error error = restoreLostDevice();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(restoreLostDevice());
}
- rx::SurfaceImpl *surfaceImpl = mImplementation->createPixmapSurface(configuration, nativePixmap, attribs);
- ASSERT(surfaceImpl != nullptr);
-
- Error error = surfaceImpl->initialize();
- if (error.isError())
- {
- SafeDelete(surfaceImpl);
- return error;
- }
-
- Surface *surface = new Surface(surfaceImpl, EGL_PIXMAP_BIT, configuration, attribs);
- mImplementation->getSurfaceSet().insert(surface);
+ SurfacePointer surface(new PixmapSurface(mImplementation, configuration, nativePixmap, attribs),
+ this);
+ ANGLE_TRY(surface->initialize(this));
ASSERT(outSurface != nullptr);
- *outSurface = surface;
- return Error(EGL_SUCCESS);
+ *outSurface = surface.release();
+ mState.surfaceSet.insert(*outSurface);
+
+ return NoError();
}
-Error Display::createImage(gl::Context *context,
+Error Display::createImage(const gl::Context *context,
EGLenum target,
EGLClientBuffer buffer,
const AttributeMap &attribs,
@@ -656,11 +671,7 @@ Error Display::createImage(gl::Context *context,
if (mImplementation->testDeviceLost())
{
- Error error = restoreLostDevice();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(restoreLostDevice());
}
egl::ImageSibling *sibling = nullptr;
@@ -678,16 +689,11 @@ Error Display::createImage(gl::Context *context,
}
ASSERT(sibling != nullptr);
- rx::ImageImpl *imageImpl = mImplementation->createImage(target, sibling, attribs);
- ASSERT(imageImpl != nullptr);
+ angle::UniqueObjectPointer<Image, gl::Context> imagePtr(
+ new Image(mImplementation, target, sibling, attribs), context);
+ ANGLE_TRY(imagePtr->initialize());
- Error error = imageImpl->initialize();
- if (error.isError())
- {
- return error;
- }
-
- Image *image = new Image(imageImpl, target, sibling, attribs);
+ Image *image = imagePtr.release();
ASSERT(outImage != nullptr);
*outImage = image;
@@ -696,49 +702,92 @@ Error Display::createImage(gl::Context *context,
image->addRef();
mImageSet.insert(image);
- return Error(EGL_SUCCESS);
+ return NoError();
+}
+
+Error Display::createStream(const AttributeMap &attribs, Stream **outStream)
+{
+ ASSERT(isInitialized());
+
+ Stream *stream = new Stream(this, attribs);
+
+ ASSERT(stream != nullptr);
+ mStreamSet.insert(stream);
+
+ ASSERT(outStream != nullptr);
+ *outStream = stream;
+
+ return NoError();
}
-Error Display::createContext(const Config *configuration, gl::Context *shareContext, const AttributeMap &attribs,
+Error Display::createContext(const Config *configuration,
+ gl::Context *shareContext,
+ const AttributeMap &attribs,
gl::Context **outContext)
{
ASSERT(isInitialized());
if (mImplementation->testDeviceLost())
{
- Error error = restoreLostDevice();
- if (error.isError())
+ ANGLE_TRY(restoreLostDevice());
+ }
+
+ // This display texture sharing will allow the first context to create the texture share group.
+ bool usingDisplayTextureShareGroup =
+ attribs.get(EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE, EGL_FALSE) == EGL_TRUE;
+ gl::TextureManager *shareTextures = nullptr;
+
+ if (usingDisplayTextureShareGroup)
+ {
+ ASSERT((mTextureManager == nullptr) == (mGlobalTextureShareGroupUsers == 0));
+ if (mTextureManager == nullptr)
{
- return error;
+ mTextureManager = new gl::TextureManager();
}
+
+ mGlobalTextureShareGroupUsers++;
+ shareTextures = mTextureManager;
}
- gl::Context *context = *outContext =
- mImplementation->createContext(configuration, shareContext, attribs);
+ gl::MemoryProgramCache *cachePointer = &mMemoryProgramCache;
+
+ // Check context creation attributes to see if we should enable the cache.
+ if (mAttributeMap.get(EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE, EGL_TRUE) == EGL_FALSE)
+ {
+ cachePointer = nullptr;
+ }
+
+ // A program cache size of zero indicates it should be disabled.
+ if (mMemoryProgramCache.maxSize() == 0)
+ {
+ cachePointer = nullptr;
+ }
+
+ gl::Context *context =
+ new gl::Context(mImplementation, configuration, shareContext, shareTextures, cachePointer,
+ attribs, mDisplayExtensions);
ASSERT(context != nullptr);
mContextSet.insert(context);
ASSERT(outContext != nullptr);
*outContext = context;
- return Error(EGL_SUCCESS);
+ return NoError();
}
-Error Display::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context)
+Error Display::makeCurrent(egl::Surface *drawSurface,
+ egl::Surface *readSurface,
+ gl::Context *context)
{
- Error error = mImplementation->makeCurrent(drawSurface, readSurface, context);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mImplementation->makeCurrent(drawSurface, readSurface, context));
- if (context != nullptr && drawSurface != nullptr)
+ if (context != nullptr)
{
ASSERT(readSurface == drawSurface);
- context->makeCurrent(drawSurface);
+ ANGLE_TRY(context->makeCurrent(this, drawSurface));
}
- return egl::Error(EGL_SUCCESS);
+ return NoError();
}
Error Display::restoreLostDevice()
@@ -748,14 +797,14 @@ Error Display::restoreLostDevice()
if ((*ctx)->isResetNotificationEnabled())
{
// If reset notifications have been requested, application must delete all contexts first
- return Error(EGL_CONTEXT_LOST);
+ return EglContextLost();
}
}
- return mImplementation->restoreLostDevice();
+ return mImplementation->restoreLostDevice(this);
}
-void Display::destroySurface(Surface *surface)
+Error Display::destroySurface(Surface *surface)
{
if (surface->getType() == EGL_WINDOW_BIT)
{
@@ -774,54 +823,89 @@ void Display::destroySurface(Surface *surface)
}
ASSERT(surfaceRemoved);
- UNUSED_ASSERTION_VARIABLE(surfaceRemoved);
}
- mImplementation->destroySurface(surface);
+ mState.surfaceSet.erase(surface);
+ ANGLE_TRY(surface->onDestroy(this));
+ return NoError();
}
void Display::destroyImage(egl::Image *image)
{
auto iter = mImageSet.find(image);
ASSERT(iter != mImageSet.end());
- (*iter)->release();
+ (*iter)->release(mProxyContext.get());
mImageSet.erase(iter);
}
-void Display::destroyContext(gl::Context *context)
+void Display::destroyStream(egl::Stream *stream)
{
+ mStreamSet.erase(stream);
+ SafeDelete(stream);
+}
+
+Error Display::destroyContext(gl::Context *context)
+{
+ if (context->usingDisplayTextureShareGroup())
+ {
+ ASSERT(mGlobalTextureShareGroupUsers >= 1 && mTextureManager != nullptr);
+ if (mGlobalTextureShareGroupUsers == 1)
+ {
+ // If this is the last context using the global share group, destroy the global texture
+ // manager so that the textures can be destroyed while a context still exists
+ mTextureManager->release(context);
+ mTextureManager = nullptr;
+ }
+ mGlobalTextureShareGroupUsers--;
+ }
+
+ ANGLE_TRY(context->onDestroy(this));
mContextSet.erase(context);
SafeDelete(context);
+ return NoError();
}
bool Display::isDeviceLost() const
{
ASSERT(isInitialized());
- return mImplementation->isDeviceLost();
+ return mDeviceLost;
}
bool Display::testDeviceLost()
{
ASSERT(isInitialized());
- return mImplementation->testDeviceLost();
+
+ if (!mDeviceLost && mImplementation->testDeviceLost())
+ {
+ notifyDeviceLost();
+ }
+
+ return mDeviceLost;
}
void Display::notifyDeviceLost()
{
+ if (mDeviceLost)
+ {
+ return;
+ }
+
for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++)
{
(*context)->markContextLost();
}
+
+ mDeviceLost = true;
}
-Error Display::waitClient() const
+Error Display::waitClient(const gl::Context *context) const
{
- return mImplementation->waitClient();
+ return mImplementation->waitClient(context);
}
-Error Display::waitNative(EGLint engine, egl::Surface *drawSurface, egl::Surface *readSurface) const
+Error Display::waitNative(const gl::Context *context, EGLint engine) const
{
- return mImplementation->waitNative(engine, drawSurface, readSurface);
+ return mImplementation->waitNative(context, engine);
}
const Caps &Display::getCaps() const
@@ -839,14 +923,14 @@ bool Display::isValidConfig(const Config *config) const
return mConfigSet.contains(config);
}
-bool Display::isValidContext(gl::Context *context) const
+bool Display::isValidContext(const gl::Context *context) const
{
- return mContextSet.find(context) != mContextSet.end();
+ return mContextSet.find(const_cast<gl::Context *>(context)) != mContextSet.end();
}
-bool Display::isValidSurface(Surface *surface) const
+bool Display::isValidSurface(const Surface *surface) const
{
- return mImplementation->getSurfaceSet().find(surface) != mImplementation->getSurfaceSet().end();
+ return mState.surfaceSet.find(const_cast<Surface *>(surface)) != mState.surfaceSet.end();
}
bool Display::isValidImage(const Image *image) const
@@ -854,6 +938,11 @@ bool Display::isValidImage(const Image *image) const
return mImageSet.find(const_cast<Image *>(image)) != mImageSet.end();
}
+bool Display::isValidStream(const Stream *stream) const
+{
+ return mStreamSet.find(const_cast<Stream *>(stream)) != mStreamSet.end();
+}
+
bool Display::hasExistingWindowSurface(EGLNativeWindowType window)
{
WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
@@ -879,12 +968,20 @@ static ClientExtensions GenerateClientExtensions()
extensions.platformANGLEOpenGL = true;
#endif
+#if defined(ANGLE_ENABLE_NULL)
+ extensions.platformANGLENULL = true;
+#endif
+
#if defined(ANGLE_ENABLE_D3D11)
extensions.deviceCreation = true;
extensions.deviceCreationD3D11 = true;
extensions.experimentalPresentPath = true;
#endif
+#if defined(ANGLE_ENABLE_VULKAN)
+ extensions.platformANGLEVulkan = true;
+#endif
+
#if defined(ANGLE_USE_X11)
extensions.x11Visual = true;
#endif
@@ -904,15 +1001,18 @@ static std::string GenerateExtensionsString(const T &extensions)
return stream.str();
}
-const ClientExtensions &Display::getClientExtensions()
+// static
+const ClientExtensions &Display::GetClientExtensions()
{
static const ClientExtensions clientExtensions = GenerateClientExtensions();
return clientExtensions;
}
-const std::string &Display::getClientExtensionString()
+// static
+const std::string &Display::GetClientExtensionString()
{
- static const std::string clientExtensionsString = GenerateExtensionsString(getClientExtensions());
+ static const std::string clientExtensionsString =
+ GenerateExtensionsString(GetClientExtensions());
return clientExtensionsString;
}
@@ -920,9 +1020,20 @@ void Display::initDisplayExtensions()
{
mDisplayExtensions = mImplementation->getExtensions();
+ // Some extensions are always available because they are implemented in the EGL layer.
+ mDisplayExtensions.createContext = true;
+ mDisplayExtensions.createContextNoError = true;
+ mDisplayExtensions.createContextWebGLCompatibility = true;
+ mDisplayExtensions.createContextBindGeneratesResource = true;
+ mDisplayExtensions.createContextClientArrays = true;
+ mDisplayExtensions.pixelFormatFloat = true;
+
// Force EGL_KHR_get_all_proc_addresses on.
mDisplayExtensions.getAllProcAddresses = true;
+ // Enable program cache control since it is not back-end dependent.
+ mDisplayExtensions.programCacheControl = true;
+
mDisplayExtensionString = GenerateExtensionsString(mDisplayExtensions);
}
@@ -931,6 +1042,14 @@ bool Display::isValidNativeWindow(EGLNativeWindowType window) const
return mImplementation->isValidNativeWindow(window);
}
+Error Display::validateClientBuffer(const Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const AttributeMap &attribs)
+{
+ return mImplementation->validateClientBuffer(configuration, buftype, clientBuffer, attribs);
+}
+
bool Display::isValidDisplay(const egl::Display *display)
{
const ANGLEPlatformDisplayMap *anglePlatformDisplayMap = GetANGLEPlatformDisplayMap();
@@ -969,7 +1088,7 @@ bool Display::isValidNativeDisplay(EGLNativeDisplayType display)
{
return true;
}
- return (WindowFromDC(display) != NULL);
+ return (WindowFromDC(display) != nullptr);
#else
return true;
#endif
@@ -1000,4 +1119,105 @@ Device *Display::getDevice() const
return mDevice;
}
+gl::Version Display::getMaxSupportedESVersion() const
+{
+ return mImplementation->getMaxSupportedESVersion();
}
+
+EGLint Display::programCacheGetAttrib(EGLenum attrib) const
+{
+ switch (attrib)
+ {
+ case EGL_PROGRAM_CACHE_KEY_LENGTH_ANGLE:
+ return static_cast<EGLint>(gl::kProgramHashLength);
+
+ case EGL_PROGRAM_CACHE_SIZE_ANGLE:
+ return static_cast<EGLint>(mMemoryProgramCache.entryCount());
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+Error Display::programCacheQuery(EGLint index,
+ void *key,
+ EGLint *keysize,
+ void *binary,
+ EGLint *binarysize)
+{
+ ASSERT(index >= 0 && index < static_cast<EGLint>(mMemoryProgramCache.entryCount()));
+
+ const angle::MemoryBuffer *programBinary = nullptr;
+ gl::ProgramHash programHash;
+ // TODO(jmadill): Make this thread-safe.
+ bool result =
+ mMemoryProgramCache.getAt(static_cast<size_t>(index), &programHash, &programBinary);
+ if (!result)
+ {
+ return EglBadAccess() << "Program binary not accessible.";
+ }
+
+ ASSERT(keysize && binarysize);
+
+ if (key)
+ {
+ ASSERT(*keysize == static_cast<EGLint>(gl::kProgramHashLength));
+ memcpy(key, programHash.data(), gl::kProgramHashLength);
+ }
+
+ if (binary)
+ {
+ // Note: we check the size here instead of in the validation code, since we need to
+ // access the cache as atomically as possible. It's possible that the cache contents
+ // could change between the validation size check and the retrieval.
+ if (programBinary->size() > static_cast<size_t>(*binarysize))
+ {
+ return EglBadAccess() << "Program binary too large or changed during access.";
+ }
+
+ memcpy(binary, programBinary->data(), programBinary->size());
+ }
+
+ *binarysize = static_cast<EGLint>(programBinary->size());
+ *keysize = static_cast<EGLint>(gl::kProgramHashLength);
+
+ return NoError();
+}
+
+Error Display::programCachePopulate(const void *key,
+ EGLint keysize,
+ const void *binary,
+ EGLint binarysize)
+{
+ ASSERT(keysize == static_cast<EGLint>(gl::kProgramHashLength));
+
+ gl::ProgramHash programHash;
+ memcpy(programHash.data(), key, gl::kProgramHashLength);
+
+ mMemoryProgramCache.putBinary(programHash, reinterpret_cast<const uint8_t *>(binary),
+ static_cast<size_t>(binarysize));
+ return NoError();
+}
+
+EGLint Display::programCacheResize(EGLint limit, EGLenum mode)
+{
+ switch (mode)
+ {
+ case EGL_PROGRAM_CACHE_RESIZE_ANGLE:
+ {
+ size_t initialSize = mMemoryProgramCache.size();
+ mMemoryProgramCache.resize(static_cast<size_t>(limit));
+ return static_cast<EGLint>(initialSize);
+ }
+
+ case EGL_PROGRAM_CACHE_TRIM_ANGLE:
+ return static_cast<EGLint>(mMemoryProgramCache.trim(static_cast<size_t>(limit)));
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+} // namespace egl
diff --git a/src/3rdparty/angle/src/libANGLE/Display.h b/src/3rdparty/angle/src/libANGLE/Display.h
index f80e308347..aa1d1c3b37 100644
--- a/src/3rdparty/angle/src/libANGLE/Display.h
+++ b/src/3rdparty/angle/src/libANGLE/Display.h
@@ -14,15 +14,18 @@
#include <set>
#include <vector>
-#include "libANGLE/Error.h"
+#include "libANGLE/AttributeMap.h"
#include "libANGLE/Caps.h"
#include "libANGLE/Config.h"
-#include "libANGLE/AttributeMap.h"
-#include "libANGLE/renderer/Renderer.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/LoggingAnnotator.h"
+#include "libANGLE/MemoryProgramCache.h"
+#include "libANGLE/Version.h"
namespace gl
{
class Context;
+class TextureManager;
}
namespace rx
@@ -35,6 +38,21 @@ namespace egl
class Device;
class Image;
class Surface;
+class Stream;
+class Thread;
+
+using SurfaceSet = std::set<Surface *>;
+
+struct DisplayState final : private angle::NonCopyable
+{
+ DisplayState();
+ ~DisplayState();
+
+ SurfaceSet surfaceSet;
+};
+
+// Constant coded here as a sanity limit.
+constexpr EGLAttrib kProgramCacheSizeAbsoluteMax = 0x4000000;
class Display final : angle::NonCopyable
{
@@ -42,48 +60,68 @@ class Display final : angle::NonCopyable
~Display();
Error initialize();
- void terminate();
+ Error terminate();
- static egl::Display *GetDisplayFromDevice(void *native_display);
- static egl::Display *GetDisplayFromAttribs(void *native_display, const AttributeMap &attribMap);
+ static Display *GetDisplayFromDevice(Device *device, const AttributeMap &attribMap);
+ static Display *GetDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay,
+ const AttributeMap &attribMap);
- static const ClientExtensions &getClientExtensions();
- static const std::string &getClientExtensionString();
+ static const ClientExtensions &GetClientExtensions();
+ static const std::string &GetClientExtensionString();
- std::vector<const Config*> getConfigs(const egl::AttributeMap &attribs) const;
- bool getConfigAttrib(const Config *configuration, EGLint attribute, EGLint *value);
+ std::vector<const Config *> getConfigs(const AttributeMap &attribs) const;
- Error createWindowSurface(const Config *configuration, EGLNativeWindowType window, const AttributeMap &attribs,
+ Error createWindowSurface(const Config *configuration,
+ EGLNativeWindowType window,
+ const AttributeMap &attribs,
Surface **outSurface);
- Error createPbufferSurface(const Config *configuration, const AttributeMap &attribs, Surface **outSurface);
- Error createPbufferFromClientBuffer(const Config *configuration, EGLClientBuffer shareHandle, const AttributeMap &attribs,
+ Error createPbufferSurface(const Config *configuration,
+ const AttributeMap &attribs,
+ Surface **outSurface);
+ Error createPbufferFromClientBuffer(const Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const AttributeMap &attribs,
Surface **outSurface);
- Error createPixmapSurface(const Config *configuration, NativePixmapType nativePixmap, const AttributeMap &attribs,
+ Error createPixmapSurface(const Config *configuration,
+ NativePixmapType nativePixmap,
+ const AttributeMap &attribs,
Surface **outSurface);
- Error createImage(gl::Context *context,
+ Error createImage(const gl::Context *context,
EGLenum target,
EGLClientBuffer buffer,
const AttributeMap &attribs,
Image **outImage);
- Error createContext(const Config *configuration, gl::Context *shareContext, const AttributeMap &attribs,
+ Error createStream(const AttributeMap &attribs, Stream **outStream);
+
+ Error createContext(const Config *configuration,
+ gl::Context *shareContext,
+ const AttributeMap &attribs,
gl::Context **outContext);
- Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context);
+ Error makeCurrent(Surface *drawSurface, Surface *readSurface, gl::Context *context);
- void destroySurface(egl::Surface *surface);
- void destroyImage(egl::Image *image);
- void destroyContext(gl::Context *context);
+ Error destroySurface(Surface *surface);
+ void destroyImage(Image *image);
+ void destroyStream(Stream *stream);
+ Error destroyContext(gl::Context *context);
bool isInitialized() const;
bool isValidConfig(const Config *config) const;
- bool isValidContext(gl::Context *context) const;
- bool isValidSurface(egl::Surface *surface) const;
+ bool isValidContext(const gl::Context *context) const;
+ bool isValidSurface(const Surface *surface) const;
bool isValidImage(const Image *image) const;
+ bool isValidStream(const Stream *stream) const;
bool isValidNativeWindow(EGLNativeWindowType window) const;
- static bool isValidDisplay(const egl::Display *display);
+ Error validateClientBuffer(const Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const AttributeMap &attribs);
+
+ static bool isValidDisplay(const Display *display);
static bool isValidNativeDisplay(EGLNativeDisplayType display);
static bool hasExistingWindowSurface(EGLNativeWindowType window);
@@ -91,8 +129,8 @@ class Display final : angle::NonCopyable
bool testDeviceLost();
void notifyDeviceLost();
- Error waitClient() const;
- Error waitNative(EGLint engine, egl::Surface *drawSurface, egl::Surface *readSurface) const;
+ Error waitClient(const gl::Context *context) const;
+ Error waitNative(const gl::Context *context, EGLint engine) const;
const Caps &getCaps() const;
@@ -100,13 +138,31 @@ class Display final : angle::NonCopyable
const std::string &getExtensionString() const;
const std::string &getVendorString() const;
+ EGLint programCacheGetAttrib(EGLenum attrib) const;
+ Error programCacheQuery(EGLint index,
+ void *key,
+ EGLint *keysize,
+ void *binary,
+ EGLint *binarysize);
+ Error programCachePopulate(const void *key,
+ EGLint keysize,
+ const void *binary,
+ EGLint binarysize);
+ EGLint programCacheResize(EGLint limit, EGLenum mode);
+
const AttributeMap &getAttributeMap() const { return mAttributeMap; }
EGLNativeDisplayType getNativeDisplayId() const { return mDisplayId; }
- rx::DisplayImpl *getImplementation() { return mImplementation; }
+ rx::DisplayImpl *getImplementation() const { return mImplementation; }
Device *getDevice() const;
EGLenum getPlatform() const { return mPlatform; }
+ gl::Version getMaxSupportedESVersion() const;
+
+ const DisplayState &getState() const { return mState; }
+
+ gl::Context *getProxyContext() const { return mProxyContext.get(); }
+
private:
Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice);
@@ -117,6 +173,7 @@ class Display final : angle::NonCopyable
void initDisplayExtensions();
void initVendorString();
+ DisplayState mState;
rx::DisplayImpl *mImplementation;
EGLNativeDisplayType mDisplayId;
@@ -130,7 +187,11 @@ class Display final : angle::NonCopyable
typedef std::set<Image *> ImageSet;
ImageSet mImageSet;
+ typedef std::set<Stream *> StreamSet;
+ StreamSet mStreamSet;
+
bool mInitialized;
+ bool mDeviceLost;
Caps mCaps;
@@ -141,8 +202,17 @@ class Display final : angle::NonCopyable
Device *mDevice;
EGLenum mPlatform;
+ angle::LoggingAnnotator mAnnotator;
+
+ gl::TextureManager *mTextureManager;
+ gl::MemoryProgramCache mMemoryProgramCache;
+ size_t mGlobalTextureShareGroupUsers;
+
+ // This gl::Context is a simple proxy to the Display for the GL back-end entry points
+ // that need access to implementation-specific data, like a Renderer object.
+ angle::UniqueObjectPointer<gl::Context, Display> mProxyContext;
};
-}
+} // namespace egl
#endif // LIBANGLE_DISPLAY_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Error.cpp b/src/3rdparty/angle/src/libANGLE/Error.cpp
index fed1594972..388f0259fa 100644
--- a/src/3rdparty/angle/src/libANGLE/Error.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Error.cpp
@@ -10,35 +10,38 @@
#include "libANGLE/Error.h"
#include "common/angleutils.h"
+#include "common/debug.h"
+#include "common/utilities.h"
#include <cstdarg>
+namespace
+{
+std::unique_ptr<std::string> EmplaceErrorString(std::string &&message)
+{
+ return message.empty() ? std::unique_ptr<std::string>()
+ : std::unique_ptr<std::string>(new std::string(std::move(message)));
+}
+} // anonymous namespace
+
namespace gl
{
-Error::Error(GLenum errorCode, const char *msg, ...) : mCode(errorCode), mID(errorCode)
+Error::Error(GLenum errorCode, std::string &&message)
+ : mCode(errorCode), mID(errorCode), mMessage(EmplaceErrorString(std::move(message)))
{
- va_list vararg;
- va_start(vararg, msg);
- createMessageString();
- *mMessage = FormatString(msg, vararg);
- va_end(vararg);
}
-Error::Error(GLenum errorCode, GLuint id, const char *msg, ...) : mCode(errorCode), mID(id)
+Error::Error(GLenum errorCode, GLuint id, std::string &&message)
+ : mCode(errorCode), mID(id), mMessage(EmplaceErrorString(std::move(message)))
{
- va_list vararg;
- va_start(vararg, msg);
- createMessageString();
- *mMessage = FormatString(msg, vararg);
- va_end(vararg);
}
void Error::createMessageString() const
{
if (!mMessage)
{
- mMessage.reset(new std::string);
+ mMessage.reset(new std::string(GetGenericErrorMessage(mCode)));
}
}
@@ -64,34 +67,32 @@ bool Error::operator!=(const Error &other) const
{
return !(*this == other);
}
+
+std::ostream &operator<<(std::ostream &os, const Error &err)
+{
+ return gl::FmtHexShort(os, err.getCode());
}
+} // namespace gl
+
namespace egl
{
-Error::Error(EGLint errorCode, const char *msg, ...) : mCode(errorCode), mID(0)
+Error::Error(EGLint errorCode, std::string &&message)
+ : mCode(errorCode), mID(errorCode), mMessage(EmplaceErrorString(std::move(message)))
{
- va_list vararg;
- va_start(vararg, msg);
- createMessageString();
- *mMessage = FormatString(msg, vararg);
- va_end(vararg);
}
-Error::Error(EGLint errorCode, EGLint id, const char *msg, ...) : mCode(errorCode), mID(id)
+Error::Error(EGLint errorCode, EGLint id, std::string &&message)
+ : mCode(errorCode), mID(id), mMessage(EmplaceErrorString(std::move(message)))
{
- va_list vararg;
- va_start(vararg, msg);
- createMessageString();
- *mMessage = FormatString(msg, vararg);
- va_end(vararg);
}
void Error::createMessageString() const
{
if (!mMessage)
{
- mMessage.reset(new std::string);
+ mMessage.reset(new std::string(GetGenericErrorMessage(mCode)));
}
}
@@ -101,4 +102,9 @@ const std::string &Error::getMessage() const
return *mMessage;
}
+std::ostream &operator<<(std::ostream &os, const Error &err)
+{
+ return gl::FmtHexShort(os, err.getCode());
}
+
+} // namespace egl
diff --git a/src/3rdparty/angle/src/libANGLE/Error.h b/src/3rdparty/angle/src/libANGLE/Error.h
index a5f760956a..1d57bb8707 100644
--- a/src/3rdparty/angle/src/libANGLE/Error.h
+++ b/src/3rdparty/angle/src/libANGLE/Error.h
@@ -9,23 +9,89 @@
#ifndef LIBANGLE_ERROR_H_
#define LIBANGLE_ERROR_H_
-#include "angle_gl.h"
#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "common/debug.h"
-#include <string>
#include <memory>
+#include <ostream>
+#include <string>
+
+namespace angle
+{
+template <typename ErrorT, typename ResultT, typename ErrorBaseT, ErrorBaseT NoErrorVal>
+class ANGLE_NO_DISCARD ErrorOrResultBase
+{
+ public:
+ ErrorOrResultBase(const ErrorT &error) : mError(error) {}
+ ErrorOrResultBase(ErrorT &&error) : mError(std::move(error)) {}
+
+ ErrorOrResultBase(ResultT &&result) : mError(NoErrorVal), mResult(std::forward<ResultT>(result))
+ {
+ }
+
+ ErrorOrResultBase(const ResultT &result) : mError(NoErrorVal), mResult(result) {}
+
+ bool isError() const { return mError.isError(); }
+ const ErrorT &getError() const { return mError; }
+ ResultT &&getResult() { return std::move(mResult); }
+
+ private:
+ ErrorT mError;
+ ResultT mResult;
+};
+
+template <typename ErrorT, typename ErrorBaseT, ErrorBaseT NoErrorVal, typename CodeT, CodeT EnumT>
+class ErrorStreamBase : angle::NonCopyable
+{
+ public:
+ ErrorStreamBase() : mID(EnumT) {}
+ ErrorStreamBase(GLuint id) : mID(id) {}
+
+ template <typename T>
+ ErrorStreamBase &operator<<(T value)
+ {
+ mErrorStream << value;
+ return *this;
+ }
+
+ operator ErrorT() { return ErrorT(EnumT, mID, mErrorStream.str()); }
+
+ template <typename ResultT>
+ operator ErrorOrResultBase<ErrorT, ResultT, ErrorBaseT, NoErrorVal>()
+ {
+ return static_cast<ErrorT>(*this);
+ }
+
+ private:
+ GLuint mID;
+ std::ostringstream mErrorStream;
+};
+} // namespace angle
+
+namespace egl
+{
+class Error;
+} // namespace egl
namespace gl
{
-class Error final
+class ANGLE_NO_DISCARD Error final
{
public:
explicit inline Error(GLenum errorCode);
- Error(GLenum errorCode, const char *msg, ...);
- Error(GLenum errorCode, GLuint id, const char *msg, ...);
+ Error(GLenum errorCode, std::string &&message);
+ Error(GLenum errorCode, GLuint id, std::string &&message);
inline Error(const Error &other);
inline Error(Error &&other);
+ inline ~Error() = default;
+
+ // automatic error type conversion
+ inline Error(egl::Error &&eglErr);
+ inline Error(egl::Error eglErr);
inline Error &operator=(const Error &other);
inline Error &operator=(Error &&other);
@@ -43,40 +109,60 @@ class Error final
private:
void createMessageString() const;
+ friend std::ostream &operator<<(std::ostream &os, const Error &err);
+ friend class egl::Error;
+
GLenum mCode;
GLuint mID;
mutable std::unique_ptr<std::string> mMessage;
};
-template <typename T>
-class ErrorOrResult
+template <typename ResultT>
+using ErrorOrResult = angle::ErrorOrResultBase<Error, ResultT, GLenum, GL_NO_ERROR>;
+
+namespace priv
{
- public:
- ErrorOrResult(const gl::Error &error) : mError(error) {}
- ErrorOrResult(T &&result) : mError(GL_NO_ERROR), mResult(std::move(result)) {}
- bool isError() const { return mError.isError(); }
- const gl::Error &getError() const { return mError; }
- T &&getResult() { return std::move(mResult); }
+template <GLenum EnumT>
+using ErrorStream = angle::ErrorStreamBase<Error, GLenum, GL_NO_ERROR, GLenum, EnumT>;
- private:
- Error mError;
- T mResult;
-};
+} // namespace priv
+
+using InternalError = priv::ErrorStream<GL_INVALID_OPERATION>;
+
+using InvalidEnum = priv::ErrorStream<GL_INVALID_ENUM>;
+using InvalidValue = priv::ErrorStream<GL_INVALID_VALUE>;
+using InvalidOperation = priv::ErrorStream<GL_INVALID_OPERATION>;
+using StackOverflow = priv::ErrorStream<GL_STACK_OVERFLOW>;
+using StackUnderflow = priv::ErrorStream<GL_STACK_UNDERFLOW>;
+using OutOfMemory = priv::ErrorStream<GL_OUT_OF_MEMORY>;
+using InvalidFramebufferOperation = priv::ErrorStream<GL_INVALID_FRAMEBUFFER_OPERATION>;
+
+inline Error NoError()
+{
+ return Error(GL_NO_ERROR);
+}
+
+using LinkResult = ErrorOrResult<bool>;
} // namespace gl
namespace egl
{
-class Error final
+class ANGLE_NO_DISCARD Error final
{
public:
explicit inline Error(EGLint errorCode);
- Error(EGLint errorCode, const char *msg, ...);
- Error(EGLint errorCode, EGLint id, const char *msg, ...);
+ Error(EGLint errorCode, std::string &&message);
+ Error(EGLint errorCode, EGLint id, std::string &&message);
inline Error(const Error &other);
inline Error(Error &&other);
+ inline ~Error() = default;
+
+ // automatic error type conversion
+ inline Error(gl::Error &&glErr);
+ inline Error(gl::Error glErr);
inline Error &operator=(const Error &other);
inline Error &operator=(Error &&other);
@@ -90,13 +176,92 @@ class Error final
private:
void createMessageString() const;
+ friend std::ostream &operator<<(std::ostream &os, const Error &err);
+ friend class gl::Error;
+
EGLint mCode;
EGLint mID;
mutable std::unique_ptr<std::string> mMessage;
};
+template <typename ResultT>
+using ErrorOrResult = angle::ErrorOrResultBase<Error, ResultT, EGLint, EGL_SUCCESS>;
+
+namespace priv
+{
+
+template <EGLint EnumT>
+using ErrorStream = angle::ErrorStreamBase<Error, EGLint, EGL_SUCCESS, EGLint, EnumT>;
+
+} // namespace priv
+
+using EglNotInitialized = priv::ErrorStream<EGL_NOT_INITIALIZED>;
+using EglBadAccess = priv::ErrorStream<EGL_BAD_ACCESS>;
+using EglBadAlloc = priv::ErrorStream<EGL_BAD_ALLOC>;
+using EglBadAttribute = priv::ErrorStream<EGL_BAD_ATTRIBUTE>;
+using EglBadConfig = priv::ErrorStream<EGL_BAD_CONFIG>;
+using EglBadContext = priv::ErrorStream<EGL_BAD_CONTEXT>;
+using EglBadCurrentSurface = priv::ErrorStream<EGL_BAD_CURRENT_SURFACE>;
+using EglBadDisplay = priv::ErrorStream<EGL_BAD_DISPLAY>;
+using EglBadMatch = priv::ErrorStream<EGL_BAD_MATCH>;
+using EglBadNativeWindow = priv::ErrorStream<EGL_BAD_NATIVE_WINDOW>;
+using EglBadParameter = priv::ErrorStream<EGL_BAD_PARAMETER>;
+using EglBadSurface = priv::ErrorStream<EGL_BAD_SURFACE>;
+using EglContextLost = priv::ErrorStream<EGL_CONTEXT_LOST>;
+using EglBadStream = priv::ErrorStream<EGL_BAD_STREAM_KHR>;
+using EglBadState = priv::ErrorStream<EGL_BAD_STATE_KHR>;
+using EglBadDevice = priv::ErrorStream<EGL_BAD_DEVICE_EXT>;
+
+inline Error NoError()
+{
+ return Error(EGL_SUCCESS);
+}
+
} // namespace egl
+#define ANGLE_CONCAT1(x, y) x##y
+#define ANGLE_CONCAT2(x, y) ANGLE_CONCAT1(x, y)
+#define ANGLE_LOCAL_VAR ANGLE_CONCAT2(_localVar, __LINE__)
+
+#define ANGLE_TRY_TEMPLATE(EXPR, FUNC) \
+ { \
+ auto ANGLE_LOCAL_VAR = EXPR; \
+ if (ANGLE_LOCAL_VAR.isError()) \
+ { \
+ FUNC(ANGLE_LOCAL_VAR); \
+ } \
+ } \
+ ANGLE_EMPTY_STATEMENT
+
+#define ANGLE_RETURN(X) return X;
+#define ANGLE_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, ANGLE_RETURN);
+
+#define ANGLE_TRY_RESULT(EXPR, RESULT) \
+ { \
+ auto ANGLE_LOCAL_VAR = EXPR; \
+ if (ANGLE_LOCAL_VAR.isError()) \
+ { \
+ return ANGLE_LOCAL_VAR.getError(); \
+ } \
+ RESULT = ANGLE_LOCAL_VAR.getResult(); \
+ } \
+ ANGLE_EMPTY_STATEMENT
+
+// TODO(jmadill): Introduce way to store errors to a const Context.
+#define ANGLE_SWALLOW_ERR(EXPR) \
+ { \
+ auto ANGLE_LOCAL_VAR = EXPR; \
+ if (ANGLE_LOCAL_VAR.isError()) \
+ { \
+ ERR() << "Unhandled internal error: " << ANGLE_LOCAL_VAR; \
+ } \
+ } \
+ ANGLE_EMPTY_STATEMENT
+
+#undef ANGLE_LOCAL_VAR
+#undef ANGLE_CONCAT2
+#undef ANGLE_CONCAT1
+
#include "Error.inl"
#endif // LIBANGLE_ERROR_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Error.inl b/src/3rdparty/angle/src/libANGLE/Error.inl
index 900fc5fd03..4632830ce0 100644
--- a/src/3rdparty/angle/src/libANGLE/Error.inl
+++ b/src/3rdparty/angle/src/libANGLE/Error.inl
@@ -37,6 +37,21 @@ Error::Error(Error &&other)
{
}
+// automatic error type conversion
+Error::Error(egl::Error &&eglErr)
+ : mCode(GL_INVALID_OPERATION),
+ mID(0),
+ mMessage(std::move(eglErr.mMessage))
+{
+}
+
+Error::Error(egl::Error eglErr)
+ : mCode(GL_INVALID_OPERATION),
+ mID(0),
+ mMessage(std::move(eglErr.mMessage))
+{
+}
+
Error &Error::operator=(const Error &other)
{
mCode = other.mCode;
@@ -82,7 +97,7 @@ bool Error::isError() const
return (mCode != GL_NO_ERROR);
}
-}
+} // namespace gl
namespace egl
{
@@ -111,6 +126,21 @@ Error::Error(Error &&other)
{
}
+// automatic error type conversion
+Error::Error(gl::Error &&glErr)
+ : mCode(EGL_BAD_ACCESS),
+ mID(0),
+ mMessage(std::move(glErr.mMessage))
+{
+}
+
+Error::Error(gl::Error glErr)
+ : mCode(EGL_BAD_ACCESS),
+ mID(0),
+ mMessage(std::move(glErr.mMessage))
+{
+}
+
Error &Error::operator=(const Error &other)
{
mCode = other.mCode;
diff --git a/src/3rdparty/angle/src/libANGLE/ErrorStrings.h b/src/3rdparty/angle/src/libANGLE/ErrorStrings.h
new file mode 100644
index 0000000000..93d64482d9
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/ErrorStrings.h
@@ -0,0 +1,173 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ErrorStrings.h: Contains mapping of commonly used error messages
+
+#ifndef LIBANGLE_ERRORSTRINGS_H_
+#define LIBANGLE_ERRORSTRINGS_H_
+
+#define ERRMSG(name, message) \
+ static const constexpr char *kError##name = static_cast<const char *>(message);
+#define ANGLE_VALIDATION_ERR(context, error, errorName) \
+ context->handleError(error << kError##errorName)
+
+namespace gl
+{
+ERRMSG(BufferNotBound, "A buffer must be bound.");
+ERRMSG(CompressedTextureDimensionsMustMatchData,
+ "Compressed texture dimensions must exactly match the dimensions of the data passed in.");
+ERRMSG(CompressedTexturesNotAttachable, "Compressed textures cannot be attached to a framebuffer.");
+ERRMSG(CubemapFacesEqualDimensions, "Each cubemap face must have equal width and height.");
+ERRMSG(CubemapIncomplete,
+ "Texture is not cubemap complete. All cubemaps faces must be defined and be the same size.");
+ERRMSG(DefaultFramebufferInvalidAttachment,
+ "Invalid attachment when the default framebuffer is bound.");
+ERRMSG(DefaultFramebufferTarget, "It is invalid to change default FBO's attachments");
+ERRMSG(EnumNotSupported, "Enum is not currently supported.");
+ERRMSG(EnumRequiresGLES31, "Enum requires GLES 3.1");
+ERRMSG(ES31Required, "OpenGL ES 3.1 Required");
+ERRMSG(ES3Required, "OpenGL ES 3.0 Required.");
+ERRMSG(ExceedsMaxElement, "Element value exceeds maximum element index.");
+ERRMSG(ExpectedProgramName, "Expected a program name, but found a shader name.");
+ERRMSG(ExpectedShaderName, "Expected a shader name, but found a program name.");
+ERRMSG(ExtensionNotEnabled, "Extension is not enabled.");
+ERRMSG(FeedbackLoop, "Feedback loop formed between Framebuffer and active Texture.");
+ERRMSG(FramebufferIncompleteAttachment,
+ "Attachment type must be compatible with attachment object.");
+ERRMSG(GenerateMipmapNotAllowed, "Texture format does not support mipmap generation.");
+ERRMSG(IndexExceedsMaxActiveUniform, "Index exceeds program active uniform count.");
+ERRMSG(IndexExceedsMaxDrawBuffer, "Index exceeds MAX_DRAW_BUFFERS.");
+ERRMSG(IndexExceedsMaxVertexAttribute, "Index exceeds MAX_VERTEX_ATTRIBS.");
+ERRMSG(InsufficientBufferSize, "Insufficient buffer size.");
+ERRMSG(InsufficientVertexBufferSize, "Vertex buffer is not big enough for the draw call");
+ERRMSG(IntegerOverflow, "Integer overflow.");
+ERRMSG(InvalidAttachment, "Invalid Attachment Type.");
+ERRMSG(InvalidBlendEquation, "Invalid blend equation.");
+ERRMSG(InvalidBlendFunction, "Invalid blend function.");
+ERRMSG(InvalidBorder, "Border must be 0.");
+ERRMSG(InvalidBufferTypes, "Invalid buffer target enum.");
+ERRMSG(InvalidBufferUsage, "Invalid buffer usage enum.");
+ERRMSG(InvalidClearMask, "Invalid mask bits.");
+ERRMSG(InvalidConstantColor,
+ "CONSTANT_COLOR (or ONE_MINUS_CONSTANT_COLOR) and CONSTANT_ALPHA (or "
+ "ONE_MINUS_CONSTANT_ALPHA) cannot be used together as source and destination factors in the "
+ "blend function.");
+ERRMSG(InvalidCoverMode, "Invalid cover mode.");
+ERRMSG(InvalidCullMode, "Cull mode not recognized.");
+ERRMSG(InvalidDebugSeverity, "Invalid debug severity.");
+ERRMSG(InvalidDebugSource, "Invalid debug source.");
+ERRMSG(InvalidDebugType, "Invalid debug type.");
+ERRMSG(InvalidDepthRange, "Near value cannot be greater than far.");
+ERRMSG(InvalidDrawMode, "Invalid draw mode.");
+ERRMSG(InvalidDrawModeTransformFeedback,
+ "Draw mode must match current transform feedback object's draw mode.");
+ERRMSG(InvalidFillMode, "Invalid fill mode.");
+ERRMSG(InvalidFilterTexture, "Texture only supports NEAREST and LINEAR filtering.");
+ERRMSG(InvalidFormat, "Invalid format.");
+ERRMSG(InvalidFramebufferTarget, "Invalid framebuffer target.");
+ERRMSG(InvalidFramebufferTextureLevel, "Mipmap level must be 0 when attaching a texture.");
+ERRMSG(InvalidFramebufferAttachmentParameter, "Invalid parameter name for framebuffer attachment.");
+ERRMSG(InvalidInternalFormat, "Invalid internal format.");
+ERRMSG(InvalidMatrixMode, "Invalid matrix mode.");
+ERRMSG(InvalidMipLevel, "Level of detail outside of range.");
+ERRMSG(InvalidName, "Invalid name.");
+ERRMSG(InvalidNameCharacters, "Name contains invalid characters.");
+ERRMSG(InvalidPname, "Invalid pname.");
+ERRMSG(InvalidPrecision, "Invalid or unsupported precision type.");
+ERRMSG(InvalidProgramName, "Program object expected.");
+ERRMSG(InvalidQueryId, "Invalid query Id.");
+ERRMSG(InvalidQueryTarget, "Invalid query target.");
+ERRMSG(InvalidQueryType, "Invalid query type.");
+ERRMSG(InvalidRange, "Invalid range.");
+ERRMSG(InvalidRenderbufferInternalFormat, "Invalid renderbuffer internalformat.");
+ERRMSG(InvalidRenderbufferTarget, "Invalid renderbuffer target.");
+ERRMSG(InvalidRenderbufferTextureParameter, "Invalid parameter name for renderbuffer attachment.");
+ERRMSG(InvalidRenderbufferWidthHeight,
+ "Renderbuffer width and height cannot be negative and cannot exceed maximum texture size.");
+ERRMSG(InvalidSampleMaskNumber,
+ "MaskNumber cannot be greater than or equal to the value of MAX_SAMPLE_MASK_WORDS.");
+ERRMSG(InvalidSampler, "Sampler is not valid");
+ERRMSG(InvalidShaderName, "Shader object expected.");
+ERRMSG(InvalidShaderType, "Invalid shader type.");
+ERRMSG(InvalidStencil, "Invalid stencil.");
+ERRMSG(InvalidStencilBitMask, "Invalid stencil bit mask.");
+ERRMSG(InvalidTarget, "Invalid target.");
+ERRMSG(InvalidTextureFilterParam, "Texture filter not recognized.");
+ERRMSG(InvalidTextureRange, "Cannot be less than 0 or greater than maximum number of textures.");
+ERRMSG(InvalidTextureTarget, "Invalid or unsupported texture target.");
+ERRMSG(InvalidTextureWrap, "Texture wrap mode not recognized.");
+ERRMSG(InvalidType, "Invalid type.");
+ERRMSG(InvalidTypePureInt, "Invalid type, should be integer");
+ERRMSG(InvalidUnpackAlignment, "Unpack alignment must be 1, 2, 4, or 8.");
+ERRMSG(InvalidVertexAttrSize, "Vertex attribute size must be 1, 2, 3, or 4.");
+ERRMSG(InvalidWidth, "Invalid width.");
+ERRMSG(InvalidWrapModeTexture, "Invalid wrap mode for texture type.");
+ERRMSG(LevelNotZero, "Texture level must be zero.");
+ERRMSG(MismatchedByteCountType, "Buffer size does not align with data type.");
+ERRMSG(MismatchedFormat, "Format must match internal format.");
+ERRMSG(MismatchedTargetAndFormat, "Invalid texture target and format combination.");
+ERRMSG(MismatchedTypeAndFormat, "Invalid format and type combination.");
+ERRMSG(MismatchedVariableProgram, "Variable is not part of the current program.");
+ERRMSG(MissingReadAttachment, "Missing read attachment.");
+ERRMSG(MustHaveElementArrayBinding, "Must have element array buffer binding.");
+ERRMSG(NameBeginsWithGL, "Attributes that begin with 'gl_' are not allowed.");
+ERRMSG(NegativeAttachments, "Negative number of attachments.");
+ERRMSG(NegativeBufferSize, "Negative buffer size.");
+ERRMSG(NegativeCount, "Negative count.");
+ERRMSG(NegativeLength, "Negative length.");
+ERRMSG(NegativeMaxCount, "Negative maxcount.");
+ERRMSG(NegativeOffset, "Negative offset.");
+ERRMSG(NegativePrimcount, "Primcount must be greater than or equal to zero.");
+ERRMSG(NegativeSize, "Cannot have negative height or width.");
+ERRMSG(NegativeStart, "Cannot have negative start.");
+ERRMSG(NegativeStride, "Cannot have negative stride.");
+ERRMSG(NoSuchPath, "No such path object.");
+ERRMSG(NoTransformFeedbackOutputVariables,
+ "The active program has specified no output variables to record.");
+ERRMSG(NoZeroDivisor, "At least one enabled attribute must have a divisor of zero.");
+ERRMSG(ObjectNotGenerated, "Object cannot be used because it has not been generated.");
+ERRMSG(OffsetMustBeMultipleOfType, "Offset must be a multiple of the passed in datatype.");
+ERRMSG(OutsideOfBounds, "Parameter outside of bounds.");
+ERRMSG(ParamOverflow, "The provided parameters overflow with the provided buffer.");
+ERRMSG(PixelDataNotNull, "Pixel data must be null.");
+ERRMSG(PixelDataNull, "Pixel data cannot be null.");
+ERRMSG(ProgramDoesNotExist, "Program doesn't exist.");
+ERRMSG(ProgramNotBound, "A program must be bound.");
+ERRMSG(ProgramNotLinked, "Program not linked.");
+ERRMSG(QueryActive, "Query is active.");
+ERRMSG(QueryExtensionNotEnabled, "Query extension not enabled.");
+ERRMSG(ReadBufferNone, "Read buffer is GL_NONE.");
+ERRMSG(RenderbufferNotBound, "A renderbuffer must be bound.");
+ERRMSG(ResourceMaxTextureSize, "Desired resource size is greater than max texture size.");
+ERRMSG(ShaderAttachmentHasShader, "Shader attachment already has a shader.");
+ERRMSG(ShaderSourceInvalidCharacters, "Shader source contains invalid characters.");
+ERRMSG(ShaderToDetachMustBeAttached,
+ "Shader to be detached must be currently attached to the program.");
+ERRMSG(SourceTextureTooSmall, "The specified dimensions are outside of the bounds of the texture.");
+ERRMSG(StencilReferenceMaskOrMismatch,
+ "Stencil reference and mask values must be the same for front facing and back facing "
+ "triangles.");
+ERRMSG(StrideMustBeMultipleOfType, "Stride must be a multiple of the passed in datatype.");
+ERRMSG(TextureNotBound, "A texture must be bound.");
+ERRMSG(TextureNotPow2, "The texture is a non-power-of-two texture.");
+ERRMSG(TransformFeedbackDoesNotExist, "Transform feedback object that does not exist.");
+ERRMSG(TypeMismatch,
+ "Passed in texture target and format must match the one originally used to define the "
+ "texture.");
+ERRMSG(TypeNotUnsignedShortByte, "Only UNSIGNED_SHORT and UNSIGNED_BYTE types are supported.");
+ERRMSG(UniformSizeMismatch, "Uniform size does not match uniform method.");
+ERRMSG(UnknownParameter, "Unknown parameter value.");
+ERRMSG(VertexArrayNoBuffer, "An enabled vertex array has no buffer.");
+ERRMSG(VertexArrayNoBufferPointer, "An enabled vertex array has no buffer and no pointer.");
+ERRMSG(ViewportNegativeSize, "Viewport size cannot be negative.");
+ERRMSG(Webgl2NameLengthLimitExceeded, "Location lengths must not be greater than 1024 characters.");
+ERRMSG(WebglBindAttribLocationReservedPrefix,
+ "Attributes that begin with 'webgl_', or '_webgl_' are not allowed.");
+ERRMSG(WebglNameLengthLimitExceeded,
+ "Location name lengths must not be greater than 256 characters.");
+}
+#undef ERRMSG
+#endif // LIBANGLE_ERRORSTRINGS_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Fence.cpp b/src/3rdparty/angle/src/libANGLE/Fence.cpp
index ff32f4bbe9..9c4d381673 100644
--- a/src/3rdparty/angle/src/libANGLE/Fence.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Fence.cpp
@@ -4,18 +4,17 @@
// found in the LICENSE file.
//
-// Fence.cpp: Implements the gl::FenceNV and gl::FenceSync classes, which support the GL_NV_fence
+// Fence.cpp: Implements the gl::FenceNV and gl::Sync classes, which support the GL_NV_fence
// extension and GLES3 sync objects.
#include "libANGLE/Fence.h"
-#include "libANGLE/renderer/FenceNVImpl.h"
-#include "libANGLE/renderer/FenceSyncImpl.h"
-#include "libANGLE/renderer/Renderer.h"
-#include "common/utilities.h"
-
#include "angle_gl.h"
+#include "common/utilities.h"
+#include "libANGLE/renderer/FenceNVImpl.h"
+#include "libANGLE/renderer/SyncImpl.h"
+
namespace gl
{
@@ -44,7 +43,7 @@ Error FenceNV::set(GLenum condition)
mStatus = GL_FALSE;
mIsSet = true;
- return Error(GL_NO_ERROR);
+ return NoError();
}
Error FenceNV::test(GLboolean *outResult)
@@ -57,7 +56,7 @@ Error FenceNV::test(GLboolean *outResult)
}
*outResult = mStatus;
- return Error(GL_NO_ERROR);
+ return NoError();
}
Error FenceNV::finish()
@@ -72,30 +71,39 @@ Error FenceNV::finish()
mStatus = GL_TRUE;
- return Error(GL_NO_ERROR);
+ return NoError();
}
-FenceSync::FenceSync(rx::FenceSyncImpl *impl, GLuint id)
- : RefCountObject(id), mFence(impl), mLabel(), mCondition(GL_NONE), mFlags(0)
+Sync::Sync(rx::SyncImpl *impl, GLuint id)
+ : RefCountObject(id),
+ mFence(impl),
+ mLabel(),
+ mCondition(GL_SYNC_GPU_COMMANDS_COMPLETE),
+ mFlags(0)
{
}
-FenceSync::~FenceSync()
+Error Sync::onDestroy(const Context *context)
+{
+ return NoError();
+}
+
+Sync::~Sync()
{
SafeDelete(mFence);
}
-void FenceSync::setLabel(const std::string &label)
+void Sync::setLabel(const std::string &label)
{
mLabel = label;
}
-const std::string &FenceSync::getLabel() const
+const std::string &Sync::getLabel() const
{
return mLabel;
}
-Error FenceSync::set(GLenum condition, GLbitfield flags)
+Error Sync::set(GLenum condition, GLbitfield flags)
{
Error error = mFence->set(condition, flags);
if (error.isError())
@@ -105,23 +113,23 @@ Error FenceSync::set(GLenum condition, GLbitfield flags)
mCondition = condition;
mFlags = flags;
- return Error(GL_NO_ERROR);
+ return NoError();
}
-Error FenceSync::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult)
+Error Sync::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult)
{
ASSERT(mCondition != GL_NONE);
return mFence->clientWait(flags, timeout, outResult);
}
-Error FenceSync::serverWait(GLbitfield flags, GLuint64 timeout)
+Error Sync::serverWait(GLbitfield flags, GLuint64 timeout)
{
return mFence->serverWait(flags, timeout);
}
-Error FenceSync::getStatus(GLint *outResult) const
+Error Sync::getStatus(GLint *outResult) const
{
return mFence->getStatus(outResult);
}
-}
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/Fence.h b/src/3rdparty/angle/src/libANGLE/Fence.h
index b2daed6f0e..24bc689ca3 100644
--- a/src/3rdparty/angle/src/libANGLE/Fence.h
+++ b/src/3rdparty/angle/src/libANGLE/Fence.h
@@ -4,7 +4,7 @@
// found in the LICENSE file.
//
-// Fence.h: Defines the gl::FenceNV and gl::FenceSync classes, which support the GL_NV_fence
+// Fence.h: Defines the gl::FenceNV and gl::Sync classes, which support the GL_NV_fence
// extension and GLES3 sync objects.
#ifndef LIBANGLE_FENCE_H_
@@ -19,7 +19,7 @@
namespace rx
{
class FenceNVImpl;
-class FenceSyncImpl;
+class SyncImpl;
}
namespace gl
@@ -48,11 +48,13 @@ class FenceNV final : angle::NonCopyable
GLenum mCondition;
};
-class FenceSync final : public RefCountObject, public LabeledObject
+class Sync final : public RefCountObject, public LabeledObject
{
public:
- FenceSync(rx::FenceSyncImpl *impl, GLuint id);
- virtual ~FenceSync();
+ Sync(rx::SyncImpl *impl, GLuint id);
+ ~Sync() override;
+
+ Error onDestroy(const Context *context) override;
void setLabel(const std::string &label) override;
const std::string &getLabel() const override;
@@ -66,7 +68,7 @@ class FenceSync final : public RefCountObject, public LabeledObject
GLbitfield getFlags() const { return mFlags; }
private:
- rx::FenceSyncImpl *mFence;
+ rx::SyncImpl *mFence;
std::string mLabel;
@@ -74,6 +76,6 @@ class FenceSync final : public RefCountObject, public LabeledObject
GLbitfield mFlags;
};
-}
+} // namespace gl
#endif // LIBANGLE_FENCE_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp b/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp
index 3def57b87e..48e71685b3 100644
--- a/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp
@@ -10,72 +10,349 @@
#include "libANGLE/Framebuffer.h"
#include "common/Optional.h"
+#include "common/bitset_utils.h"
#include "common/utilities.h"
#include "libANGLE/Config.h"
#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/Renderbuffer.h"
#include "libANGLE/Surface.h"
#include "libANGLE/Texture.h"
#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/ContextImpl.h"
#include "libANGLE/renderer/FramebufferImpl.h"
-#include "libANGLE/renderer/ImplFactory.h"
+#include "libANGLE/renderer/GLImplFactory.h"
#include "libANGLE/renderer/RenderbufferImpl.h"
#include "libANGLE/renderer/SurfaceImpl.h"
+using namespace angle;
+
namespace gl
{
namespace
{
-void DetachMatchingAttachment(FramebufferAttachment *attachment, GLenum matchType, GLuint matchId)
+
+void BindResourceChannel(OnAttachmentDirtyBinding *binding, FramebufferAttachmentObject *resource)
+{
+ binding->bind(resource ? resource->getDirtyChannel() : nullptr);
+}
+
+bool CheckMultiviewStateMatchesForCompleteness(const FramebufferAttachment *firstAttachment,
+ const FramebufferAttachment *secondAttachment)
{
- if (attachment->isAttached() &&
- attachment->type() == matchType &&
- attachment->id() == matchId)
+ ASSERT(firstAttachment && secondAttachment);
+ ASSERT(firstAttachment->isAttached() && secondAttachment->isAttached());
+
+ if (firstAttachment->getNumViews() != secondAttachment->getNumViews())
+ {
+ return false;
+ }
+ if (firstAttachment->getBaseViewIndex() != secondAttachment->getBaseViewIndex())
+ {
+ return false;
+ }
+ if (firstAttachment->getMultiviewLayout() != secondAttachment->getMultiviewLayout())
{
- attachment->detach();
+ return false;
+ }
+ if (firstAttachment->getMultiviewViewportOffsets() !=
+ secondAttachment->getMultiviewViewportOffsets())
+ {
+ return false;
}
+ return true;
}
+
+bool CheckAttachmentCompleteness(const Context *context, const FramebufferAttachment &attachment)
+{
+ ASSERT(attachment.isAttached());
+
+ const Extents &size = attachment.getSize();
+ if (size.width == 0 || size.height == 0)
+ {
+ return false;
+ }
+
+ const InternalFormat &format = *attachment.getFormat().info;
+ if (!format.renderSupport(context->getClientVersion(), context->getExtensions()))
+ {
+ return false;
+ }
+
+ if (attachment.type() == GL_TEXTURE)
+ {
+ if (attachment.layer() >= size.depth)
+ {
+ return false;
+ }
+
+ // ES3 specifies that cube map texture attachments must be cube complete.
+ // This language is missing from the ES2 spec, but we enforce it here because some
+ // desktop OpenGL drivers also enforce this validation.
+ // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
+ const Texture *texture = attachment.getTexture();
+ ASSERT(texture);
+ if (texture->getTarget() == GL_TEXTURE_CUBE_MAP &&
+ !texture->getTextureState().isCubeComplete())
+ {
+ return false;
+ }
+
+ if (!texture->getImmutableFormat())
+ {
+ GLuint attachmentMipLevel = static_cast<GLuint>(attachment.mipLevel());
+
+ // From the ES 3.0 spec, pg 213:
+ // If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of
+ // FRAMEBUFFER_ATTACHMENT_OBJECT_NAME does not name an immutable-format texture,
+ // then the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL must be in the
+ // range[levelbase, q], where levelbase is the value of TEXTURE_BASE_LEVEL and q is
+ // the effective maximum texture level defined in the Mipmapping discussion of
+ // section 3.8.10.4.
+ if (attachmentMipLevel < texture->getBaseLevel() ||
+ attachmentMipLevel > texture->getMipmapMaxLevel())
+ {
+ return false;
+ }
+
+ // Form the ES 3.0 spec, pg 213/214:
+ // If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of
+ // FRAMEBUFFER_ATTACHMENT_OBJECT_NAME does not name an immutable-format texture and
+ // the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL is not levelbase, then the
+ // texture must be mipmap complete, and if FRAMEBUFFER_ATTACHMENT_OBJECT_NAME names
+ // a cubemap texture, the texture must also be cube complete.
+ if (attachmentMipLevel != texture->getBaseLevel() && !texture->isMipmapComplete())
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+};
+
+bool CheckAttachmentSampleCompleteness(const Context *context,
+ const FramebufferAttachment &attachment,
+ bool colorAttachment,
+ Optional<int> *samples,
+ Optional<bool> *fixedSampleLocations)
+{
+ ASSERT(attachment.isAttached());
+
+ if (attachment.type() == GL_TEXTURE)
+ {
+ const Texture *texture = attachment.getTexture();
+ ASSERT(texture);
+
+ const ImageIndex &attachmentImageIndex = attachment.getTextureImageIndex();
+
+ // ES3.1 (section 9.4) requires that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS should be
+ // the same for all attached textures.
+ bool fixedSampleloc = texture->getFixedSampleLocations(attachmentImageIndex.type,
+ attachmentImageIndex.mipIndex);
+ if (fixedSampleLocations->valid() && fixedSampleloc != fixedSampleLocations->value())
+ {
+ return false;
+ }
+ else
+ {
+ *fixedSampleLocations = fixedSampleloc;
+ }
+ }
+
+ if (samples->valid())
+ {
+ if (attachment.getSamples() != samples->value())
+ {
+ if (colorAttachment)
+ {
+ // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
+ // all color attachments have the same number of samples for the FBO to be complete.
+ return false;
+ }
+ else
+ {
+ // CHROMIUM_framebuffer_mixed_samples allows a framebuffer to be considered complete
+ // when its depth or stencil samples are a multiple of the number of color samples.
+ if (!context->getExtensions().framebufferMixedSamples)
+ {
+ return false;
+ }
+
+ if ((attachment.getSamples() % std::max(samples->value(), 1)) != 0)
+ {
+ return false;
+ }
+ }
+ }
+ }
+ else
+ {
+ *samples = attachment.getSamples();
+ }
+
+ return true;
+}
+
+// Needed to index into the attachment arrays/bitsets.
+static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS) ==
+ gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX,
+ "Framebuffer Dirty bit mismatch");
+static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS) ==
+ gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT,
+ "Framebuffer Dirty bit mismatch");
+static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS + 1) ==
+ gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT,
+ "Framebuffer Dirty bit mismatch");
+
+Error InitAttachment(const Context *context, FramebufferAttachment *attachment)
+{
+ ASSERT(attachment->isAttached());
+ if (attachment->initState() == InitState::MayNeedInit)
+ {
+ ANGLE_TRY(attachment->initializeContents(context));
+ }
+ return NoError();
+}
+
+bool IsColorMaskedOut(const BlendState &blend)
+{
+ return (!blend.colorMaskRed && !blend.colorMaskGreen && !blend.colorMaskBlue &&
+ !blend.colorMaskAlpha);
+}
+
+bool IsDepthMaskedOut(const DepthStencilState &depthStencil)
+{
+ return !depthStencil.depthMask;
+}
+
+bool IsStencilMaskedOut(const DepthStencilState &depthStencil)
+{
+ return ((depthStencil.stencilMask & depthStencil.stencilWritemask) == 0);
+}
+
+bool IsClearBufferMaskedOut(const Context *context, GLenum buffer)
+{
+ switch (buffer)
+ {
+ case GL_COLOR:
+ return IsColorMaskedOut(context->getGLState().getBlendState());
+ case GL_DEPTH:
+ return IsDepthMaskedOut(context->getGLState().getDepthStencilState());
+ case GL_STENCIL:
+ return IsStencilMaskedOut(context->getGLState().getDepthStencilState());
+ case GL_DEPTH_STENCIL:
+ return IsDepthMaskedOut(context->getGLState().getDepthStencilState()) &&
+ IsStencilMaskedOut(context->getGLState().getDepthStencilState());
+ default:
+ UNREACHABLE();
+ return true;
+ }
}
-Framebuffer::Data::Data()
+} // anonymous namespace
+
+// This constructor is only used for default framebuffers.
+FramebufferState::FramebufferState()
: mLabel(),
mColorAttachments(1),
- mDrawBufferStates(1, GL_NONE),
- mReadBufferState(GL_COLOR_ATTACHMENT0_EXT)
+ mDrawBufferStates(1, GL_BACK),
+ mReadBufferState(GL_BACK),
+ mDefaultWidth(0),
+ mDefaultHeight(0),
+ mDefaultSamples(0),
+ mDefaultFixedSampleLocations(GL_FALSE),
+ mWebGLDepthStencilConsistent(true)
{
- mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
+ ASSERT(mDrawBufferStates.size() > 0);
+ mEnabledDrawBuffers.set(0);
}
-Framebuffer::Data::Data(const Caps &caps)
+FramebufferState::FramebufferState(const Caps &caps)
: mLabel(),
mColorAttachments(caps.maxColorAttachments),
mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
- mReadBufferState(GL_COLOR_ATTACHMENT0_EXT)
+ mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
+ mDefaultWidth(0),
+ mDefaultHeight(0),
+ mDefaultSamples(0),
+ mDefaultFixedSampleLocations(GL_FALSE),
+ mWebGLDepthStencilConsistent(true)
{
ASSERT(mDrawBufferStates.size() > 0);
mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
}
-Framebuffer::Data::~Data()
+FramebufferState::~FramebufferState()
{
}
-const std::string &Framebuffer::Data::getLabel()
+const std::string &FramebufferState::getLabel()
{
return mLabel;
}
-const FramebufferAttachment *Framebuffer::Data::getReadAttachment() const
+const FramebufferAttachment *FramebufferState::getAttachment(GLenum attachment) const
+{
+ if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
+ {
+ return getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
+ }
+
+ switch (attachment)
+ {
+ case GL_COLOR:
+ case GL_BACK:
+ return getColorAttachment(0);
+ case GL_DEPTH:
+ case GL_DEPTH_ATTACHMENT:
+ return getDepthAttachment();
+ case GL_STENCIL:
+ case GL_STENCIL_ATTACHMENT:
+ return getStencilAttachment();
+ case GL_DEPTH_STENCIL:
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ return getDepthStencilAttachment();
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+}
+
+size_t FramebufferState::getReadIndex() const
{
- ASSERT(mReadBufferState == GL_BACK || (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
- size_t readIndex = (mReadBufferState == GL_BACK ? 0 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
+ ASSERT(mReadBufferState == GL_BACK ||
+ (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
+ size_t readIndex = (mReadBufferState == GL_BACK
+ ? 0
+ : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
ASSERT(readIndex < mColorAttachments.size());
+ return readIndex;
+}
+
+const FramebufferAttachment *FramebufferState::getReadAttachment() const
+{
+ if (mReadBufferState == GL_NONE)
+ {
+ return nullptr;
+ }
+ size_t readIndex = getReadIndex();
return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr;
}
-const FramebufferAttachment *Framebuffer::Data::getFirstColorAttachment() const
+const FramebufferAttachment *FramebufferState::getFirstNonNullAttachment() const
+{
+ auto *colorAttachment = getFirstColorAttachment();
+ if (colorAttachment)
+ {
+ return colorAttachment;
+ }
+ return getDepthOrStencilAttachment();
+}
+
+const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const
{
for (const FramebufferAttachment &colorAttachment : mColorAttachments)
{
@@ -88,7 +365,7 @@ const FramebufferAttachment *Framebuffer::Data::getFirstColorAttachment() const
return nullptr;
}
-const FramebufferAttachment *Framebuffer::Data::getDepthOrStencilAttachment() const
+const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const
{
if (mDepthAttachment.isAttached())
{
@@ -101,31 +378,38 @@ const FramebufferAttachment *Framebuffer::Data::getDepthOrStencilAttachment() co
return nullptr;
}
-const FramebufferAttachment *Framebuffer::Data::getColorAttachment(size_t colorAttachment) const
+const FramebufferAttachment *FramebufferState::getStencilOrDepthStencilAttachment() const
+{
+ if (mStencilAttachment.isAttached())
+ {
+ return &mStencilAttachment;
+ }
+ return getDepthStencilAttachment();
+}
+
+const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const
{
ASSERT(colorAttachment < mColorAttachments.size());
- return mColorAttachments[colorAttachment].isAttached() ?
- &mColorAttachments[colorAttachment] :
- nullptr;
+ return mColorAttachments[colorAttachment].isAttached() ? &mColorAttachments[colorAttachment]
+ : nullptr;
}
-const FramebufferAttachment *Framebuffer::Data::getDepthAttachment() const
+const FramebufferAttachment *FramebufferState::getDepthAttachment() const
{
return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
}
-const FramebufferAttachment *Framebuffer::Data::getStencilAttachment() const
+const FramebufferAttachment *FramebufferState::getStencilAttachment() const
{
return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
}
-const FramebufferAttachment *Framebuffer::Data::getDepthStencilAttachment() const
+const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const
{
// A valid depth-stencil attachment has the same resource bound to both the
// depth and stencil attachment points.
if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
- mDepthAttachment.type() == mStencilAttachment.type() &&
- mDepthAttachment.id() == mStencilAttachment.id())
+ mDepthAttachment == mStencilAttachment)
{
return &mDepthAttachment;
}
@@ -133,12 +417,11 @@ const FramebufferAttachment *Framebuffer::Data::getDepthStencilAttachment() cons
return nullptr;
}
-bool Framebuffer::Data::attachmentsHaveSameDimensions() const
+bool FramebufferState::attachmentsHaveSameDimensions() const
{
Optional<Extents> attachmentSize;
- auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment)
- {
+ auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment) {
if (!attachment.isAttached())
{
return false;
@@ -150,7 +433,9 @@ bool Framebuffer::Data::attachmentsHaveSameDimensions() const
return false;
}
- return (attachment.getSize() != attachmentSize.value());
+ const auto &prevSize = attachmentSize.value();
+ const auto &curSize = attachment.getSize();
+ return (curSize.width != prevSize.width || curSize.height != prevSize.height);
};
for (const auto &attachment : mColorAttachments)
@@ -169,17 +454,184 @@ bool Framebuffer::Data::attachmentsHaveSameDimensions() const
return !hasMismatchedSize(mStencilAttachment);
}
-Framebuffer::Framebuffer(const Caps &caps, rx::ImplFactory *factory, GLuint id)
- : mData(caps), mImpl(factory->createFramebuffer(mData)), mId(id)
+const gl::FramebufferAttachment *FramebufferState::getDrawBuffer(size_t drawBufferIdx) const
+{
+ ASSERT(drawBufferIdx < mDrawBufferStates.size());
+ if (mDrawBufferStates[drawBufferIdx] != GL_NONE)
+ {
+ // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
+ // must be COLOR_ATTACHMENTi or NONE"
+ ASSERT(mDrawBufferStates[drawBufferIdx] == GL_COLOR_ATTACHMENT0 + drawBufferIdx ||
+ (drawBufferIdx == 0 && mDrawBufferStates[drawBufferIdx] == GL_BACK));
+ return getAttachment(mDrawBufferStates[drawBufferIdx]);
+ }
+ else
+ {
+ return nullptr;
+ }
+}
+
+size_t FramebufferState::getDrawBufferCount() const
+{
+ return mDrawBufferStates.size();
+}
+
+bool FramebufferState::colorAttachmentsAreUniqueImages() const
+{
+ for (size_t firstAttachmentIdx = 0; firstAttachmentIdx < mColorAttachments.size();
+ firstAttachmentIdx++)
+ {
+ const gl::FramebufferAttachment &firstAttachment = mColorAttachments[firstAttachmentIdx];
+ if (!firstAttachment.isAttached())
+ {
+ continue;
+ }
+
+ for (size_t secondAttachmentIdx = firstAttachmentIdx + 1;
+ secondAttachmentIdx < mColorAttachments.size(); secondAttachmentIdx++)
+ {
+ const gl::FramebufferAttachment &secondAttachment =
+ mColorAttachments[secondAttachmentIdx];
+ if (!secondAttachment.isAttached())
+ {
+ continue;
+ }
+
+ if (firstAttachment == secondAttachment)
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool FramebufferState::hasDepth() const
+{
+ return (mDepthAttachment.isAttached() && mDepthAttachment.getDepthSize() > 0);
+}
+
+bool FramebufferState::hasStencil() const
+{
+ return (mStencilAttachment.isAttached() && mStencilAttachment.getStencilSize() > 0);
+}
+
+GLsizei FramebufferState::getNumViews() const
+{
+ const FramebufferAttachment *attachment = getFirstNonNullAttachment();
+ if (attachment == nullptr)
+ {
+ return FramebufferAttachment::kDefaultNumViews;
+ }
+ return attachment->getNumViews();
+}
+
+const std::vector<Offset> *FramebufferState::getViewportOffsets() const
+{
+ const FramebufferAttachment *attachment = getFirstNonNullAttachment();
+ if (attachment == nullptr)
+ {
+ return nullptr;
+ }
+ return &attachment->getMultiviewViewportOffsets();
+}
+
+GLenum FramebufferState::getMultiviewLayout() const
+{
+ const FramebufferAttachment *attachment = getFirstNonNullAttachment();
+ if (attachment == nullptr)
+ {
+ return GL_NONE;
+ }
+ return attachment->getMultiviewLayout();
+}
+
+int FramebufferState::getBaseViewIndex() const
+{
+ const FramebufferAttachment *attachment = getFirstNonNullAttachment();
+ if (attachment == nullptr)
+ {
+ return GL_NONE;
+ }
+ return attachment->getBaseViewIndex();
+}
+
+Box FramebufferState::getDimensions() const
+{
+ ASSERT(attachmentsHaveSameDimensions());
+ ASSERT(getFirstNonNullAttachment() != nullptr);
+ Extents extents = getFirstNonNullAttachment()->getSize();
+ return Box(0, 0, 0, extents.width, extents.height, extents.depth);
+}
+
+Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id)
+ : mState(caps),
+ mImpl(factory->createFramebuffer(mState)),
+ mId(id),
+ mCachedStatus(),
+ mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
+ mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
{
ASSERT(mId != 0);
ASSERT(mImpl != nullptr);
+ ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments));
+
+ for (uint32_t colorIndex = 0;
+ colorIndex < static_cast<uint32_t>(mState.mColorAttachments.size()); ++colorIndex)
+ {
+ mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
+ }
}
-Framebuffer::Framebuffer(rx::SurfaceImpl *surface)
- : mData(), mImpl(surface->createDefaultFramebuffer(mData)), mId(0)
+Framebuffer::Framebuffer(const egl::Display *display, egl::Surface *surface)
+ : mState(),
+ mImpl(surface->getImplementation()->createDefaultFramebuffer(mState)),
+ mId(0),
+ mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
+ mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
+ mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
{
ASSERT(mImpl != nullptr);
+ mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
+
+ const Context *proxyContext = display->getProxyContext();
+
+ setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_BACK, gl::ImageIndex::MakeInvalid(),
+ surface, FramebufferAttachment::kDefaultNumViews,
+ FramebufferAttachment::kDefaultBaseViewIndex,
+ FramebufferAttachment::kDefaultMultiviewLayout,
+ FramebufferAttachment::kDefaultViewportOffsets);
+
+ if (surface->getConfig()->depthSize > 0)
+ {
+ setAttachmentImpl(
+ proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, gl::ImageIndex::MakeInvalid(), surface,
+ FramebufferAttachment::kDefaultNumViews, FramebufferAttachment::kDefaultBaseViewIndex,
+ FramebufferAttachment::kDefaultMultiviewLayout,
+ FramebufferAttachment::kDefaultViewportOffsets);
+ }
+
+ if (surface->getConfig()->stencilSize > 0)
+ {
+ setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_STENCIL,
+ gl::ImageIndex::MakeInvalid(), surface,
+ FramebufferAttachment::kDefaultNumViews,
+ FramebufferAttachment::kDefaultBaseViewIndex,
+ FramebufferAttachment::kDefaultMultiviewLayout,
+ FramebufferAttachment::kDefaultViewportOffsets);
+ }
+}
+
+Framebuffer::Framebuffer(rx::GLImplFactory *factory)
+ : mState(),
+ mImpl(factory->createFramebuffer(mState)),
+ mId(0),
+ mCachedStatus(GL_FRAMEBUFFER_UNDEFINED_OES),
+ mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
+ mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
+{
+ mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
}
Framebuffer::~Framebuffer()
@@ -187,148 +639,227 @@ Framebuffer::~Framebuffer()
SafeDelete(mImpl);
}
+void Framebuffer::onDestroy(const Context *context)
+{
+ for (auto &attachment : mState.mColorAttachments)
+ {
+ attachment.detach(context);
+ }
+ mState.mDepthAttachment.detach(context);
+ mState.mStencilAttachment.detach(context);
+ mState.mWebGLDepthAttachment.detach(context);
+ mState.mWebGLStencilAttachment.detach(context);
+ mState.mWebGLDepthStencilAttachment.detach(context);
+
+ mImpl->destroy(context);
+}
+
+void Framebuffer::destroyDefault(const egl::Display *display)
+{
+ mImpl->destroyDefault(display);
+}
+
void Framebuffer::setLabel(const std::string &label)
{
- mData.mLabel = label;
+ mState.mLabel = label;
}
const std::string &Framebuffer::getLabel() const
{
- return mData.mLabel;
+ return mState.mLabel;
}
-void Framebuffer::detachTexture(GLuint textureId)
+bool Framebuffer::detachTexture(const Context *context, GLuint textureId)
{
- detachResourceById(GL_TEXTURE, textureId);
+ return detachResourceById(context, GL_TEXTURE, textureId);
}
-void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
+bool Framebuffer::detachRenderbuffer(const Context *context, GLuint renderbufferId)
{
- detachResourceById(GL_RENDERBUFFER, renderbufferId);
+ return detachResourceById(context, GL_RENDERBUFFER, renderbufferId);
}
-void Framebuffer::detachResourceById(GLenum resourceType, GLuint resourceId)
+bool Framebuffer::detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId)
{
- for (auto &colorAttachment : mData.mColorAttachments)
+ bool found = false;
+
+ for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
+ {
+ if (detachMatchingAttachment(context, &mState.mColorAttachments[colorIndex], resourceType,
+ resourceId, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex))
+ {
+ found = true;
+ }
+ }
+
+ if (context->isWebGL1())
+ {
+ const std::array<FramebufferAttachment *, 3> attachments = {
+ {&mState.mWebGLDepthStencilAttachment, &mState.mWebGLDepthAttachment,
+ &mState.mWebGLStencilAttachment}};
+ for (FramebufferAttachment *attachment : attachments)
+ {
+ if (attachment->isAttached() && attachment->type() == resourceType &&
+ attachment->id() == resourceId)
+ {
+ resetAttachment(context, attachment->getBinding());
+ found = true;
+ }
+ }
+ }
+ else
{
- DetachMatchingAttachment(&colorAttachment, resourceType, resourceId);
+ if (detachMatchingAttachment(context, &mState.mDepthAttachment, resourceType, resourceId,
+ DIRTY_BIT_DEPTH_ATTACHMENT))
+ {
+ found = true;
+ }
+ if (detachMatchingAttachment(context, &mState.mStencilAttachment, resourceType, resourceId,
+ DIRTY_BIT_STENCIL_ATTACHMENT))
+ {
+ found = true;
+ }
}
- DetachMatchingAttachment(&mData.mDepthAttachment, resourceType, resourceId);
- DetachMatchingAttachment(&mData.mStencilAttachment, resourceType, resourceId);
+ return found;
+}
+
+bool Framebuffer::detachMatchingAttachment(const Context *context,
+ FramebufferAttachment *attachment,
+ GLenum matchType,
+ GLuint matchId,
+ size_t dirtyBit)
+{
+ if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
+ {
+ attachment->detach(context);
+ mDirtyBits.set(dirtyBit);
+ mState.mResourceNeedsInit.set(dirtyBit, false);
+ return true;
+ }
+
+ return false;
}
const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const
{
- return mData.getColorAttachment(colorAttachment);
+ return mState.getColorAttachment(colorAttachment);
}
const FramebufferAttachment *Framebuffer::getDepthbuffer() const
{
- return mData.getDepthAttachment();
+ return mState.getDepthAttachment();
}
const FramebufferAttachment *Framebuffer::getStencilbuffer() const
{
- return mData.getStencilAttachment();
+ return mState.getStencilAttachment();
}
const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
{
- return mData.getDepthStencilAttachment();
+ return mState.getDepthStencilAttachment();
}
const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
{
- return mData.getDepthOrStencilAttachment();
+ return mState.getDepthOrStencilAttachment();
+}
+
+const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const
+{
+ return mState.getStencilOrDepthStencilAttachment();
}
const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
{
- return mData.getReadAttachment();
+ return mState.getReadAttachment();
}
GLenum Framebuffer::getReadColorbufferType() const
{
- const FramebufferAttachment *readAttachment = mData.getReadAttachment();
+ const FramebufferAttachment *readAttachment = mState.getReadAttachment();
return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
}
const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
{
- return mData.getFirstColorAttachment();
+ return mState.getFirstColorAttachment();
+}
+
+const FramebufferAttachment *Framebuffer::getFirstNonNullAttachment() const
+{
+ return mState.getFirstNonNullAttachment();
}
const FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
{
- if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
- {
- return mData.getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
- }
- else
- {
- switch (attachment)
- {
- case GL_COLOR:
- case GL_BACK:
- return mData.getColorAttachment(0);
- case GL_DEPTH:
- case GL_DEPTH_ATTACHMENT:
- return mData.getDepthAttachment();
- case GL_STENCIL:
- case GL_STENCIL_ATTACHMENT:
- return mData.getStencilAttachment();
- case GL_DEPTH_STENCIL:
- case GL_DEPTH_STENCIL_ATTACHMENT:
- return getDepthStencilBuffer();
- default:
- UNREACHABLE();
- return nullptr;
- }
- }
+ return mState.getAttachment(attachment);
}
size_t Framebuffer::getDrawbufferStateCount() const
{
- return mData.mDrawBufferStates.size();
+ return mState.mDrawBufferStates.size();
}
GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
{
- ASSERT(drawBuffer < mData.mDrawBufferStates.size());
- return mData.mDrawBufferStates[drawBuffer];
+ ASSERT(drawBuffer < mState.mDrawBufferStates.size());
+ return mState.mDrawBufferStates[drawBuffer];
+}
+
+const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
+{
+ return mState.getDrawBufferStates();
}
void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
{
- auto &drawStates = mData.mDrawBufferStates;
+ auto &drawStates = mState.mDrawBufferStates;
ASSERT(count <= drawStates.size());
std::copy(buffers, buffers + count, drawStates.begin());
std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
+
+ mState.mEnabledDrawBuffers.reset();
+ for (size_t index = 0; index < count; ++index)
+ {
+ if (drawStates[index] != GL_NONE && mState.mColorAttachments[index].isAttached())
+ {
+ mState.mEnabledDrawBuffers.set(index);
+ }
+ }
}
const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
{
- ASSERT(drawBuffer < mData.mDrawBufferStates.size());
- if (mData.mDrawBufferStates[drawBuffer] != GL_NONE)
+ return mState.getDrawBuffer(drawBuffer);
+}
+
+GLenum Framebuffer::getDrawbufferWriteType(size_t drawBuffer) const
+{
+ const FramebufferAttachment *attachment = mState.getDrawBuffer(drawBuffer);
+ if (attachment == nullptr)
{
- // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
- // must be COLOR_ATTACHMENTi or NONE"
- ASSERT(mData.mDrawBufferStates[drawBuffer] == GL_COLOR_ATTACHMENT0 + drawBuffer ||
- (drawBuffer == 0 && mData.mDrawBufferStates[drawBuffer] == GL_BACK));
- return getAttachment(mData.mDrawBufferStates[drawBuffer]);
+ return GL_NONE;
}
- else
+
+ GLenum componentType = attachment->getFormat().info->componentType;
+ switch (componentType)
{
- return nullptr;
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ return componentType;
+
+ default:
+ return GL_FLOAT;
}
}
bool Framebuffer::hasEnabledDrawBuffer() const
{
- for (size_t drawbufferIdx = 0; drawbufferIdx < mData.mDrawBufferStates.size(); ++drawbufferIdx)
+ for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
{
if (getDrawBuffer(drawbufferIdx) != nullptr)
{
@@ -341,36 +872,36 @@ bool Framebuffer::hasEnabledDrawBuffer() const
GLenum Framebuffer::getReadBufferState() const
{
- return mData.mReadBufferState;
+ return mState.mReadBufferState;
}
void Framebuffer::setReadBuffer(GLenum buffer)
{
ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
(buffer >= GL_COLOR_ATTACHMENT0 &&
- (buffer - GL_COLOR_ATTACHMENT0) < mData.mColorAttachments.size()));
- mData.mReadBufferState = buffer;
+ (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
+ mState.mReadBufferState = buffer;
mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
}
size_t Framebuffer::getNumColorBuffers() const
{
- return mData.mColorAttachments.size();
+ return mState.mColorAttachments.size();
}
bool Framebuffer::hasDepth() const
{
- return (mData.mDepthAttachment.isAttached() && mData.mDepthAttachment.getDepthSize() > 0);
+ return mState.hasDepth();
}
bool Framebuffer::hasStencil() const
{
- return (mData.mStencilAttachment.isAttached() && mData.mStencilAttachment.getStencilSize() > 0);
+ return mState.hasStencil();
}
bool Framebuffer::usingExtendedDrawBuffers() const
{
- for (size_t drawbufferIdx = 1; drawbufferIdx < mData.mDrawBufferStates.size(); ++drawbufferIdx)
+ for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
{
if (getDrawBuffer(drawbufferIdx) != nullptr)
{
@@ -381,210 +912,234 @@ bool Framebuffer::usingExtendedDrawBuffers() const
return false;
}
-GLenum Framebuffer::checkStatus(const gl::Data &data) const
+void Framebuffer::invalidateCompletenessCache()
{
- // The default framebuffer *must* always be complete, though it may not be
- // subject to the same rules as application FBOs. ie, it could have 0x0 size.
+ if (mId != 0)
+ {
+ mCachedStatus.reset();
+ }
+}
+
+GLenum Framebuffer::checkStatus(const Context *context)
+{
+ // The default framebuffer is always complete except when it is surfaceless in which
+ // case it is always unsupported. We return early because the default framebuffer may
+ // not be subject to the same rules as application FBOs. ie, it could have 0x0 size.
if (mId == 0)
{
- return GL_FRAMEBUFFER_COMPLETE;
+ ASSERT(mCachedStatus.valid());
+ ASSERT(mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE ||
+ mCachedStatus.value() == GL_FRAMEBUFFER_UNDEFINED_OES);
+ return mCachedStatus.value();
+ }
+
+ if (hasAnyDirtyBit() || !mCachedStatus.valid())
+ {
+ mCachedStatus = checkStatusImpl(context);
}
- unsigned int colorbufferSize = 0;
- int samples = -1;
- bool missingAttachment = true;
+ return mCachedStatus.value();
+}
+
+GLenum Framebuffer::checkStatusImpl(const Context *context)
+{
+ const ContextState &state = context->getContextState();
+
+ ASSERT(mId != 0);
+
+ bool hasAttachments = false;
+ Optional<unsigned int> colorbufferSize;
+ Optional<int> samples;
+ Optional<bool> fixedSampleLocations;
+ bool hasRenderbuffer = false;
- for (const FramebufferAttachment &colorAttachment : mData.mColorAttachments)
+ const FramebufferAttachment *firstAttachment = getFirstNonNullAttachment();
+
+ for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
{
if (colorAttachment.isAttached())
{
- const Extents &size = colorAttachment.getSize();
- if (size.width == 0 || size.height == 0)
+ if (!CheckAttachmentCompleteness(context, colorAttachment))
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
- GLenum internalformat = colorAttachment.getInternalFormat();
- const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
- const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
- if (colorAttachment.type() == GL_TEXTURE)
+ const InternalFormat &format = *colorAttachment.getFormat().info;
+ if (format.depthBits > 0 || format.stencilBits > 0)
{
- if (!formatCaps.renderable)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
-
- if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
-
- if (colorAttachment.layer() >= size.depth)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
-
- // ES3 specifies that cube map texture attachments must be cube complete.
- // This language is missing from the ES2 spec, but we enforce it here because some
- // desktop OpenGL drivers also enforce this validation.
- // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
- const Texture *texture = colorAttachment.getTexture();
- ASSERT(texture);
- if (texture->getTarget() == GL_TEXTURE_CUBE_MAP && !texture->isCubeComplete())
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
- else if (colorAttachment.type() == GL_RENDERBUFFER)
+
+ if (!CheckAttachmentSampleCompleteness(context, colorAttachment, true, &samples,
+ &fixedSampleLocations))
{
- if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
+ return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
}
- if (!missingAttachment)
+ // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
+ // in GLES 3.0, there is no such restriction
+ if (state.getClientMajorVersion() < 3)
{
- // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
- // all color attachments have the same number of samples for the FBO to be complete.
- if (colorAttachment.getSamples() != samples)
+ if (colorbufferSize.valid())
{
- return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
- }
-
- // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
- // in GLES 3.0, there is no such restriction
- if (data.clientVersion < 3)
- {
- if (formatInfo.pixelBytes != colorbufferSize)
+ if (format.pixelBytes != colorbufferSize.value())
{
return GL_FRAMEBUFFER_UNSUPPORTED;
}
}
+ else
+ {
+ colorbufferSize = format.pixelBytes;
+ }
}
- else
+
+ if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &colorAttachment))
{
- samples = colorAttachment.getSamples();
- colorbufferSize = formatInfo.pixelBytes;
- missingAttachment = false;
+ return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
}
+
+ hasRenderbuffer = hasRenderbuffer || (colorAttachment.type() == GL_RENDERBUFFER);
+ hasAttachments = true;
}
}
- const FramebufferAttachment &depthAttachment = mData.mDepthAttachment;
+ const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
if (depthAttachment.isAttached())
{
- const Extents &size = depthAttachment.getSize();
- if (size.width == 0 || size.height == 0)
+ if (!CheckAttachmentCompleteness(context, depthAttachment))
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
- GLenum internalformat = depthAttachment.getInternalFormat();
- const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
- const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
- if (depthAttachment.type() == GL_TEXTURE)
+ const InternalFormat &format = *depthAttachment.getFormat().info;
+ if (format.depthBits == 0)
{
- // depth texture attachments require OES/ANGLE_depth_texture
- if (!data.extensions->depthTextures)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
- if (!formatCaps.renderable)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
+ if (!CheckAttachmentSampleCompleteness(context, depthAttachment, false, &samples,
+ &fixedSampleLocations))
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
+ }
- if (formatInfo.depthBits == 0)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
+ if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &depthAttachment))
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
}
- else if (depthAttachment.type() == GL_RENDERBUFFER)
+
+ hasRenderbuffer = hasRenderbuffer || (depthAttachment.type() == GL_RENDERBUFFER);
+ hasAttachments = true;
+ }
+
+ const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
+ if (stencilAttachment.isAttached())
+ {
+ if (!CheckAttachmentCompleteness(context, stencilAttachment))
{
- if (!formatCaps.renderable || formatInfo.depthBits == 0)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+
+ const InternalFormat &format = *stencilAttachment.getFormat().info;
+ if (format.stencilBits == 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
- if (missingAttachment)
+ if (!CheckAttachmentSampleCompleteness(context, stencilAttachment, false, &samples,
+ &fixedSampleLocations))
{
- samples = depthAttachment.getSamples();
- missingAttachment = false;
+ return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
}
- else if (samples != depthAttachment.getSamples())
+
+ if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &stencilAttachment))
{
- return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
+ return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
}
+
+ hasRenderbuffer = hasRenderbuffer || (stencilAttachment.type() == GL_RENDERBUFFER);
+ hasAttachments = true;
}
- const FramebufferAttachment &stencilAttachment = mData.mStencilAttachment;
- if (stencilAttachment.isAttached())
+ // Starting from ES 3.0 stencil and depth, if present, should be the same image
+ if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
+ stencilAttachment.isAttached() && stencilAttachment != depthAttachment)
+ {
+ return GL_FRAMEBUFFER_UNSUPPORTED;
+ }
+
+ // Special additional validation for WebGL 1 DEPTH/STENCIL/DEPTH_STENCIL.
+ if (state.isWebGL1())
{
- const Extents &size = stencilAttachment.getSize();
- if (size.width == 0 || size.height == 0)
+ if (!mState.mWebGLDepthStencilConsistent)
{
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ return GL_FRAMEBUFFER_UNSUPPORTED;
}
- GLenum internalformat = stencilAttachment.getInternalFormat();
- const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
- const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
- if (stencilAttachment.type() == GL_TEXTURE)
+ if (mState.mWebGLDepthStencilAttachment.isAttached())
{
- // texture stencil attachments come along as part
- // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
- if (!data.extensions->depthTextures)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
-
- if (!formatCaps.renderable)
+ if (mState.mWebGLDepthStencilAttachment.getDepthSize() == 0 ||
+ mState.mWebGLDepthStencilAttachment.getStencilSize() == 0)
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
- if (formatInfo.stencilBits == 0)
+ if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment,
+ &mState.mWebGLDepthStencilAttachment))
{
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
}
}
- else if (stencilAttachment.type() == GL_RENDERBUFFER)
+ else if (mState.mStencilAttachment.isAttached() &&
+ mState.mStencilAttachment.getDepthSize() > 0)
{
- if (!formatCaps.renderable || formatInfo.stencilBits == 0)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
- }
-
- if (missingAttachment)
- {
- samples = stencilAttachment.getSamples();
- missingAttachment = false;
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
- else if (samples != stencilAttachment.getSamples())
+ else if (mState.mDepthAttachment.isAttached() &&
+ mState.mDepthAttachment.getStencilSize() > 0)
{
- return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
}
- // we need to have at least one attachment to be complete
- if (missingAttachment)
+ // ES3.1(section 9.4) requires that if no image is attached to the framebuffer, and either the
+ // value of the framebuffer's FRAMEBUFFER_DEFAULT_WIDTH or FRAMEBUFFER_DEFAULT_HEIGHT parameters
+ // is zero, the framebuffer is considered incomplete.
+ GLint defaultWidth = mState.getDefaultWidth();
+ GLint defaultHeight = mState.getDefaultHeight();
+ if (!hasAttachments && (defaultWidth == 0 || defaultHeight == 0))
{
return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
}
- // In ES 2.0, all color attachments must have the same width and height.
+ // In ES 2.0 and WebGL, all color attachments must have the same width and height.
// In ES 3.0, there is no such restriction.
- if (data.clientVersion < 3 && !mData.attachmentsHaveSameDimensions())
+ if ((state.getClientMajorVersion() < 3 || state.getExtensions().webglCompatibility) &&
+ !mState.attachmentsHaveSameDimensions())
{
return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
}
- syncState();
- if (!mImpl->checkStatus())
+ // ES3.1(section 9.4) requires that if the attached images are a mix of renderbuffers and
+ // textures, the value of TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
+ if (fixedSampleLocations.valid() && hasRenderbuffer && !fixedSampleLocations.value())
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
+ }
+
+ // The WebGL conformance tests implicitly define that all framebuffer
+ // attachments must be unique. For example, the same level of a texture can
+ // not be attached to two different color attachments.
+ if (state.getExtensions().webglCompatibility)
+ {
+ if (!mState.colorAttachmentsAreUniqueImages())
+ {
+ return GL_FRAMEBUFFER_UNSUPPORTED;
+ }
+ }
+
+ syncState(context);
+ if (!mImpl->checkStatus(context))
{
return GL_FRAMEBUFFER_UNSUPPORTED;
}
@@ -592,216 +1147,1036 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const
return GL_FRAMEBUFFER_COMPLETE;
}
-Error Framebuffer::discard(size_t count, const GLenum *attachments)
+Error Framebuffer::discard(const Context *context, size_t count, const GLenum *attachments)
{
- return mImpl->discard(count, attachments);
+ // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
+ // can be no-ops, so we should probably do that to ensure consistency.
+ // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
+
+ return mImpl->discard(context, count, attachments);
}
-Error Framebuffer::invalidate(size_t count, const GLenum *attachments)
+Error Framebuffer::invalidate(const Context *context, size_t count, const GLenum *attachments)
{
- return mImpl->invalidate(count, attachments);
+ // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
+ // can be no-ops, so we should probably do that to ensure consistency.
+ // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
+
+ return mImpl->invalidate(context, count, attachments);
}
-Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
+bool Framebuffer::partialClearNeedsInit(const Context *context,
+ bool color,
+ bool depth,
+ bool stencil)
{
- return mImpl->invalidateSub(count, attachments, area);
+ const auto &glState = context->getGLState();
+
+ if (!glState.isRobustResourceInitEnabled())
+ {
+ return false;
+ }
+
+ // Scissors can affect clearing.
+ // TODO(jmadill): Check for complete scissor overlap.
+ if (glState.isScissorTestEnabled())
+ {
+ return true;
+ }
+
+ // If colors masked, we must clear before we clear. Do a simple check.
+ // TODO(jmadill): Filter out unused color channels from the test.
+ if (color)
+ {
+ const auto &blend = glState.getBlendState();
+ if (!(blend.colorMaskRed && blend.colorMaskGreen && blend.colorMaskBlue &&
+ blend.colorMaskAlpha))
+ {
+ return true;
+ }
+ }
+
+ const auto &depthStencil = glState.getDepthStencilState();
+ ASSERT(depthStencil.stencilBackMask == depthStencil.stencilMask);
+ if (stencil && depthStencil.stencilMask != depthStencil.stencilWritemask)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+Error Framebuffer::invalidateSub(const Context *context,
+ size_t count,
+ const GLenum *attachments,
+ const gl::Rectangle &area)
+{
+ // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
+ // can be no-ops, so we should probably do that to ensure consistency.
+ // TODO(jmadill): Make a invalidate no-op in WebGL 2.0.
+
+ return mImpl->invalidateSub(context, count, attachments, area);
}
-Error Framebuffer::clear(const gl::Data &data, GLbitfield mask)
+Error Framebuffer::clear(const gl::Context *context, GLbitfield mask)
{
- if (data.state->isRasterizerDiscardEnabled())
+ const auto &glState = context->getGLState();
+ if (glState.isRasterizerDiscardEnabled())
{
- return gl::Error(GL_NO_ERROR);
+ return NoError();
}
- return mImpl->clear(data, mask);
+ const auto &blend = glState.getBlendState();
+ const auto &depthStencil = glState.getDepthStencilState();
+
+ bool color = (mask & GL_COLOR_BUFFER_BIT) != 0 && !IsColorMaskedOut(blend);
+ bool depth = (mask & GL_DEPTH_BUFFER_BIT) != 0 && !IsDepthMaskedOut(depthStencil);
+ bool stencil = (mask & GL_STENCIL_BUFFER_BIT) != 0 && !IsStencilMaskedOut(depthStencil);
+
+ if (partialClearNeedsInit(context, color, depth, stencil))
+ {
+ ANGLE_TRY(ensureDrawAttachmentsInitialized(context));
+ }
+
+ ANGLE_TRY(mImpl->clear(context, mask));
+
+ if (glState.isRobustResourceInitEnabled())
+ {
+ markDrawAttachmentsInitialized(color, depth, stencil);
+ }
+
+ return NoError();
}
-Error Framebuffer::clearBufferfv(const gl::Data &data,
+Error Framebuffer::clearBufferfv(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
const GLfloat *values)
{
- if (data.state->isRasterizerDiscardEnabled())
+ if (context->getGLState().isRasterizerDiscardEnabled() ||
+ IsClearBufferMaskedOut(context, buffer))
+ {
+ return NoError();
+ }
+
+ if (partialBufferClearNeedsInit(context, buffer))
{
- return gl::Error(GL_NO_ERROR);
+ ANGLE_TRY(ensureBufferInitialized(context, buffer, drawbuffer));
}
- return mImpl->clearBufferfv(data, buffer, drawbuffer, values);
+ ANGLE_TRY(mImpl->clearBufferfv(context, buffer, drawbuffer, values));
+
+ if (context->isRobustResourceInitEnabled())
+ {
+ markBufferInitialized(buffer, drawbuffer);
+ }
+ return NoError();
}
-Error Framebuffer::clearBufferuiv(const gl::Data &data,
+Error Framebuffer::clearBufferuiv(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
const GLuint *values)
{
- if (data.state->isRasterizerDiscardEnabled())
+ if (context->getGLState().isRasterizerDiscardEnabled() ||
+ IsClearBufferMaskedOut(context, buffer))
+ {
+ return NoError();
+ }
+
+ if (partialBufferClearNeedsInit(context, buffer))
{
- return gl::Error(GL_NO_ERROR);
+ ANGLE_TRY(ensureBufferInitialized(context, buffer, drawbuffer));
}
- return mImpl->clearBufferuiv(data, buffer, drawbuffer, values);
+ ANGLE_TRY(mImpl->clearBufferuiv(context, buffer, drawbuffer, values));
+
+ if (context->isRobustResourceInitEnabled())
+ {
+ markBufferInitialized(buffer, drawbuffer);
+ }
+ return NoError();
}
-Error Framebuffer::clearBufferiv(const gl::Data &data,
+Error Framebuffer::clearBufferiv(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
const GLint *values)
{
- if (data.state->isRasterizerDiscardEnabled())
+ if (context->getGLState().isRasterizerDiscardEnabled() ||
+ IsClearBufferMaskedOut(context, buffer))
+ {
+ return NoError();
+ }
+
+ if (partialBufferClearNeedsInit(context, buffer))
{
- return gl::Error(GL_NO_ERROR);
+ ANGLE_TRY(ensureBufferInitialized(context, buffer, drawbuffer));
}
- return mImpl->clearBufferiv(data, buffer, drawbuffer, values);
+ ANGLE_TRY(mImpl->clearBufferiv(context, buffer, drawbuffer, values));
+
+ if (context->isRobustResourceInitEnabled())
+ {
+ markBufferInitialized(buffer, drawbuffer);
+ }
+ return NoError();
}
-Error Framebuffer::clearBufferfi(const gl::Data &data,
+Error Framebuffer::clearBufferfi(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
GLfloat depth,
GLint stencil)
{
- if (data.state->isRasterizerDiscardEnabled())
+ if (context->getGLState().isRasterizerDiscardEnabled() ||
+ IsClearBufferMaskedOut(context, buffer))
+ {
+ return NoError();
+ }
+
+ if (partialBufferClearNeedsInit(context, buffer))
{
- return gl::Error(GL_NO_ERROR);
+ ANGLE_TRY(ensureBufferInitialized(context, buffer, drawbuffer));
}
- return mImpl->clearBufferfi(data, buffer, drawbuffer, depth, stencil);
+ ANGLE_TRY(mImpl->clearBufferfi(context, buffer, drawbuffer, depth, stencil));
+
+ if (context->isRobustResourceInitEnabled())
+ {
+ markBufferInitialized(buffer, drawbuffer);
+ }
+ return NoError();
}
-GLenum Framebuffer::getImplementationColorReadFormat() const
+GLenum Framebuffer::getImplementationColorReadFormat(const Context *context) const
{
- return mImpl->getImplementationColorReadFormat();
+ return mImpl->getImplementationColorReadFormat(context);
}
-GLenum Framebuffer::getImplementationColorReadType() const
+GLenum Framebuffer::getImplementationColorReadType(const Context *context) const
{
- return mImpl->getImplementationColorReadType();
+ return mImpl->getImplementationColorReadType(context);
}
-Error Framebuffer::readPixels(const State &state,
+Error Framebuffer::readPixels(const gl::Context *context,
const Rectangle &area,
GLenum format,
GLenum type,
- GLvoid *pixels) const
+ void *pixels)
{
- Error error = mImpl->readPixels(state, area, format, type, pixels);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(ensureReadAttachmentInitialized(context, GL_COLOR_BUFFER_BIT));
+ ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
- Buffer *unpackBuffer = state.getUnpackState().pixelBuffer.get();
+ Buffer *unpackBuffer = context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
if (unpackBuffer)
{
unpackBuffer->onPixelUnpack();
}
- return Error(GL_NO_ERROR);
+ return NoError();
}
-Error Framebuffer::blit(const State &state,
+Error Framebuffer::blit(const gl::Context *context,
const Rectangle &sourceArea,
const Rectangle &destArea,
GLbitfield mask,
- GLenum filter,
- const Framebuffer *sourceFramebuffer)
+ GLenum filter)
{
- return mImpl->blit(state, sourceArea, destArea, mask, filter, sourceFramebuffer);
+ GLbitfield blitMask = mask;
+
+ // Note that blitting is called against draw framebuffer.
+ // See the code in gl::Context::blitFramebuffer.
+ if ((mask & GL_COLOR_BUFFER_BIT) && !hasEnabledDrawBuffer())
+ {
+ blitMask &= ~GL_COLOR_BUFFER_BIT;
+ }
+
+ if ((mask & GL_STENCIL_BUFFER_BIT) && mState.getStencilAttachment() == nullptr)
+ {
+ blitMask &= ~GL_STENCIL_BUFFER_BIT;
+ }
+
+ if ((mask & GL_DEPTH_BUFFER_BIT) && mState.getDepthAttachment() == nullptr)
+ {
+ blitMask &= ~GL_DEPTH_BUFFER_BIT;
+ }
+
+ if (!blitMask)
+ {
+ return NoError();
+ }
+
+ auto *sourceFBO = context->getGLState().getReadFramebuffer();
+ ANGLE_TRY(sourceFBO->ensureReadAttachmentInitialized(context, blitMask));
+
+ // TODO(jmadill): Only clear if not the full FBO dimensions, and only specified bitmask.
+ ANGLE_TRY(ensureDrawAttachmentsInitialized(context));
+
+ return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
}
-int Framebuffer::getSamples(const gl::Data &data) const
+int Framebuffer::getSamples(const Context *context)
{
- if (checkStatus(data) == GL_FRAMEBUFFER_COMPLETE)
+ if (complete(context))
{
- // for a complete framebuffer, all attachments must have the same sample count
- // in this case return the first nonzero sample size
- for (const FramebufferAttachment &colorAttachment : mData.mColorAttachments)
- {
- if (colorAttachment.isAttached())
- {
- return colorAttachment.getSamples();
- }
- }
+ return getCachedSamples(context);
}
return 0;
}
+int Framebuffer::getCachedSamples(const Context *context)
+{
+ // For a complete framebuffer, all attachments must have the same sample count.
+ // In this case return the first nonzero sample size.
+ const auto *firstNonNullAttachment = mState.getFirstNonNullAttachment();
+ if (firstNonNullAttachment)
+ {
+ ASSERT(firstNonNullAttachment->isAttached());
+ return firstNonNullAttachment->getSamples();
+ }
+
+ // No attachments found.
+ return 0;
+}
+
+Error Framebuffer::getSamplePosition(size_t index, GLfloat *xy) const
+{
+ ANGLE_TRY(mImpl->getSamplePosition(index, xy));
+ return NoError();
+}
+
bool Framebuffer::hasValidDepthStencil() const
{
- return mData.getDepthStencilAttachment() != nullptr;
+ return mState.getDepthStencilAttachment() != nullptr;
}
-void Framebuffer::setAttachment(GLenum type,
+void Framebuffer::setAttachment(const Context *context,
+ GLenum type,
GLenum binding,
const ImageIndex &textureIndex,
FramebufferAttachmentObject *resource)
{
- if (binding == GL_DEPTH_STENCIL || binding == GL_DEPTH_STENCIL_ATTACHMENT)
+ setAttachment(context, type, binding, textureIndex, resource,
+ FramebufferAttachment::kDefaultNumViews,
+ FramebufferAttachment::kDefaultBaseViewIndex,
+ FramebufferAttachment::kDefaultMultiviewLayout,
+ FramebufferAttachment::kDefaultViewportOffsets);
+}
+
+void Framebuffer::setAttachment(const Context *context,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource,
+ GLsizei numViews,
+ GLuint baseViewIndex,
+ GLenum multiviewLayout,
+ const GLint *viewportOffsets)
+{
+ // Context may be null in unit tests.
+ if (!context || !context->isWebGL1())
+ {
+ setAttachmentImpl(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
+ multiviewLayout, viewportOffsets);
+ return;
+ }
+
+ switch (binding)
{
- // ensure this is a legitimate depth+stencil format
- FramebufferAttachmentObject *attachmentObj = resource;
- if (resource)
+ case GL_DEPTH_STENCIL:
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ mState.mWebGLDepthStencilAttachment.attach(context, type, binding, textureIndex,
+ resource, numViews, baseViewIndex,
+ multiviewLayout, viewportOffsets);
+ break;
+ case GL_DEPTH:
+ case GL_DEPTH_ATTACHMENT:
+ mState.mWebGLDepthAttachment.attach(context, type, binding, textureIndex, resource,
+ numViews, baseViewIndex, multiviewLayout,
+ viewportOffsets);
+ break;
+ case GL_STENCIL:
+ case GL_STENCIL_ATTACHMENT:
+ mState.mWebGLStencilAttachment.attach(context, type, binding, textureIndex, resource,
+ numViews, baseViewIndex, multiviewLayout,
+ viewportOffsets);
+ break;
+ default:
+ setAttachmentImpl(context, type, binding, textureIndex, resource, numViews,
+ baseViewIndex, multiviewLayout, viewportOffsets);
+ return;
+ }
+
+ commitWebGL1DepthStencilIfConsistent(context, numViews, baseViewIndex, multiviewLayout,
+ viewportOffsets);
+}
+
+void Framebuffer::setAttachmentMultiviewLayered(const Context *context,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource,
+ GLsizei numViews,
+ GLint baseViewIndex)
+{
+ setAttachment(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
+ GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE,
+ FramebufferAttachment::kDefaultViewportOffsets);
+}
+
+void Framebuffer::setAttachmentMultiviewSideBySide(const Context *context,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource,
+ GLsizei numViews,
+ const GLint *viewportOffsets)
+{
+ setAttachment(context, type, binding, textureIndex, resource, numViews,
+ FramebufferAttachment::kDefaultBaseViewIndex,
+ GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, viewportOffsets);
+}
+
+void Framebuffer::commitWebGL1DepthStencilIfConsistent(const Context *context,
+ GLsizei numViews,
+ GLuint baseViewIndex,
+ GLenum multiviewLayout,
+ const GLint *viewportOffsets)
+{
+ int count = 0;
+
+ std::array<FramebufferAttachment *, 3> attachments = {{&mState.mWebGLDepthStencilAttachment,
+ &mState.mWebGLDepthAttachment,
+ &mState.mWebGLStencilAttachment}};
+ for (FramebufferAttachment *attachment : attachments)
+ {
+ if (attachment->isAttached())
{
- FramebufferAttachment::Target target(binding, textureIndex);
- GLenum internalFormat = resource->getAttachmentInternalFormat(target);
- const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat);
- if (formatInfo.depthBits == 0 || formatInfo.stencilBits == 0)
- {
- // Attaching nullptr detaches the current attachment.
- attachmentObj = nullptr;
- }
+ count++;
+ }
+ }
+
+ mState.mWebGLDepthStencilConsistent = (count <= 1);
+ if (!mState.mWebGLDepthStencilConsistent)
+ {
+ // Inconsistent.
+ return;
+ }
+
+ auto getImageIndexIfTextureAttachment = [](const FramebufferAttachment &attachment) {
+ if (attachment.type() == GL_TEXTURE)
+ {
+ return attachment.getTextureImageIndex();
+ }
+ else
+ {
+ return ImageIndex::MakeInvalid();
}
+ };
- mData.mDepthAttachment.attach(type, binding, textureIndex, attachmentObj);
- mData.mStencilAttachment.attach(type, binding, textureIndex, attachmentObj);
- mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
- mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
+ if (mState.mWebGLDepthAttachment.isAttached())
+ {
+ const auto &depth = mState.mWebGLDepthAttachment;
+ setAttachmentImpl(context, depth.type(), GL_DEPTH_ATTACHMENT,
+ getImageIndexIfTextureAttachment(depth), depth.getResource(), numViews,
+ baseViewIndex, multiviewLayout, viewportOffsets);
+ setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(),
+ nullptr, numViews, baseViewIndex, multiviewLayout, viewportOffsets);
+ }
+ else if (mState.mWebGLStencilAttachment.isAttached())
+ {
+ const auto &stencil = mState.mWebGLStencilAttachment;
+ setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr,
+ numViews, baseViewIndex, multiviewLayout, viewportOffsets);
+ setAttachmentImpl(context, stencil.type(), GL_STENCIL_ATTACHMENT,
+ getImageIndexIfTextureAttachment(stencil), stencil.getResource(),
+ numViews, baseViewIndex, multiviewLayout, viewportOffsets);
+ }
+ else if (mState.mWebGLDepthStencilAttachment.isAttached())
+ {
+ const auto &depthStencil = mState.mWebGLDepthStencilAttachment;
+ setAttachmentImpl(context, depthStencil.type(), GL_DEPTH_ATTACHMENT,
+ getImageIndexIfTextureAttachment(depthStencil),
+ depthStencil.getResource(), numViews, baseViewIndex, multiviewLayout,
+ viewportOffsets);
+ setAttachmentImpl(context, depthStencil.type(), GL_STENCIL_ATTACHMENT,
+ getImageIndexIfTextureAttachment(depthStencil),
+ depthStencil.getResource(), numViews, baseViewIndex, multiviewLayout,
+ viewportOffsets);
}
else
{
- switch (binding)
+ setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr,
+ numViews, baseViewIndex, multiviewLayout, viewportOffsets);
+ setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(),
+ nullptr, numViews, baseViewIndex, multiviewLayout, viewportOffsets);
+ }
+}
+
+void Framebuffer::setAttachmentImpl(const Context *context,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource,
+ GLsizei numViews,
+ GLuint baseViewIndex,
+ GLenum multiviewLayout,
+ const GLint *viewportOffsets)
+{
+ switch (binding)
+ {
+ case GL_DEPTH_STENCIL:
+ case GL_DEPTH_STENCIL_ATTACHMENT:
{
- case GL_DEPTH:
- case GL_DEPTH_ATTACHMENT:
- mData.mDepthAttachment.attach(type, binding, textureIndex, resource);
- mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
+ // ensure this is a legitimate depth+stencil format
+ FramebufferAttachmentObject *attachmentObj = resource;
+ if (resource)
+ {
+ const Format &format = resource->getAttachmentFormat(binding, textureIndex);
+ if (format.info->depthBits == 0 || format.info->stencilBits == 0)
+ {
+ // Attaching nullptr detaches the current attachment.
+ attachmentObj = nullptr;
+ }
+ }
+
+ updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
+ &mDirtyDepthAttachmentBinding, type, binding, textureIndex,
+ attachmentObj, numViews, baseViewIndex, multiviewLayout,
+ viewportOffsets);
+ updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
+ &mDirtyStencilAttachmentBinding, type, binding, textureIndex,
+ attachmentObj, numViews, baseViewIndex, multiviewLayout,
+ viewportOffsets);
break;
- case GL_STENCIL:
- case GL_STENCIL_ATTACHMENT:
- mData.mStencilAttachment.attach(type, binding, textureIndex, resource);
- mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
+ }
+
+ case GL_DEPTH:
+ case GL_DEPTH_ATTACHMENT:
+ updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
+ &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource,
+ numViews, baseViewIndex, multiviewLayout, viewportOffsets);
break;
- case GL_BACK:
- mData.mColorAttachments[0].attach(type, binding, textureIndex, resource);
- mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
+
+ case GL_STENCIL:
+ case GL_STENCIL_ATTACHMENT:
+ updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
+ &mDirtyStencilAttachmentBinding, type, binding, textureIndex, resource,
+ numViews, baseViewIndex, multiviewLayout, viewportOffsets);
break;
+
+ case GL_BACK:
+ mState.mColorAttachments[0].attach(context, type, binding, textureIndex, resource,
+ numViews, baseViewIndex, multiviewLayout,
+ viewportOffsets);
+ mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
+ // No need for a resource binding for the default FBO, it's always complete.
+ break;
+
+ default:
+ {
+ size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
+ ASSERT(colorIndex < mState.mColorAttachments.size());
+ size_t dirtyBit = DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex;
+ updateAttachment(context, &mState.mColorAttachments[colorIndex], dirtyBit,
+ &mDirtyColorAttachmentBindings[colorIndex], type, binding,
+ textureIndex, resource, numViews, baseViewIndex, multiviewLayout,
+ viewportOffsets);
+
+ // TODO(jmadill): ASSERT instead of checking the attachment exists in
+ // formsRenderingFeedbackLoopWith
+ bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE);
+ mState.mEnabledDrawBuffers.set(colorIndex, enabled);
+ }
+ break;
+ }
+
+ mAttachedTextures.reset();
+}
+
+void Framebuffer::updateAttachment(const Context *context,
+ FramebufferAttachment *attachment,
+ size_t dirtyBit,
+ OnAttachmentDirtyBinding *onDirtyBinding,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource,
+ GLsizei numViews,
+ GLuint baseViewIndex,
+ GLenum multiviewLayout,
+ const GLint *viewportOffsets)
+{
+ attachment->attach(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
+ multiviewLayout, viewportOffsets);
+ mDirtyBits.set(dirtyBit);
+ mState.mResourceNeedsInit.set(dirtyBit, attachment->initState() == InitState::MayNeedInit);
+ BindResourceChannel(onDirtyBinding, resource);
+}
+
+void Framebuffer::resetAttachment(const Context *context, GLenum binding)
+{
+ setAttachment(context, GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
+}
+
+void Framebuffer::syncState(const Context *context)
+{
+ if (mDirtyBits.any())
+ {
+ mImpl->syncState(context, mDirtyBits);
+ mDirtyBits.reset();
+ if (mId != 0)
+ {
+ mCachedStatus.reset();
+ }
+ }
+}
+
+void Framebuffer::signal(size_t dirtyBit, InitState state)
+{
+ // TOOD(jmadill): Make this only update individual attachments to do less work.
+ mCachedStatus.reset();
+
+ // Mark the appropriate init flag.
+ mState.mResourceNeedsInit.set(dirtyBit, state == InitState::MayNeedInit);
+}
+
+bool Framebuffer::complete(const Context *context)
+{
+ return (checkStatus(context) == GL_FRAMEBUFFER_COMPLETE);
+}
+
+bool Framebuffer::cachedComplete() const
+{
+ return (mCachedStatus.valid() && mCachedStatus == GL_FRAMEBUFFER_COMPLETE);
+}
+
+bool Framebuffer::formsRenderingFeedbackLoopWith(const State &state) const
+{
+ const Program *program = state.getProgram();
+
+ // TODO(jmadill): Default framebuffer feedback loops.
+ if (mId == 0)
+ {
+ return false;
+ }
+
+ // The bitset will skip inactive draw buffers.
+ for (size_t drawIndex : mState.mEnabledDrawBuffers)
+ {
+ const FramebufferAttachment &attachment = mState.mColorAttachments[drawIndex];
+ ASSERT(attachment.isAttached());
+ if (attachment.type() == GL_TEXTURE)
+ {
+ // Validate the feedback loop.
+ if (program->samplesFromTexture(state, attachment.id()))
+ {
+ return true;
+ }
+ }
+ }
+
+ // Validate depth-stencil feedback loop.
+ const auto &dsState = state.getDepthStencilState();
+
+ // We can skip the feedback loop checks if depth/stencil is masked out or disabled.
+ const FramebufferAttachment *depth = getDepthbuffer();
+ if (depth && depth->type() == GL_TEXTURE && dsState.depthTest && dsState.depthMask)
+ {
+ if (program->samplesFromTexture(state, depth->id()))
+ {
+ return true;
+ }
+ }
+
+ // Note: we assume the front and back masks are the same for WebGL.
+ const FramebufferAttachment *stencil = getStencilbuffer();
+ ASSERT(dsState.stencilBackWritemask == dsState.stencilWritemask);
+ if (stencil && stencil->type() == GL_TEXTURE && dsState.stencilTest &&
+ dsState.stencilWritemask != 0)
+ {
+ // Skip the feedback loop check if depth/stencil point to the same resource.
+ if (!depth || *stencil != *depth)
+ {
+ if (program->samplesFromTexture(state, stencil->id()))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool Framebuffer::formsCopyingFeedbackLoopWith(GLuint copyTextureID,
+ GLint copyTextureLevel,
+ GLint copyTextureLayer) const
+{
+ if (mId == 0)
+ {
+ // It seems impossible to form a texture copying feedback loop with the default FBO.
+ return false;
+ }
+
+ const FramebufferAttachment *readAttachment = getReadColorbuffer();
+ ASSERT(readAttachment);
+
+ if (readAttachment->isTextureWithId(copyTextureID))
+ {
+ const auto &imageIndex = readAttachment->getTextureImageIndex();
+ if (imageIndex.mipIndex == copyTextureLevel)
+ {
+ // Check 3D/Array texture layers.
+ return imageIndex.layerIndex == ImageIndex::ENTIRE_LEVEL ||
+ copyTextureLayer == ImageIndex::ENTIRE_LEVEL ||
+ imageIndex.layerIndex == copyTextureLayer;
+ }
+ }
+ return false;
+}
+
+GLint Framebuffer::getDefaultWidth() const
+{
+ return mState.getDefaultWidth();
+}
+
+GLint Framebuffer::getDefaultHeight() const
+{
+ return mState.getDefaultHeight();
+}
+
+GLint Framebuffer::getDefaultSamples() const
+{
+ return mState.getDefaultSamples();
+}
+
+bool Framebuffer::getDefaultFixedSampleLocations() const
+{
+ return mState.getDefaultFixedSampleLocations();
+}
+
+void Framebuffer::setDefaultWidth(GLint defaultWidth)
+{
+ mState.mDefaultWidth = defaultWidth;
+ mDirtyBits.set(DIRTY_BIT_DEFAULT_WIDTH);
+}
+
+void Framebuffer::setDefaultHeight(GLint defaultHeight)
+{
+ mState.mDefaultHeight = defaultHeight;
+ mDirtyBits.set(DIRTY_BIT_DEFAULT_HEIGHT);
+}
+
+void Framebuffer::setDefaultSamples(GLint defaultSamples)
+{
+ mState.mDefaultSamples = defaultSamples;
+ mDirtyBits.set(DIRTY_BIT_DEFAULT_SAMPLES);
+}
+
+void Framebuffer::setDefaultFixedSampleLocations(bool defaultFixedSampleLocations)
+{
+ mState.mDefaultFixedSampleLocations = defaultFixedSampleLocations;
+ mDirtyBits.set(DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS);
+}
+
+// TODO(jmadill): Remove this kludge.
+GLenum Framebuffer::checkStatus(const ValidationContext *context)
+{
+ return checkStatus(static_cast<const Context *>(context));
+}
+
+int Framebuffer::getSamples(const ValidationContext *context)
+{
+ return getSamples(static_cast<const Context *>(context));
+}
+
+GLsizei Framebuffer::getNumViews() const
+{
+ return mState.getNumViews();
+}
+
+GLint Framebuffer::getBaseViewIndex() const
+{
+ return mState.getBaseViewIndex();
+}
+
+const std::vector<Offset> *Framebuffer::getViewportOffsets() const
+{
+ return mState.getViewportOffsets();
+}
+
+GLenum Framebuffer::getMultiviewLayout() const
+{
+ return mState.getMultiviewLayout();
+}
+
+Error Framebuffer::ensureDrawAttachmentsInitialized(const Context *context)
+{
+ if (!context->isRobustResourceInitEnabled())
+ {
+ return NoError();
+ }
+
+ // Note: we don't actually filter by the draw attachment enum. Just init everything.
+ for (size_t bit : mState.mResourceNeedsInit)
+ {
+ switch (bit)
+ {
+ case DIRTY_BIT_DEPTH_ATTACHMENT:
+ ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
+ break;
+ case DIRTY_BIT_STENCIL_ATTACHMENT:
+ ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
+ break;
default:
+ ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bit]));
+ break;
+ }
+ }
+
+ mState.mResourceNeedsInit.reset();
+ return NoError();
+}
+
+Error Framebuffer::ensureReadAttachmentInitialized(const Context *context, GLbitfield blitMask)
+{
+ if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none())
+ {
+ return NoError();
+ }
+
+ if ((blitMask & GL_COLOR_BUFFER_BIT) != 0 && mState.mReadBufferState != GL_NONE)
+ {
+ size_t readIndex = mState.getReadIndex();
+ if (mState.mResourceNeedsInit[readIndex])
+ {
+ ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[readIndex]));
+ mState.mResourceNeedsInit.reset(readIndex);
+ }
+ }
+
+ if ((blitMask & GL_DEPTH_BUFFER_BIT) != 0 && hasDepth())
+ {
+ if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
+ {
+ ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
+ mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
+ }
+ }
+
+ if ((blitMask & GL_STENCIL_BUFFER_BIT) != 0 && hasStencil())
+ {
+ if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
+ {
+ ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
+ mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
+ }
+ }
+
+ return NoError();
+}
+
+void Framebuffer::markDrawAttachmentsInitialized(bool color, bool depth, bool stencil)
+{
+ // Mark attachments as initialized.
+ if (color)
+ {
+ for (auto colorIndex : mState.mEnabledDrawBuffers)
+ {
+ auto &colorAttachment = mState.mColorAttachments[colorIndex];
+ ASSERT(colorAttachment.isAttached());
+ colorAttachment.setInitState(InitState::Initialized);
+ mState.mResourceNeedsInit.reset(colorIndex);
+ }
+ }
+
+ if (depth && mState.mDepthAttachment.isAttached())
+ {
+ mState.mDepthAttachment.setInitState(InitState::Initialized);
+ mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
+ }
+
+ if (stencil && mState.mStencilAttachment.isAttached())
+ {
+ mState.mStencilAttachment.setInitState(InitState::Initialized);
+ mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
+ }
+}
+
+void Framebuffer::markBufferInitialized(GLenum bufferType, GLint bufferIndex)
+{
+ switch (bufferType)
+ {
+ case GL_COLOR:
+ {
+ ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
+ if (mState.mColorAttachments[bufferIndex].isAttached())
+ {
+ mState.mColorAttachments[bufferIndex].setInitState(InitState::Initialized);
+ mState.mResourceNeedsInit.reset(bufferIndex);
+ }
+ break;
+ }
+ case GL_DEPTH:
+ {
+ if (mState.mDepthAttachment.isAttached())
{
- size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
- ASSERT(colorIndex < mData.mColorAttachments.size());
- mData.mColorAttachments[colorIndex].attach(type, binding, textureIndex, resource);
- mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
+ mState.mDepthAttachment.setInitState(InitState::Initialized);
+ mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
}
break;
}
+ case GL_STENCIL:
+ {
+ if (mState.mStencilAttachment.isAttached())
+ {
+ mState.mStencilAttachment.setInitState(InitState::Initialized);
+ mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
+ }
+ break;
+ }
+ case GL_DEPTH_STENCIL:
+ {
+ if (mState.mDepthAttachment.isAttached())
+ {
+ mState.mDepthAttachment.setInitState(InitState::Initialized);
+ mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
+ }
+ if (mState.mStencilAttachment.isAttached())
+ {
+ mState.mStencilAttachment.setInitState(InitState::Initialized);
+ mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
+ }
+ break;
+ }
+ default:
+ UNREACHABLE();
+ break;
}
}
-void Framebuffer::resetAttachment(GLenum binding)
+Box Framebuffer::getDimensions() const
{
- setAttachment(GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
+ return mState.getDimensions();
}
-void Framebuffer::syncState() const
+Error Framebuffer::ensureBufferInitialized(const Context *context,
+ GLenum bufferType,
+ GLint bufferIndex)
{
- if (mDirtyBits.any())
+ ASSERT(context->isRobustResourceInitEnabled());
+
+ if (mState.mResourceNeedsInit.none())
{
- mImpl->syncState(mDirtyBits);
- mDirtyBits.reset();
+ return NoError();
+ }
+
+ switch (bufferType)
+ {
+ case GL_COLOR:
+ {
+ ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
+ if (mState.mResourceNeedsInit[bufferIndex])
+ {
+ ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bufferIndex]));
+ mState.mResourceNeedsInit.reset(bufferIndex);
+ }
+ break;
+ }
+ case GL_DEPTH:
+ {
+ if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
+ {
+ ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
+ mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
+ }
+ break;
+ }
+ case GL_STENCIL:
+ {
+ if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
+ {
+ ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
+ mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
+ }
+ break;
+ }
+ case GL_DEPTH_STENCIL:
+ {
+ if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
+ {
+ ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
+ mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
+ }
+ if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
+ {
+ ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
+ mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
+ }
+ break;
+ }
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ return NoError();
+}
+
+bool Framebuffer::partialBufferClearNeedsInit(const Context *context, GLenum bufferType)
+{
+ if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none())
+ {
+ return false;
}
+
+ switch (bufferType)
+ {
+ case GL_COLOR:
+ return partialClearNeedsInit(context, true, false, false);
+ case GL_DEPTH:
+ return partialClearNeedsInit(context, false, true, false);
+ case GL_STENCIL:
+ return partialClearNeedsInit(context, false, false, true);
+ case GL_DEPTH_STENCIL:
+ return partialClearNeedsInit(context, false, true, true);
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+bool Framebuffer::hasTextureAttachment(const Texture *texture) const
+{
+ if (!mAttachedTextures.valid())
+ {
+ std::set<const FramebufferAttachmentObject *> attachedTextures;
+
+ for (const auto &colorAttachment : mState.mColorAttachments)
+ {
+ if (colorAttachment.isAttached() && colorAttachment.type() == GL_TEXTURE)
+ {
+ attachedTextures.insert(colorAttachment.getResource());
+ }
+ }
+
+ if (mState.mDepthAttachment.isAttached() && mState.mDepthAttachment.type() == GL_TEXTURE)
+ {
+ attachedTextures.insert(mState.mDepthAttachment.getResource());
+ }
+
+ if (mState.mStencilAttachment.isAttached() &&
+ mState.mStencilAttachment.type() == GL_TEXTURE)
+ {
+ attachedTextures.insert(mState.mStencilAttachment.getResource());
+ }
+
+ mAttachedTextures = std::move(attachedTextures);
+ }
+
+ return (mAttachedTextures.value().count(texture) > 0);
}
} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/Framebuffer.h b/src/3rdparty/angle/src/libANGLE/Framebuffer.h
index b07b59ac90..70223f0bc7 100644
--- a/src/3rdparty/angle/src/libANGLE/Framebuffer.h
+++ b/src/3rdparty/angle/src/libANGLE/Framebuffer.h
@@ -12,16 +12,18 @@
#include <vector>
+#include "common/Optional.h"
#include "common/angleutils.h"
#include "libANGLE/Constants.h"
#include "libANGLE/Debug.h"
#include "libANGLE/Error.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/RefCountObject.h"
+#include "libANGLE/signal_utils.h"
namespace rx
{
-class ImplFactory;
+class GLImplFactory;
class FramebufferImpl;
class RenderbufferImpl;
class SurfaceImpl;
@@ -29,98 +31,171 @@ class SurfaceImpl;
namespace egl
{
+class Display;
class Surface;
}
namespace gl
{
class Context;
+class ContextState;
+class Framebuffer;
class Renderbuffer;
class State;
class Texture;
class TextureCapsMap;
+class ValidationContext;
struct Caps;
-struct Data;
struct Extensions;
struct ImageIndex;
struct Rectangle;
-class Framebuffer final : public LabeledObject
+class FramebufferState final : angle::NonCopyable
{
public:
+ FramebufferState();
+ explicit FramebufferState(const Caps &caps);
+ ~FramebufferState();
- class Data final : angle::NonCopyable
+ const std::string &getLabel();
+ size_t getReadIndex() const;
+
+ const FramebufferAttachment *getAttachment(GLenum attachment) const;
+ const FramebufferAttachment *getReadAttachment() const;
+ const FramebufferAttachment *getFirstNonNullAttachment() const;
+ const FramebufferAttachment *getFirstColorAttachment() const;
+ const FramebufferAttachment *getDepthOrStencilAttachment() const;
+ const FramebufferAttachment *getStencilOrDepthStencilAttachment() const;
+ const FramebufferAttachment *getColorAttachment(size_t colorAttachment) const;
+ const FramebufferAttachment *getDepthAttachment() const;
+ const FramebufferAttachment *getStencilAttachment() const;
+ const FramebufferAttachment *getDepthStencilAttachment() const;
+
+ const std::vector<GLenum> &getDrawBufferStates() const { return mDrawBufferStates; }
+ DrawBufferMask getEnabledDrawBuffers() const { return mEnabledDrawBuffers; }
+ GLenum getReadBufferState() const { return mReadBufferState; }
+ const std::vector<FramebufferAttachment> &getColorAttachments() const
{
- public:
- explicit Data();
- explicit Data(const Caps &caps);
- ~Data();
+ return mColorAttachments;
+ }
- const std::string &getLabel();
+ bool attachmentsHaveSameDimensions() const;
+ bool colorAttachmentsAreUniqueImages() const;
+ Box getDimensions() const;
- const FramebufferAttachment *getReadAttachment() const;
- const FramebufferAttachment *getFirstColorAttachment() const;
- const FramebufferAttachment *getDepthOrStencilAttachment() const;
- const FramebufferAttachment *getColorAttachment(size_t colorAttachment) const;
- const FramebufferAttachment *getDepthAttachment() const;
- const FramebufferAttachment *getStencilAttachment() const;
- const FramebufferAttachment *getDepthStencilAttachment() const;
+ const FramebufferAttachment *getDrawBuffer(size_t drawBufferIdx) const;
+ size_t getDrawBufferCount() const;
- const std::vector<GLenum> &getDrawBufferStates() const { return mDrawBufferStates; }
- GLenum getReadBufferState() const { return mReadBufferState; }
- const std::vector<FramebufferAttachment> &getColorAttachments() const { return mColorAttachments; }
+ GLint getDefaultWidth() const { return mDefaultWidth; };
+ GLint getDefaultHeight() const { return mDefaultHeight; };
+ GLint getDefaultSamples() const { return mDefaultSamples; };
+ bool getDefaultFixedSampleLocations() const { return mDefaultFixedSampleLocations; };
- bool attachmentsHaveSameDimensions() const;
+ bool hasDepth() const;
+ bool hasStencil() const;
- private:
- friend class Framebuffer;
+ GLenum getMultiviewLayout() const;
+ GLsizei getNumViews() const;
+ const std::vector<Offset> *getViewportOffsets() const;
+ GLint getBaseViewIndex() const;
- std::string mLabel;
+ private:
+ friend class Framebuffer;
- std::vector<FramebufferAttachment> mColorAttachments;
- FramebufferAttachment mDepthAttachment;
- FramebufferAttachment mStencilAttachment;
+ std::string mLabel;
- std::vector<GLenum> mDrawBufferStates;
- GLenum mReadBufferState;
- };
+ std::vector<FramebufferAttachment> mColorAttachments;
+ FramebufferAttachment mDepthAttachment;
+ FramebufferAttachment mStencilAttachment;
- Framebuffer(const Caps &caps, rx::ImplFactory *factory, GLuint id);
- Framebuffer(rx::SurfaceImpl *surface);
- virtual ~Framebuffer();
+ std::vector<GLenum> mDrawBufferStates;
+ GLenum mReadBufferState;
+ DrawBufferMask mEnabledDrawBuffers;
+
+ GLint mDefaultWidth;
+ GLint mDefaultHeight;
+ GLint mDefaultSamples;
+ bool mDefaultFixedSampleLocations;
+
+ // It's necessary to store all this extra state so we can restore attachments
+ // when DEPTH_STENCIL/DEPTH/STENCIL is unbound in WebGL 1.
+ FramebufferAttachment mWebGLDepthStencilAttachment;
+ FramebufferAttachment mWebGLDepthAttachment;
+ FramebufferAttachment mWebGLStencilAttachment;
+ bool mWebGLDepthStencilConsistent;
+
+ // Tracks if we need to initialize the resources for each attachment.
+ angle::BitSet<IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS + 2> mResourceNeedsInit;
+};
+
+class Framebuffer final : public LabeledObject, public OnAttachmentDirtyReceiver
+{
+ public:
+ // Constructor to build application-defined framebuffers
+ Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id);
+ // Constructor to build default framebuffers for a surface
+ Framebuffer(const egl::Display *display, egl::Surface *surface);
+ // Constructor to build a fake default framebuffer when surfaceless
+ Framebuffer(rx::GLImplFactory *factory);
+
+ ~Framebuffer() override;
+ void onDestroy(const Context *context);
+ void destroyDefault(const egl::Display *display);
void setLabel(const std::string &label) override;
const std::string &getLabel() const override;
- const rx::FramebufferImpl *getImplementation() const { return mImpl; }
- rx::FramebufferImpl *getImplementation() { return mImpl; }
+ rx::FramebufferImpl *getImplementation() const { return mImpl; }
GLuint id() const { return mId; }
- void setAttachment(GLenum type,
+ void setAttachment(const Context *context,
+ GLenum type,
GLenum binding,
const ImageIndex &textureIndex,
FramebufferAttachmentObject *resource);
- void resetAttachment(GLenum binding);
-
- void detachTexture(GLuint texture);
- void detachRenderbuffer(GLuint renderbuffer);
+ void setAttachmentMultiviewLayered(const Context *context,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource,
+ GLsizei numViews,
+ GLint baseViewIndex);
+ void setAttachmentMultiviewSideBySide(const Context *context,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource,
+ GLsizei numViews,
+ const GLint *viewportOffsets);
+ void resetAttachment(const Context *context, GLenum binding);
+
+ bool detachTexture(const Context *context, GLuint texture);
+ bool detachRenderbuffer(const Context *context, GLuint renderbuffer);
const FramebufferAttachment *getColorbuffer(size_t colorAttachment) const;
const FramebufferAttachment *getDepthbuffer() const;
const FramebufferAttachment *getStencilbuffer() const;
const FramebufferAttachment *getDepthStencilBuffer() const;
const FramebufferAttachment *getDepthOrStencilbuffer() const;
+ const FramebufferAttachment *getStencilOrDepthStencilAttachment() const;
const FramebufferAttachment *getReadColorbuffer() const;
GLenum getReadColorbufferType() const;
const FramebufferAttachment *getFirstColorbuffer() const;
+ const FramebufferAttachment *getFirstNonNullAttachment() const;
const FramebufferAttachment *getAttachment(GLenum attachment) const;
+ GLenum getMultiviewLayout() const;
+ GLsizei getNumViews() const;
+ GLint getBaseViewIndex() const;
+ const std::vector<Offset> *getViewportOffsets() const;
size_t getDrawbufferStateCount() const;
GLenum getDrawBufferState(size_t drawBuffer) const;
+ const std::vector<GLenum> &getDrawBufferStates() const;
void setDrawBuffers(size_t count, const GLenum *buffers);
const FramebufferAttachment *getDrawBuffer(size_t drawBuffer) const;
+ GLenum getDrawbufferWriteType(size_t drawBuffer) const;
bool hasEnabledDrawBuffer() const;
GLenum getReadBufferState() const;
@@ -129,48 +204,81 @@ class Framebuffer final : public LabeledObject
size_t getNumColorBuffers() const;
bool hasDepth() const;
bool hasStencil() const;
- int getSamples(const gl::Data &data) const;
+
bool usingExtendedDrawBuffers() const;
- GLenum checkStatus(const gl::Data &data) const;
+ // This method calls checkStatus.
+ int getSamples(const Context *context);
+
+ Error getSamplePosition(size_t index, GLfloat *xy) const;
+
+ GLint getDefaultWidth() const;
+ GLint getDefaultHeight() const;
+ GLint getDefaultSamples() const;
+ bool getDefaultFixedSampleLocations() const;
+ void setDefaultWidth(GLint defaultWidth);
+ void setDefaultHeight(GLint defaultHeight);
+ void setDefaultSamples(GLint defaultSamples);
+ void setDefaultFixedSampleLocations(bool defaultFixedSampleLocations);
+
+ void invalidateCompletenessCache();
+
+ GLenum checkStatus(const Context *context);
+
+ // TODO(jmadill): Remove this kludge.
+ GLenum checkStatus(const ValidationContext *context);
+ int getSamples(const ValidationContext *context);
+
+ // For when we don't want to check completeness in getSamples().
+ int getCachedSamples(const Context *context);
+
+ // Helper for checkStatus == GL_FRAMEBUFFER_COMPLETE.
+ bool complete(const Context *context);
+ bool cachedComplete() const;
+
bool hasValidDepthStencil() const;
- Error discard(size_t count, const GLenum *attachments);
- Error invalidate(size_t count, const GLenum *attachments);
- Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area);
+ Error discard(const Context *context, size_t count, const GLenum *attachments);
+ Error invalidate(const Context *context, size_t count, const GLenum *attachments);
+ Error invalidateSub(const Context *context,
+ size_t count,
+ const GLenum *attachments,
+ const gl::Rectangle &area);
- Error clear(const gl::Data &data, GLbitfield mask);
- Error clearBufferfv(const gl::Data &data,
+ Error clear(const gl::Context *context, GLbitfield mask);
+ Error clearBufferfv(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
const GLfloat *values);
- Error clearBufferuiv(const gl::Data &data,
+ Error clearBufferuiv(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
const GLuint *values);
- Error clearBufferiv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLint *values);
- Error clearBufferfi(const gl::Data &data,
+ Error clearBufferiv(const gl::Context *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *values);
+ Error clearBufferfi(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
GLfloat depth,
GLint stencil);
- GLenum getImplementationColorReadFormat() const;
- GLenum getImplementationColorReadType() const;
- Error readPixels(const gl::State &state,
+ GLenum getImplementationColorReadFormat(const Context *context) const;
+ GLenum getImplementationColorReadType(const Context *context) const;
+ Error readPixels(const gl::Context *context,
const gl::Rectangle &area,
GLenum format,
GLenum type,
- GLvoid *pixels) const;
+ void *pixels);
- Error blit(const State &state,
+ Error blit(const gl::Context *context,
const Rectangle &sourceArea,
const Rectangle &destArea,
GLbitfield mask,
- GLenum filter,
- const Framebuffer *sourceFramebuffer);
+ GLenum filter);
- enum DirtyBitType
+ enum DirtyBitType : size_t
{
DIRTY_BIT_COLOR_ATTACHMENT_0,
DIRTY_BIT_COLOR_ATTACHMENT_MAX =
@@ -179,26 +287,103 @@ class Framebuffer final : public LabeledObject
DIRTY_BIT_STENCIL_ATTACHMENT,
DIRTY_BIT_DRAW_BUFFERS,
DIRTY_BIT_READ_BUFFER,
+ DIRTY_BIT_DEFAULT_WIDTH,
+ DIRTY_BIT_DEFAULT_HEIGHT,
+ DIRTY_BIT_DEFAULT_SAMPLES,
+ DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS,
DIRTY_BIT_UNKNOWN,
- DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN,
+ DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN
};
- typedef std::bitset<DIRTY_BIT_MAX> DirtyBits;
+ typedef angle::BitSet<DIRTY_BIT_MAX> DirtyBits;
bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
- void syncState() const;
+ void syncState(const Context *context);
- protected:
- void detachResourceById(GLenum resourceType, GLuint resourceId);
+ // OnAttachmentChangedReceiver implementation
+ void signal(size_t dirtyBit, InitState state) override;
- Data mData;
+ bool formsRenderingFeedbackLoopWith(const State &state) const;
+ bool formsCopyingFeedbackLoopWith(GLuint copyTextureID,
+ GLint copyTextureLevel,
+ GLint copyTextureLayer) const;
+
+ Error ensureDrawAttachmentsInitialized(const Context *context);
+ Error ensureReadAttachmentInitialized(const Context *context, GLbitfield blitMask);
+ Box getDimensions() const;
+
+ bool hasTextureAttachment(const Texture *texture) const;
+
+ private:
+ bool detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId);
+ bool detachMatchingAttachment(const Context *context,
+ FramebufferAttachment *attachment,
+ GLenum matchType,
+ GLuint matchId,
+ size_t dirtyBit);
+ GLenum checkStatusImpl(const Context *context);
+ void setAttachment(const Context *context,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource,
+ GLsizei numViews,
+ GLuint baseViewIndex,
+ GLenum multiviewLayout,
+ const GLint *viewportOffsets);
+ void commitWebGL1DepthStencilIfConsistent(const Context *context,
+ GLsizei numViews,
+ GLuint baseViewIndex,
+ GLenum multiviewLayout,
+ const GLint *viewportOffsets);
+ void setAttachmentImpl(const Context *context,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource,
+ GLsizei numViews,
+ GLuint baseViewIndex,
+ GLenum multiviewLayout,
+ const GLint *viewportOffsets);
+ void updateAttachment(const Context *context,
+ FramebufferAttachment *attachment,
+ size_t dirtyBit,
+ OnAttachmentDirtyBinding *onDirtyBinding,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource,
+ GLsizei numViews,
+ GLuint baseViewIndex,
+ GLenum multiviewLayout,
+ const GLint *viewportOffsets);
+
+ void markDrawAttachmentsInitialized(bool color, bool depth, bool stencil);
+ void markBufferInitialized(GLenum bufferType, GLint bufferIndex);
+ Error ensureBufferInitialized(const Context *context, GLenum bufferType, GLint bufferIndex);
+
+ // Checks that we have a partially masked clear:
+ // * some color channels are masked out
+ // * some stencil values are masked out
+ // * scissor test partially overlaps the framebuffer
+ bool partialClearNeedsInit(const Context *context, bool color, bool depth, bool stencil);
+ bool partialBufferClearNeedsInit(const Context *context, GLenum bufferType);
+
+ FramebufferState mState;
rx::FramebufferImpl *mImpl;
GLuint mId;
- // TODO(jmadill): See if we can make this non-mutable.
- mutable DirtyBits mDirtyBits;
+ Optional<GLenum> mCachedStatus;
+ std::vector<OnAttachmentDirtyBinding> mDirtyColorAttachmentBindings;
+ OnAttachmentDirtyBinding mDirtyDepthAttachmentBinding;
+ OnAttachmentDirtyBinding mDirtyStencilAttachmentBinding;
+
+ DirtyBits mDirtyBits;
+
+ // A cache of attached textures for quick validation of feedback loops.
+ mutable Optional<std::set<const FramebufferAttachmentObject *>> mAttachedTextures;
};
-}
+} // namespace gl
-#endif // LIBANGLE_FRAMEBUFFER_H_
+#endif // LIBANGLE_FRAMEBUFFER_H_
diff --git a/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.cpp b/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.cpp
index 352a326c23..cf6bd9c264 100644
--- a/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.cpp
+++ b/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.cpp
@@ -11,17 +11,48 @@
#include "common/utilities.h"
#include "libANGLE/Config.h"
+#include "libANGLE/Context.h"
#include "libANGLE/Renderbuffer.h"
#include "libANGLE/Surface.h"
#include "libANGLE/Texture.h"
#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
#include "libANGLE/renderer/FramebufferImpl.h"
namespace gl
{
+namespace
+{
+
+std::vector<Offset> TransformViewportOffsetArrayToVectorOfOffsets(const GLint *viewportOffsets,
+ GLsizei numViews)
+{
+ const size_t numViewsAsSizeT = static_cast<size_t>(numViews);
+ std::vector<Offset> offsetVector;
+ offsetVector.reserve(numViewsAsSizeT);
+ for (size_t i = 0u; i < numViewsAsSizeT; ++i)
+ {
+ offsetVector.emplace_back(Offset(viewportOffsets[i * 2u], viewportOffsets[i * 2u + 1u], 0));
+ }
+ return offsetVector;
+}
+
+} // namespace
+
////// FramebufferAttachment::Target Implementation //////
+const GLsizei FramebufferAttachment::kDefaultNumViews = 1;
+const GLenum FramebufferAttachment::kDefaultMultiviewLayout = GL_NONE;
+const GLint FramebufferAttachment::kDefaultBaseViewIndex = 0;
+const GLint FramebufferAttachment::kDefaultViewportOffsets[2] = {0};
+
+std::vector<Offset> FramebufferAttachment::GetDefaultViewportOffsetVector()
+{
+ return TransformViewportOffsetArrayToVectorOfOffsets(
+ FramebufferAttachment::kDefaultViewportOffsets, FramebufferAttachment::kDefaultNumViews);
+}
+
FramebufferAttachment::Target::Target()
: mBinding(GL_NONE),
mTextureIndex(ImageIndex::MakeInvalid())
@@ -50,106 +81,143 @@ FramebufferAttachment::Target &FramebufferAttachment::Target::operator=(const Ta
////// FramebufferAttachment Implementation //////
FramebufferAttachment::FramebufferAttachment()
- : mType(GL_NONE), mResource(nullptr)
+ : mType(GL_NONE),
+ mResource(nullptr),
+ mNumViews(kDefaultNumViews),
+ mMultiviewLayout(kDefaultMultiviewLayout),
+ mBaseViewIndex(kDefaultBaseViewIndex),
+ mViewportOffsets(GetDefaultViewportOffsetVector())
{
}
-FramebufferAttachment::FramebufferAttachment(GLenum type,
+FramebufferAttachment::FramebufferAttachment(const Context *context,
+ GLenum type,
GLenum binding,
const ImageIndex &textureIndex,
FramebufferAttachmentObject *resource)
: mResource(nullptr)
{
- attach(type, binding, textureIndex, resource);
+ attach(context, type, binding, textureIndex, resource, kDefaultNumViews, kDefaultBaseViewIndex,
+ kDefaultMultiviewLayout, kDefaultViewportOffsets);
}
-FramebufferAttachment::FramebufferAttachment(const FramebufferAttachment &other)
- : mResource(nullptr)
+FramebufferAttachment::FramebufferAttachment(FramebufferAttachment &&other)
+ : FramebufferAttachment()
{
- attach(other.mType, other.mTarget.binding(), other.mTarget.textureIndex(), other.mResource);
+ *this = std::move(other);
}
-FramebufferAttachment &FramebufferAttachment::operator=(const FramebufferAttachment &other)
+FramebufferAttachment &FramebufferAttachment::operator=(FramebufferAttachment &&other)
{
- attach(other.mType, other.mTarget.binding(), other.mTarget.textureIndex(), other.mResource);
+ std::swap(mType, other.mType);
+ std::swap(mTarget, other.mTarget);
+ std::swap(mResource, other.mResource);
+ std::swap(mNumViews, other.mNumViews);
+ std::swap(mMultiviewLayout, other.mMultiviewLayout);
+ std::swap(mBaseViewIndex, other.mBaseViewIndex);
+ std::swap(mViewportOffsets, other.mViewportOffsets);
return *this;
}
FramebufferAttachment::~FramebufferAttachment()
{
- detach();
+ ASSERT(!isAttached());
}
-void FramebufferAttachment::detach()
+void FramebufferAttachment::detach(const Context *context)
{
mType = GL_NONE;
if (mResource != nullptr)
{
- mResource->onDetach();
+ mResource->onDetach(context);
mResource = nullptr;
}
+ mNumViews = kDefaultNumViews;
+ mMultiviewLayout = kDefaultMultiviewLayout;
+ mBaseViewIndex = kDefaultBaseViewIndex;
+ mViewportOffsets = GetDefaultViewportOffsetVector();
// not technically necessary, could omit for performance
mTarget = Target();
}
-void FramebufferAttachment::attach(GLenum type,
+void FramebufferAttachment::attach(const Context *context,
+ GLenum type,
GLenum binding,
const ImageIndex &textureIndex,
- FramebufferAttachmentObject *resource)
+ FramebufferAttachmentObject *resource,
+ GLsizei numViews,
+ GLuint baseViewIndex,
+ GLenum multiviewLayout,
+ const GLint *viewportOffsets)
{
+ if (resource == nullptr)
+ {
+ detach(context);
+ return;
+ }
+
mType = type;
mTarget = Target(binding, textureIndex);
-
- if (resource)
+ mNumViews = numViews;
+ mBaseViewIndex = baseViewIndex;
+ mMultiviewLayout = multiviewLayout;
+ if (multiviewLayout == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE)
{
- resource->onAttach();
+ mViewportOffsets = TransformViewportOffsetArrayToVectorOfOffsets(viewportOffsets, numViews);
}
+ else
+ {
+ mViewportOffsets = GetDefaultViewportOffsetVector();
+ }
+ resource->onAttach(context);
+
if (mResource != nullptr)
{
- mResource->onDetach();
+ mResource->onDetach(context);
}
+
mResource = resource;
}
GLuint FramebufferAttachment::getRedSize() const
{
- return GetInternalFormatInfo(getInternalFormat()).redBits;
+ return getFormat().info->redBits;
}
GLuint FramebufferAttachment::getGreenSize() const
{
- return GetInternalFormatInfo(getInternalFormat()).greenBits;
+ return getFormat().info->greenBits;
}
GLuint FramebufferAttachment::getBlueSize() const
{
- return GetInternalFormatInfo(getInternalFormat()).blueBits;
+ return getFormat().info->blueBits;
}
GLuint FramebufferAttachment::getAlphaSize() const
{
- return GetInternalFormatInfo(getInternalFormat()).alphaBits;
+ return getFormat().info->alphaBits;
}
GLuint FramebufferAttachment::getDepthSize() const
{
- return GetInternalFormatInfo(getInternalFormat()).depthBits;
+ return getFormat().info->depthBits;
}
GLuint FramebufferAttachment::getStencilSize() const
{
- return GetInternalFormatInfo(getInternalFormat()).stencilBits;
+ return getFormat().info->stencilBits;
}
GLenum FramebufferAttachment::getComponentType() const
{
- return GetInternalFormatInfo(getInternalFormat()).componentType;
+ return getFormat().info->componentType;
}
GLenum FramebufferAttachment::getColorEncoding() const
{
- return GetInternalFormatInfo(getInternalFormat()).colorEncoding;
+ return getFormat().info->colorEncoding;
}
GLuint FramebufferAttachment::id() const
@@ -190,6 +258,26 @@ GLint FramebufferAttachment::layer() const
return 0;
}
+GLsizei FramebufferAttachment::getNumViews() const
+{
+ return mNumViews;
+}
+
+GLenum FramebufferAttachment::getMultiviewLayout() const
+{
+ return mMultiviewLayout;
+}
+
+GLint FramebufferAttachment::getBaseViewIndex() const
+{
+ return mBaseViewIndex;
+}
+
+const std::vector<Offset> &FramebufferAttachment::getMultiviewViewportOffsets() const
+{
+ return mViewportOffsets;
+}
+
Texture *FramebufferAttachment::getTexture() const
{
return rx::GetAs<Texture>(mResource);
@@ -205,4 +293,93 @@ const egl::Surface *FramebufferAttachment::getSurface() const
return rx::GetAs<egl::Surface>(mResource);
}
+FramebufferAttachmentObject *FramebufferAttachment::getResource() const
+{
+ return mResource;
}
+
+bool FramebufferAttachment::operator==(const FramebufferAttachment &other) const
+{
+ if (mResource != other.mResource || mType != other.mType || mNumViews != other.mNumViews ||
+ mMultiviewLayout != other.mMultiviewLayout || mBaseViewIndex != other.mBaseViewIndex ||
+ mViewportOffsets != other.mViewportOffsets)
+ {
+ return false;
+ }
+
+ if (mType == GL_TEXTURE && getTextureImageIndex() != other.getTextureImageIndex())
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool FramebufferAttachment::operator!=(const FramebufferAttachment &other) const
+{
+ return !(*this == other);
+}
+
+InitState FramebufferAttachment::initState() const
+{
+ return mResource ? mResource->initState(mTarget.textureIndex()) : InitState::Initialized;
+}
+
+Error FramebufferAttachment::initializeContents(const Context *context)
+{
+ ASSERT(mResource);
+ ANGLE_TRY(mResource->initializeContents(context, mTarget.textureIndex()));
+ setInitState(InitState::Initialized);
+ return NoError();
+}
+
+void FramebufferAttachment::setInitState(InitState initState) const
+{
+ ASSERT(mResource);
+ mResource->setInitState(mTarget.textureIndex(), initState);
+}
+
+////// FramebufferAttachmentObject Implementation //////
+
+FramebufferAttachmentObject::FramebufferAttachmentObject()
+{
+}
+
+FramebufferAttachmentObject::~FramebufferAttachmentObject()
+{
+}
+
+Error FramebufferAttachmentObject::getAttachmentRenderTarget(
+ const Context *context,
+ GLenum binding,
+ const ImageIndex &imageIndex,
+ rx::FramebufferAttachmentRenderTarget **rtOut) const
+{
+ return getAttachmentImpl()->getAttachmentRenderTarget(context, binding, imageIndex, rtOut);
+}
+
+OnAttachmentDirtyChannel *FramebufferAttachmentObject::getDirtyChannel()
+{
+ return &mDirtyChannel;
+}
+
+Error FramebufferAttachmentObject::initializeContents(const Context *context,
+ const ImageIndex &imageIndex)
+{
+ ASSERT(context->isRobustResourceInitEnabled());
+
+ // Because gl::Texture cannot support tracking individual layer dirtiness, we only handle
+ // initializing entire mip levels for 2D array textures.
+ if (imageIndex.type == GL_TEXTURE_2D_ARRAY && imageIndex.hasLayer())
+ {
+ ImageIndex fullMipIndex = imageIndex;
+ fullMipIndex.layerIndex = ImageIndex::ENTIRE_LEVEL;
+ return getAttachmentImpl()->initializeContents(context, fullMipIndex);
+ }
+ else
+ {
+ return getAttachmentImpl()->initializeContents(context, imageIndex);
+ }
+}
+
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.h b/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.h
index 33196f5c61..5c0553a1d4 100644
--- a/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.h
+++ b/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.h
@@ -15,6 +15,7 @@
#include "libANGLE/angletypes.h"
#include "libANGLE/Error.h"
#include "libANGLE/ImageIndex.h"
+#include "libANGLE/signal_utils.h"
namespace egl
{
@@ -38,9 +39,20 @@ class FramebufferAttachmentObjectImpl;
namespace gl
{
class FramebufferAttachmentObject;
+struct Format;
class Renderbuffer;
class Texture;
+enum class InitState
+{
+ MayNeedInit,
+ Initialized,
+};
+
+using OnAttachmentDirtyBinding = angle::ChannelBinding<size_t, InitState>;
+using OnAttachmentDirtyChannel = angle::BroadcastChannel<size_t, InitState>;
+using OnAttachmentDirtyReceiver = angle::SignalReceiver<size_t, InitState>;
+
// FramebufferAttachment implements a GL framebuffer attachment.
// Attachments are "light" containers, which store pointers to ref-counted GL objects.
// We support GL texture (2D/3D/Cube/2D array) and renderbuffer object attachments.
@@ -52,43 +64,27 @@ class FramebufferAttachment final
public:
FramebufferAttachment();
- FramebufferAttachment(GLenum type,
+ FramebufferAttachment(const Context *context,
+ GLenum type,
GLenum binding,
const ImageIndex &textureIndex,
FramebufferAttachmentObject *resource);
- FramebufferAttachment(const FramebufferAttachment &other);
- FramebufferAttachment &operator=(const FramebufferAttachment &other);
+ FramebufferAttachment(FramebufferAttachment &&other);
+ FramebufferAttachment &operator=(FramebufferAttachment &&other);
~FramebufferAttachment();
- // A framebuffer attachment points to one of three types of resources: Renderbuffers,
- // Textures and egl::Surface. The "Target" struct indicates which part of the
- // object an attachment references. For the three types:
- // - a Renderbuffer has a unique renderable target, and needs no target index
- // - a Texture has targets for every image and uses an ImageIndex
- // - a Surface has targets for Color and Depth/Stencil, and uses the attachment binding
- class Target
- {
- public:
- Target();
- Target(GLenum binding, const ImageIndex &imageIndex);
- Target(const Target &other);
- Target &operator=(const Target &other);
-
- GLenum binding() const { return mBinding; }
- const ImageIndex &textureIndex() const { return mTextureIndex; }
-
- private:
- GLenum mBinding;
- ImageIndex mTextureIndex;
- };
-
- void detach();
- void attach(GLenum type,
+ void detach(const Context *context);
+ void attach(const Context *context,
+ GLenum type,
GLenum binding,
const ImageIndex &textureIndex,
- FramebufferAttachmentObject *resource);
+ FramebufferAttachmentObject *resource,
+ GLsizei numViews,
+ GLuint baseViewIndex,
+ GLenum multiviewLayout,
+ const GLint *viewportOffsets);
// Helper methods
GLuint getRedSize() const;
@@ -111,12 +107,16 @@ class FramebufferAttachment final
GLenum cubeMapFace() const;
GLint mipLevel() const;
GLint layer() const;
+ GLsizei getNumViews() const;
+ GLenum getMultiviewLayout() const;
+ GLint getBaseViewIndex() const;
+ const std::vector<Offset> &getMultiviewViewportOffsets() const;
// The size of the underlying resource the attachment points to. The 'depth' value will
// correspond to a 3D texture depth or the layer count of a 2D array texture. For Surfaces and
// Renderbuffers, it will always be 1.
Extents getSize() const;
- GLenum getInternalFormat() const;
+ const Format &getFormat() const;
GLsizei getSamples() const;
GLenum type() const { return mType; }
bool isAttached() const { return mType != GL_NONE; }
@@ -124,95 +124,127 @@ class FramebufferAttachment final
Renderbuffer *getRenderbuffer() const;
Texture *getTexture() const;
const egl::Surface *getSurface() const;
+ FramebufferAttachmentObject *getResource() const;
+ InitState initState() const;
+ Error initializeContents(const Context *context);
+ void setInitState(InitState initState) const;
// "T" must be static_castable from FramebufferAttachmentRenderTarget
template <typename T>
- gl::Error getRenderTarget(T **rtOut) const
+ gl::Error getRenderTarget(const Context *context, T **rtOut) const
{
- // Cast through the pointer-to-pointer type
- rx::FramebufferAttachmentRenderTarget *rtPtr = nullptr;
- gl::Error error = getRenderTarget(&rtPtr);
- *rtOut = static_cast<T*>(rtPtr);
- return error;
+ static_assert(std::is_base_of<rx::FramebufferAttachmentRenderTarget, T>(),
+ "Invalid RenderTarget class.");
+ return getRenderTargetImpl(
+ context, reinterpret_cast<rx::FramebufferAttachmentRenderTarget **>(rtOut));
}
+ bool operator==(const FramebufferAttachment &other) const;
+ bool operator!=(const FramebufferAttachment &other) const;
+
+ static std::vector<Offset> GetDefaultViewportOffsetVector();
+ static const GLsizei kDefaultNumViews;
+ static const GLenum kDefaultMultiviewLayout;
+ static const GLint kDefaultBaseViewIndex;
+ static const GLint kDefaultViewportOffsets[2];
+
private:
- gl::Error getRenderTarget(rx::FramebufferAttachmentRenderTarget **rtOut) const;
+ gl::Error getRenderTargetImpl(const Context *context,
+ rx::FramebufferAttachmentRenderTarget **rtOut) const;
+
+ // A framebuffer attachment points to one of three types of resources: Renderbuffers,
+ // Textures and egl::Surface. The "Target" struct indicates which part of the
+ // object an attachment references. For the three types:
+ // - a Renderbuffer has a unique renderable target, and needs no target index
+ // - a Texture has targets for every image and uses an ImageIndex
+ // - a Surface has targets for Color and Depth/Stencil, and uses the attachment binding
+ class Target
+ {
+ public:
+ Target();
+ Target(GLenum binding, const ImageIndex &imageIndex);
+ Target(const Target &other);
+ Target &operator=(const Target &other);
+
+ GLenum binding() const { return mBinding; }
+ const ImageIndex &textureIndex() const { return mTextureIndex; }
+
+ private:
+ GLenum mBinding;
+ ImageIndex mTextureIndex;
+ };
GLenum mType;
Target mTarget;
FramebufferAttachmentObject *mResource;
+ GLsizei mNumViews;
+ GLenum mMultiviewLayout;
+ GLint mBaseViewIndex;
+ std::vector<Offset> mViewportOffsets;
};
// A base class for objects that FBO Attachments may point to.
class FramebufferAttachmentObject
{
public:
- FramebufferAttachmentObject() {}
- virtual ~FramebufferAttachmentObject() {}
+ FramebufferAttachmentObject();
+ virtual ~FramebufferAttachmentObject();
- virtual Extents getAttachmentSize(const FramebufferAttachment::Target &target) const = 0;
- virtual GLenum getAttachmentInternalFormat(const FramebufferAttachment::Target &target) const = 0;
- virtual GLsizei getAttachmentSamples(const FramebufferAttachment::Target &target) const = 0;
+ virtual Extents getAttachmentSize(const ImageIndex &imageIndex) const = 0;
+ virtual const Format &getAttachmentFormat(GLenum binding,
+ const ImageIndex &imageIndex) const = 0;
+ virtual GLsizei getAttachmentSamples(const ImageIndex &imageIndex) const = 0;
- virtual void onAttach() = 0;
- virtual void onDetach() = 0;
+ virtual void onAttach(const Context *context) = 0;
+ virtual void onDetach(const Context *context) = 0;
virtual GLuint getId() const = 0;
- Error getAttachmentRenderTarget(const FramebufferAttachment::Target &target,
+ // These are used for robust resource initialization.
+ virtual InitState initState(const ImageIndex &imageIndex) const = 0;
+ virtual void setInitState(const ImageIndex &imageIndex, InitState initState) = 0;
+
+ Error getAttachmentRenderTarget(const Context *context,
+ GLenum binding,
+ const ImageIndex &imageIndex,
rx::FramebufferAttachmentRenderTarget **rtOut) const;
+ Error initializeContents(const Context *context, const ImageIndex &imageIndex);
+
+ OnAttachmentDirtyChannel *getDirtyChannel();
+
protected:
virtual rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const = 0;
+
+ OnAttachmentDirtyChannel mDirtyChannel;
};
inline Extents FramebufferAttachment::getSize() const
{
- return mResource->getAttachmentSize(mTarget);
+ ASSERT(mResource);
+ return mResource->getAttachmentSize(mTarget.textureIndex());
}
-inline GLenum FramebufferAttachment::getInternalFormat() const
+inline const Format &FramebufferAttachment::getFormat() const
{
- return mResource->getAttachmentInternalFormat(mTarget);
+ ASSERT(mResource);
+ return mResource->getAttachmentFormat(mTarget.binding(), mTarget.textureIndex());
}
inline GLsizei FramebufferAttachment::getSamples() const
{
- return mResource->getAttachmentSamples(mTarget);
-}
-
-inline gl::Error FramebufferAttachment::getRenderTarget(rx::FramebufferAttachmentRenderTarget **rtOut) const
-{
- return mResource->getAttachmentRenderTarget(mTarget, rtOut);
+ ASSERT(mResource);
+ return mResource->getAttachmentSamples(mTarget.textureIndex());
}
-} // namespace gl
-
-namespace rx
-{
-
-class FramebufferAttachmentObjectImpl : angle::NonCopyable
-{
- public:
- FramebufferAttachmentObjectImpl() {}
- virtual ~FramebufferAttachmentObjectImpl() {}
-
- virtual gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target,
- FramebufferAttachmentRenderTarget **rtOut) = 0;
-};
-
-} // namespace rx
-
-namespace gl
-{
-
-inline Error FramebufferAttachmentObject::getAttachmentRenderTarget(
- const FramebufferAttachment::Target &target,
+inline gl::Error FramebufferAttachment::getRenderTargetImpl(
+ const Context *context,
rx::FramebufferAttachmentRenderTarget **rtOut) const
{
- return getAttachmentImpl()->getAttachmentRenderTarget(target, rtOut);
+ ASSERT(mResource);
+ return mResource->getAttachmentRenderTarget(context, mTarget.binding(), mTarget.textureIndex(),
+ rtOut);
}
-}
+} // namespace gl
#endif // LIBANGLE_FRAMEBUFFERATTACHMENT_H_
diff --git a/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp b/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp
index 4815855d5a..c3c184258f 100644
--- a/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp
+++ b/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp
@@ -49,9 +49,10 @@ GLuint HandleAllocator::allocate()
{
ASSERT(!mUnallocatedList.empty() || !mReleasedList.empty());
- // Allocate from released list, constant time.
+ // Allocate from released list, logarithmic time for pop_heap.
if (!mReleasedList.empty())
{
+ std::pop_heap(mReleasedList.begin(), mReleasedList.end());
GLuint reusedHandle = mReleasedList.back();
mReleasedList.pop_back();
return reusedHandle;
@@ -63,19 +64,23 @@ GLuint HandleAllocator::allocate()
GLuint freeListHandle = listIt->begin;
ASSERT(freeListHandle > 0);
- listIt->begin++;
if (listIt->begin == listIt->end)
{
mUnallocatedList.erase(listIt);
}
+ else
+ {
+ listIt->begin++;
+ }
return freeListHandle;
}
void HandleAllocator::release(GLuint handle)
{
- // Add to released list, constant time.
+ // Add to released list, logarithmic time for push_heap.
mReleasedList.push_back(handle);
+ std::push_heap(mReleasedList.begin(), mReleasedList.end());
}
void HandleAllocator::reserve(GLuint handle)
@@ -101,7 +106,7 @@ void HandleAllocator::reserve(GLuint handle)
if (handle == begin || handle == end)
{
- if (begin + 1 == end)
+ if (begin == end)
{
mUnallocatedList.erase(boundIt);
}
@@ -117,18 +122,21 @@ void HandleAllocator::reserve(GLuint handle)
return;
}
+ ASSERT(begin < handle && handle < end);
+
// need to split the range
auto placementIt = mUnallocatedList.erase(boundIt);
+ placementIt = mUnallocatedList.insert(placementIt, HandleRange(handle + 1, end));
+ mUnallocatedList.insert(placementIt, HandleRange(begin, handle - 1));
+}
- if (handle + 1 != end)
- {
- placementIt = mUnallocatedList.insert(placementIt, HandleRange(handle + 1, end));
- }
- if (begin != handle)
- {
- ASSERT(begin < handle);
- mUnallocatedList.insert(placementIt, HandleRange(begin, handle));
- }
+void HandleAllocator::reset()
+{
+ mUnallocatedList.clear();
+ mUnallocatedList.push_back(HandleRange(1, std::numeric_limits<GLuint>::max()));
+ mReleasedList.clear();
+ mBaseValue = 1;
+ mNextValue = 1;
}
} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/HandleAllocator.h b/src/3rdparty/angle/src/libANGLE/HandleAllocator.h
index 1888d57cfa..cd21d687f4 100644
--- a/src/3rdparty/angle/src/libANGLE/HandleAllocator.h
+++ b/src/3rdparty/angle/src/libANGLE/HandleAllocator.h
@@ -14,8 +14,6 @@
#include "angle_gl.h"
-#include <stack>
-
namespace gl
{
@@ -24,7 +22,7 @@ class HandleAllocator final : angle::NonCopyable
public:
// Maximum handle = MAX_UINT-1
HandleAllocator();
- // Specify maximum handle value
+ // Specify maximum handle value. Used for testing.
HandleAllocator(GLuint maximumHandleValue);
~HandleAllocator();
@@ -34,6 +32,7 @@ class HandleAllocator final : angle::NonCopyable
GLuint allocate();
void release(GLuint handle);
void reserve(GLuint handle);
+ void reset();
private:
GLuint mBaseValue;
@@ -41,6 +40,7 @@ class HandleAllocator final : angle::NonCopyable
typedef std::vector<GLuint> HandleList;
HandleList mFreeValues;
+ // Represents an inclusive range [begin, end]
struct HandleRange
{
HandleRange(GLuint beginIn, GLuint endIn) : begin(beginIn), end(endIn) {}
@@ -53,7 +53,7 @@ class HandleAllocator final : angle::NonCopyable
// The freelist consists of never-allocated handles, stored
// as ranges, and handles that were previously allocated and
- // released, stored in a stack.
+ // released, stored in a heap.
std::vector<HandleRange> mUnallocatedList;
std::vector<GLuint> mReleasedList;
};
diff --git a/src/3rdparty/angle/src/libANGLE/HandleRangeAllocator.cpp b/src/3rdparty/angle/src/libANGLE/HandleRangeAllocator.cpp
new file mode 100644
index 0000000000..2a97ce939f
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/HandleRangeAllocator.cpp
@@ -0,0 +1,229 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// HandleRangeAllocator.cpp : Implementation for HandleRangeAllocator.h
+
+#include "libANGLE/HandleRangeAllocator.h"
+
+#include <algorithm>
+#include <limits>
+#include <utility>
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+
+namespace gl
+{
+
+const GLuint HandleRangeAllocator::kInvalidHandle = 0;
+
+HandleRangeAllocator::HandleRangeAllocator()
+{
+ // Simplify the code by making sure that lower_bound(id) never
+ // returns the beginning of the map, if id is valid (eg != kInvalidHandle).
+ mUsed.insert(std::make_pair(0u, 0u));
+}
+
+HandleRangeAllocator::~HandleRangeAllocator()
+{
+}
+
+GLuint HandleRangeAllocator::allocate()
+{
+ return allocateRange(1u);
+}
+
+GLuint HandleRangeAllocator::allocateAtOrAbove(GLuint wanted)
+{
+ if (wanted == 0u || wanted == 1u)
+ return allocateRange(1u);
+
+ auto current = mUsed.lower_bound(wanted);
+ auto next = current;
+ if (current == mUsed.end() || current->first > wanted)
+ {
+ current--;
+ }
+ else
+ {
+ next++;
+ }
+
+ GLuint firstId = current->first;
+ GLuint lastId = current->second;
+ ASSERT(wanted >= firstId);
+
+ if (wanted - 1u <= lastId)
+ {
+ // Append to current range.
+ lastId++;
+ if (lastId == 0)
+ {
+ // The increment overflowed.
+ return allocateRange(1u);
+ }
+
+ current->second = lastId;
+
+ if (next != mUsed.end() && next->first - 1u == lastId)
+ {
+ // Merge with next range.
+ current->second = next->second;
+ mUsed.erase(next);
+ }
+ return lastId;
+ }
+ else if (next != mUsed.end() && next->first - 1u == wanted)
+ {
+ // Prepend to next range.
+ GLuint lastExisting = next->second;
+ mUsed.erase(next);
+ mUsed.insert(std::make_pair(wanted, lastExisting));
+ return wanted;
+ }
+ mUsed.insert(std::make_pair(wanted, wanted));
+ return wanted;
+}
+
+GLuint HandleRangeAllocator::allocateRange(GLuint range)
+{
+ ASSERT(range != 0);
+
+ auto current = mUsed.begin();
+ auto next = current;
+
+ while (++next != mUsed.end())
+ {
+ if (next->first - current->second > range)
+ break;
+ current = next;
+ }
+ const GLuint firstId = current->second + 1u;
+ const GLuint lastId = firstId + range - 1u;
+
+ // deal with wraparound
+ if (firstId == 0u || lastId < firstId)
+ return kInvalidHandle;
+
+ current->second = lastId;
+
+ if (next != mUsed.end() && next->first - 1u == lastId)
+ {
+ // merge with next range
+ current->second = next->second;
+ mUsed.erase(next);
+ }
+ return firstId;
+}
+
+bool HandleRangeAllocator::markAsUsed(GLuint handle)
+{
+ ASSERT(handle);
+ auto current = mUsed.lower_bound(handle);
+ if (current != mUsed.end() && current->first == handle)
+ return false;
+
+ auto next = current;
+ --current;
+
+ if (current->second >= handle)
+ return false;
+
+ ASSERT(current->first < handle && current->second < handle);
+
+ if (current->second + 1u == handle)
+ {
+ // Append to current range.
+ current->second = handle;
+ if (next != mUsed.end() && next->first - 1u == handle)
+ {
+ // Merge with next range.
+ current->second = next->second;
+ mUsed.erase(next);
+ }
+ return true;
+ }
+ else if (next != mUsed.end() && next->first - 1u == handle)
+ {
+ // Prepend to next range.
+ GLuint lastExisting = next->second;
+ mUsed.erase(next);
+ mUsed.insert(std::make_pair(handle, lastExisting));
+ return true;
+ }
+
+ mUsed.insert(std::make_pair(handle, handle));
+ return true;
+}
+
+void HandleRangeAllocator::release(GLuint handle)
+{
+ releaseRange(handle, 1u);
+}
+
+void HandleRangeAllocator::releaseRange(GLuint first, GLuint range)
+{
+ if (range == 0u || (first == 0u && range == 1u))
+ return;
+
+ if (first == 0u)
+ {
+ first++;
+ range--;
+ }
+
+ GLuint last = first + range - 1u;
+ if (last < first)
+ last = std::numeric_limits<GLuint>::max();
+
+ while (true)
+ {
+ auto current = mUsed.lower_bound(last);
+ if (current == mUsed.end() || current->first > last)
+ --current;
+
+ if (current->second < first)
+ return;
+
+ if (current->first >= first)
+ {
+ const GLuint lastExisting = current->second;
+ mUsed.erase(current);
+ if (last < lastExisting)
+ {
+ mUsed.insert(std::make_pair(last + 1u, lastExisting));
+ }
+ }
+ else if (current->second <= last)
+ {
+ current->second = first - 1u;
+ }
+ else
+ {
+ ASSERT(current->first < first && current->second > last);
+ const GLuint lastExisting = current->second;
+ current->second = first - 1u;
+ mUsed.insert(std::make_pair(last + 1u, lastExisting));
+ }
+ }
+}
+
+bool HandleRangeAllocator::isUsed(GLuint handle) const
+{
+ if (handle == kInvalidHandle)
+ return false;
+
+ auto current = mUsed.lower_bound(handle);
+ if (current != mUsed.end())
+ {
+ if (current->first == handle)
+ return true;
+ }
+ --current;
+ return current->second >= handle;
+}
+
+} // namespace gl \ No newline at end of file
diff --git a/src/3rdparty/angle/src/libANGLE/HandleRangeAllocator.h b/src/3rdparty/angle/src/libANGLE/HandleRangeAllocator.h
new file mode 100644
index 0000000000..4d4b6f4f69
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/HandleRangeAllocator.h
@@ -0,0 +1,60 @@
+//
+// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// HandleRangeAllocator.h: Defines the gl::HandleRangeAllocator class, which is used to
+// allocate contiguous ranges of GL path handles.
+
+#ifndef LIBANGLE_HANDLERANGEALLOCATOR_H_
+#define LIBANGLE_HANDLERANGEALLOCATOR_H_
+
+#include <map>
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+
+namespace gl
+{
+
+// Allocates contiguous ranges of path object handles.
+class HandleRangeAllocator final : angle::NonCopyable
+{
+ public:
+ static const GLuint kInvalidHandle;
+
+ HandleRangeAllocator();
+ ~HandleRangeAllocator();
+
+ // Allocates a new path handle.
+ GLuint allocate();
+
+ // Allocates a handle starting at or above the value of |wanted|.
+ // Note: may wrap if it starts near limit.
+ GLuint allocateAtOrAbove(GLuint wanted);
+
+ // Allocates |range| amount of contiguous paths.
+ // Returns the first id to |first_id| or |kInvalidHandle| if
+ // allocation failed.
+ GLuint allocateRange(GLuint range);
+
+ // Marks an id as used. Returns false if handle was already used.
+ bool markAsUsed(GLuint handle);
+
+ // Release handle.
+ void release(GLuint handle);
+
+ // Release a |range| amount of contiguous handles, starting from |first|
+ void releaseRange(GLuint first, GLuint range);
+
+ // Checks whether or not a resource ID is in use.
+ bool isUsed(GLuint handle) const;
+
+ private:
+ std::map<GLuint, GLuint> mUsed;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_HANDLERANGEALLOCATOR_H_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/libANGLE/Image.cpp b/src/3rdparty/angle/src/libANGLE/Image.cpp
index a9448e3f6c..04c757c2c4 100644
--- a/src/3rdparty/angle/src/libANGLE/Image.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Image.cpp
@@ -11,13 +11,42 @@
#include "common/debug.h"
#include "common/utilities.h"
#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
#include "libANGLE/Texture.h"
#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/renderer/EGLImplFactory.h"
#include "libANGLE/renderer/ImageImpl.h"
namespace egl
{
-ImageSibling::ImageSibling(GLuint id) : RefCountObject(id), mSourcesOf(), mTargetOf()
+
+namespace
+{
+gl::ImageIndex GetImageIndex(EGLenum eglTarget, const egl::AttributeMap &attribs)
+{
+ if (eglTarget == EGL_GL_RENDERBUFFER)
+ {
+ return gl::ImageIndex::MakeInvalid();
+ }
+
+ GLenum target = egl_gl::EGLImageTargetToGLTextureTarget(eglTarget);
+ GLint mip = static_cast<GLint>(attribs.get(EGL_GL_TEXTURE_LEVEL_KHR, 0));
+ GLint layer = static_cast<GLint>(attribs.get(EGL_GL_TEXTURE_ZOFFSET_KHR, 0));
+
+ if (target == GL_TEXTURE_3D)
+ {
+ return gl::ImageIndex::Make3D(mip, layer);
+ }
+ else
+ {
+ ASSERT(layer == 0);
+ return gl::ImageIndex::MakeGeneric(target, mip);
+ }
+}
+} // anonymous namespace
+
+ImageSibling::ImageSibling(GLuint id)
+ : RefCountObject(id), FramebufferAttachmentObject(), mSourcesOf(), mTargetOf()
{
}
@@ -25,46 +54,38 @@ ImageSibling::~ImageSibling()
{
// EGL images should hold a ref to their targets and siblings, a Texture should not be deletable
// while it is attached to an EGL image.
+ // Child class should orphan images before destruction.
ASSERT(mSourcesOf.empty());
- orphanImages();
+ ASSERT(mTargetOf.get() == nullptr);
}
-void ImageSibling::setTargetImage(egl::Image *imageTarget)
+void ImageSibling::setTargetImage(const gl::Context *context, egl::Image *imageTarget)
{
ASSERT(imageTarget != nullptr);
- mTargetOf.set(imageTarget);
+ mTargetOf.set(context, imageTarget);
imageTarget->addTargetSibling(this);
}
-gl::Error ImageSibling::orphanImages()
+gl::Error ImageSibling::orphanImages(const gl::Context *context)
{
if (mTargetOf.get() != nullptr)
{
// Can't be a target and have sources.
ASSERT(mSourcesOf.empty());
- gl::Error error = mTargetOf->orphanSibling(this);
- if (error.isError())
- {
- return error;
- }
-
- mTargetOf.set(nullptr);
+ ANGLE_TRY(mTargetOf->orphanSibling(context, this));
+ mTargetOf.set(context, nullptr);
}
else
{
- for (auto &sourceImage : mSourcesOf)
+ for (egl::Image *sourceImage : mSourcesOf)
{
- gl::Error error = sourceImage->orphanSibling(this);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(sourceImage->orphanSibling(context, this));
}
mSourcesOf.clear();
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
void ImageSibling::addImageSource(egl::Image *imageSource)
@@ -79,114 +100,146 @@ void ImageSibling::removeImageSource(egl::Image *imageSource)
mSourcesOf.erase(imageSource);
}
-Image::Image(rx::ImageImpl *impl, EGLenum target, ImageSibling *buffer, const AttributeMap &attribs)
+bool ImageSibling::isEGLImageTarget() const
+{
+ return (mTargetOf.get() != nullptr);
+}
+
+gl::InitState ImageSibling::sourceEGLImageInitState() const
+{
+ ASSERT(isEGLImageTarget());
+ return mTargetOf->sourceInitState();
+}
+
+void ImageSibling::setSourceEGLImageInitState(gl::InitState initState) const
+{
+ ASSERT(isEGLImageTarget());
+ mTargetOf->setInitState(initState);
+}
+
+ImageState::ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs)
+ : imageIndex(GetImageIndex(target, attribs)), source(buffer), targets()
+{
+}
+
+ImageState::~ImageState()
+{
+}
+
+Image::Image(rx::EGLImplFactory *factory,
+ EGLenum target,
+ ImageSibling *buffer,
+ const AttributeMap &attribs)
: RefCountObject(0),
- mImplementation(impl),
- mInternalFormat(GL_NONE),
- mWidth(0),
- mHeight(0),
- mSamples(0),
- mSource(),
- mTargets()
+ mState(target, buffer, attribs),
+ mImplementation(factory->createImage(mState, target, attribs)),
+ mOrphanedAndNeedsInit(false)
{
ASSERT(mImplementation != nullptr);
ASSERT(buffer != nullptr);
- mSource.set(buffer);
- mSource->addImageSource(this);
-
- if (IsTextureTarget(target))
- {
- gl::Texture *texture = rx::GetAs<gl::Texture>(mSource.get());
- GLenum textureTarget = egl_gl::EGLImageTargetToGLTextureTarget(target);
- size_t level = attribs.get(EGL_GL_TEXTURE_LEVEL_KHR, 0);
- mInternalFormat = texture->getInternalFormat(textureTarget, level);
- mWidth = texture->getWidth(textureTarget, level);
- mHeight = texture->getHeight(textureTarget, level);
- mSamples = 0;
- }
- else if (IsRenderbufferTarget(target))
- {
- gl::Renderbuffer *renderbuffer = rx::GetAs<gl::Renderbuffer>(mSource.get());
- mInternalFormat = renderbuffer->getInternalFormat();
- mWidth = renderbuffer->getWidth();
- mHeight = renderbuffer->getHeight();
- mSamples = renderbuffer->getSamples();
- }
- else
- {
- UNREACHABLE();
- }
+ mState.source->addImageSource(this);
}
-Image::~Image()
+gl::Error Image::onDestroy(const gl::Context *context)
{
- SafeDelete(mImplementation);
-
// All targets should hold a ref to the egl image and it should not be deleted until there are
// no siblings left.
- ASSERT(mTargets.empty());
+ ASSERT(mState.targets.empty());
// Tell the source that it is no longer used by this image
- if (mSource.get() != nullptr)
+ if (mState.source.get() != nullptr)
{
- mSource->removeImageSource(this);
- mSource.set(nullptr);
+ mState.source->removeImageSource(this);
+ mState.source.set(context, nullptr);
}
+ return gl::NoError();
+}
+
+Image::~Image()
+{
+ SafeDelete(mImplementation);
}
void Image::addTargetSibling(ImageSibling *sibling)
{
- mTargets.insert(sibling);
+ mState.targets.insert(sibling);
}
-gl::Error Image::orphanSibling(ImageSibling *sibling)
+gl::Error Image::orphanSibling(const gl::Context *context, ImageSibling *sibling)
{
// notify impl
- gl::Error error = mImplementation->orphan(sibling);
+ ANGLE_TRY(mImplementation->orphan(context, sibling));
- if (mSource.get() == sibling)
+ if (mState.source.get() == sibling)
{
// If the sibling is the source, it cannot be a target.
- ASSERT(mTargets.find(sibling) == mTargets.end());
-
- mSource.set(nullptr);
+ ASSERT(mState.targets.find(sibling) == mState.targets.end());
+ mState.source.set(context, nullptr);
+ mOrphanedAndNeedsInit =
+ (sibling->initState(mState.imageIndex) == gl::InitState::MayNeedInit);
}
else
{
- mTargets.erase(sibling);
+ mState.targets.erase(sibling);
}
- return error;
+ return gl::NoError();
}
-GLenum Image::getInternalFormat() const
+const gl::Format &Image::getFormat() const
{
- return mInternalFormat;
+ return mState.source->getAttachmentFormat(GL_NONE, mState.imageIndex);
}
size_t Image::getWidth() const
{
- return mWidth;
+ return mState.source->getAttachmentSize(mState.imageIndex).width;
}
size_t Image::getHeight() const
{
- return mHeight;
+ return mState.source->getAttachmentSize(mState.imageIndex).height;
}
size_t Image::getSamples() const
{
- return mSamples;
+ return mState.source->getAttachmentSamples(mState.imageIndex);
}
-rx::ImageImpl *Image::getImplementation()
+rx::ImageImpl *Image::getImplementation() const
{
return mImplementation;
}
-const rx::ImageImpl *Image::getImplementation() const
+Error Image::initialize()
{
- return mImplementation;
+ return mImplementation->initialize();
+}
+
+bool Image::orphaned() const
+{
+ return (mState.source.get() == nullptr);
+}
+
+gl::InitState Image::sourceInitState() const
+{
+ if (orphaned())
+ {
+ return mOrphanedAndNeedsInit ? gl::InitState::MayNeedInit : gl::InitState::Initialized;
+ }
+
+ return mState.source->initState(mState.imageIndex);
}
+
+void Image::setInitState(gl::InitState initState)
+{
+ if (orphaned())
+ {
+ mOrphanedAndNeedsInit = false;
+ }
+
+ return mState.source->setInitState(mState.imageIndex, initState);
}
+
+} // namespace egl
diff --git a/src/3rdparty/angle/src/libANGLE/Image.h b/src/3rdparty/angle/src/libANGLE/Image.h
index 26c9df914c..d2f1b875c6 100644
--- a/src/3rdparty/angle/src/libANGLE/Image.h
+++ b/src/3rdparty/angle/src/libANGLE/Image.h
@@ -12,12 +12,15 @@
#include "common/angleutils.h"
#include "libANGLE/AttributeMap.h"
#include "libANGLE/Error.h"
+#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/RefCountObject.h"
+#include "libANGLE/formatutils.h"
#include <set>
namespace rx
{
+class EGLImplFactory;
class ImageImpl;
}
@@ -25,18 +28,25 @@ namespace egl
{
class Image;
-class ImageSibling : public RefCountObject
+// Only currently Renderbuffers and Textures can be bound with images. This makes the relationship
+// explicit, and also ensures that an image sibling can determine if it's been initialized or not,
+// which is important for the robust resource init extension with Textures and EGLImages.
+class ImageSibling : public gl::RefCountObject, public gl::FramebufferAttachmentObject
{
public:
ImageSibling(GLuint id);
- virtual ~ImageSibling();
+ ~ImageSibling() override;
+
+ bool isEGLImageTarget() const;
+ gl::InitState sourceEGLImageInitState() const;
+ void setSourceEGLImageInitState(gl::InitState initState) const;
protected:
// Set the image target of this sibling
- void setTargetImage(egl::Image *imageTarget);
+ void setTargetImage(const gl::Context *context, egl::Image *imageTarget);
// Orphan all EGL image sources and targets
- gl::Error orphanImages();
+ gl::Error orphanImages(const gl::Context *context);
private:
friend class Image;
@@ -48,22 +58,42 @@ class ImageSibling : public RefCountObject
void removeImageSource(egl::Image *imageSource);
std::set<Image *> mSourcesOf;
- BindingPointer<Image> mTargetOf;
+ gl::BindingPointer<Image> mTargetOf;
+};
+
+struct ImageState : private angle::NonCopyable
+{
+ ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs);
+ ~ImageState();
+
+ gl::ImageIndex imageIndex;
+ gl::BindingPointer<ImageSibling> source;
+ std::set<ImageSibling *> targets;
};
-class Image final : public RefCountObject
+class Image final : public gl::RefCountObject
{
public:
- Image(rx::ImageImpl *impl, EGLenum target, ImageSibling *buffer, const AttributeMap &attribs);
- ~Image();
+ Image(rx::EGLImplFactory *factory,
+ EGLenum target,
+ ImageSibling *buffer,
+ const AttributeMap &attribs);
+
+ gl::Error onDestroy(const gl::Context *context) override;
+ ~Image() override;
- GLenum getInternalFormat() const;
+ const gl::Format &getFormat() const;
size_t getWidth() const;
size_t getHeight() const;
size_t getSamples() const;
- rx::ImageImpl *getImplementation();
- const rx::ImageImpl *getImplementation() const;
+ Error initialize();
+
+ rx::ImageImpl *getImplementation() const;
+
+ bool orphaned() const;
+ gl::InitState sourceInitState() const;
+ void setInitState(gl::InitState initState);
private:
friend class ImageSibling;
@@ -74,18 +104,12 @@ class Image final : public RefCountObject
// Called from ImageSibling only to notify the image that a sibling (source or target) has
// been respecified and state tracking should be updated.
- gl::Error orphanSibling(ImageSibling *sibling);
+ gl::Error orphanSibling(const gl::Context *context, ImageSibling *sibling);
+ ImageState mState;
rx::ImageImpl *mImplementation;
-
- GLenum mInternalFormat;
- size_t mWidth;
- size_t mHeight;
- size_t mSamples;
-
- BindingPointer<ImageSibling> mSource;
- std::set<ImageSibling *> mTargets;
+ bool mOrphanedAndNeedsInit;
};
-}
+} // namespace egl
#endif // LIBANGLE_IMAGE_H_
diff --git a/src/3rdparty/angle/src/libANGLE/ImageIndex.cpp b/src/3rdparty/angle/src/libANGLE/ImageIndex.cpp
index c84e7c5d65..6f99f8ab54 100644
--- a/src/3rdparty/angle/src/libANGLE/ImageIndex.cpp
+++ b/src/3rdparty/angle/src/libANGLE/ImageIndex.cpp
@@ -1,3 +1,4 @@
+#include "ImageIndex.h"
//
// Copyright 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
@@ -16,7 +17,8 @@ namespace gl
ImageIndex::ImageIndex(const ImageIndex &other)
: type(other.type),
mipIndex(other.mipIndex),
- layerIndex(other.layerIndex)
+ layerIndex(other.layerIndex),
+ numLayers(other.numLayers)
{}
ImageIndex &ImageIndex::operator=(const ImageIndex &other)
@@ -24,29 +26,45 @@ ImageIndex &ImageIndex::operator=(const ImageIndex &other)
type = other.type;
mipIndex = other.mipIndex;
layerIndex = other.layerIndex;
+ numLayers = other.numLayers;
return *this;
}
+bool ImageIndex::is3D() const
+{
+ return type == GL_TEXTURE_3D || type == GL_TEXTURE_2D_ARRAY;
+}
+
ImageIndex ImageIndex::Make2D(GLint mipIndex)
{
- return ImageIndex(GL_TEXTURE_2D, mipIndex, ENTIRE_LEVEL);
+ return ImageIndex(GL_TEXTURE_2D, mipIndex, ENTIRE_LEVEL, 1);
+}
+
+ImageIndex ImageIndex::MakeRectangle(GLint mipIndex)
+{
+ return ImageIndex(GL_TEXTURE_RECTANGLE_ANGLE, mipIndex, ENTIRE_LEVEL, 1);
}
ImageIndex ImageIndex::MakeCube(GLenum target, GLint mipIndex)
{
ASSERT(gl::IsCubeMapTextureTarget(target));
return ImageIndex(target, mipIndex,
- static_cast<GLint>(CubeMapTextureTargetToLayerIndex(target)));
+ static_cast<GLint>(CubeMapTextureTargetToLayerIndex(target)), 1);
}
ImageIndex ImageIndex::Make2DArray(GLint mipIndex, GLint layerIndex)
{
- return ImageIndex(GL_TEXTURE_2D_ARRAY, mipIndex, layerIndex);
+ return ImageIndex(GL_TEXTURE_2D_ARRAY, mipIndex, layerIndex, 1);
+}
+
+ImageIndex ImageIndex::Make2DArrayRange(GLint mipIndex, GLint layerIndex, GLint numLayers)
+{
+ return ImageIndex(GL_TEXTURE_2D_ARRAY, mipIndex, layerIndex, numLayers);
}
ImageIndex ImageIndex::Make3D(GLint mipIndex, GLint layerIndex)
{
- return ImageIndex(GL_TEXTURE_3D, mipIndex, layerIndex);
+ return ImageIndex(GL_TEXTURE_3D, mipIndex, layerIndex, 1);
}
ImageIndex ImageIndex::MakeGeneric(GLenum target, GLint mipIndex)
@@ -54,12 +72,17 @@ ImageIndex ImageIndex::MakeGeneric(GLenum target, GLint mipIndex)
GLint layerIndex = IsCubeMapTextureTarget(target)
? static_cast<GLint>(CubeMapTextureTargetToLayerIndex(target))
: ENTIRE_LEVEL;
- return ImageIndex(target, mipIndex, layerIndex);
+ return ImageIndex(target, mipIndex, layerIndex, 1);
+}
+
+ImageIndex ImageIndex::Make2DMultisample()
+{
+ return ImageIndex(GL_TEXTURE_2D_MULTISAMPLE, 0, ENTIRE_LEVEL, 1);
}
ImageIndex ImageIndex::MakeInvalid()
{
- return ImageIndex(GL_NONE, -1, -1);
+ return ImageIndex(GL_NONE, -1, -1, -1);
}
bool ImageIndex::operator<(const ImageIndex &other) const
@@ -72,33 +95,58 @@ bool ImageIndex::operator<(const ImageIndex &other) const
{
return mipIndex < other.mipIndex;
}
- else
+ else if (layerIndex != other.layerIndex)
{
return layerIndex < other.layerIndex;
}
+ else
+ {
+ return numLayers < other.numLayers;
+ }
+}
+
+bool ImageIndex::operator==(const ImageIndex &other) const
+{
+ return (type == other.type) && (mipIndex == other.mipIndex) &&
+ (layerIndex == other.layerIndex) && (numLayers == other.numLayers);
}
-ImageIndex::ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn)
- : type(typeIn),
- mipIndex(mipIndexIn),
- layerIndex(layerIndexIn)
+bool ImageIndex::operator!=(const ImageIndex &other) const
+{
+ return !(*this == other);
+}
+
+ImageIndex::ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn, GLint numLayersIn)
+ : type(typeIn), mipIndex(mipIndexIn), layerIndex(layerIndexIn), numLayers(numLayersIn)
{}
+ImageIndexIterator::ImageIndexIterator(const ImageIndexIterator &other) = default;
+
ImageIndexIterator ImageIndexIterator::Make2D(GLint minMip, GLint maxMip)
{
return ImageIndexIterator(GL_TEXTURE_2D, Range<GLint>(minMip, maxMip),
- Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL), NULL);
+ Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL),
+ nullptr);
+}
+
+ImageIndexIterator ImageIndexIterator::MakeRectangle(GLint minMip, GLint maxMip)
+{
+ return ImageIndexIterator(GL_TEXTURE_RECTANGLE_ANGLE, Range<GLint>(minMip, maxMip),
+ Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL),
+ nullptr);
}
ImageIndexIterator ImageIndexIterator::MakeCube(GLint minMip, GLint maxMip)
{
- return ImageIndexIterator(GL_TEXTURE_CUBE_MAP, Range<GLint>(minMip, maxMip), Range<GLint>(0, 6), NULL);
+ return ImageIndexIterator(GL_TEXTURE_CUBE_MAP, Range<GLint>(minMip, maxMip), Range<GLint>(0, 6),
+ nullptr);
}
ImageIndexIterator ImageIndexIterator::Make3D(GLint minMip, GLint maxMip,
GLint minLayer, GLint maxLayer)
{
- return ImageIndexIterator(GL_TEXTURE_3D, Range<GLint>(minMip, maxMip), Range<GLint>(minLayer, maxLayer), NULL);
+ return ImageIndexIterator(GL_TEXTURE_3D, Range<GLint>(minMip, maxMip),
+ Range<GLint>(minLayer, maxLayer), nullptr);
}
ImageIndexIterator ImageIndexIterator::Make2DArray(GLint minMip, GLint maxMip,
@@ -108,19 +156,33 @@ ImageIndexIterator ImageIndexIterator::Make2DArray(GLint minMip, GLint maxMip,
Range<GLint>(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS), layerCounts);
}
-ImageIndexIterator::ImageIndexIterator(GLenum type, const Range<GLint> &mipRange,
- const Range<GLint> &layerRange, const GLsizei *layerCounts)
+ImageIndexIterator ImageIndexIterator::Make2DMultisample()
+{
+ return ImageIndexIterator(GL_TEXTURE_2D_MULTISAMPLE, Range<GLint>(0, 0),
+ Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL),
+ nullptr);
+}
+
+ImageIndexIterator::ImageIndexIterator(GLenum type,
+ const Range<GLint> &mipRange,
+ const Range<GLint> &layerRange,
+ const GLsizei *layerCounts)
: mType(type),
mMipRange(mipRange),
mLayerRange(layerRange),
mLayerCounts(layerCounts),
- mCurrentMip(mipRange.start),
- mCurrentLayer(layerRange.start)
+ mCurrentMip(mipRange.low()),
+ mCurrentLayer(layerRange.low())
{}
GLint ImageIndexIterator::maxLayer() const
{
- return (mLayerCounts ? static_cast<GLint>(mLayerCounts[mCurrentMip]) : mLayerRange.end);
+ if (mLayerCounts)
+ {
+ ASSERT(mCurrentMip >= 0);
+ return (mCurrentMip < mMipRange.high()) ? mLayerCounts[mCurrentMip] : 0;
+ }
+ return mLayerRange.high();
}
ImageIndex ImageIndexIterator::next()
@@ -134,20 +196,28 @@ ImageIndex ImageIndexIterator::next()
if (mCurrentLayer != ImageIndex::ENTIRE_LEVEL)
{
- if (mCurrentLayer < maxLayer()-1)
+ if (mCurrentLayer < maxLayer() - 1)
{
mCurrentLayer++;
}
- else if (mCurrentMip < mMipRange.end-1)
+ else if (mCurrentMip < mMipRange.high() - 1)
{
mCurrentMip++;
- mCurrentLayer = mLayerRange.start;
+ mCurrentLayer = mLayerRange.low();
+ }
+ else
+ {
+ done();
}
}
- else if (mCurrentMip < mMipRange.end-1)
+ else if (mCurrentMip < mMipRange.high() - 1)
{
mCurrentMip++;
- mCurrentLayer = mLayerRange.start;
+ mCurrentLayer = mLayerRange.low();
+ }
+ else
+ {
+ done();
}
return value;
@@ -155,7 +225,7 @@ ImageIndex ImageIndexIterator::next()
ImageIndex ImageIndexIterator::current() const
{
- ImageIndex value(mType, mCurrentMip, mCurrentLayer);
+ ImageIndex value(mType, mCurrentMip, mCurrentLayer, 1);
if (mType == GL_TEXTURE_CUBE_MAP)
{
@@ -167,7 +237,13 @@ ImageIndex ImageIndexIterator::current() const
bool ImageIndexIterator::hasNext() const
{
- return (mCurrentMip < mMipRange.end || mCurrentLayer < maxLayer());
+ return (mCurrentMip < mMipRange.high() || mCurrentLayer < maxLayer());
}
+void ImageIndexIterator::done()
+{
+ mCurrentMip = mMipRange.high();
+ mCurrentLayer = maxLayer();
}
+
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/ImageIndex.h b/src/3rdparty/angle/src/libANGLE/ImageIndex.h
index b527c7c8ab..8e1b010325 100644
--- a/src/3rdparty/angle/src/libANGLE/ImageIndex.h
+++ b/src/3rdparty/angle/src/libANGLE/ImageIndex.h
@@ -23,37 +23,48 @@ struct ImageIndex
GLenum type;
GLint mipIndex;
GLint layerIndex;
+ GLint numLayers;
ImageIndex(const ImageIndex &other);
ImageIndex &operator=(const ImageIndex &other);
bool hasLayer() const { return layerIndex != ENTIRE_LEVEL; }
+ bool is3D() const;
static ImageIndex Make2D(GLint mipIndex);
+ static ImageIndex MakeRectangle(GLint mipIndex);
static ImageIndex MakeCube(GLenum target, GLint mipIndex);
static ImageIndex Make2DArray(GLint mipIndex, GLint layerIndex);
+ static ImageIndex Make2DArrayRange(GLint mipIndex, GLint layerIndex, GLint numLayers);
static ImageIndex Make3D(GLint mipIndex, GLint layerIndex = ENTIRE_LEVEL);
static ImageIndex MakeGeneric(GLenum target, GLint mipIndex);
+ static ImageIndex Make2DMultisample();
static ImageIndex MakeInvalid();
static const GLint ENTIRE_LEVEL = static_cast<GLint>(-1);
bool operator<(const ImageIndex &other) const;
+ bool operator==(const ImageIndex &other) const;
+ bool operator!=(const ImageIndex &other) const;
private:
friend class ImageIndexIterator;
- ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn);
+ ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn, GLint numLayersIn);
};
class ImageIndexIterator
{
public:
+ ImageIndexIterator(const ImageIndexIterator &other);
+
static ImageIndexIterator Make2D(GLint minMip, GLint maxMip);
+ static ImageIndexIterator MakeRectangle(GLint minMip, GLint maxMip);
static ImageIndexIterator MakeCube(GLint minMip, GLint maxMip);
static ImageIndexIterator Make3D(GLint minMip, GLint maxMip, GLint minLayer, GLint maxLayer);
static ImageIndexIterator Make2DArray(GLint minMip, GLint maxMip, const GLsizei *layerCounts);
+ static ImageIndexIterator Make2DMultisample();
ImageIndex next();
ImageIndex current() const;
@@ -65,6 +76,7 @@ class ImageIndexIterator
const Range<GLint> &layerRange, const GLsizei *layerCounts);
GLint maxLayer() const;
+ void done();
GLenum mType;
Range<GLint> mMipRange;
diff --git a/src/3rdparty/angle/src/libANGLE/IndexRangeCache.cpp b/src/3rdparty/angle/src/libANGLE/IndexRangeCache.cpp
index 4f165c1b28..71a1392b1b 100644
--- a/src/3rdparty/angle/src/libANGLE/IndexRangeCache.cpp
+++ b/src/3rdparty/angle/src/libANGLE/IndexRangeCache.cpp
@@ -15,6 +15,14 @@
namespace gl
{
+IndexRangeCache::IndexRangeCache()
+{
+}
+
+IndexRangeCache::~IndexRangeCache()
+{
+}
+
void IndexRangeCache::addRange(GLenum type,
size_t offset,
size_t count,
diff --git a/src/3rdparty/angle/src/libANGLE/IndexRangeCache.h b/src/3rdparty/angle/src/libANGLE/IndexRangeCache.h
index 69de421c13..3b183448e6 100644
--- a/src/3rdparty/angle/src/libANGLE/IndexRangeCache.h
+++ b/src/3rdparty/angle/src/libANGLE/IndexRangeCache.h
@@ -23,6 +23,9 @@ namespace gl
class IndexRangeCache
{
public:
+ IndexRangeCache();
+ ~IndexRangeCache();
+
void addRange(GLenum type,
size_t offset,
size_t count,
diff --git a/src/3rdparty/angle/src/libANGLE/LoggingAnnotator.cpp b/src/3rdparty/angle/src/libANGLE/LoggingAnnotator.cpp
new file mode 100644
index 0000000000..799399e453
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/LoggingAnnotator.cpp
@@ -0,0 +1,44 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// LoggingAnnotator.cpp: DebugAnnotator implementing logging
+//
+
+#include "libANGLE/LoggingAnnotator.h"
+
+#include <platform/Platform.h>
+
+namespace angle
+{
+
+bool LoggingAnnotator::getStatus()
+{
+ return false;
+}
+
+void LoggingAnnotator::logMessage(const gl::LogMessage &msg) const
+{
+ auto *plat = ANGLEPlatformCurrent();
+ if (plat != nullptr)
+ {
+ switch (msg.getSeverity())
+ {
+ case gl::LOG_ERR:
+ plat->logError(plat, msg.getMessage().c_str());
+ break;
+ case gl::LOG_WARN:
+ plat->logWarning(plat, msg.getMessage().c_str());
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ else
+ {
+ gl::Trace(msg.getSeverity(), msg.getMessage().c_str());
+ }
+}
+
+} // namespace angle
diff --git a/src/3rdparty/angle/src/libANGLE/LoggingAnnotator.h b/src/3rdparty/angle/src/libANGLE/LoggingAnnotator.h
new file mode 100644
index 0000000000..5bec68e189
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/LoggingAnnotator.h
@@ -0,0 +1,31 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// LoggingAnnotator.h: DebugAnnotator implementing logging
+//
+
+#ifndef LIBANGLE_LOGGINGANNOTATOR_H_
+#define LIBANGLE_LOGGINGANNOTATOR_H_
+
+#include "common/debug.h"
+
+namespace angle
+{
+
+class LoggingAnnotator : public gl::DebugAnnotator
+{
+ public:
+ LoggingAnnotator(){};
+ ~LoggingAnnotator() override{};
+ void beginEvent(const wchar_t *eventName) override {}
+ void endEvent() override {}
+ void setMarker(const wchar_t *markerName) override {}
+ bool getStatus() override;
+ void logMessage(const gl::LogMessage &msg) const override;
+};
+
+} // namespace angle
+
+#endif // LIBANGLE_LOGGINGANNOTATOR_H_
diff --git a/src/3rdparty/angle/src/libANGLE/MemoryProgramCache.cpp b/src/3rdparty/angle/src/libANGLE/MemoryProgramCache.cpp
new file mode 100644
index 0000000000..9eec12e3ea
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/MemoryProgramCache.cpp
@@ -0,0 +1,772 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// MemoryProgramCache: Stores compiled and linked programs in memory so they don't
+// always have to be re-compiled. Can be used in conjunction with the platform
+// layer to warm up the cache from disk.
+
+#include "libANGLE/MemoryProgramCache.h"
+
+#include <GLSLANG/ShaderVars.h>
+#include <anglebase/sha1.h>
+
+#include "common/utilities.h"
+#include "common/version.h"
+#include "libANGLE/BinaryStream.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/histogram_macros.h"
+#include "libANGLE/renderer/ProgramImpl.h"
+#include "platform/Platform.h"
+
+namespace gl
+{
+
+namespace
+{
+enum CacheResult
+{
+ kCacheMiss,
+ kCacheHitMemory,
+ kCacheHitDisk,
+ kCacheResultMax,
+};
+
+constexpr unsigned int kWarningLimit = 3;
+
+void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var)
+{
+ stream->writeInt(var.type);
+ stream->writeInt(var.precision);
+ stream->writeString(var.name);
+ stream->writeString(var.mappedName);
+ stream->writeIntVector(var.arraySizes);
+ stream->writeInt(var.staticUse);
+ stream->writeString(var.structName);
+ ASSERT(var.fields.empty());
+}
+
+void LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var)
+{
+ var->type = stream->readInt<GLenum>();
+ var->precision = stream->readInt<GLenum>();
+ var->name = stream->readString();
+ var->mappedName = stream->readString();
+ stream->readIntVector<unsigned int>(&var->arraySizes);
+ var->staticUse = stream->readBool();
+ var->structName = stream->readString();
+}
+
+void WriteShaderVariableBuffer(BinaryOutputStream *stream, const ShaderVariableBuffer &var)
+{
+ stream->writeInt(var.binding);
+ stream->writeInt(var.dataSize);
+
+ stream->writeInt(var.vertexStaticUse);
+ stream->writeInt(var.fragmentStaticUse);
+ stream->writeInt(var.computeStaticUse);
+
+ stream->writeInt(var.memberIndexes.size());
+ for (unsigned int memberCounterIndex : var.memberIndexes)
+ {
+ stream->writeInt(memberCounterIndex);
+ }
+}
+
+void LoadShaderVariableBuffer(BinaryInputStream *stream, ShaderVariableBuffer *var)
+{
+ var->binding = stream->readInt<int>();
+ var->dataSize = stream->readInt<unsigned int>();
+ var->vertexStaticUse = stream->readBool();
+ var->fragmentStaticUse = stream->readBool();
+ var->computeStaticUse = stream->readBool();
+
+ unsigned int numMembers = stream->readInt<unsigned int>();
+ for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
+ {
+ var->memberIndexes.push_back(stream->readInt<unsigned int>());
+ }
+}
+
+void WriteBufferVariable(BinaryOutputStream *stream, const BufferVariable &var)
+{
+ WriteShaderVar(stream, var);
+
+ stream->writeInt(var.bufferIndex);
+ stream->writeInt(var.blockInfo.offset);
+ stream->writeInt(var.blockInfo.arrayStride);
+ stream->writeInt(var.blockInfo.matrixStride);
+ stream->writeInt(var.blockInfo.isRowMajorMatrix);
+ stream->writeInt(var.blockInfo.topLevelArrayStride);
+ stream->writeInt(var.topLevelArraySize);
+ stream->writeInt(var.vertexStaticUse);
+ stream->writeInt(var.fragmentStaticUse);
+ stream->writeInt(var.computeStaticUse);
+}
+
+void LoadBufferVariable(BinaryInputStream *stream, BufferVariable *var)
+{
+ LoadShaderVar(stream, var);
+
+ var->bufferIndex = stream->readInt<int>();
+ var->blockInfo.offset = stream->readInt<int>();
+ var->blockInfo.arrayStride = stream->readInt<int>();
+ var->blockInfo.matrixStride = stream->readInt<int>();
+ var->blockInfo.isRowMajorMatrix = stream->readBool();
+ var->blockInfo.topLevelArrayStride = stream->readInt<int>();
+ var->topLevelArraySize = stream->readInt<int>();
+ var->vertexStaticUse = stream->readBool();
+ var->fragmentStaticUse = stream->readBool();
+ var->computeStaticUse = stream->readBool();
+}
+
+void WriteInterfaceBlock(BinaryOutputStream *stream, const InterfaceBlock &block)
+{
+ stream->writeString(block.name);
+ stream->writeString(block.mappedName);
+ stream->writeInt(block.isArray);
+ stream->writeInt(block.arrayElement);
+
+ WriteShaderVariableBuffer(stream, block);
+}
+
+void LoadInterfaceBlock(BinaryInputStream *stream, InterfaceBlock *block)
+{
+ block->name = stream->readString();
+ block->mappedName = stream->readString();
+ block->isArray = stream->readBool();
+ block->arrayElement = stream->readInt<unsigned int>();
+
+ LoadShaderVariableBuffer(stream, block);
+}
+
+class HashStream final : angle::NonCopyable
+{
+ public:
+ std::string str() { return mStringStream.str(); }
+
+ template <typename T>
+ HashStream &operator<<(T value)
+ {
+ mStringStream << value << kSeparator;
+ return *this;
+ }
+
+ private:
+ static constexpr char kSeparator = ':';
+ std::ostringstream mStringStream;
+};
+
+HashStream &operator<<(HashStream &stream, const Shader *shader)
+{
+ if (shader)
+ {
+ stream << shader->getSourceString().c_str() << shader->getSourceString().length()
+ << shader->getCompilerResourcesString().c_str();
+ }
+ return stream;
+}
+
+HashStream &operator<<(HashStream &stream, const Program::Bindings &bindings)
+{
+ for (const auto &binding : bindings)
+ {
+ stream << binding.first << binding.second;
+ }
+ return stream;
+}
+
+HashStream &operator<<(HashStream &stream, const std::vector<std::string> &strings)
+{
+ for (const auto &str : strings)
+ {
+ stream << str;
+ }
+ return stream;
+}
+
+} // anonymous namespace
+
+MemoryProgramCache::MemoryProgramCache(size_t maxCacheSizeBytes)
+ : mProgramBinaryCache(maxCacheSizeBytes), mIssuedWarnings(0)
+{
+}
+
+MemoryProgramCache::~MemoryProgramCache()
+{
+}
+
+// static
+LinkResult MemoryProgramCache::Deserialize(const Context *context,
+ const Program *program,
+ ProgramState *state,
+ const uint8_t *binary,
+ size_t length,
+ InfoLog &infoLog)
+{
+ BinaryInputStream stream(binary, length);
+
+ unsigned char commitString[ANGLE_COMMIT_HASH_SIZE];
+ stream.readBytes(commitString, ANGLE_COMMIT_HASH_SIZE);
+ if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) !=
+ 0)
+ {
+ infoLog << "Invalid program binary version.";
+ return false;
+ }
+
+ int majorVersion = stream.readInt<int>();
+ int minorVersion = stream.readInt<int>();
+ if (majorVersion != context->getClientMajorVersion() ||
+ minorVersion != context->getClientMinorVersion())
+ {
+ infoLog << "Cannot load program binaries across different ES context versions.";
+ return false;
+ }
+
+ state->mComputeShaderLocalSize[0] = stream.readInt<int>();
+ state->mComputeShaderLocalSize[1] = stream.readInt<int>();
+ state->mComputeShaderLocalSize[2] = stream.readInt<int>();
+
+ state->mNumViews = stream.readInt<int>();
+
+ static_assert(MAX_VERTEX_ATTRIBS <= sizeof(unsigned long) * 8,
+ "Too many vertex attribs for mask");
+ state->mActiveAttribLocationsMask = stream.readInt<unsigned long>();
+
+ unsigned int attribCount = stream.readInt<unsigned int>();
+ ASSERT(state->mAttributes.empty());
+ for (unsigned int attribIndex = 0; attribIndex < attribCount; ++attribIndex)
+ {
+ sh::Attribute attrib;
+ LoadShaderVar(&stream, &attrib);
+ attrib.location = stream.readInt<int>();
+ state->mAttributes.push_back(attrib);
+ }
+
+ unsigned int uniformCount = stream.readInt<unsigned int>();
+ ASSERT(state->mUniforms.empty());
+ for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; ++uniformIndex)
+ {
+ LinkedUniform uniform;
+ LoadShaderVar(&stream, &uniform);
+
+ uniform.bufferIndex = stream.readInt<int>();
+ uniform.blockInfo.offset = stream.readInt<int>();
+ uniform.blockInfo.arrayStride = stream.readInt<int>();
+ uniform.blockInfo.matrixStride = stream.readInt<int>();
+ uniform.blockInfo.isRowMajorMatrix = stream.readBool();
+
+ uniform.typeInfo = &GetUniformTypeInfo(uniform.type);
+
+ state->mUniforms.push_back(uniform);
+ }
+
+ const unsigned int uniformIndexCount = stream.readInt<unsigned int>();
+ ASSERT(state->mUniformLocations.empty());
+ for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount;
+ uniformIndexIndex++)
+ {
+ VariableLocation variable;
+ stream.readInt(&variable.arrayIndex);
+ stream.readInt(&variable.index);
+ stream.readBool(&variable.ignored);
+
+ state->mUniformLocations.push_back(variable);
+ }
+
+ unsigned int uniformBlockCount = stream.readInt<unsigned int>();
+ ASSERT(state->mUniformBlocks.empty());
+ for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount;
+ ++uniformBlockIndex)
+ {
+ InterfaceBlock uniformBlock;
+ LoadInterfaceBlock(&stream, &uniformBlock);
+ state->mUniformBlocks.push_back(uniformBlock);
+
+ state->mActiveUniformBlockBindings.set(uniformBlockIndex, uniformBlock.binding != 0);
+ }
+
+ unsigned int bufferVariableCount = stream.readInt<unsigned int>();
+ ASSERT(state->mBufferVariables.empty());
+ for (unsigned int index = 0; index < bufferVariableCount; ++index)
+ {
+ BufferVariable bufferVariable;
+ LoadBufferVariable(&stream, &bufferVariable);
+ state->mBufferVariables.push_back(bufferVariable);
+ }
+
+ unsigned int shaderStorageBlockCount = stream.readInt<unsigned int>();
+ ASSERT(state->mShaderStorageBlocks.empty());
+ for (unsigned int shaderStorageBlockIndex = 0;
+ shaderStorageBlockIndex < shaderStorageBlockCount; ++shaderStorageBlockIndex)
+ {
+ InterfaceBlock shaderStorageBlock;
+ LoadInterfaceBlock(&stream, &shaderStorageBlock);
+ state->mShaderStorageBlocks.push_back(shaderStorageBlock);
+ }
+
+ unsigned int atomicCounterBufferCount = stream.readInt<unsigned int>();
+ ASSERT(state->mAtomicCounterBuffers.empty());
+ for (unsigned int bufferIndex = 0; bufferIndex < atomicCounterBufferCount; ++bufferIndex)
+ {
+ AtomicCounterBuffer atomicCounterBuffer;
+ LoadShaderVariableBuffer(&stream, &atomicCounterBuffer);
+
+ state->mAtomicCounterBuffers.push_back(atomicCounterBuffer);
+ }
+
+ unsigned int transformFeedbackVaryingCount = stream.readInt<unsigned int>();
+
+ // Reject programs that use transform feedback varyings if the hardware cannot support them.
+ if (transformFeedbackVaryingCount > 0 &&
+ context->getWorkarounds().disableProgramCachingForTransformFeedback)
+ {
+ infoLog << "Current driver does not support transform feedback in binary programs.";
+ return false;
+ }
+
+ ASSERT(state->mLinkedTransformFeedbackVaryings.empty());
+ for (unsigned int transformFeedbackVaryingIndex = 0;
+ transformFeedbackVaryingIndex < transformFeedbackVaryingCount;
+ ++transformFeedbackVaryingIndex)
+ {
+ sh::Varying varying;
+ stream.readIntVector<unsigned int>(&varying.arraySizes);
+ stream.readInt(&varying.type);
+ stream.readString(&varying.name);
+
+ GLuint arrayIndex = stream.readInt<GLuint>();
+
+ state->mLinkedTransformFeedbackVaryings.emplace_back(varying, arrayIndex);
+ }
+
+ stream.readInt(&state->mTransformFeedbackBufferMode);
+
+ unsigned int outputCount = stream.readInt<unsigned int>();
+ ASSERT(state->mOutputVariables.empty());
+ for (unsigned int outputIndex = 0; outputIndex < outputCount; ++outputIndex)
+ {
+ sh::OutputVariable output;
+ LoadShaderVar(&stream, &output);
+ output.location = stream.readInt<int>();
+ state->mOutputVariables.push_back(output);
+ }
+
+ unsigned int outputVarCount = stream.readInt<unsigned int>();
+ ASSERT(state->mOutputLocations.empty());
+ for (unsigned int outputIndex = 0; outputIndex < outputVarCount; ++outputIndex)
+ {
+ VariableLocation locationData;
+ stream.readInt(&locationData.arrayIndex);
+ stream.readInt(&locationData.index);
+ stream.readBool(&locationData.ignored);
+ state->mOutputLocations.push_back(locationData);
+ }
+
+ unsigned int outputTypeCount = stream.readInt<unsigned int>();
+ for (unsigned int outputIndex = 0; outputIndex < outputTypeCount; ++outputIndex)
+ {
+ state->mOutputVariableTypes.push_back(stream.readInt<GLenum>());
+ }
+ static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS < 8 * sizeof(uint32_t),
+ "All bits of DrawBufferMask can be contained in an uint32_t");
+ state->mActiveOutputVariables = stream.readInt<uint32_t>();
+
+ unsigned int samplerRangeLow = stream.readInt<unsigned int>();
+ unsigned int samplerRangeHigh = stream.readInt<unsigned int>();
+ state->mSamplerUniformRange = RangeUI(samplerRangeLow, samplerRangeHigh);
+ unsigned int samplerCount = stream.readInt<unsigned int>();
+ for (unsigned int samplerIndex = 0; samplerIndex < samplerCount; ++samplerIndex)
+ {
+ GLenum textureType = stream.readInt<GLenum>();
+ size_t bindingCount = stream.readInt<size_t>();
+ bool unreferenced = stream.readBool();
+ state->mSamplerBindings.emplace_back(
+ SamplerBinding(textureType, bindingCount, unreferenced));
+ }
+
+ unsigned int imageRangeLow = stream.readInt<unsigned int>();
+ unsigned int imageRangeHigh = stream.readInt<unsigned int>();
+ state->mImageUniformRange = RangeUI(imageRangeLow, imageRangeHigh);
+ unsigned int imageBindingCount = stream.readInt<unsigned int>();
+ for (unsigned int imageIndex = 0; imageIndex < imageBindingCount; ++imageIndex)
+ {
+ unsigned int elementCount = stream.readInt<unsigned int>();
+ ImageBinding imageBinding(elementCount);
+ for (unsigned int i = 0; i < elementCount; ++i)
+ {
+ imageBinding.boundImageUnits[i] = stream.readInt<unsigned int>();
+ }
+ state->mImageBindings.emplace_back(imageBinding);
+ }
+
+ unsigned int atomicCounterRangeLow = stream.readInt<unsigned int>();
+ unsigned int atomicCounterRangeHigh = stream.readInt<unsigned int>();
+ state->mAtomicCounterUniformRange = RangeUI(atomicCounterRangeLow, atomicCounterRangeHigh);
+
+ static_assert(SHADER_TYPE_MAX <= sizeof(unsigned long) * 8, "Too many shader types");
+ state->mLinkedShaderStages = stream.readInt<unsigned long>();
+
+ return program->getImplementation()->load(context, infoLog, &stream);
+}
+
+// static
+void MemoryProgramCache::Serialize(const Context *context,
+ const gl::Program *program,
+ angle::MemoryBuffer *binaryOut)
+{
+ BinaryOutputStream stream;
+
+ stream.writeBytes(reinterpret_cast<const unsigned char *>(ANGLE_COMMIT_HASH),
+ ANGLE_COMMIT_HASH_SIZE);
+
+ // nullptr context is supported when computing binary length.
+ if (context)
+ {
+ stream.writeInt(context->getClientVersion().major);
+ stream.writeInt(context->getClientVersion().minor);
+ }
+ else
+ {
+ stream.writeInt(2);
+ stream.writeInt(0);
+ }
+
+ const auto &state = program->getState();
+
+ const auto &computeLocalSize = state.getComputeShaderLocalSize();
+
+ stream.writeInt(computeLocalSize[0]);
+ stream.writeInt(computeLocalSize[1]);
+ stream.writeInt(computeLocalSize[2]);
+
+ stream.writeInt(state.mNumViews);
+
+ stream.writeInt(state.getActiveAttribLocationsMask().to_ulong());
+
+ stream.writeInt(state.getAttributes().size());
+ for (const sh::Attribute &attrib : state.getAttributes())
+ {
+ WriteShaderVar(&stream, attrib);
+ stream.writeInt(attrib.location);
+ }
+
+ stream.writeInt(state.getUniforms().size());
+ for (const LinkedUniform &uniform : state.getUniforms())
+ {
+ WriteShaderVar(&stream, uniform);
+
+ // FIXME: referenced
+
+ stream.writeInt(uniform.bufferIndex);
+ stream.writeInt(uniform.blockInfo.offset);
+ stream.writeInt(uniform.blockInfo.arrayStride);
+ stream.writeInt(uniform.blockInfo.matrixStride);
+ stream.writeInt(uniform.blockInfo.isRowMajorMatrix);
+ }
+
+ stream.writeInt(state.getUniformLocations().size());
+ for (const auto &variable : state.getUniformLocations())
+ {
+ stream.writeInt(variable.arrayIndex);
+ stream.writeIntOrNegOne(variable.index);
+ stream.writeInt(variable.ignored);
+ }
+
+ stream.writeInt(state.getUniformBlocks().size());
+ for (const InterfaceBlock &uniformBlock : state.getUniformBlocks())
+ {
+ WriteInterfaceBlock(&stream, uniformBlock);
+ }
+
+ stream.writeInt(state.getBufferVariables().size());
+ for (const BufferVariable &bufferVariable : state.getBufferVariables())
+ {
+ WriteBufferVariable(&stream, bufferVariable);
+ }
+
+ stream.writeInt(state.getShaderStorageBlocks().size());
+ for (const InterfaceBlock &shaderStorageBlock : state.getShaderStorageBlocks())
+ {
+ WriteInterfaceBlock(&stream, shaderStorageBlock);
+ }
+
+ stream.writeInt(state.mAtomicCounterBuffers.size());
+ for (const auto &atomicCounterBuffer : state.mAtomicCounterBuffers)
+ {
+ WriteShaderVariableBuffer(&stream, atomicCounterBuffer);
+ }
+
+ // Warn the app layer if saving a binary with unsupported transform feedback.
+ if (!state.getLinkedTransformFeedbackVaryings().empty() &&
+ context->getWorkarounds().disableProgramCachingForTransformFeedback)
+ {
+ WARN() << "Saving program binary with transform feedback, which is not supported on this "
+ "driver.";
+ }
+
+ stream.writeInt(state.getLinkedTransformFeedbackVaryings().size());
+ for (const auto &var : state.getLinkedTransformFeedbackVaryings())
+ {
+ stream.writeIntVector(var.arraySizes);
+ stream.writeInt(var.type);
+ stream.writeString(var.name);
+
+ stream.writeIntOrNegOne(var.arrayIndex);
+ }
+
+ stream.writeInt(state.getTransformFeedbackBufferMode());
+
+ stream.writeInt(state.getOutputVariables().size());
+ for (const sh::OutputVariable &output : state.getOutputVariables())
+ {
+ WriteShaderVar(&stream, output);
+ stream.writeInt(output.location);
+ }
+
+ stream.writeInt(state.getOutputLocations().size());
+ for (const auto &outputVar : state.getOutputLocations())
+ {
+ stream.writeInt(outputVar.arrayIndex);
+ stream.writeIntOrNegOne(outputVar.index);
+ stream.writeInt(outputVar.ignored);
+ }
+
+ stream.writeInt(state.mOutputVariableTypes.size());
+ for (const auto &outputVariableType : state.mOutputVariableTypes)
+ {
+ stream.writeInt(outputVariableType);
+ }
+
+ static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS < 8 * sizeof(uint32_t),
+ "All bits of DrawBufferMask can be contained in an uint32_t");
+ stream.writeInt(static_cast<uint32_t>(state.mActiveOutputVariables.to_ulong()));
+
+ stream.writeInt(state.getSamplerUniformRange().low());
+ stream.writeInt(state.getSamplerUniformRange().high());
+
+ stream.writeInt(state.getSamplerBindings().size());
+ for (const auto &samplerBinding : state.getSamplerBindings())
+ {
+ stream.writeInt(samplerBinding.textureType);
+ stream.writeInt(samplerBinding.boundTextureUnits.size());
+ stream.writeInt(samplerBinding.unreferenced);
+ }
+
+ stream.writeInt(state.getImageUniformRange().low());
+ stream.writeInt(state.getImageUniformRange().high());
+
+ stream.writeInt(state.getImageBindings().size());
+ for (const auto &imageBinding : state.getImageBindings())
+ {
+ stream.writeInt(imageBinding.boundImageUnits.size());
+ for (size_t i = 0; i < imageBinding.boundImageUnits.size(); ++i)
+ {
+ stream.writeInt(imageBinding.boundImageUnits[i]);
+ }
+ }
+
+ stream.writeInt(state.getAtomicCounterUniformRange().low());
+ stream.writeInt(state.getAtomicCounterUniformRange().high());
+
+ stream.writeInt(state.getLinkedShaderStages().to_ulong());
+
+ program->getImplementation()->save(context, &stream);
+
+ ASSERT(binaryOut);
+ binaryOut->resize(stream.length());
+ memcpy(binaryOut->data(), stream.data(), stream.length());
+}
+
+// static
+void MemoryProgramCache::ComputeHash(const Context *context,
+ const Program *program,
+ ProgramHash *hashOut)
+{
+ const Shader *vertexShader = program->getAttachedVertexShader();
+ const Shader *fragmentShader = program->getAttachedFragmentShader();
+ const Shader *computeShader = program->getAttachedComputeShader();
+
+ // Compute the program hash. Start with the shader hashes and resource strings.
+ HashStream hashStream;
+ hashStream << vertexShader << fragmentShader << computeShader;
+
+ // Add some ANGLE metadata and Context properties, such as version and back-end.
+ hashStream << ANGLE_COMMIT_HASH << context->getClientMajorVersion()
+ << context->getClientMinorVersion() << context->getString(GL_RENDERER);
+
+ // Hash pre-link program properties.
+ hashStream << program->getAttributeBindings() << program->getUniformLocationBindings()
+ << program->getFragmentInputBindings()
+ << program->getState().getTransformFeedbackVaryingNames()
+ << program->getState().getTransformFeedbackBufferMode();
+
+ // Call the secure SHA hashing function.
+ const std::string &programKey = hashStream.str();
+ angle::base::SHA1HashBytes(reinterpret_cast<const unsigned char *>(programKey.c_str()),
+ programKey.length(), hashOut->data());
+}
+
+LinkResult MemoryProgramCache::getProgram(const Context *context,
+ const Program *program,
+ ProgramState *state,
+ ProgramHash *hashOut)
+{
+ ComputeHash(context, program, hashOut);
+ const angle::MemoryBuffer *binaryProgram = nullptr;
+ LinkResult result(false);
+ if (get(*hashOut, &binaryProgram))
+ {
+ InfoLog infoLog;
+ ANGLE_TRY_RESULT(Deserialize(context, program, state, binaryProgram->data(),
+ binaryProgram->size(), infoLog),
+ result);
+ ANGLE_HISTOGRAM_BOOLEAN("GPU.ANGLE.ProgramCache.LoadBinarySuccess", result.getResult());
+ if (!result.getResult())
+ {
+ // Cache load failed, evict.
+ if (mIssuedWarnings++ < kWarningLimit)
+ {
+ WARN() << "Failed to load binary from cache: " << infoLog.str();
+
+ if (mIssuedWarnings == kWarningLimit)
+ {
+ WARN() << "Reaching warning limit for cache load failures, silencing "
+ "subsequent warnings.";
+ }
+ }
+ remove(*hashOut);
+ }
+ }
+ return result;
+}
+
+bool MemoryProgramCache::get(const ProgramHash &programHash, const angle::MemoryBuffer **programOut)
+{
+ const CacheEntry *entry = nullptr;
+ if (!mProgramBinaryCache.get(programHash, &entry))
+ {
+ ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.ProgramCache.CacheResult", kCacheMiss,
+ kCacheResultMax);
+ return false;
+ }
+
+ if (entry->second == CacheSource::PutProgram)
+ {
+ ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.ProgramCache.CacheResult", kCacheHitMemory,
+ kCacheResultMax);
+ }
+ else
+ {
+ ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.ProgramCache.CacheResult", kCacheHitDisk,
+ kCacheResultMax);
+ }
+
+ *programOut = &entry->first;
+ return true;
+}
+
+bool MemoryProgramCache::getAt(size_t index,
+ ProgramHash *hashOut,
+ const angle::MemoryBuffer **programOut)
+{
+ const CacheEntry *entry = nullptr;
+ if (!mProgramBinaryCache.getAt(index, hashOut, &entry))
+ {
+ return false;
+ }
+
+ *programOut = &entry->first;
+ return true;
+}
+
+void MemoryProgramCache::remove(const ProgramHash &programHash)
+{
+ bool result = mProgramBinaryCache.eraseByKey(programHash);
+ ASSERT(result);
+}
+
+void MemoryProgramCache::putProgram(const ProgramHash &programHash,
+ const Context *context,
+ const Program *program)
+{
+ CacheEntry newEntry;
+ Serialize(context, program, &newEntry.first);
+ newEntry.second = CacheSource::PutProgram;
+
+ ANGLE_HISTOGRAM_COUNTS("GPU.ANGLE.ProgramCache.ProgramBinarySizeBytes",
+ static_cast<int>(newEntry.first.size()));
+
+ const CacheEntry *result =
+ mProgramBinaryCache.put(programHash, std::move(newEntry), newEntry.first.size());
+ if (!result)
+ {
+ ERR() << "Failed to store binary program in memory cache, program is too large.";
+ }
+ else
+ {
+ auto *platform = ANGLEPlatformCurrent();
+ platform->cacheProgram(platform, programHash, result->first.size(), result->first.data());
+ }
+}
+
+void MemoryProgramCache::updateProgram(const Context *context, const Program *program)
+{
+ gl::ProgramHash programHash;
+ ComputeHash(context, program, &programHash);
+ putProgram(programHash, context, program);
+}
+
+void MemoryProgramCache::putBinary(const ProgramHash &programHash,
+ const uint8_t *binary,
+ size_t length)
+{
+ // Copy the binary.
+ CacheEntry newEntry;
+ newEntry.first.resize(length);
+ memcpy(newEntry.first.data(), binary, length);
+ newEntry.second = CacheSource::PutBinary;
+
+ // Store the binary.
+ const CacheEntry *result = mProgramBinaryCache.put(programHash, std::move(newEntry), length);
+ if (!result)
+ {
+ ERR() << "Failed to store binary program in memory cache, program is too large.";
+ }
+}
+
+void MemoryProgramCache::clear()
+{
+ mProgramBinaryCache.clear();
+ mIssuedWarnings = 0;
+}
+
+void MemoryProgramCache::resize(size_t maxCacheSizeBytes)
+{
+ mProgramBinaryCache.resize(maxCacheSizeBytes);
+}
+
+size_t MemoryProgramCache::entryCount() const
+{
+ return mProgramBinaryCache.entryCount();
+}
+
+size_t MemoryProgramCache::trim(size_t limit)
+{
+ return mProgramBinaryCache.shrinkToSize(limit);
+}
+
+size_t MemoryProgramCache::size() const
+{
+ return mProgramBinaryCache.size();
+}
+
+size_t MemoryProgramCache::maxSize() const
+{
+ return mProgramBinaryCache.maxSize();
+}
+
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/MemoryProgramCache.h b/src/3rdparty/angle/src/libANGLE/MemoryProgramCache.h
new file mode 100644
index 0000000000..044bd48ecc
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/MemoryProgramCache.h
@@ -0,0 +1,130 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// MemoryProgramCache: Stores compiled and linked programs in memory so they don't
+// always have to be re-compiled. Can be used in conjunction with the platform
+// layer to warm up the cache from disk.
+
+#ifndef LIBANGLE_MEMORY_PROGRAM_CACHE_H_
+#define LIBANGLE_MEMORY_PROGRAM_CACHE_H_
+
+#include <array>
+
+#include "common/MemoryBuffer.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/SizedMRUCache.h"
+
+namespace gl
+{
+// 160-bit SHA-1 hash key.
+constexpr size_t kProgramHashLength = 20;
+using ProgramHash = std::array<uint8_t, kProgramHashLength>;
+} // namespace gl
+
+namespace std
+{
+template <>
+struct hash<gl::ProgramHash>
+{
+ // Simple routine to hash four ints.
+ size_t operator()(const gl::ProgramHash &programHash) const
+ {
+ unsigned int hash = 0;
+ for (uint32_t num : programHash)
+ {
+ hash *= 37;
+ hash += num;
+ }
+ return hash;
+ }
+};
+} // namespace std
+
+namespace gl
+{
+class Context;
+class InfoLog;
+class Program;
+class ProgramState;
+
+class MemoryProgramCache final : angle::NonCopyable
+{
+ public:
+ MemoryProgramCache(size_t maxCacheSizeBytes);
+ ~MemoryProgramCache();
+
+ // Writes a program's binary to the output memory buffer.
+ static void Serialize(const Context *context,
+ const Program *program,
+ angle::MemoryBuffer *binaryOut);
+
+ // Loads program state according to the specified binary blob.
+ static LinkResult Deserialize(const Context *context,
+ const Program *program,
+ ProgramState *state,
+ const uint8_t *binary,
+ size_t length,
+ InfoLog &infoLog);
+
+ static void ComputeHash(const Context *context, const Program *program, ProgramHash *hashOut);
+
+ // Check if the cache contains a binary matching the specified program.
+ bool get(const ProgramHash &programHash, const angle::MemoryBuffer **programOut);
+
+ // For querying the contents of the cache.
+ bool getAt(size_t index, ProgramHash *hashOut, const angle::MemoryBuffer **programOut);
+
+ // Evict a program from the binary cache.
+ void remove(const ProgramHash &programHash);
+
+ // Helper method that serializes a program.
+ void putProgram(const ProgramHash &programHash, const Context *context, const Program *program);
+
+ // Same as putProgram but computes the hash.
+ void updateProgram(const Context *context, const Program *program);
+
+ // Store a binary directly.
+ void putBinary(const ProgramHash &programHash, const uint8_t *binary, size_t length);
+
+ // Check the cache, and deserialize and load the program if found. Evict existing hash if load
+ // fails.
+ LinkResult getProgram(const Context *context,
+ const Program *program,
+ ProgramState *state,
+ ProgramHash *hashOut);
+
+ // Empty the cache.
+ void clear();
+
+ // Resize the cache. Discards current contents.
+ void resize(size_t maxCacheSizeBytes);
+
+ // Returns the number of entries in the cache.
+ size_t entryCount() const;
+
+ // Reduces the current cache size and returns the number of bytes freed.
+ size_t trim(size_t limit);
+
+ // Returns the current cache size in bytes.
+ size_t size() const;
+
+ // Returns the maximum cache size in bytes.
+ size_t maxSize() const;
+
+ private:
+ enum class CacheSource
+ {
+ PutProgram,
+ PutBinary,
+ };
+
+ using CacheEntry = std::pair<angle::MemoryBuffer, CacheSource>;
+ angle::SizedMRUCache<ProgramHash, CacheEntry> mProgramBinaryCache;
+ unsigned int mIssuedWarnings;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_MEMORY_PROGRAM_CACHE_H_
diff --git a/src/3rdparty/angle/src/libANGLE/PackedGLEnums.h b/src/3rdparty/angle/src/libANGLE/PackedGLEnums.h
new file mode 100644
index 0000000000..70e32910fc
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/PackedGLEnums.h
@@ -0,0 +1,111 @@
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// PackedGLEnums_autogen.h:
+// Declares ANGLE-specific enums classes for GLEnum and functions operating
+// on them.
+
+#ifndef LIBANGLE_PACKEDGLENUMS_H_
+#define LIBANGLE_PACKEDGLENUMS_H_
+
+#include "libANGLE/PackedGLEnums_autogen.h"
+
+#include <array>
+#include <cstddef>
+
+namespace angle
+{
+
+template <typename E>
+class EnumIterator final
+{
+ private:
+ using UnderlyingType = typename std::underlying_type<E>::type;
+
+ public:
+ EnumIterator(E value) : mValue(static_cast<UnderlyingType>(value)) {}
+ EnumIterator &operator++()
+ {
+ mValue++;
+ return *this;
+ }
+ bool operator==(const EnumIterator &other) const { return mValue == other.mValue; }
+ bool operator!=(const EnumIterator &other) const { return mValue != other.mValue; }
+ E operator*() const { return static_cast<E>(mValue); }
+
+ private:
+ UnderlyingType mValue;
+};
+
+template <typename E>
+struct AllEnums
+{
+ EnumIterator<E> begin() const { return {static_cast<E>(0)}; }
+ EnumIterator<E> end() const { return {E::InvalidEnum}; }
+};
+
+template <typename E, typename T>
+class PackedEnumMap
+{
+ private:
+ using UnderlyingType = typename std::underlying_type<E>::type;
+ static constexpr size_t kSize = static_cast<UnderlyingType>(E::EnumCount);
+ using Storage = std::array<T, kSize>;
+
+ Storage mData;
+
+ public:
+ // types:
+ using value_type = T;
+ using pointer = T *;
+ using const_pointer = const T *;
+ using reference = T &;
+ using const_reference = const T &;
+
+ using size_type = size_t;
+ using difference_type = ptrdiff_t;
+
+ using iterator = typename Storage::iterator;
+ using const_iterator = typename Storage::const_iterator;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+ // No explicit construct/copy/destroy for aggregate type
+ void fill(const T &u) { mData.fill(u); }
+ void swap(PackedEnumMap<E, T> &a) noexcept { mData.swap(a.mData); }
+
+ // iterators:
+ iterator begin() noexcept { return mData.begin(); }
+ const_iterator begin() const noexcept { return mData.begin(); }
+ iterator end() noexcept { return mData.end(); }
+ const_iterator end() const noexcept { return mData.end(); }
+
+ reverse_iterator rbegin() noexcept { return mData.rbegin(); }
+ const_reverse_iterator rbegin() const noexcept { return mData.rbegin(); }
+ reverse_iterator rend() noexcept { return mData.rend(); }
+ const_reverse_iterator rend() const noexcept { return mData.rend(); }
+
+ // capacity:
+ constexpr size_type size() const noexcept { return mData.size(); }
+ constexpr size_type max_size() const noexcept { return mData.max_size(); }
+ constexpr bool empty() const noexcept { return mData.empty(); }
+
+ // element access:
+ reference operator[](E n) { return mData[static_cast<UnderlyingType>(n)]; }
+ const_reference operator[](E n) const { return mData[static_cast<UnderlyingType>(n)]; }
+ const_reference at(E n) const { return mData.at(static_cast<UnderlyingType>(n)); }
+ reference at(E n) { return mData.at(static_cast<UnderlyingType>(n)); }
+
+ reference front() { return mData.front(); }
+ const_reference front() const { return mData.front(); }
+ reference back() { return mData.back(); }
+ const_reference back() const { return mData.back(); }
+
+ T *data() noexcept { return mData.data(); }
+ const T *data() const noexcept { return mData.data(); }
+};
+
+} // namespace angle
+
+#endif // LIBANGLE_PACKEDGLENUMS_H_
diff --git a/src/3rdparty/angle/src/libANGLE/PackedGLEnums_autogen.cpp b/src/3rdparty/angle/src/libANGLE/PackedGLEnums_autogen.cpp
new file mode 100644
index 0000000000..4959a8ff14
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/PackedGLEnums_autogen.cpp
@@ -0,0 +1,174 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_packed_gl_enums.py using data from packed_gl_enums.json.
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// PackedGLEnums_autogen.cpp:
+// Implements ANGLE-specific enums classes for GLEnum and functions operating
+// on them.
+
+#include "libANGLE/PackedGLEnums_autogen.h"
+#include "common/debug.h"
+
+namespace gl
+{
+
+template <>
+BufferBinding FromGLenum<BufferBinding>(GLenum from)
+{
+ switch (from)
+ {
+ case GL_ARRAY_BUFFER:
+ return BufferBinding::Array;
+ case GL_ATOMIC_COUNTER_BUFFER:
+ return BufferBinding::AtomicCounter;
+ case GL_COPY_READ_BUFFER:
+ return BufferBinding::CopyRead;
+ case GL_COPY_WRITE_BUFFER:
+ return BufferBinding::CopyWrite;
+ case GL_DISPATCH_INDIRECT_BUFFER:
+ return BufferBinding::DispatchIndirect;
+ case GL_DRAW_INDIRECT_BUFFER:
+ return BufferBinding::DrawIndirect;
+ case GL_ELEMENT_ARRAY_BUFFER:
+ return BufferBinding::ElementArray;
+ case GL_PIXEL_PACK_BUFFER:
+ return BufferBinding::PixelPack;
+ case GL_PIXEL_UNPACK_BUFFER:
+ return BufferBinding::PixelUnpack;
+ case GL_SHADER_STORAGE_BUFFER:
+ return BufferBinding::ShaderStorage;
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ return BufferBinding::TransformFeedback;
+ case GL_UNIFORM_BUFFER:
+ return BufferBinding::Uniform;
+ default:
+ return BufferBinding::InvalidEnum;
+ }
+}
+
+GLenum ToGLenum(BufferBinding from)
+{
+ switch (from)
+ {
+ case BufferBinding::Array:
+ return GL_ARRAY_BUFFER;
+ case BufferBinding::AtomicCounter:
+ return GL_ATOMIC_COUNTER_BUFFER;
+ case BufferBinding::CopyRead:
+ return GL_COPY_READ_BUFFER;
+ case BufferBinding::CopyWrite:
+ return GL_COPY_WRITE_BUFFER;
+ case BufferBinding::DispatchIndirect:
+ return GL_DISPATCH_INDIRECT_BUFFER;
+ case BufferBinding::DrawIndirect:
+ return GL_DRAW_INDIRECT_BUFFER;
+ case BufferBinding::ElementArray:
+ return GL_ELEMENT_ARRAY_BUFFER;
+ case BufferBinding::PixelPack:
+ return GL_PIXEL_PACK_BUFFER;
+ case BufferBinding::PixelUnpack:
+ return GL_PIXEL_UNPACK_BUFFER;
+ case BufferBinding::ShaderStorage:
+ return GL_SHADER_STORAGE_BUFFER;
+ case BufferBinding::TransformFeedback:
+ return GL_TRANSFORM_FEEDBACK_BUFFER;
+ case BufferBinding::Uniform:
+ return GL_UNIFORM_BUFFER;
+ default:
+ UNREACHABLE();
+ return GL_NONE;
+ }
+}
+
+template <>
+BufferUsage FromGLenum<BufferUsage>(GLenum from)
+{
+ switch (from)
+ {
+ case GL_DYNAMIC_COPY:
+ return BufferUsage::DynamicCopy;
+ case GL_DYNAMIC_DRAW:
+ return BufferUsage::DynamicDraw;
+ case GL_DYNAMIC_READ:
+ return BufferUsage::DynamicRead;
+ case GL_STATIC_COPY:
+ return BufferUsage::StaticCopy;
+ case GL_STATIC_DRAW:
+ return BufferUsage::StaticDraw;
+ case GL_STATIC_READ:
+ return BufferUsage::StaticRead;
+ case GL_STREAM_COPY:
+ return BufferUsage::StreamCopy;
+ case GL_STREAM_DRAW:
+ return BufferUsage::StreamDraw;
+ case GL_STREAM_READ:
+ return BufferUsage::StreamRead;
+ default:
+ return BufferUsage::InvalidEnum;
+ }
+}
+
+GLenum ToGLenum(BufferUsage from)
+{
+ switch (from)
+ {
+ case BufferUsage::DynamicCopy:
+ return GL_DYNAMIC_COPY;
+ case BufferUsage::DynamicDraw:
+ return GL_DYNAMIC_DRAW;
+ case BufferUsage::DynamicRead:
+ return GL_DYNAMIC_READ;
+ case BufferUsage::StaticCopy:
+ return GL_STATIC_COPY;
+ case BufferUsage::StaticDraw:
+ return GL_STATIC_DRAW;
+ case BufferUsage::StaticRead:
+ return GL_STATIC_READ;
+ case BufferUsage::StreamCopy:
+ return GL_STREAM_COPY;
+ case BufferUsage::StreamDraw:
+ return GL_STREAM_DRAW;
+ case BufferUsage::StreamRead:
+ return GL_STREAM_READ;
+ default:
+ UNREACHABLE();
+ return GL_NONE;
+ }
+}
+
+template <>
+CullFaceMode FromGLenum<CullFaceMode>(GLenum from)
+{
+ switch (from)
+ {
+ case GL_BACK:
+ return CullFaceMode::Back;
+ case GL_FRONT:
+ return CullFaceMode::Front;
+ case GL_FRONT_AND_BACK:
+ return CullFaceMode::FrontAndBack;
+ default:
+ return CullFaceMode::InvalidEnum;
+ }
+}
+
+GLenum ToGLenum(CullFaceMode from)
+{
+ switch (from)
+ {
+ case CullFaceMode::Back:
+ return GL_BACK;
+ case CullFaceMode::Front:
+ return GL_FRONT;
+ case CullFaceMode::FrontAndBack:
+ return GL_FRONT_AND_BACK;
+ default:
+ UNREACHABLE();
+ return GL_NONE;
+ }
+}
+
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/PackedGLEnums_autogen.h b/src/3rdparty/angle/src/libANGLE/PackedGLEnums_autogen.h
new file mode 100644
index 0000000000..f3f349ab68
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/PackedGLEnums_autogen.h
@@ -0,0 +1,84 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_packed_gl_enums.py using data from packed_gl_enums.json.
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// PackedGLEnums_autogen.h:
+// Declares ANGLE-specific enums classes for GLEnum and functions operating
+// on them.
+
+#ifndef LIBANGLE_PACKEDGLENUMS_AUTOGEN_H_
+#define LIBANGLE_PACKEDGLENUMS_AUTOGEN_H_
+
+#include <angle_gl.h>
+
+#include <cstdint>
+
+namespace gl
+{
+
+template <typename Enum>
+Enum FromGLenum(GLenum from);
+
+enum class BufferBinding : uint8_t
+{
+ Array = 0,
+ AtomicCounter = 1,
+ CopyRead = 2,
+ CopyWrite = 3,
+ DispatchIndirect = 4,
+ DrawIndirect = 5,
+ ElementArray = 6,
+ PixelPack = 7,
+ PixelUnpack = 8,
+ ShaderStorage = 9,
+ TransformFeedback = 10,
+ Uniform = 11,
+
+ InvalidEnum = 12,
+ EnumCount = 12,
+};
+
+template <>
+BufferBinding FromGLenum<BufferBinding>(GLenum from);
+GLenum ToGLenum(BufferBinding from);
+
+enum class BufferUsage : uint8_t
+{
+ DynamicCopy = 0,
+ DynamicDraw = 1,
+ DynamicRead = 2,
+ StaticCopy = 3,
+ StaticDraw = 4,
+ StaticRead = 5,
+ StreamCopy = 6,
+ StreamDraw = 7,
+ StreamRead = 8,
+
+ InvalidEnum = 9,
+ EnumCount = 9,
+};
+
+template <>
+BufferUsage FromGLenum<BufferUsage>(GLenum from);
+GLenum ToGLenum(BufferUsage from);
+
+enum class CullFaceMode : uint8_t
+{
+ Back = 0,
+ Front = 1,
+ FrontAndBack = 2,
+
+ InvalidEnum = 3,
+ EnumCount = 3,
+};
+
+template <>
+CullFaceMode FromGLenum<CullFaceMode>(GLenum from);
+GLenum ToGLenum(CullFaceMode from);
+
+} // namespace gl
+
+#endif // LIBANGLE_PACKEDGLENUMS_AUTOGEN_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Path.cpp b/src/3rdparty/angle/src/libANGLE/Path.cpp
new file mode 100644
index 0000000000..8f2ce9ef92
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/Path.cpp
@@ -0,0 +1,78 @@
+//
+// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Path.h: Defines the gl::Path class, representing CHROMIUM_path_rendering
+// path object.
+
+#include "libANGLE/Path.h"
+#include "libANGLE/renderer/PathImpl.h"
+
+#include "common/mathutil.h"
+#include "common/debug.h"
+
+namespace gl
+{
+
+Path::Path(rx::PathImpl *impl)
+ : mPath(impl),
+ mHasData(false),
+ mEndCaps(GL_FLAT_CHROMIUM),
+ mJoinStyle(GL_MITER_REVERT_CHROMIUM),
+ mStrokeWidth(1.0f),
+ mStrokeBound(0.2f),
+ mMiterLimit(4.0f)
+{
+}
+
+Path::~Path()
+{
+ delete mPath;
+}
+
+Error Path::setCommands(GLsizei numCommands,
+ const GLubyte *commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const void *coords)
+{
+ ANGLE_TRY(mPath->setCommands(numCommands, commands, numCoords, coordType, coords));
+
+ mHasData = true;
+
+ return NoError();
+}
+
+void Path::setStrokeWidth(GLfloat width)
+{
+ mStrokeWidth = width;
+ mPath->setPathParameter(GL_PATH_STROKE_WIDTH_CHROMIUM, mStrokeWidth);
+}
+
+void Path::setStrokeBound(GLfloat bound)
+{
+ mStrokeBound = clamp(bound, 0.0f, 1.0f);
+ mPath->setPathParameter(GL_PATH_STROKE_BOUND_CHROMIUM, mStrokeBound);
+}
+
+void Path::setEndCaps(GLenum type)
+{
+ mEndCaps = type;
+ mPath->setPathParameter(GL_PATH_END_CAPS_CHROMIUM, static_cast<GLfloat>(type));
+}
+
+void Path::setJoinStyle(GLenum type)
+{
+ mJoinStyle = type;
+ mPath->setPathParameter(GL_PATH_JOIN_STYLE_CHROMIUM, static_cast<GLfloat>(type));
+}
+
+void Path::setMiterLimit(GLfloat value)
+{
+ mMiterLimit = value;
+ mPath->setPathParameter(GL_PATH_MITER_LIMIT_CHROMIUM, value);
+}
+
+} // gl
diff --git a/src/3rdparty/angle/src/libANGLE/Path.h b/src/3rdparty/angle/src/libANGLE/Path.h
new file mode 100644
index 0000000000..b103c84607
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/Path.h
@@ -0,0 +1,71 @@
+//
+// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Path.h: Defines the gl::Path class, representing CHROMIUM_path_rendering
+// path object.
+
+#ifndef LIBANGLE_PATH_H_
+#define LIBANGLE_PATH_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
+
+namespace rx
+{
+class PathImpl;
+}
+
+namespace gl
+{
+class Path final : angle::NonCopyable
+{
+ public:
+ Path(rx::PathImpl *impl);
+
+ ~Path();
+
+ Error setCommands(GLsizei numCommands,
+ const GLubyte *commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const void *coords);
+
+ void setStrokeWidth(GLfloat width);
+ void setStrokeBound(GLfloat bound);
+ void setEndCaps(GLenum type);
+ void setJoinStyle(GLenum type);
+ void setMiterLimit(GLfloat value);
+
+ GLfloat getStrokeWidth() const { return mStrokeWidth; }
+ GLfloat getStrokeBound() const { return mStrokeBound; }
+ GLfloat getMiterLimit() const { return mMiterLimit; }
+ GLenum getEndCaps() const { return mEndCaps; }
+ GLenum getJoinStyle() const { return mJoinStyle; }
+
+ bool hasPathData() const { return mHasData; }
+
+ rx::PathImpl *getImplementation() const { return mPath; }
+
+ private:
+ rx::PathImpl *mPath;
+
+ // a Path object is not actually considered "a path"
+ // untill it has been specified with data. So we'll
+ // keep this flag to support this semantics.
+ bool mHasData;
+
+ GLenum mEndCaps;
+ GLenum mJoinStyle;
+ GLfloat mStrokeWidth;
+ GLfloat mStrokeBound;
+ GLfloat mMiterLimit;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_PATH_H_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/libANGLE/Platform.cpp b/src/3rdparty/angle/src/libANGLE/Platform.cpp
index bfcdb1494e..702091624f 100644
--- a/src/3rdparty/angle/src/libANGLE/Platform.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Platform.cpp
@@ -8,28 +8,62 @@
#include <platform/Platform.h>
+#include <cstring>
+
#include "common/debug.h"
namespace
{
-angle::Platform *currentPlatform = nullptr;
+// TODO(jmadill): Make methods owned by egl::Display.
+angle::PlatformMethods g_platformMethods;
+} // anonymous namespace
+
+angle::PlatformMethods::PlatformMethods()
+{
}
-// static
-angle::Platform *ANGLE_APIENTRY ANGLEPlatformCurrent()
+angle::PlatformMethods *ANGLEPlatformCurrent()
{
- return currentPlatform;
+ return &g_platformMethods;
}
-// static
-void ANGLE_APIENTRY ANGLEPlatformInitialize(angle::Platform *platformImpl)
+bool ANGLE_APIENTRY ANGLEGetDisplayPlatform(angle::EGLDisplayType display,
+ const char *const methodNames[],
+ unsigned int methodNameCount,
+ void *context,
+ void *platformMethods)
{
- ASSERT(platformImpl != nullptr);
- currentPlatform = platformImpl;
+ angle::PlatformMethods **platformMethodsOut =
+ reinterpret_cast<angle::PlatformMethods **>(platformMethods);
+
+ // We allow for a lower input count of impl platform methods if the subset is correct.
+ if (methodNameCount > angle::g_NumPlatformMethods)
+ {
+ ERR() << "Invalid platform method count: " << methodNameCount << ", expected "
+ << angle::g_NumPlatformMethods << ".";
+ return false;
+ }
+
+ for (unsigned int nameIndex = 0; nameIndex < methodNameCount; ++nameIndex)
+ {
+ const char *expectedName = angle::g_PlatformMethodNames[nameIndex];
+ const char *actualName = methodNames[nameIndex];
+ if (strcmp(expectedName, actualName) != 0)
+ {
+ ERR() << "Invalid platform method name: " << actualName << ", expected " << expectedName
+ << ".";
+ return false;
+ }
+ }
+
+ // TODO(jmadill): Store platform methods in display.
+ g_platformMethods.context = context;
+ *platformMethodsOut = &g_platformMethods;
+ return true;
}
-// static
-void ANGLE_APIENTRY ANGLEPlatformShutdown()
+void ANGLE_APIENTRY ANGLEResetDisplayPlatform(angle::EGLDisplayType display)
{
- currentPlatform = nullptr;
+ // TODO(jmadill): Store platform methods in display.
+ g_platformMethods = angle::PlatformMethods();
}
diff --git a/src/3rdparty/angle/src/libANGLE/Program.cpp b/src/3rdparty/angle/src/libANGLE/Program.cpp
index 69497c4436..795d326041 100644
--- a/src/3rdparty/angle/src/libANGLE/Program.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Program.cpp
@@ -11,18 +11,24 @@
#include <algorithm>
-#include "common/BitSetIterator.h"
+#include "common/bitset_utils.h"
#include "common/debug.h"
#include "common/platform.h"
+#include "common/string_utils.h"
#include "common/utilities.h"
-#include "common/version.h"
#include "compiler/translator/blocklayout.h"
-#include "libANGLE/Data.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/MemoryProgramCache.h"
+#include "libANGLE/ProgramLinkedResources.h"
#include "libANGLE/ResourceManager.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/VaryingPacking.h"
#include "libANGLE/features.h"
-#include "libANGLE/renderer/Renderer.h"
-#include "libANGLE/renderer/ProgramImpl.h"
+#include "libANGLE/histogram_macros.h"
#include "libANGLE/queryconversions.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/ProgramImpl.h"
+#include "platform/Platform.h"
namespace gl
{
@@ -30,29 +36,6 @@ namespace gl
namespace
{
-void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var)
-{
- stream->writeInt(var.type);
- stream->writeInt(var.precision);
- stream->writeString(var.name);
- stream->writeString(var.mappedName);
- stream->writeInt(var.arraySize);
- stream->writeInt(var.staticUse);
- stream->writeString(var.structName);
- ASSERT(var.fields.empty());
-}
-
-void LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var)
-{
- var->type = stream->readInt<GLenum>();
- var->precision = stream->readInt<GLenum>();
- var->name = stream->readString();
- var->mappedName = stream->readString();
- var->arraySize = stream->readInt<unsigned int>();
- var->staticUse = stream->readBool();
- var->structName = stream->readString();
-}
-
// This simplified cast function doesn't need to worry about advanced concepts like
// depth range values, or casting to bool.
template <typename DestT, typename SrcT>
@@ -88,19 +71,19 @@ GLuint UniformStateQueryCast(GLint value)
template <>
GLfloat UniformStateQueryCast(GLboolean value)
{
- return (value == GL_TRUE ? 1.0f : 0.0f);
+ return (ConvertToBool(value) ? 1.0f : 0.0f);
}
template <>
GLint UniformStateQueryCast(GLboolean value)
{
- return (value == GL_TRUE ? 1 : 0);
+ return (ConvertToBool(value) ? 1 : 0);
}
template <>
GLuint UniformStateQueryCast(GLboolean value)
{
- return (value == GL_TRUE ? 1u : 0u);
+ return (ConvertToBool(value) ? 1u : 0u);
}
// Default to static_cast
@@ -123,29 +106,224 @@ void UniformStateQueryCastLoop(DestT *dataOut, const uint8_t *srcPointer, int co
}
}
-bool UniformInList(const std::vector<LinkedUniform> &list, const std::string &name)
+template <typename VarT>
+GLuint GetResourceIndexFromName(const std::vector<VarT> &list, const std::string &name)
{
- for (const LinkedUniform &uniform : list)
+ std::string nameAsArrayName = name + "[0]";
+ for (size_t index = 0; index < list.size(); index++)
{
- if (uniform.name == name)
- return true;
+ const VarT &resource = list[index];
+ if (resource.name == name || (resource.isArray() && resource.name == nameAsArrayName))
+ {
+ return static_cast<GLuint>(index);
+ }
+ }
+
+ return GL_INVALID_INDEX;
+}
+
+template <typename VarT>
+GLint GetVariableLocation(const std::vector<VarT> &list,
+ const std::vector<VariableLocation> &locationList,
+ const std::string &name)
+{
+ size_t nameLengthWithoutArrayIndex;
+ unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
+
+ for (size_t location = 0u; location < locationList.size(); ++location)
+ {
+ const VariableLocation &variableLocation = locationList[location];
+ if (!variableLocation.used())
+ {
+ continue;
+ }
+
+ const VarT &variable = list[variableLocation.index];
+
+ if (angle::BeginsWith(variable.name, name))
+ {
+ if (name.length() == variable.name.length())
+ {
+ ASSERT(name == variable.name);
+ // GLES 3.1 November 2016 page 87.
+ // The string exactly matches the name of the active variable.
+ return static_cast<GLint>(location);
+ }
+ if (name.length() + 3u == variable.name.length() && variable.isArray())
+ {
+ ASSERT(name + "[0]" == variable.name);
+ // The string identifies the base name of an active array, where the string would
+ // exactly match the name of the variable if the suffix "[0]" were appended to the
+ // string.
+ return static_cast<GLint>(location);
+ }
+ }
+ if (variable.isArray() && variableLocation.arrayIndex == arrayIndex &&
+ nameLengthWithoutArrayIndex + 3u == variable.name.length() &&
+ angle::BeginsWith(variable.name, name, nameLengthWithoutArrayIndex))
+ {
+ ASSERT(name.substr(0u, nameLengthWithoutArrayIndex) + "[0]" == variable.name);
+ // The string identifies an active element of the array, where the string ends with the
+ // concatenation of the "[" character, an integer (with no "+" sign, extra leading
+ // zeroes, or whitespace) identifying an array element, and the "]" character, the
+ // integer is less than the number of active elements of the array variable, and where
+ // the string would exactly match the enumerated name of the array if the decimal
+ // integer were replaced with zero.
+ return static_cast<GLint>(location);
+ }
}
+ return -1;
+}
+
+void CopyStringToBuffer(GLchar *buffer, const std::string &string, GLsizei bufSize, GLsizei *length)
+{
+ ASSERT(bufSize > 0);
+ strncpy(buffer, string.c_str(), bufSize);
+ buffer[bufSize - 1] = '\0';
+
+ if (length)
+ {
+ *length = static_cast<GLsizei>(strlen(buffer));
+ }
+}
+
+bool IncludeSameArrayElement(const std::set<std::string> &nameSet, const std::string &name)
+{
+ std::vector<unsigned int> subscripts;
+ std::string baseName = ParseResourceName(name, &subscripts);
+ for (auto nameInSet : nameSet)
+ {
+ std::vector<unsigned int> arrayIndices;
+ std::string arrayName = ParseResourceName(nameInSet, &arrayIndices);
+ if (baseName == arrayName &&
+ (subscripts.empty() || arrayIndices.empty() || subscripts == arrayIndices))
+ {
+ return true;
+ }
+ }
return false;
}
-} // anonymous namespace
+bool validateInterfaceBlocksCount(GLuint maxInterfaceBlocks,
+ const std::vector<sh::InterfaceBlock> &interfaceBlocks,
+ const std::string &errorMessage,
+ InfoLog &infoLog)
+{
+ GLuint blockCount = 0;
+ for (const sh::InterfaceBlock &block : interfaceBlocks)
+ {
+ if (block.staticUse || block.layout != sh::BLOCKLAYOUT_PACKED)
+ {
+ blockCount += (block.arraySize ? block.arraySize : 1);
+ if (blockCount > maxInterfaceBlocks)
+ {
+ infoLog << errorMessage << maxInterfaceBlocks << ")";
+ return false;
+ }
+ }
+ }
+ return true;
+}
-const char *const g_fakepath = "C:\\fakepath";
+GLuint GetInterfaceBlockIndex(const std::vector<InterfaceBlock> &list, const std::string &name)
+{
+ std::vector<unsigned int> subscripts;
+ std::string baseName = ParseResourceName(name, &subscripts);
+
+ unsigned int numBlocks = static_cast<unsigned int>(list.size());
+ for (unsigned int blockIndex = 0; blockIndex < numBlocks; blockIndex++)
+ {
+ const auto &block = list[blockIndex];
+ if (block.name == baseName)
+ {
+ const bool arrayElementZero =
+ (subscripts.empty() && (!block.isArray || block.arrayElement == 0));
+ const bool arrayElementMatches =
+ (subscripts.size() == 1 && subscripts[0] == block.arrayElement);
+ if (arrayElementMatches || arrayElementZero)
+ {
+ return blockIndex;
+ }
+ }
+ }
+
+ return GL_INVALID_INDEX;
+}
+
+void GetInterfaceBlockName(const GLuint index,
+ const std::vector<InterfaceBlock> &list,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name)
+{
+ ASSERT(index < list.size());
+
+ const auto &block = list[index];
+
+ if (bufSize > 0)
+ {
+ std::string blockName = block.name;
+
+ if (block.isArray)
+ {
+ blockName += ArrayString(block.arrayElement);
+ }
+ CopyStringToBuffer(name, blockName, bufSize, length);
+ }
+}
-AttributeBindings::AttributeBindings()
+void InitUniformBlockLinker(const gl::Context *context,
+ const ProgramState &state,
+ UniformBlockLinker *blockLinker)
{
+ if (state.getAttachedVertexShader())
+ {
+ blockLinker->addShaderBlocks(GL_VERTEX_SHADER,
+ &state.getAttachedVertexShader()->getUniformBlocks(context));
+ }
+
+ if (state.getAttachedFragmentShader())
+ {
+ blockLinker->addShaderBlocks(GL_FRAGMENT_SHADER,
+ &state.getAttachedFragmentShader()->getUniformBlocks(context));
+ }
+
+ if (state.getAttachedComputeShader())
+ {
+ blockLinker->addShaderBlocks(GL_COMPUTE_SHADER,
+ &state.getAttachedComputeShader()->getUniformBlocks(context));
+ }
}
-AttributeBindings::~AttributeBindings()
+void InitShaderStorageBlockLinker(const gl::Context *context,
+ const ProgramState &state,
+ ShaderStorageBlockLinker *blockLinker)
{
+ if (state.getAttachedVertexShader())
+ {
+ blockLinker->addShaderBlocks(
+ GL_VERTEX_SHADER, &state.getAttachedVertexShader()->getShaderStorageBlocks(context));
+ }
+
+ if (state.getAttachedFragmentShader())
+ {
+ blockLinker->addShaderBlocks(
+ GL_FRAGMENT_SHADER,
+ &state.getAttachedFragmentShader()->getShaderStorageBlocks(context));
+ }
+
+ if (state.getAttachedComputeShader())
+ {
+ blockLinker->addShaderBlocks(
+ GL_COMPUTE_SHADER, &state.getAttachedComputeShader()->getShaderStorageBlocks(context));
+ }
}
+} // anonymous namespace
+
+const char *const g_fakepath = "C:\\fakepath";
+
InfoLog::InfoLog()
{
}
@@ -156,7 +334,12 @@ InfoLog::~InfoLog()
size_t InfoLog::getLength() const
{
- const std::string &logString = mStream.str();
+ if (!mLazyStream)
+ {
+ return 0;
+ }
+
+ const std::string &logString = mLazyStream->str();
return logString.empty() ? 0 : logString.length() + 1;
}
@@ -166,12 +349,12 @@ void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
if (bufSize > 0)
{
- const std::string str(mStream.str());
+ const std::string logString(str());
- if (!str.empty())
+ if (!logString.empty())
{
- index = std::min(static_cast<size_t>(bufSize) - 1, str.length());
- memcpy(infoLog, str.c_str(), index);
+ index = std::min(static_cast<size_t>(bufSize) - 1, logString.length());
+ memcpy(infoLog, logString.c_str(), index);
}
infoLog[index] = '\0';
@@ -184,10 +367,12 @@ void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
}
// append a santized message to the program info log.
-// The D3D compiler includes a fake file path in some of the warning or error
+// The D3D compiler includes a fake file path in some of the warning or error
// messages, so lets remove all occurrences of this fake file path from the log.
void InfoLog::appendSanitized(const char *message)
{
+ ensureInitialized();
+
std::string msg(message);
size_t found;
@@ -201,569 +386,682 @@ void InfoLog::appendSanitized(const char *message)
}
while (found != std::string::npos);
- mStream << message << std::endl;
+ *mLazyStream << message << std::endl;
}
void InfoLog::reset()
{
}
-VariableLocation::VariableLocation()
- : name(),
- element(0),
- index(0)
+VariableLocation::VariableLocation() : arrayIndex(0), index(kUnused), ignored(false)
+{
+}
+
+VariableLocation::VariableLocation(unsigned int arrayIndex, unsigned int index)
+ : arrayIndex(arrayIndex), index(index), ignored(false)
{
+ ASSERT(arrayIndex != GL_INVALID_INDEX);
}
-VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index)
- : name(name),
- element(element),
- index(index)
+SamplerBinding::SamplerBinding(GLenum textureTypeIn, size_t elementCount, bool unreferenced)
+ : textureType(textureTypeIn), boundTextureUnits(elementCount, 0), unreferenced(unreferenced)
{
}
-Program::Data::Data()
+SamplerBinding::SamplerBinding(const SamplerBinding &other) = default;
+
+SamplerBinding::~SamplerBinding() = default;
+
+Program::Bindings::Bindings()
+{
+}
+
+Program::Bindings::~Bindings()
+{
+}
+
+void Program::Bindings::bindLocation(GLuint index, const std::string &name)
+{
+ mBindings[name] = index;
+}
+
+int Program::Bindings::getBinding(const std::string &name) const
+{
+ auto iter = mBindings.find(name);
+ return (iter != mBindings.end()) ? iter->second : -1;
+}
+
+Program::Bindings::const_iterator Program::Bindings::begin() const
+{
+ return mBindings.begin();
+}
+
+Program::Bindings::const_iterator Program::Bindings::end() const
+{
+ return mBindings.end();
+}
+
+ImageBinding::ImageBinding(size_t count) : boundImageUnits(count, 0)
+{
+}
+ImageBinding::ImageBinding(GLuint imageUnit, size_t count)
+{
+ for (size_t index = 0; index < count; ++index)
+ {
+ boundImageUnits.push_back(imageUnit + static_cast<GLuint>(index));
+ }
+}
+
+ImageBinding::ImageBinding(const ImageBinding &other) = default;
+
+ImageBinding::~ImageBinding() = default;
+
+ProgramState::ProgramState()
: mLabel(),
mAttachedFragmentShader(nullptr),
mAttachedVertexShader(nullptr),
+ mAttachedComputeShader(nullptr),
+ mAttachedGeometryShader(nullptr),
mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
- mBinaryRetrieveableHint(false)
+ mMaxActiveAttribLocation(0),
+ mSamplerUniformRange(0, 0),
+ mImageUniformRange(0, 0),
+ mAtomicCounterUniformRange(0, 0),
+ mBinaryRetrieveableHint(false),
+ mNumViews(-1)
{
+ mComputeShaderLocalSize.fill(1);
}
-Program::Data::~Data()
+ProgramState::~ProgramState()
{
- if (mAttachedVertexShader != nullptr)
- {
- mAttachedVertexShader->release();
- }
-
- if (mAttachedFragmentShader != nullptr)
- {
- mAttachedFragmentShader->release();
- }
+ ASSERT(!mAttachedVertexShader && !mAttachedFragmentShader && !mAttachedComputeShader &&
+ !mAttachedGeometryShader);
}
-const std::string &Program::Data::getLabel()
+const std::string &ProgramState::getLabel()
{
return mLabel;
}
-const LinkedUniform *Program::Data::getUniformByName(const std::string &name) const
+GLuint ProgramState::getUniformIndexFromName(const std::string &name) const
{
- for (const LinkedUniform &linkedUniform : mUniforms)
- {
- if (linkedUniform.name == name)
- {
- return &linkedUniform;
- }
- }
+ return GetResourceIndexFromName(mUniforms, name);
+}
- return nullptr;
+GLuint ProgramState::getBufferVariableIndexFromName(const std::string &name) const
+{
+ return GetResourceIndexFromName(mBufferVariables, name);
}
-GLint Program::Data::getUniformLocation(const std::string &name) const
+GLuint ProgramState::getUniformIndexFromLocation(GLint location) const
{
- size_t subscript = GL_INVALID_INDEX;
- std::string baseName = gl::ParseUniformName(name, &subscript);
+ ASSERT(location >= 0 && static_cast<size_t>(location) < mUniformLocations.size());
+ return mUniformLocations[location].index;
+}
- for (size_t location = 0; location < mUniformLocations.size(); ++location)
+Optional<GLuint> ProgramState::getSamplerIndex(GLint location) const
+{
+ GLuint index = getUniformIndexFromLocation(location);
+ if (!isSamplerUniformIndex(index))
{
- const VariableLocation &uniformLocation = mUniformLocations[location];
- const LinkedUniform &uniform = mUniforms[uniformLocation.index];
-
- if (uniform.name == baseName)
- {
- if ((uniform.isArray() && uniformLocation.element == subscript) ||
- (subscript == GL_INVALID_INDEX))
- {
- return static_cast<GLint>(location);
- }
- }
+ return Optional<GLuint>::Invalid();
}
- return -1;
+ return getSamplerIndexFromUniformIndex(index);
}
-GLuint Program::Data::getUniformIndex(const std::string &name) const
+bool ProgramState::isSamplerUniformIndex(GLuint index) const
{
- size_t subscript = GL_INVALID_INDEX;
- std::string baseName = gl::ParseUniformName(name, &subscript);
+ return mSamplerUniformRange.contains(index);
+}
- // The app is not allowed to specify array indices other than 0 for arrays of basic types
- if (subscript != 0 && subscript != GL_INVALID_INDEX)
- {
- return GL_INVALID_INDEX;
- }
+GLuint ProgramState::getSamplerIndexFromUniformIndex(GLuint uniformIndex) const
+{
+ ASSERT(isSamplerUniformIndex(uniformIndex));
+ return uniformIndex - mSamplerUniformRange.low();
+}
- for (size_t index = 0; index < mUniforms.size(); index++)
+GLuint ProgramState::getAttributeLocation(const std::string &name) const
+{
+ for (const sh::Attribute &attribute : mAttributes)
{
- const LinkedUniform &uniform = mUniforms[index];
- if (uniform.name == baseName)
+ if (attribute.name == name)
{
- if (uniform.isArray() || subscript == GL_INVALID_INDEX)
- {
- return static_cast<GLuint>(index);
- }
+ return attribute.location;
}
}
- return GL_INVALID_INDEX;
+ return static_cast<GLuint>(-1);
}
-Program::Program(rx::ImplFactory *factory, ResourceManager *manager, GLuint handle)
- : mProgram(factory->createProgram(mData)),
+Program::Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, GLuint handle)
+ : mProgram(factory->createProgram(mState)),
mValidated(false),
mLinked(false),
mDeleteStatus(false),
mRefCount(0),
mResourceManager(manager),
- mHandle(handle),
- mSamplerUniformRange(0, 0)
+ mHandle(handle)
{
ASSERT(mProgram);
- resetUniformBlockBindings();
unlink();
}
Program::~Program()
{
- unlink(true);
+ ASSERT(!mProgram);
+}
+
+void Program::onDestroy(const Context *context)
+{
+ if (mState.mAttachedVertexShader != nullptr)
+ {
+ mState.mAttachedVertexShader->release(context);
+ mState.mAttachedVertexShader = nullptr;
+ }
+ if (mState.mAttachedFragmentShader != nullptr)
+ {
+ mState.mAttachedFragmentShader->release(context);
+ mState.mAttachedFragmentShader = nullptr;
+ }
+
+ if (mState.mAttachedComputeShader != nullptr)
+ {
+ mState.mAttachedComputeShader->release(context);
+ mState.mAttachedComputeShader = nullptr;
+ }
+
+ if (mState.mAttachedGeometryShader != nullptr)
+ {
+ mState.mAttachedGeometryShader->release(context);
+ mState.mAttachedGeometryShader = nullptr;
+ }
+
+ mProgram->destroy(context);
+
+ ASSERT(!mState.mAttachedVertexShader && !mState.mAttachedFragmentShader &&
+ !mState.mAttachedComputeShader && !mState.mAttachedGeometryShader);
SafeDelete(mProgram);
+
+ delete this;
}
void Program::setLabel(const std::string &label)
{
- mData.mLabel = label;
+ mState.mLabel = label;
}
const std::string &Program::getLabel() const
{
- return mData.mLabel;
+ return mState.mLabel;
}
-bool Program::attachShader(Shader *shader)
+void Program::attachShader(Shader *shader)
{
- if (shader->getType() == GL_VERTEX_SHADER)
+ switch (shader->getType())
{
- if (mData.mAttachedVertexShader)
+ case GL_VERTEX_SHADER:
{
- return false;
+ ASSERT(!mState.mAttachedVertexShader);
+ mState.mAttachedVertexShader = shader;
+ mState.mAttachedVertexShader->addRef();
+ break;
}
-
- mData.mAttachedVertexShader = shader;
- mData.mAttachedVertexShader->addRef();
- }
- else if (shader->getType() == GL_FRAGMENT_SHADER)
- {
- if (mData.mAttachedFragmentShader)
+ case GL_FRAGMENT_SHADER:
{
- return false;
+ ASSERT(!mState.mAttachedFragmentShader);
+ mState.mAttachedFragmentShader = shader;
+ mState.mAttachedFragmentShader->addRef();
+ break;
}
-
- mData.mAttachedFragmentShader = shader;
- mData.mAttachedFragmentShader->addRef();
+ case GL_COMPUTE_SHADER:
+ {
+ ASSERT(!mState.mAttachedComputeShader);
+ mState.mAttachedComputeShader = shader;
+ mState.mAttachedComputeShader->addRef();
+ break;
+ }
+ case GL_GEOMETRY_SHADER_EXT:
+ {
+ ASSERT(!mState.mAttachedGeometryShader);
+ mState.mAttachedGeometryShader = shader;
+ mState.mAttachedGeometryShader->addRef();
+ break;
+ }
+ default:
+ UNREACHABLE();
}
- else UNREACHABLE();
-
- return true;
}
-bool Program::detachShader(Shader *shader)
+void Program::detachShader(const Context *context, Shader *shader)
{
- if (shader->getType() == GL_VERTEX_SHADER)
+ switch (shader->getType())
{
- if (mData.mAttachedVertexShader != shader)
+ case GL_VERTEX_SHADER:
{
- return false;
+ ASSERT(mState.mAttachedVertexShader == shader);
+ shader->release(context);
+ mState.mAttachedVertexShader = nullptr;
+ break;
}
-
- shader->release();
- mData.mAttachedVertexShader = nullptr;
- }
- else if (shader->getType() == GL_FRAGMENT_SHADER)
- {
- if (mData.mAttachedFragmentShader != shader)
+ case GL_FRAGMENT_SHADER:
{
- return false;
+ ASSERT(mState.mAttachedFragmentShader == shader);
+ shader->release(context);
+ mState.mAttachedFragmentShader = nullptr;
+ break;
}
-
- shader->release();
- mData.mAttachedFragmentShader = nullptr;
+ case GL_COMPUTE_SHADER:
+ {
+ ASSERT(mState.mAttachedComputeShader == shader);
+ shader->release(context);
+ mState.mAttachedComputeShader = nullptr;
+ break;
+ }
+ case GL_GEOMETRY_SHADER_EXT:
+ {
+ ASSERT(mState.mAttachedGeometryShader == shader);
+ shader->release(context);
+ mState.mAttachedGeometryShader = nullptr;
+ break;
+ }
+ default:
+ UNREACHABLE();
}
- else UNREACHABLE();
-
- return true;
}
int Program::getAttachedShadersCount() const
{
- return (mData.mAttachedVertexShader ? 1 : 0) + (mData.mAttachedFragmentShader ? 1 : 0);
+ return (mState.mAttachedVertexShader ? 1 : 0) + (mState.mAttachedFragmentShader ? 1 : 0) +
+ (mState.mAttachedComputeShader ? 1 : 0) + (mState.mAttachedGeometryShader ? 1 : 0);
}
-void AttributeBindings::bindAttributeLocation(GLuint index, const char *name)
+void Program::bindAttributeLocation(GLuint index, const char *name)
{
- if (index < MAX_VERTEX_ATTRIBS)
- {
- for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
- {
- mAttributeBinding[i].erase(name);
- }
+ mAttributeBindings.bindLocation(index, name);
+}
- mAttributeBinding[index].insert(name);
- }
+void Program::bindUniformLocation(GLuint index, const char *name)
+{
+ mUniformLocationBindings.bindLocation(index, name);
}
-void Program::bindAttributeLocation(GLuint index, const char *name)
+void Program::bindFragmentInputLocation(GLint index, const char *name)
{
- mAttributeBindings.bindAttributeLocation(index, name);
+ mFragmentInputBindings.bindLocation(index, name);
}
-// Links the HLSL code of the vertex and pixel shader by matching up their varyings,
-// compiling them into binaries, determining the attribute mappings, and collecting
-// a list of uniforms
-Error Program::link(const gl::Data &data)
+BindingInfo Program::getFragmentInputBindingInfo(const Context *context, GLint index) const
{
- unlink(false);
+ BindingInfo ret;
+ ret.type = GL_NONE;
+ ret.valid = false;
- mInfoLog.reset();
- resetUniformBlockBindings();
+ Shader *fragmentShader = mState.getAttachedFragmentShader();
+ ASSERT(fragmentShader);
- if (!mData.mAttachedFragmentShader || !mData.mAttachedFragmentShader->isCompiled())
- {
- return Error(GL_NO_ERROR);
- }
- ASSERT(mData.mAttachedFragmentShader->getType() == GL_FRAGMENT_SHADER);
+ // Find the actual fragment shader varying we're interested in
+ const std::vector<sh::Varying> &inputs = fragmentShader->getInputVaryings(context);
- if (!mData.mAttachedVertexShader || !mData.mAttachedVertexShader->isCompiled())
+ for (const auto &binding : mFragmentInputBindings)
{
- return Error(GL_NO_ERROR);
- }
- ASSERT(mData.mAttachedVertexShader->getType() == GL_VERTEX_SHADER);
+ if (binding.second != static_cast<GLuint>(index))
+ continue;
- if (!linkAttributes(data, mInfoLog, mAttributeBindings, mData.mAttachedVertexShader))
- {
- return Error(GL_NO_ERROR);
- }
+ ret.valid = true;
- if (!linkVaryings(mInfoLog, mData.mAttachedVertexShader, mData.mAttachedFragmentShader))
- {
- return Error(GL_NO_ERROR);
+ size_t nameLengthWithoutArrayIndex;
+ unsigned int arrayIndex = ParseArrayIndex(binding.first, &nameLengthWithoutArrayIndex);
+
+ for (const auto &in : inputs)
+ {
+ if (in.name.length() == nameLengthWithoutArrayIndex &&
+ angle::BeginsWith(in.name, binding.first, nameLengthWithoutArrayIndex))
+ {
+ if (in.isArray())
+ {
+ // The client wants to bind either "name" or "name[0]".
+ // GL ES 3.1 spec refers to active array names with language such as:
+ // "if the string identifies the base name of an active array, where the
+ // string would exactly match the name of the variable if the suffix "[0]"
+ // were appended to the string".
+ if (arrayIndex == GL_INVALID_INDEX)
+ arrayIndex = 0;
+
+ ret.name = in.mappedName + "[" + ToString(arrayIndex) + "]";
+ }
+ else
+ {
+ ret.name = in.mappedName;
+ }
+ ret.type = in.type;
+ return ret;
+ }
+ }
}
- if (!linkUniforms(mInfoLog, *data.caps))
+ return ret;
+}
+
+void Program::pathFragmentInputGen(const Context *context,
+ GLint index,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs)
+{
+ // If the location is -1 then the command is silently ignored
+ if (index == -1)
+ return;
+
+ const auto &binding = getFragmentInputBindingInfo(context, index);
+
+ // If the input doesn't exist then then the command is silently ignored
+ // This could happen through optimization for example, the shader translator
+ // decides that a variable is not actually being used and optimizes it away.
+ if (binding.name.empty())
+ return;
+
+ mProgram->setPathFragmentInputGen(binding.name, genMode, components, coeffs);
+}
+
+// The attached shaders are checked for linking errors by matching up their variables.
+// Uniform, input and output variables get collected.
+// The code gets compiled into binaries.
+Error Program::link(const gl::Context *context)
+{
+ const auto &data = context->getContextState();
+
+ auto *platform = ANGLEPlatformCurrent();
+ double startTime = platform->currentTime(platform);
+
+ unlink();
+
+ ProgramHash programHash;
+ auto *cache = context->getMemoryProgramCache();
+ if (cache)
{
- return Error(GL_NO_ERROR);
+ ANGLE_TRY_RESULT(cache->getProgram(context, this, &mState, &programHash), mLinked);
+ ANGLE_HISTOGRAM_BOOLEAN("GPU.ANGLE.ProgramCache.LoadBinarySuccess", mLinked);
}
- if (!linkUniformBlocks(mInfoLog, *data.caps))
+ if (mLinked)
{
- return Error(GL_NO_ERROR);
+ double delta = platform->currentTime(platform) - startTime;
+ int us = static_cast<int>(delta * 1000000.0);
+ ANGLE_HISTOGRAM_COUNTS("GPU.ANGLE.ProgramCache.ProgramCacheHitTimeUS", us);
+ return NoError();
}
- const auto &mergedVaryings = getMergedVaryings();
+ // Cache load failed, fall through to normal linking.
+ unlink();
+ mInfoLog.reset();
- if (!linkValidateTransformFeedback(mInfoLog, mergedVaryings, *data.caps))
- {
- return Error(GL_NO_ERROR);
- }
+ const Caps &caps = data.getCaps();
- linkOutputVariables();
+ Shader *vertexShader = mState.mAttachedVertexShader;
+ Shader *fragmentShader = mState.mAttachedFragmentShader;
+ Shader *computeShader = mState.mAttachedComputeShader;
- rx::LinkResult result = mProgram->link(data, mInfoLog);
- if (result.error.isError() || !result.linkSuccess)
+ bool isComputeShaderAttached = (computeShader != nullptr);
+ bool nonComputeShadersAttached = (vertexShader != nullptr || fragmentShader != nullptr);
+ // Check whether we both have a compute and non-compute shaders attached.
+ // If there are of both types attached, then linking should fail.
+ // OpenGL ES 3.10, 7.3 Program Objects, under LinkProgram
+ if (isComputeShaderAttached == true && nonComputeShadersAttached == true)
{
- return result.error;
+ mInfoLog << "Both a compute and non-compute shaders are attached to the same program.";
+ return NoError();
}
- gatherTransformFeedbackVaryings(mergedVaryings);
- gatherInterfaceBlockInfo();
-
- mLinked = true;
- return gl::Error(GL_NO_ERROR);
-}
-
-int AttributeBindings::getAttributeBinding(const std::string &name) const
-{
- for (int location = 0; location < MAX_VERTEX_ATTRIBS; location++)
+ if (computeShader)
{
- if (mAttributeBinding[location].find(name) != mAttributeBinding[location].end())
+ if (!computeShader->isCompiled(context))
{
- return location;
+ mInfoLog << "Attached compute shader is not compiled.";
+ return NoError();
}
- }
+ ASSERT(computeShader->getType() == GL_COMPUTE_SHADER);
- return -1;
-}
+ mState.mComputeShaderLocalSize = computeShader->getWorkGroupSize(context);
-// Returns the program object to an unlinked state, before re-linking, or at destruction
-void Program::unlink(bool destroy)
-{
- if (destroy) // Object being destructed
- {
- if (mData.mAttachedFragmentShader)
+ // GLSL ES 3.10, 4.4.1.1 Compute Shader Inputs
+ // If the work group size is not specified, a link time error should occur.
+ if (!mState.mComputeShaderLocalSize.isDeclared())
{
- mData.mAttachedFragmentShader->release();
- mData.mAttachedFragmentShader = nullptr;
+ mInfoLog << "Work group size is not specified.";
+ return NoError();
}
- if (mData.mAttachedVertexShader)
+ if (!linkUniforms(context, mInfoLog, mUniformLocationBindings))
{
- mData.mAttachedVertexShader->release();
- mData.mAttachedVertexShader = nullptr;
+ return NoError();
}
- }
- mData.mAttributes.clear();
- mData.mActiveAttribLocationsMask.reset();
- mData.mTransformFeedbackVaryingVars.clear();
- mData.mUniforms.clear();
- mData.mUniformLocations.clear();
- mData.mUniformBlocks.clear();
- mData.mOutputVariables.clear();
+ if (!linkInterfaceBlocks(context, mInfoLog))
+ {
+ return NoError();
+ }
- mValidated = false;
+ ProgramLinkedResources resources = {
+ {0, PackMode::ANGLE_RELAXED},
+ {&mState.mUniformBlocks, &mState.mUniforms},
+ {&mState.mShaderStorageBlocks, &mState.mBufferVariables}};
- mLinked = false;
-}
+ InitUniformBlockLinker(context, mState, &resources.uniformBlockLinker);
+ InitShaderStorageBlockLinker(context, mState, &resources.shaderStorageBlockLinker);
-bool Program::isLinked() const
-{
- return mLinked;
-}
+ ANGLE_TRY_RESULT(mProgram->link(context, resources, mInfoLog), mLinked);
+ if (!mLinked)
+ {
+ return NoError();
+ }
+ }
+ else
+ {
+ if (!fragmentShader || !fragmentShader->isCompiled(context))
+ {
+ return NoError();
+ }
+ ASSERT(fragmentShader->getType() == GL_FRAGMENT_SHADER);
-Error Program::loadBinary(GLenum binaryFormat, const void *binary, GLsizei length)
-{
- unlink(false);
+ if (!vertexShader || !vertexShader->isCompiled(context))
+ {
+ return NoError();
+ }
+ ASSERT(vertexShader->getType() == GL_VERTEX_SHADER);
-#if ANGLE_PROGRAM_BINARY_LOAD != ANGLE_ENABLED
- return Error(GL_NO_ERROR);
-#else
- ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE);
- if (binaryFormat != GL_PROGRAM_BINARY_ANGLE)
- {
- mInfoLog << "Invalid program binary format.";
- return Error(GL_NO_ERROR);
- }
+ if (fragmentShader->getShaderVersion(context) != vertexShader->getShaderVersion(context))
+ {
+ mInfoLog << "Fragment shader version does not match vertex shader version.";
+ return NoError();
+ }
- BinaryInputStream stream(binary, length);
+ if (!linkAttributes(context, mInfoLog))
+ {
+ return NoError();
+ }
- int majorVersion = stream.readInt<int>();
- int minorVersion = stream.readInt<int>();
- if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION)
- {
- mInfoLog << "Invalid program binary version.";
- return Error(GL_NO_ERROR);
- }
+ if (!linkVaryings(context, mInfoLog))
+ {
+ return NoError();
+ }
- unsigned char commitString[ANGLE_COMMIT_HASH_SIZE];
- stream.readBytes(commitString, ANGLE_COMMIT_HASH_SIZE);
- if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0)
- {
- mInfoLog << "Invalid program binary version.";
- return Error(GL_NO_ERROR);
- }
+ if (!linkUniforms(context, mInfoLog, mUniformLocationBindings))
+ {
+ return NoError();
+ }
- static_assert(MAX_VERTEX_ATTRIBS <= sizeof(unsigned long) * 8,
- "Too many vertex attribs for mask");
- mData.mActiveAttribLocationsMask = stream.readInt<unsigned long>();
+ if (!linkInterfaceBlocks(context, mInfoLog))
+ {
+ return NoError();
+ }
- unsigned int attribCount = stream.readInt<unsigned int>();
- ASSERT(mData.mAttributes.empty());
- for (unsigned int attribIndex = 0; attribIndex < attribCount; ++attribIndex)
- {
- sh::Attribute attrib;
- LoadShaderVar(&stream, &attrib);
- attrib.location = stream.readInt<int>();
- mData.mAttributes.push_back(attrib);
- }
+ if (!linkValidateGlobalNames(context, mInfoLog))
+ {
+ return NoError();
+ }
- unsigned int uniformCount = stream.readInt<unsigned int>();
- ASSERT(mData.mUniforms.empty());
- for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; ++uniformIndex)
- {
- LinkedUniform uniform;
- LoadShaderVar(&stream, &uniform);
+ const auto &mergedVaryings = getMergedVaryings(context);
- uniform.blockIndex = stream.readInt<int>();
- uniform.blockInfo.offset = stream.readInt<int>();
- uniform.blockInfo.arrayStride = stream.readInt<int>();
- uniform.blockInfo.matrixStride = stream.readInt<int>();
- uniform.blockInfo.isRowMajorMatrix = stream.readBool();
+ mState.mNumViews = vertexShader->getNumViews(context);
- mData.mUniforms.push_back(uniform);
- }
+ linkOutputVariables(context);
- const unsigned int uniformIndexCount = stream.readInt<unsigned int>();
- ASSERT(mData.mUniformLocations.empty());
- for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount;
- uniformIndexIndex++)
- {
- VariableLocation variable;
- stream.readString(&variable.name);
- stream.readInt(&variable.element);
- stream.readInt(&variable.index);
+ // Map the varyings to the register file
+ // In WebGL, we use a slightly different handling for packing variables.
+ auto packMode = data.getExtensions().webglCompatibility ? PackMode::WEBGL_STRICT
+ : PackMode::ANGLE_RELAXED;
- mData.mUniformLocations.push_back(variable);
- }
+ ProgramLinkedResources resources = {
+ {data.getCaps().maxVaryingVectors, packMode},
+ {&mState.mUniformBlocks, &mState.mUniforms},
+ {&mState.mShaderStorageBlocks, &mState.mBufferVariables}};
- unsigned int uniformBlockCount = stream.readInt<unsigned int>();
- ASSERT(mData.mUniformBlocks.empty());
- for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount;
- ++uniformBlockIndex)
- {
- UniformBlock uniformBlock;
- stream.readString(&uniformBlock.name);
- stream.readBool(&uniformBlock.isArray);
- stream.readInt(&uniformBlock.arrayElement);
- stream.readInt(&uniformBlock.dataSize);
- stream.readBool(&uniformBlock.vertexStaticUse);
- stream.readBool(&uniformBlock.fragmentStaticUse);
+ InitUniformBlockLinker(context, mState, &resources.uniformBlockLinker);
+ InitShaderStorageBlockLinker(context, mState, &resources.shaderStorageBlockLinker);
- unsigned int numMembers = stream.readInt<unsigned int>();
- for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
+ if (!linkValidateTransformFeedback(context, mInfoLog, mergedVaryings, caps))
{
- uniformBlock.memberUniformIndexes.push_back(stream.readInt<unsigned int>());
+ return NoError();
}
- mData.mUniformBlocks.push_back(uniformBlock);
- }
+ if (!resources.varyingPacking.collectAndPackUserVaryings(
+ mInfoLog, mergedVaryings, mState.getTransformFeedbackVaryingNames()))
+ {
+ return NoError();
+ }
- unsigned int transformFeedbackVaryingCount = stream.readInt<unsigned int>();
- ASSERT(mData.mTransformFeedbackVaryingVars.empty());
- for (unsigned int transformFeedbackVaryingIndex = 0;
- transformFeedbackVaryingIndex < transformFeedbackVaryingCount;
- ++transformFeedbackVaryingIndex)
- {
- sh::Varying varying;
- stream.readInt(&varying.arraySize);
- stream.readInt(&varying.type);
- stream.readString(&varying.name);
+ ANGLE_TRY_RESULT(mProgram->link(context, resources, mInfoLog), mLinked);
+ if (!mLinked)
+ {
+ return NoError();
+ }
- mData.mTransformFeedbackVaryingVars.push_back(varying);
+ gatherTransformFeedbackVaryings(mergedVaryings);
}
- stream.readInt(&mData.mTransformFeedbackBufferMode);
+ gatherAtomicCounterBuffers();
+ initInterfaceBlockBindings();
- unsigned int outputVarCount = stream.readInt<unsigned int>();
- for (unsigned int outputIndex = 0; outputIndex < outputVarCount; ++outputIndex)
- {
- int locationIndex = stream.readInt<int>();
- VariableLocation locationData;
- stream.readInt(&locationData.element);
- stream.readInt(&locationData.index);
- stream.readString(&locationData.name);
- mData.mOutputVariables[locationIndex] = locationData;
- }
+ setUniformValuesFromBindingQualifiers();
- stream.readInt(&mSamplerUniformRange.start);
- stream.readInt(&mSamplerUniformRange.end);
+ ASSERT(mLinked);
+ updateLinkedShaderStages();
- rx::LinkResult result = mProgram->load(mInfoLog, &stream);
- if (result.error.isError() || !result.linkSuccess)
+ // Mark implementation-specific unreferenced uniforms as ignored.
+ mProgram->markUnusedUniformLocations(&mState.mUniformLocations, &mState.mSamplerBindings);
+
+ // Save to the program cache.
+ if (cache && (mState.mLinkedTransformFeedbackVaryings.empty() ||
+ !context->getWorkarounds().disableProgramCachingForTransformFeedback))
{
- return result.error;
+ cache->putProgram(programHash, context, this);
}
- mLinked = true;
- return Error(GL_NO_ERROR);
-#endif // #if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_ENABLED
+ double delta = platform->currentTime(platform) - startTime;
+ int us = static_cast<int>(delta * 1000000.0);
+ ANGLE_HISTOGRAM_COUNTS("GPU.ANGLE.ProgramCache.ProgramCacheMissTimeUS", us);
+
+ return NoError();
}
-Error Program::saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) const
+void Program::updateLinkedShaderStages()
{
- if (binaryFormat)
+ if (mState.mAttachedVertexShader)
{
- *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
+ mState.mLinkedShaderStages.set(SHADER_VERTEX);
}
- BinaryOutputStream stream;
-
- stream.writeInt(ANGLE_MAJOR_VERSION);
- stream.writeInt(ANGLE_MINOR_VERSION);
- stream.writeBytes(reinterpret_cast<const unsigned char*>(ANGLE_COMMIT_HASH), ANGLE_COMMIT_HASH_SIZE);
-
- stream.writeInt(mData.mActiveAttribLocationsMask.to_ulong());
-
- stream.writeInt(mData.mAttributes.size());
- for (const sh::Attribute &attrib : mData.mAttributes)
+ if (mState.mAttachedFragmentShader)
{
- WriteShaderVar(&stream, attrib);
- stream.writeInt(attrib.location);
+ mState.mLinkedShaderStages.set(SHADER_FRAGMENT);
}
- stream.writeInt(mData.mUniforms.size());
- for (const gl::LinkedUniform &uniform : mData.mUniforms)
+ if (mState.mAttachedComputeShader)
{
- WriteShaderVar(&stream, uniform);
-
- // FIXME: referenced
-
- stream.writeInt(uniform.blockIndex);
- stream.writeInt(uniform.blockInfo.offset);
- stream.writeInt(uniform.blockInfo.arrayStride);
- stream.writeInt(uniform.blockInfo.matrixStride);
- stream.writeInt(uniform.blockInfo.isRowMajorMatrix);
+ mState.mLinkedShaderStages.set(SHADER_COMPUTE);
}
+}
- stream.writeInt(mData.mUniformLocations.size());
- for (const auto &variable : mData.mUniformLocations)
- {
- stream.writeString(variable.name);
- stream.writeInt(variable.element);
- stream.writeInt(variable.index);
- }
+// Returns the program object to an unlinked state, before re-linking, or at destruction
+void Program::unlink()
+{
+ mState.mAttributes.clear();
+ mState.mActiveAttribLocationsMask.reset();
+ mState.mMaxActiveAttribLocation = 0;
+ mState.mLinkedTransformFeedbackVaryings.clear();
+ mState.mUniforms.clear();
+ mState.mUniformLocations.clear();
+ mState.mUniformBlocks.clear();
+ mState.mActiveUniformBlockBindings.reset();
+ mState.mAtomicCounterBuffers.clear();
+ mState.mOutputVariables.clear();
+ mState.mOutputLocations.clear();
+ mState.mOutputVariableTypes.clear();
+ mState.mActiveOutputVariables.reset();
+ mState.mComputeShaderLocalSize.fill(1);
+ mState.mSamplerBindings.clear();
+ mState.mImageBindings.clear();
+ mState.mNumViews = -1;
+ mState.mLinkedShaderStages.reset();
- stream.writeInt(mData.mUniformBlocks.size());
- for (const UniformBlock &uniformBlock : mData.mUniformBlocks)
- {
- stream.writeString(uniformBlock.name);
- stream.writeInt(uniformBlock.isArray);
- stream.writeInt(uniformBlock.arrayElement);
- stream.writeInt(uniformBlock.dataSize);
+ mValidated = false;
- stream.writeInt(uniformBlock.vertexStaticUse);
- stream.writeInt(uniformBlock.fragmentStaticUse);
+ mLinked = false;
+}
- stream.writeInt(uniformBlock.memberUniformIndexes.size());
- for (unsigned int memberUniformIndex : uniformBlock.memberUniformIndexes)
- {
- stream.writeInt(memberUniformIndex);
- }
- }
+bool Program::isLinked() const
+{
+ return mLinked;
+}
+
+Error Program::loadBinary(const Context *context,
+ GLenum binaryFormat,
+ const void *binary,
+ GLsizei length)
+{
+ unlink();
- stream.writeInt(mData.mTransformFeedbackVaryingVars.size());
- for (const sh::Varying &varying : mData.mTransformFeedbackVaryingVars)
+#if ANGLE_PROGRAM_BINARY_LOAD != ANGLE_ENABLED
+ return NoError();
+#else
+ ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE);
+ if (binaryFormat != GL_PROGRAM_BINARY_ANGLE)
{
- stream.writeInt(varying.arraySize);
- stream.writeInt(varying.type);
- stream.writeString(varying.name);
+ mInfoLog << "Invalid program binary format.";
+ return NoError();
}
- stream.writeInt(mData.mTransformFeedbackBufferMode);
+ const uint8_t *bytes = reinterpret_cast<const uint8_t *>(binary);
+ ANGLE_TRY_RESULT(
+ MemoryProgramCache::Deserialize(context, this, &mState, bytes, length, mInfoLog), mLinked);
- stream.writeInt(mData.mOutputVariables.size());
- for (const auto &outputPair : mData.mOutputVariables)
- {
- stream.writeInt(outputPair.first);
- stream.writeInt(outputPair.second.element);
- stream.writeInt(outputPair.second.index);
- stream.writeString(outputPair.second.name);
- }
+ // Currently we require the full shader text to compute the program hash.
+ // TODO(jmadill): Store the binary in the internal program cache.
- stream.writeInt(mSamplerUniformRange.start);
- stream.writeInt(mSamplerUniformRange.end);
+ return NoError();
+#endif // #if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_ENABLED
+}
- gl::Error error = mProgram->save(&stream);
- if (error.isError())
+Error Program::saveBinary(const Context *context,
+ GLenum *binaryFormat,
+ void *binary,
+ GLsizei bufSize,
+ GLsizei *length) const
+{
+ if (binaryFormat)
{
- return error;
+ *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
}
- GLsizei streamLength = static_cast<GLsizei>(stream.length());
- const void *streamData = stream.data();
+ angle::MemoryBuffer memoryBuf;
+ MemoryProgramCache::Serialize(context, this, &memoryBuf);
+
+ GLsizei streamLength = static_cast<GLsizei>(memoryBuf.size());
+ const uint8_t *streamState = memoryBuf.data();
if (streamLength > bufSize)
{
@@ -775,14 +1073,14 @@ Error Program::saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, G
// TODO: This should be moved to the validation layer but computing the size of the binary before saving
// it causes the save to happen twice. It may be possible to write the binary to a separate buffer, validate
// sizes and then copy it.
- return Error(GL_INVALID_OPERATION);
+ return InternalError();
}
if (binary)
{
char *ptr = reinterpret_cast<char*>(binary);
- memcpy(ptr, streamData, streamLength);
+ memcpy(ptr, streamState, streamLength);
ptr += streamLength;
ASSERT(ptr - streamLength == binary);
@@ -793,13 +1091,13 @@ Error Program::saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, G
*length = streamLength;
}
- return Error(GL_NO_ERROR);
+ return NoError();
}
-GLint Program::getBinaryLength() const
+GLint Program::getBinaryLength(const Context *context) const
{
GLint length;
- Error error = saveBinary(nullptr, nullptr, std::numeric_limits<GLint>::max(), &length);
+ Error error = saveBinary(context, nullptr, nullptr, std::numeric_limits<GLint>::max(), &length);
if (error.isError())
{
return 0;
@@ -812,21 +1110,36 @@ void Program::setBinaryRetrievableHint(bool retrievable)
{
// TODO(jmadill) : replace with dirty bits
mProgram->setBinaryRetrievableHint(retrievable);
- mData.mBinaryRetrieveableHint = retrievable;
+ mState.mBinaryRetrieveableHint = retrievable;
}
bool Program::getBinaryRetrievableHint() const
{
- return mData.mBinaryRetrieveableHint;
+ return mState.mBinaryRetrieveableHint;
}
-void Program::release()
+void Program::setSeparable(bool separable)
+{
+ // TODO(yunchao) : replace with dirty bits
+ if (mState.mSeparable != separable)
+ {
+ mProgram->setSeparable(separable);
+ mState.mSeparable = separable;
+ }
+}
+
+bool Program::isSeparable() const
+{
+ return mState.mSeparable;
+}
+
+void Program::release(const Context *context)
{
mRefCount--;
if (mRefCount == 0 && mDeleteStatus)
{
- mResourceManager->deleteProgram(mHandle);
+ mResourceManager->deleteProgram(context, mHandle);
}
}
@@ -854,24 +1167,40 @@ void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shade
{
int total = 0;
- if (mData.mAttachedVertexShader)
+ if (mState.mAttachedComputeShader)
{
if (total < maxCount)
{
- shaders[total] = mData.mAttachedVertexShader->getHandle();
+ shaders[total] = mState.mAttachedComputeShader->getHandle();
+ total++;
}
+ }
- total++;
+ if (mState.mAttachedVertexShader)
+ {
+ if (total < maxCount)
+ {
+ shaders[total] = mState.mAttachedVertexShader->getHandle();
+ total++;
+ }
}
- if (mData.mAttachedFragmentShader)
+ if (mState.mAttachedFragmentShader)
{
if (total < maxCount)
{
- shaders[total] = mData.mAttachedFragmentShader->getHandle();
+ shaders[total] = mState.mAttachedFragmentShader->getHandle();
+ total++;
}
+ }
- total++;
+ if (mState.mAttachedGeometryShader)
+ {
+ if (total < maxCount)
+ {
+ shaders[total] = mState.mAttachedGeometryShader->getHandle();
+ total++;
+ }
}
if (count)
@@ -882,24 +1211,21 @@ void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shade
GLuint Program::getAttributeLocation(const std::string &name) const
{
- for (const sh::Attribute &attribute : mData.mAttributes)
- {
- if (attribute.name == name && attribute.staticUse)
- {
- return attribute.location;
- }
- }
-
- return static_cast<GLuint>(-1);
+ return mState.getAttributeLocation(name);
}
bool Program::isAttribLocationActive(size_t attribLocation) const
{
- ASSERT(attribLocation < mData.mActiveAttribLocationsMask.size());
- return mData.mActiveAttribLocationsMask[attribLocation];
+ ASSERT(attribLocation < mState.mActiveAttribLocationsMask.size());
+ return mState.mActiveAttribLocationsMask[attribLocation];
}
-void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+void Program::getActiveAttribute(GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name) const
{
if (!mLinked)
{
@@ -918,35 +1244,12 @@ void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length,
return;
}
- size_t attributeIndex = 0;
-
- for (const sh::Attribute &attribute : mData.mAttributes)
- {
- // Skip over inactive attributes
- if (attribute.staticUse)
- {
- if (static_cast<size_t>(index) == attributeIndex)
- {
- break;
- }
- attributeIndex++;
- }
- }
-
- ASSERT(index == attributeIndex && attributeIndex < mData.mAttributes.size());
- const sh::Attribute &attrib = mData.mAttributes[attributeIndex];
+ ASSERT(index < mState.mAttributes.size());
+ const sh::Attribute &attrib = mState.mAttributes[index];
if (bufsize > 0)
{
- const char *string = attrib.name.c_str();
-
- strncpy(name, string, bufsize);
- name[bufsize - 1] = '\0';
-
- if (length)
- {
- *length = static_cast<GLsizei>(strlen(name));
- }
+ CopyStringToBuffer(name, attrib.name, bufsize, length);
}
// Always a single 'type' instance
@@ -961,14 +1264,7 @@ GLint Program::getActiveAttributeCount() const
return 0;
}
- GLint count = 0;
-
- for (const sh::Attribute &attrib : mData.mAttributes)
- {
- count += (attrib.staticUse ? 1 : 0);
- }
-
- return count;
+ return static_cast<GLint>(mState.mAttributes.size());
}
GLint Program::getActiveAttributeMaxLength() const
@@ -980,30 +1276,105 @@ GLint Program::getActiveAttributeMaxLength() const
size_t maxLength = 0;
- for (const sh::Attribute &attrib : mData.mAttributes)
+ for (const sh::Attribute &attrib : mState.mAttributes)
{
- if (attrib.staticUse)
- {
- maxLength = std::max(attrib.name.length() + 1, maxLength);
- }
+ maxLength = std::max(attrib.name.length() + 1, maxLength);
}
return static_cast<GLint>(maxLength);
}
-GLint Program::getFragDataLocation(const std::string &name) const
+GLuint Program::getInputResourceIndex(const GLchar *name) const
{
- std::string baseName(name);
- unsigned int arrayIndex = ParseAndStripArrayIndex(&baseName);
- for (auto outputPair : mData.mOutputVariables)
+ return GetResourceIndexFromName(mState.mAttributes, std::string(name));
+}
+
+GLuint Program::getOutputResourceIndex(const GLchar *name) const
+{
+ return GetResourceIndexFromName(mState.mOutputVariables, std::string(name));
+}
+
+size_t Program::getOutputResourceCount() const
+{
+ return (mLinked ? mState.mOutputVariables.size() : 0);
+}
+
+template <typename T>
+void Program::getResourceName(GLuint index,
+ const std::vector<T> &resources,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name) const
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (!mLinked)
{
- const VariableLocation &outputVariable = outputPair.second;
- if (outputVariable.name == baseName && (arrayIndex == GL_INVALID_INDEX || arrayIndex == outputVariable.element))
+ if (bufSize > 0)
{
- return static_cast<GLint>(outputPair.first);
+ name[0] = '\0';
}
+ return;
}
- return -1;
+ ASSERT(index < resources.size());
+ const auto &resource = resources[index];
+
+ if (bufSize > 0)
+ {
+ CopyStringToBuffer(name, resource.name, bufSize, length);
+ }
+}
+
+void Program::getInputResourceName(GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name) const
+{
+ getResourceName(index, mState.mAttributes, bufSize, length, name);
+}
+
+void Program::getOutputResourceName(GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name) const
+{
+ getResourceName(index, mState.mOutputVariables, bufSize, length, name);
+}
+
+void Program::getUniformResourceName(GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name) const
+{
+ getResourceName(index, mState.mUniforms, bufSize, length, name);
+}
+
+void Program::getBufferVariableResourceName(GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name) const
+{
+ getResourceName(index, mState.mBufferVariables, bufSize, length, name);
+}
+
+const sh::Attribute &Program::getInputResource(GLuint index) const
+{
+ ASSERT(index < mState.mAttributes.size());
+ return mState.mAttributes[index];
+}
+
+const sh::OutputVariable &Program::getOutputResource(GLuint index) const
+{
+ ASSERT(index < mState.mOutputVariables.size());
+ return mState.mOutputVariables[index];
+}
+
+GLint Program::getFragDataLocation(const std::string &name) const
+{
+ return GetVariableLocation(mState.mOutputVariables, mState.mOutputLocations, name);
}
void Program::getActiveUniform(GLuint index,
@@ -1016,27 +1387,16 @@ void Program::getActiveUniform(GLuint index,
if (mLinked)
{
// index must be smaller than getActiveUniformCount()
- ASSERT(index < mData.mUniforms.size());
- const LinkedUniform &uniform = mData.mUniforms[index];
+ ASSERT(index < mState.mUniforms.size());
+ const LinkedUniform &uniform = mState.mUniforms[index];
if (bufsize > 0)
{
std::string string = uniform.name;
- if (uniform.isArray())
- {
- string += "[0]";
- }
-
- strncpy(name, string.c_str(), bufsize);
- name[bufsize - 1] = '\0';
-
- if (length)
- {
- *length = static_cast<GLsizei>(strlen(name));
- }
+ CopyStringToBuffer(name, string, bufsize, length);
}
- *size = uniform.elementCount();
+ *size = clampCast<GLint>(uniform.getBasicTypeElementCount());
*type = uniform.type;
}
else
@@ -1060,7 +1420,7 @@ GLint Program::getActiveUniformCount() const
{
if (mLinked)
{
- return static_cast<GLint>(mData.mUniforms.size());
+ return static_cast<GLint>(mState.mUniforms.size());
}
else
{
@@ -1068,13 +1428,18 @@ GLint Program::getActiveUniformCount() const
}
}
+size_t Program::getActiveBufferVariableCount() const
+{
+ return mLinked ? mState.mBufferVariables.size() : 0;
+}
+
GLint Program::getActiveUniformMaxLength() const
{
size_t maxLength = 0;
if (mLinked)
{
- for (const LinkedUniform &uniform : mData.mUniforms)
+ for (const LinkedUniform &uniform : mState.mUniforms)
{
if (!uniform.name.empty())
{
@@ -1091,188 +1456,248 @@ GLint Program::getActiveUniformMaxLength() const
return static_cast<GLint>(maxLength);
}
-GLint Program::getActiveUniformi(GLuint index, GLenum pname) const
+bool Program::isValidUniformLocation(GLint location) const
{
- ASSERT(static_cast<size_t>(index) < mData.mUniforms.size());
- const gl::LinkedUniform &uniform = mData.mUniforms[index];
- switch (pname)
- {
- case GL_UNIFORM_TYPE: return static_cast<GLint>(uniform.type);
- case GL_UNIFORM_SIZE: return static_cast<GLint>(uniform.elementCount());
- case GL_UNIFORM_NAME_LENGTH: return static_cast<GLint>(uniform.name.size() + 1 + (uniform.isArray() ? 3 : 0));
- case GL_UNIFORM_BLOCK_INDEX: return uniform.blockIndex;
- case GL_UNIFORM_OFFSET: return uniform.blockInfo.offset;
- case GL_UNIFORM_ARRAY_STRIDE: return uniform.blockInfo.arrayStride;
- case GL_UNIFORM_MATRIX_STRIDE: return uniform.blockInfo.matrixStride;
- case GL_UNIFORM_IS_ROW_MAJOR: return static_cast<GLint>(uniform.blockInfo.isRowMajorMatrix);
- default:
- UNREACHABLE();
- break;
- }
- return 0;
+ ASSERT(angle::IsValueInRangeForNumericType<GLint>(mState.mUniformLocations.size()));
+ return (location >= 0 && static_cast<size_t>(location) < mState.mUniformLocations.size() &&
+ mState.mUniformLocations[static_cast<size_t>(location)].used());
}
-bool Program::isValidUniformLocation(GLint location) const
+const LinkedUniform &Program::getUniformByLocation(GLint location) const
{
- ASSERT(rx::IsIntegerCastSafe<GLint>(mData.mUniformLocations.size()));
- return (location >= 0 && static_cast<size_t>(location) < mData.mUniformLocations.size());
+ ASSERT(location >= 0 && static_cast<size_t>(location) < mState.mUniformLocations.size());
+ return mState.mUniforms[mState.getUniformIndexFromLocation(location)];
}
-const LinkedUniform &Program::getUniformByLocation(GLint location) const
+const VariableLocation &Program::getUniformLocation(GLint location) const
+{
+ ASSERT(location >= 0 && static_cast<size_t>(location) < mState.mUniformLocations.size());
+ return mState.mUniformLocations[location];
+}
+
+const std::vector<VariableLocation> &Program::getUniformLocations() const
{
- ASSERT(location >= 0 && static_cast<size_t>(location) < mData.mUniformLocations.size());
- return mData.mUniforms[mData.mUniformLocations[location].index];
+ return mState.mUniformLocations;
+}
+
+const LinkedUniform &Program::getUniformByIndex(GLuint index) const
+{
+ ASSERT(index < static_cast<size_t>(mState.mUniforms.size()));
+ return mState.mUniforms[index];
+}
+
+const BufferVariable &Program::getBufferVariableByIndex(GLuint index) const
+{
+ ASSERT(index < static_cast<size_t>(mState.mBufferVariables.size()));
+ return mState.mBufferVariables[index];
}
GLint Program::getUniformLocation(const std::string &name) const
{
- return mData.getUniformLocation(name);
+ return GetVariableLocation(mState.mUniforms, mState.mUniformLocations, name);
}
GLuint Program::getUniformIndex(const std::string &name) const
{
- return mData.getUniformIndex(name);
+ return mState.getUniformIndexFromName(name);
}
void Program::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
{
- setUniformInternal(location, count * 1, v);
- mProgram->setUniform1fv(location, count, v);
+ const VariableLocation &locationInfo = mState.mUniformLocations[location];
+ GLsizei clampedCount = clampUniformCount(locationInfo, count, 1, v);
+ mProgram->setUniform1fv(location, clampedCount, v);
}
void Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
{
- setUniformInternal(location, count * 2, v);
- mProgram->setUniform2fv(location, count, v);
+ const VariableLocation &locationInfo = mState.mUniformLocations[location];
+ GLsizei clampedCount = clampUniformCount(locationInfo, count, 2, v);
+ mProgram->setUniform2fv(location, clampedCount, v);
}
void Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
{
- setUniformInternal(location, count * 3, v);
- mProgram->setUniform3fv(location, count, v);
+ const VariableLocation &locationInfo = mState.mUniformLocations[location];
+ GLsizei clampedCount = clampUniformCount(locationInfo, count, 3, v);
+ mProgram->setUniform3fv(location, clampedCount, v);
}
void Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
{
- setUniformInternal(location, count * 4, v);
- mProgram->setUniform4fv(location, count, v);
+ const VariableLocation &locationInfo = mState.mUniformLocations[location];
+ GLsizei clampedCount = clampUniformCount(locationInfo, count, 4, v);
+ mProgram->setUniform4fv(location, clampedCount, v);
}
-void Program::setUniform1iv(GLint location, GLsizei count, const GLint *v)
+Program::SetUniformResult Program::setUniform1iv(GLint location, GLsizei count, const GLint *v)
{
- setUniformInternal(location, count * 1, v);
- mProgram->setUniform1iv(location, count, v);
+ const VariableLocation &locationInfo = mState.mUniformLocations[location];
+ GLsizei clampedCount = clampUniformCount(locationInfo, count, 1, v);
+
+ mProgram->setUniform1iv(location, clampedCount, v);
+
+ if (mState.isSamplerUniformIndex(locationInfo.index))
+ {
+ updateSamplerUniform(locationInfo, clampedCount, v);
+ return SetUniformResult::SamplerChanged;
+ }
+
+ return SetUniformResult::NoSamplerChange;
}
void Program::setUniform2iv(GLint location, GLsizei count, const GLint *v)
{
- setUniformInternal(location, count * 2, v);
- mProgram->setUniform2iv(location, count, v);
+ const VariableLocation &locationInfo = mState.mUniformLocations[location];
+ GLsizei clampedCount = clampUniformCount(locationInfo, count, 2, v);
+ mProgram->setUniform2iv(location, clampedCount, v);
}
void Program::setUniform3iv(GLint location, GLsizei count, const GLint *v)
{
- setUniformInternal(location, count * 3, v);
- mProgram->setUniform3iv(location, count, v);
+ const VariableLocation &locationInfo = mState.mUniformLocations[location];
+ GLsizei clampedCount = clampUniformCount(locationInfo, count, 3, v);
+ mProgram->setUniform3iv(location, clampedCount, v);
}
void Program::setUniform4iv(GLint location, GLsizei count, const GLint *v)
{
- setUniformInternal(location, count * 4, v);
- mProgram->setUniform4iv(location, count, v);
+ const VariableLocation &locationInfo = mState.mUniformLocations[location];
+ GLsizei clampedCount = clampUniformCount(locationInfo, count, 4, v);
+ mProgram->setUniform4iv(location, clampedCount, v);
}
void Program::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
{
- setUniformInternal(location, count * 1, v);
- mProgram->setUniform1uiv(location, count, v);
+ const VariableLocation &locationInfo = mState.mUniformLocations[location];
+ GLsizei clampedCount = clampUniformCount(locationInfo, count, 1, v);
+ mProgram->setUniform1uiv(location, clampedCount, v);
}
void Program::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
{
- setUniformInternal(location, count * 2, v);
- mProgram->setUniform2uiv(location, count, v);
+ const VariableLocation &locationInfo = mState.mUniformLocations[location];
+ GLsizei clampedCount = clampUniformCount(locationInfo, count, 2, v);
+ mProgram->setUniform2uiv(location, clampedCount, v);
}
void Program::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
{
- setUniformInternal(location, count * 3, v);
- mProgram->setUniform3uiv(location, count, v);
+ const VariableLocation &locationInfo = mState.mUniformLocations[location];
+ GLsizei clampedCount = clampUniformCount(locationInfo, count, 3, v);
+ mProgram->setUniform3uiv(location, clampedCount, v);
}
void Program::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
{
- setUniformInternal(location, count * 4, v);
- mProgram->setUniform4uiv(location, count, v);
+ const VariableLocation &locationInfo = mState.mUniformLocations[location];
+ GLsizei clampedCount = clampUniformCount(locationInfo, count, 4, v);
+ mProgram->setUniform4uiv(location, clampedCount, v);
}
void Program::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
{
- setMatrixUniformInternal<2, 2>(location, count, transpose, v);
- mProgram->setUniformMatrix2fv(location, count, transpose, v);
+ GLsizei clampedCount = clampMatrixUniformCount<2, 2>(location, count, transpose, v);
+ mProgram->setUniformMatrix2fv(location, clampedCount, transpose, v);
}
void Program::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
{
- setMatrixUniformInternal<3, 3>(location, count, transpose, v);
- mProgram->setUniformMatrix3fv(location, count, transpose, v);
+ GLsizei clampedCount = clampMatrixUniformCount<3, 3>(location, count, transpose, v);
+ mProgram->setUniformMatrix3fv(location, clampedCount, transpose, v);
}
void Program::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
{
- setMatrixUniformInternal<4, 4>(location, count, transpose, v);
- mProgram->setUniformMatrix4fv(location, count, transpose, v);
+ GLsizei clampedCount = clampMatrixUniformCount<4, 4>(location, count, transpose, v);
+ mProgram->setUniformMatrix4fv(location, clampedCount, transpose, v);
}
void Program::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
{
- setMatrixUniformInternal<2, 3>(location, count, transpose, v);
- mProgram->setUniformMatrix2x3fv(location, count, transpose, v);
+ GLsizei clampedCount = clampMatrixUniformCount<2, 3>(location, count, transpose, v);
+ mProgram->setUniformMatrix2x3fv(location, clampedCount, transpose, v);
}
void Program::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
{
- setMatrixUniformInternal<2, 4>(location, count, transpose, v);
- mProgram->setUniformMatrix2x4fv(location, count, transpose, v);
+ GLsizei clampedCount = clampMatrixUniformCount<2, 4>(location, count, transpose, v);
+ mProgram->setUniformMatrix2x4fv(location, clampedCount, transpose, v);
}
void Program::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
{
- setMatrixUniformInternal<3, 2>(location, count, transpose, v);
- mProgram->setUniformMatrix3x2fv(location, count, transpose, v);
+ GLsizei clampedCount = clampMatrixUniformCount<3, 2>(location, count, transpose, v);
+ mProgram->setUniformMatrix3x2fv(location, clampedCount, transpose, v);
}
void Program::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
{
- setMatrixUniformInternal<3, 4>(location, count, transpose, v);
- mProgram->setUniformMatrix3x4fv(location, count, transpose, v);
+ GLsizei clampedCount = clampMatrixUniformCount<3, 4>(location, count, transpose, v);
+ mProgram->setUniformMatrix3x4fv(location, clampedCount, transpose, v);
}
void Program::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
{
- setMatrixUniformInternal<4, 2>(location, count, transpose, v);
- mProgram->setUniformMatrix4x2fv(location, count, transpose, v);
+ GLsizei clampedCount = clampMatrixUniformCount<4, 2>(location, count, transpose, v);
+ mProgram->setUniformMatrix4x2fv(location, clampedCount, transpose, v);
}
void Program::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
{
- setMatrixUniformInternal<4, 3>(location, count, transpose, v);
- mProgram->setUniformMatrix4x3fv(location, count, transpose, v);
+ GLsizei clampedCount = clampMatrixUniformCount<4, 3>(location, count, transpose, v);
+ mProgram->setUniformMatrix4x3fv(location, clampedCount, transpose, v);
}
-void Program::getUniformfv(GLint location, GLfloat *v) const
+void Program::getUniformfv(const Context *context, GLint location, GLfloat *v) const
{
- getUniformInternal(location, v);
+ const auto &uniformLocation = mState.getUniformLocations()[location];
+ const auto &uniform = mState.getUniforms()[uniformLocation.index];
+
+ GLenum nativeType = gl::VariableComponentType(uniform.type);
+ if (nativeType == GL_FLOAT)
+ {
+ mProgram->getUniformfv(context, location, v);
+ }
+ else
+ {
+ getUniformInternal(context, v, location, nativeType,
+ gl::VariableComponentCount(uniform.type));
+ }
}
-void Program::getUniformiv(GLint location, GLint *v) const
+void Program::getUniformiv(const Context *context, GLint location, GLint *v) const
{
- getUniformInternal(location, v);
+ const auto &uniformLocation = mState.getUniformLocations()[location];
+ const auto &uniform = mState.getUniforms()[uniformLocation.index];
+
+ GLenum nativeType = gl::VariableComponentType(uniform.type);
+ if (nativeType == GL_INT || nativeType == GL_BOOL)
+ {
+ mProgram->getUniformiv(context, location, v);
+ }
+ else
+ {
+ getUniformInternal(context, v, location, nativeType,
+ gl::VariableComponentCount(uniform.type));
+ }
}
-void Program::getUniformuiv(GLint location, GLuint *v) const
+void Program::getUniformuiv(const Context *context, GLint location, GLuint *v) const
{
- getUniformInternal(location, v);
+ const auto &uniformLocation = mState.getUniformLocations()[location];
+ const auto &uniform = mState.getUniforms()[uniformLocation.index];
+
+ GLenum nativeType = gl::VariableComponentType(uniform.type);
+ if (nativeType == GL_UNSIGNED_INT)
+ {
+ mProgram->getUniformuiv(context, location, v);
+ }
+ else
+ {
+ getUniformInternal(context, v, location, nativeType,
+ gl::VariableComponentCount(uniform.type));
+ }
}
void Program::flagForDeletion()
@@ -1291,7 +1716,7 @@ void Program::validate(const Caps &caps)
if (mLinked)
{
- mValidated = (mProgram->validate(caps, &mInfoLog) == GL_TRUE);
+ mValidated = ConvertToBool(mProgram->validate(caps, &mInfoLog));
}
else
{
@@ -1320,22 +1745,15 @@ bool Program::validateSamplers(InfoLog *infoLog, const Caps &caps)
// if any two active samplers in a program are of different types, but refer to the same
// texture image unit, and this is the current program, then ValidateProgram will fail, and
// DrawArrays and DrawElements will issue the INVALID_OPERATION error.
- for (unsigned int samplerIndex = mSamplerUniformRange.start;
- samplerIndex < mSamplerUniformRange.end; ++samplerIndex)
+ for (const auto &samplerBinding : mState.mSamplerBindings)
{
- const LinkedUniform &uniform = mData.mUniforms[samplerIndex];
- ASSERT(uniform.isSampler());
-
- if (!uniform.staticUse)
+ if (samplerBinding.unreferenced)
continue;
- const GLuint *dataPtr = reinterpret_cast<const GLuint *>(uniform.getDataPtrToElement(0));
- GLenum textureType = SamplerTypeToTextureType(uniform.type);
+ GLenum textureType = samplerBinding.textureType;
- for (unsigned int arrayElement = 0; arrayElement < uniform.elementCount(); ++arrayElement)
+ for (GLuint textureUnit : samplerBinding.boundTextureUnits)
{
- GLuint textureUnit = dataPtr[arrayElement];
-
if (textureUnit >= caps.maxCombinedTextureImageUnits)
{
if (infoLog)
@@ -1382,70 +1800,34 @@ bool Program::isValidated() const
GLuint Program::getActiveUniformBlockCount() const
{
- return static_cast<GLuint>(mData.mUniformBlocks.size());
+ return static_cast<GLuint>(mState.mUniformBlocks.size());
}
-void Program::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const
+GLuint Program::getActiveAtomicCounterBufferCount() const
{
- ASSERT(uniformBlockIndex <
- mData.mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount()
-
- const UniformBlock &uniformBlock = mData.mUniformBlocks[uniformBlockIndex];
-
- if (bufSize > 0)
- {
- std::string string = uniformBlock.name;
-
- if (uniformBlock.isArray)
- {
- string += ArrayString(uniformBlock.arrayElement);
- }
-
- strncpy(uniformBlockName, string.c_str(), bufSize);
- uniformBlockName[bufSize - 1] = '\0';
+ return static_cast<GLuint>(mState.mAtomicCounterBuffers.size());
+}
- if (length)
- {
- *length = static_cast<GLsizei>(strlen(uniformBlockName));
- }
- }
+GLuint Program::getActiveShaderStorageBlockCount() const
+{
+ return static_cast<GLuint>(mState.mShaderStorageBlocks.size());
}
-void Program::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const
+void Program::getActiveUniformBlockName(const GLuint blockIndex,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *blockName) const
{
- ASSERT(uniformBlockIndex <
- mData.mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount()
+ GetInterfaceBlockName(blockIndex, mState.mUniformBlocks, bufSize, length, blockName);
+}
- const UniformBlock &uniformBlock = mData.mUniformBlocks[uniformBlockIndex];
+void Program::getActiveShaderStorageBlockName(const GLuint blockIndex,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *blockName) const
+{
- switch (pname)
- {
- case GL_UNIFORM_BLOCK_DATA_SIZE:
- *params = static_cast<GLint>(uniformBlock.dataSize);
- break;
- case GL_UNIFORM_BLOCK_NAME_LENGTH:
- *params =
- static_cast<GLint>(uniformBlock.name.size() + 1 + (uniformBlock.isArray ? 3 : 0));
- break;
- case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
- *params = static_cast<GLint>(uniformBlock.memberUniformIndexes.size());
- break;
- case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
- {
- for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++)
- {
- params[blockMemberIndex] = static_cast<GLint>(uniformBlock.memberUniformIndexes[blockMemberIndex]);
- }
- }
- break;
- case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
- *params = static_cast<GLint>(uniformBlock.vertexStaticUse);
- break;
- case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
- *params = static_cast<GLint>(uniformBlock.fragmentStaticUse);
- break;
- default: UNREACHABLE();
- }
+ GetInterfaceBlockName(blockIndex, mState.mShaderStorageBlocks, bufSize, length, blockName);
}
GLint Program::getActiveUniformBlockMaxLength() const
@@ -1454,18 +1836,14 @@ GLint Program::getActiveUniformBlockMaxLength() const
if (mLinked)
{
- unsigned int numUniformBlocks = static_cast<unsigned int>(mData.mUniformBlocks.size());
+ unsigned int numUniformBlocks = static_cast<unsigned int>(mState.mUniformBlocks.size());
for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++)
{
- const UniformBlock &uniformBlock = mData.mUniformBlocks[uniformBlockIndex];
+ const InterfaceBlock &uniformBlock = mState.mUniformBlocks[uniformBlockIndex];
if (!uniformBlock.name.empty())
{
- const int length = static_cast<int>(uniformBlock.name.length()) + 1;
-
- // Counting in "[0]".
- const int arrayLength = (uniformBlock.isArray ? 3 : 0);
-
- maxLength = std::max(length + arrayLength, maxLength);
+ int length = static_cast<int>(uniformBlock.nameWithArrayIndex().length());
+ maxLength = std::max(length + 1, maxLength);
}
}
}
@@ -1475,87 +1853,77 @@ GLint Program::getActiveUniformBlockMaxLength() const
GLuint Program::getUniformBlockIndex(const std::string &name) const
{
- size_t subscript = GL_INVALID_INDEX;
- std::string baseName = gl::ParseUniformName(name, &subscript);
+ return GetInterfaceBlockIndex(mState.mUniformBlocks, name);
+}
- unsigned int numUniformBlocks = static_cast<unsigned int>(mData.mUniformBlocks.size());
- for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++)
- {
- const gl::UniformBlock &uniformBlock = mData.mUniformBlocks[blockIndex];
- if (uniformBlock.name == baseName)
- {
- const bool arrayElementZero =
- (subscript == GL_INVALID_INDEX &&
- (!uniformBlock.isArray || uniformBlock.arrayElement == 0));
- if (subscript == uniformBlock.arrayElement || arrayElementZero)
- {
- return blockIndex;
- }
- }
- }
+GLuint Program::getShaderStorageBlockIndex(const std::string &name) const
+{
+ return GetInterfaceBlockIndex(mState.mShaderStorageBlocks, name);
+}
- return GL_INVALID_INDEX;
+const InterfaceBlock &Program::getUniformBlockByIndex(GLuint index) const
+{
+ ASSERT(index < static_cast<GLuint>(mState.mUniformBlocks.size()));
+ return mState.mUniformBlocks[index];
}
-const UniformBlock &Program::getUniformBlockByIndex(GLuint index) const
+const InterfaceBlock &Program::getShaderStorageBlockByIndex(GLuint index) const
{
- ASSERT(index < static_cast<GLuint>(mData.mUniformBlocks.size()));
- return mData.mUniformBlocks[index];
+ ASSERT(index < static_cast<GLuint>(mState.mShaderStorageBlocks.size()));
+ return mState.mShaderStorageBlocks[index];
}
void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
{
- mData.mUniformBlockBindings[uniformBlockIndex] = uniformBlockBinding;
+ mState.mUniformBlocks[uniformBlockIndex].binding = uniformBlockBinding;
+ mState.mActiveUniformBlockBindings.set(uniformBlockIndex, uniformBlockBinding != 0);
mProgram->setUniformBlockBinding(uniformBlockIndex, uniformBlockBinding);
}
GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
{
- return mData.getUniformBlockBinding(uniformBlockIndex);
+ return mState.getUniformBlockBinding(uniformBlockIndex);
}
-void Program::resetUniformBlockBindings()
+GLuint Program::getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const
{
- for (unsigned int blockId = 0; blockId < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; blockId++)
- {
- mData.mUniformBlockBindings[blockId] = 0;
- }
- mData.mActiveUniformBlockBindings.reset();
+ return mState.getShaderStorageBlockBinding(shaderStorageBlockIndex);
}
void Program::setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode)
{
- mData.mTransformFeedbackVaryingNames.resize(count);
+ mState.mTransformFeedbackVaryingNames.resize(count);
for (GLsizei i = 0; i < count; i++)
{
- mData.mTransformFeedbackVaryingNames[i] = varyings[i];
+ mState.mTransformFeedbackVaryingNames[i] = varyings[i];
}
- mData.mTransformFeedbackBufferMode = bufferMode;
+ mState.mTransformFeedbackBufferMode = bufferMode;
}
void Program::getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const
{
if (mLinked)
{
- ASSERT(index < mData.mTransformFeedbackVaryingVars.size());
- const sh::Varying &varying = mData.mTransformFeedbackVaryingVars[index];
- GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varying.name.length()));
+ ASSERT(index < mState.mLinkedTransformFeedbackVaryings.size());
+ const auto &var = mState.mLinkedTransformFeedbackVaryings[index];
+ std::string varName = var.nameWithArrayIndex();
+ GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varName.length()));
if (length)
{
*length = lastNameIdx;
}
if (size)
{
- *size = varying.elementCount();
+ *size = var.size();
}
if (type)
{
- *type = varying.type;
+ *type = var.type;
}
if (name)
{
- memcpy(name, varying.name.c_str(), lastNameIdx);
+ memcpy(name, varName.c_str(), lastNameIdx);
name[lastNameIdx] = '\0';
}
}
@@ -1565,7 +1933,7 @@ GLsizei Program::getTransformFeedbackVaryingCount() const
{
if (mLinked)
{
- return static_cast<GLsizei>(mData.mTransformFeedbackVaryingVars.size());
+ return static_cast<GLsizei>(mState.mLinkedTransformFeedbackVaryings.size());
}
else
{
@@ -1578,9 +1946,10 @@ GLsizei Program::getTransformFeedbackVaryingMaxLength() const
if (mLinked)
{
GLsizei maxSize = 0;
- for (const sh::Varying &varying : mData.mTransformFeedbackVaryingVars)
+ for (const auto &var : mState.mLinkedTransformFeedbackVaryings)
{
- maxSize = std::max(maxSize, static_cast<GLsizei>(varying.name.length() + 1));
+ maxSize =
+ std::max(maxSize, static_cast<GLsizei>(var.nameWithArrayIndex().length() + 1));
}
return maxSize;
@@ -1593,16 +1962,20 @@ GLsizei Program::getTransformFeedbackVaryingMaxLength() const
GLenum Program::getTransformFeedbackBufferMode() const
{
- return mData.mTransformFeedbackBufferMode;
+ return mState.mTransformFeedbackBufferMode;
}
-// static
-bool Program::linkVaryings(InfoLog &infoLog,
- const Shader *vertexShader,
- const Shader *fragmentShader)
+bool Program::linkVaryings(const Context *context, InfoLog &infoLog) const
{
- const std::vector<sh::Varying> &vertexVaryings = vertexShader->getVaryings();
- const std::vector<sh::Varying> &fragmentVaryings = fragmentShader->getVaryings();
+ Shader *vertexShader = mState.mAttachedVertexShader;
+ Shader *fragmentShader = mState.mAttachedFragmentShader;
+
+ ASSERT(vertexShader->getShaderVersion(context) == fragmentShader->getShaderVersion(context));
+
+ const std::vector<sh::Varying> &vertexVaryings = vertexShader->getOutputVaryings(context);
+ const std::vector<sh::Varying> &fragmentVaryings = fragmentShader->getInputVaryings(context);
+
+ std::map<GLuint, std::string> staticFragmentInputLocations;
for (const sh::Varying &output : fragmentVaryings)
{
@@ -1619,7 +1992,8 @@ bool Program::linkVaryings(InfoLog &infoLog,
if (output.name == input.name)
{
ASSERT(!input.isBuiltIn());
- if (!linkValidateVaryings(infoLog, output.name, input, output))
+ if (!linkValidateVaryings(infoLog, output.name, input, output,
+ vertexShader->getShaderVersion(context)))
{
return false;
}
@@ -1635,6 +2009,34 @@ bool Program::linkVaryings(InfoLog &infoLog,
infoLog << "Fragment varying " << output.name << " does not match any vertex varying";
return false;
}
+
+ // Check for aliased path rendering input bindings (if any).
+ // If more than one binding refer statically to the same
+ // location the link must fail.
+
+ if (!output.staticUse)
+ continue;
+
+ const auto inputBinding = mFragmentInputBindings.getBinding(output.name);
+ if (inputBinding == -1)
+ continue;
+
+ const auto it = staticFragmentInputLocations.find(inputBinding);
+ if (it == std::end(staticFragmentInputLocations))
+ {
+ staticFragmentInputLocations.insert(std::make_pair(inputBinding, output.name));
+ }
+ else
+ {
+ infoLog << "Binding for fragment input " << output.name << " conflicts with "
+ << it->second;
+ return false;
+ }
+ }
+
+ if (!linkValidateBuiltInVaryings(context, infoLog))
+ {
+ return false;
}
// TODO(jmadill): verify no unmatched vertex varyings?
@@ -1642,67 +2044,135 @@ bool Program::linkVaryings(InfoLog &infoLog,
return true;
}
-bool Program::linkUniforms(gl::InfoLog &infoLog, const gl::Caps &caps)
+bool Program::linkUniforms(const Context *context,
+ InfoLog &infoLog,
+ const Bindings &uniformLocationBindings)
{
- const std::vector<sh::Uniform> &vertexUniforms = mData.mAttachedVertexShader->getUniforms();
- const std::vector<sh::Uniform> &fragmentUniforms = mData.mAttachedFragmentShader->getUniforms();
+ UniformLinker linker(mState);
+ if (!linker.link(context, infoLog, uniformLocationBindings))
+ {
+ return false;
+ }
+
+ linker.getResults(&mState.mUniforms, &mState.mUniformLocations);
- // Check that uniforms defined in the vertex and fragment shaders are identical
- std::map<std::string, LinkedUniform> linkedUniforms;
+ linkSamplerAndImageBindings();
- for (const sh::Uniform &vertexUniform : vertexUniforms)
+ if (!linkAtomicCounterBuffers())
{
- linkedUniforms[vertexUniform.name] = LinkedUniform(vertexUniform);
+ return false;
}
- for (const sh::Uniform &fragmentUniform : fragmentUniforms)
+ return true;
+}
+
+void Program::linkSamplerAndImageBindings()
+{
+ unsigned int high = static_cast<unsigned int>(mState.mUniforms.size());
+ unsigned int low = high;
+
+ for (auto counterIter = mState.mUniforms.rbegin();
+ counterIter != mState.mUniforms.rend() && counterIter->isAtomicCounter(); ++counterIter)
{
- auto entry = linkedUniforms.find(fragmentUniform.name);
- if (entry != linkedUniforms.end())
+ --low;
+ }
+
+ mState.mAtomicCounterUniformRange = RangeUI(low, high);
+
+ high = low;
+
+ for (auto imageIter = mState.mUniforms.rbegin();
+ imageIter != mState.mUniforms.rend() && imageIter->isImage(); ++imageIter)
+ {
+ --low;
+ }
+
+ mState.mImageUniformRange = RangeUI(low, high);
+
+ // If uniform is a image type, insert it into the mImageBindings array.
+ for (unsigned int imageIndex : mState.mImageUniformRange)
+ {
+ // ES3.1 (section 7.6.1) and GLSL ES3.1 (section 4.4.5), Uniform*i{v} commands
+ // cannot load values into a uniform defined as an image. if declare without a
+ // binding qualifier, any uniform image variable (include all elements of
+ // unbound image array) shoud be bound to unit zero.
+ auto &imageUniform = mState.mUniforms[imageIndex];
+ if (imageUniform.binding == -1)
{
- LinkedUniform *vertexUniform = &entry->second;
- const std::string &uniformName = "uniform '" + vertexUniform->name + "'";
- if (!linkValidateUniforms(infoLog, uniformName, *vertexUniform, fragmentUniform))
- {
- return false;
- }
+ mState.mImageBindings.emplace_back(
+ ImageBinding(imageUniform.getBasicTypeElementCount()));
+ }
+ else
+ {
+ mState.mImageBindings.emplace_back(
+ ImageBinding(imageUniform.binding, imageUniform.getBasicTypeElementCount()));
}
}
- // Flatten the uniforms list (nested fields) into a simple list (no nesting).
- // Also check the maximum uniform vector and sampler counts.
- if (!flattenUniformsAndCheckCaps(caps, infoLog))
+ high = low;
+
+ for (auto samplerIter = mState.mUniforms.rbegin() + mState.mImageUniformRange.length();
+ samplerIter != mState.mUniforms.rend() && samplerIter->isSampler(); ++samplerIter)
{
- return false;
+ --low;
}
- indexUniforms();
+ mState.mSamplerUniformRange = RangeUI(low, high);
- return true;
+ // If uniform is a sampler type, insert it into the mSamplerBindings array.
+ for (unsigned int samplerIndex : mState.mSamplerUniformRange)
+ {
+ const auto &samplerUniform = mState.mUniforms[samplerIndex];
+ GLenum textureType = SamplerTypeToTextureType(samplerUniform.type);
+ mState.mSamplerBindings.emplace_back(
+ SamplerBinding(textureType, samplerUniform.getBasicTypeElementCount(), false));
+ }
}
-void Program::indexUniforms()
+bool Program::linkAtomicCounterBuffers()
{
- for (size_t uniformIndex = 0; uniformIndex < mData.mUniforms.size(); uniformIndex++)
+ for (unsigned int index : mState.mAtomicCounterUniformRange)
{
- const gl::LinkedUniform &uniform = mData.mUniforms[uniformIndex];
-
- for (unsigned int arrayIndex = 0; arrayIndex < uniform.elementCount(); arrayIndex++)
+ auto &uniform = mState.mUniforms[index];
+ bool found = false;
+ for (unsigned int bufferIndex = 0; bufferIndex < mState.mAtomicCounterBuffers.size();
+ ++bufferIndex)
{
- if (!uniform.isBuiltIn())
+ auto &buffer = mState.mAtomicCounterBuffers[bufferIndex];
+ if (buffer.binding == uniform.binding)
{
- // Assign in-order uniform locations
- mData.mUniformLocations.push_back(gl::VariableLocation(
- uniform.name, arrayIndex, static_cast<unsigned int>(uniformIndex)));
+ buffer.memberIndexes.push_back(index);
+ uniform.bufferIndex = bufferIndex;
+ found = true;
+ buffer.unionReferencesWith(uniform);
+ break;
}
}
+ if (!found)
+ {
+ AtomicCounterBuffer atomicCounterBuffer;
+ atomicCounterBuffer.binding = uniform.binding;
+ atomicCounterBuffer.memberIndexes.push_back(index);
+ atomicCounterBuffer.unionReferencesWith(uniform);
+ mState.mAtomicCounterBuffers.push_back(atomicCounterBuffer);
+ uniform.bufferIndex = static_cast<int>(mState.mAtomicCounterBuffers.size() - 1);
+ }
}
+ // TODO(jie.a.chen@intel.com): Count each atomic counter buffer to validate against
+ // gl_Max[Vertex|Fragment|Compute|Combined]AtomicCounterBuffers.
+
+ return true;
}
-bool Program::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform)
+bool Program::linkValidateInterfaceBlockFields(InfoLog &infoLog,
+ const std::string &uniformName,
+ const sh::InterfaceBlockField &vertexUniform,
+ const sh::InterfaceBlockField &fragmentUniform,
+ bool webglCompatibility)
{
- // We don't validate precision on UBO fields. See resolution of Khronos bug 10287.
- if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, false))
+ // If webgl, validate precision of UBO fields, otherwise don't. See Khronos bug 10287.
+ if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform,
+ webglCompatibility))
{
return false;
}
@@ -1716,32 +2186,34 @@ bool Program::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::stri
return true;
}
-// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
-bool Program::linkAttributes(const gl::Data &data,
- InfoLog &infoLog,
- const AttributeBindings &attributeBindings,
- const Shader *vertexShader)
+// Assigns locations to all attributes from the bindings and program locations.
+bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
{
+ const ContextState &data = context->getContextState();
+ auto *vertexShader = mState.getAttachedVertexShader();
+
unsigned int usedLocations = 0;
- mData.mAttributes = vertexShader->getActiveAttributes();
- GLuint maxAttribs = data.caps->maxVertexAttributes;
+ mState.mAttributes = vertexShader->getActiveAttributes(context);
+ GLuint maxAttribs = data.getCaps().maxVertexAttributes;
// TODO(jmadill): handle aliasing robustly
- if (mData.mAttributes.size() > maxAttribs)
+ if (mState.mAttributes.size() > maxAttribs)
{
infoLog << "Too many vertex attributes.";
return false;
}
- std::vector<sh::Attribute *> usedAttribMap(data.caps->maxVertexAttributes, nullptr);
+ std::vector<sh::Attribute *> usedAttribMap(maxAttribs, nullptr);
// Link attributes that have a binding location
- for (sh::Attribute &attribute : mData.mAttributes)
+ for (sh::Attribute &attribute : mState.mAttributes)
{
- // TODO(jmadill): do staticUse filtering step here, or not at all
- ASSERT(attribute.staticUse);
+ // GLSL ES 3.10 January 2016 section 4.3.4: Vertex shader inputs can't be arrays or
+ // structures, so we don't need to worry about adjusting their names or generating entries
+ // for each member/element (unlike uniforms for example).
+ ASSERT(!attribute.isArray() && !attribute.isStruct());
- int bindingLocation = attributeBindings.getAttributeBinding(attribute.name);
+ int bindingLocation = mAttributeBindings.getBinding(attribute.name);
if (attribute.location == -1 && bindingLocation != -1)
{
attribute.location = bindingLocation;
@@ -1788,10 +2260,8 @@ bool Program::linkAttributes(const gl::Data &data,
}
// Link attributes that don't have a binding location
- for (sh::Attribute &attribute : mData.mAttributes)
+ for (sh::Attribute &attribute : mState.mAttributes)
{
- ASSERT(attribute.staticUse);
-
// Not set by glBindAttribLocation or by location layout qualifier
if (attribute.location == -1)
{
@@ -1808,82 +2278,150 @@ bool Program::linkAttributes(const gl::Data &data,
}
}
- for (const sh::Attribute &attribute : mData.mAttributes)
+ for (const sh::Attribute &attribute : mState.mAttributes)
{
- ASSERT(attribute.staticUse);
ASSERT(attribute.location != -1);
- int regs = VariableRegisterCount(attribute.type);
+ unsigned int regs = static_cast<unsigned int>(VariableRegisterCount(attribute.type));
- for (int r = 0; r < regs; r++)
+ for (unsigned int r = 0; r < regs; r++)
{
- mData.mActiveAttribLocationsMask.set(attribute.location + r);
+ unsigned int location = static_cast<unsigned int>(attribute.location) + r;
+ mState.mActiveAttribLocationsMask.set(location);
+ mState.mMaxActiveAttribLocation =
+ std::max(mState.mMaxActiveAttribLocation, location + 1);
}
}
return true;
}
-bool Program::linkUniformBlocks(InfoLog &infoLog, const Caps &caps)
+bool Program::validateVertexAndFragmentInterfaceBlocks(
+ const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks,
+ const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks,
+ InfoLog &infoLog,
+ bool webglCompatibility) const
{
- const Shader &vertexShader = *mData.mAttachedVertexShader;
- const Shader &fragmentShader = *mData.mAttachedFragmentShader;
-
- const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks = vertexShader.getInterfaceBlocks();
- const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks = fragmentShader.getInterfaceBlocks();
-
// Check that interface blocks defined in the vertex and fragment shaders are identical
- typedef std::map<std::string, const sh::InterfaceBlock*> UniformBlockMap;
- UniformBlockMap linkedUniformBlocks;
+ typedef std::map<std::string, const sh::InterfaceBlock *> InterfaceBlockMap;
+ InterfaceBlockMap linkedInterfaceBlocks;
- GLuint vertexBlockCount = 0;
for (const sh::InterfaceBlock &vertexInterfaceBlock : vertexInterfaceBlocks)
{
- linkedUniformBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock;
+ linkedInterfaceBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock;
+ }
- // Note: shared and std140 layouts are always considered active
- if (vertexInterfaceBlock.staticUse || vertexInterfaceBlock.layout != sh::BLOCKLAYOUT_PACKED)
+ for (const sh::InterfaceBlock &fragmentInterfaceBlock : fragmentInterfaceBlocks)
+ {
+ auto entry = linkedInterfaceBlocks.find(fragmentInterfaceBlock.name);
+ if (entry != linkedInterfaceBlocks.end())
{
- if (++vertexBlockCount > caps.maxVertexUniformBlocks)
+ const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second;
+ if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock,
+ webglCompatibility))
{
- infoLog << "Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS ("
- << caps.maxVertexUniformBlocks << ")";
return false;
}
}
+ // TODO(jiajia.qin@intel.com): Add
+ // MAX_COMBINED_UNIFORM_BLOCKS/MAX_COMBINED_SHADER_STORAGE_BLOCKS validation.
}
+ return true;
+}
- GLuint fragmentBlockCount = 0;
- for (const sh::InterfaceBlock &fragmentInterfaceBlock : fragmentInterfaceBlocks)
+bool Program::linkInterfaceBlocks(const Context *context, InfoLog &infoLog)
+{
+ const auto &caps = context->getCaps();
+
+ if (mState.mAttachedComputeShader)
{
- auto entry = linkedUniformBlocks.find(fragmentInterfaceBlock.name);
- if (entry != linkedUniformBlocks.end())
+ Shader &computeShader = *mState.mAttachedComputeShader;
+ const auto &computeUniformBlocks = computeShader.getUniformBlocks(context);
+
+ if (!validateInterfaceBlocksCount(
+ caps.maxComputeUniformBlocks, computeUniformBlocks,
+ "Compute shader uniform block count exceeds GL_MAX_COMPUTE_UNIFORM_BLOCKS (",
+ infoLog))
{
- const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second;
- if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock))
- {
- return false;
- }
+ return false;
}
- // Note: shared and std140 layouts are always considered active
- if (fragmentInterfaceBlock.staticUse ||
- fragmentInterfaceBlock.layout != sh::BLOCKLAYOUT_PACKED)
+ const auto &computeShaderStorageBlocks = computeShader.getShaderStorageBlocks(context);
+ if (!validateInterfaceBlocksCount(caps.maxComputeShaderStorageBlocks,
+ computeShaderStorageBlocks,
+ "Compute shader shader storage block count exceeds "
+ "GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS (",
+ infoLog))
{
- if (++fragmentBlockCount > caps.maxFragmentUniformBlocks)
- {
- infoLog
- << "Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS ("
- << caps.maxFragmentUniformBlocks << ")";
- return false;
- }
+ return false;
}
+ return true;
}
+ Shader &vertexShader = *mState.mAttachedVertexShader;
+ Shader &fragmentShader = *mState.mAttachedFragmentShader;
+
+ const auto &vertexUniformBlocks = vertexShader.getUniformBlocks(context);
+ const auto &fragmentUniformBlocks = fragmentShader.getUniformBlocks(context);
+
+ if (!validateInterfaceBlocksCount(
+ caps.maxVertexUniformBlocks, vertexUniformBlocks,
+ "Vertex shader uniform block count exceeds GL_MAX_VERTEX_UNIFORM_BLOCKS (", infoLog))
+ {
+ return false;
+ }
+ if (!validateInterfaceBlocksCount(
+ caps.maxFragmentUniformBlocks, fragmentUniformBlocks,
+ "Fragment shader uniform block count exceeds GL_MAX_FRAGMENT_UNIFORM_BLOCKS (",
+ infoLog))
+ {
+
+ return false;
+ }
+
+ bool webglCompatibility = context->getExtensions().webglCompatibility;
+ if (!validateVertexAndFragmentInterfaceBlocks(vertexUniformBlocks, fragmentUniformBlocks,
+ infoLog, webglCompatibility))
+ {
+ return false;
+ }
+
+ if (context->getClientVersion() >= Version(3, 1))
+ {
+ const auto &vertexShaderStorageBlocks = vertexShader.getShaderStorageBlocks(context);
+ const auto &fragmentShaderStorageBlocks = fragmentShader.getShaderStorageBlocks(context);
+
+ if (!validateInterfaceBlocksCount(caps.maxVertexShaderStorageBlocks,
+ vertexShaderStorageBlocks,
+ "Vertex shader shader storage block count exceeds "
+ "GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS (",
+ infoLog))
+ {
+ return false;
+ }
+ if (!validateInterfaceBlocksCount(caps.maxFragmentShaderStorageBlocks,
+ fragmentShaderStorageBlocks,
+ "Fragment shader shader storage block count exceeds "
+ "GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS (",
+ infoLog))
+ {
+
+ return false;
+ }
+
+ if (!validateVertexAndFragmentInterfaceBlocks(vertexShaderStorageBlocks,
+ fragmentShaderStorageBlocks, infoLog,
+ webglCompatibility))
+ {
+ return false;
+ }
+ }
return true;
}
-bool Program::areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock,
- const sh::InterfaceBlock &fragmentInterfaceBlock)
+bool Program::areMatchingInterfaceBlocks(InfoLog &infoLog,
+ const sh::InterfaceBlock &vertexInterfaceBlock,
+ const sh::InterfaceBlock &fragmentInterfaceBlock,
+ bool webglCompatibility) const
{
const char* blockName = vertexInterfaceBlock.name.c_str();
// validate blocks for the same member types
@@ -1899,7 +2437,9 @@ bool Program::areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::Interfa
<< "' between vertex and fragment shaders";
return false;
}
- if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout || vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout)
+ if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout ||
+ vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout ||
+ vertexInterfaceBlock.binding != fragmentInterfaceBlock.binding)
{
infoLog << "Layout qualifiers differ for interface block '" << blockName
<< "' between vertex and fragment shaders";
@@ -1920,7 +2460,8 @@ bool Program::areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::Interfa
return false;
}
std::string memberName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'";
- if (!linkValidateInterfaceBlockFields(infoLog, memberName, vertexMember, fragmentMember))
+ if (!linkValidateInterfaceBlockFields(infoLog, memberName, vertexMember, fragmentMember,
+ webglCompatibility))
{
return false;
}
@@ -1936,7 +2477,7 @@ bool Program::linkValidateVariablesBase(InfoLog &infoLog, const std::string &var
infoLog << "Types for " << variableName << " differ between vertex and fragment shaders";
return false;
}
- if (vertexVariable.arraySize != fragmentVariable.arraySize)
+ if (vertexVariable.arraySizes != fragmentVariable.arraySizes)
{
infoLog << "Array sizes for " << variableName << " differ between vertex and fragment shaders";
return false;
@@ -1946,6 +2487,12 @@ bool Program::linkValidateVariablesBase(InfoLog &infoLog, const std::string &var
infoLog << "Precisions for " << variableName << " differ between vertex and fragment shaders";
return false;
}
+ if (vertexVariable.structName != fragmentVariable.structName)
+ {
+ infoLog << "Structure names for " << variableName
+ << " differ between vertex and fragment shaders";
+ return false;
+ }
if (vertexVariable.fields.size() != fragmentVariable.fields.size())
{
@@ -1979,52 +2526,125 @@ bool Program::linkValidateVariablesBase(InfoLog &infoLog, const std::string &var
return true;
}
-bool Program::linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform)
+bool Program::linkValidateVaryings(InfoLog &infoLog,
+ const std::string &varyingName,
+ const sh::Varying &vertexVarying,
+ const sh::Varying &fragmentVarying,
+ int shaderVersion)
{
-#if ANGLE_PROGRAM_LINK_VALIDATE_UNIFORM_PRECISION == ANGLE_ENABLED
- const bool validatePrecision = true;
-#else
- const bool validatePrecision = false;
-#endif
+ if (!linkValidateVariablesBase(infoLog, varyingName, vertexVarying, fragmentVarying, false))
+ {
+ return false;
+ }
+
+ if (!sh::InterpolationTypesMatch(vertexVarying.interpolation, fragmentVarying.interpolation))
+ {
+ infoLog << "Interpolation types for " << varyingName
+ << " differ between vertex and fragment shaders.";
+ return false;
+ }
- if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, validatePrecision))
+ if (shaderVersion == 100 && vertexVarying.isInvariant != fragmentVarying.isInvariant)
{
+ infoLog << "Invariance for " << varyingName
+ << " differs between vertex and fragment shaders.";
return false;
}
return true;
}
-bool Program::linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying)
+bool Program::linkValidateBuiltInVaryings(const Context *context, InfoLog &infoLog) const
{
- if (!linkValidateVariablesBase(infoLog, varyingName, vertexVarying, fragmentVarying, false))
+ Shader *vertexShader = mState.mAttachedVertexShader;
+ Shader *fragmentShader = mState.mAttachedFragmentShader;
+ const auto &vertexVaryings = vertexShader->getOutputVaryings(context);
+ const auto &fragmentVaryings = fragmentShader->getInputVaryings(context);
+ int shaderVersion = vertexShader->getShaderVersion(context);
+
+ if (shaderVersion != 100)
{
- return false;
+ // Only ESSL 1.0 has restrictions on matching input and output invariance
+ return true;
}
- if (!sh::InterpolationTypesMatch(vertexVarying.interpolation, fragmentVarying.interpolation))
+ bool glPositionIsInvariant = false;
+ bool glPointSizeIsInvariant = false;
+ bool glFragCoordIsInvariant = false;
+ bool glPointCoordIsInvariant = false;
+
+ for (const sh::Varying &varying : vertexVaryings)
+ {
+ if (!varying.isBuiltIn())
+ {
+ continue;
+ }
+ if (varying.name.compare("gl_Position") == 0)
+ {
+ glPositionIsInvariant = varying.isInvariant;
+ }
+ else if (varying.name.compare("gl_PointSize") == 0)
+ {
+ glPointSizeIsInvariant = varying.isInvariant;
+ }
+ }
+
+ for (const sh::Varying &varying : fragmentVaryings)
+ {
+ if (!varying.isBuiltIn())
+ {
+ continue;
+ }
+ if (varying.name.compare("gl_FragCoord") == 0)
+ {
+ glFragCoordIsInvariant = varying.isInvariant;
+ }
+ else if (varying.name.compare("gl_PointCoord") == 0)
+ {
+ glPointCoordIsInvariant = varying.isInvariant;
+ }
+ }
+
+ // There is some ambiguity in ESSL 1.00.17 paragraph 4.6.4 interpretation,
+ // for example, https://cvs.khronos.org/bugzilla/show_bug.cgi?id=13842.
+ // Not requiring invariance to match is supported by:
+ // dEQP, WebGL CTS, Nexus 5X GLES
+ if (glFragCoordIsInvariant && !glPositionIsInvariant)
+ {
+ infoLog << "gl_FragCoord can only be declared invariant if and only if gl_Position is "
+ "declared invariant.";
+ return false;
+ }
+ if (glPointCoordIsInvariant && !glPointSizeIsInvariant)
{
- infoLog << "Interpolation types for " << varyingName << " differ between vertex and fragment shaders";
+ infoLog << "gl_PointCoord can only be declared invariant if and only if gl_PointSize is "
+ "declared invariant.";
return false;
}
return true;
}
-bool Program::linkValidateTransformFeedback(InfoLog &infoLog,
- const std::vector<const sh::Varying *> &varyings,
+bool Program::linkValidateTransformFeedback(const gl::Context *context,
+ InfoLog &infoLog,
+ const Program::MergedVaryings &varyings,
const Caps &caps) const
{
size_t totalComponents = 0;
std::set<std::string> uniqueNames;
- for (const std::string &tfVaryingName : mData.mTransformFeedbackVaryingNames)
+ for (const std::string &tfVaryingName : mState.mTransformFeedbackVaryingNames)
{
bool found = false;
- for (const sh::Varying *varying : varyings)
+ std::vector<unsigned int> subscripts;
+ std::string baseName = ParseResourceName(tfVaryingName, &subscripts);
+
+ for (const auto &ref : varyings)
{
- if (tfVaryingName == varying->name)
+ const sh::Varying *varying = ref.second.get();
+
+ if (baseName == varying->name)
{
if (uniqueNames.count(tfVaryingName) > 0)
{
@@ -2032,17 +2652,33 @@ bool Program::linkValidateTransformFeedback(InfoLog &infoLog,
<< tfVaryingName << ").";
return false;
}
- uniqueNames.insert(tfVaryingName);
-
- if (varying->isArray())
+ if (context->getClientVersion() >= Version(3, 1))
+ {
+ if (IncludeSameArrayElement(uniqueNames, tfVaryingName))
+ {
+ infoLog
+ << "Two transform feedback varyings include the same array element ("
+ << tfVaryingName << ").";
+ return false;
+ }
+ }
+ else if (varying->isArray())
{
infoLog << "Capture of arrays is undefined and not supported.";
return false;
}
+ uniqueNames.insert(tfVaryingName);
+
// TODO(jmadill): Investigate implementation limits on D3D11
- size_t componentCount = gl::VariableComponentCount(varying->type);
- if (mData.mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
+
+ // GLSL ES 3.10 section 4.3.6: A vertex output can't be an array of arrays.
+ ASSERT(!varying->isArrayOfArrays());
+ size_t elementCount =
+ ((varying->isArray() && subscripts.empty()) ? varying->getOutermostArraySize()
+ : 1);
+ size_t componentCount = VariableComponentCount(varying->type) * elementCount;
+ if (mState.mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
componentCount > caps.maxTransformFeedbackSeparateComponents)
{
infoLog << "Transform feedback varying's " << varying->name << " components ("
@@ -2056,19 +2692,21 @@ bool Program::linkValidateTransformFeedback(InfoLog &infoLog,
break;
}
}
-
- if (tfVaryingName.find('[') != std::string::npos)
+ if (context->getClientVersion() < Version(3, 1) &&
+ tfVaryingName.find('[') != std::string::npos)
{
infoLog << "Capture of array elements is undefined and not supported.";
return false;
}
-
- // All transform feedback varyings are expected to exist since packVaryings checks for them.
- ASSERT(found);
- UNUSED_ASSERTION_VARIABLE(found);
+ if (!found)
+ {
+ infoLog << "Transform feedback varying " << tfVaryingName
+ << " does not exist in the vertex shader.";
+ return false;
+ }
}
- if (mData.mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS &&
+ if (mState.mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS &&
totalComponents > caps.maxTransformFeedbackInterleavedComponents)
{
infoLog << "Transform feedback varying total components (" << totalComponents
@@ -2080,454 +2718,349 @@ bool Program::linkValidateTransformFeedback(InfoLog &infoLog,
return true;
}
-void Program::gatherTransformFeedbackVaryings(const std::vector<const sh::Varying *> &varyings)
+bool Program::linkValidateGlobalNames(const Context *context, InfoLog &infoLog) const
{
- // Gather the linked varyings that are used for transform feedback, they should all exist.
- mData.mTransformFeedbackVaryingVars.clear();
- for (const std::string &tfVaryingName : mData.mTransformFeedbackVaryingNames)
+ const std::vector<sh::Uniform> &vertexUniforms =
+ mState.mAttachedVertexShader->getUniforms(context);
+ const std::vector<sh::Uniform> &fragmentUniforms =
+ mState.mAttachedFragmentShader->getUniforms(context);
+ const std::vector<sh::Attribute> &attributes =
+ mState.mAttachedVertexShader->getActiveAttributes(context);
+ for (const auto &attrib : attributes)
{
- for (const sh::Varying *varying : varyings)
+ for (const auto &uniform : vertexUniforms)
{
- if (tfVaryingName == varying->name)
+ if (uniform.name == attrib.name)
{
- mData.mTransformFeedbackVaryingVars.push_back(*varying);
- break;
+ infoLog << "Name conflicts between a uniform and an attribute: " << attrib.name;
+ return false;
+ }
+ }
+ for (const auto &uniform : fragmentUniforms)
+ {
+ if (uniform.name == attrib.name)
+ {
+ infoLog << "Name conflicts between a uniform and an attribute: " << attrib.name;
+ return false;
}
}
}
+ return true;
}
-std::vector<const sh::Varying *> Program::getMergedVaryings() const
+void Program::gatherTransformFeedbackVaryings(const Program::MergedVaryings &varyings)
{
- std::set<std::string> uniqueNames;
- std::vector<const sh::Varying *> varyings;
-
- for (const sh::Varying &varying : mData.mAttachedVertexShader->getVaryings())
+ // Gather the linked varyings that are used for transform feedback, they should all exist.
+ mState.mLinkedTransformFeedbackVaryings.clear();
+ for (const std::string &tfVaryingName : mState.mTransformFeedbackVaryingNames)
{
- if (uniqueNames.count(varying.name) == 0)
+ std::vector<unsigned int> subscripts;
+ std::string baseName = ParseResourceName(tfVaryingName, &subscripts);
+ size_t subscript = GL_INVALID_INDEX;
+ if (!subscripts.empty())
{
- uniqueNames.insert(varying.name);
- varyings.push_back(&varying);
+ subscript = subscripts.back();
}
- }
-
- for (const sh::Varying &varying : mData.mAttachedFragmentShader->getVaryings())
- {
- if (uniqueNames.count(varying.name) == 0)
+ for (const auto &ref : varyings)
{
- uniqueNames.insert(varying.name);
- varyings.push_back(&varying);
+ const sh::Varying *varying = ref.second.get();
+ if (baseName == varying->name)
+ {
+ mState.mLinkedTransformFeedbackVaryings.emplace_back(
+ *varying, static_cast<GLuint>(subscript));
+ break;
+ }
}
}
-
- return varyings;
}
-void Program::linkOutputVariables()
+Program::MergedVaryings Program::getMergedVaryings(const Context *context) const
{
- const Shader *fragmentShader = mData.mAttachedFragmentShader;
- ASSERT(fragmentShader != nullptr);
-
- // Skip this step for GLES2 shaders.
- if (fragmentShader->getShaderVersion() == 100)
- return;
-
- const auto &shaderOutputVars = fragmentShader->getActiveOutputVariables();
-
- // TODO(jmadill): any caps validation here?
+ MergedVaryings merged;
- for (unsigned int outputVariableIndex = 0; outputVariableIndex < shaderOutputVars.size();
- outputVariableIndex++)
+ for (const sh::Varying &varying : mState.mAttachedVertexShader->getOutputVaryings(context))
{
- const sh::OutputVariable &outputVariable = shaderOutputVars[outputVariableIndex];
-
- // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
- if (outputVariable.isBuiltIn())
- continue;
-
- // Since multiple output locations must be specified, use 0 for non-specified locations.
- int baseLocation = (outputVariable.location == -1 ? 0 : outputVariable.location);
-
- ASSERT(outputVariable.staticUse);
-
- for (unsigned int elementIndex = 0; elementIndex < outputVariable.elementCount();
- elementIndex++)
- {
- const int location = baseLocation + elementIndex;
- ASSERT(mData.mOutputVariables.count(location) == 0);
- unsigned int element = outputVariable.isArray() ? elementIndex : GL_INVALID_INDEX;
- mData.mOutputVariables[location] =
- VariableLocation(outputVariable.name, element, outputVariableIndex);
- }
+ merged[varying.name].vertex = &varying;
}
-}
-
-bool Program::flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoLog)
-{
- const gl::Shader *vertexShader = mData.getAttachedVertexShader();
- VectorAndSamplerCount vsCounts;
- std::vector<LinkedUniform> samplerUniforms;
-
- for (const sh::Uniform &uniform : vertexShader->getUniforms())
+ for (const sh::Varying &varying : mState.mAttachedFragmentShader->getInputVaryings(context))
{
- if (uniform.staticUse)
- {
- vsCounts += flattenUniform(uniform, uniform.name, &samplerUniforms);
- }
+ merged[varying.name].fragment = &varying;
}
- if (vsCounts.vectorCount > caps.maxVertexUniformVectors)
- {
- infoLog << "Vertex shader active uniforms exceed MAX_VERTEX_UNIFORM_VECTORS ("
- << caps.maxVertexUniformVectors << ").";
- return false;
- }
+ return merged;
+}
- if (vsCounts.samplerCount > caps.maxVertexTextureImageUnits)
- {
- infoLog << "Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS ("
- << caps.maxVertexTextureImageUnits << ").";
- return false;
- }
- const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
- VectorAndSamplerCount fsCounts;
+void Program::linkOutputVariables(const Context *context)
+{
+ Shader *fragmentShader = mState.mAttachedFragmentShader;
+ ASSERT(fragmentShader != nullptr);
+
+ ASSERT(mState.mOutputVariableTypes.empty());
+ ASSERT(mState.mActiveOutputVariables.none());
- for (const sh::Uniform &uniform : fragmentShader->getUniforms())
+ // Gather output variable types
+ for (const auto &outputVariable : fragmentShader->getActiveOutputVariables(context))
{
- if (uniform.staticUse)
+ if (outputVariable.isBuiltIn() && outputVariable.name != "gl_FragColor" &&
+ outputVariable.name != "gl_FragData")
{
- fsCounts += flattenUniform(uniform, uniform.name, &samplerUniforms);
+ continue;
}
- }
-
- if (fsCounts.vectorCount > caps.maxFragmentUniformVectors)
- {
- infoLog << "Fragment shader active uniforms exceed MAX_FRAGMENT_UNIFORM_VECTORS ("
- << caps.maxFragmentUniformVectors << ").";
- return false;
- }
- if (fsCounts.samplerCount > caps.maxTextureImageUnits)
- {
- infoLog << "Fragment shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS ("
- << caps.maxTextureImageUnits << ").";
- return false;
- }
-
- mSamplerUniformRange.start = static_cast<unsigned int>(mData.mUniforms.size());
- mSamplerUniformRange.end =
- mSamplerUniformRange.start + static_cast<unsigned int>(samplerUniforms.size());
-
- mData.mUniforms.insert(mData.mUniforms.end(), samplerUniforms.begin(), samplerUniforms.end());
-
- return true;
-}
-
-Program::VectorAndSamplerCount Program::flattenUniform(const sh::ShaderVariable &uniform,
- const std::string &fullName,
- std::vector<LinkedUniform> *samplerUniforms)
-{
- VectorAndSamplerCount vectorAndSamplerCount;
+ unsigned int baseLocation =
+ (outputVariable.location == -1 ? 0u
+ : static_cast<unsigned int>(outputVariable.location));
- if (uniform.isStruct())
- {
- for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
+ // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
+ // structures, so we may use getBasicTypeElementCount().
+ unsigned int elementCount = outputVariable.getBasicTypeElementCount();
+ for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
{
- const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
-
- for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
+ const unsigned int location = baseLocation + elementIndex;
+ if (location >= mState.mOutputVariableTypes.size())
{
- const sh::ShaderVariable &field = uniform.fields[fieldIndex];
- const std::string &fieldFullName = (fullName + elementString + "." + field.name);
-
- vectorAndSamplerCount += flattenUniform(field, fieldFullName, samplerUniforms);
+ mState.mOutputVariableTypes.resize(location + 1, GL_NONE);
}
+ ASSERT(location < mState.mActiveOutputVariables.size());
+ mState.mActiveOutputVariables.set(location);
+ mState.mOutputVariableTypes[location] = VariableComponentType(outputVariable.type);
}
-
- return vectorAndSamplerCount;
}
- // Not a struct
- bool isSampler = IsSamplerType(uniform.type);
- if (!UniformInList(mData.getUniforms(), fullName) && !UniformInList(*samplerUniforms, fullName))
+ // Skip this step for GLES2 shaders.
+ if (fragmentShader->getShaderVersion(context) == 100)
+ return;
+
+ mState.mOutputVariables = fragmentShader->getActiveOutputVariables(context);
+ // TODO(jmadill): any caps validation here?
+
+ for (unsigned int outputVariableIndex = 0; outputVariableIndex < mState.mOutputVariables.size();
+ outputVariableIndex++)
{
- gl::LinkedUniform linkedUniform(uniform.type, uniform.precision, fullName,
- uniform.arraySize, -1,
- sh::BlockMemberInfo::getDefaultBlockInfo());
- linkedUniform.staticUse = true;
+ const sh::OutputVariable &outputVariable = mState.mOutputVariables[outputVariableIndex];
- // Store sampler uniforms separately, so we'll append them to the end of the list.
- if (isSampler)
+ if (outputVariable.isArray())
{
- samplerUniforms->push_back(linkedUniform);
+ // We're following the GLES 3.1 November 2016 spec section 7.3.1.1 Naming Active
+ // Resources and including [0] at the end of array variable names.
+ mState.mOutputVariables[outputVariableIndex].name += "[0]";
+ mState.mOutputVariables[outputVariableIndex].mappedName += "[0]";
}
- else
- {
- mData.mUniforms.push_back(linkedUniform);
- }
- }
- unsigned int elementCount = uniform.elementCount();
-
- // Samplers aren't "real" uniforms, so they don't count towards register usage.
- // Likewise, don't count "real" uniforms towards sampler count.
- vectorAndSamplerCount.vectorCount =
- (isSampler ? 0 : (VariableRegisterCount(uniform.type) * elementCount));
- vectorAndSamplerCount.samplerCount = (isSampler ? elementCount : 0);
-
- return vectorAndSamplerCount;
-}
-
-void Program::gatherInterfaceBlockInfo()
-{
- std::set<std::string> visitedList;
-
- const gl::Shader *vertexShader = mData.getAttachedVertexShader();
-
- ASSERT(mData.mUniformBlocks.empty());
- for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks())
- {
- // Only 'packed' blocks are allowed to be considered inacive.
- if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED)
- continue;
-
- if (visitedList.count(vertexBlock.name) > 0)
+ // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
+ if (outputVariable.isBuiltIn())
continue;
- defineUniformBlock(vertexBlock, GL_VERTEX_SHADER);
- visitedList.insert(vertexBlock.name);
- }
-
- const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
-
- for (const sh::InterfaceBlock &fragmentBlock : fragmentShader->getInterfaceBlocks())
- {
- // Only 'packed' blocks are allowed to be considered inacive.
- if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED)
- continue;
+ // Since multiple output locations must be specified, use 0 for non-specified locations.
+ unsigned int baseLocation =
+ (outputVariable.location == -1 ? 0u
+ : static_cast<unsigned int>(outputVariable.location));
- if (visitedList.count(fragmentBlock.name) > 0)
+ // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
+ // structures, so we may use getBasicTypeElementCount().
+ unsigned int elementCount = outputVariable.getBasicTypeElementCount();
+ for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
{
- for (gl::UniformBlock &block : mData.mUniformBlocks)
+ const unsigned int location = baseLocation + elementIndex;
+ if (location >= mState.mOutputLocations.size())
{
- if (block.name == fragmentBlock.name)
- {
- block.fragmentStaticUse = fragmentBlock.staticUse;
- }
+ mState.mOutputLocations.resize(location + 1);
+ }
+ ASSERT(!mState.mOutputLocations.at(location).used());
+ if (outputVariable.isArray())
+ {
+ mState.mOutputLocations[location] =
+ VariableLocation(elementIndex, outputVariableIndex);
+ }
+ else
+ {
+ VariableLocation locationInfo;
+ locationInfo.index = outputVariableIndex;
+ mState.mOutputLocations[location] = locationInfo;
}
-
- continue;
}
-
- defineUniformBlock(fragmentBlock, GL_FRAGMENT_SHADER);
- visitedList.insert(fragmentBlock.name);
}
}
-template <typename VarT>
-void Program::defineUniformBlockMembers(const std::vector<VarT> &fields,
- const std::string &prefix,
- int blockIndex)
+void Program::setUniformValuesFromBindingQualifiers()
{
- for (const VarT &field : fields)
+ for (unsigned int samplerIndex : mState.mSamplerUniformRange)
{
- const std::string &fullName = (prefix.empty() ? field.name : prefix + "." + field.name);
-
- if (field.isStruct())
- {
- for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
- {
- const std::string uniformElementName =
- fullName + (field.isArray() ? ArrayString(arrayElement) : "");
- defineUniformBlockMembers(field.fields, uniformElementName, blockIndex);
- }
- }
- else
+ const auto &samplerUniform = mState.mUniforms[samplerIndex];
+ if (samplerUniform.binding != -1)
{
- // If getBlockMemberInfo returns false, the uniform is optimized out.
- sh::BlockMemberInfo memberInfo;
- if (!mProgram->getUniformBlockMemberInfo(fullName, &memberInfo))
+ GLint location = getUniformLocation(samplerUniform.name);
+ ASSERT(location != -1);
+ std::vector<GLint> boundTextureUnits;
+ for (unsigned int elementIndex = 0;
+ elementIndex < samplerUniform.getBasicTypeElementCount(); ++elementIndex)
{
- continue;
+ boundTextureUnits.push_back(samplerUniform.binding + elementIndex);
}
-
- LinkedUniform newUniform(field.type, field.precision, fullName, field.arraySize,
- blockIndex, memberInfo);
-
- // Since block uniforms have no location, we don't need to store them in the uniform
- // locations list.
- mData.mUniforms.push_back(newUniform);
+ setUniform1iv(location, static_cast<GLsizei>(boundTextureUnits.size()),
+ boundTextureUnits.data());
}
}
}
-void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType)
+void Program::gatherAtomicCounterBuffers()
{
- int blockIndex = static_cast<int>(mData.mUniformBlocks.size());
- size_t blockSize = 0;
-
- // Don't define this block at all if it's not active in the implementation.
- if (!mProgram->getUniformBlockSize(interfaceBlock.name, &blockSize))
+ for (unsigned int index : mState.mAtomicCounterUniformRange)
{
- return;
+ auto &uniform = mState.mUniforms[index];
+ uniform.blockInfo.offset = uniform.offset;
+ uniform.blockInfo.arrayStride = (uniform.isArray() ? 4 : 0);
+ uniform.blockInfo.matrixStride = 0;
+ uniform.blockInfo.isRowMajorMatrix = false;
}
- // Track the first and last uniform index to determine the range of active uniforms in the
- // block.
- size_t firstBlockUniformIndex = mData.mUniforms.size();
- defineUniformBlockMembers(interfaceBlock.fields, interfaceBlock.fieldPrefix(), blockIndex);
- size_t lastBlockUniformIndex = mData.mUniforms.size();
+ // TODO(jie.a.chen@intel.com): Get the actual BUFFER_DATA_SIZE from backend for each buffer.
+}
- std::vector<unsigned int> blockUniformIndexes;
- for (size_t blockUniformIndex = firstBlockUniformIndex;
- blockUniformIndex < lastBlockUniformIndex; ++blockUniformIndex)
+void Program::initInterfaceBlockBindings()
+{
+ // Set initial bindings from shader.
+ for (unsigned int blockIndex = 0; blockIndex < mState.mUniformBlocks.size(); blockIndex++)
{
- blockUniformIndexes.push_back(static_cast<unsigned int>(blockUniformIndex));
+ InterfaceBlock &uniformBlock = mState.mUniformBlocks[blockIndex];
+ bindUniformBlock(blockIndex, uniformBlock.binding);
}
+}
- if (interfaceBlock.arraySize > 0)
- {
- for (unsigned int arrayElement = 0; arrayElement < interfaceBlock.arraySize; ++arrayElement)
- {
- UniformBlock block(interfaceBlock.name, true, arrayElement);
- block.memberUniformIndexes = blockUniformIndexes;
-
- if (shaderType == GL_VERTEX_SHADER)
- {
- block.vertexStaticUse = interfaceBlock.staticUse;
- }
- else
- {
- ASSERT(shaderType == GL_FRAGMENT_SHADER);
- block.fragmentStaticUse = interfaceBlock.staticUse;
- }
-
- // TODO(jmadill): Determine if we can ever have an inactive array element block.
- size_t blockElementSize = 0;
- if (!mProgram->getUniformBlockSize(block.nameWithArrayIndex(), &blockElementSize))
- {
- continue;
- }
-
- ASSERT(blockElementSize == blockSize);
- block.dataSize = static_cast<unsigned int>(blockElementSize);
- mData.mUniformBlocks.push_back(block);
- }
- }
- else
- {
- UniformBlock block(interfaceBlock.name, false, 0);
- block.memberUniformIndexes = blockUniformIndexes;
+void Program::updateSamplerUniform(const VariableLocation &locationInfo,
+ GLsizei clampedCount,
+ const GLint *v)
+{
+ ASSERT(mState.isSamplerUniformIndex(locationInfo.index));
+ GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(locationInfo.index);
+ std::vector<GLuint> *boundTextureUnits =
+ &mState.mSamplerBindings[samplerIndex].boundTextureUnits;
- if (shaderType == GL_VERTEX_SHADER)
- {
- block.vertexStaticUse = interfaceBlock.staticUse;
- }
- else
- {
- ASSERT(shaderType == GL_FRAGMENT_SHADER);
- block.fragmentStaticUse = interfaceBlock.staticUse;
- }
+ std::copy(v, v + clampedCount, boundTextureUnits->begin() + locationInfo.arrayIndex);
- block.dataSize = static_cast<unsigned int>(blockSize);
- mData.mUniformBlocks.push_back(block);
- }
+ // Invalidate the validation cache.
+ mCachedValidateSamplersResult.reset();
}
template <typename T>
-void Program::setUniformInternal(GLint location, GLsizei count, const T *v)
+GLsizei Program::clampUniformCount(const VariableLocation &locationInfo,
+ GLsizei count,
+ int vectorSize,
+ const T *v)
{
- const VariableLocation &locationInfo = mData.mUniformLocations[location];
- LinkedUniform *linkedUniform = &mData.mUniforms[locationInfo.index];
- uint8_t *destPointer = linkedUniform->getDataPtrToElement(locationInfo.element);
+ if (count == 1)
+ return 1;
+
+ const LinkedUniform &linkedUniform = mState.mUniforms[locationInfo.index];
- if (VariableComponentType(linkedUniform->type) == GL_BOOL)
+ // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
+ // element index used, as reported by GetActiveUniform, will be ignored by the GL."
+ unsigned int remainingElements =
+ linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
+ GLsizei maxElementCount =
+ static_cast<GLsizei>(remainingElements * linkedUniform.getElementComponents());
+
+ if (count * vectorSize > maxElementCount)
{
- // Do a cast conversion for boolean types. From the spec:
- // "The uniform is set to FALSE if the input value is 0 or 0.0f, and set to TRUE otherwise."
- GLint *destAsInt = reinterpret_cast<GLint *>(destPointer);
- for (GLsizei component = 0; component < count; ++component)
- {
- destAsInt[component] = (v[component] != static_cast<T>(0) ? GL_TRUE : GL_FALSE);
- }
+ return maxElementCount / vectorSize;
}
- else
- {
- // Invalide the validation cache if we modify the sampler data.
- if (linkedUniform->isSampler() && memcmp(destPointer, v, sizeof(T) * count) != 0)
- {
- mCachedValidateSamplersResult.reset();
- }
- memcpy(destPointer, v, sizeof(T) * count);
- }
+ return count;
}
template <size_t cols, size_t rows, typename T>
-void Program::setMatrixUniformInternal(GLint location,
- GLsizei count,
- GLboolean transpose,
- const T *v)
+GLsizei Program::clampMatrixUniformCount(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const T *v)
{
+ const VariableLocation &locationInfo = mState.mUniformLocations[location];
+
if (!transpose)
{
- setUniformInternal(location, count * cols * rows, v);
- return;
+ return clampUniformCount(locationInfo, count, cols * rows, v);
}
- // Perform a transposing copy.
- const VariableLocation &locationInfo = mData.mUniformLocations[location];
- LinkedUniform *linkedUniform = &mData.mUniforms[locationInfo.index];
- T *destPtr = reinterpret_cast<T *>(linkedUniform->getDataPtrToElement(locationInfo.element));
- for (GLsizei element = 0; element < count; ++element)
- {
- size_t elementOffset = element * rows * cols;
+ const LinkedUniform &linkedUniform = mState.mUniforms[locationInfo.index];
- for (size_t row = 0; row < rows; ++row)
- {
- for (size_t col = 0; col < cols; ++col)
- {
- destPtr[col * rows + row + elementOffset] = v[row * cols + col + elementOffset];
- }
- }
- }
+ // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
+ // element index used, as reported by GetActiveUniform, will be ignored by the GL."
+ unsigned int remainingElements =
+ linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
+ return std::min(count, static_cast<GLsizei>(remainingElements));
}
+// Driver differences mean that doing the uniform value cast ourselves gives consistent results.
+// EG: on NVIDIA drivers, it was observed that getUniformi for MAX_INT+1 returned MIN_INT.
template <typename DestT>
-void Program::getUniformInternal(GLint location, DestT *dataOut) const
+void Program::getUniformInternal(const Context *context,
+ DestT *dataOut,
+ GLint location,
+ GLenum nativeType,
+ int components) const
{
- const VariableLocation &locationInfo = mData.mUniformLocations[location];
- const LinkedUniform &uniform = mData.mUniforms[locationInfo.index];
-
- const uint8_t *srcPointer = uniform.getDataPtrToElement(locationInfo.element);
-
- GLenum componentType = VariableComponentType(uniform.type);
- if (componentType == GLTypeToGLenum<DestT>::value)
- {
- memcpy(dataOut, srcPointer, uniform.getElementSize());
- return;
- }
-
- int components = VariableComponentCount(uniform.type);
-
- switch (componentType)
+ switch (nativeType)
{
+ case GL_BOOL:
+ {
+ GLint tempValue[16] = {0};
+ mProgram->getUniformiv(context, location, tempValue);
+ UniformStateQueryCastLoop<GLboolean>(
+ dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
+ break;
+ }
case GL_INT:
- UniformStateQueryCastLoop<GLint>(dataOut, srcPointer, components);
+ {
+ GLint tempValue[16] = {0};
+ mProgram->getUniformiv(context, location, tempValue);
+ UniformStateQueryCastLoop<GLint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
+ components);
break;
+ }
case GL_UNSIGNED_INT:
- UniformStateQueryCastLoop<GLuint>(dataOut, srcPointer, components);
- break;
- case GL_BOOL:
- UniformStateQueryCastLoop<GLboolean>(dataOut, srcPointer, components);
+ {
+ GLuint tempValue[16] = {0};
+ mProgram->getUniformuiv(context, location, tempValue);
+ UniformStateQueryCastLoop<GLuint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
+ components);
break;
+ }
case GL_FLOAT:
- UniformStateQueryCastLoop<GLfloat>(dataOut, srcPointer, components);
+ {
+ GLfloat tempValue[16] = {0};
+ mProgram->getUniformfv(context, location, tempValue);
+ UniformStateQueryCastLoop<GLfloat>(
+ dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
break;
+ }
default:
UNREACHABLE();
+ break;
}
}
+
+bool Program::samplesFromTexture(const gl::State &state, GLuint textureID) const
+{
+ // Must be called after samplers are validated.
+ ASSERT(mCachedValidateSamplersResult.valid() && mCachedValidateSamplersResult.value());
+
+ for (const auto &binding : mState.mSamplerBindings)
+ {
+ GLenum textureType = binding.textureType;
+ for (const auto &unit : binding.boundTextureUnits)
+ {
+ GLenum programTextureID = state.getSamplerTextureId(unit, textureType);
+ if (programTextureID == textureID)
+ {
+ // TODO(jmadill): Check for appropriate overlap.
+ return true;
+ }
+ }
+ }
+
+ return false;
}
+
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/Program.h b/src/3rdparty/angle/src/libANGLE/Program.h
index f885ad1694..c242d84671 100644
--- a/src/3rdparty/angle/src/libANGLE/Program.h
+++ b/src/3rdparty/angle/src/libANGLE/Program.h
@@ -11,8 +11,10 @@
#define LIBANGLE_PROGRAM_H_
#include <GLES2/gl2.h>
-#include <GLSLANG/ShaderLang.h>
+#include <GLSLANG/ShaderVars.h>
+#include <array>
+#include <map>
#include <set>
#include <sstream>
#include <string>
@@ -22,15 +24,16 @@
#include "common/mathutil.h"
#include "common/Optional.h"
-#include "libANGLE/angletypes.h"
#include "libANGLE/Constants.h"
#include "libANGLE/Debug.h"
#include "libANGLE/Error.h"
#include "libANGLE/RefCountObject.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/angletypes.h"
namespace rx
{
-class ImplFactory;
+class GLImplFactory;
class ProgramImpl;
struct TranslatedAttribute;
}
@@ -38,31 +41,17 @@ struct TranslatedAttribute;
namespace gl
{
struct Caps;
-struct Data;
-class ResourceManager;
+class Context;
+class ContextState;
class Shader;
+class ShaderProgramManager;
+class State;
class InfoLog;
-class AttributeBindings;
class Buffer;
class Framebuffer;
-struct UniformBlock;
-struct LinkedUniform;
extern const char * const g_fakepath;
-class AttributeBindings
-{
- public:
- AttributeBindings();
- ~AttributeBindings();
-
- void bindAttributeLocation(GLuint index, const char *name);
- int getAttributeBinding(const std::string &name) const;
-
- private:
- std::set<std::string> mAttributeBinding[MAX_VERTEX_ATTRIBS];
-};
-
class InfoLog : angle::NonCopyable
{
public:
@@ -122,134 +111,330 @@ class InfoLog : angle::NonCopyable
template <typename T>
StreamHelper operator<<(const T &value)
{
- StreamHelper helper(&mStream);
+ ensureInitialized();
+ StreamHelper helper(mLazyStream.get());
helper << value;
return helper;
}
- std::string str() const { return mStream.str(); }
+ std::string str() const { return mLazyStream ? mLazyStream->str() : ""; }
private:
- std::stringstream mStream;
+ void ensureInitialized()
+ {
+ if (!mLazyStream)
+ {
+ mLazyStream.reset(new std::stringstream());
+ }
+ }
+
+ std::unique_ptr<std::stringstream> mLazyStream;
};
// Struct used for correlating uniforms/elements of uniform arrays to handles
struct VariableLocation
{
+ static constexpr unsigned int kUnused = GL_INVALID_INDEX;
+
VariableLocation();
- VariableLocation(const std::string &name, unsigned int element, unsigned int index);
+ VariableLocation(unsigned int arrayIndex, unsigned int index);
+
+ // If used is false, it means this location is only used to fill an empty space in an array,
+ // and there is no corresponding uniform variable for this location. It can also mean the
+ // uniform was optimized out by the implementation.
+ bool used() const { return (index != kUnused); }
+ void markUnused() { index = kUnused; }
+ void markIgnored() { ignored = true; }
+
+ // "arrayIndex" stores the index of the innermost GLSL array. It's zero for non-arrays.
+ unsigned int arrayIndex;
+ // "index" is an index of the variable. The variable contains the indices for other than the
+ // innermost GLSL arrays.
+ unsigned int index;
+
+ // If this location was bound to an unreferenced uniform. Setting data on this uniform is a
+ // no-op.
+ bool ignored;
+};
+// Information about a variable binding.
+// Currently used by CHROMIUM_path_rendering
+struct BindingInfo
+{
+ // The type of binding, for example GL_FLOAT_VEC3.
+ // This can be GL_NONE if the variable is optimized away.
+ GLenum type;
+
+ // This is the name of the variable in
+ // the translated shader program. Note that
+ // this can be empty in the case where the
+ // variable has been optimized away.
std::string name;
- unsigned int element;
- unsigned int index;
+
+ // True if the binding is valid, otherwise false.
+ bool valid;
};
-class Program final : angle::NonCopyable, public LabeledObject
+// This small structure encapsulates binding sampler uniforms to active GL textures.
+struct SamplerBinding
{
- public:
- class Data final : angle::NonCopyable
- {
- public:
- Data();
- ~Data();
+ SamplerBinding(GLenum textureTypeIn, size_t elementCount, bool unreferenced);
+ SamplerBinding(const SamplerBinding &other);
+ ~SamplerBinding();
- const std::string &getLabel();
+ // Necessary for retrieving active textures from the GL state.
+ GLenum textureType;
- const Shader *getAttachedVertexShader() const { return mAttachedVertexShader; }
- const Shader *getAttachedFragmentShader() const { return mAttachedFragmentShader; }
- const std::vector<std::string> &getTransformFeedbackVaryingNames() const
- {
- return mTransformFeedbackVaryingNames;
- }
- GLint getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; }
- GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const
- {
- ASSERT(uniformBlockIndex < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS);
- return mUniformBlockBindings[uniformBlockIndex];
- }
- const UniformBlockBindingMask &getActiveUniformBlockBindingsMask() const
- {
- return mActiveUniformBlockBindings;
- }
- const std::vector<sh::Attribute> &getAttributes() const { return mAttributes; }
- const AttributesMask &getActiveAttribLocationsMask() const
- {
- return mActiveAttribLocationsMask;
- }
- const std::map<int, VariableLocation> &getOutputVariables() const
- {
- return mOutputVariables;
- }
- const std::vector<LinkedUniform> &getUniforms() const { return mUniforms; }
- const std::vector<VariableLocation> &getUniformLocations() const
+ // List of all textures bound to this sampler, of type textureType.
+ std::vector<GLuint> boundTextureUnits;
+
+ // A note if this sampler is an unreferenced uniform.
+ bool unreferenced;
+};
+
+// A varying with tranform feedback enabled. If it's an array, either the whole array or one of its
+// elements specified by 'arrayIndex' can set to be enabled.
+struct TransformFeedbackVarying : public sh::Varying
+{
+ TransformFeedbackVarying(const sh::Varying &varyingIn, GLuint index)
+ : sh::Varying(varyingIn), arrayIndex(index)
+ {
+ ASSERT(!isArrayOfArrays());
+ }
+ std::string nameWithArrayIndex() const
+ {
+ std::stringstream fullNameStr;
+ fullNameStr << name;
+ if (arrayIndex != GL_INVALID_INDEX)
{
- return mUniformLocations;
+ fullNameStr << "[" << arrayIndex << "]";
}
- const std::vector<UniformBlock> &getUniformBlocks() const { return mUniformBlocks; }
+ return fullNameStr.str();
+ }
+ GLsizei size() const
+ {
+ return (isArray() && arrayIndex == GL_INVALID_INDEX ? getOutermostArraySize() : 1);
+ }
- const LinkedUniform *getUniformByName(const std::string &name) const;
- GLint getUniformLocation(const std::string &name) const;
- GLuint getUniformIndex(const std::string &name) const;
+ GLuint arrayIndex;
+};
- private:
- friend class Program;
+struct ImageBinding
+{
+ ImageBinding(size_t count);
+ ImageBinding(GLuint imageUnit, size_t count);
+ ImageBinding(const ImageBinding &other);
+ ~ImageBinding();
+
+ std::vector<GLuint> boundImageUnits;
+};
+
+using ShaderStagesMask = angle::BitSet<SHADER_TYPE_MAX>;
+
+class ProgramState final : angle::NonCopyable
+{
+ public:
+ ProgramState();
+ ~ProgramState();
+
+ const std::string &getLabel();
+
+ Shader *getAttachedVertexShader() const { return mAttachedVertexShader; }
+ Shader *getAttachedFragmentShader() const { return mAttachedFragmentShader; }
+ Shader *getAttachedComputeShader() const { return mAttachedComputeShader; }
+ Shader *getAttachedGeometryShader() const { return mAttachedGeometryShader; }
+ const std::vector<std::string> &getTransformFeedbackVaryingNames() const
+ {
+ return mTransformFeedbackVaryingNames;
+ }
+ GLint getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; }
+ GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const
+ {
+ ASSERT(uniformBlockIndex < mUniformBlocks.size());
+ return mUniformBlocks[uniformBlockIndex].binding;
+ }
+ GLuint getShaderStorageBlockBinding(GLuint blockIndex) const
+ {
+ ASSERT(blockIndex < mShaderStorageBlocks.size());
+ return mShaderStorageBlocks[blockIndex].binding;
+ }
+ const UniformBlockBindingMask &getActiveUniformBlockBindingsMask() const
+ {
+ return mActiveUniformBlockBindings;
+ }
+ const std::vector<sh::Attribute> &getAttributes() const { return mAttributes; }
+ const AttributesMask &getActiveAttribLocationsMask() const
+ {
+ return mActiveAttribLocationsMask;
+ }
+ unsigned int getMaxActiveAttribLocation() const { return mMaxActiveAttribLocation; }
+ DrawBufferMask getActiveOutputVariables() const { return mActiveOutputVariables; }
+ const std::vector<sh::OutputVariable> &getOutputVariables() const { return mOutputVariables; }
+ const std::vector<VariableLocation> &getOutputLocations() const { return mOutputLocations; }
+ const std::vector<LinkedUniform> &getUniforms() const { return mUniforms; }
+ const std::vector<VariableLocation> &getUniformLocations() const { return mUniformLocations; }
+ const std::vector<InterfaceBlock> &getUniformBlocks() const { return mUniformBlocks; }
+ const std::vector<InterfaceBlock> &getShaderStorageBlocks() const
+ {
+ return mShaderStorageBlocks;
+ }
+ const std::vector<BufferVariable> &getBufferVariables() const { return mBufferVariables; }
+ const std::vector<SamplerBinding> &getSamplerBindings() const { return mSamplerBindings; }
+ const std::vector<ImageBinding> &getImageBindings() const { return mImageBindings; }
+ const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; }
+ const RangeUI &getSamplerUniformRange() const { return mSamplerUniformRange; }
+ const RangeUI &getImageUniformRange() const { return mImageUniformRange; }
+ const RangeUI &getAtomicCounterUniformRange() const { return mAtomicCounterUniformRange; }
+
+ const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const
+ {
+ return mLinkedTransformFeedbackVaryings;
+ }
+ const std::vector<AtomicCounterBuffer> &getAtomicCounterBuffers() const
+ {
+ return mAtomicCounterBuffers;
+ }
- std::string mLabel;
+ GLuint getUniformIndexFromName(const std::string &name) const;
+ GLuint getUniformIndexFromLocation(GLint location) const;
+ Optional<GLuint> getSamplerIndex(GLint location) const;
+ bool isSamplerUniformIndex(GLuint index) const;
+ GLuint getSamplerIndexFromUniformIndex(GLuint uniformIndex) const;
+ GLuint getAttributeLocation(const std::string &name) const;
- Shader *mAttachedFragmentShader;
- Shader *mAttachedVertexShader;
+ GLuint getBufferVariableIndexFromName(const std::string &name) const;
- std::vector<std::string> mTransformFeedbackVaryingNames;
- std::vector<sh::Varying> mTransformFeedbackVaryingVars;
- GLenum mTransformFeedbackBufferMode;
+ int getNumViews() const { return mNumViews; }
+ bool usesMultiview() const { return mNumViews != -1; }
- GLuint mUniformBlockBindings[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS];
- UniformBlockBindingMask mActiveUniformBlockBindings;
+ const ShaderStagesMask &getLinkedShaderStages() const { return mLinkedShaderStages; }
- std::vector<sh::Attribute> mAttributes;
- std::bitset<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask;
+ private:
+ friend class MemoryProgramCache;
+ friend class Program;
+
+ std::string mLabel;
+
+ sh::WorkGroupSize mComputeShaderLocalSize;
+
+ Shader *mAttachedFragmentShader;
+ Shader *mAttachedVertexShader;
+ Shader *mAttachedComputeShader;
+ Shader *mAttachedGeometryShader;
+
+ std::vector<std::string> mTransformFeedbackVaryingNames;
+ std::vector<TransformFeedbackVarying> mLinkedTransformFeedbackVaryings;
+ GLenum mTransformFeedbackBufferMode;
+
+ // For faster iteration on the blocks currently being bound.
+ UniformBlockBindingMask mActiveUniformBlockBindings;
+
+ std::vector<sh::Attribute> mAttributes;
+ angle::BitSet<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask;
+ unsigned int mMaxActiveAttribLocation;
+
+ // Uniforms are sorted in order:
+ // 1. Non-opaque uniforms
+ // 2. Sampler uniforms
+ // 3. Image uniforms
+ // 4. Atomic counter uniforms
+ // 5. Uniform block uniforms
+ // This makes opaque uniform validation easier, since we don't need a separate list.
+ // For generating the entries and naming them we follow the spec: GLES 3.1 November 2016 section
+ // 7.3.1.1 Naming Active Resources. There's a separate entry for each struct member and each
+ // inner array of an array of arrays. Names and mapped names of uniforms that are arrays include
+ // [0] in the end. This makes implementation of queries simpler.
+ std::vector<LinkedUniform> mUniforms;
+
+ std::vector<VariableLocation> mUniformLocations;
+ std::vector<InterfaceBlock> mUniformBlocks;
+ std::vector<BufferVariable> mBufferVariables;
+ std::vector<InterfaceBlock> mShaderStorageBlocks;
+ std::vector<AtomicCounterBuffer> mAtomicCounterBuffers;
+ RangeUI mSamplerUniformRange;
+ RangeUI mImageUniformRange;
+ RangeUI mAtomicCounterUniformRange;
- // Uniforms are sorted in order:
- // 1. Non-sampler uniforms
- // 2. Sampler uniforms
- // 3. Uniform block uniforms
- // This makes sampler validation easier, since we don't need a separate list.
- std::vector<LinkedUniform> mUniforms;
- std::vector<VariableLocation> mUniformLocations;
- std::vector<UniformBlock> mUniformBlocks;
+ // An array of the samplers that are used by the program
+ std::vector<gl::SamplerBinding> mSamplerBindings;
- // TODO(jmadill): use unordered/hash map when available
- std::map<int, VariableLocation> mOutputVariables;
+ // An array of the images that are used by the program
+ std::vector<gl::ImageBinding> mImageBindings;
- bool mBinaryRetrieveableHint;
- };
+ // Names and mapped names of output variables that are arrays include [0] in the end, similarly
+ // to uniforms.
+ std::vector<sh::OutputVariable> mOutputVariables;
+ std::vector<VariableLocation> mOutputLocations;
+ DrawBufferMask mActiveOutputVariables;
- Program(rx::ImplFactory *factory, ResourceManager *manager, GLuint handle);
- ~Program();
+ // Fragment output variable base types: FLOAT, INT, or UINT. Ordered by location.
+ std::vector<GLenum> mOutputVariableTypes;
+
+ bool mBinaryRetrieveableHint;
+ bool mSeparable;
+ ShaderStagesMask mLinkedShaderStages;
+
+ // ANGLE_multiview.
+ int mNumViews;
+};
+
+class Program final : angle::NonCopyable, public LabeledObject
+{
+ public:
+ Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, GLuint handle);
+ void onDestroy(const Context *context);
GLuint id() const { return mHandle; }
void setLabel(const std::string &label) override;
const std::string &getLabel() const override;
- rx::ProgramImpl *getImplementation() { return mProgram; }
- const rx::ProgramImpl *getImplementation() const { return mProgram; }
+ rx::ProgramImpl *getImplementation() const { return mProgram; }
- bool attachShader(Shader *shader);
- bool detachShader(Shader *shader);
+ void attachShader(Shader *shader);
+ void detachShader(const Context *context, Shader *shader);
int getAttachedShadersCount() const;
- void bindAttributeLocation(GLuint index, const char *name);
+ const Shader *getAttachedVertexShader() const { return mState.mAttachedVertexShader; }
+ const Shader *getAttachedFragmentShader() const { return mState.mAttachedFragmentShader; }
+ const Shader *getAttachedComputeShader() const { return mState.mAttachedComputeShader; }
+ const Shader *getAttachedGeometryShader() const { return mState.mAttachedGeometryShader; }
- Error link(const gl::Data &data);
+ void bindAttributeLocation(GLuint index, const char *name);
+ void bindUniformLocation(GLuint index, const char *name);
+
+ // CHROMIUM_path_rendering
+ BindingInfo getFragmentInputBindingInfo(const Context *context, GLint index) const;
+ void bindFragmentInputLocation(GLint index, const char *name);
+ void pathFragmentInputGen(const Context *context,
+ GLint index,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs);
+
+ Error link(const gl::Context *context);
bool isLinked() const;
- Error loadBinary(GLenum binaryFormat, const void *binary, GLsizei length);
- Error saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) const;
- GLint getBinaryLength() const;
+ bool hasLinkedVertexShader() const { return mState.mLinkedShaderStages[SHADER_VERTEX]; }
+ bool hasLinkedFragmentShader() const { return mState.mLinkedShaderStages[SHADER_FRAGMENT]; }
+ bool hasLinkedComputeShader() const { return mState.mLinkedShaderStages[SHADER_COMPUTE]; }
+
+ Error loadBinary(const Context *context,
+ GLenum binaryFormat,
+ const void *binary,
+ GLsizei length);
+ Error saveBinary(const Context *context,
+ GLenum *binaryFormat,
+ void *binary,
+ GLsizei bufSize,
+ GLsizei *length) const;
+ GLint getBinaryLength(const Context *context) const;
void setBinaryRetrievableHint(bool retrievable);
bool getBinaryRetrievableHint() const;
+ void setSeparable(bool separable);
+ bool isSeparable() const;
+
int getInfoLogLength() const;
void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders) const;
@@ -257,12 +442,23 @@ class Program final : angle::NonCopyable, public LabeledObject
GLuint getAttributeLocation(const std::string &name) const;
bool isAttribLocationActive(size_t attribLocation) const;
- void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+ void getActiveAttribute(GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name) const;
GLint getActiveAttributeCount() const;
GLint getActiveAttributeMaxLength() const;
- const std::vector<sh::Attribute> &getAttributes() const { return mData.mAttributes; }
+ const std::vector<sh::Attribute> &getAttributes() const { return mState.mAttributes; }
GLint getFragDataLocation(const std::string &name) const;
+ size_t getOutputResourceCount() const;
+ const std::vector<GLenum> &getOutputVariableTypes() const
+ {
+ return mState.mOutputVariableTypes;
+ }
+ DrawBufferMask getActiveOutputVariables() const { return mState.mActiveOutputVariables; }
void getActiveUniform(GLuint index,
GLsizei bufsize,
@@ -271,10 +467,21 @@ class Program final : angle::NonCopyable, public LabeledObject
GLenum *type,
GLchar *name) const;
GLint getActiveUniformCount() const;
+ size_t getActiveBufferVariableCount() const;
GLint getActiveUniformMaxLength() const;
- GLint getActiveUniformi(GLuint index, GLenum pname) const;
bool isValidUniformLocation(GLint location) const;
const LinkedUniform &getUniformByLocation(GLint location) const;
+ const VariableLocation &getUniformLocation(GLint location) const;
+ const std::vector<VariableLocation> &getUniformLocations() const;
+ const LinkedUniform &getUniformByIndex(GLuint index) const;
+
+ const BufferVariable &getBufferVariableByIndex(GLuint index) const;
+
+ enum SetUniformResult
+ {
+ SamplerChanged,
+ NoSamplerChange,
+ };
GLint getUniformLocation(const std::string &name) const;
GLuint getUniformIndex(const std::string &name) const;
@@ -282,7 +489,7 @@ class Program final : angle::NonCopyable, public LabeledObject
void setUniform2fv(GLint location, GLsizei count, const GLfloat *v);
void setUniform3fv(GLint location, GLsizei count, const GLfloat *v);
void setUniform4fv(GLint location, GLsizei count, const GLfloat *v);
- void setUniform1iv(GLint location, GLsizei count, const GLint *v);
+ SetUniformResult setUniform1iv(GLint location, GLsizei count, const GLint *v);
void setUniform2iv(GLint location, GLsizei count, const GLint *v);
void setUniform3iv(GLint location, GLsizei count, const GLint *v);
void setUniform4iv(GLint location, GLsizei count, const GLint *v);
@@ -300,21 +507,32 @@ class Program final : angle::NonCopyable, public LabeledObject
void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
- void getUniformfv(GLint location, GLfloat *params) const;
- void getUniformiv(GLint location, GLint *params) const;
- void getUniformuiv(GLint location, GLuint *params) const;
-
- void getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const;
- void getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const;
+ void getUniformfv(const Context *context, GLint location, GLfloat *params) const;
+ void getUniformiv(const Context *context, GLint location, GLint *params) const;
+ void getUniformuiv(const Context *context, GLint location, GLuint *params) const;
+
+ void getActiveUniformBlockName(const GLuint blockIndex,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *blockName) const;
+ void getActiveShaderStorageBlockName(const GLuint blockIndex,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *blockName) const;
GLuint getActiveUniformBlockCount() const;
+ GLuint getActiveAtomicCounterBufferCount() const;
+ GLuint getActiveShaderStorageBlockCount() const;
GLint getActiveUniformBlockMaxLength() const;
GLuint getUniformBlockIndex(const std::string &name) const;
+ GLuint getShaderStorageBlockIndex(const std::string &name) const;
void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding);
GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const;
+ GLuint getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const;
- const UniformBlock &getUniformBlockByIndex(GLuint index) const;
+ const InterfaceBlock &getUniformBlockByIndex(GLuint index) const;
+ const InterfaceBlock &getShaderStorageBlockByIndex(GLuint index) const;
void setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode);
void getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const;
@@ -322,11 +540,14 @@ class Program final : angle::NonCopyable, public LabeledObject
GLsizei getTransformFeedbackVaryingMaxLength() const;
GLenum getTransformFeedbackBufferMode() const;
- static bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform);
- static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform);
+ static bool linkValidateInterfaceBlockFields(InfoLog &infoLog,
+ const std::string &uniformName,
+ const sh::InterfaceBlockField &vertexUniform,
+ const sh::InterfaceBlockField &fragmentUniform,
+ bool webglCompatibility);
void addRef();
- void release();
+ void release(const Context *context);
unsigned int getRefCount() const;
void flagForDeletion();
bool isFlaggedForDeletion() const;
@@ -334,28 +555,25 @@ class Program final : angle::NonCopyable, public LabeledObject
void validate(const Caps &caps);
bool validateSamplers(InfoLog *infoLog, const Caps &caps);
bool isValidated() const;
+ bool samplesFromTexture(const gl::State &state, GLuint textureID) const;
const AttributesMask &getActiveAttribLocationsMask() const
{
- return mData.mActiveAttribLocationsMask;
+ return mState.mActiveAttribLocationsMask;
}
- private:
- void unlink(bool destroy = false);
- void resetUniformBlockBindings();
-
- bool linkAttributes(const gl::Data &data,
- InfoLog &infoLog,
- const AttributeBindings &attributeBindings,
- const Shader *vertexShader);
- bool linkUniformBlocks(InfoLog &infoLog, const Caps &caps);
- static bool linkVaryings(InfoLog &infoLog,
- const Shader *vertexShader,
- const Shader *fragmentShader);
- bool linkUniforms(gl::InfoLog &infoLog, const gl::Caps &caps);
- void indexUniforms();
- bool areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock,
- const sh::InterfaceBlock &fragmentInterfaceBlock);
+ const std::vector<SamplerBinding> &getSamplerBindings() const
+ {
+ return mState.mSamplerBindings;
+ }
+
+ const std::vector<ImageBinding> &getImageBindings() const { return mState.mImageBindings; }
+ const sh::WorkGroupSize &getComputeShaderLocalSize() const
+ {
+ return mState.mComputeShaderLocalSize;
+ }
+
+ const ProgramState &getState() const { return mState; }
static bool linkValidateVariablesBase(InfoLog &infoLog,
const std::string &variableName,
@@ -363,71 +581,147 @@ class Program final : angle::NonCopyable, public LabeledObject
const sh::ShaderVariable &fragmentVariable,
bool validatePrecision);
- static bool linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying);
- bool linkValidateTransformFeedback(InfoLog &infoLog,
- const std::vector<const sh::Varying *> &linkedVaryings,
- const Caps &caps) const;
+ GLuint getInputResourceIndex(const GLchar *name) const;
+ GLuint getOutputResourceIndex(const GLchar *name) const;
+ void getInputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
+ void getOutputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
+ void getUniformResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
+ void getBufferVariableResourceName(GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name) const;
+ const sh::Attribute &getInputResource(GLuint index) const;
+ const sh::OutputVariable &getOutputResource(GLuint index) const;
+
+ class Bindings final : angle::NonCopyable
+ {
+ public:
+ Bindings();
+ ~Bindings();
+ void bindLocation(GLuint index, const std::string &name);
+ int getBinding(const std::string &name) const;
- void gatherTransformFeedbackVaryings(const std::vector<const sh::Varying *> &varyings);
- bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps);
- void defineOutputVariables(Shader *fragmentShader);
+ typedef std::unordered_map<std::string, GLuint>::const_iterator const_iterator;
+ const_iterator begin() const;
+ const_iterator end() const;
- std::vector<const sh::Varying *> getMergedVaryings() const;
- void linkOutputVariables();
+ private:
+ std::unordered_map<std::string, GLuint> mBindings;
+ };
- bool flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoLog);
+ const Bindings &getAttributeBindings() const { return mAttributeBindings; }
+ const Bindings &getUniformLocationBindings() const { return mUniformLocationBindings; }
+ const Bindings &getFragmentInputBindings() const { return mFragmentInputBindings; }
- struct VectorAndSamplerCount
- {
- VectorAndSamplerCount() : vectorCount(0), samplerCount(0) {}
- VectorAndSamplerCount(const VectorAndSamplerCount &other) = default;
- VectorAndSamplerCount &operator=(const VectorAndSamplerCount &other) = default;
+ int getNumViews() const { return mState.getNumViews(); }
+ bool usesMultiview() const { return mState.usesMultiview(); }
- VectorAndSamplerCount &operator+=(const VectorAndSamplerCount &other)
- {
- vectorCount += other.vectorCount;
- samplerCount += other.samplerCount;
- return *this;
- }
+ struct VaryingRef
+ {
+ const sh::Varying *get() const { return vertex ? vertex : fragment; }
- unsigned int vectorCount;
- unsigned int samplerCount;
+ const sh::Varying *vertex = nullptr;
+ const sh::Varying *fragment = nullptr;
};
+ using MergedVaryings = std::map<std::string, VaryingRef>;
+
+ private:
+ ~Program() override;
+
+ void unlink();
+
+ bool linkAttributes(const Context *context, InfoLog &infoLog);
+ bool validateVertexAndFragmentInterfaceBlocks(
+ const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks,
+ const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks,
+ InfoLog &infoLog,
+ bool webglCompatibility) const;
+ bool linkInterfaceBlocks(const Context *context, InfoLog &infoLog);
+ bool linkVaryings(const Context *context, InfoLog &infoLog) const;
+
+ bool linkUniforms(const Context *context,
+ InfoLog &infoLog,
+ const Bindings &uniformLocationBindings);
+ void linkSamplerAndImageBindings();
+ bool linkAtomicCounterBuffers();
+
+ void updateLinkedShaderStages();
+
+ bool areMatchingInterfaceBlocks(InfoLog &infoLog,
+ const sh::InterfaceBlock &vertexInterfaceBlock,
+ const sh::InterfaceBlock &fragmentInterfaceBlock,
+ bool webglCompatibility) const;
+
+ static bool linkValidateVaryings(InfoLog &infoLog,
+ const std::string &varyingName,
+ const sh::Varying &vertexVarying,
+ const sh::Varying &fragmentVarying,
+ int shaderVersion);
+ bool linkValidateBuiltInVaryings(const Context *context, InfoLog &infoLog) const;
+ bool linkValidateTransformFeedback(const gl::Context *context,
+ InfoLog &infoLog,
+ const MergedVaryings &linkedVaryings,
+ const Caps &caps) const;
+ bool linkValidateGlobalNames(const Context *context, InfoLog &infoLog) const;
- VectorAndSamplerCount flattenUniform(const sh::ShaderVariable &uniform,
- const std::string &fullName,
- std::vector<LinkedUniform> *samplerUniforms);
+ void gatherTransformFeedbackVaryings(const MergedVaryings &varyings);
- void gatherInterfaceBlockInfo();
- template <typename VarT>
- void defineUniformBlockMembers(const std::vector<VarT> &fields,
- const std::string &prefix,
- int blockIndex);
+ MergedVaryings getMergedVaryings(const Context *context) const;
+ void linkOutputVariables(const Context *context);
- void defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType);
+ void setUniformValuesFromBindingQualifiers();
- template <typename T>
- void setUniformInternal(GLint location, GLsizei count, const T *v);
+ void gatherAtomicCounterBuffers();
+ void initInterfaceBlockBindings();
+ // Both these function update the cached uniform values and return a modified "count"
+ // so that the uniform update doesn't overflow the uniform.
+ template <typename T>
+ GLsizei clampUniformCount(const VariableLocation &locationInfo,
+ GLsizei count,
+ int vectorSize,
+ const T *v);
template <size_t cols, size_t rows, typename T>
- void setMatrixUniformInternal(GLint location, GLsizei count, GLboolean transpose, const T *v);
+ GLsizei clampMatrixUniformCount(GLint location, GLsizei count, GLboolean transpose, const T *v);
+
+ void updateSamplerUniform(const VariableLocation &locationInfo,
+ GLsizei clampedCount,
+ const GLint *v);
template <typename DestT>
- void getUniformInternal(GLint location, DestT *dataOut) const;
+ void getUniformInternal(const Context *context,
+ DestT *dataOut,
+ GLint location,
+ GLenum nativeType,
+ int components) const;
+
+ template <typename T>
+ void getResourceName(GLuint index,
+ const std::vector<T> &resources,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name) const;
- Data mData;
+ ProgramState mState;
rx::ProgramImpl *mProgram;
bool mValidated;
- AttributeBindings mAttributeBindings;
+ Bindings mAttributeBindings;
+
+ // Note that this has nothing to do with binding layout qualifiers that can be set for some
+ // uniforms in GLES3.1+. It is used to pre-set the location of uniforms.
+ Bindings mUniformLocationBindings;
+
+ // CHROMIUM_path_rendering
+ Bindings mFragmentInputBindings;
bool mLinked;
bool mDeleteStatus; // Flag to indicate that the program can be deleted when no longer in use
unsigned int mRefCount;
- ResourceManager *mResourceManager;
+ ShaderProgramManager *mResourceManager;
const GLuint mHandle;
InfoLog mInfoLog;
@@ -435,8 +729,7 @@ class Program final : angle::NonCopyable, public LabeledObject
// Cache for sampler validation
Optional<bool> mCachedValidateSamplersResult;
std::vector<GLenum> mTextureUnitTypesCache;
- RangeUI mSamplerUniformRange;
};
-}
+} // namespace gl
#endif // LIBANGLE_PROGRAM_H_
diff --git a/src/3rdparty/angle/src/libANGLE/ProgramLinkedResources.cpp b/src/3rdparty/angle/src/libANGLE/ProgramLinkedResources.cpp
new file mode 100644
index 0000000000..a33f751525
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/ProgramLinkedResources.cpp
@@ -0,0 +1,1040 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// UniformLinker.cpp: implements link-time checks for default block uniforms, and generates uniform
+// locations. Populates data structures related to uniforms so that they can be stored in program
+// state.
+
+#include "libANGLE/ProgramLinkedResources.h"
+
+#include "common/string_utils.h"
+#include "common/utilities.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/features.h"
+
+namespace gl
+{
+
+namespace
+{
+
+LinkedUniform *FindUniform(std::vector<LinkedUniform> &list, const std::string &name)
+{
+ for (LinkedUniform &uniform : list)
+ {
+ if (uniform.name == name)
+ return &uniform;
+ }
+
+ return nullptr;
+}
+
+int GetUniformLocationBinding(const Program::Bindings &uniformLocationBindings,
+ const sh::Uniform &uniform)
+{
+ int binding = uniformLocationBindings.getBinding(uniform.name);
+ if (uniform.isArray() && binding == -1)
+ {
+ // Bindings for array uniforms can be set either with or without [0] in the end.
+ ASSERT(angle::EndsWith(uniform.name, "[0]"));
+ std::string nameWithoutIndex = uniform.name.substr(0u, uniform.name.length() - 3u);
+ return uniformLocationBindings.getBinding(nameWithoutIndex);
+ }
+ return binding;
+}
+
+} // anonymous namespace
+
+UniformLinker::UniformLinker(const ProgramState &state) : mState(state)
+{
+}
+
+UniformLinker::~UniformLinker() = default;
+
+void UniformLinker::getResults(std::vector<LinkedUniform> *uniforms,
+ std::vector<VariableLocation> *uniformLocations)
+{
+ uniforms->swap(mUniforms);
+ uniformLocations->swap(mUniformLocations);
+}
+
+bool UniformLinker::link(const Context *context,
+ InfoLog &infoLog,
+ const Program::Bindings &uniformLocationBindings)
+{
+ if (mState.getAttachedVertexShader() && mState.getAttachedFragmentShader())
+ {
+ ASSERT(mState.getAttachedComputeShader() == nullptr);
+ if (!validateVertexAndFragmentUniforms(context, infoLog))
+ {
+ return false;
+ }
+ }
+
+ // Flatten the uniforms list (nested fields) into a simple list (no nesting).
+ // Also check the maximum uniform vector and sampler counts.
+ if (!flattenUniformsAndCheckCaps(context, infoLog))
+ {
+ return false;
+ }
+
+ if (!checkMaxCombinedAtomicCounters(context->getCaps(), infoLog))
+ {
+ return false;
+ }
+
+ if (!indexUniforms(infoLog, uniformLocationBindings))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool UniformLinker::validateVertexAndFragmentUniforms(const Context *context,
+ InfoLog &infoLog) const
+{
+ // Check that uniforms defined in the vertex and fragment shaders are identical
+ std::map<std::string, sh::Uniform> linkedUniforms;
+ const std::vector<sh::Uniform> &vertexUniforms =
+ mState.getAttachedVertexShader()->getUniforms(context);
+ const std::vector<sh::Uniform> &fragmentUniforms =
+ mState.getAttachedFragmentShader()->getUniforms(context);
+
+ for (const sh::Uniform &vertexUniform : vertexUniforms)
+ {
+ linkedUniforms[vertexUniform.name] = vertexUniform;
+ }
+
+ for (const sh::Uniform &fragmentUniform : fragmentUniforms)
+ {
+ auto entry = linkedUniforms.find(fragmentUniform.name);
+ if (entry != linkedUniforms.end())
+ {
+ const sh::Uniform &linkedUniform = entry->second;
+ const std::string &uniformName = "uniform '" + linkedUniform.name + "'";
+ if (!linkValidateUniforms(infoLog, uniformName, linkedUniform, fragmentUniform))
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+// GLSL ES Spec 3.00.3, section 4.3.5.
+bool UniformLinker::linkValidateUniforms(InfoLog &infoLog,
+ const std::string &uniformName,
+ const sh::Uniform &vertexUniform,
+ const sh::Uniform &fragmentUniform)
+{
+#if ANGLE_PROGRAM_LINK_VALIDATE_UNIFORM_PRECISION == ANGLE_ENABLED
+ const bool validatePrecision = true;
+#else
+ const bool validatePrecision = false;
+#endif
+
+ if (!Program::linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform,
+ validatePrecision))
+ {
+ return false;
+ }
+
+ // GLSL ES Spec 3.10.4, section 4.4.5.
+ if (vertexUniform.binding != -1 && fragmentUniform.binding != -1 &&
+ vertexUniform.binding != fragmentUniform.binding)
+ {
+ infoLog << "Binding layout qualifiers for " << uniformName
+ << " differ between vertex and fragment shaders.";
+ return false;
+ }
+
+ // GLSL ES Spec 3.10.4, section 9.2.1.
+ if (vertexUniform.location != -1 && fragmentUniform.location != -1 &&
+ vertexUniform.location != fragmentUniform.location)
+ {
+ infoLog << "Location layout qualifiers for " << uniformName
+ << " differ between vertex and fragment shaders.";
+ return false;
+ }
+ if (vertexUniform.offset != fragmentUniform.offset)
+ {
+ infoLog << "Offset layout qualifiers for " << uniformName
+ << " differ between vertex and fragment shaders.";
+ return false;
+ }
+
+ return true;
+}
+
+bool UniformLinker::indexUniforms(InfoLog &infoLog,
+ const Program::Bindings &uniformLocationBindings)
+{
+ // All the locations where another uniform can't be located.
+ std::set<GLuint> reservedLocations;
+ // Locations which have been allocated for an unused uniform.
+ std::set<GLuint> ignoredLocations;
+
+ int maxUniformLocation = -1;
+
+ // Gather uniform locations that have been set either using the bindUniformLocation API or by
+ // using a location layout qualifier and check conflicts between them.
+ if (!gatherUniformLocationsAndCheckConflicts(infoLog, uniformLocationBindings,
+ &reservedLocations, &ignoredLocations,
+ &maxUniformLocation))
+ {
+ return false;
+ }
+
+ // Conflicts have been checked, now we can prune non-statically used uniforms. Code further down
+ // the line relies on only having statically used uniforms in mUniforms.
+ pruneUnusedUniforms();
+
+ // Gather uniforms that have their location pre-set and uniforms that don't yet have a location.
+ std::vector<VariableLocation> unlocatedUniforms;
+ std::map<GLuint, VariableLocation> preLocatedUniforms;
+
+ for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
+ {
+ const LinkedUniform &uniform = mUniforms[uniformIndex];
+
+ if (uniform.isBuiltIn() || IsAtomicCounterType(uniform.type))
+ {
+ continue;
+ }
+
+ int preSetLocation = GetUniformLocationBinding(uniformLocationBindings, uniform);
+ int shaderLocation = uniform.location;
+
+ if (shaderLocation != -1)
+ {
+ preSetLocation = shaderLocation;
+ }
+
+ unsigned int elementCount = uniform.getBasicTypeElementCount();
+ for (unsigned int arrayIndex = 0; arrayIndex < elementCount; arrayIndex++)
+ {
+ VariableLocation location(arrayIndex, static_cast<unsigned int>(uniformIndex));
+
+ if ((arrayIndex == 0 && preSetLocation != -1) || shaderLocation != -1)
+ {
+ int elementLocation = preSetLocation + arrayIndex;
+ preLocatedUniforms[elementLocation] = location;
+ }
+ else
+ {
+ unlocatedUniforms.push_back(location);
+ }
+ }
+ }
+
+ // Make enough space for all uniforms, with pre-set locations or not.
+ mUniformLocations.resize(
+ std::max(unlocatedUniforms.size() + preLocatedUniforms.size() + ignoredLocations.size(),
+ static_cast<size_t>(maxUniformLocation + 1)));
+
+ // Assign uniforms with pre-set locations
+ for (const auto &uniform : preLocatedUniforms)
+ {
+ mUniformLocations[uniform.first] = uniform.second;
+ }
+
+ // Assign ignored uniforms
+ for (const auto &ignoredLocation : ignoredLocations)
+ {
+ mUniformLocations[ignoredLocation].markIgnored();
+ }
+
+ // Automatically assign locations for the rest of the uniforms
+ size_t nextUniformLocation = 0;
+ for (const auto &unlocatedUniform : unlocatedUniforms)
+ {
+ while (mUniformLocations[nextUniformLocation].used() ||
+ mUniformLocations[nextUniformLocation].ignored)
+ {
+ nextUniformLocation++;
+ }
+
+ ASSERT(nextUniformLocation < mUniformLocations.size());
+ mUniformLocations[nextUniformLocation] = unlocatedUniform;
+ nextUniformLocation++;
+ }
+
+ return true;
+}
+
+bool UniformLinker::gatherUniformLocationsAndCheckConflicts(
+ InfoLog &infoLog,
+ const Program::Bindings &uniformLocationBindings,
+ std::set<GLuint> *reservedLocations,
+ std::set<GLuint> *ignoredLocations,
+ int *maxUniformLocation)
+{
+ for (const LinkedUniform &uniform : mUniforms)
+ {
+ if (uniform.isBuiltIn())
+ {
+ continue;
+ }
+
+ int apiBoundLocation = GetUniformLocationBinding(uniformLocationBindings, uniform);
+ int shaderLocation = uniform.location;
+
+ if (shaderLocation != -1)
+ {
+ unsigned int elementCount = uniform.getBasicTypeElementCount();
+
+ for (unsigned int arrayIndex = 0; arrayIndex < elementCount; arrayIndex++)
+ {
+ // GLSL ES 3.10 section 4.4.3
+ int elementLocation = shaderLocation + arrayIndex;
+ *maxUniformLocation = std::max(*maxUniformLocation, elementLocation);
+ if (reservedLocations->find(elementLocation) != reservedLocations->end())
+ {
+ infoLog << "Multiple uniforms bound to location " << elementLocation << ".";
+ return false;
+ }
+ reservedLocations->insert(elementLocation);
+ if (!uniform.staticUse)
+ {
+ ignoredLocations->insert(elementLocation);
+ }
+ }
+ }
+ else if (apiBoundLocation != -1 && uniform.staticUse)
+ {
+ // Only the first location is reserved even if the uniform is an array.
+ *maxUniformLocation = std::max(*maxUniformLocation, apiBoundLocation);
+ if (reservedLocations->find(apiBoundLocation) != reservedLocations->end())
+ {
+ infoLog << "Multiple uniforms bound to location " << apiBoundLocation << ".";
+ return false;
+ }
+ reservedLocations->insert(apiBoundLocation);
+ }
+ }
+
+ // Record the uniform locations that were bound using the API for uniforms that were not found
+ // from the shader. Other uniforms should not be assigned to those locations.
+ for (const auto &locationBinding : uniformLocationBindings)
+ {
+ GLuint location = locationBinding.second;
+ if (reservedLocations->find(location) == reservedLocations->end())
+ {
+ ignoredLocations->insert(location);
+ *maxUniformLocation = std::max(*maxUniformLocation, static_cast<int>(location));
+ }
+ }
+
+ return true;
+}
+
+void UniformLinker::pruneUnusedUniforms()
+{
+ auto uniformIter = mUniforms.begin();
+ while (uniformIter != mUniforms.end())
+ {
+ if (uniformIter->staticUse)
+ {
+ ++uniformIter;
+ }
+ else
+ {
+ uniformIter = mUniforms.erase(uniformIter);
+ }
+ }
+}
+
+bool UniformLinker::flattenUniformsAndCheckCapsForShader(
+ const Context *context,
+ Shader *shader,
+ GLuint maxUniformComponents,
+ GLuint maxTextureImageUnits,
+ GLuint maxImageUnits,
+ GLuint maxAtomicCounters,
+ const std::string &componentsErrorMessage,
+ const std::string &samplerErrorMessage,
+ const std::string &imageErrorMessage,
+ const std::string &atomicCounterErrorMessage,
+ std::vector<LinkedUniform> &samplerUniforms,
+ std::vector<LinkedUniform> &imageUniforms,
+ std::vector<LinkedUniform> &atomicCounterUniforms,
+ InfoLog &infoLog)
+{
+ ShaderUniformCount shaderUniformCount;
+ for (const sh::Uniform &uniform : shader->getUniforms(context))
+ {
+ shaderUniformCount += flattenUniform(uniform, &samplerUniforms, &imageUniforms,
+ &atomicCounterUniforms, shader->getType());
+ }
+
+ if (shaderUniformCount.vectorCount > maxUniformComponents)
+ {
+ infoLog << componentsErrorMessage << maxUniformComponents << ").";
+ return false;
+ }
+
+ if (shaderUniformCount.samplerCount > maxTextureImageUnits)
+ {
+ infoLog << samplerErrorMessage << maxTextureImageUnits << ").";
+ return false;
+ }
+
+ if (shaderUniformCount.imageCount > maxImageUnits)
+ {
+ infoLog << imageErrorMessage << maxImageUnits << ").";
+ return false;
+ }
+
+ if (shaderUniformCount.atomicCounterCount > maxAtomicCounters)
+ {
+ infoLog << atomicCounterErrorMessage << maxAtomicCounters << ").";
+ return false;
+ }
+
+ return true;
+}
+
+bool UniformLinker::flattenUniformsAndCheckCaps(const Context *context, InfoLog &infoLog)
+{
+ std::vector<LinkedUniform> samplerUniforms;
+ std::vector<LinkedUniform> imageUniforms;
+ std::vector<LinkedUniform> atomicCounterUniforms;
+
+ const Caps &caps = context->getCaps();
+
+ if (mState.getAttachedComputeShader())
+ {
+ Shader *computeShader = mState.getAttachedComputeShader();
+
+ // TODO (mradev): check whether we need finer-grained component counting
+ if (!flattenUniformsAndCheckCapsForShader(
+ context, computeShader, caps.maxComputeUniformComponents / 4,
+ caps.maxComputeTextureImageUnits, caps.maxComputeImageUniforms,
+ caps.maxComputeAtomicCounters,
+ "Compute shader active uniforms exceed MAX_COMPUTE_UNIFORM_COMPONENTS (",
+ "Compute shader sampler count exceeds MAX_COMPUTE_TEXTURE_IMAGE_UNITS (",
+ "Compute shader image count exceeds MAX_COMPUTE_IMAGE_UNIFORMS (",
+ "Compute shader atomic counter count exceeds MAX_COMPUTE_ATOMIC_COUNTERS (",
+ samplerUniforms, imageUniforms, atomicCounterUniforms, infoLog))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ Shader *vertexShader = mState.getAttachedVertexShader();
+
+ if (!flattenUniformsAndCheckCapsForShader(
+ context, vertexShader, caps.maxVertexUniformVectors,
+ caps.maxVertexTextureImageUnits, caps.maxVertexImageUniforms,
+ caps.maxVertexAtomicCounters,
+ "Vertex shader active uniforms exceed MAX_VERTEX_UNIFORM_VECTORS (",
+ "Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (",
+ "Vertex shader image count exceeds MAX_VERTEX_IMAGE_UNIFORMS (",
+ "Vertex shader atomic counter count exceeds MAX_VERTEX_ATOMIC_COUNTERS (",
+ samplerUniforms, imageUniforms, atomicCounterUniforms, infoLog))
+ {
+ return false;
+ }
+
+ Shader *fragmentShader = mState.getAttachedFragmentShader();
+
+ if (!flattenUniformsAndCheckCapsForShader(
+ context, fragmentShader, caps.maxFragmentUniformVectors, caps.maxTextureImageUnits,
+ caps.maxFragmentImageUniforms, caps.maxFragmentAtomicCounters,
+ "Fragment shader active uniforms exceed MAX_FRAGMENT_UNIFORM_VECTORS (",
+ "Fragment shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (",
+ "Fragment shader image count exceeds MAX_FRAGMENT_IMAGE_UNIFORMS (",
+ "Fragment shader atomic counter count exceeds MAX_FRAGMENT_ATOMIC_COUNTERS (",
+ samplerUniforms, imageUniforms, atomicCounterUniforms, infoLog))
+ {
+ return false;
+ }
+ }
+
+ mUniforms.insert(mUniforms.end(), samplerUniforms.begin(), samplerUniforms.end());
+ mUniforms.insert(mUniforms.end(), imageUniforms.begin(), imageUniforms.end());
+ mUniforms.insert(mUniforms.end(), atomicCounterUniforms.begin(), atomicCounterUniforms.end());
+ return true;
+}
+
+UniformLinker::ShaderUniformCount UniformLinker::flattenUniform(
+ const sh::Uniform &uniform,
+ std::vector<LinkedUniform> *samplerUniforms,
+ std::vector<LinkedUniform> *imageUniforms,
+ std::vector<LinkedUniform> *atomicCounterUniforms,
+ GLenum shaderType)
+{
+ int location = uniform.location;
+ ShaderUniformCount shaderUniformCount =
+ flattenUniformImpl(uniform, uniform.name, uniform.mappedName, samplerUniforms,
+ imageUniforms, atomicCounterUniforms, shaderType, uniform.staticUse,
+ uniform.binding, uniform.offset, &location);
+ if (uniform.staticUse)
+ {
+ return shaderUniformCount;
+ }
+ return ShaderUniformCount();
+}
+
+UniformLinker::ShaderUniformCount UniformLinker::flattenArrayOfStructsUniform(
+ const sh::ShaderVariable &uniform,
+ unsigned int arrayNestingIndex,
+ const std::string &namePrefix,
+ const std::string &mappedNamePrefix,
+ std::vector<LinkedUniform> *samplerUniforms,
+ std::vector<LinkedUniform> *imageUniforms,
+ std::vector<LinkedUniform> *atomicCounterUniforms,
+ GLenum shaderType,
+ bool markStaticUse,
+ int binding,
+ int offset,
+ int *location)
+{
+ // Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the
+ // innermost.
+ ShaderUniformCount shaderUniformCount;
+ const unsigned int currentArraySize = uniform.getNestedArraySize(arrayNestingIndex);
+ for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement)
+ {
+ const std::string elementName = namePrefix + ArrayString(arrayElement);
+ const std::string elementMappedName = mappedNamePrefix + ArrayString(arrayElement);
+ if (arrayNestingIndex + 1u < uniform.arraySizes.size())
+ {
+ shaderUniformCount += flattenArrayOfStructsUniform(
+ uniform, arrayNestingIndex + 1u, elementName, elementMappedName, samplerUniforms,
+ imageUniforms, atomicCounterUniforms, shaderType, markStaticUse, binding, offset,
+ location);
+ }
+ else
+ {
+ shaderUniformCount += flattenStructUniform(
+ uniform.fields, elementName, elementMappedName, samplerUniforms, imageUniforms,
+ atomicCounterUniforms, shaderType, markStaticUse, binding, offset, location);
+ }
+ }
+ return shaderUniformCount;
+}
+
+UniformLinker::ShaderUniformCount UniformLinker::flattenStructUniform(
+ const std::vector<sh::ShaderVariable> &fields,
+ const std::string &namePrefix,
+ const std::string &mappedNamePrefix,
+ std::vector<LinkedUniform> *samplerUniforms,
+ std::vector<LinkedUniform> *imageUniforms,
+ std::vector<LinkedUniform> *atomicCounterUniforms,
+ GLenum shaderType,
+ bool markStaticUse,
+ int binding,
+ int offset,
+ int *location)
+{
+ ShaderUniformCount shaderUniformCount;
+ for (const sh::ShaderVariable &field : fields)
+ {
+ const std::string &fieldName = namePrefix + "." + field.name;
+ const std::string &fieldMappedName = mappedNamePrefix + "." + field.mappedName;
+
+ shaderUniformCount +=
+ flattenUniformImpl(field, fieldName, fieldMappedName, samplerUniforms, imageUniforms,
+ atomicCounterUniforms, shaderType, markStaticUse, -1, -1, location);
+ }
+ return shaderUniformCount;
+}
+
+UniformLinker::ShaderUniformCount UniformLinker::flattenArrayUniform(
+ const sh::ShaderVariable &uniform,
+ const std::string &namePrefix,
+ const std::string &mappedNamePrefix,
+ std::vector<LinkedUniform> *samplerUniforms,
+ std::vector<LinkedUniform> *imageUniforms,
+ std::vector<LinkedUniform> *atomicCounterUniforms,
+ GLenum shaderType,
+ bool markStaticUse,
+ int binding,
+ int offset,
+ int *location)
+{
+ ShaderUniformCount shaderUniformCount;
+
+ ASSERT(uniform.isArray());
+ for (unsigned int arrayElement = 0u; arrayElement < uniform.getOutermostArraySize();
+ ++arrayElement)
+ {
+ sh::ShaderVariable uniformElement = uniform;
+ uniformElement.indexIntoArray(arrayElement);
+ const std::string elementName = namePrefix + ArrayString(arrayElement);
+ const std::string elementMappedName = mappedNamePrefix + ArrayString(arrayElement);
+
+ shaderUniformCount += flattenUniformImpl(
+ uniformElement, elementName, elementMappedName, samplerUniforms, imageUniforms,
+ atomicCounterUniforms, shaderType, markStaticUse, binding, offset, location);
+ }
+ return shaderUniformCount;
+}
+
+UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl(
+ const sh::ShaderVariable &uniform,
+ const std::string &fullName,
+ const std::string &fullMappedName,
+ std::vector<LinkedUniform> *samplerUniforms,
+ std::vector<LinkedUniform> *imageUniforms,
+ std::vector<LinkedUniform> *atomicCounterUniforms,
+ GLenum shaderType,
+ bool markStaticUse,
+ int binding,
+ int offset,
+ int *location)
+{
+ ASSERT(location);
+ ShaderUniformCount shaderUniformCount;
+
+ if (uniform.isStruct())
+ {
+ if (uniform.isArray())
+ {
+ shaderUniformCount += flattenArrayOfStructsUniform(
+ uniform, 0u, fullName, fullMappedName, samplerUniforms, imageUniforms,
+ atomicCounterUniforms, shaderType, markStaticUse, binding, offset, location);
+ }
+ else
+ {
+ shaderUniformCount += flattenStructUniform(
+ uniform.fields, fullName, fullMappedName, samplerUniforms, imageUniforms,
+ atomicCounterUniforms, shaderType, markStaticUse, binding, offset, location);
+ }
+ return shaderUniformCount;
+ }
+ if (uniform.isArrayOfArrays())
+ {
+ // GLES 3.1 November 2016 section 7.3.1 page 77:
+ // "For an active variable declared as an array of an aggregate data type (structures or
+ // arrays), a separate entry will be generated for each active array element"
+ return flattenArrayUniform(uniform, fullName, fullMappedName, samplerUniforms,
+ imageUniforms, atomicCounterUniforms, shaderType, markStaticUse,
+ binding, offset, location);
+ }
+
+ // Not a struct
+ bool isSampler = IsSamplerType(uniform.type);
+ bool isImage = IsImageType(uniform.type);
+ bool isAtomicCounter = IsAtomicCounterType(uniform.type);
+ std::vector<gl::LinkedUniform> *uniformList = &mUniforms;
+ if (isSampler)
+ {
+ uniformList = samplerUniforms;
+ }
+ else if (isImage)
+ {
+ uniformList = imageUniforms;
+ }
+ else if (isAtomicCounter)
+ {
+ uniformList = atomicCounterUniforms;
+ }
+
+ std::string fullNameWithArrayIndex(fullName);
+ std::string fullMappedNameWithArrayIndex(fullMappedName);
+
+ if (uniform.isArray())
+ {
+ // We're following the GLES 3.1 November 2016 spec section 7.3.1.1 Naming Active Resources
+ // and including [0] at the end of array variable names.
+ fullNameWithArrayIndex += "[0]";
+ fullMappedNameWithArrayIndex += "[0]";
+ }
+
+ LinkedUniform *existingUniform = FindUniform(*uniformList, fullNameWithArrayIndex);
+ if (existingUniform)
+ {
+ if (binding != -1)
+ {
+ existingUniform->binding = binding;
+ }
+ if (offset != -1)
+ {
+ existingUniform->offset = offset;
+ }
+ if (*location != -1)
+ {
+ existingUniform->location = *location;
+ }
+ if (markStaticUse)
+ {
+ existingUniform->staticUse = true;
+ existingUniform->setStaticUse(shaderType, true);
+ }
+ }
+ else
+ {
+ ASSERT(uniform.arraySizes.size() <= 1u);
+ LinkedUniform linkedUniform(uniform.type, uniform.precision, fullNameWithArrayIndex,
+ uniform.arraySizes, binding, offset, *location, -1,
+ sh::BlockMemberInfo::getDefaultBlockInfo());
+ linkedUniform.mappedName = fullMappedNameWithArrayIndex;
+ linkedUniform.staticUse = markStaticUse;
+ linkedUniform.flattenedOffsetInParentArrays = uniform.flattenedOffsetInParentArrays;
+ if (markStaticUse)
+ {
+ linkedUniform.setStaticUse(shaderType, true);
+ }
+
+ uniformList->push_back(linkedUniform);
+ }
+
+ // Struct and array of arrays uniforms get flattened so we can use getBasicTypeElementCount().
+ unsigned int elementCount = uniform.getBasicTypeElementCount();
+
+ // Samplers and images aren't "real" uniforms, so they don't count towards register usage.
+ // Likewise, don't count "real" uniforms towards opaque count.
+ shaderUniformCount.vectorCount =
+ (IsOpaqueType(uniform.type) ? 0 : (VariableRegisterCount(uniform.type) * elementCount));
+ shaderUniformCount.samplerCount = (isSampler ? elementCount : 0);
+ shaderUniformCount.imageCount = (isImage ? elementCount : 0);
+ shaderUniformCount.atomicCounterCount = (isAtomicCounter ? elementCount : 0);
+
+ if (*location != -1)
+ {
+ *location += elementCount;
+ }
+
+ return shaderUniformCount;
+}
+
+bool UniformLinker::checkMaxCombinedAtomicCounters(const Caps &caps, InfoLog &infoLog)
+{
+ unsigned int atomicCounterCount = 0;
+ for (const auto &uniform : mUniforms)
+ {
+ if (IsAtomicCounterType(uniform.type) && uniform.staticUse)
+ {
+ atomicCounterCount += uniform.getBasicTypeElementCount();
+ if (atomicCounterCount > caps.maxCombinedAtomicCounters)
+ {
+ infoLog << "atomic counter count exceeds MAX_COMBINED_ATOMIC_COUNTERS"
+ << caps.maxCombinedAtomicCounters << ").";
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+// InterfaceBlockLinker implementation.
+InterfaceBlockLinker::InterfaceBlockLinker(std::vector<InterfaceBlock> *blocksOut)
+ : mBlocksOut(blocksOut)
+{
+}
+
+InterfaceBlockLinker::~InterfaceBlockLinker()
+{
+}
+
+void InterfaceBlockLinker::addShaderBlocks(GLenum shader,
+ const std::vector<sh::InterfaceBlock> *blocks)
+{
+ mShaderBlocks.push_back(std::make_pair(shader, blocks));
+}
+
+void InterfaceBlockLinker::linkBlocks(const GetBlockSize &getBlockSize,
+ const GetBlockMemberInfo &getMemberInfo) const
+{
+ ASSERT(mBlocksOut->empty());
+
+ std::set<std::string> visitedList;
+
+ for (const auto &shaderBlocks : mShaderBlocks)
+ {
+ const GLenum shaderType = shaderBlocks.first;
+
+ for (const auto &block : *shaderBlocks.second)
+ {
+ // Only 'packed' blocks are allowed to be considered inactive.
+ if (!block.staticUse && block.layout == sh::BLOCKLAYOUT_PACKED)
+ continue;
+
+ if (visitedList.count(block.name) > 0)
+ {
+ if (block.staticUse)
+ {
+ for (InterfaceBlock &priorBlock : *mBlocksOut)
+ {
+ if (block.name == priorBlock.name)
+ {
+ priorBlock.setStaticUse(shaderType, true);
+ // TODO(jiajia.qin@intel.com): update the block members static use.
+ }
+ }
+ }
+ }
+ else
+ {
+ defineInterfaceBlock(getBlockSize, getMemberInfo, block, shaderType);
+ visitedList.insert(block.name);
+ }
+ }
+ }
+}
+
+template <typename VarT>
+void InterfaceBlockLinker::defineArrayOfStructsBlockMembers(const GetBlockMemberInfo &getMemberInfo,
+ const VarT &field,
+ unsigned int arrayNestingIndex,
+ const std::string &prefix,
+ const std::string &mappedPrefix,
+ int blockIndex,
+ bool singleEntryForTopLevelArray,
+ int topLevelArraySize) const
+{
+ // Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the
+ // innermost.
+ unsigned int entryGenerationArraySize = field.getNestedArraySize(arrayNestingIndex);
+ if (singleEntryForTopLevelArray)
+ {
+ entryGenerationArraySize = 1;
+ }
+ for (unsigned int arrayElement = 0u; arrayElement < entryGenerationArraySize; ++arrayElement)
+ {
+ const std::string elementName = prefix + ArrayString(arrayElement);
+ const std::string elementMappedName = mappedPrefix + ArrayString(arrayElement);
+ if (arrayNestingIndex + 1u < field.arraySizes.size())
+ {
+ defineArrayOfStructsBlockMembers(getMemberInfo, field, arrayNestingIndex + 1u,
+ elementName, elementMappedName, blockIndex, false,
+ topLevelArraySize);
+ }
+ else
+ {
+ defineBlockMembers(getMemberInfo, field.fields, elementName, elementMappedName,
+ blockIndex, false, topLevelArraySize);
+ }
+ }
+}
+
+template <typename VarT>
+void InterfaceBlockLinker::defineBlockMembers(const GetBlockMemberInfo &getMemberInfo,
+ const std::vector<VarT> &fields,
+ const std::string &prefix,
+ const std::string &mappedPrefix,
+ int blockIndex,
+ bool singleEntryForTopLevelArray,
+ int topLevelArraySize) const
+{
+ for (const VarT &field : fields)
+ {
+ std::string fullName = (prefix.empty() ? field.name : prefix + "." + field.name);
+ std::string fullMappedName =
+ (mappedPrefix.empty() ? field.mappedName : mappedPrefix + "." + field.mappedName);
+
+ defineBlockMember(getMemberInfo, field, fullName, fullMappedName, blockIndex,
+ singleEntryForTopLevelArray, topLevelArraySize);
+ }
+}
+
+template <typename VarT>
+void InterfaceBlockLinker::defineBlockMember(const GetBlockMemberInfo &getMemberInfo,
+ const VarT &field,
+ const std::string &fullName,
+ const std::string &fullMappedName,
+ int blockIndex,
+ bool singleEntryForTopLevelArray,
+ int topLevelArraySize) const
+{
+ int nextArraySize = topLevelArraySize;
+ if (((field.isArray() && field.isStruct()) || field.isArrayOfArrays()) &&
+ singleEntryForTopLevelArray)
+ {
+ // In OpenGL ES 3.10 spec, session 7.3.1.1 'For an active shader storage block
+ // member declared as an array of an aggregate type, an entry will be generated only
+ // for the first array element, regardless of its type.'
+ nextArraySize = field.getOutermostArraySize();
+ }
+
+ if (field.isStruct())
+ {
+ if (field.isArray())
+ {
+ defineArrayOfStructsBlockMembers(getMemberInfo, field, 0u, fullName, fullMappedName,
+ blockIndex, singleEntryForTopLevelArray,
+ nextArraySize);
+ }
+ else
+ {
+ ASSERT(nextArraySize == topLevelArraySize);
+ defineBlockMembers(getMemberInfo, field.fields, fullName, fullMappedName, blockIndex,
+ false, nextArraySize);
+ }
+ return;
+ }
+ if (field.isArrayOfArrays())
+ {
+ unsigned int entryGenerationArraySize = field.getOutermostArraySize();
+ if (singleEntryForTopLevelArray)
+ {
+ entryGenerationArraySize = 1u;
+ }
+ for (unsigned int arrayElement = 0u; arrayElement < entryGenerationArraySize;
+ ++arrayElement)
+ {
+ VarT fieldElement = field;
+ fieldElement.indexIntoArray(arrayElement);
+ const std::string elementName = fullName + ArrayString(arrayElement);
+ const std::string elementMappedName = fullMappedName + ArrayString(arrayElement);
+
+ defineBlockMember(getMemberInfo, fieldElement, elementName, elementMappedName,
+ blockIndex, false, nextArraySize);
+ }
+ return;
+ }
+
+ // If getBlockMemberInfo returns false, the variable is optimized out.
+ sh::BlockMemberInfo memberInfo;
+ if (!getMemberInfo(fullName, fullMappedName, &memberInfo))
+ {
+ return;
+ }
+
+ std::string fullNameWithArrayIndex = fullName;
+ std::string fullMappedNameWithArrayIndex = fullMappedName;
+
+ if (field.isArray())
+ {
+ fullNameWithArrayIndex += "[0]";
+ fullMappedNameWithArrayIndex += "[0]";
+ }
+
+ ASSERT(nextArraySize == topLevelArraySize);
+ defineBlockMemberImpl(field, fullNameWithArrayIndex, fullMappedNameWithArrayIndex, blockIndex,
+ memberInfo, nextArraySize);
+}
+
+void InterfaceBlockLinker::defineInterfaceBlock(const GetBlockSize &getBlockSize,
+ const GetBlockMemberInfo &getMemberInfo,
+ const sh::InterfaceBlock &interfaceBlock,
+ GLenum shaderType) const
+{
+ size_t blockSize = 0;
+ std::vector<unsigned int> blockIndexes;
+
+ int blockIndex = static_cast<int>(mBlocksOut->size());
+ // Track the first and last block member index to determine the range of active block members in
+ // the block.
+ size_t firstBlockMemberIndex = getCurrentBlockMemberIndex();
+ defineBlockMembers(getMemberInfo, interfaceBlock.fields, interfaceBlock.fieldPrefix(),
+ interfaceBlock.fieldMappedPrefix(), blockIndex,
+ interfaceBlock.blockType == sh::BlockType::BLOCK_BUFFER, 1);
+ size_t lastBlockMemberIndex = getCurrentBlockMemberIndex();
+
+ for (size_t blockMemberIndex = firstBlockMemberIndex; blockMemberIndex < lastBlockMemberIndex;
+ ++blockMemberIndex)
+ {
+ blockIndexes.push_back(static_cast<unsigned int>(blockMemberIndex));
+ }
+
+ // ESSL 3.10 section 4.4.4 page 58:
+ // Any uniform or shader storage block declared without a binding qualifier is initially
+ // assigned to block binding point zero.
+ int blockBinding = (interfaceBlock.binding == -1 ? 0 : interfaceBlock.binding);
+ for (unsigned int arrayElement = 0; arrayElement < interfaceBlock.elementCount();
+ ++arrayElement)
+ {
+ std::string blockArrayName = interfaceBlock.name;
+ std::string blockMappedArrayName = interfaceBlock.mappedName;
+ if (interfaceBlock.isArray())
+ {
+ blockArrayName += ArrayString(arrayElement);
+ blockMappedArrayName += ArrayString(arrayElement);
+ }
+
+ // Don't define this block at all if it's not active in the implementation.
+ if (!getBlockSize(blockArrayName, blockMappedArrayName, &blockSize))
+ {
+ continue;
+ }
+
+ InterfaceBlock block(interfaceBlock.name, interfaceBlock.mappedName,
+ interfaceBlock.isArray(), arrayElement, blockBinding + arrayElement);
+ block.memberIndexes = blockIndexes;
+ block.setStaticUse(shaderType, interfaceBlock.staticUse);
+
+ // Since all block elements in an array share the same active interface blocks, they
+ // will all be active once any block member is used. So, since interfaceBlock.name[0]
+ // was active, here we will add every block element in the array.
+ block.dataSize = static_cast<unsigned int>(blockSize);
+ mBlocksOut->push_back(block);
+ }
+}
+
+// UniformBlockLinker implementation.
+UniformBlockLinker::UniformBlockLinker(std::vector<InterfaceBlock> *blocksOut,
+ std::vector<LinkedUniform> *uniformsOut)
+ : InterfaceBlockLinker(blocksOut), mUniformsOut(uniformsOut)
+{
+}
+
+UniformBlockLinker::~UniformBlockLinker()
+{
+}
+
+void UniformBlockLinker::defineBlockMemberImpl(const sh::ShaderVariable &field,
+ const std::string &fullName,
+ const std::string &fullMappedName,
+ int blockIndex,
+ const sh::BlockMemberInfo &memberInfo,
+ int /*topLevelArraySize*/) const
+{
+ LinkedUniform newUniform(field.type, field.precision, fullName, field.arraySizes, -1, -1, -1,
+ blockIndex, memberInfo);
+ newUniform.mappedName = fullMappedName;
+ // TODO(jiajia.qin@intel.com): update the block memeber static use.
+
+ // Since block uniforms have no location, we don't need to store them in the uniform locations
+ // list.
+ mUniformsOut->push_back(newUniform);
+}
+
+size_t UniformBlockLinker::getCurrentBlockMemberIndex() const
+{
+ return mUniformsOut->size();
+}
+
+// ShaderStorageBlockLinker implementation.
+ShaderStorageBlockLinker::ShaderStorageBlockLinker(std::vector<InterfaceBlock> *blocksOut,
+ std::vector<BufferVariable> *bufferVariablesOut)
+ : InterfaceBlockLinker(blocksOut), mBufferVariablesOut(bufferVariablesOut)
+{
+}
+
+ShaderStorageBlockLinker::~ShaderStorageBlockLinker()
+{
+}
+
+void ShaderStorageBlockLinker::defineBlockMemberImpl(const sh::ShaderVariable &field,
+ const std::string &fullName,
+ const std::string &fullMappedName,
+ int blockIndex,
+ const sh::BlockMemberInfo &memberInfo,
+ int topLevelArraySize) const
+{
+ BufferVariable newBufferVariable(field.type, field.precision, fullName, field.arraySizes,
+ blockIndex, memberInfo);
+ newBufferVariable.mappedName = fullMappedName;
+ // TODO(jiajia.qin@intel.com): update the block memeber static use.
+
+ newBufferVariable.topLevelArraySize = topLevelArraySize;
+
+ mBufferVariablesOut->push_back(newBufferVariable);
+}
+
+size_t ShaderStorageBlockLinker::getCurrentBlockMemberIndex() const
+{
+ return mBufferVariablesOut->size();
+}
+
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/ProgramLinkedResources.h b/src/3rdparty/angle/src/libANGLE/ProgramLinkedResources.h
new file mode 100644
index 0000000000..1bf91b7f3b
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/ProgramLinkedResources.h
@@ -0,0 +1,274 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// UniformLinker.h: implements link-time checks for default block uniforms, and generates uniform
+// locations. Populates data structures related to uniforms so that they can be stored in program
+// state.
+
+#ifndef LIBANGLE_UNIFORMLINKER_H_
+#define LIBANGLE_UNIFORMLINKER_H_
+
+#include "libANGLE/Program.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/VaryingPacking.h"
+
+#include <functional>
+
+namespace gl
+{
+
+class UniformLinker
+{
+ public:
+ UniformLinker(const ProgramState &state);
+ ~UniformLinker();
+
+ bool link(const Context *context,
+ InfoLog &infoLog,
+ const Program::Bindings &uniformLocationBindings);
+
+ void getResults(std::vector<LinkedUniform> *uniforms,
+ std::vector<VariableLocation> *uniformLocations);
+
+ private:
+ struct ShaderUniformCount
+ {
+ ShaderUniformCount() : vectorCount(0), samplerCount(0), imageCount(0), atomicCounterCount(0)
+ {
+ }
+ ShaderUniformCount(const ShaderUniformCount &other) = default;
+ ShaderUniformCount &operator=(const ShaderUniformCount &other) = default;
+
+ ShaderUniformCount &operator+=(const ShaderUniformCount &other)
+ {
+ vectorCount += other.vectorCount;
+ samplerCount += other.samplerCount;
+ imageCount += other.imageCount;
+ atomicCounterCount += other.atomicCounterCount;
+ return *this;
+ }
+
+ unsigned int vectorCount;
+ unsigned int samplerCount;
+ unsigned int imageCount;
+ unsigned int atomicCounterCount;
+ };
+
+ bool validateVertexAndFragmentUniforms(const Context *context, InfoLog &infoLog) const;
+
+ static bool linkValidateUniforms(InfoLog &infoLog,
+ const std::string &uniformName,
+ const sh::Uniform &vertexUniform,
+ const sh::Uniform &fragmentUniform);
+
+ bool flattenUniformsAndCheckCapsForShader(const Context *context,
+ Shader *shader,
+ GLuint maxUniformComponents,
+ GLuint maxTextureImageUnits,
+ GLuint maxImageUnits,
+ GLuint maxAtomicCounters,
+ const std::string &componentsErrorMessage,
+ const std::string &samplerErrorMessage,
+ const std::string &imageErrorMessage,
+ const std::string &atomicCounterErrorMessage,
+ std::vector<LinkedUniform> &samplerUniforms,
+ std::vector<LinkedUniform> &imageUniforms,
+ std::vector<LinkedUniform> &atomicCounterUniforms,
+ InfoLog &infoLog);
+
+ bool flattenUniformsAndCheckCaps(const Context *context, InfoLog &infoLog);
+ bool checkMaxCombinedAtomicCounters(const Caps &caps, InfoLog &infoLog);
+
+ ShaderUniformCount flattenUniform(const sh::Uniform &uniform,
+ std::vector<LinkedUniform> *samplerUniforms,
+ std::vector<LinkedUniform> *imageUniforms,
+ std::vector<LinkedUniform> *atomicCounterUniforms,
+ GLenum shaderType);
+
+ ShaderUniformCount flattenArrayOfStructsUniform(
+ const sh::ShaderVariable &uniform,
+ unsigned int arrayNestingIndex,
+ const std::string &namePrefix,
+ const std::string &mappedNamePrefix,
+ std::vector<LinkedUniform> *samplerUniforms,
+ std::vector<LinkedUniform> *imageUniforms,
+ std::vector<LinkedUniform> *atomicCounterUniforms,
+ GLenum shaderType,
+ bool markStaticUse,
+ int binding,
+ int offset,
+ int *location);
+
+ ShaderUniformCount flattenStructUniform(const std::vector<sh::ShaderVariable> &fields,
+ const std::string &namePrefix,
+ const std::string &mappedNamePrefix,
+ std::vector<LinkedUniform> *samplerUniforms,
+ std::vector<LinkedUniform> *imageUniforms,
+ std::vector<LinkedUniform> *atomicCounterUniforms,
+ GLenum shaderType,
+ bool markStaticUse,
+ int binding,
+ int offset,
+ int *location);
+
+ ShaderUniformCount flattenArrayUniform(const sh::ShaderVariable &uniform,
+ const std::string &fullName,
+ const std::string &fullMappedName,
+ std::vector<LinkedUniform> *samplerUniforms,
+ std::vector<LinkedUniform> *imageUniforms,
+ std::vector<LinkedUniform> *atomicCounterUniforms,
+ GLenum shaderType,
+ bool markStaticUse,
+ int binding,
+ int offset,
+ int *location);
+
+ // markStaticUse is given as a separate parameter because it is tracked here at struct
+ // granularity.
+ ShaderUniformCount flattenUniformImpl(const sh::ShaderVariable &uniform,
+ const std::string &fullName,
+ const std::string &fullMappedName,
+ std::vector<LinkedUniform> *samplerUniforms,
+ std::vector<LinkedUniform> *imageUniforms,
+ std::vector<LinkedUniform> *atomicCounterUniforms,
+ GLenum shaderType,
+ bool markStaticUse,
+ int binding,
+ int offset,
+ int *location);
+
+ bool indexUniforms(InfoLog &infoLog, const Program::Bindings &uniformLocationBindings);
+ bool gatherUniformLocationsAndCheckConflicts(InfoLog &infoLog,
+ const Program::Bindings &uniformLocationBindings,
+ std::set<GLuint> *reservedLocations,
+ std::set<GLuint> *ignoredLocations,
+ int *maxUniformLocation);
+ void pruneUnusedUniforms();
+
+ const ProgramState &mState;
+ std::vector<LinkedUniform> mUniforms;
+ std::vector<VariableLocation> mUniformLocations;
+};
+
+// This class is intended to be used during the link step to store interface block information.
+// It is called by the Impl class during ProgramImpl::link so that it has access to the
+// real block size and layout.
+class InterfaceBlockLinker : angle::NonCopyable
+{
+ public:
+ virtual ~InterfaceBlockLinker();
+
+ using GetBlockSize = std::function<
+ bool(const std::string &blockName, const std::string &blockMappedName, size_t *sizeOut)>;
+ using GetBlockMemberInfo = std::function<
+ bool(const std::string &name, const std::string &mappedName, sh::BlockMemberInfo *infoOut)>;
+
+ // This is called once per shader stage. It stores a pointer to the block vector, so it's
+ // important that this class does not persist longer than the duration of Program::link.
+ void addShaderBlocks(GLenum shader, const std::vector<sh::InterfaceBlock> *blocks);
+
+ // This is called once during a link operation, after all shader blocks are added.
+ void linkBlocks(const GetBlockSize &getBlockSize,
+ const GetBlockMemberInfo &getMemberInfo) const;
+
+ protected:
+ InterfaceBlockLinker(std::vector<InterfaceBlock> *blocksOut);
+ void defineInterfaceBlock(const GetBlockSize &getBlockSize,
+ const GetBlockMemberInfo &getMemberInfo,
+ const sh::InterfaceBlock &interfaceBlock,
+ GLenum shaderType) const;
+
+ template <typename VarT>
+ void defineBlockMembers(const GetBlockMemberInfo &getMemberInfo,
+ const std::vector<VarT> &fields,
+ const std::string &prefix,
+ const std::string &mappedPrefix,
+ int blockIndex,
+ bool singleEntryForTopLevelArray,
+ int topLevelArraySize) const;
+ template <typename VarT>
+ void defineBlockMember(const GetBlockMemberInfo &getMemberInfo,
+ const VarT &field,
+ const std::string &fullName,
+ const std::string &fullMappedName,
+ int blockIndex,
+ bool singleEntryForTopLevelArray,
+ int topLevelArraySize) const;
+
+ virtual void defineBlockMemberImpl(const sh::ShaderVariable &field,
+ const std::string &fullName,
+ const std::string &fullMappedName,
+ int blockIndex,
+ const sh::BlockMemberInfo &memberInfo,
+ int topLevelArraySize) const = 0;
+ virtual size_t getCurrentBlockMemberIndex() const = 0;
+
+ using ShaderBlocks = std::pair<GLenum, const std::vector<sh::InterfaceBlock> *>;
+ std::vector<ShaderBlocks> mShaderBlocks;
+
+ std::vector<InterfaceBlock> *mBlocksOut;
+
+ private:
+ template <typename VarT>
+ void defineArrayOfStructsBlockMembers(const GetBlockMemberInfo &getMemberInfo,
+ const VarT &field,
+ unsigned int arrayNestingIndex,
+ const std::string &prefix,
+ const std::string &mappedPrefix,
+ int blockIndex,
+ bool singleEntryForTopLevelArray,
+ int topLevelArraySize) const;
+};
+
+class UniformBlockLinker final : public InterfaceBlockLinker
+{
+ public:
+ UniformBlockLinker(std::vector<InterfaceBlock> *blocksOut,
+ std::vector<LinkedUniform> *uniformsOut);
+ ~UniformBlockLinker() override;
+
+ private:
+ void defineBlockMemberImpl(const sh::ShaderVariable &field,
+ const std::string &fullName,
+ const std::string &fullMappedName,
+ int blockIndex,
+ const sh::BlockMemberInfo &memberInfo,
+ int topLevelArraySize) const override;
+ size_t getCurrentBlockMemberIndex() const override;
+ std::vector<LinkedUniform> *mUniformsOut;
+};
+
+class ShaderStorageBlockLinker final : public InterfaceBlockLinker
+{
+ public:
+ ShaderStorageBlockLinker(std::vector<InterfaceBlock> *blocksOut,
+ std::vector<BufferVariable> *bufferVariablesOut);
+ ~ShaderStorageBlockLinker() override;
+
+ private:
+ void defineBlockMemberImpl(const sh::ShaderVariable &field,
+ const std::string &fullName,
+ const std::string &fullMappedName,
+ int blockIndex,
+ const sh::BlockMemberInfo &memberInfo,
+ int topLevelArraySize) const override;
+ size_t getCurrentBlockMemberIndex() const override;
+ std::vector<BufferVariable> *mBufferVariablesOut;
+};
+
+// The link operation is responsible for finishing the link of uniform and interface blocks.
+// This way it can filter out unreferenced resources and still have access to the info.
+// TODO(jmadill): Integrate uniform linking/filtering as well as interface blocks.
+struct ProgramLinkedResources
+{
+ VaryingPacking varyingPacking;
+ UniformBlockLinker uniformBlockLinker;
+ ShaderStorageBlockLinker shaderStorageBlockLinker;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_UNIFORMLINKER_H_
diff --git a/src/3rdparty/angle/src/libANGLE/ProgramPipeline.cpp b/src/3rdparty/angle/src/libANGLE/ProgramPipeline.cpp
new file mode 100644
index 0000000000..0445512090
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/ProgramPipeline.cpp
@@ -0,0 +1,65 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ProgramPipeline.cpp: Implements the gl::ProgramPipeline class.
+// Implements GL program pipeline objects and related functionality.
+// [OpenGL ES 3.1] section 7.4 page 105.
+
+#include "libANGLE/ProgramPipeline.h"
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/ProgramPipelineImpl.h"
+
+namespace gl
+{
+
+ProgramPipelineState::ProgramPipelineState() : mLabel()
+{
+}
+
+ProgramPipelineState::~ProgramPipelineState()
+{
+}
+
+const std::string &ProgramPipelineState::getLabel() const
+{
+ return mLabel;
+}
+
+ProgramPipeline::ProgramPipeline(rx::GLImplFactory *factory, GLuint handle)
+ : RefCountObject(handle),
+ mProgramPipeline(factory->createProgramPipeline(mState))
+{
+ ASSERT(mProgramPipeline);
+}
+
+ProgramPipeline::~ProgramPipeline()
+{
+ mProgramPipeline.release();
+}
+
+Error ProgramPipeline::onDestroy(const Context *context)
+{
+ return NoError();
+}
+
+void ProgramPipeline::setLabel(const std::string &label)
+{
+ mState.mLabel = label;
+}
+
+const std::string &ProgramPipeline::getLabel() const
+{
+ return mState.mLabel;
+}
+
+rx::ProgramPipelineImpl *ProgramPipeline::getImplementation() const
+{
+ return mProgramPipeline.get();
+}
+
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/ProgramPipeline.h b/src/3rdparty/angle/src/libANGLE/ProgramPipeline.h
new file mode 100644
index 0000000000..2aac87c7b8
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/ProgramPipeline.h
@@ -0,0 +1,65 @@
+//
+// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ProgramPipeline.h: Defines the gl::ProgramPipeline class.
+// Implements GL program pipeline objects and related functionality.
+// [OpenGL ES 3.1] section 7.4 page 105.
+
+#ifndef LIBANGLE_PROGRAMPIPELINE_H_
+#define LIBANGLE_PROGRAMPIPELINE_H_
+
+#include <memory>
+
+#include "common/angleutils.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/RefCountObject.h"
+
+namespace rx
+{
+class GLImplFactory;
+class ProgramPipelineImpl;
+};
+
+namespace gl
+{
+class Context;
+class ProgramPipeline;
+
+class ProgramPipelineState final : angle::NonCopyable
+{
+ public:
+ ProgramPipelineState();
+ ~ProgramPipelineState();
+
+ const std::string &getLabel() const;
+
+ private:
+ friend class ProgramPipeline;
+
+ std::string mLabel;
+};
+
+class ProgramPipeline final : public RefCountObject, public LabeledObject
+{
+ public:
+ ProgramPipeline(rx::GLImplFactory *factory, GLuint handle);
+ ~ProgramPipeline() override;
+
+ Error onDestroy(const Context *context) override;
+
+ void setLabel(const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ rx::ProgramPipelineImpl *getImplementation() const;
+
+ private:
+ std::unique_ptr<rx::ProgramPipelineImpl> mProgramPipeline;
+
+ ProgramPipelineState mState;
+};
+}
+
+#endif // LIBANGLE_PROGRAMPIPELINE_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Query.h b/src/3rdparty/angle/src/libANGLE/Query.h
index 5486f983e7..c307eaaf08 100644
--- a/src/3rdparty/angle/src/libANGLE/Query.h
+++ b/src/3rdparty/angle/src/libANGLE/Query.h
@@ -29,7 +29,8 @@ class Query final : public RefCountObject, public LabeledObject
{
public:
Query(rx::QueryImpl *impl, GLuint id);
- virtual ~Query();
+ void destroy(const gl::Context *context) {}
+ ~Query() override;
void setLabel(const std::string &label) override;
const std::string &getLabel() const override;
diff --git a/src/3rdparty/angle/src/libANGLE/RefCountObject.cpp b/src/3rdparty/angle/src/libANGLE/RefCountObject.cpp
deleted file mode 100644
index b1210200cf..0000000000
--- a/src/3rdparty/angle/src/libANGLE/RefCountObject.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// RefCountObject.cpp: Defines the gl::RefCountObject base class that provides
-// lifecycle support for GL objects using the traditional BindObject scheme, but
-// that need to be reference counted for correct cross-context deletion.
-// (Concretely, textures, buffers and renderbuffers.)
-
-#include "RefCountObject.h"
-
-RefCountObject::RefCountObject(GLuint id)
- : mId(id),
- mRefCount(0)
-{
-}
-
-RefCountObject::~RefCountObject()
-{
- ASSERT(mRefCount == 0);
-}
-
-void RefCountObject::addRef() const
-{
- mRefCount++;
-}
-
-void RefCountObject::release() const
-{
- ASSERT(mRefCount > 0);
-
- if (--mRefCount == 0)
- {
- delete this;
- }
-}
-
diff --git a/src/3rdparty/angle/src/libANGLE/RefCountObject.h b/src/3rdparty/angle/src/libANGLE/RefCountObject.h
index 86e6d788b5..cb41cc27f4 100644
--- a/src/3rdparty/angle/src/libANGLE/RefCountObject.h
+++ b/src/3rdparty/angle/src/libANGLE/RefCountObject.h
@@ -12,16 +12,21 @@
#ifndef LIBANGLE_REFCOUNTOBJECT_H_
#define LIBANGLE_REFCOUNTOBJECT_H_
-#include "common/debug.h"
-
#include "angle_gl.h"
+#include "common/debug.h"
+#include "libANGLE/Error.h"
#include <cstddef>
-class RefCountObject : angle::NonCopyable
+namespace gl
+{
+class Context;
+
+class RefCountObjectNoID : angle::NonCopyable
{
public:
- explicit RefCountObject(GLuint id) : mId(id), mRefCount(0) {}
+ RefCountObjectNoID() : mRefCount(0) {}
+ virtual Error onDestroy(const Context *context);
void addRef() const { ++mRefCount; }
@@ -35,17 +40,56 @@ class RefCountObject : angle::NonCopyable
}
}
+ size_t getRefCount() const { return mRefCount; }
+
+ protected:
+ virtual ~RefCountObjectNoID();
+
+ // A specialized release method for objects which need a destroy context.
+ void release(const gl::Context *context)
+ {
+ ASSERT(mRefCount > 0);
+ if (--mRefCount == 0)
+ {
+ ANGLE_SWALLOW_ERR(onDestroy(context));
+ delete this;
+ }
+ }
+
+ template <class ObjectType>
+ friend class BindingPointer;
+ mutable std::size_t mRefCount;
+};
+
+inline RefCountObjectNoID::~RefCountObjectNoID()
+{
+ ASSERT(mRefCount == 0);
+}
+
+inline Error RefCountObjectNoID::onDestroy(const Context *context)
+{
+ return NoError();
+}
+
+template <class ObjectType>
+class BindingPointer;
+
+class RefCountObject : RefCountObjectNoID
+{
+ public:
+ explicit RefCountObject(GLuint id) : mId(id) {}
+
GLuint id() const { return mId; }
- size_t getRefCount() const { return mRefCount; }
+ using RefCountObjectNoID::release;
+ using RefCountObjectNoID::addRef;
+ using RefCountObjectNoID::getRefCount;
protected:
- virtual ~RefCountObject() { ASSERT(mRefCount == 0); }
+ ~RefCountObject() override {}
private:
GLuint mId;
-
- mutable std::size_t mRefCount;
};
template <class ObjectType>
@@ -57,15 +101,17 @@ class BindingPointer
{
}
- BindingPointer(const BindingPointer<ObjectType> &other)
- : mObject(nullptr)
+ BindingPointer(ObjectType *object) : mObject(object) { mObject->addRef(); }
+
+ BindingPointer(const BindingPointer<ObjectType> &other) : mObject(other.mObject)
{
- set(other.mObject);
+ mObject->addRef();
}
- void operator=(const BindingPointer<ObjectType> &other)
+ BindingPointer &operator=(BindingPointer<ObjectType> &&other)
{
- set(other.mObject);
+ std::swap(mObject, other.mObject);
+ return *this;
}
virtual ~BindingPointer()
@@ -74,11 +120,12 @@ class BindingPointer
ASSERT(mObject == nullptr);
}
- virtual void set(ObjectType *newObject)
+ virtual void set(const Context *context, ObjectType *newObject)
{
// addRef first in case newObject == mObject and this is the last reference to it.
- if (newObject != nullptr) reinterpret_cast<const RefCountObject*>(newObject)->addRef();
- if (mObject != nullptr) reinterpret_cast<const RefCountObject*>(mObject)->release();
+ if (newObject != nullptr) reinterpret_cast<const RefCountObjectNoID*>(newObject)->addRef();
+ if (mObject != nullptr)
+ reinterpret_cast<RefCountObjectNoID *>(mObject)->release(context);
mObject = newObject;
}
@@ -104,16 +151,16 @@ class OffsetBindingPointer : public BindingPointer<ObjectType>
public:
OffsetBindingPointer() : mOffset(0), mSize(0) { }
- void set(ObjectType *newObject) override
+ void set(const Context *context, ObjectType *newObject) override
{
- BindingPointer<ObjectType>::set(newObject);
+ BindingPointer<ObjectType>::set(context, newObject);
mOffset = 0;
mSize = 0;
}
- void set(ObjectType *newObject, GLintptr offset, GLsizeiptr size)
+ void set(const Context *context, ObjectType *newObject, GLintptr offset, GLsizeiptr size)
{
- BindingPointer<ObjectType>::set(newObject);
+ BindingPointer<ObjectType>::set(context, newObject);
mOffset = offset;
mSize = size;
}
@@ -135,5 +182,6 @@ class OffsetBindingPointer : public BindingPointer<ObjectType>
GLintptr mOffset;
GLsizeiptr mSize;
};
+} // namespace gl
#endif // LIBANGLE_REFCOUNTOBJECT_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Renderbuffer.cpp b/src/3rdparty/angle/src/libANGLE/Renderbuffer.cpp
index 161fbea797..8310f1abda 100644
--- a/src/3rdparty/angle/src/libANGLE/Renderbuffer.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Renderbuffer.cpp
@@ -25,11 +25,24 @@ Renderbuffer::Renderbuffer(rx::RenderbufferImpl *impl, GLuint id)
mLabel(),
mWidth(0),
mHeight(0),
- mInternalFormat(GL_RGBA4),
- mSamples(0)
+ mFormat(GL_RGBA4),
+ mSamples(0),
+ mInitState(InitState::MayNeedInit)
{
}
+Error Renderbuffer::onDestroy(const Context *context)
+{
+ ANGLE_TRY(orphanImages(context));
+
+ if (mRenderbuffer)
+ {
+ ANGLE_TRY(mRenderbuffer->onDestroy(context));
+ }
+
+ return NoError();
+}
+
Renderbuffer::~Renderbuffer()
{
SafeDelete(mRenderbuffer);
@@ -45,70 +58,70 @@ const std::string &Renderbuffer::getLabel() const
return mLabel;
}
-Error Renderbuffer::setStorage(GLenum internalformat, size_t width, size_t height)
+Error Renderbuffer::setStorage(const Context *context,
+ GLenum internalformat,
+ size_t width,
+ size_t height)
{
- orphanImages();
+ ANGLE_TRY(orphanImages(context));
- Error error = mRenderbuffer->setStorage(internalformat, width, height);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mRenderbuffer->setStorage(context, internalformat, width, height));
mWidth = static_cast<GLsizei>(width);
mHeight = static_cast<GLsizei>(height);
- mInternalFormat = internalformat;
+ mFormat = Format(internalformat);
mSamples = 0;
- return Error(GL_NO_ERROR);
+ mInitState = InitState::MayNeedInit;
+ mDirtyChannel.signal(mInitState);
+
+ return NoError();
}
-Error Renderbuffer::setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height)
+Error Renderbuffer::setStorageMultisample(const Context *context,
+ size_t samples,
+ GLenum internalformat,
+ size_t width,
+ size_t height)
{
- orphanImages();
+ ANGLE_TRY(orphanImages(context));
- Error error = mRenderbuffer->setStorageMultisample(samples, internalformat, width, height);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(
+ mRenderbuffer->setStorageMultisample(context, samples, internalformat, width, height));
mWidth = static_cast<GLsizei>(width);
mHeight = static_cast<GLsizei>(height);
- mInternalFormat = internalformat;
+ mFormat = Format(internalformat);
mSamples = static_cast<GLsizei>(samples);
- return Error(GL_NO_ERROR);
+ mInitState = InitState::MayNeedInit;
+ mDirtyChannel.signal(mInitState);
+
+ return NoError();
}
-Error Renderbuffer::setStorageEGLImageTarget(egl::Image *image)
+Error Renderbuffer::setStorageEGLImageTarget(const Context *context, egl::Image *image)
{
- orphanImages();
+ ANGLE_TRY(orphanImages(context));
- Error error = mRenderbuffer->setStorageEGLImageTarget(image);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mRenderbuffer->setStorageEGLImageTarget(context, image));
- setTargetImage(image);
+ setTargetImage(context, image);
mWidth = static_cast<GLsizei>(image->getWidth());
mHeight = static_cast<GLsizei>(image->getHeight());
- mInternalFormat = image->getInternalFormat();
+ mFormat = Format(image->getFormat());
mSamples = 0;
- return Error(GL_NO_ERROR);
-}
+ mInitState = image->sourceInitState();
+ mDirtyChannel.signal(mInitState);
-rx::RenderbufferImpl *Renderbuffer::getImplementation()
-{
- ASSERT(mRenderbuffer);
- return mRenderbuffer;
+ return NoError();
}
-const rx::RenderbufferImpl *Renderbuffer::getImplementation() const
+rx::RenderbufferImpl *Renderbuffer::getImplementation() const
{
+ ASSERT(mRenderbuffer);
return mRenderbuffer;
}
@@ -122,9 +135,9 @@ GLsizei Renderbuffer::getHeight() const
return mHeight;
}
-GLenum Renderbuffer::getInternalFormat() const
+const Format &Renderbuffer::getFormat() const
{
- return mInternalFormat;
+ return mFormat;
}
GLsizei Renderbuffer::getSamples() const
@@ -134,42 +147,42 @@ GLsizei Renderbuffer::getSamples() const
GLuint Renderbuffer::getRedSize() const
{
- return GetInternalFormatInfo(mInternalFormat).redBits;
+ return mFormat.info->redBits;
}
GLuint Renderbuffer::getGreenSize() const
{
- return GetInternalFormatInfo(mInternalFormat).greenBits;
+ return mFormat.info->greenBits;
}
GLuint Renderbuffer::getBlueSize() const
{
- return GetInternalFormatInfo(mInternalFormat).blueBits;
+ return mFormat.info->blueBits;
}
GLuint Renderbuffer::getAlphaSize() const
{
- return GetInternalFormatInfo(mInternalFormat).alphaBits;
+ return mFormat.info->alphaBits;
}
GLuint Renderbuffer::getDepthSize() const
{
- return GetInternalFormatInfo(mInternalFormat).depthBits;
+ return mFormat.info->depthBits;
}
GLuint Renderbuffer::getStencilSize() const
{
- return GetInternalFormatInfo(mInternalFormat).stencilBits;
+ return mFormat.info->stencilBits;
}
-void Renderbuffer::onAttach()
+void Renderbuffer::onAttach(const Context *context)
{
addRef();
}
-void Renderbuffer::onDetach()
+void Renderbuffer::onDetach(const Context *context)
{
- release();
+ release(context);
}
GLuint Renderbuffer::getId() const
@@ -177,8 +190,46 @@ GLuint Renderbuffer::getId() const
return id();
}
-Extents Renderbuffer::getAttachmentSize(const FramebufferAttachment::Target & /*target*/) const
+Extents Renderbuffer::getAttachmentSize(const gl::ImageIndex & /*imageIndex*/) const
{
return Extents(mWidth, mHeight, 1);
}
+
+const Format &Renderbuffer::getAttachmentFormat(GLenum /*binding*/,
+ const ImageIndex & /*imageIndex*/) const
+{
+ return getFormat();
+}
+GLsizei Renderbuffer::getAttachmentSamples(const ImageIndex & /*imageIndex*/) const
+{
+ return getSamples();
}
+
+InitState Renderbuffer::initState(const gl::ImageIndex & /*imageIndex*/) const
+{
+ if (isEGLImageTarget())
+ {
+ return sourceEGLImageInitState();
+ }
+
+ return mInitState;
+}
+
+void Renderbuffer::setInitState(const gl::ImageIndex & /*imageIndex*/, InitState initState)
+{
+ if (isEGLImageTarget())
+ {
+ setSourceEGLImageInitState(initState);
+ }
+ else
+ {
+ mInitState = initState;
+ }
+}
+
+rx::FramebufferAttachmentObjectImpl *Renderbuffer::getAttachmentImpl() const
+{
+ return mRenderbuffer;
+}
+
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/Renderbuffer.h b/src/3rdparty/angle/src/libANGLE/Renderbuffer.h
index 04af03e879..def18e6ff7 100644
--- a/src/3rdparty/angle/src/libANGLE/Renderbuffer.h
+++ b/src/3rdparty/angle/src/libANGLE/Renderbuffer.h
@@ -17,6 +17,7 @@
#include "libANGLE/Error.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/Image.h"
+#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/RenderbufferImpl.h"
namespace gl
@@ -27,26 +28,30 @@ namespace gl
// attachment point.
class Renderbuffer final : public egl::ImageSibling,
- public gl::FramebufferAttachmentObject,
public LabeledObject
{
public:
Renderbuffer(rx::RenderbufferImpl *impl, GLuint id);
- virtual ~Renderbuffer();
+ ~Renderbuffer() override;
+
+ Error onDestroy(const Context *context) override;
void setLabel(const std::string &label) override;
const std::string &getLabel() const override;
- Error setStorage(GLenum internalformat, size_t width, size_t height);
- Error setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height);
- Error setStorageEGLImageTarget(egl::Image *imageTarget);
+ Error setStorage(const Context *context, GLenum internalformat, size_t width, size_t height);
+ Error setStorageMultisample(const Context *context,
+ size_t samples,
+ GLenum internalformat,
+ size_t width,
+ size_t height);
+ Error setStorageEGLImageTarget(const Context *context, egl::Image *imageTarget);
- rx::RenderbufferImpl *getImplementation();
- const rx::RenderbufferImpl *getImplementation() const;
+ rx::RenderbufferImpl *getImplementation() const;
GLsizei getWidth() const;
GLsizei getHeight() const;
- GLenum getInternalFormat() const;
+ const Format &getFormat() const;
GLsizei getSamples() const;
GLuint getRedSize() const;
GLuint getGreenSize() const;
@@ -56,16 +61,19 @@ class Renderbuffer final : public egl::ImageSibling,
GLuint getStencilSize() const;
// FramebufferAttachmentObject Impl
- Extents getAttachmentSize(const FramebufferAttachment::Target &target) const override;
- GLenum getAttachmentInternalFormat(const FramebufferAttachment::Target &/*target*/) const override { return getInternalFormat(); }
- GLsizei getAttachmentSamples(const FramebufferAttachment::Target &/*target*/) const override { return getSamples(); }
+ Extents getAttachmentSize(const ImageIndex &imageIndex) const override;
+ const Format &getAttachmentFormat(GLenum binding, const ImageIndex &imageIndex) const override;
+ GLsizei getAttachmentSamples(const ImageIndex &imageIndex) const override;
- void onAttach() override;
- void onDetach() override;
+ void onAttach(const Context *context) override;
+ void onDetach(const Context *context) override;
GLuint getId() const override;
+ InitState initState(const ImageIndex &imageIndex) const override;
+ void setInitState(const ImageIndex &imageIndex, InitState initState) override;
+
private:
- rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override { return mRenderbuffer; }
+ rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override;
rx::RenderbufferImpl *mRenderbuffer;
@@ -73,10 +81,13 @@ class Renderbuffer final : public egl::ImageSibling,
GLsizei mWidth;
GLsizei mHeight;
- GLenum mInternalFormat;
+ Format mFormat;
GLsizei mSamples;
+
+ // For robust resource init.
+ InitState mInitState;
};
-}
+} // namespace gl
#endif // LIBANGLE_RENDERBUFFER_H_
diff --git a/src/3rdparty/angle/src/libANGLE/ResourceManager.cpp b/src/3rdparty/angle/src/libANGLE/ResourceManager.cpp
index dc9dad1e9f..79eb7e5f42 100644
--- a/src/3rdparty/angle/src/libANGLE/ResourceManager.cpp
+++ b/src/3rdparty/angle/src/libANGLE/ResourceManager.cpp
@@ -1,456 +1,483 @@
//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// ResourceManager.cpp: Implements the gl::ResourceManager class, which tracks and
-// retrieves objects which may be shared by multiple Contexts.
+// ResourceManager.cpp: Implements the the ResourceManager classes, which handle allocation and
+// lifetime of GL objects.
#include "libANGLE/ResourceManager.h"
#include "libANGLE/Buffer.h"
+#include "libANGLE/Fence.h"
+#include "libANGLE/Path.h"
#include "libANGLE/Program.h"
+#include "libANGLE/ProgramPipeline.h"
#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Sampler.h"
#include "libANGLE/Shader.h"
#include "libANGLE/Texture.h"
-#include "libANGLE/Sampler.h"
-#include "libANGLE/Fence.h"
-#include "libANGLE/renderer/Renderer.h"
+#include "libANGLE/renderer/GLImplFactory.h"
namespace gl
{
-ResourceManager::ResourceManager(rx::ImplFactory *factory)
- : mFactory(factory),
- mRefCount(1)
+
+namespace
+{
+
+template <typename ResourceType>
+GLuint AllocateEmptyObject(HandleAllocator *handleAllocator, ResourceMap<ResourceType> *objectMap)
{
+ GLuint handle = handleAllocator->allocate();
+ objectMap->assign(handle, nullptr);
+ return handle;
}
-ResourceManager::~ResourceManager()
+} // anonymous namespace
+
+template <typename HandleAllocatorType>
+ResourceManagerBase<HandleAllocatorType>::ResourceManagerBase() : mRefCount(1)
{
- while (!mBufferMap.empty())
- {
- deleteBuffer(mBufferMap.begin()->first);
- }
+}
- while (!mProgramMap.empty())
- {
- deleteProgram(mProgramMap.begin()->first);
- }
+template <typename HandleAllocatorType>
+void ResourceManagerBase<HandleAllocatorType>::addRef()
+{
+ mRefCount++;
+}
- while (!mShaderMap.empty())
+template <typename HandleAllocatorType>
+void ResourceManagerBase<HandleAllocatorType>::release(const Context *context)
+{
+ if (--mRefCount == 0)
{
- deleteShader(mShaderMap.begin()->first);
+ reset(context);
+ delete this;
}
+}
- while (!mRenderbufferMap.empty())
- {
- deleteRenderbuffer(mRenderbufferMap.begin()->first);
- }
+template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
+TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::~TypedResourceManager()
+{
+ ASSERT(mObjectMap.empty());
+}
- while (!mTextureMap.empty())
+template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
+void TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::reset(const Context *context)
+{
+ this->mHandleAllocator.reset();
+ for (const auto &resource : mObjectMap)
{
- deleteTexture(mTextureMap.begin()->first);
+ if (resource.second)
+ {
+ ImplT::DeleteObject(context, resource.second);
+ }
}
+ mObjectMap.clear();
+}
- while (!mSamplerMap.empty())
+template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
+void TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::deleteObject(
+ const Context *context,
+ GLuint handle)
+{
+ ResourceType *resource = nullptr;
+ if (!mObjectMap.erase(handle, &resource))
{
- deleteSampler(mSamplerMap.begin()->first);
+ return;
}
- while (!mFenceSyncMap.empty())
+ // Requires an explicit this-> because of C++ template rules.
+ this->mHandleAllocator.release(handle);
+
+ if (resource)
{
- deleteFenceSync(mFenceSyncMap.begin()->first);
+ ImplT::DeleteObject(context, resource);
}
}
-void ResourceManager::addRef()
+template class ResourceManagerBase<HandleAllocator>;
+template class ResourceManagerBase<HandleRangeAllocator>;
+template class TypedResourceManager<Buffer, HandleAllocator, BufferManager>;
+template class TypedResourceManager<Texture, HandleAllocator, TextureManager>;
+template class TypedResourceManager<Renderbuffer, HandleAllocator, RenderbufferManager>;
+template class TypedResourceManager<Sampler, HandleAllocator, SamplerManager>;
+template class TypedResourceManager<Sync, HandleAllocator, SyncManager>;
+template class TypedResourceManager<Framebuffer, HandleAllocator, FramebufferManager>;
+template class TypedResourceManager<ProgramPipeline, HandleAllocator, ProgramPipelineManager>;
+
+// BufferManager Implementation.
+
+// static
+Buffer *BufferManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle)
{
- mRefCount++;
+ Buffer *buffer = new Buffer(factory, handle);
+ buffer->addRef();
+ return buffer;
}
-void ResourceManager::release()
+// static
+void BufferManager::DeleteObject(const Context *context, Buffer *buffer)
{
- if (--mRefCount == 0)
- {
- delete this;
- }
+ buffer->release(context);
}
-// Returns an unused buffer name
-GLuint ResourceManager::createBuffer()
+GLuint BufferManager::createBuffer()
{
- GLuint handle = mBufferHandleAllocator.allocate();
+ return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
+}
- mBufferMap[handle] = NULL;
+Buffer *BufferManager::getBuffer(GLuint handle) const
+{
+ return mObjectMap.query(handle);
+}
- return handle;
+// ShaderProgramManager Implementation.
+
+ShaderProgramManager::ShaderProgramManager()
+{
}
-// Returns an unused shader/program name
-GLuint ResourceManager::createShader(const gl::Limitations &rendererLimitations, GLenum type)
+ShaderProgramManager::~ShaderProgramManager()
{
- GLuint handle = mProgramShaderHandleAllocator.allocate();
+ ASSERT(mPrograms.empty());
+ ASSERT(mShaders.empty());
+}
- if (type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER)
+void ShaderProgramManager::reset(const Context *context)
+{
+ while (!mPrograms.empty())
{
- mShaderMap[handle] = new Shader(this, mFactory, rendererLimitations, type, handle);
+ deleteProgram(context, mPrograms.begin()->first);
}
- else UNREACHABLE();
-
- return handle;
+ mPrograms.clear();
+ while (!mShaders.empty())
+ {
+ deleteShader(context, mShaders.begin()->first);
+ }
+ mShaders.clear();
}
-// Returns an unused program/shader name
-GLuint ResourceManager::createProgram()
+GLuint ShaderProgramManager::createShader(rx::GLImplFactory *factory,
+ const gl::Limitations &rendererLimitations,
+ GLenum type)
{
- GLuint handle = mProgramShaderHandleAllocator.allocate();
-
- mProgramMap[handle] = new Program(mFactory, this, handle);
-
+ ASSERT(type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER || type == GL_COMPUTE_SHADER ||
+ type == GL_GEOMETRY_SHADER_EXT);
+ GLuint handle = mHandleAllocator.allocate();
+ mShaders.assign(handle, new Shader(this, factory, rendererLimitations, type, handle));
return handle;
}
-// Returns an unused texture name
-GLuint ResourceManager::createTexture()
+void ShaderProgramManager::deleteShader(const Context *context, GLuint shader)
{
- GLuint handle = mTextureHandleAllocator.allocate();
-
- mTextureMap[handle] = NULL;
-
- return handle;
+ deleteObject(context, &mShaders, shader);
}
-// Returns an unused renderbuffer name
-GLuint ResourceManager::createRenderbuffer()
+Shader *ShaderProgramManager::getShader(GLuint handle) const
{
- GLuint handle = mRenderbufferHandleAllocator.allocate();
-
- mRenderbufferMap[handle] = NULL;
-
- return handle;
+ return mShaders.query(handle);
}
-// Returns an unused sampler name
-GLuint ResourceManager::createSampler()
+GLuint ShaderProgramManager::createProgram(rx::GLImplFactory *factory)
{
- GLuint handle = mSamplerHandleAllocator.allocate();
-
- mSamplerMap[handle] = NULL;
-
+ GLuint handle = mHandleAllocator.allocate();
+ mPrograms.assign(handle, new Program(factory, this, handle));
return handle;
}
-// Returns the next unused fence name, and allocates the fence
-GLuint ResourceManager::createFenceSync()
+void ShaderProgramManager::deleteProgram(const gl::Context *context, GLuint program)
{
- GLuint handle = mFenceSyncHandleAllocator.allocate();
-
- FenceSync *fenceSync = new FenceSync(mFactory->createFenceSync(), handle);
- fenceSync->addRef();
- mFenceSyncMap[handle] = fenceSync;
+ deleteObject(context, &mPrograms, program);
+}
- return handle;
+Program *ShaderProgramManager::getProgram(GLuint handle) const
+{
+ return mPrograms.query(handle);
}
-void ResourceManager::deleteBuffer(GLuint buffer)
+template <typename ObjectType>
+void ShaderProgramManager::deleteObject(const Context *context,
+ ResourceMap<ObjectType> *objectMap,
+ GLuint id)
{
- BufferMap::iterator bufferObject = mBufferMap.find(buffer);
+ ObjectType *object = objectMap->query(id);
+ if (!object)
+ {
+ return;
+ }
- if (bufferObject != mBufferMap.end())
+ if (object->getRefCount() == 0)
+ {
+ mHandleAllocator.release(id);
+ object->onDestroy(context);
+ objectMap->erase(id, &object);
+ }
+ else
{
- mBufferHandleAllocator.release(bufferObject->first);
- if (bufferObject->second) bufferObject->second->release();
- mBufferMap.erase(bufferObject);
+ object->flagForDeletion();
}
}
-void ResourceManager::deleteShader(GLuint shader)
+// TextureManager Implementation.
+
+// static
+Texture *TextureManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle, GLenum target)
{
- ShaderMap::iterator shaderObject = mShaderMap.find(shader);
+ Texture *texture = new Texture(factory, handle, target);
+ texture->addRef();
+ return texture;
+}
- if (shaderObject != mShaderMap.end())
- {
- if (shaderObject->second->getRefCount() == 0)
- {
- mProgramShaderHandleAllocator.release(shaderObject->first);
- delete shaderObject->second;
- mShaderMap.erase(shaderObject);
- }
- else
- {
- shaderObject->second->flagForDeletion();
- }
- }
+// static
+void TextureManager::DeleteObject(const Context *context, Texture *texture)
+{
+ texture->release(context);
}
-void ResourceManager::deleteProgram(GLuint program)
+GLuint TextureManager::createTexture()
{
- ProgramMap::iterator programObject = mProgramMap.find(program);
+ return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
+}
+
+Texture *TextureManager::getTexture(GLuint handle) const
+{
+ ASSERT(mObjectMap.query(0) == nullptr);
+ return mObjectMap.query(handle);
+}
- if (programObject != mProgramMap.end())
+void TextureManager::signalAllTexturesDirty() const
+{
+ for (const auto &texture : mObjectMap)
{
- if (programObject->second->getRefCount() == 0)
+ if (texture.second)
{
- mProgramShaderHandleAllocator.release(programObject->first);
- delete programObject->second;
- mProgramMap.erase(programObject);
- }
- else
- {
- programObject->second->flagForDeletion();
+ // We don't know if the Texture needs init, but that's ok, since it will only force
+ // a re-check, and will not initialize the pixels if it's not needed.
+ texture.second->signalDirty(InitState::MayNeedInit);
}
}
}
-void ResourceManager::deleteTexture(GLuint texture)
-{
- TextureMap::iterator textureObject = mTextureMap.find(texture);
+// RenderbufferManager Implementation.
- if (textureObject != mTextureMap.end())
- {
- mTextureHandleAllocator.release(textureObject->first);
- if (textureObject->second) textureObject->second->release();
- mTextureMap.erase(textureObject);
- }
+// static
+Renderbuffer *RenderbufferManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle)
+{
+ Renderbuffer *renderbuffer = new Renderbuffer(factory->createRenderbuffer(), handle);
+ renderbuffer->addRef();
+ return renderbuffer;
}
-void ResourceManager::deleteRenderbuffer(GLuint renderbuffer)
+// static
+void RenderbufferManager::DeleteObject(const Context *context, Renderbuffer *renderbuffer)
{
- RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer);
+ renderbuffer->release(context);
+}
- if (renderbufferObject != mRenderbufferMap.end())
- {
- mRenderbufferHandleAllocator.release(renderbufferObject->first);
- if (renderbufferObject->second) renderbufferObject->second->release();
- mRenderbufferMap.erase(renderbufferObject);
- }
+GLuint RenderbufferManager::createRenderbuffer()
+{
+ return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
}
-void ResourceManager::deleteSampler(GLuint sampler)
+Renderbuffer *RenderbufferManager::getRenderbuffer(GLuint handle) const
{
- auto samplerObject = mSamplerMap.find(sampler);
+ return mObjectMap.query(handle);
+}
- if (samplerObject != mSamplerMap.end())
- {
- mSamplerHandleAllocator.release(samplerObject->first);
- if (samplerObject->second) samplerObject->second->release();
- mSamplerMap.erase(samplerObject);
- }
+// SamplerManager Implementation.
+
+// static
+Sampler *SamplerManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle)
+{
+ Sampler *sampler = new Sampler(factory, handle);
+ sampler->addRef();
+ return sampler;
}
-void ResourceManager::deleteFenceSync(GLuint fenceSync)
+// static
+void SamplerManager::DeleteObject(const Context *context, Sampler *sampler)
{
- auto fenceObjectIt = mFenceSyncMap.find(fenceSync);
+ sampler->release(context);
+}
- if (fenceObjectIt != mFenceSyncMap.end())
- {
- mFenceSyncHandleAllocator.release(fenceObjectIt->first);
- if (fenceObjectIt->second) fenceObjectIt->second->release();
- mFenceSyncMap.erase(fenceObjectIt);
- }
+GLuint SamplerManager::createSampler()
+{
+ return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
}
-Buffer *ResourceManager::getBuffer(unsigned int handle)
+Sampler *SamplerManager::getSampler(GLuint handle) const
{
- BufferMap::iterator buffer = mBufferMap.find(handle);
+ return mObjectMap.query(handle);
+}
- if (buffer == mBufferMap.end())
- {
- return NULL;
- }
- else
- {
- return buffer->second;
- }
+bool SamplerManager::isSampler(GLuint sampler) const
+{
+ return mObjectMap.contains(sampler);
}
-Shader *ResourceManager::getShader(unsigned int handle)
+// SyncManager Implementation.
+
+// static
+void SyncManager::DeleteObject(const Context *context, Sync *sync)
{
- ShaderMap::iterator shader = mShaderMap.find(handle);
+ sync->release(context);
+}
- if (shader == mShaderMap.end())
- {
- return NULL;
- }
- else
- {
- return shader->second;
- }
+GLuint SyncManager::createSync(rx::GLImplFactory *factory)
+{
+ GLuint handle = mHandleAllocator.allocate();
+ Sync *sync = new Sync(factory->createSync(), handle);
+ sync->addRef();
+ mObjectMap.assign(handle, sync);
+ return handle;
}
-Texture *ResourceManager::getTexture(unsigned int handle)
+Sync *SyncManager::getSync(GLuint handle) const
{
- if (handle == 0) return NULL;
+ return mObjectMap.query(handle);
+}
- TextureMap::iterator texture = mTextureMap.find(handle);
+// PathManager Implementation.
- if (texture == mTextureMap.end())
- {
- return NULL;
- }
- else
- {
- return texture->second;
- }
+PathManager::PathManager()
+{
}
-Program *ResourceManager::getProgram(unsigned int handle) const
+ErrorOrResult<GLuint> PathManager::createPaths(rx::GLImplFactory *factory, GLsizei range)
{
- ProgramMap::const_iterator program = mProgramMap.find(handle);
+ // Allocate client side handles.
+ const GLuint client = mHandleAllocator.allocateRange(static_cast<GLuint>(range));
+ if (client == HandleRangeAllocator::kInvalidHandle)
+ return OutOfMemory() << "Failed to allocate path handle range.";
- if (program == mProgramMap.end())
+ const auto &paths = factory->createPaths(range);
+ if (paths.empty())
{
- return NULL;
+ mHandleAllocator.releaseRange(client, range);
+ return OutOfMemory() << "Failed to allocate path objects.";
}
- else
+
+ for (GLsizei i = 0; i < range; ++i)
{
- return program->second;
+ rx::PathImpl *impl = paths[static_cast<unsigned>(i)];
+ const auto id = client + i;
+ mPaths.assign(id, new Path(impl));
}
+ return client;
}
-Renderbuffer *ResourceManager::getRenderbuffer(unsigned int handle)
+void PathManager::deletePaths(GLuint first, GLsizei range)
{
- RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle);
-
- if (renderbuffer == mRenderbufferMap.end())
+ for (GLsizei i = 0; i < range; ++i)
{
- return NULL;
- }
- else
- {
- return renderbuffer->second;
+ const auto id = first + i;
+ Path *p = nullptr;
+ if (!mPaths.erase(id, &p))
+ continue;
+ delete p;
}
+ mHandleAllocator.releaseRange(first, static_cast<GLuint>(range));
}
-Sampler *ResourceManager::getSampler(unsigned int handle)
+Path *PathManager::getPath(GLuint handle) const
{
- auto sampler = mSamplerMap.find(handle);
+ return mPaths.query(handle);
+}
- if (sampler == mSamplerMap.end())
- {
- return NULL;
- }
- else
- {
- return sampler->second;
- }
+bool PathManager::hasPath(GLuint handle) const
+{
+ return mHandleAllocator.isUsed(handle);
}
-FenceSync *ResourceManager::getFenceSync(unsigned int handle)
+PathManager::~PathManager()
{
- auto fenceObjectIt = mFenceSyncMap.find(handle);
+ ASSERT(mPaths.empty());
+}
- if (fenceObjectIt == mFenceSyncMap.end())
- {
- return NULL;
- }
- else
+void PathManager::reset(const Context *context)
+{
+ for (auto path : mPaths)
{
- return fenceObjectIt->second;
+ SafeDelete(path.second);
}
+ mPaths.clear();
}
-void ResourceManager::setRenderbuffer(GLuint handle, Renderbuffer *buffer)
+// FramebufferManager Implementation.
+
+// static
+Framebuffer *FramebufferManager::AllocateNewObject(rx::GLImplFactory *factory,
+ GLuint handle,
+ const Caps &caps)
{
- mRenderbufferMap[handle] = buffer;
+ return new Framebuffer(caps, factory, handle);
}
-void ResourceManager::checkBufferAllocation(GLuint handle)
+// static
+void FramebufferManager::DeleteObject(const Context *context, Framebuffer *framebuffer)
{
- if (handle != 0)
+ // Default framebuffer are owned by their respective Surface
+ if (framebuffer->id() != 0)
{
- auto bufferMapIt = mBufferMap.find(handle);
- bool handleAllocated = (bufferMapIt != mBufferMap.end());
-
- if (handleAllocated && bufferMapIt->second != nullptr)
- {
- return;
- }
-
- Buffer *buffer = new Buffer(mFactory->createBuffer(), handle);
- buffer->addRef();
-
- if (handleAllocated)
- {
- bufferMapIt->second = buffer;
- }
- else
- {
- mBufferHandleAllocator.reserve(handle);
- mBufferMap[handle] = buffer;
- }
+ framebuffer->onDestroy(context);
+ delete framebuffer;
}
}
-void ResourceManager::checkTextureAllocation(GLuint handle, GLenum type)
+GLuint FramebufferManager::createFramebuffer()
{
- if (handle != 0)
- {
- auto textureMapIt = mTextureMap.find(handle);
- bool handleAllocated = (textureMapIt != mTextureMap.end());
-
- if (handleAllocated && textureMapIt->second != nullptr)
- {
- return;
- }
+ return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
+}
- Texture *texture = new Texture(mFactory->createTexture(type), handle, type);
- texture->addRef();
+Framebuffer *FramebufferManager::getFramebuffer(GLuint handle) const
+{
+ return mObjectMap.query(handle);
+}
- if (handleAllocated)
- {
- textureMapIt->second = texture;
- }
- else
- {
- mTextureHandleAllocator.reserve(handle);
- mTextureMap[handle] = texture;
- }
- }
+void FramebufferManager::setDefaultFramebuffer(Framebuffer *framebuffer)
+{
+ ASSERT(framebuffer == nullptr || framebuffer->id() == 0);
+ mObjectMap.assign(0, framebuffer);
}
-void ResourceManager::checkRenderbufferAllocation(GLuint handle)
+void FramebufferManager::invalidateFramebufferComplenessCache() const
{
- if (handle != 0)
+ for (const auto &framebuffer : mObjectMap)
{
- auto renderbufferMapIt = mRenderbufferMap.find(handle);
- bool handleAllocated = (renderbufferMapIt != mRenderbufferMap.end());
-
- if (handleAllocated && renderbufferMapIt->second != nullptr)
+ if (framebuffer.second)
{
- return;
+ framebuffer.second->invalidateCompletenessCache();
}
+ }
+}
- Renderbuffer *renderbuffer = new Renderbuffer(mFactory->createRenderbuffer(), handle);
- renderbuffer->addRef();
+// ProgramPipelineManager Implementation.
- if (handleAllocated)
- {
- renderbufferMapIt->second = renderbuffer;
- }
- else
- {
- mRenderbufferHandleAllocator.reserve(handle);
- mRenderbufferMap[handle] = renderbuffer;
- }
- }
+// static
+ProgramPipeline *ProgramPipelineManager::AllocateNewObject(rx::GLImplFactory *factory,
+ GLuint handle)
+{
+ ProgramPipeline *pipeline = new ProgramPipeline(factory, handle);
+ pipeline->addRef();
+ return pipeline;
}
-void ResourceManager::checkSamplerAllocation(GLuint sampler)
+// static
+void ProgramPipelineManager::DeleteObject(const Context *context, ProgramPipeline *pipeline)
{
- if (sampler != 0 && !getSampler(sampler))
- {
- Sampler *samplerObject = new Sampler(mFactory, sampler);
- mSamplerMap[sampler] = samplerObject;
- samplerObject->addRef();
- // Samplers cannot be created via Bind
- }
+ pipeline->release(context);
}
-bool ResourceManager::isSampler(GLuint sampler)
+GLuint ProgramPipelineManager::createProgramPipeline()
{
- return mSamplerMap.find(sampler) != mSamplerMap.end();
+ return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
}
+ProgramPipeline *ProgramPipelineManager::getProgramPipeline(GLuint handle) const
+{
+ return mObjectMap.query(handle);
}
+
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/ResourceManager.h b/src/3rdparty/angle/src/libANGLE/ResourceManager.h
index 2073e9d728..2dfeff5234 100644
--- a/src/3rdparty/angle/src/libANGLE/ResourceManager.h
+++ b/src/3rdparty/angle/src/libANGLE/ResourceManager.h
@@ -1,115 +1,289 @@
//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// ResourceManager.h : Defines the ResourceManager class, which tracks objects
-// shared by multiple GL contexts.
+// ResourceManager.h : Defines the ResourceManager classes, which handle allocation and lifetime of
+// GL objects.
#ifndef LIBANGLE_RESOURCEMANAGER_H_
#define LIBANGLE_RESOURCEMANAGER_H_
#include "angle_gl.h"
#include "common/angleutils.h"
-#include "libANGLE/angletypes.h"
+#include "libANGLE/Error.h"
#include "libANGLE/HandleAllocator.h"
-
-#include <map>
+#include "libANGLE/HandleRangeAllocator.h"
+#include "libANGLE/ResourceMap.h"
namespace rx
{
-class ImplFactory;
+class GLImplFactory;
}
namespace gl
{
class Buffer;
-struct Data;
-class FenceSync;
+struct Caps;
+class Context;
+class Sync;
+class Framebuffer;
struct Limitations;
+class Path;
class Program;
+class ProgramPipeline;
class Renderbuffer;
class Sampler;
class Shader;
class Texture;
-class ResourceManager : angle::NonCopyable
+template <typename HandleAllocatorType>
+class ResourceManagerBase : angle::NonCopyable
{
public:
- explicit ResourceManager(rx::ImplFactory *factory);
- ~ResourceManager();
+ ResourceManagerBase();
void addRef();
- void release();
+ void release(const Context *context);
+
+ protected:
+ virtual void reset(const Context *context) = 0;
+ virtual ~ResourceManagerBase() {}
+
+ HandleAllocatorType mHandleAllocator;
+
+ private:
+ size_t mRefCount;
+};
+
+template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
+class TypedResourceManager : public ResourceManagerBase<HandleAllocatorType>
+{
+ public:
+ TypedResourceManager() {}
+
+ void deleteObject(const Context *context, GLuint handle);
+ bool isHandleGenerated(GLuint handle) const
+ {
+ // Zero is always assumed to have been generated implicitly.
+ return handle == 0 || mObjectMap.contains(handle);
+ }
+
+ protected:
+ ~TypedResourceManager() override;
+
+ // Inlined in the header for performance.
+ template <typename... ArgTypes>
+ ResourceType *checkObjectAllocation(rx::GLImplFactory *factory, GLuint handle, ArgTypes... args)
+ {
+ ResourceType *value = mObjectMap.query(handle);
+ if (value)
+ {
+ return value;
+ }
+
+ if (handle == 0)
+ {
+ return nullptr;
+ }
+
+ ResourceType *object = ImplT::AllocateNewObject(factory, handle, args...);
+
+ if (!mObjectMap.contains(handle))
+ {
+ this->mHandleAllocator.reserve(handle);
+ }
+ mObjectMap.assign(handle, object);
+
+ return object;
+ }
+
+ void reset(const Context *context) override;
+
+ ResourceMap<ResourceType> mObjectMap;
+};
+class BufferManager : public TypedResourceManager<Buffer, HandleAllocator, BufferManager>
+{
+ public:
GLuint createBuffer();
- GLuint createShader(const gl::Limitations &rendererLimitations, GLenum type);
- GLuint createProgram();
+ Buffer *getBuffer(GLuint handle) const;
+
+ Buffer *checkBufferAllocation(rx::GLImplFactory *factory, GLuint handle)
+ {
+ return checkObjectAllocation(factory, handle);
+ }
+
+ // TODO(jmadill): Investigate design which doesn't expose these methods publicly.
+ static Buffer *AllocateNewObject(rx::GLImplFactory *factory, GLuint handle);
+ static void DeleteObject(const Context *context, Buffer *buffer);
+
+ protected:
+ ~BufferManager() override {}
+};
+
+class ShaderProgramManager : public ResourceManagerBase<HandleAllocator>
+{
+ public:
+ ShaderProgramManager();
+
+ GLuint createShader(rx::GLImplFactory *factory,
+ const Limitations &rendererLimitations,
+ GLenum type);
+ void deleteShader(const Context *context, GLuint shader);
+ Shader *getShader(GLuint handle) const;
+
+ GLuint createProgram(rx::GLImplFactory *factory);
+ void deleteProgram(const Context *context, GLuint program);
+ Program *getProgram(GLuint handle) const;
+
+ protected:
+ ~ShaderProgramManager() override;
+
+ private:
+ template <typename ObjectType>
+ void deleteObject(const Context *context, ResourceMap<ObjectType> *objectMap, GLuint id);
+
+ void reset(const Context *context) override;
+
+ ResourceMap<Shader> mShaders;
+ ResourceMap<Program> mPrograms;
+};
+
+class TextureManager : public TypedResourceManager<Texture, HandleAllocator, TextureManager>
+{
+ public:
GLuint createTexture();
+ Texture *getTexture(GLuint handle) const;
+
+ void signalAllTexturesDirty() const;
+
+ Texture *checkTextureAllocation(rx::GLImplFactory *factory, GLuint handle, GLenum target)
+ {
+ return checkObjectAllocation(factory, handle, target);
+ }
+
+ static Texture *AllocateNewObject(rx::GLImplFactory *factory, GLuint handle, GLenum target);
+ static void DeleteObject(const Context *context, Texture *texture);
+
+ protected:
+ ~TextureManager() override {}
+};
+
+class RenderbufferManager
+ : public TypedResourceManager<Renderbuffer, HandleAllocator, RenderbufferManager>
+{
+ public:
GLuint createRenderbuffer();
+ Renderbuffer *getRenderbuffer(GLuint handle) const;
+
+ Renderbuffer *checkRenderbufferAllocation(rx::GLImplFactory *factory, GLuint handle)
+ {
+ return checkObjectAllocation(factory, handle);
+ }
+
+ static Renderbuffer *AllocateNewObject(rx::GLImplFactory *factory, GLuint handle);
+ static void DeleteObject(const Context *context, Renderbuffer *renderbuffer);
+
+ protected:
+ ~RenderbufferManager() override {}
+};
+
+class SamplerManager : public TypedResourceManager<Sampler, HandleAllocator, SamplerManager>
+{
+ public:
GLuint createSampler();
- GLuint createFenceSync();
-
- void deleteBuffer(GLuint buffer);
- void deleteShader(GLuint shader);
- void deleteProgram(GLuint program);
- void deleteTexture(GLuint texture);
- void deleteRenderbuffer(GLuint renderbuffer);
- void deleteSampler(GLuint sampler);
- void deleteFenceSync(GLuint fenceSync);
-
- Buffer *getBuffer(GLuint handle);
- Shader *getShader(GLuint handle);
- Program *getProgram(GLuint handle) const;
- Texture *getTexture(GLuint handle);
- Renderbuffer *getRenderbuffer(GLuint handle);
- Sampler *getSampler(GLuint handle);
- FenceSync *getFenceSync(GLuint handle);
+ Sampler *getSampler(GLuint handle) const;
+ bool isSampler(GLuint sampler) const;
+
+ Sampler *checkSamplerAllocation(rx::GLImplFactory *factory, GLuint handle)
+ {
+ return checkObjectAllocation(factory, handle);
+ }
- void setRenderbuffer(GLuint handle, Renderbuffer *renderbuffer);
+ static Sampler *AllocateNewObject(rx::GLImplFactory *factory, GLuint handle);
+ static void DeleteObject(const Context *context, Sampler *sampler);
- void checkBufferAllocation(GLuint handle);
- void checkTextureAllocation(GLuint handle, GLenum type);
- void checkRenderbufferAllocation(GLuint handle);
- void checkSamplerAllocation(GLuint sampler);
+ protected:
+ ~SamplerManager() override {}
+};
+
+class SyncManager : public TypedResourceManager<Sync, HandleAllocator, SyncManager>
+{
+ public:
+ GLuint createSync(rx::GLImplFactory *factory);
+ Sync *getSync(GLuint handle) const;
+
+ static void DeleteObject(const Context *context, Sync *sync);
+
+ protected:
+ ~SyncManager() override {}
+};
+
+class PathManager : public ResourceManagerBase<HandleRangeAllocator>
+{
+ public:
+ PathManager();
- bool isSampler(GLuint sampler);
+ ErrorOrResult<GLuint> createPaths(rx::GLImplFactory *factory, GLsizei range);
+ void deletePaths(GLuint first, GLsizei range);
+ Path *getPath(GLuint handle) const;
+ bool hasPath(GLuint handle) const;
+
+ protected:
+ ~PathManager() override;
+ void reset(const Context *context) override;
private:
- void createTextureInternal(GLuint handle);
+ ResourceMap<Path> mPaths;
+};
- rx::ImplFactory *mFactory;
- std::size_t mRefCount;
+class FramebufferManager
+ : public TypedResourceManager<Framebuffer, HandleAllocator, FramebufferManager>
+{
+ public:
+ GLuint createFramebuffer();
+ Framebuffer *getFramebuffer(GLuint handle) const;
+ void setDefaultFramebuffer(Framebuffer *framebuffer);
- typedef std::map<GLuint, Buffer*> BufferMap;
- BufferMap mBufferMap;
- HandleAllocator mBufferHandleAllocator;
+ void invalidateFramebufferComplenessCache() const;
- typedef std::map<GLuint, Shader*> ShaderMap;
- ShaderMap mShaderMap;
+ Framebuffer *checkFramebufferAllocation(rx::GLImplFactory *factory,
+ const Caps &caps,
+ GLuint handle)
+ {
+ return checkObjectAllocation<const Caps &>(factory, handle, caps);
+ }
- typedef std::map<GLuint, Program*> ProgramMap;
- ProgramMap mProgramMap;
- HandleAllocator mProgramShaderHandleAllocator;
+ static Framebuffer *AllocateNewObject(rx::GLImplFactory *factory,
+ GLuint handle,
+ const Caps &caps);
+ static void DeleteObject(const Context *context, Framebuffer *framebuffer);
- typedef std::map<GLuint, Texture*> TextureMap;
- TextureMap mTextureMap;
- HandleAllocator mTextureHandleAllocator;
+ protected:
+ ~FramebufferManager() override {}
+};
- typedef std::map<GLuint, Renderbuffer*> RenderbufferMap;
- RenderbufferMap mRenderbufferMap;
- HandleAllocator mRenderbufferHandleAllocator;
+class ProgramPipelineManager
+ : public TypedResourceManager<ProgramPipeline, HandleAllocator, ProgramPipelineManager>
+{
+ public:
+ GLuint createProgramPipeline();
+ ProgramPipeline *getProgramPipeline(GLuint handle) const;
- typedef std::map<GLuint, Sampler*> SamplerMap;
- SamplerMap mSamplerMap;
- HandleAllocator mSamplerHandleAllocator;
+ ProgramPipeline *checkProgramPipelineAllocation(rx::GLImplFactory *factory, GLuint handle)
+ {
+ return checkObjectAllocation(factory, handle);
+ }
- typedef std::map<GLuint, FenceSync*> FenceMap;
- FenceMap mFenceSyncMap;
- HandleAllocator mFenceSyncHandleAllocator;
+ static ProgramPipeline *AllocateNewObject(rx::GLImplFactory *factory, GLuint handle);
+ static void DeleteObject(const Context *context, ProgramPipeline *pipeline);
+
+ protected:
+ ~ProgramPipelineManager() override {}
};
-}
+} // namespace gl
#endif // LIBANGLE_RESOURCEMANAGER_H_
diff --git a/src/3rdparty/angle/src/libANGLE/ResourceMap.h b/src/3rdparty/angle/src/libANGLE/ResourceMap.h
new file mode 100644
index 0000000000..b00da68612
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/ResourceMap.h
@@ -0,0 +1,305 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ResourceMap:
+// An optimized resource map which packs the first set of allocated objects into a
+// flat array, and then falls back to an unordered map for the higher handle values.
+//
+
+#ifndef LIBANGLE_RESOURCE_MAP_H_
+#define LIBANGLE_RESOURCE_MAP_H_
+
+#include "libANGLE/angletypes.h"
+
+namespace gl
+{
+
+template <typename ResourceType>
+class ResourceMap final : angle::NonCopyable
+{
+ public:
+ ResourceMap();
+ ~ResourceMap();
+
+ ResourceType *query(GLuint handle) const;
+
+ // Returns true if the handle was reserved. Not necessarily if the resource is created.
+ bool contains(GLuint handle) const;
+
+ // Returns the element that was at this location.
+ bool erase(GLuint handle, ResourceType **resourceOut);
+
+ void assign(GLuint handle, ResourceType *resource);
+
+ // Clears the map.
+ void clear();
+
+ using IndexAndResource = std::pair<GLuint, ResourceType *>;
+ using HashMap = std::unordered_map<GLuint, ResourceType *>;
+
+ class Iterator final
+ {
+ public:
+ bool operator==(const Iterator &other) const;
+ bool operator!=(const Iterator &other) const;
+ Iterator &operator++();
+ const IndexAndResource *operator->() const;
+ const IndexAndResource &operator*() const;
+
+ private:
+ friend class ResourceMap;
+ Iterator(const ResourceMap &origin,
+ GLuint flatIndex,
+ typename HashMap::const_iterator hashIndex);
+ void updateValue();
+
+ const ResourceMap &mOrigin;
+ GLuint mFlatIndex;
+ typename HashMap::const_iterator mHashIndex;
+ IndexAndResource mValue;
+ };
+
+ // null values represent reserved handles.
+ Iterator begin() const;
+ Iterator end() const;
+ Iterator find(GLuint handle) const;
+
+ // Not a constant-time operation, should only be used for verification.
+ bool empty() const;
+
+ private:
+ friend class Iterator;
+
+ GLuint nextNonNullResource(size_t flatIndex) const;
+
+ // constexpr methods cannot contain reinterpret_cast, so we need a static method.
+ static ResourceType *InvalidPointer();
+ static constexpr intptr_t kInvalidPointer = static_cast<intptr_t>(-1);
+
+ // Start with 32 maximum elements in the map, which can grow.
+ static constexpr size_t kInitialFlatResourcesSize = 0x20;
+
+ // Experimental testing suggests that 16k is a reasonable upper limit.
+ static constexpr size_t kFlatResourcesLimit = 0x4000;
+
+ std::vector<ResourceType *> mFlatResources;
+
+ // A map of GL objects indexed by object ID.
+ HashMap mHashedResources;
+};
+
+template <typename ResourceType>
+ResourceMap<ResourceType>::ResourceMap()
+ : mFlatResources(kInitialFlatResourcesSize, InvalidPointer()), mHashedResources()
+{
+}
+
+template <typename ResourceType>
+ResourceMap<ResourceType>::~ResourceMap()
+{
+ ASSERT(empty());
+}
+
+template <typename ResourceType>
+ResourceType *ResourceMap<ResourceType>::query(GLuint handle) const
+{
+ if (handle < mFlatResources.size())
+ {
+ auto value = mFlatResources[handle];
+ return (value == InvalidPointer() ? nullptr : value);
+ }
+ auto it = mHashedResources.find(handle);
+ return (it == mHashedResources.end() ? nullptr : it->second);
+}
+
+template <typename ResourceType>
+bool ResourceMap<ResourceType>::contains(GLuint handle) const
+{
+ if (handle < mFlatResources.size())
+ {
+ return (mFlatResources[handle] != InvalidPointer());
+ }
+ return (mHashedResources.find(handle) != mHashedResources.end());
+}
+
+template <typename ResourceType>
+bool ResourceMap<ResourceType>::erase(GLuint handle, ResourceType **resourceOut)
+{
+ if (handle < mFlatResources.size())
+ {
+ auto &value = mFlatResources[handle];
+ if (value == InvalidPointer())
+ {
+ return false;
+ }
+ *resourceOut = value;
+ value = InvalidPointer();
+ }
+ else
+ {
+ auto it = mHashedResources.find(handle);
+ if (it == mHashedResources.end())
+ {
+ return false;
+ }
+ *resourceOut = it->second;
+ mHashedResources.erase(it);
+ }
+ return true;
+}
+
+template <typename ResourceType>
+void ResourceMap<ResourceType>::assign(GLuint handle, ResourceType *resource)
+{
+ if (handle < kFlatResourcesLimit)
+ {
+ if (handle >= mFlatResources.size())
+ {
+ // Use power-of-two.
+ size_t newSize = mFlatResources.size();
+ while (newSize <= handle)
+ {
+ newSize *= 2;
+ }
+ mFlatResources.resize(newSize, nullptr);
+ }
+ ASSERT(mFlatResources.size() > handle);
+ mFlatResources[handle] = resource;
+ }
+ else
+ {
+ mHashedResources[handle] = resource;
+ }
+}
+
+template <typename ResourceType>
+typename ResourceMap<ResourceType>::Iterator ResourceMap<ResourceType>::begin() const
+{
+ return Iterator(*this, nextNonNullResource(0), mHashedResources.begin());
+}
+
+template <typename ResourceType>
+typename ResourceMap<ResourceType>::Iterator ResourceMap<ResourceType>::end() const
+{
+ return Iterator(*this, static_cast<GLuint>(mFlatResources.size()), mHashedResources.end());
+}
+
+template <typename ResourceType>
+typename ResourceMap<ResourceType>::Iterator ResourceMap<ResourceType>::find(GLuint handle) const
+{
+ if (handle < mFlatResources.size())
+ {
+ return (mFlatResources[handle] != InvalidPointer()
+ ? Iterator(handle, mHashedResources.begin())
+ : end());
+ }
+ else
+ {
+ return mHashedResources.find(handle);
+ }
+}
+
+template <typename ResourceType>
+bool ResourceMap<ResourceType>::empty() const
+{
+ return (begin() == end());
+}
+
+template <typename ResourceType>
+void ResourceMap<ResourceType>::clear()
+{
+ mFlatResources.assign(kInitialFlatResourcesSize, InvalidPointer());
+ mHashedResources.clear();
+}
+
+template <typename ResourceType>
+GLuint ResourceMap<ResourceType>::nextNonNullResource(size_t flatIndex) const
+{
+ for (size_t index = flatIndex; index < mFlatResources.size(); index++)
+ {
+ if (mFlatResources[index] != nullptr && mFlatResources[index] != InvalidPointer())
+ {
+ return static_cast<GLuint>(index);
+ }
+ }
+ return static_cast<GLuint>(mFlatResources.size());
+}
+
+template <typename ResourceType>
+// static
+ResourceType *ResourceMap<ResourceType>::InvalidPointer()
+{
+ return reinterpret_cast<ResourceType *>(kInvalidPointer);
+}
+
+template <typename ResourceType>
+ResourceMap<ResourceType>::Iterator::Iterator(
+ const ResourceMap &origin,
+ GLuint flatIndex,
+ typename ResourceMap<ResourceType>::HashMap::const_iterator hashIndex)
+ : mOrigin(origin), mFlatIndex(flatIndex), mHashIndex(hashIndex), mValue()
+{
+ updateValue();
+}
+
+template <typename ResourceType>
+bool ResourceMap<ResourceType>::Iterator::operator==(const Iterator &other) const
+{
+ return (mFlatIndex == other.mFlatIndex && mHashIndex == other.mHashIndex);
+}
+
+template <typename ResourceType>
+bool ResourceMap<ResourceType>::Iterator::operator!=(const Iterator &other) const
+{
+ return !(*this == other);
+}
+
+template <typename ResourceType>
+typename ResourceMap<ResourceType>::Iterator &ResourceMap<ResourceType>::Iterator::operator++()
+{
+ if (mFlatIndex < static_cast<GLuint>(mOrigin.mFlatResources.size()))
+ {
+ mFlatIndex = mOrigin.nextNonNullResource(mFlatIndex + 1);
+ }
+ else
+ {
+ mHashIndex++;
+ }
+ updateValue();
+ return *this;
+}
+
+template <typename ResourceType>
+const typename ResourceMap<ResourceType>::IndexAndResource
+ *ResourceMap<ResourceType>::Iterator::operator->() const
+{
+ return &mValue;
+}
+
+template <typename ResourceType>
+const typename ResourceMap<ResourceType>::IndexAndResource
+ &ResourceMap<ResourceType>::Iterator::operator*() const
+{
+ return mValue;
+}
+
+template <typename ResourceType>
+void ResourceMap<ResourceType>::Iterator::updateValue()
+{
+ if (mFlatIndex < static_cast<GLuint>(mOrigin.mFlatResources.size()))
+ {
+ mValue.first = mFlatIndex;
+ mValue.second = mOrigin.mFlatResources[mFlatIndex];
+ }
+ else if (mHashIndex != mOrigin.mHashedResources.end())
+ {
+ mValue.first = mHashIndex->first;
+ mValue.second = mHashIndex->second;
+ }
+}
+
+} // namespace gl
+
+#endif // LIBANGLE_RESOURCE_MAP_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Sampler.cpp b/src/3rdparty/angle/src/libANGLE/Sampler.cpp
index d8d606a46f..0f05b697a2 100644
--- a/src/3rdparty/angle/src/libANGLE/Sampler.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Sampler.cpp
@@ -9,14 +9,14 @@
#include "libANGLE/Sampler.h"
#include "libANGLE/angletypes.h"
-#include "libANGLE/renderer/ImplFactory.h"
+#include "libANGLE/renderer/GLImplFactory.h"
#include "libANGLE/renderer/SamplerImpl.h"
namespace gl
{
-Sampler::Sampler(rx::ImplFactory *factory, GLuint id)
- : RefCountObject(id), mImpl(factory->createSampler()), mLabel(), mSamplerState()
+Sampler::Sampler(rx::GLImplFactory *factory, GLuint id)
+ : RefCountObject(id), mState(), mImpl(factory->createSampler(mState)), mLabel()
{
}
@@ -25,6 +25,11 @@ Sampler::~Sampler()
SafeDelete(mImpl);
}
+Error Sampler::onDestroy(const Context *context)
+{
+ return NoError();
+}
+
void Sampler::setLabel(const std::string &label)
{
mLabel = label;
@@ -37,116 +42,128 @@ const std::string &Sampler::getLabel() const
void Sampler::setMinFilter(GLenum minFilter)
{
- mSamplerState.minFilter = minFilter;
+ mState.minFilter = minFilter;
}
GLenum Sampler::getMinFilter() const
{
- return mSamplerState.minFilter;
+ return mState.minFilter;
}
void Sampler::setMagFilter(GLenum magFilter)
{
- mSamplerState.magFilter = magFilter;
+ mState.magFilter = magFilter;
}
GLenum Sampler::getMagFilter() const
{
- return mSamplerState.magFilter;
+ return mState.magFilter;
}
void Sampler::setWrapS(GLenum wrapS)
{
- mSamplerState.wrapS = wrapS;
+ mState.wrapS = wrapS;
}
GLenum Sampler::getWrapS() const
{
- return mSamplerState.wrapS;
+ return mState.wrapS;
}
void Sampler::setWrapT(GLenum wrapT)
{
- mSamplerState.wrapT = wrapT;
+ mState.wrapT = wrapT;
}
GLenum Sampler::getWrapT() const
{
- return mSamplerState.wrapT;
+ return mState.wrapT;
}
void Sampler::setWrapR(GLenum wrapR)
{
- mSamplerState.wrapR = wrapR;
+ mState.wrapR = wrapR;
}
GLenum Sampler::getWrapR() const
{
- return mSamplerState.wrapR;
+ return mState.wrapR;
}
void Sampler::setMaxAnisotropy(float maxAnisotropy)
{
- mSamplerState.maxAnisotropy = maxAnisotropy;
+ mState.maxAnisotropy = maxAnisotropy;
}
float Sampler::getMaxAnisotropy() const
{
- return mSamplerState.maxAnisotropy;
+ return mState.maxAnisotropy;
}
void Sampler::setMinLod(GLfloat minLod)
{
- mSamplerState.minLod = minLod;
+ mState.minLod = minLod;
}
GLfloat Sampler::getMinLod() const
{
- return mSamplerState.minLod;
+ return mState.minLod;
}
void Sampler::setMaxLod(GLfloat maxLod)
{
- mSamplerState.maxLod = maxLod;
+ mState.maxLod = maxLod;
}
GLfloat Sampler::getMaxLod() const
{
- return mSamplerState.maxLod;
+ return mState.maxLod;
}
void Sampler::setCompareMode(GLenum compareMode)
{
- mSamplerState.compareMode = compareMode;
+ mState.compareMode = compareMode;
}
GLenum Sampler::getCompareMode() const
{
- return mSamplerState.compareMode;
+ return mState.compareMode;
}
void Sampler::setCompareFunc(GLenum compareFunc)
{
- mSamplerState.compareFunc = compareFunc;
+ mState.compareFunc = compareFunc;
}
GLenum Sampler::getCompareFunc() const
{
- return mSamplerState.compareFunc;
+ return mState.compareFunc;
}
-const SamplerState &Sampler::getSamplerState() const
+void Sampler::setSRGBDecode(GLenum sRGBDecode)
{
- return mSamplerState;
+ mState.sRGBDecode = sRGBDecode;
}
-const rx::SamplerImpl *Sampler::getImplementation() const
+GLenum Sampler::getSRGBDecode() const
{
- return mImpl;
+ return mState.sRGBDecode;
+}
+
+const SamplerState &Sampler::getSamplerState() const
+{
+ return mState;
}
-rx::SamplerImpl *Sampler::getImplementation()
+rx::SamplerImpl *Sampler::getImplementation() const
{
return mImpl;
}
+
+void Sampler::syncState(const Context *context)
+{
+ // TODO(jmadill): Use actual dirty bits for sampler.
+ mImpl->syncState(context);
}
+
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/Sampler.h b/src/3rdparty/angle/src/libANGLE/Sampler.h
index a40b1655fc..cd34273b44 100644
--- a/src/3rdparty/angle/src/libANGLE/Sampler.h
+++ b/src/3rdparty/angle/src/libANGLE/Sampler.h
@@ -16,7 +16,7 @@
namespace rx
{
-class ImplFactory;
+class GLImplFactory;
class SamplerImpl;
}
@@ -26,9 +26,11 @@ namespace gl
class Sampler final : public RefCountObject, public LabeledObject
{
public:
- Sampler(rx::ImplFactory *factory, GLuint id);
+ Sampler(rx::GLImplFactory *factory, GLuint id);
~Sampler() override;
+ Error onDestroy(const Context *context) override;
+
void setLabel(const std::string &label) override;
const std::string &getLabel() const override;
@@ -62,19 +64,22 @@ class Sampler final : public RefCountObject, public LabeledObject
void setCompareFunc(GLenum compareFunc);
GLenum getCompareFunc() const;
+ void setSRGBDecode(GLenum sRGBDecode);
+ GLenum getSRGBDecode() const;
+
const SamplerState &getSamplerState() const;
- const rx::SamplerImpl *getImplementation() const;
- rx::SamplerImpl *getImplementation();
+ rx::SamplerImpl *getImplementation() const;
+
+ void syncState(const Context *context);
private:
+ SamplerState mState;
rx::SamplerImpl *mImpl;
std::string mLabel;
-
- SamplerState mSamplerState;
};
-}
+} // namespace gl
#endif // LIBANGLE_SAMPLER_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Shader.cpp b/src/3rdparty/angle/src/libANGLE/Shader.cpp
index bbe9077fc9..94c4f3c705 100644
--- a/src/3rdparty/angle/src/libANGLE/Shader.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Shader.cpp
@@ -14,11 +14,13 @@
#include "common/utilities.h"
#include "GLSLANG/ShaderLang.h"
+#include "libANGLE/Caps.h"
#include "libANGLE/Compiler.h"
#include "libANGLE/Constants.h"
-#include "libANGLE/renderer/Renderer.h"
+#include "libANGLE/renderer/GLImplFactory.h"
#include "libANGLE/renderer/ShaderImpl.h"
#include "libANGLE/ResourceManager.h"
+#include "libANGLE/Context.h"
namespace gl
{
@@ -55,16 +57,16 @@ bool CompareShaderVar(const sh::ShaderVariable &x, const sh::ShaderVariable &y)
{
if (x.type == y.type)
{
- return x.arraySize > y.arraySize;
+ return x.getArraySizeProduct() > y.getArraySizeProduct();
}
// Special case for handling structs: we sort these to the end of the list
- if (x.type == GL_STRUCT_ANGLEX)
+ if (x.type == GL_NONE)
{
return false;
}
- if (y.type == GL_STRUCT_ANGLEX)
+ if (y.type == GL_NONE)
{
return true;
}
@@ -72,45 +74,61 @@ bool CompareShaderVar(const sh::ShaderVariable &x, const sh::ShaderVariable &y)
return gl::VariableSortOrder(x.type) < gl::VariableSortOrder(y.type);
}
-Shader::Data::Data(GLenum shaderType) : mLabel(), mShaderType(shaderType), mShaderVersion(100)
+ShaderState::ShaderState(GLenum shaderType)
+ : mLabel(),
+ mShaderType(shaderType),
+ mShaderVersion(100),
+ mNumViews(-1),
+ mGeometryShaderInputPrimitiveType(GL_INVALID_VALUE),
+ mGeometryShaderOutputPrimitiveType(GL_INVALID_VALUE),
+ mGeometryShaderInvocations(1),
+ mGeometryShaderMaxVertices(-1),
+ mCompileStatus(CompileStatus::NOT_COMPILED)
{
+ mLocalSize.fill(-1);
}
-Shader::Data::~Data()
+ShaderState::~ShaderState()
{
}
-Shader::Shader(ResourceManager *manager,
- rx::ImplFactory *implFactory,
+Shader::Shader(ShaderProgramManager *manager,
+ rx::GLImplFactory *implFactory,
const gl::Limitations &rendererLimitations,
GLenum type,
GLuint handle)
- : mData(type),
- mImplementation(implFactory->createShader(mData)),
+ : mState(type),
+ mImplementation(implFactory->createShader(mState)),
mRendererLimitations(rendererLimitations),
mHandle(handle),
mType(type),
mRefCount(0),
mDeleteStatus(false),
- mCompiled(false),
mResourceManager(manager)
{
ASSERT(mImplementation);
}
+void Shader::onDestroy(const gl::Context *context)
+{
+ mBoundCompiler.set(context, nullptr);
+ mImplementation.reset(nullptr);
+ delete this;
+}
+
Shader::~Shader()
{
- SafeDelete(mImplementation);
+ ASSERT(!mImplementation);
}
void Shader::setLabel(const std::string &label)
{
- mData.mLabel = label;
+ mState.mLabel = label;
}
const std::string &Shader::getLabel() const
{
- return mData.mLabel;
+ return mState.mLabel;
}
GLuint Shader::getHandle() const
@@ -134,11 +152,12 @@ void Shader::setSource(GLsizei count, const char *const *string, const GLint *le
}
}
- mData.mSource = stream.str();
+ mState.mSource = stream.str();
}
-int Shader::getInfoLogLength() const
+int Shader::getInfoLogLength(const Context *context)
{
+ resolveCompile(context);
if (mInfoLog.empty())
{
return 0;
@@ -147,8 +166,10 @@ int Shader::getInfoLogLength() const
return (static_cast<int>(mInfoLog.length()) + 1);
}
-void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
+void Shader::getInfoLog(const Context *context, GLsizei bufSize, GLsizei *length, char *infoLog)
{
+ resolveCompile(context);
+
int index = 0;
if (bufSize > 0)
@@ -167,21 +188,25 @@ void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
int Shader::getSourceLength() const
{
- return mData.mSource.empty() ? 0 : (static_cast<int>(mData.mSource.length()) + 1);
+ return mState.mSource.empty() ? 0 : (static_cast<int>(mState.mSource.length()) + 1);
}
-int Shader::getTranslatedSourceLength() const
+int Shader::getTranslatedSourceLength(const Context *context)
{
- if (mData.mTranslatedSource.empty())
+ resolveCompile(context);
+
+ if (mState.mTranslatedSource.empty())
{
return 0;
}
- return (static_cast<int>(mData.mTranslatedSource.length()) + 1);
+ return (static_cast<int>(mState.mTranslatedSource.length()) + 1);
}
-int Shader::getTranslatedSourceWithDebugInfoLength() const
+int Shader::getTranslatedSourceWithDebugInfoLength(const Context *context)
{
+ resolveCompile(context);
+
const std::string &debugInfo = mImplementation->getDebugInfo();
if (debugInfo.empty())
{
@@ -191,7 +216,11 @@ int Shader::getTranslatedSourceWithDebugInfoLength() const
return (static_cast<int>(debugInfo.length()) + 1);
}
-void Shader::getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer)
+// static
+void Shader::GetSourceImpl(const std::string &source,
+ GLsizei bufSize,
+ GLsizei *length,
+ char *buffer)
{
int index = 0;
@@ -211,117 +240,186 @@ void Shader::getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *
void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) const
{
- getSourceImpl(mData.mSource, bufSize, length, buffer);
+ GetSourceImpl(mState.mSource, bufSize, length, buffer);
+}
+
+void Shader::getTranslatedSource(const Context *context,
+ GLsizei bufSize,
+ GLsizei *length,
+ char *buffer)
+{
+ GetSourceImpl(getTranslatedSource(context), bufSize, length, buffer);
}
-void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const
+const std::string &Shader::getTranslatedSource(const Context *context)
{
- getSourceImpl(mData.mTranslatedSource, bufSize, length, buffer);
+ resolveCompile(context);
+ return mState.mTranslatedSource;
}
-void Shader::getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const
+void Shader::getTranslatedSourceWithDebugInfo(const Context *context,
+ GLsizei bufSize,
+ GLsizei *length,
+ char *buffer)
{
+ resolveCompile(context);
const std::string &debugInfo = mImplementation->getDebugInfo();
- getSourceImpl(debugInfo, bufSize, length, buffer);
+ GetSourceImpl(debugInfo, bufSize, length, buffer);
}
-void Shader::compile(Compiler *compiler)
+void Shader::compile(const Context *context)
{
- mData.mTranslatedSource.clear();
+ mState.mTranslatedSource.clear();
mInfoLog.clear();
- mData.mShaderVersion = 100;
- mData.mVaryings.clear();
- mData.mUniforms.clear();
- mData.mInterfaceBlocks.clear();
- mData.mActiveAttributes.clear();
- mData.mActiveOutputVariables.clear();
-
- ShHandle compilerHandle = compiler->getCompilerHandle(mData.mShaderType);
+ mState.mShaderVersion = 100;
+ mState.mInputVaryings.clear();
+ mState.mOutputVaryings.clear();
+ mState.mUniforms.clear();
+ mState.mUniformBlocks.clear();
+ mState.mShaderStorageBlocks.clear();
+ mState.mActiveAttributes.clear();
+ mState.mActiveOutputVariables.clear();
+ mState.mNumViews = -1;
+ mState.mGeometryShaderInputPrimitiveType = GL_INVALID_VALUE;
+ mState.mGeometryShaderOutputPrimitiveType = GL_INVALID_VALUE;
+ mState.mGeometryShaderInvocations = 1;
+ mState.mGeometryShaderMaxVertices = -1;
+
+ mState.mCompileStatus = CompileStatus::COMPILE_REQUESTED;
+ mBoundCompiler.set(context, context->getCompiler());
+
+ // Cache the compile source and options for compilation. Must be done now, since the source
+ // can change before the link call or another call that resolves the compile.
std::stringstream sourceStream;
- std::string sourcePath;
- int additionalOptions =
- mImplementation->prepareSourceAndReturnOptions(&sourceStream, &sourcePath);
- int compileOptions = (SH_OBJECT_CODE | SH_VARIABLES | additionalOptions);
+ mLastCompileOptions =
+ mImplementation->prepareSourceAndReturnOptions(&sourceStream, &mLastCompiledSourcePath);
+ mLastCompileOptions |= (SH_OBJECT_CODE | SH_VARIABLES);
+ mLastCompiledSource = sourceStream.str();
+
+ // Add default options to WebGL shaders to prevent unexpected behavior during compilation.
+ if (context->getExtensions().webglCompatibility)
+ {
+ mLastCompileOptions |= SH_INIT_GL_POSITION;
+ mLastCompileOptions |= SH_LIMIT_CALL_STACK_DEPTH;
+ mLastCompileOptions |= SH_LIMIT_EXPRESSION_COMPLEXITY;
+ mLastCompileOptions |= SH_ENFORCE_PACKING_RESTRICTIONS;
+ }
// Some targets (eg D3D11 Feature Level 9_3 and below) do not support non-constant loop indexes
// in fragment shaders. Shader compilation will fail. To provide a better error message we can
// instruct the compiler to pre-validate.
if (mRendererLimitations.shadersRequireIndexedLoopValidation)
{
- compileOptions |= SH_VALIDATE_LOOP_INDEXING;
+ mLastCompileOptions |= SH_VALIDATE_LOOP_INDEXING;
}
+}
- std::string sourceString = sourceStream.str();
- std::vector<const char *> sourceCStrings;
-
- if (!sourcePath.empty())
+void Shader::resolveCompile(const Context *context)
+{
+ if (!mState.compilePending())
{
- sourceCStrings.push_back(sourcePath.c_str());
+ return;
}
- sourceCStrings.push_back(sourceString.c_str());
+ ASSERT(mBoundCompiler.get());
+ ShHandle compilerHandle = mBoundCompiler->getCompilerHandle(mState.mShaderType);
+
+ std::vector<const char *> srcStrings;
+
+ if (!mLastCompiledSourcePath.empty())
+ {
+ srcStrings.push_back(mLastCompiledSourcePath.c_str());
+ }
- bool result =
- ShCompile(compilerHandle, &sourceCStrings[0], sourceCStrings.size(), compileOptions);
+ srcStrings.push_back(mLastCompiledSource.c_str());
- if (!result)
+ if (!sh::Compile(compilerHandle, &srcStrings[0], srcStrings.size(), mLastCompileOptions))
{
- mInfoLog = ShGetInfoLog(compilerHandle);
- TRACE("\n%s", mInfoLog.c_str());
- mCompiled = false;
+ mInfoLog = sh::GetInfoLog(compilerHandle);
+ WARN() << std::endl << mInfoLog;
+ mState.mCompileStatus = CompileStatus::NOT_COMPILED;
return;
}
- mData.mTranslatedSource = ShGetObjectCode(compilerHandle);
+ mState.mTranslatedSource = sh::GetObjectCode(compilerHandle);
-#ifndef NDEBUG
+#if !defined(NDEBUG)
// Prefix translated shader with commented out un-translated shader.
// Useful in diagnostics tools which capture the shader source.
std::ostringstream shaderStream;
shaderStream << "// GLSL\n";
shaderStream << "//\n";
- size_t curPos = 0;
- while (curPos != std::string::npos)
+ std::istringstream inputSourceStream(mState.mSource);
+ std::string line;
+ while (std::getline(inputSourceStream, line))
{
- size_t nextLine = mData.mSource.find("\n", curPos);
- size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1);
-
- shaderStream << "// " << mData.mSource.substr(curPos, len);
+ // Remove null characters from the source line
+ line.erase(std::remove(line.begin(), line.end(), '\0'), line.end());
- curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1);
+ shaderStream << "// " << line << std::endl;
}
shaderStream << "\n\n";
- shaderStream << mData.mTranslatedSource;
- mData.mTranslatedSource = shaderStream.str();
-#endif
+ shaderStream << mState.mTranslatedSource;
+ mState.mTranslatedSource = shaderStream.str();
+#endif // !defined(NDEBUG)
// Gather the shader information
- mData.mShaderVersion = ShGetShaderVersion(compilerHandle);
+ mState.mShaderVersion = sh::GetShaderVersion(compilerHandle);
- mData.mVaryings = GetShaderVariables(ShGetVaryings(compilerHandle));
- mData.mUniforms = GetShaderVariables(ShGetUniforms(compilerHandle));
- mData.mInterfaceBlocks = GetShaderVariables(ShGetInterfaceBlocks(compilerHandle));
+ mState.mUniforms = GetShaderVariables(sh::GetUniforms(compilerHandle));
+ mState.mUniformBlocks = GetShaderVariables(sh::GetUniformBlocks(compilerHandle));
+ mState.mShaderStorageBlocks = GetShaderVariables(sh::GetShaderStorageBlocks(compilerHandle));
- if (mData.mShaderType == GL_VERTEX_SHADER)
+ switch (mState.mShaderType)
{
- mData.mActiveAttributes = GetActiveShaderVariables(ShGetAttributes(compilerHandle));
- }
- else
- {
- ASSERT(mData.mShaderType == GL_FRAGMENT_SHADER);
-
- // TODO(jmadill): Figure out why we only sort in the FS, and if we need to.
- std::sort(mData.mVaryings.begin(), mData.mVaryings.end(), CompareShaderVar);
- mData.mActiveOutputVariables =
- GetActiveShaderVariables(ShGetOutputVariables(compilerHandle));
+ case GL_COMPUTE_SHADER:
+ {
+ mState.mLocalSize = sh::GetComputeShaderLocalGroupSize(compilerHandle);
+ break;
+ }
+ case GL_VERTEX_SHADER:
+ {
+ {
+ mState.mOutputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
+ mState.mActiveAttributes =
+ GetActiveShaderVariables(sh::GetAttributes(compilerHandle));
+ mState.mNumViews = sh::GetVertexShaderNumViews(compilerHandle);
+ }
+ break;
+ }
+ case GL_FRAGMENT_SHADER:
+ {
+ mState.mInputVaryings = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
+ // TODO(jmadill): Figure out why we only sort in the FS, and if we need to.
+ std::sort(mState.mInputVaryings.begin(), mState.mInputVaryings.end(), CompareShaderVar);
+ mState.mActiveOutputVariables =
+ GetActiveShaderVariables(sh::GetOutputVariables(compilerHandle));
+ break;
+ }
+ case GL_GEOMETRY_SHADER_EXT:
+ {
+ mState.mInputVaryings = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
+ mState.mOutputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
+
+ mState.mGeometryShaderInputPrimitiveType =
+ sh::GetGeometryShaderInputPrimitiveType(compilerHandle);
+ mState.mGeometryShaderOutputPrimitiveType =
+ sh::GetGeometryShaderOutputPrimitiveType(compilerHandle);
+ mState.mGeometryShaderInvocations = sh::GetGeometryShaderInvocations(compilerHandle);
+ mState.mGeometryShaderMaxVertices = sh::GetGeometryShaderMaxVertices(compilerHandle);
+ break;
+ }
+ default:
+ UNREACHABLE();
}
- ASSERT(!mData.mTranslatedSource.empty());
+ ASSERT(!mState.mTranslatedSource.empty());
- mCompiled = mImplementation->postTranslateCompile(compiler, &mInfoLog);
+ bool success = mImplementation->postTranslateCompile(mBoundCompiler.get(), &mInfoLog);
+ mState.mCompileStatus = success ? CompileStatus::COMPILED : CompileStatus::NOT_COMPILED;
}
void Shader::addRef()
@@ -329,13 +427,13 @@ void Shader::addRef()
mRefCount++;
}
-void Shader::release()
+void Shader::release(const Context *context)
{
mRefCount--;
if (mRefCount == 0 && mDeleteStatus)
{
- mResourceManager->deleteShader(mHandle);
+ mResourceManager->deleteShader(context, mHandle);
}
}
@@ -354,57 +452,110 @@ void Shader::flagForDeletion()
mDeleteStatus = true;
}
-int Shader::getShaderVersion() const
+bool Shader::isCompiled(const Context *context)
{
- return mData.mShaderVersion;
+ resolveCompile(context);
+ return mState.mCompileStatus == CompileStatus::COMPILED;
}
-const std::vector<sh::Varying> &Shader::getVaryings() const
+int Shader::getShaderVersion(const Context *context)
{
- return mData.getVaryings();
+ resolveCompile(context);
+ return mState.mShaderVersion;
}
-const std::vector<sh::Uniform> &Shader::getUniforms() const
+const std::vector<sh::Varying> &Shader::getInputVaryings(const Context *context)
{
- return mData.getUniforms();
+ resolveCompile(context);
+ return mState.getInputVaryings();
}
-const std::vector<sh::InterfaceBlock> &Shader::getInterfaceBlocks() const
+const std::vector<sh::Varying> &Shader::getOutputVaryings(const Context *context)
{
- return mData.getInterfaceBlocks();
+ resolveCompile(context);
+ return mState.getOutputVaryings();
}
-const std::vector<sh::Attribute> &Shader::getActiveAttributes() const
+const std::vector<sh::Uniform> &Shader::getUniforms(const Context *context)
{
- return mData.getActiveAttributes();
+ resolveCompile(context);
+ return mState.getUniforms();
}
-const std::vector<sh::OutputVariable> &Shader::getActiveOutputVariables() const
+const std::vector<sh::InterfaceBlock> &Shader::getUniformBlocks(const Context *context)
{
- return mData.getActiveOutputVariables();
+ resolveCompile(context);
+ return mState.getUniformBlocks();
}
-int Shader::getSemanticIndex(const std::string &attributeName) const
+const std::vector<sh::InterfaceBlock> &Shader::getShaderStorageBlocks(const Context *context)
{
- if (!attributeName.empty())
- {
- const auto &activeAttributes = mData.getActiveAttributes();
+ resolveCompile(context);
+ return mState.getShaderStorageBlocks();
+}
- int semanticIndex = 0;
- for (size_t attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
- {
- const sh::ShaderVariable &attribute = activeAttributes[attributeIndex];
+const std::vector<sh::Attribute> &Shader::getActiveAttributes(const Context *context)
+{
+ resolveCompile(context);
+ return mState.getActiveAttributes();
+}
+
+const std::vector<sh::OutputVariable> &Shader::getActiveOutputVariables(const Context *context)
+{
+ resolveCompile(context);
+ return mState.getActiveOutputVariables();
+}
- if (attribute.name == attributeName)
+std::string Shader::getTransformFeedbackVaryingMappedName(const std::string &tfVaryingName,
+ const Context *context)
+{
+ // TODO(jiawei.shao@intel.com): support transform feedback on geometry shader.
+ ASSERT(mState.getShaderType() == GL_VERTEX_SHADER);
+ const auto &varyings = getOutputVaryings(context);
+ auto bracketPos = tfVaryingName.find("[");
+ if (bracketPos != std::string::npos)
+ {
+ auto tfVaryingBaseName = tfVaryingName.substr(0, bracketPos);
+ for (const auto &varying : varyings)
+ {
+ if (varying.name == tfVaryingBaseName)
{
- return semanticIndex;
+ std::string mappedNameWithArrayIndex =
+ varying.mappedName + tfVaryingName.substr(bracketPos);
+ return mappedNameWithArrayIndex;
+ }
+ }
+ }
+ else
+ {
+ for (const auto &varying : varyings)
+ {
+ if (varying.name == tfVaryingName)
+ {
+ return varying.mappedName;
}
-
- semanticIndex += gl::VariableRegisterCount(attribute.type);
}
}
+ UNREACHABLE();
+ return std::string();
+}
- return -1;
+const sh::WorkGroupSize &Shader::getWorkGroupSize(const Context *context)
+{
+ resolveCompile(context);
+ return mState.mLocalSize;
}
+int Shader::getNumViews(const Context *context)
+{
+ resolveCompile(context);
+ return mState.mNumViews;
}
+
+const std::string &Shader::getCompilerResourcesString() const
+{
+ ASSERT(mBoundCompiler.get());
+ return mBoundCompiler->getBuiltinResourcesString(mState.mShaderType);
+}
+
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/Shader.h b/src/3rdparty/angle/src/libANGLE/Shader.h
index 997977c87b..4b6be4696d 100644
--- a/src/3rdparty/angle/src/libANGLE/Shader.h
+++ b/src/3rdparty/angle/src/libANGLE/Shader.h
@@ -12,20 +12,22 @@
#ifndef LIBANGLE_SHADER_H_
#define LIBANGLE_SHADER_H_
-#include <string>
#include <list>
+#include <memory>
+#include <string>
#include <vector>
#include "angle_gl.h"
#include <GLSLANG/ShaderLang.h>
+#include "common/Optional.h"
#include "common/angleutils.h"
-#include "libANGLE/angletypes.h"
#include "libANGLE/Debug.h"
+#include "libANGLE/angletypes.h"
namespace rx
{
-class ImplFactory;
+class GLImplFactory;
class ShaderImpl;
class ShaderSh;
}
@@ -33,63 +35,92 @@ class ShaderSh;
namespace gl
{
class Compiler;
+class ContextState;
struct Limitations;
-class ResourceManager;
-struct Data;
+class ShaderProgramManager;
+class Context;
-class Shader final : angle::NonCopyable, public LabeledObject
+// We defer the compile until link time, or until properties are queried.
+enum class CompileStatus
+{
+ NOT_COMPILED,
+ COMPILE_REQUESTED,
+ COMPILED,
+};
+
+class ShaderState final : angle::NonCopyable
{
public:
- class Data final : angle::NonCopyable
+ ShaderState(GLenum shaderType);
+ ~ShaderState();
+
+ const std::string &getLabel() const { return mLabel; }
+
+ const std::string &getSource() const { return mSource; }
+ const std::string &getTranslatedSource() const { return mTranslatedSource; }
+
+ GLenum getShaderType() const { return mShaderType; }
+ int getShaderVersion() const { return mShaderVersion; }
+
+ const std::vector<sh::Varying> &getInputVaryings() const { return mInputVaryings; }
+ const std::vector<sh::Varying> &getOutputVaryings() const { return mOutputVaryings; }
+ const std::vector<sh::Uniform> &getUniforms() const { return mUniforms; }
+ const std::vector<sh::InterfaceBlock> &getUniformBlocks() const { return mUniformBlocks; }
+ const std::vector<sh::InterfaceBlock> &getShaderStorageBlocks() const
{
- public:
- Data(GLenum shaderType);
- ~Data();
-
- const std::string &getLabel() const { return mLabel; }
-
- const std::string &getSource() const { return mSource; }
- const std::string &getTranslatedSource() const { return mTranslatedSource; }
-
- GLenum getShaderType() const { return mShaderType; }
- int getShaderVersion() const { return mShaderVersion; }
-
- const std::vector<sh::Varying> &getVaryings() const { return mVaryings; }
- const std::vector<sh::Uniform> &getUniforms() const { return mUniforms; }
- const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const
- {
- return mInterfaceBlocks;
- }
- const std::vector<sh::Attribute> &getActiveAttributes() const { return mActiveAttributes; }
- const std::vector<sh::OutputVariable> &getActiveOutputVariables() const
- {
- return mActiveOutputVariables;
- }
-
- private:
- friend class Shader;
-
- std::string mLabel;
-
- GLenum mShaderType;
- int mShaderVersion;
- std::string mTranslatedSource;
- std::string mSource;
-
- std::vector<sh::Varying> mVaryings;
- std::vector<sh::Uniform> mUniforms;
- std::vector<sh::InterfaceBlock> mInterfaceBlocks;
- std::vector<sh::Attribute> mActiveAttributes;
- std::vector<sh::OutputVariable> mActiveOutputVariables;
- };
-
- Shader(ResourceManager *manager,
- rx::ImplFactory *implFactory,
+ return mShaderStorageBlocks;
+ }
+ const std::vector<sh::Attribute> &getActiveAttributes() const { return mActiveAttributes; }
+ const std::vector<sh::OutputVariable> &getActiveOutputVariables() const
+ {
+ return mActiveOutputVariables;
+ }
+
+ bool compilePending() const { return mCompileStatus == CompileStatus::COMPILE_REQUESTED; }
+
+ private:
+ friend class Shader;
+
+ std::string mLabel;
+
+ GLenum mShaderType;
+ int mShaderVersion;
+ std::string mTranslatedSource;
+ std::string mSource;
+
+ sh::WorkGroupSize mLocalSize;
+
+ std::vector<sh::Varying> mInputVaryings;
+ std::vector<sh::Varying> mOutputVaryings;
+ std::vector<sh::Uniform> mUniforms;
+ std::vector<sh::InterfaceBlock> mUniformBlocks;
+ std::vector<sh::InterfaceBlock> mShaderStorageBlocks;
+ std::vector<sh::Attribute> mActiveAttributes;
+ std::vector<sh::OutputVariable> mActiveOutputVariables;
+
+ // ANGLE_multiview.
+ int mNumViews;
+
+ // Geometry Shader.
+ GLenum mGeometryShaderInputPrimitiveType;
+ GLenum mGeometryShaderOutputPrimitiveType;
+ int mGeometryShaderInvocations;
+ int mGeometryShaderMaxVertices;
+
+ // Indicates if this shader has been successfully compiled
+ CompileStatus mCompileStatus;
+};
+
+class Shader final : angle::NonCopyable, public LabeledObject
+{
+ public:
+ Shader(ShaderProgramManager *manager,
+ rx::GLImplFactory *implFactory,
const gl::Limitations &rendererLimitations,
GLenum type,
GLuint handle);
- virtual ~Shader();
+ void onDestroy(const Context *context);
void setLabel(const std::string &label) override;
const std::string &getLabel() const override;
@@ -97,56 +128,85 @@ class Shader final : angle::NonCopyable, public LabeledObject
GLenum getType() const { return mType; }
GLuint getHandle() const;
- const rx::ShaderImpl *getImplementation() const { return mImplementation; }
+ rx::ShaderImpl *getImplementation() const { return mImplementation.get(); }
- void deleteSource();
void setSource(GLsizei count, const char *const *string, const GLint *length);
- int getInfoLogLength() const;
- void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
+ int getInfoLogLength(const Context *context);
+ void getInfoLog(const Context *context, GLsizei bufSize, GLsizei *length, char *infoLog);
int getSourceLength() const;
+ const std::string &getSourceString() const { return mState.getSource(); }
void getSource(GLsizei bufSize, GLsizei *length, char *buffer) const;
- int getTranslatedSourceLength() const;
- int getTranslatedSourceWithDebugInfoLength() const;
- const std::string &getTranslatedSource() const { return mData.getTranslatedSource(); }
- void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const;
- void getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const;
-
- void compile(Compiler *compiler);
- bool isCompiled() const { return mCompiled; }
+ int getTranslatedSourceLength(const Context *context);
+ int getTranslatedSourceWithDebugInfoLength(const Context *context);
+ const std::string &getTranslatedSource(const Context *context);
+ void getTranslatedSource(const Context *context,
+ GLsizei bufSize,
+ GLsizei *length,
+ char *buffer);
+ void getTranslatedSourceWithDebugInfo(const Context *context,
+ GLsizei bufSize,
+ GLsizei *length,
+ char *buffer);
+
+ void compile(const Context *context);
+ bool isCompiled(const Context *context);
void addRef();
- void release();
+ void release(const Context *context);
unsigned int getRefCount() const;
bool isFlaggedForDeletion() const;
void flagForDeletion();
- int getShaderVersion() const;
+ int getShaderVersion(const Context *context);
- const std::vector<sh::Varying> &getVaryings() const;
- const std::vector<sh::Uniform> &getUniforms() const;
- const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const;
- const std::vector<sh::Attribute> &getActiveAttributes() const;
- const std::vector<sh::OutputVariable> &getActiveOutputVariables() const;
+ const std::vector<sh::Varying> &getInputVaryings(const Context *context);
+ const std::vector<sh::Varying> &getOutputVaryings(const Context *context);
+ const std::vector<sh::Uniform> &getUniforms(const Context *context);
+ const std::vector<sh::InterfaceBlock> &getUniformBlocks(const Context *context);
+ const std::vector<sh::InterfaceBlock> &getShaderStorageBlocks(const Context *context);
+ const std::vector<sh::Attribute> &getActiveAttributes(const Context *context);
+ const std::vector<sh::OutputVariable> &getActiveOutputVariables(const Context *context);
- int getSemanticIndex(const std::string &attributeName) const;
+ // Returns mapped name of a transform feedback varying. The original name may contain array
+ // brackets with an index inside, which will get copied to the mapped name. The varying must be
+ // known to be declared in the shader.
+ std::string getTransformFeedbackVaryingMappedName(const std::string &tfVaryingName,
+ const Context *context);
- private:
- static void getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer);
+ const sh::WorkGroupSize &getWorkGroupSize(const Context *context);
+
+ int getNumViews(const Context *context);
- Data mData;
- rx::ShaderImpl *mImplementation;
+ const std::string &getCompilerResourcesString() const;
+
+ private:
+ ~Shader() override;
+ static void GetSourceImpl(const std::string &source,
+ GLsizei bufSize,
+ GLsizei *length,
+ char *buffer);
+
+ void resolveCompile(const Context *context);
+
+ ShaderState mState;
+ std::string mLastCompiledSource;
+ std::string mLastCompiledSourcePath;
+ ShCompileOptions mLastCompileOptions;
+ std::unique_ptr<rx::ShaderImpl> mImplementation;
const gl::Limitations &mRendererLimitations;
const GLuint mHandle;
const GLenum mType;
unsigned int mRefCount; // Number of program objects this shader is attached to
bool mDeleteStatus; // Flag to indicate that the shader can be deleted when no longer in use
- bool mCompiled; // Indicates if this shader has been successfully compiled
std::string mInfoLog;
- ResourceManager *mResourceManager;
+ // We keep a reference to the translator in order to defer compiles while preserving settings.
+ BindingPointer<Compiler> mBoundCompiler;
+
+ ShaderProgramManager *mResourceManager;
};
bool CompareShaderVar(const sh::ShaderVariable &x, const sh::ShaderVariable &y);
-}
+} // namespace gl
#endif // LIBANGLE_SHADER_H_
diff --git a/src/3rdparty/angle/src/libANGLE/SizedMRUCache.h b/src/3rdparty/angle/src/libANGLE/SizedMRUCache.h
new file mode 100644
index 0000000000..6a608a697e
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/SizedMRUCache.h
@@ -0,0 +1,174 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// SizedMRUCache.h: A hashing map that stores blobs of sized, untyped data.
+
+#ifndef LIBANGLE_SIZED_MRU_CACHE_H_
+#define LIBANGLE_SIZED_MRU_CACHE_H_
+
+#include <anglebase/containers/mru_cache.h>
+#include "common/third_party/smhasher/src/PMurHash.h"
+
+namespace angle
+{
+
+template <typename Key, typename Value>
+class SizedMRUCache final : angle::NonCopyable
+{
+ public:
+ SizedMRUCache(size_t maximumTotalSize)
+ : mMaximumTotalSize(maximumTotalSize),
+ mCurrentSize(0),
+ mStore(SizedMRUCacheStore::NO_AUTO_EVICT)
+ {
+ }
+
+ // Returns nullptr on failure.
+ const Value *put(const Key &key, Value &&value, size_t size)
+ {
+ if (size > mMaximumTotalSize)
+ {
+ return nullptr;
+ }
+
+ // Check for existing key.
+ eraseByKey(key);
+
+ auto retVal = mStore.Put(key, ValueAndSize(std::move(value), size));
+ mCurrentSize += size;
+
+ shrinkToSize(mMaximumTotalSize);
+
+ return &retVal->second.value;
+ }
+
+ bool get(const Key &key, const Value **valueOut)
+ {
+ const auto &iter = mStore.Get(key);
+ if (iter == mStore.end())
+ {
+ return false;
+ }
+ *valueOut = &iter->second.value;
+ return true;
+ }
+
+ bool getAt(size_t index, Key *keyOut, const Value **valueOut)
+ {
+ if (index < mStore.size())
+ {
+ auto it = mStore.begin();
+ std::advance(it, index);
+ *keyOut = it->first;
+ *valueOut = &it->second.value;
+ return true;
+ }
+ *valueOut = nullptr;
+ return false;
+ }
+
+ bool empty() const { return mStore.empty(); }
+
+ void clear()
+ {
+ mStore.Clear();
+ mCurrentSize = 0;
+ }
+
+ bool eraseByKey(const Key &key)
+ {
+ // Check for existing key.
+ auto existing = mStore.Peek(key);
+ if (existing != mStore.end())
+ {
+ mCurrentSize -= existing->second.size;
+ mStore.Erase(existing);
+ return true;
+ }
+
+ return false;
+ }
+
+ size_t entryCount() const { return mStore.size(); }
+
+ size_t size() const { return mCurrentSize; }
+
+ // Also discards the cache contents.
+ void resize(size_t maximumTotalSize)
+ {
+ clear();
+ mMaximumTotalSize = maximumTotalSize;
+ }
+
+ // Reduce current memory usage.
+ size_t shrinkToSize(size_t limit)
+ {
+ size_t initialSize = mCurrentSize;
+
+ while (mCurrentSize > limit)
+ {
+ ASSERT(!mStore.empty());
+ auto iter = mStore.rbegin();
+ mCurrentSize -= iter->second.size;
+ mStore.Erase(iter);
+ }
+
+ return (initialSize - mCurrentSize);
+ }
+
+ size_t maxSize() const { return mMaximumTotalSize; }
+
+ private:
+ struct ValueAndSize
+ {
+ ValueAndSize() : value(), size(0) {}
+ ValueAndSize(Value &&value, size_t size) : value(std::move(value)), size(size) {}
+ ValueAndSize(ValueAndSize &&other) : ValueAndSize() { *this = std::move(other); }
+ ValueAndSize &operator=(ValueAndSize &&other)
+ {
+ std::swap(value, other.value);
+ std::swap(size, other.size);
+ return *this;
+ }
+
+ Value value;
+ size_t size;
+ };
+
+ using SizedMRUCacheStore = base::HashingMRUCache<Key, ValueAndSize>;
+
+ size_t mMaximumTotalSize;
+ size_t mCurrentSize;
+ SizedMRUCacheStore mStore;
+};
+
+// Helper function used in a few places.
+template <typename T>
+void TrimCache(size_t maxStates, size_t gcLimit, const char *name, T *cache)
+{
+ const size_t kGarbageCollectionLimit = maxStates / 2 + gcLimit;
+
+ if (cache->size() >= kGarbageCollectionLimit)
+ {
+ WARN() << "Overflowed the " << name << " cache limit of " << (maxStates / 2)
+ << " elements, removing the least recently used to make room.";
+ cache->ShrinkToSize(maxStates / 2);
+ }
+}
+
+// Computes a hash of struct "key". Any structs passed to this function must be multiples of
+// 4 bytes, since the PMurhHas32 method can only operate increments of 4-byte words.
+template <typename T>
+std::size_t ComputeGenericHash(const T &key)
+{
+ static const unsigned int seed = 0xABCDEF98;
+
+ // We can't support "odd" alignments.
+ static_assert(sizeof(key) % 4 == 0, "ComputeGenericHash requires aligned types");
+ return PMurHash32(seed, &key, sizeof(T));
+}
+
+} // namespace angle
+#endif // LIBANGLE_SIZED_MRU_CACHE_H_
diff --git a/src/3rdparty/angle/src/libANGLE/State.cpp b/src/3rdparty/angle/src/libANGLE/State.cpp
index a1437b838b..f87e963710 100644
--- a/src/3rdparty/angle/src/libANGLE/State.cpp
+++ b/src/3rdparty/angle/src/libANGLE/State.cpp
@@ -8,15 +8,32 @@
#include "libANGLE/State.h"
-#include "common/BitSetIterator.h"
-#include "libANGLE/Context.h"
+#include <limits>
+#include <string.h>
+
+#include "common/bitset_utils.h"
+#include "common/mathutil.h"
+#include "common/matrix_utils.h"
#include "libANGLE/Caps.h"
+#include "libANGLE/Context.h"
#include "libANGLE/Debug.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/Query.h"
#include "libANGLE/VertexArray.h"
#include "libANGLE/formatutils.h"
+#include "libANGLE/queryconversions.h"
+#include "libANGLE/renderer/ContextImpl.h"
+
+namespace
+{
+
+GLenum ActiveQueryType(const GLenum type)
+{
+ return (type == GL_ANY_SAMPLES_PASSED_CONSERVATIVE) ? GL_ANY_SAMPLES_PASSED : type;
+}
+
+} // anonymous namepace
namespace gl
{
@@ -30,11 +47,15 @@ State::State()
mSampleCoverage(false),
mSampleCoverageValue(0),
mSampleCoverageInvert(false),
+ mSampleMask(false),
+ mMaxSampleMaskWords(0),
mStencilRef(0),
mStencilBackRef(0),
mLineWidth(0),
mGenerateMipmapHint(GL_NONE),
mFragmentShaderDerivativeHint(GL_NONE),
+ mBindGeneratesResource(true),
+ mClientArraysEnabled(true),
mNearZ(0),
mFarZ(0),
mReadFramebuffer(nullptr),
@@ -42,49 +63,31 @@ State::State()
mProgram(nullptr),
mVertexArray(nullptr),
mActiveSampler(0),
- mPrimitiveRestart(false)
-{
- // Initialize dirty bit masks
- // TODO(jmadill): additional ES3 state
- mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_ALIGNMENT);
- mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_ROW_LENGTH);
- mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_IMAGE_HEIGHT);
- mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_SKIP_IMAGES);
- mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_SKIP_ROWS);
- mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_SKIP_PIXELS);
-
- mPackStateBitMask.set(DIRTY_BIT_PACK_ALIGNMENT);
- mPackStateBitMask.set(DIRTY_BIT_PACK_REVERSE_ROW_ORDER);
- mPackStateBitMask.set(DIRTY_BIT_PACK_ROW_LENGTH);
- mPackStateBitMask.set(DIRTY_BIT_PACK_SKIP_ROWS);
- mPackStateBitMask.set(DIRTY_BIT_PACK_SKIP_PIXELS);
-
- mClearStateBitMask.set(DIRTY_BIT_RASTERIZER_DISCARD_ENABLED);
- mClearStateBitMask.set(DIRTY_BIT_SCISSOR_TEST_ENABLED);
- mClearStateBitMask.set(DIRTY_BIT_SCISSOR);
- mClearStateBitMask.set(DIRTY_BIT_VIEWPORT);
- mClearStateBitMask.set(DIRTY_BIT_CLEAR_COLOR);
- mClearStateBitMask.set(DIRTY_BIT_CLEAR_DEPTH);
- mClearStateBitMask.set(DIRTY_BIT_CLEAR_STENCIL);
- mClearStateBitMask.set(DIRTY_BIT_COLOR_MASK);
- mClearStateBitMask.set(DIRTY_BIT_DEPTH_MASK);
- mClearStateBitMask.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
- mClearStateBitMask.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK);
-
- mBlitStateBitMask.set(DIRTY_BIT_SCISSOR_TEST_ENABLED);
- mBlitStateBitMask.set(DIRTY_BIT_SCISSOR);
+ mPrimitiveRestart(false),
+ mMultiSampling(false),
+ mSampleAlphaToOne(false),
+ mFramebufferSRGB(true),
+ mRobustResourceInit(false),
+ mProgramBinaryCacheEnabled(false)
+{
}
State::~State()
{
- reset();
}
-void State::initialize(const Caps &caps,
- const Extensions &extensions,
- GLuint clientVersion,
- bool debug)
+void State::initialize(const Context *context,
+ bool debug,
+ bool bindGeneratesResource,
+ bool clientArraysEnabled,
+ bool robustResourceInit,
+ bool programBinaryCacheEnabled)
{
+ const Caps &caps = context->getCaps();
+ const Extensions &extensions = context->getExtensions();
+ const Extensions &nativeExtensions = context->getImplementation()->getNativeExtensions();
+ const Version &clientVersion = context->getClientVersion();
+
mMaxDrawBuffers = caps.maxDrawBuffers;
mMaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
@@ -93,62 +96,34 @@ void State::initialize(const Caps &caps,
mDepthClearValue = 1.0f;
mStencilClearValue = 0;
- mRasterizer.rasterizerDiscard = false;
- mRasterizer.cullFace = false;
- mRasterizer.cullMode = GL_BACK;
- mRasterizer.frontFace = GL_CCW;
- mRasterizer.polygonOffsetFill = false;
- mRasterizer.polygonOffsetFactor = 0.0f;
- mRasterizer.polygonOffsetUnits = 0.0f;
- mRasterizer.pointDrawMode = false;
- mRasterizer.multiSample = false;
mScissorTest = false;
mScissor.x = 0;
mScissor.y = 0;
mScissor.width = 0;
mScissor.height = 0;
- mBlend.blend = false;
- mBlend.sourceBlendRGB = GL_ONE;
- mBlend.sourceBlendAlpha = GL_ONE;
- mBlend.destBlendRGB = GL_ZERO;
- mBlend.destBlendAlpha = GL_ZERO;
- mBlend.blendEquationRGB = GL_FUNC_ADD;
- mBlend.blendEquationAlpha = GL_FUNC_ADD;
- mBlend.sampleAlphaToCoverage = false;
- mBlend.dither = true;
-
mBlendColor.red = 0;
mBlendColor.green = 0;
mBlendColor.blue = 0;
mBlendColor.alpha = 0;
- mDepthStencil.depthTest = false;
- mDepthStencil.depthFunc = GL_LESS;
- mDepthStencil.depthMask = true;
- mDepthStencil.stencilTest = false;
- mDepthStencil.stencilFunc = GL_ALWAYS;
- mDepthStencil.stencilMask = static_cast<GLuint>(-1);
- mDepthStencil.stencilWritemask = static_cast<GLuint>(-1);
- mDepthStencil.stencilBackFunc = GL_ALWAYS;
- mDepthStencil.stencilBackMask = static_cast<GLuint>(-1);
- mDepthStencil.stencilBackWritemask = static_cast<GLuint>(-1);
- mDepthStencil.stencilFail = GL_KEEP;
- mDepthStencil.stencilPassDepthFail = GL_KEEP;
- mDepthStencil.stencilPassDepthPass = GL_KEEP;
- mDepthStencil.stencilBackFail = GL_KEEP;
- mDepthStencil.stencilBackPassDepthFail = GL_KEEP;
- mDepthStencil.stencilBackPassDepthPass = GL_KEEP;
-
mStencilRef = 0;
mStencilBackRef = 0;
mSampleCoverage = false;
mSampleCoverageValue = 1.0f;
mSampleCoverageInvert = false;
+
+ mMaxSampleMaskWords = caps.maxSampleMaskWords;
+ mSampleMask = false;
+ mSampleMaskValues.fill(~GLbitfield(0));
+
mGenerateMipmapHint = GL_DONT_CARE;
mFragmentShaderDerivativeHint = GL_DONT_CARE;
+ mBindGeneratesResource = bindGeneratesResource;
+ mClientArraysEnabled = clientArraysEnabled;
+
mLineWidth = 1.0f;
mViewport.x = 0;
@@ -167,23 +142,48 @@ void State::initialize(const Caps &caps,
mVertexAttribCurrentValues.resize(caps.maxVertexAttributes);
- mUniformBuffers.resize(caps.maxCombinedUniformBlocks);
+ mUniformBuffers.resize(caps.maxUniformBufferBindings);
mSamplerTextures[GL_TEXTURE_2D].resize(caps.maxCombinedTextureImageUnits);
mSamplerTextures[GL_TEXTURE_CUBE_MAP].resize(caps.maxCombinedTextureImageUnits);
- if (clientVersion >= 3)
+ if (clientVersion >= Version(3, 0))
{
// TODO: These could also be enabled via extension
mSamplerTextures[GL_TEXTURE_2D_ARRAY].resize(caps.maxCombinedTextureImageUnits);
mSamplerTextures[GL_TEXTURE_3D].resize(caps.maxCombinedTextureImageUnits);
}
+ if (clientVersion >= Version(3, 1))
+ {
+ mSamplerTextures[GL_TEXTURE_2D_MULTISAMPLE].resize(caps.maxCombinedTextureImageUnits);
+
+ mAtomicCounterBuffers.resize(caps.maxAtomicCounterBufferBindings);
+ mShaderStorageBuffers.resize(caps.maxShaderStorageBufferBindings);
+ mImageUnits.resize(caps.maxImageUnits);
+ }
+ if (nativeExtensions.textureRectangle)
+ {
+ mSamplerTextures[GL_TEXTURE_RECTANGLE_ANGLE].resize(caps.maxCombinedTextureImageUnits);
+ }
+ if (nativeExtensions.eglImageExternal || nativeExtensions.eglStreamConsumerExternal)
+ {
+ mSamplerTextures[GL_TEXTURE_EXTERNAL_OES].resize(caps.maxCombinedTextureImageUnits);
+ }
+ mCompleteTextureCache.resize(caps.maxCombinedTextureImageUnits, nullptr);
+ mCompleteTextureBindings.reserve(caps.maxCombinedTextureImageUnits);
+ mCachedTexturesInitState = InitState::MayNeedInit;
+ for (uint32_t textureIndex = 0; textureIndex < caps.maxCombinedTextureImageUnits;
+ ++textureIndex)
+ {
+ mCompleteTextureBindings.emplace_back(OnAttachmentDirtyBinding(this, textureIndex));
+ }
mSamplers.resize(caps.maxCombinedTextureImageUnits);
- mActiveQueries[GL_ANY_SAMPLES_PASSED].set(nullptr);
- mActiveQueries[GL_ANY_SAMPLES_PASSED_CONSERVATIVE].set(nullptr);
- mActiveQueries[GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN].set(nullptr);
- mActiveQueries[GL_TIME_ELAPSED_EXT].set(nullptr);
+ mActiveQueries[GL_ANY_SAMPLES_PASSED].set(context, nullptr);
+ mActiveQueries[GL_ANY_SAMPLES_PASSED_CONSERVATIVE].set(context, nullptr);
+ mActiveQueries[GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN].set(context, nullptr);
+ mActiveQueries[GL_TIME_ELAPSED_EXT].set(context, nullptr);
+ mActiveQueries[GL_COMMANDS_COMPLETED_CHROMIUM].set(context, nullptr);
mProgram = nullptr;
@@ -194,52 +194,89 @@ void State::initialize(const Caps &caps,
mDebug.setOutputEnabled(debug);
mDebug.setMaxLoggedMessages(extensions.maxDebugLoggedMessages);
+
+ mMultiSampling = true;
+ mSampleAlphaToOne = false;
+
+ mCoverageModulation = GL_NONE;
+
+ angle::Matrix<GLfloat>::setToIdentity(mPathMatrixProj);
+ angle::Matrix<GLfloat>::setToIdentity(mPathMatrixMV);
+ mPathStencilFunc = GL_ALWAYS;
+ mPathStencilRef = 0;
+ mPathStencilMask = std::numeric_limits<GLuint>::max();
+
+ mRobustResourceInit = robustResourceInit;
+ mProgramBinaryCacheEnabled = programBinaryCacheEnabled;
}
-void State::reset()
+void State::reset(const Context *context)
{
- for (TextureBindingMap::iterator bindingVec = mSamplerTextures.begin(); bindingVec != mSamplerTextures.end(); bindingVec++)
+ for (auto &bindingVec : mSamplerTextures)
{
- TextureBindingVector &textureVector = bindingVec->second;
+ TextureBindingVector &textureVector = bindingVec.second;
for (size_t textureIdx = 0; textureIdx < textureVector.size(); textureIdx++)
{
- textureVector[textureIdx].set(NULL);
+ textureVector[textureIdx].set(context, nullptr);
}
}
for (size_t samplerIdx = 0; samplerIdx < mSamplers.size(); samplerIdx++)
{
- mSamplers[samplerIdx].set(NULL);
+ mSamplers[samplerIdx].set(context, nullptr);
}
- mArrayBuffer.set(NULL);
- mRenderbuffer.set(NULL);
+ for (auto &imageUnit : mImageUnits)
+ {
+ imageUnit.texture.set(context, nullptr);
+ imageUnit.level = 0;
+ imageUnit.layered = false;
+ imageUnit.layer = 0;
+ imageUnit.access = GL_READ_ONLY;
+ imageUnit.format = GL_R32UI;
+ }
+
+ mRenderbuffer.set(context, nullptr);
+
+ for (auto type : angle::AllEnums<BufferBinding>())
+ {
+ mBoundBuffers[type].set(context, nullptr);
+ }
if (mProgram)
{
- mProgram->release();
+ mProgram->release(context);
}
- mProgram = NULL;
+ mProgram = nullptr;
+
+ mProgramPipeline.set(context, nullptr);
- mTransformFeedback.set(NULL);
+ mTransformFeedback.set(context, nullptr);
for (State::ActiveQueryMap::iterator i = mActiveQueries.begin(); i != mActiveQueries.end(); i++)
{
- i->second.set(NULL);
+ i->second.set(context, nullptr);
}
- mGenericUniformBuffer.set(NULL);
- for (BufferVector::iterator bufItr = mUniformBuffers.begin(); bufItr != mUniformBuffers.end(); ++bufItr)
+ for (auto &buf : mUniformBuffers)
{
- bufItr->set(NULL);
+ buf.set(context, nullptr);
}
- mCopyReadBuffer.set(NULL);
- mCopyWriteBuffer.set(NULL);
+ for (auto &buf : mAtomicCounterBuffers)
+ {
+ buf.set(context, nullptr);
+ }
- mPack.pixelBuffer.set(NULL);
- mUnpack.pixelBuffer.set(NULL);
+ for (auto &buf : mShaderStorageBuffers)
+ {
+ buf.set(context, nullptr);
+ }
- mProgram = NULL;
+ angle::Matrix<GLfloat>::setToIdentity(mPathMatrixProj);
+ angle::Matrix<GLfloat>::setToIdentity(mPathMatrixMV);
+ mPathStencilFunc = GL_ALWAYS;
+ mPathStencilRef = 0;
+ mPathStencilMask = std::numeric_limits<GLuint>::max();
// TODO(jmadill): Is this necessary?
setAllDirtyBits();
@@ -318,7 +355,7 @@ void State::setCullFace(bool enabled)
mDirtyBits.set(DIRTY_BIT_CULL_FACE_ENABLED);
}
-void State::setCullMode(GLenum mode)
+void State::setCullMode(CullFaceMode mode)
{
mRasterizer.cullMode = mode;
mDirtyBits.set(DIRTY_BIT_CULL_FACE);
@@ -528,6 +565,58 @@ bool State::getSampleCoverageInvert() const
return mSampleCoverageInvert;
}
+bool State::isSampleMaskEnabled() const
+{
+ return mSampleMask;
+}
+
+void State::setSampleMaskEnabled(bool enabled)
+{
+ mSampleMask = enabled;
+ mDirtyBits.set(DIRTY_BIT_SAMPLE_MASK_ENABLED);
+}
+
+void State::setSampleMaskParams(GLuint maskNumber, GLbitfield mask)
+{
+ ASSERT(maskNumber < mMaxSampleMaskWords);
+ mSampleMaskValues[maskNumber] = mask;
+ // TODO(jmadill): Use a child dirty bit if we ever use more than two words.
+ mDirtyBits.set(DIRTY_BIT_SAMPLE_MASK);
+}
+
+GLbitfield State::getSampleMaskWord(GLuint maskNumber) const
+{
+ ASSERT(maskNumber < mMaxSampleMaskWords);
+ return mSampleMaskValues[maskNumber];
+}
+
+GLuint State::getMaxSampleMaskWords() const
+{
+ return mMaxSampleMaskWords;
+}
+
+void State::setSampleAlphaToOne(bool enabled)
+{
+ mSampleAlphaToOne = enabled;
+ mDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_ONE);
+}
+
+bool State::isSampleAlphaToOneEnabled() const
+{
+ return mSampleAlphaToOne;
+}
+
+void State::setMultisampling(bool enabled)
+{
+ mMultiSampling = enabled;
+ mDirtyBits.set(DIRTY_BIT_MULTISAMPLING);
+}
+
+bool State::isMultisamplingEnabled() const
+{
+ return mMultiSampling;
+}
+
bool State::isScissorTestEnabled() const
{
return mScissorTest;
@@ -579,6 +668,8 @@ void State::setEnableFeature(GLenum feature, bool enabled)
{
switch (feature)
{
+ case GL_MULTISAMPLE_EXT: setMultisampling(enabled); break;
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT: setSampleAlphaToOne(enabled); break;
case GL_CULL_FACE: setCullFace(enabled); break;
case GL_POLYGON_OFFSET_FILL: setPolygonOffsetFill(enabled); break;
case GL_SAMPLE_ALPHA_TO_COVERAGE: setSampleAlphaToCoverage(enabled); break;
@@ -590,20 +681,28 @@ void State::setEnableFeature(GLenum feature, bool enabled)
case GL_DITHER: setDither(enabled); break;
case GL_PRIMITIVE_RESTART_FIXED_INDEX: setPrimitiveRestart(enabled); break;
case GL_RASTERIZER_DISCARD: setRasterizerDiscard(enabled); break;
+ case GL_SAMPLE_MASK:
+ setSampleMaskEnabled(enabled);
+ break;
case GL_DEBUG_OUTPUT_SYNCHRONOUS:
mDebug.setOutputSynchronous(enabled);
break;
case GL_DEBUG_OUTPUT:
mDebug.setOutputEnabled(enabled);
break;
+ case GL_FRAMEBUFFER_SRGB_EXT:
+ setFramebufferSRGB(enabled);
+ break;
default: UNREACHABLE();
}
}
-bool State::getEnableFeature(GLenum feature)
+bool State::getEnableFeature(GLenum feature) const
{
switch (feature)
{
+ case GL_MULTISAMPLE_EXT: return isMultisamplingEnabled();
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT: return isSampleAlphaToOneEnabled();
case GL_CULL_FACE: return isCullFaceEnabled();
case GL_POLYGON_OFFSET_FILL: return isPolygonOffsetFillEnabled();
case GL_SAMPLE_ALPHA_TO_COVERAGE: return isSampleAlphaToCoverageEnabled();
@@ -615,11 +714,26 @@ bool State::getEnableFeature(GLenum feature)
case GL_DITHER: return isDitherEnabled();
case GL_PRIMITIVE_RESTART_FIXED_INDEX: return isPrimitiveRestartEnabled();
case GL_RASTERIZER_DISCARD: return isRasterizerDiscardEnabled();
+ case GL_SAMPLE_MASK:
+ return isSampleMaskEnabled();
case GL_DEBUG_OUTPUT_SYNCHRONOUS:
return mDebug.isOutputSynchronous();
case GL_DEBUG_OUTPUT:
return mDebug.isOutputEnabled();
- default: UNREACHABLE(); return false;
+ case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
+ return isBindGeneratesResourceEnabled();
+ case GL_CLIENT_ARRAYS_ANGLE:
+ return areClientArraysEnabled();
+ case GL_FRAMEBUFFER_SRGB_EXT:
+ return getFramebufferSRGB();
+ case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ return mRobustResourceInit;
+ case GL_PROGRAM_CACHE_ENABLED_ANGLE:
+ return mProgramBinaryCacheEnabled;
+
+ default:
+ UNREACHABLE();
+ return false;
}
}
@@ -649,6 +763,16 @@ void State::setFragmentShaderDerivativeHint(GLenum hint)
// Ignore for now. It is valid for implementations to ignore hint.
}
+bool State::isBindGeneratesResourceEnabled() const
+{
+ return mBindGeneratesResource;
+}
+
+bool State::areClientArraysEnabled() const
+{
+ return mClientArraysEnabled;
+}
+
void State::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
{
mViewport.x = x;
@@ -673,9 +797,11 @@ unsigned int State::getActiveSampler() const
return static_cast<unsigned int>(mActiveSampler);
}
-void State::setSamplerTexture(GLenum type, Texture *texture)
+void State::setSamplerTexture(const Context *context, GLenum type, Texture *texture)
{
- mSamplerTextures[type][mActiveSampler].set(texture);
+ mSamplerTextures[type][mActiveSampler].set(context, texture);
+ mDirtyBits.set(DIRTY_BIT_TEXTURE_BINDINGS);
+ mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_TEXTURES);
}
Texture *State::getTargetTexture(GLenum target) const
@@ -699,7 +825,7 @@ GLuint State::getSamplerTextureId(unsigned int sampler, GLenum type) const
return it->second[sampler].id();
}
-void State::detachTexture(const TextureMap &zeroTextures, GLuint texture)
+void State::detachTexture(const Context *context, const TextureMap &zeroTextures, GLuint texture)
{
// Textures have a detach method on State rather than a simple
// removeBinding, because the zero/null texture objects are managed
@@ -710,40 +836,54 @@ void State::detachTexture(const TextureMap &zeroTextures, GLuint texture)
// If a texture object is deleted, it is as if all texture units which are bound to that texture object are
// rebound to texture object zero
- for (TextureBindingMap::iterator bindingVec = mSamplerTextures.begin(); bindingVec != mSamplerTextures.end(); bindingVec++)
+ for (auto &bindingVec : mSamplerTextures)
{
- GLenum textureType = bindingVec->first;
- TextureBindingVector &textureVector = bindingVec->second;
- for (size_t textureIdx = 0; textureIdx < textureVector.size(); textureIdx++)
+ GLenum textureType = bindingVec.first;
+ TextureBindingVector &textureVector = bindingVec.second;
+ for (BindingPointer<Texture> &binding : textureVector)
{
- BindingPointer<Texture> &binding = textureVector[textureIdx];
if (binding.id() == texture)
{
auto it = zeroTextures.find(textureType);
ASSERT(it != zeroTextures.end());
// Zero textures are the "default" textures instead of NULL
- binding.set(it->second.get());
+ binding.set(context, it->second.get());
+ mDirtyBits.set(DIRTY_BIT_TEXTURE_BINDINGS);
}
}
}
+ for (auto &bindingImageUnit : mImageUnits)
+ {
+ if (bindingImageUnit.texture.id() == texture)
+ {
+ bindingImageUnit.texture.set(context, nullptr);
+ bindingImageUnit.level = 0;
+ bindingImageUnit.layered = false;
+ bindingImageUnit.layer = 0;
+ bindingImageUnit.access = GL_READ_ONLY;
+ bindingImageUnit.format = GL_R32UI;
+ break;
+ }
+ }
+
// [OpenGL ES 2.0.24] section 4.4 page 112:
// If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
// as if Texture2DAttachment had been called, with a texture of 0, for each attachment point to which this
// image was attached in the currently bound framebuffer.
- if (mReadFramebuffer)
+ if (mReadFramebuffer && mReadFramebuffer->detachTexture(context, texture))
{
- mReadFramebuffer->detachTexture(texture);
+ mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
}
- if (mDrawFramebuffer)
+ if (mDrawFramebuffer && mDrawFramebuffer->detachTexture(context, texture))
{
- mDrawFramebuffer->detachTexture(texture);
+ mDirtyObjects.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER);
}
}
-void State::initializeZeroTextures(const TextureMap &zeroTextures)
+void State::initializeZeroTextures(const Context *context, const TextureMap &zeroTextures)
{
for (const auto &zeroTexture : zeroTextures)
{
@@ -751,14 +891,16 @@ void State::initializeZeroTextures(const TextureMap &zeroTextures)
for (size_t textureUnit = 0; textureUnit < samplerTextureArray.size(); ++textureUnit)
{
- samplerTextureArray[textureUnit].set(zeroTexture.second.get());
+ samplerTextureArray[textureUnit].set(context, zeroTexture.second.get());
}
}
}
-void State::setSamplerBinding(GLuint textureUnit, Sampler *sampler)
+void State::setSamplerBinding(const Context *context, GLuint textureUnit, Sampler *sampler)
{
- mSamplers[textureUnit].set(sampler);
+ mSamplers[textureUnit].set(context, sampler);
+ mDirtyBits.set(DIRTY_BIT_SAMPLER_BINDINGS);
+ mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_TEXTURES);
}
GLuint State::getSamplerId(GLuint textureUnit) const
@@ -772,25 +914,26 @@ Sampler *State::getSampler(GLuint textureUnit) const
return mSamplers[textureUnit].get();
}
-void State::detachSampler(GLuint sampler)
+void State::detachSampler(const Context *context, GLuint sampler)
{
// [OpenGL ES 3.0.2] section 3.8.2 pages 123-124:
// If a sampler object that is currently bound to one or more texture units is
// deleted, it is as though BindSampler is called once for each texture unit to
// which the sampler is bound, with unit set to the texture unit and sampler set to zero.
- for (size_t textureUnit = 0; textureUnit < mSamplers.size(); textureUnit++)
+ for (BindingPointer<Sampler> &samplerBinding : mSamplers)
{
- BindingPointer<Sampler> &samplerBinding = mSamplers[textureUnit];
if (samplerBinding.id() == sampler)
{
- samplerBinding.set(NULL);
+ samplerBinding.set(context, nullptr);
+ mDirtyBits.set(DIRTY_BIT_SAMPLER_BINDINGS);
}
}
}
-void State::setRenderbufferBinding(Renderbuffer *renderbuffer)
+void State::setRenderbufferBinding(const Context *context, Renderbuffer *renderbuffer)
{
- mRenderbuffer.set(renderbuffer);
+ mRenderbuffer.set(context, renderbuffer);
+ mDirtyBits.set(DIRTY_BIT_RENDERBUFFER_BINDING);
}
GLuint State::getRenderbufferId() const
@@ -798,12 +941,12 @@ GLuint State::getRenderbufferId() const
return mRenderbuffer.id();
}
-Renderbuffer *State::getCurrentRenderbuffer()
+Renderbuffer *State::getCurrentRenderbuffer() const
{
return mRenderbuffer.get();
}
-void State::detachRenderbuffer(GLuint renderbuffer)
+void State::detachRenderbuffer(const Context *context, GLuint renderbuffer)
{
// [OpenGL ES 2.0.24] section 4.4 page 109:
// If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
@@ -811,7 +954,7 @@ void State::detachRenderbuffer(GLuint renderbuffer)
if (mRenderbuffer.id() == renderbuffer)
{
- mRenderbuffer.set(NULL);
+ setRenderbufferBinding(context, nullptr);
}
// [OpenGL ES 2.0.24] section 4.4 page 111:
@@ -822,14 +965,17 @@ void State::detachRenderbuffer(GLuint renderbuffer)
Framebuffer *readFramebuffer = mReadFramebuffer;
Framebuffer *drawFramebuffer = mDrawFramebuffer;
- if (readFramebuffer)
+ if (readFramebuffer && readFramebuffer->detachRenderbuffer(context, renderbuffer))
{
- readFramebuffer->detachRenderbuffer(renderbuffer);
+ mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
}
if (drawFramebuffer && drawFramebuffer != readFramebuffer)
{
- drawFramebuffer->detachRenderbuffer(renderbuffer);
+ if (drawFramebuffer->detachRenderbuffer(context, renderbuffer))
+ {
+ mDirtyObjects.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER);
+ }
}
}
@@ -873,26 +1019,16 @@ Framebuffer *State::getTargetFramebuffer(GLenum target) const
return mDrawFramebuffer;
default:
UNREACHABLE();
- return NULL;
+ return nullptr;
}
}
-Framebuffer *State::getReadFramebuffer()
+Framebuffer *State::getReadFramebuffer() const
{
return mReadFramebuffer;
}
-Framebuffer *State::getDrawFramebuffer()
-{
- return mDrawFramebuffer;
-}
-
-const Framebuffer *State::getReadFramebuffer() const
-{
- return mReadFramebuffer;
-}
-
-const Framebuffer *State::getDrawFramebuffer() const
+Framebuffer *State::getDrawFramebuffer() const
{
return mDrawFramebuffer;
}
@@ -934,13 +1070,13 @@ void State::setVertexArrayBinding(VertexArray *vertexArray)
GLuint State::getVertexArrayId() const
{
- ASSERT(mVertexArray != NULL);
+ ASSERT(mVertexArray != nullptr);
return mVertexArray->id();
}
VertexArray *State::getVertexArray() const
{
- ASSERT(mVertexArray != NULL);
+ ASSERT(mVertexArray != nullptr);
return mVertexArray;
}
@@ -948,7 +1084,7 @@ bool State::removeVertexArrayBinding(GLuint vertexArray)
{
if (mVertexArray->id() == vertexArray)
{
- mVertexArray = NULL;
+ mVertexArray = nullptr;
mDirtyBits.set(DIRTY_BIT_VERTEX_ARRAY_BINDING);
mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
return true;
@@ -957,13 +1093,47 @@ bool State::removeVertexArrayBinding(GLuint vertexArray)
return false;
}
-void State::setProgram(Program *newProgram)
+void State::bindVertexBuffer(const Context *context,
+ GLuint bindingIndex,
+ Buffer *boundBuffer,
+ GLintptr offset,
+ GLsizei stride)
+{
+ getVertexArray()->bindVertexBuffer(context, bindingIndex, boundBuffer, offset, stride);
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+}
+
+void State::setVertexAttribBinding(const Context *context, GLuint attribIndex, GLuint bindingIndex)
+{
+ getVertexArray()->setVertexAttribBinding(context, attribIndex, bindingIndex);
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+}
+
+void State::setVertexAttribFormat(GLuint attribIndex,
+ GLint size,
+ GLenum type,
+ bool normalized,
+ bool pureInteger,
+ GLuint relativeOffset)
+{
+ getVertexArray()->setVertexAttribFormat(attribIndex, size, type, normalized, pureInteger,
+ relativeOffset);
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+}
+
+void State::setVertexBindingDivisor(GLuint bindingIndex, GLuint divisor)
+{
+ getVertexArray()->setVertexBindingDivisor(bindingIndex, divisor);
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+}
+
+void State::setProgram(const Context *context, Program *newProgram)
{
if (mProgram != newProgram)
{
if (mProgram)
{
- mProgram->release();
+ mProgram->release(context);
}
mProgram = newProgram;
@@ -971,7 +1141,10 @@ void State::setProgram(Program *newProgram)
if (mProgram)
{
newProgram->addRef();
+ mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_TEXTURES);
}
+ mDirtyBits.set(DIRTY_BIT_PROGRAM_EXECUTABLE);
+ mDirtyBits.set(DIRTY_BIT_PROGRAM_BINDING);
}
}
@@ -980,9 +1153,10 @@ Program *State::getProgram() const
return mProgram;
}
-void State::setTransformFeedbackBinding(TransformFeedback *transformFeedback)
+void State::setTransformFeedbackBinding(const Context *context,
+ TransformFeedback *transformFeedback)
{
- mTransformFeedback.set(transformFeedback);
+ mTransformFeedback.set(context, transformFeedback);
}
TransformFeedback *State::getCurrentTransformFeedback() const
@@ -992,23 +1166,37 @@ TransformFeedback *State::getCurrentTransformFeedback() const
bool State::isTransformFeedbackActiveUnpaused() const
{
- gl::TransformFeedback *curTransformFeedback = getCurrentTransformFeedback();
+ TransformFeedback *curTransformFeedback = getCurrentTransformFeedback();
return curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused();
}
-void State::detachTransformFeedback(GLuint transformFeedback)
+bool State::removeTransformFeedbackBinding(const Context *context, GLuint transformFeedback)
{
if (mTransformFeedback.id() == transformFeedback)
{
- mTransformFeedback.set(NULL);
+ mTransformFeedback.set(context, nullptr);
+ return true;
}
+
+ return false;
+}
+
+void State::setProgramPipelineBinding(const Context *context, ProgramPipeline *pipeline)
+{
+ mProgramPipeline.set(context, pipeline);
+}
+
+void State::detachProgramPipeline(const Context *context, GLuint pipeline)
+{
+ mProgramPipeline.set(context, nullptr);
}
-bool State::isQueryActive() const
+bool State::isQueryActive(const GLenum type) const
{
for (auto &iter : mActiveQueries)
{
- if (iter.second.get() != NULL)
+ const Query *query = iter.second.get();
+ if (query != nullptr && ActiveQueryType(query->getType()) == ActiveQueryType(type))
{
return true;
}
@@ -1030,9 +1218,9 @@ bool State::isQueryActive(Query *query) const
return false;
}
-void State::setActiveQuery(GLenum target, Query *query)
+void State::setActiveQuery(const Context *context, GLenum target, Query *query)
{
- mActiveQueries[target].set(query);
+ mActiveQueries[target].set(context, query);
}
GLuint State::getActiveQueryId(GLenum target) const
@@ -1051,24 +1239,64 @@ Query *State::getActiveQuery(GLenum target) const
return it->second.get();
}
-void State::setArrayBufferBinding(Buffer *buffer)
+void State::setBufferBinding(const Context *context, BufferBinding target, Buffer *buffer)
{
- mArrayBuffer.set(buffer);
-}
-
-GLuint State::getArrayBufferId() const
-{
- return mArrayBuffer.id();
+ switch (target)
+ {
+ case BufferBinding::PixelPack:
+ mBoundBuffers[target].set(context, buffer);
+ mDirtyBits.set(DIRTY_BIT_PACK_BUFFER_BINDING);
+ break;
+ case BufferBinding::PixelUnpack:
+ mBoundBuffers[target].set(context, buffer);
+ mDirtyBits.set(DIRTY_BIT_UNPACK_BUFFER_BINDING);
+ break;
+ case BufferBinding::DrawIndirect:
+ mBoundBuffers[target].set(context, buffer);
+ mDirtyBits.set(DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING);
+ break;
+ case BufferBinding::TransformFeedback:
+ if (mTransformFeedback.get() != nullptr)
+ {
+ mTransformFeedback->bindGenericBuffer(context, buffer);
+ }
+ break;
+ case BufferBinding::ElementArray:
+ getVertexArray()->setElementArrayBuffer(context, buffer);
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+ break;
+ default:
+ mBoundBuffers[target].set(context, buffer);
+ break;
+ }
}
-
-void State::setGenericUniformBufferBinding(Buffer *buffer)
+void State::setIndexedBufferBinding(const Context *context,
+ BufferBinding target,
+ GLuint index,
+ Buffer *buffer,
+ GLintptr offset,
+ GLsizeiptr size)
{
- mGenericUniformBuffer.set(buffer);
-}
+ setBufferBinding(context, target, buffer);
-void State::setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size)
-{
- mUniformBuffers[index].set(buffer, offset, size);
+ switch (target)
+ {
+ case BufferBinding::TransformFeedback:
+ mTransformFeedback->bindIndexedBuffer(context, index, buffer, offset, size);
+ break;
+ case BufferBinding::Uniform:
+ mUniformBuffers[index].set(context, buffer, offset, size);
+ break;
+ case BufferBinding::AtomicCounter:
+ mAtomicCounterBuffers[index].set(context, buffer, offset, size);
+ break;
+ case BufferBinding::ShaderStorage:
+ mShaderStorageBuffers[index].set(context, buffer, offset, size);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
}
const OffsetBindingPointer<Buffer> &State::getIndexedUniformBuffer(size_t index) const
@@ -1077,62 +1305,48 @@ const OffsetBindingPointer<Buffer> &State::getIndexedUniformBuffer(size_t index)
return mUniformBuffers[index];
}
-void State::setCopyReadBufferBinding(Buffer *buffer)
+const OffsetBindingPointer<Buffer> &State::getIndexedAtomicCounterBuffer(size_t index) const
{
- mCopyReadBuffer.set(buffer);
+ ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size());
+ return mAtomicCounterBuffers[index];
}
-void State::setCopyWriteBufferBinding(Buffer *buffer)
+const OffsetBindingPointer<Buffer> &State::getIndexedShaderStorageBuffer(size_t index) const
{
- mCopyWriteBuffer.set(buffer);
+ ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size());
+ return mShaderStorageBuffers[index];
}
-void State::setPixelPackBufferBinding(Buffer *buffer)
-{
- mPack.pixelBuffer.set(buffer);
-}
-
-void State::setPixelUnpackBufferBinding(Buffer *buffer)
-{
- mUnpack.pixelBuffer.set(buffer);
-}
-
-Buffer *State::getTargetBuffer(GLenum target) const
+Buffer *State::getTargetBuffer(BufferBinding target) const
{
switch (target)
{
- case GL_ARRAY_BUFFER: return mArrayBuffer.get();
- case GL_COPY_READ_BUFFER: return mCopyReadBuffer.get();
- case GL_COPY_WRITE_BUFFER: return mCopyWriteBuffer.get();
- case GL_ELEMENT_ARRAY_BUFFER: return getVertexArray()->getElementArrayBuffer().get();
- case GL_PIXEL_PACK_BUFFER: return mPack.pixelBuffer.get();
- case GL_PIXEL_UNPACK_BUFFER: return mUnpack.pixelBuffer.get();
- case GL_TRANSFORM_FEEDBACK_BUFFER: return mTransformFeedback->getGenericBuffer().get();
- case GL_UNIFORM_BUFFER: return mGenericUniformBuffer.get();
- default: UNREACHABLE(); return NULL;
+ case BufferBinding::ElementArray:
+ return getVertexArray()->getElementArrayBuffer().get();
+ case BufferBinding::TransformFeedback:
+ return mTransformFeedback->getGenericBuffer().get();
+ default:
+ return mBoundBuffers[target].get();
}
}
-void State::detachBuffer(GLuint bufferName)
+void State::detachBuffer(const Context *context, GLuint bufferName)
{
- BindingPointer<Buffer> *buffers[] = {&mArrayBuffer, &mCopyReadBuffer,
- &mCopyWriteBuffer, &mPack.pixelBuffer,
- &mUnpack.pixelBuffer, &mGenericUniformBuffer};
- for (auto buffer : buffers)
+ for (auto &buffer : mBoundBuffers)
{
- if (buffer->id() == bufferName)
+ if (buffer.id() == bufferName)
{
- buffer->set(nullptr);
+ buffer.set(context, nullptr);
}
}
TransformFeedback *curTransformFeedback = getCurrentTransformFeedback();
if (curTransformFeedback)
{
- curTransformFeedback->detachBuffer(bufferName);
+ curTransformFeedback->detachBuffer(context, bufferName);
}
- getVertexArray()->detachBuffer(bufferName);
+ getVertexArray()->detachBuffer(context, bufferName);
}
void State::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
@@ -1145,46 +1359,56 @@ void State::setVertexAttribf(GLuint index, const GLfloat values[4])
{
ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
mVertexAttribCurrentValues[index].setFloatValues(values);
- mDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_0 + index);
+ mDirtyBits.set(DIRTY_BIT_CURRENT_VALUES);
+ mDirtyCurrentValues.set(index);
}
void State::setVertexAttribu(GLuint index, const GLuint values[4])
{
ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
mVertexAttribCurrentValues[index].setUnsignedIntValues(values);
- mDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_0 + index);
+ mDirtyBits.set(DIRTY_BIT_CURRENT_VALUES);
+ mDirtyCurrentValues.set(index);
}
void State::setVertexAttribi(GLuint index, const GLint values[4])
{
ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
mVertexAttribCurrentValues[index].setIntValues(values);
- mDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_0 + index);
+ mDirtyBits.set(DIRTY_BIT_CURRENT_VALUES);
+ mDirtyCurrentValues.set(index);
+}
+
+void State::setVertexAttribPointer(const Context *context,
+ unsigned int attribNum,
+ Buffer *boundBuffer,
+ GLint size,
+ GLenum type,
+ bool normalized,
+ bool pureInteger,
+ GLsizei stride,
+ const void *pointer)
+{
+ getVertexArray()->setVertexAttribPointer(context, attribNum, boundBuffer, size, type,
+ normalized, pureInteger, stride, pointer);
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
}
-void State::setVertexAttribState(unsigned int attribNum,
- Buffer *boundBuffer,
- GLint size,
- GLenum type,
- bool normalized,
- bool pureInteger,
- GLsizei stride,
- const void *pointer)
+void State::setVertexAttribDivisor(const Context *context, GLuint index, GLuint divisor)
{
- getVertexArray()->setAttributeState(attribNum, boundBuffer, size, type, normalized, pureInteger, stride, pointer);
+ getVertexArray()->setVertexAttribDivisor(context, index, divisor);
mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
}
-void State::setVertexAttribDivisor(GLuint index, GLuint divisor)
+const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(size_t attribNum) const
{
- getVertexArray()->setVertexAttribDivisor(index, divisor);
- mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+ ASSERT(attribNum < mVertexAttribCurrentValues.size());
+ return mVertexAttribCurrentValues[attribNum];
}
-const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(unsigned int attribNum) const
+const std::vector<VertexAttribCurrentValueData> &State::getVertexAttribCurrentValues() const
{
- ASSERT(static_cast<size_t>(attribNum) < mVertexAttribCurrentValues.size());
- return mVertexAttribCurrentValues[attribNum];
+ return mVertexAttribCurrentValues;
}
const void *State::getVertexAttribPointer(unsigned int attribNum) const
@@ -1195,7 +1419,7 @@ const void *State::getVertexAttribPointer(unsigned int attribNum) const
void State::setPackAlignment(GLint alignment)
{
mPack.alignment = alignment;
- mDirtyBits.set(DIRTY_BIT_PACK_ALIGNMENT);
+ mDirtyBits.set(DIRTY_BIT_PACK_STATE);
}
GLint State::getPackAlignment() const
@@ -1206,7 +1430,7 @@ GLint State::getPackAlignment() const
void State::setPackReverseRowOrder(bool reverseRowOrder)
{
mPack.reverseRowOrder = reverseRowOrder;
- mDirtyBits.set(DIRTY_BIT_PACK_REVERSE_ROW_ORDER);
+ mDirtyBits.set(DIRTY_BIT_PACK_STATE);
}
bool State::getPackReverseRowOrder() const
@@ -1217,7 +1441,7 @@ bool State::getPackReverseRowOrder() const
void State::setPackRowLength(GLint rowLength)
{
mPack.rowLength = rowLength;
- mDirtyBits.set(DIRTY_BIT_PACK_ROW_LENGTH);
+ mDirtyBits.set(DIRTY_BIT_PACK_STATE);
}
GLint State::getPackRowLength() const
@@ -1228,7 +1452,7 @@ GLint State::getPackRowLength() const
void State::setPackSkipRows(GLint skipRows)
{
mPack.skipRows = skipRows;
- mDirtyBits.set(DIRTY_BIT_PACK_SKIP_ROWS);
+ mDirtyBits.set(DIRTY_BIT_PACK_STATE);
}
GLint State::getPackSkipRows() const
@@ -1239,7 +1463,7 @@ GLint State::getPackSkipRows() const
void State::setPackSkipPixels(GLint skipPixels)
{
mPack.skipPixels = skipPixels;
- mDirtyBits.set(DIRTY_BIT_PACK_SKIP_PIXELS);
+ mDirtyBits.set(DIRTY_BIT_PACK_STATE);
}
GLint State::getPackSkipPixels() const
@@ -1260,7 +1484,7 @@ PixelPackState &State::getPackState()
void State::setUnpackAlignment(GLint alignment)
{
mUnpack.alignment = alignment;
- mDirtyBits.set(DIRTY_BIT_UNPACK_ALIGNMENT);
+ mDirtyBits.set(DIRTY_BIT_UNPACK_STATE);
}
GLint State::getUnpackAlignment() const
@@ -1271,7 +1495,7 @@ GLint State::getUnpackAlignment() const
void State::setUnpackRowLength(GLint rowLength)
{
mUnpack.rowLength = rowLength;
- mDirtyBits.set(DIRTY_BIT_UNPACK_ROW_LENGTH);
+ mDirtyBits.set(DIRTY_BIT_UNPACK_STATE);
}
GLint State::getUnpackRowLength() const
@@ -1282,7 +1506,7 @@ GLint State::getUnpackRowLength() const
void State::setUnpackImageHeight(GLint imageHeight)
{
mUnpack.imageHeight = imageHeight;
- mDirtyBits.set(DIRTY_BIT_UNPACK_IMAGE_HEIGHT);
+ mDirtyBits.set(DIRTY_BIT_UNPACK_STATE);
}
GLint State::getUnpackImageHeight() const
@@ -1293,7 +1517,7 @@ GLint State::getUnpackImageHeight() const
void State::setUnpackSkipImages(GLint skipImages)
{
mUnpack.skipImages = skipImages;
- mDirtyBits.set(DIRTY_BIT_UNPACK_SKIP_IMAGES);
+ mDirtyBits.set(DIRTY_BIT_UNPACK_STATE);
}
GLint State::getUnpackSkipImages() const
@@ -1304,7 +1528,7 @@ GLint State::getUnpackSkipImages() const
void State::setUnpackSkipRows(GLint skipRows)
{
mUnpack.skipRows = skipRows;
- mDirtyBits.set(DIRTY_BIT_UNPACK_SKIP_ROWS);
+ mDirtyBits.set(DIRTY_BIT_UNPACK_STATE);
}
GLint State::getUnpackSkipRows() const
@@ -1315,7 +1539,7 @@ GLint State::getUnpackSkipRows() const
void State::setUnpackSkipPixels(GLint skipPixels)
{
mUnpack.skipPixels = skipPixels;
- mDirtyBits.set(DIRTY_BIT_UNPACK_SKIP_PIXELS);
+ mDirtyBits.set(DIRTY_BIT_UNPACK_STATE);
}
GLint State::getUnpackSkipPixels() const
@@ -1343,6 +1567,84 @@ Debug &State::getDebug()
return mDebug;
}
+void State::setCoverageModulation(GLenum components)
+{
+ mCoverageModulation = components;
+ mDirtyBits.set(DIRTY_BIT_COVERAGE_MODULATION);
+}
+
+GLenum State::getCoverageModulation() const
+{
+ return mCoverageModulation;
+}
+
+void State::loadPathRenderingMatrix(GLenum matrixMode, const GLfloat *matrix)
+{
+ if (matrixMode == GL_PATH_MODELVIEW_CHROMIUM)
+ {
+ memcpy(mPathMatrixMV, matrix, 16 * sizeof(GLfloat));
+ mDirtyBits.set(DIRTY_BIT_PATH_RENDERING_MATRIX_MV);
+ }
+ else if (matrixMode == GL_PATH_PROJECTION_CHROMIUM)
+ {
+ memcpy(mPathMatrixProj, matrix, 16 * sizeof(GLfloat));
+ mDirtyBits.set(DIRTY_BIT_PATH_RENDERING_MATRIX_PROJ);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+}
+
+const GLfloat *State::getPathRenderingMatrix(GLenum which) const
+{
+ if (which == GL_PATH_MODELVIEW_MATRIX_CHROMIUM)
+ {
+ return mPathMatrixMV;
+ }
+ else if (which == GL_PATH_PROJECTION_MATRIX_CHROMIUM)
+ {
+ return mPathMatrixProj;
+ }
+
+ UNREACHABLE();
+ return nullptr;
+}
+
+void State::setPathStencilFunc(GLenum func, GLint ref, GLuint mask)
+{
+ mPathStencilFunc = func;
+ mPathStencilRef = ref;
+ mPathStencilMask = mask;
+ mDirtyBits.set(DIRTY_BIT_PATH_RENDERING_STENCIL_STATE);
+}
+
+GLenum State::getPathStencilFunc() const
+{
+ return mPathStencilFunc;
+}
+
+GLint State::getPathStencilRef() const
+{
+ return mPathStencilRef;
+}
+
+GLuint State::getPathStencilMask() const
+{
+ return mPathStencilMask;
+}
+
+void State::setFramebufferSRGB(bool sRGB)
+{
+ mFramebufferSRGB = sRGB;
+ mDirtyBits.set(DIRTY_BIT_FRAMEBUFFER_SRGB);
+}
+
+bool State::getFramebufferSRGB() const
+{
+ return mFramebufferSRGB;
+}
+
void State::getBooleanv(GLenum pname, GLboolean *params)
{
switch (pname)
@@ -1355,10 +1657,15 @@ void State::getBooleanv(GLenum pname, GLboolean *params)
params[2] = mBlend.colorMaskBlue;
params[3] = mBlend.colorMaskAlpha;
break;
- case GL_CULL_FACE: *params = mRasterizer.cullFace; break;
+ case GL_CULL_FACE:
+ *params = mRasterizer.cullFace;
+ break;
case GL_POLYGON_OFFSET_FILL: *params = mRasterizer.polygonOffsetFill; break;
case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mBlend.sampleAlphaToCoverage; break;
case GL_SAMPLE_COVERAGE: *params = mSampleCoverage; break;
+ case GL_SAMPLE_MASK:
+ *params = mSampleMask;
+ break;
case GL_SCISSOR_TEST: *params = mScissorTest; break;
case GL_STENCIL_TEST: *params = mDepthStencil.stencilTest; break;
case GL_DEPTH_TEST: *params = mDepthStencil.depthTest; break;
@@ -1378,6 +1685,28 @@ void State::getBooleanv(GLenum pname, GLboolean *params)
case GL_DEBUG_OUTPUT:
*params = mDebug.isOutputEnabled() ? GL_TRUE : GL_FALSE;
break;
+ case GL_MULTISAMPLE_EXT:
+ *params = mMultiSampling;
+ break;
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+ *params = mSampleAlphaToOne;
+ break;
+ case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
+ *params = isBindGeneratesResourceEnabled() ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_CLIENT_ARRAYS_ANGLE:
+ *params = areClientArraysEnabled() ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_FRAMEBUFFER_SRGB_EXT:
+ *params = getFramebufferSRGB() ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ *params = mRobustResourceInit ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_PROGRAM_CACHE_ENABLED_ANGLE:
+ *params = mProgramBinaryCacheEnabled ? GL_TRUE : GL_FALSE;
+ break;
+
default:
UNREACHABLE();
break;
@@ -1413,13 +1742,21 @@ void State::getFloatv(GLenum pname, GLfloat *params)
params[2] = mBlendColor.blue;
params[3] = mBlendColor.alpha;
break;
+ case GL_MULTISAMPLE_EXT:
+ *params = static_cast<GLfloat>(mMultiSampling);
+ break;
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+ *params = static_cast<GLfloat>(mSampleAlphaToOne);
+ case GL_COVERAGE_MODULATION_CHROMIUM:
+ params[0] = static_cast<GLfloat>(mCoverageModulation);
+ break;
default:
UNREACHABLE();
break;
}
}
-void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
+void State::getIntegerv(const Context *context, GLenum pname, GLint *params)
{
if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT)
{
@@ -1437,8 +1774,15 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
// State::getFloatv.
switch (pname)
{
- case GL_ARRAY_BUFFER_BINDING: *params = mArrayBuffer.id(); break;
- case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = getVertexArray()->getElementArrayBuffer().id(); break;
+ case GL_ARRAY_BUFFER_BINDING:
+ *params = mBoundBuffers[BufferBinding::Array].id();
+ break;
+ case GL_DRAW_INDIRECT_BUFFER_BINDING:
+ *params = mBoundBuffers[BufferBinding::DrawIndirect].id();
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER_BINDING:
+ *params = getVertexArray()->getElementArrayBuffer().id();
+ break;
//case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE
case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mDrawFramebuffer->id(); break;
case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mReadFramebuffer->id(); break;
@@ -1477,10 +1821,14 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
break;
case GL_STENCIL_FUNC: *params = mDepthStencil.stencilFunc; break;
case GL_STENCIL_REF: *params = mStencilRef; break;
- case GL_STENCIL_VALUE_MASK: *params = clampToInt(mDepthStencil.stencilMask); break;
+ case GL_STENCIL_VALUE_MASK:
+ *params = CastMaskValue(context, mDepthStencil.stencilMask);
+ break;
case GL_STENCIL_BACK_FUNC: *params = mDepthStencil.stencilBackFunc; break;
case GL_STENCIL_BACK_REF: *params = mStencilBackRef; break;
- case GL_STENCIL_BACK_VALUE_MASK: *params = clampToInt(mDepthStencil.stencilBackMask); break;
+ case GL_STENCIL_BACK_VALUE_MASK:
+ *params = CastMaskValue(context, mDepthStencil.stencilBackMask);
+ break;
case GL_STENCIL_FAIL: *params = mDepthStencil.stencilFail; break;
case GL_STENCIL_PASS_DEPTH_FAIL: *params = mDepthStencil.stencilPassDepthFail; break;
case GL_STENCIL_PASS_DEPTH_PASS: *params = mDepthStencil.stencilPassDepthPass; break;
@@ -1494,32 +1842,40 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
case GL_BLEND_DST_ALPHA: *params = mBlend.destBlendAlpha; break;
case GL_BLEND_EQUATION_RGB: *params = mBlend.blendEquationRGB; break;
case GL_BLEND_EQUATION_ALPHA: *params = mBlend.blendEquationAlpha; break;
- case GL_STENCIL_WRITEMASK: *params = clampToInt(mDepthStencil.stencilWritemask); break;
- case GL_STENCIL_BACK_WRITEMASK: *params = clampToInt(mDepthStencil.stencilBackWritemask); break;
+ case GL_STENCIL_WRITEMASK:
+ *params = CastMaskValue(context, mDepthStencil.stencilWritemask);
+ break;
+ case GL_STENCIL_BACK_WRITEMASK:
+ *params = CastMaskValue(context, mDepthStencil.stencilBackWritemask);
+ break;
case GL_STENCIL_CLEAR_VALUE: *params = mStencilClearValue; break;
- case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = mReadFramebuffer->getImplementationColorReadType(); break;
- case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = mReadFramebuffer->getImplementationColorReadFormat(); break;
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+ *params = mReadFramebuffer->getImplementationColorReadType(context);
+ break;
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+ *params = mReadFramebuffer->getImplementationColorReadFormat(context);
+ break;
case GL_SAMPLE_BUFFERS:
case GL_SAMPLES:
{
- gl::Framebuffer *framebuffer = mDrawFramebuffer;
- if (framebuffer->checkStatus(data) == GL_FRAMEBUFFER_COMPLETE)
+ Framebuffer *framebuffer = mDrawFramebuffer;
+ if (framebuffer->checkStatus(context) == GL_FRAMEBUFFER_COMPLETE)
{
switch (pname)
{
- case GL_SAMPLE_BUFFERS:
- if (framebuffer->getSamples(data) != 0)
- {
- *params = 1;
- }
- else
- {
- *params = 0;
- }
- break;
- case GL_SAMPLES:
- *params = framebuffer->getSamples(data);
- break;
+ case GL_SAMPLE_BUFFERS:
+ if (framebuffer->getSamples(context) != 0)
+ {
+ *params = 1;
+ }
+ else
+ {
+ *params = 0;
+ }
+ break;
+ case GL_SAMPLES:
+ *params = framebuffer->getSamples(context);
+ break;
}
}
else
@@ -1540,15 +1896,19 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
params[2] = mScissor.width;
params[3] = mScissor.height;
break;
- case GL_CULL_FACE_MODE: *params = mRasterizer.cullMode; break;
- case GL_FRONT_FACE: *params = mRasterizer.frontFace; break;
+ case GL_CULL_FACE_MODE:
+ *params = ToGLenum(mRasterizer.cullMode);
+ break;
+ case GL_FRONT_FACE:
+ *params = mRasterizer.frontFace;
+ break;
case GL_RED_BITS:
case GL_GREEN_BITS:
case GL_BLUE_BITS:
case GL_ALPHA_BITS:
{
- gl::Framebuffer *framebuffer = getDrawFramebuffer();
- const gl::FramebufferAttachment *colorbuffer = framebuffer->getFirstColorbuffer();
+ Framebuffer *framebuffer = getDrawFramebuffer();
+ const FramebufferAttachment *colorbuffer = framebuffer->getFirstColorbuffer();
if (colorbuffer)
{
@@ -1568,8 +1928,8 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
break;
case GL_DEPTH_BITS:
{
- const gl::Framebuffer *framebuffer = getDrawFramebuffer();
- const gl::FramebufferAttachment *depthbuffer = framebuffer->getDepthbuffer();
+ const Framebuffer *framebuffer = getDrawFramebuffer();
+ const FramebufferAttachment *depthbuffer = framebuffer->getDepthbuffer();
if (depthbuffer)
{
@@ -1583,8 +1943,8 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
break;
case GL_STENCIL_BITS:
{
- const gl::Framebuffer *framebuffer = getDrawFramebuffer();
- const gl::FramebufferAttachment *stencilbuffer = framebuffer->getStencilbuffer();
+ const Framebuffer *framebuffer = getDrawFramebuffer();
+ const FramebufferAttachment *stencilbuffer = framebuffer->getStencilbuffer();
if (stencilbuffer)
{
@@ -1600,6 +1960,11 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
*params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler), GL_TEXTURE_2D);
break;
+ case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
+ ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
+ *params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler),
+ GL_TEXTURE_RECTANGLE_ANGLE);
+ break;
case GL_TEXTURE_BINDING_CUBE_MAP:
ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
*params =
@@ -1614,27 +1979,45 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
*params =
getSamplerTextureId(static_cast<unsigned int>(mActiveSampler), GL_TEXTURE_2D_ARRAY);
break;
+ case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
+ ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
+ *params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler),
+ GL_TEXTURE_2D_MULTISAMPLE);
+ break;
+ case GL_TEXTURE_BINDING_EXTERNAL_OES:
+ ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
+ *params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler),
+ GL_TEXTURE_EXTERNAL_OES);
+ break;
case GL_UNIFORM_BUFFER_BINDING:
- *params = mGenericUniformBuffer.id();
- break;
+ *params = mBoundBuffers[BufferBinding::Uniform].id();
+ break;
case GL_TRANSFORM_FEEDBACK_BINDING:
*params = mTransformFeedback.id();
break;
case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
- *params = mTransformFeedback->getGenericBuffer().id();
- break;
+ ASSERT(mTransformFeedback.get() != nullptr);
+ *params = mTransformFeedback->getGenericBuffer().id();
+ break;
case GL_COPY_READ_BUFFER_BINDING:
- *params = mCopyReadBuffer.id();
- break;
+ *params = mBoundBuffers[BufferBinding::CopyRead].id();
+ break;
case GL_COPY_WRITE_BUFFER_BINDING:
- *params = mCopyWriteBuffer.id();
- break;
+ *params = mBoundBuffers[BufferBinding::CopyWrite].id();
+ break;
case GL_PIXEL_PACK_BUFFER_BINDING:
- *params = mPack.pixelBuffer.id();
- break;
+ *params = mBoundBuffers[BufferBinding::PixelPack].id();
+ break;
case GL_PIXEL_UNPACK_BUFFER_BINDING:
- *params = mUnpack.pixelBuffer.id();
- break;
+ *params = mBoundBuffers[BufferBinding::PixelUnpack].id();
+ break;
+ case GL_READ_BUFFER:
+ *params = mReadFramebuffer->getReadBufferState();
+ break;
+ case GL_SAMPLER_BINDING:
+ ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
+ *params = getSamplerId(static_cast<GLuint>(mActiveSampler));
+ break;
case GL_DEBUG_LOGGED_MESSAGES:
*params = static_cast<GLint>(mDebug.getMessageCount());
break;
@@ -1644,6 +2027,20 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
case GL_DEBUG_GROUP_STACK_DEPTH:
*params = static_cast<GLint>(mDebug.getGroupStackDepth());
break;
+ case GL_MULTISAMPLE_EXT:
+ *params = static_cast<GLint>(mMultiSampling);
+ break;
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+ *params = static_cast<GLint>(mSampleAlphaToOne);
+ case GL_COVERAGE_MODULATION_CHROMIUM:
+ *params = static_cast<GLint>(mCoverageModulation);
+ break;
+ case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+ *params = mBoundBuffers[BufferBinding::AtomicCounter].id();
+ break;
+ case GL_SHADER_STORAGE_BUFFER_BINDING:
+ *params = mBoundBuffers[BufferBinding::ShaderStorage].id();
+ break;
default:
UNREACHABLE();
break;
@@ -1666,75 +2063,111 @@ void State::getPointerv(GLenum pname, void **params) const
}
}
-bool State::getIndexedIntegerv(GLenum target, GLuint index, GLint *data)
+void State::getIntegeri_v(GLenum target, GLuint index, GLint *data)
{
switch (target)
{
case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
- if (static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount())
- {
- *data = mTransformFeedback->getIndexedBuffer(index).id();
- }
- break;
+ ASSERT(static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount());
+ *data = mTransformFeedback->getIndexedBuffer(index).id();
+ break;
case GL_UNIFORM_BUFFER_BINDING:
- if (static_cast<size_t>(index) < mUniformBuffers.size())
- {
- *data = mUniformBuffers[index].id();
- }
- break;
+ ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
+ *data = mUniformBuffers[index].id();
+ break;
+ case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+ ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size());
+ *data = mAtomicCounterBuffers[index].id();
+ break;
+ case GL_SHADER_STORAGE_BUFFER_BINDING:
+ ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size());
+ *data = mShaderStorageBuffers[index].id();
+ break;
+ case GL_VERTEX_BINDING_BUFFER:
+ ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
+ *data = mVertexArray->getVertexBinding(index).getBuffer().id();
+ break;
+ case GL_VERTEX_BINDING_DIVISOR:
+ ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
+ *data = mVertexArray->getVertexBinding(index).getDivisor();
+ break;
+ case GL_VERTEX_BINDING_OFFSET:
+ ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
+ *data = static_cast<GLuint>(mVertexArray->getVertexBinding(index).getOffset());
+ break;
+ case GL_VERTEX_BINDING_STRIDE:
+ ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
+ *data = mVertexArray->getVertexBinding(index).getStride();
+ break;
+ case GL_SAMPLE_MASK_VALUE:
+ ASSERT(static_cast<size_t>(index) < mSampleMaskValues.size());
+ *data = mSampleMaskValues[index];
+ break;
default:
- return false;
+ UNREACHABLE();
+ break;
}
-
- return true;
}
-bool State::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data)
+void State::getInteger64i_v(GLenum target, GLuint index, GLint64 *data)
{
switch (target)
{
case GL_TRANSFORM_FEEDBACK_BUFFER_START:
- if (static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount())
- {
- *data = mTransformFeedback->getIndexedBuffer(index).getOffset();
- }
- break;
+ ASSERT(static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount());
+ *data = mTransformFeedback->getIndexedBuffer(index).getOffset();
+ break;
case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
- if (static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount())
- {
- *data = mTransformFeedback->getIndexedBuffer(index).getSize();
- }
- break;
+ ASSERT(static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount());
+ *data = mTransformFeedback->getIndexedBuffer(index).getSize();
+ break;
case GL_UNIFORM_BUFFER_START:
- if (static_cast<size_t>(index) < mUniformBuffers.size())
- {
- *data = mUniformBuffers[index].getOffset();
- }
- break;
+ ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
+ *data = mUniformBuffers[index].getOffset();
+ break;
case GL_UNIFORM_BUFFER_SIZE:
- if (static_cast<size_t>(index) < mUniformBuffers.size())
- {
- *data = mUniformBuffers[index].getSize();
- }
- break;
+ ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
+ *data = mUniformBuffers[index].getSize();
+ break;
+ case GL_ATOMIC_COUNTER_BUFFER_START:
+ ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size());
+ *data = mAtomicCounterBuffers[index].getOffset();
+ break;
+ case GL_ATOMIC_COUNTER_BUFFER_SIZE:
+ ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size());
+ *data = mAtomicCounterBuffers[index].getSize();
+ break;
+ case GL_SHADER_STORAGE_BUFFER_START:
+ ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size());
+ *data = mShaderStorageBuffers[index].getOffset();
+ break;
+ case GL_SHADER_STORAGE_BUFFER_SIZE:
+ ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size());
+ *data = mShaderStorageBuffers[index].getSize();
+ break;
default:
- return false;
+ UNREACHABLE();
+ break;
}
+}
- return true;
+void State::getBooleani_v(GLenum target, GLuint index, GLboolean *data)
+{
+ UNREACHABLE();
}
-bool State::hasMappedBuffer(GLenum target) const
+bool State::hasMappedBuffer(BufferBinding target) const
{
- if (target == GL_ARRAY_BUFFER)
+ if (target == BufferBinding::Array)
{
- const VertexArray *vao = getVertexArray();
+ const VertexArray *vao = getVertexArray();
const auto &vertexAttribs = vao->getVertexAttributes();
+ const auto &vertexBindings = vao->getVertexBindings();
size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
for (size_t attribIndex = 0; attribIndex < maxEnabledAttrib; attribIndex++)
{
- const gl::VertexAttribute &vertexAttrib = vertexAttribs[attribIndex];
- gl::Buffer *boundBuffer = vertexAttrib.buffer.get();
+ const VertexAttribute &vertexAttrib = vertexAttribs[attribIndex];
+ auto *boundBuffer = vertexBindings[vertexAttrib.bindingIndex].getBuffer().get();
if (vertexAttrib.enabled && boundBuffer && boundBuffer->isMapped())
{
return true;
@@ -1750,35 +2183,36 @@ bool State::hasMappedBuffer(GLenum target) const
}
}
-void State::syncDirtyObjects()
+void State::syncDirtyObjects(const Context *context)
{
if (!mDirtyObjects.any())
return;
- syncDirtyObjects(mDirtyObjects);
+ syncDirtyObjects(context, mDirtyObjects);
}
-void State::syncDirtyObjects(const DirtyObjects &bitset)
+void State::syncDirtyObjects(const Context *context, const DirtyObjects &bitset)
{
- for (auto dirtyObject : angle::IterateBitSet(bitset))
+ for (auto dirtyObject : bitset)
{
switch (dirtyObject)
{
case DIRTY_OBJECT_READ_FRAMEBUFFER:
ASSERT(mReadFramebuffer);
- mReadFramebuffer->syncState();
+ mReadFramebuffer->syncState(context);
break;
case DIRTY_OBJECT_DRAW_FRAMEBUFFER:
ASSERT(mDrawFramebuffer);
- mDrawFramebuffer->syncState();
+ mDrawFramebuffer->syncState(context);
break;
case DIRTY_OBJECT_VERTEX_ARRAY:
ASSERT(mVertexArray);
- mVertexArray->syncImplState();
+ mVertexArray->syncState(context);
break;
- case DIRTY_OBJECT_PROGRAM:
- // TODO(jmadill): implement this
+ case DIRTY_OBJECT_PROGRAM_TEXTURES:
+ syncProgramTextures(context);
break;
+
default:
UNREACHABLE();
break;
@@ -1788,7 +2222,82 @@ void State::syncDirtyObjects(const DirtyObjects &bitset)
mDirtyObjects &= ~bitset;
}
-void State::syncDirtyObject(GLenum target)
+void State::syncProgramTextures(const Context *context)
+{
+ // TODO(jmadill): Fine-grained updates.
+ if (!mProgram)
+ {
+ return;
+ }
+
+ ASSERT(mDirtyObjects[DIRTY_OBJECT_PROGRAM_TEXTURES]);
+ mDirtyBits.set(DIRTY_BIT_TEXTURE_BINDINGS);
+
+ ActiveTextureMask newActiveTextures;
+
+ // Initialize to the 'Initialized' state and set to 'MayNeedInit' if any texture is not
+ // initialized.
+ mCachedTexturesInitState = InitState::Initialized;
+
+ for (const SamplerBinding &samplerBinding : mProgram->getSamplerBindings())
+ {
+ if (samplerBinding.unreferenced)
+ continue;
+
+ GLenum textureType = samplerBinding.textureType;
+ for (GLuint textureUnitIndex : samplerBinding.boundTextureUnits)
+ {
+ Texture *texture = getSamplerTexture(textureUnitIndex, textureType);
+ Sampler *sampler = getSampler(textureUnitIndex);
+ ASSERT(static_cast<size_t>(textureUnitIndex) < mCompleteTextureCache.size());
+ ASSERT(static_cast<size_t>(textureUnitIndex) < newActiveTextures.size());
+
+ ASSERT(texture);
+
+ // Mark the texture binding bit as dirty if the texture completeness changes.
+ // TODO(jmadill): Use specific dirty bit for completeness change.
+ if (texture->isSamplerComplete(context, sampler) &&
+ !mDrawFramebuffer->hasTextureAttachment(texture))
+ {
+ texture->syncState();
+ mCompleteTextureCache[textureUnitIndex] = texture;
+ }
+ else
+ {
+ mCompleteTextureCache[textureUnitIndex] = nullptr;
+ }
+
+ // Bind the texture unconditionally, to recieve completeness change notifications.
+ mCompleteTextureBindings[textureUnitIndex].bind(texture->getDirtyChannel());
+ mActiveTexturesMask.set(textureUnitIndex);
+ newActiveTextures.set(textureUnitIndex);
+
+ if (sampler != nullptr)
+ {
+ sampler->syncState(context);
+ }
+
+ if (texture->initState() == InitState::MayNeedInit)
+ {
+ mCachedTexturesInitState = InitState::MayNeedInit;
+ }
+ }
+ }
+
+ // Unset now missing textures.
+ ActiveTextureMask negativeMask = mActiveTexturesMask & ~newActiveTextures;
+ if (negativeMask.any())
+ {
+ for (auto textureIndex : negativeMask)
+ {
+ mCompleteTextureBindings[textureIndex].reset();
+ mCompleteTextureCache[textureIndex] = nullptr;
+ mActiveTexturesMask.reset(textureIndex);
+ }
+ }
+}
+
+void State::syncDirtyObject(const Context *context, GLenum target)
{
DirtyObjects localSet;
@@ -1807,12 +2316,14 @@ void State::syncDirtyObject(GLenum target)
case GL_VERTEX_ARRAY:
localSet.set(DIRTY_OBJECT_VERTEX_ARRAY);
break;
+ case GL_TEXTURE:
+ case GL_SAMPLER:
case GL_PROGRAM:
- localSet.set(DIRTY_OBJECT_PROGRAM);
+ localSet.set(DIRTY_OBJECT_PROGRAM_TEXTURES);
break;
}
- syncDirtyObjects(localSet);
+ syncDirtyObjects(context, localSet);
}
void State::setObjectDirty(GLenum target)
@@ -1832,10 +2343,91 @@ void State::setObjectDirty(GLenum target)
case GL_VERTEX_ARRAY:
mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
break;
+ case GL_TEXTURE:
+ case GL_SAMPLER:
case GL_PROGRAM:
- mDirtyObjects.set(DIRTY_OBJECT_PROGRAM);
+ mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_TEXTURES);
+ mDirtyBits.set(DIRTY_BIT_TEXTURE_BINDINGS);
break;
}
}
+void State::onProgramExecutableChange(Program *program)
+{
+ // OpenGL Spec:
+ // "If LinkProgram or ProgramBinary successfully re-links a program object
+ // that was already in use as a result of a previous call to UseProgram, then the
+ // generated executable code will be installed as part of the current rendering state."
+ if (program->isLinked() && mProgram == program)
+ {
+ mDirtyBits.set(DIRTY_BIT_PROGRAM_EXECUTABLE);
+ mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_TEXTURES);
+ }
+}
+
+void State::setImageUnit(const Context *context,
+ GLuint unit,
+ Texture *texture,
+ GLint level,
+ GLboolean layered,
+ GLint layer,
+ GLenum access,
+ GLenum format)
+{
+ mImageUnits[unit].texture.set(context, texture);
+ mImageUnits[unit].level = level;
+ mImageUnits[unit].layered = layered;
+ mImageUnits[unit].layer = layer;
+ mImageUnits[unit].access = access;
+ mImageUnits[unit].format = format;
+}
+
+const ImageUnit &State::getImageUnit(GLuint unit) const
+{
+ return mImageUnits[unit];
+}
+
+// Handle a dirty texture event.
+void State::signal(size_t textureIndex, InitState initState)
+{
+ // Conservatively assume all textures are dirty.
+ // TODO(jmadill): More fine-grained update.
+ mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_TEXTURES);
+
+ if (initState == InitState::MayNeedInit)
+ {
+ mCachedTexturesInitState = InitState::MayNeedInit;
+ }
+}
+
+Error State::clearUnclearedActiveTextures(const Context *context)
+{
+ ASSERT(mRobustResourceInit);
+
+ if (mCachedTexturesInitState == InitState::Initialized)
+ {
+ return NoError();
+ }
+
+ for (auto textureIndex : mActiveTexturesMask)
+ {
+ Texture *texture = mCompleteTextureCache[textureIndex];
+ if (texture)
+ {
+ ANGLE_TRY(texture->ensureInitialized(context));
+ }
+ }
+
+ mCachedTexturesInitState = InitState::Initialized;
+
+ return NoError();
+}
+
+AttributesMask State::getAndResetDirtyCurrentValues() const
+{
+ AttributesMask retVal = mDirtyCurrentValues;
+ mDirtyCurrentValues.reset();
+ return retVal;
+}
+
} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/State.h b/src/3rdparty/angle/src/libANGLE/State.h
index e822d7e679..52e1d78382 100644
--- a/src/3rdparty/angle/src/libANGLE/State.h
+++ b/src/3rdparty/angle/src/libANGLE/State.h
@@ -12,14 +12,18 @@
#include <bitset>
#include <memory>
+#include "common/Color.h"
#include "common/angleutils.h"
+#include "common/bitset_utils.h"
#include "libANGLE/Debug.h"
#include "libANGLE/Program.h"
+#include "libANGLE/ProgramPipeline.h"
#include "libANGLE/RefCountObject.h"
#include "libANGLE/Renderbuffer.h"
#include "libANGLE/Sampler.h"
#include "libANGLE/Texture.h"
#include "libANGLE/TransformFeedback.h"
+#include "libANGLE/Version.h"
#include "libANGLE/VertexAttribute.h"
#include "libANGLE/angletypes.h"
@@ -29,21 +33,20 @@ class Query;
class VertexArray;
class Context;
struct Caps;
-struct Data;
-typedef std::map<GLenum, BindingPointer<Texture>> TextureMap;
-
-class State : angle::NonCopyable
+class State : public OnAttachmentDirtyReceiver, angle::NonCopyable
{
public:
State();
- ~State();
+ ~State() override;
- void initialize(const Caps &caps,
- const Extensions &extensions,
- GLuint clientVersion,
- bool debug);
- void reset();
+ void initialize(const Context *context,
+ bool debug,
+ bool bindGeneratesResource,
+ bool clientArraysEnabled,
+ bool robustResourceInit,
+ bool programBinaryCacheEnabled);
+ void reset(const Context *context);
// State chunk getters
const RasterizerState &getRasterizerState() const;
@@ -74,7 +77,7 @@ class State : angle::NonCopyable
// Face culling state manipulation
bool isCullFaceEnabled() const;
void setCullFace(bool enabled);
- void setCullMode(GLenum mode);
+ void setCullMode(CullFaceMode mode);
void setFrontFace(GLenum front);
// Depth test state manipulation
@@ -100,8 +103,12 @@ class State : angle::NonCopyable
void setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask);
void setStencilWritemask(GLuint stencilWritemask);
void setStencilBackWritemask(GLuint stencilBackWritemask);
- void setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass);
- void setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass);
+ void setStencilOperations(GLenum stencilFail,
+ GLenum stencilPassDepthFail,
+ GLenum stencilPassDepthPass);
+ void setStencilBackOperations(GLenum stencilBackFail,
+ GLenum stencilBackPassDepthFail,
+ GLenum stencilBackPassDepthPass);
GLint getStencilRef() const;
GLint getStencilBackRef() const;
@@ -116,9 +123,22 @@ class State : angle::NonCopyable
bool isSampleCoverageEnabled() const;
void setSampleCoverage(bool enabled);
void setSampleCoverageParams(GLclampf value, bool invert);
- GLclampf getSampleCoverageValue() const;
+ GLfloat getSampleCoverageValue() const;
bool getSampleCoverageInvert() const;
+ // Multisample mask state manipulation.
+ bool isSampleMaskEnabled() const;
+ void setSampleMaskEnabled(bool enabled);
+ void setSampleMaskParams(GLuint maskNumber, GLbitfield mask);
+ GLbitfield getSampleMaskWord(GLuint maskNumber) const;
+ GLuint getMaxSampleMaskWords() const;
+
+ // Multisampling/alpha to one manipulation.
+ void setSampleAlphaToOne(bool enabled);
+ bool isSampleAlphaToOneEnabled() const;
+ void setMultisampling(bool enabled);
+ bool isMultisamplingEnabled() const;
+
// Scissor test state toggle & query
bool isScissorTestEnabled() const;
void setScissorTest(bool enabled);
@@ -131,7 +151,7 @@ class State : angle::NonCopyable
// Generic state toggle & query
void setEnableFeature(GLenum feature, bool enabled);
- bool getEnableFeature(GLenum feature);
+ bool getEnableFeature(GLenum feature) const;
// Line width state setter
void setLineWidth(GLfloat width);
@@ -141,6 +161,12 @@ class State : angle::NonCopyable
void setGenerateMipmapHint(GLenum hint);
void setFragmentShaderDerivativeHint(GLenum hint);
+ // GL_CHROMIUM_bind_generates_resource
+ bool isBindGeneratesResourceEnabled() const;
+
+ // GL_ANGLE_client_arrays
+ bool areClientArraysEnabled() const;
+
// Viewport state setter/getter
void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height);
const Rectangle &getViewport() const;
@@ -148,33 +174,31 @@ class State : angle::NonCopyable
// Texture binding & active texture unit manipulation
void setActiveSampler(unsigned int active);
unsigned int getActiveSampler() const;
- void setSamplerTexture(GLenum type, Texture *texture);
+ void setSamplerTexture(const Context *context, GLenum type, Texture *texture);
Texture *getTargetTexture(GLenum target) const;
Texture *getSamplerTexture(unsigned int sampler, GLenum type) const;
GLuint getSamplerTextureId(unsigned int sampler, GLenum type) const;
- void detachTexture(const TextureMap &zeroTextures, GLuint texture);
- void initializeZeroTextures(const TextureMap &zeroTextures);
+ void detachTexture(const Context *context, const TextureMap &zeroTextures, GLuint texture);
+ void initializeZeroTextures(const Context *context, const TextureMap &zeroTextures);
// Sampler object binding manipulation
- void setSamplerBinding(GLuint textureUnit, Sampler *sampler);
+ void setSamplerBinding(const Context *context, GLuint textureUnit, Sampler *sampler);
GLuint getSamplerId(GLuint textureUnit) const;
Sampler *getSampler(GLuint textureUnit) const;
- void detachSampler(GLuint sampler);
+ void detachSampler(const Context *context, GLuint sampler);
// Renderbuffer binding manipulation
- void setRenderbufferBinding(Renderbuffer *renderbuffer);
+ void setRenderbufferBinding(const Context *context, Renderbuffer *renderbuffer);
GLuint getRenderbufferId() const;
- Renderbuffer *getCurrentRenderbuffer();
- void detachRenderbuffer(GLuint renderbuffer);
+ Renderbuffer *getCurrentRenderbuffer() const;
+ void detachRenderbuffer(const Context *context, GLuint renderbuffer);
// Framebuffer binding manipulation
void setReadFramebufferBinding(Framebuffer *framebuffer);
void setDrawFramebufferBinding(Framebuffer *framebuffer);
Framebuffer *getTargetFramebuffer(GLenum target) const;
- Framebuffer *getReadFramebuffer();
- Framebuffer *getDrawFramebuffer();
- const Framebuffer *getReadFramebuffer() const;
- const Framebuffer *getDrawFramebuffer() const;
+ Framebuffer *getReadFramebuffer() const;
+ Framebuffer *getDrawFramebuffer() const;
bool removeReadFramebufferBinding(GLuint framebuffer);
bool removeDrawFramebufferBinding(GLuint framebuffer);
@@ -185,55 +209,75 @@ class State : angle::NonCopyable
bool removeVertexArrayBinding(GLuint vertexArray);
// Program binding manipulation
- void setProgram(Program *newProgram);
+ void setProgram(const Context *context, Program *newProgram);
Program *getProgram() const;
// Transform feedback object (not buffer) binding manipulation
- void setTransformFeedbackBinding(TransformFeedback *transformFeedback);
+ void setTransformFeedbackBinding(const Context *context, TransformFeedback *transformFeedback);
TransformFeedback *getCurrentTransformFeedback() const;
bool isTransformFeedbackActiveUnpaused() const;
- void detachTransformFeedback(GLuint transformFeedback);
+ bool removeTransformFeedbackBinding(const Context *context, GLuint transformFeedback);
// Query binding manipulation
- bool isQueryActive() const;
+ bool isQueryActive(const GLenum type) const;
bool isQueryActive(Query *query) const;
- void setActiveQuery(GLenum target, Query *query);
+ void setActiveQuery(const Context *context, GLenum target, Query *query);
GLuint getActiveQueryId(GLenum target) const;
Query *getActiveQuery(GLenum target) const;
+ // Program Pipeline binding manipulation
+ void setProgramPipelineBinding(const Context *context, ProgramPipeline *pipeline);
+ void detachProgramPipeline(const Context *context, GLuint pipeline);
+
//// Typed buffer binding point manipulation ////
- // GL_ARRAY_BUFFER
- void setArrayBufferBinding(Buffer *buffer);
- GLuint getArrayBufferId() const;
+ void setBufferBinding(const Context *context, BufferBinding target, Buffer *buffer);
+ Buffer *getTargetBuffer(BufferBinding target) const;
+ void setIndexedBufferBinding(const Context *context,
+ BufferBinding target,
+ GLuint index,
+ Buffer *buffer,
+ GLintptr offset,
+ GLsizeiptr size);
- // GL_UNIFORM_BUFFER - Both indexed and generic targets
- void setGenericUniformBufferBinding(Buffer *buffer);
- void setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size);
const OffsetBindingPointer<Buffer> &getIndexedUniformBuffer(size_t index) const;
+ const OffsetBindingPointer<Buffer> &getIndexedAtomicCounterBuffer(size_t index) const;
+ const OffsetBindingPointer<Buffer> &getIndexedShaderStorageBuffer(size_t index) const;
- // GL_COPY_[READ/WRITE]_BUFFER
- void setCopyReadBufferBinding(Buffer *buffer);
- void setCopyWriteBufferBinding(Buffer *buffer);
-
- // GL_PIXEL[PACK/UNPACK]_BUFFER
- void setPixelPackBufferBinding(Buffer *buffer);
- void setPixelUnpackBufferBinding(Buffer *buffer);
-
- // Retrieve typed buffer by target (non-indexed)
- Buffer *getTargetBuffer(GLenum target) const;
// Detach a buffer from all bindings
- void detachBuffer(GLuint bufferName);
+ void detachBuffer(const Context *context, GLuint bufferName);
// Vertex attrib manipulation
void setEnableVertexAttribArray(unsigned int attribNum, bool enabled);
+ void setElementArrayBuffer(const Context *context, Buffer *buffer);
void setVertexAttribf(GLuint index, const GLfloat values[4]);
void setVertexAttribu(GLuint index, const GLuint values[4]);
void setVertexAttribi(GLuint index, const GLint values[4]);
- void setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type,
- bool normalized, bool pureInteger, GLsizei stride, const void *pointer);
- void setVertexAttribDivisor(GLuint index, GLuint divisor);
- const VertexAttribCurrentValueData &getVertexAttribCurrentValue(unsigned int attribNum) const;
+ void setVertexAttribPointer(const Context *context,
+ unsigned int attribNum,
+ Buffer *boundBuffer,
+ GLint size,
+ GLenum type,
+ bool normalized,
+ bool pureInteger,
+ GLsizei stride,
+ const void *pointer);
+ void setVertexAttribDivisor(const Context *context, GLuint index, GLuint divisor);
+ const VertexAttribCurrentValueData &getVertexAttribCurrentValue(size_t attribNum) const;
+ const std::vector<VertexAttribCurrentValueData> &getVertexAttribCurrentValues() const;
const void *getVertexAttribPointer(unsigned int attribNum) const;
+ void bindVertexBuffer(const Context *context,
+ GLuint bindingIndex,
+ Buffer *boundBuffer,
+ GLintptr offset,
+ GLsizei stride);
+ void setVertexAttribFormat(GLuint attribIndex,
+ GLint size,
+ GLenum type,
+ bool normalized,
+ bool pureInteger,
+ GLuint relativeOffset);
+ void setVertexAttribBinding(const Context *context, GLuint attribIndex, GLuint bindingIndex);
+ void setVertexBindingDivisor(GLuint bindingIndex, GLuint divisor);
// Pixel pack state manipulation
void setPackAlignment(GLint alignment);
@@ -269,15 +313,37 @@ class State : angle::NonCopyable
const Debug &getDebug() const;
Debug &getDebug();
+ // CHROMIUM_framebuffer_mixed_samples coverage modulation
+ void setCoverageModulation(GLenum components);
+ GLenum getCoverageModulation() const;
+
+ // CHROMIUM_path_rendering
+ void loadPathRenderingMatrix(GLenum matrixMode, const GLfloat *matrix);
+ const GLfloat *getPathRenderingMatrix(GLenum which) const;
+ void setPathStencilFunc(GLenum func, GLint ref, GLuint mask);
+
+ GLenum getPathStencilFunc() const;
+ GLint getPathStencilRef() const;
+ GLuint getPathStencilMask() const;
+
+ // GL_EXT_sRGB_write_control
+ void setFramebufferSRGB(bool sRGB);
+ bool getFramebufferSRGB() const;
+
// State query functions
void getBooleanv(GLenum pname, GLboolean *params);
void getFloatv(GLenum pname, GLfloat *params);
- void getIntegerv(const gl::Data &data, GLenum pname, GLint *params);
+ void getIntegerv(const Context *context, GLenum pname, GLint *params);
void getPointerv(GLenum pname, void **params) const;
- bool getIndexedIntegerv(GLenum target, GLuint index, GLint *data);
- bool getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data);
+ void getIntegeri_v(GLenum target, GLuint index, GLint *data);
+ void getInteger64i_v(GLenum target, GLuint index, GLint64 *data);
+ void getBooleani_v(GLenum target, GLuint index, GLboolean *data);
- bool hasMappedBuffer(GLenum target) const;
+ bool hasMappedBuffer(BufferBinding target) const;
+ bool isRobustResourceInitEnabled() const { return mRobustResourceInit; }
+
+ // Sets the dirty bit for the program executable.
+ void onProgramExecutableChange(Program *program);
enum DirtyBitType
{
@@ -293,6 +359,8 @@ class State : angle::NonCopyable
DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED,
DIRTY_BIT_SAMPLE_COVERAGE_ENABLED,
DIRTY_BIT_SAMPLE_COVERAGE,
+ DIRTY_BIT_SAMPLE_MASK_ENABLED,
+ DIRTY_BIT_SAMPLE_MASK,
DIRTY_BIT_DEPTH_TEST_ENABLED,
DIRTY_BIT_DEPTH_FUNC,
DIRTY_BIT_DEPTH_MASK,
@@ -314,17 +382,10 @@ class State : angle::NonCopyable
DIRTY_BIT_CLEAR_COLOR,
DIRTY_BIT_CLEAR_DEPTH,
DIRTY_BIT_CLEAR_STENCIL,
- DIRTY_BIT_UNPACK_ALIGNMENT,
- DIRTY_BIT_UNPACK_ROW_LENGTH,
- DIRTY_BIT_UNPACK_IMAGE_HEIGHT,
- DIRTY_BIT_UNPACK_SKIP_IMAGES,
- DIRTY_BIT_UNPACK_SKIP_ROWS,
- DIRTY_BIT_UNPACK_SKIP_PIXELS,
- DIRTY_BIT_PACK_ALIGNMENT,
- DIRTY_BIT_PACK_REVERSE_ROW_ORDER,
- DIRTY_BIT_PACK_ROW_LENGTH,
- DIRTY_BIT_PACK_SKIP_ROWS,
- DIRTY_BIT_PACK_SKIP_PIXELS,
+ DIRTY_BIT_UNPACK_STATE,
+ DIRTY_BIT_UNPACK_BUFFER_BINDING,
+ DIRTY_BIT_PACK_STATE,
+ DIRTY_BIT_PACK_BUFFER_BINDING,
DIRTY_BIT_DITHER_ENABLED,
DIRTY_BIT_GENERATE_MIPMAP_HINT,
DIRTY_BIT_SHADER_DERIVATIVE_HINT,
@@ -332,51 +393,83 @@ class State : angle::NonCopyable
DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING,
DIRTY_BIT_RENDERBUFFER_BINDING,
DIRTY_BIT_VERTEX_ARRAY_BINDING,
+ DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING,
DIRTY_BIT_PROGRAM_BINDING,
- DIRTY_BIT_CURRENT_VALUE_0,
- DIRTY_BIT_CURRENT_VALUE_MAX = DIRTY_BIT_CURRENT_VALUE_0 + MAX_VERTEX_ATTRIBS,
- DIRTY_BIT_INVALID = DIRTY_BIT_CURRENT_VALUE_MAX,
- DIRTY_BIT_MAX = DIRTY_BIT_INVALID,
+ DIRTY_BIT_PROGRAM_EXECUTABLE,
+ // TODO(jmadill): Fine-grained dirty bits for each texture/sampler.
+ DIRTY_BIT_TEXTURE_BINDINGS,
+ DIRTY_BIT_SAMPLER_BINDINGS,
+ DIRTY_BIT_MULTISAMPLING,
+ DIRTY_BIT_SAMPLE_ALPHA_TO_ONE,
+ DIRTY_BIT_COVERAGE_MODULATION, // CHROMIUM_framebuffer_mixed_samples
+ DIRTY_BIT_PATH_RENDERING_MATRIX_MV, // CHROMIUM_path_rendering path model view matrix
+ DIRTY_BIT_PATH_RENDERING_MATRIX_PROJ, // CHROMIUM_path_rendering path projection matrix
+ DIRTY_BIT_PATH_RENDERING_STENCIL_STATE,
+ DIRTY_BIT_FRAMEBUFFER_SRGB, // GL_EXT_sRGB_write_control
+ DIRTY_BIT_CURRENT_VALUES,
+ DIRTY_BIT_INVALID,
+ DIRTY_BIT_MAX = DIRTY_BIT_INVALID,
};
+ static_assert(DIRTY_BIT_MAX <= 64, "State dirty bits must be capped at 64");
+
// TODO(jmadill): Consider storing dirty objects in a list instead of by binding.
enum DirtyObjectType
{
DIRTY_OBJECT_READ_FRAMEBUFFER,
DIRTY_OBJECT_DRAW_FRAMEBUFFER,
DIRTY_OBJECT_VERTEX_ARRAY,
- DIRTY_OBJECT_PROGRAM,
+ // Use a very coarse bit for any program or texture change.
+ // TODO(jmadill): Fine-grained dirty bits for each texture/sampler.
+ DIRTY_OBJECT_PROGRAM_TEXTURES,
DIRTY_OBJECT_UNKNOWN,
DIRTY_OBJECT_MAX = DIRTY_OBJECT_UNKNOWN,
};
- typedef std::bitset<DIRTY_BIT_MAX> DirtyBits;
+ typedef angle::BitSet<DIRTY_BIT_MAX> DirtyBits;
const DirtyBits &getDirtyBits() const { return mDirtyBits; }
void clearDirtyBits() { mDirtyBits.reset(); }
void clearDirtyBits(const DirtyBits &bitset) { mDirtyBits &= ~bitset; }
void setAllDirtyBits() { mDirtyBits.set(); }
- typedef std::bitset<DIRTY_OBJECT_MAX> DirtyObjects;
+ typedef angle::BitSet<DIRTY_OBJECT_MAX> DirtyObjects;
void clearDirtyObjects() { mDirtyObjects.reset(); }
void setAllDirtyObjects() { mDirtyObjects.set(); }
- void syncDirtyObjects();
- void syncDirtyObjects(const DirtyObjects &bitset);
- void syncDirtyObject(GLenum target);
+ void syncDirtyObjects(const Context *context);
+ void syncDirtyObjects(const Context *context, const DirtyObjects &bitset);
+ void syncDirtyObject(const Context *context, GLenum target);
void setObjectDirty(GLenum target);
- // Dirty bit masks
- const DirtyBits &unpackStateBitMask() const { return mUnpackStateBitMask; }
- const DirtyBits &packStateBitMask() const { return mPackStateBitMask; }
- const DirtyBits &clearStateBitMask() const { return mClearStateBitMask; }
- const DirtyBits &blitStateBitMask() const { return mBlitStateBitMask; }
+ // This actually clears the current value dirty bits.
+ // TODO(jmadill): Pass mutable dirty bits into Impl.
+ AttributesMask getAndResetDirtyCurrentValues() const;
+
+ void setImageUnit(const Context *context,
+ GLuint unit,
+ Texture *texture,
+ GLint level,
+ GLboolean layered,
+ GLint layer,
+ GLenum access,
+ GLenum format);
+
+ const ImageUnit &getImageUnit(GLuint unit) const;
+ const std::vector<Texture *> &getCompleteTextureCache() const { return mCompleteTextureCache; }
+
+ // Handle a dirty texture event.
+ void signal(size_t textureIndex, InitState initState) override;
+
+ Error clearUnclearedActiveTextures(const Context *context);
private:
+ void syncProgramTextures(const Context *context);
+
// Cached values from Context's caps
GLuint mMaxDrawBuffers;
GLuint mMaxCombinedTextureImageUnits;
ColorF mColorClearValue;
- GLclampf mDepthClearValue;
+ GLfloat mDepthClearValue;
int mStencilClearValue;
RasterizerState mRasterizer;
@@ -386,8 +479,11 @@ class State : angle::NonCopyable
BlendState mBlend;
ColorF mBlendColor;
bool mSampleCoverage;
- GLclampf mSampleCoverageValue;
+ GLfloat mSampleCoverageValue;
bool mSampleCoverageInvert;
+ bool mSampleMask;
+ GLuint mMaxSampleMaskWords;
+ std::array<GLbitfield, MAX_SAMPLE_MASK_WORDS> mSampleMaskValues;
DepthStencilState mDepthStencil;
GLint mStencilRef;
@@ -398,59 +494,109 @@ class State : angle::NonCopyable
GLenum mGenerateMipmapHint;
GLenum mFragmentShaderDerivativeHint;
+ bool mBindGeneratesResource;
+ bool mClientArraysEnabled;
+
Rectangle mViewport;
float mNearZ;
float mFarZ;
- BindingPointer<Buffer> mArrayBuffer;
Framebuffer *mReadFramebuffer;
Framebuffer *mDrawFramebuffer;
BindingPointer<Renderbuffer> mRenderbuffer;
Program *mProgram;
+ BindingPointer<ProgramPipeline> mProgramPipeline;
typedef std::vector<VertexAttribCurrentValueData> VertexAttribVector;
- VertexAttribVector mVertexAttribCurrentValues; // From glVertexAttrib
+ VertexAttribVector mVertexAttribCurrentValues; // From glVertexAttrib
VertexArray *mVertexArray;
// Texture and sampler bindings
- size_t mActiveSampler; // Active texture unit selector - GL_TEXTURE0
+ size_t mActiveSampler; // Active texture unit selector - GL_TEXTURE0
typedef std::vector<BindingPointer<Texture>> TextureBindingVector;
typedef std::map<GLenum, TextureBindingVector> TextureBindingMap;
TextureBindingMap mSamplerTextures;
+ // Texture Completeness Caching
+ // ----------------------------
+ // The texture completeness cache uses dirty bits to avoid having to scan the list
+ // of textures each draw call. This gl::State class implements OnAttachmentDirtyReceiver,
+ // and keeps an array of bindings to the Texture class. When the Textures are marked dirty,
+ // they send messages to the State class (and any Framebuffers they're attached to) via the
+ // State::signal method (see above). Internally this then invalidates the completeness cache.
+ //
+ // Note this requires that we also invalidate the completeness cache manually on events like
+ // re-binding textures/samplers or a change in the program. For more information see the
+ // signal_utils.h header and the design doc linked there.
+
+ // A cache of complete textures. nullptr indicates unbound or incomplete.
+ // Don't use BindingPointer because this cache is only valid within a draw call.
+ // Also stores a notification channel to the texture itself to handle texture change events.
+ std::vector<Texture *> mCompleteTextureCache;
+ std::vector<OnAttachmentDirtyBinding> mCompleteTextureBindings;
+ InitState mCachedTexturesInitState;
+ using ActiveTextureMask = angle::BitSet<IMPLEMENTATION_MAX_ACTIVE_TEXTURES>;
+ ActiveTextureMask mActiveTexturesMask;
+
typedef std::vector<BindingPointer<Sampler>> SamplerBindingVector;
SamplerBindingVector mSamplers;
+ typedef std::vector<ImageUnit> ImageUnitVector;
+ ImageUnitVector mImageUnits;
+
typedef std::map<GLenum, BindingPointer<Query>> ActiveQueryMap;
ActiveQueryMap mActiveQueries;
- BindingPointer<Buffer> mGenericUniformBuffer;
- typedef std::vector<OffsetBindingPointer<Buffer>> BufferVector;
+ // Stores the currently bound buffer for each binding point. It has entries for the element
+ // array buffer and the transform feedback buffer but these should not be used. Instead these
+ // bind points are respectively owned by current the vertex array object and the current
+ // transform feedback object.
+ using BoundBufferMap = angle::PackedEnumMap<BufferBinding, BindingPointer<Buffer>>;
+ BoundBufferMap mBoundBuffers;
+
+ using BufferVector = std::vector<OffsetBindingPointer<Buffer>>;
BufferVector mUniformBuffers;
+ BufferVector mAtomicCounterBuffers;
+ BufferVector mShaderStorageBuffers;
BindingPointer<TransformFeedback> mTransformFeedback;
- BindingPointer<Buffer> mCopyReadBuffer;
- BindingPointer<Buffer> mCopyWriteBuffer;
-
+ BindingPointer<Buffer> mPixelUnpackBuffer;
PixelUnpackState mUnpack;
+ BindingPointer<Buffer> mPixelPackBuffer;
PixelPackState mPack;
bool mPrimitiveRestart;
Debug mDebug;
- DirtyBits mDirtyBits;
- DirtyBits mUnpackStateBitMask;
- DirtyBits mPackStateBitMask;
- DirtyBits mClearStateBitMask;
- DirtyBits mBlitStateBitMask;
+ bool mMultiSampling;
+ bool mSampleAlphaToOne;
+
+ GLenum mCoverageModulation;
+
+ // CHROMIUM_path_rendering
+ GLfloat mPathMatrixMV[16];
+ GLfloat mPathMatrixProj[16];
+ GLenum mPathStencilFunc;
+ GLint mPathStencilRef;
+ GLuint mPathStencilMask;
+
+ // GL_EXT_sRGB_write_control
+ bool mFramebufferSRGB;
+ // GL_ANGLE_robust_resource_intialization
+ bool mRobustResourceInit;
+
+ // GL_ANGLE_program_cache_control
+ bool mProgramBinaryCacheEnabled;
+
+ DirtyBits mDirtyBits;
DirtyObjects mDirtyObjects;
+ mutable AttributesMask mDirtyCurrentValues;
};
-}
-
-#endif // LIBANGLE_STATE_H_
+} // namespace gl
+#endif // LIBANGLE_STATE_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Stream.cpp b/src/3rdparty/angle/src/libANGLE/Stream.cpp
new file mode 100644
index 0000000000..68279976b7
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/Stream.cpp
@@ -0,0 +1,271 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Stream.cpp: Implements the egl::Stream class, representing the stream
+// where frames are streamed in. Implements EGLStreanKHR.
+
+#include "libANGLE/Stream.h"
+
+#include <platform/Platform.h>
+#include <EGL/eglext.h>
+
+#include "common/debug.h"
+#include "common/mathutil.h"
+#include "common/platform.h"
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/renderer/DisplayImpl.h"
+#include "libANGLE/renderer/StreamProducerImpl.h"
+
+namespace egl
+{
+
+Stream::Stream(Display *display, const AttributeMap &attribs)
+ : mDisplay(display),
+ mProducerImplementation(nullptr),
+ mState(EGL_STREAM_STATE_CREATED_KHR),
+ mProducerFrame(0),
+ mConsumerFrame(0),
+ mConsumerLatency(attribs.getAsInt(EGL_CONSUMER_LATENCY_USEC_KHR, 0)),
+ mConsumerAcquireTimeout(attribs.getAsInt(EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, 0)),
+ mPlaneCount(0),
+ mConsumerType(ConsumerType::NoConsumer),
+ mProducerType(ProducerType::NoProducer)
+{
+ for (auto &plane : mPlanes)
+ {
+ plane.textureUnit = -1;
+ plane.texture = nullptr;
+ }
+}
+
+Stream::~Stream()
+{
+ SafeDelete(mProducerImplementation);
+ for (auto &plane : mPlanes)
+ {
+ if (plane.texture != nullptr)
+ {
+ plane.texture->releaseStream();
+ }
+ }
+}
+
+void Stream::setConsumerLatency(EGLint latency)
+{
+ mConsumerLatency = latency;
+}
+
+EGLint Stream::getConsumerLatency() const
+{
+ return mConsumerLatency;
+}
+
+EGLuint64KHR Stream::getProducerFrame() const
+{
+ return mProducerFrame;
+}
+
+EGLuint64KHR Stream::getConsumerFrame() const
+{
+ return mConsumerFrame;
+}
+
+EGLenum Stream::getState() const
+{
+ return mState;
+}
+
+void Stream::setConsumerAcquireTimeout(EGLint timeout)
+{
+ mConsumerAcquireTimeout = timeout;
+}
+
+EGLint Stream::getConsumerAcquireTimeout() const
+{
+ return mConsumerAcquireTimeout;
+}
+
+Stream::ProducerType Stream::getProducerType() const
+{
+ return mProducerType;
+}
+
+Stream::ConsumerType Stream::getConsumerType() const
+{
+ return mConsumerType;
+}
+
+EGLint Stream::getPlaneCount() const
+{
+ return mPlaneCount;
+}
+
+rx::StreamProducerImpl *Stream::getImplementation()
+{
+ return mProducerImplementation;
+}
+
+Error Stream::createConsumerGLTextureExternal(const AttributeMap &attributes, gl::Context *context)
+{
+ ASSERT(mState == EGL_STREAM_STATE_CREATED_KHR);
+ ASSERT(mConsumerType == ConsumerType::NoConsumer);
+ ASSERT(mProducerType == ProducerType::NoProducer);
+ ASSERT(context != nullptr);
+
+ const auto &glState = context->getGLState();
+ EGLenum bufferType = attributes.getAsInt(EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER);
+ if (bufferType == EGL_RGB_BUFFER)
+ {
+ mPlanes[0].texture = glState.getTargetTexture(GL_TEXTURE_EXTERNAL_OES);
+ ASSERT(mPlanes[0].texture != nullptr);
+ mPlanes[0].texture->bindStream(this);
+ mConsumerType = ConsumerType::GLTextureRGB;
+ mPlaneCount = 1;
+ }
+ else
+ {
+ mPlaneCount = attributes.getAsInt(EGL_YUV_NUMBER_OF_PLANES_EXT, 2);
+ ASSERT(mPlaneCount <= 3);
+ for (EGLint i = 0; i < mPlaneCount; i++)
+ {
+ // Fetch all the textures
+ mPlanes[i].textureUnit = attributes.getAsInt(EGL_YUV_PLANE0_TEXTURE_UNIT_NV + i, -1);
+ if (mPlanes[i].textureUnit != EGL_NONE)
+ {
+ mPlanes[i].texture =
+ glState.getSamplerTexture(mPlanes[i].textureUnit, GL_TEXTURE_EXTERNAL_OES);
+ ASSERT(mPlanes[i].texture != nullptr);
+ }
+ }
+
+ // Bind them to the stream
+ for (EGLint i = 0; i < mPlaneCount; i++)
+ {
+ if (mPlanes[i].textureUnit != EGL_NONE)
+ {
+ mPlanes[i].texture->bindStream(this);
+ }
+ }
+ mConsumerType = ConsumerType::GLTextureYUV;
+ }
+
+ mContext = context;
+ mState = EGL_STREAM_STATE_CONNECTING_KHR;
+
+ return NoError();
+}
+
+Error Stream::createProducerD3D11TextureNV12(const AttributeMap &attributes)
+{
+ ASSERT(mState == EGL_STREAM_STATE_CONNECTING_KHR);
+ ASSERT(mConsumerType == ConsumerType::GLTextureYUV);
+ ASSERT(mProducerType == ProducerType::NoProducer);
+ ASSERT(mPlaneCount == 2);
+
+ mProducerImplementation = mDisplay->getImplementation()->createStreamProducerD3DTextureNV12(
+ mConsumerType, attributes);
+ mProducerType = ProducerType::D3D11TextureNV12;
+ mState = EGL_STREAM_STATE_EMPTY_KHR;
+
+ return NoError();
+}
+
+// Called when the consumer of this stream starts using the stream
+Error Stream::consumerAcquire(const gl::Context *context)
+{
+ ASSERT(mState == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR ||
+ mState == EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR);
+ ASSERT(mConsumerType == ConsumerType::GLTextureRGB ||
+ mConsumerType == ConsumerType::GLTextureYUV);
+ ASSERT(mProducerType == ProducerType::D3D11TextureNV12);
+
+ mState = EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR;
+ mConsumerFrame++;
+
+ // Bind the planes to the gl textures
+ for (int i = 0; i < mPlaneCount; i++)
+ {
+ if (mPlanes[i].texture != nullptr)
+ {
+ ANGLE_TRY(mPlanes[i].texture->acquireImageFromStream(
+ context, mProducerImplementation->getGLFrameDescription(i)));
+ }
+ }
+
+ return NoError();
+}
+
+Error Stream::consumerRelease(const gl::Context *context)
+{
+ ASSERT(mState == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR ||
+ mState == EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR);
+ ASSERT(mConsumerType == ConsumerType::GLTextureRGB ||
+ mConsumerType == ConsumerType::GLTextureYUV);
+ ASSERT(mProducerType == ProducerType::D3D11TextureNV12);
+
+ // Release the images
+ for (int i = 0; i < mPlaneCount; i++)
+ {
+ if (mPlanes[i].texture != nullptr)
+ {
+ ANGLE_TRY(mPlanes[i].texture->releaseImageFromStream(context));
+ }
+ }
+
+ return NoError();
+}
+
+bool Stream::isConsumerBoundToContext(const gl::Context *context) const
+{
+ ASSERT(context != nullptr);
+ return (context == mContext);
+}
+
+Error Stream::validateD3D11NV12Texture(void *texture) const
+{
+ ASSERT(mConsumerType == ConsumerType::GLTextureRGB ||
+ mConsumerType == ConsumerType::GLTextureYUV);
+ ASSERT(mProducerType == ProducerType::D3D11TextureNV12);
+ ASSERT(mProducerImplementation != nullptr);
+
+ return mProducerImplementation->validateD3DNV12Texture(texture);
+}
+
+Error Stream::postD3D11NV12Texture(void *texture, const AttributeMap &attributes)
+{
+ ASSERT(mConsumerType == ConsumerType::GLTextureRGB ||
+ mConsumerType == ConsumerType::GLTextureYUV);
+ ASSERT(mProducerType == ProducerType::D3D11TextureNV12);
+
+ mProducerImplementation->postD3DNV12Texture(texture, attributes);
+ mProducerFrame++;
+
+ mState = EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR;
+
+ return NoError();
+}
+
+// This is called when a texture object associated with this stream is destroyed. Even if multiple
+// textures are bound, one being destroyed invalidates the stream, so all the remaining textures
+// will be released and the stream will be invalidated.
+void Stream::releaseTextures()
+{
+ for (auto &plane : mPlanes)
+ {
+ if (plane.texture != nullptr)
+ {
+ plane.texture->releaseStream();
+ plane.texture = nullptr;
+ }
+ }
+ mConsumerType = ConsumerType::NoConsumer;
+ mProducerType = ProducerType::NoProducer;
+ mState = EGL_STREAM_STATE_DISCONNECTED_KHR;
+}
+
+} // namespace egl
diff --git a/src/3rdparty/angle/src/libANGLE/Stream.h b/src/3rdparty/angle/src/libANGLE/Stream.h
new file mode 100644
index 0000000000..b674c44008
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/Stream.h
@@ -0,0 +1,143 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Stream.h: Defines the egl::Stream class, representing the stream
+// where frames are streamed in. Implements EGLStreanKHR.
+
+#ifndef LIBANGLE_STREAM_H_
+#define LIBANGLE_STREAM_H_
+
+#include <array>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "common/angleutils.h"
+#include "libANGLE/AttributeMap.h"
+
+namespace rx
+{
+class StreamProducerImpl;
+}
+
+namespace gl
+{
+class Context;
+class Texture;
+}
+
+namespace egl
+{
+class Display;
+class Error;
+class Thread;
+
+class Stream final : angle::NonCopyable
+{
+ public:
+ Stream(Display *display, const AttributeMap &attribs);
+ ~Stream();
+
+ enum class ConsumerType
+ {
+ NoConsumer,
+ GLTextureRGB,
+ GLTextureYUV,
+ };
+
+ enum class ProducerType
+ {
+ NoProducer,
+ D3D11TextureNV12,
+ };
+
+ // A GL texture interpretation of a part of a producer frame. For use with GL texture consumers
+ struct GLTextureDescription
+ {
+ unsigned int width;
+ unsigned int height;
+ unsigned int internalFormat;
+ unsigned int mipLevels;
+ };
+
+ EGLenum getState() const;
+
+ void setConsumerLatency(EGLint latency);
+ EGLint getConsumerLatency() const;
+
+ EGLuint64KHR getProducerFrame() const;
+ EGLuint64KHR getConsumerFrame() const;
+
+ void setConsumerAcquireTimeout(EGLint timeout);
+ EGLint getConsumerAcquireTimeout() const;
+
+ ConsumerType getConsumerType() const;
+ ProducerType getProducerType() const;
+
+ EGLint getPlaneCount() const;
+
+ rx::StreamProducerImpl *getImplementation();
+
+ // Consumer creation methods
+ Error createConsumerGLTextureExternal(const AttributeMap &attributes, gl::Context *context);
+
+ // Producer creation methods
+ Error createProducerD3D11TextureNV12(const AttributeMap &attributes);
+
+ // Consumer methods
+ Error consumerAcquire(const gl::Context *context);
+ Error consumerRelease(const gl::Context *context);
+
+ // Some consumers are bound to GL contexts. This validates that a given context is bound to the
+ // stream's consumer
+ bool isConsumerBoundToContext(const gl::Context *context) const;
+
+ // Producer methods
+ Error validateD3D11NV12Texture(void *texture) const;
+ Error postD3D11NV12Texture(void *texture, const AttributeMap &attributes);
+
+ private:
+ // Associated display
+ Display *mDisplay;
+
+ // Producer Implementation
+ rx::StreamProducerImpl *mProducerImplementation;
+
+ // Associated GL context. Note that this is a weak pointer used for validation purposes only,
+ // and should never be arbitrarily dereferenced without knowing the context still exists as it
+ // can become dangling at any time.
+ gl::Context *mContext;
+
+ // EGL defined attributes
+ EGLint mState;
+ EGLuint64KHR mProducerFrame;
+ EGLuint64KHR mConsumerFrame;
+ EGLint mConsumerLatency;
+
+ // EGL gltexture consumer attributes
+ EGLint mConsumerAcquireTimeout;
+
+ // EGL gltexture yuv consumer attributes
+ EGLint mPlaneCount;
+ struct PlaneTexture
+ {
+ EGLint textureUnit;
+ gl::Texture *texture;
+ };
+ // Texture units and textures for all the planes
+ std::array<PlaneTexture, 3> mPlanes;
+
+ // Consumer and producer types
+ ConsumerType mConsumerType;
+ ProducerType mProducerType;
+
+ // ANGLE-only method, used internally
+ friend class gl::Texture;
+ void releaseTextures();
+};
+} // namespace egl
+
+#endif // LIBANGLE_STREAM_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Surface.cpp b/src/3rdparty/angle/src/libANGLE/Surface.cpp
index b5ed0ff5a6..746da03778 100644
--- a/src/3rdparty/angle/src/libANGLE/Surface.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Surface.cpp
@@ -10,29 +10,44 @@
#include "libANGLE/Surface.h"
-#include "libANGLE/Config.h"
-#include "libANGLE/Framebuffer.h"
-#include "libANGLE/Texture.h"
-
#include <EGL/eglext.h>
#include <iostream>
+#include "libANGLE/Config.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Thread.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/EGLImplFactory.h"
+
namespace egl
{
-Surface::Surface(rx::SurfaceImpl *impl,
- EGLint surfaceType,
- const egl::Config *config,
- const AttributeMap &attributes)
+SurfaceState::SurfaceState(const egl::Config *configIn, const AttributeMap &attributesIn)
+ : defaultFramebuffer(nullptr), config(configIn), attributes(attributesIn)
+{
+}
+
+Surface::Surface(EGLint surfaceType, const egl::Config *config, const AttributeMap &attributes)
: FramebufferAttachmentObject(),
- mImplementation(impl),
- mDefaultFramebuffer(nullptr),
+ mState(config, attributes),
+ mImplementation(nullptr),
mCurrentCount(0),
mDestroyed(false),
mType(surfaceType),
- mConfig(config),
mPostSubBufferRequested(false),
+ mLargestPbuffer(false),
+ mGLColorspace(EGL_GL_COLORSPACE_LINEAR),
+ mVGAlphaFormat(EGL_VG_ALPHA_FORMAT_NONPRE),
+ mVGColorspace(EGL_VG_COLORSPACE_sRGB),
+ mMipmapTexture(false),
+ mMipmapLevel(0),
+ mHorizontalResolution(EGL_UNKNOWN),
+ mVerticalResolution(EGL_UNKNOWN),
+ mMultisampleResolve(EGL_MULTISAMPLE_RESOLVE_DEFAULT),
mFixedSize(false),
mFixedWidth(0),
mFixedHeight(0),
@@ -41,75 +56,135 @@ Surface::Surface(rx::SurfaceImpl *impl,
// FIXME: Determine actual pixel aspect ratio
mPixelAspectRatio(static_cast<EGLint>(1.0 * EGL_DISPLAY_SCALING)),
mRenderBuffer(EGL_BACK_BUFFER),
- mSwapBehavior(impl->getSwapBehavior()),
+ mSwapBehavior(EGL_NONE),
mOrientation(0),
- mTexture()
+ mTexture(),
+ mBackFormat(config->renderTargetFormat),
+ mDSFormat(config->depthStencilFormat)
{
mPostSubBufferRequested = (attributes.get(EGL_POST_SUB_BUFFER_SUPPORTED_NV, EGL_FALSE) == EGL_TRUE);
mFlexibleSurfaceCompatibilityRequested =
(attributes.get(EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, EGL_FALSE) == EGL_TRUE);
+ if (mType == EGL_PBUFFER_BIT)
+ {
+ mLargestPbuffer = (attributes.get(EGL_LARGEST_PBUFFER, EGL_FALSE) == EGL_TRUE);
+ }
+
+ mGLColorspace =
+ static_cast<EGLenum>(attributes.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_LINEAR));
+ mVGAlphaFormat =
+ static_cast<EGLenum>(attributes.get(EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_NONPRE));
+ mVGColorspace = static_cast<EGLenum>(attributes.get(EGL_VG_COLORSPACE, EGL_VG_COLORSPACE_sRGB));
+ mMipmapTexture = (attributes.get(EGL_MIPMAP_TEXTURE, EGL_FALSE) == EGL_TRUE);
+
mDirectComposition = (attributes.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE);
+ mRobustResourceInitialization =
+ (attributes.get(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, EGL_FALSE) == EGL_TRUE);
+
mFixedSize = (attributes.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE) == EGL_TRUE);
if (mFixedSize)
{
- mFixedWidth = attributes.get(EGL_WIDTH, 0);
- mFixedHeight = attributes.get(EGL_HEIGHT, 0);
+ mFixedWidth = static_cast<size_t>(attributes.get(EGL_WIDTH, 0));
+ mFixedHeight = static_cast<size_t>(attributes.get(EGL_HEIGHT, 0));
}
if (mType != EGL_WINDOW_BIT)
{
- mTextureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
- mTextureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
+ mTextureFormat = static_cast<EGLenum>(attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE));
+ mTextureTarget = static_cast<EGLenum>(attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE));
}
- mOrientation = attributes.get(EGL_SURFACE_ORIENTATION_ANGLE, 0);
-
- mDefaultFramebuffer = createDefaultFramebuffer();
- ASSERT(mDefaultFramebuffer != nullptr);
+ mOrientation = static_cast<EGLint>(attributes.get(EGL_SURFACE_ORIENTATION_ANGLE, 0));
}
Surface::~Surface()
{
+}
+
+rx::FramebufferAttachmentObjectImpl *Surface::getAttachmentImpl() const
+{
+ return mImplementation;
+}
+
+Error Surface::destroyImpl(const Display *display)
+{
+ if (mState.defaultFramebuffer)
+ {
+ mState.defaultFramebuffer->destroyDefault(display);
+ }
+ if (mImplementation)
+ {
+ mImplementation->destroy(display);
+ }
+
if (mTexture.get())
{
if (mImplementation)
{
- mImplementation->releaseTexImage(EGL_BACK_BUFFER);
+ ANGLE_TRY(mImplementation->releaseTexImage(EGL_BACK_BUFFER));
}
- mTexture->releaseTexImageFromSurface();
- mTexture.set(nullptr);
+ auto glErr = mTexture->releaseTexImageFromSurface(display->getProxyContext());
+ if (glErr.isError())
+ {
+ return Error(EGL_BAD_SURFACE);
+ }
+ mTexture.set(nullptr, nullptr);
}
- SafeDelete(mDefaultFramebuffer);
+ if (mState.defaultFramebuffer)
+ {
+ mState.defaultFramebuffer->onDestroy(display->getProxyContext());
+ }
+ SafeDelete(mState.defaultFramebuffer);
SafeDelete(mImplementation);
+
+ delete this;
+ return NoError();
+}
+
+Error Surface::initialize(const Display *display)
+{
+ ANGLE_TRY(mImplementation->initialize(display));
+
+ // Initialized here since impl is nullptr in the constructor.
+ // Must happen after implementation initialize for Android.
+ mSwapBehavior = mImplementation->getSwapBehavior();
+
+ // Must happen after implementation initialize for OSX.
+ mState.defaultFramebuffer = createDefaultFramebuffer(display);
+ ASSERT(mState.defaultFramebuffer != nullptr);
+
+ return NoError();
}
-void Surface::setIsCurrent(bool isCurrent)
+Error Surface::setIsCurrent(const gl::Context *context, bool isCurrent)
{
if (isCurrent)
{
mCurrentCount++;
+ return NoError();
}
- else
+
+ ASSERT(mCurrentCount > 0);
+ mCurrentCount--;
+ if (mCurrentCount == 0 && mDestroyed)
{
- ASSERT(mCurrentCount > 0);
- mCurrentCount--;
- if (mCurrentCount == 0 && mDestroyed)
- {
- delete this;
- }
+ ASSERT(context);
+ return destroyImpl(context->getCurrentDisplay());
}
+ return NoError();
}
-void Surface::onDestroy()
+Error Surface::onDestroy(const Display *display)
{
mDestroyed = true;
if (mCurrentCount == 0)
{
- delete this;
+ return destroyImpl(display);
}
+ return NoError();
}
EGLint Surface::getType() const
@@ -117,14 +192,23 @@ EGLint Surface::getType() const
return mType;
}
-Error Surface::swap()
+Error Surface::swap(const gl::Context *context)
+{
+ return mImplementation->swap(context);
+}
+
+Error Surface::swapWithDamage(const gl::Context *context, EGLint *rects, EGLint n_rects)
{
- return mImplementation->swap();
+ return mImplementation->swapWithDamage(context, rects, n_rects);
}
-Error Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+Error Surface::postSubBuffer(const gl::Context *context,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height)
{
- return mImplementation->postSubBuffer(x, y, width, height);
+ return mImplementation->postSubBuffer(context, x, y, width, height);
}
Error Surface::querySurfacePointerANGLE(EGLint attribute, void **value)
@@ -142,9 +226,30 @@ void Surface::setSwapInterval(EGLint interval)
mImplementation->setSwapInterval(interval);
}
+void Surface::setMipmapLevel(EGLint level)
+{
+ // Level is set but ignored
+ UNIMPLEMENTED();
+ mMipmapLevel = level;
+}
+
+void Surface::setMultisampleResolve(EGLenum resolve)
+{
+ // Behaviour is set but ignored
+ UNIMPLEMENTED();
+ mMultisampleResolve = resolve;
+}
+
+void Surface::setSwapBehavior(EGLenum behavior)
+{
+ // Behaviour is set but ignored
+ UNIMPLEMENTED();
+ mSwapBehavior = behavior;
+}
+
const Config *Surface::getConfig() const
{
- return mConfig;
+ return mState.config;
}
EGLint Surface::getPixelAspectRatio() const
@@ -172,6 +277,51 @@ EGLenum Surface::getTextureTarget() const
return mTextureTarget;
}
+bool Surface::getLargestPbuffer() const
+{
+ return mLargestPbuffer;
+}
+
+EGLenum Surface::getGLColorspace() const
+{
+ return mGLColorspace;
+}
+
+EGLenum Surface::getVGAlphaFormat() const
+{
+ return mVGAlphaFormat;
+}
+
+EGLenum Surface::getVGColorspace() const
+{
+ return mVGColorspace;
+}
+
+bool Surface::getMipmapTexture() const
+{
+ return mMipmapTexture;
+}
+
+EGLint Surface::getMipmapLevel() const
+{
+ return mMipmapLevel;
+}
+
+EGLint Surface::getHorizontalResolution() const
+{
+ return mHorizontalResolution;
+}
+
+EGLint Surface::getVerticalResolution() const
+{
+ return mVerticalResolution;
+}
+
+EGLenum Surface::getMultisampleResolve() const
+{
+ return mMultisampleResolve;
+}
+
EGLint Surface::isFixedSize() const
{
return mFixedSize;
@@ -187,42 +337,60 @@ EGLint Surface::getHeight() const
return mFixedSize ? static_cast<EGLint>(mFixedHeight) : mImplementation->getHeight();
}
-Error Surface::bindTexImage(gl::Texture *texture, EGLint buffer)
+Error Surface::bindTexImage(const gl::Context *context, gl::Texture *texture, EGLint buffer)
{
ASSERT(!mTexture.get());
+ ANGLE_TRY(mImplementation->bindTexImage(texture, buffer));
+
+ auto glErr = texture->bindTexImageFromSurface(context, this);
+ if (glErr.isError())
+ {
+ return Error(EGL_BAD_SURFACE);
+ }
+ mTexture.set(context, texture);
- texture->bindTexImageFromSurface(this);
- mTexture.set(texture);
- return mImplementation->bindTexImage(texture, buffer);
+ return NoError();
}
-Error Surface::releaseTexImage(EGLint buffer)
+Error Surface::releaseTexImage(const gl::Context *context, EGLint buffer)
{
+ ASSERT(context);
+
+ ANGLE_TRY(mImplementation->releaseTexImage(buffer));
+
ASSERT(mTexture.get());
- mTexture->releaseTexImageFromSurface();
- mTexture.set(nullptr);
+ auto glErr = mTexture->releaseTexImageFromSurface(context);
+ if (glErr.isError())
+ {
+ return Error(EGL_BAD_SURFACE);
+ }
+ mTexture.set(context, nullptr);
- return mImplementation->releaseTexImage(buffer);
+ return NoError();
}
-void Surface::releaseTexImageFromTexture()
+Error Surface::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
+{
+ return mImplementation->getSyncValues(ust, msc, sbc);
+}
+
+void Surface::releaseTexImageFromTexture(const gl::Context *context)
{
ASSERT(mTexture.get());
- mTexture.set(nullptr);
+ mTexture.set(context, nullptr);
}
-gl::Extents Surface::getAttachmentSize(const gl::FramebufferAttachment::Target & /*target*/) const
+gl::Extents Surface::getAttachmentSize(const gl::ImageIndex & /*target*/) const
{
return gl::Extents(getWidth(), getHeight(), 1);
}
-GLenum Surface::getAttachmentInternalFormat(const gl::FramebufferAttachment::Target &target) const
+const gl::Format &Surface::getAttachmentFormat(GLenum binding, const gl::ImageIndex &target) const
{
- const egl::Config *config = getConfig();
- return (target.binding() == GL_BACK ? config->renderTargetFormat : config->depthStencilFormat);
+ return (binding == GL_BACK ? mBackFormat : mDSFormat);
}
-GLsizei Surface::getAttachmentSamples(const gl::FramebufferAttachment::Target &target) const
+GLsizei Surface::getAttachmentSamples(const gl::ImageIndex &target) const
{
return getConfig()->samples;
}
@@ -233,29 +401,84 @@ GLuint Surface::getId() const
return 0;
}
-gl::Framebuffer *Surface::createDefaultFramebuffer()
+gl::Framebuffer *Surface::createDefaultFramebuffer(const Display *display)
{
- gl::Framebuffer *framebuffer = new gl::Framebuffer(mImplementation);
+ return new gl::Framebuffer(display, this);
+}
- GLenum drawBufferState = GL_BACK;
- framebuffer->setDrawBuffers(1, &drawBufferState);
- framebuffer->setReadBuffer(GL_BACK);
+gl::InitState Surface::initState(const gl::ImageIndex & /*imageIndex*/) const
+{
+ // TODO(jmadill): Lazy surface init.
+ return gl::InitState::Initialized;
+}
- framebuffer->setAttachment(GL_FRAMEBUFFER_DEFAULT, GL_BACK, gl::ImageIndex::MakeInvalid(),
- this);
+void Surface::setInitState(const gl::ImageIndex & /*imageIndex*/, gl::InitState /*initState*/)
+{
+ // No-op.
+}
- if (mConfig->depthSize > 0)
- {
- framebuffer->setAttachment(GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, gl::ImageIndex::MakeInvalid(),
- this);
- }
+WindowSurface::WindowSurface(rx::EGLImplFactory *implFactory,
+ const egl::Config *config,
+ EGLNativeWindowType window,
+ const AttributeMap &attribs)
+ : Surface(EGL_WINDOW_BIT, config, attribs)
+{
+ mImplementation = implFactory->createWindowSurface(mState, window, attribs);
+}
- if (mConfig->stencilSize > 0)
- {
- framebuffer->setAttachment(GL_FRAMEBUFFER_DEFAULT, GL_STENCIL,
- gl::ImageIndex::MakeInvalid(), this);
- }
+WindowSurface::~WindowSurface()
+{
+}
- return framebuffer;
+PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
+ const Config *config,
+ const AttributeMap &attribs)
+ : Surface(EGL_PBUFFER_BIT, config, attribs)
+{
+ mImplementation = implFactory->createPbufferSurface(mState, attribs);
+}
+
+PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
+ const Config *config,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const AttributeMap &attribs)
+ : Surface(EGL_PBUFFER_BIT, config, attribs)
+{
+ mImplementation =
+ implFactory->createPbufferFromClientBuffer(mState, buftype, clientBuffer, attribs);
}
+
+PbufferSurface::~PbufferSurface()
+{
}
+
+PixmapSurface::PixmapSurface(rx::EGLImplFactory *implFactory,
+ const Config *config,
+ NativePixmapType nativePixmap,
+ const AttributeMap &attribs)
+ : Surface(EGL_PIXMAP_BIT, config, attribs)
+{
+ mImplementation = implFactory->createPixmapSurface(mState, nativePixmap, attribs);
+}
+
+PixmapSurface::~PixmapSurface()
+{
+}
+
+// SurfaceDeleter implementation.
+
+SurfaceDeleter::SurfaceDeleter(const Display *display) : mDisplay(display)
+{
+}
+
+SurfaceDeleter::~SurfaceDeleter()
+{
+}
+
+void SurfaceDeleter::operator()(Surface *surface)
+{
+ ANGLE_SWALLOW_ERR(surface->onDestroy(mDisplay));
+}
+
+} // namespace egl
diff --git a/src/3rdparty/angle/src/libANGLE/Surface.h b/src/3rdparty/angle/src/libANGLE/Surface.h
index e110f5da7b..b3188ff909 100644
--- a/src/3rdparty/angle/src/libANGLE/Surface.h
+++ b/src/3rdparty/angle/src/libANGLE/Surface.h
@@ -14,9 +14,11 @@
#include <EGL/egl.h>
#include "common/angleutils.h"
+#include "libANGLE/AttributeMap.h"
#include "libANGLE/Error.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/RefCountObject.h"
+#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/SurfaceImpl.h"
namespace gl
@@ -25,33 +27,55 @@ class Framebuffer;
class Texture;
}
+namespace rx
+{
+class EGLImplFactory;
+}
+
namespace egl
{
-class AttributeMap;
class Display;
struct Config;
-class Surface final : public gl::FramebufferAttachmentObject
+struct SurfaceState final : private angle::NonCopyable
{
- public:
- Surface(rx::SurfaceImpl *impl, EGLint surfaceType, const egl::Config *config, const AttributeMap &attributes);
+ SurfaceState(const egl::Config *configIn, const AttributeMap &attributesIn);
+
+ gl::Framebuffer *defaultFramebuffer;
+ const egl::Config *config;
+ AttributeMap attributes;
+};
- rx::SurfaceImpl *getImplementation() { return mImplementation; }
- const rx::SurfaceImpl *getImplementation() const { return mImplementation; }
+class Surface : public gl::FramebufferAttachmentObject
+{
+ public:
+ rx::SurfaceImpl *getImplementation() const { return mImplementation; }
EGLint getType() const;
- Error swap();
- Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height);
+ Error initialize(const Display *display);
+ Error swap(const gl::Context *context);
+ Error swapWithDamage(const gl::Context *context, EGLint *rects, EGLint n_rects);
+ Error postSubBuffer(const gl::Context *context,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height);
Error querySurfacePointerANGLE(EGLint attribute, void **value);
- Error bindTexImage(gl::Texture *texture, EGLint buffer);
- Error releaseTexImage(EGLint buffer);
+ Error bindTexImage(const gl::Context *context, gl::Texture *texture, EGLint buffer);
+ Error releaseTexImage(const gl::Context *context, EGLint buffer);
+
+ Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc);
EGLint isPostSubBufferSupported() const;
void setSwapInterval(EGLint interval);
- void setIsCurrent(bool isCurrent);
- void onDestroy();
+ Error setIsCurrent(const gl::Context *context, bool isCurrent);
+ Error onDestroy(const Display *display);
+
+ void setMipmapLevel(EGLint level);
+ void setMultisampleResolve(EGLenum resolve);
+ void setSwapBehavior(EGLenum behavior);
const Config *getConfig() const;
@@ -63,19 +87,29 @@ class Surface final : public gl::FramebufferAttachmentObject
EGLenum getSwapBehavior() const;
EGLenum getTextureFormat() const;
EGLenum getTextureTarget() const;
+ bool getLargestPbuffer() const;
+ EGLenum getGLColorspace() const;
+ EGLenum getVGAlphaFormat() const;
+ EGLenum getVGColorspace() const;
+ bool getMipmapTexture() const;
+ EGLint getMipmapLevel() const;
+ EGLint getHorizontalResolution() const;
+ EGLint getVerticalResolution() const;
+ EGLenum getMultisampleResolve() const;
gl::Texture *getBoundTexture() const { return mTexture.get(); }
- gl::Framebuffer *getDefaultFramebuffer() { return mDefaultFramebuffer; }
+ gl::Framebuffer *getDefaultFramebuffer() { return mState.defaultFramebuffer; }
EGLint isFixedSize() const;
// FramebufferAttachmentObject implementation
- gl::Extents getAttachmentSize(const gl::FramebufferAttachment::Target &target) const override;
- GLenum getAttachmentInternalFormat(const gl::FramebufferAttachment::Target &target) const override;
- GLsizei getAttachmentSamples(const gl::FramebufferAttachment::Target &target) const override;
+ gl::Extents getAttachmentSize(const gl::ImageIndex &imageIndex) const override;
+ const gl::Format &getAttachmentFormat(GLenum binding,
+ const gl::ImageIndex &imageIndex) const override;
+ GLsizei getAttachmentSamples(const gl::ImageIndex &imageIndex) const override;
- void onAttach() override {}
- void onDetach() override {}
+ void onAttach(const gl::Context *context) override {}
+ void onDetach(const gl::Context *context) override {}
GLuint getId() const override;
bool flexibleSurfaceCompatibilityRequested() const
@@ -86,34 +120,50 @@ class Surface final : public gl::FramebufferAttachmentObject
bool directComposition() const { return mDirectComposition; }
- private:
- virtual ~Surface();
- rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override { return mImplementation; }
+ gl::InitState initState(const gl::ImageIndex &imageIndex) const override;
+ void setInitState(const gl::ImageIndex &imageIndex, gl::InitState initState) override;
+
+ bool isRobustResourceInitEnabled() const { return mRobustResourceInitialization; }
+
+ protected:
+ Surface(EGLint surfaceType, const egl::Config *config, const AttributeMap &attributes);
+ ~Surface() override;
+ rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override;
- gl::Framebuffer *createDefaultFramebuffer();
+ gl::Framebuffer *createDefaultFramebuffer(const Display *display);
// ANGLE-only method, used internally
friend class gl::Texture;
- void releaseTexImageFromTexture();
+ void releaseTexImageFromTexture(const gl::Context *context);
+ SurfaceState mState;
rx::SurfaceImpl *mImplementation;
- gl::Framebuffer *mDefaultFramebuffer;
int mCurrentCount;
bool mDestroyed;
EGLint mType;
- const egl::Config *mConfig;
-
bool mPostSubBufferRequested;
bool mFlexibleSurfaceCompatibilityRequested;
+ bool mLargestPbuffer;
+ EGLenum mGLColorspace;
+ EGLenum mVGAlphaFormat;
+ EGLenum mVGColorspace;
+ bool mMipmapTexture;
+ EGLint mMipmapLevel;
+ EGLint mHorizontalResolution;
+ EGLint mVerticalResolution;
+ EGLenum mMultisampleResolve;
+
bool mFixedSize;
size_t mFixedWidth;
size_t mFixedHeight;
bool mDirectComposition;
+ bool mRobustResourceInitialization;
+
EGLenum mTextureFormat;
EGLenum mTextureTarget;
@@ -123,9 +173,66 @@ class Surface final : public gl::FramebufferAttachmentObject
EGLint mOrientation;
- BindingPointer<gl::Texture> mTexture;
+ gl::BindingPointer<gl::Texture> mTexture;
+
+ gl::Format mBackFormat;
+ gl::Format mDSFormat;
+
+ private:
+ Error destroyImpl(const Display *display);
};
-}
+class WindowSurface final : public Surface
+{
+ public:
+ WindowSurface(rx::EGLImplFactory *implFactory,
+ const Config *config,
+ EGLNativeWindowType window,
+ const AttributeMap &attribs);
+ ~WindowSurface() override;
+};
+
+class PbufferSurface final : public Surface
+{
+ public:
+ PbufferSurface(rx::EGLImplFactory *implFactory,
+ const Config *config,
+ const AttributeMap &attribs);
+ PbufferSurface(rx::EGLImplFactory *implFactory,
+ const Config *config,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const AttributeMap &attribs);
+
+ protected:
+ ~PbufferSurface() override;
+};
+
+class PixmapSurface final : public Surface
+{
+ public:
+ PixmapSurface(rx::EGLImplFactory *implFactory,
+ const Config *config,
+ NativePixmapType nativePixmap,
+ const AttributeMap &attribs);
+
+ protected:
+ ~PixmapSurface() override;
+};
+
+class SurfaceDeleter final
+{
+ public:
+ SurfaceDeleter(const Display *display);
+ ~SurfaceDeleter();
+ void operator()(Surface *surface);
+
+ private:
+ const Display *mDisplay;
+};
+
+using SurfacePointer = angle::UniqueObjectPointerBase<Surface, SurfaceDeleter>;
+
+} // namespace egl
#endif // LIBANGLE_SURFACE_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Texture.cpp b/src/3rdparty/angle/src/libANGLE/Texture.cpp
index 5ef6762d3d..da92e65916 100644
--- a/src/3rdparty/angle/src/libANGLE/Texture.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Texture.cpp
@@ -12,66 +12,571 @@
#include "common/utilities.h"
#include "libANGLE/Config.h"
#include "libANGLE/Context.h"
-#include "libANGLE/Data.h"
+#include "libANGLE/ContextState.h"
#include "libANGLE/Image.h"
#include "libANGLE/Surface.h"
#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/TextureImpl.h"
namespace gl
{
-bool IsMipmapFiltered(const gl::SamplerState &samplerState)
+namespace
+{
+bool IsPointSampled(const SamplerState &samplerState)
+{
+ return (samplerState.magFilter == GL_NEAREST &&
+ (samplerState.minFilter == GL_NEAREST ||
+ samplerState.minFilter == GL_NEAREST_MIPMAP_NEAREST));
+}
+
+size_t GetImageDescIndex(GLenum target, size_t level)
+{
+ return IsCubeMapTextureTarget(target) ? ((level * 6) + CubeMapTextureTargetToLayerIndex(target))
+ : level;
+}
+
+ImageIndex GetImageIndexFromDescIndex(GLenum target, size_t descIndex)
+{
+ if (target == GL_TEXTURE_CUBE_MAP)
+ {
+ size_t faceIndex = descIndex % 6;
+ size_t mipIndex = descIndex / 6;
+ return ImageIndex::MakeCube(LayerIndexToCubeMapTextureTarget(faceIndex),
+ static_cast<GLint>(mipIndex));
+ }
+
+ return ImageIndex::MakeGeneric(target, static_cast<GLint>(descIndex));
+}
+
+InitState DetermineInitState(const Context *context, const uint8_t *pixels)
+{
+ // Can happen in tests.
+ if (!context || !context->isRobustResourceInitEnabled())
+ return InitState::Initialized;
+
+ const auto &glState = context->getGLState();
+ return (pixels == nullptr && glState.getTargetBuffer(gl::BufferBinding::PixelUnpack) == nullptr)
+ ? InitState::MayNeedInit
+ : InitState::Initialized;
+}
+
+} // namespace
+
+bool IsMipmapFiltered(const SamplerState &samplerState)
{
switch (samplerState.minFilter)
{
- case GL_NEAREST:
- case GL_LINEAR:
+ case GL_NEAREST:
+ case GL_LINEAR:
+ return false;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ case GL_LINEAR_MIPMAP_NEAREST:
+ case GL_NEAREST_MIPMAP_LINEAR:
+ case GL_LINEAR_MIPMAP_LINEAR:
+ return true;
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+SwizzleState::SwizzleState()
+ : swizzleRed(GL_INVALID_INDEX),
+ swizzleGreen(GL_INVALID_INDEX),
+ swizzleBlue(GL_INVALID_INDEX),
+ swizzleAlpha(GL_INVALID_INDEX)
+{
+}
+
+SwizzleState::SwizzleState(GLenum red, GLenum green, GLenum blue, GLenum alpha)
+ : swizzleRed(red), swizzleGreen(green), swizzleBlue(blue), swizzleAlpha(alpha)
+{
+}
+
+bool SwizzleState::swizzleRequired() const
+{
+ return swizzleRed != GL_RED || swizzleGreen != GL_GREEN || swizzleBlue != GL_BLUE ||
+ swizzleAlpha != GL_ALPHA;
+}
+
+bool SwizzleState::operator==(const SwizzleState &other) const
+{
+ return swizzleRed == other.swizzleRed && swizzleGreen == other.swizzleGreen &&
+ swizzleBlue == other.swizzleBlue && swizzleAlpha == other.swizzleAlpha;
+}
+
+bool SwizzleState::operator!=(const SwizzleState &other) const
+{
+ return !(*this == other);
+}
+
+TextureState::TextureState(GLenum target)
+ : mTarget(target),
+ mSwizzleState(GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA),
+ mSamplerState(SamplerState::CreateDefaultForTarget(target)),
+ mBaseLevel(0),
+ mMaxLevel(1000),
+ mDepthStencilTextureMode(GL_DEPTH_COMPONENT),
+ mImmutableFormat(false),
+ mImmutableLevels(0),
+ mUsage(GL_NONE),
+ mImageDescs((IMPLEMENTATION_MAX_TEXTURE_LEVELS + 1) *
+ (target == GL_TEXTURE_CUBE_MAP ? 6 : 1)),
+ mInitState(InitState::MayNeedInit)
+{
+}
+
+TextureState::~TextureState()
+{
+}
+
+bool TextureState::swizzleRequired() const
+{
+ return mSwizzleState.swizzleRequired();
+}
+
+GLuint TextureState::getEffectiveBaseLevel() const
+{
+ if (mImmutableFormat)
+ {
+ // GLES 3.0.4 section 3.8.10
+ return std::min(mBaseLevel, mImmutableLevels - 1);
+ }
+ // Some classes use the effective base level to index arrays with level data. By clamping the
+ // effective base level to max levels these arrays need just one extra item to store properties
+ // that should be returned for all out-of-range base level values, instead of needing special
+ // handling for out-of-range base levels.
+ return std::min(mBaseLevel, static_cast<GLuint>(IMPLEMENTATION_MAX_TEXTURE_LEVELS));
+}
+
+GLuint TextureState::getEffectiveMaxLevel() const
+{
+ if (mImmutableFormat)
+ {
+ // GLES 3.0.4 section 3.8.10
+ GLuint clampedMaxLevel = std::max(mMaxLevel, getEffectiveBaseLevel());
+ clampedMaxLevel = std::min(clampedMaxLevel, mImmutableLevels - 1);
+ return clampedMaxLevel;
+ }
+ return mMaxLevel;
+}
+
+GLuint TextureState::getMipmapMaxLevel() const
+{
+ const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
+ GLuint expectedMipLevels = 0;
+ if (mTarget == GL_TEXTURE_3D)
+ {
+ const int maxDim = std::max(std::max(baseImageDesc.size.width, baseImageDesc.size.height),
+ baseImageDesc.size.depth);
+ expectedMipLevels = static_cast<GLuint>(log2(maxDim));
+ }
+ else
+ {
+ expectedMipLevels = static_cast<GLuint>(
+ log2(std::max(baseImageDesc.size.width, baseImageDesc.size.height)));
+ }
+
+ return std::min<GLuint>(getEffectiveBaseLevel() + expectedMipLevels, getEffectiveMaxLevel());
+}
+
+bool TextureState::setBaseLevel(GLuint baseLevel)
+{
+ if (mBaseLevel != baseLevel)
+ {
+ mBaseLevel = baseLevel;
+ return true;
+ }
+ return false;
+}
+
+bool TextureState::setMaxLevel(GLuint maxLevel)
+{
+ if (mMaxLevel != maxLevel)
+ {
+ mMaxLevel = maxLevel;
+ return true;
+ }
+
+ return false;
+}
+
+// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
+// According to [OpenGL ES 3.0.5] section 3.8.13 Texture Completeness page 160 any
+// per-level checks begin at the base-level.
+// For OpenGL ES2 the base level is always zero.
+bool TextureState::isCubeComplete() const
+{
+ ASSERT(mTarget == GL_TEXTURE_CUBE_MAP);
+
+ const ImageDesc &baseImageDesc =
+ getImageDesc(FirstCubeMapTextureTarget, getEffectiveBaseLevel());
+ if (baseImageDesc.size.width == 0 || baseImageDesc.size.width != baseImageDesc.size.height)
+ {
+ return false;
+ }
+
+ for (GLenum face = FirstCubeMapTextureTarget + 1; face <= LastCubeMapTextureTarget; face++)
+ {
+ const ImageDesc &faceImageDesc = getImageDesc(face, getEffectiveBaseLevel());
+ if (faceImageDesc.size.width != baseImageDesc.size.width ||
+ faceImageDesc.size.height != baseImageDesc.size.height ||
+ !Format::SameSized(faceImageDesc.format, baseImageDesc.format))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool TextureState::computeSamplerCompleteness(const SamplerState &samplerState,
+ const ContextState &data) const
+{
+ if (mBaseLevel > mMaxLevel)
+ {
+ return false;
+ }
+ const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
+ if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 ||
+ baseImageDesc.size.depth == 0)
+ {
+ return false;
+ }
+ // The cases where the texture is incomplete because base level is out of range should be
+ // handled by the above condition.
+ ASSERT(mBaseLevel < IMPLEMENTATION_MAX_TEXTURE_LEVELS || mImmutableFormat);
+
+ if (mTarget == GL_TEXTURE_CUBE_MAP && baseImageDesc.size.width != baseImageDesc.size.height)
+ {
+ return false;
+ }
+
+ // According to es 3.1 spec, texture is justified as incomplete if sized internalformat is
+ // unfilterable(table 20.11) and filter is not GL_NEAREST(8.16). The default value of minFilter
+ // is NEAREST_MIPMAP_LINEAR and magFilter is LINEAR(table 20.11,). For multismaple texture,
+ // filter state of multisample texture is ignored(11.1.3.3). So it shouldn't be judged as
+ // incomplete texture. So, we ignore filtering for multisample texture completeness here.
+ if (mTarget != GL_TEXTURE_2D_MULTISAMPLE &&
+ !baseImageDesc.format.info->filterSupport(data.getClientVersion(), data.getExtensions()) &&
+ !IsPointSampled(samplerState))
+ {
return false;
- case GL_NEAREST_MIPMAP_NEAREST:
- case GL_LINEAR_MIPMAP_NEAREST:
- case GL_NEAREST_MIPMAP_LINEAR:
- case GL_LINEAR_MIPMAP_LINEAR:
+ }
+ bool npotSupport = data.getExtensions().textureNPOT || data.getClientMajorVersion() >= 3;
+ if (!npotSupport)
+ {
+ if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !isPow2(baseImageDesc.size.width)) ||
+ (samplerState.wrapT != GL_CLAMP_TO_EDGE && !isPow2(baseImageDesc.size.height)))
+ {
+ return false;
+ }
+ }
+
+ if (mTarget != GL_TEXTURE_2D_MULTISAMPLE && IsMipmapFiltered(samplerState))
+ {
+ if (!npotSupport)
+ {
+ if (!isPow2(baseImageDesc.size.width) || !isPow2(baseImageDesc.size.height))
+ {
+ return false;
+ }
+ }
+
+ if (!computeMipmapCompleteness())
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (mTarget == GL_TEXTURE_CUBE_MAP && !isCubeComplete())
+ {
+ return false;
+ }
+ }
+
+ // From GL_OES_EGL_image_external_essl3: If state is present in a sampler object bound to a
+ // texture unit that would have been rejected by a call to TexParameter* for the texture bound
+ // to that unit, the behavior of the implementation is as if the texture were incomplete. For
+ // example, if TEXTURE_WRAP_S or TEXTURE_WRAP_T is set to anything but CLAMP_TO_EDGE on the
+ // sampler object bound to a texture unit and the texture bound to that unit is an external
+ // texture, the texture will be considered incomplete.
+ // Sampler object state which does not affect sampling for the type of texture bound to a
+ // texture unit, such as TEXTURE_WRAP_R for an external texture, does not affect completeness.
+ if (mTarget == GL_TEXTURE_EXTERNAL_OES)
+ {
+ if (samplerState.wrapS != GL_CLAMP_TO_EDGE || samplerState.wrapT != GL_CLAMP_TO_EDGE)
+ {
+ return false;
+ }
+
+ if (samplerState.minFilter != GL_LINEAR && samplerState.minFilter != GL_NEAREST)
+ {
+ return false;
+ }
+ }
+
+ // OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if:
+ // The internalformat specified for the texture arrays is a sized internal depth or
+ // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_-
+ // MODE is NONE, and either the magnification filter is not NEAREST or the mini-
+ // fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST.
+ if (mTarget != GL_TEXTURE_2D_MULTISAMPLE && baseImageDesc.format.info->depthBits > 0 &&
+ data.getClientMajorVersion() >= 3)
+ {
+ // Note: we restrict this validation to sized types. For the OES_depth_textures
+ // extension, due to some underspecification problems, we must allow linear filtering
+ // for legacy compatibility with WebGL 1.
+ // See http://crbug.com/649200
+ if (samplerState.compareMode == GL_NONE && baseImageDesc.format.info->sized)
+ {
+ if ((samplerState.minFilter != GL_NEAREST &&
+ samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) ||
+ samplerState.magFilter != GL_NEAREST)
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool TextureState::computeMipmapCompleteness() const
+{
+ const GLuint maxLevel = getMipmapMaxLevel();
+
+ for (GLuint level = getEffectiveBaseLevel(); level <= maxLevel; level++)
+ {
+ if (mTarget == GL_TEXTURE_CUBE_MAP)
+ {
+ for (GLenum face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++)
+ {
+ if (!computeLevelCompleteness(face, level))
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ if (!computeLevelCompleteness(mTarget, level))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool TextureState::computeLevelCompleteness(GLenum target, size_t level) const
+{
+ ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+
+ if (mImmutableFormat)
+ {
return true;
- default: UNREACHABLE();
+ }
+
+ const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
+ if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 ||
+ baseImageDesc.size.depth == 0)
+ {
return false;
}
+
+ const ImageDesc &levelImageDesc = getImageDesc(target, level);
+ if (levelImageDesc.size.width == 0 || levelImageDesc.size.height == 0 ||
+ levelImageDesc.size.depth == 0)
+ {
+ return false;
+ }
+
+ if (!Format::SameSized(levelImageDesc.format, baseImageDesc.format))
+ {
+ return false;
+ }
+
+ ASSERT(level >= getEffectiveBaseLevel());
+ const size_t relativeLevel = level - getEffectiveBaseLevel();
+ if (levelImageDesc.size.width != std::max(1, baseImageDesc.size.width >> relativeLevel))
+ {
+ return false;
+ }
+
+ if (levelImageDesc.size.height != std::max(1, baseImageDesc.size.height >> relativeLevel))
+ {
+ return false;
+ }
+
+ if (mTarget == GL_TEXTURE_3D)
+ {
+ if (levelImageDesc.size.depth != std::max(1, baseImageDesc.size.depth >> relativeLevel))
+ {
+ return false;
+ }
+ }
+ else if (mTarget == GL_TEXTURE_2D_ARRAY)
+ {
+ if (levelImageDesc.size.depth != baseImageDesc.size.depth)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+GLenum TextureState::getBaseImageTarget() const
+{
+ return mTarget == GL_TEXTURE_CUBE_MAP ? FirstCubeMapTextureTarget : mTarget;
+}
+
+ImageDesc::ImageDesc()
+ : ImageDesc(Extents(0, 0, 0), Format::Invalid(), 0, GL_TRUE, InitState::Initialized)
+{
}
-bool IsPointSampled(const gl::SamplerState &samplerState)
+ImageDesc::ImageDesc(const Extents &size, const Format &format, const InitState initState)
+ : size(size), format(format), samples(0), fixedSampleLocations(GL_TRUE), initState(initState)
{
- return (samplerState.magFilter == GL_NEAREST && (samplerState.minFilter == GL_NEAREST || samplerState.minFilter == GL_NEAREST_MIPMAP_NEAREST));
}
-static size_t GetImageDescIndex(GLenum target, size_t level)
+ImageDesc::ImageDesc(const Extents &size,
+ const Format &format,
+ const GLsizei samples,
+ const bool fixedSampleLocations,
+ const InitState initState)
+ : size(size),
+ format(format),
+ samples(samples),
+ fixedSampleLocations(fixedSampleLocations),
+ initState(initState)
{
- return IsCubeMapTextureTarget(target) ? ((level * 6) + CubeMapTextureTargetToLayerIndex(target)) : level;
}
-Texture::Texture(rx::TextureImpl *impl, GLuint id, GLenum target)
+const ImageDesc &TextureState::getImageDesc(GLenum target, size_t level) const
+{
+ size_t descIndex = GetImageDescIndex(target, level);
+ ASSERT(descIndex < mImageDescs.size());
+ return mImageDescs[descIndex];
+}
+
+void TextureState::setImageDesc(GLenum target, size_t level, const ImageDesc &desc)
+{
+ size_t descIndex = GetImageDescIndex(target, level);
+ ASSERT(descIndex < mImageDescs.size());
+ mImageDescs[descIndex] = desc;
+ if (desc.initState == InitState::MayNeedInit)
+ {
+ mInitState = InitState::MayNeedInit;
+ }
+}
+
+const ImageDesc &TextureState::getImageDesc(const ImageIndex &imageIndex) const
+{
+ return getImageDesc(imageIndex.type, imageIndex.mipIndex);
+}
+
+void TextureState::setImageDescChain(GLuint baseLevel,
+ GLuint maxLevel,
+ Extents baseSize,
+ const Format &format,
+ InitState initState)
+{
+ for (GLuint level = baseLevel; level <= maxLevel; level++)
+ {
+ int relativeLevel = (level - baseLevel);
+ Extents levelSize(std::max<int>(baseSize.width >> relativeLevel, 1),
+ std::max<int>(baseSize.height >> relativeLevel, 1),
+ (mTarget == GL_TEXTURE_2D_ARRAY)
+ ? baseSize.depth
+ : std::max<int>(baseSize.depth >> relativeLevel, 1));
+ ImageDesc levelInfo(levelSize, format, initState);
+
+ if (mTarget == GL_TEXTURE_CUBE_MAP)
+ {
+ for (GLenum face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++)
+ {
+ setImageDesc(face, level, levelInfo);
+ }
+ }
+ else
+ {
+ setImageDesc(mTarget, level, levelInfo);
+ }
+ }
+}
+
+void TextureState::setImageDescChainMultisample(Extents baseSize,
+ const Format &format,
+ GLsizei samples,
+ bool fixedSampleLocations,
+ InitState initState)
+{
+ ASSERT(mTarget == GL_TEXTURE_2D_MULTISAMPLE);
+ ImageDesc levelInfo(baseSize, format, samples, fixedSampleLocations, initState);
+ setImageDesc(mTarget, 0, levelInfo);
+}
+
+void TextureState::clearImageDesc(GLenum target, size_t level)
+{
+ setImageDesc(target, level, ImageDesc());
+}
+
+void TextureState::clearImageDescs()
+{
+ for (size_t descIndex = 0; descIndex < mImageDescs.size(); descIndex++)
+ {
+ mImageDescs[descIndex] = ImageDesc();
+ }
+}
+
+Texture::Texture(rx::GLImplFactory *factory, GLuint id, GLenum target)
: egl::ImageSibling(id),
- mTexture(impl),
+ mState(target),
+ mTexture(factory->createTexture(mState)),
mLabel(),
- mTextureState(),
- mTarget(target),
- mImageDescs(IMPLEMENTATION_MAX_TEXTURE_LEVELS * (target == GL_TEXTURE_CUBE_MAP ? 6 : 1)),
- mCompletenessCache(),
- mBoundSurface(NULL)
+ mBoundSurface(nullptr),
+ mBoundStream(nullptr)
{
}
-Texture::~Texture()
+Error Texture::onDestroy(const Context *context)
{
if (mBoundSurface)
{
- mBoundSurface->releaseTexImage(EGL_BACK_BUFFER);
- mBoundSurface = NULL;
+ ANGLE_TRY(mBoundSurface->releaseTexImage(context, EGL_BACK_BUFFER));
+ mBoundSurface = nullptr;
+ }
+ if (mBoundStream)
+ {
+ mBoundStream->releaseTextures();
+ mBoundStream = nullptr;
}
+
+ ANGLE_TRY(orphanImages(context));
+
+ if (mTexture)
+ {
+ ANGLE_TRY(mTexture->onDestroy(context));
+ }
+ return NoError();
+}
+
+Texture::~Texture()
+{
SafeDelete(mTexture);
}
void Texture::setLabel(const std::string &label)
{
mLabel = label;
+ mDirtyBits.set(DIRTY_BIT_LABEL);
}
const std::string &Texture::getLabel() const
@@ -81,287 +586,303 @@ const std::string &Texture::getLabel() const
GLenum Texture::getTarget() const
{
- return mTarget;
+ return mState.mTarget;
}
void Texture::setSwizzleRed(GLenum swizzleRed)
{
- mTextureState.swizzleRed = swizzleRed;
+ mState.mSwizzleState.swizzleRed = swizzleRed;
+ mDirtyBits.set(DIRTY_BIT_SWIZZLE_RED);
}
GLenum Texture::getSwizzleRed() const
{
- return mTextureState.swizzleRed;
+ return mState.mSwizzleState.swizzleRed;
}
void Texture::setSwizzleGreen(GLenum swizzleGreen)
{
- mTextureState.swizzleGreen = swizzleGreen;
+ mState.mSwizzleState.swizzleGreen = swizzleGreen;
+ mDirtyBits.set(DIRTY_BIT_SWIZZLE_GREEN);
}
GLenum Texture::getSwizzleGreen() const
{
- return mTextureState.swizzleGreen;
+ return mState.mSwizzleState.swizzleGreen;
}
void Texture::setSwizzleBlue(GLenum swizzleBlue)
{
- mTextureState.swizzleBlue = swizzleBlue;
+ mState.mSwizzleState.swizzleBlue = swizzleBlue;
+ mDirtyBits.set(DIRTY_BIT_SWIZZLE_BLUE);
}
GLenum Texture::getSwizzleBlue() const
{
- return mTextureState.swizzleBlue;
+ return mState.mSwizzleState.swizzleBlue;
}
void Texture::setSwizzleAlpha(GLenum swizzleAlpha)
{
- mTextureState.swizzleAlpha = swizzleAlpha;
+ mState.mSwizzleState.swizzleAlpha = swizzleAlpha;
+ mDirtyBits.set(DIRTY_BIT_SWIZZLE_ALPHA);
}
GLenum Texture::getSwizzleAlpha() const
{
- return mTextureState.swizzleAlpha;
+ return mState.mSwizzleState.swizzleAlpha;
}
void Texture::setMinFilter(GLenum minFilter)
{
- mTextureState.samplerState.minFilter = minFilter;
+ mState.mSamplerState.minFilter = minFilter;
+ mDirtyBits.set(DIRTY_BIT_MIN_FILTER);
}
GLenum Texture::getMinFilter() const
{
- return mTextureState.samplerState.minFilter;
+ return mState.mSamplerState.minFilter;
}
void Texture::setMagFilter(GLenum magFilter)
{
- mTextureState.samplerState.magFilter = magFilter;
+ mState.mSamplerState.magFilter = magFilter;
+ mDirtyBits.set(DIRTY_BIT_MAG_FILTER);
}
GLenum Texture::getMagFilter() const
{
- return mTextureState.samplerState.magFilter;
+ return mState.mSamplerState.magFilter;
}
void Texture::setWrapS(GLenum wrapS)
{
- mTextureState.samplerState.wrapS = wrapS;
+ mState.mSamplerState.wrapS = wrapS;
+ mDirtyBits.set(DIRTY_BIT_WRAP_S);
}
GLenum Texture::getWrapS() const
{
- return mTextureState.samplerState.wrapS;
+ return mState.mSamplerState.wrapS;
}
void Texture::setWrapT(GLenum wrapT)
{
- mTextureState.samplerState.wrapT = wrapT;
+ mState.mSamplerState.wrapT = wrapT;
+ mDirtyBits.set(DIRTY_BIT_WRAP_T);
}
GLenum Texture::getWrapT() const
{
- return mTextureState.samplerState.wrapT;
+ return mState.mSamplerState.wrapT;
}
void Texture::setWrapR(GLenum wrapR)
{
- mTextureState.samplerState.wrapR = wrapR;
+ mState.mSamplerState.wrapR = wrapR;
+ mDirtyBits.set(DIRTY_BIT_WRAP_R);
}
GLenum Texture::getWrapR() const
{
- return mTextureState.samplerState.wrapR;
+ return mState.mSamplerState.wrapR;
}
void Texture::setMaxAnisotropy(float maxAnisotropy)
{
- mTextureState.samplerState.maxAnisotropy = maxAnisotropy;
+ mState.mSamplerState.maxAnisotropy = maxAnisotropy;
+ mDirtyBits.set(DIRTY_BIT_MAX_ANISOTROPY);
}
float Texture::getMaxAnisotropy() const
{
- return mTextureState.samplerState.maxAnisotropy;
+ return mState.mSamplerState.maxAnisotropy;
}
void Texture::setMinLod(GLfloat minLod)
{
- mTextureState.samplerState.minLod = minLod;
+ mState.mSamplerState.minLod = minLod;
+ mDirtyBits.set(DIRTY_BIT_MIN_LOD);
}
GLfloat Texture::getMinLod() const
{
- return mTextureState.samplerState.minLod;
+ return mState.mSamplerState.minLod;
}
void Texture::setMaxLod(GLfloat maxLod)
{
- mTextureState.samplerState.maxLod = maxLod;
+ mState.mSamplerState.maxLod = maxLod;
+ mDirtyBits.set(DIRTY_BIT_MAX_LOD);
}
GLfloat Texture::getMaxLod() const
{
- return mTextureState.samplerState.maxLod;
+ return mState.mSamplerState.maxLod;
}
void Texture::setCompareMode(GLenum compareMode)
{
- mTextureState.samplerState.compareMode = compareMode;
+ mState.mSamplerState.compareMode = compareMode;
+ mDirtyBits.set(DIRTY_BIT_COMPARE_MODE);
}
GLenum Texture::getCompareMode() const
{
- return mTextureState.samplerState.compareMode;
+ return mState.mSamplerState.compareMode;
}
void Texture::setCompareFunc(GLenum compareFunc)
{
- mTextureState.samplerState.compareFunc = compareFunc;
+ mState.mSamplerState.compareFunc = compareFunc;
+ mDirtyBits.set(DIRTY_BIT_COMPARE_FUNC);
}
GLenum Texture::getCompareFunc() const
{
- return mTextureState.samplerState.compareFunc;
+ return mState.mSamplerState.compareFunc;
+}
+
+void Texture::setSRGBDecode(GLenum sRGBDecode)
+{
+ mState.mSamplerState.sRGBDecode = sRGBDecode;
+ mDirtyBits.set(DIRTY_BIT_SRGB_DECODE);
+}
+
+GLenum Texture::getSRGBDecode() const
+{
+ return mState.mSamplerState.sRGBDecode;
}
const SamplerState &Texture::getSamplerState() const
{
- return mTextureState.samplerState;
+ return mState.mSamplerState;
}
-void Texture::setBaseLevel(GLuint baseLevel)
+Error Texture::setBaseLevel(const Context *context, GLuint baseLevel)
{
- mTextureState.baseLevel = baseLevel;
+ if (mState.setBaseLevel(baseLevel))
+ {
+ ANGLE_TRY(mTexture->setBaseLevel(context, mState.getEffectiveBaseLevel()));
+ mDirtyBits.set(DIRTY_BIT_BASE_LEVEL);
+ invalidateCompletenessCache();
+ }
+
+ return NoError();
}
GLuint Texture::getBaseLevel() const
{
- return mTextureState.baseLevel;
+ return mState.mBaseLevel;
}
void Texture::setMaxLevel(GLuint maxLevel)
{
- mTextureState.maxLevel = maxLevel;
+ if (mState.setMaxLevel(maxLevel))
+ {
+ mDirtyBits.set(DIRTY_BIT_MAX_LEVEL);
+ invalidateCompletenessCache();
+ }
}
GLuint Texture::getMaxLevel() const
{
- return mTextureState.maxLevel;
+ return mState.mMaxLevel;
+}
+
+void Texture::setDepthStencilTextureMode(GLenum mode)
+{
+ if (mode != mState.mDepthStencilTextureMode)
+ {
+ // Changing the mode from the default state (GL_DEPTH_COMPONENT) is not implemented yet
+ UNIMPLEMENTED();
+ }
+
+ // TODO(geofflang): add dirty bits
+ mState.mDepthStencilTextureMode = mode;
+}
+
+GLenum Texture::getDepthStencilTextureMode() const
+{
+ return mState.mDepthStencilTextureMode;
}
bool Texture::getImmutableFormat() const
{
- return mTextureState.immutableFormat;
+ return mState.mImmutableFormat;
}
GLuint Texture::getImmutableLevels() const
{
- return mTextureState.immutableLevels;
+ return mState.mImmutableLevels;
}
void Texture::setUsage(GLenum usage)
{
- mTextureState.usage = usage;
- getImplementation()->setUsage(usage);
+ mState.mUsage = usage;
+ mDirtyBits.set(DIRTY_BIT_USAGE);
}
GLenum Texture::getUsage() const
{
- return mTextureState.usage;
+ return mState.mUsage;
}
const TextureState &Texture::getTextureState() const
{
- return mTextureState;
+ return mState;
}
size_t Texture::getWidth(GLenum target, size_t level) const
{
- ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
- return getImageDesc(target, level).size.width;
+ ASSERT(target == mState.mTarget ||
+ (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+ return mState.getImageDesc(target, level).size.width;
}
size_t Texture::getHeight(GLenum target, size_t level) const
{
- ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
- return getImageDesc(target, level).size.height;
+ ASSERT(target == mState.mTarget ||
+ (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+ return mState.getImageDesc(target, level).size.height;
}
size_t Texture::getDepth(GLenum target, size_t level) const
{
- ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
- return getImageDesc(target, level).size.depth;
+ ASSERT(target == mState.mTarget ||
+ (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+ return mState.getImageDesc(target, level).size.depth;
}
-GLenum Texture::getInternalFormat(GLenum target, size_t level) const
+const Format &Texture::getFormat(GLenum target, size_t level) const
{
- ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
- return getImageDesc(target, level).internalFormat;
+ ASSERT(target == mState.mTarget ||
+ (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+ return mState.getImageDesc(target, level).format;
}
-bool Texture::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
+GLsizei Texture::getSamples(GLenum target, size_t level) const
{
- const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), mTextureState.baseLevel);
- const TextureCaps &textureCaps = data.textureCaps->get(baseImageDesc.internalFormat);
- if (!mCompletenessCache.cacheValid ||
- mCompletenessCache.samplerState != samplerState ||
- mCompletenessCache.filterable != textureCaps.filterable ||
- mCompletenessCache.clientVersion != data.clientVersion ||
- mCompletenessCache.supportsNPOT != data.extensions->textureNPOT)
- {
- mCompletenessCache.cacheValid = true;
- mCompletenessCache.samplerState = samplerState;
- mCompletenessCache.filterable = textureCaps.filterable;
- mCompletenessCache.clientVersion = data.clientVersion;
- mCompletenessCache.supportsNPOT = data.extensions->textureNPOT;
- mCompletenessCache.samplerComplete = computeSamplerCompleteness(samplerState, data);
- }
- return mCompletenessCache.samplerComplete;
+ ASSERT(target == mState.mTarget ||
+ (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+ return mState.getImageDesc(target, level).samples;
}
-bool Texture::isMipmapComplete() const
+bool Texture::getFixedSampleLocations(GLenum target, size_t level) const
{
- return computeMipmapCompleteness();
+ ASSERT(target == mState.mTarget ||
+ (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+ return mState.getImageDesc(target, level).fixedSampleLocations;
}
-// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
-bool Texture::isCubeComplete() const
+GLuint Texture::getMipmapMaxLevel() const
{
- ASSERT(mTarget == GL_TEXTURE_CUBE_MAP);
-
- const ImageDesc &baseImageDesc = getImageDesc(FirstCubeMapTextureTarget, 0);
- if (baseImageDesc.size.width == 0 || baseImageDesc.size.width != baseImageDesc.size.height)
- {
- return false;
- }
-
- for (GLenum face = FirstCubeMapTextureTarget + 1; face <= LastCubeMapTextureTarget; face++)
- {
- const ImageDesc &faceImageDesc = getImageDesc(face, 0);
- if (faceImageDesc.size.width != baseImageDesc.size.width ||
- faceImageDesc.size.height != baseImageDesc.size.height ||
- faceImageDesc.internalFormat != baseImageDesc.internalFormat)
- {
- return false;
- }
- }
-
- return true;
+ return mState.getMipmapMaxLevel();
}
-size_t Texture::getMipCompleteLevels() const
+bool Texture::isMipmapComplete() const
{
- const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), 0);
- if (mTarget == GL_TEXTURE_3D)
- {
- const int maxDim = std::max(std::max(baseImageDesc.size.width, baseImageDesc.size.height),
- baseImageDesc.size.depth);
- return log2(maxDim) + 1;
- }
- else
- {
- return log2(std::max(baseImageDesc.size.width, baseImageDesc.size.height)) + 1;
- }
+ return mState.computeMipmapCompleteness();
}
egl::Surface *Texture::getBoundSurface() const
@@ -369,7 +890,19 @@ egl::Surface *Texture::getBoundSurface() const
return mBoundSurface;
}
-Error Texture::setImage(Context *context,
+egl::Stream *Texture::getBoundStream() const
+{
+ return mBoundStream;
+}
+
+void Texture::signalDirty(InitState initState) const
+{
+ mDirtyChannel.signal(initState);
+ invalidateCompletenessCache();
+}
+
+Error Texture::setImage(const Context *context,
+ const PixelUnpackState &unpackState,
GLenum target,
size_t level,
GLenum internalFormat,
@@ -378,33 +911,25 @@ Error Texture::setImage(Context *context,
GLenum type,
const uint8_t *pixels)
{
- ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+ ASSERT(target == mState.mTarget ||
+ (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
// Release from previous calls to eglBindTexImage, to avoid calling the Impl after
- releaseTexImageInternal();
- orphanImages();
+ ANGLE_TRY(releaseTexImageInternal(context));
+ ANGLE_TRY(orphanImages(context));
- // Hack: allow nullptr for testing
- if (context != nullptr)
- {
- // Sync the unpack state
- context->syncRendererState(context->getState().unpackStateBitMask());
- }
+ ANGLE_TRY(mTexture->setImage(context, target, level, internalFormat, size, format, type,
+ unpackState, pixels));
- const PixelUnpackState defaultUnpack;
- const PixelUnpackState &unpack = context ? context->getState().getUnpackState() : defaultUnpack;
- Error error = mTexture->setImage(target, level, internalFormat, size, format, type, unpack, pixels);
- if (error.isError())
- {
- return error;
- }
-
- setImageDesc(target, level, ImageDesc(size, GetSizedInternalFormat(internalFormat, type)));
+ InitState initState = DetermineInitState(context, pixels);
+ mState.setImageDesc(target, level, ImageDesc(size, Format(internalFormat, type), initState));
+ signalDirty(initState);
- return Error(GL_NO_ERROR);
+ return NoError();
}
-Error Texture::setSubImage(Context *context,
+Error Texture::setSubImage(const Context *context,
+ const PixelUnpackState &unpackState,
GLenum target,
size_t level,
const Box &area,
@@ -412,16 +937,16 @@ Error Texture::setSubImage(Context *context,
GLenum type,
const uint8_t *pixels)
{
- ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+ ASSERT(target == mState.mTarget ||
+ (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
- // Sync the unpack state
- context->syncRendererState(context->getState().unpackStateBitMask());
+ ANGLE_TRY(ensureSubImageInitialized(context, target, level, area));
- const PixelUnpackState &unpack = context->getState().getUnpackState();
- return mTexture->setSubImage(target, level, area, format, type, unpack, pixels);
+ return mTexture->setSubImage(context, target, level, area, format, type, unpackState, pixels);
}
-Error Texture::setCompressedImage(Context *context,
+Error Texture::setCompressedImage(const Context *context,
+ const PixelUnpackState &unpackState,
GLenum target,
size_t level,
GLenum internalFormat,
@@ -429,28 +954,25 @@ Error Texture::setCompressedImage(Context *context,
size_t imageSize,
const uint8_t *pixels)
{
- ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+ ASSERT(target == mState.mTarget ||
+ (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
// Release from previous calls to eglBindTexImage, to avoid calling the Impl after
- releaseTexImageInternal();
- orphanImages();
+ ANGLE_TRY(releaseTexImageInternal(context));
+ ANGLE_TRY(orphanImages(context));
- // Sync the unpack state
- context->syncRendererState(context->getState().unpackStateBitMask());
-
- const PixelUnpackState &unpack = context->getState().getUnpackState();
- Error error = mTexture->setCompressedImage(target, level, internalFormat, size, unpack, imageSize, pixels);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mTexture->setCompressedImage(context, target, level, internalFormat, size,
+ unpackState, imageSize, pixels));
- setImageDesc(target, level, ImageDesc(size, GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE)));
+ InitState initState = DetermineInitState(context, pixels);
+ mState.setImageDesc(target, level, ImageDesc(size, Format(internalFormat), initState));
+ signalDirty(initState);
- return Error(GL_NO_ERROR);
+ return NoError();
}
-Error Texture::setCompressedSubImage(Context *context,
+Error Texture::setCompressedSubImage(const Context *context,
+ const PixelUnpackState &unpackState,
GLenum target,
size_t level,
const Box &area,
@@ -458,428 +980,505 @@ Error Texture::setCompressedSubImage(Context *context,
size_t imageSize,
const uint8_t *pixels)
{
- ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+ ASSERT(target == mState.mTarget ||
+ (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
- // Sync the unpack state
- context->syncRendererState(context->getState().unpackStateBitMask());
+ ANGLE_TRY(ensureSubImageInitialized(context, target, level, area));
- const PixelUnpackState &unpack = context->getState().getUnpackState();
- return mTexture->setCompressedSubImage(target, level, area, format, unpack, imageSize, pixels);
+ return mTexture->setCompressedSubImage(context, target, level, area, format, unpackState,
+ imageSize, pixels);
}
-Error Texture::copyImage(GLenum target, size_t level, const Rectangle &sourceArea, GLenum internalFormat,
- const Framebuffer *source)
+Error Texture::copyImage(const Context *context,
+ GLenum target,
+ size_t level,
+ const Rectangle &sourceArea,
+ GLenum internalFormat,
+ Framebuffer *source)
{
- ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+ ASSERT(target == mState.mTarget ||
+ (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
// Release from previous calls to eglBindTexImage, to avoid calling the Impl after
- releaseTexImageInternal();
- orphanImages();
+ ANGLE_TRY(releaseTexImageInternal(context));
+ ANGLE_TRY(orphanImages(context));
- Error error = mTexture->copyImage(target, level, sourceArea, internalFormat, source);
- if (error.isError())
- {
- return error;
- }
+ // Ensure source FBO is initialized.
+ ANGLE_TRY(source->ensureReadAttachmentInitialized(context, GL_COLOR_BUFFER_BIT));
- setImageDesc(target, level, ImageDesc(Extents(sourceArea.width, sourceArea.height, 1),
- GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE)));
+ // Use the source FBO size as the init image area.
+ Box destBox(0, 0, 0, sourceArea.width, sourceArea.height, 1);
+ ANGLE_TRY(ensureSubImageInitialized(context, target, level, destBox));
- return Error(GL_NO_ERROR);
-}
+ ANGLE_TRY(mTexture->copyImage(context, target, level, sourceArea, internalFormat, source));
-Error Texture::copySubImage(GLenum target, size_t level, const Offset &destOffset, const Rectangle &sourceArea,
- const Framebuffer *source)
-{
- ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+ const InternalFormat &internalFormatInfo =
+ GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);
- return mTexture->copySubImage(target, level, destOffset, sourceArea, source);
+ mState.setImageDesc(target, level,
+ ImageDesc(Extents(sourceArea.width, sourceArea.height, 1),
+ Format(internalFormatInfo), InitState::Initialized));
+
+ // We need to initialize this texture only if the source attachment is not initialized.
+ signalDirty(InitState::Initialized);
+
+ return NoError();
}
-Error Texture::setStorage(GLenum target, size_t levels, GLenum internalFormat, const Extents &size)
+Error Texture::copySubImage(const Context *context,
+ GLenum target,
+ size_t level,
+ const Offset &destOffset,
+ const Rectangle &sourceArea,
+ Framebuffer *source)
{
- ASSERT(target == mTarget);
+ ASSERT(target == mState.mTarget ||
+ (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
- // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
- releaseTexImageInternal();
- orphanImages();
+ // Ensure source FBO is initialized.
+ ANGLE_TRY(source->ensureReadAttachmentInitialized(context, GL_COLOR_BUFFER_BIT));
- Error error = mTexture->setStorage(target, levels, internalFormat, size);
- if (error.isError())
- {
- return error;
- }
+ Box destBox(destOffset.x, destOffset.y, destOffset.y, sourceArea.width, sourceArea.height, 1);
+ ANGLE_TRY(ensureSubImageInitialized(context, target, level, destBox));
- mTextureState.immutableFormat = true;
- mTextureState.immutableLevels = static_cast<GLuint>(levels);
- clearImageDescs();
- setImageDescChain(levels, size, internalFormat);
-
- return Error(GL_NO_ERROR);
+ return mTexture->copySubImage(context, target, level, destOffset, sourceArea, source);
}
-Error Texture::generateMipmaps()
+Error Texture::copyTexture(const Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ GLenum type,
+ size_t sourceLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ Texture *source)
{
+ ASSERT(target == mState.mTarget ||
+ (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+
// Release from previous calls to eglBindTexImage, to avoid calling the Impl after
- releaseTexImageInternal();
+ ANGLE_TRY(releaseTexImageInternal(context));
+ ANGLE_TRY(orphanImages(context));
- // EGL_KHR_gl_image states that images are only orphaned when generating mipmaps if the texture
- // is not mip complete.
- if (!isMipmapComplete())
- {
- orphanImages();
- }
+ // Initialize source texture.
+ // Note: we don't have a way to notify which portions of the image changed currently.
+ ANGLE_TRY(source->ensureInitialized(context));
- Error error = mTexture->generateMipmaps(mTextureState);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mTexture->copyTexture(context, target, level, internalFormat, type, sourceLevel,
+ unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha,
+ source));
- const ImageDesc &baseImageInfo = getImageDesc(getBaseImageTarget(), 0);
- size_t mipLevels = log2(std::max(std::max(baseImageInfo.size.width, baseImageInfo.size.height), baseImageInfo.size.depth)) + 1;
- setImageDescChain(mipLevels, baseImageInfo.size, baseImageInfo.internalFormat);
+ const auto &sourceDesc = source->mState.getImageDesc(source->getTarget(), 0);
+ const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
+ mState.setImageDesc(
+ target, level,
+ ImageDesc(sourceDesc.size, Format(internalFormatInfo), InitState::Initialized));
- return Error(GL_NO_ERROR);
+ signalDirty(InitState::Initialized);
+
+ return NoError();
}
-void Texture::setImageDescChain(size_t levels, Extents baseSize, GLenum sizedInternalFormat)
+Error Texture::copySubTexture(const Context *context,
+ GLenum target,
+ size_t level,
+ const Offset &destOffset,
+ size_t sourceLevel,
+ const Rectangle &sourceArea,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ Texture *source)
{
- for (int level = 0; level < static_cast<int>(levels); level++)
- {
- Extents levelSize(
- std::max<int>(baseSize.width >> level, 1), std::max<int>(baseSize.height >> level, 1),
- (mTarget == GL_TEXTURE_2D_ARRAY) ? baseSize.depth
- : std::max<int>(baseSize.depth >> level, 1));
- ImageDesc levelInfo(levelSize, sizedInternalFormat);
+ ASSERT(target == mState.mTarget ||
+ (mState.mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
- if (mTarget == GL_TEXTURE_CUBE_MAP)
- {
- for (GLenum face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++)
- {
- setImageDesc(face, level, levelInfo);
- }
- }
- else
- {
- setImageDesc(mTarget, level, levelInfo);
- }
- }
-}
+ // Ensure source is initialized.
+ ANGLE_TRY(source->ensureInitialized(context));
-Texture::ImageDesc::ImageDesc()
- : ImageDesc(Extents(0, 0, 0), GL_NONE)
-{
-}
+ Box destBox(destOffset.x, destOffset.y, destOffset.y, sourceArea.width, sourceArea.height, 1);
+ ANGLE_TRY(ensureSubImageInitialized(context, target, level, destBox));
-Texture::ImageDesc::ImageDesc(const Extents &size, GLenum internalFormat)
- : size(size),
- internalFormat(internalFormat)
-{
+ return mTexture->copySubTexture(context, target, level, destOffset, sourceLevel, sourceArea,
+ unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha,
+ source);
}
-const Texture::ImageDesc &Texture::getImageDesc(GLenum target, size_t level) const
+Error Texture::copyCompressedTexture(const Context *context, const Texture *source)
{
- size_t descIndex = GetImageDescIndex(target, level);
- ASSERT(descIndex < mImageDescs.size());
- return mImageDescs[descIndex];
+ // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+ ANGLE_TRY(releaseTexImageInternal(context));
+ ANGLE_TRY(orphanImages(context));
+
+ ANGLE_TRY(mTexture->copyCompressedTexture(context, source));
+
+ ASSERT(source->getTarget() != GL_TEXTURE_CUBE_MAP && getTarget() != GL_TEXTURE_CUBE_MAP);
+ const auto &sourceDesc = source->mState.getImageDesc(source->getTarget(), 0);
+ mState.setImageDesc(getTarget(), 0, sourceDesc);
+
+ return NoError();
}
-void Texture::setImageDesc(GLenum target, size_t level, const ImageDesc &desc)
+Error Texture::setStorage(const Context *context,
+ GLenum target,
+ GLsizei levels,
+ GLenum internalFormat,
+ const Extents &size)
{
- size_t descIndex = GetImageDescIndex(target, level);
- ASSERT(descIndex < mImageDescs.size());
- mImageDescs[descIndex] = desc;
- mCompletenessCache.cacheValid = false;
+ ASSERT(target == mState.mTarget);
+
+ // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+ ANGLE_TRY(releaseTexImageInternal(context));
+ ANGLE_TRY(orphanImages(context));
+
+ ANGLE_TRY(mTexture->setStorage(context, target, levels, internalFormat, size));
+
+ mState.mImmutableFormat = true;
+ mState.mImmutableLevels = static_cast<GLuint>(levels);
+ mState.clearImageDescs();
+ mState.setImageDescChain(0, static_cast<GLuint>(levels - 1), size, Format(internalFormat),
+ InitState::MayNeedInit);
+
+ // Changing the texture to immutable can trigger a change in the base and max levels:
+ // GLES 3.0.4 section 3.8.10 pg 158:
+ // "For immutable-format textures, levelbase is clamped to the range[0;levels],levelmax is then
+ // clamped to the range[levelbase;levels].
+ mDirtyBits.set(DIRTY_BIT_BASE_LEVEL);
+ mDirtyBits.set(DIRTY_BIT_MAX_LEVEL);
+
+ signalDirty(InitState::MayNeedInit);
+
+ return NoError();
}
-void Texture::clearImageDesc(GLenum target, size_t level)
+Error Texture::setStorageMultisample(const Context *context,
+ GLenum target,
+ GLsizei samples,
+ GLint internalFormat,
+ const Extents &size,
+ bool fixedSampleLocations)
{
- setImageDesc(target, level, ImageDesc());
+ ASSERT(target == mState.mTarget);
+
+ // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+ ANGLE_TRY(releaseTexImageInternal(context));
+ ANGLE_TRY(orphanImages(context));
+
+ ANGLE_TRY(mTexture->setStorageMultisample(context, target, samples, internalFormat, size,
+ fixedSampleLocations));
+
+ mState.mImmutableFormat = true;
+ mState.mImmutableLevels = static_cast<GLuint>(1);
+ mState.clearImageDescs();
+ mState.setImageDescChainMultisample(size, Format(internalFormat), samples, fixedSampleLocations,
+ InitState::MayNeedInit);
+
+ signalDirty(InitState::MayNeedInit);
+
+ return NoError();
}
-void Texture::clearImageDescs()
+Error Texture::generateMipmap(const Context *context)
{
- for (size_t descIndex = 0; descIndex < mImageDescs.size(); descIndex++)
+ // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+ ANGLE_TRY(releaseTexImageInternal(context));
+
+ // EGL_KHR_gl_image states that images are only orphaned when generating mipmaps if the texture
+ // is not mip complete.
+ if (!isMipmapComplete())
{
- mImageDescs[descIndex] = ImageDesc();
+ ANGLE_TRY(orphanImages(context));
}
- mCompletenessCache.cacheValid = false;
+
+ const GLuint baseLevel = mState.getEffectiveBaseLevel();
+ const GLuint maxLevel = mState.getMipmapMaxLevel();
+
+ if (maxLevel > baseLevel)
+ {
+ syncState();
+ const ImageDesc &baseImageInfo =
+ mState.getImageDesc(mState.getBaseImageTarget(), baseLevel);
+
+ // Clear the base image immediately if necessary.
+ if (context->isRobustResourceInitEnabled() &&
+ baseImageInfo.initState == InitState::MayNeedInit)
+ {
+ ANGLE_TRY(initializeContents(
+ context, GetImageIndexFromDescIndex(mState.getBaseImageTarget(), baseLevel)));
+ }
+
+ ANGLE_TRY(mTexture->generateMipmap(context));
+
+ mState.setImageDescChain(baseLevel, maxLevel, baseImageInfo.size, baseImageInfo.format,
+ InitState::Initialized);
+ }
+
+ signalDirty(InitState::Initialized);
+
+ return NoError();
}
-void Texture::bindTexImageFromSurface(egl::Surface *surface)
+Error Texture::bindTexImageFromSurface(const Context *context, egl::Surface *surface)
{
ASSERT(surface);
if (mBoundSurface)
{
- releaseTexImageFromSurface();
+ ANGLE_TRY(releaseTexImageFromSurface(context));
}
- mTexture->bindTexImage(surface);
+ ANGLE_TRY(mTexture->bindTexImage(context, surface));
mBoundSurface = surface;
// Set the image info to the size and format of the surface
- ASSERT(mTarget == GL_TEXTURE_2D);
+ ASSERT(mState.mTarget == GL_TEXTURE_2D || mState.mTarget == GL_TEXTURE_RECTANGLE_ANGLE);
Extents size(surface->getWidth(), surface->getHeight(), 1);
- ImageDesc desc(size, surface->getConfig()->renderTargetFormat);
- setImageDesc(mTarget, 0, desc);
+ ImageDesc desc(size, Format(surface->getConfig()->renderTargetFormat), InitState::Initialized);
+ mState.setImageDesc(mState.mTarget, 0, desc);
+ signalDirty(InitState::Initialized);
+ return NoError();
}
-void Texture::releaseTexImageFromSurface()
+Error Texture::releaseTexImageFromSurface(const Context *context)
{
ASSERT(mBoundSurface);
mBoundSurface = nullptr;
- mTexture->releaseTexImage();
+ ANGLE_TRY(mTexture->releaseTexImage(context));
// Erase the image info for level 0
- ASSERT(mTarget == GL_TEXTURE_2D);
- clearImageDesc(mTarget, 0);
+ ASSERT(mState.mTarget == GL_TEXTURE_2D || mState.mTarget == GL_TEXTURE_RECTANGLE_ANGLE);
+ mState.clearImageDesc(mState.mTarget, 0);
+ signalDirty(InitState::Initialized);
+ return NoError();
}
-void Texture::releaseTexImageInternal()
+void Texture::bindStream(egl::Stream *stream)
+{
+ ASSERT(stream);
+
+ // It should not be possible to bind a texture already bound to another stream
+ ASSERT(mBoundStream == nullptr);
+
+ mBoundStream = stream;
+
+ ASSERT(mState.mTarget == GL_TEXTURE_EXTERNAL_OES);
+}
+
+void Texture::releaseStream()
+{
+ ASSERT(mBoundStream);
+ mBoundStream = nullptr;
+}
+
+Error Texture::acquireImageFromStream(const Context *context,
+ const egl::Stream::GLTextureDescription &desc)
+{
+ ASSERT(mBoundStream != nullptr);
+ ANGLE_TRY(mTexture->setImageExternal(context, mState.mTarget, mBoundStream, desc));
+
+ Extents size(desc.width, desc.height, 1);
+ mState.setImageDesc(mState.mTarget, 0,
+ ImageDesc(size, Format(desc.internalFormat), InitState::Initialized));
+ signalDirty(InitState::Initialized);
+ return NoError();
+}
+
+Error Texture::releaseImageFromStream(const Context *context)
+{
+ ASSERT(mBoundStream != nullptr);
+ ANGLE_TRY(mTexture->setImageExternal(context, mState.mTarget, nullptr,
+ egl::Stream::GLTextureDescription()));
+
+ // Set to incomplete
+ mState.clearImageDesc(mState.mTarget, 0);
+ signalDirty(InitState::Initialized);
+ return NoError();
+}
+
+Error Texture::releaseTexImageInternal(const Context *context)
{
if (mBoundSurface)
{
// Notify the surface
- mBoundSurface->releaseTexImageFromTexture();
+ mBoundSurface->releaseTexImageFromTexture(context);
// Then, call the same method as from the surface
- releaseTexImageFromSurface();
+ ANGLE_TRY(releaseTexImageFromSurface(context));
}
+ return NoError();
}
-Error Texture::setEGLImageTarget(GLenum target, egl::Image *imageTarget)
+Error Texture::setEGLImageTarget(const Context *context, GLenum target, egl::Image *imageTarget)
{
- ASSERT(target == mTarget);
- ASSERT(target == GL_TEXTURE_2D);
+ ASSERT(target == mState.mTarget);
+ ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES);
// Release from previous calls to eglBindTexImage, to avoid calling the Impl after
- releaseTexImageInternal();
- orphanImages();
+ ANGLE_TRY(releaseTexImageInternal(context));
+ ANGLE_TRY(orphanImages(context));
- Error error = mTexture->setEGLImageTarget(target, imageTarget);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mTexture->setEGLImageTarget(context, target, imageTarget));
- setTargetImage(imageTarget);
+ setTargetImage(context, imageTarget);
Extents size(static_cast<int>(imageTarget->getWidth()),
static_cast<int>(imageTarget->getHeight()), 1);
- GLenum internalFormat = imageTarget->getInternalFormat();
- GLenum type = GetInternalFormatInfo(internalFormat).type;
- clearImageDescs();
- setImageDesc(target, 0, ImageDesc(size, GetSizedInternalFormat(internalFormat, type)));
+ auto initState = imageTarget->sourceInitState();
+
+ mState.clearImageDescs();
+ mState.setImageDesc(target, 0, ImageDesc(size, imageTarget->getFormat(), initState));
+ signalDirty(initState);
- return Error(GL_NO_ERROR);
+ return NoError();
}
-GLenum Texture::getBaseImageTarget() const
+Extents Texture::getAttachmentSize(const ImageIndex &imageIndex) const
{
- return mTarget == GL_TEXTURE_CUBE_MAP ? FirstCubeMapTextureTarget : mTarget;
+ return mState.getImageDesc(imageIndex).size;
}
-bool Texture::computeSamplerCompleteness(const SamplerState &samplerState, const Data &data) const
+const Format &Texture::getAttachmentFormat(GLenum /*binding*/, const ImageIndex &imageIndex) const
{
- const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), mTextureState.baseLevel);
- if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 || baseImageDesc.size.depth == 0)
- {
- return false;
- }
-
- if (mTarget == GL_TEXTURE_CUBE_MAP && baseImageDesc.size.width != baseImageDesc.size.height)
- {
- return false;
- }
-
- const TextureCaps &textureCaps = data.textureCaps->get(baseImageDesc.internalFormat);
- if (!textureCaps.filterable && !IsPointSampled(samplerState))
- {
- return false;
- }
-
- bool npotSupport = data.extensions->textureNPOT || data.clientVersion >= 3;
- if (!npotSupport)
- {
- if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(baseImageDesc.size.width)) ||
- (samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(baseImageDesc.size.height)))
- {
- return false;
- }
- }
-
- if (IsMipmapFiltered(samplerState))
- {
- if (!npotSupport)
- {
- if (!gl::isPow2(baseImageDesc.size.width) || !gl::isPow2(baseImageDesc.size.height))
- {
- return false;
- }
- }
-
- if (!computeMipmapCompleteness())
- {
- return false;
- }
- }
- else
- {
- if (mTarget == GL_TEXTURE_CUBE_MAP && !isCubeComplete())
- {
- return false;
- }
- }
+ return mState.getImageDesc(imageIndex).format;
+}
- // OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if:
- // The internalformat specified for the texture arrays is a sized internal depth or
- // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_-
- // MODE is NONE, and either the magnification filter is not NEAREST or the mini-
- // fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST.
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(baseImageDesc.internalFormat);
- if (formatInfo.depthBits > 0 && data.clientVersion > 2)
- {
- if (samplerState.compareMode == GL_NONE)
- {
- if ((samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) ||
- samplerState.magFilter != GL_NEAREST)
- {
- return false;
- }
- }
- }
+GLsizei Texture::getAttachmentSamples(const ImageIndex &imageIndex) const
+{
+ return getSamples(imageIndex.type, 0);
+}
- return true;
+void Texture::onAttach(const Context *context)
+{
+ addRef();
}
-bool Texture::computeMipmapCompleteness() const
+void Texture::onDetach(const Context *context)
{
- size_t expectedMipLevels = getMipCompleteLevels();
+ release(context);
+}
- size_t maxLevel = std::min<size_t>(expectedMipLevels, mTextureState.maxLevel + 1);
+GLuint Texture::getId() const
+{
+ return id();
+}
- for (size_t level = mTextureState.baseLevel; level < maxLevel; level++)
- {
- if (mTarget == GL_TEXTURE_CUBE_MAP)
- {
- for (GLenum face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++)
- {
- if (!computeLevelCompleteness(face, level))
- {
- return false;
- }
- }
- }
- else
- {
- if (!computeLevelCompleteness(mTarget, level))
- {
- return false;
- }
- }
- }
+void Texture::syncState()
+{
+ mTexture->syncState(mDirtyBits);
+ mDirtyBits.reset();
+}
- return true;
+rx::FramebufferAttachmentObjectImpl *Texture::getAttachmentImpl() const
+{
+ return mTexture;
}
-bool Texture::computeLevelCompleteness(GLenum target, size_t level) const
+bool Texture::isSamplerComplete(const Context *context, const Sampler *optionalSampler)
{
- ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ const auto &samplerState =
+ optionalSampler ? optionalSampler->getSamplerState() : mState.mSamplerState;
+ const auto &contextState = context->getContextState();
- if (mTextureState.immutableFormat)
+ if (contextState.getContextID() != mCompletenessCache.context ||
+ mCompletenessCache.samplerState != samplerState)
{
- return true;
+ mCompletenessCache.context = context->getContextState().getContextID();
+ mCompletenessCache.samplerState = samplerState;
+ mCompletenessCache.samplerComplete =
+ mState.computeSamplerCompleteness(samplerState, contextState);
}
- const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), mTextureState.baseLevel);
- if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 || baseImageDesc.size.depth == 0)
- {
- return false;
- }
+ return mCompletenessCache.samplerComplete;
+}
- const ImageDesc &levelImageDesc = getImageDesc(target, level);
- if (levelImageDesc.size.width == 0 || levelImageDesc.size.height == 0 ||
- levelImageDesc.size.depth == 0)
- {
- return false;
- }
+Texture::SamplerCompletenessCache::SamplerCompletenessCache()
+ : context(0), samplerState(), samplerComplete(false)
+{
+}
- if (levelImageDesc.internalFormat != baseImageDesc.internalFormat)
- {
- return false;
- }
+void Texture::invalidateCompletenessCache() const
+{
+ mCompletenessCache.context = 0;
+}
- ASSERT(level >= mTextureState.baseLevel);
- const size_t relativeLevel = level - mTextureState.baseLevel;
- if (levelImageDesc.size.width != std::max(1, baseImageDesc.size.width >> relativeLevel))
+Error Texture::ensureInitialized(const Context *context)
+{
+ if (!context->isRobustResourceInitEnabled() || mState.mInitState == InitState::Initialized)
{
- return false;
+ return NoError();
}
- if (levelImageDesc.size.height != std::max(1, baseImageDesc.size.height >> relativeLevel))
- {
- return false;
- }
+ bool anyDirty = false;
- if (mTarget == GL_TEXTURE_3D)
+ for (size_t descIndex = 0; descIndex < mState.mImageDescs.size(); ++descIndex)
{
- if (levelImageDesc.size.depth != std::max(1, baseImageDesc.size.depth >> relativeLevel))
+ auto &imageDesc = mState.mImageDescs[descIndex];
+ if (imageDesc.initState == InitState::MayNeedInit)
{
- return false;
+ ASSERT(mState.mInitState == InitState::MayNeedInit);
+ const auto &imageIndex = GetImageIndexFromDescIndex(mState.mTarget, descIndex);
+ ANGLE_TRY(initializeContents(context, imageIndex));
+ imageDesc.initState = InitState::Initialized;
+ anyDirty = true;
}
}
- else if (mTarget == GL_TEXTURE_2D_ARRAY)
+ if (anyDirty)
{
- if (levelImageDesc.size.depth != baseImageDesc.size.depth)
- {
- return false;
- }
+ signalDirty(InitState::Initialized);
}
+ mState.mInitState = InitState::Initialized;
- return true;
+ return NoError();
}
-Texture::SamplerCompletenessCache::SamplerCompletenessCache()
- : cacheValid(false),
- samplerState(),
- filterable(false),
- clientVersion(0),
- supportsNPOT(false),
- samplerComplete(false)
+InitState Texture::initState(const ImageIndex &imageIndex) const
{
+ return mState.getImageDesc(imageIndex).initState;
}
-Extents Texture::getAttachmentSize(const gl::FramebufferAttachment::Target &target) const
+InitState Texture::initState() const
{
- return getImageDesc(target.textureIndex().type, target.textureIndex().mipIndex).size;
+ return mState.mInitState;
}
-GLenum Texture::getAttachmentInternalFormat(const gl::FramebufferAttachment::Target &target) const
+void Texture::setInitState(const ImageIndex &imageIndex, InitState initState)
{
- return getInternalFormat(target.textureIndex().type, target.textureIndex().mipIndex);
+ ImageDesc newDesc = mState.getImageDesc(imageIndex);
+ newDesc.initState = initState;
+ mState.setImageDesc(imageIndex.type, imageIndex.mipIndex, newDesc);
}
-GLsizei Texture::getAttachmentSamples(const gl::FramebufferAttachment::Target &/*target*/) const
+Error Texture::ensureSubImageInitialized(const Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Box &area)
{
- // Multisample textures not currently supported
- return 0;
-}
+ if (!context->isRobustResourceInitEnabled() || mState.mInitState == InitState::Initialized)
+ {
+ return NoError();
+ }
-void Texture::onAttach()
-{
- addRef();
-}
+ // Pre-initialize the texture contents if necessary.
+ // TODO(jmadill): Check if area overlaps the entire texture.
+ const auto &imageIndex = GetImageIndexFromDescIndex(target, level);
+ const auto &desc = mState.getImageDesc(imageIndex);
+ if (desc.initState == InitState::MayNeedInit)
+ {
+ ASSERT(mState.mInitState == InitState::MayNeedInit);
+ bool coversWholeImage = area.x == 0 && area.y == 0 && area.z == 0 &&
+ area.width == desc.size.width && area.height == desc.size.height &&
+ area.depth == desc.size.depth;
+ if (!coversWholeImage)
+ {
+ ANGLE_TRY(initializeContents(context, imageIndex));
+ }
+ setInitState(imageIndex, InitState::Initialized);
+ }
-void Texture::onDetach()
-{
- release();
+ return NoError();
}
-GLuint Texture::getId() const
-{
- return id();
-}
-}
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/Texture.h b/src/3rdparty/angle/src/libANGLE/Texture.h
index 7ca8a456fc..7525da2b2f 100644
--- a/src/3rdparty/angle/src/libANGLE/Texture.h
+++ b/src/3rdparty/angle/src/libANGLE/Texture.h
@@ -13,37 +13,169 @@
#include <map>
#include "angle_gl.h"
+#include "common/Optional.h"
#include "common/debug.h"
#include "libANGLE/Caps.h"
-#include "libANGLE/Debug.h"
#include "libANGLE/Constants.h"
+#include "libANGLE/Debug.h"
#include "libANGLE/Error.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/Image.h"
+#include "libANGLE/Stream.h"
#include "libANGLE/angletypes.h"
-#include "libANGLE/renderer/TextureImpl.h"
+#include "libANGLE/formatutils.h"
namespace egl
{
class Surface;
+class Stream;
+}
+
+namespace rx
+{
+class GLImplFactory;
+class TextureImpl;
+class TextureGL;
}
namespace gl
{
-class Context;
+class ContextState;
class Framebuffer;
-struct Data;
+class Sampler;
+class Texture;
bool IsMipmapFiltered(const SamplerState &samplerState);
+struct ImageDesc final
+{
+ ImageDesc();
+ ImageDesc(const Extents &size, const Format &format, const InitState initState);
+ ImageDesc(const Extents &size,
+ const Format &format,
+ const GLsizei samples,
+ const bool fixedSampleLocations,
+ const InitState initState);
+
+ ImageDesc(const ImageDesc &other) = default;
+ ImageDesc &operator=(const ImageDesc &other) = default;
+
+ Extents size;
+ Format format;
+ GLsizei samples;
+ bool fixedSampleLocations;
+
+ // Needed for robust resource initialization.
+ InitState initState;
+};
+
+struct SwizzleState final
+{
+ SwizzleState();
+ SwizzleState(GLenum red, GLenum green, GLenum blue, GLenum alpha);
+ SwizzleState(const SwizzleState &other) = default;
+ SwizzleState &operator=(const SwizzleState &other) = default;
+
+ bool swizzleRequired() const;
+
+ bool operator==(const SwizzleState &other) const;
+ bool operator!=(const SwizzleState &other) const;
+
+ GLenum swizzleRed;
+ GLenum swizzleGreen;
+ GLenum swizzleBlue;
+ GLenum swizzleAlpha;
+};
+
+// State from Table 6.9 (state per texture object) in the OpenGL ES 3.0.2 spec.
+struct TextureState final : private angle::NonCopyable
+{
+ TextureState(GLenum target);
+ ~TextureState();
+
+ bool swizzleRequired() const;
+ GLuint getEffectiveBaseLevel() const;
+ GLuint getEffectiveMaxLevel() const;
+
+ // Returns the value called "q" in the GLES 3.0.4 spec section 3.8.10.
+ GLuint getMipmapMaxLevel() const;
+
+ // Returns true if base level changed.
+ bool setBaseLevel(GLuint baseLevel);
+ bool setMaxLevel(GLuint maxLevel);
+
+ bool isCubeComplete() const;
+
+ const ImageDesc &getImageDesc(GLenum target, size_t level) const;
+ const ImageDesc &getImageDesc(const ImageIndex &imageIndex) const;
+
+ GLenum getTarget() const { return mTarget; }
+ const SwizzleState &getSwizzleState() const { return mSwizzleState; }
+ const SamplerState &getSamplerState() const { return mSamplerState; }
+ GLenum getUsage() const { return mUsage; }
+
+ private:
+ // Texture needs access to the ImageDesc functions.
+ friend class Texture;
+ // TODO(jmadill): Remove TextureGL from friends.
+ friend class rx::TextureGL;
+ friend bool operator==(const TextureState &a, const TextureState &b);
+
+ bool computeSamplerCompleteness(const SamplerState &samplerState,
+ const ContextState &data) const;
+ bool computeMipmapCompleteness() const;
+ bool computeLevelCompleteness(GLenum target, size_t level) const;
+
+ GLenum getBaseImageTarget() const;
+
+ void setImageDesc(GLenum target, size_t level, const ImageDesc &desc);
+ void setImageDescChain(GLuint baselevel,
+ GLuint maxLevel,
+ Extents baseSize,
+ const Format &format,
+ InitState initState);
+ void setImageDescChainMultisample(Extents baseSize,
+ const Format &format,
+ GLsizei samples,
+ bool fixedSampleLocations,
+ InitState initState);
+
+ void clearImageDesc(GLenum target, size_t level);
+ void clearImageDescs();
+
+ const GLenum mTarget;
+
+ SwizzleState mSwizzleState;
+
+ SamplerState mSamplerState;
+
+ GLuint mBaseLevel;
+ GLuint mMaxLevel;
+
+ GLenum mDepthStencilTextureMode;
+
+ bool mImmutableFormat;
+ GLuint mImmutableLevels;
+
+ // From GL_ANGLE_texture_usage
+ GLenum mUsage;
+
+ std::vector<ImageDesc> mImageDescs;
+ InitState mInitState;
+};
+
+bool operator==(const TextureState &a, const TextureState &b);
+bool operator!=(const TextureState &a, const TextureState &b);
+
class Texture final : public egl::ImageSibling,
- public FramebufferAttachmentObject,
public LabeledObject
{
public:
- Texture(rx::TextureImpl *impl, GLuint id, GLenum target);
+ Texture(rx::GLImplFactory *factory, GLuint id, GLenum target);
~Texture() override;
+ Error onDestroy(const Context *context) override;
+
void setLabel(const std::string &label) override;
const std::string &getLabel() const override;
@@ -91,14 +223,20 @@ class Texture final : public egl::ImageSibling,
void setCompareFunc(GLenum compareFunc);
GLenum getCompareFunc() const;
+ void setSRGBDecode(GLenum sRGBDecode);
+ GLenum getSRGBDecode() const;
+
const SamplerState &getSamplerState() const;
- void setBaseLevel(GLuint baseLevel);
+ gl::Error setBaseLevel(const Context *context, GLuint baseLevel);
GLuint getBaseLevel() const;
void setMaxLevel(GLuint maxLevel);
GLuint getMaxLevel() const;
+ void setDepthStencilTextureMode(GLenum mode);
+ GLenum getDepthStencilTextureMode() const;
+
bool getImmutableFormat() const;
GLuint getImmutableLevels() const;
@@ -111,14 +249,17 @@ class Texture final : public egl::ImageSibling,
size_t getWidth(GLenum target, size_t level) const;
size_t getHeight(GLenum target, size_t level) const;
size_t getDepth(GLenum target, size_t level) const;
- GLenum getInternalFormat(GLenum target, size_t level) const;
+ GLsizei getSamples(GLenum target, size_t level) const;
+ bool getFixedSampleLocations(GLenum target, size_t level) const;
+ const Format &getFormat(GLenum target, size_t level) const;
+
+ // Returns the value called "q" in the GLES 3.0.4 spec section 3.8.10.
+ GLuint getMipmapMaxLevel() const;
- bool isSamplerComplete(const SamplerState &samplerState, const Data &data) const;
bool isMipmapComplete() const;
- bool isCubeComplete() const;
- size_t getMipCompleteLevels() const;
- Error setImage(Context *context,
+ Error setImage(const Context *context,
+ const PixelUnpackState &unpackState,
GLenum target,
size_t level,
GLenum internalFormat,
@@ -126,7 +267,8 @@ class Texture final : public egl::ImageSibling,
GLenum format,
GLenum type,
const uint8_t *pixels);
- Error setSubImage(Context *context,
+ Error setSubImage(const Context *context,
+ const PixelUnpackState &unpackState,
GLenum target,
size_t level,
const Box &area,
@@ -134,14 +276,16 @@ class Texture final : public egl::ImageSibling,
GLenum type,
const uint8_t *pixels);
- Error setCompressedImage(Context *context,
+ Error setCompressedImage(const Context *context,
+ const PixelUnpackState &unpackState,
GLenum target,
size_t level,
GLenum internalFormat,
const Extents &size,
size_t imageSize,
const uint8_t *pixels);
- Error setCompressedSubImage(Context *context,
+ Error setCompressedSubImage(const Context *context,
+ const PixelUnpackState &unpackState,
GLenum target,
size_t level,
const Box &area,
@@ -149,98 +293,179 @@ class Texture final : public egl::ImageSibling,
size_t imageSize,
const uint8_t *pixels);
- Error copyImage(GLenum target,
+ Error copyImage(const Context *context,
+ GLenum target,
size_t level,
const Rectangle &sourceArea,
GLenum internalFormat,
- const Framebuffer *source);
- Error copySubImage(GLenum target,
+ Framebuffer *source);
+ Error copySubImage(const Context *context,
+ GLenum target,
size_t level,
const Offset &destOffset,
const Rectangle &sourceArea,
- const Framebuffer *source);
+ Framebuffer *source);
- Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const Extents &size);
+ Error copyTexture(const Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ GLenum type,
+ size_t sourceLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ Texture *source);
+ Error copySubTexture(const Context *context,
+ GLenum target,
+ size_t level,
+ const Offset &destOffset,
+ size_t sourceLevel,
+ const Rectangle &sourceArea,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ Texture *source);
+ Error copyCompressedTexture(const Context *context, const Texture *source);
+
+ Error setStorage(const Context *context,
+ GLenum target,
+ GLsizei levels,
+ GLenum internalFormat,
+ const Extents &size);
+
+ Error setStorageMultisample(const Context *context,
+ GLenum target,
+ GLsizei samples,
+ GLint internalformat,
+ const Extents &size,
+ bool fixedSampleLocations);
- Error setEGLImageTarget(GLenum target, egl::Image *imageTarget);
+ Error setEGLImageTarget(const Context *context, GLenum target, egl::Image *imageTarget);
- Error generateMipmaps();
+ Error generateMipmap(const Context *context);
egl::Surface *getBoundSurface() const;
+ egl::Stream *getBoundStream() const;
- rx::TextureImpl *getImplementation() { return mTexture; }
- const rx::TextureImpl *getImplementation() const { return mTexture; }
+ void signalDirty(InitState initState) const;
+
+ bool isSamplerComplete(const Context *context, const Sampler *optionalSampler);
+
+ rx::TextureImpl *getImplementation() const { return mTexture; }
// FramebufferAttachmentObject implementation
- Extents getAttachmentSize(const FramebufferAttachment::Target &target) const override;
- GLenum getAttachmentInternalFormat(const FramebufferAttachment::Target &target) const override;
- GLsizei getAttachmentSamples(const FramebufferAttachment::Target &target) const override;
+ Extents getAttachmentSize(const ImageIndex &imageIndex) const override;
+ const Format &getAttachmentFormat(GLenum binding, const ImageIndex &imageIndex) const override;
+ GLsizei getAttachmentSamples(const ImageIndex &imageIndex) const override;
- void onAttach() override;
- void onDetach() override;
+ void onAttach(const Context *context) override;
+ void onDetach(const Context *context) override;
GLuint getId() const override;
+ // Needed for robust resource init.
+ Error ensureInitialized(const Context *context);
+ InitState initState(const ImageIndex &imageIndex) const override;
+ InitState initState() const;
+ void setInitState(const ImageIndex &imageIndex, InitState initState) override;
+
+ enum DirtyBitType
+ {
+ // Sampler state
+ DIRTY_BIT_MIN_FILTER,
+ DIRTY_BIT_MAG_FILTER,
+ DIRTY_BIT_WRAP_S,
+ DIRTY_BIT_WRAP_T,
+ DIRTY_BIT_WRAP_R,
+ DIRTY_BIT_MAX_ANISOTROPY,
+ DIRTY_BIT_MIN_LOD,
+ DIRTY_BIT_MAX_LOD,
+ DIRTY_BIT_COMPARE_MODE,
+ DIRTY_BIT_COMPARE_FUNC,
+ DIRTY_BIT_SRGB_DECODE,
+
+ // Texture state
+ DIRTY_BIT_SWIZZLE_RED,
+ DIRTY_BIT_SWIZZLE_GREEN,
+ DIRTY_BIT_SWIZZLE_BLUE,
+ DIRTY_BIT_SWIZZLE_ALPHA,
+ DIRTY_BIT_BASE_LEVEL,
+ DIRTY_BIT_MAX_LEVEL,
+
+ // Misc
+ DIRTY_BIT_LABEL,
+ DIRTY_BIT_USAGE,
+
+ DIRTY_BIT_COUNT,
+ };
+ using DirtyBits = angle::BitSet<DIRTY_BIT_COUNT>;
+
+ void syncState();
+ bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
+
private:
- rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override { return mTexture; }
+ rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override;
// ANGLE-only method, used internally
friend class egl::Surface;
- void bindTexImageFromSurface(egl::Surface *surface);
- void releaseTexImageFromSurface();
-
+ Error bindTexImageFromSurface(const Context *context, egl::Surface *surface);
+ Error releaseTexImageFromSurface(const Context *context);
+
+ // ANGLE-only methods, used internally
+ friend class egl::Stream;
+ void bindStream(egl::Stream *stream);
+ void releaseStream();
+ Error acquireImageFromStream(const Context *context,
+ const egl::Stream::GLTextureDescription &desc);
+ Error releaseImageFromStream(const Context *context);
+
+ void invalidateCompletenessCache() const;
+ Error releaseTexImageInternal(const Context *context);
+
+ Error ensureSubImageInitialized(const Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Box &area);
+
+ TextureState mState;
+ DirtyBits mDirtyBits;
rx::TextureImpl *mTexture;
std::string mLabel;
- TextureState mTextureState;
-
- GLenum mTarget;
-
- struct ImageDesc
- {
- Extents size;
- GLenum internalFormat;
-
- ImageDesc();
- ImageDesc(const Extents &size, GLenum internalFormat);
- };
-
- GLenum getBaseImageTarget() const;
-
- bool computeSamplerCompleteness(const SamplerState &samplerState, const Data &data) const;
- bool computeMipmapCompleteness() const;
- bool computeLevelCompleteness(GLenum target, size_t level) const;
-
- const ImageDesc &getImageDesc(GLenum target, size_t level) const;
- void setImageDesc(GLenum target, size_t level, const ImageDesc &desc);
- void setImageDescChain(size_t levels, Extents baseSize, GLenum sizedInternalFormat);
- void clearImageDesc(GLenum target, size_t level);
- void clearImageDescs();
- void releaseTexImageInternal();
-
- std::vector<ImageDesc> mImageDescs;
+ egl::Surface *mBoundSurface;
+ egl::Stream *mBoundStream;
struct SamplerCompletenessCache
{
SamplerCompletenessCache();
- bool cacheValid;
+ // Context used to generate this cache entry
+ ContextID context;
// All values that affect sampler completeness that are not stored within
// the texture itself
SamplerState samplerState;
- bool filterable;
- GLint clientVersion;
- bool supportsNPOT;
// Result of the sampler completeness with the above parameters
bool samplerComplete;
};
- mutable SamplerCompletenessCache mCompletenessCache;
- egl::Surface *mBoundSurface;
+ mutable SamplerCompletenessCache mCompletenessCache;
};
+inline bool operator==(const TextureState &a, const TextureState &b)
+{
+ return a.mSwizzleState == b.mSwizzleState && a.mSamplerState == b.mSamplerState &&
+ a.mBaseLevel == b.mBaseLevel && a.mMaxLevel == b.mMaxLevel &&
+ a.mImmutableFormat == b.mImmutableFormat && a.mImmutableLevels == b.mImmutableLevels &&
+ a.mUsage == b.mUsage;
+}
+
+inline bool operator!=(const TextureState &a, const TextureState &b)
+{
+ return !(a == b);
}
+} // namespace gl
-#endif // LIBANGLE_TEXTURE_H_
+#endif // LIBANGLE_TEXTURE_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Thread.cpp b/src/3rdparty/angle/src/libANGLE/Thread.cpp
new file mode 100644
index 0000000000..d346db1fa2
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/Thread.cpp
@@ -0,0 +1,91 @@
+//
+// Copyright(c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Thread.cpp : Defines the Thread class which represents a global EGL thread.
+
+#include "libANGLE/Thread.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/Error.h"
+
+namespace egl
+{
+Thread::Thread()
+ : mError(EGL_SUCCESS),
+ mAPI(EGL_OPENGL_ES_API),
+ mContext(static_cast<gl::Context *>(EGL_NO_CONTEXT))
+{
+}
+
+void Thread::setError(const Error &error)
+{
+ mError = error.getCode();
+}
+
+EGLint Thread::getError() const
+{
+ return mError;
+}
+
+void Thread::setAPI(EGLenum api)
+{
+ mAPI = api;
+}
+
+EGLenum Thread::getAPI() const
+{
+ return mAPI;
+}
+
+void Thread::setCurrent(gl::Context *context)
+{
+ mContext = context;
+}
+
+Surface *Thread::getCurrentDrawSurface() const
+{
+ if (mContext)
+ {
+ return mContext->getCurrentDrawSurface();
+ }
+ return nullptr;
+}
+
+Surface *Thread::getCurrentReadSurface() const
+{
+ if (mContext)
+ {
+ return mContext->getCurrentReadSurface();
+ }
+ return nullptr;
+}
+
+gl::Context *Thread::getContext() const
+{
+ return mContext;
+}
+
+gl::Context *Thread::getValidContext() const
+{
+ if (mContext && mContext->isContextLost())
+ {
+ mContext->handleError(gl::OutOfMemory() << "Context has been lost.");
+ return nullptr;
+ }
+
+ return mContext;
+}
+
+Display *Thread::getCurrentDisplay() const
+{
+ if (mContext)
+ {
+ return mContext->getCurrentDisplay();
+ }
+ return nullptr;
+}
+
+} // namespace egl
diff --git a/src/3rdparty/angle/src/libANGLE/Thread.h b/src/3rdparty/angle/src/libANGLE/Thread.h
new file mode 100644
index 0000000000..6406dad9e0
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/Thread.h
@@ -0,0 +1,51 @@
+//
+// Copyright(c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Thread.h : Defines the Thread class which represents a global EGL thread.
+
+#ifndef LIBANGLE_THREAD_H_
+#define LIBANGLE_THREAD_H_
+
+#include <EGL/egl.h>
+
+namespace gl
+{
+class Context;
+} // namespace gl
+
+namespace egl
+{
+class Error;
+class Display;
+class Surface;
+
+class Thread
+{
+ public:
+ Thread();
+
+ void setError(const Error &error);
+ EGLint getError() const;
+
+ void setAPI(EGLenum api);
+ EGLenum getAPI() const;
+
+ void setCurrent(gl::Context *context);
+ Surface *getCurrentDrawSurface() const;
+ Surface *getCurrentReadSurface() const;
+ gl::Context *getContext() const;
+ gl::Context *getValidContext() const;
+ Display *getCurrentDisplay() const;
+
+ private:
+ EGLint mError;
+ EGLenum mAPI;
+ gl::Context *mContext;
+};
+
+} // namespace egl
+
+#endif // LIBANGLE_THREAD_H_
diff --git a/src/3rdparty/angle/src/libANGLE/TransformFeedback.cpp b/src/3rdparty/angle/src/libANGLE/TransformFeedback.cpp
index b7961971d0..99235debd4 100644
--- a/src/3rdparty/angle/src/libANGLE/TransformFeedback.cpp
+++ b/src/3rdparty/angle/src/libANGLE/TransformFeedback.cpp
@@ -8,133 +8,204 @@
#include "libANGLE/Buffer.h"
#include "libANGLE/Caps.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/renderer/GLImplFactory.h"
#include "libANGLE/renderer/TransformFeedbackImpl.h"
namespace gl
{
-TransformFeedback::TransformFeedback(rx::TransformFeedbackImpl *impl, GLuint id, const Caps &caps)
- : RefCountObject(id),
- mImplementation(impl),
- mLabel(),
+TransformFeedbackState::TransformFeedbackState(size_t maxIndexedBuffers)
+ : mLabel(),
mActive(false),
mPrimitiveMode(GL_NONE),
mPaused(false),
+ mProgram(nullptr),
mGenericBuffer(),
- mIndexedBuffers(caps.maxTransformFeedbackSeparateAttributes)
+ mIndexedBuffers(maxIndexedBuffers)
{
- ASSERT(impl != NULL);
}
-TransformFeedback::~TransformFeedback()
+TransformFeedbackState::~TransformFeedbackState()
+{
+}
+
+const BindingPointer<Buffer> &TransformFeedbackState::getGenericBuffer() const
{
- mGenericBuffer.set(nullptr);
- for (size_t i = 0; i < mIndexedBuffers.size(); i++)
+ return mGenericBuffer;
+}
+
+const OffsetBindingPointer<Buffer> &TransformFeedbackState::getIndexedBuffer(size_t idx) const
+{
+ return mIndexedBuffers[idx];
+}
+
+const std::vector<OffsetBindingPointer<Buffer>> &TransformFeedbackState::getIndexedBuffers() const
+{
+ return mIndexedBuffers;
+}
+
+TransformFeedback::TransformFeedback(rx::GLImplFactory *implFactory, GLuint id, const Caps &caps)
+ : RefCountObject(id),
+ mState(caps.maxTransformFeedbackSeparateAttributes),
+ mImplementation(implFactory->createTransformFeedback(mState))
+{
+ ASSERT(mImplementation != nullptr);
+}
+
+Error TransformFeedback::onDestroy(const Context *context)
+{
+ if (mState.mProgram)
{
- mIndexedBuffers[i].set(nullptr);
+ mState.mProgram->release(context);
+ mState.mProgram = nullptr;
}
+ ASSERT(!mState.mProgram);
+ mState.mGenericBuffer.set(context, nullptr);
+ for (size_t i = 0; i < mState.mIndexedBuffers.size(); i++)
+ {
+ mState.mIndexedBuffers[i].set(context, nullptr);
+ }
+
+ return NoError();
+}
+
+TransformFeedback::~TransformFeedback()
+{
SafeDelete(mImplementation);
}
void TransformFeedback::setLabel(const std::string &label)
{
- mLabel = label;
+ mState.mLabel = label;
}
const std::string &TransformFeedback::getLabel() const
{
- return mLabel;
+ return mState.mLabel;
}
-void TransformFeedback::begin(GLenum primitiveMode)
+void TransformFeedback::begin(const Context *context, GLenum primitiveMode, Program *program)
{
- mActive = true;
- mPrimitiveMode = primitiveMode;
- mPaused = false;
+ mState.mActive = true;
+ mState.mPrimitiveMode = primitiveMode;
+ mState.mPaused = false;
mImplementation->begin(primitiveMode);
+ bindProgram(context, program);
}
-void TransformFeedback::end()
+void TransformFeedback::end(const Context *context)
{
- mActive = false;
- mPrimitiveMode = GL_NONE;
- mPaused = false;
+ mState.mActive = false;
+ mState.mPrimitiveMode = GL_NONE;
+ mState.mPaused = false;
mImplementation->end();
+ if (mState.mProgram)
+ {
+ mState.mProgram->release(context);
+ mState.mProgram = nullptr;
+ }
}
void TransformFeedback::pause()
{
- mPaused = true;
+ mState.mPaused = true;
mImplementation->pause();
}
void TransformFeedback::resume()
{
- mPaused = false;
+ mState.mPaused = false;
mImplementation->resume();
}
bool TransformFeedback::isActive() const
{
- return mActive;
+ return mState.mActive;
}
bool TransformFeedback::isPaused() const
{
- return mPaused;
+ return mState.mPaused;
}
GLenum TransformFeedback::getPrimitiveMode() const
{
- return mPrimitiveMode;
+ return mState.mPrimitiveMode;
+}
+
+void TransformFeedback::bindProgram(const Context *context, Program *program)
+{
+ if (mState.mProgram != program)
+ {
+ if (mState.mProgram != nullptr)
+ {
+ mState.mProgram->release(context);
+ }
+ mState.mProgram = program;
+ if (mState.mProgram != nullptr)
+ {
+ mState.mProgram->addRef();
+ }
+ }
}
-void TransformFeedback::bindGenericBuffer(Buffer *buffer)
+bool TransformFeedback::hasBoundProgram(GLuint program) const
{
- mGenericBuffer.set(buffer);
- mImplementation->bindGenericBuffer(mGenericBuffer);
+ return mState.mProgram != nullptr && mState.mProgram->id() == program;
}
-void TransformFeedback::detachBuffer(GLuint bufferName)
+void TransformFeedback::bindGenericBuffer(const Context *context, Buffer *buffer)
{
- for (size_t index = 0; index < mIndexedBuffers.size(); index++)
+ mState.mGenericBuffer.set(context, buffer);
+ mImplementation->bindGenericBuffer(mState.mGenericBuffer);
+}
+
+void TransformFeedback::detachBuffer(const Context *context, GLuint bufferName)
+{
+ for (size_t index = 0; index < mState.mIndexedBuffers.size(); index++)
{
- if (mIndexedBuffers[index].id() == bufferName)
+ if (mState.mIndexedBuffers[index].id() == bufferName)
{
- mIndexedBuffers[index].set(nullptr);
- mImplementation->bindIndexedBuffer(index, mIndexedBuffers[index]);
+ mState.mIndexedBuffers[index].set(context, nullptr);
+ mImplementation->bindIndexedBuffer(index, mState.mIndexedBuffers[index]);
}
}
- if (mGenericBuffer.id() == bufferName)
+ if (mState.mGenericBuffer.id() == bufferName)
{
- mGenericBuffer.set(nullptr);
- mImplementation->bindGenericBuffer(mGenericBuffer);
+ mState.mGenericBuffer.set(context, nullptr);
+ mImplementation->bindGenericBuffer(mState.mGenericBuffer);
}
}
const BindingPointer<Buffer> &TransformFeedback::getGenericBuffer() const
{
- return mGenericBuffer;
+ return mState.mGenericBuffer;
}
-void TransformFeedback::bindIndexedBuffer(size_t index, Buffer *buffer, size_t offset, size_t size)
+void TransformFeedback::bindIndexedBuffer(const Context *context,
+ size_t index,
+ Buffer *buffer,
+ size_t offset,
+ size_t size)
{
- ASSERT(index < mIndexedBuffers.size());
- mIndexedBuffers[index].set(buffer, offset, size);
- mImplementation->bindIndexedBuffer(index, mIndexedBuffers[index]);
+ ASSERT(index < mState.mIndexedBuffers.size());
+ mState.mIndexedBuffers[index].set(context, buffer, offset, size);
+ mImplementation->bindIndexedBuffer(index, mState.mIndexedBuffers[index]);
}
const OffsetBindingPointer<Buffer> &TransformFeedback::getIndexedBuffer(size_t index) const
{
- ASSERT(index < mIndexedBuffers.size());
- return mIndexedBuffers[index];
+ ASSERT(index < mState.mIndexedBuffers.size());
+ return mState.mIndexedBuffers[index];
}
size_t TransformFeedback::getIndexedBufferCount() const
{
- return mIndexedBuffers.size();
+ return mState.mIndexedBuffers.size();
}
rx::TransformFeedbackImpl *TransformFeedback::getImplementation()
diff --git a/src/3rdparty/angle/src/libANGLE/TransformFeedback.h b/src/3rdparty/angle/src/libANGLE/TransformFeedback.h
index 098e4ea4d6..2b35d43f9a 100644
--- a/src/3rdparty/angle/src/libANGLE/TransformFeedback.h
+++ b/src/3rdparty/angle/src/libANGLE/TransformFeedback.h
@@ -16,6 +16,7 @@
namespace rx
{
+class GLImplFactory;
class TransformFeedbackImpl;
}
@@ -23,18 +24,46 @@ namespace gl
{
class Buffer;
struct Caps;
+class Context;
+class Program;
+
+class TransformFeedbackState final : angle::NonCopyable
+{
+ public:
+ TransformFeedbackState(size_t maxIndexedBuffers);
+ ~TransformFeedbackState();
+
+ const BindingPointer<Buffer> &getGenericBuffer() const;
+ const OffsetBindingPointer<Buffer> &getIndexedBuffer(size_t idx) const;
+ const std::vector<OffsetBindingPointer<Buffer>> &getIndexedBuffers() const;
+
+ private:
+ friend class TransformFeedback;
+
+ std::string mLabel;
+
+ bool mActive;
+ GLenum mPrimitiveMode;
+ bool mPaused;
+
+ Program *mProgram;
+
+ BindingPointer<Buffer> mGenericBuffer;
+ std::vector<OffsetBindingPointer<Buffer>> mIndexedBuffers;
+};
class TransformFeedback final : public RefCountObject, public LabeledObject
{
public:
- TransformFeedback(rx::TransformFeedbackImpl* impl, GLuint id, const Caps &caps);
- virtual ~TransformFeedback();
+ TransformFeedback(rx::GLImplFactory *implFactory, GLuint id, const Caps &caps);
+ ~TransformFeedback() override;
+ Error onDestroy(const Context *context) override;
void setLabel(const std::string &label) override;
const std::string &getLabel() const override;
- void begin(GLenum primitiveMode);
- void end();
+ void begin(const Context *context, GLenum primitiveMode, Program *program);
+ void end(const Context *context);
void pause();
void resume();
@@ -42,29 +71,29 @@ class TransformFeedback final : public RefCountObject, public LabeledObject
bool isPaused() const;
GLenum getPrimitiveMode() const;
- void bindGenericBuffer(Buffer *buffer);
+ bool hasBoundProgram(GLuint program) const;
+
+ void bindGenericBuffer(const Context *context, Buffer *buffer);
const BindingPointer<Buffer> &getGenericBuffer() const;
- void bindIndexedBuffer(size_t index, Buffer *buffer, size_t offset, size_t size);
+ void bindIndexedBuffer(const Context *context,
+ size_t index,
+ Buffer *buffer,
+ size_t offset,
+ size_t size);
const OffsetBindingPointer<Buffer> &getIndexedBuffer(size_t index) const;
size_t getIndexedBufferCount() const;
- void detachBuffer(GLuint bufferName);
+ void detachBuffer(const Context *context, GLuint bufferName);
rx::TransformFeedbackImpl *getImplementation();
const rx::TransformFeedbackImpl *getImplementation() const;
private:
- rx::TransformFeedbackImpl* mImplementation;
-
- std::string mLabel;
+ void bindProgram(const Context *context, Program *program);
- bool mActive;
- GLenum mPrimitiveMode;
- bool mPaused;
-
- BindingPointer<Buffer> mGenericBuffer;
- std::vector<OffsetBindingPointer<Buffer>> mIndexedBuffers;
+ TransformFeedbackState mState;
+ rx::TransformFeedbackImpl* mImplementation;
};
}
diff --git a/src/3rdparty/angle/src/libANGLE/Uniform.cpp b/src/3rdparty/angle/src/libANGLE/Uniform.cpp
index bfae3c014f..dee8eee915 100644
--- a/src/3rdparty/angle/src/libANGLE/Uniform.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Uniform.cpp
@@ -13,46 +13,99 @@
namespace gl
{
+StaticallyUsed::StaticallyUsed()
+ : vertexStaticUse(false), fragmentStaticUse(false), computeStaticUse(false)
+{
+}
+
+StaticallyUsed::~StaticallyUsed()
+{
+}
+
+StaticallyUsed::StaticallyUsed(const StaticallyUsed &rhs) = default;
+StaticallyUsed &StaticallyUsed::operator=(const StaticallyUsed &rhs) = default;
+
+void StaticallyUsed::setStaticUse(GLenum shaderType, bool used)
+{
+ switch (shaderType)
+ {
+ case GL_VERTEX_SHADER:
+ vertexStaticUse = used;
+ break;
+
+ case GL_FRAGMENT_SHADER:
+ fragmentStaticUse = used;
+ break;
+
+ case GL_COMPUTE_SHADER:
+ computeStaticUse = used;
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+}
+
+void StaticallyUsed::unionReferencesWith(const StaticallyUsed &other)
+{
+ vertexStaticUse |= other.vertexStaticUse;
+ fragmentStaticUse |= other.fragmentStaticUse;
+ computeStaticUse |= other.computeStaticUse;
+}
+
LinkedUniform::LinkedUniform()
- : blockIndex(-1), blockInfo(sh::BlockMemberInfo::getDefaultBlockInfo())
+ : typeInfo(nullptr), bufferIndex(-1), blockInfo(sh::BlockMemberInfo::getDefaultBlockInfo())
{
}
LinkedUniform::LinkedUniform(GLenum typeIn,
GLenum precisionIn,
const std::string &nameIn,
- unsigned int arraySizeIn,
- const int blockIndexIn,
+ const std::vector<unsigned int> &arraySizesIn,
+ const int bindingIn,
+ const int offsetIn,
+ const int locationIn,
+ const int bufferIndexIn,
const sh::BlockMemberInfo &blockInfoIn)
- : blockIndex(blockIndexIn), blockInfo(blockInfoIn)
+ : typeInfo(&GetUniformTypeInfo(typeIn)), bufferIndex(bufferIndexIn), blockInfo(blockInfoIn)
{
type = typeIn;
precision = precisionIn;
name = nameIn;
- arraySize = arraySizeIn;
+ arraySizes = arraySizesIn;
+ binding = bindingIn;
+ offset = offsetIn;
+ location = locationIn;
+ ASSERT(!isArrayOfArrays());
+ ASSERT(!isArray() || !isStruct());
}
LinkedUniform::LinkedUniform(const sh::Uniform &uniform)
- : sh::Uniform(uniform), blockIndex(-1), blockInfo(sh::BlockMemberInfo::getDefaultBlockInfo())
+ : sh::Uniform(uniform),
+ typeInfo(&GetUniformTypeInfo(type)),
+ bufferIndex(-1),
+ blockInfo(sh::BlockMemberInfo::getDefaultBlockInfo())
{
+ ASSERT(!isArrayOfArrays());
+ ASSERT(!isArray() || !isStruct());
}
LinkedUniform::LinkedUniform(const LinkedUniform &uniform)
- : sh::Uniform(uniform), blockIndex(uniform.blockIndex), blockInfo(uniform.blockInfo)
+ : sh::Uniform(uniform),
+ StaticallyUsed(uniform),
+ typeInfo(uniform.typeInfo),
+ bufferIndex(uniform.bufferIndex),
+ blockInfo(uniform.blockInfo)
{
- // This function is not intended to be called during runtime.
- ASSERT(uniform.mLazyData.empty());
}
LinkedUniform &LinkedUniform::operator=(const LinkedUniform &uniform)
{
- // This function is not intended to be called during runtime.
- ASSERT(uniform.mLazyData.empty());
-
sh::Uniform::operator=(uniform);
- blockIndex = uniform.blockIndex;
+ StaticallyUsed::operator=(uniform);
+ typeInfo = uniform.typeInfo;
+ bufferIndex = uniform.bufferIndex;
blockInfo = uniform.blockInfo;
-
return *this;
}
@@ -62,80 +115,92 @@ LinkedUniform::~LinkedUniform()
bool LinkedUniform::isInDefaultBlock() const
{
- return blockIndex == -1;
+ return bufferIndex == -1;
}
-size_t LinkedUniform::dataSize() const
+bool LinkedUniform::isSampler() const
{
- ASSERT(type != GL_STRUCT_ANGLEX);
- if (mLazyData.empty())
- {
- mLazyData.resize(VariableExternalSize(type) * elementCount());
- ASSERT(!mLazyData.empty());
- }
+ return typeInfo->isSampler;
+}
- return mLazyData.size();
+bool LinkedUniform::isImage() const
+{
+ return typeInfo->isImageType;
}
-uint8_t *LinkedUniform::data()
+bool LinkedUniform::isAtomicCounter() const
{
- if (mLazyData.empty())
- {
- // dataSize() will init the data store.
- size_t size = dataSize();
- memset(mLazyData.data(), 0, size);
- }
+ return IsAtomicCounterType(type);
+}
- return mLazyData.data();
+bool LinkedUniform::isField() const
+{
+ return name.find('.') != std::string::npos;
}
-const uint8_t *LinkedUniform::data() const
+size_t LinkedUniform::getElementSize() const
{
- return const_cast<LinkedUniform *>(this)->data();
+ return typeInfo->externalSize;
}
-bool LinkedUniform::isSampler() const
+size_t LinkedUniform::getElementComponents() const
{
- return IsSamplerType(type);
+ return typeInfo->componentCount;
}
-bool LinkedUniform::isField() const
+BufferVariable::BufferVariable()
+ : bufferIndex(-1), blockInfo(sh::BlockMemberInfo::getDefaultBlockInfo()), topLevelArraySize(-1)
{
- return name.find('.') != std::string::npos;
}
-size_t LinkedUniform::getElementSize() const
+BufferVariable::BufferVariable(GLenum typeIn,
+ GLenum precisionIn,
+ const std::string &nameIn,
+ const std::vector<unsigned int> &arraySizesIn,
+ const int bufferIndexIn,
+ const sh::BlockMemberInfo &blockInfoIn)
+ : bufferIndex(bufferIndexIn), blockInfo(blockInfoIn), topLevelArraySize(-1)
+{
+ type = typeIn;
+ precision = precisionIn;
+ name = nameIn;
+ arraySizes = arraySizesIn;
+}
+
+BufferVariable::~BufferVariable()
{
- return VariableExternalSize(type);
}
-uint8_t *LinkedUniform::getDataPtrToElement(size_t elementIndex)
+ShaderVariableBuffer::ShaderVariableBuffer() : binding(0), dataSize(0)
{
- ASSERT((!isArray() && elementIndex == 0) || (isArray() && elementIndex < arraySize));
- return data() + getElementSize() * elementIndex;
}
-const uint8_t *LinkedUniform::getDataPtrToElement(size_t elementIndex) const
+ShaderVariableBuffer::ShaderVariableBuffer(const ShaderVariableBuffer &other) = default;
+
+ShaderVariableBuffer::~ShaderVariableBuffer()
+{
+}
+
+int ShaderVariableBuffer::numActiveVariables() const
{
- return const_cast<LinkedUniform *>(this)->getDataPtrToElement(elementIndex);
+ return static_cast<int>(memberIndexes.size());
}
-UniformBlock::UniformBlock()
- : isArray(false), arrayElement(0), dataSize(0), vertexStaticUse(false), fragmentStaticUse(false)
+InterfaceBlock::InterfaceBlock() : isArray(false), arrayElement(0)
{
}
-UniformBlock::UniformBlock(const std::string &nameIn, bool isArrayIn, unsigned int arrayElementIn)
- : name(nameIn),
- isArray(isArrayIn),
- arrayElement(arrayElementIn),
- dataSize(0),
- vertexStaticUse(false),
- fragmentStaticUse(false)
+InterfaceBlock::InterfaceBlock(const std::string &nameIn,
+ const std::string &mappedNameIn,
+ bool isArrayIn,
+ unsigned int arrayElementIn,
+ int bindingIn)
+ : name(nameIn), mappedName(mappedNameIn), isArray(isArrayIn), arrayElement(arrayElementIn)
{
+ binding = bindingIn;
}
-std::string UniformBlock::nameWithArrayIndex() const
+std::string InterfaceBlock::nameWithArrayIndex() const
{
std::stringstream fullNameStr;
fullNameStr << name;
@@ -146,4 +211,16 @@ std::string UniformBlock::nameWithArrayIndex() const
return fullNameStr.str();
}
+
+std::string InterfaceBlock::mappedNameWithArrayIndex() const
+{
+ std::stringstream fullNameStr;
+ fullNameStr << mappedName;
+ if (isArray)
+ {
+ fullNameStr << "[" << arrayElement << "]";
+ }
+
+ return fullNameStr.str();
+}
}
diff --git a/src/3rdparty/angle/src/libANGLE/Uniform.h b/src/3rdparty/angle/src/libANGLE/Uniform.h
index e62a583f3d..14c39387a6 100644
--- a/src/3rdparty/angle/src/libANGLE/Uniform.h
+++ b/src/3rdparty/angle/src/libANGLE/Uniform.h
@@ -18,53 +18,107 @@
namespace gl
{
+struct UniformTypeInfo;
+
+struct StaticallyUsed
+{
+ StaticallyUsed();
+ StaticallyUsed(const StaticallyUsed &rhs);
+ virtual ~StaticallyUsed();
+
+ StaticallyUsed &operator=(const StaticallyUsed &rhs);
+
+ void setStaticUse(GLenum shaderType, bool used);
+ void unionReferencesWith(const StaticallyUsed &other);
+
+ bool vertexStaticUse;
+ bool fragmentStaticUse;
+ bool computeStaticUse;
+};
// Helper struct representing a single shader uniform
-struct LinkedUniform : public sh::Uniform
+struct LinkedUniform : public sh::Uniform, public StaticallyUsed
{
LinkedUniform();
- LinkedUniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, const int blockIndex, const sh::BlockMemberInfo &blockInfo);
+ LinkedUniform(GLenum type,
+ GLenum precision,
+ const std::string &name,
+ const std::vector<unsigned int> &arraySizes,
+ const int binding,
+ const int offset,
+ const int location,
+ const int bufferIndex,
+ const sh::BlockMemberInfo &blockInfo);
LinkedUniform(const sh::Uniform &uniform);
LinkedUniform(const LinkedUniform &uniform);
LinkedUniform &operator=(const LinkedUniform &uniform);
- ~LinkedUniform();
+ ~LinkedUniform() override;
- size_t dataSize() const;
- uint8_t *data();
- const uint8_t *data() const;
bool isSampler() const;
+ bool isImage() const;
+ bool isAtomicCounter() const;
bool isInDefaultBlock() const;
bool isField() const;
size_t getElementSize() const;
- uint8_t *getDataPtrToElement(size_t elementIndex);
- const uint8_t *getDataPtrToElement(size_t elementIndex) const;
+ size_t getElementComponents() const;
+
+ const UniformTypeInfo *typeInfo;
- int blockIndex;
+ // Identifies the containing buffer backed resource -- interface block or atomic counter buffer.
+ int bufferIndex;
sh::BlockMemberInfo blockInfo;
+};
- private:
- mutable rx::MemoryBuffer mLazyData;
+struct BufferVariable : public sh::ShaderVariable, public StaticallyUsed
+{
+ BufferVariable();
+ BufferVariable(GLenum type,
+ GLenum precision,
+ const std::string &name,
+ const std::vector<unsigned int> &arraySizes,
+ const int bufferIndex,
+ const sh::BlockMemberInfo &blockInfo);
+ ~BufferVariable() override;
+
+ int bufferIndex;
+ sh::BlockMemberInfo blockInfo;
+
+ int topLevelArraySize;
+};
+
+// Parent struct for atomic counter, uniform block, and shader storage block buffer, which all
+// contain a group of shader variables, and have a GL buffer backed.
+struct ShaderVariableBuffer : public StaticallyUsed
+{
+ ShaderVariableBuffer();
+ ShaderVariableBuffer(const ShaderVariableBuffer &other);
+ ~ShaderVariableBuffer() override;
+ int numActiveVariables() const;
+
+ int binding;
+ unsigned int dataSize;
+ std::vector<unsigned int> memberIndexes;
};
-// Helper struct representing a single shader uniform block
-struct UniformBlock
+using AtomicCounterBuffer = ShaderVariableBuffer;
+
+// Helper struct representing a single shader interface block
+struct InterfaceBlock : public ShaderVariableBuffer
{
- UniformBlock();
- UniformBlock(const std::string &nameIn, bool isArrayIn, unsigned int arrayElementIn);
- UniformBlock(const UniformBlock &other) = default;
- UniformBlock &operator=(const UniformBlock &other) = default;
+ InterfaceBlock();
+ InterfaceBlock(const std::string &nameIn,
+ const std::string &mappedNameIn,
+ bool isArrayIn,
+ unsigned int arrayElementIn,
+ int bindingIn);
std::string nameWithArrayIndex() const;
+ std::string mappedNameWithArrayIndex() const;
std::string name;
+ std::string mappedName;
bool isArray;
unsigned int arrayElement;
- unsigned int dataSize;
-
- bool vertexStaticUse;
- bool fragmentStaticUse;
-
- std::vector<unsigned int> memberUniformIndexes;
};
}
diff --git a/src/3rdparty/angle/src/libANGLE/VaryingPacking.cpp b/src/3rdparty/angle/src/libANGLE/VaryingPacking.cpp
new file mode 100644
index 0000000000..6fc707b549
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/VaryingPacking.cpp
@@ -0,0 +1,408 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// VaryingPacking:
+// Class which describes a mapping from varyings to registers, according
+// to the spec, or using custom packing algorithms. We also keep a register
+// allocation list for the D3D renderer.
+//
+
+#include "libANGLE/VaryingPacking.h"
+
+#include "common/utilities.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Shader.h"
+
+namespace gl
+{
+
+namespace
+{
+
+// true if varying x has a higher priority in packing than y
+bool ComparePackedVarying(const PackedVarying &x, const PackedVarying &y)
+{
+ // If the PackedVarying 'x' or 'y' to be compared is an array element, this clones an equivalent
+ // non-array shader variable 'vx' or 'vy' for actual comparison instead.
+ sh::ShaderVariable vx, vy;
+ const sh::ShaderVariable *px, *py;
+ if (x.isArrayElement())
+ {
+ vx = *x.varying;
+ vx.arraySizes.clear();
+ px = &vx;
+ }
+ else
+ {
+ px = x.varying;
+ }
+
+ if (y.isArrayElement())
+ {
+ vy = *y.varying;
+ vy.arraySizes.clear();
+ py = &vy;
+ }
+ else
+ {
+ py = y.varying;
+ }
+
+ return gl::CompareShaderVar(*px, *py);
+}
+
+} // anonymous namespace
+
+// Implementation of VaryingPacking
+VaryingPacking::VaryingPacking(GLuint maxVaryingVectors, PackMode packMode)
+ : mRegisterMap(maxVaryingVectors), mPackMode(packMode)
+{
+}
+
+VaryingPacking::~VaryingPacking() = default;
+
+// Packs varyings into generic varying registers, using the algorithm from
+// See [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
+// Also [OpenGL ES Shading Language 3.00 rev. 4] Section 11 page 119
+// Returns false if unsuccessful.
+bool VaryingPacking::packVarying(const PackedVarying &packedVarying)
+{
+ const auto &varying = *packedVarying.varying;
+
+ // "Non - square matrices of type matCxR consume the same space as a square matrix of type matN
+ // where N is the greater of C and R."
+ // Here we are a bit more conservative and allow packing non-square matrices more tightly.
+ // Make sure we use transposed matrix types to count registers correctly.
+ ASSERT(!varying.isStruct());
+ GLenum transposedType = gl::TransposeMatrixType(varying.type);
+ unsigned int varyingRows = gl::VariableRowCount(transposedType);
+ unsigned int varyingColumns = gl::VariableColumnCount(transposedType);
+
+ // "Variables of type mat2 occupies 2 complete rows."
+ // For non-WebGL contexts, we allow mat2 to occupy only two columns per row.
+ if (mPackMode == PackMode::WEBGL_STRICT && varying.type == GL_FLOAT_MAT2)
+ {
+ varyingColumns = 4;
+ }
+
+ // "Arrays of size N are assumed to take N times the size of the base type"
+ // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
+ // structures, so we may use getBasicTypeElementCount().
+ const unsigned int elementCount = varying.getBasicTypeElementCount();
+ varyingRows *= (packedVarying.isArrayElement() ? 1 : elementCount);
+
+ unsigned int maxVaryingVectors = static_cast<unsigned int>(mRegisterMap.size());
+
+ // Fail if we are packing a single over-large varying.
+ if (varyingRows > maxVaryingVectors)
+ {
+ return false;
+ }
+
+ // "For 2, 3 and 4 component variables packing is started using the 1st column of the 1st row.
+ // Variables are then allocated to successive rows, aligning them to the 1st column."
+ if (varyingColumns >= 2 && varyingColumns <= 4)
+ {
+ for (unsigned int row = 0; row <= maxVaryingVectors - varyingRows; ++row)
+ {
+ if (isFree(row, 0, varyingRows, varyingColumns))
+ {
+ insert(row, 0, packedVarying);
+ return true;
+ }
+ }
+
+ // "For 2 component variables, when there are no spare rows, the strategy is switched to
+ // using the highest numbered row and the lowest numbered column where the variable will
+ // fit."
+ if (varyingColumns == 2)
+ {
+ for (unsigned int r = maxVaryingVectors - varyingRows + 1; r-- >= 1;)
+ {
+ if (isFree(r, 2, varyingRows, 2))
+ {
+ insert(r, 2, packedVarying);
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ // "1 component variables have their own packing rule. They are packed in order of size, largest
+ // first. Each variable is placed in the column that leaves the least amount of space in the
+ // column and aligned to the lowest available rows within that column."
+ ASSERT(varyingColumns == 1);
+ unsigned int contiguousSpace[4] = {0};
+ unsigned int bestContiguousSpace[4] = {0};
+ unsigned int totalSpace[4] = {0};
+
+ for (unsigned int row = 0; row < maxVaryingVectors; ++row)
+ {
+ for (unsigned int column = 0; column < 4; ++column)
+ {
+ if (mRegisterMap[row][column])
+ {
+ contiguousSpace[column] = 0;
+ }
+ else
+ {
+ contiguousSpace[column]++;
+ totalSpace[column]++;
+
+ if (contiguousSpace[column] > bestContiguousSpace[column])
+ {
+ bestContiguousSpace[column] = contiguousSpace[column];
+ }
+ }
+ }
+ }
+
+ unsigned int bestColumn = 0;
+ for (unsigned int column = 1; column < 4; ++column)
+ {
+ if (bestContiguousSpace[column] >= varyingRows &&
+ (bestContiguousSpace[bestColumn] < varyingRows ||
+ totalSpace[column] < totalSpace[bestColumn]))
+ {
+ bestColumn = column;
+ }
+ }
+
+ if (bestContiguousSpace[bestColumn] >= varyingRows)
+ {
+ for (unsigned int row = 0; row < maxVaryingVectors; row++)
+ {
+ if (isFree(row, bestColumn, varyingRows, 1))
+ {
+ for (unsigned int arrayIndex = 0; arrayIndex < varyingRows; ++arrayIndex)
+ {
+ // If varyingRows > 1, it must be an array.
+ PackedVaryingRegister registerInfo;
+ registerInfo.packedVarying = &packedVarying;
+ registerInfo.registerRow = row + arrayIndex;
+ registerInfo.registerColumn = bestColumn;
+ registerInfo.varyingArrayIndex =
+ (packedVarying.isArrayElement() ? packedVarying.arrayIndex : arrayIndex);
+ registerInfo.varyingRowIndex = 0;
+ // Do not record register info for builtins.
+ // TODO(jmadill): Clean this up.
+ if (!packedVarying.varying->isBuiltIn())
+ {
+ mRegisterList.push_back(registerInfo);
+ }
+ mRegisterMap[row + arrayIndex][bestColumn] = true;
+ }
+ break;
+ }
+ }
+ return true;
+ }
+
+ return false;
+}
+
+bool VaryingPacking::isFree(unsigned int registerRow,
+ unsigned int registerColumn,
+ unsigned int varyingRows,
+ unsigned int varyingColumns) const
+{
+ for (unsigned int row = 0; row < varyingRows; ++row)
+ {
+ ASSERT(registerRow + row < mRegisterMap.size());
+ for (unsigned int column = 0; column < varyingColumns; ++column)
+ {
+ ASSERT(registerColumn + column < 4);
+ if (mRegisterMap[registerRow + row][registerColumn + column])
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+void VaryingPacking::insert(unsigned int registerRow,
+ unsigned int registerColumn,
+ const PackedVarying &packedVarying)
+{
+ unsigned int varyingRows = 0;
+ unsigned int varyingColumns = 0;
+
+ const auto &varying = *packedVarying.varying;
+ ASSERT(!varying.isStruct());
+ GLenum transposedType = gl::TransposeMatrixType(varying.type);
+ varyingRows = gl::VariableRowCount(transposedType);
+ varyingColumns = gl::VariableColumnCount(transposedType);
+
+ PackedVaryingRegister registerInfo;
+ registerInfo.packedVarying = &packedVarying;
+ registerInfo.registerColumn = registerColumn;
+
+ // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
+ // structures, so we may use getBasicTypeElementCount().
+ const unsigned int arrayElementCount = varying.getBasicTypeElementCount();
+ for (unsigned int arrayElement = 0; arrayElement < arrayElementCount; ++arrayElement)
+ {
+ if (packedVarying.isArrayElement() && arrayElement != packedVarying.arrayIndex)
+ {
+ continue;
+ }
+ for (unsigned int varyingRow = 0; varyingRow < varyingRows; ++varyingRow)
+ {
+ registerInfo.registerRow = registerRow + (arrayElement * varyingRows) + varyingRow;
+ registerInfo.varyingRowIndex = varyingRow;
+ registerInfo.varyingArrayIndex = arrayElement;
+ // Do not record register info for builtins.
+ // TODO(jmadill): Clean this up.
+ if (!packedVarying.varying->isBuiltIn())
+ {
+ mRegisterList.push_back(registerInfo);
+ }
+
+ for (unsigned int columnIndex = 0; columnIndex < varyingColumns; ++columnIndex)
+ {
+ mRegisterMap[registerInfo.registerRow][registerColumn + columnIndex] = true;
+ }
+ }
+ }
+}
+
+bool VaryingPacking::collectAndPackUserVaryings(gl::InfoLog &infoLog,
+ const Program::MergedVaryings &mergedVaryings,
+ const std::vector<std::string> &tfVaryings)
+{
+ std::set<std::string> uniqueFullNames;
+ mPackedVaryings.clear();
+
+ for (const auto &ref : mergedVaryings)
+ {
+ const sh::Varying *input = ref.second.vertex;
+ const sh::Varying *output = ref.second.fragment;
+
+ // Only pack statically used varyings that have a matched input or output, plus special
+ // builtins.
+ if (((input && output) || (output && output->isBuiltIn())) && output->staticUse)
+ {
+ // Will get the vertex shader interpolation by default.
+ auto interpolation = ref.second.get()->interpolation;
+
+ // Note that we lose the vertex shader static use information here. The data for the
+ // variable is taken from the fragment shader.
+ if (output->isStruct())
+ {
+ ASSERT(!output->isArray());
+ for (const auto &field : output->fields)
+ {
+ ASSERT(!field.isStruct() && !field.isArray());
+ mPackedVaryings.push_back(PackedVarying(field, interpolation, output->name));
+ uniqueFullNames.insert(mPackedVaryings.back().nameWithArrayIndex());
+ }
+ }
+ else
+ {
+ mPackedVaryings.push_back(PackedVarying(*output, interpolation));
+ uniqueFullNames.insert(mPackedVaryings.back().nameWithArrayIndex());
+ }
+ continue;
+ }
+
+ // Keep Transform FB varyings in the merged list always.
+ if (!input)
+ {
+ continue;
+ }
+
+ for (const std::string &tfVarying : tfVaryings)
+ {
+ std::vector<unsigned int> subscripts;
+ std::string baseName = ParseResourceName(tfVarying, &subscripts);
+ size_t subscript = GL_INVALID_INDEX;
+ if (!subscripts.empty())
+ {
+ subscript = subscripts.back();
+ }
+ // Already packed for fragment shader.
+ if (uniqueFullNames.count(tfVarying) > 0 || uniqueFullNames.count(baseName) > 0)
+ {
+ continue;
+ }
+ // Array as a whole and array element conflict has already been checked in
+ // linkValidateTransformFeedback.
+ if (baseName == input->name)
+ {
+ // Transform feedback for varying structs is underspecified.
+ // See Khronos bug 9856.
+ // TODO(jmadill): Figure out how to be spec-compliant here.
+ if (!input->isStruct() && tfVarying.compare(0, 3, "gl_") != 0)
+ {
+ mPackedVaryings.push_back(PackedVarying(*input, input->interpolation));
+ mPackedVaryings.back().vertexOnly = true;
+ mPackedVaryings.back().arrayIndex = static_cast<GLuint>(subscript);
+ uniqueFullNames.insert(tfVarying);
+ }
+ // Continue to match next array element for 'input' if the current match is array
+ // element.
+ if (subscript == GL_INVALID_INDEX)
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ std::sort(mPackedVaryings.begin(), mPackedVaryings.end(), ComparePackedVarying);
+
+ return packUserVaryings(infoLog, mPackedVaryings, tfVaryings);
+}
+
+// See comment on packVarying.
+bool VaryingPacking::packUserVaryings(gl::InfoLog &infoLog,
+ const std::vector<PackedVarying> &packedVaryings,
+ const std::vector<std::string> &transformFeedbackVaryings)
+{
+
+ // "Variables are packed into the registers one at a time so that they each occupy a contiguous
+ // subrectangle. No splitting of variables is permitted."
+ for (const PackedVarying &packedVarying : packedVaryings)
+ {
+ if (!packVarying(packedVarying))
+ {
+ infoLog << "Could not pack varying " << packedVarying.nameWithArrayIndex();
+ return false;
+ }
+ }
+
+ // Sort the packed register list
+ std::sort(mRegisterList.begin(), mRegisterList.end());
+
+ // Assign semantic indices
+ for (unsigned int semanticIndex = 0;
+ semanticIndex < static_cast<unsigned int>(mRegisterList.size()); ++semanticIndex)
+ {
+ mRegisterList[semanticIndex].semanticIndex = semanticIndex;
+ }
+
+ return true;
+}
+
+unsigned int VaryingPacking::getRegisterCount() const
+{
+ unsigned int count = 0;
+
+ for (const Register &reg : mRegisterMap)
+ {
+ if (reg.data[0] || reg.data[1] || reg.data[2] || reg.data[3])
+ {
+ ++count;
+ }
+ }
+
+ return count;
+}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/VaryingPacking.h b/src/3rdparty/angle/src/libANGLE/VaryingPacking.h
new file mode 100644
index 0000000000..14b25f929e
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/VaryingPacking.h
@@ -0,0 +1,184 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// VaryingPacking:
+// Class which describes a mapping from varyings to registers, according
+// to the spec, or using custom packing algorithms. We also keep a register
+// allocation list for the D3D renderer.
+//
+
+#ifndef LIBANGLE_VARYINGPACKING_H_
+#define LIBANGLE_VARYINGPACKING_H_
+
+#include <GLSLANG/ShaderVars.h>
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/Program.h"
+
+namespace gl
+{
+class InfoLog;
+
+struct PackedVarying
+{
+ PackedVarying(const sh::ShaderVariable &varyingIn, sh::InterpolationType interpolationIn)
+ : PackedVarying(varyingIn, interpolationIn, "")
+ {
+ }
+ PackedVarying(const sh::ShaderVariable &varyingIn,
+ sh::InterpolationType interpolationIn,
+ const std::string &parentStructNameIn)
+ : varying(&varyingIn),
+ vertexOnly(false),
+ interpolation(interpolationIn),
+ parentStructName(parentStructNameIn),
+ arrayIndex(GL_INVALID_INDEX)
+ {
+ }
+
+ bool isStructField() const { return !parentStructName.empty(); }
+
+ bool isArrayElement() const { return arrayIndex != GL_INVALID_INDEX; }
+
+ std::string nameWithArrayIndex() const
+ {
+ std::stringstream fullNameStr;
+ fullNameStr << varying->name;
+ if (arrayIndex != GL_INVALID_INDEX)
+ {
+ fullNameStr << "[" << arrayIndex << "]";
+ }
+ return fullNameStr.str();
+ }
+
+ const sh::ShaderVariable *varying;
+
+ // Transform feedback varyings can be only referenced in the VS.
+ bool vertexOnly;
+
+ // Cached so we can store sh::ShaderVariable to point to varying fields.
+ sh::InterpolationType interpolation;
+
+ // Struct name
+ std::string parentStructName;
+
+ GLuint arrayIndex;
+};
+
+struct PackedVaryingRegister final
+{
+ PackedVaryingRegister()
+ : packedVarying(nullptr),
+ varyingArrayIndex(0),
+ varyingRowIndex(0),
+ registerRow(0),
+ registerColumn(0)
+ {
+ }
+
+ PackedVaryingRegister(const PackedVaryingRegister &) = default;
+ PackedVaryingRegister &operator=(const PackedVaryingRegister &) = default;
+
+ bool operator<(const PackedVaryingRegister &other) const
+ {
+ return sortOrder() < other.sortOrder();
+ }
+
+ unsigned int sortOrder() const
+ {
+ // TODO(jmadill): Handle interpolation types
+ return registerRow * 4 + registerColumn;
+ }
+
+ bool isStructField() const { return !structFieldName.empty(); }
+
+ // Index to the array of varyings.
+ const PackedVarying *packedVarying;
+
+ // The array element of the packed varying.
+ unsigned int varyingArrayIndex;
+
+ // The row of the array element of the packed varying.
+ unsigned int varyingRowIndex;
+
+ // The register row to which we've assigned this packed varying.
+ unsigned int registerRow;
+
+ // The column of the register row into which we've packed this varying.
+ unsigned int registerColumn;
+
+ // Assigned after packing
+ unsigned int semanticIndex;
+
+ // Struct member this varying corresponds to.
+ std::string structFieldName;
+};
+
+// Supported packing modes:
+enum class PackMode
+{
+ // We treat mat2 arrays as taking two full rows.
+ WEBGL_STRICT,
+
+ // We allow mat2 to take a 2x2 chunk.
+ ANGLE_RELAXED,
+};
+
+class VaryingPacking final : angle::NonCopyable
+{
+ public:
+ VaryingPacking(GLuint maxVaryingVectors, PackMode packMode);
+ ~VaryingPacking();
+
+ bool packUserVaryings(gl::InfoLog &infoLog,
+ const std::vector<PackedVarying> &packedVaryings,
+ const std::vector<std::string> &tfVaryings);
+
+ bool collectAndPackUserVaryings(gl::InfoLog &infoLog,
+ const Program::MergedVaryings &mergedVaryings,
+ const std::vector<std::string> &tfVaryings);
+
+ struct Register
+ {
+ Register() { data[0] = data[1] = data[2] = data[3] = false; }
+
+ bool &operator[](unsigned int index) { return data[index]; }
+ bool operator[](unsigned int index) const { return data[index]; }
+
+ bool data[4];
+ };
+
+ Register &operator[](unsigned int index) { return mRegisterMap[index]; }
+ const Register &operator[](unsigned int index) const { return mRegisterMap[index]; }
+
+ const std::vector<PackedVaryingRegister> &getRegisterList() const { return mRegisterList; }
+ unsigned int getMaxSemanticIndex() const
+ {
+ return static_cast<unsigned int>(mRegisterList.size());
+ }
+ unsigned int getRegisterCount() const;
+ size_t getRegisterMapSize() const { return mRegisterMap.size(); }
+
+ private:
+ bool packVarying(const PackedVarying &packedVarying);
+ bool isFree(unsigned int registerRow,
+ unsigned int registerColumn,
+ unsigned int varyingRows,
+ unsigned int varyingColumns) const;
+ void insert(unsigned int registerRow,
+ unsigned int registerColumn,
+ const PackedVarying &packedVarying);
+
+ std::vector<Register> mRegisterMap;
+ std::vector<PackedVaryingRegister> mRegisterList;
+ std::vector<PackedVarying> mPackedVaryings;
+
+ PackMode mPackMode;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_VARYINGPACKING_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Version.h b/src/3rdparty/angle/src/libANGLE/Version.h
index 72dfbb6b8d..7bd41846c8 100644
--- a/src/3rdparty/angle/src/libANGLE/Version.h
+++ b/src/3rdparty/angle/src/libANGLE/Version.h
@@ -9,23 +9,24 @@
#ifndef LIBANGLE_VERSION_H_
#define LIBANGLE_VERSION_H_
-#include <angle_gl.h>
-
namespace gl
{
struct Version
{
- Version();
- Version(GLuint major, GLuint minor);
+ constexpr Version();
+ constexpr Version(unsigned int major, unsigned int minor);
- GLuint major;
- GLuint minor;
+ unsigned int major;
+ unsigned int minor;
};
+bool operator==(const Version &a, const Version &b);
+bool operator!=(const Version &a, const Version &b);
bool operator>=(const Version &a, const Version &b);
+bool operator<=(const Version &a, const Version &b);
bool operator<(const Version &a, const Version &b);
-
+bool operator>(const Version &a, const Version &b);
}
#include "Version.inl"
diff --git a/src/3rdparty/angle/src/libANGLE/Version.inl b/src/3rdparty/angle/src/libANGLE/Version.inl
index f64f7cae77..c98054829e 100644
--- a/src/3rdparty/angle/src/libANGLE/Version.inl
+++ b/src/3rdparty/angle/src/libANGLE/Version.inl
@@ -6,28 +6,54 @@
// Version.inl: Encapsulation of a GL version.
+#include <tuple>
+
namespace gl
{
-inline Version::Version()
+constexpr Version::Version()
: Version(0, 0)
{
}
-inline Version::Version(GLuint major_, GLuint minor_)
+// Avoid conflicts with linux system defines
+#undef major
+#undef minor
+
+constexpr Version::Version(unsigned int major_, unsigned int minor_)
+ : major(major_),
+ minor(minor_)
{
- major = major_;
- minor = minor_;
+}
+
+inline bool operator==(const Version &a, const Version &b)
+{
+ return std::tie(a.major, a.minor) == std::tie(b.major, b.minor);
+}
+
+inline bool operator!=(const Version &a, const Version &b)
+{
+ return std::tie(a.major, a.minor) != std::tie(b.major, b.minor);
}
inline bool operator>=(const Version &a, const Version &b)
{
- return a.major > b.major || (a.major == b.major && a.minor >= b.minor);
+ return std::tie(a.major, a.minor) >= std::tie(b.major, b.minor);
+}
+
+inline bool operator<=(const Version &a, const Version &b)
+{
+ return std::tie(a.major, a.minor) <= std::tie(b.major, b.minor);
}
inline bool operator<(const Version &a, const Version &b)
{
- return !(a >= b);
+ return std::tie(a.major, a.minor) < std::tie(b.major, b.minor);
}
+inline bool operator>(const Version &a, const Version &b)
+{
+ return std::tie(a.major, a.minor) > std::tie(b.major, b.minor);
}
+
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/VertexArray.cpp b/src/3rdparty/angle/src/libANGLE/VertexArray.cpp
index 8d51e9b469..a8c2fce155 100644
--- a/src/3rdparty/angle/src/libANGLE/VertexArray.cpp
+++ b/src/3rdparty/angle/src/libANGLE/VertexArray.cpp
@@ -8,36 +8,53 @@
#include "libANGLE/VertexArray.h"
#include "libANGLE/Buffer.h"
-#include "libANGLE/renderer/ImplFactory.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/renderer/GLImplFactory.h"
#include "libANGLE/renderer/VertexArrayImpl.h"
namespace gl
{
-VertexArray::Data::Data(size_t maxAttribs)
- : mLabel(), mVertexAttributes(maxAttribs), mMaxEnabledAttribute(0)
+VertexArrayState::VertexArrayState(size_t maxAttribs, size_t maxAttribBindings)
+ : mLabel(), mVertexBindings(maxAttribBindings), mMaxEnabledAttribute(0)
{
-}
+ ASSERT(maxAttribs <= maxAttribBindings);
-VertexArray::Data::~Data()
-{
- for (size_t i = 0; i < getMaxAttribs(); i++)
+ for (size_t i = 0; i < maxAttribs; i++)
{
- mVertexAttributes[i].buffer.set(nullptr);
+ mVertexAttributes.emplace_back(static_cast<GLuint>(i));
}
- mElementArrayBuffer.set(nullptr);
}
-VertexArray::VertexArray(rx::ImplFactory *factory, GLuint id, size_t maxAttribs)
+VertexArrayState::~VertexArrayState()
+{
+}
+
+VertexArray::VertexArray(rx::GLImplFactory *factory,
+ GLuint id,
+ size_t maxAttribs,
+ size_t maxAttribBindings)
: mId(id),
- mVertexArray(factory->createVertexArray(mData)),
- mData(maxAttribs)
+ mState(maxAttribs, maxAttribBindings),
+ mVertexArray(factory->createVertexArray(mState))
{
}
-VertexArray::~VertexArray()
+void VertexArray::onDestroy(const Context *context)
{
+ for (auto &binding : mState.mVertexBindings)
+ {
+ binding.setBuffer(context, nullptr);
+ }
+ mState.mElementArrayBuffer.set(context, nullptr);
+ mVertexArray->destroy(context);
SafeDelete(mVertexArray);
+ delete this;
+}
+
+VertexArray::~VertexArray()
+{
+ ASSERT(!mVertexArray);
}
GLuint VertexArray::id() const
@@ -47,94 +64,204 @@ GLuint VertexArray::id() const
void VertexArray::setLabel(const std::string &label)
{
- mData.mLabel = label;
+ mState.mLabel = label;
}
const std::string &VertexArray::getLabel() const
{
- return mData.mLabel;
+ return mState.mLabel;
}
-void VertexArray::detachBuffer(GLuint bufferName)
+void VertexArray::detachBuffer(const Context *context, GLuint bufferName)
{
- for (size_t attribute = 0; attribute < getMaxAttribs(); attribute++)
+ for (auto &binding : mState.mVertexBindings)
{
- if (mData.mVertexAttributes[attribute].buffer.id() == bufferName)
+ if (binding.getBuffer().id() == bufferName)
{
- mData.mVertexAttributes[attribute].buffer.set(nullptr);
+ binding.setBuffer(context, nullptr);
}
}
- if (mData.mElementArrayBuffer.id() == bufferName)
+ if (mState.mElementArrayBuffer.id() == bufferName)
+ {
+ mState.mElementArrayBuffer.set(context, nullptr);
+ }
+}
+
+const VertexAttribute &VertexArray::getVertexAttribute(size_t attribIndex) const
+{
+ ASSERT(attribIndex < getMaxAttribs());
+ return mState.mVertexAttributes[attribIndex];
+}
+
+const VertexBinding &VertexArray::getVertexBinding(size_t bindingIndex) const
+{
+ ASSERT(bindingIndex < getMaxBindings());
+ return mState.mVertexBindings[bindingIndex];
+}
+
+size_t VertexArray::GetVertexIndexFromDirtyBit(size_t dirtyBit)
+{
+ static_assert(gl::MAX_VERTEX_ATTRIBS == gl::MAX_VERTEX_ATTRIB_BINDINGS,
+ "The stride of vertex attributes should equal to that of vertex bindings.");
+ ASSERT(dirtyBit > DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
+ return (dirtyBit - DIRTY_BIT_ATTRIB_0_ENABLED) % gl::MAX_VERTEX_ATTRIBS;
+}
+
+void VertexArray::bindVertexBufferImpl(const Context *context,
+ size_t bindingIndex,
+ Buffer *boundBuffer,
+ GLintptr offset,
+ GLsizei stride)
+{
+ ASSERT(bindingIndex < getMaxBindings());
+
+ VertexBinding *binding = &mState.mVertexBindings[bindingIndex];
+
+ binding->setBuffer(context, boundBuffer);
+ binding->setOffset(offset);
+ binding->setStride(stride);
+}
+
+void VertexArray::bindVertexBuffer(const Context *context,
+ size_t bindingIndex,
+ Buffer *boundBuffer,
+ GLintptr offset,
+ GLsizei stride)
+{
+ bindVertexBufferImpl(context, bindingIndex, boundBuffer, offset, stride);
+
+ mDirtyBits.set(DIRTY_BIT_BINDING_0_BUFFER + bindingIndex);
+}
+
+void VertexArray::setVertexAttribBinding(const Context *context,
+ size_t attribIndex,
+ GLuint bindingIndex)
+{
+ ASSERT(attribIndex < getMaxAttribs() && bindingIndex < getMaxBindings());
+
+ if (mState.mVertexAttributes[attribIndex].bindingIndex != bindingIndex)
{
- mData.mElementArrayBuffer.set(nullptr);
+ // In ES 3.0 contexts, the binding cannot change, hence the code below is unreachable.
+ ASSERT(context->getClientVersion() >= ES_3_1);
+ mState.mVertexAttributes[attribIndex].bindingIndex = bindingIndex;
+
+ mDirtyBits.set(DIRTY_BIT_ATTRIB_0_BINDING + attribIndex);
}
}
-const VertexAttribute &VertexArray::getVertexAttribute(size_t attributeIndex) const
+void VertexArray::setVertexBindingDivisor(size_t bindingIndex, GLuint divisor)
+{
+ ASSERT(bindingIndex < getMaxBindings());
+
+ mState.mVertexBindings[bindingIndex].setDivisor(divisor);
+
+ mDirtyBits.set(DIRTY_BIT_BINDING_0_DIVISOR + bindingIndex);
+}
+
+void VertexArray::setVertexAttribFormatImpl(size_t attribIndex,
+ GLint size,
+ GLenum type,
+ bool normalized,
+ bool pureInteger,
+ GLuint relativeOffset)
{
- ASSERT(attributeIndex < getMaxAttribs());
- return mData.mVertexAttributes[attributeIndex];
+ ASSERT(attribIndex < getMaxAttribs());
+
+ VertexAttribute *attrib = &mState.mVertexAttributes[attribIndex];
+
+ attrib->size = size;
+ attrib->type = type;
+ attrib->normalized = normalized;
+ attrib->pureInteger = pureInteger;
+ attrib->relativeOffset = relativeOffset;
}
-void VertexArray::setVertexAttribDivisor(size_t index, GLuint divisor)
+void VertexArray::setVertexAttribFormat(size_t attribIndex,
+ GLint size,
+ GLenum type,
+ bool normalized,
+ bool pureInteger,
+ GLuint relativeOffset)
{
- ASSERT(index < getMaxAttribs());
- mData.mVertexAttributes[index].divisor = divisor;
- mDirtyBits.set(DIRTY_BIT_ATTRIB_0_DIVISOR + index);
+ setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, relativeOffset);
+
+ mDirtyBits.set(DIRTY_BIT_ATTRIB_0_FORMAT + attribIndex);
+}
+
+void VertexArray::setVertexAttribDivisor(const Context *context, size_t attribIndex, GLuint divisor)
+{
+ ASSERT(attribIndex < getMaxAttribs());
+
+ setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
+ setVertexBindingDivisor(attribIndex, divisor);
}
-void VertexArray::enableAttribute(size_t attributeIndex, bool enabledState)
+void VertexArray::enableAttribute(size_t attribIndex, bool enabledState)
{
- ASSERT(attributeIndex < getMaxAttribs());
- mData.mVertexAttributes[attributeIndex].enabled = enabledState;
- mDirtyBits.set(DIRTY_BIT_ATTRIB_0_ENABLED + attributeIndex);
+ ASSERT(attribIndex < getMaxAttribs());
+
+ mState.mVertexAttributes[attribIndex].enabled = enabledState;
+
+ mDirtyBits.set(DIRTY_BIT_ATTRIB_0_ENABLED + attribIndex);
// Update state cache
if (enabledState)
{
- mData.mMaxEnabledAttribute = std::max(attributeIndex + 1, mData.mMaxEnabledAttribute);
+ mState.mMaxEnabledAttribute = std::max(attribIndex + 1, mState.mMaxEnabledAttribute);
}
- else if (mData.mMaxEnabledAttribute == attributeIndex + 1)
+ else if (mState.mMaxEnabledAttribute == attribIndex + 1)
{
- while (mData.mMaxEnabledAttribute > 0 &&
- !mData.mVertexAttributes[mData.mMaxEnabledAttribute - 1].enabled)
+ while (mState.mMaxEnabledAttribute > 0 &&
+ !mState.mVertexAttributes[mState.mMaxEnabledAttribute - 1].enabled)
{
- --mData.mMaxEnabledAttribute;
+ --mState.mMaxEnabledAttribute;
}
}
}
-void VertexArray::setAttributeState(size_t attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type,
- bool normalized, bool pureInteger, GLsizei stride, const void *pointer)
+void VertexArray::setVertexAttribPointer(const Context *context,
+ size_t attribIndex,
+ gl::Buffer *boundBuffer,
+ GLint size,
+ GLenum type,
+ bool normalized,
+ bool pureInteger,
+ GLsizei stride,
+ const void *pointer)
{
- ASSERT(attributeIndex < getMaxAttribs());
+ ASSERT(attribIndex < getMaxAttribs());
+
+ GLintptr offset = boundBuffer ? reinterpret_cast<GLintptr>(pointer) : 0;
+
+ setVertexAttribFormatImpl(attribIndex, size, type, normalized, pureInteger, 0);
+ setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
- VertexAttribute *attrib = &mData.mVertexAttributes[attributeIndex];
+ VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
- attrib->buffer.set(boundBuffer);
- attrib->size = size;
- attrib->type = type;
- attrib->normalized = normalized;
- attrib->pureInteger = pureInteger;
- attrib->stride = stride;
- attrib->pointer = pointer;
- mDirtyBits.set(DIRTY_BIT_ATTRIB_0_POINTER + attributeIndex);
+ GLsizei effectiveStride =
+ stride != 0 ? stride : static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib));
+ attrib.pointer = pointer;
+ attrib.vertexAttribArrayStride = stride;
+
+ bindVertexBufferImpl(context, attribIndex, boundBuffer, offset, effectiveStride);
+
+ mDirtyBits.set(DIRTY_BIT_ATTRIB_0_POINTER + attribIndex);
}
-void VertexArray::setElementArrayBuffer(Buffer *buffer)
+void VertexArray::setElementArrayBuffer(const Context *context, Buffer *buffer)
{
- mData.mElementArrayBuffer.set(buffer);
+ mState.mElementArrayBuffer.set(context, buffer);
mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
}
-void VertexArray::syncImplState()
+void VertexArray::syncState(const Context *context)
{
if (mDirtyBits.any())
{
- mVertexArray->syncState(mDirtyBits);
+ mVertexArray->syncState(context, mDirtyBits);
mDirtyBits.reset();
}
}
-}
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/VertexArray.h b/src/3rdparty/angle/src/libANGLE/VertexArray.h
index 6bc267d399..f82ec789f0 100644
--- a/src/3rdparty/angle/src/libANGLE/VertexArray.h
+++ b/src/3rdparty/angle/src/libANGLE/VertexArray.h
@@ -23,68 +23,131 @@
namespace rx
{
-class ImplFactory;
+class GLImplFactory;
class VertexArrayImpl;
-}
+} // namespace rx
namespace gl
{
class Buffer;
-class VertexArray final : public LabeledObject
+class VertexArrayState final : angle::NonCopyable
{
public:
- VertexArray(rx::ImplFactory *factory, GLuint id, size_t maxAttribs);
- ~VertexArray();
+ VertexArrayState(size_t maxAttribs, size_t maxBindings);
+ ~VertexArrayState();
- GLuint id() const;
+ const std::string &getLabel() const { return mLabel; }
- void setLabel(const std::string &label) override;
- const std::string &getLabel() const override;
+ const BindingPointer<Buffer> &getElementArrayBuffer() const { return mElementArrayBuffer; }
+ size_t getMaxAttribs() const { return mVertexAttributes.size(); }
+ size_t getMaxBindings() const { return mVertexBindings.size(); }
+ size_t getMaxEnabledAttribute() const { return mMaxEnabledAttribute; }
+ const std::vector<VertexAttribute> &getVertexAttributes() const { return mVertexAttributes; }
+ const VertexAttribute &getVertexAttribute(size_t attribIndex) const
+ {
+ return mVertexAttributes[attribIndex];
+ }
+ const std::vector<VertexBinding> &getVertexBindings() const { return mVertexBindings; }
+ const VertexBinding &getVertexBinding(size_t bindingIndex) const
+ {
+ return mVertexBindings[bindingIndex];
+ }
+ const VertexBinding &getBindingFromAttribIndex(size_t attribIndex) const
+ {
+ return mVertexBindings[mVertexAttributes[attribIndex].bindingIndex];
+ }
+ size_t getBindingIndexFromAttribIndex(size_t attribIndex) const
+ {
+ return mVertexAttributes[attribIndex].bindingIndex;
+ }
- const VertexAttribute &getVertexAttribute(size_t attributeIndex) const;
+ private:
+ friend class VertexArray;
+ std::string mLabel;
+ std::vector<VertexAttribute> mVertexAttributes;
+ BindingPointer<Buffer> mElementArrayBuffer;
+ std::vector<VertexBinding> mVertexBindings;
+ size_t mMaxEnabledAttribute;
+};
- void detachBuffer(GLuint bufferName);
- void setVertexAttribDivisor(size_t index, GLuint divisor);
- void enableAttribute(size_t attributeIndex, bool enabledState);
- void setAttributeState(size_t attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type,
- bool normalized, bool pureInteger, GLsizei stride, const void *pointer);
+class VertexArray final : public LabeledObject
+{
+ public:
+ VertexArray(rx::GLImplFactory *factory, GLuint id, size_t maxAttribs, size_t maxAttribBindings);
- void setElementArrayBuffer(Buffer *buffer);
+ void onDestroy(const Context *context);
- const BindingPointer<Buffer> &getElementArrayBuffer() const { return mData.getElementArrayBuffer(); }
- size_t getMaxAttribs() const { return mData.getVertexAttributes().size(); }
- const std::vector<VertexAttribute> &getVertexAttributes() const { return mData.getVertexAttributes(); }
+ GLuint id() const;
- rx::VertexArrayImpl *getImplementation() { return mVertexArray; }
- const rx::VertexArrayImpl *getImplementation() const { return mVertexArray; }
+ void setLabel(const std::string &label) override;
+ const std::string &getLabel() const override;
- size_t getMaxEnabledAttribute() const { return mData.getMaxEnabledAttribute(); }
+ const VertexBinding &getVertexBinding(size_t bindingIndex) const;
+ const VertexAttribute &getVertexAttribute(size_t attribIndex) const;
+ const VertexBinding &getBindingFromAttribIndex(size_t attribIndex) const
+ {
+ return mState.getBindingFromAttribIndex(attribIndex);
+ }
+
+ void detachBuffer(const Context *context, GLuint bufferName);
+ void setVertexAttribDivisor(const Context *context, size_t index, GLuint divisor);
+ void enableAttribute(size_t attribIndex, bool enabledState);
+ void setVertexAttribPointer(const Context *context,
+ size_t attribIndex,
+ Buffer *boundBuffer,
+ GLint size,
+ GLenum type,
+ bool normalized,
+ bool pureInteger,
+ GLsizei stride,
+ const void *pointer);
+ void setVertexAttribFormat(size_t attribIndex,
+ GLint size,
+ GLenum type,
+ bool normalized,
+ bool pureInteger,
+ GLuint relativeOffset);
+ void bindVertexBuffer(const Context *context,
+ size_t bindingIndex,
+ Buffer *boundBuffer,
+ GLintptr offset,
+ GLsizei stride);
+ void setVertexAttribBinding(const Context *context, size_t attribIndex, GLuint bindingIndex);
+ void setVertexBindingDivisor(size_t bindingIndex, GLuint divisor);
+ void setVertexAttribFormatImpl(size_t attribIndex,
+ GLint size,
+ GLenum type,
+ bool normalized,
+ bool pureInteger,
+ GLuint relativeOffset);
+ void bindVertexBufferImpl(const Context *context,
+ size_t bindingIndex,
+ Buffer *boundBuffer,
+ GLintptr offset,
+ GLsizei stride);
+
+ void setElementArrayBuffer(const Context *context, Buffer *buffer);
+
+ const BindingPointer<Buffer> &getElementArrayBuffer() const
+ {
+ return mState.getElementArrayBuffer();
+ }
+ size_t getMaxAttribs() const { return mState.getMaxAttribs(); }
+ size_t getMaxBindings() const { return mState.getMaxBindings(); }
- class Data final : public angle::NonCopyable
+ const std::vector<VertexAttribute> &getVertexAttributes() const
{
- public:
- explicit Data(size_t maxAttribs);
- ~Data();
-
- const std::string &getLabel() const { return mLabel; }
-
- const BindingPointer<Buffer> &getElementArrayBuffer() const { return mElementArrayBuffer; }
- size_t getMaxAttribs() const { return mVertexAttributes.size(); }
- size_t getMaxEnabledAttribute() const { return mMaxEnabledAttribute; }
- const std::vector<VertexAttribute> &getVertexAttributes() const { return mVertexAttributes; }
- const VertexAttribute &getVertexAttribute(size_t index) const
- {
- return mVertexAttributes[index];
- }
-
- private:
- friend class VertexArray;
- std::string mLabel;
- std::vector<VertexAttribute> mVertexAttributes;
- BindingPointer<Buffer> mElementArrayBuffer;
- size_t mMaxEnabledAttribute;
- };
+ return mState.getVertexAttributes();
+ }
+ const std::vector<VertexBinding> &getVertexBindings() const
+ {
+ return mState.getVertexBindings();
+ }
+
+ rx::VertexArrayImpl *getImplementation() const { return mVertexArray; }
+
+ size_t getMaxEnabledAttribute() const { return mState.getMaxEnabledAttribute(); }
enum DirtyBitType
{
@@ -98,28 +161,45 @@ class VertexArray final : public LabeledObject
DIRTY_BIT_ATTRIB_0_POINTER = DIRTY_BIT_ATTRIB_MAX_ENABLED,
DIRTY_BIT_ATTRIB_MAX_POINTER = DIRTY_BIT_ATTRIB_0_POINTER + gl::MAX_VERTEX_ATTRIBS,
- // Reserve bits for divisors
- DIRTY_BIT_ATTRIB_0_DIVISOR = DIRTY_BIT_ATTRIB_MAX_POINTER,
- DIRTY_BIT_ATTRIB_MAX_DIVISOR = DIRTY_BIT_ATTRIB_0_DIVISOR + gl::MAX_VERTEX_ATTRIBS,
+ // Reserve bits for changes to VertexAttribFormat
+ DIRTY_BIT_ATTRIB_0_FORMAT = DIRTY_BIT_ATTRIB_MAX_POINTER,
+ DIRTY_BIT_ATTRIB_MAX_FORMAT = DIRTY_BIT_ATTRIB_0_FORMAT + gl::MAX_VERTEX_ATTRIBS,
+
+ // Reserve bits for changes to VertexAttribBinding
+ DIRTY_BIT_ATTRIB_0_BINDING = DIRTY_BIT_ATTRIB_MAX_FORMAT,
+ DIRTY_BIT_ATTRIB_MAX_BINDING = DIRTY_BIT_ATTRIB_0_BINDING + gl::MAX_VERTEX_ATTRIBS,
+
+ // Reserve bits for changes to BindVertexBuffer
+ DIRTY_BIT_BINDING_0_BUFFER = DIRTY_BIT_ATTRIB_MAX_BINDING,
+ DIRTY_BIT_BINDING_MAX_BUFFER = DIRTY_BIT_BINDING_0_BUFFER + gl::MAX_VERTEX_ATTRIB_BINDINGS,
- DIRTY_BIT_UNKNOWN = DIRTY_BIT_ATTRIB_MAX_DIVISOR,
+ // Reserve bits for binding divisors
+ DIRTY_BIT_BINDING_0_DIVISOR = DIRTY_BIT_BINDING_MAX_BUFFER,
+ DIRTY_BIT_BINDING_MAX_DIVISOR =
+ DIRTY_BIT_BINDING_0_DIVISOR + gl::MAX_VERTEX_ATTRIB_BINDINGS,
+
+ DIRTY_BIT_UNKNOWN = DIRTY_BIT_BINDING_MAX_DIVISOR,
DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN,
};
- typedef std::bitset<DIRTY_BIT_MAX> DirtyBits;
+ using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
+
+ static size_t GetVertexIndexFromDirtyBit(size_t dirtyBit);
- void syncImplState();
+ void syncState(const Context *context);
bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
private:
- GLuint mId;
+ ~VertexArray() override;
- rx::VertexArrayImpl *mVertexArray;
+ GLuint mId;
- Data mData;
+ VertexArrayState mState;
DirtyBits mDirtyBits;
+
+ rx::VertexArrayImpl *mVertexArray;
};
-}
+} // namespace gl
#endif // LIBANGLE_VERTEXARRAY_H_
diff --git a/src/3rdparty/angle/src/libANGLE/VertexAttribute.cpp b/src/3rdparty/angle/src/libANGLE/VertexAttribute.cpp
index 13d78fd13c..20f7452fa5 100644
--- a/src/3rdparty/angle/src/libANGLE/VertexAttribute.cpp
+++ b/src/3rdparty/angle/src/libANGLE/VertexAttribute.cpp
@@ -3,7 +3,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// Implementation of the state class for mananging GLES 3 Vertex Array Objects.
+// Implementation of the state classes for mananging GLES 3.1 Vertex Array Objects.
//
#include "libANGLE/VertexAttribute.h"
@@ -11,16 +11,74 @@
namespace gl
{
-VertexAttribute::VertexAttribute()
+// [OpenGL ES 3.1] (November 3, 2016) Section 20 Page 361
+// Table 20.2: Vertex Array Object State
+VertexBinding::VertexBinding() : mStride(16u), mDivisor(0), mOffset(0)
+{
+}
+
+VertexBinding::VertexBinding(VertexBinding &&binding)
+{
+ *this = std::move(binding);
+}
+
+VertexBinding::~VertexBinding()
+{
+}
+
+VertexBinding &VertexBinding::operator=(VertexBinding &&binding)
+{
+ if (this != &binding)
+ {
+ mStride = binding.mStride;
+ mDivisor = binding.mDivisor;
+ mOffset = binding.mOffset;
+ std::swap(binding.mBuffer, mBuffer);
+ }
+ return *this;
+}
+
+VertexAttribute::VertexAttribute(GLuint bindingIndex)
: enabled(false),
type(GL_FLOAT),
- size(4),
+ size(4u),
normalized(false),
pureInteger(false),
- stride(0),
- pointer(NULL),
- divisor(0)
+ pointer(nullptr),
+ relativeOffset(0),
+ vertexAttribArrayStride(0),
+ bindingIndex(bindingIndex)
+{
+}
+
+VertexAttribute::VertexAttribute(VertexAttribute &&attrib)
+ : enabled(attrib.enabled),
+ type(attrib.type),
+ size(attrib.size),
+ normalized(attrib.normalized),
+ pureInteger(attrib.pureInteger),
+ pointer(attrib.pointer),
+ relativeOffset(attrib.relativeOffset),
+ vertexAttribArrayStride(attrib.vertexAttribArrayStride),
+ bindingIndex(attrib.bindingIndex)
+{
+}
+
+VertexAttribute &VertexAttribute::operator=(VertexAttribute &&attrib)
{
+ if (this != &attrib)
+ {
+ enabled = attrib.enabled;
+ type = attrib.type;
+ size = attrib.size;
+ normalized = attrib.normalized;
+ pureInteger = attrib.pureInteger;
+ pointer = attrib.pointer;
+ relativeOffset = attrib.relativeOffset;
+ vertexAttribArrayStride = attrib.vertexAttribArrayStride;
+ bindingIndex = attrib.bindingIndex;
+ }
+ return *this;
}
size_t ComputeVertexAttributeTypeSize(const VertexAttribute& attrib)
@@ -43,32 +101,62 @@ size_t ComputeVertexAttributeTypeSize(const VertexAttribute& attrib)
}
}
-size_t ComputeVertexAttributeStride(const VertexAttribute& attrib)
+size_t ComputeVertexAttributeStride(const VertexAttribute &attrib, const VertexBinding &binding)
{
- if (!attrib.enabled)
- {
- return 16;
- }
- return attrib.stride ? attrib.stride : ComputeVertexAttributeTypeSize(attrib);
+ // In ES 3.1, VertexAttribPointer will store the type size in the binding stride.
+ // Hence, rendering always uses the binding's stride.
+ return attrib.enabled ? binding.getStride() : 16u;
+}
+
+// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
+GLintptr ComputeVertexAttributeOffset(const VertexAttribute &attrib, const VertexBinding &binding)
+{
+ return attrib.relativeOffset + binding.getOffset();
}
-size_t ComputeVertexAttributeElementCount(const VertexAttribute &attrib,
- size_t drawCount,
- size_t instanceCount)
+size_t ComputeVertexBindingElementCount(GLuint divisor, size_t drawCount, size_t instanceCount)
{
// For instanced rendering, we draw "instanceDrawCount" sets of "vertexDrawCount" vertices.
//
// A vertex attribute with a positive divisor loads one instanced vertex for every set of
// non-instanced vertices, and the instanced vertex index advances once every "mDivisor"
// instances.
- if (instanceCount > 0 && attrib.divisor > 0)
+ if (instanceCount > 0 && divisor > 0)
{
// When instanceDrawCount is not a multiple attrib.divisor, the division must round up.
// For instance, with 5 non-instanced vertices and a divisor equal to 3, we need 2 instanced
// vertices.
- return (instanceCount + attrib.divisor - 1u) / attrib.divisor;
+ return (instanceCount + divisor - 1u) / divisor;
}
return drawCount;
}
+
+GLenum GetVertexAttributeBaseType(const VertexAttribute &attrib)
+{
+ if (attrib.pureInteger)
+ {
+ switch (attrib.type)
+ {
+ case GL_BYTE:
+ case GL_SHORT:
+ case GL_INT:
+ return GL_INT;
+
+ case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_SHORT:
+ case GL_UNSIGNED_INT:
+ return GL_UNSIGNED_INT;
+
+ default:
+ UNREACHABLE();
+ return GL_NONE;
+ }
+ }
+ else
+ {
+ return GL_FLOAT;
+ }
}
+
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/VertexAttribute.h b/src/3rdparty/angle/src/libANGLE/VertexAttribute.h
index d1ee1b47a2..c531bece7c 100644
--- a/src/3rdparty/angle/src/libANGLE/VertexAttribute.h
+++ b/src/3rdparty/angle/src/libANGLE/VertexAttribute.h
@@ -3,7 +3,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// Helper structure describing a single vertex attribute
+// Helper structures about Generic Vertex Attribute.
//
#ifndef LIBANGLE_VERTEXATTRIBUTE_H_
@@ -13,45 +13,77 @@
namespace gl
{
+class VertexArray;
-struct VertexAttribute
+//
+// Implementation of Generic Vertex Attribute Bindings for ES3.1. The members are intentionally made
+// private in order to hide implementation details.
+//
+class VertexBinding final : angle::NonCopyable
{
- bool enabled; // From glEnable/DisableVertexAttribArray
+ public:
+ VertexBinding();
+ VertexBinding(VertexBinding &&binding);
+ ~VertexBinding();
+ VertexBinding &operator=(VertexBinding &&binding);
+
+ GLuint getStride() const { return mStride; }
+ void setStride(GLuint strideIn) { mStride = strideIn; }
+
+ GLuint getDivisor() const { return mDivisor; }
+ void setDivisor(GLuint divisorIn) { mDivisor = divisorIn; }
+
+ GLintptr getOffset() const { return mOffset; }
+ void setOffset(GLintptr offsetIn) { mOffset = offsetIn; }
+
+ const BindingPointer<Buffer> &getBuffer() const { return mBuffer; }
+ void setBuffer(const gl::Context *context, Buffer *bufferIn) { mBuffer.set(context, bufferIn); }
+
+ private:
+ GLuint mStride;
+ GLuint mDivisor;
+ GLintptr mOffset;
+
+ BindingPointer<Buffer> mBuffer;
+};
+//
+// Implementation of Generic Vertex Attributes for ES3.1
+//
+struct VertexAttribute final : private angle::NonCopyable
+{
+ explicit VertexAttribute(GLuint bindingIndex);
+ explicit VertexAttribute(VertexAttribute &&attrib);
+ VertexAttribute &operator=(VertexAttribute &&attrib);
+
+ bool enabled; // For glEnable/DisableVertexAttribArray
GLenum type;
GLuint size;
bool normalized;
bool pureInteger;
- GLuint stride; // 0 means natural stride
- union
- {
- const GLvoid *pointer;
- GLintptr offset;
- };
- BindingPointer<Buffer> buffer; // Captured when glVertexAttribPointer is called.
-
- GLuint divisor;
+ const void *pointer;
+ GLuint relativeOffset;
- VertexAttribute();
+ GLuint vertexAttribArrayStride; // ONLY for queries of VERTEX_ATTRIB_ARRAY_STRIDE
+ GLuint bindingIndex;
};
-bool operator==(const VertexAttribute &a, const VertexAttribute &b);
-bool operator!=(const VertexAttribute &a, const VertexAttribute &b);
+size_t ComputeVertexAttributeTypeSize(const VertexAttribute &attrib);
+
+// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
+size_t ComputeVertexAttributeStride(const VertexAttribute &attrib, const VertexBinding &binding);
+
+// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
+GLintptr ComputeVertexAttributeOffset(const VertexAttribute &attrib, const VertexBinding &binding);
-template <typename T>
-T QuerySingleVertexAttributeParameter(const VertexAttribute& attrib, GLenum pname);
+size_t ComputeVertexBindingElementCount(GLuint divisor, size_t drawCount, size_t instanceCount);
-size_t ComputeVertexAttributeTypeSize(const VertexAttribute& attrib);
-size_t ComputeVertexAttributeStride(const VertexAttribute& attrib);
-size_t ComputeVertexAttributeElementCount(const VertexAttribute &attrib,
- size_t drawCount,
- size_t instanceCount);
+GLenum GetVertexAttributeBaseType(const VertexAttribute &attrib);
struct VertexAttribCurrentValueData
{
- union
- {
+ union {
GLfloat FloatValues[4];
GLint IntValues[4];
GLuint UnsignedIntValues[4];
@@ -68,8 +100,8 @@ struct VertexAttribCurrentValueData
bool operator==(const VertexAttribCurrentValueData &a, const VertexAttribCurrentValueData &b);
bool operator!=(const VertexAttribCurrentValueData &a, const VertexAttribCurrentValueData &b);
-}
+} // namespace gl
#include "VertexAttribute.inl"
-#endif // LIBANGLE_VERTEXATTRIBUTE_H_
+#endif // LIBANGLE_VERTEXATTRIBUTE_H_
diff --git a/src/3rdparty/angle/src/libANGLE/VertexAttribute.inl b/src/3rdparty/angle/src/libANGLE/VertexAttribute.inl
index 0cd31f6762..1c1843e46f 100644
--- a/src/3rdparty/angle/src/libANGLE/VertexAttribute.inl
+++ b/src/3rdparty/angle/src/libANGLE/VertexAttribute.inl
@@ -9,51 +9,6 @@
namespace gl
{
-inline bool operator==(const VertexAttribute &a, const VertexAttribute &b)
-{
- return a.enabled == b.enabled &&
- a.type == b.type &&
- a.size == b.size &&
- a.normalized == b.normalized &&
- a.pureInteger == b.pureInteger &&
- a.stride == b.stride &&
- a.pointer == b.pointer &&
- a.buffer.get() == b.buffer.get() &&
- a.divisor == b.divisor;
-}
-
-inline bool operator!=(const VertexAttribute &a, const VertexAttribute &b)
-{
- return !(a == b);
-}
-
-template <typename T>
-T QuerySingleVertexAttributeParameter(const VertexAttribute& attrib, GLenum pname)
-{
- switch (pname)
- {
- case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
- return static_cast<T>(attrib.enabled ? GL_TRUE : GL_FALSE);
- case GL_VERTEX_ATTRIB_ARRAY_SIZE:
- return static_cast<T>(attrib.size);
- case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
- return static_cast<T>(attrib.stride);
- case GL_VERTEX_ATTRIB_ARRAY_TYPE:
- return static_cast<T>(attrib.type);
- case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
- return static_cast<T>(attrib.normalized ? GL_TRUE : GL_FALSE);
- case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
- return static_cast<T>(attrib.buffer.id());
- case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
- return static_cast<T>(attrib.divisor);
- case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
- return static_cast<T>(attrib.pureInteger ? GL_TRUE : GL_FALSE);
- default:
- UNREACHABLE();
- return static_cast<T>(0);
- }
-}
-
inline VertexAttribCurrentValueData::VertexAttribCurrentValueData()
: Type(GL_FLOAT)
{
@@ -100,4 +55,4 @@ inline bool operator!=(const VertexAttribCurrentValueData &a, const VertexAttrib
return !(a == b);
}
-}
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/Workarounds.h b/src/3rdparty/angle/src/libANGLE/Workarounds.h
new file mode 100644
index 0000000000..898031d78d
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/Workarounds.h
@@ -0,0 +1,29 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Workarounds.h: Workarounds for driver bugs and other behaviors seen
+// on all platforms.
+
+#ifndef LIBANGLE_WORKAROUNDS_H_
+#define LIBANGLE_WORKAROUNDS_H_
+
+namespace gl
+{
+
+struct Workarounds
+{
+ // Force the context to be lost (via KHR_robustness) if a GL_OUT_OF_MEMORY error occurs. The
+ // driver may be in an inconsistent state if this happens, and some users of ANGLE rely on this
+ // notification to prevent further execution.
+ bool loseContextOnOutOfMemory = false;
+
+ // Program binaries don't contain transform feedback varyings on Qualcomm GPUs.
+ // Work around this by disabling the program cache for programs with transform feedback.
+ bool disableProgramCachingForTransformFeedback = false;
+};
+} // namespace gl
+
+#endif // LIBANGLE_WORKAROUNDS_H_
diff --git a/src/3rdparty/angle/src/libANGLE/WorkerThread.cpp b/src/3rdparty/angle/src/libANGLE/WorkerThread.cpp
new file mode 100644
index 0000000000..b5d789ef93
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/WorkerThread.cpp
@@ -0,0 +1,157 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// WorkerThread:
+// Task running thread for ANGLE, similar to a TaskRunner in Chromium.
+// Might be implemented differently depending on platform.
+//
+
+#include "libANGLE/WorkerThread.h"
+
+namespace angle
+{
+
+namespace priv
+{
+// SingleThreadedWorkerPool implementation.
+SingleThreadedWorkerPool::SingleThreadedWorkerPool(size_t maxThreads)
+ : WorkerThreadPoolBase(maxThreads)
+{
+}
+
+SingleThreadedWorkerPool::~SingleThreadedWorkerPool()
+{
+}
+
+SingleThreadedWaitableEvent SingleThreadedWorkerPool::postWorkerTaskImpl(Closure *task)
+{
+ (*task)();
+ return SingleThreadedWaitableEvent(EventResetPolicy::Automatic, EventInitialState::Signaled);
+}
+
+// SingleThreadedWaitableEvent implementation.
+SingleThreadedWaitableEvent::SingleThreadedWaitableEvent()
+ : SingleThreadedWaitableEvent(EventResetPolicy::Automatic, EventInitialState::NonSignaled)
+{
+}
+
+SingleThreadedWaitableEvent::SingleThreadedWaitableEvent(EventResetPolicy resetPolicy,
+ EventInitialState initialState)
+ : WaitableEventBase(resetPolicy, initialState)
+{
+}
+
+SingleThreadedWaitableEvent::~SingleThreadedWaitableEvent()
+{
+}
+
+SingleThreadedWaitableEvent::SingleThreadedWaitableEvent(SingleThreadedWaitableEvent &&other)
+ : WaitableEventBase(std::move(other))
+{
+}
+
+SingleThreadedWaitableEvent &SingleThreadedWaitableEvent::operator=(
+ SingleThreadedWaitableEvent &&other)
+{
+ return copyBase(std::move(other));
+}
+
+void SingleThreadedWaitableEvent::resetImpl()
+{
+ mSignaled = false;
+}
+
+void SingleThreadedWaitableEvent::waitImpl()
+{
+}
+
+void SingleThreadedWaitableEvent::signalImpl()
+{
+ mSignaled = true;
+}
+
+#if (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+// AsyncWorkerPool implementation.
+AsyncWorkerPool::AsyncWorkerPool(size_t maxThreads) : WorkerThreadPoolBase(maxThreads)
+{
+}
+
+AsyncWorkerPool::~AsyncWorkerPool()
+{
+}
+
+AsyncWaitableEvent AsyncWorkerPool::postWorkerTaskImpl(Closure *task)
+{
+ auto future = std::async(std::launch::async, [task] { (*task)(); });
+
+ AsyncWaitableEvent waitable(EventResetPolicy::Automatic, EventInitialState::NonSignaled);
+
+ waitable.setFuture(std::move(future));
+
+ return waitable;
+}
+
+// AsyncWaitableEvent implementation.
+AsyncWaitableEvent::AsyncWaitableEvent()
+ : AsyncWaitableEvent(EventResetPolicy::Automatic, EventInitialState::NonSignaled)
+{
+}
+
+AsyncWaitableEvent::AsyncWaitableEvent(EventResetPolicy resetPolicy, EventInitialState initialState)
+ : WaitableEventBase(resetPolicy, initialState)
+{
+}
+
+AsyncWaitableEvent::~AsyncWaitableEvent()
+{
+}
+
+AsyncWaitableEvent::AsyncWaitableEvent(AsyncWaitableEvent &&other)
+ : WaitableEventBase(std::move(other)), mFuture(std::move(other.mFuture))
+{
+}
+
+AsyncWaitableEvent &AsyncWaitableEvent::operator=(AsyncWaitableEvent &&other)
+{
+ std::swap(mFuture, other.mFuture);
+ return copyBase(std::move(other));
+}
+
+void AsyncWaitableEvent::setFuture(std::future<void> &&future)
+{
+ mFuture = std::move(future);
+}
+
+void AsyncWaitableEvent::resetImpl()
+{
+ mSignaled = false;
+ mFuture = std::future<void>();
+}
+
+void AsyncWaitableEvent::waitImpl()
+{
+ if (mSignaled || !mFuture.valid())
+ {
+ return;
+ }
+
+ mFuture.wait();
+ signal();
+}
+
+void AsyncWaitableEvent::signalImpl()
+{
+ mSignaled = true;
+
+ if (mResetPolicy == EventResetPolicy::Automatic)
+ {
+ reset();
+ }
+}
+#endif // (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+
+} // namespace priv
+
+} // namespace angle
diff --git a/src/3rdparty/angle/src/libANGLE/WorkerThread.h b/src/3rdparty/angle/src/libANGLE/WorkerThread.h
new file mode 100644
index 0000000000..f6b81dce21
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/WorkerThread.h
@@ -0,0 +1,284 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// WorkerThread:
+// Asychronous tasks/threads for ANGLE, similar to a TaskRunner in Chromium.
+// Can be implemented as different targets, depending on platform.
+//
+
+#ifndef LIBANGLE_WORKER_THREAD_H_
+#define LIBANGLE_WORKER_THREAD_H_
+
+#include <array>
+#include <vector>
+
+#include "common/debug.h"
+#include "libANGLE/features.h"
+
+#if (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+#include <future>
+#endif // (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+
+namespace angle
+{
+// Indicates whether a WaitableEvent should automatically reset the event state after a single
+// waiting thread has been released or remain signaled until reset() is manually invoked.
+enum class EventResetPolicy
+{
+ Manual,
+ Automatic
+};
+
+// Specify the initial state on creation.
+enum class EventInitialState
+{
+ NonSignaled,
+ Signaled
+};
+
+// A callback function with no return value and no arguments.
+class Closure
+{
+ public:
+ virtual ~Closure() = default;
+ virtual void operator()() = 0;
+};
+
+namespace priv
+{
+// An event that we can wait on, useful for joining worker threads.
+template <typename Impl>
+class WaitableEventBase : angle::NonCopyable
+{
+ public:
+ WaitableEventBase(EventResetPolicy resetPolicy, EventInitialState initialState);
+
+ WaitableEventBase(WaitableEventBase &&other);
+
+ // Puts the event in the un-signaled state.
+ void reset();
+
+ // Waits indefinitely for the event to be signaled.
+ void wait();
+
+ // Puts the event in the signaled state, causing any thread blocked on Wait to be woken up.
+ // The event state is reset to non-signaled after a waiting thread has been released.
+ void signal();
+
+ protected:
+ Impl &copyBase(Impl &&other);
+
+ template <size_t Count>
+ static size_t WaitManyBase(std::array<Impl, Count> *waitables);
+
+ EventResetPolicy mResetPolicy;
+ bool mSignaled;
+};
+
+template <typename Impl>
+WaitableEventBase<Impl>::WaitableEventBase(EventResetPolicy resetPolicy,
+ EventInitialState initialState)
+ : mResetPolicy(resetPolicy), mSignaled(initialState == EventInitialState::Signaled)
+{
+}
+
+template <typename Impl>
+WaitableEventBase<Impl>::WaitableEventBase(WaitableEventBase &&other)
+ : mResetPolicy(other.mResetPolicy), mSignaled(other.mSignaled)
+{
+}
+
+template <typename Impl>
+void WaitableEventBase<Impl>::reset()
+{
+ static_cast<Impl *>(this)->resetImpl();
+}
+
+template <typename Impl>
+void WaitableEventBase<Impl>::wait()
+{
+ static_cast<Impl *>(this)->waitImpl();
+}
+
+template <typename Impl>
+void WaitableEventBase<Impl>::signal()
+{
+ static_cast<Impl *>(this)->signalImpl();
+}
+
+template <typename Impl>
+template <size_t Count>
+// static
+size_t WaitableEventBase<Impl>::WaitManyBase(std::array<Impl, Count> *waitables)
+{
+ ASSERT(Count > 0);
+
+ for (size_t index = 0; index < Count; ++index)
+ {
+ (*waitables)[index].wait();
+ }
+
+ return 0;
+}
+
+template <typename Impl>
+Impl &WaitableEventBase<Impl>::copyBase(Impl &&other)
+{
+ std::swap(mSignaled, other.mSignaled);
+ std::swap(mResetPolicy, other.mResetPolicy);
+ return *static_cast<Impl *>(this);
+}
+
+class SingleThreadedWaitableEvent : public WaitableEventBase<SingleThreadedWaitableEvent>
+{
+ public:
+ SingleThreadedWaitableEvent();
+ SingleThreadedWaitableEvent(EventResetPolicy resetPolicy, EventInitialState initialState);
+ ~SingleThreadedWaitableEvent();
+
+ SingleThreadedWaitableEvent(SingleThreadedWaitableEvent &&other);
+ SingleThreadedWaitableEvent &operator=(SingleThreadedWaitableEvent &&other);
+
+ void resetImpl();
+ void waitImpl();
+ void signalImpl();
+
+ // Wait, synchronously, on multiple events.
+ // returns the index of a WaitableEvent which has been signaled.
+ template <size_t Count>
+ static size_t WaitMany(std::array<SingleThreadedWaitableEvent, Count> *waitables);
+};
+
+template <size_t Count>
+// static
+size_t SingleThreadedWaitableEvent::WaitMany(
+ std::array<SingleThreadedWaitableEvent, Count> *waitables)
+{
+ return WaitableEventBase<SingleThreadedWaitableEvent>::WaitManyBase(waitables);
+}
+
+#if (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+class AsyncWaitableEvent : public WaitableEventBase<AsyncWaitableEvent>
+{
+ public:
+ AsyncWaitableEvent();
+ AsyncWaitableEvent(EventResetPolicy resetPolicy, EventInitialState initialState);
+ ~AsyncWaitableEvent();
+
+ AsyncWaitableEvent(AsyncWaitableEvent &&other);
+ AsyncWaitableEvent &operator=(AsyncWaitableEvent &&other);
+
+ void resetImpl();
+ void waitImpl();
+ void signalImpl();
+
+ // Wait, synchronously, on multiple events.
+ // returns the index of a WaitableEvent which has been signaled.
+ template <size_t Count>
+ static size_t WaitMany(std::array<AsyncWaitableEvent, Count> *waitables);
+
+ private:
+ friend class AsyncWorkerPool;
+ void setFuture(std::future<void> &&future);
+
+ std::future<void> mFuture;
+};
+
+template <size_t Count>
+// static
+size_t AsyncWaitableEvent::WaitMany(std::array<AsyncWaitableEvent, Count> *waitables)
+{
+ return WaitableEventBase<AsyncWaitableEvent>::WaitManyBase(waitables);
+}
+#endif // (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+
+// The traits class allows the the thread pool to return the "Typed" waitable event from postTask.
+// Otherwise postTask would always think it returns the current active type, so the unit tests
+// could not run on multiple worker types in the same compilation.
+template <typename Impl>
+struct WorkerThreadPoolTraits;
+
+class SingleThreadedWorkerPool;
+template <>
+struct WorkerThreadPoolTraits<SingleThreadedWorkerPool>
+{
+ using WaitableEventType = SingleThreadedWaitableEvent;
+};
+
+#if (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+class AsyncWorkerPool;
+template <>
+struct WorkerThreadPoolTraits<AsyncWorkerPool>
+{
+ using WaitableEventType = AsyncWaitableEvent;
+};
+#endif // (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+
+// Request WorkerThreads from the WorkerThreadPool. Each pool can keep worker threads around so
+// we avoid the costly spin up and spin down time.
+template <typename Impl>
+class WorkerThreadPoolBase : angle::NonCopyable
+{
+ public:
+ WorkerThreadPoolBase(size_t maxThreads);
+ ~WorkerThreadPoolBase();
+
+ using WaitableEventType = typename WorkerThreadPoolTraits<Impl>::WaitableEventType;
+
+ // Returns an event to wait on for the task to finish.
+ // If the pool fails to create the task, returns null.
+ WaitableEventType postWorkerTask(Closure *task);
+};
+
+template <typename Impl>
+WorkerThreadPoolBase<Impl>::WorkerThreadPoolBase(size_t maxThreads)
+{
+}
+
+template <typename Impl>
+WorkerThreadPoolBase<Impl>::~WorkerThreadPoolBase()
+{
+}
+
+template <typename Impl>
+typename WorkerThreadPoolBase<Impl>::WaitableEventType WorkerThreadPoolBase<Impl>::postWorkerTask(
+ Closure *task)
+{
+ return static_cast<Impl *>(this)->postWorkerTaskImpl(task);
+}
+
+class SingleThreadedWorkerPool : public WorkerThreadPoolBase<SingleThreadedWorkerPool>
+{
+ public:
+ SingleThreadedWorkerPool(size_t maxThreads);
+ ~SingleThreadedWorkerPool();
+
+ SingleThreadedWaitableEvent postWorkerTaskImpl(Closure *task);
+};
+
+#if (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+class AsyncWorkerPool : public WorkerThreadPoolBase<AsyncWorkerPool>
+{
+ public:
+ AsyncWorkerPool(size_t maxThreads);
+ ~AsyncWorkerPool();
+
+ AsyncWaitableEvent postWorkerTaskImpl(Closure *task);
+};
+#endif // (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+
+} // namespace priv
+
+#if (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+using WaitableEvent = priv::AsyncWaitableEvent;
+using WorkerThreadPool = priv::AsyncWorkerPool;
+#else
+using WaitableEvent = priv::SingleThreadedWaitableEvent;
+using WorkerThreadPool = priv::SingleThreadedWorkerPool;
+#endif // (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+
+} // namespace angle
+
+#endif // LIBANGLE_WORKER_THREAD_H_
diff --git a/src/3rdparty/angle/src/libANGLE/angletypes.cpp b/src/3rdparty/angle/src/libANGLE/angletypes.cpp
index fa5b157906..702d391e46 100644
--- a/src/3rdparty/angle/src/libANGLE/angletypes.cpp
+++ b/src/3rdparty/angle/src/libANGLE/angletypes.cpp
@@ -39,39 +39,143 @@ PrimitiveType GetPrimitiveType(GLenum drawMode)
}
}
+RasterizerState::RasterizerState()
+{
+ memset(this, 0, sizeof(RasterizerState));
+
+ rasterizerDiscard = false;
+ cullFace = false;
+ cullMode = CullFaceMode::Back;
+ frontFace = GL_CCW;
+ polygonOffsetFill = false;
+ polygonOffsetFactor = 0.0f;
+ polygonOffsetUnits = 0.0f;
+ pointDrawMode = false;
+ multiSample = false;
+}
+
+bool operator==(const RasterizerState &a, const RasterizerState &b)
+{
+ return memcmp(&a, &b, sizeof(RasterizerState)) == 0;
+}
+
+bool operator!=(const RasterizerState &a, const RasterizerState &b)
+{
+ return !(a == b);
+}
+
+BlendState::BlendState()
+{
+ memset(this, 0, sizeof(BlendState));
+
+ blend = false;
+ sourceBlendRGB = GL_ONE;
+ sourceBlendAlpha = GL_ONE;
+ destBlendRGB = GL_ZERO;
+ destBlendAlpha = GL_ZERO;
+ blendEquationRGB = GL_FUNC_ADD;
+ blendEquationAlpha = GL_FUNC_ADD;
+ sampleAlphaToCoverage = false;
+ dither = true;
+}
+
+BlendState::BlendState(const BlendState &other)
+{
+ memcpy(this, &other, sizeof(BlendState));
+}
+
+bool operator==(const BlendState &a, const BlendState &b)
+{
+ return memcmp(&a, &b, sizeof(BlendState)) == 0;
+}
+
+bool operator!=(const BlendState &a, const BlendState &b)
+{
+ return !(a == b);
+}
+
+DepthStencilState::DepthStencilState()
+{
+ memset(this, 0, sizeof(DepthStencilState));
+
+ depthTest = false;
+ depthFunc = GL_LESS;
+ depthMask = true;
+ stencilTest = false;
+ stencilFunc = GL_ALWAYS;
+ stencilMask = static_cast<GLuint>(-1);
+ stencilWritemask = static_cast<GLuint>(-1);
+ stencilBackFunc = GL_ALWAYS;
+ stencilBackMask = static_cast<GLuint>(-1);
+ stencilBackWritemask = static_cast<GLuint>(-1);
+ stencilFail = GL_KEEP;
+ stencilPassDepthFail = GL_KEEP;
+ stencilPassDepthPass = GL_KEEP;
+ stencilBackFail = GL_KEEP;
+ stencilBackPassDepthFail = GL_KEEP;
+ stencilBackPassDepthPass = GL_KEEP;
+}
+
+DepthStencilState::DepthStencilState(const DepthStencilState &other)
+{
+ memcpy(this, &other, sizeof(DepthStencilState));
+}
+
+bool operator==(const DepthStencilState &a, const DepthStencilState &b)
+{
+ return memcmp(&a, &b, sizeof(DepthStencilState)) == 0;
+}
+
+bool operator!=(const DepthStencilState &a, const DepthStencilState &b)
+{
+ return !(a == b);
+}
+
SamplerState::SamplerState()
- : minFilter(GL_NEAREST_MIPMAP_LINEAR),
- magFilter(GL_LINEAR),
- wrapS(GL_REPEAT),
- wrapT(GL_REPEAT),
- wrapR(GL_REPEAT),
- maxAnisotropy(1.0f),
- minLod(-1000.0f),
- maxLod(1000.0f),
- compareMode(GL_NONE),
- compareFunc(GL_LEQUAL)
{
+ memset(this, 0, sizeof(SamplerState));
+
+ minFilter = GL_NEAREST_MIPMAP_LINEAR;
+ magFilter = GL_LINEAR;
+ wrapS = GL_REPEAT;
+ wrapT = GL_REPEAT;
+ wrapR = GL_REPEAT;
+ maxAnisotropy = 1.0f;
+ minLod = -1000.0f;
+ maxLod = 1000.0f;
+ compareMode = GL_NONE;
+ compareFunc = GL_LEQUAL;
+ sRGBDecode = GL_DECODE_EXT;
}
-TextureState::TextureState()
- : swizzleRed(GL_RED),
- swizzleGreen(GL_GREEN),
- swizzleBlue(GL_BLUE),
- swizzleAlpha(GL_ALPHA),
- samplerState(),
- baseLevel(0),
- maxLevel(1000),
- immutableFormat(false),
- immutableLevels(0)
+SamplerState::SamplerState(const SamplerState &other) = default;
+
+// static
+SamplerState SamplerState::CreateDefaultForTarget(GLenum target)
{
+ SamplerState state;
+
+ // According to OES_EGL_image_external and ARB_texture_rectangle: For external textures, the
+ // default min filter is GL_LINEAR and the default s and t wrap modes are GL_CLAMP_TO_EDGE.
+ if (target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE)
+ {
+ state.minFilter = GL_LINEAR;
+ state.wrapS = GL_CLAMP_TO_EDGE;
+ state.wrapT = GL_CLAMP_TO_EDGE;
+ }
+
+ return state;
}
-bool TextureState::swizzleRequired() const
+ImageUnit::ImageUnit()
+ : texture(), level(0), layered(false), layer(0), access(GL_READ_ONLY), format(GL_R32UI)
{
- return swizzleRed != GL_RED || swizzleGreen != GL_GREEN ||
- swizzleBlue != GL_BLUE || swizzleAlpha != GL_ALPHA;
}
+ImageUnit::ImageUnit(const ImageUnit &other) = default;
+
+ImageUnit::~ImageUnit() = default;
+
static void MinMax(int a, int b, int *minimum, int *maximum)
{
if (a < b)
@@ -133,6 +237,16 @@ bool Box::operator!=(const Box &other) const
return !(*this == other);
}
+bool operator==(const Offset &a, const Offset &b)
+{
+ return a.x == b.x && a.y == b.y && a.z == b.z;
+}
+
+bool operator!=(const Offset &a, const Offset &b)
+{
+ return !(a == b);
+}
+
bool operator==(const Extents &lhs, const Extents &rhs)
{
return lhs.width == rhs.width && lhs.height == rhs.height && lhs.depth == rhs.depth;
@@ -142,4 +256,4 @@ bool operator!=(const Extents &lhs, const Extents &rhs)
{
return !(lhs == rhs);
}
-}
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/angletypes.h b/src/3rdparty/angle/src/libANGLE/angletypes.h
index c29ad06bd2..4f364b090a 100644
--- a/src/3rdparty/angle/src/libANGLE/angletypes.h
+++ b/src/3rdparty/angle/src/libANGLE/angletypes.h
@@ -9,20 +9,22 @@
#ifndef LIBANGLE_ANGLETYPES_H_
#define LIBANGLE_ANGLETYPES_H_
+#include "common/bitset_utils.h"
#include "libANGLE/Constants.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/PackedGLEnums.h"
#include "libANGLE/RefCountObject.h"
#include <stdint.h>
#include <bitset>
+#include <map>
+#include <unordered_map>
namespace gl
{
class Buffer;
-class State;
-class Program;
-struct VertexAttribute;
-struct VertexAttribCurrentValueData;
+class Texture;
enum PrimitiveType
{
@@ -41,31 +43,19 @@ PrimitiveType GetPrimitiveType(GLenum drawMode);
enum SamplerType
{
SAMPLER_PIXEL,
- SAMPLER_VERTEX
+ SAMPLER_VERTEX,
+ SAMPLER_COMPUTE
};
-template <typename T>
-struct Color
+enum ShaderType
{
- T red;
- T green;
- T blue;
- T alpha;
-
- Color() : red(0), green(0), blue(0), alpha(0) { }
- Color(T r, T g, T b, T a) : red(r), green(g), blue(b), alpha(a) { }
+ SHADER_VERTEX,
+ SHADER_FRAGMENT,
+ SHADER_GEOMETRY,
+ SHADER_COMPUTE,
+ SHADER_TYPE_MAX
};
-template <typename T>
-bool operator==(const Color<T> &a, const Color<T> &b);
-
-template <typename T>
-bool operator!=(const Color<T> &a, const Color<T> &b);
-
-typedef Color<float> ColorF;
-typedef Color<int> ColorI;
-typedef Color<unsigned int> ColorUI;
-
struct Rectangle
{
Rectangle() : x(0), y(0), width(0), height(0) {}
@@ -100,6 +90,9 @@ struct Offset
Offset(int x_in, int y_in, int z_in) : x(x_in), y(y_in), z(z_in) { }
};
+bool operator==(const Offset &a, const Offset &b);
+bool operator!=(const Offset &a, const Offset &b);
+
struct Extents
{
int width;
@@ -109,6 +102,9 @@ struct Extents
Extents() : width(0), height(0), depth(0) { }
Extents(int width_, int height_, int depth_) : width(width_), height(height_), depth(depth_) { }
+ Extents(const Extents &other) = default;
+ Extents &operator=(const Extents &other) = default;
+
bool empty() const { return (width * height * depth) == 0; }
};
@@ -131,11 +127,13 @@ struct Box
bool operator!=(const Box &other) const;
};
-
-struct RasterizerState
+struct RasterizerState final
{
+ // This will zero-initialize the struct, including padding.
+ RasterizerState();
+
bool cullFace;
- GLenum cullMode;
+ CullFaceMode cullMode;
GLenum frontFace;
bool polygonOffsetFill;
@@ -148,8 +146,15 @@ struct RasterizerState
bool rasterizerDiscard;
};
-struct BlendState
+bool operator==(const RasterizerState &a, const RasterizerState &b);
+bool operator!=(const RasterizerState &a, const RasterizerState &b);
+
+struct BlendState final
{
+ // This will zero-initialize the struct, including padding.
+ BlendState();
+ BlendState(const BlendState &other);
+
bool blend;
GLenum sourceBlendRGB;
GLenum destBlendRGB;
@@ -168,8 +173,15 @@ struct BlendState
bool dither;
};
-struct DepthStencilState
+bool operator==(const BlendState &a, const BlendState &b);
+bool operator!=(const BlendState &a, const BlendState &b);
+
+struct DepthStencilState final
{
+ // This will zero-initialize the struct, including padding.
+ DepthStencilState();
+ DepthStencilState(const DepthStencilState &other);
+
bool depthTest;
GLenum depthFunc;
bool depthMask;
@@ -189,10 +201,17 @@ struct DepthStencilState
GLuint stencilBackWritemask;
};
+bool operator==(const DepthStencilState &a, const DepthStencilState &b);
+bool operator!=(const DepthStencilState &a, const DepthStencilState &b);
+
// State from Table 6.10 (state per sampler object)
-struct SamplerState
+struct SamplerState final
{
+ // This will zero-initialize the struct, including padding.
SamplerState();
+ SamplerState(const SamplerState &other);
+
+ static SamplerState CreateDefaultForTarget(GLenum target);
GLenum minFilter;
GLenum magFilter;
@@ -209,110 +228,92 @@ struct SamplerState
GLenum compareMode;
GLenum compareFunc;
+
+ GLenum sRGBDecode;
};
bool operator==(const SamplerState &a, const SamplerState &b);
bool operator!=(const SamplerState &a, const SamplerState &b);
-// State from Table 6.9 (state per texture object) in the OpenGL ES 3.0.2 spec.
-struct TextureState
+struct DrawArraysIndirectCommand
{
- TextureState();
-
- GLenum swizzleRed;
- GLenum swizzleGreen;
- GLenum swizzleBlue;
- GLenum swizzleAlpha;
-
- SamplerState samplerState;
-
- GLuint baseLevel;
- GLuint maxLevel;
-
- bool immutableFormat;
- GLuint immutableLevels;
+ GLuint count;
+ GLuint instanceCount;
+ GLuint first;
+ GLuint baseInstance;
+};
+static_assert(sizeof(DrawArraysIndirectCommand) == 16,
+ "Unexpected size of DrawArraysIndirectCommand");
- // From GL_ANGLE_texture_usage
- GLenum usage;
+struct DrawElementsIndirectCommand
+{
+ GLuint count;
+ GLuint primCount;
+ GLuint firstIndex;
+ GLint baseVertex;
+ GLuint baseInstance;
+};
+static_assert(sizeof(DrawElementsIndirectCommand) == 20,
+ "Unexpected size of DrawElementsIndirectCommand");
- bool swizzleRequired() const;
+struct ImageUnit
+{
+ ImageUnit();
+ ImageUnit(const ImageUnit &other);
+ ~ImageUnit();
+
+ BindingPointer<Texture> texture;
+ GLint level;
+ GLboolean layered;
+ GLint layer;
+ GLenum access;
+ GLenum format;
};
-bool operator==(const TextureState &a, const TextureState &b);
-bool operator!=(const TextureState &a, const TextureState &b);
+struct PixelStoreStateBase
+{
+ GLint alignment = 4;
+ GLint rowLength = 0;
+ GLint skipRows = 0;
+ GLint skipPixels = 0;
+ GLint imageHeight = 0;
+ GLint skipImages = 0;
+};
-struct PixelUnpackState
+struct PixelUnpackState : PixelStoreStateBase
{
- BindingPointer<Buffer> pixelBuffer;
- GLint alignment;
- GLint rowLength;
- GLint skipRows;
- GLint skipPixels;
- GLint imageHeight;
- GLint skipImages;
-
- PixelUnpackState()
- : alignment(4),
- rowLength(0),
- skipRows(0),
- skipPixels(0),
- imageHeight(0),
- skipImages(0)
- {}
-
- PixelUnpackState(GLint alignmentIn, GLint rowLengthIn)
- : alignment(alignmentIn),
- rowLength(rowLengthIn),
- skipRows(0),
- skipPixels(0),
- imageHeight(0),
- skipImages(0)
- {}
};
-struct PixelPackState
+struct PixelPackState : PixelStoreStateBase
{
- BindingPointer<Buffer> pixelBuffer;
- GLint alignment;
- bool reverseRowOrder;
- GLint rowLength;
- GLint skipRows;
- GLint skipPixels;
-
- PixelPackState()
- : alignment(4),
- reverseRowOrder(false),
- rowLength(0),
- skipRows(0),
- skipPixels(0)
- {}
-
- explicit PixelPackState(GLint alignmentIn, bool reverseRowOrderIn)
- : alignment(alignmentIn),
- reverseRowOrder(reverseRowOrderIn),
- rowLength(0),
- skipRows(0),
- skipPixels(0)
- {}
+ bool reverseRowOrder = false;
};
// Used in Program and VertexArray.
-typedef std::bitset<MAX_VERTEX_ATTRIBS> AttributesMask;
+using AttributesMask = angle::BitSet<MAX_VERTEX_ATTRIBS>;
-// Use in Program
-typedef std::bitset<IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS> UniformBlockBindingMask;
-}
+// Used in Program
+using UniformBlockBindingMask = angle::BitSet<IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS>;
+
+// Used in Framebuffer
+using DrawBufferMask = angle::BitSet<IMPLEMENTATION_MAX_DRAW_BUFFERS>;
+
+using ContextID = uintptr_t;
+
+constexpr size_t CUBE_FACE_COUNT = 6;
+
+using TextureMap = std::map<GLenum, BindingPointer<Texture>>;
+
+template <typename T>
+using AttachmentArray = std::array<T, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
+
+template <typename T>
+using DrawBuffersArray = std::array<T, IMPLEMENTATION_MAX_DRAW_BUFFERS>;
+
+} // namespace gl
namespace rx
{
-enum VendorID : uint32_t
-{
- VENDOR_ID_UNKNOWN = 0x0,
- VENDOR_ID_AMD = 0x1002,
- VENDOR_ID_INTEL = 0x8086,
- VENDOR_ID_NVIDIA = 0x10DE,
-};
-
// A macro that determines whether an object has a given runtime type.
#if defined(__clang__)
#if __has_feature(cxx_rtti)
@@ -354,12 +355,12 @@ inline DestT *GetImplAs(SrcT *src)
}
template <typename DestT, typename SrcT>
-inline const DestT *GetImplAs(const SrcT *src)
+inline DestT *SafeGetImplAs(SrcT *src)
{
- return GetAs<const DestT>(src->getImplementation());
+ return src != nullptr ? GetAs<DestT>(src->getImplementation()) : nullptr;
}
-}
+} // namespace rx
#include "angletypes.inl"
@@ -407,6 +408,80 @@ inline GLenum FramebufferBindingToEnum(FramebufferBinding binding)
return GL_NONE;
}
}
-}
+
+template <typename ObjT, typename ContextT>
+class DestroyThenDelete
+{
+ public:
+ DestroyThenDelete(const ContextT *context) : mContext(context) {}
+
+ void operator()(ObjT *obj)
+ {
+ ANGLE_SWALLOW_ERR(obj->onDestroy(mContext));
+ delete obj;
+ }
+
+ private:
+ const ContextT *mContext;
+};
+
+// Helper class for wrapping an onDestroy function.
+template <typename ObjT, typename DeleterT>
+class UniqueObjectPointerBase : angle::NonCopyable
+{
+ public:
+ template <typename ContextT>
+ UniqueObjectPointerBase(const ContextT *context) : mObject(nullptr), mDeleter(context)
+ {
+ }
+
+ template <typename ContextT>
+ UniqueObjectPointerBase(ObjT *obj, const ContextT *context) : mObject(obj), mDeleter(context)
+ {
+ }
+
+ ~UniqueObjectPointerBase()
+ {
+ if (mObject)
+ {
+ mDeleter(mObject);
+ }
+ }
+
+ ObjT *operator->() const { return mObject; }
+
+ ObjT *release()
+ {
+ auto obj = mObject;
+ mObject = nullptr;
+ return obj;
+ }
+
+ ObjT *get() const { return mObject; }
+
+ void reset(ObjT *obj)
+ {
+ if (mObject)
+ {
+ mDeleter(mObject);
+ }
+ mObject = obj;
+ }
+
+ private:
+ ObjT *mObject;
+ DeleterT mDeleter;
+};
+
+template <typename ObjT, typename ContextT>
+using UniqueObjectPointer = UniqueObjectPointerBase<ObjT, DestroyThenDelete<ObjT, ContextT>>;
+
+} // namespace angle
+
+namespace gl
+{
+class ContextState;
+
+} // namespace gl
#endif // LIBANGLE_ANGLETYPES_H_
diff --git a/src/3rdparty/angle/src/libANGLE/angletypes.inl b/src/3rdparty/angle/src/libANGLE/angletypes.inl
index d51bcaaa78..3fbe0747d2 100644
--- a/src/3rdparty/angle/src/libANGLE/angletypes.inl
+++ b/src/3rdparty/angle/src/libANGLE/angletypes.inl
@@ -9,21 +9,6 @@
namespace gl
{
-template <typename T>
-bool operator==(const Color<T> &a, const Color<T> &b)
-{
- return a.red == b.red &&
- a.green == b.green &&
- a.blue == b.blue &&
- a.alpha == b.alpha;
-}
-
-template <typename T>
-bool operator!=(const Color<T> &a, const Color<T> &b)
-{
- return !(a == b);
-}
-
inline bool operator==(const Rectangle &a, const Rectangle &b)
{
return a.x == b.x &&
@@ -39,16 +24,7 @@ inline bool operator!=(const Rectangle &a, const Rectangle &b)
inline bool operator==(const SamplerState &a, const SamplerState &b)
{
- return a.minFilter == b.minFilter &&
- a.magFilter == b.magFilter &&
- a.wrapS == b.wrapS &&
- a.wrapT == b.wrapT &&
- a.wrapR == b.wrapR &&
- a.maxAnisotropy == b.maxAnisotropy &&
- a.minLod == b.minLod &&
- a.maxLod == b.maxLod &&
- a.compareMode == b.compareMode &&
- a.compareFunc == b.compareFunc;
+ return memcmp(&a, &b, sizeof(SamplerState)) == 0;
}
inline bool operator!=(const SamplerState &a, const SamplerState &b)
@@ -56,23 +32,4 @@ inline bool operator!=(const SamplerState &a, const SamplerState &b)
return !(a == b);
}
-inline bool operator==(const TextureState &a, const TextureState &b)
-{
- return a.swizzleRed == b.swizzleRed &&
- a.swizzleGreen == b.swizzleGreen &&
- a.swizzleBlue == b.swizzleBlue &&
- a.swizzleAlpha == b.swizzleAlpha &&
- a.samplerState == b.samplerState &&
- a.baseLevel == b.baseLevel &&
- a.maxLevel == b.maxLevel &&
- a.immutableFormat == b.immutableFormat &&
- a.immutableLevels == b.immutableLevels &&
- a.usage == b.usage;
-}
-
-inline bool operator!=(const TextureState &a, const TextureState &b)
-{
- return !(a == b);
-}
-
-}
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/entry_points_enum_autogen.h b/src/3rdparty/angle/src/libANGLE/entry_points_enum_autogen.h
new file mode 100644
index 0000000000..14b5e3c1b0
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/entry_points_enum_autogen.h
@@ -0,0 +1,336 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// entry_points_enum_autogen.h:
+// Defines the GLES entry points enumeration.
+
+#ifndef LIBGLESV2_ENTRYPOINTSENUM_AUTOGEN_H_
+#define LIBGLESV2_ENTRYPOINTSENUM_AUTOGEN_H_
+
+namespace gl
+{
+enum class EntryPoint
+{
+ Invalid,
+ ActiveTexture,
+ AttachShader,
+ BindAttribLocation,
+ BindBuffer,
+ BindFramebuffer,
+ BindRenderbuffer,
+ BindTexture,
+ BlendColor,
+ BlendEquation,
+ BlendEquationSeparate,
+ BlendFunc,
+ BlendFuncSeparate,
+ BufferData,
+ BufferSubData,
+ CheckFramebufferStatus,
+ Clear,
+ ClearColor,
+ ClearDepthf,
+ ClearStencil,
+ ColorMask,
+ CompileShader,
+ CompressedTexImage2D,
+ CompressedTexSubImage2D,
+ CopyTexImage2D,
+ CopyTexSubImage2D,
+ CreateProgram,
+ CreateShader,
+ CullFace,
+ DeleteBuffers,
+ DeleteFramebuffers,
+ DeleteProgram,
+ DeleteRenderbuffers,
+ DeleteShader,
+ DeleteTextures,
+ DepthFunc,
+ DepthMask,
+ DepthRangef,
+ DetachShader,
+ Disable,
+ DisableVertexAttribArray,
+ DrawArrays,
+ DrawElements,
+ Enable,
+ EnableVertexAttribArray,
+ Finish,
+ Flush,
+ FramebufferRenderbuffer,
+ FramebufferTexture2D,
+ FrontFace,
+ GenBuffers,
+ GenerateMipmap,
+ GenFramebuffers,
+ GenRenderbuffers,
+ GenTextures,
+ GetActiveAttrib,
+ GetActiveUniform,
+ GetAttachedShaders,
+ GetAttribLocation,
+ GetBooleanv,
+ GetBufferParameteriv,
+ GetError,
+ GetFloatv,
+ GetFramebufferAttachmentParameteriv,
+ GetIntegerv,
+ GetProgramiv,
+ GetProgramInfoLog,
+ GetRenderbufferParameteriv,
+ GetShaderiv,
+ GetShaderInfoLog,
+ GetShaderPrecisionFormat,
+ GetShaderSource,
+ GetString,
+ GetTexParameterfv,
+ GetTexParameteriv,
+ GetUniformfv,
+ GetUniformiv,
+ GetUniformLocation,
+ GetVertexAttribfv,
+ GetVertexAttribiv,
+ GetVertexAttribPointerv,
+ Hint,
+ IsBuffer,
+ IsEnabled,
+ IsFramebuffer,
+ IsProgram,
+ IsRenderbuffer,
+ IsShader,
+ IsTexture,
+ LineWidth,
+ LinkProgram,
+ PixelStorei,
+ PolygonOffset,
+ ReadPixels,
+ ReleaseShaderCompiler,
+ RenderbufferStorage,
+ SampleCoverage,
+ Scissor,
+ ShaderBinary,
+ ShaderSource,
+ StencilFunc,
+ StencilFuncSeparate,
+ StencilMask,
+ StencilMaskSeparate,
+ StencilOp,
+ StencilOpSeparate,
+ TexImage2D,
+ TexParameterf,
+ TexParameterfv,
+ TexParameteri,
+ TexParameteriv,
+ TexSubImage2D,
+ Uniform1f,
+ Uniform1fv,
+ Uniform1i,
+ Uniform1iv,
+ Uniform2f,
+ Uniform2fv,
+ Uniform2i,
+ Uniform2iv,
+ Uniform3f,
+ Uniform3fv,
+ Uniform3i,
+ Uniform3iv,
+ Uniform4f,
+ Uniform4fv,
+ Uniform4i,
+ Uniform4iv,
+ UniformMatrix2fv,
+ UniformMatrix3fv,
+ UniformMatrix4fv,
+ UseProgram,
+ ValidateProgram,
+ VertexAttrib1f,
+ VertexAttrib1fv,
+ VertexAttrib2f,
+ VertexAttrib2fv,
+ VertexAttrib3f,
+ VertexAttrib3fv,
+ VertexAttrib4f,
+ VertexAttrib4fv,
+ VertexAttribPointer,
+ Viewport,
+ ReadBuffer,
+ DrawRangeElements,
+ TexImage3D,
+ TexSubImage3D,
+ CopyTexSubImage3D,
+ CompressedTexImage3D,
+ CompressedTexSubImage3D,
+ GenQueries,
+ DeleteQueries,
+ IsQuery,
+ BeginQuery,
+ EndQuery,
+ GetQueryiv,
+ GetQueryObjectuiv,
+ UnmapBuffer,
+ GetBufferPointerv,
+ DrawBuffers,
+ UniformMatrix2x3fv,
+ UniformMatrix3x2fv,
+ UniformMatrix2x4fv,
+ UniformMatrix4x2fv,
+ UniformMatrix3x4fv,
+ UniformMatrix4x3fv,
+ BlitFramebuffer,
+ RenderbufferStorageMultisample,
+ FramebufferTextureLayer,
+ MapBufferRange,
+ FlushMappedBufferRange,
+ BindVertexArray,
+ DeleteVertexArrays,
+ GenVertexArrays,
+ IsVertexArray,
+ GetIntegeri_v,
+ BeginTransformFeedback,
+ EndTransformFeedback,
+ BindBufferRange,
+ BindBufferBase,
+ TransformFeedbackVaryings,
+ GetTransformFeedbackVarying,
+ VertexAttribIPointer,
+ GetVertexAttribIiv,
+ GetVertexAttribIuiv,
+ VertexAttribI4i,
+ VertexAttribI4ui,
+ VertexAttribI4iv,
+ VertexAttribI4uiv,
+ GetUniformuiv,
+ GetFragDataLocation,
+ Uniform1ui,
+ Uniform2ui,
+ Uniform3ui,
+ Uniform4ui,
+ Uniform1uiv,
+ Uniform2uiv,
+ Uniform3uiv,
+ Uniform4uiv,
+ ClearBufferiv,
+ ClearBufferuiv,
+ ClearBufferfv,
+ ClearBufferfi,
+ GetStringi,
+ CopyBufferSubData,
+ GetUniformIndices,
+ GetActiveUniformsiv,
+ GetUniformBlockIndex,
+ GetActiveUniformBlockiv,
+ GetActiveUniformBlockName,
+ UniformBlockBinding,
+ DrawArraysInstanced,
+ DrawElementsInstanced,
+ FenceSync,
+ IsSync,
+ DeleteSync,
+ ClientWaitSync,
+ WaitSync,
+ GetInteger64v,
+ GetSynciv,
+ GetInteger64i_v,
+ GetBufferParameteri64v,
+ GenSamplers,
+ DeleteSamplers,
+ IsSampler,
+ BindSampler,
+ SamplerParameteri,
+ SamplerParameteriv,
+ SamplerParameterf,
+ SamplerParameterfv,
+ GetSamplerParameteriv,
+ GetSamplerParameterfv,
+ VertexAttribDivisor,
+ BindTransformFeedback,
+ DeleteTransformFeedbacks,
+ GenTransformFeedbacks,
+ IsTransformFeedback,
+ PauseTransformFeedback,
+ ResumeTransformFeedback,
+ GetProgramBinary,
+ ProgramBinary,
+ ProgramParameteri,
+ InvalidateFramebuffer,
+ InvalidateSubFramebuffer,
+ TexStorage2D,
+ TexStorage3D,
+ GetInternalformativ,
+ DispatchCompute,
+ DispatchComputeIndirect,
+ DrawArraysIndirect,
+ DrawElementsIndirect,
+ FramebufferParameteri,
+ GetFramebufferParameteriv,
+ GetProgramInterfaceiv,
+ GetProgramResourceIndex,
+ GetProgramResourceName,
+ GetProgramResourceiv,
+ GetProgramResourceLocation,
+ UseProgramStages,
+ ActiveShaderProgram,
+ CreateShaderProgramv,
+ BindProgramPipeline,
+ DeleteProgramPipelines,
+ GenProgramPipelines,
+ IsProgramPipeline,
+ GetProgramPipelineiv,
+ ProgramUniform1i,
+ ProgramUniform2i,
+ ProgramUniform3i,
+ ProgramUniform4i,
+ ProgramUniform1ui,
+ ProgramUniform2ui,
+ ProgramUniform3ui,
+ ProgramUniform4ui,
+ ProgramUniform1f,
+ ProgramUniform2f,
+ ProgramUniform3f,
+ ProgramUniform4f,
+ ProgramUniform1iv,
+ ProgramUniform2iv,
+ ProgramUniform3iv,
+ ProgramUniform4iv,
+ ProgramUniform1uiv,
+ ProgramUniform2uiv,
+ ProgramUniform3uiv,
+ ProgramUniform4uiv,
+ ProgramUniform1fv,
+ ProgramUniform2fv,
+ ProgramUniform3fv,
+ ProgramUniform4fv,
+ ProgramUniformMatrix2fv,
+ ProgramUniformMatrix3fv,
+ ProgramUniformMatrix4fv,
+ ProgramUniformMatrix2x3fv,
+ ProgramUniformMatrix3x2fv,
+ ProgramUniformMatrix2x4fv,
+ ProgramUniformMatrix4x2fv,
+ ProgramUniformMatrix3x4fv,
+ ProgramUniformMatrix4x3fv,
+ ValidateProgramPipeline,
+ GetProgramPipelineInfoLog,
+ BindImageTexture,
+ GetBooleani_v,
+ MemoryBarrier,
+ MemoryBarrierByRegion,
+ TexStorage2DMultisample,
+ GetMultisamplefv,
+ SampleMaski,
+ GetTexLevelParameteriv,
+ GetTexLevelParameterfv,
+ BindVertexBuffer,
+ VertexAttribFormat,
+ VertexAttribIFormat,
+ VertexAttribBinding,
+ VertexBindingDivisor,
+ DrawElementsInstancedANGLE
+};
+} // namespace gl
+#endif // LIBGLESV2_ENTRY_POINTS_ENUM_AUTOGEN_H_
diff --git a/src/3rdparty/angle/src/libANGLE/es3_copy_conversion_formats.json b/src/3rdparty/angle/src/libANGLE/es3_copy_conversion_formats.json
new file mode 100644
index 0000000000..39b71fd93a
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/es3_copy_conversion_formats.json
@@ -0,0 +1,44 @@
+{
+ "From ES 3.0.1 spec, table 3.15":
+ [
+ [ "GL_ALPHA", "GL_RGBA" ],
+ [ "GL_LUMINANCE", "GL_RED" ],
+ [ "GL_LUMINANCE", "GL_RG" ],
+ [ "GL_LUMINANCE", "GL_RGB" ],
+ [ "GL_LUMINANCE", "GL_RGBA" ],
+ [ "GL_LUMINANCE_ALPHA", "GL_RGBA" ],
+ [ "GL_RED", "GL_RED" ],
+ [ "GL_RED", "GL_RG" ],
+ [ "GL_RED", "GL_RGB" ],
+ [ "GL_RED", "GL_RGBA" ],
+ [ "GL_RG", "GL_RG" ],
+ [ "GL_RG", "GL_RGB" ],
+ [ "GL_RG", "GL_RGBA" ],
+ [ "GL_RGB", "GL_RGB" ],
+ [ "GL_RGB", "GL_RGBA" ],
+ [ "GL_RGBA", "GL_RGBA" ]
+ ],
+
+ "Necessary for ANGLE back-buffers":
+ [
+ [ "GL_ALPHA", "GL_BGRA_EXT" ],
+ [ "GL_LUMINANCE", "GL_BGRA_EXT" ],
+ [ "GL_LUMINANCE_ALPHA", "GL_BGRA_EXT" ],
+ [ "GL_RED", "GL_BGRA_EXT" ],
+ [ "GL_RG", "GL_BGRA_EXT" ],
+ [ "GL_RGB", "GL_BGRA_EXT" ],
+ [ "GL_RGBA", "GL_BGRA_EXT" ],
+ [ "GL_BGRA_EXT", "GL_BGRA_EXT" ],
+
+ [ "GL_RED_INTEGER", "GL_RED_INTEGER" ],
+ [ "GL_RED_INTEGER", "GL_RG_INTEGER" ],
+ [ "GL_RED_INTEGER", "GL_RGB_INTEGER" ],
+ [ "GL_RED_INTEGER", "GL_RGBA_INTEGER" ],
+ [ "GL_RG_INTEGER", "GL_RG_INTEGER" ],
+ [ "GL_RG_INTEGER", "GL_RGB_INTEGER" ],
+ [ "GL_RG_INTEGER", "GL_RGBA_INTEGER" ],
+ [ "GL_RGB_INTEGER", "GL_RGB_INTEGER" ],
+ [ "GL_RGB_INTEGER", "GL_RGBA_INTEGER" ],
+ [ "GL_RGBA_INTEGER", "GL_RGBA_INTEGER" ]
+ ]
+}
diff --git a/src/3rdparty/angle/src/libANGLE/es3_copy_conversion_table_autogen.cpp b/src/3rdparty/angle/src/libANGLE/es3_copy_conversion_table_autogen.cpp
new file mode 100644
index 0000000000..149f79f458
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/es3_copy_conversion_table_autogen.cpp
@@ -0,0 +1,171 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_copy_conversion_table.py using data from es3_copy_conversion_formats.json.
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// format_map:
+// Determining the sized internal format from a (format,type) pair.
+// Also check es3 format combinations for validity.
+
+#include "angle_gl.h"
+#include "common/debug.h"
+
+namespace gl
+{
+
+bool ValidES3CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
+{
+ switch (textureFormat)
+ {
+ case GL_ALPHA:
+ switch (framebufferFormat)
+ {
+ case GL_BGRA_EXT:
+ case GL_RGBA:
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ case GL_BGRA_EXT:
+ switch (framebufferFormat)
+ {
+ case GL_BGRA_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ case GL_LUMINANCE:
+ switch (framebufferFormat)
+ {
+ case GL_BGRA_EXT:
+ case GL_RED:
+ case GL_RG:
+ case GL_RGB:
+ case GL_RGBA:
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ case GL_LUMINANCE_ALPHA:
+ switch (framebufferFormat)
+ {
+ case GL_BGRA_EXT:
+ case GL_RGBA:
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RED:
+ switch (framebufferFormat)
+ {
+ case GL_BGRA_EXT:
+ case GL_RED:
+ case GL_RG:
+ case GL_RGB:
+ case GL_RGBA:
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RED_INTEGER:
+ switch (framebufferFormat)
+ {
+ case GL_RED_INTEGER:
+ case GL_RGBA_INTEGER:
+ case GL_RGB_INTEGER:
+ case GL_RG_INTEGER:
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RG:
+ switch (framebufferFormat)
+ {
+ case GL_BGRA_EXT:
+ case GL_RG:
+ case GL_RGB:
+ case GL_RGBA:
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGB:
+ switch (framebufferFormat)
+ {
+ case GL_BGRA_EXT:
+ case GL_RGB:
+ case GL_RGBA:
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGBA:
+ switch (framebufferFormat)
+ {
+ case GL_BGRA_EXT:
+ case GL_RGBA:
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGBA_INTEGER:
+ switch (framebufferFormat)
+ {
+ case GL_RGBA_INTEGER:
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGB_INTEGER:
+ switch (framebufferFormat)
+ {
+ case GL_RGBA_INTEGER:
+ case GL_RGB_INTEGER:
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RG_INTEGER:
+ switch (framebufferFormat)
+ {
+ case GL_RGBA_INTEGER:
+ case GL_RGB_INTEGER:
+ case GL_RG_INTEGER:
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/es3_format_type_combinations.json b/src/3rdparty/angle/src/libANGLE/es3_format_type_combinations.json
new file mode 100644
index 0000000000..fb12242e75
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/es3_format_type_combinations.json
@@ -0,0 +1,171 @@
+{
+ "Format combinations from ES 3.0.1 spec, table 3.2":
+ [
+ [ "GL_RGBA8", "GL_RGBA", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RGB5_A1", "GL_RGBA", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RGBA4", "GL_RGBA", "GL_UNSIGNED_BYTE" ],
+ [ "GL_SRGB8_ALPHA8", "GL_RGBA", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RGBA8_SNORM", "GL_RGBA", "GL_BYTE" ],
+ [ "GL_RGBA4", "GL_RGBA", "GL_UNSIGNED_SHORT_4_4_4_4" ],
+ [ "GL_RGB10_A2", "GL_RGBA", "GL_UNSIGNED_INT_2_10_10_10_REV" ],
+ [ "GL_RGB5_A1", "GL_RGBA", "GL_UNSIGNED_INT_2_10_10_10_REV" ],
+ [ "GL_RGB5_A1", "GL_RGBA", "GL_UNSIGNED_SHORT_5_5_5_1" ],
+ [ "GL_RGBA16F", "GL_RGBA", "GL_HALF_FLOAT" ],
+ [ "GL_RGBA16F", "GL_RGBA", "GL_HALF_FLOAT_OES" ],
+ [ "GL_RGBA32F", "GL_RGBA", "GL_FLOAT" ],
+ [ "GL_RGBA16F", "GL_RGBA", "GL_FLOAT" ],
+ [ "GL_RGBA8UI", "GL_RGBA_INTEGER", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RGBA8I", "GL_RGBA_INTEGER", "GL_BYTE" ],
+ [ "GL_RGBA16UI", "GL_RGBA_INTEGER", "GL_UNSIGNED_SHORT" ],
+ [ "GL_RGBA16I", "GL_RGBA_INTEGER", "GL_SHORT" ],
+ [ "GL_RGBA32UI", "GL_RGBA_INTEGER", "GL_UNSIGNED_INT" ],
+ [ "GL_RGBA32I", "GL_RGBA_INTEGER", "GL_INT" ],
+ [ "GL_RGB10_A2UI", "GL_RGBA_INTEGER", "GL_UNSIGNED_INT_2_10_10_10_REV" ],
+ [ "GL_RGB8", "GL_RGB", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RGB565", "GL_RGB", "GL_UNSIGNED_BYTE" ],
+ [ "GL_SRGB8", "GL_RGB", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RGB8_SNORM", "GL_RGB", "GL_BYTE" ],
+ [ "GL_RGB565", "GL_RGB", "GL_UNSIGNED_SHORT_5_6_5" ],
+ [ "GL_R11F_G11F_B10F", "GL_RGB", "GL_UNSIGNED_INT_10F_11F_11F_REV" ],
+ [ "GL_RGB9_E5", "GL_RGB", "GL_UNSIGNED_INT_5_9_9_9_REV" ],
+ [ "GL_RGB16F", "GL_RGB", "GL_HALF_FLOAT" ],
+ [ "GL_RGB16F", "GL_RGB", "GL_HALF_FLOAT_OES" ],
+ [ "GL_R11F_G11F_B10F", "GL_RGB", "GL_HALF_FLOAT" ],
+ [ "GL_R11F_G11F_B10F", "GL_RGB", "GL_HALF_FLOAT_OES" ],
+ [ "GL_RGB9_E5", "GL_RGB", "GL_HALF_FLOAT" ],
+ [ "GL_RGB9_E5", "GL_RGB", "GL_HALF_FLOAT_OES" ],
+ [ "GL_RGB32F", "GL_RGB", "GL_FLOAT" ],
+ [ "GL_RGB16F", "GL_RGB", "GL_FLOAT" ],
+ [ "GL_R11F_G11F_B10F", "GL_RGB", "GL_FLOAT" ],
+ [ "GL_RGB9_E5", "GL_RGB", "GL_FLOAT" ],
+ [ "GL_RGB8UI", "GL_RGB_INTEGER", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RGB8I", "GL_RGB_INTEGER", "GL_BYTE" ],
+ [ "GL_RGB16UI", "GL_RGB_INTEGER", "GL_UNSIGNED_SHORT" ],
+ [ "GL_RGB16I", "GL_RGB_INTEGER", "GL_SHORT" ],
+ [ "GL_RGB32UI", "GL_RGB_INTEGER", "GL_UNSIGNED_INT" ],
+ [ "GL_RGB32I", "GL_RGB_INTEGER", "GL_INT" ],
+ [ "GL_RG8", "GL_RG", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RG8_SNORM", "GL_RG", "GL_BYTE" ],
+ [ "GL_RG16F", "GL_RG", "GL_HALF_FLOAT" ],
+ [ "GL_RG16F", "GL_RG", "GL_HALF_FLOAT_OES" ],
+ [ "GL_RG32F", "GL_RG", "GL_FLOAT" ],
+ [ "GL_RG16F", "GL_RG", "GL_FLOAT" ],
+ [ "GL_RG8UI", "GL_RG_INTEGER", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RG8I", "GL_RG_INTEGER", "GL_BYTE" ],
+ [ "GL_RG16UI", "GL_RG_INTEGER", "GL_UNSIGNED_SHORT" ],
+ [ "GL_RG16I", "GL_RG_INTEGER", "GL_SHORT" ],
+ [ "GL_RG32UI", "GL_RG_INTEGER", "GL_UNSIGNED_INT" ],
+ [ "GL_RG32I", "GL_RG_INTEGER", "GL_INT" ],
+ [ "GL_R8", "GL_RED", "GL_UNSIGNED_BYTE" ],
+ [ "GL_R8_SNORM", "GL_RED", "GL_BYTE" ],
+ [ "GL_R16F", "GL_RED", "GL_HALF_FLOAT" ],
+ [ "GL_R16F", "GL_RED", "GL_HALF_FLOAT_OES" ],
+ [ "GL_R32F", "GL_RED", "GL_FLOAT" ],
+ [ "GL_R16F", "GL_RED", "GL_FLOAT" ],
+ [ "GL_R8UI", "GL_RED_INTEGER", "GL_UNSIGNED_BYTE" ],
+ [ "GL_R8I", "GL_RED_INTEGER", "GL_BYTE" ],
+ [ "GL_R16UI", "GL_RED_INTEGER", "GL_UNSIGNED_SHORT" ],
+ [ "GL_R16I", "GL_RED_INTEGER", "GL_SHORT" ],
+ [ "GL_R32UI", "GL_RED_INTEGER", "GL_UNSIGNED_INT" ],
+ [ "GL_R32I", "GL_RED_INTEGER", "GL_INT" ]
+ ],
+ "Unsized formats":
+ [
+ [ "GL_RGBA", "GL_RGBA", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RGBA", "GL_RGBA", "GL_UNSIGNED_SHORT_4_4_4_4" ],
+ [ "GL_RGBA", "GL_RGBA", "GL_UNSIGNED_SHORT_5_5_5_1" ],
+ [ "GL_RGB", "GL_RGB", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RGB", "GL_RGB", "GL_UNSIGNED_SHORT_5_6_5" ],
+ [ "GL_LUMINANCE_ALPHA", "GL_LUMINANCE_ALPHA", "GL_UNSIGNED_BYTE" ],
+ [ "GL_LUMINANCE", "GL_LUMINANCE", "GL_UNSIGNED_BYTE" ],
+ [ "GL_ALPHA", "GL_ALPHA", "GL_UNSIGNED_BYTE" ],
+ [ "GL_SRGB_ALPHA_EXT", "GL_SRGB_ALPHA_EXT", "GL_UNSIGNED_BYTE" ],
+ [ "GL_SRGB_EXT", "GL_SRGB_EXT", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RG", "GL_RG", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RG", "GL_RG", "GL_FLOAT" ],
+ [ "GL_RG", "GL_RG", "GL_HALF_FLOAT" ],
+ [ "GL_RG", "GL_RG", "GL_HALF_FLOAT_OES" ],
+ [ "GL_RED", "GL_RED", "GL_UNSIGNED_BYTE" ],
+ [ "GL_RED", "GL_RED", "GL_FLOAT" ],
+ [ "GL_RED", "GL_RED", "GL_HALF_FLOAT" ],
+ [ "GL_RED", "GL_RED", "GL_HALF_FLOAT_OES" ],
+ [ "GL_DEPTH_STENCIL", "GL_DEPTH_STENCIL", "GL_UNSIGNED_INT_24_8" ]
+ ],
+ "Depth stencil formats":
+ [
+ [ "GL_DEPTH_COMPONENT16", "GL_DEPTH_COMPONENT", "GL_UNSIGNED_SHORT" ],
+ [ "GL_DEPTH_COMPONENT24", "GL_DEPTH_COMPONENT", "GL_UNSIGNED_INT" ],
+ [ "GL_DEPTH_COMPONENT16", "GL_DEPTH_COMPONENT", "GL_UNSIGNED_INT" ],
+ [ "GL_DEPTH_COMPONENT32F", "GL_DEPTH_COMPONENT", "GL_FLOAT" ],
+ [ "GL_DEPTH24_STENCIL8", "GL_DEPTH_STENCIL", "GL_UNSIGNED_INT_24_8" ],
+ [ "GL_DEPTH32F_STENCIL8", "GL_DEPTH_STENCIL", "GL_FLOAT_32_UNSIGNED_INT_24_8_REV" ]
+ ],
+ "From GL_EXT_sRGB":
+ [
+ [ "GL_SRGB8_ALPHA8_EXT", "GL_SRGB_ALPHA_EXT", "GL_UNSIGNED_BYTE" ],
+ [ "GL_SRGB8", "GL_SRGB_EXT", "GL_UNSIGNED_BYTE" ]
+ ],
+ "From GL_OES_texture_float":
+ [
+ [ "GL_RGBA", "GL_RGBA", "GL_FLOAT" ],
+ [ "GL_RGB", "GL_RGB", "GL_FLOAT" ],
+ [ "GL_LUMINANCE_ALPHA", "GL_LUMINANCE_ALPHA", "GL_FLOAT" ],
+ [ "GL_LUMINANCE", "GL_LUMINANCE", "GL_FLOAT" ],
+ [ "GL_ALPHA", "GL_ALPHA", "GL_FLOAT" ]
+ ],
+ "From GL_OES_texture_half_float":
+ [
+ [ "GL_RGBA", "GL_RGBA", "GL_HALF_FLOAT_OES" ],
+ [ "GL_RGB", "GL_RGB", "GL_HALF_FLOAT_OES" ],
+ [ "GL_LUMINANCE_ALPHA", "GL_LUMINANCE_ALPHA", "GL_HALF_FLOAT" ],
+ [ "GL_LUMINANCE_ALPHA", "GL_LUMINANCE_ALPHA", "GL_HALF_FLOAT_OES" ],
+ [ "GL_LUMINANCE", "GL_LUMINANCE", "GL_HALF_FLOAT" ],
+ [ "GL_LUMINANCE", "GL_LUMINANCE", "GL_HALF_FLOAT_OES" ],
+ [ "GL_ALPHA", "GL_ALPHA", "GL_HALF_FLOAT" ],
+ [ "GL_ALPHA", "GL_ALPHA", "GL_HALF_FLOAT_OES" ]
+ ],
+ "From GL_EXT_texture_format_BGRA8888":
+ [
+ [ "GL_BGRA_EXT", "GL_BGRA_EXT", "GL_UNSIGNED_BYTE" ]
+ ],
+ "From GL_EXT_texture_storage":
+ [
+ [ "GL_ALPHA8_EXT", "GL_ALPHA", "GL_UNSIGNED_BYTE" ],
+ [ "GL_LUMINANCE8_EXT", "GL_LUMINANCE", "GL_UNSIGNED_BYTE" ],
+ [ "GL_LUMINANCE8_ALPHA8_EXT", "GL_LUMINANCE_ALPHA", "GL_UNSIGNED_BYTE" ],
+ [ "GL_ALPHA32F_EXT", "GL_ALPHA", "GL_FLOAT" ],
+ [ "GL_LUMINANCE32F_EXT", "GL_LUMINANCE", "GL_FLOAT" ],
+ [ "GL_LUMINANCE_ALPHA32F_EXT", "GL_LUMINANCE_ALPHA", "GL_FLOAT" ],
+ [ "GL_ALPHA16F_EXT", "GL_ALPHA", "GL_HALF_FLOAT" ],
+ [ "GL_ALPHA16F_EXT", "GL_ALPHA", "GL_HALF_FLOAT_OES" ],
+ [ "GL_LUMINANCE16F_EXT", "GL_LUMINANCE", "GL_HALF_FLOAT" ],
+ [ "GL_LUMINANCE16F_EXT", "GL_LUMINANCE", "GL_HALF_FLOAT_OES" ],
+ [ "GL_LUMINANCE_ALPHA16F_EXT", "GL_LUMINANCE_ALPHA", "GL_HALF_FLOAT" ],
+ [ "GL_LUMINANCE_ALPHA16F_EXT", "GL_LUMINANCE_ALPHA", "GL_HALF_FLOAT_OES" ]
+ ],
+ "From GL_EXT_texture_storage and GL_EXT_texture_format_BGRA8888":
+ [
+ [ "GL_BGRA8_EXT", "GL_BGRA_EXT", "GL_UNSIGNED_BYTE" ],
+ [ "GL_BGRA4_ANGLEX", "GL_BGRA_EXT", "GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT" ],
+ [ "GL_BGRA4_ANGLEX", "GL_BGRA_EXT", "GL_UNSIGNED_BYTE" ],
+ [ "GL_BGR5_A1_ANGLEX", "GL_BGRA_EXT", "GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT" ],
+ [ "GL_BGR5_A1_ANGLEX", "GL_BGRA_EXT", "GL_UNSIGNED_BYTE" ]
+ ],
+ "From GL_ANGLE_depth_texture and OES_depth_texture":
+ [
+ [ "GL_DEPTH_COMPONENT32_OES", "GL_DEPTH_COMPONENT", "GL_UNSIGNED_INT_24_8" ],
+ [ "GL_DEPTH_COMPONENT", "GL_DEPTH_COMPONENT", "GL_UNSIGNED_SHORT" ],
+ [ "GL_DEPTH_COMPONENT", "GL_DEPTH_COMPONENT", "GL_UNSIGNED_INT" ]
+ ],
+ "From GL_EXT_texture_norm16":
+ [
+ [ "GL_R16_EXT", "GL_RED", "GL_UNSIGNED_SHORT" ],
+ [ "GL_RG16_EXT", "GL_RG", "GL_UNSIGNED_SHORT" ],
+ [ "GL_RGB16_EXT", "GL_RGB", "GL_UNSIGNED_SHORT" ],
+ [ "GL_RGBA16_EXT", "GL_RGBA", "GL_UNSIGNED_SHORT" ],
+ [ "GL_R16_SNORM_EXT", "GL_RED", "GL_SHORT" ],
+ [ "GL_RG16_SNORM_EXT", "GL_RG", "GL_SHORT" ],
+ [ "GL_RGB16_SNORM_EXT", "GL_RGB", "GL_SHORT" ],
+ [ "GL_RGBA16_SNORM_EXT", "GL_RGBA", "GL_SHORT" ]
+ ]
+}
diff --git a/src/3rdparty/angle/src/libANGLE/features.h b/src/3rdparty/angle/src/libANGLE/features.h
index ecf486dcf7..48a194ff0b 100644
--- a/src/3rdparty/angle/src/libANGLE/features.h
+++ b/src/3rdparty/angle/src/libANGLE/features.h
@@ -7,6 +7,8 @@
#ifndef LIBANGLE_FEATURES_H_
#define LIBANGLE_FEATURES_H_
+#include "common/platform.h"
+
#define ANGLE_DISABLED 0
#define ANGLE_ENABLED 1
@@ -50,4 +52,14 @@
#define ANGLE_PROGRAM_LINK_VALIDATE_UNIFORM_PRECISION ANGLE_ENABLED
#endif
+// Controls if our threading code uses std::async or falls back to single-threaded operations.
+// TODO(jmadill): Enable on Linux once STL chrono headers are updated.
+#if !defined(ANGLE_STD_ASYNC_WORKERS)
+#if defined(ANGLE_PLATFORM_WINDOWS)
+#define ANGLE_STD_ASYNC_WORKERS ANGLE_ENABLED
+#else
+#define ANGLE_STD_ASYNC_WORKERS ANGLE_DISABLED
+#endif // defined(ANGLE_PLATFORM_WINDOWS)
+#endif // !defined(ANGLE_STD_ASYNC_WORKERS)
+
#endif // LIBANGLE_FEATURES_H_
diff --git a/src/3rdparty/angle/src/libANGLE/format_map_autogen.cpp b/src/3rdparty/angle/src/libANGLE/format_map_autogen.cpp
new file mode 100644
index 0000000000..a7f3ebafc8
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/format_map_autogen.cpp
@@ -0,0 +1,1570 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_format_map.py using data from format_map_data.json.
+// ES3 format info from es3_format_type_combinations.json.
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// format_map:
+// Determining the sized internal format from a (format,type) pair.
+// Also check es3 format combinations for validity.
+
+#include "angle_gl.h"
+#include "common/debug.h"
+
+namespace gl
+{
+
+GLenum GetSizedFormatInternal(GLenum format, GLenum type)
+{
+ switch (format)
+ {
+ case GL_ALPHA:
+ switch (type)
+ {
+ case GL_FLOAT:
+ return GL_ALPHA32F_EXT;
+ case GL_HALF_FLOAT:
+ return GL_ALPHA16F_EXT;
+ case GL_HALF_FLOAT_OES:
+ return GL_ALPHA16F_EXT;
+ case GL_UNSIGNED_BYTE:
+ return GL_ALPHA8_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_BGRA_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_BGRA8_EXT;
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+ return GL_BGR5_A1_ANGLEX;
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+ return GL_BGRA4_ANGLEX;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ return GL_BGR565_ANGLEX;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_DEPTH_COMPONENT:
+ switch (type)
+ {
+ case GL_FLOAT:
+ return GL_DEPTH_COMPONENT32F;
+ case GL_UNSIGNED_INT:
+ return GL_DEPTH_COMPONENT32_OES;
+ case GL_UNSIGNED_SHORT:
+ return GL_DEPTH_COMPONENT16;
+ default:
+ break;
+ }
+ break;
+
+ case GL_DEPTH_STENCIL:
+ switch (type)
+ {
+ case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+ return GL_DEPTH32F_STENCIL8;
+ case GL_UNSIGNED_INT_24_8:
+ return GL_DEPTH24_STENCIL8;
+ default:
+ break;
+ }
+ break;
+
+ case GL_LUMINANCE:
+ switch (type)
+ {
+ case GL_FLOAT:
+ return GL_LUMINANCE32F_EXT;
+ case GL_HALF_FLOAT:
+ return GL_LUMINANCE16F_EXT;
+ case GL_HALF_FLOAT_OES:
+ return GL_LUMINANCE16F_EXT;
+ case GL_UNSIGNED_BYTE:
+ return GL_LUMINANCE8_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_LUMINANCE_ALPHA:
+ switch (type)
+ {
+ case GL_FLOAT:
+ return GL_LUMINANCE_ALPHA32F_EXT;
+ case GL_HALF_FLOAT:
+ return GL_LUMINANCE_ALPHA16F_EXT;
+ case GL_HALF_FLOAT_OES:
+ return GL_LUMINANCE_ALPHA16F_EXT;
+ case GL_UNSIGNED_BYTE:
+ return GL_LUMINANCE8_ALPHA8_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RED:
+ switch (type)
+ {
+ case GL_BYTE:
+ return GL_R8_SNORM;
+ case GL_FLOAT:
+ return GL_R32F;
+ case GL_HALF_FLOAT:
+ return GL_R16F;
+ case GL_HALF_FLOAT_OES:
+ return GL_R16F;
+ case GL_SHORT:
+ return GL_R16_SNORM_EXT;
+ case GL_UNSIGNED_BYTE:
+ return GL_R8;
+ case GL_UNSIGNED_SHORT:
+ return GL_R16_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RED_INTEGER:
+ switch (type)
+ {
+ case GL_BYTE:
+ return GL_R8I;
+ case GL_INT:
+ return GL_R32I;
+ case GL_SHORT:
+ return GL_R16I;
+ case GL_UNSIGNED_BYTE:
+ return GL_R8UI;
+ case GL_UNSIGNED_INT:
+ return GL_R32UI;
+ case GL_UNSIGNED_SHORT:
+ return GL_R16UI;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RG:
+ switch (type)
+ {
+ case GL_BYTE:
+ return GL_RG8_SNORM;
+ case GL_FLOAT:
+ return GL_RG32F;
+ case GL_HALF_FLOAT:
+ return GL_RG16F;
+ case GL_HALF_FLOAT_OES:
+ return GL_RG16F;
+ case GL_SHORT:
+ return GL_RG16_SNORM_EXT;
+ case GL_UNSIGNED_BYTE:
+ return GL_RG8;
+ case GL_UNSIGNED_SHORT:
+ return GL_RG16_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGB:
+ switch (type)
+ {
+ case GL_BYTE:
+ return GL_RGB8_SNORM;
+ case GL_FLOAT:
+ return GL_RGB32F;
+ case GL_HALF_FLOAT:
+ return GL_RGB16F;
+ case GL_HALF_FLOAT_OES:
+ return GL_RGB16F;
+ case GL_SHORT:
+ return GL_RGB16_SNORM_EXT;
+ case GL_UNSIGNED_BYTE:
+ return GL_RGB8;
+ case GL_UNSIGNED_INT_10F_11F_11F_REV:
+ return GL_R11F_G11F_B10F;
+ case GL_UNSIGNED_INT_5_9_9_9_REV:
+ return GL_RGB9_E5;
+ case GL_UNSIGNED_SHORT:
+ return GL_RGB16_EXT;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ return GL_RGB565;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGBA:
+ switch (type)
+ {
+ case GL_BYTE:
+ return GL_RGBA8_SNORM;
+ case GL_FLOAT:
+ return GL_RGBA32F;
+ case GL_HALF_FLOAT:
+ return GL_RGBA16F;
+ case GL_HALF_FLOAT_OES:
+ return GL_RGBA16F;
+ case GL_SHORT:
+ return GL_RGBA16_SNORM_EXT;
+ case GL_UNSIGNED_BYTE:
+ return GL_RGBA8;
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return GL_RGB10_A2;
+ case GL_UNSIGNED_SHORT:
+ return GL_RGBA16_EXT;
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ return GL_RGBA4;
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ return GL_RGB5_A1;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGBA_INTEGER:
+ switch (type)
+ {
+ case GL_BYTE:
+ return GL_RGBA8I;
+ case GL_INT:
+ return GL_RGBA32I;
+ case GL_SHORT:
+ return GL_RGBA16I;
+ case GL_UNSIGNED_BYTE:
+ return GL_RGBA8UI;
+ case GL_UNSIGNED_INT:
+ return GL_RGBA32UI;
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return GL_RGB10_A2UI;
+ case GL_UNSIGNED_SHORT:
+ return GL_RGBA16UI;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGB_INTEGER:
+ switch (type)
+ {
+ case GL_BYTE:
+ return GL_RGB8I;
+ case GL_INT:
+ return GL_RGB32I;
+ case GL_SHORT:
+ return GL_RGB16I;
+ case GL_UNSIGNED_BYTE:
+ return GL_RGB8UI;
+ case GL_UNSIGNED_INT:
+ return GL_RGB32UI;
+ case GL_UNSIGNED_SHORT:
+ return GL_RGB16UI;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RG_INTEGER:
+ switch (type)
+ {
+ case GL_BYTE:
+ return GL_RG8I;
+ case GL_INT:
+ return GL_RG32I;
+ case GL_SHORT:
+ return GL_RG16I;
+ case GL_UNSIGNED_BYTE:
+ return GL_RG8UI;
+ case GL_UNSIGNED_INT:
+ return GL_RG32UI;
+ case GL_UNSIGNED_SHORT:
+ return GL_RG16UI;
+ default:
+ break;
+ }
+ break;
+
+ case GL_SRGB_ALPHA_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_SRGB8_ALPHA8;
+ default:
+ break;
+ }
+ break;
+
+ case GL_SRGB_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_SRGB8;
+ default:
+ break;
+ }
+ break;
+
+ case GL_STENCIL:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_STENCIL_INDEX8;
+ default:
+ break;
+ }
+ break;
+
+ case GL_NONE:
+ return GL_NONE;
+
+ default:
+ break;
+ }
+
+ return GL_NONE;
+}
+
+bool ValidES3Format(GLenum format)
+{
+ switch (format)
+ {
+ case GL_ALPHA:
+ case GL_BGRA_EXT:
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_STENCIL:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_RED:
+ case GL_RED_INTEGER:
+ case GL_RG:
+ case GL_RGB:
+ case GL_RGBA:
+ case GL_RGBA_INTEGER:
+ case GL_RGB_INTEGER:
+ case GL_RG_INTEGER:
+ case GL_SRGB_ALPHA_EXT:
+ case GL_SRGB_EXT:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool ValidES3Type(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BYTE:
+ case GL_FLOAT:
+ case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+ case GL_HALF_FLOAT:
+ case GL_HALF_FLOAT_OES:
+ case GL_INT:
+ case GL_SHORT:
+ case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_INT:
+ case GL_UNSIGNED_INT_10F_11F_11F_REV:
+ case GL_UNSIGNED_INT_24_8:
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ case GL_UNSIGNED_INT_5_9_9_9_REV:
+ case GL_UNSIGNED_SHORT:
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL_UNSIGNED_SHORT_5_6_5:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool ValidES3FormatCombination(GLenum format, GLenum type, GLenum internalFormat)
+{
+ ASSERT(ValidES3Format(format) && ValidES3Type(type));
+
+ switch (format)
+ {
+ case GL_RGB_INTEGER:
+ switch (type)
+ {
+ case GL_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB32I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB16UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB16I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB8UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB8I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB32UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGBA_INTEGER:
+ switch (type)
+ {
+ case GL_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA32I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA16UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB10_A2UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA16I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA8UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA8I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA32UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGB:
+ switch (type)
+ {
+ case GL_UNSIGNED_INT_10F_11F_11F_REV:
+ {
+ switch (internalFormat)
+ {
+ case GL_R11F_G11F_B10F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB16_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB16_SNORM_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB:
+ case GL_RGB8:
+ case GL_RGB565:
+ case GL_SRGB8:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT_5_6_5:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB:
+ case GL_RGB565:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT_OES:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB:
+ case GL_RGB16F:
+ case GL_R11F_G11F_B10F:
+ case GL_RGB9_E5:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB16F:
+ case GL_R11F_G11F_B10F:
+ case GL_RGB9_E5:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB:
+ case GL_RGB32F:
+ case GL_RGB16F:
+ case GL_R11F_G11F_B10F:
+ case GL_RGB9_E5:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB8_SNORM:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT_5_9_9_9_REV:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB9_E5:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_LUMINANCE_ALPHA:
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE_ALPHA32F_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE8_ALPHA8_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT_OES:
+ {
+ switch (internalFormat)
+ {
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_ALPHA:
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_ALPHA:
+ case GL_ALPHA16F_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_ALPHA:
+ case GL_ALPHA32F_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_ALPHA:
+ case GL_ALPHA8_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT_OES:
+ {
+ switch (internalFormat)
+ {
+ case GL_ALPHA:
+ case GL_ALPHA16F_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGBA:
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA16_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB10_A2:
+ case GL_RGB5_A1:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA16_SNORM_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA:
+ case GL_RGBA4:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA:
+ case GL_RGBA8:
+ case GL_RGB5_A1:
+ case GL_RGBA4:
+ case GL_SRGB8_ALPHA8:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT_OES:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA:
+ case GL_RGBA16F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA16F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA:
+ case GL_RGBA32F:
+ case GL_RGBA16F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA8_SNORM:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA:
+ case GL_RGB5_A1:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_LUMINANCE:
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_LUMINANCE:
+ case GL_LUMINANCE16F_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_LUMINANCE:
+ case GL_LUMINANCE32F_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_LUMINANCE:
+ case GL_LUMINANCE8_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT_OES:
+ {
+ switch (internalFormat)
+ {
+ case GL_LUMINANCE:
+ case GL_LUMINANCE16F_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_RG_INTEGER:
+ switch (type)
+ {
+ case GL_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG32I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG16UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG16I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG8UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG8I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG32UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_RED_INTEGER:
+ switch (type)
+ {
+ case GL_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_R32I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_R16UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_R16I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_R8UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_R8I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_R32UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_RED:
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_R16_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_R16_SNORM_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RED:
+ case GL_R32F:
+ case GL_R16F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT_OES:
+ {
+ switch (internalFormat)
+ {
+ case GL_RED:
+ case GL_R16F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RED:
+ case GL_R16F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RED:
+ case GL_R8:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_R8_SNORM:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_DEPTH_COMPONENT:
+ switch (type)
+ {
+ case GL_UNSIGNED_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH_COMPONENT16:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT_24_8:
+ {
+ switch (internalFormat)
+ {
+ case GL_DEPTH_COMPONENT32_OES:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_DEPTH_COMPONENT32F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_COMPONENT16:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_DEPTH_STENCIL:
+ switch (type)
+ {
+ case GL_UNSIGNED_INT_24_8:
+ {
+ switch (internalFormat)
+ {
+ case GL_DEPTH_STENCIL:
+ case GL_DEPTH24_STENCIL8:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+ {
+ switch (internalFormat)
+ {
+ case GL_DEPTH32F_STENCIL8:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_SRGB_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_SRGB_EXT:
+ case GL_SRGB8:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_SRGB_ALPHA_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_SRGB_ALPHA_EXT:
+ case GL_SRGB8_ALPHA8_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_RG:
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG16_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG16_SNORM_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG:
+ case GL_RG32F:
+ case GL_RG16F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT_OES:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG:
+ case GL_RG16F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG:
+ case GL_RG16F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG:
+ case GL_RG8:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG8_SNORM:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_BGRA_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+ {
+ switch (internalFormat)
+ {
+ case GL_BGRA4_ANGLEX:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_BGRA8_EXT:
+ case GL_BGRA4_ANGLEX:
+ case GL_BGR5_A1_ANGLEX:
+ case GL_BGRA_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+ {
+ switch (internalFormat)
+ {
+ case GL_BGR5_A1_ANGLEX:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ return false;
+}
+
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/format_map_data.json b/src/3rdparty/angle/src/libANGLE/format_map_data.json
new file mode 100644
index 0000000000..a4f1c98b4d
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/format_map_data.json
@@ -0,0 +1,142 @@
+{
+ "GL_RGBA": {
+ "GL_UNSIGNED_BYTE": "GL_RGBA8",
+ "GL_UNSIGNED_SHORT": "GL_RGBA16_EXT",
+ "GL_BYTE": "GL_RGBA8_SNORM",
+ "GL_SHORT": "GL_RGBA16_SNORM_EXT",
+ "GL_UNSIGNED_SHORT_4_4_4_4": "GL_RGBA4",
+ "GL_UNSIGNED_SHORT_5_5_5_1": "GL_RGB5_A1",
+ "GL_UNSIGNED_INT_2_10_10_10_REV": "GL_RGB10_A2",
+ "GL_FLOAT": "GL_RGBA32F",
+ "GL_HALF_FLOAT": "GL_RGBA16F",
+ "GL_HALF_FLOAT_OES": "GL_RGBA16F"
+ },
+ "GL_RGBA_INTEGER": {
+ "GL_UNSIGNED_BYTE": "GL_RGBA8UI",
+ "GL_BYTE": "GL_RGBA8I",
+ "GL_UNSIGNED_SHORT": "GL_RGBA16UI",
+ "GL_SHORT": "GL_RGBA16I",
+ "GL_UNSIGNED_INT": "GL_RGBA32UI",
+ "GL_INT": "GL_RGBA32I",
+ "GL_UNSIGNED_INT_2_10_10_10_REV": "GL_RGB10_A2UI"
+ },
+ "GL_RGB": {
+ "GL_UNSIGNED_BYTE": "GL_RGB8",
+ "GL_UNSIGNED_SHORT": "GL_RGB16_EXT",
+ "GL_BYTE": "GL_RGB8_SNORM",
+ "GL_SHORT": "GL_RGB16_SNORM_EXT",
+ "GL_UNSIGNED_SHORT_5_6_5": "GL_RGB565",
+ "GL_UNSIGNED_INT_10F_11F_11F_REV": "GL_R11F_G11F_B10F",
+ "GL_UNSIGNED_INT_5_9_9_9_REV": "GL_RGB9_E5",
+ "GL_FLOAT": "GL_RGB32F",
+ "GL_HALF_FLOAT": "GL_RGB16F",
+ "GL_HALF_FLOAT_OES": "GL_RGB16F"
+ },
+ "GL_RGB_INTEGER": {
+ "GL_UNSIGNED_BYTE": "GL_RGB8UI",
+ "GL_BYTE": "GL_RGB8I", "GL_UNSIGNED_SHORT": "GL_RGB16UI",
+ "GL_SHORT": "GL_RGB16I",
+ "GL_UNSIGNED_INT": "GL_RGB32UI",
+ "GL_INT": "GL_RGB32I"
+ },
+ "GL_RG": {
+ "GL_UNSIGNED_BYTE": "GL_RG8",
+ "GL_UNSIGNED_SHORT": "GL_RG16_EXT",
+ "GL_BYTE": "GL_RG8_SNORM",
+ "GL_SHORT": "GL_RG16_SNORM_EXT",
+ "GL_FLOAT": "GL_RG32F",
+ "GL_HALF_FLOAT": "GL_RG16F",
+ "GL_HALF_FLOAT_OES": "GL_RG16F"
+ },
+ "GL_RG_INTEGER": {
+ "GL_UNSIGNED_BYTE": "GL_RG8UI",
+ "GL_BYTE": "GL_RG8I",
+ "GL_UNSIGNED_SHORT": "GL_RG16UI",
+ "GL_SHORT": "GL_RG16I",
+ "GL_UNSIGNED_INT": "GL_RG32UI",
+ "GL_INT": "GL_RG32I"
+ },
+ "GL_RED": {
+ "GL_UNSIGNED_BYTE": "GL_R8",
+ "GL_UNSIGNED_SHORT": "GL_R16_EXT",
+ "GL_BYTE": "GL_R8_SNORM",
+ "GL_SHORT": "GL_R16_SNORM_EXT",
+ "GL_FLOAT": "GL_R32F",
+ "GL_HALF_FLOAT": "GL_R16F",
+ "GL_HALF_FLOAT_OES": "GL_R16F"
+ },
+ "GL_RED_INTEGER": {
+ "GL_UNSIGNED_BYTE": "GL_R8UI",
+ "GL_BYTE": "GL_R8I",
+ "GL_UNSIGNED_SHORT": "GL_R16UI",
+ "GL_SHORT": "GL_R16I",
+ "GL_UNSIGNED_INT": "GL_R32UI",
+ "GL_INT": "GL_R32I"
+ },
+ "GL_LUMINANCE_ALPHA": {
+ "GL_UNSIGNED_BYTE": "GL_LUMINANCE8_ALPHA8_EXT",
+ "GL_FLOAT": "GL_LUMINANCE_ALPHA32F_EXT",
+ "GL_HALF_FLOAT": "GL_LUMINANCE_ALPHA16F_EXT",
+ "GL_HALF_FLOAT_OES": "GL_LUMINANCE_ALPHA16F_EXT"
+ },
+ "GL_LUMINANCE": {
+ "GL_UNSIGNED_BYTE": "GL_LUMINANCE8_EXT",
+ "GL_FLOAT": "GL_LUMINANCE32F_EXT",
+ "GL_HALF_FLOAT": "GL_LUMINANCE16F_EXT",
+ "GL_HALF_FLOAT_OES": "GL_LUMINANCE16F_EXT"
+ },
+ "GL_ALPHA": {
+ "GL_UNSIGNED_BYTE": "GL_ALPHA8_EXT",
+ "GL_FLOAT": "GL_ALPHA32F_EXT",
+ "GL_HALF_FLOAT": "GL_ALPHA16F_EXT",
+ "GL_HALF_FLOAT_OES": "GL_ALPHA16F_EXT"
+ },
+ "GL_BGRA_EXT": {
+ "GL_UNSIGNED_BYTE": "GL_BGRA8_EXT",
+ "GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT": "GL_BGRA4_ANGLEX",
+ "GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT": "GL_BGR5_A1_ANGLEX",
+ "GL_UNSIGNED_SHORT_5_6_5": "GL_BGR565_ANGLEX"
+ },
+ "GL_SRGB_EXT": {
+ "GL_UNSIGNED_BYTE": "GL_SRGB8"
+ },
+ "GL_SRGB_ALPHA_EXT": {
+ "GL_UNSIGNED_BYTE": "GL_SRGB8_ALPHA8"
+ },
+ "GL_COMPRESSED_RGB_S3TC_DXT1_EXT": {
+ "GL_UNSIGNED_BYTE": "GL_COMPRESSED_RGB_S3TC_DXT1_EXT"
+ },
+ "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT": {
+ "GL_UNSIGNED_BYTE": "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT"
+ },
+ "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE": {
+ "GL_UNSIGNED_BYTE": "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE"
+ },
+ "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE": {
+ "GL_UNSIGNED_BYTE": "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE"
+ },
+ "GL_COMPRESSED_SRGB_S3TC_DXT1_EXT": {
+ "GL_UNSIGNED_BYTE": "GL_COMPRESSED_SRGB_S3TC_DXT1_EXT"
+ },
+ "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT": {
+ "GL_UNSIGNED_BYTE": "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT"
+ },
+ "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT": {
+ "GL_UNSIGNED_BYTE": "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT"
+ },
+ "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT": {
+ "GL_UNSIGNED_BYTE": "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT"
+ },
+ "GL_DEPTH_COMPONENT": {
+ "GL_UNSIGNED_SHORT": "GL_DEPTH_COMPONENT16",
+ "GL_UNSIGNED_INT": "GL_DEPTH_COMPONENT32_OES",
+ "GL_FLOAT": "GL_DEPTH_COMPONENT32F"
+ },
+ "GL_STENCIL": {
+ "GL_UNSIGNED_BYTE": "GL_STENCIL_INDEX8"
+ },
+ "GL_DEPTH_STENCIL": {
+ "GL_UNSIGNED_INT_24_8": "GL_DEPTH24_STENCIL8",
+ "GL_FLOAT_32_UNSIGNED_INT_24_8_REV": "GL_DEPTH32F_STENCIL8"
+ }
+}
diff --git a/src/3rdparty/angle/src/libANGLE/formatutils.cpp b/src/3rdparty/angle/src/libANGLE/formatutils.cpp
index f8b9a8bab8..67bb2efdea 100644
--- a/src/3rdparty/angle/src/libANGLE/formatutils.cpp
+++ b/src/3rdparty/angle/src/libANGLE/formatutils.cpp
@@ -6,11 +6,13 @@
// formatutils.cpp: Queries for GL image formats.
-#include "common/mathutil.h"
#include "libANGLE/formatutils.h"
+
+#include "common/mathutil.h"
#include "libANGLE/Context.h"
#include "libANGLE/Framebuffer.h"
-#include "libANGLE/renderer/Renderer.h"
+
+using namespace angle;
namespace gl
{
@@ -18,116 +20,28 @@ namespace gl
// ES2 requires that format is equal to internal format at all glTex*Image2D entry points and the implementation
// can decide the true, sized, internal format. The ES2FormatMap determines the internal format for all valid
// format and type combinations.
+GLenum GetSizedFormatInternal(GLenum format, GLenum type);
-typedef std::pair<GLenum, GLenum> FormatTypePair;
-typedef std::pair<FormatTypePair, GLenum> FormatPair;
-typedef std::map<FormatTypePair, GLenum> FormatMap;
-
-// A helper function to insert data into the format map with fewer characters.
-static inline void InsertFormatMapping(FormatMap *map, GLenum format, GLenum type, GLenum internalFormat)
-{
- map->insert(FormatPair(FormatTypePair(format, type), internalFormat));
-}
-
-FormatMap BuildFormatMap()
-{
- FormatMap map;
-
- // | Format | Type | Internal format |
- InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA8);
- InsertFormatMapping(&map, GL_RGBA, GL_BYTE, GL_RGBA8_SNORM);
- InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_RGBA4);
- InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_RGB5_A1);
- InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2);
- InsertFormatMapping(&map, GL_RGBA, GL_FLOAT, GL_RGBA32F);
- InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT, GL_RGBA16F);
- InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA16F);
-
- InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_RGBA8UI);
- InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_BYTE, GL_RGBA8I);
- InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_RGBA16UI);
- InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_SHORT, GL_RGBA16I);
- InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_RGBA32UI);
- InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_INT, GL_RGBA32I);
- InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2UI);
-
- InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_BYTE, GL_RGB8);
- InsertFormatMapping(&map, GL_RGB, GL_BYTE, GL_RGB8_SNORM);
- InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_RGB565);
- InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_R11F_G11F_B10F);
- InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_RGB9_E5);
- InsertFormatMapping(&map, GL_RGB, GL_FLOAT, GL_RGB32F);
- InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT, GL_RGB16F);
- InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT_OES, GL_RGB16F);
-
- InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_RGB8UI);
- InsertFormatMapping(&map, GL_RGB_INTEGER, GL_BYTE, GL_RGB8I);
- InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_RGB16UI);
- InsertFormatMapping(&map, GL_RGB_INTEGER, GL_SHORT, GL_RGB16I);
- InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_RGB32UI);
- InsertFormatMapping(&map, GL_RGB_INTEGER, GL_INT, GL_RGB32I);
-
- InsertFormatMapping(&map, GL_RG, GL_UNSIGNED_BYTE, GL_RG8);
- InsertFormatMapping(&map, GL_RG, GL_BYTE, GL_RG8_SNORM);
- InsertFormatMapping(&map, GL_RG, GL_FLOAT, GL_RG32F);
- InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT, GL_RG16F);
- InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT_OES, GL_RG16F);
-
- InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_RG8UI);
- InsertFormatMapping(&map, GL_RG_INTEGER, GL_BYTE, GL_RG8I);
- InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_RG16UI);
- InsertFormatMapping(&map, GL_RG_INTEGER, GL_SHORT, GL_RG16I);
- InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_RG32UI);
- InsertFormatMapping(&map, GL_RG_INTEGER, GL_INT, GL_RG32I);
-
- InsertFormatMapping(&map, GL_RED, GL_UNSIGNED_BYTE, GL_R8);
- InsertFormatMapping(&map, GL_RED, GL_BYTE, GL_R8_SNORM);
- InsertFormatMapping(&map, GL_RED, GL_FLOAT, GL_R32F);
- InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT, GL_R16F);
- InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT_OES, GL_R16F);
-
- InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_R8UI);
- InsertFormatMapping(&map, GL_RED_INTEGER, GL_BYTE, GL_R8I);
- InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_R16UI);
- InsertFormatMapping(&map, GL_RED_INTEGER, GL_SHORT, GL_R16I);
- InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_R32UI);
- InsertFormatMapping(&map, GL_RED_INTEGER, GL_INT, GL_R32I);
-
- InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_LUMINANCE8_ALPHA8_EXT);
- InsertFormatMapping(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_LUMINANCE8_EXT);
- InsertFormatMapping(&map, GL_ALPHA, GL_UNSIGNED_BYTE, GL_ALPHA8_EXT);
- InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_LUMINANCE_ALPHA32F_EXT);
- InsertFormatMapping(&map, GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE32F_EXT);
- InsertFormatMapping(&map, GL_ALPHA, GL_FLOAT, GL_ALPHA32F_EXT);
- InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, GL_LUMINANCE_ALPHA16F_EXT);
- InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_LUMINANCE_ALPHA16F_EXT);
- InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT, GL_LUMINANCE16F_EXT);
- InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_LUMINANCE16F_EXT);
- InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT, GL_ALPHA16F_EXT);
- InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT_OES, GL_ALPHA16F_EXT);
-
- InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_BGRA8_EXT);
- InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_BGRA4_ANGLEX);
- InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_BGR5_A1_ANGLEX);
-
- InsertFormatMapping(&map, GL_SRGB_EXT, GL_UNSIGNED_BYTE, GL_SRGB8);
- InsertFormatMapping(&map, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, GL_SRGB8_ALPHA8);
-
- InsertFormatMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
- InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
- InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE);
- InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE);
-
- InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT16);
- InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT32_OES);
- InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_FLOAT, GL_DEPTH_COMPONENT32F);
-
- InsertFormatMapping(&map, GL_STENCIL, GL_UNSIGNED_BYTE, GL_STENCIL_INDEX8);
-
- InsertFormatMapping(&map, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH24_STENCIL8);
- InsertFormatMapping(&map, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_DEPTH32F_STENCIL8);
+namespace
+{
+using InternalFormatInfoMap =
+ std::unordered_map<GLenum, std::unordered_map<GLenum, InternalFormat>>;
- return map;
+} // anonymous namespace
+
+FormatType::FormatType() : format(GL_NONE), type(GL_NONE)
+{
+}
+
+FormatType::FormatType(GLenum format_, GLenum type_) : format(format_), type(type_)
+{
+}
+
+bool FormatType::operator<(const FormatType &other) const
+{
+ if (format != other.format)
+ return format < other.format;
+ return type < other.type;
}
Type::Type()
@@ -158,20 +72,20 @@ bool operator<(const Type& a, const Type& b)
}
// Information about internal formats
-static bool AlwaysSupported(GLuint, const Extensions &)
+static bool AlwaysSupported(const Version &, const Extensions &)
{
return true;
}
-static bool NeverSupported(GLuint, const Extensions &)
+static bool NeverSupported(const Version &, const Extensions &)
{
return false;
}
-template <GLuint minCoreGLVersion>
-static bool RequireES(GLuint clientVersion, const Extensions &)
+template <GLuint minCoreGLMajorVersion, GLuint minCoreGLMinorVersion>
+static bool RequireES(const Version &clientVersion, const Extensions &)
{
- return clientVersion >= minCoreGLVersion;
+ return clientVersion >= Version(minCoreGLMajorVersion, minCoreGLMinorVersion);
}
// Pointer to a boolean memeber of the Extensions struct
@@ -179,96 +93,192 @@ typedef bool(Extensions::*ExtensionBool);
// Check support for a single extension
template <ExtensionBool bool1>
-static bool RequireExt(GLuint, const Extensions & extensions)
+static bool RequireExt(const Version &, const Extensions &extensions)
{
return extensions.*bool1;
}
// Check for a minimum client version or a single extension
-template <GLuint minCoreGLVersion, ExtensionBool bool1>
-static bool RequireESOrExt(GLuint clientVersion, const Extensions &extensions)
+template <GLuint minCoreGLMajorVersion, GLuint minCoreGLMinorVersion, ExtensionBool bool1>
+static bool RequireESOrExt(const Version &clientVersion, const Extensions &extensions)
{
- return clientVersion >= minCoreGLVersion || extensions.*bool1;
+ return clientVersion >= Version(minCoreGLMajorVersion, minCoreGLMinorVersion) ||
+ extensions.*bool1;
}
// Check for a minimum client version or two extensions
-template <GLuint minCoreGLVersion, ExtensionBool bool1, ExtensionBool bool2>
-static bool RequireESOrExtAndExt(GLuint clientVersion, const Extensions &extensions)
+template <GLuint minCoreGLMajorVersion,
+ GLuint minCoreGLMinorVersion,
+ ExtensionBool bool1,
+ ExtensionBool bool2>
+static bool RequireESOrExtAndExt(const Version &clientVersion, const Extensions &extensions)
{
- return clientVersion >= minCoreGLVersion || (extensions.*bool1 && extensions.*bool2);
+ return clientVersion >= Version(minCoreGLMajorVersion, minCoreGLMinorVersion) ||
+ (extensions.*bool1 && extensions.*bool2);
}
// Check for a minimum client version or at least one of two extensions
-template <GLuint minCoreGLVersion, ExtensionBool bool1, ExtensionBool bool2>
-static bool RequireESOrExtOrExt(GLuint clientVersion, const Extensions &extensions)
+template <GLuint minCoreGLMajorVersion,
+ GLuint minCoreGLMinorVersion,
+ ExtensionBool bool1,
+ ExtensionBool bool2>
+static bool RequireESOrExtOrExt(const Version &clientVersion, const Extensions &extensions)
{
- return clientVersion >= minCoreGLVersion || extensions.*bool1 || extensions.*bool2;
+ return clientVersion >= Version(minCoreGLMajorVersion, minCoreGLMinorVersion) ||
+ extensions.*bool1 || extensions.*bool2;
}
// Check support for two extensions
template <ExtensionBool bool1, ExtensionBool bool2>
-static bool RequireExtAndExt(GLuint, const Extensions &extensions)
+static bool RequireExtAndExt(const Version &, const Extensions &extensions)
{
return extensions.*bool1 && extensions.*bool2;
}
// Check support for either of two extensions
template <ExtensionBool bool1, ExtensionBool bool2>
-static bool RequireExtOrExt(GLuint, const Extensions &extensions)
+static bool RequireExtOrExt(const Version &, const Extensions &extensions)
{
return extensions.*bool1 || extensions.*bool2;
}
// Special function for half float formats with three or four channels.
-static bool HalfFloatSupport(GLuint clientVersion, const Extensions &extensions)
+static bool HalfFloatSupport(const Version &clientVersion, const Extensions &extensions)
{
- return clientVersion >= 3 || extensions.textureHalfFloat;
+ return clientVersion >= Version(3, 0) || extensions.textureHalfFloat;
}
-static bool HalfFloatRenderableSupport(GLuint clientVersion, const Extensions &extensions)
+static bool HalfFloatRGBRenderableSupport(const Version &clientVersion,
+ const Extensions &extensions)
{
return HalfFloatSupport(clientVersion, extensions) && extensions.colorBufferHalfFloat;
}
+static bool HalfFloatRGBARenderableSupport(const Version &clientVersion,
+ const Extensions &extensions)
+{
+ return HalfFloatSupport(clientVersion, extensions) &&
+ (extensions.colorBufferHalfFloat || extensions.colorBufferFloat);
+}
+
// Special function for half float formats with one or two channels.
-static bool HalfFloatSupportRG(GLuint clientVersion, const Extensions &extensions)
+
+// R16F, RG16F
+static bool HalfFloatRGSupport(const Version &clientVersion, const Extensions &extensions)
+{
+ return clientVersion >= Version(3, 0) || (extensions.textureHalfFloat && extensions.textureRG);
+}
+
+// R16F, RG16F
+static bool HalfFloatRGRenderableSupport(const Version &clientVersion, const Extensions &extensions)
{
- return clientVersion >= 3 || (extensions.textureHalfFloat && extensions.textureRG);
+ // It's unclear if EXT_color_buffer_half_float gives renderability to non-OES half float
+ // textures
+ return HalfFloatRGSupport(clientVersion, extensions) &&
+ (extensions.colorBufferHalfFloat || extensions.colorBufferFloat);
}
-static bool HalfFloatRenderableSupportRG(GLuint clientVersion, const Extensions &extensions)
+// RED + HALF_FLOAT_OES, RG + HALF_FLOAT_OES
+static bool UnsizedHalfFloatOESRGSupport(const Version &, const Extensions &extensions)
{
- return HalfFloatSupportRG(clientVersion, extensions) && extensions.colorBufferHalfFloat;
+ return extensions.textureHalfFloat && extensions.textureRG;
+}
+
+// RED + HALF_FLOAT_OES, RG + HALF_FLOAT_OES
+static bool UnsizedHalfFloatOESRGRenderableSupport(const Version &clientVersion,
+ const Extensions &extensions)
+{
+ return UnsizedHalfFloatOESRGSupport(clientVersion, extensions) &&
+ extensions.colorBufferHalfFloat;
+}
+
+// RGB + HALF_FLOAT_OES, RGBA + HALF_FLOAT_OES
+static bool UnsizedHalfFloatOESSupport(const Version &clientVersion, const Extensions &extensions)
+{
+ return extensions.textureHalfFloat;
+}
+
+// RGB + HALF_FLOAT_OES, RGBA + HALF_FLOAT_OES
+static bool UnsizedHalfFloatOESRenderableSupport(const Version &clientVersion,
+ const Extensions &extensions)
+{
+ return UnsizedHalfFloatOESSupport(clientVersion, extensions) && extensions.colorBufferHalfFloat;
}
// Special function for float formats with three or four channels.
-static bool FloatSupport(GLuint clientVersion, const Extensions &extensions)
+
+// RGB32F, RGBA32F
+static bool FloatSupport(const Version &clientVersion, const Extensions &extensions)
{
- return clientVersion >= 3 || extensions.textureFloat;
+ return clientVersion >= Version(3, 0) || extensions.textureFloat;
}
-static bool FloatRenderableSupport(GLuint clientVersion, const Extensions &extensions)
+// RGB32F
+static bool FloatRGBRenderableSupport(const Version &clientVersion, const Extensions &extensions)
+{
+ return FloatSupport(clientVersion, extensions) && extensions.colorBufferFloatRGB;
+}
+
+// RGBA32F
+static bool FloatRGBARenderableSupport(const Version &clientVersion, const Extensions &extensions)
{
- // We don't expose colorBufferFloat in ES2, but we silently support rendering to float.
return FloatSupport(clientVersion, extensions) &&
- (extensions.colorBufferFloat || clientVersion == 2);
+ (extensions.colorBufferFloat || extensions.colorBufferFloatRGBA);
+}
+
+// RGB + FLOAT, RGBA + FLOAT
+static bool UnsizedFloatSupport(const Version &clientVersion, const Extensions &extensions)
+{
+ return extensions.textureFloat;
+}
+
+// RGB + FLOAT
+static bool UnsizedFloatRGBRenderableSupport(const Version &clientVersion,
+ const Extensions &extensions)
+{
+ return UnsizedFloatSupport(clientVersion, extensions) && extensions.colorBufferFloatRGB;
+}
+
+// RGBA + FLOAT
+static bool UnsizedFloatRGBARenderableSupport(const Version &clientVersion,
+ const Extensions &extensions)
+{
+ return UnsizedFloatSupport(clientVersion, extensions) &&
+ (extensions.colorBufferFloatRGBA || extensions.colorBufferFloat);
}
// Special function for float formats with one or two channels.
-static bool FloatSupportRG(GLuint clientVersion, const Extensions &extensions)
+
+// R32F, RG32F
+static bool FloatRGSupport(const Version &clientVersion, const Extensions &extensions)
+{
+ return clientVersion >= Version(3, 0) || (extensions.textureFloat && extensions.textureRG);
+}
+
+// R32F, RG32F
+static bool FloatRGRenderableSupport(const Version &clientVersion, const Extensions &extensions)
{
- return clientVersion >= 3 || (extensions.textureFloat && extensions.textureRG);
+ return FloatRGSupport(clientVersion, extensions) && extensions.colorBufferFloat;
}
-static bool FloatRenderableSupportRG(GLuint clientVersion, const Extensions &extensions)
+// RED + FLOAT, RG + FLOAT
+static bool UnsizedFloatRGSupport(const Version &clientVersion, const Extensions &extensions)
{
- // We don't expose colorBufferFloat in ES2, but we silently support rendering to float.
- return FloatSupportRG(clientVersion, extensions) &&
- (extensions.colorBufferFloat || clientVersion == 2);
+ return extensions.textureFloat && extensions.textureRG;
+}
+
+// RED + FLOAT, RG + FLOAT
+static bool UnsizedFloatRGRenderableSupport(const Version &clientVersion,
+ const Extensions &extensions)
+{
+ return FloatRGSupport(clientVersion, extensions) && extensions.colorBufferFloat;
}
InternalFormat::InternalFormat()
- : redBits(0),
+ : internalFormat(GL_NONE),
+ sized(false),
+ sizedInternalFormat(GL_NONE),
+ redBits(0),
greenBits(0),
blueBits(0),
luminanceBits(0),
@@ -291,32 +301,252 @@ InternalFormat::InternalFormat()
{
}
-static InternalFormat UnsizedFormat(GLenum format, InternalFormat::SupportCheckFunction textureSupport,
- InternalFormat::SupportCheckFunction renderSupport,
- InternalFormat::SupportCheckFunction filterSupport)
+InternalFormat::InternalFormat(const InternalFormat &other) = default;
+
+bool InternalFormat::isLUMA() const
{
- InternalFormat formatInfo;
- formatInfo.format = format;
- formatInfo.textureSupport = textureSupport;
- formatInfo.renderSupport = renderSupport;
- formatInfo.filterSupport = filterSupport;
- return formatInfo;
+ return ((redBits + greenBits + blueBits + depthBits + stencilBits) == 0 &&
+ (luminanceBits + alphaBits) > 0);
+}
+
+GLenum InternalFormat::getReadPixelsFormat() const
+{
+ return format;
}
-static InternalFormat RGBAFormat(GLuint red, GLuint green, GLuint blue, GLuint alpha, GLuint shared,
- GLenum format, GLenum type, GLenum componentType, bool srgb,
- InternalFormat::SupportCheckFunction textureSupport,
- InternalFormat::SupportCheckFunction renderSupport,
- InternalFormat::SupportCheckFunction filterSupport)
+GLenum InternalFormat::getReadPixelsType(const Version &version) const
+{
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ case GL_HALF_FLOAT_OES:
+ if (version < Version(3, 0))
+ {
+ // The internal format may have a type of GL_HALF_FLOAT but when exposing this type
+ // as the IMPLEMENTATION_READ_TYPE, only HALF_FLOAT_OES is allowed by
+ // OES_texture_half_float. HALF_FLOAT becomes core in ES3 and is acceptable to use
+ // as an IMPLEMENTATION_READ_TYPE.
+ return GL_HALF_FLOAT_OES;
+ }
+ else
+ {
+ return GL_HALF_FLOAT;
+ }
+
+ default:
+ return type;
+ }
+}
+
+bool InternalFormat::isRequiredRenderbufferFormat(const Version &version) const
+{
+ // GLES 3.0.5 section 4.4.2.2:
+ // "Implementations are required to support the same internal formats for renderbuffers as the
+ // required formats for textures enumerated in section 3.8.3.1, with the exception of the color
+ // formats labelled "texture-only"."
+ if (!sized || compressed)
+ {
+ return false;
+ }
+
+ // Luma formats.
+ if (isLUMA())
+ {
+ return false;
+ }
+
+ // Depth/stencil formats.
+ if (depthBits > 0 || stencilBits > 0)
+ {
+ // GLES 2.0.25 table 4.5.
+ // GLES 3.0.5 section 3.8.3.1.
+ // GLES 3.1 table 8.14.
+
+ // Required formats in all versions.
+ switch (internalFormat)
+ {
+ case GL_DEPTH_COMPONENT16:
+ case GL_STENCIL_INDEX8:
+ // Note that STENCIL_INDEX8 is not mentioned in GLES 3.0.5 section 3.8.3.1, but it
+ // is in section 4.4.2.2.
+ return true;
+ default:
+ break;
+ }
+ if (version.major < 3)
+ {
+ return false;
+ }
+ // Required formats in GLES 3.0 and up.
+ switch (internalFormat)
+ {
+ case GL_DEPTH_COMPONENT32F:
+ case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH32F_STENCIL8:
+ case GL_DEPTH24_STENCIL8:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ // RGBA formats.
+ // GLES 2.0.25 table 4.5.
+ // GLES 3.0.5 section 3.8.3.1.
+ // GLES 3.1 table 8.13.
+
+ // Required formats in all versions.
+ switch (internalFormat)
+ {
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGB565:
+ return true;
+ default:
+ break;
+ }
+ if (version.major < 3)
+ {
+ return false;
+ }
+
+ if (format == GL_BGRA_EXT)
+ {
+ return false;
+ }
+
+ switch (componentType)
+ {
+ case GL_SIGNED_NORMALIZED:
+ case GL_FLOAT:
+ return false;
+ case GL_UNSIGNED_INT:
+ case GL_INT:
+ // Integer RGB formats are not required renderbuffer formats.
+ if (alphaBits == 0 && blueBits != 0)
+ {
+ return false;
+ }
+ // All integer R and RG formats are required.
+ // Integer RGBA formats including RGB10_A2_UI are required.
+ return true;
+ case GL_UNSIGNED_NORMALIZED:
+ if (internalFormat == GL_SRGB8)
+ {
+ return false;
+ }
+ return true;
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+Format::Format(GLenum internalFormat) : Format(GetSizedInternalFormatInfo(internalFormat))
+{
+}
+
+Format::Format(const InternalFormat &internalFormat) : info(&internalFormat)
+{
+}
+
+Format::Format(GLenum internalFormat, GLenum type)
+ : info(&GetInternalFormatInfo(internalFormat, type))
+{
+}
+
+Format::Format(const Format &other) = default;
+Format &Format::operator=(const Format &other) = default;
+
+bool Format::valid() const
+{
+ return info->internalFormat != GL_NONE;
+}
+
+// static
+bool Format::SameSized(const Format &a, const Format &b)
+{
+ return a.info->sizedInternalFormat == b.info->sizedInternalFormat;
+}
+
+static GLenum EquivalentBlitInternalFormat(GLenum internalformat)
+{
+ // BlitFramebuffer works if the color channels are identically
+ // sized, even if there is a swizzle (for example, blitting from a
+ // multisampled RGBA8 renderbuffer to a BGRA8 texture). This could
+ // be expanded and/or autogenerated if that is found necessary.
+ if (internalformat == GL_BGRA8_EXT)
+ return GL_RGBA8;
+ return internalformat;
+}
+
+// static
+bool Format::EquivalentForBlit(const Format &a, const Format &b)
+{
+ return (EquivalentBlitInternalFormat(a.info->sizedInternalFormat) ==
+ EquivalentBlitInternalFormat(b.info->sizedInternalFormat));
+}
+
+// static
+Format Format::Invalid()
+{
+ static Format invalid(GL_NONE, GL_NONE);
+ return invalid;
+}
+
+std::ostream &operator<<(std::ostream &os, const Format &fmt)
+{
+ // TODO(ynovikov): return string representation when available
+ return FmtHexShort(os, fmt.info->sizedInternalFormat);
+}
+
+bool InternalFormat::operator==(const InternalFormat &other) const
+{
+ // We assume all internal formats are unique if they have the same internal format and type
+ return internalFormat == other.internalFormat && type == other.type;
+}
+
+bool InternalFormat::operator!=(const InternalFormat &other) const
+{
+ return !(*this == other);
+}
+
+void InsertFormatInfo(InternalFormatInfoMap *map, const InternalFormat &formatInfo)
+{
+ ASSERT(!formatInfo.sized || (*map).count(formatInfo.internalFormat) == 0);
+ ASSERT((*map)[formatInfo.internalFormat].count(formatInfo.type) == 0);
+ (*map)[formatInfo.internalFormat][formatInfo.type] = formatInfo;
+}
+
+void AddRGBAFormat(InternalFormatInfoMap *map,
+ GLenum internalFormat,
+ bool sized,
+ GLuint red,
+ GLuint green,
+ GLuint blue,
+ GLuint alpha,
+ GLuint shared,
+ GLenum format,
+ GLenum type,
+ GLenum componentType,
+ bool srgb,
+ InternalFormat::SupportCheckFunction textureSupport,
+ InternalFormat::SupportCheckFunction renderSupport,
+ InternalFormat::SupportCheckFunction filterSupport)
{
InternalFormat formatInfo;
+ formatInfo.internalFormat = internalFormat;
+ formatInfo.sized = sized;
+ formatInfo.sizedInternalFormat =
+ sized ? internalFormat : GetSizedFormatInternal(internalFormat, type);
formatInfo.redBits = red;
formatInfo.greenBits = green;
formatInfo.blueBits = blue;
formatInfo.alphaBits = alpha;
formatInfo.sharedBits = shared;
formatInfo.pixelBytes = (red + green + blue + alpha + shared) / 8;
- formatInfo.componentCount = ((red > 0) ? 1 : 0) + ((green > 0) ? 1 : 0) + ((blue > 0) ? 1 : 0) + ((alpha > 0) ? 1 : 0);
+ formatInfo.componentCount =
+ ((red > 0) ? 1 : 0) + ((green > 0) ? 1 : 0) + ((blue > 0) ? 1 : 0) + ((alpha > 0) ? 1 : 0);
formatInfo.format = format;
formatInfo.type = type;
formatInfo.componentType = componentType;
@@ -324,15 +554,27 @@ static InternalFormat RGBAFormat(GLuint red, GLuint green, GLuint blue, GLuint a
formatInfo.textureSupport = textureSupport;
formatInfo.renderSupport = renderSupport;
formatInfo.filterSupport = filterSupport;
- return formatInfo;
+
+ InsertFormatInfo(map, formatInfo);
}
-static InternalFormat LUMAFormat(GLuint luminance, GLuint alpha, GLenum format, GLenum type, GLenum componentType,
- InternalFormat::SupportCheckFunction textureSupport,
- InternalFormat::SupportCheckFunction renderSupport,
- InternalFormat::SupportCheckFunction filterSupport)
+static void AddLUMAFormat(InternalFormatInfoMap *map,
+ GLenum internalFormat,
+ bool sized,
+ GLuint luminance,
+ GLuint alpha,
+ GLenum format,
+ GLenum type,
+ GLenum componentType,
+ InternalFormat::SupportCheckFunction textureSupport,
+ InternalFormat::SupportCheckFunction renderSupport,
+ InternalFormat::SupportCheckFunction filterSupport)
{
InternalFormat formatInfo;
+ formatInfo.internalFormat = internalFormat;
+ formatInfo.sized = sized;
+ formatInfo.sizedInternalFormat =
+ sized ? internalFormat : GetSizedFormatInternal(internalFormat, type);
formatInfo.luminanceBits = luminance;
formatInfo.alphaBits = alpha;
formatInfo.pixelBytes = (luminance + alpha) / 8;
@@ -344,15 +586,28 @@ static InternalFormat LUMAFormat(GLuint luminance, GLuint alpha, GLenum format,
formatInfo.textureSupport = textureSupport;
formatInfo.renderSupport = renderSupport;
formatInfo.filterSupport = filterSupport;
- return formatInfo;
+
+ InsertFormatInfo(map, formatInfo);
}
-static InternalFormat DepthStencilFormat(GLuint depthBits, GLuint stencilBits, GLuint unusedBits, GLenum format,
- GLenum type, GLenum componentType, InternalFormat::SupportCheckFunction textureSupport,
- InternalFormat::SupportCheckFunction renderSupport,
- InternalFormat::SupportCheckFunction filterSupport)
+void AddDepthStencilFormat(InternalFormatInfoMap *map,
+ GLenum internalFormat,
+ bool sized,
+ GLuint depthBits,
+ GLuint stencilBits,
+ GLuint unusedBits,
+ GLenum format,
+ GLenum type,
+ GLenum componentType,
+ InternalFormat::SupportCheckFunction textureSupport,
+ InternalFormat::SupportCheckFunction renderSupport,
+ InternalFormat::SupportCheckFunction filterSupport)
{
InternalFormat formatInfo;
+ formatInfo.internalFormat = internalFormat;
+ formatInfo.sized = sized;
+ formatInfo.sizedInternalFormat =
+ sized ? internalFormat : GetSizedFormatInternal(internalFormat, type);
formatInfo.depthBits = depthBits;
formatInfo.stencilBits = stencilBits;
formatInfo.pixelBytes = (depthBits + stencilBits + unusedBits) / 8;
@@ -364,16 +619,27 @@ static InternalFormat DepthStencilFormat(GLuint depthBits, GLuint stencilBits, G
formatInfo.textureSupport = textureSupport;
formatInfo.renderSupport = renderSupport;
formatInfo.filterSupport = filterSupport;
- return formatInfo;
+
+ InsertFormatInfo(map, formatInfo);
}
-static InternalFormat CompressedFormat(GLuint compressedBlockWidth, GLuint compressedBlockHeight, GLuint compressedBlockSize,
- GLuint componentCount, GLenum format, GLenum type, bool srgb,
- InternalFormat::SupportCheckFunction textureSupport,
- InternalFormat::SupportCheckFunction renderSupport,
- InternalFormat::SupportCheckFunction filterSupport)
+void AddCompressedFormat(InternalFormatInfoMap *map,
+ GLenum internalFormat,
+ GLuint compressedBlockWidth,
+ GLuint compressedBlockHeight,
+ GLuint compressedBlockSize,
+ GLuint componentCount,
+ GLenum format,
+ GLenum type,
+ bool srgb,
+ InternalFormat::SupportCheckFunction textureSupport,
+ InternalFormat::SupportCheckFunction renderSupport,
+ InternalFormat::SupportCheckFunction filterSupport)
{
InternalFormat formatInfo;
+ formatInfo.internalFormat = internalFormat;
+ formatInfo.sized = true;
+ formatInfo.sizedInternalFormat = internalFormat;
formatInfo.compressedBlockWidth = compressedBlockWidth;
formatInfo.compressedBlockHeight = compressedBlockHeight;
formatInfo.pixelBytes = compressedBlockSize / 8;
@@ -386,189 +652,279 @@ static InternalFormat CompressedFormat(GLuint compressedBlockWidth, GLuint compr
formatInfo.textureSupport = textureSupport;
formatInfo.renderSupport = renderSupport;
formatInfo.filterSupport = filterSupport;
- return formatInfo;
-}
-typedef std::pair<GLenum, InternalFormat> InternalFormatInfoPair;
-typedef std::map<GLenum, InternalFormat> InternalFormatInfoMap;
+ InsertFormatInfo(map, formatInfo);
+}
static InternalFormatInfoMap BuildInternalFormatInfoMap()
{
InternalFormatInfoMap map;
- // clang-format off
// From ES 3.0.1 spec, table 3.12
- map.insert(InternalFormatInfoPair(GL_NONE, InternalFormat()));
-
- // | Internal format | | R | G | B | A |S | Format | Type | Component type | SRGB | Texture supported | Renderable | Filterable |
- map.insert(InternalFormatInfoPair(GL_R8, RGBAFormat( 8, 0, 0, 0, 0, GL_RED, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, &Extensions::textureRG>, RequireESOrExt<3, &Extensions::textureRG>, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_R8_SNORM, RGBAFormat( 8, 0, 0, 0, 0, GL_RED, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_RG8, RGBAFormat( 8, 8, 0, 0, 0, GL_RG, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, &Extensions::textureRG>, RequireESOrExt<3, &Extensions::textureRG>, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_RG8_SNORM, RGBAFormat( 8, 8, 0, 0, 0, GL_RG, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_RGB8, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, &Extensions::rgb8rgba8>, RequireESOrExt<3, &Extensions::rgb8rgba8>, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_RGB8_SNORM, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_RGB565, RGBAFormat( 5, 6, 5, 0, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_NORMALIZED, false, RequireES<2>, RequireES<2>, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_RGBA4, RGBAFormat( 4, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_NORMALIZED, false, RequireES<2>, RequireES<2>, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_RGB5_A1, RGBAFormat( 5, 5, 5, 1, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_NORMALIZED, false, RequireES<2>, RequireES<2>, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_RGBA8, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, &Extensions::rgb8rgba8>, RequireESOrExt<3, &Extensions::rgb8rgba8>, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_RGBA8_SNORM, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_RGB10_A2, RGBAFormat(10, 10, 10, 2, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_NORMALIZED, false, RequireES<3>, RequireES<3>, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_RGB10_A2UI, RGBAFormat(10, 10, 10, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
- map.insert(InternalFormatInfoPair(GL_SRGB8, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireESOrExt<3, &Extensions::sRGB>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_SRGB8_ALPHA8, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireESOrExt<3, &Extensions::sRGB>, RequireESOrExt<3, &Extensions::sRGB>, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_R11F_G11F_B10F, RGBAFormat(11, 11, 10, 0, 0, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_FLOAT, false, RequireES<3>, RequireExt<&Extensions::colorBufferFloat>, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_RGB9_E5, RGBAFormat( 9, 9, 9, 0, 5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT, false, RequireES<3>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_R8I, RGBAFormat( 8, 0, 0, 0, 0, GL_RED_INTEGER, GL_BYTE, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
- map.insert(InternalFormatInfoPair(GL_R8UI, RGBAFormat( 8, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
- map.insert(InternalFormatInfoPair(GL_R16I, RGBAFormat(16, 0, 0, 0, 0, GL_RED_INTEGER, GL_SHORT, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
- map.insert(InternalFormatInfoPair(GL_R16UI, RGBAFormat(16, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
- map.insert(InternalFormatInfoPair(GL_R32I, RGBAFormat(32, 0, 0, 0, 0, GL_RED_INTEGER, GL_INT, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
- map.insert(InternalFormatInfoPair(GL_R32UI, RGBAFormat(32, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
- map.insert(InternalFormatInfoPair(GL_RG8I, RGBAFormat( 8, 8, 0, 0, 0, GL_RG_INTEGER, GL_BYTE, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
- map.insert(InternalFormatInfoPair(GL_RG8UI, RGBAFormat( 8, 8, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
- map.insert(InternalFormatInfoPair(GL_RG16I, RGBAFormat(16, 16, 0, 0, 0, GL_RG_INTEGER, GL_SHORT, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
- map.insert(InternalFormatInfoPair(GL_RG16UI, RGBAFormat(16, 16, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
- map.insert(InternalFormatInfoPair(GL_RG32I, RGBAFormat(32, 32, 0, 0, 0, GL_RG_INTEGER, GL_INT, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
- map.insert(InternalFormatInfoPair(GL_RG32UI, RGBAFormat(32, 32, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
- map.insert(InternalFormatInfoPair(GL_RGB8I, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB_INTEGER, GL_BYTE, GL_INT, false, RequireES<3>, NeverSupported, NeverSupported)));
- map.insert(InternalFormatInfoPair(GL_RGB8UI, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3>, NeverSupported, NeverSupported)));
- map.insert(InternalFormatInfoPair(GL_RGB16I, RGBAFormat(16, 16, 16, 0, 0, GL_RGB_INTEGER, GL_SHORT, GL_INT, false, RequireES<3>, NeverSupported, NeverSupported)));
- map.insert(InternalFormatInfoPair(GL_RGB16UI, RGBAFormat(16, 16, 16, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3>, NeverSupported, NeverSupported)));
- map.insert(InternalFormatInfoPair(GL_RGB32I, RGBAFormat(32, 32, 32, 0, 0, GL_RGB_INTEGER, GL_INT, GL_INT, false, RequireES<3>, NeverSupported, NeverSupported)));
- map.insert(InternalFormatInfoPair(GL_RGB32UI, RGBAFormat(32, 32, 32, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3>, NeverSupported, NeverSupported)));
- map.insert(InternalFormatInfoPair(GL_RGBA8I, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA_INTEGER, GL_BYTE, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
- map.insert(InternalFormatInfoPair(GL_RGBA8UI, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
- map.insert(InternalFormatInfoPair(GL_RGBA16I, RGBAFormat(16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_SHORT, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
- map.insert(InternalFormatInfoPair(GL_RGBA16UI, RGBAFormat(16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
- map.insert(InternalFormatInfoPair(GL_RGBA32I, RGBAFormat(32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_INT, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
- map.insert(InternalFormatInfoPair(GL_RGBA32UI, RGBAFormat(32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported)));
-
- map.insert(InternalFormatInfoPair(GL_BGRA8_EXT, RGBAFormat( 8, 8, 8, 8, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_BGRA4_ANGLEX, RGBAFormat( 4, 4, 4, 4, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_BGR5_A1_ANGLEX, RGBAFormat( 5, 5, 5, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported)));
+ map[GL_NONE][GL_NONE] = InternalFormat();
+
+ // clang-format off
+
+ // | Internal format |sized| R | G | B | A |S | Format | Type | Component type | SRGB | Texture supported | Renderable | Filterable |
+ AddRGBAFormat(&map, GL_R8, true, 8, 0, 0, 0, 0, GL_RED, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, 0, &Extensions::textureRG>, RequireESOrExt<3, 0, &Extensions::textureRG>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_R8_SNORM, true, 8, 0, 0, 0, 0, GL_RED, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RG8, true, 8, 8, 0, 0, 0, GL_RG, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, 0, &Extensions::textureRG>, RequireESOrExt<3, 0, &Extensions::textureRG>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RG8_SNORM, true, 8, 8, 0, 0, 0, GL_RG, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGB8, true, 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, 0, &Extensions::rgb8rgba8>, RequireESOrExt<3, 0, &Extensions::rgb8rgba8>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGB8_SNORM, true, 8, 8, 8, 0, 0, GL_RGB, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGB565, true, 5, 6, 5, 0, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_NORMALIZED, false, RequireES<2, 0>, RequireES<2, 0>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGBA4, true, 4, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_NORMALIZED, false, RequireES<2, 0>, RequireES<2, 0>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGB5_A1, true, 5, 5, 5, 1, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_NORMALIZED, false, RequireES<2, 0>, RequireES<2, 0>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGBA8, true, 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, 0, &Extensions::rgb8rgba8>, RequireESOrExt<3, 0, &Extensions::rgb8rgba8>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGBA8_SNORM, true, 8, 8, 8, 8, 0, GL_RGBA, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGB10_A2, true, 10, 10, 10, 2, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_NORMALIZED, false, RequireES<3, 0>, RequireES<3, 0>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGB10_A2UI, true, 10, 10, 10, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_SRGB8, true, 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireESOrExt<3, 0, &Extensions::sRGB>, NeverSupported, AlwaysSupported);
+ AddRGBAFormat(&map, GL_SRGB8_ALPHA8, true, 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireESOrExt<3, 0, &Extensions::sRGB>, RequireESOrExt<3, 0, &Extensions::sRGB>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGB9_E5, true, 9, 9, 9, 0, 5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT, false, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+ AddRGBAFormat(&map, GL_R8I, true, 8, 0, 0, 0, 0, GL_RED_INTEGER, GL_BYTE, GL_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_R8UI, true, 8, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_R16I, true, 16, 0, 0, 0, 0, GL_RED_INTEGER, GL_SHORT, GL_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_R16UI, true, 16, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_R32I, true, 32, 0, 0, 0, 0, GL_RED_INTEGER, GL_INT, GL_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_R32UI, true, 32, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RG8I, true, 8, 8, 0, 0, 0, GL_RG_INTEGER, GL_BYTE, GL_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RG8UI, true, 8, 8, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RG16I, true, 16, 16, 0, 0, 0, GL_RG_INTEGER, GL_SHORT, GL_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RG16UI, true, 16, 16, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RG32I, true, 32, 32, 0, 0, 0, GL_RG_INTEGER, GL_INT, GL_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_R11F_G11F_B10F, true, 11, 11, 10, 0, 0, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_FLOAT, false, RequireES<3, 0>, RequireExt<&Extensions::colorBufferFloat>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RG32UI, true, 32, 32, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB8I, true, 8, 8, 8, 0, 0, GL_RGB_INTEGER, GL_BYTE, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB8UI, true, 8, 8, 8, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB16I, true, 16, 16, 16, 0, 0, GL_RGB_INTEGER, GL_SHORT, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB16UI, true, 16, 16, 16, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB32I, true, 32, 32, 32, 0, 0, GL_RGB_INTEGER, GL_INT, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB32UI, true, 32, 32, 32, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA8I, true, 8, 8, 8, 8, 0, GL_RGBA_INTEGER, GL_BYTE, GL_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA8UI, true, 8, 8, 8, 8, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA16I, true, 16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_SHORT, GL_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA16UI, true, 16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA32I, true, 32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_INT, GL_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA32UI, true, 32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+
+ AddRGBAFormat(&map, GL_BGRA8_EXT, true, 8, 8, 8, 8, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_BGRA4_ANGLEX, true, 4, 4, 4, 4, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_BGR5_A1_ANGLEX, true, 5, 5, 5, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported);
+
+ // Special format which is not really supported, so always false for all supports.
+ AddRGBAFormat(&map, GL_BGR565_ANGLEX, true, 5, 6, 5, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_NORMALIZED, false, NeverSupported, NeverSupported, NeverSupported);
// Floating point renderability and filtering is provided by OES_texture_float and OES_texture_half_float
- // | Internal format | | D |S | Format | Type | Comp | SRGB | Texture supported | Renderable | Filterable |
- // | | | | | | | type | | | | |
- map.insert(InternalFormatInfoPair(GL_R16F, RGBAFormat(16, 0, 0, 0, 0, GL_RED, GL_HALF_FLOAT, GL_FLOAT, false, HalfFloatSupportRG, HalfFloatRenderableSupportRG, RequireExt<&Extensions::textureHalfFloatLinear>)));
- map.insert(InternalFormatInfoPair(GL_RG16F, RGBAFormat(16, 16, 0, 0, 0, GL_RG, GL_HALF_FLOAT, GL_FLOAT, false, HalfFloatSupportRG, HalfFloatRenderableSupportRG, RequireExt<&Extensions::textureHalfFloatLinear>)));
- map.insert(InternalFormatInfoPair(GL_RGB16F, RGBAFormat(16, 16, 16, 0, 0, GL_RGB, GL_HALF_FLOAT, GL_FLOAT, false, HalfFloatSupport, HalfFloatRenderableSupport, RequireExt<&Extensions::textureHalfFloatLinear>)));
- map.insert(InternalFormatInfoPair(GL_RGBA16F, RGBAFormat(16, 16, 16, 16, 0, GL_RGBA, GL_HALF_FLOAT, GL_FLOAT, false, HalfFloatSupport, HalfFloatRenderableSupport, RequireExt<&Extensions::textureHalfFloatLinear>)));
- map.insert(InternalFormatInfoPair(GL_R32F, RGBAFormat(32, 0, 0, 0, 0, GL_RED, GL_FLOAT, GL_FLOAT, false, FloatSupportRG, FloatRenderableSupportRG, RequireExt<&Extensions::textureFloatLinear> )));
- map.insert(InternalFormatInfoPair(GL_RG32F, RGBAFormat(32, 32, 0, 0, 0, GL_RG, GL_FLOAT, GL_FLOAT, false, FloatSupportRG, FloatRenderableSupportRG, RequireExt<&Extensions::textureFloatLinear> )));
- map.insert(InternalFormatInfoPair(GL_RGB32F, RGBAFormat(32, 32, 32, 0, 0, GL_RGB, GL_FLOAT, GL_FLOAT, false, FloatSupport, FloatRenderableSupport, RequireExt<&Extensions::textureFloatLinear> )));
- map.insert(InternalFormatInfoPair(GL_RGBA32F, RGBAFormat(32, 32, 32, 32, 0, GL_RGBA, GL_FLOAT, GL_FLOAT, false, FloatSupport, FloatRenderableSupport, RequireExt<&Extensions::textureFloatLinear> )));
+ // | Internal format |sized| D |S | Format | Type | Comp | SRGB | Texture supported | Renderable | Filterable |
+ // | | | | | | | type | | | | |
+ AddRGBAFormat(&map, GL_R16F, true, 16, 0, 0, 0, 0, GL_RED, GL_HALF_FLOAT, GL_FLOAT, false, HalfFloatRGSupport, HalfFloatRGRenderableSupport, RequireESOrExt<3, 0, &Extensions::textureHalfFloatLinear>);
+ AddRGBAFormat(&map, GL_RG16F, true, 16, 16, 0, 0, 0, GL_RG, GL_HALF_FLOAT, GL_FLOAT, false, HalfFloatRGSupport, HalfFloatRGRenderableSupport, RequireESOrExt<3, 0, &Extensions::textureHalfFloatLinear>);
+ AddRGBAFormat(&map, GL_RGB16F, true, 16, 16, 16, 0, 0, GL_RGB, GL_HALF_FLOAT, GL_FLOAT, false, HalfFloatSupport, HalfFloatRGBRenderableSupport, RequireESOrExt<3, 0, &Extensions::textureHalfFloatLinear>);
+ AddRGBAFormat(&map, GL_RGBA16F, true, 16, 16, 16, 16, 0, GL_RGBA, GL_HALF_FLOAT, GL_FLOAT, false, HalfFloatSupport, HalfFloatRGBARenderableSupport, RequireESOrExt<3, 0, &Extensions::textureHalfFloatLinear>);
+ AddRGBAFormat(&map, GL_R32F, true, 32, 0, 0, 0, 0, GL_RED, GL_FLOAT, GL_FLOAT, false, FloatRGSupport, FloatRGRenderableSupport, RequireExt<&Extensions::textureFloatLinear> );
+ AddRGBAFormat(&map, GL_RG32F, true, 32, 32, 0, 0, 0, GL_RG, GL_FLOAT, GL_FLOAT, false, FloatRGSupport, FloatRGRenderableSupport, RequireExt<&Extensions::textureFloatLinear> );
+ AddRGBAFormat(&map, GL_RGB32F, true, 32, 32, 32, 0, 0, GL_RGB, GL_FLOAT, GL_FLOAT, false, FloatSupport, FloatRGBRenderableSupport, RequireExt<&Extensions::textureFloatLinear> );
+ AddRGBAFormat(&map, GL_RGBA32F, true, 32, 32, 32, 32, 0, GL_RGBA, GL_FLOAT, GL_FLOAT, false, FloatSupport, FloatRGBARenderableSupport, RequireExt<&Extensions::textureFloatLinear> );
// Depth stencil formats
- // | Internal format | | D |S | X | Format | Type | Component type | Supported | Renderable | Filterable |
- map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT16, DepthStencilFormat(16, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, RequireES<2>, RequireES<2>, RequireESOrExt<3, &Extensions::depthTextures>)));
- map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT24, DepthStencilFormat(24, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireES<3>, RequireES<3>, RequireESOrExt<3, &Extensions::depthTextures>)));
- map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32F, DepthStencilFormat(32, 0, 0, GL_DEPTH_COMPONENT, GL_FLOAT, GL_FLOAT, RequireES<3>, RequireES<3>, RequireESOrExt<3, &Extensions::depthTextures>)));
- map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32_OES, DepthStencilFormat(32, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireExtOrExt<&Extensions::depthTextures, &Extensions::depth32>, RequireExtOrExt<&Extensions::depthTextures, &Extensions::depth32>, AlwaysSupported )));
- map.insert(InternalFormatInfoPair(GL_DEPTH24_STENCIL8, DepthStencilFormat(24, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_UNSIGNED_NORMALIZED, RequireESOrExt<3, &Extensions::depthTextures>, RequireESOrExtOrExt<3, &Extensions::depthTextures, &Extensions::packedDepthStencil>, AlwaysSupported )));
- map.insert(InternalFormatInfoPair(GL_DEPTH32F_STENCIL8, DepthStencilFormat(32, 8, 24, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT, RequireES<3>, RequireES<3>, AlwaysSupported )));
+ // | Internal format |sized| D |S | X | Format | Type | Component type | Supported | Renderable | Filterable |
+ AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT16, true, 16, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, RequireES<2, 0>, RequireES<2, 0>, RequireESOrExt<3, 0, &Extensions::depthTextures>);
+ AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT24, true, 24, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireES<3, 0>, RequireES<3, 0>, RequireESOrExt<3, 0, &Extensions::depthTextures>);
+ AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT32F, true, 32, 0, 0, GL_DEPTH_COMPONENT, GL_FLOAT, GL_FLOAT, RequireES<3, 0>, RequireES<3, 0>, RequireESOrExt<3, 0, &Extensions::depthTextures>);
+ AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT32_OES, true, 32, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireExtOrExt<&Extensions::depthTextures, &Extensions::depth32>, RequireExtOrExt<&Extensions::depthTextures, &Extensions::depth32>, AlwaysSupported );
+ AddDepthStencilFormat(&map, GL_DEPTH24_STENCIL8, true, 24, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_UNSIGNED_NORMALIZED, RequireESOrExt<3, 0, &Extensions::depthTextures>, RequireESOrExtOrExt<3, 0, &Extensions::depthTextures, &Extensions::packedDepthStencil>, AlwaysSupported );
+ AddDepthStencilFormat(&map, GL_DEPTH32F_STENCIL8, true, 32, 8, 24, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT, RequireES<3, 0>, RequireES<3, 0>, AlwaysSupported );
// STENCIL_INDEX8 is special-cased, see around the bottom of the list.
// Luminance alpha formats
- // | Internal format | | L | A | Format | Type | Component type | Supported | Renderable | Filterable |
- map.insert(InternalFormatInfoPair(GL_ALPHA8_EXT, LUMAFormat( 0, 8, GL_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::textureStorage>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_LUMINANCE8_EXT, LUMAFormat( 8, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::textureStorage>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_ALPHA32F_EXT, LUMAFormat( 0, 32, GL_ALPHA, GL_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureFloat>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_LUMINANCE32F_EXT, LUMAFormat(32, 0, GL_LUMINANCE, GL_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureFloat>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_ALPHA16F_EXT, LUMAFormat( 0, 16, GL_ALPHA, GL_HALF_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_LUMINANCE16F_EXT, LUMAFormat(16, 0, GL_LUMINANCE, GL_HALF_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_LUMINANCE8_ALPHA8_EXT, LUMAFormat( 8, 8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::textureStorage>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA32F_EXT, LUMAFormat(32, 32, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureFloat>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA16F_EXT, LUMAFormat(16, 16, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported)));
-
- // Unsized formats
- // | Internal format | | Format | Supported | Renderable | Filterable |
- map.insert(InternalFormatInfoPair(GL_ALPHA, UnsizedFormat(GL_ALPHA, RequireES<2>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_LUMINANCE, UnsizedFormat(GL_LUMINANCE, RequireES<2>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA, UnsizedFormat(GL_LUMINANCE_ALPHA, RequireES<2>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_RED, UnsizedFormat(GL_RED, RequireESOrExt<3, &Extensions::textureRG>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_RG, UnsizedFormat(GL_RG, RequireESOrExt<3, &Extensions::textureRG>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_RGB, UnsizedFormat(GL_RGB, RequireES<2>, RequireES<2>, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_RGBA, UnsizedFormat(GL_RGBA, RequireES<2>, RequireES<2>, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_RED_INTEGER, UnsizedFormat(GL_RED_INTEGER, RequireES<3>, NeverSupported, NeverSupported )));
- map.insert(InternalFormatInfoPair(GL_RG_INTEGER, UnsizedFormat(GL_RG_INTEGER, RequireES<3>, NeverSupported, NeverSupported )));
- map.insert(InternalFormatInfoPair(GL_RGB_INTEGER, UnsizedFormat(GL_RGB_INTEGER, RequireES<3>, NeverSupported, NeverSupported )));
- map.insert(InternalFormatInfoPair(GL_RGBA_INTEGER, UnsizedFormat(GL_RGBA_INTEGER, RequireES<3>, NeverSupported, NeverSupported )));
- map.insert(InternalFormatInfoPair(GL_BGRA_EXT, UnsizedFormat(GL_BGRA_EXT, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT, UnsizedFormat(GL_DEPTH_COMPONENT, RequireES<2>, RequireES<2>, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_DEPTH_STENCIL, UnsizedFormat(GL_DEPTH_STENCIL, RequireESOrExt<3, &Extensions::packedDepthStencil>, RequireESOrExt<3, &Extensions::packedDepthStencil>, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_SRGB_EXT, UnsizedFormat(GL_RGB, RequireESOrExt<3, &Extensions::sRGB>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_SRGB_ALPHA_EXT, UnsizedFormat(GL_RGBA, RequireESOrExt<3, &Extensions::sRGB>, RequireESOrExt<3, &Extensions::sRGB>, AlwaysSupported)));
+ // | Internal format |sized| L | A | Format | Type | Component type | Supported | Renderable | Filterable |
+ AddLUMAFormat(&map, GL_ALPHA8_EXT, true, 0, 8, GL_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::textureStorage>, NeverSupported, AlwaysSupported);
+ AddLUMAFormat(&map, GL_LUMINANCE8_EXT, true, 8, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::textureStorage>, NeverSupported, AlwaysSupported);
+ AddLUMAFormat(&map, GL_LUMINANCE8_ALPHA8_EXT, true, 8, 8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::textureStorage>, NeverSupported, AlwaysSupported);
+ AddLUMAFormat(&map, GL_ALPHA16F_EXT, true, 0, 16, GL_ALPHA, GL_HALF_FLOAT_OES, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, RequireESOrExt<3, 0, &Extensions::textureHalfFloatLinear>);
+ AddLUMAFormat(&map, GL_LUMINANCE16F_EXT, true, 16, 0, GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, RequireESOrExt<3, 0, &Extensions::textureHalfFloatLinear>);
+ AddLUMAFormat(&map, GL_LUMINANCE_ALPHA16F_EXT, true, 16, 16, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, RequireESOrExt<3, 0, &Extensions::textureHalfFloatLinear>);
+ AddLUMAFormat(&map, GL_ALPHA32F_EXT, true, 0, 32, GL_ALPHA, GL_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureFloat>, NeverSupported, RequireExt<&Extensions::textureFloatLinear>);
+ AddLUMAFormat(&map, GL_LUMINANCE32F_EXT, true, 32, 0, GL_LUMINANCE, GL_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureFloat>, NeverSupported, RequireExt<&Extensions::textureFloatLinear>);
+ AddLUMAFormat(&map, GL_LUMINANCE_ALPHA32F_EXT, true, 32, 32, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureFloat>, NeverSupported, RequireExt<&Extensions::textureFloatLinear>);
// Compressed formats, From ES 3.0.1 spec, table 3.16
- // | Internal format | |W |H | BS |CC| Format | Type | SRGB | Supported | Renderable | Filterable |
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_R11_EAC, CompressedFormat(4, 4, 64, 1, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, false, RequireES<3>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_SIGNED_R11_EAC, CompressedFormat(4, 4, 64, 1, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE, false, RequireES<3>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_RG11_EAC, CompressedFormat(4, 4, 128, 2, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE, false, RequireES<3>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_SIGNED_RG11_EAC, CompressedFormat(4, 4, 128, 2, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE, false, RequireES<3>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE, false, RequireES<3>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE, true, RequireES<3>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, false, RequireES<3>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, true, RequireES<3>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA8_ETC2_EAC, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE, false, RequireES<3>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE, true, RequireES<3>, NeverSupported, AlwaysSupported)));
+ // | Internal format |W |H | BS |CC| Format | Type | SRGB | Supported | Renderable | Filterable |
+ AddCompressedFormat(&map, GL_COMPRESSED_R11_EAC, 4, 4, 64, 1, GL_RED, GL_UNSIGNED_BYTE, false, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SIGNED_R11_EAC, 4, 4, 64, 1, GL_RED, GL_UNSIGNED_BYTE, false, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RG11_EAC, 4, 4, 128, 2, GL_RG, GL_UNSIGNED_BYTE, false, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SIGNED_RG11_EAC, 4, 4, 128, 2, GL_RG, GL_UNSIGNED_BYTE, false, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGB8_ETC2, 4, 4, 64, 3, GL_RGB, GL_UNSIGNED_BYTE, false, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ETC2, 4, 4, 64, 3, GL_RGB, GL_UNSIGNED_BYTE, true, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, 4, 4, 64, 3, GL_RGB, GL_UNSIGNED_BYTE, false, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 4, 4, 64, 3, GL_RGB, GL_UNSIGNED_BYTE, true, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, 4, 4, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireES<3, 0>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, 4, 4, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true, RequireES<3, 0>, NeverSupported, AlwaysSupported);
// From GL_EXT_texture_compression_dxt1
- // | Internal format | |W |H | BS |CC| Format | Type | SRGB | Supported | Renderable | Filterable |
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT1>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, CompressedFormat(4, 4, 64, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT1>, NeverSupported, AlwaysSupported)));
+ // | Internal format |W |H | BS |CC| Format | Type | SRGB | Supported | Renderable | Filterable |
+ AddCompressedFormat(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 64, 3, GL_RGB, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT1>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 64, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT1>, NeverSupported, AlwaysSupported);
// From GL_ANGLE_texture_compression_dxt3
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT5>, NeverSupported, AlwaysSupported)));
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, 4, 4, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT3>, NeverSupported, AlwaysSupported);
// From GL_ANGLE_texture_compression_dxt5
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT5>, NeverSupported, AlwaysSupported)));
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, 4, 4, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT5>, NeverSupported, AlwaysSupported);
// From GL_OES_compressed_ETC1_RGB8_texture
- map.insert(InternalFormatInfoPair(GL_ETC1_RGB8_OES, CompressedFormat(4, 4, 64, 3, GL_ETC1_RGB8_OES, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::compressedETC1RGB8Texture>, NeverSupported, AlwaysSupported)));
+ AddCompressedFormat(&map, GL_ETC1_RGB8_OES, 4, 4, 64, 3, GL_RGB, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::compressedETC1RGB8Texture>, NeverSupported, AlwaysSupported);
+
+ // From GL_EXT_texture_compression_s3tc_srgb
+ // | Internal format |W |H | BS |CC| Format | Type | SRGB | Supported | Renderable | Filterable |
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, 4, 4, 64, 3, GL_RGB, GL_UNSIGNED_BYTE, true, RequireExt<&Extensions::textureCompressionS3TCsRGB>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 4, 4, 64, 4, GL_RGBA, GL_UNSIGNED_BYTE, true, RequireExt<&Extensions::textureCompressionS3TCsRGB>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 4, 4, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true, RequireExt<&Extensions::textureCompressionS3TCsRGB>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 4, 4, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true, RequireExt<&Extensions::textureCompressionS3TCsRGB>, NeverSupported, AlwaysSupported);
// From KHR_texture_compression_astc_hdr
- // | Internal format | | W | H | BS |CC| Format | Type | SRGB | Supported | Renderable | Filterable |
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_4x4_KHR, CompressedFormat( 4, 4, 128, 4, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_5x4_KHR, CompressedFormat( 5, 4, 128, 4, GL_COMPRESSED_RGBA_ASTC_5x4_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_5x5_KHR, CompressedFormat( 5, 5, 128, 4, GL_COMPRESSED_RGBA_ASTC_5x5_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_6x5_KHR, CompressedFormat( 6, 5, 128, 4, GL_COMPRESSED_RGBA_ASTC_6x5_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_6x6_KHR, CompressedFormat( 6, 6, 128, 4, GL_COMPRESSED_RGBA_ASTC_6x6_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_8x5_KHR, CompressedFormat( 8, 5, 128, 4, GL_COMPRESSED_RGBA_ASTC_8x5_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_8x6_KHR, CompressedFormat( 8, 6, 128, 4, GL_COMPRESSED_RGBA_ASTC_8x6_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_8x8_KHR, CompressedFormat( 8, 8, 128, 4, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_10x5_KHR, CompressedFormat(10, 5, 128, 4, GL_COMPRESSED_RGBA_ASTC_10x5_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_10x6_KHR, CompressedFormat(10, 6, 128, 4, GL_COMPRESSED_RGBA_ASTC_10x6_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_10x8_KHR, CompressedFormat(10, 8, 128, 4, GL_COMPRESSED_RGBA_ASTC_10x8_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_10x10_KHR, CompressedFormat(10, 10, 128, 4, GL_COMPRESSED_RGBA_ASTC_10x10_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_12x10_KHR, CompressedFormat(12, 10, 128, 4, GL_COMPRESSED_RGBA_ASTC_12x10_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_12x12_KHR, CompressedFormat(12, 12, 128, 4, GL_COMPRESSED_RGBA_ASTC_12x12_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
-
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, CompressedFormat( 4, 4, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, CompressedFormat( 5, 4, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, CompressedFormat( 5, 5, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, CompressedFormat( 6, 5, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, CompressedFormat( 6, 6, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, CompressedFormat( 8, 5, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, CompressedFormat( 8, 6, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, CompressedFormat( 8, 8, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, CompressedFormat(10, 5, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, CompressedFormat(10, 6, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, CompressedFormat(10, 8, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, CompressedFormat(10, 10, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, CompressedFormat(12, 10, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
- map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, CompressedFormat(12, 12, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported)));
+ // | Internal format | W | H | BS |CC| Format | Type | SRGB | Supported | Renderable | Filterable |
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, 4, 4, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_5x4_KHR, 5, 4, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_5x5_KHR, 5, 5, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_6x5_KHR, 6, 5, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_6x6_KHR, 6, 6, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_8x5_KHR, 8, 5, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_8x6_KHR, 8, 6, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, 8, 8, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_10x5_KHR, 10, 5, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_10x6_KHR, 10, 6, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_10x8_KHR, 10, 8, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_10x10_KHR, 10, 10, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_12x10_KHR, 12, 10, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_12x12_KHR, 12, 12, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, 4, 4, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, 5, 4, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, 5, 5, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, 6, 5, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, 6, 6, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, 8, 5, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, 8, 6, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, 8, 8, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, 10, 5, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, 10, 6, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, 10, 8, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, 10, 10, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, 12, 10, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, 12, 12, 128, 4, GL_RGBA, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported);
// For STENCIL_INDEX8 we chose a normalized component type for the following reasons:
// - Multisampled buffer are disallowed for non-normalized integer component types and we want to support it for STENCIL_INDEX8
// - All other stencil formats (all depth-stencil) are either float or normalized
// - It affects only validation of internalformat in RenderbufferStorageMultisample.
- // | Internal format | |D |S |X | Format | Type | Component type | Supported | Renderable | Filterable |
- map.insert(InternalFormatInfoPair(GL_STENCIL_INDEX8, DepthStencilFormat(0, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireES<2>, RequireES<2>, NeverSupported)));
+ // | Internal format |sized|D |S |X | Format | Type | Component type | Supported | Renderable | Filterable |
+ AddDepthStencilFormat(&map, GL_STENCIL_INDEX8, true, 0, 8, 0, GL_STENCIL, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireES<2, 0>, RequireES<2, 0>, NeverSupported);
// From GL_ANGLE_lossy_etc_decode
- map.insert(InternalFormatInfoPair(GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, CompressedFormat(4, 4, 64, 3, GL_ETC1_RGB8_OES, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::lossyETCDecode>, NeverSupported, AlwaysSupported)));
+ // | Internal format |W |H |BS |CC| Format | Type | SRGB | Supported | Renderable | Filterable |
+ AddCompressedFormat(&map, GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, 4, 4, 64, 3, GL_RGB, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::lossyETCDecode>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE, 4, 4, 64, 3, GL_RGB, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::lossyETCDecode>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE, 4, 4, 64, 3, GL_RGB, GL_UNSIGNED_BYTE, true, RequireExt<&Extensions::lossyETCDecode>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 4, 4, 64, 3, GL_RGBA, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::lossyETCDecode>, NeverSupported, AlwaysSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 4, 4, 64, 3, GL_RGBA, GL_UNSIGNED_BYTE, true, RequireExt<&Extensions::lossyETCDecode>, NeverSupported, AlwaysSupported);
+
+ // From GL_EXT_texture_norm16
+ // | Internal format |sized| R | G | B | A |S | Format | Type | Component type | SRGB | Texture supported | Renderable | Filterable |
+ AddRGBAFormat(&map, GL_R16_EXT, true, 16, 0, 0, 0, 0, GL_RED, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16>, RequireExt<&Extensions::textureNorm16>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_R16_SNORM_EXT, true, 16, 0, 0, 0, 0, GL_RED, GL_SHORT, GL_SIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16>, NeverSupported, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RG16_EXT, true, 16, 16, 0, 0, 0, GL_RG, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16>, RequireExt<&Extensions::textureNorm16>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RG16_SNORM_EXT, true, 16, 16, 0, 0, 0, GL_RG, GL_SHORT, GL_SIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16>, NeverSupported, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGB16_EXT, true, 16, 16, 16, 0, 0, GL_RGB, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16>, NeverSupported, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGB16_SNORM_EXT, true, 16, 16, 16, 0, 0, GL_RGB, GL_SHORT, GL_SIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16>, NeverSupported, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGBA16_EXT, true, 16, 16, 16, 16, 0, GL_RGBA, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16>, RequireExt<&Extensions::textureNorm16>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGBA16_SNORM_EXT, true, 16, 16, 16, 16, 0, GL_RGBA, GL_SHORT, GL_SIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16>, NeverSupported, AlwaysSupported);
+ // Unsized formats
+ // | Internal format |sized | R | G | B | A |S | Format | Type | Component type | SRGB | Texture supported | Renderable | Filterable |
+ AddRGBAFormat(&map, GL_RED, false, 8, 0, 0, 0, 0, GL_RED, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureRG>, AlwaysSupported, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RED, false, 8, 0, 0, 0, 0, GL_RED, GL_BYTE, GL_SIGNED_NORMALIZED, false, NeverSupported, NeverSupported, NeverSupported );
+ AddRGBAFormat(&map, GL_RG, false, 8, 8, 0, 0, 0, GL_RG, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureRG>, AlwaysSupported, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RG, false, 8, 8, 0, 0, 0, GL_RG, GL_BYTE, GL_SIGNED_NORMALIZED, false, NeverSupported, NeverSupported, NeverSupported );
+ AddRGBAFormat(&map, GL_RGB, false, 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireES<2, 0>, AlwaysSupported, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGB, false, 5, 6, 5, 0, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_NORMALIZED, false, RequireES<2, 0>, RequireES<2, 0>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGB, false, 8, 8, 8, 0, 0, GL_RGB, GL_BYTE, GL_SIGNED_NORMALIZED, false, NeverSupported, NeverSupported, NeverSupported );
+ AddRGBAFormat(&map, GL_RGBA, false, 4, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_NORMALIZED, false, RequireES<2, 0>, RequireES<2, 0>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGBA, false, 5, 5, 5, 1, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_NORMALIZED, false, RequireES<2, 0>, RequireES<2, 0>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGBA, false, 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireES<2, 0>, RequireES<2, 0>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGBA, false, 10, 10, 10, 2, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_NORMALIZED, false, RequireES<2, 0>, RequireES<2, 0>, AlwaysSupported);
+ AddRGBAFormat(&map, GL_RGBA, false, 8, 8, 8, 8, 0, GL_RGBA, GL_BYTE, GL_SIGNED_NORMALIZED, false, NeverSupported, NeverSupported, NeverSupported );
+ AddRGBAFormat(&map, GL_SRGB, false, 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireExt<&Extensions::sRGB>, NeverSupported, AlwaysSupported);
+ AddRGBAFormat(&map, GL_SRGB_ALPHA_EXT, false, 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireExt<&Extensions::sRGB>, RequireExt<&Extensions::sRGB>, AlwaysSupported);
+
+ AddRGBAFormat(&map, GL_BGRA_EXT, false, 8, 8, 8, 8, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported);
+
+ // Unsized integer formats
+ // |Internal format |sized | R | G | B | A |S | Format | Type | Component type | SRGB | Texture | Renderable | Filterable |
+ AddRGBAFormat(&map, GL_RED_INTEGER, false, 8, 0, 0, 0, 0, GL_RED_INTEGER, GL_BYTE, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RED_INTEGER, false, 8, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RED_INTEGER, false, 16, 0, 0, 0, 0, GL_RED_INTEGER, GL_SHORT, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RED_INTEGER, false, 16, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RED_INTEGER, false, 32, 0, 0, 0, 0, GL_RED_INTEGER, GL_INT, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RED_INTEGER, false, 32, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RG_INTEGER, false, 8, 8, 0, 0, 0, GL_RG_INTEGER, GL_BYTE, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RG_INTEGER, false, 8, 8, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RG_INTEGER, false, 16, 16, 0, 0, 0, GL_RG_INTEGER, GL_SHORT, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RG_INTEGER, false, 16, 16, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RG_INTEGER, false, 32, 32, 0, 0, 0, GL_RG_INTEGER, GL_INT, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RG_INTEGER, false, 32, 32, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB_INTEGER, false, 8, 8, 8, 0, 0, GL_RGB_INTEGER, GL_BYTE, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB_INTEGER, false, 8, 8, 8, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB_INTEGER, false, 16, 16, 16, 0, 0, GL_RGB_INTEGER, GL_SHORT, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB_INTEGER, false, 16, 16, 16, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB_INTEGER, false, 32, 32, 32, 0, 0, GL_RGB_INTEGER, GL_INT, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB_INTEGER, false, 32, 32, 32, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA_INTEGER, false, 8, 8, 8, 8, 0, GL_RGBA_INTEGER, GL_BYTE, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA_INTEGER, false, 8, 8, 8, 8, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA_INTEGER, false, 16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_SHORT, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA_INTEGER, false, 16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA_INTEGER, false, 32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_INT, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA_INTEGER, false, 32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA_INTEGER, false, 10, 10, 10, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported);
+
+ // Unsized floating point formats
+ // |Internal format |sized | R | G | B | A |S | Format | Type | Comp | SRGB | Texture supported | Renderable | Filterable |
+ AddRGBAFormat(&map, GL_RED, false, 16, 0, 0, 0, 0, GL_RED, GL_HALF_FLOAT, GL_FLOAT, false, NeverSupported, NeverSupported, NeverSupported );
+ AddRGBAFormat(&map, GL_RG, false, 16, 16, 0, 0, 0, GL_RG, GL_HALF_FLOAT, GL_FLOAT, false, NeverSupported, NeverSupported, NeverSupported );
+ AddRGBAFormat(&map, GL_RGB, false, 16, 16, 16, 0, 0, GL_RGB, GL_HALF_FLOAT, GL_FLOAT, false, NeverSupported, NeverSupported, NeverSupported );
+ AddRGBAFormat(&map, GL_RGBA, false, 16, 16, 16, 16, 0, GL_RGBA, GL_HALF_FLOAT, GL_FLOAT, false, NeverSupported, NeverSupported, NeverSupported );
+ AddRGBAFormat(&map, GL_RED, false, 16, 0, 0, 0, 0, GL_RED, GL_HALF_FLOAT_OES, GL_FLOAT, false, UnsizedHalfFloatOESRGSupport, UnsizedHalfFloatOESRGRenderableSupport, RequireESOrExt<3, 0, &Extensions::textureHalfFloatLinear>);
+ AddRGBAFormat(&map, GL_RG, false, 16, 16, 0, 0, 0, GL_RG, GL_HALF_FLOAT_OES, GL_FLOAT, false, UnsizedHalfFloatOESRGSupport, UnsizedHalfFloatOESRGRenderableSupport, RequireESOrExt<3, 0, &Extensions::textureHalfFloatLinear>);
+ AddRGBAFormat(&map, GL_RGB, false, 16, 16, 16, 0, 0, GL_RGB, GL_HALF_FLOAT_OES, GL_FLOAT, false, UnsizedHalfFloatOESSupport, UnsizedHalfFloatOESRenderableSupport, RequireESOrExt<3, 0, &Extensions::textureHalfFloatLinear>);
+ AddRGBAFormat(&map, GL_RGBA, false, 16, 16, 16, 16, 0, GL_RGBA, GL_HALF_FLOAT_OES, GL_FLOAT, false, UnsizedHalfFloatOESSupport, UnsizedHalfFloatOESRenderableSupport, RequireESOrExt<3, 0, &Extensions::textureHalfFloatLinear>);
+ AddRGBAFormat(&map, GL_RED, false, 32, 0, 0, 0, 0, GL_RED, GL_FLOAT, GL_FLOAT, false, UnsizedFloatRGSupport, UnsizedFloatRGRenderableSupport, RequireExt<&Extensions::textureFloatLinear> );
+ AddRGBAFormat(&map, GL_RG, false, 32, 32, 0, 0, 0, GL_RG, GL_FLOAT, GL_FLOAT, false, UnsizedFloatRGSupport, UnsizedFloatRGRenderableSupport, RequireExt<&Extensions::textureFloatLinear> );
+ AddRGBAFormat(&map, GL_RGB, false, 32, 32, 32, 0, 0, GL_RGB, GL_FLOAT, GL_FLOAT, false, UnsizedFloatSupport, UnsizedFloatRGBRenderableSupport, RequireExt<&Extensions::textureFloatLinear> );
+ AddRGBAFormat(&map, GL_RGB, false, 9, 9, 9, 0, 5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT, false, NeverSupported, NeverSupported, NeverSupported );
+ AddRGBAFormat(&map, GL_RGB, false, 11, 11, 10, 0, 0, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_FLOAT, false, NeverSupported, NeverSupported, NeverSupported );
+ AddRGBAFormat(&map, GL_RGBA, false, 32, 32, 32, 32, 0, GL_RGBA, GL_FLOAT, GL_FLOAT, false, UnsizedFloatSupport, UnsizedFloatRGBARenderableSupport, RequireExt<&Extensions::textureFloatLinear> );
+
+ // Unsized luminance alpha formats
+ // | Internal format |sized | L | A | Format | Type | Component type | Supported | Renderable | Filterable |
+ AddLUMAFormat(&map, GL_ALPHA, false, 0, 8, GL_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireES<2, 0>, NeverSupported, AlwaysSupported );
+ AddLUMAFormat(&map, GL_LUMINANCE, false, 8, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireES<2, 0>, NeverSupported, AlwaysSupported );
+ AddLUMAFormat(&map, GL_LUMINANCE_ALPHA, false, 8, 8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireES<2, 0>, NeverSupported, AlwaysSupported );
+ AddLUMAFormat(&map, GL_ALPHA, false, 0, 16, GL_ALPHA, GL_HALF_FLOAT_OES, GL_FLOAT, RequireExt<&Extensions::textureHalfFloat>, NeverSupported, RequireExt<&Extensions::textureHalfFloatLinear>);
+ AddLUMAFormat(&map, GL_LUMINANCE, false, 16, 0, GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_FLOAT, RequireExt<&Extensions::textureHalfFloat>, NeverSupported, RequireExt<&Extensions::textureHalfFloatLinear>);
+ AddLUMAFormat(&map, GL_LUMINANCE_ALPHA ,false, 16, 16, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_FLOAT, RequireExt<&Extensions::textureHalfFloat>, NeverSupported, RequireExt<&Extensions::textureHalfFloatLinear>);
+ AddLUMAFormat(&map, GL_ALPHA, false, 0, 32, GL_ALPHA, GL_FLOAT, GL_FLOAT, RequireExt<&Extensions::textureFloat>, NeverSupported, RequireExt<&Extensions::textureFloatLinear> );
+ AddLUMAFormat(&map, GL_LUMINANCE, false, 32, 0, GL_LUMINANCE, GL_FLOAT, GL_FLOAT, RequireExt<&Extensions::textureFloat>, NeverSupported, RequireExt<&Extensions::textureFloatLinear> );
+ AddLUMAFormat(&map, GL_LUMINANCE_ALPHA, false, 32, 32, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_FLOAT, RequireExt<&Extensions::textureFloat>, NeverSupported, RequireExt<&Extensions::textureFloatLinear> );
+
+ // Unsized depth stencil formats
+ // | Internal format |sized | D |S | X | Format | Type | Component type | Supported | Renderable | Filterable |
+ AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT, false, 16, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, RequireES<2, 0>, RequireES<2, 0>, AlwaysSupported);
+ AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT, false, 24, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireES<2, 0>, RequireES<2, 0>, AlwaysSupported);
+ AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT, false, 32, 0, 0, GL_DEPTH_COMPONENT, GL_FLOAT, GL_FLOAT, RequireES<2, 0>, RequireES<2, 0>, AlwaysSupported);
+ AddDepthStencilFormat(&map, GL_DEPTH_STENCIL, false, 24, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_UNSIGNED_NORMALIZED, RequireESOrExt<3, 0, &Extensions::packedDepthStencil>, RequireESOrExt<3, 0, &Extensions::packedDepthStencil>, AlwaysSupported);
+ AddDepthStencilFormat(&map, GL_DEPTH_STENCIL, false, 32, 8, 24, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT, RequireESOrExt<3, 0, &Extensions::packedDepthStencil>, RequireESOrExt<3, 0, &Extensions::packedDepthStencil>, AlwaysSupported);
+ AddDepthStencilFormat(&map, GL_STENCIL, false, 0, 8, 0, GL_STENCIL, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireES<2, 0>, RequireES<2, 0>, NeverSupported);
// clang-format on
return map;
@@ -584,12 +940,18 @@ static FormatSet BuildAllSizedInternalFormatSet()
{
FormatSet result;
- const InternalFormatInfoMap &formats = GetInternalFormatMap();
- for (InternalFormatInfoMap::const_iterator i = formats.begin(); i != formats.end(); i++)
+ for (const auto &internalFormat : GetInternalFormatMap())
{
- if (i->second.pixelBytes > 0)
+ for (const auto &type : internalFormat.second)
{
- result.insert(i->first);
+ if (type.second.sized)
+ {
+ // TODO(jmadill): Fix this hack.
+ if (internalFormat.first == GL_BGR565_ANGLEX)
+ continue;
+
+ result.insert(internalFormat.first);
+ }
}
}
@@ -652,107 +1014,199 @@ const Type &GetTypeInfo(GLenum type)
}
}
-const InternalFormat GetInternalFormatInfo(GLenum internalFormat)
+const InternalFormat &GetSizedInternalFormatInfo(GLenum internalFormat)
{
+ static const InternalFormat defaultInternalFormat;
const InternalFormatInfoMap &formatMap = GetInternalFormatMap();
- InternalFormatInfoMap::const_iterator iter = formatMap.find(internalFormat);
- if (iter != formatMap.end())
+ auto iter = formatMap.find(internalFormat);
+
+ // Sized internal formats only have one type per entry
+ if (iter == formatMap.end() || iter->second.size() != 1)
{
- return iter->second;
+ return defaultInternalFormat;
}
- else
+
+ const InternalFormat &internalFormatInfo = iter->second.begin()->second;
+ if (!internalFormatInfo.sized)
{
- static const InternalFormat defaultInternalFormat;
return defaultInternalFormat;
}
+
+ return internalFormatInfo;
}
-GLuint InternalFormat::computeRowPitch(GLenum formatType, GLsizei width, GLint alignment, GLint rowLength) const
+const InternalFormat &GetInternalFormatInfo(GLenum internalFormat, GLenum type)
{
- ASSERT(alignment > 0 && isPow2(alignment));
- GLuint rowBytes;
- if (rowLength > 0)
+ static const InternalFormat defaultInternalFormat;
+ const InternalFormatInfoMap &formatMap = GetInternalFormatMap();
+
+ auto internalFormatIter = formatMap.find(internalFormat);
+ if (internalFormatIter == formatMap.end())
{
- ASSERT(!compressed);
- rowBytes = pixelBytes * rowLength;
+ return defaultInternalFormat;
}
- else
+
+ // If the internal format is sized, simply return it without the type check.
+ if (internalFormatIter->second.size() == 1 && internalFormatIter->second.begin()->second.sized)
{
- rowBytes = computeBlockSize(formatType, width, 1);
+ return internalFormatIter->second.begin()->second;
}
- return rx::roundUp(rowBytes, static_cast<GLuint>(alignment));
+
+ auto typeIter = internalFormatIter->second.find(type);
+ if (typeIter == internalFormatIter->second.end())
+ {
+ return defaultInternalFormat;
+ }
+
+ return typeIter->second;
+}
+
+GLuint InternalFormat::computePixelBytes(GLenum formatType) const
+{
+ const auto &typeInfo = GetTypeInfo(formatType);
+ GLuint components = typeInfo.specialInterpretation ? 1u : componentCount;
+ return components * typeInfo.bytes;
}
-GLuint InternalFormat::computeDepthPitch(GLenum formatType,
- GLsizei width,
- GLsizei height,
- GLint alignment,
- GLint rowLength,
- GLint imageHeight) const
+ErrorOrResult<GLuint> InternalFormat::computeRowPitch(GLenum formatType,
+ GLsizei width,
+ GLint alignment,
+ GLint rowLength) const
{
- GLuint rows;
- if (imageHeight > 0)
+ // Compressed images do not use pack/unpack parameters.
+ if (compressed)
{
- rows = imageHeight;
+ ASSERT(rowLength == 0);
+ return computeCompressedImageSize(Extents(width, 1, 1));
}
- else
+
+ CheckedNumeric<GLuint> checkedWidth(rowLength > 0 ? rowLength : width);
+ CheckedNumeric<GLuint> checkedRowBytes = checkedWidth * computePixelBytes(formatType);
+
+ ASSERT(alignment > 0 && isPow2(alignment));
+ CheckedNumeric<GLuint> checkedAlignment(alignment);
+ auto aligned = rx::roundUp(checkedRowBytes, checkedAlignment);
+ ANGLE_TRY_CHECKED_MATH(aligned);
+ return aligned.ValueOrDie();
+}
+
+ErrorOrResult<GLuint> InternalFormat::computeDepthPitch(GLsizei height,
+ GLint imageHeight,
+ GLuint rowPitch) const
+{
+ GLuint rows =
+ (imageHeight > 0 ? static_cast<GLuint>(imageHeight) : static_cast<GLuint>(height));
+ CheckedNumeric<GLuint> checkedRowPitch(rowPitch);
+
+ auto depthPitch = checkedRowPitch * rows;
+ ANGLE_TRY_CHECKED_MATH(depthPitch);
+ return depthPitch.ValueOrDie();
+}
+
+ErrorOrResult<GLuint> InternalFormat::computeDepthPitch(GLenum formatType,
+ GLsizei width,
+ GLsizei height,
+ GLint alignment,
+ GLint rowLength,
+ GLint imageHeight) const
+{
+ GLuint rowPitch = 0;
+ ANGLE_TRY_RESULT(computeRowPitch(formatType, width, alignment, rowLength), rowPitch);
+ return computeDepthPitch(height, imageHeight, rowPitch);
+}
+
+ErrorOrResult<GLuint> InternalFormat::computeCompressedImageSize(const Extents &size) const
+{
+ CheckedNumeric<GLuint> checkedWidth(size.width);
+ CheckedNumeric<GLuint> checkedHeight(size.height);
+ CheckedNumeric<GLuint> checkedDepth(size.depth);
+ CheckedNumeric<GLuint> checkedBlockWidth(compressedBlockWidth);
+ CheckedNumeric<GLuint> checkedBlockHeight(compressedBlockHeight);
+
+ ASSERT(compressed);
+ auto numBlocksWide = (checkedWidth + checkedBlockWidth - 1u) / checkedBlockWidth;
+ auto numBlocksHigh = (checkedHeight + checkedBlockHeight - 1u) / checkedBlockHeight;
+ auto bytes = numBlocksWide * numBlocksHigh * pixelBytes * checkedDepth;
+ ANGLE_TRY_CHECKED_MATH(bytes);
+ return bytes.ValueOrDie();
+}
+
+ErrorOrResult<GLuint> InternalFormat::computeSkipBytes(GLuint rowPitch,
+ GLuint depthPitch,
+ const PixelStoreStateBase &state,
+ bool is3D) const
+{
+ CheckedNumeric<GLuint> checkedRowPitch(rowPitch);
+ CheckedNumeric<GLuint> checkedDepthPitch(depthPitch);
+ CheckedNumeric<GLuint> checkedSkipImages(static_cast<GLuint>(state.skipImages));
+ CheckedNumeric<GLuint> checkedSkipRows(static_cast<GLuint>(state.skipRows));
+ CheckedNumeric<GLuint> checkedSkipPixels(static_cast<GLuint>(state.skipPixels));
+ CheckedNumeric<GLuint> checkedPixelBytes(pixelBytes);
+ auto checkedSkipImagesBytes = checkedSkipImages * checkedDepthPitch;
+ if (!is3D)
{
- rows = height;
+ checkedSkipImagesBytes = 0;
}
- return computeRowPitch(formatType, width, alignment, rowLength) * rows;
+ auto skipBytes = checkedSkipImagesBytes + checkedSkipRows * checkedRowPitch +
+ checkedSkipPixels * checkedPixelBytes;
+ ANGLE_TRY_CHECKED_MATH(skipBytes);
+ return skipBytes.ValueOrDie();
}
-GLuint InternalFormat::computeBlockSize(GLenum formatType, GLsizei width, GLsizei height) const
+ErrorOrResult<GLuint> InternalFormat::computePackUnpackEndByte(
+ GLenum formatType,
+ const Extents &size,
+ const PixelStoreStateBase &state,
+ bool is3D) const
{
+ GLuint rowPitch = 0;
+ ANGLE_TRY_RESULT(computeRowPitch(formatType, size.width, state.alignment, state.rowLength),
+ rowPitch);
+
+ GLuint depthPitch = 0;
+ if (is3D)
+ {
+ ANGLE_TRY_RESULT(computeDepthPitch(size.height, state.imageHeight, rowPitch), depthPitch);
+ }
+
+ CheckedNumeric<GLuint> checkedCopyBytes = 0;
if (compressed)
{
- GLsizei numBlocksWide = (width + compressedBlockWidth - 1) / compressedBlockWidth;
- GLsizei numBlocksHight = (height + compressedBlockHeight - 1) / compressedBlockHeight;
- return (pixelBytes * numBlocksWide * numBlocksHight);
+ ANGLE_TRY_RESULT(computeCompressedImageSize(size), checkedCopyBytes);
}
- else
+ else if (size.height != 0 && (!is3D || size.depth != 0))
{
- const Type &typeInfo = GetTypeInfo(formatType);
- if (typeInfo.specialInterpretation)
- {
- return typeInfo.bytes * width * height;
- }
- else
+ CheckedNumeric<GLuint> bytes = computePixelBytes(formatType);
+ checkedCopyBytes += size.width * bytes;
+
+ CheckedNumeric<GLuint> heightMinusOne = size.height - 1;
+ checkedCopyBytes += heightMinusOne * rowPitch;
+
+ if (is3D)
{
- return componentCount * typeInfo.bytes * width * height;
+ CheckedNumeric<GLuint> depthMinusOne = size.depth - 1;
+ checkedCopyBytes += depthMinusOne * depthPitch;
}
}
-}
-GLuint InternalFormat::computeSkipPixels(GLint rowPitch,
- GLint depthPitch,
- GLint skipImages,
- GLint skipRows,
- GLint skipPixels) const
-{
- return skipImages * depthPitch + skipRows * rowPitch + skipPixels * pixelBytes;
+ CheckedNumeric<GLuint> checkedSkipBytes = 0;
+ ANGLE_TRY_RESULT(computeSkipBytes(rowPitch, depthPitch, state, is3D), checkedSkipBytes);
+
+ CheckedNumeric<GLuint> endByte = checkedCopyBytes + checkedSkipBytes;
+
+ ANGLE_TRY_CHECKED_MATH(endByte);
+ return endByte.ValueOrDie();
}
-GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type)
+GLenum GetUnsizedFormat(GLenum internalFormat)
{
- const InternalFormat& formatInfo = GetInternalFormatInfo(internalFormat);
- if (formatInfo.pixelBytes > 0)
+ auto sizedFormatInfo = GetSizedInternalFormatInfo(internalFormat);
+ if (sizedFormatInfo.internalFormat != GL_NONE)
{
- return internalFormat;
- }
- else
- {
- static const FormatMap formatMap = BuildFormatMap();
- FormatMap::const_iterator iter = formatMap.find(FormatTypePair(internalFormat, type));
- if (iter != formatMap.end())
- {
- return iter->second;
- }
- else
- {
- return GL_NONE;
- }
+ return sizedFormatInfo.format;
}
+
+ return internalFormat;
}
const FormatSet &GetAllSizedInternalFormats()
@@ -1543,6 +1997,129 @@ const VertexFormat &GetVertexFormatFromType(VertexFormatType vertexFormatType)
}
}
+size_t GetVertexFormatTypeSize(VertexFormatType vertexFormatType)
+{
+ switch (vertexFormatType)
+ {
+ case VERTEX_FORMAT_SBYTE1:
+ case VERTEX_FORMAT_SBYTE1_NORM:
+ case VERTEX_FORMAT_UBYTE1:
+ case VERTEX_FORMAT_UBYTE1_NORM:
+ case VERTEX_FORMAT_SBYTE1_INT:
+ case VERTEX_FORMAT_UBYTE1_INT:
+ return 1;
+
+ case VERTEX_FORMAT_SBYTE2:
+ case VERTEX_FORMAT_SBYTE2_NORM:
+ case VERTEX_FORMAT_UBYTE2:
+ case VERTEX_FORMAT_UBYTE2_NORM:
+ case VERTEX_FORMAT_SBYTE2_INT:
+ case VERTEX_FORMAT_UBYTE2_INT:
+ case VERTEX_FORMAT_SSHORT1:
+ case VERTEX_FORMAT_SSHORT1_NORM:
+ case VERTEX_FORMAT_USHORT1:
+ case VERTEX_FORMAT_USHORT1_NORM:
+ case VERTEX_FORMAT_SSHORT1_INT:
+ case VERTEX_FORMAT_USHORT1_INT:
+ case VERTEX_FORMAT_HALF1:
+ return 2;
+
+ case VERTEX_FORMAT_SBYTE3:
+ case VERTEX_FORMAT_SBYTE3_NORM:
+ case VERTEX_FORMAT_UBYTE3:
+ case VERTEX_FORMAT_UBYTE3_NORM:
+ case VERTEX_FORMAT_SBYTE3_INT:
+ case VERTEX_FORMAT_UBYTE3_INT:
+ return 3;
+
+ case VERTEX_FORMAT_SBYTE4:
+ case VERTEX_FORMAT_SBYTE4_NORM:
+ case VERTEX_FORMAT_UBYTE4:
+ case VERTEX_FORMAT_UBYTE4_NORM:
+ case VERTEX_FORMAT_SBYTE4_INT:
+ case VERTEX_FORMAT_UBYTE4_INT:
+ case VERTEX_FORMAT_SSHORT2:
+ case VERTEX_FORMAT_SSHORT2_NORM:
+ case VERTEX_FORMAT_USHORT2:
+ case VERTEX_FORMAT_USHORT2_NORM:
+ case VERTEX_FORMAT_SSHORT2_INT:
+ case VERTEX_FORMAT_USHORT2_INT:
+ case VERTEX_FORMAT_SINT1:
+ case VERTEX_FORMAT_SINT1_NORM:
+ case VERTEX_FORMAT_UINT1:
+ case VERTEX_FORMAT_UINT1_NORM:
+ case VERTEX_FORMAT_SINT1_INT:
+ case VERTEX_FORMAT_UINT1_INT:
+ case VERTEX_FORMAT_HALF2:
+ case VERTEX_FORMAT_FIXED1:
+ case VERTEX_FORMAT_FLOAT1:
+ case VERTEX_FORMAT_SINT210:
+ case VERTEX_FORMAT_UINT210:
+ case VERTEX_FORMAT_SINT210_NORM:
+ case VERTEX_FORMAT_UINT210_NORM:
+ case VERTEX_FORMAT_SINT210_INT:
+ case VERTEX_FORMAT_UINT210_INT:
+ return 4;
+
+ case VERTEX_FORMAT_SSHORT3:
+ case VERTEX_FORMAT_SSHORT3_NORM:
+ case VERTEX_FORMAT_USHORT3:
+ case VERTEX_FORMAT_USHORT3_NORM:
+ case VERTEX_FORMAT_SSHORT3_INT:
+ case VERTEX_FORMAT_USHORT3_INT:
+ case VERTEX_FORMAT_HALF3:
+ return 6;
+
+ case VERTEX_FORMAT_SSHORT4:
+ case VERTEX_FORMAT_SSHORT4_NORM:
+ case VERTEX_FORMAT_USHORT4:
+ case VERTEX_FORMAT_USHORT4_NORM:
+ case VERTEX_FORMAT_SSHORT4_INT:
+ case VERTEX_FORMAT_USHORT4_INT:
+ case VERTEX_FORMAT_SINT2:
+ case VERTEX_FORMAT_SINT2_NORM:
+ case VERTEX_FORMAT_UINT2:
+ case VERTEX_FORMAT_UINT2_NORM:
+ case VERTEX_FORMAT_SINT2_INT:
+ case VERTEX_FORMAT_UINT2_INT:
+ case VERTEX_FORMAT_HALF4:
+ case VERTEX_FORMAT_FIXED2:
+ case VERTEX_FORMAT_FLOAT2:
+ return 8;
+
+ case VERTEX_FORMAT_SINT3:
+ case VERTEX_FORMAT_SINT3_NORM:
+ case VERTEX_FORMAT_UINT3:
+ case VERTEX_FORMAT_UINT3_NORM:
+ case VERTEX_FORMAT_SINT3_INT:
+ case VERTEX_FORMAT_UINT3_INT:
+ case VERTEX_FORMAT_FIXED3:
+ case VERTEX_FORMAT_FLOAT3:
+ return 12;
+
+ case VERTEX_FORMAT_SINT4:
+ case VERTEX_FORMAT_SINT4_NORM:
+ case VERTEX_FORMAT_UINT4:
+ case VERTEX_FORMAT_UINT4_NORM:
+ case VERTEX_FORMAT_SINT4_INT:
+ case VERTEX_FORMAT_UINT4_INT:
+ case VERTEX_FORMAT_FIXED4:
+ case VERTEX_FORMAT_FLOAT4:
+ return 16;
+
+ case VERTEX_FORMAT_INVALID:
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+bool ValidES3InternalFormat(GLenum internalFormat)
+{
+ const InternalFormatInfoMap &formatMap = GetInternalFormatMap();
+ return internalFormat != GL_NONE && formatMap.find(internalFormat) != formatMap.end();
+}
+
VertexFormat::VertexFormat(GLenum typeIn, GLboolean normalizedIn, GLuint componentsIn, bool pureIntegerIn)
: type(typeIn),
normalized(normalizedIn),
diff --git a/src/3rdparty/angle/src/libANGLE/formatutils.h b/src/3rdparty/angle/src/libANGLE/formatutils.h
index 2165e6badd..dbfe590846 100644
--- a/src/3rdparty/angle/src/libANGLE/formatutils.h
+++ b/src/3rdparty/angle/src/libANGLE/formatutils.h
@@ -9,16 +9,32 @@
#ifndef LIBANGLE_FORMATUTILS_H_
#define LIBANGLE_FORMATUTILS_H_
-#include "libANGLE/Caps.h"
-#include "libANGLE/angletypes.h"
-
-#include "angle_gl.h"
-
#include <cstddef>
+#include <ostream>
#include <stdint.h>
+#include "angle_gl.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Version.h"
+#include "libANGLE/angletypes.h"
+
namespace gl
{
+struct VertexAttribute;
+
+struct FormatType final
+{
+ FormatType();
+ FormatType(GLenum format_, GLenum type_);
+ FormatType(const FormatType &other) = default;
+ FormatType &operator=(const FormatType &other) = default;
+
+ bool operator<(const FormatType &other) const;
+
+ GLenum format;
+ GLenum type;
+};
struct Type
{
@@ -30,9 +46,58 @@ struct Type
};
const Type &GetTypeInfo(GLenum type);
+// Information about an OpenGL internal format. Can be keyed on the internalFormat and type
+// members.
struct InternalFormat
{
InternalFormat();
+ InternalFormat(const InternalFormat &other);
+
+ GLuint computePixelBytes(GLenum formatType) const;
+
+ ErrorOrResult<GLuint> computeRowPitch(GLenum formatType,
+ GLsizei width,
+ GLint alignment,
+ GLint rowLength) const;
+ ErrorOrResult<GLuint> computeDepthPitch(GLsizei height,
+ GLint imageHeight,
+ GLuint rowPitch) const;
+ ErrorOrResult<GLuint> computeDepthPitch(GLenum formatType,
+ GLsizei width,
+ GLsizei height,
+ GLint alignment,
+ GLint rowLength,
+ GLint imageHeight) const;
+
+ ErrorOrResult<GLuint> computeCompressedImageSize(const Extents &size) const;
+
+ ErrorOrResult<GLuint> computeSkipBytes(GLuint rowPitch,
+ GLuint depthPitch,
+ const PixelStoreStateBase &state,
+ bool is3D) const;
+
+ ErrorOrResult<GLuint> computePackUnpackEndByte(GLenum formatType,
+ const Extents &size,
+ const PixelStoreStateBase &state,
+ bool is3D) const;
+
+ bool isLUMA() const;
+ GLenum getReadPixelsFormat() const;
+ GLenum getReadPixelsType(const Version &version) const;
+
+ // Return true if the format is a required renderbuffer format in the given version of the core
+ // spec. Note that it isn't always clear whether all the rules that apply to core required
+ // renderbuffer formats also apply to additional formats added by extensions. Because of this
+ // extension formats are conservatively not included.
+ bool isRequiredRenderbufferFormat(const Version &version) const;
+
+ bool operator==(const InternalFormat &other) const;
+ bool operator!=(const InternalFormat &other) const;
+
+ GLenum internalFormat;
+
+ bool sized;
+ GLenum sizedInternalFormat;
GLuint redBits;
GLuint greenBits;
@@ -60,28 +125,45 @@ struct InternalFormat
GLenum componentType;
GLenum colorEncoding;
- typedef bool (*SupportCheckFunction)(GLuint, const Extensions &);
+ typedef bool (*SupportCheckFunction)(const Version &, const Extensions &);
SupportCheckFunction textureSupport;
SupportCheckFunction renderSupport;
SupportCheckFunction filterSupport;
+};
+
+// A "Format" wraps an InternalFormat struct, querying it from either a sized internal format or
+// unsized internal format and type.
+// TODO(geofflang): Remove this, it doesn't add any more information than the InternalFormat object.
+struct Format
+{
+ // Sized types only.
+ explicit Format(GLenum internalFormat);
+
+ // Sized or unsized types.
+ explicit Format(const InternalFormat &internalFormat);
+ Format(GLenum internalFormat, GLenum type);
+
+ Format(const Format &other);
+ Format &operator=(const Format &other);
- GLuint computeRowPitch(GLenum formatType, GLsizei width, GLint alignment, GLint rowLength) const;
- GLuint computeDepthPitch(GLenum formatType,
- GLsizei width,
- GLsizei height,
- GLint alignment,
- GLint rowLength,
- GLint imageHeight) const;
- GLuint computeBlockSize(GLenum formatType, GLsizei width, GLsizei height) const;
- GLuint computeSkipPixels(GLint rowPitch,
- GLint depthPitch,
- GLint skipImages,
- GLint skipRows,
- GLint skipPixels) const;
+ bool valid() const;
+
+ static Format Invalid();
+ static bool SameSized(const Format &a, const Format &b);
+ static bool EquivalentForBlit(const Format &a, const Format &b);
+
+ friend std::ostream &operator<<(std::ostream &os, const Format &fmt);
+
+ // This is the sized info.
+ const InternalFormat *info;
};
-const InternalFormat GetInternalFormatInfo(GLenum internalFormat);
-GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type);
+const InternalFormat &GetSizedInternalFormatInfo(GLenum internalFormat);
+const InternalFormat &GetInternalFormatInfo(GLenum internalFormat, GLenum type);
+
+// Strip sizing information from an internal format. Doesn't necessarily validate that the internal
+// format is valid.
+GLenum GetUnsizedFormat(GLenum internalFormat);
typedef std::set<GLenum> FormatSet;
const FormatSet &GetAllSizedInternalFormats();
@@ -212,9 +294,9 @@ enum VertexFormatType
VERTEX_FORMAT_UINT210_INT,
};
-typedef std::vector<gl::VertexFormatType> InputLayout;
+typedef std::vector<VertexFormatType> InputLayout;
-struct VertexFormat : angle::NonCopyable
+struct VertexFormat : private angle::NonCopyable
{
VertexFormat(GLenum typeIn, GLboolean normalizedIn, GLuint componentsIn, bool pureIntegerIn);
@@ -228,6 +310,19 @@ VertexFormatType GetVertexFormatType(GLenum type, GLboolean normalized, GLuint c
VertexFormatType GetVertexFormatType(const VertexAttribute &attrib);
VertexFormatType GetVertexFormatType(const VertexAttribute &attrib, GLenum currentValueType);
const VertexFormat &GetVertexFormatFromType(VertexFormatType vertexFormatType);
+size_t GetVertexFormatTypeSize(VertexFormatType vertexFormatType);
+
+// Check if an internal format is ever valid in ES3. Makes no checks about support for a specific
+// context.
+bool ValidES3InternalFormat(GLenum internalFormat);
+
+// Implemented in format_map_autogen.cpp
+bool ValidES3Format(GLenum format);
+bool ValidES3Type(GLenum type);
+bool ValidES3FormatCombination(GLenum format, GLenum type, GLenum internalFormat);
+
+// Implemented in es3_copy_conversion_table_autogen.cpp
+bool ValidES3CopyConversion(GLenum textureFormat, GLenum framebufferFormat);
} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/histogram_macros.h b/src/3rdparty/angle/src/libANGLE/histogram_macros.h
index d1c952a6bd..fb428b46d2 100644
--- a/src/3rdparty/angle/src/libANGLE/histogram_macros.h
+++ b/src/3rdparty/angle/src/libANGLE/histogram_macros.h
@@ -41,18 +41,19 @@
#define ANGLE_HISTOGRAM_COUNTS_10000(name, sample) \
ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, 1, 10000, 50)
-#define ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \
- ANGLEPlatformCurrent()->histogramCustomCounts(\
- name, sample, min, max, bucket_count)
+#define ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \
+ ANGLEPlatformCurrent()->histogramCustomCounts(ANGLEPlatformCurrent(), name, sample, min, max, \
+ bucket_count)
#define ANGLE_HISTOGRAM_PERCENTAGE(name, under_one_hundred) \
ANGLE_HISTOGRAM_ENUMERATION(name, under_one_hundred, 101)
#define ANGLE_HISTOGRAM_BOOLEAN(name, sample) \
- ANGLEPlatformCurrent()->histogramBoolean(name, sample)
+ ANGLEPlatformCurrent()->histogramBoolean(ANGLEPlatformCurrent(), name, sample)
-#define ANGLE_HISTOGRAM_ENUMERATION(name, sample, boundary_value) \
- ANGLEPlatformCurrent()->histogramEnumeration(name, sample, boundary_value)
+#define ANGLE_HISTOGRAM_ENUMERATION(name, sample, boundary_value) \
+ ANGLEPlatformCurrent()->histogramEnumeration(ANGLEPlatformCurrent(), name, sample, \
+ boundary_value)
#define ANGLE_HISTOGRAM_MEMORY_KB(name, sample) ANGLE_HISTOGRAM_CUSTOM_COUNTS( \
name, sample, 1000, 500000, 50)
@@ -61,7 +62,7 @@
name, sample, 1, 1000, 50)
#define ANGLE_HISTOGRAM_SPARSE_SLOWLY(name, sample) \
- ANGLEPlatformCurrent()->histogramSparse(name, sample)
+ ANGLEPlatformCurrent()->histogramSparse(ANGLEPlatformCurrent(), name, sample)
// Scoped class which logs its time on this earth as a UMA statistic. This is
// recommended for when you want a histogram which measures the time it takes
@@ -79,29 +80,33 @@
#define SCOPED_ANGLE_HISTOGRAM_TIMER_EXPANDER(name, is_long, key) \
SCOPED_ANGLE_HISTOGRAM_TIMER_UNIQUE(name, is_long, key)
-#define SCOPED_ANGLE_HISTOGRAM_TIMER_UNIQUE(name, is_long, key) \
- class ScopedHistogramTimer##key \
- { \
- public: \
- ScopedHistogramTimer##key() : constructed_(ANGLEPlatformCurrent()->currentTime()) {} \
- ~ScopedHistogramTimer##key() \
- { \
- if (constructed_ == 0) \
- return; \
- double elapsed = ANGLEPlatformCurrent()->currentTime() - constructed_; \
- int elapsedMS = static_cast<int>(elapsed * 1000.0); \
- if (is_long) \
- { \
- ANGLE_HISTOGRAM_LONG_TIMES_100(name, elapsedMS); \
- } \
- else \
- { \
- ANGLE_HISTOGRAM_TIMES(name, elapsedMS); \
- } \
- } \
- \
- private: \
- double constructed_; \
+#define SCOPED_ANGLE_HISTOGRAM_TIMER_UNIQUE(name, is_long, key) \
+ class ScopedHistogramTimer##key \
+ { \
+ public: \
+ ScopedHistogramTimer##key() \
+ : constructed_(ANGLEPlatformCurrent()->currentTime(ANGLEPlatformCurrent())) \
+ { \
+ } \
+ ~ScopedHistogramTimer##key() \
+ { \
+ if (constructed_ == 0) \
+ return; \
+ auto *platform = ANGLEPlatformCurrent(); \
+ double elapsed = platform->currentTime(platform) - constructed_; \
+ int elapsedMS = static_cast<int>(elapsed * 1000.0); \
+ if (is_long) \
+ { \
+ ANGLE_HISTOGRAM_LONG_TIMES_100(name, elapsedMS); \
+ } \
+ else \
+ { \
+ ANGLE_HISTOGRAM_TIMES(name, elapsedMS); \
+ } \
+ } \
+ \
+ private: \
+ double constructed_; \
} scoped_histogram_timer_##key
-#endif // BASE_METRICS_HISTOGRAM_MACROS_H_
+#endif // LIBANGLE_HISTOGRAM_MACROS_H_
diff --git a/src/3rdparty/angle/src/libANGLE/packed_gl_enums.json b/src/3rdparty/angle/src/libANGLE/packed_gl_enums.json
new file mode 100644
index 0000000000..7e77de2f36
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/packed_gl_enums.json
@@ -0,0 +1,35 @@
+{
+ "BufferBinding":
+ {
+ "Array": "GL_ARRAY_BUFFER",
+ "AtomicCounter": "GL_ATOMIC_COUNTER_BUFFER",
+ "CopyRead": "GL_COPY_READ_BUFFER",
+ "CopyWrite": "GL_COPY_WRITE_BUFFER",
+ "DispatchIndirect": "GL_DISPATCH_INDIRECT_BUFFER",
+ "DrawIndirect": "GL_DRAW_INDIRECT_BUFFER",
+ "ElementArray": "GL_ELEMENT_ARRAY_BUFFER",
+ "PixelPack": "GL_PIXEL_PACK_BUFFER",
+ "PixelUnpack": "GL_PIXEL_UNPACK_BUFFER",
+ "ShaderStorage": "GL_SHADER_STORAGE_BUFFER",
+ "TransformFeedback": "GL_TRANSFORM_FEEDBACK_BUFFER",
+ "Uniform": "GL_UNIFORM_BUFFER"
+ },
+ "BufferUsage":
+ {
+ "DynamicCopy": "GL_DYNAMIC_COPY",
+ "DynamicDraw": "GL_DYNAMIC_DRAW",
+ "DynamicRead": "GL_DYNAMIC_READ",
+ "StaticCopy": "GL_STATIC_COPY",
+ "StaticDraw": "GL_STATIC_DRAW",
+ "StaticRead": "GL_STATIC_READ",
+ "StreamCopy": "GL_STREAM_COPY",
+ "StreamDraw": "GL_STREAM_DRAW",
+ "StreamRead": "GL_STREAM_READ"
+ },
+ "CullFaceMode":
+ {
+ "Back": "GL_BACK",
+ "Front": "GL_FRONT",
+ "FrontAndBack": "GL_FRONT_AND_BACK"
+ }
+}
diff --git a/src/3rdparty/angle/src/libANGLE/params.cpp b/src/3rdparty/angle/src/libANGLE/params.cpp
new file mode 100644
index 0000000000..a89d87e0a9
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/params.cpp
@@ -0,0 +1,68 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// params:
+// Parameter wrapper structs for OpenGL ES. These helpers cache re-used values
+// in entry point routines.
+
+#include "libANGLE/params.h"
+
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/VertexArray.h"
+
+namespace gl
+{
+
+// static
+constexpr ParamTypeInfo ParamsBase::TypeInfo;
+constexpr ParamTypeInfo HasIndexRange::TypeInfo;
+
+HasIndexRange::HasIndexRange()
+ : ParamsBase(nullptr), mContext(nullptr), mCount(0), mType(GL_NONE), mIndices(nullptr)
+{
+}
+
+HasIndexRange::HasIndexRange(Context *context, GLsizei count, GLenum type, const void *indices)
+ : ParamsBase(context), mContext(context), mCount(count), mType(type), mIndices(indices)
+{
+}
+
+const Optional<IndexRange> &HasIndexRange::getIndexRange() const
+{
+ if (mIndexRange.valid() || !mContext)
+ {
+ return mIndexRange;
+ }
+
+ const State &state = mContext->getGLState();
+
+ const gl::VertexArray *vao = state.getVertexArray();
+ gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
+
+ if (elementArrayBuffer)
+ {
+ uintptr_t offset = reinterpret_cast<uintptr_t>(mIndices);
+ IndexRange indexRange;
+ Error error =
+ elementArrayBuffer->getIndexRange(mContext, mType, static_cast<size_t>(offset), mCount,
+ state.isPrimitiveRestartEnabled(), &indexRange);
+ if (error.isError())
+ {
+ mContext->handleError(error);
+ return mIndexRange;
+ }
+
+ mIndexRange = indexRange;
+ }
+ else
+ {
+ mIndexRange = ComputeIndexRange(mType, mIndices, mCount, state.isPrimitiveRestartEnabled());
+ }
+
+ return mIndexRange;
+}
+
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/params.h b/src/3rdparty/angle/src/libANGLE/params.h
new file mode 100644
index 0000000000..27dba640ff
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/params.h
@@ -0,0 +1,228 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// params:
+// Parameter wrapper structs for OpenGL ES. These helpers cache re-used values
+// in entry point routines.
+
+#ifndef LIBANGLE_PARAMS_H_
+#define LIBANGLE_PARAMS_H_
+
+#include "angle_gl.h"
+#include "common/Optional.h"
+#include "common/angleutils.h"
+#include "common/mathutil.h"
+#include "libANGLE/entry_points_enum_autogen.h"
+
+namespace gl
+{
+class Context;
+
+template <EntryPoint EP>
+struct EntryPointParam;
+
+template <EntryPoint EP>
+using EntryPointParamType = typename EntryPointParam<EP>::Type;
+
+class ParamTypeInfo
+{
+ public:
+ constexpr ParamTypeInfo(const char *selfClass, const ParamTypeInfo *parentType)
+ : mSelfClass(selfClass), mParentTypeInfo(parentType)
+ {
+ }
+
+ constexpr bool hasDynamicType(const ParamTypeInfo &typeInfo) const
+ {
+ return mSelfClass == typeInfo.mSelfClass ||
+ (mParentTypeInfo && mParentTypeInfo->hasDynamicType(typeInfo));
+ }
+
+ constexpr bool isValid() const { return mSelfClass != nullptr; }
+
+ private:
+ const char *mSelfClass;
+ const ParamTypeInfo *mParentTypeInfo;
+};
+
+#define ANGLE_PARAM_TYPE_INFO(NAME, BASENAME) \
+ static constexpr ParamTypeInfo TypeInfo = {#NAME, &BASENAME::TypeInfo}
+
+class ParamsBase : angle::NonCopyable
+{
+ public:
+ ParamsBase(Context *context, ...){};
+
+ template <EntryPoint EP, typename... ArgsT>
+ static void Factory(EntryPointParamType<EP> *objBuffer, ArgsT... args);
+
+ static constexpr ParamTypeInfo TypeInfo = {nullptr, nullptr};
+};
+
+// static
+template <EntryPoint EP, typename... ArgsT>
+ANGLE_INLINE void ParamsBase::Factory(EntryPointParamType<EP> *objBuffer, ArgsT... args)
+{
+ new (objBuffer) EntryPointParamType<EP>(args...);
+}
+
+class HasIndexRange : public ParamsBase
+{
+ public:
+ // Dummy placeholder that can't generate an index range.
+ HasIndexRange();
+ HasIndexRange(Context *context, GLsizei count, GLenum type, const void *indices);
+
+ template <EntryPoint EP, typename... ArgsT>
+ static void Factory(HasIndexRange *objBuffer, ArgsT... args);
+
+ const Optional<IndexRange> &getIndexRange() const;
+
+ ANGLE_PARAM_TYPE_INFO(HasIndexRange, ParamsBase);
+
+ private:
+ Context *mContext;
+ GLsizei mCount;
+ GLenum mType;
+ const GLvoid *mIndices;
+ mutable Optional<IndexRange> mIndexRange;
+};
+
+// Entry point funcs essentially re-map different entry point parameter arrays into
+// the format the parameter type class expects. For example, for HasIndexRange, for the
+// various indexed draw calls, they drop parameters that aren't useful and re-arrange
+// the rest.
+#define ANGLE_ENTRY_POINT_FUNC(NAME, CLASS, ...) \
+ \
+template<> struct EntryPointParam<EntryPoint::NAME> \
+ { \
+ using Type = CLASS; \
+ }; \
+ \
+template<> inline void CLASS::Factory<EntryPoint::NAME>(__VA_ARGS__)
+
+ANGLE_ENTRY_POINT_FUNC(DrawElements,
+ HasIndexRange,
+ HasIndexRange *objBuffer,
+ Context *context,
+ GLenum /*mode*/,
+ GLsizei count,
+ GLenum type,
+ const void *indices)
+{
+ return ParamsBase::Factory<EntryPoint::DrawElements>(objBuffer, context, count, type, indices);
+}
+
+ANGLE_ENTRY_POINT_FUNC(DrawElementsInstanced,
+ HasIndexRange,
+ HasIndexRange *objBuffer,
+ Context *context,
+ GLenum /*mode*/,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei /*instanceCount*/)
+{
+ return ParamsBase::Factory<EntryPoint::DrawElementsInstanced>(objBuffer, context, count, type,
+ indices);
+}
+
+ANGLE_ENTRY_POINT_FUNC(DrawElementsInstancedANGLE,
+ HasIndexRange,
+ HasIndexRange *objBuffer,
+ Context *context,
+ GLenum /*mode*/,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei /*instanceCount*/)
+{
+ return ParamsBase::Factory<EntryPoint::DrawElementsInstancedANGLE>(objBuffer, context, count,
+ type, indices);
+}
+
+ANGLE_ENTRY_POINT_FUNC(DrawRangeElements,
+ HasIndexRange,
+ HasIndexRange *objBuffer,
+ Context *context,
+ GLenum /*mode*/,
+ GLuint /*start*/,
+ GLuint /*end*/,
+ GLsizei count,
+ GLenum type,
+ const void *indices)
+{
+ return ParamsBase::Factory<EntryPoint::DrawRangeElements>(objBuffer, context, count, type,
+ indices);
+}
+
+#undef ANGLE_ENTRY_POINT_FUNC
+
+template <EntryPoint EP>
+struct EntryPointParam
+{
+ using Type = ParamsBase;
+};
+
+// A template struct for determining the default value to return for each entry point.
+template <EntryPoint EP, typename ReturnType>
+struct DefaultReturnValue;
+
+// Default return values for each basic return type.
+template <EntryPoint EP>
+struct DefaultReturnValue<EP, GLint>
+{
+ static constexpr GLint kValue = -1;
+};
+
+// This doubles as the GLenum return value.
+template <EntryPoint EP>
+struct DefaultReturnValue<EP, GLuint>
+{
+ static constexpr GLuint kValue = 0;
+};
+
+template <EntryPoint EP>
+struct DefaultReturnValue<EP, GLboolean>
+{
+ static constexpr GLboolean kValue = GL_FALSE;
+};
+
+// Catch-all rules for pointer types.
+template <EntryPoint EP, typename PointerType>
+struct DefaultReturnValue<EP, const PointerType *>
+{
+ static constexpr const PointerType *kValue = nullptr;
+};
+
+template <EntryPoint EP, typename PointerType>
+struct DefaultReturnValue<EP, PointerType *>
+{
+ static constexpr PointerType *kValue = nullptr;
+};
+
+// Overloaded to return invalid index
+template <>
+struct DefaultReturnValue<EntryPoint::GetUniformBlockIndex, GLuint>
+{
+ static constexpr GLuint kValue = GL_INVALID_INDEX;
+};
+
+// Specialized enum error value.
+template <>
+struct DefaultReturnValue<EntryPoint::ClientWaitSync, GLenum>
+{
+ static constexpr GLenum kValue = GL_WAIT_FAILED;
+};
+
+template <EntryPoint EP, typename ReturnType>
+constexpr ANGLE_INLINE ReturnType GetDefaultReturnValue()
+{
+ return DefaultReturnValue<EP, ReturnType>::kValue;
+}
+
+} // namespace gl
+
+#endif // LIBANGLE_PARAMS_H_
diff --git a/src/3rdparty/angle/src/libANGLE/queryconversions.cpp b/src/3rdparty/angle/src/libANGLE/queryconversions.cpp
index 3a6059a89c..78d219365e 100644
--- a/src/3rdparty/angle/src/libANGLE/queryconversions.cpp
+++ b/src/3rdparty/angle/src/libANGLE/queryconversions.cpp
@@ -24,18 +24,9 @@ GLint64 ExpandFloatToInteger(GLfloat value)
return static_cast<GLint64>((static_cast<double>(0xFFFFFFFFULL) * value - 1.0) / 2.0);
}
-template <typename QueryT>
-QueryT ClampToQueryRange(GLint64 value)
-{
- const GLint64 min = static_cast<GLint64>(std::numeric_limits<QueryT>::min());
- const GLint64 max = static_cast<GLint64>(std::numeric_limits<QueryT>::max());
- return static_cast<QueryT>(clamp(value, min, max));
-}
-
template <typename QueryT, typename NativeT>
-QueryT CastStateValueToInt(GLenum pname, NativeT value)
+QueryT CastFromStateValueToInt(GLenum pname, NativeT value)
{
- GLenum queryType = GLTypeToGLenum<QueryT>::value;
GLenum nativeType = GLTypeToGLenum<NativeT>::value;
if (nativeType == GL_FLOAT)
@@ -43,37 +34,68 @@ QueryT CastStateValueToInt(GLenum pname, NativeT value)
// RGBA color values and DepthRangeF values are converted to integer using Equation 2.4 from Table 4.5
if (pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR)
{
- return ClampToQueryRange<QueryT>(ExpandFloatToInteger(static_cast<GLfloat>(value)));
+ return clampCast<QueryT>(ExpandFloatToInteger(static_cast<GLfloat>(value)));
}
else
{
- return gl::iround<QueryT>(static_cast<GLfloat>(value));
+ return clampCast<QueryT>(std::round(value));
}
}
- // Clamp 64-bit int values when casting to int
- if (nativeType == GL_INT_64_ANGLEX && queryType == GL_INT)
+ return clampCast<QueryT>(value);
+}
+
+template <typename NativeT, typename QueryT>
+NativeT CastQueryValueToInt(GLenum pname, QueryT value)
+{
+ GLenum queryType = GLTypeToGLenum<QueryT>::value;
+
+ if (queryType == GL_FLOAT)
{
- GLint64 minIntValue = static_cast<GLint64>(std::numeric_limits<GLint>::min());
- GLint64 maxIntValue = static_cast<GLint64>(std::numeric_limits<GLint>::max());
- GLint64 clampedValue = std::max(std::min(static_cast<GLint64>(value), maxIntValue), minIntValue);
- return static_cast<QueryT>(clampedValue);
+ return static_cast<NativeT>(std::round(value));
}
- return static_cast<QueryT>(value);
+ return static_cast<NativeT>(value);
+}
+
+} // anonymous namespace
+
+// ES 3.10 Section 2.2.2
+// When querying bitmasks(such as SAMPLE_MASK_VALUE or STENCIL_WRITEMASK) with GetIntegerv, the
+// mask value is treated as a signed integer, so that mask values with the high bit set will not be
+// clamped when returned as signed integers.
+GLint CastMaskValue(const Context *context, GLuint value)
+{
+ return (context->getClientVersion() >= Version(3, 1) ? static_cast<GLint>(value)
+ : clampCast<GLint>(value));
+}
+
+template <typename QueryT, typename InternalT>
+QueryT CastFromGLintStateValue(GLenum pname, InternalT value)
+{
+ return CastFromStateValue<QueryT, GLint>(pname, clampCast<GLint, InternalT>(value));
}
+template GLfloat CastFromGLintStateValue<GLfloat, GLenum>(GLenum pname, GLenum value);
+template GLint CastFromGLintStateValue<GLint, GLenum>(GLenum pname, GLenum value);
+template GLint64 CastFromGLintStateValue<GLint64, GLenum>(GLenum pname, GLenum value);
+template GLuint CastFromGLintStateValue<GLuint, GLenum>(GLenum pname, GLenum value);
+template GLfloat CastFromGLintStateValue<GLfloat, bool>(GLenum pname, bool value);
+template GLuint CastFromGLintStateValue<GLuint, bool>(GLenum pname, bool value);
+template GLint CastFromGLintStateValue<GLint, bool>(GLenum pname, bool value);
+
template <typename QueryT, typename NativeT>
-QueryT CastStateValue(GLenum pname, NativeT value)
+QueryT CastFromStateValue(GLenum pname, NativeT value)
{
GLenum queryType = GLTypeToGLenum<QueryT>::value;
switch (queryType)
{
case GL_INT:
- return CastStateValueToInt<QueryT, NativeT>(pname, value);
case GL_INT_64_ANGLEX:
- return CastStateValueToInt<QueryT, NativeT>(pname, value);
+ case GL_UNSIGNED_INT:
+ case GL_UINT_64_ANGLEX:
+ return CastFromStateValueToInt<QueryT, NativeT>(pname, value);
case GL_FLOAT:
return static_cast<QueryT>(value);
case GL_BOOL:
@@ -83,19 +105,50 @@ QueryT CastStateValue(GLenum pname, NativeT value)
return 0;
}
}
+template GLint CastFromStateValue<GLint, GLint>(GLenum pname, GLint value);
+template GLint CastFromStateValue<GLint, GLint64>(GLenum pname, GLint64 value);
+template GLint64 CastFromStateValue<GLint64, GLint>(GLenum pname, GLint value);
+template GLint64 CastFromStateValue<GLint64, GLint64>(GLenum pname, GLint64 value);
+template GLfloat CastFromStateValue<GLfloat, GLint>(GLenum pname, GLint value);
+template GLfloat CastFromStateValue<GLfloat, GLfloat>(GLenum pname, GLfloat value);
+template GLint CastFromStateValue<GLint, GLfloat>(GLenum pname, GLfloat value);
+template GLuint CastFromStateValue<GLuint, GLint>(GLenum pname, GLint value);
+template GLuint CastFromStateValue<GLuint, GLuint>(GLenum pname, GLuint value);
+template GLint CastFromStateValue<GLint, GLboolean>(GLenum pname, GLboolean value);
+template GLint64 CastFromStateValue<GLint64, GLboolean>(GLenum pname, GLboolean value);
+template GLint CastFromStateValue<GLint, GLuint>(GLenum pname, GLuint value);
+template GLint64 CastFromStateValue<GLint64, GLuint>(GLenum pname, GLuint value);
+template GLuint64 CastFromStateValue<GLuint64, GLuint>(GLenum pname, GLuint value);
-} // anonymous namespace
+template <typename NativeT, typename QueryT>
+NativeT CastQueryValueTo(GLenum pname, QueryT value)
+{
+ GLenum nativeType = GLTypeToGLenum<NativeT>::value;
+
+ switch (nativeType)
+ {
+ case GL_INT:
+ case GL_INT_64_ANGLEX:
+ case GL_UNSIGNED_INT:
+ case GL_UINT_64_ANGLEX:
+ return CastQueryValueToInt<NativeT, QueryT>(pname, value);
+ case GL_FLOAT:
+ return static_cast<NativeT>(value);
+ case GL_BOOL:
+ return static_cast<NativeT>(value == static_cast<QueryT>(0) ? GL_FALSE : GL_TRUE);
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
-template <>
-GLenum GLTypeToGLenum<GLint>::value = GL_INT;
-template <>
-GLenum GLTypeToGLenum<GLuint>::value = GL_UNSIGNED_INT;
-template <>
-GLenum GLTypeToGLenum<GLboolean>::value = GL_BOOL;
-template <>
-GLenum GLTypeToGLenum<GLint64>::value = GL_INT_64_ANGLEX;
-template <>
-GLenum GLTypeToGLenum<GLfloat>::value = GL_FLOAT;
+template GLint CastQueryValueTo<GLint, GLfloat>(GLenum pname, GLfloat value);
+template GLboolean CastQueryValueTo<GLboolean, GLint>(GLenum pname, GLint value);
+template GLint CastQueryValueTo<GLint, GLint>(GLenum pname, GLint value);
+template GLfloat CastQueryValueTo<GLfloat, GLint>(GLenum pname, GLint value);
+template GLfloat CastQueryValueTo<GLfloat, GLfloat>(GLenum pname, GLfloat value);
+template GLuint CastQueryValueTo<GLuint, GLint>(GLenum pname, GLint value);
+template GLuint CastQueryValueTo<GLuint, GLfloat>(GLenum pname, GLfloat value);
template <typename QueryT>
void CastStateValues(Context *context, GLenum nativeType, GLenum pname,
@@ -104,17 +157,17 @@ void CastStateValues(Context *context, GLenum nativeType, GLenum pname,
if (nativeType == GL_INT)
{
std::vector<GLint> intParams(numParams, 0);
- context->getIntegerv(pname, intParams.data());
+ context->getIntegervImpl(pname, intParams.data());
for (unsigned int i = 0; i < numParams; ++i)
{
- outParams[i] = CastStateValue<QueryT>(pname, intParams[i]);
+ outParams[i] = CastFromStateValue<QueryT>(pname, intParams[i]);
}
}
else if (nativeType == GL_BOOL)
{
std::vector<GLboolean> boolParams(numParams, GL_FALSE);
- context->getBooleanv(pname, boolParams.data());
+ context->getBooleanvImpl(pname, boolParams.data());
for (unsigned int i = 0; i < numParams; ++i)
{
@@ -124,11 +177,11 @@ void CastStateValues(Context *context, GLenum nativeType, GLenum pname,
else if (nativeType == GL_FLOAT)
{
std::vector<GLfloat> floatParams(numParams, 0.0f);
- context->getFloatv(pname, floatParams.data());
+ context->getFloatvImpl(pname, floatParams.data());
for (unsigned int i = 0; i < numParams; ++i)
{
- outParams[i] = CastStateValue<QueryT>(pname, floatParams[i]);
+ outParams[i] = CastFromStateValue<QueryT>(pname, floatParams[i]);
}
}
else if (nativeType == GL_INT_64_ANGLEX)
@@ -138,7 +191,7 @@ void CastStateValues(Context *context, GLenum nativeType, GLenum pname,
for (unsigned int i = 0; i < numParams; ++i)
{
- outParams[i] = CastStateValue<QueryT>(pname, int64Params[i]);
+ outParams[i] = CastFromStateValue<QueryT>(pname, int64Params[i]);
}
}
else UNREACHABLE();
@@ -146,7 +199,7 @@ void CastStateValues(Context *context, GLenum nativeType, GLenum pname,
// Explicit template instantiation (how we export template functions in different files)
// The calls below will make CastStateValues successfully link with the GL state query types
-// The GL state query API types are: bool, int, uint, float, int64
+// The GL state query API types are: bool, int, uint, float, int64, uint64
template void CastStateValues<GLboolean>(Context *, GLenum, GLenum, unsigned int, GLboolean *);
template void CastStateValues<GLint>(Context *, GLenum, GLenum, unsigned int, GLint *);
@@ -154,4 +207,77 @@ template void CastStateValues<GLuint>(Context *, GLenum, GLenum, unsigned int, G
template void CastStateValues<GLfloat>(Context *, GLenum, GLenum, unsigned int, GLfloat *);
template void CastStateValues<GLint64>(Context *, GLenum, GLenum, unsigned int, GLint64 *);
+template <typename QueryT>
+void CastIndexedStateValues(Context *context,
+ GLenum nativeType,
+ GLenum pname,
+ GLuint index,
+ unsigned int numParams,
+ QueryT *outParams)
+{
+ if (nativeType == GL_INT)
+ {
+ std::vector<GLint> intParams(numParams, 0);
+ context->getIntegeri_v(pname, index, intParams.data());
+
+ for (unsigned int i = 0; i < numParams; ++i)
+ {
+ outParams[i] = CastFromStateValue<QueryT>(pname, intParams[i]);
+ }
+ }
+ else if (nativeType == GL_BOOL)
+ {
+ std::vector<GLboolean> boolParams(numParams, GL_FALSE);
+ context->getBooleani_v(pname, index, boolParams.data());
+
+ for (unsigned int i = 0; i < numParams; ++i)
+ {
+ outParams[i] =
+ (boolParams[i] == GL_FALSE ? static_cast<QueryT>(0) : static_cast<QueryT>(1));
+ }
+ }
+ else if (nativeType == GL_INT_64_ANGLEX)
+ {
+ std::vector<GLint64> int64Params(numParams, 0);
+ context->getInteger64i_v(pname, index, int64Params.data());
+
+ for (unsigned int i = 0; i < numParams; ++i)
+ {
+ outParams[i] = CastFromStateValue<QueryT>(pname, int64Params[i]);
+ }
+ }
+ else
+ UNREACHABLE();
+}
+
+template void CastIndexedStateValues<GLboolean>(Context *,
+ GLenum,
+ GLenum,
+ GLuint index,
+ unsigned int,
+ GLboolean *);
+template void CastIndexedStateValues<GLint>(Context *,
+ GLenum,
+ GLenum,
+ GLuint index,
+ unsigned int,
+ GLint *);
+template void CastIndexedStateValues<GLuint>(Context *,
+ GLenum,
+ GLenum,
+ GLuint index,
+ unsigned int,
+ GLuint *);
+template void CastIndexedStateValues<GLfloat>(Context *,
+ GLenum,
+ GLenum,
+ GLuint index,
+ unsigned int,
+ GLfloat *);
+template void CastIndexedStateValues<GLint64>(Context *,
+ GLenum,
+ GLenum,
+ GLuint index,
+ unsigned int,
+ GLint64 *);
}
diff --git a/src/3rdparty/angle/src/libANGLE/queryconversions.h b/src/3rdparty/angle/src/libANGLE/queryconversions.h
index e0fdbe17e0..805f36cf02 100644
--- a/src/3rdparty/angle/src/libANGLE/queryconversions.h
+++ b/src/3rdparty/angle/src/libANGLE/queryconversions.h
@@ -18,19 +18,100 @@ class Context;
// Helper class for converting a GL type to a GLenum:
// We can't use CastStateValueEnum generally, because of GLboolean + GLubyte overlap.
-// We restrict our use to CastStateValue, where it eliminates duplicate parameters.
+// We restrict our use to CastFromStateValue and CastQueryValueTo, where it eliminates
+// duplicate parameters.
template <typename GLType>
struct GLTypeToGLenum
{
- static GLenum value;
+ // static constexpr GLenum value;
};
-// The GL state query API types are: bool, int, uint, float, int64
+template <>
+struct GLTypeToGLenum<GLint>
+{
+ static constexpr GLenum value = GL_INT;
+};
+template <>
+struct GLTypeToGLenum<GLuint>
+{
+ static constexpr GLenum value = GL_UNSIGNED_INT;
+};
+template <>
+struct GLTypeToGLenum<GLboolean>
+{
+ static constexpr GLenum value = GL_BOOL;
+};
+template <>
+struct GLTypeToGLenum<GLint64>
+{
+ static constexpr GLenum value = GL_INT_64_ANGLEX;
+};
+template <>
+struct GLTypeToGLenum<GLuint64>
+{
+ static constexpr GLenum value = GL_UINT_64_ANGLEX;
+};
+template <>
+struct GLTypeToGLenum<GLfloat>
+{
+ static constexpr GLenum value = GL_FLOAT;
+};
+
+GLint CastMaskValue(const Context *context, GLuint value);
+
+template <typename QueryT, typename InternalT>
+QueryT CastFromGLintStateValue(GLenum pname, InternalT value);
+
+template <typename QueryT, typename NativeT>
+QueryT CastFromStateValue(GLenum pname, NativeT value);
+
+template <typename NativeT, typename QueryT>
+NativeT CastQueryValueTo(GLenum pname, QueryT value);
+
+template <typename ParamType>
+GLenum ConvertToGLenum(GLenum pname, ParamType param)
+{
+ return static_cast<GLenum>(CastQueryValueTo<GLuint>(pname, param));
+}
+
+template <typename ParamType>
+GLenum ConvertToGLenum(ParamType param)
+{
+ return ConvertToGLenum(GL_NONE, param);
+}
+
+template <typename ParamType>
+GLenum ConvertToGLint(ParamType param)
+{
+ return CastQueryValueTo<GLint>(GL_NONE, param);
+}
+
+template <typename ParamType>
+bool ConvertToBool(ParamType param)
+{
+ return param != GL_FALSE;
+}
+
+template <typename ParamType>
+GLboolean ConvertToGLBoolean(ParamType param)
+{
+ return param ? GL_TRUE : GL_FALSE;
+}
+
+// The GL state query API types are: bool, int, uint, float, int64, uint64
template <typename QueryT>
void CastStateValues(Context *context, GLenum nativeType, GLenum pname,
unsigned int numParams, QueryT *outParams);
+// The GL state query API types are: bool, int, uint, float, int64, uint64
+template <typename QueryT>
+void CastIndexedStateValues(Context *context,
+ GLenum nativeType,
+ GLenum pname,
+ GLuint index,
+ unsigned int numParams,
+ QueryT *outParams);
}
#endif // LIBANGLE_QUERY_CONVERSIONS_H_
diff --git a/src/3rdparty/angle/src/libANGLE/queryutils.cpp b/src/3rdparty/angle/src/libANGLE/queryutils.cpp
new file mode 100644
index 0000000000..16a989c688
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/queryutils.cpp
@@ -0,0 +1,1916 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// queryutils.cpp: Utilities for querying values from GL objects
+
+#include "libANGLE/queryutils.h"
+
+#include "common/utilities.h"
+
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Fence.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Sampler.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/queryconversions.h"
+
+namespace gl
+{
+
+namespace
+{
+
+template <typename ParamType>
+void QueryTexLevelParameterBase(const Texture *texture,
+ GLenum target,
+ GLint level,
+ GLenum pname,
+ ParamType *params)
+{
+ ASSERT(texture != nullptr);
+ const InternalFormat *info = texture->getTextureState().getImageDesc(target, level).format.info;
+
+ switch (pname)
+ {
+ case GL_TEXTURE_RED_TYPE:
+ *params = CastFromGLintStateValue<ParamType>(
+ pname, info->redBits ? info->componentType : GL_NONE);
+ break;
+ case GL_TEXTURE_GREEN_TYPE:
+ *params = CastFromGLintStateValue<ParamType>(
+ pname, info->greenBits ? info->componentType : GL_NONE);
+ break;
+ case GL_TEXTURE_BLUE_TYPE:
+ *params = CastFromGLintStateValue<ParamType>(
+ pname, info->blueBits ? info->componentType : GL_NONE);
+ break;
+ case GL_TEXTURE_ALPHA_TYPE:
+ *params = CastFromGLintStateValue<ParamType>(
+ pname, info->alphaBits ? info->componentType : GL_NONE);
+ break;
+ case GL_TEXTURE_DEPTH_TYPE:
+ *params = CastFromGLintStateValue<ParamType>(
+ pname, info->depthBits ? info->componentType : GL_NONE);
+ break;
+ case GL_TEXTURE_RED_SIZE:
+ *params = CastFromGLintStateValue<ParamType>(pname, info->redBits);
+ break;
+ case GL_TEXTURE_GREEN_SIZE:
+ *params = CastFromGLintStateValue<ParamType>(pname, info->greenBits);
+ break;
+ case GL_TEXTURE_BLUE_SIZE:
+ *params = CastFromGLintStateValue<ParamType>(pname, info->blueBits);
+ break;
+ case GL_TEXTURE_ALPHA_SIZE:
+ *params = CastFromGLintStateValue<ParamType>(pname, info->alphaBits);
+ break;
+ case GL_TEXTURE_DEPTH_SIZE:
+ *params = CastFromGLintStateValue<ParamType>(pname, info->depthBits);
+ break;
+ case GL_TEXTURE_STENCIL_SIZE:
+ *params = CastFromGLintStateValue<ParamType>(pname, info->stencilBits);
+ break;
+ case GL_TEXTURE_SHARED_SIZE:
+ *params = CastFromGLintStateValue<ParamType>(pname, info->sharedBits);
+ break;
+ case GL_TEXTURE_INTERNAL_FORMAT:
+ *params = CastFromGLintStateValue<ParamType>(
+ pname, info->internalFormat ? info->internalFormat : GL_RGBA);
+ break;
+ case GL_TEXTURE_WIDTH:
+ *params = CastFromGLintStateValue<ParamType>(
+ pname, static_cast<uint32_t>(texture->getWidth(target, level)));
+ break;
+ case GL_TEXTURE_HEIGHT:
+ *params = CastFromGLintStateValue<ParamType>(
+ pname, static_cast<uint32_t>(texture->getHeight(target, level)));
+ break;
+ case GL_TEXTURE_DEPTH:
+ *params = CastFromGLintStateValue<ParamType>(
+ pname, static_cast<uint32_t>(texture->getDepth(target, level)));
+ break;
+ case GL_TEXTURE_SAMPLES:
+ *params = CastFromStateValue<ParamType>(pname, texture->getSamples(target, level));
+ break;
+ case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
+ *params = CastFromStateValue<ParamType>(
+ pname, static_cast<GLint>(texture->getFixedSampleLocations(target, level)));
+ break;
+ case GL_TEXTURE_COMPRESSED:
+ *params = CastFromStateValue<ParamType>(pname, static_cast<GLint>(info->compressed));
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+template <typename ParamType>
+void QueryTexParameterBase(const Texture *texture, GLenum pname, ParamType *params)
+{
+ ASSERT(texture != nullptr);
+
+ switch (pname)
+ {
+ case GL_TEXTURE_MAG_FILTER:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getMagFilter());
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getMinFilter());
+ break;
+ case GL_TEXTURE_WRAP_S:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getWrapS());
+ break;
+ case GL_TEXTURE_WRAP_T:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getWrapT());
+ break;
+ case GL_TEXTURE_WRAP_R:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getWrapR());
+ break;
+ case GL_TEXTURE_IMMUTABLE_FORMAT:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getImmutableFormat());
+ break;
+ case GL_TEXTURE_IMMUTABLE_LEVELS:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getImmutableLevels());
+ break;
+ case GL_TEXTURE_USAGE_ANGLE:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getUsage());
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ *params = CastFromStateValue<ParamType>(pname, texture->getMaxAnisotropy());
+ break;
+ case GL_TEXTURE_SWIZZLE_R:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getSwizzleRed());
+ break;
+ case GL_TEXTURE_SWIZZLE_G:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getSwizzleGreen());
+ break;
+ case GL_TEXTURE_SWIZZLE_B:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getSwizzleBlue());
+ break;
+ case GL_TEXTURE_SWIZZLE_A:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getSwizzleAlpha());
+ break;
+ case GL_TEXTURE_BASE_LEVEL:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getBaseLevel());
+ break;
+ case GL_TEXTURE_MAX_LEVEL:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getMaxLevel());
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ *params = CastFromStateValue<ParamType>(pname, texture->getSamplerState().minLod);
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ *params = CastFromStateValue<ParamType>(pname, texture->getSamplerState().maxLod);
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getCompareMode());
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getCompareFunc());
+ break;
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getSRGBDecode());
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+template <typename ParamType>
+void SetTexParameterBase(Context *context, Texture *texture, GLenum pname, const ParamType *params)
+{
+ ASSERT(texture != nullptr);
+
+ switch (pname)
+ {
+ case GL_TEXTURE_WRAP_S:
+ texture->setWrapS(ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_WRAP_T:
+ texture->setWrapT(ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_WRAP_R:
+ texture->setWrapR(ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ texture->setMinFilter(ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ texture->setMagFilter(ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_USAGE_ANGLE:
+ texture->setUsage(ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ texture->setMaxAnisotropy(CastQueryValueTo<GLfloat>(pname, params[0]));
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ texture->setCompareMode(ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ texture->setCompareFunc(ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_SWIZZLE_R:
+ texture->setSwizzleRed(ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_SWIZZLE_G:
+ texture->setSwizzleGreen(ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_SWIZZLE_B:
+ texture->setSwizzleBlue(ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_SWIZZLE_A:
+ texture->setSwizzleAlpha(ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_BASE_LEVEL:
+ {
+ context->handleError(texture->setBaseLevel(
+ context, clampCast<GLuint>(CastQueryValueTo<GLint>(pname, params[0]))));
+ break;
+ }
+ case GL_TEXTURE_MAX_LEVEL:
+ texture->setMaxLevel(clampCast<GLuint>(CastQueryValueTo<GLint>(pname, params[0])));
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ texture->setMinLod(CastQueryValueTo<GLfloat>(pname, params[0]));
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ texture->setMaxLod(CastQueryValueTo<GLfloat>(pname, params[0]));
+ break;
+ case GL_DEPTH_STENCIL_TEXTURE_MODE:
+ texture->setDepthStencilTextureMode(ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ texture->setSRGBDecode(ConvertToGLenum(pname, params[0]));
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+template <typename ParamType>
+void QuerySamplerParameterBase(const Sampler *sampler, GLenum pname, ParamType *params)
+{
+ switch (pname)
+ {
+ case GL_TEXTURE_MIN_FILTER:
+ *params = CastFromGLintStateValue<ParamType>(pname, sampler->getMinFilter());
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ *params = CastFromGLintStateValue<ParamType>(pname, sampler->getMagFilter());
+ break;
+ case GL_TEXTURE_WRAP_S:
+ *params = CastFromGLintStateValue<ParamType>(pname, sampler->getWrapS());
+ break;
+ case GL_TEXTURE_WRAP_T:
+ *params = CastFromGLintStateValue<ParamType>(pname, sampler->getWrapT());
+ break;
+ case GL_TEXTURE_WRAP_R:
+ *params = CastFromGLintStateValue<ParamType>(pname, sampler->getWrapR());
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ *params = CastFromStateValue<ParamType>(pname, sampler->getMaxAnisotropy());
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ *params = CastFromStateValue<ParamType>(pname, sampler->getMinLod());
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ *params = CastFromStateValue<ParamType>(pname, sampler->getMaxLod());
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ *params = CastFromGLintStateValue<ParamType>(pname, sampler->getCompareMode());
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ *params = CastFromGLintStateValue<ParamType>(pname, sampler->getCompareFunc());
+ break;
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ *params = CastFromGLintStateValue<ParamType>(pname, sampler->getSRGBDecode());
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+template <typename ParamType>
+void SetSamplerParameterBase(Sampler *sampler, GLenum pname, const ParamType *params)
+{
+ switch (pname)
+ {
+ case GL_TEXTURE_WRAP_S:
+ sampler->setWrapS(ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_WRAP_T:
+ sampler->setWrapT(ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_WRAP_R:
+ sampler->setWrapR(ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ sampler->setMinFilter(ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ sampler->setMagFilter(ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ sampler->setMaxAnisotropy(CastQueryValueTo<GLfloat>(pname, params[0]));
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ sampler->setCompareMode(ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ sampler->setCompareFunc(ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ sampler->setMinLod(CastQueryValueTo<GLfloat>(pname, params[0]));
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ sampler->setMaxLod(CastQueryValueTo<GLfloat>(pname, params[0]));
+ break;
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ sampler->setSRGBDecode(ConvertToGLenum(pname, params[0]));
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
+template <typename ParamType, typename CurrentDataType, size_t CurrentValueCount>
+void QueryVertexAttribBase(const VertexAttribute &attrib,
+ const VertexBinding &binding,
+ const CurrentDataType (&currentValueData)[CurrentValueCount],
+ GLenum pname,
+ ParamType *params)
+{
+ switch (pname)
+ {
+ case GL_CURRENT_VERTEX_ATTRIB:
+ for (size_t i = 0; i < CurrentValueCount; ++i)
+ {
+ params[i] = CastFromStateValue<ParamType>(pname, currentValueData[i]);
+ }
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
+ *params = CastFromStateValue<ParamType>(pname, static_cast<GLint>(attrib.enabled));
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_SIZE:
+ *params = CastFromGLintStateValue<ParamType>(pname, attrib.size);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
+ *params = CastFromGLintStateValue<ParamType>(pname, attrib.vertexAttribArrayStride);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_TYPE:
+ *params = CastFromGLintStateValue<ParamType>(pname, attrib.type);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
+ *params = CastFromStateValue<ParamType>(pname, static_cast<GLint>(attrib.normalized));
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
+ *params = CastFromGLintStateValue<ParamType>(pname, binding.getBuffer().id());
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
+ *params = CastFromGLintStateValue<ParamType>(pname, binding.getDivisor());
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
+ *params = CastFromGLintStateValue<ParamType>(pname, attrib.pureInteger);
+ break;
+ case GL_VERTEX_ATTRIB_BINDING:
+ *params = CastFromGLintStateValue<ParamType>(pname, attrib.bindingIndex);
+ break;
+ case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
+ *params = CastFromGLintStateValue<ParamType>(pname, attrib.relativeOffset);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+template <typename ParamType>
+void QueryBufferParameterBase(const Buffer *buffer, GLenum pname, ParamType *params)
+{
+ ASSERT(buffer != nullptr);
+
+ switch (pname)
+ {
+ case GL_BUFFER_USAGE:
+ *params = CastFromGLintStateValue<ParamType>(pname, ToGLenum(buffer->getUsage()));
+ break;
+ case GL_BUFFER_SIZE:
+ *params = CastFromStateValue<ParamType>(pname, buffer->getSize());
+ break;
+ case GL_BUFFER_ACCESS_FLAGS:
+ *params = CastFromGLintStateValue<ParamType>(pname, buffer->getAccessFlags());
+ break;
+ case GL_BUFFER_ACCESS_OES:
+ *params = CastFromGLintStateValue<ParamType>(pname, buffer->getAccess());
+ break;
+ case GL_BUFFER_MAPPED:
+ *params = CastFromStateValue<ParamType>(pname, buffer->isMapped());
+ break;
+ case GL_BUFFER_MAP_OFFSET:
+ *params = CastFromStateValue<ParamType>(pname, buffer->getMapOffset());
+ break;
+ case GL_BUFFER_MAP_LENGTH:
+ *params = CastFromStateValue<ParamType>(pname, buffer->getMapLength());
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+GLint GetCommonVariableProperty(const sh::ShaderVariable &var, GLenum prop)
+{
+ switch (prop)
+ {
+ case GL_TYPE:
+ return clampCast<GLint>(var.type);
+
+ case GL_ARRAY_SIZE:
+ // Queryable variables are guaranteed not to be arrays of arrays or arrays of structs,
+ // see GLES 3.1 spec section 7.3.1.1 page 77.
+ return clampCast<GLint>(var.getBasicTypeElementCount());
+
+ case GL_NAME_LENGTH:
+ // ES31 spec p84: This counts the terminating null char.
+ return clampCast<GLint>(var.name.size() + 1u);
+
+ default:
+ UNREACHABLE();
+ return GL_INVALID_VALUE;
+ }
+}
+
+GLint GetInputResourceProperty(const Program *program, GLuint index, GLenum prop)
+{
+ const auto &attribute = program->getInputResource(index);
+ switch (prop)
+ {
+ case GL_TYPE:
+ case GL_ARRAY_SIZE:
+ case GL_NAME_LENGTH:
+ return GetCommonVariableProperty(attribute, prop);
+
+ case GL_LOCATION:
+ return program->getAttributeLocation(attribute.name);
+
+ case GL_REFERENCED_BY_VERTEX_SHADER:
+ return 1;
+
+ case GL_REFERENCED_BY_FRAGMENT_SHADER:
+ case GL_REFERENCED_BY_COMPUTE_SHADER:
+ return 0;
+
+ default:
+ UNREACHABLE();
+ return GL_INVALID_VALUE;
+ }
+}
+
+GLint GetOutputResourceProperty(const Program *program, GLuint index, const GLenum prop)
+{
+ const auto &outputVariable = program->getOutputResource(index);
+ switch (prop)
+ {
+ case GL_TYPE:
+ case GL_ARRAY_SIZE:
+ case GL_NAME_LENGTH:
+ return GetCommonVariableProperty(outputVariable, prop);
+
+ case GL_LOCATION:
+ return program->getFragDataLocation(outputVariable.name);
+
+ case GL_REFERENCED_BY_VERTEX_SHADER:
+ return 0;
+
+ case GL_REFERENCED_BY_FRAGMENT_SHADER:
+ return 1;
+
+ case GL_REFERENCED_BY_COMPUTE_SHADER:
+ return 0;
+
+ default:
+ UNREACHABLE();
+ return GL_INVALID_VALUE;
+ }
+}
+
+GLint QueryProgramInterfaceActiveResources(const Program *program, GLenum programInterface)
+{
+ switch (programInterface)
+ {
+ case GL_PROGRAM_INPUT:
+ return clampCast<GLint>(program->getAttributes().size());
+
+ case GL_PROGRAM_OUTPUT:
+ return clampCast<GLint>(program->getState().getOutputVariables().size());
+
+ case GL_UNIFORM:
+ return clampCast<GLint>(program->getState().getUniforms().size());
+
+ case GL_UNIFORM_BLOCK:
+ return clampCast<GLint>(program->getState().getUniformBlocks().size());
+
+ case GL_ATOMIC_COUNTER_BUFFER:
+ return clampCast<GLint>(program->getState().getAtomicCounterBuffers().size());
+
+ case GL_BUFFER_VARIABLE:
+ return clampCast<GLint>(program->getState().getBufferVariables().size());
+
+ case GL_SHADER_STORAGE_BLOCK:
+ return clampCast<GLint>(program->getState().getShaderStorageBlocks().size());
+
+ // TODO(jie.a.chen@intel.com): more interfaces.
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ UNIMPLEMENTED();
+ return 0;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+template <typename T, typename M>
+GLint FindMaxSize(const std::vector<T> &resources, M member)
+{
+ GLint max = 0;
+ for (const T &resource : resources)
+ {
+ max = std::max(max, clampCast<GLint>((resource.*member).size()));
+ }
+ return max;
+}
+
+GLint QueryProgramInterfaceMaxNameLength(const Program *program, GLenum programInterface)
+{
+ GLint maxNameLength = 0;
+ switch (programInterface)
+ {
+ case GL_PROGRAM_INPUT:
+ maxNameLength = FindMaxSize(program->getAttributes(), &sh::Attribute::name);
+ break;
+
+ case GL_PROGRAM_OUTPUT:
+ maxNameLength =
+ FindMaxSize(program->getState().getOutputVariables(), &sh::OutputVariable::name);
+ break;
+
+ case GL_UNIFORM:
+ maxNameLength = FindMaxSize(program->getState().getUniforms(), &LinkedUniform::name);
+ break;
+
+ case GL_UNIFORM_BLOCK:
+ maxNameLength =
+ FindMaxSize(program->getState().getUniformBlocks(), &InterfaceBlock::name);
+ break;
+
+ case GL_BUFFER_VARIABLE:
+ maxNameLength =
+ FindMaxSize(program->getState().getBufferVariables(), &BufferVariable::name);
+ break;
+
+ case GL_SHADER_STORAGE_BLOCK:
+ maxNameLength =
+ FindMaxSize(program->getState().getShaderStorageBlocks(), &InterfaceBlock::name);
+ break;
+
+ // TODO(jie.a.chen@intel.com): more interfaces.
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ UNIMPLEMENTED();
+ return 0;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+ // This length includes an extra character for the null terminator.
+ return (maxNameLength == 0 ? 0 : maxNameLength + 1);
+}
+
+GLint QueryProgramInterfaceMaxNumActiveVariables(const Program *program, GLenum programInterface)
+{
+ switch (programInterface)
+ {
+ case GL_UNIFORM_BLOCK:
+ return FindMaxSize(program->getState().getUniformBlocks(),
+ &InterfaceBlock::memberIndexes);
+ case GL_ATOMIC_COUNTER_BUFFER:
+ return FindMaxSize(program->getState().getAtomicCounterBuffers(),
+ &AtomicCounterBuffer::memberIndexes);
+
+ case GL_SHADER_STORAGE_BLOCK:
+ return FindMaxSize(program->getState().getShaderStorageBlocks(),
+ &InterfaceBlock::memberIndexes);
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+GLenum GetUniformPropertyEnum(GLenum prop)
+{
+ switch (prop)
+ {
+ case GL_UNIFORM_TYPE:
+ return GL_TYPE;
+ case GL_UNIFORM_SIZE:
+ return GL_ARRAY_SIZE;
+ case GL_UNIFORM_NAME_LENGTH:
+ return GL_NAME_LENGTH;
+ case GL_UNIFORM_BLOCK_INDEX:
+ return GL_BLOCK_INDEX;
+ case GL_UNIFORM_OFFSET:
+ return GL_OFFSET;
+ case GL_UNIFORM_ARRAY_STRIDE:
+ return GL_ARRAY_STRIDE;
+ case GL_UNIFORM_MATRIX_STRIDE:
+ return GL_MATRIX_STRIDE;
+ case GL_UNIFORM_IS_ROW_MAJOR:
+ return GL_IS_ROW_MAJOR;
+
+ default:
+ return prop;
+ }
+}
+
+GLenum GetUniformBlockPropertyEnum(GLenum prop)
+{
+ switch (prop)
+ {
+ case GL_UNIFORM_BLOCK_BINDING:
+ return GL_BUFFER_BINDING;
+
+ case GL_UNIFORM_BLOCK_DATA_SIZE:
+ return GL_BUFFER_DATA_SIZE;
+
+ case GL_UNIFORM_BLOCK_NAME_LENGTH:
+ return GL_NAME_LENGTH;
+
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
+ return GL_NUM_ACTIVE_VARIABLES;
+
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
+ return GL_ACTIVE_VARIABLES;
+
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
+ return GL_REFERENCED_BY_VERTEX_SHADER;
+
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
+ return GL_REFERENCED_BY_FRAGMENT_SHADER;
+
+ default:
+ return prop;
+ }
+}
+
+void GetShaderVariableBufferResourceProperty(const ShaderVariableBuffer &buffer,
+ GLenum pname,
+ GLint *params,
+ GLsizei bufSize,
+ GLsizei *outputPosition)
+
+{
+ switch (pname)
+ {
+ case GL_BUFFER_BINDING:
+ params[(*outputPosition)++] = buffer.binding;
+ break;
+ case GL_BUFFER_DATA_SIZE:
+ params[(*outputPosition)++] = clampCast<GLint>(buffer.dataSize);
+ break;
+ case GL_NUM_ACTIVE_VARIABLES:
+ params[(*outputPosition)++] = buffer.numActiveVariables();
+ break;
+ case GL_ACTIVE_VARIABLES:
+ for (size_t memberIndex = 0;
+ memberIndex < buffer.memberIndexes.size() && *outputPosition < bufSize;
+ ++memberIndex)
+ {
+ params[(*outputPosition)++] = clampCast<GLint>(buffer.memberIndexes[memberIndex]);
+ }
+ break;
+ case GL_REFERENCED_BY_VERTEX_SHADER:
+ params[(*outputPosition)++] = static_cast<GLint>(buffer.vertexStaticUse);
+ break;
+ case GL_REFERENCED_BY_FRAGMENT_SHADER:
+ params[(*outputPosition)++] = static_cast<GLint>(buffer.fragmentStaticUse);
+ break;
+ case GL_REFERENCED_BY_COMPUTE_SHADER:
+ params[(*outputPosition)++] = static_cast<GLint>(buffer.computeStaticUse);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void GetInterfaceBlockResourceProperty(const InterfaceBlock &block,
+ GLenum pname,
+ GLint *params,
+ GLsizei bufSize,
+ GLsizei *outputPosition)
+{
+ if (pname == GL_NAME_LENGTH)
+ {
+ params[(*outputPosition)++] = clampCast<GLint>(block.nameWithArrayIndex().size() + 1);
+ return;
+ }
+ GetShaderVariableBufferResourceProperty(block, pname, params, bufSize, outputPosition);
+}
+
+void GetUniformBlockResourceProperty(const Program *program,
+ GLuint blockIndex,
+ GLenum pname,
+ GLint *params,
+ GLsizei bufSize,
+ GLsizei *outputPosition)
+
+{
+ ASSERT(*outputPosition < bufSize);
+ const auto &block = program->getUniformBlockByIndex(blockIndex);
+ GetInterfaceBlockResourceProperty(block, pname, params, bufSize, outputPosition);
+}
+
+void GetShaderStorageBlockResourceProperty(const Program *program,
+ GLuint blockIndex,
+ GLenum pname,
+ GLint *params,
+ GLsizei bufSize,
+ GLsizei *outputPosition)
+
+{
+ ASSERT(*outputPosition < bufSize);
+ const auto &block = program->getShaderStorageBlockByIndex(blockIndex);
+ GetInterfaceBlockResourceProperty(block, pname, params, bufSize, outputPosition);
+}
+
+void GetAtomicCounterBufferResourceProperty(const Program *program,
+ GLuint index,
+ GLenum pname,
+ GLint *params,
+ GLsizei bufSize,
+ GLsizei *outputPosition)
+
+{
+ ASSERT(*outputPosition < bufSize);
+ const auto &buffer = program->getState().getAtomicCounterBuffers()[index];
+ GetShaderVariableBufferResourceProperty(buffer, pname, params, bufSize, outputPosition);
+}
+
+} // anonymous namespace
+
+void QueryFramebufferAttachmentParameteriv(const Framebuffer *framebuffer,
+ GLenum attachment,
+ GLenum pname,
+ GLint *params)
+{
+ ASSERT(framebuffer);
+
+ const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
+ if (attachmentObject == nullptr)
+ {
+ // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
+ // is NONE, then querying any other pname will generate INVALID_ENUM.
+
+ // ES 3.0.2 spec pg 235 states that if the attachment type is none,
+ // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
+ // INVALID_OPERATION for all other pnames
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
+ *params = GL_NONE;
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+ *params = 0;
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
+ *params = attachmentObject->type();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+ *params = attachmentObject->id();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
+ *params = attachmentObject->mipLevel();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
+ *params = attachmentObject->cubeMapFace();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
+ *params = attachmentObject->getRedSize();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
+ *params = attachmentObject->getGreenSize();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
+ *params = attachmentObject->getBlueSize();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
+ *params = attachmentObject->getAlphaSize();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
+ *params = attachmentObject->getDepthSize();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
+ *params = attachmentObject->getStencilSize();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
+ *params = attachmentObject->getComponentType();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
+ *params = attachmentObject->getColorEncoding();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
+ *params = attachmentObject->layer();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
+ *params = attachmentObject->getNumViews();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
+ *params = static_cast<GLint>(attachmentObject->getMultiviewLayout());
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
+ *params = attachmentObject->getBaseViewIndex();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
+ {
+ const std::vector<Offset> &offsets = attachmentObject->getMultiviewViewportOffsets();
+ for (size_t i = 0u; i < offsets.size(); ++i)
+ {
+ params[i * 2u] = offsets[i].x;
+ params[i * 2u + 1u] = offsets[i].y;
+ }
+ }
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void QueryBufferParameteriv(const Buffer *buffer, GLenum pname, GLint *params)
+{
+ QueryBufferParameterBase(buffer, pname, params);
+}
+
+void QueryBufferParameteri64v(const Buffer *buffer, GLenum pname, GLint64 *params)
+{
+ QueryBufferParameterBase(buffer, pname, params);
+}
+
+void QueryBufferPointerv(const Buffer *buffer, GLenum pname, void **params)
+{
+ switch (pname)
+ {
+ case GL_BUFFER_MAP_POINTER:
+ *params = buffer->getMapPointer();
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void QueryProgramiv(const Context *context, const Program *program, GLenum pname, GLint *params)
+{
+ ASSERT(program != nullptr);
+
+ switch (pname)
+ {
+ case GL_DELETE_STATUS:
+ *params = program->isFlaggedForDeletion();
+ return;
+ case GL_LINK_STATUS:
+ *params = program->isLinked();
+ return;
+ case GL_VALIDATE_STATUS:
+ *params = program->isValidated();
+ return;
+ case GL_INFO_LOG_LENGTH:
+ *params = program->getInfoLogLength();
+ return;
+ case GL_ATTACHED_SHADERS:
+ *params = program->getAttachedShadersCount();
+ return;
+ case GL_ACTIVE_ATTRIBUTES:
+ *params = program->getActiveAttributeCount();
+ return;
+ case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
+ *params = program->getActiveAttributeMaxLength();
+ return;
+ case GL_ACTIVE_UNIFORMS:
+ *params = program->getActiveUniformCount();
+ return;
+ case GL_ACTIVE_UNIFORM_MAX_LENGTH:
+ *params = program->getActiveUniformMaxLength();
+ return;
+ case GL_PROGRAM_BINARY_LENGTH_OES:
+ *params = program->getBinaryLength(context);
+ return;
+ case GL_ACTIVE_UNIFORM_BLOCKS:
+ *params = program->getActiveUniformBlockCount();
+ return;
+ case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
+ *params = program->getActiveUniformBlockMaxLength();
+ break;
+ case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
+ *params = program->getTransformFeedbackBufferMode();
+ break;
+ case GL_TRANSFORM_FEEDBACK_VARYINGS:
+ *params = program->getTransformFeedbackVaryingCount();
+ break;
+ case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
+ *params = program->getTransformFeedbackVaryingMaxLength();
+ break;
+ case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
+ *params = program->getBinaryRetrievableHint();
+ break;
+ case GL_PROGRAM_SEPARABLE:
+ *params = program->isSeparable();
+ break;
+ case GL_COMPUTE_WORK_GROUP_SIZE:
+ {
+ const sh::WorkGroupSize &localSize = program->getComputeShaderLocalSize();
+ params[0] = localSize[0];
+ params[1] = localSize[1];
+ params[2] = localSize[2];
+ }
+ break;
+ case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
+ *params = program->getActiveAtomicCounterBufferCount();
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void QueryRenderbufferiv(const Context *context,
+ const Renderbuffer *renderbuffer,
+ GLenum pname,
+ GLint *params)
+{
+ ASSERT(renderbuffer != nullptr);
+
+ switch (pname)
+ {
+ case GL_RENDERBUFFER_WIDTH:
+ *params = renderbuffer->getWidth();
+ break;
+ case GL_RENDERBUFFER_HEIGHT:
+ *params = renderbuffer->getHeight();
+ break;
+ case GL_RENDERBUFFER_INTERNAL_FORMAT:
+ // Special case the WebGL 1 DEPTH_STENCIL format.
+ if (context->isWebGL1() &&
+ renderbuffer->getFormat().info->internalFormat == GL_DEPTH24_STENCIL8)
+ {
+ *params = GL_DEPTH_STENCIL;
+ }
+ else
+ {
+ *params = renderbuffer->getFormat().info->internalFormat;
+ }
+ break;
+ case GL_RENDERBUFFER_RED_SIZE:
+ *params = renderbuffer->getRedSize();
+ break;
+ case GL_RENDERBUFFER_GREEN_SIZE:
+ *params = renderbuffer->getGreenSize();
+ break;
+ case GL_RENDERBUFFER_BLUE_SIZE:
+ *params = renderbuffer->getBlueSize();
+ break;
+ case GL_RENDERBUFFER_ALPHA_SIZE:
+ *params = renderbuffer->getAlphaSize();
+ break;
+ case GL_RENDERBUFFER_DEPTH_SIZE:
+ *params = renderbuffer->getDepthSize();
+ break;
+ case GL_RENDERBUFFER_STENCIL_SIZE:
+ *params = renderbuffer->getStencilSize();
+ break;
+ case GL_RENDERBUFFER_SAMPLES_ANGLE:
+ *params = renderbuffer->getSamples();
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void QueryShaderiv(const Context *context, Shader *shader, GLenum pname, GLint *params)
+{
+ ASSERT(shader != nullptr);
+
+ switch (pname)
+ {
+ case GL_SHADER_TYPE:
+ *params = shader->getType();
+ return;
+ case GL_DELETE_STATUS:
+ *params = shader->isFlaggedForDeletion();
+ return;
+ case GL_COMPILE_STATUS:
+ *params = shader->isCompiled(context) ? GL_TRUE : GL_FALSE;
+ return;
+ case GL_INFO_LOG_LENGTH:
+ *params = shader->getInfoLogLength(context);
+ return;
+ case GL_SHADER_SOURCE_LENGTH:
+ *params = shader->getSourceLength();
+ return;
+ case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
+ *params = shader->getTranslatedSourceWithDebugInfoLength(context);
+ return;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void QueryTexLevelParameterfv(const Texture *texture,
+ GLenum target,
+ GLint level,
+ GLenum pname,
+ GLfloat *params)
+{
+ QueryTexLevelParameterBase(texture, target, level, pname, params);
+}
+
+void QueryTexLevelParameteriv(const Texture *texture,
+ GLenum target,
+ GLint level,
+ GLenum pname,
+ GLint *params)
+{
+ QueryTexLevelParameterBase(texture, target, level, pname, params);
+}
+
+void QueryTexParameterfv(const Texture *texture, GLenum pname, GLfloat *params)
+{
+ QueryTexParameterBase(texture, pname, params);
+}
+
+void QueryTexParameteriv(const Texture *texture, GLenum pname, GLint *params)
+{
+ QueryTexParameterBase(texture, pname, params);
+}
+
+void QuerySamplerParameterfv(const Sampler *sampler, GLenum pname, GLfloat *params)
+{
+ QuerySamplerParameterBase(sampler, pname, params);
+}
+
+void QuerySamplerParameteriv(const Sampler *sampler, GLenum pname, GLint *params)
+{
+ QuerySamplerParameterBase(sampler, pname, params);
+}
+
+void QueryVertexAttribfv(const VertexAttribute &attrib,
+ const VertexBinding &binding,
+ const VertexAttribCurrentValueData &currentValueData,
+ GLenum pname,
+ GLfloat *params)
+{
+ QueryVertexAttribBase(attrib, binding, currentValueData.FloatValues, pname, params);
+}
+
+void QueryVertexAttribiv(const VertexAttribute &attrib,
+ const VertexBinding &binding,
+ const VertexAttribCurrentValueData &currentValueData,
+ GLenum pname,
+ GLint *params)
+{
+ QueryVertexAttribBase(attrib, binding, currentValueData.FloatValues, pname, params);
+}
+
+void QueryVertexAttribPointerv(const VertexAttribute &attrib, GLenum pname, void **pointer)
+{
+ switch (pname)
+ {
+ case GL_VERTEX_ATTRIB_ARRAY_POINTER:
+ *pointer = const_cast<void *>(attrib.pointer);
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void QueryVertexAttribIiv(const VertexAttribute &attrib,
+ const VertexBinding &binding,
+ const VertexAttribCurrentValueData &currentValueData,
+ GLenum pname,
+ GLint *params)
+{
+ QueryVertexAttribBase(attrib, binding, currentValueData.IntValues, pname, params);
+}
+
+void QueryVertexAttribIuiv(const VertexAttribute &attrib,
+ const VertexBinding &binding,
+ const VertexAttribCurrentValueData &currentValueData,
+ GLenum pname,
+ GLuint *params)
+{
+ QueryVertexAttribBase(attrib, binding, currentValueData.UnsignedIntValues, pname, params);
+}
+
+void QueryActiveUniformBlockiv(const Program *program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLint *params)
+{
+ GLenum prop = GetUniformBlockPropertyEnum(pname);
+ QueryProgramResourceiv(program, GL_UNIFORM_BLOCK, uniformBlockIndex, 1, &prop,
+ std::numeric_limits<GLsizei>::max(), nullptr, params);
+}
+
+void QueryInternalFormativ(const TextureCaps &format, GLenum pname, GLsizei bufSize, GLint *params)
+{
+ switch (pname)
+ {
+ case GL_NUM_SAMPLE_COUNTS:
+ if (bufSize != 0)
+ {
+ *params = clampCast<GLint>(format.sampleCounts.size());
+ }
+ break;
+
+ case GL_SAMPLES:
+ {
+ size_t returnCount = std::min<size_t>(bufSize, format.sampleCounts.size());
+ auto sampleReverseIt = format.sampleCounts.rbegin();
+ for (size_t sampleIndex = 0; sampleIndex < returnCount; ++sampleIndex)
+ {
+ params[sampleIndex] = *sampleReverseIt++;
+ }
+ }
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void QueryFramebufferParameteriv(const Framebuffer *framebuffer, GLenum pname, GLint *params)
+{
+ ASSERT(framebuffer);
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_DEFAULT_WIDTH:
+ *params = framebuffer->getDefaultWidth();
+ break;
+ case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
+ *params = framebuffer->getDefaultHeight();
+ break;
+ case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
+ *params = framebuffer->getDefaultSamples();
+ break;
+ case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
+ *params = ConvertToGLBoolean(framebuffer->getDefaultFixedSampleLocations());
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+Error QuerySynciv(const Sync *sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values)
+{
+ ASSERT(sync);
+
+ // All queries return one value, exit early if the buffer can't fit anything.
+ if (bufSize < 1)
+ {
+ if (length != nullptr)
+ {
+ *length = 0;
+ }
+ return NoError();
+ }
+
+ switch (pname)
+ {
+ case GL_OBJECT_TYPE:
+ *values = clampCast<GLint>(GL_SYNC_FENCE);
+ break;
+ case GL_SYNC_CONDITION:
+ *values = clampCast<GLint>(sync->getCondition());
+ break;
+ case GL_SYNC_FLAGS:
+ *values = clampCast<GLint>(sync->getFlags());
+ break;
+ case GL_SYNC_STATUS:
+ ANGLE_TRY(sync->getStatus(values));
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ if (length != nullptr)
+ {
+ *length = 1;
+ }
+
+ return NoError();
+}
+
+void SetTexParameterf(Context *context, Texture *texture, GLenum pname, GLfloat param)
+{
+ SetTexParameterBase(context, texture, pname, &param);
+}
+
+void SetTexParameterfv(Context *context, Texture *texture, GLenum pname, const GLfloat *params)
+{
+ SetTexParameterBase(context, texture, pname, params);
+}
+
+void SetTexParameteri(Context *context, Texture *texture, GLenum pname, GLint param)
+{
+ SetTexParameterBase(context, texture, pname, &param);
+}
+
+void SetTexParameteriv(Context *context, Texture *texture, GLenum pname, const GLint *params)
+{
+ SetTexParameterBase(context, texture, pname, params);
+}
+
+void SetSamplerParameterf(Sampler *sampler, GLenum pname, GLfloat param)
+{
+ SetSamplerParameterBase(sampler, pname, &param);
+}
+
+void SetSamplerParameterfv(Sampler *sampler, GLenum pname, const GLfloat *params)
+{
+ SetSamplerParameterBase(sampler, pname, params);
+}
+
+void SetSamplerParameteri(Sampler *sampler, GLenum pname, GLint param)
+{
+ SetSamplerParameterBase(sampler, pname, &param);
+}
+
+void SetSamplerParameteriv(Sampler *sampler, GLenum pname, const GLint *params)
+{
+ SetSamplerParameterBase(sampler, pname, params);
+}
+
+void SetFramebufferParameteri(Framebuffer *framebuffer, GLenum pname, GLint param)
+{
+ ASSERT(framebuffer);
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_DEFAULT_WIDTH:
+ framebuffer->setDefaultWidth(param);
+ break;
+ case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
+ framebuffer->setDefaultHeight(param);
+ break;
+ case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
+ framebuffer->setDefaultSamples(param);
+ break;
+ case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
+ framebuffer->setDefaultFixedSampleLocations(ConvertToBool(param));
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void SetProgramParameteri(Program *program, GLenum pname, GLint value)
+{
+ ASSERT(program);
+
+ switch (pname)
+ {
+ case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
+ program->setBinaryRetrievableHint(ConvertToBool(value));
+ break;
+ case GL_PROGRAM_SEPARABLE:
+ program->setSeparable(ConvertToBool(value));
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+GLint GetUniformResourceProperty(const Program *program, GLuint index, const GLenum prop)
+{
+ const auto &uniform = program->getUniformByIndex(index);
+ GLenum resourceProp = GetUniformPropertyEnum(prop);
+ switch (resourceProp)
+ {
+ case GL_TYPE:
+ case GL_ARRAY_SIZE:
+ case GL_NAME_LENGTH:
+ return GetCommonVariableProperty(uniform, resourceProp);
+
+ case GL_LOCATION:
+ return program->getUniformLocation(uniform.name);
+
+ case GL_BLOCK_INDEX:
+ return (uniform.isAtomicCounter() ? -1 : uniform.bufferIndex);
+
+ case GL_OFFSET:
+ return uniform.blockInfo.offset;
+
+ case GL_ARRAY_STRIDE:
+ return uniform.blockInfo.arrayStride;
+
+ case GL_MATRIX_STRIDE:
+ return uniform.blockInfo.matrixStride;
+
+ case GL_IS_ROW_MAJOR:
+ return static_cast<GLint>(uniform.blockInfo.isRowMajorMatrix);
+
+ case GL_REFERENCED_BY_VERTEX_SHADER:
+ return uniform.vertexStaticUse;
+
+ case GL_REFERENCED_BY_FRAGMENT_SHADER:
+ return uniform.fragmentStaticUse;
+
+ case GL_REFERENCED_BY_COMPUTE_SHADER:
+ return uniform.computeStaticUse;
+
+ case GL_ATOMIC_COUNTER_BUFFER_INDEX:
+ return (uniform.isAtomicCounter() ? uniform.bufferIndex : -1);
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+GLint GetBufferVariableResourceProperty(const Program *program, GLuint index, const GLenum prop)
+{
+ const auto &bufferVariable = program->getBufferVariableByIndex(index);
+ switch (prop)
+ {
+ case GL_TYPE:
+ case GL_ARRAY_SIZE:
+ case GL_NAME_LENGTH:
+ return GetCommonVariableProperty(bufferVariable, prop);
+
+ case GL_BLOCK_INDEX:
+ return bufferVariable.bufferIndex;
+
+ case GL_OFFSET:
+ return bufferVariable.blockInfo.offset;
+
+ case GL_ARRAY_STRIDE:
+ return bufferVariable.blockInfo.arrayStride;
+
+ case GL_MATRIX_STRIDE:
+ return bufferVariable.blockInfo.matrixStride;
+
+ case GL_IS_ROW_MAJOR:
+ return static_cast<GLint>(bufferVariable.blockInfo.isRowMajorMatrix);
+
+ case GL_REFERENCED_BY_VERTEX_SHADER:
+ return bufferVariable.vertexStaticUse;
+
+ case GL_REFERENCED_BY_FRAGMENT_SHADER:
+ return bufferVariable.fragmentStaticUse;
+
+ case GL_REFERENCED_BY_COMPUTE_SHADER:
+ return bufferVariable.computeStaticUse;
+
+ case GL_TOP_LEVEL_ARRAY_SIZE:
+ return bufferVariable.topLevelArraySize;
+
+ case GL_TOP_LEVEL_ARRAY_STRIDE:
+ return bufferVariable.blockInfo.topLevelArrayStride;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+GLuint QueryProgramResourceIndex(const Program *program,
+ GLenum programInterface,
+ const GLchar *name)
+{
+ switch (programInterface)
+ {
+ case GL_PROGRAM_INPUT:
+ return program->getInputResourceIndex(name);
+
+ case GL_PROGRAM_OUTPUT:
+ return program->getOutputResourceIndex(name);
+
+ case GL_UNIFORM:
+ return program->getState().getUniformIndexFromName(name);
+
+ case GL_BUFFER_VARIABLE:
+ return program->getState().getBufferVariableIndexFromName(name);
+
+ case GL_SHADER_STORAGE_BLOCK:
+ return program->getShaderStorageBlockIndex(name);
+
+ case GL_UNIFORM_BLOCK:
+ return program->getUniformBlockIndex(name);
+
+ // TODO(jie.a.chen@intel.com): more interfaces.
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ UNIMPLEMENTED();
+ return GL_INVALID_INDEX;
+
+ default:
+ UNREACHABLE();
+ return GL_INVALID_INDEX;
+ }
+}
+
+void QueryProgramResourceName(const Program *program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name)
+{
+ switch (programInterface)
+ {
+ case GL_PROGRAM_INPUT:
+ program->getInputResourceName(index, bufSize, length, name);
+ break;
+
+ case GL_PROGRAM_OUTPUT:
+ program->getOutputResourceName(index, bufSize, length, name);
+ break;
+
+ case GL_UNIFORM:
+ program->getUniformResourceName(index, bufSize, length, name);
+ break;
+
+ case GL_BUFFER_VARIABLE:
+ program->getBufferVariableResourceName(index, bufSize, length, name);
+ break;
+
+ case GL_SHADER_STORAGE_BLOCK:
+ program->getActiveShaderStorageBlockName(index, bufSize, length, name);
+ break;
+
+ case GL_UNIFORM_BLOCK:
+ program->getActiveUniformBlockName(index, bufSize, length, name);
+ break;
+
+ // TODO(jie.a.chen@intel.com): more interfaces.
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ UNIMPLEMENTED();
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+}
+
+GLint QueryProgramResourceLocation(const Program *program,
+ GLenum programInterface,
+ const GLchar *name)
+{
+ switch (programInterface)
+ {
+ case GL_PROGRAM_INPUT:
+ return program->getAttributeLocation(name);
+
+ case GL_PROGRAM_OUTPUT:
+ return program->getFragDataLocation(name);
+
+ case GL_UNIFORM:
+ return program->getUniformLocation(name);
+
+ default:
+ UNREACHABLE();
+ return -1;
+ }
+}
+
+void QueryProgramResourceiv(const Program *program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum *props,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!program->isLinked())
+ {
+ if (length != nullptr)
+ {
+ *length = 0;
+ }
+ return;
+ }
+
+ GLsizei pos = 0;
+ for (GLsizei i = 0; i < propCount; i++)
+ {
+ switch (programInterface)
+ {
+ case GL_PROGRAM_INPUT:
+ params[i] = GetInputResourceProperty(program, index, props[i]);
+ ++pos;
+ break;
+
+ case GL_PROGRAM_OUTPUT:
+ params[i] = GetOutputResourceProperty(program, index, props[i]);
+ ++pos;
+ break;
+
+ case GL_UNIFORM:
+ params[i] = GetUniformResourceProperty(program, index, props[i]);
+ ++pos;
+ break;
+
+ case GL_BUFFER_VARIABLE:
+ params[i] = GetBufferVariableResourceProperty(program, index, props[i]);
+ ++pos;
+ break;
+
+ case GL_UNIFORM_BLOCK:
+ GetUniformBlockResourceProperty(program, index, props[i], params, bufSize, &pos);
+ break;
+
+ case GL_SHADER_STORAGE_BLOCK:
+ GetShaderStorageBlockResourceProperty(program, index, props[i], params, bufSize,
+ &pos);
+ break;
+
+ case GL_ATOMIC_COUNTER_BUFFER:
+ GetAtomicCounterBufferResourceProperty(program, index, props[i], params, bufSize,
+ &pos);
+ break;
+ // TODO(jie.a.chen@intel.com): more interfaces.
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ UNIMPLEMENTED();
+ params[i] = GL_INVALID_VALUE;
+ break;
+
+ default:
+ UNREACHABLE();
+ params[i] = GL_INVALID_VALUE;
+ }
+ if (pos == bufSize)
+ {
+ // Most properties return one value, but GL_ACTIVE_VARIABLES returns an array of values.
+ // This checks not to break buffer bounds for such case.
+ break;
+ }
+ }
+
+ if (length != nullptr)
+ {
+ *length = pos;
+ }
+}
+
+void QueryProgramInterfaceiv(const Program *program,
+ GLenum programInterface,
+ GLenum pname,
+ GLint *params)
+{
+ switch (pname)
+ {
+ case GL_ACTIVE_RESOURCES:
+ *params = QueryProgramInterfaceActiveResources(program, programInterface);
+ break;
+
+ case GL_MAX_NAME_LENGTH:
+ *params = QueryProgramInterfaceMaxNameLength(program, programInterface);
+ break;
+
+ case GL_MAX_NUM_ACTIVE_VARIABLES:
+ *params = QueryProgramInterfaceMaxNumActiveVariables(program, programInterface);
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+}
+
+} // namespace gl
+
+namespace egl
+{
+
+void QueryConfigAttrib(const Config *config, EGLint attribute, EGLint *value)
+{
+ ASSERT(config != nullptr);
+ switch (attribute)
+ {
+ case EGL_BUFFER_SIZE:
+ *value = config->bufferSize;
+ break;
+ case EGL_ALPHA_SIZE:
+ *value = config->alphaSize;
+ break;
+ case EGL_BLUE_SIZE:
+ *value = config->blueSize;
+ break;
+ case EGL_GREEN_SIZE:
+ *value = config->greenSize;
+ break;
+ case EGL_RED_SIZE:
+ *value = config->redSize;
+ break;
+ case EGL_DEPTH_SIZE:
+ *value = config->depthSize;
+ break;
+ case EGL_STENCIL_SIZE:
+ *value = config->stencilSize;
+ break;
+ case EGL_CONFIG_CAVEAT:
+ *value = config->configCaveat;
+ break;
+ case EGL_CONFIG_ID:
+ *value = config->configID;
+ break;
+ case EGL_LEVEL:
+ *value = config->level;
+ break;
+ case EGL_NATIVE_RENDERABLE:
+ *value = config->nativeRenderable;
+ break;
+ case EGL_NATIVE_VISUAL_ID:
+ *value = config->nativeVisualID;
+ break;
+ case EGL_NATIVE_VISUAL_TYPE:
+ *value = config->nativeVisualType;
+ break;
+ case EGL_SAMPLES:
+ *value = config->samples;
+ break;
+ case EGL_SAMPLE_BUFFERS:
+ *value = config->sampleBuffers;
+ break;
+ case EGL_SURFACE_TYPE:
+ *value = config->surfaceType;
+ break;
+ case EGL_TRANSPARENT_TYPE:
+ *value = config->transparentType;
+ break;
+ case EGL_TRANSPARENT_BLUE_VALUE:
+ *value = config->transparentBlueValue;
+ break;
+ case EGL_TRANSPARENT_GREEN_VALUE:
+ *value = config->transparentGreenValue;
+ break;
+ case EGL_TRANSPARENT_RED_VALUE:
+ *value = config->transparentRedValue;
+ break;
+ case EGL_BIND_TO_TEXTURE_RGB:
+ *value = config->bindToTextureRGB;
+ break;
+ case EGL_BIND_TO_TEXTURE_RGBA:
+ *value = config->bindToTextureRGBA;
+ break;
+ case EGL_MIN_SWAP_INTERVAL:
+ *value = config->minSwapInterval;
+ break;
+ case EGL_MAX_SWAP_INTERVAL:
+ *value = config->maxSwapInterval;
+ break;
+ case EGL_LUMINANCE_SIZE:
+ *value = config->luminanceSize;
+ break;
+ case EGL_ALPHA_MASK_SIZE:
+ *value = config->alphaMaskSize;
+ break;
+ case EGL_COLOR_BUFFER_TYPE:
+ *value = config->colorBufferType;
+ break;
+ case EGL_RENDERABLE_TYPE:
+ *value = config->renderableType;
+ break;
+ case EGL_MATCH_NATIVE_PIXMAP:
+ *value = false;
+ UNIMPLEMENTED();
+ break;
+ case EGL_CONFORMANT:
+ *value = config->conformant;
+ break;
+ case EGL_MAX_PBUFFER_WIDTH:
+ *value = config->maxPBufferWidth;
+ break;
+ case EGL_MAX_PBUFFER_HEIGHT:
+ *value = config->maxPBufferHeight;
+ break;
+ case EGL_MAX_PBUFFER_PIXELS:
+ *value = config->maxPBufferPixels;
+ break;
+ case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
+ *value = config->optimalOrientation;
+ break;
+ case EGL_COLOR_COMPONENT_TYPE_EXT:
+ *value = config->colorComponentType;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void QueryContextAttrib(const gl::Context *context, EGLint attribute, EGLint *value)
+{
+ switch (attribute)
+ {
+ case EGL_CONFIG_ID:
+ *value = context->getConfig()->configID;
+ break;
+ case EGL_CONTEXT_CLIENT_TYPE:
+ *value = context->getClientType();
+ break;
+ case EGL_CONTEXT_CLIENT_VERSION:
+ *value = context->getClientMajorVersion();
+ break;
+ case EGL_RENDER_BUFFER:
+ *value = context->getRenderBuffer();
+ break;
+ case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ *value = context->isRobustResourceInitEnabled();
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void QuerySurfaceAttrib(const Surface *surface, EGLint attribute, EGLint *value)
+{
+ switch (attribute)
+ {
+ case EGL_GL_COLORSPACE:
+ *value = surface->getGLColorspace();
+ break;
+ case EGL_VG_ALPHA_FORMAT:
+ *value = surface->getVGAlphaFormat();
+ break;
+ case EGL_VG_COLORSPACE:
+ *value = surface->getVGColorspace();
+ break;
+ case EGL_CONFIG_ID:
+ *value = surface->getConfig()->configID;
+ break;
+ case EGL_HEIGHT:
+ *value = surface->getHeight();
+ break;
+ case EGL_HORIZONTAL_RESOLUTION:
+ *value = surface->getHorizontalResolution();
+ break;
+ case EGL_LARGEST_PBUFFER:
+ // The EGL spec states that value is not written if the surface is not a pbuffer
+ if (surface->getType() == EGL_PBUFFER_BIT)
+ {
+ *value = surface->getLargestPbuffer();
+ }
+ break;
+ case EGL_MIPMAP_TEXTURE:
+ // The EGL spec states that value is not written if the surface is not a pbuffer
+ if (surface->getType() == EGL_PBUFFER_BIT)
+ {
+ *value = surface->getMipmapTexture();
+ }
+ break;
+ case EGL_MIPMAP_LEVEL:
+ // The EGL spec states that value is not written if the surface is not a pbuffer
+ if (surface->getType() == EGL_PBUFFER_BIT)
+ {
+ *value = surface->getMipmapLevel();
+ }
+ break;
+ case EGL_MULTISAMPLE_RESOLVE:
+ *value = surface->getMultisampleResolve();
+ break;
+ case EGL_PIXEL_ASPECT_RATIO:
+ *value = surface->getPixelAspectRatio();
+ break;
+ case EGL_RENDER_BUFFER:
+ *value = surface->getRenderBuffer();
+ break;
+ case EGL_SWAP_BEHAVIOR:
+ *value = surface->getSwapBehavior();
+ break;
+ case EGL_TEXTURE_FORMAT:
+ // The EGL spec states that value is not written if the surface is not a pbuffer
+ if (surface->getType() == EGL_PBUFFER_BIT)
+ {
+ *value = surface->getTextureFormat();
+ }
+ break;
+ case EGL_TEXTURE_TARGET:
+ // The EGL spec states that value is not written if the surface is not a pbuffer
+ if (surface->getType() == EGL_PBUFFER_BIT)
+ {
+ *value = surface->getTextureTarget();
+ }
+ break;
+ case EGL_VERTICAL_RESOLUTION:
+ *value = surface->getVerticalResolution();
+ break;
+ case EGL_WIDTH:
+ *value = surface->getWidth();
+ break;
+ case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
+ *value = surface->isPostSubBufferSupported();
+ break;
+ case EGL_FIXED_SIZE_ANGLE:
+ *value = surface->isFixedSize();
+ break;
+ case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
+ *value = surface->flexibleSurfaceCompatibilityRequested();
+ break;
+ case EGL_SURFACE_ORIENTATION_ANGLE:
+ *value = surface->getOrientation();
+ break;
+ case EGL_DIRECT_COMPOSITION_ANGLE:
+ *value = surface->directComposition();
+ break;
+ case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ *value = surface->isRobustResourceInitEnabled();
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void SetSurfaceAttrib(Surface *surface, EGLint attribute, EGLint value)
+{
+ switch (attribute)
+ {
+ case EGL_MIPMAP_LEVEL:
+ surface->setMipmapLevel(value);
+ break;
+ case EGL_MULTISAMPLE_RESOLVE:
+ surface->setMultisampleResolve(value);
+ break;
+ case EGL_SWAP_BEHAVIOR:
+ surface->setSwapBehavior(value);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+} // namespace egl
diff --git a/src/3rdparty/angle/src/libANGLE/queryutils.h b/src/3rdparty/angle/src/libANGLE/queryutils.h
new file mode 100644
index 0000000000..990cbc169e
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/queryutils.h
@@ -0,0 +1,162 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// queryutils.h: Utilities for querying values from GL objects
+
+#ifndef LIBANGLE_QUERYUTILS_H_
+#define LIBANGLE_QUERYUTILS_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+
+#include <EGL/egl.h>
+
+namespace gl
+{
+class Buffer;
+class Context;
+class Error;
+class Sync;
+class Framebuffer;
+class Program;
+class Renderbuffer;
+class Sampler;
+class Shader;
+class Texture;
+struct TextureCaps;
+struct UniformBlock;
+struct VertexAttribute;
+class VertexBinding;
+struct VertexAttribCurrentValueData;
+
+void QueryFramebufferAttachmentParameteriv(const Framebuffer *framebuffer,
+ GLenum attachment,
+ GLenum pname,
+ GLint *params);
+void QueryBufferParameteriv(const Buffer *buffer, GLenum pname, GLint *params);
+void QueryBufferParameteri64v(const Buffer *buffer, GLenum pname, GLint64 *params);
+void QueryBufferPointerv(const Buffer *buffer, GLenum pname, void **params);
+void QueryProgramiv(const Context *context, const Program *program, GLenum pname, GLint *params);
+void QueryRenderbufferiv(const Context *context,
+ const Renderbuffer *renderbuffer,
+ GLenum pname,
+ GLint *params);
+void QueryShaderiv(const Context *context, Shader *shader, GLenum pname, GLint *params);
+void QueryTexLevelParameterfv(const Texture *texture,
+ GLenum target,
+ GLint level,
+ GLenum pname,
+ GLfloat *params);
+void QueryTexLevelParameteriv(const Texture *texture,
+ GLenum target,
+ GLint level,
+ GLenum pname,
+ GLint *params);
+void QueryTexParameterfv(const Texture *texture, GLenum pname, GLfloat *params);
+void QueryTexParameteriv(const Texture *texture, GLenum pname, GLint *params);
+void QuerySamplerParameterfv(const Sampler *sampler, GLenum pname, GLfloat *params);
+void QuerySamplerParameteriv(const Sampler *sampler, GLenum pname, GLint *params);
+
+// Warning: you should ensure binding really matches attrib.bindingIndex before using the following
+// functions.
+void QueryVertexAttribfv(const VertexAttribute &attrib,
+ const VertexBinding &binding,
+ const VertexAttribCurrentValueData &currentValueData,
+ GLenum pname,
+ GLfloat *params);
+
+void QueryVertexAttribiv(const VertexAttribute &attrib,
+ const VertexBinding &binding,
+ const VertexAttribCurrentValueData &currentValueData,
+ GLenum pname,
+ GLint *params);
+
+void QueryVertexAttribPointerv(const VertexAttribute &attrib, GLenum pname, void **pointer);
+
+void QueryVertexAttribIiv(const VertexAttribute &attrib,
+ const VertexBinding &binding,
+ const VertexAttribCurrentValueData &currentValueData,
+ GLenum pname,
+ GLint *params);
+
+void QueryVertexAttribIuiv(const VertexAttribute &attrib,
+ const VertexBinding &binding,
+ const VertexAttribCurrentValueData &currentValueData,
+ GLenum pname,
+ GLuint *params);
+
+void QueryActiveUniformBlockiv(const Program *program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLint *params);
+
+void QueryInternalFormativ(const TextureCaps &format, GLenum pname, GLsizei bufSize, GLint *params);
+
+void QueryFramebufferParameteriv(const Framebuffer *framebuffer, GLenum pname, GLint *params);
+
+Error QuerySynciv(const Sync *sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+
+void SetTexParameterf(Context *context, Texture *texture, GLenum pname, GLfloat param);
+void SetTexParameterfv(Context *context, Texture *texture, GLenum pname, const GLfloat *params);
+void SetTexParameteri(Context *context, Texture *texture, GLenum pname, GLint param);
+void SetTexParameteriv(Context *context, Texture *texture, GLenum pname, const GLint *params);
+
+void SetSamplerParameterf(Sampler *sampler, GLenum pname, GLfloat param);
+void SetSamplerParameterfv(Sampler *sampler, GLenum pname, const GLfloat *params);
+void SetSamplerParameteri(Sampler *sampler, GLenum pname, GLint param);
+void SetSamplerParameteriv(Sampler *sampler, GLenum pname, const GLint *params);
+
+void SetFramebufferParameteri(Framebuffer *framebuffer, GLenum pname, GLint param);
+
+void SetProgramParameteri(Program *program, GLenum pname, GLint value);
+
+GLint GetUniformResourceProperty(const Program *program, GLuint index, const GLenum prop);
+
+GLuint QueryProgramResourceIndex(const Program *program,
+ GLenum programInterface,
+ const GLchar *name);
+
+void QueryProgramResourceName(const Program *program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name);
+
+GLint QueryProgramResourceLocation(const Program *program,
+ GLenum programInterface,
+ const GLchar *name);
+void QueryProgramResourceiv(const Program *program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum *props,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+
+void QueryProgramInterfaceiv(const Program *program,
+ GLenum programInterface,
+ GLenum pname,
+ GLint *params);
+
+} // namespace gl
+
+namespace egl
+{
+struct Config;
+class Surface;
+
+void QueryConfigAttrib(const Config *config, EGLint attribute, EGLint *value);
+
+void QueryContextAttrib(const gl::Context *context, EGLint attribute, EGLint *value);
+
+void QuerySurfaceAttrib(const Surface *surface, EGLint attribute, EGLint *value);
+void SetSurfaceAttrib(Surface *surface, EGLint attribute, EGLint value);
+
+} // namespace egl
+
+#endif // LIBANGLE_QUERYUTILS_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/BufferImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/BufferImpl.h
index d77f06cf09..f76fcdc8d7 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/BufferImpl.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/BufferImpl.h
@@ -12,31 +12,58 @@
#include "common/angleutils.h"
#include "common/mathutil.h"
#include "libANGLE/Error.h"
+#include "libANGLE/PackedGLEnums.h"
#include <stdint.h>
-namespace rx
+namespace gl
{
+class BufferState;
+class Context;
+}
+namespace rx
+{
class BufferImpl : angle::NonCopyable
{
public:
- virtual ~BufferImpl() { }
+ BufferImpl(const gl::BufferState &state) : mState(state) {}
+ virtual ~BufferImpl() {}
+ virtual void destroy(const gl::Context *context) {}
- virtual gl::Error setData(const void* data, size_t size, GLenum usage) = 0;
- virtual gl::Error setSubData(const void* data, size_t size, size_t offset) = 0;
- virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) = 0;
- virtual gl::Error map(GLenum access, GLvoid **mapPtr) = 0;
- virtual gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) = 0;
- virtual gl::Error unmap(GLboolean *result) = 0;
+ virtual gl::Error setData(const gl::Context *context,
+ gl::BufferBinding target,
+ const void *data,
+ size_t size,
+ gl::BufferUsage usage) = 0;
+ virtual gl::Error setSubData(const gl::Context *context,
+ gl::BufferBinding target,
+ const void *data,
+ size_t size,
+ size_t offset) = 0;
+ virtual gl::Error copySubData(const gl::Context *context,
+ BufferImpl *source,
+ GLintptr sourceOffset,
+ GLintptr destOffset,
+ GLsizeiptr size) = 0;
+ virtual gl::Error map(const gl::Context *context, GLenum access, void **mapPtr) = 0;
+ virtual gl::Error mapRange(const gl::Context *context,
+ size_t offset,
+ size_t length,
+ GLbitfield access,
+ void **mapPtr) = 0;
+ virtual gl::Error unmap(const gl::Context *context, GLboolean *result) = 0;
- virtual gl::Error getIndexRange(GLenum type,
+ virtual gl::Error getIndexRange(const gl::Context *context,
+ GLenum type,
size_t offset,
size_t count,
bool primitiveRestartEnabled,
gl::IndexRange *outRange) = 0;
-};
+ protected:
+ const gl::BufferState &mState;
+};
}
-#endif // LIBANGLE_RENDERER_BUFFERIMPL_H_
+#endif // LIBANGLE_RENDERER_BUFFERIMPL_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/BufferImpl_mock.h b/src/3rdparty/angle/src/libANGLE/renderer/BufferImpl_mock.h
index a6387661ce..5a4e21003c 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/BufferImpl_mock.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/BufferImpl_mock.h
@@ -11,28 +11,38 @@
#include "gmock/gmock.h"
+#include "libANGLE/Buffer.h"
#include "libANGLE/renderer/BufferImpl.h"
namespace rx
{
-
class MockBufferImpl : public BufferImpl
{
public:
+ MockBufferImpl() : BufferImpl(mMockState) {}
~MockBufferImpl() { destructor(); }
- MOCK_METHOD3(setData, gl::Error(const void*, size_t, GLenum));
- MOCK_METHOD3(setSubData, gl::Error(const void*, size_t, size_t));
- MOCK_METHOD4(copySubData, gl::Error(BufferImpl *, GLintptr, GLintptr, GLsizeiptr));
- MOCK_METHOD2(map, gl::Error(GLenum, GLvoid **));
- MOCK_METHOD4(mapRange, gl::Error(size_t, size_t, GLbitfield, GLvoid **));
- MOCK_METHOD1(unmap, gl::Error(GLboolean *result));
-
- MOCK_METHOD5(getIndexRange, gl::Error(GLenum, size_t, size_t, bool, gl::IndexRange *));
+ MOCK_METHOD5(
+ setData,
+ gl::Error(const gl::Context *, gl::BufferBinding, const void *, size_t, gl::BufferUsage));
+ MOCK_METHOD5(setSubData,
+ gl::Error(const gl::Context *, gl::BufferBinding, const void *, size_t, size_t));
+ MOCK_METHOD5(
+ copySubData,
+ gl::Error(const gl::Context *contextImpl, BufferImpl *, GLintptr, GLintptr, GLsizeiptr));
+ MOCK_METHOD3(map, gl::Error(const gl::Context *contextImpl, GLenum, void **));
+ MOCK_METHOD5(mapRange,
+ gl::Error(const gl::Context *contextImpl, size_t, size_t, GLbitfield, void **));
+ MOCK_METHOD2(unmap, gl::Error(const gl::Context *contextImpl, GLboolean *result));
+
+ MOCK_METHOD6(getIndexRange,
+ gl::Error(const gl::Context *, GLenum, size_t, size_t, bool, gl::IndexRange *));
MOCK_METHOD0(destructor, void());
-};
+ protected:
+ gl::BufferState mMockState;
+};
}
-#endif // LIBANGLE_RENDERER_BUFFERIMPLMOCK_H_
+#endif // LIBANGLE_RENDERER_BUFFERIMPLMOCK_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/ContextImpl.cpp b/src/3rdparty/angle/src/libANGLE/renderer/ContextImpl.cpp
new file mode 100644
index 0000000000..8d3df291d3
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/ContextImpl.cpp
@@ -0,0 +1,119 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ContextImpl:
+// Implementation-specific functionality associated with a GL Context.
+//
+
+#include "libANGLE/renderer/ContextImpl.h"
+
+namespace rx
+{
+
+ContextImpl::ContextImpl(const gl::ContextState &state)
+ : mState(state), mMemoryProgramCache(nullptr)
+{
+}
+
+ContextImpl::~ContextImpl()
+{
+}
+
+void ContextImpl::stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask)
+{
+ UNREACHABLE();
+}
+
+void ContextImpl::stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask)
+{
+ UNREACHABLE();
+}
+
+void ContextImpl::coverFillPath(const gl::Path *path, GLenum coverMode)
+{
+ UNREACHABLE();
+}
+
+void ContextImpl::coverStrokePath(const gl::Path *path, GLenum coverMode)
+{
+ UNREACHABLE();
+}
+
+void ContextImpl::stencilThenCoverFillPath(const gl::Path *path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode)
+{
+ UNREACHABLE();
+}
+
+void ContextImpl::stencilThenCoverStrokePath(const gl::Path *path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode)
+{
+ UNREACHABLE();
+}
+
+void ContextImpl::coverFillPathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ UNREACHABLE();
+}
+
+void ContextImpl::coverStrokePathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ UNREACHABLE();
+}
+
+void ContextImpl::stencilFillPathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ UNREACHABLE();
+}
+
+void ContextImpl::stencilStrokePathInstanced(const std::vector<gl::Path *> &paths,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ UNREACHABLE();
+}
+
+void ContextImpl::stencilThenCoverFillPathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ UNREACHABLE();
+}
+
+void ContextImpl::stencilThenCoverStrokePathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ UNREACHABLE();
+}
+
+void ContextImpl::setMemoryProgramCache(gl::MemoryProgramCache *memoryProgramCache)
+{
+ mMemoryProgramCache = memoryProgramCache;
+}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/ContextImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/ContextImpl.h
new file mode 100644
index 0000000000..7ba4b5ad2d
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/ContextImpl.h
@@ -0,0 +1,186 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ContextImpl:
+// Implementation-specific functionality associated with a GL Context.
+//
+
+#ifndef LIBANGLE_RENDERER_CONTEXTIMPL_H_
+#define LIBANGLE_RENDERER_CONTEXTIMPL_H_
+
+#include <vector>
+
+#include "common/angleutils.h"
+#include "libANGLE/ContextState.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+
+namespace gl
+{
+class MemoryProgramCache;
+class Path;
+struct Workarounds;
+}
+
+namespace rx
+{
+class ContextImpl : public GLImplFactory
+{
+ public:
+ ContextImpl(const gl::ContextState &state);
+ ~ContextImpl() override;
+
+ virtual void onDestroy(const gl::Context *context) {}
+
+ virtual gl::Error initialize() = 0;
+
+ // Flush and finish.
+ virtual gl::Error flush(const gl::Context *context) = 0;
+ virtual gl::Error finish(const gl::Context *context) = 0;
+
+ // Drawing methods.
+ virtual gl::Error drawArrays(const gl::Context *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count) = 0;
+ virtual gl::Error drawArraysInstanced(const gl::Context *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount) = 0;
+
+ virtual gl::Error drawElements(const gl::Context *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices) = 0;
+ virtual gl::Error drawElementsInstanced(const gl::Context *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei instances) = 0;
+ virtual gl::Error drawRangeElements(const gl::Context *context,
+ GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const void *indices) = 0;
+
+ virtual gl::Error drawArraysIndirect(const gl::Context *context,
+ GLenum mode,
+ const void *indirect) = 0;
+ virtual gl::Error drawElementsIndirect(const gl::Context *context,
+ GLenum mode,
+ GLenum type,
+ const void *indirect) = 0;
+
+ // CHROMIUM_path_rendering path drawing methods.
+ virtual void stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask);
+ virtual void stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask);
+ virtual void coverFillPath(const gl::Path *path, GLenum coverMode);
+ virtual void coverStrokePath(const gl::Path *path, GLenum coverMode);
+ virtual void stencilThenCoverFillPath(const gl::Path *path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode);
+
+ virtual void stencilThenCoverStrokePath(const gl::Path *path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode);
+
+ virtual void coverFillPathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ virtual void coverStrokePathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ virtual void stencilFillPathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ virtual void stencilStrokePathInstanced(const std::vector<gl::Path *> &paths,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ virtual void stencilThenCoverFillPathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ virtual void stencilThenCoverStrokePathInstanced(const std::vector<gl::Path *> &paths,
+ GLenum coverMode,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+
+ // Device loss
+ virtual GLenum getResetStatus() = 0;
+
+ // Vendor and description strings.
+ virtual std::string getVendorString() const = 0;
+ virtual std::string getRendererDescription() const = 0;
+
+ // EXT_debug_marker
+ virtual void insertEventMarker(GLsizei length, const char *marker) = 0;
+ virtual void pushGroupMarker(GLsizei length, const char *marker) = 0;
+ virtual void popGroupMarker() = 0;
+
+ // KHR_debug
+ virtual void pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message) = 0;
+ virtual void popDebugGroup() = 0;
+
+ // State sync with dirty bits.
+ virtual void syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits) = 0;
+
+ // Disjoint timer queries
+ virtual GLint getGPUDisjoint() = 0;
+ virtual GLint64 getTimestamp() = 0;
+
+ // Context switching
+ virtual void onMakeCurrent(const gl::Context *context) = 0;
+
+ // Native capabilities, unmodified by gl::Context.
+ virtual const gl::Caps &getNativeCaps() const = 0;
+ virtual const gl::TextureCapsMap &getNativeTextureCaps() const = 0;
+ virtual const gl::Extensions &getNativeExtensions() const = 0;
+ virtual const gl::Limitations &getNativeLimitations() const = 0;
+
+ virtual void applyNativeWorkarounds(gl::Workarounds *workarounds) const {}
+
+ virtual gl::Error dispatchCompute(const gl::Context *context,
+ GLuint numGroupsX,
+ GLuint numGroupsY,
+ GLuint numGroupsZ) = 0;
+
+ const gl::ContextState &getContextState() { return mState; }
+ int getClientMajorVersion() const { return mState.getClientMajorVersion(); }
+ int getClientMinorVersion() const { return mState.getClientMinorVersion(); }
+ const gl::State &getGLState() const { return mState.getState(); }
+ const gl::Caps &getCaps() const { return mState.getCaps(); }
+ const gl::TextureCapsMap &getTextureCaps() const { return mState.getTextureCaps(); }
+ const gl::Extensions &getExtensions() const { return mState.getExtensions(); }
+ const gl::Limitations &getLimitations() const { return mState.getLimitations(); }
+
+ // A common GL driver behaviour is to trigger dynamic shader recompilation on a draw call,
+ // based on the current render states. We store a mutable pointer to the program cache so
+ // on draw calls we can store the refreshed shaders in the cache.
+ void setMemoryProgramCache(gl::MemoryProgramCache *memoryProgramCache);
+
+ protected:
+ const gl::ContextState &mState;
+ gl::MemoryProgramCache *mMemoryProgramCache;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_CONTEXTIMPL_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.cpp b/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.cpp
index 8061189f0a..5cc9da96dc 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.cpp
@@ -8,26 +8,20 @@
#include "libANGLE/renderer/DisplayImpl.h"
+#include "libANGLE/Display.h"
#include "libANGLE/Surface.h"
namespace rx
{
-DisplayImpl::DisplayImpl()
- : mExtensionsInitialized(false),
- mCapsInitialized(false)
+DisplayImpl::DisplayImpl(const egl::DisplayState &state)
+ : mState(state), mExtensionsInitialized(false), mCapsInitialized(false)
{
}
DisplayImpl::~DisplayImpl()
{
- ASSERT(mSurfaceSet.empty());
-}
-
-void DisplayImpl::destroySurface(egl::Surface *surface)
-{
- mSurfaceSet.erase(surface);
- surface->onDestroy();
+ ASSERT(mState.surfaceSet.empty());
}
const egl::DisplayExtensions &DisplayImpl::getExtensions() const
@@ -41,6 +35,15 @@ const egl::DisplayExtensions &DisplayImpl::getExtensions() const
return mExtensions;
}
+egl::Error DisplayImpl::validateClientBuffer(const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const
+{
+ UNREACHABLE();
+ return egl::EglBadDisplay() << "DisplayImpl::validateClientBuffer unimplemented.";
+}
+
const egl::Caps &DisplayImpl::getCaps() const
{
if (!mCapsInitialized)
@@ -52,4 +55,4 @@ const egl::Caps &DisplayImpl::getCaps() const
return mCaps;
}
-}
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.h
index 9e38f63370..b1c49d9bc8 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.h
@@ -13,7 +13,9 @@
#include "libANGLE/Caps.h"
#include "libANGLE/Config.h"
#include "libANGLE/Error.h"
-#include "libANGLE/renderer/Renderer.h"
+#include "libANGLE/renderer/EGLImplFactory.h"
+#include "libANGLE/Stream.h"
+#include "libANGLE/Version.h"
#include <set>
#include <vector>
@@ -22,9 +24,11 @@ namespace egl
{
class AttributeMap;
class Display;
+struct DisplayState;
struct Config;
class Surface;
class ImageSibling;
+class Thread;
}
namespace gl
@@ -38,69 +42,43 @@ class SurfaceImpl;
class ImageImpl;
struct ConfigDesc;
class DeviceImpl;
+class StreamProducerImpl;
-class DisplayImpl : angle::NonCopyable
+class DisplayImpl : public EGLImplFactory
{
public:
- DisplayImpl();
- virtual ~DisplayImpl();
+ DisplayImpl(const egl::DisplayState &state);
+ ~DisplayImpl() override;
virtual egl::Error initialize(egl::Display *display) = 0;
virtual void terminate() = 0;
- virtual SurfaceImpl *createWindowSurface(const egl::Config *configuration,
- EGLNativeWindowType window,
- const egl::AttributeMap &attribs) = 0;
- virtual SurfaceImpl *createPbufferSurface(const egl::Config *configuration,
- const egl::AttributeMap &attribs) = 0;
- virtual SurfaceImpl *createPbufferFromClientBuffer(const egl::Config *configuration,
- EGLClientBuffer shareHandle,
- const egl::AttributeMap &attribs) = 0;
- virtual SurfaceImpl *createPixmapSurface(const egl::Config *configuration,
- NativePixmapType nativePixmap,
- const egl::AttributeMap &attribs) = 0;
-
- virtual ImageImpl *createImage(EGLenum target,
- egl::ImageSibling *buffer,
- const egl::AttributeMap &attribs) = 0;
-
- virtual gl::Context *createContext(const egl::Config *config,
- const gl::Context *shareContext,
- const egl::AttributeMap &attribs) = 0;
-
virtual egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) = 0;
- virtual egl::ConfigSet generateConfigs() const = 0;
+ virtual egl::ConfigSet generateConfigs() = 0;
- virtual bool isDeviceLost() const = 0;
virtual bool testDeviceLost() = 0;
- virtual egl::Error restoreLostDevice() = 0;
+ virtual egl::Error restoreLostDevice(const egl::Display *display) = 0;
virtual bool isValidNativeWindow(EGLNativeWindowType window) const = 0;
+ virtual egl::Error validateClientBuffer(const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const;
virtual std::string getVendorString() const = 0;
virtual egl::Error getDevice(DeviceImpl **device) = 0;
- virtual egl::Error waitClient() const = 0;
- virtual egl::Error waitNative(EGLint engine,
- egl::Surface *drawSurface,
- egl::Surface *readSurface) const = 0;
-
+ virtual egl::Error waitClient(const gl::Context *context) const = 0;
+ virtual egl::Error waitNative(const gl::Context *context, EGLint engine) const = 0;
+ virtual gl::Version getMaxSupportedESVersion() const = 0;
const egl::Caps &getCaps() const;
- typedef std::set<egl::Surface*> SurfaceSet;
- const SurfaceSet &getSurfaceSet() const { return mSurfaceSet; }
- SurfaceSet &getSurfaceSet() { return mSurfaceSet; }
-
- void destroySurface(egl::Surface *surface);
-
const egl::DisplayExtensions &getExtensions() const;
protected:
- // Place the surface set here so it can be accessible for handling
- // context loss events. (It is shared between the Display and Impl.)
- SurfaceSet mSurfaceSet;
+ const egl::DisplayState &mState;
private:
virtual void generateExtensions(egl::DisplayExtensions *outExtensions) const = 0;
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/EGLImplFactory.h b/src/3rdparty/angle/src/libANGLE/renderer/EGLImplFactory.h
new file mode 100644
index 0000000000..0433364cd3
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/EGLImplFactory.h
@@ -0,0 +1,68 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// EGLImplFactory.h:
+// Factory interface for EGL Impl objects.
+//
+
+#ifndef LIBANGLE_RENDERER_EGLIMPLFACTORY_H_
+#define LIBANGLE_RENDERER_EGLIMPLFACTORY_H_
+
+#include "libANGLE/Stream.h"
+
+namespace egl
+{
+class AttributeMap;
+struct Config;
+class ImageSibling;
+struct ImageState;
+struct SurfaceState;
+}
+
+namespace gl
+{
+class Context;
+class ContextState;
+}
+
+namespace rx
+{
+class ContextImpl;
+class ImageImpl;
+class SurfaceImpl;
+
+class EGLImplFactory : angle::NonCopyable
+{
+ public:
+ EGLImplFactory() {}
+ virtual ~EGLImplFactory() {}
+
+ virtual SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs) = 0;
+ virtual SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+ const egl::AttributeMap &attribs) = 0;
+ virtual SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) = 0;
+ virtual SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs) = 0;
+
+ virtual ImageImpl *createImage(const egl::ImageState &state,
+ EGLenum target,
+ const egl::AttributeMap &attribs) = 0;
+
+ virtual ContextImpl *createContext(const gl::ContextState &state) = 0;
+
+ virtual StreamProducerImpl *createStreamProducerD3DTextureNV12(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs) = 0;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_EGLIMPLFACTORY_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/FenceSyncImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/FenceSyncImpl.h
deleted file mode 100644
index 6b78e69d47..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/FenceSyncImpl.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// FenceSyncImpl.h: Defines the rx::FenceSyncImpl class.
-
-#ifndef LIBANGLE_RENDERER_FENCESYNCIMPL_H_
-#define LIBANGLE_RENDERER_FENCESYNCIMPL_H_
-
-#include "libANGLE/Error.h"
-
-#include "common/angleutils.h"
-
-#include "angle_gl.h"
-
-namespace rx
-{
-
-class FenceSyncImpl : angle::NonCopyable
-{
- public:
- FenceSyncImpl() { };
- virtual ~FenceSyncImpl() { };
-
- virtual gl::Error set(GLenum condition, GLbitfield flags) = 0;
- virtual gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) = 0;
- virtual gl::Error serverWait(GLbitfield flags, GLuint64 timeout) = 0;
- virtual gl::Error getStatus(GLint *outResult) = 0;
-};
-
-}
-
-#endif // LIBANGLE_RENDERER_FENCESYNCIMPL_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/Format.h b/src/3rdparty/angle/src/libANGLE/renderer/Format.h
new file mode 100644
index 0000000000..66bdace3e9
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/Format.h
@@ -0,0 +1,105 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Format:
+// A universal description of typed GPU storage. Across multiple
+// renderer back-ends, there are common formats and some distinct
+// permutations, this enum encapsulates them all. Formats apply to
+// textures, but could also apply to any typed data.
+
+#ifndef LIBANGLE_RENDERER_FORMAT_H_
+#define LIBANGLE_RENDERER_FORMAT_H_
+
+#include "libANGLE/renderer/renderer_utils.h"
+
+namespace angle
+{
+
+struct Format final : private angle::NonCopyable
+{
+ enum class ID;
+
+ constexpr Format(ID id,
+ GLenum glFormat,
+ GLenum fboFormat,
+ rx::MipGenerationFunction mipGen,
+ const rx::FastCopyFunctionMap &fastCopyFunctions,
+ rx::ColorReadFunction colorRead,
+ rx::ColorWriteFunction colorWrite,
+ GLenum componentType,
+ GLuint redBits,
+ GLuint greenBits,
+ GLuint blueBits,
+ GLuint alphaBits,
+ GLuint depthBits,
+ GLuint stencilBits);
+
+ static const Format &Get(ID id);
+ static ID InternalFormatToID(GLenum internalFormat);
+
+ ID id;
+
+ // The closest matching GL internal format for the storage this format uses. Note that this
+ // may be a different internal format than the one this ANGLE format is used for.
+ GLenum glInternalFormat;
+
+ // The format we should report to the GL layer when querying implementation formats from a FBO.
+ // This might not be the same as the glInternalFormat, since some DXGI formats don't have
+ // matching GL format enums, like BGRA4, BGR5A1 and B5G6R6.
+ GLenum fboImplementationInternalFormat;
+
+ rx::MipGenerationFunction mipGenerationFunction;
+ rx::ColorReadFunction colorReadFunction;
+ rx::ColorWriteFunction colorWriteFunction;
+
+ // A map from a gl::FormatType to a fast pixel copy function for this format.
+ const rx::FastCopyFunctionMap &fastCopyFunctions;
+
+ GLenum componentType;
+
+ GLuint redBits;
+ GLuint greenBits;
+ GLuint blueBits;
+ GLuint alphaBits;
+ GLuint depthBits;
+ GLuint stencilBits;
+};
+
+constexpr Format::Format(ID id,
+ GLenum glFormat,
+ GLenum fboFormat,
+ rx::MipGenerationFunction mipGen,
+ const rx::FastCopyFunctionMap &fastCopyFunctions,
+ rx::ColorReadFunction colorRead,
+ rx::ColorWriteFunction colorWrite,
+ GLenum componentType,
+ GLuint redBits,
+ GLuint greenBits,
+ GLuint blueBits,
+ GLuint alphaBits,
+ GLuint depthBits,
+ GLuint stencilBits)
+ : id(id),
+ glInternalFormat(glFormat),
+ fboImplementationInternalFormat(fboFormat),
+ mipGenerationFunction(mipGen),
+ colorReadFunction(colorRead),
+ colorWriteFunction(colorWrite),
+ fastCopyFunctions(fastCopyFunctions),
+ componentType(componentType),
+ redBits(redBits),
+ greenBits(greenBits),
+ blueBits(blueBits),
+ alphaBits(alphaBits),
+ depthBits(depthBits),
+ stencilBits(stencilBits)
+{
+}
+
+} // namespace angle
+
+#include "libANGLE/renderer/Format_ID_autogen.inl"
+
+#endif // LIBANGLE_RENDERER_FORMAT_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/Format_ID_autogen.inl b/src/3rdparty/angle/src/libANGLE/renderer/Format_ID_autogen.inl
new file mode 100644
index 0000000000..b2cbfb0410
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/Format_ID_autogen.inl
@@ -0,0 +1,147 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_angle_format_table.py using data from angle_format_data.json
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ANGLE format enumeration.
+
+namespace angle
+{
+
+enum class Format::ID
+{
+ NONE,
+ A16_FLOAT,
+ A32_FLOAT,
+ A8_UNORM,
+ ASTC_10x10_SRGB_BLOCK,
+ ASTC_10x10_UNORM_BLOCK,
+ ASTC_10x5_SRGB_BLOCK,
+ ASTC_10x5_UNORM_BLOCK,
+ ASTC_10x6_SRGB_BLOCK,
+ ASTC_10x6_UNORM_BLOCK,
+ ASTC_10x8_SRGB_BLOCK,
+ ASTC_10x8_UNORM_BLOCK,
+ ASTC_12x10_SRGB_BLOCK,
+ ASTC_12x10_UNORM_BLOCK,
+ ASTC_12x12_SRGB_BLOCK,
+ ASTC_12x12_UNORM_BLOCK,
+ ASTC_4x4_SRGB_BLOCK,
+ ASTC_4x4_UNORM_BLOCK,
+ ASTC_5x4_SRGB_BLOCK,
+ ASTC_5x4_UNORM_BLOCK,
+ ASTC_5x5_SRGB_BLOCK,
+ ASTC_5x5_UNORM_BLOCK,
+ ASTC_6x5_SRGB_BLOCK,
+ ASTC_6x5_UNORM_BLOCK,
+ ASTC_6x6_SRGB_BLOCK,
+ ASTC_6x6_UNORM_BLOCK,
+ ASTC_8x5_SRGB_BLOCK,
+ ASTC_8x5_UNORM_BLOCK,
+ ASTC_8x6_SRGB_BLOCK,
+ ASTC_8x6_UNORM_BLOCK,
+ ASTC_8x8_SRGB_BLOCK,
+ ASTC_8x8_UNORM_BLOCK,
+ B4G4R4A4_UNORM,
+ B5G5R5A1_UNORM,
+ B5G6R5_UNORM,
+ B8G8R8A8_UNORM,
+ B8G8R8A8_UNORM_SRGB,
+ B8G8R8X8_UNORM,
+ BC1_RGBA_UNORM_BLOCK,
+ BC1_RGBA_UNORM_SRGB_BLOCK,
+ BC1_RGB_UNORM_BLOCK,
+ BC1_RGB_UNORM_SRGB_BLOCK,
+ BC2_RGBA_UNORM_BLOCK,
+ BC2_RGBA_UNORM_SRGB_BLOCK,
+ BC3_RGBA_UNORM_BLOCK,
+ BC3_RGBA_UNORM_SRGB_BLOCK,
+ D16_UNORM,
+ D24_UNORM,
+ D24_UNORM_S8_UINT,
+ D32_FLOAT,
+ D32_FLOAT_S8X24_UINT,
+ D32_UNORM,
+ EAC_R11G11_SNORM_BLOCK,
+ EAC_R11G11_UNORM_BLOCK,
+ EAC_R11_SNORM_BLOCK,
+ EAC_R11_UNORM_BLOCK,
+ ETC1_LOSSY_DECODE_R8G8B8_UNORM_BLOCK,
+ ETC1_R8G8B8_UNORM_BLOCK,
+ ETC2_R8G8B8A1_SRGB_BLOCK,
+ ETC2_R8G8B8A1_UNORM_BLOCK,
+ ETC2_R8G8B8A8_SRGB_BLOCK,
+ ETC2_R8G8B8A8_UNORM_BLOCK,
+ ETC2_R8G8B8_SRGB_BLOCK,
+ ETC2_R8G8B8_UNORM_BLOCK,
+ L16A16_FLOAT,
+ L16_FLOAT,
+ L32A32_FLOAT,
+ L32_FLOAT,
+ L8A8_UNORM,
+ L8_UNORM,
+ R10G10B10A2_UINT,
+ R10G10B10A2_UNORM,
+ R11G11B10_FLOAT,
+ R16G16B16A16_FLOAT,
+ R16G16B16A16_SINT,
+ R16G16B16A16_SNORM,
+ R16G16B16A16_UINT,
+ R16G16B16A16_UNORM,
+ R16G16B16_FLOAT,
+ R16G16B16_SINT,
+ R16G16B16_SNORM,
+ R16G16B16_UINT,
+ R16G16B16_UNORM,
+ R16G16_FLOAT,
+ R16G16_SINT,
+ R16G16_SNORM,
+ R16G16_UINT,
+ R16G16_UNORM,
+ R16_FLOAT,
+ R16_SINT,
+ R16_SNORM,
+ R16_UINT,
+ R16_UNORM,
+ R32G32B32A32_FLOAT,
+ R32G32B32A32_SINT,
+ R32G32B32A32_UINT,
+ R32G32B32_FLOAT,
+ R32G32B32_SINT,
+ R32G32B32_UINT,
+ R32G32_FLOAT,
+ R32G32_SINT,
+ R32G32_UINT,
+ R32_FLOAT,
+ R32_SINT,
+ R32_UINT,
+ R4G4B4A4_UNORM,
+ R5G5B5A1_UNORM,
+ R5G6B5_UNORM,
+ R8G8B8A8_SINT,
+ R8G8B8A8_SNORM,
+ R8G8B8A8_UINT,
+ R8G8B8A8_UNORM,
+ R8G8B8A8_UNORM_SRGB,
+ R8G8B8_SINT,
+ R8G8B8_SNORM,
+ R8G8B8_UINT,
+ R8G8B8_UNORM,
+ R8G8B8_UNORM_SRGB,
+ R8G8_SINT,
+ R8G8_SNORM,
+ R8G8_UINT,
+ R8G8_UNORM,
+ R8_SINT,
+ R8_SNORM,
+ R8_UINT,
+ R8_UNORM,
+ R9G9B9E5_SHAREDEXP,
+ S8_UINT
+};
+
+constexpr uint32_t kNumANGLEFormats = 128;
+
+} // namespace angle
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/Format_table_autogen.cpp b/src/3rdparty/angle/src/libANGLE/renderer/Format_table_autogen.cpp
new file mode 100644
index 0000000000..ecb3ad231a
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/Format_table_autogen.cpp
@@ -0,0 +1,434 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_angle_format_table.py using data from angle_format_data.json
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ANGLE Format table:
+// Queries for typed format information from the ANGLE format enum.
+
+#include "libANGLE/renderer/Format.h"
+
+#include "image_util/copyimage.h"
+#include "image_util/generatemip.h"
+#include "image_util/loadimage.h"
+
+namespace angle
+{
+
+static constexpr rx::FastCopyFunctionMap::Entry BGRAEntry = {GL_RGBA, GL_UNSIGNED_BYTE,
+ CopyBGRA8ToRGBA8};
+static constexpr rx::FastCopyFunctionMap BGRACopyFunctions = {&BGRAEntry, 1};
+static constexpr rx::FastCopyFunctionMap NoCopyFunctions;
+
+constexpr Format g_formatInfoTable[] = {
+ // clang-format off
+ { Format::ID::NONE, GL_NONE, GL_NONE, nullptr, NoCopyFunctions, nullptr, nullptr, GL_NONE, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::A16_FLOAT, GL_ALPHA16F_EXT, GL_ALPHA16F_EXT, GenerateMip<A16F>, NoCopyFunctions, ReadColor<A16F, GLfloat>, WriteColor<A16F, GLfloat>, GL_FLOAT, 0, 0, 0, 16, 0, 0 },
+ { Format::ID::A32_FLOAT, GL_ALPHA32F_EXT, GL_ALPHA32F_EXT, GenerateMip<A32F>, NoCopyFunctions, ReadColor<A32F, GLfloat>, WriteColor<A32F, GLfloat>, GL_FLOAT, 0, 0, 0, 32, 0, 0 },
+ { Format::ID::A8_UNORM, GL_ALPHA8_EXT, GL_ALPHA8_EXT, GenerateMip<A8>, NoCopyFunctions, ReadColor<A8, GLfloat>, WriteColor<A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 8, 0, 0 },
+ { Format::ID::ASTC_10x10_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_10x10_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_10x10_KHR, GL_COMPRESSED_RGBA_ASTC_10x10_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_10x5_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_10x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_10x5_KHR, GL_COMPRESSED_RGBA_ASTC_10x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_10x6_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_10x6_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_10x6_KHR, GL_COMPRESSED_RGBA_ASTC_10x6_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_10x8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_10x8_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_10x8_KHR, GL_COMPRESSED_RGBA_ASTC_10x8_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_12x10_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_12x10_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_12x10_KHR, GL_COMPRESSED_RGBA_ASTC_12x10_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_12x12_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_12x12_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_12x12_KHR, GL_COMPRESSED_RGBA_ASTC_12x12_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_4x4_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_4x4_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_5x4_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_5x4_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_5x4_KHR, GL_COMPRESSED_RGBA_ASTC_5x4_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_5x5_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_5x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_5x5_KHR, GL_COMPRESSED_RGBA_ASTC_5x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_6x5_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_6x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_6x5_KHR, GL_COMPRESSED_RGBA_ASTC_6x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_6x6_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_6x6_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_6x6_KHR, GL_COMPRESSED_RGBA_ASTC_6x6_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_8x5_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_8x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_8x5_KHR, GL_COMPRESSED_RGBA_ASTC_8x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_8x6_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_8x6_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_8x6_KHR, GL_COMPRESSED_RGBA_ASTC_8x6_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_8x8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::ASTC_8x8_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::B4G4R4A4_UNORM, GL_BGRA4_ANGLEX, GL_RGBA4, GenerateMip<A4R4G4B4>, NoCopyFunctions, ReadColor<A4R4G4B4, GLfloat>, WriteColor<A4R4G4B4, GLfloat>, GL_UNSIGNED_NORMALIZED, 4, 4, 4, 4, 0, 0 },
+ { Format::ID::B5G5R5A1_UNORM, GL_BGR5_A1_ANGLEX, GL_RGB5_A1, GenerateMip<A1R5G5B5>, NoCopyFunctions, ReadColor<A1R5G5B5, GLfloat>, WriteColor<A1R5G5B5, GLfloat>, GL_UNSIGNED_NORMALIZED, 5, 5, 5, 1, 0, 0 },
+ { Format::ID::B5G6R5_UNORM, GL_BGR565_ANGLEX, GL_RGB565, GenerateMip<B5G6R5>, NoCopyFunctions, ReadColor<B5G6R5, GLfloat>, WriteColor<B5G6R5, GLfloat>, GL_UNSIGNED_NORMALIZED, 5, 6, 5, 0, 0, 0 },
+ { Format::ID::B8G8R8A8_UNORM, GL_BGRA8_EXT, GL_BGRA8_EXT, GenerateMip<B8G8R8A8>, BGRACopyFunctions, ReadColor<B8G8R8A8, GLfloat>, WriteColor<B8G8R8A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0 },
+ { Format::ID::B8G8R8A8_UNORM_SRGB, GL_BGRA8_SRGB_ANGLEX, GL_BGRA8_SRGB_ANGLEX, GenerateMip<B8G8R8A8>, NoCopyFunctions, ReadColor<B8G8R8A8, GLfloat>, WriteColor<B8G8R8A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0 },
+ { Format::ID::B8G8R8X8_UNORM, GL_BGRA8_EXT, GL_BGRA8_EXT, GenerateMip<B8G8R8X8>, NoCopyFunctions, ReadColor<B8G8R8X8, GLfloat>, WriteColor<B8G8R8X8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0 },
+ { Format::ID::BC1_RGBA_UNORM_BLOCK, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::BC1_RGBA_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::BC1_RGB_UNORM_BLOCK, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::BC1_RGB_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::BC2_RGBA_UNORM_BLOCK, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::BC2_RGBA_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::BC3_RGBA_UNORM_BLOCK, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::BC3_RGBA_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::D16_UNORM, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT16, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 16, 0 },
+ { Format::ID::D24_UNORM, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT24, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 24, 0 },
+ { Format::ID::D24_UNORM_S8_UINT, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 24, 8 },
+ { Format::ID::D32_FLOAT, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT32F, nullptr, NoCopyFunctions, nullptr, nullptr, GL_FLOAT, 0, 0, 0, 0, 32, 0 },
+ { Format::ID::D32_FLOAT_S8X24_UINT, GL_DEPTH32F_STENCIL8, GL_DEPTH32F_STENCIL8, nullptr, NoCopyFunctions, nullptr, nullptr, GL_FLOAT, 0, 0, 0, 0, 32, 8 },
+ { Format::ID::D32_UNORM, GL_DEPTH_COMPONENT32_OES, GL_DEPTH_COMPONENT32_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 32, 0 },
+ { Format::ID::EAC_R11G11_SNORM_BLOCK, GL_COMPRESSED_SIGNED_RG11_EAC, GL_COMPRESSED_SIGNED_RG11_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_SIGNED_NORMALIZED, 11, 11, 0, 0, 0, 0 },
+ { Format::ID::EAC_R11G11_UNORM_BLOCK, GL_COMPRESSED_RG11_EAC, GL_COMPRESSED_RG11_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 11, 11, 0, 0, 0, 0 },
+ { Format::ID::EAC_R11_SNORM_BLOCK, GL_COMPRESSED_SIGNED_R11_EAC, GL_COMPRESSED_SIGNED_R11_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_SIGNED_NORMALIZED, 11, 0, 0, 0, 0, 0 },
+ { Format::ID::EAC_R11_UNORM_BLOCK, GL_COMPRESSED_R11_EAC, GL_COMPRESSED_R11_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 11, 0, 0, 0, 0, 0 },
+ { Format::ID::ETC1_LOSSY_DECODE_R8G8B8_UNORM_BLOCK, GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0 },
+ { Format::ID::ETC1_R8G8B8_UNORM_BLOCK, GL_ETC1_RGB8_OES, GL_ETC1_RGB8_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0 },
+ { Format::ID::ETC2_R8G8B8A1_SRGB_BLOCK, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 1, 0, 0 },
+ { Format::ID::ETC2_R8G8B8A1_UNORM_BLOCK, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 1, 0, 0 },
+ { Format::ID::ETC2_R8G8B8A8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0 },
+ { Format::ID::ETC2_R8G8B8A8_UNORM_BLOCK, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_COMPRESSED_RGBA8_ETC2_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0 },
+ { Format::ID::ETC2_R8G8B8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ETC2, GL_COMPRESSED_SRGB8_ETC2, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0 },
+ { Format::ID::ETC2_R8G8B8_UNORM_BLOCK, GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_RGB8_ETC2, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0 },
+ { Format::ID::L16A16_FLOAT, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA16F_EXT, GenerateMip<L16A16F>, NoCopyFunctions, ReadColor<L16A16F, GLfloat>, WriteColor<L16A16F, GLfloat>, GL_FLOAT, 0, 0, 0, 16, 0, 0 },
+ { Format::ID::L16_FLOAT, GL_LUMINANCE16F_EXT, GL_LUMINANCE16F_EXT, GenerateMip<L16F>, NoCopyFunctions, ReadColor<L16F, GLfloat>, WriteColor<L16F, GLfloat>, GL_FLOAT, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::L32A32_FLOAT, GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA32F_EXT, GenerateMip<L32A32F>, NoCopyFunctions, ReadColor<L32A32F, GLfloat>, WriteColor<L32A32F, GLfloat>, GL_FLOAT, 0, 0, 0, 32, 0, 0 },
+ { Format::ID::L32_FLOAT, GL_LUMINANCE32F_EXT, GL_LUMINANCE32F_EXT, GenerateMip<L32F>, NoCopyFunctions, ReadColor<L32F, GLfloat>, WriteColor<L32F, GLfloat>, GL_FLOAT, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::L8A8_UNORM, GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE8_ALPHA8_EXT, GenerateMip<L8A8>, NoCopyFunctions, ReadColor<L8A8, GLfloat>, WriteColor<L8A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 8, 0, 0 },
+ { Format::ID::L8_UNORM, GL_LUMINANCE8_EXT, GL_LUMINANCE8_EXT, GenerateMip<L8>, NoCopyFunctions, ReadColor<L8, GLfloat>, WriteColor<L8, GLfloat>, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0 },
+ { Format::ID::R10G10B10A2_UINT, GL_RGB10_A2UI, GL_RGB10_A2UI, GenerateMip<R10G10B10A2>, NoCopyFunctions, ReadColor<R10G10B10A2, GLuint>, WriteColor<R10G10B10A2, GLuint>, GL_UNSIGNED_INT, 10, 10, 10, 2, 0, 0 },
+ { Format::ID::R10G10B10A2_UNORM, GL_RGB10_A2, GL_RGB10_A2, GenerateMip<R10G10B10A2>, NoCopyFunctions, ReadColor<R10G10B10A2, GLfloat>, WriteColor<R10G10B10A2, GLfloat>, GL_UNSIGNED_NORMALIZED, 10, 10, 10, 2, 0, 0 },
+ { Format::ID::R11G11B10_FLOAT, GL_R11F_G11F_B10F, GL_R11F_G11F_B10F, GenerateMip<R11G11B10F>, NoCopyFunctions, ReadColor<R11G11B10F, GLfloat>, WriteColor<R11G11B10F, GLfloat>, GL_FLOAT, 11, 11, 10, 0, 0, 0 },
+ { Format::ID::R16G16B16A16_FLOAT, GL_RGBA16F, GL_RGBA16F, GenerateMip<R16G16B16A16F>, NoCopyFunctions, ReadColor<R16G16B16A16F, GLfloat>, WriteColor<R16G16B16A16F, GLfloat>, GL_FLOAT, 16, 16, 16, 16, 0, 0 },
+ { Format::ID::R16G16B16A16_SINT, GL_RGBA16I, GL_RGBA16I, GenerateMip<R16G16B16A16S>, NoCopyFunctions, ReadColor<R16G16B16A16S, GLint>, WriteColor<R16G16B16A16S, GLint>, GL_INT, 16, 16, 16, 16, 0, 0 },
+ { Format::ID::R16G16B16A16_SNORM, GL_RGBA16_SNORM_EXT, GL_RGBA16_SNORM_EXT, GenerateMip<R16G16B16A16S>, NoCopyFunctions, ReadColor<R16G16B16A16S, GLfloat>, WriteColor<R16G16B16A16S, GLfloat>, GL_SIGNED_NORMALIZED, 16, 16, 16, 16, 0, 0 },
+ { Format::ID::R16G16B16A16_UINT, GL_RGBA16UI, GL_RGBA16UI, GenerateMip<R16G16B16A16>, NoCopyFunctions, ReadColor<R16G16B16A16, GLuint>, WriteColor<R16G16B16A16, GLuint>, GL_UNSIGNED_INT, 16, 16, 16, 16, 0, 0 },
+ { Format::ID::R16G16B16A16_UNORM, GL_RGBA16_EXT, GL_RGBA16_EXT, GenerateMip<R16G16B16A16>, NoCopyFunctions, ReadColor<R16G16B16A16, GLfloat>, WriteColor<R16G16B16A16, GLfloat>, GL_UNSIGNED_NORMALIZED, 16, 16, 16, 16, 0, 0 },
+ { Format::ID::R16G16B16_FLOAT, GL_RGB16F, GL_RGB16F, GenerateMip<R16G16B16F>, NoCopyFunctions, ReadColor<R16G16B16F, GLfloat>, WriteColor<R16G16B16F, GLfloat>, GL_FLOAT, 16, 16, 16, 0, 0, 0 },
+ { Format::ID::R16G16B16_SINT, GL_RGB16I, GL_RGB16I, GenerateMip<R16G16B16S>, NoCopyFunctions, ReadColor<R16G16B16S, GLint>, WriteColor<R16G16B16S, GLint>, GL_INT, 16, 16, 16, 0, 0, 0 },
+ { Format::ID::R16G16B16_SNORM, GL_RGB16_SNORM_EXT, GL_RGB16_SNORM_EXT, GenerateMip<R16G16B16S>, NoCopyFunctions, ReadColor<R16G16B16S, GLfloat>, WriteColor<R16G16B16S, GLfloat>, GL_SIGNED_NORMALIZED, 16, 16, 16, 0, 0, 0 },
+ { Format::ID::R16G16B16_UINT, GL_RGB16UI, GL_RGB16UI, GenerateMip<R16G16B16>, NoCopyFunctions, ReadColor<R16G16B16, GLuint>, WriteColor<R16G16B16, GLuint>, GL_UNSIGNED_INT, 16, 16, 16, 0, 0, 0 },
+ { Format::ID::R16G16B16_UNORM, GL_RGB16_EXT, GL_RGB16_EXT, GenerateMip<R16G16B16>, NoCopyFunctions, ReadColor<R16G16B16, GLfloat>, WriteColor<R16G16B16, GLfloat>, GL_UNSIGNED_NORMALIZED, 16, 16, 16, 0, 0, 0 },
+ { Format::ID::R16G16_FLOAT, GL_RG16F, GL_RG16F, GenerateMip<R16G16F>, NoCopyFunctions, ReadColor<R16G16F, GLfloat>, WriteColor<R16G16F, GLfloat>, GL_FLOAT, 16, 16, 0, 0, 0, 0 },
+ { Format::ID::R16G16_SINT, GL_RG16I, GL_RG16I, GenerateMip<R16G16S>, NoCopyFunctions, ReadColor<R16G16S, GLint>, WriteColor<R16G16S, GLint>, GL_INT, 16, 16, 0, 0, 0, 0 },
+ { Format::ID::R16G16_SNORM, GL_RG16_SNORM_EXT, GL_RG16_SNORM_EXT, GenerateMip<R16G16S>, NoCopyFunctions, ReadColor<R16G16S, GLfloat>, WriteColor<R16G16S, GLfloat>, GL_SIGNED_NORMALIZED, 16, 16, 0, 0, 0, 0 },
+ { Format::ID::R16G16_UINT, GL_RG16UI, GL_RG16UI, GenerateMip<R16G16>, NoCopyFunctions, ReadColor<R16G16, GLuint>, WriteColor<R16G16, GLuint>, GL_UNSIGNED_INT, 16, 16, 0, 0, 0, 0 },
+ { Format::ID::R16G16_UNORM, GL_RG16_EXT, GL_RG16_EXT, GenerateMip<R16G16>, NoCopyFunctions, ReadColor<R16G16, GLfloat>, WriteColor<R16G16, GLfloat>, GL_UNSIGNED_NORMALIZED, 16, 16, 0, 0, 0, 0 },
+ { Format::ID::R16_FLOAT, GL_R16F, GL_R16F, GenerateMip<R16F>, NoCopyFunctions, ReadColor<R16F, GLfloat>, WriteColor<R16F, GLfloat>, GL_FLOAT, 16, 0, 0, 0, 0, 0 },
+ { Format::ID::R16_SINT, GL_R16I, GL_R16I, GenerateMip<R16S>, NoCopyFunctions, ReadColor<R16S, GLint>, WriteColor<R16S, GLint>, GL_INT, 16, 0, 0, 0, 0, 0 },
+ { Format::ID::R16_SNORM, GL_R16_SNORM_EXT, GL_R16_SNORM_EXT, GenerateMip<R16S>, NoCopyFunctions, ReadColor<R16S, GLfloat>, WriteColor<R16S, GLfloat>, GL_SIGNED_NORMALIZED, 16, 0, 0, 0, 0, 0 },
+ { Format::ID::R16_UINT, GL_R16UI, GL_R16UI, GenerateMip<R16>, NoCopyFunctions, ReadColor<R16, GLuint>, WriteColor<R16, GLuint>, GL_UNSIGNED_INT, 16, 0, 0, 0, 0, 0 },
+ { Format::ID::R16_UNORM, GL_R16_EXT, GL_R16_EXT, GenerateMip<R16>, NoCopyFunctions, ReadColor<R16, GLfloat>, WriteColor<R16, GLfloat>, GL_UNSIGNED_NORMALIZED, 16, 0, 0, 0, 0, 0 },
+ { Format::ID::R32G32B32A32_FLOAT, GL_RGBA32F, GL_RGBA32F, GenerateMip<R32G32B32A32F>, NoCopyFunctions, ReadColor<R32G32B32A32F, GLfloat>, WriteColor<R32G32B32A32F, GLfloat>, GL_FLOAT, 32, 32, 32, 32, 0, 0 },
+ { Format::ID::R32G32B32A32_SINT, GL_RGBA32I, GL_RGBA32I, GenerateMip<R32G32B32A32S>, NoCopyFunctions, ReadColor<R32G32B32A32S, GLint>, WriteColor<R32G32B32A32S, GLint>, GL_INT, 32, 32, 32, 32, 0, 0 },
+ { Format::ID::R32G32B32A32_UINT, GL_RGBA32UI, GL_RGBA32UI, GenerateMip<R32G32B32A32>, NoCopyFunctions, ReadColor<R32G32B32A32, GLuint>, WriteColor<R32G32B32A32, GLuint>, GL_UNSIGNED_INT, 32, 32, 32, 32, 0, 0 },
+ { Format::ID::R32G32B32_FLOAT, GL_RGB32F, GL_RGB32F, GenerateMip<R32G32B32F>, NoCopyFunctions, ReadColor<R32G32B32F, GLfloat>, WriteColor<R32G32B32F, GLfloat>, GL_FLOAT, 32, 32, 32, 0, 0, 0 },
+ { Format::ID::R32G32B32_SINT, GL_RGB32I, GL_RGB32I, GenerateMip<R32G32B32S>, NoCopyFunctions, ReadColor<R32G32B32S, GLint>, WriteColor<R32G32B32S, GLint>, GL_INT, 32, 32, 32, 0, 0, 0 },
+ { Format::ID::R32G32B32_UINT, GL_RGB32UI, GL_RGB32UI, GenerateMip<R32G32B32>, NoCopyFunctions, ReadColor<R32G32B32, GLuint>, WriteColor<R32G32B32, GLuint>, GL_UNSIGNED_INT, 32, 32, 32, 0, 0, 0 },
+ { Format::ID::R32G32_FLOAT, GL_RG32F, GL_RG32F, GenerateMip<R32G32F>, NoCopyFunctions, ReadColor<R32G32F, GLfloat>, WriteColor<R32G32F, GLfloat>, GL_FLOAT, 32, 32, 0, 0, 0, 0 },
+ { Format::ID::R32G32_SINT, GL_RG32I, GL_RG32I, GenerateMip<R32G32S>, NoCopyFunctions, ReadColor<R32G32S, GLint>, WriteColor<R32G32S, GLint>, GL_INT, 32, 32, 0, 0, 0, 0 },
+ { Format::ID::R32G32_UINT, GL_RG32UI, GL_RG32UI, GenerateMip<R32G32>, NoCopyFunctions, ReadColor<R32G32, GLuint>, WriteColor<R32G32, GLuint>, GL_UNSIGNED_INT, 32, 32, 0, 0, 0, 0 },
+ { Format::ID::R32_FLOAT, GL_R32F, GL_R32F, GenerateMip<R32F>, NoCopyFunctions, ReadColor<R32F, GLfloat>, WriteColor<R32F, GLfloat>, GL_FLOAT, 32, 0, 0, 0, 0, 0 },
+ { Format::ID::R32_SINT, GL_R32I, GL_R32I, GenerateMip<R32S>, NoCopyFunctions, ReadColor<R32S, GLint>, WriteColor<R32S, GLint>, GL_INT, 32, 0, 0, 0, 0, 0 },
+ { Format::ID::R32_UINT, GL_R32UI, GL_R32UI, GenerateMip<R32>, NoCopyFunctions, ReadColor<R32, GLuint>, WriteColor<R32, GLuint>, GL_UNSIGNED_INT, 32, 0, 0, 0, 0, 0 },
+ { Format::ID::R4G4B4A4_UNORM, GL_RGBA4, GL_RGBA4, GenerateMip<R4G4B4A4>, NoCopyFunctions, ReadColor<R4G4B4A4, GLfloat>, WriteColor<R4G4B4A4, GLfloat>, GL_UNSIGNED_NORMALIZED, 4, 4, 4, 4, 0, 0 },
+ { Format::ID::R5G5B5A1_UNORM, GL_RGB5_A1, GL_RGB5_A1, GenerateMip<R5G5B5A1>, NoCopyFunctions, ReadColor<R5G5B5A1, GLfloat>, WriteColor<R5G5B5A1, GLfloat>, GL_UNSIGNED_NORMALIZED, 5, 5, 5, 1, 0, 0 },
+ { Format::ID::R5G6B5_UNORM, GL_RGB565, GL_RGB565, GenerateMip<R5G6B5>, NoCopyFunctions, ReadColor<R5G6B5, GLfloat>, WriteColor<R5G6B5, GLfloat>, GL_UNSIGNED_NORMALIZED, 5, 6, 5, 0, 0, 0 },
+ { Format::ID::R8G8B8A8_SINT, GL_RGBA8I, GL_RGBA8I, GenerateMip<R8G8B8A8S>, NoCopyFunctions, ReadColor<R8G8B8A8S, GLint>, WriteColor<R8G8B8A8S, GLint>, GL_INT, 8, 8, 8, 8, 0, 0 },
+ { Format::ID::R8G8B8A8_SNORM, GL_RGBA8_SNORM, GL_RGBA8_SNORM, GenerateMip<R8G8B8A8S>, NoCopyFunctions, ReadColor<R8G8B8A8S, GLfloat>, WriteColor<R8G8B8A8S, GLfloat>, GL_SIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0 },
+ { Format::ID::R8G8B8A8_UINT, GL_RGBA8UI, GL_RGBA8UI, GenerateMip<R8G8B8A8>, NoCopyFunctions, ReadColor<R8G8B8A8, GLuint>, WriteColor<R8G8B8A8, GLuint>, GL_UNSIGNED_INT, 8, 8, 8, 8, 0, 0 },
+ { Format::ID::R8G8B8A8_UNORM, GL_RGBA8, GL_RGBA8, GenerateMip<R8G8B8A8>, NoCopyFunctions, ReadColor<R8G8B8A8, GLfloat>, WriteColor<R8G8B8A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0 },
+ { Format::ID::R8G8B8A8_UNORM_SRGB, GL_SRGB8_ALPHA8, GL_SRGB8_ALPHA8, GenerateMip<R8G8B8A8SRGB>, NoCopyFunctions, ReadColor<R8G8B8A8SRGB, GLfloat>, WriteColor<R8G8B8A8SRGB, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0 },
+ { Format::ID::R8G8B8_SINT, GL_RGB8I, GL_RGB8I, GenerateMip<R8G8B8S>, NoCopyFunctions, ReadColor<R8G8B8S, GLint>, WriteColor<R8G8B8S, GLint>, GL_INT, 8, 8, 8, 0, 0, 0 },
+ { Format::ID::R8G8B8_SNORM, GL_RGB8_SNORM, GL_RGB8_SNORM, GenerateMip<R8G8B8S>, NoCopyFunctions, ReadColor<R8G8B8S, GLfloat>, WriteColor<R8G8B8S, GLfloat>, GL_SIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0 },
+ { Format::ID::R8G8B8_UINT, GL_RGB8UI, GL_RGB8UI, GenerateMip<R8G8B8>, NoCopyFunctions, ReadColor<R8G8B8, GLuint>, WriteColor<R8G8B8, GLuint>, GL_UNSIGNED_INT, 8, 8, 8, 0, 0, 0 },
+ { Format::ID::R8G8B8_UNORM, GL_RGB8, GL_RGB8, GenerateMip<R8G8B8>, NoCopyFunctions, ReadColor<R8G8B8, GLfloat>, WriteColor<R8G8B8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0 },
+ { Format::ID::R8G8B8_UNORM_SRGB, GL_SRGB8, GL_SRGB8, GenerateMip<R8G8B8>, NoCopyFunctions, ReadColor<R8G8B8, GLfloat>, WriteColor<R8G8B8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0 },
+ { Format::ID::R8G8_SINT, GL_RG8I, GL_RG8I, GenerateMip<R8G8S>, NoCopyFunctions, ReadColor<R8G8S, GLint>, WriteColor<R8G8S, GLint>, GL_INT, 8, 8, 0, 0, 0, 0 },
+ { Format::ID::R8G8_SNORM, GL_RG8_SNORM, GL_RG8_SNORM, GenerateMip<R8G8S>, NoCopyFunctions, ReadColor<R8G8S, GLfloat>, WriteColor<R8G8S, GLfloat>, GL_SIGNED_NORMALIZED, 8, 8, 0, 0, 0, 0 },
+ { Format::ID::R8G8_UINT, GL_RG8UI, GL_RG8UI, GenerateMip<R8G8>, NoCopyFunctions, ReadColor<R8G8, GLuint>, WriteColor<R8G8, GLuint>, GL_UNSIGNED_INT, 8, 8, 0, 0, 0, 0 },
+ { Format::ID::R8G8_UNORM, GL_RG8, GL_RG8, GenerateMip<R8G8>, NoCopyFunctions, ReadColor<R8G8, GLfloat>, WriteColor<R8G8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 0, 0, 0, 0 },
+ { Format::ID::R8_SINT, GL_R8I, GL_R8I, GenerateMip<R8S>, NoCopyFunctions, ReadColor<R8S, GLint>, WriteColor<R8S, GLint>, GL_INT, 8, 0, 0, 0, 0, 0 },
+ { Format::ID::R8_SNORM, GL_R8_SNORM, GL_R8_SNORM, GenerateMip<R8S>, NoCopyFunctions, ReadColor<R8S, GLfloat>, WriteColor<R8S, GLfloat>, GL_SIGNED_NORMALIZED, 8, 0, 0, 0, 0, 0 },
+ { Format::ID::R8_UINT, GL_R8UI, GL_R8UI, GenerateMip<R8>, NoCopyFunctions, ReadColor<R8, GLuint>, WriteColor<R8, GLuint>, GL_UNSIGNED_INT, 8, 0, 0, 0, 0, 0 },
+ { Format::ID::R8_UNORM, GL_R8, GL_R8, GenerateMip<R8>, NoCopyFunctions, ReadColor<R8, GLfloat>, WriteColor<R8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 0, 0, 0, 0, 0 },
+ { Format::ID::R9G9B9E5_SHAREDEXP, GL_RGB9_E5, GL_RGB9_E5, GenerateMip<R9G9B9E5>, NoCopyFunctions, ReadColor<R9G9B9E5, GLfloat>, WriteColor<R9G9B9E5, GLfloat>, GL_FLOAT, 9, 9, 9, 0, 0, 0 },
+ { Format::ID::S8_UINT, GL_STENCIL_INDEX8, GL_STENCIL_INDEX8, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_INT, 0, 0, 0, 0, 0, 8 },
+ // clang-format on
+};
+
+// static
+Format::ID Format::InternalFormatToID(GLenum internalFormat)
+{
+ switch (internalFormat)
+ {
+ case GL_RGBA16_EXT:
+ return Format::ID::R16G16B16A16_UNORM;
+ case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+ return Format::ID::ETC1_LOSSY_DECODE_R8G8B8_UNORM_BLOCK;
+ case GL_RG8I:
+ return Format::ID::R8G8_SINT;
+ case GL_R16F:
+ return Format::ID::R16_FLOAT;
+ case GL_RGBA8I:
+ return Format::ID::R8G8B8A8_SINT;
+ case GL_RG8UI:
+ return Format::ID::R8G8_UINT;
+ case GL_RGBA8_SNORM:
+ return Format::ID::R8G8B8A8_SNORM;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
+ return Format::ID::ASTC_12x10_SRGB_BLOCK;
+ case GL_RG8_SNORM:
+ return Format::ID::R8G8_SNORM;
+ case GL_BGR565_ANGLEX:
+ return Format::ID::B5G6R5_UNORM;
+ case GL_DEPTH_COMPONENT24:
+ return Format::ID::D24_UNORM;
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ return Format::ID::ETC2_R8G8B8A1_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
+ return Format::ID::ASTC_10x10_UNORM_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
+ return Format::ID::ASTC_8x6_SRGB_BLOCK;
+ case GL_RGB32UI:
+ return Format::ID::R32G32B32_UINT;
+ case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
+ return Format::ID::ASTC_6x5_UNORM_BLOCK;
+ case GL_ALPHA32F_EXT:
+ return Format::ID::A32_FLOAT;
+ case GL_R16UI:
+ return Format::ID::R16_UINT;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
+ return Format::ID::ASTC_5x4_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
+ return Format::ID::ASTC_5x5_SRGB_BLOCK;
+ case GL_COMPRESSED_R11_EAC:
+ return Format::ID::EAC_R11_UNORM_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
+ return Format::ID::ASTC_10x10_SRGB_BLOCK;
+ case GL_RGBA32UI:
+ return Format::ID::R32G32B32A32_UINT;
+ case GL_R8_SNORM:
+ return Format::ID::R8_SNORM;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ return Format::ID::BC1_RGBA_UNORM_SRGB_BLOCK;
+ case GL_LUMINANCE32F_EXT:
+ return Format::ID::L32_FLOAT;
+ case GL_RG16_EXT:
+ return Format::ID::R16G16_UNORM;
+ case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ return Format::ID::ETC2_R8G8B8A1_SRGB_BLOCK;
+ case GL_SRGB8:
+ return Format::ID::R8G8B8_UNORM_SRGB;
+ case GL_LUMINANCE8_ALPHA8_EXT:
+ return Format::ID::L8A8_UNORM;
+ case GL_BGRX8_ANGLEX:
+ return Format::ID::B8G8R8X8_UNORM;
+ case GL_RGB16_SNORM_EXT:
+ return Format::ID::R16G16B16_SNORM;
+ case GL_RGBA8UI:
+ return Format::ID::R8G8B8A8_UINT;
+ case GL_BGRA4_ANGLEX:
+ return Format::ID::B4G4R4A4_UNORM;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+ return Format::ID::ETC2_R8G8B8A8_SRGB_BLOCK;
+ case GL_LUMINANCE8_EXT:
+ return Format::ID::L8_UNORM;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ return Format::ID::BC3_RGBA_UNORM_BLOCK;
+ case GL_R16I:
+ return Format::ID::R16_SINT;
+ case GL_RGB5_A1:
+ return Format::ID::R5G5B5A1_UNORM;
+ case GL_RGB16UI:
+ return Format::ID::R16G16B16_UINT;
+ case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
+ return Format::ID::ASTC_4x4_UNORM_BLOCK;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ return Format::ID::BC2_RGBA_UNORM_SRGB_BLOCK;
+ case GL_R16_SNORM_EXT:
+ return Format::ID::R16_SNORM;
+ case GL_COMPRESSED_RGB8_ETC2:
+ return Format::ID::ETC2_R8G8B8_UNORM_BLOCK;
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ return Format::ID::BC1_RGB_UNORM_SRGB_BLOCK;
+ case GL_RGBA32F:
+ return Format::ID::R32G32B32A32_FLOAT;
+ case GL_RGBA32I:
+ return Format::ID::R32G32B32A32_SINT;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ return Format::ID::BC3_RGBA_UNORM_SRGB_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
+ return Format::ID::ASTC_8x5_UNORM_BLOCK;
+ case GL_RG8:
+ return Format::ID::R8G8_UNORM;
+ case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
+ return Format::ID::ASTC_8x8_UNORM_BLOCK;
+ case GL_RGB10_A2:
+ return Format::ID::R10G10B10A2_UNORM;
+ case GL_COMPRESSED_SIGNED_RG11_EAC:
+ return Format::ID::EAC_R11G11_SNORM_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
+ return Format::ID::ASTC_6x6_SRGB_BLOCK;
+ case GL_DEPTH_COMPONENT16:
+ return Format::ID::D16_UNORM;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
+ return Format::ID::ASTC_10x5_SRGB_BLOCK;
+ case GL_RGB32I:
+ return Format::ID::R32G32B32_SINT;
+ case GL_R8:
+ return Format::ID::R8_UNORM;
+ case GL_RGB32F:
+ return Format::ID::R32G32B32_FLOAT;
+ case GL_R16_EXT:
+ return Format::ID::R16_UNORM;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
+ return Format::ID::ASTC_8x8_SRGB_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
+ return Format::ID::ASTC_10x5_UNORM_BLOCK;
+ case GL_R11F_G11F_B10F:
+ return Format::ID::R11G11B10_FLOAT;
+ case GL_RGB8:
+ return Format::ID::R8G8B8_UNORM;
+ case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
+ return Format::ID::ASTC_5x5_UNORM_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
+ return Format::ID::ASTC_8x5_SRGB_BLOCK;
+ case GL_RGBA16I:
+ return Format::ID::R16G16B16A16_SINT;
+ case GL_R8I:
+ return Format::ID::R8_SINT;
+ case GL_RGB8_SNORM:
+ return Format::ID::R8G8B8_SNORM;
+ case GL_RG32F:
+ return Format::ID::R32G32_FLOAT;
+ case GL_DEPTH_COMPONENT32F:
+ return Format::ID::D32_FLOAT;
+ case GL_RG32I:
+ return Format::ID::R32G32_SINT;
+ case GL_ALPHA8_EXT:
+ return Format::ID::A8_UNORM;
+ case GL_RGB16_EXT:
+ return Format::ID::R16G16B16_UNORM;
+ case GL_BGRA8_EXT:
+ return Format::ID::B8G8R8A8_UNORM;
+ case GL_RG32UI:
+ return Format::ID::R32G32_UINT;
+ case GL_RGBA16UI:
+ return Format::ID::R16G16B16A16_UINT;
+ case GL_COMPRESSED_RGBA8_ETC2_EAC:
+ return Format::ID::ETC2_R8G8B8A8_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ return Format::ID::BC1_RGBA_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
+ return Format::ID::ASTC_10x6_UNORM_BLOCK;
+ case GL_COMPRESSED_SRGB8_ETC2:
+ return Format::ID::ETC2_R8G8B8_SRGB_BLOCK;
+ case GL_BGRA8_SRGB_ANGLEX:
+ return Format::ID::B8G8R8A8_UNORM_SRGB;
+ case GL_DEPTH32F_STENCIL8:
+ return Format::ID::D32_FLOAT_S8X24_UINT;
+ case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
+ return Format::ID::ASTC_6x6_UNORM_BLOCK;
+ case GL_R32UI:
+ return Format::ID::R32_UINT;
+ case GL_BGR5_A1_ANGLEX:
+ return Format::ID::B5G5R5A1_UNORM;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
+ return Format::ID::ASTC_12x12_SRGB_BLOCK;
+ case GL_COMPRESSED_RG11_EAC:
+ return Format::ID::EAC_R11G11_UNORM_BLOCK;
+ case GL_SRGB8_ALPHA8:
+ return Format::ID::R8G8B8A8_UNORM_SRGB;
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ return Format::ID::L16A16_FLOAT;
+ case GL_RGBA:
+ return Format::ID::R8G8B8A8_UNORM;
+ case GL_ETC1_RGB8_OES:
+ return Format::ID::ETC1_R8G8B8_UNORM_BLOCK;
+ case GL_DEPTH24_STENCIL8:
+ return Format::ID::D24_UNORM_S8_UINT;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
+ return Format::ID::ASTC_4x4_SRGB_BLOCK;
+ case GL_RGB16I:
+ return Format::ID::R16G16B16_SINT;
+ case GL_R8UI:
+ return Format::ID::R8_UINT;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
+ return Format::ID::ASTC_10x6_SRGB_BLOCK;
+ case GL_RGBA16F:
+ return Format::ID::R16G16B16A16_FLOAT;
+ case GL_COMPRESSED_SIGNED_R11_EAC:
+ return Format::ID::EAC_R11_SNORM_BLOCK;
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ return Format::ID::BC1_RGB_UNORM_BLOCK;
+ case GL_RGB8I:
+ return Format::ID::R8G8B8_SINT;
+ case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
+ return Format::ID::ASTC_8x6_UNORM_BLOCK;
+ case GL_STENCIL_INDEX8:
+ return Format::ID::S8_UINT;
+ case GL_LUMINANCE_ALPHA32F_EXT:
+ return Format::ID::L32A32_FLOAT;
+ case GL_ALPHA16F_EXT:
+ return Format::ID::A16_FLOAT;
+ case GL_RGB8UI:
+ return Format::ID::R8G8B8_UINT;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
+ return Format::ID::ASTC_10x8_SRGB_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
+ return Format::ID::ASTC_12x10_UNORM_BLOCK;
+ case GL_RGB9_E5:
+ return Format::ID::R9G9B9E5_SHAREDEXP;
+ case GL_RGBA16_SNORM_EXT:
+ return Format::ID::R16G16B16A16_SNORM;
+ case GL_R32I:
+ return Format::ID::R32_SINT;
+ case GL_DEPTH_COMPONENT32_OES:
+ return Format::ID::D32_UNORM;
+ case GL_R32F:
+ return Format::ID::R32_FLOAT;
+ case GL_NONE:
+ return Format::ID::NONE;
+ case GL_RG16F:
+ return Format::ID::R16G16_FLOAT;
+ case GL_RGB:
+ return Format::ID::R8G8B8_UNORM;
+ case GL_RGB565:
+ return Format::ID::R5G6B5_UNORM;
+ case GL_LUMINANCE16F_EXT:
+ return Format::ID::L16_FLOAT;
+ case GL_RG16UI:
+ return Format::ID::R16G16_UINT;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ return Format::ID::BC2_RGBA_UNORM_BLOCK;
+ case GL_RG16I:
+ return Format::ID::R16G16_SINT;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
+ return Format::ID::ASTC_6x5_SRGB_BLOCK;
+ case GL_RG16_SNORM_EXT:
+ return Format::ID::R16G16_SNORM;
+ case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
+ return Format::ID::ASTC_12x12_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
+ return Format::ID::ASTC_5x4_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
+ return Format::ID::ASTC_10x8_UNORM_BLOCK;
+ case GL_RGBA4:
+ return Format::ID::R4G4B4A4_UNORM;
+ case GL_RGBA8:
+ return Format::ID::R8G8B8A8_UNORM;
+ case GL_RGB16F:
+ return Format::ID::R16G16B16_FLOAT;
+ case GL_RGB10_A2UI:
+ return Format::ID::R10G10B10A2_UINT;
+ default:
+ return Format::ID::NONE;
+ }
+}
+
+// static
+const Format &Format::Get(ID id)
+{
+ return g_formatInfoTable[static_cast<size_t>(id)];
+}
+
+} // namespace angle
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.h
new file mode 100644
index 0000000000..056ddc833a
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.h
@@ -0,0 +1,54 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// FramebufferAttachmentObjectImpl.h:
+// Common ancenstor for all implementations of FBO attachable-objects.
+// This means Surfaces, Textures and Renderbuffers.
+//
+
+#ifndef LIBANGLE_RENDERER_FRAMEBUFFER_ATTACHMENT_OBJECT_IMPL_H_
+#define LIBANGLE_RENDERER_FRAMEBUFFER_ATTACHMENT_OBJECT_IMPL_H_
+
+#include "libANGLE/FramebufferAttachment.h"
+
+namespace rx
+{
+
+class FramebufferAttachmentObjectImpl : angle::NonCopyable
+{
+ public:
+ FramebufferAttachmentObjectImpl() {}
+ virtual ~FramebufferAttachmentObjectImpl() {}
+
+ virtual gl::Error getAttachmentRenderTarget(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex,
+ FramebufferAttachmentRenderTarget **rtOut);
+
+ virtual gl::Error initializeContents(const gl::Context *context,
+ const gl::ImageIndex &imageIndex);
+};
+
+inline gl::Error FramebufferAttachmentObjectImpl::getAttachmentRenderTarget(
+ const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex,
+ FramebufferAttachmentRenderTarget **rtOut)
+{
+ UNIMPLEMENTED();
+ return gl::OutOfMemory() << "getAttachmentRenderTarget not supported.";
+}
+
+inline gl::Error FramebufferAttachmentObjectImpl::initializeContents(
+ const gl::Context *context,
+ const gl::ImageIndex &imageIndex)
+{
+ UNIMPLEMENTED();
+ return gl::OutOfMemory() << "initialize not supported.";
+}
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_FRAMEBUFFER_ATTACHMENT_OBJECT_IMPL_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl.h
index 680122d0ed..ebb166ca80 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl.h
@@ -24,53 +24,72 @@ struct Rectangle;
namespace rx
{
+class DisplayImpl;
class FramebufferImpl : angle::NonCopyable
{
public:
- explicit FramebufferImpl(const gl::Framebuffer::Data &data) : mData(data) { }
- virtual ~FramebufferImpl() { }
-
- virtual gl::Error discard(size_t count, const GLenum *attachments) = 0;
- virtual gl::Error invalidate(size_t count, const GLenum *attachments) = 0;
- virtual gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) = 0;
-
- virtual gl::Error clear(const gl::Data &data, GLbitfield mask) = 0;
- virtual gl::Error clearBufferfv(const gl::Data &data,
+ explicit FramebufferImpl(const gl::FramebufferState &state) : mState(state) {}
+ virtual ~FramebufferImpl() {}
+ virtual void destroy(const gl::Context *context) {}
+ virtual void destroyDefault(const egl::Display *display) {}
+
+ virtual gl::Error discard(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments) = 0;
+ virtual gl::Error invalidate(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments) = 0;
+ virtual gl::Error invalidateSub(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments,
+ const gl::Rectangle &area) = 0;
+
+ virtual gl::Error clear(const gl::Context *context, GLbitfield mask) = 0;
+ virtual gl::Error clearBufferfv(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
const GLfloat *values) = 0;
- virtual gl::Error clearBufferuiv(const gl::Data &data,
+ virtual gl::Error clearBufferuiv(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
const GLuint *values) = 0;
- virtual gl::Error clearBufferiv(const gl::Data &data,
+ virtual gl::Error clearBufferiv(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
const GLint *values) = 0;
- virtual gl::Error clearBufferfi(const gl::Data &data,
+ virtual gl::Error clearBufferfi(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
GLfloat depth,
GLint stencil) = 0;
- virtual GLenum getImplementationColorReadFormat() const = 0;
- virtual GLenum getImplementationColorReadType() const = 0;
- virtual gl::Error readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const = 0;
+ virtual GLenum getImplementationColorReadFormat(const gl::Context *context) const = 0;
+ virtual GLenum getImplementationColorReadType(const gl::Context *context) const = 0;
+ virtual gl::Error readPixels(const gl::Context *context,
+ const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ void *pixels) = 0;
- virtual gl::Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
- GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) = 0;
+ virtual gl::Error blit(const gl::Context *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ GLbitfield mask,
+ GLenum filter) = 0;
- virtual bool checkStatus() const = 0;
+ virtual bool checkStatus(const gl::Context *context) const = 0;
- virtual void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) = 0;
+ virtual void syncState(const gl::Context *context,
+ const gl::Framebuffer::DirtyBits &dirtyBits) = 0;
- const gl::Framebuffer::Data &getData() const { return mData; }
+ virtual gl::Error getSamplePosition(size_t index, GLfloat *xy) const = 0;
+
+ const gl::FramebufferState &getState() const { return mState; }
protected:
- const gl::Framebuffer::Data &mData;
+ const gl::FramebufferState &mState;
};
-
}
-#endif // LIBANGLE_RENDERER_FRAMEBUFFERIMPL_H_
+#endif // LIBANGLE_RENDERER_FRAMEBUFFERIMPL_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl_mock.h b/src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl_mock.h
index 57c95342d7..c2d069676e 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl_mock.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl_mock.h
@@ -20,38 +20,39 @@ namespace rx
class MockFramebufferImpl : public rx::FramebufferImpl
{
public:
- MockFramebufferImpl() : rx::FramebufferImpl(gl::Framebuffer::Data()) {}
- virtual ~MockFramebufferImpl() { destroy(); }
-
- MOCK_METHOD2(discard, gl::Error(size_t, const GLenum *));
- MOCK_METHOD2(invalidate, gl::Error(size_t, const GLenum *));
- MOCK_METHOD3(invalidateSub, gl::Error(size_t, const GLenum *, const gl::Rectangle &));
-
- MOCK_METHOD2(clear, gl::Error(const gl::Data &, GLbitfield));
- MOCK_METHOD4(clearBufferfv, gl::Error(const gl::Data &, GLenum, GLint, const GLfloat *));
- MOCK_METHOD4(clearBufferuiv, gl::Error(const gl::Data &, GLenum, GLint, const GLuint *));
- MOCK_METHOD4(clearBufferiv, gl::Error(const gl::Data &, GLenum, GLint, const GLint *));
- MOCK_METHOD5(clearBufferfi, gl::Error(const gl::Data &, GLenum, GLint, GLfloat, GLint));
-
- MOCK_CONST_METHOD0(getImplementationColorReadFormat, GLenum());
- MOCK_CONST_METHOD0(getImplementationColorReadType, GLenum());
- MOCK_CONST_METHOD5(
- readPixels,
- gl::Error(const gl::State &, const gl::Rectangle &, GLenum, GLenum, GLvoid *));
-
- MOCK_METHOD6(blit,
- gl::Error(const gl::State &,
+ MockFramebufferImpl() : rx::FramebufferImpl(gl::FramebufferState()) {}
+ virtual ~MockFramebufferImpl() { destructor(); }
+
+ MOCK_METHOD3(discard, gl::Error(const gl::Context *, size_t, const GLenum *));
+ MOCK_METHOD3(invalidate, gl::Error(const gl::Context *, size_t, const GLenum *));
+ MOCK_METHOD4(invalidateSub,
+ gl::Error(const gl::Context *, size_t, const GLenum *, const gl::Rectangle &));
+
+ MOCK_METHOD2(clear, gl::Error(const gl::Context *, GLbitfield));
+ MOCK_METHOD4(clearBufferfv, gl::Error(const gl::Context *, GLenum, GLint, const GLfloat *));
+ MOCK_METHOD4(clearBufferuiv, gl::Error(const gl::Context *, GLenum, GLint, const GLuint *));
+ MOCK_METHOD4(clearBufferiv, gl::Error(const gl::Context *, GLenum, GLint, const GLint *));
+ MOCK_METHOD5(clearBufferfi, gl::Error(const gl::Context *, GLenum, GLint, GLfloat, GLint));
+
+ MOCK_CONST_METHOD1(getImplementationColorReadFormat, GLenum(const gl::Context *));
+ MOCK_CONST_METHOD1(getImplementationColorReadType, GLenum(const gl::Context *));
+ MOCK_METHOD5(readPixels,
+ gl::Error(const gl::Context *, const gl::Rectangle &, GLenum, GLenum, void *));
+
+ MOCK_CONST_METHOD2(getSamplePosition, gl::Error(size_t, GLfloat *));
+
+ MOCK_METHOD5(blit,
+ gl::Error(const gl::Context *,
const gl::Rectangle &,
const gl::Rectangle &,
GLbitfield,
- GLenum,
- const gl::Framebuffer *));
+ GLenum));
- MOCK_CONST_METHOD0(checkStatus, bool());
+ MOCK_CONST_METHOD1(checkStatus, bool(const gl::Context *));
- MOCK_METHOD1(syncState, void(const gl::Framebuffer::DirtyBits &));
+ MOCK_METHOD2(syncState, void(const gl::Context *, const gl::Framebuffer::DirtyBits &));
- MOCK_METHOD0(destroy, void());
+ MOCK_METHOD0(destructor, void());
};
inline ::testing::NiceMock<MockFramebufferImpl> *MakeFramebufferMock()
@@ -59,10 +60,10 @@ inline ::testing::NiceMock<MockFramebufferImpl> *MakeFramebufferMock()
::testing::NiceMock<MockFramebufferImpl> *framebufferImpl =
new ::testing::NiceMock<MockFramebufferImpl>();
// TODO(jmadill): add ON_CALLS for other returning methods
- ON_CALL(*framebufferImpl, checkStatus()).WillByDefault(::testing::Return(true));
+ ON_CALL(*framebufferImpl, checkStatus(testing::_)).WillByDefault(::testing::Return(true));
// We must mock the destructor since NiceMock doesn't work for destructors.
- EXPECT_CALL(*framebufferImpl, destroy()).Times(1).RetiresOnSaturation();
+ EXPECT_CALL(*framebufferImpl, destructor()).Times(1).RetiresOnSaturation();
return framebufferImpl;
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/GLImplFactory.h b/src/3rdparty/angle/src/libANGLE/renderer/GLImplFactory.h
new file mode 100644
index 0000000000..b9a135f596
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/GLImplFactory.h
@@ -0,0 +1,93 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// GLImplFactory.h:
+// Factory interface for OpenGL ES Impl objects.
+//
+
+#ifndef LIBANGLE_RENDERER_GLIMPLFACTORY_H_
+#define LIBANGLE_RENDERER_GLIMPLFACTORY_H_
+
+#include <vector>
+
+#include "angle_gl.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/ProgramPipeline.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/TransformFeedback.h"
+#include "libANGLE/VertexArray.h"
+
+namespace gl
+{
+class ContextState;
+}
+
+namespace rx
+{
+class BufferImpl;
+class CompilerImpl;
+class ContextImpl;
+class FenceNVImpl;
+class SyncImpl;
+class FramebufferImpl;
+class PathImpl;
+class ProgramImpl;
+class ProgramPipelineImpl;
+class QueryImpl;
+class RenderbufferImpl;
+class SamplerImpl;
+class ShaderImpl;
+class TextureImpl;
+class TransformFeedbackImpl;
+class VertexArrayImpl;
+
+class GLImplFactory : angle::NonCopyable
+{
+ public:
+ GLImplFactory() {}
+ virtual ~GLImplFactory() {}
+
+ // Shader creation
+ virtual CompilerImpl *createCompiler() = 0;
+ virtual ShaderImpl *createShader(const gl::ShaderState &data) = 0;
+ virtual ProgramImpl *createProgram(const gl::ProgramState &data) = 0;
+
+ // Framebuffer creation
+ virtual FramebufferImpl *createFramebuffer(const gl::FramebufferState &data) = 0;
+
+ // Texture creation
+ virtual TextureImpl *createTexture(const gl::TextureState &state) = 0;
+
+ // Renderbuffer creation
+ virtual RenderbufferImpl *createRenderbuffer() = 0;
+
+ // Buffer creation
+ virtual BufferImpl *createBuffer(const gl::BufferState &state) = 0;
+
+ // Vertex Array creation
+ virtual VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data) = 0;
+
+ // Query and Fence creation
+ virtual QueryImpl *createQuery(GLenum type) = 0;
+ virtual FenceNVImpl *createFenceNV() = 0;
+ virtual SyncImpl *createSync() = 0;
+
+ // Transform Feedback creation
+ virtual TransformFeedbackImpl *createTransformFeedback(
+ const gl::TransformFeedbackState &state) = 0;
+
+ // Sampler object creation
+ virtual SamplerImpl *createSampler(const gl::SamplerState &state) = 0;
+
+ // Program Pipeline object creation
+ virtual ProgramPipelineImpl *createProgramPipeline(const gl::ProgramPipelineState &data) = 0;
+
+ virtual std::vector<PathImpl *> createPaths(GLsizei range) = 0;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GLIMPLFACTORY_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/Image.h b/src/3rdparty/angle/src/libANGLE/renderer/Image.h
deleted file mode 100644
index 62d854c9b6..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/Image.h
+++ /dev/null
@@ -1,77 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Image.h: Defines the rx::Image class, an abstract base class for the
-// renderer-specific classes which will define the interface to the underlying
-// surfaces or resources.
-
-#ifndef LIBANGLE_RENDERER_IMAGE_H_
-#define LIBANGLE_RENDERER_IMAGE_H_
-
-#include "common/debug.h"
-#include "libANGLE/Error.h"
-
-#include <GLES2/gl2.h>
-
-namespace gl
-{
-class Framebuffer;
-struct Rectangle;
-struct Extents;
-struct Box;
-struct Offset;
-struct ImageIndex;
-}
-
-namespace rx
-{
-class RendererD3D;
-class RenderTarget;
-class TextureStorage;
-
-class Image
-{
- public:
- Image();
- virtual ~Image() {};
-
- GLsizei getWidth() const { return mWidth; }
- GLsizei getHeight() const { return mHeight; }
- GLsizei getDepth() const { return mDepth; }
- GLenum getInternalFormat() const { return mInternalFormat; }
- GLenum getTarget() const { return mTarget; }
- bool isRenderableFormat() const { return mRenderable; }
-
- void markDirty() {mDirty = true;}
- void markClean() {mDirty = false;}
- virtual bool isDirty() const = 0;
-
- virtual bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) = 0;
-
- virtual gl::Error loadData(const gl::Box &area, GLint unpackAlignment, GLenum type, const void *input) = 0;
- virtual gl::Error loadCompressedData(const gl::Box &area, const void *input) = 0;
-
- virtual gl::Error copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, const gl::Framebuffer *source) = 0;
- virtual gl::Error copy(const gl::Offset &destOffset, const gl::Box &sourceArea,
- const gl::ImageIndex &sourceIndex, TextureStorage *source) = 0;
-
- protected:
- GLsizei mWidth;
- GLsizei mHeight;
- GLsizei mDepth;
- GLenum mInternalFormat;
- bool mRenderable;
- GLenum mTarget;
-
- bool mDirty;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Image);
-};
-
-}
-
-#endif // LIBANGLE_RENDERER_IMAGE_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/ImageImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/ImageImpl.h
index e48f1946a8..79694eaebf 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/ImageImpl.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/ImageImpl.h
@@ -12,21 +12,31 @@
#include "common/angleutils.h"
#include "libANGLE/Error.h"
+namespace gl
+{
+class Context;
+} // namespace gl
+
namespace egl
{
class ImageSibling;
-}
+struct ImageState;
+} // namespace egl
namespace rx
{
class ImageImpl : angle::NonCopyable
{
public:
+ ImageImpl(const egl::ImageState &state) : mState(state) {}
virtual ~ImageImpl() {}
virtual egl::Error initialize() = 0;
- virtual gl::Error orphan(egl::ImageSibling *sibling) = 0;
+ virtual gl::Error orphan(const gl::Context *context, egl::ImageSibling *sibling) = 0;
+
+ protected:
+ const egl::ImageState &mState;
};
-}
+} // namespace rx
#endif // LIBANGLE_RENDERER_IMAGEIMPL_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/ImageImpl_mock.h b/src/3rdparty/angle/src/libANGLE/renderer/ImageImpl_mock.h
index 27fe6a3947..30c0cc2594 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/ImageImpl_mock.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/ImageImpl_mock.h
@@ -18,11 +18,17 @@ namespace rx
class MockImageImpl : public ImageImpl
{
public:
+ MockImageImpl(const egl::ImageState &state,
+ EGLenum /*target*/,
+ const egl::AttributeMap & /*attribs*/)
+ : ImageImpl(state)
+ {
+ }
virtual ~MockImageImpl() { destructor(); }
MOCK_METHOD0(initialize, egl::Error(void));
- MOCK_METHOD1(orphan, gl::Error(egl::ImageSibling *));
+ MOCK_METHOD2(orphan, gl::Error(const gl::Context *, egl::ImageSibling *));
MOCK_METHOD0(destructor, void());
};
-}
+} // namespace rx
#endif // LIBANGLE_RENDERER_IMAGEIMPLMOCK_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/ImplFactory.h b/src/3rdparty/angle/src/libANGLE/renderer/ImplFactory.h
deleted file mode 100644
index b988fcf97f..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/ImplFactory.h
+++ /dev/null
@@ -1,74 +0,0 @@
-//
-// Copyright 2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// ImplFactory.h:
-// Factory interface for Impl objects.
-//
-
-#ifndef LIBANGLE_RENDERER_IMPLFACTORY_H_
-#define LIBANGLE_RENDERER_IMPLFACTORY_H_
-
-#include "libANGLE/Framebuffer.h"
-#include "libANGLE/Program.h"
-#include "libANGLE/Shader.h"
-#include "libANGLE/VertexArray.h"
-
-namespace rx
-{
-class BufferImpl;
-class CompilerImpl;
-class FenceNVImpl;
-class FenceSyncImpl;
-class FramebufferImpl;
-class ProgramImpl;
-class QueryImpl;
-class RenderbufferImpl;
-class SamplerImpl;
-class ShaderImpl;
-class TextureImpl;
-class TransformFeedbackImpl;
-class VertexArrayImpl;
-
-class ImplFactory : angle::NonCopyable
-{
- public:
- ImplFactory() {}
- virtual ~ImplFactory() {}
-
- // Shader creation
- virtual CompilerImpl *createCompiler() = 0;
- virtual ShaderImpl *createShader(const gl::Shader::Data &data) = 0;
- virtual ProgramImpl *createProgram(const gl::Program::Data &data) = 0;
-
- // Framebuffer creation
- virtual FramebufferImpl *createFramebuffer(const gl::Framebuffer::Data &data) = 0;
-
- // Texture creation
- virtual TextureImpl *createTexture(GLenum target) = 0;
-
- // Renderbuffer creation
- virtual RenderbufferImpl *createRenderbuffer() = 0;
-
- // Buffer creation
- virtual BufferImpl *createBuffer() = 0;
-
- // Vertex Array creation
- virtual VertexArrayImpl *createVertexArray(const gl::VertexArray::Data &data) = 0;
-
- // Query and Fence creation
- virtual QueryImpl *createQuery(GLenum type) = 0;
- virtual FenceNVImpl *createFenceNV() = 0;
- virtual FenceSyncImpl *createFenceSync() = 0;
-
- // Transform Feedback creation
- virtual TransformFeedbackImpl *createTransformFeedback() = 0;
-
- // Sampler object creation
- virtual SamplerImpl *createSampler() = 0;
-};
-
-}
-
-#endif // LIBANGLE_RENDERER_IMPLFACTORY_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/PathImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/PathImpl.h
new file mode 100644
index 0000000000..3607f69a2b
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/PathImpl.h
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// PathImpl.h: Defines the Path implementation interface for
+// CHROMIUM_path_rendering path objects.
+
+#ifndef LIBANGLE_RENDERER_PATHIMPL_H_
+#define LIBANGLE_RENDERER_PATHIMPL_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+
+namespace rx
+{
+
+class PathImpl : angle::NonCopyable
+{
+ public:
+ virtual ~PathImpl() {}
+
+ virtual gl::Error setCommands(GLsizei numCommands,
+ const GLubyte *commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const void *coords) = 0;
+
+ virtual void setPathParameter(GLenum pname, GLfloat value) = 0;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_PATHIMPL_H_ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.cpp b/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.cpp
deleted file mode 100644
index 8fbc53768f..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.cpp
+++ /dev/null
@@ -1,152 +0,0 @@
-//
-// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl.
-
-#include "libANGLE/renderer/ProgramImpl.h"
-
-#include "common/utilities.h"
-
-namespace rx
-{
-
-namespace
-{
-
-unsigned int ParseAndStripArrayIndex(std::string* name)
-{
- unsigned int subscript = GL_INVALID_INDEX;
-
- // Strip any trailing array operator and retrieve the subscript
- size_t open = name->find_last_of('[');
- size_t close = name->find_last_of(']');
- if (open != std::string::npos && close == name->length() - 1)
- {
- subscript = atoi(name->substr(open + 1).c_str());
- name->erase(open);
- }
-
- return subscript;
-}
-
-}
-
-LinkResult::LinkResult(bool linkSuccess, const gl::Error &error)
- : linkSuccess(linkSuccess),
- error(error)
-{
-}
-
-ProgramImpl::~ProgramImpl()
-{
- // Ensure that reset was called by the inherited class during destruction
- ASSERT(mUniformIndex.size() == 0);
-}
-
-gl::LinkedUniform *ProgramImpl::getUniformByLocation(GLint location) const
-{
- ASSERT(location >= 0 && static_cast<size_t>(location) < mUniformIndex.size());
- return mUniforms[mUniformIndex[location].index];
-}
-
-gl::LinkedUniform *ProgramImpl::getUniformByName(const std::string &name) const
-{
- for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
- {
- if (mUniforms[uniformIndex]->name == name)
- {
- return mUniforms[uniformIndex];
- }
- }
-
- return NULL;
-}
-
-gl::UniformBlock *ProgramImpl::getUniformBlockByIndex(GLuint blockIndex) const
-{
- ASSERT(blockIndex < mUniformBlocks.size());
- return mUniformBlocks[blockIndex];
-}
-
-GLint ProgramImpl::getUniformLocation(std::string name)
-{
- unsigned int subscript = ParseAndStripArrayIndex(&name);
-
- unsigned int numUniforms = mUniformIndex.size();
- for (unsigned int location = 0; location < numUniforms; location++)
- {
- if (mUniformIndex[location].name == name)
- {
- const int index = mUniformIndex[location].index;
- const bool isArray = mUniforms[index]->isArray();
-
- if ((isArray && mUniformIndex[location].element == subscript) ||
- (subscript == GL_INVALID_INDEX))
- {
- return location;
- }
- }
- }
-
- return -1;
-}
-
-GLuint ProgramImpl::getUniformIndex(std::string name)
-{
- unsigned int subscript = ParseAndStripArrayIndex(&name);
-
- // The app is not allowed to specify array indices other than 0 for arrays of basic types
- if (subscript != 0 && subscript != GL_INVALID_INDEX)
- {
- return GL_INVALID_INDEX;
- }
-
- unsigned int numUniforms = mUniforms.size();
- for (unsigned int index = 0; index < numUniforms; index++)
- {
- if (mUniforms[index]->name == name)
- {
- if (mUniforms[index]->isArray() || subscript == GL_INVALID_INDEX)
- {
- return index;
- }
- }
- }
-
- return GL_INVALID_INDEX;
-}
-
-GLuint ProgramImpl::getUniformBlockIndex(std::string name) const
-{
- unsigned int subscript = ParseAndStripArrayIndex(&name);
-
- unsigned int numUniformBlocks = mUniformBlocks.size();
- for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++)
- {
- const gl::UniformBlock &uniformBlock = *mUniformBlocks[blockIndex];
- if (uniformBlock.name == name)
- {
- const bool arrayElementZero = (subscript == GL_INVALID_INDEX && uniformBlock.elementIndex == 0);
- if (subscript == uniformBlock.elementIndex || arrayElementZero)
- {
- return blockIndex;
- }
- }
- }
-
- return GL_INVALID_INDEX;
-}
-
-void ProgramImpl::reset()
-{
- std::fill(mSemanticIndex, mSemanticIndex + ArraySize(mSemanticIndex), -1);
- SafeDeleteContainer(mUniforms);
- mUniformIndex.clear();
- SafeDeleteContainer(mUniformBlocks);
- mTransformFeedbackLinkedVaryings.clear();
-}
-
-}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.h
index 1e688045a1..2371b2759c 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.h
@@ -14,32 +14,39 @@
#include "libANGLE/Constants.h"
#include "libANGLE/Program.h"
#include "libANGLE/Shader.h"
-#include "libANGLE/renderer/Renderer.h"
#include <map>
-namespace rx
+namespace gl
{
+class Context;
+struct ProgramLinkedResources;
+}
-struct LinkResult
+namespace sh
{
- LinkResult(bool linkSuccess, const gl::Error &error) : linkSuccess(linkSuccess), error(error) {}
-
- bool linkSuccess;
- gl::Error error;
-};
+struct BlockMemberInfo;
+}
+namespace rx
+{
class ProgramImpl : angle::NonCopyable
{
public:
- ProgramImpl(const gl::Program::Data &data) : mData(data) {}
+ ProgramImpl(const gl::ProgramState &state) : mState(state) {}
virtual ~ProgramImpl() {}
+ virtual void destroy(const gl::Context *context) {}
- virtual LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0;
- virtual gl::Error save(gl::BinaryOutputStream *stream) = 0;
+ virtual gl::LinkResult load(const gl::Context *context,
+ gl::InfoLog &infoLog,
+ gl::BinaryInputStream *stream) = 0;
+ virtual void save(const gl::Context *context, gl::BinaryOutputStream *stream) = 0;
virtual void setBinaryRetrievableHint(bool retrievable) = 0;
+ virtual void setSeparable(bool separable) = 0;
- virtual LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) = 0;
+ virtual gl::LinkResult link(const gl::Context *context,
+ const gl::ProgramLinkedResources &resources,
+ gl::InfoLog &infoLog) = 0;
virtual GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) = 0;
virtual void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) = 0;
@@ -64,22 +71,37 @@ class ProgramImpl : angle::NonCopyable
virtual void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
virtual void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0;
+ // Done in the back-end to avoid having to keep a system copy of uniform data.
+ virtual void getUniformfv(const gl::Context *context,
+ GLint location,
+ GLfloat *params) const = 0;
+ virtual void getUniformiv(const gl::Context *context, GLint location, GLint *params) const = 0;
+ virtual void getUniformuiv(const gl::Context *context,
+ GLint location,
+ GLuint *params) const = 0;
+
// TODO: synchronize in syncState when dirty bits exist.
virtual void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) = 0;
- // May only be called after a successful link operation.
- // Return false for inactive blocks.
- virtual bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const = 0;
-
- // May only be called after a successful link operation.
- // Returns false for inactive members.
- virtual bool getUniformBlockMemberInfo(const std::string &memberUniformName,
- sh::BlockMemberInfo *memberInfoOut) const = 0;
+ // CHROMIUM_path_rendering
+ // Set parameters to control fragment shader input variable interpolation
+ virtual void setPathFragmentInputGen(const std::string &inputName,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs) = 0;
+
+ // Implementation-specific method for ignoring unreferenced uniforms. Some implementations may
+ // perform more extensive analysis and ignore some locations that ANGLE doesn't detect as
+ // unreferenced. This method is not required to be overriden by a back-end.
+ virtual void markUnusedUniformLocations(std::vector<gl::VariableLocation> *uniformLocations,
+ std::vector<gl::SamplerBinding> *samplerBindings)
+ {
+ }
protected:
- const gl::Program::Data &mData;
+ const gl::ProgramState &mState;
};
-}
+} // namespace rx
#endif // LIBANGLE_RENDERER_PROGRAMIMPL_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl_mock.h b/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl_mock.h
index d6aa238f64..4717ab8843 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl_mock.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl_mock.h
@@ -12,6 +12,7 @@
#include "gmock/gmock.h"
+#include "libANGLE/ProgramLinkedResources.h"
#include "libANGLE/renderer/ProgramImpl.h"
namespace rx
@@ -20,14 +21,18 @@ namespace rx
class MockProgramImpl : public rx::ProgramImpl
{
public:
- MockProgramImpl() : ProgramImpl(gl::Program::Data()) {}
- virtual ~MockProgramImpl() { destroy(); }
+ MockProgramImpl() : ProgramImpl(gl::ProgramState()) {}
+ virtual ~MockProgramImpl() { destructor(); }
- MOCK_METHOD2(load, LinkResult(gl::InfoLog &, gl::BinaryInputStream *));
- MOCK_METHOD1(save, gl::Error(gl::BinaryOutputStream *));
+ MOCK_METHOD3(load, gl::LinkResult(const gl::Context *, gl::InfoLog &, gl::BinaryInputStream *));
+ MOCK_METHOD2(save, void(const gl::Context *, gl::BinaryOutputStream *));
MOCK_METHOD1(setBinaryRetrievableHint, void(bool));
+ MOCK_METHOD1(setSeparable, void(bool));
- MOCK_METHOD2(link, LinkResult(const gl::Data &, gl::InfoLog &));
+ MOCK_METHOD3(link,
+ gl::LinkResult(const gl::Context *,
+ const gl::ProgramLinkedResources &,
+ gl::InfoLog &));
MOCK_METHOD2(validate, GLboolean(const gl::Caps &, gl::InfoLog *));
MOCK_METHOD3(setUniform1fv, void(GLint, GLsizei, const GLfloat *));
@@ -53,11 +58,15 @@ class MockProgramImpl : public rx::ProgramImpl
MOCK_METHOD4(setUniformMatrix3x4fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
MOCK_METHOD4(setUniformMatrix4x3fv, void(GLint, GLsizei, GLboolean, const GLfloat *));
+ MOCK_CONST_METHOD3(getUniformfv, void(const gl::Context *, GLint, GLfloat *));
+ MOCK_CONST_METHOD3(getUniformiv, void(const gl::Context *, GLint, GLint *));
+ MOCK_CONST_METHOD3(getUniformuiv, void(const gl::Context *, GLint, GLuint *));
+
MOCK_METHOD2(setUniformBlockBinding, void(GLuint, GLuint));
- MOCK_CONST_METHOD2(getUniformBlockSize, bool(const std::string &, size_t *));
- MOCK_CONST_METHOD2(getUniformBlockMemberInfo, bool(const std::string &, sh::BlockMemberInfo *));
+ MOCK_METHOD4(setPathFragmentInputGen,
+ void(const std::string &, GLenum, GLint, const GLfloat *));
- MOCK_METHOD0(destroy, void());
+ MOCK_METHOD0(destructor, void());
};
inline ::testing::NiceMock<MockProgramImpl> *MakeProgramMock()
@@ -65,7 +74,7 @@ inline ::testing::NiceMock<MockProgramImpl> *MakeProgramMock()
::testing::NiceMock<MockProgramImpl> *programImpl = new ::testing::NiceMock<MockProgramImpl>();
// TODO(jmadill): add ON_CALLS for returning methods
// We must mock the destructor since NiceMock doesn't work for destructors.
- EXPECT_CALL(*programImpl, destroy()).Times(1).RetiresOnSaturation();
+ EXPECT_CALL(*programImpl, destructor()).Times(1).RetiresOnSaturation();
return programImpl;
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/ProgramPipelineImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/ProgramPipelineImpl.h
new file mode 100644
index 0000000000..242e9260f1
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/ProgramPipelineImpl.h
@@ -0,0 +1,32 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ProgramPipelineImpl.h: Defines the abstract rx::ProgramPipelineImpl class.
+
+#ifndef LIBANGLE_RENDERER_PROGRAMPIPELINEIMPL_H_
+#define LIBANGLE_RENDERER_PROGRAMPIPELINEIMPL_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/ProgramPipeline.h"
+
+namespace rx
+{
+class ContextImpl;
+
+class ProgramPipelineImpl : public angle::NonCopyable
+{
+ public:
+ ProgramPipelineImpl(const gl::ProgramPipelineState &state) : mState(state) {}
+ virtual ~ProgramPipelineImpl() {}
+ virtual void destroy(const ContextImpl *contextImpl) {}
+
+ protected:
+ const gl::ProgramPipelineState &mState;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_PROGRAMPIPELINEIMPL_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.cpp b/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.cpp
deleted file mode 100644
index ea5a40a21a..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-//
-// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// RenderbufferImpl.h: Implements the shared methods of the abstract class gl::RenderbufferImpl
-
-#include "libANGLE/renderer/RenderbufferImpl.h"
-
-namespace rx
-{
-RenderbufferImpl::RenderbufferImpl()
-{
-}
-
-RenderbufferImpl::~RenderbufferImpl()
-{
-}
-
-}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.h
index 75b4cdcfee..a70ab1d0f0 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.h
@@ -12,7 +12,7 @@
#include "angle_gl.h"
#include "common/angleutils.h"
#include "libANGLE/Error.h"
-#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
namespace egl
{
@@ -26,13 +26,25 @@ class RenderbufferImpl : public FramebufferAttachmentObjectImpl
{
public:
RenderbufferImpl() {}
- virtual ~RenderbufferImpl() {}
-
- virtual gl::Error setStorage(GLenum internalformat, size_t width, size_t height) = 0;
- virtual gl::Error setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height) = 0;
- virtual gl::Error setStorageEGLImageTarget(egl::Image *image) = 0;
+ ~RenderbufferImpl() override {}
+ virtual gl::Error onDestroy(const gl::Context *context);
+
+ virtual gl::Error setStorage(const gl::Context *context,
+ GLenum internalformat,
+ size_t width,
+ size_t height) = 0;
+ virtual gl::Error setStorageMultisample(const gl::Context *context,
+ size_t samples,
+ GLenum internalformat,
+ size_t width,
+ size_t height) = 0;
+ virtual gl::Error setStorageEGLImageTarget(const gl::Context *context, egl::Image *image) = 0;
};
+inline gl::Error RenderbufferImpl::onDestroy(const gl::Context *context)
+{
+ return gl::NoError();
+}
}
#endif // LIBANGLE_RENDERER_RENDERBUFFERIMPL_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl_mock.h b/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl_mock.h
index c2c67cc76a..408b9a5fe9 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl_mock.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl_mock.h
@@ -21,11 +21,16 @@ class MockRenderbufferImpl : public RenderbufferImpl
{
public:
virtual ~MockRenderbufferImpl() { destructor(); }
- MOCK_METHOD3(setStorage, gl::Error(GLenum, size_t, size_t));
- MOCK_METHOD4(setStorageMultisample, gl::Error(size_t, GLenum, size_t, size_t));
- MOCK_METHOD1(setStorageEGLImageTarget, gl::Error(egl::Image *));
-
- MOCK_METHOD2(getAttachmentRenderTarget, gl::Error(const gl::FramebufferAttachment::Target &, FramebufferAttachmentRenderTarget **));
+ MOCK_METHOD4(setStorage, gl::Error(const gl::Context *, GLenum, size_t, size_t));
+ MOCK_METHOD5(setStorageMultisample,
+ gl::Error(const gl::Context *, size_t, GLenum, size_t, size_t));
+ MOCK_METHOD2(setStorageEGLImageTarget, gl::Error(const gl::Context *, egl::Image *));
+
+ MOCK_METHOD4(getAttachmentRenderTarget,
+ gl::Error(const gl::Context *,
+ GLenum,
+ const gl::ImageIndex &,
+ FramebufferAttachmentRenderTarget **));
MOCK_METHOD0(destructor, void());
};
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/Renderer.cpp b/src/3rdparty/angle/src/libANGLE/renderer/Renderer.cpp
deleted file mode 100644
index f3f7f55bb9..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/Renderer.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Renderer.cpp: Implements EGL dependencies for creating and destroying Renderer instances.
-
-#include "common/utilities.h"
-#include "libANGLE/AttributeMap.h"
-#include "libANGLE/renderer/Renderer.h"
-
-#include <EGL/eglext.h>
-
-namespace rx
-{
-Renderer::Renderer() : mCapsInitialized(false)
-{
-}
-
-Renderer::~Renderer()
-{
-}
-
-void Renderer::ensureCapsInitialized() const
-{
- if (!mCapsInitialized)
- {
- generateCaps(&mCaps, &mTextureCaps, &mExtensions, &mLimitations);
- mCapsInitialized = true;
- }
-}
-
-const gl::Caps &Renderer::getRendererCaps() const
-{
- ensureCapsInitialized();
-
- return mCaps;
-}
-
-const gl::TextureCapsMap &Renderer::getRendererTextureCaps() const
-{
- ensureCapsInitialized();
-
- return mTextureCaps;
-}
-
-const gl::Extensions &Renderer::getRendererExtensions() const
-{
- ensureCapsInitialized();
-
- return mExtensions;
-}
-
-const gl::Limitations &Renderer::getRendererLimitations() const
-{
- ensureCapsInitialized();
-
- return mLimitations;
-}
-
-}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/Renderer.h b/src/3rdparty/angle/src/libANGLE/renderer/Renderer.h
deleted file mode 100644
index d0da2b140c..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/Renderer.h
+++ /dev/null
@@ -1,121 +0,0 @@
-//
-// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Renderer.h: Defines a back-end specific class that hides the details of the
-// implementation-specific renderer.
-
-#ifndef LIBANGLE_RENDERER_RENDERER_H_
-#define LIBANGLE_RENDERER_RENDERER_H_
-
-#include "libANGLE/Caps.h"
-#include "libANGLE/Error.h"
-#include "libANGLE/Framebuffer.h"
-#include "libANGLE/State.h"
-#include "libANGLE/Uniform.h"
-#include "libANGLE/angletypes.h"
-#include "libANGLE/renderer/ImplFactory.h"
-#include "common/mathutil.h"
-
-#include <stdint.h>
-
-#include <EGL/egl.h>
-
-namespace egl
-{
-class AttributeMap;
-class Display;
-class Surface;
-}
-
-namespace rx
-{
-struct TranslatedIndexData;
-struct SourceIndexData;
-struct WorkaroundsD3D;
-class DisplayImpl;
-
-class Renderer : public ImplFactory
-{
- public:
- Renderer();
- virtual ~Renderer();
-
- virtual gl::Error flush() = 0;
- virtual gl::Error finish() = 0;
-
- virtual gl::Error drawArrays(const gl::Data &data, GLenum mode, GLint first, GLsizei count) = 0;
- virtual gl::Error drawArraysInstanced(const gl::Data &data,
- GLenum mode,
- GLint first,
- GLsizei count,
- GLsizei instanceCount) = 0;
-
- virtual gl::Error drawElements(const gl::Data &data,
- GLenum mode,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- const gl::IndexRange &indexRange) = 0;
- virtual gl::Error drawElementsInstanced(const gl::Data &data,
- GLenum mode,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- GLsizei instances,
- const gl::IndexRange &indexRange) = 0;
- virtual gl::Error drawRangeElements(const gl::Data &data,
- GLenum mode,
- GLuint start,
- GLuint end,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- const gl::IndexRange &indexRange) = 0;
-
- // lost device
- //TODO(jmadill): investigate if this stuff is necessary in GL
- virtual void notifyDeviceLost() = 0;
- virtual bool isDeviceLost() const = 0;
- virtual bool testDeviceLost() = 0;
- virtual bool testDeviceResettable() = 0;
-
- virtual std::string getVendorString() const = 0;
- virtual std::string getRendererDescription() const = 0;
-
- virtual void insertEventMarker(GLsizei length, const char *marker) = 0;
- virtual void pushGroupMarker(GLsizei length, const char *marker) = 0;
- virtual void popGroupMarker() = 0;
-
- virtual void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) = 0;
-
- // Disjoint timer queries
- virtual GLint getGPUDisjoint() = 0;
- virtual GLint64 getTimestamp() = 0;
-
- // Context switching
- virtual void onMakeCurrent(const gl::Data &data) = 0;
-
- // Renderer capabilities
- const gl::Caps &getRendererCaps() const;
- const gl::TextureCapsMap &getRendererTextureCaps() const;
- const gl::Extensions &getRendererExtensions() const;
- const gl::Limitations &getRendererLimitations() const;
-
- private:
- void ensureCapsInitialized() const;
- virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap* outTextureCaps,
- gl::Extensions *outExtensions,
- gl::Limitations *outLimitations) const = 0;
-
- mutable bool mCapsInitialized;
- mutable gl::Caps mCaps;
- mutable gl::TextureCapsMap mTextureCaps;
- mutable gl::Extensions mExtensions;
- mutable gl::Limitations mLimitations;
-};
-
-}
-#endif // LIBANGLE_RENDERER_RENDERER_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/SamplerImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/SamplerImpl.h
index 85383cf8e5..66e1079b64 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/SamplerImpl.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/SamplerImpl.h
@@ -11,15 +11,29 @@
#include "common/angleutils.h"
+namespace gl
+{
+class Context;
+struct SamplerState;
+} // namespace gl
+
namespace rx
{
-class SamplerImpl : public angle::NonCopyable
+class SamplerImpl : angle::NonCopyable
{
public:
- SamplerImpl() {}
+ SamplerImpl(const gl::SamplerState &state) : mState(state) {}
virtual ~SamplerImpl() {}
+
+ virtual void syncState(const gl::Context *context)
+ {
+ // Default implementation: no-op.
+ }
+
+ protected:
+ const gl::SamplerState &mState;
};
-}
+} // namespace rx
#endif // LIBANGLE_RENDERER_SAMPLERIMPL_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/ShaderImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/ShaderImpl.h
index 5a466377a5..77e02d0237 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/ShaderImpl.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/ShaderImpl.h
@@ -18,21 +18,21 @@ namespace rx
class ShaderImpl : angle::NonCopyable
{
public:
- ShaderImpl(const gl::Shader::Data &data) : mData(data) {}
+ ShaderImpl(const gl::ShaderState &data) : mData(data) {}
virtual ~ShaderImpl() { }
- // Returns additional ShCompile options.
- virtual int prepareSourceAndReturnOptions(std::stringstream *sourceStream,
- std::string *sourcePath) = 0;
+ // Returns additional sh::Compile options.
+ virtual ShCompileOptions prepareSourceAndReturnOptions(std::stringstream *sourceStream,
+ std::string *sourcePath) = 0;
// Returns success for compiling on the driver. Returns success.
virtual bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) = 0;
virtual std::string getDebugInfo() const = 0;
- const gl::Shader::Data &getData() const { return mData; }
+ const gl::ShaderState &getData() const { return mData; }
protected:
- const gl::Shader::Data &mData;
+ const gl::ShaderState &mData;
};
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/StreamProducerImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/StreamProducerImpl.h
new file mode 100644
index 0000000000..1915bf75d3
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/StreamProducerImpl.h
@@ -0,0 +1,39 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// StreamProducerImpl.h: Defines the abstract rx::StreamProducerImpl class.
+
+#ifndef LIBANGLE_RENDERER_STREAMPRODUCERIMPL_H_
+#define LIBANGLE_RENDERER_STREAMPRODUCERIMPL_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Stream.h"
+
+namespace rx
+{
+
+class StreamProducerImpl : angle::NonCopyable
+{
+ public:
+ explicit StreamProducerImpl() {}
+ virtual ~StreamProducerImpl() {}
+
+ // Validates the ability for the producer to accept an arbitrary pointer to a frame. All
+ // pointers should be validated through this function before being used to produce a frame.
+ virtual egl::Error validateD3DNV12Texture(void *pointer) const = 0;
+
+ // Constructs a frame from an arbitrary external pointer that points to producer specific frame
+ // data. Replaces the internal frame with the new one.
+ virtual void postD3DNV12Texture(void *pointer, const egl::AttributeMap &attributes) = 0;
+
+ // Returns an OpenGL texture interpretation of some frame attributes for the purpose of
+ // constructing an OpenGL texture from a frame. Depending on the producer and consumer, some
+ // frames may have multiple "planes" with different OpenGL texture representations.
+ virtual egl::Stream::GLTextureDescription getGLFrameDescription(int planeIndex) = 0;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_STREAMPRODUCERIMPL_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.cpp b/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.cpp
index 36f5fdca3f..cd2fa3dde6 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.cpp
@@ -11,7 +11,7 @@
namespace rx
{
-SurfaceImpl::SurfaceImpl()
+SurfaceImpl::SurfaceImpl(const egl::SurfaceState &state) : mState(state)
{
}
@@ -19,4 +19,10 @@ SurfaceImpl::~SurfaceImpl()
{
}
+egl::Error SurfaceImpl::swapWithDamage(const gl::Context *context, EGLint *rects, EGLint n_rects)
+{
+ UNREACHABLE();
+ return egl::EglBadSurface() << "swapWithDamage implementation missing.";
}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.h
index 32125d542c..eaa27de281 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.h
@@ -9,35 +9,51 @@
#ifndef LIBANGLE_RENDERER_SURFACEIMPL_H_
#define LIBANGLE_RENDERER_SURFACEIMPL_H_
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
#include "common/angleutils.h"
#include "libANGLE/Error.h"
-#include "libANGLE/Framebuffer.h"
#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
+
+namespace gl
+{
+class FramebufferState;
+}
namespace egl
{
class Display;
struct Config;
+struct SurfaceState;
+class Thread;
}
namespace rx
{
-
class FramebufferImpl;
class SurfaceImpl : public FramebufferAttachmentObjectImpl
{
public:
- SurfaceImpl();
- virtual ~SurfaceImpl();
+ SurfaceImpl(const egl::SurfaceState &surfaceState);
+ ~SurfaceImpl() override;
+ virtual void destroy(const egl::Display *display) {}
- virtual egl::Error initialize() = 0;
- virtual FramebufferImpl *createDefaultFramebuffer(const gl::Framebuffer::Data &data) = 0;
- virtual egl::Error swap() = 0;
- virtual egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) = 0;
+ virtual egl::Error initialize(const egl::Display *display) = 0;
+ virtual FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) = 0;
+ virtual egl::Error swap(const gl::Context *context) = 0;
+ virtual egl::Error swapWithDamage(const gl::Context *context, EGLint *rects, EGLint n_rects);
+ virtual egl::Error postSubBuffer(const gl::Context *context,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height) = 0;
virtual egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) = 0;
virtual egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) = 0;
virtual egl::Error releaseTexImage(EGLint buffer) = 0;
+ virtual egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) = 0;
virtual void setSwapInterval(EGLint interval) = 0;
// width and height can change with client window resizing
@@ -46,6 +62,9 @@ class SurfaceImpl : public FramebufferAttachmentObjectImpl
virtual EGLint isPostSubBufferSupported() const = 0;
virtual EGLint getSwapBehavior() const = 0;
+
+ protected:
+ const egl::SurfaceState &mState;
};
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/SyncImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/SyncImpl.h
new file mode 100644
index 0000000000..22c92c3729
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/SyncImpl.h
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SyncImpl.h: Defines the rx::SyncImpl class.
+
+#ifndef LIBANGLE_RENDERER_FENCESYNCIMPL_H_
+#define LIBANGLE_RENDERER_FENCESYNCIMPL_H_
+
+#include "libANGLE/Error.h"
+
+#include "common/angleutils.h"
+
+#include "angle_gl.h"
+
+namespace rx
+{
+
+class SyncImpl : angle::NonCopyable
+{
+ public:
+ SyncImpl(){};
+ virtual ~SyncImpl(){};
+
+ virtual gl::Error set(GLenum condition, GLbitfield flags) = 0;
+ virtual gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) = 0;
+ virtual gl::Error serverWait(GLbitfield flags, GLuint64 timeout) = 0;
+ virtual gl::Error getStatus(GLint *outResult) = 0;
+};
+}
+
+#endif // LIBANGLE_RENDERER_FENCESYNCIMPL_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl.cpp b/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl.cpp
new file mode 100644
index 0000000000..830d30e6d1
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl.cpp
@@ -0,0 +1,63 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TextureImpl.cpp: Defines the abstract rx::TextureImpl classes.
+
+#include "libANGLE/renderer/TextureImpl.h"
+
+namespace rx
+{
+
+TextureImpl::TextureImpl(const gl::TextureState &state) : mState(state)
+{
+}
+
+TextureImpl::~TextureImpl()
+{
+}
+
+gl::Error TextureImpl::onDestroy(const gl::Context *context)
+{
+ return gl::NoError();
+}
+
+gl::Error TextureImpl::copyTexture(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ GLenum type,
+ size_t sourceLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source)
+{
+ UNREACHABLE();
+ return gl::InternalError() << "CHROMIUM_copy_texture exposed but not implemented.";
+}
+
+gl::Error TextureImpl::copySubTexture(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Offset &destOffset,
+ size_t sourceLevel,
+ const gl::Rectangle &sourceArea,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source)
+{
+ UNREACHABLE();
+ return gl::InternalError() << "CHROMIUM_copy_texture exposed but not implemented.";
+}
+
+gl::Error TextureImpl::copyCompressedTexture(const gl::Context *context, const gl::Texture *source)
+{
+ UNREACHABLE();
+ return gl::InternalError() << "CHROMIUM_copy_compressed_texture exposed but not implemented.";
+}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl.h
index ad4ec8d830..3b4f28f5f7 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl.h
@@ -14,8 +14,10 @@
#include "angle_gl.h"
#include "common/angleutils.h"
#include "libANGLE/Error.h"
-#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/ImageIndex.h"
+#include "libANGLE/Stream.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
namespace egl
{
@@ -36,38 +38,120 @@ struct TextureState;
namespace rx
{
+class ContextImpl;
class TextureImpl : public FramebufferAttachmentObjectImpl
{
public:
- TextureImpl() {}
- virtual ~TextureImpl() {}
-
- virtual void setUsage(GLenum usage) = 0;
-
- virtual gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
- const gl::PixelUnpackState &unpack, const uint8_t *pixels) = 0;
- virtual gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
- const gl::PixelUnpackState &unpack, const uint8_t *pixels) = 0;
-
- virtual gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
- const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) = 0;
- virtual gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
- const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) = 0;
-
- virtual gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+ TextureImpl(const gl::TextureState &state);
+ ~TextureImpl() override;
+
+ virtual gl::Error onDestroy(const gl::Context *context);
+
+ virtual gl::Error setImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels) = 0;
+ virtual gl::Error setSubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels) = 0;
+
+ virtual gl::Error setCompressedImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) = 0;
+ virtual gl::Error setCompressedSubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) = 0;
+
+ virtual gl::Error copyImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
const gl::Framebuffer *source) = 0;
- virtual gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
+ virtual gl::Error copySubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
const gl::Framebuffer *source) = 0;
- virtual gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) = 0;
-
- virtual gl::Error setEGLImageTarget(GLenum target, egl::Image *image) = 0;
-
- virtual gl::Error generateMipmaps(const gl::TextureState &textureState) = 0;
-
- virtual void bindTexImage(egl::Surface *surface) = 0;
- virtual void releaseTexImage() = 0;
+ virtual gl::Error copyTexture(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ GLenum type,
+ size_t sourceLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source);
+ virtual gl::Error copySubTexture(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Offset &destOffset,
+ size_t sourceLevel,
+ const gl::Rectangle &sourceArea,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source);
+
+ virtual gl::Error copyCompressedTexture(const gl::Context *context, const gl::Texture *source);
+
+ virtual gl::Error setStorage(const gl::Context *context,
+ GLenum target,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size) = 0;
+
+ virtual gl::Error setStorageMultisample(const gl::Context *context,
+ GLenum target,
+ GLsizei samples,
+ GLint internalformat,
+ const gl::Extents &size,
+ bool fixedSampleLocations) = 0;
+
+ virtual gl::Error setEGLImageTarget(const gl::Context *context,
+ GLenum target,
+ egl::Image *image) = 0;
+
+ virtual gl::Error setImageExternal(const gl::Context *context,
+ GLenum target,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc) = 0;
+
+ virtual gl::Error generateMipmap(const gl::Context *context) = 0;
+
+ virtual gl::Error setBaseLevel(const gl::Context *context, GLuint baseLevel) = 0;
+
+ virtual gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) = 0;
+ virtual gl::Error releaseTexImage(const gl::Context *context) = 0;
+
+ virtual void syncState(const gl::Texture::DirtyBits &dirtyBits) = 0;
+
+ protected:
+ const gl::TextureState &mState;
};
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl_mock.h b/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl_mock.h
index 3eb43f0033..e7fa441781 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl_mock.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl_mock.h
@@ -19,23 +19,111 @@ namespace rx
class MockTextureImpl : public TextureImpl
{
public:
+ MockTextureImpl() : TextureImpl(mMockState), mMockState(GL_TEXTURE_2D) {}
virtual ~MockTextureImpl() { destructor(); }
- MOCK_METHOD1(setUsage, void(GLenum));
- MOCK_METHOD8(setImage, gl::Error(GLenum, size_t, GLenum, const gl::Extents &, GLenum, GLenum, const gl::PixelUnpackState &, const uint8_t *));
- MOCK_METHOD7(setSubImage, gl::Error(GLenum, size_t, const gl::Box &, GLenum, GLenum, const gl::PixelUnpackState &, const uint8_t *));
- MOCK_METHOD7(setCompressedImage, gl::Error(GLenum, size_t, GLenum, const gl::Extents &, const gl::PixelUnpackState &, size_t, const uint8_t *));
- MOCK_METHOD7(setCompressedSubImage, gl::Error(GLenum, size_t, const gl::Box &, GLenum, const gl::PixelUnpackState &, size_t, const uint8_t *));
- MOCK_METHOD5(copyImage, gl::Error(GLenum, size_t, const gl::Rectangle &, GLenum, const gl::Framebuffer *));
- MOCK_METHOD5(copySubImage, gl::Error(GLenum, size_t, const gl::Offset &, const gl::Rectangle &, const gl::Framebuffer *));
- MOCK_METHOD4(setStorage, gl::Error(GLenum, size_t, GLenum, const gl::Extents &));
- MOCK_METHOD2(setEGLImageTarget, gl::Error(GLenum, egl::Image *));
- MOCK_METHOD1(generateMipmaps, gl::Error(const gl::TextureState &));
- MOCK_METHOD1(bindTexImage, void(egl::Surface *));
- MOCK_METHOD0(releaseTexImage, void(void));
-
- MOCK_METHOD2(getAttachmentRenderTarget, gl::Error(const gl::FramebufferAttachment::Target &, FramebufferAttachmentRenderTarget **));
+ MOCK_METHOD9(setImage,
+ gl::Error(const gl::Context *,
+ GLenum,
+ size_t,
+ GLenum,
+ const gl::Extents &,
+ GLenum,
+ GLenum,
+ const gl::PixelUnpackState &,
+ const uint8_t *));
+ MOCK_METHOD8(setSubImage,
+ gl::Error(const gl::Context *,
+ GLenum,
+ size_t,
+ const gl::Box &,
+ GLenum,
+ GLenum,
+ const gl::PixelUnpackState &,
+ const uint8_t *));
+ MOCK_METHOD8(setCompressedImage,
+ gl::Error(const gl::Context *,
+ GLenum,
+ size_t,
+ GLenum,
+ const gl::Extents &,
+ const gl::PixelUnpackState &,
+ size_t,
+ const uint8_t *));
+ MOCK_METHOD8(setCompressedSubImage,
+ gl::Error(const gl::Context *,
+ GLenum,
+ size_t,
+ const gl::Box &,
+ GLenum,
+ const gl::PixelUnpackState &,
+ size_t,
+ const uint8_t *));
+ MOCK_METHOD6(copyImage,
+ gl::Error(const gl::Context *,
+ GLenum,
+ size_t,
+ const gl::Rectangle &,
+ GLenum,
+ const gl::Framebuffer *));
+ MOCK_METHOD6(copySubImage,
+ gl::Error(const gl::Context *,
+ GLenum,
+ size_t,
+ const gl::Offset &,
+ const gl::Rectangle &,
+ const gl::Framebuffer *));
+ MOCK_METHOD10(copyTexture,
+ gl::Error(const gl::Context *,
+ GLenum,
+ size_t,
+ GLenum,
+ GLenum,
+ size_t,
+ bool,
+ bool,
+ bool,
+ const gl::Texture *));
+ MOCK_METHOD10(copySubTexture,
+ gl::Error(const gl::Context *,
+ GLenum,
+ size_t,
+ const gl::Offset &,
+ size_t,
+ const gl::Rectangle &,
+ bool,
+ bool,
+ bool,
+ const gl::Texture *));
+ MOCK_METHOD2(copyCompressedTexture, gl::Error(const gl::Context *, const gl::Texture *source));
+ MOCK_METHOD5(setStorage,
+ gl::Error(const gl::Context *, GLenum, size_t, GLenum, const gl::Extents &));
+ MOCK_METHOD4(setImageExternal,
+ gl::Error(const gl::Context *,
+ GLenum,
+ egl::Stream *,
+ const egl::Stream::GLTextureDescription &));
+ MOCK_METHOD3(setEGLImageTarget, gl::Error(const gl::Context *, GLenum, egl::Image *));
+ MOCK_METHOD1(generateMipmap, gl::Error(const gl::Context *));
+ MOCK_METHOD2(bindTexImage, gl::Error(const gl::Context *, egl::Surface *));
+ MOCK_METHOD1(releaseTexImage, gl::Error(const gl::Context *));
+
+ MOCK_METHOD4(getAttachmentRenderTarget,
+ gl::Error(const gl::Context *,
+ GLenum,
+ const gl::ImageIndex &,
+ FramebufferAttachmentRenderTarget **));
+
+ MOCK_METHOD6(setStorageMultisample,
+ gl::Error(const gl::Context *, GLenum, GLsizei, GLint, const gl::Extents &, bool));
+
+ MOCK_METHOD2(setBaseLevel, gl::Error(const gl::Context *, GLuint));
+
+ MOCK_METHOD1(syncState, void(const gl::Texture::DirtyBits &));
MOCK_METHOD0(destructor, void());
+
+ protected:
+ gl::TextureState mMockState;
};
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl.h
index 5df7cad87b..ad371e9b36 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl.h
@@ -18,6 +18,7 @@ namespace rx
class TransformFeedbackImpl : angle::NonCopyable
{
public:
+ TransformFeedbackImpl(const gl::TransformFeedbackState &state) : mState(state) {}
virtual ~TransformFeedbackImpl() { }
virtual void begin(GLenum primitiveMode) = 0;
@@ -25,8 +26,12 @@ class TransformFeedbackImpl : angle::NonCopyable
virtual void pause() = 0;
virtual void resume() = 0;
- virtual void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) = 0;
- virtual void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) = 0;
+ virtual void bindGenericBuffer(const gl::BindingPointer<gl::Buffer> &binding) = 0;
+ virtual void bindIndexedBuffer(size_t index,
+ const gl::OffsetBindingPointer<gl::Buffer> &binding) = 0;
+
+ protected:
+ const gl::TransformFeedbackState &mState;
};
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl_mock.h b/src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl_mock.h
index c7d2fc620d..2de3ad79a9 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl_mock.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl_mock.h
@@ -19,6 +19,10 @@ namespace rx
class MockTransformFeedbackImpl : public TransformFeedbackImpl
{
public:
+ MockTransformFeedbackImpl(const gl::TransformFeedbackState &state)
+ : TransformFeedbackImpl(state)
+ {
+ }
~MockTransformFeedbackImpl() { destructor(); }
MOCK_METHOD1(begin, void(GLenum primitiveMode));
@@ -26,8 +30,8 @@ class MockTransformFeedbackImpl : public TransformFeedbackImpl
MOCK_METHOD0(pause, void());
MOCK_METHOD0(resume, void());
- MOCK_METHOD1(bindGenericBuffer, void(const BindingPointer<gl::Buffer> &));
- MOCK_METHOD2(bindIndexedBuffer, void(size_t, const OffsetBindingPointer<gl::Buffer> &));
+ MOCK_METHOD1(bindGenericBuffer, void(const gl::BindingPointer<gl::Buffer> &));
+ MOCK_METHOD2(bindIndexedBuffer, void(size_t, const gl::OffsetBindingPointer<gl::Buffer> &));
MOCK_METHOD0(destructor, void());
};
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/VertexArrayImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/VertexArrayImpl.h
index 13617c7ecb..e48cc53d6c 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/VertexArrayImpl.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/VertexArrayImpl.h
@@ -15,15 +15,21 @@
namespace rx
{
+class ContextImpl;
class VertexArrayImpl : angle::NonCopyable
{
public:
- VertexArrayImpl(const gl::VertexArray::Data &data) : mData(data) { }
- virtual ~VertexArrayImpl() { }
- virtual void syncState(const gl::VertexArray::DirtyBits &dirtyBits) {}
+ VertexArrayImpl(const gl::VertexArrayState &state) : mState(state) {}
+ virtual void syncState(const gl::Context *context, const gl::VertexArray::DirtyBits &dirtyBits)
+ {
+ }
+
+ virtual void destroy(const gl::Context *context) {}
+ virtual ~VertexArrayImpl() {}
+
protected:
- const gl::VertexArray::Data &mData;
+ const gl::VertexArrayState &mState;
};
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/Workarounds.h b/src/3rdparty/angle/src/libANGLE/renderer/Workarounds.h
deleted file mode 100644
index b73f4a5472..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/Workarounds.h
+++ /dev/null
@@ -1,74 +0,0 @@
-//
-// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// angletypes.h: Workarounds for driver bugs and other issues.
-
-#ifndef LIBANGLE_RENDERER_WORKAROUNDS_H_
-#define LIBANGLE_RENDERER_WORKAROUNDS_H_
-
-// TODO(jmadill,zmo,geofflang): make a workarounds library that can operate
-// independent of ANGLE's renderer. Workarounds should also be accessible
-// outside of the Renderer.
-
-namespace rx
-{
-
-struct D3DCompilerWorkarounds : angle::NonCopyable
-{
- D3DCompilerWorkarounds()
- : skipOptimization(false),
- useMaxOptimization(false),
- enableIEEEStrictness(false)
- {}
-
- void reset()
- {
- skipOptimization = false;
- useMaxOptimization = false;
- enableIEEEStrictness = false;
- }
-
- bool skipOptimization;
- bool useMaxOptimization;
-
- // IEEE strictness needs to be enabled for NANs to work.
- bool enableIEEEStrictness;
-};
-
-struct Workarounds
-{
- Workarounds()
- : mrtPerfWorkaround(false),
- setDataFasterThanImageUpload(false),
- zeroMaxLodWorkaround(false),
- useInstancedPointSpriteEmulation(false)
- {}
-
- // On some systems, having extra rendertargets than necessary slows down the shader.
- // We can fix this by optimizing those out of the shader. At the same time, we can
- // work around a bug on some nVidia drivers that they ignore "null" render targets
- // in D3D11, by compacting the active color attachments list to omit null entries.
- bool mrtPerfWorkaround;
-
- bool setDataFasterThanImageUpload;
-
- // Some renderers can't disable mipmaps on a mipmapped texture (i.e. solely sample from level zero, and ignore the other levels).
- // D3D11 Feature Level 10+ does this by setting MaxLOD to 0.0f in the Sampler state. D3D9 sets D3DSAMP_MIPFILTER to D3DTEXF_NONE.
- // There is no equivalent to this in D3D11 Feature Level 9_3.
- // This causes problems when (for example) an application creates a mipmapped texture2D, but sets GL_TEXTURE_MIN_FILTER to GL_NEAREST (i.e disables mipmaps).
- // To work around this, D3D11 FL9_3 has to create two copies of the texture. The textures' level zeros are identical, but only one texture has mips.
- bool zeroMaxLodWorkaround;
-
- // Some renderers do not support Geometry Shaders so the Geometry Shader-based
- // PointSprite emulation will not work.
- // To work around this, D3D11 FL9_3 has to use a different pointsprite
- // emulation that is implemented using instanced quads.
- bool useInstancedPointSpriteEmulation;
-};
-
-}
-
-#endif // LIBANGLE_RENDERER_WORKAROUNDS_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/angle_format_data.json b/src/3rdparty/angle/src/libANGLE/renderer/angle_format_data.json
new file mode 100644
index 0000000000..5b3a226e2e
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/angle_format_data.json
@@ -0,0 +1,24 @@
+{
+ "B5G6R5_UNORM": {
+ "fboImplementationInternalFormat": "GL_RGB565"
+ },
+ "B5G5R5A1_UNORM": {
+ "fboImplementationInternalFormat": "GL_RGB5_A1",
+ "channelStruct": "A1R5G5B5"
+ },
+ "B8G8R8X8_UNORM": {
+ "glInternalFormat": "GL_BGRA8_EXT",
+ "channelStruct": "B8G8R8X8"
+ },
+ "R9G9B9E5_SHAREDEXP": {
+ "componentType": "float",
+ "channelStruct": "R9G9B9E5"
+ },
+ "B4G4R4A4_UNORM": {
+ "fboImplementationInternalFormat": "GL_RGBA4",
+ "channelStruct": "A4R4G4B4"
+ },
+ "R8G8B8A8_UNORM_SRGB": {
+ "channelStruct": "R8G8B8A8SRGB"
+ }
+}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/angle_format_map.json b/src/3rdparty/angle/src/libANGLE/renderer/angle_format_map.json
new file mode 100644
index 0000000000..5a4e487cbd
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/angle_format_map.json
@@ -0,0 +1,132 @@
+[
+ [ "GL_ALPHA16F_EXT", "A16_FLOAT" ],
+ [ "GL_ALPHA32F_EXT", "A32_FLOAT" ],
+ [ "GL_ALPHA8_EXT", "A8_UNORM" ],
+ [ "GL_BGR565_ANGLEX", "B5G6R5_UNORM" ],
+ [ "GL_BGR5_A1_ANGLEX", "B5G5R5A1_UNORM" ],
+ [ "GL_BGRA4_ANGLEX", "B4G4R4A4_UNORM" ],
+ [ "GL_BGRA8_EXT", "B8G8R8A8_UNORM" ],
+ [ "GL_BGRA8_SRGB_ANGLEX", "B8G8R8A8_UNORM_SRGB"],
+ [ "GL_BGRX8_ANGLEX", "B8G8R8X8_UNORM" ],
+ [ "GL_COMPRESSED_R11_EAC", "EAC_R11_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RG11_EAC", "EAC_R11G11_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGB8_ETC2", "ETC2_R8G8B8_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2", "ETC2_R8G8B8A1_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA8_ETC2_EAC", "ETC2_R8G8B8A8_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT", "BC1_RGBA_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE", "BC2_RGBA_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE", "BC3_RGBA_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_4x4_KHR", "ASTC_4x4_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_5x4_KHR", "ASTC_5x4_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_5x5_KHR", "ASTC_5x5_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_6x5_KHR", "ASTC_6x5_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_6x6_KHR", "ASTC_6x6_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_8x5_KHR", "ASTC_8x5_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_8x6_KHR", "ASTC_8x6_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_8x8_KHR", "ASTC_8x8_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_10x5_KHR", "ASTC_10x5_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_10x6_KHR", "ASTC_10x6_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_10x8_KHR", "ASTC_10x8_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_10x10_KHR", "ASTC_10x10_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_12x10_KHR", "ASTC_12x10_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGBA_ASTC_12x12_KHR", "ASTC_12x12_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_RGB_S3TC_DXT1_EXT", "BC1_RGB_UNORM_BLOCK" ],
+ [ "GL_COMPRESSED_SIGNED_R11_EAC", "EAC_R11_SNORM_BLOCK" ],
+ [ "GL_COMPRESSED_SIGNED_RG11_EAC", "EAC_R11G11_SNORM_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR", "ASTC_4x4_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR", "ASTC_5x4_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR", "ASTC_5x5_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR", "ASTC_6x5_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR", "ASTC_6x6_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR", "ASTC_8x5_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR", "ASTC_8x6_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR", "ASTC_8x8_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR", "ASTC_10x5_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR", "ASTC_10x6_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR", "ASTC_10x8_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR", "ASTC_10x10_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR", "ASTC_12x10_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR", "ASTC_12x12_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC", "ETC2_R8G8B8A8_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_ETC2", "ETC2_R8G8B8_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2", "ETC2_R8G8B8A1_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT", "BC1_RGBA_UNORM_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT", "BC2_RGBA_UNORM_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT", "BC3_RGBA_UNORM_SRGB_BLOCK" ],
+ [ "GL_COMPRESSED_SRGB_S3TC_DXT1_EXT", "BC1_RGB_UNORM_SRGB_BLOCK" ],
+ [ "GL_DEPTH24_STENCIL8", "D24_UNORM_S8_UINT" ],
+ [ "GL_DEPTH32F_STENCIL8", "D32_FLOAT_S8X24_UINT" ],
+ [ "GL_DEPTH_COMPONENT16", "D16_UNORM" ],
+ [ "GL_DEPTH_COMPONENT24", "D24_UNORM" ],
+ [ "GL_DEPTH_COMPONENT32F", "D32_FLOAT" ],
+ [ "GL_DEPTH_COMPONENT32_OES", "D32_UNORM" ],
+ [ "GL_ETC1_RGB8_OES", "ETC1_R8G8B8_UNORM_BLOCK" ],
+ [ "GL_ETC1_RGB8_LOSSY_DECODE_ANGLE", "ETC1_LOSSY_DECODE_R8G8B8_UNORM_BLOCK" ],
+ [ "GL_LUMINANCE16F_EXT", "L16_FLOAT" ],
+ [ "GL_LUMINANCE32F_EXT", "L32_FLOAT" ],
+ [ "GL_LUMINANCE8_ALPHA8_EXT", "L8A8_UNORM" ],
+ [ "GL_LUMINANCE8_EXT", "L8_UNORM" ],
+ [ "GL_LUMINANCE_ALPHA16F_EXT", "L16A16_FLOAT" ],
+ [ "GL_LUMINANCE_ALPHA32F_EXT", "L32A32_FLOAT" ],
+ [ "GL_NONE", "NONE" ],
+ [ "GL_R11F_G11F_B10F", "R11G11B10_FLOAT" ],
+ [ "GL_R16F", "R16_FLOAT" ],
+ [ "GL_R16I", "R16_SINT" ],
+ [ "GL_R16UI", "R16_UINT" ],
+ [ "GL_R32F", "R32_FLOAT" ],
+ [ "GL_R32I", "R32_SINT" ],
+ [ "GL_R32UI", "R32_UINT" ],
+ [ "GL_R8", "R8_UNORM" ],
+ [ "GL_R8I", "R8_SINT" ],
+ [ "GL_R8UI", "R8_UINT" ],
+ [ "GL_R8_SNORM", "R8_SNORM" ],
+ [ "GL_RG16F", "R16G16_FLOAT" ],
+ [ "GL_RG16I", "R16G16_SINT" ],
+ [ "GL_RG16UI", "R16G16_UINT" ],
+ [ "GL_RG32F", "R32G32_FLOAT" ],
+ [ "GL_RG32I", "R32G32_SINT" ],
+ [ "GL_RG32UI", "R32G32_UINT" ],
+ [ "GL_RG8", "R8G8_UNORM" ],
+ [ "GL_RG8I", "R8G8_SINT" ],
+ [ "GL_RG8UI", "R8G8_UINT" ],
+ [ "GL_RG8_SNORM", "R8G8_SNORM" ],
+ [ "GL_RGB", "R8G8B8_UNORM" ],
+ [ "GL_RGB10_A2", "R10G10B10A2_UNORM" ],
+ [ "GL_RGB10_A2UI", "R10G10B10A2_UINT" ],
+ [ "GL_RGB16F", "R16G16B16_FLOAT" ],
+ [ "GL_RGB16I", "R16G16B16_SINT" ],
+ [ "GL_RGB16UI", "R16G16B16_UINT" ],
+ [ "GL_RGB32F", "R32G32B32_FLOAT" ],
+ [ "GL_RGB32I", "R32G32B32_SINT" ],
+ [ "GL_RGB32UI", "R32G32B32_UINT" ],
+ [ "GL_RGB565", "R5G6B5_UNORM" ],
+ [ "GL_RGB5_A1", "R5G5B5A1_UNORM" ],
+ [ "GL_RGB8", "R8G8B8_UNORM" ],
+ [ "GL_RGB8I", "R8G8B8_SINT" ],
+ [ "GL_RGB8UI", "R8G8B8_UINT" ],
+ [ "GL_RGB8_SNORM", "R8G8B8_SNORM" ],
+ [ "GL_RGB9_E5", "R9G9B9E5_SHAREDEXP" ],
+ [ "GL_RGBA", "R8G8B8A8_UNORM" ],
+ [ "GL_RGBA16F", "R16G16B16A16_FLOAT" ],
+ [ "GL_RGBA16I", "R16G16B16A16_SINT" ],
+ [ "GL_RGBA16UI", "R16G16B16A16_UINT" ],
+ [ "GL_RGBA32F", "R32G32B32A32_FLOAT" ],
+ [ "GL_RGBA32I", "R32G32B32A32_SINT" ],
+ [ "GL_RGBA32UI", "R32G32B32A32_UINT" ],
+ [ "GL_RGBA4", "R4G4B4A4_UNORM" ],
+ [ "GL_RGBA8", "R8G8B8A8_UNORM" ],
+ [ "GL_RGBA8I", "R8G8B8A8_SINT" ],
+ [ "GL_RGBA8UI", "R8G8B8A8_UINT" ],
+ [ "GL_RGBA8_SNORM", "R8G8B8A8_SNORM" ],
+ [ "GL_SRGB8", "R8G8B8_UNORM_SRGB" ],
+ [ "GL_SRGB8_ALPHA8", "R8G8B8A8_UNORM_SRGB" ],
+ [ "GL_STENCIL_INDEX8", "S8_UINT" ],
+ [ "GL_R16_EXT", "R16_UNORM" ],
+ [ "GL_RG16_EXT", "R16G16_UNORM" ],
+ [ "GL_RGB16_EXT", "R16G16B16_UNORM" ],
+ [ "GL_RGBA16_EXT", "R16G16B16A16_UNORM" ],
+ [ "GL_R16_SNORM_EXT", "R16_SNORM" ],
+ [ "GL_RG16_SNORM_EXT", "R16G16_SNORM" ],
+ [ "GL_RGB16_SNORM_EXT", "R16G16B16_SNORM" ],
+ [ "GL_RGBA16_SNORM_EXT", "R16G16B16A16_SNORM" ]
+]
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp
index ffca99c3ac..7769ab2b75 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp
@@ -12,42 +12,33 @@
#include "common/utilities.h"
#include "libANGLE/renderer/d3d/IndexBuffer.h"
#include "libANGLE/renderer/d3d/VertexBuffer.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
namespace rx
{
unsigned int BufferD3D::mNextSerial = 1;
-BufferD3D::BufferD3D(BufferFactoryD3D *factory)
- : BufferImpl(),
+BufferD3D::BufferD3D(const gl::BufferState &state, BufferFactoryD3D *factory)
+ : BufferImpl(state),
mFactory(factory),
- mStaticVertexBuffer(nullptr),
mStaticIndexBuffer(nullptr),
- mStaticBufferCache(nullptr),
mStaticBufferCacheTotalSize(0),
mStaticVertexBufferOutOfDate(false),
mUnmodifiedDataUse(0),
- mUsage(D3D_BUFFER_USAGE_STATIC)
+ mUsage(D3DBufferUsage::STATIC)
{
updateSerial();
}
BufferD3D::~BufferD3D()
{
- SafeDelete(mStaticVertexBuffer);
SafeDelete(mStaticIndexBuffer);
-
- emptyStaticBufferCache();
}
void BufferD3D::emptyStaticBufferCache()
{
- if (mStaticBufferCache != nullptr)
- {
- SafeDeleteContainer(*mStaticBufferCache);
- SafeDelete(mStaticBufferCache);
- }
-
+ mStaticVertexBuffers.clear();
mStaticBufferCacheTotalSize = 0;
}
@@ -56,35 +47,37 @@ void BufferD3D::updateSerial()
mSerial = mNextSerial++;
}
-void BufferD3D::updateD3DBufferUsage(GLenum usage)
+void BufferD3D::updateD3DBufferUsage(const gl::Context *context, gl::BufferUsage usage)
{
switch (usage)
{
- case GL_STATIC_DRAW:
- case GL_STATIC_READ:
- case GL_STATIC_COPY:
- mUsage = D3D_BUFFER_USAGE_STATIC;
- initializeStaticData();
+ case gl::BufferUsage::StaticCopy:
+ case gl::BufferUsage::StaticDraw:
+ case gl::BufferUsage::StaticRead:
+ mUsage = D3DBufferUsage::STATIC;
+ initializeStaticData(context);
break;
- case GL_STREAM_DRAW:
- case GL_STREAM_READ:
- case GL_STREAM_COPY:
- case GL_DYNAMIC_READ:
- case GL_DYNAMIC_COPY:
- case GL_DYNAMIC_DRAW:
- mUsage = D3D_BUFFER_USAGE_DYNAMIC;
+ case gl::BufferUsage::DynamicCopy:
+ case gl::BufferUsage::DynamicDraw:
+ case gl::BufferUsage::DynamicRead:
+ case gl::BufferUsage::StreamCopy:
+ case gl::BufferUsage::StreamDraw:
+ case gl::BufferUsage::StreamRead:
+ mUsage = D3DBufferUsage::DYNAMIC;
break;
default:
UNREACHABLE();
}
}
-void BufferD3D::initializeStaticData()
+void BufferD3D::initializeStaticData(const gl::Context *context)
{
- if (!mStaticVertexBuffer)
+ if (mStaticVertexBuffers.empty())
{
- mStaticVertexBuffer = new StaticVertexBufferInterface(mFactory);
+ StaticVertexBufferInterface *newStaticBuffer = new StaticVertexBufferInterface(mFactory);
+ mStaticVertexBuffers.push_back(
+ std::unique_ptr<StaticVertexBufferInterface>(newStaticBuffer));
}
if (!mStaticIndexBuffer)
{
@@ -97,168 +90,101 @@ StaticIndexBufferInterface *BufferD3D::getStaticIndexBuffer()
return mStaticIndexBuffer;
}
-StaticVertexBufferInterface *BufferD3D::getStaticVertexBuffer(
- const gl::VertexAttribute &attribute,
- D3DStaticBufferCreationType creationType)
+StaticVertexBufferInterface *BufferD3D::getStaticVertexBuffer(const gl::VertexAttribute &attribute,
+ const gl::VertexBinding &binding)
{
- if (!mStaticVertexBuffer)
+ if (mStaticVertexBuffers.empty())
{
// Early out if there aren't any static buffers at all
- ASSERT(mStaticBufferCache == nullptr);
return nullptr;
}
- if (mStaticBufferCache == nullptr && !mStaticVertexBuffer->isCommitted())
+ // Early out, the attribute can be added to mStaticVertexBuffer.
+ if (mStaticVertexBuffers.size() == 1 && mStaticVertexBuffers[0]->empty())
{
- // Early out, the attribute can be added to mStaticVertexBuffer or is already in there
- return mStaticVertexBuffer;
+ return mStaticVertexBuffers[0].get();
}
- // At this point, see if any of the existing static buffers contains the attribute data
+ // Cache size limiting: track the total allocated buffer sizes.
+ size_t currentTotalSize = 0;
- // If the default static vertex buffer contains the attribute, then return it
- if (mStaticVertexBuffer->lookupAttribute(attribute, nullptr))
- {
- return mStaticVertexBuffer;
- }
-
- if (mStaticBufferCache != nullptr)
+ // At this point, see if any of the existing static buffers contains the attribute data
+ // If there is a cached static buffer that already contains the attribute, then return it
+ for (const auto &staticBuffer : mStaticVertexBuffers)
{
- // If there is a cached static buffer that already contains the attribute, then return it
- for (StaticVertexBufferInterface *staticBuffer : *mStaticBufferCache)
+ if (staticBuffer->matchesAttribute(attribute, binding))
{
- if (staticBuffer->lookupAttribute(attribute, nullptr))
- {
- return staticBuffer;
- }
+ return staticBuffer.get();
}
- }
- if (!mStaticVertexBuffer->isCommitted())
- {
- // None of the existing static buffers contain the attribute data and we are able to add
- // the data to mStaticVertexBuffer, so we should just do so
- return mStaticVertexBuffer;
+ currentTotalSize += staticBuffer->getBufferSize();
}
- // At this point, we must create a new static buffer for the attribute data
- if (creationType != D3D_BUFFER_CREATE_IF_NECESSARY)
- {
- return nullptr;
- }
+ // Cache size limiting: Clean-up threshold is four times the base buffer size, with a minimum.
+ ASSERT(getSize() < std::numeric_limits<size_t>::max() / 4u);
+ size_t sizeThreshold = std::max(getSize() * 4u, static_cast<size_t>(0x1000u));
- ASSERT(mStaticVertexBuffer);
- ASSERT(mStaticVertexBuffer->isCommitted());
- unsigned int staticVertexBufferSize = mStaticVertexBuffer->getBufferSize();
- if (IsUnsignedAdditionSafe(staticVertexBufferSize, mStaticBufferCacheTotalSize))
+ // If we're past the threshold, clear the buffer cache. Note that this will release buffers
+ // that are currenly bound, and in an edge case can even translate the same attribute twice
+ // in the same draw call. It will not delete currently bound buffers, however, because they
+ // are ref counted.
+ if (currentTotalSize > sizeThreshold)
{
- // Ensure that the total size of the static buffer cache remains less than 4x the
- // size of the original buffer
- unsigned int maxStaticCacheSize =
- IsUnsignedMultiplicationSafe(static_cast<unsigned int>(getSize()), 4u)
- ? 4u * static_cast<unsigned int>(getSize())
- : std::numeric_limits<unsigned int>::max();
-
- // We can't reuse the default static vertex buffer, so we add it to the cache
- if (staticVertexBufferSize + mStaticBufferCacheTotalSize <= maxStaticCacheSize)
- {
- if (mStaticBufferCache == nullptr)
- {
- mStaticBufferCache = new std::vector<StaticVertexBufferInterface *>();
- }
-
- mStaticBufferCacheTotalSize += staticVertexBufferSize;
- (*mStaticBufferCache).push_back(mStaticVertexBuffer);
- mStaticVertexBuffer = nullptr;
-
- // Then reinitialize the static buffers to create a new static vertex buffer
- initializeStaticData();
-
- // Return the default static vertex buffer
- return mStaticVertexBuffer;
- }
+ emptyStaticBufferCache();
}
- // At this point:
- // - mStaticVertexBuffer is committed and can't be altered
- // - mStaticBufferCache is full (or nearly overflowing)
- // The inputted attribute should be put in some static buffer at some point, but it can't
- // go in one right now, since mStaticBufferCache is full and we can't delete mStaticVertexBuffer
- // in case another attribute is relying upon it for the current draw.
- // We therefore mark mStaticVertexBuffer for deletion at the next possible time.
- mStaticVertexBufferOutOfDate = true;
- return nullptr;
+ // At this point, we must create a new static buffer for the attribute data.
+ StaticVertexBufferInterface *newStaticBuffer = new StaticVertexBufferInterface(mFactory);
+ newStaticBuffer->setAttribute(attribute, binding);
+ mStaticVertexBuffers.push_back(std::unique_ptr<StaticVertexBufferInterface>(newStaticBuffer));
+ return newStaticBuffer;
}
-void BufferD3D::reinitOutOfDateStaticData()
+void BufferD3D::invalidateStaticData(const gl::Context *context)
{
- if (mStaticVertexBufferOutOfDate)
- {
- // During the last draw the caller tried to use some attribute with static data, but neither
- // the static buffer cache nor mStaticVertexBuffer contained that data.
- // Therefore, invalidate mStaticVertexBuffer so that if the caller tries to use that
- // attribute in the next draw, it'll successfully get put into mStaticVertexBuffer.
- invalidateStaticData(D3D_BUFFER_INVALIDATE_DEFAULT_BUFFER_ONLY);
- mStaticVertexBufferOutOfDate = false;
- }
-}
+ emptyStaticBufferCache();
-void BufferD3D::invalidateStaticData(D3DBufferInvalidationType invalidationType)
-{
- if (invalidationType == D3D_BUFFER_INVALIDATE_WHOLE_CACHE && mStaticBufferCache != nullptr)
+ if (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0)
{
- emptyStaticBufferCache();
+ SafeDelete(mStaticIndexBuffer);
}
- if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0))
+ // If the buffer was created with a static usage then we recreate the static
+ // buffers so that they are populated the next time we use this buffer.
+ if (mUsage == D3DBufferUsage::STATIC)
{
- SafeDelete(mStaticVertexBuffer);
- SafeDelete(mStaticIndexBuffer);
-
- // If the buffer was created with a static usage then we recreate the static
- // buffers so that they are populated the next time we use this buffer.
- if (mUsage == D3D_BUFFER_USAGE_STATIC)
- {
- initializeStaticData();
- }
+ initializeStaticData(context);
}
mUnmodifiedDataUse = 0;
}
// Creates static buffers if sufficient used data has been left unmodified
-void BufferD3D::promoteStaticUsage(int dataSize)
+void BufferD3D::promoteStaticUsage(const gl::Context *context, int dataSize)
{
- if (!mStaticVertexBuffer && !mStaticIndexBuffer)
+ if (mUsage == D3DBufferUsage::DYNAMIC)
{
- // There isn't any scenario that involves promoting static usage and the static buffer cache
- // being non-empty
- ASSERT(mStaticBufferCache == nullptr);
-
mUnmodifiedDataUse += dataSize;
if (mUnmodifiedDataUse > 3 * getSize())
{
- initializeStaticData();
+ updateD3DBufferUsage(context, gl::BufferUsage::StaticDraw);
}
}
}
-gl::Error BufferD3D::getIndexRange(GLenum type,
+gl::Error BufferD3D::getIndexRange(const gl::Context *context,
+ GLenum type,
size_t offset,
size_t count,
bool primitiveRestartEnabled,
gl::IndexRange *outRange)
{
const uint8_t *data = nullptr;
- gl::Error error = getData(&data);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(getData(context, &data));
*outRange = gl::ComputeIndexRange(type, data + offset, count, primitiveRestartEnabled);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-}
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.h
index a27ca9857a..60153748e6 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.h
@@ -15,71 +15,69 @@
#include <stdint.h>
#include <vector>
+namespace gl
+{
+struct VertexAttribute;
+class VertexBinding;
+}
+
namespace rx
{
class BufferFactoryD3D;
class StaticIndexBufferInterface;
class StaticVertexBufferInterface;
-enum D3DBufferUsage
-{
- D3D_BUFFER_USAGE_STATIC,
- D3D_BUFFER_USAGE_DYNAMIC,
-};
-
-enum D3DBufferInvalidationType
+enum class D3DBufferUsage
{
- D3D_BUFFER_INVALIDATE_WHOLE_CACHE,
- D3D_BUFFER_INVALIDATE_DEFAULT_BUFFER_ONLY,
-};
-
-enum D3DStaticBufferCreationType
-{
- D3D_BUFFER_CREATE_IF_NECESSARY,
- D3D_BUFFER_DO_NOT_CREATE,
+ STATIC,
+ DYNAMIC,
};
class BufferD3D : public BufferImpl
{
public:
- BufferD3D(BufferFactoryD3D *factory);
- virtual ~BufferD3D();
+ BufferD3D(const gl::BufferState &state, BufferFactoryD3D *factory);
+ ~BufferD3D() override;
unsigned int getSerial() const { return mSerial; }
virtual size_t getSize() const = 0;
virtual bool supportsDirectBinding() const = 0;
- virtual void markTransformFeedbackUsage() = 0;
- virtual gl::Error getData(const uint8_t **outData) = 0;
+ virtual gl::Error markTransformFeedbackUsage(const gl::Context *context) = 0;
+ virtual gl::Error getData(const gl::Context *context, const uint8_t **outData) = 0;
+ // Warning: you should ensure binding really matches attrib.bindingIndex before using this
+ // function.
StaticVertexBufferInterface *getStaticVertexBuffer(const gl::VertexAttribute &attribute,
- D3DStaticBufferCreationType creationType);
+ const gl::VertexBinding &binding);
StaticIndexBufferInterface *getStaticIndexBuffer();
- void initializeStaticData();
- void invalidateStaticData(D3DBufferInvalidationType invalidationType);
- void reinitOutOfDateStaticData();
+ virtual void initializeStaticData(const gl::Context *context);
+ virtual void invalidateStaticData(const gl::Context *context);
- void promoteStaticUsage(int dataSize);
+ void promoteStaticUsage(const gl::Context *context, int dataSize);
- gl::Error getIndexRange(GLenum type,
+ gl::Error getIndexRange(const gl::Context *context,
+ GLenum type,
size_t offset,
size_t count,
bool primitiveRestartEnabled,
gl::IndexRange *outRange) override;
+ BufferFactoryD3D *getFactory() const { return mFactory; }
+ D3DBufferUsage getUsage() const { return mUsage; }
+
protected:
void updateSerial();
- void updateD3DBufferUsage(GLenum usage);
+ void updateD3DBufferUsage(const gl::Context *context, gl::BufferUsage usage);
void emptyStaticBufferCache();
BufferFactoryD3D *mFactory;
unsigned int mSerial;
static unsigned int mNextSerial;
- StaticVertexBufferInterface *mStaticVertexBuffer;
+ std::vector<std::unique_ptr<StaticVertexBufferInterface>> mStaticVertexBuffers;
StaticIndexBufferInterface *mStaticIndexBuffer;
- std::vector<StaticVertexBufferInterface *> *mStaticBufferCache;
unsigned int mStaticBufferCacheTotalSize;
unsigned int mStaticVertexBufferOutOfDate;
unsigned int mUnmodifiedDataUse;
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp
index 6f8d1717cd..8ceeec3c39 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp
@@ -17,4 +17,14 @@ CompilerD3D::CompilerD3D(ShShaderOutput translatorOutputType)
{
}
+gl::Error CompilerD3D::release()
+{
+ return gl::NoError();
+}
+
+ShShaderOutput CompilerD3D::getTranslatorOutputType() const
+{
+ return mTranslatorOutputType;
+}
+
} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.h
index 8f4334963d..bcfe810d04 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.h
@@ -21,8 +21,8 @@ class CompilerD3D : public CompilerImpl
CompilerD3D(ShShaderOutput translatorOutputType);
~CompilerD3D() override {}
- gl::Error release() override { return gl::Error(GL_NO_ERROR); }
- ShShaderOutput getTranslatorOutputType() const override { return mTranslatorOutputType; }
+ gl::Error release() override;
+ ShShaderOutput getTranslatorOutputType() const override;
private:
ShShaderOutput mTranslatorOutputType;
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp
index f40e6e6cab..5a06b15279 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp
@@ -39,11 +39,11 @@ egl::Error DeviceD3D::getDevice(void **outValue)
if (!mIsInitialized)
{
*outValue = nullptr;
- return egl::Error(EGL_BAD_DEVICE_EXT);
+ return egl::EglBadDevice();
}
*outValue = mDevice;
- return egl::Error(EGL_SUCCESS);
+ return egl::NoError();
}
egl::Error DeviceD3D::initialize(void *device,
@@ -53,15 +53,11 @@ egl::Error DeviceD3D::initialize(void *device,
ASSERT(!mIsInitialized);
if (mIsInitialized)
{
- return egl::Error(EGL_BAD_DEVICE_EXT);
+ return egl::EglBadDevice();
}
- mDevice = device;
- mDeviceType = deviceType;
- mDeviceExternallySourced = !!deviceExternallySourced;
-
#if defined(ANGLE_ENABLE_D3D11)
- if (mDeviceType == EGL_D3D11_DEVICE_ANGLE)
+ if (deviceType == EGL_D3D11_DEVICE_ANGLE)
{
// Validate the device
IUnknown *iunknown = reinterpret_cast<IUnknown *>(device);
@@ -71,7 +67,7 @@ egl::Error DeviceD3D::initialize(void *device,
iunknown->QueryInterface(__uuidof(ID3D11Device), reinterpret_cast<void **>(&d3dDevice));
if (FAILED(hr))
{
- return egl::Error(EGL_BAD_ATTRIBUTE, "Invalid D3D device passed into EGLDeviceEXT");
+ return egl::EglBadAttribute() << "Invalid D3D device passed into EGLDeviceEXT";
}
// The QI to ID3D11Device adds a ref to the D3D11 device.
@@ -81,12 +77,15 @@ egl::Error DeviceD3D::initialize(void *device,
else
#endif
{
- ASSERT(!mDeviceExternallySourced);
+ ASSERT(deviceExternallySourced == EGL_FALSE);
}
- mIsInitialized = true;
+ mDevice = device;
+ mDeviceType = deviceType;
+ mDeviceExternallySourced = !!deviceExternallySourced;
+ mIsInitialized = true;
- return egl::Error(EGL_SUCCESS);
+ return egl::NoError();
}
EGLint DeviceD3D::getType()
@@ -99,4 +98,8 @@ void DeviceD3D::generateExtensions(egl::DeviceExtensions *outExtensions) const
outExtensions->deviceD3D = true;
}
+bool DeviceD3D::deviceExternallySourced()
+{
+ return mDeviceExternallySourced;
+}
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.h
index 1dd9979708..15eaf9210a 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.h
@@ -25,7 +25,7 @@ class DeviceD3D : public DeviceImpl
egl::Error getDevice(void **outValue) override;
EGLint getType() override;
void generateExtensions(egl::DeviceExtensions *outExtensions) const override;
- bool deviceExternallySourced() override { return mDeviceExternallySourced; }
+ bool deviceExternallySourced() override;
private:
void *mDevice;
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp
index d4dc702582..0edda9c584 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp
@@ -8,18 +8,19 @@
#include "libANGLE/renderer/d3d/DisplayD3D.h"
-#include "libANGLE/Context.h"
+#include <EGL/eglext.h>
+
#include "libANGLE/Config.h"
+#include "libANGLE/Context.h"
#include "libANGLE/Display.h"
#include "libANGLE/Surface.h"
+#include "libANGLE/Thread.h"
#include "libANGLE/histogram_macros.h"
+#include "libANGLE/renderer/d3d/DeviceD3D.h"
#include "libANGLE/renderer/d3d/EGLImageD3D.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/SurfaceD3D.h"
#include "libANGLE/renderer/d3d/SwapChainD3D.h"
-#include "libANGLE/renderer/d3d/DeviceD3D.h"
-
-#include <EGL/eglext.h>
#if defined (ANGLE_ENABLE_D3D9)
# include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
@@ -29,10 +30,6 @@
# include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#endif // ANGLE_ENABLE_D3D11
-#if defined (ANGLE_TEST_CONFIG)
-# define ANGLE_DEFAULT_D3D11 1
-#endif
-
#if !defined(ANGLE_DEFAULT_D3D11)
// Enables use of the Direct3D 11 API for a default display, when available
# define ANGLE_DEFAULT_D3D11 1
@@ -60,8 +57,8 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer)
const auto &attribMap = display->getAttributeMap();
EGLNativeDisplayType nativeDisplay = display->getNativeDisplayId();
- EGLint requestedDisplayType =
- attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
+ EGLint requestedDisplayType = static_cast<EGLint>(
+ attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE));
# if defined(ANGLE_ENABLE_D3D11)
if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
@@ -117,11 +114,10 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer)
UNIMPLEMENTED();
}
- egl::Error result(EGL_NOT_INITIALIZED, "No available renderers.");
for (size_t i = 0; i < rendererCreationFunctions.size(); i++)
{
RendererD3D *renderer = rendererCreationFunctions[i](display);
- result = renderer->initialize();
+ egl::Error result = renderer->initialize();
# if defined(ANGLE_ENABLE_D3D11)
if (renderer->getRendererClass() == RENDERER_D3D11)
@@ -146,70 +142,45 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer)
if (!result.isError())
{
*outRenderer = renderer;
- break;
- }
- else
- {
- // Failed to create the renderer, try the next
- SafeDelete(renderer);
+ return result;
}
+
+ // Failed to create the renderer, try the next
+ SafeDelete(renderer);
}
- return result;
+ return egl::EglNotInitialized() << "No available renderers.";
}
-DisplayD3D::DisplayD3D() : mRenderer(nullptr)
+DisplayD3D::DisplayD3D(const egl::DisplayState &state) : DisplayImpl(state), mRenderer(nullptr)
{
}
-
-SurfaceImpl *DisplayD3D::createWindowSurface(const egl::Config *configuration,
+SurfaceImpl *DisplayD3D::createWindowSurface(const egl::SurfaceState &state,
EGLNativeWindowType window,
const egl::AttributeMap &attribs)
{
ASSERT(mRenderer != nullptr);
-
- EGLint width = attribs.get(EGL_WIDTH, 0);
- EGLint height = attribs.get(EGL_HEIGHT, 0);
- EGLint fixedSize = attribs.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE);
- EGLint orientation = attribs.get(EGL_SURFACE_ORIENTATION_ANGLE, 0);
- EGLint directComposition = attribs.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE);
-
- if (!fixedSize)
- {
- width = -1;
- height = -1;
- }
-
- return SurfaceD3D::createFromWindow(mRenderer, mDisplay, configuration, window, fixedSize,
- directComposition, width, height, orientation);
+ return new WindowSurfaceD3D(state, mRenderer, mDisplay, window, attribs);
}
-SurfaceImpl *DisplayD3D::createPbufferSurface(const egl::Config *configuration,
+SurfaceImpl *DisplayD3D::createPbufferSurface(const egl::SurfaceState &state,
const egl::AttributeMap &attribs)
{
ASSERT(mRenderer != nullptr);
-
- EGLint width = attribs.get(EGL_WIDTH, 0);
- EGLint height = attribs.get(EGL_HEIGHT, 0);
-
- return SurfaceD3D::createOffscreen(mRenderer, mDisplay, configuration, nullptr, width, height);
+ return new PbufferSurfaceD3D(state, mRenderer, mDisplay, 0, nullptr, attribs);
}
-SurfaceImpl *DisplayD3D::createPbufferFromClientBuffer(const egl::Config *configuration,
- EGLClientBuffer shareHandle,
+SurfaceImpl *DisplayD3D::createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs)
{
ASSERT(mRenderer != nullptr);
-
- EGLint width = attribs.get(EGL_WIDTH, 0);
- EGLint height = attribs.get(EGL_HEIGHT, 0);
-
- return SurfaceD3D::createOffscreen(
- mRenderer, mDisplay, configuration, shareHandle, width, height);
+ return new PbufferSurfaceD3D(state, mRenderer, mDisplay, buftype, clientBuffer, attribs);
}
-SurfaceImpl *DisplayD3D::createPixmapSurface(const egl::Config *configuration,
+SurfaceImpl *DisplayD3D::createPixmapSurface(const egl::SurfaceState &state,
NativePixmapType nativePixmap,
const egl::AttributeMap &attribs)
{
@@ -217,11 +188,11 @@ SurfaceImpl *DisplayD3D::createPixmapSurface(const egl::Config *configuration,
return nullptr;
}
-ImageImpl *DisplayD3D::createImage(EGLenum target,
- egl::ImageSibling *buffer,
+ImageImpl *DisplayD3D::createImage(const egl::ImageState &state,
+ EGLenum target,
const egl::AttributeMap &attribs)
{
- return new EGLImageD3D(mRenderer, target, buffer, attribs);
+ return new EGLImageD3D(state, target, attribs, mRenderer);
}
egl::Error DisplayD3D::getDevice(DeviceImpl **device)
@@ -229,30 +200,31 @@ egl::Error DisplayD3D::getDevice(DeviceImpl **device)
return mRenderer->getEGLDevice(device);
}
-gl::Context *DisplayD3D::createContext(const egl::Config *config,
- const gl::Context *shareContext,
- const egl::AttributeMap &attribs)
+ContextImpl *DisplayD3D::createContext(const gl::ContextState &state)
{
ASSERT(mRenderer != nullptr);
- return new gl::Context(config, shareContext, mRenderer, attribs);
+ return mRenderer->createContext(state);
+}
+
+StreamProducerImpl *DisplayD3D::createStreamProducerD3DTextureNV12(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs)
+{
+ ASSERT(mRenderer != nullptr);
+ return mRenderer->createStreamProducerD3DTextureNV12(consumerType, attribs);
}
egl::Error DisplayD3D::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context)
{
- return egl::Error(EGL_SUCCESS);
+ return egl::NoError();
}
egl::Error DisplayD3D::initialize(egl::Display *display)
{
ASSERT(mRenderer == nullptr && display != nullptr);
mDisplay = display;
- egl::Error error = CreateRendererD3D(display, &mRenderer);
- if (error.isError())
- {
- return error;
- }
-
- return egl::Error(EGL_SUCCESS);
+ ANGLE_TRY(CreateRendererD3D(display, &mRenderer));
+ return egl::NoError();
}
void DisplayD3D::terminate()
@@ -260,32 +232,26 @@ void DisplayD3D::terminate()
SafeDelete(mRenderer);
}
-egl::ConfigSet DisplayD3D::generateConfigs() const
+egl::ConfigSet DisplayD3D::generateConfigs()
{
ASSERT(mRenderer != nullptr);
return mRenderer->generateConfigs();
}
-bool DisplayD3D::isDeviceLost() const
-{
- ASSERT(mRenderer != nullptr);
- return mRenderer->isDeviceLost();
-}
-
bool DisplayD3D::testDeviceLost()
{
ASSERT(mRenderer != nullptr);
return mRenderer->testDeviceLost();
}
-egl::Error DisplayD3D::restoreLostDevice()
+egl::Error DisplayD3D::restoreLostDevice(const egl::Display *display)
{
// Release surface resources to make the Reset() succeed
- for (auto &surface : mSurfaceSet)
+ for (egl::Surface *surface : mState.surfaceSet)
{
if (surface->getBoundTexture())
{
- surface->releaseTexImage(EGL_BACK_BUFFER);
+ ANGLE_TRY(surface->releaseTexImage(display->getProxyContext(), EGL_BACK_BUFFER));
}
SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
surfaceD3D->releaseSwapChain();
@@ -293,27 +259,43 @@ egl::Error DisplayD3D::restoreLostDevice()
if (!mRenderer->resetDevice())
{
- return egl::Error(EGL_BAD_ALLOC);
+ return egl::EglBadAlloc();
}
// Restore any surfaces that may have been lost
- for (const auto &surface : mSurfaceSet)
+ for (const egl::Surface *surface : mState.surfaceSet)
{
SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
- egl::Error error = surfaceD3D->resetSwapChain();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(surfaceD3D->resetSwapChain(display));
}
- return egl::Error(EGL_SUCCESS);
+ return egl::NoError();
}
bool DisplayD3D::isValidNativeWindow(EGLNativeWindowType window) const
{
- return NativeWindow::isValidNativeWindow(window);
+ return mRenderer->isValidNativeWindow(window);
+}
+
+egl::Error DisplayD3D::validateClientBuffer(const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const
+{
+ switch (buftype)
+ {
+ case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
+ return mRenderer->validateShareHandle(configuration, static_cast<HANDLE>(clientBuffer),
+ attribs);
+
+ case EGL_D3D_TEXTURE_ANGLE:
+ return mRenderer->getD3DTextureInfo(
+ configuration, static_cast<IUnknown *>(clientBuffer), nullptr, nullptr, nullptr);
+
+ default:
+ return DisplayImpl::validateClientBuffer(configuration, buftype, clientBuffer, attribs);
+ }
}
void DisplayD3D::generateExtensions(egl::DisplayExtensions *outExtensions) const
@@ -337,20 +319,43 @@ void DisplayD3D::generateCaps(egl::Caps *outCaps) const
// Display must be initialized to generate caps
ASSERT(mRenderer != nullptr);
- outCaps->textureNPOT = mRenderer->getRendererExtensions().textureNPOT;
+ outCaps->textureNPOT = mRenderer->getNativeExtensions().textureNPOT;
}
-egl::Error DisplayD3D::waitClient() const
+egl::Error DisplayD3D::waitClient(const gl::Context *context) const
{
- // Unimplemented as it is a noop on D3D
- return egl::Error(EGL_SUCCESS);
+ for (egl::Surface *surface : mState.surfaceSet)
+ {
+ SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
+ ANGLE_TRY(surfaceD3D->checkForOutOfDateSwapChain(context));
+ }
+
+ return egl::NoError();
}
-egl::Error DisplayD3D::waitNative(EGLint engine,
- egl::Surface *drawSurface,
- egl::Surface *readSurface) const
+egl::Error DisplayD3D::waitNative(const gl::Context *context, EGLint engine) const
{
- // Unimplemented as it is a noop on D3D
- return egl::Error(EGL_SUCCESS);
+ egl::Surface *drawSurface = context->getCurrentDrawSurface();
+ egl::Surface *readSurface = context->getCurrentReadSurface();
+
+ if (drawSurface != nullptr)
+ {
+ SurfaceD3D *drawSurfaceD3D = GetImplAs<SurfaceD3D>(drawSurface);
+ ANGLE_TRY(drawSurfaceD3D->checkForOutOfDateSwapChain(context));
+ }
+
+ if (readSurface != nullptr)
+ {
+ SurfaceD3D *readSurfaceD3D = GetImplAs<SurfaceD3D>(readSurface);
+ ANGLE_TRY(readSurfaceD3D->checkForOutOfDateSwapChain(context));
+ }
+
+ return egl::NoError();
}
+
+gl::Version DisplayD3D::getMaxSupportedESVersion() const
+{
+ return mRenderer->getMaxSupportedESVersion();
}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.h
index 0ce196dea2..7090522312 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.h
@@ -19,50 +19,55 @@ class RendererD3D;
class DisplayD3D : public DisplayImpl
{
public:
- DisplayD3D();
+ DisplayD3D(const egl::DisplayState &state);
egl::Error initialize(egl::Display *display) override;
- virtual void terminate() override;
+ void terminate() override;
// Surface creation
- SurfaceImpl *createWindowSurface(const egl::Config *configuration,
+ SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
EGLNativeWindowType window,
const egl::AttributeMap &attribs) override;
- SurfaceImpl *createPbufferSurface(const egl::Config *configuration,
+ SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
const egl::AttributeMap &attribs) override;
- SurfaceImpl *createPbufferFromClientBuffer(const egl::Config *configuration,
- EGLClientBuffer shareHandle,
+ SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs) override;
- SurfaceImpl *createPixmapSurface(const egl::Config *configuration,
+ SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
NativePixmapType nativePixmap,
const egl::AttributeMap &attribs) override;
- ImageImpl *createImage(EGLenum target,
- egl::ImageSibling *buffer,
+ ImageImpl *createImage(const egl::ImageState &state,
+ EGLenum target,
const egl::AttributeMap &attribs) override;
- gl::Context *createContext(const egl::Config *config,
- const gl::Context *shareContext,
- const egl::AttributeMap &attribs) override;
+ ContextImpl *createContext(const gl::ContextState &state) override;
+
+ StreamProducerImpl *createStreamProducerD3DTextureNV12(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs) override;
egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) override;
- egl::ConfigSet generateConfigs() const override;
+ egl::ConfigSet generateConfigs() override;
- bool isDeviceLost() const override;
bool testDeviceLost() override;
- egl::Error restoreLostDevice() override;
+ egl::Error restoreLostDevice(const egl::Display *display) override;
bool isValidNativeWindow(EGLNativeWindowType window) const override;
+ egl::Error validateClientBuffer(const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const override;
egl::Error getDevice(DeviceImpl **device) override;
std::string getVendorString() const override;
- egl::Error waitClient() const override;
- egl::Error waitNative(EGLint engine,
- egl::Surface *drawSurface,
- egl::Surface *readSurface) const override;
+ egl::Error waitClient(const gl::Context *context) const override;
+ egl::Error waitNative(const gl::Context *context, EGLint engine) const override;
+ gl::Version getMaxSupportedESVersion() const override;
private:
void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
index 42a534f573..b4143a3f5f 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
@@ -8,15 +8,17 @@
#include "libANGLE/renderer/d3d/DynamicHLSL.h"
+#include "common/string_utils.h"
#include "common/utilities.h"
#include "compiler/translator/blocklayoutHLSL.h"
+#include "libANGLE/Context.h"
#include "libANGLE/Program.h"
#include "libANGLE/Shader.h"
+#include "libANGLE/VaryingPacking.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/d3d/ProgramD3D.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/ShaderD3D.h"
-#include "libANGLE/renderer/d3d/VaryingPacking.h"
using namespace gl;
@@ -26,7 +28,28 @@ namespace rx
namespace
{
-std::string HLSLComponentTypeString(GLenum componentType)
+// This class needs to match OutputHLSL::decorate
+class DecorateVariable final : angle::NonCopyable
+{
+ public:
+ explicit DecorateVariable(const std::string &str) : mName(str) {}
+ const std::string &getName() const { return mName; }
+
+ private:
+ const std::string &mName;
+};
+
+std::ostream &operator<<(std::ostream &o, const DecorateVariable &dv)
+{
+ if (dv.getName().compare(0, 3, "gl_") != 0)
+ {
+ o << "_";
+ }
+ o << dv.getName();
+ return o;
+}
+
+const char *HLSLComponentTypeString(GLenum componentType)
{
switch (componentType)
{
@@ -44,12 +67,16 @@ std::string HLSLComponentTypeString(GLenum componentType)
}
}
-std::string HLSLComponentTypeString(GLenum componentType, int componentCount)
+void HLSLComponentTypeString(std::ostringstream &ostream, GLenum componentType, int componentCount)
{
- return HLSLComponentTypeString(componentType) + (componentCount > 1 ? Str(componentCount) : "");
+ ostream << HLSLComponentTypeString(componentType);
+ if (componentCount > 1)
+ {
+ ostream << componentCount;
+ }
}
-std::string HLSLMatrixTypeString(GLenum type)
+const char *HLSLMatrixTypeString(GLenum type)
{
switch (type)
{
@@ -77,15 +104,16 @@ std::string HLSLMatrixTypeString(GLenum type)
}
}
-std::string HLSLTypeString(GLenum type)
+void HLSLTypeString(std::ostringstream &ostream, GLenum type)
{
if (gl::IsMatrixType(type))
{
- return HLSLMatrixTypeString(type);
+ ostream << HLSLMatrixTypeString(type);
+ return;
}
- return HLSLComponentTypeString(gl::VariableComponentType(type),
- gl::VariableComponentCount(type));
+ HLSLComponentTypeString(ostream, gl::VariableComponentType(type),
+ gl::VariableComponentCount(type));
}
const PixelShaderOutputVariable *FindOutputAtLocation(
@@ -103,7 +131,7 @@ const PixelShaderOutputVariable *FindOutputAtLocation(
return nullptr;
}
-void WriteArrayString(std::stringstream &strstr, unsigned int i)
+void WriteArrayString(std::ostringstream &strstr, unsigned int i)
{
static_assert(GL_INVALID_INDEX == UINT_MAX,
"GL_INVALID_INDEX must be equal to the max unsigned int.");
@@ -117,16 +145,14 @@ void WriteArrayString(std::stringstream &strstr, unsigned int i)
strstr << "]";
}
-const std::string VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@";
-const std::string PIXEL_OUTPUT_STUB_STRING = "@@ PIXEL OUTPUT @@";
+constexpr const char *VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@";
+constexpr const char *PIXEL_OUTPUT_STUB_STRING = "@@ PIXEL OUTPUT @@";
} // anonymous namespace
-std::string GetVaryingSemantic(int majorShaderModel, bool programUsesPointSize)
-{
- // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord)
- // In D3D11 we manually compute gl_PointCoord in the GS.
- return ((programUsesPointSize && majorShaderModel < 4) ? "COLOR" : "TEXCOORD");
-}
+// BuiltinInfo implementation
+
+BuiltinInfo::BuiltinInfo() = default;
+BuiltinInfo::~BuiltinInfo() = default;
// DynamicHLSL implementation
@@ -134,55 +160,13 @@ DynamicHLSL::DynamicHLSL(RendererD3D *const renderer) : mRenderer(renderer)
{
}
-void DynamicHLSL::generateVaryingHLSL(const VaryingPacking &varyingPacking,
- std::stringstream &hlslStream) const
-{
- std::string varyingSemantic =
- GetVaryingSemantic(mRenderer->getMajorShaderModel(), varyingPacking.usesPointSize());
-
- for (const PackedVaryingRegister &registerInfo : varyingPacking.getRegisterList())
- {
- const auto &varying = *registerInfo.packedVarying->varying;
- ASSERT(!varying.isStruct());
-
- // TODO: Add checks to ensure D3D interpolation modifiers don't result in too many
- // registers being used.
- // For example, if there are N registers, and we have N vec3 varyings and 1 float
- // varying, then D3D will pack them into N registers.
- // If the float varying has the 'nointerpolation' modifier on it then we would need
- // N + 1 registers, and D3D compilation will fail.
-
- switch (registerInfo.packedVarying->interpolation)
- {
- case sh::INTERPOLATION_SMOOTH:
- hlslStream << " ";
- break;
- case sh::INTERPOLATION_FLAT:
- hlslStream << " nointerpolation ";
- break;
- case sh::INTERPOLATION_CENTROID:
- hlslStream << " centroid ";
- break;
- default:
- UNREACHABLE();
- }
-
- GLenum transposedType = gl::TransposeMatrixType(varying.type);
- GLenum componentType = gl::VariableComponentType(transposedType);
- int columnCount = gl::VariableColumnCount(transposedType);
- hlslStream << HLSLComponentTypeString(componentType, columnCount);
- unsigned int semanticIndex = registerInfo.semanticIndex;
- hlslStream << " v" << semanticIndex << " : " << varyingSemantic << semanticIndex << ";\n";
- }
-}
-
std::string DynamicHLSL::generateVertexShaderForInputLayout(
const std::string &sourceShader,
const InputLayout &inputLayout,
const std::vector<sh::Attribute> &shaderAttributes) const
{
- std::stringstream structStream;
- std::stringstream initStream;
+ std::ostringstream structStream;
+ std::ostringstream initStream;
structStream << "struct VS_INPUT\n"
<< "{\n";
@@ -231,26 +215,31 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(
{
GLenum componentType = mRenderer->getVertexComponentType(vertexFormatType);
- if (shaderAttribute.name == "gl_InstanceID")
+ if (shaderAttribute.name == "gl_InstanceID" ||
+ shaderAttribute.name == "gl_VertexID")
{
- // The input type of the instance ID in HLSL (uint) differs from the one in ESSL
- // (int).
+ // The input types of the instance ID and vertex ID in HLSL (uint) differs from
+ // the ones in ESSL (int).
structStream << " uint";
}
else
{
- structStream << " " << HLSLComponentTypeString(
- componentType,
- VariableComponentCount(shaderAttribute.type));
+ structStream << " ";
+ HLSLComponentTypeString(structStream, componentType,
+ VariableComponentCount(shaderAttribute.type));
}
}
- structStream << " " << decorateVariable(shaderAttribute.name) << " : ";
+ structStream << " " << DecorateVariable(shaderAttribute.name) << " : ";
if (shaderAttribute.name == "gl_InstanceID")
{
structStream << "SV_InstanceID";
}
+ else if (shaderAttribute.name == "gl_VertexID")
+ {
+ structStream << "SV_VertexID";
+ }
else
{
structStream << "TEXCOORD" << semanticIndex;
@@ -260,7 +249,7 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(
structStream << ";\n";
// HLSL code for initialization
- initStream << " " << decorateVariable(shaderAttribute.name) << " = ";
+ initStream << " " << DecorateVariable(shaderAttribute.name) << " = ";
// Mismatched vertex attribute to vertex input may result in an undefined
// data reinterpretation (eg for pure integer->float, float->pure integer)
@@ -268,11 +257,11 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(
if (IsMatrixType(shaderAttribute.type) ||
(mRenderer->getVertexConversionType(vertexFormatType) & VERTEX_CONVERT_GPU) != 0)
{
- initStream << generateAttributeConversionHLSL(vertexFormatType, shaderAttribute);
+ GenerateAttributeConversionHLSL(vertexFormatType, shaderAttribute, initStream);
}
else
{
- initStream << "input." << decorateVariable(shaderAttribute.name);
+ initStream << "input." << DecorateVariable(shaderAttribute.name);
}
initStream << ";\n";
@@ -289,8 +278,9 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(
std::string vertexHLSL(sourceShader);
- size_t copyInsertionPos = vertexHLSL.find(VERTEX_ATTRIBUTE_STUB_STRING);
- vertexHLSL.replace(copyInsertionPos, VERTEX_ATTRIBUTE_STUB_STRING.length(), structStream.str());
+ bool success =
+ angle::ReplaceSubstring(&vertexHLSL, VERTEX_ATTRIBUTE_STUB_STRING, structStream.str());
+ ASSERT(success);
return vertexHLSL;
}
@@ -305,22 +295,32 @@ std::string DynamicHLSL::generatePixelShaderForOutputSignature(
std::string targetSemantic = (shaderModel >= 4) ? "SV_TARGET" : "COLOR";
std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH";
- std::stringstream declarationStream;
- std::stringstream copyStream;
+ std::ostringstream declarationStream;
+ std::ostringstream copyStream;
declarationStream << "struct PS_OUTPUT\n"
"{\n";
- for (size_t layoutIndex = 0; layoutIndex < outputLayout.size(); ++layoutIndex)
+ size_t numOutputs = outputLayout.size();
+
+ // Workaround for HLSL 3.x: We can't do a depth/stencil only render, the runtime will complain.
+ if (numOutputs == 0 && (shaderModel == 3 || !mRenderer->getShaderModelSuffix().empty()))
+ {
+ numOutputs = 1u;
+ }
+ const PixelShaderOutputVariable defaultOutput(GL_FLOAT_VEC4, "dummy", "float4(0, 0, 0, 1)", 0);
+
+ for (size_t layoutIndex = 0; layoutIndex < numOutputs; ++layoutIndex)
{
- GLenum binding = outputLayout[layoutIndex];
+ GLenum binding = outputLayout.empty() ? GL_COLOR_ATTACHMENT0 : outputLayout[layoutIndex];
if (binding != GL_NONE)
{
unsigned int location = (binding - GL_COLOR_ATTACHMENT0);
const PixelShaderOutputVariable *outputVariable =
- FindOutputAtLocation(outputVariables, location);
+ outputLayout.empty() ? &defaultOutput
+ : FindOutputAtLocation(outputVariables, location);
// OpenGL ES 3.0 spec $4.2.1
// If [...] not all user-defined output variables are written, the values of fragment
@@ -328,8 +328,9 @@ std::string DynamicHLSL::generatePixelShaderForOutputSignature(
// corresponding to unwritten variables are similarly undefined.
if (outputVariable)
{
- declarationStream << " " + HLSLTypeString(outputVariable->type) << " "
- << outputVariable->name << " : " << targetSemantic
+ declarationStream << " ";
+ HLSLTypeString(declarationStream, outputVariable->type);
+ declarationStream << " " << outputVariable->name << " : " << targetSemantic
<< static_cast<int>(layoutIndex) << ";\n";
copyStream << " output." << outputVariable->name << " = "
@@ -354,61 +355,113 @@ std::string DynamicHLSL::generatePixelShaderForOutputSignature(
std::string pixelHLSL(sourceShader);
- size_t outputInsertionPos = pixelHLSL.find(PIXEL_OUTPUT_STUB_STRING);
- pixelHLSL.replace(outputInsertionPos, PIXEL_OUTPUT_STUB_STRING.length(),
- declarationStream.str());
+ bool success =
+ angle::ReplaceSubstring(&pixelHLSL, PIXEL_OUTPUT_STUB_STRING, declarationStream.str());
+ ASSERT(success);
return pixelHLSL;
}
-void DynamicHLSL::generateVaryingLinkHLSL(ShaderType shaderType,
- const VaryingPacking &varyingPacking,
- std::stringstream &linkStream) const
+void DynamicHLSL::generateVaryingLinkHLSL(const VaryingPacking &varyingPacking,
+ const BuiltinInfo &builtins,
+ bool programUsesPointSize,
+ std::ostringstream &hlslStream) const
{
- const auto &builtins = varyingPacking.builtins(shaderType);
ASSERT(builtins.dxPosition.enabled);
- linkStream << "{\n"
+ hlslStream << "{\n"
<< " float4 dx_Position : " << builtins.dxPosition.str() << ";\n";
if (builtins.glPosition.enabled)
{
- linkStream << " float4 gl_Position : " << builtins.glPosition.str() << ";\n";
+ hlslStream << " float4 gl_Position : " << builtins.glPosition.str() << ";\n";
}
if (builtins.glFragCoord.enabled)
{
- linkStream << " float4 gl_FragCoord : " << builtins.glFragCoord.str() << ";\n";
+ hlslStream << " float4 gl_FragCoord : " << builtins.glFragCoord.str() << ";\n";
}
if (builtins.glPointCoord.enabled)
{
- linkStream << " float2 gl_PointCoord : " << builtins.glPointCoord.str() << ";\n";
+ hlslStream << " float2 gl_PointCoord : " << builtins.glPointCoord.str() << ";\n";
}
if (builtins.glPointSize.enabled)
{
- linkStream << " float gl_PointSize : " << builtins.glPointSize.str() << ";\n";
+ hlslStream << " float gl_PointSize : " << builtins.glPointSize.str() << ";\n";
+ }
+
+ if (builtins.glViewIDOVR.enabled)
+ {
+ hlslStream << " nointerpolation uint gl_ViewID_OVR : " << builtins.glViewIDOVR.str()
+ << ";\n";
+ }
+
+ if (builtins.glViewportIndex.enabled)
+ {
+ hlslStream << " nointerpolation uint gl_ViewportIndex : "
+ << builtins.glViewportIndex.str() << ";\n";
+ }
+
+ if (builtins.glLayer.enabled)
+ {
+ hlslStream << " nointerpolation uint gl_Layer : " << builtins.glLayer.str() << ";\n";
}
- // Do this after glPointSize, to potentially combine gl_PointCoord and gl_PointSize into the
- // same register.
- generateVaryingHLSL(varyingPacking, linkStream);
+ std::string varyingSemantic =
+ GetVaryingSemantic(mRenderer->getMajorShaderModel(), programUsesPointSize);
- linkStream << "};\n";
+ for (const PackedVaryingRegister &registerInfo : varyingPacking.getRegisterList())
+ {
+ const auto &varying = *registerInfo.packedVarying->varying;
+ ASSERT(!varying.isStruct());
+
+ // TODO: Add checks to ensure D3D interpolation modifiers don't result in too many
+ // registers being used.
+ // For example, if there are N registers, and we have N vec3 varyings and 1 float
+ // varying, then D3D will pack them into N registers.
+ // If the float varying has the 'nointerpolation' modifier on it then we would need
+ // N + 1 registers, and D3D compilation will fail.
+
+ switch (registerInfo.packedVarying->interpolation)
+ {
+ case sh::INTERPOLATION_SMOOTH:
+ hlslStream << " ";
+ break;
+ case sh::INTERPOLATION_FLAT:
+ hlslStream << " nointerpolation ";
+ break;
+ case sh::INTERPOLATION_CENTROID:
+ hlslStream << " centroid ";
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ GLenum transposedType = gl::TransposeMatrixType(varying.type);
+ GLenum componentType = gl::VariableComponentType(transposedType);
+ int columnCount = gl::VariableColumnCount(transposedType);
+ HLSLComponentTypeString(hlslStream, componentType, columnCount);
+ unsigned int semanticIndex = registerInfo.semanticIndex;
+ hlslStream << " v" << semanticIndex << " : " << varyingSemantic << semanticIndex << ";\n";
+ }
+
+ hlslStream << "};\n";
}
-bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
- const gl::Program::Data &programData,
+void DynamicHLSL::generateShaderLinkHLSL(const gl::Context *context,
+ const gl::ProgramState &programData,
const ProgramD3DMetadata &programMetadata,
const VaryingPacking &varyingPacking,
+ const BuiltinVaryingsD3D &builtinsD3D,
std::string *pixelHLSL,
std::string *vertexHLSL) const
{
ASSERT(pixelHLSL->empty() && vertexHLSL->empty());
- const gl::Shader *vertexShaderGL = programData.getAttachedVertexShader();
- const ShaderD3D *vertexShader = GetImplAs<ShaderD3D>(vertexShaderGL);
- const gl::Shader *fragmentShaderGL = programData.getAttachedFragmentShader();
+ const auto &data = context->getContextState();
+ gl::Shader *vertexShaderGL = programData.getAttachedVertexShader();
+ gl::Shader *fragmentShaderGL = programData.getAttachedFragmentShader();
const ShaderD3D *fragmentShader = GetImplAs<ShaderD3D>(fragmentShaderGL);
const int shaderModel = mRenderer->getMajorShaderModel();
@@ -422,48 +475,59 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
// Validation done in the compiler
ASSERT(!fragmentShader->usesFragColor() || !fragmentShader->usesFragData());
- std::stringstream vertexStream;
- vertexStream << vertexShaderGL->getTranslatedSource();
+ std::ostringstream vertexStream;
+ vertexStream << vertexShaderGL->getTranslatedSource(context);
// Instanced PointSprite emulation requires additional entries originally generated in the
// GeometryShader HLSL. These include pointsize clamp values.
if (useInstancedPointSpriteEmulation)
{
vertexStream << "static float minPointSize = "
- << static_cast<int>(data.caps->minAliasedPointSize) << ".0f;\n"
+ << static_cast<int>(data.getCaps().minAliasedPointSize) << ".0f;\n"
<< "static float maxPointSize = "
- << static_cast<int>(data.caps->maxAliasedPointSize) << ".0f;\n";
+ << static_cast<int>(data.getCaps().maxAliasedPointSize) << ".0f;\n";
}
// Add stub string to be replaced when shader is dynamically defined by its layout
- vertexStream << "\n" << VERTEX_ATTRIBUTE_STUB_STRING + "\n";
+ vertexStream << "\n" << std::string(VERTEX_ATTRIBUTE_STUB_STRING) << "\n";
+
+ const auto &vertexBuiltins = builtinsD3D[gl::SHADER_VERTEX];
// Write the HLSL input/output declarations
vertexStream << "struct VS_OUTPUT\n";
- generateVaryingLinkHLSL(SHADER_VERTEX, varyingPacking, vertexStream);
+ generateVaryingLinkHLSL(varyingPacking, vertexBuiltins, builtinsD3D.usesPointSize(),
+ vertexStream);
vertexStream << "\n"
<< "VS_OUTPUT main(VS_INPUT input)\n"
<< "{\n"
<< " initAttributes(input);\n";
- if (vertexShader->usesDeferredInit())
- {
- vertexStream << "\n"
- << " initializeDeferredGlobals();\n";
- }
-
vertexStream << "\n"
<< " gl_main();\n"
<< "\n"
<< " VS_OUTPUT output;\n";
- const auto &vertexBuiltins = varyingPacking.builtins(SHADER_VERTEX);
-
if (vertexBuiltins.glPosition.enabled)
{
vertexStream << " output.gl_Position = gl_Position;\n";
}
+ if (vertexBuiltins.glViewIDOVR.enabled)
+ {
+ vertexStream << " output.gl_ViewID_OVR = _ViewID_OVR;\n";
+ }
+ if (programMetadata.hasANGLEMultiviewEnabled() && programMetadata.canSelectViewInVertexShader())
+ {
+ ASSERT(vertexBuiltins.glViewportIndex.enabled && vertexBuiltins.glLayer.enabled);
+ vertexStream << " if (multiviewSelectViewportIndex)\n"
+ << " {\n"
+ << " output.gl_ViewportIndex = _ViewID_OVR;\n"
+ << " } else {\n"
+ << " output.gl_ViewportIndex = 0;\n"
+ << " output.gl_Layer = _ViewID_OVR;\n"
+ << " }\n";
+ }
+
// On D3D9 or D3D11 Feature Level 9, we need to emulate large viewports using dx_ViewAdjust.
if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "")
{
@@ -528,10 +592,10 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
if (packedVarying.isStructField())
{
- vertexStream << decorateVariable(packedVarying.parentStructName) << ".";
+ vertexStream << DecorateVariable(packedVarying.parentStructName) << ".";
}
- vertexStream << decorateVariable(varying.name);
+ vertexStream << DecorateVariable(varying.name);
if (varying.isArray())
{
@@ -593,13 +657,16 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
<< " return output;\n"
<< "}\n";
- std::stringstream pixelStream;
- pixelStream << fragmentShaderGL->getTranslatedSource();
+ const auto &pixelBuiltins = builtinsD3D[gl::SHADER_FRAGMENT];
+
+ std::ostringstream pixelStream;
+ pixelStream << fragmentShaderGL->getTranslatedSource(context);
pixelStream << "struct PS_INPUT\n";
- generateVaryingLinkHLSL(SHADER_PIXEL, varyingPacking, pixelStream);
+ generateVaryingLinkHLSL(varyingPacking, pixelBuiltins, builtinsD3D.usesPointSize(),
+ pixelStream);
pixelStream << "\n";
- pixelStream << PIXEL_OUTPUT_STUB_STRING + "\n";
+ pixelStream << std::string(PIXEL_OUTPUT_STUB_STRING) << "\n";
if (fragmentShader->usesFrontFacing())
{
@@ -620,7 +687,11 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
<< "{\n";
}
- const auto &pixelBuiltins = varyingPacking.builtins(SHADER_PIXEL);
+ if (fragmentShader->usesViewID())
+ {
+ ASSERT(pixelBuiltins.glViewIDOVR.enabled);
+ pixelStream << " _ViewID_OVR = input.gl_ViewID_OVR;\n";
+ }
if (pixelBuiltins.glFragCoord.enabled)
{
@@ -721,18 +792,19 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
const auto &varying = *packedVarying.varying;
ASSERT(!varying.isBuiltIn() && !varying.isStruct());
- // Don't reference VS-only transform feedback varyings in the PS.
- if (registerInfo.packedVarying->vertexOnly)
+ // Don't reference VS-only transform feedback varyings in the PS. Note that we're relying on
+ // that the staticUse flag is set according to usage in the fragment shader.
+ if (packedVarying.vertexOnly || !varying.staticUse)
continue;
pixelStream << " ";
if (packedVarying.isStructField())
{
- pixelStream << decorateVariable(packedVarying.parentStructName) << ".";
+ pixelStream << DecorateVariable(packedVarying.parentStructName) << ".";
}
- pixelStream << decorateVariable(varying.name);
+ pixelStream << DecorateVariable(varying.name);
if (varying.isArray())
{
@@ -766,12 +838,6 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
pixelStream << ";\n";
}
- if (fragmentShader->usesDeferredInit())
- {
- pixelStream << "\n"
- << " initializeDeferredGlobals();\n";
- }
-
pixelStream << "\n"
<< " gl_main();\n"
<< "\n"
@@ -780,34 +846,126 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data,
*vertexHLSL = vertexStream.str();
*pixelHLSL = pixelStream.str();
+}
+
+std::string DynamicHLSL::generateComputeShaderLinkHLSL(const gl::Context *context,
+ const gl::ProgramState &programData) const
+{
+ gl::Shader *computeShaderGL = programData.getAttachedComputeShader();
+ std::stringstream computeStream;
+ std::string translatedSource = computeShaderGL->getTranslatedSource(context);
+ computeStream << translatedSource;
+
+ bool usesWorkGroupID = translatedSource.find("GL_USES_WORK_GROUP_ID") != std::string::npos;
+ bool usesLocalInvocationID =
+ translatedSource.find("GL_USES_LOCAL_INVOCATION_ID") != std::string::npos;
+ bool usesGlobalInvocationID =
+ translatedSource.find("GL_USES_GLOBAL_INVOCATION_ID") != std::string::npos;
+ bool usesLocalInvocationIndex =
+ translatedSource.find("GL_USES_LOCAL_INVOCATION_INDEX") != std::string::npos;
+
+ computeStream << "\nstruct CS_INPUT\n{\n";
+ if (usesWorkGroupID)
+ {
+ computeStream << " uint3 dx_WorkGroupID : "
+ << "SV_GroupID;\n";
+ }
- return true;
+ if (usesLocalInvocationID)
+ {
+ computeStream << " uint3 dx_LocalInvocationID : "
+ << "SV_GroupThreadID;\n";
+ }
+
+ if (usesGlobalInvocationID)
+ {
+ computeStream << " uint3 dx_GlobalInvocationID : "
+ << "SV_DispatchThreadID;\n";
+ }
+
+ if (usesLocalInvocationIndex)
+ {
+ computeStream << " uint dx_LocalInvocationIndex : "
+ << "SV_GroupIndex;\n";
+ }
+
+ computeStream << "};\n\n";
+
+ const sh::WorkGroupSize &localSize = computeShaderGL->getWorkGroupSize(context);
+ computeStream << "[numthreads(" << localSize[0] << ", " << localSize[1] << ", " << localSize[2]
+ << ")]\n";
+
+ computeStream << "void main(CS_INPUT input)\n"
+ << "{\n";
+
+ if (usesWorkGroupID)
+ {
+ computeStream << " gl_WorkGroupID = input.dx_WorkGroupID;\n";
+ }
+ if (usesLocalInvocationID)
+ {
+ computeStream << " gl_LocalInvocationID = input.dx_LocalInvocationID;\n";
+ }
+ if (usesGlobalInvocationID)
+ {
+ computeStream << " gl_GlobalInvocationID = input.dx_GlobalInvocationID;\n";
+ }
+ if (usesLocalInvocationIndex)
+ {
+ computeStream << " gl_LocalInvocationIndex = input.dx_LocalInvocationIndex;\n";
+ }
+
+ computeStream << "\n"
+ << " gl_main();\n"
+ << "}\n";
+
+ return computeStream.str();
}
-std::string DynamicHLSL::generateGeometryShaderPreamble(const VaryingPacking &varyingPacking) const
+std::string DynamicHLSL::generateGeometryShaderPreamble(const VaryingPacking &varyingPacking,
+ const BuiltinVaryingsD3D &builtinsD3D,
+ const bool hasANGLEMultiviewEnabled,
+ const bool selectViewInVS) const
{
ASSERT(mRenderer->getMajorShaderModel() >= 4);
- std::stringstream preambleStream;
+ std::ostringstream preambleStream;
- const auto &builtins = varyingPacking.builtins(SHADER_VERTEX);
+ const auto &vertexBuiltins = builtinsD3D[gl::SHADER_VERTEX];
preambleStream << "struct GS_INPUT\n";
- generateVaryingLinkHLSL(SHADER_VERTEX, varyingPacking, preambleStream);
+ generateVaryingLinkHLSL(varyingPacking, vertexBuiltins, builtinsD3D.usesPointSize(),
+ preambleStream);
preambleStream << "\n"
<< "struct GS_OUTPUT\n";
- generateVaryingLinkHLSL(SHADER_GEOMETRY, varyingPacking, preambleStream);
+ generateVaryingLinkHLSL(varyingPacking, builtinsD3D[gl::SHADER_GEOMETRY],
+ builtinsD3D.usesPointSize(), preambleStream);
preambleStream
<< "\n"
<< "void copyVertex(inout GS_OUTPUT output, GS_INPUT input, GS_INPUT flatinput)\n"
<< "{\n"
<< " output.gl_Position = input.gl_Position;\n";
- if (builtins.glPointSize.enabled)
+ if (vertexBuiltins.glPointSize.enabled)
{
preambleStream << " output.gl_PointSize = input.gl_PointSize;\n";
}
+ if (hasANGLEMultiviewEnabled)
+ {
+ preambleStream << " output.gl_ViewID_OVR = input.gl_ViewID_OVR;\n";
+ if (selectViewInVS)
+ {
+ ASSERT(builtinsD3D[gl::SHADER_GEOMETRY].glViewportIndex.enabled &&
+ builtinsD3D[gl::SHADER_GEOMETRY].glLayer.enabled);
+
+ // If the view is already selected in the VS, then we just pass the gl_ViewportIndex and
+ // gl_Layer to the output.
+ preambleStream << " output.gl_ViewportIndex = input.gl_ViewportIndex;\n"
+ << " output.gl_Layer = input.gl_Layer;\n";
+ }
+ }
+
for (const PackedVaryingRegister &varyingRegister : varyingPacking.getRegisterList())
{
preambleStream << " output.v" << varyingRegister.semanticIndex << " = ";
@@ -818,7 +976,7 @@ std::string DynamicHLSL::generateGeometryShaderPreamble(const VaryingPacking &va
preambleStream << "input.v" << varyingRegister.semanticIndex << "; \n";
}
- if (builtins.glFragCoord.enabled)
+ if (vertexBuiltins.glFragCoord.enabled)
{
preambleStream << " output.gl_FragCoord = input.gl_FragCoord;\n";
}
@@ -829,20 +987,46 @@ std::string DynamicHLSL::generateGeometryShaderPreamble(const VaryingPacking &va
<< "#endif // ANGLE_POINT_SPRITE_SHADER\n"
<< "}\n";
+ if (hasANGLEMultiviewEnabled && !selectViewInVS)
+ {
+ ASSERT(builtinsD3D[gl::SHADER_GEOMETRY].glViewportIndex.enabled &&
+ builtinsD3D[gl::SHADER_GEOMETRY].glLayer.enabled);
+
+ // According to the HLSL reference, using SV_RenderTargetArrayIndex is only valid if the
+ // render target is an array resource. Because of this we do not write to gl_Layer if we are
+ // taking the side-by-side code path. We still select the viewport index in the layered code
+ // path as that is always valid. See:
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/bb509647(v=vs.85).aspx
+ preambleStream << "\n"
+ << "void selectView(inout GS_OUTPUT output, GS_INPUT input)\n"
+ << "{\n"
+ << " if (multiviewSelectViewportIndex)\n"
+ << " {\n"
+ << " output.gl_ViewportIndex = input.gl_ViewID_OVR;\n"
+ << " } else {\n"
+ << " output.gl_ViewportIndex = 0;\n"
+ << " output.gl_Layer = input.gl_ViewID_OVR;\n"
+ << " }\n"
+ << "}\n";
+ }
+
return preambleStream.str();
}
-std::string DynamicHLSL::generateGeometryShaderHLSL(gl::PrimitiveType primitiveType,
- const gl::Data &data,
- const gl::Program::Data &programData,
+std::string DynamicHLSL::generateGeometryShaderHLSL(const gl::Context *context,
+ gl::PrimitiveType primitiveType,
+ const gl::ProgramState &programData,
const bool useViewScale,
+ const bool hasANGLEMultiviewEnabled,
+ const bool selectViewInVS,
+ const bool pointSpriteEmulation,
const std::string &preambleString) const
{
ASSERT(mRenderer->getMajorShaderModel() >= 4);
std::stringstream shaderStream;
- const bool pointSprites = (primitiveType == PRIMITIVE_POINTS);
+ const bool pointSprites = (primitiveType == PRIMITIVE_POINTS) && pointSpriteEmulation;
const bool usesPointCoord = preambleString.find("gl_PointCoord") != std::string::npos;
const char *inputPT = nullptr;
@@ -854,9 +1038,19 @@ std::string DynamicHLSL::generateGeometryShaderHLSL(gl::PrimitiveType primitiveT
{
case PRIMITIVE_POINTS:
inputPT = "point";
- outputPT = "Triangle";
inputSize = 1;
- maxVertexOutput = 4;
+
+ if (pointSprites)
+ {
+ outputPT = "Triangle";
+ maxVertexOutput = 4;
+ }
+ else
+ {
+ outputPT = "Point";
+ maxVertexOutput = 1;
+ }
+
break;
case PRIMITIVE_LINES:
@@ -882,18 +1076,34 @@ std::string DynamicHLSL::generateGeometryShaderHLSL(gl::PrimitiveType primitiveT
break;
}
- if (pointSprites)
+ if (pointSprites || hasANGLEMultiviewEnabled)
{
- shaderStream << "#define ANGLE_POINT_SPRITE_SHADER\n"
- "\n"
- "uniform float4 dx_ViewCoords : register(c1);\n";
+ shaderStream << "cbuffer DriverConstants : register(b0)\n"
+ "{\n";
+
+ if (pointSprites)
+ {
+ shaderStream << " float4 dx_ViewCoords : packoffset(c1);\n";
+ if (useViewScale)
+ {
+ shaderStream << " float2 dx_ViewScale : packoffset(c3);\n";
+ }
+ }
- if (useViewScale)
+ if (hasANGLEMultiviewEnabled)
{
- shaderStream << "uniform float2 dx_ViewScale : register(c3);\n";
+ // We have to add a value which we can use to keep track of which multi-view code path
+ // is to be selected in the GS.
+ shaderStream << " float multiviewSelectViewportIndex : packoffset(c3.z);\n";
}
- shaderStream << "\n"
+ shaderStream << "};\n\n";
+ }
+
+ if (pointSprites)
+ {
+ shaderStream << "#define ANGLE_POINT_SPRITE_SHADER\n"
+ "\n"
"static float2 pointSpriteCorners[] = \n"
"{\n"
" float2( 0.5f, -0.5f),\n"
@@ -911,10 +1121,10 @@ std::string DynamicHLSL::generateGeometryShaderHLSL(gl::PrimitiveType primitiveT
"};\n"
"\n"
"static float minPointSize = "
- << static_cast<int>(data.caps->minAliasedPointSize)
+ << static_cast<int>(context->getCaps().minAliasedPointSize)
<< ".0f;\n"
"static float maxPointSize = "
- << static_cast<int>(data.caps->maxAliasedPointSize) << ".0f;\n"
+ << static_cast<int>(context->getCaps().maxAliasedPointSize) << ".0f;\n"
<< "\n";
}
@@ -944,7 +1154,10 @@ std::string DynamicHLSL::generateGeometryShaderHLSL(gl::PrimitiveType primitiveT
{
shaderStream << " copyVertex(output, input[" << vertexIndex
<< "], input[lastVertexIndex]);\n";
-
+ if (hasANGLEMultiviewEnabled && !selectViewInVS)
+ {
+ shaderStream << " selectView(output, input[" << vertexIndex << "]);\n";
+ }
if (!pointSprites)
{
ASSERT(inputSize == maxVertexOutput);
@@ -995,50 +1208,38 @@ std::string DynamicHLSL::generateGeometryShaderHLSL(gl::PrimitiveType primitiveT
return shaderStream.str();
}
-// This method needs to match OutputHLSL::decorate
-std::string DynamicHLSL::decorateVariable(const std::string &name)
-{
- if (name.compare(0, 3, "gl_") != 0)
- {
- return "_" + name;
- }
-
- return name;
-}
-
-std::string DynamicHLSL::generateAttributeConversionHLSL(
- gl::VertexFormatType vertexFormatType,
- const sh::ShaderVariable &shaderAttrib) const
+// static
+void DynamicHLSL::GenerateAttributeConversionHLSL(gl::VertexFormatType vertexFormatType,
+ const sh::ShaderVariable &shaderAttrib,
+ std::ostringstream &outStream)
{
- const gl::VertexFormat &vertexFormat = gl::GetVertexFormatFromType(vertexFormatType);
- std::string attribString = "input." + decorateVariable(shaderAttrib.name);
-
// Matrix
if (IsMatrixType(shaderAttrib.type))
{
- return "transpose(" + attribString + ")";
+ outStream << "transpose(input." << DecorateVariable(shaderAttrib.name) << ")";
+ return;
}
GLenum shaderComponentType = VariableComponentType(shaderAttrib.type);
int shaderComponentCount = VariableComponentCount(shaderAttrib.type);
+ const gl::VertexFormat &vertexFormat = gl::GetVertexFormatFromType(vertexFormatType);
// Perform integer to float conversion (if necessary)
- bool requiresTypeConversion =
- (shaderComponentType == GL_FLOAT && vertexFormat.type != GL_FLOAT);
-
- if (requiresTypeConversion)
+ if (shaderComponentType == GL_FLOAT && vertexFormat.type != GL_FLOAT)
{
// TODO: normalization for 32-bit integer formats
ASSERT(!vertexFormat.normalized && !vertexFormat.pureInteger);
- return "float" + Str(shaderComponentCount) + "(" + attribString + ")";
+ outStream << "float" << shaderComponentCount << "(input."
+ << DecorateVariable(shaderAttrib.name) << ")";
+ return;
}
// No conversion necessary
- return attribString;
+ outStream << "input." << DecorateVariable(shaderAttrib.name);
}
-void DynamicHLSL::getPixelShaderOutputKey(const gl::Data &data,
- const gl::Program::Data &programData,
+void DynamicHLSL::getPixelShaderOutputKey(const gl::ContextState &data,
+ const gl::ProgramState &programData,
const ProgramD3DMetadata &metadata,
std::vector<PixelShaderOutputVariable> *outPixelShaderKey)
{
@@ -1047,7 +1248,7 @@ void DynamicHLSL::getPixelShaderOutputKey(const gl::Data &data,
// - with a 2.0 context, the output color is broadcast to all channels
bool broadcast = metadata.usesBroadcast(data);
const unsigned int numRenderTargets =
- (broadcast || metadata.usesMultipleFragmentOuts() ? data.caps->maxDrawBuffers : 1);
+ (broadcast || metadata.usesMultipleFragmentOuts() ? data.getCaps().maxDrawBuffers : 1);
if (metadata.getMajorShaderVersion() < 300)
{
@@ -1069,25 +1270,158 @@ void DynamicHLSL::getPixelShaderOutputKey(const gl::Data &data,
const auto &shaderOutputVars =
metadata.getFragmentShader()->getData().getActiveOutputVariables();
- for (auto outputPair : programData.getOutputVariables())
+ for (size_t outputLocationIndex = 0u;
+ outputLocationIndex < programData.getOutputLocations().size(); ++outputLocationIndex)
{
- const VariableLocation &outputLocation = outputPair.second;
+ const VariableLocation &outputLocation =
+ programData.getOutputLocations().at(outputLocationIndex);
+ if (!outputLocation.used())
+ {
+ continue;
+ }
const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index];
- const std::string &variableName = "out_" + outputLocation.name;
+ const std::string &variableName = "out_" + outputVariable.name;
+
+ // Fragment outputs can't be arrays of arrays. ESSL 3.10 section 4.3.6.
const std::string &elementString =
- (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element));
+ (outputVariable.isArray() ? Str(outputLocation.arrayIndex) : "");
ASSERT(outputVariable.staticUse);
PixelShaderOutputVariable outputKeyVariable;
outputKeyVariable.type = outputVariable.type;
outputKeyVariable.name = variableName + elementString;
- outputKeyVariable.source = variableName + ArrayString(outputLocation.element);
- outputKeyVariable.outputIndex = outputPair.first;
+ outputKeyVariable.source =
+ variableName +
+ (outputVariable.isArray() ? ArrayString(outputLocation.arrayIndex) : "");
+ outputKeyVariable.outputIndex = outputLocationIndex;
outPixelShaderKey->push_back(outputKeyVariable);
}
}
}
+// BuiltinVarying Implementation.
+BuiltinVarying::BuiltinVarying() : enabled(false), index(0), systemValue(false)
+{
+}
+
+std::string BuiltinVarying::str() const
+{
+ return (systemValue ? semantic : (semantic + Str(index)));
+}
+
+void BuiltinVarying::enableSystem(const std::string &systemValueSemantic)
+{
+ enabled = true;
+ semantic = systemValueSemantic;
+ systemValue = true;
+}
+
+void BuiltinVarying::enable(const std::string &semanticVal, unsigned int indexVal)
+{
+ enabled = true;
+ semantic = semanticVal;
+ index = indexVal;
+}
+
+// BuiltinVaryingsD3D Implementation.
+BuiltinVaryingsD3D::BuiltinVaryingsD3D(const ProgramD3DMetadata &metadata,
+ const VaryingPacking &packing)
+{
+ updateBuiltins(gl::SHADER_VERTEX, metadata, packing);
+ updateBuiltins(gl::SHADER_FRAGMENT, metadata, packing);
+ if (metadata.getRendererMajorShaderModel() >= 4)
+ {
+ updateBuiltins(gl::SHADER_GEOMETRY, metadata, packing);
+ }
+}
+
+BuiltinVaryingsD3D::~BuiltinVaryingsD3D() = default;
+
+void BuiltinVaryingsD3D::updateBuiltins(gl::ShaderType shaderType,
+ const ProgramD3DMetadata &metadata,
+ const VaryingPacking &packing)
+{
+ const std::string &userSemantic = GetVaryingSemantic(metadata.getRendererMajorShaderModel(),
+ metadata.usesSystemValuePointSize());
+
+ unsigned int reservedSemanticIndex = packing.getMaxSemanticIndex();
+
+ BuiltinInfo *builtins = &mBuiltinInfo[shaderType];
+
+ if (metadata.getRendererMajorShaderModel() >= 4)
+ {
+ builtins->dxPosition.enableSystem("SV_Position");
+ }
+ else if (shaderType == gl::SHADER_FRAGMENT)
+ {
+ builtins->dxPosition.enableSystem("VPOS");
+ }
+ else
+ {
+ builtins->dxPosition.enableSystem("POSITION");
+ }
+
+ if (metadata.usesTransformFeedbackGLPosition())
+ {
+ builtins->glPosition.enable(userSemantic, reservedSemanticIndex++);
+ }
+
+ if (metadata.usesFragCoord())
+ {
+ builtins->glFragCoord.enable(userSemantic, reservedSemanticIndex++);
+ }
+
+ if (shaderType == gl::SHADER_VERTEX ? metadata.addsPointCoordToVertexShader()
+ : metadata.usesPointCoord())
+ {
+ // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord)
+ // In D3D11 we manually compute gl_PointCoord in the GS.
+ if (metadata.getRendererMajorShaderModel() >= 4)
+ {
+ builtins->glPointCoord.enable(userSemantic, reservedSemanticIndex++);
+ }
+ else
+ {
+ builtins->glPointCoord.enable("TEXCOORD", 0);
+ }
+ }
+
+ if (shaderType == gl::SHADER_VERTEX && metadata.hasANGLEMultiviewEnabled())
+ {
+ builtins->glViewIDOVR.enable(userSemantic, reservedSemanticIndex++);
+ if (metadata.canSelectViewInVertexShader())
+ {
+ builtins->glViewportIndex.enableSystem("SV_ViewportArrayIndex");
+ builtins->glLayer.enableSystem("SV_RenderTargetArrayIndex");
+ }
+ }
+
+ if (shaderType == gl::SHADER_FRAGMENT && metadata.hasANGLEMultiviewEnabled())
+ {
+ builtins->glViewIDOVR.enable(userSemantic, reservedSemanticIndex++);
+ }
+
+ if (shaderType == gl::SHADER_GEOMETRY && metadata.hasANGLEMultiviewEnabled())
+ {
+ // Although it is possible to retrieve gl_ViewID_OVR from the value of
+ // SV_ViewportArrayIndex or SV_RenderTargetArrayIndex based on the multi-view state in the
+ // driver constant buffer, it is easier and cleaner to pass it as a varying.
+ builtins->glViewIDOVR.enable(userSemantic, reservedSemanticIndex++);
+
+ // gl_Layer and gl_ViewportIndex are necessary so that we can write to either based on the
+ // multiview state in the driver constant buffer.
+ builtins->glViewportIndex.enableSystem("SV_ViewportArrayIndex");
+ builtins->glLayer.enableSystem("SV_RenderTargetArrayIndex");
+ }
+
+ // Special case: do not include PSIZE semantic in HLSL 3 pixel shaders
+ if (metadata.usesSystemValuePointSize() &&
+ (shaderType != gl::SHADER_FRAGMENT || metadata.getRendererMajorShaderModel() >= 4))
+ {
+ builtins->glPointSize.enableSystem("PSIZE");
+ }
+}
+
} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h
index 69d941c06a..fe8d9cb0a3 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h
@@ -16,6 +16,7 @@
#include "common/angleutils.h"
#include "libANGLE/Constants.h"
#include "libANGLE/Program.h"
+#include "libANGLE/angletypes.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
@@ -29,23 +30,88 @@ namespace gl
{
class InfoLog;
struct VariableLocation;
+class VaryingPacking;
struct VertexAttribute;
-struct Data;
}
namespace rx
{
-struct PackedVarying;
class ProgramD3DMetadata;
class ShaderD3D;
-class VaryingPacking;
struct PixelShaderOutputVariable
{
- GLenum type;
+ PixelShaderOutputVariable() {}
+ PixelShaderOutputVariable(GLenum typeIn,
+ const std::string &nameIn,
+ const std::string &sourceIn,
+ size_t outputIndexIn)
+ : type(typeIn), name(nameIn), source(sourceIn), outputIndex(outputIndexIn)
+ {
+ }
+
+ GLenum type = GL_NONE;
std::string name;
std::string source;
- size_t outputIndex;
+ size_t outputIndex = 0;
+};
+
+struct BuiltinVarying final : private angle::NonCopyable
+{
+ BuiltinVarying();
+
+ std::string str() const;
+ void enableSystem(const std::string &systemValueSemantic);
+ void enable(const std::string &semanticVal, unsigned int indexVal);
+
+ bool enabled;
+ std::string semantic;
+ unsigned int index;
+ bool systemValue;
+};
+
+struct BuiltinInfo
+{
+ BuiltinInfo();
+ ~BuiltinInfo();
+
+ BuiltinVarying dxPosition;
+ BuiltinVarying glPosition;
+ BuiltinVarying glFragCoord;
+ BuiltinVarying glPointCoord;
+ BuiltinVarying glPointSize;
+ BuiltinVarying glViewIDOVR;
+ BuiltinVarying glViewportIndex;
+ BuiltinVarying glLayer;
+};
+
+inline std::string GetVaryingSemantic(int majorShaderModel, bool programUsesPointSize)
+{
+ // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord)
+ // In D3D11 we manually compute gl_PointCoord in the GS.
+ return ((programUsesPointSize && majorShaderModel < 4) ? "COLOR" : "TEXCOORD");
+}
+
+class BuiltinVaryingsD3D
+{
+ public:
+ BuiltinVaryingsD3D(const ProgramD3DMetadata &metadata, const gl::VaryingPacking &packing);
+ ~BuiltinVaryingsD3D();
+
+ bool usesPointSize() const { return mBuiltinInfo[gl::SHADER_VERTEX].glPointSize.enabled; }
+
+ const BuiltinInfo &operator[](gl::ShaderType shaderType) const
+ {
+ return mBuiltinInfo[shaderType];
+ }
+ BuiltinInfo &operator[](gl::ShaderType shaderType) { return mBuiltinInfo[shaderType]; }
+
+ private:
+ void updateBuiltins(gl::ShaderType shaderType,
+ const ProgramD3DMetadata &metadata,
+ const gl::VaryingPacking &packing);
+
+ std::array<BuiltinInfo, gl::SHADER_TYPE_MAX> mBuiltinInfo;
};
class DynamicHLSL : angle::NonCopyable
@@ -62,43 +128,48 @@ class DynamicHLSL : angle::NonCopyable
const std::vector<PixelShaderOutputVariable> &outputVariables,
bool usesFragDepth,
const std::vector<GLenum> &outputLayout) const;
- bool generateShaderLinkHLSL(const gl::Data &data,
- const gl::Program::Data &programData,
+ void generateShaderLinkHLSL(const gl::Context *context,
+ const gl::ProgramState &programData,
const ProgramD3DMetadata &programMetadata,
- const VaryingPacking &varyingPacking,
+ const gl::VaryingPacking &varyingPacking,
+ const BuiltinVaryingsD3D &builtinsD3D,
std::string *pixelHLSL,
std::string *vertexHLSL) const;
+ std::string generateComputeShaderLinkHLSL(const gl::Context *context,
+ const gl::ProgramState &programData) const;
- std::string generateGeometryShaderPreamble(const VaryingPacking &varyingPacking) const;
+ std::string generateGeometryShaderPreamble(const gl::VaryingPacking &varyingPacking,
+ const BuiltinVaryingsD3D &builtinsD3D,
+ const bool hasANGLEMultiviewEnabled,
+ const bool selectViewInVS) const;
- std::string generateGeometryShaderHLSL(gl::PrimitiveType primitiveType,
- const gl::Data &data,
- const gl::Program::Data &programData,
+ std::string generateGeometryShaderHLSL(const gl::Context *context,
+ gl::PrimitiveType primitiveType,
+ const gl::ProgramState &programData,
const bool useViewScale,
+ const bool hasANGLEMultiviewEnabled,
+ const bool selectViewInVS,
+ const bool pointSpriteEmulation,
const std::string &preambleString) const;
- void getPixelShaderOutputKey(const gl::Data &data,
- const gl::Program::Data &programData,
+ void getPixelShaderOutputKey(const gl::ContextState &data,
+ const gl::ProgramState &programData,
const ProgramD3DMetadata &metadata,
std::vector<PixelShaderOutputVariable> *outPixelShaderKey);
private:
RendererD3D *const mRenderer;
- void generateVaryingLinkHLSL(ShaderType shaderType,
- const VaryingPacking &varyingPacking,
- std::stringstream &linkStream) const;
- void generateVaryingHLSL(const VaryingPacking &varyingPacking,
- std::stringstream &hlslStream) const;
-
- // Prepend an underscore
- static std::string decorateVariable(const std::string &name);
+ void generateVaryingLinkHLSL(const gl::VaryingPacking &varyingPacking,
+ const BuiltinInfo &builtins,
+ bool programUsesPointSize,
+ std::ostringstream &hlslStream) const;
- std::string generateAttributeConversionHLSL(gl::VertexFormatType vertexFormatType,
- const sh::ShaderVariable &shaderAttrib) const;
+ static void GenerateAttributeConversionHLSL(gl::VertexFormatType vertexFormatType,
+ const sh::ShaderVariable &shaderAttrib,
+ std::ostringstream &outStream);
};
-std::string GetVaryingSemantic(int majorShaderModel, bool programUsesPointSize);
-}
+} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.cpp
index ca4b16987f..fcc2456bd6 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.cpp
@@ -22,46 +22,14 @@
namespace rx
{
-static gl::ImageIndex GetImageIndex(GLenum target, size_t mip, size_t layer)
-{
- if (target == GL_TEXTURE_3D)
- {
- return gl::ImageIndex::Make3D(static_cast<GLint>(mip), static_cast<GLint>(layer));
- }
- else
- {
- ASSERT(layer == 0);
- return gl::ImageIndex::MakeGeneric(target, static_cast<GLint>(mip));
- }
-}
-EGLImageD3D::EGLImageD3D(RendererD3D *renderer,
+EGLImageD3D::EGLImageD3D(const egl::ImageState &state,
EGLenum target,
- egl::ImageSibling *buffer,
- const egl::AttributeMap &attribs)
- : mRenderer(renderer), mBuffer(buffer), mAttachmentBuffer(nullptr), mRenderTarget(nullptr)
+ const egl::AttributeMap &attribs,
+ RendererD3D *renderer)
+ : ImageImpl(state), mRenderer(renderer), mRenderTarget(nullptr)
{
ASSERT(renderer != nullptr);
- ASSERT(buffer != nullptr);
-
- if (egl::IsTextureTarget(target))
- {
- mAttachmentBuffer = GetImplAs<TextureD3D>(GetAs<gl::Texture>(buffer));
- mAttachmentTarget = gl::FramebufferAttachment::Target(
- GL_NONE, GetImageIndex(egl_gl::EGLImageTargetToGLTextureTarget(target),
- attribs.get(EGL_GL_TEXTURE_LEVEL_KHR, 0),
- attribs.get(EGL_GL_TEXTURE_ZOFFSET_KHR, 0)));
- }
- else if (egl::IsRenderbufferTarget(target))
- {
- mAttachmentBuffer = GetImplAs<RenderbufferD3D>(GetAs<gl::Renderbuffer>(buffer));
- mAttachmentTarget =
- gl::FramebufferAttachment::Target(GL_NONE, gl::ImageIndex::MakeInvalid());
- }
- else
- {
- UNREACHABLE();
- }
}
EGLImageD3D::~EGLImageD3D()
@@ -71,62 +39,49 @@ EGLImageD3D::~EGLImageD3D()
egl::Error EGLImageD3D::initialize()
{
- return egl::Error(EGL_SUCCESS);
+ return egl::NoError();
}
-gl::Error EGLImageD3D::orphan(egl::ImageSibling *sibling)
+gl::Error EGLImageD3D::orphan(const gl::Context *context, egl::ImageSibling *sibling)
{
- if (sibling == mBuffer)
+ if (sibling == mState.source.get())
{
- gl::Error error = copyToLocalRendertarget();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(copyToLocalRendertarget(context));
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error EGLImageD3D::getRenderTarget(RenderTargetD3D **outRT) const
+gl::Error EGLImageD3D::getRenderTarget(const gl::Context *context, RenderTargetD3D **outRT) const
{
- if (mAttachmentBuffer)
+ if (mState.source.get())
{
+ ASSERT(!mRenderTarget);
FramebufferAttachmentRenderTarget *rt = nullptr;
- gl::Error error = mAttachmentBuffer->getAttachmentRenderTarget(mAttachmentTarget, &rt);
- if (error.isError())
- {
- return error;
- }
-
+ ANGLE_TRY(
+ mState.source->getAttachmentRenderTarget(context, GL_NONE, mState.imageIndex, &rt));
*outRT = static_cast<RenderTargetD3D *>(rt);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
else
{
ASSERT(mRenderTarget);
*outRT = mRenderTarget;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
}
-gl::Error EGLImageD3D::copyToLocalRendertarget()
+gl::Error EGLImageD3D::copyToLocalRendertarget(const gl::Context *context)
{
- ASSERT(mBuffer != nullptr);
- ASSERT(mAttachmentBuffer != nullptr);
+ ASSERT(mState.source.get() != nullptr);
ASSERT(mRenderTarget == nullptr);
RenderTargetD3D *curRenderTarget = nullptr;
- gl::Error error = getRenderTarget(&curRenderTarget);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(getRenderTarget(context, &curRenderTarget));
- // Clear the source image buffers
- mBuffer = nullptr;
- mAttachmentBuffer = nullptr;
+ // This only currently applies do D3D11, where it invalidates FBOs with this Image attached.
+ curRenderTarget->signalDirty(context);
return mRenderer->createRenderTargetCopy(curRenderTarget, &mRenderTarget);
}
-}
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.h
index 6ec33e08f2..1ee7984426 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.h
@@ -9,9 +9,13 @@
#ifndef LIBANGLE_RENDERER_D3D_EGLIMAGED3D_H_
#define LIBANGLE_RENDERER_D3D_EGLIMAGED3D_H_
-#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/renderer/ImageImpl.h"
+namespace gl
+{
+class Context;
+}
+
namespace egl
{
class AttributeMap;
@@ -19,6 +23,7 @@ class AttributeMap;
namespace rx
{
+class FramebufferAttachmentObjectImpl;
class TextureD3D;
class RenderbufferD3D;
class RendererD3D;
@@ -27,30 +32,24 @@ class RenderTargetD3D;
class EGLImageD3D final : public ImageImpl
{
public:
- EGLImageD3D(RendererD3D *renderer,
+ EGLImageD3D(const egl::ImageState &state,
EGLenum target,
- egl::ImageSibling *buffer,
- const egl::AttributeMap &attribs);
+ const egl::AttributeMap &attribs,
+ RendererD3D *renderer);
~EGLImageD3D() override;
egl::Error initialize() override;
- gl::Error orphan(egl::ImageSibling *sibling) override;
+ gl::Error orphan(const gl::Context *context, egl::ImageSibling *sibling) override;
- gl::Error getRenderTarget(RenderTargetD3D **outRT) const;
+ gl::Error getRenderTarget(const gl::Context *context, RenderTargetD3D **outRT) const;
private:
- gl::Error copyToLocalRendertarget();
+ gl::Error copyToLocalRendertarget(const gl::Context *context);
RendererD3D *mRenderer;
-
- egl::ImageSibling *mBuffer;
-
- gl::FramebufferAttachment::Target mAttachmentTarget;
- FramebufferAttachmentObjectImpl *mAttachmentBuffer;
-
RenderTargetD3D *mRenderTarget;
};
-}
+} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_EGLIMAGED3D_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
index 82967aced0..3d73b2c840 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
@@ -8,14 +8,16 @@
#include "libANGLE/renderer/d3d/FramebufferD3D.h"
-#include "common/BitSetIterator.h"
-#include "libANGLE/formatutils.h"
+#include "common/bitset_utils.h"
+#include "libANGLE/Context.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/Surface.h"
-#include "libANGLE/renderer/d3d/RendererD3D.h"
-#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/ContextImpl.h"
#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/SurfaceD3D.h"
#include "libANGLE/renderer/d3d/SwapChainD3D.h"
#include "libANGLE/renderer/d3d/TextureD3D.h"
@@ -37,19 +39,19 @@ ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask)
{
clearParams.clearColor[i] = false;
}
- clearParams.colorFClearValue = state.getColorClearValue();
- clearParams.colorClearType = GL_FLOAT;
- clearParams.colorMaskRed = blendState.colorMaskRed;
- clearParams.colorMaskGreen = blendState.colorMaskGreen;
- clearParams.colorMaskBlue = blendState.colorMaskBlue;
- clearParams.colorMaskAlpha = blendState.colorMaskAlpha;
- clearParams.clearDepth = false;
- clearParams.depthClearValue = state.getDepthClearValue();
- clearParams.clearStencil = false;
- clearParams.stencilClearValue = state.getStencilClearValue();
+ clearParams.colorF = state.getColorClearValue();
+ clearParams.colorType = GL_FLOAT;
+ clearParams.colorMaskRed = blendState.colorMaskRed;
+ clearParams.colorMaskGreen = blendState.colorMaskGreen;
+ clearParams.colorMaskBlue = blendState.colorMaskBlue;
+ clearParams.colorMaskAlpha = blendState.colorMaskAlpha;
+ clearParams.clearDepth = false;
+ clearParams.depthValue = state.getDepthClearValue();
+ clearParams.clearStencil = false;
+ clearParams.stencilValue = state.getStencilClearValue();
clearParams.stencilWriteMask = state.getDepthStencilState().stencilWritemask;
- clearParams.scissorEnabled = state.isScissorTestEnabled();
- clearParams.scissor = state.getScissor();
+ clearParams.scissorEnabled = state.isScissorTestEnabled();
+ clearParams.scissor = state.getScissor();
const gl::Framebuffer *framebufferObject = state.getDrawFramebuffer();
if (mask & GL_COLOR_BUFFER_BIT)
@@ -65,7 +67,8 @@ ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask)
if (mask & GL_DEPTH_BUFFER_BIT)
{
- if (state.getDepthStencilState().depthMask && framebufferObject->getDepthbuffer() != NULL)
+ if (state.getDepthStencilState().depthMask &&
+ framebufferObject->getDepthbuffer() != nullptr)
{
clearParams.clearDepth = true;
}
@@ -73,7 +76,7 @@ ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask)
if (mask & GL_STENCIL_BUFFER_BIT)
{
- if (framebufferObject->getStencilbuffer() != NULL &&
+ if (framebufferObject->getStencilbuffer() != nullptr &&
framebufferObject->getStencilbuffer()->getStencilSize() > 0)
{
clearParams.clearStencil = true;
@@ -82,10 +85,13 @@ ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask)
return clearParams;
}
-
}
-FramebufferD3D::FramebufferD3D(const gl::Framebuffer::Data &data, RendererD3D *renderer)
+ClearParameters::ClearParameters() = default;
+
+ClearParameters::ClearParameters(const ClearParameters &other) = default;
+
+FramebufferD3D::FramebufferD3D(const gl::FramebufferState &data, RendererD3D *renderer)
: FramebufferImpl(data), mRenderer(renderer)
{
}
@@ -94,20 +100,19 @@ FramebufferD3D::~FramebufferD3D()
{
}
-gl::Error FramebufferD3D::clear(const gl::Data &data, GLbitfield mask)
+gl::Error FramebufferD3D::clear(const gl::Context *context, GLbitfield mask)
{
- const gl::State &state = *data.state;
- ClearParameters clearParams = GetClearParameters(state, mask);
- return clear(data, clearParams);
+ ClearParameters clearParams = GetClearParameters(context->getGLState(), mask);
+ return clearImpl(context, clearParams);
}
-gl::Error FramebufferD3D::clearBufferfv(const gl::Data &data,
+gl::Error FramebufferD3D::clearBufferfv(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
const GLfloat *values)
{
// glClearBufferfv can be called to clear the color buffer or depth buffer
- ClearParameters clearParams = GetClearParameters(*data.state, 0);
+ ClearParameters clearParams = GetClearParameters(context->getGLState(), 0);
if (buffer == GL_COLOR)
{
@@ -115,43 +120,43 @@ gl::Error FramebufferD3D::clearBufferfv(const gl::Data &data,
{
clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
}
- clearParams.colorFClearValue = gl::ColorF(values[0], values[1], values[2], values[3]);
- clearParams.colorClearType = GL_FLOAT;
+ clearParams.colorF = gl::ColorF(values[0], values[1], values[2], values[3]);
+ clearParams.colorType = GL_FLOAT;
}
if (buffer == GL_DEPTH)
{
clearParams.clearDepth = true;
- clearParams.depthClearValue = values[0];
+ clearParams.depthValue = values[0];
}
- return clear(data, clearParams);
+ return clearImpl(context, clearParams);
}
-gl::Error FramebufferD3D::clearBufferuiv(const gl::Data &data,
+gl::Error FramebufferD3D::clearBufferuiv(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
const GLuint *values)
{
// glClearBufferuiv can only be called to clear a color buffer
- ClearParameters clearParams = GetClearParameters(*data.state, 0);
+ ClearParameters clearParams = GetClearParameters(context->getGLState(), 0);
for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
{
clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
}
- clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]);
- clearParams.colorClearType = GL_UNSIGNED_INT;
+ clearParams.colorUI = gl::ColorUI(values[0], values[1], values[2], values[3]);
+ clearParams.colorType = GL_UNSIGNED_INT;
- return clear(data, clearParams);
+ return clearImpl(context, clearParams);
}
-gl::Error FramebufferD3D::clearBufferiv(const gl::Data &data,
+gl::Error FramebufferD3D::clearBufferiv(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
const GLint *values)
{
// glClearBufferiv can be called to clear the color buffer or stencil buffer
- ClearParameters clearParams = GetClearParameters(*data.state, 0);
+ ClearParameters clearParams = GetClearParameters(context->getGLState(), 0);
if (buffer == GL_COLOR)
{
@@ -159,167 +164,154 @@ gl::Error FramebufferD3D::clearBufferiv(const gl::Data &data,
{
clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
}
- clearParams.colorIClearValue = gl::ColorI(values[0], values[1], values[2], values[3]);
- clearParams.colorClearType = GL_INT;
+ clearParams.colorI = gl::ColorI(values[0], values[1], values[2], values[3]);
+ clearParams.colorType = GL_INT;
}
if (buffer == GL_STENCIL)
{
clearParams.clearStencil = true;
- clearParams.stencilClearValue = values[1];
+ clearParams.stencilValue = values[0];
}
- return clear(data, clearParams);
+ return clearImpl(context, clearParams);
}
-gl::Error FramebufferD3D::clearBufferfi(const gl::Data &data,
+gl::Error FramebufferD3D::clearBufferfi(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
GLfloat depth,
GLint stencil)
{
// glClearBufferfi can only be called to clear a depth stencil buffer
- ClearParameters clearParams = GetClearParameters(*data.state, 0);
- clearParams.clearDepth = true;
- clearParams.depthClearValue = depth;
- clearParams.clearStencil = true;
- clearParams.stencilClearValue = stencil;
+ ClearParameters clearParams = GetClearParameters(context->getGLState(), 0);
+ clearParams.clearDepth = true;
+ clearParams.depthValue = depth;
+ clearParams.clearStencil = true;
+ clearParams.stencilValue = stencil;
- return clear(data, clearParams);
+ return clearImpl(context, clearParams);
}
-GLenum FramebufferD3D::getImplementationColorReadFormat() const
+GLenum FramebufferD3D::getImplementationColorReadFormat(const gl::Context *context) const
{
- const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment();
+ const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
if (readAttachment == nullptr)
{
return GL_NONE;
}
- RenderTargetD3D *attachmentRenderTarget = NULL;
- gl::Error error = readAttachment->getRenderTarget(&attachmentRenderTarget);
+ RenderTargetD3D *attachmentRenderTarget = nullptr;
+ gl::Error error = readAttachment->getRenderTarget(context, &attachmentRenderTarget);
if (error.isError())
{
return GL_NONE;
}
GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
- const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat);
+ const gl::InternalFormat &implementationFormatInfo =
+ gl::GetSizedInternalFormatInfo(implementationFormat);
- return implementationFormatInfo.format;
+ return implementationFormatInfo.getReadPixelsFormat();
}
-GLenum FramebufferD3D::getImplementationColorReadType() const
+GLenum FramebufferD3D::getImplementationColorReadType(const gl::Context *context) const
{
- const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment();
+ const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
if (readAttachment == nullptr)
{
return GL_NONE;
}
- RenderTargetD3D *attachmentRenderTarget = NULL;
- gl::Error error = readAttachment->getRenderTarget(&attachmentRenderTarget);
+ RenderTargetD3D *attachmentRenderTarget = nullptr;
+ gl::Error error = readAttachment->getRenderTarget(context, &attachmentRenderTarget);
if (error.isError())
{
return GL_NONE;
}
GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
- const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat);
+ const gl::InternalFormat &implementationFormatInfo =
+ gl::GetSizedInternalFormatInfo(implementationFormat);
- return implementationFormatInfo.type;
+ return implementationFormatInfo.getReadPixelsType(context->getClientVersion());
}
-gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
+gl::Error FramebufferD3D::readPixels(const gl::Context *context,
+ const gl::Rectangle &origArea,
+ GLenum format,
+ GLenum type,
+ void *pixels)
{
- const gl::PixelPackState &packState = state.getPackState();
-
- GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type);
- const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
- GLuint outputPitch =
- sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, packState.rowLength);
- GLsizei outputSkipBytes = sizedFormatInfo.computeSkipPixels(
- outputPitch, 0, 0, packState.skipRows, packState.skipPixels);
-
- return readPixelsImpl(area, format, type, outputPitch, packState,
- reinterpret_cast<uint8_t *>(pixels) + outputSkipBytes);
-}
-
-gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
- GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
-{
- bool blitRenderTarget = false;
- if ((mask & GL_COLOR_BUFFER_BIT) &&
- sourceFramebuffer->getReadColorbuffer() != nullptr &&
- mData.getFirstColorAttachment() != nullptr)
+ // Clip read area to framebuffer.
+ const gl::Extents fbSize = getState().getReadAttachment()->getSize();
+ const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
+ gl::Rectangle area;
+ if (!ClipRectangle(origArea, fbRect, &area))
{
- blitRenderTarget = true;
+ // nothing to read
+ return gl::NoError();
}
- bool blitStencil = false;
- if ((mask & GL_STENCIL_BUFFER_BIT) &&
- sourceFramebuffer->getStencilbuffer() != nullptr &&
- mData.getStencilAttachment() != nullptr)
- {
- blitStencil = true;
- }
+ const gl::PixelPackState &packState = context->getGLState().getPackState();
- bool blitDepth = false;
- if ((mask & GL_DEPTH_BUFFER_BIT) &&
- sourceFramebuffer->getDepthbuffer() != nullptr &&
- mData.getDepthAttachment() != nullptr)
- {
- blitDepth = true;
- }
+ const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(format, type);
- if (blitRenderTarget || blitDepth || blitStencil)
- {
- const gl::Rectangle *scissor = state.isScissorTestEnabled() ? &state.getScissor() : NULL;
- gl::Error error = blit(sourceArea, destArea, scissor, blitRenderTarget, blitDepth, blitStencil,
- filter, sourceFramebuffer);
- if (error.isError())
- {
- return error;
- }
- }
+ GLuint outputPitch = 0;
+ ANGLE_TRY_RESULT(sizedFormatInfo.computeRowPitch(type, origArea.width, packState.alignment,
+ packState.rowLength),
+ outputPitch);
+ GLuint outputSkipBytes = 0;
+ ANGLE_TRY_RESULT(sizedFormatInfo.computeSkipBytes(outputPitch, 0, packState, false),
+ outputSkipBytes);
+ outputSkipBytes +=
+ (area.x - origArea.x) * sizedFormatInfo.pixelBytes + (area.y - origArea.y) * outputPitch;
+
+ return readPixelsImpl(context, area, format, type, outputPitch, packState,
+ reinterpret_cast<uint8_t *>(pixels) + outputSkipBytes);
+}
- return gl::Error(GL_NO_ERROR);
+gl::Error FramebufferD3D::blit(const gl::Context *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ GLbitfield mask,
+ GLenum filter)
+{
+ const auto &glState = context->getGLState();
+ const gl::Framebuffer *sourceFramebuffer = glState.getReadFramebuffer();
+ const gl::Rectangle *scissor = glState.isScissorTestEnabled() ? &glState.getScissor() : nullptr;
+ ANGLE_TRY(blitImpl(context, sourceArea, destArea, scissor, (mask & GL_COLOR_BUFFER_BIT) != 0,
+ (mask & GL_DEPTH_BUFFER_BIT) != 0, (mask & GL_STENCIL_BUFFER_BIT) != 0,
+ filter, sourceFramebuffer));
+
+ return gl::NoError();
}
-bool FramebufferD3D::checkStatus() const
+bool FramebufferD3D::checkStatus(const gl::Context *context) const
{
// if we have both a depth and stencil buffer, they must refer to the same object
// since we only support packed_depth_stencil and not separate depth and stencil
- if (mData.getDepthAttachment() != nullptr && mData.getStencilAttachment() != nullptr &&
- mData.getDepthStencilAttachment() == nullptr)
+ if (mState.getDepthAttachment() != nullptr && mState.getStencilAttachment() != nullptr &&
+ mState.getDepthStencilAttachment() == nullptr)
{
return false;
}
- // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
- const auto &colorAttachments = mData.getColorAttachments();
- for (size_t colorAttachment = 0; colorAttachment < colorAttachments.size(); colorAttachment++)
+ // D3D11 does not allow for overlapping RenderTargetViews.
+ // If WebGL compatibility is enabled, this has already been checked at a higher level.
+ ASSERT(!context->getExtensions().webglCompatibility || mState.colorAttachmentsAreUniqueImages());
+ if (!context->getExtensions().webglCompatibility)
{
- const gl::FramebufferAttachment &attachment = colorAttachments[colorAttachment];
- if (attachment.isAttached())
+ if (!mState.colorAttachmentsAreUniqueImages())
{
- for (size_t prevColorAttachment = 0; prevColorAttachment < colorAttachment; prevColorAttachment++)
- {
- const gl::FramebufferAttachment &prevAttachment = colorAttachments[prevColorAttachment];
- if (prevAttachment.isAttached() &&
- (attachment.id() == prevAttachment.id() &&
- attachment.type() == prevAttachment.type()))
- {
- return false;
- }
- }
+ return false;
}
}
// D3D requires all render targets to have the same dimensions.
- if (!mData.attachmentsHaveSameDimensions())
+ if (!mState.attachmentsHaveSameDimensions())
{
return false;
}
@@ -327,45 +319,52 @@ bool FramebufferD3D::checkStatus() const
return true;
}
-void FramebufferD3D::syncState(const gl::Framebuffer::DirtyBits &dirtyBits)
+void FramebufferD3D::syncState(const gl::Context *context,
+ const gl::Framebuffer::DirtyBits &dirtyBits)
{
- bool invalidateColorAttachmentCache = false;
-
if (!mColorAttachmentsForRender.valid())
{
- invalidateColorAttachmentCache = true;
+ return;
}
- for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
+ for (auto dirtyBit : dirtyBits)
{
if ((dirtyBit >= gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 &&
dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX) ||
dirtyBit == gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS)
{
- invalidateColorAttachmentCache = true;
+ mColorAttachmentsForRender.reset();
}
}
+}
- if (!invalidateColorAttachmentCache)
+const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender(const gl::Context *context)
+{
+ gl::DrawBufferMask activeProgramOutputs =
+ context->getContextState().getState().getProgram()->getActiveOutputVariables();
+
+ if (mColorAttachmentsForRender.valid() && mCurrentActiveProgramOutputs == activeProgramOutputs)
{
- return;
+ return mColorAttachmentsForRender.value();
}
// Does not actually free memory
gl::AttachmentList colorAttachmentsForRender;
- const auto &colorAttachments = mData.getColorAttachments();
- const auto &drawBufferStates = mData.getDrawBufferStates();
+ const auto &colorAttachments = mState.getColorAttachments();
+ const auto &drawBufferStates = mState.getDrawBufferStates();
const auto &workarounds = mRenderer->getWorkarounds();
for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size(); ++attachmentIndex)
{
- GLenum drawBufferState = drawBufferStates[attachmentIndex];
+ GLenum drawBufferState = drawBufferStates[attachmentIndex];
const gl::FramebufferAttachment &colorAttachment = colorAttachments[attachmentIndex];
- if (colorAttachment.isAttached() && drawBufferState != GL_NONE)
+ if (colorAttachment.isAttached() && drawBufferState != GL_NONE &&
+ activeProgramOutputs[attachmentIndex])
{
- ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex));
+ ASSERT(drawBufferState == GL_BACK ||
+ drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex));
colorAttachmentsForRender.push_back(&colorAttachment);
}
else if (!workarounds.mrtPerfWorkaround)
@@ -374,12 +373,32 @@ void FramebufferD3D::syncState(const gl::Framebuffer::DirtyBits &dirtyBits)
}
}
+ // When rendering with no render target on D3D, two bugs lead to incorrect behavior on Intel
+ // drivers < 4815. The rendering samples always pass neglecting discard statements in pixel
+ // shader. We add a dummy texture as render target in such case.
+ if (mRenderer->getWorkarounds().addDummyTextureNoRenderTarget &&
+ colorAttachmentsForRender.empty())
+ {
+ static_assert(static_cast<size_t>(activeProgramOutputs.size()) <= 32,
+ "Size of active program outputs should less or equal than 32.");
+ GLenum i = static_cast<GLenum>(
+ gl::ScanForward(static_cast<uint32_t>(activeProgramOutputs.bits())));
+
+ gl::Texture *dummyTex = nullptr;
+ // TODO(Jamie): Handle error if dummy texture can't be created.
+ ANGLE_SWALLOW_ERR(mRenderer->getIncompleteTexture(context, GL_TEXTURE_2D, &dummyTex));
+ if (dummyTex)
+ {
+ gl::ImageIndex index = gl::ImageIndex::Make2D(0);
+ gl::FramebufferAttachment *dummyAttach = new gl::FramebufferAttachment(
+ context, GL_TEXTURE, GL_COLOR_ATTACHMENT0_EXT + i, index, dummyTex);
+ colorAttachmentsForRender.push_back(dummyAttach);
+ }
+ }
+
mColorAttachmentsForRender = std::move(colorAttachmentsForRender);
-}
+ mCurrentActiveProgramOutputs = activeProgramOutputs;
-const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender() const
-{
- ASSERT(mColorAttachmentsForRender.valid());
return mColorAttachmentsForRender.value();
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h
index eb839c4364..a7312fdef4 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h
@@ -9,9 +9,10 @@
#ifndef LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_
#define LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_
-#include <vector>
#include <cstdint>
+#include <vector>
+#include "common/Color.h"
#include "common/Optional.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/renderer/FramebufferImpl.h"
@@ -22,32 +23,33 @@ class FramebufferAttachment;
struct PixelPackState;
typedef std::vector<const FramebufferAttachment *> AttachmentList;
-
}
namespace rx
{
class RendererD3D;
class RenderTargetD3D;
-struct WorkaroundsD3D;
struct ClearParameters
{
+ ClearParameters();
+ ClearParameters(const ClearParameters &other);
+
bool clearColor[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS];
- gl::ColorF colorFClearValue;
- gl::ColorI colorIClearValue;
- gl::ColorUI colorUIClearValue;
- GLenum colorClearType;
+ gl::ColorF colorF;
+ gl::ColorI colorI;
+ gl::ColorUI colorUI;
+ GLenum colorType;
bool colorMaskRed;
bool colorMaskGreen;
bool colorMaskBlue;
bool colorMaskAlpha;
bool clearDepth;
- float depthClearValue;
+ float depthValue;
bool clearStencil;
- GLint stencilClearValue;
+ GLint stencilValue;
GLuint stencilWriteMask;
bool scissorEnabled;
@@ -57,61 +59,76 @@ struct ClearParameters
class FramebufferD3D : public FramebufferImpl
{
public:
- FramebufferD3D(const gl::Framebuffer::Data &data, RendererD3D *renderer);
- virtual ~FramebufferD3D();
+ FramebufferD3D(const gl::FramebufferState &data, RendererD3D *renderer);
+ ~FramebufferD3D() override;
- gl::Error clear(const gl::Data &data, GLbitfield mask) override;
- gl::Error clearBufferfv(const gl::Data &data,
+ gl::Error clear(const gl::Context *context, GLbitfield mask) override;
+ gl::Error clearBufferfv(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
const GLfloat *values) override;
- gl::Error clearBufferuiv(const gl::Data &data,
+ gl::Error clearBufferuiv(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
const GLuint *values) override;
- gl::Error clearBufferiv(const gl::Data &data,
+ gl::Error clearBufferiv(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
const GLint *values) override;
- gl::Error clearBufferfi(const gl::Data &data,
+ gl::Error clearBufferfi(const gl::Context *context,
GLenum buffer,
GLint drawbuffer,
GLfloat depth,
GLint stencil) override;
- GLenum getImplementationColorReadFormat() const override;
- GLenum getImplementationColorReadType() const override;
- gl::Error readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const override;
+ GLenum getImplementationColorReadFormat(const gl::Context *context) const override;
+ GLenum getImplementationColorReadType(const gl::Context *context) const override;
+ gl::Error readPixels(const gl::Context *context,
+ const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ void *pixels) override;
- gl::Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
- GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) override;
+ gl::Error blit(const gl::Context *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ GLbitfield mask,
+ GLenum filter) override;
- bool checkStatus() const override;
+ bool checkStatus(const gl::Context *context) const override;
- void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) override;
+ void syncState(const gl::Context *context,
+ const gl::Framebuffer::DirtyBits &dirtyBits) override;
- const gl::AttachmentList &getColorAttachmentsForRender() const;
+ const gl::AttachmentList &getColorAttachmentsForRender(const gl::Context *context);
private:
- virtual gl::Error clear(const gl::Data &data, const ClearParameters &clearParams) = 0;
+ virtual gl::Error clearImpl(const gl::Context *context, const ClearParameters &clearParams) = 0;
- virtual gl::Error readPixelsImpl(const gl::Rectangle &area,
+ virtual gl::Error readPixelsImpl(const gl::Context *context,
+ const gl::Rectangle &area,
GLenum format,
GLenum type,
size_t outputPitch,
const gl::PixelPackState &pack,
- uint8_t *pixels) const = 0;
-
- virtual gl::Error blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor,
- bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter,
- const gl::Framebuffer *sourceFramebuffer) = 0;
+ uint8_t *pixels) = 0;
+
+ virtual gl::Error blitImpl(const gl::Context *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ const gl::Rectangle *scissor,
+ bool blitRenderTarget,
+ bool blitDepth,
+ bool blitStencil,
+ GLenum filter,
+ const gl::Framebuffer *sourceFramebuffer) = 0;
virtual GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const = 0;
RendererD3D *mRenderer;
Optional<gl::AttachmentList> mColorAttachmentsForRender;
+ gl::DrawBufferMask mCurrentActiveProgramOutputs;
};
-
}
-#endif // LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_
+#endif // LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
index df0257e370..b38765070b 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
@@ -6,16 +6,14 @@
#include "libANGLE/renderer/d3d/HLSLCompiler.h"
+#include <sstream>
+
#include "common/utilities.h"
#include "libANGLE/Program.h"
#include "libANGLE/features.h"
#include "libANGLE/histogram_macros.h"
#include "third_party/trace_event/trace_event.h"
-#ifndef QT_D3DCOMPILER_DLL
-#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL
-#endif
-
#if ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED
namespace
{
@@ -25,15 +23,6 @@ namespace
#define CREATE_COMPILER_FLAG_INFO(flag) { flag, #flag }
-#if defined(ANGLE_MINGW32_COMPAT)
-#ifndef D3DCOMPILE_RESERVED16
-#define D3DCOMPILE_RESERVED16 0x10000
-#endif
-#ifndef D3DCOMPILE_RESERVED17
-#define D3DCOMPILE_RESERVED17 0x20000
-#endif
-#endif
-
struct CompilerFlagInfo
{
UINT mFlag;
@@ -119,11 +108,11 @@ HLSLCompiler::~HLSLCompiler()
release();
}
-gl::Error HLSLCompiler::initialize()
+gl::Error HLSLCompiler::ensureInitialized()
{
if (mInitialized)
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
TRACE_EVENT0("gpu.angle", "HLSLCompiler::initialize");
@@ -141,28 +130,6 @@ gl::Error HLSLCompiler::initialize()
}
#endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES
- // Load the compiler DLL specified by the environment, or default to QT_D3DCOMPILER_DLL
- const wchar_t *defaultCompiler = _wgetenv(L"QT_D3DCOMPILER_DLL");
- if (!defaultCompiler)
- defaultCompiler = QT_D3DCOMPILER_DLL;
-
- const wchar_t *compilerDlls[] = {
- defaultCompiler,
- L"d3dcompiler_47.dll",
- L"d3dcompiler_46.dll",
- L"d3dcompiler_43.dll",
- 0
- };
-
- // Load the first available known compiler DLL
- for (int i = 0; compilerDlls[i]; ++i)
- {
- mD3DCompilerModule = LoadLibrary(compilerDlls[i]);
- if (mD3DCompilerModule)
- break;
- }
-
-
if (!mD3DCompilerModule)
{
// Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with.
@@ -171,7 +138,8 @@ gl::Error HLSLCompiler::initialize()
if (!mD3DCompilerModule)
{
- return gl::Error(GL_INVALID_OPERATION, "No D3D compiler module found - aborting!\n");
+ ERR() << "D3D compiler module not found.";
+ return gl::OutOfMemory() << "D3D compiler module not found.";
}
mD3DCompileFunc = reinterpret_cast<pD3DCompile>(GetProcAddress(mD3DCompilerModule, "D3DCompile"));
@@ -190,11 +158,11 @@ gl::Error HLSLCompiler::initialize()
if (mD3DCompileFunc == nullptr)
{
- return gl::Error(GL_INVALID_OPERATION, "Error finding D3DCompile entry point");
+ return gl::OutOfMemory() << "Error finding D3DCompile entry point.";
}
mInitialized = true;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
void HLSLCompiler::release()
@@ -213,11 +181,7 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string
const std::vector<CompileConfig> &configs, const D3D_SHADER_MACRO *overrideMacros,
ID3DBlob **outCompiledBlob, std::string *outDebugInfo)
{
- gl::Error error = initialize();
- if (error.isError())
- {
- return error;
- }
+ ASSERT(mInitialized);
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
ASSERT(mD3DCompilerModule);
@@ -228,7 +192,9 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string
if (gl::DebugAnnotationsActive())
{
std::string sourcePath = getTempPath();
- std::string sourceText = FormatString("#line 2 \"%s\"\n\n%s", sourcePath.c_str(), hlsl.c_str());
+ std::ostringstream stream;
+ stream << "#line 2 \"" << sourcePath << "\"\n\n" << hlsl;
+ std::string sourceText = stream.str();
writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
}
#endif
@@ -255,8 +221,11 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string
SafeRelease(errorMessage);
infoLog.appendSanitized(message.c_str());
- TRACE("\n%s", hlsl.c_str());
- TRACE("\n%s", message.c_str());
+
+ // This produces unbelievable amounts of spam in about:gpu.
+ // WARN() << std::endl << hlsl;
+
+ WARN() << std::endl << message;
if ((message.find("error X3531:") != std::string::npos || // "can't unroll loops marked with loop attribute"
message.find("error X4014:") != std::string::npos) && // "cannot have gradient operations inside loops with divergent flow control",
@@ -304,20 +273,17 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string
}
std::string disassembly;
- error = disassembleBinary(binary, &disassembly);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(disassembleBinary(binary, &disassembly));
(*outDebugInfo) += "\n" + disassembly + "\n// ASSEMBLY END\n";
#endif // ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
if (result == E_OUTOFMEMORY)
{
*outCompiledBlob = nullptr;
- return gl::Error(GL_OUT_OF_MEMORY, "HLSL compiler had an unexpected failure, result: 0x%X.", result);
+ return gl::OutOfMemory()
+ << "HLSL compiler had an unexpected failure, " << gl::FmtHR(result);
}
infoLog << "Warning: D3D shader compilation failed with " << configs[i].name << " flags. ("
@@ -331,16 +297,12 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string
// None of the configurations succeeded in compiling this shader but the compiler is still intact
*outCompiledBlob = nullptr;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error HLSLCompiler::disassembleBinary(ID3DBlob *shaderBinary, std::string *disassemblyOut)
{
- gl::Error error = initialize();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(ensureInitialized());
// Retrieve disassembly
UINT flags = D3D_DISASM_ENABLE_DEFAULT_VALUE_PRINTS | D3D_DISASM_ENABLE_INSTRUCTION_NUMBERING;
@@ -361,7 +323,7 @@ gl::Error HLSLCompiler::disassembleBinary(ID3DBlob *shaderBinary, std::string *d
SafeRelease(disassembly);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h
index 3c0d2adcac..c8f9eac290 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h
@@ -1,3 +1,11 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// HLSLCompiler: Wrapper for the D3DCompiler DLL.
+//
+
#ifndef LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_
#define LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_
@@ -41,9 +49,9 @@ class HLSLCompiler : angle::NonCopyable
ID3DBlob **outCompiledBlob, std::string *outDebugInfo);
gl::Error disassembleBinary(ID3DBlob *shaderBinary, std::string *disassemblyOut);
+ gl::Error ensureInitialized();
private:
- gl::Error initialize();
bool mInitialized;
HMODULE mD3DCompilerModule;
@@ -53,4 +61,4 @@ class HLSLCompiler : angle::NonCopyable
}
-#endif // LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_
+#endif // LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp
index ead5db6453..dbbcbbed2a 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp
@@ -29,4 +29,34 @@ ImageD3D::ImageD3D()
{
}
+gl::Error ImageD3D::setManagedSurface2D(const gl::Context *context,
+ TextureStorage *storage,
+ int level)
+{
+ return gl::NoError();
+}
+
+gl::Error ImageD3D::setManagedSurfaceCube(const gl::Context *context,
+ TextureStorage *storage,
+ int face,
+ int level)
+{
+ return gl::NoError();
+}
+
+gl::Error ImageD3D::setManagedSurface3D(const gl::Context *context,
+ TextureStorage *storage,
+ int level)
+{
+ return gl::NoError();
+}
+
+gl::Error ImageD3D::setManagedSurface2DArray(const gl::Context *context,
+ TextureStorage *storage,
+ int layer,
+ int level)
+{
+ return gl::NoError();
+}
+
} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.h
index 2afe1cfabf..1b7235fbaa 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.h
@@ -17,6 +17,7 @@
namespace gl
{
+class Context;
class Framebuffer;
struct ImageIndex;
struct Box;
@@ -51,18 +52,40 @@ class ImageD3D : angle::NonCopyable
virtual bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) = 0;
- virtual gl::Error loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input) = 0;
- virtual gl::Error loadCompressedData(const gl::Box &area, const void *input) = 0;
-
- virtual gl::Error setManagedSurface2D(TextureStorage *storage, int level) { return gl::Error(GL_NO_ERROR); };
- virtual gl::Error setManagedSurfaceCube(TextureStorage *storage, int face, int level) { return gl::Error(GL_NO_ERROR); };
- virtual gl::Error setManagedSurface3D(TextureStorage *storage, int level) { return gl::Error(GL_NO_ERROR); };
- virtual gl::Error setManagedSurface2DArray(TextureStorage *storage, int layer, int level) { return gl::Error(GL_NO_ERROR); };
- virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region) = 0;
-
- virtual gl::Error copyFromTexStorage(const gl::ImageIndex &imageIndex,
+ virtual gl::Error loadData(const gl::Context *context,
+ const gl::Box &area,
+ const gl::PixelUnpackState &unpack,
+ GLenum type,
+ const void *input,
+ bool applySkipImages) = 0;
+ virtual gl::Error loadCompressedData(const gl::Context *context,
+ const gl::Box &area,
+ const void *input) = 0;
+
+ virtual gl::Error setManagedSurface2D(const gl::Context *context,
+ TextureStorage *storage,
+ int level);
+ virtual gl::Error setManagedSurfaceCube(const gl::Context *context,
+ TextureStorage *storage,
+ int face,
+ int level);
+ virtual gl::Error setManagedSurface3D(const gl::Context *context,
+ TextureStorage *storage,
+ int level);
+ virtual gl::Error setManagedSurface2DArray(const gl::Context *context,
+ TextureStorage *storage,
+ int layer,
+ int level);
+ virtual gl::Error copyToStorage(const gl::Context *context,
+ TextureStorage *storage,
+ const gl::ImageIndex &index,
+ const gl::Box &region) = 0;
+
+ virtual gl::Error copyFromTexStorage(const gl::Context *context,
+ const gl::ImageIndex &imageIndex,
TextureStorage *source) = 0;
- virtual gl::Error copyFromFramebuffer(const gl::Offset &destOffset,
+ virtual gl::Error copyFromFramebuffer(const gl::Context *context,
+ const gl::Offset &destOffset,
const gl::Rectangle &sourceArea,
const gl::Framebuffer *source) = 0;
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp
index 677b8bb240..937512a96a 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp
@@ -71,7 +71,8 @@ gl::Error IndexBufferInterface::mapBuffer(unsigned int size, void **outMappedMem
// Protect against integer overflow
if (mWritePosition + size < mWritePosition)
{
- return gl::Error(GL_OUT_OF_MEMORY, "Mapping of internal index buffer would cause an integer overflow.");
+ return gl::OutOfMemory()
+ << "Mapping of internal index buffer would cause an integer overflow.";
}
gl::Error error = mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory);
@@ -79,7 +80,7 @@ gl::Error IndexBufferInterface::mapBuffer(unsigned int size, void **outMappedMem
{
if (outMappedMemory)
{
- *outMappedMemory = NULL;
+ *outMappedMemory = nullptr;
}
return error;
}
@@ -90,7 +91,7 @@ gl::Error IndexBufferInterface::mapBuffer(unsigned int size, void **outMappedMem
}
mWritePosition += size;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error IndexBufferInterface::unmapBuffer()
@@ -145,24 +146,16 @@ gl::Error StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, G
unsigned int writePos = getWritePosition();
if (size > curBufferSize)
{
- gl::Error error = setBufferSize(std::max(size, 2 * curBufferSize), indexType);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(setBufferSize(std::max(size, 2 * curBufferSize), indexType));
setWritePosition(0);
}
else if (writePos + size > curBufferSize || writePos + size < writePos)
{
- gl::Error error = discard();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(discard());
setWritePosition(0);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
@@ -184,13 +177,13 @@ gl::Error StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLen
}
else if (curSize >= size && indexType == getIndexType())
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
else
{
UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION, "Internal static index buffers can't be resized");
+ return gl::InternalError() << "Internal static index buffers can't be resized";
}
}
-}
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.h
index 0b7b28ddf0..969cf6ae63 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.h
@@ -81,7 +81,7 @@ class StreamingIndexBufferInterface : public IndexBufferInterface
{
public:
explicit StreamingIndexBufferInterface(BufferFactoryD3D *factory);
- ~StreamingIndexBufferInterface();
+ ~StreamingIndexBufferInterface() override;
gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) override;
};
@@ -90,7 +90,7 @@ class StaticIndexBufferInterface : public IndexBufferInterface
{
public:
explicit StaticIndexBufferInterface(BufferFactoryD3D *factory);
- ~StaticIndexBufferInterface();
+ ~StaticIndexBufferInterface() override;
gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) override;
};
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp
index f1ba3d3db0..e974097b45 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp
@@ -10,10 +10,12 @@
#include "libANGLE/renderer/d3d/IndexDataManager.h"
#include "common/utilities.h"
-#include "libANGLE/renderer/d3d/BufferD3D.h"
-#include "libANGLE/renderer/d3d/IndexBuffer.h"
#include "libANGLE/Buffer.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/VertexArray.h"
#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/IndexBuffer.h"
namespace rx
{
@@ -76,11 +78,12 @@ void ConvertIndices(GLenum sourceType,
ConvertIndexArray<GLushort, GLuint>(input, sourceType, output, destinationType, count,
usePrimitiveRestartFixedIndex);
}
- else UNREACHABLE();
+ else
+ UNREACHABLE();
}
gl::Error StreamInIndexBuffer(IndexBufferInterface *buffer,
- const GLvoid *data,
+ const void *data,
unsigned int count,
GLenum srcType,
GLenum dstType,
@@ -91,50 +94,59 @@ gl::Error StreamInIndexBuffer(IndexBufferInterface *buffer,
if (count > (std::numeric_limits<unsigned int>::max() >> dstTypeInfo.bytesShift))
{
- return gl::Error(GL_OUT_OF_MEMORY,
- "Reserving %u indices of %u bytes each exceeds the maximum buffer size.",
- count, dstTypeInfo.bytes);
+ return gl::OutOfMemory() << "Reserving " << count << " indices of " << dstTypeInfo.bytes
+ << " bytes each exceeds the maximum buffer size.";
}
unsigned int bufferSizeRequired = count << dstTypeInfo.bytesShift;
- gl::Error error = buffer->reserveBufferSpace(bufferSizeRequired, dstType);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(buffer->reserveBufferSpace(bufferSizeRequired, dstType));
void *output = nullptr;
- error = buffer->mapBuffer(bufferSizeRequired, &output, offset);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(buffer->mapBuffer(bufferSizeRequired, &output, offset));
ConvertIndices(srcType, dstType, data, count, output, usePrimitiveRestartFixedIndex);
- error = buffer->unmapBuffer();
- if (error.isError())
+ ANGLE_TRY(buffer->unmapBuffer());
+ return gl::NoError();
+}
+
+unsigned int ElementTypeSize(GLenum elementType)
+{
+ switch (elementType)
{
- return error;
+ case GL_UNSIGNED_BYTE:
+ return sizeof(GLubyte);
+ case GL_UNSIGNED_SHORT:
+ return sizeof(GLushort);
+ case GL_UNSIGNED_INT:
+ return sizeof(GLuint);
+ default:
+ UNREACHABLE();
+ return 0;
}
-
- return gl::Error(GL_NO_ERROR);
}
} // anonymous namespace
-IndexDataManager::IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass)
- : mFactory(factory),
- mRendererClass(rendererClass),
- mStreamingBufferShort(nullptr),
- mStreamingBufferInt(nullptr)
+bool IsOffsetAligned(GLenum elementType, unsigned int offset)
+{
+ return (offset % ElementTypeSize(elementType) == 0);
+}
+
+// IndexDataManager implementation.
+IndexDataManager::IndexDataManager(BufferFactoryD3D *factory)
+ : mFactory(factory), mStreamingBufferShort(), mStreamingBufferInt()
{
}
IndexDataManager::~IndexDataManager()
{
- SafeDelete(mStreamingBufferShort);
- SafeDelete(mStreamingBufferInt);
+}
+
+void IndexDataManager::deinitialize()
+{
+ mStreamingBufferShort.reset();
+ mStreamingBufferInt.reset();
}
// This function translates a GL-style indices into DX-style indices, with their description
@@ -143,43 +155,31 @@ IndexDataManager::~IndexDataManager()
// possible in DX and requires streaming (Case 1). If the GL indices are specified with a buffer
// (Case 2), in a format supported by DX (subcase a) then all is good.
// When we have a buffer with an unsupported format (subcase b) then we need to do some translation:
-// we will start by falling back to streaming, and after a while will start using a static translated
-// copy of the index buffer.
-gl::Error IndexDataManager::prepareIndexData(GLenum srcType,
+// we will start by falling back to streaming, and after a while will start using a static
+// translated copy of the index buffer.
+gl::Error IndexDataManager::prepareIndexData(const gl::Context *context,
+ GLenum srcType,
+ GLenum dstType,
GLsizei count,
gl::Buffer *glBuffer,
- const GLvoid *indices,
- TranslatedIndexData *translated,
- bool primitiveRestartFixedIndexEnabled)
+ const void *indices,
+ TranslatedIndexData *translated)
{
- // Avoid D3D11's primitive restart index value
- // see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx
- bool hasPrimitiveRestartIndex =
- translated->indexRange.vertexIndexCount < static_cast<size_t>(count) ||
- translated->indexRange.end == gl::GetPrimitiveRestartIndex(srcType);
- bool primitiveRestartWorkaround = mRendererClass == RENDERER_D3D11 &&
- !primitiveRestartFixedIndexEnabled &&
- hasPrimitiveRestartIndex && srcType == GL_UNSIGNED_SHORT;
-
- // We should never have to deal with MAX_UINT indices, since we restrict it via
- // MAX_ELEMENT_INDEX.
- ASSERT(!(mRendererClass == RENDERER_D3D11 && !primitiveRestartFixedIndexEnabled &&
- hasPrimitiveRestartIndex && srcType == GL_UNSIGNED_INT));
-
- const GLenum dstType = (srcType == GL_UNSIGNED_INT || primitiveRestartWorkaround) ?
- GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
-
const gl::Type &srcTypeInfo = gl::GetTypeInfo(srcType);
const gl::Type &dstTypeInfo = gl::GetTypeInfo(dstType);
BufferD3D *buffer = glBuffer ? GetImplAs<BufferD3D>(glBuffer) : nullptr;
- translated->indexType = dstType;
+ translated->indexType = dstType;
translated->srcIndexData.srcBuffer = buffer;
translated->srcIndexData.srcIndices = indices;
translated->srcIndexData.srcIndexType = srcType;
translated->srcIndexData.srcCount = count;
+ // Context can be nullptr in perf tests.
+ bool primitiveRestartFixedIndexEnabled =
+ context ? context->getGLState().isPrimitiveRestartEnabled() : false;
+
// Case 1: the indices are passed by pointer, which forces the streaming of index data
if (glBuffer == nullptr)
{
@@ -192,95 +192,69 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType,
unsigned int offset = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(indices));
ASSERT(srcTypeInfo.bytes * static_cast<unsigned int>(count) + offset <= buffer->getSize());
- bool offsetAligned;
- switch (srcType)
- {
- case GL_UNSIGNED_BYTE: offsetAligned = (offset % sizeof(GLubyte) == 0); break;
- case GL_UNSIGNED_SHORT: offsetAligned = (offset % sizeof(GLushort) == 0); break;
- case GL_UNSIGNED_INT: offsetAligned = (offset % sizeof(GLuint) == 0); break;
- default: UNREACHABLE(); offsetAligned = false;
- }
+ bool offsetAligned = IsOffsetAligned(srcType, offset);
// Case 2a: the buffer can be used directly
- if (offsetAligned && buffer->supportsDirectBinding() &&
- dstType == srcType && !primitiveRestartWorkaround)
+ if (offsetAligned && buffer->supportsDirectBinding() && dstType == srcType)
{
- translated->storage = buffer;
+ translated->storage = buffer;
translated->indexBuffer = nullptr;
- translated->serial = buffer->getSerial();
- translated->startIndex = (offset >> srcTypeInfo.bytesShift);
+ translated->serial = buffer->getSerial();
+ translated->startIndex = (offset >> srcTypeInfo.bytesShift);
translated->startOffset = offset;
- buffer->promoteStaticUsage(count << srcTypeInfo.bytesShift);
- return gl::Error(GL_NO_ERROR);
- }
- else
- {
- translated->storage = nullptr;
+ return gl::NoError();
}
+ translated->storage = nullptr;
+
// Case 2b: use a static translated copy or fall back to streaming
StaticIndexBufferInterface *staticBuffer = buffer->getStaticIndexBuffer();
bool staticBufferInitialized = staticBuffer && staticBuffer->getBufferSize() != 0;
- bool staticBufferUsable = staticBuffer &&
- offsetAligned && staticBuffer->getIndexType() == dstType;
+ bool staticBufferUsable =
+ staticBuffer && offsetAligned && staticBuffer->getIndexType() == dstType;
if (staticBufferInitialized && !staticBufferUsable)
{
- buffer->invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE);
+ buffer->invalidateStaticData(context);
staticBuffer = nullptr;
}
if (staticBuffer == nullptr || !offsetAligned)
{
const uint8_t *bufferData = nullptr;
- gl::Error error = buffer->getData(&bufferData);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(buffer->getData(context, &bufferData));
ASSERT(bufferData != nullptr);
- error = streamIndexData(bufferData + offset, count, srcType, dstType,
- primitiveRestartFixedIndexEnabled, translated);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(streamIndexData(bufferData + offset, count, srcType, dstType,
+ primitiveRestartFixedIndexEnabled, translated));
+ buffer->promoteStaticUsage(context, count << srcTypeInfo.bytesShift);
}
else
{
if (!staticBufferInitialized)
{
const uint8_t *bufferData = nullptr;
- gl::Error error = buffer->getData(&bufferData);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(buffer->getData(context, &bufferData));
ASSERT(bufferData != nullptr);
unsigned int convertCount =
static_cast<unsigned int>(buffer->getSize()) >> srcTypeInfo.bytesShift;
- error = StreamInIndexBuffer(staticBuffer, bufferData, convertCount, srcType, dstType,
- primitiveRestartFixedIndexEnabled, nullptr);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(StreamInIndexBuffer(staticBuffer, bufferData, convertCount, srcType, dstType,
+ primitiveRestartFixedIndexEnabled, nullptr));
}
ASSERT(offsetAligned && staticBuffer->getIndexType() == dstType);
translated->indexBuffer = staticBuffer->getIndexBuffer();
- translated->serial = staticBuffer->getSerial();
- translated->startIndex = (offset >> srcTypeInfo.bytesShift);
+ translated->serial = staticBuffer->getSerial();
+ translated->startIndex = (offset >> srcTypeInfo.bytesShift);
translated->startOffset = (offset >> srcTypeInfo.bytesShift) << dstTypeInfo.bytesShift;
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error IndexDataManager::streamIndexData(const GLvoid *data,
+gl::Error IndexDataManager::streamIndexData(const void *data,
unsigned int count,
GLenum srcType,
GLenum dstType,
@@ -290,65 +264,57 @@ gl::Error IndexDataManager::streamIndexData(const GLvoid *data,
const gl::Type &dstTypeInfo = gl::GetTypeInfo(dstType);
IndexBufferInterface *indexBuffer = nullptr;
- gl::Error error = getStreamingIndexBuffer(dstType, &indexBuffer);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(getStreamingIndexBuffer(dstType, &indexBuffer));
ASSERT(indexBuffer != nullptr);
unsigned int offset;
- StreamInIndexBuffer(indexBuffer, data, count, srcType, dstType, usePrimitiveRestartFixedIndex,
- &offset);
+ ANGLE_TRY(StreamInIndexBuffer(indexBuffer, data, count, srcType, dstType,
+ usePrimitiveRestartFixedIndex, &offset));
translated->indexBuffer = indexBuffer->getIndexBuffer();
- translated->serial = indexBuffer->getSerial();
- translated->startIndex = (offset >> dstTypeInfo.bytesShift);
+ translated->serial = indexBuffer->getSerial();
+ translated->startIndex = (offset >> dstTypeInfo.bytesShift);
translated->startOffset = offset;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error IndexDataManager::getStreamingIndexBuffer(GLenum destinationIndexType,
IndexBufferInterface **outBuffer)
{
ASSERT(outBuffer);
- if (destinationIndexType == GL_UNSIGNED_INT)
- {
- if (!mStreamingBufferInt)
- {
- mStreamingBufferInt = new StreamingIndexBufferInterface(mFactory);
- gl::Error error = mStreamingBufferInt->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE,
- GL_UNSIGNED_INT);
- if (error.isError())
- {
- SafeDelete(mStreamingBufferInt);
- return error;
- }
- }
+ ASSERT(destinationIndexType == GL_UNSIGNED_SHORT || destinationIndexType == GL_UNSIGNED_INT);
- *outBuffer = mStreamingBufferInt;
- return gl::Error(GL_NO_ERROR);
- }
- else
+ auto &streamingBuffer =
+ (destinationIndexType == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort;
+
+ if (!streamingBuffer)
{
- ASSERT(destinationIndexType == GL_UNSIGNED_SHORT);
+ StreamingBuffer newBuffer(new StreamingIndexBufferInterface(mFactory));
+ ANGLE_TRY(newBuffer->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, destinationIndexType));
+ streamingBuffer = std::move(newBuffer);
+ }
- if (!mStreamingBufferShort)
+ *outBuffer = streamingBuffer.get();
+ return gl::NoError();
+}
+
+GLenum GetIndexTranslationDestType(GLenum srcType,
+ const gl::HasIndexRange &lazyIndexRange,
+ bool usePrimitiveRestartWorkaround)
+{
+ // Avoid D3D11's primitive restart index value
+ // see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx
+ if (usePrimitiveRestartWorkaround)
+ {
+ const gl::IndexRange &indexRange = lazyIndexRange.getIndexRange().value();
+ if (indexRange.end == gl::GetPrimitiveRestartIndex(srcType))
{
- mStreamingBufferShort = new StreamingIndexBufferInterface(mFactory);
- gl::Error error = mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE,
- GL_UNSIGNED_SHORT);
- if (error.isError())
- {
- SafeDelete(mStreamingBufferShort);
- return error;
- }
+ return GL_UNSIGNED_INT;
}
-
- *outBuffer = mStreamingBufferShort;
- return gl::Error(GL_NO_ERROR);
}
-}
+ return (srcType == GL_UNSIGNED_INT) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.h
index 44eb68c071..77f05df92d 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.h
@@ -19,7 +19,10 @@
namespace
{
- enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) };
+enum
+{
+ INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint)
+};
}
namespace gl
@@ -39,7 +42,7 @@ class RendererD3D;
struct SourceIndexData
{
BufferD3D *srcBuffer;
- const GLvoid *srcIndices;
+ const void *srcIndices;
unsigned int srcCount;
GLenum srcIndexType;
bool srcIndicesChanged;
@@ -47,9 +50,8 @@ struct SourceIndexData
struct TranslatedIndexData
{
- gl::IndexRange indexRange;
unsigned int startIndex;
- unsigned int startOffset; // In bytes
+ unsigned int startOffset; // In bytes
IndexBuffer *indexBuffer;
BufferD3D *storage;
@@ -62,18 +64,21 @@ struct TranslatedIndexData
class IndexDataManager : angle::NonCopyable
{
public:
- explicit IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass);
+ explicit IndexDataManager(BufferFactoryD3D *factory);
virtual ~IndexDataManager();
- gl::Error prepareIndexData(GLenum srcType,
+ void deinitialize();
+
+ gl::Error prepareIndexData(const gl::Context *context,
+ GLenum srcType,
+ GLenum dstType,
GLsizei count,
gl::Buffer *glBuffer,
- const GLvoid *indices,
- TranslatedIndexData *translated,
- bool primitiveRestartFixedIndexEnabled);
+ const void *indices,
+ TranslatedIndexData *translated);
private:
- gl::Error streamIndexData(const GLvoid *data,
+ gl::Error streamIndexData(const void *data,
unsigned int count,
GLenum srcType,
GLenum dstType,
@@ -82,12 +87,19 @@ class IndexDataManager : angle::NonCopyable
gl::Error getStreamingIndexBuffer(GLenum destinationIndexType,
IndexBufferInterface **outBuffer);
+ using StreamingBuffer = std::unique_ptr<StreamingIndexBufferInterface>;
+
BufferFactoryD3D *const mFactory;
- RendererClass mRendererClass;
- StreamingIndexBufferInterface *mStreamingBufferShort;
- StreamingIndexBufferInterface *mStreamingBufferInt;
+ std::unique_ptr<StreamingIndexBufferInterface> mStreamingBufferShort;
+ std::unique_ptr<StreamingIndexBufferInterface> mStreamingBufferInt;
};
-}
+GLenum GetIndexTranslationDestType(GLenum srcType,
+ const gl::HasIndexRange &lazyIndexRange,
+ bool usePrimitiveRestartWorkaround);
+
+bool IsOffsetAligned(GLenum elementType, unsigned int offset);
+
+} // namespace rx
-#endif // LIBANGLE_INDEXDATAMANAGER_H_
+#endif // LIBANGLE_INDEXDATAMANAGER_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.cpp
new file mode 100644
index 0000000000..113bad647c
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.cpp
@@ -0,0 +1,23 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// NativeWindowD3D.cpp: Defines NativeWindowD3D, a class for managing and performing operations on
+// an EGLNativeWindowType for the D3D renderers.
+
+#include "libANGLE/renderer/d3d/NativeWindowD3D.h"
+
+namespace rx
+{
+
+NativeWindowD3D::NativeWindowD3D(EGLNativeWindowType window) : mWindow(window)
+{
+}
+
+NativeWindowD3D::~NativeWindowD3D()
+{
+}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.h
new file mode 100644
index 0000000000..365448488d
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/NativeWindowD3D.h
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// NativeWindowD3D.h: Defines NativeWindowD3D, a class for managing and performing operations on an
+// EGLNativeWindowType for the D3D renderers.
+
+#ifndef LIBANGLE_RENDERER_D3D_NATIVEWINDOWD3D_H_
+#define LIBANGLE_RENDERER_D3D_NATIVEWINDOWD3D_H_
+
+#include "common/debug.h"
+#include "common/platform.h"
+
+#include <EGL/eglplatform.h>
+#include "libANGLE/Config.h"
+
+namespace rx
+{
+class NativeWindowD3D : angle::NonCopyable
+{
+ public:
+ NativeWindowD3D(EGLNativeWindowType window);
+ virtual ~NativeWindowD3D();
+
+ virtual bool initialize() = 0;
+ virtual bool getClientRect(LPRECT rect) const = 0;
+ virtual bool isIconic() const = 0;
+
+ inline EGLNativeWindowType getNativeWindow() const { return mWindow; }
+
+ private:
+ EGLNativeWindowType mWindow;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_NATIVEWINDOWD3D_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp
index 72c6f1a1a9..afc318d9fa 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp
@@ -8,31 +8,41 @@
#include "libANGLE/renderer/d3d/ProgramD3D.h"
-#include "common/BitSetIterator.h"
+#include "common/bitset_utils.h"
+#include "common/string_utils.h"
#include "common/utilities.h"
+#include "libANGLE/Context.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/Program.h"
+#include "libANGLE/ProgramLinkedResources.h"
+#include "libANGLE/Uniform.h"
#include "libANGLE/VertexArray.h"
#include "libANGLE/features.h"
+#include "libANGLE/queryconversions.h"
+#include "libANGLE/renderer/ContextImpl.h"
#include "libANGLE/renderer/d3d/DynamicHLSL.h"
#include "libANGLE/renderer/d3d/FramebufferD3D.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/ShaderD3D.h"
#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
-#include "libANGLE/renderer/d3d/VaryingPacking.h"
#include "libANGLE/renderer/d3d/VertexDataManager.h"
+using namespace angle;
+
namespace rx
{
namespace
{
-gl::InputLayout GetDefaultInputLayoutFromShader(const gl::Shader *vertexShader)
+void GetDefaultInputLayoutFromShader(const gl::Context *context,
+ gl::Shader *vertexShader,
+ gl::InputLayout *inputLayoutOut)
{
- gl::InputLayout defaultLayout;
- for (const sh::Attribute &shaderAttr : vertexShader->getActiveAttributes())
+ inputLayoutOut->clear();
+
+ for (const sh::Attribute &shaderAttr : vertexShader->getActiveAttributes(context))
{
if (shaderAttr.type != GL_NONE)
{
@@ -47,301 +57,256 @@ gl::InputLayout GetDefaultInputLayoutFromShader(const gl::Shader *vertexShader)
gl::VertexFormatType defaultType =
gl::GetVertexFormatType(componentType, GL_FALSE, components, pureInt);
- defaultLayout.push_back(defaultType);
+ inputLayoutOut->push_back(defaultType);
}
}
}
-
- return defaultLayout;
}
-std::vector<GLenum> GetDefaultOutputLayoutFromShader(
- const std::vector<PixelShaderOutputVariable> &shaderOutputVars)
+void GetDefaultOutputLayoutFromShader(
+ const std::vector<PixelShaderOutputVariable> &shaderOutputVars,
+ std::vector<GLenum> *outputLayoutOut)
{
- std::vector<GLenum> defaultPixelOutput;
+ outputLayoutOut->clear();
if (!shaderOutputVars.empty())
{
- defaultPixelOutput.push_back(GL_COLOR_ATTACHMENT0 +
- static_cast<unsigned int>(shaderOutputVars[0].outputIndex));
+ outputLayoutOut->push_back(GL_COLOR_ATTACHMENT0 +
+ static_cast<unsigned int>(shaderOutputVars[0].outputIndex));
}
-
- return defaultPixelOutput;
}
-bool IsRowMajorLayout(const sh::InterfaceBlockField &var)
+template <typename T, int cols, int rows>
+bool TransposeExpandMatrix(T *target, const GLfloat *value)
{
- return var.isRowMajorLayout;
-}
+ constexpr int targetWidth = 4;
+ constexpr int targetHeight = rows;
+ constexpr int srcWidth = rows;
+ constexpr int srcHeight = cols;
-bool IsRowMajorLayout(const sh::ShaderVariable &var)
-{
- return false;
-}
+ constexpr int copyWidth = std::min(targetHeight, srcWidth);
+ constexpr int copyHeight = std::min(targetWidth, srcHeight);
-struct AttributeSorter
-{
- AttributeSorter(const ProgramD3D::SemanticIndexArray &semanticIndices)
- : originalIndices(&semanticIndices)
+ T staging[targetWidth * targetHeight] = {0};
+
+ for (int x = 0; x < copyWidth; x++)
{
+ for (int y = 0; y < copyHeight; y++)
+ {
+ staging[x * targetWidth + y] = static_cast<T>(value[y * srcWidth + x]);
+ }
}
- bool operator()(int a, int b)
+ if (memcmp(target, staging, targetWidth * targetHeight * sizeof(T)) == 0)
{
- int indexA = (*originalIndices)[a];
- int indexB = (*originalIndices)[b];
-
- if (indexA == -1)
- return false;
- if (indexB == -1)
- return true;
- return (indexA < indexB);
+ return false;
}
- const ProgramD3D::SemanticIndexArray *originalIndices;
-};
-
-// true if varying x has a higher priority in packing than y
-bool ComparePackedVarying(const PackedVarying &x, const PackedVarying &y)
-{
- return gl::CompareShaderVar(*x.varying, *y.varying);
+ memcpy(target, staging, targetWidth * targetHeight * sizeof(T));
+ return true;
}
-std::vector<PackedVarying> MergeVaryings(const gl::Shader &vertexShader,
- const gl::Shader &fragmentShader,
- const std::vector<std::string> &tfVaryings)
+template <typename T, int cols, int rows>
+bool ExpandMatrix(T *target, const GLfloat *value)
{
- std::vector<PackedVarying> packedVaryings;
+ constexpr int targetWidth = 4;
+ constexpr int targetHeight = rows;
+ constexpr int srcWidth = cols;
+ constexpr int srcHeight = rows;
- for (const sh::Varying &output : vertexShader.getVaryings())
- {
- bool packed = false;
+ constexpr int copyWidth = std::min(targetWidth, srcWidth);
+ constexpr int copyHeight = std::min(targetHeight, srcHeight);
- // Built-in varyings obey special rules
- if (output.isBuiltIn())
- {
- continue;
- }
-
- for (const sh::Varying &input : fragmentShader.getVaryings())
- {
- if (output.name == input.name)
- {
- if (output.isStruct())
- {
- ASSERT(!output.isArray());
- for (const auto &field : output.fields)
- {
- ASSERT(!field.isStruct() && !field.isArray());
- packedVaryings.push_back(
- PackedVarying(field, input.interpolation, input.name));
- }
- }
- else
- {
- packedVaryings.push_back(PackedVarying(input, input.interpolation));
- }
- packed = true;
- break;
- }
- }
+ T staging[targetWidth * targetHeight] = {0};
- // Keep Transform FB varyings in the merged list always.
- if (!packed)
+ for (int y = 0; y < copyHeight; y++)
+ {
+ for (int x = 0; x < copyWidth; x++)
{
- for (const std::string &tfVarying : tfVaryings)
- {
- if (tfVarying == output.name)
- {
- // Transform feedback for varying structs is underspecified.
- // See Khronos bug 9856.
- // TODO(jmadill): Figure out how to be spec-compliant here.
- if (!output.isStruct())
- {
- packedVaryings.push_back(PackedVarying(output, output.interpolation));
- packedVaryings.back().vertexOnly = true;
- }
- break;
- }
- }
+ staging[y * targetWidth + x] = static_cast<T>(value[y * srcWidth + x]);
}
}
- std::sort(packedVaryings.begin(), packedVaryings.end(), ComparePackedVarying);
+ if (memcmp(target, staging, targetWidth * targetHeight * sizeof(T)) == 0)
+ {
+ return false;
+ }
- return packedVaryings;
+ memcpy(target, staging, targetWidth * targetHeight * sizeof(T));
+ return true;
}
-template <typename VarT>
-void GetUniformBlockInfo(const std::vector<VarT> &fields,
- const std::string &prefix,
- sh::BlockLayoutEncoder *encoder,
- bool inRowMajorLayout,
- std::map<std::string, sh::BlockMemberInfo> *blockInfoOut)
+gl::PrimitiveType GetGeometryShaderTypeFromDrawMode(GLenum drawMode)
{
- for (const VarT &field : fields)
+ switch (drawMode)
{
- const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
+ // Uses the point sprite geometry shader.
+ case GL_POINTS:
+ return gl::PRIMITIVE_POINTS;
- if (field.isStruct())
- {
- bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field));
+ // All line drawing uses the same geometry shader.
+ case GL_LINES:
+ case GL_LINE_STRIP:
+ case GL_LINE_LOOP:
+ return gl::PRIMITIVE_LINES;
- for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
- {
- encoder->enterAggregateType();
+ // The triangle fan primitive is emulated with strips in D3D11.
+ case GL_TRIANGLES:
+ case GL_TRIANGLE_FAN:
+ return gl::PRIMITIVE_TRIANGLES;
- const std::string uniformElementName =
- fieldName + (field.isArray() ? ArrayString(arrayElement) : "");
- GetUniformBlockInfo(field.fields, uniformElementName, encoder, rowMajorLayout,
- blockInfoOut);
+ // Special case for triangle strips.
+ case GL_TRIANGLE_STRIP:
+ return gl::PRIMITIVE_TRIANGLE_STRIP;
- encoder->exitAggregateType();
- }
- }
- else
- {
- bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout);
- (*blockInfoOut)[fieldName] =
- encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix);
- }
+ default:
+ UNREACHABLE();
+ return gl::PRIMITIVE_TYPE_MAX;
}
}
-template <typename T>
-static inline void SetIfDirty(T *dest, const T &source, bool *dirtyFlag)
-{
- ASSERT(dest != NULL);
- ASSERT(dirtyFlag != NULL);
-
- *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0);
- *dest = source;
-}
-
-template <typename T>
-bool TransposeMatrix(T *target,
- const GLfloat *value,
- int targetWidth,
- int targetHeight,
- int srcWidth,
- int srcHeight)
+bool FindFlatInterpolationVarying(const std::vector<sh::Varying> &varyings)
{
- bool dirty = false;
- int copyWidth = std::min(targetHeight, srcWidth);
- int copyHeight = std::min(targetWidth, srcHeight);
-
- for (int x = 0; x < copyWidth; x++)
+ // Note: this assumes nested structs can only be packed with one interpolation.
+ for (const auto &varying : varyings)
{
- for (int y = 0; y < copyHeight; y++)
- {
- SetIfDirty(target + (x * targetWidth + y), static_cast<T>(value[y * srcWidth + x]),
- &dirty);
- }
- }
- // clear unfilled right side
- for (int y = 0; y < copyWidth; y++)
- {
- for (int x = copyHeight; x < targetWidth; x++)
+ if (varying.interpolation == sh::INTERPOLATION_FLAT)
{
- SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
+ return true;
}
}
- // clear unfilled bottom.
- for (int y = copyWidth; y < targetHeight; y++)
+
+ return false;
+}
+
+// Helper method to de-tranpose a matrix uniform for an API query.
+void GetMatrixUniform(GLint columns, GLint rows, GLfloat *dataOut, const GLfloat *source)
+{
+ for (GLint col = 0; col < columns; ++col)
{
- for (int x = 0; x < targetWidth; x++)
+ for (GLint row = 0; row < rows; ++row)
{
- SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
+ GLfloat *outptr = dataOut + ((col * rows) + row);
+ const GLfloat *inptr = source + ((row * 4) + col);
+ *outptr = *inptr;
}
}
+}
- return dirty;
+template <typename NonFloatT>
+void GetMatrixUniform(GLint columns, GLint rows, NonFloatT *dataOut, const NonFloatT *source)
+{
+ UNREACHABLE();
}
-template <typename T>
-bool ExpandMatrix(T *target,
- const GLfloat *value,
- int targetWidth,
- int targetHeight,
- int srcWidth,
- int srcHeight)
+class UniformBlockInfo final : angle::NonCopyable
{
- bool dirty = false;
- int copyWidth = std::min(targetWidth, srcWidth);
- int copyHeight = std::min(targetHeight, srcHeight);
+ public:
+ UniformBlockInfo() {}
- for (int y = 0; y < copyHeight; y++)
+ void getShaderBlockInfo(const gl::Context *context, gl::Shader *shader);
+
+ bool getBlockSize(const std::string &name, const std::string &mappedName, size_t *sizeOut);
+ bool getBlockMemberInfo(const std::string &name,
+ const std::string &mappedName,
+ sh::BlockMemberInfo *infoOut);
+
+ private:
+ size_t getBlockInfo(const sh::InterfaceBlock &interfaceBlock);
+
+ std::map<std::string, size_t> mBlockSizes;
+ sh::BlockLayoutMap mBlockLayout;
+};
+
+void UniformBlockInfo::getShaderBlockInfo(const gl::Context *context, gl::Shader *shader)
+{
+ for (const sh::InterfaceBlock &interfaceBlock : shader->getUniformBlocks(context))
{
- for (int x = 0; x < copyWidth; x++)
- {
- SetIfDirty(target + (y * targetWidth + x), static_cast<T>(value[y * srcWidth + x]),
- &dirty);
- }
+ if (!interfaceBlock.staticUse && interfaceBlock.layout == sh::BLOCKLAYOUT_PACKED)
+ continue;
+
+ if (mBlockSizes.count(interfaceBlock.name) > 0)
+ continue;
+
+ size_t dataSize = getBlockInfo(interfaceBlock);
+ mBlockSizes[interfaceBlock.name] = dataSize;
}
- // clear unfilled right side
- for (int y = 0; y < copyHeight; y++)
+}
+
+size_t UniformBlockInfo::getBlockInfo(const sh::InterfaceBlock &interfaceBlock)
+{
+ ASSERT(interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED);
+
+ // define member uniforms
+ sh::Std140BlockEncoder std140Encoder;
+ sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED, false);
+ sh::BlockLayoutEncoder *encoder = nullptr;
+
+ if (interfaceBlock.layout == sh::BLOCKLAYOUT_STD140)
{
- for (int x = copyWidth; x < targetWidth; x++)
- {
- SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
- }
+ encoder = &std140Encoder;
}
- // clear unfilled bottom.
- for (int y = copyHeight; y < targetHeight; y++)
+ else
{
- for (int x = 0; x < targetWidth; x++)
- {
- SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
- }
+ encoder = &hlslEncoder;
}
- return dirty;
+ sh::GetUniformBlockInfo(interfaceBlock.fields, interfaceBlock.fieldPrefix(), encoder,
+ interfaceBlock.isRowMajorLayout, &mBlockLayout);
+
+ return encoder->getBlockSize();
}
-gl::PrimitiveType GetGeometryShaderTypeFromDrawMode(GLenum drawMode)
+bool UniformBlockInfo::getBlockSize(const std::string &name,
+ const std::string &mappedName,
+ size_t *sizeOut)
{
- switch (drawMode)
+ size_t nameLengthWithoutArrayIndex;
+ gl::ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
+ std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
+ auto sizeIter = mBlockSizes.find(baseName);
+ if (sizeIter == mBlockSizes.end())
{
- // Uses the point sprite geometry shader.
- case GL_POINTS:
- return gl::PRIMITIVE_POINTS;
-
- // All line drawing uses the same geometry shader.
- case GL_LINES:
- case GL_LINE_STRIP:
- case GL_LINE_LOOP:
- return gl::PRIMITIVE_LINES;
-
- // The triangle fan primitive is emulated with strips in D3D11.
- case GL_TRIANGLES:
- case GL_TRIANGLE_FAN:
- return gl::PRIMITIVE_TRIANGLES;
+ *sizeOut = 0;
+ return false;
+ }
- // Special case for triangle strips.
- case GL_TRIANGLE_STRIP:
- return gl::PRIMITIVE_TRIANGLE_STRIP;
+ *sizeOut = sizeIter->second;
+ return true;
+};
- default:
- UNREACHABLE();
- return gl::PRIMITIVE_TYPE_MAX;
+bool UniformBlockInfo::getBlockMemberInfo(const std::string &name,
+ const std::string &mappedName,
+ sh::BlockMemberInfo *infoOut)
+{
+ auto infoIter = mBlockLayout.find(name);
+ if (infoIter == mBlockLayout.end())
+ {
+ *infoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
+ return false;
}
-}
+
+ *infoOut = infoIter->second;
+ return true;
+};
} // anonymous namespace
// D3DUniform Implementation
-D3DUniform::D3DUniform(GLenum typeIn,
+D3DUniform::D3DUniform(GLenum type,
const std::string &nameIn,
- unsigned int arraySizeIn,
+ const std::vector<unsigned int> &arraySizesIn,
bool defaultBlock)
- : type(typeIn),
+ : typeInfo(gl::GetUniformTypeInfo(type)),
name(nameIn),
- arraySize(arraySizeIn),
- data(nullptr),
- dirty(true),
+ arraySizes(arraySizesIn),
+ vsData(nullptr),
+ psData(nullptr),
+ csData(nullptr),
vsRegisterIndex(GL_INVALID_INDEX),
psRegisterIndex(GL_INVALID_INDEX),
+ csRegisterIndex(GL_INVALID_INDEX),
registerCount(0),
registerElement(0)
{
@@ -350,23 +315,36 @@ D3DUniform::D3DUniform(GLenum typeIn,
// Uniform blocks/buffers are treated separately by the Renderer (ES3 path only)
if (defaultBlock)
{
- size_t bytes = gl::VariableInternalSize(type) * elementCount();
- data = new uint8_t[bytes];
- memset(data, 0, bytes);
-
- // TODO(jmadill): is this correct with non-square matrices?
- registerCount = gl::VariableRowCount(type) * elementCount();
+ // Use the row count as register count, will work for non-square matrices.
+ registerCount = typeInfo.rowCount * getArraySizeProduct();
}
}
D3DUniform::~D3DUniform()
{
- SafeDeleteArray(data);
+}
+
+unsigned int D3DUniform::getArraySizeProduct() const
+{
+ return gl::ArraySizeProduct(arraySizes);
+}
+
+const uint8_t *D3DUniform::getDataPtrToElement(size_t elementIndex) const
+{
+ ASSERT((!isArray() && elementIndex == 0) ||
+ (isArray() && elementIndex < getArraySizeProduct()));
+
+ if (isSampler())
+ {
+ return reinterpret_cast<const uint8_t *>(&mSamplerData[elementIndex]);
+ }
+
+ return firstNonNullData() + (elementIndex > 0 ? (typeInfo.internalSize * elementIndex) : 0u);
}
bool D3DUniform::isSampler() const
{
- return gl::IsSamplerType(type);
+ return typeInfo.isSampler;
}
bool D3DUniform::isReferencedByVertexShader() const
@@ -379,6 +357,23 @@ bool D3DUniform::isReferencedByFragmentShader() const
return psRegisterIndex != GL_INVALID_INDEX;
}
+bool D3DUniform::isReferencedByComputeShader() const
+{
+ return csRegisterIndex != GL_INVALID_INDEX;
+}
+
+const uint8_t *D3DUniform::firstNonNullData() const
+{
+ ASSERT(vsData || psData || csData || !mSamplerData.empty());
+
+ if (!mSamplerData.empty())
+ {
+ return reinterpret_cast<const uint8_t *>(mSamplerData.data());
+ }
+
+ return vsData ? vsData : (psData ? psData : csData);
+}
+
// D3DVarying Implementation
D3DVarying::D3DVarying() : semanticIndex(0), componentCount(0), outputSlot(0)
@@ -398,16 +393,17 @@ D3DVarying::D3DVarying(const std::string &semanticNameIn,
// ProgramD3DMetadata Implementation
-ProgramD3DMetadata::ProgramD3DMetadata(int rendererMajorShaderModel,
- const std::string &shaderModelSuffix,
- bool usesInstancedPointSpriteEmulation,
- bool usesViewScale,
+ProgramD3DMetadata::ProgramD3DMetadata(RendererD3D *renderer,
const ShaderD3D *vertexShader,
const ShaderD3D *fragmentShader)
- : mRendererMajorShaderModel(rendererMajorShaderModel),
- mShaderModelSuffix(shaderModelSuffix),
- mUsesInstancedPointSpriteEmulation(usesInstancedPointSpriteEmulation),
- mUsesViewScale(usesViewScale),
+ : mRendererMajorShaderModel(renderer->getMajorShaderModel()),
+ mShaderModelSuffix(renderer->getShaderModelSuffix()),
+ mUsesInstancedPointSpriteEmulation(
+ renderer->getWorkarounds().useInstancedPointSpriteEmulation),
+ mUsesViewScale(renderer->presentPathFastEnabled()),
+ mHasANGLEMultiviewEnabled(vertexShader->hasANGLEMultiviewEnabled()),
+ mUsesViewID(fragmentShader->usesViewID()),
+ mCanSelectViewInVertexShader(renderer->canSelectViewInVertexShader()),
mVertexShader(vertexShader),
mFragmentShader(fragmentShader)
{
@@ -418,12 +414,13 @@ int ProgramD3DMetadata::getRendererMajorShaderModel() const
return mRendererMajorShaderModel;
}
-bool ProgramD3DMetadata::usesBroadcast(const gl::Data &data) const
+bool ProgramD3DMetadata::usesBroadcast(const gl::ContextState &data) const
{
- return (mFragmentShader->usesFragColor() && data.clientVersion < 3);
+ return (mFragmentShader->usesFragColor() && mFragmentShader->usesMultipleRenderTargets() &&
+ data.getClientMajorVersion() < 3);
}
-bool ProgramD3DMetadata::usesFragDepth(const gl::Program::Data &programData) const
+bool ProgramD3DMetadata::usesFragDepth() const
{
return mFragmentShader->usesFragDepth();
}
@@ -445,7 +442,8 @@ bool ProgramD3DMetadata::usesPointSize() const
bool ProgramD3DMetadata::usesInsertedPointCoordValue() const
{
- return !usesPointSize() && usesPointCoord() && mRendererMajorShaderModel >= 4;
+ return (!usesPointSize() || !mUsesInstancedPointSpriteEmulation) && usesPointCoord() &&
+ mRendererMajorShaderModel >= 4;
}
bool ProgramD3DMetadata::usesViewScale() const
@@ -453,15 +451,29 @@ bool ProgramD3DMetadata::usesViewScale() const
return mUsesViewScale;
}
+bool ProgramD3DMetadata::hasANGLEMultiviewEnabled() const
+{
+ return mHasANGLEMultiviewEnabled;
+}
+
+bool ProgramD3DMetadata::usesViewID() const
+{
+ return mUsesViewID;
+}
+
+bool ProgramD3DMetadata::canSelectViewInVertexShader() const
+{
+ return mCanSelectViewInVertexShader;
+}
+
bool ProgramD3DMetadata::addsPointCoordToVertexShader() const
{
- // Instanced PointSprite emulation requires that gl_PointCoord is present in the vertex shader
+ // PointSprite emulation requiress that gl_PointCoord is present in the vertex shader
// VS_OUTPUT structure to ensure compatibility with the generated PS_INPUT of the pixel shader.
- // GeometryShader PointSprite emulation does not require this additional entry because the
- // GS_OUTPUT of the Geometry shader contains the pointCoord value and already matches the
- // PS_INPUT of the generated pixel shader. The Geometry Shader point sprite implementation needs
- // gl_PointSize to be in VS_OUTPUT and GS_INPUT. Instanced point sprites doesn't need
- // gl_PointSize in VS_OUTPUT.
+ // Even with a geometry shader, the app can render triangles or lines and reference
+ // gl_PointCoord in the fragment shader, requiring us to provide a dummy value. For
+ // simplicity, we always add this to the vertex shader when the fragment shader
+ // references gl_PointCoord, even if we could skip it in the geometry shader.
return (mUsesInstancedPointSpriteEmulation && usesPointCoord()) ||
usesInsertedPointCoordValue();
}
@@ -509,24 +521,44 @@ ProgramD3D::VertexExecutable::~VertexExecutable()
}
// static
+ProgramD3D::VertexExecutable::HLSLAttribType ProgramD3D::VertexExecutable::GetAttribType(
+ GLenum type)
+{
+ switch (type)
+ {
+ case GL_INT:
+ return HLSLAttribType::SIGNED_INT;
+ case GL_UNSIGNED_INT:
+ return HLSLAttribType::UNSIGNED_INT;
+ case GL_SIGNED_NORMALIZED:
+ case GL_UNSIGNED_NORMALIZED:
+ case GL_FLOAT:
+ return HLSLAttribType::FLOAT;
+ default:
+ UNREACHABLE();
+ return HLSLAttribType::FLOAT;
+ }
+}
+
+// static
void ProgramD3D::VertexExecutable::getSignature(RendererD3D *renderer,
const gl::InputLayout &inputLayout,
Signature *signatureOut)
{
- signatureOut->resize(inputLayout.size());
+ signatureOut->assign(inputLayout.size(), HLSLAttribType::FLOAT);
for (size_t index = 0; index < inputLayout.size(); ++index)
{
gl::VertexFormatType vertexFormatType = inputLayout[index];
- bool converted = false;
- if (vertexFormatType != gl::VERTEX_FORMAT_INVALID)
- {
- VertexConversionType conversionType =
- renderer->getVertexConversionType(vertexFormatType);
- converted = ((conversionType & VERTEX_CONVERT_GPU) != 0);
- }
+ if (vertexFormatType == gl::VERTEX_FORMAT_INVALID)
+ continue;
+
+ VertexConversionType conversionType = renderer->getVertexConversionType(vertexFormatType);
+ if ((conversionType & VERTEX_CONVERT_GPU) == 0)
+ continue;
- (*signatureOut)[index] = converted;
+ GLenum componentType = renderer->getVertexComponentType(vertexFormatType);
+ (*signatureOut)[index] = GetAttribType(componentType);
}
}
@@ -535,9 +567,9 @@ bool ProgramD3D::VertexExecutable::matchesSignature(const Signature &signature)
size_t limit = std::max(mSignature.size(), signature.size());
for (size_t index = 0; index < limit; ++index)
{
- // treat undefined indexes as 'not converted'
- bool a = index < signature.size() ? signature[index] : false;
- bool b = index < mSignature.size() ? mSignature[index] : false;
+ // treat undefined indexes as FLOAT
+ auto a = index < signature.size() ? signature[index] : HLSLAttribType::FLOAT;
+ auto b = index < mSignature.size() ? mSignature[index] : HLSLAttribType::FLOAT;
if (a != b)
return false;
}
@@ -562,19 +594,25 @@ ProgramD3D::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureTy
unsigned int ProgramD3D::mCurrentSerial = 1;
-ProgramD3D::ProgramD3D(const gl::Program::Data &data, RendererD3D *renderer)
- : ProgramImpl(data),
+ProgramD3D::ProgramD3D(const gl::ProgramState &state, RendererD3D *renderer)
+ : ProgramImpl(state),
mRenderer(renderer),
- mDynamicHLSL(NULL),
- mGeometryExecutables(gl::PRIMITIVE_TYPE_MAX, nullptr),
+ mDynamicHLSL(nullptr),
+ mGeometryExecutables(gl::PRIMITIVE_TYPE_MAX),
+ mComputeExecutable(nullptr),
mUsesPointSize(false),
mUsesFlatInterpolation(false),
- mVertexUniformStorage(NULL),
- mFragmentUniformStorage(NULL),
+ mVertexUniformStorage(nullptr),
+ mFragmentUniformStorage(nullptr),
+ mComputeUniformStorage(nullptr),
mUsedVertexSamplerRange(0),
mUsedPixelSamplerRange(0),
+ mUsedComputeSamplerRange(0),
mDirtySamplerMapping(true),
- mSerial(issueSerial())
+ mSerial(issueSerial()),
+ mVertexUniformsDirty(true),
+ mFragmentUniformsDirty(true),
+ mComputeUniformsDirty(true)
{
mDynamicHLSL = new DynamicHLSL(renderer);
}
@@ -590,14 +628,22 @@ bool ProgramD3D::usesPointSpriteEmulation() const
return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
}
+bool ProgramD3D::usesGeometryShaderForPointSpriteEmulation() const
+{
+ return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation();
+}
+
bool ProgramD3D::usesGeometryShader(GLenum drawMode) const
{
+ if (mHasANGLEMultiviewEnabled && !mRenderer->canSelectViewInVertexShader())
+ {
+ return true;
+ }
if (drawMode != GL_POINTS)
{
return mUsesFlatInterpolation;
}
-
- return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation();
+ return usesGeometryShaderForPointSpriteEmulation();
}
bool ProgramD3D::usesInstancedPointSpriteEmulation() const
@@ -627,6 +673,13 @@ GLint ProgramD3D::getSamplerMapping(gl::SamplerType type,
logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
}
break;
+ case gl::SAMPLER_COMPUTE:
+ ASSERT(samplerIndex < caps.maxComputeTextureImageUnits);
+ if (samplerIndex < mSamplersCS.size() && mSamplersCS[samplerIndex].active)
+ {
+ logicalTextureUnit = mSamplersCS[samplerIndex].logicalTextureUnit;
+ }
+ break;
default:
UNREACHABLE();
}
@@ -654,6 +707,10 @@ GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samp
ASSERT(samplerIndex < mSamplersVS.size());
ASSERT(mSamplersVS[samplerIndex].active);
return mSamplersVS[samplerIndex].textureType;
+ case gl::SAMPLER_COMPUTE:
+ ASSERT(samplerIndex < mSamplersCS.size());
+ ASSERT(mSamplersCS[samplerIndex].active);
+ return mSamplersCS[samplerIndex].textureType;
default:
UNREACHABLE();
}
@@ -661,7 +718,7 @@ GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samp
return GL_TEXTURE_2D;
}
-GLint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const
+GLuint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const
{
switch (type)
{
@@ -669,17 +726,19 @@ GLint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const
return mUsedPixelSamplerRange;
case gl::SAMPLER_VERTEX:
return mUsedVertexSamplerRange;
+ case gl::SAMPLER_COMPUTE:
+ return mUsedComputeSamplerRange;
default:
UNREACHABLE();
- return 0;
+ return 0u;
}
}
-void ProgramD3D::updateSamplerMapping()
+ProgramD3D::SamplerMapping ProgramD3D::updateSamplerMapping()
{
if (!mDirtySamplerMapping)
{
- return;
+ return SamplerMapping::WasClean;
}
mDirtySamplerMapping = false;
@@ -687,14 +746,10 @@ void ProgramD3D::updateSamplerMapping()
// Retrieve sampler uniform values
for (const D3DUniform *d3dUniform : mD3DUniforms)
{
- if (!d3dUniform->dirty)
- continue;
-
if (!d3dUniform->isSampler())
continue;
- int count = d3dUniform->elementCount();
- const GLint(*v)[4] = reinterpret_cast<const GLint(*)[4]>(d3dUniform->data);
+ int count = d3dUniform->getArraySizeProduct();
if (d3dUniform->isReferencedByFragmentShader())
{
@@ -707,7 +762,7 @@ void ProgramD3D::updateSamplerMapping()
if (samplerIndex < mSamplersPS.size())
{
ASSERT(mSamplersPS[samplerIndex].active);
- mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0];
+ mSamplersPS[samplerIndex].logicalTextureUnit = d3dUniform->mSamplerData[i];
}
}
}
@@ -723,15 +778,37 @@ void ProgramD3D::updateSamplerMapping()
if (samplerIndex < mSamplersVS.size())
{
ASSERT(mSamplersVS[samplerIndex].active);
- mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0];
+ mSamplersVS[samplerIndex].logicalTextureUnit = d3dUniform->mSamplerData[i];
+ }
+ }
+ }
+
+ if (d3dUniform->isReferencedByComputeShader())
+ {
+ unsigned int firstIndex = d3dUniform->csRegisterIndex;
+
+ for (int i = 0; i < count; i++)
+ {
+ unsigned int samplerIndex = firstIndex + i;
+
+ if (samplerIndex < mSamplersCS.size())
+ {
+ ASSERT(mSamplersCS[samplerIndex].active);
+ mSamplersCS[samplerIndex].logicalTextureUnit = d3dUniform->mSamplerData[i];
}
}
}
}
+
+ return SamplerMapping::WasDirty;
}
-LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
+gl::LinkResult ProgramD3D::load(const gl::Context *context,
+ gl::InfoLog &infoLog,
+ gl::BinaryInputStream *stream)
{
+ // TODO(jmadill): Use Renderer from contextImpl.
+
reset();
DeviceIdentifier binaryDeviceIdentifier = {0};
@@ -742,20 +819,19 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0)
{
infoLog << "Invalid program binary, device configuration has changed.";
- return LinkResult(false, gl::Error(GL_NO_ERROR));
+ return false;
}
int compileFlags = stream->readInt<int>();
if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
{
infoLog << "Mismatched compilation flags.";
- return LinkResult(false, gl::Error(GL_NO_ERROR));
+ return false;
}
- // TODO(jmadill): replace MAX_VERTEX_ATTRIBS
- for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i)
+ for (int &index : mAttribLocationToD3DSemantic)
{
- stream->readInt(&mSemanticIndexes[i]);
+ stream->readInt(&index);
}
const unsigned int psSamplerCount = stream->readInt<unsigned int>();
@@ -777,27 +853,39 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
mSamplersVS.push_back(sampler);
}
+ const unsigned int csSamplerCount = stream->readInt<unsigned int>();
+ for (unsigned int i = 0; i < csSamplerCount; ++i)
+ {
+ Sampler sampler;
+ stream->readBool(&sampler.active);
+ stream->readInt(&sampler.logicalTextureUnit);
+ stream->readInt(&sampler.textureType);
+ mSamplersCS.push_back(sampler);
+ }
+
stream->readInt(&mUsedVertexSamplerRange);
stream->readInt(&mUsedPixelSamplerRange);
+ stream->readInt(&mUsedComputeSamplerRange);
const unsigned int uniformCount = stream->readInt<unsigned int>();
if (stream->error())
{
infoLog << "Invalid program binary.";
- return LinkResult(false, gl::Error(GL_NO_ERROR));
+ return false;
}
- const auto &linkedUniforms = mData.getUniforms();
+ const auto &linkedUniforms = mState.getUniforms();
ASSERT(mD3DUniforms.empty());
for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
{
const gl::LinkedUniform &linkedUniform = linkedUniforms[uniformIndex];
D3DUniform *d3dUniform =
- new D3DUniform(linkedUniform.type, linkedUniform.name, linkedUniform.arraySize,
+ new D3DUniform(linkedUniform.type, linkedUniform.name, linkedUniform.arraySizes,
linkedUniform.isInDefaultBlock());
stream->readInt(&d3dUniform->psRegisterIndex);
stream->readInt(&d3dUniform->vsRegisterIndex);
+ stream->readInt(&d3dUniform->csRegisterIndex);
stream->readInt(&d3dUniform->registerCount);
stream->readInt(&d3dUniform->registerElement);
@@ -808,7 +896,7 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
if (stream->error())
{
infoLog << "Invalid program binary.";
- return LinkResult(false, gl::Error(GL_NO_ERROR));
+ return false;
}
ASSERT(mD3DUniformBlocks.empty());
@@ -817,6 +905,7 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
D3DUniformBlock uniformBlock;
stream->readInt(&uniformBlock.psRegisterIndex);
stream->readInt(&uniformBlock.vsRegisterIndex);
+ stream->readInt(&uniformBlock.csRegisterIndex);
mD3DUniformBlocks.push_back(uniformBlock);
}
@@ -834,11 +923,13 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
stream->readString(&mVertexHLSL);
stream->readBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds),
- sizeof(D3DCompilerWorkarounds));
+ sizeof(angle::CompilerWorkaroundsD3D));
stream->readString(&mPixelHLSL);
stream->readBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds),
- sizeof(D3DCompilerWorkarounds));
+ sizeof(angle::CompilerWorkaroundsD3D));
stream->readBool(&mUsesFragDepth);
+ stream->readBool(&mHasANGLEMultiviewEnabled);
+ stream->readBool(&mUsesViewID);
stream->readBool(&mUsesPointSize);
stream->readBool(&mUsesFlatInterpolation);
@@ -857,6 +948,8 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
const unsigned char *binary = reinterpret_cast<const unsigned char *>(stream->data());
+ bool separateAttribs = (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS);
+
const unsigned int vertexShaderCount = stream->readInt<unsigned int>();
for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount;
vertexShaderIndex++)
@@ -874,18 +967,14 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
ShaderExecutableD3D *shaderExecutable = nullptr;
- gl::Error error = mRenderer->loadExecutable(
- vertexShaderFunction, vertexShaderSize, SHADER_VERTEX, mStreamOutVaryings,
- (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable);
- if (error.isError())
- {
- return LinkResult(false, error);
- }
+ ANGLE_TRY(mRenderer->loadExecutable(vertexShaderFunction, vertexShaderSize,
+ gl::SHADER_VERTEX, mStreamOutVaryings, separateAttribs,
+ &shaderExecutable));
if (!shaderExecutable)
{
infoLog << "Could not create vertex shader.";
- return LinkResult(false, gl::Error(GL_NO_ERROR));
+ return false;
}
// generated converted input layout
@@ -893,8 +982,8 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
VertexExecutable::getSignature(mRenderer, inputLayout, &signature);
// add new binary
- mVertexExecutables.push_back(
- new VertexExecutable(inputLayout, signature, shaderExecutable));
+ mVertexExecutables.push_back(std::unique_ptr<VertexExecutable>(
+ new VertexExecutable(inputLayout, signature, shaderExecutable)));
stream->skip(vertexShaderSize);
}
@@ -913,22 +1002,19 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
const unsigned char *pixelShaderFunction = binary + stream->offset();
ShaderExecutableD3D *shaderExecutable = nullptr;
- gl::Error error = mRenderer->loadExecutable(
- pixelShaderFunction, pixelShaderSize, SHADER_PIXEL, mStreamOutVaryings,
- (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable);
- if (error.isError())
- {
- return LinkResult(false, error);
- }
+ ANGLE_TRY(mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize,
+ gl::SHADER_FRAGMENT, mStreamOutVaryings,
+ separateAttribs, &shaderExecutable));
if (!shaderExecutable)
{
infoLog << "Could not create pixel shader.";
- return LinkResult(false, gl::Error(GL_NO_ERROR));
+ return false;
}
// add new binary
- mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable));
+ mPixelExecutables.push_back(
+ std::unique_ptr<PixelExecutable>(new PixelExecutable(outputs, shaderExecutable)));
stream->skip(pixelShaderSize);
}
@@ -939,36 +1025,52 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
unsigned int geometryShaderSize = stream->readInt<unsigned int>();
if (geometryShaderSize == 0)
{
- mGeometryExecutables[geometryExeIndex] = nullptr;
continue;
}
const unsigned char *geometryShaderFunction = binary + stream->offset();
- bool splitAttribs = (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS);
- gl::Error error = mRenderer->loadExecutable(
- geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY, mStreamOutVaryings,
- splitAttribs, &mGeometryExecutables[geometryExeIndex]);
- if (error.isError())
- {
- return LinkResult(false, error);
- }
+ ShaderExecutableD3D *geometryExecutable = nullptr;
+ ANGLE_TRY(mRenderer->loadExecutable(geometryShaderFunction, geometryShaderSize,
+ gl::SHADER_GEOMETRY, mStreamOutVaryings,
+ separateAttribs, &geometryExecutable));
- if (!mGeometryExecutables[geometryExeIndex])
+ if (!geometryExecutable)
{
infoLog << "Could not create geometry shader.";
- return LinkResult(false, gl::Error(GL_NO_ERROR));
+ return false;
}
+
+ mGeometryExecutables[geometryExeIndex].reset(geometryExecutable);
+
stream->skip(geometryShaderSize);
}
+ unsigned int computeShaderSize = stream->readInt<unsigned int>();
+ if (computeShaderSize > 0)
+ {
+ const unsigned char *computeShaderFunction = binary + stream->offset();
+
+ ShaderExecutableD3D *computeExecutable = nullptr;
+ ANGLE_TRY(mRenderer->loadExecutable(computeShaderFunction, computeShaderSize,
+ gl::SHADER_COMPUTE, std::vector<D3DVarying>(), false,
+ &computeExecutable));
+
+ if (!computeExecutable)
+ {
+ infoLog << "Could not create compute shader.";
+ return false;
+ }
+
+ mComputeExecutable.reset(computeExecutable);
+ }
+
initializeUniformStorage();
- initAttributesByLayout();
- return LinkResult(true, gl::Error(GL_NO_ERROR));
+ return true;
}
-gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
+void ProgramD3D::save(const gl::Context *context, gl::BinaryOutputStream *stream)
{
// Output the DeviceIdentifier before we output any shader code
// When we load the binary again later, we can validate the device identifier before trying to
@@ -979,10 +1081,9 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
- // TODO(jmadill): replace MAX_VERTEX_ATTRIBS
- for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i)
+ for (int d3dSemantic : mAttribLocationToD3DSemantic)
{
- stream->writeInt(mSemanticIndexes[i]);
+ stream->writeInt(d3dSemantic);
}
stream->writeInt(mSamplersPS.size());
@@ -1001,15 +1102,25 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
stream->writeInt(mSamplersVS[i].textureType);
}
+ stream->writeInt(mSamplersCS.size());
+ for (unsigned int i = 0; i < mSamplersCS.size(); ++i)
+ {
+ stream->writeInt(mSamplersCS[i].active);
+ stream->writeInt(mSamplersCS[i].logicalTextureUnit);
+ stream->writeInt(mSamplersCS[i].textureType);
+ }
+
stream->writeInt(mUsedVertexSamplerRange);
stream->writeInt(mUsedPixelSamplerRange);
+ stream->writeInt(mUsedComputeSamplerRange);
stream->writeInt(mD3DUniforms.size());
for (const D3DUniform *uniform : mD3DUniforms)
{
// Type, name and arraySize are redundant, so aren't stored in the binary.
- stream->writeInt(uniform->psRegisterIndex);
- stream->writeInt(uniform->vsRegisterIndex);
+ stream->writeIntOrNegOne(uniform->psRegisterIndex);
+ stream->writeIntOrNegOne(uniform->vsRegisterIndex);
+ stream->writeIntOrNegOne(uniform->csRegisterIndex);
stream->writeInt(uniform->registerCount);
stream->writeInt(uniform->registerElement);
}
@@ -1017,8 +1128,9 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
stream->writeInt(mD3DUniformBlocks.size());
for (const D3DUniformBlock &uniformBlock : mD3DUniformBlocks)
{
- stream->writeInt(uniformBlock.psRegisterIndex);
- stream->writeInt(uniformBlock.vsRegisterIndex);
+ stream->writeIntOrNegOne(uniformBlock.psRegisterIndex);
+ stream->writeIntOrNegOne(uniformBlock.vsRegisterIndex);
+ stream->writeIntOrNegOne(uniformBlock.csRegisterIndex);
}
stream->writeInt(mStreamOutVaryings.size());
@@ -1032,11 +1144,13 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
stream->writeString(mVertexHLSL);
stream->writeBytes(reinterpret_cast<unsigned char *>(&mVertexWorkarounds),
- sizeof(D3DCompilerWorkarounds));
+ sizeof(angle::CompilerWorkaroundsD3D));
stream->writeString(mPixelHLSL);
stream->writeBytes(reinterpret_cast<unsigned char *>(&mPixelWorkarounds),
- sizeof(D3DCompilerWorkarounds));
+ sizeof(angle::CompilerWorkaroundsD3D));
stream->writeInt(mUsesFragDepth);
+ stream->writeInt(mHasANGLEMultiviewEnabled);
+ stream->writeInt(mUsesViewID);
stream->writeInt(mUsesPointSize);
stream->writeInt(mUsesFlatInterpolation);
@@ -1058,14 +1172,14 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size();
vertexExecutableIndex++)
{
- VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex];
+ VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex].get();
const auto &inputLayout = vertexExecutable->inputs();
stream->writeInt(inputLayout.size());
for (size_t inputIndex = 0; inputIndex < inputLayout.size(); inputIndex++)
{
- stream->writeInt(inputLayout[inputIndex]);
+ stream->writeInt(static_cast<unsigned int>(inputLayout[inputIndex]));
}
size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
@@ -1079,7 +1193,7 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size();
pixelExecutableIndex++)
{
- PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex];
+ PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex].get();
const std::vector<GLenum> outputs = pixelExecutable->outputSignature();
stream->writeInt(outputs.size());
@@ -1095,150 +1209,120 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
stream->writeBytes(pixelBlob, pixelShaderSize);
}
- for (const ShaderExecutableD3D *geometryExe : mGeometryExecutables)
+ for (auto const &geometryExecutable : mGeometryExecutables)
{
- if (geometryExe == nullptr)
+ if (!geometryExecutable)
{
stream->writeInt(0);
continue;
}
- size_t geometryShaderSize = geometryExe->getLength();
+ size_t geometryShaderSize = geometryExecutable->getLength();
stream->writeInt(geometryShaderSize);
- stream->writeBytes(geometryExe->getFunction(), geometryShaderSize);
+ stream->writeBytes(geometryExecutable->getFunction(), geometryShaderSize);
}
- return gl::Error(GL_NO_ERROR);
+ if (mComputeExecutable)
+ {
+ size_t computeShaderSize = mComputeExecutable->getLength();
+ stream->writeInt(computeShaderSize);
+ stream->writeBytes(mComputeExecutable->getFunction(), computeShaderSize);
+ }
+ else
+ {
+ stream->writeInt(0);
+ }
}
void ProgramD3D::setBinaryRetrievableHint(bool /* retrievable */)
{
}
-gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo,
- ShaderExecutableD3D **outExecutable)
+void ProgramD3D::setSeparable(bool /* separable */)
{
- mPixelShaderOutputFormatCache.clear();
-
- const FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(fbo);
- const gl::AttachmentList &colorbuffers = fboD3D->getColorAttachmentsForRender();
-
- for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
- {
- const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
-
- if (colorbuffer)
- {
- mPixelShaderOutputFormatCache.push_back(colorbuffer->getBinding() == GL_BACK
- ? GL_COLOR_ATTACHMENT0
- : colorbuffer->getBinding());
- }
- else
- {
- mPixelShaderOutputFormatCache.push_back(GL_NONE);
- }
- }
-
- return getPixelExecutableForOutputLayout(mPixelShaderOutputFormatCache, outExecutable, nullptr);
}
-gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature,
- ShaderExecutableD3D **outExectuable,
- gl::InfoLog *infoLog)
+gl::Error ProgramD3D::getPixelExecutableForCachedOutputLayout(ShaderExecutableD3D **outExecutable,
+ gl::InfoLog *infoLog)
{
- for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
+ if (mCachedPixelExecutableIndex.valid())
{
- if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature))
- {
- *outExectuable = mPixelExecutables[executableIndex]->shaderExecutable();
- return gl::Error(GL_NO_ERROR);
- }
+ *outExecutable = mPixelExecutables[mCachedPixelExecutableIndex.value()]->shaderExecutable();
+ return gl::NoError();
}
std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(
- mPixelHLSL, mPixelShaderKey, mUsesFragDepth, outputSignature);
+ mPixelHLSL, mPixelShaderKey, mUsesFragDepth, mPixelShaderOutputLayoutCache);
// Generate new pixel executable
- ShaderExecutableD3D *pixelExecutable = NULL;
+ ShaderExecutableD3D *pixelExecutable = nullptr;
gl::InfoLog tempInfoLog;
gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
- gl::Error error = mRenderer->compileToExecutable(
- *currentInfoLog, finalPixelHLSL, SHADER_PIXEL, mStreamOutVaryings,
- (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mPixelWorkarounds,
- &pixelExecutable);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mRenderer->compileToExecutable(
+ *currentInfoLog, finalPixelHLSL, gl::SHADER_FRAGMENT, mStreamOutVaryings,
+ (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mPixelWorkarounds,
+ &pixelExecutable));
if (pixelExecutable)
{
- mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable));
+ mPixelExecutables.push_back(std::unique_ptr<PixelExecutable>(
+ new PixelExecutable(mPixelShaderOutputLayoutCache, pixelExecutable)));
+ mCachedPixelExecutableIndex = mPixelExecutables.size() - 1;
}
else if (!infoLog)
{
- std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
- tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
- ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]);
+ ERR() << "Error compiling dynamic pixel executable:" << std::endl
+ << tempInfoLog.str() << std::endl;
}
- *outExectuable = pixelExecutable;
- return gl::Error(GL_NO_ERROR);
+ *outExecutable = pixelExecutable;
+ return gl::NoError();
}
-gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout,
- ShaderExecutableD3D **outExectuable,
- gl::InfoLog *infoLog)
+gl::Error ProgramD3D::getVertexExecutableForCachedInputLayout(ShaderExecutableD3D **outExectuable,
+ gl::InfoLog *infoLog)
{
- VertexExecutable::getSignature(mRenderer, inputLayout, &mCachedVertexSignature);
-
- for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
+ if (mCachedVertexExecutableIndex.valid())
{
- if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
- {
- *outExectuable = mVertexExecutables[executableIndex]->shaderExecutable();
- return gl::Error(GL_NO_ERROR);
- }
+ *outExectuable =
+ mVertexExecutables[mCachedVertexExecutableIndex.value()]->shaderExecutable();
+ return gl::NoError();
}
// Generate new dynamic layout with attribute conversions
std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(
- mVertexHLSL, inputLayout, mData.getAttributes());
+ mVertexHLSL, mCachedInputLayout, mState.getAttributes());
// Generate new vertex executable
- ShaderExecutableD3D *vertexExecutable = NULL;
+ ShaderExecutableD3D *vertexExecutable = nullptr;
gl::InfoLog tempInfoLog;
gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
- gl::Error error = mRenderer->compileToExecutable(
- *currentInfoLog, finalVertexHLSL, SHADER_VERTEX, mStreamOutVaryings,
- (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mVertexWorkarounds,
- &vertexExecutable);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mRenderer->compileToExecutable(
+ *currentInfoLog, finalVertexHLSL, gl::SHADER_VERTEX, mStreamOutVaryings,
+ (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mVertexWorkarounds,
+ &vertexExecutable));
if (vertexExecutable)
{
- mVertexExecutables.push_back(
- new VertexExecutable(inputLayout, mCachedVertexSignature, vertexExecutable));
+ mVertexExecutables.push_back(std::unique_ptr<VertexExecutable>(
+ new VertexExecutable(mCachedInputLayout, mCachedVertexSignature, vertexExecutable)));
+ mCachedVertexExecutableIndex = mVertexExecutables.size() - 1;
}
else if (!infoLog)
{
- std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
- tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
- ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]);
+ ERR() << "Error compiling dynamic vertex executable:" << std::endl
+ << tempInfoLog.str() << std::endl;
}
*outExectuable = vertexExecutable;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::Data &data,
+gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::Context *context,
GLenum drawMode,
ShaderExecutableD3D **outExecutable,
gl::InfoLog *infoLog)
@@ -1251,75 +1335,188 @@ gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::Data &data
// Return a null shader if the current rendering doesn't use a geometry shader
if (!usesGeometryShader(drawMode))
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::PrimitiveType geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
- if (mGeometryExecutables[geometryShaderType] != nullptr)
+ if (mGeometryExecutables[geometryShaderType])
{
if (outExecutable)
{
- *outExecutable = mGeometryExecutables[geometryShaderType];
+ *outExecutable = mGeometryExecutables[geometryShaderType].get();
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(
- geometryShaderType, data, mData, mRenderer->presentPathFastEnabled(),
- mGeometryShaderPreamble);
+ context, geometryShaderType, mState, mRenderer->presentPathFastEnabled(),
+ mHasANGLEMultiviewEnabled, mRenderer->canSelectViewInVertexShader(),
+ usesGeometryShaderForPointSpriteEmulation(), mGeometryShaderPreamble);
gl::InfoLog tempInfoLog;
gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
- gl::Error error = mRenderer->compileToExecutable(
- *currentInfoLog, geometryHLSL, SHADER_GEOMETRY, mStreamOutVaryings,
- (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), D3DCompilerWorkarounds(),
- &mGeometryExecutables[geometryShaderType]);
+ ShaderExecutableD3D *geometryExecutable = nullptr;
+ gl::Error error = mRenderer->compileToExecutable(
+ *currentInfoLog, geometryHLSL, gl::SHADER_GEOMETRY, mStreamOutVaryings,
+ (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
+ angle::CompilerWorkaroundsD3D(), &geometryExecutable);
if (!infoLog && error.isError())
{
- std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
- tempInfoLog.getLog(static_cast<GLsizei>(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]);
- ERR("Error compiling dynamic geometry executable:\n%s\n", &tempCharBuffer[0]);
+ ERR() << "Error compiling dynamic geometry executable:" << std::endl
+ << tempInfoLog.str() << std::endl;
+ }
+
+ if (geometryExecutable != nullptr)
+ {
+ mGeometryExecutables[geometryShaderType].reset(geometryExecutable);
}
if (outExecutable)
{
- *outExecutable = mGeometryExecutables[geometryShaderType];
+ *outExecutable = mGeometryExecutables[geometryShaderType].get();
}
return error;
}
-LinkResult ProgramD3D::compileProgramExecutables(const gl::Data &data, gl::InfoLog &infoLog)
+class ProgramD3D::GetExecutableTask : public Closure
+{
+ public:
+ GetExecutableTask(ProgramD3D *program)
+ : mProgram(program), mError(gl::NoError()), mInfoLog(), mResult(nullptr)
+ {
+ }
+
+ virtual gl::Error run() = 0;
+
+ void operator()() override { mError = run(); }
+
+ const gl::Error &getError() const { return mError; }
+ const gl::InfoLog &getInfoLog() const { return mInfoLog; }
+ ShaderExecutableD3D *getResult() { return mResult; }
+
+ protected:
+ ProgramD3D *mProgram;
+ gl::Error mError;
+ gl::InfoLog mInfoLog;
+ ShaderExecutableD3D *mResult;
+};
+
+class ProgramD3D::GetVertexExecutableTask : public ProgramD3D::GetExecutableTask
+{
+ public:
+ GetVertexExecutableTask(ProgramD3D *program, const gl::Context *context)
+ : GetExecutableTask(program), mContext(context)
+ {
+ }
+ gl::Error run() override
+ {
+ mProgram->updateCachedInputLayoutFromShader(mContext);
+
+ ANGLE_TRY(mProgram->getVertexExecutableForCachedInputLayout(&mResult, &mInfoLog));
+
+ return gl::NoError();
+ }
+
+ private:
+ const gl::Context *mContext;
+};
+
+void ProgramD3D::updateCachedInputLayoutFromShader(const gl::Context *context)
+{
+ GetDefaultInputLayoutFromShader(context, mState.getAttachedVertexShader(), &mCachedInputLayout);
+ VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature);
+ updateCachedVertexExecutableIndex();
+}
+
+class ProgramD3D::GetPixelExecutableTask : public ProgramD3D::GetExecutableTask
+{
+ public:
+ GetPixelExecutableTask(ProgramD3D *program) : GetExecutableTask(program) {}
+ gl::Error run() override
+ {
+ mProgram->updateCachedOutputLayoutFromShader();
+
+ ANGLE_TRY(mProgram->getPixelExecutableForCachedOutputLayout(&mResult, &mInfoLog));
+
+ return gl::NoError();
+ }
+};
+
+void ProgramD3D::updateCachedOutputLayoutFromShader()
+{
+ GetDefaultOutputLayoutFromShader(mPixelShaderKey, &mPixelShaderOutputLayoutCache);
+ updateCachedPixelExecutableIndex();
+}
+
+class ProgramD3D::GetGeometryExecutableTask : public ProgramD3D::GetExecutableTask
{
- const gl::InputLayout &defaultInputLayout =
- GetDefaultInputLayoutFromShader(mData.getAttachedVertexShader());
- ShaderExecutableD3D *defaultVertexExecutable = NULL;
- gl::Error error =
- getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable, &infoLog);
- if (error.isError())
+ public:
+ GetGeometryExecutableTask(ProgramD3D *program, const gl::Context *context)
+ : GetExecutableTask(program), mContext(context)
{
- return LinkResult(false, error);
}
- std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey());
- ShaderExecutableD3D *defaultPixelExecutable = NULL;
- error =
- getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable, &infoLog);
- if (error.isError())
+ gl::Error run() override
{
- return LinkResult(false, error);
+ // Auto-generate the geometry shader here, if we expect to be using point rendering in
+ // D3D11.
+ if (mProgram->usesGeometryShader(GL_POINTS))
+ {
+ ANGLE_TRY(mProgram->getGeometryExecutableForPrimitiveType(mContext, GL_POINTS, &mResult,
+ &mInfoLog));
+ }
+
+ return gl::NoError();
}
- // Auto-generate the geometry shader here, if we expect to be using point rendering in D3D11.
- ShaderExecutableD3D *pointGS = nullptr;
- if (usesGeometryShader(GL_POINTS))
+ private:
+ const gl::Context *mContext;
+};
+
+gl::Error ProgramD3D::getComputeExecutable(ShaderExecutableD3D **outExecutable)
+{
+ if (outExecutable)
{
- getGeometryExecutableForPrimitiveType(data, GL_POINTS, &pointGS, &infoLog);
+ *outExecutable = mComputeExecutable.get();
}
- const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader());
+ return gl::NoError();
+}
+
+gl::LinkResult ProgramD3D::compileProgramExecutables(const gl::Context *context,
+ gl::InfoLog &infoLog)
+{
+ // Ensure the compiler is initialized to avoid race conditions.
+ ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized());
+
+ WorkerThreadPool *workerPool = mRenderer->getWorkerThreadPool();
+
+ GetVertexExecutableTask vertexTask(this, context);
+ GetPixelExecutableTask pixelTask(this);
+ GetGeometryExecutableTask geometryTask(this, context);
+
+ std::array<WaitableEvent, 3> waitEvents = {{workerPool->postWorkerTask(&vertexTask),
+ workerPool->postWorkerTask(&pixelTask),
+ workerPool->postWorkerTask(&geometryTask)}};
+
+ WaitableEvent::WaitMany(&waitEvents);
+
+ infoLog << vertexTask.getInfoLog().str();
+ infoLog << pixelTask.getInfoLog().str();
+ infoLog << geometryTask.getInfoLog().str();
+
+ ANGLE_TRY(vertexTask.getError());
+ ANGLE_TRY(pixelTask.getError());
+ ANGLE_TRY(geometryTask.getError());
+
+ ShaderExecutableD3D *defaultVertexExecutable = vertexTask.getResult();
+ ShaderExecutableD3D *defaultPixelExecutable = pixelTask.getResult();
+ ShaderExecutableD3D *pointGS = geometryTask.getResult();
+
+ const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedVertexShader());
if (usesGeometryShader(GL_POINTS) && pointGS)
{
@@ -1339,128 +1536,148 @@ LinkResult ProgramD3D::compileProgramExecutables(const gl::Data &data, gl::InfoL
if (defaultPixelExecutable)
{
const ShaderD3D *fragmentShaderD3D =
- GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader());
+ GetImplAs<ShaderD3D>(mState.getAttachedFragmentShader());
fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo());
}
- bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable &&
- (!usesGeometryShader(GL_POINTS) || pointGS));
- return LinkResult(linkSuccess, gl::Error(GL_NO_ERROR));
+ return (defaultVertexExecutable && defaultPixelExecutable &&
+ (!usesGeometryShader(GL_POINTS) || pointGS));
}
-LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog)
+gl::LinkResult ProgramD3D::compileComputeExecutable(const gl::Context *context,
+ gl::InfoLog &infoLog)
{
- reset();
+ // Ensure the compiler is initialized to avoid race conditions.
+ ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized());
+
+ std::string computeShader = mDynamicHLSL->generateComputeShaderLinkHLSL(context, mState);
- // TODO(jmadill): structures containing samplers
- for (const gl::LinkedUniform &linkedUniform : mData.getUniforms())
+ ShaderExecutableD3D *computeExecutable = nullptr;
+ ANGLE_TRY(mRenderer->compileToExecutable(infoLog, computeShader, gl::SHADER_COMPUTE,
+ std::vector<D3DVarying>(), false,
+ angle::CompilerWorkaroundsD3D(), &computeExecutable));
+
+ if (computeExecutable == nullptr)
{
- if (linkedUniform.isSampler() && linkedUniform.isField())
- {
- infoLog << "Structures containing samplers not currently supported in D3D.";
- return LinkResult(false, gl::Error(GL_NO_ERROR));
- }
+ ERR() << "Error compiling dynamic compute executable:" << std::endl
+ << infoLog.str() << std::endl;
+ }
+ else
+ {
+ const ShaderD3D *computeShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedComputeShader());
+ computeShaderD3D->appendDebugInfo(computeExecutable->getDebugInfo());
+ mComputeExecutable.reset(computeExecutable);
}
- const gl::Shader *vertexShader = mData.getAttachedVertexShader();
- const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
-
- const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
- const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
+ return mComputeExecutable.get() != nullptr;
+}
- mSamplersVS.resize(data.caps->maxVertexTextureImageUnits);
- mSamplersPS.resize(data.caps->maxTextureImageUnits);
+gl::LinkResult ProgramD3D::link(const gl::Context *context,
+ const gl::ProgramLinkedResources &resources,
+ gl::InfoLog &infoLog)
+{
+ const auto &data = context->getContextState();
- vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds);
- fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds);
+ reset();
- if (mRenderer->getRendererLimitations().noFrontFacingSupport)
+ gl::Shader *computeShader = mState.getAttachedComputeShader();
+ if (computeShader)
{
- if (fragmentShaderD3D->usesFrontFacing())
+ mSamplersCS.resize(data.getCaps().maxComputeTextureImageUnits);
+
+ defineUniformsAndAssignRegisters(context);
+
+ gl::LinkResult result = compileComputeExecutable(context, infoLog);
+ if (result.isError())
{
- infoLog << "The current renderer doesn't support gl_FrontFacing";
- return LinkResult(false, gl::Error(GL_NO_ERROR));
+ infoLog << result.getError().getMessage();
+ return result;
+ }
+ else if (!result.getResult())
+ {
+ infoLog << "Failed to create D3D compute shader.";
+ return result;
}
}
+ else
+ {
+ gl::Shader *vertexShader = mState.getAttachedVertexShader();
+ gl::Shader *fragmentShader = mState.getAttachedFragmentShader();
- std::vector<PackedVarying> packedVaryings =
- MergeVaryings(*vertexShader, *fragmentShader, mData.getTransformFeedbackVaryingNames());
+ const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(vertexShader);
+ const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(fragmentShader);
- // Map the varyings to the register file
- VaryingPacking varyingPacking(data.caps->maxVaryingVectors);
- if (!varyingPacking.packVaryings(infoLog, packedVaryings,
- mData.getTransformFeedbackVaryingNames()))
- {
- return LinkResult(false, gl::Error(GL_NO_ERROR));
- }
+ mSamplersVS.resize(data.getCaps().maxVertexTextureImageUnits);
+ mSamplersPS.resize(data.getCaps().maxTextureImageUnits);
- ProgramD3DMetadata metadata(mRenderer->getMajorShaderModel(), mRenderer->getShaderModelSuffix(),
- usesInstancedPointSpriteEmulation(),
- mRenderer->presentPathFastEnabled(), vertexShaderD3D,
- fragmentShaderD3D);
+ vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds);
+ fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds);
- varyingPacking.enableBuiltins(SHADER_VERTEX, metadata);
- varyingPacking.enableBuiltins(SHADER_PIXEL, metadata);
+ if (mRenderer->getNativeLimitations().noFrontFacingSupport)
+ {
+ if (fragmentShaderD3D->usesFrontFacing())
+ {
+ infoLog << "The current renderer doesn't support gl_FrontFacing";
+ return false;
+ }
+ }
- if (static_cast<GLuint>(varyingPacking.getRegisterCount()) > data.caps->maxVaryingVectors)
- {
- infoLog << "No varying registers left to support gl_FragCoord/gl_PointCoord";
- return LinkResult(false, gl::Error(GL_NO_ERROR));
- }
+ // TODO(jmadill): Implement more sophisticated component packing in D3D9.
+ // We can fail here because we use one semantic per GLSL varying. D3D11 can pack varyings
+ // intelligently, but D3D9 assumes one semantic per register.
+ if (mRenderer->getRendererClass() == RENDERER_D3D9 &&
+ resources.varyingPacking.getMaxSemanticIndex() > data.getCaps().maxVaryingVectors)
+ {
+ infoLog << "Cannot pack these varyings on D3D9.";
+ return false;
+ }
- // TODO(jmadill): Implement more sophisticated component packing in D3D9.
- // We can fail here because we use one semantic per GLSL varying. D3D11 can pack varyings
- // intelligently, but D3D9 assumes one semantic per register.
- if (mRenderer->getRendererClass() == RENDERER_D3D9 &&
- varyingPacking.getMaxSemanticIndex() > data.caps->maxVaryingVectors)
- {
- infoLog << "Cannot pack these varyings on D3D9.";
- return LinkResult(false, gl::Error(GL_NO_ERROR));
- }
+ ProgramD3DMetadata metadata(mRenderer, vertexShaderD3D, fragmentShaderD3D);
+ BuiltinVaryingsD3D builtins(metadata, resources.varyingPacking);
- if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, metadata, varyingPacking, &mPixelHLSL,
- &mVertexHLSL))
- {
- return LinkResult(false, gl::Error(GL_NO_ERROR));
- }
+ mDynamicHLSL->generateShaderLinkHLSL(context, mState, metadata, resources.varyingPacking,
+ builtins, &mPixelHLSL, &mVertexHLSL);
- mUsesPointSize = vertexShaderD3D->usesPointSize();
- mDynamicHLSL->getPixelShaderOutputKey(data, mData, metadata, &mPixelShaderKey);
- mUsesFragDepth = metadata.usesFragDepth(mData);
+ mUsesPointSize = vertexShaderD3D->usesPointSize();
+ mDynamicHLSL->getPixelShaderOutputKey(data, mState, metadata, &mPixelShaderKey);
+ mUsesFragDepth = metadata.usesFragDepth();
+ mUsesViewID = metadata.usesViewID();
+ mHasANGLEMultiviewEnabled = metadata.hasANGLEMultiviewEnabled();
- // Cache if we use flat shading
- mUsesFlatInterpolation = false;
- for (const auto &varying : packedVaryings)
- {
- if (varying.interpolation == sh::INTERPOLATION_FLAT)
+ // Cache if we use flat shading
+ mUsesFlatInterpolation =
+ (FindFlatInterpolationVarying(fragmentShader->getInputVaryings(context)) ||
+ FindFlatInterpolationVarying(vertexShader->getOutputVaryings(context)));
+
+ if (mRenderer->getMajorShaderModel() >= 4)
{
- mUsesFlatInterpolation = true;
- break;
+ mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(
+ resources.varyingPacking, builtins, mHasANGLEMultiviewEnabled,
+ metadata.canSelectViewInVertexShader());
}
- }
- if (mRenderer->getMajorShaderModel() >= 4)
- {
- varyingPacking.enableBuiltins(SHADER_GEOMETRY, metadata);
- mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(varyingPacking);
- }
+ initAttribLocationsToD3DSemantic(context);
- initSemanticIndex();
+ defineUniformsAndAssignRegisters(context);
- defineUniformsAndAssignRegisters();
+ gatherTransformFeedbackVaryings(resources.varyingPacking, builtins[gl::SHADER_VERTEX]);
- gatherTransformFeedbackVaryings(varyingPacking);
-
- LinkResult result = compileProgramExecutables(data, infoLog);
- if (result.error.isError() || !result.linkSuccess)
- {
- infoLog << "Failed to create D3D shaders.";
- return result;
+ gl::LinkResult result = compileProgramExecutables(context, infoLog);
+ if (result.isError())
+ {
+ infoLog << result.getError().getMessage();
+ return result;
+ }
+ else if (!result.getResult())
+ {
+ infoLog << "Failed to create D3D shaders.";
+ return result;
+ }
}
- initUniformBlockInfo();
+ linkResources(context, resources);
- return LinkResult(true, gl::Error(GL_NO_ERROR));
+ return true;
}
GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
@@ -1469,46 +1686,22 @@ GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLo
return GL_TRUE;
}
-void ProgramD3D::initUniformBlockInfo()
+void ProgramD3D::initializeUniformBlocks()
{
- const gl::Shader *vertexShader = mData.getAttachedVertexShader();
-
- for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks())
- {
- if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED)
- continue;
-
- if (mBlockDataSizes.count(vertexBlock.name) > 0)
- continue;
-
- size_t dataSize = getUniformBlockInfo(vertexBlock);
- mBlockDataSizes[vertexBlock.name] = dataSize;
- }
-
- const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
-
- for (const sh::InterfaceBlock &fragmentBlock : fragmentShader->getInterfaceBlocks())
+ if (mState.getUniformBlocks().empty())
{
- if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED)
- continue;
-
- if (mBlockDataSizes.count(fragmentBlock.name) > 0)
- continue;
-
- size_t dataSize = getUniformBlockInfo(fragmentBlock);
- mBlockDataSizes[fragmentBlock.name] = dataSize;
+ return;
}
-}
-void ProgramD3D::assignUniformBlockRegisters()
-{
- mD3DUniformBlocks.clear();
+ ASSERT(mD3DUniformBlocks.empty());
// Assign registers and update sizes.
- const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedVertexShader());
- const ShaderD3D *fragmentShaderD3D = GetImplAs<ShaderD3D>(mData.getAttachedFragmentShader());
+ const ShaderD3D *vertexShaderD3D = SafeGetImplAs<ShaderD3D>(mState.getAttachedVertexShader());
+ const ShaderD3D *fragmentShaderD3D =
+ SafeGetImplAs<ShaderD3D>(mState.getAttachedFragmentShader());
+ const ShaderD3D *computeShaderD3D = SafeGetImplAs<ShaderD3D>(mState.getAttachedComputeShader());
- for (const gl::UniformBlock &uniformBlock : mData.getUniformBlocks())
+ for (const gl::InterfaceBlock &uniformBlock : mState.getUniformBlocks())
{
unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0;
@@ -1516,18 +1709,27 @@ void ProgramD3D::assignUniformBlockRegisters()
if (uniformBlock.vertexStaticUse)
{
- unsigned int baseRegister =
- vertexShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
+ ASSERT(vertexShaderD3D != nullptr);
+ unsigned int baseRegister = vertexShaderD3D->getUniformBlockRegister(uniformBlock.name);
d3dUniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement;
}
if (uniformBlock.fragmentStaticUse)
{
+ ASSERT(fragmentShaderD3D != nullptr);
unsigned int baseRegister =
- fragmentShaderD3D->getInterfaceBlockRegister(uniformBlock.name);
+ fragmentShaderD3D->getUniformBlockRegister(uniformBlock.name);
d3dUniformBlock.psRegisterIndex = baseRegister + uniformBlockElement;
}
+ if (uniformBlock.computeStaticUse)
+ {
+ ASSERT(computeShaderD3D != nullptr);
+ unsigned int baseRegister =
+ computeShaderD3D->getUniformBlockRegister(uniformBlock.name);
+ d3dUniformBlock.csRegisterIndex = baseRegister + uniformBlockElement;
+ }
+
mD3DUniformBlocks.push_back(d3dUniformBlock);
}
}
@@ -1537,6 +1739,7 @@ void ProgramD3D::initializeUniformStorage()
// Compute total default block size
unsigned int vertexRegisters = 0;
unsigned int fragmentRegisters = 0;
+ unsigned int computeRegisters = 0;
for (const D3DUniform *d3dUniform : mD3DUniforms)
{
if (!d3dUniform->isSampler())
@@ -1551,55 +1754,67 @@ void ProgramD3D::initializeUniformStorage()
fragmentRegisters = std::max(
fragmentRegisters, d3dUniform->psRegisterIndex + d3dUniform->registerCount);
}
+ if (d3dUniform->isReferencedByComputeShader())
+ {
+ computeRegisters = std::max(
+ computeRegisters, d3dUniform->csRegisterIndex + d3dUniform->registerCount);
+ }
}
}
- mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
- mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
-}
-
-gl::Error ProgramD3D::applyUniforms(GLenum drawMode)
-{
- ASSERT(!mDirtySamplerMapping);
-
- gl::Error error = mRenderer->applyUniforms(*this, drawMode, mD3DUniforms);
- if (error.isError())
- {
- return error;
- }
+ mVertexUniformStorage =
+ std::unique_ptr<UniformStorageD3D>(mRenderer->createUniformStorage(vertexRegisters * 16u));
+ mFragmentUniformStorage = std::unique_ptr<UniformStorageD3D>(
+ mRenderer->createUniformStorage(fragmentRegisters * 16u));
+ mComputeUniformStorage =
+ std::unique_ptr<UniformStorageD3D>(mRenderer->createUniformStorage(computeRegisters * 16u));
+ // Iterate the uniforms again to assign data pointers to default block uniforms.
for (D3DUniform *d3dUniform : mD3DUniforms)
{
- d3dUniform->dirty = false;
- }
+ if (d3dUniform->isSampler())
+ {
+ d3dUniform->mSamplerData.resize(d3dUniform->getArraySizeProduct(), 0);
+ continue;
+ }
- return gl::Error(GL_NO_ERROR);
-}
+ if (d3dUniform->isReferencedByVertexShader())
+ {
+ d3dUniform->vsData = mVertexUniformStorage->getDataPointer(d3dUniform->vsRegisterIndex,
+ d3dUniform->registerElement);
+ }
-gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data)
-{
- if (mData.getUniformBlocks().empty())
- {
- return gl::Error(GL_NO_ERROR);
+ if (d3dUniform->isReferencedByFragmentShader())
+ {
+ d3dUniform->psData = mFragmentUniformStorage->getDataPointer(
+ d3dUniform->psRegisterIndex, d3dUniform->registerElement);
+ }
+
+ if (d3dUniform->isReferencedByComputeShader())
+ {
+ d3dUniform->csData = mComputeUniformStorage->getDataPointer(
+ d3dUniform->csRegisterIndex, d3dUniform->registerElement);
+ }
}
+}
- // Lazy init.
- if (mD3DUniformBlocks.empty())
+void ProgramD3D::updateUniformBufferCache(const gl::Caps &caps,
+ unsigned int reservedVertex,
+ unsigned int reservedFragment)
+{
+ if (mState.getUniformBlocks().empty())
{
- assignUniformBlockRegisters();
+ return;
}
mVertexUBOCache.clear();
mFragmentUBOCache.clear();
- const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
- const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
-
for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mD3DUniformBlocks.size();
uniformBlockIndex++)
{
const D3DUniformBlock &uniformBlock = mD3DUniformBlocks[uniformBlockIndex];
- GLuint blockBinding = mData.getUniformBlockBinding(uniformBlockIndex);
+ GLuint blockBinding = mState.getUniformBlockBinding(uniformBlockIndex);
// Unnecessary to apply an unreferenced standard or shared UBO
if (!uniformBlock.vertexStaticUse() && !uniformBlock.fragmentStaticUse())
@@ -1609,8 +1824,8 @@ gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data)
if (uniformBlock.vertexStaticUse())
{
- unsigned int registerIndex = uniformBlock.vsRegisterIndex - reservedBuffersInVS;
- ASSERT(registerIndex < data.caps->maxVertexUniformBlocks);
+ unsigned int registerIndex = uniformBlock.vsRegisterIndex - reservedVertex;
+ ASSERT(registerIndex < caps.maxVertexUniformBlocks);
if (mVertexUBOCache.size() <= registerIndex)
{
@@ -1623,8 +1838,8 @@ gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data)
if (uniformBlock.fragmentStaticUse())
{
- unsigned int registerIndex = uniformBlock.psRegisterIndex - reservedBuffersInFS;
- ASSERT(registerIndex < data.caps->maxFragmentUniformBlocks);
+ unsigned int registerIndex = uniformBlock.psRegisterIndex - reservedFragment;
+ ASSERT(registerIndex < caps.maxFragmentUniformBlocks);
if (mFragmentUBOCache.size() <= registerIndex)
{
@@ -1635,36 +1850,50 @@ gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data)
mFragmentUBOCache[registerIndex] = blockBinding;
}
}
+}
- return mRenderer->setUniformBuffers(data, mVertexUBOCache, mFragmentUBOCache);
+const std::vector<GLint> &ProgramD3D::getVertexUniformBufferCache() const
+{
+ return mVertexUBOCache;
+}
+
+const std::vector<GLint> &ProgramD3D::getFragmentUniformBufferCache() const
+{
+ return mFragmentUBOCache;
}
void ProgramD3D::dirtyAllUniforms()
{
- for (D3DUniform *d3dUniform : mD3DUniforms)
- {
- d3dUniform->dirty = true;
- }
+ mVertexUniformsDirty = true;
+ mFragmentUniformsDirty = true;
+ mComputeUniformsDirty = true;
+}
+
+void ProgramD3D::markUniformsClean()
+{
+ mVertexUniformsDirty = false;
+ mFragmentUniformsDirty = false;
+ mComputeUniformsDirty = false;
}
void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
{
- setUniform(location, count, v, GL_FLOAT);
+ setUniformInternal(location, count, v, GL_FLOAT);
}
void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
{
- setUniform(location, count, v, GL_FLOAT_VEC2);
+ setUniformInternal(location, count, v, GL_FLOAT_VEC2);
}
void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
{
- setUniform(location, count, v, GL_FLOAT_VEC3);
+ setUniformInternal(location, count, v, GL_FLOAT_VEC3);
}
void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
{
- setUniform(location, count, v, GL_FLOAT_VEC4);
+ setUniformInternal(location, count, v, GL_FLOAT_VEC4);
}
void ProgramD3D::setUniformMatrix2fv(GLint location,
@@ -1672,7 +1901,7 @@ void ProgramD3D::setUniformMatrix2fv(GLint location,
GLboolean transpose,
const GLfloat *value)
{
- setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
+ setUniformMatrixfvInternal<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
}
void ProgramD3D::setUniformMatrix3fv(GLint location,
@@ -1680,7 +1909,7 @@ void ProgramD3D::setUniformMatrix3fv(GLint location,
GLboolean transpose,
const GLfloat *value)
{
- setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
+ setUniformMatrixfvInternal<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
}
void ProgramD3D::setUniformMatrix4fv(GLint location,
@@ -1688,7 +1917,7 @@ void ProgramD3D::setUniformMatrix4fv(GLint location,
GLboolean transpose,
const GLfloat *value)
{
- setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
+ setUniformMatrixfvInternal<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
}
void ProgramD3D::setUniformMatrix2x3fv(GLint location,
@@ -1696,7 +1925,7 @@ void ProgramD3D::setUniformMatrix2x3fv(GLint location,
GLboolean transpose,
const GLfloat *value)
{
- setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
+ setUniformMatrixfvInternal<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
}
void ProgramD3D::setUniformMatrix3x2fv(GLint location,
@@ -1704,7 +1933,7 @@ void ProgramD3D::setUniformMatrix3x2fv(GLint location,
GLboolean transpose,
const GLfloat *value)
{
- setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
+ setUniformMatrixfvInternal<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
}
void ProgramD3D::setUniformMatrix2x4fv(GLint location,
@@ -1712,7 +1941,7 @@ void ProgramD3D::setUniformMatrix2x4fv(GLint location,
GLboolean transpose,
const GLfloat *value)
{
- setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
+ setUniformMatrixfvInternal<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
}
void ProgramD3D::setUniformMatrix4x2fv(GLint location,
@@ -1720,7 +1949,7 @@ void ProgramD3D::setUniformMatrix4x2fv(GLint location,
GLboolean transpose,
const GLfloat *value)
{
- setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
+ setUniformMatrixfvInternal<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
}
void ProgramD3D::setUniformMatrix3x4fv(GLint location,
@@ -1728,7 +1957,7 @@ void ProgramD3D::setUniformMatrix3x4fv(GLint location,
GLboolean transpose,
const GLfloat *value)
{
- setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
+ setUniformMatrixfvInternal<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
}
void ProgramD3D::setUniformMatrix4x3fv(GLint location,
@@ -1736,47 +1965,47 @@ void ProgramD3D::setUniformMatrix4x3fv(GLint location,
GLboolean transpose,
const GLfloat *value)
{
- setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
+ setUniformMatrixfvInternal<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
}
void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v)
{
- setUniform(location, count, v, GL_INT);
+ setUniformInternal(location, count, v, GL_INT);
}
void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v)
{
- setUniform(location, count, v, GL_INT_VEC2);
+ setUniformInternal(location, count, v, GL_INT_VEC2);
}
void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v)
{
- setUniform(location, count, v, GL_INT_VEC3);
+ setUniformInternal(location, count, v, GL_INT_VEC3);
}
void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v)
{
- setUniform(location, count, v, GL_INT_VEC4);
+ setUniformInternal(location, count, v, GL_INT_VEC4);
}
void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
{
- setUniform(location, count, v, GL_UNSIGNED_INT);
+ setUniformInternal(location, count, v, GL_UNSIGNED_INT);
}
void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
{
- setUniform(location, count, v, GL_UNSIGNED_INT_VEC2);
+ setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC2);
}
void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
{
- setUniform(location, count, v, GL_UNSIGNED_INT_VEC3);
+ setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC3);
}
void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
{
- setUniform(location, count, v, GL_UNSIGNED_INT_VEC4);
+ setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC4);
}
void ProgramD3D::setUniformBlockBinding(GLuint /*uniformBlockIndex*/,
@@ -1784,35 +2013,58 @@ void ProgramD3D::setUniformBlockBinding(GLuint /*uniformBlockIndex*/,
{
}
-void ProgramD3D::defineUniformsAndAssignRegisters()
+void ProgramD3D::defineUniformsAndAssignRegisters(const gl::Context *context)
{
D3DUniformMap uniformMap;
- const gl::Shader *vertexShader = mData.getAttachedVertexShader();
- for (const sh::Uniform &vertexUniform : vertexShader->getUniforms())
-
+ gl::Shader *computeShader = mState.getAttachedComputeShader();
+ if (computeShader)
{
- if (vertexUniform.staticUse)
+ for (const sh::Uniform &computeUniform : computeShader->getUniforms(context))
{
- defineUniformBase(vertexShader, vertexUniform, &uniformMap);
+ if (computeUniform.staticUse)
+ {
+ defineUniformBase(computeShader, computeUniform, &uniformMap);
+ }
}
}
-
- const gl::Shader *fragmentShader = mData.getAttachedFragmentShader();
- for (const sh::Uniform &fragmentUniform : fragmentShader->getUniforms())
+ else
{
- if (fragmentUniform.staticUse)
+ gl::Shader *vertexShader = mState.getAttachedVertexShader();
+ for (const sh::Uniform &vertexUniform : vertexShader->getUniforms(context))
+ {
+ if (vertexUniform.staticUse)
+ {
+ defineUniformBase(vertexShader, vertexUniform, &uniformMap);
+ }
+ }
+
+ gl::Shader *fragmentShader = mState.getAttachedFragmentShader();
+ for (const sh::Uniform &fragmentUniform : fragmentShader->getUniforms(context))
{
- defineUniformBase(fragmentShader, fragmentUniform, &uniformMap);
+ if (fragmentUniform.staticUse)
+ {
+ defineUniformBase(fragmentShader, fragmentUniform, &uniformMap);
+ }
}
}
// Initialize the D3DUniform list to mirror the indexing of the GL layer.
- for (const gl::LinkedUniform &glUniform : mData.getUniforms())
+ for (const gl::LinkedUniform &glUniform : mState.getUniforms())
{
if (!glUniform.isInDefaultBlock())
continue;
- auto mapEntry = uniformMap.find(glUniform.name);
+ std::string name = glUniform.name;
+ if (glUniform.isArray())
+ {
+ // In the program state, array uniform names include [0] as in the program resource
+ // spec. Here we don't include it.
+ // TODO(oetuaho@nvidia.com): consider using the same uniform naming here as in the GL
+ // layer.
+ ASSERT(angle::EndsWith(name, "[0]"));
+ name.resize(name.length() - 3);
+ }
+ auto mapEntry = uniformMap.find(name);
ASSERT(mapEntry != uniformMap.end());
mD3DUniforms.push_back(mapEntry->second);
}
@@ -1825,7 +2077,8 @@ void ProgramD3D::defineUniformBase(const gl::Shader *shader,
const sh::Uniform &uniform,
D3DUniformMap *uniformMap)
{
- if (uniform.isBuiltIn())
+ // Samplers get their registers assigned in assignAllSamplerRegisters.
+ if (uniform.isBuiltIn() || gl::IsSamplerType(uniform.type))
{
defineUniform(shader->getType(), uniform, uniform.name, nullptr, uniformMap);
return;
@@ -1835,7 +2088,7 @@ void ProgramD3D::defineUniformBase(const gl::Shader *shader,
unsigned int startRegister = shaderD3D->getUniformRegister(uniform.name);
ShShaderOutput outputType = shaderD3D->getCompilerOutputType();
- sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType));
+ sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType), true);
encoder.skipRegisters(startRegister);
defineUniform(shader->getType(), uniform, uniform.name, &encoder, uniformMap);
@@ -1854,6 +2107,84 @@ D3DUniform *ProgramD3D::getD3DUniformByName(const std::string &name)
return nullptr;
}
+void ProgramD3D::defineStructUniformFields(GLenum shaderType,
+ const std::vector<sh::ShaderVariable> &fields,
+ const std::string &namePrefix,
+ sh::HLSLBlockEncoder *encoder,
+ D3DUniformMap *uniformMap)
+{
+ if (encoder)
+ encoder->enterAggregateType();
+
+ for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
+ {
+ const sh::ShaderVariable &field = fields[fieldIndex];
+ const std::string &fieldFullName = (namePrefix + "." + field.name);
+
+ // Samplers get their registers assigned in assignAllSamplerRegisters.
+ // Also they couldn't use the same encoder as the rest of the struct, since they are
+ // extracted out of the struct by the shader translator.
+ if (gl::IsSamplerType(field.type))
+ {
+ defineUniform(shaderType, field, fieldFullName, nullptr, uniformMap);
+ }
+ else
+ {
+ defineUniform(shaderType, field, fieldFullName, encoder, uniformMap);
+ }
+ }
+
+ if (encoder)
+ encoder->exitAggregateType();
+}
+
+void ProgramD3D::defineArrayOfStructsUniformFields(GLenum shaderType,
+ const sh::ShaderVariable &uniform,
+ unsigned int arrayNestingIndex,
+ const std::string &prefix,
+ sh::HLSLBlockEncoder *encoder,
+ D3DUniformMap *uniformMap)
+{
+ // Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the
+ // innermost.
+ const unsigned int currentArraySize = uniform.getNestedArraySize(arrayNestingIndex);
+ for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement)
+ {
+ const std::string &elementString = prefix + ArrayString(arrayElement);
+ if (arrayNestingIndex + 1u < uniform.arraySizes.size())
+ {
+ defineArrayOfStructsUniformFields(shaderType, uniform, arrayNestingIndex + 1u,
+ elementString, encoder, uniformMap);
+ }
+ else
+ {
+ defineStructUniformFields(shaderType, uniform.fields, elementString, encoder,
+ uniformMap);
+ }
+ }
+}
+
+void ProgramD3D::defineArrayUniformElements(GLenum shaderType,
+ const sh::ShaderVariable &uniform,
+ const std::string &fullName,
+ sh::HLSLBlockEncoder *encoder,
+ D3DUniformMap *uniformMap)
+{
+ if (encoder)
+ encoder->enterAggregateType();
+
+ sh::ShaderVariable uniformElement = uniform;
+ uniformElement.arraySizes.pop_back();
+ for (unsigned int arrayIndex = 0u; arrayIndex < uniform.getOutermostArraySize(); ++arrayIndex)
+ {
+ std::string elementFullName = fullName + ArrayString(arrayIndex);
+ defineUniform(shaderType, uniformElement, elementFullName, encoder, uniformMap);
+ }
+
+ if (encoder)
+ encoder->exitAggregateType();
+}
+
void ProgramD3D::defineUniform(GLenum shaderType,
const sh::ShaderVariable &uniform,
const std::string &fullName,
@@ -1862,24 +2193,20 @@ void ProgramD3D::defineUniform(GLenum shaderType,
{
if (uniform.isStruct())
{
- for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++)
+ if (uniform.isArray())
{
- const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : "");
-
- if (encoder)
- encoder->enterAggregateType();
-
- for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++)
- {
- const sh::ShaderVariable &field = uniform.fields[fieldIndex];
- const std::string &fieldFullName = (fullName + elementString + "." + field.name);
-
- defineUniform(shaderType, field, fieldFullName, encoder, uniformMap);
- }
-
- if (encoder)
- encoder->exitAggregateType();
+ defineArrayOfStructsUniformFields(shaderType, uniform, 0u, fullName, encoder,
+ uniformMap);
}
+ else
+ {
+ defineStructUniformFields(shaderType, uniform.fields, fullName, encoder, uniformMap);
+ }
+ return;
+ }
+ if (uniform.isArrayOfArrays())
+ {
+ defineArrayUniformElements(shaderType, uniform, fullName, encoder, uniformMap);
return;
}
@@ -1891,7 +2218,7 @@ void ProgramD3D::defineUniform(GLenum shaderType,
// Advance the uniform offset, to track registers allocation for structs
sh::BlockMemberInfo blockInfo =
- encoder ? encoder->encodeType(uniform.type, uniform.arraySize, false)
+ encoder ? encoder->encodeType(uniform.type, uniform.arraySizes, false)
: sh::BlockMemberInfo::getDefaultBlockInfo();
auto uniformMapEntry = uniformMap->find(fullName);
@@ -1903,7 +2230,7 @@ void ProgramD3D::defineUniform(GLenum shaderType,
}
else
{
- d3dUniform = new D3DUniform(uniform.type, fullName, uniform.arraySize, true);
+ d3dUniform = new D3DUniform(uniform.type, fullName, uniform.arraySizes, true);
(*uniformMap)[fullName] = d3dUniform;
}
@@ -1917,11 +2244,15 @@ void ProgramD3D::defineUniform(GLenum shaderType,
{
d3dUniform->psRegisterIndex = reg;
}
- else
+ else if (shaderType == GL_VERTEX_SHADER)
{
- ASSERT(shaderType == GL_VERTEX_SHADER);
d3dUniform->vsRegisterIndex = reg;
}
+ else
+ {
+ ASSERT(shaderType == GL_COMPUTE_SHADER);
+ d3dUniform->csRegisterIndex = reg;
+ }
// Arrays are treated as aggregate types
if (uniform.isArray())
@@ -1931,177 +2262,223 @@ void ProgramD3D::defineUniform(GLenum shaderType,
}
}
+// Assume count is already clamped.
template <typename T>
-void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum targetUniformType)
+void ProgramD3D::setUniformImpl(const gl::VariableLocation &locationInfo,
+ GLsizei count,
+ const T *v,
+ uint8_t *targetData,
+ GLenum uniformType)
{
- const int components = gl::VariableComponentCount(targetUniformType);
- const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType);
-
- D3DUniform *targetUniform = getD3DUniformFromLocation(location);
+ D3DUniform *targetUniform = mD3DUniforms[locationInfo.index];
+ const int components = targetUniform->typeInfo.componentCount;
+ const unsigned int arrayElementOffset = locationInfo.arrayIndex;
- unsigned int elementCount = targetUniform->elementCount();
- unsigned int arrayElement = mData.getUniformLocations()[location].element;
- unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
-
- if (targetUniform->type == targetUniformType)
+ if (targetUniform->typeInfo.type == uniformType)
{
- T *target = reinterpret_cast<T *>(targetUniform->data) + arrayElement * 4;
+ T *dest = reinterpret_cast<T *>(targetData) + arrayElementOffset * 4;
+ const T *source = v;
- for (unsigned int i = 0; i < count; i++)
+ for (GLint i = 0; i < count; i++, dest += 4, source += components)
{
- T *dest = target + (i * 4);
- const T *source = v + (i * components);
-
- for (int c = 0; c < components; c++)
- {
- SetIfDirty(dest + c, source[c], &targetUniform->dirty);
- }
- for (int c = components; c < 4; c++)
- {
- SetIfDirty(dest + c, T(0), &targetUniform->dirty);
- }
+ memcpy(dest, source, components * sizeof(T));
}
}
- else if (targetUniform->type == targetBoolType)
+ else
{
- GLint *boolParams = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
+ ASSERT(targetUniform->typeInfo.type == gl::VariableBoolVectorType(uniformType));
+ GLint *boolParams = reinterpret_cast<GLint *>(targetData) + arrayElementOffset * 4;
- for (unsigned int i = 0; i < count; i++)
+ for (GLint i = 0; i < count; i++)
{
GLint *dest = boolParams + (i * 4);
const T *source = v + (i * components);
for (int c = 0; c < components; c++)
{
- SetIfDirty(dest + c, (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE,
- &targetUniform->dirty);
- }
- for (int c = components; c < 4; c++)
- {
- SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty);
+ dest[c] = (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE;
}
}
}
- else if (targetUniform->isSampler())
- {
- ASSERT(targetUniformType == GL_INT);
-
- GLint *target = reinterpret_cast<GLint *>(targetUniform->data) + arrayElement * 4;
-
- bool wasDirty = targetUniform->dirty;
-
- for (unsigned int i = 0; i < count; i++)
- {
- GLint *dest = target + (i * 4);
- const GLint *source = reinterpret_cast<const GLint *>(v) + (i * components);
+}
- SetIfDirty(dest + 0, source[0], &targetUniform->dirty);
- SetIfDirty(dest + 1, 0, &targetUniform->dirty);
- SetIfDirty(dest + 2, 0, &targetUniform->dirty);
- SetIfDirty(dest + 3, 0, &targetUniform->dirty);
- }
+template <typename T>
+void ProgramD3D::setUniformInternal(GLint location, GLsizei count, const T *v, GLenum uniformType)
+{
+ const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
+ D3DUniform *targetUniform = mD3DUniforms[locationInfo.index];
- if (!wasDirty && targetUniform->dirty)
+ if (targetUniform->typeInfo.isSampler)
+ {
+ ASSERT(uniformType == GL_INT);
+ size_t size = count * sizeof(T);
+ GLint *dest = &targetUniform->mSamplerData[locationInfo.arrayIndex];
+ if (memcmp(dest, v, size) != 0)
{
+ memcpy(dest, v, size);
mDirtySamplerMapping = true;
}
+ return;
+ }
+
+ if (targetUniform->vsData)
+ {
+ setUniformImpl(locationInfo, count, v, targetUniform->vsData, uniformType);
+ mVertexUniformsDirty = true;
+ }
+
+ if (targetUniform->psData)
+ {
+ setUniformImpl(locationInfo, count, v, targetUniform->psData, uniformType);
+ mFragmentUniformsDirty = true;
+ }
+
+ if (targetUniform->csData)
+ {
+ setUniformImpl(locationInfo, count, v, targetUniform->csData, uniformType);
+ mComputeUniformsDirty = true;
}
- else
- UNREACHABLE();
}
template <int cols, int rows>
-void ProgramD3D::setUniformMatrixfv(GLint location,
- GLsizei countIn,
- GLboolean transpose,
- const GLfloat *value,
- GLenum targetUniformType)
+bool ProgramD3D::setUniformMatrixfvImpl(GLint location,
+ GLsizei countIn,
+ GLboolean transpose,
+ const GLfloat *value,
+ uint8_t *targetData,
+ GLenum targetUniformType)
{
D3DUniform *targetUniform = getD3DUniformFromLocation(location);
- unsigned int elementCount = targetUniform->elementCount();
- unsigned int arrayElement = mData.getUniformLocations()[location].element;
- unsigned int count = std::min(elementCount - arrayElement, static_cast<unsigned int>(countIn));
+ unsigned int elementCount = targetUniform->getArraySizeProduct();
+ unsigned int arrayElementOffset = mState.getUniformLocations()[location].arrayIndex;
+ unsigned int count =
+ std::min(elementCount - arrayElementOffset, static_cast<unsigned int>(countIn));
const unsigned int targetMatrixStride = (4 * rows);
- GLfloat *target =
- (GLfloat *)(targetUniform->data + arrayElement * sizeof(GLfloat) * targetMatrixStride);
+ GLfloat *target = reinterpret_cast<GLfloat *>(
+ targetData + arrayElementOffset * sizeof(GLfloat) * targetMatrixStride);
+
+ bool dirty = false;
for (unsigned int i = 0; i < count; i++)
{
// Internally store matrices as transposed versions to accomodate HLSL matrix indexing
if (transpose == GL_FALSE)
{
- targetUniform->dirty = TransposeMatrix<GLfloat>(target, value, 4, rows, rows, cols) ||
- targetUniform->dirty;
+ dirty = TransposeExpandMatrix<GLfloat, cols, rows>(target, value) || dirty;
}
else
{
- targetUniform->dirty =
- ExpandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty;
+ dirty = ExpandMatrix<GLfloat, cols, rows>(target, value) || dirty;
}
target += targetMatrixStride;
value += cols * rows;
}
+
+ return dirty;
}
-size_t ProgramD3D::getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock)
+template <int cols, int rows>
+void ProgramD3D::setUniformMatrixfvInternal(GLint location,
+ GLsizei countIn,
+ GLboolean transpose,
+ const GLfloat *value,
+ GLenum targetUniformType)
{
- ASSERT(interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED);
-
- // define member uniforms
- sh::Std140BlockEncoder std140Encoder;
- sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED);
- sh::BlockLayoutEncoder *encoder = nullptr;
+ D3DUniform *targetUniform = getD3DUniformFromLocation(location);
- if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD)
+ if (targetUniform->vsData)
{
- encoder = &std140Encoder;
+ if (setUniformMatrixfvImpl<cols, rows>(location, countIn, transpose, value,
+ targetUniform->vsData, targetUniformType))
+ {
+ mVertexUniformsDirty = true;
+ }
}
- else
+
+ if (targetUniform->psData)
{
- encoder = &hlslEncoder;
+ if (setUniformMatrixfvImpl<cols, rows>(location, countIn, transpose, value,
+ targetUniform->psData, targetUniformType))
+ {
+ mFragmentUniformsDirty = true;
+ }
}
- GetUniformBlockInfo(interfaceBlock.fields, interfaceBlock.fieldPrefix(), encoder,
- interfaceBlock.isRowMajorLayout, &mBlockInfo);
-
- return encoder->getBlockSize();
+ if (targetUniform->csData)
+ {
+ if (setUniformMatrixfvImpl<cols, rows>(location, countIn, transpose, value,
+ targetUniform->csData, targetUniformType))
+ {
+ mComputeUniformsDirty = true;
+ }
+ }
}
void ProgramD3D::assignAllSamplerRegisters()
{
- for (const D3DUniform *d3dUniform : mD3DUniforms)
+ for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex)
{
- if (d3dUniform->isSampler())
+ if (mD3DUniforms[uniformIndex]->isSampler())
{
- assignSamplerRegisters(d3dUniform);
+ assignSamplerRegisters(uniformIndex);
}
}
}
-void ProgramD3D::assignSamplerRegisters(const D3DUniform *d3dUniform)
+void ProgramD3D::assignSamplerRegisters(size_t uniformIndex)
{
+ D3DUniform *d3dUniform = mD3DUniforms[uniformIndex];
ASSERT(d3dUniform->isSampler());
- ASSERT(d3dUniform->vsRegisterIndex != GL_INVALID_INDEX ||
- d3dUniform->psRegisterIndex != GL_INVALID_INDEX);
-
- if (d3dUniform->vsRegisterIndex != GL_INVALID_INDEX)
- {
- AssignSamplers(d3dUniform->vsRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
- mSamplersVS, &mUsedVertexSamplerRange);
+ // If the uniform is an array of arrays, then we have separate entries for each inner array in
+ // mD3DUniforms. However, the sampler register info is stored in the shader only for the
+ // outermost array.
+ std::vector<unsigned int> subscripts;
+ const std::string baseName = gl::ParseResourceName(d3dUniform->name, &subscripts);
+ unsigned int registerOffset = mState.getUniforms()[uniformIndex].flattenedOffsetInParentArrays *
+ d3dUniform->getArraySizeProduct();
+
+ const gl::Shader *computeShader = mState.getAttachedComputeShader();
+ if (computeShader)
+ {
+ const ShaderD3D *computeShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedComputeShader());
+ ASSERT(computeShaderD3D->hasUniform(baseName));
+ d3dUniform->csRegisterIndex =
+ computeShaderD3D->getUniformRegister(baseName) + registerOffset;
+ ASSERT(d3dUniform->csRegisterIndex != GL_INVALID_INDEX);
+ AssignSamplers(d3dUniform->csRegisterIndex, d3dUniform->typeInfo,
+ d3dUniform->getArraySizeProduct(), mSamplersCS, &mUsedComputeSamplerRange);
}
-
- if (d3dUniform->psRegisterIndex != GL_INVALID_INDEX)
+ else
{
- AssignSamplers(d3dUniform->psRegisterIndex, d3dUniform->type, d3dUniform->arraySize,
- mSamplersPS, &mUsedPixelSamplerRange);
+ const ShaderD3D *vertexShaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedVertexShader());
+ const ShaderD3D *fragmentShaderD3D =
+ GetImplAs<ShaderD3D>(mState.getAttachedFragmentShader());
+ ASSERT(vertexShaderD3D->hasUniform(baseName) || fragmentShaderD3D->hasUniform(baseName));
+ if (vertexShaderD3D->hasUniform(baseName))
+ {
+ d3dUniform->vsRegisterIndex =
+ vertexShaderD3D->getUniformRegister(baseName) + registerOffset;
+ ASSERT(d3dUniform->vsRegisterIndex != GL_INVALID_INDEX);
+ AssignSamplers(d3dUniform->vsRegisterIndex, d3dUniform->typeInfo,
+ d3dUniform->getArraySizeProduct(), mSamplersVS,
+ &mUsedVertexSamplerRange);
+ }
+ if (fragmentShaderD3D->hasUniform(baseName))
+ {
+ d3dUniform->psRegisterIndex =
+ fragmentShaderD3D->getUniformRegister(baseName) + registerOffset;
+ ASSERT(d3dUniform->psRegisterIndex != GL_INVALID_INDEX);
+ AssignSamplers(d3dUniform->psRegisterIndex, d3dUniform->typeInfo,
+ d3dUniform->getArraySizeProduct(), mSamplersPS, &mUsedPixelSamplerRange);
+ }
}
}
// static
void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
- GLenum samplerType,
+ const gl::UniformTypeInfo &typeInfo,
unsigned int samplerCount,
std::vector<Sampler> &outSamplers,
GLuint *outUsedRange)
@@ -2113,7 +2490,7 @@ void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
ASSERT(samplerIndex < outSamplers.size());
Sampler *sampler = &outSamplers[samplerIndex];
sampler->active = true;
- sampler->textureType = gl::SamplerTypeToTextureType(samplerType);
+ sampler->textureType = typeInfo.samplerTextureType;
sampler->logicalTextureUnit = 0;
*outUsedRange = std::max(samplerIndex + 1, *outUsedRange);
samplerIndex++;
@@ -2122,20 +2499,24 @@ void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
void ProgramD3D::reset()
{
- SafeDeleteContainer(mVertexExecutables);
- SafeDeleteContainer(mPixelExecutables);
+ mVertexExecutables.clear();
+ mPixelExecutables.clear();
- for (auto &element : mGeometryExecutables)
+ for (auto &geometryExecutable : mGeometryExecutables)
{
- SafeDelete(element);
+ geometryExecutable.reset(nullptr);
}
+ mComputeExecutable.reset(nullptr);
+
mVertexHLSL.clear();
- mVertexWorkarounds = D3DCompilerWorkarounds();
+ mVertexWorkarounds = angle::CompilerWorkaroundsD3D();
mPixelHLSL.clear();
- mPixelWorkarounds = D3DCompilerWorkarounds();
+ mPixelWorkarounds = angle::CompilerWorkaroundsD3D();
mUsesFragDepth = false;
+ mHasANGLEMultiviewEnabled = false;
+ mUsesViewID = false;
mPixelShaderKey.clear();
mUsesPointSize = false;
mUsesFlatInterpolation = false;
@@ -2143,22 +2524,29 @@ void ProgramD3D::reset()
SafeDeleteContainer(mD3DUniforms);
mD3DUniformBlocks.clear();
- SafeDelete(mVertexUniformStorage);
- SafeDelete(mFragmentUniformStorage);
+ mVertexUniformStorage.reset(nullptr);
+ mFragmentUniformStorage.reset(nullptr);
+ mComputeUniformStorage.reset(nullptr);
mSamplersPS.clear();
mSamplersVS.clear();
+ mSamplersCS.clear();
mUsedVertexSamplerRange = 0;
mUsedPixelSamplerRange = 0;
+ mUsedComputeSamplerRange = 0;
mDirtySamplerMapping = true;
- std::fill(mSemanticIndexes, mSemanticIndexes + ArraySize(mSemanticIndexes), -1);
- std::fill(mAttributesByLayout, mAttributesByLayout + ArraySize(mAttributesByLayout), -1);
+ mAttribLocationToD3DSemantic.fill(-1);
mStreamOutVaryings.clear();
mGeometryShaderPreamble.clear();
+
+ dirtyAllUniforms();
+
+ mCachedPixelExecutableIndex.reset();
+ mCachedVertexExecutableIndex.reset();
}
unsigned int ProgramD3D::getSerial() const
@@ -2171,84 +2559,96 @@ unsigned int ProgramD3D::issueSerial()
return mCurrentSerial++;
}
-void ProgramD3D::initSemanticIndex()
+void ProgramD3D::initAttribLocationsToD3DSemantic(const gl::Context *context)
{
- const gl::Shader *vertexShader = mData.getAttachedVertexShader();
+ gl::Shader *vertexShader = mState.getAttachedVertexShader();
ASSERT(vertexShader != nullptr);
// Init semantic index
- for (const sh::Attribute &attribute : mData.getAttributes())
+ int semanticIndex = 0;
+ for (const sh::Attribute &attribute : vertexShader->getActiveAttributes(context))
{
- int attributeIndex = attribute.location;
- int index = vertexShader->getSemanticIndex(attribute.name);
- int regs = gl::VariableRegisterCount(attribute.type);
+ int regCount = gl::VariableRegisterCount(attribute.type);
+ GLuint location = mState.getAttributeLocation(attribute.name);
+ ASSERT(location != std::numeric_limits<GLuint>::max());
- for (int reg = 0; reg < regs; ++reg)
+ for (int reg = 0; reg < regCount; ++reg)
{
- mSemanticIndexes[attributeIndex + reg] = index + reg;
+ mAttribLocationToD3DSemantic[location + reg] = semanticIndex++;
}
}
-
- initAttributesByLayout();
}
-void ProgramD3D::initAttributesByLayout()
+void ProgramD3D::updateCachedInputLayout(Serial associatedSerial, const gl::State &state)
{
- for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ if (mCurrentVertexArrayStateSerial == associatedSerial)
{
- mAttributesByLayout[i] = i;
+ return;
}
- std::sort(&mAttributesByLayout[0], &mAttributesByLayout[gl::MAX_VERTEX_ATTRIBS],
- AttributeSorter(mSemanticIndexes));
-}
+ mCurrentVertexArrayStateSerial = associatedSerial;
+ mCachedInputLayout.clear();
-void ProgramD3D::sortAttributesByLayout(
- const std::vector<TranslatedAttribute> &unsortedAttributes,
- int sortedSemanticIndicesOut[gl::MAX_VERTEX_ATTRIBS],
- const rx::TranslatedAttribute *sortedAttributesOut[gl::MAX_VERTEX_ATTRIBS]) const
-{
- for (size_t attribIndex = 0; attribIndex < unsortedAttributes.size(); ++attribIndex)
+ const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
+
+ for (size_t locationIndex : mState.getActiveAttribLocationsMask())
{
- int oldIndex = mAttributesByLayout[attribIndex];
- sortedSemanticIndicesOut[attribIndex] = mSemanticIndexes[oldIndex];
- sortedAttributesOut[attribIndex] = &unsortedAttributes[oldIndex];
+ int d3dSemantic = mAttribLocationToD3DSemantic[locationIndex];
+
+ if (d3dSemantic != -1)
+ {
+ if (mCachedInputLayout.size() < static_cast<size_t>(d3dSemantic + 1))
+ {
+ mCachedInputLayout.resize(d3dSemantic + 1, gl::VERTEX_FORMAT_INVALID);
+ }
+ mCachedInputLayout[d3dSemantic] =
+ GetVertexFormatType(vertexAttributes[locationIndex],
+ state.getVertexAttribCurrentValue(locationIndex).Type);
+ }
}
+
+ VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature);
+
+ updateCachedVertexExecutableIndex();
}
-void ProgramD3D::updateCachedInputLayout(const gl::State &state)
+void ProgramD3D::updateCachedOutputLayout(const gl::Context *context,
+ const gl::Framebuffer *framebuffer)
{
- mCachedInputLayout.clear();
- const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
+ mPixelShaderOutputLayoutCache.clear();
+
+ FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(framebuffer);
+ const auto &colorbuffers = fboD3D->getColorAttachmentsForRender(context);
- for (unsigned int attributeIndex : angle::IterateBitSet(mData.getActiveAttribLocationsMask()))
+ for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
{
- int semanticIndex = mSemanticIndexes[attributeIndex];
+ const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
- if (semanticIndex != -1)
+ if (colorbuffer)
{
- if (mCachedInputLayout.size() < static_cast<size_t>(semanticIndex + 1))
- {
- mCachedInputLayout.resize(semanticIndex + 1, gl::VERTEX_FORMAT_INVALID);
- }
- mCachedInputLayout[semanticIndex] =
- GetVertexFormatType(vertexAttributes[attributeIndex],
- state.getVertexAttribCurrentValue(attributeIndex).Type);
+ auto binding = colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0
+ : colorbuffer->getBinding();
+ mPixelShaderOutputLayoutCache.push_back(binding);
+ }
+ else
+ {
+ mPixelShaderOutputLayoutCache.push_back(GL_NONE);
}
}
+
+ updateCachedPixelExecutableIndex();
}
-void ProgramD3D::gatherTransformFeedbackVaryings(const VaryingPacking &varyingPacking)
+void ProgramD3D::gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyingPacking,
+ const BuiltinInfo &builtins)
{
- const auto &builtins = varyingPacking.builtins(SHADER_VERTEX);
-
const std::string &varyingSemantic =
GetVaryingSemantic(mRenderer->getMajorShaderModel(), usesPointSize());
// Gather the linked varyings that are used for transform feedback, they should all exist.
mStreamOutVaryings.clear();
- const auto &tfVaryingNames = mData.getTransformFeedbackVaryingNames();
+ const auto &tfVaryingNames = mState.getTransformFeedbackVaryingNames();
for (unsigned int outputSlot = 0; outputSlot < static_cast<unsigned int>(tfVaryingNames.size());
++outputSlot)
{
@@ -2278,7 +2678,14 @@ void ProgramD3D::gatherTransformFeedbackVaryings(const VaryingPacking &varyingPa
}
else
{
- for (const PackedVaryingRegister &registerInfo : varyingPacking.getRegisterList())
+ std::vector<unsigned int> subscripts;
+ std::string baseName = gl::ParseResourceName(tfVaryingName, &subscripts);
+ size_t subscript = GL_INVALID_INDEX;
+ if (!subscripts.empty())
+ {
+ subscript = subscripts.back();
+ }
+ for (const auto &registerInfo : varyingPacking.getRegisterList())
{
const auto &varying = *registerInfo.packedVarying->varying;
GLenum transposedType = gl::TransposeMatrixType(varying.type);
@@ -2293,7 +2700,8 @@ void ProgramD3D::gatherTransformFeedbackVaryings(const VaryingPacking &varyingPa
// There can be more than one register assigned to a particular varying, and each
// register needs its own stream out entry.
- if (tfVaryingName == varying.name)
+ if (baseName == registerInfo.packedVarying->varying->name &&
+ (subscript == GL_INVALID_INDEX || subscript == registerInfo.varyingArrayIndex))
{
mStreamOutVaryings.push_back(D3DVarying(
varyingSemantic, registerInfo.semanticIndex, componentCount, outputSlot));
@@ -2305,36 +2713,155 @@ void ProgramD3D::gatherTransformFeedbackVaryings(const VaryingPacking &varyingPa
D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
{
- return mD3DUniforms[mData.getUniformLocations()[location].index];
+ return mD3DUniforms[mState.getUniformLocations()[location].index];
+}
+
+const D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location) const
+{
+ return mD3DUniforms[mState.getUniformLocations()[location].index];
+}
+
+void ProgramD3D::setPathFragmentInputGen(const std::string &inputName,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs)
+{
+ UNREACHABLE();
}
-bool ProgramD3D::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
+bool ProgramD3D::hasVertexExecutableForCachedInputLayout()
{
- std::string baseName = blockName;
- gl::ParseAndStripArrayIndex(&baseName);
+ return mCachedVertexExecutableIndex.valid();
+}
- auto sizeIter = mBlockDataSizes.find(baseName);
- if (sizeIter == mBlockDataSizes.end())
+bool ProgramD3D::hasGeometryExecutableForPrimitiveType(GLenum drawMode)
+{
+ if (!usesGeometryShader(drawMode))
{
- *sizeOut = 0;
- return false;
+ // No shader necessary mean we have the required (null) executable.
+ return true;
}
- *sizeOut = sizeIter->second;
- return true;
+ gl::PrimitiveType geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
+ return mGeometryExecutables[geometryShaderType].get() != nullptr;
+}
+
+bool ProgramD3D::hasPixelExecutableForCachedOutputLayout()
+{
+ return mCachedPixelExecutableIndex.valid();
}
-bool ProgramD3D::getUniformBlockMemberInfo(const std::string &memberUniformName,
- sh::BlockMemberInfo *memberInfoOut) const
+template <typename DestT>
+void ProgramD3D::getUniformInternal(GLint location, DestT *dataOut) const
{
- auto infoIter = mBlockInfo.find(memberUniformName);
- if (infoIter == mBlockInfo.end())
+ const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
+ const gl::LinkedUniform &uniform = mState.getUniforms()[locationInfo.index];
+
+ const D3DUniform *targetUniform = getD3DUniformFromLocation(location);
+ const uint8_t *srcPointer = targetUniform->getDataPtrToElement(locationInfo.arrayIndex);
+
+ if (gl::IsMatrixType(uniform.type))
{
- *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
- return false;
+ GetMatrixUniform(gl::VariableColumnCount(uniform.type), gl::VariableRowCount(uniform.type),
+ dataOut, reinterpret_cast<const DestT *>(srcPointer));
}
+ else
+ {
+ memcpy(dataOut, srcPointer, uniform.getElementSize());
+ }
+}
- *memberInfoOut = infoIter->second;
- return true;
+void ProgramD3D::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
+{
+ getUniformInternal(location, params);
+}
+
+void ProgramD3D::getUniformiv(const gl::Context *context, GLint location, GLint *params) const
+{
+ getUniformInternal(location, params);
+}
+
+void ProgramD3D::getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const
+{
+ getUniformInternal(location, params);
+}
+
+void ProgramD3D::updateCachedVertexExecutableIndex()
+{
+ mCachedVertexExecutableIndex.reset();
+ for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
+ {
+ if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
+ {
+ mCachedVertexExecutableIndex = executableIndex;
+ break;
+ }
+ }
+}
+
+void ProgramD3D::updateCachedPixelExecutableIndex()
+{
+ mCachedPixelExecutableIndex.reset();
+ for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
+ {
+ if (mPixelExecutables[executableIndex]->matchesSignature(mPixelShaderOutputLayoutCache))
+ {
+ mCachedPixelExecutableIndex = executableIndex;
+ break;
+ }
+ }
}
+
+void ProgramD3D::linkResources(const gl::Context *context,
+ const gl::ProgramLinkedResources &resources)
+{
+ UniformBlockInfo uniformBlockInfo;
+
+ if (mState.getAttachedVertexShader())
+ {
+ uniformBlockInfo.getShaderBlockInfo(context, mState.getAttachedVertexShader());
+ }
+
+ if (mState.getAttachedFragmentShader())
+ {
+ uniformBlockInfo.getShaderBlockInfo(context, mState.getAttachedFragmentShader());
+ }
+
+ if (mState.getAttachedComputeShader())
+ {
+ uniformBlockInfo.getShaderBlockInfo(context, mState.getAttachedComputeShader());
+ }
+
+ // Gather interface block info.
+ auto getUniformBlockSize = [&uniformBlockInfo](const std::string &name,
+ const std::string &mappedName, size_t *sizeOut) {
+ return uniformBlockInfo.getBlockSize(name, mappedName, sizeOut);
+ };
+
+ auto getUniformBlockMemberInfo = [&uniformBlockInfo](const std::string &name,
+ const std::string &mappedName,
+ sh::BlockMemberInfo *infoOut) {
+ return uniformBlockInfo.getBlockMemberInfo(name, mappedName, infoOut);
+ };
+
+ resources.uniformBlockLinker.linkBlocks(getUniformBlockSize, getUniformBlockMemberInfo);
+ initializeUniformBlocks();
+
+ // TODO(jiajia.qin@intel.com): Determine correct shader storage block info.
+ auto getShaderStorageBlockSize = [](const std::string &name, const std::string &mappedName,
+ size_t *sizeOut) {
+ *sizeOut = 0;
+ return true;
+ };
+
+ auto getShaderStorageBlockMemberInfo =
+ [](const std::string &name, const std::string &mappedName, sh::BlockMemberInfo *infoOut) {
+ *infoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
+ return true;
+ };
+
+ resources.shaderStorageBlockLinker.linkBlocks(getShaderStorageBlockSize,
+ getShaderStorageBlockMemberInfo);
}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.h
index 3dfe52db1c..829757a73e 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.h
@@ -17,7 +17,7 @@
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/ProgramImpl.h"
#include "libANGLE/renderer/d3d/DynamicHLSL.h"
-#include "libANGLE/renderer/d3d/WorkaroundsD3D.h"
+#include "platform/WorkaroundsD3D.h"
namespace rx
{
@@ -32,52 +32,71 @@ class ShaderExecutableD3D;
#endif
// Helper struct representing a single shader uniform
-struct D3DUniform : angle::NonCopyable
+// TODO(jmadill): Make uniform blocks shared between all programs, so we don't need separate
+// register indices.
+struct D3DUniform : private angle::NonCopyable
{
- D3DUniform(GLenum typeIn,
+ D3DUniform(GLenum type,
const std::string &nameIn,
- unsigned int arraySizeIn,
+ const std::vector<unsigned int> &arraySizesIn,
bool defaultBlock);
~D3DUniform();
bool isSampler() const;
- unsigned int elementCount() const { return std::max(1u, arraySize); }
+
+ bool isArray() const { return !arraySizes.empty(); }
+ unsigned int getArraySizeProduct() const;
+
bool isReferencedByVertexShader() const;
bool isReferencedByFragmentShader() const;
+ bool isReferencedByComputeShader() const;
- // Duplicated from the GL layer
- GLenum type;
- std::string name;
- unsigned int arraySize;
+ const uint8_t *firstNonNullData() const;
+ const uint8_t *getDataPtrToElement(size_t elementIndex) const;
- // Pointer to a system copy of the data.
- // TODO(jmadill): remove this in favor of gl::LinkedUniform::data().
- uint8_t *data;
+ // Duplicated from the GL layer
+ const gl::UniformTypeInfo &typeInfo;
+ std::string name; // Names of arrays don't include [0], unlike at the GL layer.
+ std::vector<unsigned int> arraySizes;
- // Has the data been updated since the last sync?
- bool dirty;
+ // Pointer to a system copies of the data. Separate pointers for each uniform storage type.
+ uint8_t *vsData;
+ uint8_t *psData;
+ uint8_t *csData;
// Register information.
unsigned int vsRegisterIndex;
unsigned int psRegisterIndex;
+ unsigned int csRegisterIndex;
unsigned int registerCount;
// Register "elements" are used for uniform structs in ES3, to appropriately identify single
// uniforms
// inside aggregate types, which are packed according C-like structure rules.
unsigned int registerElement;
+
+ // Special buffer for sampler values.
+ std::vector<GLint> mSamplerData;
};
struct D3DUniformBlock
{
- D3DUniformBlock() : vsRegisterIndex(GL_INVALID_INDEX), psRegisterIndex(GL_INVALID_INDEX) {}
+ D3DUniformBlock()
+ : vsRegisterIndex(GL_INVALID_INDEX),
+ psRegisterIndex(GL_INVALID_INDEX),
+ csRegisterIndex(GL_INVALID_INDEX)
+ {
+ }
bool vertexStaticUse() const { return vsRegisterIndex != GL_INVALID_INDEX; }
bool fragmentStaticUse() const { return psRegisterIndex != GL_INVALID_INDEX; }
+ bool computeStaticUse() const { return csRegisterIndex != GL_INVALID_INDEX; }
+
unsigned int vsRegisterIndex;
unsigned int psRegisterIndex;
+ unsigned int csRegisterIndex;
};
struct D3DVarying final
@@ -97,24 +116,24 @@ struct D3DVarying final
unsigned int outputSlot;
};
-class ProgramD3DMetadata : angle::NonCopyable
+class ProgramD3DMetadata final : angle::NonCopyable
{
public:
- ProgramD3DMetadata(int rendererMajorShaderModel,
- const std::string &shaderModelSuffix,
- bool usesInstancedPointSpriteEmulation,
- bool usesViewScale,
+ ProgramD3DMetadata(RendererD3D *renderer,
const ShaderD3D *vertexShader,
const ShaderD3D *fragmentShader);
int getRendererMajorShaderModel() const;
- bool usesBroadcast(const gl::Data &data) const;
- bool usesFragDepth(const gl::Program::Data &programData) const;
+ bool usesBroadcast(const gl::ContextState &data) const;
+ bool usesFragDepth() const;
bool usesPointCoord() const;
bool usesFragCoord() const;
bool usesPointSize() const;
bool usesInsertedPointCoordValue() const;
bool usesViewScale() const;
+ bool hasANGLEMultiviewEnabled() const;
+ bool usesViewID() const;
+ bool canSelectViewInVertexShader() const;
bool addsPointCoordToVertexShader() const;
bool usesTransformFeedbackGLPosition() const;
bool usesSystemValuePointSize() const;
@@ -127,6 +146,9 @@ class ProgramD3DMetadata : angle::NonCopyable
const std::string mShaderModelSuffix;
const bool mUsesInstancedPointSpriteEmulation;
const bool mUsesViewScale;
+ const bool mHasANGLEMultiviewEnabled;
+ const bool mUsesViewID;
+ const bool mCanSelectViewInVertexShader;
const ShaderD3D *mVertexShader;
const ShaderD3D *mFragmentShader;
};
@@ -134,10 +156,8 @@ class ProgramD3DMetadata : angle::NonCopyable
class ProgramD3D : public ProgramImpl
{
public:
- typedef int SemanticIndexArray[gl::MAX_VERTEX_ATTRIBS];
-
- ProgramD3D(const gl::Program::Data &data, RendererD3D *renderer);
- virtual ~ProgramD3D();
+ ProgramD3D(const gl::ProgramState &data, RendererD3D *renderer);
+ ~ProgramD3D() override;
const std::vector<PixelShaderOutputVariable> &getPixelShaderKey() { return mPixelShaderKey; }
@@ -145,116 +165,157 @@ class ProgramD3D : public ProgramImpl
unsigned int samplerIndex,
const gl::Caps &caps) const;
GLenum getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const;
- GLint getUsedSamplerRange(gl::SamplerType type) const;
- void updateSamplerMapping();
+ GLuint getUsedSamplerRange(gl::SamplerType type) const;
+
+ enum SamplerMapping
+ {
+ WasDirty,
+ WasClean,
+ };
+
+ SamplerMapping updateSamplerMapping();
bool usesPointSize() const { return mUsesPointSize; }
bool usesPointSpriteEmulation() const;
bool usesGeometryShader(GLenum drawMode) const;
+ bool usesGeometryShaderForPointSpriteEmulation() const;
bool usesInstancedPointSpriteEmulation() const;
- LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) override;
- gl::Error save(gl::BinaryOutputStream *stream) override;
+ gl::LinkResult load(const gl::Context *context,
+ gl::InfoLog &infoLog,
+ gl::BinaryInputStream *stream) override;
+ void save(const gl::Context *context, gl::BinaryOutputStream *stream) override;
void setBinaryRetrievableHint(bool retrievable) override;
+ void setSeparable(bool separable) override;
- gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo,
- ShaderExecutableD3D **outExectuable);
- gl::Error getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout,
- ShaderExecutableD3D **outExectuable,
- gl::InfoLog *infoLog);
- gl::Error getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout,
- ShaderExecutableD3D **outExectuable,
- gl::InfoLog *infoLog);
- gl::Error getGeometryExecutableForPrimitiveType(const gl::Data &data,
+ gl::Error getVertexExecutableForCachedInputLayout(ShaderExecutableD3D **outExectuable,
+ gl::InfoLog *infoLog);
+ gl::Error getGeometryExecutableForPrimitiveType(const gl::Context *context,
GLenum drawMode,
ShaderExecutableD3D **outExecutable,
gl::InfoLog *infoLog);
-
- LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) override;
+ gl::Error getPixelExecutableForCachedOutputLayout(ShaderExecutableD3D **outExectuable,
+ gl::InfoLog *infoLog);
+ gl::Error getComputeExecutable(ShaderExecutableD3D **outExecutable);
+ gl::LinkResult link(const gl::Context *context,
+ const gl::ProgramLinkedResources &resources,
+ gl::InfoLog &infoLog) override;
GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
- bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override;
- bool getUniformBlockMemberInfo(const std::string &memberUniformName,
- sh::BlockMemberInfo *memberInfoOut) const override;
+ void setPathFragmentInputGen(const std::string &inputName,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs) override;
void initializeUniformStorage();
- gl::Error applyUniforms(GLenum drawMode);
- gl::Error applyUniformBuffers(const gl::Data &data);
+ void updateUniformBufferCache(const gl::Caps &caps,
+ unsigned int reservedVertex,
+ unsigned int reservedFragment);
+ const std::vector<GLint> &getVertexUniformBufferCache() const;
+ const std::vector<GLint> &getFragmentUniformBufferCache() const;
+
void dirtyAllUniforms();
- void setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
- void setUniform2fv(GLint location, GLsizei count, const GLfloat *v);
- void setUniform3fv(GLint location, GLsizei count, const GLfloat *v);
- void setUniform4fv(GLint location, GLsizei count, const GLfloat *v);
- void setUniform1iv(GLint location, GLsizei count, const GLint *v);
- void setUniform2iv(GLint location, GLsizei count, const GLint *v);
- void setUniform3iv(GLint location, GLsizei count, const GLint *v);
- void setUniform4iv(GLint location, GLsizei count, const GLint *v);
- void setUniform1uiv(GLint location, GLsizei count, const GLuint *v);
- void setUniform2uiv(GLint location, GLsizei count, const GLuint *v);
- void setUniform3uiv(GLint location, GLsizei count, const GLuint *v);
- void setUniform4uiv(GLint location, GLsizei count, const GLuint *v);
+ void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) override;
+ void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) override;
+ void setUniform3fv(GLint location, GLsizei count, const GLfloat *v) override;
+ void setUniform4fv(GLint location, GLsizei count, const GLfloat *v) override;
+ void setUniform1iv(GLint location, GLsizei count, const GLint *v) override;
+ void setUniform2iv(GLint location, GLsizei count, const GLint *v) override;
+ void setUniform3iv(GLint location, GLsizei count, const GLint *v) override;
+ void setUniform4iv(GLint location, GLsizei count, const GLint *v) override;
+ void setUniform1uiv(GLint location, GLsizei count, const GLuint *v) override;
+ void setUniform2uiv(GLint location, GLsizei count, const GLuint *v) override;
+ void setUniform3uiv(GLint location, GLsizei count, const GLuint *v) override;
+ void setUniform4uiv(GLint location, GLsizei count, const GLuint *v) override;
void setUniformMatrix2fv(GLint location,
GLsizei count,
GLboolean transpose,
- const GLfloat *value);
+ const GLfloat *value) override;
void setUniformMatrix3fv(GLint location,
GLsizei count,
GLboolean transpose,
- const GLfloat *value);
+ const GLfloat *value) override;
void setUniformMatrix4fv(GLint location,
GLsizei count,
GLboolean transpose,
- const GLfloat *value);
+ const GLfloat *value) override;
void setUniformMatrix2x3fv(GLint location,
GLsizei count,
GLboolean transpose,
- const GLfloat *value);
+ const GLfloat *value) override;
void setUniformMatrix3x2fv(GLint location,
GLsizei count,
GLboolean transpose,
- const GLfloat *value);
+ const GLfloat *value) override;
void setUniformMatrix2x4fv(GLint location,
GLsizei count,
GLboolean transpose,
- const GLfloat *value);
+ const GLfloat *value) override;
void setUniformMatrix4x2fv(GLint location,
GLsizei count,
GLboolean transpose,
- const GLfloat *value);
+ const GLfloat *value) override;
void setUniformMatrix3x4fv(GLint location,
GLsizei count,
GLboolean transpose,
- const GLfloat *value);
+ const GLfloat *value) override;
void setUniformMatrix4x3fv(GLint location,
GLsizei count,
GLboolean transpose,
- const GLfloat *value);
+ const GLfloat *value) override;
+
+ void getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const override;
+ void getUniformiv(const gl::Context *context, GLint location, GLint *params) const override;
+ void getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const override;
void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override;
- const UniformStorageD3D &getVertexUniformStorage() const { return *mVertexUniformStorage; }
- const UniformStorageD3D &getFragmentUniformStorage() const { return *mFragmentUniformStorage; }
+ UniformStorageD3D &getVertexUniformStorage() const { return *mVertexUniformStorage.get(); }
+ UniformStorageD3D &getFragmentUniformStorage() const { return *mFragmentUniformStorage.get(); }
+ UniformStorageD3D &getComputeUniformStorage() const { return *mComputeUniformStorage.get(); }
unsigned int getSerial() const;
- void sortAttributesByLayout(
- const std::vector<TranslatedAttribute> &unsortedAttributes,
- int sortedSemanticIndicesOut[gl::MAX_VERTEX_ATTRIBS],
- const rx::TranslatedAttribute *sortedAttributesOut[gl::MAX_VERTEX_ATTRIBS]) const;
- const SemanticIndexArray &getSemanticIndexes() const { return mSemanticIndexes; }
- const SemanticIndexArray &getAttributesByLayout() const { return mAttributesByLayout; }
+ const AttribIndexArray &getAttribLocationToD3DSemantics() const
+ {
+ return mAttribLocationToD3DSemantic;
+ }
- void updateCachedInputLayout(const gl::State &state);
- const gl::InputLayout &getCachedInputLayout() const { return mCachedInputLayout; }
+ void updateCachedInputLayout(Serial associatedSerial, const gl::State &state);
+ void updateCachedOutputLayout(const gl::Context *context, const gl::Framebuffer *framebuffer);
bool isSamplerMappingDirty() { return mDirtySamplerMapping; }
+ // Checks if we need to recompile certain shaders.
+ bool hasVertexExecutableForCachedInputLayout();
+ bool hasGeometryExecutableForPrimitiveType(GLenum drawMode);
+ bool hasPixelExecutableForCachedOutputLayout();
+
+ bool areVertexUniformsDirty() const { return mVertexUniformsDirty; }
+ bool areFragmentUniformsDirty() const { return mFragmentUniformsDirty; }
+ bool areComputeUniformsDirty() const { return mComputeUniformsDirty; }
+ const std::vector<D3DUniform *> &getD3DUniforms() const { return mD3DUniforms; }
+ void markUniformsClean();
+
private:
+ // These forward-declared tasks are used for multi-thread shader compiles.
+ class GetExecutableTask;
+ class GetVertexExecutableTask;
+ class GetPixelExecutableTask;
+ class GetGeometryExecutableTask;
+
class VertexExecutable
{
public:
- typedef std::vector<bool> Signature;
+ enum HLSLAttribType
+ {
+ FLOAT,
+ UNSIGNED_INT,
+ SIGNED_INT,
+ };
+
+ typedef std::vector<HLSLAttribType> Signature;
VertexExecutable(const gl::InputLayout &inputLayout,
const Signature &signature,
@@ -271,6 +332,8 @@ class ProgramD3D : public ProgramImpl
ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; }
private:
+ static HLSLAttribType GetAttribType(GLenum type);
+
gl::InputLayout mInputs;
Signature mSignature;
ShaderExecutableD3D *mShaderExecutable;
@@ -307,62 +370,105 @@ class ProgramD3D : public ProgramImpl
typedef std::map<std::string, D3DUniform *> D3DUniformMap;
- void defineUniformsAndAssignRegisters();
+ void defineUniformsAndAssignRegisters(const gl::Context *context);
void defineUniformBase(const gl::Shader *shader,
const sh::Uniform &uniform,
D3DUniformMap *uniformMap);
+ void defineStructUniformFields(GLenum shaderType,
+ const std::vector<sh::ShaderVariable> &fields,
+ const std::string &namePrefix,
+ sh::HLSLBlockEncoder *encoder,
+ D3DUniformMap *uniformMap);
+ void defineArrayOfStructsUniformFields(GLenum shaderType,
+ const sh::ShaderVariable &uniform,
+ unsigned int arrayNestingIndex,
+ const std::string &prefix,
+ sh::HLSLBlockEncoder *encoder,
+ D3DUniformMap *uniformMap);
+ void defineArrayUniformElements(GLenum shaderType,
+ const sh::ShaderVariable &uniform,
+ const std::string &fullName,
+ sh::HLSLBlockEncoder *encoder,
+ D3DUniformMap *uniformMap);
void defineUniform(GLenum shaderType,
const sh::ShaderVariable &uniform,
const std::string &fullName,
sh::HLSLBlockEncoder *encoder,
D3DUniformMap *uniformMap);
void assignAllSamplerRegisters();
- void assignSamplerRegisters(const D3DUniform *d3dUniform);
+ void assignSamplerRegisters(size_t uniformIndex);
static void AssignSamplers(unsigned int startSamplerIndex,
- GLenum samplerType,
+ const gl::UniformTypeInfo &typeInfo,
unsigned int samplerCount,
std::vector<Sampler> &outSamplers,
GLuint *outUsedRange);
+ template <typename DestT>
+ void getUniformInternal(GLint location, DestT *dataOut) const;
+
+ template <typename T>
+ void setUniformImpl(const gl::VariableLocation &locationInfo,
+ GLsizei count,
+ const T *v,
+ uint8_t *targetData,
+ GLenum uniformType);
+
template <typename T>
- void setUniform(GLint location, GLsizei count, const T *v, GLenum targetUniformType);
+ void setUniformInternal(GLint location, GLsizei count, const T *v, GLenum uniformType);
template <int cols, int rows>
- void setUniformMatrixfv(GLint location,
- GLsizei count,
- GLboolean transpose,
- const GLfloat *value,
- GLenum targetUniformType);
+ bool setUniformMatrixfvImpl(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ uint8_t *targetData,
+ GLenum targetUniformType);
- LinkResult compileProgramExecutables(const gl::Data &data, gl::InfoLog &infoLog);
+ template <int cols, int rows>
+ void setUniformMatrixfvInternal(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ GLenum targetUniformType);
- void gatherTransformFeedbackVaryings(const VaryingPacking &varyings);
+ gl::LinkResult compileProgramExecutables(const gl::Context *context, gl::InfoLog &infoLog);
+ gl::LinkResult compileComputeExecutable(const gl::Context *context, gl::InfoLog &infoLog);
+
+ void gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyings,
+ const BuiltinInfo &builtins);
D3DUniform *getD3DUniformByName(const std::string &name);
D3DUniform *getD3DUniformFromLocation(GLint location);
+ const D3DUniform *getD3DUniformFromLocation(GLint location) const;
- void initSemanticIndex();
- void initAttributesByLayout();
+ void initAttribLocationsToD3DSemantic(const gl::Context *context);
void reset();
- void assignUniformBlockRegisters();
+ void initializeUniformBlocks();
+
+ void updateCachedInputLayoutFromShader(const gl::Context *context);
+ void updateCachedOutputLayoutFromShader();
+ void updateCachedVertexExecutableIndex();
+ void updateCachedPixelExecutableIndex();
- void initUniformBlockInfo();
- size_t getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock);
+ void linkResources(const gl::Context *context, const gl::ProgramLinkedResources &resources);
RendererD3D *mRenderer;
DynamicHLSL *mDynamicHLSL;
- std::vector<VertexExecutable *> mVertexExecutables;
- std::vector<PixelExecutable *> mPixelExecutables;
- std::vector<ShaderExecutableD3D *> mGeometryExecutables;
+ std::vector<std::unique_ptr<VertexExecutable>> mVertexExecutables;
+ std::vector<std::unique_ptr<PixelExecutable>> mPixelExecutables;
+ std::vector<std::unique_ptr<ShaderExecutableD3D>> mGeometryExecutables;
+ std::unique_ptr<ShaderExecutableD3D> mComputeExecutable;
std::string mVertexHLSL;
- D3DCompilerWorkarounds mVertexWorkarounds;
+ angle::CompilerWorkaroundsD3D mVertexWorkarounds;
std::string mPixelHLSL;
- D3DCompilerWorkarounds mPixelWorkarounds;
+ angle::CompilerWorkaroundsD3D mPixelWorkarounds;
bool mUsesFragDepth;
+ bool mHasANGLEMultiviewEnabled;
+ bool mUsesViewID;
std::vector<PixelShaderOutputVariable> mPixelShaderKey;
// Common code for all dynamic geometry shaders. Consists mainly of the GS input and output
@@ -373,20 +479,23 @@ class ProgramD3D : public ProgramImpl
bool mUsesPointSize;
bool mUsesFlatInterpolation;
- UniformStorageD3D *mVertexUniformStorage;
- UniformStorageD3D *mFragmentUniformStorage;
+ std::unique_ptr<UniformStorageD3D> mVertexUniformStorage;
+ std::unique_ptr<UniformStorageD3D> mFragmentUniformStorage;
+ std::unique_ptr<UniformStorageD3D> mComputeUniformStorage;
std::vector<Sampler> mSamplersPS;
std::vector<Sampler> mSamplersVS;
+ std::vector<Sampler> mSamplersCS;
GLuint mUsedVertexSamplerRange;
GLuint mUsedPixelSamplerRange;
+ GLuint mUsedComputeSamplerRange;
bool mDirtySamplerMapping;
- // Cache for getPixelExecutableForFramebuffer
- std::vector<GLenum> mPixelShaderOutputFormatCache;
+ // Cache for pixel shader output layout to save reallocations.
+ std::vector<GLenum> mPixelShaderOutputLayoutCache;
+ Optional<size_t> mCachedPixelExecutableIndex;
- SemanticIndexArray mSemanticIndexes;
- SemanticIndexArray mAttributesByLayout;
+ AttribIndexArray mAttribLocationToD3DSemantic;
unsigned int mSerial;
@@ -394,17 +503,21 @@ class ProgramD3D : public ProgramImpl
std::vector<GLint> mFragmentUBOCache;
VertexExecutable::Signature mCachedVertexSignature;
gl::InputLayout mCachedInputLayout;
+ Optional<size_t> mCachedVertexExecutableIndex;
std::vector<D3DVarying> mStreamOutVaryings;
std::vector<D3DUniform *> mD3DUniforms;
std::vector<D3DUniformBlock> mD3DUniformBlocks;
- std::map<std::string, sh::BlockMemberInfo> mBlockInfo;
- std::map<std::string, size_t> mBlockDataSizes;
+ bool mVertexUniformsDirty;
+ bool mFragmentUniformsDirty;
+ bool mComputeUniformsDirty;
static unsigned int issueSerial();
static unsigned int mCurrentSerial;
+
+ Serial mCurrentVertexArrayStateSerial;
};
-}
+} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h
index b2d895d9c6..fde96133b0 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h
@@ -21,7 +21,7 @@ class RenderTargetD3D : public FramebufferAttachmentRenderTarget
{
public:
RenderTargetD3D();
- virtual ~RenderTargetD3D();
+ ~RenderTargetD3D() override;
virtual GLsizei getWidth() const = 0;
virtual GLsizei getHeight() const = 0;
@@ -29,10 +29,14 @@ class RenderTargetD3D : public FramebufferAttachmentRenderTarget
virtual GLenum getInternalFormat() const = 0;
virtual GLsizei getSamples() const = 0;
gl::Extents getExtents() const { return gl::Extents(getWidth(), getHeight(), getDepth()); }
+ bool isMultisampled() const { return getSamples() > 0; }
virtual unsigned int getSerial() const;
static unsigned int issueSerials(unsigned int count);
+ // Only currently applies to D3D11.
+ virtual void signalDirty(const gl::Context *context) {}
+
private:
const unsigned int mSerial;
static unsigned int mCurrentSerial;
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp
index 991801a091..d799e0b992 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp
@@ -27,12 +27,25 @@ RenderbufferD3D::~RenderbufferD3D()
mImage = nullptr;
}
-gl::Error RenderbufferD3D::setStorage(GLenum internalformat, size_t width, size_t height)
+gl::Error RenderbufferD3D::onDestroy(const gl::Context *context)
{
- return setStorageMultisample(0, internalformat, width, height);
+ deleteRenderTarget(context);
+ return gl::NoError();
}
-gl::Error RenderbufferD3D::setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height)
+gl::Error RenderbufferD3D::setStorage(const gl::Context *context,
+ GLenum internalformat,
+ size_t width,
+ size_t height)
+{
+ return setStorageMultisample(context, 0, internalformat, width, height);
+}
+
+gl::Error RenderbufferD3D::setStorageMultisample(const gl::Context *context,
+ size_t samples,
+ GLenum internalformat,
+ size_t width,
+ size_t height)
{
// If the renderbuffer parameters are queried, the calling function
// will expect one of the valid renderbuffer formats for use in
@@ -48,54 +61,70 @@ gl::Error RenderbufferD3D::setStorageMultisample(size_t samples, GLenum internal
// the specified storage.
// Because ES 3.0 already knows the exact number of supported samples, it would already have been
// validated and generated GL_INVALID_VALUE.
- const gl::TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(creationFormat);
+ const gl::TextureCaps &formatCaps = mRenderer->getNativeTextureCaps().get(creationFormat);
if (samples > formatCaps.getMaxSamples())
{
- return gl::Error(GL_OUT_OF_MEMORY, "Renderbuffer format does not support %u samples, %u is the maximum.",
- samples, formatCaps.getMaxSamples());
+ return gl::OutOfMemory() << "Renderbuffer format does not support " << samples
+ << " samples, " << formatCaps.getMaxSamples()
+ << " is the maximum.";
}
- RenderTargetD3D *newRT = NULL;
- gl::Error error =
- mRenderer->createRenderTarget(static_cast<int>(width), static_cast<int>(height),
- creationFormat, static_cast<GLsizei>(samples), &newRT);
- if (error.isError())
- {
- return error;
- }
+ RenderTargetD3D *newRT = nullptr;
+ ANGLE_TRY(mRenderer->createRenderTarget(static_cast<int>(width), static_cast<int>(height),
+ creationFormat, static_cast<GLsizei>(samples), &newRT));
- SafeDelete(mRenderTarget);
+ deleteRenderTarget(context);
mImage = nullptr;
mRenderTarget = newRT;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error RenderbufferD3D::setStorageEGLImageTarget(egl::Image *image)
+gl::Error RenderbufferD3D::setStorageEGLImageTarget(const gl::Context *context, egl::Image *image)
{
mImage = GetImplAs<EGLImageD3D>(image);
- SafeDelete(mRenderTarget);
+ deleteRenderTarget(context);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error RenderbufferD3D::getRenderTarget(RenderTargetD3D **outRenderTarget)
+gl::Error RenderbufferD3D::getRenderTarget(const gl::Context *context,
+ RenderTargetD3D **outRenderTarget)
{
if (mImage)
{
- return mImage->getRenderTarget(outRenderTarget);
+ return mImage->getRenderTarget(context, outRenderTarget);
}
else
{
*outRenderTarget = mRenderTarget;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
}
-gl::Error RenderbufferD3D::getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target,
+gl::Error RenderbufferD3D::getAttachmentRenderTarget(const gl::Context *context,
+ GLenum /*binding*/,
+ const gl::ImageIndex & /*imageIndex*/,
FramebufferAttachmentRenderTarget **rtOut)
{
- return getRenderTarget(reinterpret_cast<RenderTargetD3D **>(rtOut));
+ return getRenderTarget(context, reinterpret_cast<RenderTargetD3D **>(rtOut));
}
+void RenderbufferD3D::deleteRenderTarget(const gl::Context *context)
+{
+ if (mRenderTarget)
+ {
+ mRenderTarget->signalDirty(context);
+ SafeDelete(mRenderTarget);
+ }
}
+
+gl::Error RenderbufferD3D::initializeContents(const gl::Context *context,
+ const gl::ImageIndex &imageIndex)
+{
+ RenderTargetD3D *renderTarget = nullptr;
+ ANGLE_TRY(getRenderTarget(context, &renderTarget));
+ return mRenderer->initRenderTarget(renderTarget);
+}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h
index 20f6a10b2d..b50eff7db7 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h
@@ -25,20 +25,33 @@ class RenderbufferD3D : public RenderbufferImpl
{
public:
RenderbufferD3D(RendererD3D *renderer);
- virtual ~RenderbufferD3D();
+ ~RenderbufferD3D() override;
- gl::Error setStorage(GLenum internalformat, size_t width, size_t height) override;
- gl::Error setStorageMultisample(size_t samples,
+ gl::Error onDestroy(const gl::Context *context) override;
+
+ gl::Error setStorage(const gl::Context *context,
+ GLenum internalformat,
+ size_t width,
+ size_t height) override;
+ gl::Error setStorageMultisample(const gl::Context *context,
+ size_t samples,
GLenum internalformat,
size_t width,
size_t height) override;
- gl::Error setStorageEGLImageTarget(egl::Image *image) override;
+ gl::Error setStorageEGLImageTarget(const gl::Context *context, egl::Image *image) override;
- gl::Error getRenderTarget(RenderTargetD3D **outRenderTarget);
- gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target,
+ gl::Error getRenderTarget(const gl::Context *context, RenderTargetD3D **outRenderTarget);
+ gl::Error getAttachmentRenderTarget(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex,
FramebufferAttachmentRenderTarget **rtOut) override;
+ gl::Error initializeContents(const gl::Context *context,
+ const gl::ImageIndex &imageIndex) override;
+
private:
+ void deleteRenderTarget(const gl::Context *context);
+
RendererD3D *mRenderer;
RenderTargetD3D *mRenderTarget;
EGLImageD3D *mImage;
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp
index 105587f62c..2167200a91 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp
@@ -8,43 +8,39 @@
#include "libANGLE/renderer/d3d/RendererD3D.h"
-#include "common/debug.h"
#include "common/MemoryBuffer.h"
+#include "common/debug.h"
#include "common/utilities.h"
+#include "libANGLE/Context.h"
#include "libANGLE/Display.h"
-#include "libANGLE/formatutils.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/ImageIndex.h"
+#include "libANGLE/ResourceManager.h"
+#include "libANGLE/State.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/TextureImpl.h"
#include "libANGLE/renderer/d3d/BufferD3D.h"
#include "libANGLE/renderer/d3d/DeviceD3D.h"
#include "libANGLE/renderer/d3d/DisplayD3D.h"
#include "libANGLE/renderer/d3d/IndexDataManager.h"
#include "libANGLE/renderer/d3d/ProgramD3D.h"
#include "libANGLE/renderer/d3d/SamplerD3D.h"
-#include "libANGLE/ResourceManager.h"
-#include "libANGLE/State.h"
-#include "libANGLE/VertexArray.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
namespace rx
{
-namespace
-{
-// If we request a scratch buffer requesting a smaller size this many times,
-// release and recreate the scratch buffer. This ensures we don't have a
-// degenerate case where we are stuck hogging memory.
-const int ScratchMemoryBufferLifetime = 1000;
-
-} // anonymous namespace
-
RendererD3D::RendererD3D(egl::Display *display)
: mDisplay(display),
- mDeviceLost(false),
- mAnnotator(nullptr),
mPresentPathFastEnabled(false),
- mScratchMemoryBufferResetCounter(0),
+ mCapsInitialized(false),
mWorkaroundsInitialized(false),
- mDisjoint(false)
+ mDisjoint(false),
+ mDeviceLost(false),
+ mWorkerThreadPool(4)
{
}
@@ -55,451 +51,29 @@ RendererD3D::~RendererD3D()
void RendererD3D::cleanup()
{
- mScratchMemoryBuffer.resize(0);
- for (auto &incompleteTexture : mIncompleteTextures)
- {
- incompleteTexture.second.set(NULL);
- }
- mIncompleteTextures.clear();
-
- if (mAnnotator != nullptr)
- {
- gl::UninitializeDebugAnnotations();
- SafeDelete(mAnnotator);
- }
-}
-
-SamplerImpl *RendererD3D::createSampler()
-{
- return new SamplerD3D();
-}
-
-gl::Error RendererD3D::drawArrays(const gl::Data &data, GLenum mode, GLint first, GLsizei count)
-{
- return genericDrawArrays(data, mode, first, count, 0);
-}
-
-gl::Error RendererD3D::drawArraysInstanced(const gl::Data &data,
- GLenum mode,
- GLint first,
- GLsizei count,
- GLsizei instanceCount)
-{
- return genericDrawArrays(data, mode, first, count, instanceCount);
-}
-
-gl::Error RendererD3D::drawElements(const gl::Data &data,
- GLenum mode,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- const gl::IndexRange &indexRange)
-{
- return genericDrawElements(data, mode, count, type, indices, 0, indexRange);
-}
-
-gl::Error RendererD3D::drawElementsInstanced(const gl::Data &data,
- GLenum mode,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- GLsizei instances,
- const gl::IndexRange &indexRange)
-{
- return genericDrawElements(data, mode, count, type, indices, instances, indexRange);
-}
-
-gl::Error RendererD3D::drawRangeElements(const gl::Data &data,
- GLenum mode,
- GLuint start,
- GLuint end,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- const gl::IndexRange &indexRange)
-{
- return genericDrawElements(data, mode, count, type, indices, 0, indexRange);
-}
-
-gl::Error RendererD3D::genericDrawElements(const gl::Data &data,
- GLenum mode,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- GLsizei instances,
- const gl::IndexRange &indexRange)
-{
- gl::Program *program = data.state->getProgram();
- ASSERT(program != nullptr);
- ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
- bool usesPointSize = programD3D->usesPointSize();
-
- programD3D->updateSamplerMapping();
-
- gl::Error error = generateSwizzles(data);
- if (error.isError())
- {
- return error;
- }
-
- if (!applyPrimitiveType(mode, count, usesPointSize))
- {
- return gl::Error(GL_NO_ERROR);
- }
-
- error = updateState(data, mode);
- if (error.isError())
- {
- return error;
- }
-
- TranslatedIndexData indexInfo;
- indexInfo.indexRange = indexRange;
-
- error = applyIndexBuffer(data, indices, count, mode, type, &indexInfo);
- if (error.isError())
- {
- return error;
- }
-
- applyTransformFeedbackBuffers(*data.state);
- // Transform feedback is not allowed for DrawElements, this error should have been caught at the API validation
- // layer.
- ASSERT(!data.state->isTransformFeedbackActiveUnpaused());
-
- size_t vertexCount = indexInfo.indexRange.vertexCount();
- error = applyVertexBuffer(*data.state, mode, static_cast<GLsizei>(indexInfo.indexRange.start),
- static_cast<GLsizei>(vertexCount), instances, &indexInfo);
- if (error.isError())
- {
- return error;
- }
-
- error = applyTextures(data);
- if (error.isError())
- {
- return error;
- }
-
- error = applyShaders(data, mode);
- if (error.isError())
- {
- return error;
- }
-
- error = programD3D->applyUniformBuffers(data);
- if (error.isError())
- {
- return error;
- }
-
- if (!skipDraw(data, mode))
- {
- error = drawElementsImpl(data, indexInfo, mode, count, type, indices, instances);
- if (error.isError())
- {
- return error;
- }
- }
-
- return gl::Error(GL_NO_ERROR);
-}
-
-gl::Error RendererD3D::genericDrawArrays(const gl::Data &data,
- GLenum mode,
- GLint first,
- GLsizei count,
- GLsizei instances)
-{
- gl::Program *program = data.state->getProgram();
- ASSERT(program != nullptr);
- ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
- bool usesPointSize = programD3D->usesPointSize();
-
- programD3D->updateSamplerMapping();
-
- gl::Error error = generateSwizzles(data);
- if (error.isError())
- {
- return error;
- }
-
- if (!applyPrimitiveType(mode, count, usesPointSize))
- {
- return gl::Error(GL_NO_ERROR);
- }
-
- error = updateState(data, mode);
- if (error.isError())
- {
- return error;
- }
-
- applyTransformFeedbackBuffers(*data.state);
-
- error = applyVertexBuffer(*data.state, mode, first, count, instances, nullptr);
- if (error.isError())
- {
- return error;
- }
-
- error = applyTextures(data);
- if (error.isError())
- {
- return error;
- }
-
- error = applyShaders(data, mode);
- if (error.isError())
- {
- return error;
- }
-
- error = programD3D->applyUniformBuffers(data);
- if (error.isError())
- {
- return error;
- }
-
- if (!skipDraw(data, mode))
- {
- error = drawArraysImpl(data, mode, count, instances);
- if (error.isError())
- {
- return error;
- }
-
- if (data.state->isTransformFeedbackActiveUnpaused())
- {
- markTransformFeedbackUsage(data);
- }
- }
-
- return gl::Error(GL_NO_ERROR);
-}
-
-gl::Error RendererD3D::generateSwizzles(const gl::Data &data, gl::SamplerType type)
-{
- ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram());
-
- unsigned int samplerRange = static_cast<unsigned int>(programD3D->getUsedSamplerRange(type));
-
- for (unsigned int i = 0; i < samplerRange; i++)
- {
- GLenum textureType = programD3D->getSamplerTextureType(type, i);
- GLint textureUnit = programD3D->getSamplerMapping(type, i, *data.caps);
- if (textureUnit != -1)
- {
- gl::Texture *texture = data.state->getSamplerTexture(textureUnit, textureType);
- ASSERT(texture);
- if (texture->getTextureState().swizzleRequired())
- {
- gl::Error error = generateSwizzle(texture);
- if (error.isError())
- {
- return error;
- }
- }
- }
- }
-
- return gl::Error(GL_NO_ERROR);
-}
-
-gl::Error RendererD3D::generateSwizzles(const gl::Data &data)
-{
- gl::Error error = generateSwizzles(data, gl::SAMPLER_VERTEX);
- if (error.isError())
- {
- return error;
- }
-
- error = generateSwizzles(data, gl::SAMPLER_PIXEL);
- if (error.isError())
- {
- return error;
- }
-
- return gl::Error(GL_NO_ERROR);
-}
-
-unsigned int RendererD3D::GetBlendSampleMask(const gl::Data &data, int samples)
-{
- unsigned int mask = 0;
- if (data.state->isSampleCoverageEnabled())
- {
- GLclampf coverageValue = data.state->getSampleCoverageValue();
- if (coverageValue != 0)
- {
- float threshold = 0.5f;
-
- for (int i = 0; i < samples; ++i)
- {
- mask <<= 1;
-
- if ((i + 1) * coverageValue >= threshold)
- {
- threshold += 1.0f;
- mask |= 1;
- }
- }
- }
-
- bool coverageInvert = data.state->getSampleCoverageInvert();
- if (coverageInvert)
- {
- mask = ~mask;
- }
- }
- else
- {
- mask = 0xFFFFFFFF;
- }
-
- return mask;
-}
-
-// Applies the shaders and shader constants to the Direct3D device
-gl::Error RendererD3D::applyShaders(const gl::Data &data, GLenum drawMode)
-{
- gl::Program *program = data.state->getProgram();
- ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
- programD3D->updateCachedInputLayout(*data.state);
-
- gl::Error error = applyShadersImpl(data, drawMode);
- if (error.isError())
- {
- return error;
- }
-
- return programD3D->applyUniforms(drawMode);
-}
-
-// For each Direct3D sampler of either the pixel or vertex stage,
-// looks up the corresponding OpenGL texture image unit and texture type,
-// and sets the texture and its addressing/filtering state (or NULL when inactive).
-// Sampler mapping needs to be up-to-date on the program object before this is called.
-gl::Error RendererD3D::applyTextures(const gl::Data &data, gl::SamplerType shaderType,
- const FramebufferTextureArray &framebufferTextures, size_t framebufferTextureCount)
-{
- ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram());
-
- ASSERT(!programD3D->isSamplerMappingDirty());
-
- unsigned int samplerRange = programD3D->getUsedSamplerRange(shaderType);
- for (unsigned int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
- {
- GLenum textureType = programD3D->getSamplerTextureType(shaderType, samplerIndex);
- GLint textureUnit = programD3D->getSamplerMapping(shaderType, samplerIndex, *data.caps);
- if (textureUnit != -1)
- {
- gl::Texture *texture = data.state->getSamplerTexture(textureUnit, textureType);
- ASSERT(texture);
-
- gl::Sampler *samplerObject = data.state->getSampler(textureUnit);
-
- const gl::SamplerState &samplerState =
- samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState();
-
- // TODO: std::binary_search may become unavailable using older versions of GCC
- if (texture->isSamplerComplete(samplerState, data) &&
- !std::binary_search(framebufferTextures.begin(),
- framebufferTextures.begin() + framebufferTextureCount, texture))
- {
- gl::Error error = setSamplerState(shaderType, samplerIndex, texture, samplerState);
- if (error.isError())
- {
- return error;
- }
-
- error = setTexture(shaderType, samplerIndex, texture);
- if (error.isError())
- {
- return error;
- }
- }
- else
- {
- // Texture is not sampler complete or it is in use by the framebuffer. Bind the incomplete texture.
- gl::Texture *incompleteTexture = getIncompleteTexture(textureType);
-
- gl::Error error = setSamplerState(shaderType, samplerIndex, incompleteTexture,
- incompleteTexture->getSamplerState());
- if (error.isError())
- {
- return error;
- }
-
- error = setTexture(shaderType, samplerIndex, incompleteTexture);
- if (error.isError())
- {
- return error;
- }
- }
- }
- else
- {
- // No texture bound to this slot even though it is used by the shader, bind a NULL texture
- gl::Error error = setTexture(shaderType, samplerIndex, NULL);
- if (error.isError())
- {
- return error;
- }
- }
- }
-
- // Set all the remaining textures to NULL
- size_t samplerCount = (shaderType == gl::SAMPLER_PIXEL) ? data.caps->maxTextureImageUnits
- : data.caps->maxVertexTextureImageUnits;
- clearTextures(shaderType, samplerRange, samplerCount);
-
- return gl::Error(GL_NO_ERROR);
-}
-
-gl::Error RendererD3D::applyTextures(const gl::Data &data)
-{
- FramebufferTextureArray framebufferTextures;
- size_t framebufferSerialCount = getBoundFramebufferTextures(data, &framebufferTextures);
-
- gl::Error error = applyTextures(data, gl::SAMPLER_VERTEX, framebufferTextures, framebufferSerialCount);
- if (error.isError())
- {
- return error;
- }
-
- error = applyTextures(data, gl::SAMPLER_PIXEL, framebufferTextures, framebufferSerialCount);
- if (error.isError())
- {
- return error;
- }
-
- return gl::Error(GL_NO_ERROR);
+ mIncompleteTextures.onDestroy(mDisplay->getProxyContext());
}
-bool RendererD3D::skipDraw(const gl::Data &data, GLenum drawMode)
+bool RendererD3D::skipDraw(const gl::State &glState, GLenum drawMode)
{
- const gl::State &state = *data.state;
-
if (drawMode == GL_POINTS)
{
- bool usesPointSize = GetImplAs<ProgramD3D>(state.getProgram())->usesPointSize();
+ bool usesPointSize = GetImplAs<ProgramD3D>(glState.getProgram())->usesPointSize();
// ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
// which affects varying interpolation. Since the value of gl_PointSize is
// undefined when not written, just skip drawing to avoid unexpected results.
- if (!usesPointSize && !state.isTransformFeedbackActiveUnpaused())
+ if (!usesPointSize && !glState.isTransformFeedbackActiveUnpaused())
{
- // This is stictly speaking not an error, but developers should be
- // notified of risking undefined behavior.
- ERR("Point rendering without writing to gl_PointSize.");
-
+ // Notify developers of risking undefined behavior.
+ WARN() << "Point rendering without writing to gl_PointSize.";
return true;
}
}
else if (gl::IsTriangleMode(drawMode))
{
- if (state.getRasterizerState().cullFace &&
- state.getRasterizerState().cullMode == GL_FRONT_AND_BACK)
+ if (glState.getRasterizerState().cullFace &&
+ glState.getRasterizerState().cullMode == gl::CullFaceMode::FrontAndBack)
{
return true;
}
@@ -508,196 +82,179 @@ bool RendererD3D::skipDraw(const gl::Data &data, GLenum drawMode)
return false;
}
-void RendererD3D::markTransformFeedbackUsage(const gl::Data &data)
+gl::Error RendererD3D::getIncompleteTexture(const gl::Context *context,
+ GLenum type,
+ gl::Texture **textureOut)
{
- const gl::TransformFeedback *transformFeedback = data.state->getCurrentTransformFeedback();
- for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
- {
- const OffsetBindingPointer<gl::Buffer> &binding = transformFeedback->getIndexedBuffer(i);
- if (binding.get() != nullptr)
- {
- BufferD3D *bufferD3D = GetImplAs<BufferD3D>(binding.get());
- bufferD3D->markTransformFeedbackUsage();
- }
- }
+ return mIncompleteTextures.getIncompleteTexture(context, type, this, textureOut);
}
-size_t RendererD3D::getBoundFramebufferTextures(const gl::Data &data, FramebufferTextureArray *outTextureArray)
+GLenum RendererD3D::getResetStatus()
{
- size_t textureCount = 0;
-
- const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer();
- for (size_t i = 0; i < drawFramebuffer->getNumColorBuffers(); i++)
+ if (!mDeviceLost)
{
- const gl::FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i);
- if (attachment && attachment->type() == GL_TEXTURE)
+ if (testDeviceLost())
{
- (*outTextureArray)[textureCount++] = attachment->getTexture();
+ mDeviceLost = true;
+ notifyDeviceLost();
+ return GL_UNKNOWN_CONTEXT_RESET_EXT;
}
+ return GL_NO_ERROR;
}
- const gl::FramebufferAttachment *depthStencilAttachment = drawFramebuffer->getDepthOrStencilbuffer();
- if (depthStencilAttachment && depthStencilAttachment->type() == GL_TEXTURE)
+ if (testDeviceResettable())
{
- (*outTextureArray)[textureCount++] = depthStencilAttachment->getTexture();
+ return GL_NO_ERROR;
}
- std::sort(outTextureArray->begin(), outTextureArray->begin() + textureCount);
-
- return textureCount;
-}
-
-gl::Texture *RendererD3D::getIncompleteTexture(GLenum type)
-{
- if (mIncompleteTextures.find(type) == mIncompleteTextures.end())
- {
- const GLubyte color[] = { 0, 0, 0, 255 };
- const gl::Extents colorSize(1, 1, 1);
- const gl::PixelUnpackState unpack(1, 0);
- const gl::Box area(0, 0, 0, 1, 1, 1);
-
- // Skip the API layer to avoid needing to pass the Context and mess with dirty bits.
- gl::Texture *t =
- new gl::Texture(createTexture(type), std::numeric_limits<GLuint>::max(), type);
- t->setStorage(type, 1, GL_RGBA8, colorSize);
-
- if (type == GL_TEXTURE_CUBE_MAP)
- {
- for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; face++)
- {
- t->getImplementation()->setSubImage(face, 0, area, GL_RGBA8, GL_UNSIGNED_BYTE,
- unpack, color);
- }
- }
- else
- {
- t->getImplementation()->setSubImage(type, 0, area, GL_RGBA8, GL_UNSIGNED_BYTE, unpack,
- color);
- }
-
- mIncompleteTextures[type].set(t);
- }
-
- return mIncompleteTextures[type].get();
-}
-
-bool RendererD3D::isDeviceLost() const
-{
- return mDeviceLost;
+ return GL_UNKNOWN_CONTEXT_RESET_EXT;
}
void RendererD3D::notifyDeviceLost()
{
- mDeviceLost = true;
mDisplay->notifyDeviceLost();
}
std::string RendererD3D::getVendorString() const
{
- LUID adapterLuid = { 0 };
+ LUID adapterLuid = {0};
if (getLUID(&adapterLuid))
{
char adapterLuidString[64];
- sprintf_s(adapterLuidString, sizeof(adapterLuidString), "(adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart);
+ sprintf_s(adapterLuidString, sizeof(adapterLuidString), "(adapter LUID: %08x%08x)",
+ adapterLuid.HighPart, adapterLuid.LowPart);
return std::string(adapterLuidString);
}
return std::string("");
}
-gl::Error RendererD3D::getScratchMemoryBuffer(size_t requestedSize, MemoryBuffer **bufferOut)
+void RendererD3D::setGPUDisjoint()
{
- if (mScratchMemoryBuffer.size() == requestedSize)
- {
- mScratchMemoryBufferResetCounter = ScratchMemoryBufferLifetime;
- *bufferOut = &mScratchMemoryBuffer;
- return gl::Error(GL_NO_ERROR);
- }
-
- if (mScratchMemoryBuffer.size() > requestedSize)
- {
- mScratchMemoryBufferResetCounter--;
- }
+ mDisjoint = true;
+}
- if (mScratchMemoryBufferResetCounter <= 0 || mScratchMemoryBuffer.size() < requestedSize)
- {
- mScratchMemoryBuffer.resize(0);
- if (!mScratchMemoryBuffer.resize(requestedSize))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal buffer.");
- }
- mScratchMemoryBufferResetCounter = ScratchMemoryBufferLifetime;
- }
+GLint RendererD3D::getGPUDisjoint()
+{
+ bool disjoint = mDisjoint;
- ASSERT(mScratchMemoryBuffer.size() >= requestedSize);
+ // Disjoint flag is cleared when read
+ mDisjoint = false;
- *bufferOut = &mScratchMemoryBuffer;
- return gl::Error(GL_NO_ERROR);
+ return disjoint;
}
-void RendererD3D::insertEventMarker(GLsizei length, const char *marker)
+GLint64 RendererD3D::getTimestamp()
{
- std::vector<wchar_t> wcstring (length + 1);
- size_t convertedChars = 0;
- errno_t err = mbstowcs_s(&convertedChars, wcstring.data(), length + 1, marker, _TRUNCATE);
- if (err == 0)
- {
- getAnnotator()->setMarker(wcstring.data());
- }
+ // D3D has no way to get an actual timestamp reliably so 0 is returned
+ return 0;
}
-void RendererD3D::pushGroupMarker(GLsizei length, const char *marker)
+void RendererD3D::ensureCapsInitialized() const
{
- std::vector<wchar_t> wcstring(length + 1);
- size_t convertedChars = 0;
- errno_t err = mbstowcs_s(&convertedChars, wcstring.data(), length + 1, marker, _TRUNCATE);
- if (err == 0)
+ if (!mCapsInitialized)
{
- getAnnotator()->beginEvent(wcstring.data());
+ generateCaps(&mNativeCaps, &mNativeTextureCaps, &mNativeExtensions, &mNativeLimitations);
+ mCapsInitialized = true;
}
}
-void RendererD3D::popGroupMarker()
+const gl::Caps &RendererD3D::getNativeCaps() const
{
- getAnnotator()->endEvent();
+ ensureCapsInitialized();
+ return mNativeCaps;
}
-void RendererD3D::setGPUDisjoint()
+const gl::TextureCapsMap &RendererD3D::getNativeTextureCaps() const
{
- mDisjoint = true;
+ ensureCapsInitialized();
+ return mNativeTextureCaps;
}
-GLint RendererD3D::getGPUDisjoint()
+const gl::Extensions &RendererD3D::getNativeExtensions() const
{
- bool disjoint = mDisjoint;
+ ensureCapsInitialized();
+ return mNativeExtensions;
+}
- // Disjoint flag is cleared when read
- mDisjoint = false;
+const gl::Limitations &RendererD3D::getNativeLimitations() const
+{
+ ensureCapsInitialized();
+ return mNativeLimitations;
+}
- return disjoint;
+angle::WorkerThreadPool *RendererD3D::getWorkerThreadPool()
+{
+ return &mWorkerThreadPool;
}
-GLint64 RendererD3D::getTimestamp()
+Serial RendererD3D::generateSerial()
{
- // D3D has no way to get an actual timestamp reliably so 0 is returned
- return 0;
+ return mSerialFactory.generate();
}
-void RendererD3D::onMakeCurrent(const gl::Data &data)
+bool InstancedPointSpritesActive(ProgramD3D *programD3D, GLenum mode)
{
+ return programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation() &&
+ mode == GL_POINTS;
}
-void RendererD3D::initializeDebugAnnotator()
+gl::Error RendererD3D::initRenderTarget(RenderTargetD3D *renderTarget)
{
- createAnnotator();
- ASSERT(mAnnotator);
- gl::InitializeDebugAnnotations(mAnnotator);
+ return clearRenderTarget(renderTarget, gl::ColorF(0, 0, 0, 0), 1, 0);
}
-gl::DebugAnnotator *RendererD3D::getAnnotator()
+gl::Error RendererD3D::initializeMultisampleTextureToBlack(const gl::Context *context,
+ gl::Texture *glTexture)
{
- ASSERT(mAnnotator);
- return mAnnotator;
+ ASSERT(glTexture->getTarget() == GL_TEXTURE_2D_MULTISAMPLE);
+ TextureD3D *textureD3D = GetImplAs<TextureD3D>(glTexture);
+ gl::ImageIndex index = gl::ImageIndex::Make2DMultisample();
+ RenderTargetD3D *renderTarget = nullptr;
+ ANGLE_TRY(textureD3D->getRenderTarget(context, index, &renderTarget));
+ return clearRenderTarget(renderTarget, gl::ColorF(0.0f, 0.0f, 0.0f, 1.0f), 1.0f, 0);
}
+
+unsigned int GetBlendSampleMask(const gl::State &glState, int samples)
+{
+ unsigned int mask = 0;
+ if (glState.isSampleCoverageEnabled())
+ {
+ GLfloat coverageValue = glState.getSampleCoverageValue();
+ if (coverageValue != 0)
+ {
+ float threshold = 0.5f;
+
+ for (int i = 0; i < samples; ++i)
+ {
+ mask <<= 1;
+
+ if ((i + 1) * coverageValue >= threshold)
+ {
+ threshold += 1.0f;
+ mask |= 1;
+ }
+ }
+ }
+
+ bool coverageInvert = glState.getSampleCoverageInvert();
+ if (coverageInvert)
+ {
+ mask = ~mask;
+ }
+ }
+ else
+ {
+ mask = 0xFFFFFFFF;
+ }
+
+ if (glState.isSampleMaskEnabled())
+ {
+ mask &= glState.getSampleMaskWord(0);
+ }
+
+ return mask;
}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.h
index f956f037e2..dcc98f2ec6 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.h
@@ -9,19 +9,21 @@
#ifndef LIBANGLE_RENDERER_D3D_RENDERERD3D_H_
#define LIBANGLE_RENDERER_D3D_RENDERERD3D_H_
-#include "common/debug.h"
+#include <array>
+
+#include "common/Color.h"
#include "common/MemoryBuffer.h"
-#include "libANGLE/Data.h"
+#include "common/debug.h"
+#include "libANGLE/ContextState.h"
#include "libANGLE/Device.h"
+#include "libANGLE/Version.h"
+#include "libANGLE/WorkerThread.h"
+#include "libANGLE/angletypes.h"
#include "libANGLE/formatutils.h"
-#include "libANGLE/renderer/Renderer.h"
#include "libANGLE/renderer/d3d/VertexDataManager.h"
#include "libANGLE/renderer/d3d/formatutilsD3D.h"
-#include "libANGLE/renderer/d3d/WorkaroundsD3D.h"
-#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h"
-
-//FIXME(jmadill): std::array is currently prohibited by Chromium style guide
-#include <array>
+#include "libANGLE/renderer/renderer_utils.h"
+#include "platform/WorkaroundsD3D.h"
namespace egl
{
@@ -30,7 +32,7 @@ class ConfigSet;
namespace gl
{
-class DebugAnnotator;
+class FramebufferState;
class InfoLog;
class Texture;
struct LinkedVarying;
@@ -38,28 +40,24 @@ struct LinkedVarying;
namespace rx
{
+class ContextImpl;
struct D3DUniform;
struct D3DVarying;
class DeviceD3D;
class EGLImageD3D;
+class FramebufferImpl;
class ImageD3D;
class IndexBuffer;
+class NativeWindowD3D;
class ProgramD3D;
class RenderTargetD3D;
class ShaderExecutableD3D;
class SwapChainD3D;
class TextureStorage;
+struct TranslatedIndexData;
class UniformStorageD3D;
class VertexBuffer;
-enum ShaderType
-{
- SHADER_VERTEX,
- SHADER_PIXEL,
- SHADER_GEOMETRY,
- SHADER_TYPE_MAX
-};
-
struct DeviceIdentifier
{
UINT VendorId;
@@ -76,7 +74,7 @@ enum RendererClass
};
// Useful for unit testing
-class BufferFactoryD3D
+class BufferFactoryD3D : angle::NonCopyable
{
public:
BufferFactoryD3D() {}
@@ -88,52 +86,32 @@ class BufferFactoryD3D
// TODO(jmadill): add VertexFormatCaps
virtual VertexConversionType getVertexConversionType(gl::VertexFormatType vertexFormatType) const = 0;
virtual GLenum getVertexComponentType(gl::VertexFormatType vertexFormatType) const = 0;
+
+ // Warning: you should ensure binding really matches attrib.bindingIndex before using this
+ // function.
+ virtual gl::ErrorOrResult<unsigned int> getVertexSpaceRequired(
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ GLsizei count,
+ GLsizei instances) const = 0;
};
-class RendererD3D : public Renderer, public BufferFactoryD3D
+using AttribIndexArray = std::array<int, gl::MAX_VERTEX_ATTRIBS>;
+
+class RendererD3D : public BufferFactoryD3D, public MultisampleTextureInitializer
{
public:
explicit RendererD3D(egl::Display *display);
- virtual ~RendererD3D();
+ ~RendererD3D() override;
virtual egl::Error initialize() = 0;
- virtual egl::ConfigSet generateConfigs() const = 0;
+ virtual egl::ConfigSet generateConfigs() = 0;
virtual void generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const = 0;
- gl::Error drawArrays(const gl::Data &data, GLenum mode, GLint first, GLsizei count) override;
- gl::Error drawArraysInstanced(const gl::Data &data,
- GLenum mode,
- GLint first,
- GLsizei count,
- GLsizei instanceCount) override;
-
- gl::Error drawElements(const gl::Data &data,
- GLenum mode,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- const gl::IndexRange &indexRange) override;
- gl::Error drawElementsInstanced(const gl::Data &data,
- GLenum mode,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- GLsizei instances,
- const gl::IndexRange &indexRange) override;
- gl::Error drawRangeElements(const gl::Data &data,
- GLenum mode,
- GLuint start,
- GLuint end,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- const gl::IndexRange &indexRange) override;
-
- bool isDeviceLost() const override;
- std::string getVendorString() const override;
-
- SamplerImpl *createSampler() override;
+ virtual ContextImpl *createContext(const gl::ContextState &state) = 0;
+
+ std::string getVendorString() const;
virtual int getMinorShaderModel() const = 0;
virtual std::string getShaderModelSuffix() const = 0;
@@ -141,204 +119,241 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
// Direct3D Specific methods
virtual DeviceIdentifier getAdapterIdentifier() const = 0;
- virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow,
+ virtual bool isValidNativeWindow(EGLNativeWindowType window) const = 0;
+ virtual NativeWindowD3D *createNativeWindow(EGLNativeWindowType window,
+ const egl::Config *config,
+ const egl::AttributeMap &attribs) const = 0;
+
+ virtual SwapChainD3D *createSwapChain(NativeWindowD3D *nativeWindow,
HANDLE shareHandle,
+ IUnknown *d3dTexture,
GLenum backBufferFormat,
GLenum depthBufferFormat,
- EGLint orientation) = 0;
-
- virtual gl::Error generateSwizzle(gl::Texture *texture) = 0;
- virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler) = 0;
- virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0;
-
- virtual gl::Error setUniformBuffers(const gl::Data &data,
- const std::vector<GLint> &vertexUniformBuffers,
- const std::vector<GLint> &fragmentUniformBuffers) = 0;
-
- virtual gl::Error updateState(const gl::Data &data, GLenum drawMode) = 0;
-
- virtual gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) = 0;
- virtual gl::Error applyUniforms(const ProgramD3D &programD3D,
- GLenum drawMode,
- const std::vector<D3DUniform *> &uniformArray) = 0;
- virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize) = 0;
- virtual gl::Error applyVertexBuffer(const gl::State &state,
- GLenum mode,
- GLint first,
- GLsizei count,
- GLsizei instances,
- TranslatedIndexData *indexInfo) = 0;
- virtual gl::Error applyIndexBuffer(const gl::Data &data,
- const GLvoid *indices,
- GLsizei count,
- GLenum mode,
- GLenum type,
- TranslatedIndexData *indexInfo) = 0;
- virtual void applyTransformFeedbackBuffers(const gl::State& state) = 0;
-
- virtual unsigned int getReservedVertexUniformVectors() const = 0;
- virtual unsigned int getReservedFragmentUniformVectors() const = 0;
- virtual unsigned int getReservedVertexUniformBuffers() const = 0;
- virtual unsigned int getReservedFragmentUniformBuffers() const = 0;
+ EGLint orientation,
+ EGLint samples) = 0;
+ virtual egl::Error getD3DTextureInfo(const egl::Config *configuration,
+ IUnknown *d3dTexture,
+ EGLint *width,
+ EGLint *height,
+ GLenum *fboFormat) const = 0;
+ virtual egl::Error validateShareHandle(const egl::Config *config,
+ HANDLE shareHandle,
+ const egl::AttributeMap &attribs) const = 0;
virtual int getMajorShaderModel() const = 0;
- const WorkaroundsD3D &getWorkarounds() const;
+ const angle::WorkaroundsD3D &getWorkarounds() const;
// Pixel operations
- virtual gl::Error copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- const gl::Offset &destOffset, TextureStorage *storage, GLint level) = 0;
- virtual gl::Error copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level) = 0;
- virtual gl::Error copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- const gl::Offset &destOffset, TextureStorage *storage, GLint level) = 0;
- virtual gl::Error copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- const gl::Offset &destOffset, TextureStorage *storage, GLint level) = 0;
+ virtual gl::Error copyImage2D(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level) = 0;
+ virtual gl::Error copyImageCube(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLenum target,
+ GLint level) = 0;
+ virtual gl::Error copyImage3D(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level) = 0;
+ virtual gl::Error copyImage2DArray(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level) = 0;
+
+ virtual gl::Error copyTexture(const gl::Context *context,
+ const gl::Texture *source,
+ GLint sourceLevel,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLenum destTarget,
+ GLint destLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha) = 0;
+ virtual gl::Error copyCompressedTexture(const gl::Context *context,
+ const gl::Texture *source,
+ GLint sourceLevel,
+ TextureStorage *storage,
+ GLint destLevel) = 0;
// RenderTarget creation
virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT) = 0;
virtual gl::Error createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) = 0;
// Shader operations
- virtual gl::Error loadExecutable(const void *function,
+ virtual gl::Error loadExecutable(const uint8_t *function,
size_t length,
- ShaderType type,
+ gl::ShaderType type,
const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers,
- ShaderExecutableD3D **outExecutable) = 0;
+ ShaderExecutableD3D **outExecutable) = 0;
virtual gl::Error compileToExecutable(gl::InfoLog &infoLog,
const std::string &shaderHLSL,
- ShaderType type,
+ gl::ShaderType type,
const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers,
- const D3DCompilerWorkarounds &workarounds,
+ const angle::CompilerWorkaroundsD3D &workarounds,
ShaderExecutableD3D **outExectuable) = 0;
+ virtual gl::Error ensureHLSLCompilerInitialized() = 0;
+
virtual UniformStorageD3D *createUniformStorage(size_t storageSize) = 0;
// Image operations
virtual ImageD3D *createImage() = 0;
- virtual gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) = 0;
- virtual gl::Error generateMipmapsUsingD3D(TextureStorage *storage,
- const gl::TextureState &textureState) = 0;
+ virtual gl::Error generateMipmap(const gl::Context *context,
+ ImageD3D *dest,
+ ImageD3D *source) = 0;
+ virtual gl::Error generateMipmapUsingD3D(const gl::Context *context,
+ TextureStorage *storage,
+ const gl::TextureState &textureState) = 0;
+ virtual gl::Error copyImage(const gl::Context *context,
+ ImageD3D *dest,
+ ImageD3D *source,
+ const gl::Rectangle &sourceRect,
+ const gl::Offset &destOffset,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha) = 0;
virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain) = 0;
- virtual TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage) = 0;
+ virtual TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage,
+ RenderTargetD3D *renderTargetD3D) = 0;
+ virtual TextureStorage *createTextureStorageExternal(
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc) = 0;
virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly) = 0;
virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) = 0;
virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0;
virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0;
+ virtual TextureStorage *createTextureStorage2DMultisample(GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ int samples,
+ bool fixedSampleLocations) = 0;
// Buffer-to-texture and Texture-to-buffer copies
virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const = 0;
- virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget,
- GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) = 0;
+ virtual gl::Error fastCopyBufferToTexture(const gl::Context *context,
+ const gl::PixelUnpackState &unpack,
+ unsigned int offset,
+ RenderTargetD3D *destRenderTarget,
+ GLenum destinationFormat,
+ GLenum sourcePixelsType,
+ const gl::Box &destArea) = 0;
// Device lost
- void notifyDeviceLost() override;
+ GLenum getResetStatus();
+ void notifyDeviceLost();
virtual bool resetDevice() = 0;
+ virtual bool testDeviceLost() = 0;
+ virtual bool testDeviceResettable() = 0;
+
virtual RendererClass getRendererClass() const = 0;
virtual void *getD3DDevice() = 0;
- gl::Error getScratchMemoryBuffer(size_t requestedSize, MemoryBuffer **bufferOut);
-
- // EXT_debug_marker
- void insertEventMarker(GLsizei length, const char *marker) override;
- void pushGroupMarker(GLsizei length, const char *marker) override;
- void popGroupMarker() override;
-
void setGPUDisjoint();
- GLint getGPUDisjoint() override;
- GLint64 getTimestamp() override;
-
- void onMakeCurrent(const gl::Data &data) override;
+ GLint getGPUDisjoint();
+ GLint64 getTimestamp();
- // In D3D11, faster than calling setTexture a jillion times
- virtual gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) = 0;
+ virtual gl::Error clearRenderTarget(RenderTargetD3D *renderTarget,
+ const gl::ColorF &clearColorValue,
+ const float clearDepthValue,
+ const unsigned int clearStencilValue) = 0;
virtual egl::Error getEGLDevice(DeviceImpl **device) = 0;
bool presentPathFastEnabled() const { return mPresentPathFastEnabled; }
+ // Stream creation
+ virtual StreamProducerImpl *createStreamProducerD3DTextureNV12(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs) = 0;
+
+ const gl::Caps &getNativeCaps() const;
+ const gl::TextureCapsMap &getNativeTextureCaps() const;
+ const gl::Extensions &getNativeExtensions() const;
+ const gl::Limitations &getNativeLimitations() const;
+
+ // Necessary hack for default framebuffers in D3D.
+ virtual FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) = 0;
+
+ virtual gl::Version getMaxSupportedESVersion() const = 0;
+
+ gl::Error initRenderTarget(RenderTargetD3D *renderTarget);
+
+ angle::WorkerThreadPool *getWorkerThreadPool();
+
+ gl::Error getIncompleteTexture(const gl::Context *context,
+ GLenum type,
+ gl::Texture **textureOut);
+
+ Serial generateSerial();
+
+ virtual bool canSelectViewInVertexShader() const = 0;
+
+ gl::Error initializeMultisampleTextureToBlack(const gl::Context *context,
+ gl::Texture *glTexture) override;
+
protected:
virtual bool getLUID(LUID *adapterLuid) const = 0;
- virtual gl::Error applyShadersImpl(const gl::Data &data, GLenum drawMode) = 0;
+ virtual void generateCaps(gl::Caps *outCaps,
+ gl::TextureCapsMap *outTextureCaps,
+ gl::Extensions *outExtensions,
+ gl::Limitations *outLimitations) const = 0;
void cleanup();
- virtual void createAnnotator() = 0;
-
- static unsigned int GetBlendSampleMask(const gl::Data &data, int samples);
- // dirtyPointer is a special value that will make the comparison with any valid pointer fail and force the renderer to re-apply the state.
+ bool skipDraw(const gl::State &glState, GLenum drawMode);
egl::Display *mDisplay;
- bool mDeviceLost;
-
- void initializeDebugAnnotator();
- gl::DebugAnnotator *mAnnotator;
-
- std::vector<TranslatedAttribute> mTranslatedAttribCache;
bool mPresentPathFastEnabled;
private:
- gl::Error genericDrawArrays(const gl::Data &data,
- GLenum mode,
- GLint first,
- GLsizei count,
- GLsizei instances);
-
- gl::Error genericDrawElements(const gl::Data &data,
- GLenum mode,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- GLsizei instances,
- const gl::IndexRange &indexRange);
-
- virtual gl::Error drawArraysImpl(const gl::Data &data,
- GLenum mode,
- GLsizei count,
- GLsizei instances) = 0;
- virtual gl::Error drawElementsImpl(const gl::Data &data,
- const TranslatedIndexData &indexInfo,
- GLenum mode,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- GLsizei instances) = 0;
-
- //FIXME(jmadill): std::array is currently prohibited by Chromium style guide
- typedef std::array<gl::Texture*, gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS> FramebufferTextureArray;
-
- gl::Error generateSwizzles(const gl::Data &data, gl::SamplerType type);
- gl::Error generateSwizzles(const gl::Data &data);
-
- gl::Error applyState(const gl::Data &data, GLenum drawMode);
- gl::Error applyShaders(const gl::Data &data, GLenum drawMode);
- gl::Error applyTextures(const gl::Data &data, gl::SamplerType shaderType,
- const FramebufferTextureArray &framebufferTextures, size_t framebufferTextureCount);
- gl::Error applyTextures(const gl::Data &data);
-
- bool skipDraw(const gl::Data &data, GLenum drawMode);
- void markTransformFeedbackUsage(const gl::Data &data);
-
- size_t getBoundFramebufferTextures(const gl::Data &data, FramebufferTextureArray *outTextureArray);
- gl::Texture *getIncompleteTexture(GLenum type);
-
- gl::DebugAnnotator *getAnnotator();
-
- virtual WorkaroundsD3D generateWorkarounds() const = 0;
-
- gl::TextureMap mIncompleteTextures;
- MemoryBuffer mScratchMemoryBuffer;
- unsigned int mScratchMemoryBufferResetCounter;
+ void ensureCapsInitialized() const;
+
+ virtual angle::WorkaroundsD3D generateWorkarounds() const = 0;
+
+ mutable bool mCapsInitialized;
+ mutable gl::Caps mNativeCaps;
+ mutable gl::TextureCapsMap mNativeTextureCaps;
+ mutable gl::Extensions mNativeExtensions;
+ mutable gl::Limitations mNativeLimitations;
+
+ IncompleteTextureSet mIncompleteTextures;
mutable bool mWorkaroundsInitialized;
- mutable WorkaroundsD3D mWorkarounds;
+ mutable angle::WorkaroundsD3D mWorkarounds;
bool mDisjoint;
+ bool mDeviceLost;
+
+ angle::WorkerThreadPool mWorkerThreadPool;
+
+ SerialFactory mSerialFactory;
};
-}
+unsigned int GetBlendSampleMask(const gl::State &glState, int samples);
+bool InstancedPointSpritesActive(ProgramD3D *programD3D, GLenum mode);
+
+} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_RENDERERD3D_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SamplerD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SamplerD3D.h
index 7aabdc8132..3f8f5b9d8d 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SamplerD3D.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SamplerD3D.h
@@ -17,7 +17,7 @@ namespace rx
class SamplerD3D : public SamplerImpl
{
public:
- SamplerD3D() {}
+ SamplerD3D(const gl::SamplerState &state) : SamplerImpl(state) {}
~SamplerD3D() override {}
};
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp
index 1ecbfb7410..2a8f1fb11c 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp
@@ -9,9 +9,11 @@
#include "libANGLE/renderer/d3d/ShaderD3D.h"
#include "common/utilities.h"
+#include "libANGLE/Caps.h"
#include "libANGLE/Compiler.h"
#include "libANGLE/Shader.h"
#include "libANGLE/features.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
// Definitions local to the translation unit
@@ -28,6 +30,9 @@ const char *GetShaderTypeString(GLenum type)
case GL_FRAGMENT_SHADER:
return "FRAGMENT";
+ case GL_COMPUTE_SHADER:
+ return "COMPUTE";
+
default:
UNREACHABLE();
return "";
@@ -39,9 +44,39 @@ const char *GetShaderTypeString(GLenum type)
namespace rx
{
-ShaderD3D::ShaderD3D(const gl::Shader::Data &data) : ShaderImpl(data)
+ShaderD3D::ShaderD3D(const gl::ShaderState &data,
+ const angle::WorkaroundsD3D &workarounds,
+ const gl::Extensions &extensions)
+ : ShaderImpl(data), mAdditionalOptions(0)
{
uncompile();
+
+ if (workarounds.expandIntegerPowExpressions)
+ {
+ mAdditionalOptions |= SH_EXPAND_SELECT_HLSL_INTEGER_POW_EXPRESSIONS;
+ }
+
+ if (workarounds.getDimensionsIgnoresBaseLevel)
+ {
+ mAdditionalOptions |= SH_HLSL_GET_DIMENSIONS_IGNORES_BASE_LEVEL;
+ }
+
+ if (workarounds.preAddTexelFetchOffsets)
+ {
+ mAdditionalOptions |= SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH;
+ }
+ if (workarounds.rewriteUnaryMinusOperator)
+ {
+ mAdditionalOptions |= SH_REWRITE_INTEGER_UNARY_MINUS_OPERATOR;
+ }
+ if (workarounds.emulateIsnanFloat)
+ {
+ mAdditionalOptions |= SH_EMULATE_ISNAN_FLOAT_FUNCTION;
+ }
+ if (extensions.multiview)
+ {
+ mAdditionalOptions |= SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW;
+ }
}
ShaderD3D::~ShaderD3D()
@@ -50,6 +85,11 @@ ShaderD3D::~ShaderD3D()
std::string ShaderD3D::getDebugInfo() const
{
+ if (mDebugInfo.empty())
+ {
+ return "";
+ }
+
return mDebugInfo + std::string("\n// ") + GetShaderTypeString(mData.getShaderType()) +
" SHADER END\n";
}
@@ -69,15 +109,16 @@ void ShaderD3D::uncompile()
mUsesPointCoord = false;
mUsesDepthRange = false;
mUsesFragDepth = false;
+ mHasANGLEMultiviewEnabled = false;
+ mUsesViewID = false;
mUsesDiscardRewriting = false;
mUsesNestedBreak = false;
- mUsesDeferredInit = false;
mRequiresIEEEStrictCompiling = false;
mDebugInfo.clear();
}
-void ShaderD3D::generateWorkarounds(D3DCompilerWorkarounds *workarounds) const
+void ShaderD3D::generateWorkarounds(angle::CompilerWorkaroundsD3D *workarounds) const
{
if (mUsesDiscardRewriting)
{
@@ -106,10 +147,10 @@ unsigned int ShaderD3D::getUniformRegister(const std::string &uniformName) const
return mUniformRegisterMap.find(uniformName)->second;
}
-unsigned int ShaderD3D::getInterfaceBlockRegister(const std::string &blockName) const
+unsigned int ShaderD3D::getUniformBlockRegister(const std::string &blockName) const
{
- ASSERT(mInterfaceBlockRegisterMap.count(blockName) > 0);
- return mInterfaceBlockRegisterMap.find(blockName)->second;
+ ASSERT(mUniformBlockRegisterMap.count(blockName) > 0);
+ return mUniformBlockRegisterMap.find(blockName)->second;
}
ShShaderOutput ShaderD3D::getCompilerOutputType() const
@@ -117,12 +158,12 @@ ShShaderOutput ShaderD3D::getCompilerOutputType() const
return mCompilerOutputType;
}
-int ShaderD3D::prepareSourceAndReturnOptions(std::stringstream *shaderSourceStream,
- std::string *sourcePath)
+ShCompileOptions ShaderD3D::prepareSourceAndReturnOptions(std::stringstream *shaderSourceStream,
+ std::string *sourcePath)
{
uncompile();
- int additionalOptions = 0;
+ ShCompileOptions additionalOptions = 0;
const std::string &source = mData.getSource();
@@ -135,10 +176,24 @@ int ShaderD3D::prepareSourceAndReturnOptions(std::stringstream *shaderSourceStre
}
#endif
+ additionalOptions |= mAdditionalOptions;
+
*shaderSourceStream << source;
return additionalOptions;
}
+bool ShaderD3D::hasUniform(const std::string &name) const
+{
+ return mUniformRegisterMap.find(name) != mUniformRegisterMap.end();
+}
+
+const std::map<std::string, unsigned int> &GetUniformRegisterMap(
+ const std::map<std::string, unsigned int> *uniformRegisterMap)
+{
+ ASSERT(uniformRegisterMap);
+ return *uniformRegisterMap;
+}
+
bool ShaderD3D::postTranslateCompile(gl::Compiler *compiler, std::string *infoLog)
{
// TODO(jmadill): We shouldn't need to cache this.
@@ -154,41 +209,30 @@ bool ShaderD3D::postTranslateCompile(gl::Compiler *compiler, std::string *infoLo
mUsesPointSize = translatedSource.find("GL_USES_POINT_SIZE") != std::string::npos;
mUsesPointCoord = translatedSource.find("GL_USES_POINT_COORD") != std::string::npos;
mUsesDepthRange = translatedSource.find("GL_USES_DEPTH_RANGE") != std::string::npos;
- mUsesFragDepth = translatedSource.find("GL_USES_FRAG_DEPTH") != std::string::npos;
+ mUsesFragDepth = translatedSource.find("GL_USES_FRAG_DEPTH") != std::string::npos;
+ mHasANGLEMultiviewEnabled =
+ translatedSource.find("GL_ANGLE_MULTIVIEW_ENABLED") != std::string::npos;
+ mUsesViewID = translatedSource.find("GL_USES_VIEW_ID") != std::string::npos;
mUsesDiscardRewriting =
translatedSource.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos;
mUsesNestedBreak = translatedSource.find("ANGLE_USES_NESTED_BREAK") != std::string::npos;
- mUsesDeferredInit = translatedSource.find("ANGLE_USES_DEFERRED_INIT") != std::string::npos;
mRequiresIEEEStrictCompiling =
translatedSource.find("ANGLE_REQUIRES_IEEE_STRICT_COMPILING") != std::string::npos;
ShHandle compilerHandle = compiler->getCompilerHandle(mData.getShaderType());
- for (const sh::Uniform &uniform : mData.getUniforms())
- {
- if (uniform.staticUse && !uniform.isBuiltIn())
- {
- unsigned int index = static_cast<unsigned int>(-1);
- bool getUniformRegisterResult =
- ShGetUniformRegister(compilerHandle, uniform.name, &index);
- UNUSED_ASSERTION_VARIABLE(getUniformRegisterResult);
- ASSERT(getUniformRegisterResult);
-
- mUniformRegisterMap[uniform.name] = index;
- }
- }
+ mUniformRegisterMap = GetUniformRegisterMap(sh::GetUniformRegisterMap(compilerHandle));
- for (const sh::InterfaceBlock &interfaceBlock : mData.getInterfaceBlocks())
+ for (const sh::InterfaceBlock &interfaceBlock : mData.getUniformBlocks())
{
if (interfaceBlock.staticUse)
{
unsigned int index = static_cast<unsigned int>(-1);
bool blockRegisterResult =
- ShGetInterfaceBlockRegister(compilerHandle, interfaceBlock.name, &index);
- UNUSED_ASSERTION_VARIABLE(blockRegisterResult);
+ sh::GetUniformBlockRegister(compilerHandle, interfaceBlock.name, &index);
ASSERT(blockRegisterResult);
- mInterfaceBlockRegisterMap[interfaceBlock.name] = index;
+ mUniformBlockRegisterMap[interfaceBlock.name] = index;
}
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.h
index 47a73dc27b..f7b0b20db4 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.h
@@ -13,31 +13,50 @@
#include <map>
+namespace angle
+{
+struct CompilerWorkaroundsD3D;
+struct WorkaroundsD3D;
+}
+
+namespace gl
+{
+struct Extensions;
+}
+
namespace rx
{
class DynamicHLSL;
class RendererD3D;
-struct D3DCompilerWorkarounds;
+struct D3DUniform;
class ShaderD3D : public ShaderImpl
{
public:
- ShaderD3D(const gl::Shader::Data &data);
- virtual ~ShaderD3D();
+ ShaderD3D(const gl::ShaderState &data,
+ const angle::WorkaroundsD3D &workarounds,
+ const gl::Extensions &extensions);
+ ~ShaderD3D() override;
// ShaderImpl implementation
- int prepareSourceAndReturnOptions(std::stringstream *sourceStream,
- std::string *sourcePath) override;
+ ShCompileOptions prepareSourceAndReturnOptions(std::stringstream *sourceStream,
+ std::string *sourcePath) override;
bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) override;
std::string getDebugInfo() const override;
// D3D-specific methods
void uncompile();
+
+ bool hasUniform(const std::string &name) const;
+
+ // Query regular uniforms with their name. Query sampler fields of structs with field selection
+ // using dot (.) operator.
unsigned int getUniformRegister(const std::string &uniformName) const;
- unsigned int getInterfaceBlockRegister(const std::string &blockName) const;
+
+ unsigned int getUniformBlockRegister(const std::string &blockName) const;
void appendDebugInfo(const std::string &info) const { mDebugInfo += info; }
- void generateWorkarounds(D3DCompilerWorkarounds *workarounds) const;
+ void generateWorkarounds(angle::CompilerWorkaroundsD3D *workarounds) const;
bool usesMultipleRenderTargets() const { return mUsesMultipleRenderTargets; }
bool usesFragColor() const { return mUsesFragColor; }
@@ -48,7 +67,8 @@ class ShaderD3D : public ShaderImpl
bool usesPointCoord() const { return mUsesPointCoord; }
bool usesDepthRange() const { return mUsesDepthRange; }
bool usesFragDepth() const { return mUsesFragDepth; }
- bool usesDeferredInit() const { return mUsesDeferredInit; }
+ bool usesViewID() const { return mUsesViewID; }
+ bool hasANGLEMultiviewEnabled() const { return mHasANGLEMultiviewEnabled; }
ShShaderOutput getCompilerOutputType() const;
@@ -62,16 +82,18 @@ class ShaderD3D : public ShaderImpl
bool mUsesPointCoord;
bool mUsesDepthRange;
bool mUsesFragDepth;
+ bool mHasANGLEMultiviewEnabled;
+ bool mUsesViewID;
bool mUsesDiscardRewriting;
bool mUsesNestedBreak;
- bool mUsesDeferredInit;
bool mRequiresIEEEStrictCompiling;
ShShaderOutput mCompilerOutputType;
mutable std::string mDebugInfo;
std::map<std::string, unsigned int> mUniformRegisterMap;
- std::map<std::string, unsigned int> mInterfaceBlockRegisterMap;
+ std::map<std::string, unsigned int> mUniformBlockRegisterMap;
+ ShCompileOptions mAdditionalOptions;
};
-}
+} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_SHADERD3D_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp
index 97ffdf5094..83a66bd1a5 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp
@@ -44,9 +44,13 @@ void ShaderExecutableD3D::appendDebugInfo(const std::string &info)
mDebugInfo += info;
}
-
-UniformStorageD3D::UniformStorageD3D(size_t initialSize) : mSize(initialSize)
+UniformStorageD3D::UniformStorageD3D(size_t initialSize) : mUniformData()
{
+ bool result = mUniformData.resize(initialSize);
+ ASSERT(result);
+
+ // Uniform data is zero-initialized by default.
+ mUniformData.fill(0);
}
UniformStorageD3D::~UniformStorageD3D()
@@ -55,7 +59,13 @@ UniformStorageD3D::~UniformStorageD3D()
size_t UniformStorageD3D::size() const
{
- return mSize;
+ return mUniformData.size();
}
+uint8_t *UniformStorageD3D::getDataPointer(unsigned int registerIndex, unsigned int registerElement)
+{
+ size_t offset = ((registerIndex * 4 + registerElement) * sizeof(float));
+ return mUniformData.data() + offset;
}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h
index 71b83b7954..b8097710e2 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h
@@ -10,6 +10,7 @@
#ifndef LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_
#define LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_
+#include "common/MemoryBuffer.h"
#include "common/debug.h"
#include <vector>
@@ -45,10 +46,12 @@ class UniformStorageD3D : angle::NonCopyable
size_t size() const;
+ uint8_t *getDataPointer(unsigned int registerIndex, unsigned int registerElement);
+
private:
- size_t mSize;
+ angle::MemoryBuffer mUniformData;
};
-}
+} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
index f567f47525..7657aef79e 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
@@ -8,10 +8,11 @@
#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+#include "libANGLE/Context.h"
#include "libANGLE/Display.h"
#include "libANGLE/Surface.h"
-#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/SwapChainD3D.h"
#include <tchar.h>
@@ -21,60 +22,62 @@
namespace rx
{
-SurfaceD3D *SurfaceD3D::createOffscreen(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLClientBuffer shareHandle,
- EGLint width, EGLint height)
-{
- return new SurfaceD3D(renderer, display, config, width, height, EGL_TRUE, 0, EGL_FALSE,
- shareHandle, NULL);
-}
-
-SurfaceD3D *SurfaceD3D::createFromWindow(RendererD3D *renderer,
- egl::Display *display,
- const egl::Config *config,
- EGLNativeWindowType window,
- EGLint fixedSize,
- EGLint directComposition,
- EGLint width,
- EGLint height,
- EGLint orientation)
-{
- return new SurfaceD3D(renderer, display, config, width, height, fixedSize, orientation,
- directComposition, static_cast<EGLClientBuffer>(0), window);
-}
-
-SurfaceD3D::SurfaceD3D(RendererD3D *renderer,
+SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state,
+ RendererD3D *renderer,
egl::Display *display,
- const egl::Config *config,
- EGLint width,
- EGLint height,
- EGLint fixedSize,
- EGLint orientation,
- EGLint directComposition,
- EGLClientBuffer shareHandle,
- EGLNativeWindowType window)
- : SurfaceImpl(),
+ EGLNativeWindowType window,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs)
+ : SurfaceImpl(state),
mRenderer(renderer),
mDisplay(display),
- mFixedSize(fixedSize == EGL_TRUE),
- mOrientation(orientation),
- mRenderTargetFormat(config->renderTargetFormat),
- mDepthStencilFormat(config->depthStencilFormat),
+ mFixedSize(window == nullptr || attribs.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE) == EGL_TRUE),
+ mOrientation(static_cast<EGLint>(attribs.get(EGL_SURFACE_ORIENTATION_ANGLE, 0))),
+ mRenderTargetFormat(state.config->renderTargetFormat),
+ mDepthStencilFormat(state.config->depthStencilFormat),
mSwapChain(nullptr),
mSwapIntervalDirty(true),
mWindowSubclassed(false),
- mNativeWindow(window, config, directComposition == EGL_TRUE),
- mWidth(width),
- mHeight(height),
+ mNativeWindow(renderer->createNativeWindow(window, state.config, attribs)),
+ mWidth(static_cast<EGLint>(attribs.get(EGL_WIDTH, 0))),
+ mHeight(static_cast<EGLint>(attribs.get(EGL_HEIGHT, 0))),
mSwapInterval(1),
- mShareHandle(reinterpret_cast<HANDLE *>(shareHandle))
+ mShareHandle(0),
+ mD3DTexture(nullptr)
{
subclassWindow();
+ if (window != nullptr && !mFixedSize)
+ {
+ mWidth = -1;
+ mHeight = -1;
+ }
+
+ switch (buftype)
+ {
+ case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
+ mShareHandle = static_cast<HANDLE>(clientBuffer);
+ break;
+
+ case EGL_D3D_TEXTURE_ANGLE:
+ mD3DTexture = static_cast<IUnknown *>(clientBuffer);
+ ASSERT(mD3DTexture != nullptr);
+ mD3DTexture->AddRef();
+ ANGLE_SWALLOW_ERR(mRenderer->getD3DTextureInfo(state.config, mD3DTexture, &mWidth,
+ &mHeight, &mRenderTargetFormat));
+ break;
+
+ default:
+ break;
+ }
}
SurfaceD3D::~SurfaceD3D()
{
unsubclassWindow();
releaseSwapChain();
+ SafeDelete(mNativeWindow);
+ SafeRelease(mD3DTexture);
}
void SurfaceD3D::releaseSwapChain()
@@ -82,41 +85,41 @@ void SurfaceD3D::releaseSwapChain()
SafeDelete(mSwapChain);
}
-egl::Error SurfaceD3D::initialize()
+egl::Error SurfaceD3D::initialize(const egl::Display *display)
{
- if (mNativeWindow.getNativeWindow())
+ if (mNativeWindow->getNativeWindow())
{
- if (!mNativeWindow.initialize())
+ if (!mNativeWindow->initialize())
{
- return egl::Error(EGL_BAD_SURFACE);
+ return egl::EglBadSurface();
}
}
- egl::Error error = resetSwapChain();
- if (error.isError())
- {
- return error;
- }
-
- return egl::Error(EGL_SUCCESS);
+ ANGLE_TRY(resetSwapChain(display));
+ return egl::NoError();
}
-FramebufferImpl *SurfaceD3D::createDefaultFramebuffer(const gl::Framebuffer::Data &data)
+FramebufferImpl *SurfaceD3D::createDefaultFramebuffer(const gl::FramebufferState &data)
{
- return mRenderer->createFramebuffer(data);
+ return mRenderer->createDefaultFramebuffer(data);
}
egl::Error SurfaceD3D::bindTexImage(gl::Texture *, EGLint)
{
- return egl::Error(EGL_SUCCESS);
+ return egl::NoError();
}
egl::Error SurfaceD3D::releaseTexImage(EGLint)
{
- return egl::Error(EGL_SUCCESS);
+ return egl::NoError();
+}
+
+egl::Error SurfaceD3D::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
+{
+ return mSwapChain->getSyncValues(ust, msc, sbc);
}
-egl::Error SurfaceD3D::resetSwapChain()
+egl::Error SurfaceD3D::resetSwapChain(const egl::Display *display)
{
ASSERT(!mSwapChain);
@@ -126,11 +129,11 @@ egl::Error SurfaceD3D::resetSwapChain()
if (!mFixedSize)
{
RECT windowRect;
- if (!mNativeWindow.getClientRect(&windowRect))
+ if (!mNativeWindow->getClientRect(&windowRect))
{
ASSERT(false);
- return egl::Error(EGL_BAD_SURFACE, "Could not retrieve the window dimensions");
+ return egl::EglBadSurface() << "Could not retrieve the window dimensions";
}
width = windowRect.right - windowRect.left;
@@ -143,29 +146,34 @@ egl::Error SurfaceD3D::resetSwapChain()
height = mHeight;
}
- mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle, mRenderTargetFormat,
- mDepthStencilFormat, mOrientation);
+ mSwapChain =
+ mRenderer->createSwapChain(mNativeWindow, mShareHandle, mD3DTexture, mRenderTargetFormat,
+ mDepthStencilFormat, mOrientation, mState.config->samples);
if (!mSwapChain)
{
- return egl::Error(EGL_BAD_ALLOC);
+ return egl::EglBadAlloc();
}
- egl::Error error = resetSwapChain(width, height);
+ // This is a bit risky to pass the proxy context here, but it can happen at almost any time.
+ egl::Error error = resetSwapChain(display->getProxyContext(), width, height);
if (error.isError())
{
SafeDelete(mSwapChain);
return error;
}
- return egl::Error(EGL_SUCCESS);
+ return egl::NoError();
}
-egl::Error SurfaceD3D::resizeSwapChain(int backbufferWidth, int backbufferHeight)
+egl::Error SurfaceD3D::resizeSwapChain(const gl::Context *context,
+ int backbufferWidth,
+ int backbufferHeight)
{
ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
ASSERT(mSwapChain);
- EGLint status = mSwapChain->resize(std::max(1, backbufferWidth), std::max(1, backbufferHeight));
+ EGLint status =
+ mSwapChain->resize(context, std::max(1, backbufferWidth), std::max(1, backbufferHeight));
if (status == EGL_CONTEXT_LOST)
{
@@ -180,15 +188,18 @@ egl::Error SurfaceD3D::resizeSwapChain(int backbufferWidth, int backbufferHeight
mWidth = backbufferWidth;
mHeight = backbufferHeight;
- return egl::Error(EGL_SUCCESS);
+ return egl::NoError();
}
-egl::Error SurfaceD3D::resetSwapChain(int backbufferWidth, int backbufferHeight)
+egl::Error SurfaceD3D::resetSwapChain(const gl::Context *context,
+ int backbufferWidth,
+ int backbufferHeight)
{
ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
ASSERT(mSwapChain);
- EGLint status = mSwapChain->reset(std::max(1, backbufferWidth), std::max(1, backbufferHeight), mSwapInterval);
+ EGLint status = mSwapChain->reset(context, std::max(1, backbufferWidth),
+ std::max(1, backbufferHeight), mSwapInterval);
if (status == EGL_CONTEXT_LOST)
{
@@ -204,17 +215,20 @@ egl::Error SurfaceD3D::resetSwapChain(int backbufferWidth, int backbufferHeight)
mHeight = backbufferHeight;
mSwapIntervalDirty = false;
- return egl::Error(EGL_SUCCESS);
+ return egl::NoError();
}
-egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+egl::Error SurfaceD3D::swapRect(const gl::Context *context,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height)
{
if (!mSwapChain)
{
- return egl::Error(EGL_SUCCESS);
+ return egl::NoError();
}
-#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (defined(ANGLE_ENABLE_WINDOWS_STORE) && WINAPI_FAMILY == WINAPI_FAMILY_PC_APP) // Qt WP: eglPostSubBufferNV comes here
if (x + width > mWidth)
{
width = mWidth - x;
@@ -224,11 +238,10 @@ egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
{
height = mHeight - y;
}
-#endif
if (width != 0 && height != 0)
{
- EGLint status = mSwapChain->swapRect(x, y, width, height);
+ EGLint status = mSwapChain->swapRect(context, x, y, width, height);
if (status == EGL_CONTEXT_LOST)
{
@@ -241,34 +254,36 @@ egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
}
}
- checkForOutOfDateSwapChain();
+ ANGLE_TRY(checkForOutOfDateSwapChain(context));
- return egl::Error(EGL_SUCCESS);
+ return egl::NoError();
}
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
#define kSurfaceProperty _TEXT("Egl::SurfaceOwner")
#define kParentWndProc _TEXT("Egl::SurfaceParentWndProc")
+#define kDisplayProperty _TEXT("Egl::Display")
static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
- if (message == WM_SIZE)
- {
- SurfaceD3D* surf = reinterpret_cast<SurfaceD3D*>(GetProp(hwnd, kSurfaceProperty));
- if(surf)
- {
- surf->checkForOutOfDateSwapChain();
- }
- }
- WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc));
- return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam);
+ if (message == WM_SIZE)
+ {
+ SurfaceD3D* surf = reinterpret_cast<SurfaceD3D*>(GetProp(hwnd, kSurfaceProperty));
+ if(surf)
+ {
+ egl::Display *display = reinterpret_cast<egl::Display *>(GetProp(hwnd, kDisplayProperty));
+ surf->checkForOutOfDateSwapChain(display->getProxyContext());
+ }
+ }
+ WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc));
+ return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam);
}
#endif
void SurfaceD3D::subclassWindow()
{
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
- HWND window = mNativeWindow.getNativeWindow();
+ HWND window = mNativeWindow->getNativeWindow();
if (!window)
{
return;
@@ -291,6 +306,7 @@ void SurfaceD3D::subclassWindow()
SetProp(window, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
SetProp(window, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc));
+ SetProp(window, kDisplayProperty, reinterpret_cast<HANDLE>(mDisplay));
mWindowSubclassed = true;
#endif
}
@@ -303,7 +319,7 @@ void SurfaceD3D::unsubclassWindow()
}
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
- HWND window = mNativeWindow.getNativeWindow();
+ HWND window = mNativeWindow->getNativeWindow();
if (!window)
{
return;
@@ -320,30 +336,31 @@ void SurfaceD3D::unsubclassWindow()
if(parentWndFunc)
{
LONG_PTR prevWndFunc = SetWindowLongPtr(window, GWLP_WNDPROC, parentWndFunc);
- UNUSED_ASSERTION_VARIABLE(prevWndFunc);
ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
}
RemoveProp(window, kSurfaceProperty);
RemoveProp(window, kParentWndProc);
+ RemoveProp(window, kDisplayProperty);
#endif
mWindowSubclassed = false;
}
-bool SurfaceD3D::checkForOutOfDateSwapChain()
+
+egl::Error SurfaceD3D::checkForOutOfDateSwapChain(const gl::Context *context)
{
RECT client;
int clientWidth = getWidth();
int clientHeight = getHeight();
bool sizeDirty = false;
- if (!mFixedSize && !mNativeWindow.isIconic())
+ if (!mFixedSize && !mNativeWindow->isIconic())
{
// The window is automatically resized to 150x22 when it's minimized, but the swapchain shouldn't be resized
// because that's not a useful size to render to.
- if (!mNativeWindow.getClientRect(&client))
+ if (!mNativeWindow->getClientRect(&client))
{
- ASSERT(false);
- return false;
+ UNREACHABLE();
+ return egl::NoError();
}
// Grow the buffer now, if the window has grown. We need to grow now to avoid losing information.
@@ -352,28 +369,30 @@ bool SurfaceD3D::checkForOutOfDateSwapChain()
sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();
}
- bool wasDirty = (mSwapIntervalDirty || sizeDirty);
-
if (mSwapIntervalDirty)
{
- resetSwapChain(clientWidth, clientHeight);
+ ANGLE_TRY(resetSwapChain(context, clientWidth, clientHeight));
}
else if (sizeDirty)
{
- resizeSwapChain(clientWidth, clientHeight);
+ ANGLE_TRY(resizeSwapChain(context, clientWidth, clientHeight));
}
- return wasDirty;
+ return egl::NoError();
}
-egl::Error SurfaceD3D::swap()
+egl::Error SurfaceD3D::swap(const gl::Context *context)
{
- return swapRect(0, 0, mWidth, mHeight);
+ return swapRect(context, 0, 0, mWidth, mHeight);
}
-egl::Error SurfaceD3D::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+egl::Error SurfaceD3D::postSubBuffer(const gl::Context *context,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height)
{
- return swapRect(x, y, width, height);
+ return swapRect(context, x, y, width, height);
}
rx::SwapChainD3D *SurfaceD3D::getSwapChain() const
@@ -429,13 +448,15 @@ egl::Error SurfaceD3D::querySurfacePointerANGLE(EGLint attribute, void **value)
}
else UNREACHABLE();
- return egl::Error(EGL_SUCCESS);
+ return egl::NoError();
}
-gl::Error SurfaceD3D::getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target,
+gl::Error SurfaceD3D::getAttachmentRenderTarget(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex,
FramebufferAttachmentRenderTarget **rtOut)
{
- if (target.binding() == GL_BACK)
+ if (binding == GL_BACK)
{
*rtOut = mSwapChain->getColorRenderTarget();
}
@@ -443,7 +464,46 @@ gl::Error SurfaceD3D::getAttachmentRenderTarget(const gl::FramebufferAttachment:
{
*rtOut = mSwapChain->getDepthStencilRenderTarget();
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
+}
+
+WindowSurfaceD3D::WindowSurfaceD3D(const egl::SurfaceState &state,
+ RendererD3D *renderer,
+ egl::Display *display,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs)
+ : SurfaceD3D(state,
+ renderer,
+ display,
+ window,
+ 0,
+ static_cast<EGLClientBuffer>(0),
+ attribs)
+{
+}
+
+WindowSurfaceD3D::~WindowSurfaceD3D()
+{
}
+PbufferSurfaceD3D::PbufferSurfaceD3D(const egl::SurfaceState &state,
+ RendererD3D *renderer,
+ egl::Display *display,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs)
+ : SurfaceD3D(state,
+ renderer,
+ display,
+ static_cast<EGLNativeWindowType>(0),
+ buftype,
+ clientBuffer,
+ attribs)
+{
}
+
+PbufferSurfaceD3D::~PbufferSurfaceD3D()
+{
+}
+
+} // namespace rc
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h
index 67d408ddd9..01d2573244 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h
@@ -10,7 +10,7 @@
#define LIBANGLE_RENDERER_D3D_SURFACED3D_H_
#include "libANGLE/renderer/SurfaceImpl.h"
-#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h"
+#include "libANGLE/renderer/d3d/NativeWindowD3D.h"
namespace egl
{
@@ -25,28 +25,22 @@ class RendererD3D;
class SurfaceD3D : public SurfaceImpl
{
public:
- static SurfaceD3D *createFromWindow(RendererD3D *renderer,
- egl::Display *display,
- const egl::Config *config,
- EGLNativeWindowType window,
- EGLint fixedSize,
- EGLint directComposition,
- EGLint width,
- EGLint height,
- EGLint orientation);
- static SurfaceD3D *createOffscreen(RendererD3D *renderer, egl::Display *display, const egl::Config *config,
- EGLClientBuffer shareHandle, EGLint width, EGLint height);
~SurfaceD3D() override;
void releaseSwapChain();
- egl::Error initialize() override;
- FramebufferImpl *createDefaultFramebuffer(const gl::Framebuffer::Data &data) override;
+ egl::Error initialize(const egl::Display *display) override;
+ FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
- egl::Error swap() override;
- egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+ egl::Error swap(const gl::Context *context) override;
+ egl::Error postSubBuffer(const gl::Context *context,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height) override;
egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
egl::Error releaseTexImage(EGLint buffer) override;
+ egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override;
void setSwapInterval(EGLint interval) override;
EGLint getWidth() const override;
@@ -58,29 +52,35 @@ class SurfaceD3D : public SurfaceImpl
// D3D implementations
SwapChainD3D *getSwapChain() const;
- egl::Error resetSwapChain();
+ egl::Error resetSwapChain(const egl::Display *display);
- // Returns true if swapchain changed due to resize or interval update
- bool checkForOutOfDateSwapChain();
+ egl::Error checkForOutOfDateSwapChain(const gl::Context *context);
- gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target,
+ gl::Error getAttachmentRenderTarget(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex,
FramebufferAttachmentRenderTarget **rtOut) override;
- private:
- SurfaceD3D(RendererD3D *renderer,
+ protected:
+ SurfaceD3D(const egl::SurfaceState &state,
+ RendererD3D *renderer,
egl::Display *display,
- const egl::Config *config,
- EGLint width,
- EGLint height,
- EGLint fixedSize,
- EGLint orientation,
- EGLint directComposition,
- EGLClientBuffer shareHandle,
- EGLNativeWindowType window);
-
- egl::Error swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
- egl::Error resetSwapChain(int backbufferWidth, int backbufferHeight);
- egl::Error resizeSwapChain(int backbufferWidth, int backbufferHeight);
+ EGLNativeWindowType window,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs);
+
+ egl::Error swapRect(const gl::Context *context,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height);
+ egl::Error resetSwapChain(const gl::Context *context,
+ int backbufferWidth,
+ int backbufferHeight);
+ egl::Error resizeSwapChain(const gl::Context *context,
+ int backbufferWidth,
+ int backbufferHeight);
void subclassWindow();
void unsubclassWindow();
@@ -96,18 +96,41 @@ class SurfaceD3D : public SurfaceImpl
SwapChainD3D *mSwapChain;
bool mSwapIntervalDirty;
- bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking
+ bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking
- NativeWindow mNativeWindow; // Handler for the Window that the surface is created for.
+ NativeWindowD3D *mNativeWindow; // Handler for the Window that the surface is created for.
EGLint mWidth;
EGLint mHeight;
EGLint mSwapInterval;
HANDLE mShareHandle;
+ IUnknown *mD3DTexture;
};
+class WindowSurfaceD3D : public SurfaceD3D
+{
+ public:
+ WindowSurfaceD3D(const egl::SurfaceState &state,
+ RendererD3D *renderer,
+ egl::Display *display,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs);
+ ~WindowSurfaceD3D() override;
+};
-}
+class PbufferSurfaceD3D : public SurfaceD3D
+{
+ public:
+ PbufferSurfaceD3D(const egl::SurfaceState &state,
+ RendererD3D *renderer,
+ egl::Display *display,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs);
+ ~PbufferSurfaceD3D() override;
+};
+
+} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_SURFACED3D_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.cpp
new file mode 100644
index 0000000000..de8534c3da
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.cpp
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SwapChainD3D.cpp: Defines a back-end specific class that hides the details of the
+// implementation-specific swapchain.
+
+#include "libANGLE/renderer/d3d/SwapChainD3D.h"
+
+namespace rx
+{
+
+SwapChainD3D::SwapChainD3D(HANDLE shareHandle,
+ IUnknown *d3dTexture,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat)
+ : mOffscreenRenderTargetFormat(backBufferFormat),
+ mDepthBufferFormat(depthBufferFormat),
+ mShareHandle(shareHandle),
+ mD3DTexture(d3dTexture)
+{
+ if (mD3DTexture)
+ {
+ mD3DTexture->AddRef();
+ }
+}
+
+SwapChainD3D::~SwapChainD3D()
+{
+ SafeRelease(mD3DTexture);
+}
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h
index 171cab54dd..017737b878 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h
@@ -12,17 +12,26 @@
#include <GLES2/gl2.h>
#include <EGL/egl.h>
+#include <EGL/eglext.h>
#include "common/angleutils.h"
#include "common/platform.h"
-
-// TODO: move out of D3D11
-#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h"
+#include "libANGLE/Error.h"
#if !defined(ANGLE_FORCE_VSYNC_OFF)
#define ANGLE_FORCE_VSYNC_OFF 0
#endif
+namespace gl
+{
+class Context;
+} // namespace gl
+
+namespace egl
+{
+class Display;
+} // namespace egl
+
namespace rx
{
class RenderTargetD3D;
@@ -30,35 +39,45 @@ class RenderTargetD3D;
class SwapChainD3D : angle::NonCopyable
{
public:
- SwapChainD3D(rx::NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
- : mNativeWindow(nativeWindow), mOffscreenRenderTargetFormat(backBufferFormat), mDepthBufferFormat(depthBufferFormat), mShareHandle(shareHandle)
- {
- }
-
- virtual ~SwapChainD3D() {};
-
- virtual EGLint resize(EGLint backbufferWidth, EGLint backbufferSize) = 0;
- virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval) = 0;
- virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height) = 0;
+ SwapChainD3D(HANDLE shareHandle,
+ IUnknown *d3dTexture,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat);
+ virtual ~SwapChainD3D();
+
+ virtual EGLint resize(const gl::Context *context,
+ EGLint backbufferWidth,
+ EGLint backbufferSize) = 0;
+ virtual EGLint reset(const gl::Context *context,
+ EGLint backbufferWidth,
+ EGLint backbufferHeight,
+ EGLint swapInterval) = 0;
+ virtual EGLint swapRect(const gl::Context *context,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height) = 0;
virtual void recreate() = 0;
- virtual void *getDevice() { return NULL; }
+ virtual void *getDevice() { return nullptr; }
virtual RenderTargetD3D *getColorRenderTarget() = 0;
virtual RenderTargetD3D *getDepthStencilRenderTarget() = 0;
- GLenum GetRenderTargetInternalFormat() const { return mOffscreenRenderTargetFormat; }
- GLenum GetDepthBufferInternalFormat() const { return mDepthBufferFormat; }
+ GLenum getRenderTargetInternalFormat() const { return mOffscreenRenderTargetFormat; }
+ GLenum getDepthBufferInternalFormat() const { return mDepthBufferFormat; }
HANDLE getShareHandle() { return mShareHandle; }
virtual void *getKeyedMutex() = 0;
+ virtual egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) = 0;
+
protected:
- rx::NativeWindow mNativeWindow; // Handler for the Window that the surface is created for.
const GLenum mOffscreenRenderTargetFormat;
const GLenum mDepthBufferFormat;
HANDLE mShareHandle;
+ IUnknown *mD3DTexture;
};
-}
+} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_SWAPCHAIND3D_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp
index 430576b318..bf44cbb5d2 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp
@@ -12,6 +12,7 @@
#include "common/utilities.h"
#include "libANGLE/Buffer.h"
#include "libANGLE/Config.h"
+#include "libANGLE/Context.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/Image.h"
#include "libANGLE/Surface.h"
@@ -21,8 +22,8 @@
#include "libANGLE/renderer/d3d/BufferD3D.h"
#include "libANGLE/renderer/d3d/EGLImageD3D.h"
#include "libANGLE/renderer/d3d/ImageD3D.h"
-#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/SurfaceD3D.h"
#include "libANGLE/renderer/d3d/TextureStorage.h"
@@ -32,26 +33,24 @@ namespace rx
namespace
{
-gl::Error GetUnpackPointer(const gl::PixelUnpackState &unpack, const uint8_t *pixels,
- ptrdiff_t layerOffset, const uint8_t **pointerOut)
+gl::Error GetUnpackPointer(const gl::Context *context,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels,
+ ptrdiff_t layerOffset,
+ const uint8_t **pointerOut)
{
- if (unpack.pixelBuffer.id() != 0)
+ if (unpackBuffer)
{
// Do a CPU readback here, if we have an unpack buffer bound and the fast GPU path is not supported
- gl::Buffer *pixelBuffer = unpack.pixelBuffer.get();
ptrdiff_t offset = reinterpret_cast<ptrdiff_t>(pixels);
// TODO: this is the only place outside of renderer that asks for a buffers raw data.
// This functionality should be moved into renderer and the getData method of BufferImpl removed.
- BufferD3D *bufferD3D = GetImplAs<BufferD3D>(pixelBuffer);
+ BufferD3D *bufferD3D = GetImplAs<BufferD3D>(unpackBuffer);
ASSERT(bufferD3D);
- const uint8_t *bufferData = NULL;
- gl::Error error = bufferD3D->getData(&bufferData);
- if (error.isError())
- {
- return error;
- }
-
+ const uint8_t *bufferData = nullptr;
+ ANGLE_TRY(bufferD3D->getData(context, &bufferData));
*pointerOut = bufferData + offset;
}
else
@@ -65,7 +64,7 @@ gl::Error GetUnpackPointer(const gl::PixelUnpackState &unpack, const uint8_t *pi
*pointerOut += layerOffset;
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
bool IsRenderTargetUsage(GLenum usage)
@@ -75,41 +74,66 @@ bool IsRenderTargetUsage(GLenum usage)
}
-TextureD3D::TextureD3D(RendererD3D *renderer)
- : mRenderer(renderer),
- mUsage(GL_NONE),
+TextureD3D::TextureD3D(const gl::TextureState &state, RendererD3D *renderer)
+ : TextureImpl(state),
+ mRenderer(renderer),
mDirtyImages(true),
mImmutable(false),
- mTexStorage(NULL)
+ mTexStorage(nullptr),
+ mBaseLevel(0)
{
}
TextureD3D::~TextureD3D()
{
+ ASSERT(!mTexStorage);
}
-gl::Error TextureD3D::getNativeTexture(TextureStorage **outStorage)
+gl::Error TextureD3D::getNativeTexture(const gl::Context *context, TextureStorage **outStorage)
{
// ensure the underlying texture is created
- gl::Error error = initializeStorage(false);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(initializeStorage(context, false));
if (mTexStorage)
{
- error = updateStorage();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(updateStorage(context));
}
ASSERT(outStorage);
*outStorage = mTexStorage;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
+}
+
+gl::Error TextureD3D::getImageAndSyncFromStorage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ ImageD3D **outImage)
+{
+ ImageD3D *image = getImage(index);
+ if (mTexStorage && mTexStorage->isRenderTarget())
+ {
+ ANGLE_TRY(image->copyFromTexStorage(context, index, mTexStorage));
+ mDirtyImages = true;
+ }
+ *outImage = image;
+ return gl::NoError();
+}
+
+GLint TextureD3D::getLevelZeroWidth() const
+{
+ ASSERT(gl::CountLeadingZeros(static_cast<uint32_t>(getBaseLevelWidth())) > getBaseLevel());
+ return getBaseLevelWidth() << mBaseLevel;
+}
+
+GLint TextureD3D::getLevelZeroHeight() const
+{
+ ASSERT(gl::CountLeadingZeros(static_cast<uint32_t>(getBaseLevelHeight())) > getBaseLevel());
+ return getBaseLevelHeight() << mBaseLevel;
+}
+
+GLint TextureD3D::getLevelZeroDepth() const
+{
+ return getBaseLevelDepth();
}
GLint TextureD3D::getBaseLevelWidth() const
@@ -139,6 +163,27 @@ GLenum TextureD3D::getBaseLevelInternalFormat() const
return (baseImage ? baseImage->getInternalFormat() : GL_NONE);
}
+gl::Error TextureD3D::setStorage(const gl::Context *context,
+ GLenum target,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size)
+{
+ UNREACHABLE();
+ return gl::InternalError();
+}
+
+gl::Error TextureD3D::setStorageMultisample(const gl::Context *context,
+ GLenum target,
+ GLsizei samples,
+ GLint internalFormat,
+ const gl::Extents &size,
+ bool fixedSampleLocations)
+{
+ UNREACHABLE();
+ return gl::InternalError();
+}
+
bool TextureD3D::shouldUseSetData(const ImageD3D *image) const
{
if (!mRenderer->getWorkarounds().setDataFasterThanImageUpload)
@@ -146,7 +191,12 @@ bool TextureD3D::shouldUseSetData(const ImageD3D *image) const
return false;
}
- gl::InternalFormat internalFormat = gl::GetInternalFormatInfo(image->getInternalFormat());
+ if (image->isDirty())
+ {
+ return false;
+ }
+
+ gl::InternalFormat internalFormat = gl::GetSizedInternalFormatInfo(image->getInternalFormat());
// We can only handle full updates for depth-stencil textures, so to avoid complications
// disable them entirely.
@@ -159,173 +209,166 @@ bool TextureD3D::shouldUseSetData(const ImageD3D *image) const
return (mTexStorage && !internalFormat.compressed);
}
-gl::Error TextureD3D::setImageImpl(const gl::ImageIndex &index,
+gl::Error TextureD3D::setImageImpl(const gl::Context *context,
+ const gl::ImageIndex &index,
GLenum type,
const gl::PixelUnpackState &unpack,
const uint8_t *pixels,
ptrdiff_t layerOffset)
{
ImageD3D *image = getImage(index);
+ gl::Buffer *unpackBuffer =
+ context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
ASSERT(image);
// No-op
if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0)
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
// We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains.
// From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components.
- const uint8_t *pixelData = NULL;
- gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData);
- if (error.isError())
- {
- return error;
- }
+ const uint8_t *pixelData = nullptr;
+ ANGLE_TRY(GetUnpackPointer(context, unpack, unpackBuffer, pixels, layerOffset, &pixelData));
if (pixelData != nullptr)
{
if (shouldUseSetData(image))
{
- error = mTexStorage->setData(index, image, NULL, type, unpack, pixelData);
+ ANGLE_TRY(
+ mTexStorage->setData(context, index, image, nullptr, type, unpack, pixelData));
}
else
{
gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth());
- error = image->loadData(fullImageArea, unpack, type, pixelData);
- }
-
- if (error.isError())
- {
- return error;
+ ANGLE_TRY(
+ image->loadData(context, fullImageArea, unpack, type, pixelData, index.is3D()));
}
mDirtyImages = true;
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D::subImage(const gl::ImageIndex &index, const gl::Box &area, GLenum format, GLenum type,
- const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset)
+gl::Error TextureD3D::subImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels,
+ ptrdiff_t layerOffset)
{
// CPU readback & copy where direct GPU copy is not supported
- const uint8_t *pixelData = NULL;
- gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData);
- if (error.isError())
- {
- return error;
- }
+ const uint8_t *pixelData = nullptr;
+ gl::Buffer *unpackBuffer =
+ context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
+ ANGLE_TRY(GetUnpackPointer(context, unpack, unpackBuffer, pixels, layerOffset, &pixelData));
- if (pixelData != NULL)
+ if (pixelData != nullptr)
{
ImageD3D *image = getImage(index);
ASSERT(image);
if (shouldUseSetData(image))
{
- return mTexStorage->setData(index, image, &area, type, unpack, pixelData);
- }
-
- error = image->loadData(area, unpack, type, pixelData);
- if (error.isError())
- {
- return error;
- }
-
- error = commitRegion(index, area);
- if (error.isError())
- {
- return error;
+ return mTexStorage->setData(context, index, image, &area, type, unpack, pixelData);
}
+ ANGLE_TRY(image->loadData(context, area, unpack, type, pixelData, index.is3D()));
+ ANGLE_TRY(commitRegion(context, index, area));
mDirtyImages = true;
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D::setCompressedImageImpl(const gl::ImageIndex &index,
+gl::Error TextureD3D::setCompressedImageImpl(const gl::Context *context,
+ const gl::ImageIndex &index,
const gl::PixelUnpackState &unpack,
const uint8_t *pixels,
ptrdiff_t layerOffset)
{
- // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains.
- // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components.
- const uint8_t *pixelData = NULL;
- gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData);
- if (error.isError())
+ ImageD3D *image = getImage(index);
+ ASSERT(image);
+
+ if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0)
{
- return error;
+ return gl::NoError();
}
- if (pixelData != NULL)
- {
- ImageD3D *image = getImage(index);
- ASSERT(image);
+ // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains.
+ // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components.
+ const uint8_t *pixelData = nullptr;
+ gl::Buffer *unpackBuffer =
+ context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
+ ANGLE_TRY(GetUnpackPointer(context, unpack, unpackBuffer, pixels, layerOffset, &pixelData));
+ if (pixelData != nullptr)
+ {
gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth());
- error = image->loadCompressedData(fullImageArea, pixelData);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(image->loadCompressedData(context, fullImageArea, pixelData));
mDirtyImages = true;
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D::subImageCompressed(const gl::ImageIndex &index, const gl::Box &area, GLenum format,
- const gl::PixelUnpackState &unpack, const uint8_t *pixels,
+gl::Error TextureD3D::subImageCompressed(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels,
ptrdiff_t layerOffset)
{
- const uint8_t *pixelData = NULL;
- gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData);
- if (error.isError())
- {
- return error;
- }
+ const uint8_t *pixelData = nullptr;
+ gl::Buffer *unpackBuffer =
+ context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
+ ANGLE_TRY(GetUnpackPointer(context, unpack, unpackBuffer, pixels, layerOffset, &pixelData));
- if (pixelData != NULL)
+ if (pixelData != nullptr)
{
ImageD3D *image = getImage(index);
ASSERT(image);
- error = image->loadCompressedData(area, pixelData);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(image->loadCompressedData(context, area, pixelData));
mDirtyImages = true;
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat)
+bool TextureD3D::isFastUnpackable(const gl::Buffer *unpackBuffer, GLenum sizedInternalFormat)
{
- return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat);
+ return unpackBuffer != nullptr &&
+ mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat);
}
-gl::Error TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const uint8_t *pixels, const gl::Box &destArea,
- GLenum sizedInternalFormat, GLenum type, RenderTargetD3D *destRenderTarget)
+gl::Error TextureD3D::fastUnpackPixels(const gl::Context *context,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels,
+ const gl::Box &destArea,
+ GLenum sizedInternalFormat,
+ GLenum type,
+ RenderTargetD3D *destRenderTarget)
{
if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 ||
unpack.skipImages != 0)
{
// TODO(jmadill): additional unpack parameters
UNIMPLEMENTED();
- return gl::Error(GL_INVALID_OPERATION,
- "Unimplemented pixel store parameters in fastUnpackPixels");
+ return gl::InternalError() << "Unimplemented pixel store parameters in fastUnpackPixels";
}
// No-op
if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0)
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
// In order to perform the fast copy through the shader, we must have the right format, and be able
@@ -334,18 +377,17 @@ gl::Error TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const
uintptr_t offset = reinterpret_cast<uintptr_t>(pixels);
- gl::Error error = mRenderer->fastCopyBufferToTexture(unpack, static_cast<unsigned int>(offset), destRenderTarget, sizedInternalFormat, type, destArea);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mRenderer->fastCopyBufferToTexture(context, unpack, static_cast<unsigned int>(offset),
+ destRenderTarget, sizedInternalFormat, type,
+ destArea));
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
GLint TextureD3D::creationLevels(GLsizei width, GLsizei height, GLsizei depth) const
{
- if ((gl::isPow2(width) && gl::isPow2(height) && gl::isPow2(depth)) || mRenderer->getRendererExtensions().textureNPOT)
+ if ((gl::isPow2(width) && gl::isPow2(height) && gl::isPow2(depth)) ||
+ mRenderer->getNativeExtensions().textureNPOT)
{
// Maximum number of levels
return gl::log2(std::max(std::max(width, height), depth)) + 1;
@@ -357,11 +399,6 @@ GLint TextureD3D::creationLevels(GLsizei width, GLsizei height, GLsizei depth) c
}
}
-int TextureD3D::mipLevels() const
-{
- return gl::log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1;
-}
-
TextureStorage *TextureD3D::getStorage()
{
ASSERT(mTexStorage);
@@ -370,72 +407,60 @@ TextureStorage *TextureD3D::getStorage()
ImageD3D *TextureD3D::getBaseLevelImage() const
{
- return getImage(getImageIndex(0, 0));
+ if (mBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ return nullptr;
+ }
+ return getImage(getImageIndex(mBaseLevel, 0));
}
-gl::Error TextureD3D::generateMipmaps(const gl::TextureState &textureState)
+gl::Error TextureD3D::setImageExternal(const gl::Context *context,
+ GLenum target,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc)
{
- GLint mipCount = mipLevels();
+ // Only external images can accept external textures
+ UNREACHABLE();
+ return gl::InternalError();
+}
- if (mipCount == 1)
- {
- return gl::Error(GL_NO_ERROR); // no-op
- }
+gl::Error TextureD3D::generateMipmap(const gl::Context *context)
+{
+ const GLuint baseLevel = mState.getEffectiveBaseLevel();
+ const GLuint maxLevel = mState.getMipmapMaxLevel();
+ ASSERT(maxLevel > baseLevel); // Should be checked before calling this.
if (mTexStorage && mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
// Switch to using the mipmapped texture.
- TextureStorage *textureStorage = NULL;
- gl::Error error = getNativeTexture(&textureStorage);
- if (error.isError())
- {
- return error;
- }
-
- error = textureStorage->useLevelZeroWorkaroundTexture(false);
- if (error.isError())
- {
- return error;
- }
+ TextureStorage *textureStorage = nullptr;
+ ANGLE_TRY(getNativeTexture(context, &textureStorage));
+ ANGLE_TRY(textureStorage->useLevelZeroWorkaroundTexture(context, false));
}
// Set up proper mipmap chain in our Image array.
- initMipmapsImages();
+ ANGLE_TRY(initMipmapImages(context));
if (mTexStorage && mTexStorage->supportsNativeMipmapFunction())
{
- gl::Error error = updateStorage();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(updateStorage(context));
// Generate the mipmap chain using the ad-hoc DirectX function.
- error = mRenderer->generateMipmapsUsingD3D(mTexStorage, textureState);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mRenderer->generateMipmapUsingD3D(context, mTexStorage, mState));
}
else
{
// Generate the mipmap chain, one level at a time.
- gl::Error error = generateMipmapsUsingImages();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(generateMipmapUsingImages(context, maxLevel));
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D::generateMipmapsUsingImages()
+gl::Error TextureD3D::generateMipmapUsingImages(const gl::Context *context, const GLuint maxLevel)
{
- GLint mipCount = mipLevels();
-
// We know that all layers have the same dimension, for the texture to be complete
- GLint layerCount = static_cast<GLint>(getLayerCount(0));
+ GLint layerCount = static_cast<GLint>(getLayerCount(mBaseLevel));
// When making mipmaps with the setData workaround enabled, the texture storage has
// the image data already. For non-render-target storage, we have to pull it out into
@@ -447,23 +472,15 @@ gl::Error TextureD3D::generateMipmapsUsingImages()
// Copy from the storage mip 0 to Image mip 0
for (GLint layer = 0; layer < layerCount; ++layer)
{
- gl::ImageIndex srcIndex = getImageIndex(0, layer);
+ gl::ImageIndex srcIndex = getImageIndex(mBaseLevel, layer);
ImageD3D *image = getImage(srcIndex);
- gl::Error error = image->copyFromTexStorage(srcIndex, mTexStorage);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(image->copyFromTexStorage(context, srcIndex, mTexStorage));
}
}
else
{
- gl::Error error = updateStorage();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(updateStorage(context));
}
}
@@ -476,7 +493,7 @@ gl::Error TextureD3D::generateMipmapsUsingImages()
for (GLint layer = 0; layer < layerCount; ++layer)
{
- for (GLint mip = 1; mip < mipCount; ++mip)
+ for (GLuint mip = mBaseLevel + 1; mip <= maxLevel; ++mip)
{
ASSERT(getLayerCount(mip) == layerCount);
@@ -486,30 +503,25 @@ gl::Error TextureD3D::generateMipmapsUsingImages()
if (renderableStorage)
{
// GPU-side mipmapping
- gl::Error error = mTexStorage->generateMipmap(sourceIndex, destIndex);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mTexStorage->generateMipmap(context, sourceIndex, destIndex));
}
else
{
// CPU-side mipmapping
- gl::Error error = mRenderer->generateMipmap(getImage(destIndex), getImage(sourceIndex));
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(
+ mRenderer->generateMipmap(context, getImage(destIndex), getImage(sourceIndex)));
}
}
}
+ mDirtyImages = true;
+
if (mTexStorage)
{
- updateStorage();
+ ANGLE_TRY(updateStorage(context));
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
bool TextureD3D::isBaseImageZeroSize() const
@@ -531,7 +543,7 @@ bool TextureD3D::isBaseImageZeroSize() const
return true;
}
- if (baseImage->getTarget() == GL_TEXTURE_2D_ARRAY && getLayerCount(0) <= 0)
+ if (baseImage->getTarget() == GL_TEXTURE_2D_ARRAY && getLayerCount(getBaseLevel()) <= 0)
{
return true;
}
@@ -539,12 +551,16 @@ bool TextureD3D::isBaseImageZeroSize() const
return false;
}
-gl::Error TextureD3D::ensureRenderTarget()
+gl::Error TextureD3D::ensureRenderTarget(const gl::Context *context)
{
- gl::Error error = initializeStorage(true);
- if (error.isError())
+ ANGLE_TRY(initializeStorage(context, true));
+
+ // initializeStorage can fail with NoError if the texture is not complete. This is not
+ // an error for incomplete sampling, but it is a big problem for rendering.
+ if (!mTexStorage)
{
- return error;
+ UNREACHABLE();
+ return gl::InternalError() << "Cannot render to incomplete texture.";
}
if (!isBaseImageZeroSize())
@@ -552,94 +568,210 @@ gl::Error TextureD3D::ensureRenderTarget()
ASSERT(mTexStorage);
if (!mTexStorage->isRenderTarget())
{
- TextureStorage *newRenderTargetStorage = NULL;
- error = createCompleteStorage(true, &newRenderTargetStorage);
- if (error.isError())
- {
- return error;
- }
+ TexStoragePointer newRenderTargetStorage(context);
+ ANGLE_TRY(createCompleteStorage(true, &newRenderTargetStorage));
- error = mTexStorage->copyToStorage(newRenderTargetStorage);
- if (error.isError())
- {
- SafeDelete(newRenderTargetStorage);
- return error;
- }
-
- error = setCompleteTexStorage(newRenderTargetStorage);
- if (error.isError())
- {
- SafeDelete(newRenderTargetStorage);
- return error;
- }
+ ANGLE_TRY(mTexStorage->copyToStorage(context, newRenderTargetStorage.get()));
+ ANGLE_TRY(setCompleteTexStorage(context, newRenderTargetStorage.get()));
+ newRenderTargetStorage.release();
}
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
bool TextureD3D::canCreateRenderTargetForImage(const gl::ImageIndex &index) const
{
+ if (index.type == GL_TEXTURE_2D_MULTISAMPLE)
+ return true;
+
ImageD3D *image = getImage(index);
+ ASSERT(image);
bool levelsComplete = (isImageComplete(index) && isImageComplete(getImageIndex(0, 0)));
return (image->isRenderableFormat() && levelsComplete);
}
-gl::Error TextureD3D::commitRegion(const gl::ImageIndex &index, const gl::Box &region)
+gl::Error TextureD3D::commitRegion(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &region)
{
if (mTexStorage)
{
ASSERT(isValidIndex(index));
ImageD3D *image = getImage(index);
- gl::Error error = image->copyToStorage(mTexStorage, index, region);
- if (error.isError())
- {
- return error;
- }
-
+ ANGLE_TRY(image->copyToStorage(context, mTexStorage, index, region));
image->markClean();
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D::getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target,
+gl::Error TextureD3D::getAttachmentRenderTarget(const gl::Context *context,
+ GLenum /*binding*/,
+ const gl::ImageIndex &imageIndex,
FramebufferAttachmentRenderTarget **rtOut)
{
RenderTargetD3D *rtD3D = nullptr;
- gl::Error error = getRenderTarget(target.textureIndex(), &rtD3D);
+ gl::Error error = getRenderTarget(context, imageIndex, &rtD3D);
*rtOut = static_cast<FramebufferAttachmentRenderTarget *>(rtD3D);
return error;
}
-TextureD3D_2D::TextureD3D_2D(RendererD3D *renderer)
- : TextureD3D(renderer)
+gl::Error TextureD3D::setBaseLevel(const gl::Context *context, GLuint baseLevel)
+{
+ const int oldStorageWidth = std::max(1, getLevelZeroWidth());
+ const int oldStorageHeight = std::max(1, getLevelZeroHeight());
+ const int oldStorageDepth = std::max(1, getLevelZeroDepth());
+ const int oldStorageFormat = getBaseLevelInternalFormat();
+ mBaseLevel = baseLevel;
+
+ // When the base level changes, the texture storage might not be valid anymore, since it could
+ // have been created based on the dimensions of the previous specified level range.
+ const int newStorageWidth = std::max(1, getLevelZeroWidth());
+ const int newStorageHeight = std::max(1, getLevelZeroHeight());
+ const int newStorageDepth = std::max(1, getLevelZeroDepth());
+ const int newStorageFormat = getBaseLevelInternalFormat();
+ if (mTexStorage &&
+ (newStorageWidth != oldStorageWidth || newStorageHeight != oldStorageHeight ||
+ newStorageDepth != oldStorageDepth || newStorageFormat != oldStorageFormat))
+ {
+ markAllImagesDirty();
+ ANGLE_TRY(releaseTexStorage(context));
+ }
+
+ return gl::NoError();
+}
+
+void TextureD3D::syncState(const gl::Texture::DirtyBits &dirtyBits)
+{
+ // TODO(geofflang): Use dirty bits
+}
+
+gl::Error TextureD3D::releaseTexStorage(const gl::Context *context)
+{
+ if (!mTexStorage)
+ {
+ return gl::NoError();
+ }
+ auto err = mTexStorage->onDestroy(context);
+ SafeDelete(mTexStorage);
+ return err;
+}
+
+gl::Error TextureD3D::onDestroy(const gl::Context *context)
+{
+ return releaseTexStorage(context);
+}
+
+gl::Error TextureD3D::initializeContents(const gl::Context *context,
+ const gl::ImageIndex &imageIndexIn)
+{
+ gl::ImageIndex imageIndex = imageIndexIn;
+
+ // Special case for D3D11 3D textures. We can't create render targets for individual layers of a
+ // 3D texture, so force the clear to the entire mip. There shouldn't ever be a case where we
+ // would lose existing data.
+ if (imageIndex.type == GL_TEXTURE_3D)
+ {
+ imageIndex.layerIndex = gl::ImageIndex::ENTIRE_LEVEL;
+ }
+ else if (imageIndex.type == GL_TEXTURE_2D_ARRAY &&
+ imageIndex.layerIndex == gl::ImageIndex::ENTIRE_LEVEL)
+ {
+ GLsizei layerCount = getLayerCount(imageIndex.mipIndex);
+ for (imageIndex.layerIndex = 0; imageIndex.layerIndex < layerCount; ++imageIndex.layerIndex)
+ {
+ ANGLE_TRY(initializeContents(context, imageIndex));
+ }
+ return gl::NoError();
+ }
+
+ // Force image clean.
+ ImageD3D *image = getImage(imageIndex);
+ if (image)
+ {
+ image->markClean();
+ }
+
+ // Fast path: can use a render target clear.
+ if (canCreateRenderTargetForImage(imageIndex))
+ {
+ ANGLE_TRY(ensureRenderTarget(context));
+ ASSERT(mTexStorage);
+ RenderTargetD3D *renderTarget = nullptr;
+ ANGLE_TRY(mTexStorage->getRenderTarget(context, imageIndex, &renderTarget));
+ ANGLE_TRY(mRenderer->initRenderTarget(renderTarget));
+ return gl::NoError();
+ }
+
+ // Slow path: non-renderable texture or the texture levels aren't set up.
+ const auto &formatInfo = gl::GetSizedInternalFormatInfo(image->getInternalFormat());
+
+ size_t imageBytes = 0;
+ ANGLE_TRY_RESULT(formatInfo.computeRowPitch(formatInfo.type, image->getWidth(), 1, 0),
+ imageBytes);
+ imageBytes *= image->getHeight() * image->getDepth();
+
+ gl::PixelUnpackState defaultUnpackState;
+
+ angle::MemoryBuffer *zeroBuffer = nullptr;
+ ANGLE_TRY(context->getZeroFilledBuffer(imageBytes, &zeroBuffer));
+ if (shouldUseSetData(image))
+ {
+ ANGLE_TRY(mTexStorage->setData(context, imageIndex, image, nullptr, formatInfo.type,
+ defaultUnpackState, zeroBuffer->data()));
+ }
+ else
+ {
+ gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth());
+ ANGLE_TRY(image->loadData(context, fullImageArea, defaultUnpackState, formatInfo.type,
+ zeroBuffer->data(), false));
+
+ // Force an update to the tex storage so we avoid problems with subImage and dirty regions.
+ if (mTexStorage)
+ {
+ ANGLE_TRY(commitRegion(context, imageIndex, fullImageArea));
+ image->markClean();
+ }
+ else
+ {
+ mDirtyImages = true;
+ }
+ }
+ return gl::NoError();
+}
+
+TextureD3D_2D::TextureD3D_2D(const gl::TextureState &state, RendererD3D *renderer)
+ : TextureD3D(state, renderer)
{
mEGLImageTarget = false;
- for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
+ for (auto &image : mImageArray)
{
- mImageArray[i] = renderer->createImage();
+ image.reset(renderer->createImage());
}
}
-TextureD3D_2D::~TextureD3D_2D()
+gl::Error TextureD3D_2D::onDestroy(const gl::Context *context)
{
- // Delete the Images before the TextureStorage.
- // Images might be relying on the TextureStorage for some of their data.
- // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images.
- for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
+ // Delete the Images before the TextureStorage. Images might be relying on the TextureStorage
+ // for some of their data. If TextureStorage is deleted before the Images, then their data will
+ // be wastefully copied back from the GPU before we delete the Images.
+ for (auto &image : mImageArray)
{
- delete mImageArray[i];
+ image.reset();
}
+ return TextureD3D::onDestroy(context);
+}
- SafeDelete(mTexStorage);
+TextureD3D_2D::~TextureD3D_2D()
+{
}
ImageD3D *TextureD3D_2D::getImage(int level, int layer) const
{
ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
ASSERT(layer == 0);
- return mImageArray[level];
+ return mImageArray[level].get();
}
ImageD3D *TextureD3D_2D::getImage(const gl::ImageIndex &index) const
@@ -647,7 +779,7 @@ ImageD3D *TextureD3D_2D::getImage(const gl::ImageIndex &index) const
ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
ASSERT(!index.hasLayer());
ASSERT(index.type == GL_TEXTURE_2D);
- return mImageArray[index.mipIndex];
+ return mImageArray[index.mipIndex].get();
}
GLsizei TextureD3D_2D::getLayerCount(int level) const
@@ -682,10 +814,16 @@ GLenum TextureD3D_2D::getInternalFormat(GLint level) const
bool TextureD3D_2D::isDepth(GLint level) const
{
- return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
+ return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
+}
+
+bool TextureD3D_2D::isSRGB(GLint level) const
+{
+ return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).colorEncoding == GL_SRGB;
}
-gl::Error TextureD3D_2D::setImage(GLenum target,
+gl::Error TextureD3D_2D::setImage(const gl::Context *context,
+ GLenum target,
size_t imageLevel,
GLenum internalFormat,
const gl::Extents &size,
@@ -696,33 +834,29 @@ gl::Error TextureD3D_2D::setImage(GLenum target,
{
ASSERT(target == GL_TEXTURE_2D && size.depth == 1);
- GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
+ const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
bool fastUnpacked = false;
GLint level = static_cast<GLint>(imageLevel);
- redefineImage(level, sizedInternalFormat, size, false);
+ ANGLE_TRY(redefineImage(context, level, internalFormatInfo.sizedInternalFormat, size, false));
gl::ImageIndex index = gl::ImageIndex::Make2D(level);
// Attempt a fast gpu copy of the pixel data to the surface
- if (isFastUnpackable(unpack, sizedInternalFormat) && isLevelComplete(level))
+ gl::Buffer *unpackBuffer =
+ context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
+ if (isFastUnpackable(unpackBuffer, internalFormatInfo.sizedInternalFormat) &&
+ isLevelComplete(level))
{
// Will try to create RT storage if it does not exist
- RenderTargetD3D *destRenderTarget = NULL;
- gl::Error error = getRenderTarget(index, &destRenderTarget);
- if (error.isError())
- {
- return error;
- }
+ RenderTargetD3D *destRenderTarget = nullptr;
+ ANGLE_TRY(getRenderTarget(context, index, &destRenderTarget));
gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1);
- error = fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(fastUnpackPixels(context, unpack, pixels, destArea,
+ internalFormatInfo.sizedInternalFormat, type, destRenderTarget));
// Ensure we don't overwrite our newly initialized data
mImageArray[level]->markClean();
@@ -732,17 +866,14 @@ gl::Error TextureD3D_2D::setImage(GLenum target,
if (!fastUnpacked)
{
- gl::Error error = setImageImpl(index, type, unpack, pixels, 0);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(setImageImpl(context, index, type, unpack, pixels, 0));
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D_2D::setSubImage(GLenum target,
+gl::Error TextureD3D_2D::setSubImage(const gl::Context *context,
+ GLenum target,
size_t imageLevel,
const gl::Box &area,
GLenum format,
@@ -754,26 +885,26 @@ gl::Error TextureD3D_2D::setSubImage(GLenum target,
GLint level = static_cast<GLint>(imageLevel);
gl::ImageIndex index = gl::ImageIndex::Make2D(level);
- if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level))
- {
- RenderTargetD3D *renderTarget = NULL;
- gl::Error error = getRenderTarget(index, &renderTarget);
- if (error.isError())
- {
- return error;
- }
+ gl::Buffer *unpackBuffer =
+ context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
+ if (isFastUnpackable(unpackBuffer, getInternalFormat(level)) && isLevelComplete(level))
+ {
+ RenderTargetD3D *renderTarget = nullptr;
+ ANGLE_TRY(getRenderTarget(context, index, &renderTarget));
ASSERT(!mImageArray[level]->isDirty());
- return fastUnpackPixels(unpack, pixels, area, getInternalFormat(level), type, renderTarget);
+ return fastUnpackPixels(context, unpack, pixels, area, getInternalFormat(level), type,
+ renderTarget);
}
else
{
- return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0);
+ return TextureD3D::subImage(context, index, area, format, type, unpack, pixels, 0);
}
}
-gl::Error TextureD3D_2D::setCompressedImage(GLenum target,
+gl::Error TextureD3D_2D::setCompressedImage(const gl::Context *context,
+ GLenum target,
size_t imageLevel,
GLenum internalFormat,
const gl::Extents &size,
@@ -785,84 +916,120 @@ gl::Error TextureD3D_2D::setCompressedImage(GLenum target,
GLint level = static_cast<GLint>(imageLevel);
// compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
- redefineImage(level, internalFormat, size, false);
+ ANGLE_TRY(redefineImage(context, level, internalFormat, size, false));
- return setCompressedImageImpl(gl::ImageIndex::Make2D(level), unpack, pixels, 0);
+ return setCompressedImageImpl(context, gl::ImageIndex::Make2D(level), unpack, pixels, 0);
}
-gl::Error TextureD3D_2D::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
- const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels)
+gl::Error TextureD3D_2D::setCompressedSubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
{
ASSERT(target == GL_TEXTURE_2D && area.depth == 1 && area.z == 0);
gl::ImageIndex index = gl::ImageIndex::Make2D(static_cast<GLint>(level));
- gl::Error error = TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(TextureD3D::subImageCompressed(context, index, area, format, unpack, pixels, 0));
- return commitRegion(index, area);
+ return commitRegion(context, index, area);
}
-gl::Error TextureD3D_2D::copyImage(GLenum target,
+gl::Error TextureD3D_2D::copyImage(const gl::Context *context,
+ GLenum target,
size_t imageLevel,
- const gl::Rectangle &sourceArea,
+ const gl::Rectangle &origSourceArea,
GLenum internalFormat,
const gl::Framebuffer *source)
{
ASSERT(target == GL_TEXTURE_2D);
- GLint level = static_cast<GLint>(imageLevel);
- GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE);
- redefineImage(level, sizedInternalFormat, gl::Extents(sourceArea.width, sourceArea.height, 1),
- false);
+ GLint level = static_cast<GLint>(imageLevel);
+ const gl::InternalFormat &internalFormatInfo =
+ gl::GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);
+ gl::Extents sourceExtents(origSourceArea.width, origSourceArea.height, 1);
+ ANGLE_TRY(redefineImage(context, level, internalFormatInfo.sizedInternalFormat, sourceExtents,
+ false));
+
+ gl::Extents fbSize = source->getReadColorbuffer()->getSize();
+
+ // Does the read area extend beyond the framebuffer?
+ bool outside = origSourceArea.x < 0 || origSourceArea.y < 0 ||
+ origSourceArea.x + origSourceArea.width > fbSize.width ||
+ origSourceArea.y + origSourceArea.height > fbSize.height;
+
+ // In WebGL mode we need to zero the texture outside the framebuffer.
+ // If we have robust resource init, it was already zeroed by redefineImage() above, otherwise
+ // zero it explicitly.
+ // TODO(fjhenigman): When robust resource is fully implemented look into making it a
+ // prerequisite for WebGL and deleting this code.
+ if (outside &&
+ (context->getExtensions().webglCompatibility || context->isRobustResourceInitEnabled()))
+ {
+ angle::MemoryBuffer *zero;
+ ANGLE_TRY(context->getZeroFilledBuffer(
+ origSourceArea.width * origSourceArea.height * internalFormatInfo.pixelBytes, &zero));
+ gl::PixelUnpackState unpack;
+ unpack.alignment = 1;
+ ANGLE_TRY(setImage(context, target, imageLevel, internalFormat, sourceExtents,
+ internalFormatInfo.format, internalFormatInfo.type, unpack,
+ zero->data()));
+ }
+
+ gl::Rectangle sourceArea;
+ if (!ClipRectangle(origSourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height),
+ &sourceArea))
+ {
+ // Empty source area, nothing to do.
+ return gl::NoError();
+ }
gl::ImageIndex index = gl::ImageIndex::Make2D(level);
- gl::Offset destOffset(0, 0, 0);
+ gl::Offset destOffset(sourceArea.x - origSourceArea.x, sourceArea.y - origSourceArea.y, 0);
// If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders,
// so we should use the non-rendering copy path.
if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
- gl::Error error = mImageArray[level]->copyFromFramebuffer(destOffset, sourceArea, source);
- if (error.isError())
- {
- return error;
- }
-
+ ANGLE_TRY(mImageArray[level]->copyFromFramebuffer(context, destOffset, sourceArea, source));
mDirtyImages = true;
}
else
{
- gl::Error error = ensureRenderTarget();
- if (error.isError())
- {
- return error;
- }
-
- mImageArray[level]->markClean();
+ ANGLE_TRY(ensureRenderTarget(context));
if (sourceArea.width != 0 && sourceArea.height != 0 && isValidLevel(level))
{
- error = mRenderer->copyImage2D(source, sourceArea, internalFormat, destOffset, mTexStorage, level);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(updateStorageLevel(context, level));
+ ANGLE_TRY(mRenderer->copyImage2D(context, source, sourceArea, internalFormat,
+ destOffset, mTexStorage, level));
}
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D_2D::copySubImage(GLenum target,
+gl::Error TextureD3D_2D::copySubImage(const gl::Context *context,
+ GLenum target,
size_t imageLevel,
- const gl::Offset &destOffset,
- const gl::Rectangle &sourceArea,
+ const gl::Offset &origDestOffset,
+ const gl::Rectangle &origSourceArea,
const gl::Framebuffer *source)
{
- ASSERT(target == GL_TEXTURE_2D && destOffset.z == 0);
+ ASSERT(target == GL_TEXTURE_2D && origDestOffset.z == 0);
+
+ gl::Extents fbSize = source->getReadColorbuffer()->getSize();
+ gl::Rectangle sourceArea;
+ if (!ClipRectangle(origSourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height),
+ &sourceArea))
+ {
+ return gl::NoError();
+ }
+ const gl::Offset destOffset(origDestOffset.x + sourceArea.x - origSourceArea.x,
+ origDestOffset.y + sourceArea.y - origSourceArea.y, 0);
// can only make our texture storage to a render target if level 0 is defined (with a width & height) and
// the current level we're copying to is defined (with appropriate format, width & height)
@@ -874,44 +1041,162 @@ gl::Error TextureD3D_2D::copySubImage(GLenum target,
// so we should use the non-rendering copy path.
if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
- gl::Error error = mImageArray[level]->copyFromFramebuffer(destOffset, sourceArea, source);
- if (error.isError())
+ ANGLE_TRY(mImageArray[level]->copyFromFramebuffer(context, destOffset, sourceArea, source));
+ mDirtyImages = true;
+ }
+ else
+ {
+ ANGLE_TRY(ensureRenderTarget(context));
+
+ if (isValidLevel(level))
{
- return error;
+ ANGLE_TRY(updateStorageLevel(context, level));
+ ANGLE_TRY(mRenderer->copyImage2D(context, source, sourceArea,
+ gl::GetUnsizedFormat(getBaseLevelInternalFormat()),
+ destOffset, mTexStorage, level));
}
+ }
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_2D::copyTexture(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ GLenum type,
+ size_t sourceLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source)
+{
+ ASSERT(target == GL_TEXTURE_2D);
+
+ GLenum sourceTarget = source->getTarget();
+
+ GLint destLevel = static_cast<GLint>(level);
+
+ const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
+ gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevel)),
+ static_cast<int>(source->getHeight(sourceTarget, sourceLevel)), 1);
+ ANGLE_TRY(
+ redefineImage(context, destLevel, internalFormatInfo.sizedInternalFormat, size, false));
+
+ gl::Rectangle sourceRect(0, 0, size.width, size.height);
+ gl::Offset destOffset(0, 0, 0);
+
+ if (!isSRGB(destLevel) && canCreateRenderTargetForImage(gl::ImageIndex::Make2D(destLevel)))
+ {
+ ANGLE_TRY(ensureRenderTarget(context));
+ ASSERT(isValidLevel(destLevel));
+ ANGLE_TRY(updateStorageLevel(context, destLevel));
+
+ ANGLE_TRY(mRenderer->copyTexture(context, source, static_cast<GLint>(sourceLevel),
+ sourceRect, internalFormatInfo.format, destOffset,
+ mTexStorage, target, destLevel, unpackFlipY,
+ unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+ }
+ else
+ {
+ gl::ImageIndex sourceImageIndex = gl::ImageIndex::Make2D(static_cast<GLint>(sourceLevel));
+ TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
+ ImageD3D *sourceImage = nullptr;
+ ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, sourceImageIndex, &sourceImage));
+
+ gl::ImageIndex destImageIndex = gl::ImageIndex::Make2D(static_cast<GLint>(destLevel));
+ ImageD3D *destImage = nullptr;
+ ANGLE_TRY(getImageAndSyncFromStorage(context, destImageIndex, &destImage));
+
+ ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, sourceRect, destOffset,
+ unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
mDirtyImages = true;
+
+ gl::Box destRegion(destOffset, size);
+ ANGLE_TRY(commitRegion(context, destImageIndex, destRegion));
+ }
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_2D::copySubTexture(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Offset &destOffset,
+ size_t sourceLevel,
+ const gl::Rectangle &sourceArea,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source)
+{
+ ASSERT(target == GL_TEXTURE_2D);
+
+ GLint destLevel = static_cast<GLint>(level);
+
+ if (!isSRGB(destLevel) && canCreateRenderTargetForImage(gl::ImageIndex::Make2D(destLevel)))
+ {
+ ANGLE_TRY(ensureRenderTarget(context));
+ ASSERT(isValidLevel(destLevel));
+ ANGLE_TRY(updateStorageLevel(context, destLevel));
+
+ ANGLE_TRY(mRenderer->copyTexture(
+ context, source, static_cast<GLint>(sourceLevel), sourceArea,
+ gl::GetUnsizedFormat(getInternalFormat(destLevel)), destOffset, mTexStorage, target,
+ destLevel, unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
}
else
{
- gl::Error error = ensureRenderTarget();
- if (error.isError())
- {
- return error;
- }
+ gl::ImageIndex sourceImageIndex = gl::ImageIndex::Make2D(static_cast<GLint>(sourceLevel));
+ TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
+ ImageD3D *sourceImage = nullptr;
+ ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, sourceImageIndex, &sourceImage));
- if (isValidLevel(level))
- {
- error = updateStorageLevel(level);
- if (error.isError())
- {
- return error;
- }
+ gl::ImageIndex destImageIndex = gl::ImageIndex::Make2D(static_cast<GLint>(destLevel));
+ ImageD3D *destImage = nullptr;
+ ANGLE_TRY(getImageAndSyncFromStorage(context, destImageIndex, &destImage));
- error = mRenderer->copyImage2D(source, sourceArea,
- gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
- destOffset, mTexStorage, level);
- if (error.isError())
- {
- return error;
- }
- }
+ ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, sourceArea, destOffset,
+ unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+
+ mDirtyImages = true;
+
+ gl::Box destRegion(destOffset.x, destOffset.y, 0, sourceArea.width, sourceArea.height, 1);
+ ANGLE_TRY(commitRegion(context, destImageIndex, destRegion));
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_2D::copyCompressedTexture(const gl::Context *context,
+ const gl::Texture *source)
+{
+ GLenum sourceTarget = source->getTarget();
+ GLint sourceLevel = 0;
+
+ GLint destLevel = 0;
+
+ GLenum sizedInternalFormat =
+ source->getFormat(sourceTarget, sourceLevel).info->sizedInternalFormat;
+ gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevel)),
+ static_cast<int>(source->getHeight(sourceTarget, sourceLevel)), 1);
+ ANGLE_TRY(redefineImage(context, destLevel, sizedInternalFormat, size, false));
+
+ ANGLE_TRY(initializeStorage(context, false));
+ ASSERT(mTexStorage);
+
+ ANGLE_TRY(
+ mRenderer->copyCompressedTexture(context, source, sourceLevel, mTexStorage, destLevel));
+
+ return gl::NoError();
}
-gl::Error TextureD3D_2D::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size)
+gl::Error TextureD3D_2D::setStorage(const gl::Context *context,
+ GLenum target,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size)
{
ASSERT(GL_TEXTURE_2D && size.depth == 1);
@@ -920,49 +1205,38 @@ gl::Error TextureD3D_2D::setStorage(GLenum target, size_t levels, GLenum interna
gl::Extents levelSize(std::max(1, size.width >> level),
std::max(1, size.height >> level),
1);
- redefineImage(level, internalFormat, levelSize, true);
+ ANGLE_TRY(redefineImage(context, level, internalFormat, levelSize, true));
}
for (size_t level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
{
- redefineImage(level, GL_NONE, gl::Extents(0, 0, 1), true);
+ ANGLE_TRY(redefineImage(context, level, GL_NONE, gl::Extents(0, 0, 1), true));
}
// TODO(geofflang): Verify storage creation had no errors
- bool renderTarget = IsRenderTargetUsage(mUsage);
- TextureStorage *storage = mRenderer->createTextureStorage2D(
- internalFormat, renderTarget, size.width, size.height, static_cast<int>(levels), false);
+ bool renderTarget = IsRenderTargetUsage(mState.getUsage());
+ TexStoragePointer storage(context);
+ storage.reset(mRenderer->createTextureStorage2D(internalFormat, renderTarget, size.width,
+ size.height, static_cast<int>(levels), false));
- gl::Error error = setCompleteTexStorage(storage);
- if (error.isError())
- {
- SafeDelete(storage);
- return error;
- }
-
- error = updateStorage();
+ ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+ storage.release();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(updateStorage(context));
mImmutable = true;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-void TextureD3D_2D::bindTexImage(egl::Surface *surface)
+gl::Error TextureD3D_2D::bindTexImage(const gl::Context *context, egl::Surface *surface)
{
GLenum internalformat = surface->getConfig()->renderTargetFormat;
gl::Extents size(surface->getWidth(), surface->getHeight(), 1);
- redefineImage(0, internalformat, size, true);
+ ANGLE_TRY(redefineImage(context, 0, internalformat, size, true));
- if (mTexStorage)
- {
- SafeDelete(mTexStorage);
- }
+ ANGLE_TRY(releaseTexStorage(context));
SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
ASSERT(surfaceD3D);
@@ -970,78 +1244,84 @@ void TextureD3D_2D::bindTexImage(egl::Surface *surface)
mTexStorage = mRenderer->createTextureStorage2D(surfaceD3D->getSwapChain());
mEGLImageTarget = false;
- mDirtyImages = true;
+ mDirtyImages = false;
+ mImageArray[0]->markClean();
+
+ return gl::NoError();
}
-void TextureD3D_2D::releaseTexImage()
+gl::Error TextureD3D_2D::releaseTexImage(const gl::Context *context)
{
if (mTexStorage)
{
- SafeDelete(mTexStorage);
+ ANGLE_TRY(releaseTexStorage(context));
}
for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
- redefineImage(i, GL_NONE, gl::Extents(0, 0, 1), true);
+ ANGLE_TRY(redefineImage(context, i, GL_NONE, gl::Extents(0, 0, 1), true));
}
+
+ return gl::NoError();
}
-gl::Error TextureD3D_2D::setEGLImageTarget(GLenum target, egl::Image *image)
+gl::Error TextureD3D_2D::setEGLImageTarget(const gl::Context *context,
+ GLenum target,
+ egl::Image *image)
{
EGLImageD3D *eglImaged3d = GetImplAs<EGLImageD3D>(image);
// Set the properties of the base mip level from the EGL image
- GLenum internalformat = image->getInternalFormat();
+ const auto &format = image->getFormat();
gl::Extents size(static_cast<int>(image->getWidth()), static_cast<int>(image->getHeight()), 1);
- redefineImage(0, internalformat, size, true);
+ ANGLE_TRY(redefineImage(context, 0, format.info->sizedInternalFormat, size, true));
// Clear all other images.
- for (size_t level = 1; level < ArraySize(mImageArray); level++)
+ for (size_t level = 1; level < mImageArray.size(); level++)
{
- redefineImage(level, GL_NONE, gl::Extents(0, 0, 1), true);
+ ANGLE_TRY(redefineImage(context, level, GL_NONE, gl::Extents(0, 0, 1), true));
}
- SafeDelete(mTexStorage);
+ ANGLE_TRY(releaseTexStorage(context));
mImageArray[0]->markClean();
- mTexStorage = mRenderer->createTextureStorageEGLImage(eglImaged3d);
+ // Pass in the RenderTargetD3D here: createTextureStorage can't generate an error.
+ RenderTargetD3D *renderTargetD3D = nullptr;
+ ANGLE_TRY(eglImaged3d->getRenderTarget(context, &renderTargetD3D));
+
+ mTexStorage = mRenderer->createTextureStorageEGLImage(eglImaged3d, renderTargetD3D);
mEGLImageTarget = true;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-void TextureD3D_2D::initMipmapsImages()
+gl::Error TextureD3D_2D::initMipmapImages(const gl::Context *context)
{
- // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
- int levelCount = mipLevels();
- for (int level = 1; level < levelCount; level++)
+ const GLuint baseLevel = mState.getEffectiveBaseLevel();
+ const GLuint maxLevel = mState.getMipmapMaxLevel();
+ // Purge array levels baseLevel + 1 through q and reset them to represent the generated mipmap
+ // levels.
+ for (GLuint level = baseLevel + 1; level <= maxLevel; level++)
{
- gl::Extents levelSize(std::max(getBaseLevelWidth() >> level, 1),
- std::max(getBaseLevelHeight() >> level, 1),
- 1);
+ gl::Extents levelSize(std::max(getLevelZeroWidth() >> level, 1),
+ std::max(getLevelZeroHeight() >> level, 1), 1);
- redefineImage(level, getBaseLevelInternalFormat(), levelSize, false);
+ ANGLE_TRY(redefineImage(context, level, getBaseLevelInternalFormat(), levelSize, false));
}
+ return gl::NoError();
}
-gl::Error TextureD3D_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+gl::Error TextureD3D_2D::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT)
{
ASSERT(!index.hasLayer());
// ensure the underlying texture is created
- gl::Error error = ensureRenderTarget();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(ensureRenderTarget(context));
+ ANGLE_TRY(updateStorageLevel(context, index.mipIndex));
- error = updateStorageLevel(index.mipIndex);
- if (error.isError())
- {
- return error;
- }
-
- return mTexStorage->getRenderTarget(index, outRT);
+ return mTexStorage->getRenderTarget(context, index, outRT);
}
bool TextureD3D_2D::isValidLevel(int level) const
@@ -1056,10 +1336,8 @@ bool TextureD3D_2D::isLevelComplete(int level) const
return true;
}
- const ImageD3D *baseImage = getBaseLevelImage();
-
- GLsizei width = baseImage->getWidth();
- GLsizei height = baseImage->getHeight();
+ GLsizei width = getLevelZeroWidth();
+ GLsizei height = getLevelZeroHeight();
if (width <= 0 || height <= 0)
{
@@ -1067,15 +1345,16 @@ bool TextureD3D_2D::isLevelComplete(int level) const
}
// The base image level is complete if the width and height are positive
- if (level == 0)
+ if (level == static_cast<int>(getBaseLevel()))
{
return true;
}
- ASSERT(level >= 1 && level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
- ImageD3D *image = mImageArray[level];
+ ASSERT(level >= 0 && level <= static_cast<int>(mImageArray.size()) &&
+ mImageArray[level] != nullptr);
+ ImageD3D *image = mImageArray[level].get();
- if (image->getInternalFormat() != baseImage->getInternalFormat())
+ if (image->getInternalFormat() != getBaseLevelInternalFormat())
{
return false;
}
@@ -1099,52 +1378,41 @@ bool TextureD3D_2D::isImageComplete(const gl::ImageIndex &index) const
}
// Constructs a native texture resource from the texture images
-gl::Error TextureD3D_2D::initializeStorage(bool renderTarget)
+gl::Error TextureD3D_2D::initializeStorage(const gl::Context *context, bool renderTarget)
{
// Only initialize the first time this texture is used as a render target or shader resource
if (mTexStorage)
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
// do not attempt to create storage for nonexistant data
- if (!isLevelComplete(0))
+ if (!isLevelComplete(getBaseLevel()))
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
- bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage));
+ bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage()));
- TextureStorage *storage = NULL;
- gl::Error error = createCompleteStorage(createRenderTarget, &storage);
- if (error.isError())
- {
- return error;
- }
+ TexStoragePointer storage(context);
+ ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));
- error = setCompleteTexStorage(storage);
- if (error.isError())
- {
- SafeDelete(storage);
- return error;
- }
+ ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+ storage.release();
ASSERT(mTexStorage);
// flush image data to the storage
- error = updateStorage();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(updateStorage(context));
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D_2D::createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const
+gl::Error TextureD3D_2D::createCompleteStorage(bool renderTarget,
+ TexStoragePointer *outStorage) const
{
- GLsizei width = getBaseLevelWidth();
- GLsizei height = getBaseLevelHeight();
+ GLsizei width = getLevelZeroWidth();
+ GLsizei height = getLevelZeroHeight();
GLenum internalFormat = getBaseLevelInternalFormat();
ASSERT(width > 0 && height > 0);
@@ -1165,84 +1433,83 @@ gl::Error TextureD3D_2D::createCompleteStorage(bool renderTarget, TextureStorage
}
// TODO(geofflang): Determine if the texture creation succeeded
- *outTexStorage = mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height, levels, hintLevelZeroOnly);
+ outStorage->reset(mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height,
+ levels, hintLevelZeroOnly));
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D_2D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+gl::Error TextureD3D_2D::setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage)
{
if (newCompleteTexStorage && newCompleteTexStorage->isManaged())
{
for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++)
{
- gl::Error error = mImageArray[level]->setManagedSurface2D(newCompleteTexStorage, level);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(
+ mImageArray[level]->setManagedSurface2D(context, newCompleteTexStorage, level));
}
}
- SafeDelete(mTexStorage);
+ ANGLE_TRY(releaseTexStorage(context));
mTexStorage = newCompleteTexStorage;
mDirtyImages = true;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D_2D::updateStorage()
+gl::Error TextureD3D_2D::updateStorage(const gl::Context *context)
{
- ASSERT(mTexStorage != NULL);
+ if (!mDirtyImages)
+ {
+ return gl::NoError();
+ }
+
+ ASSERT(mTexStorage != nullptr);
GLint storageLevels = mTexStorage->getLevelCount();
for (int level = 0; level < storageLevels; level++)
{
if (mImageArray[level]->isDirty() && isLevelComplete(level))
{
- gl::Error error = updateStorageLevel(level);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(updateStorageLevel(context, level));
}
}
- return gl::Error(GL_NO_ERROR);
+ mDirtyImages = false;
+ return gl::NoError();
}
-gl::Error TextureD3D_2D::updateStorageLevel(int level)
+gl::Error TextureD3D_2D::updateStorageLevel(const gl::Context *context, int level)
{
- ASSERT(level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
+ ASSERT(level <= static_cast<int>(mImageArray.size()) && mImageArray[level] != nullptr);
ASSERT(isLevelComplete(level));
if (mImageArray[level]->isDirty())
{
gl::ImageIndex index = gl::ImageIndex::Make2D(level);
gl::Box region(0, 0, 0, getWidth(level), getHeight(level), 1);
- gl::Error error = commitRegion(index, region);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(commitRegion(context, index, region));
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-void TextureD3D_2D::redefineImage(size_t level,
- GLenum internalformat,
- const gl::Extents &size,
- bool forceRelease)
+gl::Error TextureD3D_2D::redefineImage(const gl::Context *context,
+ size_t level,
+ GLenum internalformat,
+ const gl::Extents &size,
+ bool forceRelease)
{
ASSERT(size.depth == 1);
// If there currently is a corresponding storage texture image, it has these parameters
- const int storageWidth = std::max(1, getBaseLevelWidth() >> level);
- const int storageHeight = std::max(1, getBaseLevelHeight() >> level);
+ const int storageWidth = std::max(1, getLevelZeroWidth() >> level);
+ const int storageHeight = std::max(1, getLevelZeroHeight() >> level);
const GLenum storageFormat = getBaseLevelInternalFormat();
mImageArray[level]->redefine(GL_TEXTURE_2D, internalformat, size, forceRelease);
+ mDirtyImages = mDirtyImages || mImageArray[level]->isDirty();
if (mTexStorage)
{
@@ -1252,27 +1519,23 @@ void TextureD3D_2D::redefineImage(size_t level,
// while orphaning
if (level != 0 && mEGLImageTarget)
{
- // TODO(jmadill): Don't discard error.
- mImageArray[0]->copyFromTexStorage(gl::ImageIndex::Make2D(0), mTexStorage);
+ ANGLE_TRY(mImageArray[0]->copyFromTexStorage(context, gl::ImageIndex::Make2D(0),
+ mTexStorage));
}
- if ((level >= storageLevels && storageLevels != 0) ||
- size.width != storageWidth ||
+ if ((level >= storageLevels && storageLevels != 0) || size.width != storageWidth ||
size.height != storageHeight ||
- internalformat != storageFormat) // Discard mismatched storage
+ internalformat != storageFormat) // Discard mismatched storage
{
- for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
- {
- mImageArray[i]->markDirty();
- }
-
- SafeDelete(mTexStorage);
- mDirtyImages = true;
+ ANGLE_TRY(releaseTexStorage(context));
+ markAllImagesDirty();
}
}
// Can't be an EGL image target after being redefined
mEGLImageTarget = false;
+
+ return gl::NoError();
}
gl::ImageIndexIterator TextureD3D_2D::imageIterator() const
@@ -1292,46 +1555,58 @@ bool TextureD3D_2D::isValidIndex(const gl::ImageIndex &index) const
index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount());
}
-TextureD3D_Cube::TextureD3D_Cube(RendererD3D *renderer)
- : TextureD3D(renderer)
+void TextureD3D_2D::markAllImagesDirty()
+{
+ for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ mImageArray[i]->markDirty();
+ }
+ mDirtyImages = true;
+}
+
+TextureD3D_Cube::TextureD3D_Cube(const gl::TextureState &state, RendererD3D *renderer)
+ : TextureD3D(state, renderer)
{
- for (int i = 0; i < 6; i++)
+ for (auto &face : mImageArray)
{
- for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j)
+ for (auto &image : face)
{
- mImageArray[i][j] = renderer->createImage();
+ image.reset(renderer->createImage());
}
}
}
-TextureD3D_Cube::~TextureD3D_Cube()
+gl::Error TextureD3D_Cube::onDestroy(const gl::Context *context)
{
- // Delete the Images before the TextureStorage.
- // Images might be relying on the TextureStorage for some of their data.
- // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images.
- for (int i = 0; i < 6; i++)
+ // Delete the Images before the TextureStorage. Images might be relying on the TextureStorage
+ // for some of their data. If TextureStorage is deleted before the Images, then their data will
+ // be wastefully copied back from the GPU before we delete the Images.
+ for (auto &face : mImageArray)
{
- for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j)
+ for (auto &image : face)
{
- SafeDelete(mImageArray[i][j]);
+ image.reset();
}
}
+ return TextureD3D::onDestroy(context);
+}
- SafeDelete(mTexStorage);
+TextureD3D_Cube::~TextureD3D_Cube()
+{
}
ImageD3D *TextureD3D_Cube::getImage(int level, int layer) const
{
ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
ASSERT(layer >= 0 && layer < 6);
- return mImageArray[layer][level];
+ return mImageArray[layer][level].get();
}
ImageD3D *TextureD3D_Cube::getImage(const gl::ImageIndex &index) const
{
ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
ASSERT(index.layerIndex >= 0 && index.layerIndex < 6);
- return mImageArray[index.layerIndex][index.mipIndex];
+ return mImageArray[index.layerIndex][index.mipIndex].get();
}
GLsizei TextureD3D_Cube::getLayerCount(int level) const
@@ -1350,128 +1625,191 @@ GLenum TextureD3D_Cube::getInternalFormat(GLint level, GLint layer) const
bool TextureD3D_Cube::isDepth(GLint level, GLint layer) const
{
- return gl::GetInternalFormatInfo(getInternalFormat(level, layer)).depthBits > 0;
+ return gl::GetSizedInternalFormatInfo(getInternalFormat(level, layer)).depthBits > 0;
}
-gl::Error TextureD3D_Cube::setEGLImageTarget(GLenum target, egl::Image *image)
+bool TextureD3D_Cube::isSRGB(GLint level, GLint layer) const
+{
+ return gl::GetSizedInternalFormatInfo(getInternalFormat(level, layer)).colorEncoding == GL_SRGB;
+}
+
+gl::Error TextureD3D_Cube::setEGLImageTarget(const gl::Context *context,
+ GLenum target,
+ egl::Image *image)
{
UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION);
+ return gl::InternalError();
}
-gl::Error TextureD3D_Cube::setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
- const gl::PixelUnpackState &unpack, const uint8_t *pixels)
+gl::Error TextureD3D_Cube::setImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels)
{
ASSERT(size.depth == 1);
- GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
+ const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level));
- redefineImage(index.layerIndex, static_cast<GLint>(level), sizedInternalFormat, size);
+ ANGLE_TRY(redefineImage(context, index.layerIndex, static_cast<GLint>(level),
+ internalFormatInfo.sizedInternalFormat, size, false));
- return setImageImpl(index, type, unpack, pixels, 0);
+ return setImageImpl(context, index, type, unpack, pixels, 0);
}
-gl::Error TextureD3D_Cube::setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
- const gl::PixelUnpackState &unpack, const uint8_t *pixels)
+gl::Error TextureD3D_Cube::setSubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels)
{
ASSERT(area.depth == 1 && area.z == 0);
gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level));
- return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0);
+ return TextureD3D::subImage(context, index, area, format, type, unpack, pixels, 0);
}
-gl::Error TextureD3D_Cube::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
- const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels)
+gl::Error TextureD3D_Cube::setCompressedImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
{
ASSERT(size.depth == 1);
// compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
size_t faceIndex = gl::CubeMapTextureTargetToLayerIndex(target);
- redefineImage(static_cast<int>(faceIndex), static_cast<GLint>(level), internalFormat, size);
+ ANGLE_TRY(redefineImage(context, static_cast<int>(faceIndex), static_cast<GLint>(level),
+ internalFormat, size, false));
gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level));
- return setCompressedImageImpl(index, unpack, pixels, 0);
+ return setCompressedImageImpl(context, index, unpack, pixels, 0);
}
-gl::Error TextureD3D_Cube::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
- const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels)
+gl::Error TextureD3D_Cube::setCompressedSubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
{
ASSERT(area.depth == 1 && area.z == 0);
gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level));
- gl::Error error = TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0);
- if (error.isError())
- {
- return error;
- }
-
- return commitRegion(index, area);
+ ANGLE_TRY(TextureD3D::subImageCompressed(context, index, area, format, unpack, pixels, 0));
+ return commitRegion(context, index, area);
}
-gl::Error TextureD3D_Cube::copyImage(GLenum target,
+gl::Error TextureD3D_Cube::copyImage(const gl::Context *context,
+ GLenum target,
size_t imageLevel,
- const gl::Rectangle &sourceArea,
+ const gl::Rectangle &origSourceArea,
GLenum internalFormat,
const gl::Framebuffer *source)
{
int faceIndex = static_cast<int>(gl::CubeMapTextureTargetToLayerIndex(target));
- GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE);
+ const gl::InternalFormat &internalFormatInfo =
+ gl::GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);
GLint level = static_cast<GLint>(imageLevel);
- gl::Extents size(sourceArea.width, sourceArea.height, 1);
- redefineImage(static_cast<int>(faceIndex), level, sizedInternalFormat, size);
+ gl::Extents size(origSourceArea.width, origSourceArea.height, 1);
+ ANGLE_TRY(redefineImage(context, static_cast<int>(faceIndex), level,
+ internalFormatInfo.sizedInternalFormat, size, false));
+
+ gl::Extents fbSize = source->getReadColorbuffer()->getSize();
+
+ // Does the read area extend beyond the framebuffer?
+ bool outside = origSourceArea.x < 0 || origSourceArea.y < 0 ||
+ origSourceArea.x + origSourceArea.width > fbSize.width ||
+ origSourceArea.y + origSourceArea.height > fbSize.height;
+
+ // In WebGL mode we need to zero the texture outside the framebuffer.
+ // If we have robust resource init, it was already zeroed by redefineImage() above, otherwise
+ // zero it explicitly.
+ // TODO(fjhenigman): When robust resource is fully implemented look into making it a
+ // prerequisite for WebGL and deleting this code.
+ if (outside && context->getExtensions().webglCompatibility &&
+ !context->isRobustResourceInitEnabled())
+ {
+ angle::MemoryBuffer *zero;
+ ANGLE_TRY(context->getZeroFilledBuffer(
+ origSourceArea.width * origSourceArea.height * internalFormatInfo.pixelBytes, &zero));
+ gl::PixelUnpackState unpack;
+ unpack.alignment = 1;
+ ANGLE_TRY(setImage(context, target, imageLevel, internalFormat, size,
+ internalFormatInfo.format, internalFormatInfo.type, unpack,
+ zero->data()));
+ }
+
+ gl::Rectangle sourceArea;
+ if (!ClipRectangle(origSourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height),
+ &sourceArea))
+ {
+ // Empty source area, nothing to do.
+ return gl::NoError();
+ }
gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
- gl::Offset destOffset(0, 0, 0);
+ gl::Offset destOffset(sourceArea.x - origSourceArea.x, sourceArea.y - origSourceArea.y, 0);
// If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders,
// so we should use the non-rendering copy path.
if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
- gl::Error error =
- mImageArray[faceIndex][level]->copyFromFramebuffer(destOffset, sourceArea, source);
- if (error.isError())
- {
- return error;
- }
-
+ ANGLE_TRY(mImageArray[faceIndex][level]->copyFromFramebuffer(context, destOffset,
+ sourceArea, source));
mDirtyImages = true;
}
else
{
- gl::Error error = ensureRenderTarget();
- if (error.isError())
- {
- return error;
- }
-
- mImageArray[faceIndex][level]->markClean();
+ ANGLE_TRY(ensureRenderTarget(context));
ASSERT(size.width == size.height);
if (size.width > 0 && isValidFaceLevel(faceIndex, level))
{
- error = mRenderer->copyImageCube(source, sourceArea, internalFormat, destOffset, mTexStorage, target, level);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, level));
+ ANGLE_TRY(mRenderer->copyImageCube(context, source, sourceArea, internalFormat,
+ destOffset, mTexStorage, target, level));
}
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D_Cube::copySubImage(GLenum target,
+gl::Error TextureD3D_Cube::copySubImage(const gl::Context *context,
+ GLenum target,
size_t imageLevel,
- const gl::Offset &destOffset,
- const gl::Rectangle &sourceArea,
+ const gl::Offset &origDestOffset,
+ const gl::Rectangle &origSourceArea,
const gl::Framebuffer *source)
{
+ gl::Extents fbSize = source->getReadColorbuffer()->getSize();
+ gl::Rectangle sourceArea;
+ if (!ClipRectangle(origSourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height),
+ &sourceArea))
+ {
+ return gl::NoError();
+ }
+ const gl::Offset destOffset(origDestOffset.x + sourceArea.x - origSourceArea.x,
+ origDestOffset.y + sourceArea.y - origSourceArea.y, 0);
+
int faceIndex = static_cast<int>(gl::CubeMapTextureTargetToLayerIndex(target));
GLint level = static_cast<GLint>(imageLevel);
@@ -1481,44 +1819,145 @@ gl::Error TextureD3D_Cube::copySubImage(GLenum target,
// so we should use the non-rendering copy path.
if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
- gl::Error error =
- mImageArray[faceIndex][level]->copyFromFramebuffer(destOffset, sourceArea, source);
- if (error.isError())
+ ANGLE_TRY(mImageArray[faceIndex][level]->copyFromFramebuffer(context, destOffset,
+ sourceArea, source));
+ mDirtyImages = true;
+ }
+ else
+ {
+ ANGLE_TRY(ensureRenderTarget(context));
+ if (isValidFaceLevel(faceIndex, level))
{
- return error;
+ ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, level));
+ ANGLE_TRY(mRenderer->copyImageCube(context, source, sourceArea,
+ gl::GetUnsizedFormat(getBaseLevelInternalFormat()),
+ destOffset, mTexStorage, target, level));
}
+ }
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_Cube::copyTexture(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ GLenum type,
+ size_t sourceLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source)
+{
+ ASSERT(gl::IsCubeMapTextureTarget(target));
+
+ GLenum sourceTarget = source->getTarget();
+
+ GLint destLevel = static_cast<GLint>(level);
+ int faceIndex = static_cast<int>(gl::CubeMapTextureTargetToLayerIndex(target));
+
+ const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
+ gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevel)),
+ static_cast<int>(source->getHeight(sourceTarget, sourceLevel)), 1);
+ ANGLE_TRY(redefineImage(context, faceIndex, destLevel, internalFormatInfo.sizedInternalFormat,
+ size, false));
+
+ gl::Rectangle sourceRect(0, 0, size.width, size.height);
+ gl::Offset destOffset(0, 0, 0);
+
+ if (!isSRGB(destLevel, faceIndex) &&
+ canCreateRenderTargetForImage(gl::ImageIndex::MakeCube(target, destLevel)))
+ {
+ ANGLE_TRY(ensureRenderTarget(context));
+ ASSERT(isValidFaceLevel(faceIndex, destLevel));
+ ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, destLevel));
+
+ ANGLE_TRY(mRenderer->copyTexture(context, source, static_cast<GLint>(sourceLevel),
+ sourceRect, internalFormatInfo.format, destOffset,
+ mTexStorage, target, destLevel, unpackFlipY,
+ unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+ }
+ else
+ {
+ gl::ImageIndex sourceImageIndex = gl::ImageIndex::Make2D(static_cast<GLint>(sourceLevel));
+ TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
+ ImageD3D *sourceImage = nullptr;
+ ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, sourceImageIndex, &sourceImage));
+
+ gl::ImageIndex destImageIndex =
+ gl::ImageIndex::MakeCube(target, static_cast<GLint>(destLevel));
+ ImageD3D *destImage = nullptr;
+ ANGLE_TRY(getImageAndSyncFromStorage(context, destImageIndex, &destImage));
+
+ ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, sourceRect, destOffset,
+ unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
mDirtyImages = true;
+
+ gl::Box destRegion(destOffset, size);
+ ANGLE_TRY(commitRegion(context, destImageIndex, destRegion));
+ }
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_Cube::copySubTexture(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Offset &destOffset,
+ size_t sourceLevel,
+ const gl::Rectangle &sourceArea,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source)
+{
+ ASSERT(gl::IsCubeMapTextureTarget(target));
+
+ GLint destLevel = static_cast<GLint>(level);
+ int faceIndex = static_cast<int>(gl::CubeMapTextureTargetToLayerIndex(target));
+
+ if (!isSRGB(destLevel, faceIndex) &&
+ canCreateRenderTargetForImage(gl::ImageIndex::MakeCube(target, destLevel)))
+ {
+ ANGLE_TRY(ensureRenderTarget(context));
+ ASSERT(isValidFaceLevel(faceIndex, destLevel));
+ ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, destLevel));
+
+ ANGLE_TRY(mRenderer->copyTexture(
+ context, source, static_cast<GLint>(sourceLevel), sourceArea,
+ gl::GetUnsizedFormat(getInternalFormat(destLevel, faceIndex)), destOffset, mTexStorage,
+ target, destLevel, unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
}
else
{
- gl::Error error = ensureRenderTarget();
- if (error.isError())
- {
- return error;
- }
+ gl::ImageIndex sourceImageIndex = gl::ImageIndex::Make2D(static_cast<GLint>(sourceLevel));
+ TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
+ ImageD3D *sourceImage = nullptr;
+ ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, sourceImageIndex, &sourceImage));
- if (isValidFaceLevel(faceIndex, level))
- {
- error = updateStorageFaceLevel(faceIndex, level);
- if (error.isError())
- {
- return error;
- }
+ gl::ImageIndex destImageIndex =
+ gl::ImageIndex::MakeCube(target, static_cast<GLint>(destLevel));
+ ImageD3D *destImage = nullptr;
+ ANGLE_TRY(getImageAndSyncFromStorage(context, destImageIndex, &destImage));
- error = mRenderer->copyImageCube(source, sourceArea, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
- destOffset, mTexStorage, target, level);
- if (error.isError())
- {
- return error;
- }
- }
+ ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, sourceArea, destOffset,
+ unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+
+ mDirtyImages = true;
+
+ gl::Box destRegion(destOffset.x, destOffset.y, 0, sourceArea.width, sourceArea.height, 1);
+ ANGLE_TRY(commitRegion(context, destImageIndex, destRegion));
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D_Cube::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size)
+gl::Error TextureD3D_Cube::setStorage(const gl::Context *context,
+ GLenum target,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size)
{
ASSERT(size.width == size.height);
ASSERT(size.depth == 1);
@@ -1541,28 +1980,20 @@ gl::Error TextureD3D_Cube::setStorage(GLenum target, size_t levels, GLenum inter
}
// TODO(geofflang): Verify storage creation had no errors
- bool renderTarget = IsRenderTargetUsage(mUsage);
+ bool renderTarget = IsRenderTargetUsage(mState.getUsage());
- TextureStorage *storage = mRenderer->createTextureStorageCube(
- internalFormat, renderTarget, size.width, static_cast<int>(levels), false);
+ TexStoragePointer storage(context);
+ storage.reset(mRenderer->createTextureStorageCube(internalFormat, renderTarget, size.width,
+ static_cast<int>(levels), false));
- gl::Error error = setCompleteTexStorage(storage);
- if (error.isError())
- {
- SafeDelete(storage);
- return error;
- }
-
- error = updateStorage();
+ ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+ storage.release();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(updateStorage(context));
mImmutable = true;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
@@ -1579,7 +2010,7 @@ bool TextureD3D_Cube::isCubeComplete() const
for (int faceIndex = 1; faceIndex < 6; faceIndex++)
{
- const ImageD3D &faceBaseImage = *mImageArray[faceIndex][0];
+ const ImageD3D &faceBaseImage = *mImageArray[faceIndex][getBaseLevel()];
if (faceBaseImage.getWidth() != baseWidth ||
faceBaseImage.getHeight() != baseHeight ||
@@ -1592,97 +2023,85 @@ bool TextureD3D_Cube::isCubeComplete() const
return true;
}
-void TextureD3D_Cube::bindTexImage(egl::Surface *surface)
+gl::Error TextureD3D_Cube::bindTexImage(const gl::Context *context, egl::Surface *surface)
{
UNREACHABLE();
+ return gl::InternalError();
}
-void TextureD3D_Cube::releaseTexImage()
+gl::Error TextureD3D_Cube::releaseTexImage(const gl::Context *context)
{
UNREACHABLE();
+ return gl::InternalError();
}
-
-void TextureD3D_Cube::initMipmapsImages()
+gl::Error TextureD3D_Cube::initMipmapImages(const gl::Context *context)
{
- // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
- int levelCount = mipLevels();
+ const GLuint baseLevel = mState.getEffectiveBaseLevel();
+ const GLuint maxLevel = mState.getMipmapMaxLevel();
+ // Purge array levels baseLevel + 1 through q and reset them to represent the generated mipmap
+ // levels.
for (int faceIndex = 0; faceIndex < 6; faceIndex++)
{
- for (int level = 1; level < levelCount; level++)
+ for (GLuint level = baseLevel + 1; level <= maxLevel; level++)
{
- int faceLevelSize = (std::max(mImageArray[faceIndex][0]->getWidth() >> level, 1));
- redefineImage(faceIndex, level, mImageArray[faceIndex][0]->getInternalFormat(),
- gl::Extents(faceLevelSize, faceLevelSize, 1));
+ int faceLevelSize =
+ (std::max(mImageArray[faceIndex][baseLevel]->getWidth() >> (level - baseLevel), 1));
+ ANGLE_TRY(redefineImage(context, faceIndex, level,
+ mImageArray[faceIndex][baseLevel]->getInternalFormat(),
+ gl::Extents(faceLevelSize, faceLevelSize, 1), false));
}
}
+ return gl::NoError();
}
-gl::Error TextureD3D_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+gl::Error TextureD3D_Cube::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT)
{
ASSERT(gl::IsCubeMapTextureTarget(index.type));
// ensure the underlying texture is created
- gl::Error error = ensureRenderTarget();
- if (error.isError())
- {
- return error;
- }
-
- error = updateStorageFaceLevel(index.layerIndex, index.mipIndex);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(ensureRenderTarget(context));
+ ANGLE_TRY(updateStorageFaceLevel(context, index.layerIndex, index.mipIndex));
- return mTexStorage->getRenderTarget(index, outRT);
+ return mTexStorage->getRenderTarget(context, index, outRT);
}
-gl::Error TextureD3D_Cube::initializeStorage(bool renderTarget)
+gl::Error TextureD3D_Cube::initializeStorage(const gl::Context *context, bool renderTarget)
{
// Only initialize the first time this texture is used as a render target or shader resource
if (mTexStorage)
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
// do not attempt to create storage for nonexistant data
- if (!isFaceLevelComplete(0, 0))
+ if (!isFaceLevelComplete(0, getBaseLevel()))
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
- bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage));
+ bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage()));
- TextureStorage *storage = NULL;
- gl::Error error = createCompleteStorage(createRenderTarget, &storage);
- if (error.isError())
- {
- return error;
- }
+ TexStoragePointer storage(context);
+ ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));
- error = setCompleteTexStorage(storage);
- if (error.isError())
- {
- SafeDelete(storage);
- return error;
- }
+ ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+ storage.release();
ASSERT(mTexStorage);
// flush image data to the storage
- error = updateStorage();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(updateStorage(context));
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D_Cube::createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const
+gl::Error TextureD3D_Cube::createCompleteStorage(bool renderTarget,
+ TexStoragePointer *outStorage) const
{
- GLsizei size = getBaseLevelWidth();
+ GLsizei size = getLevelZeroWidth();
ASSERT(size > 0);
@@ -1705,12 +2124,14 @@ gl::Error TextureD3D_Cube::createCompleteStorage(bool renderTarget, TextureStora
}
// TODO (geofflang): detect if storage creation succeeded
- *outTexStorage = mRenderer->createTextureStorageCube(getBaseLevelInternalFormat(), renderTarget, size, levels, hintLevelZeroOnly);
+ outStorage->reset(mRenderer->createTextureStorageCube(
+ getBaseLevelInternalFormat(), renderTarget, size, levels, hintLevelZeroOnly));
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D_Cube::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+gl::Error TextureD3D_Cube::setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage)
{
if (newCompleteTexStorage && newCompleteTexStorage->isManaged())
{
@@ -1718,25 +2139,27 @@ gl::Error TextureD3D_Cube::setCompleteTexStorage(TextureStorage *newCompleteTexS
{
for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++)
{
- gl::Error error = mImageArray[faceIndex][level]->setManagedSurfaceCube(newCompleteTexStorage, faceIndex, level);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mImageArray[faceIndex][level]->setManagedSurfaceCube(
+ context, newCompleteTexStorage, faceIndex, level));
}
}
}
- SafeDelete(mTexStorage);
+ ANGLE_TRY(releaseTexStorage(context));
mTexStorage = newCompleteTexStorage;
mDirtyImages = true;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D_Cube::updateStorage()
+gl::Error TextureD3D_Cube::updateStorage(const gl::Context *context)
{
- ASSERT(mTexStorage != NULL);
+ if (!mDirtyImages)
+ {
+ return gl::NoError();
+ }
+
+ ASSERT(mTexStorage != nullptr);
GLint storageLevels = mTexStorage->getLevelCount();
for (int face = 0; face < 6; face++)
{
@@ -1744,16 +2167,13 @@ gl::Error TextureD3D_Cube::updateStorage()
{
if (mImageArray[face][level]->isDirty() && isFaceLevelComplete(face, level))
{
- gl::Error error = updateStorageFaceLevel(face, level);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(updateStorageFaceLevel(context, face, level));
}
}
}
- return gl::Error(GL_NO_ERROR);
+ mDirtyImages = false;
+ return gl::NoError();
}
bool TextureD3D_Cube::isValidFaceLevel(int faceIndex, int level) const
@@ -1763,16 +2183,21 @@ bool TextureD3D_Cube::isValidFaceLevel(int faceIndex, int level) const
bool TextureD3D_Cube::isFaceLevelComplete(int faceIndex, int level) const
{
- ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && mImageArray[faceIndex][level] != NULL);
+ if (getBaseLevel() >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ return false;
+ }
+ ASSERT(level >= 0 && faceIndex < 6 && level < static_cast<int>(mImageArray[faceIndex].size()) &&
+ mImageArray[faceIndex][level] != nullptr);
if (isImmutable())
{
return true;
}
- int baseSize = getBaseLevelWidth();
+ int levelZeroSize = getLevelZeroWidth();
- if (baseSize <= 0)
+ if (levelZeroSize <= 0)
{
return false;
}
@@ -1786,14 +2211,14 @@ bool TextureD3D_Cube::isFaceLevelComplete(int faceIndex, int level) const
}
// Check that non-zero levels are consistent with the base level.
- const ImageD3D *faceLevelImage = mImageArray[faceIndex][level];
+ const ImageD3D *faceLevelImage = mImageArray[faceIndex][level].get();
if (faceLevelImage->getInternalFormat() != getBaseLevelInternalFormat())
{
return false;
}
- if (faceLevelImage->getWidth() != std::max(1, baseSize >> level))
+ if (faceLevelImage->getWidth() != std::max(1, levelZeroSize >> level))
{
return false;
}
@@ -1806,57 +2231,55 @@ bool TextureD3D_Cube::isImageComplete(const gl::ImageIndex &index) const
return isFaceLevelComplete(index.layerIndex, index.mipIndex);
}
-gl::Error TextureD3D_Cube::updateStorageFaceLevel(int faceIndex, int level)
+gl::Error TextureD3D_Cube::updateStorageFaceLevel(const gl::Context *context,
+ int faceIndex,
+ int level)
{
- ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && mImageArray[faceIndex][level] != NULL);
- ImageD3D *image = mImageArray[faceIndex][level];
+ ASSERT(level >= 0 && faceIndex < 6 && level < static_cast<int>(mImageArray[faceIndex].size()) &&
+ mImageArray[faceIndex][level] != nullptr);
+ ImageD3D *image = mImageArray[faceIndex][level].get();
if (image->isDirty())
{
GLenum faceTarget = gl::LayerIndexToCubeMapTextureTarget(faceIndex);
gl::ImageIndex index = gl::ImageIndex::MakeCube(faceTarget, level);
gl::Box region(0, 0, 0, image->getWidth(), image->getHeight(), 1);
- gl::Error error = commitRegion(index, region);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(commitRegion(context, index, region));
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-void TextureD3D_Cube::redefineImage(int faceIndex, GLint level, GLenum internalformat, const gl::Extents &size)
+gl::Error TextureD3D_Cube::redefineImage(const gl::Context *context,
+ int faceIndex,
+ GLint level,
+ GLenum internalformat,
+ const gl::Extents &size,
+ bool forceRelease)
{
// If there currently is a corresponding storage texture image, it has these parameters
- const int storageWidth = std::max(1, getBaseLevelWidth() >> level);
- const int storageHeight = std::max(1, getBaseLevelHeight() >> level);
+ const int storageWidth = std::max(1, getLevelZeroWidth() >> level);
+ const int storageHeight = std::max(1, getLevelZeroHeight() >> level);
const GLenum storageFormat = getBaseLevelInternalFormat();
- mImageArray[faceIndex][level]->redefine(GL_TEXTURE_CUBE_MAP, internalformat, size, false);
+ mImageArray[faceIndex][level]->redefine(GL_TEXTURE_CUBE_MAP, internalformat, size,
+ forceRelease);
+ mDirtyImages = mDirtyImages || mImageArray[faceIndex][level]->isDirty();
if (mTexStorage)
{
const int storageLevels = mTexStorage->getLevelCount();
- if ((level >= storageLevels && storageLevels != 0) ||
- size.width != storageWidth ||
+ if ((level >= storageLevels && storageLevels != 0) || size.width != storageWidth ||
size.height != storageHeight ||
- internalformat != storageFormat) // Discard mismatched storage
+ internalformat != storageFormat) // Discard mismatched storage
{
- for (int dirtyLevel = 0; dirtyLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; dirtyLevel++)
- {
- for (int dirtyFace = 0; dirtyFace < 6; dirtyFace++)
- {
- mImageArray[dirtyFace][dirtyLevel]->markDirty();
- }
- }
-
- SafeDelete(mTexStorage);
-
- mDirtyImages = true;
+ markAllImagesDirty();
+ ANGLE_TRY(releaseTexStorage(context));
}
}
+
+ return gl::NoError();
}
gl::ImageIndexIterator TextureD3D_Cube::imageIterator() const
@@ -1876,33 +2299,48 @@ bool TextureD3D_Cube::isValidIndex(const gl::ImageIndex &index) const
index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount());
}
-TextureD3D_3D::TextureD3D_3D(RendererD3D *renderer)
- : TextureD3D(renderer)
+void TextureD3D_Cube::markAllImagesDirty()
{
- for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
+ for (int dirtyLevel = 0; dirtyLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; dirtyLevel++)
{
- mImageArray[i] = renderer->createImage();
+ for (int dirtyFace = 0; dirtyFace < 6; dirtyFace++)
+ {
+ mImageArray[dirtyFace][dirtyLevel]->markDirty();
+ }
}
+ mDirtyImages = true;
}
-TextureD3D_3D::~TextureD3D_3D()
+TextureD3D_3D::TextureD3D_3D(const gl::TextureState &state, RendererD3D *renderer)
+ : TextureD3D(state, renderer)
{
- // Delete the Images before the TextureStorage.
- // Images might be relying on the TextureStorage for some of their data.
- // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images.
for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
{
- delete mImageArray[i];
+ mImageArray[i].reset(renderer->createImage());
}
+}
- SafeDelete(mTexStorage);
+gl::Error TextureD3D_3D::onDestroy(const gl::Context *context)
+{
+ // Delete the Images before the TextureStorage. Images might be relying on the TextureStorage
+ // for some of their data. If TextureStorage is deleted before the Images, then their data will
+ // be wastefully copied back from the GPU before we delete the Images.
+ for (auto &image : mImageArray)
+ {
+ image.reset();
+ }
+ return TextureD3D::onDestroy(context);
+}
+
+TextureD3D_3D::~TextureD3D_3D()
+{
}
ImageD3D *TextureD3D_3D::getImage(int level, int layer) const
{
ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
ASSERT(layer == 0);
- return mImageArray[level];
+ return mImageArray[level].get();
}
ImageD3D *TextureD3D_3D::getImage(const gl::ImageIndex &index) const
@@ -1910,7 +2348,7 @@ ImageD3D *TextureD3D_3D::getImage(const gl::ImageIndex &index) const
ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
ASSERT(!index.hasLayer());
ASSERT(index.type == GL_TEXTURE_3D);
- return mImageArray[index.mipIndex];
+ return mImageArray[index.mipIndex].get();
}
GLsizei TextureD3D_3D::getLayerCount(int level) const
@@ -1953,16 +2391,19 @@ GLenum TextureD3D_3D::getInternalFormat(GLint level) const
bool TextureD3D_3D::isDepth(GLint level) const
{
- return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
+ return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
}
-gl::Error TextureD3D_3D::setEGLImageTarget(GLenum target, egl::Image *image)
+gl::Error TextureD3D_3D::setEGLImageTarget(const gl::Context *context,
+ GLenum target,
+ egl::Image *image)
{
UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION);
+ return gl::InternalError();
}
-gl::Error TextureD3D_3D::setImage(GLenum target,
+gl::Error TextureD3D_3D::setImage(const gl::Context *context,
+ GLenum target,
size_t imageLevel,
GLenum internalFormat,
const gl::Extents &size,
@@ -1972,33 +2413,29 @@ gl::Error TextureD3D_3D::setImage(GLenum target,
const uint8_t *pixels)
{
ASSERT(target == GL_TEXTURE_3D);
- GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
+ const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
GLint level = static_cast<GLint>(imageLevel);
- redefineImage(level, sizedInternalFormat, size);
+ ANGLE_TRY(redefineImage(context, level, internalFormatInfo.sizedInternalFormat, size, false));
bool fastUnpacked = false;
gl::ImageIndex index = gl::ImageIndex::Make3D(level);
// Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
- if (isFastUnpackable(unpack, sizedInternalFormat) && !size.empty())
+ gl::Buffer *unpackBuffer =
+ context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
+ if (isFastUnpackable(unpackBuffer, internalFormatInfo.sizedInternalFormat) && !size.empty() &&
+ isLevelComplete(level))
{
// Will try to create RT storage if it does not exist
- RenderTargetD3D *destRenderTarget = NULL;
- gl::Error error = getRenderTarget(index, &destRenderTarget);
- if (error.isError())
- {
- return error;
- }
+ RenderTargetD3D *destRenderTarget = nullptr;
+ ANGLE_TRY(getRenderTarget(context, index, &destRenderTarget));
gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), getDepth(level));
- error = fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(fastUnpackPixels(context, unpack, pixels, destArea,
+ internalFormatInfo.sizedInternalFormat, type, destRenderTarget));
// Ensure we don't overwrite our newly initialized data
mImageArray[level]->markClean();
@@ -2008,17 +2445,14 @@ gl::Error TextureD3D_3D::setImage(GLenum target,
if (!fastUnpacked)
{
- gl::Error error = setImageImpl(index, type, unpack, pixels, 0);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(setImageImpl(context, index, type, unpack, pixels, 0));
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D_3D::setSubImage(GLenum target,
+gl::Error TextureD3D_3D::setSubImage(const gl::Context *context,
+ GLenum target,
size_t imageLevel,
const gl::Box &area,
GLenum format,
@@ -2032,26 +2466,25 @@ gl::Error TextureD3D_3D::setSubImage(GLenum target,
gl::ImageIndex index = gl::ImageIndex::Make3D(level);
// Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
- if (isFastUnpackable(unpack, getInternalFormat(level)))
+ gl::Buffer *unpackBuffer =
+ context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
+ if (isFastUnpackable(unpackBuffer, getInternalFormat(level)) && isLevelComplete(level))
{
- RenderTargetD3D *destRenderTarget = NULL;
- gl::Error error = getRenderTarget(index, &destRenderTarget);
- if (error.isError())
- {
- return error;
- }
-
+ RenderTargetD3D *destRenderTarget = nullptr;
+ ANGLE_TRY(getRenderTarget(context, index, &destRenderTarget));
ASSERT(!mImageArray[level]->isDirty());
- return fastUnpackPixels(unpack, pixels, area, getInternalFormat(level), type, destRenderTarget);
+ return fastUnpackPixels(context, unpack, pixels, area, getInternalFormat(level), type,
+ destRenderTarget);
}
else
{
- return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0);
+ return TextureD3D::subImage(context, index, area, format, type, unpack, pixels, 0);
}
}
-gl::Error TextureD3D_3D::setCompressedImage(GLenum target,
+gl::Error TextureD3D_3D::setCompressedImage(const gl::Context *context,
+ GLenum target,
size_t imageLevel,
GLenum internalFormat,
const gl::Extents &size,
@@ -2063,35 +2496,41 @@ gl::Error TextureD3D_3D::setCompressedImage(GLenum target,
GLint level = static_cast<GLint>(imageLevel);
// compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
- redefineImage(level, internalFormat, size);
+ ANGLE_TRY(redefineImage(context, level, internalFormat, size, false));
gl::ImageIndex index = gl::ImageIndex::Make3D(level);
- return setCompressedImageImpl(index, unpack, pixels, 0);
+ return setCompressedImageImpl(context, index, unpack, pixels, 0);
}
-gl::Error TextureD3D_3D::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
- const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels)
+gl::Error TextureD3D_3D::setCompressedSubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
{
ASSERT(target == GL_TEXTURE_3D);
gl::ImageIndex index = gl::ImageIndex::Make3D(static_cast<GLint>(level));
- gl::Error error = TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0);
- if (error.isError())
- {
- return error;
- }
-
- return commitRegion(index, area);
+ ANGLE_TRY(TextureD3D::subImageCompressed(context, index, area, format, unpack, pixels, 0));
+ return commitRegion(context, index, area);
}
-gl::Error TextureD3D_3D::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+gl::Error TextureD3D_3D::copyImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
const gl::Framebuffer *source)
{
UNIMPLEMENTED();
- return gl::Error(GL_INVALID_OPERATION, "Copying 3D textures is unimplemented.");
+ return gl::InternalError() << "Copying 3D textures is unimplemented.";
}
-gl::Error TextureD3D_3D::copySubImage(GLenum target,
+gl::Error TextureD3D_3D::copySubImage(const gl::Context *context,
+ GLenum target,
size_t imageLevel,
const gl::Offset &destOffset,
const gl::Rectangle &sourceArea,
@@ -2099,49 +2538,47 @@ gl::Error TextureD3D_3D::copySubImage(GLenum target,
{
ASSERT(target == GL_TEXTURE_3D);
- GLint level = static_cast<GLint>(imageLevel);
- gl::ImageIndex index = gl::ImageIndex::Make3D(level);
+ GLint level = static_cast<GLint>(imageLevel);
- if (canCreateRenderTargetForImage(index))
+ gl::Extents fbSize = source->getReadColorbuffer()->getSize();
+ gl::Rectangle clippedSourceArea;
+ if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height),
+ &clippedSourceArea))
{
- gl::Error error = mImageArray[level]->copyFromFramebuffer(destOffset, sourceArea, source);
- if (error.isError())
- {
- return error;
- }
-
- mDirtyImages = true;
+ return gl::NoError();
}
- else
- {
- gl::Error error = ensureRenderTarget();
- if (error.isError())
- {
- return error;
- }
+ const gl::Offset clippedDestOffset(destOffset.x + clippedSourceArea.x - sourceArea.x,
+ destOffset.y + clippedSourceArea.y - sourceArea.y,
+ destOffset.z);
- if (isValidLevel(level))
- {
- error = updateStorageLevel(level);
- if (error.isError())
- {
- return error;
- }
+ // Currently, copying directly to the storage is not possible because it's not possible to
+ // create an SRV from a single layer of a 3D texture. Instead, make sure the image is up to
+ // date before the copy and then copy back to the storage afterwards if needed.
+ // TODO: Investigate 3D blits in D3D11.
- error = mRenderer->copyImage3D(source, sourceArea,
- gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
- destOffset, mTexStorage, level);
- if (error.isError())
- {
- return error;
- }
- }
+ bool syncTexStorage = mTexStorage && isLevelComplete(level);
+ if (syncTexStorage)
+ {
+ gl::ImageIndex index = gl::ImageIndex::Make3D(level);
+ ANGLE_TRY(mImageArray[level]->copyFromTexStorage(context, index, mTexStorage));
}
+ ANGLE_TRY(mImageArray[level]->copyFromFramebuffer(context, clippedDestOffset, clippedSourceArea,
+ source));
+ mDirtyImages = true;
- return gl::Error(GL_NO_ERROR);
+ if (syncTexStorage)
+ {
+ ANGLE_TRY(updateStorageLevel(context, level));
+ }
+
+ return gl::NoError();
}
-gl::Error TextureD3D_3D::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size)
+gl::Error TextureD3D_3D::setStorage(const gl::Context *context,
+ GLenum target,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size)
{
ASSERT(target == GL_TEXTURE_3D);
@@ -2159,130 +2596,106 @@ gl::Error TextureD3D_3D::setStorage(GLenum target, size_t levels, GLenum interna
}
// TODO(geofflang): Verify storage creation had no errors
- bool renderTarget = IsRenderTargetUsage(mUsage);
- TextureStorage *storage =
- mRenderer->createTextureStorage3D(internalFormat, renderTarget, size.width, size.height,
- size.depth, static_cast<int>(levels));
+ bool renderTarget = IsRenderTargetUsage(mState.getUsage());
+ TexStoragePointer storage(context);
+ storage.reset(mRenderer->createTextureStorage3D(internalFormat, renderTarget, size.width,
+ size.height, size.depth,
+ static_cast<int>(levels)));
- gl::Error error = setCompleteTexStorage(storage);
- if (error.isError())
- {
- SafeDelete(storage);
- return error;
- }
+ ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+ storage.release();
- error = updateStorage();
-
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(updateStorage(context));
mImmutable = true;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-void TextureD3D_3D::bindTexImage(egl::Surface *surface)
+gl::Error TextureD3D_3D::bindTexImage(const gl::Context *context, egl::Surface *surface)
{
UNREACHABLE();
+ return gl::InternalError();
}
-void TextureD3D_3D::releaseTexImage()
+gl::Error TextureD3D_3D::releaseTexImage(const gl::Context *context)
{
UNREACHABLE();
+ return gl::InternalError();
}
-
-void TextureD3D_3D::initMipmapsImages()
+gl::Error TextureD3D_3D::initMipmapImages(const gl::Context *context)
{
- // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
- int levelCount = mipLevels();
- for (int level = 1; level < levelCount; level++)
+ const GLuint baseLevel = mState.getEffectiveBaseLevel();
+ const GLuint maxLevel = mState.getMipmapMaxLevel();
+ // Purge array levels baseLevel + 1 through q and reset them to represent the generated mipmap
+ // levels.
+ for (GLuint level = baseLevel + 1; level <= maxLevel; level++)
{
- gl::Extents levelSize(std::max(getBaseLevelWidth() >> level, 1),
- std::max(getBaseLevelHeight() >> level, 1),
- std::max(getBaseLevelDepth() >> level, 1));
- redefineImage(level, getBaseLevelInternalFormat(), levelSize);
+ gl::Extents levelSize(std::max(getLevelZeroWidth() >> level, 1),
+ std::max(getLevelZeroHeight() >> level, 1),
+ std::max(getLevelZeroDepth() >> level, 1));
+ ANGLE_TRY(redefineImage(context, level, getBaseLevelInternalFormat(), levelSize, false));
}
+
+ return gl::NoError();
}
-gl::Error TextureD3D_3D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+gl::Error TextureD3D_3D::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT)
{
// ensure the underlying texture is created
- gl::Error error = ensureRenderTarget();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(ensureRenderTarget(context));
if (index.hasLayer())
{
- error = updateStorage();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(updateStorage(context));
}
else
{
- error = updateStorageLevel(index.mipIndex);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(updateStorageLevel(context, index.mipIndex));
}
- return mTexStorage->getRenderTarget(index, outRT);
+ return mTexStorage->getRenderTarget(context, index, outRT);
}
-gl::Error TextureD3D_3D::initializeStorage(bool renderTarget)
+gl::Error TextureD3D_3D::initializeStorage(const gl::Context *context, bool renderTarget)
{
// Only initialize the first time this texture is used as a render target or shader resource
if (mTexStorage)
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
// do not attempt to create storage for nonexistant data
- if (!isLevelComplete(0))
+ if (!isLevelComplete(getBaseLevel()))
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
- bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage));
+ bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage()));
- TextureStorage *storage = NULL;
- gl::Error error = createCompleteStorage(createRenderTarget, &storage);
- if (error.isError())
- {
- return error;
- }
+ TexStoragePointer storage(context);
+ ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));
- error = setCompleteTexStorage(storage);
- if (error.isError())
- {
- SafeDelete(storage);
- return error;
- }
+ ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+ storage.release();
ASSERT(mTexStorage);
// flush image data to the storage
- error = updateStorage();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(updateStorage(context));
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D_3D::createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const
+gl::Error TextureD3D_3D::createCompleteStorage(bool renderTarget,
+ TexStoragePointer *outStorage) const
{
- GLsizei width = getBaseLevelWidth();
- GLsizei height = getBaseLevelHeight();
- GLsizei depth = getBaseLevelDepth();
+ GLsizei width = getLevelZeroWidth();
+ GLsizei height = getLevelZeroHeight();
+ GLsizei depth = getLevelZeroDepth();
GLenum internalFormat = getBaseLevelInternalFormat();
ASSERT(width > 0 && height > 0 && depth > 0);
@@ -2291,40 +2704,44 @@ gl::Error TextureD3D_3D::createCompleteStorage(bool renderTarget, TextureStorage
GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, depth));
// TODO: Verify creation of the storage succeeded
- *outStorage = mRenderer->createTextureStorage3D(internalFormat, renderTarget, width, height, depth, levels);
+ outStorage->reset(mRenderer->createTextureStorage3D(internalFormat, renderTarget, width, height,
+ depth, levels));
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D_3D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+gl::Error TextureD3D_3D::setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage)
{
- SafeDelete(mTexStorage);
+ ANGLE_TRY(releaseTexStorage(context));
mTexStorage = newCompleteTexStorage;
mDirtyImages = true;
// We do not support managed 3D storage, as that is D3D9/ES2-only
ASSERT(!mTexStorage->isManaged());
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D_3D::updateStorage()
+gl::Error TextureD3D_3D::updateStorage(const gl::Context *context)
{
- ASSERT(mTexStorage != NULL);
+ if (!mDirtyImages)
+ {
+ return gl::NoError();
+ }
+
+ ASSERT(mTexStorage != nullptr);
GLint storageLevels = mTexStorage->getLevelCount();
for (int level = 0; level < storageLevels; level++)
{
if (mImageArray[level]->isDirty() && isLevelComplete(level))
{
- gl::Error error = updateStorageLevel(level);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(updateStorageLevel(context, level));
}
}
- return gl::Error(GL_NO_ERROR);
+ mDirtyImages = false;
+ return gl::NoError();
}
bool TextureD3D_3D::isValidLevel(int level) const
@@ -2334,28 +2751,29 @@ bool TextureD3D_3D::isValidLevel(int level) const
bool TextureD3D_3D::isLevelComplete(int level) const
{
- ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
+ ASSERT(level >= 0 && level < static_cast<int>(mImageArray.size()) &&
+ mImageArray[level] != nullptr);
if (isImmutable())
{
return true;
}
- GLsizei width = getBaseLevelWidth();
- GLsizei height = getBaseLevelHeight();
- GLsizei depth = getBaseLevelDepth();
+ GLsizei width = getLevelZeroWidth();
+ GLsizei height = getLevelZeroHeight();
+ GLsizei depth = getLevelZeroDepth();
if (width <= 0 || height <= 0 || depth <= 0)
{
return false;
}
- if (level == 0)
+ if (level == static_cast<int>(getBaseLevel()))
{
return true;
}
- ImageD3D *levelImage = mImageArray[level];
+ ImageD3D *levelImage = mImageArray[level].get();
if (levelImage->getInternalFormat() != getBaseLevelInternalFormat())
{
@@ -2385,54 +2803,51 @@ bool TextureD3D_3D::isImageComplete(const gl::ImageIndex &index) const
return isLevelComplete(index.mipIndex);
}
-gl::Error TextureD3D_3D::updateStorageLevel(int level)
+gl::Error TextureD3D_3D::updateStorageLevel(const gl::Context *context, int level)
{
- ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL);
+ ASSERT(level >= 0 && level < static_cast<int>(mImageArray.size()) &&
+ mImageArray[level] != nullptr);
ASSERT(isLevelComplete(level));
if (mImageArray[level]->isDirty())
{
gl::ImageIndex index = gl::ImageIndex::Make3D(level);
gl::Box region(0, 0, 0, getWidth(level), getHeight(level), getDepth(level));
- gl::Error error = commitRegion(index, region);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(commitRegion(context, index, region));
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, const gl::Extents &size)
+gl::Error TextureD3D_3D::redefineImage(const gl::Context *context,
+ GLint level,
+ GLenum internalformat,
+ const gl::Extents &size,
+ bool forceRelease)
{
// If there currently is a corresponding storage texture image, it has these parameters
- const int storageWidth = std::max(1, getBaseLevelWidth() >> level);
- const int storageHeight = std::max(1, getBaseLevelHeight() >> level);
- const int storageDepth = std::max(1, getBaseLevelDepth() >> level);
+ const int storageWidth = std::max(1, getLevelZeroWidth() >> level);
+ const int storageHeight = std::max(1, getLevelZeroHeight() >> level);
+ const int storageDepth = std::max(1, getLevelZeroDepth() >> level);
const GLenum storageFormat = getBaseLevelInternalFormat();
- mImageArray[level]->redefine(GL_TEXTURE_3D, internalformat, size, false);
+ mImageArray[level]->redefine(GL_TEXTURE_3D, internalformat, size, forceRelease);
+ mDirtyImages = mDirtyImages || mImageArray[level]->isDirty();
if (mTexStorage)
{
const int storageLevels = mTexStorage->getLevelCount();
- if ((level >= storageLevels && storageLevels != 0) ||
- size.width != storageWidth ||
- size.height != storageHeight ||
- size.depth != storageDepth ||
- internalformat != storageFormat) // Discard mismatched storage
+ if ((level >= storageLevels && storageLevels != 0) || size.width != storageWidth ||
+ size.height != storageHeight || size.depth != storageDepth ||
+ internalformat != storageFormat) // Discard mismatched storage
{
- for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
- {
- mImageArray[i]->markDirty();
- }
-
- SafeDelete(mTexStorage);
- mDirtyImages = true;
+ markAllImagesDirty();
+ ANGLE_TRY(releaseTexStorage(context));
}
}
+
+ return gl::NoError();
}
gl::ImageIndexIterator TextureD3D_3D::imageIterator() const
@@ -2453,23 +2868,42 @@ bool TextureD3D_3D::isValidIndex(const gl::ImageIndex &index) const
index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount());
}
-TextureD3D_2DArray::TextureD3D_2DArray(RendererD3D *renderer)
- : TextureD3D(renderer)
+void TextureD3D_3D::markAllImagesDirty()
+{
+ for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ mImageArray[i]->markDirty();
+ }
+ mDirtyImages = true;
+}
+
+GLint TextureD3D_3D::getLevelZeroDepth() const
+{
+ ASSERT(gl::CountLeadingZeros(static_cast<uint32_t>(getBaseLevelDepth())) > getBaseLevel());
+ return getBaseLevelDepth() << getBaseLevel();
+}
+
+TextureD3D_2DArray::TextureD3D_2DArray(const gl::TextureState &state, RendererD3D *renderer)
+ : TextureD3D(state, renderer)
{
for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level)
{
mLayerCounts[level] = 0;
- mImageArray[level] = NULL;
+ mImageArray[level] = nullptr;
}
}
-TextureD3D_2DArray::~TextureD3D_2DArray()
+gl::Error TextureD3D_2DArray::onDestroy(const gl::Context *context)
{
- // Delete the Images before the TextureStorage.
- // Images might be relying on the TextureStorage for some of their data.
- // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images.
+ // Delete the Images before the TextureStorage. Images might be relying on the TextureStorage
+ // for some of their data. If TextureStorage is deleted before the Images, then their data will
+ // be wastefully copied back from the GPU before we delete the Images.
deleteImages();
- SafeDelete(mTexStorage);
+ return TextureD3D::onDestroy(context);
+}
+
+TextureD3D_2DArray::~TextureD3D_2DArray()
+{
}
ImageD3D *TextureD3D_2DArray::getImage(int level, int layer) const
@@ -2477,16 +2911,17 @@ ImageD3D *TextureD3D_2DArray::getImage(int level, int layer) const
ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
ASSERT((layer == 0 && mLayerCounts[level] == 0) ||
layer < mLayerCounts[level]);
- return (mImageArray[level] ? mImageArray[level][layer] : NULL);
+ return (mImageArray[level] ? mImageArray[level][layer] : nullptr);
}
ImageD3D *TextureD3D_2DArray::getImage(const gl::ImageIndex &index) const
{
ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(index.layerIndex != gl::ImageIndex::ENTIRE_LEVEL);
ASSERT((index.layerIndex == 0 && mLayerCounts[index.mipIndex] == 0) ||
index.layerIndex < mLayerCounts[index.mipIndex]);
ASSERT(index.type == GL_TEXTURE_2D_ARRAY);
- return (mImageArray[index.mipIndex] ? mImageArray[index.mipIndex][index.layerIndex] : NULL);
+ return (mImageArray[index.mipIndex] ? mImageArray[index.mipIndex][index.layerIndex] : nullptr);
}
GLsizei TextureD3D_2DArray::getLayerCount(int level) const
@@ -2512,16 +2947,19 @@ GLenum TextureD3D_2DArray::getInternalFormat(GLint level) const
bool TextureD3D_2DArray::isDepth(GLint level) const
{
- return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
+ return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
}
-gl::Error TextureD3D_2DArray::setEGLImageTarget(GLenum target, egl::Image *image)
+gl::Error TextureD3D_2DArray::setEGLImageTarget(const gl::Context *context,
+ GLenum target,
+ egl::Image *image)
{
UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION);
+ return gl::InternalError();
}
-gl::Error TextureD3D_2DArray::setImage(GLenum target,
+gl::Error TextureD3D_2DArray::setImage(const gl::Context *context,
+ GLenum target,
size_t imageLevel,
GLenum internalFormat,
const gl::Extents &size,
@@ -2532,30 +2970,28 @@ gl::Error TextureD3D_2DArray::setImage(GLenum target,
{
ASSERT(target == GL_TEXTURE_2D_ARRAY);
- GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
GLint level = static_cast<GLint>(imageLevel);
- redefineImage(level, sizedInternalFormat, size);
+ ANGLE_TRY(redefineImage(context, level, formatInfo.sizedInternalFormat, size, false));
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
- GLsizei inputDepthPitch = formatInfo.computeDepthPitch(
- type, size.width, size.height, unpack.alignment, unpack.rowLength, unpack.imageHeight);
+ GLsizei inputDepthPitch = 0;
+ ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(type, size.width, size.height, unpack.alignment,
+ unpack.rowLength, unpack.imageHeight),
+ inputDepthPitch);
for (int i = 0; i < size.depth; i++)
{
const ptrdiff_t layerOffset = (inputDepthPitch * i);
gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i);
- gl::Error error = setImageImpl(index, type, unpack, pixels, layerOffset);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(setImageImpl(context, index, type, unpack, pixels, layerOffset));
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D_2DArray::setSubImage(GLenum target,
+gl::Error TextureD3D_2DArray::setSubImage(const gl::Context *context,
+ GLenum target,
size_t imageLevel,
const gl::Box &area,
GLenum format,
@@ -2565,9 +3001,12 @@ gl::Error TextureD3D_2DArray::setSubImage(GLenum target,
{
ASSERT(target == GL_TEXTURE_2D_ARRAY);
GLint level = static_cast<GLint>(imageLevel);
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(level));
- GLsizei inputDepthPitch = formatInfo.computeDepthPitch(
- type, area.width, area.height, unpack.alignment, unpack.rowLength, unpack.imageHeight);
+ const gl::InternalFormat &formatInfo =
+ gl::GetInternalFormatInfo(getInternalFormat(level), type);
+ GLsizei inputDepthPitch = 0;
+ ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(type, area.width, area.height, unpack.alignment,
+ unpack.rowLength, unpack.imageHeight),
+ inputDepthPitch);
for (int i = 0; i < area.depth; i++)
{
@@ -2577,17 +3016,15 @@ gl::Error TextureD3D_2DArray::setSubImage(GLenum target,
gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1);
gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer);
- gl::Error error = TextureD3D::subImage(index, layerArea, format, type, unpack, pixels, layerOffset);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(TextureD3D::subImage(context, index, layerArea, format, type, unpack, pixels,
+ layerOffset));
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D_2DArray::setCompressedImage(GLenum target,
+gl::Error TextureD3D_2DArray::setCompressedImage(const gl::Context *context,
+ GLenum target,
size_t imageLevel,
GLenum internalFormat,
const gl::Extents &size,
@@ -2599,35 +3036,41 @@ gl::Error TextureD3D_2DArray::setCompressedImage(GLenum target,
GLint level = static_cast<GLint>(imageLevel);
// compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
- redefineImage(level, internalFormat, size);
+ ANGLE_TRY(redefineImage(context, level, internalFormat, size, false));
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
- GLsizei inputDepthPitch =
- formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, size.width, size.height, 1, 0, 0);
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
+ GLsizei inputDepthPitch = 0;
+ ANGLE_TRY_RESULT(
+ formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, size.width, size.height, 1, 0, 0),
+ inputDepthPitch);
for (int i = 0; i < size.depth; i++)
{
const ptrdiff_t layerOffset = (inputDepthPitch * i);
gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i);
- gl::Error error = setCompressedImageImpl(index, unpack, pixels, layerOffset);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(setCompressedImageImpl(context, index, unpack, pixels, layerOffset));
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D_2DArray::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
- const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels)
+gl::Error TextureD3D_2DArray::setCompressedSubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
{
ASSERT(target == GL_TEXTURE_2D_ARRAY);
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format);
- GLsizei inputDepthPitch =
- formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0, 0);
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(format);
+ GLsizei inputDepthPitch = 0;
+ ANGLE_TRY_RESULT(
+ formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0, 0),
+ inputDepthPitch);
for (int i = 0; i < area.depth; i++)
{
@@ -2637,30 +3080,27 @@ gl::Error TextureD3D_2DArray::setCompressedSubImage(GLenum target, size_t level,
gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1);
gl::ImageIndex index = gl::ImageIndex::Make2DArray(static_cast<GLint>(level), layer);
- gl::Error error = TextureD3D::subImageCompressed(index, layerArea, format, unpack, pixels, layerOffset);
- if (error.isError())
- {
- return error;
- }
-
- error = commitRegion(index, layerArea);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(TextureD3D::subImageCompressed(context, index, layerArea, format, unpack, pixels,
+ layerOffset));
+ ANGLE_TRY(commitRegion(context, index, layerArea));
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D_2DArray::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+gl::Error TextureD3D_2DArray::copyImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
const gl::Framebuffer *source)
{
UNIMPLEMENTED();
- return gl::Error(GL_INVALID_OPERATION, "Copying 2D array textures is unimplemented.");
+ return gl::InternalError() << "Copying 2D array textures is unimplemented.";
}
-gl::Error TextureD3D_2DArray::copySubImage(GLenum target,
+gl::Error TextureD3D_2DArray::copySubImage(const gl::Context *context,
+ GLenum target,
size_t imageLevel,
const gl::Offset &destOffset,
const gl::Rectangle &sourceArea,
@@ -2671,46 +3111,45 @@ gl::Error TextureD3D_2DArray::copySubImage(GLenum target,
GLint level = static_cast<GLint>(imageLevel);
gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z);
- if (canCreateRenderTargetForImage(index))
+ gl::Extents fbSize = source->getReadColorbuffer()->getSize();
+ gl::Rectangle clippedSourceArea;
+ if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height),
+ &clippedSourceArea))
{
- gl::Offset destLayerOffset(destOffset.x, destOffset.y, 0);
- gl::Error error = mImageArray[level][destOffset.z]->copyFromFramebuffer(destLayerOffset,
- sourceArea, source);
- if (error.isError())
- {
- return error;
- }
+ return gl::NoError();
+ }
+ const gl::Offset clippedDestOffset(destOffset.x + clippedSourceArea.x - sourceArea.x,
+ destOffset.y + clippedSourceArea.y - sourceArea.y,
+ destOffset.z);
+ if (!canCreateRenderTargetForImage(index))
+ {
+ gl::Offset destLayerOffset(clippedDestOffset.x, clippedDestOffset.y, 0);
+ ANGLE_TRY(mImageArray[level][clippedDestOffset.z]->copyFromFramebuffer(
+ context, destLayerOffset, clippedSourceArea, source));
mDirtyImages = true;
}
else
{
- gl::Error error = ensureRenderTarget();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(ensureRenderTarget(context));
if (isValidLevel(level))
{
- error = updateStorageLevel(level);
- if (error.isError())
- {
- return error;
- }
-
- error = mRenderer->copyImage2DArray(source, sourceArea, gl::GetInternalFormatInfo(getInternalFormat(0)).format,
- destOffset, mTexStorage, level);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(updateStorageLevel(context, level));
+ ANGLE_TRY(
+ mRenderer->copyImage2DArray(context, source, clippedSourceArea,
+ gl::GetUnsizedFormat(getInternalFormat(getBaseLevel())),
+ clippedDestOffset, mTexStorage, level));
}
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D_2DArray::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size)
+gl::Error TextureD3D_2DArray::setStorage(const gl::Context *context,
+ GLenum target,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size)
{
ASSERT(target == GL_TEXTURE_2D_ARRAY);
@@ -2738,124 +3177,103 @@ gl::Error TextureD3D_2DArray::setStorage(GLenum target, size_t levels, GLenum in
}
// TODO(geofflang): Verify storage creation had no errors
- bool renderTarget = IsRenderTargetUsage(mUsage);
- TextureStorage *storage =
- mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, size.width,
- size.height, size.depth, static_cast<int>(levels));
+ bool renderTarget = IsRenderTargetUsage(mState.getUsage());
+ TexStoragePointer storage(context);
+ storage.reset(mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, size.width,
+ size.height, size.depth,
+ static_cast<int>(levels)));
- gl::Error error = setCompleteTexStorage(storage);
- if (error.isError())
- {
- SafeDelete(storage);
- return error;
- }
+ ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+ storage.release();
- error = updateStorage();
-
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(updateStorage(context));
mImmutable = true;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-void TextureD3D_2DArray::bindTexImage(egl::Surface *surface)
+gl::Error TextureD3D_2DArray::bindTexImage(const gl::Context *context, egl::Surface *surface)
{
UNREACHABLE();
+ return gl::InternalError();
}
-void TextureD3D_2DArray::releaseTexImage()
+gl::Error TextureD3D_2DArray::releaseTexImage(const gl::Context *context)
{
UNREACHABLE();
+ return gl::InternalError();
}
-
-void TextureD3D_2DArray::initMipmapsImages()
+gl::Error TextureD3D_2DArray::initMipmapImages(const gl::Context *context)
{
- int baseWidth = getBaseLevelWidth();
- int baseHeight = getBaseLevelHeight();
- int baseDepth = getLayerCount(0);
+ const GLuint baseLevel = mState.getEffectiveBaseLevel();
+ const GLuint maxLevel = mState.getMipmapMaxLevel();
+ int baseWidth = getLevelZeroWidth();
+ int baseHeight = getLevelZeroHeight();
+ int baseDepth = getLayerCount(getBaseLevel());
GLenum baseFormat = getBaseLevelInternalFormat();
- // Purge array levels 1 through q and reset them to represent the generated mipmap levels.
- int levelCount = mipLevels();
- for (int level = 1; level < levelCount; level++)
+ // Purge array levels baseLevel + 1 through q and reset them to represent the generated mipmap
+ // levels.
+ for (GLuint level = baseLevel + 1u; level <= maxLevel; level++)
{
+ ASSERT((baseWidth >> level) > 0 || (baseHeight >> level) > 0);
gl::Extents levelLayerSize(std::max(baseWidth >> level, 1),
std::max(baseHeight >> level, 1),
baseDepth);
- redefineImage(level, baseFormat, levelLayerSize);
+ ANGLE_TRY(redefineImage(context, level, baseFormat, levelLayerSize, false));
}
+
+ return gl::NoError();
}
-gl::Error TextureD3D_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+gl::Error TextureD3D_2DArray::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT)
{
// ensure the underlying texture is created
- gl::Error error = ensureRenderTarget();
- if (error.isError())
- {
- return error;
- }
-
- error = updateStorageLevel(index.mipIndex);
- if (error.isError())
- {
- return error;
- }
-
- return mTexStorage->getRenderTarget(index, outRT);
+ ANGLE_TRY(ensureRenderTarget(context));
+ ANGLE_TRY(updateStorageLevel(context, index.mipIndex));
+ return mTexStorage->getRenderTarget(context, index, outRT);
}
-gl::Error TextureD3D_2DArray::initializeStorage(bool renderTarget)
+gl::Error TextureD3D_2DArray::initializeStorage(const gl::Context *context, bool renderTarget)
{
// Only initialize the first time this texture is used as a render target or shader resource
if (mTexStorage)
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
// do not attempt to create storage for nonexistant data
- if (!isLevelComplete(0))
+ if (!isLevelComplete(getBaseLevel()))
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
- bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage));
+ bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage()));
- TextureStorage *storage = NULL;
- gl::Error error = createCompleteStorage(createRenderTarget, &storage);
- if (error.isError())
- {
- return error;
- }
+ TexStoragePointer storage(context);
+ ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));
- error = setCompleteTexStorage(storage);
- if (error.isError())
- {
- SafeDelete(storage);
- return error;
- }
+ ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+ storage.release();
ASSERT(mTexStorage);
// flush image data to the storage
- error = updateStorage();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(updateStorage(context));
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D_2DArray::createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const
+gl::Error TextureD3D_2DArray::createCompleteStorage(bool renderTarget,
+ TexStoragePointer *outStorage) const
{
- GLsizei width = getBaseLevelWidth();
- GLsizei height = getBaseLevelHeight();
- GLsizei depth = getLayerCount(0);
+ GLsizei width = getLevelZeroWidth();
+ GLsizei height = getLevelZeroHeight();
+ GLsizei depth = getLayerCount(getBaseLevel());
GLenum internalFormat = getBaseLevelInternalFormat();
ASSERT(width > 0 && height > 0 && depth > 0);
@@ -2864,40 +3282,44 @@ gl::Error TextureD3D_2DArray::createCompleteStorage(bool renderTarget, TextureSt
GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1));
// TODO(geofflang): Verify storage creation succeeds
- *outStorage = mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, width, height, depth, levels);
+ outStorage->reset(mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, width,
+ height, depth, levels));
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D_2DArray::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
+gl::Error TextureD3D_2DArray::setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage)
{
- SafeDelete(mTexStorage);
+ ANGLE_TRY(releaseTexStorage(context));
mTexStorage = newCompleteTexStorage;
mDirtyImages = true;
// We do not support managed 2D array storage, as managed storage is ES2/D3D9 only
ASSERT(!mTexStorage->isManaged());
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureD3D_2DArray::updateStorage()
+gl::Error TextureD3D_2DArray::updateStorage(const gl::Context *context)
{
- ASSERT(mTexStorage != NULL);
+ if (!mDirtyImages)
+ {
+ return gl::NoError();
+ }
+
+ ASSERT(mTexStorage != nullptr);
GLint storageLevels = mTexStorage->getLevelCount();
for (int level = 0; level < storageLevels; level++)
{
if (isLevelComplete(level))
{
- gl::Error error = updateStorageLevel(level);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(updateStorageLevel(context, level));
}
}
- return gl::Error(GL_NO_ERROR);
+ mDirtyImages = false;
+ return gl::NoError();
}
bool TextureD3D_2DArray::isValidLevel(int level) const
@@ -2914,21 +3336,29 @@ bool TextureD3D_2DArray::isLevelComplete(int level) const
return true;
}
- GLsizei width = getBaseLevelWidth();
- GLsizei height = getBaseLevelHeight();
- GLsizei layers = getLayerCount(0);
+ GLsizei width = getLevelZeroWidth();
+ GLsizei height = getLevelZeroHeight();
- if (width <= 0 || height <= 0 || layers <= 0)
+ if (width <= 0 || height <= 0)
{
return false;
}
- if (level == 0)
+ // Layers check needs to happen after the above checks, otherwise out-of-range base level may be
+ // queried.
+ GLsizei layers = getLayerCount(getBaseLevel());
+
+ if (layers <= 0)
+ {
+ return false;
+ }
+
+ if (level == static_cast<int>(getBaseLevel()))
{
return true;
}
- if (getInternalFormat(level) != getInternalFormat(0))
+ if (getInternalFormat(level) != getInternalFormat(getBaseLevel()))
{
return false;
}
@@ -2956,27 +3386,23 @@ bool TextureD3D_2DArray::isImageComplete(const gl::ImageIndex &index) const
return isLevelComplete(index.mipIndex);
}
-gl::Error TextureD3D_2DArray::updateStorageLevel(int level)
+gl::Error TextureD3D_2DArray::updateStorageLevel(const gl::Context *context, int level)
{
- ASSERT(level >= 0 && level < (int)ArraySize(mLayerCounts));
+ ASSERT(level >= 0 && level < static_cast<int>(ArraySize(mLayerCounts)));
ASSERT(isLevelComplete(level));
for (int layer = 0; layer < mLayerCounts[level]; layer++)
{
- ASSERT(mImageArray[level] != NULL && mImageArray[level][layer] != NULL);
+ ASSERT(mImageArray[level] != nullptr && mImageArray[level][layer] != nullptr);
if (mImageArray[level][layer]->isDirty())
{
gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer);
gl::Box region(0, 0, 0, getWidth(level), getHeight(level), 1);
- gl::Error error = commitRegion(index, region);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(commitRegion(context, index, region));
}
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
void TextureD3D_2DArray::deleteImages()
@@ -2988,18 +3414,26 @@ void TextureD3D_2DArray::deleteImages()
delete mImageArray[level][layer];
}
delete[] mImageArray[level];
- mImageArray[level] = NULL;
+ mImageArray[level] = nullptr;
mLayerCounts[level] = 0;
}
}
-void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, const gl::Extents &size)
+gl::Error TextureD3D_2DArray::redefineImage(const gl::Context *context,
+ GLint level,
+ GLenum internalformat,
+ const gl::Extents &size,
+ bool forceRelease)
{
// If there currently is a corresponding storage texture image, it has these parameters
- const int storageWidth = std::max(1, getBaseLevelWidth() >> level);
- const int storageHeight = std::max(1, getBaseLevelHeight() >> level);
- const int storageDepth = getLayerCount(0);
- const GLenum storageFormat = getBaseLevelInternalFormat();
+ const int storageWidth = std::max(1, getLevelZeroWidth() >> level);
+ const int storageHeight = std::max(1, getLevelZeroHeight() >> level);
+ const GLuint baseLevel = getBaseLevel();
+ int storageDepth = 0;
+ if (baseLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ storageDepth = getLayerCount(baseLevel);
+ }
// Only reallocate the layers if the size doesn't match
if (size.depth != mLayerCounts[level])
@@ -3026,33 +3460,27 @@ void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, const
for (int layer = 0; layer < mLayerCounts[level]; layer++)
{
mImageArray[level][layer]->redefine(GL_TEXTURE_2D_ARRAY, internalformat,
- gl::Extents(size.width, size.height, 1), false);
+ gl::Extents(size.width, size.height, 1),
+ forceRelease);
+ mDirtyImages = mDirtyImages || mImageArray[level][layer]->isDirty();
}
}
if (mTexStorage)
{
+ const GLenum storageFormat = getBaseLevelInternalFormat();
const int storageLevels = mTexStorage->getLevelCount();
- if ((level >= storageLevels && storageLevels != 0) ||
- size.width != storageWidth ||
- size.height != storageHeight ||
- size.depth != storageDepth ||
- internalformat != storageFormat) // Discard mismatched storage
+ if ((level >= storageLevels && storageLevels != 0) || size.width != storageWidth ||
+ size.height != storageHeight || size.depth != storageDepth ||
+ internalformat != storageFormat) // Discard mismatched storage
{
- for (int dirtyLevel = 0; dirtyLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; dirtyLevel++)
- {
- for (int dirtyLayer = 0; dirtyLayer < mLayerCounts[dirtyLevel]; dirtyLayer++)
- {
- mImageArray[dirtyLevel][dirtyLayer]->markDirty();
- }
- }
-
- delete mTexStorage;
- mTexStorage = NULL;
- mDirtyImages = true;
+ markAllImagesDirty();
+ ANGLE_TRY(releaseTexStorage(context));
}
}
+
+ return gl::NoError();
}
gl::ImageIndexIterator TextureD3D_2DArray::imageIterator() const
@@ -3083,4 +3511,464 @@ bool TextureD3D_2DArray::isValidIndex(const gl::ImageIndex &index) const
return (!index.hasLayer() || (index.layerIndex >= 0 && index.layerIndex < mLayerCounts[index.mipIndex]));
}
+void TextureD3D_2DArray::markAllImagesDirty()
+{
+ for (int dirtyLevel = 0; dirtyLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; dirtyLevel++)
+ {
+ for (int dirtyLayer = 0; dirtyLayer < mLayerCounts[dirtyLevel]; dirtyLayer++)
+ {
+ mImageArray[dirtyLevel][dirtyLayer]->markDirty();
+ }
+ }
+ mDirtyImages = true;
+}
+
+TextureD3D_External::TextureD3D_External(const gl::TextureState &state, RendererD3D *renderer)
+ : TextureD3D(state, renderer)
+{
+}
+
+TextureD3D_External::~TextureD3D_External()
+{
+}
+
+ImageD3D *TextureD3D_External::getImage(const gl::ImageIndex &index) const
+{
+ UNREACHABLE();
+ return nullptr;
+}
+
+GLsizei TextureD3D_External::getLayerCount(int level) const
+{
+ return 1;
+}
+
+gl::Error TextureD3D_External::setImage(const gl::Context *context,
+ GLenum target,
+ size_t imageLevel,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels)
+{
+ // Image setting is not supported for external images
+ UNREACHABLE();
+ return gl::InternalError();
+}
+
+gl::Error TextureD3D_External::setSubImage(const gl::Context *context,
+ GLenum target,
+ size_t imageLevel,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels)
+{
+ UNREACHABLE();
+ return gl::InternalError();
+}
+
+gl::Error TextureD3D_External::setCompressedImage(const gl::Context *context,
+ GLenum target,
+ size_t imageLevel,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ UNREACHABLE();
+ return gl::InternalError();
+}
+
+gl::Error TextureD3D_External::setCompressedSubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ UNREACHABLE();
+ return gl::InternalError();
+}
+
+gl::Error TextureD3D_External::copyImage(const gl::Context *context,
+ GLenum target,
+ size_t imageLevel,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ const gl::Framebuffer *source)
+{
+ UNREACHABLE();
+ return gl::InternalError();
+}
+
+gl::Error TextureD3D_External::copySubImage(const gl::Context *context,
+ GLenum target,
+ size_t imageLevel,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source)
+{
+ UNREACHABLE();
+ return gl::InternalError();
+}
+
+gl::Error TextureD3D_External::setStorage(const gl::Context *context,
+ GLenum target,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size)
+{
+ UNREACHABLE();
+ return gl::InternalError();
+}
+
+gl::Error TextureD3D_External::setImageExternal(const gl::Context *context,
+ GLenum target,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc)
+{
+ ASSERT(target == GL_TEXTURE_EXTERNAL_OES);
+
+ ANGLE_TRY(releaseTexStorage(context));
+
+ // If the stream is null, the external image is unbound and we release the storage
+ if (stream != nullptr)
+ {
+ mTexStorage = mRenderer->createTextureStorageExternal(stream, desc);
+ }
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_External::bindTexImage(const gl::Context *context, egl::Surface *surface)
+{
+ UNREACHABLE();
+ return gl::InternalError();
+}
+
+gl::Error TextureD3D_External::releaseTexImage(const gl::Context *context)
+{
+ UNREACHABLE();
+ return gl::InternalError();
+}
+
+gl::Error TextureD3D_External::setEGLImageTarget(const gl::Context *context,
+ GLenum target,
+ egl::Image *image)
+{
+ EGLImageD3D *eglImaged3d = GetImplAs<EGLImageD3D>(image);
+
+ // Pass in the RenderTargetD3D here: createTextureStorage can't generate an error.
+ RenderTargetD3D *renderTargetD3D = nullptr;
+ ANGLE_TRY(eglImaged3d->getRenderTarget(context, &renderTargetD3D));
+
+ ANGLE_TRY(releaseTexStorage(context));
+ mTexStorage = mRenderer->createTextureStorageEGLImage(eglImaged3d, renderTargetD3D);
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_External::initMipmapImages(const gl::Context *context)
+{
+ UNREACHABLE();
+ return gl::InternalError();
+}
+
+gl::Error TextureD3D_External::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT)
+{
+ UNREACHABLE();
+ return gl::InternalError();
+}
+
+bool TextureD3D_External::isImageComplete(const gl::ImageIndex &index) const
+{
+ return (index.mipIndex == 0) ? (mTexStorage != nullptr) : false;
+}
+
+gl::Error TextureD3D_External::initializeStorage(const gl::Context *context, bool renderTarget)
+{
+ // Texture storage is created when an external image is bound
+ ASSERT(mTexStorage);
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_External::createCompleteStorage(bool renderTarget,
+ TexStoragePointer *outStorage) const
+{
+ UNREACHABLE();
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_External::setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage)
+{
+ UNREACHABLE();
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_External::updateStorage(const gl::Context *context)
+{
+ // Texture storage does not need to be updated since it is already loaded with the latest
+ // external image
+ ASSERT(mTexStorage);
+ return gl::NoError();
+}
+
+gl::ImageIndexIterator TextureD3D_External::imageIterator() const
+{
+ return gl::ImageIndexIterator::Make2D(0, mTexStorage->getLevelCount());
+}
+
+gl::ImageIndex TextureD3D_External::getImageIndex(GLint mip, GLint /*layer*/) const
+{
+ // "layer" does not apply to 2D Textures.
+ return gl::ImageIndex::Make2D(mip);
+}
+
+bool TextureD3D_External::isValidIndex(const gl::ImageIndex &index) const
+{
+ return (mTexStorage && index.type == GL_TEXTURE_EXTERNAL_OES && index.mipIndex == 0);
+}
+
+void TextureD3D_External::markAllImagesDirty()
+{
+ UNREACHABLE();
+}
+
+TextureD3D_2DMultisample::TextureD3D_2DMultisample(const gl::TextureState &state,
+ RendererD3D *renderer)
+ : TextureD3D(state, renderer)
+{
+}
+
+TextureD3D_2DMultisample::~TextureD3D_2DMultisample()
+{
+}
+
+ImageD3D *TextureD3D_2DMultisample::getImage(const gl::ImageIndex &index) const
+{
+ return nullptr;
+}
+
+gl::Error TextureD3D_2DMultisample::setImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels)
+{
+ UNREACHABLE();
+ return gl::InternalError();
+}
+
+gl::Error TextureD3D_2DMultisample::setSubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels)
+{
+ UNREACHABLE();
+ return gl::InternalError();
+}
+
+gl::Error TextureD3D_2DMultisample::setCompressedImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ UNREACHABLE();
+ return gl::InternalError();
+}
+
+gl::Error TextureD3D_2DMultisample::setCompressedSubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ UNREACHABLE();
+ return gl::InternalError();
+}
+
+gl::Error TextureD3D_2DMultisample::copyImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ const gl::Framebuffer *source)
+{
+ UNREACHABLE();
+ return gl::InternalError();
+}
+
+gl::Error TextureD3D_2DMultisample::copySubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source)
+{
+ UNREACHABLE();
+ return gl::InternalError();
+}
+
+gl::Error TextureD3D_2DMultisample::setStorageMultisample(const gl::Context *context,
+ GLenum target,
+ GLsizei samples,
+ GLint internalFormat,
+ const gl::Extents &size,
+ bool fixedSampleLocations)
+{
+ ASSERT(target == GL_TEXTURE_2D_MULTISAMPLE && size.depth == 1);
+
+ TexStoragePointer storage(context);
+ storage.reset(mRenderer->createTextureStorage2DMultisample(internalFormat, size.width,
+ size.height, static_cast<int>(0),
+ samples, fixedSampleLocations));
+
+ ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+ storage.release();
+
+ ANGLE_TRY(updateStorage(context));
+
+ mImmutable = false;
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_2DMultisample::bindTexImage(const gl::Context *context, egl::Surface *surface)
+{
+ UNREACHABLE();
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_2DMultisample::releaseTexImage(const gl::Context *context)
+{
+ UNREACHABLE();
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_2DMultisample::setEGLImageTarget(const gl::Context *context,
+ GLenum target,
+ egl::Image *image)
+{
+ UNREACHABLE();
+ return gl::InternalError();
+}
+
+gl::Error TextureD3D_2DMultisample::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT)
+{
+ ASSERT(!index.hasLayer());
+
+ // ensure the underlying texture is created
+ ANGLE_TRY(ensureRenderTarget(context));
+
+ return mTexStorage->getRenderTarget(context, index, outRT);
+}
+
+gl::ImageIndexIterator TextureD3D_2DMultisample::imageIterator() const
+{
+ return gl::ImageIndexIterator::Make2DMultisample();
+}
+
+gl::ImageIndex TextureD3D_2DMultisample::getImageIndex(GLint mip, GLint layer) const
+{
+ return gl::ImageIndex::Make2DMultisample();
+}
+
+bool TextureD3D_2DMultisample::isValidIndex(const gl::ImageIndex &index) const
+{
+ return (mTexStorage && index.type == GL_TEXTURE_2D_MULTISAMPLE && index.mipIndex == 0);
+}
+
+GLsizei TextureD3D_2DMultisample::getLayerCount(int level) const
+{
+ return 1;
}
+
+void TextureD3D_2DMultisample::markAllImagesDirty()
+{
+}
+
+gl::Error TextureD3D_2DMultisample::initializeStorage(const gl::Context *context, bool renderTarget)
+{
+ // Only initialize the first time this texture is used as a render target or shader resource
+ if (mTexStorage)
+ {
+ return gl::NoError();
+ }
+
+ bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage()));
+
+ TexStoragePointer storage(context);
+ ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));
+
+ ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+ storage.release();
+
+ ASSERT(mTexStorage);
+
+ // flush image data to the storage
+ ANGLE_TRY(updateStorage(context));
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_2DMultisample::createCompleteStorage(bool renderTarget,
+ TexStoragePointer *outStorage) const
+{
+ outStorage->reset(mTexStorage);
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_2DMultisample::setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage)
+{
+ ANGLE_TRY(releaseTexStorage(context));
+ mTexStorage = newCompleteTexStorage;
+
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_2DMultisample::updateStorage(const gl::Context *context)
+{
+ return gl::NoError();
+}
+
+gl::Error TextureD3D_2DMultisample::initMipmapImages(const gl::Context *context)
+{
+ UNIMPLEMENTED();
+ return gl::NoError();
+}
+
+bool TextureD3D_2DMultisample::isImageComplete(const gl::ImageIndex &index) const
+{
+ return true;
+}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.h
index 1d5faee703..eb206a6ccc 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.h
@@ -9,9 +9,12 @@
#ifndef LIBANGLE_RENDERER_D3D_TEXTURED3D_H_
#define LIBANGLE_RENDERER_D3D_TEXTURED3D_H_
-#include "libANGLE/renderer/TextureImpl.h"
-#include "libANGLE/angletypes.h"
+#include "common/Color.h"
#include "libANGLE/Constants.h"
+#include "libANGLE/Stream.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/TextureImpl.h"
+#include "libANGLE/renderer/d3d/TextureStorage.h"
namespace gl
{
@@ -26,29 +29,51 @@ class RendererD3D;
class RenderTargetD3D;
class TextureStorage;
+template <typename T>
+using TexLevelsArray = std::array<T, gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS>;
+
class TextureD3D : public TextureImpl
{
public:
- TextureD3D(RendererD3D *renderer);
- virtual ~TextureD3D();
+ TextureD3D(const gl::TextureState &data, RendererD3D *renderer);
+ ~TextureD3D() override;
+
+ gl::Error onDestroy(const gl::Context *context) override;
- gl::Error getNativeTexture(TextureStorage **outStorage);
+ gl::Error getNativeTexture(const gl::Context *context, TextureStorage **outStorage);
- virtual void setUsage(GLenum usage) { mUsage = usage; }
bool hasDirtyImages() const { return mDirtyImages; }
void resetDirty() { mDirtyImages = false; }
virtual ImageD3D *getImage(const gl::ImageIndex &index) const = 0;
virtual GLsizei getLayerCount(int level) const = 0;
+ gl::Error getImageAndSyncFromStorage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ ImageD3D **outImage);
+
GLint getBaseLevelWidth() const;
GLint getBaseLevelHeight() const;
- GLint getBaseLevelDepth() const;
GLenum getBaseLevelInternalFormat() const;
+ gl::Error setStorage(const gl::Context *context,
+ GLenum target,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size) override;
+
+ gl::Error setStorageMultisample(const gl::Context *context,
+ GLenum target,
+ GLsizei samples,
+ GLint internalFormat,
+ const gl::Extents &size,
+ bool fixedSampleLocations) override;
+
bool isImmutable() const { return mImmutable; }
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0;
+ virtual gl::Error getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT) = 0;
// Returns an iterator over all "Images" for this particular Texture.
virtual gl::ImageIndexIterator imageIterator() const = 0;
@@ -58,47 +83,91 @@ class TextureD3D : public TextureImpl
virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const = 0;
virtual bool isValidIndex(const gl::ImageIndex &index) const = 0;
- gl::Error generateMipmaps(const gl::TextureState &textureState) override;
+ gl::Error setImageExternal(const gl::Context *context,
+ GLenum target,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc) override;
+ gl::Error generateMipmap(const gl::Context *context) override;
TextureStorage *getStorage();
ImageD3D *getBaseLevelImage() const;
- gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target,
+ gl::Error getAttachmentRenderTarget(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex,
FramebufferAttachmentRenderTarget **rtOut) override;
+ gl::Error setBaseLevel(const gl::Context *context, GLuint baseLevel) override;
+
+ void syncState(const gl::Texture::DirtyBits &dirtyBits) override;
+
+ gl::Error initializeContents(const gl::Context *context,
+ const gl::ImageIndex &imageIndex) override;
+
protected:
- gl::Error setImageImpl(const gl::ImageIndex &index,
+ gl::Error setImageImpl(const gl::Context *context,
+ const gl::ImageIndex &index,
GLenum type,
const gl::PixelUnpackState &unpack,
const uint8_t *pixels,
ptrdiff_t layerOffset);
- gl::Error subImage(const gl::ImageIndex &index, const gl::Box &area, GLenum format, GLenum type,
- const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset);
- gl::Error setCompressedImageImpl(const gl::ImageIndex &index,
+ gl::Error subImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels,
+ ptrdiff_t layerOffset);
+ gl::Error setCompressedImageImpl(const gl::Context *context,
+ const gl::ImageIndex &index,
const gl::PixelUnpackState &unpack,
const uint8_t *pixels,
ptrdiff_t layerOffset);
- gl::Error subImageCompressed(const gl::ImageIndex &index, const gl::Box &area, GLenum format,
- const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset);
- bool isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat);
- gl::Error fastUnpackPixels(const gl::PixelUnpackState &unpack, const uint8_t *pixels, const gl::Box &destArea,
- GLenum sizedInternalFormat, GLenum type, RenderTargetD3D *destRenderTarget);
+ gl::Error subImageCompressed(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels,
+ ptrdiff_t layerOffset);
+ bool isFastUnpackable(const gl::Buffer *unpackBuffer, GLenum sizedInternalFormat);
+ gl::Error fastUnpackPixels(const gl::Context *context,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels,
+ const gl::Box &destArea,
+ GLenum sizedInternalFormat,
+ GLenum type,
+ RenderTargetD3D *destRenderTarget);
+
+ GLint getLevelZeroWidth() const;
+ GLint getLevelZeroHeight() const;
+ virtual GLint getLevelZeroDepth() const;
GLint creationLevels(GLsizei width, GLsizei height, GLsizei depth) const;
- int mipLevels() const;
- virtual void initMipmapsImages() = 0;
+ virtual gl::Error initMipmapImages(const gl::Context *context) = 0;
bool isBaseImageZeroSize() const;
virtual bool isImageComplete(const gl::ImageIndex &index) const = 0;
bool canCreateRenderTargetForImage(const gl::ImageIndex &index) const;
- virtual gl::Error ensureRenderTarget();
+ gl::Error ensureRenderTarget(const gl::Context *context);
- virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const = 0;
- virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage) = 0;
- gl::Error commitRegion(const gl::ImageIndex &index, const gl::Box &region);
+ virtual gl::Error createCompleteStorage(bool renderTarget,
+ TexStoragePointer *outTexStorage) const = 0;
+ virtual gl::Error setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage) = 0;
+ gl::Error commitRegion(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &region);
- RendererD3D *mRenderer;
+ gl::Error releaseTexStorage(const gl::Context *context);
+
+ GLuint getBaseLevel() const { return mBaseLevel; };
- GLenum mUsage;
+ virtual void markAllImagesDirty() = 0;
+
+ GLint getBaseLevelDepth() const;
+
+ RendererD3D *mRenderer;
bool mDirtyImages;
@@ -106,154 +175,301 @@ class TextureD3D : public TextureImpl
TextureStorage *mTexStorage;
private:
- virtual gl::Error initializeStorage(bool renderTarget) = 0;
+ virtual gl::Error initializeStorage(const gl::Context *context, bool renderTarget) = 0;
- virtual gl::Error updateStorage() = 0;
+ virtual gl::Error updateStorage(const gl::Context *context) = 0;
bool shouldUseSetData(const ImageD3D *image) const;
- gl::Error generateMipmapsUsingImages();
+ gl::Error generateMipmapUsingImages(const gl::Context *context, const GLuint maxLevel);
+
+ GLuint mBaseLevel;
};
class TextureD3D_2D : public TextureD3D
{
public:
- TextureD3D_2D(RendererD3D *renderer);
- virtual ~TextureD3D_2D();
+ TextureD3D_2D(const gl::TextureState &data, RendererD3D *renderer);
+ ~TextureD3D_2D() override;
- virtual ImageD3D *getImage(int level, int layer) const;
- virtual ImageD3D *getImage(const gl::ImageIndex &index) const;
- virtual GLsizei getLayerCount(int level) const;
+ gl::Error onDestroy(const gl::Context *context) override;
+
+ ImageD3D *getImage(int level, int layer) const;
+ ImageD3D *getImage(const gl::ImageIndex &index) const override;
+ GLsizei getLayerCount(int level) const override;
GLsizei getWidth(GLint level) const;
GLsizei getHeight(GLint level) const;
GLenum getInternalFormat(GLint level) const;
bool isDepth(GLint level) const;
+ bool isSRGB(GLint level) const;
- gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
- const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
- gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
- const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
-
- gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
- const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override;
- gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
- const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override;
-
- gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+ gl::Error setImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels) override;
+ gl::Error setSubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels) override;
+
+ gl::Error setCompressedImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+ gl::Error setCompressedSubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+
+ gl::Error copyImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
const gl::Framebuffer *source) override;
- gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
+ gl::Error copySubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
const gl::Framebuffer *source) override;
- gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override;
-
- virtual void bindTexImage(egl::Surface *surface);
- virtual void releaseTexImage();
+ gl::Error copyTexture(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ GLenum type,
+ size_t sourceLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source) override;
+ gl::Error copySubTexture(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Offset &destOffset,
+ size_t sourceLevel,
+ const gl::Rectangle &sourceArea,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source) override;
+ gl::Error copyCompressedTexture(const gl::Context *context, const gl::Texture *source) override;
+
+ gl::Error setStorage(const gl::Context *context,
+ GLenum target,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size) override;
+
+ gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) override;
+ gl::Error releaseTexImage(const gl::Context *context) override;
+
+ gl::Error setEGLImageTarget(const gl::Context *context,
+ GLenum target,
+ egl::Image *image) override;
+
+ gl::Error getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT) override;
+
+ gl::ImageIndexIterator imageIterator() const override;
+ gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override;
+ bool isValidIndex(const gl::ImageIndex &index) const override;
- gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
-
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
-
- virtual gl::ImageIndexIterator imageIterator() const;
- virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const;
- virtual bool isValidIndex(const gl::ImageIndex &index) const;
+ protected:
+ void markAllImagesDirty() override;
private:
- virtual gl::Error initializeStorage(bool renderTarget);
- virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const;
- virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
+ gl::Error initializeStorage(const gl::Context *context, bool renderTarget) override;
+ gl::Error createCompleteStorage(bool renderTarget,
+ TexStoragePointer *outTexStorage) const override;
+ gl::Error setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage) override;
- virtual gl::Error updateStorage();
- virtual void initMipmapsImages();
+ gl::Error updateStorage(const gl::Context *context) override;
+ gl::Error initMipmapImages(const gl::Context *context) override;
bool isValidLevel(int level) const;
bool isLevelComplete(int level) const;
- virtual bool isImageComplete(const gl::ImageIndex &index) const;
+ bool isImageComplete(const gl::ImageIndex &index) const override;
- gl::Error updateStorageLevel(int level);
+ gl::Error updateStorageLevel(const gl::Context *context, int level);
- void redefineImage(size_t level,
- GLenum internalformat,
- const gl::Extents &size,
- bool forceRelease);
+ gl::Error redefineImage(const gl::Context *context,
+ size_t level,
+ GLenum internalformat,
+ const gl::Extents &size,
+ bool forceRelease);
bool mEGLImageTarget;
- ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+ TexLevelsArray<std::unique_ptr<ImageD3D>> mImageArray;
};
class TextureD3D_Cube : public TextureD3D
{
public:
- TextureD3D_Cube(RendererD3D *renderer);
- virtual ~TextureD3D_Cube();
+ TextureD3D_Cube(const gl::TextureState &data, RendererD3D *renderer);
+ ~TextureD3D_Cube() override;
- virtual ImageD3D *getImage(int level, int layer) const;
- virtual ImageD3D *getImage(const gl::ImageIndex &index) const;
- virtual GLsizei getLayerCount(int level) const;
+ gl::Error onDestroy(const gl::Context *context) override;
- virtual bool hasDirtyImages() const { return mDirtyImages; }
- virtual void resetDirty() { mDirtyImages = false; }
- virtual void setUsage(GLenum usage) { mUsage = usage; }
+ ImageD3D *getImage(int level, int layer) const;
+ ImageD3D *getImage(const gl::ImageIndex &index) const override;
+ GLsizei getLayerCount(int level) const override;
GLenum getInternalFormat(GLint level, GLint layer) const;
bool isDepth(GLint level, GLint layer) const;
+ bool isSRGB(GLint level, GLint layer) const;
- gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
- const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
- gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
- const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
-
- gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
- const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override;
- gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
- const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override;
-
- gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+ gl::Error setImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels) override;
+ gl::Error setSubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels) override;
+
+ gl::Error setCompressedImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+ gl::Error setCompressedSubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+
+ gl::Error copyImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
const gl::Framebuffer *source) override;
- gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
+ gl::Error copySubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
const gl::Framebuffer *source) override;
- gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override;
+ gl::Error copyTexture(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ GLenum type,
+ size_t sourceLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source) override;
+ gl::Error copySubTexture(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Offset &destOffset,
+ size_t sourceLevel,
+ const gl::Rectangle &sourceArea,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source) override;
+
+ gl::Error setStorage(const gl::Context *context,
+ GLenum target,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size) override;
+
+ gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) override;
+ gl::Error releaseTexImage(const gl::Context *context) override;
+
+ gl::Error setEGLImageTarget(const gl::Context *context,
+ GLenum target,
+ egl::Image *image) override;
+
+ gl::Error getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT) override;
+
+ gl::ImageIndexIterator imageIterator() const override;
+ gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override;
+ bool isValidIndex(const gl::ImageIndex &index) const override;
- virtual void bindTexImage(egl::Surface *surface);
- virtual void releaseTexImage();
-
- gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
-
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
-
- virtual gl::ImageIndexIterator imageIterator() const;
- virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const;
- virtual bool isValidIndex(const gl::ImageIndex &index) const;
+ protected:
+ void markAllImagesDirty() override;
private:
- virtual gl::Error initializeStorage(bool renderTarget);
- virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const;
- virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
+ gl::Error initializeStorage(const gl::Context *context, bool renderTarget) override;
+ gl::Error createCompleteStorage(bool renderTarget,
+ TexStoragePointer *outTexStorage) const override;
+ gl::Error setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage) override;
- virtual gl::Error updateStorage();
- virtual void initMipmapsImages();
+ gl::Error updateStorage(const gl::Context *context) override;
+ gl::Error initMipmapImages(const gl::Context *context) override;
bool isValidFaceLevel(int faceIndex, int level) const;
bool isFaceLevelComplete(int faceIndex, int level) const;
bool isCubeComplete() const;
- virtual bool isImageComplete(const gl::ImageIndex &index) const;
- gl::Error updateStorageFaceLevel(int faceIndex, int level);
+ bool isImageComplete(const gl::ImageIndex &index) const override;
+ gl::Error updateStorageFaceLevel(const gl::Context *context, int faceIndex, int level);
- void redefineImage(int faceIndex, GLint level, GLenum internalformat, const gl::Extents &size);
+ gl::Error redefineImage(const gl::Context *context,
+ int faceIndex,
+ GLint level,
+ GLenum internalformat,
+ const gl::Extents &size,
+ bool forceRelease);
- ImageD3D *mImageArray[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+ std::array<TexLevelsArray<std::unique_ptr<ImageD3D>>, 6> mImageArray;
};
class TextureD3D_3D : public TextureD3D
{
public:
- TextureD3D_3D(RendererD3D *renderer);
- virtual ~TextureD3D_3D();
+ TextureD3D_3D(const gl::TextureState &data, RendererD3D *renderer);
+ ~TextureD3D_3D() override;
- virtual ImageD3D *getImage(int level, int layer) const;
- virtual ImageD3D *getImage(const gl::ImageIndex &index) const;
- virtual GLsizei getLayerCount(int level) const;
+ gl::Error onDestroy(const gl::Context *context) override;
+
+ ImageD3D *getImage(int level, int layer) const;
+ ImageD3D *getImage(const gl::ImageIndex &index) const override;
+ GLsizei getLayerCount(int level) const override;
GLsizei getWidth(GLint level) const;
GLsizei getHeight(GLint level) const;
@@ -261,110 +477,213 @@ class TextureD3D_3D : public TextureD3D
GLenum getInternalFormat(GLint level) const;
bool isDepth(GLint level) const;
- gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
- const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
- gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
- const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
-
- gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
- const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override;
- gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
- const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override;
-
- gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+ gl::Error setImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels) override;
+ gl::Error setSubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels) override;
+
+ gl::Error setCompressedImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+ gl::Error setCompressedSubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+
+ gl::Error copyImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
const gl::Framebuffer *source) override;
- gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
+ gl::Error copySubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
const gl::Framebuffer *source) override;
- gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override;
+ gl::Error setStorage(const gl::Context *context,
+ GLenum target,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size) override;
- virtual void bindTexImage(egl::Surface *surface);
- virtual void releaseTexImage();
+ gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) override;
+ gl::Error releaseTexImage(const gl::Context *context) override;
- gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+ gl::Error setEGLImageTarget(const gl::Context *context,
+ GLenum target,
+ egl::Image *image) override;
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+ gl::Error getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT) override;
- virtual gl::ImageIndexIterator imageIterator() const;
- virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const;
- virtual bool isValidIndex(const gl::ImageIndex &index) const;
+ gl::ImageIndexIterator imageIterator() const override;
+ gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override;
+ bool isValidIndex(const gl::ImageIndex &index) const override;
+
+ protected:
+ void markAllImagesDirty() override;
+ GLint getLevelZeroDepth() const override;
private:
- virtual gl::Error initializeStorage(bool renderTarget);
- virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const;
- virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
+ gl::Error initializeStorage(const gl::Context *context, bool renderTarget) override;
+ gl::Error createCompleteStorage(bool renderTarget,
+ TexStoragePointer *outStorage) const override;
+ gl::Error setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage) override;
- virtual gl::Error updateStorage();
- virtual void initMipmapsImages();
+ gl::Error updateStorage(const gl::Context *context) override;
+ gl::Error initMipmapImages(const gl::Context *context) override;
bool isValidLevel(int level) const;
bool isLevelComplete(int level) const;
- virtual bool isImageComplete(const gl::ImageIndex &index) const;
- gl::Error updateStorageLevel(int level);
+ bool isImageComplete(const gl::ImageIndex &index) const override;
+ gl::Error updateStorageLevel(const gl::Context *context, int level);
- void redefineImage(GLint level, GLenum internalformat, const gl::Extents &size);
+ gl::Error redefineImage(const gl::Context *context,
+ GLint level,
+ GLenum internalformat,
+ const gl::Extents &size,
+ bool forceRelease);
- ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+ TexLevelsArray<std::unique_ptr<ImageD3D>> mImageArray;
};
class TextureD3D_2DArray : public TextureD3D
{
public:
- TextureD3D_2DArray(RendererD3D *renderer);
- virtual ~TextureD3D_2DArray();
+ TextureD3D_2DArray(const gl::TextureState &data, RendererD3D *renderer);
+ ~TextureD3D_2DArray() override;
+
+ gl::Error onDestroy(const gl::Context *context) override;
virtual ImageD3D *getImage(int level, int layer) const;
- virtual ImageD3D *getImage(const gl::ImageIndex &index) const;
- virtual GLsizei getLayerCount(int level) const;
+ ImageD3D *getImage(const gl::ImageIndex &index) const override;
+ GLsizei getLayerCount(int level) const override;
GLsizei getWidth(GLint level) const;
GLsizei getHeight(GLint level) const;
GLenum getInternalFormat(GLint level) const;
bool isDepth(GLint level) const;
- gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
- const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
- gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
- const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
-
- gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
- const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override;
- gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
- const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override;
-
- gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+ gl::Error setImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels) override;
+ gl::Error setSubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels) override;
+
+ gl::Error setCompressedImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+ gl::Error setCompressedSubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+
+ gl::Error copyImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
const gl::Framebuffer *source) override;
- gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
+ gl::Error copySubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
const gl::Framebuffer *source) override;
- gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override;
+ gl::Error setStorage(const gl::Context *context,
+ GLenum target,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size) override;
+
+ gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) override;
+ gl::Error releaseTexImage(const gl::Context *context) override;
- virtual void bindTexImage(egl::Surface *surface);
- virtual void releaseTexImage();
+ gl::Error setEGLImageTarget(const gl::Context *context,
+ GLenum target,
+ egl::Image *image) override;
- gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override;
+ gl::Error getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT) override;
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+ gl::ImageIndexIterator imageIterator() const override;
+ gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override;
+ bool isValidIndex(const gl::ImageIndex &index) const override;
- virtual gl::ImageIndexIterator imageIterator() const;
- virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const;
- virtual bool isValidIndex(const gl::ImageIndex &index) const;
+ protected:
+ void markAllImagesDirty() override;
private:
- virtual gl::Error initializeStorage(bool renderTarget);
- virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const;
- virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
+ gl::Error initializeStorage(const gl::Context *context, bool renderTarget) override;
+ gl::Error createCompleteStorage(bool renderTarget,
+ TexStoragePointer *outStorage) const override;
+ gl::Error setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage) override;
- virtual gl::Error updateStorage();
- virtual void initMipmapsImages();
+ gl::Error updateStorage(const gl::Context *context) override;
+ gl::Error initMipmapImages(const gl::Context *context) override;
bool isValidLevel(int level) const;
bool isLevelComplete(int level) const;
- virtual bool isImageComplete(const gl::ImageIndex &index) const;
- gl::Error updateStorageLevel(int level);
+ bool isImageComplete(const gl::ImageIndex &index) const override;
+ gl::Error updateStorageLevel(const gl::Context *context, int level);
void deleteImages();
- void redefineImage(GLint level, GLenum internalformat, const gl::Extents &size);
+ gl::Error redefineImage(const gl::Context *context,
+ GLint level,
+ GLenum internalformat,
+ const gl::Extents &size,
+ bool forceRelease);
// Storing images as an array of single depth textures since D3D11 treats each array level of a
// Texture2D object as a separate subresource. Each layer would have to be looped over
@@ -374,6 +693,199 @@ class TextureD3D_2DArray : public TextureD3D
ImageD3D **mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
};
+class TextureD3D_External : public TextureD3D
+{
+ public:
+ TextureD3D_External(const gl::TextureState &data, RendererD3D *renderer);
+ ~TextureD3D_External() override;
+
+ ImageD3D *getImage(const gl::ImageIndex &index) const override;
+ GLsizei getLayerCount(int level) const override;
+
+ gl::Error setImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels) override;
+ gl::Error setSubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels) override;
+
+ gl::Error setCompressedImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+ gl::Error setCompressedSubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+
+ gl::Error copyImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ const gl::Framebuffer *source) override;
+ gl::Error copySubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source) override;
+
+ gl::Error setStorage(const gl::Context *context,
+ GLenum target,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size) override;
+
+ gl::Error setImageExternal(const gl::Context *context,
+ GLenum target,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc) override;
+
+ gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) override;
+ gl::Error releaseTexImage(const gl::Context *context) override;
+
+ gl::Error setEGLImageTarget(const gl::Context *context,
+ GLenum target,
+ egl::Image *image) override;
+
+ gl::Error getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT) override;
+
+ gl::ImageIndexIterator imageIterator() const override;
+ gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override;
+ bool isValidIndex(const gl::ImageIndex &index) const override;
+
+ protected:
+ void markAllImagesDirty() override;
+
+ private:
+ gl::Error initializeStorage(const gl::Context *context, bool renderTarget) override;
+ gl::Error createCompleteStorage(bool renderTarget,
+ TexStoragePointer *outTexStorage) const override;
+ gl::Error setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage) override;
+
+ gl::Error updateStorage(const gl::Context *context) override;
+ gl::Error initMipmapImages(const gl::Context *context) override;
+
+ bool isImageComplete(const gl::ImageIndex &index) const override;
+};
+
+class TextureD3D_2DMultisample : public TextureD3D
+{
+ public:
+ TextureD3D_2DMultisample(const gl::TextureState &data, RendererD3D *renderer);
+ ~TextureD3D_2DMultisample() override;
+
+ ImageD3D *getImage(const gl::ImageIndex &index) const override;
+ gl::Error setImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels) override;
+ gl::Error setSubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels) override;
+
+ gl::Error setCompressedImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+ gl::Error setCompressedSubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+
+ gl::Error copyImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ const gl::Framebuffer *source) override;
+ gl::Error copySubImage(const gl::Context *context,
+ GLenum target,
+ size_t level,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source) override;
+
+ gl::Error setStorageMultisample(const gl::Context *context,
+ GLenum target,
+ GLsizei samples,
+ GLint internalFormat,
+ const gl::Extents &size,
+ bool fixedSampleLocations) override;
+
+ gl::Error bindTexImage(const gl::Context *context, egl::Surface *surface) override;
+ gl::Error releaseTexImage(const gl::Context *context) override;
+
+ gl::Error setEGLImageTarget(const gl::Context *context,
+ GLenum target,
+ egl::Image *image) override;
+
+ gl::Error getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT) override;
+
+ gl::ImageIndexIterator imageIterator() const override;
+ gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override;
+ bool isValidIndex(const gl::ImageIndex &index) const override;
+
+ GLsizei getLayerCount(int level) const override;
+
+ protected:
+ void markAllImagesDirty() override;
+
+ private:
+ gl::Error initializeStorage(const gl::Context *context, bool renderTarget) override;
+ gl::Error createCompleteStorage(bool renderTarget,
+ TexStoragePointer *outTexStorage) const override;
+ gl::Error setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage) override;
+
+ gl::Error updateStorage(const gl::Context *context) override;
+ gl::Error initMipmapImages(const gl::Context *context) override;
+
+ bool isImageComplete(const gl::ImageIndex &index) const override;
+};
}
#endif // LIBANGLE_RENDERER_D3D_TEXTURED3D_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.cpp
deleted file mode 100644
index abb83a14d5..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// TextureStorage.cpp: Shared members of abstract rx::TextureStorage class.
-
-#include "libANGLE/renderer/d3d/TextureStorage.h"
-#include "libANGLE/renderer/d3d/TextureD3D.h"
-#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
-#include "libANGLE/renderer/Renderer.h"
-#include "libANGLE/Renderbuffer.h"
-#include "libANGLE/Texture.h"
-
-#include "common/debug.h"
-#include "common/mathutil.h"
-
-namespace rx
-{
-
-TextureStorage::TextureStorage()
- : mFirstRenderTargetSerial(0),
- mRenderTargetSerialsLayerStride(0)
-{}
-
-void TextureStorage::initializeSerials(unsigned int rtSerialsToReserve, unsigned int rtSerialsLayerStride)
-{
- mFirstRenderTargetSerial = RenderTargetD3D::issueSerials(rtSerialsToReserve);
- mRenderTargetSerialsLayerStride = rtSerialsLayerStride;
-}
-
-unsigned int TextureStorage::getRenderTargetSerial(const gl::ImageIndex &index) const
-{
- unsigned int layerOffset = (index.hasLayer() ? (static_cast<unsigned int>(index.layerIndex) * mRenderTargetSerialsLayerStride) : 0);
- return mFirstRenderTargetSerial + static_cast<unsigned int>(index.mipIndex) + layerOffset;
-}
-
-}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.h
index 417237495d..383fbc2141 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.h
@@ -9,20 +9,19 @@
#ifndef LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_
#define LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_
-#include "libANGLE/Error.h"
-
#include "common/debug.h"
-#include "libANGLE/Error.h"
+#include "libANGLE/angletypes.h"
#include <GLES2/gl2.h>
#include <stdint.h>
namespace gl
{
+class Context;
struct ImageIndex;
struct Box;
struct PixelUnpackState;
-}
+} // namespace gl
namespace rx
{
@@ -36,23 +35,48 @@ class TextureStorage : angle::NonCopyable
TextureStorage() {}
virtual ~TextureStorage() {}
+ virtual gl::Error onDestroy(const gl::Context *context);
+
virtual int getTopLevel() const = 0;
virtual bool isRenderTarget() const = 0;
virtual bool isManaged() const = 0;
virtual bool supportsNativeMipmapFunction() const = 0;
virtual int getLevelCount() const = 0;
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0;
- virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) = 0;
+ virtual gl::Error getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT) = 0;
+ virtual gl::Error generateMipmap(const gl::Context *context,
+ const gl::ImageIndex &sourceIndex,
+ const gl::ImageIndex &destIndex) = 0;
- virtual gl::Error copyToStorage(TextureStorage *destStorage) = 0;
- virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type,
- const gl::PixelUnpackState &unpack, const uint8_t *pixelData) = 0;
+ virtual gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) = 0;
+ virtual gl::Error setData(const gl::Context *context,
+ const gl::ImageIndex &index,
+ ImageD3D *image,
+ const gl::Box *destBox,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixelData) = 0;
// This is a no-op for most implementations of TextureStorage. Some (e.g. TextureStorage11_2D) might override it.
- virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) { return gl::Error(GL_NO_ERROR); }
+ virtual gl::Error useLevelZeroWorkaroundTexture(const gl::Context *context,
+ bool useLevelZeroTexture);
};
+inline gl::Error TextureStorage::onDestroy(const gl::Context *context)
+{
+ return gl::NoError();
}
+inline gl::Error TextureStorage::useLevelZeroWorkaroundTexture(const gl::Context *context,
+ bool useLevelZeroTexture)
+{
+ return gl::NoError();
+}
+
+using TexStoragePointer = angle::UniqueObjectPointer<TextureStorage, gl::Context>;
+
+} // namespace rx
+
#endif // LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.cpp
deleted file mode 100644
index 80a4ec3ae1..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-// Copyright 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// TransformFeedbackD3D.cpp is a no-op implementation for both the D3D9 and D3D11 renderers.
-
-#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h"
-
-namespace rx
-{
-
-TransformFeedbackD3D::TransformFeedbackD3D()
-{
-}
-
-TransformFeedbackD3D::~TransformFeedbackD3D()
-{
-}
-
-void TransformFeedbackD3D::begin(GLenum primitiveMode)
-{
-}
-
-void TransformFeedbackD3D::end()
-{
-}
-
-void TransformFeedbackD3D::pause()
-{
-}
-
-void TransformFeedbackD3D::resume()
-{
-}
-
-void TransformFeedbackD3D::bindGenericBuffer(const BindingPointer<gl::Buffer> &binding)
-{
-}
-
-void TransformFeedbackD3D::bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding)
-{
-}
-
-}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.h
deleted file mode 100644
index 6925966153..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-// Copyright 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// TransformFeedbackD3D.h: Implements the abstract rx::TransformFeedbackImpl class.
-
-#ifndef LIBANGLE_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_
-#define LIBANGLE_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_
-
-#include "libANGLE/renderer/TransformFeedbackImpl.h"
-#include "libANGLE/angletypes.h"
-
-namespace rx
-{
-
-class TransformFeedbackD3D : public TransformFeedbackImpl
-{
- public:
- TransformFeedbackD3D();
- virtual ~TransformFeedbackD3D();
-
- void begin(GLenum primitiveMode) override;
- void end() override;
- void pause() override;
- void resume() override;
-
- void bindGenericBuffer(const BindingPointer<gl::Buffer> &binding) override;
- void bindIndexedBuffer(size_t index, const OffsetBindingPointer<gl::Buffer> &binding) override;
-};
-
-}
-
-#endif // LIBANGLE_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp
deleted file mode 100644
index f2654d34e3..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp
+++ /dev/null
@@ -1,397 +0,0 @@
-//
-// Copyright 2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// VaryingPacking:
-// Class which describes a mapping from varyings to registers in D3D
-// for linking between shader stages.
-//
-
-#include "libANGLE/renderer/d3d/VaryingPacking.h"
-
-#include "common/utilities.h"
-#include "compiler/translator/blocklayoutHLSL.h"
-#include "libANGLE/renderer/d3d/DynamicHLSL.h"
-#include "libANGLE/renderer/d3d/ProgramD3D.h"
-
-namespace rx
-{
-
-// Implementation of VaryingPacking::BuiltinVarying
-VaryingPacking::BuiltinVarying::BuiltinVarying() : enabled(false), index(0), systemValue(false)
-{
-}
-
-std::string VaryingPacking::BuiltinVarying::str() const
-{
- return (systemValue ? semantic : (semantic + Str(index)));
-}
-
-void VaryingPacking::BuiltinVarying::enableSystem(const std::string &systemValueSemantic)
-{
- enabled = true;
- semantic = systemValueSemantic;
- systemValue = true;
-}
-
-void VaryingPacking::BuiltinVarying::enable(const std::string &semanticVal, unsigned int indexVal)
-{
- enabled = true;
- semantic = semanticVal;
- index = indexVal;
-}
-
-// Implementation of VaryingPacking
-VaryingPacking::VaryingPacking(GLuint maxVaryingVectors)
- : mRegisterMap(maxVaryingVectors), mBuiltinInfo(SHADER_TYPE_MAX)
-{
-}
-
-// Packs varyings into generic varying registers, using the algorithm from
-// See [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
-// Also [OpenGL ES Shading Language 3.00 rev. 4] Section 11 page 119
-// Returns false if unsuccessful.
-bool VaryingPacking::packVarying(const PackedVarying &packedVarying)
-{
- unsigned int varyingRows = 0;
- unsigned int varyingColumns = 0;
-
- const auto &varying = *packedVarying.varying;
-
- // "Non - square matrices of type matCxR consume the same space as a square matrix of type matN
- // where N is the greater of C and R.Variables of type mat2 occupies 2 complete rows."
- // Here we are a bit more conservative and allow packing non-square matrices more tightly.
- // Make sure we use transposed matrix types to count registers correctly.
- ASSERT(!varying.isStruct());
- GLenum transposedType = gl::TransposeMatrixType(varying.type);
- varyingRows = gl::VariableRowCount(transposedType);
- varyingColumns = gl::VariableColumnCount(transposedType);
-
- // "Arrays of size N are assumed to take N times the size of the base type"
- varyingRows *= varying.elementCount();
-
- unsigned int maxVaryingVectors = static_cast<unsigned int>(mRegisterMap.size());
-
- // "For 2, 3 and 4 component variables packing is started using the 1st column of the 1st row.
- // Variables are then allocated to successive rows, aligning them to the 1st column."
- if (varyingColumns >= 2 && varyingColumns <= 4)
- {
- for (unsigned int row = 0; row <= maxVaryingVectors - varyingRows; ++row)
- {
- if (isFree(row, 0, varyingRows, varyingColumns))
- {
- insert(row, 0, packedVarying);
- return true;
- }
- }
-
- // "For 2 component variables, when there are no spare rows, the strategy is switched to
- // using the highest numbered row and the lowest numbered column where the variable will
- // fit."
- if (varyingColumns == 2)
- {
- for (unsigned int r = maxVaryingVectors - varyingRows + 1; r-- >= 1;)
- {
- if (isFree(r, 2, varyingRows, 2))
- {
- insert(r, 2, packedVarying);
- return true;
- }
- }
- }
-
- return false;
- }
-
- // "1 component variables have their own packing rule. They are packed in order of size, largest
- // first. Each variable is placed in the column that leaves the least amount of space in the
- // column and aligned to the lowest available rows within that column."
- ASSERT(varyingColumns == 1);
- unsigned int contiguousSpace[4] = {0};
- unsigned int bestContiguousSpace[4] = {0};
- unsigned int totalSpace[4] = {0};
-
- for (unsigned int row = 0; row < maxVaryingVectors; ++row)
- {
- for (unsigned int column = 0; column < 4; ++column)
- {
- if (mRegisterMap[row][column])
- {
- contiguousSpace[column] = 0;
- }
- else
- {
- contiguousSpace[column]++;
- totalSpace[column]++;
-
- if (contiguousSpace[column] > bestContiguousSpace[column])
- {
- bestContiguousSpace[column] = contiguousSpace[column];
- }
- }
- }
- }
-
- unsigned int bestColumn = 0;
- for (unsigned int column = 1; column < 4; ++column)
- {
- if (bestContiguousSpace[column] >= varyingRows &&
- (bestContiguousSpace[bestColumn] < varyingRows ||
- totalSpace[column] < totalSpace[bestColumn]))
- {
- bestColumn = column;
- }
- }
-
- if (bestContiguousSpace[bestColumn] >= varyingRows)
- {
- for (unsigned int row = 0; row < maxVaryingVectors; row++)
- {
- if (isFree(row, bestColumn, varyingRows, 1))
- {
- for (unsigned int arrayIndex = 0; arrayIndex < varyingRows; ++arrayIndex)
- {
- // If varyingRows > 1, it must be an array.
- PackedVaryingRegister registerInfo;
- registerInfo.packedVarying = &packedVarying;
- registerInfo.registerRow = row + arrayIndex;
- registerInfo.registerColumn = bestColumn;
- registerInfo.varyingArrayIndex = arrayIndex;
- registerInfo.varyingRowIndex = 0;
- mRegisterList.push_back(registerInfo);
- mRegisterMap[row + arrayIndex][bestColumn] = true;
- }
- break;
- }
- }
- return true;
- }
-
- return false;
-}
-
-bool VaryingPacking::isFree(unsigned int registerRow,
- unsigned int registerColumn,
- unsigned int varyingRows,
- unsigned int varyingColumns) const
-{
- for (unsigned int row = 0; row < varyingRows; ++row)
- {
- ASSERT(registerRow + row < mRegisterMap.size());
- for (unsigned int column = 0; column < varyingColumns; ++column)
- {
- ASSERT(registerColumn + column < 4);
- if (mRegisterMap[registerRow + row][registerColumn + column])
- {
- return false;
- }
- }
- }
-
- return true;
-}
-
-void VaryingPacking::insert(unsigned int registerRow,
- unsigned int registerColumn,
- const PackedVarying &packedVarying)
-{
- unsigned int varyingRows = 0;
- unsigned int varyingColumns = 0;
-
- const auto &varying = *packedVarying.varying;
- ASSERT(!varying.isStruct());
- GLenum transposedType = gl::TransposeMatrixType(varying.type);
- varyingRows = gl::VariableRowCount(transposedType);
- varyingColumns = gl::VariableColumnCount(transposedType);
-
- PackedVaryingRegister registerInfo;
- registerInfo.packedVarying = &packedVarying;
- registerInfo.registerColumn = registerColumn;
-
- for (unsigned int arrayElement = 0; arrayElement < varying.elementCount(); ++arrayElement)
- {
- for (unsigned int varyingRow = 0; varyingRow < varyingRows; ++varyingRow)
- {
- registerInfo.registerRow = registerRow + (arrayElement * varyingRows) + varyingRow;
- registerInfo.varyingRowIndex = varyingRow;
- registerInfo.varyingArrayIndex = arrayElement;
- mRegisterList.push_back(registerInfo);
-
- for (unsigned int columnIndex = 0; columnIndex < varyingColumns; ++columnIndex)
- {
- mRegisterMap[registerInfo.registerRow][registerColumn + columnIndex] = true;
- }
- }
- }
-}
-
-// See comment on packVarying.
-bool VaryingPacking::packVaryings(gl::InfoLog &infoLog,
- const std::vector<PackedVarying> &packedVaryings,
- const std::vector<std::string> &transformFeedbackVaryings)
-{
- std::set<std::string> uniqueVaryingNames;
-
- // "Variables are packed into the registers one at a time so that they each occupy a contiguous
- // subrectangle. No splitting of variables is permitted."
- for (const PackedVarying &packedVarying : packedVaryings)
- {
- const auto &varying = *packedVarying.varying;
-
- // Do not assign registers to built-in or unreferenced varyings
- if (varying.isBuiltIn() || (!varying.staticUse && !packedVarying.isStructField()))
- {
- continue;
- }
-
- ASSERT(!varying.isStruct());
- ASSERT(uniqueVaryingNames.count(varying.name) == 0);
-
- if (packVarying(packedVarying))
- {
- uniqueVaryingNames.insert(varying.name);
- }
- else
- {
- infoLog << "Could not pack varying " << varying.name;
- return false;
- }
- }
-
- for (const std::string &transformFeedbackVaryingName : transformFeedbackVaryings)
- {
- if (transformFeedbackVaryingName.compare(0, 3, "gl_") == 0)
- {
- // do not pack builtin XFB varyings
- continue;
- }
-
- for (const PackedVarying &packedVarying : packedVaryings)
- {
- const auto &varying = *packedVarying.varying;
-
- // Make sure transform feedback varyings aren't optimized out.
- if (uniqueVaryingNames.count(transformFeedbackVaryingName) == 0)
- {
- bool found = false;
- if (transformFeedbackVaryingName == varying.name)
- {
- if (!packVarying(packedVarying))
- {
- infoLog << "Could not pack varying " << varying.name;
- return false;
- }
-
- found = true;
- break;
- }
- if (!found)
- {
- infoLog << "Transform feedback varying " << transformFeedbackVaryingName
- << " does not exist in the vertex shader.";
- return false;
- }
- }
- }
- }
-
- // Sort the packed register list
- std::sort(mRegisterList.begin(), mRegisterList.end());
-
- // Assign semantic indices
- for (unsigned int semanticIndex = 0;
- semanticIndex < static_cast<unsigned int>(mRegisterList.size()); ++semanticIndex)
- {
- mRegisterList[semanticIndex].semanticIndex = semanticIndex;
- }
-
- return true;
-}
-
-unsigned int VaryingPacking::getRegisterCount() const
-{
- unsigned int count = 0;
-
- for (const Register &reg : mRegisterMap)
- {
- if (reg.data[0] || reg.data[1] || reg.data[2] || reg.data[3])
- {
- ++count;
- }
- }
-
- if (mBuiltinInfo[SHADER_PIXEL].glFragCoord.enabled)
- {
- ++count;
- }
-
- if (mBuiltinInfo[SHADER_PIXEL].glPointCoord.enabled)
- {
- ++count;
- }
-
- return count;
-}
-
-void VaryingPacking::enableBuiltins(ShaderType shaderType,
- const ProgramD3DMetadata &programMetadata)
-{
- int majorShaderModel = programMetadata.getRendererMajorShaderModel();
- bool position = programMetadata.usesTransformFeedbackGLPosition();
- bool fragCoord = programMetadata.usesFragCoord();
- bool pointCoord = shaderType == SHADER_VERTEX ? programMetadata.addsPointCoordToVertexShader()
- : programMetadata.usesPointCoord();
- bool pointSize = programMetadata.usesSystemValuePointSize();
- bool hlsl4 = (majorShaderModel >= 4);
- const std::string &userSemantic = GetVaryingSemantic(majorShaderModel, pointSize);
-
- unsigned int reservedSemanticIndex = getMaxSemanticIndex();
-
- BuiltinInfo *builtins = &mBuiltinInfo[shaderType];
-
- if (hlsl4)
- {
- builtins->dxPosition.enableSystem("SV_Position");
- }
- else if (shaderType == SHADER_PIXEL)
- {
- builtins->dxPosition.enableSystem("VPOS");
- }
- else
- {
- builtins->dxPosition.enableSystem("POSITION");
- }
-
- if (position)
- {
- builtins->glPosition.enable(userSemantic, reservedSemanticIndex++);
- }
-
- if (fragCoord)
- {
- builtins->glFragCoord.enable(userSemantic, reservedSemanticIndex++);
- }
-
- if (pointCoord)
- {
- // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord)
- // In D3D11 we manually compute gl_PointCoord in the GS.
- if (hlsl4)
- {
- builtins->glPointCoord.enable(userSemantic, reservedSemanticIndex++);
- }
- else
- {
- builtins->glPointCoord.enable("TEXCOORD", 0);
- }
- }
-
- // Special case: do not include PSIZE semantic in HLSL 3 pixel shaders
- if (pointSize && (shaderType != SHADER_PIXEL || hlsl4))
- {
- builtins->glPointSize.enableSystem("PSIZE");
- }
-}
-
-} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VaryingPacking.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VaryingPacking.h
deleted file mode 100644
index ca4640b000..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VaryingPacking.h
+++ /dev/null
@@ -1,175 +0,0 @@
-//
-// Copyright 2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// VaryingPacking:
-// Class which describes a mapping from varyings to registers in D3D
-// for linking between shader stages.
-//
-
-#ifndef LIBANGLE_RENDERER_D3D_VARYINGPACKING_H_
-#define LIBANGLE_RENDERER_D3D_VARYINGPACKING_H_
-
-#include "libANGLE/renderer/d3d/RendererD3D.h"
-
-namespace rx
-{
-class ProgramD3DMetadata;
-
-struct PackedVarying
-{
- PackedVarying(const sh::ShaderVariable &varyingIn, sh::InterpolationType interpolationIn)
- : varying(&varyingIn), vertexOnly(false), interpolation(interpolationIn)
- {
- }
- PackedVarying(const sh::ShaderVariable &varyingIn,
- sh::InterpolationType interpolationIn,
- const std::string &parentStructNameIn)
- : varying(&varyingIn),
- vertexOnly(false),
- interpolation(interpolationIn),
- parentStructName(parentStructNameIn)
- {
- }
-
- bool isStructField() const { return !parentStructName.empty(); }
-
- const sh::ShaderVariable *varying;
-
- // Transform feedback varyings can be only referenced in the VS.
- bool vertexOnly;
-
- // Cached so we can store sh::ShaderVariable to point to varying fields.
- sh::InterpolationType interpolation;
-
- // Struct name
- std::string parentStructName;
-};
-
-struct PackedVaryingRegister final
-{
- PackedVaryingRegister()
- : packedVarying(nullptr),
- varyingArrayIndex(0),
- varyingRowIndex(0),
- registerRow(0),
- registerColumn(0)
- {
- }
-
- PackedVaryingRegister(const PackedVaryingRegister &) = default;
- PackedVaryingRegister &operator=(const PackedVaryingRegister &) = default;
-
- bool operator<(const PackedVaryingRegister &other) const
- {
- return sortOrder() < other.sortOrder();
- }
-
- unsigned int sortOrder() const
- {
- // TODO(jmadill): Handle interpolation types
- return registerRow * 4 + registerColumn;
- }
-
- bool isStructField() const { return !structFieldName.empty(); }
-
- // Index to the array of varyings.
- const PackedVarying *packedVarying;
-
- // The array element of the packed varying.
- unsigned int varyingArrayIndex;
-
- // The row of the array element of the packed varying.
- unsigned int varyingRowIndex;
-
- // The register row to which we've assigned this packed varying.
- unsigned int registerRow;
-
- // The column of the register row into which we've packed this varying.
- unsigned int registerColumn;
-
- // Assigned after packing
- unsigned int semanticIndex;
-
- // Struct member this varying corresponds to.
- std::string structFieldName;
-};
-
-class VaryingPacking final : angle::NonCopyable
-{
- public:
- VaryingPacking(GLuint maxVaryingVectors);
-
- bool packVaryings(gl::InfoLog &infoLog,
- const std::vector<PackedVarying> &packedVaryings,
- const std::vector<std::string> &transformFeedbackVaryings);
-
- struct Register
- {
- Register() { data[0] = data[1] = data[2] = data[3] = false; }
-
- bool &operator[](unsigned int index) { return data[index]; }
- bool operator[](unsigned int index) const { return data[index]; }
-
- bool data[4];
- };
-
- Register &operator[](unsigned int index) { return mRegisterMap[index]; }
- const Register &operator[](unsigned int index) const { return mRegisterMap[index]; }
-
- const std::vector<PackedVaryingRegister> &getRegisterList() const { return mRegisterList; }
- unsigned int getMaxSemanticIndex() const
- {
- return static_cast<unsigned int>(mRegisterList.size());
- }
- unsigned int getRegisterCount() const;
-
- void enableBuiltins(ShaderType shaderType, const ProgramD3DMetadata &programMetadata);
-
- struct BuiltinVarying final : angle::NonCopyable
- {
- BuiltinVarying();
-
- std::string str() const;
- void enableSystem(const std::string &systemValueSemantic);
- void enable(const std::string &semanticVal, unsigned int indexVal);
-
- bool enabled;
- std::string semantic;
- unsigned int index;
- bool systemValue;
- };
-
- struct BuiltinInfo
- {
- BuiltinVarying dxPosition;
- BuiltinVarying glPosition;
- BuiltinVarying glFragCoord;
- BuiltinVarying glPointCoord;
- BuiltinVarying glPointSize;
- };
-
- const BuiltinInfo &builtins(ShaderType shaderType) const { return mBuiltinInfo[shaderType]; }
-
- bool usesPointSize() const { return mBuiltinInfo[SHADER_VERTEX].glPointSize.enabled; }
-
- private:
- bool packVarying(const PackedVarying &packedVarying);
- bool isFree(unsigned int registerRow,
- unsigned int registerColumn,
- unsigned int varyingRows,
- unsigned int varyingColumns) const;
- void insert(unsigned int registerRow,
- unsigned int registerColumn,
- const PackedVarying &packedVarying);
-
- std::vector<Register> mRegisterMap;
- std::vector<PackedVaryingRegister> mRegisterList;
-
- std::vector<BuiltinInfo> mBuiltinInfo;
-};
-
-} // namespace rx
-
-#endif // LIBANGLE_RENDERER_D3D_VARYINGPACKING_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp
index 9efee9db7c..7c2d5aec70 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp
@@ -8,18 +8,19 @@
// class with derivations, classes that perform graphics API agnostic vertex buffer operations.
#include "libANGLE/renderer/d3d/VertexBuffer.h"
+
+#include "common/mathutil.h"
#include "libANGLE/renderer/d3d/BufferD3D.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/VertexAttribute.h"
-#include "common/mathutil.h"
-
namespace rx
{
+// VertexBuffer Implementation
unsigned int VertexBuffer::mNextSerial = 1;
-VertexBuffer::VertexBuffer()
+VertexBuffer::VertexBuffer() : mRefCount(1)
{
updateSerial();
}
@@ -38,19 +39,34 @@ unsigned int VertexBuffer::getSerial() const
return mSerial;
}
-VertexBufferInterface::VertexBufferInterface(BufferFactoryD3D *factory, bool dynamic)
- : mFactory(factory)
+void VertexBuffer::addRef()
{
- mDynamic = dynamic;
- mWritePosition = 0;
- mReservedSpace = 0;
+ mRefCount++;
+}
+
+void VertexBuffer::release()
+{
+ ASSERT(mRefCount > 0);
+ mRefCount--;
+
+ if (mRefCount == 0)
+ {
+ delete this;
+ }
+}
- mVertexBuffer = factory->createVertexBuffer();
+// VertexBufferInterface Implementation
+VertexBufferInterface::VertexBufferInterface(BufferFactoryD3D *factory, bool dynamic)
+ : mFactory(factory), mVertexBuffer(factory->createVertexBuffer()), mDynamic(dynamic)
+{
}
VertexBufferInterface::~VertexBufferInterface()
{
- delete mVertexBuffer;
+ if (mVertexBuffer)
+ {
+ mVertexBuffer->release();
+ }
}
unsigned int VertexBufferInterface::getSerial() const
@@ -69,181 +85,172 @@ gl::Error VertexBufferInterface::setBufferSize(unsigned int size)
{
return mVertexBuffer->initialize(size, mDynamic);
}
- else
+
+ return mVertexBuffer->setBufferSize(size);
+}
+
+gl::ErrorOrResult<unsigned int> VertexBufferInterface::getSpaceRequired(
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ GLsizei count,
+ GLsizei instances) const
+{
+ unsigned int spaceRequired = 0;
+ ANGLE_TRY_RESULT(mFactory->getVertexSpaceRequired(attrib, binding, count, instances),
+ spaceRequired);
+
+ // Align to 16-byte boundary
+ unsigned int alignedSpaceRequired = roundUp(spaceRequired, 16u);
+
+ if (alignedSpaceRequired < spaceRequired)
{
- return mVertexBuffer->setBufferSize(size);
+ return gl::OutOfMemory()
+ << "Vertex buffer overflow in VertexBufferInterface::getSpaceRequired.";
}
+
+ return alignedSpaceRequired;
}
-unsigned int VertexBufferInterface::getWritePosition() const
+gl::Error VertexBufferInterface::discard()
{
- return mWritePosition;
+ return mVertexBuffer->discard();
}
-void VertexBufferInterface::setWritePosition(unsigned int writePosition)
+VertexBuffer *VertexBufferInterface::getVertexBuffer() const
{
- mWritePosition = writePosition;
+ return mVertexBuffer;
}
-gl::Error VertexBufferInterface::discard()
+// StreamingVertexBufferInterface Implementation
+StreamingVertexBufferInterface::StreamingVertexBufferInterface(BufferFactoryD3D *factory,
+ std::size_t initialSize)
+ : VertexBufferInterface(factory, true), mWritePosition(0), mReservedSpace(0)
{
- return mVertexBuffer->discard();
+ // TODO(jmadill): Make an initialize method that can return an error.
+ ANGLE_SWALLOW_ERR(setBufferSize(static_cast<unsigned int>(initialSize)));
}
-gl::Error VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib,
- GLenum currentValueType,
- GLint start,
- GLsizei count,
- GLsizei instances,
- unsigned int *outStreamOffset,
- const uint8_t *sourceData)
+StreamingVertexBufferInterface::~StreamingVertexBufferInterface()
{
- gl::Error error(GL_NO_ERROR);
+}
- unsigned int spaceRequired;
- error = mVertexBuffer->getSpaceRequired(attrib, count, instances, &spaceRequired);
- if (error.isError())
+gl::Error StreamingVertexBufferInterface::reserveSpace(unsigned int size)
+{
+ unsigned int curBufferSize = getBufferSize();
+ if (size > curBufferSize)
+ {
+ ANGLE_TRY(setBufferSize(std::max(size, 3 * curBufferSize / 2)));
+ mWritePosition = 0;
+ }
+ else if (mWritePosition + size > curBufferSize)
{
- return error;
+ ANGLE_TRY(discard());
+ mWritePosition = 0;
}
- // Align to 16-byte boundary
- unsigned int alignedSpaceRequired = roundUp(spaceRequired, 16u);
+ return gl::NoError();
+}
+
+gl::Error StreamingVertexBufferInterface::storeDynamicAttribute(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ GLenum currentValueType,
+ GLint start,
+ GLsizei count,
+ GLsizei instances,
+ unsigned int *outStreamOffset,
+ const uint8_t *sourceData)
+{
+ unsigned int spaceRequired = 0;
+ ANGLE_TRY_RESULT(getSpaceRequired(attrib, binding, count, instances), spaceRequired);
// Protect against integer overflow
- if (!IsUnsignedAdditionSafe(mWritePosition, alignedSpaceRequired) ||
- alignedSpaceRequired < spaceRequired)
+ angle::CheckedNumeric<unsigned int> checkedPosition(mWritePosition);
+ checkedPosition += spaceRequired;
+ if (!checkedPosition.IsValid())
{
- return gl::Error(GL_OUT_OF_MEMORY, "Internal error, new vertex buffer write position would overflow.");
+ return gl::OutOfMemory()
+ << "Internal error, new vertex buffer write position would overflow.";
}
- error = reserveSpace(mReservedSpace);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(reserveSpace(mReservedSpace));
mReservedSpace = 0;
- error = mVertexBuffer->storeVertexAttributes(attrib, currentValueType, start, count, instances, mWritePosition, sourceData);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mVertexBuffer->storeVertexAttributes(attrib, binding, currentValueType, start, count,
+ instances, mWritePosition, sourceData));
if (outStreamOffset)
{
*outStreamOffset = mWritePosition;
}
- mWritePosition += alignedSpaceRequired;
+ mWritePosition += spaceRequired;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances)
+gl::Error StreamingVertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ GLsizei count,
+ GLsizei instances)
{
- gl::Error error(GL_NO_ERROR);
-
- unsigned int requiredSpace;
- error = mVertexBuffer->getSpaceRequired(attrib, count, instances, &requiredSpace);
- if (error.isError())
- {
- return error;
- }
+ unsigned int requiredSpace = 0;
+ ANGLE_TRY_RESULT(mFactory->getVertexSpaceRequired(attrib, binding, count, instances),
+ requiredSpace);
// Align to 16-byte boundary
- unsigned int alignedRequiredSpace = roundUp(requiredSpace, 16u);
+ auto alignedRequiredSpace = rx::CheckedRoundUp(requiredSpace, 16u);
+ alignedRequiredSpace += mReservedSpace;
// Protect against integer overflow
- if (!IsUnsignedAdditionSafe(mReservedSpace, alignedRequiredSpace) ||
- alignedRequiredSpace < requiredSpace)
+ if (!alignedRequiredSpace.IsValid())
{
- return gl::Error(GL_OUT_OF_MEMORY, "Unable to reserve %u extra bytes in internal vertex buffer, "
- "it would result in an overflow.", requiredSpace);
+ return gl::OutOfMemory()
+ << "Unable to reserve " << requiredSpace
+ << " extra bytes in internal vertex buffer, it would result in an overflow.";
}
- mReservedSpace += alignedRequiredSpace;
+ mReservedSpace = alignedRequiredSpace.ValueOrDie();
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-VertexBuffer* VertexBufferInterface::getVertexBuffer() const
+// StaticVertexBufferInterface Implementation
+StaticVertexBufferInterface::AttributeSignature::AttributeSignature()
+ : type(GL_NONE), size(0), stride(0), normalized(false), pureInteger(false), offset(0)
{
- return mVertexBuffer;
}
-bool VertexBufferInterface::directStoragePossible(const gl::VertexAttribute &attrib,
- GLenum currentValueType) const
+bool StaticVertexBufferInterface::AttributeSignature::matchesAttribute(
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding) const
{
- gl::Buffer *buffer = attrib.buffer.get();
- BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : NULL;
+ size_t attribStride = ComputeVertexAttributeStride(attrib, binding);
- if (!storage || !storage->supportsDirectBinding())
+ if (type != attrib.type || size != attrib.size || static_cast<GLuint>(stride) != attribStride ||
+ normalized != attrib.normalized || pureInteger != attrib.pureInteger)
{
return false;
}
- // Alignment restrictions: In D3D, vertex data must be aligned to
- // the format stride, or to a 4-byte boundary, whichever is smaller.
- // (Undocumented, and experimentally confirmed)
- size_t alignment = 4;
- bool requiresConversion = false;
-
- if (attrib.type != GL_FLOAT)
- {
- gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, currentValueType);
-
- unsigned int outputElementSize;
- getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize);
- alignment = std::min<size_t>(outputElementSize, 4);
-
- // TODO(jmadill): add VertexFormatCaps
- requiresConversion = (mFactory->getVertexConversionType(vertexFormatType) & VERTEX_CONVERT_CPU) != 0;
- }
-
- bool isAligned = (static_cast<size_t>(ComputeVertexAttributeStride(attrib)) % alignment == 0) &&
- (static_cast<size_t>(attrib.offset) % alignment == 0);
-
- return !requiresConversion && isAligned;
+ size_t attribOffset =
+ (static_cast<size_t>(ComputeVertexAttributeOffset(attrib, binding)) % attribStride);
+ return (offset == attribOffset);
}
-StreamingVertexBufferInterface::StreamingVertexBufferInterface(BufferFactoryD3D *factory, std::size_t initialSize)
- : VertexBufferInterface(factory, true)
+void StaticVertexBufferInterface::AttributeSignature::set(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding)
{
- setBufferSize(static_cast<unsigned int>(initialSize));
-}
-
-StreamingVertexBufferInterface::~StreamingVertexBufferInterface()
-{
-}
-
-gl::Error StreamingVertexBufferInterface::reserveSpace(unsigned int size)
-{
- unsigned int curBufferSize = getBufferSize();
- if (size > curBufferSize)
- {
- gl::Error error = setBufferSize(std::max(size, 3 * curBufferSize / 2));
- if (error.isError())
- {
- return error;
- }
- setWritePosition(0);
- }
- else if (getWritePosition() + size > curBufferSize)
- {
- gl::Error error = discard();
- if (error.isError())
- {
- return error;
- }
- setWritePosition(0);
- }
-
- return gl::Error(GL_NO_ERROR);
+ type = attrib.type;
+ size = attrib.size;
+ normalized = attrib.normalized;
+ pureInteger = attrib.pureInteger;
+ offset = stride = static_cast<GLuint>(ComputeVertexAttributeStride(attrib, binding));
+ offset = static_cast<size_t>(ComputeVertexAttributeOffset(attrib, binding)) %
+ ComputeVertexAttributeStride(attrib, binding);
}
StaticVertexBufferInterface::StaticVertexBufferInterface(BufferFactoryD3D *factory)
- : VertexBufferInterface(factory, false), mIsCommitted(false)
+ : VertexBufferInterface(factory, false)
{
}
@@ -251,82 +258,36 @@ StaticVertexBufferInterface::~StaticVertexBufferInterface()
{
}
-bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attrib, unsigned int *outStreamOffset)
+bool StaticVertexBufferInterface::matchesAttribute(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding) const
{
- for (unsigned int element = 0; element < mCache.size(); element++)
- {
- size_t attribStride = ComputeVertexAttributeStride(attrib);
-
- if (mCache[element].type == attrib.type && mCache[element].size == attrib.size &&
- mCache[element].stride == attribStride &&
- mCache[element].normalized == attrib.normalized &&
- mCache[element].pureInteger == attrib.pureInteger)
- {
- size_t offset = (static_cast<size_t>(attrib.offset) % attribStride);
- if (mCache[element].attributeOffset == offset)
- {
- if (outStreamOffset)
- {
- *outStreamOffset = mCache[element].streamOffset;
- }
- return true;
- }
- }
- }
-
- return false;
+ return mSignature.matchesAttribute(attrib, binding);
}
-gl::Error StaticVertexBufferInterface::reserveSpace(unsigned int size)
+void StaticVertexBufferInterface::setAttribute(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding)
{
- unsigned int curSize = getBufferSize();
- if (curSize == 0)
- {
- return setBufferSize(size);
- }
- else if (curSize >= size)
- {
- return gl::Error(GL_NO_ERROR);
- }
- else
- {
- UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION, "Internal error, Static vertex buffers can't be resized.");
- }
+ return mSignature.set(attrib, binding);
}
-gl::Error StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib,
- GLenum currentValueType,
- GLint start,
- GLsizei count,
- GLsizei instances,
- unsigned int *outStreamOffset,
- const uint8_t *sourceData)
+gl::Error StaticVertexBufferInterface::storeStaticAttribute(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ GLint start,
+ GLsizei count,
+ GLsizei instances,
+ const uint8_t *sourceData)
{
- unsigned int streamOffset;
- gl::Error error = VertexBufferInterface::storeVertexAttributes(attrib, currentValueType, start, count, instances, &streamOffset, sourceData);
- if (error.isError())
- {
- return error;
- }
+ unsigned int spaceRequired = 0;
+ ANGLE_TRY_RESULT(getSpaceRequired(attrib, binding, count, instances), spaceRequired);
+ ANGLE_TRY(setBufferSize(spaceRequired));
- size_t attributeOffset = static_cast<size_t>(attrib.offset) % ComputeVertexAttributeStride(attrib);
- VertexElement element = { attrib.type, attrib.size, static_cast<GLuint>(ComputeVertexAttributeStride(attrib)), attrib.normalized, attrib.pureInteger, attributeOffset, streamOffset };
- mCache.push_back(element);
-
- if (outStreamOffset)
- {
- *outStreamOffset = streamOffset;
- }
+ ASSERT(attrib.enabled);
+ ANGLE_TRY(mVertexBuffer->storeVertexAttributes(attrib, binding, GL_NONE, start, count,
+ instances, 0, sourceData));
- return gl::Error(GL_NO_ERROR);
+ mSignature.set(attrib, binding);
+ mVertexBuffer->hintUnmapResource();
+ return gl::NoError();
}
-void StaticVertexBufferInterface::commit()
-{
- if (getBufferSize() > 0)
- {
- mIsCommitted = true;
- }
-}
-}
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.h
index 692b6ac506..df8085d3cb 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.h
@@ -22,6 +22,7 @@
namespace gl
{
struct VertexAttribute;
+class VertexBinding;
struct VertexAttribCurrentValueData;
}
@@ -29,23 +30,25 @@ namespace rx
{
class BufferFactoryD3D;
+// Use a ref-counting scheme with self-deletion on release. We do this so that we can more
+// easily manage the static buffer cache, without deleting currently bound buffers.
class VertexBuffer : angle::NonCopyable
{
public:
VertexBuffer();
- virtual ~VertexBuffer();
virtual gl::Error initialize(unsigned int size, bool dynamicUsage) = 0;
+ // Warning: you should ensure binding really matches attrib.bindingIndex before using this
+ // function.
virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
GLenum currentValueType,
GLint start,
GLsizei count,
GLsizei instances,
unsigned int offset,
const uint8_t *sourceData) = 0;
- virtual gl::Error getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances,
- unsigned int *outSpaceRequired) const = 0;
virtual unsigned int getBufferSize() const = 0;
virtual gl::Error setBufferSize(unsigned int size) = 0;
@@ -56,12 +59,18 @@ class VertexBuffer : angle::NonCopyable
// This may be overridden (e.g. by VertexBuffer11) if necessary.
virtual void hintUnmapResource() { };
+ // Reference counting.
+ void addRef();
+ void release();
+
protected:
void updateSerial();
+ virtual ~VertexBuffer();
private:
unsigned int mSerial;
static unsigned int mNextSerial;
+ unsigned int mRefCount;
};
class VertexBufferInterface : angle::NonCopyable
@@ -70,42 +79,24 @@ class VertexBufferInterface : angle::NonCopyable
VertexBufferInterface(BufferFactoryD3D *factory, bool dynamic);
virtual ~VertexBufferInterface();
- gl::Error reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances);
-
unsigned int getBufferSize() const;
+ bool empty() const { return getBufferSize() == 0; }
unsigned int getSerial() const;
- virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib,
- GLenum currentValueType,
- GLint start,
- GLsizei count,
- GLsizei instances,
- unsigned int *outStreamOffset,
- const uint8_t *sourceData);
-
- bool directStoragePossible(const gl::VertexAttribute &attrib,
- GLenum currentValueType) const;
-
- VertexBuffer* getVertexBuffer() const;
+ VertexBuffer *getVertexBuffer() const;
protected:
- virtual gl::Error reserveSpace(unsigned int size) = 0;
-
- unsigned int getWritePosition() const;
- void setWritePosition(unsigned int writePosition);
-
gl::Error discard();
gl::Error setBufferSize(unsigned int size);
- private:
+ gl::ErrorOrResult<unsigned int> getSpaceRequired(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ GLsizei count,
+ GLsizei instances) const;
BufferFactoryD3D *const mFactory;
-
- VertexBuffer* mVertexBuffer;
-
- unsigned int mWritePosition;
- unsigned int mReservedSpace;
+ VertexBuffer *mVertexBuffer;
bool mDynamic;
};
@@ -113,53 +104,72 @@ class StreamingVertexBufferInterface : public VertexBufferInterface
{
public:
StreamingVertexBufferInterface(BufferFactoryD3D *factory, std::size_t initialSize);
- ~StreamingVertexBufferInterface();
+ ~StreamingVertexBufferInterface() override;
- protected:
+ gl::Error storeDynamicAttribute(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ GLenum currentValueType,
+ GLint start,
+ GLsizei count,
+ GLsizei instances,
+ unsigned int *outStreamOffset,
+ const uint8_t *sourceData);
+
+ gl::Error reserveVertexSpace(const gl::VertexAttribute &attribute,
+ const gl::VertexBinding &binding,
+ GLsizei count,
+ GLsizei instances);
+
+ private:
gl::Error reserveSpace(unsigned int size);
+
+ unsigned int mWritePosition;
+ unsigned int mReservedSpace;
};
class StaticVertexBufferInterface : public VertexBufferInterface
{
public:
explicit StaticVertexBufferInterface(BufferFactoryD3D *factory);
- ~StaticVertexBufferInterface();
+ ~StaticVertexBufferInterface() override;
- gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib,
- GLenum currentValueType,
- GLint start,
- GLsizei count,
- GLsizei instances,
- unsigned int *outStreamOffset,
- const uint8_t *sourceData) override;
-
- bool lookupAttribute(const gl::VertexAttribute &attribute, unsigned int* outStreamFffset);
+ // Warning: you should ensure binding really matches attrib.bindingIndex before using these
+ // functions.
+ gl::Error storeStaticAttribute(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ GLint start,
+ GLsizei count,
+ GLsizei instances,
+ const uint8_t *sourceData);
- // If a static vertex buffer is committed then no more attribute data can be added to it
- // A new static vertex buffer should be created instead
- void commit();
- bool isCommitted() { return mIsCommitted; }
+ bool matchesAttribute(const gl::VertexAttribute &attribute,
+ const gl::VertexBinding &binding) const;
- protected:
- gl::Error reserveSpace(unsigned int size);
+ void setAttribute(const gl::VertexAttribute &attribute, const gl::VertexBinding &binding);
private:
- struct VertexElement
+ class AttributeSignature final : angle::NonCopyable
{
+ public:
+ AttributeSignature();
+
+ bool matchesAttribute(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding) const;
+
+ void set(const gl::VertexAttribute &attrib, const gl::VertexBinding &binding);
+
+ private:
GLenum type;
GLuint size;
GLuint stride;
bool normalized;
bool pureInteger;
- size_t attributeOffset;
-
- unsigned int streamOffset;
+ size_t offset;
};
- bool mIsCommitted;
- std::vector<VertexElement> mCache;
+ AttributeSignature mSignature;
};
-}
+} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_VERTEXBUFFER_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp
index b392d0f4da..54ad5e54f5 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp
@@ -9,25 +9,38 @@
#include "libANGLE/renderer/d3d/VertexDataManager.h"
+#include "common/bitset_utils.h"
#include "libANGLE/Buffer.h"
+#include "libANGLE/Context.h"
#include "libANGLE/Program.h"
#include "libANGLE/State.h"
-#include "libANGLE/VertexAttribute.h"
#include "libANGLE/VertexArray.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/VertexBuffer.h"
-namespace
-{
- enum { INITIAL_STREAM_BUFFER_SIZE = 1024*1024 };
- // This has to be at least 4k or else it fails on ATI cards.
- enum { CONSTANT_VERTEX_BUFFER_SIZE = 4096 };
-}
+using namespace angle;
namespace rx
{
+namespace
+{
+enum
+{
+ INITIAL_STREAM_BUFFER_SIZE = 1024 * 1024
+};
+// This has to be at least 4k or else it fails on ATI cards.
+enum
+{
+ CONSTANT_VERTEX_BUFFER_SIZE = 4096
+};
-static int ElementsInBuffer(const gl::VertexAttribute &attrib, unsigned int size)
+// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
+int ElementsInBuffer(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ unsigned int size)
{
// Size cannot be larger than a GLsizei
if (size > static_cast<unsigned int>(std::numeric_limits<int>::max()))
@@ -35,15 +48,139 @@ static int ElementsInBuffer(const gl::VertexAttribute &attrib, unsigned int size
size = static_cast<unsigned int>(std::numeric_limits<int>::max());
}
- GLsizei stride = static_cast<GLsizei>(ComputeVertexAttributeStride(attrib));
- return (size - attrib.offset % stride +
+ GLsizei stride = static_cast<GLsizei>(ComputeVertexAttributeStride(attrib, binding));
+ GLsizei offset = static_cast<GLsizei>(ComputeVertexAttributeOffset(attrib, binding));
+ return (size - offset % stride +
(stride - static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib)))) /
stride;
}
-VertexDataManager::CurrentValueState::CurrentValueState()
- : buffer(nullptr),
- offset(0)
+// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
+bool DirectStoragePossible(const gl::VertexAttribute &attrib, const gl::VertexBinding &binding)
+{
+ // Current value attribs may not use direct storage.
+ if (!attrib.enabled)
+ {
+ return false;
+ }
+
+ gl::Buffer *buffer = binding.getBuffer().get();
+ if (!buffer)
+ {
+ return false;
+ }
+
+ BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
+ ASSERT(bufferD3D);
+ if (!bufferD3D->supportsDirectBinding())
+ {
+ return false;
+ }
+
+ // Alignment restrictions: In D3D, vertex data must be aligned to the format stride, or to a
+ // 4-byte boundary, whichever is smaller. (Undocumented, and experimentally confirmed)
+ size_t alignment = 4;
+
+ // TODO(jmadill): add VertexFormatCaps
+ BufferFactoryD3D *factory = bufferD3D->getFactory();
+
+ gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib);
+
+ // CPU-converted vertex data must be converted (naturally).
+ if ((factory->getVertexConversionType(vertexFormatType) & VERTEX_CONVERT_CPU) != 0)
+ {
+ return false;
+ }
+
+ if (attrib.type != GL_FLOAT)
+ {
+ auto errorOrElementSize = factory->getVertexSpaceRequired(attrib, binding, 1, 0);
+ if (errorOrElementSize.isError())
+ {
+ ERR() << "Unlogged error in DirectStoragePossible.";
+ return false;
+ }
+
+ alignment = std::min<size_t>(errorOrElementSize.getResult(), 4);
+ }
+
+ GLintptr offset = ComputeVertexAttributeOffset(attrib, binding);
+ // Final alignment check - unaligned data must be converted.
+ return (static_cast<size_t>(ComputeVertexAttributeStride(attrib, binding)) % alignment == 0) &&
+ (static_cast<size_t>(offset) % alignment == 0);
+}
+} // anonymous namespace
+
+TranslatedAttribute::TranslatedAttribute()
+ : active(false),
+ attribute(nullptr),
+ binding(nullptr),
+ currentValueType(GL_NONE),
+ baseOffset(0),
+ usesFirstVertexOffset(false),
+ stride(0),
+ vertexBuffer(),
+ storage(nullptr),
+ serial(0),
+ divisor(0)
+{
+}
+
+TranslatedAttribute::TranslatedAttribute(const TranslatedAttribute &other) = default;
+
+gl::ErrorOrResult<unsigned int> TranslatedAttribute::computeOffset(GLint startVertex) const
+{
+ if (!usesFirstVertexOffset)
+ {
+ return baseOffset;
+ }
+
+ CheckedNumeric<unsigned int> offset;
+
+ offset = baseOffset + stride * static_cast<unsigned int>(startVertex);
+ ANGLE_TRY_CHECKED_MATH(offset);
+ return offset.ValueOrDie();
+}
+
+// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
+VertexStorageType ClassifyAttributeStorage(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding)
+{
+ // If attribute is disabled, we use the current value.
+ if (!attrib.enabled)
+ {
+ return VertexStorageType::CURRENT_VALUE;
+ }
+
+ // If specified with immediate data, we must use dynamic storage.
+ auto *buffer = binding.getBuffer().get();
+ if (!buffer)
+ {
+ return VertexStorageType::DYNAMIC;
+ }
+
+ // Check if the buffer supports direct storage.
+ if (DirectStoragePossible(attrib, binding))
+ {
+ return VertexStorageType::DIRECT;
+ }
+
+ // Otherwise the storage is static or dynamic.
+ BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
+ ASSERT(bufferD3D);
+ switch (bufferD3D->getUsage())
+ {
+ case D3DBufferUsage::DYNAMIC:
+ return VertexStorageType::DYNAMIC;
+ case D3DBufferUsage::STATIC:
+ return VertexStorageType::STATIC;
+ default:
+ UNREACHABLE();
+ return VertexStorageType::UNKNOWN;
+ }
+}
+
+VertexDataManager::CurrentValueState::CurrentValueState() : buffer(), offset(0)
{
data.FloatValues[0] = std::numeric_limits<float>::quiet_NaN();
data.FloatValues[1] = std::numeric_limits<float>::quiet_NaN();
@@ -54,379 +191,456 @@ VertexDataManager::CurrentValueState::CurrentValueState()
VertexDataManager::CurrentValueState::~CurrentValueState()
{
- SafeDelete(buffer);
}
VertexDataManager::VertexDataManager(BufferFactoryD3D *factory)
- : mFactory(factory),
- mStreamingBuffer(nullptr),
- // TODO(jmadill): use context caps
- mCurrentValueCache(gl::MAX_VERTEX_ATTRIBS)
+ : mFactory(factory), mStreamingBuffer(), mCurrentValueCache(gl::MAX_VERTEX_ATTRIBS)
{
- mStreamingBuffer = new StreamingVertexBufferInterface(factory, INITIAL_STREAM_BUFFER_SIZE);
-
- if (!mStreamingBuffer)
- {
- ERR("Failed to allocate the streaming vertex buffer.");
- }
-
- // TODO(jmadill): use context caps
- mActiveEnabledAttributes.reserve(gl::MAX_VERTEX_ATTRIBS);
- mActiveDisabledAttributes.reserve(gl::MAX_VERTEX_ATTRIBS);
}
VertexDataManager::~VertexDataManager()
{
- SafeDelete(mStreamingBuffer);
}
-void VertexDataManager::hintUnmapAllResources(const std::vector<gl::VertexAttribute> &vertexAttributes)
+gl::Error VertexDataManager::initialize()
{
- mStreamingBuffer->getVertexBuffer()->hintUnmapResource();
-
- for (const TranslatedAttribute *translated : mActiveEnabledAttributes)
+ mStreamingBuffer.reset(
+ new StreamingVertexBufferInterface(mFactory, INITIAL_STREAM_BUFFER_SIZE));
+ if (!mStreamingBuffer)
{
- gl::Buffer *buffer = translated->attribute->buffer.get();
- BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
- StaticVertexBufferInterface *staticBuffer =
- storage
- ? storage->getStaticVertexBuffer(*translated->attribute, D3D_BUFFER_DO_NOT_CREATE)
- : nullptr;
-
- if (staticBuffer)
- {
- // Commit all the static vertex buffers. This fixes them in size/contents, and forces
- // ANGLE to use a new static buffer (or recreate the static buffers) next time
- staticBuffer->commit();
-
- staticBuffer->getVertexBuffer()->hintUnmapResource();
- }
+ return gl::OutOfMemory() << "Failed to allocate the streaming vertex buffer.";
}
- for (auto &currentValue : mCurrentValueCache)
- {
- if (currentValue.buffer != nullptr)
- {
- currentValue.buffer->getVertexBuffer()->hintUnmapResource();
- }
- }
+ return gl::NoError();
}
-gl::Error VertexDataManager::prepareVertexData(const gl::State &state,
+void VertexDataManager::deinitialize()
+{
+ mStreamingBuffer.reset();
+ mCurrentValueCache.clear();
+}
+
+gl::Error VertexDataManager::prepareVertexData(const gl::Context *context,
GLint start,
GLsizei count,
std::vector<TranslatedAttribute> *translatedAttribs,
GLsizei instances)
{
- if (!mStreamingBuffer)
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Internal streaming vertex buffer is unexpectedly NULL.");
- }
+ ASSERT(mStreamingBuffer);
- // Compute active enabled and active disable attributes, for speed.
- // TODO(jmadill): don't recompute if there was no state change
+ const gl::State &state = context->getGLState();
const gl::VertexArray *vertexArray = state.getVertexArray();
- const gl::Program *program = state.getProgram();
const auto &vertexAttributes = vertexArray->getVertexAttributes();
+ const auto &vertexBindings = vertexArray->getVertexBindings();
+
+ mDynamicAttribsMaskCache.reset();
+ const gl::Program *program = state.getProgram();
- mActiveEnabledAttributes.clear();
- mActiveDisabledAttributes.clear();
translatedAttribs->clear();
for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex)
{
- if (program->isAttribLocationActive(attribIndex))
- {
- // Resize automatically puts in empty attribs
- translatedAttribs->resize(attribIndex + 1);
+ // Skip attrib locations the program doesn't use.
+ if (!program->isAttribLocationActive(attribIndex))
+ continue;
+
+ const auto &attrib = vertexAttributes[attribIndex];
+ const auto &binding = vertexBindings[attrib.bindingIndex];
- TranslatedAttribute *translated = &(*translatedAttribs)[attribIndex];
+ // Resize automatically puts in empty attribs
+ translatedAttribs->resize(attribIndex + 1);
- // Record the attribute now
- translated->active = true;
- translated->attribute = &vertexAttributes[attribIndex];
- translated->currentValueType =
- state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)).Type;
- translated->divisor = vertexAttributes[attribIndex].divisor;
+ TranslatedAttribute *translated = &(*translatedAttribs)[attribIndex];
+ auto currentValueData = state.getVertexAttribCurrentValue(attribIndex);
- if (vertexAttributes[attribIndex].enabled)
+ // Record the attribute now
+ translated->active = true;
+ translated->attribute = &attrib;
+ translated->binding = &binding;
+ translated->currentValueType = currentValueData.Type;
+ translated->divisor = binding.getDivisor();
+
+ switch (ClassifyAttributeStorage(attrib, binding))
+ {
+ case VertexStorageType::STATIC:
{
- mActiveEnabledAttributes.push_back(translated);
-
- gl::Buffer *buffer = vertexAttributes[attribIndex].buffer.get();
- if (buffer)
- {
- // Also reinitialize static buffers which didn't contain matching data
- // last time they were used
- BufferD3D *bufferImpl = GetImplAs<BufferD3D>(buffer);
- bufferImpl->reinitOutOfDateStaticData();
- }
+ // Store static attribute.
+ ANGLE_TRY(StoreStaticAttrib(context, translated));
+ break;
}
- else
+ case VertexStorageType::DYNAMIC:
+ // Dynamic attributes must be handled together.
+ mDynamicAttribsMaskCache.set(attribIndex);
+ break;
+ case VertexStorageType::DIRECT:
+ // Update translated data for direct attributes.
+ StoreDirectAttrib(translated);
+ break;
+ case VertexStorageType::CURRENT_VALUE:
{
- mActiveDisabledAttributes.push_back(attribIndex);
+ ANGLE_TRY(storeCurrentValue(currentValueData, translated, attribIndex));
+ break;
}
+ default:
+ UNREACHABLE();
+ break;
}
}
- // Reserve the required space in the buffers
- for (const TranslatedAttribute *activeAttrib : mActiveEnabledAttributes)
+ if (mDynamicAttribsMaskCache.none())
{
- gl::Error error = reserveSpaceForAttrib(*activeAttrib, count, instances);
- if (error.isError())
- {
- return error;
- }
+ return gl::NoError();
}
- // Perform the vertex data translations
- for (TranslatedAttribute *activeAttrib : mActiveEnabledAttributes)
+ ANGLE_TRY(storeDynamicAttribs(context, translatedAttribs, mDynamicAttribsMaskCache, start,
+ count, instances));
+
+ PromoteDynamicAttribs(context, *translatedAttribs, mDynamicAttribsMaskCache, count);
+
+ return gl::NoError();
+}
+
+// static
+void VertexDataManager::StoreDirectAttrib(TranslatedAttribute *directAttrib)
+{
+ ASSERT(directAttrib->attribute && directAttrib->binding);
+ const auto &attrib = *directAttrib->attribute;
+ const auto &binding = *directAttrib->binding;
+
+ gl::Buffer *buffer = binding.getBuffer().get();
+ ASSERT(buffer);
+ BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
+
+ ASSERT(DirectStoragePossible(attrib, binding));
+ directAttrib->vertexBuffer.set(nullptr);
+ directAttrib->storage = bufferD3D;
+ directAttrib->serial = bufferD3D->getSerial();
+ directAttrib->stride = static_cast<unsigned int>(ComputeVertexAttributeStride(attrib, binding));
+ directAttrib->baseOffset =
+ static_cast<unsigned int>(ComputeVertexAttributeOffset(attrib, binding));
+
+ // Instanced vertices do not apply the 'start' offset
+ directAttrib->usesFirstVertexOffset = (binding.getDivisor() == 0);
+}
+
+// static
+gl::Error VertexDataManager::StoreStaticAttrib(const gl::Context *context,
+ TranslatedAttribute *translated)
+{
+ ASSERT(translated->attribute && translated->binding);
+ const auto &attrib = *translated->attribute;
+ const auto &binding = *translated->binding;
+
+ gl::Buffer *buffer = binding.getBuffer().get();
+ ASSERT(buffer && attrib.enabled && !DirectStoragePossible(attrib, binding));
+ BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
+
+ // Compute source data pointer
+ const uint8_t *sourceData = nullptr;
+ const int offset = static_cast<int>(ComputeVertexAttributeOffset(attrib, binding));
+
+ ANGLE_TRY(bufferD3D->getData(context, &sourceData));
+ sourceData += offset;
+
+ unsigned int streamOffset = 0;
+
+ translated->storage = nullptr;
+ ANGLE_TRY_RESULT(bufferD3D->getFactory()->getVertexSpaceRequired(attrib, binding, 1, 0),
+ translated->stride);
+
+ auto *staticBuffer = bufferD3D->getStaticVertexBuffer(attrib, binding);
+ ASSERT(staticBuffer);
+
+ if (staticBuffer->empty())
{
- gl::Error error = storeAttribute(activeAttrib, start, count, instances);
+ // Convert the entire buffer
+ int totalCount =
+ ElementsInBuffer(attrib, binding, static_cast<unsigned int>(bufferD3D->getSize()));
+ int startIndex = offset / static_cast<int>(ComputeVertexAttributeStride(attrib, binding));
- if (error.isError())
- {
- hintUnmapAllResources(vertexAttributes);
- return error;
- }
+ ANGLE_TRY(staticBuffer->storeStaticAttribute(attrib, binding, -startIndex, totalCount, 0,
+ sourceData));
}
- for (size_t attribIndex : mActiveDisabledAttributes)
+ unsigned int firstElementOffset =
+ (static_cast<unsigned int>(offset) /
+ static_cast<unsigned int>(ComputeVertexAttributeStride(attrib, binding))) *
+ translated->stride;
+
+ VertexBuffer *vertexBuffer = staticBuffer->getVertexBuffer();
+
+ CheckedNumeric<unsigned int> checkedOffset(streamOffset);
+ checkedOffset += firstElementOffset;
+
+ if (!checkedOffset.IsValid())
{
- if (mCurrentValueCache[attribIndex].buffer == nullptr)
- {
- mCurrentValueCache[attribIndex].buffer = new StreamingVertexBufferInterface(mFactory, CONSTANT_VERTEX_BUFFER_SIZE);
- }
+ return gl::InternalError() << "Integer overflow in VertexDataManager::StoreStaticAttrib";
+ }
+
+ translated->vertexBuffer.set(vertexBuffer);
+ translated->serial = vertexBuffer->getSerial();
+ translated->baseOffset = streamOffset + firstElementOffset;
+
+ // Instanced vertices do not apply the 'start' offset
+ translated->usesFirstVertexOffset = (binding.getDivisor() == 0);
- gl::Error error = storeCurrentValue(
- state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)),
- &(*translatedAttribs)[attribIndex], &mCurrentValueCache[attribIndex]);
- if (error.isError())
+ return gl::NoError();
+}
+
+gl::Error VertexDataManager::storeDynamicAttribs(
+ const gl::Context *context,
+ std::vector<TranslatedAttribute> *translatedAttribs,
+ const gl::AttributesMask &dynamicAttribsMask,
+ GLint start,
+ GLsizei count,
+ GLsizei instances)
+{
+ // Instantiating this class will ensure the streaming buffer is never left mapped.
+ class StreamingBufferUnmapper final : NonCopyable
+ {
+ public:
+ StreamingBufferUnmapper(StreamingVertexBufferInterface *streamingBuffer)
+ : mStreamingBuffer(streamingBuffer)
{
- hintUnmapAllResources(vertexAttributes);
- return error;
+ ASSERT(mStreamingBuffer);
}
+ ~StreamingBufferUnmapper() { mStreamingBuffer->getVertexBuffer()->hintUnmapResource(); }
+
+ private:
+ StreamingVertexBufferInterface *mStreamingBuffer;
+ };
+
+ // Will trigger unmapping on return.
+ StreamingBufferUnmapper localUnmapper(mStreamingBuffer.get());
+
+ // Reserve the required space for the dynamic buffers.
+ for (auto attribIndex : dynamicAttribsMask)
+ {
+ const auto &dynamicAttrib = (*translatedAttribs)[attribIndex];
+ ANGLE_TRY(reserveSpaceForAttrib(dynamicAttrib, start, count, instances));
+ }
+
+ // Store dynamic attributes
+ for (auto attribIndex : dynamicAttribsMask)
+ {
+ auto *dynamicAttrib = &(*translatedAttribs)[attribIndex];
+ ANGLE_TRY(storeDynamicAttrib(context, dynamicAttrib, start, count, instances));
}
- // Hint to unmap all the resources
- hintUnmapAllResources(vertexAttributes);
+ return gl::NoError();
+}
- for (const TranslatedAttribute *activeAttrib : mActiveEnabledAttributes)
+void VertexDataManager::PromoteDynamicAttribs(
+ const gl::Context *context,
+ const std::vector<TranslatedAttribute> &translatedAttribs,
+ const gl::AttributesMask &dynamicAttribsMask,
+ GLsizei count)
+{
+ for (auto attribIndex : dynamicAttribsMask)
{
- gl::Buffer *buffer = activeAttrib->attribute->buffer.get();
+ const auto &dynamicAttrib = translatedAttribs[attribIndex];
+ ASSERT(dynamicAttrib.attribute && dynamicAttrib.binding);
+ const auto &binding = *dynamicAttrib.binding;
+ gl::Buffer *buffer = binding.getBuffer().get();
if (buffer)
{
BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
- size_t typeSize = ComputeVertexAttributeTypeSize(*activeAttrib->attribute);
- bufferD3D->promoteStaticUsage(count * static_cast<int>(typeSize));
+ size_t typeSize = ComputeVertexAttributeTypeSize(*dynamicAttrib.attribute);
+ bufferD3D->promoteStaticUsage(context, count * static_cast<int>(typeSize));
}
}
-
- return gl::Error(GL_NO_ERROR);
}
gl::Error VertexDataManager::reserveSpaceForAttrib(const TranslatedAttribute &translatedAttrib,
+ GLint start,
GLsizei count,
GLsizei instances) const
{
- const gl::VertexAttribute &attrib = *translatedAttrib.attribute;
- gl::Buffer *buffer = attrib.buffer.get();
- BufferD3D *bufferImpl = buffer ? GetImplAs<BufferD3D>(buffer) : NULL;
- StaticVertexBufferInterface *staticBuffer =
- bufferImpl ? bufferImpl->getStaticVertexBuffer(attrib, D3D_BUFFER_CREATE_IF_NECESSARY)
- : NULL;
- VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
-
- if (!vertexBuffer->directStoragePossible(attrib, translatedAttrib.currentValueType))
+ ASSERT(translatedAttrib.attribute && translatedAttrib.binding);
+ const auto &attrib = *translatedAttrib.attribute;
+ const auto &binding = *translatedAttrib.binding;
+
+ ASSERT(!DirectStoragePossible(attrib, binding));
+
+ gl::Buffer *buffer = binding.getBuffer().get();
+ BufferD3D *bufferD3D = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
+ ASSERT(!bufferD3D || bufferD3D->getStaticVertexBuffer(attrib, binding) == nullptr);
+
+ size_t totalCount = gl::ComputeVertexBindingElementCount(
+ binding.getDivisor(), static_cast<size_t>(count), static_cast<size_t>(instances));
+ // TODO(jiajia.qin@intel.com): force the index buffer to clamp any out of range indices instead
+ // of invalid operation here.
+ if (bufferD3D)
{
- if (staticBuffer)
+ // Vertices do not apply the 'start' offset when the divisor is non-zero even when doing
+ // a non-instanced draw call
+ GLint firstVertexIndex = binding.getDivisor() > 0 ? 0 : start;
+ int64_t maxVertexCount =
+ static_cast<int64_t>(firstVertexIndex) + static_cast<int64_t>(totalCount);
+ int elementsInBuffer =
+ ElementsInBuffer(attrib, binding, static_cast<unsigned int>(bufferD3D->getSize()));
+
+ if (maxVertexCount > elementsInBuffer)
{
- if (staticBuffer->getBufferSize() == 0)
- {
- int totalCount =
- ElementsInBuffer(attrib, static_cast<unsigned int>(bufferImpl->getSize()));
- gl::Error error = staticBuffer->reserveVertexSpace(attrib, totalCount, 0);
- if (error.isError())
- {
- return error;
- }
- }
- }
- else
- {
- size_t totalCount = ComputeVertexAttributeElementCount(attrib, count, instances);
- ASSERT(!bufferImpl ||
- ElementsInBuffer(attrib, static_cast<unsigned int>(bufferImpl->getSize())) >=
- static_cast<int>(totalCount));
-
- gl::Error error = mStreamingBuffer->reserveVertexSpace(
- attrib, static_cast<GLsizei>(totalCount), instances);
- if (error.isError())
- {
- return error;
- }
+ return gl::InvalidOperation() << "Vertex buffer is not big enough for the draw call.";
}
}
-
- return gl::Error(GL_NO_ERROR);
+ return mStreamingBuffer->reserveVertexSpace(attrib, binding, static_cast<GLsizei>(totalCount),
+ instances);
}
-gl::Error VertexDataManager::storeAttribute(TranslatedAttribute *translated,
- GLint start,
- GLsizei count,
- GLsizei instances)
+gl::Error VertexDataManager::storeDynamicAttrib(const gl::Context *context,
+ TranslatedAttribute *translated,
+ GLint start,
+ GLsizei count,
+ GLsizei instances)
{
- const gl::VertexAttribute &attrib = *translated->attribute;
+ ASSERT(translated->attribute && translated->binding);
+ const auto &attrib = *translated->attribute;
+ const auto &binding = *translated->binding;
- gl::Buffer *buffer = attrib.buffer.get();
+ gl::Buffer *buffer = binding.getBuffer().get();
ASSERT(buffer || attrib.pointer);
ASSERT(attrib.enabled);
- BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : NULL;
- StaticVertexBufferInterface *staticBuffer =
- storage ? storage->getStaticVertexBuffer(attrib, D3D_BUFFER_DO_NOT_CREATE) : NULL;
- VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
- bool directStorage = vertexBuffer->directStoragePossible(attrib, translated->currentValueType);
+ BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
// Instanced vertices do not apply the 'start' offset
- GLint firstVertexIndex = (attrib.divisor > 0 ? 0 : start);
-
- translated->vertexBuffer = vertexBuffer->getVertexBuffer();
-
- if (directStorage)
- {
- translated->storage = storage;
- translated->serial = storage->getSerial();
- translated->stride = static_cast<unsigned int>(ComputeVertexAttributeStride(attrib));
- translated->offset = static_cast<unsigned int>(attrib.offset + translated->stride * firstVertexIndex);
-
- return gl::Error(GL_NO_ERROR);
- }
+ GLint firstVertexIndex = (binding.getDivisor() > 0 ? 0 : start);
// Compute source data pointer
const uint8_t *sourceData = nullptr;
if (buffer)
{
- gl::Error error = storage->getData(&sourceData);
- if (error.isError())
- {
- return error;
- }
- sourceData += static_cast<int>(attrib.offset);
+ ANGLE_TRY(storage->getData(context, &sourceData));
+ sourceData += static_cast<int>(ComputeVertexAttributeOffset(attrib, binding));
}
else
{
+ // Attributes using client memory ignore the VERTEX_ATTRIB_BINDING state.
+ // https://www.opengl.org/registry/specs/ARB/vertex_attrib_binding.txt
sourceData = static_cast<const uint8_t*>(attrib.pointer);
}
unsigned int streamOffset = 0;
- unsigned int outputElementSize = 0;
- if (staticBuffer)
- {
- gl::Error error = staticBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize);
- if (error.isError())
- {
- return error;
- }
-
- if (!staticBuffer->lookupAttribute(attrib, &streamOffset))
- {
- // Convert the entire buffer
- int totalCount =
- ElementsInBuffer(attrib, static_cast<unsigned int>(storage->getSize()));
- int startIndex = static_cast<int>(attrib.offset) /
- static_cast<int>(ComputeVertexAttributeStride(attrib));
-
- error = staticBuffer->storeVertexAttributes(attrib,
- translated->currentValueType,
- -startIndex,
- totalCount,
- 0,
- &streamOffset,
- sourceData);
- if (error.isError())
- {
- return error;
- }
- }
+ translated->storage = nullptr;
+ ANGLE_TRY_RESULT(mFactory->getVertexSpaceRequired(attrib, binding, 1, 0), translated->stride);
- unsigned int firstElementOffset =
- (static_cast<unsigned int>(attrib.offset) /
- static_cast<unsigned int>(ComputeVertexAttributeStride(attrib))) *
- outputElementSize;
- ASSERT(attrib.divisor == 0 || firstVertexIndex == 0);
- unsigned int startOffset = firstVertexIndex * outputElementSize;
- if (streamOffset + firstElementOffset + startOffset < streamOffset)
- {
- return gl::Error(GL_OUT_OF_MEMORY);
- }
+ size_t totalCount = gl::ComputeVertexBindingElementCount(
+ binding.getDivisor(), static_cast<size_t>(count), static_cast<size_t>(instances));
- streamOffset += firstElementOffset + startOffset;
- }
- else
- {
- size_t totalCount = ComputeVertexAttributeElementCount(attrib, count, instances);
- gl::Error error = mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mStreamingBuffer->storeDynamicAttribute(
+ attrib, binding, translated->currentValueType, firstVertexIndex,
+ static_cast<GLsizei>(totalCount), instances, &streamOffset, sourceData));
- error = mStreamingBuffer->storeVertexAttributes(
- attrib, translated->currentValueType, firstVertexIndex,
- static_cast<GLsizei>(totalCount), instances, &streamOffset, sourceData);
- if (error.isError())
- {
- return error;
- }
- }
+ VertexBuffer *vertexBuffer = mStreamingBuffer->getVertexBuffer();
- translated->storage = nullptr;
+ translated->vertexBuffer.set(vertexBuffer);
translated->serial = vertexBuffer->getSerial();
- translated->stride = outputElementSize;
- translated->offset = streamOffset;
+ translated->baseOffset = streamOffset;
+ translated->usesFirstVertexOffset = false;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error VertexDataManager::storeCurrentValue(const gl::VertexAttribCurrentValueData &currentValue,
TranslatedAttribute *translated,
- CurrentValueState *cachedState)
+ size_t attribIndex)
{
+ CurrentValueState *cachedState = &mCurrentValueCache[attribIndex];
+ auto &buffer = cachedState->buffer;
+
+ if (!buffer)
+ {
+ buffer.reset(new StreamingVertexBufferInterface(mFactory, CONSTANT_VERTEX_BUFFER_SIZE));
+ }
+
if (cachedState->data != currentValue)
{
- const gl::VertexAttribute &attrib = *translated->attribute;
+ ASSERT(translated->attribute && translated->binding);
+ const auto &attrib = *translated->attribute;
+ const auto &binding = *translated->binding;
- gl::Error error = cachedState->buffer->reserveVertexSpace(attrib, 1, 0);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(buffer->reserveVertexSpace(attrib, binding, 1, 0));
const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(currentValue.FloatValues);
unsigned int streamOffset;
- error = cachedState->buffer->storeVertexAttributes(attrib, currentValue.Type, 0, 1, 0, &streamOffset, sourceData);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(buffer->storeDynamicAttribute(attrib, binding, currentValue.Type, 0, 1, 0,
+ &streamOffset, sourceData));
+
+ buffer->getVertexBuffer()->hintUnmapResource();
cachedState->data = currentValue;
cachedState->offset = streamOffset;
}
- translated->storage = NULL;
- translated->vertexBuffer = cachedState->buffer->getVertexBuffer();
- translated->serial = cachedState->buffer->getSerial();
+ translated->vertexBuffer.set(buffer->getVertexBuffer());
+
+ translated->storage = nullptr;
+ translated->serial = buffer->getSerial();
translated->divisor = 0;
+ translated->stride = 0;
+ translated->baseOffset = static_cast<unsigned int>(cachedState->offset);
+ translated->usesFirstVertexOffset = false;
- translated->stride = 0;
- translated->offset = static_cast<unsigned int>(cachedState->offset);
+ return gl::NoError();
+}
- return gl::Error(GL_NO_ERROR);
+// VertexBufferBinding implementation
+VertexBufferBinding::VertexBufferBinding() : mBoundVertexBuffer(nullptr)
+{
}
+VertexBufferBinding::VertexBufferBinding(const VertexBufferBinding &other)
+ : mBoundVertexBuffer(other.mBoundVertexBuffer)
+{
+ if (mBoundVertexBuffer)
+ {
+ mBoundVertexBuffer->addRef();
+ }
+}
+
+VertexBufferBinding::~VertexBufferBinding()
+{
+ if (mBoundVertexBuffer)
+ {
+ mBoundVertexBuffer->release();
+ }
}
+
+VertexBufferBinding &VertexBufferBinding::operator=(const VertexBufferBinding &other)
+{
+ mBoundVertexBuffer = other.mBoundVertexBuffer;
+ if (mBoundVertexBuffer)
+ {
+ mBoundVertexBuffer->addRef();
+ }
+ return *this;
+}
+
+void VertexBufferBinding::set(VertexBuffer *vertexBuffer)
+{
+ if (mBoundVertexBuffer == vertexBuffer)
+ return;
+
+ if (mBoundVertexBuffer)
+ {
+ mBoundVertexBuffer->release();
+ }
+ if (vertexBuffer)
+ {
+ vertexBuffer->addRef();
+ }
+
+ mBoundVertexBuffer = vertexBuffer;
+}
+
+VertexBuffer *VertexBufferBinding::get() const
+{
+ return mBoundVertexBuffer;
+}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.h
index fb349c4cc2..694366deb7 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.h
@@ -10,14 +10,16 @@
#ifndef LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_
#define LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_
+#include "common/angleutils.h"
+#include "libANGLE/angletypes.h"
#include "libANGLE/Constants.h"
#include "libANGLE/VertexAttribute.h"
-#include "common/angleutils.h"
namespace gl
{
class State;
struct VertexAttribute;
+class VertexBinding;
struct VertexAttribCurrentValueData;
}
@@ -28,81 +30,123 @@ class BufferFactoryD3D;
class StreamingVertexBufferInterface;
class VertexBuffer;
+class VertexBufferBinding final
+{
+ public:
+ VertexBufferBinding();
+ VertexBufferBinding(const VertexBufferBinding &other);
+ ~VertexBufferBinding();
+
+ void set(VertexBuffer *vertexBuffer);
+ VertexBuffer *get() const;
+ VertexBufferBinding &operator=(const VertexBufferBinding &other);
+
+ private:
+ VertexBuffer *mBoundVertexBuffer;
+};
+
struct TranslatedAttribute
{
- TranslatedAttribute()
- : active(false),
- attribute(NULL),
- currentValueType(GL_NONE),
- offset(0),
- stride(0),
- vertexBuffer(NULL),
- storage(NULL),
- serial(0),
- divisor(0)
- {}
+ TranslatedAttribute();
+ TranslatedAttribute(const TranslatedAttribute &other);
+
+ // Computes the correct offset from baseOffset, usesFirstVertexOffset, stride and startVertex.
+ // Can throw an error on integer overflow.
+ gl::ErrorOrResult<unsigned int> computeOffset(GLint startVertex) const;
bool active;
const gl::VertexAttribute *attribute;
+ const gl::VertexBinding *binding;
GLenum currentValueType;
- unsigned int offset;
+ unsigned int baseOffset;
+ bool usesFirstVertexOffset;
unsigned int stride; // 0 means not to advance the read pointer at all
- VertexBuffer *vertexBuffer;
+ VertexBufferBinding vertexBuffer;
BufferD3D *storage;
unsigned int serial;
unsigned int divisor;
};
+enum class VertexStorageType
+{
+ UNKNOWN,
+ STATIC, // Translate the vertex data once and re-use it.
+ DYNAMIC, // Translate the data every frame into a ring buffer.
+ DIRECT, // Bind a D3D buffer directly without any translation.
+ CURRENT_VALUE, // Use a single value for the attribute.
+};
+
+// Given a vertex attribute, return the type of storage it will use.
+VertexStorageType ClassifyAttributeStorage(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding);
+
class VertexDataManager : angle::NonCopyable
{
public:
VertexDataManager(BufferFactoryD3D *factory);
virtual ~VertexDataManager();
- gl::Error prepareVertexData(const gl::State &state,
+ gl::Error initialize();
+ void deinitialize();
+
+ gl::Error prepareVertexData(const gl::Context *context,
GLint start,
GLsizei count,
std::vector<TranslatedAttribute> *translatedAttribs,
GLsizei instances);
+ static void StoreDirectAttrib(TranslatedAttribute *directAttrib);
+
+ static gl::Error StoreStaticAttrib(const gl::Context *context, TranslatedAttribute *translated);
+
+ gl::Error storeDynamicAttribs(const gl::Context *context,
+ std::vector<TranslatedAttribute> *translatedAttribs,
+ const gl::AttributesMask &dynamicAttribsMask,
+ GLint start,
+ GLsizei count,
+ GLsizei instances);
+
+ // Promote static usage of dynamic buffers.
+ static void PromoteDynamicAttribs(const gl::Context *context,
+ const std::vector<TranslatedAttribute> &translatedAttribs,
+ const gl::AttributesMask &dynamicAttribsMask,
+ GLsizei count);
+
+ gl::Error storeCurrentValue(const gl::VertexAttribCurrentValueData &currentValue,
+ TranslatedAttribute *translated,
+ size_t attribIndex);
+
private:
struct CurrentValueState
{
CurrentValueState();
~CurrentValueState();
- StreamingVertexBufferInterface *buffer;
+ std::unique_ptr<StreamingVertexBufferInterface> buffer;
gl::VertexAttribCurrentValueData data;
size_t offset;
};
gl::Error reserveSpaceForAttrib(const TranslatedAttribute &translatedAttrib,
GLsizei count,
+ GLint start,
GLsizei instances) const;
- gl::Error storeAttribute(TranslatedAttribute *translated,
- GLint start,
- GLsizei count,
- GLsizei instances);
-
- gl::Error storeCurrentValue(const gl::VertexAttribCurrentValueData &currentValue,
- TranslatedAttribute *translated,
- CurrentValueState *cachedState);
-
- void hintUnmapAllResources(const std::vector<gl::VertexAttribute> &vertexAttributes);
+ gl::Error storeDynamicAttrib(const gl::Context *context,
+ TranslatedAttribute *translated,
+ GLint start,
+ GLsizei count,
+ GLsizei instances);
BufferFactoryD3D *const mFactory;
- StreamingVertexBufferInterface *mStreamingBuffer;
+ std::unique_ptr<StreamingVertexBufferInterface> mStreamingBuffer;
std::vector<CurrentValueState> mCurrentValueCache;
-
- // Cache variables
- std::vector<TranslatedAttribute *> mActiveEnabledAttributes;
- std::vector<size_t> mActiveDisabledAttributes;
+ gl::AttributesMask mDynamicAttribsMaskCache;
};
-}
+} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/WorkaroundsD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/WorkaroundsD3D.h
deleted file mode 100644
index 58f65f6496..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/WorkaroundsD3D.h
+++ /dev/null
@@ -1,66 +0,0 @@
-//
-// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// WorkaroundsD3D.h: Workarounds for D3D driver bugs and other issues.
-
-#ifndef LIBANGLE_RENDERER_D3D_WORKAROUNDSD3D_H_
-#define LIBANGLE_RENDERER_D3D_WORKAROUNDSD3D_H_
-
-// TODO(jmadill,zmo,geofflang): make a workarounds library that can operate
-// independent of ANGLE's renderer. Workarounds should also be accessible
-// outside of the Renderer.
-
-namespace rx
-{
-struct D3DCompilerWorkarounds
-{
- D3DCompilerWorkarounds()
- : skipOptimization(false), useMaxOptimization(false), enableIEEEStrictness(false)
- {
- }
-
- bool skipOptimization;
- bool useMaxOptimization;
-
- // IEEE strictness needs to be enabled for NANs to work.
- bool enableIEEEStrictness;
-};
-
-struct WorkaroundsD3D
-{
- WorkaroundsD3D()
- : mrtPerfWorkaround(false),
- setDataFasterThanImageUpload(false),
- zeroMaxLodWorkaround(false),
- useInstancedPointSpriteEmulation(false)
- {
- }
-
- // On some systems, having extra rendertargets than necessary slows down the shader.
- // We can fix this by optimizing those out of the shader. At the same time, we can
- // work around a bug on some nVidia drivers that they ignore "null" render targets
- // in D3D11, by compacting the active color attachments list to omit null entries.
- bool mrtPerfWorkaround;
-
- bool setDataFasterThanImageUpload;
-
- // Some renderers can't disable mipmaps on a mipmapped texture (i.e. solely sample from level
- // zero, and ignore the other levels). D3D11 Feature Level 10+ does this by setting MaxLOD to
- // 0.0f in the Sampler state. D3D9 sets D3DSAMP_MIPFILTER to D3DTEXF_NONE. There is no
- // equivalent to this in D3D11 Feature Level 9_3. This causes problems when (for example) an
- // application creates a mipmapped texture2D, but sets GL_TEXTURE_MIN_FILTER to GL_NEAREST
- // (i.e disables mipmaps). To work around this, D3D11 FL9_3 has to create two copies of the
- // texture. The textures' level zeros are identical, but only one texture has mips.
- bool zeroMaxLodWorkaround;
-
- // Some renderers do not support Geometry Shaders so the Geometry Shader-based PointSprite
- // emulation will not work. To work around this, D3D11 FL9_3 has to use a different pointsprite
- // emulation that is implemented using instanced quads.
- bool useInstancedPointSpriteEmulation;
-};
-}
-
-#endif // LIBANGLE_RENDERER_D3D_WORKAROUNDSD3D_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.cpp
deleted file mode 100644
index b1798454ca..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// copyimage.cpp: Defines image copying functions
-
-#include "libANGLE/renderer/d3d/copyimage.h"
-
-namespace rx
-{
-
-void CopyBGRA8ToRGBA8(const uint8_t *source, uint8_t *dest)
-{
- uint32_t argb = *reinterpret_cast<const uint32_t*>(source);
- *reinterpret_cast<uint32_t*>(dest) = (argb & 0xFF00FF00) | // Keep alpha and green
- (argb & 0x00FF0000) >> 16 | // Move red to blue
- (argb & 0x000000FF) << 16; // Move blue to red
-}
-
-}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.h
deleted file mode 100644
index 189654ca39..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// copyimage.h: Defines image copying functions
-
-#ifndef LIBANGLE_RENDERER_D3D_COPYIMAGE_H_
-#define LIBANGLE_RENDERER_D3D_COPYIMAGE_H_
-
-#include "common/mathutil.h"
-#include "libANGLE/angletypes.h"
-
-#include <stdint.h>
-
-namespace rx
-{
-
-template <typename sourceType, typename colorDataType>
-void ReadColor(const uint8_t *source, uint8_t *dest);
-
-template <typename destType, typename colorDataType>
-void WriteColor(const uint8_t *source, uint8_t *dest);
-
-template <typename sourceType, typename destType, typename colorDataType>
-void CopyPixel(const uint8_t *source, uint8_t *dest);
-
-void CopyBGRA8ToRGBA8(const uint8_t *source, uint8_t *dest);
-
-}
-
-#include "copyimage.inl"
-
-#endif // LIBANGLE_RENDERER_D3D_COPYIMAGE_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.inl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.inl
deleted file mode 100644
index 0498cf7750..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.inl
+++ /dev/null
@@ -1,32 +0,0 @@
-//
-// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// copyimage.inl: Defines image copying functions
-
-namespace rx
-{
-
-template <typename sourceType, typename colorDataType>
-inline void ReadColor(const uint8_t *source, uint8_t *dest)
-{
- sourceType::readColor(reinterpret_cast<gl::Color<colorDataType>*>(dest), reinterpret_cast<const sourceType*>(source));
-}
-
-template <typename destType, typename colorDataType>
-inline void WriteColor(const uint8_t *source, uint8_t *dest)
-{
- destType::writeColor(reinterpret_cast<destType*>(dest), reinterpret_cast<const gl::Color<colorDataType>*>(source));
-}
-
-template <typename sourceType, typename destType, typename colorDataType>
-inline void CopyPixel(const uint8_t *source, uint8_t *dest)
-{
- colorDataType temp;
- ReadColor<sourceType, colorDataType>(source, &temp);
- WriteColor<destType, colorDataType>(&temp, dest);
-}
-
-}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp
index e951e13408..f032e888f1 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp
@@ -10,112 +10,404 @@
#include <float.h>
+#include "common/utilities.h"
#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
-#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
#include "third_party/trace_event/trace_event.h"
+namespace rx
+{
+
+namespace
+{
+
+// Include inline shaders in the anonymous namespace to make sure no symbols are exported
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrougha2d11ps.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h"
+
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_luma_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_lumaalpha_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_luma_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_lumaalpha_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgb_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgba_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgb_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgba_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgb_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgba_ps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h"
+
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepth11_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvestencil11_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h"
-namespace rx
+void StretchedBlitNearest_RowByRow(const gl::Box &sourceArea,
+ const gl::Box &destArea,
+ const gl::Rectangle &clippedDestArea,
+ const gl::Extents &sourceSize,
+ unsigned int sourceRowPitch,
+ unsigned int destRowPitch,
+ size_t pixelSize,
+ const uint8_t *sourceData,
+ uint8_t *destData)
{
+ int srcHeightSubOne = (sourceArea.height - 1);
+ size_t copySize = pixelSize * destArea.width;
+ size_t srcOffset = sourceArea.x * pixelSize;
+ size_t destOffset = destArea.x * pixelSize;
-namespace
+ for (int y = clippedDestArea.y; y < clippedDestArea.y + clippedDestArea.height; y++)
+ {
+ float yPerc = static_cast<float>(y - destArea.y) / (destArea.height - 1);
+
+ // Interpolate using the original source rectangle to determine which row to sample from
+ // while clamping to the edges
+ unsigned int readRow = static_cast<unsigned int>(
+ gl::clamp(sourceArea.y + floor(yPerc * srcHeightSubOne + 0.5f), 0, srcHeightSubOne));
+ unsigned int writeRow = y;
+
+ const uint8_t *sourceRow = sourceData + readRow * sourceRowPitch + srcOffset;
+ uint8_t *destRow = destData + writeRow * destRowPitch + destOffset;
+ memcpy(destRow, sourceRow, copySize);
+ }
+}
+
+void StretchedBlitNearest_PixelByPixel(const gl::Box &sourceArea,
+ const gl::Box &destArea,
+ const gl::Rectangle &clippedDestArea,
+ const gl::Extents &sourceSize,
+ unsigned int sourceRowPitch,
+ unsigned int destRowPitch,
+ ptrdiff_t readOffset,
+ ptrdiff_t writeOffset,
+ size_t copySize,
+ size_t srcPixelStride,
+ size_t destPixelStride,
+ const uint8_t *sourceData,
+ uint8_t *destData)
{
+ auto xMax = clippedDestArea.x + clippedDestArea.width;
+ auto yMax = clippedDestArea.y + clippedDestArea.height;
-DXGI_FORMAT GetTextureFormat(ID3D11Resource *resource)
+ for (int writeRow = clippedDestArea.y; writeRow < yMax; writeRow++)
+ {
+ // Interpolate using the original source rectangle to determine which row to sample from
+ // while clamping to the edges
+ float yPerc = static_cast<float>(writeRow - destArea.y) / (destArea.height - 1);
+ float yRounded = floor(yPerc * (sourceArea.height - 1) + 0.5f);
+ unsigned int readRow =
+ static_cast<unsigned int>(gl::clamp(sourceArea.y + yRounded, 0, sourceSize.height - 1));
+
+ for (int writeColumn = clippedDestArea.x; writeColumn < xMax; writeColumn++)
+ {
+ // Interpolate the original source rectangle to determine which column to sample
+ // from while clamping to the edges
+ float xPerc = static_cast<float>(writeColumn - destArea.x) / (destArea.width - 1);
+ float xRounded = floor(xPerc * (sourceArea.width - 1) + 0.5f);
+ unsigned int readColumn = static_cast<unsigned int>(
+ gl::clamp(sourceArea.x + xRounded, 0, sourceSize.height - 1));
+
+ const uint8_t *sourcePixel =
+ sourceData + readRow * sourceRowPitch + readColumn * srcPixelStride + readOffset;
+
+ uint8_t *destPixel =
+ destData + writeRow * destRowPitch + writeColumn * destPixelStride + writeOffset;
+
+ memcpy(destPixel, sourcePixel, copySize);
+ }
+ }
+}
+
+void StretchedBlitNearest(const gl::Box &sourceArea,
+ const gl::Box &destArea,
+ const gl::Rectangle &clipRect,
+ const gl::Extents &sourceSize,
+ unsigned int sourceRowPitch,
+ unsigned int destRowPitch,
+ ptrdiff_t readOffset,
+ ptrdiff_t writeOffset,
+ size_t copySize,
+ size_t srcPixelStride,
+ size_t destPixelStride,
+ const uint8_t *sourceData,
+ uint8_t *destData)
{
- ID3D11Texture2D *texture = d3d11::DynamicCastComObject<ID3D11Texture2D>(resource);
- if (!texture)
+ gl::Rectangle clippedDestArea(destArea.x, destArea.y, destArea.width, destArea.height);
+ gl::ClipRectangle(clippedDestArea, clipRect, &clippedDestArea);
+
+ // Determine if entire rows can be copied at once instead of each individual pixel. There
+ // must be no out of bounds lookups, whole rows copies, and no scale.
+ if (sourceArea.width == clippedDestArea.width && sourceArea.x >= 0 &&
+ sourceArea.x + sourceArea.width <= sourceSize.width && copySize == srcPixelStride &&
+ copySize == destPixelStride)
+ {
+ StretchedBlitNearest_RowByRow(sourceArea, destArea, clippedDestArea, sourceSize,
+ sourceRowPitch, destRowPitch, srcPixelStride, sourceData,
+ destData);
+ }
+ else
{
- return DXGI_FORMAT_UNKNOWN;
+ StretchedBlitNearest_PixelByPixel(sourceArea, destArea, clippedDestArea, sourceSize,
+ sourceRowPitch, destRowPitch, readOffset, writeOffset,
+ copySize, srcPixelStride, destPixelStride, sourceData,
+ destData);
}
+}
- D3D11_TEXTURE2D_DESC desc;
- texture->GetDesc(&desc);
+using DepthStencilLoader = void(const float *, uint8_t *);
- SafeRelease(texture);
+void LoadDepth16(const float *source, uint8_t *dest)
+{
+ uint32_t convertedDepth = gl::floatToNormalized<16, uint32_t>(source[0]);
+ memcpy(dest, &convertedDepth, 2u);
+}
- return desc.Format;
+void LoadDepth24(const float *source, uint8_t *dest)
+{
+ uint32_t convertedDepth = gl::floatToNormalized<24, uint32_t>(source[0]);
+ memcpy(dest, &convertedDepth, 3u);
}
-ID3D11Resource *CreateStagingTexture(ID3D11Device *device, ID3D11DeviceContext *context,
- ID3D11Resource *source, unsigned int subresource,
- const gl::Extents &size, unsigned int cpuAccessFlags)
+void LoadStencilHelper(const float *source, uint8_t *dest)
{
- D3D11_TEXTURE2D_DESC stagingDesc;
- stagingDesc.Width = size.width;
- stagingDesc.Height = size.height;
- stagingDesc.MipLevels = 1;
- stagingDesc.ArraySize = 1;
- stagingDesc.Format = GetTextureFormat(source);
- stagingDesc.SampleDesc.Count = 1;
- stagingDesc.SampleDesc.Quality = 0;
- stagingDesc.Usage = D3D11_USAGE_STAGING;
- stagingDesc.CPUAccessFlags = cpuAccessFlags;
- stagingDesc.MiscFlags = 0;
- stagingDesc.BindFlags = 0;
-
- ID3D11Texture2D *stagingTexture = nullptr;
- HRESULT result = device->CreateTexture2D(&stagingDesc, nullptr, &stagingTexture);
- if (FAILED(result))
+ uint32_t convertedStencil = gl::getShiftedData<8, 0>(static_cast<uint32_t>(source[1]));
+ memcpy(dest, &convertedStencil, 1u);
+}
+
+void LoadStencil8(const float *source, uint8_t *dest)
+{
+ // STENCIL_INDEX8 is implemented with D24S8, with the depth bits unused. Writes zero for safety.
+ float zero = 0.0f;
+ LoadDepth24(&zero, &dest[0]);
+ LoadStencilHelper(source, &dest[3]);
+}
+
+void LoadDepth24Stencil8(const float *source, uint8_t *dest)
+{
+ LoadDepth24(source, &dest[0]);
+ LoadStencilHelper(source, &dest[3]);
+}
+
+void LoadDepth32F(const float *source, uint8_t *dest)
+{
+ memcpy(dest, source, sizeof(float));
+}
+
+void LoadDepth32FStencil8(const float *source, uint8_t *dest)
+{
+ LoadDepth32F(source, &dest[0]);
+ LoadStencilHelper(source, &dest[4]);
+}
+
+template <DepthStencilLoader loader>
+void CopyDepthStencil(const gl::Box &sourceArea,
+ const gl::Box &destArea,
+ const gl::Rectangle &clippedDestArea,
+ const gl::Extents &sourceSize,
+ unsigned int sourceRowPitch,
+ unsigned int destRowPitch,
+ ptrdiff_t readOffset,
+ ptrdiff_t writeOffset,
+ size_t copySize,
+ size_t srcPixelStride,
+ size_t destPixelStride,
+ const uint8_t *sourceData,
+ uint8_t *destData)
+{
+ // No stretching or subregions are supported, only full blits.
+ ASSERT(sourceArea == destArea);
+ ASSERT(sourceSize.width == sourceArea.width && sourceSize.height == sourceArea.height &&
+ sourceSize.depth == 1);
+ ASSERT(clippedDestArea.width == sourceSize.width &&
+ clippedDestArea.height == sourceSize.height);
+ ASSERT(readOffset == 0 && writeOffset == 0);
+ ASSERT(destArea.x == 0 && destArea.y == 0);
+
+ for (int row = 0; row < destArea.height; ++row)
+ {
+ for (int column = 0; column < destArea.width; ++column)
+ {
+ ptrdiff_t offset = row * sourceRowPitch + column * srcPixelStride;
+ const float *sourcePixel = reinterpret_cast<const float *>(sourceData + offset);
+
+ uint8_t *destPixel = destData + row * destRowPitch + column * destPixelStride;
+
+ loader(sourcePixel, destPixel);
+ }
+ }
+}
+
+void Depth32FStencil8ToDepth32F(const float *source, float *dest)
+{
+ *dest = *source;
+}
+
+void Depth24Stencil8ToDepth32F(const uint32_t *source, float *dest)
+{
+ uint32_t normDepth = source[0] & 0x00FFFFFF;
+ float floatDepth = gl::normalizedToFloat<24>(normDepth);
+ *dest = floatDepth;
+}
+
+void BlitD24S8ToD32F(const gl::Box &sourceArea,
+ const gl::Box &destArea,
+ const gl::Rectangle &clippedDestArea,
+ const gl::Extents &sourceSize,
+ unsigned int sourceRowPitch,
+ unsigned int destRowPitch,
+ ptrdiff_t readOffset,
+ ptrdiff_t writeOffset,
+ size_t copySize,
+ size_t srcPixelStride,
+ size_t destPixelStride,
+ const uint8_t *sourceData,
+ uint8_t *destData)
+{
+ // No stretching or subregions are supported, only full blits.
+ ASSERT(sourceArea == destArea);
+ ASSERT(sourceSize.width == sourceArea.width && sourceSize.height == sourceArea.height &&
+ sourceSize.depth == 1);
+ ASSERT(clippedDestArea.width == sourceSize.width &&
+ clippedDestArea.height == sourceSize.height);
+ ASSERT(readOffset == 0 && writeOffset == 0);
+ ASSERT(destArea.x == 0 && destArea.y == 0);
+
+ for (int row = 0; row < destArea.height; ++row)
{
- ERR("Failed to create staging texture for depth stencil blit. HRESULT: 0x%X.", result);
- return nullptr;
+ for (int column = 0; column < destArea.width; ++column)
+ {
+ ptrdiff_t offset = row * sourceRowPitch + column * srcPixelStride;
+ const uint32_t *sourcePixel = reinterpret_cast<const uint32_t *>(sourceData + offset);
+
+ float *destPixel =
+ reinterpret_cast<float *>(destData + row * destRowPitch + column * destPixelStride);
+
+ Depth24Stencil8ToDepth32F(sourcePixel, destPixel);
+ }
}
+}
- context->CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, source, subresource, nullptr);
+void BlitD32FS8ToD32F(const gl::Box &sourceArea,
+ const gl::Box &destArea,
+ const gl::Rectangle &clippedDestArea,
+ const gl::Extents &sourceSize,
+ unsigned int sourceRowPitch,
+ unsigned int destRowPitch,
+ ptrdiff_t readOffset,
+ ptrdiff_t writeOffset,
+ size_t copySize,
+ size_t srcPixelStride,
+ size_t destPixelStride,
+ const uint8_t *sourceData,
+ uint8_t *destData)
+{
+ // No stretching or subregions are supported, only full blits.
+ ASSERT(sourceArea == destArea);
+ ASSERT(sourceSize.width == sourceArea.width && sourceSize.height == sourceArea.height &&
+ sourceSize.depth == 1);
+ ASSERT(clippedDestArea.width == sourceSize.width &&
+ clippedDestArea.height == sourceSize.height);
+ ASSERT(readOffset == 0 && writeOffset == 0);
+ ASSERT(destArea.x == 0 && destArea.y == 0);
+
+ for (int row = 0; row < destArea.height; ++row)
+ {
+ for (int column = 0; column < destArea.width; ++column)
+ {
+ ptrdiff_t offset = row * sourceRowPitch + column * srcPixelStride;
+ const float *sourcePixel = reinterpret_cast<const float *>(sourceData + offset);
+ float *destPixel =
+ reinterpret_cast<float *>(destData + row * destRowPitch + column * destPixelStride);
- return stagingTexture;
+ Depth32FStencil8ToDepth32F(sourcePixel, destPixel);
+ }
+ }
+}
+
+Blit11::BlitConvertFunction *GetCopyDepthStencilFunction(GLenum internalFormat)
+{
+ switch (internalFormat)
+ {
+ case GL_DEPTH_COMPONENT16:
+ return &CopyDepthStencil<LoadDepth16>;
+ case GL_DEPTH_COMPONENT24:
+ return &CopyDepthStencil<LoadDepth24>;
+ case GL_DEPTH_COMPONENT32F:
+ return &CopyDepthStencil<LoadDepth32F>;
+ case GL_STENCIL_INDEX8:
+ return &CopyDepthStencil<LoadStencil8>;
+ case GL_DEPTH24_STENCIL8:
+ return &CopyDepthStencil<LoadDepth24Stencil8>;
+ case GL_DEPTH32F_STENCIL8:
+ return &CopyDepthStencil<LoadDepth32FStencil8>;
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
}
-inline void GenerateVertexCoords(const gl::Box &sourceArea, const gl::Extents &sourceSize,
- const gl::Box &destArea, const gl::Extents &destSize,
- float *x1, float *y1, float *x2, float *y2,
- float *u1, float *v1, float *u2, float *v2)
+inline void GenerateVertexCoords(const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ float *x1,
+ float *y1,
+ float *x2,
+ float *y2,
+ float *u1,
+ float *v1,
+ float *u2,
+ float *v2)
{
*x1 = (destArea.x / float(destSize.width)) * 2.0f - 1.0f;
*y1 = ((destSize.height - destArea.y - destArea.height) / float(destSize.height)) * 2.0f - 1.0f;
@@ -128,37 +420,49 @@ inline void GenerateVertexCoords(const gl::Box &sourceArea, const gl::Extents &s
*v2 = (sourceArea.y + sourceArea.height) / float(sourceSize.height);
}
-void Write2DVertices(const gl::Box &sourceArea, const gl::Extents &sourceSize,
- const gl::Box &destArea, const gl::Extents &destSize,
- void *outVertices, unsigned int *outStride, unsigned int *outVertexCount,
+void Write2DVertices(const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ void *outVertices,
+ unsigned int *outStride,
+ unsigned int *outVertexCount,
D3D11_PRIMITIVE_TOPOLOGY *outTopology)
{
float x1, y1, x2, y2, u1, v1, u2, v2;
- GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1, &u2, &v2);
+ GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1,
+ &u2, &v2);
- d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(outVertices);
+ d3d11::PositionTexCoordVertex *vertices =
+ static_cast<d3d11::PositionTexCoordVertex *>(outVertices);
d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v2);
d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v1);
d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v2);
d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v1);
- *outStride = sizeof(d3d11::PositionTexCoordVertex);
+ *outStride = sizeof(d3d11::PositionTexCoordVertex);
*outVertexCount = 4;
- *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
+ *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
}
-void Write3DVertices(const gl::Box &sourceArea, const gl::Extents &sourceSize,
- const gl::Box &destArea, const gl::Extents &destSize,
- void *outVertices, unsigned int *outStride, unsigned int *outVertexCount,
+void Write3DVertices(const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ void *outVertices,
+ unsigned int *outStride,
+ unsigned int *outVertexCount,
D3D11_PRIMITIVE_TOPOLOGY *outTopology)
{
ASSERT(sourceSize.depth > 0 && destSize.depth > 0);
float x1, y1, x2, y2, u1, v1, u2, v2;
- GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1, &u2, &v2);
+ GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1,
+ &u2, &v2);
- d3d11::PositionLayerTexCoord3DVertex *vertices = static_cast<d3d11::PositionLayerTexCoord3DVertex*>(outVertices);
+ d3d11::PositionLayerTexCoord3DVertex *vertices =
+ static_cast<d3d11::PositionLayerTexCoord3DVertex *>(outVertices);
for (int i = 0; i < destSize.depth; i++)
{
@@ -173,24 +477,38 @@ void Write3DVertices(const gl::Box &sourceArea, const gl::Extents &sourceSize,
d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 5], x2, y1, i, u2, v2, readDepth);
}
- *outStride = sizeof(d3d11::PositionLayerTexCoord3DVertex);
+ *outStride = sizeof(d3d11::PositionLayerTexCoord3DVertex);
*outVertexCount = destSize.depth * 6;
- *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+ *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
}
-inline unsigned int GetSwizzleIndex(GLenum swizzle)
+unsigned int GetSwizzleIndex(GLenum swizzle)
{
unsigned int colorIndex = 0;
switch (swizzle)
{
- case GL_RED: colorIndex = 0; break;
- case GL_GREEN: colorIndex = 1; break;
- case GL_BLUE: colorIndex = 2; break;
- case GL_ALPHA: colorIndex = 3; break;
- case GL_ZERO: colorIndex = 4; break;
- case GL_ONE: colorIndex = 5; break;
- default: UNREACHABLE(); break;
+ case GL_RED:
+ colorIndex = 0;
+ break;
+ case GL_GREEN:
+ colorIndex = 1;
+ break;
+ case GL_BLUE:
+ colorIndex = 2;
+ break;
+ case GL_ALPHA:
+ colorIndex = 3;
+ break;
+ case GL_ZERO:
+ colorIndex = 4;
+ break;
+ case GL_ONE:
+ colorIndex = 5;
+ break;
+ default:
+ UNREACHABLE();
+ break;
}
return colorIndex;
@@ -213,30 +531,50 @@ D3D11_BLEND_DESC GetAlphaMaskBlendStateDesc()
return desc;
}
-D3D11_INPUT_ELEMENT_DESC quad2DLayout[] =
-{
- { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
- { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+D3D11_INPUT_ELEMENT_DESC quad2DLayout[] = {
+ {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
+ {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
};
-D3D11_INPUT_ELEMENT_DESC quad3DLayout[] =
-{
- { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
- { "LAYER", 0, DXGI_FORMAT_R32_UINT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
- { "TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+D3D11_INPUT_ELEMENT_DESC quad3DLayout[] = {
+ {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
+ {"LAYER", 0, DXGI_FORMAT_R32_UINT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
+ {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
};
-} // namespace
+DXGI_FORMAT GetStencilSRVFormat(const d3d11::Format &formatSet)
+{
+ switch (formatSet.texFormat)
+ {
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ return DXGI_FORMAT_X32_TYPELESS_G8X24_UINT;
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ return DXGI_FORMAT_X24_TYPELESS_G8_UINT;
+ default:
+ UNREACHABLE();
+ return DXGI_FORMAT_UNKNOWN;
+ }
+}
+
+} // namespace
+
+Blit11::Shader::Shader() = default;
+
+Blit11::Shader::Shader(Shader &&other) = default;
+
+Blit11::Shader::~Shader() = default;
+
+Blit11::Shader &Blit11::Shader::operator=(Blit11::Shader &&other) = default;
Blit11::Blit11(Renderer11 *renderer)
: mRenderer(renderer),
mResourcesInitialized(false),
- mVertexBuffer(nullptr),
- mPointSampler(nullptr),
- mLinearSampler(nullptr),
- mScissorEnabledRasterizerState(nullptr),
- mScissorDisabledRasterizerState(nullptr),
- mDepthStencilState(nullptr),
+ mVertexBuffer(),
+ mPointSampler(),
+ mLinearSampler(),
+ mScissorEnabledRasterizerState(),
+ mScissorDisabledRasterizerState(),
+ mDepthStencilState(),
mQuad2DIL(quad2DLayout,
ArraySize(quad2DLayout),
g_VS_Passthrough2D,
@@ -254,516 +592,552 @@ Blit11::Blit11(Renderer11 *renderer)
mQuad3DVS(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), "Blit11 3D vertex shader"),
mQuad3DGS(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), "Blit11 3D geometry shader"),
mAlphaMaskBlendState(GetAlphaMaskBlendStateDesc(), "Blit11 Alpha Mask Blend"),
- mSwizzleCB(nullptr)
+ mSwizzleCB(),
+ mResolveDepthStencilVS(g_VS_ResolveDepthStencil,
+ ArraySize(g_VS_ResolveDepthStencil),
+ "Blit11::mResolveDepthStencilVS"),
+ mResolveDepthPS(g_PS_ResolveDepth, ArraySize(g_PS_ResolveDepth), "Blit11::mResolveDepthPS"),
+ mResolveDepthStencilPS(g_PS_ResolveDepthStencil,
+ ArraySize(g_PS_ResolveDepthStencil),
+ "Blit11::mResolveDepthStencilPS"),
+ mResolveStencilPS(g_PS_ResolveStencil,
+ ArraySize(g_PS_ResolveStencil),
+ "Blit11::mResolveStencilPS"),
+ mStencilSRV(),
+ mResolvedDepthStencilRTView()
{
}
Blit11::~Blit11()
{
- freeResources();
-
- mQuad2DIL.release();
- mQuad2DVS.release();
- mDepthPS.release();
-
- mQuad3DIL.release();
- mQuad3DVS.release();
- mQuad3DGS.release();
-
- clearShaderMap();
}
gl::Error Blit11::initResources()
{
if (mResourcesInitialized)
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
TRACE_EVENT0("gpu.angle", "Blit11::initResources");
- HRESULT result;
- ID3D11Device *device = mRenderer->getDevice();
-
D3D11_BUFFER_DESC vbDesc;
vbDesc.ByteWidth =
static_cast<unsigned int>(std::max(sizeof(d3d11::PositionLayerTexCoord3DVertex),
sizeof(d3d11::PositionTexCoordVertex)) *
- 6 * mRenderer->getRendererCaps().max3DTextureSize);
- vbDesc.Usage = D3D11_USAGE_DYNAMIC;
- vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
- vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
- vbDesc.MiscFlags = 0;
+ 6 * mRenderer->getNativeCaps().max3DTextureSize);
+ vbDesc.Usage = D3D11_USAGE_DYNAMIC;
+ vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ vbDesc.MiscFlags = 0;
vbDesc.StructureByteStride = 0;
- result = device->CreateBuffer(&vbDesc, nullptr, &mVertexBuffer);
- ASSERT(SUCCEEDED(result));
- if (FAILED(result))
- {
- freeResources();
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create blit vertex buffer, HRESULT: 0x%X",
- result);
- }
- d3d11::SetDebugName(mVertexBuffer, "Blit11 vertex buffer");
+ ANGLE_TRY(mRenderer->allocateResource(vbDesc, &mVertexBuffer));
+ mVertexBuffer.setDebugName("Blit11 vertex buffer");
D3D11_SAMPLER_DESC pointSamplerDesc;
- pointSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
- pointSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
- pointSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
- pointSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
- pointSamplerDesc.MipLODBias = 0.0f;
- pointSamplerDesc.MaxAnisotropy = 0;
+ pointSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
+ pointSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
+ pointSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
+ pointSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
+ pointSamplerDesc.MipLODBias = 0.0f;
+ pointSamplerDesc.MaxAnisotropy = 0;
pointSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
pointSamplerDesc.BorderColor[0] = 0.0f;
pointSamplerDesc.BorderColor[1] = 0.0f;
pointSamplerDesc.BorderColor[2] = 0.0f;
pointSamplerDesc.BorderColor[3] = 0.0f;
- pointSamplerDesc.MinLOD = 0.0f;
- pointSamplerDesc.MaxLOD = FLT_MAX;
+ pointSamplerDesc.MinLOD = 0.0f;
+ pointSamplerDesc.MaxLOD = FLT_MAX;
- result = device->CreateSamplerState(&pointSamplerDesc, &mPointSampler);
- ASSERT(SUCCEEDED(result));
- if (FAILED(result))
- {
- freeResources();
- return gl::Error(GL_OUT_OF_MEMORY,
- "Failed to create blit point sampler state, HRESULT: 0x%X", result);
- }
- d3d11::SetDebugName(mPointSampler, "Blit11 point sampler");
+ ANGLE_TRY(mRenderer->allocateResource(pointSamplerDesc, &mPointSampler));
+ mPointSampler.setDebugName("Blit11 point sampler");
D3D11_SAMPLER_DESC linearSamplerDesc;
- linearSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
- linearSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
- linearSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
- linearSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
- linearSamplerDesc.MipLODBias = 0.0f;
- linearSamplerDesc.MaxAnisotropy = 0;
+ linearSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
+ linearSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
+ linearSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
+ linearSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
+ linearSamplerDesc.MipLODBias = 0.0f;
+ linearSamplerDesc.MaxAnisotropy = 0;
linearSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
linearSamplerDesc.BorderColor[0] = 0.0f;
linearSamplerDesc.BorderColor[1] = 0.0f;
linearSamplerDesc.BorderColor[2] = 0.0f;
linearSamplerDesc.BorderColor[3] = 0.0f;
- linearSamplerDesc.MinLOD = 0.0f;
- linearSamplerDesc.MaxLOD = FLT_MAX;
+ linearSamplerDesc.MinLOD = 0.0f;
+ linearSamplerDesc.MaxLOD = FLT_MAX;
- result = device->CreateSamplerState(&linearSamplerDesc, &mLinearSampler);
- ASSERT(SUCCEEDED(result));
- if (FAILED(result))
- {
- freeResources();
- return gl::Error(GL_OUT_OF_MEMORY,
- "Failed to create blit linear sampler state, HRESULT: 0x%X", result);
- }
- d3d11::SetDebugName(mLinearSampler, "Blit11 linear sampler");
+ ANGLE_TRY(mRenderer->allocateResource(linearSamplerDesc, &mLinearSampler));
+ mLinearSampler.setDebugName("Blit11 linear sampler");
// Use a rasterizer state that will not cull so that inverted quads will not be culled
D3D11_RASTERIZER_DESC rasterDesc;
- rasterDesc.FillMode = D3D11_FILL_SOLID;
- rasterDesc.CullMode = D3D11_CULL_NONE;
+ rasterDesc.FillMode = D3D11_FILL_SOLID;
+ rasterDesc.CullMode = D3D11_CULL_NONE;
rasterDesc.FrontCounterClockwise = FALSE;
- rasterDesc.DepthBias = 0;
- rasterDesc.SlopeScaledDepthBias = 0.0f;
- rasterDesc.DepthBiasClamp = 0.0f;
- rasterDesc.DepthClipEnable = TRUE;
- rasterDesc.MultisampleEnable = FALSE;
+ rasterDesc.DepthBias = 0;
+ rasterDesc.SlopeScaledDepthBias = 0.0f;
+ rasterDesc.DepthBiasClamp = 0.0f;
+ rasterDesc.DepthClipEnable = TRUE;
+ rasterDesc.MultisampleEnable = FALSE;
rasterDesc.AntialiasedLineEnable = FALSE;
rasterDesc.ScissorEnable = TRUE;
- result = device->CreateRasterizerState(&rasterDesc, &mScissorEnabledRasterizerState);
- ASSERT(SUCCEEDED(result));
- if (FAILED(result))
- {
- freeResources();
- return gl::Error(GL_OUT_OF_MEMORY,
- "Failed to create blit scissoring rasterizer state, HRESULT: 0x%X",
- result);
- }
- d3d11::SetDebugName(mScissorEnabledRasterizerState, "Blit11 scissoring rasterizer state");
+ ANGLE_TRY(mRenderer->allocateResource(rasterDesc, &mScissorEnabledRasterizerState));
+ mScissorEnabledRasterizerState.setDebugName("Blit11 scissoring rasterizer state");
rasterDesc.ScissorEnable = FALSE;
- result = device->CreateRasterizerState(&rasterDesc, &mScissorDisabledRasterizerState);
- ASSERT(SUCCEEDED(result));
- if (FAILED(result))
- {
- freeResources();
- return gl::Error(GL_OUT_OF_MEMORY,
- "Failed to create blit no scissoring rasterizer state, HRESULT: 0x%X",
- result);
- }
- d3d11::SetDebugName(mScissorDisabledRasterizerState, "Blit11 no scissoring rasterizer state");
+ ANGLE_TRY(mRenderer->allocateResource(rasterDesc, &mScissorDisabledRasterizerState));
+ mScissorDisabledRasterizerState.setDebugName("Blit11 no scissoring rasterizer state");
D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
- depthStencilDesc.DepthEnable = true;
- depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
- depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS;
- depthStencilDesc.StencilEnable = FALSE;
- depthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
- depthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
- depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
+ depthStencilDesc.DepthEnable = TRUE;
+ depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
+ depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS;
+ depthStencilDesc.StencilEnable = FALSE;
+ depthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
+ depthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
+ depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
- depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
- depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
- depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
- depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
- depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
- depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
-
- result = device->CreateDepthStencilState(&depthStencilDesc, &mDepthStencilState);
- ASSERT(SUCCEEDED(result));
- if (FAILED(result))
- {
- freeResources();
- return gl::Error(GL_OUT_OF_MEMORY,
- "Failed to create blit depth stencil state, HRESULT: 0x%X", result);
- }
- d3d11::SetDebugName(mDepthStencilState, "Blit11 depth stencil state");
+ depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
+ depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
+ depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
+ depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
+ depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
+ depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
+
+ ANGLE_TRY(mRenderer->allocateResource(depthStencilDesc, &mDepthStencilState));
+ mDepthStencilState.setDebugName("Blit11 depth stencil state");
D3D11_BUFFER_DESC swizzleBufferDesc;
- swizzleBufferDesc.ByteWidth = sizeof(unsigned int) * 4;
- swizzleBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
- swizzleBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
- swizzleBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
- swizzleBufferDesc.MiscFlags = 0;
+ swizzleBufferDesc.ByteWidth = sizeof(unsigned int) * 4;
+ swizzleBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
+ swizzleBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ swizzleBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ swizzleBufferDesc.MiscFlags = 0;
swizzleBufferDesc.StructureByteStride = 0;
- result = device->CreateBuffer(&swizzleBufferDesc, nullptr, &mSwizzleCB);
- ASSERT(SUCCEEDED(result));
- if (FAILED(result))
- {
- freeResources();
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create blit swizzle buffer, HRESULT: 0x%X",
- result);
- }
- d3d11::SetDebugName(mSwizzleCB, "Blit11 swizzle constant buffer");
+ ANGLE_TRY(mRenderer->allocateResource(swizzleBufferDesc, &mSwizzleCB));
+ mSwizzleCB.setDebugName("Blit11 swizzle constant buffer");
mResourcesInitialized = true;
- return gl::Error(GL_NO_ERROR);
-}
-
-void Blit11::freeResources()
-{
- SafeRelease(mVertexBuffer);
- SafeRelease(mPointSampler);
- SafeRelease(mLinearSampler);
- SafeRelease(mScissorEnabledRasterizerState);
- SafeRelease(mScissorDisabledRasterizerState);
- SafeRelease(mDepthStencilState);
- SafeRelease(mSwizzleCB);
-
- mResourcesInitialized = false;
+ return gl::NoError();
}
// static
-Blit11::BlitShaderType Blit11::GetBlitShaderType(GLenum destinationFormat, bool isSigned, ShaderDimension dimension)
+Blit11::BlitShaderType Blit11::GetBlitShaderType(GLenum destinationFormat,
+ GLenum sourceFormat,
+ bool isSigned,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ ShaderDimension dimension)
{
if (dimension == SHADER_3D)
{
+ ASSERT(!unpackPremultiplyAlpha && !unpackUnmultiplyAlpha);
+
if (isSigned)
{
switch (destinationFormat)
{
- case GL_RGBA_INTEGER: return BLITSHADER_3D_RGBAI;
- case GL_RGB_INTEGER: return BLITSHADER_3D_RGBI;
- case GL_RG_INTEGER: return BLITSHADER_3D_RGI;
- case GL_RED_INTEGER: return BLITSHADER_3D_RI;
- default:
- UNREACHABLE();
- return BLITSHADER_INVALID;
+ case GL_RGBA_INTEGER:
+ return BLITSHADER_3D_RGBAI;
+ case GL_RGB_INTEGER:
+ return BLITSHADER_3D_RGBI;
+ case GL_RG_INTEGER:
+ return BLITSHADER_3D_RGI;
+ case GL_RED_INTEGER:
+ return BLITSHADER_3D_RI;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
}
}
else
{
switch (destinationFormat)
{
- case GL_RGBA: return BLITSHADER_3D_RGBAF;
- case GL_RGBA_INTEGER: return BLITSHADER_3D_RGBAUI;
- case GL_BGRA_EXT: return BLITSHADER_3D_BGRAF;
- case GL_RGB: return BLITSHADER_3D_RGBF;
- case GL_RGB_INTEGER: return BLITSHADER_3D_RGBUI;
- case GL_RG: return BLITSHADER_3D_RGF;
- case GL_RG_INTEGER: return BLITSHADER_3D_RGUI;
- case GL_RED: return BLITSHADER_3D_RF;
- case GL_RED_INTEGER: return BLITSHADER_3D_RUI;
- case GL_ALPHA: return BLITSHADER_3D_ALPHA;
- case GL_LUMINANCE: return BLITSHADER_3D_LUMA;
- case GL_LUMINANCE_ALPHA: return BLITSHADER_3D_LUMAALPHA;
- default:
- UNREACHABLE();
- return BLITSHADER_INVALID;
+ case GL_RGBA:
+ return BLITSHADER_3D_RGBAF;
+ case GL_RGBA_INTEGER:
+ return BLITSHADER_3D_RGBAUI;
+ case GL_BGRA_EXT:
+ return BLITSHADER_3D_BGRAF;
+ case GL_RGB:
+ return BLITSHADER_3D_RGBF;
+ case GL_RGB_INTEGER:
+ return BLITSHADER_3D_RGBUI;
+ case GL_RG:
+ return BLITSHADER_3D_RGF;
+ case GL_RG_INTEGER:
+ return BLITSHADER_3D_RGUI;
+ case GL_RED:
+ return BLITSHADER_3D_RF;
+ case GL_RED_INTEGER:
+ return BLITSHADER_3D_RUI;
+ case GL_ALPHA:
+ return BLITSHADER_3D_ALPHA;
+ case GL_LUMINANCE:
+ return BLITSHADER_3D_LUMA;
+ case GL_LUMINANCE_ALPHA:
+ return BLITSHADER_3D_LUMAALPHA;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
}
}
}
else if (isSigned)
{
+ ASSERT(!unpackPremultiplyAlpha && !unpackUnmultiplyAlpha);
+
switch (destinationFormat)
{
- case GL_RGBA_INTEGER: return BLITSHADER_2D_RGBAI;
- case GL_RGB_INTEGER: return BLITSHADER_2D_RGBI;
- case GL_RG_INTEGER: return BLITSHADER_2D_RGI;
- case GL_RED_INTEGER: return BLITSHADER_2D_RI;
- default:
- UNREACHABLE();
- return BLITSHADER_INVALID;
+ case GL_RGBA_INTEGER:
+ return BLITSHADER_2D_RGBAI;
+ case GL_RGB_INTEGER:
+ return BLITSHADER_2D_RGBI;
+ case GL_RG_INTEGER:
+ return BLITSHADER_2D_RGI;
+ case GL_RED_INTEGER:
+ return BLITSHADER_2D_RI;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
}
}
else
{
- switch (destinationFormat)
+ bool floatToIntBlit =
+ !gl::IsIntegerFormat(sourceFormat) && gl::IsIntegerFormat(destinationFormat);
+ if (unpackPremultiplyAlpha != unpackUnmultiplyAlpha || floatToIntBlit)
{
- case GL_RGBA: return BLITSHADER_2D_RGBAF;
- case GL_RGBA_INTEGER: return BLITSHADER_2D_RGBAUI;
- case GL_BGRA_EXT: return BLITSHADER_2D_BGRAF;
- case GL_RGB: return BLITSHADER_2D_RGBF;
- case GL_RGB_INTEGER: return BLITSHADER_2D_RGBUI;
- case GL_RG: return BLITSHADER_2D_RGF;
- case GL_RG_INTEGER: return BLITSHADER_2D_RGUI;
- case GL_RED: return BLITSHADER_2D_RF;
- case GL_RED_INTEGER: return BLITSHADER_2D_RUI;
- case GL_ALPHA: return BLITSHADER_2D_ALPHA;
- case GL_LUMINANCE: return BLITSHADER_2D_LUMA;
- case GL_LUMINANCE_ALPHA: return BLITSHADER_2D_LUMAALPHA;
- default:
- UNREACHABLE();
- return BLITSHADER_INVALID;
+ switch (destinationFormat)
+ {
+ case GL_RGBA:
+ case GL_BGRA_EXT:
+ ASSERT(!floatToIntBlit);
+ return unpackPremultiplyAlpha ? BLITSHADER_2D_RGBAF_PREMULTIPLY
+ : BLITSHADER_2D_RGBAF_UNMULTIPLY;
+
+ case GL_RGB:
+ case GL_RG:
+ case GL_RED:
+ ASSERT(!floatToIntBlit);
+ return unpackPremultiplyAlpha ? BLITSHADER_2D_RGBF_PREMULTIPLY
+ : BLITSHADER_2D_RGBF_UNMULTIPLY;
+
+ case GL_RGBA_INTEGER:
+ if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
+ {
+ return BLITSHADER_2D_RGBAF_TOUI;
+ }
+ else
+ {
+ return unpackPremultiplyAlpha ? BLITSHADER_2D_RGBAF_TOUI_PREMULTIPLY
+ : BLITSHADER_2D_RGBAF_TOUI_UNMULTIPLY;
+ }
+
+ case GL_RGB_INTEGER:
+ case GL_RG_INTEGER:
+ case GL_RED_INTEGER:
+ if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
+ {
+ return BLITSHADER_2D_RGBF_TOUI;
+ }
+ else
+ {
+ return unpackPremultiplyAlpha ? BLITSHADER_2D_RGBF_TOUI_PREMULTIPLY
+ : BLITSHADER_2D_RGBF_TOUI_UNMULTIPLY;
+ }
+ case GL_LUMINANCE:
+ ASSERT(!floatToIntBlit);
+ return unpackPremultiplyAlpha ? BLITSHADER_2D_LUMAF_PREMULTIPLY
+ : BLITSHADER_2D_LUMAF_UNMULTIPLY;
+ case GL_LUMINANCE_ALPHA:
+ ASSERT(!floatToIntBlit);
+ return unpackPremultiplyAlpha ? BLITSHADER_2D_LUMAALPHAF_PREMULTIPLY
+ : BLITSHADER_2D_LUMAALPHAF_UNMULTIPLY;
+ case GL_ALPHA:
+ ASSERT(!floatToIntBlit);
+ return BLITSHADER_2D_ALPHA;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ }
+ else
+ {
+ switch (destinationFormat)
+ {
+ case GL_RGBA:
+ return BLITSHADER_2D_RGBAF;
+ case GL_RGBA_INTEGER:
+ return BLITSHADER_2D_RGBAUI;
+ case GL_BGRA_EXT:
+ return BLITSHADER_2D_BGRAF;
+ case GL_RGB:
+ return BLITSHADER_2D_RGBF;
+ case GL_RGB_INTEGER:
+ return BLITSHADER_2D_RGBUI;
+ case GL_RG:
+ return BLITSHADER_2D_RGF;
+ case GL_RG_INTEGER:
+ return BLITSHADER_2D_RGUI;
+ case GL_RED:
+ return BLITSHADER_2D_RF;
+ case GL_RED_INTEGER:
+ return BLITSHADER_2D_RUI;
+ case GL_ALPHA:
+ return BLITSHADER_2D_ALPHA;
+ case GL_LUMINANCE:
+ return BLITSHADER_2D_LUMA;
+ case GL_LUMINANCE_ALPHA:
+ return BLITSHADER_2D_LUMAALPHA;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
}
}
}
// static
-Blit11::SwizzleShaderType Blit11::GetSwizzleShaderType(GLenum type, D3D11_SRV_DIMENSION dimensionality)
+Blit11::SwizzleShaderType Blit11::GetSwizzleShaderType(GLenum type,
+ D3D11_SRV_DIMENSION dimensionality)
{
switch (dimensionality)
{
- case D3D11_SRV_DIMENSION_TEXTURE2D:
- switch (type)
- {
- case GL_FLOAT: return SWIZZLESHADER_2D_FLOAT;
- case GL_UNSIGNED_INT: return SWIZZLESHADER_2D_UINT;
- case GL_INT: return SWIZZLESHADER_2D_INT;
- default:
- UNREACHABLE();
- return SWIZZLESHADER_INVALID;
- }
- case D3D11_SRV_DIMENSION_TEXTURECUBE:
- switch (type)
- {
- case GL_FLOAT: return SWIZZLESHADER_CUBE_FLOAT;
- case GL_UNSIGNED_INT: return SWIZZLESHADER_CUBE_UINT;
- case GL_INT: return SWIZZLESHADER_CUBE_INT;
- default:
- UNREACHABLE();
- return SWIZZLESHADER_INVALID;
- }
- case D3D11_SRV_DIMENSION_TEXTURE3D:
- switch (type)
- {
- case GL_FLOAT: return SWIZZLESHADER_3D_FLOAT;
- case GL_UNSIGNED_INT: return SWIZZLESHADER_3D_UINT;
- case GL_INT: return SWIZZLESHADER_3D_INT;
- default:
- UNREACHABLE();
- return SWIZZLESHADER_INVALID;
- }
- case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
- switch (type)
- {
- case GL_FLOAT: return SWIZZLESHADER_ARRAY_FLOAT;
- case GL_UNSIGNED_INT: return SWIZZLESHADER_ARRAY_UINT;
- case GL_INT: return SWIZZLESHADER_ARRAY_INT;
- default:
+ case D3D11_SRV_DIMENSION_TEXTURE2D:
+ switch (type)
+ {
+ case GL_FLOAT:
+ return SWIZZLESHADER_2D_FLOAT;
+ case GL_UNSIGNED_INT:
+ return SWIZZLESHADER_2D_UINT;
+ case GL_INT:
+ return SWIZZLESHADER_2D_INT;
+ default:
+ UNREACHABLE();
+ return SWIZZLESHADER_INVALID;
+ }
+ case D3D11_SRV_DIMENSION_TEXTURECUBE:
+ switch (type)
+ {
+ case GL_FLOAT:
+ return SWIZZLESHADER_CUBE_FLOAT;
+ case GL_UNSIGNED_INT:
+ return SWIZZLESHADER_CUBE_UINT;
+ case GL_INT:
+ return SWIZZLESHADER_CUBE_INT;
+ default:
+ UNREACHABLE();
+ return SWIZZLESHADER_INVALID;
+ }
+ case D3D11_SRV_DIMENSION_TEXTURE3D:
+ switch (type)
+ {
+ case GL_FLOAT:
+ return SWIZZLESHADER_3D_FLOAT;
+ case GL_UNSIGNED_INT:
+ return SWIZZLESHADER_3D_UINT;
+ case GL_INT:
+ return SWIZZLESHADER_3D_INT;
+ default:
+ UNREACHABLE();
+ return SWIZZLESHADER_INVALID;
+ }
+ case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
+ switch (type)
+ {
+ case GL_FLOAT:
+ return SWIZZLESHADER_ARRAY_FLOAT;
+ case GL_UNSIGNED_INT:
+ return SWIZZLESHADER_ARRAY_UINT;
+ case GL_INT:
+ return SWIZZLESHADER_ARRAY_INT;
+ default:
+ UNREACHABLE();
+ return SWIZZLESHADER_INVALID;
+ }
+ default:
UNREACHABLE();
return SWIZZLESHADER_INVALID;
- }
- default:
- UNREACHABLE();
- return SWIZZLESHADER_INVALID;
}
}
-Blit11::ShaderSupport Blit11::getShaderSupport(const Shader &shader)
+gl::Error Blit11::getShaderSupport(const Shader &shader, Blit11::ShaderSupport *supportOut)
{
- ID3D11Device *device = mRenderer->getDevice();
- ShaderSupport support;
-
if (shader.dimension == SHADER_2D)
{
- support.inputLayout = mQuad2DIL.resolve(device);
- support.vertexShader = mQuad2DVS.resolve(device);
- support.geometryShader = nullptr;
- support.vertexWriteFunction = Write2DVertices;
+ ANGLE_TRY(mQuad2DIL.resolve(mRenderer));
+ ANGLE_TRY(mQuad2DVS.resolve(mRenderer));
+ supportOut->inputLayout = &mQuad2DIL.getObj();
+ supportOut->vertexShader = &mQuad2DVS.getObj();
+ supportOut->geometryShader = nullptr;
+ supportOut->vertexWriteFunction = Write2DVertices;
}
else
{
ASSERT(shader.dimension == SHADER_3D);
- support.inputLayout = mQuad3DIL.resolve(device);
- support.vertexShader = mQuad3DVS.resolve(device);
- support.geometryShader = mQuad3DGS.resolve(device);
- support.vertexWriteFunction = Write3DVertices;
+ ANGLE_TRY(mQuad3DIL.resolve(mRenderer));
+ ANGLE_TRY(mQuad3DVS.resolve(mRenderer));
+ ANGLE_TRY(mQuad3DGS.resolve(mRenderer));
+ supportOut->inputLayout = &mQuad2DIL.getObj();
+ supportOut->vertexShader = &mQuad3DVS.getObj();
+ supportOut->geometryShader = &mQuad3DGS.getObj();
+ supportOut->vertexWriteFunction = Write3DVertices;
}
- return support;
+ return gl::NoError();
}
-gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source,
- ID3D11RenderTargetView *dest,
+gl::Error Blit11::swizzleTexture(const gl::Context *context,
+ const d3d11::SharedSRV &source,
+ const d3d11::RenderTargetView &dest,
const gl::Extents &size,
- GLenum swizzleRed,
- GLenum swizzleGreen,
- GLenum swizzleBlue,
- GLenum swizzleAlpha)
+ const gl::SwizzleState &swizzleTarget)
{
- gl::Error error = initResources();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(initResources());
HRESULT result;
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
- source->GetDesc(&sourceSRVDesc);
+ source.get()->GetDesc(&sourceSRVDesc);
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(sourceSRVDesc.Format);
- const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat);
+ GLenum componentType = d3d11::GetComponentType(sourceSRVDesc.Format);
+ if (componentType == GL_NONE)
+ {
+ // We're swizzling the depth component of a depth-stencil texture.
+ switch (sourceSRVDesc.Format)
+ {
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ componentType = GL_UNSIGNED_NORMALIZED;
+ break;
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ componentType = GL_FLOAT;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
GLenum shaderType = GL_NONE;
- switch (sourceFormatInfo.componentType)
+ switch (componentType)
{
- case GL_UNSIGNED_NORMALIZED:
- case GL_SIGNED_NORMALIZED:
- case GL_FLOAT:
- shaderType = GL_FLOAT;
- break;
- case GL_INT:
- shaderType = GL_INT;
- break;
- case GL_UNSIGNED_INT:
- shaderType = GL_UNSIGNED_INT;
- break;
- default:
- UNREACHABLE();
- break;
+ case GL_UNSIGNED_NORMALIZED:
+ case GL_SIGNED_NORMALIZED:
+ case GL_FLOAT:
+ shaderType = GL_FLOAT;
+ break;
+ case GL_INT:
+ shaderType = GL_INT;
+ break;
+ case GL_UNSIGNED_INT:
+ shaderType = GL_UNSIGNED_INT;
+ break;
+ default:
+ UNREACHABLE();
+ break;
}
const Shader *shader = nullptr;
- error = getSwizzleShader(shaderType, sourceSRVDesc.ViewDimension, &shader);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(getSwizzleShader(shaderType, sourceSRVDesc.ViewDimension, &shader));
// Set vertices
D3D11_MAPPED_SUBRESOURCE mappedResource;
- result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ result =
+ deviceContext->Map(mVertexBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer for swizzle, HRESULT: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to map internal vertex buffer for swizzle, "
+ << gl::FmtHR(result);
}
- const ShaderSupport &support = getShaderSupport(*shader);
+ ShaderSupport support;
+ ANGLE_TRY(getShaderSupport(*shader, &support));
- UINT stride = 0;
- UINT startIdx = 0;
+ UINT stride = 0;
UINT drawCount = 0;
D3D11_PRIMITIVE_TOPOLOGY topology;
gl::Box area(0, 0, 0, size.width, size.height, size.depth);
- support.vertexWriteFunction(area, size, area, size, mappedResource.pData, &stride, &drawCount, &topology);
+ support.vertexWriteFunction(area, size, area, size, mappedResource.pData, &stride, &drawCount,
+ &topology);
- deviceContext->Unmap(mVertexBuffer, 0);
+ deviceContext->Unmap(mVertexBuffer.get(), 0);
// Set constant buffer
- result = deviceContext->Map(mSwizzleCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ result = deviceContext->Map(mSwizzleCB.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal constant buffer for swizzle, HRESULT: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to map internal constant buffer for swizzle, "
+ << gl::FmtHR(result);
}
- unsigned int *swizzleIndices = reinterpret_cast<unsigned int*>(mappedResource.pData);
- swizzleIndices[0] = GetSwizzleIndex(swizzleRed);
- swizzleIndices[1] = GetSwizzleIndex(swizzleGreen);
- swizzleIndices[2] = GetSwizzleIndex(swizzleBlue);
- swizzleIndices[3] = GetSwizzleIndex(swizzleAlpha);
+ unsigned int *swizzleIndices = reinterpret_cast<unsigned int *>(mappedResource.pData);
+ swizzleIndices[0] = GetSwizzleIndex(swizzleTarget.swizzleRed);
+ swizzleIndices[1] = GetSwizzleIndex(swizzleTarget.swizzleGreen);
+ swizzleIndices[2] = GetSwizzleIndex(swizzleTarget.swizzleBlue);
+ swizzleIndices[3] = GetSwizzleIndex(swizzleTarget.swizzleAlpha);
- deviceContext->Unmap(mSwizzleCB, 0);
+ deviceContext->Unmap(mSwizzleCB.get(), 0);
+
+ StateManager11 *stateManager = mRenderer->getStateManager();
// Apply vertex buffer
- deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx);
+ stateManager->setSingleVertexBuffer(&mVertexBuffer, stride, 0);
// Apply constant buffer
- deviceContext->PSSetConstantBuffers(0, 1, &mSwizzleCB);
+ stateManager->setPixelConstantBuffer(0, &mSwizzleCB);
// Apply state
- deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
- deviceContext->OMSetDepthStencilState(nullptr, 0xFFFFFFFF);
- deviceContext->RSSetState(mScissorDisabledRasterizerState);
+ stateManager->setSimpleBlendState(nullptr);
+ stateManager->setDepthStencilState(nullptr, 0xFFFFFFFF);
+ stateManager->setRasterizerState(&mScissorDisabledRasterizerState);
// Apply shaders
- deviceContext->IASetInputLayout(support.inputLayout);
- deviceContext->IASetPrimitiveTopology(topology);
- deviceContext->VSSetShader(support.vertexShader, nullptr, 0);
-
- deviceContext->PSSetShader(shader->pixelShader, nullptr, 0);
- deviceContext->GSSetShader(support.geometryShader, nullptr, 0);
+ stateManager->setInputLayout(support.inputLayout);
+ stateManager->setPrimitiveTopology(topology);
- // Unset the currently bound shader resource to avoid conflicts
- auto stateManager = mRenderer->getStateManager();
- stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
+ stateManager->setDrawShaders(support.vertexShader, support.geometryShader,
+ &shader->pixelShader);
// Apply render target
- mRenderer->setOneTimeRenderTarget(dest);
+ stateManager->setRenderTarget(dest.get(), nullptr);
// Set the viewport
- D3D11_VIEWPORT viewport;
- viewport.TopLeftX = 0;
- viewport.TopLeftY = 0;
- viewport.Width = static_cast<FLOAT>(size.width);
- viewport.Height = static_cast<FLOAT>(size.height);
- viewport.MinDepth = 0.0f;
- viewport.MaxDepth = 1.0f;
- deviceContext->RSSetViewports(1, &viewport);
-
- // Apply textures
- stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, source);
+ stateManager->setSimpleViewport(size);
- // Apply samplers
- deviceContext->PSSetSamplers(0, 1, &mPointSampler);
+ // Apply textures and sampler
+ stateManager->setSimplePixelTextureAndSampler(source, mPointSampler);
// Draw the quad
deviceContext->Draw(drawCount, 0);
- // Unbind textures and render targets and vertex buffer
- stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
-
- mRenderer->unapplyRenderTargets();
-
- UINT zero = 0;
- ID3D11Buffer *const nullBuffer = nullptr;
- deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
-
- mRenderer->markAllStateDirty();
-
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source,
+gl::Error Blit11::copyTexture(const gl::Context *context,
+ const d3d11::SharedSRV &source,
const gl::Box &sourceArea,
const gl::Extents &sourceSize,
- ID3D11RenderTargetView *dest,
+ GLenum sourceFormat,
+ const d3d11::RenderTargetView &dest,
const gl::Box &destArea,
const gl::Extents &destSize,
const gl::Rectangle *scissor,
GLenum destFormat,
GLenum filter,
- bool maskOffAlpha)
+ bool maskOffAlpha,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha)
{
- gl::Error error = initResources();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(initResources());
HRESULT result;
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
@@ -771,635 +1145,1009 @@ gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source,
// Determine if the source format is a signed integer format, the destFormat will already
// be GL_XXXX_INTEGER but it does not tell us if it is signed or unsigned.
D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
- source->GetDesc(&sourceSRVDesc);
+ source.get()->GetDesc(&sourceSRVDesc);
+
+ GLenum componentType = d3d11::GetComponentType(sourceSRVDesc.Format);
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(sourceSRVDesc.Format);
- const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat);
+ ASSERT(componentType != GL_NONE);
+ ASSERT(componentType != GL_SIGNED_NORMALIZED);
+ bool isSigned = (componentType == GL_INT);
- bool isSigned = (internalFormatInfo.componentType == GL_INT);
- ShaderDimension dimension = (sourceSRVDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE3D) ? SHADER_3D : SHADER_2D;
+ ShaderDimension dimension =
+ (sourceSRVDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE3D) ? SHADER_3D : SHADER_2D;
const Shader *shader = nullptr;
- error = getBlitShader(destFormat, isSigned, dimension, &shader);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(getBlitShader(destFormat, sourceFormat, isSigned, unpackPremultiplyAlpha,
+ unpackUnmultiplyAlpha, dimension, &shader));
- const ShaderSupport &support = getShaderSupport(*shader);
+ ShaderSupport support;
+ ANGLE_TRY(getShaderSupport(*shader, &support));
// Set vertices
D3D11_MAPPED_SUBRESOURCE mappedResource;
- result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ result =
+ deviceContext->Map(mVertexBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer for texture copy, HRESULT: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to map internal vertex buffer for texture copy, "
+ << gl::FmtHR(result);
}
- UINT stride = 0;
- UINT startIdx = 0;
+ UINT stride = 0;
UINT drawCount = 0;
D3D11_PRIMITIVE_TOPOLOGY topology;
support.vertexWriteFunction(sourceArea, sourceSize, destArea, destSize, mappedResource.pData,
&stride, &drawCount, &topology);
- deviceContext->Unmap(mVertexBuffer, 0);
+ deviceContext->Unmap(mVertexBuffer.get(), 0);
+
+ StateManager11 *stateManager = mRenderer->getStateManager();
// Apply vertex buffer
- deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx);
+ stateManager->setSingleVertexBuffer(&mVertexBuffer, stride, 0);
// Apply state
if (maskOffAlpha)
{
- ID3D11BlendState *blendState = mAlphaMaskBlendState.resolve(mRenderer->getDevice());
- ASSERT(blendState);
- deviceContext->OMSetBlendState(blendState, nullptr, 0xFFFFFFF);
+ ANGLE_TRY(mAlphaMaskBlendState.resolve(mRenderer));
+ stateManager->setSimpleBlendState(&mAlphaMaskBlendState.getObj());
}
else
{
- deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
+ stateManager->setSimpleBlendState(nullptr);
}
- deviceContext->OMSetDepthStencilState(nullptr, 0xFFFFFFFF);
+ stateManager->setDepthStencilState(nullptr, 0xFFFFFFFF);
if (scissor)
{
- D3D11_RECT scissorRect;
- scissorRect.left = scissor->x;
- scissorRect.right = scissor->x + scissor->width;
- scissorRect.top = scissor->y;
- scissorRect.bottom = scissor->y + scissor->height;
-
- deviceContext->RSSetScissorRects(1, &scissorRect);
- deviceContext->RSSetState(mScissorEnabledRasterizerState);
+ stateManager->setSimpleScissorRect(*scissor);
+ stateManager->setRasterizerState(&mScissorEnabledRasterizerState);
}
else
{
- deviceContext->RSSetState(mScissorDisabledRasterizerState);
+ stateManager->setRasterizerState(&mScissorDisabledRasterizerState);
}
// Apply shaders
- deviceContext->IASetInputLayout(support.inputLayout);
- deviceContext->IASetPrimitiveTopology(topology);
- deviceContext->VSSetShader(support.vertexShader, nullptr, 0);
-
- deviceContext->PSSetShader(shader->pixelShader, nullptr, 0);
- deviceContext->GSSetShader(support.geometryShader, nullptr, 0);
+ stateManager->setInputLayout(support.inputLayout);
+ stateManager->setPrimitiveTopology(topology);
- // Unset the currently bound shader resource to avoid conflicts
- auto stateManager = mRenderer->getStateManager();
- stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
+ stateManager->setDrawShaders(support.vertexShader, support.geometryShader,
+ &shader->pixelShader);
// Apply render target
- mRenderer->setOneTimeRenderTarget(dest);
+ stateManager->setRenderTarget(dest.get(), nullptr);
// Set the viewport
- D3D11_VIEWPORT viewport;
- viewport.TopLeftX = 0;
- viewport.TopLeftY = 0;
- viewport.Width = static_cast<FLOAT>(destSize.width);
- viewport.Height = static_cast<FLOAT>(destSize.height);
- viewport.MinDepth = 0.0f;
- viewport.MaxDepth = 1.0f;
- deviceContext->RSSetViewports(1, &viewport);
-
- // Apply textures
- stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, source);
-
- // Apply samplers
- ID3D11SamplerState *sampler = nullptr;
+ stateManager->setSimpleViewport(destSize);
+
+ // Apply texture and sampler
switch (filter)
{
- case GL_NEAREST: sampler = mPointSampler; break;
- case GL_LINEAR: sampler = mLinearSampler; break;
-
- default:
- UNREACHABLE();
- return gl::Error(GL_OUT_OF_MEMORY, "Internal error, unknown blit filter mode.");
+ case GL_NEAREST:
+ stateManager->setSimplePixelTextureAndSampler(source, mPointSampler);
+ break;
+ case GL_LINEAR:
+ stateManager->setSimplePixelTextureAndSampler(source, mLinearSampler);
+ break;
+
+ default:
+ UNREACHABLE();
+ return gl::InternalError() << "Internal error, unknown blit filter mode.";
}
- deviceContext->PSSetSamplers(0, 1, &sampler);
// Draw the quad
deviceContext->Draw(drawCount, 0);
- // Unbind textures and render targets and vertex buffer
- stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
-
- mRenderer->unapplyRenderTargets();
-
- UINT zero = 0;
- ID3D11Buffer *const nullBuffer = nullptr;
- deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
-
- mRenderer->markAllStateDirty();
-
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Blit11::copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
- ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
+gl::Error Blit11::copyStencil(const gl::Context *context,
+ const TextureHelper11 &source,
+ unsigned int sourceSubresource,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const TextureHelper11 &dest,
+ unsigned int destSubresource,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
const gl::Rectangle *scissor)
{
- return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize,
- dest, destSubresource, destArea, destSize,
- scissor, true);
+ return copyDepthStencilImpl(source, sourceSubresource, sourceArea, sourceSize, dest,
+ destSubresource, destArea, destSize, scissor, true);
}
-gl::Error Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize,
- ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize,
+gl::Error Blit11::copyDepth(const gl::Context *context,
+ const d3d11::SharedSRV &source,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const d3d11::DepthStencilView &dest,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
const gl::Rectangle *scissor)
{
- gl::Error error = initResources();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(initResources());
HRESULT result;
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
// Set vertices
D3D11_MAPPED_SUBRESOURCE mappedResource;
- result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ result =
+ deviceContext->Map(mVertexBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer for texture copy, HRESULT: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to map internal vertex buffer for texture copy, "
+ << gl::FmtHR(result);
}
- UINT stride = 0;
- UINT startIdx = 0;
+ UINT stride = 0;
UINT drawCount = 0;
D3D11_PRIMITIVE_TOPOLOGY topology;
- Write2DVertices(sourceArea, sourceSize, destArea, destSize, mappedResource.pData,
- &stride, &drawCount, &topology);
+ Write2DVertices(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, &stride,
+ &drawCount, &topology);
- deviceContext->Unmap(mVertexBuffer, 0);
+ deviceContext->Unmap(mVertexBuffer.get(), 0);
+
+ StateManager11 *stateManager = mRenderer->getStateManager();
// Apply vertex buffer
- deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx);
+ stateManager->setSingleVertexBuffer(&mVertexBuffer, stride, 0);
// Apply state
- deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
- deviceContext->OMSetDepthStencilState(mDepthStencilState, 0xFFFFFFFF);
+ stateManager->setSimpleBlendState(nullptr);
+ stateManager->setDepthStencilState(&mDepthStencilState, 0xFFFFFFFF);
if (scissor)
{
- D3D11_RECT scissorRect;
- scissorRect.left = scissor->x;
- scissorRect.right = scissor->x + scissor->width;
- scissorRect.top = scissor->y;
- scissorRect.bottom = scissor->y + scissor->height;
-
- deviceContext->RSSetScissorRects(1, &scissorRect);
- deviceContext->RSSetState(mScissorEnabledRasterizerState);
+ stateManager->setSimpleScissorRect(*scissor);
+ stateManager->setRasterizerState(&mScissorEnabledRasterizerState);
}
else
{
- deviceContext->RSSetState(mScissorDisabledRasterizerState);
+ stateManager->setRasterizerState(&mScissorDisabledRasterizerState);
}
- ID3D11Device *device = mRenderer->getDevice();
- ID3D11VertexShader *quad2DVS = mQuad2DVS.resolve(device);
- if (quad2DVS == nullptr)
- {
- return gl::Error(GL_INVALID_OPERATION, "Error compiling internal 2D blit vertex shader");
- }
+ ANGLE_TRY(mQuad2DIL.resolve(mRenderer));
+ ANGLE_TRY(mQuad2DVS.resolve(mRenderer));
+ ANGLE_TRY(mDepthPS.resolve(mRenderer));
// Apply shaders
- deviceContext->IASetInputLayout(mQuad2DIL.resolve(device));
- deviceContext->IASetPrimitiveTopology(topology);
- deviceContext->VSSetShader(quad2DVS, nullptr, 0);
+ stateManager->setInputLayout(&mQuad2DIL.getObj());
+ stateManager->setPrimitiveTopology(topology);
- deviceContext->PSSetShader(mDepthPS.resolve(device), nullptr, 0);
- deviceContext->GSSetShader(nullptr, nullptr, 0);
-
- // Unset the currently bound shader resource to avoid conflicts
- auto stateManager = mRenderer->getStateManager();
- stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
+ stateManager->setDrawShaders(&mQuad2DVS.getObj(), nullptr, &mDepthPS.getObj());
// Apply render target
- deviceContext->OMSetRenderTargets(0, nullptr, dest);
+ stateManager->setRenderTarget(nullptr, dest.get());
// Set the viewport
- D3D11_VIEWPORT viewport;
- viewport.TopLeftX = 0;
- viewport.TopLeftY = 0;
- viewport.Width = static_cast<FLOAT>(destSize.width);
- viewport.Height = static_cast<FLOAT>(destSize.height);
- viewport.MinDepth = 0.0f;
- viewport.MaxDepth = 1.0f;
- deviceContext->RSSetViewports(1, &viewport);
-
- // Apply textures
- stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, source);
+ stateManager->setSimpleViewport(destSize);
- // Apply samplers
- deviceContext->PSSetSamplers(0, 1, &mPointSampler);
+ // Apply texture and sampler
+ stateManager->setSimplePixelTextureAndSampler(source, mPointSampler);
// Draw the quad
deviceContext->Draw(drawCount, 0);
- // Unbind textures and render targets and vertex buffer
- stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
-
- mRenderer->unapplyRenderTargets();
-
- UINT zero = 0;
- ID3D11Buffer *const nullBuffer = nullptr;
- deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
-
- mRenderer->markAllStateDirty();
-
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
- ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
+gl::Error Blit11::copyDepthStencil(const TextureHelper11 &source,
+ unsigned int sourceSubresource,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const TextureHelper11 &dest,
+ unsigned int destSubresource,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
const gl::Rectangle *scissor)
{
- return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize,
- dest, destSubresource, destArea, destSize,
- scissor, false);
+ return copyDepthStencilImpl(source, sourceSubresource, sourceArea, sourceSize, dest,
+ destSubresource, destArea, destSize, scissor, false);
}
-gl::Error Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
- ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
- const gl::Rectangle *scissor, bool stencilOnly)
+gl::Error Blit11::copyDepthStencilImpl(const TextureHelper11 &source,
+ unsigned int sourceSubresource,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const TextureHelper11 &dest,
+ unsigned int destSubresource,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor,
+ bool stencilOnly)
{
- gl::Error error = initResources();
- if (error.isError())
- {
- return error;
- }
+ auto srcDXGIFormat = source.getFormat();
+ const auto &srcSizeInfo = d3d11::GetDXGIFormatSizeInfo(srcDXGIFormat);
+ unsigned int srcPixelSize = srcSizeInfo.pixelBytes;
+ unsigned int copyOffset = 0;
+ unsigned int copySize = srcPixelSize;
+ auto destDXGIFormat = dest.getFormat();
+ const auto &destSizeInfo = d3d11::GetDXGIFormatSizeInfo(destDXGIFormat);
+ unsigned int destPixelSize = destSizeInfo.pixelBytes;
- ID3D11Device *device = mRenderer->getDevice();
- ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ ASSERT(srcDXGIFormat == destDXGIFormat || destDXGIFormat == DXGI_FORMAT_R32_TYPELESS);
- ID3D11Resource *sourceStaging = CreateStagingTexture(device, deviceContext, source, sourceSubresource, sourceSize, D3D11_CPU_ACCESS_READ);
- // HACK: Create the destination staging buffer as a read/write texture so ID3D11DevicContext::UpdateSubresource can be called
- // using it's mapped data as a source
- ID3D11Resource *destStaging = CreateStagingTexture(device, deviceContext, dest, destSubresource, destSize, D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE);
+ if (stencilOnly)
+ {
+ const auto &srcFormat = source.getFormatSet().format();
+
+ // Stencil channel should be right after the depth channel. Some views to depth/stencil
+ // resources have red channel for depth, in which case the depth channel bit width is in
+ // redBits.
+ ASSERT((srcFormat.redBits != 0) != (srcFormat.depthBits != 0));
+ GLuint depthBits = srcFormat.redBits + srcFormat.depthBits;
+ // Known formats have either 24 or 32 bits of depth.
+ ASSERT(depthBits == 24 || depthBits == 32);
+ copyOffset = depthBits / 8;
+
+ // Stencil is assumed to be 8-bit - currently this is true for all possible formats.
+ copySize = 1;
+ }
- if (!sourceStaging || !destStaging)
+ if (srcDXGIFormat != destDXGIFormat)
{
- SafeRelease(sourceStaging);
- SafeRelease(destStaging);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal staging textures for depth stencil blit.");
+ if (srcDXGIFormat == DXGI_FORMAT_R24G8_TYPELESS)
+ {
+ ASSERT(sourceArea == destArea && sourceSize == destSize && scissor == nullptr);
+ return copyAndConvert(source, sourceSubresource, sourceArea, sourceSize, dest,
+ destSubresource, destArea, destSize, scissor, copyOffset,
+ copyOffset, copySize, srcPixelSize, destPixelSize,
+ BlitD24S8ToD32F);
+ }
+ ASSERT(srcDXGIFormat == DXGI_FORMAT_R32G8X24_TYPELESS);
+ return copyAndConvert(source, sourceSubresource, sourceArea, sourceSize, dest,
+ destSubresource, destArea, destSize, scissor, copyOffset, copyOffset,
+ copySize, srcPixelSize, destPixelSize, BlitD32FS8ToD32F);
}
- DXGI_FORMAT format = GetTextureFormat(source);
- ASSERT(format == GetTextureFormat(dest));
+ return copyAndConvert(source, sourceSubresource, sourceArea, sourceSize, dest, destSubresource,
+ destArea, destSize, scissor, copyOffset, copyOffset, copySize,
+ srcPixelSize, destPixelSize, StretchedBlitNearest);
+}
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format);
- unsigned int pixelSize = dxgiFormatInfo.pixelBytes;
- unsigned int copyOffset = 0;
- unsigned int copySize = pixelSize;
- if (stencilOnly)
- {
- copyOffset = dxgiFormatInfo.depthBits / 8;
- copySize = dxgiFormatInfo.stencilBits / 8;
+gl::Error Blit11::copyAndConvertImpl(const TextureHelper11 &source,
+ unsigned int sourceSubresource,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const TextureHelper11 &destStaging,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor,
+ size_t readOffset,
+ size_t writeOffset,
+ size_t copySize,
+ size_t srcPixelStride,
+ size_t destPixelStride,
+ BlitConvertFunction *convertFunction)
+{
+ ANGLE_TRY(initResources());
- // It would be expensive to have non-byte sized stencil sizes since it would
- // require reading from the destination, currently there aren't any though.
- ASSERT(dxgiFormatInfo.stencilBits % 8 == 0 &&
- dxgiFormatInfo.depthBits % 8 == 0);
- }
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ TextureHelper11 sourceStaging;
+ ANGLE_TRY_RESULT(mRenderer->createStagingTexture(ResourceType::Texture2D, source.getFormatSet(),
+ sourceSize, StagingAccess::READ),
+ sourceStaging);
+
+ deviceContext->CopySubresourceRegion(sourceStaging.get(), 0, 0, 0, 0, source.get(),
+ sourceSubresource, nullptr);
D3D11_MAPPED_SUBRESOURCE sourceMapping;
- HRESULT result = deviceContext->Map(sourceStaging, 0, D3D11_MAP_READ, 0, &sourceMapping);
+ HRESULT result = deviceContext->Map(sourceStaging.get(), 0, D3D11_MAP_READ, 0, &sourceMapping);
if (FAILED(result))
{
- SafeRelease(sourceStaging);
- SafeRelease(destStaging);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal source staging texture for depth stencil blit, HRESULT: 0x%X.", result);
+ return gl::OutOfMemory()
+ << "Failed to map internal source staging texture for depth stencil blit, "
+ << gl::FmtHR(result);
}
D3D11_MAPPED_SUBRESOURCE destMapping;
- result = deviceContext->Map(destStaging, 0, D3D11_MAP_WRITE, 0, &destMapping);
+ result = deviceContext->Map(destStaging.get(), 0, D3D11_MAP_WRITE, 0, &destMapping);
if (FAILED(result))
{
- deviceContext->Unmap(sourceStaging, 0);
- SafeRelease(sourceStaging);
- SafeRelease(destStaging);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal destination staging texture for depth stencil blit, HRESULT: 0x%X.", result);
+ deviceContext->Unmap(sourceStaging.get(), 0);
+ return gl::OutOfMemory()
+ << "Failed to map internal destination staging texture for depth stencil blit, "
+ << gl::FmtHR(result);
}
- gl::Rectangle clippedDestArea(destArea.x, destArea.y, destArea.width, destArea.height);
-
// Clip dest area to the destination size
- gl::ClipRectangle(clippedDestArea, gl::Rectangle(0, 0, destSize.width, destSize.height), &clippedDestArea);
+ gl::Rectangle clipRect = gl::Rectangle(0, 0, destSize.width, destSize.height);
// Clip dest area to the scissor
if (scissor)
{
- gl::ClipRectangle(clippedDestArea, *scissor, &clippedDestArea);
+ gl::ClipRectangle(clipRect, *scissor, &clipRect);
}
- // Determine if entire rows can be copied at once instead of each individual pixel, requires that there is
- // no out of bounds lookups required, the entire pixel is copied and no stretching
- bool wholeRowCopy = sourceArea.width == clippedDestArea.width &&
- sourceArea.x >= 0 && sourceArea.x + sourceArea.width <= sourceSize.width &&
- copySize == pixelSize;
+ convertFunction(sourceArea, destArea, clipRect, sourceSize, sourceMapping.RowPitch,
+ destMapping.RowPitch, readOffset, writeOffset, copySize, srcPixelStride,
+ destPixelStride, static_cast<const uint8_t *>(sourceMapping.pData),
+ static_cast<uint8_t *>(destMapping.pData));
- for (int y = clippedDestArea.y; y < clippedDestArea.y + clippedDestArea.height; y++)
- {
- float yPerc = static_cast<float>(y - destArea.y) / (destArea.height - 1);
+ deviceContext->Unmap(sourceStaging.get(), 0);
+ deviceContext->Unmap(destStaging.get(), 0);
- // Interpolate using the original source rectangle to determine which row to sample from while clamping to the edges
- unsigned int readRow = static_cast<unsigned int>(gl::clamp(sourceArea.y + floor(yPerc * (sourceArea.height - 1) + 0.5f), 0, sourceSize.height - 1));
- unsigned int writeRow = y;
-
- if (wholeRowCopy)
- {
- void *sourceRow = reinterpret_cast<char*>(sourceMapping.pData) +
- readRow * sourceMapping.RowPitch +
- sourceArea.x * pixelSize;
+ return gl::NoError();
+}
- void *destRow = reinterpret_cast<char*>(destMapping.pData) +
- writeRow * destMapping.RowPitch +
- destArea.x * pixelSize;
+gl::Error Blit11::copyAndConvert(const TextureHelper11 &source,
+ unsigned int sourceSubresource,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const TextureHelper11 &dest,
+ unsigned int destSubresource,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor,
+ size_t readOffset,
+ size_t writeOffset,
+ size_t copySize,
+ size_t srcPixelStride,
+ size_t destPixelStride,
+ BlitConvertFunction *convertFunction)
+{
+ ANGLE_TRY(initResources());
- memcpy(destRow, sourceRow, pixelSize * destArea.width);
- }
- else
- {
- for (int x = clippedDestArea.x; x < clippedDestArea.x + clippedDestArea.width; x++)
- {
- float xPerc = static_cast<float>(x - destArea.x) / (destArea.width - 1);
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
- // Interpolate the original source rectangle to determine which column to sample from while clamping to the edges
- unsigned int readColumn = static_cast<unsigned int>(gl::clamp(sourceArea.x + floor(xPerc * (sourceArea.width - 1) + 0.5f), 0, sourceSize.width - 1));
- unsigned int writeColumn = x;
+ // HACK: Create the destination staging buffer as a read/write texture so
+ // ID3D11DevicContext::UpdateSubresource can be called
+ // using it's mapped data as a source
+ TextureHelper11 destStaging;
+ ANGLE_TRY_RESULT(mRenderer->createStagingTexture(ResourceType::Texture2D, dest.getFormatSet(),
+ destSize, StagingAccess::READ_WRITE),
+ destStaging);
- void *sourcePixel = reinterpret_cast<char*>(sourceMapping.pData) +
- readRow * sourceMapping.RowPitch +
- readColumn * pixelSize +
- copyOffset;
+ deviceContext->CopySubresourceRegion(destStaging.get(), 0, 0, 0, 0, dest.get(), destSubresource,
+ nullptr);
- void *destPixel = reinterpret_cast<char*>(destMapping.pData) +
- writeRow * destMapping.RowPitch +
- writeColumn * pixelSize +
- copyOffset;
+ ANGLE_TRY(copyAndConvertImpl(source, sourceSubresource, sourceArea, sourceSize, destStaging,
+ destArea, destSize, scissor, readOffset, writeOffset, copySize,
+ srcPixelStride, destPixelStride, convertFunction));
- memcpy(destPixel, sourcePixel, copySize);
- }
- }
+ // Work around timeouts/TDRs in older NVIDIA drivers.
+ if (mRenderer->getWorkarounds().depthStencilBlitExtraCopy)
+ {
+ D3D11_MAPPED_SUBRESOURCE mapped;
+ deviceContext->Map(destStaging.get(), 0, D3D11_MAP_READ, 0, &mapped);
+ deviceContext->UpdateSubresource(dest.get(), destSubresource, nullptr, mapped.pData,
+ mapped.RowPitch, mapped.DepthPitch);
+ deviceContext->Unmap(destStaging.get(), 0);
+ }
+ else
+ {
+ deviceContext->CopySubresourceRegion(dest.get(), destSubresource, 0, 0, 0,
+ destStaging.get(), 0, nullptr);
}
- // HACK: Use ID3D11DevicContext::UpdateSubresource which causes an extra copy compared to ID3D11DevicContext::CopySubresourceRegion
- // according to MSDN.
- deviceContext->UpdateSubresource(dest, destSubresource, nullptr, destMapping.pData, destMapping.RowPitch, destMapping.DepthPitch);
-
- deviceContext->Unmap(sourceStaging, 0);
- deviceContext->Unmap(destStaging, 0);
-
- // TODO: Determine why this call to ID3D11DevicContext::CopySubresourceRegion causes a TDR timeout on some
- // systems when called repeatedly.
- // deviceContext->CopySubresourceRegion(dest, destSubresource, 0, 0, 0, destStaging, 0, nullptr);
-
- SafeRelease(sourceStaging);
- SafeRelease(destStaging);
-
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-void Blit11::addBlitShaderToMap(BlitShaderType blitShaderType, ShaderDimension dimension, ID3D11PixelShader *ps)
+gl::Error Blit11::addBlitShaderToMap(BlitShaderType blitShaderType,
+ ShaderDimension dimension,
+ const ShaderData &shaderData,
+ const char *name)
{
ASSERT(mBlitShaderMap.find(blitShaderType) == mBlitShaderMap.end());
- ASSERT(ps);
+
+ d3d11::PixelShader ps;
+ ANGLE_TRY(mRenderer->allocateResource(shaderData, &ps));
+ ps.setDebugName(name);
Shader shader;
- shader.dimension = dimension;
- shader.pixelShader = ps;
+ shader.dimension = dimension;
+ shader.pixelShader = std::move(ps);
- mBlitShaderMap[blitShaderType] = shader;
+ mBlitShaderMap[blitShaderType] = std::move(shader);
+ return gl::NoError();
}
-void Blit11::addSwizzleShaderToMap(SwizzleShaderType swizzleShaderType, ShaderDimension dimension, ID3D11PixelShader *ps)
+gl::Error Blit11::addSwizzleShaderToMap(SwizzleShaderType swizzleShaderType,
+ ShaderDimension dimension,
+ const ShaderData &shaderData,
+ const char *name)
{
ASSERT(mSwizzleShaderMap.find(swizzleShaderType) == mSwizzleShaderMap.end());
- ASSERT(ps);
+
+ d3d11::PixelShader ps;
+ ANGLE_TRY(mRenderer->allocateResource(shaderData, &ps));
+ ps.setDebugName(name);
Shader shader;
- shader.dimension = dimension;
- shader.pixelShader = ps;
+ shader.dimension = dimension;
+ shader.pixelShader = std::move(ps);
- mSwizzleShaderMap[swizzleShaderType] = shader;
+ mSwizzleShaderMap[swizzleShaderType] = std::move(shader);
+ return gl::NoError();
}
void Blit11::clearShaderMap()
{
- for (auto &blitShader : mBlitShaderMap)
- {
- SafeRelease(blitShader.second.pixelShader);
- }
mBlitShaderMap.clear();
-
- for (auto &swizzleShader : mSwizzleShaderMap)
- {
- SafeRelease(swizzleShader.second.pixelShader);
- }
mSwizzleShaderMap.clear();
}
-gl::Error Blit11::getBlitShader(GLenum destFormat, bool isSigned, ShaderDimension dimension, const Shader **shader)
+gl::Error Blit11::getBlitShader(GLenum destFormat,
+ GLenum sourceFormat,
+ bool isSigned,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ ShaderDimension dimension,
+ const Shader **shader)
{
- BlitShaderType blitShaderType = GetBlitShaderType(destFormat, isSigned, dimension);
+ BlitShaderType blitShaderType =
+ GetBlitShaderType(destFormat, sourceFormat, isSigned, unpackPremultiplyAlpha,
+ unpackUnmultiplyAlpha, dimension);
if (blitShaderType == BLITSHADER_INVALID)
{
- return gl::Error(GL_INVALID_OPERATION, "Internal blit shader type mismatch");
+ return gl::InternalError() << "Internal blit shader type mismatch";
}
auto blitShaderIt = mBlitShaderMap.find(blitShaderType);
if (blitShaderIt != mBlitShaderMap.end())
{
*shader = &blitShaderIt->second;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
ASSERT(dimension == SHADER_2D || mRenderer->isES3Capable());
- ID3D11Device *device = mRenderer->getDevice();
-
switch (blitShaderType)
{
- case BLITSHADER_2D_RGBAF:
- addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D RGBA pixel shader"));
- break;
- case BLITSHADER_2D_BGRAF:
- addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D BGRA pixel shader"));
- break;
- case BLITSHADER_2D_RGBF:
- addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughRGB2D, "Blit11 2D RGB pixel shader"));
- break;
- case BLITSHADER_2D_RGF:
- addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughRG2D, "Blit11 2D RG pixel shader"));
- break;
- case BLITSHADER_2D_RF:
- addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughR2D, "Blit11 2D R pixel shader"));
- break;
- case BLITSHADER_2D_ALPHA:
- addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D alpha pixel shader"));
- break;
- case BLITSHADER_2D_LUMA:
- addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughLum2D, "Blit11 2D lum pixel shader"));
- break;
- case BLITSHADER_2D_LUMAALPHA:
- addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha2D, "Blit11 2D luminance alpha pixel shader"));
- break;
- case BLITSHADER_2D_RGBAUI:
- addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DUI, "Blit11 2D RGBA UI pixel shader"));
- break;
- case BLITSHADER_2D_RGBAI:
- addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DI, "Blit11 2D RGBA I pixel shader"));
- break;
- case BLITSHADER_2D_RGBUI:
- addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughRGB2DUI, "Blit11 2D RGB UI pixel shader"));
- break;
- case BLITSHADER_2D_RGBI:
- addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughRGB2DI, "Blit11 2D RGB I pixel shader"));
- break;
- case BLITSHADER_2D_RGUI:
- addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughRG2DUI, "Blit11 2D RG UI pixel shader"));
- break;
- case BLITSHADER_2D_RGI:
- addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughRG2DI, "Blit11 2D RG I pixel shader"));
- break;
- case BLITSHADER_2D_RUI:
- addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughR2DUI, "Blit11 2D R UI pixel shader"));
- break;
- case BLITSHADER_2D_RI:
- addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughR2DI, "Blit11 2D R I pixel shader"));
- break;
- case BLITSHADER_3D_RGBAF:
- addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D RGBA pixel shader"));
- break;
- case BLITSHADER_3D_RGBAUI:
- addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DUI, "Blit11 3D UI RGBA pixel shader"));
- break;
- case BLITSHADER_3D_RGBAI:
- addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DI, "Blit11 3D I RGBA pixel shader"));
- break;
- case BLITSHADER_3D_BGRAF:
- addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D BGRA pixel shader"));
- break;
- case BLITSHADER_3D_RGBF:
- addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughRGB3D, "Blit11 3D RGB pixel shader"));
- break;
- case BLITSHADER_3D_RGBUI:
- addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughRGB3DUI, "Blit11 3D RGB UI pixel shader"));
- break;
- case BLITSHADER_3D_RGBI:
- addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughRGB3DI, "Blit11 3D RGB I pixel shader"));
- break;
- case BLITSHADER_3D_RGF:
- addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughRG3D, "Blit11 3D RG pixel shader"));
- break;
- case BLITSHADER_3D_RGUI:
- addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughRG3DUI, "Blit11 3D RG UI pixel shader"));
- break;
- case BLITSHADER_3D_RGI:
- addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughRG3DI, "Blit11 3D RG I pixel shader"));
- break;
- case BLITSHADER_3D_RF:
- addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughR3D, "Blit11 3D R pixel shader"));
- break;
- case BLITSHADER_3D_RUI:
- addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughR3DUI, "Blit11 3D R UI pixel shader"));
- break;
- case BLITSHADER_3D_RI:
- addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughR3DI, "Blit11 3D R I pixel shader"));
- break;
- case BLITSHADER_3D_ALPHA:
- addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D alpha pixel shader"));
- break;
- case BLITSHADER_3D_LUMA:
- addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughLum3D, "Blit11 3D luminance pixel shader"));
- break;
- case BLITSHADER_3D_LUMAALPHA:
- addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha3D, "Blit11 3D luminance alpha pixel shader"));
- break;
- default:
- UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION, "Internal error");
+ case BLITSHADER_2D_RGBAF:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughRGBA2D),
+ "Blit11 2D RGBA pixel shader"));
+ break;
+ case BLITSHADER_2D_BGRAF:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughRGBA2D),
+ "Blit11 2D BGRA pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBF:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughRGB2D),
+ "Blit11 2D RGB pixel shader"));
+ break;
+ case BLITSHADER_2D_RGF:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughRG2D),
+ "Blit11 2D RG pixel shader"));
+ break;
+ case BLITSHADER_2D_RF:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_PassthroughR2D),
+ "Blit11 2D R pixel shader"));
+ break;
+ case BLITSHADER_2D_ALPHA:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_PassthroughA2D),
+ "Blit11 2D alpha pixel shader"));
+ break;
+ case BLITSHADER_2D_LUMA:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughLum2D),
+ "Blit11 2D lum pixel shader"));
+ break;
+ case BLITSHADER_2D_LUMAALPHA:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughLumAlpha2D),
+ "Blit11 2D luminance alpha pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBAUI:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughRGBA2DUI),
+ "Blit11 2D RGBA UI pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBAI:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughRGBA2DI),
+ "Blit11 2D RGBA I pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBUI:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughRGB2DUI),
+ "Blit11 2D RGB UI pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBI:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughRGB2DI),
+ "Blit11 2D RGB I pixel shader"));
+ break;
+ case BLITSHADER_2D_RGUI:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughRG2DUI),
+ "Blit11 2D RG UI pixel shader"));
+ break;
+ case BLITSHADER_2D_RGI:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughRG2DI),
+ "Blit11 2D RG I pixel shader"));
+ break;
+ case BLITSHADER_2D_RUI:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughR2DUI),
+ "Blit11 2D R UI pixel shader"));
+ break;
+ case BLITSHADER_2D_RI:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughR2DI),
+ "Blit11 2D R I pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBAF:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRGBA3D),
+ "Blit11 3D RGBA pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBAUI:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRGBA3DUI),
+ "Blit11 3D UI RGBA pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBAI:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRGBA3DI),
+ "Blit11 3D I RGBA pixel shader"));
+ break;
+ case BLITSHADER_3D_BGRAF:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRGBA3D),
+ "Blit11 3D BGRA pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBF:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRGB3D),
+ "Blit11 3D RGB pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBUI:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRGB3DUI),
+ "Blit11 3D RGB UI pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBI:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRGB3DI),
+ "Blit11 3D RGB I pixel shader"));
+ break;
+ case BLITSHADER_3D_RGF:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRG3D),
+ "Blit11 3D RG pixel shader"));
+ break;
+ case BLITSHADER_3D_RGUI:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRG3DUI),
+ "Blit11 3D RG UI pixel shader"));
+ break;
+ case BLITSHADER_3D_RGI:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRG3DI),
+ "Blit11 3D RG I pixel shader"));
+ break;
+ case BLITSHADER_3D_RF:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, ShaderData(g_PS_PassthroughR3D),
+ "Blit11 3D R pixel shader"));
+ break;
+ case BLITSHADER_3D_RUI:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughR3DUI),
+ "Blit11 3D R UI pixel shader"));
+ break;
+ case BLITSHADER_3D_RI:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughR3DI),
+ "Blit11 3D R I pixel shader"));
+ break;
+ case BLITSHADER_3D_ALPHA:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRGBA3D),
+ "Blit11 3D alpha pixel shader"));
+ break;
+ case BLITSHADER_3D_LUMA:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughLum3D),
+ "Blit11 3D luminance pixel shader"));
+ break;
+ case BLITSHADER_3D_LUMAALPHA:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughLumAlpha3D),
+ "Blit11 3D luminance alpha pixel shader"));
+ break;
+
+ case BLITSHADER_2D_RGBAF_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoF_PM_RGBA),
+ "Blit11 2D RGBA premultiply pixel shader"));
+ break;
+
+ case BLITSHADER_2D_RGBAF_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoF_UM_RGBA),
+ "Blit11 2D RGBA unmultiply pixel shader"));
+ break;
+
+ case BLITSHADER_2D_RGBF_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoF_PM_RGB),
+ "Blit11 2D RGB premultiply pixel shader"));
+ break;
+
+ case BLITSHADER_2D_RGBF_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoF_UM_RGB),
+ "Blit11 2D RGB unmultiply pixel shader"));
+ break;
+
+ case BLITSHADER_2D_RGBAF_TOUI:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoU_PT_RGBA),
+ "Blit11 2D RGBA to uint pixel shader"));
+ break;
+
+ case BLITSHADER_2D_RGBAF_TOUI_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoU_PM_RGBA),
+ "Blit11 2D RGBA to uint premultiply pixel shader"));
+ break;
+
+ case BLITSHADER_2D_RGBAF_TOUI_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoU_UM_RGBA),
+ "Blit11 2D RGBA to uint unmultiply pixel shader"));
+ break;
+
+ case BLITSHADER_2D_RGBF_TOUI:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoU_PT_RGB),
+ "Blit11 2D RGB to uint pixel shader"));
+ break;
+
+ case BLITSHADER_2D_RGBF_TOUI_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoU_PM_RGB),
+ "Blit11 2D RGB to uint premultiply pixel shader"));
+ break;
+
+ case BLITSHADER_2D_RGBF_TOUI_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoU_UM_RGB),
+ "Blit11 2D RGB to uint unmultiply pixel shader"));
+ break;
+ case BLITSHADER_2D_LUMAF_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoF_PM_LUMA),
+ "Blit11 2D LUMA premultiply pixel shader"));
+ break;
+ case BLITSHADER_2D_LUMAF_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoF_UM_LUMA),
+ "Blit11 2D LUMA unmultiply pixel shader"));
+ break;
+ case BLITSHADER_2D_LUMAALPHAF_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D,
+ ShaderData(g_PS_FtoF_PM_LUMAALPHA),
+ "Blit11 2D LUMAALPHA premultiply pixel shader"));
+ break;
+ case BLITSHADER_2D_LUMAALPHAF_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D,
+ ShaderData(g_PS_FtoF_UM_LUMAALPHA),
+ "Blit11 2D LUMAALPHA unmultiply pixel shader"));
+ break;
+
+ default:
+ UNREACHABLE();
+ return gl::InternalError() << "Internal error";
}
blitShaderIt = mBlitShaderMap.find(blitShaderType);
ASSERT(blitShaderIt != mBlitShaderMap.end());
*shader = &blitShaderIt->second;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Blit11::getSwizzleShader(GLenum type, D3D11_SRV_DIMENSION viewDimension, const Shader **shader)
+gl::Error Blit11::getSwizzleShader(GLenum type,
+ D3D11_SRV_DIMENSION viewDimension,
+ const Shader **shader)
{
SwizzleShaderType swizzleShaderType = GetSwizzleShaderType(type, viewDimension);
if (swizzleShaderType == SWIZZLESHADER_INVALID)
{
- return gl::Error(GL_INVALID_OPERATION, "Swizzle shader type not found");
+ return gl::InternalError() << "Swizzle shader type not found";
}
auto swizzleShaderIt = mSwizzleShaderMap.find(swizzleShaderType);
if (swizzleShaderIt != mSwizzleShaderMap.end())
{
*shader = &swizzleShaderIt->second;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
// Swizzling shaders (OpenGL ES 3+)
ASSERT(mRenderer->isES3Capable());
- ID3D11Device *device = mRenderer->getDevice();
-
switch (swizzleShaderType)
{
- case SWIZZLESHADER_2D_FLOAT:
- addSwizzleShaderToMap(swizzleShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_SwizzleF2D, "Blit11 2D F swizzle pixel shader"));
- break;
- case SWIZZLESHADER_2D_UINT:
- addSwizzleShaderToMap(swizzleShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_SwizzleUI2D, "Blit11 2D UI swizzle pixel shader"));
- break;
- case SWIZZLESHADER_2D_INT:
- addSwizzleShaderToMap(swizzleShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_SwizzleI2D, "Blit11 2D I swizzle pixel shader"));
- break;
- case SWIZZLESHADER_CUBE_FLOAT:
- addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_SwizzleF2DArray, "Blit11 2D Cube F swizzle pixel shader"));
- break;
- case SWIZZLESHADER_CUBE_UINT:
- addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Cube UI swizzle pixel shader"));
- break;
- case SWIZZLESHADER_CUBE_INT:
- addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_SwizzleI2DArray, "Blit11 2D Cube I swizzle pixel shader"));
- break;
- case SWIZZLESHADER_3D_FLOAT:
- addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_SwizzleF3D, "Blit11 3D F swizzle pixel shader"));
- break;
- case SWIZZLESHADER_3D_UINT:
- addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_SwizzleUI3D, "Blit11 3D UI swizzle pixel shader"));
- break;
- case SWIZZLESHADER_3D_INT:
- addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_SwizzleI3D, "Blit11 3D I swizzle pixel shader"));
- break;
- case SWIZZLESHADER_ARRAY_FLOAT:
- addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_SwizzleF2DArray, "Blit11 2D Array F swizzle pixel shader"));
- break;
- case SWIZZLESHADER_ARRAY_UINT:
- addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Array UI swizzle pixel shader"));
- break;
- case SWIZZLESHADER_ARRAY_INT:
- addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_SwizzleI2DArray, "Blit11 2D Array I swizzle pixel shader"));
- break;
- default:
- UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION, "Internal error");
+ case SWIZZLESHADER_2D_FLOAT:
+ ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_2D,
+ ShaderData(g_PS_SwizzleF2D),
+ "Blit11 2D F swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_2D_UINT:
+ ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_2D,
+ ShaderData(g_PS_SwizzleUI2D),
+ "Blit11 2D UI swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_2D_INT:
+ ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_2D,
+ ShaderData(g_PS_SwizzleI2D),
+ "Blit11 2D I swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_CUBE_FLOAT:
+ ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
+ ShaderData(g_PS_SwizzleF2DArray),
+ "Blit11 2D Cube F swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_CUBE_UINT:
+ ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
+ ShaderData(g_PS_SwizzleUI2DArray),
+ "Blit11 2D Cube UI swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_CUBE_INT:
+ ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
+ ShaderData(g_PS_SwizzleI2DArray),
+ "Blit11 2D Cube I swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_3D_FLOAT:
+ ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
+ ShaderData(g_PS_SwizzleF3D),
+ "Blit11 3D F swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_3D_UINT:
+ ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
+ ShaderData(g_PS_SwizzleUI3D),
+ "Blit11 3D UI swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_3D_INT:
+ ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
+ ShaderData(g_PS_SwizzleI3D),
+ "Blit11 3D I swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_ARRAY_FLOAT:
+ ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
+ ShaderData(g_PS_SwizzleF2DArray),
+ "Blit11 2D Array F swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_ARRAY_UINT:
+ ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
+ ShaderData(g_PS_SwizzleUI2DArray),
+ "Blit11 2D Array UI swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_ARRAY_INT:
+ ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
+ ShaderData(g_PS_SwizzleI2DArray),
+ "Blit11 2D Array I swizzle pixel shader"));
+ break;
+ default:
+ UNREACHABLE();
+ return gl::InternalError() << "Internal error";
}
swizzleShaderIt = mSwizzleShaderMap.find(swizzleShaderType);
ASSERT(swizzleShaderIt != mSwizzleShaderMap.end());
*shader = &swizzleShaderIt->second;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
+gl::ErrorOrResult<TextureHelper11> Blit11::resolveDepth(const gl::Context *context,
+ RenderTarget11 *depth)
+{
+ ANGLE_TRY(initResources());
+
+ // Multisampled depth stencil SRVs are not available in feature level 10.0
+ ASSERT(mRenderer->getRenderer11DeviceCaps().featureLevel > D3D_FEATURE_LEVEL_10_0);
+
+ const auto &extents = depth->getExtents();
+ auto *deviceContext = mRenderer->getDeviceContext();
+ auto *stateManager = mRenderer->getStateManager();
+
+ ANGLE_TRY(initResolveDepthOnly(depth->getFormatSet(), extents));
+
+ ANGLE_TRY(mResolveDepthStencilVS.resolve(mRenderer));
+ ANGLE_TRY(mResolveDepthPS.resolve(mRenderer));
+
+ // Apply the necessary state changes to the D3D11 immediate device context.
+ stateManager->setInputLayout(nullptr);
+ stateManager->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ stateManager->setDrawShaders(&mResolveDepthStencilVS.getObj(), nullptr,
+ &mResolveDepthPS.getObj());
+ stateManager->setRasterizerState(nullptr);
+ stateManager->setDepthStencilState(&mDepthStencilState, 0xFFFFFFFF);
+ stateManager->setRenderTargets(nullptr, 0, mResolvedDepthDSView.get());
+ stateManager->setSimpleBlendState(nullptr);
+ stateManager->setSimpleViewport(extents);
+
+ // Set the viewport
+ stateManager->setShaderResourceShared(gl::SAMPLER_PIXEL, 0, &depth->getShaderResourceView());
+
+ // Trigger the blit on the GPU.
+ deviceContext->Draw(6, 0);
+
+ return mResolvedDepth;
}
+
+gl::Error Blit11::initResolveDepthOnly(const d3d11::Format &format, const gl::Extents &extents)
+{
+ if (mResolvedDepth.valid() && extents == mResolvedDepth.getExtents() &&
+ format.texFormat == mResolvedDepth.getFormat())
+ {
+ return gl::NoError();
+ }
+
+ D3D11_TEXTURE2D_DESC textureDesc;
+ textureDesc.Width = extents.width;
+ textureDesc.Height = extents.height;
+ textureDesc.MipLevels = 1;
+ textureDesc.ArraySize = 1;
+ textureDesc.Format = format.texFormat;
+ textureDesc.SampleDesc.Count = 1;
+ textureDesc.SampleDesc.Quality = 0;
+ textureDesc.Usage = D3D11_USAGE_DEFAULT;
+ textureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
+ textureDesc.CPUAccessFlags = 0;
+ textureDesc.MiscFlags = 0;
+
+ ANGLE_TRY(mRenderer->allocateTexture(textureDesc, format, &mResolvedDepth));
+ mResolvedDepth.setDebugName("Blit11::mResolvedDepth");
+
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+ dsvDesc.Flags = 0;
+ dsvDesc.Format = format.dsvFormat;
+ dsvDesc.Texture2D.MipSlice = 0;
+ dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+
+ ANGLE_TRY(mRenderer->allocateResource(dsvDesc, mResolvedDepth.get(), &mResolvedDepthDSView));
+ mResolvedDepthDSView.setDebugName("Blit11::mResolvedDepthDSView");
+
+ // Possibly D3D11 bug or undefined behaviour: Clear the DSV so that our first render
+ // works as expected. Otherwise the results of the first use seem to be incorrect.
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ context->ClearDepthStencilView(mResolvedDepthDSView.get(), D3D11_CLEAR_DEPTH, 1.0f, 0);
+
+ return gl::NoError();
+}
+
+gl::Error Blit11::initResolveDepthStencil(const gl::Extents &extents)
+{
+ // Check if we need to recreate depth stencil view
+ if (mResolvedDepthStencil.valid() && extents == mResolvedDepthStencil.getExtents())
+ {
+ ASSERT(mResolvedDepthStencil.getFormat() == DXGI_FORMAT_R32G32_FLOAT);
+ return gl::NoError();
+ }
+
+ if (mResolvedDepthStencil.valid())
+ {
+ releaseResolveDepthStencilResources();
+ }
+
+ const auto &formatSet = d3d11::Format::Get(GL_RG32F, mRenderer->getRenderer11DeviceCaps());
+
+ D3D11_TEXTURE2D_DESC textureDesc;
+ textureDesc.Width = extents.width;
+ textureDesc.Height = extents.height;
+ textureDesc.MipLevels = 1;
+ textureDesc.ArraySize = 1;
+ textureDesc.Format = formatSet.texFormat;
+ textureDesc.SampleDesc.Count = 1;
+ textureDesc.SampleDesc.Quality = 0;
+ textureDesc.Usage = D3D11_USAGE_DEFAULT;
+ textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET;
+ textureDesc.CPUAccessFlags = 0;
+ textureDesc.MiscFlags = 0;
+
+ ANGLE_TRY(mRenderer->allocateTexture(textureDesc, formatSet, &mResolvedDepthStencil));
+ mResolvedDepthStencil.setDebugName("Blit11::mResolvedDepthStencil");
+
+ ANGLE_TRY(mRenderer->allocateResourceNoDesc(mResolvedDepthStencil.get(),
+ &mResolvedDepthStencilRTView));
+ mResolvedDepthStencilRTView.setDebugName("Blit11::mResolvedDepthStencilRTView");
+
+ return gl::NoError();
+}
+
+gl::ErrorOrResult<TextureHelper11> Blit11::resolveStencil(const gl::Context *context,
+ RenderTarget11 *depthStencil,
+ bool alsoDepth)
+{
+ ANGLE_TRY(initResources());
+
+ // Multisampled depth stencil SRVs are not available in feature level 10.0
+ ASSERT(mRenderer->getRenderer11DeviceCaps().featureLevel > D3D_FEATURE_LEVEL_10_0);
+
+ const auto &extents = depthStencil->getExtents();
+
+ ANGLE_TRY(initResolveDepthStencil(extents));
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ auto *stateManager = mRenderer->getStateManager();
+ ID3D11Resource *stencilResource = depthStencil->getTexture().get();
+
+ // Check if we need to re-create the stencil SRV.
+ if (mStencilSRV.valid())
+ {
+ ID3D11Resource *priorResource = nullptr;
+ mStencilSRV.get()->GetResource(&priorResource);
+
+ if (stencilResource != priorResource)
+ {
+ mStencilSRV.reset();
+ }
+
+ SafeRelease(priorResource);
+ }
+
+ if (!mStencilSRV.valid())
+ {
+ D3D11_SHADER_RESOURCE_VIEW_DESC srViewDesc;
+ srViewDesc.Format = GetStencilSRVFormat(depthStencil->getFormatSet());
+ srViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
+
+ ANGLE_TRY(mRenderer->allocateResource(srViewDesc, stencilResource, &mStencilSRV));
+ mStencilSRV.setDebugName("Blit11::mStencilSRV");
+ }
+
+ // Notify the Renderer that all state should be invalidated.
+ ANGLE_TRY(mResolveDepthStencilVS.resolve(mRenderer));
+
+ // Resolving the depth buffer works by sampling the depth in the shader using a SRV, then
+ // writing to the resolved depth buffer using SV_Depth. We can't use this method for stencil
+ // because SV_StencilRef isn't supported until HLSL 5.1/D3D11.3.
+ const d3d11::PixelShader *pixelShader = nullptr;
+ if (alsoDepth)
+ {
+ ANGLE_TRY(mResolveDepthStencilPS.resolve(mRenderer));
+ pixelShader = &mResolveDepthStencilPS.getObj();
+ }
+ else
+ {
+ ANGLE_TRY(mResolveStencilPS.resolve(mRenderer));
+ pixelShader = &mResolveStencilPS.getObj();
+ }
+
+ // Apply the necessary state changes to the D3D11 immediate device context.
+ stateManager->setInputLayout(nullptr);
+ stateManager->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ stateManager->setDrawShaders(&mResolveDepthStencilVS.getObj(), nullptr, pixelShader);
+ stateManager->setRasterizerState(nullptr);
+ stateManager->setDepthStencilState(nullptr, 0xFFFFFFFF);
+ stateManager->setRenderTarget(mResolvedDepthStencilRTView.get(), nullptr);
+ stateManager->setSimpleBlendState(nullptr);
+
+ // Set the viewport
+ stateManager->setSimpleViewport(extents);
+ stateManager->setShaderResourceShared(gl::SAMPLER_PIXEL, 0,
+ &depthStencil->getShaderResourceView());
+ stateManager->setShaderResource(gl::SAMPLER_PIXEL, 1, &mStencilSRV);
+
+ // Trigger the blit on the GPU.
+ deviceContext->Draw(6, 0);
+
+ gl::Box copyBox(0, 0, 0, extents.width, extents.height, 1);
+
+ TextureHelper11 dest;
+ ANGLE_TRY_RESULT(
+ mRenderer->createStagingTexture(ResourceType::Texture2D, depthStencil->getFormatSet(),
+ extents, StagingAccess::READ_WRITE),
+ dest);
+
+ const auto &copyFunction = GetCopyDepthStencilFunction(depthStencil->getInternalFormat());
+ const auto &dsFormatSet = depthStencil->getFormatSet();
+ const auto &dsDxgiInfo = d3d11::GetDXGIFormatSizeInfo(dsFormatSet.texFormat);
+
+ ANGLE_TRY(copyAndConvertImpl(mResolvedDepthStencil, 0, copyBox, extents, dest, copyBox, extents,
+ nullptr, 0, 0, 0, 8u, dsDxgiInfo.pixelBytes, copyFunction));
+
+ // Return the resolved depth texture, which the caller must Release.
+ return dest;
+}
+
+void Blit11::releaseResolveDepthStencilResources()
+{
+ mStencilSRV.reset();
+ mResolvedDepthStencilRTView.reset();
+}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h
index 906616131e..14078f9db8 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h
@@ -10,8 +10,9 @@
#define LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_
#include "common/angleutils.h"
-#include "libANGLE/angletypes.h"
#include "libANGLE/Error.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
#include <map>
@@ -26,36 +27,84 @@ class Blit11 : angle::NonCopyable
explicit Blit11(Renderer11 *renderer);
~Blit11();
- gl::Error swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTargetView *dest, const gl::Extents &size,
- GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha);
+ gl::Error swizzleTexture(const gl::Context *context,
+ const d3d11::SharedSRV &source,
+ const d3d11::RenderTargetView &dest,
+ const gl::Extents &size,
+ const gl::SwizzleState &swizzleTarget);
- gl::Error copyTexture(ID3D11ShaderResourceView *source,
+ gl::Error copyTexture(const gl::Context *context,
+ const d3d11::SharedSRV &source,
const gl::Box &sourceArea,
const gl::Extents &sourceSize,
- ID3D11RenderTargetView *dest,
+ GLenum sourceFormat,
+ const d3d11::RenderTargetView &dest,
const gl::Box &destArea,
const gl::Extents &destSize,
const gl::Rectangle *scissor,
GLenum destFormat,
GLenum filter,
- bool maskOffAlpha);
+ bool maskOffAlpha,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha);
- gl::Error copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
- ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
+ gl::Error copyStencil(const gl::Context *context,
+ const TextureHelper11 &source,
+ unsigned int sourceSubresource,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const TextureHelper11 &dest,
+ unsigned int destSubresource,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
const gl::Rectangle *scissor);
- gl::Error copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize,
- ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize,
+ gl::Error copyDepth(const gl::Context *context,
+ const d3d11::SharedSRV &source,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const d3d11::DepthStencilView &dest,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
const gl::Rectangle *scissor);
- gl::Error copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
- ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
+ gl::Error copyDepthStencil(const TextureHelper11 &source,
+ unsigned int sourceSubresource,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const TextureHelper11 &dest,
+ unsigned int destSubresource,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
const gl::Rectangle *scissor);
+ gl::ErrorOrResult<TextureHelper11> resolveDepth(const gl::Context *context,
+ RenderTarget11 *depth);
+
+ gl::ErrorOrResult<TextureHelper11> resolveStencil(const gl::Context *context,
+ RenderTarget11 *depthStencil,
+ bool alsoDepth);
+
+ using BlitConvertFunction = void(const gl::Box &sourceArea,
+ const gl::Box &destArea,
+ const gl::Rectangle &clipRect,
+ const gl::Extents &sourceSize,
+ unsigned int sourceRowPitch,
+ unsigned int destRowPitch,
+ ptrdiff_t readOffset,
+ ptrdiff_t writeOffset,
+ size_t copySize,
+ size_t srcPixelStride,
+ size_t destPixelStride,
+ const uint8_t *sourceData,
+ uint8_t *destData);
+
private:
enum BlitShaderType
{
BLITSHADER_INVALID,
+
+ // Passthrough shaders
BLITSHADER_2D_RGBAF,
BLITSHADER_2D_BGRAF,
BLITSHADER_2D_RGBF,
@@ -88,6 +137,27 @@ class Blit11 : angle::NonCopyable
BLITSHADER_3D_ALPHA,
BLITSHADER_3D_LUMA,
BLITSHADER_3D_LUMAALPHA,
+
+ // Multiply alpha shaders
+ BLITSHADER_2D_RGBAF_PREMULTIPLY,
+ BLITSHADER_2D_RGBAF_UNMULTIPLY,
+
+ BLITSHADER_2D_RGBF_PREMULTIPLY,
+ BLITSHADER_2D_RGBF_UNMULTIPLY,
+
+ BLITSHADER_2D_RGBAF_TOUI,
+ BLITSHADER_2D_RGBAF_TOUI_PREMULTIPLY,
+ BLITSHADER_2D_RGBAF_TOUI_UNMULTIPLY,
+
+ BLITSHADER_2D_RGBF_TOUI,
+ BLITSHADER_2D_RGBF_TOUI_PREMULTIPLY,
+ BLITSHADER_2D_RGBF_TOUI_UNMULTIPLY,
+
+ BLITSHADER_2D_LUMAF_PREMULTIPLY,
+ BLITSHADER_2D_LUMAF_UNMULTIPLY,
+
+ BLITSHADER_2D_LUMAALPHAF_PREMULTIPLY,
+ BLITSHADER_2D_LUMAALPHAF_UNMULTIPLY
};
enum SwizzleShaderType
@@ -107,9 +177,13 @@ class Blit11 : angle::NonCopyable
SWIZZLESHADER_ARRAY_INT,
};
- typedef void (*WriteVertexFunction)(const gl::Box &sourceArea, const gl::Extents &sourceSize,
- const gl::Box &destArea, const gl::Extents &destSize,
- void *outVertices, unsigned int *outStride, unsigned int *outVertexCount,
+ typedef void (*WriteVertexFunction)(const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ void *outVertices,
+ unsigned int *outStride,
+ unsigned int *outVertexCount,
D3D11_PRIMITIVE_TOPOLOGY *outTopology);
enum ShaderDimension
@@ -120,38 +194,102 @@ class Blit11 : angle::NonCopyable
struct Shader
{
+ Shader();
+ Shader(Shader &&other);
+ ~Shader();
+ Shader &operator=(Shader &&other);
+
ShaderDimension dimension;
- ID3D11PixelShader *pixelShader;
+ d3d11::PixelShader pixelShader;
};
struct ShaderSupport
{
- ID3D11InputLayout *inputLayout;
- ID3D11VertexShader *vertexShader;
- ID3D11GeometryShader *geometryShader;
+ const d3d11::InputLayout *inputLayout;
+ const d3d11::VertexShader *vertexShader;
+ const d3d11::GeometryShader *geometryShader;
WriteVertexFunction vertexWriteFunction;
};
gl::Error initResources();
- void freeResources();
- ShaderSupport getShaderSupport(const Shader &shader);
+ gl::Error getShaderSupport(const Shader &shader, ShaderSupport *supportOut);
- static BlitShaderType GetBlitShaderType(GLenum destinationFormat, bool isSigned, ShaderDimension dimension);
+ static BlitShaderType GetBlitShaderType(GLenum destinationFormat,
+ GLenum sourceFormat,
+ bool isSigned,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ ShaderDimension dimension);
static SwizzleShaderType GetSwizzleShaderType(GLenum type, D3D11_SRV_DIMENSION dimensionality);
- gl::Error copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
- ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
- const gl::Rectangle *scissor, bool stencilOnly);
-
- void addBlitShaderToMap(BlitShaderType blitShaderType, ShaderDimension dimension, ID3D11PixelShader *ps);
-
- gl::Error getBlitShader(GLenum destFormat, bool isSigned, ShaderDimension dimension, const Shader **shaderOut);
- gl::Error getSwizzleShader(GLenum type, D3D11_SRV_DIMENSION viewDimension, const Shader **shaderOut);
-
- void addSwizzleShaderToMap(SwizzleShaderType swizzleShaderType, ShaderDimension dimension, ID3D11PixelShader *ps);
+ gl::Error copyDepthStencilImpl(const TextureHelper11 &source,
+ unsigned int sourceSubresource,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const TextureHelper11 &dest,
+ unsigned int destSubresource,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor,
+ bool stencilOnly);
+
+ gl::Error copyAndConvertImpl(const TextureHelper11 &source,
+ unsigned int sourceSubresource,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const TextureHelper11 &destStaging,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor,
+ size_t readOffset,
+ size_t writeOffset,
+ size_t copySize,
+ size_t srcPixelStride,
+ size_t destPixelStride,
+ BlitConvertFunction *convertFunction);
+
+ gl::Error copyAndConvert(const TextureHelper11 &source,
+ unsigned int sourceSubresource,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const TextureHelper11 &dest,
+ unsigned int destSubresource,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor,
+ size_t readOffset,
+ size_t writeOffset,
+ size_t copySize,
+ size_t srcPixelStride,
+ size_t destPixelStride,
+ BlitConvertFunction *convertFunction);
+
+ gl::Error addBlitShaderToMap(BlitShaderType blitShaderType,
+ ShaderDimension dimension,
+ const ShaderData &shaderData,
+ const char *name);
+
+ gl::Error getBlitShader(GLenum destFormat,
+ GLenum sourceFormat,
+ bool isSigned,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ ShaderDimension dimension,
+ const Shader **shaderOut);
+ gl::Error getSwizzleShader(GLenum type,
+ D3D11_SRV_DIMENSION viewDimension,
+ const Shader **shaderOut);
+
+ gl::Error addSwizzleShaderToMap(SwizzleShaderType swizzleShaderType,
+ ShaderDimension dimension,
+ const ShaderData &shaderData,
+ const char *name);
void clearShaderMap();
+ void releaseResolveDepthStencilResources();
+ gl::Error initResolveDepthOnly(const d3d11::Format &format, const gl::Extents &extents);
+ gl::Error initResolveDepthStencil(const gl::Extents &extents);
Renderer11 *mRenderer;
@@ -159,12 +297,12 @@ class Blit11 : angle::NonCopyable
std::map<SwizzleShaderType, Shader> mSwizzleShaderMap;
bool mResourcesInitialized;
- ID3D11Buffer *mVertexBuffer;
- ID3D11SamplerState *mPointSampler;
- ID3D11SamplerState *mLinearSampler;
- ID3D11RasterizerState *mScissorEnabledRasterizerState;
- ID3D11RasterizerState *mScissorDisabledRasterizerState;
- ID3D11DepthStencilState *mDepthStencilState;
+ d3d11::Buffer mVertexBuffer;
+ d3d11::SamplerState mPointSampler;
+ d3d11::SamplerState mLinearSampler;
+ d3d11::RasterizerState mScissorEnabledRasterizerState;
+ d3d11::RasterizerState mScissorDisabledRasterizerState;
+ d3d11::DepthStencilState mDepthStencilState;
d3d11::LazyInputLayout mQuad2DIL;
d3d11::LazyShader<ID3D11VertexShader> mQuad2DVS;
@@ -176,9 +314,19 @@ class Blit11 : angle::NonCopyable
d3d11::LazyBlendState mAlphaMaskBlendState;
- ID3D11Buffer *mSwizzleCB;
+ d3d11::Buffer mSwizzleCB;
+
+ d3d11::LazyShader<ID3D11VertexShader> mResolveDepthStencilVS;
+ d3d11::LazyShader<ID3D11PixelShader> mResolveDepthPS;
+ d3d11::LazyShader<ID3D11PixelShader> mResolveDepthStencilPS;
+ d3d11::LazyShader<ID3D11PixelShader> mResolveStencilPS;
+ d3d11::ShaderResourceView mStencilSRV;
+ TextureHelper11 mResolvedDepthStencil;
+ d3d11::RenderTargetView mResolvedDepthStencilRTView;
+ TextureHelper11 mResolvedDepth;
+ d3d11::DepthStencilView mResolvedDepthDSView;
};
-}
+} // namespace rx
-#endif // LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
index 0d5dc08b03..2317c9abdb 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
@@ -13,10 +13,14 @@
#include "common/MemoryBuffer.h"
#include "libANGLE/renderer/d3d/IndexDataManager.h"
#include "libANGLE/renderer/d3d/VertexDataManager.h"
-#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
-#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/renderer_utils.h"
+
+namespace rx
+{
namespace
{
@@ -27,41 +31,41 @@ GLuint ReadIndexValueFromIndices(const uint8_t *data, size_t index)
return reinterpret_cast<const T *>(data)[index];
}
typedef GLuint (*ReadIndexValueFunction)(const uint8_t *data, size_t index);
-}
-
-#if defined(ANGLE_MINGW32_COMPAT)
-typedef enum D3D11_MAP_FLAG {
- D3D11_MAP_FLAG_DO_NOT_WAIT = 0x100000
-} D3D11_MAP_FLAG;
-#endif
-namespace rx
-{
-PackPixelsParams::PackPixelsParams()
- : format(GL_NONE), type(GL_NONE), outputPitch(0), packBuffer(nullptr), offset(0)
+enum class CopyResult
{
-}
+ RECREATED,
+ NOT_RECREATED,
+};
-PackPixelsParams::PackPixelsParams(const gl::Rectangle &areaIn,
- GLenum formatIn,
- GLenum typeIn,
- GLuint outputPitchIn,
- const gl::PixelPackState &packIn,
- ptrdiff_t offsetIn)
- : area(areaIn),
- format(formatIn),
- type(typeIn),
- outputPitch(outputPitchIn),
- packBuffer(packIn.pixelBuffer.get()),
- pack(packIn.alignment, packIn.reverseRowOrder),
- offset(offsetIn)
+void CalculateConstantBufferParams(GLintptr offset,
+ GLsizeiptr size,
+ UINT *outFirstConstant,
+ UINT *outNumConstants)
{
+ // The offset must be aligned to 256 bytes (should have been enforced by glBindBufferRange).
+ ASSERT(offset % 256 == 0);
+
+ // firstConstant and numConstants are expressed in constants of 16-bytes. Furthermore they must
+ // be a multiple of 16 constants.
+ *outFirstConstant = static_cast<UINT>(offset / 16);
+
+ // The GL size is not required to be aligned to a 256 bytes boundary.
+ // Round the size up to a 256 bytes boundary then express the results in constants of 16-bytes.
+ *outNumConstants = static_cast<UINT>(rx::roundUp(size, static_cast<GLsizeiptr>(256)) / 16);
+
+ // Since the size is rounded up, firstConstant + numConstants may be bigger than the actual size
+ // of the buffer. This behaviour is explictly allowed according to the documentation on
+ // ID3D11DeviceContext1::PSSetConstantBuffers1
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx
}
+} // anonymous namespace
+
namespace gl_d3d11
{
-D3D11_MAP GetD3DMapTypeFromBits(GLbitfield access)
+D3D11_MAP GetD3DMapTypeFromBits(BufferUsage usage, GLbitfield access)
{
bool readBit = ((access & GL_MAP_READ_BIT) != 0);
bool writeBit = ((access & GL_MAP_WRITE_BIT) != 0);
@@ -77,7 +81,8 @@ D3D11_MAP GetD3DMapTypeFromBits(GLbitfield access)
}
else if (writeBit && !readBit)
{
- return D3D11_MAP_WRITE;
+ // Special case for uniform storage - we only allow full buffer updates.
+ return usage == BUFFER_USAGE_UNIFORM ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE;
}
else if (writeBit && readBit)
{
@@ -89,7 +94,7 @@ D3D11_MAP GetD3DMapTypeFromBits(GLbitfield access)
return D3D11_MAP_READ;
}
}
-}
+} // namespace gl_d3d11
// Each instance of Buffer11::BufferStorage is specialized for a class of D3D binding points
// - vertex/transform feedback buffers
@@ -106,16 +111,22 @@ class Buffer11::BufferStorage : angle::NonCopyable
size_t getSize() const { return mBufferSize; }
void setDataRevision(DataRevision rev) { mRevision = rev; }
- virtual bool isMappable() const = 0;
+ virtual bool isCPUAccessible(GLbitfield access) const = 0;
+
+ virtual bool isGPUAccessible() const = 0;
- virtual bool copyFromStorage(BufferStorage *source,
- size_t sourceOffset,
- size_t size,
- size_t destOffset) = 0;
- virtual gl::Error resize(size_t size, bool preserveData) = 0;
+ virtual gl::ErrorOrResult<CopyResult> copyFromStorage(const gl::Context *context,
+ BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset) = 0;
+ virtual gl::Error resize(const gl::Context *context, size_t size, bool preserveData) = 0;
- virtual uint8_t *map(size_t offset, size_t length, GLbitfield access) = 0;
- virtual void unmap() = 0;
+ virtual gl::Error map(size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut) = 0;
+ virtual void unmap() = 0;
gl::Error setData(const uint8_t *data, size_t offset, size_t size);
@@ -133,28 +144,41 @@ class Buffer11::BufferStorage : angle::NonCopyable
class Buffer11::NativeStorage : public Buffer11::BufferStorage
{
public:
- NativeStorage(Renderer11 *renderer, BufferUsage usage);
+ NativeStorage(Renderer11 *renderer,
+ BufferUsage usage,
+ const OnBufferDataDirtyChannel *onStorageChanged);
~NativeStorage() override;
- bool isMappable() const override { return mUsage == BUFFER_USAGE_STAGING; }
+ bool isCPUAccessible(GLbitfield access) const override;
+
+ bool isGPUAccessible() const override { return true; }
- ID3D11Buffer *getNativeStorage() const { return mNativeStorage; }
- bool copyFromStorage(BufferStorage *source,
- size_t sourceOffset,
- size_t size,
- size_t destOffset) override;
- gl::Error resize(size_t size, bool preserveData) override;
+ const d3d11::Buffer &getBuffer() const { return mBuffer; }
+ gl::ErrorOrResult<CopyResult> copyFromStorage(const gl::Context *context,
+ BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset) override;
+ gl::Error resize(const gl::Context *context, size_t size, bool preserveData) override;
- uint8_t *map(size_t offset, size_t length, GLbitfield access) override;
+ gl::Error map(size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut) override;
void unmap() override;
+ gl::ErrorOrResult<const d3d11::ShaderResourceView *> getSRVForFormat(DXGI_FORMAT srvFormat);
+
private:
- static void fillBufferDesc(D3D11_BUFFER_DESC *bufferDesc,
+ static void FillBufferDesc(D3D11_BUFFER_DESC *bufferDesc,
Renderer11 *renderer,
BufferUsage usage,
unsigned int bufferSize);
+ void clearSRVs();
- ID3D11Buffer *mNativeStorage;
+ d3d11::Buffer mBuffer;
+ const OnBufferDataDirtyChannel *mOnStorageChanged;
+ std::map<DXGI_FORMAT, d3d11::ShaderResourceView> mBufferResourceViews;
};
// A emulated indexed buffer storage represents an underlying D3D11 buffer for data
@@ -166,28 +190,32 @@ class Buffer11::EmulatedIndexedStorage : public Buffer11::BufferStorage
EmulatedIndexedStorage(Renderer11 *renderer);
~EmulatedIndexedStorage() override;
- bool isMappable() const override { return true; }
+ bool isCPUAccessible(GLbitfield access) const override { return true; }
+
+ bool isGPUAccessible() const override { return false; }
- ID3D11Buffer *getNativeStorage();
+ gl::ErrorOrResult<const d3d11::Buffer *> getBuffer(SourceIndexData *indexInfo,
+ const TranslatedAttribute &attribute,
+ GLint startVertex);
- bool copyFromStorage(BufferStorage *source,
- size_t sourceOffset,
- size_t size,
- size_t destOffset) override;
+ gl::ErrorOrResult<CopyResult> copyFromStorage(const gl::Context *context,
+ BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset) override;
- gl::Error resize(size_t size, bool preserveData) override;
+ gl::Error resize(const gl::Context *context, size_t size, bool preserveData) override;
- uint8_t *map(size_t offset, size_t length, GLbitfield access) override;
+ gl::Error map(size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut) override;
void unmap() override;
- bool update(SourceIndexData *indexInfo, const TranslatedAttribute *attribute);
private:
- ID3D11Buffer *mNativeStorage; // contains expanded data for use by D3D
- MemoryBuffer mMemoryBuffer; // original data (not expanded)
- MemoryBuffer mIndicesMemoryBuffer; // indices data
- SourceIndexData mIndexInfo; // indices information
- size_t mAttributeStride; // per element stride in bytes
- size_t mAttributeOffset; // starting offset
+ d3d11::Buffer mBuffer; // contains expanded data for use by D3D
+ angle::MemoryBuffer mMemoryBuffer; // original data (not expanded)
+ angle::MemoryBuffer mIndicesMemoryBuffer; // indices data
};
// Pack storage represents internal storage for pack buffers. We implement pack buffers
@@ -198,24 +226,32 @@ class Buffer11::PackStorage : public Buffer11::BufferStorage
explicit PackStorage(Renderer11 *renderer);
~PackStorage() override;
- bool isMappable() const override { return true; }
- bool copyFromStorage(BufferStorage *source,
- size_t sourceOffset,
- size_t size,
- size_t destOffset) override;
- gl::Error resize(size_t size, bool preserveData) override;
+ bool isCPUAccessible(GLbitfield access) const override { return true; }
- uint8_t *map(size_t offset, size_t length, GLbitfield access) override;
+ bool isGPUAccessible() const override { return false; }
+
+ gl::ErrorOrResult<CopyResult> copyFromStorage(const gl::Context *context,
+ BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset) override;
+ gl::Error resize(const gl::Context *context, size_t size, bool preserveData) override;
+
+ gl::Error map(size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut) override;
void unmap() override;
- gl::Error packPixels(const gl::FramebufferAttachment &readAttachment,
+ gl::Error packPixels(const gl::Context *context,
+ const gl::FramebufferAttachment &readAttachment,
const PackPixelsParams &params);
private:
gl::Error flushQueuedPackCommand();
TextureHelper11 mStagingTexture;
- MemoryBuffer mMemoryBuffer;
+ angle::MemoryBuffer mMemoryBuffer;
std::unique_ptr<PackPixelsParams> mQueuedPackCommand;
PackPixelsParams mPackParams;
bool mDataModified;
@@ -230,37 +266,46 @@ class Buffer11::SystemMemoryStorage : public Buffer11::BufferStorage
explicit SystemMemoryStorage(Renderer11 *renderer);
~SystemMemoryStorage() override {}
- bool isMappable() const override { return true; }
- bool copyFromStorage(BufferStorage *source,
- size_t sourceOffset,
- size_t size,
- size_t destOffset) override;
- gl::Error resize(size_t size, bool preserveData) override;
+ bool isCPUAccessible(GLbitfield access) const override { return true; }
+
+ bool isGPUAccessible() const override { return false; }
- uint8_t *map(size_t offset, size_t length, GLbitfield access) override;
+ gl::ErrorOrResult<CopyResult> copyFromStorage(const gl::Context *context,
+ BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset) override;
+ gl::Error resize(const gl::Context *context, size_t size, bool preserveData) override;
+
+ gl::Error map(size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut) override;
void unmap() override;
- MemoryBuffer *getSystemCopy() { return &mSystemCopy; }
+ angle::MemoryBuffer *getSystemCopy() { return &mSystemCopy; }
protected:
- MemoryBuffer mSystemCopy;
+ angle::MemoryBuffer mSystemCopy;
};
-Buffer11::Buffer11(Renderer11 *renderer)
- : BufferD3D(renderer),
+Buffer11::Buffer11(const gl::BufferState &state, Renderer11 *renderer)
+ : BufferD3D(state, renderer),
mRenderer(renderer),
mSize(0),
mMappedStorage(nullptr),
- mBufferStorages(BUFFER_USAGE_COUNT, nullptr),
+ mBufferStorages({}),
+ mLatestBufferStorage(nullptr),
+ mDeallocThresholds({}),
+ mIdleness({}),
mConstantBufferStorageAdditionalSize(0),
- mMaxConstantBufferLruCount(0),
- mReadUsageCount(0)
+ mMaxConstantBufferLruCount(0)
{
}
Buffer11::~Buffer11()
{
- for (auto &storage : mBufferStorages)
+ for (BufferStorage *&storage : mBufferStorages)
{
SafeDelete(storage);
}
@@ -273,79 +318,74 @@ Buffer11::~Buffer11()
mRenderer->onBufferDelete(this);
}
-gl::Error Buffer11::setData(const void *data, size_t size, GLenum usage)
+gl::Error Buffer11::setData(const gl::Context *context,
+ gl::BufferBinding target,
+ const void *data,
+ size_t size,
+ gl::BufferUsage usage)
{
- gl::Error error = setSubData(data, size, 0);
- if (error.isError())
- {
- return error;
- }
-
- updateD3DBufferUsage(usage);
- return error;
+ updateD3DBufferUsage(context, usage);
+ ANGLE_TRY(setSubData(context, target, data, size, 0));
+ return gl::NoError();
}
-gl::Error Buffer11::getData(const uint8_t **outData)
+gl::Error Buffer11::getData(const gl::Context *context, const uint8_t **outData)
{
SystemMemoryStorage *systemMemoryStorage = nullptr;
- gl::Error error = getSystemMemoryStorage(&systemMemoryStorage);
-
- if (error.isError())
- {
- *outData = nullptr;
- return error;
- }
-
- mReadUsageCount = 0;
+ ANGLE_TRY_RESULT(getSystemMemoryStorage(context), systemMemoryStorage);
ASSERT(systemMemoryStorage->getSize() >= mSize);
*outData = systemMemoryStorage->getSystemCopy()->data();
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Buffer11::getSystemMemoryStorage(SystemMemoryStorage **storageOut)
+gl::ErrorOrResult<Buffer11::SystemMemoryStorage *> Buffer11::getSystemMemoryStorage(
+ const gl::Context *context)
{
- BufferStorage *memStorageUntyped = getBufferStorage(BUFFER_USAGE_SYSTEM_MEMORY);
-
- if (memStorageUntyped == nullptr)
- {
- // TODO(jmadill): convert all to errors
- return gl::Error(GL_OUT_OF_MEMORY);
- }
-
- *storageOut = GetAs<SystemMemoryStorage>(memStorageUntyped);
- return gl::Error(GL_NO_ERROR);
+ BufferStorage *storage = nullptr;
+ ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_SYSTEM_MEMORY), storage);
+ return GetAs<SystemMemoryStorage>(storage);
}
-gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset)
+gl::Error Buffer11::setSubData(const gl::Context *context,
+ gl::BufferBinding target,
+ const void *data,
+ size_t size,
+ size_t offset)
{
size_t requiredSize = size + offset;
if (data && size > 0)
{
// Use system memory storage for dynamic buffers.
-
+ // Try using a constant storage for constant buffers
BufferStorage *writeBuffer = nullptr;
- if (supportsDirectBinding())
+ if (target == gl::BufferBinding::Uniform)
{
- writeBuffer = getStagingStorage();
-
- if (!writeBuffer)
+ // If we are a very large uniform buffer, keep system memory storage around so that we
+ // aren't forced to read back from a constant buffer. We also check the workaround for
+ // Intel - this requires us to use system memory so we don't end up having to copy from
+ // a constant buffer to a staging buffer.
+ // TODO(jmadill): Use Context caps.
+ if (offset == 0 && size >= mSize &&
+ size <= static_cast<UINT>(mRenderer->getNativeCaps().maxUniformBlockSize) &&
+ !mRenderer->getWorkarounds().useSystemMemoryForConstantBuffers)
+ {
+ ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_UNIFORM), writeBuffer);
+ }
+ else
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal buffer.");
+ ANGLE_TRY_RESULT(getSystemMemoryStorage(context), writeBuffer);
}
}
+ else if (supportsDirectBinding())
+ {
+ ANGLE_TRY_RESULT(getStagingStorage(context), writeBuffer);
+ }
else
{
- SystemMemoryStorage *systemMemoryStorage = nullptr;
- gl::Error error = getSystemMemoryStorage(&systemMemoryStorage);
- if (error.isError())
- {
- return error;
- }
-
- writeBuffer = systemMemoryStorage;
+ ANGLE_TRY_RESULT(getSystemMemoryStorage(context), writeBuffer);
}
ASSERT(writeBuffer);
@@ -355,24 +395,25 @@ gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset)
if (writeBuffer->getSize() < requiredSize)
{
bool preserveData = (offset > 0);
- gl::Error error = writeBuffer->resize(requiredSize, preserveData);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(writeBuffer->resize(context, requiredSize, preserveData));
}
- writeBuffer->setData(static_cast<const uint8_t *>(data), offset, size);
- writeBuffer->setDataRevision(writeBuffer->getDataRevision() + 1);
+ ANGLE_TRY(writeBuffer->setData(static_cast<const uint8_t *>(data), offset, size));
+ onStorageUpdate(writeBuffer);
+
+ // Notify any vertex arrays that we have dirty data.
+ // TODO(jmadill): Use a more fine grained notification for data updates.
+ mDirectBroadcastChannel.signal(context);
}
mSize = std::max(mSize, requiredSize);
- invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE);
+ invalidateStaticData(context);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Buffer11::copySubData(BufferImpl *source,
+gl::Error Buffer11::copySubData(const gl::Context *context,
+ BufferImpl *source,
GLintptr sourceOffset,
GLintptr destOffset,
GLsizeiptr size)
@@ -380,28 +421,32 @@ gl::Error Buffer11::copySubData(BufferImpl *source,
Buffer11 *sourceBuffer = GetAs<Buffer11>(source);
ASSERT(sourceBuffer != nullptr);
- BufferStorage *copyDest = getLatestBufferStorage();
+ BufferStorage *copyDest = nullptr;
+ ANGLE_TRY_RESULT(getLatestBufferStorage(context), copyDest);
+
if (!copyDest)
{
- copyDest = getStagingStorage();
+ ANGLE_TRY_RESULT(getStagingStorage(context), copyDest);
}
- BufferStorage *copySource = sourceBuffer->getLatestBufferStorage();
+ BufferStorage *copySource = nullptr;
+ ANGLE_TRY_RESULT(sourceBuffer->getLatestBufferStorage(context), copySource);
- if (!copySource || !copyDest)
+ if (!copySource)
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging buffer.");
+ ANGLE_TRY_RESULT(sourceBuffer->getStagingStorage(context), copySource);
}
- // If copying to/from a pixel pack buffer, we must have a staging or
- // pack buffer partner, because other native buffers can't be mapped
- if (copyDest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copySource->isMappable())
+ ASSERT(copySource && copyDest);
+
+ // A staging buffer is needed if there is no cpu-cpu or gpu-gpu copy path avaiable.
+ if (!copyDest->isGPUAccessible() && !copySource->isCPUAccessible(GL_MAP_READ_BIT))
{
- copySource = sourceBuffer->getStagingStorage();
+ ANGLE_TRY_RESULT(sourceBuffer->getStagingStorage(context), copySource);
}
- else if (copySource->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copyDest->isMappable())
+ else if (!copySource->isGPUAccessible() && !copyDest->isCPUAccessible(GL_MAP_WRITE_BIT))
{
- copyDest = getStagingStorage();
+ ANGLE_TRY_RESULT(getStagingStorage(context), copyDest);
}
// D3D11 does not allow overlapped copies until 11.1, and only if the
@@ -411,36 +456,48 @@ gl::Error Buffer11::copySubData(BufferImpl *source,
{
if (copySource->getUsage() == BUFFER_USAGE_STAGING)
{
- copySource = getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
+ ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK),
+ copySource);
}
else
{
- copySource = getStagingStorage();
+ ANGLE_TRY_RESULT(getStagingStorage(context), copySource);
}
}
- copyDest->copyFromStorage(copySource, sourceOffset, size, destOffset);
- copyDest->setDataRevision(copyDest->getDataRevision() + 1);
+ CopyResult copyResult = CopyResult::NOT_RECREATED;
+ ANGLE_TRY_RESULT(copyDest->copyFromStorage(context, copySource, sourceOffset, size, destOffset),
+ copyResult);
+ onStorageUpdate(copyDest);
mSize = std::max<size_t>(mSize, destOffset + size);
- invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE);
+ invalidateStaticData(context);
+
+ // Also notify that direct buffers are dirty.
+ mDirectBroadcastChannel.signal(context);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Buffer11::map(GLenum access, GLvoid **mapPtr)
+gl::Error Buffer11::map(const gl::Context *context, GLenum access, void **mapPtr)
{
// GL_OES_mapbuffer uses an enum instead of a bitfield for it's access, convert to a bitfield
// and call mapRange.
ASSERT(access == GL_WRITE_ONLY_OES);
- return mapRange(0, mSize, GL_MAP_WRITE_BIT, mapPtr);
+ return mapRange(context, 0, mSize, GL_MAP_WRITE_BIT, mapPtr);
}
-gl::Error Buffer11::mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr)
+gl::Error Buffer11::mapRange(const gl::Context *context,
+ size_t offset,
+ size_t length,
+ GLbitfield access,
+ void **mapPtr)
{
ASSERT(!mMappedStorage);
- BufferStorage *latestStorage = getLatestBufferStorage();
+ BufferStorage *latestStorage = nullptr;
+ ANGLE_TRY_RESULT(getLatestBufferStorage(context), latestStorage);
+
if (latestStorage && (latestStorage->getUsage() == BUFFER_USAGE_PIXEL_PACK ||
latestStorage->getUsage() == BUFFER_USAGE_STAGING))
{
@@ -449,34 +506,32 @@ gl::Error Buffer11::mapRange(size_t offset, size_t length, GLbitfield access, GL
}
else
{
- // Fall back to using the staging buffer if the latest storage does
- // not exist or is not CPU-accessible.
- mMappedStorage = getStagingStorage();
+ // Fall back to using the staging buffer if the latest storage does not exist or is not
+ // CPU-accessible.
+ ANGLE_TRY_RESULT(getStagingStorage(context), mMappedStorage);
}
if (!mMappedStorage)
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate mappable internal buffer.");
+ return gl::OutOfMemory() << "Failed to allocate mappable internal buffer.";
}
if ((access & GL_MAP_WRITE_BIT) > 0)
{
// Update the data revision immediately, since the data might be changed at any time
- mMappedStorage->setDataRevision(mMappedStorage->getDataRevision() + 1);
- invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE);
+ onStorageUpdate(mMappedStorage);
+ invalidateStaticData(context);
}
- uint8_t *mappedBuffer = mMappedStorage->map(offset, length, access);
- if (!mappedBuffer)
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer.");
- }
+ uint8_t *mappedBuffer = nullptr;
+ ANGLE_TRY(mMappedStorage->map(offset, length, access, &mappedBuffer));
+ ASSERT(mappedBuffer);
- *mapPtr = static_cast<GLvoid *>(mappedBuffer);
- return gl::Error(GL_NO_ERROR);
+ *mapPtr = static_cast<void *>(mappedBuffer);
+ return gl::NoError();
}
-gl::Error Buffer11::unmap(GLboolean *result)
+gl::Error Buffer11::unmap(const gl::Context *context, GLboolean *result)
{
ASSERT(mMappedStorage);
mMappedStorage->unmap();
@@ -485,168 +540,171 @@ gl::Error Buffer11::unmap(GLboolean *result)
// TODO: detect if we had corruption. if so, return false.
*result = GL_TRUE;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-void Buffer11::markTransformFeedbackUsage()
+gl::Error Buffer11::markTransformFeedbackUsage(const gl::Context *context)
{
- BufferStorage *transformFeedbackStorage =
- getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
+ BufferStorage *transformFeedbackStorage = nullptr;
+ ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK),
+ transformFeedbackStorage);
if (transformFeedbackStorage)
{
- transformFeedbackStorage->setDataRevision(transformFeedbackStorage->getDataRevision() + 1);
+ onStorageUpdate(transformFeedbackStorage);
}
- invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE);
+ invalidateStaticData(context);
+ return gl::NoError();
}
-void Buffer11::markBufferUsage()
+void Buffer11::updateDeallocThreshold(BufferUsage usage)
{
- mReadUsageCount++;
+ // The following strategy was tuned on the Oort online benchmark (http://oortonline.gl/)
+ // as well as a custom microbenchmark (IndexConversionPerfTest.Run/index_range_d3d11)
+
+ // First readback: 8 unmodified uses before we free buffer memory.
+ // After that, double the threshold each time until we reach the max.
+ if (mDeallocThresholds[usage] == 0)
+ {
+ mDeallocThresholds[usage] = 8;
+ }
+ else if (mDeallocThresholds[usage] < std::numeric_limits<unsigned int>::max() / 2u)
+ {
+ mDeallocThresholds[usage] *= 2u;
+ }
+ else
+ {
+ mDeallocThresholds[usage] = std::numeric_limits<unsigned int>::max();
+ }
+}
- // Free the system memory storage if we decide it isn't being used very often.
- const unsigned int usageLimit = 5;
+// Free the storage if we decide it isn't being used very often.
+gl::Error Buffer11::checkForDeallocation(const gl::Context *context, BufferUsage usage)
+{
+ mIdleness[usage]++;
- BufferStorage *&sysMemUsage = mBufferStorages[BUFFER_USAGE_SYSTEM_MEMORY];
- if (mReadUsageCount > usageLimit && sysMemUsage != nullptr)
+ BufferStorage *&storage = mBufferStorages[usage];
+ if (storage != nullptr && mIdleness[usage] > mDeallocThresholds[usage])
{
- if (getLatestBufferStorage() != sysMemUsage)
+ BufferStorage *latestStorage = nullptr;
+ ANGLE_TRY_RESULT(getLatestBufferStorage(context), latestStorage);
+ if (latestStorage != storage)
{
- SafeDelete(sysMemUsage);
+ SafeDelete(storage);
}
}
+
+ return gl::NoError();
}
-ID3D11Buffer *Buffer11::getBuffer(BufferUsage usage)
+// Keep system memory when we are using it for the canonical version of data.
+bool Buffer11::canDeallocateSystemMemory() const
{
- markBufferUsage();
-
- BufferStorage *bufferStorage = getBufferStorage(usage);
-
- if (!bufferStorage)
+ // Must keep system memory on Intel.
+ if (mRenderer->getWorkarounds().useSystemMemoryForConstantBuffers)
{
- // Storage out-of-memory
- return nullptr;
+ return false;
}
- return GetAs<NativeStorage>(bufferStorage)->getNativeStorage();
+ return (!mBufferStorages[BUFFER_USAGE_UNIFORM] ||
+ mSize <= mRenderer->getNativeCaps().maxUniformBlockSize);
}
-ID3D11Buffer *Buffer11::getEmulatedIndexedBuffer(SourceIndexData *indexInfo,
- const TranslatedAttribute *attribute)
+void Buffer11::markBufferUsage(BufferUsage usage)
{
- markBufferUsage();
-
- assert(indexInfo != nullptr);
- assert(attribute != nullptr);
+ mIdleness[usage] = 0;
+}
- BufferStorage *bufferStorage = getBufferStorage(BUFFER_USAGE_EMULATED_INDEXED_VERTEX);
- if (!bufferStorage)
+gl::Error Buffer11::garbageCollection(const gl::Context *context, BufferUsage currentUsage)
+{
+ if (currentUsage != BUFFER_USAGE_SYSTEM_MEMORY && canDeallocateSystemMemory())
{
- // Storage out-of-memory
- return nullptr;
+ ANGLE_TRY(checkForDeallocation(context, BUFFER_USAGE_SYSTEM_MEMORY));
}
- EmulatedIndexedStorage *emulatedStorage = GetAs<EmulatedIndexedStorage>(bufferStorage);
- if (!emulatedStorage->update(indexInfo, attribute))
+ if (currentUsage != BUFFER_USAGE_STAGING)
{
- // Storage out-of-memory
- return nullptr;
+ ANGLE_TRY(checkForDeallocation(context, BUFFER_USAGE_STAGING));
}
- return emulatedStorage->getNativeStorage();
+ return gl::NoError();
}
-ID3D11Buffer *Buffer11::getConstantBufferRange(GLintptr offset, GLsizeiptr size)
+gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getBuffer(const gl::Context *context, BufferUsage usage)
{
- markBufferUsage();
+ BufferStorage *storage = nullptr;
+ ANGLE_TRY_RESULT(getBufferStorage(context, usage), storage);
+ return GetAs<NativeStorage>(storage)->getBuffer().get();
+}
- BufferStorage *bufferStorage;
+gl::ErrorOrResult<ID3D11Buffer *> Buffer11::getEmulatedIndexedBuffer(
+ const gl::Context *context,
+ SourceIndexData *indexInfo,
+ const TranslatedAttribute &attribute,
+ GLint startVertex)
+{
+ ASSERT(indexInfo);
- if (offset == 0)
- {
- bufferStorage = getBufferStorage(BUFFER_USAGE_UNIFORM);
- }
- else
- {
- bufferStorage = getConstantBufferRangeStorage(offset, size);
- }
+ BufferStorage *untypedStorage = nullptr;
+ ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_EMULATED_INDEXED_VERTEX),
+ untypedStorage);
- if (!bufferStorage)
- {
- // Storage out-of-memory
- return nullptr;
- }
+ EmulatedIndexedStorage *emulatedStorage = GetAs<EmulatedIndexedStorage>(untypedStorage);
+
+ const d3d11::Buffer *nativeStorage = nullptr;
+ ANGLE_TRY_RESULT(emulatedStorage->getBuffer(indexInfo, attribute, startVertex), nativeStorage);
- return GetAs<NativeStorage>(bufferStorage)->getNativeStorage();
+ return nativeStorage->get();
}
-ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat)
+gl::Error Buffer11::getConstantBufferRange(const gl::Context *context,
+ GLintptr offset,
+ GLsizeiptr size,
+ const d3d11::Buffer **bufferOut,
+ UINT *firstConstantOut,
+ UINT *numConstantsOut)
{
- BufferStorage *storage = getBufferStorage(BUFFER_USAGE_PIXEL_UNPACK);
+ BufferStorage *bufferStorage = nullptr;
- if (!storage)
+ if (offset == 0 || mRenderer->getRenderer11DeviceCaps().supportsConstantBufferOffsets)
{
- // Storage out-of-memory
- return nullptr;
+ ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_UNIFORM), bufferStorage);
+ CalculateConstantBufferParams(offset, size, firstConstantOut, numConstantsOut);
}
-
- ID3D11Buffer *buffer = GetAs<NativeStorage>(storage)->getNativeStorage();
-
- auto bufferSRVIt = mBufferResourceViews.find(srvFormat);
-
- if (bufferSRVIt != mBufferResourceViews.end())
+ else
{
- if (bufferSRVIt->second.first == buffer)
- {
- return bufferSRVIt->second.second;
- }
- else
- {
- // The underlying buffer has changed since the SRV was created: recreate the SRV.
- SafeRelease(bufferSRVIt->second.second);
- }
+ ANGLE_TRY_RESULT(getConstantBufferRangeStorage(context, offset, size), bufferStorage);
+ *firstConstantOut = 0;
+ *numConstantsOut = 0;
}
- ID3D11Device *device = mRenderer->getDevice();
- ID3D11ShaderResourceView *bufferSRV = nullptr;
-
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(srvFormat);
+ *bufferOut = &GetAs<NativeStorage>(bufferStorage)->getBuffer();
- D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc;
- bufferSRVDesc.Buffer.ElementOffset = 0;
- bufferSRVDesc.Buffer.ElementWidth =
- static_cast<unsigned int>(mSize) / dxgiFormatInfo.pixelBytes;
- bufferSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
- bufferSRVDesc.Format = srvFormat;
-
- HRESULT result = device->CreateShaderResourceView(buffer, &bufferSRVDesc, &bufferSRV);
- UNUSED_ASSERTION_VARIABLE(result);
- ASSERT(SUCCEEDED(result));
-
- mBufferResourceViews[srvFormat] = BufferSRVPair(buffer, bufferSRV);
+ return gl::NoError();
+}
- return bufferSRV;
+gl::ErrorOrResult<const d3d11::ShaderResourceView *> Buffer11::getSRV(const gl::Context *context,
+ DXGI_FORMAT srvFormat)
+{
+ BufferStorage *storage = nullptr;
+ ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_PIXEL_UNPACK), storage);
+ NativeStorage *nativeStorage = GetAs<NativeStorage>(storage);
+ return nativeStorage->getSRVForFormat(srvFormat);
}
-gl::Error Buffer11::packPixels(const gl::FramebufferAttachment &readAttachment,
+gl::Error Buffer11::packPixels(const gl::Context *context,
+ const gl::FramebufferAttachment &readAttachment,
const PackPixelsParams &params)
{
- PackStorage *packStorage = getPackStorage();
- BufferStorage *latestStorage = getLatestBufferStorage();
+ PackStorage *packStorage = nullptr;
+ ANGLE_TRY_RESULT(getPackStorage(context), packStorage);
- if (packStorage)
- {
- gl::Error error = packStorage->packPixels(readAttachment, params);
- if (error.isError())
- {
- return error;
- }
- packStorage->setDataRevision(latestStorage ? latestStorage->getDataRevision() + 1 : 1);
- }
+ ASSERT(packStorage);
+ ANGLE_TRY(packStorage->packPixels(context, readAttachment, params));
+ onStorageUpdate(packStorage);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
size_t Buffer11::getTotalCPUBufferMemoryBytes() const
@@ -662,48 +720,56 @@ size_t Buffer11::getTotalCPUBufferMemoryBytes() const
return allocationSize;
}
-Buffer11::BufferStorage *Buffer11::getBufferStorage(BufferUsage usage)
+gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getBufferStorage(const gl::Context *context,
+ BufferUsage usage)
{
ASSERT(0 <= usage && usage < BUFFER_USAGE_COUNT);
BufferStorage *&newStorage = mBufferStorages[usage];
if (!newStorage)
{
- if (usage == BUFFER_USAGE_PIXEL_PACK)
- {
- newStorage = new PackStorage(mRenderer);
- }
- else if (usage == BUFFER_USAGE_SYSTEM_MEMORY)
- {
- newStorage = new SystemMemoryStorage(mRenderer);
- }
- else if (usage == BUFFER_USAGE_EMULATED_INDEXED_VERTEX)
- {
- newStorage = new EmulatedIndexedStorage(mRenderer);
- }
- else
- {
- // buffer is not allocated, create it
- newStorage = new NativeStorage(mRenderer, usage);
- }
+ newStorage = allocateStorage(usage);
}
+ markBufferUsage(usage);
+
// resize buffer
if (newStorage->getSize() < mSize)
{
- if (newStorage->resize(mSize, true).isError())
- {
- // Out of memory error
- return nullptr;
- }
+ ANGLE_TRY(newStorage->resize(context, mSize, true));
}
- updateBufferStorage(newStorage, 0, mSize);
+ ASSERT(newStorage);
+
+ ANGLE_TRY(updateBufferStorage(context, newStorage, 0, mSize));
+ ANGLE_TRY(garbageCollection(context, usage));
return newStorage;
}
-Buffer11::BufferStorage *Buffer11::getConstantBufferRangeStorage(GLintptr offset, GLsizeiptr size)
+Buffer11::BufferStorage *Buffer11::allocateStorage(BufferUsage usage)
+{
+ updateDeallocThreshold(usage);
+ switch (usage)
+ {
+ case BUFFER_USAGE_PIXEL_PACK:
+ return new PackStorage(mRenderer);
+ case BUFFER_USAGE_SYSTEM_MEMORY:
+ return new SystemMemoryStorage(mRenderer);
+ case BUFFER_USAGE_EMULATED_INDEXED_VERTEX:
+ return new EmulatedIndexedStorage(mRenderer);
+ case BUFFER_USAGE_INDEX:
+ case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK:
+ return new NativeStorage(mRenderer, usage, &mDirectBroadcastChannel);
+ default:
+ return new NativeStorage(mRenderer, usage, nullptr);
+ }
+}
+
+gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getConstantBufferRangeStorage(
+ const gl::Context *context,
+ GLintptr offset,
+ GLsizeiptr size)
{
BufferStorage *newStorage;
@@ -714,7 +780,7 @@ Buffer11::BufferStorage *Buffer11::getConstantBufferRangeStorage(GLintptr offset
if (!cacheEntry->storage)
{
- cacheEntry->storage = new NativeStorage(mRenderer, BUFFER_USAGE_UNIFORM);
+ cacheEntry->storage = allocateStorage(BUFFER_USAGE_UNIFORM);
cacheEntry->lruCount = ++mMaxConstantBufferLruCount;
}
@@ -722,6 +788,8 @@ Buffer11::BufferStorage *Buffer11::getConstantBufferRangeStorage(GLintptr offset
newStorage = cacheEntry->storage;
}
+ markBufferUsage(BUFFER_USAGE_UNIFORM);
+
if (newStorage->getSize() < static_cast<size_t>(size))
{
size_t maximumAllowedAdditionalSize = 2 * getSize();
@@ -733,8 +801,7 @@ Buffer11::BufferStorage *Buffer11::getConstantBufferRangeStorage(GLintptr offset
auto iter = std::min_element(std::begin(mConstantBufferRangeStoragesCache),
std::end(mConstantBufferRangeStoragesCache),
[](const ConstantBufferCache::value_type &a,
- const ConstantBufferCache::value_type &b)
- {
+ const ConstantBufferCache::value_type &b) {
return a.second.lruCount < b.second.lruCount;
});
@@ -746,12 +813,7 @@ Buffer11::BufferStorage *Buffer11::getConstantBufferRangeStorage(GLintptr offset
mConstantBufferRangeStoragesCache.erase(iter);
}
- if (newStorage->resize(size, false).isError())
- {
- // Out of memory error
- return nullptr;
- }
-
+ ANGLE_TRY(newStorage->resize(context, size, false));
mConstantBufferStorageAdditionalSize += sizeDelta;
// We don't copy the old data when resizing the constant buffer because the data may be
@@ -760,103 +822,148 @@ Buffer11::BufferStorage *Buffer11::getConstantBufferRangeStorage(GLintptr offset
newStorage->setDataRevision(0);
}
- updateBufferStorage(newStorage, offset, size);
-
+ ANGLE_TRY(updateBufferStorage(context, newStorage, offset, size));
+ ANGLE_TRY(garbageCollection(context, BUFFER_USAGE_UNIFORM));
return newStorage;
}
-void Buffer11::updateBufferStorage(BufferStorage *storage, size_t sourceOffset, size_t storageSize)
+gl::Error Buffer11::updateBufferStorage(const gl::Context *context,
+ BufferStorage *storage,
+ size_t sourceOffset,
+ size_t storageSize)
{
- BufferStorage *latestBuffer = getLatestBufferStorage();
- if (latestBuffer && latestBuffer->getDataRevision() > storage->getDataRevision())
- {
- // Copy through a staging buffer if we're copying from or to a non-staging, mappable
- // buffer storage. This is because we can't map a GPU buffer, and copy CPU
- // data directly. If we're already using a staging buffer we're fine.
- if (latestBuffer->getUsage() != BUFFER_USAGE_STAGING &&
- storage->getUsage() != BUFFER_USAGE_STAGING &&
- (!latestBuffer->isMappable() || !storage->isMappable()))
- {
- NativeStorage *stagingBuffer = getStagingStorage();
+ BufferStorage *latestBuffer = nullptr;
+ ANGLE_TRY_RESULT(getLatestBufferStorage(context), latestBuffer);
- stagingBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0);
- stagingBuffer->setDataRevision(latestBuffer->getDataRevision());
-
- latestBuffer = stagingBuffer;
- }
+ ASSERT(storage);
- // if copyFromStorage returns true, the D3D buffer has been recreated
- // and we should update our serial
- if (storage->copyFromStorage(latestBuffer, sourceOffset, storageSize, 0))
- {
- updateSerial();
- }
- storage->setDataRevision(latestBuffer->getDataRevision());
+ if (!latestBuffer)
+ {
+ onStorageUpdate(storage);
+ return gl::NoError();
}
-}
-Buffer11::BufferStorage *Buffer11::getLatestBufferStorage() const
-{
- // Even though we iterate over all the direct buffers, it is expected that only
- // 1 or 2 will be present.
- BufferStorage *latestStorage = nullptr;
- DataRevision latestRevision = 0;
- for (auto &storage : mBufferStorages)
+ if (latestBuffer->getDataRevision() <= storage->getDataRevision())
{
- if (storage && (!latestStorage || storage->getDataRevision() > latestRevision))
- {
- latestStorage = storage;
- latestRevision = storage->getDataRevision();
- }
+ return gl::NoError();
}
- // resize buffer
- if (latestStorage && latestStorage->getSize() < mSize)
+ // Copy through a staging buffer if we're copying from or to a non-staging, mappable
+ // buffer storage. This is because we can't map a GPU buffer, and copy CPU
+ // data directly. If we're already using a staging buffer we're fine.
+ if (latestBuffer->getUsage() != BUFFER_USAGE_STAGING &&
+ storage->getUsage() != BUFFER_USAGE_STAGING &&
+ (!latestBuffer->isCPUAccessible(GL_MAP_READ_BIT) ||
+ !storage->isCPUAccessible(GL_MAP_WRITE_BIT)))
{
- if (latestStorage->resize(mSize, true).isError())
- {
- // Out of memory error
- return nullptr;
- }
+ NativeStorage *stagingBuffer = nullptr;
+ ANGLE_TRY_RESULT(getStagingStorage(context), stagingBuffer);
+
+ CopyResult copyResult = CopyResult::NOT_RECREATED;
+ ANGLE_TRY_RESULT(
+ stagingBuffer->copyFromStorage(context, latestBuffer, 0, latestBuffer->getSize(), 0),
+ copyResult);
+ onCopyStorage(stagingBuffer, latestBuffer);
+
+ latestBuffer = stagingBuffer;
}
- return latestStorage;
+ CopyResult copyResult = CopyResult::NOT_RECREATED;
+ ANGLE_TRY_RESULT(storage->copyFromStorage(context, latestBuffer, sourceOffset, storageSize, 0),
+ copyResult);
+ // If the D3D buffer has been recreated, we should update our serial.
+ if (copyResult == CopyResult::RECREATED)
+ {
+ updateSerial();
+ }
+ onCopyStorage(storage, latestBuffer);
+ return gl::NoError();
}
-Buffer11::NativeStorage *Buffer11::getStagingStorage()
+gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getLatestBufferStorage(
+ const gl::Context *context) const
{
- BufferStorage *stagingStorage = getBufferStorage(BUFFER_USAGE_STAGING);
-
- if (!stagingStorage)
+ // resize buffer
+ if (mLatestBufferStorage && mLatestBufferStorage->getSize() < mSize)
{
- // Out-of-memory
- return nullptr;
+ ANGLE_TRY(mLatestBufferStorage->resize(context, mSize, true));
}
- return GetAs<NativeStorage>(stagingStorage);
+ return mLatestBufferStorage;
}
-Buffer11::PackStorage *Buffer11::getPackStorage()
+gl::ErrorOrResult<Buffer11::NativeStorage *> Buffer11::getStagingStorage(const gl::Context *context)
{
- BufferStorage *packStorage = getBufferStorage(BUFFER_USAGE_PIXEL_PACK);
-
- if (!packStorage)
- {
- // Out-of-memory
- return nullptr;
- }
+ BufferStorage *stagingStorage = nullptr;
+ ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_STAGING), stagingStorage);
+ return GetAs<NativeStorage>(stagingStorage);
+}
+gl::ErrorOrResult<Buffer11::PackStorage *> Buffer11::getPackStorage(const gl::Context *context)
+{
+ BufferStorage *packStorage = nullptr;
+ ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_PIXEL_PACK), packStorage);
return GetAs<PackStorage>(packStorage);
}
+size_t Buffer11::getSize() const
+{
+ return mSize;
+}
+
bool Buffer11::supportsDirectBinding() const
{
// Do not support direct buffers for dynamic data. The streaming buffer
// offers better performance for data which changes every frame.
- // Check for absence of static buffer interfaces to detect dynamic data.
- return (mStaticVertexBuffer && mStaticIndexBuffer);
+ return (mUsage == D3DBufferUsage::STATIC);
+}
+
+void Buffer11::initializeStaticData(const gl::Context *context)
+{
+ BufferD3D::initializeStaticData(context);
+
+ // Notify when static data changes.
+ mStaticBroadcastChannel.signal(context);
}
+void Buffer11::invalidateStaticData(const gl::Context *context)
+{
+ BufferD3D::invalidateStaticData(context);
+
+ // Notify when static data changes.
+ mStaticBroadcastChannel.signal(context);
+}
+
+OnBufferDataDirtyChannel *Buffer11::getStaticBroadcastChannel()
+{
+ return &mStaticBroadcastChannel;
+}
+
+OnBufferDataDirtyChannel *Buffer11::getDirectBroadcastChannel()
+{
+ return &mDirectBroadcastChannel;
+}
+
+void Buffer11::onCopyStorage(BufferStorage *dest, BufferStorage *source)
+{
+ ASSERT(source && mLatestBufferStorage);
+ dest->setDataRevision(source->getDataRevision());
+
+ // Only update the latest buffer storage if our usage index is lower. See comment in header.
+ if (dest->getUsage() < mLatestBufferStorage->getUsage())
+ {
+ mLatestBufferStorage = dest;
+ }
+}
+
+void Buffer11::onStorageUpdate(BufferStorage *updatedStorage)
+{
+ updatedStorage->setDataRevision(updatedStorage->getDataRevision() + 1);
+ mLatestBufferStorage = updatedStorage;
+}
+
+// Buffer11::BufferStorage implementation
+
Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage)
: mRenderer(renderer), mRevision(0), mUsage(usage), mBufferSize(0)
{
@@ -864,113 +971,118 @@ Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage)
gl::Error Buffer11::BufferStorage::setData(const uint8_t *data, size_t offset, size_t size)
{
- ASSERT(isMappable());
+ ASSERT(isCPUAccessible(GL_MAP_WRITE_BIT));
- uint8_t *writePointer = map(offset, size, GL_MAP_WRITE_BIT);
- if (!writePointer)
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer.");
- }
+ // Uniform storage can have a different internal size than the buffer size. Ensure we don't
+ // overflow.
+ size_t mapSize = std::min(size, mBufferSize - offset);
+
+ uint8_t *writePointer = nullptr;
+ ANGLE_TRY(map(offset, mapSize, GL_MAP_WRITE_BIT, &writePointer));
- memcpy(writePointer, data, size);
+ memcpy(writePointer, data, mapSize);
unmap();
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer, BufferUsage usage)
- : BufferStorage(renderer, usage), mNativeStorage(nullptr)
+// Buffer11::NativeStorage implementation
+
+Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer,
+ BufferUsage usage,
+ const OnBufferDataDirtyChannel *onStorageChanged)
+ : BufferStorage(renderer, usage), mBuffer(), mOnStorageChanged(onStorageChanged)
{
}
Buffer11::NativeStorage::~NativeStorage()
{
- SafeRelease(mNativeStorage);
+ clearSRVs();
}
-// Returns true if it recreates the direct buffer
-bool Buffer11::NativeStorage::copyFromStorage(BufferStorage *source,
- size_t sourceOffset,
- size_t size,
- size_t destOffset)
+bool Buffer11::NativeStorage::isCPUAccessible(GLbitfield access) const
{
- ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ if ((access & GL_MAP_READ_BIT) != 0)
+ {
+ // Read is more exclusive than write mappability.
+ return (mUsage == BUFFER_USAGE_STAGING);
+ }
+ ASSERT((access & GL_MAP_WRITE_BIT) != 0);
+ return (mUsage == BUFFER_USAGE_STAGING || mUsage == BUFFER_USAGE_UNIFORM);
+}
+// Returns true if it recreates the direct buffer
+gl::ErrorOrResult<CopyResult> Buffer11::NativeStorage::copyFromStorage(const gl::Context *context,
+ BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset)
+{
size_t requiredSize = destOffset + size;
- bool createBuffer = !mNativeStorage || mBufferSize < requiredSize;
+ bool createBuffer = !mBuffer.valid() || mBufferSize < requiredSize;
// (Re)initialize D3D buffer if needed
+ bool preserveData = (destOffset > 0);
if (createBuffer)
{
- bool preserveData = (destOffset > 0);
- resize(requiredSize, preserveData);
+ ANGLE_TRY(resize(context, requiredSize, preserveData));
+ }
+
+ size_t clampedSize = size;
+ if (mUsage == BUFFER_USAGE_UNIFORM)
+ {
+ clampedSize = std::min(clampedSize, mBufferSize - destOffset);
}
if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK ||
source->getUsage() == BUFFER_USAGE_SYSTEM_MEMORY)
{
- ASSERT(source->isMappable());
-
- uint8_t *sourcePointer = source->map(sourceOffset, size, GL_MAP_READ_BIT);
-
- D3D11_MAPPED_SUBRESOURCE mappedResource;
- HRESULT hr = context->Map(mNativeStorage, 0, D3D11_MAP_WRITE, 0, &mappedResource);
- ASSERT(SUCCEEDED(hr));
- if (FAILED(hr))
- {
- source->unmap();
- return false;
- }
+ ASSERT(source->isCPUAccessible(GL_MAP_READ_BIT) && isCPUAccessible(GL_MAP_WRITE_BIT));
- uint8_t *destPointer = static_cast<uint8_t *>(mappedResource.pData) + destOffset;
+ // Uniform buffers must be mapped with write/discard.
+ ASSERT(!(preserveData && mUsage == BUFFER_USAGE_UNIFORM));
- // Offset bounds are validated at the API layer
- ASSERT(sourceOffset + size <= destOffset + mBufferSize);
- memcpy(destPointer, sourcePointer, size);
+ uint8_t *sourcePointer = nullptr;
+ ANGLE_TRY(source->map(sourceOffset, clampedSize, GL_MAP_READ_BIT, &sourcePointer));
- context->Unmap(mNativeStorage, 0);
+ auto err = setData(sourcePointer, destOffset, clampedSize);
source->unmap();
+ ANGLE_TRY(err);
}
else
{
D3D11_BOX srcBox;
srcBox.left = static_cast<unsigned int>(sourceOffset);
- srcBox.right = static_cast<unsigned int>(sourceOffset + size);
+ srcBox.right = static_cast<unsigned int>(sourceOffset + clampedSize);
srcBox.top = 0;
srcBox.bottom = 1;
srcBox.front = 0;
srcBox.back = 1;
- ID3D11Buffer *sourceBuffer = GetAs<NativeStorage>(source)->getNativeStorage();
+ const d3d11::Buffer *sourceBuffer = &GetAs<NativeStorage>(source)->getBuffer();
- context->CopySubresourceRegion(mNativeStorage, 0, static_cast<unsigned int>(destOffset), 0,
- 0, sourceBuffer, 0, &srcBox);
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ deviceContext->CopySubresourceRegion(mBuffer.get(), 0,
+ static_cast<unsigned int>(destOffset), 0, 0,
+ sourceBuffer->get(), 0, &srcBox);
}
- return createBuffer;
+ return createBuffer ? CopyResult::RECREATED : CopyResult::NOT_RECREATED;
}
-gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData)
+gl::Error Buffer11::NativeStorage::resize(const gl::Context *context,
+ size_t size,
+ bool preserveData)
{
- ID3D11Device *device = mRenderer->getDevice();
- ID3D11DeviceContext *context = mRenderer->getDeviceContext();
-
D3D11_BUFFER_DESC bufferDesc;
- fillBufferDesc(&bufferDesc, mRenderer, mUsage, static_cast<unsigned int>(size));
-
- ID3D11Buffer *newBuffer;
- HRESULT result = device->CreateBuffer(&bufferDesc, nullptr, &newBuffer);
-
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer, result: 0x%X.",
- result);
- }
+ FillBufferDesc(&bufferDesc, mRenderer, mUsage, static_cast<unsigned int>(size));
- d3d11::SetDebugName(newBuffer, "Buffer11::NativeStorage");
+ d3d11::Buffer newBuffer;
+ ANGLE_TRY(mRenderer->allocateResource(bufferDesc, &newBuffer));
+ newBuffer.setDebugName("Buffer11::NativeStorage");
- if (mNativeStorage && preserveData)
+ if (mBuffer.valid() && preserveData)
{
// We don't call resize if the buffer is big enough already.
ASSERT(mBufferSize <= size);
@@ -983,19 +1095,30 @@ gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData)
srcBox.front = 0;
srcBox.back = 1;
- context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mNativeStorage, 0, &srcBox);
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ deviceContext->CopySubresourceRegion(newBuffer.get(), 0, 0, 0, 0, mBuffer.get(), 0,
+ &srcBox);
}
// No longer need the old buffer
- SafeRelease(mNativeStorage);
- mNativeStorage = newBuffer;
+ mBuffer = std::move(newBuffer);
mBufferSize = bufferDesc.ByteWidth;
- return gl::Error(GL_NO_ERROR);
+ // Free the SRVs.
+ clearSRVs();
+
+ // Notify that the storage has changed.
+ if (mOnStorageChanged)
+ {
+ mOnStorageChanged->signal(context);
+ }
+
+ return gl::NoError();
}
-void Buffer11::NativeStorage::fillBufferDesc(D3D11_BUFFER_DESC *bufferDesc,
+// static
+void Buffer11::NativeStorage::FillBufferDesc(D3D11_BUFFER_DESC *bufferDesc,
Renderer11 *renderer,
BufferUsage usage,
unsigned int bufferSize)
@@ -1030,6 +1153,13 @@ void Buffer11::NativeStorage::fillBufferDesc(D3D11_BUFFER_DESC *bufferDesc,
bufferDesc->CPUAccessFlags = 0;
break;
+ case BUFFER_USAGE_INDIRECT:
+ bufferDesc->MiscFlags = D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS;
+ bufferDesc->Usage = D3D11_USAGE_DEFAULT;
+ bufferDesc->BindFlags = 0;
+ bufferDesc->CPUAccessFlags = 0;
+ break;
+
case BUFFER_USAGE_PIXEL_UNPACK:
bufferDesc->Usage = D3D11_USAGE_DEFAULT;
bufferDesc->BindFlags = D3D11_BIND_SHADER_RESOURCE;
@@ -1044,9 +1174,12 @@ void Buffer11::NativeStorage::fillBufferDesc(D3D11_BUFFER_DESC *bufferDesc,
// Constant buffers must be of a limited size, and aligned to 16 byte boundaries
// For our purposes we ignore any buffer data past the maximum constant buffer size
bufferDesc->ByteWidth = roundUp(bufferDesc->ByteWidth, 16u);
+
+ // Note: it seems that D3D11 allows larger buffers on some platforms, but not all.
+ // (Windows 10 seems to allow larger constant buffers, but not Windows 7)
bufferDesc->ByteWidth =
std::min<UINT>(bufferDesc->ByteWidth,
- static_cast<UINT>(renderer->getRendererCaps().maxUniformBlockSize));
+ static_cast<UINT>(renderer->getNativeCaps().maxUniformBlockSize));
break;
default:
@@ -1054,67 +1187,146 @@ void Buffer11::NativeStorage::fillBufferDesc(D3D11_BUFFER_DESC *bufferDesc,
}
}
-uint8_t *Buffer11::NativeStorage::map(size_t offset, size_t length, GLbitfield access)
+gl::Error Buffer11::NativeStorage::map(size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut)
{
- ASSERT(mUsage == BUFFER_USAGE_STAGING);
+ ASSERT(isCPUAccessible(access));
D3D11_MAPPED_SUBRESOURCE mappedResource;
ID3D11DeviceContext *context = mRenderer->getDeviceContext();
- D3D11_MAP d3dMapType = gl_d3d11::GetD3DMapTypeFromBits(access);
- UINT d3dMapFlag = ((access & GL_MAP_UNSYNCHRONIZED_BIT) != 0 ? D3D11_MAP_FLAG_DO_NOT_WAIT : 0);
+ D3D11_MAP d3dMapType = gl_d3d11::GetD3DMapTypeFromBits(mUsage, access);
+ UINT d3dMapFlag = ((access & GL_MAP_UNSYNCHRONIZED_BIT) != 0 ? D3D11_MAP_FLAG_DO_NOT_WAIT : 0);
- HRESULT result = context->Map(mNativeStorage, 0, d3dMapType, d3dMapFlag, &mappedResource);
+ HRESULT result = context->Map(mBuffer.get(), 0, d3dMapType, d3dMapFlag, &mappedResource);
ASSERT(SUCCEEDED(result));
if (FAILED(result))
{
- return nullptr;
+ return gl::OutOfMemory() << "Failed to map native storage in Buffer11::NativeStorage::map";
}
- return static_cast<uint8_t *>(mappedResource.pData) + offset;
+ ASSERT(mappedResource.pData);
+ *mapPointerOut = static_cast<uint8_t *>(mappedResource.pData) + offset;
+ return gl::NoError();
}
void Buffer11::NativeStorage::unmap()
{
- ASSERT(mUsage == BUFFER_USAGE_STAGING);
+ ASSERT(isCPUAccessible(GL_MAP_WRITE_BIT) || isCPUAccessible(GL_MAP_READ_BIT));
ID3D11DeviceContext *context = mRenderer->getDeviceContext();
- context->Unmap(mNativeStorage, 0);
+ context->Unmap(mBuffer.get(), 0);
+}
+
+gl::ErrorOrResult<const d3d11::ShaderResourceView *> Buffer11::NativeStorage::getSRVForFormat(
+ DXGI_FORMAT srvFormat)
+{
+ auto bufferSRVIt = mBufferResourceViews.find(srvFormat);
+
+ if (bufferSRVIt != mBufferResourceViews.end())
+ {
+ return &bufferSRVIt->second;
+ }
+
+ const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(srvFormat);
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc;
+ bufferSRVDesc.Buffer.ElementOffset = 0;
+ bufferSRVDesc.Buffer.ElementWidth = static_cast<UINT>(mBufferSize) / dxgiFormatInfo.pixelBytes;
+ bufferSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
+ bufferSRVDesc.Format = srvFormat;
+
+ ANGLE_TRY(mRenderer->allocateResource(bufferSRVDesc, mBuffer.get(),
+ &mBufferResourceViews[srvFormat]));
+
+ return &mBufferResourceViews[srvFormat];
+}
+
+void Buffer11::NativeStorage::clearSRVs()
+{
+ mBufferResourceViews.clear();
}
+// Buffer11::EmulatedIndexStorage implementation
+
Buffer11::EmulatedIndexedStorage::EmulatedIndexedStorage(Renderer11 *renderer)
- : BufferStorage(renderer, BUFFER_USAGE_EMULATED_INDEXED_VERTEX), mNativeStorage(nullptr)
+ : BufferStorage(renderer, BUFFER_USAGE_EMULATED_INDEXED_VERTEX), mBuffer()
{
}
Buffer11::EmulatedIndexedStorage::~EmulatedIndexedStorage()
{
- SafeRelease(mNativeStorage);
}
-ID3D11Buffer *Buffer11::EmulatedIndexedStorage::getNativeStorage()
+gl::ErrorOrResult<const d3d11::Buffer *> Buffer11::EmulatedIndexedStorage::getBuffer(
+ SourceIndexData *indexInfo,
+ const TranslatedAttribute &attribute,
+ GLint startVertex)
{
- if (!mNativeStorage)
+ // If a change in the indices applied from the last draw call is detected, then the emulated
+ // indexed buffer needs to be invalidated. After invalidation, the change detected flag should
+ // be cleared to avoid unnecessary recreation of the buffer.
+ if (!mBuffer.valid() || indexInfo->srcIndicesChanged)
+ {
+ mBuffer.reset();
+
+ // Copy the source index data. This ensures that the lifetime of the indices pointer
+ // stays with this storage until the next time we invalidate.
+ size_t indicesDataSize = 0;
+ switch (indexInfo->srcIndexType)
+ {
+ case GL_UNSIGNED_INT:
+ indicesDataSize = sizeof(GLuint) * indexInfo->srcCount;
+ break;
+ case GL_UNSIGNED_SHORT:
+ indicesDataSize = sizeof(GLushort) * indexInfo->srcCount;
+ break;
+ case GL_UNSIGNED_BYTE:
+ indicesDataSize = sizeof(GLubyte) * indexInfo->srcCount;
+ break;
+ default:
+ indicesDataSize = sizeof(GLushort) * indexInfo->srcCount;
+ break;
+ }
+
+ if (!mIndicesMemoryBuffer.resize(indicesDataSize))
+ {
+ return gl::OutOfMemory() << "Error resizing index memory buffer in "
+ "Buffer11::EmulatedIndexedStorage::getBuffer";
+ }
+
+ memcpy(mIndicesMemoryBuffer.data(), indexInfo->srcIndices, indicesDataSize);
+
+ indexInfo->srcIndicesChanged = false;
+ }
+
+ if (!mBuffer.valid())
{
+ unsigned int offset = 0;
+ ANGLE_TRY_RESULT(attribute.computeOffset(startVertex), offset);
+
// Expand the memory storage upon request and cache the results.
unsigned int expandedDataSize =
- static_cast<unsigned int>((mIndexInfo.srcCount * mAttributeStride) + mAttributeOffset);
- MemoryBuffer expandedData;
+ static_cast<unsigned int>((indexInfo->srcCount * attribute.stride) + offset);
+ angle::MemoryBuffer expandedData;
if (!expandedData.resize(expandedDataSize))
{
- return nullptr;
+ return gl::OutOfMemory()
+ << "Error resizing buffer in Buffer11::EmulatedIndexedStorage::getBuffer";
}
// Clear the contents of the allocated buffer
ZeroMemory(expandedData.data(), expandedDataSize);
uint8_t *curr = expandedData.data();
- const uint8_t *ptr = static_cast<const uint8_t *>(mIndexInfo.srcIndices);
+ const uint8_t *ptr = static_cast<const uint8_t *>(indexInfo->srcIndices);
// Ensure that we start in the correct place for the emulated data copy operation to
// maintain offset behaviors.
- curr += mAttributeOffset;
+ curr += offset;
ReadIndexValueFunction readIndexValue = ReadIndexValueFromIndices<GLushort>;
- switch (mIndexInfo.srcIndexType)
+ switch (indexInfo->srcIndexType)
{
case GL_UNSIGNED_INT:
readIndexValue = ReadIndexValueFromIndices<GLuint>;
@@ -1128,17 +1340,15 @@ ID3D11Buffer *Buffer11::EmulatedIndexedStorage::getNativeStorage()
}
// Iterate over the cached index data and copy entries indicated into the emulated buffer.
- for (GLuint i = 0; i < mIndexInfo.srcCount; i++)
+ for (GLuint i = 0; i < indexInfo->srcCount; i++)
{
GLuint idx = readIndexValue(ptr, i);
- memcpy(curr, mMemoryBuffer.data() + (mAttributeStride * idx), mAttributeStride);
- curr += mAttributeStride;
+ memcpy(curr, mMemoryBuffer.data() + (attribute.stride * idx), attribute.stride);
+ curr += attribute.stride;
}
// Finally, initialize the emulated indexed native storage object with the newly copied data
// and free the temporary buffers used.
- ID3D11Device *device = mRenderer->getDevice();
-
D3D11_BUFFER_DESC bufferDesc;
bufferDesc.ByteWidth = expandedDataSize;
bufferDesc.MiscFlags = 0;
@@ -1149,99 +1359,53 @@ ID3D11Buffer *Buffer11::EmulatedIndexedStorage::getNativeStorage()
D3D11_SUBRESOURCE_DATA subResourceData = {expandedData.data(), 0, 0};
- HRESULT result = device->CreateBuffer(&bufferDesc, &subResourceData, &mNativeStorage);
- if (FAILED(result))
- {
- ERR("Could not create emulated index data buffer: %08lX", result);
- return nullptr;
- }
- d3d11::SetDebugName(mNativeStorage, "Buffer11::EmulatedIndexedStorage");
+ ANGLE_TRY(mRenderer->allocateResource(bufferDesc, &subResourceData, &mBuffer));
+ mBuffer.setDebugName("Buffer11::EmulatedIndexedStorage");
}
- return mNativeStorage;
-}
-
-bool Buffer11::EmulatedIndexedStorage::update(SourceIndexData *indexInfo,
- const TranslatedAttribute *attribute)
-{
- // If a change in the indices applied from the last draw call is detected, then the emulated
- // indexed buffer needs to be invalidated. After invalidation, the change detected flag should
- // be cleared to avoid unnecessary recreation of the buffer.
- if (mNativeStorage == nullptr || indexInfo->srcIndicesChanged)
- {
- SafeRelease(mNativeStorage);
-
- // Copy attribute offset and stride information
- mAttributeStride = attribute->stride;
- mAttributeOffset = attribute->offset;
-
- // Copy the source index data. This ensures that the lifetime of the indices pointer
- // stays with this storage until the next time we invalidate.
- size_t indicesDataSize = 0;
- switch (indexInfo->srcIndexType)
- {
- case GL_UNSIGNED_INT:
- indicesDataSize = sizeof(GLuint) * indexInfo->srcCount;
- break;
- case GL_UNSIGNED_SHORT:
- indicesDataSize = sizeof(GLushort) * indexInfo->srcCount;
- break;
- case GL_UNSIGNED_BYTE:
- indicesDataSize = sizeof(GLubyte) * indexInfo->srcCount;
- break;
- default:
- indicesDataSize = sizeof(GLushort) * indexInfo->srcCount;
- break;
- }
-
- if (!mIndicesMemoryBuffer.resize(indicesDataSize))
- {
- return false;
- }
-
- memcpy(mIndicesMemoryBuffer.data(), indexInfo->srcIndices, indicesDataSize);
-
- // Copy the source index data description and update the srcIndices pointer to point
- // to our cached index data.
- mIndexInfo = *indexInfo;
- mIndexInfo.srcIndices = mIndicesMemoryBuffer.data();
-
- indexInfo->srcIndicesChanged = false;
- }
- return true;
+ return &mBuffer;
}
-bool Buffer11::EmulatedIndexedStorage::copyFromStorage(BufferStorage *source,
- size_t sourceOffset,
- size_t size,
- size_t destOffset)
+gl::ErrorOrResult<CopyResult> Buffer11::EmulatedIndexedStorage::copyFromStorage(
+ const gl::Context *context,
+ BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset)
{
- ASSERT(source->isMappable());
- const uint8_t *sourceData = source->map(sourceOffset, size, GL_MAP_READ_BIT);
+ ASSERT(source->isCPUAccessible(GL_MAP_READ_BIT));
+ uint8_t *sourceData = nullptr;
+ ANGLE_TRY(source->map(sourceOffset, size, GL_MAP_READ_BIT, &sourceData));
ASSERT(destOffset + size <= mMemoryBuffer.size());
memcpy(mMemoryBuffer.data() + destOffset, sourceData, size);
source->unmap();
- return true;
+ return CopyResult::RECREATED;
}
-gl::Error Buffer11::EmulatedIndexedStorage::resize(size_t size, bool preserveData)
+gl::Error Buffer11::EmulatedIndexedStorage::resize(const gl::Context *context,
+ size_t size,
+ bool preserveData)
{
if (mMemoryBuffer.size() < size)
{
if (!mMemoryBuffer.resize(size))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize EmulatedIndexedStorage");
+ return gl::OutOfMemory() << "Failed to resize EmulatedIndexedStorage";
}
mBufferSize = size;
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-uint8_t *Buffer11::EmulatedIndexedStorage::map(size_t offset, size_t length, GLbitfield access)
+gl::Error Buffer11::EmulatedIndexedStorage::map(size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut)
{
ASSERT(!mMemoryBuffer.empty() && offset + length <= mMemoryBuffer.size());
- return mMemoryBuffer.data() + offset;
+ *mapPointerOut = mMemoryBuffer.data() + offset;
+ return gl::NoError();
}
void Buffer11::EmulatedIndexedStorage::unmap()
@@ -1249,6 +1413,8 @@ void Buffer11::EmulatedIndexedStorage::unmap()
// No-op
}
+// Buffer11::PackStorage implementation
+
Buffer11::PackStorage::PackStorage(Renderer11 *renderer)
: BufferStorage(renderer, BUFFER_USAGE_PIXEL_PACK), mStagingTexture(), mDataModified(false)
{
@@ -1258,32 +1424,42 @@ Buffer11::PackStorage::~PackStorage()
{
}
-bool Buffer11::PackStorage::copyFromStorage(BufferStorage *source,
- size_t sourceOffset,
- size_t size,
- size_t destOffset)
+gl::ErrorOrResult<CopyResult> Buffer11::PackStorage::copyFromStorage(const gl::Context *context,
+ BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset)
{
- // We copy through a staging buffer when drawing with a pack buffer,
- // or for other cases where we access the pack buffer
- UNREACHABLE();
- return false;
+ ANGLE_TRY(flushQueuedPackCommand());
+
+ // For all use cases of pack buffers, we must copy through a readable buffer.
+ ASSERT(source->isCPUAccessible(GL_MAP_READ_BIT));
+ uint8_t *sourceData = nullptr;
+ ANGLE_TRY(source->map(sourceOffset, size, GL_MAP_READ_BIT, &sourceData));
+ ASSERT(destOffset + size <= mMemoryBuffer.size());
+ memcpy(mMemoryBuffer.data() + destOffset, sourceData, size);
+ source->unmap();
+ return CopyResult::NOT_RECREATED;
}
-gl::Error Buffer11::PackStorage::resize(size_t size, bool preserveData)
+gl::Error Buffer11::PackStorage::resize(const gl::Context *context, size_t size, bool preserveData)
{
if (size != mBufferSize)
{
if (!mMemoryBuffer.resize(size))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal buffer storage.");
+ return gl::OutOfMemory() << "Failed to resize internal buffer storage.";
}
mBufferSize = size;
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-uint8_t *Buffer11::PackStorage::map(size_t offset, size_t length, GLbitfield access)
+gl::Error Buffer11::PackStorage::map(size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut)
{
ASSERT(offset + length <= getSize());
// TODO: fast path
@@ -1291,15 +1467,12 @@ uint8_t *Buffer11::PackStorage::map(size_t offset, size_t length, GLbitfield acc
// and if D3D packs the staging texture memory identically to how we would fill
// the pack buffer according to the current pack state.
- gl::Error error = flushQueuedPackCommand();
- if (error.isError())
- {
- return nullptr;
- }
+ ANGLE_TRY(flushQueuedPackCommand());
mDataModified = (mDataModified || (access & GL_MAP_WRITE_BIT) != 0);
- return mMemoryBuffer.data() + offset;
+ *mapPointerOut = mMemoryBuffer.data() + offset;
+ return gl::NoError();
}
void Buffer11::PackStorage::unmap()
@@ -1307,42 +1480,29 @@ void Buffer11::PackStorage::unmap()
// No-op
}
-gl::Error Buffer11::PackStorage::packPixels(const gl::FramebufferAttachment &readAttachment,
+gl::Error Buffer11::PackStorage::packPixels(const gl::Context *context,
+ const gl::FramebufferAttachment &readAttachment,
const PackPixelsParams &params)
{
- gl::Error error = flushQueuedPackCommand();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(flushQueuedPackCommand());
RenderTarget11 *renderTarget = nullptr;
- error = readAttachment.getRenderTarget(&renderTarget);
- if (error.isError())
- {
- return error;
- }
-
- ID3D11Resource *renderTargetResource = renderTarget->getTexture();
- ASSERT(renderTargetResource);
+ ANGLE_TRY(readAttachment.getRenderTarget(context, &renderTarget));
+ const TextureHelper11 &srcTexture = renderTarget->getTexture();
+ ASSERT(srcTexture.valid());
unsigned int srcSubresource = renderTarget->getSubresourceIndex();
- TextureHelper11 srcTexture = TextureHelper11::MakeAndReference(renderTargetResource);
mQueuedPackCommand.reset(new PackPixelsParams(params));
gl::Extents srcTextureSize(params.area.width, params.area.height, 1);
- if (!mStagingTexture.getResource() || mStagingTexture.getFormat() != srcTexture.getFormat() ||
+ if (!mStagingTexture.get() || mStagingTexture.getFormat() != srcTexture.getFormat() ||
mStagingTexture.getExtents() != srcTextureSize)
{
- auto textureOrError =
- CreateStagingTexture(srcTexture.getTextureType(), srcTexture.getFormat(),
- srcTextureSize, mRenderer->getDevice());
- if (textureOrError.isError())
- {
- return textureOrError.getError();
- }
- mStagingTexture = std::move(textureOrError.getResult());
+ ANGLE_TRY_RESULT(
+ mRenderer->createStagingTexture(srcTexture.getTextureType(), srcTexture.getFormatSet(),
+ srcTextureSize, StagingAccess::READ),
+ mStagingTexture);
}
// ReadPixels from multisampled FBOs isn't supported in current GL
@@ -1357,17 +1517,17 @@ gl::Error Buffer11::PackStorage::packPixels(const gl::FramebufferAttachment &rea
// Select the correct layer from a 3D attachment
srcBox.front = 0;
- if (mStagingTexture.getTextureType() == GL_TEXTURE_3D)
+ if (mStagingTexture.is3D())
{
srcBox.front = static_cast<UINT>(readAttachment.layer());
}
srcBox.back = srcBox.front + 1;
// Asynchronous copy
- immediateContext->CopySubresourceRegion(mStagingTexture.getResource(), 0, 0, 0, 0,
- srcTexture.getResource(), srcSubresource, &srcBox);
+ immediateContext->CopySubresourceRegion(mStagingTexture.get(), 0, 0, 0, 0, srcTexture.get(),
+ srcSubresource, &srcBox);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error Buffer11::PackStorage::flushQueuedPackCommand()
@@ -1376,58 +1536,65 @@ gl::Error Buffer11::PackStorage::flushQueuedPackCommand()
if (mQueuedPackCommand)
{
- gl::Error error =
- mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, mMemoryBuffer.data());
+ ANGLE_TRY(
+ mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, mMemoryBuffer.data()));
mQueuedPackCommand.reset(nullptr);
- if (error.isError())
- {
- return error;
- }
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
+// Buffer11::SystemMemoryStorage implementation
+
Buffer11::SystemMemoryStorage::SystemMemoryStorage(Renderer11 *renderer)
: Buffer11::BufferStorage(renderer, BUFFER_USAGE_SYSTEM_MEMORY)
{
}
-bool Buffer11::SystemMemoryStorage::copyFromStorage(BufferStorage *source,
- size_t sourceOffset,
- size_t size,
- size_t destOffset)
+gl::ErrorOrResult<CopyResult> Buffer11::SystemMemoryStorage::copyFromStorage(
+ const gl::Context *context,
+ BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset)
{
- ASSERT(source->isMappable());
- const uint8_t *sourceData = source->map(sourceOffset, size, GL_MAP_READ_BIT);
+ ASSERT(source->isCPUAccessible(GL_MAP_READ_BIT));
+ uint8_t *sourceData = nullptr;
+ ANGLE_TRY(source->map(sourceOffset, size, GL_MAP_READ_BIT, &sourceData));
ASSERT(destOffset + size <= mSystemCopy.size());
memcpy(mSystemCopy.data() + destOffset, sourceData, size);
source->unmap();
- return true;
+ return CopyResult::RECREATED;
}
-gl::Error Buffer11::SystemMemoryStorage::resize(size_t size, bool preserveData)
+gl::Error Buffer11::SystemMemoryStorage::resize(const gl::Context *context,
+ size_t size,
+ bool preserveData)
{
if (mSystemCopy.size() < size)
{
if (!mSystemCopy.resize(size))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize SystemMemoryStorage");
+ return gl::OutOfMemory() << "Failed to resize SystemMemoryStorage";
}
mBufferSize = size;
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-uint8_t *Buffer11::SystemMemoryStorage::map(size_t offset, size_t length, GLbitfield access)
+gl::Error Buffer11::SystemMemoryStorage::map(size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut)
{
ASSERT(!mSystemCopy.empty() && offset + length <= mSystemCopy.size());
- return mSystemCopy.data() + offset;
+ *mapPointerOut = mSystemCopy.data() + offset;
+ return gl::NoError();
}
void Buffer11::SystemMemoryStorage::unmap()
{
// No-op
}
-}
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h
index a748db57ae..ddbeeb90d2 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h
@@ -9,10 +9,12 @@
#ifndef LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_
#define LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_
+#include <array>
#include <map>
#include "libANGLE/angletypes.h"
#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
namespace gl
{
@@ -21,69 +23,92 @@ class FramebufferAttachment;
namespace rx
{
+struct PackPixelsParams;
class Renderer11;
struct SourceIndexData;
struct TranslatedAttribute;
+// The order of this enum governs priority of 'getLatestBufferStorage'.
enum BufferUsage
{
+ BUFFER_USAGE_SYSTEM_MEMORY,
BUFFER_USAGE_STAGING,
BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK,
BUFFER_USAGE_INDEX,
+ // TODO: possibly share this buffer type with shader storage buffers.
+ BUFFER_USAGE_INDIRECT,
BUFFER_USAGE_PIXEL_UNPACK,
BUFFER_USAGE_PIXEL_PACK,
BUFFER_USAGE_UNIFORM,
- BUFFER_USAGE_SYSTEM_MEMORY,
BUFFER_USAGE_EMULATED_INDEXED_VERTEX,
BUFFER_USAGE_COUNT,
};
-struct PackPixelsParams
-{
- PackPixelsParams();
- PackPixelsParams(const gl::Rectangle &area, GLenum format, GLenum type, GLuint outputPitch,
- const gl::PixelPackState &pack, ptrdiff_t offset);
-
- gl::Rectangle area;
- GLenum format;
- GLenum type;
- GLuint outputPitch;
- gl::Buffer *packBuffer;
- gl::PixelPackState pack;
- ptrdiff_t offset;
-};
-
typedef size_t DataRevision;
class Buffer11 : public BufferD3D
{
public:
- Buffer11(Renderer11 *renderer);
- virtual ~Buffer11();
-
- ID3D11Buffer *getBuffer(BufferUsage usage);
- ID3D11Buffer *getEmulatedIndexedBuffer(SourceIndexData *indexInfo, const TranslatedAttribute *attribute);
- ID3D11Buffer *getConstantBufferRange(GLintptr offset, GLsizeiptr size);
- ID3D11ShaderResourceView *getSRV(DXGI_FORMAT srvFormat);
- bool isMapped() const { return mMappedStorage != NULL; }
- gl::Error packPixels(const gl::FramebufferAttachment &readAttachment,
+ Buffer11(const gl::BufferState &state, Renderer11 *renderer);
+ ~Buffer11() override;
+
+ gl::ErrorOrResult<ID3D11Buffer *> getBuffer(const gl::Context *context, BufferUsage usage);
+ gl::ErrorOrResult<ID3D11Buffer *> getEmulatedIndexedBuffer(const gl::Context *context,
+ SourceIndexData *indexInfo,
+ const TranslatedAttribute &attribute,
+ GLint startVertex);
+ gl::Error getConstantBufferRange(const gl::Context *context,
+ GLintptr offset,
+ GLsizeiptr size,
+ const d3d11::Buffer **bufferOut,
+ UINT *firstConstantOut,
+ UINT *numConstantsOut);
+ gl::ErrorOrResult<const d3d11::ShaderResourceView *> getSRV(const gl::Context *context,
+ DXGI_FORMAT srvFormat);
+ bool isMapped() const { return mMappedStorage != nullptr; }
+ gl::Error packPixels(const gl::Context *context,
+ const gl::FramebufferAttachment &readAttachment,
const PackPixelsParams &params);
size_t getTotalCPUBufferMemoryBytes() const;
// BufferD3D implementation
- virtual size_t getSize() const { return mSize; }
- virtual bool supportsDirectBinding() const;
- gl::Error getData(const uint8_t **outData) override;
+ size_t getSize() const override;
+ bool supportsDirectBinding() const override;
+ gl::Error getData(const gl::Context *context, const uint8_t **outData) override;
+ void initializeStaticData(const gl::Context *context) override;
+ void invalidateStaticData(const gl::Context *context) override;
// BufferImpl implementation
- virtual gl::Error setData(const void* data, size_t size, GLenum usage);
- virtual gl::Error setSubData(const void* data, size_t size, size_t offset);
- virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size);
- virtual gl::Error map(GLenum access, GLvoid **mapPtr);
- virtual gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr);
- virtual gl::Error unmap(GLboolean *result);
- virtual void markTransformFeedbackUsage();
+ gl::Error setData(const gl::Context *context,
+ gl::BufferBinding target,
+ const void *data,
+ size_t size,
+ gl::BufferUsage usage) override;
+ gl::Error setSubData(const gl::Context *context,
+ gl::BufferBinding target,
+ const void *data,
+ size_t size,
+ size_t offset) override;
+ gl::Error copySubData(const gl::Context *context,
+ BufferImpl *source,
+ GLintptr sourceOffset,
+ GLintptr destOffset,
+ GLsizeiptr size) override;
+ gl::Error map(const gl::Context *context, GLenum access, void **mapPtr) override;
+ gl::Error mapRange(const gl::Context *context,
+ size_t offset,
+ size_t length,
+ GLbitfield access,
+ void **mapPtr) override;
+ gl::Error unmap(const gl::Context *context, GLboolean *result) override;
+ gl::Error markTransformFeedbackUsage(const gl::Context *context) override;
+
+ // We use two set of dirty events. Static buffers are marked dirty whenever
+ // data changes, because they must be re-translated. Direct buffers only need to be
+ // updated when the underlying ID3D11Buffer pointer changes - hopefully far less often.
+ OnBufferDataDirtyChannel *getStaticBroadcastChannel();
+ OnBufferDataDirtyChannel *getDirectBroadcastChannel();
private:
class BufferStorage;
@@ -92,21 +117,61 @@ class Buffer11 : public BufferD3D
class PackStorage;
class SystemMemoryStorage;
- Renderer11 *mRenderer;
- size_t mSize;
-
- BufferStorage *mMappedStorage;
-
- std::vector<BufferStorage*> mBufferStorages;
-
struct ConstantBufferCacheEntry
{
- ConstantBufferCacheEntry() : storage(nullptr), lruCount(0) { }
+ ConstantBufferCacheEntry() : storage(nullptr), lruCount(0) {}
BufferStorage *storage;
unsigned int lruCount;
};
+ void markBufferUsage(BufferUsage usage);
+ gl::Error garbageCollection(const gl::Context *context, BufferUsage currentUsage);
+ gl::ErrorOrResult<NativeStorage *> getStagingStorage(const gl::Context *context);
+ gl::ErrorOrResult<PackStorage *> getPackStorage(const gl::Context *context);
+ gl::ErrorOrResult<SystemMemoryStorage *> getSystemMemoryStorage(const gl::Context *context);
+
+ gl::Error updateBufferStorage(const gl::Context *context,
+ BufferStorage *storage,
+ size_t sourceOffset,
+ size_t storageSize);
+ gl::ErrorOrResult<BufferStorage *> getBufferStorage(const gl::Context *context,
+ BufferUsage usage);
+ gl::ErrorOrResult<BufferStorage *> getLatestBufferStorage(const gl::Context *context) const;
+
+ gl::ErrorOrResult<BufferStorage *> getConstantBufferRangeStorage(const gl::Context *context,
+ GLintptr offset,
+ GLsizeiptr size);
+
+ BufferStorage *allocateStorage(BufferUsage usage);
+ void updateDeallocThreshold(BufferUsage usage);
+
+ // Free the storage if we decide it isn't being used very often.
+ gl::Error checkForDeallocation(const gl::Context *context, BufferUsage usage);
+
+ // For some cases of uniform buffer storage, we can't deallocate system memory storage.
+ bool canDeallocateSystemMemory() const;
+
+ // Updates data revisions and latest storage.
+ void onCopyStorage(BufferStorage *dest, BufferStorage *source);
+ void onStorageUpdate(BufferStorage *updatedStorage);
+
+ Renderer11 *mRenderer;
+ size_t mSize;
+
+ BufferStorage *mMappedStorage;
+
+ // Buffer storages are sorted by usage. It's important that the latest buffer storage picks
+ // the lowest usage in the case where two storages are tied on data revision - this ensures
+ // we never do anything dangerous like map a uniform buffer over a staging or system memory
+ // copy.
+ std::array<BufferStorage *, BUFFER_USAGE_COUNT> mBufferStorages;
+ BufferStorage *mLatestBufferStorage;
+
+ // These two arrays are used to track when to free unused storage.
+ std::array<unsigned int, BUFFER_USAGE_COUNT> mDeallocThresholds;
+ std::array<unsigned int, BUFFER_USAGE_COUNT> mIdleness;
+
// Cache of D3D11 constant buffer for specific ranges of buffer data.
// This is used to emulate UBO ranges on 11.0 devices.
// Constant buffers are indexed by there start offset.
@@ -115,25 +180,10 @@ class Buffer11 : public BufferD3D
size_t mConstantBufferStorageAdditionalSize;
unsigned int mMaxConstantBufferLruCount;
- typedef std::pair<ID3D11Buffer *, ID3D11ShaderResourceView *> BufferSRVPair;
- std::map<DXGI_FORMAT, BufferSRVPair> mBufferResourceViews;
-
- unsigned int mReadUsageCount;
-
- void markBufferUsage();
- NativeStorage *getStagingStorage();
- PackStorage *getPackStorage();
- gl::Error getSystemMemoryStorage(SystemMemoryStorage **storageOut);
-
- void updateBufferStorage(BufferStorage *storage, size_t sourceOffset, size_t storageSize);
- BufferStorage *getBufferStorage(BufferUsage usage);
- BufferStorage *getLatestBufferStorage() const;
-
- BufferStorage *getConstantBufferRangeStorage(GLintptr offset, GLsizeiptr size);
-
- void invalidateEmulatedIndexedBuffer();
+ OnBufferDataDirtyChannel mStaticBroadcastChannel;
+ OnBufferDataDirtyChannel mDirectBroadcastChannel;
};
-}
+} // namespace rx
-#endif // LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
index cd95c65d1c..f9dda0aeb4 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
@@ -1,4 +1,4 @@
-//
+
// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -20,624 +20,814 @@
#include "third_party/trace_event/trace_event.h"
// Precompiled shaders
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11vs.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11_fl9vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11multiviewgs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11multiviewvs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/cleardepth11ps.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h"
-
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11vs.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h"
-
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11vs.h"
-#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps1.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps2.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps3.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps4.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps5.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps6.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps7.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps8.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps1.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps2.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps3.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps4.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps5.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps6.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps7.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps8.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps1.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps2.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps3.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps4.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps5.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps6.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps7.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps8.h"
namespace rx
{
+namespace
+{
+constexpr uint32_t g_ConstantBufferSize = sizeof(RtvDsvClearInfo<float>);
+constexpr uint32_t g_VertexSize = sizeof(d3d11::PositionVertex);
+
+// Updates color, depth and alpha components of cached CB if necessary.
+// Returns true if any constants are updated, false otherwise.
template <typename T>
-static void ApplyVertices(const gl::Extents &framebufferSize, const gl::Rectangle *scissor, const gl::Color<T> &color, float depth, void *buffer)
+bool UpdateDataCache(RtvDsvClearInfo<T> *dataCache,
+ const gl::Color<T> &color,
+ const float *zValue,
+ const uint32_t numRtvs,
+ const uint8_t writeMask)
{
- d3d11::PositionDepthColorVertex<T> *vertices = reinterpret_cast<d3d11::PositionDepthColorVertex<T>*>(buffer);
+ bool cacheDirty = false;
+
+ if (numRtvs > 0)
+ {
+ const bool writeRGB = (writeMask & ~D3D11_COLOR_WRITE_ENABLE_ALPHA) != 0;
+ if (writeRGB && memcmp(&dataCache->r, &color.red, sizeof(T) * 3) != 0)
+ {
+ dataCache->r = color.red;
+ dataCache->g = color.green;
+ dataCache->b = color.blue;
+ cacheDirty = true;
+ }
- float depthClear = gl::clamp01(depth);
- float left = -1.0f;
- float right = 1.0f;
- float top = -1.0f;
- float bottom = 1.0f;
+ const bool writeAlpha = (writeMask & D3D11_COLOR_WRITE_ENABLE_ALPHA) != 0;
+ if (writeAlpha && (dataCache->a != color.alpha))
+ {
+ dataCache->a = color.alpha;
+ cacheDirty = true;
+ }
+ }
- // Clip the quad coordinates to the scissor if needed
- if (scissor != nullptr)
+ if (zValue)
{
- left = std::max(left, (scissor->x / float(framebufferSize.width)) * 2.0f - 1.0f);
- right = std::min(right, ((scissor->x + scissor->width) / float(framebufferSize.width)) * 2.0f - 1.0f);
- top = std::max(top, ((framebufferSize.height - scissor->y - scissor->height) / float(framebufferSize.height)) * 2.0f - 1.0f);
- bottom = std::min(bottom, ((framebufferSize.height - scissor->y) / float(framebufferSize.height)) * 2.0f - 1.0f);
+ const float clampedZValue = gl::clamp01(*zValue);
+
+ if (clampedZValue != dataCache->z)
+ {
+ dataCache->z = clampedZValue;
+ cacheDirty = true;
+ }
}
- d3d11::SetPositionDepthColorVertex<T>(vertices + 0, left, bottom, depthClear, color);
- d3d11::SetPositionDepthColorVertex<T>(vertices + 1, left, top, depthClear, color);
- d3d11::SetPositionDepthColorVertex<T>(vertices + 2, right, bottom, depthClear, color);
- d3d11::SetPositionDepthColorVertex<T>(vertices + 3, right, top, depthClear, color);
+ return cacheDirty;
}
-Clear11::ClearShader::ClearShader(DXGI_FORMAT colorType,
- const char *inputLayoutName,
- const BYTE *vsByteCode,
- size_t vsSize,
- const char *vsDebugName,
- const BYTE *psByteCode,
- size_t psSize,
- const char *psDebugName)
- : inputLayout(nullptr),
- vertexShader(vsByteCode, vsSize, vsDebugName),
- pixelShader(psByteCode, psSize, psDebugName)
+bool AllOffsetsAreNonNegative(const std::vector<gl::Offset> &viewportOffsets)
{
- D3D11_INPUT_ELEMENT_DESC quadLayout[] =
+ for (size_t i = 0u; i < viewportOffsets.size(); ++i)
{
- { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
- { "COLOR", 0, colorType, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
- };
-
- inputLayout = new d3d11::LazyInputLayout(quadLayout, 2, vsByteCode, vsSize, inputLayoutName);
+ const auto &offset = viewportOffsets[i];
+ if (offset.x < 0 || offset.y < 0)
+ {
+ return false;
+ }
+ }
+ return true;
}
-
-Clear11::ClearShader::~ClearShader()
+} // anonymous namespace
+
+#define CLEARPS(Index) \
+ d3d11::LazyShader<ID3D11PixelShader>(g_PS_Clear##Index, ArraySize(g_PS_Clear##Index), \
+ "Clear11 PS " ANGLE_STRINGIFY(Index))
+
+Clear11::ShaderManager::ShaderManager()
+ : mIl9(),
+ mVs9(g_VS_Clear_FL9, ArraySize(g_VS_Clear_FL9), "Clear11 VS FL9"),
+ mPsFloat9(g_PS_ClearFloat_FL9, ArraySize(g_PS_ClearFloat_FL9), "Clear11 PS FloatFL9"),
+ mVs(g_VS_Clear, ArraySize(g_VS_Clear), "Clear11 VS"),
+ mVsMultiview(g_VS_Multiview_Clear, ArraySize(g_VS_Multiview_Clear), "Clear11 VS Multiview"),
+ mGsMultiview(g_GS_Multiview_Clear, ArraySize(g_GS_Multiview_Clear), "Clear11 GS Multiview"),
+ mPsDepth(g_PS_ClearDepth, ArraySize(g_PS_ClearDepth), "Clear11 PS Depth"),
+ mPsFloat{{CLEARPS(Float1), CLEARPS(Float2), CLEARPS(Float3), CLEARPS(Float4), CLEARPS(Float5),
+ CLEARPS(Float6), CLEARPS(Float7), CLEARPS(Float8)}},
+ mPsUInt{{CLEARPS(Uint1), CLEARPS(Uint2), CLEARPS(Uint3), CLEARPS(Uint4), CLEARPS(Uint5),
+ CLEARPS(Uint6), CLEARPS(Uint7), CLEARPS(Uint8)}},
+ mPsSInt{{CLEARPS(Sint1), CLEARPS(Sint2), CLEARPS(Sint3), CLEARPS(Sint4), CLEARPS(Sint5),
+ CLEARPS(Sint6), CLEARPS(Sint7), CLEARPS(Sint8)}}
{
- SafeDelete(inputLayout);
- vertexShader.release();
- pixelShader.release();
}
-Clear11::Clear11(Renderer11 *renderer)
- : mRenderer(renderer),
- mClearBlendStates(StructLessThan<ClearBlendInfo>),
- mFloatClearShader(nullptr),
- mUintClearShader(nullptr),
- mIntClearShader(nullptr),
- mClearDepthStencilStates(StructLessThan<ClearDepthStencilInfo>),
- mVertexBuffer(nullptr),
- mRasterizerState(nullptr)
+#undef CLEARPS
+
+Clear11::ShaderManager::~ShaderManager()
{
- TRACE_EVENT0("gpu.angle", "Clear11::Clear11");
+}
- HRESULT result;
- ID3D11Device *device = renderer->getDevice();
+gl::Error Clear11::ShaderManager::getShadersAndLayout(Renderer11 *renderer,
+ const INT clearType,
+ const uint32_t numRTs,
+ const bool hasLayeredLayout,
+ const d3d11::InputLayout **il,
+ const d3d11::VertexShader **vs,
+ const d3d11::GeometryShader **gs,
+ const d3d11::PixelShader **ps)
+{
+ if (renderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
+ {
+ ASSERT(clearType == GL_FLOAT);
- D3D11_BUFFER_DESC vbDesc;
- vbDesc.ByteWidth = sizeof(d3d11::PositionDepthColorVertex<float>) * 4;
- vbDesc.Usage = D3D11_USAGE_DYNAMIC;
- vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
- vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
- vbDesc.MiscFlags = 0;
- vbDesc.StructureByteStride = 0;
+ ANGLE_TRY(mVs9.resolve(renderer));
+ ANGLE_TRY(mPsFloat9.resolve(renderer));
- result = device->CreateBuffer(&vbDesc, nullptr, &mVertexBuffer);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mVertexBuffer, "Clear11 masked clear vertex buffer");
+ if (!mIl9.valid())
+ {
+ const D3D11_INPUT_ELEMENT_DESC ilDesc[] = {
+ {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}};
- D3D11_RASTERIZER_DESC rsDesc;
- rsDesc.FillMode = D3D11_FILL_SOLID;
- rsDesc.CullMode = D3D11_CULL_NONE;
- rsDesc.FrontCounterClockwise = FALSE;
- rsDesc.DepthBias = 0;
- rsDesc.DepthBiasClamp = 0.0f;
- rsDesc.SlopeScaledDepthBias = 0.0f;
- rsDesc.DepthClipEnable = TRUE;
- rsDesc.ScissorEnable = FALSE;
- rsDesc.MultisampleEnable = FALSE;
- rsDesc.AntialiasedLineEnable = FALSE;
+ InputElementArray ilDescArray(ilDesc);
+ ShaderData vertexShader(g_VS_Clear_FL9);
- result = device->CreateRasterizerState(&rsDesc, &mRasterizerState);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mRasterizerState, "Clear11 masked clear rasterizer state");
+ ANGLE_TRY(renderer->allocateResource(ilDescArray, &vertexShader, &mIl9));
+ }
- if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
+ *vs = &mVs9.getObj();
+ *gs = nullptr;
+ *il = &mIl9;
+ *ps = &mPsFloat9.getObj();
+ return gl::NoError();
+ }
+ if (!hasLayeredLayout)
{
- mFloatClearShader = new ClearShader(DXGI_FORMAT_R32G32B32A32_FLOAT,
- "Clear11 Float IL",
- g_VS_ClearFloat,
- ArraySize(g_VS_ClearFloat),
- "Clear11 Float VS",
- g_PS_ClearFloat_FL9,
- ArraySize(g_PS_ClearFloat_FL9),
- "Clear11 Float PS");
+ ANGLE_TRY(mVs.resolve(renderer));
+ *vs = &mVs.getObj();
+ *gs = nullptr;
}
else
{
- mFloatClearShader = new ClearShader(DXGI_FORMAT_R32G32B32A32_FLOAT,
- "Clear11 Float IL",
- g_VS_ClearFloat,
- ArraySize(g_VS_ClearFloat),
- "Clear11 Float VS",
- g_PS_ClearFloat,
- ArraySize(g_PS_ClearFloat),
- "Clear11 Float PS");
+ // For layered framebuffers we have to use the multi-view versions of the VS and GS.
+ ANGLE_TRY(mVsMultiview.resolve(renderer));
+ ANGLE_TRY(mGsMultiview.resolve(renderer));
+ *vs = &mVsMultiview.getObj();
+ *gs = &mGsMultiview.getObj();
+ }
+
+ *il = nullptr;
+
+ if (numRTs == 0)
+ {
+ ANGLE_TRY(mPsDepth.resolve(renderer));
+ *ps = &mPsDepth.getObj();
+ return gl::NoError();
}
- if (renderer->isES3Capable())
+ switch (clearType)
{
- mUintClearShader = new ClearShader(DXGI_FORMAT_R32G32B32A32_UINT,
- "Clear11 UINT IL",
- g_VS_ClearUint,
- ArraySize(g_VS_ClearUint),
- "Clear11 UINT VS",
- g_PS_ClearUint,
- ArraySize(g_PS_ClearUint),
- "Clear11 UINT PS");
- mIntClearShader = new ClearShader(DXGI_FORMAT_R32G32B32A32_UINT,
- "Clear11 SINT IL",
- g_VS_ClearSint,
- ArraySize(g_VS_ClearSint),
- "Clear11 SINT VS",
- g_PS_ClearSint,
- ArraySize(g_PS_ClearSint),
- "Clear11 SINT PS");
+ case GL_FLOAT:
+ ANGLE_TRY(mPsFloat[numRTs - 1].resolve(renderer));
+ *ps = &mPsFloat[numRTs - 1].getObj();
+ break;
+ case GL_UNSIGNED_INT:
+ ANGLE_TRY(mPsUInt[numRTs - 1].resolve(renderer));
+ *ps = &mPsUInt[numRTs - 1].getObj();
+ break;
+ case GL_INT:
+ ANGLE_TRY(mPsSInt[numRTs - 1].resolve(renderer));
+ *ps = &mPsSInt[numRTs - 1].getObj();
+ break;
+ default:
+ UNREACHABLE();
+ break;
}
+
+ return gl::NoError();
+}
+
+Clear11::Clear11(Renderer11 *renderer)
+ : mRenderer(renderer),
+ mResourcesInitialized(false),
+ mScissorEnabledRasterizerState(),
+ mScissorDisabledRasterizerState(),
+ mShaderManager(),
+ mConstantBuffer(),
+ mVertexBuffer(),
+ mShaderData({})
+{
}
Clear11::~Clear11()
{
- for (ClearBlendStateMap::iterator i = mClearBlendStates.begin(); i != mClearBlendStates.end(); i++)
+}
+
+gl::Error Clear11::ensureResourcesInitialized()
+{
+ if (mResourcesInitialized)
{
- SafeRelease(i->second);
+ return gl::NoError();
}
- mClearBlendStates.clear();
- SafeDelete(mFloatClearShader);
- SafeDelete(mUintClearShader);
- SafeDelete(mIntClearShader);
+ TRACE_EVENT0("gpu.angle", "Clear11::ensureResourcesInitialized");
+
+ static_assert((sizeof(RtvDsvClearInfo<float>) == sizeof(RtvDsvClearInfo<int>)),
+ "Size of rx::RtvDsvClearInfo<float> is not equal to rx::RtvDsvClearInfo<int>");
+
+ static_assert(
+ (sizeof(RtvDsvClearInfo<float>) == sizeof(RtvDsvClearInfo<uint32_t>)),
+ "Size of rx::RtvDsvClearInfo<float> is not equal to rx::RtvDsvClearInfo<uint32_t>");
- for (ClearDepthStencilStateMap::iterator i = mClearDepthStencilStates.begin(); i != mClearDepthStencilStates.end(); i++)
+ static_assert((sizeof(RtvDsvClearInfo<float>) % 16 == 0),
+ "The size of RtvDsvClearInfo<float> should be a multiple of 16bytes.");
+
+ // Create Rasterizer States
+ D3D11_RASTERIZER_DESC rsDesc;
+ rsDesc.FillMode = D3D11_FILL_SOLID;
+ rsDesc.CullMode = D3D11_CULL_NONE;
+ rsDesc.FrontCounterClockwise = FALSE;
+ rsDesc.DepthBias = 0;
+ rsDesc.DepthBiasClamp = 0.0f;
+ rsDesc.SlopeScaledDepthBias = 0.0f;
+ rsDesc.DepthClipEnable = TRUE;
+ rsDesc.ScissorEnable = FALSE;
+ rsDesc.MultisampleEnable = FALSE;
+ rsDesc.AntialiasedLineEnable = FALSE;
+
+ ANGLE_TRY(mRenderer->allocateResource(rsDesc, &mScissorDisabledRasterizerState));
+ mScissorDisabledRasterizerState.setDebugName("Clear11 Rasterizer State with scissor disabled");
+
+ rsDesc.ScissorEnable = TRUE;
+ ANGLE_TRY(mRenderer->allocateResource(rsDesc, &mScissorEnabledRasterizerState));
+ mScissorEnabledRasterizerState.setDebugName("Clear11 Rasterizer State with scissor enabled");
+
+ // Initialize Depthstencil state with defaults
+ mDepthStencilStateKey.depthTest = false;
+ mDepthStencilStateKey.depthMask = false;
+ mDepthStencilStateKey.depthFunc = GL_ALWAYS;
+ mDepthStencilStateKey.stencilWritemask = static_cast<GLuint>(-1);
+ mDepthStencilStateKey.stencilBackWritemask = static_cast<GLuint>(-1);
+ mDepthStencilStateKey.stencilBackMask = 0;
+ mDepthStencilStateKey.stencilTest = false;
+ mDepthStencilStateKey.stencilMask = 0;
+ mDepthStencilStateKey.stencilFail = GL_REPLACE;
+ mDepthStencilStateKey.stencilPassDepthFail = GL_REPLACE;
+ mDepthStencilStateKey.stencilPassDepthPass = GL_REPLACE;
+ mDepthStencilStateKey.stencilFunc = GL_ALWAYS;
+ mDepthStencilStateKey.stencilBackFail = GL_REPLACE;
+ mDepthStencilStateKey.stencilBackPassDepthFail = GL_REPLACE;
+ mDepthStencilStateKey.stencilBackPassDepthPass = GL_REPLACE;
+ mDepthStencilStateKey.stencilBackFunc = GL_ALWAYS;
+
+ // Initialize BlendStateKey with defaults
+ mBlendStateKey.blendState.blend = false;
+ mBlendStateKey.blendState.sourceBlendRGB = GL_ONE;
+ mBlendStateKey.blendState.sourceBlendAlpha = GL_ONE;
+ mBlendStateKey.blendState.destBlendRGB = GL_ZERO;
+ mBlendStateKey.blendState.destBlendAlpha = GL_ZERO;
+ mBlendStateKey.blendState.blendEquationRGB = GL_FUNC_ADD;
+ mBlendStateKey.blendState.blendEquationAlpha = GL_FUNC_ADD;
+ mBlendStateKey.blendState.sampleAlphaToCoverage = false;
+ mBlendStateKey.blendState.dither = true;
+
+ mResourcesInitialized = true;
+ return gl::NoError();
+}
+
+bool Clear11::useVertexBuffer() const
+{
+ return (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3);
+}
+
+gl::Error Clear11::ensureConstantBufferCreated()
+{
+ if (mConstantBuffer.valid())
{
- SafeRelease(i->second);
+ return gl::NoError();
}
- mClearDepthStencilStates.clear();
- SafeRelease(mVertexBuffer);
- SafeRelease(mRasterizerState);
+ // Create constant buffer for color & depth data
+
+ D3D11_BUFFER_DESC bufferDesc;
+ bufferDesc.ByteWidth = g_ConstantBufferSize;
+ bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
+ bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.StructureByteStride = 0;
+
+ D3D11_SUBRESOURCE_DATA initialData;
+ initialData.pSysMem = &mShaderData;
+ initialData.SysMemPitch = g_ConstantBufferSize;
+ initialData.SysMemSlicePitch = g_ConstantBufferSize;
+
+ ANGLE_TRY(mRenderer->allocateResource(bufferDesc, &initialData, &mConstantBuffer));
+ mConstantBuffer.setDebugName("Clear11 Constant Buffer");
+ return gl::NoError();
}
-gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl::Framebuffer::Data &fboData)
+gl::Error Clear11::ensureVertexBufferCreated()
{
- const auto &colorAttachments = fboData.getColorAttachments();
- const auto &drawBufferStates = fboData.getDrawBufferStates();
- const auto *depthAttachment = fboData.getDepthAttachment();
- const auto *stencilAttachment = fboData.getStencilAttachment();
+ ASSERT(useVertexBuffer());
+
+ if (mVertexBuffer.valid())
+ {
+ return gl::NoError();
+ }
+
+ // Create vertex buffer with vertices for a quad covering the entire surface
+
+ static_assert((sizeof(d3d11::PositionVertex) % 16) == 0,
+ "d3d11::PositionVertex should be a multiple of 16 bytes");
+ const d3d11::PositionVertex vbData[6] = {{-1.0f, 1.0f, 0.0f, 1.0f}, {1.0f, -1.0f, 0.0f, 1.0f},
+ {-1.0f, -1.0f, 0.0f, 1.0f}, {-1.0f, 1.0f, 0.0f, 1.0f},
+ {1.0f, 1.0f, 0.0f, 1.0f}, {1.0f, -1.0f, 0.0f, 1.0f}};
+
+ const UINT vbSize = sizeof(vbData);
+
+ D3D11_BUFFER_DESC bufferDesc;
+ bufferDesc.ByteWidth = vbSize;
+ bufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
+ bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ bufferDesc.CPUAccessFlags = 0;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.StructureByteStride = 0;
+
+ D3D11_SUBRESOURCE_DATA initialData;
+ initialData.pSysMem = vbData;
+ initialData.SysMemPitch = vbSize;
+ initialData.SysMemSlicePitch = initialData.SysMemPitch;
+
+ ANGLE_TRY(mRenderer->allocateResource(bufferDesc, &initialData, &mVertexBuffer));
+ mVertexBuffer.setDebugName("Clear11 Vertex Buffer");
+ return gl::NoError();
+}
- ASSERT(colorAttachments.size() == drawBufferStates.size());
+gl::Error Clear11::clearFramebuffer(const gl::Context *context,
+ const ClearParameters &clearParams,
+ const gl::FramebufferState &fboData)
+{
+ ANGLE_TRY(ensureResourcesInitialized());
// Iterate over the color buffers which require clearing and determine if they can be
// cleared with ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView.
// This requires:
- // 1) The render target is being cleared to a float value (will be cast to integer when clearing integer
- // render targets as expected but does not work the other way around)
+ // 1) The render target is being cleared to a float value (will be cast to integer when clearing
+ // integer render targets as expected but does not work the other way around)
// 2) The format of the render target has no color channels that are currently masked out.
- // Clear the easy-to-clear buffers on the spot and accumulate the ones that require special work.
+ // Clear the easy-to-clear buffers on the spot and accumulate the ones that require special
+ // work.
//
// If these conditions are met, and:
// - No scissored clear is needed, then clear using ID3D11DeviceContext::ClearRenderTargetView.
// - A scissored clear is needed then clear using ID3D11DeviceContext1::ClearView if available.
- // Otherwise draw a quad.
+ // Otherwise perform a shader based clear.
//
- // Also determine if the depth stencil can be cleared with ID3D11DeviceContext::ClearDepthStencilView
- // by checking if the stencil write mask covers the entire stencil.
+ // Also determine if the DSV can be cleared withID3D11DeviceContext::ClearDepthStencilView by
+ // checking if the stencil write mask covers the entire stencil.
//
- // To clear the remaining buffers, quads must be drawn containing an int, uint or float vertex color
- // attribute.
+ // To clear the remaining buffers, a shader based clear is performed:
+ // - The appropriate ShaderManagers (VS & PS) for the clearType is set
+ // - A CB containing the clear color and Z values is bound
+ // - An IL and VB are bound (for FL93 and below)
+ // - ScissorRect/Raststate/Viewport set as required
+ // - Blendstate set containing appropriate colorMasks
+ // - DepthStencilState set with appropriate parameters for a z or stencil clear if required
+ // - Color and/or Z buffers to be cleared are bound
+ // - Primitive covering entire clear area is drawn
gl::Extents framebufferSize;
- const gl::FramebufferAttachment *colorAttachment = fboData.getFirstColorAttachment();
- if (colorAttachment != nullptr)
- {
- framebufferSize = colorAttachment->getSize();
- }
- else if (depthAttachment != nullptr)
- {
- framebufferSize = depthAttachment->getSize();
- }
- else if (stencilAttachment != nullptr)
+ const auto *depthStencilAttachment = fboData.getDepthOrStencilAttachment();
+ if (depthStencilAttachment != nullptr)
{
- framebufferSize = stencilAttachment->getSize();
+ framebufferSize = depthStencilAttachment->getSize();
}
else
{
- UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION);
+ const gl::FramebufferAttachment *colorAttachment = fboData.getFirstColorAttachment();
+
+ if (!colorAttachment)
+ {
+ UNREACHABLE();
+ return gl::InternalError();
+ }
+
+ framebufferSize = colorAttachment->getSize();
}
- if (clearParams.scissorEnabled && (clearParams.scissor.x >= framebufferSize.width ||
- clearParams.scissor.y >= framebufferSize.height ||
- clearParams.scissor.x + clearParams.scissor.width <= 0 ||
- clearParams.scissor.y + clearParams.scissor.height <= 0))
+ const bool isSideBySideFBO =
+ (fboData.getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE);
+ bool needScissoredClear = false;
+ std::vector<D3D11_RECT> scissorRects;
+ if (clearParams.scissorEnabled)
{
- // Scissor is enabled and the scissor rectangle is outside the renderbuffer
- return gl::Error(GL_NO_ERROR);
- }
+ const std::vector<gl::Offset> *viewportOffsets = fboData.getViewportOffsets();
+ ASSERT(viewportOffsets != nullptr);
+ ASSERT(AllOffsetsAreNonNegative(*fboData.getViewportOffsets()));
- bool needScissoredClear = clearParams.scissorEnabled && (clearParams.scissor.x > 0 || clearParams.scissor.y > 0 ||
- clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width ||
- clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height);
+ if (clearParams.scissor.x >= framebufferSize.width ||
+ clearParams.scissor.y >= framebufferSize.height || clearParams.scissor.width == 0 ||
+ clearParams.scissor.height == 0)
+ {
+ // The check assumes that the viewport offsets are not negative as according to the
+ // ANGLE_multiview spec.
+ // Scissor rect is outside the renderbuffer or is an empty rect.
+ return gl::NoError();
+ }
- std::vector<MaskedRenderTarget> maskedClearRenderTargets;
- RenderTarget11* maskedClearDepthStencil = nullptr;
+ if (isSideBySideFBO)
+ {
+ // We always have to do a scissor clear for side-by-side framebuffers.
+ needScissoredClear = true;
+ }
+ else
+ {
+ // Because the viewport offsets can generate scissor rectangles within the framebuffer's
+ // bounds, we can do this check only for non-side-by-side framebuffers.
+ if (clearParams.scissor.x + clearParams.scissor.width <= 0 ||
+ clearParams.scissor.y + clearParams.scissor.height <= 0)
+ {
+ // Scissor rect is outside the renderbuffer.
+ return gl::NoError();
+ }
+ needScissoredClear =
+ clearParams.scissor.x > 0 || clearParams.scissor.y > 0 ||
+ clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width ||
+ clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height;
+ }
- ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
-#if defined(ANGLE_ENABLE_D3D11_1)
+ if (needScissoredClear)
+ {
+ // Apply viewport offsets to compute the final scissor rectangles. This is valid also
+ // for non-side-by-side framebuffers, because the default viewport offset is {0,0}.
+ const size_t numViews = viewportOffsets->size();
+ scissorRects.reserve(numViews);
+ for (size_t i = 0u; i < numViews; ++i)
+ {
+ const gl::Offset &offset = (*viewportOffsets)[i];
+ D3D11_RECT rect;
+ int x = clearParams.scissor.x + offset.x;
+ int y = clearParams.scissor.y + offset.y;
+ rect.left = x;
+ rect.right = x + clearParams.scissor.width;
+ rect.top = y;
+ rect.bottom = y + clearParams.scissor.height;
+ scissorRects.emplace_back(rect);
+ }
+ }
+ }
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
-#endif
- ID3D11Device *device = mRenderer->getDevice();
- for (size_t colorAttachmentIndex = 0; colorAttachmentIndex < colorAttachments.size();
- colorAttachmentIndex++)
+ std::array<ID3D11RenderTargetView *, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> rtvs;
+ std::array<uint8_t, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> rtvMasks = {};
+
+ uint32_t numRtvs = 0;
+ const uint8_t colorMask =
+ gl_d3d11::ConvertColorMask(clearParams.colorMaskRed, clearParams.colorMaskGreen,
+ clearParams.colorMaskBlue, clearParams.colorMaskAlpha);
+
+ const auto &colorAttachments = fboData.getColorAttachments();
+ for (auto colorAttachmentIndex : fboData.getEnabledDrawBuffers())
{
const gl::FramebufferAttachment &attachment = colorAttachments[colorAttachmentIndex];
- if (clearParams.clearColor[colorAttachmentIndex] && attachment.isAttached() &&
- drawBufferStates[colorAttachmentIndex] != GL_NONE)
+ if (!clearParams.clearColor[colorAttachmentIndex])
{
- RenderTarget11 *renderTarget = nullptr;
- gl::Error error = attachment.getRenderTarget(&renderTarget);
- if (error.isError())
- {
- return error;
- }
+ continue;
+ }
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment.getInternalFormat());
+ RenderTarget11 *renderTarget = nullptr;
+ ANGLE_TRY(attachment.getRenderTarget(context, &renderTarget));
- if (clearParams.colorClearType == GL_FLOAT &&
- !(formatInfo.componentType == GL_FLOAT || formatInfo.componentType == GL_UNSIGNED_NORMALIZED || formatInfo.componentType == GL_SIGNED_NORMALIZED))
- {
- ERR(
- "It is undefined behaviour to clear a render buffer which is not normalized "
- "fixed point or floating-"
- "point to floating point values (color attachment %u has internal format "
- "0x%X).",
- colorAttachmentIndex, attachment.getInternalFormat());
- }
+ const gl::InternalFormat &formatInfo = *attachment.getFormat().info;
- if ((formatInfo.redBits == 0 || !clearParams.colorMaskRed) &&
- (formatInfo.greenBits == 0 || !clearParams.colorMaskGreen) &&
- (formatInfo.blueBits == 0 || !clearParams.colorMaskBlue) &&
- (formatInfo.alphaBits == 0 || !clearParams.colorMaskAlpha))
- {
- // Every channel either does not exist in the render target or is masked out
- continue;
- }
- else if ((!(mRenderer->getRenderer11DeviceCaps().supportsClearView) && needScissoredClear) || clearParams.colorClearType != GL_FLOAT ||
- (formatInfo.redBits > 0 && !clearParams.colorMaskRed) ||
- (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) ||
- (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) ||
- (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha))
- {
- // A masked clear is required, or a scissored clear is required and ID3D11DeviceContext1::ClearView is unavailable
- MaskedRenderTarget maskAndRt;
- bool clearColor = clearParams.clearColor[colorAttachmentIndex];
- maskAndRt.colorMask[0] = (clearColor && clearParams.colorMaskRed);
- maskAndRt.colorMask[1] = (clearColor && clearParams.colorMaskGreen);
- maskAndRt.colorMask[2] = (clearColor && clearParams.colorMaskBlue);
- maskAndRt.colorMask[3] = (clearColor && clearParams.colorMaskAlpha);
- maskAndRt.renderTarget = renderTarget;
- maskedClearRenderTargets.push_back(maskAndRt);
- }
- else
- {
- // ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView is possible
+ if (clearParams.colorType == GL_FLOAT &&
+ !(formatInfo.componentType == GL_FLOAT ||
+ formatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
+ formatInfo.componentType == GL_SIGNED_NORMALIZED))
+ {
+ ERR() << "It is undefined behaviour to clear a render buffer which is not "
+ "normalized fixed point or floating-point to floating point values (color "
+ "attachment "
+ << colorAttachmentIndex << " has internal format " << attachment.getFormat()
+ << ").";
+ }
- ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView();
- if (!framebufferRTV)
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null.");
- }
+ if ((formatInfo.redBits == 0 || !clearParams.colorMaskRed) &&
+ (formatInfo.greenBits == 0 || !clearParams.colorMaskGreen) &&
+ (formatInfo.blueBits == 0 || !clearParams.colorMaskBlue) &&
+ (formatInfo.alphaBits == 0 || !clearParams.colorMaskAlpha))
+ {
+ // Every channel either does not exist in the render target or is masked out
+ continue;
+ }
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(renderTarget->getDXGIFormat());
+ const auto &framebufferRTV = renderTarget->getRenderTargetView();
+ ASSERT(framebufferRTV.valid());
- // Check if the actual format has a channel that the internal format does not and set them to the
- // default values
- float clearValues[4] =
- {
- ((formatInfo.redBits == 0 && dxgiFormatInfo.redBits > 0) ? 0.0f : clearParams.colorFClearValue.red),
- ((formatInfo.greenBits == 0 && dxgiFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green),
- ((formatInfo.blueBits == 0 && dxgiFormatInfo.blueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue),
- ((formatInfo.alphaBits == 0 && dxgiFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha),
- };
+ if ((!(mRenderer->getRenderer11DeviceCaps().supportsClearView) && needScissoredClear) ||
+ clearParams.colorType != GL_FLOAT ||
+ (formatInfo.redBits > 0 && !clearParams.colorMaskRed) ||
+ (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) ||
+ (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) ||
+ (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha))
+ {
+ rtvs[numRtvs] = framebufferRTV.get();
+ rtvMasks[numRtvs] = gl_d3d11::GetColorMask(formatInfo) & colorMask;
+ numRtvs++;
+ }
+ else
+ {
+ // ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView is
+ // possible
+
+ const auto &nativeFormat = renderTarget->getFormatSet().format();
+
+ // Check if the actual format has a channel that the internal format does not and
+ // set them to the default values
+ float clearValues[4] = {
+ ((formatInfo.redBits == 0 && nativeFormat.redBits > 0) ? 0.0f
+ : clearParams.colorF.red),
+ ((formatInfo.greenBits == 0 && nativeFormat.greenBits > 0)
+ ? 0.0f
+ : clearParams.colorF.green),
+ ((formatInfo.blueBits == 0 && nativeFormat.blueBits > 0) ? 0.0f
+ : clearParams.colorF.blue),
+ ((formatInfo.alphaBits == 0 && nativeFormat.alphaBits > 0)
+ ? 1.0f
+ : clearParams.colorF.alpha),
+ };
+
+ if (formatInfo.alphaBits == 1)
+ {
+ // Some drivers do not correctly handle calling Clear() on a format with 1-bit
+ // alpha. They can incorrectly round all non-zero values up to 1.0f. Note that
+ // WARP does not do this. We should handle the rounding for them instead.
+ clearValues[3] = (clearParams.colorF.alpha >= 0.5f) ? 1.0f : 0.0f;
+ }
- if (dxgiFormatInfo.alphaBits == 1)
+ if (needScissoredClear)
+ {
+ // We shouldn't reach here if deviceContext1 is unavailable.
+ ASSERT(deviceContext1);
+ // There must be at least one scissor rectangle.
+ ASSERT(!scissorRects.empty());
+ deviceContext1->ClearView(framebufferRTV.get(), clearValues, scissorRects.data(),
+ static_cast<UINT>(scissorRects.size()));
+ if (mRenderer->getWorkarounds().callClearTwice)
{
- // Some drivers do not correctly handle calling Clear() on a format with 1-bit alpha.
- // They can incorrectly round all non-zero values up to 1.0f. Note that WARP does not do this.
- // We should handle the rounding for them instead.
- clearValues[3] = (clearParams.colorFClearValue.alpha >= 0.5f) ? 1.0f : 0.0f;
+ deviceContext1->ClearView(framebufferRTV.get(), clearValues,
+ scissorRects.data(),
+ static_cast<UINT>(scissorRects.size()));
}
-
-#if defined(ANGLE_ENABLE_D3D11_1)
- if (needScissoredClear)
- {
- // We shouldn't reach here if deviceContext1 is unavailable.
- ASSERT(deviceContext1);
-
- D3D11_RECT rect;
- rect.left = clearParams.scissor.x;
- rect.right = clearParams.scissor.x + clearParams.scissor.width;
- rect.top = clearParams.scissor.y;
- rect.bottom = clearParams.scissor.y + clearParams.scissor.height;
-
- deviceContext1->ClearView(framebufferRTV, clearValues, &rect, 1);
- }
- else
-#endif
+ }
+ else
+ {
+ deviceContext->ClearRenderTargetView(framebufferRTV.get(), clearValues);
+ if (mRenderer->getWorkarounds().callClearTwice)
{
- deviceContext->ClearRenderTargetView(framebufferRTV, clearValues);
+ deviceContext->ClearRenderTargetView(framebufferRTV.get(), clearValues);
}
}
}
}
+ ID3D11DepthStencilView *dsv = nullptr;
+
if (clearParams.clearDepth || clearParams.clearStencil)
{
- const gl::FramebufferAttachment *attachment = (depthAttachment != nullptr) ? depthAttachment : stencilAttachment;
- ASSERT(attachment != nullptr);
+ RenderTarget11 *depthStencilRenderTarget = nullptr;
- RenderTarget11 *renderTarget = nullptr;
- gl::Error error = attachment->getRenderTarget(&renderTarget);
- if (error.isError())
- {
- return error;
- }
+ ASSERT(depthStencilAttachment != nullptr);
+ ANGLE_TRY(depthStencilAttachment->getRenderTarget(context, &depthStencilRenderTarget));
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(renderTarget->getDXGIFormat());
+ dsv = depthStencilRenderTarget->getDepthStencilView().get();
+ ASSERT(dsv != nullptr);
- unsigned int stencilUnmasked = (stencilAttachment != nullptr) ? (1 << dxgiFormatInfo.stencilBits) - 1 : 0;
- bool needMaskedStencilClear = clearParams.clearStencil && (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
+ const auto &nativeFormat = depthStencilRenderTarget->getFormatSet().format();
+ const auto *stencilAttachment = fboData.getStencilAttachment();
- if (needScissoredClear || needMaskedStencilClear)
- {
- maskedClearDepthStencil = renderTarget;
- }
- else
+ uint32_t stencilUnmasked =
+ (stencilAttachment != nullptr) ? (1 << nativeFormat.stencilBits) - 1 : 0;
+ bool needMaskedStencilClear =
+ clearParams.clearStencil &&
+ (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
+
+ if (!needScissoredClear && !needMaskedStencilClear)
{
- ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView();
- if (!framebufferDSV)
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null.");
- }
+ const UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) |
+ (clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0);
+ const FLOAT depthClear = gl::clamp01(clearParams.depthValue);
+ const UINT8 stencilClear = clearParams.stencilValue & 0xFF;
- UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) |
- (clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0);
- FLOAT depthClear = gl::clamp01(clearParams.depthClearValue);
- UINT8 stencilClear = clearParams.stencilClearValue & 0xFF;
+ deviceContext->ClearDepthStencilView(dsv, clearFlags, depthClear, stencilClear);
- deviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear);
+ dsv = nullptr;
}
}
- if (maskedClearRenderTargets.size() > 0 || maskedClearDepthStencil)
+ if (numRtvs == 0 && dsv == nullptr)
{
- // To clear the render targets and depth stencil in one pass:
- //
- // Render a quad clipped to the scissor rectangle which draws the clear color and a blend
- // state that will perform the required color masking.
- //
- // The quad's depth is equal to the depth clear value with a depth stencil state that
- // will enable or disable depth test/writes if the depth buffer should be cleared or not.
- //
- // The rasterizer state's stencil is set to always pass or fail based on if the stencil
- // should be cleared or not with a stencil write mask of the stencil clear value.
- //
- // ======================================================================================
- //
- // Luckily, the gl spec (ES 3.0.2 pg 183) states that the results of clearing a render-
- // buffer that is not normalized fixed point or floating point with floating point values
- // are undefined so we can just write floats to them and D3D11 will bit cast them to
- // integers.
- //
- // Also, we don't have to worry about attempting to clear a normalized fixed/floating point
- // buffer with integer values because there is no gl API call which would allow it,
- // glClearBuffer* calls only clear a single renderbuffer at a time which is verified to
- // be a compatible clear type.
-
- // Bind all the render targets which need clearing
- ASSERT(maskedClearRenderTargets.size() <= mRenderer->getRendererCaps().maxDrawBuffers);
- std::vector<ID3D11RenderTargetView*> rtvs(maskedClearRenderTargets.size());
- for (unsigned int i = 0; i < maskedClearRenderTargets.size(); i++)
- {
- RenderTarget11 *renderTarget = maskedClearRenderTargets[i].renderTarget;
- ID3D11RenderTargetView *rtv = renderTarget->getRenderTargetView();
- if (!rtv)
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null.");
- }
+ return gl::NoError();
+ }
- rtvs[i] = rtv;
- }
- ID3D11DepthStencilView *dsv = maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : nullptr;
+ // Clear the remaining render targets and depth stencil in one pass by rendering a quad:
+ //
+ // IA/VS: Vertices containing position and color members are passed through to the next stage.
+ // The vertex position has XY coordinates equal to clip extents and a Z component equal to the
+ // Z clear value. The vertex color contains the clear color.
+ //
+ // Rasterizer: Viewport scales the VS output over the entire surface and depending on whether
+ // or not scissoring is enabled the appropriate scissor rect and rasterizerState with or without
+ // the scissor test enabled is set as well.
+ //
+ // DepthStencilTest: DepthTesting, DepthWrites, StencilMask and StencilWrites will be enabled or
+ // disabled or set depending on what the input depthStencil clear parameters are. Since the PS
+ // is not writing out depth or rejecting pixels, this should happen prior to the PS stage.
+ //
+ // PS: Will write out the color values passed through from the previous stage to all outputs.
+ //
+ // OM: BlendState will perform the required color masking and output to RTV(s).
+
+ //
+ // ======================================================================================
+ //
+ // Luckily, the gl spec (ES 3.0.2 pg 183) states that the results of clearing a render-
+ // buffer that is not normalized fixed point or floating point with floating point values
+ // are undefined so we can just write floats to them and D3D11 will bit cast them to
+ // integers.
+ //
+ // Also, we don't have to worry about attempting to clear a normalized fixed/floating point
+ // buffer with integer values because there is no gl API call which would allow it,
+ // glClearBuffer* calls only clear a single renderbuffer at a time which is verified to
+ // be a compatible clear type.
- ID3D11BlendState *blendState = getBlendState(maskedClearRenderTargets);
- const FLOAT blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
- const UINT sampleMask = 0xFFFFFFFF;
+ ASSERT(numRtvs <= mRenderer->getNativeCaps().maxDrawBuffers);
- ID3D11DepthStencilState *dsState = getDepthStencilState(clearParams);
- const UINT stencilClear = clearParams.stencilClearValue & 0xFF;
+ // Setup BlendStateKey parameters
+ mBlendStateKey.blendState.colorMaskRed = clearParams.colorMaskRed;
+ mBlendStateKey.blendState.colorMaskGreen = clearParams.colorMaskGreen;
+ mBlendStateKey.blendState.colorMaskBlue = clearParams.colorMaskBlue;
+ mBlendStateKey.blendState.colorMaskAlpha = clearParams.colorMaskAlpha;
+ mBlendStateKey.rtvMax = numRtvs;
+ memcpy(mBlendStateKey.rtvMasks, &rtvMasks[0], sizeof(mBlendStateKey.rtvMasks));
- // Set the vertices
- UINT vertexStride = 0;
- const UINT startIdx = 0;
- ClearShader *shader = nullptr;
- D3D11_MAPPED_SUBRESOURCE mappedResource;
- HRESULT result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal masked clear vertex buffer, HRESULT: 0x%X.", result);
- }
+ // Get BlendState
+ const d3d11::BlendState *blendState = nullptr;
+ ANGLE_TRY(mRenderer->getBlendState(mBlendStateKey, &blendState));
- const gl::Rectangle *scissorPtr = clearParams.scissorEnabled ? &clearParams.scissor : nullptr;
- switch (clearParams.colorClearType)
- {
- case GL_FLOAT:
- ApplyVertices(framebufferSize, scissorPtr, clearParams.colorFClearValue, clearParams.depthClearValue, mappedResource.pData);
- vertexStride = sizeof(d3d11::PositionDepthColorVertex<float>);
- shader = mFloatClearShader;
- break;
+ const d3d11::DepthStencilState *dsState = nullptr;
+ const float *zValue = nullptr;
- case GL_UNSIGNED_INT:
- ApplyVertices(framebufferSize, scissorPtr, clearParams.colorUIClearValue, clearParams.depthClearValue, mappedResource.pData);
- vertexStride = sizeof(d3d11::PositionDepthColorVertex<unsigned int>);
- shader = mUintClearShader;
- break;
+ if (dsv)
+ {
+ // Setup DepthStencilStateKey
+ mDepthStencilStateKey.depthTest = clearParams.clearDepth;
+ mDepthStencilStateKey.depthMask = clearParams.clearDepth;
+ mDepthStencilStateKey.stencilWritemask = clearParams.stencilWriteMask;
+ mDepthStencilStateKey.stencilTest = clearParams.clearStencil;
+
+ // Get DepthStencilState
+ ANGLE_TRY(mRenderer->getDepthStencilState(mDepthStencilStateKey, &dsState));
+ zValue = clearParams.clearDepth ? &clearParams.depthValue : nullptr;
+ }
- case GL_INT:
- ApplyVertices(framebufferSize, scissorPtr, clearParams.colorIClearValue, clearParams.depthClearValue, mappedResource.pData);
- vertexStride = sizeof(d3d11::PositionDepthColorVertex<int>);
- shader = mIntClearShader;
- break;
+ bool dirtyCb = false;
- default:
+ // Compare the input color/z values against the CB cache and update it if necessary
+ switch (clearParams.colorType)
+ {
+ case GL_FLOAT:
+ dirtyCb = UpdateDataCache(reinterpret_cast<RtvDsvClearInfo<float> *>(&mShaderData),
+ clearParams.colorF, zValue, numRtvs, colorMask);
+ break;
+ case GL_UNSIGNED_INT:
+ dirtyCb = UpdateDataCache(reinterpret_cast<RtvDsvClearInfo<uint32_t> *>(&mShaderData),
+ clearParams.colorUI, zValue, numRtvs, colorMask);
+ break;
+ case GL_INT:
+ dirtyCb = UpdateDataCache(reinterpret_cast<RtvDsvClearInfo<int> *>(&mShaderData),
+ clearParams.colorI, zValue, numRtvs, colorMask);
+ break;
+ default:
UNREACHABLE();
break;
- }
-
- deviceContext->Unmap(mVertexBuffer, 0);
-
- // Set the viewport to be the same size as the framebuffer
- D3D11_VIEWPORT viewport;
- viewport.TopLeftX = 0;
- viewport.TopLeftY = 0;
- viewport.Width = static_cast<FLOAT>(framebufferSize.width);
- viewport.Height = static_cast<FLOAT>(framebufferSize.height);
- viewport.MinDepth = 0;
- viewport.MaxDepth = 1;
- deviceContext->RSSetViewports(1, &viewport);
-
- // Apply state
- deviceContext->OMSetBlendState(blendState, blendFactors, sampleMask);
- deviceContext->OMSetDepthStencilState(dsState, stencilClear);
- deviceContext->RSSetState(mRasterizerState);
-
- // Apply shaders
- deviceContext->IASetInputLayout(shader->inputLayout->resolve(device));
- deviceContext->VSSetShader(shader->vertexShader.resolve(device), nullptr, 0);
- deviceContext->PSSetShader(shader->pixelShader.resolve(device), nullptr, 0);
- deviceContext->GSSetShader(nullptr, nullptr, 0);
-
- // Apply vertex buffer
- deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &vertexStride, &startIdx);
- deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
-
- // Apply render targets
- deviceContext->OMSetRenderTargets(static_cast<unsigned int>(rtvs.size()),
- (rtvs.empty() ? nullptr : &rtvs[0]), dsv);
-
- // Draw the clear quad
- deviceContext->Draw(4, 0);
-
- // Clean up
- mRenderer->markAllStateDirty();
}
- return gl::Error(GL_NO_ERROR);
-}
+ ANGLE_TRY(ensureConstantBufferCreated());
-ID3D11BlendState *Clear11::getBlendState(const std::vector<MaskedRenderTarget>& rts)
-{
- ClearBlendInfo blendKey = {};
- for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
+ if (dirtyCb)
{
- if (i < rts.size())
- {
- RenderTarget11 *rt = rts[i].renderTarget;
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(rt->getInternalFormat());
-
- blendKey.maskChannels[i][0] = (rts[i].colorMask[0] && formatInfo.redBits > 0);
- blendKey.maskChannels[i][1] = (rts[i].colorMask[1] && formatInfo.greenBits > 0);
- blendKey.maskChannels[i][2] = (rts[i].colorMask[2] && formatInfo.blueBits > 0);
- blendKey.maskChannels[i][3] = (rts[i].colorMask[3] && formatInfo.alphaBits > 0);
- }
- else
+ // Update the constant buffer with the updated cache contents
+ // TODO(Shahmeer): Consider using UpdateSubresource1 D3D11_COPY_DISCARD where possible.
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ HRESULT result = deviceContext->Map(mConstantBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0,
+ &mappedResource);
+ if (FAILED(result))
{
- blendKey.maskChannels[i][0] = false;
- blendKey.maskChannels[i][1] = false;
- blendKey.maskChannels[i][2] = false;
- blendKey.maskChannels[i][3] = false;
+ return gl::OutOfMemory() << "Clear11: Failed to map CB, " << gl::FmtHR(result);
}
- }
- ClearBlendStateMap::const_iterator i = mClearBlendStates.find(blendKey);
- if (i != mClearBlendStates.end())
- {
- return i->second;
+ memcpy(mappedResource.pData, &mShaderData, g_ConstantBufferSize);
+ deviceContext->Unmap(mConstantBuffer.get(), 0);
}
- else
- {
- D3D11_BLEND_DESC blendDesc = { 0 };
- blendDesc.AlphaToCoverageEnable = FALSE;
- blendDesc.IndependentBlendEnable = (rts.size() > 1) ? TRUE : FALSE;
- for (unsigned int j = 0; j < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; j++)
- {
- blendDesc.RenderTarget[j].BlendEnable = FALSE;
- blendDesc.RenderTarget[j].RenderTargetWriteMask = gl_d3d11::ConvertColorMask(blendKey.maskChannels[j][0],
- blendKey.maskChannels[j][1],
- blendKey.maskChannels[j][2],
- blendKey.maskChannels[j][3]);
- }
+ auto *stateManager = mRenderer->getStateManager();
- ID3D11Device *device = mRenderer->getDevice();
- ID3D11BlendState* blendState = nullptr;
- HRESULT result = device->CreateBlendState(&blendDesc, &blendState);
- if (FAILED(result) || !blendState)
- {
- ERR("Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result);
- return nullptr;
- }
+ // Set the viewport to be the same size as the framebuffer.
+ stateManager->setSimpleViewport(framebufferSize);
- mClearBlendStates[blendKey] = blendState;
+ // Apply state
+ stateManager->setSimpleBlendState(blendState);
- return blendState;
- }
-}
+ const UINT stencilValue = clearParams.stencilValue & 0xFF;
+ stateManager->setDepthStencilState(dsState, stencilValue);
-ID3D11DepthStencilState *Clear11::getDepthStencilState(const ClearParameters &clearParams)
-{
- ClearDepthStencilInfo dsKey = { 0 };
- dsKey.clearDepth = clearParams.clearDepth;
- dsKey.clearStencil = clearParams.clearStencil;
- dsKey.stencilWriteMask = clearParams.stencilWriteMask & 0xFF;
+ if (needScissoredClear)
+ {
+ stateManager->setRasterizerState(&mScissorEnabledRasterizerState);
+ }
+ else
+ {
+ stateManager->setRasterizerState(&mScissorDisabledRasterizerState);
+ }
- ClearDepthStencilStateMap::const_iterator i = mClearDepthStencilStates.find(dsKey);
- if (i != mClearDepthStencilStates.end())
+ // Get Shaders
+ const d3d11::VertexShader *vs = nullptr;
+ const d3d11::GeometryShader *gs = nullptr;
+ const d3d11::InputLayout *il = nullptr;
+ const d3d11::PixelShader *ps = nullptr;
+ const bool hasLayeredLayout =
+ (fboData.getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE);
+ ANGLE_TRY(mShaderManager.getShadersAndLayout(mRenderer, clearParams.colorType, numRtvs,
+ hasLayeredLayout, &il, &vs, &gs, &ps));
+
+ // Apply Shaders
+ stateManager->setDrawShaders(vs, gs, ps);
+ stateManager->setPixelConstantBuffer(0, &mConstantBuffer);
+
+ // Bind IL & VB if needed
+ stateManager->setIndexBuffer(nullptr, DXGI_FORMAT_UNKNOWN, 0);
+ stateManager->setInputLayout(il);
+
+ if (useVertexBuffer())
{
- return i->second;
+ ANGLE_TRY(ensureVertexBufferCreated());
+ stateManager->setSingleVertexBuffer(&mVertexBuffer, g_VertexSize, 0);
}
else
{
- D3D11_DEPTH_STENCIL_DESC dsDesc = { 0 };
- dsDesc.DepthEnable = dsKey.clearDepth ? TRUE : FALSE;
- dsDesc.DepthWriteMask = dsKey.clearDepth ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
- dsDesc.DepthFunc = D3D11_COMPARISON_ALWAYS;
- dsDesc.StencilEnable = dsKey.clearStencil ? TRUE : FALSE;
- dsDesc.StencilReadMask = 0;
- dsDesc.StencilWriteMask = dsKey.stencilWriteMask;
- dsDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_REPLACE;
- dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE;
- dsDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE;
- dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
- dsDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_REPLACE;
- dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE;
- dsDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE;
- dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
-
- ID3D11Device *device = mRenderer->getDevice();
- ID3D11DepthStencilState* dsState = nullptr;
- HRESULT result = device->CreateDepthStencilState(&dsDesc, &dsState);
- if (FAILED(result) || !dsState)
- {
- ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result);
- return nullptr;
- }
+ stateManager->setSingleVertexBuffer(nullptr, 0, 0);
+ }
- mClearDepthStencilStates[dsKey] = dsState;
+ stateManager->setPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
- return dsState;
+ // Apply render targets
+ stateManager->setRenderTargets(&rtvs[0], numRtvs, dsv);
+
+ // If scissors are necessary to be applied, then the number of clears is the number of scissor
+ // rects. If no scissors are necessary, then a single full-size clear is enough.
+ size_t necessaryNumClears = needScissoredClear ? scissorRects.size() : 1u;
+ for (size_t i = 0u; i < necessaryNumClears; ++i)
+ {
+ if (needScissoredClear)
+ {
+ ASSERT(i < scissorRects.size());
+ stateManager->setScissorRectD3D(scissorRects[i]);
+ }
+ // Draw the fullscreen quad.
+ if (!hasLayeredLayout || isSideBySideFBO)
+ {
+ deviceContext->Draw(6, 0);
+ }
+ else
+ {
+ ASSERT(hasLayeredLayout);
+ deviceContext->DrawInstanced(6, static_cast<UINT>(fboData.getNumViews()), 0, 0);
+ }
}
-}
+ return gl::NoError();
}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h
index 3ff73c85d1..a09812c42b 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h
@@ -23,6 +23,14 @@ class Renderer11;
class RenderTarget11;
struct ClearParameters;
+template <typename T>
+struct RtvDsvClearInfo
+{
+ T r, g, b, a;
+ float z;
+ float c1padding[3];
+};
+
class Clear11 : angle::NonCopyable
{
public:
@@ -30,68 +38,63 @@ class Clear11 : angle::NonCopyable
~Clear11();
// Clears the framebuffer with the supplied clear parameters, assumes that the framebuffer is currently applied.
- gl::Error clearFramebuffer(const ClearParameters &clearParams, const gl::Framebuffer::Data &fboData);
+ gl::Error clearFramebuffer(const gl::Context *context,
+ const ClearParameters &clearParams,
+ const gl::FramebufferState &fboData);
private:
- struct MaskedRenderTarget
- {
- bool colorMask[4];
- RenderTarget11 *renderTarget;
- };
-
- ID3D11BlendState *getBlendState(const std::vector<MaskedRenderTarget> &rts);
- ID3D11DepthStencilState *getDepthStencilState(const ClearParameters &clearParams);
-
- struct ClearShader final : public angle::NonCopyable
+ class ShaderManager final : angle::NonCopyable
{
- ClearShader(DXGI_FORMAT colorType,
- const char *inputLayoutName,
- const BYTE *vsByteCode,
- size_t vsSize,
- const char *vsDebugName,
- const BYTE *psByteCode,
- size_t psSize,
- const char *psDebugName);
- ~ClearShader();
-
- d3d11::LazyInputLayout *inputLayout;
- d3d11::LazyShader<ID3D11VertexShader> vertexShader;
- d3d11::LazyShader<ID3D11PixelShader> pixelShader;
+ public:
+ ShaderManager();
+ ~ShaderManager();
+ gl::Error getShadersAndLayout(Renderer11 *renderer,
+ const INT clearType,
+ const uint32_t numRTs,
+ const bool hasLayeredLayout,
+ const d3d11::InputLayout **il,
+ const d3d11::VertexShader **vs,
+ const d3d11::GeometryShader **gs,
+ const d3d11::PixelShader **ps);
+
+ private:
+ constexpr static size_t kNumShaders = D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;
+
+ d3d11::InputLayout mIl9;
+ d3d11::LazyShader<ID3D11VertexShader> mVs9;
+ d3d11::LazyShader<ID3D11PixelShader> mPsFloat9;
+ d3d11::LazyShader<ID3D11VertexShader> mVs;
+ d3d11::LazyShader<ID3D11VertexShader> mVsMultiview;
+ d3d11::LazyShader<ID3D11GeometryShader> mGsMultiview;
+ d3d11::LazyShader<ID3D11PixelShader> mPsDepth;
+ std::array<d3d11::LazyShader<ID3D11PixelShader>, kNumShaders> mPsFloat;
+ std::array<d3d11::LazyShader<ID3D11PixelShader>, kNumShaders> mPsUInt;
+ std::array<d3d11::LazyShader<ID3D11PixelShader>, kNumShaders> mPsSInt;
};
- template <unsigned int vsSize, unsigned int psSize>
- static ClearShader CreateClearShader(ID3D11Device *device, DXGI_FORMAT colorType, const BYTE(&vsByteCode)[vsSize], const BYTE(&psByteCode)[psSize]);
-
- struct ClearBlendInfo
- {
- bool maskChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4];
- };
- typedef bool(*ClearBlendInfoComparisonFunction)(const ClearBlendInfo&, const ClearBlendInfo &);
- typedef std::map<ClearBlendInfo, ID3D11BlendState*, ClearBlendInfoComparisonFunction> ClearBlendStateMap;
-
- struct ClearDepthStencilInfo
- {
- bool clearDepth;
- bool clearStencil;
- UINT8 stencilWriteMask;
- };
- typedef bool(*ClearDepthStencilInfoComparisonFunction)(const ClearDepthStencilInfo&, const ClearDepthStencilInfo &);
- typedef std::map<ClearDepthStencilInfo, ID3D11DepthStencilState*, ClearDepthStencilInfoComparisonFunction> ClearDepthStencilStateMap;
+ bool useVertexBuffer() const;
+ gl::Error ensureConstantBufferCreated();
+ gl::Error ensureVertexBufferCreated();
+ gl::Error ensureResourcesInitialized();
Renderer11 *mRenderer;
+ bool mResourcesInitialized;
- ClearBlendStateMap mClearBlendStates;
-
- ClearShader *mFloatClearShader;
- ClearShader *mUintClearShader;
- ClearShader *mIntClearShader;
+ // States
+ d3d11::RasterizerState mScissorEnabledRasterizerState;
+ d3d11::RasterizerState mScissorDisabledRasterizerState;
+ gl::DepthStencilState mDepthStencilStateKey;
+ d3d11::BlendStateKey mBlendStateKey;
- ClearDepthStencilStateMap mClearDepthStencilStates;
+ // Shaders and shader resources
+ ShaderManager mShaderManager;
+ d3d11::Buffer mConstantBuffer;
+ d3d11::Buffer mVertexBuffer;
- ID3D11Buffer *mVertexBuffer;
- ID3D11RasterizerState *mRasterizerState;
+ // Buffer data and draw parameters
+ RtvDsvClearInfo<float> mShaderData;
};
-}
+} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_D3D11_CLEAR11_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp
new file mode 100644
index 0000000000..b79dd3603a
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp
@@ -0,0 +1,405 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Context11:
+// D3D11-specific functionality associated with a GL Context.
+//
+
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+
+#include "common/string_utils.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/MemoryProgramCache.h"
+#include "libANGLE/renderer/d3d/CompilerD3D.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/SamplerD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Fence11.h"
+#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/StateManager11.h"
+#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
+#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
+
+namespace rx
+{
+
+Context11::Context11(const gl::ContextState &state, Renderer11 *renderer)
+ : ContextImpl(state), mRenderer(renderer)
+{
+}
+
+Context11::~Context11()
+{
+}
+
+gl::Error Context11::initialize()
+{
+ return gl::NoError();
+}
+
+CompilerImpl *Context11::createCompiler()
+{
+ if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
+ {
+ return new CompilerD3D(SH_HLSL_4_0_FL9_3_OUTPUT);
+ }
+ else
+ {
+ return new CompilerD3D(SH_HLSL_4_1_OUTPUT);
+ }
+}
+
+ShaderImpl *Context11::createShader(const gl::ShaderState &data)
+{
+ return new ShaderD3D(data, mRenderer->getWorkarounds(), mRenderer->getNativeExtensions());
+}
+
+ProgramImpl *Context11::createProgram(const gl::ProgramState &data)
+{
+ return new ProgramD3D(data, mRenderer);
+}
+
+FramebufferImpl *Context11::createFramebuffer(const gl::FramebufferState &data)
+{
+ return new Framebuffer11(data, mRenderer);
+}
+
+TextureImpl *Context11::createTexture(const gl::TextureState &state)
+{
+ switch (state.getTarget())
+ {
+ case GL_TEXTURE_2D:
+ return new TextureD3D_2D(state, mRenderer);
+ case GL_TEXTURE_CUBE_MAP:
+ return new TextureD3D_Cube(state, mRenderer);
+ case GL_TEXTURE_3D:
+ return new TextureD3D_3D(state, mRenderer);
+ case GL_TEXTURE_2D_ARRAY:
+ return new TextureD3D_2DArray(state, mRenderer);
+ case GL_TEXTURE_EXTERNAL_OES:
+ return new TextureD3D_External(state, mRenderer);
+ case GL_TEXTURE_2D_MULTISAMPLE:
+ return new TextureD3D_2DMultisample(state, mRenderer);
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return nullptr;
+}
+
+RenderbufferImpl *Context11::createRenderbuffer()
+{
+ return new RenderbufferD3D(mRenderer);
+}
+
+BufferImpl *Context11::createBuffer(const gl::BufferState &state)
+{
+ Buffer11 *buffer = new Buffer11(state, mRenderer);
+ mRenderer->onBufferCreate(buffer);
+ return buffer;
+}
+
+VertexArrayImpl *Context11::createVertexArray(const gl::VertexArrayState &data)
+{
+ return new VertexArray11(data);
+}
+
+QueryImpl *Context11::createQuery(GLenum type)
+{
+ return new Query11(mRenderer, type);
+}
+
+FenceNVImpl *Context11::createFenceNV()
+{
+ return new FenceNV11(mRenderer);
+}
+
+SyncImpl *Context11::createSync()
+{
+ return new Sync11(mRenderer);
+}
+
+TransformFeedbackImpl *Context11::createTransformFeedback(const gl::TransformFeedbackState &state)
+{
+ return new TransformFeedback11(state, mRenderer);
+}
+
+SamplerImpl *Context11::createSampler(const gl::SamplerState &state)
+{
+ return new SamplerD3D(state);
+}
+
+ProgramPipelineImpl *Context11::createProgramPipeline(const gl::ProgramPipelineState &data)
+{
+ return new ProgramPipeline11(data);
+}
+
+std::vector<PathImpl *> Context11::createPaths(GLsizei)
+{
+ return std::vector<PathImpl *>();
+}
+
+gl::Error Context11::flush(const gl::Context *context)
+{
+ return mRenderer->flush();
+}
+
+gl::Error Context11::finish(const gl::Context *context)
+{
+ return mRenderer->finish();
+}
+
+gl::Error Context11::drawArrays(const gl::Context *context, GLenum mode, GLint first, GLsizei count)
+{
+ ANGLE_TRY(prepareForDrawCall(context, mode));
+ return mRenderer->drawArrays(context, mode, first, count, 0);
+}
+
+gl::Error Context11::drawArraysInstanced(const gl::Context *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount)
+{
+ ANGLE_TRY(prepareForDrawCall(context, mode));
+ return mRenderer->drawArrays(context, mode, first, count, instanceCount);
+}
+
+gl::Error Context11::drawElements(const gl::Context *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices)
+{
+ ANGLE_TRY(prepareForDrawCall(context, mode));
+ return mRenderer->drawElements(context, mode, count, type, indices, 0);
+}
+
+gl::Error Context11::drawElementsInstanced(const gl::Context *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei instances)
+{
+ ANGLE_TRY(prepareForDrawCall(context, mode));
+ return mRenderer->drawElements(context, mode, count, type, indices, instances);
+}
+
+gl::Error Context11::drawRangeElements(const gl::Context *context,
+ GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const void *indices)
+{
+ ANGLE_TRY(prepareForDrawCall(context, mode));
+ return mRenderer->drawElements(context, mode, count, type, indices, 0);
+}
+
+gl::Error Context11::drawArraysIndirect(const gl::Context *context,
+ GLenum mode,
+ const void *indirect)
+{
+ ANGLE_TRY(prepareForDrawCall(context, mode));
+ return mRenderer->drawArraysIndirect(context, mode, indirect);
+}
+
+gl::Error Context11::drawElementsIndirect(const gl::Context *context,
+ GLenum mode,
+ GLenum type,
+ const void *indirect)
+{
+ ANGLE_TRY(prepareForDrawCall(context, mode));
+ return mRenderer->drawElementsIndirect(context, mode, type, indirect);
+}
+
+GLenum Context11::getResetStatus()
+{
+ return mRenderer->getResetStatus();
+}
+
+std::string Context11::getVendorString() const
+{
+ return mRenderer->getVendorString();
+}
+
+std::string Context11::getRendererDescription() const
+{
+ return mRenderer->getRendererDescription();
+}
+
+void Context11::insertEventMarker(GLsizei length, const char *marker)
+{
+ auto optionalString = angle::WidenString(static_cast<size_t>(length), marker);
+ if (optionalString.valid())
+ {
+ mRenderer->getAnnotator()->setMarker(optionalString.value().data());
+ }
+}
+
+void Context11::pushGroupMarker(GLsizei length, const char *marker)
+{
+ auto optionalString = angle::WidenString(static_cast<size_t>(length), marker);
+ if (optionalString.valid())
+ {
+ mRenderer->getAnnotator()->beginEvent(optionalString.value().data());
+ }
+}
+
+void Context11::popGroupMarker()
+{
+ mRenderer->getAnnotator()->endEvent();
+}
+
+void Context11::pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message)
+{
+ // Fall through to the EXT_debug_marker functions
+ pushGroupMarker(length, message);
+}
+
+void Context11::popDebugGroup()
+{
+ // Fall through to the EXT_debug_marker functions
+ popGroupMarker();
+}
+
+void Context11::syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits)
+{
+ mRenderer->getStateManager()->syncState(context, dirtyBits);
+}
+
+GLint Context11::getGPUDisjoint()
+{
+ return mRenderer->getGPUDisjoint();
+}
+
+GLint64 Context11::getTimestamp()
+{
+ return mRenderer->getTimestamp();
+}
+
+void Context11::onMakeCurrent(const gl::Context *context)
+{
+ ANGLE_SWALLOW_ERR(mRenderer->getStateManager()->onMakeCurrent(context));
+}
+
+const gl::Caps &Context11::getNativeCaps() const
+{
+ return mRenderer->getNativeCaps();
+}
+
+const gl::TextureCapsMap &Context11::getNativeTextureCaps() const
+{
+ return mRenderer->getNativeTextureCaps();
+}
+
+const gl::Extensions &Context11::getNativeExtensions() const
+{
+ return mRenderer->getNativeExtensions();
+}
+
+const gl::Limitations &Context11::getNativeLimitations() const
+{
+ return mRenderer->getNativeLimitations();
+}
+
+gl::Error Context11::dispatchCompute(const gl::Context *context,
+ GLuint numGroupsX,
+ GLuint numGroupsY,
+ GLuint numGroupsZ)
+{
+ return mRenderer->dispatchCompute(context, numGroupsX, numGroupsY, numGroupsZ);
+}
+
+gl::Error Context11::triggerDrawCallProgramRecompilation(const gl::Context *context,
+ GLenum drawMode)
+{
+ const auto &glState = context->getGLState();
+ const auto *va11 = GetImplAs<VertexArray11>(glState.getVertexArray());
+ const auto *drawFBO = glState.getDrawFramebuffer();
+ gl::Program *program = glState.getProgram();
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+
+ programD3D->updateCachedInputLayout(va11->getCurrentStateSerial(), glState);
+ programD3D->updateCachedOutputLayout(context, drawFBO);
+
+ bool recompileVS = !programD3D->hasVertexExecutableForCachedInputLayout();
+ bool recompileGS = !programD3D->hasGeometryExecutableForPrimitiveType(drawMode);
+ bool recompilePS = !programD3D->hasPixelExecutableForCachedOutputLayout();
+
+ if (!recompileVS && !recompileGS && !recompilePS)
+ {
+ return gl::NoError();
+ }
+
+ // Load the compiler if necessary and recompile the programs.
+ ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized());
+
+ gl::InfoLog infoLog;
+
+ if (recompileVS)
+ {
+ ShaderExecutableD3D *vertexExe = nullptr;
+ ANGLE_TRY(programD3D->getVertexExecutableForCachedInputLayout(&vertexExe, &infoLog));
+ if (!programD3D->hasVertexExecutableForCachedInputLayout())
+ {
+ ASSERT(infoLog.getLength() > 0);
+ ERR() << "Dynamic recompilation error log: " << infoLog.str();
+ return gl::InternalError()
+ << "Error compiling dynamic vertex executable:" << infoLog.str();
+ }
+ }
+
+ if (recompileGS)
+ {
+ ShaderExecutableD3D *geometryExe = nullptr;
+ ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(context, drawMode, &geometryExe,
+ &infoLog));
+ if (!programD3D->hasGeometryExecutableForPrimitiveType(drawMode))
+ {
+ ASSERT(infoLog.getLength() > 0);
+ ERR() << "Dynamic recompilation error log: " << infoLog.str();
+ return gl::InternalError()
+ << "Error compiling dynamic geometry executable:" << infoLog.str();
+ }
+ }
+
+ if (recompilePS)
+ {
+ ShaderExecutableD3D *pixelExe = nullptr;
+ ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(&pixelExe, &infoLog));
+ if (!programD3D->hasPixelExecutableForCachedOutputLayout())
+ {
+ ASSERT(infoLog.getLength() > 0);
+ ERR() << "Dynamic recompilation error log: " << infoLog.str();
+ return gl::InternalError()
+ << "Error compiling dynamic pixel executable:" << infoLog.str();
+ }
+ }
+
+ // Refresh the program cache entry.
+ if (mMemoryProgramCache)
+ {
+ mMemoryProgramCache->updateProgram(context, program);
+ }
+
+ return gl::NoError();
+}
+
+gl::Error Context11::prepareForDrawCall(const gl::Context *context, GLenum drawMode)
+{
+ ANGLE_TRY(mRenderer->getStateManager()->updateState(context, drawMode));
+ return gl::NoError();
+}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h
new file mode 100644
index 0000000000..dd99111b19
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h
@@ -0,0 +1,155 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Context11:
+// D3D11-specific functionality associated with a GL Context.
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_CONTEXT11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_CONTEXT11_H_
+
+#include "libANGLE/renderer/ContextImpl.h"
+
+namespace rx
+{
+class Renderer11;
+
+class Context11 : public ContextImpl
+{
+ public:
+ Context11(const gl::ContextState &state, Renderer11 *renderer);
+ ~Context11() override;
+
+ gl::Error initialize() override;
+
+ // Shader creation
+ CompilerImpl *createCompiler() override;
+ ShaderImpl *createShader(const gl::ShaderState &data) override;
+ ProgramImpl *createProgram(const gl::ProgramState &data) override;
+
+ // Framebuffer creation
+ FramebufferImpl *createFramebuffer(const gl::FramebufferState &data) override;
+
+ // Texture creation
+ TextureImpl *createTexture(const gl::TextureState &state) override;
+
+ // Renderbuffer creation
+ RenderbufferImpl *createRenderbuffer() override;
+
+ // Buffer creation
+ BufferImpl *createBuffer(const gl::BufferState &state) override;
+
+ // Vertex Array creation
+ VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data) override;
+
+ // Query and Fence creation
+ QueryImpl *createQuery(GLenum type) override;
+ FenceNVImpl *createFenceNV() override;
+ SyncImpl *createSync() override;
+
+ // Transform Feedback creation
+ TransformFeedbackImpl *createTransformFeedback(
+ const gl::TransformFeedbackState &state) override;
+
+ // Sampler object creation
+ SamplerImpl *createSampler(const gl::SamplerState &state) override;
+
+ // Program Pipeline object creation
+ ProgramPipelineImpl *createProgramPipeline(const gl::ProgramPipelineState &data) override;
+
+ // Path object creation.
+ std::vector<PathImpl *> createPaths(GLsizei) override;
+
+ // Flush and finish.
+ gl::Error flush(const gl::Context *context) override;
+ gl::Error finish(const gl::Context *context) override;
+
+ // Drawing methods.
+ gl::Error drawArrays(const gl::Context *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count) override;
+ gl::Error drawArraysInstanced(const gl::Context *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount) override;
+
+ gl::Error drawElements(const gl::Context *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices) override;
+ gl::Error drawElementsInstanced(const gl::Context *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei instances) override;
+ gl::Error drawRangeElements(const gl::Context *context,
+ GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const void *indices) override;
+ gl::Error drawArraysIndirect(const gl::Context *context,
+ GLenum mode,
+ const void *indirect) override;
+ gl::Error drawElementsIndirect(const gl::Context *context,
+ GLenum mode,
+ GLenum type,
+ const void *indirect) override;
+
+ // Device loss
+ GLenum getResetStatus() override;
+
+ // Vendor and description strings.
+ std::string getVendorString() const override;
+ std::string getRendererDescription() const override;
+
+ // EXT_debug_marker
+ void insertEventMarker(GLsizei length, const char *marker) override;
+ void pushGroupMarker(GLsizei length, const char *marker) override;
+ void popGroupMarker() override;
+
+ // KHR_debug
+ void pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message) override;
+ void popDebugGroup() override;
+
+ // State sync with dirty bits.
+ void syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits) override;
+
+ // Disjoint timer queries
+ GLint getGPUDisjoint() override;
+ GLint64 getTimestamp() override;
+
+ // Context switching
+ void onMakeCurrent(const gl::Context *context) override;
+
+ // Caps queries
+ const gl::Caps &getNativeCaps() const override;
+ const gl::TextureCapsMap &getNativeTextureCaps() const override;
+ const gl::Extensions &getNativeExtensions() const override;
+ const gl::Limitations &getNativeLimitations() const override;
+
+ Renderer11 *getRenderer() const { return mRenderer; }
+
+ gl::Error dispatchCompute(const gl::Context *context,
+ GLuint numGroupsX,
+ GLuint numGroupsY,
+ GLuint numGroupsZ) override;
+
+ gl::Error triggerDrawCallProgramRecompilation(const gl::Context *context, GLenum drawMode);
+
+ private:
+ gl::Error prepareForDrawCall(const gl::Context *context, GLenum drawMode);
+
+ Renderer11 *mRenderer;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_CONTEXT11_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
index 1c35ab45cc..1e70363e11 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
@@ -27,9 +27,7 @@ DebugAnnotator11::~DebugAnnotator11()
{
if (mInitialized)
{
-#if defined(ANGLE_ENABLE_D3D11_1)
SafeRelease(mUserDefinedAnnotation);
-#endif
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
FreeLibrary(mD3d11Module);
@@ -43,9 +41,7 @@ void DebugAnnotator11::beginEvent(const wchar_t *eventName)
if (mUserDefinedAnnotation != nullptr)
{
-#if defined(ANGLE_ENABLE_D3D11_1)
mUserDefinedAnnotation->BeginEvent(eventName);
-#endif
}
}
@@ -55,9 +51,7 @@ void DebugAnnotator11::endEvent()
if (mUserDefinedAnnotation != nullptr)
{
-#if defined(ANGLE_ENABLE_D3D11_1)
mUserDefinedAnnotation->EndEvent();
-#endif
}
}
@@ -67,16 +61,14 @@ void DebugAnnotator11::setMarker(const wchar_t *markerName)
if (mUserDefinedAnnotation != nullptr)
{
-#if defined(ANGLE_ENABLE_D3D11_1)
mUserDefinedAnnotation->SetMarker(markerName);
-#endif
}
}
bool DebugAnnotator11::getStatus()
{
#if defined(ANGLE_ENABLE_WINDOWS_STORE)
-#if (NTDDI_VERSION == NTDDI_WIN10)
+ static_assert(NTDDI_VERSION >= NTDDI_WIN10, "GetStatus only works on Win10 and above");
initializeDevice();
if (mUserDefinedAnnotation != nullptr)
@@ -85,38 +77,6 @@ bool DebugAnnotator11::getStatus()
}
return true; // Default if initializeDevice() failed
-#elif defined(_DEBUG) && (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
- static bool underCapture = true;
-
- // ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in
- // Windows 8.1/Visual Studio 2013. We can use IDXGraphicsAnalysis, though.
- // The call to GetDebugInterface1 only succeeds if the app is under capture.
- // This should only be called in DEBUG mode.
- // If an app links against DXGIGetDebugInterface1 in release mode then it will fail Windows
- // Store ingestion checks.
-
- // Cache the result to reduce the number of calls to DXGIGetDebugInterface1
- static bool triedIDXGraphicsAnalysis = false;
-
- if (!triedIDXGraphicsAnalysis)
- {
- IDXGraphicsAnalysis *graphicsAnalysis = nullptr;
-
- HRESULT result = DXGIGetDebugInterface1(0, IID_PPV_ARGS(&graphicsAnalysis));
- if (SUCCEEDED(result))
- {
- underCapture = (graphicsAnalysis != nullptr);
- }
-
- SafeRelease(graphicsAnalysis);
- triedIDXGraphicsAnalysis = true;
- }
-
- return underCapture;
-#else
- // We can't detect GetStatus() on release WinRT 8.1 builds, so always return true.
- return true;
-#endif // (NTDDI_VERSION == NTDDI_WIN10) or _DEBUG
#else
// We can't detect GetStatus() on desktop ANGLE builds so always return true.
return true;
@@ -141,14 +101,13 @@ void DebugAnnotator11::initializeDevice()
HRESULT hr = E_FAIL;
// Create a D3D_DRIVER_TYPE_NULL device, which is much cheaper than other types of device.
- hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_NULL, nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, &device, nullptr, &context);
+ hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_NULL, nullptr, 0, nullptr, 0,
+ D3D11_SDK_VERSION, &device, nullptr, &context);
ASSERT(SUCCEEDED(hr));
if (SUCCEEDED(hr))
{
-#if defined(ANGLE_ENABLE_D3D11_1)
mUserDefinedAnnotation = d3d11::DynamicCastComObject<ID3DUserDefinedAnnotation>(context);
ASSERT(mUserDefinedAnnotation != nullptr);
-#endif
mInitialized = true;
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h
index d1a0f7fd2e..62662c49ae 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h
@@ -9,14 +9,12 @@
#ifndef LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_
#define LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_
-#include "common/debug.h"
-
-struct ID3DUserDefinedAnnotation;
+#include "libANGLE/LoggingAnnotator.h"
namespace rx
{
-class DebugAnnotator11 : public gl::DebugAnnotator
+class DebugAnnotator11 : public angle::LoggingAnnotator
{
public:
DebugAnnotator11();
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp
index 53fac65f2a..082f28d794 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp
@@ -4,7 +4,8 @@
// found in the LICENSE file.
//
-// Fence11.cpp: Defines the rx::FenceNV11 and rx::FenceSync11 classes which implement rx::FenceNVImpl and rx::FenceSyncImpl.
+// Fence11.cpp: Defines the rx::FenceNV11 and rx::Sync11 classes which implement
+// rx::FenceNVImpl and rx::SyncImpl.
#include "libANGLE/renderer/d3d/d3d11/Fence11.h"
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
@@ -14,28 +15,30 @@
namespace rx
{
+static const int kDeviceLostCheckPeriod = 64;
+
//
// Template helpers for set and test operations.
//
-template<class FenceClass>
+template <class FenceClass>
gl::Error FenceSetHelper(FenceClass *fence)
{
if (!fence->mQuery)
{
D3D11_QUERY_DESC queryDesc;
- queryDesc.Query = D3D11_QUERY_EVENT;
+ queryDesc.Query = D3D11_QUERY_EVENT;
queryDesc.MiscFlags = 0;
HRESULT result = fence->mRenderer->getDevice()->CreateQuery(&queryDesc, &fence->mQuery);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to create event query, " << gl::FmtHR(result);
}
}
fence->mRenderer->getDeviceContext()->End(fence->mQuery);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
template <class FenceClass>
@@ -44,30 +47,24 @@ gl::Error FenceTestHelper(FenceClass *fence, bool flushCommandBuffer, GLboolean
ASSERT(fence->mQuery);
UINT getDataFlags = (flushCommandBuffer ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH);
- HRESULT result = fence->mRenderer->getDeviceContext()->GetData(fence->mQuery, NULL, 0, getDataFlags);
+ HRESULT result =
+ fence->mRenderer->getDeviceContext()->GetData(fence->mQuery, nullptr, 0, getDataFlags);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to get query data, result: 0x%X.", result);
- }
- else if (fence->mRenderer->isDeviceLost())
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while querying result of an event query.");
+ return gl::OutOfMemory() << "Failed to get query data, " << gl::FmtHR(result);
}
ASSERT(result == S_OK || result == S_FALSE);
*outFinished = ((result == S_OK) ? GL_TRUE : GL_FALSE);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
//
// FenceNV11
//
-FenceNV11::FenceNV11(Renderer11 *renderer)
- : FenceNVImpl(),
- mRenderer(renderer),
- mQuery(NULL)
+FenceNV11::FenceNV11(Renderer11 *renderer) : FenceNVImpl(), mRenderer(renderer), mQuery(nullptr)
{
}
@@ -89,22 +86,26 @@ gl::Error FenceNV11::test(GLboolean *outFinished)
gl::Error FenceNV11::finish()
{
GLboolean finished = GL_FALSE;
+
+ int loopCount = 0;
while (finished != GL_TRUE)
{
- gl::Error error = FenceTestHelper(this, true, &finished);
- if (error.isError())
+ loopCount++;
+ ANGLE_TRY(FenceTestHelper(this, true, &finished));
+
+ if (loopCount % kDeviceLostCheckPeriod == 0 && mRenderer->testDeviceLost())
{
- return error;
+ return gl::OutOfMemory() << "Device was lost while querying result of an event query.";
}
ScheduleYield();
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
//
-// FenceSync11
+// Sync11
//
// Important note on accurate timers in Windows:
@@ -118,38 +119,34 @@ gl::Error FenceNV11::finish()
// We still opt to use QPC. In the present and moving forward, most newer systems will not suffer
// from buggy implementations.
-FenceSync11::FenceSync11(Renderer11 *renderer)
- : FenceSyncImpl(),
- mRenderer(renderer),
- mQuery(NULL)
+Sync11::Sync11(Renderer11 *renderer) : SyncImpl(), mRenderer(renderer), mQuery(nullptr)
{
LARGE_INTEGER counterFreqency = {};
- BOOL success = QueryPerformanceFrequency(&counterFreqency);
- UNUSED_ASSERTION_VARIABLE(success);
+ BOOL success = QueryPerformanceFrequency(&counterFreqency);
ASSERT(success);
mCounterFrequency = counterFreqency.QuadPart;
}
-FenceSync11::~FenceSync11()
+Sync11::~Sync11()
{
SafeRelease(mQuery);
}
-gl::Error FenceSync11::set(GLenum condition, GLbitfield flags)
+gl::Error Sync11::set(GLenum condition, GLbitfield flags)
{
ASSERT(condition == GL_SYNC_GPU_COMMANDS_COMPLETE && flags == 0);
return FenceSetHelper(this);
}
-gl::Error FenceSync11::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult)
+gl::Error Sync11::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult)
{
ASSERT(outResult);
bool flushCommandBuffer = ((flags & GL_SYNC_FLUSH_COMMANDS_BIT) != 0);
GLboolean result = GL_FALSE;
- gl::Error error = FenceTestHelper(this, flushCommandBuffer, &result);
+ gl::Error error = FenceTestHelper(this, flushCommandBuffer, &result);
if (error.isError())
{
*outResult = GL_WAIT_FAILED;
@@ -159,28 +156,34 @@ gl::Error FenceSync11::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *ou
if (result == GL_TRUE)
{
*outResult = GL_ALREADY_SIGNALED;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
if (timeout == 0)
{
*outResult = GL_TIMEOUT_EXPIRED;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
LARGE_INTEGER currentCounter = {};
- BOOL success = QueryPerformanceCounter(&currentCounter);
- UNUSED_ASSERTION_VARIABLE(success);
+ BOOL success = QueryPerformanceCounter(&currentCounter);
ASSERT(success);
- LONGLONG timeoutInSeconds = static_cast<LONGLONG>(timeout) * static_cast<LONGLONG>(1000000ll);
- LONGLONG endCounter = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds;
+ LONGLONG timeoutInSeconds = static_cast<LONGLONG>(timeout / 1000000000ull);
+ LONGLONG endCounter = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds;
+ // Extremely unlikely, but if mCounterFrequency is large enough, endCounter can wrap
+ if (endCounter < currentCounter.QuadPart)
+ {
+ endCounter = MAXLONGLONG;
+ }
+
+ int loopCount = 0;
while (currentCounter.QuadPart < endCounter && !result)
{
+ loopCount++;
ScheduleYield();
success = QueryPerformanceCounter(&currentCounter);
- UNUSED_ASSERTION_VARIABLE(success);
ASSERT(success);
error = FenceTestHelper(this, flushCommandBuffer, &result);
@@ -189,6 +192,12 @@ gl::Error FenceSync11::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *ou
*outResult = GL_WAIT_FAILED;
return error;
}
+
+ if ((loopCount % kDeviceLostCheckPeriod) == 0 && mRenderer->testDeviceLost())
+ {
+ *outResult = GL_WAIT_FAILED;
+ return gl::OutOfMemory() << "Device was lost while querying result of an event query.";
+ }
}
if (currentCounter.QuadPart >= endCounter)
@@ -200,32 +209,32 @@ gl::Error FenceSync11::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *ou
*outResult = GL_CONDITION_SATISFIED;
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error FenceSync11::serverWait(GLbitfield flags, GLuint64 timeout)
+gl::Error Sync11::serverWait(GLbitfield flags, GLuint64 timeout)
{
// Because our API is currently designed to be called from a single thread, we don't need to do
- // extra work for a server-side fence. GPU commands issued after the fence is created will always
- // be processed after the fence is signaled.
- return gl::Error(GL_NO_ERROR);
+ // extra work for a server-side fence. GPU commands issued after the fence is created will
+ // always be processed after the fence is signaled.
+ return gl::NoError();
}
-gl::Error FenceSync11::getStatus(GLint *outResult)
+gl::Error Sync11::getStatus(GLint *outResult)
{
GLboolean result = GL_FALSE;
- gl::Error error = FenceTestHelper(this, false, &result);
+ gl::Error error = FenceTestHelper(this, false, &result);
if (error.isError())
{
- // The spec does not specify any way to report errors during the status test (e.g. device lost)
- // so we report the fence is unblocked in case of error or signaled.
+ // The spec does not specify any way to report errors during the status test (e.g. device
+ // lost) so we report the fence is unblocked in case of error or signaled.
*outResult = GL_SIGNALED;
return error;
}
*outResult = (result ? GL_SIGNALED : GL_UNSIGNALED);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-} // namespace rx
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h
index 595978885b..4168df5365 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h
@@ -4,13 +4,14 @@
// found in the LICENSE file.
//
-// Fence11.h: Defines the rx::FenceNV11 and rx::FenceSync11 classes which implement rx::FenceNVImpl and rx::FenceSyncImpl.
+// Fence11.h: Defines the rx::FenceNV11 and rx::Sync11 classes which implement rx::FenceNVImpl
+// and rx::SyncImpl.
#ifndef LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_
#define LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_
#include "libANGLE/renderer/FenceNVImpl.h"
-#include "libANGLE/renderer/FenceSyncImpl.h"
+#include "libANGLE/renderer/SyncImpl.h"
namespace rx
{
@@ -34,11 +35,11 @@ class FenceNV11 : public FenceNVImpl
ID3D11Query *mQuery;
};
-class FenceSync11 : public FenceSyncImpl
+class Sync11 : public SyncImpl
{
public:
- explicit FenceSync11(Renderer11 *renderer);
- ~FenceSync11() override;
+ explicit Sync11(Renderer11 *renderer);
+ ~Sync11() override;
gl::Error set(GLenum condition, GLbitfield flags) override;
gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) override;
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
index 186a035902..02326d7b50 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
@@ -8,94 +8,119 @@
#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
+#include "common/bitset_utils.h"
#include "common/debug.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
#include "libANGLE/renderer/d3d/d3d11/Clear11.h"
-#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
-#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
-#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
-#include "libANGLE/renderer/d3d/TextureD3D.h"
-#include "libANGLE/Framebuffer.h"
-#include "libANGLE/FramebufferAttachment.h"
-#include "libANGLE/Texture.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+using namespace angle;
namespace rx
{
-Framebuffer11::Framebuffer11(const gl::Framebuffer::Data &data, Renderer11 *renderer)
- : FramebufferD3D(data, renderer), mRenderer(renderer)
+namespace
{
- ASSERT(mRenderer != nullptr);
-}
-
-Framebuffer11::~Framebuffer11()
+gl::Error MarkAttachmentsDirty(const gl::Context *context,
+ const gl::FramebufferAttachment *attachment)
{
-}
-
-static gl::Error InvalidateAttachmentSwizzles(const gl::FramebufferAttachment *attachment)
-{
- if (attachment && attachment->type() == GL_TEXTURE)
+ if (attachment->type() == GL_TEXTURE)
{
gl::Texture *texture = attachment->getTexture();
TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
TextureStorage *texStorage = nullptr;
- gl::Error error = textureD3D->getNativeTexture(&texStorage);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(textureD3D->getNativeTexture(context, &texStorage));
if (texStorage)
{
TextureStorage11 *texStorage11 = GetAs<TextureStorage11>(texStorage);
ASSERT(texStorage11);
- texStorage11->invalidateSwizzleCacheLevel(attachment->mipLevel());
+ texStorage11->markLevelDirty(attachment->mipLevel());
}
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Framebuffer11::invalidateSwizzles() const
+void UpdateCachedRenderTarget(const gl::Context *context,
+ const gl::FramebufferAttachment *attachment,
+ RenderTarget11 *&cachedRenderTarget,
+ OnRenderTargetDirtyBinding *channelBinding)
{
- for (const auto &colorAttachment : mData.getColorAttachments())
+ RenderTarget11 *newRenderTarget = nullptr;
+ if (attachment)
{
- if (colorAttachment.isAttached())
+ // TODO(jmadill): Don't swallow this error.
+ gl::Error error = attachment->getRenderTarget(context, &newRenderTarget);
+ if (error.isError())
{
- gl::Error error = InvalidateAttachmentSwizzles(&colorAttachment);
- if (error.isError())
- {
- return error;
- }
+ ERR() << "Internal rendertarget error: " << error;
}
}
+ if (newRenderTarget != cachedRenderTarget)
+ {
+ OnRenderTargetDirtyChannel *channel =
+ (newRenderTarget ? newRenderTarget->getBroadcastChannel() : nullptr);
+ channelBinding->bind(channel);
+ cachedRenderTarget = newRenderTarget;
+ }
+}
+} // anonymous namespace
+
+Framebuffer11::Framebuffer11(const gl::FramebufferState &data, Renderer11 *renderer)
+ : FramebufferD3D(data, renderer),
+ mRenderer(renderer),
+ mCachedDepthStencilRenderTarget(nullptr),
+ mDepthStencilRenderTargetDirty(this, gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS)
+{
+ ASSERT(mRenderer != nullptr);
+ mCachedColorRenderTargets.fill(nullptr);
+ for (size_t colorIndex = 0; colorIndex < data.getColorAttachments().size(); ++colorIndex)
+ {
+ mColorRenderTargetsDirty.emplace_back(this, colorIndex);
+ }
+}
- gl::Error error = InvalidateAttachmentSwizzles(mData.getDepthAttachment());
- if (error.isError())
+Framebuffer11::~Framebuffer11()
+{
+}
+
+gl::Error Framebuffer11::markAttachmentsDirty(const gl::Context *context) const
+{
+ const auto &colorAttachments = mState.getColorAttachments();
+ for (size_t drawBuffer : mState.getEnabledDrawBuffers())
{
- return error;
+ const gl::FramebufferAttachment &colorAttachment = colorAttachments[drawBuffer];
+ ASSERT(colorAttachment.isAttached());
+ ANGLE_TRY(MarkAttachmentsDirty(context, &colorAttachment));
}
- error = InvalidateAttachmentSwizzles(mData.getStencilAttachment());
- if (error.isError())
+ const gl::FramebufferAttachment *dsAttachment = mState.getDepthOrStencilAttachment();
+ if (dsAttachment)
{
- return error;
+ ANGLE_TRY(MarkAttachmentsDirty(context, dsAttachment));
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Framebuffer11::clear(const gl::Data &data, const ClearParameters &clearParams)
+gl::Error Framebuffer11::clearImpl(const gl::Context *context, const ClearParameters &clearParams)
{
Clear11 *clearer = mRenderer->getClearer();
- gl::Error error(GL_NO_ERROR);
- const gl::FramebufferAttachment *colorAttachment = mData.getFirstColorAttachment();
+ const gl::FramebufferAttachment *colorAttachment = mState.getFirstColorAttachment();
if (clearParams.scissorEnabled == true && colorAttachment != nullptr &&
UsePresentPathFast(mRenderer, colorAttachment))
{
@@ -107,46 +132,43 @@ gl::Error Framebuffer11::clear(const gl::Data &data, const ClearParameters &clea
presentPathFastClearParams.scissor.y = framebufferSize.height -
presentPathFastClearParams.scissor.y -
presentPathFastClearParams.scissor.height;
- error = clearer->clearFramebuffer(presentPathFastClearParams, mData);
+ ANGLE_TRY(clearer->clearFramebuffer(context, presentPathFastClearParams, mState));
}
else
{
- error = clearer->clearFramebuffer(clearParams, mData);
+ ANGLE_TRY(clearer->clearFramebuffer(context, clearParams, mState));
}
- if (error.isError())
- {
- return error;
- }
-
- error = invalidateSwizzles();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(markAttachmentsDirty(context));
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Framebuffer11::invalidate(size_t count, const GLenum *attachments)
+gl::Error Framebuffer11::invalidate(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments)
{
- return invalidateBase(count, attachments, false);
+ return invalidateBase(context, count, attachments, false);
}
-gl::Error Framebuffer11::discard(size_t count, const GLenum *attachments)
+gl::Error Framebuffer11::discard(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments)
{
- return invalidateBase(count, attachments, true);
+ return invalidateBase(context, count, attachments, true);
}
-gl::Error Framebuffer11::invalidateBase(size_t count, const GLenum *attachments, bool useEXTBehavior) const
+gl::Error Framebuffer11::invalidateBase(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments,
+ bool useEXTBehavior) const
{
-#if defined(ANGLE_ENABLE_D3D11_1)
ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
if (!deviceContext1)
{
// DiscardView() is only supported on ID3D11DeviceContext1
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
bool foundDepth = false;
@@ -175,37 +197,14 @@ gl::Error Framebuffer11::invalidateBase(size_t count, const GLenum *attachments,
ASSERT((attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15) ||
(attachments[i] == GL_COLOR));
- RenderTarget11 *renderTarget = nullptr;
- ID3D11View *colorView = nullptr;
- gl::Error error(GL_NO_ERROR);
- size_t colorAttachmentID = 0;
-
- if (attachments[i] == GL_COLOR)
- {
- colorAttachmentID = 0;
- }
- else
+ size_t colorIndex =
+ (attachments[i] == GL_COLOR ? 0u : (attachments[i] - GL_COLOR_ATTACHMENT0));
+ const gl::FramebufferAttachment *colorAttachment =
+ mState.getColorAttachment(colorIndex);
+ if (colorAttachment)
{
- colorAttachmentID = attachments[i] - GL_COLOR_ATTACHMENT0;
+ ANGLE_TRY(invalidateAttachment(context, colorAttachment));
}
-
- if (mData.getColorAttachment(static_cast<unsigned int>(colorAttachmentID)))
- {
- error = mData.getColorAttachment(static_cast<unsigned int>(colorAttachmentID))
- ->getRenderTarget(&renderTarget);
- if (error.isError())
- {
- return error;
- }
-
- colorView = renderTarget->getRenderTargetView();
-
- if (colorView != nullptr)
- {
- deviceContext1->DiscardView(colorView);
- }
- }
-
break;
}
}
@@ -222,7 +221,7 @@ gl::Error Framebuffer11::invalidateBase(size_t count, const GLenum *attachments,
discardDepth = foundDepth;
// Don't bother discarding the stencil buffer if the depth buffer will already do it
- discardStencil = foundStencil && (!discardDepth || mData.getDepthAttachment() == nullptr);
+ discardStencil = foundStencil && (!discardDepth || mState.getDepthAttachment() == nullptr);
}
else
{
@@ -230,94 +229,86 @@ gl::Error Framebuffer11::invalidateBase(size_t count, const GLenum *attachments,
// attachments list does not include DEPTH_STENCIL_ATTACHMENT or both DEPTH_ATTACHMENT and
// STENCIL_ATTACHMENT, then only the specified portion of every pixel in the subregion of pixels
// of the DEPTH_STENCIL buffer may be invalidated, and the other portion must be preserved.
- discardDepth = (foundDepth && foundStencil) || (foundDepth && (mData.getStencilAttachment() == nullptr));
- discardStencil = (foundStencil && (mData.getDepthAttachment() == nullptr));
+ discardDepth = (foundDepth && foundStencil) ||
+ (foundDepth && (mState.getStencilAttachment() == nullptr));
+ discardStencil = (foundStencil && (mState.getDepthAttachment() == nullptr));
}
- if (discardDepth && mData.getDepthAttachment())
+ if (discardDepth && mState.getDepthAttachment())
{
- RenderTarget11 *renderTarget = nullptr;
- ID3D11View *depthView = nullptr;
- gl::Error error(GL_NO_ERROR);
-
- error = mData.getDepthAttachment()->getRenderTarget(&renderTarget);
- if (error.isError())
- {
- return error;
- }
-
- depthView = renderTarget->getDepthStencilView();
-
- if (depthView != nullptr)
- {
- deviceContext1->DiscardView(depthView);
- }
+ ANGLE_TRY(invalidateAttachment(context, mState.getDepthAttachment()));
}
- if (discardStencil && mData.getStencilAttachment())
+ if (discardStencil && mState.getStencilAttachment())
{
- RenderTarget11 *renderTarget = nullptr;
- ID3D11View *stencilView = nullptr;
- gl::Error error(GL_NO_ERROR);
-
- error = mData.getStencilAttachment()->getRenderTarget(&renderTarget);
- if (error.isError())
- {
- return error;
- }
-
- stencilView = renderTarget->getDepthStencilView();
-
- if (stencilView != nullptr)
- {
- deviceContext1->DiscardView(stencilView);
- }
+ ANGLE_TRY(invalidateAttachment(context, mState.getStencilAttachment()));
}
-#endif // ANGLE_ENABLE_D3D11_1
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Framebuffer11::invalidateSub(size_t, const GLenum *, const gl::Rectangle &)
+gl::Error Framebuffer11::invalidateSub(const gl::Context *context,
+ size_t,
+ const GLenum *,
+ const gl::Rectangle &)
{
// A no-op implementation conforms to the spec, so don't call UNIMPLEMENTED()
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Framebuffer11::readPixelsImpl(const gl::Rectangle &area,
+gl::Error Framebuffer11::invalidateAttachment(const gl::Context *context,
+ const gl::FramebufferAttachment *attachment) const
+{
+ ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
+ ASSERT(deviceContext1);
+ ASSERT(attachment && attachment->isAttached());
+
+ RenderTarget11 *renderTarget = nullptr;
+ ANGLE_TRY(attachment->getRenderTarget(context, &renderTarget));
+ const auto &rtv = renderTarget->getRenderTargetView();
+
+ if (rtv.valid())
+ {
+ deviceContext1->DiscardView(rtv.get());
+ }
+
+ return gl::NoError();
+}
+
+gl::Error Framebuffer11::readPixelsImpl(const gl::Context *context,
+ const gl::Rectangle &area,
GLenum format,
GLenum type,
size_t outputPitch,
const gl::PixelPackState &pack,
- uint8_t *pixels) const
+ uint8_t *pixels)
{
- const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment();
+ const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
ASSERT(readAttachment);
- gl::Buffer *packBuffer = pack.pixelBuffer.get();
+ gl::Buffer *packBuffer = context->getGLState().getTargetBuffer(gl::BufferBinding::PixelPack);
if (packBuffer != nullptr)
{
- if (pack.rowLength != 0 || pack.skipRows != 0 || pack.skipPixels != 0)
- {
- UNIMPLEMENTED();
- return gl::Error(GL_INVALID_OPERATION,
- "Unimplemented pixel store parameters in readPixelsImpl");
- }
-
Buffer11 *packBufferStorage = GetImplAs<Buffer11>(packBuffer);
PackPixelsParams packParams(area, format, type, static_cast<GLuint>(outputPitch), pack,
- reinterpret_cast<ptrdiff_t>(pixels));
+ packBuffer, reinterpret_cast<ptrdiff_t>(pixels));
- return packBufferStorage->packPixels(*readAttachment, packParams);
+ return packBufferStorage->packPixels(context, *readAttachment, packParams);
}
- return mRenderer->readFromAttachment(*readAttachment, area, format, type,
+ return mRenderer->readFromAttachment(context, *readAttachment, area, format, type,
static_cast<GLuint>(outputPitch), pack, pixels);
}
-gl::Error Framebuffer11::blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor,
- bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter,
- const gl::Framebuffer *sourceFramebuffer)
+gl::Error Framebuffer11::blitImpl(const gl::Context *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ const gl::Rectangle *scissor,
+ bool blitRenderTarget,
+ bool blitDepth,
+ bool blitStencil,
+ GLenum filter,
+ const gl::Framebuffer *sourceFramebuffer)
{
if (blitRenderTarget)
{
@@ -325,15 +316,11 @@ gl::Error Framebuffer11::blit(const gl::Rectangle &sourceArea, const gl::Rectang
ASSERT(readBuffer);
RenderTargetD3D *readRenderTarget = nullptr;
- gl::Error error = readBuffer->getRenderTarget(&readRenderTarget);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(readBuffer->getRenderTarget(context, &readRenderTarget));
ASSERT(readRenderTarget);
- const auto &colorAttachments = mData.getColorAttachments();
- const auto &drawBufferStates = mData.getDrawBufferStates();
+ const auto &colorAttachments = mState.getColorAttachments();
+ const auto &drawBufferStates = mState.getDrawBufferStates();
for (size_t colorAttachment = 0; colorAttachment < colorAttachments.size(); colorAttachment++)
{
@@ -343,11 +330,7 @@ gl::Error Framebuffer11::blit(const gl::Rectangle &sourceArea, const gl::Rectang
drawBufferStates[colorAttachment] != GL_NONE)
{
RenderTargetD3D *drawRenderTarget = nullptr;
- error = drawBuffer.getRenderTarget(&drawRenderTarget);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(drawBuffer.getRenderTarget(context, &drawRenderTarget));
ASSERT(drawRenderTarget);
const bool invertColorSource = UsePresentPathFast(mRenderer, readBuffer);
@@ -368,13 +351,9 @@ gl::Error Framebuffer11::blit(const gl::Rectangle &sourceArea, const gl::Rectang
actualDestArea.height = -destArea.height;
}
- error = mRenderer->blitRenderbufferRect(actualSourceArea, actualDestArea,
- readRenderTarget, drawRenderTarget, filter,
- scissor, blitRenderTarget, false, false);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mRenderer->blitRenderbufferRect(
+ context, actualSourceArea, actualDestArea, readRenderTarget, drawRenderTarget,
+ filter, scissor, blitRenderTarget, false, false));
}
}
}
@@ -385,46 +364,144 @@ gl::Error Framebuffer11::blit(const gl::Rectangle &sourceArea, const gl::Rectang
ASSERT(readBuffer);
RenderTargetD3D *readRenderTarget = nullptr;
- gl::Error error = readBuffer->getRenderTarget(&readRenderTarget);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(readBuffer->getRenderTarget(context, &readRenderTarget));
ASSERT(readRenderTarget);
- const gl::FramebufferAttachment *drawBuffer = mData.getDepthOrStencilAttachment();
+ const gl::FramebufferAttachment *drawBuffer = mState.getDepthOrStencilAttachment();
ASSERT(drawBuffer);
RenderTargetD3D *drawRenderTarget = nullptr;
- error = drawBuffer->getRenderTarget(&drawRenderTarget);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(drawBuffer->getRenderTarget(context, &drawRenderTarget));
ASSERT(drawRenderTarget);
- error = mRenderer->blitRenderbufferRect(sourceArea, destArea, readRenderTarget, drawRenderTarget, filter, scissor,
- false, blitDepth, blitStencil);
- if (error.isError())
+ ANGLE_TRY(mRenderer->blitRenderbufferRect(context, sourceArea, destArea, readRenderTarget,
+ drawRenderTarget, filter, scissor, false,
+ blitDepth, blitStencil));
+ }
+
+ ANGLE_TRY(markAttachmentsDirty(context));
+ return gl::NoError();
+}
+
+GLenum Framebuffer11::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const
+{
+ RenderTarget11 *renderTarget11 = GetAs<RenderTarget11>(renderTarget);
+ return renderTarget11->getFormatSet().format().fboImplementationInternalFormat;
+}
+
+void Framebuffer11::updateColorRenderTarget(const gl::Context *context, size_t colorIndex)
+{
+ UpdateCachedRenderTarget(context, mState.getColorAttachment(colorIndex),
+ mCachedColorRenderTargets[colorIndex],
+ &mColorRenderTargetsDirty[colorIndex]);
+}
+
+void Framebuffer11::updateDepthStencilRenderTarget(const gl::Context *context)
+{
+ UpdateCachedRenderTarget(context, mState.getDepthOrStencilAttachment(),
+ mCachedDepthStencilRenderTarget, &mDepthStencilRenderTargetDirty);
+}
+
+void Framebuffer11::syncState(const gl::Context *context,
+ const gl::Framebuffer::DirtyBits &dirtyBits)
+{
+ const auto &mergedDirtyBits = dirtyBits | mInternalDirtyBits;
+ mInternalDirtyBits.reset();
+
+ for (auto dirtyBit : mergedDirtyBits)
+ {
+ switch (dirtyBit)
{
- return error;
+ case gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
+ case gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
+ updateDepthStencilRenderTarget(context);
+ break;
+ case gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
+ case gl::Framebuffer::DIRTY_BIT_READ_BUFFER:
+ break;
+ case gl::Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
+ case gl::Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
+ case gl::Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
+ case gl::Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
+ break;
+ default:
+ {
+ ASSERT(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 &&
+ dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
+ size_t colorIndex =
+ static_cast<size_t>(dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
+ updateColorRenderTarget(context, colorIndex);
+ break;
+ }
}
}
- gl::Error error = invalidateSwizzles();
- if (error.isError())
+ // We should not have dirtied any additional state during our sync.
+ ASSERT(!mInternalDirtyBits.any());
+
+ FramebufferD3D::syncState(context, dirtyBits);
+
+ // Call this last to allow the state manager to take advantage of the cached render targets.
+ mRenderer->getStateManager()->invalidateRenderTarget();
+
+ // Call this to syncViewport for framebuffer default parameters.
+ if (mState.getDefaultWidth() != 0 || mState.getDefaultHeight() != 0)
+ {
+ mRenderer->getStateManager()->invalidateViewport(context);
+ }
+}
+
+void Framebuffer11::signal(size_t channelID, const gl::Context *context)
+{
+ if (channelID == gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS)
+ {
+ // Stencil is redundant in this case.
+ mInternalDirtyBits.set(gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT);
+ mCachedDepthStencilRenderTarget = nullptr;
+ }
+ else
{
- return error;
+ mInternalDirtyBits.set(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 + channelID);
+ mCachedColorRenderTargets[channelID] = nullptr;
}
- return gl::Error(GL_NO_ERROR);
+ // Notify the context we need to re-validate the RenderTarget.
+ // TODO(jmadill): Check that we're the active draw framebuffer.
+ mRenderer->getStateManager()->invalidateRenderTarget();
}
-GLenum Framebuffer11::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const
+gl::Error Framebuffer11::getSamplePosition(size_t index, GLfloat *xy) const
{
- RenderTarget11 *renderTarget11 = GetAs<RenderTarget11>(renderTarget);
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(renderTarget11->getDXGIFormat());
- return dxgiFormatInfo.internalFormat;
+ const gl::FramebufferAttachment *attachment = mState.getFirstNonNullAttachment();
+ ASSERT(attachment);
+ GLsizei sampleCount = attachment->getSamples();
+
+ d3d11_gl::GetSamplePosition(sampleCount, index, xy);
+ return gl::NoError();
+}
+
+bool Framebuffer11::hasAnyInternalDirtyBit() const
+{
+ return mInternalDirtyBits.any();
+}
+
+void Framebuffer11::syncInternalState(const gl::Context *context)
+{
+ syncState(context, gl::Framebuffer::DirtyBits());
}
+RenderTarget11 *Framebuffer11::getFirstRenderTarget() const
+{
+ ASSERT(mInternalDirtyBits.none());
+ for (auto *renderTarget : mCachedColorRenderTargets)
+ {
+ if (renderTarget)
+ {
+ return renderTarget;
+ }
+ }
+
+ return mCachedDepthStencilRenderTarget;
}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
index c8a33ec7e5..afdda299b9 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
@@ -10,43 +10,93 @@
#define LIBANGLE_RENDERER_D3D_D3D11_FRAMBUFFER11_H_
#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/signal_utils.h"
namespace rx
{
class Renderer11;
-class Framebuffer11 : public FramebufferD3D
+class Framebuffer11 : public FramebufferD3D, public OnRenderTargetDirtyReceiver
{
public:
- Framebuffer11(const gl::Framebuffer::Data &data, Renderer11 *renderer);
- virtual ~Framebuffer11();
+ Framebuffer11(const gl::FramebufferState &data, Renderer11 *renderer);
+ ~Framebuffer11() override;
- gl::Error discard(size_t count, const GLenum *attachments) override;
- gl::Error invalidate(size_t count, const GLenum *attachments) override;
- gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override;
+ gl::Error discard(const gl::Context *context, size_t count, const GLenum *attachments) override;
+ gl::Error invalidate(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments) override;
+ gl::Error invalidateSub(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments,
+ const gl::Rectangle &area) override;
// Invalidate the cached swizzles of all bound texture attachments.
- gl::Error invalidateSwizzles() const;
+ gl::Error markAttachmentsDirty(const gl::Context *context) const;
+
+ void syncState(const gl::Context *context,
+ const gl::Framebuffer::DirtyBits &dirtyBits) override;
+
+ const RenderTargetArray &getCachedColorRenderTargets() const
+ {
+ return mCachedColorRenderTargets;
+ }
+ const RenderTarget11 *getCachedDepthStencilRenderTarget() const
+ {
+ return mCachedDepthStencilRenderTarget;
+ }
+
+ RenderTarget11 *getFirstRenderTarget() const;
+
+ bool hasAnyInternalDirtyBit() const;
+ void syncInternalState(const gl::Context *context);
+
+ void signal(size_t channelID, const gl::Context *context) override;
+
+ gl::Error getSamplePosition(size_t index, GLfloat *xy) const override;
private:
- gl::Error clear(const gl::Data &data, const ClearParameters &clearParams) override;
+ gl::Error clearImpl(const gl::Context *context, const ClearParameters &clearParams) override;
- gl::Error readPixelsImpl(const gl::Rectangle &area,
+ gl::Error readPixelsImpl(const gl::Context *context,
+ const gl::Rectangle &area,
GLenum format,
GLenum type,
size_t outputPitch,
const gl::PixelPackState &pack,
- uint8_t *pixels) const override;
+ uint8_t *pixels) override;
- gl::Error blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor,
- bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter,
- const gl::Framebuffer *sourceFramebuffer) override;
+ gl::Error blitImpl(const gl::Context *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ const gl::Rectangle *scissor,
+ bool blitRenderTarget,
+ bool blitDepth,
+ bool blitStencil,
+ GLenum filter,
+ const gl::Framebuffer *sourceFramebuffer) override;
- gl::Error invalidateBase(size_t count, const GLenum *attachments, bool useEXTBehavior) const;
+ gl::Error invalidateBase(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments,
+ bool useEXTBehavior) const;
+ gl::Error invalidateAttachment(const gl::Context *context,
+ const gl::FramebufferAttachment *attachment) const;
GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const override;
+ void updateColorRenderTarget(const gl::Context *context, size_t colorIndex);
+ void updateDepthStencilRenderTarget(const gl::Context *context);
+
Renderer11 *const mRenderer;
+ RenderTargetArray mCachedColorRenderTargets;
+ RenderTarget11 *mCachedDepthStencilRenderTarget;
+
+ std::vector<OnRenderTargetDirtyBinding> mColorRenderTargetsDirty;
+ OnRenderTargetDirtyBinding mDepthStencilRenderTargetDirty;
+
+ gl::Framebuffer::DirtyBits mInternalDirtyBits;
};
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
index c52092d81e..bd921f1935 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
@@ -26,10 +26,10 @@ namespace rx
Image11::Image11(Renderer11 *renderer)
: mRenderer(renderer),
mDXGIFormat(DXGI_FORMAT_UNKNOWN),
- mStagingTexture(NULL),
+ mStagingTexture(),
mStagingSubresource(0),
mRecoverFromStorage(false),
- mAssociatedStorage(NULL),
+ mAssociatedStorage(nullptr),
mAssociatedImageIndex(gl::ImageIndex::MakeInvalid()),
mRecoveredFromStorageCount(0)
{
@@ -41,55 +41,106 @@ Image11::~Image11()
releaseStagingTexture();
}
-gl::Error Image11::generateMipmap(Image11 *dest, Image11 *src)
+// static
+gl::Error Image11::GenerateMipmap(const gl::Context *context,
+ Image11 *dest,
+ Image11 *src,
+ const Renderer11DeviceCaps &rendererCaps)
{
ASSERT(src->getDXGIFormat() == dest->getDXGIFormat());
ASSERT(src->getWidth() == 1 || src->getWidth() / 2 == dest->getWidth());
ASSERT(src->getHeight() == 1 || src->getHeight() / 2 == dest->getHeight());
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(src->getDXGIFormat());
- ASSERT(dxgiFormatInfo.mipGenerationFunction != NULL);
-
D3D11_MAPPED_SUBRESOURCE destMapped;
- gl::Error error = dest->map(D3D11_MAP_WRITE, &destMapped);
+ ANGLE_TRY(dest->map(context, D3D11_MAP_WRITE, &destMapped));
+
+ D3D11_MAPPED_SUBRESOURCE srcMapped;
+ gl::Error error = src->map(context, D3D11_MAP_READ, &srcMapped);
if (error.isError())
{
+ dest->unmap();
return error;
}
+ const uint8_t *sourceData = reinterpret_cast<const uint8_t *>(srcMapped.pData);
+ uint8_t *destData = reinterpret_cast<uint8_t *>(destMapped.pData);
+
+ auto mipGenerationFunction =
+ d3d11::Format::Get(src->getInternalFormat(), rendererCaps).format().mipGenerationFunction;
+ mipGenerationFunction(src->getWidth(), src->getHeight(), src->getDepth(), sourceData,
+ srcMapped.RowPitch, srcMapped.DepthPitch, destData, destMapped.RowPitch,
+ destMapped.DepthPitch);
+
+ dest->unmap();
+ src->unmap();
+
+ dest->markDirty();
+
+ return gl::NoError();
+}
+
+// static
+gl::Error Image11::CopyImage(const gl::Context *context,
+ Image11 *dest,
+ Image11 *source,
+ const gl::Rectangle &sourceRect,
+ const gl::Offset &destOffset,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const Renderer11DeviceCaps &rendererCaps)
+{
+ D3D11_MAPPED_SUBRESOURCE destMapped;
+ ANGLE_TRY(dest->map(context, D3D11_MAP_WRITE, &destMapped));
+
D3D11_MAPPED_SUBRESOURCE srcMapped;
- error = src->map(D3D11_MAP_READ, &srcMapped);
+ gl::Error error = source->map(context, D3D11_MAP_READ, &srcMapped);
if (error.isError())
{
dest->unmap();
return error;
}
- const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(srcMapped.pData);
- uint8_t *destData = reinterpret_cast<uint8_t*>(destMapped.pData);
+ const auto &sourceFormat =
+ d3d11::Format::Get(source->getInternalFormat(), rendererCaps).format();
+ GLuint sourcePixelBytes =
+ gl::GetSizedInternalFormatInfo(sourceFormat.fboImplementationInternalFormat).pixelBytes;
+
+ GLenum destUnsizedFormat = gl::GetUnsizedFormat(dest->getInternalFormat());
+ const auto &destFormat = d3d11::Format::Get(dest->getInternalFormat(), rendererCaps).format();
+ const auto &destFormatInfo =
+ gl::GetSizedInternalFormatInfo(destFormat.fboImplementationInternalFormat);
+ GLuint destPixelBytes = destFormatInfo.pixelBytes;
- dxgiFormatInfo.mipGenerationFunction(src->getWidth(), src->getHeight(), src->getDepth(),
- sourceData, srcMapped.RowPitch, srcMapped.DepthPitch,
- destData, destMapped.RowPitch, destMapped.DepthPitch);
+ const uint8_t *sourceData = reinterpret_cast<const uint8_t *>(srcMapped.pData) +
+ sourceRect.x * sourcePixelBytes + sourceRect.y * srcMapped.RowPitch;
+ uint8_t *destData = reinterpret_cast<uint8_t *>(destMapped.pData) +
+ destOffset.x * destPixelBytes + destOffset.y * destMapped.RowPitch;
+
+ CopyImageCHROMIUM(sourceData, srcMapped.RowPitch, sourcePixelBytes,
+ sourceFormat.colorReadFunction, destData, destMapped.RowPitch, destPixelBytes,
+ destFormat.colorWriteFunction, destUnsizedFormat,
+ destFormatInfo.componentType, sourceRect.width, sourceRect.height,
+ unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
dest->unmap();
- src->unmap();
+ source->unmap();
dest->markDirty();
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
bool Image11::isDirty() const
{
- // If mDirty is true
- // AND mStagingTexture doesn't exist AND mStagingTexture doesn't need to be recovered from TextureStorage
- // AND the texture doesn't require init data (i.e. a blank new texture will suffice)
- // then isDirty should still return false.
- if (mDirty && !mStagingTexture && !mRecoverFromStorage)
+ // If mDirty is true AND mStagingTexture doesn't exist AND mStagingTexture doesn't need to be
+ // recovered from TextureStorage AND the texture doesn't require init data (i.e. a blank new
+ // texture will suffice) AND robust resource initialization is not enabled then isDirty should
+ // still return false.
+ if (mDirty && !mStagingTexture.valid() && !mRecoverFromStorage)
{
const Renderer11DeviceCaps &deviceCaps = mRenderer->getRenderer11DeviceCaps();
- const d3d11::TextureFormat formatInfo = d3d11::GetTextureFormatInfo(mInternalFormat, deviceCaps);
+ const auto &formatInfo = d3d11::Format::Get(mInternalFormat, deviceCaps);
if (formatInfo.dataInitializerFunction == nullptr)
{
return false;
@@ -99,92 +150,69 @@ bool Image11::isDirty() const
return mDirty;
}
-gl::Error Image11::copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region)
+gl::Error Image11::copyToStorage(const gl::Context *context,
+ TextureStorage *storage,
+ const gl::ImageIndex &index,
+ const gl::Box &region)
{
TextureStorage11 *storage11 = GetAs<TextureStorage11>(storage);
- // If an app's behavior results in an Image11 copying its data to/from to a TextureStorage multiple times,
- // then we should just keep the staging texture around to prevent the copying from impacting perf.
- // We allow the Image11 to copy its data to/from TextureStorage once.
- // This accounts for an app making a late call to glGenerateMipmap.
+ // If an app's behavior results in an Image11 copying its data to/from to a TextureStorage
+ // multiple times, then we should just keep the staging texture around to prevent the copying
+ // from impacting perf. We allow the Image11 to copy its data to/from TextureStorage once. This
+ // accounts for an app making a late call to glGenerateMipmap.
bool attemptToReleaseStagingTexture = (mRecoveredFromStorageCount < 2);
if (attemptToReleaseStagingTexture)
{
- // If another image is relying on this Storage for its data, then we must let it recover its data before we overwrite it.
- gl::Error error = storage11->releaseAssociatedImage(index, this);
- if (error.isError())
- {
- return error;
- }
+ // If another image is relying on this Storage for its data, then we must let it recover its
+ // data before we overwrite it.
+ ANGLE_TRY(storage11->releaseAssociatedImage(context, index, this));
}
- ID3D11Resource *stagingTexture = NULL;
+ const TextureHelper11 *stagingTexture = nullptr;
unsigned int stagingSubresourceIndex = 0;
- gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex);
- if (error.isError())
- {
- return error;
- }
-
- error = storage11->updateSubresourceLevel(stagingTexture, stagingSubresourceIndex, index, region);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(getStagingTexture(&stagingTexture, &stagingSubresourceIndex));
+ ANGLE_TRY(storage11->updateSubresourceLevel(context, *stagingTexture, stagingSubresourceIndex,
+ index, region));
// Once the image data has been copied into the Storage, we can release it locally.
if (attemptToReleaseStagingTexture)
{
storage11->associateImage(this, index);
releaseStagingTexture();
- mRecoverFromStorage = true;
- mAssociatedStorage = storage11;
+ mRecoverFromStorage = true;
+ mAssociatedStorage = storage11;
mAssociatedImageIndex = index;
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-bool Image11::isAssociatedStorageValid(TextureStorage11* textureStorage) const
+void Image11::verifyAssociatedStorageValid(TextureStorage11 *textureStorage) const
{
- return (mAssociatedStorage == textureStorage);
+ ASSERT(mAssociatedStorage == textureStorage);
}
-gl::Error Image11::recoverFromAssociatedStorage()
+gl::Error Image11::recoverFromAssociatedStorage(const gl::Context *context)
{
if (mRecoverFromStorage)
{
- gl::Error error = createStagingTexture();
- if (error.isError())
- {
- return error;
- }
-
- bool textureStorageCorrect = mAssociatedStorage->isAssociatedImageValid(mAssociatedImageIndex, this);
+ ANGLE_TRY(createStagingTexture());
- // This means that the cached TextureStorage has been modified after this Image11 released its copy of its data.
- // This should not have happened. The TextureStorage should have told this Image11 to recover its data before it was overwritten.
- ASSERT(textureStorageCorrect);
+ mAssociatedStorage->verifyAssociatedImageValid(mAssociatedImageIndex, this);
- if (textureStorageCorrect)
- {
- // CopySubResource from the Storage to the Staging texture
- gl::Box region(0, 0, 0, mWidth, mHeight, mDepth);
- error = mAssociatedStorage->copySubresourceLevel(mStagingTexture, mStagingSubresource, mAssociatedImageIndex, region);
- if (error.isError())
- {
- return error;
- }
-
- mRecoveredFromStorageCount += 1;
- }
+ // CopySubResource from the Storage to the Staging texture
+ gl::Box region(0, 0, 0, mWidth, mHeight, mDepth);
+ ANGLE_TRY(mAssociatedStorage->copySubresourceLevel(
+ context, mStagingTexture, mStagingSubresource, mAssociatedImageIndex, region));
+ mRecoveredFromStorageCount += 1;
// Reset all the recovery parameters, even if the texture storage association is broken.
disassociateStorage();
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
void Image11::disassociateStorage()
@@ -194,17 +222,18 @@ void Image11::disassociateStorage()
// Make the texturestorage release the Image11 too
mAssociatedStorage->disassociateImage(mAssociatedImageIndex, this);
- mRecoverFromStorage = false;
- mAssociatedStorage = NULL;
+ mRecoverFromStorage = false;
+ mAssociatedStorage = nullptr;
mAssociatedImageIndex = gl::ImageIndex::MakeInvalid();
}
}
-bool Image11::redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease)
+bool Image11::redefine(GLenum target,
+ GLenum internalformat,
+ const gl::Extents &size,
+ bool forceRelease)
{
- if (mWidth != size.width ||
- mHeight != size.height ||
- mInternalFormat != internalformat ||
+ if (mWidth != size.width || mHeight != size.height || mInternalFormat != internalformat ||
forceRelease)
{
// End the association with the TextureStorage, since that data will be out of date.
@@ -212,19 +241,20 @@ bool Image11::redefine(GLenum target, GLenum internalformat, const gl::Extents &
disassociateStorage();
mRecoveredFromStorageCount = 0;
- mWidth = size.width;
- mHeight = size.height;
- mDepth = size.depth;
+ mWidth = size.width;
+ mHeight = size.height;
+ mDepth = size.depth;
mInternalFormat = internalformat;
- mTarget = target;
+ mTarget = target;
// compute the d3d format that will be used
- const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, mRenderer->getRenderer11DeviceCaps());
+ const d3d11::Format &formatInfo =
+ d3d11::Format::Get(internalformat, mRenderer->getRenderer11DeviceCaps());
mDXGIFormat = formatInfo.texFormat;
mRenderable = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
releaseStagingTexture();
- mDirty = (formatInfo.dataInitializerFunction != NULL);
+ mDirty = (formatInfo.dataInitializerFunction != nullptr);
return true;
}
@@ -241,119 +271,125 @@ DXGI_FORMAT Image11::getDXGIFormat() const
return mDXGIFormat;
}
-// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
+// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as
+// format/type at input
// into the target pixel rectangle.
-gl::Error Image11::loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input)
+gl::Error Image11::loadData(const gl::Context *context,
+ const gl::Box &area,
+ const gl::PixelUnpackState &unpack,
+ GLenum type,
+ const void *input,
+ bool applySkipImages)
{
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
- GLsizei inputRowPitch = formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength);
- GLsizei inputDepthPitch = formatInfo.computeDepthPitch(
- type, area.width, area.height, unpack.alignment, unpack.rowLength, unpack.imageHeight);
- GLsizei inputSkipBytes = formatInfo.computeSkipPixels(
- inputRowPitch, inputDepthPitch, unpack.skipImages, unpack.skipRows, unpack.skipPixels);
-
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat);
- GLuint outputPixelSize = dxgiFormatInfo.pixelBytes;
-
- const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat, mRenderer->getRenderer11DeviceCaps());
- LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(type).loadFunction;
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat);
+ GLuint inputRowPitch = 0;
+ ANGLE_TRY_RESULT(
+ formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength),
+ inputRowPitch);
+ GLuint inputDepthPitch = 0;
+ ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(area.height, unpack.imageHeight, inputRowPitch),
+ inputDepthPitch);
+ GLuint inputSkipBytes = 0;
+ ANGLE_TRY_RESULT(
+ formatInfo.computeSkipBytes(inputRowPitch, inputDepthPitch, unpack, applySkipImages),
+ inputSkipBytes);
+
+ const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat);
+ GLuint outputPixelSize = dxgiFormatInfo.pixelBytes;
+
+ const d3d11::Format &d3dFormatInfo =
+ d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps());
+ LoadImageFunction loadFunction = d3dFormatInfo.getLoadFunctions()(type).loadFunction;
D3D11_MAPPED_SUBRESOURCE mappedImage;
- gl::Error error = map(D3D11_MAP_WRITE, &mappedImage);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(map(context, D3D11_MAP_WRITE, &mappedImage));
- uint8_t *offsetMappedData = (reinterpret_cast<uint8_t*>(mappedImage.pData) + (area.y * mappedImage.RowPitch + area.x * outputPixelSize + area.z * mappedImage.DepthPitch));
+ uint8_t *offsetMappedData = (reinterpret_cast<uint8_t *>(mappedImage.pData) +
+ (area.y * mappedImage.RowPitch + area.x * outputPixelSize +
+ area.z * mappedImage.DepthPitch));
loadFunction(area.width, area.height, area.depth,
reinterpret_cast<const uint8_t *>(input) + inputSkipBytes, inputRowPitch,
inputDepthPitch, offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch);
unmap();
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Image11::loadCompressedData(const gl::Box &area, const void *input)
+gl::Error Image11::loadCompressedData(const gl::Context *context,
+ const gl::Box &area,
+ const void *input)
{
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
- GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0);
- GLsizei inputDepthPitch =
- formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0, 0);
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat);
+ GLsizei inputRowPitch = 0;
+ ANGLE_TRY_RESULT(formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0), inputRowPitch);
+ GLsizei inputDepthPitch = 0;
+ ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(area.height, 0, inputRowPitch), inputDepthPitch);
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat);
- GLuint outputPixelSize = dxgiFormatInfo.pixelBytes;
- GLuint outputBlockWidth = dxgiFormatInfo.blockWidth;
- GLuint outputBlockHeight = dxgiFormatInfo.blockHeight;
+ const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat);
+ GLuint outputPixelSize = dxgiFormatInfo.pixelBytes;
+ GLuint outputBlockWidth = dxgiFormatInfo.blockWidth;
+ GLuint outputBlockHeight = dxgiFormatInfo.blockHeight;
ASSERT(area.x % outputBlockWidth == 0);
ASSERT(area.y % outputBlockHeight == 0);
- const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat, mRenderer->getRenderer11DeviceCaps());
- LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(GL_UNSIGNED_BYTE).loadFunction;
+ const d3d11::Format &d3dFormatInfo =
+ d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps());
+ LoadImageFunction loadFunction =
+ d3dFormatInfo.getLoadFunctions()(GL_UNSIGNED_BYTE).loadFunction;
D3D11_MAPPED_SUBRESOURCE mappedImage;
- gl::Error error = map(D3D11_MAP_WRITE, &mappedImage);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(map(context, D3D11_MAP_WRITE, &mappedImage));
- uint8_t* offsetMappedData = reinterpret_cast<uint8_t*>(mappedImage.pData) + ((area.y / outputBlockHeight) * mappedImage.RowPitch +
- (area.x / outputBlockWidth) * outputPixelSize +
- area.z * mappedImage.DepthPitch);
+ uint8_t *offsetMappedData =
+ reinterpret_cast<uint8_t *>(mappedImage.pData) +
+ ((area.y / outputBlockHeight) * mappedImage.RowPitch +
+ (area.x / outputBlockWidth) * outputPixelSize + area.z * mappedImage.DepthPitch);
- loadFunction(area.width, area.height, area.depth,
- reinterpret_cast<const uint8_t*>(input), inputRowPitch, inputDepthPitch,
- offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch);
+ loadFunction(area.width, area.height, area.depth, reinterpret_cast<const uint8_t *>(input),
+ inputRowPitch, inputDepthPitch, offsetMappedData, mappedImage.RowPitch,
+ mappedImage.DepthPitch);
unmap();
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Image11::copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source)
+gl::Error Image11::copyFromTexStorage(const gl::Context *context,
+ const gl::ImageIndex &imageIndex,
+ TextureStorage *source)
{
TextureStorage11 *storage11 = GetAs<TextureStorage11>(source);
- ID3D11Resource *resource = nullptr;
- gl::Error error = storage11->getResource(&resource);
- if (error.isError())
- {
- return error;
- }
+ const TextureHelper11 *textureHelper = nullptr;
+ ANGLE_TRY(storage11->getResource(context, &textureHelper));
- UINT subresourceIndex = storage11->getSubresourceIndex(imageIndex);
- TextureHelper11 textureHelper = TextureHelper11::MakeAndReference(resource);
+ UINT subresourceIndex = storage11->getSubresourceIndex(imageIndex);
gl::Box sourceBox(0, 0, 0, mWidth, mHeight, mDepth);
- return copyWithoutConversion(gl::Offset(), sourceBox, textureHelper, subresourceIndex);
+ return copyWithoutConversion(gl::Offset(), sourceBox, *textureHelper, subresourceIndex);
}
-gl::Error Image11::copyFromFramebuffer(const gl::Offset &destOffset,
+gl::Error Image11::copyFromFramebuffer(const gl::Context *context,
+ const gl::Offset &destOffset,
const gl::Rectangle &sourceArea,
const gl::Framebuffer *sourceFBO)
{
const gl::FramebufferAttachment *srcAttachment = sourceFBO->getReadColorbuffer();
ASSERT(srcAttachment);
- const auto &d3d11Format = d3d11::GetTextureFormatInfo(srcAttachment->getInternalFormat(),
- mRenderer->getRenderer11DeviceCaps());
+ GLenum sourceInternalFormat = srcAttachment->getFormat().info->sizedInternalFormat;
+ const auto &d3d11Format =
+ d3d11::Format::Get(sourceInternalFormat, mRenderer->getRenderer11DeviceCaps());
- if (d3d11Format.texFormat == mDXGIFormat)
+ if (d3d11Format.texFormat == mDXGIFormat && sourceInternalFormat == mInternalFormat)
{
- RenderTargetD3D *renderTarget = nullptr;
- gl::Error error = srcAttachment->getRenderTarget(&renderTarget);
- if (error.isError())
- {
- return error;
- }
-
- RenderTarget11 *rt11 = GetAs<RenderTarget11>(renderTarget);
- ASSERT(rt11->getTexture());
+ RenderTarget11 *rt11 = nullptr;
+ ANGLE_TRY(srcAttachment->getRenderTarget(context, &rt11));
+ ASSERT(rt11->getTexture().get());
- TextureHelper11 textureHelper = TextureHelper11::MakeAndReference(rt11->getTexture());
+ TextureHelper11 textureHelper = rt11->getTexture();
unsigned int sourceSubResource = rt11->getSubresourceIndex();
gl::Box sourceBox(sourceArea.x, sourceArea.y, 0, sourceArea.width, sourceArea.height, 1);
@@ -363,25 +399,47 @@ gl::Error Image11::copyFromFramebuffer(const gl::Offset &destOffset,
// This format requires conversion, so we must copy the texture to staging and manually convert
// via readPixels
D3D11_MAPPED_SUBRESOURCE mappedImage;
- gl::Error error = map(D3D11_MAP_WRITE, &mappedImage);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(map(context, D3D11_MAP_WRITE, &mappedImage));
// determine the offset coordinate into the destination buffer
- const auto &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat);
+ const auto &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat);
GLsizei rowOffset = dxgiFormatInfo.pixelBytes * destOffset.x;
uint8_t *dataOffset = static_cast<uint8_t *>(mappedImage.pData) +
mappedImage.RowPitch * destOffset.y + rowOffset +
destOffset.z * mappedImage.DepthPitch;
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
+ const gl::InternalFormat &destFormatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat);
+ const auto &destD3D11Format =
+ d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps());
+
+ auto loadFunction = destD3D11Format.getLoadFunctions()(destFormatInfo.type);
+ gl::Error error = gl::NoError();
+ if (loadFunction.requiresConversion)
+ {
+ size_t bufferSize = destFormatInfo.pixelBytes * sourceArea.width * sourceArea.height;
+ angle::MemoryBuffer *memoryBuffer = nullptr;
+ error = mRenderer->getScratchMemoryBuffer(bufferSize, &memoryBuffer);
+
+ if (!error.isError())
+ {
+ GLuint memoryBufferRowPitch = destFormatInfo.pixelBytes * sourceArea.width;
- error = mRenderer->readFromAttachment(*srcAttachment, sourceArea, formatInfo.format,
- formatInfo.type, mappedImage.RowPitch,
- gl::PixelPackState(), dataOffset);
+ error = mRenderer->readFromAttachment(
+ context, *srcAttachment, sourceArea, destFormatInfo.format, destFormatInfo.type,
+ memoryBufferRowPitch, gl::PixelPackState(), memoryBuffer->data());
+
+ loadFunction.loadFunction(sourceArea.width, sourceArea.height, 1, memoryBuffer->data(),
+ memoryBufferRowPitch, 0, dataOffset, mappedImage.RowPitch,
+ mappedImage.DepthPitch);
+ }
+ }
+ else
+ {
+ error = mRenderer->readFromAttachment(
+ context, *srcAttachment, sourceArea, destFormatInfo.format, destFormatInfo.type,
+ mappedImage.RowPitch, gl::PixelPackState(), dataOffset);
+ }
unmap();
mDirty = true;
@@ -395,26 +453,23 @@ gl::Error Image11::copyWithoutConversion(const gl::Offset &destOffset,
UINT sourceSubResource)
{
// No conversion needed-- use copyback fastpath
- ID3D11Resource *stagingTexture = nullptr;
+ const TextureHelper11 *stagingTexture = nullptr;
unsigned int stagingSubresourceIndex = 0;
- gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(getStagingTexture(&stagingTexture, &stagingSubresourceIndex));
- ID3D11Device *device = mRenderer->getDevice();
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
- UINT subresourceAfterResolve = sourceSubResource;
-
- ID3D11Resource *srcTex = nullptr;
const gl::Extents &extents = textureHelper.getExtents();
- bool needResolve =
- (textureHelper.getTextureType() == GL_TEXTURE_2D && textureHelper.getSampleCount() > 1);
+ D3D11_BOX srcBox;
+ srcBox.left = sourceArea.x;
+ srcBox.right = sourceArea.x + sourceArea.width;
+ srcBox.top = sourceArea.y;
+ srcBox.bottom = sourceArea.y + sourceArea.height;
+ srcBox.front = sourceArea.z;
+ srcBox.back = sourceArea.z + sourceArea.depth;
- if (needResolve)
+ if (textureHelper.is2D() && textureHelper.getSampleCount() > 1)
{
D3D11_TEXTURE2D_DESC resolveDesc;
resolveDesc.Width = extents.width;
@@ -429,80 +484,57 @@ gl::Error Image11::copyWithoutConversion(const gl::Offset &destOffset,
resolveDesc.CPUAccessFlags = 0;
resolveDesc.MiscFlags = 0;
- ID3D11Texture2D *srcTex2D = NULL;
- HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex2D);
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY,
- "Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.",
- result);
- }
- srcTex = srcTex2D;
+ d3d11::Texture2D resolveTex;
+ ANGLE_TRY(mRenderer->allocateResource(resolveDesc, &resolveTex));
- deviceContext->ResolveSubresource(srcTex, 0, textureHelper.getTexture2D(),
+ deviceContext->ResolveSubresource(resolveTex.get(), 0, textureHelper.get(),
sourceSubResource, textureHelper.getFormat());
- subresourceAfterResolve = 0;
+
+ deviceContext->CopySubresourceRegion(stagingTexture->get(), stagingSubresourceIndex,
+ destOffset.x, destOffset.y, destOffset.z,
+ resolveTex.get(), 0, &srcBox);
}
else
{
- srcTex = textureHelper.getResource();
- }
-
- D3D11_BOX srcBox;
- srcBox.left = sourceArea.x;
- srcBox.right = sourceArea.x + sourceArea.width;
- srcBox.top = sourceArea.y;
- srcBox.bottom = sourceArea.y + sourceArea.height;
- srcBox.front = sourceArea.z;
- srcBox.back = sourceArea.z + sourceArea.depth;
-
- deviceContext->CopySubresourceRegion(stagingTexture, stagingSubresourceIndex, destOffset.x,
- destOffset.y, destOffset.z, srcTex,
- subresourceAfterResolve, &srcBox);
-
- if (needResolve)
- {
- SafeRelease(srcTex);
+ deviceContext->CopySubresourceRegion(stagingTexture->get(), stagingSubresourceIndex,
+ destOffset.x, destOffset.y, destOffset.z,
+ textureHelper.get(), sourceSubResource, &srcBox);
}
mDirty = true;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Image11::getStagingTexture(ID3D11Resource **outStagingTexture, unsigned int *outSubresourceIndex)
+gl::Error Image11::getStagingTexture(const TextureHelper11 **outStagingTexture,
+ unsigned int *outSubresourceIndex)
{
- gl::Error error = createStagingTexture();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(createStagingTexture());
- *outStagingTexture = mStagingTexture;
+ *outStagingTexture = &mStagingTexture;
*outSubresourceIndex = mStagingSubresource;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
void Image11::releaseStagingTexture()
{
- SafeRelease(mStagingTexture);
+ mStagingTexture.reset();
}
gl::Error Image11::createStagingTexture()
{
- if (mStagingTexture)
+ if (mStagingTexture.valid())
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
ASSERT(mWidth > 0 && mHeight > 0 && mDepth > 0);
const DXGI_FORMAT dxgiFormat = getDXGIFormat();
+ const auto &formatInfo =
+ d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps());
- ID3D11Device *device = mRenderer->getDevice();
- HRESULT result;
-
- int lodOffset = 1;
- GLsizei width = mWidth;
+ int lodOffset = 1;
+ GLsizei width = mWidth;
GLsizei height = mHeight;
// adjust size if needed for compressed textures
@@ -510,80 +542,69 @@ gl::Error Image11::createStagingTexture()
if (mTarget == GL_TEXTURE_3D)
{
- ID3D11Texture3D *newTexture = NULL;
-
D3D11_TEXTURE3D_DESC desc;
- desc.Width = width;
- desc.Height = height;
- desc.Depth = mDepth;
- desc.MipLevels = lodOffset + 1;
- desc.Format = dxgiFormat;
- desc.Usage = D3D11_USAGE_STAGING;
- desc.BindFlags = 0;
+ desc.Width = width;
+ desc.Height = height;
+ desc.Depth = mDepth;
+ desc.MipLevels = lodOffset + 1;
+ desc.Format = dxgiFormat;
+ desc.Usage = D3D11_USAGE_STAGING;
+ desc.BindFlags = 0;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
- desc.MiscFlags = 0;
+ desc.MiscFlags = 0;
- if (d3d11::GetTextureFormatInfo(mInternalFormat, mRenderer->getRenderer11DeviceCaps()).dataInitializerFunction != NULL)
+ if (formatInfo.dataInitializerFunction != nullptr)
{
std::vector<D3D11_SUBRESOURCE_DATA> initialData;
std::vector<std::vector<BYTE>> textureData;
- d3d11::GenerateInitialTextureData(mInternalFormat, mRenderer->getRenderer11DeviceCaps(), width, height, mDepth,
- lodOffset + 1, &initialData, &textureData);
+ d3d11::GenerateInitialTextureData(mInternalFormat, mRenderer->getRenderer11DeviceCaps(),
+ width, height, mDepth, lodOffset + 1, &initialData,
+ &textureData);
- result = device->CreateTexture3D(&desc, initialData.data(), &newTexture);
+ ANGLE_TRY(
+ mRenderer->allocateTexture(desc, formatInfo, initialData.data(), &mStagingTexture));
}
else
{
- result = device->CreateTexture3D(&desc, NULL, &newTexture);
+ ANGLE_TRY(mRenderer->allocateTexture(desc, formatInfo, &mStagingTexture));
}
- if (FAILED(result))
- {
- ASSERT(result == E_OUTOFMEMORY);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create staging texture, result: 0x%X.", result);
- }
-
- mStagingTexture = newTexture;
+ mStagingTexture.setDebugName("Image11::StagingTexture3D");
mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1);
}
- else if (mTarget == GL_TEXTURE_2D || mTarget == GL_TEXTURE_2D_ARRAY || mTarget == GL_TEXTURE_CUBE_MAP)
+ else if (mTarget == GL_TEXTURE_2D || mTarget == GL_TEXTURE_2D_ARRAY ||
+ mTarget == GL_TEXTURE_CUBE_MAP)
{
- ID3D11Texture2D *newTexture = NULL;
-
D3D11_TEXTURE2D_DESC desc;
- desc.Width = width;
- desc.Height = height;
- desc.MipLevels = lodOffset + 1;
- desc.ArraySize = 1;
- desc.Format = dxgiFormat;
- desc.SampleDesc.Count = 1;
+ desc.Width = width;
+ desc.Height = height;
+ desc.MipLevels = lodOffset + 1;
+ desc.ArraySize = 1;
+ desc.Format = dxgiFormat;
+ desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
- desc.Usage = D3D11_USAGE_STAGING;
- desc.BindFlags = 0;
- desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
- desc.MiscFlags = 0;
+ desc.Usage = D3D11_USAGE_STAGING;
+ desc.BindFlags = 0;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
+ desc.MiscFlags = 0;
- if (d3d11::GetTextureFormatInfo(mInternalFormat, mRenderer->getRenderer11DeviceCaps()).dataInitializerFunction != NULL)
+ if (formatInfo.dataInitializerFunction != nullptr)
{
std::vector<D3D11_SUBRESOURCE_DATA> initialData;
std::vector<std::vector<BYTE>> textureData;
- d3d11::GenerateInitialTextureData(mInternalFormat, mRenderer->getRenderer11DeviceCaps(), width, height, 1,
- lodOffset + 1, &initialData, &textureData);
+ d3d11::GenerateInitialTextureData(mInternalFormat, mRenderer->getRenderer11DeviceCaps(),
+ width, height, 1, lodOffset + 1, &initialData,
+ &textureData);
- result = device->CreateTexture2D(&desc, initialData.data(), &newTexture);
+ ANGLE_TRY(
+ mRenderer->allocateTexture(desc, formatInfo, initialData.data(), &mStagingTexture));
}
else
{
- result = device->CreateTexture2D(&desc, NULL, &newTexture);
+ ANGLE_TRY(mRenderer->allocateTexture(desc, formatInfo, &mStagingTexture));
}
- if (FAILED(result))
- {
- ASSERT(result == E_OUTOFMEMORY);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create staging texture, result: 0x%X.", result);
- }
-
- mStagingTexture = newTexture;
+ mStagingTexture.setDebugName("Image11::StagingTexture2D");
mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1);
}
else
@@ -592,30 +613,22 @@ gl::Error Image11::createStagingTexture()
}
mDirty = false;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map)
+gl::Error Image11::map(const gl::Context *context, D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map)
{
// We must recover from the TextureStorage if necessary, even for D3D11_MAP_WRITE.
- gl::Error error = recoverFromAssociatedStorage();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(recoverFromAssociatedStorage(context));
- ID3D11Resource *stagingTexture = NULL;
- unsigned int subresourceIndex = 0;
- error = getStagingTexture(&stagingTexture, &subresourceIndex);
- if (error.isError())
- {
- return error;
- }
+ const TextureHelper11 *stagingTexture = nullptr;
+ unsigned int subresourceIndex = 0;
+ ANGLE_TRY(getStagingTexture(&stagingTexture, &subresourceIndex));
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
- ASSERT(mStagingTexture);
- HRESULT result = deviceContext->Map(stagingTexture, subresourceIndex, mapType, 0, map);
+ ASSERT(stagingTexture && stagingTexture->valid());
+ HRESULT result = deviceContext->Map(stagingTexture->get(), subresourceIndex, mapType, 0, map);
if (FAILED(result))
{
@@ -624,20 +637,20 @@ gl::Error Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map)
{
mRenderer->notifyDeviceLost();
}
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to map staging texture, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to map staging texture, " << gl::FmtHR(result);
}
mDirty = true;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
void Image11::unmap()
{
- if (mStagingTexture)
+ if (mStagingTexture.valid())
{
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
- deviceContext->Unmap(mStagingTexture, mStagingSubresource);
+ deviceContext->Unmap(mStagingTexture.get(), mStagingSubresource);
}
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h
index a5fcec84f8..584d231b37 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h
@@ -10,10 +10,10 @@
#ifndef LIBANGLE_RENDERER_D3D_D3D11_IMAGE11_H_
#define LIBANGLE_RENDERER_D3D_D3D11_IMAGE11_H_
-#include "libANGLE/renderer/d3d/ImageD3D.h"
-#include "libANGLE/ImageIndex.h"
-
#include "common/debug.h"
+#include "libANGLE/ImageIndex.h"
+#include "libANGLE/renderer/d3d/ImageD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
namespace gl
{
@@ -25,37 +25,63 @@ namespace rx
class Renderer11;
class TextureHelper11;
class TextureStorage11;
+struct Renderer11DeviceCaps;
class Image11 : public ImageD3D
{
public:
Image11(Renderer11 *renderer);
- virtual ~Image11();
-
- static gl::Error generateMipmap(Image11 *dest, Image11 *src);
-
- virtual bool isDirty() const;
-
- virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region);
+ ~Image11() override;
+
+ static gl::Error GenerateMipmap(const gl::Context *context,
+ Image11 *dest,
+ Image11 *src,
+ const Renderer11DeviceCaps &rendererCaps);
+ static gl::Error CopyImage(const gl::Context *context,
+ Image11 *dest,
+ Image11 *source,
+ const gl::Rectangle &sourceRect,
+ const gl::Offset &destOffset,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const Renderer11DeviceCaps &rendererCaps);
+
+ bool isDirty() const override;
+
+ gl::Error copyToStorage(const gl::Context *context,
+ TextureStorage *storage,
+ const gl::ImageIndex &index,
+ const gl::Box &region) override;
bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) override;
DXGI_FORMAT getDXGIFormat() const;
- virtual gl::Error loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input);
- virtual gl::Error loadCompressedData(const gl::Box &area, const void *input);
-
- gl::Error copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source) override;
- gl::Error copyFromFramebuffer(const gl::Offset &destOffset,
+ gl::Error loadData(const gl::Context *context,
+ const gl::Box &area,
+ const gl::PixelUnpackState &unpack,
+ GLenum type,
+ const void *input,
+ bool applySkipImages) override;
+ gl::Error loadCompressedData(const gl::Context *context,
+ const gl::Box &area,
+ const void *input) override;
+
+ gl::Error copyFromTexStorage(const gl::Context *context,
+ const gl::ImageIndex &imageIndex,
+ TextureStorage *source) override;
+ gl::Error copyFromFramebuffer(const gl::Context *context,
+ const gl::Offset &destOffset,
const gl::Rectangle &sourceArea,
const gl::Framebuffer *source) override;
- gl::Error recoverFromAssociatedStorage();
- bool isAssociatedStorageValid(TextureStorage11* textureStorage) const;
+ gl::Error recoverFromAssociatedStorage(const gl::Context *context);
+ void verifyAssociatedStorageValid(TextureStorage11 *textureStorage) const;
void disassociateStorage();
protected:
- gl::Error map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map);
+ gl::Error map(const gl::Context *context, D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map);
void unmap();
private:
@@ -64,14 +90,15 @@ class Image11 : public ImageD3D
const TextureHelper11 &textureHelper,
UINT sourceSubResource);
- gl::Error getStagingTexture(ID3D11Resource **outStagingTexture, unsigned int *outSubresourceIndex);
+ gl::Error getStagingTexture(const TextureHelper11 **outStagingTexture,
+ unsigned int *outSubresourceIndex);
gl::Error createStagingTexture();
void releaseStagingTexture();
Renderer11 *mRenderer;
DXGI_FORMAT mDXGIFormat;
- ID3D11Resource *mStagingTexture;
+ TextureHelper11 mStagingTexture;
unsigned int mStagingSubresource;
bool mRecoverFromStorage;
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp
index a5e78a245d..a79fb71f71 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp
@@ -14,28 +14,23 @@
namespace rx
{
-IndexBuffer11::IndexBuffer11(Renderer11 *const renderer) : mRenderer(renderer)
+IndexBuffer11::IndexBuffer11(Renderer11 *const renderer)
+ : mRenderer(renderer), mBuffer(), mBufferSize(0), mIndexType(GL_NONE), mDynamicUsage(false)
{
- mBuffer = NULL;
- mBufferSize = 0;
- mDynamicUsage = false;
}
IndexBuffer11::~IndexBuffer11()
{
- SafeRelease(mBuffer);
}
gl::Error IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic)
{
- SafeRelease(mBuffer);
+ mBuffer.reset();
updateSerial();
if (bufferSize > 0)
{
- ID3D11Device* dxDevice = mRenderer->getDevice();
-
D3D11_BUFFER_DESC bufferDesc;
bufferDesc.ByteWidth = bufferSize;
bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
@@ -44,19 +39,15 @@ gl::Error IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, b
bufferDesc.MiscFlags = 0;
bufferDesc.StructureByteStride = 0;
- HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer);
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal index buffer of size, %lu.", bufferSize);
- }
+ ANGLE_TRY(mRenderer->allocateResource(bufferDesc, &mBuffer));
if (dynamic)
{
- d3d11::SetDebugName(mBuffer, "IndexBuffer11 (dynamic)");
+ mBuffer.setDebugName("IndexBuffer11 (dynamic)");
}
else
{
- d3d11::SetDebugName(mBuffer, "IndexBuffer11 (static)");
+ mBuffer.setDebugName("IndexBuffer11 (static)");
}
}
@@ -64,45 +55,46 @@ gl::Error IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, b
mIndexType = indexType;
mDynamicUsage = dynamic;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory)
{
- if (!mBuffer)
+ if (!mBuffer.valid())
{
- return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
+ return gl::OutOfMemory() << "Internal index buffer is not initialized.";
}
// Check for integer overflows and out-out-bounds map requests
if (offset + size < offset || offset + size > mBufferSize)
{
- return gl::Error(GL_OUT_OF_MEMORY, "Index buffer map range is not inside the buffer.");
+ return gl::OutOfMemory() << "Index buffer map range is not inside the buffer.";
}
ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
D3D11_MAPPED_SUBRESOURCE mappedResource;
- HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
+ HRESULT result =
+ dxContext->Map(mBuffer.get(), 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal index buffer, HRESULT: 0x%08x.", result);
+ return gl::OutOfMemory() << "Failed to map internal index buffer, " << gl::FmtHR(result);
}
*outMappedMemory = reinterpret_cast<char*>(mappedResource.pData) + offset;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error IndexBuffer11::unmapBuffer()
{
- if (!mBuffer)
+ if (!mBuffer.valid())
{
- return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
+ return gl::OutOfMemory() << "Internal index buffer is not initialized.";
}
ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
- dxContext->Unmap(mBuffer, 0);
- return gl::Error(GL_NO_ERROR);
+ dxContext->Unmap(mBuffer.get(), 0);
+ return gl::NoError();
}
GLenum IndexBuffer11::getIndexType() const
@@ -123,29 +115,29 @@ gl::Error IndexBuffer11::setSize(unsigned int bufferSize, GLenum indexType)
}
else
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
}
gl::Error IndexBuffer11::discard()
{
- if (!mBuffer)
+ if (!mBuffer.valid())
{
- return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
+ return gl::OutOfMemory() << "Internal index buffer is not initialized.";
}
ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
D3D11_MAPPED_SUBRESOURCE mappedResource;
- HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ HRESULT result = dxContext->Map(mBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal index buffer, HRESULT: 0x%08x.", result);
+ return gl::OutOfMemory() << "Failed to map internal index buffer, " << gl::FmtHR(result);
}
- dxContext->Unmap(mBuffer, 0);
+ dxContext->Unmap(mBuffer.get(), 0);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
DXGI_FORMAT IndexBuffer11::getIndexFormat() const
@@ -159,9 +151,9 @@ DXGI_FORMAT IndexBuffer11::getIndexFormat() const
}
}
-ID3D11Buffer *IndexBuffer11::getBuffer() const
+const d3d11::Buffer &IndexBuffer11::getBuffer() const
{
return mBuffer;
}
-}
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h
index e730377e00..7b5d744c02 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h
@@ -10,6 +10,7 @@
#define LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_
#include "libANGLE/renderer/d3d/IndexBuffer.h"
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
namespace rx
{
@@ -19,31 +20,31 @@ class IndexBuffer11 : public IndexBuffer
{
public:
explicit IndexBuffer11(Renderer11 *const renderer);
- virtual ~IndexBuffer11();
+ ~IndexBuffer11() override;
- virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic);
+ gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) override;
- virtual gl::Error mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory);
- virtual gl::Error unmapBuffer();
+ gl::Error mapBuffer(unsigned int offset, unsigned int size, void **outMappedMemory) override;
+ gl::Error unmapBuffer() override;
- virtual GLenum getIndexType() const;
- virtual unsigned int getBufferSize() const;
- virtual gl::Error setSize(unsigned int bufferSize, GLenum indexType);
+ GLenum getIndexType() const override;
+ unsigned int getBufferSize() const override;
+ gl::Error setSize(unsigned int bufferSize, GLenum indexType) override;
- virtual gl::Error discard();
+ gl::Error discard() override;
DXGI_FORMAT getIndexFormat() const;
- ID3D11Buffer *getBuffer() const;
+ const d3d11::Buffer &getBuffer() const;
private:
Renderer11 *const mRenderer;
- ID3D11Buffer *mBuffer;
+ d3d11::Buffer mBuffer;
unsigned int mBufferSize;
GLenum mIndexType;
bool mDynamicUsage;
};
-}
+} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp
index 3a6d797ea6..a238f97b08 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp
@@ -9,17 +9,22 @@
#include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h"
+#include "common/bitset_utils.h"
#include "common/utilities.h"
+#include "libANGLE/Context.h"
#include "libANGLE/Program.h"
+#include "libANGLE/VertexArray.h"
#include "libANGLE/VertexAttribute.h"
#include "libANGLE/renderer/d3d/IndexDataManager.h"
#include "libANGLE/renderer/d3d/ProgramD3D.h"
#include "libANGLE/renderer/d3d/VertexDataManager.h"
#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
+#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
-#include "third_party/murmurhash/MurmurHash3.h"
namespace rx
{
@@ -32,24 +37,7 @@ size_t GetReservedBufferCount(bool usesPointSpriteEmulation)
return usesPointSpriteEmulation ? 1 : 0;
}
-gl::InputLayout GetInputLayout(const SortedAttribArray &translatedAttributes, size_t attributeCount)
-{
- gl::InputLayout inputLayout(attributeCount, gl::VERTEX_FORMAT_INVALID);
-
- for (size_t attributeIndex = 0; attributeIndex < attributeCount; ++attributeIndex)
- {
- const TranslatedAttribute *translatedAttribute = translatedAttributes[attributeIndex];
-
- if (translatedAttribute->active)
- {
- inputLayout[attributeIndex] = gl::GetVertexFormatType(
- *translatedAttribute->attribute, translatedAttribute->currentValueType);
- }
- }
- return inputLayout;
-}
-
-GLenum GetGLSLAttributeType(const std::vector<sh::Attribute> &shaderAttributes, int index)
+GLenum GetGLSLAttributeType(const std::vector<sh::Attribute> &shaderAttributes, size_t index)
{
// Count matrices differently
for (const sh::Attribute &attrib : shaderAttributes)
@@ -61,8 +49,9 @@ GLenum GetGLSLAttributeType(const std::vector<sh::Attribute> &shaderAttributes,
GLenum transposedType = gl::TransposeMatrixType(attrib.type);
int rows = gl::VariableRowCount(transposedType);
+ int intIndex = static_cast<int>(index);
- if (index >= attrib.location && index < attrib.location + rows)
+ if (intIndex >= attrib.location && intIndex < attrib.location + rows)
{
return transposedType;
}
@@ -72,8 +61,6 @@ GLenum GetGLSLAttributeType(const std::vector<sh::Attribute> &shaderAttributes,
return GL_NONE;
}
-const unsigned int kDefaultCacheSize = 1024;
-
struct PackedAttribute
{
uint8_t attribType;
@@ -82,26 +69,18 @@ struct PackedAttribute
uint8_t divisor;
};
-Optional<size_t> FindFirstNonInstanced(const SortedAttribArray &sortedAttributes, size_t maxIndex)
-{
- for (size_t index = 0; index < maxIndex; ++index)
- {
- if (sortedAttributes[index]->divisor == 0)
- {
- return Optional<size_t>(index);
- }
- }
+} // anonymous namespace
- return Optional<size_t>::Invalid();
+PackedAttributeLayout::PackedAttributeLayout() : numAttributes(0), flags(0), attributeData({})
+{
}
-} // anonymous namespace
+PackedAttributeLayout::PackedAttributeLayout(const PackedAttributeLayout &other) = default;
-void InputLayoutCache::PackedAttributeLayout::addAttributeData(
- GLenum glType,
- UINT semanticIndex,
- gl::VertexFormatType vertexFormatType,
- unsigned int divisor)
+void PackedAttributeLayout::addAttributeData(GLenum glType,
+ UINT semanticIndex,
+ gl::VertexFormatType vertexFormatType,
+ unsigned int divisor)
{
gl::AttributeType attribType = gl::GetAttributeType(glType);
@@ -121,139 +100,58 @@ void InputLayoutCache::PackedAttributeLayout::addAttributeData(
attributeData[numAttributes++] = gl::bitCast<uint32_t>(packedAttrib);
}
-bool InputLayoutCache::PackedAttributeLayout::operator<(const PackedAttributeLayout &other) const
+bool PackedAttributeLayout::operator==(const PackedAttributeLayout &other) const
{
- if (numAttributes != other.numAttributes)
- {
- return numAttributes < other.numAttributes;
- }
-
- if (flags != other.flags)
- {
- return flags < other.flags;
- }
-
- return memcmp(attributeData, other.attributeData, sizeof(uint32_t) * numAttributes) < 0;
+ return (numAttributes == other.numAttributes) && (flags == other.flags) &&
+ (attributeData == other.attributeData);
}
-InputLayoutCache::InputLayoutCache() : mUnsortedAttributesCount(0), mCacheSize(kDefaultCacheSize)
+InputLayoutCache::InputLayoutCache()
+ : mLayoutCache(kDefaultCacheSize * 2), mPointSpriteVertexBuffer(), mPointSpriteIndexBuffer()
{
- mCounter = 0;
- mDevice = NULL;
- mDeviceContext = NULL;
- mCurrentIL = NULL;
-
- for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
- {
- mCurrentBuffers[i] = NULL;
- mCurrentVertexStrides[i] = static_cast<UINT>(-1);
- mCurrentVertexOffsets[i] = static_cast<UINT>(-1);
- }
- mPointSpriteVertexBuffer = NULL;
- mPointSpriteIndexBuffer = NULL;
}
InputLayoutCache::~InputLayoutCache()
{
- clear();
-}
-
-void InputLayoutCache::initialize(ID3D11Device *device, ID3D11DeviceContext *context)
-{
- clear();
- mDevice = device;
- mDeviceContext = context;
- mFeatureLevel = device->GetFeatureLevel();
}
void InputLayoutCache::clear()
{
- for (auto &layout : mLayoutMap)
- {
- SafeRelease(layout.second);
- }
- mLayoutMap.clear();
- SafeRelease(mPointSpriteVertexBuffer);
- SafeRelease(mPointSpriteIndexBuffer);
- markDirty();
-}
-
-void InputLayoutCache::markDirty()
-{
- mCurrentIL = NULL;
- for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
- {
- mCurrentBuffers[i] = NULL;
- mCurrentVertexStrides[i] = static_cast<UINT>(-1);
- mCurrentVertexOffsets[i] = static_cast<UINT>(-1);
- }
- mUnsortedAttributesCount = 0;
+ mLayoutCache.Clear();
+ mPointSpriteVertexBuffer.reset();
+ mPointSpriteIndexBuffer.reset();
}
gl::Error InputLayoutCache::applyVertexBuffers(
- const std::vector<TranslatedAttribute> &unsortedAttributes,
+ const gl::Context *context,
+ const std::vector<const TranslatedAttribute *> &currentAttributes,
GLenum mode,
- gl::Program *program,
- TranslatedIndexData *indexInfo,
- GLsizei numIndicesPerInstance)
+ GLint start,
+ bool isIndexedRendering)
{
- ASSERT(mDevice && mDeviceContext);
-
+ Renderer11 *renderer = GetImplAs<Context11>(context)->getRenderer();
+ const gl::State &state = context->getGLState();
+ auto *stateManager = renderer->getStateManager();
+ gl::Program *program = state.getProgram();
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
bool programUsesInstancedPointSprites = programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation();
bool instancedPointSpritesActive = programUsesInstancedPointSprites && (mode == GL_POINTS);
- SortedIndexArray sortedSemanticIndices;
- mSortedAttributes.fill(nullptr);
- mUnsortedAttributesCount = unsortedAttributes.size();
-
- programD3D->sortAttributesByLayout(unsortedAttributes, sortedSemanticIndices.data(),
- mSortedAttributes.data());
-
- // If we are using FL 9_3, make sure the first attribute is not instanced
- if (mFeatureLevel <= D3D_FEATURE_LEVEL_9_3 && !unsortedAttributes.empty())
- {
- if (mSortedAttributes[0]->divisor > 0)
- {
- Optional<size_t> firstNonInstancedIndex =
- FindFirstNonInstanced(mSortedAttributes, unsortedAttributes.size());
- if (firstNonInstancedIndex.valid())
- {
- size_t index = firstNonInstancedIndex.value();
- std::swap(mSortedAttributes[0], mSortedAttributes[index]);
- std::swap(sortedSemanticIndices[0], sortedSemanticIndices[index]);
- }
- }
- }
-
- gl::Error error = updateInputLayout(program, mode, mSortedAttributes, sortedSemanticIndices,
- unsortedAttributes.size(), numIndicesPerInstance);
- if (error.isError())
- {
- return error;
- }
-
- bool dirtyBuffers = false;
- size_t minDiff = gl::MAX_VERTEX_ATTRIBS;
- size_t maxDiff = 0;
-
// Note that if we use instance emulation, we reserve the first buffer slot.
size_t reservedBuffers = GetReservedBufferCount(programUsesInstancedPointSprites);
for (size_t attribIndex = 0; attribIndex < (gl::MAX_VERTEX_ATTRIBS - reservedBuffers);
++attribIndex)
{
- ID3D11Buffer *buffer = NULL;
- UINT vertexStride = 0;
- UINT vertexOffset = 0;
+ ID3D11Buffer *buffer = nullptr;
+ UINT vertexStride = 0;
+ UINT vertexOffset = 0;
- const auto &attrib = *mSortedAttributes[attribIndex];
-
- if (attribIndex < unsortedAttributes.size() && attrib.active)
+ if (attribIndex < currentAttributes.size())
{
- VertexBuffer11 *vertexBuffer = GetAs<VertexBuffer11>(attrib.vertexBuffer);
- Buffer11 *bufferStorage = attrib.storage ? GetAs<Buffer11>(attrib.storage) : nullptr;
+ const auto &attrib = *currentAttributes[attribIndex];
+ Buffer11 *bufferStorage = attrib.storage ? GetAs<Buffer11>(attrib.storage) : nullptr;
// If indexed pointsprite emulation is active, then we need to take a less efficent code path.
// Emulated indexed pointsprite rendering requires that the vertex buffers match exactly to
@@ -261,18 +159,18 @@ gl::Error InputLayoutCache::applyVertexBuffers(
// on the number of points indicated by the index list or how many duplicates are found on the index list.
if (bufferStorage == nullptr)
{
- buffer = vertexBuffer->getBuffer();
+ ASSERT(attrib.vertexBuffer.get());
+ buffer = GetAs<VertexBuffer11>(attrib.vertexBuffer.get())->getBuffer().get();
}
- else if (instancedPointSpritesActive && (indexInfo != nullptr))
+ else if (instancedPointSpritesActive && isIndexedRendering)
{
+ VertexArray11 *vao11 = GetImplAs<VertexArray11>(state.getVertexArray());
+ ASSERT(vao11->isCachedIndexInfoValid());
+ TranslatedIndexData *indexInfo = vao11->getCachedIndexInfo();
if (indexInfo->srcIndexData.srcBuffer != nullptr)
{
const uint8_t *bufferData = nullptr;
- error = indexInfo->srcIndexData.srcBuffer->getData(&bufferData);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(indexInfo->srcIndexData.srcBuffer->getData(context, &bufferData));
ASSERT(bufferData != nullptr);
ptrdiff_t offset =
@@ -281,31 +179,24 @@ gl::Error InputLayoutCache::applyVertexBuffers(
indexInfo->srcIndexData.srcIndices = bufferData + offset;
}
- buffer = bufferStorage->getEmulatedIndexedBuffer(&indexInfo->srcIndexData, &attrib);
+ ANGLE_TRY_RESULT(bufferStorage->getEmulatedIndexedBuffer(
+ context, &indexInfo->srcIndexData, attrib, start),
+ buffer);
}
else
{
- buffer = bufferStorage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
+ ANGLE_TRY_RESULT(
+ bufferStorage->getBuffer(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK),
+ buffer);
}
vertexStride = attrib.stride;
- vertexOffset = attrib.offset;
+ ANGLE_TRY_RESULT(attrib.computeOffset(start), vertexOffset);
}
size_t bufferIndex = reservedBuffers + attribIndex;
- if (buffer != mCurrentBuffers[bufferIndex] ||
- vertexStride != mCurrentVertexStrides[bufferIndex] ||
- vertexOffset != mCurrentVertexOffsets[bufferIndex])
- {
- dirtyBuffers = true;
- minDiff = std::min(minDiff, bufferIndex);
- maxDiff = std::max(maxDiff, bufferIndex);
-
- mCurrentBuffers[bufferIndex] = buffer;
- mCurrentVertexStrides[bufferIndex] = vertexStride;
- mCurrentVertexOffsets[bufferIndex] = vertexOffset;
- }
+ stateManager->queueVertexBufferChange(bufferIndex, buffer, vertexStride, vertexOffset);
}
// Instanced PointSprite emulation requires two additional ID3D11Buffers. A vertex buffer needs
@@ -317,10 +208,9 @@ gl::Error InputLayoutCache::applyVertexBuffers(
// handle missing vertex data and will TDR the system.
if (programUsesInstancedPointSprites)
{
- HRESULT result = S_OK;
const UINT pointSpriteVertexStride = sizeof(float) * 5;
- if (!mPointSpriteVertexBuffer)
+ if (!mPointSpriteVertexBuffer.valid())
{
static const float pointSpriteVertices[] =
{
@@ -342,25 +232,16 @@ gl::Error InputLayoutCache::applyVertexBuffers(
vertexBufferDesc.MiscFlags = 0;
vertexBufferDesc.StructureByteStride = 0;
- result = mDevice->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &mPointSpriteVertexBuffer);
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create instanced pointsprite emulation vertex buffer, HRESULT: 0x%08x", result);
- }
+ ANGLE_TRY(renderer->allocateResource(vertexBufferDesc, &vertexBufferData,
+ &mPointSpriteVertexBuffer));
}
- mCurrentBuffers[0] = mPointSpriteVertexBuffer;
// Set the stride to 0 if GL_POINTS mode is not being used to instruct the driver to avoid
// indexing into the vertex buffer.
- mCurrentVertexStrides[0] = instancedPointSpritesActive ? pointSpriteVertexStride : 0;
- mCurrentVertexOffsets[0] = 0;
-
- // Update maxDiff to include the additional point sprite vertex buffer
- // to ensure that IASetVertexBuffers uses the correct buffer count.
- minDiff = 0;
- maxDiff = std::max(maxDiff, static_cast<size_t>(0));
+ UINT stride = instancedPointSpritesActive ? pointSpriteVertexStride : 0;
+ stateManager->queueVertexBufferChange(0, mPointSpriteVertexBuffer.get(), stride, 0);
- if (!mPointSpriteIndexBuffer)
+ if (!mPointSpriteIndexBuffer.valid())
{
// Create an index buffer and set it for pointsprite rendering
static const unsigned short pointSpriteIndices[] =
@@ -377,12 +258,8 @@ gl::Error InputLayoutCache::applyVertexBuffers(
indexBufferDesc.MiscFlags = 0;
indexBufferDesc.StructureByteStride = 0;
- result = mDevice->CreateBuffer(&indexBufferDesc, &indexBufferData, &mPointSpriteIndexBuffer);
- if (FAILED(result))
- {
- SafeRelease(mPointSpriteVertexBuffer);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create instanced pointsprite emulation index buffer, HRESULT: 0x%08x", result);
- }
+ ANGLE_TRY(renderer->allocateResource(indexBufferDesc, &indexBufferData,
+ &mPointSpriteIndexBuffer));
}
if (instancedPointSpritesActive)
@@ -391,51 +268,51 @@ gl::Error InputLayoutCache::applyVertexBuffers(
// non-indexed rendering path in ANGLE (DrawArrays). This means that applyIndexBuffer()
// on the renderer will not be called and setting this buffer here ensures that the
// rendering path will contain the correct index buffers.
- mDeviceContext->IASetIndexBuffer(mPointSpriteIndexBuffer, DXGI_FORMAT_R16_UINT, 0);
+ stateManager->setIndexBuffer(mPointSpriteIndexBuffer.get(), DXGI_FORMAT_R16_UINT, 0);
}
}
- if (dirtyBuffers)
- {
- ASSERT(minDiff <= maxDiff && maxDiff < gl::MAX_VERTEX_ATTRIBS);
- mDeviceContext->IASetVertexBuffers(
- static_cast<UINT>(minDiff), static_cast<UINT>(maxDiff - minDiff + 1),
- mCurrentBuffers + minDiff, mCurrentVertexStrides + minDiff,
- mCurrentVertexOffsets + minDiff);
- }
-
- return gl::Error(GL_NO_ERROR);
+ stateManager->applyVertexBufferChanges();
+ return gl::NoError();
}
-gl::Error InputLayoutCache::updateVertexOffsetsForPointSpritesEmulation(GLsizei emulatedInstanceId)
+gl::Error InputLayoutCache::updateVertexOffsetsForPointSpritesEmulation(
+ Renderer11 *renderer,
+ const std::vector<const TranslatedAttribute *> &currentAttributes,
+ GLint startVertex,
+ GLsizei emulatedInstanceId)
{
+ auto *stateManager = renderer->getStateManager();
+
size_t reservedBuffers = GetReservedBufferCount(true);
- for (size_t attribIndex = 0; attribIndex < mUnsortedAttributesCount; ++attribIndex)
+ for (size_t attribIndex = 0; attribIndex < currentAttributes.size(); ++attribIndex)
{
- const auto &attrib = *mSortedAttributes[attribIndex];
+ const auto &attrib = *currentAttributes[attribIndex];
size_t bufferIndex = reservedBuffers + attribIndex;
- if (attrib.active && attrib.divisor > 0)
+ if (attrib.divisor > 0)
{
- mCurrentVertexOffsets[bufferIndex] =
- attrib.offset + (attrib.stride * (emulatedInstanceId / attrib.divisor));
+ unsigned int offset = 0;
+ ANGLE_TRY_RESULT(attrib.computeOffset(startVertex), offset);
+ offset += (attrib.stride * (emulatedInstanceId / attrib.divisor));
+ stateManager->queueVertexOffsetChange(bufferIndex, offset);
}
}
- mDeviceContext->IASetVertexBuffers(0, gl::MAX_VERTEX_ATTRIBS, mCurrentBuffers,
- mCurrentVertexStrides, mCurrentVertexOffsets);
-
- return gl::Error(GL_NO_ERROR);
+ stateManager->applyVertexBufferChanges();
+ return gl::NoError();
}
-gl::Error InputLayoutCache::updateInputLayout(gl::Program *program,
- GLenum mode,
- const SortedAttribArray &sortedAttributes,
- const SortedIndexArray &sortedSemanticIndices,
- size_t attribCount,
- GLsizei numIndicesPerInstance)
+gl::Error InputLayoutCache::updateInputLayout(
+ Renderer11 *renderer,
+ const gl::State &state,
+ const std::vector<const TranslatedAttribute *> &currentAttributes,
+ GLenum mode,
+ const AttribIndexArray &sortedSemanticIndices,
+ const DrawCallVertexParams &vertexParams)
{
- const std::vector<sh::Attribute> &shaderAttributes = program->getAttributes();
+ gl::Program *program = state.getProgram();
+ const auto &shaderAttributes = program->getAttributes();
PackedAttributeLayout layout;
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
@@ -453,90 +330,70 @@ gl::Error InputLayoutCache::updateInputLayout(gl::Program *program,
layout.flags |= PackedAttributeLayout::FLAG_INSTANCED_SPRITES_ACTIVE;
}
- if (numIndicesPerInstance > 0)
+ if (vertexParams.instances() > 0)
{
layout.flags |= PackedAttributeLayout::FLAG_INSTANCED_RENDERING_ACTIVE;
}
- const auto &semanticToLocation = programD3D->getAttributesByLayout();
+ const auto &attribs = state.getVertexArray()->getVertexAttributes();
+ const auto &bindings = state.getVertexArray()->getVertexBindings();
+ const auto &locationToSemantic = programD3D->getAttribLocationToD3DSemantics();
+ int divisorMultiplier = program->usesMultiview() ? program->getNumViews() : 1;
- for (size_t attribIndex = 0; attribIndex < attribCount; ++attribIndex)
+ for (size_t attribIndex : program->getActiveAttribLocationsMask())
{
- const auto &attrib = *sortedAttributes[attribIndex];
- int sortedIndex = sortedSemanticIndices[attribIndex];
-
- if (!attrib.active)
- continue;
-
- gl::VertexFormatType vertexFormatType =
- gl::GetVertexFormatType(*attrib.attribute, attrib.currentValueType);
-
// Record the type of the associated vertex shader vector in our key
// This will prevent mismatched vertex shaders from using the same input layout
- GLenum glslElementType =
- GetGLSLAttributeType(shaderAttributes, semanticToLocation[sortedIndex]);
+ GLenum glslElementType = GetGLSLAttributeType(shaderAttributes, attribIndex);
- layout.addAttributeData(glslElementType, sortedIndex, vertexFormatType, attrib.divisor);
+ const auto &attrib = attribs[attribIndex];
+ const auto &binding = bindings[attrib.bindingIndex];
+ int d3dSemantic = locationToSemantic[attribIndex];
+
+ const auto &currentValue =
+ state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex));
+ gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, currentValue.Type);
+
+ layout.addAttributeData(glslElementType, d3dSemantic, vertexFormatType,
+ binding.getDivisor() * divisorMultiplier);
}
- ID3D11InputLayout *inputLayout = nullptr;
+ const d3d11::InputLayout *inputLayout = nullptr;
if (layout.numAttributes > 0 || layout.flags != 0)
{
- auto layoutMapIt = mLayoutMap.find(layout);
- if (layoutMapIt != mLayoutMap.end())
+ auto it = mLayoutCache.Get(layout);
+ if (it != mLayoutCache.end())
{
- inputLayout = layoutMapIt->second;
+ inputLayout = &it->second;
}
else
{
- gl::Error error =
- createInputLayout(sortedAttributes, sortedSemanticIndices, attribCount, mode,
- program, numIndicesPerInstance, &inputLayout);
- if (error.isError())
- {
- return error;
- }
- if (mLayoutMap.size() >= mCacheSize)
- {
- TRACE("Overflowed the limit of %u input layouts, purging half the cache.",
- mCacheSize);
+ angle::TrimCache(mLayoutCache.max_size() / 2, kGCLimit, "input layout", &mLayoutCache);
- // Randomly release every second element
- auto it = mLayoutMap.begin();
- while (it != mLayoutMap.end())
- {
- it++;
- if (it != mLayoutMap.end())
- {
- // c++11 erase allows us to easily delete the current iterator.
- SafeRelease(it->second);
- it = mLayoutMap.erase(it);
- }
- }
- }
+ d3d11::InputLayout newInputLayout;
+ ANGLE_TRY(createInputLayout(renderer, sortedSemanticIndices, currentAttributes, mode,
+ program, vertexParams, &newInputLayout));
- mLayoutMap[layout] = inputLayout;
+ auto insertIt = mLayoutCache.Put(layout, std::move(newInputLayout));
+ inputLayout = &insertIt->second;
}
}
- if (inputLayout != mCurrentIL)
- {
- mDeviceContext->IASetInputLayout(inputLayout);
- mCurrentIL = inputLayout;
- }
-
- return gl::Error(GL_NO_ERROR);
+ renderer->getStateManager()->setInputLayout(inputLayout);
+ return gl::NoError();
}
-gl::Error InputLayoutCache::createInputLayout(const SortedAttribArray &sortedAttributes,
- const SortedIndexArray &sortedSemanticIndices,
- size_t attribCount,
- GLenum mode,
- gl::Program *program,
- GLsizei numIndicesPerInstance,
- ID3D11InputLayout **inputLayoutOut)
+gl::Error InputLayoutCache::createInputLayout(
+ Renderer11 *renderer,
+ const AttribIndexArray &sortedSemanticIndices,
+ const std::vector<const TranslatedAttribute *> &currentAttributes,
+ GLenum mode,
+ gl::Program *program,
+ const DrawCallVertexParams &vertexParams,
+ d3d11::InputLayout *inputLayoutOut)
{
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+ auto featureLevel = renderer->getRenderer11DeviceCaps().featureLevel;
bool programUsesInstancedPointSprites =
programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation();
@@ -544,20 +401,17 @@ gl::Error InputLayoutCache::createInputLayout(const SortedAttribArray &sortedAtt
unsigned int inputElementCount = 0;
std::array<D3D11_INPUT_ELEMENT_DESC, gl::MAX_VERTEX_ATTRIBS> inputElements;
- for (size_t attribIndex = 0; attribIndex < attribCount; ++attribIndex)
+ for (size_t attribIndex = 0; attribIndex < currentAttributes.size(); ++attribIndex)
{
- const auto &attrib = *sortedAttributes[attribIndex];
+ const auto &attrib = *currentAttributes[attribIndex];
const int sortedIndex = sortedSemanticIndices[attribIndex];
- if (!attrib.active)
- continue;
-
D3D11_INPUT_CLASSIFICATION inputClass =
attrib.divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA;
const auto &vertexFormatType =
gl::GetVertexFormatType(*attrib.attribute, attrib.currentValueType);
- const auto &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormatType, mFeatureLevel);
+ const auto &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormatType, featureLevel);
auto *inputElement = &inputElements[inputElementCount];
@@ -584,23 +438,28 @@ gl::Error InputLayoutCache::createInputLayout(const SortedAttribArray &sortedAtt
// doesn't support OpenGL ES 3.0.
// As per the spec for ANGLE_instanced_arrays, not all attributes can be instanced
// simultaneously, so a non-instanced element must exist.
+
+ GLsizei numIndicesPerInstance = 0;
+ if (vertexParams.instances() > 0)
+ {
+ // This may trigger an evaluation of the index range.
+ numIndicesPerInstance = vertexParams.vertexCount();
+ }
+
for (size_t elementIndex = 0; elementIndex < inputElementCount; ++elementIndex)
{
- if (sortedAttributes[elementIndex]->active)
+ // If rendering points and instanced pointsprite emulation is being used, the
+ // inputClass is required to be configured as per instance data
+ if (mode == GL_POINTS)
{
- // If rendering points and instanced pointsprite emulation is being used, the
- // inputClass is required to be configured as per instance data
- if (mode == GL_POINTS)
+ inputElements[elementIndex].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
+ inputElements[elementIndex].InstanceDataStepRate = 1;
+ if (numIndicesPerInstance > 0 && currentAttributes[elementIndex]->divisor > 0)
{
- inputElements[elementIndex].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
- inputElements[elementIndex].InstanceDataStepRate = 1;
- if (numIndicesPerInstance > 0 && sortedAttributes[elementIndex]->divisor > 0)
- {
- inputElements[elementIndex].InstanceDataStepRate = numIndicesPerInstance;
- }
+ inputElements[elementIndex].InstanceDataStepRate = numIndicesPerInstance;
}
- inputElements[elementIndex].InputSlot++;
}
+ inputElements[elementIndex].InputSlot++;
}
inputElements[inputElementCount].SemanticName = "SPRITEPOSITION";
@@ -622,28 +481,23 @@ gl::Error InputLayoutCache::createInputLayout(const SortedAttribArray &sortedAtt
inputElementCount++;
}
- const gl::InputLayout &shaderInputLayout = GetInputLayout(sortedAttributes, attribCount);
-
ShaderExecutableD3D *shader = nullptr;
- gl::Error error =
- programD3D->getVertexExecutableForInputLayout(shaderInputLayout, &shader, nullptr);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(programD3D->getVertexExecutableForCachedInputLayout(&shader, nullptr));
ShaderExecutableD3D *shader11 = GetAs<ShaderExecutable11>(shader);
- HRESULT result =
- mDevice->CreateInputLayout(inputElements.data(), inputElementCount, shader11->getFunction(),
- shader11->getLength(), inputLayoutOut);
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY,
- "Failed to create internal input layout, HRESULT: 0x%08x", result);
- }
+ InputElementArray inputElementArray(inputElements.data(), inputElementCount);
+ ShaderData vertexShaderData(shader11->getFunction(), shader11->getLength());
- return gl::Error(GL_NO_ERROR);
+ ANGLE_TRY(renderer->allocateResource(inputElementArray, &vertexShaderData, inputLayoutOut));
+ return gl::NoError();
+}
+
+void InputLayoutCache::setCacheSize(size_t newCacheSize)
+{
+ // Forces a reset of the cache.
+ LayoutCache newCache(newCacheSize);
+ mLayoutCache.Swap(newCache);
}
} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h
index e208ae3c64..8d7c7dd0f0 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h
@@ -20,12 +20,55 @@
#include "common/angleutils.h"
#include "libANGLE/Constants.h"
#include "libANGLE/Error.h"
+#include "libANGLE/SizedMRUCache.h"
#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
+
+namespace rx
+{
+class DrawCallVertexParams;
+struct PackedAttributeLayout
+{
+ PackedAttributeLayout();
+ PackedAttributeLayout(const PackedAttributeLayout &other);
+
+ void addAttributeData(GLenum glType,
+ UINT semanticIndex,
+ gl::VertexFormatType vertexFormatType,
+ unsigned int divisor);
+
+ bool operator==(const PackedAttributeLayout &other) const;
+
+ enum Flags
+ {
+ FLAG_USES_INSTANCED_SPRITES = 0x1,
+ FLAG_INSTANCED_SPRITES_ACTIVE = 0x2,
+ FLAG_INSTANCED_RENDERING_ACTIVE = 0x4,
+ };
+
+ uint32_t numAttributes;
+ uint32_t flags;
+ std::array<uint32_t, gl::MAX_VERTEX_ATTRIBS> attributeData;
+};
+} // namespace rx
+
+namespace std
+{
+template <>
+struct hash<rx::PackedAttributeLayout>
+{
+ size_t operator()(const rx::PackedAttributeLayout &value) const
+ {
+ return angle::ComputeGenericHash(value);
+ }
+};
+} // namespace std
namespace gl
{
class Program;
-}
+} // namespace gl
namespace rx
{
@@ -33,91 +76,58 @@ struct TranslatedAttribute;
struct TranslatedIndexData;
struct SourceIndexData;
class ProgramD3D;
-
-using SortedAttribArray = std::array<const TranslatedAttribute *, gl::MAX_VERTEX_ATTRIBS>;
-using SortedIndexArray = std::array<int, gl::MAX_VERTEX_ATTRIBS>;
+class Renderer11;
class InputLayoutCache : angle::NonCopyable
{
public:
InputLayoutCache();
- virtual ~InputLayoutCache();
+ ~InputLayoutCache();
- void initialize(ID3D11Device *device, ID3D11DeviceContext *context);
void clear();
- void markDirty();
- gl::Error applyVertexBuffers(const std::vector<TranslatedAttribute> &attributes,
+ gl::Error applyVertexBuffers(const gl::Context *context,
+ const std::vector<const TranslatedAttribute *> &currentAttributes,
GLenum mode,
- gl::Program *program,
- TranslatedIndexData *indexInfo,
- GLsizei numIndicesPerInstance);
+ GLint start,
+ bool isIndexedRendering);
- gl::Error updateVertexOffsetsForPointSpritesEmulation(GLsizei emulatedInstanceId);
+ gl::Error updateVertexOffsetsForPointSpritesEmulation(
+ Renderer11 *renderer,
+ const std::vector<const TranslatedAttribute *> &currentAttributes,
+ GLint startVertex,
+ GLsizei emulatedInstanceId);
// Useful for testing
- void setCacheSize(unsigned int cacheSize) { mCacheSize = cacheSize; }
-
- private:
- struct PackedAttributeLayout
- {
- PackedAttributeLayout()
- : numAttributes(0),
- flags(0)
- {
- }
-
- void addAttributeData(GLenum glType,
- UINT semanticIndex,
- gl::VertexFormatType vertexFormatType,
- unsigned int divisor);
-
- bool operator<(const PackedAttributeLayout &other) const;
-
- enum Flags
- {
- FLAG_USES_INSTANCED_SPRITES = 0x1,
- FLAG_INSTANCED_SPRITES_ACTIVE = 0x2,
- FLAG_INSTANCED_RENDERING_ACTIVE = 0x4,
- };
-
- size_t numAttributes;
- unsigned int flags;
- uint32_t attributeData[gl::MAX_VERTEX_ATTRIBS];
- };
+ void setCacheSize(size_t newCacheSize);
- gl::Error updateInputLayout(gl::Program *program,
+ gl::Error updateInputLayout(Renderer11 *renderer,
+ const gl::State &state,
+ const std::vector<const TranslatedAttribute *> &currentAttributes,
GLenum mode,
- const SortedAttribArray &sortedAttributes,
- const SortedIndexArray &sortedSemanticIndices,
- size_t attribCount,
- GLsizei numIndicesPerInstance);
- gl::Error createInputLayout(const SortedAttribArray &sortedAttributes,
- const SortedIndexArray &sortedSemanticIndices,
- size_t attribCount,
+ const AttribIndexArray &sortedSemanticIndices,
+ const DrawCallVertexParams &vertexParams);
+
+ private:
+ gl::Error createInputLayout(Renderer11 *renderer,
+ const AttribIndexArray &sortedSemanticIndices,
+ const std::vector<const TranslatedAttribute *> &currentAttributes,
GLenum mode,
gl::Program *program,
- GLsizei numIndicesPerInstance,
- ID3D11InputLayout **inputLayoutOut);
-
- std::map<PackedAttributeLayout, ID3D11InputLayout *> mLayoutMap;
+ const DrawCallVertexParams &vertexParams,
+ d3d11::InputLayout *inputLayoutOut);
- ID3D11InputLayout *mCurrentIL;
- ID3D11Buffer *mCurrentBuffers[gl::MAX_VERTEX_ATTRIBS];
- UINT mCurrentVertexStrides[gl::MAX_VERTEX_ATTRIBS];
- UINT mCurrentVertexOffsets[gl::MAX_VERTEX_ATTRIBS];
- SortedAttribArray mSortedAttributes;
- size_t mUnsortedAttributesCount;
+ // Starting cache size.
+ static constexpr size_t kDefaultCacheSize = 1024;
- ID3D11Buffer *mPointSpriteVertexBuffer;
- ID3D11Buffer *mPointSpriteIndexBuffer;
+ // The cache tries to clean up this many states at once.
+ static constexpr size_t kGCLimit = 128;
- unsigned int mCacheSize;
- unsigned long long mCounter;
+ using LayoutCache = angle::base::HashingMRUCache<PackedAttributeLayout, d3d11::InputLayout>;
+ LayoutCache mLayoutCache;
- ID3D11Device *mDevice;
- ID3D11DeviceContext *mDeviceContext;
- D3D_FEATURE_LEVEL mFeatureLevel;
+ d3d11::Buffer mPointSpriteVertexBuffer;
+ d3d11::Buffer mPointSpriteIndexBuffer;
};
} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
deleted file mode 100644
index 612b06bb10..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
+++ /dev/null
@@ -1,97 +0,0 @@
-//
-// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// NativeWindow.h: Defines NativeWindow, a class for managing and
-// performing operations on an EGLNativeWindowType.
-// It is used for HWND (Desktop Windows) and IInspectable objects
-//(Windows Store Applications).
-
-#ifndef LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW_H_
-#define LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW_H_
-
-#include "common/debug.h"
-#include "common/platform.h"
-
-#include <EGL/eglplatform.h>
-#include "libANGLE/Config.h"
-
-// DXGISwapChain and DXGIFactory are typedef'd to specific required
-// types. The HWND NativeWindow implementation requires IDXGISwapChain
-// and IDXGIFactory and the Windows Store NativeWindow
-// implementation requires IDXGISwapChain1 and IDXGIFactory2.
-#if defined(ANGLE_ENABLE_WINDOWS_STORE)
-typedef IDXGISwapChain1 DXGISwapChain;
-typedef IDXGIFactory2 DXGIFactory;
-
-#include <wrl.h>
-#include <wrl/wrappers/corewrappers.h>
-#include <windows.applicationmodel.core.h>
-#include <memory>
-
-namespace rx
-{
-class InspectableNativeWindow;
-}
-
-using namespace Microsoft::WRL;
-using namespace Microsoft::WRL::Wrappers;
-
-#elif defined(ANGLE_ENABLE_D3D11)
-typedef IDXGISwapChain DXGISwapChain;
-typedef IDXGIFactory DXGIFactory;
-#endif
-
-typedef interface IDCompositionDevice IDCompositionDevice;
-typedef interface IDCompositionTarget IDCompositionTarget;
-typedef interface IDCompositionVisual IDCompositionVisual;
-
-namespace rx
-{
-
-class NativeWindow
-{
- public:
- enum RotationFlags { RotateNone = 0, RotateLeft = 1, RotateRight = 2 };
- explicit NativeWindow(EGLNativeWindowType window,
- const egl::Config *config,
- bool directComposition);
-
- ~NativeWindow();
- bool initialize();
- bool getClientRect(LPRECT rect);
- bool isIconic();
-#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
- RotationFlags rotationFlags() const;
-#endif
- static bool isValidNativeWindow(EGLNativeWindowType window);
-
-#if defined(ANGLE_ENABLE_D3D11)
- HRESULT createSwapChain(ID3D11Device* device, DXGIFactory* factory,
- DXGI_FORMAT format, UINT width, UINT height,
- DXGISwapChain** swapChain);
-#endif
-
- inline EGLNativeWindowType getNativeWindow() const { return mWindow; }
-
- void commitChange();
-
- private:
- EGLNativeWindowType mWindow;
-
- bool mDirectComposition;
- IDCompositionDevice *mDevice;
- IDCompositionTarget *mCompositionTarget;
- IDCompositionVisual *mVisual;
- const egl::Config *mConfig;
-#if defined(ANGLE_ENABLE_WINDOWS_STORE)
- std::shared_ptr<InspectableNativeWindow> mImpl;
-#endif
-
-};
-
-}
-
-#endif // LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h
new file mode 100644
index 0000000000..ab234d4450
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// NativeWindow11.h: Defines NativeWindow11, a class for managing and performing operations on an
+// EGLNativeWindowType for the D3D11 renderer.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW11_H_
+
+#include "common/debug.h"
+#include "common/platform.h"
+
+#include "libANGLE/Config.h"
+#include "libANGLE/renderer/d3d/NativeWindowD3D.h"
+
+namespace rx
+{
+
+class NativeWindow11 : public NativeWindowD3D
+{
+ public:
+ NativeWindow11(EGLNativeWindowType window) : NativeWindowD3D(window) {}
+
+ virtual HRESULT createSwapChain(ID3D11Device *device,
+ IDXGIFactory *factory,
+ DXGI_FORMAT format,
+ UINT width,
+ UINT height,
+ UINT samples,
+ IDXGISwapChain **swapChain) = 0;
+ virtual void commitChange() = 0;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW11_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp
index dfc521f14f..7d7ecb0976 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp
@@ -36,40 +36,25 @@ namespace rx
PixelTransfer11::PixelTransfer11(Renderer11 *renderer)
: mRenderer(renderer),
mResourcesLoaded(false),
- mBufferToTextureVS(NULL),
- mBufferToTextureGS(NULL),
- mParamsConstantBuffer(NULL),
- mCopyRasterizerState(NULL),
- mCopyDepthStencilState(NULL)
+ mBufferToTextureVS(),
+ mBufferToTextureGS(),
+ mParamsConstantBuffer(),
+ mCopyRasterizerState(),
+ mCopyDepthStencilState()
{
}
PixelTransfer11::~PixelTransfer11()
{
- for (auto shaderMapIt = mBufferToTexturePSMap.begin(); shaderMapIt != mBufferToTexturePSMap.end(); shaderMapIt++)
- {
- SafeRelease(shaderMapIt->second);
- }
-
- mBufferToTexturePSMap.clear();
-
- SafeRelease(mBufferToTextureVS);
- SafeRelease(mBufferToTextureGS);
- SafeRelease(mParamsConstantBuffer);
- SafeRelease(mCopyRasterizerState);
- SafeRelease(mCopyDepthStencilState);
}
gl::Error PixelTransfer11::loadResources()
{
if (mResourcesLoaded)
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
- HRESULT result = S_OK;
- ID3D11Device *device = mRenderer->getDevice();
-
D3D11_RASTERIZER_DESC rasterDesc;
rasterDesc.FillMode = D3D11_FILL_SOLID;
rasterDesc.CullMode = D3D11_CULL_NONE;
@@ -82,12 +67,7 @@ gl::Error PixelTransfer11::loadResources()
rasterDesc.MultisampleEnable = FALSE;
rasterDesc.AntialiasedLineEnable = FALSE;
- result = device->CreateRasterizerState(&rasterDesc, &mCopyRasterizerState);
- ASSERT(SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer rasterizer state, result: 0x%X.", result);
- }
+ ANGLE_TRY(mRenderer->allocateResource(rasterDesc, &mCopyRasterizerState));
D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
depthStencilDesc.DepthEnable = true;
@@ -105,12 +85,7 @@ gl::Error PixelTransfer11::loadResources()
depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
- result = device->CreateDepthStencilState(&depthStencilDesc, &mCopyDepthStencilState);
- ASSERT(SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer depth stencil state, result: 0x%X.", result);
- }
+ ANGLE_TRY(mRenderer->allocateResource(depthStencilDesc, &mCopyDepthStencilState));
D3D11_BUFFER_DESC constantBufferDesc = { 0 };
constantBufferDesc.ByteWidth = roundUp<UINT>(sizeof(CopyShaderParams), 32u);
@@ -120,38 +95,23 @@ gl::Error PixelTransfer11::loadResources()
constantBufferDesc.MiscFlags = 0;
constantBufferDesc.StructureByteStride = 0;
- result = device->CreateBuffer(&constantBufferDesc, NULL, &mParamsConstantBuffer);
- ASSERT(SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer constant buffer, result: 0x%X.", result);
- }
- d3d11::SetDebugName(mParamsConstantBuffer, "PixelTransfer11 constant buffer");
+ ANGLE_TRY(mRenderer->allocateResource(constantBufferDesc, &mParamsConstantBuffer));
+ mParamsConstantBuffer.setDebugName("PixelTransfer11 constant buffer");
// init shaders
- mBufferToTextureVS = d3d11::CompileVS(device, g_VS_BufferToTexture, "BufferToTexture VS");
- if (!mBufferToTextureVS)
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture vertex shader.");
- }
+ ANGLE_TRY(mRenderer->allocateResource(ShaderData(g_VS_BufferToTexture), &mBufferToTextureVS));
+ mBufferToTextureVS.setDebugName("BufferToTexture VS");
- mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS");
- if (!mBufferToTextureGS)
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture geometry shader.");
- }
+ ANGLE_TRY(mRenderer->allocateResource(ShaderData(g_GS_BufferToTexture), &mBufferToTextureGS));
+ mBufferToTextureGS.setDebugName("BufferToTexture GS");
- gl::Error error = buildShaderMap();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(buildShaderMap());
StructZero(&mParamsData);
mResourcesLoaded = true;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, const gl::Extents &destSize, GLenum internalFormat,
@@ -162,7 +122,7 @@ void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, cons
float texelCenterX = 0.5f / static_cast<float>(destSize.width - 1);
float texelCenterY = 0.5f / static_cast<float>(destSize.height - 1);
- unsigned int bytesPerPixel = gl::GetInternalFormatInfo(internalFormat).pixelBytes;
+ unsigned int bytesPerPixel = gl::GetSizedInternalFormatInfo(internalFormat).pixelBytes;
unsigned int alignmentBytes = static_cast<unsigned int>(unpack.alignment);
unsigned int alignmentPixels = (alignmentBytes <= bytesPerPixel ? 1 : alignmentBytes / bytesPerPixel);
@@ -177,14 +137,15 @@ void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, cons
parametersOut->FirstSlice = destArea.z;
}
-gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget,
- GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea)
+gl::Error PixelTransfer11::copyBufferToTexture(const gl::Context *context,
+ const gl::PixelUnpackState &unpack,
+ unsigned int offset,
+ RenderTargetD3D *destRenderTarget,
+ GLenum destinationFormat,
+ GLenum sourcePixelsType,
+ const gl::Box &destArea)
{
- gl::Error error = loadResources();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(loadResources());
gl::Extents destSize = destRenderTarget->getExtents();
@@ -192,114 +153,106 @@ gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpac
destArea.y >= 0 && destArea.y + destArea.height <= destSize.height &&
destArea.z >= 0 && destArea.z + destArea.depth <= destSize.depth );
- const gl::Buffer &sourceBuffer = *unpack.pixelBuffer.get();
+ const gl::Buffer &sourceBuffer =
+ *context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
ASSERT(mRenderer->supportsFastCopyBufferToTexture(destinationFormat));
- ID3D11PixelShader *pixelShader = findBufferToTexturePS(destinationFormat);
+ const d3d11::PixelShader *pixelShader = findBufferToTexturePS(destinationFormat);
ASSERT(pixelShader);
// The SRV must be in the proper read format, which may be different from the destination format
// EG: for half float data, we can load full precision floats with implicit conversion
- GLenum unsizedFormat = gl::GetInternalFormatInfo(destinationFormat).format;
- GLenum sourceFormat = gl::GetSizedInternalFormat(unsizedFormat, sourcePixelsType);
+ GLenum unsizedFormat = gl::GetUnsizedFormat(destinationFormat);
+ const gl::InternalFormat &sourceglFormatInfo =
+ gl::GetInternalFormatInfo(unsizedFormat, sourcePixelsType);
- const d3d11::TextureFormat &sourceFormatInfo = d3d11::GetTextureFormatInfo(sourceFormat, mRenderer->getRenderer11DeviceCaps());
+ const d3d11::Format &sourceFormatInfo = d3d11::Format::Get(
+ sourceglFormatInfo.sizedInternalFormat, mRenderer->getRenderer11DeviceCaps());
DXGI_FORMAT srvFormat = sourceFormatInfo.srvFormat;
ASSERT(srvFormat != DXGI_FORMAT_UNKNOWN);
Buffer11 *bufferStorage11 = GetAs<Buffer11>(sourceBuffer.getImplementation());
- ID3D11ShaderResourceView *bufferSRV = bufferStorage11->getSRV(srvFormat);
- ASSERT(bufferSRV != NULL);
+ const d3d11::ShaderResourceView *bufferSRV = nullptr;
+ ANGLE_TRY_RESULT(bufferStorage11->getSRV(context, srvFormat), bufferSRV);
+ ASSERT(bufferSRV != nullptr);
- ID3D11RenderTargetView *textureRTV = GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView();
- ASSERT(textureRTV != NULL);
+ const d3d11::RenderTargetView &textureRTV =
+ GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView();
+ ASSERT(textureRTV.valid());
CopyShaderParams shaderParams;
- setBufferToTextureCopyParams(destArea, destSize, sourceFormat, unpack, offset, &shaderParams);
+ setBufferToTextureCopyParams(destArea, destSize, sourceglFormatInfo.sizedInternalFormat, unpack,
+ offset, &shaderParams);
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
- ID3D11Buffer *nullBuffer = NULL;
- UINT zero = 0;
-
// Are we doing a 2D or 3D copy?
- ID3D11GeometryShader *geometryShader = ((destSize.depth > 1) ? mBufferToTextureGS : NULL);
- auto stateManager = mRenderer->getStateManager();
+ const auto *geometryShader = ((destSize.depth > 1) ? &mBufferToTextureGS : nullptr);
+ StateManager11 *stateManager = mRenderer->getStateManager();
- deviceContext->VSSetShader(mBufferToTextureVS, NULL, 0);
- deviceContext->GSSetShader(geometryShader, NULL, 0);
- deviceContext->PSSetShader(pixelShader, NULL, 0);
+ stateManager->setDrawShaders(&mBufferToTextureVS, geometryShader, pixelShader);
stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, bufferSRV);
- deviceContext->IASetInputLayout(NULL);
- deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
+ stateManager->setInputLayout(nullptr);
+ stateManager->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
- deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
- deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF);
- deviceContext->OMSetDepthStencilState(mCopyDepthStencilState, 0xFFFFFFFF);
- deviceContext->RSSetState(mCopyRasterizerState);
+ stateManager->setSingleVertexBuffer(nullptr, 0, 0);
+ stateManager->setSimpleBlendState(nullptr);
+ stateManager->setDepthStencilState(&mCopyDepthStencilState, 0xFFFFFFFF);
+ stateManager->setRasterizerState(&mCopyRasterizerState);
- mRenderer->setOneTimeRenderTarget(textureRTV);
+ stateManager->setRenderTarget(textureRTV.get(), nullptr);
if (!StructEquals(mParamsData, shaderParams))
{
- d3d11::SetBufferData(deviceContext, mParamsConstantBuffer, shaderParams);
+ d3d11::SetBufferData(deviceContext, mParamsConstantBuffer.get(), shaderParams);
mParamsData = shaderParams;
}
- deviceContext->VSSetConstantBuffers(0, 1, &mParamsConstantBuffer);
+ stateManager->setVertexConstantBuffer(0, &mParamsConstantBuffer);
// Set the viewport
- D3D11_VIEWPORT viewport;
- viewport.TopLeftX = 0;
- viewport.TopLeftY = 0;
- viewport.Width = static_cast<FLOAT>(destSize.width);
- viewport.Height = static_cast<FLOAT>(destSize.height);
- viewport.MinDepth = 0.0f;
- viewport.MaxDepth = 1.0f;
- deviceContext->RSSetViewports(1, &viewport);
+ stateManager->setSimpleViewport(destSize);
UINT numPixels = (destArea.width * destArea.height * destArea.depth);
deviceContext->Draw(numPixels, 0);
- // Unbind textures and render targets and vertex buffer
- stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL);
- deviceContext->VSSetConstantBuffers(0, 1, &nullBuffer);
-
- mRenderer->markAllStateDirty();
-
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error PixelTransfer11::buildShaderMap()
{
- ID3D11Device *device = mRenderer->getDevice();
-
- mBufferToTexturePSMap[GL_FLOAT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4F, "BufferToTexture RGBA ps");
- mBufferToTexturePSMap[GL_INT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4I, "BufferToTexture RGBA-I ps");
- mBufferToTexturePSMap[GL_UNSIGNED_INT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4UI, "BufferToTexture RGBA-UI ps");
-
- // Check that all the shaders were created successfully
- for (auto shaderMapIt = mBufferToTexturePSMap.begin(); shaderMapIt != mBufferToTexturePSMap.end(); shaderMapIt++)
- {
- if (shaderMapIt->second == NULL)
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture pixel shader.");
- }
- }
-
- return gl::Error(GL_NO_ERROR);
+ d3d11::PixelShader bufferToTextureFloat;
+ d3d11::PixelShader bufferToTextureInt;
+ d3d11::PixelShader bufferToTextureUint;
+
+ ANGLE_TRY(
+ mRenderer->allocateResource(ShaderData(g_PS_BufferToTexture_4F), &bufferToTextureFloat));
+ ANGLE_TRY(
+ mRenderer->allocateResource(ShaderData(g_PS_BufferToTexture_4I), &bufferToTextureInt));
+ ANGLE_TRY(
+ mRenderer->allocateResource(ShaderData(g_PS_BufferToTexture_4UI), &bufferToTextureUint));
+
+ bufferToTextureFloat.setDebugName("BufferToTexture RGBA ps");
+ bufferToTextureInt.setDebugName("BufferToTexture RGBA-I ps");
+ bufferToTextureUint.setDebugName("BufferToTexture RGBA-UI ps");
+
+ mBufferToTexturePSMap[GL_FLOAT] = std::move(bufferToTextureFloat);
+ mBufferToTexturePSMap[GL_INT] = std::move(bufferToTextureInt);
+ mBufferToTexturePSMap[GL_UNSIGNED_INT] = std::move(bufferToTextureUint);
+
+ return gl::NoError();
}
-ID3D11PixelShader *PixelTransfer11::findBufferToTexturePS(GLenum internalFormat) const
+const d3d11::PixelShader *PixelTransfer11::findBufferToTexturePS(GLenum internalFormat) const
{
- GLenum componentType = gl::GetInternalFormatInfo(internalFormat).componentType;
+ GLenum componentType = gl::GetSizedInternalFormatInfo(internalFormat).componentType;
if (componentType == GL_SIGNED_NORMALIZED || componentType == GL_UNSIGNED_NORMALIZED)
{
componentType = GL_FLOAT;
}
auto shaderMapIt = mBufferToTexturePSMap.find(componentType);
- return (shaderMapIt == mBufferToTexturePSMap.end() ? NULL : shaderMapIt->second);
+ return (shaderMapIt == mBufferToTexturePSMap.end() ? nullptr : &shaderMapIt->second);
}
-}
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h
index 1672121ec7..a93544247e 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h
@@ -11,14 +11,14 @@
#ifndef LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_
#define LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_
-#include "libANGLE/Error.h"
-
-#include "common/platform.h"
-
#include <GLES2/gl2.h>
#include <map>
+#include "common/platform.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
+
namespace gl
{
@@ -45,8 +45,13 @@ class PixelTransfer11
// destRenderTarget: individual slice/layer of a target texture
// destinationFormat/sourcePixelsType: determines shaders + shader parameters
// destArea: the sub-section of destRenderTarget to copy to
- gl::Error copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget,
- GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea);
+ gl::Error copyBufferToTexture(const gl::Context *context,
+ const gl::PixelUnpackState &unpack,
+ unsigned int offset,
+ RenderTargetD3D *destRenderTarget,
+ GLenum destinationFormat,
+ GLenum sourcePixelsType,
+ const gl::Box &destArea);
private:
@@ -68,22 +73,21 @@ class PixelTransfer11
gl::Error loadResources();
gl::Error buildShaderMap();
- ID3D11PixelShader *findBufferToTexturePS(GLenum internalFormat) const;
+ const d3d11::PixelShader *findBufferToTexturePS(GLenum internalFormat) const;
Renderer11 *mRenderer;
bool mResourcesLoaded;
- std::map<GLenum, ID3D11PixelShader *> mBufferToTexturePSMap;
- ID3D11VertexShader *mBufferToTextureVS;
- ID3D11GeometryShader *mBufferToTextureGS;
- ID3D11Buffer *mParamsConstantBuffer;
+ std::map<GLenum, d3d11::PixelShader> mBufferToTexturePSMap;
+ d3d11::VertexShader mBufferToTextureVS;
+ d3d11::GeometryShader mBufferToTextureGS;
+ d3d11::Buffer mParamsConstantBuffer;
CopyShaderParams mParamsData;
- ID3D11RasterizerState *mCopyRasterizerState;
- ID3D11DepthStencilState *mCopyDepthStencilState;
-
+ d3d11::RasterizerState mCopyRasterizerState;
+ d3d11::DepthStencilState mCopyDepthStencilState;
};
-}
+} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.cpp
new file mode 100644
index 0000000000..c9554431e5
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.cpp
@@ -0,0 +1,24 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ProgramPipelineNULL.cpp:
+// Implements the class methods for ProgramPipeline11.
+//
+
+#include "libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h"
+
+namespace rx
+{
+
+ProgramPipeline11::ProgramPipeline11(const gl::ProgramPipelineState &state)
+ : ProgramPipelineImpl(state)
+{
+}
+
+ProgramPipeline11::~ProgramPipeline11()
+{
+}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h
new file mode 100644
index 0000000000..cf838eec05
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h
@@ -0,0 +1,27 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ProgramPipeline11.h:
+// Defines the class interface for ProgramPipeline11, implementing ProgramPipelineImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_PROGRAMPIPELINE11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_PROGRAMPIPELINE11_H_
+
+#include "libANGLE/renderer/ProgramPipelineImpl.h"
+
+namespace rx
+{
+
+class ProgramPipeline11 : public ProgramPipelineImpl
+{
+ public:
+ ProgramPipeline11(const gl::ProgramPipelineState &state);
+ ~ProgramPipeline11() override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_PROGRAMPIPELINE11_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
index 0a79b26df0..66b9476e7f 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
@@ -7,146 +7,96 @@
// Query11.cpp: Defines the rx::Query11 class which implements rx::QueryImpl.
#include "libANGLE/renderer/d3d/d3d11/Query11.h"
-#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
-#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
-#include "common/utilities.h"
#include <GLES2/gl2ext.h>
-#if defined(ANGLE_MINGW32_COMPAT)
-typedef struct D3D11_QUERY_DATA_SO_STATISTICS {
- UINT64 NumPrimitivesWritten;
- UINT64 PrimitivesStorageNeeded;
-} D3D11_QUERY_DATA_SO_STATISTICS;
-#endif // ANGLE_MINGW32_COMPAT
-
-#ifndef ANGLE_D3D11_QDTD_AVAILABLE
-typedef struct D3D11_QUERY_DATA_TIMESTAMP_DISJOINT {
- UINT64 Frequency;
- BOOL Disjoint;
-} D3D11_QUERY_DATA_TIMESTAMP_DISJOINT;
-#endif // MINGW32
+#include "common/utilities.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
-namespace rx
+namespace
{
-Query11::Query11(Renderer11 *renderer, GLenum type)
- : QueryImpl(type),
- mResult(0),
- mQueryFinished(false),
- mRenderer(renderer),
- mQuery(nullptr),
- mTimestampBeginQuery(nullptr),
- mTimestampEndQuery(nullptr)
+GLuint64 MergeQueryResults(GLenum type, GLuint64 currentResult, GLuint64 newResult)
{
-}
+ switch (type)
+ {
+ case GL_ANY_SAMPLES_PASSED:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
+ return (currentResult == GL_TRUE || newResult == GL_TRUE) ? GL_TRUE : GL_FALSE;
-Query11::~Query11()
-{
- SafeRelease(mQuery);
- SafeRelease(mTimestampBeginQuery);
- SafeRelease(mTimestampEndQuery);
-}
+ case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+ return currentResult + newResult;
-gl::Error Query11::begin()
-{
- if (mQuery == nullptr)
- {
- D3D11_QUERY_DESC queryDesc;
- queryDesc.Query = gl_d3d11::ConvertQueryType(getType());
- queryDesc.MiscFlags = 0;
+ case GL_TIME_ELAPSED_EXT:
+ return currentResult + newResult;
- ID3D11Device *device = mRenderer->getDevice();
+ case GL_TIMESTAMP_EXT:
+ return newResult;
- HRESULT result = device->CreateQuery(&queryDesc, &mQuery);
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.", result);
- }
+ case GL_COMMANDS_COMPLETED_CHROMIUM:
+ return newResult;
- // If we are doing time elapsed we also need a query to actually query the timestamp
- if (getType() == GL_TIME_ELAPSED_EXT)
- {
- D3D11_QUERY_DESC desc;
- desc.Query = D3D11_QUERY_TIMESTAMP;
- desc.MiscFlags = 0;
- result = device->CreateQuery(&desc, &mTimestampBeginQuery);
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.",
- result);
- }
- result = device->CreateQuery(&desc, &mTimestampEndQuery);
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.",
- result);
- }
- }
+ default:
+ UNREACHABLE();
+ return 0;
}
+}
- ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+} // anonymous namespace
- context->Begin(mQuery);
+namespace rx
+{
- // If we are doing time elapsed query the begin timestamp
- if (getType() == GL_TIME_ELAPSED_EXT)
- {
- context->End(mTimestampBeginQuery);
- }
- return gl::Error(GL_NO_ERROR);
+Query11::QueryState::QueryState() : query(), beginTimestamp(), endTimestamp(), finished(false)
+{
}
-gl::Error Query11::end()
+Query11::QueryState::~QueryState()
{
- ASSERT(mQuery);
-
- ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+}
- // If we are doing time elapsed query the end timestamp
- if (getType() == GL_TIME_ELAPSED_EXT)
- {
- context->End(mTimestampEndQuery);
- }
+Query11::Query11(Renderer11 *renderer, GLenum type)
+ : QueryImpl(type), mResult(0), mResultSum(0), mRenderer(renderer)
+{
+ mActiveQuery = std::unique_ptr<QueryState>(new QueryState());
+}
- context->End(mQuery);
+Query11::~Query11()
+{
+ mRenderer->getStateManager()->onDeleteQueryObject(this);
+}
- mQueryFinished = false;
- mResult = GL_FALSE;
+gl::Error Query11::begin()
+{
+ mResultSum = 0;
+ mRenderer->getStateManager()->onBeginQuery(this);
+ return resume();
+}
- return gl::Error(GL_NO_ERROR);
+gl::Error Query11::end()
+{
+ return pause();
}
gl::Error Query11::queryCounter()
{
// This doesn't do anything for D3D11 as we don't support timestamps
ASSERT(getType() == GL_TIMESTAMP_EXT);
- mQueryFinished = true;
- mResult = 0;
- return gl::Error(GL_NO_ERROR);
+ mResultSum = 0;
+ mPendingQueries.push_back(std::unique_ptr<QueryState>(new QueryState()));
+ return gl::NoError();
}
template <typename T>
gl::Error Query11::getResultBase(T *params)
{
- while (!mQueryFinished)
- {
- gl::Error error = testQuery();
- if (error.isError())
- {
- return error;
- }
-
- if (!mQueryFinished)
- {
- ScheduleYield();
- }
- }
+ ASSERT(!mActiveQuery->query.valid());
+ ANGLE_TRY(flush(true));
+ ASSERT(mPendingQueries.empty());
+ *params = static_cast<T>(mResultSum);
- ASSERT(mQueryFinished);
- *params = static_cast<T>(mResult);
-
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error Query11::getResult(GLint *params)
@@ -171,105 +121,197 @@ gl::Error Query11::getResult(GLuint64 *params)
gl::Error Query11::isResultAvailable(bool *available)
{
- gl::Error error = testQuery();
- if (error.isError())
+ ANGLE_TRY(flush(false));
+
+ *available = mPendingQueries.empty();
+ return gl::NoError();
+}
+
+gl::Error Query11::pause()
+{
+ if (mActiveQuery->query.valid())
{
- return error;
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ GLenum queryType = getType();
+
+ // If we are doing time elapsed query the end timestamp
+ if (queryType == GL_TIME_ELAPSED_EXT)
+ {
+ context->End(mActiveQuery->endTimestamp.get());
+ }
+
+ context->End(mActiveQuery->query.get());
+
+ mPendingQueries.push_back(std::move(mActiveQuery));
+ mActiveQuery = std::unique_ptr<QueryState>(new QueryState());
}
- *available = mQueryFinished;
+ return flush(false);
+}
+
+gl::Error Query11::resume()
+{
+ if (!mActiveQuery->query.valid())
+ {
+ ANGLE_TRY(flush(false));
+
+ GLenum queryType = getType();
+ D3D11_QUERY d3dQueryType = gl_d3d11::ConvertQueryType(queryType);
- return gl::Error(GL_NO_ERROR);
+ D3D11_QUERY_DESC queryDesc;
+ queryDesc.Query = d3dQueryType;
+ queryDesc.MiscFlags = 0;
+
+ ANGLE_TRY(mRenderer->allocateResource(queryDesc, &mActiveQuery->query));
+
+ // If we are doing time elapsed we also need a query to actually query the timestamp
+ if (queryType == GL_TIME_ELAPSED_EXT)
+ {
+ D3D11_QUERY_DESC desc;
+ desc.Query = D3D11_QUERY_TIMESTAMP;
+ desc.MiscFlags = 0;
+
+ ANGLE_TRY(mRenderer->allocateResource(desc, &mActiveQuery->beginTimestamp));
+ ANGLE_TRY(mRenderer->allocateResource(desc, &mActiveQuery->endTimestamp));
+ }
+
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ if (d3dQueryType != D3D11_QUERY_EVENT)
+ {
+ context->Begin(mActiveQuery->query.get());
+ }
+
+ // If we are doing time elapsed, query the begin timestamp
+ if (queryType == GL_TIME_ELAPSED_EXT)
+ {
+ context->End(mActiveQuery->beginTimestamp.get());
+ }
+ }
+
+ return gl::NoError();
}
-gl::Error Query11::testQuery()
+gl::Error Query11::flush(bool force)
{
- if (!mQueryFinished)
+ while (!mPendingQueries.empty())
{
- ASSERT(mQuery);
+ QueryState *query = mPendingQueries.front().get();
+ do
+ {
+ ANGLE_TRY(testQuery(query));
+ if (!query->finished && !force)
+ {
+ return gl::NoError();
+ }
+ } while (!query->finished);
+
+ mResultSum = MergeQueryResults(getType(), mResultSum, mResult);
+ mPendingQueries.pop_front();
+ }
+
+ return gl::NoError();
+}
+
+gl::Error Query11::testQuery(QueryState *queryState)
+{
+ if (!queryState->finished)
+ {
ID3D11DeviceContext *context = mRenderer->getDeviceContext();
switch (getType())
{
- case GL_ANY_SAMPLES_PASSED_EXT:
- case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+ case GL_ANY_SAMPLES_PASSED_EXT:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
{
+ ASSERT(queryState->query.valid());
UINT64 numPixels = 0;
- HRESULT result = context->GetData(mQuery, &numPixels, sizeof(numPixels), 0);
+ HRESULT result =
+ context->GetData(queryState->query.get(), &numPixels, sizeof(numPixels), 0);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the data of an internal query, result: 0x%X.", result);
+ return gl::OutOfMemory()
+ << "Failed to get the data of an internal query, " << gl::FmtHR(result);
}
if (result == S_OK)
{
- mQueryFinished = true;
- mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE;
+ queryState->finished = true;
+ mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE;
}
}
break;
- case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+ case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
{
- D3D11_QUERY_DATA_SO_STATISTICS soStats = { 0 };
- HRESULT result = context->GetData(mQuery, &soStats, sizeof(soStats), 0);
+ ASSERT(queryState->query.valid());
+ D3D11_QUERY_DATA_SO_STATISTICS soStats = {0};
+ HRESULT result =
+ context->GetData(queryState->query.get(), &soStats, sizeof(soStats), 0);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the data of an internal query, result: 0x%X.", result);
+ return gl::OutOfMemory()
+ << "Failed to get the data of an internal query, " << gl::FmtHR(result);
}
if (result == S_OK)
{
- mQueryFinished = true;
- mResult = static_cast<GLuint64>(soStats.NumPrimitivesWritten);
+ queryState->finished = true;
+ mResult = static_cast<GLuint64>(soStats.NumPrimitivesWritten);
}
}
break;
case GL_TIME_ELAPSED_EXT:
{
+ ASSERT(queryState->query.valid());
+ ASSERT(queryState->beginTimestamp.valid());
+ ASSERT(queryState->endTimestamp.valid());
D3D11_QUERY_DATA_TIMESTAMP_DISJOINT timeStats = {0};
- HRESULT result = context->GetData(mQuery, &timeStats, sizeof(timeStats), 0);
+ HRESULT result =
+ context->GetData(queryState->query.get(), &timeStats, sizeof(timeStats), 0);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY,
- "Failed to get the data of an internal query, result: 0x%X.",
- result);
+ return gl::OutOfMemory()
+ << "Failed to get the data of an internal query, " << gl::FmtHR(result);
}
if (result == S_OK)
{
UINT64 beginTime = 0;
- HRESULT beginRes =
- context->GetData(mTimestampBeginQuery, &beginTime, sizeof(UINT64), 0);
+ HRESULT beginRes = context->GetData(queryState->beginTimestamp.get(),
+ &beginTime, sizeof(UINT64), 0);
if (FAILED(beginRes))
{
- return gl::Error(
- GL_OUT_OF_MEMORY,
- "Failed to get the data of an internal query, result: 0x%X.", beginRes);
+ return gl::OutOfMemory() << "Failed to get the data of an internal query, "
+ << gl::FmtHR(beginRes);
}
UINT64 endTime = 0;
- HRESULT endRes =
- context->GetData(mTimestampEndQuery, &endTime, sizeof(UINT64), 0);
+ HRESULT endRes = context->GetData(queryState->endTimestamp.get(), &endTime,
+ sizeof(UINT64), 0);
if (FAILED(endRes))
{
- return gl::Error(
- GL_OUT_OF_MEMORY,
- "Failed to get the data of an internal query, result: 0x%X.", endRes);
+ return gl::OutOfMemory() << "Failed to get the data of an internal query, "
+ << gl::FmtHR(endRes);
}
if (beginRes == S_OK && endRes == S_OK)
{
- mQueryFinished = true;
+ queryState->finished = true;
if (timeStats.Disjoint)
{
mRenderer->setGPUDisjoint();
}
static_assert(sizeof(UINT64) == sizeof(unsigned long long),
"D3D UINT64 isn't 64 bits");
- if (rx::IsUnsignedMultiplicationSafe(endTime - beginTime, 1000000000ull))
+
+ angle::CheckedNumeric<UINT64> checkedTime(endTime);
+ checkedTime -= beginTime;
+ checkedTime *= 1000000000ull;
+ checkedTime /= timeStats.Frequency;
+ if (checkedTime.IsValid())
{
- mResult = ((endTime - beginTime) * 1000000000ull) / timeStats.Frequency;
+ mResult = checkedTime.ValueOrDie();
}
else
{
@@ -288,23 +330,46 @@ gl::Error Query11::testQuery()
// D3D11 doesn't support GL timestamp queries as D3D timestamps are not guaranteed
// to have any sort of continuity outside of a disjoint timestamp query block, which
// GL depends on
- mResult = 0;
+ ASSERT(!queryState->query.valid());
+ mResult = 0;
+ queryState->finished = true;
}
break;
- default:
- UNREACHABLE();
+ case GL_COMMANDS_COMPLETED_CHROMIUM:
+ {
+ ASSERT(queryState->query.valid());
+ BOOL completed = 0;
+ HRESULT result =
+ context->GetData(queryState->query.get(), &completed, sizeof(completed), 0);
+ if (FAILED(result))
+ {
+ return gl::OutOfMemory()
+ << "Failed to get the data of an internal query, " << gl::FmtHR(result);
+ }
+
+ if (result == S_OK)
+ {
+ queryState->finished = true;
+ ASSERT(completed == TRUE);
+ mResult = (completed == TRUE) ? GL_TRUE : GL_FALSE;
+ }
+ }
break;
+
+ default:
+ UNREACHABLE();
+ break;
}
- if (!mQueryFinished && mRenderer->testDeviceLost())
+ if (!queryState->finished && mRenderer->testDeviceLost())
{
mRenderer->notifyDeviceLost();
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost.");
+ return gl::OutOfMemory() << "Failed to test get query result, device is lost.";
}
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-}
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h
index 29a6e6f85d..a88a8892aa 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h
@@ -9,7 +9,10 @@
#ifndef LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_
#define LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_
+#include <deque>
+
#include "libANGLE/renderer/QueryImpl.h"
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
namespace rx
{
@@ -19,31 +22,45 @@ class Query11 : public QueryImpl
{
public:
Query11(Renderer11 *renderer, GLenum type);
- virtual ~Query11();
+ ~Query11() override;
+
+ gl::Error begin() override;
+ gl::Error end() override;
+ gl::Error queryCounter() override;
+ gl::Error getResult(GLint *params) override;
+ gl::Error getResult(GLuint *params) override;
+ gl::Error getResult(GLint64 *params) override;
+ gl::Error getResult(GLuint64 *params) override;
+ gl::Error isResultAvailable(bool *available) override;
- virtual gl::Error begin();
- virtual gl::Error end();
- virtual gl::Error queryCounter();
- virtual gl::Error getResult(GLint *params);
- virtual gl::Error getResult(GLuint *params);
- virtual gl::Error getResult(GLint64 *params);
- virtual gl::Error getResult(GLuint64 *params);
- virtual gl::Error isResultAvailable(bool *available);
+ gl::Error pause();
+ gl::Error resume();
private:
- gl::Error testQuery();
+ struct QueryState final : private angle::NonCopyable
+ {
+ QueryState();
+ ~QueryState();
+
+ d3d11::Query query;
+ d3d11::Query beginTimestamp;
+ d3d11::Query endTimestamp;
+ bool finished;
+ };
+
+ gl::Error flush(bool force);
+ gl::Error testQuery(QueryState *queryState);
template <typename T>
gl::Error getResultBase(T *params);
GLuint64 mResult;
-
- bool mQueryFinished;
+ GLuint64 mResultSum;
Renderer11 *mRenderer;
- ID3D11Query *mQuery;
- ID3D11Query *mTimestampBeginQuery;
- ID3D11Query *mTimestampEndQuery;
+
+ std::unique_ptr<QueryState> mActiveQuery;
+ std::deque<std::unique_ptr<QueryState>> mPendingQueries;
};
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp
index 2ee25cfb6c..5b85196c2e 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp
@@ -17,338 +17,180 @@
#include "libANGLE/renderer/d3d/FramebufferD3D.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
-#include "third_party/murmurhash/MurmurHash3.h"
namespace rx
{
using namespace gl_d3d11;
-template <typename mapType>
-static void ClearStateMap(mapType &map)
-{
- for (typename mapType::iterator i = map.begin(); i != map.end(); i++)
- {
- SafeRelease(i->second.first);
- }
- map.clear();
-}
-
-// MSDN's documentation of ID3D11Device::CreateBlendState, ID3D11Device::CreateRasterizerState,
-// ID3D11Device::CreateDepthStencilState and ID3D11Device::CreateSamplerState claims the maximum
-// number of unique states of each type an application can create is 4096
-const unsigned int RenderStateCache::kMaxBlendStates = 4096;
-const unsigned int RenderStateCache::kMaxRasterizerStates = 4096;
-const unsigned int RenderStateCache::kMaxDepthStencilStates = 4096;
-const unsigned int RenderStateCache::kMaxSamplerStates = 4096;
-
-RenderStateCache::RenderStateCache(Renderer11 *renderer)
- : mRenderer(renderer),
- mCounter(0),
- mBlendStateCache(kMaxBlendStates, hashBlendState, compareBlendStates),
- mRasterizerStateCache(kMaxRasterizerStates, hashRasterizerState, compareRasterizerStates),
- mDepthStencilStateCache(kMaxDepthStencilStates, hashDepthStencilState, compareDepthStencilStates),
- mSamplerStateCache(kMaxSamplerStates, hashSamplerState, compareSamplerStates),
- mDevice(NULL)
+RenderStateCache::RenderStateCache()
+ : mBlendStateCache(kMaxStates),
+ mRasterizerStateCache(kMaxStates),
+ mDepthStencilStateCache(kMaxStates),
+ mSamplerStateCache(kMaxStates)
{
}
RenderStateCache::~RenderStateCache()
{
- clear();
-}
-
-void RenderStateCache::initialize(ID3D11Device *device)
-{
- clear();
- mDevice = device;
}
void RenderStateCache::clear()
{
- ClearStateMap(mBlendStateCache);
- ClearStateMap(mRasterizerStateCache);
- ClearStateMap(mDepthStencilStateCache);
- ClearStateMap(mSamplerStateCache);
+ mBlendStateCache.Clear();
+ mRasterizerStateCache.Clear();
+ mDepthStencilStateCache.Clear();
+ mSamplerStateCache.Clear();
}
-std::size_t RenderStateCache::hashBlendState(const BlendStateKey &blendState)
+// static
+d3d11::BlendStateKey RenderStateCache::GetBlendStateKey(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::BlendState &blendState)
{
- static const unsigned int seed = 0xABCDEF98;
-
- std::size_t hash = 0;
- MurmurHash3_x86_32(&blendState, sizeof(gl::BlendState), seed, &hash);
- return hash;
-}
+ d3d11::BlendStateKey key;
+ FramebufferD3D *framebufferD3D = GetImplAs<FramebufferD3D>(framebuffer);
+ const gl::AttachmentList &colorbuffers = framebufferD3D->getColorAttachmentsForRender(context);
+ const UINT8 blendStateMask =
+ gl_d3d11::ConvertColorMask(blendState.colorMaskRed, blendState.colorMaskGreen,
+ blendState.colorMaskBlue, blendState.colorMaskAlpha);
-bool RenderStateCache::compareBlendStates(const BlendStateKey &a, const BlendStateKey &b)
-{
- return memcmp(&a, &b, sizeof(BlendStateKey)) == 0;
-}
-
-gl::Error RenderStateCache::getBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState,
- ID3D11BlendState **outBlendState)
-{
- if (!mDevice)
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized.");
- }
-
- bool mrt = false;
-
- const FramebufferD3D *framebufferD3D = GetImplAs<FramebufferD3D>(framebuffer);
- const gl::AttachmentList &colorbuffers = framebufferD3D->getColorAttachmentsForRender();
-
- BlendStateKey key = {};
key.blendState = blendState;
- for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
- {
- const gl::FramebufferAttachment *attachment = colorbuffers[colorAttachment];
- auto rtChannels = key.rtChannels[colorAttachment];
+ for (size_t i = 0; i < colorbuffers.size(); i++)
+ {
+ const gl::FramebufferAttachment *attachment = colorbuffers[i];
if (attachment)
{
- if (colorAttachment > 0)
- {
- mrt = true;
- }
-
- rtChannels[0] = attachment->getRedSize() > 0;
- rtChannels[1] = attachment->getGreenSize() > 0;
- rtChannels[2] = attachment->getBlueSize() > 0;
- rtChannels[3] = attachment->getAlphaSize() > 0;
+ key.rtvMax = static_cast<uint32_t>(i) + 1;
+ key.rtvMasks[i] =
+ (gl_d3d11::GetColorMask(*attachment->getFormat().info)) & blendStateMask;
}
}
- BlendStateMap::iterator keyIter = mBlendStateCache.find(key);
+ return key;
+}
+
+gl::Error RenderStateCache::getBlendState(Renderer11 *renderer,
+ const d3d11::BlendStateKey &key,
+ const d3d11::BlendState **outBlendState)
+{
+ auto keyIter = mBlendStateCache.Get(key);
if (keyIter != mBlendStateCache.end())
{
- BlendStateCounterPair &state = keyIter->second;
- state.second = mCounter++;
- *outBlendState = state.first;
- return gl::Error(GL_NO_ERROR);
+ *outBlendState = &keyIter->second;
+ return gl::NoError();
}
- else
- {
- if (mBlendStateCache.size() >= kMaxBlendStates)
- {
- TRACE("Overflowed the limit of %u blend states, removing the least recently used "
- "to make room.", kMaxBlendStates);
-
- BlendStateMap::iterator leastRecentlyUsed = mBlendStateCache.begin();
- for (BlendStateMap::iterator i = mBlendStateCache.begin(); i != mBlendStateCache.end(); i++)
- {
- if (i->second.second < leastRecentlyUsed->second.second)
- {
- leastRecentlyUsed = i;
- }
- }
- SafeRelease(leastRecentlyUsed->second.first);
- mBlendStateCache.erase(leastRecentlyUsed);
- }
- // Create a new blend state and insert it into the cache
- D3D11_BLEND_DESC blendDesc = { 0 };
- blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage;
- blendDesc.IndependentBlendEnable = mrt ? TRUE : FALSE;
+ TrimCache(kMaxStates, kGCLimit, "blend state", &mBlendStateCache);
- for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
- {
- D3D11_RENDER_TARGET_BLEND_DESC &rtBlend = blendDesc.RenderTarget[i];
-
- rtBlend.BlendEnable = blendState.blend;
- if (blendState.blend)
- {
- rtBlend.SrcBlend = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendRGB, false);
- rtBlend.DestBlend = gl_d3d11::ConvertBlendFunc(blendState.destBlendRGB, false);
- rtBlend.BlendOp = gl_d3d11::ConvertBlendOp(blendState.blendEquationRGB);
-
- rtBlend.SrcBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendAlpha, true);
- rtBlend.DestBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.destBlendAlpha, true);
- rtBlend.BlendOpAlpha = gl_d3d11::ConvertBlendOp(blendState.blendEquationAlpha);
- }
-
- rtBlend.RenderTargetWriteMask = gl_d3d11::ConvertColorMask(key.rtChannels[i][0] && blendState.colorMaskRed,
- key.rtChannels[i][1] && blendState.colorMaskGreen,
- key.rtChannels[i][2] && blendState.colorMaskBlue,
- key.rtChannels[i][3] && blendState.colorMaskAlpha);
- }
+ // Create a new blend state and insert it into the cache
+ D3D11_BLEND_DESC blendDesc;
+ D3D11_RENDER_TARGET_BLEND_DESC &rtDesc0 = blendDesc.RenderTarget[0];
+ const gl::BlendState &blendState = key.blendState;
- ID3D11BlendState *dx11BlendState = NULL;
- HRESULT result = mDevice->CreateBlendState(&blendDesc, &dx11BlendState);
- if (FAILED(result) || !dx11BlendState)
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result);
- }
+ blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage;
+ blendDesc.IndependentBlendEnable = key.rtvMax > 1 ? TRUE : FALSE;
- mBlendStateCache.insert(std::make_pair(key, std::make_pair(dx11BlendState, mCounter++)));
+ rtDesc0 = {};
- *outBlendState = dx11BlendState;
- return gl::Error(GL_NO_ERROR);
+ if (blendState.blend)
+ {
+ rtDesc0.BlendEnable = true;
+ rtDesc0.SrcBlend = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendRGB, false);
+ rtDesc0.DestBlend = gl_d3d11::ConvertBlendFunc(blendState.destBlendRGB, false);
+ rtDesc0.BlendOp = gl_d3d11::ConvertBlendOp(blendState.blendEquationRGB);
+ rtDesc0.SrcBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendAlpha, true);
+ rtDesc0.DestBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.destBlendAlpha, true);
+ rtDesc0.BlendOpAlpha = gl_d3d11::ConvertBlendOp(blendState.blendEquationAlpha);
}
-}
-std::size_t RenderStateCache::hashRasterizerState(const RasterizerStateKey &rasterState)
-{
- static const unsigned int seed = 0xABCDEF98;
+ rtDesc0.RenderTargetWriteMask = key.rtvMasks[0];
- std::size_t hash = 0;
- MurmurHash3_x86_32(&rasterState, sizeof(RasterizerStateKey), seed, &hash);
- return hash;
-}
+ for (unsigned int i = 1; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
+ {
+ blendDesc.RenderTarget[i] = rtDesc0;
+ blendDesc.RenderTarget[i].RenderTargetWriteMask = key.rtvMasks[i];
+ }
-bool RenderStateCache::compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b)
-{
- return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0;
+ d3d11::BlendState d3dBlendState;
+ ANGLE_TRY(renderer->allocateResource(blendDesc, &d3dBlendState));
+ const auto &iter = mBlendStateCache.Put(key, std::move(d3dBlendState));
+
+ *outBlendState = &iter->second;
+
+ return gl::NoError();
}
-gl::Error RenderStateCache::getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled,
+gl::Error RenderStateCache::getRasterizerState(Renderer11 *renderer,
+ const gl::RasterizerState &rasterState,
+ bool scissorEnabled,
ID3D11RasterizerState **outRasterizerState)
{
- if (!mDevice)
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized.");
- }
-
- RasterizerStateKey key = {};
+ d3d11::RasterizerStateKey key;
key.rasterizerState = rasterState;
- key.scissorEnabled = scissorEnabled;
+ key.scissorEnabled = scissorEnabled ? 1 : 0;
- RasterizerStateMap::iterator keyIter = mRasterizerStateCache.find(key);
+ auto keyIter = mRasterizerStateCache.Get(key);
if (keyIter != mRasterizerStateCache.end())
{
- RasterizerStateCounterPair &state = keyIter->second;
- state.second = mCounter++;
- *outRasterizerState = state.first;
- return gl::Error(GL_NO_ERROR);
+ *outRasterizerState = keyIter->second.get();
+ return gl::NoError();
}
- else
- {
- if (mRasterizerStateCache.size() >= kMaxRasterizerStates)
- {
- TRACE("Overflowed the limit of %u rasterizer states, removing the least recently used "
- "to make room.", kMaxRasterizerStates);
-
- RasterizerStateMap::iterator leastRecentlyUsed = mRasterizerStateCache.begin();
- for (RasterizerStateMap::iterator i = mRasterizerStateCache.begin(); i != mRasterizerStateCache.end(); i++)
- {
- if (i->second.second < leastRecentlyUsed->second.second)
- {
- leastRecentlyUsed = i;
- }
- }
- SafeRelease(leastRecentlyUsed->second.first);
- mRasterizerStateCache.erase(leastRecentlyUsed);
- }
- D3D11_CULL_MODE cullMode = gl_d3d11::ConvertCullMode(rasterState.cullFace, rasterState.cullMode);
+ TrimCache(kMaxStates, kGCLimit, "rasterizer state", &mRasterizerStateCache);
- // Disable culling if drawing points
- if (rasterState.pointDrawMode)
- {
- cullMode = D3D11_CULL_NONE;
- }
+ D3D11_CULL_MODE cullMode =
+ gl_d3d11::ConvertCullMode(rasterState.cullFace, rasterState.cullMode);
- D3D11_RASTERIZER_DESC rasterDesc;
- rasterDesc.FillMode = D3D11_FILL_SOLID;
- rasterDesc.CullMode = cullMode;
- rasterDesc.FrontCounterClockwise = (rasterState.frontFace == GL_CCW) ? FALSE: TRUE;
- rasterDesc.DepthBiasClamp = 0.0f; // MSDN documentation of DepthBiasClamp implies a value of zero will preform no clamping, must be tested though.
- rasterDesc.DepthClipEnable = TRUE;
- rasterDesc.ScissorEnable = scissorEnabled ? TRUE : FALSE;
- rasterDesc.MultisampleEnable = rasterState.multiSample;
- rasterDesc.AntialiasedLineEnable = FALSE;
-
- if (rasterState.polygonOffsetFill)
- {
- rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetFactor;
- rasterDesc.DepthBias = (INT)rasterState.polygonOffsetUnits;
- }
- else
- {
- rasterDesc.SlopeScaledDepthBias = 0.0f;
- rasterDesc.DepthBias = 0;
- }
-
- ID3D11RasterizerState *dx11RasterizerState = NULL;
- HRESULT result = mDevice->CreateRasterizerState(&rasterDesc, &dx11RasterizerState);
- if (FAILED(result) || !dx11RasterizerState)
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11RasterizerState, HRESULT: 0x%X.", result);
- }
-
- mRasterizerStateCache.insert(std::make_pair(key, std::make_pair(dx11RasterizerState, mCounter++)));
-
- *outRasterizerState = dx11RasterizerState;
- return gl::Error(GL_NO_ERROR);
- }
-}
-
-std::size_t RenderStateCache::hashDepthStencilState(const gl::DepthStencilState &dsState)
-{
- static const unsigned int seed = 0xABCDEF98;
-
- std::size_t hash = 0;
- MurmurHash3_x86_32(&dsState, sizeof(gl::DepthStencilState), seed, &hash);
- return hash;
-}
-
-bool RenderStateCache::compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b)
-{
- return memcmp(&a, &b, sizeof(gl::DepthStencilState)) == 0;
-}
-
-gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &originalState,
- bool disableDepth,
- bool disableStencil,
- ID3D11DepthStencilState **outDSState)
-{
- if (!mDevice)
+ // Disable culling if drawing points
+ if (rasterState.pointDrawMode)
{
- return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized.");
+ cullMode = D3D11_CULL_NONE;
}
- gl::DepthStencilState glState = originalState;
- if (disableDepth)
+ D3D11_RASTERIZER_DESC rasterDesc;
+ rasterDesc.FillMode = D3D11_FILL_SOLID;
+ rasterDesc.CullMode = cullMode;
+ rasterDesc.FrontCounterClockwise = (rasterState.frontFace == GL_CCW) ? FALSE : TRUE;
+ rasterDesc.DepthBiasClamp = 0.0f; // MSDN documentation of DepthBiasClamp implies a value of
+ // zero will preform no clamping, must be tested though.
+ rasterDesc.DepthClipEnable = TRUE;
+ rasterDesc.ScissorEnable = scissorEnabled ? TRUE : FALSE;
+ rasterDesc.MultisampleEnable = rasterState.multiSample;
+ rasterDesc.AntialiasedLineEnable = FALSE;
+
+ if (rasterState.polygonOffsetFill)
{
- glState.depthTest = false;
- glState.depthMask = false;
+ rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetFactor;
+ rasterDesc.DepthBias = (INT)rasterState.polygonOffsetUnits;
}
-
- if (disableStencil)
+ else
{
- glState.stencilWritemask = 0;
- glState.stencilBackWritemask = 0;
- glState.stencilTest = false;
+ rasterDesc.SlopeScaledDepthBias = 0.0f;
+ rasterDesc.DepthBias = 0;
}
- auto keyIter = mDepthStencilStateCache.find(glState);
+ d3d11::RasterizerState dx11RasterizerState;
+ ANGLE_TRY(renderer->allocateResource(rasterDesc, &dx11RasterizerState));
+ *outRasterizerState = dx11RasterizerState.get();
+ mRasterizerStateCache.Put(key, std::move(dx11RasterizerState));
+
+ return gl::NoError();
+}
+
+gl::Error RenderStateCache::getDepthStencilState(Renderer11 *renderer,
+ const gl::DepthStencilState &glState,
+ const d3d11::DepthStencilState **outDSState)
+{
+ auto keyIter = mDepthStencilStateCache.Get(glState);
if (keyIter != mDepthStencilStateCache.end())
{
- DepthStencilStateCounterPair &state = keyIter->second;
- state.second = mCounter++;
- *outDSState = state.first;
- return gl::Error(GL_NO_ERROR);
+ *outDSState = &keyIter->second;
+ return gl::NoError();
}
- if (mDepthStencilStateCache.size() >= kMaxDepthStencilStates)
- {
- TRACE(
- "Overflowed the limit of %u depth stencil states, removing the least recently used "
- "to make room.",
- kMaxDepthStencilStates);
-
- auto leastRecentlyUsed = mDepthStencilStateCache.begin();
- for (auto i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++)
- {
- if (i->second.second < leastRecentlyUsed->second.second)
- {
- leastRecentlyUsed = i;
- }
- }
- SafeRelease(leastRecentlyUsed->second.first);
- mDepthStencilStateCache.erase(leastRecentlyUsed);
- }
+ TrimCache(kMaxStates, kGCLimit, "depth stencil state", &mDepthStencilStateCache);
D3D11_DEPTH_STENCIL_DESC dsDesc = {0};
dsDesc.DepthEnable = glState.depthTest ? TRUE : FALSE;
@@ -366,107 +208,66 @@ gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &or
dsDesc.BackFace.StencilPassOp = ConvertStencilOp(glState.stencilBackPassDepthPass);
dsDesc.BackFace.StencilFunc = ConvertComparison(glState.stencilBackFunc);
- ID3D11DepthStencilState *dx11DepthStencilState = NULL;
- HRESULT result = mDevice->CreateDepthStencilState(&dsDesc, &dx11DepthStencilState);
- if (FAILED(result) || !dx11DepthStencilState)
- {
- return gl::Error(GL_OUT_OF_MEMORY,
- "Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result);
- }
+ d3d11::DepthStencilState dx11DepthStencilState;
+ ANGLE_TRY(renderer->allocateResource(dsDesc, &dx11DepthStencilState));
+ const auto &iter = mDepthStencilStateCache.Put(glState, std::move(dx11DepthStencilState));
- mDepthStencilStateCache.insert(
- std::make_pair(glState, std::make_pair(dx11DepthStencilState, mCounter++)));
+ *outDSState = &iter->second;
- *outDSState = dx11DepthStencilState;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-std::size_t RenderStateCache::hashSamplerState(const gl::SamplerState &samplerState)
+gl::Error RenderStateCache::getSamplerState(Renderer11 *renderer,
+ const gl::SamplerState &samplerState,
+ ID3D11SamplerState **outSamplerState)
{
- static const unsigned int seed = 0xABCDEF98;
-
- std::size_t hash = 0;
- MurmurHash3_x86_32(&samplerState, sizeof(gl::SamplerState), seed, &hash);
- return hash;
-}
-
-bool RenderStateCache::compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b)
-{
- return memcmp(&a, &b, sizeof(gl::SamplerState)) == 0;
-}
-
-gl::Error RenderStateCache::getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState)
-{
- if (!mDevice)
+ auto keyIter = mSamplerStateCache.Get(samplerState);
+ if (keyIter != mSamplerStateCache.end())
{
- return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized.");
+ *outSamplerState = keyIter->second.get();
+ return gl::NoError();
}
- SamplerStateMap::iterator keyIter = mSamplerStateCache.find(samplerState);
- if (keyIter != mSamplerStateCache.end())
+ TrimCache(kMaxStates, kGCLimit, "sampler state", &mSamplerStateCache);
+
+ const auto &featureLevel = renderer->getRenderer11DeviceCaps().featureLevel;
+
+ D3D11_SAMPLER_DESC samplerDesc;
+ samplerDesc.Filter =
+ gl_d3d11::ConvertFilter(samplerState.minFilter, samplerState.magFilter,
+ samplerState.maxAnisotropy, samplerState.compareMode);
+ samplerDesc.AddressU = gl_d3d11::ConvertTextureWrap(samplerState.wrapS);
+ samplerDesc.AddressV = gl_d3d11::ConvertTextureWrap(samplerState.wrapT);
+ samplerDesc.AddressW = gl_d3d11::ConvertTextureWrap(samplerState.wrapR);
+ samplerDesc.MipLODBias = 0;
+ samplerDesc.MaxAnisotropy =
+ gl_d3d11::ConvertMaxAnisotropy(samplerState.maxAnisotropy, featureLevel);
+ samplerDesc.ComparisonFunc = gl_d3d11::ConvertComparison(samplerState.compareFunc);
+ samplerDesc.BorderColor[0] = 0.0f;
+ samplerDesc.BorderColor[1] = 0.0f;
+ samplerDesc.BorderColor[2] = 0.0f;
+ samplerDesc.BorderColor[3] = 0.0f;
+ samplerDesc.MinLOD = samplerState.minLod;
+ samplerDesc.MaxLOD = samplerState.maxLod;
+
+ if (featureLevel <= D3D_FEATURE_LEVEL_9_3)
{
- SamplerStateCounterPair &state = keyIter->second;
- state.second = mCounter++;
- *outSamplerState = state.first;
- return gl::Error(GL_NO_ERROR);
+ // Check that maxLOD is nearly FLT_MAX (1000.0f is the default), since 9_3 doesn't support
+ // anything other than FLT_MAX. Note that Feature Level 9_* only supports GL ES 2.0, so the
+ // consumer of ANGLE can't modify the Max LOD themselves.
+ ASSERT(samplerState.maxLod >= 999.9f);
+
+ // Now just set MaxLOD to FLT_MAX. Other parts of the renderer (e.g. the non-zero max LOD
+ // workaround) should take account of this.
+ samplerDesc.MaxLOD = FLT_MAX;
}
- else
- {
- if (mSamplerStateCache.size() >= kMaxSamplerStates)
- {
- TRACE("Overflowed the limit of %u sampler states, removing the least recently used "
- "to make room.", kMaxSamplerStates);
-
- SamplerStateMap::iterator leastRecentlyUsed = mSamplerStateCache.begin();
- for (SamplerStateMap::iterator i = mSamplerStateCache.begin(); i != mSamplerStateCache.end(); i++)
- {
- if (i->second.second < leastRecentlyUsed->second.second)
- {
- leastRecentlyUsed = i;
- }
- }
- SafeRelease(leastRecentlyUsed->second.first);
- mSamplerStateCache.erase(leastRecentlyUsed);
- }
- D3D11_SAMPLER_DESC samplerDesc;
- samplerDesc.Filter = gl_d3d11::ConvertFilter(samplerState.minFilter, samplerState.magFilter,
- samplerState.maxAnisotropy, samplerState.compareMode);
- samplerDesc.AddressU = gl_d3d11::ConvertTextureWrap(samplerState.wrapS);
- samplerDesc.AddressV = gl_d3d11::ConvertTextureWrap(samplerState.wrapT);
- samplerDesc.AddressW = gl_d3d11::ConvertTextureWrap(samplerState.wrapR);
- samplerDesc.MipLODBias = 0;
- samplerDesc.MaxAnisotropy = static_cast<UINT>(samplerState.maxAnisotropy);
- samplerDesc.ComparisonFunc = gl_d3d11::ConvertComparison(samplerState.compareFunc);
- samplerDesc.BorderColor[0] = 0.0f;
- samplerDesc.BorderColor[1] = 0.0f;
- samplerDesc.BorderColor[2] = 0.0f;
- samplerDesc.BorderColor[3] = 0.0f;
- samplerDesc.MinLOD = samplerState.minLod;
- samplerDesc.MaxLOD = samplerState.maxLod;
-
- if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
- {
- // Check that maxLOD is nearly FLT_MAX (1000.0f is the default), since 9_3 doesn't support anything other than FLT_MAX.
- // Note that Feature Level 9_* only supports GL ES 2.0, so the consumer of ANGLE can't modify the Max LOD themselves.
- ASSERT(samplerState.maxLod >= 999.9f);
-
- // Now just set MaxLOD to FLT_MAX. Other parts of the renderer (e.g. the non-zero max LOD workaround) should take account of this.
- samplerDesc.MaxLOD = FLT_MAX;
- }
+ d3d11::SamplerState dx11SamplerState;
+ ANGLE_TRY(renderer->allocateResource(samplerDesc, &dx11SamplerState));
+ *outSamplerState = dx11SamplerState.get();
+ mSamplerStateCache.Put(samplerState, std::move(dx11SamplerState));
- ID3D11SamplerState *dx11SamplerState = NULL;
- HRESULT result = mDevice->CreateSamplerState(&samplerDesc, &dx11SamplerState);
- if (FAILED(result) || !dx11SamplerState)
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11SamplerState, HRESULT: 0x%X.", result);
- }
-
- mSamplerStateCache.insert(std::make_pair(samplerState, std::make_pair(dx11SamplerState, mCounter++)));
-
- *outSamplerState = dx11SamplerState;
- return gl::Error(GL_NO_ERROR);
- }
+ return gl::NoError();
}
-}
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h
index 82cb13903c..7501e83fc4 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h
@@ -10,9 +10,11 @@
#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_
#define LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_
-#include "libANGLE/angletypes.h"
-#include "libANGLE/Error.h"
#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/SizedMRUCache.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
#include <unordered_map>
@@ -21,6 +23,42 @@ namespace gl
class Framebuffer;
}
+namespace std
+{
+template <>
+struct hash<rx::d3d11::BlendStateKey>
+{
+ size_t operator()(const rx::d3d11::BlendStateKey &key) const
+ {
+ return angle::ComputeGenericHash(key);
+ }
+};
+
+template <>
+struct hash<rx::d3d11::RasterizerStateKey>
+{
+ size_t operator()(const rx::d3d11::RasterizerStateKey &key) const
+ {
+ return angle::ComputeGenericHash(key);
+ }
+};
+
+template <>
+struct hash<gl::DepthStencilState>
+{
+ size_t operator()(const gl::DepthStencilState &key) const
+ {
+ return angle::ComputeGenericHash(key);
+ }
+};
+
+template <>
+struct hash<gl::SamplerState>
+{
+ size_t operator()(const gl::SamplerState &key) const { return angle::ComputeGenericHash(key); }
+};
+} // namespace std
+
namespace rx
{
class Renderer11;
@@ -28,87 +66,58 @@ class Renderer11;
class RenderStateCache : angle::NonCopyable
{
public:
- RenderStateCache(Renderer11 *renderer);
+ RenderStateCache();
virtual ~RenderStateCache();
- void initialize(ID3D11Device *device);
void clear();
- gl::Error getBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, ID3D11BlendState **outBlendState);
- gl::Error getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled, ID3D11RasterizerState **outRasterizerState);
- gl::Error getDepthStencilState(const gl::DepthStencilState &dsState,
- bool disableDepth,
- bool disableStencil,
- ID3D11DepthStencilState **outDSState);
- gl::Error getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState);
+ static d3d11::BlendStateKey GetBlendStateKey(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::BlendState &blendState);
+ gl::Error getBlendState(Renderer11 *renderer,
+ const d3d11::BlendStateKey &key,
+ const d3d11::BlendState **outBlendState);
+ gl::Error getRasterizerState(Renderer11 *renderer,
+ const gl::RasterizerState &rasterState,
+ bool scissorEnabled,
+ ID3D11RasterizerState **outRasterizerState);
+ gl::Error getDepthStencilState(Renderer11 *renderer,
+ const gl::DepthStencilState &dsState,
+ const d3d11::DepthStencilState **outDSState);
+ gl::Error getSamplerState(Renderer11 *renderer,
+ const gl::SamplerState &samplerState,
+ ID3D11SamplerState **outSamplerState);
private:
- Renderer11 *mRenderer;
- unsigned long long mCounter;
+ // MSDN's documentation of ID3D11Device::CreateBlendState, ID3D11Device::CreateRasterizerState,
+ // ID3D11Device::CreateDepthStencilState and ID3D11Device::CreateSamplerState claims the maximum
+ // number of unique states of each type an application can create is 4096
+ // TODO(ShahmeerEsmail): Revisit the cache sizes to make sure they are appropriate for most
+ // scenarios.
+ static constexpr unsigned int kMaxStates = 4096;
+
+ // The cache tries to clean up this many states at once.
+ static constexpr unsigned int kGCLimit = 128;
// Blend state cache
- struct BlendStateKey
- {
- gl::BlendState blendState;
- bool rtChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4];
- };
- static std::size_t hashBlendState(const BlendStateKey &blendState);
- static bool compareBlendStates(const BlendStateKey &a, const BlendStateKey &b);
- static const unsigned int kMaxBlendStates;
-
- typedef std::size_t (*BlendStateHashFunction)(const BlendStateKey &);
- typedef bool (*BlendStateEqualityFunction)(const BlendStateKey &, const BlendStateKey &);
- typedef std::pair<ID3D11BlendState*, unsigned long long> BlendStateCounterPair;
- typedef std::unordered_map<BlendStateKey, BlendStateCounterPair, BlendStateHashFunction, BlendStateEqualityFunction> BlendStateMap;
+ using BlendStateMap = angle::base::HashingMRUCache<d3d11::BlendStateKey, d3d11::BlendState>;
BlendStateMap mBlendStateCache;
// Rasterizer state cache
- struct RasterizerStateKey
- {
- gl::RasterizerState rasterizerState;
- bool scissorEnabled;
- };
- static std::size_t hashRasterizerState(const RasterizerStateKey &rasterState);
- static bool compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b);
- static const unsigned int kMaxRasterizerStates;
-
- typedef std::size_t (*RasterizerStateHashFunction)(const RasterizerStateKey &);
- typedef bool (*RasterizerStateEqualityFunction)(const RasterizerStateKey &, const RasterizerStateKey &);
- typedef std::pair<ID3D11RasterizerState*, unsigned long long> RasterizerStateCounterPair;
- typedef std::unordered_map<RasterizerStateKey, RasterizerStateCounterPair, RasterizerStateHashFunction, RasterizerStateEqualityFunction> RasterizerStateMap;
+ using RasterizerStateMap =
+ angle::base::HashingMRUCache<d3d11::RasterizerStateKey, d3d11::RasterizerState>;
RasterizerStateMap mRasterizerStateCache;
// Depth stencil state cache
- static std::size_t hashDepthStencilState(const gl::DepthStencilState &dsState);
- static bool compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b);
- static const unsigned int kMaxDepthStencilStates;
-
- typedef std::size_t (*DepthStencilStateHashFunction)(const gl::DepthStencilState &);
- typedef bool (*DepthStencilStateEqualityFunction)(const gl::DepthStencilState &, const gl::DepthStencilState &);
- typedef std::pair<ID3D11DepthStencilState*, unsigned long long> DepthStencilStateCounterPair;
- typedef std::unordered_map<gl::DepthStencilState,
- DepthStencilStateCounterPair,
- DepthStencilStateHashFunction,
- DepthStencilStateEqualityFunction> DepthStencilStateMap;
+ using DepthStencilStateMap =
+ angle::base::HashingMRUCache<gl::DepthStencilState, d3d11::DepthStencilState>;
DepthStencilStateMap mDepthStencilStateCache;
// Sample state cache
- static std::size_t hashSamplerState(const gl::SamplerState &samplerState);
- static bool compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b);
- static const unsigned int kMaxSamplerStates;
-
- typedef std::size_t (*SamplerStateHashFunction)(const gl::SamplerState &);
- typedef bool (*SamplerStateEqualityFunction)(const gl::SamplerState &, const gl::SamplerState &);
- typedef std::pair<ID3D11SamplerState*, unsigned long long> SamplerStateCounterPair;
- typedef std::unordered_map<gl::SamplerState,
- SamplerStateCounterPair,
- SamplerStateHashFunction,
- SamplerStateEqualityFunction> SamplerStateMap;
+ using SamplerStateMap = angle::base::HashingMRUCache<gl::SamplerState, d3d11::SamplerState>;
SamplerStateMap mSamplerStateCache;
-
- ID3D11Device *mDevice;
};
-}
+} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp
index cdfcacc287..594a382a72 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp
@@ -18,7 +18,9 @@
namespace rx
{
-static bool getTextureProperties(ID3D11Resource *resource, unsigned int *mipLevels, unsigned int *samples)
+namespace
+{
+bool GetTextureProperties(ID3D11Resource *resource, unsigned int *mipLevels, unsigned int *samples)
{
ID3D11Texture1D *texture1D = d3d11::DynamicCastComObject<ID3D11Texture1D>(resource);
if (texture1D)
@@ -62,7 +64,7 @@ static bool getTextureProperties(ID3D11Resource *resource, unsigned int *mipLeve
return false;
}
-static unsigned int getRTVSubresourceIndex(ID3D11Resource *resource, ID3D11RenderTargetView *view)
+unsigned int GetRTVSubresourceIndex(ID3D11Resource *resource, ID3D11RenderTargetView *view)
{
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
view->GetDesc(&rtvDesc);
@@ -72,58 +74,58 @@ static unsigned int getRTVSubresourceIndex(ID3D11Resource *resource, ID3D11Rende
switch (rtvDesc.ViewDimension)
{
- case D3D11_RTV_DIMENSION_TEXTURE1D:
- mipSlice = rtvDesc.Texture1D.MipSlice;
- arraySlice = 0;
- break;
-
- case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
- mipSlice = rtvDesc.Texture1DArray.MipSlice;
- arraySlice = rtvDesc.Texture1DArray.FirstArraySlice;
- break;
-
- case D3D11_RTV_DIMENSION_TEXTURE2D:
- mipSlice = rtvDesc.Texture2D.MipSlice;
- arraySlice = 0;
- break;
-
- case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
- mipSlice = rtvDesc.Texture2DArray.MipSlice;
- arraySlice = rtvDesc.Texture2DArray.FirstArraySlice;
- break;
-
- case D3D11_RTV_DIMENSION_TEXTURE2DMS:
- mipSlice = 0;
- arraySlice = 0;
- break;
-
- case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
- mipSlice = 0;
- arraySlice = rtvDesc.Texture2DMSArray.FirstArraySlice;
- break;
-
- case D3D11_RTV_DIMENSION_TEXTURE3D:
- mipSlice = rtvDesc.Texture3D.MipSlice;
- arraySlice = 0;
- break;
-
- case D3D11_RTV_DIMENSION_UNKNOWN:
- case D3D11_RTV_DIMENSION_BUFFER:
- UNIMPLEMENTED();
- break;
-
- default:
- UNREACHABLE();
- break;
+ case D3D11_RTV_DIMENSION_TEXTURE1D:
+ mipSlice = rtvDesc.Texture1D.MipSlice;
+ arraySlice = 0;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
+ mipSlice = rtvDesc.Texture1DArray.MipSlice;
+ arraySlice = rtvDesc.Texture1DArray.FirstArraySlice;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2D:
+ mipSlice = rtvDesc.Texture2D.MipSlice;
+ arraySlice = 0;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
+ mipSlice = rtvDesc.Texture2DArray.MipSlice;
+ arraySlice = rtvDesc.Texture2DArray.FirstArraySlice;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2DMS:
+ mipSlice = 0;
+ arraySlice = 0;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
+ mipSlice = 0;
+ arraySlice = rtvDesc.Texture2DMSArray.FirstArraySlice;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE3D:
+ mipSlice = rtvDesc.Texture3D.MipSlice;
+ arraySlice = 0;
+ break;
+
+ case D3D11_RTV_DIMENSION_UNKNOWN:
+ case D3D11_RTV_DIMENSION_BUFFER:
+ UNIMPLEMENTED();
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
}
unsigned int mipLevels, samples;
- getTextureProperties(resource, &mipLevels, &samples);
+ GetTextureProperties(resource, &mipLevels, &samples);
return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels);
}
-static unsigned int getDSVSubresourceIndex(ID3D11Resource *resource, ID3D11DepthStencilView *view)
+unsigned int GetDSVSubresourceIndex(ID3D11Resource *resource, ID3D11DepthStencilView *view)
{
D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
view->GetDesc(&dsvDesc);
@@ -133,157 +135,170 @@ static unsigned int getDSVSubresourceIndex(ID3D11Resource *resource, ID3D11Depth
switch (dsvDesc.ViewDimension)
{
- case D3D11_DSV_DIMENSION_TEXTURE1D:
- mipSlice = dsvDesc.Texture1D.MipSlice;
- arraySlice = 0;
- break;
-
- case D3D11_DSV_DIMENSION_TEXTURE1DARRAY:
- mipSlice = dsvDesc.Texture1DArray.MipSlice;
- arraySlice = dsvDesc.Texture1DArray.FirstArraySlice;
- break;
-
- case D3D11_DSV_DIMENSION_TEXTURE2D:
- mipSlice = dsvDesc.Texture2D.MipSlice;
- arraySlice = 0;
- break;
-
- case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
- mipSlice = dsvDesc.Texture2DArray.MipSlice;
- arraySlice = dsvDesc.Texture2DArray.FirstArraySlice;
- break;
-
- case D3D11_DSV_DIMENSION_TEXTURE2DMS:
- mipSlice = 0;
- arraySlice = 0;
- break;
-
- case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY:
- mipSlice = 0;
- arraySlice = dsvDesc.Texture2DMSArray.FirstArraySlice;
- break;
-
- case D3D11_DSV_DIMENSION_UNKNOWN:
- UNIMPLEMENTED();
- break;
-
- default:
- UNREACHABLE();
- break;
+ case D3D11_DSV_DIMENSION_TEXTURE1D:
+ mipSlice = dsvDesc.Texture1D.MipSlice;
+ arraySlice = 0;
+ break;
+
+ case D3D11_DSV_DIMENSION_TEXTURE1DARRAY:
+ mipSlice = dsvDesc.Texture1DArray.MipSlice;
+ arraySlice = dsvDesc.Texture1DArray.FirstArraySlice;
+ break;
+
+ case D3D11_DSV_DIMENSION_TEXTURE2D:
+ mipSlice = dsvDesc.Texture2D.MipSlice;
+ arraySlice = 0;
+ break;
+
+ case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
+ mipSlice = dsvDesc.Texture2DArray.MipSlice;
+ arraySlice = dsvDesc.Texture2DArray.FirstArraySlice;
+ break;
+
+ case D3D11_DSV_DIMENSION_TEXTURE2DMS:
+ mipSlice = 0;
+ arraySlice = 0;
+ break;
+
+ case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY:
+ mipSlice = 0;
+ arraySlice = dsvDesc.Texture2DMSArray.FirstArraySlice;
+ break;
+
+ case D3D11_DSV_DIMENSION_UNKNOWN:
+ UNIMPLEMENTED();
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
}
unsigned int mipLevels, samples;
- getTextureProperties(resource, &mipLevels, &samples);
+ GetTextureProperties(resource, &mipLevels, &samples);
return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels);
}
-TextureRenderTarget11::TextureRenderTarget11(ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv,
- GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples)
- : mWidth(width),
+GLenum GetSurfaceRTFormat(bool depth, SwapChain11 *swapChain)
+{
+ return (depth ? swapChain->getDepthBufferInternalFormat()
+ : swapChain->getRenderTargetInternalFormat());
+}
+
+const d3d11::Format &GetSurfaceFormatSet(bool depth, SwapChain11 *swapChain, Renderer11 *renderer)
+{
+ return d3d11::Format::Get(GetSurfaceRTFormat(depth, swapChain),
+ renderer->getRenderer11DeviceCaps());
+}
+
+} // anonymous namespace
+
+RenderTarget11::RenderTarget11(const d3d11::Format &formatSet) : mFormatSet(formatSet)
+{
+}
+
+RenderTarget11::~RenderTarget11()
+{
+ ASSERT(mBroadcastChannel.empty());
+}
+
+void RenderTarget11::signalDirty(const gl::Context *context)
+{
+ mBroadcastChannel.signal(context);
+
+ // Clear the list. We can't do this in the receiver because it would mutate during iteration.
+ mBroadcastChannel.reset();
+}
+
+TextureRenderTarget11::TextureRenderTarget11(d3d11::RenderTargetView &&rtv,
+ const TextureHelper11 &resource,
+ const d3d11::SharedSRV &srv,
+ const d3d11::SharedSRV &blitSRV,
+ GLenum internalFormat,
+ const d3d11::Format &formatSet,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLsizei samples)
+ : RenderTarget11(formatSet),
+ mWidth(width),
mHeight(height),
mDepth(depth),
mInternalFormat(internalFormat),
- mDXGIFormat(DXGI_FORMAT_UNKNOWN),
mSamples(samples),
mSubresourceIndex(0),
mTexture(resource),
- mRenderTarget(rtv),
- mDepthStencil(NULL),
- mShaderResource(srv)
+ mRenderTarget(std::move(rtv)),
+ mDepthStencil(),
+ mShaderResource(srv.makeCopy()),
+ mBlitShaderResource(blitSRV.makeCopy())
{
- if (mTexture)
- {
- mTexture->AddRef();
- }
-
- if (mRenderTarget)
- {
- mRenderTarget->AddRef();
- }
-
- if (mShaderResource)
- {
- mShaderResource->AddRef();
- }
-
- if (mRenderTarget && mTexture)
+ if (mRenderTarget.valid() && mTexture.valid())
{
- mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget);
-
- D3D11_RENDER_TARGET_VIEW_DESC desc;
- mRenderTarget->GetDesc(&desc);
- mDXGIFormat = desc.Format;
+ mSubresourceIndex = GetRTVSubresourceIndex(mTexture.get(), mRenderTarget.get());
}
+ ASSERT(mFormatSet.formatID != angle::Format::ID::NONE || mWidth == 0 || mHeight == 0);
}
-TextureRenderTarget11::TextureRenderTarget11(ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv,
- GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples)
- : mWidth(width),
+TextureRenderTarget11::TextureRenderTarget11(d3d11::DepthStencilView &&dsv,
+ const TextureHelper11 &resource,
+ const d3d11::SharedSRV &srv,
+ GLenum internalFormat,
+ const d3d11::Format &formatSet,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLsizei samples)
+ : RenderTarget11(formatSet),
+ mWidth(width),
mHeight(height),
mDepth(depth),
mInternalFormat(internalFormat),
- mDXGIFormat(DXGI_FORMAT_UNKNOWN),
mSamples(samples),
mSubresourceIndex(0),
mTexture(resource),
- mRenderTarget(NULL),
- mDepthStencil(dsv),
- mShaderResource(srv)
+ mRenderTarget(),
+ mDepthStencil(std::move(dsv)),
+ mShaderResource(srv.makeCopy()),
+ mBlitShaderResource()
{
- if (mTexture)
+ if (mDepthStencil.valid() && mTexture.valid())
{
- mTexture->AddRef();
- }
-
- if (mDepthStencil)
- {
- mDepthStencil->AddRef();
- }
-
- if (mShaderResource)
- {
- mShaderResource->AddRef();
- }
-
- if (mDepthStencil && mTexture)
- {
- mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil);
-
- D3D11_DEPTH_STENCIL_VIEW_DESC desc;
- mDepthStencil->GetDesc(&desc);
- mDXGIFormat = desc.Format;
+ mSubresourceIndex = GetDSVSubresourceIndex(mTexture.get(), mDepthStencil.get());
}
+ ASSERT(mFormatSet.formatID != angle::Format::ID::NONE || mWidth == 0 || mHeight == 0);
}
TextureRenderTarget11::~TextureRenderTarget11()
{
- SafeRelease(mTexture);
- SafeRelease(mRenderTarget);
- SafeRelease(mDepthStencil);
- SafeRelease(mShaderResource);
}
-ID3D11Resource *TextureRenderTarget11::getTexture() const
+const TextureHelper11 &TextureRenderTarget11::getTexture() const
{
return mTexture;
}
-ID3D11RenderTargetView *TextureRenderTarget11::getRenderTargetView() const
+const d3d11::RenderTargetView &TextureRenderTarget11::getRenderTargetView() const
{
return mRenderTarget;
}
-ID3D11DepthStencilView *TextureRenderTarget11::getDepthStencilView() const
+const d3d11::DepthStencilView &TextureRenderTarget11::getDepthStencilView() const
{
return mDepthStencil;
}
-ID3D11ShaderResourceView *TextureRenderTarget11::getShaderResourceView() const
+const d3d11::SharedSRV &TextureRenderTarget11::getShaderResourceView() const
{
return mShaderResource;
}
+const d3d11::SharedSRV &TextureRenderTarget11::getBlitShaderResourceView() const
+{
+ return mBlitShaderResource;
+}
+
GLsizei TextureRenderTarget11::getWidth() const
{
return mWidth;
@@ -314,14 +329,11 @@ unsigned int TextureRenderTarget11::getSubresourceIndex() const
return mSubresourceIndex;
}
-DXGI_FORMAT TextureRenderTarget11::getDXGIFormat() const
-{
- return mDXGIFormat;
-}
-
-SurfaceRenderTarget11::SurfaceRenderTarget11(SwapChain11 *swapChain, Renderer11 *renderer, bool depth)
- : mSwapChain(swapChain),
- mRenderer(renderer),
+SurfaceRenderTarget11::SurfaceRenderTarget11(SwapChain11 *swapChain,
+ Renderer11 *renderer,
+ bool depth)
+ : RenderTarget11(GetSurfaceFormatSet(depth, swapChain, renderer)),
+ mSwapChain(swapChain),
mDepth(depth)
{
ASSERT(mSwapChain);
@@ -348,43 +360,46 @@ GLsizei SurfaceRenderTarget11::getDepth() const
GLenum SurfaceRenderTarget11::getInternalFormat() const
{
- return (mDepth ? mSwapChain->GetDepthBufferInternalFormat() : mSwapChain->GetRenderTargetInternalFormat());
+ return GetSurfaceRTFormat(mDepth, mSwapChain);
}
GLsizei SurfaceRenderTarget11::getSamples() const
{
- // Our EGL surfaces do not support multisampling.
- return 0;
+ return mSwapChain->getSamples();
}
-ID3D11Resource *SurfaceRenderTarget11::getTexture() const
+const TextureHelper11 &SurfaceRenderTarget11::getTexture() const
{
return (mDepth ? mSwapChain->getDepthStencilTexture() : mSwapChain->getOffscreenTexture());
}
-ID3D11RenderTargetView *SurfaceRenderTarget11::getRenderTargetView() const
+const d3d11::RenderTargetView &SurfaceRenderTarget11::getRenderTargetView() const
{
- return (mDepth ? NULL : mSwapChain->getRenderTarget());
+ ASSERT(!mDepth);
+ return mSwapChain->getRenderTarget();
}
-ID3D11DepthStencilView *SurfaceRenderTarget11::getDepthStencilView() const
+const d3d11::DepthStencilView &SurfaceRenderTarget11::getDepthStencilView() const
{
- return (mDepth ? mSwapChain->getDepthStencil() : NULL);
+ ASSERT(mDepth);
+ return mSwapChain->getDepthStencil();
}
-ID3D11ShaderResourceView *SurfaceRenderTarget11::getShaderResourceView() const
+const d3d11::SharedSRV &SurfaceRenderTarget11::getShaderResourceView() const
{
- return (mDepth ? mSwapChain->getDepthStencilShaderResource() : mSwapChain->getRenderTargetShaderResource());
+ return (mDepth ? mSwapChain->getDepthStencilShaderResource()
+ : mSwapChain->getRenderTargetShaderResource());
}
-unsigned int SurfaceRenderTarget11::getSubresourceIndex() const
+const d3d11::SharedSRV &SurfaceRenderTarget11::getBlitShaderResourceView() const
{
- return 0;
+ // The SurfaceRenderTargetView format should always be such that the normal SRV works for blits.
+ return getShaderResourceView();
}
-DXGI_FORMAT SurfaceRenderTarget11::getDXGIFormat() const
+unsigned int SurfaceRenderTarget11::getSubresourceIndex() const
{
- return d3d11::GetTextureFormatInfo(getInternalFormat(), mRenderer->getRenderer11DeviceCaps()).texFormat;
+ return 0;
}
-}
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h
index d47b237c09..db49cac9f5 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h
@@ -11,6 +11,9 @@
#define LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_
#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
namespace rx
{
@@ -20,28 +23,51 @@ class Renderer11;
class RenderTarget11 : public RenderTargetD3D
{
public:
- RenderTarget11() { }
- virtual ~RenderTarget11() { }
+ RenderTarget11(const d3d11::Format &formatSet);
+ ~RenderTarget11() override;
- virtual ID3D11Resource *getTexture() const = 0;
- virtual ID3D11RenderTargetView *getRenderTargetView() const = 0;
- virtual ID3D11DepthStencilView *getDepthStencilView() const = 0;
- virtual ID3D11ShaderResourceView *getShaderResourceView() const = 0;
+ virtual const TextureHelper11 &getTexture() const = 0;
+ virtual const d3d11::RenderTargetView &getRenderTargetView() const = 0;
+ virtual const d3d11::DepthStencilView &getDepthStencilView() const = 0;
+ virtual const d3d11::SharedSRV &getShaderResourceView() const = 0;
+ virtual const d3d11::SharedSRV &getBlitShaderResourceView() const = 0;
virtual unsigned int getSubresourceIndex() const = 0;
- virtual DXGI_FORMAT getDXGIFormat() const = 0;
+ void signalDirty(const gl::Context *context) override;
+ OnRenderTargetDirtyChannel *getBroadcastChannel() { return &mBroadcastChannel; }
+
+ const d3d11::Format &getFormatSet() const { return mFormatSet; }
+
+ protected:
+ OnRenderTargetDirtyChannel mBroadcastChannel;
+ const d3d11::Format &mFormatSet;
};
class TextureRenderTarget11 : public RenderTarget11
{
public:
// TextureRenderTarget11 takes ownership of any D3D11 resources it is given and will AddRef them
- TextureRenderTarget11(ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv,
- GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples);
- TextureRenderTarget11(ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv,
- GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples);
- virtual ~TextureRenderTarget11();
+ TextureRenderTarget11(d3d11::RenderTargetView &&rtv,
+ const TextureHelper11 &resource,
+ const d3d11::SharedSRV &srv,
+ const d3d11::SharedSRV &blitSRV,
+ GLenum internalFormat,
+ const d3d11::Format &formatSet,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLsizei samples);
+ TextureRenderTarget11(d3d11::DepthStencilView &&dsv,
+ const TextureHelper11 &resource,
+ const d3d11::SharedSRV &srv,
+ GLenum internalFormat,
+ const d3d11::Format &formatSet,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLsizei samples);
+ ~TextureRenderTarget11() override;
GLsizei getWidth() const override;
GLsizei getHeight() const override;
@@ -49,35 +75,37 @@ class TextureRenderTarget11 : public RenderTarget11
GLenum getInternalFormat() const override;
GLsizei getSamples() const override;
- ID3D11Resource *getTexture() const override;
- ID3D11RenderTargetView *getRenderTargetView() const override;
- ID3D11DepthStencilView *getDepthStencilView() const override;
- ID3D11ShaderResourceView *getShaderResourceView() const override;
+ const TextureHelper11 &getTexture() const override;
+ const d3d11::RenderTargetView &getRenderTargetView() const override;
+ const d3d11::DepthStencilView &getDepthStencilView() const override;
+ const d3d11::SharedSRV &getShaderResourceView() const override;
+ const d3d11::SharedSRV &getBlitShaderResourceView() const override;
unsigned int getSubresourceIndex() const override;
- DXGI_FORMAT getDXGIFormat() const override;
-
private:
GLsizei mWidth;
GLsizei mHeight;
GLsizei mDepth;
GLenum mInternalFormat;
- DXGI_FORMAT mDXGIFormat;
GLsizei mSamples;
unsigned int mSubresourceIndex;
- ID3D11Resource *mTexture;
- ID3D11RenderTargetView *mRenderTarget;
- ID3D11DepthStencilView *mDepthStencil;
- ID3D11ShaderResourceView *mShaderResource;
+ TextureHelper11 mTexture;
+ d3d11::RenderTargetView mRenderTarget;
+ d3d11::DepthStencilView mDepthStencil;
+ d3d11::SharedSRV mShaderResource;
+
+ // Shader resource view to use with internal blit shaders. Not set for depth/stencil render
+ // targets.
+ d3d11::SharedSRV mBlitShaderResource;
};
class SurfaceRenderTarget11 : public RenderTarget11
{
public:
SurfaceRenderTarget11(SwapChain11 *swapChain, Renderer11 *renderer, bool depth);
- virtual ~SurfaceRenderTarget11();
+ ~SurfaceRenderTarget11() override;
GLsizei getWidth() const override;
GLsizei getHeight() const override;
@@ -85,21 +113,19 @@ class SurfaceRenderTarget11 : public RenderTarget11
GLenum getInternalFormat() const override;
GLsizei getSamples() const override;
- ID3D11Resource *getTexture() const override;
- ID3D11RenderTargetView *getRenderTargetView() const override;
- ID3D11DepthStencilView *getDepthStencilView() const override;
- ID3D11ShaderResourceView *getShaderResourceView() const override;
+ const TextureHelper11 &getTexture() const override;
+ const d3d11::RenderTargetView &getRenderTargetView() const override;
+ const d3d11::DepthStencilView &getDepthStencilView() const override;
+ const d3d11::SharedSRV &getShaderResourceView() const override;
+ const d3d11::SharedSRV &getBlitShaderResourceView() const override;
unsigned int getSubresourceIndex() const override;
- DXGI_FORMAT getDXGIFormat() const override;
-
private:
SwapChain11 *mSwapChain;
- Renderer11 *mRenderer;
bool mDepth;
};
-}
+} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
index 5118bdbe9c..b0ef9abddc 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
@@ -9,56 +9,64 @@
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include <EGL/eglext.h>
+#include <versionhelpers.h>
#include <sstream>
-#if !defined(ANGLE_MINGW32_COMPAT) && WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
-#include <VersionHelpers.h>
-#endif
#include "common/tls.h"
#include "common/utilities.h"
#include "libANGLE/Buffer.h"
+#include "libANGLE/Context.h"
#include "libANGLE/Display.h"
-#include "libANGLE/formatutils.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/FramebufferAttachment.h"
-#include "libANGLE/histogram_macros.h"
#include "libANGLE/Program.h"
+#include "libANGLE/State.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/histogram_macros.h"
#include "libANGLE/renderer/d3d/CompilerD3D.h"
+#include "libANGLE/renderer/d3d/DeviceD3D.h"
+#include "libANGLE/renderer/d3d/DisplayD3D.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
#include "libANGLE/renderer/d3d/d3d11/Blit11.h"
#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
#include "libANGLE/renderer/d3d/d3d11/Clear11.h"
-#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
#include "libANGLE/renderer/d3d/d3d11/Fence11.h"
-#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
#include "libANGLE/renderer/d3d/d3d11/Image11.h"
#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
#include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h"
#include "libANGLE/renderer/d3d/d3d11/Query11.h"
-#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
+#include "libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h"
#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
-#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
+#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
#include "libANGLE/renderer/d3d/d3d11/Trim11.h"
#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
-#include "libANGLE/renderer/d3d/CompilerD3D.h"
-#include "libANGLE/renderer/d3d/DeviceD3D.h"
-#include "libANGLE/renderer/d3d/FramebufferD3D.h"
-#include "libANGLE/renderer/d3d/IndexDataManager.h"
-#include "libANGLE/renderer/d3d/ProgramD3D.h"
-#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
-#include "libANGLE/renderer/d3d/ShaderD3D.h"
-#include "libANGLE/renderer/d3d/SurfaceD3D.h"
-#include "libANGLE/renderer/d3d/TextureD3D.h"
-#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h"
-#include "libANGLE/renderer/d3d/VertexDataManager.h"
-#include "libANGLE/State.h"
-#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "libANGLE/renderer/renderer_utils.h"
#include "third_party/trace_event/trace_event.h"
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+#include "libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h"
+#else
+#include "libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h"
+#endif
+
// Include the D3D9 debug annotator header for use by the desktop D3D11 renderer
// because the D3D11 interface method ID3DUserDefinedAnnotation::GetStatus
// doesn't work with the Graphics Diagnostics tools in Visual Studio 2013.
@@ -72,12 +80,6 @@
#define ANGLE_SKIP_DXGI_1_2_CHECK 0
#endif
-#ifdef _DEBUG
-// this flag enables suppressing some spurious warnings that pop up in certain WebGL samples
-// and conformance tests. to enable all warnings, remove this define.
-#define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1
-#endif
-
namespace rx
{
@@ -89,25 +91,6 @@ enum
MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16
};
-#if defined(ANGLE_ENABLE_D3D11_1)
-void CalculateConstantBufferParams(GLintptr offset, GLsizeiptr size, UINT *outFirstConstant, UINT *outNumConstants)
-{
- // The offset must be aligned to 256 bytes (should have been enforced by glBindBufferRange).
- ASSERT(offset % 256 == 0);
-
- // firstConstant and numConstants are expressed in constants of 16-bytes. Furthermore they must be a multiple of 16 constants.
- *outFirstConstant = static_cast<UINT>(offset / 16);
-
- // The GL size is not required to be aligned to a 256 bytes boundary.
- // Round the size up to a 256 bytes boundary then express the results in constants of 16-bytes.
- *outNumConstants = static_cast<UINT>(rx::roundUp(size, static_cast<GLsizeiptr>(256)) / 16);
-
- // Since the size is rounded up, firstConstant + numConstants may be bigger than the actual size of the buffer.
- // This behaviour is explictly allowed according to the documentation on ID3D11DeviceContext1::PSSetConstantBuffers1
- // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx
-}
-#endif
-
enum ANGLEFeatureLevel
{
ANGLE_FEATURE_LEVEL_INVALID,
@@ -123,14 +106,18 @@ ANGLEFeatureLevel GetANGLEFeatureLevel(D3D_FEATURE_LEVEL d3dFeatureLevel)
{
switch (d3dFeatureLevel)
{
- case D3D_FEATURE_LEVEL_9_3: return ANGLE_FEATURE_LEVEL_9_3;
- case D3D_FEATURE_LEVEL_10_0: return ANGLE_FEATURE_LEVEL_10_0;
- case D3D_FEATURE_LEVEL_10_1: return ANGLE_FEATURE_LEVEL_10_1;
- case D3D_FEATURE_LEVEL_11_0: return ANGLE_FEATURE_LEVEL_11_0;
- // Note: we don't ever request a 11_1 device, because this gives
- // an E_INVALIDARG error on systems that don't have the platform update.
- case D3D_FEATURE_LEVEL_11_1: return ANGLE_FEATURE_LEVEL_11_1;
- default: return ANGLE_FEATURE_LEVEL_INVALID;
+ case D3D_FEATURE_LEVEL_9_3:
+ return ANGLE_FEATURE_LEVEL_9_3;
+ case D3D_FEATURE_LEVEL_10_0:
+ return ANGLE_FEATURE_LEVEL_10_0;
+ case D3D_FEATURE_LEVEL_10_1:
+ return ANGLE_FEATURE_LEVEL_10_1;
+ case D3D_FEATURE_LEVEL_11_0:
+ return ANGLE_FEATURE_LEVEL_11_0;
+ case D3D_FEATURE_LEVEL_11_1:
+ return ANGLE_FEATURE_LEVEL_11_1;
+ default:
+ return ANGLE_FEATURE_LEVEL_INVALID;
}
}
@@ -144,7 +131,7 @@ void SetLineLoopIndices(GLuint *dest, size_t count)
}
template <typename T>
-void CopyLineLoopIndices(const GLvoid *indices, GLuint *dest, size_t count)
+void CopyLineLoopIndices(const void *indices, GLuint *dest, size_t count)
{
const T *srcPtr = static_cast<const T *>(indices);
for (size_t i = 0; i < count; ++i)
@@ -165,7 +152,7 @@ void SetTriangleFanIndices(GLuint *destPtr, size_t numTris)
}
template <typename T>
-void CopyLineLoopIndicesWithRestart(const GLvoid *indices,
+void CopyLineLoopIndicesWithRestart(const void *indices,
size_t count,
GLenum indexType,
std::vector<GLuint> *bufferOut)
@@ -206,7 +193,7 @@ void CopyLineLoopIndicesWithRestart(const GLvoid *indices,
}
}
-void GetLineLoopIndices(const GLvoid *indices,
+void GetLineLoopIndices(const void *indices,
GLenum indexType,
GLuint count,
bool usePrimitiveRestartFixedIndex,
@@ -257,7 +244,7 @@ void GetLineLoopIndices(const GLvoid *indices,
}
template <typename T>
-void CopyTriangleFanIndices(const GLvoid *indices, GLuint *destPtr, size_t numTris)
+void CopyTriangleFanIndices(const void *indices, GLuint *destPtr, size_t numTris)
{
const T *srcPtr = static_cast<const T *>(indices);
@@ -270,7 +257,7 @@ void CopyTriangleFanIndices(const GLvoid *indices, GLuint *destPtr, size_t numTr
}
template <typename T>
-void CopyTriangleFanIndicesWithRestart(const GLvoid *indices,
+void CopyTriangleFanIndicesWithRestart(const void *indices,
GLuint indexCount,
GLenum indexType,
std::vector<GLuint> *bufferOut)
@@ -314,7 +301,7 @@ void CopyTriangleFanIndicesWithRestart(const GLvoid *indices,
}
}
-void GetTriFanIndices(const GLvoid *indices,
+void GetTriFanIndices(const void *indices,
GLenum indexType,
GLuint count,
bool usePrimitiveRestartFixedIndex,
@@ -365,60 +352,135 @@ void GetTriFanIndices(const GLvoid *indices,
}
}
+bool DrawCallNeedsTranslation(const gl::Context *context, GLenum mode)
+{
+ const auto &glState = context->getGLState();
+ const gl::VertexArray *vertexArray = glState.getVertexArray();
+ VertexArray11 *vertexArray11 = GetImplAs<VertexArray11>(vertexArray);
+ // Direct drawing doesn't support dynamic attribute storage since it needs the first and count
+ // to translate when applyVertexBuffer. GL_LINE_LOOP and GL_TRIANGLE_FAN are not supported
+ // either since we need to simulate them in D3D.
+ if (vertexArray11->hasActiveDynamicAttrib(context) || mode == GL_LINE_LOOP ||
+ mode == GL_TRIANGLE_FAN)
+ {
+ return true;
+ }
+
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
+ if (InstancedPointSpritesActive(programD3D, mode))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+bool IsArrayRTV(ID3D11RenderTargetView *rtv)
+{
+ D3D11_RENDER_TARGET_VIEW_DESC desc;
+ rtv->GetDesc(&desc);
+ if (desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE1DARRAY &&
+ desc.Texture1DArray.ArraySize > 1)
+ return true;
+ if (desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE2DARRAY &&
+ desc.Texture2DArray.ArraySize > 1)
+ return true;
+ if (desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY &&
+ desc.Texture2DMSArray.ArraySize > 1)
+ return true;
+ return false;
+}
+
+int GetAdjustedInstanceCount(const gl::Program *program, int instanceCount)
+{
+ if (!program->usesMultiview())
+ {
+ return instanceCount;
+ }
+ if (instanceCount == 0)
+ {
+ return program->getNumViews();
+ }
+ return program->getNumViews() * instanceCount;
+}
+
+const uint32_t ScratchMemoryBufferLifetime = 1000;
+
+void PopulateFormatDeviceCaps(ID3D11Device *device,
+ DXGI_FORMAT format,
+ UINT *outSupport,
+ UINT *outMaxSamples)
+{
+ if (FAILED(device->CheckFormatSupport(format, outSupport)))
+ {
+ *outSupport = 0;
+ }
+
+ *outMaxSamples = 0;
+ for (UINT sampleCount = 2; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; sampleCount *= 2)
+ {
+ UINT qualityCount = 0;
+ if (FAILED(device->CheckMultisampleQualityLevels(format, sampleCount, &qualityCount)) ||
+ qualityCount == 0)
+ {
+ break;
+ }
+
+ *outMaxSamples = sampleCount;
+ }
+}
+
+bool CullsEverything(const gl::State &glState)
+{
+ return (glState.getRasterizerState().cullFace &&
+ glState.getRasterizerState().cullMode == gl::CullFaceMode::FrontAndBack);
+}
+
} // anonymous namespace
+Renderer11DeviceCaps::Renderer11DeviceCaps() = default;
+
Renderer11::Renderer11(egl::Display *display)
: RendererD3D(display),
- mStateCache(this),
+ mCreateDebugDevice(false),
+ mStateCache(),
mStateManager(this),
- mLastHistogramUpdateTime(ANGLEPlatformCurrent()->monotonicallyIncreasingTime())
-#if !defined(ANGLE_MINGW32_COMPAT)
- ,mDebug(nullptr)
-#endif
+ mLastHistogramUpdateTime(
+ ANGLEPlatformCurrent()->monotonicallyIncreasingTime(ANGLEPlatformCurrent())),
+ mDebug(nullptr),
+ mScratchMemoryBuffer(ScratchMemoryBufferLifetime),
+ mAnnotator(nullptr)
{
- mVertexDataManager = NULL;
- mIndexDataManager = NULL;
+ mLineLoopIB = nullptr;
+ mTriangleFanIB = nullptr;
- mLineLoopIB = NULL;
- mTriangleFanIB = NULL;
- mAppliedIBChanged = false;
+ mBlit = nullptr;
+ mPixelTransfer = nullptr;
- mBlit = NULL;
- mPixelTransfer = NULL;
+ mClear = nullptr;
- mClear = NULL;
+ mTrim = nullptr;
- mTrim = NULL;
-
- mSyncQuery = NULL;
-
- mRenderer11DeviceCaps.supportsClearView = false;
+ mRenderer11DeviceCaps.supportsClearView = false;
mRenderer11DeviceCaps.supportsConstantBufferOffsets = false;
- mRenderer11DeviceCaps.supportsDXGI1_2 = false;
- mRenderer11DeviceCaps.B5G6R5support = 0;
- mRenderer11DeviceCaps.B4G4R4A4support = 0;
- mRenderer11DeviceCaps.B5G5R5A1support = 0;
-
- mD3d11Module = NULL;
- mDxgiModule = NULL;
- mDCompModule = NULL;
+ mRenderer11DeviceCaps.supportsVpRtIndexWriteFromVertexShader = false;
+ mRenderer11DeviceCaps.supportsDXGI1_2 = false;
+ mRenderer11DeviceCaps.B5G6R5support = 0;
+ mRenderer11DeviceCaps.B4G4R4A4support = 0;
+ mRenderer11DeviceCaps.B5G5R5A1support = 0;
+
+ mD3d11Module = nullptr;
+ mDxgiModule = nullptr;
+ mDCompModule = nullptr;
mCreatedWithDeviceEXT = false;
mEGLDevice = nullptr;
- mDevice = NULL;
- mDeviceContext = NULL;
- mDeviceContext1 = NULL;
- mDxgiAdapter = NULL;
- mDxgiFactory = NULL;
-
- mDriverConstantBufferVS = NULL;
- mDriverConstantBufferPS = NULL;
-
- mAppliedVertexShader = NULL;
- mAppliedGeometryShader = NULL;
- mAppliedPixelShader = NULL;
-
- mAppliedNumXFBBindings = static_cast<size_t>(-1);
+ mDevice = nullptr;
+ mDeviceContext = nullptr;
+ mDeviceContext1 = nullptr;
+ mDeviceContext3 = nullptr;
+ mDxgiAdapter = nullptr;
+ mDxgiFactory = nullptr;
ZeroMemory(&mAdapterDescription, sizeof(mAdapterDescription));
@@ -426,13 +488,21 @@ Renderer11::Renderer11(egl::Display *display)
{
const auto &attributes = mDisplay->getAttributeMap();
- EGLint requestedMajorVersion =
- attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE);
- EGLint requestedMinorVersion =
- attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE);
+ EGLint requestedMajorVersion = static_cast<EGLint>(
+ attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE));
+ EGLint requestedMinorVersion = static_cast<EGLint>(
+ attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE));
if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 11)
{
+ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
+ {
+ // This could potentially lead to failed context creation if done on a system
+ // without the platform update which installs DXGI 1.2. Currently, for Chrome users
+ // D3D11 contexts are only created if the platform update is available, so this
+ // should not cause any issues.
+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_1);
+ }
if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
{
mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_0);
@@ -451,11 +521,7 @@ Renderer11::Renderer11(egl::Display *display)
}
}
-#if defined(ANGLE_ENABLE_WINDOWS_STORE)
- if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9)
-#else
if (requestedMajorVersion == 9 && requestedMinorVersion == 3)
-#endif
{
if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 3)
{
@@ -473,8 +539,8 @@ Renderer11::Renderer11(egl::Display *display)
#endif
}
- EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
- EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
+ EGLint requestedDeviceType = static_cast<EGLint>(attributes.get(
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE));
switch (requestedDeviceType)
{
case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
@@ -497,9 +563,11 @@ Renderer11::Renderer11(egl::Display *display)
UNREACHABLE();
}
- const EGLenum presentPath = attributes.get(EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE,
- EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE);
+ const EGLenum presentPath = static_cast<EGLenum>(attributes.get(
+ EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE, EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE));
mPresentPathFastEnabled = (presentPath == EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE);
+
+ mCreateDebugDevice = ShouldUseDebugLayers(attributes);
}
else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT)
{
@@ -509,11 +577,22 @@ Renderer11::Renderer11(egl::Display *display)
// Also set EGL_PLATFORM_ANGLE_ANGLE variables, in case they're used elsewhere in ANGLE
// mAvailableFeatureLevels defaults to empty
- mRequestedDriverType = D3D_DRIVER_TYPE_UNKNOWN;
+ mRequestedDriverType = D3D_DRIVER_TYPE_UNKNOWN;
mPresentPathFastEnabled = false;
}
- initializeDebugAnnotator();
+// The D3D11 renderer must choose the D3D9 debug annotator because the D3D11 interface
+// method ID3DUserDefinedAnnotation::GetStatus on desktop builds doesn't work with the Graphics
+// Diagnostics tools in Visual Studio 2013.
+// The D3D9 annotator works properly for both D3D11 and D3D9.
+// Incorrect status reporting can cause ANGLE to log unnecessary debug events.
+#ifdef ANGLE_ENABLE_D3D9
+ mAnnotator = new DebugAnnotator9();
+#else
+ mAnnotator = new DebugAnnotator11();
+#endif
+ ASSERT(mAnnotator);
+ gl::InitializeDebugAnnotations(mAnnotator);
}
Renderer11::~Renderer11()
@@ -529,20 +608,17 @@ egl::Error Renderer11::initialize()
{
HRESULT result = S_OK;
- egl::Error error = initializeD3DDevice();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(initializeD3DDevice());
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
#if !ANGLE_SKIP_DXGI_1_2_CHECK
{
TRACE_EVENT0("gpu.angle", "Renderer11::initialize (DXGICheck)");
- // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is required.
+ // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is
+ // required.
// The easiest way to check is to query for a IDXGIDevice2.
bool requireDXGI1_2 = false;
- HWND hwnd = WindowFromDC(mDisplay->getNativeDisplayId());
+ HWND hwnd = WindowFromDC(mDisplay->getNativeDisplayId());
if (hwnd)
{
DWORD currentProcessId = GetCurrentProcessId();
@@ -557,13 +633,12 @@ egl::Error Renderer11::initialize()
if (requireDXGI1_2)
{
- IDXGIDevice2 *dxgiDevice2 = NULL;
- result = mDevice->QueryInterface(__uuidof(IDXGIDevice2), (void**)&dxgiDevice2);
+ IDXGIDevice2 *dxgiDevice2 = nullptr;
+ result = mDevice->QueryInterface(__uuidof(IDXGIDevice2), (void **)&dxgiDevice2);
if (FAILED(result))
{
- return egl::Error(EGL_NOT_INITIALIZED,
- D3D11_INIT_INCOMPATIBLE_DXGI,
- "DXGI 1.2 required to present to HWNDs owned by another process.");
+ return egl::EglNotInitialized(D3D11_INIT_INCOMPATIBLE_DXGI)
+ << "DXGI 1.2 required to present to HWNDs owned by another process.";
}
SafeRelease(dxgiDevice2);
}
@@ -573,90 +648,83 @@ egl::Error Renderer11::initialize()
{
TRACE_EVENT0("gpu.angle", "Renderer11::initialize (ComQueries)");
- // Cast the DeviceContext to a DeviceContext1.
+ // Cast the DeviceContext to a DeviceContext1 and DeviceContext3.
// This could fail on Windows 7 without the Platform Update.
- // Don't error in this case- just don't use mDeviceContext1.
-#if defined(ANGLE_ENABLE_D3D11_1)
+ // Don't error in this case- just don't use mDeviceContext1 or mDeviceContext3.
mDeviceContext1 = d3d11::DynamicCastComObject<ID3D11DeviceContext1>(mDeviceContext);
-#endif
+ mDeviceContext3 = d3d11::DynamicCastComObject<ID3D11DeviceContext3>(mDeviceContext);
- IDXGIDevice *dxgiDevice = NULL;
- result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice);
+ IDXGIDevice *dxgiDevice = nullptr;
+ result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice);
if (FAILED(result))
{
- return egl::Error(EGL_NOT_INITIALIZED,
- D3D11_INIT_OTHER_ERROR,
- "Could not query DXGI device.");
+ return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) << "Could not query DXGI device.";
}
- result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter);
+ result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&mDxgiAdapter);
if (FAILED(result))
{
- return egl::Error(EGL_NOT_INITIALIZED,
- D3D11_INIT_OTHER_ERROR,
- "Could not retrieve DXGI adapter");
+ return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR)
+ << "Could not retrieve DXGI adapter";
}
SafeRelease(dxgiDevice);
-#if defined(ANGLE_ENABLE_D3D11_1)
IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter);
- // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter" for the description string.
- // If DXGI1.2 is available then IDXGIAdapter2::GetDesc2 can be used to get the actual hardware values.
- if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3 && dxgiAdapter2 != NULL)
+ // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter" for the
+ // description string.
+ // If DXGI1.2 is available then IDXGIAdapter2::GetDesc2 can be used to get the actual
+ // hardware values.
+ if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3 && dxgiAdapter2 != nullptr)
{
DXGI_ADAPTER_DESC2 adapterDesc2 = {};
- result = dxgiAdapter2->GetDesc2(&adapterDesc2);
+ result = dxgiAdapter2->GetDesc2(&adapterDesc2);
if (SUCCEEDED(result))
{
- // Copy the contents of the DXGI_ADAPTER_DESC2 into mAdapterDescription (a DXGI_ADAPTER_DESC).
- memcpy(mAdapterDescription.Description, adapterDesc2.Description, sizeof(mAdapterDescription.Description));
- mAdapterDescription.VendorId = adapterDesc2.VendorId;
- mAdapterDescription.DeviceId = adapterDesc2.DeviceId;
- mAdapterDescription.SubSysId = adapterDesc2.SubSysId;
- mAdapterDescription.Revision = adapterDesc2.Revision;
- mAdapterDescription.DedicatedVideoMemory = adapterDesc2.DedicatedVideoMemory;
+ // Copy the contents of the DXGI_ADAPTER_DESC2 into mAdapterDescription (a
+ // DXGI_ADAPTER_DESC).
+ memcpy(mAdapterDescription.Description, adapterDesc2.Description,
+ sizeof(mAdapterDescription.Description));
+ mAdapterDescription.VendorId = adapterDesc2.VendorId;
+ mAdapterDescription.DeviceId = adapterDesc2.DeviceId;
+ mAdapterDescription.SubSysId = adapterDesc2.SubSysId;
+ mAdapterDescription.Revision = adapterDesc2.Revision;
+ mAdapterDescription.DedicatedVideoMemory = adapterDesc2.DedicatedVideoMemory;
mAdapterDescription.DedicatedSystemMemory = adapterDesc2.DedicatedSystemMemory;
- mAdapterDescription.SharedSystemMemory = adapterDesc2.SharedSystemMemory;
- mAdapterDescription.AdapterLuid = adapterDesc2.AdapterLuid;
+ mAdapterDescription.SharedSystemMemory = adapterDesc2.SharedSystemMemory;
+ mAdapterDescription.AdapterLuid = adapterDesc2.AdapterLuid;
}
}
else
-#endif
{
result = mDxgiAdapter->GetDesc(&mAdapterDescription);
}
-#if defined(ANGLE_ENABLE_D3D11_1)
SafeRelease(dxgiAdapter2);
-#endif
if (FAILED(result))
{
- return egl::Error(EGL_NOT_INITIALIZED,
- D3D11_INIT_OTHER_ERROR,
- "Could not read DXGI adaptor description.");
+ return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR)
+ << "Could not read DXGI adaptor description.";
}
memset(mDescription, 0, sizeof(mDescription));
wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1);
- result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&mDxgiFactory);
+ result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void **)&mDxgiFactory);
if (!mDxgiFactory || FAILED(result))
{
- return egl::Error(EGL_NOT_INITIALIZED,
- D3D11_INIT_OTHER_ERROR,
- "Could not create DXGI factory.");
+ return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR)
+ << "Could not create DXGI factory.";
}
}
-#if !defined(ANGLE_MINGW32_COMPAT)
// Disable some spurious D3D11 debug warnings to prevent them from flooding the output log
-#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG)
+ if (mCreateDebugDevice)
{
TRACE_EVENT0("gpu.angle", "Renderer11::initialize (HideWarnings)");
ID3D11InfoQueue *infoQueue;
@@ -664,29 +732,33 @@ egl::Error Renderer11::initialize()
if (SUCCEEDED(result))
{
- D3D11_MESSAGE_ID hideMessages[] =
- {
- D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET
- };
+ D3D11_MESSAGE_ID hideMessages[] = {
+ D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET};
D3D11_INFO_QUEUE_FILTER filter = {};
filter.DenyList.NumIDs = static_cast<unsigned int>(ArraySize(hideMessages));
- filter.DenyList.pIDList = hideMessages;
+ filter.DenyList.pIDList = hideMessages;
infoQueue->AddStorageFilterEntries(&filter);
SafeRelease(infoQueue);
}
}
-#endif
#if !defined(NDEBUG)
mDebug = d3d11::DynamicCastComObject<ID3D11Debug>(mDevice);
#endif
-#endif // !ANGLE_MINGW32_COMPAT
- initializeDevice();
+ ANGLE_TRY(initializeDevice());
+
+ return egl::NoError();
+}
- return egl::Error(EGL_SUCCESS);
+HRESULT Renderer11::callD3D11CreateDevice(PFN_D3D11_CREATE_DEVICE createDevice, bool debug)
+{
+ return createDevice(
+ nullptr, mRequestedDriverType, nullptr, debug ? D3D11_CREATE_DEVICE_DEBUG : 0,
+ mAvailableFeatureLevels.data(), static_cast<unsigned int>(mAvailableFeatureLevels.size()),
+ D3D11_SDK_VERSION, &mDevice, &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext);
}
egl::Error Renderer11::initializeD3DDevice()
@@ -706,8 +778,8 @@ egl::Error Renderer11::initializeD3DDevice()
if (mD3d11Module == nullptr || mDxgiModule == nullptr)
{
- return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_MISSING_DEP,
- "Could not load D3D11 or DXGI library.");
+ return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP)
+ << "Could not load D3D11 or DXGI library.";
}
// create the D3D11 device
@@ -717,68 +789,76 @@ egl::Error Renderer11::initializeD3DDevice()
if (D3D11CreateDevice == nullptr)
{
- return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_MISSING_DEP,
- "Could not retrieve D3D11CreateDevice address.");
+ return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP)
+ << "Could not retrieve D3D11CreateDevice address.";
}
}
#endif
-#ifdef _DEBUG
+ if (mCreateDebugDevice)
{
TRACE_EVENT0("gpu.angle", "D3D11CreateDevice (Debug)");
- result = D3D11CreateDevice(nullptr, mRequestedDriverType, nullptr,
- D3D11_CREATE_DEVICE_DEBUG, mAvailableFeatureLevels.data(),
- static_cast<unsigned int>(mAvailableFeatureLevels.size()),
- D3D11_SDK_VERSION, &mDevice,
- &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext);
- }
+ result = callD3D11CreateDevice(D3D11CreateDevice, true);
- if (!mDevice || FAILED(result))
- {
- ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n");
+ if (result == E_INVALIDARG && mAvailableFeatureLevels.size() > 1u &&
+ mAvailableFeatureLevels[0] == D3D_FEATURE_LEVEL_11_1)
+ {
+ // On older Windows platforms, D3D11.1 is not supported which returns E_INVALIDARG.
+ // Try again without passing D3D_FEATURE_LEVEL_11_1 in case we have other feature
+ // levels to fall back on.
+ mAvailableFeatureLevels.erase(mAvailableFeatureLevels.begin());
+ result = callD3D11CreateDevice(D3D11CreateDevice, true);
+ }
+
+ if (!mDevice || FAILED(result))
+ {
+ WARN() << "Failed creating Debug D3D11 device - falling back to release runtime.";
+ }
}
if (!mDevice || FAILED(result))
-#endif
{
SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.D3D11CreateDeviceMS");
TRACE_EVENT0("gpu.angle", "D3D11CreateDevice");
- result = D3D11CreateDevice(
- nullptr, mRequestedDriverType, nullptr, 0, mAvailableFeatureLevels.data(),
- static_cast<unsigned int>(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION,
- &mDevice, &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext);
+ result = callD3D11CreateDevice(D3D11CreateDevice, false);
+
+ if (result == E_INVALIDARG && mAvailableFeatureLevels.size() > 1u &&
+ mAvailableFeatureLevels[0] == D3D_FEATURE_LEVEL_11_1)
+ {
+ // On older Windows platforms, D3D11.1 is not supported which returns E_INVALIDARG.
+ // Try again without passing D3D_FEATURE_LEVEL_11_1 in case we have other feature
+ // levels to fall back on.
+ mAvailableFeatureLevels.erase(mAvailableFeatureLevels.begin());
+ result = callD3D11CreateDevice(D3D11CreateDevice, false);
+ }
// Cleanup done by destructor
if (!mDevice || FAILED(result))
{
ANGLE_HISTOGRAM_SPARSE_SLOWLY("GPU.ANGLE.D3D11CreateDeviceError",
static_cast<int>(result));
- return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_CREATEDEVICE_ERROR,
- "Could not create D3D11 device.");
+ return egl::EglNotInitialized(D3D11_INIT_CREATEDEVICE_ERROR)
+ << "Could not create D3D11 device.";
}
}
}
else
{
// We should use the inputted D3D11 device instead
- void *device = nullptr;
- egl::Error error = mEGLDevice->getDevice(&device);
- if (error.isError())
- {
- return error;
- }
+ void *device = nullptr;
+ ANGLE_TRY(mEGLDevice->getDevice(&device));
ID3D11Device *d3dDevice = reinterpret_cast<ID3D11Device *>(device);
if (FAILED(d3dDevice->GetDeviceRemovedReason()))
{
- return egl::Error(EGL_NOT_INITIALIZED, "Inputted D3D11 device has been lost.");
+ return egl::EglNotInitialized() << "Inputted D3D11 device has been lost.";
}
if (d3dDevice->GetFeatureLevel() < D3D_FEATURE_LEVEL_9_3)
{
- return egl::Error(EGL_NOT_INITIALIZED,
- "Inputted D3D11 device must be Feature Level 9_3 or greater.");
+ return egl::EglNotInitialized()
+ << "Inputted D3D11 device must be Feature Level 9_3 or greater.";
}
// The Renderer11 adds a ref to the inputted D3D11 device, like D3D11CreateDevice does.
@@ -788,27 +868,24 @@ egl::Error Renderer11::initializeD3DDevice()
mRenderer11DeviceCaps.featureLevel = mDevice->GetFeatureLevel();
}
+ mResourceManager11.setAllocationsInitialized(mCreateDebugDevice);
+
d3d11::SetDebugName(mDeviceContext, "DeviceContext");
- return egl::Error(EGL_SUCCESS);
+ return egl::NoError();
}
// do any one-time device initialization
// NOTE: this is also needed after a device lost/reset
// to reset the scene status and ensure the default states are reset.
-void Renderer11::initializeDevice()
+egl::Error Renderer11::initializeDevice()
{
SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.Renderer11InitializeDeviceMS");
TRACE_EVENT0("gpu.angle", "Renderer11::initializeDevice");
populateRenderer11DeviceCaps();
- mStateCache.initialize(mDevice);
- mInputLayoutCache.initialize(mDevice, mDeviceContext);
-
- ASSERT(!mVertexDataManager && !mIndexDataManager);
- mVertexDataManager = new VertexDataManager(this);
- mIndexDataManager = new IndexDataManager(this, getRendererClass());
+ mStateCache.clear();
ASSERT(!mBlit);
mBlit = new Blit11(this);
@@ -820,7 +897,8 @@ void Renderer11::initializeDevice()
// If automatic trim is enabled, DXGIDevice3::Trim( ) is called for the application
// automatically when an application is suspended by the OS. This feature is currently
// only supported for Windows Store applications.
- EGLint enableAutoTrim = attributes.get(EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_FALSE);
+ EGLint enableAutoTrim = static_cast<EGLint>(
+ attributes.get(EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_FALSE));
if (enableAutoTrim == EGL_TRUE)
{
@@ -831,19 +909,12 @@ void Renderer11::initializeDevice()
ASSERT(!mPixelTransfer);
mPixelTransfer = new PixelTransfer11(this);
- const gl::Caps &rendererCaps = getRendererCaps();
-
- mStateManager.initialize(rendererCaps);
-
- mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
- mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
-
- mForceSetPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits);
- mCurPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits);
-
- mStateManager.initialize(rendererCaps);
+ const gl::Caps &rendererCaps = getNativeCaps();
- markAllStateDirty();
+ if (mStateManager.initialize(rendererCaps, getNativeExtensions()).isError())
+ {
+ return egl::EglBadAlloc() << "Error initializing state manager.";
+ }
// Gather stats on DXGI and D3D feature level
ANGLE_HISTOGRAM_BOOLEAN("GPU.ANGLE.SupportsDXGI1_2", mRenderer11DeviceCaps.supportsDXGI1_2);
@@ -859,57 +930,117 @@ void Renderer11::initializeDevice()
angleFeatureLevel = ANGLE_FEATURE_LEVEL_11_1;
}
- ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11FeatureLevel",
- angleFeatureLevel,
+ ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11FeatureLevel", angleFeatureLevel,
NUM_ANGLE_FEATURE_LEVELS);
- // TODO(jmadill): use context caps, and place in common D3D location
- mTranslatedAttribCache.resize(getRendererCaps().maxVertexAttributes);
+ return egl::NoError();
}
void Renderer11::populateRenderer11DeviceCaps()
{
HRESULT hr = S_OK;
-#if defined(ANGLE_ENABLE_D3D11_1)
+ LARGE_INTEGER version;
+ hr = mDxgiAdapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &version);
+ if (FAILED(hr))
+ {
+ mRenderer11DeviceCaps.driverVersion.reset();
+ ERR() << "Error querying driver version from DXGI Adapter.";
+ }
+ else
+ {
+ mRenderer11DeviceCaps.driverVersion = version;
+ }
+
if (mDeviceContext1)
{
D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options;
- HRESULT result = mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options, sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS));
+ HRESULT result = mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options,
+ sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS));
if (SUCCEEDED(result))
{
mRenderer11DeviceCaps.supportsClearView = (d3d11Options.ClearView != FALSE);
- mRenderer11DeviceCaps.supportsConstantBufferOffsets = (d3d11Options.ConstantBufferOffsetting != FALSE);
+ mRenderer11DeviceCaps.supportsConstantBufferOffsets =
+ (d3d11Options.ConstantBufferOffsetting != FALSE);
}
}
-#endif
- hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B5G6R5_UNORM, &(mRenderer11DeviceCaps.B5G6R5support));
- if (FAILED(hr))
+ if (mDeviceContext3)
{
- mRenderer11DeviceCaps.B5G6R5support = 0;
+ D3D11_FEATURE_DATA_D3D11_OPTIONS3 d3d11Options3;
+ HRESULT result = mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS3, &d3d11Options3,
+ sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS3));
+ if (SUCCEEDED(result))
+ {
+ mRenderer11DeviceCaps.supportsVpRtIndexWriteFromVertexShader =
+ (d3d11Options3.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer == TRUE);
+ }
}
- hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B4G4R4A4_UNORM, &(mRenderer11DeviceCaps.B4G4R4A4support));
- if (FAILED(hr))
+ mRenderer11DeviceCaps.supportsMultisampledDepthStencilSRVs =
+ mRenderer11DeviceCaps.featureLevel > D3D_FEATURE_LEVEL_10_0;
+
+ if (getWorkarounds().disableB5G6R5Support)
{
- mRenderer11DeviceCaps.B4G4R4A4support = 0;
+ mRenderer11DeviceCaps.B5G6R5support = 0;
+ mRenderer11DeviceCaps.B5G6R5maxSamples = 0;
}
-
- hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B5G5R5A1_UNORM, &(mRenderer11DeviceCaps.B5G5R5A1support));
- if (FAILED(hr))
+ else
{
- mRenderer11DeviceCaps.B5G5R5A1support = 0;
+ PopulateFormatDeviceCaps(mDevice, DXGI_FORMAT_B5G6R5_UNORM,
+ &mRenderer11DeviceCaps.B5G6R5support,
+ &mRenderer11DeviceCaps.B5G6R5maxSamples);
}
-#if defined(ANGLE_ENABLE_D3D11_1)
+ PopulateFormatDeviceCaps(mDevice, DXGI_FORMAT_B4G4R4A4_UNORM,
+ &mRenderer11DeviceCaps.B4G4R4A4support,
+ &mRenderer11DeviceCaps.B4G4R4A4maxSamples);
+ PopulateFormatDeviceCaps(mDevice, DXGI_FORMAT_B5G5R5A1_UNORM,
+ &mRenderer11DeviceCaps.B5G5R5A1support,
+ &mRenderer11DeviceCaps.B5G5R5A1maxSamples);
+
IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter);
mRenderer11DeviceCaps.supportsDXGI1_2 = (dxgiAdapter2 != nullptr);
SafeRelease(dxgiAdapter2);
+}
+
+gl::SupportedSampleSet Renderer11::generateSampleSetForEGLConfig(
+ const gl::TextureCaps &colorBufferFormatCaps,
+ const gl::TextureCaps &depthStencilBufferFormatCaps) const
+{
+ gl::SupportedSampleSet sampleCounts;
+
+#if 0 // Disabling support for multisampling with Qt5 as it's causing a crash in the D3D11 shaders.
+
+ // Generate a new set from the set intersection of sample counts between the color and depth
+ // format caps.
+ std::set_intersection(colorBufferFormatCaps.sampleCounts.begin(),
+ colorBufferFormatCaps.sampleCounts.end(),
+ depthStencilBufferFormatCaps.sampleCounts.begin(),
+ depthStencilBufferFormatCaps.sampleCounts.end(),
+ std::inserter(sampleCounts, sampleCounts.begin()));
+
+ // Format of GL_NONE results in no supported sample counts.
+ // Add back the color sample counts to the supported sample set.
+ if (depthStencilBufferFormatCaps.sampleCounts.empty())
+ {
+ sampleCounts = colorBufferFormatCaps.sampleCounts;
+ }
+ else if (colorBufferFormatCaps.sampleCounts.empty())
+ {
+ // Likewise, add back the depth sample counts to the supported sample set.
+ sampleCounts = depthStencilBufferFormatCaps.sampleCounts;
+ }
+
#endif
+
+ // Always support 0 samples
+ sampleCounts.insert(0);
+
+ return sampleCounts;
}
-egl::ConfigSet Renderer11::generateConfigs() const
+egl::ConfigSet Renderer11::generateConfigs()
{
std::vector<GLenum> colorBufferFormats;
@@ -920,6 +1051,14 @@ egl::ConfigSet Renderer11::generateConfigs() const
// 24-bit supported formats
colorBufferFormats.push_back(GL_RGB8_OES);
+ if (mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0)
+ {
+ // Additional high bit depth formats added in D3D 10.0
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/bb173064.aspx
+ colorBufferFormats.push_back(GL_RGBA16F);
+ colorBufferFormats.push_back(GL_RGB10_A2);
+ }
+
if (!mPresentPathFastEnabled)
{
// 16-bit supported formats
@@ -930,15 +1069,13 @@ egl::ConfigSet Renderer11::generateConfigs() const
colorBufferFormats.push_back(GL_RGB565);
}
- static const GLenum depthStencilBufferFormats[] =
- {
- GL_NONE,
- GL_DEPTH24_STENCIL8_OES,
- GL_DEPTH_COMPONENT16,
+ static const GLenum depthStencilBufferFormats[] = {
+ GL_NONE, GL_DEPTH24_STENCIL8_OES, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT16,
+ GL_STENCIL_INDEX8,
};
- const gl::Caps &rendererCaps = getRendererCaps();
- const gl::TextureCapsMap &rendererTextureCaps = getRendererTextureCaps();
+ const gl::Caps &rendererCaps = getNativeCaps();
+ const gl::TextureCapsMap &rendererTextureCaps = getNativeTextureCaps();
const EGLint optimalSurfaceOrientation =
mPresentPathFastEnabled ? 0 : EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE;
@@ -946,7 +1083,8 @@ egl::ConfigSet Renderer11::generateConfigs() const
egl::ConfigSet configs;
for (GLenum colorBufferInternalFormat : colorBufferFormats)
{
- const gl::TextureCaps &colorBufferFormatCaps = rendererTextureCaps.get(colorBufferInternalFormat);
+ const gl::TextureCaps &colorBufferFormatCaps =
+ rendererTextureCaps.get(colorBufferInternalFormat);
if (!colorBufferFormatCaps.renderable)
{
continue;
@@ -963,64 +1101,87 @@ egl::ConfigSet Renderer11::generateConfigs() const
}
const gl::InternalFormat &colorBufferFormatInfo =
- gl::GetInternalFormatInfo(colorBufferInternalFormat);
+ gl::GetSizedInternalFormatInfo(colorBufferInternalFormat);
const gl::InternalFormat &depthStencilBufferFormatInfo =
- gl::GetInternalFormatInfo(depthStencilBufferInternalFormat);
-
- egl::Config config;
- config.renderTargetFormat = colorBufferInternalFormat;
- config.depthStencilFormat = depthStencilBufferInternalFormat;
- config.bufferSize = colorBufferFormatInfo.pixelBytes * 8;
- config.redSize = colorBufferFormatInfo.redBits;
- config.greenSize = colorBufferFormatInfo.greenBits;
- config.blueSize = colorBufferFormatInfo.blueBits;
- config.luminanceSize = colorBufferFormatInfo.luminanceBits;
- config.alphaSize = colorBufferFormatInfo.alphaBits;
- config.alphaMaskSize = 0;
- config.bindToTextureRGB = (colorBufferFormatInfo.format == GL_RGB);
- config.bindToTextureRGBA = (colorBufferFormatInfo.format == GL_RGBA ||
- colorBufferFormatInfo.format == GL_BGRA_EXT);
- config.colorBufferType = EGL_RGB_BUFFER;
- config.configID = static_cast<EGLint>(configs.size() + 1);
- // Can only support a conformant ES2 with feature level greater than 10.0.
- config.conformant = (mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0)
- ? (EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR)
- : 0;
- config.configCaveat = config.conformant == EGL_NONE ? EGL_NON_CONFORMANT_CONFIG : EGL_NONE;
-
- // PresentPathFast may not be conformant
- if (mPresentPathFastEnabled)
+ gl::GetSizedInternalFormatInfo(depthStencilBufferInternalFormat);
+ const gl::Version &maxVersion = getMaxSupportedESVersion();
+
+ const gl::SupportedSampleSet sampleCounts =
+ generateSampleSetForEGLConfig(colorBufferFormatCaps, depthStencilBufferFormatCaps);
+
+ for (GLuint sampleCount : sampleCounts)
{
+ egl::Config config;
+ config.renderTargetFormat = colorBufferInternalFormat;
+ config.depthStencilFormat = depthStencilBufferInternalFormat;
+ config.bufferSize = colorBufferFormatInfo.pixelBytes * 8;
+ config.redSize = colorBufferFormatInfo.redBits;
+ config.greenSize = colorBufferFormatInfo.greenBits;
+ config.blueSize = colorBufferFormatInfo.blueBits;
+ config.luminanceSize = colorBufferFormatInfo.luminanceBits;
+ config.alphaSize = colorBufferFormatInfo.alphaBits;
+ config.alphaMaskSize = 0;
+ config.bindToTextureRGB =
+ ((colorBufferFormatInfo.format == GL_RGB) && (sampleCount <= 1));
+ config.bindToTextureRGBA = (((colorBufferFormatInfo.format == GL_RGBA) ||
+ (colorBufferFormatInfo.format == GL_BGRA_EXT)) &&
+ (sampleCount <= 1));
+ config.colorBufferType = EGL_RGB_BUFFER;
+ config.configCaveat = EGL_NONE;
+ config.configID = static_cast<EGLint>(configs.size() + 1);
+
+ // PresentPathFast may not be conformant
config.conformant = 0;
- }
+ if (!mPresentPathFastEnabled)
+ {
+ // Can only support a conformant ES2 with feature level greater than 10.0.
+ if (mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0)
+ {
+ config.conformant |= EGL_OPENGL_ES2_BIT;
+ }
+
+ // We can only support conformant ES3 on FL 10.1+
+ if (maxVersion.major >= 3)
+ {
+ config.conformant |= EGL_OPENGL_ES3_BIT_KHR;
+ }
+ }
+
+ config.depthSize = depthStencilBufferFormatInfo.depthBits;
+ config.level = 0;
+ config.matchNativePixmap = EGL_NONE;
+ config.maxPBufferWidth = rendererCaps.max2DTextureSize;
+ config.maxPBufferHeight = rendererCaps.max2DTextureSize;
+ config.maxPBufferPixels =
+ rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize;
+ config.maxSwapInterval = 4;
+ config.minSwapInterval = 0;
+ config.nativeRenderable = EGL_FALSE;
+ config.nativeVisualID = 0;
+ config.nativeVisualType = EGL_NONE;
+
+ // Can't support ES3 at all without feature level 10.1
+ config.renderableType = EGL_OPENGL_ES2_BIT;
+ if (maxVersion.major >= 3)
+ {
+ config.renderableType |= EGL_OPENGL_ES3_BIT_KHR;
+ }
- config.depthSize = depthStencilBufferFormatInfo.depthBits;
- config.level = 0;
- config.matchNativePixmap = EGL_NONE;
- config.maxPBufferWidth = rendererCaps.max2DTextureSize;
- config.maxPBufferHeight = rendererCaps.max2DTextureSize;
- config.maxPBufferPixels = rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize;
- config.maxSwapInterval = 4;
- config.minSwapInterval = 0;
- config.nativeRenderable = EGL_FALSE;
- config.nativeVisualID = 0;
- config.nativeVisualType = EGL_NONE;
- // Can't support ES3 at all without feature level 10.0
- config.renderableType =
- EGL_OPENGL_ES2_BIT | ((mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0)
- ? EGL_OPENGL_ES3_BIT_KHR
- : 0);
- config.sampleBuffers = 0; // FIXME: enumerate multi-sampling
- config.samples = 0;
- config.stencilSize = depthStencilBufferFormatInfo.stencilBits;
- config.surfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
- config.transparentType = EGL_NONE;
- config.transparentRedValue = 0;
- config.transparentGreenValue = 0;
- config.transparentBlueValue = 0;
- config.optimalOrientation = optimalSurfaceOrientation;
-
- configs.add(config);
+ config.sampleBuffers = (sampleCount == 0) ? 0 : 1;
+ config.samples = sampleCount;
+ config.stencilSize = depthStencilBufferFormatInfo.stencilBits;
+ config.surfaceType =
+ EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
+ config.transparentType = EGL_NONE;
+ config.transparentRedValue = 0;
+ config.transparentGreenValue = 0;
+ config.transparentBlueValue = 0;
+ config.optimalOrientation = optimalSurfaceOrientation;
+ config.colorComponentType = gl_egl::GLComponentTypeToEGLColorComponentType(
+ colorBufferFormatInfo.componentType);
+
+ configs.add(config);
+ }
}
}
@@ -1037,8 +1198,9 @@ void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions
outExtensions->d3dShareHandleClientBuffer = true;
outExtensions->surfaceD3DTexture2DShareHandle = true;
}
+ outExtensions->d3dTextureClientBuffer = true;
- outExtensions->keyedMutex = true;
+ outExtensions->keyedMutex = true;
outExtensions->querySurfacePointer = true;
outExtensions->windowFixedSize = true;
@@ -1048,624 +1210,350 @@ void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions
// D3D11 does not support present with dirty rectangles until DXGI 1.2.
outExtensions->postSubBuffer = mRenderer11DeviceCaps.supportsDXGI1_2;
- outExtensions->createContext = true;
-
outExtensions->deviceQuery = true;
- outExtensions->createContextNoError = true;
-
outExtensions->image = true;
outExtensions->imageBase = true;
outExtensions->glTexture2DImage = true;
outExtensions->glTextureCubemapImage = true;
outExtensions->glRenderbufferImage = true;
+ outExtensions->stream = true;
+ outExtensions->streamConsumerGLTexture = true;
+ outExtensions->streamConsumerGLTextureYUV = true;
+ // Not all D3D11 devices support NV12 textures
+ if (getNV12TextureSupport())
+ {
+ outExtensions->streamProducerD3DTextureNV12 = true;
+ }
+
outExtensions->flexibleSurfaceCompatibility = true;
outExtensions->directComposition = !!mDCompModule;
+
+ // Contexts are virtualized so textures can be shared globally
+ outExtensions->displayTextureShareGroup = true;
+
+ // getSyncValues requires direct composition.
+ outExtensions->getSyncValues = outExtensions->directComposition;
+
+ // D3D11 can be used without a swap chain
+ outExtensions->surfacelessContext = true;
+
+ // All D3D feature levels support robust resource init
+ outExtensions->robustResourceInitialization = true;
}
gl::Error Renderer11::flush()
{
mDeviceContext->Flush();
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error Renderer11::finish()
{
- HRESULT result;
-
- if (!mSyncQuery)
+ if (!mSyncQuery.valid())
{
D3D11_QUERY_DESC queryDesc;
- queryDesc.Query = D3D11_QUERY_EVENT;
+ queryDesc.Query = D3D11_QUERY_EVENT;
queryDesc.MiscFlags = 0;
- result = mDevice->CreateQuery(&queryDesc, &mSyncQuery);
- ASSERT(SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.", result);
- }
+ ANGLE_TRY(allocateResource(queryDesc, &mSyncQuery));
}
- mDeviceContext->End(mSyncQuery);
- mDeviceContext->Flush();
+ mDeviceContext->End(mSyncQuery.get());
+ HRESULT result = S_OK;
+ unsigned int attempt = 0;
do
{
- result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH);
+ unsigned int flushFrequency = 100;
+ UINT flags = (attempt % flushFrequency == 0) ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH;
+ attempt++;
+
+ result = mDeviceContext->GetData(mSyncQuery.get(), nullptr, 0, flags);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to get event query data, " << gl::FmtHR(result);
}
- // Keep polling, but allow other threads to do something useful first
- ScheduleYield();
+ if (result == S_FALSE)
+ {
+ // Keep polling, but allow other threads to do something useful first
+ ScheduleYield();
+ }
if (testDeviceLost())
{
mDisplay->notifyDeviceLost();
- return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while waiting for sync.");
+ return gl::OutOfMemory() << "Device was lost while waiting for sync.";
}
- }
- while (result == S_FALSE);
+ } while (result == S_FALSE);
- return gl::Error(GL_NO_ERROR);
-}
-
-SwapChainD3D *Renderer11::createSwapChain(NativeWindow nativeWindow,
- HANDLE shareHandle,
- GLenum backBufferFormat,
- GLenum depthBufferFormat,
- EGLint orientation)
-{
- return new SwapChain11(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat,
- orientation);
+ return gl::NoError();
}
-CompilerImpl *Renderer11::createCompiler()
+bool Renderer11::isValidNativeWindow(EGLNativeWindowType window) const
{
- if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3)
- {
- return new CompilerD3D(SH_HLSL_4_0_FL9_3_OUTPUT);
- }
- else
- {
- return new CompilerD3D(SH_HLSL_4_1_OUTPUT);
- }
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+ return NativeWindow11WinRT::IsValidNativeWindow(window);
+#else
+ return NativeWindow11Win32::IsValidNativeWindow(window);
+#endif
}
-void *Renderer11::getD3DDevice()
+NativeWindowD3D *Renderer11::createNativeWindow(EGLNativeWindowType window,
+ const egl::Config *config,
+ const egl::AttributeMap &attribs) const
{
- return reinterpret_cast<void*>(mDevice);
+#ifdef ANGLE_ENABLE_WINDOWS_STORE
+ UNUSED_VARIABLE(attribs);
+ return new NativeWindow11WinRT(window, config->alphaSize > 0);
+#else
+ return new NativeWindow11Win32(
+ window, config->alphaSize > 0,
+ attribs.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE);
+#endif
}
-gl::Error Renderer11::generateSwizzle(gl::Texture *texture)
+egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration,
+ IUnknown *d3dTexture,
+ EGLint *width,
+ EGLint *height,
+ GLenum *fboFormat) const
{
- if (texture)
+ ID3D11Texture2D *texture = d3d11::DynamicCastComObject<ID3D11Texture2D>(d3dTexture);
+ if (texture == nullptr)
{
- TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
- ASSERT(textureD3D);
-
- TextureStorage *texStorage = nullptr;
- gl::Error error = textureD3D->getNativeTexture(&texStorage);
- if (error.isError())
- {
- return error;
- }
-
- if (texStorage)
- {
- TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
- const gl::TextureState &textureState = texture->getTextureState();
- error =
- storage11->generateSwizzles(textureState.swizzleRed, textureState.swizzleGreen,
- textureState.swizzleBlue, textureState.swizzleAlpha);
- if (error.isError())
- {
- return error;
- }
- }
+ return egl::EglBadParameter() << "client buffer is not a ID3D11Texture2D";
}
- return gl::Error(GL_NO_ERROR);
-}
-
-gl::Error Renderer11::setSamplerState(gl::SamplerType type,
- int index,
- gl::Texture *texture,
- const gl::SamplerState &samplerState)
-{
- // Make sure to add the level offset for our tiny compressed texture workaround
- TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
-
- TextureStorage *storage = nullptr;
- gl::Error error = textureD3D->getNativeTexture(&storage);
- if (error.isError())
+ ID3D11Device *textureDevice = nullptr;
+ texture->GetDevice(&textureDevice);
+ if (textureDevice != mDevice)
{
- return error;
+ SafeRelease(texture);
+ return egl::EglBadParameter() << "Texture's device does not match.";
}
+ SafeRelease(textureDevice);
- // Storage should exist, texture should be complete
- ASSERT(storage);
+ D3D11_TEXTURE2D_DESC desc = {0};
+ texture->GetDesc(&desc);
+ SafeRelease(texture);
- if (type == gl::SAMPLER_PIXEL)
+ if (width)
{
- ASSERT(static_cast<unsigned int>(index) < getRendererCaps().maxTextureImageUnits);
-
- if (mForceSetPixelSamplerStates[index] ||
- memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0)
- {
- ID3D11SamplerState *dxSamplerState = NULL;
- error = mStateCache.getSamplerState(samplerState, &dxSamplerState);
- if (error.isError())
- {
- return error;
- }
-
- ASSERT(dxSamplerState != NULL);
- mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState);
-
- mCurPixelSamplerStates[index] = samplerState;
- }
-
- mForceSetPixelSamplerStates[index] = false;
+ *width = static_cast<EGLint>(desc.Width);
}
- else if (type == gl::SAMPLER_VERTEX)
+ if (height)
{
- ASSERT(static_cast<unsigned int>(index) < getRendererCaps().maxVertexTextureImageUnits);
-
- if (mForceSetVertexSamplerStates[index] ||
- memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0)
- {
- ID3D11SamplerState *dxSamplerState = NULL;
- error = mStateCache.getSamplerState(samplerState, &dxSamplerState);
- if (error.isError())
- {
- return error;
- }
-
- ASSERT(dxSamplerState != NULL);
- mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState);
-
- mCurVertexSamplerStates[index] = samplerState;
- }
-
- mForceSetVertexSamplerStates[index] = false;
+ *height = static_cast<EGLint>(desc.Height);
}
- else UNREACHABLE();
-
- return gl::Error(GL_NO_ERROR);
-}
-
-gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
-{
- ID3D11ShaderResourceView *textureSRV = NULL;
-
- if (texture)
+ if (static_cast<EGLint>(desc.SampleDesc.Count) != configuration->samples)
{
- TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture);
-
- TextureStorage *texStorage = nullptr;
- gl::Error error = textureImpl->getNativeTexture(&texStorage);
- if (error.isError())
- {
- return error;
- }
-
- // Texture should be complete and have a storage
- ASSERT(texStorage);
-
- TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
-
- // Make sure to add the level offset for our tiny compressed texture workaround
- gl::TextureState textureState = texture->getTextureState();
- textureState.baseLevel += storage11->getTopLevel();
-
- error = storage11->getSRV(textureState, &textureSRV);
- if (error.isError())
+ // Both the texture and EGL config sample count may not be the same when multi-sampling
+ // is disabled. The EGL sample count can be 0 but a D3D texture is always 1. Therefore,
+ // we must only check for a invalid match when the EGL config is non-zero or the texture is
+ // not one.
+ if (configuration->samples != 0 || desc.SampleDesc.Count != 1)
{
- return error;
+ return egl::EglBadParameter() << "Texture's sample count does not match.";
}
-
- // If we get NULL back from getSRV here, something went wrong in the texture class and we're unexpectedly
- // missing the shader resource view
- ASSERT(textureSRV != NULL);
-
- textureImpl->resetDirty();
}
-
- ASSERT((type == gl::SAMPLER_PIXEL && static_cast<unsigned int>(index) < getRendererCaps().maxTextureImageUnits) ||
- (type == gl::SAMPLER_VERTEX && static_cast<unsigned int>(index) < getRendererCaps().maxVertexTextureImageUnits));
-
- mStateManager.setShaderResource(type, index, textureSRV);
-
- return gl::Error(GL_NO_ERROR);
-}
-
-gl::Error Renderer11::setUniformBuffers(const gl::Data &data,
- const std::vector<GLint> &vertexUniformBuffers,
- const std::vector<GLint> &fragmentUniformBuffers)
-{
- for (size_t uniformBufferIndex = 0; uniformBufferIndex < vertexUniformBuffers.size(); uniformBufferIndex++)
+ // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
+ switch (desc.Format)
{
- GLint binding = vertexUniformBuffers[uniformBufferIndex];
-
- if (binding == -1)
- {
- continue;
- }
-
- const OffsetBindingPointer<gl::Buffer> &uniformBuffer =
- data.state->getIndexedUniformBuffer(binding);
- GLintptr uniformBufferOffset = uniformBuffer.getOffset();
- GLsizeiptr uniformBufferSize = uniformBuffer.getSize();
-
- if (uniformBuffer.get() != nullptr)
- {
- Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer.get());
- ID3D11Buffer *constantBuffer;
-
- if (mRenderer11DeviceCaps.supportsConstantBufferOffsets)
- {
- constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM);
- }
- else
- {
- constantBuffer = bufferStorage->getConstantBufferRange(uniformBufferOffset, uniformBufferSize);
- }
-
- if (!constantBuffer)
- {
- return gl::Error(GL_OUT_OF_MEMORY);
- }
-
- if (mCurrentConstantBufferVS[uniformBufferIndex] != bufferStorage->getSerial() ||
- mCurrentConstantBufferVSOffset[uniformBufferIndex] != uniformBufferOffset ||
- mCurrentConstantBufferVSSize[uniformBufferIndex] != uniformBufferSize)
- {
-#if defined(ANGLE_ENABLE_D3D11_1)
- if (mRenderer11DeviceCaps.supportsConstantBufferOffsets && uniformBufferSize != 0)
- {
- UINT firstConstant = 0, numConstants = 0;
- CalculateConstantBufferParams(uniformBufferOffset, uniformBufferSize, &firstConstant, &numConstants);
- mDeviceContext1->VSSetConstantBuffers1(
- getReservedVertexUniformBuffers() +
- static_cast<unsigned int>(uniformBufferIndex),
- 1, &constantBuffer, &firstConstant, &numConstants);
- }
- else
-#endif
- {
- mDeviceContext->VSSetConstantBuffers(
- getReservedVertexUniformBuffers() +
- static_cast<unsigned int>(uniformBufferIndex),
- 1, &constantBuffer);
- }
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ break;
- mCurrentConstantBufferVS[uniformBufferIndex] = bufferStorage->getSerial();
- mCurrentConstantBufferVSOffset[uniformBufferIndex] = uniformBufferOffset;
- mCurrentConstantBufferVSSize[uniformBufferIndex] = uniformBufferSize;
- }
- }
+ default:
+ return egl::EglBadParameter()
+ << "Unknown client buffer texture format: " << desc.Format;
}
- for (size_t uniformBufferIndex = 0; uniformBufferIndex < fragmentUniformBuffers.size(); uniformBufferIndex++)
+ if (fboFormat)
{
- GLint binding = fragmentUniformBuffers[uniformBufferIndex];
-
- if (binding == -1)
- {
- continue;
- }
-
- const OffsetBindingPointer<gl::Buffer> &uniformBuffer =
- data.state->getIndexedUniformBuffer(binding);
- GLintptr uniformBufferOffset = uniformBuffer.getOffset();
- GLsizeiptr uniformBufferSize = uniformBuffer.getSize();
-
- if (uniformBuffer.get() != nullptr)
- {
- Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer.get());
- ID3D11Buffer *constantBuffer;
-
- if (mRenderer11DeviceCaps.supportsConstantBufferOffsets)
- {
- constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM);
- }
- else
- {
- constantBuffer = bufferStorage->getConstantBufferRange(uniformBufferOffset, uniformBufferSize);
- }
-
- if (!constantBuffer)
- {
- return gl::Error(GL_OUT_OF_MEMORY);
- }
-
- if (mCurrentConstantBufferPS[uniformBufferIndex] != bufferStorage->getSerial() ||
- mCurrentConstantBufferPSOffset[uniformBufferIndex] != uniformBufferOffset ||
- mCurrentConstantBufferPSSize[uniformBufferIndex] != uniformBufferSize)
- {
-#if defined(ANGLE_ENABLE_D3D11_1)
- if (mRenderer11DeviceCaps.supportsConstantBufferOffsets && uniformBufferSize != 0)
- {
- UINT firstConstant = 0, numConstants = 0;
- CalculateConstantBufferParams(uniformBufferOffset, uniformBufferSize, &firstConstant, &numConstants);
- mDeviceContext1->PSSetConstantBuffers1(
- getReservedFragmentUniformBuffers() +
- static_cast<unsigned int>(uniformBufferIndex),
- 1, &constantBuffer, &firstConstant, &numConstants);
- }
- else
-#endif
- {
- mDeviceContext->PSSetConstantBuffers(
- getReservedFragmentUniformBuffers() +
- static_cast<unsigned int>(uniformBufferIndex),
- 1, &constantBuffer);
- }
-
- mCurrentConstantBufferPS[uniformBufferIndex] = bufferStorage->getSerial();
- mCurrentConstantBufferPSOffset[uniformBufferIndex] = uniformBufferOffset;
- mCurrentConstantBufferPSSize[uniformBufferIndex] = uniformBufferSize;
- }
- }
+ const angle::Format &angleFormat = d3d11_angle::GetFormat(desc.Format);
+ *fboFormat = angleFormat.fboImplementationInternalFormat;
}
- return gl::Error(GL_NO_ERROR);
+ return egl::NoError();
}
-gl::Error Renderer11::updateState(const gl::Data &data, GLenum drawMode)
+egl::Error Renderer11::validateShareHandle(const egl::Config *config,
+ HANDLE shareHandle,
+ const egl::AttributeMap &attribs) const
{
- // Applies the render target surface, depth stencil surface, viewport rectangle and
- // scissor rectangle to the renderer
- const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer();
- ASSERT(framebufferObject && framebufferObject->checkStatus(data) == GL_FRAMEBUFFER_COMPLETE);
- gl::Error error = applyRenderTarget(framebufferObject);
- if (error.isError())
+ if (shareHandle == nullptr)
{
- return error;
+ return egl::EglBadParameter() << "NULL share handle.";
}
- // Set the present path state
- const bool presentPathFastActive =
- UsePresentPathFast(this, framebufferObject->getFirstColorbuffer());
- mStateManager.updatePresentPath(presentPathFastActive,
- framebufferObject->getFirstColorbuffer());
-
- // Setting viewport state
- mStateManager.setViewport(data.caps, data.state->getViewport(), data.state->getNearPlane(),
- data.state->getFarPlane());
-
- // Setting scissor state
- mStateManager.setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled());
-
- // Applying rasterizer state to D3D11 device
- int samples = framebufferObject->getSamples(data);
- gl::RasterizerState rasterizer = data.state->getRasterizerState();
- rasterizer.pointDrawMode = (drawMode == GL_POINTS);
- rasterizer.multiSample = (samples != 0);
-
- error = mStateManager.setRasterizerState(rasterizer);
- if (error.isError())
+ ID3D11Resource *tempResource11 = nullptr;
+ HRESULT result = mDevice->OpenSharedResource(shareHandle, __uuidof(ID3D11Resource),
+ (void **)&tempResource11);
+ if (FAILED(result))
{
- return error;
+ return egl::EglBadParameter() << "Failed to open share handle, " << gl::FmtHR(result);
}
- // Setting blend state
- unsigned int mask = GetBlendSampleMask(data, samples);
- error = mStateManager.setBlendState(framebufferObject, data.state->getBlendState(),
- data.state->getBlendColor(), mask);
- if (error.isError())
+ ID3D11Texture2D *texture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(tempResource11);
+ SafeRelease(tempResource11);
+
+ if (texture2D == nullptr)
{
- return error;
+ return egl::EglBadParameter()
+ << "Failed to query ID3D11Texture2D object from share handle.";
}
- // Setting depth stencil state
- error = mStateManager.setDepthStencilState(*data.state);
- return error;
-}
-
-void Renderer11::syncState(const gl::State &state, const gl::State::DirtyBits &bitmask)
-{
- mStateManager.syncState(state, bitmask);
-}
-
-bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize)
-{
- D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
+ D3D11_TEXTURE2D_DESC desc = {0};
+ texture2D->GetDesc(&desc);
+ SafeRelease(texture2D);
- GLsizei minCount = 0;
+ EGLint width = attribs.getAsInt(EGL_WIDTH, 0);
+ EGLint height = attribs.getAsInt(EGL_HEIGHT, 0);
+ ASSERT(width != 0 && height != 0);
- switch (mode)
- {
- case GL_POINTS: primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; minCount = 1; break;
- case GL_LINES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; minCount = 2; break;
- case GL_LINE_LOOP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break;
- case GL_LINE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break;
- case GL_TRIANGLES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break;
- case GL_TRIANGLE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; minCount = 3; break;
- // emulate fans via rewriting index buffer
- case GL_TRIANGLE_FAN: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break;
- default:
- UNREACHABLE();
- return false;
- }
+ const d3d11::Format &backbufferFormatInfo =
+ d3d11::Format::Get(config->renderTargetFormat, getRenderer11DeviceCaps());
- // If instanced pointsprite emulation is being used and If gl_PointSize is used in the shader,
- // GL_POINTS mode is expected to render pointsprites.
- // Instanced PointSprite emulation requires that the topology to be D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST.
- if (mode == GL_POINTS && usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation)
+ if (desc.Width != static_cast<UINT>(width) || desc.Height != static_cast<UINT>(height) ||
+ desc.Format != backbufferFormatInfo.texFormat || desc.MipLevels != 1 || desc.ArraySize != 1)
{
- primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+ return egl::EglBadParameter() << "Invalid texture parameters in share handle texture.";
}
- if (primitiveTopology != mCurrentPrimitiveTopology)
- {
- mDeviceContext->IASetPrimitiveTopology(primitiveTopology);
- mCurrentPrimitiveTopology = primitiveTopology;
- }
-
- return count >= minCount;
+ return egl::NoError();
}
-gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer)
+SwapChainD3D *Renderer11::createSwapChain(NativeWindowD3D *nativeWindow,
+ HANDLE shareHandle,
+ IUnknown *d3dTexture,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation,
+ EGLint samples)
{
- return mStateManager.syncFramebuffer(framebuffer);
+ return new SwapChain11(this, GetAs<NativeWindow11>(nativeWindow), shareHandle, d3dTexture,
+ backBufferFormat, depthBufferFormat, orientation, samples);
}
-gl::Error Renderer11::applyVertexBuffer(const gl::State &state,
- GLenum mode,
- GLint first,
- GLsizei count,
- GLsizei instances,
- TranslatedIndexData *indexInfo)
+void *Renderer11::getD3DDevice()
{
- gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, &mTranslatedAttribCache, instances);
- if (error.isError())
- {
- return error;
- }
-
- // If index information is passed, mark it with the current changed status.
- if (indexInfo)
- {
- indexInfo->srcIndexData.srcIndicesChanged = mAppliedIBChanged;
- }
-
- GLsizei numIndicesPerInstance = 0;
- if (instances > 0)
- {
- numIndicesPerInstance = count;
- }
- return mInputLayoutCache.applyVertexBuffers(mTranslatedAttribCache, mode, state.getProgram(),
- indexInfo, numIndicesPerInstance);
+ return reinterpret_cast<void *>(mDevice);
}
-gl::Error Renderer11::applyIndexBuffer(const gl::Data &data,
- const GLvoid *indices,
- GLsizei count,
- GLenum mode,
- GLenum type,
- TranslatedIndexData *indexInfo)
+bool Renderer11::applyPrimitiveType(const gl::State &glState, GLenum mode, GLsizei count)
{
- gl::VertexArray *vao = data.state->getVertexArray();
- gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
- gl::Error error =
- mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo,
- data.state->isPrimitiveRestartEnabled());
- if (error.isError())
- {
- return error;
- }
-
- ID3D11Buffer *buffer = NULL;
- DXGI_FORMAT bufferFormat = (indexInfo->indexType == GL_UNSIGNED_INT) ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT;
-
- if (indexInfo->storage)
- {
- Buffer11 *storage = GetAs<Buffer11>(indexInfo->storage);
- buffer = storage->getBuffer(BUFFER_USAGE_INDEX);
- }
- else
- {
- IndexBuffer11* indexBuffer = GetAs<IndexBuffer11>(indexInfo->indexBuffer);
- buffer = indexBuffer->getBuffer();
- }
-
- mAppliedIBChanged = false;
- if (buffer != mAppliedIB || bufferFormat != mAppliedIBFormat || indexInfo->startOffset != mAppliedIBOffset)
- {
- mDeviceContext->IASetIndexBuffer(buffer, bufferFormat, indexInfo->startOffset);
-
- mAppliedIB = buffer;
- mAppliedIBFormat = bufferFormat;
- mAppliedIBOffset = indexInfo->startOffset;
- mAppliedIBChanged = true;
- }
-
- return gl::Error(GL_NO_ERROR);
-}
+ D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
-void Renderer11::applyTransformFeedbackBuffers(const gl::State &state)
-{
- size_t numXFBBindings = 0;
- bool requiresUpdate = false;
+ GLsizei minCount = 0;
- if (state.isTransformFeedbackActiveUnpaused())
+ switch (mode)
{
- const gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback();
- numXFBBindings = transformFeedback->getIndexedBufferCount();
- ASSERT(numXFBBindings <= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
-
- for (size_t i = 0; i < numXFBBindings; i++)
+ case GL_POINTS:
{
- const OffsetBindingPointer<gl::Buffer> &binding = transformFeedback->getIndexedBuffer(i);
-
- ID3D11Buffer *d3dBuffer = NULL;
- if (binding.get() != nullptr)
- {
- Buffer11 *storage = GetImplAs<Buffer11>(binding.get());
- d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
- }
+ bool usesPointSize = GetImplAs<ProgramD3D>(glState.getProgram())->usesPointSize();
- // TODO: mAppliedTFBuffers and friends should also be kept in a vector.
- if (d3dBuffer != mAppliedTFBuffers[i] || binding.getOffset() != mAppliedTFOffsets[i])
+ // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
+ // which affects varying interpolation. Since the value of gl_PointSize is
+ // undefined when not written, just skip drawing to avoid unexpected results.
+ if (!usesPointSize && !glState.isTransformFeedbackActiveUnpaused())
{
- requiresUpdate = true;
+ // Notify developers of risking undefined behavior.
+ WARN() << "Point rendering without writing to gl_PointSize.";
+ return false;
}
- }
- }
- if (requiresUpdate || numXFBBindings != mAppliedNumXFBBindings)
- {
- const gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback();
- for (size_t i = 0; i < numXFBBindings; ++i)
- {
- const OffsetBindingPointer<gl::Buffer> &binding = transformFeedback->getIndexedBuffer(i);
- if (binding.get() != nullptr)
+ // If instanced pointsprites are enabled and the shader uses gl_PointSize, the topology
+ // must be D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST.
+ if (usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation)
{
- Buffer11 *storage = GetImplAs<Buffer11>(binding.get());
- ID3D11Buffer *d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
-
- mCurrentD3DOffsets[i] = (mAppliedTFBuffers[i] != d3dBuffer || mAppliedTFOffsets[i] != binding.getOffset()) ?
- static_cast<UINT>(binding.getOffset()) : -1;
- mAppliedTFBuffers[i] = d3dBuffer;
+ primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
}
else
{
- mAppliedTFBuffers[i] = NULL;
- mCurrentD3DOffsets[i] = 0;
+ primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
}
- mAppliedTFOffsets[i] = binding.getOffset();
+ minCount = 1;
+ break;
}
+ case GL_LINES:
+ primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST;
+ minCount = 2;
+ break;
+ case GL_LINE_LOOP:
+ primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
+ minCount = 2;
+ break;
+ case GL_LINE_STRIP:
+ primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
+ minCount = 2;
+ break;
+ case GL_TRIANGLES:
+ primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+ minCount = CullsEverything(glState) ? std::numeric_limits<GLsizei>::max() : 3;
+ break;
+ case GL_TRIANGLE_STRIP:
+ primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
+ minCount = CullsEverything(glState) ? std::numeric_limits<GLsizei>::max() : 3;
+ break;
+ // emulate fans via rewriting index buffer
+ case GL_TRIANGLE_FAN:
+ primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+ minCount = CullsEverything(glState) ? std::numeric_limits<GLsizei>::max() : 3;
+ break;
+ default:
+ UNREACHABLE();
+ return false;
+ }
- mAppliedNumXFBBindings = numXFBBindings;
+ mStateManager.setPrimitiveTopology(primitiveTopology);
- mDeviceContext->SOSetTargets(static_cast<unsigned int>(numXFBBindings), mAppliedTFBuffers,
- mCurrentD3DOffsets);
- }
+ return count >= minCount;
}
-gl::Error Renderer11::drawArraysImpl(const gl::Data &data,
- GLenum mode,
- GLsizei count,
- GLsizei instances)
+gl::Error Renderer11::drawArrays(const gl::Context *context,
+ GLenum mode,
+ GLint startVertex,
+ GLsizei count,
+ GLsizei instances)
{
- ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram());
+ const auto &glState = context->getGLState();
- if (programD3D->usesGeometryShader(mode) && data.state->isTransformFeedbackActiveUnpaused())
+ if (!applyPrimitiveType(glState, mode, count))
+ {
+ return gl::NoError();
+ }
+
+ DrawCallVertexParams vertexParams(startVertex, count, instances);
+ ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, false));
+
+ if (glState.isTransformFeedbackActiveUnpaused())
+ {
+ ANGLE_TRY(markTransformFeedbackUsage(context));
+ }
+
+ gl::Program *program = glState.getProgram();
+ ASSERT(program != nullptr);
+ GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(program, instances);
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+
+ if (programD3D->usesGeometryShader(mode) && glState.isTransformFeedbackActiveUnpaused())
{
// Since we use a geometry if-and-only-if we rewrite vertex streams, transform feedback
// won't get the correct output. To work around this, draw with *only* the stream out
// first (no pixel shader) to feed the stream out buffers and then draw again with the
// geometry shader + pixel shader to rasterize the primitives.
- mDeviceContext->PSSetShader(nullptr, nullptr, 0);
+ mStateManager.setPixelShader(nullptr);
- if (instances > 0)
+ if (adjustedInstanceCount > 0)
{
- mDeviceContext->DrawInstanced(count, instances, 0, 0);
+ mDeviceContext->DrawInstanced(count, adjustedInstanceCount, 0, 0);
}
else
{
@@ -1673,203 +1561,330 @@ gl::Error Renderer11::drawArraysImpl(const gl::Data &data,
}
rx::ShaderExecutableD3D *pixelExe = nullptr;
- gl::Error error = programD3D->getPixelExecutableForFramebuffer(data.state->getDrawFramebuffer(), &pixelExe);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(&pixelExe, nullptr));
// Skip the draw call if rasterizer discard is enabled (or no fragment shader).
- if (!pixelExe || data.state->getRasterizerState().rasterizerDiscard)
+ if (!pixelExe || glState.getRasterizerState().rasterizerDiscard)
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
- ID3D11PixelShader *pixelShader = GetAs<ShaderExecutable11>(pixelExe)->getPixelShader();
- ASSERT(reinterpret_cast<uintptr_t>(pixelShader) == mAppliedPixelShader);
- mDeviceContext->PSSetShader(pixelShader, NULL, 0);
+ mStateManager.setPixelShader(&GetAs<ShaderExecutable11>(pixelExe)->getPixelShader());
// Retrieve the geometry shader.
rx::ShaderExecutableD3D *geometryExe = nullptr;
- error =
- programD3D->getGeometryExecutableForPrimitiveType(data, mode, &geometryExe, nullptr);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(context, mode, &geometryExe,
+ nullptr));
- ID3D11GeometryShader *geometryShader =
- (geometryExe ? GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : NULL);
- mAppliedGeometryShader = reinterpret_cast<uintptr_t>(geometryShader);
- ASSERT(geometryShader);
- mDeviceContext->GSSetShader(geometryShader, NULL, 0);
+ mStateManager.setGeometryShader(
+ &GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader());
- if (instances > 0)
+ if (adjustedInstanceCount > 0)
{
- mDeviceContext->DrawInstanced(count, instances, 0, 0);
+ mDeviceContext->DrawInstanced(count, adjustedInstanceCount, 0, 0);
}
else
{
mDeviceContext->Draw(count, 0);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
if (mode == GL_LINE_LOOP)
{
- return drawLineLoop(data, count, GL_NONE, nullptr, nullptr, instances);
+ return drawLineLoop(context, count, GL_NONE, nullptr, 0, adjustedInstanceCount);
}
if (mode == GL_TRIANGLE_FAN)
{
- return drawTriangleFan(data, count, GL_NONE, nullptr, 0, instances);
+ return drawTriangleFan(context, count, GL_NONE, nullptr, 0, adjustedInstanceCount);
}
bool useInstancedPointSpriteEmulation =
programD3D->usesPointSize() && getWorkarounds().useInstancedPointSpriteEmulation;
- if (instances > 0)
+ if (mode != GL_POINTS || !useInstancedPointSpriteEmulation)
{
- if (mode == GL_POINTS && useInstancedPointSpriteEmulation)
+ if (adjustedInstanceCount == 0)
{
- // If pointsprite emulation is used with glDrawArraysInstanced then we need to take a
- // less efficent code path.
- // Instanced rendering of emulated pointsprites requires a loop to draw each batch of
- // points. An offset into the instanced data buffer is calculated and applied on each
- // iteration to ensure all instances are rendered correctly.
-
- // Each instance being rendered requires the inputlayout cache to reapply buffers and
- // offsets.
- for (GLsizei i = 0; i < instances; i++)
- {
- gl::Error error = mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation(i);
- if (error.isError())
- {
- return error;
- }
-
- mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
- }
+ mDeviceContext->Draw(count, 0);
}
else
{
- mDeviceContext->DrawInstanced(count, instances, 0, 0);
+ mDeviceContext->DrawInstanced(count, adjustedInstanceCount, 0, 0);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
+ // This code should not be reachable by multi-view programs.
+ ASSERT(program->usesMultiview() == false);
+
// If the shader is writing to gl_PointSize, then pointsprites are being rendered.
// Emulating instanced point sprites for FL9_3 requires the topology to be
// D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead.
- if (mode == GL_POINTS && useInstancedPointSpriteEmulation)
+ if (adjustedInstanceCount == 0)
{
mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
+ return gl::NoError();
}
- else
+
+ // If pointsprite emulation is used with glDrawArraysInstanced then we need to take a less
+ // efficent code path. Instanced rendering of emulated pointsprites requires a loop to draw each
+ // batch of points. An offset into the instanced data buffer is calculated and applied on each
+ // iteration to ensure all instances are rendered correctly. Each instance being rendered
+ // requires the inputlayout cache to reapply buffers and offsets.
+ for (GLsizei i = 0; i < instances; i++)
{
- mDeviceContext->Draw(count, 0);
+ ANGLE_TRY(mStateManager.updateVertexOffsetsForPointSpritesEmulation(startVertex, i));
+ mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
}
- return gl::Error(GL_NO_ERROR);
+
+ // This required by updateVertexOffsets... above but is outside of the loop for speed.
+ mStateManager.invalidateVertexBuffer();
+ return gl::NoError();
}
-gl::Error Renderer11::drawElementsImpl(const gl::Data &data,
- const TranslatedIndexData &indexInfo,
- GLenum mode,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- GLsizei instances)
+gl::Error Renderer11::drawElements(const gl::Context *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei instances)
{
- int minIndex = static_cast<int>(indexInfo.indexRange.start);
+ const auto &glState = context->getGLState();
+
+ if (!applyPrimitiveType(glState, mode, count))
+ {
+ return gl::NoError();
+ }
+
+ // Transform feedback is not allowed for DrawElements, this error should have been caught at the
+ // API validation layer.
+ ASSERT(!glState.isTransformFeedbackActiveUnpaused());
+
+ const auto &lazyIndexRange = context->getParams<gl::HasIndexRange>();
+
+ bool usePrimitiveRestartWorkaround =
+ UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), type);
+ DrawCallVertexParams vertexParams(!usePrimitiveRestartWorkaround, lazyIndexRange, 0, instances);
+
+ ANGLE_TRY(mStateManager.applyIndexBuffer(context, indices, count, type, lazyIndexRange,
+ usePrimitiveRestartWorkaround));
+ ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, true));
+
+ int startVertex = static_cast<int>(vertexParams.firstVertex());
+ int baseVertex = -startVertex;
+
+ const gl::Program *program = glState.getProgram();
+ GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(program, instances);
if (mode == GL_LINE_LOOP)
{
- return drawLineLoop(data, count, type, indices, &indexInfo, instances);
+ return drawLineLoop(context, count, type, indices, baseVertex, adjustedInstanceCount);
}
if (mode == GL_TRIANGLE_FAN)
{
- return drawTriangleFan(data, count, type, indices, minIndex, instances);
+ return drawTriangleFan(context, count, type, indices, baseVertex, adjustedInstanceCount);
}
- const ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram());
- if (instances > 0)
+ const ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
+
+ if (mode != GL_POINTS || !programD3D->usesInstancedPointSpriteEmulation())
{
- if (mode == GL_POINTS && programD3D->usesInstancedPointSpriteEmulation())
+ if (adjustedInstanceCount == 0)
{
- // If pointsprite emulation is used with glDrawElementsInstanced then we need to take a
- // less efficent code path.
- // Instanced rendering of emulated pointsprites requires a loop to draw each batch of
- // points. An offset into the instanced data buffer is calculated and applied on each
- // iteration to ensure all instances are rendered correctly.
- GLsizei elementsToRender = static_cast<GLsizei>(indexInfo.indexRange.vertexCount());
-
- // Each instance being rendered requires the inputlayout cache to reapply buffers and
- // offsets.
- for (GLsizei i = 0; i < instances; i++)
- {
- gl::Error error = mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation(i);
- if (error.isError())
- {
- return error;
- }
-
- mDeviceContext->DrawIndexedInstanced(6, elementsToRender, 0, 0, 0);
- }
+ mDeviceContext->DrawIndexed(count, 0, baseVertex);
}
else
{
- mDeviceContext->DrawIndexedInstanced(count, instances, 0, -minIndex, 0);
+ mDeviceContext->DrawIndexedInstanced(count, adjustedInstanceCount, 0, baseVertex, 0);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
+ // This code should not be reachable by multi-view programs.
+ ASSERT(program->usesMultiview() == false);
+
// If the shader is writing to gl_PointSize, then pointsprites are being rendered.
// Emulating instanced point sprites for FL9_3 requires the topology to be
// D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead.
- if (mode == GL_POINTS && programD3D->usesInstancedPointSpriteEmulation())
- {
- // The count parameter passed to drawElements represents the total number of instances
- // to be rendered. Each instance is referenced by the bound index buffer from the
- // the caller.
- //
- // Indexed pointsprite emulation replicates data for duplicate entries found
- // in the index buffer.
- // This is not an efficent rendering mechanism and is only used on downlevel renderers
- // that do not support geometry shaders.
+ //
+ // The count parameter passed to drawElements represents the total number of instances to be
+ // rendered. Each instance is referenced by the bound index buffer from the the caller.
+ //
+ // Indexed pointsprite emulation replicates data for duplicate entries found in the index
+ // buffer. This is not an efficent rendering mechanism and is only used on downlevel renderers
+ // that do not support geometry shaders.
+ if (instances == 0)
+ {
mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
+ return gl::NoError();
}
- else
+
+ // If pointsprite emulation is used with glDrawElementsInstanced then we need to take a less
+ // efficent code path. Instanced rendering of emulated pointsprites requires a loop to draw each
+ // batch of points. An offset into the instanced data buffer is calculated and applied on each
+ // iteration to ensure all instances are rendered correctly.
+ GLsizei elementsToRender = vertexParams.vertexCount();
+
+ // Each instance being rendered requires the inputlayout cache to reapply buffers and offsets.
+ for (GLsizei i = 0; i < instances; i++)
+ {
+ ANGLE_TRY(mStateManager.updateVertexOffsetsForPointSpritesEmulation(startVertex, i));
+ mDeviceContext->DrawIndexedInstanced(6, elementsToRender, 0, 0, 0);
+ }
+ mStateManager.invalidateVertexBuffer();
+ return gl::NoError();
+}
+
+gl::Error Renderer11::drawArraysIndirect(const gl::Context *context,
+ GLenum mode,
+ const void *indirect)
+{
+ const auto &glState = context->getGLState();
+ ASSERT(!glState.isTransformFeedbackActiveUnpaused());
+
+ if (!applyPrimitiveType(glState, mode, std::numeric_limits<int>::max() - 1))
+ {
+ return gl::NoError();
+ }
+
+ gl::Buffer *drawIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
+ ASSERT(drawIndirectBuffer);
+ Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer);
+ uintptr_t offset = reinterpret_cast<uintptr_t>(indirect);
+
+ if (!DrawCallNeedsTranslation(context, mode))
+ {
+ DrawCallVertexParams vertexParams(0, 0, 0);
+ ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, false));
+ ID3D11Buffer *buffer = nullptr;
+ ANGLE_TRY_RESULT(storage->getBuffer(context, BUFFER_USAGE_INDIRECT), buffer);
+ mDeviceContext->DrawInstancedIndirect(buffer, static_cast<unsigned int>(offset));
+ return gl::NoError();
+ }
+
+ const uint8_t *bufferData = nullptr;
+ ANGLE_TRY(storage->getData(context, &bufferData));
+ ASSERT(bufferData);
+ const gl::DrawArraysIndirectCommand *args =
+ reinterpret_cast<const gl::DrawArraysIndirectCommand *>(bufferData + offset);
+ GLuint count = args->count;
+ GLuint instances = args->instanceCount;
+ GLuint first = args->first;
+
+ DrawCallVertexParams vertexParams(first, count, instances);
+ ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, false));
+
+ if (mode == GL_LINE_LOOP)
+ {
+ return drawLineLoop(context, count, GL_NONE, nullptr, 0, instances);
+ }
+ if (mode == GL_TRIANGLE_FAN)
+ {
+ return drawTriangleFan(context, count, GL_NONE, nullptr, 0, instances);
+ }
+
+ mDeviceContext->DrawInstanced(count, instances, 0, 0);
+ return gl::NoError();
+}
+
+gl::Error Renderer11::drawElementsIndirect(const gl::Context *context,
+ GLenum mode,
+ GLenum type,
+ const void *indirect)
+{
+ const auto &glState = context->getGLState();
+ ASSERT(!glState.isTransformFeedbackActiveUnpaused());
+
+ if (!applyPrimitiveType(glState, mode, std::numeric_limits<int>::max() - 1))
+ {
+ return gl::NoError();
+ }
+
+ gl::Buffer *drawIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
+ ASSERT(drawIndirectBuffer);
+ Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer);
+ uintptr_t offset = reinterpret_cast<uintptr_t>(indirect);
+
+ // TODO(jmadill): Remove the if statement and compute indirect parameters lazily.
+ bool usePrimitiveRestartWorkaround =
+ UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), type);
+
+ if (!DrawCallNeedsTranslation(context, mode) && !IsStreamingIndexData(context, type))
+ {
+ ANGLE_TRY(mStateManager.applyIndexBuffer(context, nullptr, 0, type, gl::HasIndexRange(),
+ usePrimitiveRestartWorkaround));
+ DrawCallVertexParams vertexParams(0, 0, 0);
+ ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, true));
+ ID3D11Buffer *buffer = nullptr;
+ ANGLE_TRY_RESULT(storage->getBuffer(context, BUFFER_USAGE_INDIRECT), buffer);
+ mDeviceContext->DrawIndexedInstancedIndirect(buffer, static_cast<unsigned int>(offset));
+ return gl::NoError();
+ }
+
+ const uint8_t *bufferData = nullptr;
+ ANGLE_TRY(storage->getData(context, &bufferData));
+ ASSERT(bufferData);
+
+ const gl::DrawElementsIndirectCommand *cmd =
+ reinterpret_cast<const gl::DrawElementsIndirectCommand *>(bufferData + offset);
+ GLsizei count = cmd->count;
+ GLuint instances = cmd->primCount;
+ GLuint firstIndex = cmd->firstIndex;
+ GLint baseVertex = cmd->baseVertex;
+
+ // TODO(jmadill): Fix const cast.
+ const gl::Type &typeInfo = gl::GetTypeInfo(type);
+ const void *indices =
+ reinterpret_cast<const void *>(static_cast<uintptr_t>(firstIndex * typeInfo.bytes));
+ gl::HasIndexRange lazyIndexRange(const_cast<gl::Context *>(context), count, type, indices);
+
+ ANGLE_TRY(mStateManager.applyIndexBuffer(context, indices, count, type, lazyIndexRange,
+ usePrimitiveRestartWorkaround));
+
+ DrawCallVertexParams vertexParams(false, lazyIndexRange, baseVertex, instances);
+
+ ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, true));
+
+ int baseVertexLocation = -static_cast<int>(lazyIndexRange.getIndexRange().value().start);
+
+ if (mode == GL_LINE_LOOP)
{
- mDeviceContext->DrawIndexed(count, 0, -minIndex);
+ return drawLineLoop(context, count, type, indices, baseVertexLocation, instances);
}
- return gl::Error(GL_NO_ERROR);
+
+ if (mode == GL_TRIANGLE_FAN)
+ {
+ return drawTriangleFan(context, count, type, indices, baseVertexLocation, instances);
+ }
+
+ mDeviceContext->DrawIndexedInstanced(count, instances, 0, baseVertexLocation, 0);
+ return gl::NoError();
}
-gl::Error Renderer11::drawLineLoop(const gl::Data &data,
+gl::Error Renderer11::drawLineLoop(const gl::Context *context,
GLsizei count,
GLenum type,
- const GLvoid *indexPointer,
- const TranslatedIndexData *indexInfo,
+ const void *indexPointer,
+ int baseVertex,
int instances)
{
- gl::VertexArray *vao = data.state->getVertexArray();
+ const gl::State &glState = context->getGLState();
+ gl::VertexArray *vao = glState.getVertexArray();
gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
- const GLvoid *indices = indexPointer;
+ const void *indices = indexPointer;
// Get the raw indices for an indexed draw
if (type != GL_NONE && elementArrayBuffer)
{
BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
- intptr_t offset = reinterpret_cast<intptr_t>(indices);
+ intptr_t offset = reinterpret_cast<intptr_t>(indices);
- const uint8_t *bufferData = NULL;
- gl::Error error = storage->getData(&bufferData);
- if (error.isError())
- {
- return error;
- }
+ const uint8_t *bufferData = nullptr;
+ ANGLE_TRY(storage->getData(context, &bufferData));
indices = bufferData + offset;
}
@@ -1877,7 +1892,8 @@ gl::Error Renderer11::drawLineLoop(const gl::Data &data,
if (!mLineLoopIB)
{
mLineLoopIB = new StreamingIndexBufferInterface(this);
- gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
+ gl::Error error =
+ mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
if (error.isError())
{
SafeDelete(mLineLoopIB);
@@ -1888,92 +1904,71 @@ gl::Error Renderer11::drawLineLoop(const gl::Data &data,
// Checked by Renderer11::applyPrimitiveType
ASSERT(count >= 0);
- if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
+ if (static_cast<unsigned int>(count) + 1 >
+ (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
+ return gl::OutOfMemory() << "Failed to create a 32-bit looping index buffer for "
+ "GL_LINE_LOOP, too many indices required.";
}
GetLineLoopIndices(indices, type, static_cast<GLuint>(count),
- data.state->isPrimitiveRestartEnabled(), &mScratchIndexDataBuffer);
+ glState.isPrimitiveRestartEnabled(), &mScratchIndexDataBuffer);
unsigned int spaceNeeded =
static_cast<unsigned int>(sizeof(GLuint) * mScratchIndexDataBuffer.size());
- gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT));
- void* mappedMemory = NULL;
+ void *mappedMemory = nullptr;
unsigned int offset;
- error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset));
// Copy over the converted index data.
memcpy(mappedMemory, &mScratchIndexDataBuffer[0],
sizeof(GLuint) * mScratchIndexDataBuffer.size());
- error = mLineLoopIB->unmapBuffer();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mLineLoopIB->unmapBuffer());
- IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(mLineLoopIB->getIndexBuffer());
- ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer();
- DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat();
+ IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(mLineLoopIB->getIndexBuffer());
+ const d3d11::Buffer &d3dIndexBuffer = indexBuffer->getBuffer();
+ DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat();
- if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat ||
- mAppliedIBOffset != offset)
- {
- mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, offset);
- mAppliedIB = d3dIndexBuffer;
- mAppliedIBFormat = indexFormat;
- mAppliedIBOffset = offset;
- }
+ mStateManager.setIndexBuffer(d3dIndexBuffer.get(), indexFormat, offset);
- INT baseVertexLocation = (indexInfo ? -static_cast<int>(indexInfo->indexRange.start) : 0);
UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size());
if (instances > 0)
{
- mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertexLocation, 0);
+ mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertex, 0);
}
else
{
- mDeviceContext->DrawIndexed(indexCount, 0, baseVertexLocation);
+ mDeviceContext->DrawIndexed(indexCount, 0, baseVertex);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Renderer11::drawTriangleFan(const gl::Data &data,
+gl::Error Renderer11::drawTriangleFan(const gl::Context *context,
GLsizei count,
GLenum type,
- const GLvoid *indices,
- int minIndex,
+ const void *indices,
+ int baseVertex,
int instances)
{
- gl::VertexArray *vao = data.state->getVertexArray();
+ const gl::State &glState = context->getGLState();
+ gl::VertexArray *vao = glState.getVertexArray();
gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
- const GLvoid *indexPointer = indices;
+ const void *indexPointer = indices;
// Get the raw indices for an indexed draw
if (type != GL_NONE && elementArrayBuffer)
{
BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
- intptr_t offset = reinterpret_cast<intptr_t>(indices);
+ intptr_t offset = reinterpret_cast<intptr_t>(indices);
- const uint8_t *bufferData = NULL;
- gl::Error error = storage->getData(&bufferData);
- if (error.isError())
- {
- return error;
- }
+ const uint8_t *bufferData = nullptr;
+ ANGLE_TRY(storage->getData(context, &bufferData));
indexPointer = bufferData + offset;
}
@@ -1981,7 +1976,8 @@ gl::Error Renderer11::drawTriangleFan(const gl::Data &data,
if (!mTriangleFanIB)
{
mTriangleFanIB = new StreamingIndexBufferInterface(this);
- gl::Error error = mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
+ gl::Error error =
+ mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
if (error.isError())
{
SafeDelete(mTriangleFanIB);
@@ -1996,386 +1992,50 @@ gl::Error Renderer11::drawTriangleFan(const gl::Data &data,
if (numTris > (std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3)))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required.");
+ return gl::OutOfMemory() << "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, "
+ "too many indices required.";
}
- GetTriFanIndices(indexPointer, type, count, data.state->isPrimitiveRestartEnabled(),
+ GetTriFanIndices(indexPointer, type, count, glState.isPrimitiveRestartEnabled(),
&mScratchIndexDataBuffer);
const unsigned int spaceNeeded =
static_cast<unsigned int>(mScratchIndexDataBuffer.size() * sizeof(unsigned int));
- gl::Error error = mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT));
void *mappedMemory = nullptr;
unsigned int offset;
- error = mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset));
memcpy(mappedMemory, &mScratchIndexDataBuffer[0], spaceNeeded);
- error = mTriangleFanIB->unmapBuffer();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mTriangleFanIB->unmapBuffer());
- IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(mTriangleFanIB->getIndexBuffer());
- ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer();
- DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat();
+ IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(mTriangleFanIB->getIndexBuffer());
+ const d3d11::Buffer &d3dIndexBuffer = indexBuffer->getBuffer();
+ DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat();
- if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat ||
- mAppliedIBOffset != offset)
- {
- mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, offset);
- mAppliedIB = d3dIndexBuffer;
- mAppliedIBFormat = indexFormat;
- mAppliedIBOffset = offset;
- }
+ mStateManager.setIndexBuffer(d3dIndexBuffer.get(), indexFormat, offset);
UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size());
if (instances > 0)
{
- mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, -minIndex, 0);
+ mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertex, 0);
}
else
{
- mDeviceContext->DrawIndexed(indexCount, 0, -minIndex);
+ mDeviceContext->DrawIndexed(indexCount, 0, baseVertex);
}
- return gl::Error(GL_NO_ERROR);
-}
-
-gl::Error Renderer11::applyShadersImpl(const gl::Data &data, GLenum drawMode)
-{
- ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram());
- const auto &inputLayout = programD3D->getCachedInputLayout();
-
- ShaderExecutableD3D *vertexExe = NULL;
- gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe, nullptr);
- if (error.isError())
- {
- return error;
- }
-
- const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer();
- ShaderExecutableD3D *pixelExe = NULL;
- error = programD3D->getPixelExecutableForFramebuffer(drawFramebuffer, &pixelExe);
- if (error.isError())
- {
- return error;
- }
-
- ShaderExecutableD3D *geometryExe = nullptr;
- error =
- programD3D->getGeometryExecutableForPrimitiveType(data, drawMode, &geometryExe, nullptr);
- if (error.isError())
- {
- return error;
- }
-
- ID3D11VertexShader *vertexShader = (vertexExe ? GetAs<ShaderExecutable11>(vertexExe)->getVertexShader() : NULL);
-
- ID3D11PixelShader *pixelShader = NULL;
- // Skip pixel shader if we're doing rasterizer discard.
- bool rasterizerDiscard = data.state->getRasterizerState().rasterizerDiscard;
- if (!rasterizerDiscard)
- {
- pixelShader = (pixelExe ? GetAs<ShaderExecutable11>(pixelExe)->getPixelShader() : NULL);
- }
-
- ID3D11GeometryShader *geometryShader = NULL;
- bool transformFeedbackActive = data.state->isTransformFeedbackActiveUnpaused();
- if (transformFeedbackActive)
- {
- geometryShader = (vertexExe ? GetAs<ShaderExecutable11>(vertexExe)->getStreamOutShader() : NULL);
- }
- else
- {
- geometryShader = (geometryExe ? GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : NULL);
- }
-
- bool dirtyUniforms = false;
-
- if (reinterpret_cast<uintptr_t>(vertexShader) != mAppliedVertexShader)
- {
- mDeviceContext->VSSetShader(vertexShader, NULL, 0);
- mAppliedVertexShader = reinterpret_cast<uintptr_t>(vertexShader);
- dirtyUniforms = true;
- }
-
- if (reinterpret_cast<uintptr_t>(geometryShader) != mAppliedGeometryShader)
- {
- mDeviceContext->GSSetShader(geometryShader, NULL, 0);
- mAppliedGeometryShader = reinterpret_cast<uintptr_t>(geometryShader);
- dirtyUniforms = true;
- }
-
- if (reinterpret_cast<uintptr_t>(pixelShader) != mAppliedPixelShader)
- {
- mDeviceContext->PSSetShader(pixelShader, NULL, 0);
- mAppliedPixelShader = reinterpret_cast<uintptr_t>(pixelShader);
- dirtyUniforms = true;
- }
-
- if (dirtyUniforms)
- {
- programD3D->dirtyAllUniforms();
- }
-
- return gl::Error(GL_NO_ERROR);
-}
-
-gl::Error Renderer11::applyUniforms(const ProgramD3D &programD3D,
- GLenum drawMode,
- const std::vector<D3DUniform *> &uniformArray)
-{
- unsigned int totalRegisterCountVS = 0;
- unsigned int totalRegisterCountPS = 0;
-
- bool vertexUniformsDirty = false;
- bool pixelUniformsDirty = false;
-
- for (const D3DUniform *uniform : uniformArray)
- {
- if (uniform->isReferencedByVertexShader() && !uniform->isSampler())
- {
- totalRegisterCountVS += uniform->registerCount;
- vertexUniformsDirty = (vertexUniformsDirty || uniform->dirty);
- }
-
- if (uniform->isReferencedByFragmentShader() && !uniform->isSampler())
- {
- totalRegisterCountPS += uniform->registerCount;
- pixelUniformsDirty = (pixelUniformsDirty || uniform->dirty);
- }
- }
-
- const UniformStorage11 *vertexUniformStorage =
- GetAs<UniformStorage11>(&programD3D.getVertexUniformStorage());
- const UniformStorage11 *fragmentUniformStorage =
- GetAs<UniformStorage11>(&programD3D.getFragmentUniformStorage());
- ASSERT(vertexUniformStorage);
- ASSERT(fragmentUniformStorage);
-
- ID3D11Buffer *vertexConstantBuffer = vertexUniformStorage->getConstantBuffer();
- ID3D11Buffer *pixelConstantBuffer = fragmentUniformStorage->getConstantBuffer();
-
- float (*mapVS)[4] = NULL;
- float (*mapPS)[4] = NULL;
-
- if (totalRegisterCountVS > 0 && vertexUniformsDirty)
- {
- D3D11_MAPPED_SUBRESOURCE map = {0};
- HRESULT result = mDeviceContext->Map(vertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
- UNUSED_ASSERTION_VARIABLE(result);
- ASSERT(SUCCEEDED(result));
- mapVS = (float(*)[4])map.pData;
- }
-
- if (totalRegisterCountPS > 0 && pixelUniformsDirty)
- {
- D3D11_MAPPED_SUBRESOURCE map = {0};
- HRESULT result = mDeviceContext->Map(pixelConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
- UNUSED_ASSERTION_VARIABLE(result);
- ASSERT(SUCCEEDED(result));
- mapPS = (float(*)[4])map.pData;
- }
-
- for (const D3DUniform *uniform : uniformArray)
- {
- if (uniform->isSampler())
- continue;
-
- unsigned int componentCount = (4 - uniform->registerElement);
-
- // we assume that uniforms from structs are arranged in struct order in our uniforms list.
- // otherwise we would overwrite previously written regions of memory.
-
- if (uniform->isReferencedByVertexShader() && mapVS)
- {
- memcpy(&mapVS[uniform->vsRegisterIndex][uniform->registerElement], uniform->data,
- uniform->registerCount * sizeof(float) * componentCount);
- }
-
- if (uniform->isReferencedByFragmentShader() && mapPS)
- {
- memcpy(&mapPS[uniform->psRegisterIndex][uniform->registerElement], uniform->data,
- uniform->registerCount * sizeof(float) * componentCount);
- }
- }
-
- if (mapVS)
- {
- mDeviceContext->Unmap(vertexConstantBuffer, 0);
- }
-
- if (mapPS)
- {
- mDeviceContext->Unmap(pixelConstantBuffer, 0);
- }
-
- if (mCurrentVertexConstantBuffer != vertexConstantBuffer)
- {
- mDeviceContext->VSSetConstantBuffers(0, 1, &vertexConstantBuffer);
- mCurrentVertexConstantBuffer = vertexConstantBuffer;
- }
-
- if (mCurrentPixelConstantBuffer != pixelConstantBuffer)
- {
- mDeviceContext->PSSetConstantBuffers(0, 1, &pixelConstantBuffer);
- mCurrentPixelConstantBuffer = pixelConstantBuffer;
- }
-
- // Driver uniforms
- if (!mDriverConstantBufferVS)
- {
- D3D11_BUFFER_DESC constantBufferDescription = {0};
- constantBufferDescription.ByteWidth = sizeof(dx_VertexConstants11);
- constantBufferDescription.Usage = D3D11_USAGE_DEFAULT;
- constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
- constantBufferDescription.CPUAccessFlags = 0;
- constantBufferDescription.MiscFlags = 0;
- constantBufferDescription.StructureByteStride = 0;
-
- HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferVS);
- ASSERT(SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create vertex shader constant buffer, result: 0x%X.", result);
- }
- mDeviceContext->VSSetConstantBuffers(1, 1, &mDriverConstantBufferVS);
- }
-
- if (!mDriverConstantBufferPS)
- {
- D3D11_BUFFER_DESC constantBufferDescription = {0};
- constantBufferDescription.ByteWidth = sizeof(dx_PixelConstants11);
- constantBufferDescription.Usage = D3D11_USAGE_DEFAULT;
- constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
- constantBufferDescription.CPUAccessFlags = 0;
- constantBufferDescription.MiscFlags = 0;
- constantBufferDescription.StructureByteStride = 0;
-
- HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferPS);
- ASSERT(SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create pixel shader constant buffer, result: 0x%X.", result);
- }
- mDeviceContext->PSSetConstantBuffers(1, 1, &mDriverConstantBufferPS);
- }
-
- const dx_VertexConstants11 &vertexConstants = mStateManager.getVertexConstants();
- if (memcmp(&vertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants11)) != 0)
- {
- ASSERT(mDriverConstantBufferVS != nullptr);
- if (mDriverConstantBufferVS)
- {
- mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &vertexConstants,
- 16, 0);
- memcpy(&mAppliedVertexConstants, &vertexConstants, sizeof(dx_VertexConstants11));
- }
- }
-
- const dx_PixelConstants11 &pixelConstants = mStateManager.getPixelConstants();
- if (memcmp(&pixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants11)) != 0)
- {
- ASSERT(mDriverConstantBufferPS != nullptr);
- if (mDriverConstantBufferPS)
- {
- mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &pixelConstants, 16,
- 0);
- memcpy(&mAppliedPixelConstants, &pixelConstants, sizeof(dx_PixelConstants11));
- }
- }
-
- // GSSetConstantBuffers triggers device removal on 9_3, so we should only call it if necessary
- if (programD3D.usesGeometryShader(drawMode))
- {
- // needed for the point sprite geometry shader
- if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS)
- {
- ASSERT(mDriverConstantBufferPS != nullptr);
- if (mDriverConstantBufferPS)
- {
- mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS);
- mCurrentGeometryConstantBuffer = mDriverConstantBufferPS;
- }
- }
- }
-
- return gl::Error(GL_NO_ERROR);
-}
-
-void Renderer11::markAllStateDirty()
-{
- TRACE_EVENT0("gpu.angle", "Renderer11::markAllStateDirty");
-
- for (size_t vsamplerId = 0; vsamplerId < mForceSetVertexSamplerStates.size(); ++vsamplerId)
- {
- mForceSetVertexSamplerStates[vsamplerId] = true;
- }
-
- for (size_t fsamplerId = 0; fsamplerId < mForceSetPixelSamplerStates.size(); ++fsamplerId)
- {
- mForceSetPixelSamplerStates[fsamplerId] = true;
- }
-
- mStateManager.invalidateEverything();
-
- mAppliedIB = NULL;
- mAppliedIBFormat = DXGI_FORMAT_UNKNOWN;
- mAppliedIBOffset = 0;
-
- mAppliedVertexShader = angle::DirtyPointer;
- mAppliedGeometryShader = angle::DirtyPointer;
- mAppliedPixelShader = angle::DirtyPointer;
-
- mAppliedNumXFBBindings = static_cast<size_t>(-1);
-
- for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
- {
- mAppliedTFBuffers[i] = NULL;
- mAppliedTFOffsets[i] = 0;
- }
-
- memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants11));
- memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants11));
-
- mInputLayoutCache.markDirty();
-
- for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; i++)
- {
- mCurrentConstantBufferVS[i] = static_cast<unsigned int>(-1);
- mCurrentConstantBufferVSOffset[i] = 0;
- mCurrentConstantBufferVSSize[i] = 0;
- mCurrentConstantBufferPS[i] = static_cast<unsigned int>(-1);
- mCurrentConstantBufferPSOffset[i] = 0;
- mCurrentConstantBufferPSSize[i] = 0;
- }
-
- mCurrentVertexConstantBuffer = NULL;
- mCurrentPixelConstantBuffer = NULL;
- mCurrentGeometryConstantBuffer = NULL;
-
- mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
+ return gl::NoError();
}
void Renderer11::releaseDeviceResources()
{
+ mStateManager.deinitialize();
mStateCache.clear();
- mInputLayoutCache.clear();
- SafeDelete(mVertexDataManager);
- SafeDelete(mIndexDataManager);
SafeDelete(mLineLoopIB);
SafeDelete(mTriangleFanIB);
SafeDelete(mBlit);
@@ -2383,9 +2043,9 @@ void Renderer11::releaseDeviceResources()
SafeDelete(mTrim);
SafeDelete(mPixelTransfer);
- SafeRelease(mDriverConstantBufferVS);
- SafeRelease(mDriverConstantBufferPS);
- SafeRelease(mSyncQuery);
+ mSyncQuery.reset();
+
+ mCachedResolveTexture.reset();
}
// set notify to true to broadcast a message to all contexts of the device loss
@@ -2393,24 +2053,18 @@ bool Renderer11::testDeviceLost()
{
bool isLost = false;
+ if (!mDevice)
+ {
+ return true;
+ }
+
// GetRemovedReason is used to test if the device is removed
HRESULT result = mDevice->GetDeviceRemovedReason();
- isLost = d3d11::isDeviceLostError(result);
+ isLost = d3d11::isDeviceLostError(result);
if (isLost)
{
- // Log error if this is a new device lost event
- if (mDeviceLost == false)
- {
- ERR("The D3D11 device was removed: 0x%08X", result);
- }
-
- // ensure we note the device loss --
- // we'll probably get this done again by notifyDeviceLost
- // but best to remember it!
- // Note that we don't want to clear the device loss status here
- // -- this needs to be done by resetDevice
- mDeviceLost = true;
+ ERR() << "The D3D11 device was removed, " << gl::FmtHR(result);
}
return isLost;
@@ -2419,27 +2073,24 @@ bool Renderer11::testDeviceLost()
bool Renderer11::testDeviceResettable()
{
// determine if the device is resettable by creating a dummy device
- PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
+ PFN_D3D11_CREATE_DEVICE D3D11CreateDevice =
+ (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
- if (D3D11CreateDevice == NULL)
+ if (D3D11CreateDevice == nullptr)
{
return false;
}
- ID3D11Device* dummyDevice;
+ ID3D11Device *dummyDevice;
D3D_FEATURE_LEVEL dummyFeatureLevel;
- ID3D11DeviceContext* dummyContext;
+ ID3D11DeviceContext *dummyContext;
+ UINT flags = (mCreateDebugDevice ? D3D11_CREATE_DEVICE_DEBUG : 0);
ASSERT(mRequestedDriverType != D3D_DRIVER_TYPE_UNKNOWN);
HRESULT result = D3D11CreateDevice(
- NULL, mRequestedDriverType, NULL,
- #if defined(_DEBUG)
- D3D11_CREATE_DEVICE_DEBUG,
- #else
- 0,
- #endif
- mAvailableFeatureLevels.data(), static_cast<unsigned int>(mAvailableFeatureLevels.size()),
- D3D11_SDK_VERSION, &dummyDevice, &dummyFeatureLevel, &dummyContext);
+ nullptr, mRequestedDriverType, nullptr, flags, mAvailableFeatureLevels.data(),
+ static_cast<unsigned int>(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION, &dummyDevice,
+ &dummyFeatureLevel, &dummyContext);
if (!mDevice || FAILED(result))
{
@@ -2456,6 +2107,14 @@ void Renderer11::release()
{
RendererD3D::cleanup();
+ mScratchMemoryBuffer.clear();
+
+ if (mAnnotator != nullptr)
+ {
+ gl::UninitializeDebugAnnotations();
+ SafeDelete(mAnnotator);
+ }
+
releaseDeviceResources();
if (!mCreatedWithDeviceEXT)
@@ -2468,9 +2127,8 @@ void Renderer11::release()
SafeRelease(mDxgiFactory);
SafeRelease(mDxgiAdapter);
-#if defined(ANGLE_ENABLE_D3D11_1)
+ SafeRelease(mDeviceContext3);
SafeRelease(mDeviceContext1);
-#endif
if (mDeviceContext)
{
@@ -2480,26 +2138,24 @@ void Renderer11::release()
}
SafeRelease(mDevice);
-#if !defined(ANGLE_MINGW32_COMPAT)
SafeRelease(mDebug);
-#endif
if (mD3d11Module)
{
FreeLibrary(mD3d11Module);
- mD3d11Module = NULL;
+ mD3d11Module = nullptr;
}
if (mDxgiModule)
{
FreeLibrary(mDxgiModule);
- mDxgiModule = NULL;
+ mDxgiModule = nullptr;
}
if (mDCompModule)
{
FreeLibrary(mDCompModule);
- mDCompModule = NULL;
+ mDCompModule = nullptr;
}
mCompiler.release();
@@ -2515,12 +2171,10 @@ bool Renderer11::resetDevice()
if (result.isError())
{
- ERR("Could not reinitialize D3D11 device: %08X", result.getCode());
+ ERR() << "Could not reinitialize D3D11 device: " << result;
return false;
}
- mDeviceLost = false;
-
return true;
}
@@ -2531,8 +2185,10 @@ std::string Renderer11::getRendererDescription() const
rendererString << mDescription;
rendererString << " Direct3D11";
- rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel() << getShaderModelSuffix();
- rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel() << getShaderModelSuffix();
+ rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel()
+ << getShaderModelSuffix();
+ rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel()
+ << getShaderModelSuffix();
return rendererString.str();
}
@@ -2540,12 +2196,12 @@ std::string Renderer11::getRendererDescription() const
DeviceIdentifier Renderer11::getAdapterIdentifier() const
{
// Don't use the AdapterLuid here, since that doesn't persist across reboot.
- DeviceIdentifier deviceIdentifier = { 0 };
- deviceIdentifier.VendorId = mAdapterDescription.VendorId;
- deviceIdentifier.DeviceId = mAdapterDescription.DeviceId;
- deviceIdentifier.SubSysId = mAdapterDescription.SubSysId;
- deviceIdentifier.Revision = mAdapterDescription.Revision;
- deviceIdentifier.FeatureLevel = static_cast<UINT>(mRenderer11DeviceCaps.featureLevel);
+ DeviceIdentifier deviceIdentifier = {0};
+ deviceIdentifier.VendorId = mAdapterDescription.VendorId;
+ deviceIdentifier.DeviceId = mAdapterDescription.DeviceId;
+ deviceIdentifier.SubSysId = mAdapterDescription.SubSysId;
+ deviceIdentifier.Revision = mAdapterDescription.Revision;
+ deviceIdentifier.FeatureLevel = static_cast<UINT>(mRenderer11DeviceCaps.featureLevel);
return deviceIdentifier;
}
@@ -2605,7 +2261,7 @@ bool Renderer11::getShareHandleSupport() const
// We only currently support share handles with BGRA surfaces, because
// chrome needs BGRA. Once chrome fixes this, we should always support them.
- if (!getRendererExtensions().textureFormatBGRA8888)
+ if (!getNativeExtensions().textureFormatBGRA8888)
{
mSupportsShareHandles = false;
return false;
@@ -2620,7 +2276,8 @@ bool Renderer11::getShareHandleSupport() const
// Qt: we don't care about the 9_3 limitation
#if 0
- // Also disable share handles on Feature Level 9_3, since it doesn't support share handles on RGBA8 textures/swapchains.
+ // Also disable share handles on Feature Level 9_3, since it doesn't support share handles on
+ // RGBA8 textures/swapchains.
if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3)
{
mSupportsShareHandles = false;
@@ -2668,15 +2325,34 @@ bool Renderer11::getShareHandleSupport() const
return true;
}
+bool Renderer11::getNV12TextureSupport() const
+{
+ HRESULT result;
+ UINT formatSupport;
+ result = mDevice->CheckFormatSupport(DXGI_FORMAT_NV12, &formatSupport);
+ if (result == E_FAIL)
+ {
+ return false;
+ }
+ return (formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0;
+}
+
int Renderer11::getMajorShaderModel() const
{
switch (mRenderer11DeviceCaps.featureLevel)
{
- case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5
- case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MAJOR_VERSION; // 4
- case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION; // 4
- case D3D_FEATURE_LEVEL_9_3: return D3D10_SHADER_MAJOR_VERSION; // 4
- default: UNREACHABLE(); return 0;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_SHADER_MAJOR_VERSION; // 5
+ case D3D_FEATURE_LEVEL_10_1:
+ return D3D10_1_SHADER_MAJOR_VERSION; // 4
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_SHADER_MAJOR_VERSION; // 4
+ case D3D_FEATURE_LEVEL_9_3:
+ return D3D10_SHADER_MAJOR_VERSION; // 4
+ default:
+ UNREACHABLE();
+ return 0;
}
}
@@ -2684,11 +2360,18 @@ int Renderer11::getMinorShaderModel() const
{
switch (mRenderer11DeviceCaps.featureLevel)
{
- case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MINOR_VERSION; // 0
- case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MINOR_VERSION; // 1
- case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MINOR_VERSION; // 0
- case D3D_FEATURE_LEVEL_9_3: return D3D10_SHADER_MINOR_VERSION; // 0
- default: UNREACHABLE(); return 0;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_SHADER_MINOR_VERSION; // 0
+ case D3D_FEATURE_LEVEL_10_1:
+ return D3D10_1_SHADER_MINOR_VERSION; // 1
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_SHADER_MINOR_VERSION; // 0
+ case D3D_FEATURE_LEVEL_9_3:
+ return D3D10_SHADER_MINOR_VERSION; // 0
+ default:
+ UNREACHABLE();
+ return 0;
}
}
@@ -2696,15 +2379,22 @@ std::string Renderer11::getShaderModelSuffix() const
{
switch (mRenderer11DeviceCaps.featureLevel)
{
- case D3D_FEATURE_LEVEL_11_0: return "";
- case D3D_FEATURE_LEVEL_10_1: return "";
- case D3D_FEATURE_LEVEL_10_0: return "";
- case D3D_FEATURE_LEVEL_9_3: return "_level_9_3";
- default: UNREACHABLE(); return "";
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return "";
+ case D3D_FEATURE_LEVEL_10_1:
+ return "";
+ case D3D_FEATURE_LEVEL_10_0:
+ return "";
+ case D3D_FEATURE_LEVEL_9_3:
+ return "_level_9_3";
+ default:
+ UNREACHABLE();
+ return "";
}
}
-const WorkaroundsD3D &RendererD3D::getWorkarounds() const
+const angle::WorkaroundsD3D &RendererD3D::getWorkarounds() const
{
if (!mWorkaroundsInitialized)
{
@@ -2715,42 +2405,31 @@ const WorkaroundsD3D &RendererD3D::getWorkarounds() const
return mWorkarounds;
}
-gl::Error Renderer11::copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- const gl::Offset &destOffset, TextureStorage *storage, GLint level)
+gl::Error Renderer11::copyImageInternal(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ RenderTargetD3D *destRenderTarget)
{
- const gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer();
- ASSERT(colorbuffer);
+ const gl::FramebufferAttachment *colorAttachment = framebuffer->getReadColorbuffer();
+ ASSERT(colorAttachment);
- RenderTarget11 *sourceRenderTarget = NULL;
- gl::Error error = colorbuffer->getRenderTarget(&sourceRenderTarget);
- if (error.isError())
- {
- return error;
- }
+ RenderTarget11 *sourceRenderTarget = nullptr;
+ ANGLE_TRY(colorAttachment->getRenderTarget(context, &sourceRenderTarget));
ASSERT(sourceRenderTarget);
- ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
- ASSERT(source);
-
- TextureStorage11_2D *storage11 = GetAs<TextureStorage11_2D>(storage);
- ASSERT(storage11);
-
- gl::ImageIndex index = gl::ImageIndex::Make2D(level);
- RenderTargetD3D *destRenderTarget = NULL;
- error = storage11->getRenderTarget(index, &destRenderTarget);
- if (error.isError())
- {
- return error;
- }
- ASSERT(destRenderTarget);
+ const d3d11::SharedSRV &source = sourceRenderTarget->getBlitShaderResourceView();
+ ASSERT(source.valid());
- ID3D11RenderTargetView *dest = GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView();
- ASSERT(dest);
+ const d3d11::RenderTargetView &dest =
+ GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView();
+ ASSERT(dest.valid());
gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
- const bool invertSource = UsePresentPathFast(this, colorbuffer);
+ const bool invertSource = UsePresentPathFast(this, colorAttachment);
if (invertSource)
{
sourceArea.y = sourceSize.height - sourceRect.y;
@@ -2760,226 +2439,267 @@ gl::Error Renderer11::copyImage2D(const gl::Framebuffer *framebuffer, const gl::
gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1);
gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1);
- // Use nearest filtering because source and destination are the same size for the direct
- // copy
- error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
- destFormat, GL_NEAREST, false);
- if (error.isError())
- {
- return error;
- }
+ // Use nearest filtering because source and destination are the same size for the direct copy.
+ // Convert to the unsized format before calling copyTexture.
+ GLenum sourceFormat = colorAttachment->getFormat().info->format;
+ ANGLE_TRY(mBlit->copyTexture(context, source, sourceArea, sourceSize, sourceFormat, dest,
+ destArea, destSize, nullptr, gl::GetUnsizedFormat(destFormat),
+ GL_NEAREST, false, false, false));
- storage11->invalidateSwizzleCacheLevel(level);
-
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Renderer11::copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level)
+gl::Error Renderer11::copyImage2D(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level)
{
- const gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer();
- ASSERT(colorbuffer);
+ TextureStorage11_2D *storage11 = GetAs<TextureStorage11_2D>(storage);
+ ASSERT(storage11);
- RenderTarget11 *sourceRenderTarget = NULL;
- gl::Error error = colorbuffer->getRenderTarget(&sourceRenderTarget);
- if (error.isError())
- {
- return error;
- }
- ASSERT(sourceRenderTarget);
+ gl::ImageIndex index = gl::ImageIndex::Make2D(level);
+ RenderTargetD3D *destRenderTarget = nullptr;
+ ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget));
+ ASSERT(destRenderTarget);
+
+ ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset,
+ destRenderTarget));
+
+ storage11->markLevelDirty(level);
- ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
- ASSERT(source);
+ return gl::NoError();
+}
+gl::Error Renderer11::copyImageCube(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLenum target,
+ GLint level)
+{
TextureStorage11_Cube *storage11 = GetAs<TextureStorage11_Cube>(storage);
ASSERT(storage11);
- gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
- RenderTargetD3D *destRenderTarget = NULL;
- error = storage11->getRenderTarget(index, &destRenderTarget);
- if (error.isError())
- {
- return error;
- }
+ gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
+ RenderTargetD3D *destRenderTarget = nullptr;
+ ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget));
ASSERT(destRenderTarget);
- ID3D11RenderTargetView *dest = GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView();
- ASSERT(dest);
+ ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset,
+ destRenderTarget));
- gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
- gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
+ storage11->markLevelDirty(level);
- const bool invertSource = UsePresentPathFast(this, colorbuffer);
- if (invertSource)
- {
- sourceArea.y = sourceSize.height - sourceRect.y;
- sourceArea.height = -sourceArea.height;
- }
+ return gl::NoError();
+}
- gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1);
- gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1);
+gl::Error Renderer11::copyImage3D(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level)
+{
+ TextureStorage11_3D *storage11 = GetAs<TextureStorage11_3D>(storage);
+ ASSERT(storage11);
- // Use nearest filtering because source and destination are the same size for the direct
- // copy
- error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
- destFormat, GL_NEAREST, false);
- if (error.isError())
- {
- return error;
- }
+ gl::ImageIndex index = gl::ImageIndex::Make3D(level, destOffset.z);
+ RenderTargetD3D *destRenderTarget = nullptr;
+ ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget));
+ ASSERT(destRenderTarget);
+
+ ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset,
+ destRenderTarget));
- storage11->invalidateSwizzleCacheLevel(level);
+ storage11->markLevelDirty(level);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Renderer11::copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- const gl::Offset &destOffset, TextureStorage *storage, GLint level)
+gl::Error Renderer11::copyImage2DArray(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level)
{
- const gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer();
- ASSERT(colorbuffer);
+ TextureStorage11_2DArray *storage11 = GetAs<TextureStorage11_2DArray>(storage);
+ ASSERT(storage11);
- RenderTarget11 *sourceRenderTarget = NULL;
- gl::Error error = colorbuffer->getRenderTarget(&sourceRenderTarget);
- if (error.isError())
- {
- return error;
- }
- ASSERT(sourceRenderTarget);
+ gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z);
+ RenderTargetD3D *destRenderTarget = nullptr;
+ ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget));
+ ASSERT(destRenderTarget);
- ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
- ASSERT(source);
+ ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset,
+ destRenderTarget));
+ storage11->markLevelDirty(level);
- TextureStorage11_3D *storage11 = GetAs<TextureStorage11_3D>(storage);
- ASSERT(storage11);
+ return gl::NoError();
+}
- gl::ImageIndex index = gl::ImageIndex::Make3D(level, destOffset.z);
- RenderTargetD3D *destRenderTarget = NULL;
- error = storage11->getRenderTarget(index, &destRenderTarget);
- if (error.isError())
- {
- return error;
- }
- ASSERT(destRenderTarget);
+gl::Error Renderer11::copyTexture(const gl::Context *context,
+ const gl::Texture *source,
+ GLint sourceLevel,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLenum destTarget,
+ GLint destLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha)
+{
+ TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
- ID3D11RenderTargetView *dest = GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView();
- ASSERT(dest);
+ TextureStorage *sourceStorage = nullptr;
+ ANGLE_TRY(sourceD3D->getNativeTexture(context, &sourceStorage));
- gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
- gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
+ TextureStorage11_2D *sourceStorage11 = GetAs<TextureStorage11_2D>(sourceStorage);
+ ASSERT(sourceStorage11);
- gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1);
- gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1);
+ TextureStorage11 *destStorage11 = GetAs<TextureStorage11>(storage);
+ ASSERT(destStorage11);
- // Use nearest filtering because source and destination are the same size for the direct
- // copy
- error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
- destFormat, GL_NEAREST, false);
- if (error.isError())
+ // Check for fast path where a CopySubresourceRegion can be used.
+ if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha && !unpackFlipY &&
+ source->getFormat(GL_TEXTURE_2D, sourceLevel).info->format == destFormat &&
+ sourceStorage11->getFormatSet().texFormat == destStorage11->getFormatSet().texFormat)
{
- return error;
- }
+ const TextureHelper11 *sourceResource = nullptr;
+ ANGLE_TRY(sourceStorage11->getResource(context, &sourceResource));
- storage11->invalidateSwizzleCacheLevel(level);
+ gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel);
+ UINT sourceSubresource = sourceStorage11->getSubresourceIndex(sourceIndex);
- return gl::Error(GL_NO_ERROR);
-}
+ const TextureHelper11 *destResource = nullptr;
+ ANGLE_TRY(destStorage11->getResource(context, &destResource));
-gl::Error Renderer11::copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- const gl::Offset &destOffset, TextureStorage *storage, GLint level)
-{
- const gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer();
- ASSERT(colorbuffer);
+ gl::ImageIndex destIndex = gl::ImageIndex::MakeGeneric(destTarget, destLevel);
+ UINT destSubresource = destStorage11->getSubresourceIndex(destIndex);
- RenderTarget11 *sourceRenderTarget = NULL;
- gl::Error error = colorbuffer->getRenderTarget(&sourceRenderTarget);
- if (error.isError())
- {
- return error;
+ D3D11_BOX sourceBox{
+ static_cast<UINT>(sourceRect.x),
+ static_cast<UINT>(sourceRect.y),
+ 0u,
+ static_cast<UINT>(sourceRect.x + sourceRect.width),
+ static_cast<UINT>(sourceRect.y + sourceRect.height),
+ 1u,
+ };
+
+ mDeviceContext->CopySubresourceRegion(destResource->get(), destSubresource, destOffset.x,
+ destOffset.y, destOffset.z, sourceResource->get(),
+ sourceSubresource, &sourceBox);
}
- ASSERT(sourceRenderTarget);
+ else
+ {
+ const d3d11::SharedSRV *sourceSRV = nullptr;
+ ANGLE_TRY(sourceStorage11->getSRVLevels(context, sourceLevel, sourceLevel, &sourceSRV));
- ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
- ASSERT(source);
+ gl::ImageIndex destIndex = gl::ImageIndex::MakeGeneric(destTarget, destLevel);
+ RenderTargetD3D *destRenderTargetD3D = nullptr;
+ ANGLE_TRY(destStorage11->getRenderTarget(context, destIndex, &destRenderTargetD3D));
- TextureStorage11_2DArray *storage11 = GetAs<TextureStorage11_2DArray>(storage);
- ASSERT(storage11);
-
- gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z);
- RenderTargetD3D *destRenderTarget = NULL;
- error = storage11->getRenderTarget(index, &destRenderTarget);
- if (error.isError())
- {
- return error;
- }
- ASSERT(destRenderTarget);
+ RenderTarget11 *destRenderTarget11 = GetAs<RenderTarget11>(destRenderTargetD3D);
- ID3D11RenderTargetView *dest = GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView();
- ASSERT(dest);
+ const d3d11::RenderTargetView &destRTV = destRenderTarget11->getRenderTargetView();
+ ASSERT(destRTV.valid());
- gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
- gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
+ gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
+ gl::Extents sourceSize(
+ static_cast<int>(source->getWidth(source->getTarget(), sourceLevel)),
+ static_cast<int>(source->getHeight(source->getTarget(), sourceLevel)), 1);
+ if (unpackFlipY)
+ {
+ sourceArea.y += sourceArea.height;
+ sourceArea.height = -sourceArea.height;
+ }
- gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1);
- gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1);
+ gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1);
+ gl::Extents destSize(destRenderTarget11->getWidth(), destRenderTarget11->getHeight(), 1);
- // Use nearest filtering because source and destination are the same size for the direct
- // copy
- error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
- destFormat, GL_NEAREST, false);
- if (error.isError())
- {
- return error;
+ // Use nearest filtering because source and destination are the same size for the direct
+ // copy
+ GLenum sourceFormat = source->getFormat(GL_TEXTURE_2D, sourceLevel).info->format;
+ ANGLE_TRY(mBlit->copyTexture(context, *sourceSRV, sourceArea, sourceSize, sourceFormat,
+ destRTV, destArea, destSize, nullptr, destFormat, GL_NEAREST,
+ false, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
}
- storage11->invalidateSwizzleCacheLevel(level);
+ destStorage11->markLevelDirty(destLevel);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-void Renderer11::unapplyRenderTargets()
+gl::Error Renderer11::copyCompressedTexture(const gl::Context *context,
+ const gl::Texture *source,
+ GLint sourceLevel,
+ TextureStorage *storage,
+ GLint destLevel)
{
- setOneTimeRenderTarget(NULL);
-}
+ TextureStorage11_2D *destStorage11 = GetAs<TextureStorage11_2D>(storage);
+ ASSERT(destStorage11);
-// When finished with this rendertarget, markAllStateDirty must be called.
-void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView)
-{
- ID3D11RenderTargetView *rtvArray[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL};
+ const TextureHelper11 *destResource = nullptr;
+ ANGLE_TRY(destStorage11->getResource(context, &destResource));
- rtvArray[0] = renderTargetView;
+ gl::ImageIndex destIndex = gl::ImageIndex::Make2D(destLevel);
+ UINT destSubresource = destStorage11->getSubresourceIndex(destIndex);
- mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, rtvArray, NULL);
+ TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
+ ASSERT(sourceD3D);
- // Do not preserve the serial for this one-time-use render target
- for (size_t rtIndex = 0; rtIndex < ArraySize(mAppliedRTVs); rtIndex++)
- {
- mAppliedRTVs[rtIndex] = angle::DirtyPointer;
- }
- mAppliedDSV = angle::DirtyPointer;
+ TextureStorage *sourceStorage = nullptr;
+ ANGLE_TRY(sourceD3D->getNativeTexture(context, &sourceStorage));
+
+ TextureStorage11_2D *sourceStorage11 = GetAs<TextureStorage11_2D>(sourceStorage);
+ ASSERT(sourceStorage11);
+
+ const TextureHelper11 *sourceResource = nullptr;
+ ANGLE_TRY(sourceStorage11->getResource(context, &sourceResource));
+
+ gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel);
+ UINT sourceSubresource = sourceStorage11->getSubresourceIndex(sourceIndex);
+
+ mDeviceContext->CopySubresourceRegion(destResource->get(), destSubresource, 0, 0, 0,
+ sourceResource->get(), sourceSubresource, nullptr);
+
+ return gl::NoError();
}
-gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT)
+gl::Error Renderer11::createRenderTarget(int width,
+ int height,
+ GLenum format,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
{
- const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(format, mRenderer11DeviceCaps);
+ const d3d11::Format &formatInfo = d3d11::Format::Get(format, mRenderer11DeviceCaps);
- const gl::TextureCaps &textureCaps = getRendererTextureCaps().get(format);
- GLuint supportedSamples = textureCaps.getNearestSamples(samples);
+ const gl::TextureCaps &textureCaps = getNativeTextureCaps().get(format);
+ GLuint supportedSamples = textureCaps.getNearestSamples(samples);
if (width > 0 && height > 0)
{
// Create texture resource
D3D11_TEXTURE2D_DESC desc;
- desc.Width = width;
- desc.Height = height;
- desc.MipLevels = 1;
- desc.ArraySize = 1;
- desc.Format = formatInfo.texFormat;
- desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples;
+ desc.Width = width;
+ desc.Height = height;
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.Format = formatInfo.texFormat;
+ desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples;
desc.SampleDesc.Quality = 0;
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.CPUAccessFlags = 0;
- desc.MiscFlags = 0;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = 0;
// If a rendertarget or depthstencil format exists for this texture format,
// we'll flag it to allow binding that way. Shader resource views are a little
@@ -2987,110 +2707,105 @@ gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, G
bool bindRTV = false, bindDSV = false, bindSRV = false;
bindRTV = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
bindDSV = (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
- if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN)
+ bindSRV = (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN);
+
+ bool isMultisampledDepthStencil = bindDSV && desc.SampleDesc.Count > 1;
+ if (isMultisampledDepthStencil &&
+ !mRenderer11DeviceCaps.supportsMultisampledDepthStencilSRVs)
{
- // Multisample targets flagged for binding as depth stencil cannot also be
- // flagged for binding as SRV, so make certain not to add the SRV flag for
- // these targets.
- bindSRV = !(formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN && desc.SampleDesc.Count > 1);
+ bindSRV = false;
}
- desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) |
- (bindDSV ? D3D11_BIND_DEPTH_STENCIL : 0) |
+ desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) |
+ (bindDSV ? D3D11_BIND_DEPTH_STENCIL : 0) |
(bindSRV ? D3D11_BIND_SHADER_RESOURCE : 0);
// The format must be either an RTV or a DSV
ASSERT(bindRTV != bindDSV);
- ID3D11Texture2D *texture = NULL;
- HRESULT result = mDevice->CreateTexture2D(&desc, NULL, &texture);
- if (FAILED(result))
- {
- ASSERT(result == E_OUTOFMEMORY);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target texture, result: 0x%X.", result);
- }
+ TextureHelper11 texture;
+ ANGLE_TRY(allocateTexture(desc, formatInfo, &texture));
- ID3D11ShaderResourceView *srv = NULL;
+ d3d11::SharedSRV srv;
+ d3d11::SharedSRV blitSRV;
if (bindSRV)
{
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
- srvDesc.Format = formatInfo.srvFormat;
- srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS;
+ srvDesc.Format = formatInfo.srvFormat;
+ srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D
+ : D3D11_SRV_DIMENSION_TEXTURE2DMS;
srvDesc.Texture2D.MostDetailedMip = 0;
- srvDesc.Texture2D.MipLevels = 1;
+ srvDesc.Texture2D.MipLevels = 1;
- result = mDevice->CreateShaderResourceView(texture, &srvDesc, &srv);
- if (FAILED(result))
+ ANGLE_TRY(allocateResource(srvDesc, texture.get(), &srv));
+
+ if (formatInfo.blitSRVFormat != formatInfo.srvFormat)
{
- ASSERT(result == E_OUTOFMEMORY);
- SafeRelease(texture);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target shader resource view, result: 0x%X.", result);
+ D3D11_SHADER_RESOURCE_VIEW_DESC blitSRVDesc;
+ blitSRVDesc.Format = formatInfo.blitSRVFormat;
+ blitSRVDesc.ViewDimension = (supportedSamples == 0)
+ ? D3D11_SRV_DIMENSION_TEXTURE2D
+ : D3D11_SRV_DIMENSION_TEXTURE2DMS;
+ blitSRVDesc.Texture2D.MostDetailedMip = 0;
+ blitSRVDesc.Texture2D.MipLevels = 1;
+
+ ANGLE_TRY(allocateResource(blitSRVDesc, texture.get(), &blitSRV));
+ }
+ else
+ {
+ blitSRV = srv.makeCopy();
}
}
if (bindDSV)
{
D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
- dsvDesc.Format = formatInfo.dsvFormat;
- dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS;
+ dsvDesc.Format = formatInfo.dsvFormat;
+ dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D
+ : D3D11_DSV_DIMENSION_TEXTURE2DMS;
dsvDesc.Texture2D.MipSlice = 0;
- dsvDesc.Flags = 0;
+ dsvDesc.Flags = 0;
- ID3D11DepthStencilView *dsv = NULL;
- result = mDevice->CreateDepthStencilView(texture, &dsvDesc, &dsv);
- if (FAILED(result))
- {
- ASSERT(result == E_OUTOFMEMORY);
- SafeRelease(texture);
- SafeRelease(srv);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target depth stencil view, result: 0x%X.", result);
- }
+ d3d11::DepthStencilView dsv;
+ ANGLE_TRY(allocateResource(dsvDesc, texture.get(), &dsv));
- *outRT = new TextureRenderTarget11(dsv, texture, srv, format, width, height, 1, supportedSamples);
-
- SafeRelease(dsv);
+ *outRT = new TextureRenderTarget11(std::move(dsv), texture, srv, format, formatInfo,
+ width, height, 1, supportedSamples);
}
else if (bindRTV)
{
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- rtvDesc.Format = formatInfo.rtvFormat;
- rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS;
+ rtvDesc.Format = formatInfo.rtvFormat;
+ rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D
+ : D3D11_RTV_DIMENSION_TEXTURE2DMS;
rtvDesc.Texture2D.MipSlice = 0;
- ID3D11RenderTargetView *rtv = NULL;
- result = mDevice->CreateRenderTargetView(texture, &rtvDesc, &rtv);
- if (FAILED(result))
- {
- ASSERT(result == E_OUTOFMEMORY);
- SafeRelease(texture);
- SafeRelease(srv);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target render target view, result: 0x%X.", result);
- }
+ d3d11::RenderTargetView rtv;
+ ANGLE_TRY(allocateResource(rtvDesc, texture.get(), &rtv));
- if (formatInfo.dataInitializerFunction != NULL)
+ if (formatInfo.dataInitializerFunction != nullptr)
{
- const float clearValues[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
- mDeviceContext->ClearRenderTargetView(rtv, clearValues);
+ const float clearValues[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ mDeviceContext->ClearRenderTargetView(rtv.get(), clearValues);
}
- *outRT = new TextureRenderTarget11(rtv, texture, srv, format, width, height, 1, supportedSamples);
-
- SafeRelease(rtv);
+ *outRT = new TextureRenderTarget11(std::move(rtv), texture, srv, blitSRV, format,
+ formatInfo, width, height, 1, supportedSamples);
}
else
{
UNREACHABLE();
}
-
- SafeRelease(texture);
- SafeRelease(srv);
}
else
{
- *outRT = new TextureRenderTarget11(reinterpret_cast<ID3D11RenderTargetView*>(NULL), NULL, NULL, format, width, height, 1, supportedSamples);
+ *outRT = new TextureRenderTarget11(d3d11::RenderTargetView(), TextureHelper11(),
+ d3d11::SharedSRV(), d3d11::SharedSRV(), format,
+ d3d11::Format::Get(GL_NONE, mRenderer11DeviceCaps),
+ width, height, 1, supportedSamples);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error Renderer11::createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT)
@@ -3098,58 +2813,35 @@ gl::Error Renderer11::createRenderTargetCopy(RenderTargetD3D *source, RenderTarg
ASSERT(source != nullptr);
RenderTargetD3D *newRT = nullptr;
- gl::Error error = createRenderTarget(source->getWidth(), source->getHeight(),
- source->getInternalFormat(), source->getSamples(), &newRT);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(createRenderTarget(source->getWidth(), source->getHeight(),
+ source->getInternalFormat(), source->getSamples(), &newRT));
RenderTarget11 *source11 = GetAs<RenderTarget11>(source);
RenderTarget11 *dest11 = GetAs<RenderTarget11>(newRT);
- mDeviceContext->CopySubresourceRegion(dest11->getTexture(), dest11->getSubresourceIndex(), 0, 0,
- 0, source11->getTexture(),
+ mDeviceContext->CopySubresourceRegion(dest11->getTexture().get(), dest11->getSubresourceIndex(),
+ 0, 0, 0, source11->getTexture().get(),
source11->getSubresourceIndex(), nullptr);
*outRT = newRT;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-FramebufferImpl *Renderer11::createFramebuffer(const gl::Framebuffer::Data &data)
-{
- return new Framebuffer11(data, this);
-}
-
-ShaderImpl *Renderer11::createShader(const gl::Shader::Data &data)
-{
- return new ShaderD3D(data);
-}
-
-ProgramImpl *Renderer11::createProgram(const gl::Program::Data &data)
-{
- return new ProgramD3D(data, this);
-}
-
-gl::Error Renderer11::loadExecutable(const void *function,
+gl::Error Renderer11::loadExecutable(const uint8_t *function,
size_t length,
- ShaderType type,
+ gl::ShaderType type,
const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers,
ShaderExecutableD3D **outExecutable)
{
+ ShaderData shaderData(function, length);
+
switch (type)
{
- case SHADER_VERTEX:
+ case gl::SHADER_VERTEX:
{
- ID3D11VertexShader *vertexShader = NULL;
- ID3D11GeometryShader *streamOutShader = NULL;
-
- HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vertexShader);
- ASSERT(SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create vertex shader, result: 0x%X.", result);
- }
+ d3d11::VertexShader vertexShader;
+ d3d11::GeometryShader streamOutShader;
+ ANGLE_TRY(allocateResource(shaderData, &vertexShader));
if (!streamOutVaryings.empty())
{
@@ -3163,88 +2855,80 @@ gl::Error Renderer11::loadExecutable(const void *function,
entry.SemanticName = streamOutVarying.semanticName.c_str();
entry.SemanticIndex = streamOutVarying.semanticIndex;
entry.StartComponent = 0;
- entry.ComponentCount = static_cast<BYTE>(streamOutVarying.componentCount);
- entry.OutputSlot = static_cast<BYTE>(
+ entry.ComponentCount = static_cast<BYTE>(streamOutVarying.componentCount);
+ entry.OutputSlot = static_cast<BYTE>(
(separatedOutputBuffers ? streamOutVarying.outputSlot : 0));
soDeclaration.push_back(entry);
}
- result = mDevice->CreateGeometryShaderWithStreamOutput(
- function, static_cast<unsigned int>(length), soDeclaration.data(),
- static_cast<unsigned int>(soDeclaration.size()), NULL, 0, 0, NULL,
- &streamOutShader);
- ASSERT(SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create steam output shader, result: 0x%X.", result);
- }
+ ANGLE_TRY(allocateResource(shaderData, &soDeclaration, &streamOutShader));
}
- *outExecutable = new ShaderExecutable11(function, length, vertexShader, streamOutShader);
+ *outExecutable = new ShaderExecutable11(function, length, std::move(vertexShader),
+ std::move(streamOutShader));
}
break;
- case SHADER_PIXEL:
+ case gl::SHADER_FRAGMENT:
{
- ID3D11PixelShader *pixelShader = NULL;
-
- HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pixelShader);
- ASSERT(SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create pixel shader, result: 0x%X.", result);
- }
-
- *outExecutable = new ShaderExecutable11(function, length, pixelShader);
+ d3d11::PixelShader pixelShader;
+ ANGLE_TRY(allocateResource(shaderData, &pixelShader));
+ *outExecutable = new ShaderExecutable11(function, length, std::move(pixelShader));
}
break;
- case SHADER_GEOMETRY:
+ case gl::SHADER_GEOMETRY:
{
- ID3D11GeometryShader *geometryShader = NULL;
-
- HRESULT result = mDevice->CreateGeometryShader(function, length, NULL, &geometryShader);
- ASSERT(SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create geometry shader, result: 0x%X.", result);
- }
-
- *outExecutable = new ShaderExecutable11(function, length, geometryShader);
+ d3d11::GeometryShader geometryShader;
+ ANGLE_TRY(allocateResource(shaderData, &geometryShader));
+ *outExecutable = new ShaderExecutable11(function, length, std::move(geometryShader));
+ }
+ break;
+ case gl::SHADER_COMPUTE:
+ {
+ d3d11::ComputeShader computeShader;
+ ANGLE_TRY(allocateResource(shaderData, &computeShader));
+ *outExecutable = new ShaderExecutable11(function, length, std::move(computeShader));
}
break;
- default:
- UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION);
+ default:
+ UNREACHABLE();
+ return gl::InternalError();
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog,
const std::string &shaderHLSL,
- ShaderType type,
+ gl::ShaderType type,
const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers,
- const D3DCompilerWorkarounds &workarounds,
+ const angle::CompilerWorkaroundsD3D &workarounds,
ShaderExecutableD3D **outExectuable)
{
- const char *profileType = NULL;
+ std::stringstream profileStream;
+
switch (type)
{
- case SHADER_VERTEX:
- profileType = "vs";
- break;
- case SHADER_PIXEL:
- profileType = "ps";
- break;
- case SHADER_GEOMETRY:
- profileType = "gs";
- break;
- default:
- UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION);
+ case gl::SHADER_VERTEX:
+ profileStream << "vs";
+ break;
+ case gl::SHADER_FRAGMENT:
+ profileStream << "ps";
+ break;
+ case gl::SHADER_GEOMETRY:
+ profileStream << "gs";
+ break;
+ case gl::SHADER_COMPUTE:
+ profileStream << "cs";
+ break;
+ default:
+ UNREACHABLE();
+ return gl::InternalError();
}
- std::string profile = FormatString("%s_%d_%d%s", profileType, getMajorShaderModel(), getMinorShaderModel(), getShaderModelSuffix().c_str());
+ profileStream << "_" << getMajorShaderModel() << "_" << getMinorShaderModel()
+ << getShaderModelSuffix();
+ std::string profile = profileStream.str();
UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL2;
@@ -3260,11 +2944,12 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog,
if (workarounds.enableIEEEStrictness)
flags |= D3DCOMPILE_IEEE_STRICTNESS;
- // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options.
+ // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders
+ // when it would otherwise pass with alternative options.
// Try the default flags first and if compilation fails, try some alternatives.
std::vector<CompileConfig> configs;
- configs.push_back(CompileConfig(flags, "default" ));
- configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_VALIDATION, "skip validation" ));
+ configs.push_back(CompileConfig(flags, "default"));
+ configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_VALIDATION, "skip validation"));
configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_OPTIMIZATION, "skip optimization"));
if (getMajorShaderModel() == 4 && getShaderModelSuffix() != "")
@@ -3276,26 +2961,26 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog,
CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control"));
}
- D3D_SHADER_MACRO loopMacros[] = { {"ANGLE_ENABLE_LOOP_FLATTEN", "1"}, {0, 0} };
+ D3D_SHADER_MACRO loopMacros[] = {{"ANGLE_ENABLE_LOOP_FLATTEN", "1"}, {0, 0}};
- ID3DBlob *binary = NULL;
+ // TODO(jmadill): Use ComPtr?
+ ID3DBlob *binary = nullptr;
std::string debugInfo;
- gl::Error error = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, loopMacros, &binary, &debugInfo);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, loopMacros, &binary,
+ &debugInfo));
- // It's possible that binary is NULL if the compiler failed in all configurations. Set the executable to NULL
- // and return GL_NO_ERROR to signify that there was a link error but the internal state is still OK.
+ // It's possible that binary is NULL if the compiler failed in all configurations. Set the
+ // executable to NULL and return GL_NO_ERROR to signify that there was a link error but the
+ // internal state is still OK.
if (!binary)
{
- *outExectuable = NULL;
- return gl::Error(GL_NO_ERROR);
+ *outExectuable = nullptr;
+ return gl::NoError();
}
- error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
- streamOutVaryings, separatedOutputBuffers, outExectuable);
+ gl::Error error = loadExecutable(reinterpret_cast<const uint8_t *>(binary->GetBufferPointer()),
+ binary->GetBufferSize(), type, streamOutVaryings,
+ separatedOutputBuffers, outExectuable);
SafeRelease(binary);
if (error.isError())
@@ -3308,12 +2993,17 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog,
(*outExectuable)->appendDebugInfo(debugInfo);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
+}
+
+gl::Error Renderer11::ensureHLSLCompilerInitialized()
+{
+ return mCompiler.ensureInitialized();
}
UniformStorageD3D *Renderer11::createUniformStorage(size_t storageSize)
{
- return new UniformStorage11(this, storageSize);
+ return new UniformStorage11(storageSize);
}
VertexBuffer *Renderer11::createVertexBuffer()
@@ -3326,45 +3016,20 @@ IndexBuffer *Renderer11::createIndexBuffer()
return new IndexBuffer11(this);
}
-BufferImpl *Renderer11::createBuffer()
-{
- Buffer11 *buffer = new Buffer11(this);
- mAliveBuffers.insert(buffer);
- return buffer;
-}
-
-VertexArrayImpl *Renderer11::createVertexArray(const gl::VertexArray::Data &data)
-{
- return new VertexArray11(data);
-}
-
-QueryImpl *Renderer11::createQuery(GLenum type)
+StreamProducerImpl *Renderer11::createStreamProducerD3DTextureNV12(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs)
{
- return new Query11(this, type);
-}
-
-FenceNVImpl *Renderer11::createFenceNV()
-{
- return new FenceNV11(this);
-}
-
-FenceSyncImpl *Renderer11::createFenceSync()
-{
- return new FenceSync11(this);
-}
-
-TransformFeedbackImpl* Renderer11::createTransformFeedback()
-{
- return new TransformFeedbackD3D();
+ return new StreamProducerNV12(this);
}
bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const
{
- ASSERT(getRendererExtensions().pixelBufferObject);
+ ASSERT(getNativeExtensions().pixelBufferObject);
- const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
- const d3d11::TextureFormat &d3d11FormatInfo = d3d11::GetTextureFormatInfo(internalFormat, mRenderer11DeviceCaps);
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3d11FormatInfo.texFormat);
+ const gl::InternalFormat &internalFormatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
+ const d3d11::Format &d3d11FormatInfo =
+ d3d11::Format::Get(internalFormat, mRenderer11DeviceCaps);
// sRGB formats do not work with D3D11 buffer SRVs
if (internalFormatInfo.colorEncoding == GL_SRGB)
@@ -3385,7 +3050,19 @@ bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const
}
// We don't support formats which we can't represent without conversion
- if (dxgiFormatInfo.internalFormat != internalFormat)
+ if (d3d11FormatInfo.format().glInternalFormat != internalFormat)
+ {
+ return false;
+ }
+
+ // Buffer SRV creation for this format was not working on Windows 10.
+ if (d3d11FormatInfo.texFormat == DXGI_FORMAT_B5G5R5A1_UNORM)
+ {
+ return false;
+ }
+
+ // This format is not supported as a buffer SRV.
+ if (d3d11FormatInfo.texFormat == DXGI_FORMAT_A8_UNORM)
{
return false;
}
@@ -3393,11 +3070,17 @@ bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const
return true;
}
-gl::Error Renderer11::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget,
- GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea)
+gl::Error Renderer11::fastCopyBufferToTexture(const gl::Context *context,
+ const gl::PixelUnpackState &unpack,
+ unsigned int offset,
+ RenderTargetD3D *destRenderTarget,
+ GLenum destinationFormat,
+ GLenum sourcePixelsType,
+ const gl::Box &destArea)
{
ASSERT(supportsFastCopyBufferToTexture(destinationFormat));
- return mPixelTransfer->copyBufferToTexture(unpack, offset, destRenderTarget, destinationFormat, sourcePixelsType, destArea);
+ return mPixelTransfer->copyBufferToTexture(context, unpack, offset, destRenderTarget,
+ destinationFormat, sourcePixelsType, destArea);
}
ImageD3D *Renderer11::createImage()
@@ -3405,31 +3088,44 @@ ImageD3D *Renderer11::createImage()
return new Image11(this);
}
-gl::Error Renderer11::generateMipmap(ImageD3D *dest, ImageD3D *src)
+gl::Error Renderer11::generateMipmap(const gl::Context *context, ImageD3D *dest, ImageD3D *src)
{
Image11 *dest11 = GetAs<Image11>(dest);
- Image11 *src11 = GetAs<Image11>(src);
- return Image11::generateMipmap(dest11, src11);
+ Image11 *src11 = GetAs<Image11>(src);
+ return Image11::GenerateMipmap(context, dest11, src11, mRenderer11DeviceCaps);
}
-gl::Error Renderer11::generateMipmapsUsingD3D(TextureStorage *storage,
- const gl::TextureState &textureState)
+gl::Error Renderer11::generateMipmapUsingD3D(const gl::Context *context,
+ TextureStorage *storage,
+ const gl::TextureState &textureState)
{
TextureStorage11 *storage11 = GetAs<TextureStorage11>(storage);
ASSERT(storage11->isRenderTarget());
ASSERT(storage11->supportsNativeMipmapFunction());
- ID3D11ShaderResourceView *srv;
- gl::Error error = storage11->getSRVLevels(textureState.baseLevel, textureState.maxLevel, &srv);
- if (error.isError())
- {
- return error;
- }
+ const d3d11::SharedSRV *srv = nullptr;
+ ANGLE_TRY(storage11->getSRVLevels(context, textureState.getEffectiveBaseLevel(),
+ textureState.getEffectiveMaxLevel(), &srv));
- mDeviceContext->GenerateMips(srv);
+ mDeviceContext->GenerateMips(srv->get());
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
+}
+
+gl::Error Renderer11::copyImage(const gl::Context *context,
+ ImageD3D *dest,
+ ImageD3D *source,
+ const gl::Rectangle &sourceRect,
+ const gl::Offset &destOffset,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha)
+{
+ Image11 *dest11 = GetAs<Image11>(dest);
+ Image11 *src11 = GetAs<Image11>(source);
+ return Image11::CopyImage(context, dest11, src11, sourceRect, destOffset, unpackFlipY,
+ unpackPremultiplyAlpha, unpackUnmultiplyAlpha, mRenderer11DeviceCaps);
}
TextureStorage *Renderer11::createTextureStorage2D(SwapChainD3D *swapChain)
@@ -3438,53 +3134,75 @@ TextureStorage *Renderer11::createTextureStorage2D(SwapChainD3D *swapChain)
return new TextureStorage11_2D(this, swapChain11);
}
-TextureStorage *Renderer11::createTextureStorageEGLImage(EGLImageD3D *eglImage)
+TextureStorage *Renderer11::createTextureStorageEGLImage(EGLImageD3D *eglImage,
+ RenderTargetD3D *renderTargetD3D)
{
- return new TextureStorage11_EGLImage(this, eglImage);
+ return new TextureStorage11_EGLImage(this, eglImage, GetAs<RenderTarget11>(renderTargetD3D));
}
-TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly)
+TextureStorage *Renderer11::createTextureStorageExternal(
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc)
{
- return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels, hintLevelZeroOnly);
+ return new TextureStorage11_External(this, stream, desc);
}
-TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly)
+TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ bool hintLevelZeroOnly)
{
- return new TextureStorage11_Cube(this, internalformat, renderTarget, size, levels, hintLevelZeroOnly);
+ return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels,
+ hintLevelZeroOnly);
}
-TextureStorage *Renderer11::createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels)
+TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat,
+ bool renderTarget,
+ int size,
+ int levels,
+ bool hintLevelZeroOnly)
{
- return new TextureStorage11_3D(this, internalformat, renderTarget, width, height, depth, levels);
+ return new TextureStorage11_Cube(this, internalformat, renderTarget, size, levels,
+ hintLevelZeroOnly);
}
-TextureStorage *Renderer11::createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels)
+TextureStorage *Renderer11::createTextureStorage3D(GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels)
{
- return new TextureStorage11_2DArray(this, internalformat, renderTarget, width, height, depth, levels);
+ return new TextureStorage11_3D(this, internalformat, renderTarget, width, height, depth,
+ levels);
}
-TextureImpl *Renderer11::createTexture(GLenum target)
+TextureStorage *Renderer11::createTextureStorage2DArray(GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels)
{
- switch(target)
- {
- case GL_TEXTURE_2D: return new TextureD3D_2D(this);
- case GL_TEXTURE_CUBE_MAP: return new TextureD3D_Cube(this);
- case GL_TEXTURE_3D: return new TextureD3D_3D(this);
- case GL_TEXTURE_2D_ARRAY: return new TextureD3D_2DArray(this);
- default:
- UNREACHABLE();
- }
-
- return NULL;
+ return new TextureStorage11_2DArray(this, internalformat, renderTarget, width, height, depth,
+ levels);
}
-RenderbufferImpl *Renderer11::createRenderbuffer()
+TextureStorage *Renderer11::createTextureStorage2DMultisample(GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ int samples,
+ bool fixedSampleLocations)
{
- RenderbufferD3D *renderbuffer = new RenderbufferD3D(this);
- return renderbuffer;
+ return new TextureStorage11_2DMultisample(this, internalformat, width, height, levels, samples,
+ fixedSampleLocations);
}
-gl::Error Renderer11::readFromAttachment(const gl::FramebufferAttachment &srcAttachment,
+gl::Error Renderer11::readFromAttachment(const gl::Context *context,
+ const gl::FramebufferAttachment &srcAttachment,
const gl::Rectangle &sourceArea,
GLenum format,
GLenum type,
@@ -3497,17 +3215,11 @@ gl::Error Renderer11::readFromAttachment(const gl::FramebufferAttachment &srcAtt
const bool invertTexture = UsePresentPathFast(this, &srcAttachment);
- RenderTargetD3D *renderTarget = nullptr;
- gl::Error error = srcAttachment.getRenderTarget(&renderTarget);
- if (error.isError())
- {
- return error;
- }
+ RenderTarget11 *rt11 = nullptr;
+ ANGLE_TRY(srcAttachment.getRenderTarget(context, &rt11));
+ ASSERT(rt11->getTexture().valid());
- RenderTarget11 *rt11 = GetAs<RenderTarget11>(renderTarget);
- ASSERT(rt11->getTexture());
-
- TextureHelper11 textureHelper = TextureHelper11::MakeAndReference(rt11->getTexture());
+ const TextureHelper11 &textureHelper = rt11->getTexture();
unsigned int sourceSubResource = rt11->getSubresourceIndex();
const gl::Extents &texSize = textureHelper.getExtents();
@@ -3535,52 +3247,42 @@ gl::Error Renderer11::readFromAttachment(const gl::FramebufferAttachment &srcAtt
if (safeArea.width == 0 || safeArea.height == 0)
{
// no work to do
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Extents safeSize(safeArea.width, safeArea.height, 1);
- auto errorOrResult = CreateStagingTexture(textureHelper.getTextureType(),
- textureHelper.getFormat(), safeSize, mDevice);
- if (errorOrResult.isError())
- {
- return errorOrResult.getError();
- }
+ TextureHelper11 stagingHelper;
+ ANGLE_TRY_RESULT(
+ createStagingTexture(textureHelper.getTextureType(), textureHelper.getFormatSet(), safeSize,
+ StagingAccess::READ),
+ stagingHelper);
- TextureHelper11 stagingHelper(errorOrResult.getResult());
TextureHelper11 resolvedTextureHelper;
// "srcTexture" usually points to the source texture.
// For 2D multisampled textures, it points to the multisampled resolve texture.
const TextureHelper11 *srcTexture = &textureHelper;
- if (textureHelper.getTextureType() == GL_TEXTURE_2D && textureHelper.getSampleCount() > 1)
+ if (textureHelper.is2D() && textureHelper.getSampleCount() > 1)
{
D3D11_TEXTURE2D_DESC resolveDesc;
resolveDesc.Width = static_cast<UINT>(texSize.width);
resolveDesc.Height = static_cast<UINT>(texSize.height);
- resolveDesc.MipLevels = 1;
- resolveDesc.ArraySize = 1;
+ resolveDesc.MipLevels = 1;
+ resolveDesc.ArraySize = 1;
resolveDesc.Format = textureHelper.getFormat();
- resolveDesc.SampleDesc.Count = 1;
+ resolveDesc.SampleDesc.Count = 1;
resolveDesc.SampleDesc.Quality = 0;
- resolveDesc.Usage = D3D11_USAGE_DEFAULT;
- resolveDesc.BindFlags = 0;
- resolveDesc.CPUAccessFlags = 0;
- resolveDesc.MiscFlags = 0;
+ resolveDesc.Usage = D3D11_USAGE_DEFAULT;
+ resolveDesc.BindFlags = 0;
+ resolveDesc.CPUAccessFlags = 0;
+ resolveDesc.MiscFlags = 0;
- ID3D11Texture2D *resolveTex2D = nullptr;
- HRESULT result = mDevice->CreateTexture2D(&resolveDesc, nullptr, &resolveTex2D);
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY,
- "Renderer11::readTextureData failed to create internal resolve "
- "texture for ReadPixels, HRESULT: 0x%X.",
- result);
- }
+ ANGLE_TRY(
+ allocateTexture(resolveDesc, textureHelper.getFormatSet(), &resolvedTextureHelper));
- mDeviceContext->ResolveSubresource(resolveTex2D, 0, textureHelper.getTexture2D(),
+ mDeviceContext->ResolveSubresource(resolvedTextureHelper.get(), 0, textureHelper.get(),
sourceSubResource, textureHelper.getFormat());
- resolvedTextureHelper = TextureHelper11::MakeAndReference(resolveTex2D);
sourceSubResource = 0;
srcTexture = &resolvedTextureHelper;
@@ -3594,132 +3296,66 @@ gl::Error Renderer11::readFromAttachment(const gl::FramebufferAttachment &srcAtt
// Select the correct layer from a 3D attachment
srcBox.front = 0;
- if (textureHelper.getTextureType() == GL_TEXTURE_3D)
+ if (textureHelper.is3D())
{
srcBox.front = static_cast<UINT>(srcAttachment.layer());
}
srcBox.back = srcBox.front + 1;
- mDeviceContext->CopySubresourceRegion(stagingHelper.getResource(), 0, 0, 0, 0,
- srcTexture->getResource(), sourceSubResource, &srcBox);
-
- if (invertTexture)
- {
- gl::PixelPackState invertTexturePack;
-
- // Create a new PixelPackState with reversed row order. Note that we can't just assign
- // 'invertTexturePack' to be 'pack' (or memcpy) since that breaks the ref counting/object
- // tracking in the 'pixelBuffer' members, causing leaks. Instead we must use
- // pixelBuffer.set() twice, which performs the addRef/release correctly
- invertTexturePack.alignment = pack.alignment;
- invertTexturePack.pixelBuffer.set(pack.pixelBuffer.get());
- invertTexturePack.reverseRowOrder = !pack.reverseRowOrder;
-
- PackPixelsParams packParams(safeArea, format, type, outputPitch, invertTexturePack, 0);
- error = packPixels(stagingHelper, packParams, pixelsOut);
-
- invertTexturePack.pixelBuffer.set(nullptr);
+ mDeviceContext->CopySubresourceRegion(stagingHelper.get(), 0, 0, 0, 0, srcTexture->get(),
+ sourceSubResource, &srcBox);
- return error;
- }
- else
+ gl::Buffer *packBuffer = context->getGLState().getTargetBuffer(gl::BufferBinding::PixelPack);
+ if (!invertTexture)
{
- PackPixelsParams packParams(safeArea, format, type, outputPitch, pack, 0);
+ PackPixelsParams packParams(safeArea, format, type, outputPitch, pack, packBuffer, 0);
return packPixels(stagingHelper, packParams, pixelsOut);
}
+
+ // Create a new PixelPackState with reversed row order. Note that we can't just assign
+ // 'invertTexturePack' to be 'pack' (or memcpy) since that breaks the ref counting/object
+ // tracking in the 'pixelBuffer' members, causing leaks. Instead we must use
+ // pixelBuffer.set() twice, which performs the addRef/release correctly
+ gl::PixelPackState invertTexturePack;
+ invertTexturePack.alignment = pack.alignment;
+ invertTexturePack.reverseRowOrder = !pack.reverseRowOrder;
+
+ PackPixelsParams packParams(safeArea, format, type, outputPitch, invertTexturePack, packBuffer,
+ 0);
+ gl::Error error = packPixels(stagingHelper, packParams, pixelsOut);
+ ANGLE_TRY(error);
+ return gl::NoError();
}
gl::Error Renderer11::packPixels(const TextureHelper11 &textureHelper,
const PackPixelsParams &params,
uint8_t *pixelsOut)
{
- ID3D11Resource *readResource = textureHelper.getResource();
+ ID3D11Resource *readResource = textureHelper.get();
D3D11_MAPPED_SUBRESOURCE mapping;
HRESULT hr = mDeviceContext->Map(readResource, 0, D3D11_MAP_READ, 0, &mapping);
if (FAILED(hr))
{
ASSERT(hr == E_OUTOFMEMORY);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal texture for reading, result: 0x%X.", hr);
- }
-
- uint8_t *source;
- int inputPitch;
- if (params.pack.reverseRowOrder)
- {
- source = static_cast<uint8_t*>(mapping.pData) + mapping.RowPitch * (params.area.height - 1);
- inputPitch = -static_cast<int>(mapping.RowPitch);
- }
- else
- {
- source = static_cast<uint8_t*>(mapping.pData);
- inputPitch = static_cast<int>(mapping.RowPitch);
+ return gl::OutOfMemory() << "Failed to map internal texture for reading, " << gl::FmtHR(hr);
}
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(textureHelper.getFormat());
- const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat);
- if (sourceFormatInfo.format == params.format && sourceFormatInfo.type == params.type)
- {
- uint8_t *dest = pixelsOut + params.offset;
- for (int y = 0; y < params.area.height; y++)
- {
- memcpy(dest + y * params.outputPitch, source + y * inputPitch, params.area.width * sourceFormatInfo.pixelBytes);
- }
- }
- else
- {
- ColorCopyFunction fastCopyFunc =
- dxgiFormatInfo.getFastCopyFunction(params.format, params.type);
- GLenum sizedDestInternalFormat = gl::GetSizedInternalFormat(params.format, params.type);
- const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(sizedDestInternalFormat);
-
- if (fastCopyFunc)
- {
- // Fast copy is possible through some special function
- for (int y = 0; y < params.area.height; y++)
- {
- for (int x = 0; x < params.area.width; x++)
- {
- uint8_t *dest = pixelsOut + params.offset + y * params.outputPitch + x * destFormatInfo.pixelBytes;
- const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes;
-
- fastCopyFunc(src, dest);
- }
- }
- }
- else
- {
- ColorReadFunction colorReadFunction = dxgiFormatInfo.colorReadFunction;
- ColorWriteFunction colorWriteFunction = GetColorWriteFunction(params.format, params.type);
-
- uint8_t temp[16]; // Maximum size of any Color<T> type used.
- static_assert(sizeof(temp) >= sizeof(gl::ColorF) &&
- sizeof(temp) >= sizeof(gl::ColorUI) &&
- sizeof(temp) >= sizeof(gl::ColorI),
- "Unexpected size of gl::Color struct.");
+ uint8_t *source = static_cast<uint8_t *>(mapping.pData);
+ int inputPitch = static_cast<int>(mapping.RowPitch);
- for (int y = 0; y < params.area.height; y++)
- {
- for (int x = 0; x < params.area.width; x++)
- {
- uint8_t *dest = pixelsOut + params.offset + y * params.outputPitch + x * destFormatInfo.pixelBytes;
- const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes;
+ const auto &formatInfo = textureHelper.getFormatSet();
+ ASSERT(formatInfo.format().glInternalFormat != GL_NONE);
- // readFunc and writeFunc will be using the same type of color, CopyTexImage
- // will not allow the copy otherwise.
- colorReadFunction(src, temp);
- colorWriteFunction(temp, dest);
- }
- }
- }
- }
+ PackPixels(params, formatInfo.format(), inputPitch, source, pixelsOut);
mDeviceContext->Unmap(readResource, 0);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn,
+gl::Error Renderer11::blitRenderbufferRect(const gl::Context *context,
+ const gl::Rectangle &readRectIn,
const gl::Rectangle &drawRectIn,
RenderTargetD3D *readRenderTarget,
RenderTargetD3D *drawRenderTarget,
@@ -3735,63 +3371,64 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn,
ASSERT(colorBlit != (depthBlit || stencilBlit));
RenderTarget11 *drawRenderTarget11 = GetAs<RenderTarget11>(drawRenderTarget);
- if (!drawRenderTarget)
+ if (!drawRenderTarget11)
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal draw render target from the draw framebuffer.");
+ return gl::OutOfMemory()
+ << "Failed to retrieve the internal draw render target from the draw framebuffer.";
}
- ID3D11Resource *drawTexture = drawRenderTarget11->getTexture();
- unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex();
- ID3D11RenderTargetView *drawRTV = drawRenderTarget11->getRenderTargetView();
- ID3D11DepthStencilView *drawDSV = drawRenderTarget11->getDepthStencilView();
+ const TextureHelper11 &drawTexture = drawRenderTarget11->getTexture();
+ unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex();
RenderTarget11 *readRenderTarget11 = GetAs<RenderTarget11>(readRenderTarget);
- if (!readRenderTarget)
+ if (!readRenderTarget11)
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal read render target from the read framebuffer.");
+ return gl::OutOfMemory()
+ << "Failed to retrieve the internal read render target from the read framebuffer.";
}
- ID3D11Resource *readTexture = NULL;
- ID3D11ShaderResourceView *readSRV = NULL;
- unsigned int readSubresource = 0;
- if (readRenderTarget->getSamples() > 0)
+ TextureHelper11 readTexture;
+ unsigned int readSubresource = 0;
+ d3d11::SharedSRV readSRV;
+
+ if (readRenderTarget->isMultisampled())
{
- ID3D11Resource *unresolvedResource = readRenderTarget11->getTexture();
- ID3D11Texture2D *unresolvedTexture = d3d11::DynamicCastComObject<ID3D11Texture2D>(unresolvedResource);
+ ANGLE_TRY_RESULT(
+ resolveMultisampledTexture(context, readRenderTarget11, depthBlit, stencilBlit),
+ readTexture);
- if (unresolvedTexture)
+ if (!stencilBlit)
{
- readTexture = resolveMultisampledTexture(unresolvedTexture, readRenderTarget11->getSubresourceIndex());
- readSubresource = 0;
+ const auto &readFormatSet = readTexture.getFormatSet();
- SafeRelease(unresolvedTexture);
+ D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
+ viewDesc.Format = readFormatSet.srvFormat;
+ viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ viewDesc.Texture2D.MipLevels = 1;
+ viewDesc.Texture2D.MostDetailedMip = 0;
- HRESULT hresult = mDevice->CreateShaderResourceView(readTexture, NULL, &readSRV);
- if (FAILED(hresult))
- {
- SafeRelease(readTexture);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create shader resource view to resolve multisampled framebuffer.");
- }
+ ANGLE_TRY(allocateResource(viewDesc, readTexture.get(), &readSRV));
}
}
else
{
- readTexture = readRenderTarget11->getTexture();
- readTexture->AddRef();
+ ASSERT(readRenderTarget11);
+ readTexture = readRenderTarget11->getTexture();
readSubresource = readRenderTarget11->getSubresourceIndex();
- readSRV = readRenderTarget11->getShaderResourceView();
- readSRV->AddRef();
+ readSRV = readRenderTarget11->getBlitShaderResourceView().makeCopy();
+ if (!readSRV.valid())
+ {
+ ASSERT(depthBlit || stencilBlit);
+ readSRV = readRenderTarget11->getShaderResourceView().makeCopy();
+ }
+ ASSERT(readSRV.valid());
}
- if (!readTexture || !readSRV)
- {
- SafeRelease(readTexture);
- SafeRelease(readSRV);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal read render target view from the read render target.");
- }
+ // Stencil blits don't use shaders.
+ ASSERT(readSRV.valid() || stencilBlit);
- gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
- gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);
+ const gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
+ const gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);
// From the spec:
// "The actual region taken from the read framebuffer is limited to the intersection of the
@@ -3801,8 +3438,32 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn,
// by internally scaling the read and draw rectangles.
gl::Rectangle readRect = readRectIn;
gl::Rectangle drawRect = drawRectIn;
- auto readToDrawX = [&drawRectIn, &readRectIn](int readOffset)
+
+ auto flip = [](int val) { return val >= 0 ? 1 : -1; };
+
+ if (readRect.x > readSize.width && readRect.width < 0)
+ {
+ int delta = readRect.x - readSize.width;
+ readRect.x -= delta;
+ readRect.width += delta;
+
+ int drawDelta = delta * flip(drawRect.width);
+ drawRect.x += drawDelta;
+ drawRect.width -= drawDelta;
+ }
+
+ if (readRect.y > readSize.height && readRect.height < 0)
{
+ int delta = readRect.y - readSize.height;
+ readRect.y -= delta;
+ readRect.height += delta;
+
+ int drawDelta = delta * flip(drawRect.height);
+ drawRect.y += drawDelta;
+ drawRect.height -= drawDelta;
+ }
+
+ auto readToDrawX = [&drawRectIn, &readRectIn](int readOffset) {
double readToDrawScale =
static_cast<double>(drawRectIn.width) / static_cast<double>(readRectIn.width);
return static_cast<int>(round(static_cast<double>(readOffset) * readToDrawScale));
@@ -3818,8 +3479,7 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn,
drawRect.width -= drawOffset;
}
- auto readToDrawY = [&drawRectIn, &readRectIn](int readOffset)
- {
+ auto readToDrawY = [&drawRectIn, &readRectIn](int readOffset) {
double readToDrawScale =
static_cast<double>(drawRectIn.height) / static_cast<double>(readRectIn.height);
return static_cast<int>(round(static_cast<double>(readOffset) * readToDrawScale));
@@ -3853,24 +3513,41 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn,
drawRect.height += drawOffset;
}
- bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, NULL);
+ if (readRect.x1() > readSize.width)
+ {
+ int delta = readRect.x1() - readSize.width;
+ readRect.width -= delta;
+ drawRect.width -= delta * flip(drawRect.width);
+ }
+
+ if (readRect.y1() > readSize.height)
+ {
+ int delta = readRect.y1() - readSize.height;
+ readRect.height -= delta;
+ drawRect.height -= delta * flip(drawRect.height);
+ }
+
+ bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, nullptr);
- const auto &destFormatInfo = gl::GetInternalFormatInfo(drawRenderTarget->getInternalFormat());
- const auto &srcFormatInfo = gl::GetInternalFormatInfo(readRenderTarget->getInternalFormat());
- const auto &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(drawRenderTarget11->getDXGIFormat());
+ const auto &destFormatInfo =
+ gl::GetSizedInternalFormatInfo(drawRenderTarget->getInternalFormat());
+ const auto &srcFormatInfo =
+ gl::GetSizedInternalFormatInfo(readRenderTarget->getInternalFormat());
+ const auto &formatSet = drawRenderTarget11->getFormatSet();
+ const auto &nativeFormat = formatSet.format();
// Some blits require masking off emulated texture channels. eg: from RGBA8 to RGB8, we
// emulate RGB8 with RGBA8, so we need to mask off the alpha channel when we copy.
gl::Color<bool> colorMask;
- colorMask.red = (srcFormatInfo.redBits > 0) && (destFormatInfo.redBits == 0) &&
- (dxgiFormatInfo.redBits > 0);
+ colorMask.red =
+ (srcFormatInfo.redBits > 0) && (destFormatInfo.redBits == 0) && (nativeFormat.redBits > 0);
colorMask.green = (srcFormatInfo.greenBits > 0) && (destFormatInfo.greenBits == 0) &&
- (dxgiFormatInfo.greenBits > 0);
+ (nativeFormat.greenBits > 0);
colorMask.blue = (srcFormatInfo.blueBits > 0) && (destFormatInfo.blueBits == 0) &&
- (dxgiFormatInfo.blueBits > 0);
+ (nativeFormat.blueBits > 0);
colorMask.alpha = (srcFormatInfo.alphaBits > 0) && (destFormatInfo.alphaBits == 0) &&
- (dxgiFormatInfo.alphaBits > 0);
+ (nativeFormat.alphaBits > 0);
// We only currently support masking off the alpha channel.
bool colorMaskingNeeded = colorMask.alpha;
@@ -3884,18 +3561,19 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn,
bool stretchRequired = readRect.width != drawRect.width || readRect.height != drawRect.height;
- bool flipRequired = readRect.width < 0 || readRect.height < 0 || drawRect.width < 0 || drawRect.height < 0;
+ bool flipRequired =
+ readRect.width < 0 || readRect.height < 0 || drawRect.width < 0 || drawRect.height < 0;
bool outOfBounds = readRect.x < 0 || readRect.x + readRect.width > readSize.width ||
readRect.y < 0 || readRect.y + readRect.height > readSize.height ||
drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width ||
drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height;
- bool partialDSBlit = (dxgiFormatInfo.depthBits > 0 && depthBlit) != (dxgiFormatInfo.stencilBits > 0 && stencilBlit);
+ bool partialDSBlit =
+ (nativeFormat.depthBits > 0 && depthBlit) != (nativeFormat.stencilBits > 0 && stencilBlit);
- gl::Error result(GL_NO_ERROR);
-
- if (readRenderTarget11->getDXGIFormat() == drawRenderTarget11->getDXGIFormat() &&
+ if (readRenderTarget11->getFormatSet().formatID ==
+ drawRenderTarget11->getFormatSet().formatID &&
!stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit &&
!colorMaskingNeeded && (!(depthBlit || stencilBlit) || wholeBufferCopy))
{
@@ -3903,16 +3581,17 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn,
UINT dstY = drawRect.y;
D3D11_BOX readBox;
- readBox.left = readRect.x;
- readBox.right = readRect.x + readRect.width;
- readBox.top = readRect.y;
+ readBox.left = readRect.x;
+ readBox.right = readRect.x + readRect.width;
+ readBox.top = readRect.y;
readBox.bottom = readRect.y + readRect.height;
- readBox.front = 0;
- readBox.back = 1;
+ readBox.front = 0;
+ readBox.back = 1;
if (scissorNeeded)
{
- // drawRect is guaranteed to have positive width and height because stretchRequired is false.
+ // drawRect is guaranteed to have positive width and height because stretchRequired is
+ // false.
ASSERT(drawRect.width >= 0 || drawRect.height >= 0);
if (drawRect.x < scissor->x)
@@ -3937,11 +3616,10 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn,
// D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox
// We also require complete framebuffer copies for depth-stencil blit.
- D3D11_BOX *pSrcBox = wholeBufferCopy ? NULL : &readBox;
+ D3D11_BOX *pSrcBox = wholeBufferCopy ? nullptr : &readBox;
- mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, dstX, dstY, 0,
- readTexture, readSubresource, pSrcBox);
- result = gl::Error(GL_NO_ERROR);
+ mDeviceContext->CopySubresourceRegion(drawTexture.get(), drawSubresource, dstX, dstY, 0,
+ readTexture.get(), readSubresource, pSrcBox);
}
else
{
@@ -3950,47 +3628,56 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn,
if (depthBlit && stencilBlit)
{
- result = mBlit->copyDepthStencil(readTexture, readSubresource, readArea, readSize,
- drawTexture, drawSubresource, drawArea, drawSize,
- scissor);
+ ANGLE_TRY(mBlit->copyDepthStencil(readTexture, readSubresource, readArea, readSize,
+ drawTexture, drawSubresource, drawArea, drawSize,
+ scissor));
}
else if (depthBlit)
{
- result = mBlit->copyDepth(readSRV, readArea, readSize, drawDSV, drawArea, drawSize,
- scissor);
+ const d3d11::DepthStencilView &drawDSV = drawRenderTarget11->getDepthStencilView();
+ ASSERT(readSRV.valid());
+ ANGLE_TRY(mBlit->copyDepth(context, readSRV, readArea, readSize, drawDSV, drawArea,
+ drawSize, scissor));
}
else if (stencilBlit)
{
- result = mBlit->copyStencil(readTexture, readSubresource, readArea, readSize,
- drawTexture, drawSubresource, drawArea, drawSize,
- scissor);
+ ANGLE_TRY(mBlit->copyStencil(context, readTexture, readSubresource, readArea, readSize,
+ drawTexture, drawSubresource, drawArea, drawSize,
+ scissor));
}
else
{
+ const d3d11::RenderTargetView &drawRTV = drawRenderTarget11->getRenderTargetView();
+
// We don't currently support masking off any other channel than alpha
bool maskOffAlpha = colorMaskingNeeded && colorMask.alpha;
- result = mBlit->copyTexture(readSRV, readArea, readSize, drawRTV, drawArea, drawSize,
- scissor, destFormatInfo.format, filter, maskOffAlpha);
+ ASSERT(readSRV.valid());
+ ANGLE_TRY(mBlit->copyTexture(
+ context, readSRV, readArea, readSize, srcFormatInfo.format, drawRTV, drawArea,
+ drawSize, scissor, destFormatInfo.format, filter, maskOffAlpha, false, false));
}
}
- SafeRelease(readTexture);
- SafeRelease(readSRV);
-
- return result;
+ return gl::NoError();
}
bool Renderer11::isES3Capable() const
{
- return (d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps.featureLevel) > 2);
-};
+ return (d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps.featureLevel).major > 2);
+}
+
+RendererClass Renderer11::getRendererClass() const
+{
+ return RENDERER_D3D11;
+}
void Renderer11::onSwap()
{
// Send histogram updates every half hour
const double kHistogramUpdateInterval = 30 * 60;
- const double currentTime = ANGLEPlatformCurrent()->monotonicallyIncreasingTime();
+ auto *platform = ANGLEPlatformCurrent();
+ const double currentTime = platform->monotonicallyIncreasingTime(platform);
const double timeSinceLastUpdate = currentTime - mLastHistogramUpdateTime;
if (timeSinceLastUpdate > kHistogramUpdateInterval)
@@ -4005,7 +3692,7 @@ void Renderer11::updateHistograms()
// Update the buffer CPU memory histogram
{
size_t sizeSum = 0;
- for (auto &buffer : mAliveBuffers)
+ for (const Buffer11 *buffer : mAliveBuffers)
{
sizeSum += buffer->getTotalCPUBufferMemoryBytes();
}
@@ -4015,53 +3702,71 @@ void Renderer11::updateHistograms()
}
}
+void Renderer11::onBufferCreate(const Buffer11 *created)
+{
+ mAliveBuffers.insert(created);
+}
+
void Renderer11::onBufferDelete(const Buffer11 *deleted)
{
mAliveBuffers.erase(deleted);
}
-ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource)
+gl::ErrorOrResult<TextureHelper11> Renderer11::resolveMultisampledTexture(
+ const gl::Context *context,
+ RenderTarget11 *renderTarget,
+ bool depth,
+ bool stencil)
{
- D3D11_TEXTURE2D_DESC textureDesc;
- source->GetDesc(&textureDesc);
+ if (depth && !stencil)
+ {
+ return mBlit->resolveDepth(context, renderTarget);
+ }
- if (textureDesc.SampleDesc.Count > 1)
+ if (stencil)
{
- D3D11_TEXTURE2D_DESC resolveDesc;
- resolveDesc.Width = textureDesc.Width;
- resolveDesc.Height = textureDesc.Height;
- resolveDesc.MipLevels = 1;
- resolveDesc.ArraySize = 1;
- resolveDesc.Format = textureDesc.Format;
- resolveDesc.SampleDesc.Count = 1;
- resolveDesc.SampleDesc.Quality = 0;
- resolveDesc.Usage = textureDesc.Usage;
- resolveDesc.BindFlags = textureDesc.BindFlags;
- resolveDesc.CPUAccessFlags = 0;
- resolveDesc.MiscFlags = 0;
+ return mBlit->resolveStencil(context, renderTarget, depth);
+ }
- ID3D11Texture2D *resolveTexture = NULL;
- HRESULT result = mDevice->CreateTexture2D(&resolveDesc, NULL, &resolveTexture);
- if (FAILED(result))
- {
- ERR("Failed to create a multisample resolve texture, HRESULT: 0x%X.", result);
- return NULL;
- }
+ const auto &formatSet = renderTarget->getFormatSet();
- mDeviceContext->ResolveSubresource(resolveTexture, 0, source, subresource, textureDesc.Format);
- return resolveTexture;
- }
- else
+ ASSERT(renderTarget->isMultisampled());
+ const d3d11::SharedSRV &sourceSRV = renderTarget->getShaderResourceView();
+ D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
+ sourceSRV.get()->GetDesc(&sourceSRVDesc);
+ ASSERT(sourceSRVDesc.ViewDimension == D3D_SRV_DIMENSION_TEXTURE2DMS);
+
+ if (!mCachedResolveTexture.valid() ||
+ mCachedResolveTexture.getExtents().width != renderTarget->getWidth() ||
+ mCachedResolveTexture.getExtents().height != renderTarget->getHeight() ||
+ mCachedResolveTexture.getFormat() != formatSet.texFormat)
{
- source->AddRef();
- return source;
+ D3D11_TEXTURE2D_DESC resolveDesc;
+ resolveDesc.Width = renderTarget->getWidth();
+ resolveDesc.Height = renderTarget->getHeight();
+ resolveDesc.MipLevels = 1;
+ resolveDesc.ArraySize = 1;
+ resolveDesc.Format = formatSet.texFormat;
+ resolveDesc.SampleDesc.Count = 1;
+ resolveDesc.SampleDesc.Quality = 0;
+ resolveDesc.Usage = D3D11_USAGE_DEFAULT;
+ resolveDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ resolveDesc.CPUAccessFlags = 0;
+ resolveDesc.MiscFlags = 0;
+
+ ANGLE_TRY(allocateTexture(resolveDesc, formatSet, &mCachedResolveTexture));
}
+
+ mDeviceContext->ResolveSubresource(mCachedResolveTexture.get(), 0,
+ renderTarget->getTexture().get(),
+ renderTarget->getSubresourceIndex(), formatSet.texFormat);
+ return mCachedResolveTexture;
}
bool Renderer11::getLUID(LUID *adapterLuid) const
{
adapterLuid->HighPart = 0;
- adapterLuid->LowPart = 0;
+ adapterLuid->LowPart = 0;
if (!mDxgiAdapter)
{
@@ -4078,45 +3783,70 @@ bool Renderer11::getLUID(LUID *adapterLuid) const
return true;
}
-VertexConversionType Renderer11::getVertexConversionType(gl::VertexFormatType vertexFormatType) const
+VertexConversionType Renderer11::getVertexConversionType(
+ gl::VertexFormatType vertexFormatType) const
{
- return d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel).conversionType;
+ return d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel)
+ .conversionType;
}
GLenum Renderer11::getVertexComponentType(gl::VertexFormatType vertexFormatType) const
{
- return d3d11::GetDXGIFormatInfo(d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel).nativeFormat).componentType;
+ const auto &format =
+ d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel);
+ return d3d11::GetComponentType(format.nativeFormat);
}
-void Renderer11::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps,
- gl::Extensions *outExtensions, gl::Limitations *outLimitations) const
+gl::ErrorOrResult<unsigned int> Renderer11::getVertexSpaceRequired(
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ GLsizei count,
+ GLsizei instances) const
{
- d3d11_gl::GenerateCaps(mDevice, mDeviceContext, mRenderer11DeviceCaps, outCaps, outTextureCaps,
- outExtensions, outLimitations);
-}
+ if (!attrib.enabled)
+ {
+ return 16u;
+ }
-WorkaroundsD3D Renderer11::generateWorkarounds() const
-{
- return d3d11::GenerateWorkarounds(mRenderer11DeviceCaps.featureLevel);
+ unsigned int elementCount = 0;
+ const unsigned int divisor = binding.getDivisor();
+ if (instances == 0 || divisor == 0)
+ {
+ elementCount = count;
+ }
+ else
+ {
+ // Round up to divisor, if possible
+ elementCount = UnsignedCeilDivide(static_cast<unsigned int>(instances), divisor);
+ }
+
+ gl::VertexFormatType formatType = gl::GetVertexFormatType(attrib);
+ const D3D_FEATURE_LEVEL featureLevel = mRenderer11DeviceCaps.featureLevel;
+ const d3d11::VertexFormat &vertexFormatInfo =
+ d3d11::GetVertexFormatInfo(formatType, featureLevel);
+ const d3d11::DXGIFormatSize &dxgiFormatInfo =
+ d3d11::GetDXGIFormatSizeInfo(vertexFormatInfo.nativeFormat);
+ unsigned int elementSize = dxgiFormatInfo.pixelBytes;
+ if (elementSize > std::numeric_limits<unsigned int>::max() / elementCount)
+ {
+ return gl::OutOfMemory() << "New vertex buffer size would result in an overflow.";
+ }
+
+ return elementSize * elementCount;
}
-void Renderer11::createAnnotator()
+void Renderer11::generateCaps(gl::Caps *outCaps,
+ gl::TextureCapsMap *outTextureCaps,
+ gl::Extensions *outExtensions,
+ gl::Limitations *outLimitations) const
{
- // The D3D11 renderer must choose the D3D9 debug annotator because the D3D11 interface
- // method ID3DUserDefinedAnnotation::GetStatus on desktop builds doesn't work with the Graphics
- // Diagnostics tools in Visual Studio 2013.
- // The D3D9 annotator works properly for both D3D11 and D3D9.
- // Incorrect status reporting can cause ANGLE to log unnecessary debug events.
-#ifdef ANGLE_ENABLE_D3D9
- mAnnotator = new DebugAnnotator9();
-#else
- mAnnotator = new DebugAnnotator11();
-#endif
+ d3d11_gl::GenerateCaps(mDevice, mDeviceContext, mRenderer11DeviceCaps, outCaps, outTextureCaps,
+ outExtensions, outLimitations);
}
-gl::Error Renderer11::clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd)
+angle::WorkaroundsD3D Renderer11::generateWorkarounds() const
{
- return mStateManager.clearTextures(samplerType, rangeStart, rangeEnd);
+ return d3d11::GenerateWorkarounds(mRenderer11DeviceCaps, mAdapterDescription);
}
egl::Error Renderer11::getEGLDevice(DeviceImpl **device)
@@ -4136,6 +3866,224 @@ egl::Error Renderer11::getEGLDevice(DeviceImpl **device)
}
*device = static_cast<DeviceImpl *>(mEGLDevice);
- return egl::Error(EGL_SUCCESS);
+ return egl::NoError();
+}
+
+ContextImpl *Renderer11::createContext(const gl::ContextState &state)
+{
+ return new Context11(state, this);
+}
+
+FramebufferImpl *Renderer11::createDefaultFramebuffer(const gl::FramebufferState &state)
+{
+ return new Framebuffer11(state, this);
+}
+
+gl::Error Renderer11::getScratchMemoryBuffer(size_t requestedSize, angle::MemoryBuffer **bufferOut)
+{
+ if (!mScratchMemoryBuffer.get(requestedSize, bufferOut))
+ {
+ return gl::OutOfMemory() << "Failed to allocate internal buffer.";
+ }
+ return gl::NoError();
+}
+
+gl::Version Renderer11::getMaxSupportedESVersion() const
+{
+ return d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps.featureLevel);
+}
+
+gl::DebugAnnotator *Renderer11::getAnnotator()
+{
+ return mAnnotator;
+}
+
+gl::Error Renderer11::applyComputeShader(const gl::Context *context)
+{
+ ANGLE_TRY(ensureHLSLCompilerInitialized());
+
+ const auto &glState = context->getGLState();
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
+
+ ShaderExecutableD3D *computeExe = nullptr;
+ ANGLE_TRY(programD3D->getComputeExecutable(&computeExe));
+ ASSERT(computeExe != nullptr);
+
+ mStateManager.setComputeShader(&GetAs<ShaderExecutable11>(computeExe)->getComputeShader());
+ ANGLE_TRY(mStateManager.applyComputeUniforms(programD3D));
+
+ return gl::NoError();
+}
+
+gl::Error Renderer11::dispatchCompute(const gl::Context *context,
+ GLuint numGroupsX,
+ GLuint numGroupsY,
+ GLuint numGroupsZ)
+{
+ ANGLE_TRY(mStateManager.updateStateForCompute(context, numGroupsX, numGroupsY, numGroupsZ));
+ ANGLE_TRY(applyComputeShader(context));
+
+ mDeviceContext->Dispatch(numGroupsX, numGroupsY, numGroupsZ);
+
+ return gl::NoError();
+}
+
+gl::ErrorOrResult<TextureHelper11> Renderer11::createStagingTexture(
+ ResourceType textureType,
+ const d3d11::Format &formatSet,
+ const gl::Extents &size,
+ StagingAccess readAndWriteAccess)
+{
+ if (textureType == ResourceType::Texture2D)
+ {
+ D3D11_TEXTURE2D_DESC stagingDesc;
+ stagingDesc.Width = size.width;
+ stagingDesc.Height = size.height;
+ stagingDesc.MipLevels = 1;
+ stagingDesc.ArraySize = 1;
+ stagingDesc.Format = formatSet.texFormat;
+ stagingDesc.SampleDesc.Count = 1;
+ stagingDesc.SampleDesc.Quality = 0;
+ stagingDesc.Usage = D3D11_USAGE_STAGING;
+ stagingDesc.BindFlags = 0;
+ stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+ stagingDesc.MiscFlags = 0;
+
+ if (readAndWriteAccess == StagingAccess::READ_WRITE)
+ {
+ stagingDesc.CPUAccessFlags |= D3D11_CPU_ACCESS_WRITE;
+ }
+
+ TextureHelper11 stagingTex;
+ ANGLE_TRY(allocateTexture(stagingDesc, formatSet, &stagingTex));
+ return stagingTex;
+ }
+ ASSERT(textureType == ResourceType::Texture3D);
+
+ D3D11_TEXTURE3D_DESC stagingDesc;
+ stagingDesc.Width = size.width;
+ stagingDesc.Height = size.height;
+ stagingDesc.Depth = 1;
+ stagingDesc.MipLevels = 1;
+ stagingDesc.Format = formatSet.texFormat;
+ stagingDesc.Usage = D3D11_USAGE_STAGING;
+ stagingDesc.BindFlags = 0;
+ stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+ stagingDesc.MiscFlags = 0;
+
+ TextureHelper11 stagingTex;
+ ANGLE_TRY(allocateTexture(stagingDesc, formatSet, &stagingTex));
+ return stagingTex;
+}
+
+gl::Error Renderer11::allocateTexture(const D3D11_TEXTURE2D_DESC &desc,
+ const d3d11::Format &format,
+ const D3D11_SUBRESOURCE_DATA *initData,
+ TextureHelper11 *textureOut)
+{
+ d3d11::Texture2D texture;
+ ANGLE_TRY(mResourceManager11.allocate(this, &desc, initData, &texture));
+ textureOut->init(std::move(texture), desc, format);
+ return gl::NoError();
+}
+
+gl::Error Renderer11::allocateTexture(const D3D11_TEXTURE3D_DESC &desc,
+ const d3d11::Format &format,
+ const D3D11_SUBRESOURCE_DATA *initData,
+ TextureHelper11 *textureOut)
+{
+ d3d11::Texture3D texture;
+ ANGLE_TRY(mResourceManager11.allocate(this, &desc, initData, &texture));
+ textureOut->init(std::move(texture), desc, format);
+ return gl::NoError();
+}
+
+gl::Error Renderer11::getBlendState(const d3d11::BlendStateKey &key,
+ const d3d11::BlendState **outBlendState)
+{
+ return mStateCache.getBlendState(this, key, outBlendState);
+}
+
+gl::Error Renderer11::getRasterizerState(const gl::RasterizerState &rasterState,
+ bool scissorEnabled,
+ ID3D11RasterizerState **outRasterizerState)
+{
+ return mStateCache.getRasterizerState(this, rasterState, scissorEnabled, outRasterizerState);
+}
+
+gl::Error Renderer11::getDepthStencilState(const gl::DepthStencilState &dsState,
+ const d3d11::DepthStencilState **outDSState)
+{
+ return mStateCache.getDepthStencilState(this, dsState, outDSState);
+}
+
+gl::Error Renderer11::getSamplerState(const gl::SamplerState &samplerState,
+ ID3D11SamplerState **outSamplerState)
+{
+ return mStateCache.getSamplerState(this, samplerState, outSamplerState);
+}
+
+gl::Error Renderer11::clearRenderTarget(RenderTargetD3D *renderTarget,
+ const gl::ColorF &clearColorValue,
+ const float clearDepthValue,
+ const unsigned int clearStencilValue)
+{
+ RenderTarget11 *rt11 = GetAs<RenderTarget11>(renderTarget);
+
+ if (rt11->getDepthStencilView().valid())
+ {
+ const auto &format = rt11->getFormatSet();
+ const UINT clearFlags = (format.format().depthBits > 0 ? D3D11_CLEAR_DEPTH : 0) |
+ (format.format().stencilBits ? D3D11_CLEAR_STENCIL : 0);
+ mDeviceContext->ClearDepthStencilView(rt11->getDepthStencilView().get(), clearFlags,
+ clearDepthValue,
+ static_cast<UINT8>(clearStencilValue));
+ return gl::NoError();
+ }
+
+ ASSERT(rt11->getRenderTargetView().valid());
+ ID3D11RenderTargetView *rtv = rt11->getRenderTargetView().get();
+
+ // There are complications with some types of RTV and FL 9_3 with ClearRenderTargetView.
+ // See https://msdn.microsoft.com/en-us/library/windows/desktop/ff476388(v=vs.85).aspx
+ ASSERT(mRenderer11DeviceCaps.featureLevel > D3D_FEATURE_LEVEL_9_3 || !IsArrayRTV(rtv));
+
+ const auto &d3d11Format = rt11->getFormatSet();
+ const auto &glFormat = gl::GetSizedInternalFormatInfo(renderTarget->getInternalFormat());
+
+ gl::ColorF safeClearColor = clearColorValue;
+
+ if (d3d11Format.format().alphaBits > 0 && glFormat.alphaBits == 0)
+ {
+ safeClearColor.alpha = 1.0f;
+ }
+
+ mDeviceContext->ClearRenderTargetView(rtv, &safeClearColor.red);
+ return gl::NoError();
+}
+
+bool Renderer11::canSelectViewInVertexShader() const
+{
+ return !getWorkarounds().selectViewInGeometryShader &&
+ getRenderer11DeviceCaps().supportsVpRtIndexWriteFromVertexShader;
}
+
+gl::Error Renderer11::markTransformFeedbackUsage(const gl::Context *context)
+{
+ const gl::State &glState = context->getGLState();
+ const gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback();
+ for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
+ {
+ const gl::OffsetBindingPointer<gl::Buffer> &binding =
+ transformFeedback->getIndexedBuffer(i);
+ if (binding.get() != nullptr)
+ {
+ BufferD3D *bufferD3D = GetImplAs<BufferD3D>(binding.get());
+ ANGLE_TRY(bufferD3D->markTransformFeedbackUsage(context));
+ }
+ }
+
+ return gl::NoError();
}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
index b4e7761ffc..a8c24e681b 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
@@ -14,13 +14,14 @@
#include "libANGLE/AttributeMap.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/renderer/d3d/HLSLCompiler.h"
-#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h"
-#include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h"
-#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h"
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
#include "libANGLE/renderer/d3d/d3d11/StateManager11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
namespace gl
{
@@ -28,36 +29,46 @@ class FramebufferAttachment;
struct ImageIndex;
}
-struct ID3D11DeviceContext1;
-
namespace rx
{
-
-class VertexDataManager;
-class IndexDataManager;
-class StreamingIndexBufferInterface;
class Blit11;
class Buffer11;
class Clear11;
+class Context11;
+class IndexDataManager;
+struct PackPixelsParams;
class PixelTransfer11;
class RenderTarget11;
+class StreamingIndexBufferInterface;
class Trim11;
-struct PackPixelsParams;
+class VertexDataManager;
struct Renderer11DeviceCaps
{
+ Renderer11DeviceCaps();
+
D3D_FEATURE_LEVEL featureLevel;
- bool supportsDXGI1_2; // Support for DXGI 1.2
- bool supportsClearView; // Support for ID3D11DeviceContext1::ClearView
- bool supportsConstantBufferOffsets; // Support for Constant buffer offset
- UINT B5G6R5support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B5G6R5_UNORM
- UINT B4G4R4A4support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B4G4R4A4_UNORM
- UINT B5G5R5A1support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B5G5R5A1_UNORM
+ bool supportsDXGI1_2; // Support for DXGI 1.2
+ bool supportsClearView; // Support for ID3D11DeviceContext1::ClearView
+ bool supportsConstantBufferOffsets; // Support for Constant buffer offset
+ bool supportsVpRtIndexWriteFromVertexShader; // VP/RT can be selected in the Vertex Shader
+ // stage.
+ bool supportsMultisampledDepthStencilSRVs; // D3D feature level 10.0 no longer allows creation
+ // of textures with both the bind SRV and DSV flags
+ // when multisampled. Textures will need to be
+ // resolved before reading. crbug.com/656989
+ UINT B5G6R5support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B5G6R5_UNORM
+ UINT B5G6R5maxSamples; // Maximum number of samples supported by DXGI_FORMAT_B5G6R5_UNORM
+ UINT B4G4R4A4support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B4G4R4A4_UNORM
+ UINT B4G4R4A4maxSamples; // Maximum number of samples supported by DXGI_FORMAT_B4G4R4A4_UNORM
+ UINT B5G5R5A1support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B5G5R5A1_UNORM
+ UINT B5G5R5A1maxSamples; // Maximum number of samples supported by DXGI_FORMAT_B5G5R5A1_UNORM
+ Optional<LARGE_INTEGER> driverVersion; // Four-part driver version number.
};
enum
{
- MAX_VERTEX_UNIFORM_VECTORS_D3D11 = 1024,
+ MAX_VERTEX_UNIFORM_VECTORS_D3D11 = 1024,
MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 = 1024
};
@@ -103,172 +114,244 @@ class Renderer11 : public RendererD3D
{
public:
explicit Renderer11(egl::Display *display);
- virtual ~Renderer11();
+ ~Renderer11() override;
egl::Error initialize() override;
- virtual bool resetDevice();
+ bool resetDevice() override;
- egl::ConfigSet generateConfigs() const override;
+ egl::ConfigSet generateConfigs() override;
void generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const override;
- gl::Error flush() override;
- gl::Error finish() override;
+ ContextImpl *createContext(const gl::ContextState &state) override;
+
+ gl::Error flush();
+ gl::Error finish();
- SwapChainD3D *createSwapChain(NativeWindow nativeWindow,
+ bool isValidNativeWindow(EGLNativeWindowType window) const override;
+ NativeWindowD3D *createNativeWindow(EGLNativeWindowType window,
+ const egl::Config *config,
+ const egl::AttributeMap &attribs) const override;
+
+ SwapChainD3D *createSwapChain(NativeWindowD3D *nativeWindow,
HANDLE shareHandle,
+ IUnknown *d3dTexture,
GLenum backBufferFormat,
GLenum depthBufferFormat,
- EGLint orientation) override;
-
- CompilerImpl *createCompiler() override;
-
- virtual gl::Error generateSwizzle(gl::Texture *texture);
- virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler);
- virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture);
-
- gl::Error setUniformBuffers(const gl::Data &data,
- const std::vector<GLint> &vertexUniformBuffers,
- const std::vector<GLint> &fragmentUniformBuffers) override;
-
- gl::Error updateState(const gl::Data &data, GLenum drawMode) override;
-
- virtual bool applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize);
- gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) override;
- gl::Error applyUniforms(const ProgramD3D &programD3D,
- GLenum drawMode,
- const std::vector<D3DUniform *> &uniformArray) override;
- virtual gl::Error applyVertexBuffer(const gl::State &state,
- GLenum mode,
- GLint first,
- GLsizei count,
- GLsizei instances,
- TranslatedIndexData *indexInfo);
- gl::Error applyIndexBuffer(const gl::Data &data,
- const GLvoid *indices,
- GLsizei count,
- GLenum mode,
- GLenum type,
- TranslatedIndexData *indexInfo) override;
- void applyTransformFeedbackBuffers(const gl::State &state) override;
+ EGLint orientation,
+ EGLint samples) override;
+ egl::Error getD3DTextureInfo(const egl::Config *configuration,
+ IUnknown *d3dTexture,
+ EGLint *width,
+ EGLint *height,
+ GLenum *fboFormat) const override;
+ egl::Error validateShareHandle(const egl::Config *config,
+ HANDLE shareHandle,
+ const egl::AttributeMap &attribs) const override;
+
+ bool applyPrimitiveType(const gl::State &glState, GLenum mode, GLsizei count);
// lost device
bool testDeviceLost() override;
bool testDeviceResettable() override;
- std::string getRendererDescription() const override;
+ std::string getRendererDescription() const;
DeviceIdentifier getAdapterIdentifier() const override;
- virtual unsigned int getReservedVertexUniformVectors() const;
- virtual unsigned int getReservedFragmentUniformVectors() const;
- virtual unsigned int getReservedVertexUniformBuffers() const;
- virtual unsigned int getReservedFragmentUniformBuffers() const;
+ unsigned int getReservedVertexUniformVectors() const;
+ unsigned int getReservedFragmentUniformVectors() const;
+ unsigned int getReservedVertexUniformBuffers() const;
+ unsigned int getReservedFragmentUniformBuffers() const;
bool getShareHandleSupport() const;
- virtual int getMajorShaderModel() const;
+ bool getNV12TextureSupport() const;
+
+ int getMajorShaderModel() const override;
int getMinorShaderModel() const override;
std::string getShaderModelSuffix() const override;
// Pixel operations
- virtual gl::Error copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- const gl::Offset &destOffset, TextureStorage *storage, GLint level);
- virtual gl::Error copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level);
- virtual gl::Error copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- const gl::Offset &destOffset, TextureStorage *storage, GLint level);
- virtual gl::Error copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- const gl::Offset &destOffset, TextureStorage *storage, GLint level);
+ gl::Error copyImage2D(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level) override;
+ gl::Error copyImageCube(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLenum target,
+ GLint level) override;
+ gl::Error copyImage3D(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level) override;
+ gl::Error copyImage2DArray(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level) override;
+
+ gl::Error copyTexture(const gl::Context *context,
+ const gl::Texture *source,
+ GLint sourceLevel,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLenum destTarget,
+ GLint destLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha) override;
+ gl::Error copyCompressedTexture(const gl::Context *context,
+ const gl::Texture *source,
+ GLint sourceLevel,
+ TextureStorage *storage,
+ GLint destLevel) override;
// RenderTarget creation
- virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT);
+ gl::Error createRenderTarget(int width,
+ int height,
+ GLenum format,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
gl::Error createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) override;
- // Framebuffer creation
- FramebufferImpl *createFramebuffer(const gl::Framebuffer::Data &data) override;
-
- // Shader creation
- ShaderImpl *createShader(const gl::Shader::Data &data) override;
- ProgramImpl *createProgram(const gl::Program::Data &data) override;
-
// Shader operations
- gl::Error loadExecutable(const void *function,
+ gl::Error loadExecutable(const uint8_t *function,
size_t length,
- ShaderType type,
+ gl::ShaderType type,
const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers,
ShaderExecutableD3D **outExecutable) override;
gl::Error compileToExecutable(gl::InfoLog &infoLog,
const std::string &shaderHLSL,
- ShaderType type,
+ gl::ShaderType type,
const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers,
- const D3DCompilerWorkarounds &workarounds,
+ const angle::CompilerWorkaroundsD3D &workarounds,
ShaderExecutableD3D **outExectuable) override;
+ gl::Error ensureHLSLCompilerInitialized() override;
+
UniformStorageD3D *createUniformStorage(size_t storageSize) override;
// Image operations
- virtual ImageD3D *createImage();
- gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override;
- gl::Error generateMipmapsUsingD3D(TextureStorage *storage,
- const gl::TextureState &textureState) override;
- virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain);
- TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage) override;
- virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly);
- virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly);
- virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels);
- virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels);
-
- // Texture creation
- virtual TextureImpl *createTexture(GLenum target);
-
- // Renderbuffer creation
- virtual RenderbufferImpl *createRenderbuffer();
-
- // Buffer creation
- virtual BufferImpl *createBuffer();
- virtual VertexBuffer *createVertexBuffer();
- virtual IndexBuffer *createIndexBuffer();
-
- // Vertex Array creation
- VertexArrayImpl *createVertexArray(const gl::VertexArray::Data &data) override;
-
- // Query and Fence creation
- virtual QueryImpl *createQuery(GLenum type);
- virtual FenceNVImpl *createFenceNV();
- virtual FenceSyncImpl *createFenceSync();
-
- // Transform Feedback creation
- virtual TransformFeedbackImpl* createTransformFeedback();
+ ImageD3D *createImage() override;
+ gl::Error generateMipmap(const gl::Context *context, ImageD3D *dest, ImageD3D *source) override;
+ gl::Error generateMipmapUsingD3D(const gl::Context *context,
+ TextureStorage *storage,
+ const gl::TextureState &textureState) override;
+ gl::Error copyImage(const gl::Context *context,
+ ImageD3D *dest,
+ ImageD3D *source,
+ const gl::Rectangle &sourceRect,
+ const gl::Offset &destOffset,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha) override;
+ TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain) override;
+ TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage,
+ RenderTargetD3D *renderTargetD3D) override;
+ TextureStorage *createTextureStorageExternal(
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc) override;
+ TextureStorage *createTextureStorage2D(GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ bool hintLevelZeroOnly) override;
+ TextureStorage *createTextureStorageCube(GLenum internalformat,
+ bool renderTarget,
+ int size,
+ int levels,
+ bool hintLevelZeroOnly) override;
+ TextureStorage *createTextureStorage3D(GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels) override;
+ TextureStorage *createTextureStorage2DArray(GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels) override;
+ TextureStorage *createTextureStorage2DMultisample(GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ int samples,
+ bool fixedSampleLocations) override;
+
+ VertexBuffer *createVertexBuffer() override;
+ IndexBuffer *createIndexBuffer() override;
+
+ // Stream Creation
+ StreamProducerImpl *createStreamProducerD3DTextureNV12(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs) override;
// D3D11-renderer specific methods
ID3D11Device *getDevice() { return mDevice; }
void *getD3DDevice() override;
ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; };
ID3D11DeviceContext1 *getDeviceContext1IfSupported() { return mDeviceContext1; };
- DXGIFactory *getDxgiFactory() { return mDxgiFactory; };
-
- RenderStateCache &getStateCache() { return mStateCache; }
+ IDXGIFactory *getDxgiFactory() { return mDxgiFactory; };
+
+ gl::Error getBlendState(const d3d11::BlendStateKey &key,
+ const d3d11::BlendState **outBlendState);
+ gl::Error getRasterizerState(const gl::RasterizerState &rasterState,
+ bool scissorEnabled,
+ ID3D11RasterizerState **outRasterizerState);
+ gl::Error getDepthStencilState(const gl::DepthStencilState &dsState,
+ const d3d11::DepthStencilState **outDSState);
+ gl::Error getSamplerState(const gl::SamplerState &samplerState,
+ ID3D11SamplerState **outSamplerState);
Blit11 *getBlitter() { return mBlit; }
Clear11 *getClearer() { return mClear; }
+ gl::DebugAnnotator *getAnnotator();
// Buffer-to-texture and Texture-to-buffer copies
- virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const;
- virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget,
- GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea);
+ bool supportsFastCopyBufferToTexture(GLenum internalFormat) const override;
+ gl::Error fastCopyBufferToTexture(const gl::Context *context,
+ const gl::PixelUnpackState &unpack,
+ unsigned int offset,
+ RenderTargetD3D *destRenderTarget,
+ GLenum destinationFormat,
+ GLenum sourcePixelsType,
+ const gl::Box &destArea) override;
- void markAllStateDirty();
- void unapplyRenderTargets();
- void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView);
gl::Error packPixels(const TextureHelper11 &textureHelper,
const PackPixelsParams &params,
uint8_t *pixelsOut);
bool getLUID(LUID *adapterLuid) const override;
- VertexConversionType getVertexConversionType(gl::VertexFormatType vertexFormatType) const override;
+ VertexConversionType getVertexConversionType(
+ gl::VertexFormatType vertexFormatType) const override;
GLenum getVertexComponentType(gl::VertexFormatType vertexFormatType) const override;
- gl::Error readFromAttachment(const gl::FramebufferAttachment &srcAttachment,
+ // Warning: you should ensure binding really matches attrib.bindingIndex before using this
+ // function.
+ gl::ErrorOrResult<unsigned int> getVertexSpaceRequired(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ GLsizei count,
+ GLsizei instances) const override;
+
+ gl::Error readFromAttachment(const gl::Context *context,
+ const gl::FramebufferAttachment &srcAttachment,
const gl::Rectangle &sourceArea,
GLenum format,
GLenum type,
@@ -276,145 +359,175 @@ class Renderer11 : public RendererD3D
const gl::PixelPackState &pack,
uint8_t *pixels);
- gl::Error blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTargetD3D *readRenderTarget,
- RenderTargetD3D *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor,
- bool colorBlit, bool depthBlit, bool stencilBlit);
+ gl::Error blitRenderbufferRect(const gl::Context *context,
+ const gl::Rectangle &readRect,
+ const gl::Rectangle &drawRect,
+ RenderTargetD3D *readRenderTarget,
+ RenderTargetD3D *drawRenderTarget,
+ GLenum filter,
+ const gl::Rectangle *scissor,
+ bool colorBlit,
+ bool depthBlit,
+ bool stencilBlit);
bool isES3Capable() const;
- const Renderer11DeviceCaps &getRenderer11DeviceCaps() { return mRenderer11DeviceCaps; };
+ const Renderer11DeviceCaps &getRenderer11DeviceCaps() const { return mRenderer11DeviceCaps; };
- RendererClass getRendererClass() const override { return RENDERER_D3D11; }
- InputLayoutCache *getInputLayoutCache() { return &mInputLayoutCache; }
+ RendererClass getRendererClass() const override;
StateManager11 *getStateManager() { return &mStateManager; }
void onSwap();
+ void onBufferCreate(const Buffer11 *created);
void onBufferDelete(const Buffer11 *deleted);
egl::Error getEGLDevice(DeviceImpl **device) override;
- protected:
- void createAnnotator() override;
- gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) override;
- gl::Error applyShadersImpl(const gl::Data &data, GLenum drawMode) override;
+ gl::Error drawArrays(const gl::Context *context,
+ GLenum mode,
+ GLint startVertex,
+ GLsizei count,
+ GLsizei instances);
- void syncState(const gl::State &state, const gl::State::DirtyBits &bitmask) override;
+ gl::Error drawElements(const gl::Context *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei instances);
+
+ gl::Error drawArraysIndirect(const gl::Context *context, GLenum mode, const void *indirect);
+ gl::Error drawElementsIndirect(const gl::Context *context,
+ GLenum mode,
+ GLenum type,
+ const void *indirect);
+
+ // Necessary hack for default framebuffers in D3D.
+ FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
+
+ gl::Error getScratchMemoryBuffer(size_t requestedSize, angle::MemoryBuffer **bufferOut);
+
+ gl::Version getMaxSupportedESVersion() const override;
+
+ gl::Error dispatchCompute(const gl::Context *context,
+ GLuint numGroupsX,
+ GLuint numGroupsY,
+ GLuint numGroupsZ);
+ gl::Error applyComputeShader(const gl::Context *context);
+
+ gl::ErrorOrResult<TextureHelper11> createStagingTexture(ResourceType textureType,
+ const d3d11::Format &formatSet,
+ const gl::Extents &size,
+ StagingAccess readAndWriteAccess);
+
+ template <typename DescT, typename ResourceT>
+ gl::Error allocateResource(const DescT &desc, ResourceT *resourceOut)
+ {
+ return mResourceManager11.allocate(this, &desc, nullptr, resourceOut);
+ }
+
+ template <typename DescT, typename InitDataT, typename ResourceT>
+ gl::Error allocateResource(const DescT &desc, InitDataT *initData, ResourceT *resourceOut)
+ {
+ return mResourceManager11.allocate(this, &desc, initData, resourceOut);
+ }
+
+ template <typename InitDataT, typename ResourceT>
+ gl::Error allocateResourceNoDesc(InitDataT *initData, ResourceT *resourceOut)
+ {
+ return mResourceManager11.allocate(this, nullptr, initData, resourceOut);
+ }
+
+ template <typename DescT>
+ gl::Error allocateTexture(const DescT &desc,
+ const d3d11::Format &format,
+ TextureHelper11 *textureOut)
+ {
+ return allocateTexture(desc, format, nullptr, textureOut);
+ }
+
+ gl::Error allocateTexture(const D3D11_TEXTURE2D_DESC &desc,
+ const d3d11::Format &format,
+ const D3D11_SUBRESOURCE_DATA *initData,
+ TextureHelper11 *textureOut);
+
+ gl::Error allocateTexture(const D3D11_TEXTURE3D_DESC &desc,
+ const d3d11::Format &format,
+ const D3D11_SUBRESOURCE_DATA *initData,
+ TextureHelper11 *textureOut);
+
+ gl::Error clearRenderTarget(RenderTargetD3D *renderTarget,
+ const gl::ColorF &clearColorValue,
+ const float clearDepthValue,
+ const unsigned int clearStencilValue) override;
+
+ bool canSelectViewInVertexShader() const override;
private:
- gl::Error drawArraysImpl(const gl::Data &data,
- GLenum mode,
- GLsizei count,
- GLsizei instances) override;
- gl::Error drawElementsImpl(const gl::Data &data,
- const TranslatedIndexData &indexInfo,
- GLenum mode,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- GLsizei instances) override;
-
- void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps,
+ void generateCaps(gl::Caps *outCaps,
+ gl::TextureCapsMap *outTextureCaps,
gl::Extensions *outExtensions,
gl::Limitations *outLimitations) const override;
- WorkaroundsD3D generateWorkarounds() const override;
+ angle::WorkaroundsD3D generateWorkarounds() const override;
- gl::Error drawLineLoop(const gl::Data &data,
+ gl::Error drawLineLoop(const gl::Context *context,
GLsizei count,
GLenum type,
- const GLvoid *indices,
- const TranslatedIndexData *indexInfo,
+ const void *indices,
+ int baseVertex,
int instances);
- gl::Error drawTriangleFan(const gl::Data &data,
+ gl::Error drawTriangleFan(const gl::Context *context,
GLsizei count,
GLenum type,
- const GLvoid *indices,
- int minIndex,
+ const void *indices,
+ int baseVertex,
int instances);
- ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource);
+ gl::ErrorOrResult<TextureHelper11> resolveMultisampledTexture(const gl::Context *context,
+ RenderTarget11 *renderTarget,
+ bool depth,
+ bool stencil);
void populateRenderer11DeviceCaps();
void updateHistograms();
- HMODULE mD3d11Module;
- HMODULE mDxgiModule;
- HMODULE mDCompModule;
- std::vector<D3D_FEATURE_LEVEL> mAvailableFeatureLevels;
- D3D_DRIVER_TYPE mRequestedDriverType;
- bool mCreatedWithDeviceEXT;
- DeviceD3D *mEGLDevice;
+ gl::Error copyImageInternal(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ RenderTargetD3D *destRenderTarget);
- HLSLCompiler mCompiler;
+ gl::SupportedSampleSet generateSampleSetForEGLConfig(
+ const gl::TextureCaps &colorBufferFormatCaps,
+ const gl::TextureCaps &depthStencilBufferFormatCaps) const;
+ HRESULT callD3D11CreateDevice(PFN_D3D11_CREATE_DEVICE createDevice, bool debug);
egl::Error initializeD3DDevice();
- void initializeDevice();
+ egl::Error initializeDevice();
void releaseDeviceResources();
void release();
d3d11::ANGLED3D11DeviceType getDeviceType() const;
- RenderStateCache mStateCache;
+ gl::Error markTransformFeedbackUsage(const gl::Context *context);
- // current render target states
- uintptr_t mAppliedRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS];
- uintptr_t mAppliedDSV;
+ HMODULE mD3d11Module;
+ HMODULE mDxgiModule;
+ HMODULE mDCompModule;
+ std::vector<D3D_FEATURE_LEVEL> mAvailableFeatureLevels;
+ D3D_DRIVER_TYPE mRequestedDriverType;
+ bool mCreateDebugDevice;
+ bool mCreatedWithDeviceEXT;
+ DeviceD3D *mEGLDevice;
- // Currently applied sampler states
- std::vector<bool> mForceSetVertexSamplerStates;
- std::vector<gl::SamplerState> mCurVertexSamplerStates;
+ HLSLCompiler mCompiler;
- std::vector<bool> mForceSetPixelSamplerStates;
- std::vector<gl::SamplerState> mCurPixelSamplerStates;
+ RenderStateCache mStateCache;
StateManager11 mStateManager;
- // Currently applied primitive topology
- D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology;
-
- // Currently applied index buffer
- ID3D11Buffer *mAppliedIB;
- DXGI_FORMAT mAppliedIBFormat;
- unsigned int mAppliedIBOffset;
- bool mAppliedIBChanged;
-
- // Currently applied transform feedback buffers
- size_t mAppliedNumXFBBindings;
- ID3D11Buffer *mAppliedTFBuffers[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the current D3D buffers
- // in use for streamout
- GLintptr mAppliedTFOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the current GL-specified
- // buffer offsets to transform feedback
- // buffers
- UINT mCurrentD3DOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the D3D buffer offsets,
- // which may differ from GLs, due
- // to different append behavior
-
- // Currently applied shaders
- uintptr_t mAppliedVertexShader;
- uintptr_t mAppliedGeometryShader;
- uintptr_t mAppliedPixelShader;
-
- dx_VertexConstants11 mAppliedVertexConstants;
- ID3D11Buffer *mDriverConstantBufferVS;
- ID3D11Buffer *mCurrentVertexConstantBuffer;
- unsigned int mCurrentConstantBufferVS[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS];
- GLintptr mCurrentConstantBufferVSOffset[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS];
- GLsizeiptr mCurrentConstantBufferVSSize[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS];
-
- dx_PixelConstants11 mAppliedPixelConstants;
- ID3D11Buffer *mDriverConstantBufferPS;
- ID3D11Buffer *mCurrentPixelConstantBuffer;
- unsigned int mCurrentConstantBufferPS[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS];
- GLintptr mCurrentConstantBufferPSOffset[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS];
- GLsizeiptr mCurrentConstantBufferPSSize[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS];
-
- ID3D11Buffer *mCurrentGeometryConstantBuffer;
-
- // Vertex, index and input layouts
- VertexDataManager *mVertexDataManager;
- IndexDataManager *mIndexDataManager;
- InputLayoutCache mInputLayoutCache;
-
StreamingIndexBufferInterface *mLineLoopIB;
StreamingIndexBufferInterface *mTriangleFanIB;
@@ -429,10 +542,10 @@ class Renderer11 : public RendererD3D
Trim11 *mTrim;
// Sync query
- ID3D11Query *mSyncQuery;
+ d3d11::Query mSyncQuery;
// Created objects state tracking
- std::set<const Buffer11*> mAliveBuffers;
+ std::set<const Buffer11 *> mAliveBuffers;
double mLastHistogramUpdateTime;
@@ -440,18 +553,24 @@ class Renderer11 : public RendererD3D
Renderer11DeviceCaps mRenderer11DeviceCaps;
ID3D11DeviceContext *mDeviceContext;
ID3D11DeviceContext1 *mDeviceContext1;
+ ID3D11DeviceContext3 *mDeviceContext3;
IDXGIAdapter *mDxgiAdapter;
DXGI_ADAPTER_DESC mAdapterDescription;
char mDescription[128];
- DXGIFactory *mDxgiFactory;
-#if !defined(ANGLE_MINGW32_COMPAT)
+ IDXGIFactory *mDxgiFactory;
ID3D11Debug *mDebug;
-#endif
std::vector<GLuint> mScratchIndexDataBuffer;
+ angle::ScratchBuffer mScratchMemoryBuffer;
+
+ gl::DebugAnnotator *mAnnotator;
+
mutable Optional<bool> mSupportsShareHandles;
+ ResourceManager11 mResourceManager11;
+
+ TextureHelper11 mCachedResolveTexture;
};
-}
-#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_
+} // namespace rx
+#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp
new file mode 100644
index 0000000000..c228380a34
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp
@@ -0,0 +1,533 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ResourceManager11:
+// Centralized point of allocation for all D3D11 Resources.
+
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+
+namespace rx
+{
+
+namespace
+{
+
+constexpr uint8_t kDebugInitTextureDataValue = 0x48;
+constexpr FLOAT kDebugColorInitClearValue[4] = {0.3f, 0.5f, 0.7f, 0.5f};
+constexpr FLOAT kDebugDepthInitValue = 0.2f;
+constexpr UINT8 kDebugStencilInitValue = 3;
+
+uint64_t ComputeMippedMemoryUsage(unsigned int width,
+ unsigned int height,
+ unsigned int depth,
+ uint64_t pixelSize,
+ unsigned int mipLevels)
+{
+ uint64_t sizeSum = 0;
+
+ for (unsigned int level = 0; level < mipLevels; ++level)
+ {
+ unsigned int mipWidth = std::max(width >> level, 1u);
+ unsigned int mipHeight = std::max(height >> level, 1u);
+ unsigned int mipDepth = std::max(depth >> level, 1u);
+ sizeSum += static_cast<uint64_t>(mipWidth * mipHeight * mipDepth) * pixelSize;
+ }
+
+ return sizeSum;
+}
+
+uint64_t ComputeMemoryUsage(const D3D11_TEXTURE2D_DESC *desc)
+{
+ ASSERT(desc);
+ uint64_t pixelBytes =
+ static_cast<uint64_t>(d3d11::GetDXGIFormatSizeInfo(desc->Format).pixelBytes);
+ return ComputeMippedMemoryUsage(desc->Width, desc->Height, 1, pixelBytes, desc->MipLevels);
+}
+
+uint64_t ComputeMemoryUsage(const D3D11_TEXTURE3D_DESC *desc)
+{
+ ASSERT(desc);
+ uint64_t pixelBytes =
+ static_cast<uint64_t>(d3d11::GetDXGIFormatSizeInfo(desc->Format).pixelBytes);
+ return ComputeMippedMemoryUsage(desc->Width, desc->Height, desc->Depth, pixelBytes,
+ desc->MipLevels);
+}
+
+uint64_t ComputeMemoryUsage(const D3D11_BUFFER_DESC *desc)
+{
+ ASSERT(desc);
+ return static_cast<uint64_t>(desc->ByteWidth);
+}
+
+template <typename T>
+uint64_t ComputeMemoryUsage(const T *desc)
+{
+ return 0;
+}
+
+template <ResourceType ResourceT>
+uint64_t ComputeGenericMemoryUsage(ID3D11DeviceChild *genericResource)
+{
+ auto *typedResource = static_cast<GetD3D11Type<ResourceT> *>(genericResource);
+ GetDescType<ResourceT> desc;
+ typedResource->GetDesc(&desc);
+ return ComputeMemoryUsage(&desc);
+}
+
+uint64_t ComputeGenericMemoryUsage(ResourceType resourceType, ID3D11DeviceChild *resource)
+{
+ switch (resourceType)
+ {
+ case ResourceType::Texture2D:
+ return ComputeGenericMemoryUsage<ResourceType::Texture2D>(resource);
+ case ResourceType::Texture3D:
+ return ComputeGenericMemoryUsage<ResourceType::Texture3D>(resource);
+ case ResourceType::Buffer:
+ return ComputeGenericMemoryUsage<ResourceType::Buffer>(resource);
+
+ default:
+ return 0;
+ }
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const D3D11_BLEND_DESC *desc,
+ void * /*initData*/,
+ ID3D11BlendState **blendState)
+{
+ return device->CreateBlendState(desc, blendState);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const D3D11_BUFFER_DESC *desc,
+ const D3D11_SUBRESOURCE_DATA *initData,
+ ID3D11Buffer **buffer)
+{
+ return device->CreateBuffer(desc, initData, buffer);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const ShaderData *desc,
+ void * /*initData*/,
+ ID3D11ComputeShader **resourceOut)
+{
+ return device->CreateComputeShader(desc->get(), desc->size(), nullptr, resourceOut);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const D3D11_DEPTH_STENCIL_DESC *desc,
+ void * /*initData*/,
+ ID3D11DepthStencilState **resourceOut)
+{
+ return device->CreateDepthStencilState(desc, resourceOut);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const D3D11_DEPTH_STENCIL_VIEW_DESC *desc,
+ ID3D11Resource *resource,
+ ID3D11DepthStencilView **resourceOut)
+{
+ return device->CreateDepthStencilView(resource, desc, resourceOut);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const ShaderData *desc,
+ const std::vector<D3D11_SO_DECLARATION_ENTRY> *initData,
+ ID3D11GeometryShader **resourceOut)
+{
+ if (initData)
+ {
+ return device->CreateGeometryShaderWithStreamOutput(
+ desc->get(), desc->size(), initData->data(), static_cast<UINT>(initData->size()),
+ nullptr, 0, 0, nullptr, resourceOut);
+ }
+ else
+ {
+ return device->CreateGeometryShader(desc->get(), desc->size(), nullptr, resourceOut);
+ }
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const InputElementArray *desc,
+ const ShaderData *initData,
+ ID3D11InputLayout **resourceOut)
+{
+ return device->CreateInputLayout(desc->get(), static_cast<UINT>(desc->size()), initData->get(),
+ initData->size(), resourceOut);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const ShaderData *desc,
+ void * /*initData*/,
+ ID3D11PixelShader **resourceOut)
+{
+ return device->CreatePixelShader(desc->get(), desc->size(), nullptr, resourceOut);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const D3D11_QUERY_DESC *desc,
+ void * /*initData*/,
+ ID3D11Query **resourceOut)
+{
+ return device->CreateQuery(desc, resourceOut);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const D3D11_RASTERIZER_DESC *desc,
+ void * /*initData*/,
+ ID3D11RasterizerState **rasterizerState)
+{
+ return device->CreateRasterizerState(desc, rasterizerState);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const D3D11_RENDER_TARGET_VIEW_DESC *desc,
+ ID3D11Resource *resource,
+ ID3D11RenderTargetView **renderTargetView)
+{
+ return device->CreateRenderTargetView(resource, desc, renderTargetView);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const D3D11_SAMPLER_DESC *desc,
+ void * /*initData*/,
+ ID3D11SamplerState **resourceOut)
+{
+ return device->CreateSamplerState(desc, resourceOut);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const D3D11_SHADER_RESOURCE_VIEW_DESC *desc,
+ ID3D11Resource *resource,
+ ID3D11ShaderResourceView **resourceOut)
+{
+ return device->CreateShaderResourceView(resource, desc, resourceOut);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const D3D11_TEXTURE2D_DESC *desc,
+ const D3D11_SUBRESOURCE_DATA *initData,
+ ID3D11Texture2D **texture)
+{
+ return device->CreateTexture2D(desc, initData, texture);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const D3D11_TEXTURE3D_DESC *desc,
+ const D3D11_SUBRESOURCE_DATA *initData,
+ ID3D11Texture3D **texture)
+{
+ return device->CreateTexture3D(desc, initData, texture);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const ShaderData *desc,
+ void * /*initData*/,
+ ID3D11VertexShader **resourceOut)
+{
+ return device->CreateVertexShader(desc->get(), desc->size(), nullptr, resourceOut);
+}
+
+DXGI_FORMAT GetTypedDepthStencilFormat(DXGI_FORMAT dxgiFormat)
+{
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R16_TYPELESS:
+ return DXGI_FORMAT_D16_UNORM;
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ return DXGI_FORMAT_D24_UNORM_S8_UINT;
+ case DXGI_FORMAT_R32_TYPELESS:
+ return DXGI_FORMAT_D32_FLOAT;
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
+ default:
+ return dxgiFormat;
+ }
+}
+
+template <typename DescT, typename ResourceT>
+gl::Error ClearResource(Renderer11 *renderer, const DescT *desc, ResourceT *texture)
+{
+ // No-op.
+ return gl::NoError();
+}
+
+template <>
+gl::Error ClearResource(Renderer11 *renderer,
+ const D3D11_TEXTURE2D_DESC *desc,
+ ID3D11Texture2D *texture)
+{
+ ID3D11DeviceContext *context = renderer->getDeviceContext();
+
+ if ((desc->BindFlags & D3D11_BIND_DEPTH_STENCIL) != 0)
+ {
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+ dsvDesc.Flags = 0;
+ dsvDesc.Format = GetTypedDepthStencilFormat(desc->Format);
+
+ const auto &format = d3d11_angle::GetFormat(dsvDesc.Format);
+ UINT clearFlags = (format.depthBits > 0 ? D3D11_CLEAR_DEPTH : 0) |
+ (format.stencilBits > 0 ? D3D11_CLEAR_STENCIL : 0);
+
+ // Must process each mip level individually.
+ for (UINT mipLevel = 0; mipLevel < desc->MipLevels; ++mipLevel)
+ {
+ if (desc->SampleDesc.Count == 0)
+ {
+ dsvDesc.Texture2D.MipSlice = mipLevel;
+ dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+ }
+ else
+ {
+ dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
+ }
+
+ d3d11::DepthStencilView dsv;
+ ANGLE_TRY(renderer->allocateResource(dsvDesc, texture, &dsv));
+
+ context->ClearDepthStencilView(dsv.get(), clearFlags, kDebugDepthInitValue,
+ kDebugStencilInitValue);
+ }
+ }
+ else
+ {
+ ASSERT((desc->BindFlags & D3D11_BIND_RENDER_TARGET) != 0);
+ d3d11::RenderTargetView rtv;
+ ANGLE_TRY(renderer->allocateResourceNoDesc(texture, &rtv));
+
+ context->ClearRenderTargetView(rtv.get(), kDebugColorInitClearValue);
+ }
+
+ return gl::NoError();
+}
+
+template <>
+gl::Error ClearResource(Renderer11 *renderer,
+ const D3D11_TEXTURE3D_DESC *desc,
+ ID3D11Texture3D *texture)
+{
+ ID3D11DeviceContext *context = renderer->getDeviceContext();
+
+ ASSERT((desc->BindFlags & D3D11_BIND_DEPTH_STENCIL) == 0);
+ ASSERT((desc->BindFlags & D3D11_BIND_RENDER_TARGET) != 0);
+
+ d3d11::RenderTargetView rtv;
+ ANGLE_TRY(renderer->allocateResourceNoDesc(texture, &rtv));
+
+ context->ClearRenderTargetView(rtv.get(), kDebugColorInitClearValue);
+ return gl::NoError();
+}
+
+#define ANGLE_RESOURCE_STRINGIFY_OP(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) #RESTYPE,
+
+constexpr std::array<const char *, NumResourceTypes> kResourceTypeNames = {
+ {ANGLE_RESOURCE_TYPE_OP(Stringify, ANGLE_RESOURCE_STRINGIFY_OP)}};
+static_assert(kResourceTypeNames[NumResourceTypes - 1] != nullptr,
+ "All members must be initialized.");
+
+} // anonymous namespace
+
+// ResourceManager11 Implementation.
+ResourceManager11::ResourceManager11()
+ : mInitializeAllocations(false),
+ mAllocatedResourceCounts({{}}),
+ mAllocatedResourceDeviceMemory({{}})
+{
+}
+
+ResourceManager11::~ResourceManager11()
+{
+ for (size_t count : mAllocatedResourceCounts)
+ {
+ ASSERT(count == 0);
+ }
+
+ for (uint64_t memorySize : mAllocatedResourceDeviceMemory)
+ {
+ ASSERT(memorySize == 0);
+ }
+}
+
+template <typename T>
+gl::Error ResourceManager11::allocate(Renderer11 *renderer,
+ const GetDescFromD3D11<T> *desc,
+ GetInitDataFromD3D11<T> *initData,
+ Resource11<T> *resourceOut)
+{
+ ID3D11Device *device = renderer->getDevice();
+ T *resource = nullptr;
+
+ GetInitDataFromD3D11<T> *shadowInitData = initData;
+ if (!shadowInitData && mInitializeAllocations)
+ {
+ shadowInitData = createInitDataIfNeeded<T>(desc);
+ }
+
+ HRESULT hr = CreateResource(device, desc, shadowInitData, &resource);
+ if (FAILED(hr))
+ {
+ ASSERT(!resource);
+ if (d3d11::isDeviceLostError(hr))
+ {
+ renderer->notifyDeviceLost();
+ }
+ return gl::OutOfMemory() << "Error allocating "
+ << std::string(kResourceTypeNames[ResourceTypeIndex<T>()]) << ". "
+ << gl::FmtHR(hr);
+ }
+
+ if (!shadowInitData && mInitializeAllocations)
+ {
+ ANGLE_TRY(ClearResource(renderer, desc, resource));
+ }
+
+ ASSERT(resource);
+ incrResource(GetResourceTypeFromD3D11<T>(), ComputeMemoryUsage(desc));
+ *resourceOut = std::move(Resource11<T>(resource, this));
+ return gl::NoError();
+}
+
+void ResourceManager11::incrResource(ResourceType resourceType, uint64_t memorySize)
+{
+ size_t typeIndex = ResourceTypeIndex(resourceType);
+
+ mAllocatedResourceCounts[typeIndex]++;
+ mAllocatedResourceDeviceMemory[typeIndex] += memorySize;
+
+ // This checks for integer overflow.
+ ASSERT(mAllocatedResourceCounts[typeIndex] > 0);
+ ASSERT(mAllocatedResourceDeviceMemory[typeIndex] >= memorySize);
+}
+
+void ResourceManager11::decrResource(ResourceType resourceType, uint64_t memorySize)
+{
+ size_t typeIndex = ResourceTypeIndex(resourceType);
+
+ ASSERT(mAllocatedResourceCounts[typeIndex] > 0);
+ mAllocatedResourceCounts[typeIndex]--;
+ ASSERT(mAllocatedResourceDeviceMemory[typeIndex] >= memorySize);
+ mAllocatedResourceDeviceMemory[typeIndex] -= memorySize;
+}
+
+void ResourceManager11::onReleaseGeneric(ResourceType resourceType, ID3D11DeviceChild *resource)
+{
+ ASSERT(resource);
+ decrResource(resourceType, ComputeGenericMemoryUsage(resourceType, resource));
+}
+
+template <>
+const D3D11_SUBRESOURCE_DATA *ResourceManager11::createInitDataIfNeeded<ID3D11Texture2D>(
+ const D3D11_TEXTURE2D_DESC *desc)
+{
+ ASSERT(desc);
+
+ if ((desc->BindFlags & (D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_RENDER_TARGET)) != 0)
+ {
+ // This will be done using ClearView methods.
+ return nullptr;
+ }
+
+ size_t requiredSize = static_cast<size_t>(ComputeMemoryUsage(desc));
+ if (mZeroMemory.size() < requiredSize)
+ {
+ mZeroMemory.resize(requiredSize);
+ mZeroMemory.fill(kDebugInitTextureDataValue);
+ }
+
+ const auto &formatSizeInfo = d3d11::GetDXGIFormatSizeInfo(desc->Format);
+
+ UINT subresourceCount = desc->MipLevels * desc->ArraySize;
+ if (mShadowInitData.size() < subresourceCount)
+ {
+ mShadowInitData.resize(subresourceCount);
+ }
+
+ for (UINT mipLevel = 0; mipLevel < desc->MipLevels; ++mipLevel)
+ {
+ for (UINT arrayIndex = 0; arrayIndex < desc->ArraySize; ++arrayIndex)
+ {
+ UINT subresourceIndex = D3D11CalcSubresource(mipLevel, arrayIndex, desc->MipLevels);
+ D3D11_SUBRESOURCE_DATA *data = &mShadowInitData[subresourceIndex];
+
+ UINT levelWidth = std::max(desc->Width >> mipLevel, 1u);
+ UINT levelHeight = std::max(desc->Height >> mipLevel, 1u);
+
+ data->SysMemPitch = levelWidth * formatSizeInfo.pixelBytes;
+ data->SysMemSlicePitch = data->SysMemPitch * levelHeight;
+ data->pSysMem = mZeroMemory.data();
+ }
+ }
+
+ return mShadowInitData.data();
+}
+
+template <>
+const D3D11_SUBRESOURCE_DATA *ResourceManager11::createInitDataIfNeeded<ID3D11Texture3D>(
+ const D3D11_TEXTURE3D_DESC *desc)
+{
+ ASSERT(desc);
+
+ if ((desc->BindFlags & D3D11_BIND_RENDER_TARGET) != 0)
+ {
+ // This will be done using ClearView methods.
+ return nullptr;
+ }
+
+ size_t requiredSize = static_cast<size_t>(ComputeMemoryUsage(desc));
+ if (mZeroMemory.size() < requiredSize)
+ {
+ mZeroMemory.resize(requiredSize);
+ mZeroMemory.fill(kDebugInitTextureDataValue);
+ }
+
+ const auto &formatSizeInfo = d3d11::GetDXGIFormatSizeInfo(desc->Format);
+
+ UINT subresourceCount = desc->MipLevels;
+ if (mShadowInitData.size() < subresourceCount)
+ {
+ mShadowInitData.resize(subresourceCount);
+ }
+
+ for (UINT mipLevel = 0; mipLevel < desc->MipLevels; ++mipLevel)
+ {
+ UINT subresourceIndex = D3D11CalcSubresource(mipLevel, 0, desc->MipLevels);
+ D3D11_SUBRESOURCE_DATA *data = &mShadowInitData[subresourceIndex];
+
+ UINT levelWidth = std::max(desc->Width >> mipLevel, 1u);
+ UINT levelHeight = std::max(desc->Height >> mipLevel, 1u);
+
+ data->SysMemPitch = levelWidth * formatSizeInfo.pixelBytes;
+ data->SysMemSlicePitch = data->SysMemPitch * levelHeight;
+ data->pSysMem = mZeroMemory.data();
+ }
+
+ return mShadowInitData.data();
+}
+
+template <typename T>
+GetInitDataFromD3D11<T> *ResourceManager11::createInitDataIfNeeded(const GetDescFromD3D11<T> *desc)
+{
+ // No-op.
+ return nullptr;
+}
+
+void ResourceManager11::setAllocationsInitialized(bool initialize)
+{
+ mInitializeAllocations = initialize;
+}
+
+#define ANGLE_INSTANTIATE_OP(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
+ \
+template \
+gl::Error \
+ ResourceManager11::allocate(Renderer11 *, const DESCTYPE *, INITDATATYPE *, \
+ Resource11<D3D11TYPE> *);
+
+ANGLE_RESOURCE_TYPE_OP(Instantitate, ANGLE_INSTANTIATE_OP)
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h
new file mode 100644
index 0000000000..0bdde9f8b6
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h
@@ -0,0 +1,366 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ResourceManager11:
+// Centralized point of allocation for all D3D11 Resources.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_RESOURCEFACTORY11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_RESOURCEFACTORY11_H_
+
+#include <array>
+#include <memory>
+
+#include "common/MemoryBuffer.h"
+#include "common/angleutils.h"
+#include "common/debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/renderer/renderer_utils.h"
+
+namespace rx
+{
+// These two methods are declared here to prevent circular includes.
+namespace d3d11
+{
+HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name);
+
+template <typename T>
+HRESULT SetDebugName(angle::ComPtr<T> &resource, const char *name)
+{
+ return SetDebugName(resource.Get(), name);
+}
+} // namespace d3d11
+
+class Renderer11;
+class ResourceManager11;
+template <typename T>
+class SharedResource11;
+class TextureHelper11;
+
+using InputElementArray = WrappedArray<D3D11_INPUT_ELEMENT_DESC>;
+using ShaderData = WrappedArray<uint8_t>;
+
+// Format: ResourceType, D3D11 type, DESC type, init data type.
+#define ANGLE_RESOURCE_TYPE_OP(NAME, OP) \
+ OP(NAME, BlendState, ID3D11BlendState, D3D11_BLEND_DESC, void) \
+ OP(NAME, Buffer, ID3D11Buffer, D3D11_BUFFER_DESC, const D3D11_SUBRESOURCE_DATA) \
+ OP(NAME, ComputeShader, ID3D11ComputeShader, ShaderData, void) \
+ OP(NAME, DepthStencilState, ID3D11DepthStencilState, D3D11_DEPTH_STENCIL_DESC, void) \
+ OP(NAME, DepthStencilView, ID3D11DepthStencilView, D3D11_DEPTH_STENCIL_VIEW_DESC, \
+ ID3D11Resource) \
+ OP(NAME, GeometryShader, ID3D11GeometryShader, ShaderData, \
+ const std::vector<D3D11_SO_DECLARATION_ENTRY>) \
+ OP(NAME, InputLayout, ID3D11InputLayout, InputElementArray, const ShaderData) \
+ OP(NAME, PixelShader, ID3D11PixelShader, ShaderData, void) \
+ OP(NAME, Query, ID3D11Query, D3D11_QUERY_DESC, void) \
+ OP(NAME, RasterizerState, ID3D11RasterizerState, D3D11_RASTERIZER_DESC, void) \
+ OP(NAME, RenderTargetView, ID3D11RenderTargetView, D3D11_RENDER_TARGET_VIEW_DESC, \
+ ID3D11Resource) \
+ OP(NAME, SamplerState, ID3D11SamplerState, D3D11_SAMPLER_DESC, void) \
+ OP(NAME, ShaderResourceView, ID3D11ShaderResourceView, D3D11_SHADER_RESOURCE_VIEW_DESC, \
+ ID3D11Resource) \
+ OP(NAME, Texture2D, ID3D11Texture2D, D3D11_TEXTURE2D_DESC, const D3D11_SUBRESOURCE_DATA) \
+ OP(NAME, Texture3D, ID3D11Texture3D, D3D11_TEXTURE3D_DESC, const D3D11_SUBRESOURCE_DATA) \
+ OP(NAME, VertexShader, ID3D11VertexShader, ShaderData, void)
+
+#define ANGLE_RESOURCE_TYPE_LIST(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) RESTYPE,
+
+enum class ResourceType
+{
+ ANGLE_RESOURCE_TYPE_OP(List, ANGLE_RESOURCE_TYPE_LIST) Last
+};
+
+#undef ANGLE_RESOURCE_TYPE_LIST
+
+constexpr size_t ResourceTypeIndex(ResourceType resourceType)
+{
+ return static_cast<size_t>(resourceType);
+}
+
+constexpr size_t NumResourceTypes = ResourceTypeIndex(ResourceType::Last);
+
+#define ANGLE_RESOURCE_TYPE_TO_D3D11(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
+ \
+template<> struct NAME<ResourceType::RESTYPE> \
+ { \
+ using Value = D3D11TYPE; \
+ };
+
+#define ANGLE_RESOURCE_TYPE_TO_DESC(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
+ \
+template<> struct NAME<ResourceType::RESTYPE> \
+ { \
+ using Value = DESCTYPE; \
+ };
+
+#define ANGLE_RESOURCE_TYPE_TO_INIT_DATA(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
+ \
+template<> struct NAME<ResourceType::RESTYPE> \
+ { \
+ using Value = INITDATATYPE; \
+ };
+
+#define ANGLE_RESOURCE_TYPE_TO_TYPE(NAME, OP) \
+ template <ResourceType Param> \
+ struct NAME; \
+ ANGLE_RESOURCE_TYPE_OP(NAME, OP) \
+ \
+template<ResourceType Param> struct NAME \
+ { \
+ }; \
+ \
+template<ResourceType Param> using Get##NAME = typename NAME<Param>::Value;
+
+ANGLE_RESOURCE_TYPE_TO_TYPE(D3D11Type, ANGLE_RESOURCE_TYPE_TO_D3D11)
+ANGLE_RESOURCE_TYPE_TO_TYPE(DescType, ANGLE_RESOURCE_TYPE_TO_DESC)
+ANGLE_RESOURCE_TYPE_TO_TYPE(InitDataType, ANGLE_RESOURCE_TYPE_TO_INIT_DATA)
+
+#undef ANGLE_RESOURCE_TYPE_TO_D3D11
+#undef ANGLE_RESOURCE_TYPE_TO_DESC
+#undef ANGLE_RESOURCE_TYPE_TO_INIT_DATA
+#undef ANGLE_RESOURCE_TYPE_TO_TYPE
+
+#define ANGLE_TYPE_TO_RESOURCE_TYPE(NAME, OP) \
+ template <typename Param> \
+ struct NAME; \
+ ANGLE_RESOURCE_TYPE_OP(NAME, OP) \
+ \
+template<typename Param> struct NAME \
+ { \
+ }; \
+ \
+template<typename Param> constexpr ResourceType Get##NAME() \
+ { \
+ return NAME<Param>::Value; \
+ }
+
+#define ANGLE_D3D11_TO_RESOURCE_TYPE(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
+ \
+template<> struct NAME<D3D11TYPE> \
+ { \
+ static constexpr ResourceType Value = ResourceType::RESTYPE; \
+ };
+
+ANGLE_TYPE_TO_RESOURCE_TYPE(ResourceTypeFromD3D11, ANGLE_D3D11_TO_RESOURCE_TYPE)
+
+#undef ANGLE_D3D11_TO_RESOURCE_TYPE
+#undef ANGLE_TYPE_TO_RESOURCE_TYPE
+
+template <typename T>
+using GetDescFromD3D11 = GetDescType<ResourceTypeFromD3D11<T>::Value>;
+
+template <typename T>
+using GetInitDataFromD3D11 = GetInitDataType<ResourceTypeFromD3D11<T>::Value>;
+
+template <typename T>
+constexpr size_t ResourceTypeIndex()
+{
+ return static_cast<size_t>(GetResourceTypeFromD3D11<T>());
+}
+
+template <typename T>
+struct TypedData
+{
+ TypedData() {}
+ ~TypedData();
+
+ T *object = nullptr;
+ ResourceManager11 *manager = nullptr;
+};
+
+// Smart pointer type. Wraps the resource and a factory for safe deletion.
+template <typename T, template <class> class Pointer, typename DataT>
+class Resource11Base : angle::NonCopyable
+{
+ public:
+ T *get() const { return mData->object; }
+ T *const *getPointer() const { return &mData->object; }
+
+ void setDebugName(const char *name) { d3d11::SetDebugName(mData->object, name); }
+
+ void set(T *object)
+ {
+ ASSERT(!valid());
+ mData->object = object;
+ }
+
+ bool valid() const { return (mData->object != nullptr); }
+
+ void reset()
+ {
+ if (valid())
+ mData.reset(new DataT());
+ }
+
+ ResourceSerial getSerial() const
+ {
+ return ResourceSerial(reinterpret_cast<uintptr_t>(mData->object));
+ }
+
+ protected:
+ friend class TextureHelper11;
+
+ Resource11Base() : mData(new DataT()) {}
+
+ Resource11Base(Resource11Base &&movedObj) : mData(new DataT())
+ {
+ std::swap(mData, movedObj.mData);
+ }
+
+ virtual ~Resource11Base() { mData.reset(); }
+
+ Resource11Base &operator=(Resource11Base &&movedObj)
+ {
+ std::swap(mData, movedObj.mData);
+ return *this;
+ }
+
+ Pointer<DataT> mData;
+};
+
+template <typename T>
+using UniquePtr = typename std::unique_ptr<T, std::default_delete<T>>;
+
+template <typename ResourceT>
+class Resource11 : public Resource11Base<ResourceT, UniquePtr, TypedData<ResourceT>>
+{
+ public:
+ Resource11() {}
+ Resource11(Resource11 &&other)
+ : Resource11Base<ResourceT, UniquePtr, TypedData<ResourceT>>(std::move(other))
+ {
+ }
+ Resource11 &operator=(Resource11 &&other)
+ {
+ std::swap(this->mData, other.mData);
+ return *this;
+ }
+
+ private:
+ template <typename T>
+ friend class SharedResource11;
+ friend class ResourceManager11;
+
+ Resource11(ResourceT *object, ResourceManager11 *manager)
+ {
+ this->mData->object = object;
+ this->mData->manager = manager;
+ }
+};
+
+template <typename T>
+class SharedResource11 : public Resource11Base<T, std::shared_ptr, TypedData<T>>
+{
+ public:
+ SharedResource11() {}
+ SharedResource11(SharedResource11 &&movedObj)
+ : Resource11Base<T, std::shared_ptr, TypedData<T>>(std::move(movedObj))
+ {
+ }
+
+ SharedResource11 &operator=(SharedResource11 &&other)
+ {
+ std::swap(this->mData, other.mData);
+ return *this;
+ }
+
+ SharedResource11 makeCopy() const
+ {
+ SharedResource11 copy;
+ copy.mData = this->mData;
+ return std::move(copy);
+ }
+
+ private:
+ friend class ResourceManager11;
+ SharedResource11(Resource11<T> &&obj) : Resource11Base<T, std::shared_ptr, TypedData<T>>()
+ {
+ std::swap(this->mData->manager, obj.mData->manager);
+
+ // Can't use std::swap because of ID3D11Resource.
+ auto temp = this->mData->object;
+ this->mData->object = obj.mData->object;
+ obj.mData->object = static_cast<T *>(temp);
+ }
+};
+
+class ResourceManager11 final : angle::NonCopyable
+{
+ public:
+ ResourceManager11();
+ ~ResourceManager11();
+
+ template <typename T>
+ gl::Error allocate(Renderer11 *renderer,
+ const GetDescFromD3D11<T> *desc,
+ GetInitDataFromD3D11<T> *initData,
+ Resource11<T> *resourceOut);
+
+ template <typename T>
+ gl::Error allocate(Renderer11 *renderer,
+ const GetDescFromD3D11<T> *desc,
+ GetInitDataFromD3D11<T> *initData,
+ SharedResource11<T> *sharedRes)
+ {
+ Resource11<T> res;
+ ANGLE_TRY(allocate(renderer, desc, initData, &res));
+ *sharedRes = std::move(res);
+ return gl::NoError();
+ }
+
+ template <typename T>
+ void onRelease(T *resource)
+ {
+ onReleaseGeneric(GetResourceTypeFromD3D11<T>(), resource);
+ }
+
+ void onReleaseGeneric(ResourceType resourceType, ID3D11DeviceChild *resource);
+
+ void setAllocationsInitialized(bool initialize);
+
+ private:
+ void incrResource(ResourceType resourceType, uint64_t memorySize);
+ void decrResource(ResourceType resourceType, uint64_t memorySize);
+
+ template <typename T>
+ GetInitDataFromD3D11<T> *createInitDataIfNeeded(const GetDescFromD3D11<T> *desc);
+
+ bool mInitializeAllocations;
+
+ std::array<size_t, NumResourceTypes> mAllocatedResourceCounts;
+ std::array<uint64_t, NumResourceTypes> mAllocatedResourceDeviceMemory;
+ angle::MemoryBuffer mZeroMemory;
+
+ std::vector<D3D11_SUBRESOURCE_DATA> mShadowInitData;
+};
+
+template <typename ResourceT>
+TypedData<ResourceT>::~TypedData()
+{
+ if (object)
+ {
+ // We can have a nullptr factory when holding passed-in resources.
+ if (manager)
+ {
+ manager->onRelease(object);
+ }
+ object->Release();
+ }
+}
+
+#define ANGLE_RESOURCE_TYPE_CLASS(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
+ using RESTYPE = Resource11<D3D11TYPE>;
+
+namespace d3d11
+{
+ANGLE_RESOURCE_TYPE_OP(ClassList, ANGLE_RESOURCE_TYPE_CLASS)
+
+using SharedSRV = SharedResource11<ID3D11ShaderResourceView>;
+} // namespace d3d11
+
+#undef ANGLE_RESOURCE_TYPE_CLASS
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_RESOURCEFACTORY11_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp
index 4da51afe49..73a530add0 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp
@@ -13,86 +13,107 @@
namespace rx
{
-ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable)
- : ShaderExecutableD3D(function, length)
+ShaderExecutable11::ShaderExecutable11(const void *function,
+ size_t length,
+ d3d11::PixelShader &&executable)
+ : ShaderExecutableD3D(function, length),
+ mPixelExecutable(std::move(executable)),
+ mVertexExecutable(),
+ mGeometryExecutable(),
+ mStreamOutExecutable(),
+ mComputeExecutable()
{
- mPixelExecutable = executable;
- mVertexExecutable = NULL;
- mGeometryExecutable = NULL;
- mStreamOutExecutable = NULL;
}
-ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut)
- : ShaderExecutableD3D(function, length)
+ShaderExecutable11::ShaderExecutable11(const void *function,
+ size_t length,
+ d3d11::VertexShader &&executable,
+ d3d11::GeometryShader &&streamOut)
+ : ShaderExecutableD3D(function, length),
+ mPixelExecutable(),
+ mVertexExecutable(std::move(executable)),
+ mGeometryExecutable(),
+ mStreamOutExecutable(std::move(streamOut)),
+ mComputeExecutable()
{
- mVertexExecutable = executable;
- mPixelExecutable = NULL;
- mGeometryExecutable = NULL;
- mStreamOutExecutable = streamOut;
}
-ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable)
- : ShaderExecutableD3D(function, length)
+ShaderExecutable11::ShaderExecutable11(const void *function,
+ size_t length,
+ d3d11::GeometryShader &&executable)
+ : ShaderExecutableD3D(function, length),
+ mPixelExecutable(),
+ mVertexExecutable(),
+ mGeometryExecutable(std::move(executable)),
+ mStreamOutExecutable(),
+ mComputeExecutable()
+{
+}
+
+ShaderExecutable11::ShaderExecutable11(const void *function,
+ size_t length,
+ d3d11::ComputeShader &&executable)
+ : ShaderExecutableD3D(function, length),
+ mPixelExecutable(),
+ mVertexExecutable(),
+ mGeometryExecutable(),
+ mStreamOutExecutable(),
+ mComputeExecutable(std::move(executable))
{
- mGeometryExecutable = executable;
- mVertexExecutable = NULL;
- mPixelExecutable = NULL;
- mStreamOutExecutable = NULL;
}
ShaderExecutable11::~ShaderExecutable11()
{
- SafeRelease(mVertexExecutable);
- SafeRelease(mPixelExecutable);
- SafeRelease(mGeometryExecutable);
- SafeRelease(mStreamOutExecutable);
}
-ID3D11VertexShader *ShaderExecutable11::getVertexShader() const
+const d3d11::VertexShader &ShaderExecutable11::getVertexShader() const
{
return mVertexExecutable;
}
-ID3D11PixelShader *ShaderExecutable11::getPixelShader() const
+const d3d11::PixelShader &ShaderExecutable11::getPixelShader() const
{
return mPixelExecutable;
}
-ID3D11GeometryShader *ShaderExecutable11::getGeometryShader() const
+const d3d11::GeometryShader &ShaderExecutable11::getGeometryShader() const
{
return mGeometryExecutable;
}
-ID3D11GeometryShader *ShaderExecutable11::getStreamOutShader() const
+const d3d11::GeometryShader &ShaderExecutable11::getStreamOutShader() const
{
return mStreamOutExecutable;
}
-UniformStorage11::UniformStorage11(Renderer11 *renderer, size_t initialSize)
- : UniformStorageD3D(initialSize),
- mConstantBuffer(NULL)
+const d3d11::ComputeShader &ShaderExecutable11::getComputeShader() const
{
- ID3D11Device *d3d11Device = renderer->getDevice();
+ return mComputeExecutable;
+}
- if (initialSize > 0)
- {
- D3D11_BUFFER_DESC constantBufferDescription = {0};
- constantBufferDescription.ByteWidth = static_cast<unsigned int>(initialSize);
- constantBufferDescription.Usage = D3D11_USAGE_DYNAMIC;
- constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
- constantBufferDescription.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
- constantBufferDescription.MiscFlags = 0;
- constantBufferDescription.StructureByteStride = 0;
-
- HRESULT result = d3d11Device->CreateBuffer(&constantBufferDescription, NULL, &mConstantBuffer);
- UNUSED_ASSERTION_VARIABLE(result);
- ASSERT(SUCCEEDED(result));
- }
+UniformStorage11::UniformStorage11(size_t initialSize)
+ : UniformStorageD3D(initialSize), mConstantBuffer()
+{
}
UniformStorage11::~UniformStorage11()
{
- SafeRelease(mConstantBuffer);
}
+gl::Error UniformStorage11::getConstantBuffer(Renderer11 *renderer, const d3d11::Buffer **bufferOut)
+{
+ if (size() > 0 && !mConstantBuffer.valid())
+ {
+ D3D11_BUFFER_DESC desc = {0};
+ desc.ByteWidth = static_cast<unsigned int>(size());
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+
+ ANGLE_TRY(renderer->allocateResource(desc, &mConstantBuffer));
+ }
+
+ *bufferOut = &mConstantBuffer;
+ return gl::NoError();
}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h
index 379f39fe53..3f417578a3 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h
@@ -11,6 +11,7 @@
#define LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_
#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
namespace rx
{
@@ -20,36 +21,42 @@ class UniformStorage11;
class ShaderExecutable11 : public ShaderExecutableD3D
{
public:
- ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable);
- ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut);
- ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable);
-
- virtual ~ShaderExecutable11();
-
- ID3D11PixelShader *getPixelShader() const;
- ID3D11VertexShader *getVertexShader() const;
- ID3D11GeometryShader *getGeometryShader() const;
- ID3D11GeometryShader *getStreamOutShader() const;
+ ShaderExecutable11(const void *function, size_t length, d3d11::PixelShader &&executable);
+ ShaderExecutable11(const void *function,
+ size_t length,
+ d3d11::VertexShader &&executable,
+ d3d11::GeometryShader &&streamOut);
+ ShaderExecutable11(const void *function, size_t length, d3d11::GeometryShader &&executable);
+ ShaderExecutable11(const void *function, size_t length, d3d11::ComputeShader &&executable);
+
+ ~ShaderExecutable11() override;
+
+ const d3d11::PixelShader &getPixelShader() const;
+ const d3d11::VertexShader &getVertexShader() const;
+ const d3d11::GeometryShader &getGeometryShader() const;
+ const d3d11::GeometryShader &getStreamOutShader() const;
+ const d3d11::ComputeShader &getComputeShader() const;
private:
- ID3D11PixelShader *mPixelExecutable;
- ID3D11VertexShader *mVertexExecutable;
- ID3D11GeometryShader *mGeometryExecutable;
- ID3D11GeometryShader *mStreamOutExecutable;
+ d3d11::PixelShader mPixelExecutable;
+ d3d11::VertexShader mVertexExecutable;
+ d3d11::GeometryShader mGeometryExecutable;
+ d3d11::GeometryShader mStreamOutExecutable;
+ d3d11::ComputeShader mComputeExecutable;
};
class UniformStorage11 : public UniformStorageD3D
{
public:
- UniformStorage11(Renderer11 *renderer, size_t initialSize);
- virtual ~UniformStorage11();
+ UniformStorage11(size_t initialSize);
+ ~UniformStorage11() override;
- ID3D11Buffer *getConstantBuffer() const { return mConstantBuffer; }
+ gl::Error getConstantBuffer(Renderer11 *renderer, const d3d11::Buffer **bufferOut);
private:
- ID3D11Buffer *mConstantBuffer;
+ d3d11::Buffer mConstantBuffer;
};
-}
+} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
index aa34fd4de8..e9902d3f14 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
@@ -8,11 +8,22 @@
#include "libANGLE/renderer/d3d/d3d11/StateManager11.h"
-#include "common/BitSetIterator.h"
+#include "common/bitset_utils.h"
#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Query.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
-#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
+#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
+#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
+#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
namespace rx
{
@@ -22,15 +33,16 @@ namespace
bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOURCE_VIEW_DESC desc)
{
unsigned mipLevel = index.mipIndex;
- unsigned layerIndex = index.layerIndex;
+ GLint layerIndex = index.layerIndex;
GLenum type = index.type;
switch (desc.ViewDimension)
{
case D3D11_SRV_DIMENSION_TEXTURE2D:
{
- unsigned maxSrvMip = desc.Texture2D.MipLevels + desc.Texture2D.MostDetailedMip;
- maxSrvMip = (desc.Texture2D.MipLevels == -1) ? INT_MAX : maxSrvMip;
+ bool allLevels = (desc.Texture2D.MipLevels == std::numeric_limits<UINT>::max());
+ unsigned int maxSrvMip = desc.Texture2D.MipLevels + desc.Texture2D.MostDetailedMip;
+ maxSrvMip = allLevels ? INT_MAX : maxSrvMip;
unsigned mipMin = index.mipIndex;
unsigned mipMax = (layerIndex == -1) ? INT_MAX : layerIndex;
@@ -42,22 +54,25 @@ bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOUR
case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
{
- unsigned maxSrvMip =
+ bool allLevels = (desc.Texture2DArray.MipLevels == std::numeric_limits<UINT>::max());
+ unsigned int maxSrvMip =
desc.Texture2DArray.MipLevels + desc.Texture2DArray.MostDetailedMip;
- maxSrvMip = (desc.Texture2DArray.MipLevels == -1) ? INT_MAX : maxSrvMip;
+ maxSrvMip = allLevels ? INT_MAX : maxSrvMip;
unsigned maxSlice = desc.Texture2DArray.FirstArraySlice + desc.Texture2DArray.ArraySize;
// Cube maps can be mapped to Texture2DArray SRVs
return (type == GL_TEXTURE_2D_ARRAY || gl::IsCubeMapTextureTarget(type)) &&
desc.Texture2DArray.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip &&
- desc.Texture2DArray.FirstArraySlice <= layerIndex && layerIndex < maxSlice;
+ desc.Texture2DArray.FirstArraySlice <= static_cast<UINT>(layerIndex) &&
+ static_cast<UINT>(layerIndex) < maxSlice;
}
case D3D11_SRV_DIMENSION_TEXTURECUBE:
{
- unsigned maxSrvMip = desc.TextureCube.MipLevels + desc.TextureCube.MostDetailedMip;
- maxSrvMip = (desc.TextureCube.MipLevels == -1) ? INT_MAX : maxSrvMip;
+ bool allLevels = (desc.TextureCube.MipLevels == std::numeric_limits<UINT>::max());
+ unsigned int maxSrvMip = desc.TextureCube.MipLevels + desc.TextureCube.MostDetailedMip;
+ maxSrvMip = allLevels ? INT_MAX : maxSrvMip;
return gl::IsCubeMapTextureTarget(type) &&
desc.TextureCube.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip;
@@ -65,8 +80,9 @@ bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOUR
case D3D11_SRV_DIMENSION_TEXTURE3D:
{
- unsigned maxSrvMip = desc.Texture3D.MipLevels + desc.Texture3D.MostDetailedMip;
- maxSrvMip = (desc.Texture3D.MipLevels == -1) ? INT_MAX : maxSrvMip;
+ bool allLevels = (desc.Texture3D.MipLevels == std::numeric_limits<UINT>::max());
+ unsigned int maxSrvMip = desc.Texture3D.MipLevels + desc.Texture3D.MostDetailedMip;
+ maxSrvMip = allLevels ? INT_MAX : maxSrvMip;
return type == GL_TEXTURE_3D && desc.Texture3D.MostDetailedMip <= mipLevel &&
mipLevel < maxSrvMip;
@@ -82,15 +98,97 @@ bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOUR
// Does *not* increment the resource ref count!!
ID3D11Resource *GetViewResource(ID3D11View *view)
{
- ID3D11Resource *resource = NULL;
+ ID3D11Resource *resource = nullptr;
ASSERT(view);
view->GetResource(&resource);
resource->Release();
return resource;
}
+int GetWrapBits(GLenum wrap)
+{
+ switch (wrap)
+ {
+ case GL_CLAMP_TO_EDGE:
+ return 0x1;
+ case GL_REPEAT:
+ return 0x2;
+ case GL_MIRRORED_REPEAT:
+ return 0x3;
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+Optional<size_t> FindFirstNonInstanced(
+ const std::vector<const TranslatedAttribute *> &currentAttributes)
+{
+ for (size_t index = 0; index < currentAttributes.size(); ++index)
+ {
+ if (currentAttributes[index]->divisor == 0)
+ {
+ return Optional<size_t>(index);
+ }
+ }
+
+ return Optional<size_t>::Invalid();
+}
+
+void SortAttributesByLayout(const gl::Program *program,
+ const std::vector<TranslatedAttribute> &vertexArrayAttribs,
+ const std::vector<TranslatedAttribute> &currentValueAttribs,
+ AttribIndexArray *sortedD3DSemanticsOut,
+ std::vector<const TranslatedAttribute *> *sortedAttributesOut)
+{
+ sortedAttributesOut->clear();
+
+ const auto &locationToSemantic =
+ GetImplAs<ProgramD3D>(program)->getAttribLocationToD3DSemantics();
+
+ for (auto locationIndex : program->getActiveAttribLocationsMask())
+ {
+ int d3dSemantic = locationToSemantic[locationIndex];
+ if (sortedAttributesOut->size() <= static_cast<size_t>(d3dSemantic))
+ {
+ sortedAttributesOut->resize(d3dSemantic + 1);
+ }
+
+ (*sortedD3DSemanticsOut)[d3dSemantic] = d3dSemantic;
+
+ const auto *arrayAttrib = &vertexArrayAttribs[locationIndex];
+ if (arrayAttrib->attribute && arrayAttrib->attribute->enabled)
+ {
+ (*sortedAttributesOut)[d3dSemantic] = arrayAttrib;
+ }
+ else
+ {
+ ASSERT(currentValueAttribs[locationIndex].attribute);
+ (*sortedAttributesOut)[d3dSemantic] = &currentValueAttribs[locationIndex];
+ }
+ }
+}
+
+void UpdateUniformBuffer(ID3D11DeviceContext *deviceContext,
+ UniformStorage11 *storage,
+ const d3d11::Buffer *buffer)
+{
+ deviceContext->UpdateSubresource(buffer->get(), 0, nullptr, storage->getDataPointer(0, 0), 0,
+ 0);
+}
+
} // anonymous namespace
+// StateManager11::SRVCache Implementation.
+
+StateManager11::SRVCache::SRVCache() : mHighestUsedSRV(0)
+{
+}
+
+StateManager11::SRVCache::~SRVCache()
+{
+}
+
void StateManager11::SRVCache::update(size_t resourceIndex, ID3D11ShaderResourceView *srv)
{
ASSERT(resourceIndex < mCurrentSRVs.size());
@@ -128,27 +226,348 @@ void StateManager11::SRVCache::clear()
mHighestUsedSRV = 0;
}
+// ShaderConstants11 implementation
+
+ShaderConstants11::ShaderConstants11()
+ : mVertexDirty(true),
+ mPixelDirty(true),
+ mComputeDirty(true),
+ mSamplerMetadataVSDirty(true),
+ mSamplerMetadataPSDirty(true),
+ mSamplerMetadataCSDirty(true)
+{
+}
+
+ShaderConstants11::~ShaderConstants11()
+{
+}
+
+void ShaderConstants11::init(const gl::Caps &caps)
+{
+ mSamplerMetadataVS.resize(caps.maxVertexTextureImageUnits);
+ mSamplerMetadataPS.resize(caps.maxTextureImageUnits);
+ mSamplerMetadataCS.resize(caps.maxComputeTextureImageUnits);
+}
+
+size_t ShaderConstants11::getRequiredBufferSize(gl::SamplerType samplerType) const
+{
+ switch (samplerType)
+ {
+ case gl::SAMPLER_VERTEX:
+ return sizeof(Vertex) + mSamplerMetadataVS.size() * sizeof(SamplerMetadata);
+ case gl::SAMPLER_PIXEL:
+ return sizeof(Pixel) + mSamplerMetadataPS.size() * sizeof(SamplerMetadata);
+ case gl::SAMPLER_COMPUTE:
+ return sizeof(Compute) + mSamplerMetadataCS.size() * sizeof(SamplerMetadata);
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+void ShaderConstants11::markDirty()
+{
+ mVertexDirty = true;
+ mPixelDirty = true;
+ mComputeDirty = true;
+ mSamplerMetadataVSDirty = true;
+ mSamplerMetadataPSDirty = true;
+ mSamplerMetadataCSDirty = true;
+}
+
+bool ShaderConstants11::updateSamplerMetadata(SamplerMetadata *data, const gl::Texture &texture)
+{
+ bool dirty = false;
+ unsigned int baseLevel = texture.getTextureState().getEffectiveBaseLevel();
+ GLenum sizedFormat =
+ texture.getFormat(texture.getTarget(), baseLevel).info->sizedInternalFormat;
+ if (data->baseLevel != static_cast<int>(baseLevel))
+ {
+ data->baseLevel = static_cast<int>(baseLevel);
+ dirty = true;
+ }
+
+ // Some metadata is needed only for integer textures. We avoid updating the constant buffer
+ // unnecessarily by changing the data only in case the texture is an integer texture and
+ // the values have changed.
+ bool needIntegerTextureMetadata = false;
+ // internalFormatBits == 0 means a 32-bit texture in the case of integer textures.
+ int internalFormatBits = 0;
+ switch (sizedFormat)
+ {
+ case GL_RGBA32I:
+ case GL_RGBA32UI:
+ case GL_RGB32I:
+ case GL_RGB32UI:
+ case GL_RG32I:
+ case GL_RG32UI:
+ case GL_R32I:
+ case GL_R32UI:
+ needIntegerTextureMetadata = true;
+ break;
+ case GL_RGBA16I:
+ case GL_RGBA16UI:
+ case GL_RGB16I:
+ case GL_RGB16UI:
+ case GL_RG16I:
+ case GL_RG16UI:
+ case GL_R16I:
+ case GL_R16UI:
+ needIntegerTextureMetadata = true;
+ internalFormatBits = 16;
+ break;
+ case GL_RGBA8I:
+ case GL_RGBA8UI:
+ case GL_RGB8I:
+ case GL_RGB8UI:
+ case GL_RG8I:
+ case GL_RG8UI:
+ case GL_R8I:
+ case GL_R8UI:
+ needIntegerTextureMetadata = true;
+ internalFormatBits = 8;
+ break;
+ case GL_RGB10_A2UI:
+ needIntegerTextureMetadata = true;
+ internalFormatBits = 10;
+ break;
+ default:
+ break;
+ }
+ if (needIntegerTextureMetadata)
+ {
+ if (data->internalFormatBits != internalFormatBits)
+ {
+ data->internalFormatBits = internalFormatBits;
+ dirty = true;
+ }
+ // Pack the wrap values into one integer so we can fit all the metadata in one 4-integer
+ // vector.
+ GLenum wrapS = texture.getWrapS();
+ GLenum wrapT = texture.getWrapT();
+ GLenum wrapR = texture.getWrapR();
+ int wrapModes = GetWrapBits(wrapS) | (GetWrapBits(wrapT) << 2) | (GetWrapBits(wrapR) << 4);
+ if (data->wrapModes != wrapModes)
+ {
+ data->wrapModes = wrapModes;
+ dirty = true;
+ }
+ }
+
+ return dirty;
+}
+
+void ShaderConstants11::setComputeWorkGroups(GLuint numGroupsX,
+ GLuint numGroupsY,
+ GLuint numGroupsZ)
+{
+ mCompute.numWorkGroups[0] = numGroupsX;
+ mCompute.numWorkGroups[1] = numGroupsY;
+ mCompute.numWorkGroups[2] = numGroupsZ;
+ mComputeDirty = true;
+}
+
+void ShaderConstants11::setMultiviewWriteToViewportIndex(GLfloat index)
+{
+ mVertex.multiviewWriteToViewportIndex = index;
+ mVertexDirty = true;
+ mPixel.multiviewWriteToViewportIndex = index;
+ mPixelDirty = true;
+}
+
+void ShaderConstants11::onViewportChange(const gl::Rectangle &glViewport,
+ const D3D11_VIEWPORT &dxViewport,
+ bool is9_3,
+ bool presentPathFast)
+{
+ mVertexDirty = true;
+ mPixelDirty = true;
+
+ // On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders
+ // using viewAdjust (like the D3D9 renderer).
+ if (is9_3)
+ {
+ mVertex.viewAdjust[0] = static_cast<float>((glViewport.width - dxViewport.Width) +
+ 2 * (glViewport.x - dxViewport.TopLeftX)) /
+ dxViewport.Width;
+ mVertex.viewAdjust[1] = static_cast<float>((glViewport.height - dxViewport.Height) +
+ 2 * (glViewport.y - dxViewport.TopLeftY)) /
+ dxViewport.Height;
+ mVertex.viewAdjust[2] = static_cast<float>(glViewport.width) / dxViewport.Width;
+ mVertex.viewAdjust[3] = static_cast<float>(glViewport.height) / dxViewport.Height;
+ }
+
+ mPixel.viewCoords[0] = glViewport.width * 0.5f;
+ mPixel.viewCoords[1] = glViewport.height * 0.5f;
+ mPixel.viewCoords[2] = glViewport.x + (glViewport.width * 0.5f);
+ mPixel.viewCoords[3] = glViewport.y + (glViewport.height * 0.5f);
+
+ // Instanced pointsprite emulation requires ViewCoords to be defined in the
+ // the vertex shader.
+ mVertex.viewCoords[0] = mPixel.viewCoords[0];
+ mVertex.viewCoords[1] = mPixel.viewCoords[1];
+ mVertex.viewCoords[2] = mPixel.viewCoords[2];
+ mVertex.viewCoords[3] = mPixel.viewCoords[3];
+
+ const float zNear = dxViewport.MinDepth;
+ const float zFar = dxViewport.MaxDepth;
+
+ mPixel.depthFront[0] = (zFar - zNear) * 0.5f;
+ mPixel.depthFront[1] = (zNear + zFar) * 0.5f;
+
+ mVertex.depthRange[0] = zNear;
+ mVertex.depthRange[1] = zFar;
+ mVertex.depthRange[2] = zFar - zNear;
+
+ mPixel.depthRange[0] = zNear;
+ mPixel.depthRange[1] = zFar;
+ mPixel.depthRange[2] = zFar - zNear;
+
+ mPixel.viewScale[0] = 1.0f;
+ mPixel.viewScale[1] = presentPathFast ? 1.0f : -1.0f;
+ // Updates to the multiviewWriteToViewportIndex member are to be handled whenever the draw
+ // framebuffer's layout is changed.
+
+ mVertex.viewScale[0] = mPixel.viewScale[0];
+ mVertex.viewScale[1] = mPixel.viewScale[1];
+}
+
+void ShaderConstants11::onSamplerChange(gl::SamplerType samplerType,
+ unsigned int samplerIndex,
+ const gl::Texture &texture)
+{
+ switch (samplerType)
+ {
+ case gl::SAMPLER_VERTEX:
+ if (updateSamplerMetadata(&mSamplerMetadataVS[samplerIndex], texture))
+ {
+ mSamplerMetadataVSDirty = true;
+ }
+ break;
+ case gl::SAMPLER_PIXEL:
+ if (updateSamplerMetadata(&mSamplerMetadataPS[samplerIndex], texture))
+ {
+ mSamplerMetadataPSDirty = true;
+ }
+ break;
+ case gl::SAMPLER_COMPUTE:
+ if (updateSamplerMetadata(&mSamplerMetadataCS[samplerIndex], texture))
+ {
+ mSamplerMetadataCSDirty = true;
+ }
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+gl::Error ShaderConstants11::updateBuffer(ID3D11DeviceContext *deviceContext,
+ gl::SamplerType samplerType,
+ const ProgramD3D &programD3D,
+ const d3d11::Buffer &driverConstantBuffer)
+{
+ bool dirty = false;
+ size_t dataSize = 0;
+ const uint8_t *data = nullptr;
+ const uint8_t *samplerData = nullptr;
+
+ switch (samplerType)
+ {
+ case gl::SAMPLER_VERTEX:
+ dirty = mVertexDirty || mSamplerMetadataVSDirty;
+ dataSize = sizeof(Vertex);
+ data = reinterpret_cast<const uint8_t *>(&mVertex);
+ samplerData = reinterpret_cast<const uint8_t *>(mSamplerMetadataVS.data());
+ mVertexDirty = false;
+ mSamplerMetadataVSDirty = false;
+ break;
+ case gl::SAMPLER_PIXEL:
+ dirty = mPixelDirty || mSamplerMetadataPSDirty;
+ dataSize = sizeof(Pixel);
+ data = reinterpret_cast<const uint8_t *>(&mPixel);
+ samplerData = reinterpret_cast<const uint8_t *>(mSamplerMetadataPS.data());
+ mPixelDirty = false;
+ mSamplerMetadataPSDirty = false;
+ break;
+ case gl::SAMPLER_COMPUTE:
+ dirty = mComputeDirty || mSamplerMetadataCSDirty;
+ dataSize = sizeof(Compute);
+ data = reinterpret_cast<const uint8_t *>(&mCompute);
+ samplerData = reinterpret_cast<const uint8_t *>(mSamplerMetadataCS.data());
+ mComputeDirty = false;
+ mSamplerMetadataCSDirty = false;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ ASSERT(driverConstantBuffer.valid());
+
+ if (!dirty)
+ {
+ return gl::NoError();
+ }
+
+ // Previous buffer contents are discarded, so we need to refresh the whole buffer.
+ D3D11_MAPPED_SUBRESOURCE mapping = {0};
+ HRESULT result =
+ deviceContext->Map(driverConstantBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapping);
+
+ if (FAILED(result))
+ {
+ return gl::OutOfMemory() << "Internal error mapping constant buffer: " << gl::FmtHR(result);
+ }
+
+ size_t samplerDataBytes = sizeof(SamplerMetadata) * programD3D.getUsedSamplerRange(samplerType);
+
+ memcpy(mapping.pData, data, dataSize);
+ memcpy(reinterpret_cast<uint8_t *>(mapping.pData) + dataSize, samplerData, samplerDataBytes);
+
+ deviceContext->Unmap(driverConstantBuffer.get(), 0);
+
+ return gl::NoError();
+}
+
+static const GLenum QueryTypes[] = {GL_ANY_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED_CONSERVATIVE,
+ GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_TIME_ELAPSED_EXT,
+ GL_COMMANDS_COMPLETED_CHROMIUM};
+
StateManager11::StateManager11(Renderer11 *renderer)
: mRenderer(renderer),
- mBlendStateIsDirty(false),
+ mInternalDirtyBits(),
mCurBlendColor(0, 0, 0, 0),
mCurSampleMask(0),
- mDepthStencilStateIsDirty(false),
mCurStencilRef(0),
mCurStencilBackRef(0),
mCurStencilSize(0),
- mRasterizerStateIsDirty(false),
- mScissorStateIsDirty(false),
mCurScissorEnabled(false),
mCurScissorRect(),
- mViewportStateIsDirty(false),
mCurViewport(),
mCurNear(0.0f),
mCurFar(0.0f),
mViewportBounds(),
+ mRenderTargetIsDirty(true),
mCurPresentPathFastEnabled(false),
mCurPresentPathFastColorBufferHeight(0),
- mAppliedDSV(angle::DirtyPointer)
+ mDirtyCurrentValueAttribs(),
+ mCurrentValueAttribs(),
+ mCurrentInputLayout(),
+ mInputLayoutIsDirty(false),
+ mVertexAttribsNeedTranslation(false),
+ mDirtyVertexBufferRange(gl::MAX_VERTEX_ATTRIBS, 0),
+ mCurrentPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_UNDEFINED),
+ mDirtySwizzles(false),
+ mAppliedIB(nullptr),
+ mAppliedIBFormat(DXGI_FORMAT_UNKNOWN),
+ mAppliedIBOffset(0),
+ mIndexBufferIsDirty(false),
+ mVertexDataManager(renderer),
+ mIndexDataManager(renderer),
+ mIsMultiviewEnabled(false),
+ mEmptySerial(mRenderer->generateSerial()),
+ mIsTransformFeedbackCurrentlyActiveUnpaused(false)
{
mCurBlendState.blend = false;
mCurBlendState.sourceBlendRGB = GL_ONE;
@@ -182,64 +601,127 @@ StateManager11::StateManager11(Renderer11 *renderer)
mCurRasterState.rasterizerDiscard = false;
mCurRasterState.cullFace = false;
- mCurRasterState.cullMode = GL_BACK;
+ mCurRasterState.cullMode = gl::CullFaceMode::Back;
mCurRasterState.frontFace = GL_CCW;
mCurRasterState.polygonOffsetFill = false;
mCurRasterState.polygonOffsetFactor = 0.0f;
mCurRasterState.polygonOffsetUnits = 0.0f;
mCurRasterState.pointDrawMode = false;
mCurRasterState.multiSample = false;
+
+ // Start with all internal dirty bits set.
+ mInternalDirtyBits.set();
+
+ // Initially all current value attributes must be updated on first use.
+ mDirtyCurrentValueAttribs.set();
+
+ mCurrentVertexBuffers.fill(nullptr);
+ mCurrentVertexStrides.fill(std::numeric_limits<UINT>::max());
+ mCurrentVertexOffsets.fill(std::numeric_limits<UINT>::max());
}
StateManager11::~StateManager11()
{
}
-void StateManager11::updateStencilSizeIfChanged(bool depthStencilInitialized,
- unsigned int stencilSize)
+template <typename SRVType>
+void StateManager11::setShaderResourceInternal(gl::SamplerType shaderType,
+ UINT resourceSlot,
+ const SRVType *srv)
{
- if (!depthStencilInitialized || stencilSize != mCurStencilSize)
+ auto &currentSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
+
+ ASSERT(static_cast<size_t>(resourceSlot) < currentSRVs.size());
+ const SRVRecord &record = currentSRVs[resourceSlot];
+
+ if (record.srv != reinterpret_cast<uintptr_t>(srv))
{
- mCurStencilSize = stencilSize;
- mDepthStencilStateIsDirty = true;
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ ID3D11ShaderResourceView *srvPtr = srv ? srv->get() : nullptr;
+ if (shaderType == gl::SAMPLER_VERTEX)
+ {
+ deviceContext->VSSetShaderResources(resourceSlot, 1, &srvPtr);
+ }
+ else
+ {
+ deviceContext->PSSetShaderResources(resourceSlot, 1, &srvPtr);
+ }
+
+ currentSRVs.update(resourceSlot, srvPtr);
}
}
-void StateManager11::setViewportBounds(const int width, const int height)
+void StateManager11::updateStencilSizeIfChanged(bool depthStencilInitialized,
+ unsigned int stencilSize)
{
- if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3 &&
- (mViewportBounds.width != width || mViewportBounds.height != height))
+ if (!depthStencilInitialized || stencilSize != mCurStencilSize)
{
- mViewportBounds = gl::Extents(width, height, 1);
- mViewportStateIsDirty = true;
+ mCurStencilSize = stencilSize;
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
}
}
-void StateManager11::updatePresentPath(bool presentPathFastActive,
- const gl::FramebufferAttachment *framebufferAttachment)
+void StateManager11::checkPresentPath(const gl::Context *context)
{
- const int colorBufferHeight =
- framebufferAttachment ? framebufferAttachment->getSize().height : 0;
+ if (!mRenderer->presentPathFastEnabled())
+ return;
+
+ const auto *framebuffer = context->getGLState().getDrawFramebuffer();
+ const auto *firstColorAttachment = framebuffer->getFirstColorbuffer();
+ const bool presentPathFastActive = UsePresentPathFast(mRenderer, firstColorAttachment);
+
+ const int colorBufferHeight = firstColorAttachment ? firstColorAttachment->getSize().height : 0;
if ((mCurPresentPathFastEnabled != presentPathFastActive) ||
(presentPathFastActive && (colorBufferHeight != mCurPresentPathFastColorBufferHeight)))
{
mCurPresentPathFastEnabled = presentPathFastActive;
mCurPresentPathFastColorBufferHeight = colorBufferHeight;
- mViewportStateIsDirty = true; // Viewport may need to be vertically inverted
- mScissorStateIsDirty = true; // Scissor rect may need to be vertically inverted
- mRasterizerStateIsDirty = true; // Cull Mode may need to be inverted
+
+ // Scissor rect may need to be vertically inverted
+ mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
+
+ // Cull Mode may need to be inverted
+ mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
+
+ // Viewport may need to be vertically inverted
+ invalidateViewport(context);
}
}
-void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits)
+gl::Error StateManager11::updateStateForCompute(const gl::Context *context,
+ GLuint numGroupsX,
+ GLuint numGroupsY,
+ GLuint numGroupsZ)
+{
+ mShaderConstants.setComputeWorkGroups(numGroupsX, numGroupsY, numGroupsZ);
+
+ // TODO(jmadill): Use dirty bits.
+ const auto &glState = context->getGLState();
+ auto *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
+ programD3D->updateSamplerMapping();
+
+ // TODO(jmadill): Use dirty bits.
+ ANGLE_TRY(generateSwizzlesForShader(context, gl::SAMPLER_COMPUTE));
+
+ // TODO(jmadill): More complete implementation.
+ ANGLE_TRY(syncTextures(context));
+
+ // TODO(Xinghua): applyUniformBuffers for compute shader.
+
+ return gl::NoError();
+}
+
+void StateManager11::syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits)
{
if (!dirtyBits.any())
{
return;
}
- for (unsigned int dirtyBit : angle::IterateBitSet(dirtyBits))
+ const auto &state = context->getGLState();
+
+ for (auto dirtyBit : dirtyBits)
{
switch (dirtyBit)
{
@@ -249,7 +731,7 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit
if (blendState.blendEquationRGB != mCurBlendState.blendEquationRGB ||
blendState.blendEquationAlpha != mCurBlendState.blendEquationAlpha)
{
- mBlendStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
}
break;
}
@@ -261,27 +743,27 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit
blendState.sourceBlendAlpha != mCurBlendState.sourceBlendAlpha ||
blendState.destBlendAlpha != mCurBlendState.destBlendAlpha)
{
- mBlendStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
}
break;
}
case gl::State::DIRTY_BIT_BLEND_ENABLED:
if (state.getBlendState().blend != mCurBlendState.blend)
{
- mBlendStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
}
break;
case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
if (state.getBlendState().sampleAlphaToCoverage !=
mCurBlendState.sampleAlphaToCoverage)
{
- mBlendStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
}
break;
case gl::State::DIRTY_BIT_DITHER_ENABLED:
if (state.getBlendState().dither != mCurBlendState.dither)
{
- mBlendStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
}
break;
case gl::State::DIRTY_BIT_COLOR_MASK:
@@ -292,38 +774,38 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit
blendState.colorMaskBlue != mCurBlendState.colorMaskBlue ||
blendState.colorMaskAlpha != mCurBlendState.colorMaskAlpha)
{
- mBlendStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
}
break;
}
case gl::State::DIRTY_BIT_BLEND_COLOR:
if (state.getBlendColor() != mCurBlendColor)
{
- mBlendStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
}
break;
case gl::State::DIRTY_BIT_DEPTH_MASK:
if (state.getDepthStencilState().depthMask != mCurDepthStencilState.depthMask)
{
- mDepthStencilStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
}
break;
case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED:
if (state.getDepthStencilState().depthTest != mCurDepthStencilState.depthTest)
{
- mDepthStencilStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
}
break;
case gl::State::DIRTY_BIT_DEPTH_FUNC:
if (state.getDepthStencilState().depthFunc != mCurDepthStencilState.depthFunc)
{
- mDepthStencilStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
}
break;
case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
if (state.getDepthStencilState().stencilTest != mCurDepthStencilState.stencilTest)
{
- mDepthStencilStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
}
break;
case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
@@ -333,7 +815,7 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit
depthStencil.stencilMask != mCurDepthStencilState.stencilMask ||
state.getStencilRef() != mCurStencilRef)
{
- mDepthStencilStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
}
break;
}
@@ -344,7 +826,7 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit
depthStencil.stencilBackMask != mCurDepthStencilState.stencilBackMask ||
state.getStencilBackRef() != mCurStencilBackRef)
{
- mDepthStencilStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
}
break;
}
@@ -352,14 +834,14 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit
if (state.getDepthStencilState().stencilWritemask !=
mCurDepthStencilState.stencilWritemask)
{
- mDepthStencilStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
}
break;
case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
if (state.getDepthStencilState().stencilBackWritemask !=
mCurDepthStencilState.stencilBackWritemask)
{
- mDepthStencilStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
}
break;
case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT:
@@ -370,7 +852,7 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit
mCurDepthStencilState.stencilPassDepthFail ||
depthStencil.stencilPassDepthPass != mCurDepthStencilState.stencilPassDepthPass)
{
- mDepthStencilStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
}
break;
}
@@ -383,33 +865,33 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit
depthStencil.stencilBackPassDepthPass !=
mCurDepthStencilState.stencilBackPassDepthPass)
{
- mDepthStencilStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
}
break;
}
case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
if (state.getRasterizerState().cullFace != mCurRasterState.cullFace)
{
- mRasterizerStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
}
break;
case gl::State::DIRTY_BIT_CULL_FACE:
if (state.getRasterizerState().cullMode != mCurRasterState.cullMode)
{
- mRasterizerStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
}
break;
case gl::State::DIRTY_BIT_FRONT_FACE:
if (state.getRasterizerState().frontFace != mCurRasterState.frontFace)
{
- mRasterizerStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
}
break;
case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
if (state.getRasterizerState().polygonOffsetFill !=
mCurRasterState.polygonOffsetFill)
{
- mRasterizerStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
}
break;
case gl::State::DIRTY_BIT_POLYGON_OFFSET:
@@ -418,7 +900,7 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit
if (rasterState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor ||
rasterState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits)
{
- mRasterizerStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
}
break;
}
@@ -426,58 +908,150 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit
if (state.getRasterizerState().rasterizerDiscard !=
mCurRasterState.rasterizerDiscard)
{
- mRasterizerStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
+
+ // Enabling/disabling rasterizer discard affects the pixel shader.
+ invalidateShaders();
}
break;
case gl::State::DIRTY_BIT_SCISSOR:
if (state.getScissor() != mCurScissorRect)
{
- mScissorStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
}
break;
case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
if (state.isScissorTestEnabled() != mCurScissorEnabled)
{
- mScissorStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
// Rasterizer state update needs mCurScissorsEnabled and updates when it changes
- mRasterizerStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
}
break;
case gl::State::DIRTY_BIT_DEPTH_RANGE:
if (state.getNearPlane() != mCurNear || state.getFarPlane() != mCurFar)
{
- mViewportStateIsDirty = true;
+ invalidateViewport(context);
}
break;
case gl::State::DIRTY_BIT_VIEWPORT:
if (state.getViewport() != mCurViewport)
{
- mViewportStateIsDirty = true;
+ invalidateViewport(context);
+ }
+ break;
+ case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
+ invalidateRenderTarget();
+ if (mIsMultiviewEnabled)
+ {
+ handleMultiviewDrawFramebufferChange(context);
}
break;
+ case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING:
+ invalidateVertexBuffer();
+ // Force invalidate the current value attributes, since the VertexArray11 keeps an
+ // internal cache of TranslatedAttributes, and they CurrentValue attributes are
+ // owned by the StateManager11/Context.
+ mDirtyCurrentValueAttribs.set();
+ // Invalidate the cached index buffer.
+ mIndexBufferIsDirty = true;
+ break;
+ case gl::State::DIRTY_BIT_TEXTURE_BINDINGS:
+ invalidateTexturesAndSamplers();
+ break;
+ case gl::State::DIRTY_BIT_SAMPLER_BINDINGS:
+ invalidateTexturesAndSamplers();
+ break;
+ case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE:
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_SHADERS);
+ invalidateVertexBuffer();
+ invalidateRenderTarget();
+ invalidateTexturesAndSamplers();
+ invalidateProgramUniforms();
+ invalidateProgramUniformBuffers();
+ gl::VertexArray *vao = state.getVertexArray();
+ if (mIsMultiviewEnabled && vao != nullptr)
+ {
+ // If ANGLE_multiview is enabled, the attribute divisor has to be updated for
+ // each binding.
+ VertexArray11 *vao11 = GetImplAs<VertexArray11>(vao);
+ const gl::Program *program = state.getProgram();
+ int numViews = 1;
+ if (program != nullptr && program->usesMultiview())
+ {
+ numViews = program->getNumViews();
+ }
+ vao11->markAllAttributeDivisorsForAdjustment(numViews);
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_CURRENT_VALUES:
+ {
+ for (auto attribIndex : state.getAndResetDirtyCurrentValues())
+ {
+ invalidateCurrentValueAttrib(attribIndex);
+ }
+ }
default:
break;
}
}
+
+ // TODO(jmadill): Input layout and vertex buffer state.
}
-gl::Error StateManager11::setBlendState(const gl::Framebuffer *framebuffer,
- const gl::BlendState &blendState,
- const gl::ColorF &blendColor,
- unsigned int sampleMask)
+void StateManager11::handleMultiviewDrawFramebufferChange(const gl::Context *context)
{
- if (!mBlendStateIsDirty && sampleMask == mCurSampleMask)
+ const auto &glState = context->getGLState();
+ const gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
+ ASSERT(drawFramebuffer != nullptr);
+
+ // Update viewport offsets.
+ const std::vector<gl::Offset> *attachmentViewportOffsets =
+ drawFramebuffer->getViewportOffsets();
+ const std::vector<gl::Offset> &viewportOffsets =
+ attachmentViewportOffsets != nullptr
+ ? *attachmentViewportOffsets
+ : gl::FramebufferAttachment::GetDefaultViewportOffsetVector();
+ if (mViewportOffsets != viewportOffsets)
{
- return gl::Error(GL_NO_ERROR);
- }
+ mViewportOffsets = viewportOffsets;
- ID3D11BlendState *dxBlendState = nullptr;
- gl::Error error =
- mRenderer->getStateCache().getBlendState(framebuffer, blendState, &dxBlendState);
- if (error.isError())
+ // Because new viewport offsets are to be applied, we have to mark the internal viewport and
+ // scissor state as dirty.
+ invalidateViewport(context);
+ mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
+ }
+ switch (drawFramebuffer->getMultiviewLayout())
{
- return error;
+ case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
+ mShaderConstants.setMultiviewWriteToViewportIndex(1.0f);
+ break;
+ case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
+ // Because the base view index is applied as an offset to the 2D texture array when the
+ // RTV is created, we just have to pass a boolean to select which code path is to be
+ // used.
+ mShaderConstants.setMultiviewWriteToViewportIndex(0.0f);
+ break;
+ default:
+ // There is no need to update the value in the constant buffer if the active framebuffer
+ // object does not have a multiview layout.
+ break;
}
+}
+
+gl::Error StateManager11::syncBlendState(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::BlendState &blendState,
+ const gl::ColorF &blendColor,
+ unsigned int sampleMask)
+{
+ const d3d11::BlendState *dxBlendState = nullptr;
+ const d3d11::BlendStateKey &key =
+ RenderStateCache::GetBlendStateKey(context, framebuffer, blendState);
+
+ ANGLE_TRY(mRenderer->getBlendState(key, &dxBlendState));
ASSERT(dxBlendState != nullptr);
@@ -500,62 +1074,53 @@ gl::Error StateManager11::setBlendState(const gl::Framebuffer *framebuffer,
blendColors[3] = blendColor.alpha;
}
- mRenderer->getDeviceContext()->OMSetBlendState(dxBlendState, blendColors, sampleMask);
+ mRenderer->getDeviceContext()->OMSetBlendState(dxBlendState->get(), blendColors, sampleMask);
mCurBlendState = blendState;
mCurBlendColor = blendColor;
mCurSampleMask = sampleMask;
- mBlendStateIsDirty = false;
-
- return error;
+ return gl::NoError();
}
-gl::Error StateManager11::setDepthStencilState(const gl::State &glState)
+gl::Error StateManager11::syncDepthStencilState(const gl::State &glState)
{
- const auto &fbo = *glState.getDrawFramebuffer();
-
- // Disable the depth test/depth write if we are using a stencil-only attachment.
- // This is because ANGLE emulates stencil-only with D24S8 on D3D11 - we should neither read
- // nor write to the unused depth part of this emulated texture.
- bool disableDepth = (!fbo.hasDepth() && fbo.hasStencil());
-
- // Similarly we disable the stencil portion of the DS attachment if the app only binds depth.
- bool disableStencil = (fbo.hasDepth() && !fbo.hasStencil());
+ mCurDepthStencilState = glState.getDepthStencilState();
+ mCurStencilRef = glState.getStencilRef();
+ mCurStencilBackRef = glState.getStencilBackRef();
- // CurDisableDepth/Stencil are reset automatically after we call forceSetDepthStencilState.
- if (!mDepthStencilStateIsDirty && mCurDisableDepth.valid() &&
- disableDepth == mCurDisableDepth.value() && mCurDisableStencil.valid() &&
- disableStencil == mCurDisableStencil.value())
+ // get the maximum size of the stencil ref
+ unsigned int maxStencil = 0;
+ if (mCurDepthStencilState.stencilTest && mCurStencilSize > 0)
{
- return gl::Error(GL_NO_ERROR);
+ maxStencil = (1 << mCurStencilSize) - 1;
}
+ ASSERT((mCurDepthStencilState.stencilWritemask & maxStencil) ==
+ (mCurDepthStencilState.stencilBackWritemask & maxStencil));
+ ASSERT(mCurStencilRef == mCurStencilBackRef);
+ ASSERT((mCurDepthStencilState.stencilMask & maxStencil) ==
+ (mCurDepthStencilState.stencilBackMask & maxStencil));
- const auto &depthStencilState = glState.getDepthStencilState();
- int stencilRef = glState.getStencilRef();
- int stencilBackRef = glState.getStencilBackRef();
+ gl::DepthStencilState modifiedGLState = glState.getDepthStencilState();
- // get the maximum size of the stencil ref
- unsigned int maxStencil = 0;
- if (depthStencilState.stencilTest && mCurStencilSize > 0)
+ ASSERT(mCurDisableDepth.valid() && mCurDisableStencil.valid());
+
+ if (mCurDisableDepth.value())
{
- maxStencil = (1 << mCurStencilSize) - 1;
+ modifiedGLState.depthTest = false;
+ modifiedGLState.depthMask = false;
}
- ASSERT((depthStencilState.stencilWritemask & maxStencil) ==
- (depthStencilState.stencilBackWritemask & maxStencil));
- ASSERT(stencilRef == stencilBackRef);
- ASSERT((depthStencilState.stencilMask & maxStencil) ==
- (depthStencilState.stencilBackMask & maxStencil));
- ID3D11DepthStencilState *dxDepthStencilState = NULL;
- gl::Error error = mRenderer->getStateCache().getDepthStencilState(
- depthStencilState, disableDepth, disableStencil, &dxDepthStencilState);
- if (error.isError())
+ if (mCurDisableStencil.value())
{
- return error;
+ modifiedGLState.stencilWritemask = 0;
+ modifiedGLState.stencilBackWritemask = 0;
+ modifiedGLState.stencilTest = false;
}
- ASSERT(dxDepthStencilState);
+ const d3d11::DepthStencilState *d3dState = nullptr;
+ ANGLE_TRY(mRenderer->getDepthStencilState(modifiedGLState, &d3dState));
+ ASSERT(d3dState);
// Max D3D11 stencil reference value is 0xFF,
// corresponding to the max 8 bits in a stencil buffer
@@ -565,30 +1130,21 @@ gl::Error StateManager11::setDepthStencilState(const gl::State &glState)
"Unexpected value of D3D11_DEFAULT_STENCIL_READ_MASK");
static_assert(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF,
"Unexpected value of D3D11_DEFAULT_STENCIL_WRITE_MASK");
- UINT dxStencilRef = std::min<UINT>(stencilRef, 0xFFu);
+ UINT dxStencilRef = std::min<UINT>(mCurStencilRef, 0xFFu);
- mRenderer->getDeviceContext()->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef);
+ mRenderer->getDeviceContext()->OMSetDepthStencilState(d3dState->get(), dxStencilRef);
- mCurDepthStencilState = depthStencilState;
- mCurStencilRef = stencilRef;
- mCurStencilBackRef = stencilBackRef;
- mCurDisableDepth = disableDepth;
- mCurDisableStencil = disableStencil;
-
- mDepthStencilStateIsDirty = false;
-
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error StateManager11::setRasterizerState(const gl::RasterizerState &rasterState)
+gl::Error StateManager11::syncRasterizerState(const gl::Context *context, bool pointDrawMode)
{
- if (!mRasterizerStateIsDirty)
- {
- return gl::Error(GL_NO_ERROR);
- }
+ // TODO: Remove pointDrawMode and multiSample from gl::RasterizerState.
+ gl::RasterizerState rasterState = context->getGLState().getRasterizerState();
+ rasterState.pointDrawMode = pointDrawMode;
+ rasterState.multiSample = mCurRasterState.multiSample;
ID3D11RasterizerState *dxRasterState = nullptr;
- gl::Error error(GL_NO_ERROR);
if (mCurPresentPathFastEnabled)
{
@@ -607,33 +1163,23 @@ gl::Error StateManager11::setRasterizerState(const gl::RasterizerState &rasterSt
modifiedRasterState.frontFace = GL_CCW;
}
- error = mRenderer->getStateCache().getRasterizerState(modifiedRasterState,
- mCurScissorEnabled, &dxRasterState);
+ ANGLE_TRY(
+ mRenderer->getRasterizerState(modifiedRasterState, mCurScissorEnabled, &dxRasterState));
}
else
{
- error = mRenderer->getStateCache().getRasterizerState(rasterState, mCurScissorEnabled,
- &dxRasterState);
- }
-
- if (error.isError())
- {
- return error;
+ ANGLE_TRY(mRenderer->getRasterizerState(rasterState, mCurScissorEnabled, &dxRasterState));
}
mRenderer->getDeviceContext()->RSSetState(dxRasterState);
- mCurRasterState = rasterState;
- mRasterizerStateIsDirty = false;
+ mCurRasterState = rasterState;
- return error;
+ return gl::NoError();
}
-void StateManager11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
+void StateManager11::syncScissorRectangle(const gl::Rectangle &scissor, bool enabled)
{
- if (!mScissorStateIsDirty)
- return;
-
int modifiedScissorY = scissor.y;
if (mCurPresentPathFastEnabled)
{
@@ -642,37 +1188,41 @@ void StateManager11::setScissorRectangle(const gl::Rectangle &scissor, bool enab
if (enabled)
{
- D3D11_RECT rect;
- rect.left = std::max(0, scissor.x);
- rect.top = std::max(0, modifiedScissorY);
- rect.right = scissor.x + std::max(0, scissor.width);
- rect.bottom = modifiedScissorY + std::max(0, scissor.height);
-
- mRenderer->getDeviceContext()->RSSetScissorRects(1, &rect);
+ std::array<D3D11_RECT, gl::IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS> rectangles;
+ const UINT numRectangles = static_cast<UINT>(mViewportOffsets.size());
+ for (UINT i = 0u; i < numRectangles; ++i)
+ {
+ D3D11_RECT &rect = rectangles[i];
+ int x = scissor.x + mViewportOffsets[i].x;
+ int y = modifiedScissorY + mViewportOffsets[i].y;
+ rect.left = std::max(0, x);
+ rect.top = std::max(0, y);
+ rect.right = x + std::max(0, scissor.width);
+ rect.bottom = y + std::max(0, scissor.height);
+ }
+ mRenderer->getDeviceContext()->RSSetScissorRects(numRectangles, rectangles.data());
}
mCurScissorRect = scissor;
mCurScissorEnabled = enabled;
- mScissorStateIsDirty = false;
}
-void StateManager11::setViewport(const gl::Caps *caps,
- const gl::Rectangle &viewport,
- float zNear,
- float zFar)
+void StateManager11::syncViewport(const gl::Context *context)
{
- if (!mViewportStateIsDirty)
- return;
-
- float actualZNear = gl::clamp01(zNear);
- float actualZFar = gl::clamp01(zFar);
-
- int dxMaxViewportBoundsX = static_cast<int>(caps->maxViewportWidth);
- int dxMaxViewportBoundsY = static_cast<int>(caps->maxViewportHeight);
+ const auto &glState = context->getGLState();
+ gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
+ float actualZNear = gl::clamp01(glState.getNearPlane());
+ float actualZFar = gl::clamp01(glState.getFarPlane());
+
+ const auto &caps = context->getCaps();
+ int dxMaxViewportBoundsX = static_cast<int>(caps.maxViewportWidth);
+ int dxMaxViewportBoundsY = static_cast<int>(caps.maxViewportHeight);
int dxMinViewportBoundsX = -dxMaxViewportBoundsX;
int dxMinViewportBoundsY = -dxMaxViewportBoundsY;
- if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
+ bool is9_3 = mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3;
+
+ if (is9_3)
{
// Feature Level 9 viewports shouldn't exceed the dimensions of the rendertarget.
dxMaxViewportBoundsX = static_cast<int>(mViewportBounds.width);
@@ -681,173 +1231,295 @@ void StateManager11::setViewport(const gl::Caps *caps,
dxMinViewportBoundsY = 0;
}
- int dxViewportTopLeftX = gl::clamp(viewport.x, dxMinViewportBoundsX, dxMaxViewportBoundsX);
- int dxViewportTopLeftY = gl::clamp(viewport.y, dxMinViewportBoundsY, dxMaxViewportBoundsY);
- int dxViewportWidth = gl::clamp(viewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX);
- int dxViewportHeight = gl::clamp(viewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY);
+ const auto &viewport = glState.getViewport();
+ std::array<D3D11_VIEWPORT, gl::IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS> dxViewports;
+ const UINT numRectangles = static_cast<UINT>(mViewportOffsets.size());
- D3D11_VIEWPORT dxViewport;
- dxViewport.TopLeftX = static_cast<float>(dxViewportTopLeftX);
+ int dxViewportTopLeftX = 0;
+ int dxViewportTopLeftY = 0;
+ int dxViewportWidth = 0;
+ int dxViewportHeight = 0;
- if (mCurPresentPathFastEnabled)
- {
- // When present path fast is active and we're rendering to framebuffer 0, we must invert
- // the viewport in Y-axis.
- // NOTE: We delay the inversion until right before the call to RSSetViewports, and leave
- // dxViewportTopLeftY unchanged. This allows us to calculate viewAdjust below using the
- // unaltered dxViewportTopLeftY value.
- dxViewport.TopLeftY = static_cast<float>(mCurPresentPathFastColorBufferHeight -
- dxViewportTopLeftY - dxViewportHeight);
- }
- else
+ for (UINT i = 0u; i < numRectangles; ++i)
{
- dxViewport.TopLeftY = static_cast<float>(dxViewportTopLeftY);
- }
+ dxViewportTopLeftX = gl::clamp(viewport.x + mViewportOffsets[i].x, dxMinViewportBoundsX,
+ dxMaxViewportBoundsX);
+ dxViewportTopLeftY = gl::clamp(viewport.y + mViewportOffsets[i].y, dxMinViewportBoundsY,
+ dxMaxViewportBoundsY);
+ dxViewportWidth = gl::clamp(viewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX);
+ dxViewportHeight = gl::clamp(viewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY);
+
+ D3D11_VIEWPORT &dxViewport = dxViewports[i];
+ dxViewport.TopLeftX = static_cast<float>(dxViewportTopLeftX);
+ if (mCurPresentPathFastEnabled)
+ {
+ // When present path fast is active and we're rendering to framebuffer 0, we must invert
+ // the viewport in Y-axis.
+ // NOTE: We delay the inversion until right before the call to RSSetViewports, and leave
+ // dxViewportTopLeftY unchanged. This allows us to calculate viewAdjust below using the
+ // unaltered dxViewportTopLeftY value.
+ dxViewport.TopLeftY = static_cast<float>(mCurPresentPathFastColorBufferHeight -
+ dxViewportTopLeftY - dxViewportHeight);
+ }
+ else
+ {
+ dxViewport.TopLeftY = static_cast<float>(dxViewportTopLeftY);
+ }
- dxViewport.Width = static_cast<float>(dxViewportWidth);
- dxViewport.Height = static_cast<float>(dxViewportHeight);
- dxViewport.MinDepth = actualZNear;
- dxViewport.MaxDepth = actualZFar;
+ // The es 3.1 spec section 9.2 states that, "If there are no attachments, rendering
+ // will be limited to a rectangle having a lower left of (0, 0) and an upper right of
+ // (width, height), where width and height are the framebuffer object's default width
+ // and height." See http://anglebug.com/1594
+ // If the Framebuffer has no color attachment and the default width or height is smaller
+ // than the current viewport, use the smaller of the two sizes.
+ // If framebuffer default width or height is 0, the params should not set.
+ if (!framebuffer->getFirstNonNullAttachment() &&
+ (framebuffer->getDefaultWidth() || framebuffer->getDefaultHeight()))
+ {
+ dxViewport.Width =
+ static_cast<GLfloat>(std::min(viewport.width, framebuffer->getDefaultWidth()));
+ dxViewport.Height =
+ static_cast<GLfloat>(std::min(viewport.height, framebuffer->getDefaultHeight()));
+ }
+ else
+ {
+ dxViewport.Width = static_cast<float>(dxViewportWidth);
+ dxViewport.Height = static_cast<float>(dxViewportHeight);
+ }
+ dxViewport.MinDepth = actualZNear;
+ dxViewport.MaxDepth = actualZFar;
+ }
- mRenderer->getDeviceContext()->RSSetViewports(1, &dxViewport);
+ mRenderer->getDeviceContext()->RSSetViewports(numRectangles, dxViewports.data());
mCurViewport = viewport;
mCurNear = actualZNear;
mCurFar = actualZFar;
- // On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders
- // using viewAdjust (like the D3D9 renderer).
+ const D3D11_VIEWPORT adjustViewport = {static_cast<FLOAT>(dxViewportTopLeftX),
+ static_cast<FLOAT>(dxViewportTopLeftY),
+ static_cast<FLOAT>(dxViewportWidth),
+ static_cast<FLOAT>(dxViewportHeight),
+ actualZNear,
+ actualZFar};
+ mShaderConstants.onViewportChange(viewport, adjustViewport, is9_3, mCurPresentPathFastEnabled);
+}
+
+void StateManager11::invalidateRenderTarget()
+{
+ mRenderTargetIsDirty = true;
+}
+
+void StateManager11::processFramebufferInvalidation(const gl::Context *context)
+{
+ if (!mRenderTargetIsDirty)
+ {
+ return;
+ }
+
+ ASSERT(context);
+
+ mRenderTargetIsDirty = false;
+ mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET);
+
+ // The pixel shader is dependent on the output layout.
+ invalidateShaders();
+
+ // The D3D11 blend state is heavily dependent on the current render target.
+ mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
+
+ gl::Framebuffer *fbo = context->getGLState().getDrawFramebuffer();
+ ASSERT(fbo);
+
+ // Disable the depth test/depth write if we are using a stencil-only attachment.
+ // This is because ANGLE emulates stencil-only with D24S8 on D3D11 - we should neither read
+ // nor write to the unused depth part of this emulated texture.
+ bool disableDepth = (!fbo->hasDepth() && fbo->hasStencil());
+
+ // Similarly we disable the stencil portion of the DS attachment if the app only binds depth.
+ bool disableStencil = (fbo->hasDepth() && !fbo->hasStencil());
+
+ if (!mCurDisableDepth.valid() || disableDepth != mCurDisableDepth.value() ||
+ !mCurDisableStencil.valid() || disableStencil != mCurDisableStencil.value())
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
+ mCurDisableDepth = disableDepth;
+ mCurDisableStencil = disableStencil;
+ }
+
+ bool multiSample = (fbo->getCachedSamples(context) != 0);
+ if (multiSample != mCurRasterState.multiSample)
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
+ mCurRasterState.multiSample = multiSample;
+ }
+
+ checkPresentPath(context);
+
if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
{
- mVertexConstants.viewAdjust[0] = static_cast<float>((viewport.width - dxViewportWidth) +
- 2 * (viewport.x - dxViewportTopLeftX)) /
- dxViewport.Width;
- mVertexConstants.viewAdjust[1] = static_cast<float>((viewport.height - dxViewportHeight) +
- 2 * (viewport.y - dxViewportTopLeftY)) /
- dxViewport.Height;
- mVertexConstants.viewAdjust[2] = static_cast<float>(viewport.width) / dxViewport.Width;
- mVertexConstants.viewAdjust[3] = static_cast<float>(viewport.height) / dxViewport.Height;
+ const auto *firstAttachment = fbo->getFirstNonNullAttachment();
+ if (firstAttachment)
+ {
+ const auto &size = firstAttachment->getSize();
+ if (mViewportBounds.width != size.width || mViewportBounds.height != size.height)
+ {
+ mViewportBounds = gl::Extents(size.width, size.height, 1);
+ invalidateViewport(context);
+ }
+ }
}
+}
- mPixelConstants.viewCoords[0] = viewport.width * 0.5f;
- mPixelConstants.viewCoords[1] = viewport.height * 0.5f;
- mPixelConstants.viewCoords[2] = viewport.x + (viewport.width * 0.5f);
- mPixelConstants.viewCoords[3] = viewport.y + (viewport.height * 0.5f);
+void StateManager11::invalidateBoundViews()
+{
+ mCurVertexSRVs.clear();
+ mCurPixelSRVs.clear();
- // Instanced pointsprite emulation requires ViewCoords to be defined in the
- // the vertex shader.
- mVertexConstants.viewCoords[0] = mPixelConstants.viewCoords[0];
- mVertexConstants.viewCoords[1] = mPixelConstants.viewCoords[1];
- mVertexConstants.viewCoords[2] = mPixelConstants.viewCoords[2];
- mVertexConstants.viewCoords[3] = mPixelConstants.viewCoords[3];
+ invalidateRenderTarget();
+}
- mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
- mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
+void StateManager11::invalidateVertexBuffer()
+{
+ unsigned int limit = std::min<unsigned int>(mRenderer->getNativeCaps().maxVertexAttributes,
+ gl::MAX_VERTEX_ATTRIBS);
+ mDirtyVertexBufferRange = gl::RangeUI(0, limit);
+ mInputLayoutIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_ATTRIBS);
+ invalidateVertexAttributeTranslation();
+}
- mVertexConstants.depthRange[0] = actualZNear;
- mVertexConstants.depthRange[1] = actualZFar;
- mVertexConstants.depthRange[2] = actualZFar - actualZNear;
+void StateManager11::invalidateViewport(const gl::Context *context)
+{
+ mInternalDirtyBits.set(DIRTY_BIT_VIEWPORT_STATE);
- mPixelConstants.depthRange[0] = actualZNear;
- mPixelConstants.depthRange[1] = actualZFar;
- mPixelConstants.depthRange[2] = actualZFar - actualZNear;
+ // Viewport affects the driver constants.
+ invalidateDriverUniforms();
+}
- mPixelConstants.viewScale[0] = 1.0f;
- mPixelConstants.viewScale[1] = mCurPresentPathFastEnabled ? 1.0f : -1.0f;
- mPixelConstants.viewScale[2] = 1.0f;
- mPixelConstants.viewScale[3] = 1.0f;
+void StateManager11::invalidateTexturesAndSamplers()
+{
+ mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
+ invalidateSwizzles();
- mVertexConstants.viewScale[0] = mPixelConstants.viewScale[0];
- mVertexConstants.viewScale[1] = mPixelConstants.viewScale[1];
- mVertexConstants.viewScale[2] = mPixelConstants.viewScale[2];
- mVertexConstants.viewScale[3] = mPixelConstants.viewScale[3];
+ // Texture state affects the driver uniforms (base level, etc).
+ invalidateDriverUniforms();
+}
- mViewportStateIsDirty = false;
+void StateManager11::invalidateSwizzles()
+{
+ mDirtySwizzles = true;
}
-void StateManager11::invalidateRenderTarget()
+void StateManager11::invalidateProgramUniforms()
+{
+ mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORMS);
+}
+
+void StateManager11::invalidateDriverUniforms()
+{
+ mInternalDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS);
+}
+
+void StateManager11::invalidateProgramUniformBuffers()
+{
+ mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS);
+}
+
+void StateManager11::invalidateConstantBuffer(unsigned int slot)
{
- for (auto &appliedRTV : mAppliedRTVs)
+ if (slot == d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER)
{
- appliedRTV = angle::DirtyPointer;
+ invalidateDriverUniforms();
+ }
+ else if (slot == d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK)
+ {
+ invalidateProgramUniforms();
+ }
+ else
+ {
+ invalidateProgramUniformBuffers();
}
- mAppliedDSV = angle::DirtyPointer;
}
-void StateManager11::invalidateEverything()
+void StateManager11::invalidateShaders()
{
- mBlendStateIsDirty = true;
- mDepthStencilStateIsDirty = true;
- mRasterizerStateIsDirty = true;
- mScissorStateIsDirty = true;
- mViewportStateIsDirty = true;
+ mInternalDirtyBits.set(DIRTY_BIT_SHADERS);
+}
- // We reset the current SRV data because it might not be in sync with D3D's state
- // anymore. For example when a currently used SRV is used as an RTV, D3D silently
- // remove it from its state.
- mCurVertexSRVs.clear();
- mCurPixelSRVs.clear();
+void StateManager11::setRenderTarget(ID3D11RenderTargetView *rtv, ID3D11DepthStencilView *dsv)
+{
+ if ((rtv && unsetConflictingView(rtv)) || (dsv && unsetConflictingView(dsv)))
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
+ }
- invalidateRenderTarget();
+ mRenderer->getDeviceContext()->OMSetRenderTargets(1, &rtv, dsv);
+ mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET);
}
-bool StateManager11::setRenderTargets(const RenderTargetArray &renderTargets,
- ID3D11DepthStencilView *depthStencil)
+void StateManager11::setRenderTargets(ID3D11RenderTargetView **rtvs,
+ UINT numRTVs,
+ ID3D11DepthStencilView *dsv)
{
- // TODO(jmadill): Use context caps?
- UINT drawBuffers = mRenderer->getRendererCaps().maxDrawBuffers;
+ bool anyDirty = false;
- // Apply the render target and depth stencil
- size_t arraySize = sizeof(uintptr_t) * drawBuffers;
- if (memcmp(renderTargets.data(), mAppliedRTVs.data(), arraySize) == 0 &&
- reinterpret_cast<uintptr_t>(depthStencil) == mAppliedDSV)
+ for (UINT rtvIndex = 0; rtvIndex < numRTVs; ++rtvIndex)
{
- return false;
+ anyDirty = anyDirty || unsetConflictingView(rtvs[rtvIndex]);
}
- // The D3D11 blend state is heavily dependent on the current render target.
- mBlendStateIsDirty = true;
+ if (dsv)
+ {
+ anyDirty = anyDirty || unsetConflictingView(dsv);
+ }
- for (UINT rtIndex = 0; rtIndex < drawBuffers; rtIndex++)
+ if (anyDirty)
{
- mAppliedRTVs[rtIndex] = reinterpret_cast<uintptr_t>(renderTargets[rtIndex]);
+ mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
}
- mAppliedDSV = reinterpret_cast<uintptr_t>(depthStencil);
- mRenderer->getDeviceContext()->OMSetRenderTargets(drawBuffers, renderTargets.data(),
- depthStencil);
- return true;
+ mRenderer->getDeviceContext()->OMSetRenderTargets(numRTVs, (numRTVs > 0) ? rtvs : nullptr, dsv);
+ mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET);
}
-void StateManager11::setRenderTarget(ID3D11RenderTargetView *renderTarget,
- ID3D11DepthStencilView *depthStencil)
+void StateManager11::invalidateVertexAttributeTranslation()
{
- mRenderer->getDeviceContext()->OMSetRenderTargets(1, &renderTarget, depthStencil);
+ mVertexAttribsNeedTranslation = true;
}
-void StateManager11::setShaderResource(gl::SamplerType shaderType,
- UINT resourceSlot,
- ID3D11ShaderResourceView *srv)
+void StateManager11::onBeginQuery(Query11 *query)
{
- auto &currentSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
+ mCurrentQueries.insert(query);
+}
- ASSERT(static_cast<size_t>(resourceSlot) < currentSRVs.size());
- const SRVRecord &record = currentSRVs[resourceSlot];
+void StateManager11::onDeleteQueryObject(Query11 *query)
+{
+ mCurrentQueries.erase(query);
+}
- if (record.srv != reinterpret_cast<uintptr_t>(srv))
+gl::Error StateManager11::onMakeCurrent(const gl::Context *context)
+{
+ const gl::State &state = context->getGLState();
+
+ for (Query11 *query : mCurrentQueries)
{
- auto deviceContext = mRenderer->getDeviceContext();
- if (shaderType == gl::SAMPLER_VERTEX)
- {
- deviceContext->VSSetShaderResources(resourceSlot, 1, &srv);
- }
- else
+ ANGLE_TRY(query->pause());
+ }
+ mCurrentQueries.clear();
+
+ for (GLenum queryType : QueryTypes)
+ {
+ gl::Query *query = state.getActiveQuery(queryType);
+ if (query != nullptr)
{
- deviceContext->PSSetShaderResources(resourceSlot, 1, &srv);
+ Query11 *query11 = GetImplAs<Query11>(query);
+ ANGLE_TRY(query11->resume());
+ mCurrentQueries.insert(query11);
}
-
- currentSRVs.update(resourceSlot, srv);
}
+
+ return gl::NoError();
}
gl::Error StateManager11::clearTextures(gl::SamplerType samplerType,
@@ -856,185 +1528,1548 @@ gl::Error StateManager11::clearTextures(gl::SamplerType samplerType,
{
if (rangeStart == rangeEnd)
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
auto &currentSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
- gl::Range<size_t> clearRange(rangeStart, rangeStart);
- clearRange.extend(std::min(rangeEnd, currentSRVs.highestUsed()));
-
+ gl::Range<size_t> clearRange(rangeStart, std::min(rangeEnd, currentSRVs.highestUsed()));
if (clearRange.empty())
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
- auto deviceContext = mRenderer->getDeviceContext();
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
if (samplerType == gl::SAMPLER_VERTEX)
{
- deviceContext->VSSetShaderResources(static_cast<unsigned int>(rangeStart),
- static_cast<unsigned int>(rangeEnd - rangeStart),
+ deviceContext->VSSetShaderResources(static_cast<unsigned int>(clearRange.low()),
+ static_cast<unsigned int>(clearRange.length()),
&mNullSRVs[0]);
}
else
{
- deviceContext->PSSetShaderResources(static_cast<unsigned int>(rangeStart),
- static_cast<unsigned int>(rangeEnd - rangeStart),
+ deviceContext->PSSetShaderResources(static_cast<unsigned int>(clearRange.low()),
+ static_cast<unsigned int>(clearRange.length()),
&mNullSRVs[0]);
}
- for (size_t samplerIndex = rangeStart; samplerIndex < rangeEnd; ++samplerIndex)
+ for (size_t samplerIndex : clearRange)
{
currentSRVs.update(samplerIndex, nullptr);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-void StateManager11::unsetConflictingSRVs(gl::SamplerType samplerType,
+bool StateManager11::unsetConflictingView(ID3D11View *view)
+{
+ uintptr_t resource = reinterpret_cast<uintptr_t>(GetViewResource(view));
+ return unsetConflictingSRVs(gl::SAMPLER_VERTEX, resource, nullptr) ||
+ unsetConflictingSRVs(gl::SAMPLER_PIXEL, resource, nullptr);
+}
+
+bool StateManager11::unsetConflictingSRVs(gl::SamplerType samplerType,
uintptr_t resource,
- const gl::ImageIndex &index)
+ const gl::ImageIndex *index)
{
auto &currentSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
+ bool foundOne = false;
+
for (size_t resourceIndex = 0; resourceIndex < currentSRVs.size(); ++resourceIndex)
{
auto &record = currentSRVs[resourceIndex];
if (record.srv && record.resource == resource &&
- ImageIndexConflictsWithSRV(index, record.desc))
+ (!index || ImageIndexConflictsWithSRV(*index, record.desc)))
{
- setShaderResource(samplerType, static_cast<UINT>(resourceIndex), NULL);
+ setShaderResourceInternal<d3d11::ShaderResourceView>(
+ samplerType, static_cast<UINT>(resourceIndex), nullptr);
+ foundOne = true;
}
}
+
+ return foundOne;
+}
+
+void StateManager11::unsetConflictingAttachmentResources(
+ const gl::FramebufferAttachment *attachment,
+ ID3D11Resource *resource)
+{
+ // Unbind render target SRVs from the shader here to prevent D3D11 warnings.
+ if (attachment->type() == GL_TEXTURE)
+ {
+ uintptr_t resourcePtr = reinterpret_cast<uintptr_t>(resource);
+ const gl::ImageIndex &index = attachment->getTextureImageIndex();
+ // The index doesn't need to be corrected for the small compressed texture workaround
+ // because a rendertarget is never compressed.
+ unsetConflictingSRVs(gl::SAMPLER_VERTEX, resourcePtr, &index);
+ unsetConflictingSRVs(gl::SAMPLER_PIXEL, resourcePtr, &index);
+ }
+ else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT)
+ {
+ uintptr_t resourcePtr = reinterpret_cast<uintptr_t>(resource);
+ unsetConflictingSRVs(gl::SAMPLER_VERTEX, resourcePtr, nullptr);
+ unsetConflictingSRVs(gl::SAMPLER_PIXEL, resourcePtr, nullptr);
+ }
}
-void StateManager11::initialize(const gl::Caps &caps)
+gl::Error StateManager11::initialize(const gl::Caps &caps, const gl::Extensions &extensions)
{
mCurVertexSRVs.initialize(caps.maxVertexTextureImageUnits);
mCurPixelSRVs.initialize(caps.maxTextureImageUnits);
// Initialize cached NULL SRV block
mNullSRVs.resize(caps.maxTextureImageUnits, nullptr);
+
+ mCurrentValueAttribs.resize(caps.maxVertexAttributes);
+
+ mForceSetVertexSamplerStates.resize(caps.maxVertexTextureImageUnits, true);
+ mForceSetPixelSamplerStates.resize(caps.maxTextureImageUnits, true);
+ mForceSetComputeSamplerStates.resize(caps.maxComputeTextureImageUnits, true);
+
+ mCurVertexSamplerStates.resize(caps.maxVertexTextureImageUnits);
+ mCurPixelSamplerStates.resize(caps.maxTextureImageUnits);
+ mCurComputeSamplerStates.resize(caps.maxComputeTextureImageUnits);
+
+ mShaderConstants.init(caps);
+
+ mIsMultiviewEnabled = extensions.multiview;
+ mViewportOffsets.resize(1u);
+
+ ANGLE_TRY(mVertexDataManager.initialize());
+
+ mCurrentAttributes.reserve(gl::MAX_VERTEX_ATTRIBS);
+
+ return gl::NoError();
+}
+
+void StateManager11::deinitialize()
+{
+ mCurrentValueAttribs.clear();
+ mInputLayoutCache.clear();
+ mVertexDataManager.deinitialize();
+ mIndexDataManager.deinitialize();
+
+ mDriverConstantBufferVS.reset();
+ mDriverConstantBufferPS.reset();
+ mDriverConstantBufferCS.reset();
}
-gl::Error StateManager11::syncFramebuffer(const gl::Framebuffer *framebuffer)
+gl::Error StateManager11::syncFramebuffer(const gl::Context *context, gl::Framebuffer *framebuffer)
{
- // Get the color render buffer and serial
- // Also extract the render target dimensions and view
- unsigned int renderTargetWidth = 0;
- unsigned int renderTargetHeight = 0;
- DXGI_FORMAT renderTargetFormat = DXGI_FORMAT_UNKNOWN;
- RenderTargetArray framebufferRTVs;
- bool missingColorRenderTarget = true;
+ Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer);
+
+ // Applies the render target surface, depth stencil surface, viewport rectangle and
+ // scissor rectangle to the renderer
+ ASSERT(framebuffer && !framebuffer->hasAnyDirtyBit() && framebuffer->cachedComplete());
+
+ // Check for zero-sized default framebuffer, which is a special case.
+ // in this case we do not wish to modify any state and just silently return false.
+ // this will not report any gl error but will cause the calling method to return.
+ if (framebuffer->id() == 0)
+ {
+ ASSERT(!framebuffer11->hasAnyInternalDirtyBit());
+ const gl::Extents &size = framebuffer->getFirstColorbuffer()->getSize();
+ if (size.width == 0 || size.height == 0)
+ {
+ return gl::NoError();
+ }
+ }
+
+ RTVArray framebufferRTVs = {{}};
- framebufferRTVs.fill(nullptr);
+ const auto &colorRTs = framebuffer11->getCachedColorRenderTargets();
- const Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer);
- const gl::AttachmentList &colorbuffers = framebuffer11->getColorAttachmentsForRender();
+ size_t appliedRTIndex = 0;
+ bool skipInactiveRTs = mRenderer->getWorkarounds().mrtPerfWorkaround;
+ const auto &drawStates = framebuffer->getDrawBufferStates();
+ gl::DrawBufferMask activeProgramOutputs =
+ context->getContextState().getState().getProgram()->getActiveOutputVariables();
+ UINT maxExistingRT = 0;
- for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
+ for (size_t rtIndex = 0; rtIndex < colorRTs.size(); ++rtIndex)
{
- const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
+ const RenderTarget11 *renderTarget = colorRTs[rtIndex];
- if (colorbuffer)
+ // Skip inactive rendertargets if the workaround is enabled.
+ if (skipInactiveRTs &&
+ (!renderTarget || drawStates[rtIndex] == GL_NONE || !activeProgramOutputs[rtIndex]))
{
- // the draw buffer must be either "none", "back" for the default buffer or the same
- // index as this color (in order)
-
- // check for zero-sized default framebuffer, which is a special case.
- // in this case we do not wish to modify any state and just silently return false.
- // this will not report any gl error but will cause the calling method to return.
- const gl::Extents &size = colorbuffer->getSize();
- if (size.width == 0 || size.height == 0)
- {
- return gl::Error(GL_NO_ERROR);
- }
+ continue;
+ }
- // Extract the render target dimensions and view
- RenderTarget11 *renderTarget = NULL;
- gl::Error error = colorbuffer->getRenderTarget(&renderTarget);
- if (error.isError())
- {
- return error;
- }
- ASSERT(renderTarget);
+ if (renderTarget)
+ {
+ framebufferRTVs[appliedRTIndex] = renderTarget->getRenderTargetView().get();
+ ASSERT(framebufferRTVs[appliedRTIndex]);
+ maxExistingRT = static_cast<UINT>(appliedRTIndex) + 1;
+
+ // Unset conflicting texture SRVs
+ const auto *attachment = framebuffer->getColorbuffer(rtIndex);
+ ASSERT(attachment);
+ unsetConflictingAttachmentResources(attachment, renderTarget->getTexture().get());
+ }
+
+ appliedRTIndex++;
+ }
+
+ // Get the depth stencil buffers
+ ID3D11DepthStencilView *framebufferDSV = nullptr;
+ const auto *depthStencilRenderTarget = framebuffer11->getCachedDepthStencilRenderTarget();
+ if (depthStencilRenderTarget)
+ {
+ framebufferDSV = depthStencilRenderTarget->getDepthStencilView().get();
+ ASSERT(framebufferDSV);
+
+ // Unset conflicting texture SRVs
+ const auto *attachment = framebuffer->getDepthOrStencilbuffer();
+ ASSERT(attachment);
+ unsetConflictingAttachmentResources(attachment,
+ depthStencilRenderTarget->getTexture().get());
+ }
+
+ // TODO(jmadill): Use context caps?
+ ASSERT(maxExistingRT <= static_cast<UINT>(mRenderer->getNativeCaps().maxDrawBuffers));
+
+ // Apply the render target and depth stencil
+ mRenderer->getDeviceContext()->OMSetRenderTargets(maxExistingRT, framebufferRTVs.data(),
+ framebufferDSV);
+
+ return gl::NoError();
+}
+
+void StateManager11::invalidateCurrentValueAttrib(size_t attribIndex)
+{
+ mDirtyCurrentValueAttribs.set(attribIndex);
+ mInternalDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_ATTRIBS);
+}
+
+gl::Error StateManager11::syncCurrentValueAttribs(const gl::State &glState)
+{
+ const auto &activeAttribsMask = glState.getProgram()->getActiveAttribLocationsMask();
+ const auto &dirtyActiveAttribs = (activeAttribsMask & mDirtyCurrentValueAttribs);
+
+ if (!dirtyActiveAttribs.any())
+ {
+ return gl::NoError();
+ }
+
+ const auto &vertexAttributes = glState.getVertexArray()->getVertexAttributes();
+ const auto &vertexBindings = glState.getVertexArray()->getVertexBindings();
+ mDirtyCurrentValueAttribs = (mDirtyCurrentValueAttribs & ~dirtyActiveAttribs);
+
+ for (auto attribIndex : dirtyActiveAttribs)
+ {
+ if (vertexAttributes[attribIndex].enabled)
+ continue;
+
+ const auto *attrib = &vertexAttributes[attribIndex];
+ const auto &currentValue = glState.getVertexAttribCurrentValue(attribIndex);
+ TranslatedAttribute *currentValueAttrib = &mCurrentValueAttribs[attribIndex];
+ currentValueAttrib->currentValueType = currentValue.Type;
+ currentValueAttrib->attribute = attrib;
+ currentValueAttrib->binding = &vertexBindings[attrib->bindingIndex];
+
+ mDirtyVertexBufferRange.extend(static_cast<unsigned int>(attribIndex));
+ mInputLayoutIsDirty = true;
+
+ ANGLE_TRY(mVertexDataManager.storeCurrentValue(currentValue, currentValueAttrib,
+ static_cast<size_t>(attribIndex)));
+ }
+
+ return gl::NoError();
+}
- framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView();
- ASSERT(framebufferRTVs[colorAttachment]);
+void StateManager11::setInputLayout(const d3d11::InputLayout *inputLayout)
+{
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ if (inputLayout == nullptr)
+ {
+ if (!mCurrentInputLayout.empty())
+ {
+ deviceContext->IASetInputLayout(nullptr);
+ mCurrentInputLayout.clear();
+ mInputLayoutIsDirty = true;
+ }
+ }
+ else if (inputLayout->getSerial() != mCurrentInputLayout)
+ {
+ deviceContext->IASetInputLayout(inputLayout->get());
+ mCurrentInputLayout = inputLayout->getSerial();
+ mInputLayoutIsDirty = true;
+ }
+}
+
+bool StateManager11::queueVertexBufferChange(size_t bufferIndex,
+ ID3D11Buffer *buffer,
+ UINT stride,
+ UINT offset)
+{
+ if (buffer != mCurrentVertexBuffers[bufferIndex] ||
+ stride != mCurrentVertexStrides[bufferIndex] ||
+ offset != mCurrentVertexOffsets[bufferIndex])
+ {
+ mInputLayoutIsDirty = true;
+ mDirtyVertexBufferRange.extend(static_cast<unsigned int>(bufferIndex));
+
+ mCurrentVertexBuffers[bufferIndex] = buffer;
+ mCurrentVertexStrides[bufferIndex] = stride;
+ mCurrentVertexOffsets[bufferIndex] = offset;
+ return true;
+ }
+
+ return false;
+}
+
+bool StateManager11::queueVertexOffsetChange(size_t bufferIndex, UINT offsetOnly)
+{
+ if (offsetOnly != mCurrentVertexOffsets[bufferIndex])
+ {
+ mInputLayoutIsDirty = true;
+ mDirtyVertexBufferRange.extend(static_cast<unsigned int>(bufferIndex));
+ mCurrentVertexOffsets[bufferIndex] = offsetOnly;
+ return true;
+ }
+ return false;
+}
- if (missingColorRenderTarget)
+void StateManager11::applyVertexBufferChanges()
+{
+ if (mDirtyVertexBufferRange.empty())
+ {
+ return;
+ }
+
+ ASSERT(mDirtyVertexBufferRange.high() <= gl::MAX_VERTEX_ATTRIBS);
+
+ UINT start = static_cast<UINT>(mDirtyVertexBufferRange.low());
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ deviceContext->IASetVertexBuffers(start, static_cast<UINT>(mDirtyVertexBufferRange.length()),
+ &mCurrentVertexBuffers[start], &mCurrentVertexStrides[start],
+ &mCurrentVertexOffsets[start]);
+
+ mDirtyVertexBufferRange = gl::RangeUI(gl::MAX_VERTEX_ATTRIBS, 0);
+}
+
+void StateManager11::setSingleVertexBuffer(const d3d11::Buffer *buffer, UINT stride, UINT offset)
+{
+ ID3D11Buffer *native = buffer ? buffer->get() : nullptr;
+ if (queueVertexBufferChange(0, native, stride, offset))
+ {
+ applyVertexBufferChanges();
+ }
+}
+
+gl::Error StateManager11::updateState(const gl::Context *context, GLenum drawMode)
+{
+ const auto &glState = context->getGLState();
+ auto *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
+
+ // TODO(jmadill): Use dirty bits.
+ processFramebufferInvalidation(context);
+
+ // TODO(jmadill): Use dirty bits.
+ if (programD3D->updateSamplerMapping() == ProgramD3D::SamplerMapping::WasDirty)
+ {
+ invalidateTexturesAndSamplers();
+ }
+
+ // TODO(jmadill): Use dirty bits.
+ if (programD3D->areVertexUniformsDirty() || programD3D->areFragmentUniformsDirty())
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORMS);
+ }
+
+ // Transform feedback affects the stream-out geometry shader.
+ // TODO(jmadill): Use dirty bits.
+ if (glState.isTransformFeedbackActiveUnpaused() != mIsTransformFeedbackCurrentlyActiveUnpaused)
+ {
+ mIsTransformFeedbackCurrentlyActiveUnpaused = glState.isTransformFeedbackActiveUnpaused();
+ invalidateShaders();
+ }
+
+ // Swizzling can cause internal state changes with blit shaders.
+ if (mDirtySwizzles)
+ {
+ ANGLE_TRY(generateSwizzles(context));
+ mDirtySwizzles = false;
+ }
+
+ gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
+ Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer);
+ ANGLE_TRY(framebuffer11->markAttachmentsDirty(context));
+
+ if (framebuffer11->hasAnyInternalDirtyBit())
+ {
+ ASSERT(framebuffer->id() != 0);
+ framebuffer11->syncInternalState(context);
+ }
+
+ bool pointDrawMode = (drawMode == GL_POINTS);
+ if (pointDrawMode != mCurRasterState.pointDrawMode)
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
+
+ // Changing from points to not points (or vice-versa) affects the geometry shader.
+ invalidateShaders();
+ }
+
+ // TODO(jiawei.shao@intel.com): This can be recomputed only on framebuffer or multisample mask
+ // state changes.
+ RenderTarget11 *firstRT = framebuffer11->getFirstRenderTarget();
+ int samples = (firstRT ? firstRT->getSamples() : 0);
+ unsigned int sampleMask = GetBlendSampleMask(glState, samples);
+ if (sampleMask != mCurSampleMask)
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
+ }
+
+ // Changing the vertex attribute state can affect the vertex shader.
+ gl::VertexArray *vao = glState.getVertexArray();
+ VertexArray11 *vao11 = GetImplAs<VertexArray11>(vao);
+ if (vao11->flushAttribUpdates(context))
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_SHADERS);
+ }
+
+ auto dirtyBitsCopy = mInternalDirtyBits;
+ mInternalDirtyBits.reset();
+
+ for (auto dirtyBit : dirtyBitsCopy)
+ {
+ switch (dirtyBit)
+ {
+ case DIRTY_BIT_RENDER_TARGET:
+ ANGLE_TRY(syncFramebuffer(context, framebuffer));
+ break;
+ case DIRTY_BIT_VIEWPORT_STATE:
+ syncViewport(context);
+ break;
+ case DIRTY_BIT_SCISSOR_STATE:
+ syncScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());
+ break;
+ case DIRTY_BIT_RASTERIZER_STATE:
+ ANGLE_TRY(syncRasterizerState(context, pointDrawMode));
+ break;
+ case DIRTY_BIT_BLEND_STATE:
+ ANGLE_TRY(syncBlendState(context, framebuffer, glState.getBlendState(),
+ glState.getBlendColor(), sampleMask));
+ break;
+ case DIRTY_BIT_DEPTH_STENCIL_STATE:
+ ANGLE_TRY(syncDepthStencilState(glState));
+ break;
+ case DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE:
+ // TODO(jmadill): More fine-grained update.
+ ANGLE_TRY(syncTextures(context));
+ break;
+ case DIRTY_BIT_PROGRAM_UNIFORMS:
+ ANGLE_TRY(applyUniforms(programD3D));
+ break;
+ case DIRTY_BIT_DRIVER_UNIFORMS:
+ // This must happen after viewport sync; the viewport affects builtin uniforms.
+ ANGLE_TRY(applyDriverUniforms(*programD3D));
+ break;
+ case DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS:
+ ANGLE_TRY(syncUniformBuffers(context, programD3D));
+ break;
+ case DIRTY_BIT_SHADERS:
+ ANGLE_TRY(syncProgram(context, drawMode));
+ break;
+ case DIRTY_BIT_CURRENT_VALUE_ATTRIBS:
+ ANGLE_TRY(syncCurrentValueAttribs(glState));
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+
+ ANGLE_TRY(syncTransformFeedbackBuffers(context));
+
+ // Check that we haven't set any dirty bits in the flushing of the dirty bits loop.
+ ASSERT(mInternalDirtyBits.none());
+
+ return gl::NoError();
+}
+
+void StateManager11::setShaderResourceShared(gl::SamplerType shaderType,
+ UINT resourceSlot,
+ const d3d11::SharedSRV *srv)
+{
+ setShaderResourceInternal(shaderType, resourceSlot, srv);
+
+ // TODO(jmadill): Narrower dirty region.
+ mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
+}
+
+void StateManager11::setShaderResource(gl::SamplerType shaderType,
+ UINT resourceSlot,
+ const d3d11::ShaderResourceView *srv)
+{
+ setShaderResourceInternal(shaderType, resourceSlot, srv);
+
+ // TODO(jmadill): Narrower dirty region.
+ mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
+}
+
+void StateManager11::setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology)
+{
+ if (primitiveTopology != mCurrentPrimitiveTopology)
+ {
+ mRenderer->getDeviceContext()->IASetPrimitiveTopology(primitiveTopology);
+ mCurrentPrimitiveTopology = primitiveTopology;
+ }
+}
+
+void StateManager11::setDrawShaders(const d3d11::VertexShader *vertexShader,
+ const d3d11::GeometryShader *geometryShader,
+ const d3d11::PixelShader *pixelShader)
+{
+ setVertexShader(vertexShader);
+ setGeometryShader(geometryShader);
+ setPixelShader(pixelShader);
+}
+
+void StateManager11::setVertexShader(const d3d11::VertexShader *shader)
+{
+ ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);
+
+ if (serial != mAppliedVertexShader)
+ {
+ ID3D11VertexShader *appliedShader = shader ? shader->get() : nullptr;
+ mRenderer->getDeviceContext()->VSSetShader(appliedShader, nullptr, 0);
+ mAppliedVertexShader = serial;
+ invalidateShaders();
+ }
+}
+
+void StateManager11::setGeometryShader(const d3d11::GeometryShader *shader)
+{
+ ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);
+
+ if (serial != mAppliedGeometryShader)
+ {
+ ID3D11GeometryShader *appliedShader = shader ? shader->get() : nullptr;
+ mRenderer->getDeviceContext()->GSSetShader(appliedShader, nullptr, 0);
+ mAppliedGeometryShader = serial;
+ invalidateShaders();
+ }
+}
+
+void StateManager11::setPixelShader(const d3d11::PixelShader *shader)
+{
+ ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);
+
+ if (serial != mAppliedPixelShader)
+ {
+ ID3D11PixelShader *appliedShader = shader ? shader->get() : nullptr;
+ mRenderer->getDeviceContext()->PSSetShader(appliedShader, nullptr, 0);
+ mAppliedPixelShader = serial;
+ invalidateShaders();
+ }
+}
+
+void StateManager11::setComputeShader(const d3d11::ComputeShader *shader)
+{
+ ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);
+
+ if (serial != mAppliedComputeShader)
+ {
+ ID3D11ComputeShader *appliedShader = shader ? shader->get() : nullptr;
+ mRenderer->getDeviceContext()->CSSetShader(appliedShader, nullptr, 0);
+ mAppliedComputeShader = serial;
+ // TODO(jmadill): Dirty bits for compute.
+ }
+}
+
+void StateManager11::setVertexConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer)
+{
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ auto &currentSerial = mCurrentConstantBufferVS[slot];
+
+ mCurrentConstantBufferVSOffset[slot] = 0;
+ mCurrentConstantBufferVSSize[slot] = 0;
+
+ if (buffer)
+ {
+ if (currentSerial != buffer->getSerial())
+ {
+ deviceContext->VSSetConstantBuffers(slot, 1, buffer->getPointer());
+ currentSerial = buffer->getSerial();
+ invalidateConstantBuffer(slot);
+ }
+ }
+ else
+ {
+ if (!currentSerial.empty())
+ {
+ ID3D11Buffer *nullBuffer = nullptr;
+ deviceContext->VSSetConstantBuffers(slot, 1, &nullBuffer);
+ currentSerial.clear();
+ invalidateConstantBuffer(slot);
+ }
+ }
+}
+
+void StateManager11::setPixelConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer)
+{
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ auto &currentSerial = mCurrentConstantBufferPS[slot];
+
+ mCurrentConstantBufferPSOffset[slot] = 0;
+ mCurrentConstantBufferPSSize[slot] = 0;
+
+ if (buffer)
+ {
+ if (currentSerial != buffer->getSerial())
+ {
+ deviceContext->PSSetConstantBuffers(slot, 1, buffer->getPointer());
+ currentSerial = buffer->getSerial();
+ invalidateConstantBuffer(slot);
+ }
+ }
+ else
+ {
+ if (!currentSerial.empty())
+ {
+ ID3D11Buffer *nullBuffer = nullptr;
+ deviceContext->PSSetConstantBuffers(slot, 1, &nullBuffer);
+ currentSerial.clear();
+ invalidateConstantBuffer(slot);
+ }
+ }
+}
+
+void StateManager11::setDepthStencilState(const d3d11::DepthStencilState *depthStencilState,
+ UINT stencilRef)
+{
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ if (depthStencilState)
+ {
+ deviceContext->OMSetDepthStencilState(depthStencilState->get(), stencilRef);
+ }
+ else
+ {
+ deviceContext->OMSetDepthStencilState(nullptr, stencilRef);
+ }
+
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
+}
+
+void StateManager11::setSimpleBlendState(const d3d11::BlendState *blendState)
+{
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ if (blendState)
+ {
+ deviceContext->OMSetBlendState(blendState->get(), nullptr, 0xFFFFFFFF);
+ }
+ else
+ {
+ deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFFF);
+ }
+
+ mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
+}
+
+void StateManager11::setRasterizerState(const d3d11::RasterizerState *rasterizerState)
+{
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ if (rasterizerState)
+ {
+ deviceContext->RSSetState(rasterizerState->get());
+ }
+ else
+ {
+ deviceContext->RSSetState(nullptr);
+ }
+
+ mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
+}
+
+void StateManager11::setSimpleViewport(const gl::Extents &extents)
+{
+ setSimpleViewport(extents.width, extents.height);
+}
+
+void StateManager11::setSimpleViewport(int width, int height)
+{
+ D3D11_VIEWPORT viewport;
+ viewport.TopLeftX = 0;
+ viewport.TopLeftY = 0;
+ viewport.Width = static_cast<FLOAT>(width);
+ viewport.Height = static_cast<FLOAT>(height);
+ viewport.MinDepth = 0.0f;
+ viewport.MaxDepth = 1.0f;
+
+ mRenderer->getDeviceContext()->RSSetViewports(1, &viewport);
+ mInternalDirtyBits.set(DIRTY_BIT_VIEWPORT_STATE);
+}
+
+void StateManager11::setSimplePixelTextureAndSampler(const d3d11::SharedSRV &srv,
+ const d3d11::SamplerState &samplerState)
+{
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ setShaderResourceInternal(gl::SAMPLER_PIXEL, 0, &srv);
+ deviceContext->PSSetSamplers(0, 1, samplerState.getPointer());
+
+ mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
+ mForceSetPixelSamplerStates[0] = true;
+}
+
+void StateManager11::setSimpleScissorRect(const gl::Rectangle &glRect)
+{
+ D3D11_RECT scissorRect;
+ scissorRect.left = glRect.x;
+ scissorRect.right = glRect.x + glRect.width;
+ scissorRect.top = glRect.y;
+ scissorRect.bottom = glRect.y + glRect.height;
+ setScissorRectD3D(scissorRect);
+}
+
+void StateManager11::setScissorRectD3D(const D3D11_RECT &d3dRect)
+{
+ mRenderer->getDeviceContext()->RSSetScissorRects(1, &d3dRect);
+ mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
+}
+
+// For each Direct3D sampler of either the pixel or vertex stage,
+// looks up the corresponding OpenGL texture image unit and texture type,
+// and sets the texture and its addressing/filtering state (or NULL when inactive).
+// Sampler mapping needs to be up-to-date on the program object before this is called.
+gl::Error StateManager11::applyTextures(const gl::Context *context, gl::SamplerType shaderType)
+{
+ const auto &glState = context->getGLState();
+ const auto &caps = context->getCaps();
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
+
+ ASSERT(!programD3D->isSamplerMappingDirty());
+
+ // TODO(jmadill): Use the Program's sampler bindings.
+ const auto &completeTextures = glState.getCompleteTextureCache();
+
+ unsigned int samplerRange = programD3D->getUsedSamplerRange(shaderType);
+ for (unsigned int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
+ {
+ GLint textureUnit = programD3D->getSamplerMapping(shaderType, samplerIndex, caps);
+ ASSERT(textureUnit != -1);
+ gl::Texture *texture = completeTextures[textureUnit];
+
+ // A nullptr texture indicates incomplete.
+ if (texture)
+ {
+ gl::Sampler *samplerObject = glState.getSampler(textureUnit);
+
+ const gl::SamplerState &samplerState =
+ samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState();
+
+ ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, texture, samplerState));
+ ANGLE_TRY(setTexture(context, shaderType, samplerIndex, texture));
+ }
+ else
+ {
+ GLenum textureType = programD3D->getSamplerTextureType(shaderType, samplerIndex);
+
+ // Texture is not sampler complete or it is in use by the framebuffer. Bind the
+ // incomplete texture.
+ gl::Texture *incompleteTexture = nullptr;
+ ANGLE_TRY(mRenderer->getIncompleteTexture(context, textureType, &incompleteTexture));
+ ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, incompleteTexture,
+ incompleteTexture->getSamplerState()));
+ ANGLE_TRY(setTexture(context, shaderType, samplerIndex, incompleteTexture));
+ }
+ }
+
+ // Set all the remaining textures to NULL
+ size_t samplerCount = (shaderType == gl::SAMPLER_PIXEL) ? caps.maxTextureImageUnits
+ : caps.maxVertexTextureImageUnits;
+ ANGLE_TRY(clearTextures(shaderType, samplerRange, samplerCount));
+
+ return gl::NoError();
+}
+
+gl::Error StateManager11::syncTextures(const gl::Context *context)
+{
+ ANGLE_TRY(applyTextures(context, gl::SAMPLER_VERTEX));
+ ANGLE_TRY(applyTextures(context, gl::SAMPLER_PIXEL));
+ return gl::NoError();
+}
+
+gl::Error StateManager11::setSamplerState(const gl::Context *context,
+ gl::SamplerType type,
+ int index,
+ gl::Texture *texture,
+ const gl::SamplerState &samplerState)
+{
+#if !defined(NDEBUG)
+ // Storage should exist, texture should be complete. Only verified in Debug.
+ TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
+ TextureStorage *storage = nullptr;
+ ANGLE_TRY(textureD3D->getNativeTexture(context, &storage));
+ ASSERT(storage);
+#endif // !defined(NDEBUG)
+
+ auto *deviceContext = mRenderer->getDeviceContext();
+
+ if (type == gl::SAMPLER_PIXEL)
+ {
+ ASSERT(static_cast<unsigned int>(index) < mRenderer->getNativeCaps().maxTextureImageUnits);
+
+ if (mForceSetPixelSamplerStates[index] ||
+ memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0)
+ {
+ ID3D11SamplerState *dxSamplerState = nullptr;
+ ANGLE_TRY(mRenderer->getSamplerState(samplerState, &dxSamplerState));
+
+ ASSERT(dxSamplerState != nullptr);
+ deviceContext->PSSetSamplers(index, 1, &dxSamplerState);
+
+ mCurPixelSamplerStates[index] = samplerState;
+ }
+
+ mForceSetPixelSamplerStates[index] = false;
+ }
+ else if (type == gl::SAMPLER_VERTEX)
+ {
+ ASSERT(static_cast<unsigned int>(index) <
+ mRenderer->getNativeCaps().maxVertexTextureImageUnits);
+
+ if (mForceSetVertexSamplerStates[index] ||
+ memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0)
+ {
+ ID3D11SamplerState *dxSamplerState = nullptr;
+ ANGLE_TRY(mRenderer->getSamplerState(samplerState, &dxSamplerState));
+
+ ASSERT(dxSamplerState != nullptr);
+ deviceContext->VSSetSamplers(index, 1, &dxSamplerState);
+
+ mCurVertexSamplerStates[index] = samplerState;
+ }
+
+ mForceSetVertexSamplerStates[index] = false;
+ }
+ else if (type == gl::SAMPLER_COMPUTE)
+ {
+ ASSERT(static_cast<unsigned int>(index) <
+ mRenderer->getNativeCaps().maxComputeTextureImageUnits);
+
+ if (mForceSetComputeSamplerStates[index] ||
+ memcmp(&samplerState, &mCurComputeSamplerStates[index], sizeof(gl::SamplerState)) != 0)
+ {
+ ID3D11SamplerState *dxSamplerState = nullptr;
+ ANGLE_TRY(mRenderer->getSamplerState(samplerState, &dxSamplerState));
+
+ ASSERT(dxSamplerState != nullptr);
+ deviceContext->CSSetSamplers(index, 1, &dxSamplerState);
+
+ mCurComputeSamplerStates[index] = samplerState;
+ }
+
+ mForceSetComputeSamplerStates[index] = false;
+ }
+ else
+ UNREACHABLE();
+
+ // Sampler metadata that's passed to shaders in uniforms is stored separately from rest of the
+ // sampler state since having it in contiguous memory makes it possible to memcpy to a constant
+ // buffer, and it doesn't affect the state set by PSSetSamplers/VSSetSamplers.
+ mShaderConstants.onSamplerChange(type, index, *texture);
+
+ return gl::NoError();
+}
+
+gl::Error StateManager11::setTexture(const gl::Context *context,
+ gl::SamplerType type,
+ int index,
+ gl::Texture *texture)
+{
+ const d3d11::SharedSRV *textureSRV = nullptr;
+
+ if (texture)
+ {
+ TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture);
+
+ TextureStorage *texStorage = nullptr;
+ ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage));
+
+ // Texture should be complete and have a storage
+ ASSERT(texStorage);
+
+ TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
+
+ ANGLE_TRY(storage11->getSRV(context, texture->getTextureState(), &textureSRV));
+
+ // If we get an invalid SRV here, something went wrong in the texture class and we're
+ // unexpectedly missing the shader resource view.
+ ASSERT(textureSRV->valid());
+
+ textureImpl->resetDirty();
+ }
+
+ ASSERT(
+ (type == gl::SAMPLER_PIXEL &&
+ static_cast<unsigned int>(index) < mRenderer->getNativeCaps().maxTextureImageUnits) ||
+ (type == gl::SAMPLER_VERTEX &&
+ static_cast<unsigned int>(index) < mRenderer->getNativeCaps().maxVertexTextureImageUnits));
+
+ setShaderResourceInternal(type, index, textureSRV);
+ return gl::NoError();
+}
+
+// Things that affect a program's dirtyness:
+// 1. Directly changing the program executable -> triggered in StateManager11::syncState.
+// 2. The vertex attribute layout -> triggered in VertexArray11::syncState/signal.
+// 3. The fragment shader's rendertargets -> triggered in Framebuffer11::syncState/signal.
+// 4. Enabling/disabling rasterizer discard. -> triggered in StateManager11::syncState.
+// 5. Enabling/disabling transform feedback. -> checked in StateManager11::updateState.
+// 6. An internal shader was used. -> triggered in StateManager11::set*Shader.
+// 7. Drawing with/without point sprites. -> checked in StateManager11::updateState.
+// TODO(jmadill): Use dirty bits for transform feedback.
+gl::Error StateManager11::syncProgram(const gl::Context *context, GLenum drawMode)
+{
+ Context11 *context11 = GetImplAs<Context11>(context);
+ ANGLE_TRY(context11->triggerDrawCallProgramRecompilation(context, drawMode));
+
+ const auto &glState = context->getGLState();
+ const auto *va11 = GetImplAs<VertexArray11>(glState.getVertexArray());
+ auto *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
+
+ programD3D->updateCachedInputLayout(va11->getCurrentStateSerial(), glState);
+
+ // Binaries must be compiled before the sync.
+ ASSERT(programD3D->hasVertexExecutableForCachedInputLayout());
+ ASSERT(programD3D->hasGeometryExecutableForPrimitiveType(drawMode));
+ ASSERT(programD3D->hasPixelExecutableForCachedOutputLayout());
+
+ ShaderExecutableD3D *vertexExe = nullptr;
+ ANGLE_TRY(programD3D->getVertexExecutableForCachedInputLayout(&vertexExe, nullptr));
+
+ ShaderExecutableD3D *pixelExe = nullptr;
+ ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(&pixelExe, nullptr));
+
+ ShaderExecutableD3D *geometryExe = nullptr;
+ ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(context, drawMode, &geometryExe,
+ nullptr));
+
+ const d3d11::VertexShader *vertexShader =
+ (vertexExe ? &GetAs<ShaderExecutable11>(vertexExe)->getVertexShader() : nullptr);
+
+ // Skip pixel shader if we're doing rasterizer discard.
+ const d3d11::PixelShader *pixelShader = nullptr;
+ if (!glState.getRasterizerState().rasterizerDiscard)
+ {
+ pixelShader = (pixelExe ? &GetAs<ShaderExecutable11>(pixelExe)->getPixelShader() : nullptr);
+ }
+
+ const d3d11::GeometryShader *geometryShader = nullptr;
+ if (glState.isTransformFeedbackActiveUnpaused())
+ {
+ geometryShader =
+ (vertexExe ? &GetAs<ShaderExecutable11>(vertexExe)->getStreamOutShader() : nullptr);
+ }
+ else
+ {
+ geometryShader =
+ (geometryExe ? &GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : nullptr);
+ }
+
+ setDrawShaders(vertexShader, geometryShader, pixelShader);
+
+ // Explicitly clear the shaders dirty bit.
+ mInternalDirtyBits.reset(DIRTY_BIT_SHADERS);
+
+ return gl::NoError();
+}
+
+gl::Error StateManager11::applyVertexBuffer(const gl::Context *context,
+ GLenum mode,
+ const DrawCallVertexParams &vertexParams,
+ bool isIndexedRendering)
+{
+ const auto &state = context->getGLState();
+ const gl::VertexArray *vertexArray = state.getVertexArray();
+ VertexArray11 *vertexArray11 = GetImplAs<VertexArray11>(vertexArray);
+
+ if (mVertexAttribsNeedTranslation)
+ {
+ ANGLE_TRY(vertexArray11->updateDirtyAndDynamicAttribs(context, &mVertexDataManager,
+ vertexParams));
+ mInputLayoutIsDirty = true;
+
+ // Determine if we need to update attribs on the next draw.
+ mVertexAttribsNeedTranslation = (vertexArray11->hasActiveDynamicAttrib(context));
+ }
+
+ if (!mLastFirstVertex.valid() || mLastFirstVertex.value() != vertexParams.firstVertex())
+ {
+ mLastFirstVertex = vertexParams.firstVertex();
+ mInputLayoutIsDirty = true;
+ }
+
+ if (!mInputLayoutIsDirty)
+ {
+ return gl::NoError();
+ }
+
+ const auto &vertexArrayAttribs = vertexArray11->getTranslatedAttribs();
+ gl::Program *program = state.getProgram();
+
+ // Sort the attributes according to ensure we re-use similar input layouts.
+ AttribIndexArray sortedSemanticIndices;
+ SortAttributesByLayout(program, vertexArrayAttribs, mCurrentValueAttribs,
+ &sortedSemanticIndices, &mCurrentAttributes);
+
+ auto featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel;
+
+ // If we are using FL 9_3, make sure the first attribute is not instanced
+ if (featureLevel <= D3D_FEATURE_LEVEL_9_3 && !mCurrentAttributes.empty())
+ {
+ if (mCurrentAttributes[0]->divisor > 0)
+ {
+ Optional<size_t> firstNonInstancedIndex = FindFirstNonInstanced(mCurrentAttributes);
+ if (firstNonInstancedIndex.valid())
{
- renderTargetWidth = renderTarget->getWidth();
- renderTargetHeight = renderTarget->getHeight();
- renderTargetFormat = renderTarget->getDXGIFormat();
- missingColorRenderTarget = false;
+ size_t index = firstNonInstancedIndex.value();
+ std::swap(mCurrentAttributes[0], mCurrentAttributes[index]);
+ std::swap(sortedSemanticIndices[0], sortedSemanticIndices[index]);
}
+ }
+ }
+
+ // Update the applied input layout by querying the cache.
+ ANGLE_TRY(mInputLayoutCache.updateInputLayout(mRenderer, state, mCurrentAttributes, mode,
+ sortedSemanticIndices, vertexParams));
+
+ // Update the applied vertex buffers.
+ ANGLE_TRY(mInputLayoutCache.applyVertexBuffers(context, mCurrentAttributes, mode,
+ vertexParams.firstVertex(), isIndexedRendering));
+
+ // InputLayoutCache::applyVertexBuffers calls through to the Bufer11 to get the native vertex
+ // buffer (ID3D11Buffer *). Because we allocate these buffers lazily, this will trigger
+ // allocation. This in turn will signal that the buffer is dirty. Since we just resolved the
+ // dirty-ness in VertexArray11::updateDirtyAndDynamicAttribs, this can make us do a needless
+ // update on the second draw call.
+ // Hence we clear the flags here, after we've applied vertex data, since we know everything
+ // is clean. This is a bit of a hack.
+ vertexArray11->clearDirtyAndPromoteDynamicAttribs(context, vertexParams);
+
+ mInputLayoutIsDirty = false;
+ return gl::NoError();
+}
+
+gl::Error StateManager11::applyIndexBuffer(const gl::Context *context,
+ const void *indices,
+ GLsizei count,
+ GLenum type,
+ const gl::HasIndexRange &lazyIndexRange,
+ bool usePrimitiveRestartWorkaround)
+{
+ const auto &glState = context->getGLState();
+ gl::VertexArray *vao = glState.getVertexArray();
+ VertexArray11 *vao11 = GetImplAs<VertexArray11>(vao);
+
+ GLenum destElementType =
+ GetIndexTranslationDestType(type, lazyIndexRange, usePrimitiveRestartWorkaround);
+
+ if (!vao11->updateElementArrayStorage(context, type, destElementType, indices) &&
+ !mIndexBufferIsDirty)
+ {
+ // No streaming or index buffer application necessary.
+ return gl::NoError();
+ }
+
+ gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
+
+ TranslatedIndexData *indexInfo = vao11->getCachedIndexInfo();
+ ANGLE_TRY(mIndexDataManager.prepareIndexData(context, type, destElementType, count,
+ elementArrayBuffer, indices, indexInfo));
+
+ ID3D11Buffer *buffer = nullptr;
+ DXGI_FORMAT bufferFormat =
+ (indexInfo->indexType == GL_UNSIGNED_INT) ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT;
+
+ if (indexInfo->storage)
+ {
+ Buffer11 *storage = GetAs<Buffer11>(indexInfo->storage);
+ ANGLE_TRY_RESULT(storage->getBuffer(context, BUFFER_USAGE_INDEX), buffer);
+ }
+ else
+ {
+ IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(indexInfo->indexBuffer);
+ buffer = indexBuffer->getBuffer().get();
+ }
+
+ // Track dirty indices in the index range cache.
+ indexInfo->srcIndexData.srcIndicesChanged =
+ syncIndexBuffer(buffer, bufferFormat, indexInfo->startOffset);
+
+ mIndexBufferIsDirty = false;
+
+ vao11->setCachedIndexInfoValid();
+ return gl::NoError();
+}
+
+void StateManager11::setIndexBuffer(ID3D11Buffer *buffer,
+ DXGI_FORMAT indexFormat,
+ unsigned int offset)
+{
+ if (syncIndexBuffer(buffer, indexFormat, offset))
+ {
+ mIndexBufferIsDirty = true;
+ }
+}
- // Unbind render target SRVs from the shader here to prevent D3D11 warnings.
- if (colorbuffer->type() == GL_TEXTURE)
+bool StateManager11::syncIndexBuffer(ID3D11Buffer *buffer,
+ DXGI_FORMAT indexFormat,
+ unsigned int offset)
+{
+ if (buffer != mAppliedIB || indexFormat != mAppliedIBFormat || offset != mAppliedIBOffset)
+ {
+ mRenderer->getDeviceContext()->IASetIndexBuffer(buffer, indexFormat, offset);
+
+ mAppliedIB = buffer;
+ mAppliedIBFormat = indexFormat;
+ mAppliedIBOffset = offset;
+ return true;
+ }
+
+ return false;
+}
+
+// Vertex buffer is invalidated outside this function.
+gl::Error StateManager11::updateVertexOffsetsForPointSpritesEmulation(GLint startVertex,
+ GLsizei emulatedInstanceId)
+{
+ return mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation(
+ mRenderer, mCurrentAttributes, startVertex, emulatedInstanceId);
+}
+
+gl::Error StateManager11::generateSwizzle(const gl::Context *context, gl::Texture *texture)
+{
+ if (!texture)
+ {
+ return gl::NoError();
+ }
+
+ TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
+ ASSERT(textureD3D);
+
+ TextureStorage *texStorage = nullptr;
+ ANGLE_TRY(textureD3D->getNativeTexture(context, &texStorage));
+
+ if (texStorage)
+ {
+ TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
+ const gl::TextureState &textureState = texture->getTextureState();
+ ANGLE_TRY(storage11->generateSwizzles(context, textureState.getSwizzleState()));
+ }
+
+ return gl::NoError();
+}
+
+gl::Error StateManager11::generateSwizzlesForShader(const gl::Context *context,
+ gl::SamplerType type)
+{
+ const auto &glState = context->getGLState();
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
+
+ unsigned int samplerRange = programD3D->getUsedSamplerRange(type);
+
+ for (unsigned int i = 0; i < samplerRange; i++)
+ {
+ GLenum textureType = programD3D->getSamplerTextureType(type, i);
+ GLint textureUnit = programD3D->getSamplerMapping(type, i, context->getCaps());
+ if (textureUnit != -1)
+ {
+ gl::Texture *texture = glState.getSamplerTexture(textureUnit, textureType);
+ ASSERT(texture);
+ if (texture->getTextureState().swizzleRequired())
{
- uintptr_t rtResource =
- reinterpret_cast<uintptr_t>(GetViewResource(framebufferRTVs[colorAttachment]));
- const gl::ImageIndex &index = colorbuffer->getTextureImageIndex();
- // The index doesn't need to be corrected for the small compressed texture
- // workaround
- // because a rendertarget is never compressed.
- unsetConflictingSRVs(gl::SAMPLER_VERTEX, rtResource, index);
- unsetConflictingSRVs(gl::SAMPLER_PIXEL, rtResource, index);
+ ANGLE_TRY(generateSwizzle(context, texture));
}
}
}
- // Get the depth stencil buffers
- ID3D11DepthStencilView *framebufferDSV = NULL;
- const gl::FramebufferAttachment *depthStencil = framebuffer->getDepthOrStencilbuffer();
- if (depthStencil)
+ return gl::NoError();
+}
+
+gl::Error StateManager11::generateSwizzles(const gl::Context *context)
+{
+ ANGLE_TRY(generateSwizzlesForShader(context, gl::SAMPLER_VERTEX));
+ ANGLE_TRY(generateSwizzlesForShader(context, gl::SAMPLER_PIXEL));
+ return gl::NoError();
+}
+
+gl::Error StateManager11::applyUniforms(ProgramD3D *programD3D)
+{
+ UniformStorage11 *vertexUniformStorage =
+ GetAs<UniformStorage11>(&programD3D->getVertexUniformStorage());
+ UniformStorage11 *fragmentUniformStorage =
+ GetAs<UniformStorage11>(&programD3D->getFragmentUniformStorage());
+ ASSERT(vertexUniformStorage);
+ ASSERT(fragmentUniformStorage);
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ const d3d11::Buffer *vertexConstantBuffer = nullptr;
+ ANGLE_TRY(vertexUniformStorage->getConstantBuffer(mRenderer, &vertexConstantBuffer));
+ const d3d11::Buffer *pixelConstantBuffer = nullptr;
+ ANGLE_TRY(fragmentUniformStorage->getConstantBuffer(mRenderer, &pixelConstantBuffer));
+
+ if (vertexUniformStorage->size() > 0 && programD3D->areVertexUniformsDirty())
+ {
+ UpdateUniformBuffer(deviceContext, vertexUniformStorage, vertexConstantBuffer);
+ }
+
+ if (fragmentUniformStorage->size() > 0 && programD3D->areFragmentUniformsDirty())
+ {
+ UpdateUniformBuffer(deviceContext, fragmentUniformStorage, pixelConstantBuffer);
+ }
+
+ unsigned int slot = d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK;
+
+ if (mCurrentConstantBufferVS[slot] != vertexConstantBuffer->getSerial())
+ {
+ deviceContext->VSSetConstantBuffers(slot, 1, vertexConstantBuffer->getPointer());
+ mCurrentConstantBufferVS[slot] = vertexConstantBuffer->getSerial();
+ mCurrentConstantBufferVSOffset[slot] = 0;
+ mCurrentConstantBufferVSSize[slot] = 0;
+ }
+
+ if (mCurrentConstantBufferPS[slot] != pixelConstantBuffer->getSerial())
+ {
+ deviceContext->PSSetConstantBuffers(slot, 1, pixelConstantBuffer->getPointer());
+ mCurrentConstantBufferPS[slot] = pixelConstantBuffer->getSerial();
+ mCurrentConstantBufferPSOffset[slot] = 0;
+ mCurrentConstantBufferPSSize[slot] = 0;
+ }
+
+ programD3D->markUniformsClean();
+
+ return gl::NoError();
+}
+
+gl::Error StateManager11::applyDriverUniforms(const ProgramD3D &programD3D)
+{
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ if (!mDriverConstantBufferVS.valid())
+ {
+ size_t requiredSize = mShaderConstants.getRequiredBufferSize(gl::SAMPLER_VERTEX);
+
+ D3D11_BUFFER_DESC constantBufferDescription = {0};
+ d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize);
+ ANGLE_TRY(mRenderer->allocateResource(constantBufferDescription, &mDriverConstantBufferVS));
+
+ ID3D11Buffer *driverVSConstants = mDriverConstantBufferVS.get();
+ deviceContext->VSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
+ &driverVSConstants);
+ }
+
+ if (!mDriverConstantBufferPS.valid())
+ {
+ size_t requiredSize = mShaderConstants.getRequiredBufferSize(gl::SAMPLER_PIXEL);
+
+ D3D11_BUFFER_DESC constantBufferDescription = {0};
+ d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize);
+ ANGLE_TRY(mRenderer->allocateResource(constantBufferDescription, &mDriverConstantBufferPS));
+
+ ID3D11Buffer *driverVSConstants = mDriverConstantBufferPS.get();
+ deviceContext->PSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
+ &driverVSConstants);
+ }
+
+ // Sampler metadata and driver constants need to coexist in the same constant buffer to conserve
+ // constant buffer slots. We update both in the constant buffer if needed.
+ ANGLE_TRY(mShaderConstants.updateBuffer(deviceContext, gl::SAMPLER_VERTEX, programD3D,
+ mDriverConstantBufferVS));
+ ANGLE_TRY(mShaderConstants.updateBuffer(deviceContext, gl::SAMPLER_PIXEL, programD3D,
+ mDriverConstantBufferPS));
+
+ // needed for the point sprite geometry shader
+ // GSSetConstantBuffers triggers device removal on 9_3, so we should only call it for ES3.
+ if (mRenderer->isES3Capable())
{
- RenderTarget11 *depthStencilRenderTarget = NULL;
- gl::Error error = depthStencil->getRenderTarget(&depthStencilRenderTarget);
- if (error.isError())
+ if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS.getSerial())
{
- return error;
+ ASSERT(mDriverConstantBufferPS.valid());
+ deviceContext->GSSetConstantBuffers(0, 1, mDriverConstantBufferPS.getPointer());
+ mCurrentGeometryConstantBuffer = mDriverConstantBufferPS.getSerial();
}
- ASSERT(depthStencilRenderTarget);
+ }
- framebufferDSV = depthStencilRenderTarget->getDepthStencilView();
- ASSERT(framebufferDSV);
+ return gl::NoError();
+}
+
+gl::Error StateManager11::applyComputeUniforms(ProgramD3D *programD3D)
+{
+ UniformStorage11 *computeUniformStorage =
+ GetAs<UniformStorage11>(&programD3D->getComputeUniformStorage());
+ ASSERT(computeUniformStorage);
+
+ const d3d11::Buffer *constantBuffer = nullptr;
+ ANGLE_TRY(computeUniformStorage->getConstantBuffer(mRenderer, &constantBuffer));
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ if (computeUniformStorage->size() > 0 && programD3D->areComputeUniformsDirty())
+ {
+ UpdateUniformBuffer(deviceContext, computeUniformStorage, constantBuffer);
+ programD3D->markUniformsClean();
+ }
+
+ if (mCurrentComputeConstantBuffer != constantBuffer->getSerial())
+ {
+ deviceContext->CSSetConstantBuffers(
+ d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK, 1,
+ constantBuffer->getPointer());
+ mCurrentComputeConstantBuffer = constantBuffer->getSerial();
+ }
+
+ if (!mDriverConstantBufferCS.valid())
+ {
+ size_t requiredSize = mShaderConstants.getRequiredBufferSize(gl::SAMPLER_COMPUTE);
+
+ D3D11_BUFFER_DESC constantBufferDescription = {0};
+ d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize);
+ ANGLE_TRY(mRenderer->allocateResource(constantBufferDescription, &mDriverConstantBufferCS));
+ ID3D11Buffer *buffer = mDriverConstantBufferCS.get();
+ deviceContext->CSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
+ &buffer);
+ }
+
+ ANGLE_TRY(mShaderConstants.updateBuffer(deviceContext, gl::SAMPLER_COMPUTE, *programD3D,
+ mDriverConstantBufferCS));
+
+ return gl::NoError();
+}
+
+gl::Error StateManager11::syncUniformBuffers(const gl::Context *context, ProgramD3D *programD3D)
+{
+ unsigned int reservedVertex = mRenderer->getReservedVertexUniformBuffers();
+ unsigned int reservedFragment = mRenderer->getReservedFragmentUniformBuffers();
+
+ programD3D->updateUniformBufferCache(context->getCaps(), reservedVertex, reservedFragment);
+
+ const auto &vertexUniformBuffers = programD3D->getVertexUniformBufferCache();
+ const auto &fragmentUniformBuffers = programD3D->getFragmentUniformBufferCache();
+ const auto &glState = context->getGLState();
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
+
+ for (size_t bufferIndex = 0; bufferIndex < vertexUniformBuffers.size(); bufferIndex++)
+ {
+ GLint binding = vertexUniformBuffers[bufferIndex];
+
+ if (binding == -1)
+ {
+ continue;
+ }
+
+ const auto &uniformBuffer = glState.getIndexedUniformBuffer(binding);
+ GLintptr uniformBufferOffset = uniformBuffer.getOffset();
+ GLsizeiptr uniformBufferSize = uniformBuffer.getSize();
+
+ if (uniformBuffer.get() == nullptr)
+ {
+ continue;
+ }
+
+ Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer.get());
+ const d3d11::Buffer *constantBuffer = nullptr;
+ UINT firstConstant = 0;
+ UINT numConstants = 0;
+
+ ANGLE_TRY(bufferStorage->getConstantBufferRange(context, uniformBufferOffset,
+ uniformBufferSize, &constantBuffer,
+ &firstConstant, &numConstants));
+
+ ASSERT(constantBuffer);
+
+ if (mCurrentConstantBufferVS[bufferIndex] == constantBuffer->getSerial() &&
+ mCurrentConstantBufferVSOffset[bufferIndex] == uniformBufferOffset &&
+ mCurrentConstantBufferVSSize[bufferIndex] == uniformBufferSize)
+ {
+ continue;
+ }
+
+ unsigned int appliedIndex = reservedVertex + static_cast<unsigned int>(bufferIndex);
+
+ if (firstConstant != 0 && uniformBufferSize != 0)
+ {
+ ASSERT(numConstants != 0);
+ deviceContext1->VSSetConstantBuffers1(appliedIndex, 1, constantBuffer->getPointer(),
+ &firstConstant, &numConstants);
+ }
+ else
+ {
+ deviceContext->VSSetConstantBuffers(appliedIndex, 1, constantBuffer->getPointer());
+ }
+
+ mCurrentConstantBufferVS[appliedIndex] = constantBuffer->getSerial();
+ mCurrentConstantBufferVSOffset[appliedIndex] = uniformBufferOffset;
+ mCurrentConstantBufferVSSize[appliedIndex] = uniformBufferSize;
+ }
+
+ for (size_t bufferIndex = 0; bufferIndex < fragmentUniformBuffers.size(); bufferIndex++)
+ {
+ GLint binding = fragmentUniformBuffers[bufferIndex];
- // If there is no render buffer, the width, height and format values come from
- // the depth stencil
- if (missingColorRenderTarget)
+ if (binding == -1)
{
- renderTargetWidth = depthStencilRenderTarget->getWidth();
- renderTargetHeight = depthStencilRenderTarget->getHeight();
+ continue;
}
- // Unbind render target SRVs from the shader here to prevent D3D11 warnings.
- if (depthStencil->type() == GL_TEXTURE)
+ const auto &uniformBuffer = glState.getIndexedUniformBuffer(binding);
+ GLintptr uniformBufferOffset = uniformBuffer.getOffset();
+ GLsizeiptr uniformBufferSize = uniformBuffer.getSize();
+
+ if (uniformBuffer.get() == nullptr)
{
- uintptr_t depthStencilResource =
- reinterpret_cast<uintptr_t>(GetViewResource(framebufferDSV));
- const gl::ImageIndex &index = depthStencil->getTextureImageIndex();
- // The index doesn't need to be corrected for the small compressed texture workaround
- // because a rendertarget is never compressed.
- unsetConflictingSRVs(gl::SAMPLER_VERTEX, depthStencilResource, index);
- unsetConflictingSRVs(gl::SAMPLER_PIXEL, depthStencilResource, index);
+ continue;
}
+
+ Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer.get());
+ const d3d11::Buffer *constantBuffer = nullptr;
+ UINT firstConstant = 0;
+ UINT numConstants = 0;
+
+ ANGLE_TRY(bufferStorage->getConstantBufferRange(context, uniformBufferOffset,
+ uniformBufferSize, &constantBuffer,
+ &firstConstant, &numConstants));
+
+ ASSERT(constantBuffer);
+
+ if (mCurrentConstantBufferPS[bufferIndex] == constantBuffer->getSerial() &&
+ mCurrentConstantBufferPSOffset[bufferIndex] == uniformBufferOffset &&
+ mCurrentConstantBufferPSSize[bufferIndex] == uniformBufferSize)
+ {
+ continue;
+ }
+
+ unsigned int appliedIndex = reservedFragment + static_cast<unsigned int>(bufferIndex);
+
+ if (firstConstant != 0 && uniformBufferSize != 0)
+ {
+ deviceContext1->PSSetConstantBuffers1(appliedIndex, 1, constantBuffer->getPointer(),
+ &firstConstant, &numConstants);
+ }
+ else
+ {
+ deviceContext->PSSetConstantBuffers(appliedIndex, 1, constantBuffer->getPointer());
+ }
+
+ mCurrentConstantBufferPS[appliedIndex] = constantBuffer->getSerial();
+ mCurrentConstantBufferPSOffset[appliedIndex] = uniformBufferOffset;
+ mCurrentConstantBufferPSSize[appliedIndex] = uniformBufferSize;
}
- if (setRenderTargets(framebufferRTVs, framebufferDSV))
+ return gl::NoError();
+}
+
+gl::Error StateManager11::syncTransformFeedbackBuffers(const gl::Context *context)
+{
+ const auto &glState = context->getGLState();
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ // If transform feedback is not active, unbind all buffers
+ if (!glState.isTransformFeedbackActiveUnpaused())
{
- setViewportBounds(renderTargetWidth, renderTargetHeight);
+ if (mAppliedTFSerial != mEmptySerial)
+ {
+ deviceContext->SOSetTargets(0, nullptr, nullptr);
+ mAppliedTFSerial = mEmptySerial;
+ }
+ return gl::NoError();
}
- gl::Error error = framebuffer11->invalidateSwizzles();
- if (error.isError())
+ gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback();
+ TransformFeedback11 *tf11 = GetImplAs<TransformFeedback11>(transformFeedback);
+ if (mAppliedTFSerial == tf11->getSerial() && !tf11->isDirty())
{
- return error;
+ return gl::NoError();
}
- return gl::Error(GL_NO_ERROR);
+ const std::vector<ID3D11Buffer *> *soBuffers = nullptr;
+ ANGLE_TRY_RESULT(tf11->getSOBuffers(context), soBuffers);
+ const std::vector<UINT> &soOffsets = tf11->getSOBufferOffsets();
+
+ deviceContext->SOSetTargets(tf11->getNumSOBuffers(), soBuffers->data(), soOffsets.data());
+
+ mAppliedTFSerial = tf11->getSerial();
+ tf11->onApply();
+
+ return gl::NoError();
+}
+
+// DrawCallVertexParams implementation.
+DrawCallVertexParams::DrawCallVertexParams(GLint firstVertex,
+ GLsizei vertexCount,
+ GLsizei instances)
+ : mHasIndexRange(nullptr),
+ mFirstVertex(firstVertex),
+ mVertexCount(vertexCount),
+ mInstances(instances),
+ mBaseVertex(0)
+{
+}
+
+// Use when in a drawElements call.
+DrawCallVertexParams::DrawCallVertexParams(bool firstVertexDefinitelyZero,
+ const gl::HasIndexRange &hasIndexRange,
+ GLint baseVertex,
+ GLsizei instances)
+ : mHasIndexRange(&hasIndexRange),
+ mFirstVertex(),
+ mVertexCount(0),
+ mInstances(instances),
+ mBaseVertex(baseVertex)
+{
+ if (firstVertexDefinitelyZero)
+ {
+ mFirstVertex = baseVertex;
+ }
+}
+
+GLint DrawCallVertexParams::firstVertex() const
+{
+ if (!mFirstVertex.valid())
+ {
+ ensureResolved();
+ ASSERT(mFirstVertex.valid());
+ }
+ return mFirstVertex.value();
+}
+
+GLsizei DrawCallVertexParams::vertexCount() const
+{
+ ensureResolved();
+ return mVertexCount;
+}
+
+GLsizei DrawCallVertexParams::instances() const
+{
+ return mInstances;
+}
+
+void DrawCallVertexParams::ensureResolved() const
+{
+ if (mHasIndexRange)
+ {
+ ASSERT(!mFirstVertex.valid() || mFirstVertex == mBaseVertex);
+
+ // Resolve the index range now if we need to.
+ const auto &indexRange = mHasIndexRange->getIndexRange().value();
+ mFirstVertex = mBaseVertex + static_cast<GLint>(indexRange.start);
+ mVertexCount = static_cast<GLsizei>(indexRange.vertexCount());
+ mHasIndexRange = nullptr;
+ }
}
} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
index f900882d7e..e48bc83a22 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
@@ -11,12 +11,15 @@
#include <array>
-#include "libANGLE/angletypes.h"
-#include "libANGLE/Data.h"
+#include "libANGLE/ContextState.h"
#include "libANGLE/State.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h"
+#include "libANGLE/renderer/d3d/d3d11/Query11.h"
#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
-#include "libANGLE/renderer/d3d/RendererD3D.h"
namespace rx
{
@@ -24,20 +27,147 @@ namespace rx
struct RenderTargetDesc;
struct Renderer11DeviceCaps;
-struct dx_VertexConstants11
+class ShaderConstants11 : angle::NonCopyable
{
- float depthRange[4];
- float viewAdjust[4];
- float viewCoords[4];
- float viewScale[4];
+ public:
+ ShaderConstants11();
+ ~ShaderConstants11();
+
+ void init(const gl::Caps &caps);
+ size_t getRequiredBufferSize(gl::SamplerType samplerType) const;
+ void markDirty();
+
+ void setComputeWorkGroups(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ);
+ void setMultiviewWriteToViewportIndex(GLfloat index);
+ void onViewportChange(const gl::Rectangle &glViewport,
+ const D3D11_VIEWPORT &dxViewport,
+ bool is9_3,
+ bool presentPathFast);
+ void onSamplerChange(gl::SamplerType samplerType,
+ unsigned int samplerIndex,
+ const gl::Texture &texture);
+
+ gl::Error updateBuffer(ID3D11DeviceContext *deviceContext,
+ gl::SamplerType samplerType,
+ const ProgramD3D &programD3D,
+ const d3d11::Buffer &driverConstantBuffer);
+
+ private:
+ struct Vertex
+ {
+ Vertex()
+ : depthRange{.0f},
+ viewAdjust{.0f},
+ viewCoords{.0f},
+ viewScale{.0f},
+ multiviewWriteToViewportIndex{.0f},
+ padding{.0f}
+ {
+ }
+
+ float depthRange[4];
+ float viewAdjust[4];
+ float viewCoords[4];
+ float viewScale[2];
+ // multiviewWriteToViewportIndex is used to select either the side-by-side or layered
+ // code-path in the GS. It's value, if set, is either 0.0f or 1.0f. The value is updated
+ // whenever a multi-view draw framebuffer is made active.
+ float multiviewWriteToViewportIndex;
+
+ // Added here to manually pad the struct.
+ float padding;
+ };
+
+ struct Pixel
+ {
+ Pixel()
+ : depthRange{.0f},
+ viewCoords{.0f},
+ depthFront{.0f},
+ viewScale{.0f},
+ multiviewWriteToViewportIndex(0),
+ padding(0)
+ {
+ }
+
+ float depthRange[4];
+ float viewCoords[4];
+ float depthFront[4];
+ float viewScale[2];
+ // multiviewWriteToViewportIndex is used to select either the side-by-side or layered
+ // code-path in the GS. It's value, if set, is either 0.0f or 1.0f. The value is updated
+ // whenever a multi-view draw framebuffer is made active.
+ float multiviewWriteToViewportIndex;
+
+ // Added here to manually pad the struct.
+ float padding;
+ };
+
+ struct Compute
+ {
+ Compute() : numWorkGroups{0u}, padding(0u) {}
+ unsigned int numWorkGroups[3];
+ unsigned int padding; // This just pads the struct to 16 bytes
+ };
+
+ struct SamplerMetadata
+ {
+ SamplerMetadata() : baseLevel(0), internalFormatBits(0), wrapModes(0), padding(0) {}
+
+ int baseLevel;
+ int internalFormatBits;
+ int wrapModes;
+ int padding; // This just pads the struct to 16 bytes
+ };
+
+ static_assert(sizeof(SamplerMetadata) == 16u,
+ "Sampler metadata struct must be one 4-vec / 16 bytes.");
+
+ // Return true if dirty.
+ bool updateSamplerMetadata(SamplerMetadata *data, const gl::Texture &texture);
+
+ Vertex mVertex;
+ bool mVertexDirty;
+ Pixel mPixel;
+ bool mPixelDirty;
+ Compute mCompute;
+ bool mComputeDirty;
+
+ std::vector<SamplerMetadata> mSamplerMetadataVS;
+ bool mSamplerMetadataVSDirty;
+ std::vector<SamplerMetadata> mSamplerMetadataPS;
+ bool mSamplerMetadataPSDirty;
+ std::vector<SamplerMetadata> mSamplerMetadataCS;
+ bool mSamplerMetadataCSDirty;
};
-struct dx_PixelConstants11
+class DrawCallVertexParams final : angle::NonCopyable
{
- float depthRange[4];
- float viewCoords[4];
- float depthFront[4];
- float viewScale[4];
+ public:
+ // Use when in a drawArrays call.
+ DrawCallVertexParams(GLint firstVertex, GLsizei vertexCount, GLsizei instances);
+
+ // Use when in a drawElements call.
+ DrawCallVertexParams(bool firstVertexDefinitelyZero,
+ const gl::HasIndexRange &hasIndexRange,
+ GLint baseVertex,
+ GLsizei instances);
+
+ // It should be possible to also use an overload to handle the 'slow' indirect draw path.
+ // TODO(jmadill): Indirect draw slow path overload.
+
+ GLint firstVertex() const;
+ GLsizei vertexCount() const;
+ GLsizei instances() const;
+
+ private:
+ void ensureResolved() const;
+
+ mutable const gl::HasIndexRange *mHasIndexRange;
+ mutable Optional<GLint> mFirstVertex;
+ mutable GLsizei mVertexCount;
+ GLsizei mInstances;
+ GLint mBaseVertex;
};
class StateManager11 final : angle::NonCopyable
@@ -46,62 +176,221 @@ class StateManager11 final : angle::NonCopyable
StateManager11(Renderer11 *renderer);
~StateManager11();
- void initialize(const gl::Caps &caps);
- void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits);
+ gl::Error initialize(const gl::Caps &caps, const gl::Extensions &extensions);
+ void deinitialize();
- gl::Error setBlendState(const gl::Framebuffer *framebuffer,
- const gl::BlendState &blendState,
- const gl::ColorF &blendColor,
- unsigned int sampleMask);
+ void syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits);
- gl::Error setDepthStencilState(const gl::State &glState);
+ gl::Error updateStateForCompute(const gl::Context *context,
+ GLuint numGroupsX,
+ GLuint numGroupsY,
+ GLuint numGroupsZ);
- gl::Error setRasterizerState(const gl::RasterizerState &rasterState);
+ void updateStencilSizeIfChanged(bool depthStencilInitialized, unsigned int stencilSize);
- void setScissorRectangle(const gl::Rectangle &scissor, bool enabled);
+ // These invalidations methods are called externally.
- void setViewport(const gl::Caps *caps, const gl::Rectangle &viewport, float zNear, float zFar);
+ // Called from TextureStorage11.
+ void invalidateBoundViews();
- void updatePresentPath(bool presentPathFastActive,
- const gl::FramebufferAttachment *framebufferAttachment);
+ // Called from VertexArray11::updateVertexAttribStorage.
+ void invalidateCurrentValueAttrib(size_t attribIndex);
- const dx_VertexConstants11 &getVertexConstants() const { return mVertexConstants; }
- const dx_PixelConstants11 &getPixelConstants() const { return mPixelConstants; }
+ // Checks are done on a framebuffer state change to trigger other state changes.
+ // The Context is allowed to be nullptr for these methods, when called in EGL init code.
+ void invalidateRenderTarget();
- void updateStencilSizeIfChanged(bool depthStencilInitialized, unsigned int stencilSize);
+ // Called by instanced point sprite emulation.
+ void invalidateVertexBuffer();
+
+ // Called by Framebuffer11::syncState for the default sized viewport.
+ void invalidateViewport(const gl::Context *context);
+
+ // Called by TextureStorage11::markLevelDirty.
+ void invalidateSwizzles();
+
+ // Called by the Framebuffer11 and VertexArray11.
+ void invalidateShaders();
+ // Called by VertexArray11 to trigger attribute translation.
+ void invalidateVertexAttributeTranslation();
+
+ void setRenderTarget(ID3D11RenderTargetView *rtv, ID3D11DepthStencilView *dsv);
+ void setRenderTargets(ID3D11RenderTargetView **rtvs, UINT numRtvs, ID3D11DepthStencilView *dsv);
+
+ void onBeginQuery(Query11 *query);
+ void onDeleteQueryObject(Query11 *query);
+ gl::Error onMakeCurrent(const gl::Context *context);
+
+ void setInputLayout(const d3d11::InputLayout *inputLayout);
+
+ // TODO(jmadill): Migrate to d3d11::Buffer.
+ bool queueVertexBufferChange(size_t bufferIndex,
+ ID3D11Buffer *buffer,
+ UINT stride,
+ UINT offset);
+ bool queueVertexOffsetChange(size_t bufferIndex, UINT offsetOnly);
+ void applyVertexBufferChanges();
+
+ void setSingleVertexBuffer(const d3d11::Buffer *buffer, UINT stride, UINT offset);
+
+ gl::Error updateState(const gl::Context *context, GLenum drawMode);
+
+ void setShaderResourceShared(gl::SamplerType shaderType,
+ UINT resourceSlot,
+ const d3d11::SharedSRV *srv);
void setShaderResource(gl::SamplerType shaderType,
UINT resourceSlot,
- ID3D11ShaderResourceView *srv);
+ const d3d11::ShaderResourceView *srv);
+ void setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology);
+
+ void setDrawShaders(const d3d11::VertexShader *vertexShader,
+ const d3d11::GeometryShader *geometryShader,
+ const d3d11::PixelShader *pixelShader);
+ void setVertexShader(const d3d11::VertexShader *shader);
+ void setGeometryShader(const d3d11::GeometryShader *shader);
+ void setPixelShader(const d3d11::PixelShader *shader);
+ void setComputeShader(const d3d11::ComputeShader *shader);
+ void setVertexConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer);
+ void setPixelConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer);
+ void setDepthStencilState(const d3d11::DepthStencilState *depthStencilState, UINT stencilRef);
+ void setSimpleBlendState(const d3d11::BlendState *blendState);
+ void setRasterizerState(const d3d11::RasterizerState *rasterizerState);
+ void setSimpleViewport(const gl::Extents &viewportExtents);
+ void setSimpleViewport(int width, int height);
+ void setSimplePixelTextureAndSampler(const d3d11::SharedSRV &srv,
+ const d3d11::SamplerState &samplerState);
+ void setSimpleScissorRect(const gl::Rectangle &glRect);
+ void setScissorRectD3D(const D3D11_RECT &d3dRect);
+
+ // Not handled by an internal dirty bit because of the extra draw parameters.
+ gl::Error applyVertexBuffer(const gl::Context *context,
+ GLenum mode,
+ const DrawCallVertexParams &vertexParams,
+ bool isIndexedRendering);
+
+ gl::Error applyIndexBuffer(const gl::Context *context,
+ const void *indices,
+ GLsizei count,
+ GLenum type,
+ const gl::HasIndexRange &lazyIndexRange,
+ bool usePrimitiveRestartWorkaround);
+
+ void setIndexBuffer(ID3D11Buffer *buffer, DXGI_FORMAT indexFormat, unsigned int offset);
+
+ gl::Error updateVertexOffsetsForPointSpritesEmulation(GLint startVertex,
+ GLsizei emulatedInstanceId);
+
+ // TODO(jmadill): Should be private.
+ gl::Error applyComputeUniforms(ProgramD3D *programD3D);
+
+ // Only used in testing.
+ InputLayoutCache *getInputLayoutCache() { return &mInputLayoutCache; }
+
+ private:
+ template <typename SRVType>
+ void setShaderResourceInternal(gl::SamplerType shaderType,
+ UINT resourceSlot,
+ const SRVType *srv);
+
+ bool unsetConflictingView(ID3D11View *view);
+ bool unsetConflictingSRVs(gl::SamplerType shaderType,
+ uintptr_t resource,
+ const gl::ImageIndex *index);
+ void unsetConflictingAttachmentResources(const gl::FramebufferAttachment *attachment,
+ ID3D11Resource *resource);
+
+ gl::Error syncBlendState(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::BlendState &blendState,
+ const gl::ColorF &blendColor,
+ unsigned int sampleMask);
+
+ gl::Error syncDepthStencilState(const gl::State &glState);
+
+ gl::Error syncRasterizerState(const gl::Context *context, bool pointDrawMode);
+
+ void syncScissorRectangle(const gl::Rectangle &scissor, bool enabled);
+
+ void syncViewport(const gl::Context *context);
+
+ void checkPresentPath(const gl::Context *context);
+
+ gl::Error syncFramebuffer(const gl::Context *context, gl::Framebuffer *framebuffer);
+ gl::Error syncProgram(const gl::Context *context, GLenum drawMode);
+
+ gl::Error syncTextures(const gl::Context *context);
+ gl::Error applyTextures(const gl::Context *context, gl::SamplerType shaderType);
+
+ gl::Error setSamplerState(const gl::Context *context,
+ gl::SamplerType type,
+ int index,
+ gl::Texture *texture,
+ const gl::SamplerState &sampler);
+ gl::Error setTexture(const gl::Context *context,
+ gl::SamplerType type,
+ int index,
+ gl::Texture *texture);
+
+ // Faster than calling setTexture a jillion times
gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd);
+ void handleMultiviewDrawFramebufferChange(const gl::Context *context);
- gl::Error syncFramebuffer(const gl::Framebuffer *framebuffer);
+ gl::Error syncCurrentValueAttribs(const gl::State &glState);
- void invalidateRenderTarget();
- void invalidateEverything();
- bool setRenderTargets(const RenderTargetArray &renderTargets,
- ID3D11DepthStencilView *depthStencil);
- void setRenderTarget(ID3D11RenderTargetView *renderTarget,
- ID3D11DepthStencilView *depthStencil);
+ gl::Error generateSwizzle(const gl::Context *context, gl::Texture *texture);
+ gl::Error generateSwizzlesForShader(const gl::Context *context, gl::SamplerType type);
+ gl::Error generateSwizzles(const gl::Context *context);
- private:
- void unsetConflictingSRVs(gl::SamplerType shaderType,
- uintptr_t resource,
- const gl::ImageIndex &index);
- void setViewportBounds(const int width, const int height);
+ gl::Error applyDriverUniforms(const ProgramD3D &programD3D);
+ gl::Error applyUniforms(ProgramD3D *programD3D);
+
+ gl::Error syncUniformBuffers(const gl::Context *context, ProgramD3D *programD3D);
+ gl::Error syncTransformFeedbackBuffers(const gl::Context *context);
+
+ // These are currently only called internally.
+ void invalidateTexturesAndSamplers();
+ void invalidateDriverUniforms();
+ void invalidateProgramUniforms();
+ void invalidateProgramUniformBuffers();
+ void invalidateConstantBuffer(unsigned int slot);
+
+ // Called by the Framebuffer11 directly.
+ void processFramebufferInvalidation(const gl::Context *context);
+
+ bool syncIndexBuffer(ID3D11Buffer *buffer, DXGI_FORMAT indexFormat, unsigned int offset);
+
+ enum DirtyBitType
+ {
+ DIRTY_BIT_RENDER_TARGET,
+ DIRTY_BIT_VIEWPORT_STATE,
+ DIRTY_BIT_SCISSOR_STATE,
+ DIRTY_BIT_RASTERIZER_STATE,
+ DIRTY_BIT_BLEND_STATE,
+ DIRTY_BIT_DEPTH_STENCIL_STATE,
+ DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE,
+ DIRTY_BIT_PROGRAM_UNIFORMS,
+ DIRTY_BIT_DRIVER_UNIFORMS,
+ DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS,
+ DIRTY_BIT_SHADERS,
+ DIRTY_BIT_CURRENT_VALUE_ATTRIBS,
+ DIRTY_BIT_INVALID,
+ DIRTY_BIT_MAX = DIRTY_BIT_INVALID,
+ };
+
+ using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
Renderer11 *mRenderer;
+ // Internal dirty bits.
+ DirtyBits mInternalDirtyBits;
+
// Blend State
- bool mBlendStateIsDirty;
- // TODO(dianx) temporary representation of a dirty bit. once we move enough states in,
- // try experimenting with dirty bit instead of a bool
gl::BlendState mCurBlendState;
gl::ColorF mCurBlendColor;
unsigned int mCurSampleMask;
// Currently applied depth stencil state
- bool mDepthStencilStateIsDirty;
gl::DepthStencilState mCurDepthStencilState;
int mCurStencilRef;
int mCurStencilBackRef;
@@ -110,34 +399,35 @@ class StateManager11 final : angle::NonCopyable
Optional<bool> mCurDisableStencil;
// Currently applied rasterizer state
- bool mRasterizerStateIsDirty;
gl::RasterizerState mCurRasterState;
// Currently applied scissor rectangle state
- bool mScissorStateIsDirty;
bool mCurScissorEnabled;
gl::Rectangle mCurScissorRect;
// Currently applied viewport state
- bool mViewportStateIsDirty;
gl::Rectangle mCurViewport;
float mCurNear;
float mCurFar;
+ // The viewport offsets are guaranteed to be updated whenever the gl::State::DirtyBits are
+ // resolved and can be applied to the viewport and scissor whenever the internal viewport and
+ // scissor bits are resolved.
+ std::vector<gl::Offset> mViewportOffsets;
+
// Things needed in viewport state
- dx_VertexConstants11 mVertexConstants;
- dx_PixelConstants11 mPixelConstants;
+ ShaderConstants11 mShaderConstants;
// Render target variables
gl::Extents mViewportBounds;
+ bool mRenderTargetIsDirty;
// EGL_ANGLE_experimental_present_path variables
bool mCurPresentPathFastEnabled;
int mCurPresentPathFastColorBufferHeight;
- // Current RenderTarget state
- std::array<uintptr_t, gl::IMPLEMENTATION_MAX_DRAW_BUFFERS> mAppliedRTVs;
- uintptr_t mAppliedDSV;
+ // Queries that are currently active in this state
+ std::set<Query11 *> mCurrentQueries;
// Currently applied textures
struct SRVRecord
@@ -154,7 +444,8 @@ class StateManager11 final : angle::NonCopyable
class SRVCache : angle::NonCopyable
{
public:
- SRVCache() : mHighestUsedSRV(0) {}
+ SRVCache();
+ ~SRVCache();
void initialize(size_t size) { mCurrentSRVs.resize(size); }
@@ -175,6 +466,91 @@ class StateManager11 final : angle::NonCopyable
// A block of NULL pointers, cached so we don't re-allocate every draw call
std::vector<ID3D11ShaderResourceView *> mNullSRVs;
+
+ // Current translations of "Current-Value" data - owned by Context, not VertexArray.
+ gl::AttributesMask mDirtyCurrentValueAttribs;
+ std::vector<TranslatedAttribute> mCurrentValueAttribs;
+
+ // Current applied input layout.
+ ResourceSerial mCurrentInputLayout;
+ bool mInputLayoutIsDirty;
+ bool mVertexAttribsNeedTranslation;
+
+ // Current applied vertex states.
+ // TODO(jmadill): Figure out how to use ResourceSerial here.
+ std::array<ID3D11Buffer *, gl::MAX_VERTEX_ATTRIBS> mCurrentVertexBuffers;
+ std::array<UINT, gl::MAX_VERTEX_ATTRIBS> mCurrentVertexStrides;
+ std::array<UINT, gl::MAX_VERTEX_ATTRIBS> mCurrentVertexOffsets;
+ gl::RangeUI mDirtyVertexBufferRange;
+
+ // Currently applied primitive topology
+ D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology;
+
+ // Currently applied shaders
+ ResourceSerial mAppliedVertexShader;
+ ResourceSerial mAppliedGeometryShader;
+ ResourceSerial mAppliedPixelShader;
+ ResourceSerial mAppliedComputeShader;
+
+ // Currently applied sampler states
+ std::vector<bool> mForceSetVertexSamplerStates;
+ std::vector<gl::SamplerState> mCurVertexSamplerStates;
+
+ std::vector<bool> mForceSetPixelSamplerStates;
+ std::vector<gl::SamplerState> mCurPixelSamplerStates;
+
+ std::vector<bool> mForceSetComputeSamplerStates;
+ std::vector<gl::SamplerState> mCurComputeSamplerStates;
+
+ // Special dirty bit for swizzles. Since they use internal shaders, must be done in a pre-pass.
+ bool mDirtySwizzles;
+
+ // Currently applied index buffer
+ ID3D11Buffer *mAppliedIB;
+ DXGI_FORMAT mAppliedIBFormat;
+ unsigned int mAppliedIBOffset;
+ bool mIndexBufferIsDirty;
+
+ // Vertex, index and input layouts
+ VertexDataManager mVertexDataManager;
+ IndexDataManager mIndexDataManager;
+ InputLayoutCache mInputLayoutCache;
+ std::vector<const TranslatedAttribute *> mCurrentAttributes;
+ Optional<GLint> mLastFirstVertex;
+
+ // ANGLE_multiview.
+ bool mIsMultiviewEnabled;
+
+ // Driver Constants.
+ d3d11::Buffer mDriverConstantBufferVS;
+ d3d11::Buffer mDriverConstantBufferPS;
+ d3d11::Buffer mDriverConstantBufferCS;
+
+ ResourceSerial mCurrentComputeConstantBuffer;
+ ResourceSerial mCurrentGeometryConstantBuffer;
+
+ template <typename T>
+ using VertexConstantBufferArray =
+ std::array<T, gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS>;
+
+ VertexConstantBufferArray<ResourceSerial> mCurrentConstantBufferVS;
+ VertexConstantBufferArray<GLintptr> mCurrentConstantBufferVSOffset;
+ VertexConstantBufferArray<GLsizeiptr> mCurrentConstantBufferVSSize;
+
+ template <typename T>
+ using FragmentConstantBufferArray =
+ std::array<T, gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS>;
+
+ FragmentConstantBufferArray<ResourceSerial> mCurrentConstantBufferPS;
+ FragmentConstantBufferArray<GLintptr> mCurrentConstantBufferPSOffset;
+ FragmentConstantBufferArray<GLsizeiptr> mCurrentConstantBufferPSSize;
+
+ // Currently applied transform feedback buffers
+ Serial mAppliedTFSerial;
+
+ Serial mEmptySerial;
+
+ bool mIsTransformFeedbackCurrentlyActiveUnpaused;
};
} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.cpp
new file mode 100644
index 0000000000..1981b5f7b2
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.cpp
@@ -0,0 +1,102 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// StreamProducerNV12.cpp: Implements the stream producer for NV12 textures
+
+#include "libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h"
+
+#include "common/utilities.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace rx
+{
+
+StreamProducerNV12::StreamProducerNV12(Renderer11 *renderer)
+ : mRenderer(renderer), mTexture(nullptr), mArraySlice(0), mTextureWidth(0), mTextureHeight(0)
+{
+}
+
+StreamProducerNV12::~StreamProducerNV12()
+{
+ SafeRelease(mTexture);
+}
+
+egl::Error StreamProducerNV12::validateD3DNV12Texture(void *pointer) const
+{
+ ID3D11Texture2D *textureD3D = static_cast<ID3D11Texture2D *>(pointer);
+
+ // Check that the texture originated from our device
+ ID3D11Device *device;
+ textureD3D->GetDevice(&device);
+ if (device != mRenderer->getDevice())
+ {
+ return egl::EglBadParameter() << "Texture not created on ANGLE D3D device";
+ }
+
+ // Get the description and validate it
+ D3D11_TEXTURE2D_DESC desc;
+ textureD3D->GetDesc(&desc);
+ if (desc.Format != DXGI_FORMAT_NV12)
+ {
+ return egl::EglBadParameter() << "Texture format not DXGI_FORMAT_NV12";
+ }
+ if (desc.Width < 1 || desc.Height < 1)
+ {
+ return egl::EglBadParameter() << "Texture is of size 0";
+ }
+ if ((desc.Width % 2) != 0 || (desc.Height % 2) != 0)
+ {
+ return egl::EglBadParameter() << "Texture dimensions are not even";
+ }
+ return egl::NoError();
+}
+
+void StreamProducerNV12::postD3DNV12Texture(void *pointer, const egl::AttributeMap &attributes)
+{
+ ASSERT(pointer != nullptr);
+ ID3D11Texture2D *textureD3D = static_cast<ID3D11Texture2D *>(pointer);
+
+ // Check that the texture originated from our device
+ ID3D11Device *device;
+ textureD3D->GetDevice(&device);
+
+ // Get the description
+ D3D11_TEXTURE2D_DESC desc;
+ textureD3D->GetDesc(&desc);
+
+ // Release the previous texture if there is one
+ SafeRelease(mTexture);
+
+ mTexture = textureD3D;
+ mTexture->AddRef();
+ mTextureWidth = desc.Width;
+ mTextureHeight = desc.Height;
+ mArraySlice = static_cast<UINT>(attributes.get(EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE, 0));
+}
+
+egl::Stream::GLTextureDescription StreamProducerNV12::getGLFrameDescription(int planeIndex)
+{
+ // The UV plane of NV12 textures has half the width/height of the Y plane
+ egl::Stream::GLTextureDescription desc;
+ desc.width = (planeIndex == 0) ? mTextureWidth : (mTextureWidth / 2);
+ desc.height = (planeIndex == 0) ? mTextureHeight : (mTextureHeight / 2);
+ desc.internalFormat = (planeIndex == 0) ? GL_R8 : GL_RG8;
+ desc.mipLevels = 0;
+ return desc;
+}
+
+ID3D11Texture2D *StreamProducerNV12::getD3DTexture()
+{
+ return mTexture;
+}
+
+UINT StreamProducerNV12::getArraySlice()
+{
+ return mArraySlice;
+}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h
new file mode 100644
index 0000000000..304c9dfe53
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h
@@ -0,0 +1,44 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// StreamProducerNV12.h: Interface for a NV12 texture stream producer
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_STREAM11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_STREAM11_H_
+
+#include "libANGLE/renderer/StreamProducerImpl.h"
+
+namespace rx
+{
+class Renderer11;
+
+class StreamProducerNV12 : public StreamProducerImpl
+{
+ public:
+ StreamProducerNV12(Renderer11 *renderer);
+ ~StreamProducerNV12() override;
+
+ egl::Error validateD3DNV12Texture(void *pointer) const override;
+ void postD3DNV12Texture(void *pointer, const egl::AttributeMap &attributes) override;
+ egl::Stream::GLTextureDescription getGLFrameDescription(int planeIndex) override;
+
+ // Gets a pointer to the internal D3D texture
+ ID3D11Texture2D *getD3DTexture();
+
+ // Gets the slice index for the D3D texture that the frame is in
+ UINT getArraySlice();
+
+ private:
+ Renderer11 *mRenderer;
+
+ ID3D11Texture2D *mTexture;
+ UINT mArraySlice;
+ UINT mTextureWidth;
+ UINT mTextureHeight;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_STREAM11_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
index 42c336c8cf..dcfd06484d 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
@@ -11,9 +11,9 @@
#include <EGL/eglext.h>
#include "libANGLE/features.h"
-#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
-#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h"
+#include "libANGLE/renderer/d3d/d3d11/NativeWindow11.h"
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
#include "third_party/trace_event/trace_event.h"
@@ -21,6 +21,7 @@
// Precompiled shaders
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h"
#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dms11ps.h"
#ifdef ANGLE_ENABLE_KEYEDMUTEX
#define ANGLE_RESOURCE_SHARE_TYPE D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX
@@ -33,22 +34,30 @@ namespace rx
namespace
{
-bool NeedsOffscreenTexture(Renderer11 *renderer, NativeWindow nativeWindow, EGLint orientation)
+// To avoid overflow in QPC to Microseconds calculations, since we multiply
+// by kMicrosecondsPerSecond, then the QPC value should not exceed
+// (2^63 - 1) / 1E6. If it exceeds that threshold, we divide then multiply.
+static constexpr int64_t kQPCOverflowThreshold = 0x8637BD05AF7;
+static constexpr int64_t kMicrosecondsPerSecond = 1000000;
+
+bool NeedsOffscreenTexture(Renderer11 *renderer, NativeWindow11 *nativeWindow, EGLint orientation)
{
// We don't need an offscreen texture if either orientation = INVERT_Y,
// or present path fast is enabled and we're not rendering onto an offscreen surface.
return orientation != EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE &&
- !(renderer->presentPathFastEnabled() && nativeWindow.getNativeWindow());
+ !(renderer->presentPathFastEnabled() && nativeWindow->getNativeWindow());
}
} // anonymous namespace
SwapChain11::SwapChain11(Renderer11 *renderer,
- NativeWindow nativeWindow,
+ NativeWindow11 *nativeWindow,
HANDLE shareHandle,
+ IUnknown *d3dTexture,
GLenum backBufferFormat,
GLenum depthBufferFormat,
- EGLint orientation)
- : SwapChainD3D(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat),
+ EGLint orientation,
+ EGLint samples)
+ : SwapChainD3D(shareHandle, d3dTexture, backBufferFormat, depthBufferFormat),
mRenderer(renderer),
mWidth(-1),
mHeight(-1),
@@ -56,33 +65,42 @@ SwapChain11::SwapChain11(Renderer11 *renderer,
mAppCreatedShareHandle(mShareHandle != nullptr),
mSwapInterval(0),
mPassThroughResourcesInit(false),
+ mNativeWindow(nativeWindow),
mFirstSwap(true),
mSwapChain(nullptr),
-#if defined(ANGLE_ENABLE_D3D11_1)
mSwapChain1(nullptr),
-#endif
mKeyedMutex(nullptr),
- mBackBufferTexture(nullptr),
- mBackBufferRTView(nullptr),
- mBackBufferSRView(nullptr),
+ mBackBufferTexture(),
+ mBackBufferRTView(),
+ mBackBufferSRView(),
mNeedsOffscreenTexture(NeedsOffscreenTexture(renderer, nativeWindow, orientation)),
- mOffscreenTexture(nullptr),
- mOffscreenRTView(nullptr),
- mOffscreenSRView(nullptr),
- mDepthStencilTexture(nullptr),
- mDepthStencilDSView(nullptr),
- mDepthStencilSRView(nullptr),
- mQuadVB(nullptr),
- mPassThroughSampler(nullptr),
- mPassThroughIL(nullptr),
- mPassThroughVS(nullptr),
- mPassThroughPS(nullptr),
- mPassThroughRS(nullptr),
+ mOffscreenTexture(),
+ mOffscreenRTView(),
+ mOffscreenSRView(),
+ mNeedsOffscreenTextureCopy(false),
+ mOffscreenTextureCopyForSRV(),
+ mDepthStencilTexture(),
+ mDepthStencilDSView(),
+ mDepthStencilSRView(),
+ mQuadVB(),
+ mPassThroughSampler(),
+ mPassThroughIL(),
+ mPassThroughVS(),
+ mPassThroughPS(),
+ mPassThroughRS(),
mColorRenderTarget(this, renderer, false),
- mDepthStencilRenderTarget(this, renderer, true)
+ mDepthStencilRenderTarget(this, renderer, true),
+ mEGLSamples(samples)
{
// Sanity check that if present path fast is active then we're using the default orientation
ASSERT(!mRenderer->presentPathFastEnabled() || orientation == 0);
+
+ // Get the performance counter
+ LARGE_INTEGER counterFreqency = {};
+ BOOL success = QueryPerformanceFrequency(&counterFreqency);
+ ASSERT(success);
+
+ mQPCFrequency = counterFreqency.QuadPart;
}
SwapChain11::~SwapChain11()
@@ -92,52 +110,56 @@ SwapChain11::~SwapChain11()
void SwapChain11::release()
{
-#if defined(ANGLE_ENABLE_D3D11_1)
+ // TODO(jmadill): Should probably signal that the RenderTarget is dirty.
+
SafeRelease(mSwapChain1);
-#endif
SafeRelease(mSwapChain);
SafeRelease(mKeyedMutex);
- SafeRelease(mBackBufferTexture);
- SafeRelease(mBackBufferRTView);
- SafeRelease(mBackBufferSRView);
- SafeRelease(mOffscreenTexture);
- SafeRelease(mOffscreenRTView);
- SafeRelease(mOffscreenSRView);
- SafeRelease(mDepthStencilTexture);
- SafeRelease(mDepthStencilDSView);
- SafeRelease(mDepthStencilSRView);
- SafeRelease(mQuadVB);
- SafeRelease(mPassThroughSampler);
- SafeRelease(mPassThroughIL);
- SafeRelease(mPassThroughVS);
- SafeRelease(mPassThroughPS);
- SafeRelease(mPassThroughRS);
+ mBackBufferTexture.reset();
+ mBackBufferRTView.reset();
+ mBackBufferSRView.reset();
+ mOffscreenTexture.reset();
+ mOffscreenRTView.reset();
+ mOffscreenSRView.reset();
+ mDepthStencilTexture.reset();
+ mDepthStencilDSView.reset();
+ mDepthStencilSRView.reset();
+ mQuadVB.reset();
+ mPassThroughSampler.reset();
+ mPassThroughIL.reset();
+ mPassThroughVS.reset();
+ mPassThroughPS.reset();
+ mPassThroughRS.reset();
if (!mAppCreatedShareHandle)
{
- mShareHandle = NULL;
+ mShareHandle = nullptr;
}
}
void SwapChain11::releaseOffscreenColorBuffer()
{
- SafeRelease(mOffscreenTexture);
- SafeRelease(mOffscreenRTView);
- SafeRelease(mOffscreenSRView);
+ mOffscreenTexture.reset();
+ mOffscreenRTView.reset();
+ mOffscreenSRView.reset();
+ mNeedsOffscreenTextureCopy = false;
+ mOffscreenTextureCopyForSRV.reset();
}
void SwapChain11::releaseOffscreenDepthBuffer()
{
- SafeRelease(mDepthStencilTexture);
- SafeRelease(mDepthStencilDSView);
- SafeRelease(mDepthStencilSRView);
+ mDepthStencilTexture.reset();
+ mDepthStencilDSView.reset();
+ mDepthStencilSRView.reset();
}
-EGLint SwapChain11::resetOffscreenBuffers(int backbufferWidth, int backbufferHeight)
+EGLint SwapChain11::resetOffscreenBuffers(const gl::Context *context,
+ int backbufferWidth,
+ int backbufferHeight)
{
if (mNeedsOffscreenTexture)
{
- EGLint result = resetOffscreenColorBuffer(backbufferWidth, backbufferHeight);
+ EGLint result = resetOffscreenColorBuffer(context, backbufferWidth, backbufferHeight);
if (result != EGL_SUCCESS)
{
return result;
@@ -156,117 +178,106 @@ EGLint SwapChain11::resetOffscreenBuffers(int backbufferWidth, int backbufferHei
return EGL_SUCCESS;
}
-EGLint SwapChain11::resetOffscreenColorBuffer(int backbufferWidth, int backbufferHeight)
+EGLint SwapChain11::resetOffscreenColorBuffer(const gl::Context *context,
+ int backbufferWidth,
+ int backbufferHeight)
{
ASSERT(mNeedsOffscreenTexture);
TRACE_EVENT0("gpu.angle", "SwapChain11::resetOffscreenTexture");
ID3D11Device *device = mRenderer->getDevice();
- ASSERT(device != NULL);
+ ASSERT(device != nullptr);
// D3D11 does not allow zero size textures
ASSERT(backbufferWidth >= 1);
ASSERT(backbufferHeight >= 1);
// Preserve the render target content
- ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture;
- if (previousOffscreenTexture)
- {
- previousOffscreenTexture->AddRef();
- }
+ TextureHelper11 previousOffscreenTexture(std::move(mOffscreenTexture));
const int previousWidth = mWidth;
const int previousHeight = mHeight;
releaseOffscreenColorBuffer();
- const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps());
+ const d3d11::Format &backbufferFormatInfo =
+ d3d11::Format::Get(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps());
+ D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
- // If the app passed in a share handle, open the resource
- // See EGL_ANGLE_d3d_share_handle_client_buffer
- if (mAppCreatedShareHandle)
+ // If the app passed in a share handle or D3D texture, open the resource
+ // See EGL_ANGLE_d3d_share_handle_client_buffer and EGL_ANGLE_d3d_texture_client_buffer
+ if (mAppCreatedShareHandle || mD3DTexture != nullptr)
{
- ID3D11Resource *tempResource11;
- HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11);
+ if (mAppCreatedShareHandle)
+ {
+ ID3D11Resource *tempResource11;
+ HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource),
+ (void **)&tempResource11);
+ ASSERT(SUCCEEDED(result));
- if (FAILED(result))
+ mOffscreenTexture.set(d3d11::DynamicCastComObject<ID3D11Texture2D>(tempResource11),
+ backbufferFormatInfo);
+ SafeRelease(tempResource11);
+ }
+ else if (mD3DTexture != nullptr)
{
- ERR("Failed to open the swap chain pbuffer share handle: %08lX", result);
- release();
- return EGL_BAD_PARAMETER;
+ mOffscreenTexture.set(d3d11::DynamicCastComObject<ID3D11Texture2D>(mD3DTexture),
+ backbufferFormatInfo);
}
-
- result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture);
- SafeRelease(tempResource11);
-
- if (FAILED(result))
+ else
{
- ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result);
- release();
- return EGL_BAD_PARAMETER;
+ UNREACHABLE();
}
+ ASSERT(mOffscreenTexture.valid());
+ mOffscreenTexture.getDesc(&offscreenTextureDesc);
- // Validate offscreen texture parameters
- D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
- mOffscreenTexture->GetDesc(&offscreenTextureDesc);
-
- if (offscreenTextureDesc.Width != (UINT)backbufferWidth ||
- offscreenTextureDesc.Height != (UINT)backbufferHeight ||
- offscreenTextureDesc.Format != backbufferFormatInfo.texFormat ||
- offscreenTextureDesc.MipLevels != 1 ||
- offscreenTextureDesc.ArraySize != 1)
+ // Fail if the offscreen texture is not renderable.
+ if ((offscreenTextureDesc.BindFlags & D3D11_BIND_RENDER_TARGET) == 0)
{
- ERR("Invalid texture parameters in the shared offscreen texture pbuffer");
+ ERR() << "Could not use provided offscreen texture, texture not renderable.";
release();
- return EGL_BAD_PARAMETER;
+ return EGL_BAD_SURFACE;
}
}
else
{
- const bool useSharedResource = !mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport();
+ const bool useSharedResource =
+ !mNativeWindow->getNativeWindow() && mRenderer->getShareHandleSupport();
- D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
offscreenTextureDesc.Width = backbufferWidth;
offscreenTextureDesc.Height = backbufferHeight;
- offscreenTextureDesc.Format = backbufferFormatInfo.texFormat;
+ offscreenTextureDesc.Format = backbufferFormatInfo.texFormat;
offscreenTextureDesc.MipLevels = 1;
offscreenTextureDesc.ArraySize = 1;
- offscreenTextureDesc.SampleDesc.Count = 1;
+ offscreenTextureDesc.SampleDesc.Count = getD3DSamples();
offscreenTextureDesc.SampleDesc.Quality = 0;
offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT;
offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
offscreenTextureDesc.CPUAccessFlags = 0;
offscreenTextureDesc.MiscFlags = useSharedResource ? ANGLE_RESOURCE_SHARE_TYPE : 0;
- HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture);
-
- if (FAILED(result))
+ gl::Error err = mRenderer->allocateTexture(offscreenTextureDesc, backbufferFormatInfo,
+ &mOffscreenTexture);
+ if (err.isError())
{
- ERR("Could not create offscreen texture: %08lX", result);
+ ERR() << "Could not create offscreen texture, " << err;
release();
-
- if (d3d11::isDeviceLostError(result))
- {
- return EGL_CONTEXT_LOST;
- }
- else
- {
- return EGL_BAD_ALLOC;
- }
+ return EGL_BAD_ALLOC;
}
- d3d11::SetDebugName(mOffscreenTexture, "Offscreen back buffer texture");
+ mOffscreenTexture.setDebugName("Offscreen back buffer texture");
// EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client
if (useSharedResource)
{
- IDXGIResource *offscreenTextureResource = NULL;
- result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource);
+ IDXGIResource *offscreenTextureResource = nullptr;
+ HRESULT result = mOffscreenTexture.get()->QueryInterface(
+ __uuidof(IDXGIResource), (void **)&offscreenTextureResource);
// Fall back to no share handle on failure
if (FAILED(result))
{
- ERR("Could not query offscreen texture resource: %08lX", result);
+ ERR() << "Could not query offscreen texture resource, " << gl::FmtHR(result);
}
else
{
@@ -275,36 +286,49 @@ EGLint SwapChain11::resetOffscreenColorBuffer(int backbufferWidth, int backbuffe
if (FAILED(result))
{
- mShareHandle = NULL;
- ERR("Could not get offscreen texture shared handle: %08lX", result);
+ mShareHandle = nullptr;
+ ERR() << "Could not get offscreen texture shared handle, " << gl::FmtHR(result);
}
}
}
}
// This may return null if the original texture was created without a keyed mutex.
- mKeyedMutex = d3d11::DynamicCastComObject<IDXGIKeyedMutex>(mOffscreenTexture);
+ mKeyedMutex = d3d11::DynamicCastComObject<IDXGIKeyedMutex>(mOffscreenTexture.get());
D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc;
- offscreenRTVDesc.Format = backbufferFormatInfo.rtvFormat;
- offscreenRTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ offscreenRTVDesc.Format = backbufferFormatInfo.rtvFormat;
+ offscreenRTVDesc.ViewDimension =
+ (mEGLSamples <= 1) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS;
offscreenRTVDesc.Texture2D.MipSlice = 0;
- HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, &offscreenRTVDesc, &mOffscreenRTView);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mOffscreenRTView, "Offscreen back buffer render target");
+ gl::Error err =
+ mRenderer->allocateResource(offscreenRTVDesc, mOffscreenTexture.get(), &mOffscreenRTView);
+ ASSERT(!err.isError());
+ mOffscreenRTView.setDebugName("Offscreen back buffer render target");
D3D11_SHADER_RESOURCE_VIEW_DESC offscreenSRVDesc;
- offscreenSRVDesc.Format = backbufferFormatInfo.srvFormat;
- offscreenSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ offscreenSRVDesc.Format = backbufferFormatInfo.srvFormat;
+ offscreenSRVDesc.ViewDimension =
+ (mEGLSamples <= 1) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS;
offscreenSRVDesc.Texture2D.MostDetailedMip = 0;
offscreenSRVDesc.Texture2D.MipLevels = static_cast<UINT>(-1);
- result = device->CreateShaderResourceView(mOffscreenTexture, &offscreenSRVDesc, &mOffscreenSRView);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mOffscreenSRView, "Offscreen back buffer shader resource");
+ if (offscreenTextureDesc.BindFlags & D3D11_BIND_SHADER_RESOURCE)
+ {
+ err = mRenderer->allocateResource(offscreenSRVDesc, mOffscreenTexture.get(),
+ &mOffscreenSRView);
+ ASSERT(!err.isError());
+ mOffscreenSRView.setDebugName("Offscreen back buffer shader resource");
+ }
+ else
+ {
+ // Special case for external textures that cannot support sampling. Since internally we
+ // assume our SwapChain is always readable, we make a copy texture that is compatible.
+ mNeedsOffscreenTextureCopy = true;
+ }
- if (previousOffscreenTexture != nullptr)
+ if (previousOffscreenTexture.valid())
{
D3D11_BOX sourceBox = {0};
sourceBox.left = 0;
@@ -316,14 +340,12 @@ EGLint SwapChain11::resetOffscreenColorBuffer(int backbufferWidth, int backbuffe
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
const int yoffset = std::max(backbufferHeight - previousHeight, 0);
- deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0,
- previousOffscreenTexture, 0, &sourceBox);
-
- SafeRelease(previousOffscreenTexture);
+ deviceContext->CopySubresourceRegion(mOffscreenTexture.get(), 0, 0, yoffset, 0,
+ previousOffscreenTexture.get(), 0, &sourceBox);
if (mSwapChain)
{
- swapRect(0, 0, backbufferWidth, backbufferHeight);
+ swapRect(context, 0, 0, backbufferWidth, backbufferHeight);
}
}
@@ -336,21 +358,38 @@ EGLint SwapChain11::resetOffscreenDepthBuffer(int backbufferWidth, int backbuffe
if (mDepthBufferFormat != GL_NONE)
{
- const d3d11::TextureFormat &depthBufferFormatInfo =
- d3d11::GetTextureFormatInfo(mDepthBufferFormat, mRenderer->getRenderer11DeviceCaps());
+ const d3d11::Format &depthBufferFormatInfo =
+ d3d11::Format::Get(mDepthBufferFormat, mRenderer->getRenderer11DeviceCaps());
D3D11_TEXTURE2D_DESC depthStencilTextureDesc;
depthStencilTextureDesc.Width = backbufferWidth;
depthStencilTextureDesc.Height = backbufferHeight;
- depthStencilTextureDesc.Format = depthBufferFormatInfo.texFormat;
+ depthStencilTextureDesc.Format = depthBufferFormatInfo.texFormat;
depthStencilTextureDesc.MipLevels = 1;
depthStencilTextureDesc.ArraySize = 1;
- depthStencilTextureDesc.SampleDesc.Count = 1;
- depthStencilTextureDesc.SampleDesc.Quality = 0;
+ depthStencilTextureDesc.SampleDesc.Count = getD3DSamples();
depthStencilTextureDesc.Usage = D3D11_USAGE_DEFAULT;
depthStencilTextureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
- if (depthBufferFormatInfo.srvFormat != DXGI_FORMAT_UNKNOWN)
+ // If there is a multisampled offscreen color texture, the offscreen depth-stencil texture
+ // must also have the same quality value.
+ if (mOffscreenTexture.valid() && getD3DSamples() > 1)
+ {
+ D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
+ mOffscreenTexture.getDesc(&offscreenTextureDesc);
+ depthStencilTextureDesc.SampleDesc.Quality = offscreenTextureDesc.SampleDesc.Quality;
+ }
+ else
+ {
+ depthStencilTextureDesc.SampleDesc.Quality = 0;
+ }
+
+ // Only create an SRV if it is supported
+ bool depthStencilSRV =
+ depthBufferFormatInfo.srvFormat != DXGI_FORMAT_UNKNOWN &&
+ (mRenderer->getRenderer11DeviceCaps().supportsMultisampledDepthStencilSRVs ||
+ depthStencilTextureDesc.SampleDesc.Count <= 1);
+ if (depthStencilSRV)
{
depthStencilTextureDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
}
@@ -358,58 +397,56 @@ EGLint SwapChain11::resetOffscreenDepthBuffer(int backbufferWidth, int backbuffe
depthStencilTextureDesc.CPUAccessFlags = 0;
depthStencilTextureDesc.MiscFlags = 0;
- ID3D11Device *device = mRenderer->getDevice();
- HRESULT result =
- device->CreateTexture2D(&depthStencilTextureDesc, NULL, &mDepthStencilTexture);
- if (FAILED(result))
+ gl::Error err = mRenderer->allocateTexture(depthStencilTextureDesc, depthBufferFormatInfo,
+ &mDepthStencilTexture);
+ if (err.isError())
{
- ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
+ ERR() << "Could not create depthstencil surface for new swap chain, " << err;
release();
-
- if (d3d11::isDeviceLostError(result))
- {
- return EGL_CONTEXT_LOST;
- }
- else
- {
- return EGL_BAD_ALLOC;
- }
+ return EGL_BAD_ALLOC;
}
- d3d11::SetDebugName(mDepthStencilTexture, "Offscreen depth stencil texture");
+ mDepthStencilTexture.setDebugName("Offscreen depth stencil texture");
D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilDesc;
- depthStencilDesc.Format = depthBufferFormatInfo.dsvFormat;
- depthStencilDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+ depthStencilDesc.Format = depthBufferFormatInfo.dsvFormat;
+ depthStencilDesc.ViewDimension =
+ (mEGLSamples <= 1) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS;
depthStencilDesc.Flags = 0;
depthStencilDesc.Texture2D.MipSlice = 0;
- result = device->CreateDepthStencilView(mDepthStencilTexture, &depthStencilDesc, &mDepthStencilDSView);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mDepthStencilDSView, "Offscreen depth stencil view");
+ err = mRenderer->allocateResource(depthStencilDesc, mDepthStencilTexture.get(),
+ &mDepthStencilDSView);
+ ASSERT(!err.isError());
+ mDepthStencilDSView.setDebugName("Offscreen depth stencil view");
- if (depthBufferFormatInfo.srvFormat != DXGI_FORMAT_UNKNOWN)
+ if (depthStencilSRV)
{
D3D11_SHADER_RESOURCE_VIEW_DESC depthStencilSRVDesc;
- depthStencilSRVDesc.Format = depthBufferFormatInfo.srvFormat;
- depthStencilSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ depthStencilSRVDesc.Format = depthBufferFormatInfo.srvFormat;
+ depthStencilSRVDesc.ViewDimension = (mEGLSamples <= 1)
+ ? D3D11_SRV_DIMENSION_TEXTURE2D
+ : D3D11_SRV_DIMENSION_TEXTURE2DMS;
depthStencilSRVDesc.Texture2D.MostDetailedMip = 0;
depthStencilSRVDesc.Texture2D.MipLevels = static_cast<UINT>(-1);
- result = device->CreateShaderResourceView(mDepthStencilTexture, &depthStencilSRVDesc, &mDepthStencilSRView);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mDepthStencilSRView, "Offscreen depth stencil shader resource");
+ err = mRenderer->allocateResource(depthStencilSRVDesc, mDepthStencilTexture.get(),
+ &mDepthStencilSRView);
+ ASSERT(!err.isError());
+ mDepthStencilSRView.setDebugName("Offscreen depth stencil shader resource");
}
}
return EGL_SUCCESS;
}
-EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
+EGLint SwapChain11::resize(const gl::Context *context,
+ EGLint backbufferWidth,
+ EGLint backbufferHeight)
{
TRACE_EVENT0("gpu.angle", "SwapChain11::resize");
ID3D11Device *device = mRenderer->getDevice();
- if (device == NULL)
+ if (device == nullptr)
{
return EGL_BAD_ACCESS;
}
@@ -427,18 +464,19 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
}
// Can only call resize if we have already created our swap buffer and resources
- ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView && mBackBufferSRView);
+ ASSERT(mSwapChain && mBackBufferTexture.valid() && mBackBufferRTView.valid() &&
+ mBackBufferSRView.valid());
- SafeRelease(mBackBufferTexture);
- SafeRelease(mBackBufferRTView);
- SafeRelease(mBackBufferSRView);
+ mBackBufferTexture.reset();
+ mBackBufferRTView.reset();
+ mBackBufferSRView.reset();
// Resize swap chain
DXGI_SWAP_CHAIN_DESC desc;
HRESULT result = mSwapChain->GetDesc(&desc);
if (FAILED(result))
{
- ERR("Error reading swap chain description: 0x%08X", result);
+ ERR() << "Error reading swap chain description, " << gl::FmtHR(result);
release();
return EGL_BAD_ALLOC;
}
@@ -447,7 +485,7 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
if (FAILED(result))
{
- ERR("Error resizing swap chain buffers: 0x%08X", result);
+ ERR() << "Error resizing swap chain buffers, " << gl::FmtHR(result);
release();
if (d3d11::isDeviceLostError(result))
@@ -460,39 +498,64 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
}
}
- result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
+ ID3D11Texture2D *backbufferTexture = nullptr;
+ result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
+ reinterpret_cast<void **>(&backbufferTexture));
ASSERT(SUCCEEDED(result));
if (SUCCEEDED(result))
{
- d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
- result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
- ASSERT(SUCCEEDED(result));
- if (SUCCEEDED(result))
- {
- d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
- }
-
- result = device->CreateShaderResourceView(mBackBufferTexture, nullptr, &mBackBufferSRView);
- ASSERT(SUCCEEDED(result));
- if (SUCCEEDED(result))
- {
- d3d11::SetDebugName(mBackBufferSRView, "Back buffer shader resource");
- }
+ const auto &format =
+ d3d11::Format::Get(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps());
+ mBackBufferTexture.set(backbufferTexture, format);
+ mBackBufferTexture.setDebugName("Back buffer texture");
+
+ gl::Error err =
+ mRenderer->allocateResourceNoDesc(mBackBufferTexture.get(), &mBackBufferRTView);
+ ASSERT(!err.isError());
+ mBackBufferRTView.setDebugName("Back buffer render target");
+
+ err = mRenderer->allocateResourceNoDesc(mBackBufferTexture.get(), &mBackBufferSRView);
+ ASSERT(!err.isError());
+ mBackBufferSRView.setDebugName("Back buffer shader resource");
}
mFirstSwap = true;
- return resetOffscreenBuffers(backbufferWidth, backbufferHeight);
+ return resetOffscreenBuffers(context, backbufferWidth, backbufferHeight);
}
DXGI_FORMAT SwapChain11::getSwapChainNativeFormat() const
{
// Return a render target format for offscreen rendering is supported by IDXGISwapChain.
// MSDN https://msdn.microsoft.com/en-us/library/windows/desktop/bb173064(v=vs.85).aspx
- return (mOffscreenRenderTargetFormat == GL_BGRA8_EXT) ? DXGI_FORMAT_B8G8R8A8_UNORM : DXGI_FORMAT_R8G8B8A8_UNORM;
+ switch (mOffscreenRenderTargetFormat)
+ {
+ case GL_RGBA8:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGB8:
+ case GL_RGB565:
+ return DXGI_FORMAT_R8G8B8A8_UNORM;
+
+ case GL_BGRA8_EXT:
+ return DXGI_FORMAT_B8G8R8A8_UNORM;
+
+ case GL_RGB10_A2:
+ return DXGI_FORMAT_R10G10B10A2_UNORM;
+
+ case GL_RGBA16F:
+ return DXGI_FORMAT_R16G16B16A16_FLOAT;
+
+ default:
+ UNREACHABLE();
+ return DXGI_FORMAT_UNKNOWN;
+ }
}
-EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
+EGLint SwapChain11::reset(const gl::Context *context,
+ EGLint backbufferWidth,
+ EGLint backbufferHeight,
+ EGLint swapInterval)
{
mSwapInterval = static_cast<unsigned int>(swapInterval);
if (mSwapInterval > 4)
@@ -505,25 +568,23 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap
// If the swap chain already exists, just resize
if (mSwapChain != nullptr)
{
- return resize(backbufferWidth, backbufferHeight);
+ return resize(context, backbufferWidth, backbufferHeight);
}
TRACE_EVENT0("gpu.angle", "SwapChain11::reset");
ID3D11Device *device = mRenderer->getDevice();
- if (device == NULL)
+ if (device == nullptr)
{
return EGL_BAD_ACCESS;
}
// Release specific resources to free up memory for the new render target, while the
// old render target still exists for the purpose of preserving its contents.
-#if defined(ANGLE_ENABLE_D3D11_1)
SafeRelease(mSwapChain1);
-#endif
SafeRelease(mSwapChain);
- SafeRelease(mBackBufferTexture);
- SafeRelease(mBackBufferRTView);
+ mBackBufferTexture.reset();
+ mBackBufferRTView.reset();
// EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains
if (backbufferWidth < 1 || backbufferHeight < 1)
@@ -532,15 +593,16 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap
return EGL_SUCCESS;
}
- if (mNativeWindow.getNativeWindow())
+ if (mNativeWindow->getNativeWindow())
{
- HRESULT result = mNativeWindow.createSwapChain(device, mRenderer->getDxgiFactory(),
- getSwapChainNativeFormat(),
- backbufferWidth, backbufferHeight, &mSwapChain);
+ HRESULT result = mNativeWindow->createSwapChain(
+ device, mRenderer->getDxgiFactory(), getSwapChainNativeFormat(), backbufferWidth,
+ backbufferHeight, getD3DSamples(), &mSwapChain);
if (FAILED(result))
{
- ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
+ ERR() << "Could not create additional swap chains or offscreen surfaces, "
+ << gl::FmtHR(result);
release();
if (d3d11::isDeviceLostError(result))
@@ -555,27 +617,31 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap
if (mRenderer->getRenderer11DeviceCaps().supportsDXGI1_2)
{
-#if defined(ANGLE_ENABLE_D3D11_1)
mSwapChain1 = d3d11::DynamicCastComObject<IDXGISwapChain1>(mSwapChain);
-#endif
}
- result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
-
- result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
-
- result = device->CreateShaderResourceView(mBackBufferTexture, nullptr, &mBackBufferSRView);
+ ID3D11Texture2D *backbufferTex = nullptr;
+ result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
+ reinterpret_cast<LPVOID *>(&backbufferTex));
ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mBackBufferSRView, "Back buffer shader resource view");
+ const auto &format =
+ d3d11::Format::Get(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps());
+ mBackBufferTexture.set(backbufferTex, format);
+ mBackBufferTexture.setDebugName("Back buffer texture");
+
+ gl::Error err =
+ mRenderer->allocateResourceNoDesc(mBackBufferTexture.get(), &mBackBufferRTView);
+ ASSERT(!err.isError());
+ mBackBufferRTView.setDebugName("Back buffer render target");
+
+ err = mRenderer->allocateResourceNoDesc(mBackBufferTexture.get(), &mBackBufferSRView);
+ ASSERT(!err.isError());
+ mBackBufferSRView.setDebugName("Back buffer shader resource view");
}
mFirstSwap = true;
- return resetOffscreenBuffers(backbufferWidth, backbufferHeight);
+ return resetOffscreenBuffers(context, backbufferWidth, backbufferHeight);
}
void SwapChain11::initPassThroughResources()
@@ -588,11 +654,11 @@ void SwapChain11::initPassThroughResources()
TRACE_EVENT0("gpu.angle", "SwapChain11::initPassThroughResources");
ID3D11Device *device = mRenderer->getDevice();
- ASSERT(device != NULL);
+ ASSERT(device != nullptr);
// Make sure our resources are all not allocated, when we create
- ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL);
- ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL);
+ ASSERT(!mQuadVB.valid() && !mPassThroughSampler.valid());
+ ASSERT(!mPassThroughIL.valid() && !mPassThroughVS.valid() && !mPassThroughPS.valid());
D3D11_BUFFER_DESC vbDesc;
vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4;
@@ -602,9 +668,9 @@ void SwapChain11::initPassThroughResources()
vbDesc.MiscFlags = 0;
vbDesc.StructureByteStride = 0;
- HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer");
+ gl::Error err = mRenderer->allocateResource(vbDesc, &mQuadVB);
+ ASSERT(!err.isError());
+ mQuadVB.setDebugName("Swap chain quad vertex buffer");
D3D11_SAMPLER_DESC samplerDesc;
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
@@ -621,9 +687,9 @@ void SwapChain11::initPassThroughResources()
samplerDesc.MinLOD = 0;
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
- result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler");
+ err = mRenderer->allocateResource(samplerDesc, &mPassThroughSampler);
+ ASSERT(!err.isError());
+ mPassThroughSampler.setDebugName("Swap chain pass through sampler");
D3D11_INPUT_ELEMENT_DESC quadLayout[] =
{
@@ -631,17 +697,30 @@ void SwapChain11::initPassThroughResources()
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
- result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), &mPassThroughIL);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout");
+ InputElementArray quadElements(quadLayout);
+ ShaderData vertexShaderData(g_VS_Passthrough2D);
- result = device->CreateVertexShader(g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), NULL, &mPassThroughVS);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader");
+ err = mRenderer->allocateResource(quadElements, &vertexShaderData, &mPassThroughIL);
+ ASSERT(!err.isError());
+ mPassThroughIL.setDebugName("Swap chain pass through layout");
- result = device->CreatePixelShader(g_PS_PassthroughRGBA2D, sizeof(g_PS_PassthroughRGBA2D), NULL, &mPassThroughPS);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader");
+ err = mRenderer->allocateResource(vertexShaderData, &mPassThroughVS);
+ ASSERT(!err.isError());
+ mPassThroughVS.setDebugName("Swap chain pass through vertex shader");
+
+ if (mEGLSamples <= 1)
+ {
+ ShaderData pixelShaderData(g_PS_PassthroughRGBA2D);
+ err = mRenderer->allocateResource(pixelShaderData, &mPassThroughPS);
+ }
+ else
+ {
+ ShaderData pixelShaderData(g_PS_PassthroughRGBA2DMS);
+ err = mRenderer->allocateResource(pixelShaderData, &mPassThroughPS);
+ }
+
+ ASSERT(!err.isError());
+ mPassThroughPS.setDebugName("Swap chain pass through pixel shader");
// Use the default rasterizer state but without culling
D3D11_RASTERIZER_DESC rasterizerDesc;
@@ -655,26 +734,31 @@ void SwapChain11::initPassThroughResources()
rasterizerDesc.ScissorEnable = FALSE;
rasterizerDesc.MultisampleEnable = FALSE;
rasterizerDesc.AntialiasedLineEnable = FALSE;
- result = device->CreateRasterizerState(&rasterizerDesc, &mPassThroughRS);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mPassThroughRS, "Swap chain pass through rasterizer state");
+
+ err = mRenderer->allocateResource(rasterizerDesc, &mPassThroughRS);
+ ASSERT(!err.isError());
+ mPassThroughRS.setDebugName("Swap chain pass through rasterizer state");
mPassThroughResourcesInit = true;
}
// parameters should be validated/clamped by caller
-EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+EGLint SwapChain11::swapRect(const gl::Context *context,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height)
{
if (mNeedsOffscreenTexture)
{
- EGLint result = copyOffscreenToBackbuffer(x, y, width, height);
+ EGLint result = copyOffscreenToBackbuffer(context, x, y, width, height);
if (result != EGL_SUCCESS)
{
return result;
}
}
- EGLint result = present(x, y, width, height);
+ EGLint result = present(context, x, y, width, height);
if (result != EGL_SUCCESS)
{
return result;
@@ -685,7 +769,11 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
return EGL_SUCCESS;
}
-EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+EGLint SwapChain11::copyOffscreenToBackbuffer(const gl::Context *context,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height)
{
if (!mSwapChain)
{
@@ -698,7 +786,8 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width,
// Set vertices
D3D11_MAPPED_SUBRESOURCE mappedResource;
- HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ HRESULT result =
+ deviceContext->Map(mQuadVB.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(result))
{
return EGL_BAD_ACCESS;
@@ -716,7 +805,6 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width,
float v1 = y / float(height);
float u2 = (x + width) / float(width);
float v2 = (y + height) / float(height);
-
// Invert the quad vertices depending on the surface orientation.
if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE) != 0)
{
@@ -732,60 +820,43 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width,
d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2);
- deviceContext->Unmap(mQuadVB, 0);
+ deviceContext->Unmap(mQuadVB.get(), 0);
- static UINT stride = sizeof(d3d11::PositionTexCoordVertex);
- static UINT startIdx = 0;
- deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx);
-
- // Apply state
- deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
+ StateManager11 *stateManager = mRenderer->getStateManager();
- static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
- deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF);
+ constexpr UINT stride = sizeof(d3d11::PositionTexCoordVertex);
+ stateManager->setSingleVertexBuffer(&mQuadVB, stride, 0);
- deviceContext->RSSetState(mPassThroughRS);
+ // Apply state
+ stateManager->setDepthStencilState(nullptr, 0xFFFFFFFF);
+ stateManager->setSimpleBlendState(nullptr);
+ stateManager->setRasterizerState(&mPassThroughRS);
// Apply shaders
- deviceContext->IASetInputLayout(mPassThroughIL);
- deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
- deviceContext->VSSetShader(mPassThroughVS, NULL, 0);
- deviceContext->PSSetShader(mPassThroughPS, NULL, 0);
- deviceContext->GSSetShader(NULL, NULL, 0);
+ stateManager->setInputLayout(&mPassThroughIL);
+ stateManager->setPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
+ stateManager->setDrawShaders(&mPassThroughVS, nullptr, &mPassThroughPS);
- // Apply render targets
- mRenderer->setOneTimeRenderTarget(mBackBufferRTView);
+ // Apply render targets. Use the proxy context in display.
+ stateManager->setRenderTarget(mBackBufferRTView.get(), nullptr);
// Set the viewport
- D3D11_VIEWPORT viewport;
- viewport.TopLeftX = 0;
- viewport.TopLeftY = 0;
- viewport.Width = static_cast<FLOAT>(width);
- viewport.Height = static_cast<FLOAT>(height);
- viewport.MinDepth = 0.0f;
- viewport.MaxDepth = 1.0f;
- deviceContext->RSSetViewports(1, &viewport);
+ stateManager->setSimpleViewport(mWidth, mHeight);
// Apply textures
- auto stateManager = mRenderer->getStateManager();
- stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, mOffscreenSRView);
- deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler);
+ stateManager->setSimplePixelTextureAndSampler(mOffscreenSRView, mPassThroughSampler);
// Draw
deviceContext->Draw(4, 0);
- // Rendering to the swapchain is now complete. Now we can call Present().
- // Before that, we perform any cleanup on the D3D device. We do this before Present() to make sure the
- // cleanup is caught under the current eglSwapBuffers() PIX/Graphics Diagnostics call rather than the next one.
- stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL);
-
- mRenderer->unapplyRenderTargets();
- mRenderer->markAllStateDirty();
-
return EGL_SUCCESS;
}
-EGLint SwapChain11::present(EGLint x, EGLint y, EGLint width, EGLint height)
+EGLint SwapChain11::present(const gl::Context *context,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height)
{
if (!mSwapChain)
{
@@ -799,9 +870,9 @@ EGLint SwapChain11::present(EGLint x, EGLint y, EGLint width, EGLint height)
HRESULT result = S_OK;
-#if defined(ANGLE_ENABLE_D3D11_1)
// Use IDXGISwapChain1::Present1 with a dirty rect if DXGI 1.2 is available.
- if (mSwapChain1 != nullptr)
+ // Dirty rect present is not supported with a multisampled swapchain.
+ if (mSwapChain1 != nullptr && mEGLSamples <= 1)
{
if (mFirstSwap)
{
@@ -818,7 +889,6 @@ EGLint SwapChain11::present(EGLint x, EGLint y, EGLint width, EGLint height)
}
}
else
-#endif
{
result = mSwapChain->Present(swapInterval, 0);
}
@@ -826,60 +896,111 @@ EGLint SwapChain11::present(EGLint x, EGLint y, EGLint width, EGLint height)
mFirstSwap = false;
// Some swapping mechanisms such as DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL unbind the current render
- // target. Mark it dirty.
+ // target. Mark it dirty. Use the proxy context in display since there is none available.
mRenderer->getStateManager()->invalidateRenderTarget();
if (result == DXGI_ERROR_DEVICE_REMOVED)
{
- ERR("Present failed: the D3D11 device was removed: 0x%08X",
- mRenderer->getDevice()->GetDeviceRemovedReason());
+ ERR() << "Present failed: the D3D11 device was removed, "
+ << gl::FmtHR(mRenderer->getDevice()->GetDeviceRemovedReason());
return EGL_CONTEXT_LOST;
}
else if (result == DXGI_ERROR_DEVICE_RESET)
{
- ERR("Present failed: the D3D11 device was reset from a bad command.");
+ ERR() << "Present failed: the D3D11 device was reset from a bad command.";
return EGL_CONTEXT_LOST;
}
else if (FAILED(result))
{
- ERR("Present failed with error code 0x%08X", result);
+ ERR() << "Present failed with " << gl::FmtHR(result);
}
- mNativeWindow.commitChange();
+ mNativeWindow->commitChange();
return EGL_SUCCESS;
}
-ID3D11Texture2D *SwapChain11::getOffscreenTexture()
+const TextureHelper11 &SwapChain11::getOffscreenTexture()
{
return mNeedsOffscreenTexture ? mOffscreenTexture : mBackBufferTexture;
}
-ID3D11RenderTargetView *SwapChain11::getRenderTarget()
+const d3d11::RenderTargetView &SwapChain11::getRenderTarget()
{
return mNeedsOffscreenTexture ? mOffscreenRTView : mBackBufferRTView;
}
-ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource()
+const d3d11::SharedSRV &SwapChain11::getRenderTargetShaderResource()
{
- return mNeedsOffscreenTexture ? mOffscreenSRView : mBackBufferSRView;
+ if (!mNeedsOffscreenTexture)
+ {
+ ASSERT(mBackBufferSRView.valid());
+ return mBackBufferSRView;
+ }
+
+ if (!mNeedsOffscreenTextureCopy)
+ {
+ ASSERT(mOffscreenSRView.valid());
+ return mOffscreenSRView;
+ }
+
+ if (!mOffscreenTextureCopyForSRV.valid())
+ {
+ const d3d11::Format &backbufferFormatInfo =
+ d3d11::Format::Get(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps());
+
+ D3D11_TEXTURE2D_DESC offscreenCopyDesc;
+ mOffscreenTexture.getDesc(&offscreenCopyDesc);
+
+ offscreenCopyDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ offscreenCopyDesc.MiscFlags = 0;
+ offscreenCopyDesc.CPUAccessFlags = 0;
+ gl::Error err = mRenderer->allocateTexture(offscreenCopyDesc, backbufferFormatInfo,
+ &mOffscreenTextureCopyForSRV);
+ ASSERT(!err.isError());
+ mOffscreenTextureCopyForSRV.setDebugName("Offscreen back buffer copy for SRV");
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC offscreenSRVDesc;
+ offscreenSRVDesc.Format = backbufferFormatInfo.srvFormat;
+ offscreenSRVDesc.ViewDimension =
+ (mEGLSamples <= 1) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS;
+ offscreenSRVDesc.Texture2D.MostDetailedMip = 0;
+ offscreenSRVDesc.Texture2D.MipLevels = static_cast<UINT>(-1);
+
+ err = mRenderer->allocateResource(offscreenSRVDesc, mOffscreenTextureCopyForSRV.get(),
+ &mOffscreenSRView);
+ ASSERT(!err.isError());
+ mOffscreenSRView.setDebugName("Offscreen back buffer shader resource");
+ }
+
+ // Need to copy the offscreen texture into the shader-readable copy, since it's external and
+ // we don't know if the copy is up-to-date. This works around the problem we have when the app
+ // passes in a texture that isn't shader-readable.
+ mRenderer->getDeviceContext()->CopyResource(mOffscreenTextureCopyForSRV.get(),
+ mOffscreenTexture.get());
+ return mOffscreenSRView;
}
-ID3D11DepthStencilView *SwapChain11::getDepthStencil()
+const d3d11::DepthStencilView &SwapChain11::getDepthStencil()
{
return mDepthStencilDSView;
}
-ID3D11ShaderResourceView * SwapChain11::getDepthStencilShaderResource()
+const d3d11::SharedSRV &SwapChain11::getDepthStencilShaderResource()
{
return mDepthStencilSRView;
}
-ID3D11Texture2D *SwapChain11::getDepthStencilTexture()
+const TextureHelper11 &SwapChain11::getDepthStencilTexture()
{
return mDepthStencilTexture;
}
+void *SwapChain11::getKeyedMutex()
+{
+ return mKeyedMutex;
+}
+
void SwapChain11::recreate()
{
// possibly should use this method instead of reset
@@ -890,4 +1011,61 @@ void *rx::SwapChain11::getDevice()
return mRenderer->getDevice();
}
+RenderTargetD3D *SwapChain11::getColorRenderTarget()
+{
+ return &mColorRenderTarget;
+}
+
+RenderTargetD3D *SwapChain11::getDepthStencilRenderTarget()
+{
+ return &mDepthStencilRenderTarget;
+}
+
+egl::Error SwapChain11::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
+{
+ if (!mSwapChain)
+ {
+ return egl::EglNotInitialized() << "Swap chain uninitialized";
+ }
+
+ DXGI_FRAME_STATISTICS stats = {};
+ HRESULT result = mSwapChain->GetFrameStatistics(&stats);
+
+ if (FAILED(result))
+ {
+ return egl::EglBadAlloc() << "Failed to get frame statistics, " << gl::FmtHR(result);
+ }
+
+ // Conversion from DXGI_FRAME_STATISTICS to the output values:
+ // stats.SyncRefreshCount -> msc
+ // stats.PresentCount -> sbc
+ // stats.SyncQPCTime -> ust with conversion to microseconds via QueryPerformanceFrequency
+ *msc = stats.SyncRefreshCount;
+ *sbc = stats.PresentCount;
+
+ LONGLONG syncQPCValue = stats.SyncQPCTime.QuadPart;
+ // If the QPC Value is below the overflow threshold, we proceed with
+ // simple multiply and divide.
+ if (syncQPCValue < kQPCOverflowThreshold)
+ {
+ *ust = syncQPCValue * kMicrosecondsPerSecond / mQPCFrequency;
+ }
+ else
+ {
+ // Otherwise, calculate microseconds in a round about manner to avoid
+ // overflow and precision issues.
+ int64_t wholeSeconds = syncQPCValue / mQPCFrequency;
+ int64_t leftoverTicks = syncQPCValue - (wholeSeconds * mQPCFrequency);
+ *ust = wholeSeconds * kMicrosecondsPerSecond +
+ leftoverTicks * kMicrosecondsPerSecond / mQPCFrequency;
+ }
+
+ return egl::NoError();
+}
+
+UINT SwapChain11::getD3DSamples() const
+{
+ return (mEGLSamples == 0) ? 1 : mEGLSamples;
}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
index adcd07adb0..eca068210b 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
@@ -16,39 +16,54 @@
namespace rx
{
class Renderer11;
+class NativeWindow11;
-class SwapChain11 : public SwapChainD3D
+class SwapChain11 final : public SwapChainD3D
{
public:
SwapChain11(Renderer11 *renderer,
- NativeWindow nativeWindow,
+ NativeWindow11 *nativeWindow,
HANDLE shareHandle,
+ IUnknown *d3dTexture,
GLenum backBufferFormat,
GLenum depthBufferFormat,
- EGLint orientation);
- virtual ~SwapChain11();
-
- EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight);
- virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval);
- virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
- virtual void recreate();
-
- RenderTargetD3D *getColorRenderTarget() override { return &mColorRenderTarget; }
- RenderTargetD3D *getDepthStencilRenderTarget() override { return &mDepthStencilRenderTarget; }
-
- virtual ID3D11Texture2D *getOffscreenTexture();
- virtual ID3D11RenderTargetView *getRenderTarget();
- virtual ID3D11ShaderResourceView *getRenderTargetShaderResource();
-
- virtual ID3D11Texture2D *getDepthStencilTexture();
- virtual ID3D11DepthStencilView *getDepthStencil();
- virtual ID3D11ShaderResourceView *getDepthStencilShaderResource();
+ EGLint orientation,
+ EGLint samples);
+ ~SwapChain11() override;
+
+ EGLint resize(const gl::Context *context,
+ EGLint backbufferWidth,
+ EGLint backbufferHeight) override;
+ EGLint reset(const gl::Context *context,
+ EGLint backbufferWidth,
+ EGLint backbufferHeight,
+ EGLint swapInterval) override;
+ EGLint swapRect(const gl::Context *context,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height) override;
+ void recreate() override;
+
+ RenderTargetD3D *getColorRenderTarget() override;
+ RenderTargetD3D *getDepthStencilRenderTarget() override;
+
+ const TextureHelper11 &getOffscreenTexture();
+ const d3d11::RenderTargetView &getRenderTarget();
+ const d3d11::SharedSRV &getRenderTargetShaderResource();
+
+ const TextureHelper11 &getDepthStencilTexture();
+ const d3d11::DepthStencilView &getDepthStencil();
+ const d3d11::SharedSRV &getDepthStencilShaderResource();
EGLint getWidth() const { return mWidth; }
EGLint getHeight() const { return mHeight; }
- void *getKeyedMutex() override { return mKeyedMutex; }
+ void *getKeyedMutex() override;
+ EGLint getSamples() const { return mEGLSamples; }
+
+ void *getDevice() override;
- virtual void *getDevice();
+ egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override;
private:
void release();
@@ -56,14 +71,23 @@ class SwapChain11 : public SwapChainD3D
void releaseOffscreenColorBuffer();
void releaseOffscreenDepthBuffer();
- EGLint resetOffscreenBuffers(int backbufferWidth, int backbufferHeight);
- EGLint resetOffscreenColorBuffer(int backbufferWidth, int backbufferHeight);
+ EGLint resetOffscreenBuffers(const gl::Context *context,
+ int backbufferWidth,
+ int backbufferHeight);
+ EGLint resetOffscreenColorBuffer(const gl::Context *context,
+ int backbufferWidth,
+ int backbufferHeight);
EGLint resetOffscreenDepthBuffer(int backbufferWidth, int backbufferHeight);
DXGI_FORMAT getSwapChainNativeFormat() const;
- EGLint copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, EGLint height);
- EGLint present(EGLint x, EGLint y, EGLint width, EGLint height);
+ EGLint copyOffscreenToBackbuffer(const gl::Context *context,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height);
+ EGLint present(const gl::Context *context, EGLint x, EGLint y, EGLint width, EGLint height);
+ UINT getD3DSamples() const;
Renderer11 *mRenderer;
EGLint mWidth;
@@ -73,36 +97,41 @@ class SwapChain11 : public SwapChainD3D
unsigned int mSwapInterval;
bool mPassThroughResourcesInit;
+ NativeWindow11 *mNativeWindow; // Handler for the Window that the surface is created for.
+
bool mFirstSwap;
- DXGISwapChain *mSwapChain;
-#if defined(ANGLE_ENABLE_D3D11_1)
+ IDXGISwapChain *mSwapChain;
IDXGISwapChain1 *mSwapChain1;
-#endif
IDXGIKeyedMutex *mKeyedMutex;
- ID3D11Texture2D *mBackBufferTexture;
- ID3D11RenderTargetView *mBackBufferRTView;
- ID3D11ShaderResourceView *mBackBufferSRView;
+ TextureHelper11 mBackBufferTexture;
+ d3d11::RenderTargetView mBackBufferRTView;
+ d3d11::SharedSRV mBackBufferSRView;
const bool mNeedsOffscreenTexture;
- ID3D11Texture2D *mOffscreenTexture;
- ID3D11RenderTargetView *mOffscreenRTView;
- ID3D11ShaderResourceView *mOffscreenSRView;
-
- ID3D11Texture2D *mDepthStencilTexture;
- ID3D11DepthStencilView *mDepthStencilDSView;
- ID3D11ShaderResourceView *mDepthStencilSRView;
-
- ID3D11Buffer *mQuadVB;
- ID3D11SamplerState *mPassThroughSampler;
- ID3D11InputLayout *mPassThroughIL;
- ID3D11VertexShader *mPassThroughVS;
- ID3D11PixelShader *mPassThroughPS;
- ID3D11RasterizerState *mPassThroughRS;
+ TextureHelper11 mOffscreenTexture;
+ d3d11::RenderTargetView mOffscreenRTView;
+ d3d11::SharedSRV mOffscreenSRView;
+ bool mNeedsOffscreenTextureCopy;
+ TextureHelper11 mOffscreenTextureCopyForSRV;
+
+ TextureHelper11 mDepthStencilTexture;
+ d3d11::DepthStencilView mDepthStencilDSView;
+ d3d11::SharedSRV mDepthStencilSRView;
+
+ d3d11::Buffer mQuadVB;
+ d3d11::SamplerState mPassThroughSampler;
+ d3d11::InputLayout mPassThroughIL;
+ d3d11::VertexShader mPassThroughVS;
+ d3d11::PixelShader mPassThroughPS;
+ d3d11::RasterizerState mPassThroughRS;
SurfaceRenderTarget11 mColorRenderTarget;
SurfaceRenderTarget11 mDepthStencilRenderTarget;
+
+ EGLint mEGLSamples;
+ LONGLONG mQPCFrequency;
};
-}
+} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_D3D11_SWAPCHAIN11_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
index 11b9f76464..b702450ded 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
@@ -5,7 +5,8 @@
//
// TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived
-// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture.
+// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11
+// texture.
#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
@@ -21,6 +22,7 @@
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h"
#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
#include "libANGLE/renderer/d3d/EGLImageD3D.h"
@@ -29,82 +31,79 @@
namespace rx
{
-TextureStorage11::SwizzleCacheValue::SwizzleCacheValue()
- : swizzleRed(GL_INVALID_INDEX),
- swizzleGreen(GL_INVALID_INDEX),
- swizzleBlue(GL_INVALID_INDEX),
- swizzleAlpha(GL_INVALID_INDEX)
+namespace
{
+
+void InvalidateRenderTarget(const gl::Context *context, RenderTarget11 *renderTarget)
+{
+ if (renderTarget)
+ {
+ renderTarget->signalDirty(context);
+ }
}
-TextureStorage11::SwizzleCacheValue::SwizzleCacheValue(GLenum red, GLenum green, GLenum blue, GLenum alpha)
- : swizzleRed(red), swizzleGreen(green), swizzleBlue(blue), swizzleAlpha(alpha)
+RenderTarget11 *GetRenderTarget(std::unique_ptr<RenderTarget11> *pointer)
{
+ return pointer->get();
}
-bool TextureStorage11::SwizzleCacheValue::operator==(const SwizzleCacheValue &other) const
+template <typename KeyT>
+RenderTarget11 *GetRenderTarget(std::pair<KeyT, std::unique_ptr<RenderTarget11>> *pair)
{
- return swizzleRed == other.swizzleRed &&
- swizzleGreen == other.swizzleGreen &&
- swizzleBlue == other.swizzleBlue &&
- swizzleAlpha == other.swizzleAlpha;
+ return pair->second.get();
}
-bool TextureStorage11::SwizzleCacheValue::operator!=(const SwizzleCacheValue &other) const
+template <typename T>
+void InvalidateRenderTargetContainer(const gl::Context *context, T *renderTargetContainer)
{
- return !(*this == other);
+ for (auto &rt : *renderTargetContainer)
+ {
+ InvalidateRenderTarget(context, GetRenderTarget(&rt));
+ }
}
-TextureStorage11::SRVKey::SRVKey(int baseLevel, int mipLevels, bool swizzle)
- : baseLevel(baseLevel), mipLevels(mipLevels), swizzle(swizzle)
+} // anonymous namespace
+
+TextureStorage11::SRVKey::SRVKey(int baseLevel, int mipLevels, bool swizzle, bool dropStencil)
+ : baseLevel(baseLevel), mipLevels(mipLevels), swizzle(swizzle), dropStencil(dropStencil)
{
}
bool TextureStorage11::SRVKey::operator<(const SRVKey &rhs) const
{
- return std::tie(baseLevel, mipLevels, swizzle) < std::tie(rhs.baseLevel, rhs.mipLevels, rhs.swizzle);
+ return std::tie(baseLevel, mipLevels, swizzle, dropStencil) <
+ std::tie(rhs.baseLevel, rhs.mipLevels, rhs.swizzle, rhs.dropStencil);
}
-TextureStorage11::TextureStorage11(Renderer11 *renderer, UINT bindFlags, UINT miscFlags)
+TextureStorage11::TextureStorage11(Renderer11 *renderer,
+ UINT bindFlags,
+ UINT miscFlags,
+ GLenum internalFormat)
: mRenderer(renderer),
mTopLevel(0),
mMipLevels(0),
- mInternalFormat(GL_NONE),
- mTextureFormat(DXGI_FORMAT_UNKNOWN),
- mShaderResourceFormat(DXGI_FORMAT_UNKNOWN),
- mRenderTargetFormat(DXGI_FORMAT_UNKNOWN),
- mDepthStencilFormat(DXGI_FORMAT_UNKNOWN),
+ mFormatInfo(d3d11::Format::Get(internalFormat, mRenderer->getRenderer11DeviceCaps())),
mTextureWidth(0),
mTextureHeight(0),
mTextureDepth(0),
+ mDropStencilTexture(),
mBindFlags(bindFlags),
mMiscFlags(miscFlags)
{
- for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
- {
- mLevelSRVs[i] = nullptr;
- }
}
TextureStorage11::~TextureStorage11()
{
- for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
- {
- SafeRelease(mLevelSRVs[level]);
- }
-
- for (SRVCache::iterator i = mSrvCache.begin(); i != mSrvCache.end(); i++)
- {
- SafeRelease(i->second);
- }
mSrvCache.clear();
}
-DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, const Renderer11DeviceCaps &renderer11DeviceCaps, bool renderTarget)
+DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat,
+ const Renderer11DeviceCaps &renderer11DeviceCaps,
+ bool renderTarget)
{
UINT bindFlags = 0;
- const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat, renderer11DeviceCaps);
+ const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps);
if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN)
{
bindFlags |= D3D11_BIND_SHADER_RESOURCE;
@@ -121,16 +120,17 @@ DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, const Rendere
return bindFlags;
}
-DWORD TextureStorage11::GetTextureMiscFlags(GLenum internalFormat, const Renderer11DeviceCaps &renderer11DeviceCaps, bool renderTarget, int levels)
+DWORD TextureStorage11::GetTextureMiscFlags(GLenum internalFormat,
+ const Renderer11DeviceCaps &renderer11DeviceCaps,
+ bool renderTarget,
+ int levels)
{
UINT miscFlags = 0;
- const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat, renderer11DeviceCaps);
+ const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps);
if (renderTarget && levels > 1)
{
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(formatInfo.texFormat);
-
- if (dxgiFormatInfo.nativeMipmapSupport(renderer11DeviceCaps.featureLevel))
+ if (d3d11::SupportsMipGen(formatInfo.texFormat, renderer11DeviceCaps.featureLevel))
{
miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
}
@@ -151,6 +151,8 @@ UINT TextureStorage11::getMiscFlags() const
int TextureStorage11::getTopLevel() const
{
+ // Applying top level is meant to be encapsulated inside TextureStorage11.
+ UNREACHABLE();
return mTopLevel;
}
@@ -189,24 +191,35 @@ int TextureStorage11::getLevelDepth(int mipLevel) const
return std::max(static_cast<int>(mTextureDepth) >> mipLevel, 1);
}
+gl::Error TextureStorage11::getMippedResource(const gl::Context *context,
+ const TextureHelper11 **outResource)
+{
+ return getResource(context, outResource);
+}
+
UINT TextureStorage11::getSubresourceIndex(const gl::ImageIndex &index) const
{
- UINT mipSlice = static_cast<UINT>(index.mipIndex + mTopLevel);
- UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0);
+ UINT mipSlice = static_cast<UINT>(index.mipIndex + mTopLevel);
+ UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0);
UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels);
ASSERT(subresource != std::numeric_limits<UINT>::max());
return subresource;
}
-gl::Error TextureStorage11::getSRV(const gl::TextureState &textureState,
- ID3D11ShaderResourceView **outSRV)
+gl::Error TextureStorage11::getSRV(const gl::Context *context,
+ const gl::TextureState &textureState,
+ const d3d11::SharedSRV **outSRV)
{
- bool swizzleRequired = textureState.swizzleRequired();
- bool mipmapping = gl::IsMipmapFiltered(textureState.samplerState);
- unsigned int mipLevels = mipmapping ? (textureState.maxLevel - textureState.baseLevel + 1) : 1;
+ // Make sure to add the level offset for our tiny compressed texture workaround
+ const GLuint effectiveBaseLevel = textureState.getEffectiveBaseLevel();
+ bool swizzleRequired = textureState.swizzleRequired();
+ bool mipmapping = gl::IsMipmapFiltered(textureState.getSamplerState());
+ unsigned int mipLevels =
+ mipmapping ? (textureState.getEffectiveMaxLevel() - effectiveBaseLevel + 1) : 1;
- // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level, which corresponds to GL level 0)
- mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - textureState.baseLevel);
+ // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level,
+ // which corresponds to GL level 0)
+ mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - effectiveBaseLevel);
if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
{
@@ -217,89 +230,133 @@ gl::Error TextureStorage11::getSRV(const gl::TextureState &textureState,
if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
// We must ensure that the level zero texture is in sync with mipped texture.
- gl::Error error = useLevelZeroWorkaroundTexture(mipLevels == 1);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(useLevelZeroWorkaroundTexture(context, mipLevels == 1));
}
if (swizzleRequired)
{
- verifySwizzleExists(textureState.swizzleRed, textureState.swizzleGreen,
- textureState.swizzleBlue, textureState.swizzleAlpha);
+ verifySwizzleExists(textureState.getSwizzleState());
}
- SRVKey key(textureState.baseLevel, mipLevels, swizzleRequired);
+ // We drop the stencil when sampling from the SRV if three conditions hold:
+ // 1. the drop stencil workaround is enabled.
+ bool workaround = mRenderer->getWorkarounds().emulateTinyStencilTextures;
+ // 2. this is a stencil texture.
+ bool hasStencil = (mFormatInfo.format().stencilBits > 0);
+ // 3. the texture has a 1x1 or 2x2 mip.
+ int effectiveTopLevel = effectiveBaseLevel + mipLevels - 1;
+ bool hasSmallMips =
+ (getLevelWidth(effectiveTopLevel) <= 2 || getLevelHeight(effectiveTopLevel) <= 2);
+
+ bool useDropStencil = (workaround && hasStencil && hasSmallMips);
+ SRVKey key(effectiveBaseLevel, mipLevels, swizzleRequired, useDropStencil);
+ if (useDropStencil)
+ {
+ // Ensure drop texture gets created.
+ DropStencil result = DropStencil::CREATED;
+ ANGLE_TRY_RESULT(ensureDropStencilTexture(context), result);
+
+ // Clear the SRV cache if necessary.
+ // TODO(jmadill): Re-use find query result.
+ auto srvEntry = mSrvCache.find(key);
+ if (result == DropStencil::CREATED && srvEntry != mSrvCache.end())
+ {
+ mSrvCache.erase(key);
+ }
+ }
+
+ ANGLE_TRY(getCachedOrCreateSRV(context, key, outSRV));
+
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11::getCachedOrCreateSRV(const gl::Context *context,
+ const SRVKey &key,
+ const d3d11::SharedSRV **outSRV)
+{
auto iter = mSrvCache.find(key);
if (iter != mSrvCache.end())
{
- *outSRV = iter->second;
- return gl::Error(GL_NO_ERROR);
+ *outSRV = &iter->second;
+ return gl::NoError();
}
- ID3D11Resource *texture = nullptr;
- if (swizzleRequired)
+ const TextureHelper11 *texture = nullptr;
+ DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
+
+ if (key.swizzle)
{
- gl::Error error = getSwizzleTexture(&texture);
- if (error.isError())
- {
- return error;
- }
+ const auto &swizzleFormat =
+ mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
+ ASSERT(!key.dropStencil || swizzleFormat.format().stencilBits == 0);
+ ANGLE_TRY(getSwizzleTexture(&texture));
+ format = swizzleFormat.srvFormat;
}
- else
+ else if (key.dropStencil)
{
- gl::Error error = getResource(&texture);
- if (error.isError())
- {
- return error;
- }
+ ASSERT(mDropStencilTexture.valid());
+ texture = &mDropStencilTexture;
+ format = DXGI_FORMAT_R32_FLOAT;
}
-
- ID3D11ShaderResourceView *srv = nullptr;
- DXGI_FORMAT format = (swizzleRequired ? mSwizzleShaderResourceFormat : mShaderResourceFormat);
- gl::Error error = createSRV(textureState.baseLevel, mipLevels, format, texture, &srv);
- if (error.isError())
+ else
{
- return error;
+ ANGLE_TRY(getResource(context, &texture));
+ format = mFormatInfo.srvFormat;
}
- mSrvCache.insert(std::make_pair(key, srv));
- *outSRV = srv;
+ d3d11::SharedSRV srv;
+
+ ANGLE_TRY(createSRV(context, key.baseLevel, key.mipLevels, format, *texture, &srv));
+
+ const auto &insertIt = mSrvCache.insert(std::make_pair(key, std::move(srv)));
+ *outSRV = &insertIt.first->second;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage11::getSRVLevel(int mipLevel, ID3D11ShaderResourceView **outSRV)
+gl::Error TextureStorage11::getSRVLevel(const gl::Context *context,
+ int mipLevel,
+ bool blitSRV,
+ const d3d11::SharedSRV **outSRV)
{
ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
- if (!mLevelSRVs[mipLevel])
+ auto &levelSRVs = (blitSRV) ? mLevelBlitSRVs : mLevelSRVs;
+ auto &otherLevelSRVs = (blitSRV) ? mLevelSRVs : mLevelBlitSRVs;
+
+ if (!levelSRVs[mipLevel].valid())
{
- ID3D11Resource *resource = NULL;
- gl::Error error = getResource(&resource);
- if (error.isError())
+ // Only create a different SRV for blit if blit format is different from regular srv format
+ if (otherLevelSRVs[mipLevel].valid() && mFormatInfo.srvFormat == mFormatInfo.blitSRVFormat)
{
- return error;
+ levelSRVs[mipLevel] = otherLevelSRVs[mipLevel].makeCopy();
}
-
- error = createSRV(mipLevel, 1, mShaderResourceFormat, resource, &mLevelSRVs[mipLevel]);
- if (error.isError())
+ else
{
- return error;
+ const TextureHelper11 *resource = nullptr;
+ ANGLE_TRY(getResource(context, &resource));
+
+ DXGI_FORMAT resourceFormat =
+ blitSRV ? mFormatInfo.blitSRVFormat : mFormatInfo.srvFormat;
+ ANGLE_TRY(
+ createSRV(context, mipLevel, 1, resourceFormat, *resource, &levelSRVs[mipLevel]));
}
}
- *outSRV = mLevelSRVs[mipLevel];
+ *outSRV = &levelSRVs[mipLevel];
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage11::getSRVLevels(GLint baseLevel, GLint maxLevel, ID3D11ShaderResourceView **outSRV)
+gl::Error TextureStorage11::getSRVLevels(const gl::Context *context,
+ GLint baseLevel,
+ GLint maxLevel,
+ const d3d11::SharedSRV **outSRV)
{
unsigned int mipLevels = maxLevel - baseLevel + 1;
- // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level, which corresponds to GL level 0)
+ // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level,
+ // which corresponds to GL level 0)
mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - baseLevel);
if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
@@ -310,245 +367,218 @@ gl::Error TextureStorage11::getSRVLevels(GLint baseLevel, GLint maxLevel, ID3D11
if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
// We must ensure that the level zero texture is in sync with mipped texture.
- gl::Error error = useLevelZeroWorkaroundTexture(mipLevels == 1);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(useLevelZeroWorkaroundTexture(context, mipLevels == 1));
}
- SRVKey key(baseLevel, mipLevels, false);
- auto iter = mSrvCache.find(key);
- if (iter != mSrvCache.end())
- {
- *outSRV = iter->second;
- return gl::Error(GL_NO_ERROR);
- }
+ // TODO(jmadill): Assert we don't need to drop stencil.
- ID3D11Resource *texture = nullptr;
- gl::Error error = getResource(&texture);
- if (error.isError())
- {
- return error;
- }
+ SRVKey key(baseLevel, mipLevels, false, false);
+ ANGLE_TRY(getCachedOrCreateSRV(context, key, outSRV));
- ID3D11ShaderResourceView *srv = nullptr;
- error = createSRV(baseLevel, mipLevels, mShaderResourceFormat, texture, &srv);
- if (error.isError())
- {
- return error;
- }
-
- mSrvCache[key] = srv;
- *outSRV = srv;
+ return gl::NoError();
+}
- return gl::Error(GL_NO_ERROR);
+const d3d11::Format &TextureStorage11::getFormatSet() const
+{
+ return mFormatInfo;
}
-gl::Error TextureStorage11::generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha)
+gl::Error TextureStorage11::generateSwizzles(const gl::Context *context,
+ const gl::SwizzleState &swizzleTarget)
{
- SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha);
for (int level = 0; level < getLevelCount(); level++)
{
// Check if the swizzle for this level is out of date
if (mSwizzleCache[level] != swizzleTarget)
{
// Need to re-render the swizzle for this level
- ID3D11ShaderResourceView *sourceSRV = NULL;
- gl::Error error = getSRVLevel(level, &sourceSRV);
- if (error.isError())
- {
- return error;
- }
+ const d3d11::SharedSRV *sourceSRV = nullptr;
+ ANGLE_TRY(getSRVLevel(context, level, true, &sourceSRV));
- ID3D11RenderTargetView *destRTV = NULL;
- error = getSwizzleRenderTarget(level, &destRTV);
- if (error.isError())
- {
- return error;
- }
+ const d3d11::RenderTargetView *destRTV;
+ ANGLE_TRY(getSwizzleRenderTarget(level, &destRTV));
gl::Extents size(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level));
Blit11 *blitter = mRenderer->getBlitter();
- error = blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(blitter->swizzleTexture(context, *sourceSRV, *destRTV, size, swizzleTarget));
mSwizzleCache[level] = swizzleTarget;
}
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-void TextureStorage11::invalidateSwizzleCacheLevel(int mipLevel)
+void TextureStorage11::markLevelDirty(int mipLevel)
{
- if (mipLevel >= 0 && static_cast<unsigned int>(mipLevel) < ArraySize(mSwizzleCache))
+ if (mipLevel >= 0 && static_cast<size_t>(mipLevel) < mSwizzleCache.size())
{
- // The default constructor of SwizzleCacheValue has GL_NONE for all channels which is not a
- // valid swizzle combination
- mSwizzleCache[mipLevel] = SwizzleCacheValue();
+ // The default constructor of SwizzleState has GL_INVALID_INDEX for all channels which is
+ // not a valid swizzle combination
+ if (mSwizzleCache[mipLevel] != gl::SwizzleState())
+ {
+ // TODO(jmadill): Invalidate specific swizzle.
+ mRenderer->getStateManager()->invalidateSwizzles();
+ mSwizzleCache[mipLevel] = gl::SwizzleState();
+ }
+ }
+
+ if (mDropStencilTexture.valid())
+ {
+ mDropStencilTexture.reset();
}
}
-void TextureStorage11::invalidateSwizzleCache()
+void TextureStorage11::markDirty()
{
- for (unsigned int mipLevel = 0; mipLevel < ArraySize(mSwizzleCache); mipLevel++)
+ for (size_t mipLevel = 0; mipLevel < mSwizzleCache.size(); ++mipLevel)
{
- invalidateSwizzleCacheLevel(mipLevel);
+ markLevelDirty(static_cast<int>(mipLevel));
}
}
-gl::Error TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsigned int sourceSubresource,
- const gl::ImageIndex &index, const gl::Box &copyArea)
+gl::Error TextureStorage11::updateSubresourceLevel(const gl::Context *context,
+ const TextureHelper11 &srcTexture,
+ unsigned int sourceSubresource,
+ const gl::ImageIndex &index,
+ const gl::Box &copyArea)
{
- ASSERT(srcTexture);
+ ASSERT(srcTexture.valid());
- GLint level = index.mipIndex;
+ const GLint level = index.mipIndex;
- invalidateSwizzleCacheLevel(level);
+ markLevelDirty(level);
gl::Extents texSize(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level));
- bool fullCopy = copyArea.x == 0 &&
- copyArea.y == 0 &&
- copyArea.z == 0 &&
- copyArea.width == texSize.width &&
- copyArea.height == texSize.height &&
- copyArea.depth == texSize.depth;
+ bool fullCopy = copyArea.x == 0 && copyArea.y == 0 && copyArea.z == 0 &&
+ copyArea.width == texSize.width && copyArea.height == texSize.height &&
+ copyArea.depth == texSize.depth;
- ID3D11Resource *dstTexture = NULL;
- gl::Error error(GL_NO_ERROR);
+ const TextureHelper11 *dstTexture = nullptr;
- // If the zero-LOD workaround is active and we want to update a level greater than zero, then we should
- // update the mipmapped texture, even if mapmaps are currently disabled.
+ // If the zero-LOD workaround is active and we want to update a level greater than zero, then we
+ // should update the mipmapped texture, even if mapmaps are currently disabled.
if (index.mipIndex > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
- error = getMippedResource(&dstTexture);
+ ANGLE_TRY(getMippedResource(context, &dstTexture));
}
else
{
- error = getResource(&dstTexture);
- }
-
- if (error.isError())
- {
- return error;
+ ANGLE_TRY(getResource(context, &dstTexture));
}
unsigned int dstSubresource = getSubresourceIndex(index);
- ASSERT(dstTexture);
+ ASSERT(dstTexture->valid());
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat);
- if (!fullCopy && (dxgiFormatInfo.depthBits > 0 || dxgiFormatInfo.stencilBits > 0))
+ const d3d11::DXGIFormatSize &dxgiFormatSizeInfo =
+ d3d11::GetDXGIFormatSizeInfo(mFormatInfo.texFormat);
+ if (!fullCopy && mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN)
{
// CopySubresourceRegion cannot copy partial depth stencils, use the blitter instead
- Blit11 *blitter = mRenderer->getBlitter();
-
+ Blit11 *blitter = mRenderer->getBlitter();
return blitter->copyDepthStencil(srcTexture, sourceSubresource, copyArea, texSize,
- dstTexture, dstSubresource, copyArea, texSize,
- NULL);
+ *dstTexture, dstSubresource, copyArea, texSize, nullptr);
}
- else
- {
- D3D11_BOX srcBox;
- srcBox.left = copyArea.x;
- srcBox.top = copyArea.y;
- srcBox.right = copyArea.x + roundUp(static_cast<UINT>(copyArea.width), dxgiFormatInfo.blockWidth);
- srcBox.bottom = copyArea.y + roundUp(static_cast<UINT>(copyArea.height), dxgiFormatInfo.blockHeight);
- srcBox.front = copyArea.z;
- srcBox.back = copyArea.z + copyArea.depth;
- ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ D3D11_BOX srcBox;
+ srcBox.left = copyArea.x;
+ srcBox.top = copyArea.y;
+ srcBox.right =
+ copyArea.x + roundUp(static_cast<UINT>(copyArea.width), dxgiFormatSizeInfo.blockWidth);
+ srcBox.bottom =
+ copyArea.y + roundUp(static_cast<UINT>(copyArea.height), dxgiFormatSizeInfo.blockHeight);
+ srcBox.front = copyArea.z;
+ srcBox.back = copyArea.z + copyArea.depth;
- context->CopySubresourceRegion(dstTexture, dstSubresource, copyArea.x, copyArea.y, copyArea.z,
- srcTexture, sourceSubresource, fullCopy ? NULL : &srcBox);
- return gl::Error(GL_NO_ERROR);
- }
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ deviceContext->CopySubresourceRegion(dstTexture->get(), dstSubresource, copyArea.x, copyArea.y,
+ copyArea.z, srcTexture.get(), sourceSubresource,
+ fullCopy ? nullptr : &srcBox);
+ return gl::NoError();
}
-gl::Error TextureStorage11::copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource,
- const gl::ImageIndex &index, const gl::Box &region)
+gl::Error TextureStorage11::copySubresourceLevel(const gl::Context *context,
+ const TextureHelper11 &dstTexture,
+ unsigned int dstSubresource,
+ const gl::ImageIndex &index,
+ const gl::Box &region)
{
- ASSERT(dstTexture);
+ ASSERT(dstTexture.valid());
- ID3D11Resource *srcTexture = NULL;
- gl::Error error(GL_NO_ERROR);
+ const TextureHelper11 *srcTexture = nullptr;
- // If the zero-LOD workaround is active and we want to update a level greater than zero, then we should
- // update the mipmapped texture, even if mapmaps are currently disabled.
+ // If the zero-LOD workaround is active and we want to update a level greater than zero, then we
+ // should update the mipmapped texture, even if mapmaps are currently disabled.
if (index.mipIndex > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
- error = getMippedResource(&srcTexture);
+ ANGLE_TRY(getMippedResource(context, &srcTexture));
}
else
{
- error = getResource(&srcTexture);
+ ANGLE_TRY(getResource(context, &srcTexture));
}
- if (error.isError())
- {
- return error;
- }
-
- ASSERT(srcTexture);
+ ASSERT(srcTexture->valid());
unsigned int srcSubresource = getSubresourceIndex(index);
- ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
- // D3D11 can't perform partial CopySubresourceRegion on depth/stencil textures, so pSrcBox should be NULL.
+ // D3D11 can't perform partial CopySubresourceRegion on depth/stencil textures, so pSrcBox
+ // should be nullptr.
D3D11_BOX srcBox;
- D3D11_BOX *pSrcBox = NULL;
+ D3D11_BOX *pSrcBox = nullptr;
if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
{
- // However, D3D10Level9 doesn't always perform CopySubresourceRegion correctly unless the source box
- // is specified. This is okay, since we don't perform CopySubresourceRegion on depth/stencil
- // textures on 9_3.
- ASSERT(d3d11::GetDXGIFormatInfo(mTextureFormat).depthBits == 0);
- ASSERT(d3d11::GetDXGIFormatInfo(mTextureFormat).stencilBits == 0);
- srcBox.left = region.x;
- srcBox.right = region.x + region.width;
- srcBox.top = region.y;
- srcBox.bottom = region.y + region.height;
- srcBox.front = region.z;
- srcBox.back = region.z + region.depth;
- pSrcBox = &srcBox;
+ GLsizei width = region.width;
+ GLsizei height = region.height;
+ d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, nullptr);
+
+ // Keep srcbox as nullptr if we're dealing with tiny mips of compressed textures.
+ if (width == region.width && height == region.height)
+ {
+ // However, D3D10Level9 doesn't always perform CopySubresourceRegion correctly unless
+ // the source box is specified. This is okay, since we don't perform
+ // CopySubresourceRegion on depth/stencil textures on 9_3.
+ ASSERT(mFormatInfo.dsvFormat == DXGI_FORMAT_UNKNOWN);
+ srcBox.left = region.x;
+ srcBox.right = region.x + region.width;
+ srcBox.top = region.y;
+ srcBox.bottom = region.y + region.height;
+ srcBox.front = region.z;
+ srcBox.back = region.z + region.depth;
+ pSrcBox = &srcBox;
+ }
}
- context->CopySubresourceRegion(dstTexture, dstSubresource, region.x, region.y, region.z,
- srcTexture, srcSubresource, pSrcBox);
+ deviceContext->CopySubresourceRegion(dstTexture.get(), dstSubresource, region.x, region.y,
+ region.z, srcTexture->get(), srcSubresource, pSrcBox);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage11::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex)
+gl::Error TextureStorage11::generateMipmap(const gl::Context *context,
+ const gl::ImageIndex &sourceIndex,
+ const gl::ImageIndex &destIndex)
{
ASSERT(sourceIndex.layerIndex == destIndex.layerIndex);
- invalidateSwizzleCacheLevel(destIndex.mipIndex);
+ markLevelDirty(destIndex.mipIndex);
- RenderTargetD3D *source = NULL;
- gl::Error error = getRenderTarget(sourceIndex, &source);
- if (error.isError())
- {
- return error;
- }
+ RenderTargetD3D *source = nullptr;
+ ANGLE_TRY(getRenderTarget(context, sourceIndex, &source));
- RenderTargetD3D *dest = NULL;
- error = getRenderTarget(destIndex, &dest);
- if (error.isError())
- {
- return error;
- }
+ RenderTargetD3D *dest = nullptr;
+ ANGLE_TRY(getRenderTarget(context, destIndex, &dest));
- ID3D11ShaderResourceView *sourceSRV = GetAs<RenderTarget11>(source)->getShaderResourceView();
- ID3D11RenderTargetView *destRTV = GetAs<RenderTarget11>(dest)->getRenderTargetView();
+ RenderTarget11 *rt11 = GetAs<RenderTarget11>(source);
+ const d3d11::SharedSRV &sourceSRV = rt11->getBlitShaderResourceView();
+ const d3d11::RenderTargetView &destRTV = rt11->getRenderTargetView();
gl::Box sourceArea(0, 0, 0, source->getWidth(), source->getHeight(), source->getDepth());
gl::Extents sourceSize(source->getWidth(), source->getHeight(), source->getDepth());
@@ -557,90 +587,75 @@ gl::Error TextureStorage11::generateMipmap(const gl::ImageIndex &sourceIndex, co
gl::Extents destSize(dest->getWidth(), dest->getHeight(), dest->getDepth());
Blit11 *blitter = mRenderer->getBlitter();
- return blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize,
- NULL, gl::GetInternalFormatInfo(source->getInternalFormat()).format,
- GL_LINEAR, false);
+ GLenum format = gl::GetUnsizedFormat(source->getInternalFormat());
+ return blitter->copyTexture(context, sourceSRV, sourceArea, sourceSize, format, destRTV,
+ destArea, destSize, nullptr, format, GL_LINEAR, false, false,
+ false);
}
-void TextureStorage11::verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha)
+void TextureStorage11::verifySwizzleExists(const gl::SwizzleState &swizzleState)
{
- SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha);
for (unsigned int level = 0; level < mMipLevels; level++)
{
- ASSERT(mSwizzleCache[level] == swizzleTarget);
+ ASSERT(mSwizzleCache[level] == swizzleState);
}
}
void TextureStorage11::clearSRVCache()
{
- invalidateSwizzleCache();
-
- auto iter = mSrvCache.begin();
- while (iter != mSrvCache.end())
- {
- if (!iter->first.swizzle)
- {
- SafeRelease(iter->second);
- iter = mSrvCache.erase(iter);
- }
- else
- {
- iter++;
- }
- }
+ markDirty();
+ mSrvCache.clear();
- for (size_t level = 0; level < ArraySize(mLevelSRVs); level++)
+ for (size_t level = 0; level < mLevelSRVs.size(); level++)
{
- SafeRelease(mLevelSRVs[level]);
+ mLevelSRVs[level].reset();
+ mLevelBlitSRVs[level].reset();
}
}
-gl::Error TextureStorage11::copyToStorage(TextureStorage *destStorage)
+gl::Error TextureStorage11::copyToStorage(const gl::Context *context, TextureStorage *destStorage)
{
ASSERT(destStorage);
- ID3D11Resource *sourceResouce = NULL;
- gl::Error error = getResource(&sourceResouce);
- if (error.isError())
- {
- return error;
- }
+ const TextureHelper11 *sourceResouce = nullptr;
+ ANGLE_TRY(getResource(context, &sourceResouce));
- TextureStorage11 *dest11 = GetAs<TextureStorage11>(destStorage);
- ID3D11Resource *destResource = NULL;
- error = dest11->getResource(&destResource);
- if (error.isError())
- {
- return error;
- }
+ TextureStorage11 *dest11 = GetAs<TextureStorage11>(destStorage);
+ const TextureHelper11 *destResource = nullptr;
+ ANGLE_TRY(dest11->getResource(context, &destResource));
ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
- immediateContext->CopyResource(destResource, sourceResouce);
+ immediateContext->CopyResource(destResource->get(), sourceResouce->get());
- dest11->invalidateSwizzleCache();
+ dest11->markDirty();
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type,
- const gl::PixelUnpackState &unpack, const uint8_t *pixelData)
+gl::Error TextureStorage11::setData(const gl::Context *context,
+ const gl::ImageIndex &index,
+ ImageD3D *image,
+ const gl::Box *destBox,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixelData)
{
ASSERT(!image->isDirty());
- ID3D11Resource *resource = NULL;
- gl::Error error = getResource(&resource);
- if (error.isError())
- {
- return error;
- }
- ASSERT(resource);
+ markLevelDirty(index.mipIndex);
+
+ const TextureHelper11 *resource = nullptr;
+ ANGLE_TRY(getResource(context, &resource));
+ ASSERT(resource && resource->valid());
UINT destSubresource = getSubresourceIndex(index);
- const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(image->getInternalFormat());
+ const gl::InternalFormat &internalFormatInfo =
+ gl::GetInternalFormatInfo(image->getInternalFormat(), type);
- gl::Box levelBox(0, 0, 0, getLevelWidth(index.mipIndex), getLevelHeight(index.mipIndex), getLevelDepth(index.mipIndex));
- bool fullUpdate = (destBox == NULL || *destBox == levelBox);
+ gl::Box levelBox(0, 0, 0, getLevelWidth(index.mipIndex), getLevelHeight(index.mipIndex),
+ getLevelDepth(index.mipIndex));
+ bool fullUpdate = (destBox == nullptr || *destBox == levelBox);
ASSERT(internalFormatInfo.depthBits == 0 || fullUpdate);
// TODO(jmadill): Handle compressed formats
@@ -649,36 +664,44 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ImageD3D *image
// with compressed formats in the calling logic.
ASSERT(!internalFormatInfo.compressed);
- int width = destBox ? destBox->width : static_cast<int>(image->getWidth());
- int height = destBox ? destBox->height : static_cast<int>(image->getHeight());
- int depth = destBox ? destBox->depth : static_cast<int>(image->getDepth());
- UINT srcRowPitch = internalFormatInfo.computeRowPitch(type, width, unpack.alignment, unpack.rowLength);
- UINT srcDepthPitch = internalFormatInfo.computeDepthPitch(type, width, height, unpack.alignment,
- unpack.rowLength, unpack.imageHeight);
- GLsizei srcSkipBytes = internalFormatInfo.computeSkipPixels(
- srcRowPitch, srcDepthPitch, unpack.skipImages, unpack.skipRows, unpack.skipPixels);
-
- const d3d11::TextureFormat &d3d11Format = d3d11::GetTextureFormatInfo(image->getInternalFormat(), mRenderer->getRenderer11DeviceCaps());
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3d11Format.texFormat);
-
- size_t outputPixelSize = dxgiFormatInfo.pixelBytes;
+ const int imageWidth = static_cast<int>(image->getWidth());
+ const int width = destBox ? destBox->width : imageWidth;
+ const int imageHeight = static_cast<int>(image->getHeight());
+ const int height = destBox ? destBox->height : imageHeight;
+ const int imageDepth = static_cast<int>(image->getDepth());
+ const int depth = destBox ? destBox->depth : imageDepth;
+ if (imageWidth < width || imageHeight < height || imageDepth < depth)
+ fullUpdate = true;
+ GLuint srcRowPitch = 0;
+ ANGLE_TRY_RESULT(
+ internalFormatInfo.computeRowPitch(type, width, unpack.alignment, unpack.rowLength),
+ srcRowPitch);
+ GLuint srcDepthPitch = 0;
+ ANGLE_TRY_RESULT(internalFormatInfo.computeDepthPitch(height, unpack.imageHeight, srcRowPitch),
+ srcDepthPitch);
+ GLuint srcSkipBytes = 0;
+ ANGLE_TRY_RESULT(
+ internalFormatInfo.computeSkipBytes(srcRowPitch, srcDepthPitch, unpack, index.is3D()),
+ srcSkipBytes);
+
+ const d3d11::Format &d3d11Format =
+ d3d11::Format::Get(image->getInternalFormat(), mRenderer->getRenderer11DeviceCaps());
+ const d3d11::DXGIFormatSize &dxgiFormatInfo =
+ d3d11::GetDXGIFormatSizeInfo(d3d11Format.texFormat);
+
+ const size_t outputPixelSize = dxgiFormatInfo.pixelBytes;
UINT bufferRowPitch = static_cast<unsigned int>(outputPixelSize) * width;
UINT bufferDepthPitch = bufferRowPitch * height;
- size_t neededSize = bufferDepthPitch * depth;
- MemoryBuffer *conversionBuffer = nullptr;
+ const size_t neededSize = bufferDepthPitch * depth;
+ angle::MemoryBuffer *conversionBuffer = nullptr;
const uint8_t *data = nullptr;
- d3d11::LoadImageFunctionInfo loadFunctionInfo = d3d11Format.loadFunctions.at(type);
+ LoadImageFunctionInfo loadFunctionInfo = d3d11Format.getLoadFunctions()(type);
if (loadFunctionInfo.requiresConversion)
{
- error = mRenderer->getScratchMemoryBuffer(neededSize, &conversionBuffer);
- if (error.isError())
- {
- return error;
- }
-
+ ANGLE_TRY(mRenderer->getScratchMemoryBuffer(neededSize, &conversionBuffer));
loadFunctionInfo.loadFunction(width, height, depth, pixelData + srcSkipBytes, srcRowPitch,
srcDepthPitch, conversionBuffer->data(), bufferRowPitch,
bufferDepthPitch);
@@ -698,264 +721,233 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ImageD3D *image
ASSERT(destBox);
D3D11_BOX destD3DBox;
- destD3DBox.left = destBox->x;
- destD3DBox.right = destBox->x + destBox->width;
- destD3DBox.top = destBox->y;
+ destD3DBox.left = destBox->x;
+ destD3DBox.right = destBox->x + destBox->width;
+ destD3DBox.top = destBox->y;
destD3DBox.bottom = destBox->y + destBox->height;
- destD3DBox.front = destBox->z;
- destD3DBox.back = destBox->z + destBox->depth;
+ destD3DBox.front = destBox->z;
+ destD3DBox.back = destBox->z + destBox->depth;
- immediateContext->UpdateSubresource(resource, destSubresource, &destD3DBox, data,
+ immediateContext->UpdateSubresource(resource->get(), destSubresource, &destD3DBox, data,
bufferRowPitch, bufferDepthPitch);
}
else
{
- immediateContext->UpdateSubresource(resource, destSubresource, NULL, data, bufferRowPitch,
- bufferDepthPitch);
+ immediateContext->UpdateSubresource(resource->get(), destSubresource, nullptr, data,
+ bufferRowPitch, bufferDepthPitch);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
+}
+
+gl::ErrorOrResult<TextureStorage11::DropStencil> TextureStorage11::ensureDropStencilTexture(
+ const gl::Context *context)
+{
+ UNIMPLEMENTED();
+ return gl::InternalError() << "Drop stencil texture not implemented.";
}
TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain)
- : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, 0),
+ : TextureStorage11(renderer,
+ D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
+ 0,
+ swapchain->getRenderTargetInternalFormat()),
mTexture(swapchain->getOffscreenTexture()),
- mLevelZeroTexture(NULL),
- mLevelZeroRenderTarget(NULL),
+ mLevelZeroTexture(),
+ mLevelZeroRenderTarget(nullptr),
mUseLevelZeroTexture(false),
- mSwizzleTexture(NULL)
+ mSwizzleTexture()
{
- mTexture->AddRef();
-
for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
- mAssociatedImages[i] = NULL;
- mRenderTarget[i] = NULL;
- mSwizzleRenderTargets[i] = NULL;
+ mAssociatedImages[i] = nullptr;
+ mRenderTarget[i] = nullptr;
}
D3D11_TEXTURE2D_DESC texDesc;
- mTexture->GetDesc(&texDesc);
- mMipLevels = texDesc.MipLevels;
- mTextureFormat = texDesc.Format;
- mTextureWidth = texDesc.Width;
+ mTexture.getDesc(&texDesc);
+ mMipLevels = texDesc.MipLevels;
+ mTextureWidth = texDesc.Width;
mTextureHeight = texDesc.Height;
- mTextureDepth = 1;
-
- mInternalFormat = swapchain->GetRenderTargetInternalFormat();
-
- ID3D11ShaderResourceView *srv = swapchain->getRenderTargetShaderResource();
- D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
- srv->GetDesc(&srvDesc);
- mShaderResourceFormat = srvDesc.Format;
-
- ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget();
- D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- offscreenRTV->GetDesc(&rtvDesc);
- mRenderTargetFormat = rtvDesc.Format;
-
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat);
- const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(dxgiFormatInfo.internalFormat, mRenderer->getRenderer11DeviceCaps());
- mSwizzleTextureFormat = formatInfo.swizzleTexFormat;
- mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
- mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
-
- mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
-}
-
-TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly)
- : TextureStorage11(renderer,
- GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
- GetTextureMiscFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget, levels)),
- mTexture(NULL),
- mLevelZeroTexture(NULL),
- mLevelZeroRenderTarget(NULL),
- mUseLevelZeroTexture(false),
- mSwizzleTexture(NULL)
+ mTextureDepth = 1;
+ mHasKeyedMutex = (texDesc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) != 0;
+}
+
+TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer,
+ GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ bool hintLevelZeroOnly)
+ : TextureStorage11(
+ renderer,
+ GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
+ GetTextureMiscFlags(internalformat,
+ renderer->getRenderer11DeviceCaps(),
+ renderTarget,
+ levels),
+ internalformat),
+ mTexture(),
+ mHasKeyedMutex(false),
+ mLevelZeroTexture(),
+ mLevelZeroRenderTarget(nullptr),
+ mUseLevelZeroTexture(hintLevelZeroOnly && levels > 1),
+ mSwizzleTexture()
{
for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
- mAssociatedImages[i] = NULL;
- mRenderTarget[i] = NULL;
- mSwizzleRenderTargets[i] = NULL;
+ mAssociatedImages[i] = nullptr;
+ mRenderTarget[i] = nullptr;
}
- mInternalFormat = internalformat;
-
- const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getRenderer11DeviceCaps());
- mTextureFormat = formatInfo.texFormat;
- mShaderResourceFormat = formatInfo.srvFormat;
- mDepthStencilFormat = formatInfo.dsvFormat;
- mRenderTargetFormat = formatInfo.rtvFormat;
- mSwizzleTextureFormat = formatInfo.swizzleTexFormat;
- mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
- mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
-
- d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel);
- mMipLevels = mTopLevel + levels;
- mTextureWidth = width;
+ d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel);
+ mMipLevels = mTopLevel + levels;
+ mTextureWidth = width;
mTextureHeight = height;
- mTextureDepth = 1;
+ mTextureDepth = 1;
- if (hintLevelZeroOnly && levels > 1)
- {
- //The LevelZeroOnly hint should only be true if the zero max LOD workaround is active.
- ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround);
- mUseLevelZeroTexture = true;
- }
+ // The LevelZeroOnly hint should only be true if the zero max LOD workaround is active.
+ ASSERT(!mUseLevelZeroTexture || mRenderer->getWorkarounds().zeroMaxLodWorkaround);
}
-TextureStorage11_2D::~TextureStorage11_2D()
+gl::Error TextureStorage11_2D::onDestroy(const gl::Context *context)
{
for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
- if (mAssociatedImages[i] != NULL)
+ if (mAssociatedImages[i] != nullptr)
{
- bool imageAssociationCorrect = mAssociatedImages[i]->isAssociatedStorageValid(this);
- ASSERT(imageAssociationCorrect);
+ mAssociatedImages[i]->verifyAssociatedStorageValid(this);
- if (imageAssociationCorrect)
- {
- // We must let the Images recover their data before we delete it from the TextureStorage.
- gl::Error error = mAssociatedImages[i]->recoverFromAssociatedStorage();
- if (error.isError())
- {
- // TODO: Find a way to report this back to the context
- }
- }
+ // We must let the Images recover their data before we delete it from the
+ // TextureStorage.
+ ANGLE_TRY(mAssociatedImages[i]->recoverFromAssociatedStorage(context));
}
}
- SafeRelease(mTexture);
- SafeRelease(mSwizzleTexture);
-
- SafeRelease(mLevelZeroTexture);
- SafeDelete(mLevelZeroRenderTarget);
-
- for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ if (mHasKeyedMutex)
{
- SafeDelete(mRenderTarget[i]);
- SafeRelease(mSwizzleRenderTargets[i]);
+ // If the keyed mutex is released that will unbind it and cause the state cache to become
+ // desynchronized.
+ mRenderer->getStateManager()->invalidateBoundViews();
}
+
+ // Invalidate RenderTargets.
+ InvalidateRenderTargetContainer(context, &mRenderTarget);
+ InvalidateRenderTarget(context, mLevelZeroRenderTarget.get());
+
+ return gl::NoError();
+}
+
+TextureStorage11_2D::~TextureStorage11_2D()
+{
}
-gl::Error TextureStorage11_2D::copyToStorage(TextureStorage *destStorage)
+gl::Error TextureStorage11_2D::copyToStorage(const gl::Context *context,
+ TextureStorage *destStorage)
{
ASSERT(destStorage);
- TextureStorage11_2D *dest11 = GetAs<TextureStorage11_2D>(destStorage);
+ TextureStorage11_2D *dest11 = GetAs<TextureStorage11_2D>(destStorage);
+ ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
- ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
-
- // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the corresponding textures in destStorage.
- if (mTexture)
+ // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the
+ // corresponding textures in destStorage.
+ if (mTexture.valid())
{
- gl::Error error = dest11->useLevelZeroWorkaroundTexture(false);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, false));
- ID3D11Resource *destResource = NULL;
- error = dest11->getResource(&destResource);
- if (error.isError())
- {
- return error;
- }
+ const TextureHelper11 *destResource = nullptr;
+ ANGLE_TRY(dest11->getResource(context, &destResource));
- immediateContext->CopyResource(destResource, mTexture);
+ immediateContext->CopyResource(destResource->get(), mTexture.get());
}
- if (mLevelZeroTexture)
+ if (mLevelZeroTexture.valid())
{
- gl::Error error = dest11->useLevelZeroWorkaroundTexture(true);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, true));
- ID3D11Resource *destResource = NULL;
- error = dest11->getResource(&destResource);
- if (error.isError())
- {
- return error;
- }
+ const TextureHelper11 *destResource = nullptr;
+ ANGLE_TRY(dest11->getResource(context, &destResource));
- immediateContext->CopyResource(destResource, mLevelZeroTexture);
+ immediateContext->CopyResource(destResource->get(), mLevelZeroTexture.get());
}
+
+ return gl::NoError();
}
- else
- {
- ID3D11Resource *sourceResouce = NULL;
- gl::Error error = getResource(&sourceResouce);
- if (error.isError())
- {
- return error;
- }
- ID3D11Resource *destResource = NULL;
- error = dest11->getResource(&destResource);
- if (error.isError())
- {
- return error;
- }
+ const TextureHelper11 *sourceResouce = nullptr;
+ ANGLE_TRY(getResource(context, &sourceResouce));
- ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
- immediateContext->CopyResource(destResource, sourceResouce);
- }
+ const TextureHelper11 *destResource = nullptr;
+ ANGLE_TRY(dest11->getResource(context, &destResource));
- dest11->invalidateSwizzleCache();
+ immediateContext->CopyResource(destResource->get(), sourceResouce->get());
+ dest11->markDirty();
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage11_2D::useLevelZeroWorkaroundTexture(bool useLevelZeroTexture)
+gl::Error TextureStorage11_2D::useLevelZeroWorkaroundTexture(const gl::Context *context,
+ bool useLevelZeroTexture)
{
+ bool lastSetting = mUseLevelZeroTexture;
+
if (useLevelZeroTexture && mMipLevels > 1)
{
- if (!mUseLevelZeroTexture && mTexture)
+ if (!mUseLevelZeroTexture && mTexture.valid())
{
- gl::Error error = ensureTextureExists(1);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(ensureTextureExists(1));
// Pull data back from the mipped texture if necessary.
- ASSERT(mLevelZeroTexture);
- ID3D11DeviceContext *context = mRenderer->getDeviceContext();
- context->CopySubresourceRegion(mLevelZeroTexture, 0, 0, 0, 0, mTexture, 0, NULL);
+ ASSERT(mLevelZeroTexture.valid());
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ deviceContext->CopySubresourceRegion(mLevelZeroTexture.get(), 0, 0, 0, 0,
+ mTexture.get(), 0, nullptr);
}
mUseLevelZeroTexture = true;
}
else
{
- if (mUseLevelZeroTexture && mLevelZeroTexture)
+ if (mUseLevelZeroTexture && mLevelZeroTexture.valid())
{
- gl::Error error = ensureTextureExists(mMipLevels);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(ensureTextureExists(mMipLevels));
// Pull data back from the level zero texture if necessary.
- ASSERT(mTexture);
- ID3D11DeviceContext *context = mRenderer->getDeviceContext();
- context->CopySubresourceRegion(mTexture, 0, 0, 0, 0, mLevelZeroTexture, 0, NULL);
+ ASSERT(mTexture.valid());
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ deviceContext->CopySubresourceRegion(mTexture.get(), 0, 0, 0, 0,
+ mLevelZeroTexture.get(), 0, nullptr);
}
mUseLevelZeroTexture = false;
}
- return gl::Error(GL_NO_ERROR);
+ if (lastSetting != mUseLevelZeroTexture)
+ {
+ // Mark everything as dirty to be conservative.
+ if (mLevelZeroRenderTarget)
+ {
+ mLevelZeroRenderTarget->signalDirty(context);
+ }
+ for (auto &renderTarget : mRenderTarget)
+ {
+ if (renderTarget)
+ {
+ renderTarget->signalDirty(context);
+ }
+ }
+ }
+
+ return gl::NoError();
}
-void TextureStorage11_2D::associateImage(Image11* image, const gl::ImageIndex &index)
+void TextureStorage11_2D::associateImage(Image11 *image, const gl::ImageIndex &index)
{
- GLint level = index.mipIndex;
+ const GLint level = index.mipIndex;
ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
@@ -965,539 +957,569 @@ void TextureStorage11_2D::associateImage(Image11* image, const gl::ImageIndex &i
}
}
-bool TextureStorage11_2D::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage)
+void TextureStorage11_2D::verifyAssociatedImageValid(const gl::ImageIndex &index,
+ Image11 *expectedImage)
{
- GLint level = index.mipIndex;
+ const GLint level = index.mipIndex;
- if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
- {
- // This validation check should never return false. It means the Image/TextureStorage association is broken.
- bool retValue = (mAssociatedImages[level] == expectedImage);
- ASSERT(retValue);
- return retValue;
- }
-
- return false;
+ ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ // This validation check should never return false. It means the Image/TextureStorage
+ // association is broken.
+ ASSERT(mAssociatedImages[level] == expectedImage);
}
// disassociateImage allows an Image to end its association with a Storage.
-void TextureStorage11_2D::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage)
+void TextureStorage11_2D::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage)
{
- GLint level = index.mipIndex;
+ const GLint level = index.mipIndex;
ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
-
- if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
- {
- ASSERT(mAssociatedImages[level] == expectedImage);
-
- if (mAssociatedImages[level] == expectedImage)
- {
- mAssociatedImages[level] = NULL;
- }
- }
+ ASSERT(mAssociatedImages[level] == expectedImage);
+ mAssociatedImages[level] = nullptr;
}
-// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association.
-gl::Error TextureStorage11_2D::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage)
+// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
+// recover its data before ending the association.
+gl::Error TextureStorage11_2D::releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage)
{
- GLint level = index.mipIndex;
+ const GLint level = index.mipIndex;
ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
{
// No need to let the old Image recover its data, if it is also the incoming Image.
- if (mAssociatedImages[level] != NULL && mAssociatedImages[level] != incomingImage)
+ if (mAssociatedImages[level] != nullptr && mAssociatedImages[level] != incomingImage)
{
- // Ensure that the Image is still associated with this TextureStorage. This should be true.
- bool imageAssociationCorrect = mAssociatedImages[level]->isAssociatedStorageValid(this);
- ASSERT(imageAssociationCorrect);
+ // Ensure that the Image is still associated with this TextureStorage.
+ mAssociatedImages[level]->verifyAssociatedStorageValid(this);
- if (imageAssociationCorrect)
- {
- // Force the image to recover from storage before its data is overwritten.
- // This will reset mAssociatedImages[level] to NULL too.
- gl::Error error = mAssociatedImages[level]->recoverFromAssociatedStorage();
- if (error.isError())
- {
- return error;
- }
- }
+ // Force the image to recover from storage before its data is overwritten.
+ // This will reset mAssociatedImages[level] to nullptr too.
+ ANGLE_TRY(mAssociatedImages[level]->recoverFromAssociatedStorage(context));
}
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage11_2D::getResource(ID3D11Resource **outResource)
+gl::Error TextureStorage11_2D::getResource(const gl::Context *context,
+ const TextureHelper11 **outResource)
{
if (mUseLevelZeroTexture && mMipLevels > 1)
{
- gl::Error error = ensureTextureExists(1);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(ensureTextureExists(1));
- *outResource = mLevelZeroTexture;
- return gl::Error(GL_NO_ERROR);
+ *outResource = &mLevelZeroTexture;
+ return gl::NoError();
}
- else
- {
- gl::Error error = ensureTextureExists(mMipLevels);
- if (error.isError())
- {
- return error;
- }
- *outResource = mTexture;
- return gl::Error(GL_NO_ERROR);
- }
+ ANGLE_TRY(ensureTextureExists(mMipLevels));
+
+ *outResource = &mTexture;
+ return gl::NoError();
}
-gl::Error TextureStorage11_2D::getMippedResource(ID3D11Resource **outResource)
+gl::Error TextureStorage11_2D::getMippedResource(const gl::Context *context,
+ const TextureHelper11 **outResource)
{
// This shouldn't be called unless the zero max LOD workaround is active.
ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround);
- gl::Error error = ensureTextureExists(mMipLevels);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(ensureTextureExists(mMipLevels));
- *outResource = mTexture;
- return gl::Error(GL_NO_ERROR);
+ *outResource = &mTexture;
+ return gl::NoError();
}
gl::Error TextureStorage11_2D::ensureTextureExists(int mipLevels)
{
// If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture.
- bool useLevelZeroTexture = mRenderer->getWorkarounds().zeroMaxLodWorkaround ? (mipLevels == 1) && (mMipLevels > 1) : false;
- ID3D11Texture2D **outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture;
+ bool useLevelZeroTexture = mRenderer->getWorkarounds().zeroMaxLodWorkaround
+ ? (mipLevels == 1) && (mMipLevels > 1)
+ : false;
+ TextureHelper11 *outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture;
// if the width or height is not positive this should be treated as an incomplete texture
// we handle that here by skipping the d3d texture creation
- if (*outputTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0)
+ if (!outputTexture->valid() && mTextureWidth > 0 && mTextureHeight > 0)
{
ASSERT(mipLevels > 0);
- ID3D11Device *device = mRenderer->getDevice();
-
D3D11_TEXTURE2D_DESC desc;
- desc.Width = mTextureWidth; // Compressed texture size constraints?
- desc.Height = mTextureHeight;
- desc.MipLevels = mipLevels;
- desc.ArraySize = 1;
- desc.Format = mTextureFormat;
- desc.SampleDesc.Count = 1;
+ desc.Width = mTextureWidth; // Compressed texture size constraints?
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mipLevels;
+ desc.ArraySize = 1;
+ desc.Format = mFormatInfo.texFormat;
+ desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.BindFlags = getBindFlags();
- desc.CPUAccessFlags = 0;
- desc.MiscFlags = getMiscFlags();
-
- HRESULT result = device->CreateTexture2D(&desc, NULL, outputTexture);
-
- // this can happen from windows TDR
- if (d3d11::isDeviceLostError(result))
- {
- mRenderer->notifyDeviceLost();
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D texture storage, result: 0x%X.", result);
- }
- else if (FAILED(result))
- {
- ASSERT(result == E_OUTOFMEMORY);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D texture storage, result: 0x%X.", result);
- }
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = getBindFlags();
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = getMiscFlags();
- d3d11::SetDebugName(*outputTexture, "TexStorage2D.Texture");
+ ANGLE_TRY(mRenderer->allocateTexture(desc, mFormatInfo, outputTexture));
+ outputTexture->setDebugName("TexStorage2D.Texture");
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+gl::Error TextureStorage11_2D::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT)
{
ASSERT(!index.hasLayer());
- int level = index.mipIndex;
+ const int level = index.mipIndex;
ASSERT(level >= 0 && level < getLevelCount());
- // In GL ES 2.0, the application can only render to level zero of the texture (Section 4.4.3 of the GLES 2.0 spec, page 113 of version 2.0.25).
- // Other parts of TextureStorage11_2D could create RTVs on non-zero levels of the texture (e.g. generateMipmap).
- // On Feature Level 9_3, this is unlikely to be useful. The renderer can't create SRVs on the individual levels of the texture,
- // so methods like generateMipmap can't do anything useful with non-zero-level RTVs.
- // Therefore if level > 0 on 9_3 then there's almost certainly something wrong.
- ASSERT(!(mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3 && level > 0));
-
- if (!mRenderTarget[level])
+ // In GL ES 2.0, the application can only render to level zero of the texture (Section 4.4.3 of
+ // the GLES 2.0 spec, page 113 of version 2.0.25). Other parts of TextureStorage11_2D could
+ // create RTVs on non-zero levels of the texture (e.g. generateMipmap).
+ // On Feature Level 9_3, this is unlikely to be useful. The renderer can't create SRVs on the
+ // individual levels of the texture, so methods like generateMipmap can't do anything useful
+ // with non-zero-level RTVs. Therefore if level > 0 on 9_3 then there's almost certainly
+ // something wrong.
+ ASSERT(
+ !(mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3 && level > 0));
+ ASSERT(outRT);
+ if (mRenderTarget[level])
{
- ID3D11Resource *texture = NULL;
- gl::Error error = getResource(&texture);
- if (error.isError())
- {
- return error;
- }
-
- ID3D11ShaderResourceView *srv = NULL;
- error = getSRVLevel(level, &srv);
- if (error.isError())
- {
- return error;
- }
-
- if (mUseLevelZeroTexture)
- {
- if (!mLevelZeroRenderTarget)
- {
- ID3D11Device *device = mRenderer->getDevice();
-
- D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- rtvDesc.Format = mRenderTargetFormat;
- rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
- rtvDesc.Texture2D.MipSlice = mTopLevel + level;
-
- ID3D11RenderTargetView *rtv;
- HRESULT result = device->CreateRenderTargetView(mLevelZeroTexture, &rtvDesc, &rtv);
+ *outRT = mRenderTarget[level].get();
+ return gl::NoError();
+ }
- if (result == E_OUTOFMEMORY)
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result);
- }
- ASSERT(SUCCEEDED(result));
+ if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ ASSERT(index.mipIndex == 0);
+ ANGLE_TRY(useLevelZeroWorkaroundTexture(context, true));
+ }
- mLevelZeroRenderTarget = new TextureRenderTarget11(rtv, mLevelZeroTexture, NULL, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0);
+ const TextureHelper11 *texture = nullptr;
+ ANGLE_TRY(getResource(context, &texture));
- // RenderTarget will take ownership of these resources
- SafeRelease(rtv);
- }
+ const d3d11::SharedSRV *srv = nullptr;
+ ANGLE_TRY(getSRVLevel(context, level, false, &srv));
- ASSERT(outRT);
- *outRT = mLevelZeroRenderTarget;
- return gl::Error(GL_NO_ERROR);
- }
+ const d3d11::SharedSRV *blitSRV = nullptr;
+ ANGLE_TRY(getSRVLevel(context, level, true, &blitSRV));
- if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
+ if (mUseLevelZeroTexture)
+ {
+ if (!mLevelZeroRenderTarget)
{
- ID3D11Device *device = mRenderer->getDevice();
-
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- rtvDesc.Format = mRenderTargetFormat;
- rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ rtvDesc.Format = mFormatInfo.rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
rtvDesc.Texture2D.MipSlice = mTopLevel + level;
- ID3D11RenderTargetView *rtv;
- HRESULT result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv);
+ d3d11::RenderTargetView rtv;
+ ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mLevelZeroTexture.get(), &rtv));
- ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result);
- }
-
- mRenderTarget[level] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0);
-
- // RenderTarget will take ownership of these resources
- SafeRelease(rtv);
+ mLevelZeroRenderTarget.reset(new TextureRenderTarget11(
+ std::move(rtv), mLevelZeroTexture, d3d11::SharedSRV(), d3d11::SharedSRV(),
+ mFormatInfo.internalFormat, getFormatSet(), getLevelWidth(level),
+ getLevelHeight(level), 1, 0));
}
- else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
- {
- ID3D11Device *device = mRenderer->getDevice();
- D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
- dsvDesc.Format = mDepthStencilFormat;
- dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
- dsvDesc.Texture2D.MipSlice = mTopLevel + level;
- dsvDesc.Flags = 0;
+ *outRT = mLevelZeroRenderTarget.get();
+ return gl::NoError();
+ }
- ID3D11DepthStencilView *dsv;
- HRESULT result = device->CreateDepthStencilView(texture, &dsvDesc, &dsv);
+ if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mFormatInfo.rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ rtvDesc.Texture2D.MipSlice = mTopLevel + level;
- ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY,"Failed to create internal depth stencil view for texture storage, result: 0x%X.", result);
- }
+ d3d11::RenderTargetView rtv;
+ ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture->get(), &rtv));
- mRenderTarget[level] = new TextureRenderTarget11(dsv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0);
+ mRenderTarget[level].reset(new TextureRenderTarget11(
+ std::move(rtv), *texture, *srv, *blitSRV, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(level), getLevelHeight(level), 1, 0));
- // RenderTarget will take ownership of these resources
- SafeRelease(dsv);
- }
- else
- {
- UNREACHABLE();
- }
+ *outRT = mRenderTarget[level].get();
+ return gl::NoError();
}
- ASSERT(outRT);
- *outRT = mRenderTarget[level];
- return gl::Error(GL_NO_ERROR);
+ ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
+
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+ dsvDesc.Format = mFormatInfo.dsvFormat;
+ dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+ dsvDesc.Texture2D.MipSlice = mTopLevel + level;
+ dsvDesc.Flags = 0;
+
+ d3d11::DepthStencilView dsv;
+ ANGLE_TRY(mRenderer->allocateResource(dsvDesc, texture->get(), &dsv));
+
+ mRenderTarget[level].reset(new TextureRenderTarget11(
+ std::move(dsv), *texture, *srv, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(level), getLevelHeight(level), 1, 0));
+
+ *outRT = mRenderTarget[level].get();
+ return gl::NoError();
}
-gl::Error TextureStorage11_2D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
- ID3D11ShaderResourceView **outSRV) const
+gl::Error TextureStorage11_2D::createSRV(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV)
{
ASSERT(outSRV);
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
- srvDesc.Format = format;
- srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ srvDesc.Format = format;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel;
- srvDesc.Texture2D.MipLevels = mipLevels;
+ srvDesc.Texture2D.MipLevels = mipLevels;
- ID3D11Resource *srvTexture = texture;
+ const TextureHelper11 *srvTexture = &texture;
if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
ASSERT(mTopLevel == 0);
ASSERT(baseLevel == 0);
- // This code also assumes that the incoming texture equals either mLevelZeroTexture or mTexture.
+ // This code also assumes that the incoming texture equals either mLevelZeroTexture or
+ // mTexture.
if (mipLevels == 1 && mMipLevels > 1)
{
// We must use a SRV on the level-zero-only texture.
- ASSERT(mLevelZeroTexture != NULL && texture == mLevelZeroTexture);
- srvTexture = mLevelZeroTexture;
+ ANGLE_TRY(ensureTextureExists(1));
+ srvTexture = &mLevelZeroTexture;
}
else
{
ASSERT(mipLevels == static_cast<int>(mMipLevels));
- ASSERT(mTexture != NULL && texture == mTexture);
- srvTexture = mTexture;
+ ASSERT(mTexture.valid() && texture == mTexture);
+ srvTexture = &mTexture;
}
}
- ID3D11Device *device = mRenderer->getDevice();
- HRESULT result = device->CreateShaderResourceView(srvTexture, &srvDesc, outSRV);
-
- ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal texture storage SRV, result: 0x%X.", result);
- }
-
- d3d11::SetDebugName(*outSRV, "TexStorage2D.SRV");
+ ANGLE_TRY(mRenderer->allocateResource(srvDesc, srvTexture->get(), outSRV));
+ outSRV->setDebugName("TexStorage2D.SRV");
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage11_2D::getSwizzleTexture(ID3D11Resource **outTexture)
+gl::Error TextureStorage11_2D::getSwizzleTexture(const TextureHelper11 **outTexture)
{
ASSERT(outTexture);
- if (!mSwizzleTexture)
+ if (!mSwizzleTexture.valid())
{
- ID3D11Device *device = mRenderer->getDevice();
+ const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
D3D11_TEXTURE2D_DESC desc;
- desc.Width = mTextureWidth;
- desc.Height = mTextureHeight;
- desc.MipLevels = mMipLevels;
- desc.ArraySize = 1;
- desc.Format = mSwizzleTextureFormat;
- desc.SampleDesc.Count = 1;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mMipLevels;
+ desc.ArraySize = 1;
+ desc.Format = format.texFormat;
+ desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
- desc.CPUAccessFlags = 0;
- desc.MiscFlags = 0;
-
- HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture);
-
- ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle texture, result: 0x%X.", result);
- }
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = 0;
- d3d11::SetDebugName(mSwizzleTexture, "TexStorage2D.SwizzleTexture");
+ ANGLE_TRY(mRenderer->allocateTexture(desc, format, &mSwizzleTexture));
+ mSwizzleTexture.setDebugName("TexStorage2D.SwizzleTexture");
}
- *outTexture = mSwizzleTexture;
- return gl::Error(GL_NO_ERROR);
+ *outTexture = &mSwizzleTexture;
+ return gl::NoError();
}
-gl::Error TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV)
+gl::Error TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel,
+ const d3d11::RenderTargetView **outRTV)
{
ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
ASSERT(outRTV);
- if (!mSwizzleRenderTargets[mipLevel])
+ if (!mSwizzleRenderTargets[mipLevel].valid())
{
- ID3D11Resource *swizzleTexture = NULL;
- gl::Error error = getSwizzleTexture(&swizzleTexture);
- if (error.isError())
- {
- return error;
- }
-
- ID3D11Device *device = mRenderer->getDevice();
+ const TextureHelper11 *swizzleTexture = nullptr;
+ ANGLE_TRY(getSwizzleTexture(&swizzleTexture));
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- rtvDesc.Format = mSwizzleRenderTargetFormat;
- rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ rtvDesc.Format =
+ mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel;
- HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]);
-
- ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle render target view, result: 0x%X.", result);
- }
+ ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture.get(),
+ &mSwizzleRenderTargets[mipLevel]));
}
- *outRTV = mSwizzleRenderTargets[mipLevel];
- return gl::Error(GL_NO_ERROR);
+ *outRTV = &mSwizzleRenderTargets[mipLevel];
+ return gl::NoError();
}
-TextureStorage11_EGLImage::TextureStorage11_EGLImage(Renderer11 *renderer, EGLImageD3D *eglImage)
- : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, 0),
- mImage(eglImage),
- mCurrentRenderTarget(0),
- mSwizzleTexture(nullptr),
- mSwizzleRenderTargets(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS, nullptr)
+gl::ErrorOrResult<TextureStorage11::DropStencil> TextureStorage11_2D::ensureDropStencilTexture(
+ const gl::Context *context)
{
- RenderTargetD3D *renderTargetD3D = nullptr;
- mImage->getRenderTarget(&renderTargetD3D);
- RenderTarget11 *renderTarget11 = GetAs<RenderTarget11>(renderTargetD3D);
- mCurrentRenderTarget = reinterpret_cast<uintptr_t>(renderTarget11);
-
- mMipLevels = 1;
- mTextureFormat = renderTarget11->getDXGIFormat();
- mTextureWidth = renderTarget11->getWidth();
- mTextureHeight = renderTarget11->getHeight();
- mTextureDepth = 1;
- mInternalFormat = renderTarget11->getInternalFormat();
-
- ID3D11ShaderResourceView *srv = renderTarget11->getShaderResourceView();
- D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
- srv->GetDesc(&srvDesc);
- mShaderResourceFormat = srvDesc.Format;
-
- ID3D11RenderTargetView *rtv = renderTarget11->getRenderTargetView();
- if (rtv != nullptr)
- {
- D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- rtv->GetDesc(&rtvDesc);
- mRenderTargetFormat = rtvDesc.Format;
- }
- else
+ if (mDropStencilTexture.valid())
{
- mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
+ return DropStencil::ALREADY_EXISTS;
}
- ID3D11DepthStencilView *dsv = renderTarget11->getDepthStencilView();
- if (dsv != nullptr)
- {
- D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
- dsv->GetDesc(&dsvDesc);
- mDepthStencilFormat = dsvDesc.Format;
- }
- else
- {
- mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
- }
+ D3D11_TEXTURE2D_DESC dropDesc = {};
+ dropDesc.ArraySize = 1;
+ dropDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
+ dropDesc.CPUAccessFlags = 0;
+ dropDesc.Format = DXGI_FORMAT_R32_TYPELESS;
+ dropDesc.Height = mTextureHeight;
+ dropDesc.MipLevels = mMipLevels;
+ dropDesc.MiscFlags = 0;
+ dropDesc.SampleDesc.Count = 1;
+ dropDesc.SampleDesc.Quality = 0;
+ dropDesc.Usage = D3D11_USAGE_DEFAULT;
+ dropDesc.Width = mTextureWidth;
+
+ const auto &format =
+ d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps());
+ ANGLE_TRY(mRenderer->allocateTexture(dropDesc, format, &mDropStencilTexture));
+ mDropStencilTexture.setDebugName("TexStorage2D.DropStencil");
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat);
- const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(
- dxgiFormatInfo.internalFormat, mRenderer->getRenderer11DeviceCaps());
- mSwizzleTextureFormat = formatInfo.swizzleTexFormat;
- mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
- mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
+ ANGLE_TRY(initDropStencilTexture(context, gl::ImageIndexIterator::Make2D(0, mMipLevels)));
+
+ return DropStencil::CREATED;
}
-TextureStorage11_EGLImage::~TextureStorage11_EGLImage()
+TextureStorage11_External::TextureStorage11_External(
+ Renderer11 *renderer,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &glDesc)
+ : TextureStorage11(renderer, D3D11_BIND_SHADER_RESOURCE, 0, glDesc.internalFormat)
{
- SafeRelease(mSwizzleTexture);
- for (size_t i = 0; i < mSwizzleRenderTargets.size(); i++)
- {
- SafeRelease(mSwizzleRenderTargets[i]);
- }
+ ASSERT(stream->getProducerType() == egl::Stream::ProducerType::D3D11TextureNV12);
+ StreamProducerNV12 *producer = static_cast<StreamProducerNV12 *>(stream->getImplementation());
+ mTexture.set(producer->getD3DTexture(), mFormatInfo);
+ mSubresourceIndex = producer->getArraySlice();
+ mTexture.get()->AddRef();
+ mMipLevels = 1;
+
+ D3D11_TEXTURE2D_DESC desc;
+ mTexture.getDesc(&desc);
+ mTextureWidth = desc.Width;
+ mTextureHeight = desc.Height;
+ mTextureDepth = 1;
+ mHasKeyedMutex = (desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) != 0;
}
-gl::Error TextureStorage11_EGLImage::getResource(ID3D11Resource **outResource)
+gl::Error TextureStorage11_External::onDestroy(const gl::Context *context)
{
- gl::Error error = checkForUpdatedRenderTarget();
- if (error.isError())
+ if (mHasKeyedMutex)
{
- return error;
+ // If the keyed mutex is released that will unbind it and cause the state cache to become
+ // desynchronized.
+ mRenderer->getStateManager()->invalidateBoundViews();
}
- RenderTarget11 *renderTarget11 = nullptr;
- error = getImageRenderTarget(&renderTarget11);
- if (error.isError())
- {
- return error;
- }
+ return gl::NoError();
+}
+
+TextureStorage11_External::~TextureStorage11_External()
+{
+}
+
+gl::Error TextureStorage11_External::copyToStorage(const gl::Context *context,
+ TextureStorage *destStorage)
+{
+ UNIMPLEMENTED();
+ return gl::NoError();
+}
- *outResource = renderTarget11->getTexture();
- return gl::Error(GL_NO_ERROR);
+void TextureStorage11_External::associateImage(Image11 *image, const gl::ImageIndex &index)
+{
+ ASSERT(index.mipIndex == 0);
+ mAssociatedImage = image;
+}
+
+void TextureStorage11_External::verifyAssociatedImageValid(const gl::ImageIndex &index,
+ Image11 *expectedImage)
+{
+ ASSERT(index.mipIndex == 0 && mAssociatedImage == expectedImage);
}
-gl::Error TextureStorage11_EGLImage::getSRV(const gl::TextureState &textureState,
- ID3D11ShaderResourceView **outSRV)
+void TextureStorage11_External::disassociateImage(const gl::ImageIndex &index,
+ Image11 *expectedImage)
{
- gl::Error error = checkForUpdatedRenderTarget();
- if (error.isError())
+ ASSERT(index.mipIndex == 0);
+ ASSERT(mAssociatedImage == expectedImage);
+ mAssociatedImage = nullptr;
+}
+
+gl::Error TextureStorage11_External::releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage)
+{
+ ASSERT(index.mipIndex == 0);
+
+ if (mAssociatedImage != nullptr && mAssociatedImage != incomingImage)
{
- return error;
+ mAssociatedImage->verifyAssociatedStorageValid(this);
+
+ ANGLE_TRY(mAssociatedImage->recoverFromAssociatedStorage(context));
}
- return TextureStorage11::getSRV(textureState, outSRV);
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_External::getResource(const gl::Context *context,
+ const TextureHelper11 **outResource)
+{
+ *outResource = &mTexture;
+ return gl::NoError();
}
-gl::Error TextureStorage11_EGLImage::getMippedResource(ID3D11Resource **)
+gl::Error TextureStorage11_External::getMippedResource(const gl::Context *context,
+ const TextureHelper11 **outResource)
+{
+ *outResource = &mTexture;
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_External::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT)
+{
+ // Render targets are not supported for external textures
+ UNREACHABLE();
+ return gl::InternalError();
+}
+
+gl::Error TextureStorage11_External::createSRV(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV)
+{
+ // Since external textures are treates as non-mipmapped textures, we ignore mipmap levels and
+ // use the specified subresource ID the storage was created with.
+ ASSERT(mipLevels == 1);
+ ASSERT(outSRV);
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = format;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ // subresource index is equal to the mip level for 2D textures
+ srvDesc.Texture2DArray.MostDetailedMip = 0;
+ srvDesc.Texture2DArray.MipLevels = 1;
+ srvDesc.Texture2DArray.FirstArraySlice = mSubresourceIndex;
+ srvDesc.Texture2DArray.ArraySize = 1;
+
+ ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), outSRV));
+ outSRV->setDebugName("TexStorage2D.SRV");
+
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_External::getSwizzleTexture(const TextureHelper11 **outTexture)
+{
+ UNIMPLEMENTED();
+ return gl::InternalError();
+}
+
+gl::Error TextureStorage11_External::getSwizzleRenderTarget(int mipLevel,
+ const d3d11::RenderTargetView **outRTV)
+{
+ UNIMPLEMENTED();
+ return gl::InternalError();
+}
+
+TextureStorage11_EGLImage::TextureStorage11_EGLImage(Renderer11 *renderer,
+ EGLImageD3D *eglImage,
+ RenderTarget11 *renderTarget11)
+ : TextureStorage11(renderer,
+ D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
+ 0,
+ renderTarget11->getInternalFormat()),
+ mImage(eglImage),
+ mCurrentRenderTarget(0),
+ mSwizzleTexture(),
+ mSwizzleRenderTargets(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+{
+ mCurrentRenderTarget = reinterpret_cast<uintptr_t>(renderTarget11);
+
+ mMipLevels = 1;
+ mTextureWidth = renderTarget11->getWidth();
+ mTextureHeight = renderTarget11->getHeight();
+ mTextureDepth = 1;
+}
+
+TextureStorage11_EGLImage::~TextureStorage11_EGLImage()
+{
+}
+
+gl::Error TextureStorage11_EGLImage::getResource(const gl::Context *context,
+ const TextureHelper11 **outResource)
+{
+ ANGLE_TRY(checkForUpdatedRenderTarget(context));
+
+ RenderTarget11 *renderTarget11 = nullptr;
+ ANGLE_TRY(getImageRenderTarget(context, &renderTarget11));
+ *outResource = &renderTarget11->getTexture();
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_EGLImage::getSRV(const gl::Context *context,
+ const gl::TextureState &textureState,
+ const d3d11::SharedSRV **outSRV)
+{
+ ANGLE_TRY(checkForUpdatedRenderTarget(context));
+ return TextureStorage11::getSRV(context, textureState, outSRV);
+}
+
+gl::Error TextureStorage11_EGLImage::getMippedResource(const gl::Context *context,
+ const TextureHelper11 **)
{
// This shouldn't be called unless the zero max LOD workaround is active.
// EGL images are unavailable in this configuration.
UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION);
+ return gl::InternalError();
}
-gl::Error TextureStorage11_EGLImage::getRenderTarget(const gl::ImageIndex &index,
+gl::Error TextureStorage11_EGLImage::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
RenderTargetD3D **outRT)
{
ASSERT(!index.hasLayer());
ASSERT(index.mipIndex == 0);
- UNUSED_ASSERTION_VARIABLE(index);
- gl::Error error = checkForUpdatedRenderTarget();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(checkForUpdatedRenderTarget(context));
- return mImage->getRenderTarget(outRT);
+ return mImage->getRenderTarget(context, outRT);
}
-gl::Error TextureStorage11_EGLImage::copyToStorage(TextureStorage *destStorage)
+gl::Error TextureStorage11_EGLImage::copyToStorage(const gl::Context *context,
+ TextureStorage *destStorage)
{
- ID3D11Resource *sourceResouce = nullptr;
- gl::Error error = getResource(&sourceResouce);
- if (error.isError())
- {
- return error;
- }
+ const TextureHelper11 *sourceResouce = nullptr;
+ ANGLE_TRY(getResource(context, &sourceResouce));
ASSERT(destStorage);
TextureStorage11_2D *dest11 = GetAs<TextureStorage11_2D>(destStorage);
- ID3D11Resource *destResource = nullptr;
- error = dest11->getResource(&destResource);
- if (error.isError())
- {
- return error;
- }
+ const TextureHelper11 *destResource = nullptr;
+ ANGLE_TRY(dest11->getResource(context, &destResource));
ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
- immediateContext->CopyResource(destResource, sourceResouce);
+ immediateContext->CopyResource(destResource->get(), sourceResouce->get());
- dest11->invalidateSwizzleCache();
+ dest11->markDirty();
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
void TextureStorage11_EGLImage::associateImage(Image11 *, const gl::ImageIndex &)
@@ -1508,36 +1530,37 @@ void TextureStorage11_EGLImage::disassociateImage(const gl::ImageIndex &, Image1
{
}
-bool TextureStorage11_EGLImage::isAssociatedImageValid(const gl::ImageIndex &, Image11 *)
+void TextureStorage11_EGLImage::verifyAssociatedImageValid(const gl::ImageIndex &, Image11 *)
{
- return false;
}
-gl::Error TextureStorage11_EGLImage::releaseAssociatedImage(const gl::ImageIndex &, Image11 *)
+gl::Error TextureStorage11_EGLImage::releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &,
+ Image11 *)
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage11_EGLImage::useLevelZeroWorkaroundTexture(bool)
+gl::Error TextureStorage11_EGLImage::useLevelZeroWorkaroundTexture(const gl::Context *context, bool)
{
UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION);
+ return gl::InternalError();
}
-gl::Error TextureStorage11_EGLImage::getSwizzleTexture(ID3D11Resource **outTexture)
+gl::Error TextureStorage11_EGLImage::getSwizzleTexture(const TextureHelper11 **outTexture)
{
ASSERT(outTexture);
- if (!mSwizzleTexture)
+ if (!mSwizzleTexture.valid())
{
- ID3D11Device *device = mRenderer->getDevice();
+ const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
D3D11_TEXTURE2D_DESC desc;
desc.Width = mTextureWidth;
desc.Height = mTextureHeight;
desc.MipLevels = mMipLevels;
desc.ArraySize = 1;
- desc.Format = mSwizzleTextureFormat;
+ desc.Format = format.texFormat;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
@@ -1545,68 +1568,43 @@ gl::Error TextureStorage11_EGLImage::getSwizzleTexture(ID3D11Resource **outTextu
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
- HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture);
-
- ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY,
- "Failed to create internal swizzle texture, result: 0x%X.", result);
- }
-
- d3d11::SetDebugName(mSwizzleTexture, "TexStorageEGLImage.SwizzleTexture");
+ ANGLE_TRY(mRenderer->allocateTexture(desc, format, &mSwizzleTexture));
+ mSwizzleTexture.setDebugName("TexStorageEGLImage.SwizzleTexture");
}
- *outTexture = mSwizzleTexture;
- return gl::Error(GL_NO_ERROR);
+ *outTexture = &mSwizzleTexture;
+ return gl::NoError();
}
gl::Error TextureStorage11_EGLImage::getSwizzleRenderTarget(int mipLevel,
- ID3D11RenderTargetView **outRTV)
+ const d3d11::RenderTargetView **outRTV)
{
ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
ASSERT(outRTV);
- if (!mSwizzleRenderTargets[mipLevel])
+ if (!mSwizzleRenderTargets[mipLevel].valid())
{
- ID3D11Resource *swizzleTexture = NULL;
- gl::Error error = getSwizzleTexture(&swizzleTexture);
- if (error.isError())
- {
- return error;
- }
-
- ID3D11Device *device = mRenderer->getDevice();
+ const TextureHelper11 *swizzleTexture = nullptr;
+ ANGLE_TRY(getSwizzleTexture(&swizzleTexture));
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- rtvDesc.Format = mSwizzleRenderTargetFormat;
+ rtvDesc.Format =
+ mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel;
- HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc,
- &mSwizzleRenderTargets[mipLevel]);
-
- ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY,
- "Failed to create internal swizzle render target view, result: 0x%X.",
- result);
- }
+ ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture.get(),
+ &mSwizzleRenderTargets[mipLevel]));
}
- *outRTV = mSwizzleRenderTargets[mipLevel];
- return gl::Error(GL_NO_ERROR);
+ *outRTV = &mSwizzleRenderTargets[mipLevel];
+ return gl::NoError();
}
-gl::Error TextureStorage11_EGLImage::checkForUpdatedRenderTarget()
+gl::Error TextureStorage11_EGLImage::checkForUpdatedRenderTarget(const gl::Context *context)
{
RenderTarget11 *renderTarget11 = nullptr;
- gl::Error error = getImageRenderTarget(&renderTarget11);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(getImageRenderTarget(context, &renderTarget11));
if (mCurrentRenderTarget != reinterpret_cast<uintptr_t>(renderTarget11))
{
@@ -1614,14 +1612,15 @@ gl::Error TextureStorage11_EGLImage::checkForUpdatedRenderTarget()
mCurrentRenderTarget = reinterpret_cast<uintptr_t>(renderTarget11);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage11_EGLImage::createSRV(int baseLevel,
+gl::Error TextureStorage11_EGLImage::createSRV(const gl::Context *context,
+ int baseLevel,
int mipLevels,
DXGI_FORMAT format,
- ID3D11Resource *texture,
- ID3D11ShaderResourceView **outSRV) const
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV)
{
ASSERT(baseLevel == 0);
ASSERT(mipLevels == 1);
@@ -1637,163 +1636,129 @@ gl::Error TextureStorage11_EGLImage::createSRV(int baseLevel,
srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel;
srvDesc.Texture2D.MipLevels = mipLevels;
- ID3D11Device *device = mRenderer->getDevice();
- HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV);
-
- ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY,
- "Failed to create internal texture storage SRV, result: 0x%X.",
- result);
- }
-
- d3d11::SetDebugName(*outSRV, "TexStorageEGLImage.SRV");
+ ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), outSRV));
+ outSRV->setDebugName("TexStorageEGLImage.SRV");
}
else
{
RenderTarget11 *renderTarget = nullptr;
- gl::Error error = getImageRenderTarget(&renderTarget);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(getImageRenderTarget(context, &renderTarget));
ASSERT(texture == renderTarget->getTexture());
- *outSRV = renderTarget->getShaderResourceView();
- (*outSRV)->AddRef();
+ *outSRV = renderTarget->getShaderResourceView().makeCopy();
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage11_EGLImage::getImageRenderTarget(RenderTarget11 **outRT) const
+gl::Error TextureStorage11_EGLImage::getImageRenderTarget(const gl::Context *context,
+ RenderTarget11 **outRT) const
{
RenderTargetD3D *renderTargetD3D = nullptr;
- gl::Error error = mImage->getRenderTarget(&renderTargetD3D);
- if (error.isError())
- {
- return error;
- }
-
+ ANGLE_TRY(mImage->getRenderTarget(context, &renderTargetD3D));
*outRT = GetAs<RenderTarget11>(renderTargetD3D);
- return gl::Error(GL_NO_ERROR);
-}
-
-TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly)
- : TextureStorage11(renderer,
- GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
- GetTextureMiscFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget, levels))
+ return gl::NoError();
+}
+
+TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer,
+ GLenum internalformat,
+ bool renderTarget,
+ int size,
+ int levels,
+ bool hintLevelZeroOnly)
+ : TextureStorage11(
+ renderer,
+ GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
+ GetTextureMiscFlags(internalformat,
+ renderer->getRenderer11DeviceCaps(),
+ renderTarget,
+ levels),
+ internalformat),
+ mTexture(),
+ mLevelZeroTexture(),
+ mUseLevelZeroTexture(hintLevelZeroOnly && levels > 1),
+ mSwizzleTexture()
{
- mTexture = NULL;
- mSwizzleTexture = NULL;
-
for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
{
- mSwizzleRenderTargets[level] = NULL;
- for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++)
+ for (unsigned int face = 0; face < gl::CUBE_FACE_COUNT; face++)
{
- mAssociatedImages[face][level] = NULL;
- mRenderTarget[face][level] = NULL;
+ mAssociatedImages[face][level] = nullptr;
+ mRenderTarget[face][level] = nullptr;
}
}
- mLevelZeroTexture = NULL;
- mUseLevelZeroTexture = false;
-
- for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++)
+ for (unsigned int face = 0; face < gl::CUBE_FACE_COUNT; face++)
{
- mLevelZeroRenderTarget[face] = NULL;
+ mLevelZeroRenderTarget[face] = nullptr;
}
- mInternalFormat = internalformat;
-
- const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getRenderer11DeviceCaps());
- mTextureFormat = formatInfo.texFormat;
- mShaderResourceFormat = formatInfo.srvFormat;
- mDepthStencilFormat = formatInfo.dsvFormat;
- mRenderTargetFormat = formatInfo.rtvFormat;
- mSwizzleTextureFormat = formatInfo.swizzleTexFormat;
- mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
- mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
-
// adjust size if needed for compressed textures
int height = size;
- d3d11::MakeValidSize(false, mTextureFormat, &size, &height, &mTopLevel);
+ d3d11::MakeValidSize(false, mFormatInfo.texFormat, &size, &height, &mTopLevel);
- mMipLevels = mTopLevel + levels;
- mTextureWidth = size;
+ mMipLevels = mTopLevel + levels;
+ mTextureWidth = size;
mTextureHeight = size;
- mTextureDepth = 1;
+ mTextureDepth = 1;
- if (hintLevelZeroOnly && levels > 1)
- {
- //The LevelZeroOnly hint should only be true if the zero max LOD workaround is active.
- ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround);
- mUseLevelZeroTexture = true;
- }
+ // The LevelZeroOnly hint should only be true if the zero max LOD workaround is active.
+ ASSERT(!mUseLevelZeroTexture || mRenderer->getWorkarounds().zeroMaxLodWorkaround);
}
-TextureStorage11_Cube::~TextureStorage11_Cube()
+gl::Error TextureStorage11_Cube::onDestroy(const gl::Context *context)
{
for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
{
- for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++)
+ for (unsigned int face = 0; face < gl::CUBE_FACE_COUNT; face++)
{
- if (mAssociatedImages[face][level] != NULL)
+ if (mAssociatedImages[face][level] != nullptr)
{
- bool imageAssociationCorrect = mAssociatedImages[face][level]->isAssociatedStorageValid(this);
- ASSERT(imageAssociationCorrect);
-
- if (imageAssociationCorrect)
- {
- // We must let the Images recover their data before we delete it from the TextureStorage.
- mAssociatedImages[face][level]->recoverFromAssociatedStorage();
- }
+ mAssociatedImages[face][level]->verifyAssociatedStorageValid(this);
+
+ // We must let the Images recover their data before we delete it from the
+ // TextureStorage.
+ ANGLE_TRY(mAssociatedImages[face][level]->recoverFromAssociatedStorage(context));
}
}
}
- SafeRelease(mTexture);
- SafeRelease(mSwizzleTexture);
- SafeRelease(mLevelZeroTexture);
-
- for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++)
+ for (auto &faceRenderTargets : mRenderTarget)
{
- SafeDelete(mLevelZeroRenderTarget[face]);
+ InvalidateRenderTargetContainer(context, &faceRenderTargets);
}
+ InvalidateRenderTargetContainer(context, &mLevelZeroRenderTarget);
- for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
- {
- SafeRelease(mSwizzleRenderTargets[level]);
- for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++)
- {
- SafeDelete(mRenderTarget[face][level]);
- }
- }
+ return gl::NoError();
+}
+
+TextureStorage11_Cube::~TextureStorage11_Cube()
+{
}
UINT TextureStorage11_Cube::getSubresourceIndex(const gl::ImageIndex &index) const
{
- if (mRenderer->getWorkarounds().zeroMaxLodWorkaround && mUseLevelZeroTexture && index.mipIndex == 0)
+ if (mRenderer->getWorkarounds().zeroMaxLodWorkaround && mUseLevelZeroTexture &&
+ index.mipIndex == 0)
{
- UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0);
+ UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0);
UINT subresource = D3D11CalcSubresource(0, arraySlice, 1);
ASSERT(subresource != std::numeric_limits<UINT>::max());
return subresource;
}
else
{
- UINT mipSlice = static_cast<UINT>(index.mipIndex + mTopLevel);
- UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0);
+ UINT mipSlice = static_cast<UINT>(index.mipIndex + mTopLevel);
+ UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0);
UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels);
ASSERT(subresource != std::numeric_limits<UINT>::max());
return subresource;
}
}
-gl::Error TextureStorage11_Cube::copyToStorage(TextureStorage *destStorage)
+gl::Error TextureStorage11_Cube::copyToStorage(const gl::Context *context,
+ TextureStorage *destStorage)
{
ASSERT(destStorage);
@@ -1803,87 +1768,63 @@ gl::Error TextureStorage11_Cube::copyToStorage(TextureStorage *destStorage)
{
ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
- // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the corresponding textures in destStorage.
- if (mTexture)
+ // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the
+ // corresponding textures in destStorage.
+ if (mTexture.valid())
{
- gl::Error error = dest11->useLevelZeroWorkaroundTexture(false);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, false));
- ID3D11Resource *destResource = NULL;
- error = dest11->getResource(&destResource);
- if (error.isError())
- {
- return error;
- }
+ const TextureHelper11 *destResource = nullptr;
+ ANGLE_TRY(dest11->getResource(context, &destResource));
- immediateContext->CopyResource(destResource, mTexture);
+ immediateContext->CopyResource(destResource->get(), mTexture.get());
}
- if (mLevelZeroTexture)
+ if (mLevelZeroTexture.valid())
{
- gl::Error error = dest11->useLevelZeroWorkaroundTexture(true);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, true));
- ID3D11Resource *destResource = NULL;
- error = dest11->getResource(&destResource);
- if (error.isError())
- {
- return error;
- }
+ const TextureHelper11 *destResource = nullptr;
+ ANGLE_TRY(dest11->getResource(context, &destResource));
- immediateContext->CopyResource(destResource, mLevelZeroTexture);
+ immediateContext->CopyResource(destResource->get(), mLevelZeroTexture.get());
}
}
else
{
- ID3D11Resource *sourceResouce = NULL;
- gl::Error error = getResource(&sourceResouce);
- if (error.isError())
- {
- return error;
- }
+ const TextureHelper11 *sourceResouce = nullptr;
+ ANGLE_TRY(getResource(context, &sourceResouce));
- ID3D11Resource *destResource = NULL;
- error = dest11->getResource(&destResource);
- if (error.isError())
- {
- return error;
- }
+ const TextureHelper11 *destResource = nullptr;
+ ANGLE_TRY(dest11->getResource(context, &destResource));
ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
- immediateContext->CopyResource(destResource, sourceResouce);
+ immediateContext->CopyResource(destResource->get(), sourceResouce->get());
}
- dest11->invalidateSwizzleCache();
+ dest11->markDirty();
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage11_Cube::useLevelZeroWorkaroundTexture(bool useLevelZeroTexture)
+gl::Error TextureStorage11_Cube::useLevelZeroWorkaroundTexture(const gl::Context *context,
+ bool useLevelZeroTexture)
{
if (useLevelZeroTexture && mMipLevels > 1)
{
- if (!mUseLevelZeroTexture && mTexture)
+ if (!mUseLevelZeroTexture && mTexture.valid())
{
- gl::Error error = ensureTextureExists(1);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(ensureTextureExists(1));
// Pull data back from the mipped texture if necessary.
- ASSERT(mLevelZeroTexture);
- ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ ASSERT(mLevelZeroTexture.valid());
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
for (int face = 0; face < 6; face++)
{
- context->CopySubresourceRegion(mLevelZeroTexture, D3D11CalcSubresource(0, face, 1), 0, 0, 0, mTexture, face * mMipLevels, NULL);
+ deviceContext->CopySubresourceRegion(mLevelZeroTexture.get(),
+ D3D11CalcSubresource(0, face, 1), 0, 0, 0,
+ mTexture.get(), face * mMipLevels, nullptr);
}
}
@@ -1891,346 +1832,286 @@ gl::Error TextureStorage11_Cube::useLevelZeroWorkaroundTexture(bool useLevelZero
}
else
{
- if (mUseLevelZeroTexture && mLevelZeroTexture)
+ if (mUseLevelZeroTexture && mLevelZeroTexture.valid())
{
- gl::Error error = ensureTextureExists(mMipLevels);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(ensureTextureExists(mMipLevels));
// Pull data back from the level zero texture if necessary.
- ASSERT(mTexture);
- ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ ASSERT(mTexture.valid());
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
for (int face = 0; face < 6; face++)
{
- context->CopySubresourceRegion(mTexture, D3D11CalcSubresource(0, face, mMipLevels), 0, 0, 0, mLevelZeroTexture, face, NULL);
+ deviceContext->CopySubresourceRegion(mTexture.get(),
+ D3D11CalcSubresource(0, face, mMipLevels), 0,
+ 0, 0, mLevelZeroTexture.get(), face, nullptr);
}
}
mUseLevelZeroTexture = false;
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-void TextureStorage11_Cube::associateImage(Image11* image, const gl::ImageIndex &index)
+void TextureStorage11_Cube::associateImage(Image11 *image, const gl::ImageIndex &index)
{
- GLint level = index.mipIndex;
- GLint layerTarget = index.layerIndex;
+ const GLint level = index.mipIndex;
+ const GLint layerTarget = index.layerIndex;
ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
- ASSERT(0 <= layerTarget && layerTarget < CUBE_FACE_COUNT);
+ ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::CUBE_FACE_COUNT));
if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
{
- if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT)
+ if (0 <= layerTarget && layerTarget < static_cast<GLint>(gl::CUBE_FACE_COUNT))
{
mAssociatedImages[layerTarget][level] = image;
}
}
}
-bool TextureStorage11_Cube::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage)
+void TextureStorage11_Cube::verifyAssociatedImageValid(const gl::ImageIndex &index,
+ Image11 *expectedImage)
{
- GLint level = index.mipIndex;
- GLint layerTarget = index.layerIndex;
-
- if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
- {
- if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT)
- {
- // This validation check should never return false. It means the Image/TextureStorage association is broken.
- bool retValue = (mAssociatedImages[layerTarget][level] == expectedImage);
- ASSERT(retValue);
- return retValue;
- }
- }
+ const GLint level = index.mipIndex;
+ const GLint layerTarget = index.layerIndex;
- return false;
+ ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::CUBE_FACE_COUNT));
+ // This validation check should never return false. It means the Image/TextureStorage
+ // association is broken.
+ ASSERT(mAssociatedImages[layerTarget][level] == expectedImage);
}
// disassociateImage allows an Image to end its association with a Storage.
-void TextureStorage11_Cube::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage)
+void TextureStorage11_Cube::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage)
{
- GLint level = index.mipIndex;
- GLint layerTarget = index.layerIndex;
+ const GLint level = index.mipIndex;
+ const GLint layerTarget = index.layerIndex;
ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
- ASSERT(0 <= layerTarget && layerTarget < CUBE_FACE_COUNT);
-
- if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
- {
- if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT)
- {
- ASSERT(mAssociatedImages[layerTarget][level] == expectedImage);
-
- if (mAssociatedImages[layerTarget][level] == expectedImage)
- {
- mAssociatedImages[layerTarget][level] = NULL;
- }
- }
- }
+ ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::CUBE_FACE_COUNT));
+ ASSERT(mAssociatedImages[layerTarget][level] == expectedImage);
+ mAssociatedImages[layerTarget][level] = nullptr;
}
-// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association.
-gl::Error TextureStorage11_Cube::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage)
+// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
+// recover its data before ending the association.
+gl::Error TextureStorage11_Cube::releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage)
{
- GLint level = index.mipIndex;
- GLint layerTarget = index.layerIndex;
+ const GLint level = index.mipIndex;
+ const GLint layerTarget = index.layerIndex;
ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
- ASSERT(0 <= layerTarget && layerTarget < CUBE_FACE_COUNT);
+ ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::CUBE_FACE_COUNT));
if ((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
{
- if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT)
+ if (0 <= layerTarget && layerTarget < static_cast<GLint>(gl::CUBE_FACE_COUNT))
{
// No need to let the old Image recover its data, if it is also the incoming Image.
- if (mAssociatedImages[layerTarget][level] != NULL && mAssociatedImages[layerTarget][level] != incomingImage)
+ if (mAssociatedImages[layerTarget][level] != nullptr &&
+ mAssociatedImages[layerTarget][level] != incomingImage)
{
- // Ensure that the Image is still associated with this TextureStorage. This should be true.
- bool imageAssociationCorrect = mAssociatedImages[layerTarget][level]->isAssociatedStorageValid(this);
- ASSERT(imageAssociationCorrect);
-
- if (imageAssociationCorrect)
- {
- // Force the image to recover from storage before its data is overwritten.
- // This will reset mAssociatedImages[level] to NULL too.
- gl::Error error = mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage();
- if (error.isError())
- {
- return error;
- }
- }
+ // Ensure that the Image is still associated with this TextureStorage.
+ mAssociatedImages[layerTarget][level]->verifyAssociatedStorageValid(this);
+
+ // Force the image to recover from storage before its data is overwritten.
+ // This will reset mAssociatedImages[level] to nullptr too.
+ ANGLE_TRY(
+ mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage(context));
}
}
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage11_Cube::getResource(ID3D11Resource **outResource)
+gl::Error TextureStorage11_Cube::getResource(const gl::Context *context,
+ const TextureHelper11 **outResource)
{
if (mUseLevelZeroTexture && mMipLevels > 1)
{
- gl::Error error = ensureTextureExists(1);
- if (error.isError())
- {
- return error;
- }
-
- *outResource = mLevelZeroTexture;
- return gl::Error(GL_NO_ERROR);
+ ANGLE_TRY(ensureTextureExists(1));
+ *outResource = &mLevelZeroTexture;
+ return gl::NoError();
}
else
{
- gl::Error error = ensureTextureExists(mMipLevels);
- if (error.isError())
- {
- return error;
- }
-
- *outResource = mTexture;
- return gl::Error(GL_NO_ERROR);
+ ANGLE_TRY(ensureTextureExists(mMipLevels));
+ *outResource = &mTexture;
+ return gl::NoError();
}
}
-gl::Error TextureStorage11_Cube::getMippedResource(ID3D11Resource **outResource)
+gl::Error TextureStorage11_Cube::getMippedResource(const gl::Context *context,
+ const TextureHelper11 **outResource)
{
// This shouldn't be called unless the zero max LOD workaround is active.
ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround);
- gl::Error error = ensureTextureExists(mMipLevels);
- if (error.isError())
- {
- return error;
- }
-
- *outResource = mTexture;
- return gl::Error(GL_NO_ERROR);
+ ANGLE_TRY(ensureTextureExists(mMipLevels));
+ *outResource = &mTexture;
+ return gl::NoError();
}
gl::Error TextureStorage11_Cube::ensureTextureExists(int mipLevels)
{
// If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture.
- bool useLevelZeroTexture = mRenderer->getWorkarounds().zeroMaxLodWorkaround ? (mipLevels == 1) && (mMipLevels > 1) : false;
- ID3D11Texture2D **outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture;
+ bool useLevelZeroTexture = mRenderer->getWorkarounds().zeroMaxLodWorkaround
+ ? (mipLevels == 1) && (mMipLevels > 1)
+ : false;
+ TextureHelper11 *outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture;
// if the size is not positive this should be treated as an incomplete texture
// we handle that here by skipping the d3d texture creation
- if (*outputTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0)
+ if (!outputTexture->valid() && mTextureWidth > 0 && mTextureHeight > 0)
{
ASSERT(mMipLevels > 0);
- ID3D11Device *device = mRenderer->getDevice();
-
D3D11_TEXTURE2D_DESC desc;
- desc.Width = mTextureWidth;
- desc.Height = mTextureHeight;
- desc.MipLevels = mipLevels;
- desc.ArraySize = CUBE_FACE_COUNT;
- desc.Format = mTextureFormat;
- desc.SampleDesc.Count = 1;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mipLevels;
+ desc.ArraySize = gl::CUBE_FACE_COUNT;
+ desc.Format = mFormatInfo.texFormat;
+ desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.BindFlags = getBindFlags();
- desc.CPUAccessFlags = 0;
- desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE | getMiscFlags();
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = getBindFlags();
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE | getMiscFlags();
- HRESULT result = device->CreateTexture2D(&desc, NULL, outputTexture);
+ ANGLE_TRY(mRenderer->allocateTexture(desc, mFormatInfo, outputTexture));
+ outputTexture->setDebugName("TexStorageCube.Texture");
+ }
- // this can happen from windows TDR
- if (d3d11::isDeviceLostError(result))
- {
- mRenderer->notifyDeviceLost();
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube texture storage, result: 0x%X.", result);
- }
- else if (FAILED(result))
- {
- ASSERT(result == E_OUTOFMEMORY);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube texture storage, result: 0x%X.", result);
- }
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_Cube::createRenderTargetSRV(const TextureHelper11 &texture,
+ const gl::ImageIndex &index,
+ DXGI_FORMAT resourceFormat,
+ d3d11::SharedSRV *srv) const
+{
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = resourceFormat;
+ srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + index.mipIndex;
+ srvDesc.Texture2DArray.MipLevels = 1;
+ srvDesc.Texture2DArray.FirstArraySlice = index.layerIndex;
+ srvDesc.Texture2DArray.ArraySize = 1;
- d3d11::SetDebugName(*outputTexture, "TexStorageCube.Texture");
+ if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_10_0)
+ {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
+ }
+ else
+ {
+ // Will be used with Texture2D sampler, not TextureCube
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
}
- return gl::Error(GL_NO_ERROR);
+ ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), srv));
+ return gl::NoError();
}
-gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+gl::Error TextureStorage11_Cube::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT)
{
- int faceIndex = index.layerIndex;
- int level = index.mipIndex;
+ const int faceIndex = index.layerIndex;
+ const int level = index.mipIndex;
ASSERT(level >= 0 && level < getLevelCount());
- ASSERT(faceIndex >= 0 && faceIndex < CUBE_FACE_COUNT);
+ ASSERT(faceIndex >= 0 && faceIndex < static_cast<GLint>(gl::CUBE_FACE_COUNT));
if (!mRenderTarget[faceIndex][level])
{
- ID3D11Device *device = mRenderer->getDevice();
- HRESULT result;
-
- ID3D11Resource *texture = NULL;
- gl::Error error = getResource(&texture);
- if (error.isError())
+ if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
- return error;
+ ASSERT(index.mipIndex == 0);
+ ANGLE_TRY(useLevelZeroWorkaroundTexture(context, true));
}
+ const TextureHelper11 *texture = nullptr;
+ ANGLE_TRY(getResource(context, &texture));
+
if (mUseLevelZeroTexture)
{
if (!mLevelZeroRenderTarget[faceIndex])
{
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- rtvDesc.Format = mRenderTargetFormat;
- rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
- rtvDesc.Texture2DArray.MipSlice = mTopLevel + level;
+ rtvDesc.Format = mFormatInfo.rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+ rtvDesc.Texture2DArray.MipSlice = mTopLevel + level;
rtvDesc.Texture2DArray.FirstArraySlice = faceIndex;
- rtvDesc.Texture2DArray.ArraySize = 1;
-
- ID3D11RenderTargetView *rtv;
- result = device->CreateRenderTargetView(mLevelZeroTexture, &rtvDesc, &rtv);
+ rtvDesc.Texture2DArray.ArraySize = 1;
- if (result == E_OUTOFMEMORY)
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result);
- }
- ASSERT(SUCCEEDED(result));
+ d3d11::RenderTargetView rtv;
+ ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mLevelZeroTexture.get(), &rtv));
- mLevelZeroRenderTarget[faceIndex] = new TextureRenderTarget11(rtv, mLevelZeroTexture, NULL, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0);
-
- // RenderTarget will take ownership of these resources
- SafeRelease(rtv);
+ mLevelZeroRenderTarget[faceIndex].reset(new TextureRenderTarget11(
+ std::move(rtv), mLevelZeroTexture, d3d11::SharedSRV(), d3d11::SharedSRV(),
+ mFormatInfo.internalFormat, getFormatSet(), getLevelWidth(level),
+ getLevelHeight(level), 1, 0));
}
ASSERT(outRT);
- *outRT = mLevelZeroRenderTarget[faceIndex];
- return gl::Error(GL_NO_ERROR);
+ *outRT = mLevelZeroRenderTarget[faceIndex].get();
+ return gl::NoError();
}
- D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
- srvDesc.Format = mShaderResourceFormat;
- srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + level;
- srvDesc.Texture2DArray.MipLevels = 1;
- srvDesc.Texture2DArray.FirstArraySlice = faceIndex;
- srvDesc.Texture2DArray.ArraySize = 1;
-
- if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
+ d3d11::SharedSRV srv;
+ ANGLE_TRY(createRenderTargetSRV(*texture, index, mFormatInfo.srvFormat, &srv));
+ d3d11::SharedSRV blitSRV;
+ if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat)
{
- srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
+ ANGLE_TRY(createRenderTargetSRV(*texture, index, mFormatInfo.blitSRVFormat, &blitSRV));
}
else
{
- srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube
+ blitSRV = srv.makeCopy();
}
- ID3D11ShaderResourceView *srv;
- result = device->CreateShaderResourceView(texture, &srvDesc, &srv);
+ srv.setDebugName("TexStorageCube.RenderTargetSRV");
- ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal shader resource view for texture storage, result: 0x%X.", result);
- }
-
- d3d11::SetDebugName(srv, "TexStorageCube.RenderTargetSRV");
-
- if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
+ if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
{
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- rtvDesc.Format = mRenderTargetFormat;
- rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
- rtvDesc.Texture2DArray.MipSlice = mTopLevel + level;
+ rtvDesc.Format = mFormatInfo.rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+ rtvDesc.Texture2DArray.MipSlice = mTopLevel + level;
rtvDesc.Texture2DArray.FirstArraySlice = faceIndex;
- rtvDesc.Texture2DArray.ArraySize = 1;
+ rtvDesc.Texture2DArray.ArraySize = 1;
- ID3D11RenderTargetView *rtv;
- result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv);
+ d3d11::RenderTargetView rtv;
+ ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture->get(), &rtv));
+ rtv.setDebugName("TexStorageCube.RenderTargetRTV");
- ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
- if (FAILED(result))
- {
- SafeRelease(srv);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result);
- }
-
- d3d11::SetDebugName(rtv, "TexStorageCube.RenderTargetRTV");
-
- mRenderTarget[faceIndex][level] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0);
-
- // RenderTarget will take ownership of these resources
- SafeRelease(rtv);
- SafeRelease(srv);
+ mRenderTarget[faceIndex][level].reset(new TextureRenderTarget11(
+ std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(level), getLevelHeight(level), 1, 0));
}
- else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
+ else if (mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN)
{
D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
- dsvDesc.Format = mDepthStencilFormat;
- dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
- dsvDesc.Flags = 0;
- dsvDesc.Texture2DArray.MipSlice = mTopLevel + level;
+ dsvDesc.Format = mFormatInfo.dsvFormat;
+ dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
+ dsvDesc.Flags = 0;
+ dsvDesc.Texture2DArray.MipSlice = mTopLevel + level;
dsvDesc.Texture2DArray.FirstArraySlice = faceIndex;
- dsvDesc.Texture2DArray.ArraySize = 1;
-
- ID3D11DepthStencilView *dsv;
- result = device->CreateDepthStencilView(texture, &dsvDesc, &dsv);
-
- ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
- if (FAILED(result))
- {
- SafeRelease(srv);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal depth stencil view for texture storage, result: 0x%X.", result);
- }
+ dsvDesc.Texture2DArray.ArraySize = 1;
- d3d11::SetDebugName(dsv, "TexStorageCube.RenderTargetDSV");
+ d3d11::DepthStencilView dsv;
+ ANGLE_TRY(mRenderer->allocateResource(dsvDesc, texture->get(), &dsv));
+ dsv.setDebugName("TexStorageCube.RenderTargetDSV");
- mRenderTarget[faceIndex][level] = new TextureRenderTarget11(dsv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0);
-
- // RenderTarget will take ownership of these resources
- SafeRelease(dsv);
- SafeRelease(srv);
+ mRenderTarget[faceIndex][level].reset(new TextureRenderTarget11(
+ std::move(dsv), *texture, srv, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(level), getLevelHeight(level), 1, 0));
}
else
{
@@ -2239,215 +2120,237 @@ gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, Re
}
ASSERT(outRT);
- *outRT = mRenderTarget[faceIndex][level];
- return gl::Error(GL_NO_ERROR);
+ *outRT = mRenderTarget[faceIndex][level].get();
+ return gl::NoError();
}
-gl::Error TextureStorage11_Cube::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
- ID3D11ShaderResourceView **outSRV) const
+gl::Error TextureStorage11_Cube::createSRV(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV)
{
ASSERT(outSRV);
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
srvDesc.Format = format;
- // Unnormalized integer cube maps are not supported by DX11; we emulate them as an array of six 2D textures
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format);
- if (dxgiFormatInfo.componentType == GL_INT || dxgiFormatInfo.componentType == GL_UNSIGNED_INT)
+ // Unnormalized integer cube maps are not supported by DX11; we emulate them as an array of six
+ // 2D textures
+ const GLenum componentType = d3d11::GetComponentType(format);
+ if (componentType == GL_INT || componentType == GL_UNSIGNED_INT)
{
- srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel;
srvDesc.Texture2DArray.MipLevels = mipLevels;
srvDesc.Texture2DArray.FirstArraySlice = 0;
- srvDesc.Texture2DArray.ArraySize = CUBE_FACE_COUNT;
+ srvDesc.Texture2DArray.ArraySize = gl::CUBE_FACE_COUNT;
}
else
{
- srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
- srvDesc.TextureCube.MipLevels = mipLevels;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
+ srvDesc.TextureCube.MipLevels = mipLevels;
srvDesc.TextureCube.MostDetailedMip = mTopLevel + baseLevel;
}
- ID3D11Resource *srvTexture = texture;
+ const TextureHelper11 *srvTexture = &texture;
if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
ASSERT(mTopLevel == 0);
ASSERT(baseLevel == 0);
- // This code also assumes that the incoming texture equals either mLevelZeroTexture or mTexture.
+ // This code also assumes that the incoming texture equals either mLevelZeroTexture or
+ // mTexture.
if (mipLevels == 1 && mMipLevels > 1)
{
// We must use a SRV on the level-zero-only texture.
- ASSERT(mLevelZeroTexture != NULL && texture == mLevelZeroTexture);
- srvTexture = mLevelZeroTexture;
+ ANGLE_TRY(ensureTextureExists(1));
+ srvTexture = &mLevelZeroTexture;
}
else
{
ASSERT(mipLevels == static_cast<int>(mMipLevels));
- ASSERT(mTexture != NULL && texture == mTexture);
- srvTexture = mTexture;
+ ASSERT(mTexture.valid() && texture == mTexture);
+ srvTexture = &mTexture;
}
}
- ID3D11Device *device = mRenderer->getDevice();
- HRESULT result = device->CreateShaderResourceView(srvTexture, &srvDesc, outSRV);
-
- ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal texture storage SRV, result: 0x%X.", result);
- }
-
- d3d11::SetDebugName(*outSRV, "TexStorageCube.SRV");
+ ANGLE_TRY(mRenderer->allocateResource(srvDesc, srvTexture->get(), outSRV));
+ outSRV->setDebugName("TexStorageCube.SRV");
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage11_Cube::getSwizzleTexture(ID3D11Resource **outTexture)
+gl::Error TextureStorage11_Cube::getSwizzleTexture(const TextureHelper11 **outTexture)
{
ASSERT(outTexture);
- if (!mSwizzleTexture)
+ if (!mSwizzleTexture.valid())
{
- ID3D11Device *device = mRenderer->getDevice();
+ const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
D3D11_TEXTURE2D_DESC desc;
- desc.Width = mTextureWidth;
- desc.Height = mTextureHeight;
- desc.MipLevels = mMipLevels;
- desc.ArraySize = CUBE_FACE_COUNT;
- desc.Format = mSwizzleTextureFormat;
- desc.SampleDesc.Count = 1;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mMipLevels;
+ desc.ArraySize = gl::CUBE_FACE_COUNT;
+ desc.Format = format.texFormat;
+ desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
- desc.CPUAccessFlags = 0;
- desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
-
- HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture);
-
- ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle texture, result: 0x%X.", result);
- }
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
- d3d11::SetDebugName(*outTexture, "TexStorageCube.SwizzleTexture");
+ ANGLE_TRY(mRenderer->allocateTexture(desc, format, &mSwizzleTexture));
+ mSwizzleTexture.setDebugName("TexStorageCube.SwizzleTexture");
}
- *outTexture = mSwizzleTexture;
- return gl::Error(GL_NO_ERROR);
+ *outTexture = &mSwizzleTexture;
+ return gl::NoError();
}
-gl::Error TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV)
+gl::Error TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel,
+ const d3d11::RenderTargetView **outRTV)
{
ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
ASSERT(outRTV);
- if (!mSwizzleRenderTargets[mipLevel])
+ if (!mSwizzleRenderTargets[mipLevel].valid())
{
- ID3D11Resource *swizzleTexture = NULL;
- gl::Error error = getSwizzleTexture(&swizzleTexture);
- if (error.isError())
- {
- return error;
- }
-
- ID3D11Device *device = mRenderer->getDevice();
+ const TextureHelper11 *swizzleTexture = nullptr;
+ ANGLE_TRY(getSwizzleTexture(&swizzleTexture));
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- rtvDesc.Format = mSwizzleRenderTargetFormat;
- rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
- rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
+ rtvDesc.Format =
+ mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+ rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
rtvDesc.Texture2DArray.FirstArraySlice = 0;
- rtvDesc.Texture2DArray.ArraySize = CUBE_FACE_COUNT;
-
- HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]);
+ rtvDesc.Texture2DArray.ArraySize = gl::CUBE_FACE_COUNT;
- ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle render target view, result: 0x%X.", result);
- }
+ ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture.get(),
+ &mSwizzleRenderTargets[mipLevel]));
}
- *outRTV = mSwizzleRenderTargets[mipLevel];
- return gl::Error(GL_NO_ERROR);
+ *outRTV = &mSwizzleRenderTargets[mipLevel];
+ return gl::NoError();
}
-TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer, GLenum internalformat, bool renderTarget,
- GLsizei width, GLsizei height, GLsizei depth, int levels)
- : TextureStorage11(renderer,
- GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
- GetTextureMiscFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget, levels))
+gl::Error TextureStorage11::initDropStencilTexture(const gl::Context *context,
+ const gl::ImageIndexIterator &it)
{
- mTexture = NULL;
- mSwizzleTexture = NULL;
+ const TextureHelper11 *sourceTexture = nullptr;
+ ANGLE_TRY(getResource(context, &sourceTexture));
- for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ gl::ImageIndexIterator itCopy = it;
+
+ while (itCopy.hasNext())
{
- mAssociatedImages[i] = NULL;
- mLevelRenderTargets[i] = NULL;
- mSwizzleRenderTargets[i] = NULL;
+ gl::ImageIndex index = itCopy.next();
+ gl::Box wholeArea(0, 0, 0, getLevelWidth(index.mipIndex), getLevelHeight(index.mipIndex),
+ 1);
+ gl::Extents wholeSize(wholeArea.width, wholeArea.height, 1);
+ UINT subresource = getSubresourceIndex(index);
+ ANGLE_TRY(mRenderer->getBlitter()->copyDepthStencil(
+ *sourceTexture, subresource, wholeArea, wholeSize, mDropStencilTexture, subresource,
+ wholeArea, wholeSize, nullptr));
}
- mInternalFormat = internalformat;
+ return gl::NoError();
+}
- const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getRenderer11DeviceCaps());
- mTextureFormat = formatInfo.texFormat;
- mShaderResourceFormat = formatInfo.srvFormat;
- mDepthStencilFormat = formatInfo.dsvFormat;
- mRenderTargetFormat = formatInfo.rtvFormat;
- mSwizzleTextureFormat = formatInfo.swizzleTexFormat;
- mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
- mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
+gl::ErrorOrResult<TextureStorage11::DropStencil> TextureStorage11_Cube::ensureDropStencilTexture(
+ const gl::Context *context)
+{
+ if (mDropStencilTexture.valid())
+ {
+ return DropStencil::ALREADY_EXISTS;
+ }
+
+ D3D11_TEXTURE2D_DESC dropDesc = {};
+ dropDesc.ArraySize = 6;
+ dropDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
+ dropDesc.CPUAccessFlags = 0;
+ dropDesc.Format = DXGI_FORMAT_R32_TYPELESS;
+ dropDesc.Height = mTextureHeight;
+ dropDesc.MipLevels = mMipLevels;
+ dropDesc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
+ dropDesc.SampleDesc.Count = 1;
+ dropDesc.SampleDesc.Quality = 0;
+ dropDesc.Usage = D3D11_USAGE_DEFAULT;
+ dropDesc.Width = mTextureWidth;
+
+ const auto &format =
+ d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps());
+ ANGLE_TRY(mRenderer->allocateTexture(dropDesc, format, &mDropStencilTexture));
+ mDropStencilTexture.setDebugName("TexStorageCube.DropStencil");
+
+ ANGLE_TRY(initDropStencilTexture(context, gl::ImageIndexIterator::MakeCube(0, mMipLevels)));
+
+ return DropStencil::CREATED;
+}
+
+TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer,
+ GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels)
+ : TextureStorage11(
+ renderer,
+ GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
+ GetTextureMiscFlags(internalformat,
+ renderer->getRenderer11DeviceCaps(),
+ renderTarget,
+ levels),
+ internalformat)
+{
+ for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ mAssociatedImages[i] = nullptr;
+ mLevelRenderTargets[i] = nullptr;
+ }
// adjust size if needed for compressed textures
- d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel);
+ d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel);
- mMipLevels = mTopLevel + levels;
- mTextureWidth = width;
+ mMipLevels = mTopLevel + levels;
+ mTextureWidth = width;
mTextureHeight = height;
- mTextureDepth = depth;
+ mTextureDepth = depth;
}
-TextureStorage11_3D::~TextureStorage11_3D()
+gl::Error TextureStorage11_3D::onDestroy(const gl::Context *context)
{
for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
- if (mAssociatedImages[i] != NULL)
+ if (mAssociatedImages[i] != nullptr)
{
- bool imageAssociationCorrect = mAssociatedImages[i]->isAssociatedStorageValid(this);
- ASSERT(imageAssociationCorrect);
+ mAssociatedImages[i]->verifyAssociatedStorageValid(this);
- if (imageAssociationCorrect)
- {
- // We must let the Images recover their data before we delete it from the TextureStorage.
- mAssociatedImages[i]->recoverFromAssociatedStorage();
- }
+ // We must let the Images recover their data before we delete it from the
+ // TextureStorage.
+ ANGLE_TRY(mAssociatedImages[i]->recoverFromAssociatedStorage(context));
}
}
- SafeRelease(mTexture);
- SafeRelease(mSwizzleTexture);
+ InvalidateRenderTargetContainer(context, &mLevelRenderTargets);
+ InvalidateRenderTargetContainer(context, &mLevelLayerRenderTargets);
- for (RenderTargetMap::iterator i = mLevelLayerRenderTargets.begin(); i != mLevelLayerRenderTargets.end(); i++)
- {
- SafeDelete(i->second);
- }
- mLevelLayerRenderTargets.clear();
+ return gl::NoError();
+}
- for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
- {
- SafeDelete(mLevelRenderTargets[i]);
- SafeRelease(mSwizzleRenderTargets[i]);
- }
+TextureStorage11_3D::~TextureStorage11_3D()
+{
}
-void TextureStorage11_3D::associateImage(Image11* image, const gl::ImageIndex &index)
+void TextureStorage11_3D::associateImage(Image11 *image, const gl::ImageIndex &index)
{
- GLint level = index.mipIndex;
+ const GLint level = index.mipIndex;
ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
@@ -2457,676 +2360,796 @@ void TextureStorage11_3D::associateImage(Image11* image, const gl::ImageIndex &i
}
}
-bool TextureStorage11_3D::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage)
+void TextureStorage11_3D::verifyAssociatedImageValid(const gl::ImageIndex &index,
+ Image11 *expectedImage)
{
- GLint level = index.mipIndex;
-
- if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
- {
- // This validation check should never return false. It means the Image/TextureStorage association is broken.
- bool retValue = (mAssociatedImages[level] == expectedImage);
- ASSERT(retValue);
- return retValue;
- }
+ const GLint level = index.mipIndex;
- return false;
+ ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ // This validation check should never return false. It means the Image/TextureStorage
+ // association is broken.
+ ASSERT(mAssociatedImages[level] == expectedImage);
}
// disassociateImage allows an Image to end its association with a Storage.
-void TextureStorage11_3D::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage)
+void TextureStorage11_3D::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage)
{
- GLint level = index.mipIndex;
+ const GLint level = index.mipIndex;
ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
-
- if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
- {
- ASSERT(mAssociatedImages[level] == expectedImage);
-
- if (mAssociatedImages[level] == expectedImage)
- {
- mAssociatedImages[level] = NULL;
- }
- }
+ ASSERT(mAssociatedImages[level] == expectedImage);
+ mAssociatedImages[level] = nullptr;
}
-// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association.
-gl::Error TextureStorage11_3D::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage)
+// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
+// recover its data before ending the association.
+gl::Error TextureStorage11_3D::releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage)
{
- GLint level = index.mipIndex;
+ const GLint level = index.mipIndex;
ASSERT((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS));
if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
{
// No need to let the old Image recover its data, if it is also the incoming Image.
- if (mAssociatedImages[level] != NULL && mAssociatedImages[level] != incomingImage)
+ if (mAssociatedImages[level] != nullptr && mAssociatedImages[level] != incomingImage)
{
- // Ensure that the Image is still associated with this TextureStorage. This should be true.
- bool imageAssociationCorrect = mAssociatedImages[level]->isAssociatedStorageValid(this);
- ASSERT(imageAssociationCorrect);
+ // Ensure that the Image is still associated with this TextureStorage.
+ mAssociatedImages[level]->verifyAssociatedStorageValid(this);
- if (imageAssociationCorrect)
- {
- // Force the image to recover from storage before its data is overwritten.
- // This will reset mAssociatedImages[level] to NULL too.
- gl::Error error = mAssociatedImages[level]->recoverFromAssociatedStorage();
- if (error.isError())
- {
- return error;
- }
- }
+ // Force the image to recover from storage before its data is overwritten.
+ // This will reset mAssociatedImages[level] to nullptr too.
+ ANGLE_TRY(mAssociatedImages[level]->recoverFromAssociatedStorage(context));
}
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage11_3D::getResource(ID3D11Resource **outResource)
+gl::Error TextureStorage11_3D::getResource(const gl::Context *context,
+ const TextureHelper11 **outResource)
{
- // If the width, height or depth are not positive this should be treated as an incomplete texture
- // we handle that here by skipping the d3d texture creation
- if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0)
+ // If the width, height or depth are not positive this should be treated as an incomplete
+ // texture. We handle that here by skipping the d3d texture creation.
+ if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0)
{
ASSERT(mMipLevels > 0);
- ID3D11Device *device = mRenderer->getDevice();
-
D3D11_TEXTURE3D_DESC desc;
- desc.Width = mTextureWidth;
- desc.Height = mTextureHeight;
- desc.Depth = mTextureDepth;
- desc.MipLevels = mMipLevels;
- desc.Format = mTextureFormat;
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.BindFlags = getBindFlags();
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.Depth = mTextureDepth;
+ desc.MipLevels = mMipLevels;
+ desc.Format = mFormatInfo.texFormat;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = getBindFlags();
desc.CPUAccessFlags = 0;
- desc.MiscFlags = getMiscFlags();
+ desc.MiscFlags = getMiscFlags();
- HRESULT result = device->CreateTexture3D(&desc, NULL, &mTexture);
-
- // this can happen from windows TDR
- if (d3d11::isDeviceLostError(result))
- {
- mRenderer->notifyDeviceLost();
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 3D texture storage, result: 0x%X.", result);
- }
- else if (FAILED(result))
- {
- ASSERT(result == E_OUTOFMEMORY);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 3D texture storage, result: 0x%X.", result);
- }
-
- d3d11::SetDebugName(mTexture, "TexStorage3D.Texture");
+ ANGLE_TRY(mRenderer->allocateTexture(desc, mFormatInfo, &mTexture));
+ mTexture.setDebugName("TexStorage3D.Texture");
}
- *outResource = mTexture;
- return gl::Error(GL_NO_ERROR);
+ *outResource = &mTexture;
+ return gl::NoError();
}
-gl::Error TextureStorage11_3D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
- ID3D11ShaderResourceView **outSRV) const
+gl::Error TextureStorage11_3D::createSRV(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV)
{
ASSERT(outSRV);
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
- srvDesc.Format = format;
- srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
+ srvDesc.Format = format;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
srvDesc.Texture3D.MostDetailedMip = baseLevel;
- srvDesc.Texture3D.MipLevels = mipLevels;
-
- ID3D11Device *device = mRenderer->getDevice();
- HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV);
-
- ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal texture storage SRV, result: 0x%X.", result);
- }
+ srvDesc.Texture3D.MipLevels = mipLevels;
- d3d11::SetDebugName(*outSRV, "TexStorage3D.SRV");
+ ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), outSRV));
+ outSRV->setDebugName("TexStorage3D.SRV");
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+gl::Error TextureStorage11_3D::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT)
{
- int mipLevel = index.mipIndex;
+ const int mipLevel = index.mipIndex;
ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
- ASSERT(mRenderTargetFormat != DXGI_FORMAT_UNKNOWN);
+ ASSERT(mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
if (!index.hasLayer())
{
if (!mLevelRenderTargets[mipLevel])
{
- ID3D11Resource *texture = NULL;
- gl::Error error = getResource(&texture);
- if (error.isError())
- {
- return error;
- }
+ const TextureHelper11 *texture = nullptr;
+ ANGLE_TRY(getResource(context, &texture));
- ID3D11ShaderResourceView *srv = NULL;
- error = getSRVLevel(mipLevel, &srv);
- if (error.isError())
- {
- return error;
- }
+ const d3d11::SharedSRV *srv = nullptr;
+ ANGLE_TRY(getSRVLevel(context, mipLevel, false, &srv));
- ID3D11Device *device = mRenderer->getDevice();
+ const d3d11::SharedSRV *blitSRV = nullptr;
+ ANGLE_TRY(getSRVLevel(context, mipLevel, true, &blitSRV));
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- rtvDesc.Format = mRenderTargetFormat;
- rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
- rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
+ rtvDesc.Format = mFormatInfo.rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
+ rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
rtvDesc.Texture3D.FirstWSlice = 0;
- rtvDesc.Texture3D.WSize = static_cast<UINT>(-1);
-
- ID3D11RenderTargetView *rtv;
- HRESULT result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv);
-
- ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
- if (FAILED(result))
- {
- SafeRelease(srv);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result);
- }
-
- d3d11::SetDebugName(rtv, "TexStorage3D.RTV");
+ rtvDesc.Texture3D.WSize = static_cast<UINT>(-1);
- mLevelRenderTargets[mipLevel] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), getLevelDepth(mipLevel), 0);
+ d3d11::RenderTargetView rtv;
+ ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture->get(), &rtv));
+ rtv.setDebugName("TexStorage3D.RTV");
- // RenderTarget will take ownership of these resources
- SafeRelease(rtv);
+ mLevelRenderTargets[mipLevel].reset(new TextureRenderTarget11(
+ std::move(rtv), *texture, *srv, *blitSRV, mFormatInfo.internalFormat,
+ getFormatSet(), getLevelWidth(mipLevel), getLevelHeight(mipLevel),
+ getLevelDepth(mipLevel), 0));
}
ASSERT(outRT);
- *outRT = mLevelRenderTargets[mipLevel];
- return gl::Error(GL_NO_ERROR);
+ *outRT = mLevelRenderTargets[mipLevel].get();
+ return gl::NoError();
}
- else
- {
- int layer = index.layerIndex;
- LevelLayerKey key(mipLevel, layer);
- if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end())
- {
- ID3D11Device *device = mRenderer->getDevice();
- HRESULT result;
+ const int layer = index.layerIndex;
- ID3D11Resource *texture = NULL;
- gl::Error error = getResource(&texture);
- if (error.isError())
- {
- return error;
- }
-
- // TODO, what kind of SRV is expected here?
- ID3D11ShaderResourceView *srv = NULL;
-
- D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- rtvDesc.Format = mRenderTargetFormat;
- rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
- rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
- rtvDesc.Texture3D.FirstWSlice = layer;
- rtvDesc.Texture3D.WSize = 1;
-
- ID3D11RenderTargetView *rtv;
- result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv);
-
- ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
- if (FAILED(result))
- {
- SafeRelease(srv); return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result);
- }
- ASSERT(SUCCEEDED(result));
+ LevelLayerKey key(mipLevel, layer);
+ if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end())
+ {
+ const TextureHelper11 *texture = nullptr;
+ ANGLE_TRY(getResource(context, &texture));
- d3d11::SetDebugName(rtv, "TexStorage3D.LayerRTV");
+ // TODO, what kind of SRV is expected here?
+ const d3d11::SharedSRV srv;
+ const d3d11::SharedSRV blitSRV;
- mLevelLayerRenderTargets[key] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0);
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mFormatInfo.rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
+ rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
+ rtvDesc.Texture3D.FirstWSlice = layer;
+ rtvDesc.Texture3D.WSize = 1;
- // RenderTarget will take ownership of these resources
- SafeRelease(rtv);
- }
+ d3d11::RenderTargetView rtv;
+ ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture->get(), &rtv));
+ rtv.setDebugName("TexStorage3D.LayerRTV");
- ASSERT(outRT);
- *outRT = mLevelLayerRenderTargets[key];
- return gl::Error(GL_NO_ERROR);
+ mLevelLayerRenderTargets[key].reset(new TextureRenderTarget11(
+ std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0));
}
+
+ ASSERT(outRT);
+ *outRT = mLevelLayerRenderTargets[key].get();
+ return gl::NoError();
}
-gl::Error TextureStorage11_3D::getSwizzleTexture(ID3D11Resource **outTexture)
+gl::Error TextureStorage11_3D::getSwizzleTexture(const TextureHelper11 **outTexture)
{
ASSERT(outTexture);
- if (!mSwizzleTexture)
+ if (!mSwizzleTexture.valid())
{
- ID3D11Device *device = mRenderer->getDevice();
+ const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
D3D11_TEXTURE3D_DESC desc;
- desc.Width = mTextureWidth;
- desc.Height = mTextureHeight;
- desc.Depth = mTextureDepth;
- desc.MipLevels = mMipLevels;
- desc.Format = mSwizzleTextureFormat;
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.Depth = mTextureDepth;
+ desc.MipLevels = mMipLevels;
+ desc.Format = format.texFormat;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
desc.CPUAccessFlags = 0;
- desc.MiscFlags = 0;
-
- HRESULT result = device->CreateTexture3D(&desc, NULL, &mSwizzleTexture);
-
- ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle texture, result: 0x%X.", result);
- }
+ desc.MiscFlags = 0;
- d3d11::SetDebugName(mSwizzleTexture, "TexStorage3D.SwizzleTexture");
+ ANGLE_TRY(mRenderer->allocateTexture(desc, format, &mSwizzleTexture));
+ mSwizzleTexture.setDebugName("TexStorage3D.SwizzleTexture");
}
- *outTexture = mSwizzleTexture;
- return gl::Error(GL_NO_ERROR);
+ *outTexture = &mSwizzleTexture;
+ return gl::NoError();
}
-gl::Error TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV)
+gl::Error TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel,
+ const d3d11::RenderTargetView **outRTV)
{
ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
ASSERT(outRTV);
- if (!mSwizzleRenderTargets[mipLevel])
+ if (!mSwizzleRenderTargets[mipLevel].valid())
{
- ID3D11Resource *swizzleTexture = NULL;
- gl::Error error = getSwizzleTexture(&swizzleTexture);
- if (error.isError())
- {
- return error;
- }
-
- ID3D11Device *device = mRenderer->getDevice();
+ const TextureHelper11 *swizzleTexture = nullptr;
+ ANGLE_TRY(getSwizzleTexture(&swizzleTexture));
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- rtvDesc.Format = mSwizzleRenderTargetFormat;
- rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
- rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
+ rtvDesc.Format =
+ mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
+ rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
rtvDesc.Texture3D.FirstWSlice = 0;
- rtvDesc.Texture3D.WSize = static_cast<UINT>(-1);
+ rtvDesc.Texture3D.WSize = static_cast<UINT>(-1);
- HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]);
-
- ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle render target view, result: 0x%X.", result);
- }
-
- d3d11::SetDebugName(mSwizzleTexture, "TexStorage3D.SwizzleRTV");
+ ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture.get(),
+ &mSwizzleRenderTargets[mipLevel]));
+ mSwizzleRenderTargets[mipLevel].setDebugName("TexStorage3D.SwizzleRTV");
}
- *outRTV = mSwizzleRenderTargets[mipLevel];
- return gl::Error(GL_NO_ERROR);
+ *outRTV = &mSwizzleRenderTargets[mipLevel];
+ return gl::NoError();
}
-TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer11 *renderer, GLenum internalformat, bool renderTarget,
- GLsizei width, GLsizei height, GLsizei depth, int levels)
- : TextureStorage11(renderer,
- GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
- GetTextureMiscFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget, levels))
+TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer11 *renderer,
+ GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels)
+ : TextureStorage11(
+ renderer,
+ GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget),
+ GetTextureMiscFlags(internalformat,
+ renderer->getRenderer11DeviceCaps(),
+ renderTarget,
+ levels),
+ internalformat)
{
- mTexture = NULL;
- mSwizzleTexture = NULL;
-
- for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
- {
- mSwizzleRenderTargets[level] = NULL;
- }
-
- mInternalFormat = internalformat;
-
- const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getRenderer11DeviceCaps());
- mTextureFormat = formatInfo.texFormat;
- mShaderResourceFormat = formatInfo.srvFormat;
- mDepthStencilFormat = formatInfo.dsvFormat;
- mRenderTargetFormat = formatInfo.rtvFormat;
- mSwizzleTextureFormat = formatInfo.swizzleTexFormat;
- mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
- mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
-
// adjust size if needed for compressed textures
- d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel);
+ d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel);
- mMipLevels = mTopLevel + levels;
- mTextureWidth = width;
+ mMipLevels = mTopLevel + levels;
+ mTextureWidth = width;
mTextureHeight = height;
- mTextureDepth = depth;
+ mTextureDepth = depth;
}
-TextureStorage11_2DArray::~TextureStorage11_2DArray()
+gl::Error TextureStorage11_2DArray::onDestroy(const gl::Context *context)
{
- for (ImageMap::iterator i = mAssociatedImages.begin(); i != mAssociatedImages.end(); i++)
+ for (auto iter : mAssociatedImages)
{
- if (i->second)
+ if (iter.second)
{
- bool imageAssociationCorrect = i->second->isAssociatedStorageValid(this);
- ASSERT(imageAssociationCorrect);
+ iter.second->verifyAssociatedStorageValid(this);
- if (imageAssociationCorrect)
- {
- // We must let the Images recover their data before we delete it from the TextureStorage.
- i->second->recoverFromAssociatedStorage();
- }
+ // We must let the Images recover their data before we delete it from the
+ // TextureStorage.
+ ANGLE_TRY(iter.second->recoverFromAssociatedStorage(context));
}
}
mAssociatedImages.clear();
- SafeRelease(mTexture);
- SafeRelease(mSwizzleTexture);
+ InvalidateRenderTargetContainer(context, &mRenderTargets);
- for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
- {
- SafeRelease(mSwizzleRenderTargets[level]);
- }
+ return gl::NoError();
+}
- for (RenderTargetMap::iterator i = mRenderTargets.begin(); i != mRenderTargets.end(); i++)
- {
- SafeDelete(i->second);
- }
- mRenderTargets.clear();
+TextureStorage11_2DArray::~TextureStorage11_2DArray()
+{
}
-void TextureStorage11_2DArray::associateImage(Image11* image, const gl::ImageIndex &index)
+void TextureStorage11_2DArray::associateImage(Image11 *image, const gl::ImageIndex &index)
{
- GLint level = index.mipIndex;
- GLint layerTarget = index.layerIndex;
+ const GLint level = index.mipIndex;
+ const GLint layerTarget = index.layerIndex;
+ const GLint numLayers = index.numLayers;
ASSERT(0 <= level && level < getLevelCount());
if (0 <= level && level < getLevelCount())
{
- LevelLayerKey key(level, layerTarget);
+ LevelLayerRangeKey key(level, layerTarget, numLayers);
mAssociatedImages[key] = image;
}
}
-bool TextureStorage11_2DArray::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage)
+void TextureStorage11_2DArray::verifyAssociatedImageValid(const gl::ImageIndex &index,
+ Image11 *expectedImage)
{
- GLint level = index.mipIndex;
- GLint layerTarget = index.layerIndex;
+ const GLint level = index.mipIndex;
+ const GLint layerTarget = index.layerIndex;
+ const GLint numLayers = index.numLayers;
- LevelLayerKey key(level, layerTarget);
+ LevelLayerRangeKey key(level, layerTarget, numLayers);
- // This validation check should never return false. It means the Image/TextureStorage association is broken.
- bool retValue = (mAssociatedImages.find(key) != mAssociatedImages.end() && (mAssociatedImages[key] == expectedImage));
+ // This validation check should never return false. It means the Image/TextureStorage
+ // association is broken.
+ bool retValue = (mAssociatedImages.find(key) != mAssociatedImages.end() &&
+ (mAssociatedImages[key] == expectedImage));
ASSERT(retValue);
- return retValue;
}
// disassociateImage allows an Image to end its association with a Storage.
-void TextureStorage11_2DArray::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage)
+void TextureStorage11_2DArray::disassociateImage(const gl::ImageIndex &index,
+ Image11 *expectedImage)
{
- GLint level = index.mipIndex;
- GLint layerTarget = index.layerIndex;
+ const GLint level = index.mipIndex;
+ const GLint layerTarget = index.layerIndex;
+ const GLint numLayers = index.numLayers;
- LevelLayerKey key(level, layerTarget);
+ LevelLayerRangeKey key(level, layerTarget, numLayers);
- bool imageAssociationCorrect = (mAssociatedImages.find(key) != mAssociatedImages.end() && (mAssociatedImages[key] == expectedImage));
+ bool imageAssociationCorrect = (mAssociatedImages.find(key) != mAssociatedImages.end() &&
+ (mAssociatedImages[key] == expectedImage));
ASSERT(imageAssociationCorrect);
-
- if (imageAssociationCorrect)
- {
- mAssociatedImages[key] = NULL;
- }
+ mAssociatedImages[key] = nullptr;
}
-// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association.
-gl::Error TextureStorage11_2DArray::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage)
+// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
+// recover its data before ending the association.
+gl::Error TextureStorage11_2DArray::releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage)
{
- GLint level = index.mipIndex;
- GLint layerTarget = index.layerIndex;
+ const GLint level = index.mipIndex;
+ const GLint layerTarget = index.layerIndex;
+ const GLint numLayers = index.numLayers;
- LevelLayerKey key(level, layerTarget);
+ LevelLayerRangeKey key(level, layerTarget, numLayers);
if (mAssociatedImages.find(key) != mAssociatedImages.end())
{
- if (mAssociatedImages[key] != NULL && mAssociatedImages[key] != incomingImage)
+ if (mAssociatedImages[key] != nullptr && mAssociatedImages[key] != incomingImage)
{
- // Ensure that the Image is still associated with this TextureStorage. This should be true.
- bool imageAssociationCorrect = mAssociatedImages[key]->isAssociatedStorageValid(this);
- ASSERT(imageAssociationCorrect);
+ // Ensure that the Image is still associated with this TextureStorage.
+ mAssociatedImages[key]->verifyAssociatedStorageValid(this);
- if (imageAssociationCorrect)
- {
- // Force the image to recover from storage before its data is overwritten.
- // This will reset mAssociatedImages[level] to NULL too.
- gl::Error error = mAssociatedImages[key]->recoverFromAssociatedStorage();
- if (error.isError())
- {
- return error;
- }
- }
+ // Force the image to recover from storage before its data is overwritten.
+ // This will reset mAssociatedImages[level] to nullptr too.
+ ANGLE_TRY(mAssociatedImages[key]->recoverFromAssociatedStorage(context));
}
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage11_2DArray::getResource(ID3D11Resource **outResource)
+gl::Error TextureStorage11_2DArray::getResource(const gl::Context *context,
+ const TextureHelper11 **outResource)
{
// if the width, height or depth is not positive this should be treated as an incomplete texture
// we handle that here by skipping the d3d texture creation
- if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0)
+ if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0)
{
ASSERT(mMipLevels > 0);
- ID3D11Device *device = mRenderer->getDevice();
-
D3D11_TEXTURE2D_DESC desc;
- desc.Width = mTextureWidth;
- desc.Height = mTextureHeight;
- desc.MipLevels = mMipLevels;
- desc.ArraySize = mTextureDepth;
- desc.Format = mTextureFormat;
- desc.SampleDesc.Count = 1;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mMipLevels;
+ desc.ArraySize = mTextureDepth;
+ desc.Format = mFormatInfo.texFormat;
+ desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.BindFlags = getBindFlags();
- desc.CPUAccessFlags = 0;
- desc.MiscFlags = getMiscFlags();
-
- HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
-
- // this can happen from windows TDR
- if (d3d11::isDeviceLostError(result))
- {
- mRenderer->notifyDeviceLost();
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D array texture storage, result: 0x%X.", result);
- }
- else if (FAILED(result))
- {
- ASSERT(result == E_OUTOFMEMORY);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D array texture storage, result: 0x%X.", result);
- }
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = getBindFlags();
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = getMiscFlags();
- d3d11::SetDebugName(mTexture, "TexStorage2DArray.Texture");
+ ANGLE_TRY(mRenderer->allocateTexture(desc, mFormatInfo, &mTexture));
+ mTexture.setDebugName("TexStorage2DArray.Texture");
}
- *outResource = mTexture;
- return gl::Error(GL_NO_ERROR);
+ *outResource = &mTexture;
+ return gl::NoError();
}
-gl::Error TextureStorage11_2DArray::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
- ID3D11ShaderResourceView **outSRV) const
+gl::Error TextureStorage11_2DArray::createSRV(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV)
{
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
- srvDesc.Format = format;
- srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ srvDesc.Format = format;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel;
- srvDesc.Texture2DArray.MipLevels = mipLevels;
+ srvDesc.Texture2DArray.MipLevels = mipLevels;
srvDesc.Texture2DArray.FirstArraySlice = 0;
- srvDesc.Texture2DArray.ArraySize = mTextureDepth;
+ srvDesc.Texture2DArray.ArraySize = mTextureDepth;
- ID3D11Device *device = mRenderer->getDevice();
- HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV);
+ ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), outSRV));
+ outSRV->setDebugName("TexStorage2DArray.SRV");
- ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal texture storage SRV, result: 0x%X.", result);
- }
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_2DArray::createRenderTargetSRV(const TextureHelper11 &texture,
+ const gl::ImageIndex &index,
+ DXGI_FORMAT resourceFormat,
+ d3d11::SharedSRV *srv) const
+{
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = resourceFormat;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + index.mipIndex;
+ srvDesc.Texture2DArray.MipLevels = 1;
+ srvDesc.Texture2DArray.FirstArraySlice = index.layerIndex;
+ srvDesc.Texture2DArray.ArraySize = index.numLayers;
- d3d11::SetDebugName(*outSRV, "TexStorage2DArray.SRV");
+ ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), srv));
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT)
{
ASSERT(index.hasLayer());
- int mipLevel = index.mipIndex;
- int layer = index.layerIndex;
+ const int mipLevel = index.mipIndex;
+ const int layer = index.layerIndex;
+ const int numLayers = index.numLayers;
ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
- LevelLayerKey key(mipLevel, layer);
+ LevelLayerRangeKey key(mipLevel, layer, numLayers);
if (mRenderTargets.find(key) == mRenderTargets.end())
{
- ID3D11Device *device = mRenderer->getDevice();
- HRESULT result;
-
- ID3D11Resource *texture = NULL;
- gl::Error error = getResource(&texture);
- if (error.isError())
+ const TextureHelper11 *texture = nullptr;
+ ANGLE_TRY(getResource(context, &texture));
+ d3d11::SharedSRV srv;
+ ANGLE_TRY(createRenderTargetSRV(*texture, index, mFormatInfo.srvFormat, &srv));
+ d3d11::SharedSRV blitSRV;
+ if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat)
{
- return error;
+ ANGLE_TRY(createRenderTargetSRV(*texture, index, mFormatInfo.blitSRVFormat, &blitSRV));
}
-
- D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
- srvDesc.Format = mShaderResourceFormat;
- srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
- srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + mipLevel;
- srvDesc.Texture2DArray.MipLevels = 1;
- srvDesc.Texture2DArray.FirstArraySlice = layer;
- srvDesc.Texture2DArray.ArraySize = 1;
-
- ID3D11ShaderResourceView *srv;
- result = device->CreateShaderResourceView(texture, &srvDesc, &srv);
-
- ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
- if (FAILED(result))
+ else
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal shader resource view for texture storage, result: 0x%X.", result);
+ blitSRV = srv.makeCopy();
}
- d3d11::SetDebugName(srv, "TexStorage2DArray.RenderTargetSRV");
+ srv.setDebugName("TexStorage2DArray.RenderTargetSRV");
- if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
+ if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
{
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- rtvDesc.Format = mRenderTargetFormat;
- rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
- rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
+ rtvDesc.Format = mFormatInfo.rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+ rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
rtvDesc.Texture2DArray.FirstArraySlice = layer;
- rtvDesc.Texture2DArray.ArraySize = 1;
+ rtvDesc.Texture2DArray.ArraySize = numLayers;
- ID3D11RenderTargetView *rtv;
- result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv);
+ d3d11::RenderTargetView rtv;
+ ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture->get(), &rtv));
+ rtv.setDebugName("TexStorage2DArray.RenderTargetRTV");
- ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
- if (FAILED(result))
- {
- SafeRelease(srv);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result);
- }
-
- d3d11::SetDebugName(rtv, "TexStorage2DArray.RenderTargetRTV");
-
- mRenderTargets[key] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0);
-
- // RenderTarget will take ownership of these resources
- SafeRelease(rtv);
- SafeRelease(srv);
+ mRenderTargets[key].reset(new TextureRenderTarget11(
+ std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0));
}
else
{
- UNREACHABLE();
+ ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
+
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+ dsvDesc.Format = mFormatInfo.dsvFormat;
+ dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
+ dsvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
+ dsvDesc.Texture2DArray.FirstArraySlice = layer;
+ dsvDesc.Texture2DArray.ArraySize = numLayers;
+ dsvDesc.Flags = 0;
+
+ d3d11::DepthStencilView dsv;
+ ANGLE_TRY(mRenderer->allocateResource(dsvDesc, texture->get(), &dsv));
+ dsv.setDebugName("TexStorage2DArray.RenderTargetDSV");
+
+ mRenderTargets[key].reset(new TextureRenderTarget11(
+ std::move(dsv), *texture, srv, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0));
}
}
ASSERT(outRT);
- *outRT = mRenderTargets[key];
- return gl::Error(GL_NO_ERROR);
+ *outRT = mRenderTargets[key].get();
+ return gl::NoError();
}
-gl::Error TextureStorage11_2DArray::getSwizzleTexture(ID3D11Resource **outTexture)
+gl::Error TextureStorage11_2DArray::getSwizzleTexture(const TextureHelper11 **outTexture)
{
- if (!mSwizzleTexture)
+ if (!mSwizzleTexture.valid())
{
- ID3D11Device *device = mRenderer->getDevice();
+ const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
D3D11_TEXTURE2D_DESC desc;
- desc.Width = mTextureWidth;
- desc.Height = mTextureHeight;
- desc.MipLevels = mMipLevels;
- desc.ArraySize = mTextureDepth;
- desc.Format = mSwizzleTextureFormat;
- desc.SampleDesc.Count = 1;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mMipLevels;
+ desc.ArraySize = mTextureDepth;
+ desc.Format = format.texFormat;
+ desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
- desc.CPUAccessFlags = 0;
- desc.MiscFlags = 0;
-
- HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture);
-
- ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle texture, result: 0x%X.", result);
- }
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = 0;
- d3d11::SetDebugName(*outTexture, "TexStorage2DArray.SwizzleTexture");
+ ANGLE_TRY(mRenderer->allocateTexture(desc, format, &mSwizzleTexture));
+ mSwizzleTexture.setDebugName("TexStorage2DArray.SwizzleTexture");
}
- *outTexture = mSwizzleTexture;
- return gl::Error(GL_NO_ERROR);
+ *outTexture = &mSwizzleTexture;
+ return gl::NoError();
}
-gl::Error TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV)
+gl::Error TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel,
+ const d3d11::RenderTargetView **outRTV)
{
ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
ASSERT(outRTV);
- if (!mSwizzleRenderTargets[mipLevel])
+ if (!mSwizzleRenderTargets[mipLevel].valid())
{
- ID3D11Resource *swizzleTexture = NULL;
- gl::Error error = getSwizzleTexture(&swizzleTexture);
- if (error.isError())
- {
- return error;
- }
-
- ID3D11Device *device = mRenderer->getDevice();
+ const TextureHelper11 *swizzleTexture = nullptr;
+ ANGLE_TRY(getSwizzleTexture(&swizzleTexture));
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- rtvDesc.Format = mSwizzleRenderTargetFormat;
- rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
- rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
+ rtvDesc.Format =
+ mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+ rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
rtvDesc.Texture2DArray.FirstArraySlice = 0;
- rtvDesc.Texture2DArray.ArraySize = mTextureDepth;
+ rtvDesc.Texture2DArray.ArraySize = mTextureDepth;
- HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]);
+ ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture.get(),
+ &mSwizzleRenderTargets[mipLevel]));
+ }
- ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle render target view, result: 0x%X.", result);
- }
+ *outRTV = &mSwizzleRenderTargets[mipLevel];
+ return gl::NoError();
+}
+
+gl::ErrorOrResult<TextureStorage11::DropStencil> TextureStorage11_2DArray::ensureDropStencilTexture(
+ const gl::Context *context)
+{
+ if (mDropStencilTexture.valid())
+ {
+ return DropStencil::ALREADY_EXISTS;
}
- *outRTV = mSwizzleRenderTargets[mipLevel];
- return gl::Error(GL_NO_ERROR);
+ D3D11_TEXTURE2D_DESC dropDesc = {};
+ dropDesc.ArraySize = mTextureDepth;
+ dropDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
+ dropDesc.CPUAccessFlags = 0;
+ dropDesc.Format = DXGI_FORMAT_R32_TYPELESS;
+ dropDesc.Height = mTextureHeight;
+ dropDesc.MipLevels = mMipLevels;
+ dropDesc.MiscFlags = 0;
+ dropDesc.SampleDesc.Count = 1;
+ dropDesc.SampleDesc.Quality = 0;
+ dropDesc.Usage = D3D11_USAGE_DEFAULT;
+ dropDesc.Width = mTextureWidth;
+
+ const auto &format =
+ d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps());
+ ANGLE_TRY(mRenderer->allocateTexture(dropDesc, format, &mDropStencilTexture));
+ mDropStencilTexture.setDebugName("TexStorage2DArray.DropStencil");
+
+ std::vector<GLsizei> layerCounts(mMipLevels, mTextureDepth);
+
+ ANGLE_TRY(initDropStencilTexture(
+ context, gl::ImageIndexIterator::Make2DArray(0, mMipLevels, layerCounts.data())));
+
+ return DropStencil::CREATED;
}
+TextureStorage11_2DMultisample::TextureStorage11_2DMultisample(Renderer11 *renderer,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ int samples,
+ bool fixedSampleLocations)
+ : TextureStorage11(
+ renderer,
+ GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), true),
+ GetTextureMiscFlags(internalformat, renderer->getRenderer11DeviceCaps(), true, levels),
+ internalformat),
+ mTexture(),
+ mRenderTarget(nullptr)
+{
+ // adjust size if needed for compressed textures
+ d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel);
+
+ mMipLevels = 1;
+ mTextureWidth = width;
+ mTextureHeight = height;
+ mTextureDepth = 1;
+ mSamples = samples;
+ mFixedSampleLocations = fixedSampleLocations;
+}
+
+gl::Error TextureStorage11_2DMultisample::onDestroy(const gl::Context *context)
+{
+ InvalidateRenderTarget(context, mRenderTarget.get());
+ mRenderTarget.reset();
+ return gl::NoError();
}
+
+TextureStorage11_2DMultisample::~TextureStorage11_2DMultisample()
+{
+}
+
+gl::Error TextureStorage11_2DMultisample::copyToStorage(const gl::Context *context,
+ TextureStorage *destStorage)
+{
+ UNIMPLEMENTED();
+ return gl::InternalError() << "copyToStorage is unimplemented";
+}
+
+void TextureStorage11_2DMultisample::associateImage(Image11 *image, const gl::ImageIndex &index)
+{
+}
+
+void TextureStorage11_2DMultisample::verifyAssociatedImageValid(const gl::ImageIndex &index,
+ Image11 *expectedImage)
+{
+}
+
+void TextureStorage11_2DMultisample::disassociateImage(const gl::ImageIndex &index,
+ Image11 *expectedImage)
+{
+}
+
+gl::Error TextureStorage11_2DMultisample::releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage)
+{
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_2DMultisample::getResource(const gl::Context *context,
+ const TextureHelper11 **outResource)
+{
+ ANGLE_TRY(ensureTextureExists(1));
+
+ *outResource = &mTexture;
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_2DMultisample::ensureTextureExists(int mipLevels)
+{
+ // For Multisampled textures, mipLevels always equals 1.
+ ASSERT(mipLevels == 1);
+
+ // if the width or height is not positive this should be treated as an incomplete texture
+ // we handle that here by skipping the d3d texture creation
+ if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0)
+ {
+ D3D11_TEXTURE2D_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.Width = mTextureWidth; // Compressed texture size constraints?
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mipLevels;
+ desc.ArraySize = 1;
+ desc.Format = mFormatInfo.texFormat;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = getBindFlags();
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = getMiscFlags();
+
+ const gl::TextureCaps &textureCaps =
+ mRenderer->getNativeTextureCaps().get(mFormatInfo.internalFormat);
+ GLuint supportedSamples = textureCaps.getNearestSamples(mSamples);
+ desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples;
+ desc.SampleDesc.Quality = static_cast<UINT>(D3D11_STANDARD_MULTISAMPLE_PATTERN);
+
+ ANGLE_TRY(mRenderer->allocateTexture(desc, mFormatInfo, &mTexture));
+ mTexture.setDebugName("TexStorage2DMS.Texture");
+ }
+
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_2DMultisample::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT)
+{
+ ASSERT(!index.hasLayer());
+
+ const int level = index.mipIndex;
+ ASSERT(level == 0);
+
+ ASSERT(outRT);
+ if (mRenderTarget)
+ {
+ *outRT = mRenderTarget.get();
+ return gl::NoError();
+ }
+
+ const TextureHelper11 *texture = nullptr;
+ ANGLE_TRY(getResource(context, &texture));
+
+ const d3d11::SharedSRV *srv = nullptr;
+ ANGLE_TRY(getSRVLevel(context, level, false, &srv));
+
+ const d3d11::SharedSRV *blitSRV = nullptr;
+ ANGLE_TRY(getSRVLevel(context, level, true, &blitSRV));
+
+ if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mFormatInfo.rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
+
+ d3d11::RenderTargetView rtv;
+ ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture->get(), &rtv));
+
+ mRenderTarget.reset(new TextureRenderTarget11(
+ std::move(rtv), *texture, *srv, *blitSRV, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(level), getLevelHeight(level), 1, mSamples));
+
+ *outRT = mRenderTarget.get();
+ return gl::NoError();
+ }
+
+ ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
+
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+ dsvDesc.Format = mFormatInfo.dsvFormat;
+ dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
+ dsvDesc.Flags = 0;
+
+ d3d11::DepthStencilView dsv;
+ ANGLE_TRY(mRenderer->allocateResource(dsvDesc, texture->get(), &dsv));
+
+ mRenderTarget.reset(new TextureRenderTarget11(
+ std::move(dsv), *texture, *srv, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(level), getLevelHeight(level), 1, mSamples));
+
+ *outRT = mRenderTarget.get();
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_2DMultisample::createSRV(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV)
+{
+ ASSERT(outSRV);
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = format;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
+
+ ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), outSRV));
+ outSRV->setDebugName("TexStorage2DMS.SRV");
+ return gl::NoError();
+}
+
+gl::Error TextureStorage11_2DMultisample::getSwizzleTexture(const TextureHelper11 **outTexture)
+{
+ UNIMPLEMENTED();
+ return gl::InternalError() << "getSwizzleTexture is unimplemented.";
+}
+
+gl::Error TextureStorage11_2DMultisample::getSwizzleRenderTarget(
+ int mipLevel,
+ const d3d11::RenderTargetView **outRTV)
+{
+ UNIMPLEMENTED();
+ return gl::InternalError() << "getSwizzleRenderTarget is unimplemented.";
+}
+
+gl::ErrorOrResult<TextureStorage11::DropStencil>
+TextureStorage11_2DMultisample::ensureDropStencilTexture(const gl::Context *context)
+{
+ UNIMPLEMENTED();
+ return gl::InternalError() << "Drop stencil texture not implemented.";
+}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h
index a88db2f0af..336aa495a8 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h
@@ -10,10 +10,13 @@
#ifndef LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_
#define LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_
-#include "libANGLE/Texture.h"
#include "libANGLE/Error.h"
+#include "libANGLE/Texture.h"
#include "libANGLE/renderer/d3d/TextureStorage.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include <array>
#include <map>
namespace gl
@@ -31,69 +34,111 @@ class SwapChain11;
class Image11;
struct Renderer11DeviceCaps;
+template <typename T>
+using TexLevelArray = std::array<T, gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS>;
+
+template <typename T>
+using CubeFaceArray = std::array<T, gl::CUBE_FACE_COUNT>;
+
class TextureStorage11 : public TextureStorage
{
public:
- virtual ~TextureStorage11();
+ ~TextureStorage11() override;
static DWORD GetTextureBindFlags(GLenum internalFormat, const Renderer11DeviceCaps &renderer11DeviceCaps, bool renderTarget);
static DWORD GetTextureMiscFlags(GLenum internalFormat, const Renderer11DeviceCaps &renderer11DeviceCaps, bool renderTarget, int levels);
UINT getBindFlags() const;
UINT getMiscFlags() const;
-
- virtual gl::Error getResource(ID3D11Resource **outResource) = 0;
- virtual gl::Error getSRV(const gl::TextureState &textureState,
- ID3D11ShaderResourceView **outSRV);
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0;
-
- virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex);
-
- virtual int getTopLevel() const;
- virtual bool isRenderTarget() const;
- virtual bool isManaged() const;
+ const d3d11::Format &getFormatSet() const;
+ gl::Error getSRVLevels(const gl::Context *context,
+ GLint baseLevel,
+ GLint maxLevel,
+ const d3d11::SharedSRV **outSRV);
+ gl::Error generateSwizzles(const gl::Context *context, const gl::SwizzleState &swizzleTarget);
+ void markLevelDirty(int mipLevel);
+ void markDirty();
+
+ gl::Error updateSubresourceLevel(const gl::Context *context,
+ const TextureHelper11 &texture,
+ unsigned int sourceSubresource,
+ const gl::ImageIndex &index,
+ const gl::Box &copyArea);
+
+ gl::Error copySubresourceLevel(const gl::Context *context,
+ const TextureHelper11 &dstTexture,
+ unsigned int dstSubresource,
+ const gl::ImageIndex &index,
+ const gl::Box &region);
+
+ // TextureStorage virtual functions
+ int getTopLevel() const override;
+ bool isRenderTarget() const override;
+ bool isManaged() const override;
bool supportsNativeMipmapFunction() const override;
- virtual int getLevelCount() const;
+ int getLevelCount() const override;
+ gl::Error generateMipmap(const gl::Context *context,
+ const gl::ImageIndex &sourceIndex,
+ const gl::ImageIndex &destIndex) override;
+ gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
+ gl::Error setData(const gl::Context *context,
+ const gl::ImageIndex &index,
+ ImageD3D *image,
+ const gl::Box *destBox,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixelData) override;
+
+ virtual gl::Error getSRV(const gl::Context *context,
+ const gl::TextureState &textureState,
+ const d3d11::SharedSRV **outSRV);
virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const;
-
- gl::Error generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha);
- void invalidateSwizzleCacheLevel(int mipLevel);
- void invalidateSwizzleCache();
-
- gl::Error updateSubresourceLevel(ID3D11Resource *texture, unsigned int sourceSubresource,
- const gl::ImageIndex &index, const gl::Box &copyArea);
-
- gl::Error copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource,
- const gl::ImageIndex &index, const gl::Box &region);
-
+ virtual gl::Error getResource(const gl::Context *context,
+ const TextureHelper11 **outResource) = 0;
virtual void associateImage(Image11* image, const gl::ImageIndex &index) = 0;
virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) = 0;
- virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) = 0;
- virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) = 0;
-
- virtual gl::Error copyToStorage(TextureStorage *destStorage);
- virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type,
- const gl::PixelUnpackState &unpack, const uint8_t *pixelData);
-
- gl::Error getSRVLevels(GLint baseLevel, GLint maxLevel, ID3D11ShaderResourceView **outSRV);
+ virtual void verifyAssociatedImageValid(const gl::ImageIndex &index,
+ Image11 *expectedImage) = 0;
+ virtual gl::Error releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage) = 0;
protected:
- TextureStorage11(Renderer11 *renderer, UINT bindFlags, UINT miscFlags);
+ TextureStorage11(Renderer11 *renderer, UINT bindFlags, UINT miscFlags, GLenum internalFormat);
int getLevelWidth(int mipLevel) const;
int getLevelHeight(int mipLevel) const;
int getLevelDepth(int mipLevel) const;
// Some classes (e.g. TextureStorage11_2D) will override getMippedResource.
- virtual gl::Error getMippedResource(ID3D11Resource **outResource) { return getResource(outResource); }
-
- virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture) = 0;
- virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) = 0;
- gl::Error getSRVLevel(int mipLevel, ID3D11ShaderResourceView **outSRV);
+ virtual gl::Error getMippedResource(const gl::Context *context,
+ const TextureHelper11 **outResource);
+
+ virtual gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) = 0;
+ virtual gl::Error getSwizzleRenderTarget(int mipLevel,
+ const d3d11::RenderTargetView **outRTV) = 0;
+ gl::Error getSRVLevel(const gl::Context *context,
+ int mipLevel,
+ bool blitSRV,
+ const d3d11::SharedSRV **outSRV);
+
+ // Get a version of a depth texture with only depth information, not stencil.
+ enum DropStencil
+ {
+ CREATED,
+ ALREADY_EXISTS
+ };
+ virtual gl::ErrorOrResult<DropStencil> ensureDropStencilTexture(const gl::Context *context);
+ gl::Error initDropStencilTexture(const gl::Context *context, const gl::ImageIndexIterator &it);
- virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
- ID3D11ShaderResourceView **outSRV) const = 0;
+ // The baseLevel parameter should *not* have mTopLevel applied.
+ virtual gl::Error createSRV(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) = 0;
- void verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha);
+ void verifySwizzleExists(const gl::SwizzleState &swizzleState);
// Clear all cached non-swizzle SRVs and invalidate the swizzle cache.
void clearSRVCache();
@@ -102,32 +147,13 @@ class TextureStorage11 : public TextureStorage
int mTopLevel;
unsigned int mMipLevels;
- GLenum mInternalFormat;
- DXGI_FORMAT mTextureFormat;
- DXGI_FORMAT mShaderResourceFormat;
- DXGI_FORMAT mRenderTargetFormat;
- DXGI_FORMAT mDepthStencilFormat;
- DXGI_FORMAT mSwizzleTextureFormat;
- DXGI_FORMAT mSwizzleShaderResourceFormat;
- DXGI_FORMAT mSwizzleRenderTargetFormat;
+ const d3d11::Format &mFormatInfo;
unsigned int mTextureWidth;
unsigned int mTextureHeight;
unsigned int mTextureDepth;
- struct SwizzleCacheValue
- {
- GLenum swizzleRed;
- GLenum swizzleGreen;
- GLenum swizzleBlue;
- GLenum swizzleAlpha;
-
- SwizzleCacheValue();
- SwizzleCacheValue(GLenum red, GLenum green, GLenum blue, GLenum alpha);
-
- bool operator ==(const SwizzleCacheValue &other) const;
- bool operator !=(const SwizzleCacheValue &other) const;
- };
- SwizzleCacheValue mSwizzleCache[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+ TexLevelArray<gl::SwizzleState> mSwizzleCache;
+ TextureHelper11 mDropStencilTexture;
private:
const UINT mBindFlags;
@@ -135,18 +161,24 @@ class TextureStorage11 : public TextureStorage
struct SRVKey
{
- SRVKey(int baseLevel = 0, int mipLevels = 0, bool swizzle = false);
+ SRVKey(int baseLevel, int mipLevels, bool swizzle, bool dropStencil);
bool operator<(const SRVKey &rhs) const;
- int baseLevel;
- int mipLevels;
- bool swizzle;
+ int baseLevel = 0; // Without mTopLevel applied.
+ int mipLevels = 0;
+ bool swizzle = false;
+ bool dropStencil = false;
};
- typedef std::map<SRVKey, ID3D11ShaderResourceView *> SRVCache;
+ typedef std::map<SRVKey, d3d11::SharedSRV> SRVCache;
+
+ gl::Error getCachedOrCreateSRV(const gl::Context *context,
+ const SRVKey &key,
+ const d3d11::SharedSRV **outSRV);
SRVCache mSrvCache;
- ID3D11ShaderResourceView *mLevelSRVs[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+ TexLevelArray<d3d11::SharedSRV> mLevelSRVs;
+ TexLevelArray<d3d11::SharedSRV> mLevelBlitSRVs;
};
class TextureStorage11_2D : public TextureStorage11
@@ -154,33 +186,48 @@ class TextureStorage11_2D : public TextureStorage11
public:
TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain);
TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly = false);
- virtual ~TextureStorage11_2D();
+ ~TextureStorage11_2D() override;
- virtual gl::Error getResource(ID3D11Resource **outResource);
- virtual gl::Error getMippedResource(ID3D11Resource **outResource);
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+ gl::Error onDestroy(const gl::Context *context) override;
- virtual gl::Error copyToStorage(TextureStorage *destStorage);
+ gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override;
+ gl::Error getMippedResource(const gl::Context *context,
+ const TextureHelper11 **outResource) override;
+ gl::Error getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT) override;
- virtual void associateImage(Image11* image, const gl::ImageIndex &index);
- virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage);
- virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage);
- virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage);
+ gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
- virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture);
+ void associateImage(Image11 *image, const gl::ImageIndex &index) override;
+ void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ gl::Error releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage) override;
+
+ gl::Error useLevelZeroWorkaroundTexture(const gl::Context *context,
+ bool useLevelZeroTexture) override;
protected:
- virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture);
- virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV);
+ gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override;
+ gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override;
+
+ gl::ErrorOrResult<DropStencil> ensureDropStencilTexture(const gl::Context *context) override;
gl::Error ensureTextureExists(int mipLevels);
private:
- virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
- ID3D11ShaderResourceView **outSRV) const;
+ gl::Error createSRV(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) override;
- ID3D11Texture2D *mTexture;
- RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+ TextureHelper11 mTexture;
+ TexLevelArray<std::unique_ptr<RenderTarget11>> mRenderTarget;
+ bool mHasKeyedMutex;
// These are members related to the zero max-LOD workaround.
// D3D11 Feature Level 9_3 can't disable mipmaps on a mipmapped texture (i.e. solely sample from level zero).
@@ -191,108 +238,179 @@ class TextureStorage11_2D : public TextureStorage11
// One example of this is an application that creates a texture, calls glGenerateMipmap, and then disables mipmaps on the texture.
// A more likely example is an app that creates an empty texture, renders to it, and then calls glGenerateMipmap
// TODO: In this rendering scenario, release the mLevelZeroTexture after mTexture has been created to save memory.
- ID3D11Texture2D *mLevelZeroTexture;
- RenderTarget11 *mLevelZeroRenderTarget;
+ TextureHelper11 mLevelZeroTexture;
+ std::unique_ptr<RenderTarget11> mLevelZeroRenderTarget;
bool mUseLevelZeroTexture;
// Swizzle-related variables
- ID3D11Texture2D *mSwizzleTexture;
- ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+ TextureHelper11 mSwizzleTexture;
+ TexLevelArray<d3d11::RenderTargetView> mSwizzleRenderTargets;
+
+ TexLevelArray<Image11 *> mAssociatedImages;
+};
+
+class TextureStorage11_External : public TextureStorage11
+{
+ public:
+ TextureStorage11_External(Renderer11 *renderer,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &glDesc);
+ ~TextureStorage11_External() override;
+
+ gl::Error onDestroy(const gl::Context *context) override;
+
+ gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override;
+ gl::Error getMippedResource(const gl::Context *context,
+ const TextureHelper11 **outResource) override;
+ gl::Error getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT) override;
+
+ gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
+
+ void associateImage(Image11 *image, const gl::ImageIndex &index) override;
+ void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ gl::Error releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage) override;
+
+ protected:
+ gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override;
+ gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override;
+
+ private:
+ gl::Error createSRV(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) override;
+
+ TextureHelper11 mTexture;
+ int mSubresourceIndex;
+ bool mHasKeyedMutex;
- Image11 *mAssociatedImages[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+ Image11 *mAssociatedImage;
};
class TextureStorage11_EGLImage final : public TextureStorage11
{
public:
- TextureStorage11_EGLImage(Renderer11 *renderer, EGLImageD3D *eglImage);
+ TextureStorage11_EGLImage(Renderer11 *renderer,
+ EGLImageD3D *eglImage,
+ RenderTarget11 *renderTarget11);
~TextureStorage11_EGLImage() override;
- gl::Error getResource(ID3D11Resource **outResource) override;
- gl::Error getSRV(const gl::TextureState &textureState,
- ID3D11ShaderResourceView **outSRV) override;
- gl::Error getMippedResource(ID3D11Resource **outResource) override;
- gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
+ gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override;
+ gl::Error getSRV(const gl::Context *context,
+ const gl::TextureState &textureState,
+ const d3d11::SharedSRV **outSRV) override;
+ gl::Error getMippedResource(const gl::Context *context,
+ const TextureHelper11 **outResource) override;
+ gl::Error getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT) override;
- gl::Error copyToStorage(TextureStorage *destStorage) override;
+ gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
void associateImage(Image11 *image, const gl::ImageIndex &index) override;
void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
- bool isAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
- gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override;
+ void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ gl::Error releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage) override;
- gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) override;
+ gl::Error useLevelZeroWorkaroundTexture(const gl::Context *context,
+ bool useLevelZeroTexture) override;
protected:
- gl::Error getSwizzleTexture(ID3D11Resource **outTexture) override;
- gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) override;
+ gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override;
+ gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override;
private:
// Check if the EGL image's render target has been updated due to orphaning and delete
// any SRVs and other resources based on the image's old render target.
- gl::Error checkForUpdatedRenderTarget();
+ gl::Error checkForUpdatedRenderTarget(const gl::Context *context);
- gl::Error createSRV(int baseLevel,
+ gl::Error createSRV(const gl::Context *context,
+ int baseLevel,
int mipLevels,
DXGI_FORMAT format,
- ID3D11Resource *texture,
- ID3D11ShaderResourceView **outSRV) const override;
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) override;
- gl::Error getImageRenderTarget(RenderTarget11 **outRT) const;
+ gl::Error getImageRenderTarget(const gl::Context *context, RenderTarget11 **outRT) const;
EGLImageD3D *mImage;
uintptr_t mCurrentRenderTarget;
// Swizzle-related variables
- ID3D11Texture2D *mSwizzleTexture;
- std::vector<ID3D11RenderTargetView *> mSwizzleRenderTargets;
+ TextureHelper11 mSwizzleTexture;
+ std::vector<d3d11::RenderTargetView> mSwizzleRenderTargets;
};
class TextureStorage11_Cube : public TextureStorage11
{
public:
TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly);
- virtual ~TextureStorage11_Cube();
+ ~TextureStorage11_Cube() override;
- virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const;
+ gl::Error onDestroy(const gl::Context *context) override;
+
+ UINT getSubresourceIndex(const gl::ImageIndex &index) const override;
- virtual gl::Error getResource(ID3D11Resource **outResource);
- virtual gl::Error getMippedResource(ID3D11Resource **outResource);
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+ gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override;
+ gl::Error getMippedResource(const gl::Context *context,
+ const TextureHelper11 **outResource) override;
+ gl::Error getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT) override;
- virtual gl::Error copyToStorage(TextureStorage *destStorage);
+ gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
- virtual void associateImage(Image11* image, const gl::ImageIndex &index);
- virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage);
- virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage);
- virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage);
+ void associateImage(Image11 *image, const gl::ImageIndex &index) override;
+ void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ gl::Error releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage) override;
- virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture);
+ gl::Error useLevelZeroWorkaroundTexture(const gl::Context *context,
+ bool useLevelZeroTexture) override;
protected:
- virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture);
- virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV);
+ gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override;
+ gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override;
+
+ gl::ErrorOrResult<DropStencil> ensureDropStencilTexture(const gl::Context *context) override;
gl::Error ensureTextureExists(int mipLevels);
private:
- virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
- ID3D11ShaderResourceView **outSRV) const;
-
- static const size_t CUBE_FACE_COUNT = 6;
+ gl::Error createSRV(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) override;
+ gl::Error createRenderTargetSRV(const TextureHelper11 &texture,
+ const gl::ImageIndex &index,
+ DXGI_FORMAT resourceFormat,
+ d3d11::SharedSRV *srv) const;
- ID3D11Texture2D *mTexture;
- RenderTarget11 *mRenderTarget[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+ TextureHelper11 mTexture;
+ CubeFaceArray<TexLevelArray<std::unique_ptr<RenderTarget11>>> mRenderTarget;
// Level-zero workaround members. See TextureStorage11_2D's workaround members for a description.
- ID3D11Texture2D *mLevelZeroTexture;
- RenderTarget11 *mLevelZeroRenderTarget[CUBE_FACE_COUNT];
+ TextureHelper11 mLevelZeroTexture;
+ CubeFaceArray<std::unique_ptr<RenderTarget11>> mLevelZeroRenderTarget;
bool mUseLevelZeroTexture;
- ID3D11Texture2D *mSwizzleTexture;
- ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+ TextureHelper11 mSwizzleTexture;
+ TexLevelArray<d3d11::RenderTargetView> mSwizzleRenderTargets;
- Image11 *mAssociatedImages[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+ CubeFaceArray<TexLevelArray<Image11 *>> mAssociatedImages;
};
class TextureStorage11_3D : public TextureStorage11
@@ -300,37 +418,46 @@ class TextureStorage11_3D : public TextureStorage11
public:
TextureStorage11_3D(Renderer11 *renderer, GLenum internalformat, bool renderTarget,
GLsizei width, GLsizei height, GLsizei depth, int levels);
- virtual ~TextureStorage11_3D();
+ ~TextureStorage11_3D() override;
+
+ gl::Error onDestroy(const gl::Context *context) override;
- virtual gl::Error getResource(ID3D11Resource **outResource);
+ gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override;
// Handles both layer and non-layer RTs
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+ gl::Error getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT) override;
- virtual void associateImage(Image11* image, const gl::ImageIndex &index);
- virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage);
- virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage);
- virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage);
+ void associateImage(Image11 *image, const gl::ImageIndex &index) override;
+ void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ gl::Error releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage) override;
protected:
- virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture);
- virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV);
+ gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override;
+ gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override;
private:
- virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
- ID3D11ShaderResourceView **outSRV) const;
+ gl::Error createSRV(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) override;
typedef std::pair<int, int> LevelLayerKey;
- typedef std::map<LevelLayerKey, RenderTarget11*> RenderTargetMap;
- RenderTargetMap mLevelLayerRenderTargets;
+ std::map<LevelLayerKey, std::unique_ptr<RenderTarget11>> mLevelLayerRenderTargets;
- RenderTarget11 *mLevelRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+ TexLevelArray<std::unique_ptr<RenderTarget11>> mLevelRenderTargets;
- ID3D11Texture3D *mTexture;
- ID3D11Texture3D *mSwizzleTexture;
- ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+ TextureHelper11 mTexture;
+ TextureHelper11 mSwizzleTexture;
+ TexLevelArray<d3d11::RenderTargetView> mSwizzleRenderTargets;
- Image11 *mAssociatedImages[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+ TexLevelArray<Image11 *> mAssociatedImages;
};
class TextureStorage11_2DArray : public TextureStorage11
@@ -338,37 +465,125 @@ class TextureStorage11_2DArray : public TextureStorage11
public:
TextureStorage11_2DArray(Renderer11 *renderer, GLenum internalformat, bool renderTarget,
GLsizei width, GLsizei height, GLsizei depth, int levels);
- virtual ~TextureStorage11_2DArray();
+ ~TextureStorage11_2DArray() override;
+
+ gl::Error onDestroy(const gl::Context *context) override;
- virtual gl::Error getResource(ID3D11Resource **outResource);
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+ gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override;
+ gl::Error getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT) override;
- virtual void associateImage(Image11* image, const gl::ImageIndex &index);
- virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage);
- virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage);
- virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage);
+ void associateImage(Image11 *image, const gl::ImageIndex &index) override;
+ void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ gl::Error releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage) override;
protected:
- virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture);
- virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV);
+ gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override;
+ gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override;
+
+ gl::ErrorOrResult<DropStencil> ensureDropStencilTexture(const gl::Context *context) override;
private:
- virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
- ID3D11ShaderResourceView **outSRV) const;
+ struct LevelLayerRangeKey
+ {
+ LevelLayerRangeKey(int mipLevelIn, int layerIn, int numLayersIn)
+ : mipLevel(mipLevelIn), layer(layerIn), numLayers(numLayersIn)
+ {
+ }
+ bool operator<(const LevelLayerRangeKey &other) const
+ {
+ if (mipLevel != other.mipLevel)
+ {
+ return mipLevel < other.mipLevel;
+ }
+ if (layer != other.layer)
+ {
+ return layer < other.layer;
+ }
+ return numLayers < other.numLayers;
+ }
+ int mipLevel;
+ int layer;
+ int numLayers;
+ };
- typedef std::pair<int, int> LevelLayerKey;
- typedef std::map<LevelLayerKey, RenderTarget11*> RenderTargetMap;
- RenderTargetMap mRenderTargets;
+ private:
+ gl::Error createSRV(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) override;
+ gl::Error createRenderTargetSRV(const TextureHelper11 &texture,
+ const gl::ImageIndex &index,
+ DXGI_FORMAT resourceFormat,
+ d3d11::SharedSRV *srv) const;
+
+ std::map<LevelLayerRangeKey, std::unique_ptr<RenderTarget11>> mRenderTargets;
- ID3D11Texture2D *mTexture;
+ TextureHelper11 mTexture;
- ID3D11Texture2D *mSwizzleTexture;
- ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+ TextureHelper11 mSwizzleTexture;
+ TexLevelArray<d3d11::RenderTargetView> mSwizzleRenderTargets;
- typedef std::map<LevelLayerKey, Image11*> ImageMap;
+ typedef std::map<LevelLayerRangeKey, Image11 *> ImageMap;
ImageMap mAssociatedImages;
};
+class TextureStorage11_2DMultisample : public TextureStorage11
+{
+ public:
+ TextureStorage11_2DMultisample(Renderer11 *renderer,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ int samples,
+ bool fixedSampleLocations);
+ ~TextureStorage11_2DMultisample() override;
+
+ gl::Error onDestroy(const gl::Context *context) override;
+
+ gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override;
+ gl::Error getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT) override;
+
+ gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
+
+ void associateImage(Image11 *image, const gl::ImageIndex &index) override;
+ void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ gl::Error releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage) override;
+
+ protected:
+ gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override;
+ gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override;
+
+ gl::ErrorOrResult<DropStencil> ensureDropStencilTexture(const gl::Context *context) override;
+
+ gl::Error ensureTextureExists(int mipLevels);
+
+ private:
+ gl::Error createSRV(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) override;
+
+ TextureHelper11 mTexture;
+ std::unique_ptr<RenderTarget11> mRenderTarget;
+
+ unsigned int mSamples;
+ GLboolean mFixedSampleLocations;
+};
}
#endif // LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp
new file mode 100644
index 0000000000..4b08edf71f
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp
@@ -0,0 +1,124 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TransformFeedbackD3D.cpp is a no-op implementation for both the D3D9 and D3D11 renderers.
+
+#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
+
+#include "libANGLE/Buffer.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+
+namespace rx
+{
+
+TransformFeedback11::TransformFeedback11(const gl::TransformFeedbackState &state,
+ Renderer11 *renderer)
+ : TransformFeedbackImpl(state),
+ mRenderer(renderer),
+ mIsDirty(true),
+ mBuffers(state.getIndexedBuffers().size(), nullptr),
+ mBufferOffsets(state.getIndexedBuffers().size(), 0),
+ mSerial(mRenderer->generateSerial())
+{
+}
+
+TransformFeedback11::~TransformFeedback11()
+{
+}
+
+void TransformFeedback11::begin(GLenum primitiveMode)
+{
+ // Reset all the cached offsets to the binding offsets
+ mIsDirty = true;
+ for (size_t bindingIdx = 0; bindingIdx < mBuffers.size(); bindingIdx++)
+ {
+ const auto &binding = mState.getIndexedBuffer(bindingIdx);
+ if (binding.get() != nullptr)
+ {
+ mBufferOffsets[bindingIdx] = static_cast<UINT>(binding.getOffset());
+ }
+ else
+ {
+ mBufferOffsets[bindingIdx] = 0;
+ }
+ }
+}
+
+void TransformFeedback11::end()
+{
+ if (mRenderer->getWorkarounds().flushAfterEndingTransformFeedback)
+ {
+ mRenderer->getDeviceContext()->Flush();
+ }
+}
+
+void TransformFeedback11::pause()
+{
+}
+
+void TransformFeedback11::resume()
+{
+}
+
+void TransformFeedback11::bindGenericBuffer(const gl::BindingPointer<gl::Buffer> &binding)
+{
+}
+
+void TransformFeedback11::bindIndexedBuffer(size_t index,
+ const gl::OffsetBindingPointer<gl::Buffer> &binding)
+{
+ mIsDirty = true;
+ mBufferOffsets[index] = static_cast<UINT>(binding.getOffset());
+}
+
+void TransformFeedback11::onApply()
+{
+ mIsDirty = false;
+
+ // Change all buffer offsets to -1 so that if any of them need to be re-applied, the are set to
+ // append
+ std::fill(mBufferOffsets.begin(), mBufferOffsets.end(), -1);
+}
+
+bool TransformFeedback11::isDirty() const
+{
+ return mIsDirty;
+}
+
+UINT TransformFeedback11::getNumSOBuffers() const
+{
+ return static_cast<UINT>(mBuffers.size());
+}
+
+gl::ErrorOrResult<const std::vector<ID3D11Buffer *> *> TransformFeedback11::getSOBuffers(
+ const gl::Context *context)
+{
+ for (size_t bindingIdx = 0; bindingIdx < mBuffers.size(); bindingIdx++)
+ {
+ const auto &binding = mState.getIndexedBuffer(bindingIdx);
+ if (binding.get() != nullptr)
+ {
+ Buffer11 *storage = GetImplAs<Buffer11>(binding.get());
+ ANGLE_TRY_RESULT(storage->getBuffer(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK),
+ mBuffers[bindingIdx]);
+ }
+ }
+
+ return &mBuffers;
+}
+
+const std::vector<UINT> &TransformFeedback11::getSOBufferOffsets() const
+{
+ return mBufferOffsets;
+}
+
+Serial TransformFeedback11::getSerial() const
+{
+ return mSerial;
+}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h
new file mode 100644
index 0000000000..cc9fcc335a
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h
@@ -0,0 +1,60 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TransformFeedback11.h: Implements the abstract rx::TransformFeedbackImpl class.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_TRANSFORMFEEDBACK11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_TRANSFORMFEEDBACK11_H_
+
+#include "common/platform.h"
+
+#include "libANGLE/Error.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/TransformFeedbackImpl.h"
+#include "libANGLE/renderer/renderer_utils.h"
+
+namespace rx
+{
+
+class Renderer11;
+
+class TransformFeedback11 : public TransformFeedbackImpl
+{
+ public:
+ TransformFeedback11(const gl::TransformFeedbackState &state, Renderer11 *renderer);
+ ~TransformFeedback11() override;
+
+ void begin(GLenum primitiveMode) override;
+ void end() override;
+ void pause() override;
+ void resume() override;
+
+ void bindGenericBuffer(const gl::BindingPointer<gl::Buffer> &binding) override;
+ void bindIndexedBuffer(size_t index,
+ const gl::OffsetBindingPointer<gl::Buffer> &binding) override;
+
+ void onApply();
+
+ bool isDirty() const;
+
+ UINT getNumSOBuffers() const;
+ gl::ErrorOrResult<const std::vector<ID3D11Buffer *> *> getSOBuffers(const gl::Context *context);
+ const std::vector<UINT> &getSOBufferOffsets() const;
+
+ Serial getSerial() const;
+
+ private:
+ Renderer11 *mRenderer;
+
+ bool mIsDirty;
+ std::vector<ID3D11Buffer *> mBuffers;
+ std::vector<UINT> mBufferOffsets;
+
+ Serial mSerial;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_TRANSFORMFEEDBACK11_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp
index 213ce31817..29185a9d93 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp
@@ -11,9 +11,15 @@
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
#if defined (ANGLE_ENABLE_WINDOWS_STORE)
-using namespace ABI::Windows::Foundation;
+#include <wrl.h>
+#include <wrl/wrappers/corewrappers.h>
+#include <windows.applicationmodel.core.h>
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::ApplicationModel;
using namespace ABI::Windows::ApplicationModel::Core;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
#endif
namespace rx
@@ -41,7 +47,6 @@ void Trim11::trim()
#if defined (ANGLE_ENABLE_WINDOWS_STORE)
ID3D11Device* device = mRenderer->getDevice();
- // IDXGIDevice3 is only supported on Windows 8.1 and Windows Phone 8.1 and above.
IDXGIDevice3 *dxgiDevice3 = d3d11::DynamicCastComObject<IDXGIDevice3>(device);
if (dxgiDevice3)
{
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h
index 4741e81601..69fa05a57b 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h
@@ -13,9 +13,7 @@
#include "libANGLE/angletypes.h"
#include "libANGLE/Error.h"
-#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
-typedef void* EventRegistrationToken;
-#else
+#if defined(ANGLE_ENABLE_WINDOWS_STORE)
#include <EventToken.h>
#endif
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
new file mode 100644
index 0000000000..97c29415ed
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
@@ -0,0 +1,413 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// VertexArray11:
+// Implementation of rx::VertexArray11.
+//
+
+#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
+
+#include "common/bitset_utils.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+
+using namespace angle;
+
+namespace rx
+{
+
+namespace
+{
+OnBufferDataDirtyChannel *GetBufferBroadcastChannel(Buffer11 *buffer11,
+ IndexStorageType storageType)
+{
+ switch (storageType)
+ {
+ case IndexStorageType::Direct:
+ return buffer11->getDirectBroadcastChannel();
+ case IndexStorageType::Static:
+ return buffer11->getStaticBroadcastChannel();
+ case IndexStorageType::Dynamic:
+ return buffer11 ? buffer11->getStaticBroadcastChannel() : nullptr;
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+}
+} // anonymous namespace
+
+VertexArray11::VertexArray11(const gl::VertexArrayState &data)
+ : VertexArrayImpl(data),
+ mAttributeStorageTypes(data.getMaxAttribs(), VertexStorageType::CURRENT_VALUE),
+ mTranslatedAttribs(data.getMaxAttribs()),
+ mCurrentArrayBuffers(data.getMaxAttribs()),
+ mCurrentElementArrayBuffer(),
+ mOnArrayBufferDataDirty(),
+ mOnElementArrayBufferDataDirty(this, mCurrentArrayBuffers.size()),
+ mAppliedNumViewsToDivisor(1),
+ mLastElementType(GL_NONE),
+ mLastDrawElementsOffset(0),
+ mCurrentElementArrayStorage(IndexStorageType::Invalid),
+ mCachedIndexInfoValid(false)
+{
+ for (size_t attribIndex = 0; attribIndex < mCurrentArrayBuffers.size(); ++attribIndex)
+ {
+ mOnArrayBufferDataDirty.emplace_back(this, attribIndex);
+ }
+}
+
+VertexArray11::~VertexArray11()
+{
+}
+
+void VertexArray11::destroy(const gl::Context *context)
+{
+ for (auto &buffer : mCurrentArrayBuffers)
+ {
+ if (buffer.get())
+ {
+ buffer.set(context, nullptr);
+ }
+ }
+
+ mCurrentElementArrayBuffer.set(context, nullptr);
+}
+
+void VertexArray11::syncState(const gl::Context *context,
+ const gl::VertexArray::DirtyBits &dirtyBits)
+{
+ ASSERT(dirtyBits.any());
+
+ // Generate a state serial. This serial is used in the program class to validate the cached
+ // input layout, and skip recomputation in the fast path.
+ Renderer11 *renderer = GetImplAs<Context11>(context)->getRenderer();
+ mCurrentStateSerial = renderer->generateSerial();
+
+ // TODO(jmadill): Individual attribute invalidation.
+ renderer->getStateManager()->invalidateVertexBuffer();
+
+ for (auto dirtyBit : dirtyBits)
+ {
+ if (dirtyBit == gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER)
+ {
+ mCachedIndexInfoValid = false;
+ mLastElementType = GL_NONE;
+ }
+ else
+ {
+ size_t index = gl::VertexArray::GetVertexIndexFromDirtyBit(dirtyBit);
+ // TODO(jiawei.shao@intel.com): Vertex Attrib Bindings
+ ASSERT(index == mState.getBindingIndexFromAttribIndex(index));
+ mAttribsToUpdate.set(index);
+ }
+ }
+}
+
+bool VertexArray11::flushAttribUpdates(const gl::Context *context)
+{
+ if (mAttribsToUpdate.any())
+ {
+ const auto &activeLocations =
+ context->getGLState().getProgram()->getActiveAttribLocationsMask();
+
+ // Skip attrib locations the program doesn't use.
+ gl::AttributesMask activeToUpdate = mAttribsToUpdate & activeLocations;
+
+ for (auto toUpdateIndex : activeToUpdate)
+ {
+ mAttribsToUpdate.reset(toUpdateIndex);
+ updateVertexAttribStorage(context, toUpdateIndex);
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+bool VertexArray11::updateElementArrayStorage(const gl::Context *context,
+ GLenum elementType,
+ GLenum destElementType,
+ const void *indices)
+{
+ unsigned int offset = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(indices));
+
+ if (mCachedIndexInfoValid && mLastElementType == elementType &&
+ offset == mLastDrawElementsOffset)
+ {
+ // Dynamic index buffers must be re-streamed every draw.
+ return (mCurrentElementArrayStorage == IndexStorageType::Dynamic);
+ }
+
+ gl::Buffer *newBuffer = mState.getElementArrayBuffer().get();
+ gl::Buffer *oldBuffer = mCurrentElementArrayBuffer.get();
+ bool needsTranslation = false;
+ IndexStorageType newStorageType = ClassifyIndexStorage(
+ context->getGLState(), newBuffer, elementType, destElementType, offset, &needsTranslation);
+
+ if (newBuffer != oldBuffer)
+ {
+ mCurrentElementArrayBuffer.set(context, newBuffer);
+ }
+
+ if (newStorageType != mCurrentElementArrayStorage || newBuffer != oldBuffer)
+ {
+ Buffer11 *newBuffer11 = SafeGetImplAs<Buffer11>(newBuffer);
+
+ auto *newChannel = GetBufferBroadcastChannel(newBuffer11, newStorageType);
+
+ mCurrentElementArrayStorage = newStorageType;
+ mOnElementArrayBufferDataDirty.bind(newChannel);
+ needsTranslation = true;
+ }
+
+ if (mLastDrawElementsOffset != offset)
+ {
+ needsTranslation = true;
+ mLastDrawElementsOffset = offset;
+ }
+
+ if (mLastElementType != elementType)
+ {
+ needsTranslation = true;
+ mLastElementType = elementType;
+ }
+
+ // TODO(jmadill): We should probably promote static usage immediately, because this can change
+ // the storage type for dynamic buffers.
+ return needsTranslation || !mCachedIndexInfoValid;
+}
+
+void VertexArray11::updateVertexAttribStorage(const gl::Context *context, size_t attribIndex)
+{
+ const auto &attrib = mState.getVertexAttribute(attribIndex);
+ const auto &binding = mState.getBindingFromAttribIndex(attribIndex);
+
+ // Note: having an unchanged storage type doesn't mean the attribute is clean.
+ auto oldStorageType = mAttributeStorageTypes[attribIndex];
+ auto newStorageType = ClassifyAttributeStorage(attrib, binding);
+
+ mAttributeStorageTypes[attribIndex] = newStorageType;
+
+ StateManager11 *stateManager = GetImplAs<Context11>(context)->getRenderer()->getStateManager();
+
+ if (newStorageType == VertexStorageType::DYNAMIC)
+ {
+ if (oldStorageType != VertexStorageType::DYNAMIC)
+ {
+ // Sync dynamic attribs in a different set.
+ mAttribsToTranslate.reset(attribIndex);
+ mDynamicAttribsMask.set(attribIndex);
+ }
+ }
+ else
+ {
+ mAttribsToTranslate.set(attribIndex);
+ stateManager->invalidateVertexAttributeTranslation();
+
+ if (oldStorageType == VertexStorageType::DYNAMIC)
+ {
+ ASSERT(mDynamicAttribsMask[attribIndex]);
+ mDynamicAttribsMask.reset(attribIndex);
+ }
+ }
+
+ gl::Buffer *oldBufferGL = mCurrentArrayBuffers[attribIndex].get();
+ gl::Buffer *newBufferGL = binding.getBuffer().get();
+ Buffer11 *oldBuffer11 = oldBufferGL ? GetImplAs<Buffer11>(oldBufferGL) : nullptr;
+ Buffer11 *newBuffer11 = newBufferGL ? GetImplAs<Buffer11>(newBufferGL) : nullptr;
+
+ if (oldBuffer11 != newBuffer11 || oldStorageType != newStorageType)
+ {
+ OnBufferDataDirtyChannel *newChannel = nullptr;
+
+ if (newStorageType == VertexStorageType::CURRENT_VALUE)
+ {
+ stateManager->invalidateCurrentValueAttrib(attribIndex);
+ }
+ else if (newBuffer11 != nullptr)
+ {
+ // Note that for static callbacks, promotion to a static buffer from a dynamic buffer
+ // means we need to tag dynamic buffers with static callbacks.
+ switch (newStorageType)
+ {
+ case VertexStorageType::DIRECT:
+ newChannel = newBuffer11->getDirectBroadcastChannel();
+ break;
+ case VertexStorageType::STATIC:
+ case VertexStorageType::DYNAMIC:
+ newChannel = newBuffer11->getStaticBroadcastChannel();
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+
+ mOnArrayBufferDataDirty[attribIndex].bind(newChannel);
+ mCurrentArrayBuffers[attribIndex].set(context, binding.getBuffer().get());
+ }
+}
+
+bool VertexArray11::hasActiveDynamicAttrib(const gl::Context *context)
+{
+ flushAttribUpdates(context);
+ const auto &activeLocations =
+ context->getGLState().getProgram()->getActiveAttribLocationsMask();
+ auto activeDynamicAttribs = (mDynamicAttribsMask & activeLocations);
+ return activeDynamicAttribs.any();
+}
+
+gl::Error VertexArray11::updateDirtyAndDynamicAttribs(const gl::Context *context,
+ VertexDataManager *vertexDataManager,
+ const DrawCallVertexParams &vertexParams)
+{
+ flushAttribUpdates(context);
+
+ const auto &glState = context->getGLState();
+ const gl::Program *program = glState.getProgram();
+ const auto &activeLocations = program->getActiveAttribLocationsMask();
+ const auto &attribs = mState.getVertexAttributes();
+ const auto &bindings = mState.getVertexBindings();
+ mAppliedNumViewsToDivisor =
+ (program != nullptr && program->usesMultiview()) ? program->getNumViews() : 1;
+
+ if (mAttribsToTranslate.any())
+ {
+ // Skip attrib locations the program doesn't use, saving for the next frame.
+ gl::AttributesMask dirtyActiveAttribs = (mAttribsToTranslate & activeLocations);
+
+ for (auto dirtyAttribIndex : dirtyActiveAttribs)
+ {
+ mAttribsToTranslate.reset(dirtyAttribIndex);
+
+ auto *translatedAttrib = &mTranslatedAttribs[dirtyAttribIndex];
+ const auto &currentValue = glState.getVertexAttribCurrentValue(dirtyAttribIndex);
+
+ // Record basic attrib info
+ translatedAttrib->attribute = &attribs[dirtyAttribIndex];
+ translatedAttrib->binding = &bindings[translatedAttrib->attribute->bindingIndex];
+ translatedAttrib->currentValueType = currentValue.Type;
+ translatedAttrib->divisor =
+ translatedAttrib->binding->getDivisor() * mAppliedNumViewsToDivisor;
+
+ switch (mAttributeStorageTypes[dirtyAttribIndex])
+ {
+ case VertexStorageType::DIRECT:
+ VertexDataManager::StoreDirectAttrib(translatedAttrib);
+ break;
+ case VertexStorageType::STATIC:
+ {
+ ANGLE_TRY(VertexDataManager::StoreStaticAttrib(context, translatedAttrib));
+ break;
+ }
+ case VertexStorageType::CURRENT_VALUE:
+ // Current value attribs are managed by the StateManager11.
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+ }
+
+ if (mDynamicAttribsMask.any())
+ {
+ auto activeDynamicAttribs = (mDynamicAttribsMask & activeLocations);
+ if (activeDynamicAttribs.none())
+ {
+ return gl::NoError();
+ }
+
+ for (auto dynamicAttribIndex : activeDynamicAttribs)
+ {
+ auto *dynamicAttrib = &mTranslatedAttribs[dynamicAttribIndex];
+ const auto &currentValue = glState.getVertexAttribCurrentValue(dynamicAttribIndex);
+
+ // Record basic attrib info
+ dynamicAttrib->attribute = &attribs[dynamicAttribIndex];
+ dynamicAttrib->binding = &bindings[dynamicAttrib->attribute->bindingIndex];
+ dynamicAttrib->currentValueType = currentValue.Type;
+ dynamicAttrib->divisor =
+ dynamicAttrib->binding->getDivisor() * mAppliedNumViewsToDivisor;
+ }
+
+ ANGLE_TRY(vertexDataManager->storeDynamicAttribs(
+ context, &mTranslatedAttribs, activeDynamicAttribs, vertexParams.firstVertex(),
+ vertexParams.vertexCount(), vertexParams.instances()));
+ }
+
+ return gl::NoError();
+}
+
+const std::vector<TranslatedAttribute> &VertexArray11::getTranslatedAttribs() const
+{
+ return mTranslatedAttribs;
+}
+
+void VertexArray11::signal(size_t channelID, const gl::Context *context)
+{
+ if (channelID == mAttributeStorageTypes.size())
+ {
+ mCachedIndexInfoValid = false;
+ mLastElementType = GL_NONE;
+ mLastDrawElementsOffset = 0;
+ }
+ else
+ {
+ ASSERT(mAttributeStorageTypes[channelID] != VertexStorageType::CURRENT_VALUE);
+
+ // This can change a buffer's storage, we'll need to re-check.
+ mAttribsToUpdate.set(channelID);
+
+ // Changing the vertex attribute state can affect the vertex shader.
+ Renderer11 *renderer = GetImplAs<Context11>(context)->getRenderer();
+ renderer->getStateManager()->invalidateShaders();
+ }
+}
+
+void VertexArray11::clearDirtyAndPromoteDynamicAttribs(const gl::Context *context,
+ const DrawCallVertexParams &vertexParams)
+{
+ const gl::State &state = context->getGLState();
+ const gl::Program *program = state.getProgram();
+ const auto &activeLocations = program->getActiveAttribLocationsMask();
+ mAttribsToUpdate &= ~activeLocations;
+
+ // Promote to static after we clear the dirty attributes, otherwise we can lose dirtyness.
+ auto activeDynamicAttribs = (mDynamicAttribsMask & activeLocations);
+ if (activeDynamicAttribs.any())
+ {
+ VertexDataManager::PromoteDynamicAttribs(context, mTranslatedAttribs, activeDynamicAttribs,
+ vertexParams.vertexCount());
+ }
+}
+
+void VertexArray11::markAllAttributeDivisorsForAdjustment(int numViews)
+{
+ if (mAppliedNumViewsToDivisor != numViews)
+ {
+ mAppliedNumViewsToDivisor = numViews;
+ mAttribsToUpdate.set();
+ }
+}
+
+TranslatedIndexData *VertexArray11::getCachedIndexInfo()
+{
+ return &mCachedIndexInfo;
+}
+
+void VertexArray11::setCachedIndexInfoValid()
+{
+ mCachedIndexInfoValid = true;
+}
+
+bool VertexArray11::isCachedIndexInfoValid() const
+{
+ return mCachedIndexInfoValid;
+}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h
index b397140e71..4cdc92531d 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h
@@ -9,23 +9,91 @@
#ifndef LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_
#define LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_
+#include "libANGLE/Framebuffer.h"
#include "libANGLE/renderer/VertexArrayImpl.h"
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/signal_utils.h"
namespace rx
{
class Renderer11;
-class VertexArray11 : public VertexArrayImpl
+class VertexArray11 : public VertexArrayImpl, public OnBufferDataDirtyReceiver
{
public:
- VertexArray11(const gl::VertexArray::Data &data)
- : VertexArrayImpl(data)
- {
- }
- virtual ~VertexArray11() {}
+ VertexArray11(const gl::VertexArrayState &data);
+ ~VertexArray11() override;
+ void destroy(const gl::Context *context) override;
+
+ void syncState(const gl::Context *context,
+ const gl::VertexArray::DirtyBits &dirtyBits) override;
+ // This will flush any pending attrib updates and then check the dynamic attribs mask.
+ bool hasActiveDynamicAttrib(const gl::Context *context);
+ gl::Error updateDirtyAndDynamicAttribs(const gl::Context *context,
+ VertexDataManager *vertexDataManager,
+ const DrawCallVertexParams &vertexParams);
+ void clearDirtyAndPromoteDynamicAttribs(const gl::Context *context,
+ const DrawCallVertexParams &vertexParams);
+
+ const std::vector<TranslatedAttribute> &getTranslatedAttribs() const;
+
+ // SignalReceiver implementation
+ void signal(size_t channelID, const gl::Context *context) override;
+
+ Serial getCurrentStateSerial() const { return mCurrentStateSerial; }
+
+ // In case of a multi-view program change, we have to update all attributes so that the divisor
+ // is adjusted.
+ void markAllAttributeDivisorsForAdjustment(int numViews);
+
+ bool flushAttribUpdates(const gl::Context *context);
+
+ // Returns true if the element array buffer needs to be translated.
+ bool updateElementArrayStorage(const gl::Context *context,
+ GLenum elementType,
+ GLenum destElementType,
+ const void *indices);
+
+ TranslatedIndexData *getCachedIndexInfo();
+ void setCachedIndexInfoValid();
+ bool isCachedIndexInfoValid() const;
+
+ private:
+ void updateVertexAttribStorage(const gl::Context *context, size_t attribIndex);
+
+ std::vector<VertexStorageType> mAttributeStorageTypes;
+ std::vector<TranslatedAttribute> mTranslatedAttribs;
+
+ // The mask of attributes marked as dynamic.
+ gl::AttributesMask mDynamicAttribsMask;
+
+ // A mask of attributes that need to be re-evaluated.
+ gl::AttributesMask mAttribsToUpdate;
+
+ // A set of attributes we know are dirty, and need to be re-translated.
+ gl::AttributesMask mAttribsToTranslate;
+
+ // We need to keep a safe pointer to the Buffer so we can attach the correct dirty callbacks.
+ std::vector<gl::BindingPointer<gl::Buffer>> mCurrentArrayBuffers;
+ gl::BindingPointer<gl::Buffer> mCurrentElementArrayBuffer;
+
+ std::vector<OnBufferDataDirtyBinding> mOnArrayBufferDataDirty;
+ OnBufferDataDirtyBinding mOnElementArrayBufferDataDirty;
+
+ Serial mCurrentStateSerial;
+
+ // The numViews value used to adjust the divisor.
+ int mAppliedNumViewsToDivisor;
+
+ // If the index buffer needs re-streaming.
+ GLenum mLastElementType;
+ unsigned int mLastDrawElementsOffset;
+ IndexStorageType mCurrentElementArrayStorage;
+ TranslatedIndexData mCachedIndexInfo;
+ bool mCachedIndexInfoValid;
};
-}
+} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp
index 098cefcd53..611bd0f18b 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp
@@ -19,92 +19,88 @@
namespace rx
{
-VertexBuffer11::VertexBuffer11(Renderer11 *const renderer) : mRenderer(renderer)
+VertexBuffer11::VertexBuffer11(Renderer11 *const renderer)
+ : mRenderer(renderer),
+ mBuffer(),
+ mBufferSize(0),
+ mDynamicUsage(false),
+ mMappedResourceData(nullptr)
{
- mBuffer = NULL;
- mBufferSize = 0;
- mDynamicUsage = false;
- mMappedResourceData = NULL;
}
VertexBuffer11::~VertexBuffer11()
{
- ASSERT(mMappedResourceData == NULL);
- SafeRelease(mBuffer);
+ ASSERT(mMappedResourceData == nullptr);
}
gl::Error VertexBuffer11::initialize(unsigned int size, bool dynamicUsage)
{
- SafeRelease(mBuffer);
-
+ mBuffer.reset();
updateSerial();
if (size > 0)
{
- ID3D11Device* dxDevice = mRenderer->getDevice();
-
D3D11_BUFFER_DESC bufferDesc;
- bufferDesc.ByteWidth = size;
- bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
- bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
- bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
- bufferDesc.MiscFlags = 0;
+ bufferDesc.ByteWidth = size;
+ bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
+ bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ bufferDesc.MiscFlags = 0;
bufferDesc.StructureByteStride = 0;
- HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer);
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal vertex buffer of size, %lu.", size);
- }
+ ANGLE_TRY(mRenderer->allocateResource(bufferDesc, &mBuffer));
if (dynamicUsage)
{
- d3d11::SetDebugName(mBuffer, "VertexBuffer11 (dynamic)");
+ mBuffer.setDebugName("VertexBuffer11 (dynamic)");
}
else
{
- d3d11::SetDebugName(mBuffer, "VertexBuffer11 (static)");
+ mBuffer.setDebugName("VertexBuffer11 (static)");
}
}
- mBufferSize = size;
+ mBufferSize = size;
mDynamicUsage = dynamicUsage;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error VertexBuffer11::mapResource()
{
- if (mMappedResourceData == NULL)
+ if (mMappedResourceData == nullptr)
{
ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
D3D11_MAPPED_SUBRESOURCE mappedResource;
- HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
+ HRESULT result =
+ dxContext->Map(mBuffer.get(), 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer, HRESULT: 0x%08x.", result);
+ return gl::OutOfMemory()
+ << "Failed to map internal vertex buffer, " << gl::FmtHR(result);
}
- mMappedResourceData = reinterpret_cast<uint8_t*>(mappedResource.pData);
+ mMappedResourceData = reinterpret_cast<uint8_t *>(mappedResource.pData);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
void VertexBuffer11::hintUnmapResource()
{
- if (mMappedResourceData != NULL)
+ if (mMappedResourceData != nullptr)
{
ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
- dxContext->Unmap(mBuffer, 0);
+ dxContext->Unmap(mBuffer.get(), 0);
- mMappedResourceData = NULL;
+ mMappedResourceData = nullptr;
}
}
gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
GLenum currentValueType,
GLint start,
GLsizei count,
@@ -112,81 +108,33 @@ gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attri
unsigned int offset,
const uint8_t *sourceData)
{
- if (!mBuffer)
+ if (!mBuffer.valid())
{
- return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
+ return gl::OutOfMemory() << "Internal vertex buffer is not initialized.";
}
- int inputStride = static_cast<int>(ComputeVertexAttributeStride(attrib));
+ int inputStride = static_cast<int>(ComputeVertexAttributeStride(attrib, binding));
// This will map the resource if it isn't already mapped.
- gl::Error error = mapResource();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mapResource());
uint8_t *output = mMappedResourceData + offset;
const uint8_t *input = sourceData;
- if (instances == 0 || attrib.divisor == 0)
+ if (instances == 0 || binding.getDivisor() == 0)
{
input += inputStride * start;
}
gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, currentValueType);
- const D3D_FEATURE_LEVEL featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel;
- const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormatType, featureLevel);
- ASSERT(vertexFormatInfo.copyFunction != NULL);
+ const D3D_FEATURE_LEVEL featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel;
+ const d3d11::VertexFormat &vertexFormatInfo =
+ d3d11::GetVertexFormatInfo(vertexFormatType, featureLevel);
+ ASSERT(vertexFormatInfo.copyFunction != nullptr);
vertexFormatInfo.copyFunction(input, inputStride, count, output);
- return gl::Error(GL_NO_ERROR);
-}
-
-gl::Error VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count,
- GLsizei instances, unsigned int *outSpaceRequired) const
-{
- unsigned int elementCount = 0;
- if (attrib.enabled)
- {
- if (instances == 0 || attrib.divisor == 0)
- {
- elementCount = count;
- }
- else
- {
- // Round up to divisor, if possible
- elementCount = UnsignedCeilDivide(static_cast<unsigned int>(instances), attrib.divisor);
- }
-
- gl::VertexFormatType formatType = gl::GetVertexFormatType(attrib);
- const D3D_FEATURE_LEVEL featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel;
- const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(formatType, featureLevel);
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(vertexFormatInfo.nativeFormat);
- unsigned int elementSize = dxgiFormatInfo.pixelBytes;
- if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount)
- {
- if (outSpaceRequired)
- {
- *outSpaceRequired = elementSize * elementCount;
- }
- return gl::Error(GL_NO_ERROR);
- }
- else
- {
- return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow.");
- }
- }
- else
- {
- const unsigned int elementSize = 4;
- if (outSpaceRequired)
- {
- *outSpaceRequired = elementSize * 4;
- }
- return gl::Error(GL_NO_ERROR);
- }
+ return gl::NoError();
}
unsigned int VertexBuffer11::getBufferSize() const
@@ -202,34 +150,35 @@ gl::Error VertexBuffer11::setBufferSize(unsigned int size)
}
else
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
}
gl::Error VertexBuffer11::discard()
{
- if (!mBuffer)
+ if (!mBuffer.valid())
{
- return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
+ return gl::OutOfMemory() << "Internal vertex buffer is not initialized.";
}
ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
D3D11_MAPPED_SUBRESOURCE mappedResource;
- HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ HRESULT result = dxContext->Map(mBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer for discarding, HRESULT: 0x%08x", result);
+ return gl::OutOfMemory() << "Failed to map internal buffer for discarding, "
+ << gl::FmtHR(result);
}
- dxContext->Unmap(mBuffer, 0);
+ dxContext->Unmap(mBuffer.get(), 0);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-ID3D11Buffer *VertexBuffer11::getBuffer() const
+const d3d11::Buffer &VertexBuffer11::getBuffer() const
{
return mBuffer;
}
-}
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h
index 773c4474e1..ab619ae503 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h
@@ -12,6 +12,7 @@
#include <stdint.h>
#include "libANGLE/renderer/d3d/VertexBuffer.h"
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
namespace rx
{
@@ -21,11 +22,13 @@ class VertexBuffer11 : public VertexBuffer
{
public:
explicit VertexBuffer11(Renderer11 *const renderer);
- virtual ~VertexBuffer11();
- virtual gl::Error initialize(unsigned int size, bool dynamicUsage);
+ gl::Error initialize(unsigned int size, bool dynamicUsage) override;
+ // Warning: you should ensure binding really matches attrib.bindingIndex before using this
+ // function.
gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
GLenum currentValueType,
GLint start,
GLsizei count,
@@ -33,29 +36,27 @@ class VertexBuffer11 : public VertexBuffer
unsigned int offset,
const uint8_t *sourceData) override;
- virtual gl::Error getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances,
- unsigned int *outSpaceRequired) const;
+ unsigned int getBufferSize() const override;
+ gl::Error setBufferSize(unsigned int size) override;
+ gl::Error discard() override;
- virtual unsigned int getBufferSize() const;
- virtual gl::Error setBufferSize(unsigned int size);
- virtual gl::Error discard();
+ void hintUnmapResource() override;
- virtual void hintUnmapResource();
-
- ID3D11Buffer *getBuffer() const;
+ const d3d11::Buffer &getBuffer() const;
private:
+ ~VertexBuffer11() override;
gl::Error mapResource();
Renderer11 *const mRenderer;
- ID3D11Buffer *mBuffer;
+ d3d11::Buffer mBuffer;
unsigned int mBufferSize;
bool mDynamicUsage;
uint8_t *mMappedResourceData;
};
-}
+} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_D3D11_VERTEXBUFFER11_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl
index 1ec21dee55..7c5c157c6f 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl
@@ -15,33 +15,42 @@ inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t cou
if (attribSize == stride && inputComponentCount == outputComponentCount)
{
memcpy(output, input, count * attribSize);
+ return;
}
- else
- {
- const T defaultAlphaValue = gl::bitCast<T>(alphaDefaultValueBits);
- const size_t lastNonAlphaOutputComponent = std::min<size_t>(outputComponentCount, 3);
+ if (inputComponentCount == outputComponentCount)
+ {
for (size_t i = 0; i < count; i++)
{
const T *offsetInput = reinterpret_cast<const T*>(input + (i * stride));
T *offsetOutput = reinterpret_cast<T*>(output) + i * outputComponentCount;
- for (size_t j = 0; j < inputComponentCount; j++)
- {
- offsetOutput[j] = offsetInput[j];
- }
+ memcpy(offsetOutput, offsetInput, attribSize);
+ }
+ return;
+ }
- for (size_t j = inputComponentCount; j < lastNonAlphaOutputComponent; j++)
- {
- // Set the remaining G/B channels to 0.
- offsetOutput[j] = 0;
- }
+ const T defaultAlphaValue = gl::bitCast<T>(alphaDefaultValueBits);
+ const size_t lastNonAlphaOutputComponent = std::min<size_t>(outputComponentCount, 3);
- if (inputComponentCount < outputComponentCount && outputComponentCount == 4)
- {
- // Set the remaining alpha channel to the defaultAlphaValue.
- offsetOutput[3] = defaultAlphaValue;
- }
+ for (size_t i = 0; i < count; i++)
+ {
+ const T *offsetInput = reinterpret_cast<const T*>(input + (i * stride));
+ T *offsetOutput = reinterpret_cast<T*>(output) + i * outputComponentCount;
+
+ memcpy(offsetOutput, offsetInput, attribSize);
+
+ if (inputComponentCount < lastNonAlphaOutputComponent)
+ {
+ // Set the remaining G/B channels to 0.
+ size_t numComponents = (lastNonAlphaOutputComponent - inputComponentCount);
+ memset(&offsetOutput[inputComponentCount], 0, numComponents * sizeof(T));
+ }
+
+ if (inputComponentCount < outputComponentCount && outputComponentCount == 4)
+ {
+ // Set the remaining alpha channel to the defaultAlphaValue.
+ offsetOutput[3] = defaultAlphaValue;
}
}
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_data.json b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_data.json
new file mode 100644
index 0000000000..891d30d252
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_data.json
@@ -0,0 +1,118 @@
+{
+ "UNKNOWN": "NONE",
+ "R32G32B32A32_TYPELESS": "",
+ "R32G32B32A32_FLOAT": "",
+ "R32G32B32A32_UINT": "",
+ "R32G32B32A32_SINT": "",
+ "R32G32B32_TYPELESS": "",
+ "R32G32B32_FLOAT": "",
+ "R32G32B32_UINT": "",
+ "R32G32B32_SINT": "",
+ "R16G16B16A16_TYPELESS": "",
+ "R16G16B16A16_FLOAT": "",
+ "R16G16B16A16_UNORM": "",
+ "R16G16B16A16_UINT": "",
+ "R16G16B16A16_SNORM": "",
+ "R16G16B16A16_SINT": "",
+ "R32G32_TYPELESS": "",
+ "R32G32_FLOAT": "",
+ "R32G32_UINT": "",
+ "R32G32_SINT": "",
+ "R32G8X24_TYPELESS": "",
+ "D32_FLOAT_S8X24_UINT": "",
+ "R32_FLOAT_X8X24_TYPELESS": "",
+ "X32_TYPELESS_G8X24_UINT": "",
+ "R10G10B10A2_TYPELESS": "",
+ "R10G10B10A2_UNORM": "",
+ "R10G10B10A2_UINT": "",
+ "R11G11B10_FLOAT": "",
+ "R8G8B8A8_TYPELESS": "",
+ "R8G8B8A8_UNORM": "",
+ "R8G8B8A8_UNORM_SRGB": "",
+ "R8G8B8A8_UINT": "",
+ "R8G8B8A8_SNORM": "",
+ "R8G8B8A8_SINT": "",
+ "R16G16_TYPELESS": "",
+ "R16G16_FLOAT": "",
+ "R16G16_UNORM": "",
+ "R16G16_UINT": "",
+ "R16G16_SNORM": "",
+ "R16G16_SINT": "",
+ "R32_TYPELESS": "",
+ "D32_FLOAT": "",
+ "R32_FLOAT": "",
+ "R32_UINT": "",
+ "R32_SINT": "",
+ "R24G8_TYPELESS": "",
+ "D24_UNORM_S8_UINT": "",
+ "R24_UNORM_X8_TYPELESS": "",
+ "X24_TYPELESS_G8_UINT": "",
+ "R8G8_TYPELESS": "",
+ "R8G8_UNORM": "",
+ "R8G8_UINT": "",
+ "R8G8_SNORM": "",
+ "R8G8_SINT": "",
+ "R16_TYPELESS": "",
+ "R16_FLOAT": "",
+ "D16_UNORM": "",
+ "R16_UNORM": "",
+ "R16_UINT": "",
+ "R16_SNORM": "",
+ "R16_SINT": "",
+ "R8_TYPELESS": "",
+ "R8_UNORM": "",
+ "R8_UINT": "",
+ "R8_SNORM": "",
+ "R8_SINT": "",
+ "A8_UNORM": "",
+ "R1_UNORM": "",
+ "R9G9B9E5_SHAREDEXP": "",
+ "R8G8_B8G8_UNORM": "",
+ "G8R8_G8B8_UNORM": "",
+ "BC1_TYPELESS": "",
+ "BC1_UNORM": "BC1_RGBA_UNORM_BLOCK",
+ "BC1_UNORM_SRGB": "BC1_RGBA_UNORM_SRGB_BLOCK",
+ "BC2_TYPELESS": "",
+ "BC2_UNORM": "BC2_RGBA_UNORM_BLOCK",
+ "BC2_UNORM_SRGB": "BC2_RGBA_UNORM_SRGB_BLOCK",
+ "BC3_TYPELESS": "",
+ "BC3_UNORM": "BC3_RGBA_UNORM_BLOCK",
+ "BC3_UNORM_SRGB": "BC3_RGBA_UNORM_SRGB_BLOCK",
+ "BC4_TYPELESS": "",
+ "BC4_UNORM": "",
+ "BC4_SNORM": "",
+ "BC5_TYPELESS": "",
+ "BC5_UNORM": "",
+ "BC5_SNORM": "",
+ "B5G6R5_UNORM": "",
+ "B5G5R5A1_UNORM": "",
+ "B8G8R8A8_UNORM": "",
+ "B8G8R8X8_UNORM": "",
+ "R10G10B10_XR_BIAS_A2_UNORM": "",
+ "B8G8R8A8_TYPELESS": "",
+ "B8G8R8A8_UNORM_SRGB": "",
+ "B8G8R8X8_TYPELESS": "",
+ "B8G8R8X8_UNORM_SRGB": "",
+ "BC6H_TYPELESS": "",
+ "BC6H_UF16": "",
+ "BC6H_SF16": "",
+ "BC7_TYPELESS": "",
+ "BC7_UNORM": "",
+ "BC7_UNORM_SRGB": "",
+ "AYUV": "",
+ "Y410": "",
+ "Y416": "",
+ "NV12": "",
+ "P010": "",
+ "P016": "",
+ "420_OPAQUE": "",
+ "YUY2": "",
+ "Y210": "",
+ "Y216": "",
+ "NV11": "",
+ "AI44": "",
+ "IA44": "",
+ "P8": "",
+ "A8P8": "",
+ "B4G4R4A4_UNORM": ""
+}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_map_autogen.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_map_autogen.cpp
new file mode 100644
index 0000000000..b0697bc5db
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_map_autogen.cpp
@@ -0,0 +1,516 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_dxgi_format_table.py using data from dxgi_format_data.json.
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DXGI format info:
+// Determining metadata about a DXGI format.
+
+#include "libANGLE/renderer/Format.h"
+
+using namespace angle;
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+GLenum GetComponentType(DXGI_FORMAT dxgiFormat)
+{
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_420_OPAQUE:
+ break;
+ case DXGI_FORMAT_A8P8:
+ break;
+ case DXGI_FORMAT_A8_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_AI44:
+ break;
+ case DXGI_FORMAT_AYUV:
+ break;
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ break;
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+ break;
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_BC1_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC1_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_BC2_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC2_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_BC3_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC3_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_BC4_SNORM:
+ return GL_SIGNED_NORMALIZED;
+ case DXGI_FORMAT_BC4_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC4_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_BC5_SNORM:
+ return GL_SIGNED_NORMALIZED;
+ case DXGI_FORMAT_BC5_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC5_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_BC6H_SF16:
+ break;
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC6H_UF16:
+ break;
+ case DXGI_FORMAT_BC7_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC7_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_D16_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ break;
+ case DXGI_FORMAT_D32_FLOAT:
+ return GL_FLOAT;
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ break;
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_IA44:
+ break;
+ case DXGI_FORMAT_NV11:
+ break;
+ case DXGI_FORMAT_NV12:
+ break;
+ case DXGI_FORMAT_P010:
+ break;
+ case DXGI_FORMAT_P016:
+ break;
+ case DXGI_FORMAT_P8:
+ break;
+ case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+ break;
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ return GL_FLOAT;
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ return GL_FLOAT;
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ return GL_INT;
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ return GL_SIGNED_NORMALIZED;
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ break;
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_R16G16_FLOAT:
+ return GL_FLOAT;
+ case DXGI_FORMAT_R16G16_SINT:
+ return GL_INT;
+ case DXGI_FORMAT_R16G16_SNORM:
+ return GL_SIGNED_NORMALIZED;
+ case DXGI_FORMAT_R16G16_TYPELESS:
+ break;
+ case DXGI_FORMAT_R16G16_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_R16G16_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_R16_FLOAT:
+ return GL_FLOAT;
+ case DXGI_FORMAT_R16_SINT:
+ return GL_INT;
+ case DXGI_FORMAT_R16_SNORM:
+ return GL_SIGNED_NORMALIZED;
+ case DXGI_FORMAT_R16_TYPELESS:
+ break;
+ case DXGI_FORMAT_R16_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_R16_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_R1_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ break;
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ return GL_FLOAT;
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ return GL_INT;
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ return GL_FLOAT;
+ case DXGI_FORMAT_R32G32B32_SINT:
+ return GL_INT;
+ case DXGI_FORMAT_R32G32B32_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32G32B32_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_R32G32_FLOAT:
+ return GL_FLOAT;
+ case DXGI_FORMAT_R32G32_SINT:
+ return GL_INT;
+ case DXGI_FORMAT_R32G32_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32G32_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32_FLOAT:
+ return GL_FLOAT;
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ return GL_FLOAT;
+ case DXGI_FORMAT_R32_SINT:
+ return GL_INT;
+ case DXGI_FORMAT_R32_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ return GL_INT;
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ return GL_SIGNED_NORMALIZED;
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ break;
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_R8G8_SINT:
+ return GL_INT;
+ case DXGI_FORMAT_R8G8_SNORM:
+ return GL_SIGNED_NORMALIZED;
+ case DXGI_FORMAT_R8G8_TYPELESS:
+ break;
+ case DXGI_FORMAT_R8G8_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_R8G8_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_R8_SINT:
+ return GL_INT;
+ case DXGI_FORMAT_R8_SNORM:
+ return GL_SIGNED_NORMALIZED;
+ case DXGI_FORMAT_R8_TYPELESS:
+ break;
+ case DXGI_FORMAT_R8_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_R8_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ return GL_FLOAT;
+ case DXGI_FORMAT_UNKNOWN:
+ break;
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_Y210:
+ break;
+ case DXGI_FORMAT_Y216:
+ break;
+ case DXGI_FORMAT_Y410:
+ break;
+ case DXGI_FORMAT_Y416:
+ break;
+ case DXGI_FORMAT_YUY2:
+ break;
+ default:
+ break;
+ }
+
+ UNREACHABLE();
+ return GL_NONE;
+}
+
+} // namespace d3d11
+
+namespace d3d11_angle
+{
+
+const Format &GetFormat(DXGI_FORMAT dxgiFormat)
+{
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_420_OPAQUE:
+ break;
+ case DXGI_FORMAT_A8P8:
+ break;
+ case DXGI_FORMAT_A8_UNORM:
+ return Format::Get(Format::ID::A8_UNORM);
+ case DXGI_FORMAT_AI44:
+ break;
+ case DXGI_FORMAT_AYUV:
+ break;
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ return Format::Get(Format::ID::B4G4R4A4_UNORM);
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ return Format::Get(Format::ID::B5G5R5A1_UNORM);
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ return Format::Get(Format::ID::B5G6R5_UNORM);
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ break;
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ return Format::Get(Format::ID::B8G8R8A8_UNORM);
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ return Format::Get(Format::ID::B8G8R8A8_UNORM_SRGB);
+ case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+ break;
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ return Format::Get(Format::ID::B8G8R8X8_UNORM);
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ break;
+ case DXGI_FORMAT_BC1_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC1_UNORM:
+ return Format::Get(Format::ID::BC1_RGBA_UNORM_BLOCK);
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ return Format::Get(Format::ID::BC1_RGBA_UNORM_SRGB_BLOCK);
+ case DXGI_FORMAT_BC2_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC2_UNORM:
+ return Format::Get(Format::ID::BC2_RGBA_UNORM_BLOCK);
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ return Format::Get(Format::ID::BC2_RGBA_UNORM_SRGB_BLOCK);
+ case DXGI_FORMAT_BC3_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC3_UNORM:
+ return Format::Get(Format::ID::BC3_RGBA_UNORM_BLOCK);
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ return Format::Get(Format::ID::BC3_RGBA_UNORM_SRGB_BLOCK);
+ case DXGI_FORMAT_BC4_SNORM:
+ break;
+ case DXGI_FORMAT_BC4_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC4_UNORM:
+ break;
+ case DXGI_FORMAT_BC5_SNORM:
+ break;
+ case DXGI_FORMAT_BC5_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC5_UNORM:
+ break;
+ case DXGI_FORMAT_BC6H_SF16:
+ break;
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC6H_UF16:
+ break;
+ case DXGI_FORMAT_BC7_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC7_UNORM:
+ break;
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ break;
+ case DXGI_FORMAT_D16_UNORM:
+ return Format::Get(Format::ID::D16_UNORM);
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ return Format::Get(Format::ID::D24_UNORM_S8_UINT);
+ case DXGI_FORMAT_D32_FLOAT:
+ return Format::Get(Format::ID::D32_FLOAT);
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ return Format::Get(Format::ID::D32_FLOAT_S8X24_UINT);
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ break;
+ case DXGI_FORMAT_IA44:
+ break;
+ case DXGI_FORMAT_NV11:
+ break;
+ case DXGI_FORMAT_NV12:
+ break;
+ case DXGI_FORMAT_P010:
+ break;
+ case DXGI_FORMAT_P016:
+ break;
+ case DXGI_FORMAT_P8:
+ break;
+ case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+ break;
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ return Format::Get(Format::ID::R10G10B10A2_UINT);
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ return Format::Get(Format::ID::R10G10B10A2_UNORM);
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+ break;
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ return Format::Get(Format::ID::R11G11B10_FLOAT);
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ return Format::Get(Format::ID::R16G16B16A16_FLOAT);
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ return Format::Get(Format::ID::R16G16B16A16_SINT);
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ return Format::Get(Format::ID::R16G16B16A16_SNORM);
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ break;
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ return Format::Get(Format::ID::R16G16B16A16_UINT);
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ return Format::Get(Format::ID::R16G16B16A16_UNORM);
+ case DXGI_FORMAT_R16G16_FLOAT:
+ return Format::Get(Format::ID::R16G16_FLOAT);
+ case DXGI_FORMAT_R16G16_SINT:
+ return Format::Get(Format::ID::R16G16_SINT);
+ case DXGI_FORMAT_R16G16_SNORM:
+ return Format::Get(Format::ID::R16G16_SNORM);
+ case DXGI_FORMAT_R16G16_TYPELESS:
+ break;
+ case DXGI_FORMAT_R16G16_UINT:
+ return Format::Get(Format::ID::R16G16_UINT);
+ case DXGI_FORMAT_R16G16_UNORM:
+ return Format::Get(Format::ID::R16G16_UNORM);
+ case DXGI_FORMAT_R16_FLOAT:
+ return Format::Get(Format::ID::R16_FLOAT);
+ case DXGI_FORMAT_R16_SINT:
+ return Format::Get(Format::ID::R16_SINT);
+ case DXGI_FORMAT_R16_SNORM:
+ return Format::Get(Format::ID::R16_SNORM);
+ case DXGI_FORMAT_R16_TYPELESS:
+ break;
+ case DXGI_FORMAT_R16_UINT:
+ return Format::Get(Format::ID::R16_UINT);
+ case DXGI_FORMAT_R16_UNORM:
+ return Format::Get(Format::ID::R16_UNORM);
+ case DXGI_FORMAT_R1_UNORM:
+ break;
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ break;
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ return Format::Get(Format::ID::R32G32B32A32_FLOAT);
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ return Format::Get(Format::ID::R32G32B32A32_SINT);
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ return Format::Get(Format::ID::R32G32B32A32_UINT);
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ return Format::Get(Format::ID::R32G32B32_FLOAT);
+ case DXGI_FORMAT_R32G32B32_SINT:
+ return Format::Get(Format::ID::R32G32B32_SINT);
+ case DXGI_FORMAT_R32G32B32_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32G32B32_UINT:
+ return Format::Get(Format::ID::R32G32B32_UINT);
+ case DXGI_FORMAT_R32G32_FLOAT:
+ return Format::Get(Format::ID::R32G32_FLOAT);
+ case DXGI_FORMAT_R32G32_SINT:
+ return Format::Get(Format::ID::R32G32_SINT);
+ case DXGI_FORMAT_R32G32_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32G32_UINT:
+ return Format::Get(Format::ID::R32G32_UINT);
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32_FLOAT:
+ return Format::Get(Format::ID::R32_FLOAT);
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32_SINT:
+ return Format::Get(Format::ID::R32_SINT);
+ case DXGI_FORMAT_R32_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32_UINT:
+ return Format::Get(Format::ID::R32_UINT);
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ return Format::Get(Format::ID::R8G8B8A8_SINT);
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ return Format::Get(Format::ID::R8G8B8A8_SNORM);
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ break;
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ return Format::Get(Format::ID::R8G8B8A8_UINT);
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ return Format::Get(Format::ID::R8G8B8A8_UNORM);
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ return Format::Get(Format::ID::R8G8B8A8_UNORM_SRGB);
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ break;
+ case DXGI_FORMAT_R8G8_SINT:
+ return Format::Get(Format::ID::R8G8_SINT);
+ case DXGI_FORMAT_R8G8_SNORM:
+ return Format::Get(Format::ID::R8G8_SNORM);
+ case DXGI_FORMAT_R8G8_TYPELESS:
+ break;
+ case DXGI_FORMAT_R8G8_UINT:
+ return Format::Get(Format::ID::R8G8_UINT);
+ case DXGI_FORMAT_R8G8_UNORM:
+ return Format::Get(Format::ID::R8G8_UNORM);
+ case DXGI_FORMAT_R8_SINT:
+ return Format::Get(Format::ID::R8_SINT);
+ case DXGI_FORMAT_R8_SNORM:
+ return Format::Get(Format::ID::R8_SNORM);
+ case DXGI_FORMAT_R8_TYPELESS:
+ break;
+ case DXGI_FORMAT_R8_UINT:
+ return Format::Get(Format::ID::R8_UINT);
+ case DXGI_FORMAT_R8_UNORM:
+ return Format::Get(Format::ID::R8_UNORM);
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ return Format::Get(Format::ID::R9G9B9E5_SHAREDEXP);
+ case DXGI_FORMAT_UNKNOWN:
+ return Format::Get(Format::ID::NONE);
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ break;
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ break;
+ case DXGI_FORMAT_Y210:
+ break;
+ case DXGI_FORMAT_Y216:
+ break;
+ case DXGI_FORMAT_Y410:
+ break;
+ case DXGI_FORMAT_Y416:
+ break;
+ case DXGI_FORMAT_YUY2:
+ break;
+ default:
+ break;
+ }
+
+ UNREACHABLE();
+ return Format::Get(Format::ID::NONE);
+}
+
+} // namespace d3d11_angle
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_data.json b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_data.json
index e81b4deea5..942745674f 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_data.json
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_data.json
@@ -8,7 +8,8 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R32G32B32A32_TYPELESS":
{
@@ -18,7 +19,8 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R32G32B32A32_FLOAT":
{
@@ -28,27 +30,30 @@
"shaderSample": "10_0check10_1always",
"renderTarget": "always",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "always"
},
"DXGI_FORMAT_R32G32B32A32_UINT":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "never",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R32G32B32A32_SINT":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "never",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R32G32B32_TYPELESS":
{
@@ -58,7 +63,8 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R32G32B32_FLOAT":
{
@@ -68,7 +74,8 @@
"shaderSample": "11_0check",
"renderTarget": "check",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R32G32B32_UINT":
{
@@ -78,7 +85,8 @@
"shaderSample": "never",
"renderTarget": "check",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R32G32B32_SINT":
{
@@ -88,7 +96,8 @@
"shaderSample": "never",
"renderTarget": "check",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R16G16B16A16_TYPELESS":
{
@@ -98,57 +107,63 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R16G16B16A16_FLOAT":
{
"texture2D": "always",
"texture3D": "always",
"textureCube": "always",
- "shaderSample": "10_0",
+ "shaderSample": "9_3check_10_0always",
"renderTarget": "always",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "always"
},
"DXGI_FORMAT_R16G16B16A16_UNORM":
{
"texture2D": "always",
"texture3D": "always",
"textureCube": "always",
- "shaderSample": "10_0",
+ "shaderSample": "always",
"renderTarget": "always",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "always"
},
"DXGI_FORMAT_R16G16B16A16_UINT":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "never",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R16G16B16A16_SNORM":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "10_0",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
},
"DXGI_FORMAT_R16G16B16A16_SINT":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "never",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R32G32_TYPELESS":
{
@@ -158,7 +173,8 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R32G32_FLOAT":
{
@@ -168,37 +184,41 @@
"shaderSample": "10_0check10_1always",
"renderTarget": "always",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
},
"DXGI_FORMAT_R32G32_UINT":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "never",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R32G32_SINT":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "never",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R32G8X24_TYPELESS":
{
- "texture2D": "always",
+ "texture2D": "10_0",
"texture3D": "never",
- "textureCube": "always",
+ "textureCube": "10_0",
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_D32_FLOAT_S8X24_UINT":
{
@@ -208,7 +228,8 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "check",
- "depthStencil": "always"
+ "depthStencil": "10_0",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS":
{
@@ -218,7 +239,8 @@
"shaderSample": "10_0check10_1always",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_X32_TYPELESS_G8X24_UINT":
{
@@ -228,47 +250,52 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R10G10B10A2_TYPELESS":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R10G10B10A2_UNORM":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "10_0",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
},
"DXGI_FORMAT_R10G10B10A2_UINT":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "never",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R11G11B10_FLOAT":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "10_0",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
},
"DXGI_FORMAT_R8G8B8A8_TYPELESS":
{
@@ -278,57 +305,63 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R8G8B8A8_UNORM":
{
"texture2D": "always",
"texture3D": "always",
"textureCube": "always",
- "shaderSample": "10_0",
+ "shaderSample": "always",
"renderTarget": "always",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "always"
},
"DXGI_FORMAT_R8G8B8A8_UNORM_SRGB":
{
"texture2D": "always",
"texture3D": "always",
"textureCube": "always",
- "shaderSample": "10_0",
+ "shaderSample": "always",
"renderTarget": "always",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "always"
},
"DXGI_FORMAT_R8G8B8A8_UINT":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "never",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R8G8B8A8_SNORM":
{
"texture2D": "always",
"texture3D": "always",
"textureCube": "always",
- "shaderSample": "10_0",
+ "shaderSample": "always",
"renderTarget": "always",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
},
"DXGI_FORMAT_R8G8B8A8_SINT":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "never",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R16G16_TYPELESS":
{
@@ -338,7 +371,8 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R16G16_FLOAT":
{
@@ -348,57 +382,63 @@
"shaderSample": "10_0",
"renderTarget": "always",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "always"
},
"DXGI_FORMAT_R16G16_UNORM":
{
"texture2D": "always",
"texture3D": "always",
"textureCube": "always",
- "shaderSample": "10_0",
+ "shaderSample": "always",
"renderTarget": "always",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "always"
},
"DXGI_FORMAT_R16G16_UINT":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "never",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R16G16_SNORM":
{
"texture2D": "always",
"texture3D": "always",
"textureCube": "always",
- "shaderSample": "10_0",
+ "shaderSample": "always",
"renderTarget": "always",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
},
"DXGI_FORMAT_R16G16_SINT":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "never",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R32_TYPELESS":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_D32_FLOAT":
{
@@ -408,7 +448,8 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "check",
- "depthStencil": "always"
+ "depthStencil": "10_0",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R32_FLOAT":
{
@@ -418,27 +459,30 @@
"shaderSample": "10_0check10_1always",
"renderTarget": "always",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "always"
},
"DXGI_FORMAT_R32_UINT":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "never",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R32_SINT":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "never",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R24G8_TYPELESS":
{
@@ -448,7 +492,8 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_D24_UNORM_S8_UINT":
{
@@ -468,7 +513,8 @@
"shaderSample": "10_0check10_1always",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_X24_TYPELESS_G8_UINT":
{
@@ -478,7 +524,8 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R8G8_TYPELESS":
{
@@ -488,47 +535,52 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R8G8_UNORM":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
- "shaderSample": "10_0",
- "renderTarget": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "9_3check_10_0always",
+ "renderTarget": "9_3check_10_0always",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
},
"DXGI_FORMAT_R8G8_UINT":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "never",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R8G8_SNORM":
{
"texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
- "shaderSample": "10_0",
- "renderTarget": "always",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
+ "shaderSample": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
},
"DXGI_FORMAT_R8G8_SINT":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "never",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R16_TYPELESS":
{
@@ -538,17 +590,19 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R16_FLOAT":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "10_0",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
},
"DXGI_FORMAT_D16_UNORM":
{
@@ -558,47 +612,52 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "check",
- "depthStencil": "always"
+ "depthStencil": "always",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R16_UNORM":
{
"texture2D": "always",
"texture3D": "always",
"textureCube": "always",
- "shaderSample": "10_0",
- "renderTarget": "always",
+ "shaderSample": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
},
"DXGI_FORMAT_R16_UINT":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "never",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R16_SNORM":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "10_0",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
},
"DXGI_FORMAT_R16_SINT":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "never",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R8_TYPELESS":
{
@@ -608,47 +667,52 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R8_UNORM":
{
"texture2D": "always",
"texture3D": "always",
"textureCube": "always",
- "shaderSample": "10_0",
- "renderTarget": "always",
+ "shaderSample": "always",
+ "renderTarget": "9_3check_10_0always",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
},
"DXGI_FORMAT_R8_UINT":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "never",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R8_SNORM":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "10_0",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
},
"DXGI_FORMAT_R8_SINT":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "never",
- "renderTarget": "always",
+ "renderTarget": "10_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_A8_UNORM":
{
@@ -658,7 +722,8 @@
"shaderSample": "10_0",
"renderTarget": "always",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "10_0"
},
"DXGI_FORMAT_R1_UNORM":
{
@@ -668,17 +733,19 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R9G9B9E5_SHAREDEXP":
{
- "texture2D": "always",
- "texture3D": "always",
- "textureCube": "always",
+ "texture2D": "10_0",
+ "texture3D": "10_0",
+ "textureCube": "10_0",
"shaderSample": "10_0",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R8G8_B8G8_UNORM":
{
@@ -688,7 +755,8 @@
"shaderSample": "10_0",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_G8R8_G8B8_UNORM":
{
@@ -698,7 +766,8 @@
"shaderSample": "10_0",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_BC1_TYPELESS":
{
@@ -708,27 +777,30 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_BC1_UNORM":
{
"texture2D": "always",
"texture3D": "always",
"textureCube": "always",
- "shaderSample": "10_0",
+ "shaderSample": "always",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_BC1_UNORM_SRGB":
{
"texture2D": "always",
"texture3D": "always",
"textureCube": "always",
- "shaderSample": "10_0",
+ "shaderSample": "always",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_BC2_TYPELESS":
{
@@ -738,27 +810,30 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_BC2_UNORM":
{
"texture2D": "always",
"texture3D": "always",
"textureCube": "always",
- "shaderSample": "10_0",
+ "shaderSample": "always",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_BC2_UNORM_SRGB":
{
"texture2D": "always",
"texture3D": "always",
"textureCube": "always",
- "shaderSample": "10_0",
+ "shaderSample": "always",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_BC3_TYPELESS":
{
@@ -768,27 +843,30 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_BC3_UNORM":
{
"texture2D": "always",
"texture3D": "always",
"textureCube": "always",
- "shaderSample": "10_0",
+ "shaderSample": "always",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_BC3_UNORM_SRGB":
{
"texture2D": "always",
"texture3D": "always",
"textureCube": "always",
- "shaderSample": "10_0",
+ "shaderSample": "always",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_BC4_TYPELESS":
{
@@ -798,7 +876,8 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_BC4_UNORM":
{
@@ -808,7 +887,8 @@
"shaderSample": "10_0",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_BC4_SNORM":
{
@@ -818,7 +898,8 @@
"shaderSample": "10_0",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_BC5_TYPELESS":
{
@@ -828,7 +909,8 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_BC5_UNORM":
{
@@ -838,7 +920,8 @@
"shaderSample": "10_0",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_BC5_SNORM":
{
@@ -848,7 +931,8 @@
"shaderSample": "10_0",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_B5G6R5_UNORM":
{
@@ -858,7 +942,8 @@
"shaderSample": "dxgi1_2",
"renderTarget": "dxgi1_2",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "dxgi1_2"
},
"DXGI_FORMAT_B5G5R5A1_UNORM":
{
@@ -868,17 +953,19 @@
"shaderSample": "dxgi1_2",
"renderTarget": "check",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "dxgi1_2"
},
"DXGI_FORMAT_B8G8R8A8_UNORM":
{
"texture2D": "check",
"texture3D": "check",
"textureCube": "check",
- "shaderSample": "10_0check11_0always",
- "renderTarget": "10_0check11_0always",
+ "shaderSample": "9_3always_10_0check11_0always",
+ "renderTarget": "9_3always_10_0check11_0always",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "always"
},
"DXGI_FORMAT_B8G8R8X8_UNORM":
{
@@ -888,7 +975,8 @@
"shaderSample": "10_0check11_0always",
"renderTarget": "11_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM":
{
@@ -898,7 +986,8 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_B8G8R8A8_TYPELESS":
{
@@ -908,7 +997,8 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_B8G8R8A8_UNORM_SRGB":
{
@@ -918,7 +1008,8 @@
"shaderSample": "10_0check11_0always",
"renderTarget": "11_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_B8G8R8X8_TYPELESS":
{
@@ -928,7 +1019,8 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_B8G8R8X8_UNORM_SRGB":
{
@@ -938,7 +1030,8 @@
"shaderSample": "10_0check11_0always",
"renderTarget": "11_0",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_BC6H_TYPELESS":
{
@@ -948,7 +1041,8 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_BC6H_UF16":
{
@@ -958,7 +1052,8 @@
"shaderSample": "11_0",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_BC6H_SF16":
{
@@ -968,7 +1063,8 @@
"shaderSample": "11_0",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_BC7_TYPELESS":
{
@@ -978,7 +1074,8 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_BC7_UNORM":
{
@@ -988,7 +1085,8 @@
"shaderSample": "11_0",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_BC7_UNORM_SRGB":
{
@@ -998,7 +1096,8 @@
"shaderSample": "11_0",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_AYUV":
{
@@ -1008,7 +1107,8 @@
"shaderSample": "11_1",
"renderTarget": "11_1",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_Y410":
{
@@ -1018,7 +1118,8 @@
"shaderSample": "11_1",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_Y416":
{
@@ -1028,7 +1129,8 @@
"shaderSample": "11_1",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_NV12":
{
@@ -1038,7 +1140,8 @@
"shaderSample": "11_1",
"renderTarget": "11_1",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_P010":
{
@@ -1048,7 +1151,8 @@
"shaderSample": "11_1",
"renderTarget": "11_1",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_P016":
{
@@ -1058,7 +1162,8 @@
"shaderSample": "11_1",
"renderTarget": "11_1",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_420_OPAQUE":
{
@@ -1068,7 +1173,8 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_YUY2":
{
@@ -1078,7 +1184,8 @@
"shaderSample": "11_1",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_Y210":
{
@@ -1088,7 +1195,8 @@
"shaderSample": "11_1",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_Y216":
{
@@ -1098,7 +1206,8 @@
"shaderSample": "11_1",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_NV11":
{
@@ -1108,7 +1217,8 @@
"shaderSample": "11_1",
"renderTarget": "11_1",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_AI44":
{
@@ -1118,7 +1228,8 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_IA44":
{
@@ -1128,7 +1239,8 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_P8":
{
@@ -1138,7 +1250,8 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_A8P8":
{
@@ -1148,7 +1261,8 @@
"shaderSample": "never",
"renderTarget": "never",
"multisampleRT": "never",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "never"
},
"DXGI_FORMAT_B4G4R4A4_UNORM":
{
@@ -1158,7 +1272,8 @@
"shaderSample": "dxgi1_2",
"renderTarget": "check",
"multisampleRT": "check",
- "depthStencil": "never"
+ "depthStencil": "never",
+ "mipAutoGen": "dxgi1_2"
}
}
]
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp
index cbc36445e6..4d7e46bdf2 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp
@@ -26,205 +26,205 @@ namespace d3d11
#define F_RT D3D11_FORMAT_SUPPORT_RENDER_TARGET
#define F_MS D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET
#define F_DS D3D11_FORMAT_SUPPORT_DEPTH_STENCIL
+#define F_MIPGEN D3D11_FORMAT_SUPPORT_MIP_AUTOGEN
namespace
{
const DXGISupport &GetDefaultSupport()
{
- static UINT AllSupportFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D |
- D3D11_FORMAT_SUPPORT_TEXTURE3D |
- D3D11_FORMAT_SUPPORT_TEXTURECUBE |
- D3D11_FORMAT_SUPPORT_SHADER_SAMPLE |
- D3D11_FORMAT_SUPPORT_RENDER_TARGET |
- D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET |
- D3D11_FORMAT_SUPPORT_DEPTH_STENCIL;
+ static UINT AllSupportFlags =
+ D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURE3D |
+ D3D11_FORMAT_SUPPORT_TEXTURECUBE | D3D11_FORMAT_SUPPORT_SHADER_SAMPLE |
+ D3D11_FORMAT_SUPPORT_RENDER_TARGET | D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET |
+ D3D11_FORMAT_SUPPORT_DEPTH_STENCIL | D3D11_FORMAT_SUPPORT_MIP_AUTOGEN;
static const DXGISupport defaultSupport(0, 0, AllSupportFlags);
return defaultSupport;
}
-const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat)
+const DXGISupport &GetDXGISupport_9_3(DXGI_FORMAT dxgiFormat)
{
+ // clang-format off
switch (dxgiFormat)
{
case DXGI_FORMAT_420_OPAQUE:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_A8P8:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_A8_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_AI44:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_AYUV:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
return info;
}
case DXGI_FORMAT_B4G4R4A4_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS, F_MS | F_RT);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
return info;
}
case DXGI_FORMAT_B5G5R5A1_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS, F_MS | F_RT);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
return info;
}
case DXGI_FORMAT_B5G6R5_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_B8G8R8A8_TYPELESS:
{
- static const DXGISupport info(0, F_DS | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
return info;
}
case DXGI_FORMAT_B8G8R8A8_UNORM:
{
- static const DXGISupport info(0, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_RT | F_SAMPLE);
+ static const DXGISupport info(F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS);
return info;
}
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
{
- static const DXGISupport info(0, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
+ static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS);
return info;
}
case DXGI_FORMAT_B8G8R8X8_TYPELESS:
{
- static const DXGISupport info(0, F_DS | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
return info;
}
case DXGI_FORMAT_B8G8R8X8_UNORM:
{
- static const DXGISupport info(0, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
+ static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS);
return info;
}
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
{
- static const DXGISupport info(0, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
+ static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS);
return info;
}
case DXGI_FORMAT_BC1_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_BC1_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC1_UNORM_SRGB:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC2_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_BC2_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC2_UNORM_SRGB:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC3_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_BC3_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC3_UNORM_SRGB:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC4_SNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC4_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_BC4_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC5_SNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC5_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_BC5_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC6H_SF16:
{
- static const DXGISupport info(0, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC6H_TYPELESS:
{
- static const DXGISupport info(0, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_BC6H_UF16:
{
- static const DXGISupport info(0, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC7_TYPELESS:
{
- static const DXGISupport info(0, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_BC7_UNORM:
{
- static const DXGISupport info(0, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC7_UNORM_SRGB:
{
- static const DXGISupport info(0, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_D16_UNORM:
{
- static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_D24_UNORM_S8_UINT:
@@ -234,112 +234,112 @@ const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat)
}
case DXGI_FORMAT_D32_FLOAT:
{
- static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
{
- static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_G8R8_G8B8_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_IA44:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_NV11:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
return info;
}
case DXGI_FORMAT_NV12:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
return info;
}
case DXGI_FORMAT_P010:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
return info;
}
case DXGI_FORMAT_P016:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
return info;
}
case DXGI_FORMAT_P8:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R10G10B10A2_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R10G10B10A2_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R10G10B10A2_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(0, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
{
- static const DXGISupport info(0, F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, F_2D | F_3D);
+ static const DXGISupport info(0, F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D);
return info;
}
case DXGI_FORMAT_R11G11B10_FLOAT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(0, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16G16B16A16_FLOAT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS | F_SAMPLE);
return info;
}
case DXGI_FORMAT_R16G16B16A16_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R16G16B16A16_SNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(0, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16G16B16A16_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R16G16B16A16_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R16G16B16A16_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16G16_FLOAT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16G16_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R16G16_SNORM:
@@ -349,157 +349,157 @@ const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat)
}
case DXGI_FORMAT_R16G16_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R16G16_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R16G16_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16_FLOAT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(0, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R16_SNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(0, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R16_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R16_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R1_UNORM:
{
- static const DXGISupport info(F_2D, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R24G8_TYPELESS:
{
- static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
{
- static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT, F_SAMPLE);
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_R32G32B32A32_FLOAT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS, F_MS | F_SAMPLE);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R32G32B32A32_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R32G32B32A32_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R32G32B32_FLOAT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS, F_MS | F_RT);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN, F_MS | F_RT);
return info;
}
case DXGI_FORMAT_R32G32B32_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_SAMPLE, F_MS | F_RT);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
return info;
}
case DXGI_FORMAT_R32G32B32_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R32G32B32_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_SAMPLE, F_MS | F_RT);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
return info;
}
case DXGI_FORMAT_R32G32_FLOAT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS, F_MS | F_SAMPLE);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R32G32_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R32G32_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R32G32_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R32G8X24_TYPELESS:
{
- static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R32_FLOAT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS, F_MS | F_SAMPLE);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
{
- static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT, F_SAMPLE);
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_R32_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R32_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R32_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R8G8B8A8_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R8G8B8A8_SNORM:
@@ -509,122 +509,122 @@ const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat)
}
case DXGI_FORMAT_R8G8B8A8_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R8G8B8A8_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R8G8B8A8_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R8G8_B8G8_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_R8G8_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R8G8_SNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R8G8_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R8G8_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R8G8_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(0, F_DS, F_MS | F_RT | F_SAMPLE);
return info;
}
case DXGI_FORMAT_R8_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R8_SNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(0, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R8_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R8_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R8_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS, F_MS | F_RT);
return info;
}
case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_UNKNOWN:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
{
- static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
{
- static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_Y210:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_Y216:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_Y410:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_Y416:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_YUY2:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
@@ -632,190 +632,192 @@ const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat)
UNREACHABLE();
return GetDefaultSupport();
}
+ // clang-format on
}
-const DXGISupport &GetDXGISupport_10_1(DXGI_FORMAT dxgiFormat)
+const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat)
{
+ // clang-format off
switch (dxgiFormat)
{
case DXGI_FORMAT_420_OPAQUE:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_A8P8:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_A8_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_AI44:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_AYUV:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
return info;
}
case DXGI_FORMAT_B4G4R4A4_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS, F_MS | F_RT);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
return info;
}
case DXGI_FORMAT_B5G5R5A1_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS, F_MS | F_RT);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
return info;
}
case DXGI_FORMAT_B5G6R5_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_B8G8R8A8_TYPELESS:
{
- static const DXGISupport info(0, F_DS | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
return info;
}
case DXGI_FORMAT_B8G8R8A8_UNORM:
{
- static const DXGISupport info(0, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_RT | F_SAMPLE);
+ static const DXGISupport info(F_MIPGEN, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_RT | F_SAMPLE);
return info;
}
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
{
- static const DXGISupport info(0, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
+ static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
return info;
}
case DXGI_FORMAT_B8G8R8X8_TYPELESS:
{
- static const DXGISupport info(0, F_DS | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
return info;
}
case DXGI_FORMAT_B8G8R8X8_UNORM:
{
- static const DXGISupport info(0, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
+ static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
return info;
}
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
{
- static const DXGISupport info(0, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
+ static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
return info;
}
case DXGI_FORMAT_BC1_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_BC1_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC1_UNORM_SRGB:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC2_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_BC2_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC2_UNORM_SRGB:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC3_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_BC3_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC3_UNORM_SRGB:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC4_SNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC4_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_BC4_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC5_SNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC5_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_BC5_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC6H_SF16:
{
- static const DXGISupport info(0, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC6H_TYPELESS:
{
- static const DXGISupport info(0, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_BC6H_UF16:
{
- static const DXGISupport info(0, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC7_TYPELESS:
{
- static const DXGISupport info(0, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_BC7_UNORM:
{
- static const DXGISupport info(0, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC7_UNORM_SRGB:
{
- static const DXGISupport info(0, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_D16_UNORM:
{
- static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_D24_UNORM_S8_UINT:
@@ -825,397 +827,990 @@ const DXGISupport &GetDXGISupport_10_1(DXGI_FORMAT dxgiFormat)
}
case DXGI_FORMAT_D32_FLOAT:
{
- static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
{
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_IA44:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_NV11:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_NV12:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P010:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P016:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P8:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+ {
+ static const DXGISupport info(0, F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D);
+ return info;
+ }
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R16_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R1_UNORM:
+ {
+ static const DXGISupport info(F_2D, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS | F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS | F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS | F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_R32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y210:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y216:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y410:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y416:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_YUY2:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+
+ default:
+ UNREACHABLE();
+ return GetDefaultSupport();
+ }
+ // clang-format on
+}
+
+const DXGISupport &GetDXGISupport_10_1(DXGI_FORMAT dxgiFormat)
+{
+ // clang-format off
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_420_OPAQUE:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_A8P8:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_A8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_AI44:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_AYUV:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ {
+ static const DXGISupport info(F_MIPGEN, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_RT | F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_BC1_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC1_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC2_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC2_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC3_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC3_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC4_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC4_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC4_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC5_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC5_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC5_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC6H_SF16:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC6H_UF16:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC7_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC7_UNORM:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_D16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ {
static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS);
return info;
}
+ case DXGI_FORMAT_D32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
case DXGI_FORMAT_G8R8_G8B8_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_IA44:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_NV11:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
return info;
}
case DXGI_FORMAT_NV12:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
return info;
}
case DXGI_FORMAT_P010:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
return info;
}
case DXGI_FORMAT_P016:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
return info;
}
case DXGI_FORMAT_P8:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R10G10B10A2_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R10G10B10A2_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R10G10B10A2_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
{
- static const DXGISupport info(0, F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, F_2D | F_3D);
+ static const DXGISupport info(0, F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D);
return info;
}
case DXGI_FORMAT_R11G11B10_FLOAT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16G16B16A16_FLOAT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16G16B16A16_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R16G16B16A16_SNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16G16B16A16_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R16G16B16A16_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R16G16B16A16_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16G16_FLOAT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16G16_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R16G16_SNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16G16_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R16G16_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R16G16_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16_FLOAT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R16_SNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R16_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R16_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R1_UNORM:
{
- static const DXGISupport info(F_2D, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R24G8_TYPELESS:
{
- static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
{
- static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_R32G32B32A32_FLOAT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R32G32B32A32_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R32G32B32A32_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R32G32B32_FLOAT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS, F_MS | F_RT);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN, F_MS | F_RT);
return info;
}
case DXGI_FORMAT_R32G32B32_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_SAMPLE, F_MS | F_RT);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
return info;
}
case DXGI_FORMAT_R32G32B32_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R32G32B32_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_SAMPLE, F_MS | F_RT);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
return info;
}
case DXGI_FORMAT_R32G32_FLOAT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R32G32_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R32G32_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R32G32_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R32G8X24_TYPELESS:
{
- static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R32_FLOAT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
{
- static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_R32_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R32_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R32_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R8G8B8A8_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R8G8B8A8_SNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R8G8B8A8_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R8G8B8A8_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R8G8B8A8_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R8G8_B8G8_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_R8G8_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R8G8_SNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R8G8_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R8G8_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R8G8_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R8_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R8_SNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R8_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R8_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R8_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_UNKNOWN:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
{
- static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
{
- static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_Y210:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_Y216:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_Y410:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_Y416:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_YUY2:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
@@ -1223,190 +1818,192 @@ const DXGISupport &GetDXGISupport_10_1(DXGI_FORMAT dxgiFormat)
UNREACHABLE();
return GetDefaultSupport();
}
+ // clang-format on
}
const DXGISupport &GetDXGISupport_11_0(DXGI_FORMAT dxgiFormat)
{
+ // clang-format off
switch (dxgiFormat)
{
case DXGI_FORMAT_420_OPAQUE:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_A8P8:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_A8_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_AI44:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_AYUV:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS);
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
return info;
}
case DXGI_FORMAT_B4G4R4A4_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS, F_MS | F_RT);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
return info;
}
case DXGI_FORMAT_B5G5R5A1_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS, F_MS | F_RT);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
return info;
}
case DXGI_FORMAT_B5G6R5_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_B8G8R8A8_TYPELESS:
{
- static const DXGISupport info(0, F_DS | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
return info;
}
case DXGI_FORMAT_B8G8R8A8_UNORM:
{
- static const DXGISupport info(F_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS);
+ static const DXGISupport info(F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS);
return info;
}
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
{
- static const DXGISupport info(F_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS);
+ static const DXGISupport info(F_RT | F_SAMPLE, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS);
return info;
}
case DXGI_FORMAT_B8G8R8X8_TYPELESS:
{
- static const DXGISupport info(0, F_DS | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
return info;
}
case DXGI_FORMAT_B8G8R8X8_UNORM:
{
- static const DXGISupport info(F_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS);
+ static const DXGISupport info(F_RT | F_SAMPLE, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS);
return info;
}
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
{
- static const DXGISupport info(F_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS);
+ static const DXGISupport info(F_RT | F_SAMPLE, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS);
return info;
}
case DXGI_FORMAT_BC1_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_BC1_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC1_UNORM_SRGB:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC2_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_BC2_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC2_UNORM_SRGB:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC3_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_BC3_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC3_UNORM_SRGB:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC4_SNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC4_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_BC4_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC5_SNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC5_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_BC5_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC6H_SF16:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC6H_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_BC6H_UF16:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC7_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_BC7_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_BC7_UNORM_SRGB:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_D16_UNORM:
{
- static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_D24_UNORM_S8_UINT:
@@ -1416,397 +2013,990 @@ const DXGISupport &GetDXGISupport_11_0(DXGI_FORMAT dxgiFormat)
}
case DXGI_FORMAT_D32_FLOAT:
{
- static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
{
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_IA44:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_NV11:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_NV12:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P010:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P016:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P8:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+ {
+ static const DXGISupport info(0, F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D);
+ return info;
+ }
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R16_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R1_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y210:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y216:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y410:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y416:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_YUY2:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+
+ default:
+ UNREACHABLE();
+ return GetDefaultSupport();
+ }
+ // clang-format on
+}
+
+const DXGISupport &GetDXGISupport_11_1(DXGI_FORMAT dxgiFormat)
+{
+ // clang-format off
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_420_OPAQUE:
+ {
+ static const DXGISupport info(F_2D, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_A8P8:
+ {
+ static const DXGISupport info(F_2D, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_A8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_AI44:
+ {
+ static const DXGISupport info(F_2D, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_AYUV:
+ {
+ static const DXGISupport info(F_2D | F_RT | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ {
+ static const DXGISupport info(F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_RT | F_SAMPLE, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ {
+ static const DXGISupport info(F_RT | F_SAMPLE, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_RT | F_SAMPLE, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_BC1_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC1_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC2_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC2_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC3_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC3_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC4_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC4_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC4_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC5_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC5_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC5_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC6H_SF16:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC6H_UF16:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC7_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC7_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_D16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ {
static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS);
return info;
}
+ case DXGI_FORMAT_D32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
case DXGI_FORMAT_G8R8_G8B8_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_IA44:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_NV11:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_RT | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
return info;
}
case DXGI_FORMAT_NV12:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_RT | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
return info;
}
case DXGI_FORMAT_P010:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_RT | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
return info;
}
case DXGI_FORMAT_P016:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_RT | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
return info;
}
case DXGI_FORMAT_P8:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R10G10B10A2_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R10G10B10A2_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R10G10B10A2_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
{
- static const DXGISupport info(0, F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, F_2D | F_3D);
+ static const DXGISupport info(0, F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D);
return info;
}
case DXGI_FORMAT_R11G11B10_FLOAT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16G16B16A16_FLOAT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16G16B16A16_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R16G16B16A16_SNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16G16B16A16_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R16G16B16A16_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R16G16B16A16_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16G16_FLOAT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16G16_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R16G16_SNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16G16_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R16G16_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R16G16_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16_FLOAT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R16_SNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R16_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R16_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R16_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R1_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R24G8_TYPELESS:
{
- static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
{
- static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_R32G32B32A32_FLOAT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R32G32B32A32_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R32G32B32A32_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R32G32B32_FLOAT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS, F_MS | F_RT);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN, F_MS | F_RT);
return info;
}
case DXGI_FORMAT_R32G32B32_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_SAMPLE, F_MS | F_RT);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
return info;
}
case DXGI_FORMAT_R32G32B32_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R32G32B32_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_SAMPLE, F_MS | F_RT);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
return info;
}
case DXGI_FORMAT_R32G32_FLOAT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R32G32_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R32G32_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R32G32_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R32G8X24_TYPELESS:
{
- static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R32_FLOAT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
{
- static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_R32_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R32_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R32_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R8G8B8A8_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R8G8B8A8_SNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R8G8B8A8_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R8G8B8A8_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R8G8B8A8_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R8G8_B8G8_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_R8G8_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R8G8_SNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R8G8_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R8G8_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R8G8_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R8_SINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R8_SNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R8_TYPELESS:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_R8_UINT:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
return info;
}
case DXGI_FORMAT_R8_UNORM:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
return info;
}
case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
{
- static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0);
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_UNKNOWN:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
{
- static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
{
- static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
return info;
}
case DXGI_FORMAT_Y210:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_Y216:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_Y410:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_Y416:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
case DXGI_FORMAT_YUY2:
{
- static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0);
+ static const DXGISupport info(F_2D | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
return info;
}
@@ -1814,6 +3004,7 @@ const DXGISupport &GetDXGISupport_11_0(DXGI_FORMAT dxgiFormat)
UNREACHABLE();
return GetDefaultSupport();
}
+ // clang-format on
}
}
@@ -1825,17 +3016,22 @@ const DXGISupport &GetDXGISupport_11_0(DXGI_FORMAT dxgiFormat)
#undef F_RT
#undef F_MS
#undef F_DS
+#undef F_MIPGEN
const DXGISupport &GetDXGISupport(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
+ case D3D_FEATURE_LEVEL_9_3:
+ return GetDXGISupport_9_3(dxgiFormat);
case D3D_FEATURE_LEVEL_10_0:
return GetDXGISupport_10_0(dxgiFormat);
case D3D_FEATURE_LEVEL_10_1:
return GetDXGISupport_10_1(dxgiFormat);
case D3D_FEATURE_LEVEL_11_0:
return GetDXGISupport_11_0(dxgiFormat);
+ case D3D_FEATURE_LEVEL_11_1:
+ return GetDXGISupport_11_1(dxgiFormat);
default:
return GetDefaultSupport();
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h
index 1d8d68565e..a818f376ef 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h
@@ -8,6 +8,9 @@
// version, D3D feature level, and is sometimes guaranteed or optional.
//
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_DXGI_SUPPORT_TABLE_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_DXGI_SUPPORT_TABLE_H_
+
#include "common/platform.h"
namespace rx
@@ -42,3 +45,5 @@ const DXGISupport &GetDXGISupport(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL feat
} // namespace d3d11
} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_DXGI_SUPPORT_TABLE_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp
index f073e9f46f..ce4edd26db 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp
@@ -9,14 +9,15 @@
#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "image_util/copyimage.h"
+#include "image_util/generatemip.h"
+#include "image_util/loadimage.h"
+
#include "libANGLE/formatutils.h"
-#include "libANGLE/renderer/d3d/copyimage.h"
#include "libANGLE/renderer/d3d/d3d11/copyvertex.h"
+#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
-#include "libANGLE/renderer/d3d/generatemip.h"
-#include "libANGLE/renderer/d3d/loadimage.h"
-#include "libANGLE/renderer/Renderer.h"
namespace rx
{
@@ -24,559 +25,388 @@ namespace rx
namespace d3d11
{
-typedef std::map<DXGI_FORMAT, GLenum> DXGIToESFormatMap;
-
-inline void AddDXGIToESEntry(DXGIToESFormatMap *map, DXGI_FORMAT key, GLenum value)
+bool SupportsMipGen(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel)
{
- map->insert(std::make_pair(key, value));
+ const auto &support = GetDXGISupport(dxgiFormat, featureLevel);
+ ASSERT((support.optionallySupportedFlags & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN) == 0);
+ return ((support.alwaysSupportedFlags & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN) != 0);
}
-static DXGIToESFormatMap BuildDXGIToESFormatMap()
+DXGIFormatSize::DXGIFormatSize(GLuint pixelBits, GLuint blockWidth, GLuint blockHeight)
+ : pixelBytes(pixelBits / 8), blockWidth(blockWidth), blockHeight(blockHeight)
{
- DXGIToESFormatMap map;
-
- AddDXGIToESEntry(&map, DXGI_FORMAT_UNKNOWN, GL_NONE);
-
- AddDXGIToESEntry(&map, DXGI_FORMAT_A8_UNORM, GL_ALPHA8_EXT);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R8_UNORM, GL_R8);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_UNORM, GL_RG8);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UNORM, GL_RGBA8);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, GL_SRGB8_ALPHA8);
- AddDXGIToESEntry(&map, DXGI_FORMAT_B8G8R8A8_UNORM, GL_BGRA8_EXT);
-
- AddDXGIToESEntry(&map, DXGI_FORMAT_R8_SNORM, GL_R8_SNORM);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_SNORM, GL_RG8_SNORM);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_SNORM, GL_RGBA8_SNORM);
-
- AddDXGIToESEntry(&map, DXGI_FORMAT_R8_UINT, GL_R8UI);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R16_UINT, GL_R16UI);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R32_UINT, GL_R32UI);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_UINT, GL_RG8UI);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_UINT, GL_RG16UI);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_UINT, GL_RG32UI);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_UINT, GL_RGB32UI);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UINT, GL_RGBA8UI);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_UINT, GL_RGBA16UI);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_UINT, GL_RGBA32UI);
-
- AddDXGIToESEntry(&map, DXGI_FORMAT_R8_SINT, GL_R8I);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R16_SINT, GL_R16I);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R32_SINT, GL_R32I);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_SINT, GL_RG8I);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_SINT, GL_RG16I);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_SINT, GL_RG32I);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_SINT, GL_RGB32I);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_SINT, GL_RGBA8I);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_SINT, GL_RGBA16I);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_SINT, GL_RGBA32I);
-
- AddDXGIToESEntry(&map, DXGI_FORMAT_R10G10B10A2_UNORM, GL_RGB10_A2);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R10G10B10A2_UINT, GL_RGB10_A2UI);
-
- AddDXGIToESEntry(&map, DXGI_FORMAT_R16_FLOAT, GL_R16F);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_FLOAT, GL_RG16F);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, GL_RGBA16F);
-
- AddDXGIToESEntry(&map, DXGI_FORMAT_R32_FLOAT, GL_R32F);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_FLOAT, GL_RG32F);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_FLOAT, GL_RGB32F);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, GL_RGBA32F);
-
- AddDXGIToESEntry(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, GL_RGB9_E5);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R11G11B10_FLOAT, GL_R11F_G11F_B10F);
-
- AddDXGIToESEntry(&map, DXGI_FORMAT_R16_TYPELESS, GL_DEPTH_COMPONENT16);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R16_UNORM, GL_DEPTH_COMPONENT16);
- AddDXGIToESEntry(&map, DXGI_FORMAT_D16_UNORM, GL_DEPTH_COMPONENT16);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R24G8_TYPELESS, GL_DEPTH24_STENCIL8_OES);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, GL_DEPTH24_STENCIL8_OES);
- AddDXGIToESEntry(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, GL_DEPTH24_STENCIL8_OES);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R32G8X24_TYPELESS, GL_DEPTH32F_STENCIL8);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, GL_DEPTH32F_STENCIL8);
- AddDXGIToESEntry(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, GL_DEPTH32F_STENCIL8);
- AddDXGIToESEntry(&map, DXGI_FORMAT_R32_TYPELESS, GL_DEPTH_COMPONENT32F);
- AddDXGIToESEntry(&map, DXGI_FORMAT_D32_FLOAT, GL_DEPTH_COMPONENT32F);
-
- AddDXGIToESEntry(&map, DXGI_FORMAT_BC1_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
- AddDXGIToESEntry(&map, DXGI_FORMAT_BC2_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE);
- AddDXGIToESEntry(&map, DXGI_FORMAT_BC3_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE);
-
- AddDXGIToESEntry(&map, DXGI_FORMAT_B5G6R5_UNORM, GL_RGB565);
- AddDXGIToESEntry(&map, DXGI_FORMAT_B5G5R5A1_UNORM, GL_RGB5_A1);
- AddDXGIToESEntry(&map, DXGI_FORMAT_B4G4R4A4_UNORM, GL_RGBA4);
-
- return map;
}
-struct D3D11FastCopyFormat
+const DXGIFormatSize &GetDXGIFormatSizeInfo(DXGI_FORMAT format)
{
- GLenum destFormat;
- GLenum destType;
- ColorCopyFunction copyFunction;
-
- D3D11FastCopyFormat(GLenum destFormat, GLenum destType, ColorCopyFunction copyFunction)
- : destFormat(destFormat), destType(destType), copyFunction(copyFunction)
- { }
-
- bool operator<(const D3D11FastCopyFormat& other) const
+ static const DXGIFormatSize sizeUnknown(0, 0, 0);
+ static const DXGIFormatSize size128(128, 1, 1);
+ static const DXGIFormatSize size96(96, 1, 1);
+ static const DXGIFormatSize size64(64, 1, 1);
+ static const DXGIFormatSize size32(32, 1, 1);
+ static const DXGIFormatSize size16(16, 1, 1);
+ static const DXGIFormatSize size8(8, 1, 1);
+ static const DXGIFormatSize sizeBC1(64, 4, 4);
+ static const DXGIFormatSize sizeBC2(128, 4, 4);
+ static const DXGIFormatSize sizeBC3(128, 4, 4);
+ static const DXGIFormatSize sizeBC4(64, 4, 4);
+ static const DXGIFormatSize sizeBC5(128, 4, 4);
+ static const DXGIFormatSize sizeBC6H(128, 4, 4);
+ static const DXGIFormatSize sizeBC7(128, 4, 4);
+ switch (format)
{
- return memcmp(this, &other, sizeof(D3D11FastCopyFormat)) < 0;
+ case DXGI_FORMAT_UNKNOWN:
+ return sizeUnknown;
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ return size128;
+ case DXGI_FORMAT_R32G32B32_TYPELESS:
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ case DXGI_FORMAT_R32G32B32_UINT:
+ case DXGI_FORMAT_R32G32B32_SINT:
+ return size96;
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ case DXGI_FORMAT_R32G32_TYPELESS:
+ case DXGI_FORMAT_R32G32_FLOAT:
+ case DXGI_FORMAT_R32G32_UINT:
+ case DXGI_FORMAT_R32G32_SINT:
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ return size64;
+ case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ case DXGI_FORMAT_R16G16_TYPELESS:
+ case DXGI_FORMAT_R16G16_FLOAT:
+ case DXGI_FORMAT_R16G16_UNORM:
+ case DXGI_FORMAT_R16G16_UINT:
+ case DXGI_FORMAT_R16G16_SNORM:
+ case DXGI_FORMAT_R16G16_SINT:
+ case DXGI_FORMAT_R32_TYPELESS:
+ case DXGI_FORMAT_D32_FLOAT:
+ case DXGI_FORMAT_R32_FLOAT:
+ case DXGI_FORMAT_R32_UINT:
+ case DXGI_FORMAT_R32_SINT:
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ return size32;
+ case DXGI_FORMAT_R8G8_TYPELESS:
+ case DXGI_FORMAT_R8G8_UNORM:
+ case DXGI_FORMAT_R8G8_UINT:
+ case DXGI_FORMAT_R8G8_SNORM:
+ case DXGI_FORMAT_R8G8_SINT:
+ case DXGI_FORMAT_R16_TYPELESS:
+ case DXGI_FORMAT_R16_FLOAT:
+ case DXGI_FORMAT_D16_UNORM:
+ case DXGI_FORMAT_R16_UNORM:
+ case DXGI_FORMAT_R16_UINT:
+ case DXGI_FORMAT_R16_SNORM:
+ case DXGI_FORMAT_R16_SINT:
+ return size16;
+ case DXGI_FORMAT_R8_TYPELESS:
+ case DXGI_FORMAT_R8_UNORM:
+ case DXGI_FORMAT_R8_UINT:
+ case DXGI_FORMAT_R8_SNORM:
+ case DXGI_FORMAT_R8_SINT:
+ case DXGI_FORMAT_A8_UNORM:
+ return size8;
+ case DXGI_FORMAT_R1_UNORM:
+ UNREACHABLE();
+ return sizeUnknown;
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ return size32;
+ case DXGI_FORMAT_BC1_TYPELESS:
+ case DXGI_FORMAT_BC1_UNORM:
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ return sizeBC1;
+ case DXGI_FORMAT_BC2_TYPELESS:
+ case DXGI_FORMAT_BC2_UNORM:
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ return sizeBC2;
+ case DXGI_FORMAT_BC3_TYPELESS:
+ case DXGI_FORMAT_BC3_UNORM:
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ return sizeBC3;
+ case DXGI_FORMAT_BC4_TYPELESS:
+ case DXGI_FORMAT_BC4_UNORM:
+ case DXGI_FORMAT_BC4_SNORM:
+ return sizeBC4;
+ case DXGI_FORMAT_BC5_TYPELESS:
+ case DXGI_FORMAT_BC5_UNORM:
+ case DXGI_FORMAT_BC5_SNORM:
+ return sizeBC5;
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ return size16;
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ return size32;
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ case DXGI_FORMAT_BC6H_UF16:
+ case DXGI_FORMAT_BC6H_SF16:
+ return sizeBC6H;
+ case DXGI_FORMAT_BC7_TYPELESS:
+ case DXGI_FORMAT_BC7_UNORM:
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ return sizeBC7;
+ case DXGI_FORMAT_AYUV:
+ case DXGI_FORMAT_Y410:
+ case DXGI_FORMAT_Y416:
+ case DXGI_FORMAT_NV12:
+ case DXGI_FORMAT_P010:
+ case DXGI_FORMAT_P016:
+ case DXGI_FORMAT_420_OPAQUE:
+ case DXGI_FORMAT_YUY2:
+ case DXGI_FORMAT_Y210:
+ case DXGI_FORMAT_Y216:
+ case DXGI_FORMAT_NV11:
+ case DXGI_FORMAT_AI44:
+ case DXGI_FORMAT_IA44:
+ case DXGI_FORMAT_P8:
+ case DXGI_FORMAT_A8P8:
+ UNREACHABLE();
+ return sizeUnknown;
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ return size16;
+ default:
+ UNREACHABLE();
+ return sizeUnknown;
}
-};
-
-typedef std::multimap<DXGI_FORMAT, D3D11FastCopyFormat> D3D11FastCopyMap;
-
-static D3D11FastCopyMap BuildFastCopyMap()
-{
- D3D11FastCopyMap map;
-
- map.insert(std::make_pair(DXGI_FORMAT_B8G8R8A8_UNORM, D3D11FastCopyFormat(GL_RGBA, GL_UNSIGNED_BYTE, CopyBGRA8ToRGBA8)));
-
- return map;
-}
-
-struct DXGIColorFormatInfo
-{
- size_t redBits;
- size_t greenBits;
- size_t blueBits;
-
- size_t luminanceBits;
-
- size_t alphaBits;
- size_t sharedBits;
-};
-
-typedef std::map<DXGI_FORMAT, DXGIColorFormatInfo> ColorFormatInfoMap;
-typedef std::pair<DXGI_FORMAT, DXGIColorFormatInfo> ColorFormatInfoPair;
-
-static inline void InsertDXGIColorFormatInfo(ColorFormatInfoMap *map, DXGI_FORMAT format, size_t redBits, size_t greenBits,
- size_t blueBits, size_t alphaBits, size_t sharedBits)
-{
- DXGIColorFormatInfo info;
- info.redBits = redBits;
- info.greenBits = greenBits;
- info.blueBits = blueBits;
- info.alphaBits = alphaBits;
- info.sharedBits = sharedBits;
-
- map->insert(std::make_pair(format, info));
-}
-
-static ColorFormatInfoMap BuildColorFormatInfoMap()
-{
- ColorFormatInfoMap map;
-
- // | DXGI format | R | G | B | A | S |
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_A8_UNORM, 0, 0, 0, 8, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8_UNORM, 8, 0, 0, 0, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8_UNORM, 8, 8, 0, 0, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_UNORM, 8, 8, 8, 8, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 8, 8, 8, 8, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_B8G8R8A8_UNORM, 8, 8, 8, 8, 0);
-
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8_SNORM, 8, 0, 0, 0, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8_SNORM, 8, 8, 0, 0, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_SNORM, 8, 8, 8, 8, 0);
-
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8_UINT, 8, 0, 0, 0, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16_UINT, 16, 0, 0, 0, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32_UINT, 32, 0, 0, 0, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8_UINT, 8, 8, 0, 0, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16_UINT, 16, 16, 0, 0, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32_UINT, 32, 32, 0, 0, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32_UINT, 32, 32, 32, 0, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_UINT, 8, 8, 8, 8, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16B16A16_UINT, 16, 16, 16, 16, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32A32_UINT, 32, 32, 32, 32, 0);
-
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8_SINT, 8, 0, 0, 0, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16_SINT, 16, 0, 0, 0, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32_SINT, 32, 0, 0, 0, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8_SINT, 8, 8, 0, 0, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16_SINT, 16, 16, 0, 0, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32_SINT, 32, 32, 0, 0, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32_SINT, 32, 32, 32, 0, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_SINT, 8, 8, 8, 8, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16B16A16_SINT, 16, 16, 16, 16, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32A32_SINT, 32, 32, 32, 32, 0);
-
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R10G10B10A2_UNORM, 10, 10, 10, 2, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R10G10B10A2_UINT, 10, 10, 10, 2, 0);
-
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16_FLOAT, 16, 0, 0, 0, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16_FLOAT, 16, 16, 0, 0, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, 16, 16, 16, 16, 0);
-
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32_FLOAT, 32, 0, 0, 0, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32_FLOAT, 32, 32, 0, 0, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32_FLOAT, 32, 32, 32, 0, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, 32, 32, 32, 32, 0);
-
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, 9, 9, 9, 0, 5);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R11G11B10_FLOAT, 11, 11, 10, 0, 0);
-
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_B5G6R5_UNORM, 5, 6, 5, 0, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_B4G4R4A4_UNORM, 4, 4, 4, 4, 0);
- InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_B5G5R5A1_UNORM, 5, 5, 5, 1, 0);
-
- return map;
-}
-
-struct DXGIDepthStencilInfo
-{
- unsigned int depthBits;
- unsigned int depthOffset;
- unsigned int stencilBits;
- unsigned int stencilOffset;
-};
-
-typedef std::map<DXGI_FORMAT, DXGIDepthStencilInfo> DepthStencilInfoMap;
-typedef std::pair<DXGI_FORMAT, DXGIDepthStencilInfo> DepthStencilInfoPair;
-
-static inline void InsertDXGIDepthStencilInfo(DepthStencilInfoMap *map, DXGI_FORMAT format, unsigned int depthBits,
- unsigned int depthOffset, unsigned int stencilBits, unsigned int stencilOffset)
-{
- DXGIDepthStencilInfo info;
- info.depthBits = depthBits;
- info.depthOffset = depthOffset;
- info.stencilBits = stencilBits;
- info.stencilOffset = stencilOffset;
-
- map->insert(std::make_pair(format, info));
}
-static DepthStencilInfoMap BuildDepthStencilInfoMap()
+constexpr VertexFormat::VertexFormat()
+ : conversionType(VERTEX_CONVERT_NONE), nativeFormat(DXGI_FORMAT_UNKNOWN), copyFunction(nullptr)
{
- DepthStencilInfoMap map;
-
- InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R16_TYPELESS, 16, 0, 0, 0);
- InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R16_UNORM, 16, 0, 0, 0);
- InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D16_UNORM, 16, 0, 0, 0);
-
- InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R24G8_TYPELESS, 24, 0, 8, 24);
- InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, 24, 0, 8, 24);
- InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, 24, 0, 8, 24);
-
- InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32_TYPELESS, 32, 0, 0, 0);
- InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32_FLOAT, 32, 0, 0, 0);
- InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D32_FLOAT, 32, 0, 0, 0);
-
- InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32G8X24_TYPELESS, 32, 0, 8, 32);
- InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, 32, 0, 8, 32);
- InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, 32, 0, 8, 32);
-
- return map;
-}
-
-typedef std::map<DXGI_FORMAT, DXGIFormat> DXGIFormatInfoMap;
-
-DXGIFormat::DXGIFormat()
- : pixelBytes(0),
- blockWidth(0),
- blockHeight(0),
- redBits(0),
- greenBits(0),
- blueBits(0),
- alphaBits(0),
- sharedBits(0),
- depthBits(0),
- depthOffset(0),
- stencilBits(0),
- stencilOffset(0),
- internalFormat(GL_NONE),
- componentType(GL_NONE),
- mipGenerationFunction(NULL),
- colorReadFunction(NULL),
- fastCopyFunctions(),
- nativeMipmapSupport(NULL)
-{
-}
-
-static bool NeverSupported(D3D_FEATURE_LEVEL)
-{
- return false;
-}
-
-template <D3D_FEATURE_LEVEL requiredFeatureLevel>
-static bool RequiresFeatureLevel(D3D_FEATURE_LEVEL featureLevel)
-{
- return featureLevel >= requiredFeatureLevel;
}
-ColorCopyFunction DXGIFormat::getFastCopyFunction(GLenum format, GLenum type) const
+constexpr VertexFormat::VertexFormat(VertexConversionType conversionTypeIn,
+ DXGI_FORMAT nativeFormatIn,
+ VertexCopyFunction copyFunctionIn)
+ : conversionType(conversionTypeIn), nativeFormat(nativeFormatIn), copyFunction(copyFunctionIn)
{
- FastCopyFunctionMap::const_iterator iter = fastCopyFunctions.find(std::make_pair(format, type));
- return (iter != fastCopyFunctions.end()) ? iter->second : NULL;
}
-void AddDXGIFormat(DXGIFormatInfoMap *map, DXGI_FORMAT dxgiFormat, GLuint pixelBits, GLuint blockWidth, GLuint blockHeight,
- GLenum componentType, MipGenerationFunction mipFunc, ColorReadFunction readFunc, NativeMipmapGenerationSupportFunction nativeMipmapSupport)
+const VertexFormat *GetVertexFormatInfo_FL_9_3(gl::VertexFormatType vertexFormatType)
{
- DXGIFormat info;
- info.pixelBytes = pixelBits / 8;
- info.blockWidth = blockWidth;
- info.blockHeight = blockHeight;
-
- static const ColorFormatInfoMap colorInfoMap = BuildColorFormatInfoMap();
- ColorFormatInfoMap::const_iterator colorInfoIter = colorInfoMap.find(dxgiFormat);
- if (colorInfoIter != colorInfoMap.end())
- {
- const DXGIColorFormatInfo &colorInfo = colorInfoIter->second;
- info.redBits = static_cast<GLuint>(colorInfo.redBits);
- info.greenBits = static_cast<GLuint>(colorInfo.greenBits);
- info.blueBits = static_cast<GLuint>(colorInfo.blueBits);
- info.alphaBits = static_cast<GLuint>(colorInfo.alphaBits);
- info.sharedBits = static_cast<GLuint>(colorInfo.sharedBits);
- }
-
- static const DepthStencilInfoMap dsInfoMap = BuildDepthStencilInfoMap();
- DepthStencilInfoMap::const_iterator dsInfoIter = dsInfoMap.find(dxgiFormat);
- if (dsInfoIter != dsInfoMap.end())
- {
- const DXGIDepthStencilInfo &dsInfo = dsInfoIter->second;
- info.depthBits = dsInfo.depthBits;
- info.depthOffset = dsInfo.depthOffset;
- info.stencilBits = dsInfo.stencilBits;
- info.stencilOffset = dsInfo.stencilOffset;
- }
-
- static const DXGIToESFormatMap dxgiToESMap = BuildDXGIToESFormatMap();
- DXGIToESFormatMap::const_iterator dxgiToESIter = dxgiToESMap.find(dxgiFormat);
- info.internalFormat = (dxgiToESIter != dxgiToESMap.end()) ? dxgiToESIter->second : GL_NONE;
-
- info.componentType = componentType;
-
- info.mipGenerationFunction = mipFunc;
- info.colorReadFunction = readFunc;
+ // D3D11 Feature Level 9_3 doesn't support as many formats for vertex buffer resource as Feature
+ // Level 10_0+.
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/ff471324(v=vs.85).aspx
- static const D3D11FastCopyMap fastCopyMap = BuildFastCopyMap();
- std::pair<D3D11FastCopyMap::const_iterator, D3D11FastCopyMap::const_iterator> fastCopyIter = fastCopyMap.equal_range(dxgiFormat);
- for (D3D11FastCopyMap::const_iterator i = fastCopyIter.first; i != fastCopyIter.second; i++)
+ switch (vertexFormatType)
{
- info.fastCopyFunctions.insert(std::make_pair(std::make_pair(i->second.destFormat, i->second.destType), i->second.copyFunction));
- }
-
- info.nativeMipmapSupport = nativeMipmapSupport;
-
- map->insert(std::make_pair(dxgiFormat, info));
-}
-
-// A map to determine the pixel size and mipmap generation function of a given DXGI format
-static DXGIFormatInfoMap BuildDXGIFormatInfoMap()
-{
- DXGIFormatInfoMap map;
-
- // | DXGI format |S |W |H |Component Type | Mip generation function | Color read function | Native mipmap function
- AddDXGIFormat(&map, DXGI_FORMAT_UNKNOWN, 0, 0, 0, GL_NONE, NULL, NULL, NeverSupported);
-
- AddDXGIFormat(&map, DXGI_FORMAT_A8_UNORM, 8, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<A8>, ReadColor<A8, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_10_0>);
- AddDXGIFormat(&map, DXGI_FORMAT_R8_UNORM, 8, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<R8>, ReadColor<R8, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_10_0>);
- AddDXGIFormat(&map, DXGI_FORMAT_R8G8_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<R8G8>, ReadColor<R8G8, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_10_0>);
- AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<R8G8B8A8>, ReadColor<R8G8B8A8, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_9_1>);
- AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<R8G8B8A8>, ReadColor<R8G8B8A8, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_9_1>);
- AddDXGIFormat(&map, DXGI_FORMAT_B8G8R8A8_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<B8G8R8A8>, ReadColor<B8G8R8A8, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_9_1>);
-
- AddDXGIFormat(&map, DXGI_FORMAT_R8_SNORM, 8, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip<R8S>, ReadColor<R8S, GLfloat> , RequiresFeatureLevel<D3D_FEATURE_LEVEL_10_0>);
- AddDXGIFormat(&map, DXGI_FORMAT_R8G8_SNORM, 16, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip<R8G8S>, ReadColor<R8G8S, GLfloat> , RequiresFeatureLevel<D3D_FEATURE_LEVEL_10_0>);
- AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_SNORM, 32, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip<R8G8B8A8S>, ReadColor<R8G8B8A8S, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_10_0>);
-
- AddDXGIFormat(&map, DXGI_FORMAT_R8_UINT, 8, 1, 1, GL_UNSIGNED_INT, GenerateMip<R8>, ReadColor<R8, GLuint>, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R16_UINT, 16, 1, 1, GL_UNSIGNED_INT, GenerateMip<R16>, ReadColor<R16, GLuint>, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R32_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip<R32>, ReadColor<R32, GLuint>, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R8G8_UINT, 16, 1, 1, GL_UNSIGNED_INT, GenerateMip<R8G8>, ReadColor<R8G8, GLuint>, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R16G16_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip<R16G16>, ReadColor<R16G16, GLuint>, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R32G32_UINT, 64, 1, 1, GL_UNSIGNED_INT, GenerateMip<R32G32>, ReadColor<R32G32, GLuint>, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_UINT, 96, 1, 1, GL_UNSIGNED_INT, GenerateMip<R32G32B32>, ReadColor<R32G32B32, GLuint>, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip<R8G8B8A8>, ReadColor<R8G8B8A8, GLuint>, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_UINT, 64, 1, 1, GL_UNSIGNED_INT, GenerateMip<R16G16B16A16>, ReadColor<R16G16B16A16, GLuint>, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_UINT, 128, 1, 1, GL_UNSIGNED_INT, GenerateMip<R32G32B32A32>, ReadColor<R32G32B32A32, GLuint>, NeverSupported);
+ // GL_BYTE -- unnormalized
+ case gl::VERTEX_FORMAT_SBYTE1:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT,
+ &Copy8SintTo16SintVertexData<1, 2>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_SBYTE2:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT,
+ &Copy8SintTo16SintVertexData<2, 2>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_SBYTE3:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT,
+ &Copy8SintTo16SintVertexData<3, 4>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_SBYTE4:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT,
+ &Copy8SintTo16SintVertexData<4, 4>);
+ return &info;
+ }
- AddDXGIFormat(&map, DXGI_FORMAT_R8_SINT, 8, 1, 1, GL_INT, GenerateMip<R8S>, ReadColor<R8S, GLint>, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R16_SINT, 16, 1, 1, GL_INT, GenerateMip<R16S>, ReadColor<R16S, GLint>, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R32_SINT, 32, 1, 1, GL_INT, GenerateMip<R32S>, ReadColor<R32S, GLint>, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R8G8_SINT, 16, 1, 1, GL_INT, GenerateMip<R8G8S>, ReadColor<R8G8S, GLint>, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R16G16_SINT, 32, 1, 1, GL_INT, GenerateMip<R16G16S>, ReadColor<R16G16S, GLint>, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R32G32_SINT, 64, 1, 1, GL_INT, GenerateMip<R32G32S>, ReadColor<R32G32S, GLint>, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_SINT, 96, 1, 1, GL_INT, GenerateMip<R32G32B32S>, ReadColor<R32G32B32S, GLint>, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_SINT, 32, 1, 1, GL_INT, GenerateMip<R8G8B8A8S>, ReadColor<R8G8B8A8S, GLint>, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_SINT, 64, 1, 1, GL_INT, GenerateMip<R16G16B16A16S>, ReadColor<R16G16B16A16S, GLint>, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_SINT, 128, 1, 1, GL_INT, GenerateMip<R32G32B32A32S>, ReadColor<R32G32B32A32S, GLint>, NeverSupported);
+ // GL_BYTE -- normalized
+ case gl::VERTEX_FORMAT_SBYTE1_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM,
+ &Copy8SnormTo16SnormVertexData<1, 2>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_SBYTE2_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM,
+ &Copy8SnormTo16SnormVertexData<2, 2>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_SBYTE3_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM,
+ &Copy8SnormTo16SnormVertexData<3, 4>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_SBYTE4_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM,
+ &Copy8SnormTo16SnormVertexData<4, 4>);
+ return &info;
+ }
- AddDXGIFormat(&map, DXGI_FORMAT_R10G10B10A2_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<R10G10B10A2>, ReadColor<R10G10B10A2, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_10_0>);
- AddDXGIFormat(&map, DXGI_FORMAT_R10G10B10A2_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip<R10G10B10A2>, ReadColor<R10G10B10A2, GLuint>, NeverSupported);
+ // GL_UNSIGNED_BYTE -- un-normalized
+ // NOTE: 3 and 4 component unnormalized GL_UNSIGNED_BYTE should use the default format
+ // table.
+ case gl::VERTEX_FORMAT_UBYTE1:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT,
+ &CopyNativeVertexData<GLubyte, 1, 4, 1>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_UBYTE2:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT,
+ &CopyNativeVertexData<GLubyte, 2, 4, 1>);
+ return &info;
+ }
- AddDXGIFormat(&map, DXGI_FORMAT_R16_FLOAT, 16, 1, 1, GL_FLOAT, GenerateMip<R16F>, ReadColor<R16F, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_10_0>);
- AddDXGIFormat(&map, DXGI_FORMAT_R16G16_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip<R16G16F>, ReadColor<R16G16F, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_9_2>);
- AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, 64, 1, 1, GL_FLOAT, GenerateMip<R16G16B16A16F>, ReadColor<R16G16B16A16F, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_9_2>);
+ // GL_UNSIGNED_BYTE -- normalized
+ // NOTE: 3 and 4 component normalized GL_UNSIGNED_BYTE should use the default format table.
- AddDXGIFormat(&map, DXGI_FORMAT_R32_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip<R32F>, ReadColor<R32F, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_9_2>);
- AddDXGIFormat(&map, DXGI_FORMAT_R32G32_FLOAT, 64, 1, 1, GL_FLOAT, GenerateMip<R32G32F>, ReadColor<R32G32F, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_10_0>);
- AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_FLOAT, 96, 1, 1, GL_FLOAT, NULL, NULL, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, 128, 1, 1, GL_FLOAT, GenerateMip<R32G32B32A32F>, ReadColor<R32G32B32A32F, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_9_3>);
+ // GL_UNSIGNED_BYTE -- normalized
+ case gl::VERTEX_FORMAT_UBYTE1_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM,
+ &CopyNativeVertexData<GLubyte, 1, 4, UINT8_MAX>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_UBYTE2_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM,
+ &CopyNativeVertexData<GLubyte, 2, 4, UINT8_MAX>);
+ return &info;
+ }
- AddDXGIFormat(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, 32, 1, 1, GL_FLOAT, GenerateMip<R9G9B9E5>, ReadColor<R9G9B9E5, GLfloat>, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R11G11B10_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip<R11G11B10F>, ReadColor<R11G11B10F, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_10_0>);
+ // GL_SHORT -- un-normalized
+ // NOTE: 2, 3 and 4 component unnormalized GL_SHORT should use the default format table.
+ case gl::VERTEX_FORMAT_SSHORT1:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT,
+ &CopyNativeVertexData<GLshort, 1, 2, 0>);
+ return &info;
+ }
- AddDXGIFormat(&map, DXGI_FORMAT_R16_TYPELESS, 16, 1, 1, GL_NONE, NULL, NULL, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_D16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R24G8_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, 32, 1, 1, GL_UNSIGNED_INT, NULL, NULL, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R32G8X24_TYPELESS, 64, 1, 1, GL_NONE, NULL, NULL, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, 64, 1, 1, GL_NONE, NULL, NULL, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, 64, 1, 1, GL_UNSIGNED_INT, NULL, NULL, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R32_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_D32_FLOAT, 32, 1, 1, GL_FLOAT, NULL, NULL, NeverSupported);
+ // GL_SHORT -- normalized
+ // NOTE: 2, 3 and 4 component normalized GL_SHORT should use the default format table.
+ case gl::VERTEX_FORMAT_SSHORT1_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM,
+ &CopyNativeVertexData<GLshort, 1, 2, 0>);
+ return &info;
+ }
- AddDXGIFormat(&map, DXGI_FORMAT_BC1_UNORM, 64, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_BC2_UNORM, 128, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_BC3_UNORM, 128, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL, NeverSupported);
+ // GL_UNSIGNED_SHORT -- un-normalized
+ case gl::VERTEX_FORMAT_USHORT1:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &CopyTo32FVertexData<GLushort, 1, 2, false>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_USHORT2:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &CopyTo32FVertexData<GLushort, 2, 2, false>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_USHORT3:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT,
+ &CopyTo32FVertexData<GLushort, 3, 3, false>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_USHORT4:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &CopyTo32FVertexData<GLushort, 4, 4, false>);
+ return &info;
+ }
- // B5G6R5 in D3D11 is treated the same as R5G6B5 in D3D9, so reuse the R5G6B5 functions used by the D3D9 renderer.
- // The same applies to B4G4R4A4 and B5G5R5A1 with A4R4G4B4 and A1R5G5B5 respectively.
- AddDXGIFormat(&map, DXGI_FORMAT_B5G6R5_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<R5G6B5>, ReadColor<R5G6B5, GLfloat>, RequiresFeatureLevel<D3D_FEATURE_LEVEL_9_1>);
- AddDXGIFormat(&map, DXGI_FORMAT_B4G4R4A4_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<A4R4G4B4>, ReadColor<A4R4G4B4, GLfloat>, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_B5G5R5A1_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip<A1R5G5B5>, ReadColor<A1R5G5B5, GLfloat>, NeverSupported);
+ // GL_UNSIGNED_SHORT -- normalized
+ case gl::VERTEX_FORMAT_USHORT1_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &CopyTo32FVertexData<GLushort, 1, 2, true>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_USHORT2_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &CopyTo32FVertexData<GLushort, 2, 2, true>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_USHORT3_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT,
+ &CopyTo32FVertexData<GLushort, 3, 3, true>);
+ return &info;
+ }
+ case gl::VERTEX_FORMAT_USHORT4_NORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &CopyTo32FVertexData<GLushort, 4, 4, true>);
+ return &info;
+ }
- // Useful formats for vertex buffers
- AddDXGIFormat(&map, DXGI_FORMAT_R16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R16_SNORM, 16, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R16G16_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R16G16_SNORM, 32, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_UNORM, 64, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL, NeverSupported);
- AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_SNORM, 64, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL, NeverSupported);
+ // GL_FIXED
+ // TODO: Add test to verify that this works correctly.
+ // NOTE: 2, 3 and 4 component GL_FIXED should use the default format table.
+ case gl::VERTEX_FORMAT_FIXED1:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &Copy32FixedTo32FVertexData<1, 2>);
+ return &info;
+ }
- return map;
-}
+ // GL_FLOAT
+ // TODO: Add test to verify that this works correctly.
+ // NOTE: 2, 3 and 4 component GL_FLOAT should use the default format table.
+ case gl::VERTEX_FORMAT_FLOAT1:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &CopyNativeVertexData<GLfloat, 1, 2, 0>);
+ return &info;
+ }
-const DXGIFormat &GetDXGIFormatInfo(DXGI_FORMAT format)
-{
- static const DXGIFormatInfoMap infoMap = BuildDXGIFormatInfoMap();
- DXGIFormatInfoMap::const_iterator iter = infoMap.find(format);
- if (iter != infoMap.end())
- {
- return iter->second;
- }
- else
- {
- static DXGIFormat defaultInfo;
- return defaultInfo;
+ default:
+ return nullptr;
}
}
-typedef std::map<gl::VertexFormatType, VertexFormat> D3D11VertexFormatInfoMap;
-typedef std::pair<gl::VertexFormatType, VertexFormat> D3D11VertexFormatPair;
-
-VertexFormat::VertexFormat()
- : conversionType(VERTEX_CONVERT_NONE),
- nativeFormat(DXGI_FORMAT_UNKNOWN),
- copyFunction(NULL)
-{
-}
-
-VertexFormat::VertexFormat(VertexConversionType conversionTypeIn,
- DXGI_FORMAT nativeFormatIn,
- VertexCopyFunction copyFunctionIn)
- : conversionType(conversionTypeIn),
- nativeFormat(nativeFormatIn),
- copyFunction(copyFunctionIn)
-{
-}
-
-static void AddVertexFormatInfo(D3D11VertexFormatInfoMap *map,
- GLenum inputType,
- GLboolean normalized,
- GLuint componentCount,
- VertexConversionType conversionType,
- DXGI_FORMAT nativeFormat,
- VertexCopyFunction copyFunction)
-{
- gl::VertexFormatType formatType = gl::GetVertexFormatType(inputType, normalized, componentCount, false);
-
- VertexFormat info;
- info.conversionType = conversionType;
- info.nativeFormat = nativeFormat;
- info.copyFunction = copyFunction;
-
- map->insert(D3D11VertexFormatPair(formatType, info));
-}
-
-static D3D11VertexFormatInfoMap BuildD3D11_FL9_3VertexFormatInfoOverrideMap()
-{
- // D3D11 Feature Level 9_3 doesn't support as many formats for vertex buffer resource as Feature Level 10_0+.
- // http://msdn.microsoft.com/en-us/library/windows/desktop/ff471324(v=vs.85).aspx
-
- D3D11VertexFormatInfoMap map;
-
- // GL_BYTE -- unnormalized
- AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 1, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT, &Copy8SintTo16SintVertexData<1, 2>);
- AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 2, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT, &Copy8SintTo16SintVertexData<2, 2>);
- AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, &Copy8SintTo16SintVertexData<3, 4>);
- AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 4, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, &Copy8SintTo16SintVertexData<4, 4>);
-
- // GL_BYTE -- normalized
- AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM, &Copy8SnormTo16SnormVertexData<1, 2>);
- AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM, &Copy8SnormTo16SnormVertexData<2, 2>);
- AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, &Copy8SnormTo16SnormVertexData<3, 4>);
- AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, &Copy8SnormTo16SnormVertexData<4, 4>);
-
- // GL_UNSIGNED_BYTE -- unnormalized
- AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 1, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 1, 4, 1>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 2, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 2, 4, 1>);
- // NOTE: 3 and 4 component unnormalized GL_UNSIGNED_BYTE should use the default format table.
-
- // GL_UNSIGNED_BYTE -- normalized
- AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData<GLubyte, 1, 4, UINT8_MAX>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData<GLubyte, 2, 4, UINT8_MAX>);
- // NOTE: 3 and 4 component normalized GL_UNSIGNED_BYTE should use the default format table.
-
- // GL_SHORT -- unnormalized
- AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 1, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData<GLshort, 1, 2, 0>);
- // NOTE: 2, 3 and 4 component unnormalized GL_SHORT should use the default format table.
-
- // GL_SHORT -- normalized
- AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM, &CopyNativeVertexData<GLshort, 1, 2, 0>);
- // NOTE: 2, 3 and 4 component normalized GL_SHORT should use the default format table.
-
- // GL_UNSIGNED_SHORT -- unnormalized
- AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLushort, 1, 2, false>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLushort, 2, 2, false>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData<GLushort, 3, 3, false>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData<GLushort, 4, 4, false>);
-
- // GL_UNSIGNED_SHORT -- normalized
- AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLushort, 1, 2, true>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLushort, 2, 2, true>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData<GLushort, 3, 3, true>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData<GLushort, 4, 4, true>);
-
- // GL_FIXED
- // TODO: Add test to verify that this works correctly.
- AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &Copy32FixedTo32FVertexData<1, 2>);
- // NOTE: 2, 3 and 4 component GL_FIXED should use the default format table.
-
- // GL_FLOAT
- // TODO: Add test to verify that this works correctly.
- AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyNativeVertexData<GLfloat, 1, 2, 0>);
- // NOTE: 2, 3 and 4 component GL_FLOAT should use the default format table.
-
- return map;
-}
-
const VertexFormat &GetVertexFormatInfo(gl::VertexFormatType vertexFormatType, D3D_FEATURE_LEVEL featureLevel)
{
if (featureLevel == D3D_FEATURE_LEVEL_9_3)
{
- static const D3D11VertexFormatInfoMap vertexFormatMapFL9_3Override =
- BuildD3D11_FL9_3VertexFormatInfoOverrideMap();
-
- // First see if the format has a special mapping for FL9_3
- auto iter = vertexFormatMapFL9_3Override.find(vertexFormatType);
- if (iter != vertexFormatMapFL9_3Override.end())
+ const VertexFormat *result = GetVertexFormatInfo_FL_9_3(vertexFormatType);
+ if (result)
{
- return iter->second;
+ return *result;
}
}
@@ -589,354 +419,418 @@ const VertexFormat &GetVertexFormatInfo(gl::VertexFormatType vertexFormatType, D
// GL_BYTE -- un-normalized
case gl::VERTEX_FORMAT_SBYTE1:
{
- static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData<GLbyte, 1, 1, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_SINT,
+ &CopyNativeVertexData<GLbyte, 1, 1, 0>);
return info;
}
case gl::VERTEX_FORMAT_SBYTE2:
{
- static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_SINT, &CopyNativeVertexData<GLbyte, 2, 2, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_SINT,
+ &CopyNativeVertexData<GLbyte, 2, 2, 0>);
return info;
}
case gl::VERTEX_FORMAT_SBYTE3:
{
- static const VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 3, 4, 1>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_SINT,
+ &CopyNativeVertexData<GLbyte, 3, 4, 1>);
return info;
}
case gl::VERTEX_FORMAT_SBYTE4:
{
- static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 4, 4, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_SINT,
+ &CopyNativeVertexData<GLbyte, 4, 4, 0>);
return info;
}
// GL_BYTE -- normalized
case gl::VERTEX_FORMAT_SBYTE1_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SNORM, &CopyNativeVertexData<GLbyte, 1, 1, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SNORM,
+ &CopyNativeVertexData<GLbyte, 1, 1, 0>);
return info;
}
case gl::VERTEX_FORMAT_SBYTE2_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SNORM, &CopyNativeVertexData<GLbyte, 2, 2, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SNORM,
+ &CopyNativeVertexData<GLbyte, 2, 2, 0>);
return info;
}
case gl::VERTEX_FORMAT_SBYTE3_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SNORM, &CopyNativeVertexData<GLbyte, 3, 4, INT8_MAX>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SNORM,
+ &CopyNativeVertexData<GLbyte, 3, 4, INT8_MAX>);
return info;
}
case gl::VERTEX_FORMAT_SBYTE4_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SNORM, &CopyNativeVertexData<GLbyte, 4, 4, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SNORM,
+ &CopyNativeVertexData<GLbyte, 4, 4, 0>);
return info;
}
// GL_UNSIGNED_BYTE -- un-normalized
case gl::VERTEX_FORMAT_UBYTE1:
{
- static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData<GLubyte, 1, 1, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_UINT,
+ &CopyNativeVertexData<GLubyte, 1, 1, 0>);
return info;
}
case gl::VERTEX_FORMAT_UBYTE2:
{
- static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_UINT, &CopyNativeVertexData<GLubyte, 2, 2, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_UINT,
+ &CopyNativeVertexData<GLubyte, 2, 2, 0>);
return info;
}
case gl::VERTEX_FORMAT_UBYTE3:
{
- static const VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 3, 4, 1>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT,
+ &CopyNativeVertexData<GLubyte, 3, 4, 1>);
return info;
}
case gl::VERTEX_FORMAT_UBYTE4:
{
- static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 4, 4, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_UINT,
+ &CopyNativeVertexData<GLubyte, 4, 4, 0>);
return info;
}
// GL_UNSIGNED_BYTE -- normalized
case gl::VERTEX_FORMAT_UBYTE1_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UNORM, &CopyNativeVertexData<GLubyte, 1, 1, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UNORM,
+ &CopyNativeVertexData<GLubyte, 1, 1, 0>);
return info;
}
case gl::VERTEX_FORMAT_UBYTE2_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UNORM, &CopyNativeVertexData<GLubyte, 2, 2, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UNORM,
+ &CopyNativeVertexData<GLubyte, 2, 2, 0>);
return info;
}
case gl::VERTEX_FORMAT_UBYTE3_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData<GLubyte, 3, 4, UINT8_MAX>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM,
+ &CopyNativeVertexData<GLubyte, 3, 4, UINT8_MAX>);
return info;
}
case gl::VERTEX_FORMAT_UBYTE4_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData<GLubyte, 4, 4, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UNORM,
+ &CopyNativeVertexData<GLubyte, 4, 4, 0>);
return info;
}
// GL_SHORT -- un-normalized
case gl::VERTEX_FORMAT_SSHORT1:
{
- static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData<GLshort, 1, 1, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_SINT,
+ &CopyNativeVertexData<GLshort, 1, 1, 0>);
return info;
}
case gl::VERTEX_FORMAT_SSHORT2:
{
- static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData<GLshort, 2, 2, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_SINT,
+ &CopyNativeVertexData<GLshort, 2, 2, 0>);
return info;
}
case gl::VERTEX_FORMAT_SSHORT3:
{
- static const VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 3, 4, 1>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT,
+ &CopyNativeVertexData<GLshort, 3, 4, 1>);
return info;
}
case gl::VERTEX_FORMAT_SSHORT4:
{
- static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 4, 4, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_SINT,
+ &CopyNativeVertexData<GLshort, 4, 4, 0>);
return info;
}
// GL_SHORT -- normalized
case gl::VERTEX_FORMAT_SSHORT1_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SNORM, &CopyNativeVertexData<GLshort, 1, 1, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SNORM,
+ &CopyNativeVertexData<GLshort, 1, 1, 0>);
return info;
}
case gl::VERTEX_FORMAT_SSHORT2_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SNORM, &CopyNativeVertexData<GLshort, 2, 2, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SNORM,
+ &CopyNativeVertexData<GLshort, 2, 2, 0>);
return info;
}
case gl::VERTEX_FORMAT_SSHORT3_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, &CopyNativeVertexData<GLshort, 3, 4, INT16_MAX>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM,
+ &CopyNativeVertexData<GLshort, 3, 4, INT16_MAX>);
return info;
}
case gl::VERTEX_FORMAT_SSHORT4_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SNORM, &CopyNativeVertexData<GLshort, 4, 4, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SNORM,
+ &CopyNativeVertexData<GLshort, 4, 4, 0>);
return info;
}
// GL_UNSIGNED_SHORT -- un-normalized
case gl::VERTEX_FORMAT_USHORT1:
{
- static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData<GLushort, 1, 1, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_UINT,
+ &CopyNativeVertexData<GLushort, 1, 1, 0>);
return info;
}
case gl::VERTEX_FORMAT_USHORT2:
{
- static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_UINT, &CopyNativeVertexData<GLushort, 2, 2, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_UINT,
+ &CopyNativeVertexData<GLushort, 2, 2, 0>);
return info;
}
case gl::VERTEX_FORMAT_USHORT3:
{
- static const VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 3, 4, 1>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_UINT,
+ &CopyNativeVertexData<GLushort, 3, 4, 1>);
return info;
}
case gl::VERTEX_FORMAT_USHORT4:
{
- static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 4, 4, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_UINT,
+ &CopyNativeVertexData<GLushort, 4, 4, 0>);
return info;
}
// GL_UNSIGNED_SHORT -- normalized
case gl::VERTEX_FORMAT_USHORT1_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UNORM, &CopyNativeVertexData<GLushort, 1, 1, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UNORM,
+ &CopyNativeVertexData<GLushort, 1, 1, 0>);
return info;
}
case gl::VERTEX_FORMAT_USHORT2_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UNORM, &CopyNativeVertexData<GLushort, 2, 2, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UNORM,
+ &CopyNativeVertexData<GLushort, 2, 2, 0>);
return info;
}
case gl::VERTEX_FORMAT_USHORT3_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UNORM, &CopyNativeVertexData<GLushort, 3, 4, UINT16_MAX>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UNORM,
+ &CopyNativeVertexData<GLushort, 3, 4, UINT16_MAX>);
return info;
}
case gl::VERTEX_FORMAT_USHORT4_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UNORM, &CopyNativeVertexData<GLushort, 4, 4, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UNORM,
+ &CopyNativeVertexData<GLushort, 4, 4, 0>);
return info;
}
// GL_INT -- un-normalized
case gl::VERTEX_FORMAT_SINT1:
{
- static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData<GLint, 1, 1, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_SINT,
+ &CopyNativeVertexData<GLint, 1, 1, 0>);
return info;
}
case gl::VERTEX_FORMAT_SINT2:
{
- static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData<GLint, 2, 2, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_SINT,
+ &CopyNativeVertexData<GLint, 2, 2, 0>);
return info;
}
case gl::VERTEX_FORMAT_SINT3:
{
- static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData<GLint, 3, 3, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_SINT,
+ &CopyNativeVertexData<GLint, 3, 3, 0>);
return info;
}
case gl::VERTEX_FORMAT_SINT4:
{
- static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData<GLint, 4, 4, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_SINT,
+ &CopyNativeVertexData<GLint, 4, 4, 0>);
return info;
}
// GL_INT -- normalized
case gl::VERTEX_FORMAT_SINT1_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData<GLint, 1, 1, true>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT,
+ &CopyTo32FVertexData<GLint, 1, 1, true>);
return info;
}
case gl::VERTEX_FORMAT_SINT2_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLint, 2, 2, true>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &CopyTo32FVertexData<GLint, 2, 2, true>);
return info;
}
case gl::VERTEX_FORMAT_SINT3_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData<GLint, 3, 3, true>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT,
+ &CopyTo32FVertexData<GLint, 3, 3, true>);
return info;
}
case gl::VERTEX_FORMAT_SINT4_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData<GLint, 4, 4, true>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &CopyTo32FVertexData<GLint, 4, 4, true>);
return info;
}
// GL_UNSIGNED_INT -- un-normalized
case gl::VERTEX_FORMAT_UINT1:
{
- static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_UINT, &CopyNativeVertexData<GLuint, 1, 1, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_UINT,
+ &CopyNativeVertexData<GLuint, 1, 1, 0>);
return info;
}
case gl::VERTEX_FORMAT_UINT2:
{
- static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_UINT, &CopyNativeVertexData<GLuint, 2, 2, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_UINT,
+ &CopyNativeVertexData<GLuint, 2, 2, 0>);
return info;
}
case gl::VERTEX_FORMAT_UINT3:
{
- static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_UINT, &CopyNativeVertexData<GLuint, 3, 3, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_UINT,
+ &CopyNativeVertexData<GLuint, 3, 3, 0>);
return info;
}
case gl::VERTEX_FORMAT_UINT4:
{
- static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_UINT, &CopyNativeVertexData<GLuint, 4, 4, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_UINT,
+ &CopyNativeVertexData<GLuint, 4, 4, 0>);
return info;
}
// GL_UNSIGNED_INT -- normalized
case gl::VERTEX_FORMAT_UINT1_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData<GLuint, 1, 1, true>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT,
+ &CopyTo32FVertexData<GLuint, 1, 1, true>);
return info;
}
case gl::VERTEX_FORMAT_UINT2_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLuint, 2, 2, true>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &CopyTo32FVertexData<GLuint, 2, 2, true>);
return info;
}
case gl::VERTEX_FORMAT_UINT3_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData<GLuint, 3, 3, true>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT,
+ &CopyTo32FVertexData<GLuint, 3, 3, true>);
return info;
}
case gl::VERTEX_FORMAT_UINT4_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData<GLuint, 4, 4, true>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &CopyTo32FVertexData<GLuint, 4, 4, true>);
return info;
}
// GL_FIXED
case gl::VERTEX_FORMAT_FIXED1:
{
- static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &Copy32FixedTo32FVertexData<1, 1>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT,
+ &Copy32FixedTo32FVertexData<1, 1>);
return info;
}
case gl::VERTEX_FORMAT_FIXED2:
{
- static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &Copy32FixedTo32FVertexData<2, 2>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &Copy32FixedTo32FVertexData<2, 2>);
return info;
}
case gl::VERTEX_FORMAT_FIXED3:
{
- static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &Copy32FixedTo32FVertexData<3, 3>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT,
+ &Copy32FixedTo32FVertexData<3, 3>);
return info;
}
case gl::VERTEX_FORMAT_FIXED4:
{
- static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &Copy32FixedTo32FVertexData<4, 4>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &Copy32FixedTo32FVertexData<4, 4>);
return info;
}
// GL_HALF_FLOAT
case gl::VERTEX_FORMAT_HALF1:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_FLOAT, &CopyNativeVertexData<GLhalf, 1, 1, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_FLOAT,
+ &CopyNativeVertexData<GLhalf, 1, 1, 0>);
return info;
}
case gl::VERTEX_FORMAT_HALF2:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_FLOAT, &CopyNativeVertexData<GLhalf, 2, 2, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_FLOAT,
+ &CopyNativeVertexData<GLhalf, 2, 2, 0>);
return info;
}
case gl::VERTEX_FORMAT_HALF3:
{
- static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_FLOAT, &CopyNativeVertexData<GLhalf, 3, 4, gl::Float16One>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_FLOAT,
+ &CopyNativeVertexData<GLhalf, 3, 4, gl::Float16One>);
return info;
}
case gl::VERTEX_FORMAT_HALF4:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_FLOAT, &CopyNativeVertexData<GLhalf, 4, 4, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_FLOAT,
+ &CopyNativeVertexData<GLhalf, 4, 4, 0>);
return info;
}
// GL_FLOAT
case gl::VERTEX_FORMAT_FLOAT1:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyNativeVertexData<GLfloat, 1, 1, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT,
+ &CopyNativeVertexData<GLfloat, 1, 1, 0>);
return info;
}
case gl::VERTEX_FORMAT_FLOAT2:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, &CopyNativeVertexData<GLfloat, 2, 2, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT,
+ &CopyNativeVertexData<GLfloat, 2, 2, 0>);
return info;
}
case gl::VERTEX_FORMAT_FLOAT3:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_FLOAT, &CopyNativeVertexData<GLfloat, 3, 3, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_FLOAT,
+ &CopyNativeVertexData<GLfloat, 3, 3, 0>);
return info;
}
case gl::VERTEX_FORMAT_FLOAT4:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyNativeVertexData<GLfloat, 4, 4, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &CopyNativeVertexData<GLfloat, 4, 4, 0>);
return info;
}
// GL_INT_2_10_10_10_REV
case gl::VERTEX_FORMAT_SINT210:
{
- static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData<true, false, true>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &CopyXYZ10W2ToXYZW32FVertexData<true, false, true>);
return info;
}
case gl::VERTEX_FORMAT_SINT210_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData<true, true, true>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &CopyXYZ10W2ToXYZW32FVertexData<true, true, true>);
return info;
}
// GL_UNSIGNED_INT_2_10_10_10_REV
case gl::VERTEX_FORMAT_UINT210:
{
- static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData<false, false, true>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &CopyXYZ10W2ToXYZW32FVertexData<false, false, true>);
return info;
}
case gl::VERTEX_FORMAT_UINT210_NORM:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UNORM, &CopyNativeVertexData<GLuint, 1, 1, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UNORM,
+ &CopyNativeVertexData<GLuint, 1, 1, 0>);
return info;
}
@@ -947,157 +841,183 @@ const VertexFormat &GetVertexFormatInfo(gl::VertexFormatType vertexFormatType, D
// GL_BYTE
case gl::VERTEX_FORMAT_SBYTE1_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData<GLbyte, 1, 1, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SINT,
+ &CopyNativeVertexData<GLbyte, 1, 1, 0>);
return info;
}
case gl::VERTEX_FORMAT_SBYTE2_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SINT, &CopyNativeVertexData<GLbyte, 2, 2, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SINT,
+ &CopyNativeVertexData<GLbyte, 2, 2, 0>);
return info;
}
case gl::VERTEX_FORMAT_SBYTE3_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 3, 4, 1>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SINT,
+ &CopyNativeVertexData<GLbyte, 3, 4, 1>);
return info;
}
case gl::VERTEX_FORMAT_SBYTE4_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 4, 4, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SINT,
+ &CopyNativeVertexData<GLbyte, 4, 4, 0>);
return info;
}
// GL_UNSIGNED_BYTE
case gl::VERTEX_FORMAT_UBYTE1_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData<GLubyte, 1, 1, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UINT,
+ &CopyNativeVertexData<GLubyte, 1, 1, 0>);
return info;
}
case gl::VERTEX_FORMAT_UBYTE2_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UINT, &CopyNativeVertexData<GLubyte, 2, 2, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UINT,
+ &CopyNativeVertexData<GLubyte, 2, 2, 0>);
return info;
}
case gl::VERTEX_FORMAT_UBYTE3_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 3, 4, 1>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UINT,
+ &CopyNativeVertexData<GLubyte, 3, 4, 1>);
return info;
}
case gl::VERTEX_FORMAT_UBYTE4_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 4, 4, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UINT,
+ &CopyNativeVertexData<GLubyte, 4, 4, 0>);
return info;
}
// GL_SHORT
case gl::VERTEX_FORMAT_SSHORT1_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData<GLshort, 1, 1, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SINT,
+ &CopyNativeVertexData<GLshort, 1, 1, 0>);
return info;
}
case gl::VERTEX_FORMAT_SSHORT2_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData<GLshort, 2, 2, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SINT,
+ &CopyNativeVertexData<GLshort, 2, 2, 0>);
return info;
}
case gl::VERTEX_FORMAT_SSHORT3_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 3, 4, 1>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT,
+ &CopyNativeVertexData<GLshort, 3, 4, 1>);
return info;
}
case gl::VERTEX_FORMAT_SSHORT4_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 4, 4, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SINT,
+ &CopyNativeVertexData<GLshort, 4, 4, 0>);
return info;
}
// GL_UNSIGNED_SHORT
case gl::VERTEX_FORMAT_USHORT1_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData<GLushort, 1, 1, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UINT,
+ &CopyNativeVertexData<GLushort, 1, 1, 0>);
return info;
}
case gl::VERTEX_FORMAT_USHORT2_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UINT, &CopyNativeVertexData<GLushort, 2, 2, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UINT,
+ &CopyNativeVertexData<GLushort, 2, 2, 0>);
return info;
}
case gl::VERTEX_FORMAT_USHORT3_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 3, 4, 1>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UINT,
+ &CopyNativeVertexData<GLushort, 3, 4, 1>);
return info;
}
case gl::VERTEX_FORMAT_USHORT4_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 4, 4, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UINT,
+ &CopyNativeVertexData<GLushort, 4, 4, 0>);
return info;
}
// GL_INT
case gl::VERTEX_FORMAT_SINT1_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData<GLint, 1, 1, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT,
+ &CopyNativeVertexData<GLint, 1, 1, 0>);
return info;
}
case gl::VERTEX_FORMAT_SINT2_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData<GLint, 2, 2, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT,
+ &CopyNativeVertexData<GLint, 2, 2, 0>);
return info;
}
case gl::VERTEX_FORMAT_SINT3_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData<GLint, 3, 3, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT,
+ &CopyNativeVertexData<GLint, 3, 3, 0>);
return info;
}
case gl::VERTEX_FORMAT_SINT4_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData<GLint, 4, 4, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT,
+ &CopyNativeVertexData<GLint, 4, 4, 0>);
return info;
}
// GL_UNSIGNED_INT
case gl::VERTEX_FORMAT_UINT1_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData<GLuint, 1, 1, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT,
+ &CopyNativeVertexData<GLuint, 1, 1, 0>);
return info;
}
case gl::VERTEX_FORMAT_UINT2_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData<GLuint, 2, 2, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT,
+ &CopyNativeVertexData<GLuint, 2, 2, 0>);
return info;
}
case gl::VERTEX_FORMAT_UINT3_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData<GLuint, 3, 3, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT,
+ &CopyNativeVertexData<GLuint, 3, 3, 0>);
return info;
}
case gl::VERTEX_FORMAT_UINT4_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData<GLuint, 4, 4, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT,
+ &CopyNativeVertexData<GLuint, 4, 4, 0>);
return info;
}
// GL_INT_2_10_10_10_REV
case gl::VERTEX_FORMAT_SINT210_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyXYZ10W2ToXYZW32FVertexData<true, true, false>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT,
+ &CopyXYZ10W2ToXYZW32FVertexData<true, true, false>);
return info;
}
// GL_UNSIGNED_INT_2_10_10_10_REV
case gl::VERTEX_FORMAT_UINT210_INT:
{
- static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UINT, &CopyNativeVertexData<GLuint, 1, 1, 0>);
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UINT,
+ &CopyNativeVertexData<GLuint, 1, 1, 0>);
return info;
}
default:
{
- static const VertexFormat info;
+ static constexpr VertexFormat info;
return info;
}
}
}
-}
+} // namespace d3d11
-}
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h
index 7b97527140..883d338377 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h
@@ -15,6 +15,7 @@
#include "common/platform.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/renderer_utils.h"
#include "libANGLE/renderer/d3d/formatutilsD3D.h"
namespace rx
@@ -24,58 +25,47 @@ struct Renderer11DeviceCaps;
namespace d3d11
{
-typedef std::map<std::pair<GLenum, GLenum>, ColorCopyFunction> FastCopyFunctionMap;
-typedef bool (*NativeMipmapGenerationSupportFunction)(D3D_FEATURE_LEVEL);
+// A texture might be stored as DXGI_FORMAT_R16_TYPELESS but store integer components,
+// which are accessed through an DXGI_FORMAT_R16_SINT view. It's easy to write code which queries
+// information about the wrong format. Therefore, use of this should be avoided where possible.
-struct DXGIFormat
+bool SupportsMipGen(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel);
+
+struct DXGIFormatSize
{
- DXGIFormat();
+ DXGIFormatSize(GLuint pixelBits, GLuint blockWidth, GLuint blockHeight);
GLuint pixelBytes;
GLuint blockWidth;
GLuint blockHeight;
-
- GLuint redBits;
- GLuint greenBits;
- GLuint blueBits;
- GLuint alphaBits;
- GLuint sharedBits;
-
- GLuint depthBits;
- GLuint depthOffset;
- GLuint stencilBits;
- GLuint stencilOffset;
-
- GLenum internalFormat;
- GLenum componentType;
-
- MipGenerationFunction mipGenerationFunction;
- ColorReadFunction colorReadFunction;
-
- FastCopyFunctionMap fastCopyFunctions;
-
- NativeMipmapGenerationSupportFunction nativeMipmapSupport;
-
- ColorCopyFunction getFastCopyFunction(GLenum format, GLenum type) const;
};
-const DXGIFormat &GetDXGIFormatInfo(DXGI_FORMAT format);
+const DXGIFormatSize &GetDXGIFormatSizeInfo(DXGI_FORMAT format);
-struct VertexFormat
+struct VertexFormat : private angle::NonCopyable
{
- VertexFormat();
- VertexFormat(VertexConversionType conversionType,
- DXGI_FORMAT nativeFormat,
- VertexCopyFunction copyFunction);
+ constexpr VertexFormat();
+ constexpr VertexFormat(VertexConversionType conversionType,
+ DXGI_FORMAT nativeFormat,
+ VertexCopyFunction copyFunction);
VertexConversionType conversionType;
DXGI_FORMAT nativeFormat;
VertexCopyFunction copyFunction;
};
+
const VertexFormat &GetVertexFormatInfo(gl::VertexFormatType vertexFormatType,
D3D_FEATURE_LEVEL featureLevel);
+// Auto-generated in dxgi_format_map_autogen.cpp.
+GLenum GetComponentType(DXGI_FORMAT dxgiFormat);
+
} // namespace d3d11
+namespace d3d11_angle
+{
+const angle::Format &GetFormat(DXGI_FORMAT dxgiFormat);
+}
+
} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/gen_load_functions_table.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/gen_load_functions_table.cpp
deleted file mode 100644
index e69de29bb2..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/gen_load_functions_table.cpp
+++ /dev/null
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.cpp
deleted file mode 100644
index adb20a5e60..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.cpp
+++ /dev/null
@@ -1,170 +0,0 @@
-//
-// Copyright 2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// internal_format_initializer_table:
-// Contains table to go from internal format and dxgi format to initializer function
-// for TextureFormat
-//
-
-#include "libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h"
-#include "libANGLE/renderer/d3d/loadimage.h"
-
-namespace rx
-{
-
-namespace d3d11
-{
-
-// TODO: This should be generated by a JSON file
-InitializeTextureDataFunction GetInternalFormatInitializer(GLenum internalFormat,
- DXGI_FORMAT dxgiFormat)
-{
- switch (internalFormat)
- {
- case GL_RGB8:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8B8A8_UNORM:
- {
- return Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>;
- }
- default:
- break;
- }
- }
- case GL_RGB565:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8B8A8_UNORM:
- {
- return Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>;
- }
- default:
- break;
- }
- }
- case GL_SRGB8:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
- {
- return Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>;
- }
- default:
- break;
- }
- }
- case GL_RGB16F:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R16G16B16A16_FLOAT:
- {
- return Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>;
- }
- default:
- break;
- }
- }
- case GL_RGB32F:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R32G32B32A32_FLOAT:
- {
- return Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000,
- gl::Float32One>;
- }
- default:
- break;
- }
- }
- case GL_RGB8UI:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8B8A8_UINT:
- {
- return Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0x01>;
- }
- default:
- break;
- }
- }
- case GL_RGB8I:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8B8A8_SINT:
- {
- return Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x01>;
- }
- default:
- break;
- }
- }
- case GL_RGB16UI:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R16G16B16A16_UINT:
- {
- return Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x0001>;
- }
- default:
- break;
- }
- }
- case GL_RGB16I:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R16G16B16A16_SINT:
- {
- return Initialize4ComponentData<GLshort, 0x0000, 0x0000, 0x0000, 0x0001>;
- }
- default:
- break;
- }
- }
- case GL_RGB32UI:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R32G32B32A32_UINT:
- {
- return Initialize4ComponentData<GLuint, 0x00000000, 0x00000000, 0x00000000,
- 0x00000001>;
- }
- default:
- break;
- }
- }
- case GL_RGB32I:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R32G32B32A32_SINT:
- {
- return Initialize4ComponentData<GLint, 0x00000000, 0x00000000, 0x00000000,
- 0x00000001>;
- }
- default:
- break;
- }
- }
- default:
- {
- return nullptr;
- }
- }
-}
-
-} // namespace d3d11
-
-} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h
deleted file mode 100644
index 2d538e1d82..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// Copyright 2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// internal_format_initializer_table:
-// Contains table to go from internal format and dxgi format to initializer function
-// for TextureFormat
-//
-
-#ifndef LIBANGLE_RENDERER_D3D_D3D11_INTERNALFORMATINITIALIZERTABLE_H_
-#define LIBANGLE_RENDERER_D3D_D3D11_INTERNALFORMATINITIALIZERTABLE_H_
-
-#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
-
-#include <map>
-
-namespace rx
-{
-
-namespace d3d11
-{
-
-InitializeTextureDataFunction GetInternalFormatInitializer(GLenum internalFormat,
- DXGI_FORMAT dxgiFormat);
-
-} // namespace d3d11
-
-} // namespace rx
-
-#endif // LIBANGLE_RENDERER_D3D_D3D11_INTERNALFORMATINITIALIZERTABLE_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json
deleted file mode 100644
index c85393e06b..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json
+++ /dev/null
@@ -1,1116 +0,0 @@
-{
- "GL_RG8_SNORM": {
- "GL_BYTE": [
- {
- "loadFunction": "LoadToNative<GLbyte,2>",
- "dxgiFormat": "DXGI_FORMAT_R8G8_SNORM",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_SRGB8": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadToNative3To4<GLubyte,0xFF>",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_RGBA8I": {
- "GL_BYTE": [
- {
- "loadFunction": "LoadToNative<GLbyte,4>",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_R8_SNORM": {
- "GL_BYTE": [
- {
- "loadFunction": "LoadToNative<GLbyte,1>",
- "dxgiFormat": "DXGI_FORMAT_R8_SNORM",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_RGBA8_SNORM": {
- "GL_BYTE": [
- {
- "loadFunction": "LoadToNative<GLbyte,4>",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_SNORM",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_R16I": {
- "GL_SHORT": [
- {
- "loadFunction": "LoadToNative<GLshort,1>",
- "dxgiFormat": "DXGI_FORMAT_R16_SINT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadETC2SRGBA8ToSRGBA8",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadETC2RGB8A1ToRGBA8",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_RGB32UI": {
- "GL_UNSIGNED_INT": [
- {
- "loadFunction": "LoadToNative3To4<GLuint,0x00000001>",
- "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_ALPHA32F_EXT": {
- "GL_FLOAT": [
- {
- "loadFunction": "LoadA32FToRGBA32F",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_R16UI": {
- "GL_UNSIGNED_SHORT": [
- {
- "loadFunction": "LoadToNative<GLushort,1>",
- "dxgiFormat": "DXGI_FORMAT_R16_UINT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_RGB9_E5": {
- "GL_HALF_FLOAT": [
- {
- "loadFunction": "LoadRGB16FToRGB9E5",
- "dxgiFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP",
- "requiresConversion": "true"
- }
- ],
- "GL_UNSIGNED_INT_5_9_9_9_REV": [
- {
- "loadFunction": "LoadToNative<GLuint,1>",
- "dxgiFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP",
- "requiresConversion": "false"
- }
- ],
- "GL_FLOAT": [
- {
- "loadFunction": "LoadRGB32FToRGB9E5",
- "dxgiFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP",
- "requiresConversion": "true"
- }
- ],
- "GL_HALF_FLOAT_OES": [
- {
- "loadFunction": "LoadRGB16FToRGB9E5",
- "dxgiFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_COMPRESSED_R11_EAC": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadEACR11ToR8",
- "dxgiFormat": "DXGI_FORMAT_R8_UNORM",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_RGBA32UI": {
- "GL_UNSIGNED_INT": [
- {
- "loadFunction": "LoadToNative<GLuint,4>",
- "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_RG8UI": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadToNative<GLubyte,2>",
- "dxgiFormat": "DXGI_FORMAT_R8G8_UINT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_LUMINANCE32F_EXT": {
- "GL_FLOAT": [
- {
- "loadFunction": "LoadL32FToRGBA32F",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadETC2SRGB8A1ToRGBA8",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_R16F": {
- "GL_HALF_FLOAT": [
- {
- "loadFunction": "LoadToNative<GLhalf,1>",
- "dxgiFormat": "DXGI_FORMAT_R16_FLOAT",
- "requiresConversion": "false"
- }
- ],
- "GL_FLOAT": [
- {
- "loadFunction": "Load32FTo16F<1>",
- "dxgiFormat": "DXGI_FORMAT_R16_FLOAT",
- "requiresConversion": "true"
- }
- ],
- "GL_HALF_FLOAT_OES": [
- {
- "loadFunction": "LoadToNative<GLhalf,1>",
- "dxgiFormat": "DXGI_FORMAT_R16_FLOAT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_RGBA8UI": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadToNative<GLubyte,4>",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_BGRA4_ANGLEX": {
- "GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT": [
- {
- "loadFunction": "LoadRGBA4ToRGBA8",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ],
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadToNative<GLubyte,4>",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_RGBA16F": {
- "GL_HALF_FLOAT": [
- {
- "loadFunction": "LoadToNative<GLhalf,4>",
- "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "requiresConversion": "false"
- }
- ],
- "GL_FLOAT": [
- {
- "loadFunction": "Load32FTo16F<4>",
- "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "requiresConversion": "true"
- }
- ],
- "GL_HALF_FLOAT_OES": [
- {
- "loadFunction": "LoadToNative<GLhalf,4>",
- "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_LUMINANCE8_EXT": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadL8ToRGBA8",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadCompressedToNative<4,4,16>",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_RGB": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "UnreachableLoadFunction",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ],
- "GL_UNSIGNED_SHORT_5_6_5": [
- {
- "loadFunction": "UnreachableLoadFunction",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_RGB5_A1": {
- "GL_UNSIGNED_INT_2_10_10_10_REV": [
- {
- "loadFunction": "LoadRGB10A2ToRGBA8",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "requiresConversion": "true"
- }
- ],
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadToNative<GLubyte,4>",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "requiresConversion": "false"
- }
- ],
- "GL_UNSIGNED_SHORT_5_5_5_1": [
- {
- "loadFunction": "LoadRGB5A1ToRGBA8",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "requiresConversion": "true"
- },
- {
- "loadFunction": "LoadRGB5A1ToA1RGB5",
- "dxgiFormat": "DXGI_FORMAT_B5G5R5A1_UNORM",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_RGB16UI": {
- "GL_UNSIGNED_SHORT": [
- {
- "loadFunction": "LoadToNative3To4<GLushort,0x0001>",
- "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_BGRA_EXT": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "UnreachableLoadFunction",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_COMPRESSED_RGB8_ETC2": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadETC2RGB8ToRGBA8",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_RGBA32F": {
- "GL_FLOAT": [
- {
- "loadFunction": "LoadToNative<GLfloat,4>",
- "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_RGBA32I": {
- "GL_INT": [
- {
- "loadFunction": "LoadToNative<GLint,4>",
- "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_LUMINANCE8_ALPHA8_EXT": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadLA8ToRGBA8",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_RG8": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadToNative<GLubyte,2>",
- "dxgiFormat": "DXGI_FORMAT_R8G8_UNORM",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_RGB10_A2": {
- "GL_UNSIGNED_INT_2_10_10_10_REV": [
- {
- "loadFunction": "LoadToNative<GLuint,1>",
- "dxgiFormat": "DXGI_FORMAT_R10G10B10A2_UNORM",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_COMPRESSED_SIGNED_RG11_EAC": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadEACRG11SToRG8",
- "dxgiFormat": "DXGI_FORMAT_R8G8_SNORM",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_DEPTH_COMPONENT16": {
- "GL_UNSIGNED_INT": [
- {
- "loadFunction": "LoadR32ToR16",
- "dxgiFormat": "DXGI_FORMAT_R16_TYPELESS",
- "requiresConversion": "true"
- }
- ],
- "GL_UNSIGNED_SHORT": [
- {
- "loadFunction": "LoadToNative<GLushort,1>",
- "dxgiFormat": "DXGI_FORMAT_R16_TYPELESS",
- "requiresConversion": "false"
- },
- {
- "loadFunction": "LoadToNative<GLushort,1>",
- "dxgiFormat": "DXGI_FORMAT_D16_UNORM",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_RGB32I": {
- "GL_INT": [
- {
- "loadFunction": "LoadToNative3To4<GLint,0x00000001>",
- "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_R8": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadToNative<GLubyte,1>",
- "dxgiFormat": "DXGI_FORMAT_R8_UNORM",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_RGB32F": {
- "GL_FLOAT": [
- {
- "loadFunction": "LoadToNative3To4<GLfloat,gl::Float32One>",
- "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_R11F_G11F_B10F": {
- "GL_UNSIGNED_INT_10F_11F_11F_REV": [
- {
- "loadFunction": "LoadToNative<GLuint,1>",
- "dxgiFormat": "DXGI_FORMAT_R11G11B10_FLOAT",
- "requiresConversion": "false"
- }
- ],
- "GL_HALF_FLOAT": [
- {
- "loadFunction": "LoadRGB16FToRG11B10F",
- "dxgiFormat": "DXGI_FORMAT_R11G11B10_FLOAT",
- "requiresConversion": "true"
- }
- ],
- "GL_FLOAT": [
- {
- "loadFunction": "LoadRGB32FToRG11B10F",
- "dxgiFormat": "DXGI_FORMAT_R11G11B10_FLOAT",
- "requiresConversion": "true"
- }
- ],
- "GL_HALF_FLOAT_OES": [
- {
- "loadFunction": "LoadRGB16FToRG11B10F",
- "dxgiFormat": "DXGI_FORMAT_R11G11B10_FLOAT",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_RGB8": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadToNative3To4<GLubyte,0xFF>",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_LUMINANCE_ALPHA": {
- "GL_HALF_FLOAT": [
- {
- "loadFunction": "LoadLA16FToRGBA16F",
- "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "requiresConversion": "true"
- }
- ],
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "UnreachableLoadFunction",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ],
- "GL_FLOAT": [
- {
- "loadFunction": "LoadLA32FToRGBA32F",
- "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
- "requiresConversion": "true"
- }
- ],
- "GL_HALF_FLOAT_OES": [
- {
- "loadFunction": "LoadLA16FToRGBA16F",
- "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_RGBA16I": {
- "GL_SHORT": [
- {
- "loadFunction": "LoadToNative<GLshort,4>",
- "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_R8I": {
- "GL_BYTE": [
- {
- "loadFunction": "LoadToNative<GLbyte,1>",
- "dxgiFormat": "DXGI_FORMAT_R8_SINT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_RGB8_SNORM": {
- "GL_BYTE": [
- {
- "loadFunction": "LoadToNative3To4<GLbyte,0x7F>",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_SNORM",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_RG32F": {
- "GL_FLOAT": [
- {
- "loadFunction": "LoadToNative<GLfloat,2>",
- "dxgiFormat": "DXGI_FORMAT_R32G32_FLOAT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_DEPTH_COMPONENT32F": {
- "GL_FLOAT": [
- {
- "loadFunction": "LoadToNative<GLfloat,1>",
- "dxgiFormat": "DXGI_FORMAT_R32_TYPELESS",
- "requiresConversion": "false"
- },
- {
- "loadFunction": "UnimplementedLoadFunction",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_RG32I": {
- "GL_INT": [
- {
- "loadFunction": "LoadToNative<GLint,2>",
- "dxgiFormat": "DXGI_FORMAT_R32G32_SINT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_ALPHA8_EXT": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadToNative<GLubyte,1>",
- "dxgiFormat": "DXGI_FORMAT_A8_UNORM",
- "requiresConversion": "false"
- },
- {
- "loadFunction": "LoadA8ToRGBA8",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_RG32UI": {
- "GL_UNSIGNED_INT": [
- {
- "loadFunction": "LoadToNative<GLuint,2>",
- "dxgiFormat": "DXGI_FORMAT_R32G32_UINT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_RGBA16UI": {
- "GL_UNSIGNED_SHORT": [
- {
- "loadFunction": "LoadToNative<GLushort,4>",
- "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_COMPRESSED_RGBA8_ETC2_EAC": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadETC2RGBA8ToRGBA8",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_RGB8I": {
- "GL_BYTE": [
- {
- "loadFunction": "LoadToNative3To4<GLbyte,0x01>",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_COMPRESSED_SRGB8_ETC2": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadETC2SRGB8ToRGBA8",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_DEPTH32F_STENCIL8": {
- "GL_FLOAT_32_UNSIGNED_INT_24_8_REV": [
- {
- "loadFunction": "LoadToNative<GLuint,2>",
- "dxgiFormat": "DXGI_FORMAT_R32G8X24_TYPELESS",
- "requiresConversion": "false"
- },
- {
- "loadFunction": "UnimplementedLoadFunction",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_RG8I": {
- "GL_BYTE": [
- {
- "loadFunction": "LoadToNative<GLbyte,2>",
- "dxgiFormat": "DXGI_FORMAT_R8G8_SINT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_R32UI": {
- "GL_UNSIGNED_INT": [
- {
- "loadFunction": "LoadToNative<GLuint,1>",
- "dxgiFormat": "DXGI_FORMAT_R32_UINT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_BGR5_A1_ANGLEX": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadToNative<GLubyte,4>",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "false"
- }
- ],
- "GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT": [
- {
- "loadFunction": "LoadRGB5A1ToRGBA8",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_COMPRESSED_RG11_EAC": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadEACRG11ToRG8",
- "dxgiFormat": "DXGI_FORMAT_R8G8_UNORM",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_SRGB8_ALPHA8": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadToNative<GLubyte,4>",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_LUMINANCE_ALPHA16F_EXT": {
- "GL_HALF_FLOAT": [
- {
- "loadFunction": "LoadLA16FToRGBA16F",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ],
- "GL_HALF_FLOAT_OES": [
- {
- "loadFunction": "LoadLA16FToRGBA16F",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_RGBA": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "UnreachableLoadFunction",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ],
- "GL_UNSIGNED_SHORT_4_4_4_4": [
- {
- "loadFunction": "UnreachableLoadFunction",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ],
- "GL_UNSIGNED_SHORT_5_5_5_1": [
- {
- "loadFunction": "UnreachableLoadFunction",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_DEPTH24_STENCIL8": {
- "GL_UNSIGNED_INT_24_8": [
- {
- "loadFunction": "LoadR32ToR24G8",
- "dxgiFormat": "DXGI_FORMAT_R24G8_TYPELESS",
- "requiresConversion": "true"
- },
- {
- "loadFunction": "LoadR32ToR24G8",
- "dxgiFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_RGB16I": {
- "GL_SHORT": [
- {
- "loadFunction": "LoadToNative3To4<GLshort,0x0001>",
- "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_R8UI": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadToNative<GLubyte,1>",
- "dxgiFormat": "DXGI_FORMAT_R8_UINT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_ALPHA": {
- "GL_HALF_FLOAT": [
- {
- "loadFunction": "LoadA16FToRGBA16F",
- "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "requiresConversion": "true"
- }
- ],
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "UnreachableLoadFunction",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ],
- "GL_FLOAT": [
- {
- "loadFunction": "LoadA32FToRGBA32F",
- "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
- "requiresConversion": "true"
- }
- ],
- "GL_HALF_FLOAT_OES": [
- {
- "loadFunction": "LoadA16FToRGBA16F",
- "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_RGB16F": {
- "GL_HALF_FLOAT": [
- {
- "loadFunction": "LoadToNative3To4<GLhalf,gl::Float16One>",
- "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "requiresConversion": "true"
- }
- ],
- "GL_FLOAT": [
- {
- "loadFunction": "LoadRGB32FToRGBA16F",
- "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "requiresConversion": "true"
- }
- ],
- "GL_HALF_FLOAT_OES": [
- {
- "loadFunction": "LoadToNative3To4<GLhalf,gl::Float16One>",
- "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_COMPRESSED_SIGNED_R11_EAC": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadEACR11SToR8",
- "dxgiFormat": "DXGI_FORMAT_R8_SNORM",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_COMPRESSED_RGB_S3TC_DXT1_EXT": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadCompressedToNative<4,4,8>",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadCompressedToNative<4,4,8>",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_STENCIL_INDEX8": {
- "DXGI_FORMAT_R24G8_TYPELESS": [
- {
- "loadFunction": "UnimplementedLoadFunction",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ],
- "DXGI_FORMAT_D24_UNORM_S8_UINT": [
- {
- "loadFunction": "UnimplementedLoadFunction",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_LUMINANCE_ALPHA32F_EXT": {
- "GL_FLOAT": [
- {
- "loadFunction": "LoadLA32FToRGBA32F",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_RGB8UI": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadToNative3To4<GLubyte,0x01>",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_DEPTH_COMPONENT24": {
- "GL_UNSIGNED_INT": [
- {
- "loadFunction": "LoadR32ToR24G8",
- "dxgiFormat": "DXGI_FORMAT_R24G8_TYPELESS",
- "requiresConversion": "true"
- },
- {
- "loadFunction": "LoadR32ToR24G8",
- "dxgiFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_R32I": {
- "GL_INT": [
- {
- "loadFunction": "LoadToNative<GLint,1>",
- "dxgiFormat": "DXGI_FORMAT_R32_SINT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_DEPTH_COMPONENT32_OES": {
- "GL_UNSIGNED_INT": [
- {
- "loadFunction": "LoadR32ToR24G8",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_R32F": {
- "GL_FLOAT": [
- {
- "loadFunction": "LoadToNative<GLfloat,1>",
- "dxgiFormat": "DXGI_FORMAT_R32_FLOAT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_RG16F": {
- "GL_HALF_FLOAT": [
- {
- "loadFunction": "LoadToNative<GLhalf,2>",
- "dxgiFormat": "DXGI_FORMAT_R16G16_FLOAT",
- "requiresConversion": "false"
- }
- ],
- "GL_FLOAT": [
- {
- "loadFunction": "Load32FTo16F<2>",
- "dxgiFormat": "DXGI_FORMAT_R16G16_FLOAT",
- "requiresConversion": "true"
- }
- ],
- "GL_HALF_FLOAT_OES": [
- {
- "loadFunction": "LoadToNative<GLhalf,2>",
- "dxgiFormat": "DXGI_FORMAT_R16G16_FLOAT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_RGB565": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadToNative3To4<GLubyte,0xFF>",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "requiresConversion": "true"
- }
- ],
- "GL_UNSIGNED_SHORT_5_6_5": [
- {
- "loadFunction": "LoadR5G6B5ToRGBA8",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "requiresConversion": "true"
- },
- {
- "loadFunction": "LoadToNative<GLushort,1>",
- "dxgiFormat": "DXGI_FORMAT_B5G6R5_UNORM",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_LUMINANCE16F_EXT": {
- "GL_HALF_FLOAT": [
- {
- "loadFunction": "LoadL16FToRGBA16F",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ],
- "GL_HALF_FLOAT_OES": [
- {
- "loadFunction": "LoadL16FToRGBA16F",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_RG16UI": {
- "GL_UNSIGNED_SHORT": [
- {
- "loadFunction": "LoadToNative<GLushort,2>",
- "dxgiFormat": "DXGI_FORMAT_R16G16_UINT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadCompressedToNative<4,4,16>",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_RG16I": {
- "GL_SHORT": [
- {
- "loadFunction": "LoadToNative<GLshort,2>",
- "dxgiFormat": "DXGI_FORMAT_R16G16_SINT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_BGRA8_EXT": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadToNative<GLubyte,4>",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_ALPHA16F_EXT": {
- "GL_HALF_FLOAT": [
- {
- "loadFunction": "LoadA16FToRGBA16F",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ],
- "GL_HALF_FLOAT_OES": [
- {
- "loadFunction": "LoadA16FToRGBA16F",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_RGBA4": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadToNative<GLubyte,4>",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "requiresConversion": "false"
- }
- ],
- "GL_UNSIGNED_SHORT_4_4_4_4": [
- {
- "loadFunction": "LoadRGBA4ToRGBA8",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "requiresConversion": "true"
- },
- {
- "loadFunction": "LoadRGBA4ToARGB4",
- "dxgiFormat": "DXGI_FORMAT_B4G4R4A4_UNORM",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_RGBA8": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadToNative<GLubyte,4>",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_LUMINANCE": {
- "GL_HALF_FLOAT": [
- {
- "loadFunction": "LoadL16FToRGBA16F",
- "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "requiresConversion": "true"
- }
- ],
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "UnreachableLoadFunction",
- "dxgiFormat": "DXGI_FORMAT_UNKNOWN",
- "requiresConversion": "true"
- }
- ],
- "GL_FLOAT": [
- {
- "loadFunction": "LoadL32FToRGBA32F",
- "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
- "requiresConversion": "true"
- }
- ],
- "GL_HALF_FLOAT_OES": [
- {
- "loadFunction": "LoadL16FToRGBA16F",
- "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_RGB10_A2UI": {
- "GL_UNSIGNED_INT_2_10_10_10_REV": [
- {
- "loadFunction": "LoadToNative<GLuint,1>",
- "dxgiFormat": "DXGI_FORMAT_R10G10B10A2_UINT",
- "requiresConversion": "false"
- }
- ]
- },
- "GL_ETC1_RGB8_OES": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadETC1RGB8ToRGBA8",
- "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "requiresConversion": "true"
- }
- ]
- },
- "GL_ETC1_RGB8_LOSSY_DECODE_ANGLE": {
- "GL_UNSIGNED_BYTE": [
- {
- "loadFunction": "LoadETC1RGB8ToBC1",
- "dxgiFormat": "DXGI_FORMAT_BC1_UNORM",
- "requiresConversion": "true"
- }
- ]
- }
-} \ No newline at end of file
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table.h
deleted file mode 100644
index b17062f68d..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// Copyright 2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// load_functions_table:
-// Contains load functions table depending on internal format and dxgi format
-//
-
-#ifndef LIBANGLE_RENDERER_D3D_D3D11_LOADFUNCTIONSTABLE_H_
-#define LIBANGLE_RENDERER_D3D_D3D11_LOADFUNCTIONSTABLE_H_
-
-#include <map>
-
-#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
-#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
-
-namespace rx
-{
-
-namespace d3d11
-{
-
-const std::map<GLenum, LoadImageFunctionInfo> &GetLoadFunctionsMap(GLenum internalFormat,
- DXGI_FORMAT dxgiFormat);
-
-} // namespace d3d11
-
-} // namespace rx
-
-#endif // LIBANGLE_RENDERER_D3D_D3D11_LOADFUNCTIONSTABLE_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp
deleted file mode 100644
index acb48b9573..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp
+++ /dev/null
@@ -1,2098 +0,0 @@
-// GENERATED FILE - DO NOT EDIT.
-// Generated by gen_load_functions_table.py using data from load_functions_data.json
-//
-// Copyright 2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// load_functions_table:
-// Contains the GetLoadFunctionsMap for texture_format_util.h
-//
-
-#include "libANGLE/renderer/d3d/d3d11/load_functions_table.h"
-#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
-#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
-#include "libANGLE/renderer/d3d/loadimage.h"
-#include "libANGLE/renderer/d3d/loadimage_etc.h"
-
-namespace rx
-{
-
-namespace d3d11
-{
-
-namespace
-{
-
-// ES3 image loading functions vary based on:
-// - the GL internal format (supplied to glTex*Image*D)
-// - the GL data type given (supplied to glTex*Image*D)
-// - the target DXGI_FORMAT that the image will be loaded into (which is chosen based on the D3D
-// device's capabilities)
-// This map type determines which loading function to use, based on these three parameters.
-// Source formats and types are taken from Tables 3.2 and 3.3 of the ES 3 spec.
-void UnimplementedLoadFunction(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch)
-{
- UNIMPLEMENTED();
-}
-
-void UnreachableLoadFunction(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch)
-{
- UNREACHABLE();
-}
-
-} // namespace
-
-// TODO we can replace these maps with more generated code
-const std::map<GLenum, LoadImageFunctionInfo> &GetLoadFunctionsMap(GLenum internalFormat,
- DXGI_FORMAT dxgiFormat)
-{
- // clang-format off
- switch (internalFormat)
- {
- case GL_ALPHA:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R16G16B16A16_FLOAT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadA16FToRGBA16F, true);
- loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadA16FToRGBA16F, true);
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- case DXGI_FORMAT_R32G32B32A32_FLOAT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadA32FToRGBA32F, true);
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
- case GL_ALPHA16F_EXT:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadA16FToRGBA16F, true);
- loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadA16FToRGBA16F, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadA16FToRGBA16F, true);
- loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadA16FToRGBA16F, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
- case GL_ALPHA32F_EXT:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadA32FToRGBA32F, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadA32FToRGBA32F, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
- case GL_ALPHA8_EXT:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_A8_UNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,1>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- case DXGI_FORMAT_R8G8B8A8_UNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadA8ToRGBA8, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_BGR5_A1_ANGLEX:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT] = LoadImageFunctionInfo(LoadRGB5A1ToRGBA8, true);
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,4>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,4>, true);
- loadMap[GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT] = LoadImageFunctionInfo(LoadRGB5A1ToRGBA8, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
- case GL_BGRA4_ANGLEX:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT] = LoadImageFunctionInfo(LoadRGBA4ToRGBA8, true);
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,4>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,4>, true);
- loadMap[GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT] = LoadImageFunctionInfo(LoadRGBA4ToRGBA8, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
- case GL_BGRA8_EXT:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,4>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,4>, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
- case GL_BGRA_EXT:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
- case GL_COMPRESSED_R11_EAC:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8_UNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadEACR11ToR8, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_COMPRESSED_RG11_EAC:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8_UNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadEACRG11ToRG8, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_COMPRESSED_RGB8_ETC2:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8B8A8_UNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadETC2RGB8ToRGBA8, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8B8A8_UNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadETC2RGB8A1ToRGBA8, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_COMPRESSED_RGBA8_ETC2_EAC:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8B8A8_UNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadETC2RGBA8ToRGBA8, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadCompressedToNative<4,4,8>, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadCompressedToNative<4,4,8>, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadCompressedToNative<4,4,16>, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadCompressedToNative<4,4,16>, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadCompressedToNative<4,4,16>, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadCompressedToNative<4,4,16>, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadCompressedToNative<4,4,8>, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadCompressedToNative<4,4,8>, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
- case GL_COMPRESSED_SIGNED_R11_EAC:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8_SNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadEACR11SToR8, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_COMPRESSED_SIGNED_RG11_EAC:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8_SNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadEACRG11SToRG8, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadETC2SRGBA8ToSRGBA8, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_COMPRESSED_SRGB8_ETC2:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadETC2SRGB8ToRGBA8, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadETC2SRGB8A1ToRGBA8, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_DEPTH24_STENCIL8:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_D24_UNORM_S8_UINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_INT_24_8] = LoadImageFunctionInfo(LoadR32ToR24G8, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- case DXGI_FORMAT_R24G8_TYPELESS:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_INT_24_8] = LoadImageFunctionInfo(LoadR32ToR24G8, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_DEPTH32F_STENCIL8:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R32G8X24_TYPELESS:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_FLOAT_32_UNSIGNED_INT_24_8_REV] = LoadImageFunctionInfo(LoadToNative<GLuint,2>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_FLOAT_32_UNSIGNED_INT_24_8_REV] = LoadImageFunctionInfo(UnimplementedLoadFunction, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_FLOAT_32_UNSIGNED_INT_24_8_REV] = LoadImageFunctionInfo(UnimplementedLoadFunction, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
- case GL_DEPTH_COMPONENT16:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_D16_UNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_SHORT] = LoadImageFunctionInfo(LoadToNative<GLushort,1>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- case DXGI_FORMAT_R16_TYPELESS:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadR32ToR16, true);
- loadMap[GL_UNSIGNED_SHORT] = LoadImageFunctionInfo(LoadToNative<GLushort,1>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_DEPTH_COMPONENT24:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_D24_UNORM_S8_UINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadR32ToR24G8, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- case DXGI_FORMAT_R24G8_TYPELESS:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadR32ToR24G8, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_DEPTH_COMPONENT32F:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R32_TYPELESS:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadToNative<GLfloat,1>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_FLOAT] = LoadImageFunctionInfo(UnimplementedLoadFunction, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_FLOAT] = LoadImageFunctionInfo(UnimplementedLoadFunction, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
- case GL_DEPTH_COMPONENT32_OES:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadR32ToR24G8, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadR32ToR24G8, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
- case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_BC1_UNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadETC1RGB8ToBC1, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_ETC1_RGB8_OES:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8B8A8_UNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadETC1RGB8ToRGBA8, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_LUMINANCE:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R16G16B16A16_FLOAT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadL16FToRGBA16F, true);
- loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadL16FToRGBA16F, true);
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- case DXGI_FORMAT_R32G32B32A32_FLOAT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadL32FToRGBA32F, true);
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
- case GL_LUMINANCE16F_EXT:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadL16FToRGBA16F, true);
- loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadL16FToRGBA16F, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadL16FToRGBA16F, true);
- loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadL16FToRGBA16F, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
- case GL_LUMINANCE32F_EXT:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadL32FToRGBA32F, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadL32FToRGBA32F, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
- case GL_LUMINANCE8_ALPHA8_EXT:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadLA8ToRGBA8, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadLA8ToRGBA8, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
- case GL_LUMINANCE8_EXT:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadL8ToRGBA8, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadL8ToRGBA8, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
- case GL_LUMINANCE_ALPHA:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R16G16B16A16_FLOAT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadLA16FToRGBA16F, true);
- loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadLA16FToRGBA16F, true);
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- case DXGI_FORMAT_R32G32B32A32_FLOAT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadLA32FToRGBA32F, true);
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
- case GL_LUMINANCE_ALPHA16F_EXT:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadLA16FToRGBA16F, true);
- loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadLA16FToRGBA16F, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadLA16FToRGBA16F, true);
- loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadLA16FToRGBA16F, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
- case GL_LUMINANCE_ALPHA32F_EXT:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadLA32FToRGBA32F, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadLA32FToRGBA32F, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
- case GL_R11F_G11F_B10F:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R11G11B10_FLOAT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadRGB16FToRG11B10F, true);
- loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadRGB16FToRG11B10F, true);
- loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadRGB32FToRG11B10F, true);
- loadMap[GL_UNSIGNED_INT_10F_11F_11F_REV] = LoadImageFunctionInfo(LoadToNative<GLuint,1>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_R16F:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R16_FLOAT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_FLOAT] = LoadImageFunctionInfo(Load32FTo16F<1>, true);
- loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadToNative<GLhalf,1>, false);
- loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadToNative<GLhalf,1>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_R16I:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R16_SINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_SHORT] = LoadImageFunctionInfo(LoadToNative<GLshort,1>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_R16UI:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R16_UINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_SHORT] = LoadImageFunctionInfo(LoadToNative<GLushort,1>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_R32F:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R32_FLOAT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadToNative<GLfloat,1>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_R32I:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R32_SINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_INT] = LoadImageFunctionInfo(LoadToNative<GLint,1>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_R32UI:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R32_UINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadToNative<GLuint,1>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_R8:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8_UNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,1>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_R8I:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8_SINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_BYTE] = LoadImageFunctionInfo(LoadToNative<GLbyte,1>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_R8UI:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8_UINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,1>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_R8_SNORM:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8_SNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_BYTE] = LoadImageFunctionInfo(LoadToNative<GLbyte,1>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RG16F:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R16G16_FLOAT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_FLOAT] = LoadImageFunctionInfo(Load32FTo16F<2>, true);
- loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadToNative<GLhalf,2>, false);
- loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadToNative<GLhalf,2>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RG16I:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R16G16_SINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_SHORT] = LoadImageFunctionInfo(LoadToNative<GLshort,2>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RG16UI:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R16G16_UINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_SHORT] = LoadImageFunctionInfo(LoadToNative<GLushort,2>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RG32F:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R32G32_FLOAT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadToNative<GLfloat,2>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RG32I:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R32G32_SINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_INT] = LoadImageFunctionInfo(LoadToNative<GLint,2>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RG32UI:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R32G32_UINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadToNative<GLuint,2>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RG8:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8_UNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,2>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RG8I:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8_SINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_BYTE] = LoadImageFunctionInfo(LoadToNative<GLbyte,2>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RG8UI:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8_UINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,2>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RG8_SNORM:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8_SNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_BYTE] = LoadImageFunctionInfo(LoadToNative<GLbyte,2>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGB:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true);
- loadMap[GL_UNSIGNED_SHORT_5_6_5] = LoadImageFunctionInfo(UnreachableLoadFunction, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true);
- loadMap[GL_UNSIGNED_SHORT_5_6_5] = LoadImageFunctionInfo(UnreachableLoadFunction, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
- case GL_RGB10_A2:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R10G10B10A2_UNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_INT_2_10_10_10_REV] = LoadImageFunctionInfo(LoadToNative<GLuint,1>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGB10_A2UI:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R10G10B10A2_UINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_INT_2_10_10_10_REV] = LoadImageFunctionInfo(LoadToNative<GLuint,1>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGB16F:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R16G16B16A16_FLOAT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadRGB32FToRGBA16F, true);
- loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadToNative3To4<GLhalf,gl::Float16One>, true);
- loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadToNative3To4<GLhalf,gl::Float16One>, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGB16I:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R16G16B16A16_SINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_SHORT] = LoadImageFunctionInfo(LoadToNative3To4<GLshort,0x0001>, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGB16UI:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R16G16B16A16_UINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_SHORT] = LoadImageFunctionInfo(LoadToNative3To4<GLushort,0x0001>, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGB32F:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R32G32B32A32_FLOAT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadToNative3To4<GLfloat,gl::Float32One>, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGB32I:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R32G32B32A32_SINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_INT] = LoadImageFunctionInfo(LoadToNative3To4<GLint,0x00000001>, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGB32UI:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R32G32B32A32_UINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadToNative3To4<GLuint,0x00000001>, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGB565:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_B5G6R5_UNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_SHORT_5_6_5] = LoadImageFunctionInfo(LoadToNative<GLushort,1>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- case DXGI_FORMAT_R8G8B8A8_UNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_SHORT_5_6_5] = LoadImageFunctionInfo(LoadR5G6B5ToRGBA8, true);
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative3To4<GLubyte,0xFF>, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGB5_A1:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_B5G5R5A1_UNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_SHORT_5_5_5_1] = LoadImageFunctionInfo(LoadRGB5A1ToA1RGB5, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- case DXGI_FORMAT_R8G8B8A8_UNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_INT_2_10_10_10_REV] = LoadImageFunctionInfo(LoadRGB10A2ToRGBA8, true);
- loadMap[GL_UNSIGNED_SHORT_5_5_5_1] = LoadImageFunctionInfo(LoadRGB5A1ToRGBA8, true);
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,4>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGB8:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8B8A8_UNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative3To4<GLubyte,0xFF>, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGB8I:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8B8A8_SINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_BYTE] = LoadImageFunctionInfo(LoadToNative3To4<GLbyte,0x01>, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGB8UI:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8B8A8_UINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative3To4<GLubyte,0x01>, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGB8_SNORM:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8B8A8_SNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_BYTE] = LoadImageFunctionInfo(LoadToNative3To4<GLbyte,0x7F>, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGB9_E5:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadRGB16FToRGB9E5, true);
- loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadRGB16FToRGB9E5, true);
- loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadRGB32FToRGB9E5, true);
- loadMap[GL_UNSIGNED_INT_5_9_9_9_REV] = LoadImageFunctionInfo(LoadToNative<GLuint,1>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGBA:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true);
- loadMap[GL_UNSIGNED_SHORT_4_4_4_4] = LoadImageFunctionInfo(UnreachableLoadFunction, true);
- loadMap[GL_UNSIGNED_SHORT_5_5_5_1] = LoadImageFunctionInfo(UnreachableLoadFunction, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true);
- loadMap[GL_UNSIGNED_SHORT_4_4_4_4] = LoadImageFunctionInfo(UnreachableLoadFunction, true);
- loadMap[GL_UNSIGNED_SHORT_5_5_5_1] = LoadImageFunctionInfo(UnreachableLoadFunction, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
- case GL_RGBA16F:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R16G16B16A16_FLOAT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_FLOAT] = LoadImageFunctionInfo(Load32FTo16F<4>, true);
- loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadToNative<GLhalf,4>, false);
- loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadToNative<GLhalf,4>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGBA16I:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R16G16B16A16_SINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_SHORT] = LoadImageFunctionInfo(LoadToNative<GLshort,4>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGBA16UI:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R16G16B16A16_UINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_SHORT] = LoadImageFunctionInfo(LoadToNative<GLushort,4>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGBA32F:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R32G32B32A32_FLOAT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadToNative<GLfloat,4>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGBA32I:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R32G32B32A32_SINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_INT] = LoadImageFunctionInfo(LoadToNative<GLint,4>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGBA32UI:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R32G32B32A32_UINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadToNative<GLuint,4>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGBA4:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_B4G4R4A4_UNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_SHORT_4_4_4_4] = LoadImageFunctionInfo(LoadRGBA4ToARGB4, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- case DXGI_FORMAT_R8G8B8A8_UNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_SHORT_4_4_4_4] = LoadImageFunctionInfo(LoadRGBA4ToRGBA8, true);
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,4>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGBA8:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8B8A8_UNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,4>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGBA8I:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8B8A8_SINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_BYTE] = LoadImageFunctionInfo(LoadToNative<GLbyte,4>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGBA8UI:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8B8A8_UINT:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,4>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_RGBA8_SNORM:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8B8A8_SNORM:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_BYTE] = LoadImageFunctionInfo(LoadToNative<GLbyte,4>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_SRGB8:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative3To4<GLubyte,0xFF>, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_SRGB8_ALPHA8:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative<GLubyte,4>, false);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- break;
- }
- }
- case GL_STENCIL_INDEX8:
- {
- switch (dxgiFormat)
- {
- case DXGI_FORMAT_UNKNOWN:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[DXGI_FORMAT_D24_UNORM_S8_UINT] = LoadImageFunctionInfo(UnimplementedLoadFunction, true);
- loadMap[DXGI_FORMAT_R24G8_TYPELESS] = LoadImageFunctionInfo(UnimplementedLoadFunction, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- default:
- {
- static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = []() {
- std::map<GLenum, LoadImageFunctionInfo> loadMap;
- loadMap[DXGI_FORMAT_D24_UNORM_S8_UINT] = LoadImageFunctionInfo(UnimplementedLoadFunction, true);
- loadMap[DXGI_FORMAT_R24G8_TYPELESS] = LoadImageFunctionInfo(UnimplementedLoadFunction, true);
- return loadMap;
- }();
-
- return loadFunctionsMap;
- }
- }
- }
-
- default:
- {
- static std::map<GLenum, LoadImageFunctionInfo> emptyLoadFunctionsMap;
- return emptyLoadFunctionsMap;
- }
- }
- // clang-format on
-
-} // GetLoadFunctionsMap
-
-} // namespace d3d11
-
-} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
index a1175db9af..d059b36120 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
@@ -12,319 +12,52 @@
#include <algorithm>
#include "common/debug.h"
-#include "libANGLE/formatutils.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Context.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/Program.h"
+#include "libANGLE/State.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/IndexBuffer.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h"
#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
-#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
-#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
-#include "libANGLE/renderer/d3d/FramebufferD3D.h"
-#include "libANGLE/renderer/d3d/WorkaroundsD3D.h"
-
-#ifndef D3D_FL9_1_DEFAULT_MAX_ANISOTROPY
-# define D3D_FL9_1_DEFAULT_MAX_ANISOTROPY 2
-#endif
-#ifndef D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT
-# define D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT 1
-#endif
-#ifndef D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT
-# define D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT 4
-#endif
-#ifndef D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT
-# define D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT 65535
-#endif
-#ifndef D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT
-# define D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT 1048575
-#endif
-#ifndef D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION
-# define D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION 512
-#endif
-#ifndef D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION
-# define D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION 4096
-#endif
-#ifndef D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION
-# define D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION 2048
-#endif
-#ifndef D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION
-# define D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 256
-#endif
-#ifndef D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION
-# define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096
-#endif
-#ifndef D3D11_REQ_TEXTURECUBE_DIMENSION
-# define D3D11_REQ_TEXTURECUBE_DIMENSION 16384
-#endif
-#ifndef D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION
-# define D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION 2048
-#endif
-#ifndef D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION
-# define D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 2048
-#endif
-#ifndef D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP
-# define D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP 32
-#endif
-#ifndef D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP
-# define D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP 32
-#endif
-#ifndef D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT
-# define D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT 32
-#endif
-#ifndef D3D11_STANDARD_VERTEX_ELEMENT_COUNT
-# define D3D11_STANDARD_VERTEX_ELEMENT_COUNT 32
-#endif
-#ifndef D3D10_1_SO_BUFFER_SLOT_COUNT
-# define D3D10_1_SO_BUFFER_SLOT_COUNT 4
-#endif
-#ifndef D3D11_SO_BUFFER_SLOT_COUNT
-# define D3D11_SO_BUFFER_SLOT_COUNT 4
-#endif
-#ifndef D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT
-# define D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT 14
-#endif
-#ifndef D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT
-# define D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT 16
-#endif
-#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE
-# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE -8
-#endif
-#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE
-# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE 7
-#endif
-#ifndef D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT
-# define D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT 4096
-#endif
-#ifndef D3D11_PS_INPUT_REGISTER_COUNT
-# define D3D11_PS_INPUT_REGISTER_COUNT 32
-#endif
-#ifndef D3D10_1_VS_OUTPUT_REGISTER_COUNT
-# define D3D10_1_VS_OUTPUT_REGISTER_COUNT 32
-#endif
-#if defined(ANGLE_MINGW32_COMPAT)
-static const IID WKPDID_D3DDebugObjectName = { 0x429b8c22, 0x9188, 0x4b0c, 0x87, 0x42, 0xac, 0xb0, 0xbf, 0x85, 0xc2, 0x00 };
-#endif
+#include "libANGLE/renderer/driver_utils.h"
+#include "platform/Platform.h"
+#include "platform/WorkaroundsD3D.h"
namespace rx
{
-namespace gl_d3d11
-{
-
-D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha)
-{
- D3D11_BLEND d3dBlend = D3D11_BLEND_ZERO;
-
- switch (glBlend)
- {
- case GL_ZERO: d3dBlend = D3D11_BLEND_ZERO; break;
- case GL_ONE: d3dBlend = D3D11_BLEND_ONE; break;
- case GL_SRC_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_SRC_ALPHA : D3D11_BLEND_SRC_COLOR); break;
- case GL_ONE_MINUS_SRC_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC_ALPHA : D3D11_BLEND_INV_SRC_COLOR); break;
- case GL_DST_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_DEST_COLOR); break;
- case GL_ONE_MINUS_DST_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_INV_DEST_COLOR); break;
- case GL_SRC_ALPHA: d3dBlend = D3D11_BLEND_SRC_ALPHA; break;
- case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3D11_BLEND_INV_SRC_ALPHA; break;
- case GL_DST_ALPHA: d3dBlend = D3D11_BLEND_DEST_ALPHA; break;
- case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3D11_BLEND_INV_DEST_ALPHA; break;
- case GL_CONSTANT_COLOR: d3dBlend = D3D11_BLEND_BLEND_FACTOR; break;
- case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR; break;
- case GL_CONSTANT_ALPHA: d3dBlend = D3D11_BLEND_BLEND_FACTOR; break;
- case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR; break;
- case GL_SRC_ALPHA_SATURATE: d3dBlend = D3D11_BLEND_SRC_ALPHA_SAT; break;
- default: UNREACHABLE();
- }
-
- return d3dBlend;
-}
-
-D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp)
-{
- D3D11_BLEND_OP d3dBlendOp = D3D11_BLEND_OP_ADD;
-
- switch (glBlendOp)
- {
- case GL_FUNC_ADD: d3dBlendOp = D3D11_BLEND_OP_ADD; break;
- case GL_FUNC_SUBTRACT: d3dBlendOp = D3D11_BLEND_OP_SUBTRACT; break;
- case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3D11_BLEND_OP_REV_SUBTRACT; break;
- case GL_MIN: d3dBlendOp = D3D11_BLEND_OP_MIN; break;
- case GL_MAX: d3dBlendOp = D3D11_BLEND_OP_MAX; break;
- default: UNREACHABLE();
- }
-
- return d3dBlendOp;
-}
-
-UINT8 ConvertColorMask(bool red, bool green, bool blue, bool alpha)
-{
- UINT8 mask = 0;
- if (red)
- {
- mask |= D3D11_COLOR_WRITE_ENABLE_RED;
- }
- if (green)
- {
- mask |= D3D11_COLOR_WRITE_ENABLE_GREEN;
- }
- if (blue)
- {
- mask |= D3D11_COLOR_WRITE_ENABLE_BLUE;
- }
- if (alpha)
- {
- mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
- }
- return mask;
-}
-
-D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode)
-{
- D3D11_CULL_MODE cull = D3D11_CULL_NONE;
-
- if (cullEnabled)
- {
- switch (cullMode)
- {
- case GL_FRONT: cull = D3D11_CULL_FRONT; break;
- case GL_BACK: cull = D3D11_CULL_BACK; break;
- case GL_FRONT_AND_BACK: cull = D3D11_CULL_NONE; break;
- default: UNREACHABLE();
- }
- }
- else
- {
- cull = D3D11_CULL_NONE;
- }
-
- return cull;
-}
-
-D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison)
-{
- D3D11_COMPARISON_FUNC d3dComp = D3D11_COMPARISON_NEVER;
- switch (comparison)
- {
- case GL_NEVER: d3dComp = D3D11_COMPARISON_NEVER; break;
- case GL_ALWAYS: d3dComp = D3D11_COMPARISON_ALWAYS; break;
- case GL_LESS: d3dComp = D3D11_COMPARISON_LESS; break;
- case GL_LEQUAL: d3dComp = D3D11_COMPARISON_LESS_EQUAL; break;
- case GL_EQUAL: d3dComp = D3D11_COMPARISON_EQUAL; break;
- case GL_GREATER: d3dComp = D3D11_COMPARISON_GREATER; break;
- case GL_GEQUAL: d3dComp = D3D11_COMPARISON_GREATER_EQUAL; break;
- case GL_NOTEQUAL: d3dComp = D3D11_COMPARISON_NOT_EQUAL; break;
- default: UNREACHABLE();
- }
-
- return d3dComp;
-}
-
-D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled)
-{
- return depthWriteEnabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
-}
-
-UINT8 ConvertStencilMask(GLuint stencilmask)
-{
- return static_cast<UINT8>(stencilmask);
-}
-
-D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp)
-{
- D3D11_STENCIL_OP d3dStencilOp = D3D11_STENCIL_OP_KEEP;
-
- switch (stencilOp)
- {
- case GL_ZERO: d3dStencilOp = D3D11_STENCIL_OP_ZERO; break;
- case GL_KEEP: d3dStencilOp = D3D11_STENCIL_OP_KEEP; break;
- case GL_REPLACE: d3dStencilOp = D3D11_STENCIL_OP_REPLACE; break;
- case GL_INCR: d3dStencilOp = D3D11_STENCIL_OP_INCR_SAT; break;
- case GL_DECR: d3dStencilOp = D3D11_STENCIL_OP_DECR_SAT; break;
- case GL_INVERT: d3dStencilOp = D3D11_STENCIL_OP_INVERT; break;
- case GL_INCR_WRAP: d3dStencilOp = D3D11_STENCIL_OP_INCR; break;
- case GL_DECR_WRAP: d3dStencilOp = D3D11_STENCIL_OP_DECR; break;
- default: UNREACHABLE();
- }
-
- return d3dStencilOp;
-}
-
-D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy, GLenum comparisonMode)
-{
- bool comparison = comparisonMode != GL_NONE;
-
- if (maxAnisotropy > 1.0f)
- {
- return D3D11_ENCODE_ANISOTROPIC_FILTER(static_cast<D3D11_COMPARISON_FUNC>(comparison));
- }
- else
- {
- D3D11_FILTER_TYPE dxMin = D3D11_FILTER_TYPE_POINT;
- D3D11_FILTER_TYPE dxMip = D3D11_FILTER_TYPE_POINT;
- switch (minFilter)
- {
- case GL_NEAREST: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_POINT; break;
- case GL_LINEAR: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_POINT; break;
- case GL_NEAREST_MIPMAP_NEAREST: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_POINT; break;
- case GL_LINEAR_MIPMAP_NEAREST: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_POINT; break;
- case GL_NEAREST_MIPMAP_LINEAR: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_LINEAR; break;
- case GL_LINEAR_MIPMAP_LINEAR: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_LINEAR; break;
- default: UNREACHABLE();
- }
-
- D3D11_FILTER_TYPE dxMag = D3D11_FILTER_TYPE_POINT;
- switch (magFilter)
- {
- case GL_NEAREST: dxMag = D3D11_FILTER_TYPE_POINT; break;
- case GL_LINEAR: dxMag = D3D11_FILTER_TYPE_LINEAR; break;
- default: UNREACHABLE();
- }
-
- return D3D11_ENCODE_BASIC_FILTER(dxMin, dxMag, dxMip, static_cast<D3D11_COMPARISON_FUNC>(comparison));
- }
-}
-
-D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap)
-{
- switch (wrap)
- {
- case GL_REPEAT: return D3D11_TEXTURE_ADDRESS_WRAP;
- case GL_CLAMP_TO_EDGE: return D3D11_TEXTURE_ADDRESS_CLAMP;
- case GL_MIRRORED_REPEAT: return D3D11_TEXTURE_ADDRESS_MIRROR;
- default: UNREACHABLE();
- }
-
- return D3D11_TEXTURE_ADDRESS_WRAP;
-}
-
-D3D11_QUERY ConvertQueryType(GLenum queryType)
-{
- switch (queryType)
- {
- case GL_ANY_SAMPLES_PASSED_EXT:
- case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: return D3D11_QUERY_OCCLUSION;
- case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: return D3D11_QUERY_SO_STATISTICS;
- case GL_TIME_ELAPSED_EXT:
- // Two internal queries are also created for begin/end timestamps
- return D3D11_QUERY_TIMESTAMP_DISJOINT;
- default: UNREACHABLE(); return D3D11_QUERY_EVENT;
- }
-}
-
-} // namespace gl_d3d11
-
namespace d3d11_gl
{
-
namespace
{
+// Standard D3D sample positions from
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ff476218.aspx
+using SamplePositionsArray = std::array<float, 32>;
+static constexpr std::array<SamplePositionsArray, 5> kSamplePositions = {
+ {{{0.5f, 0.5f}},
+ {{0.75f, 0.75f, 0.25f, 0.25f}},
+ {{0.375f, 0.125f, 0.875f, 0.375f, 0.125f, 0.625f, 0.625f, 0.875f}},
+ {{0.5625f, 0.3125f, 0.4375f, 0.6875f, 0.8125f, 0.5625f, 0.3125f, 0.1875f, 0.1875f, 0.8125f,
+ 0.0625f, 0.4375f, 0.6875f, 0.9375f, 0.9375f, 0.0625f}},
+ {{0.5625f, 0.5625f, 0.4375f, 0.3125f, 0.3125f, 0.625f, 0.75f, 0.4375f,
+ 0.1875f, 0.375f, 0.625f, 0.8125f, 0.8125f, 0.6875f, 0.6875f, 0.1875f,
+ 0.375f, 0.875f, 0.5f, 0.0625f, 0.25f, 0.125f, 0.125f, 0.75f,
+ 0.0f, 0.5f, 0.9375f, 0.25f, 0.875f, 0.9375f, 0.0625f, 0.0f}}}};
// Helper functor for querying DXGI support. Saves passing the parameters repeatedly.
class DXGISupportHelper : angle::NonCopyable
{
public:
DXGISupportHelper(ID3D11Device *device, D3D_FEATURE_LEVEL featureLevel)
- : mDevice(device),
- mFeatureLevel(featureLevel)
+ : mDevice(device), mFeatureLevel(featureLevel)
{
}
@@ -347,7 +80,7 @@ class DXGISupportHelper : angle::NonCopyable
else
{
// TODO(jmadill): find out why we fail this call sometimes in FL9_3
- // ERR("Error checking format support for format 0x%x", dxgiFormat);
+ // ERR() << "Error checking format support for format 0x" << std::hex << dxgiFormat;
}
}
@@ -359,93 +92,46 @@ class DXGISupportHelper : angle::NonCopyable
D3D_FEATURE_LEVEL mFeatureLevel;
};
-} // anonymous namespace
-
-unsigned int GetReservedVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel)
-{
- switch (featureLevel)
- {
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0:
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0:
- return 0;
-
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1:
- return 3; // dx_ViewAdjust, dx_ViewCoords and dx_ViewScale
-
- default:
- UNREACHABLE();
- return 0;
- }
-}
-
-unsigned int GetReservedFragmentUniformVectors(D3D_FEATURE_LEVEL featureLevel)
-{
- switch (featureLevel)
- {
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0:
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0:
- return 0;
-
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1:
- return 3;
-
- default:
- UNREACHABLE();
- return 0;
- }
-}
-
-GLint GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel)
-{
- switch (featureLevel)
- {
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0:
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return 3;
-
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return 2;
-
- default: UNREACHABLE(); return 0;
- }
-}
-
-static gl::TextureCaps GenerateTextureFormatCaps(GLint maxClientVersion, GLenum internalFormat, ID3D11Device *device, const Renderer11DeviceCaps &renderer11DeviceCaps)
+gl::TextureCaps GenerateTextureFormatCaps(gl::Version maxClientVersion,
+ GLenum internalFormat,
+ ID3D11Device *device,
+ const Renderer11DeviceCaps &renderer11DeviceCaps)
{
gl::TextureCaps textureCaps;
DXGISupportHelper support(device, renderer11DeviceCaps.featureLevel);
- const d3d11::TextureFormat &formatInfo =
- d3d11::GetTextureFormatInfo(internalFormat, renderer11DeviceCaps);
+ const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps);
- const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
+ const gl::InternalFormat &internalFormatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
UINT texSupportMask = D3D11_FORMAT_SUPPORT_TEXTURE2D;
if (internalFormatInfo.depthBits == 0 && internalFormatInfo.stencilBits == 0)
{
texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURECUBE;
- if (maxClientVersion > 2)
+ if (maxClientVersion.major > 2)
{
texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURE3D;
}
}
textureCaps.texturable = support.query(formatInfo.texFormat, texSupportMask);
- textureCaps.filterable = support.query(formatInfo.srvFormat, D3D11_FORMAT_SUPPORT_SHADER_SAMPLE);
- textureCaps.renderable = (support.query(formatInfo.rtvFormat, D3D11_FORMAT_SUPPORT_RENDER_TARGET)) ||
- (support.query(formatInfo.dsvFormat, D3D11_FORMAT_SUPPORT_DEPTH_STENCIL));
+ textureCaps.filterable =
+ support.query(formatInfo.srvFormat, D3D11_FORMAT_SUPPORT_SHADER_SAMPLE);
+ textureCaps.renderable =
+ (support.query(formatInfo.rtvFormat, D3D11_FORMAT_SUPPORT_RENDER_TARGET)) ||
+ (support.query(formatInfo.dsvFormat, D3D11_FORMAT_SUPPORT_DEPTH_STENCIL));
- if (support.query(formatInfo.renderFormat, D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET))
+ DXGI_FORMAT renderFormat = DXGI_FORMAT_UNKNOWN;
+ if (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ renderFormat = formatInfo.dsvFormat;
+ }
+ else if (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ renderFormat = formatInfo.rtvFormat;
+ }
+ if (renderFormat != DXGI_FORMAT_UNKNOWN &&
+ support.query(renderFormat, D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET))
{
// Assume 1x
textureCaps.sampleCounts.insert(1);
@@ -454,7 +140,8 @@ static gl::TextureCaps GenerateTextureFormatCaps(GLint maxClientVersion, GLenum
sampleCount *= 2)
{
UINT qualityCount = 0;
- if (SUCCEEDED(device->CheckMultisampleQualityLevels(formatInfo.renderFormat, sampleCount, &qualityCount)))
+ if (SUCCEEDED(device->CheckMultisampleQualityLevels(renderFormat, sampleCount,
+ &qualityCount)))
{
// Assume we always support lower sample counts
if (qualityCount == 0)
@@ -469,691 +156,1124 @@ static gl::TextureCaps GenerateTextureFormatCaps(GLint maxClientVersion, GLenum
return textureCaps;
}
-static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel)
+bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0:
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return true;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return true;
// From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return false;
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return false;
- default: UNREACHABLE(); return false;
+ default:
+ UNREACHABLE();
+ return false;
}
}
-static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel)
+float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0: return D3D11_MAX_MAXANISOTROPY;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_MAX_MAXANISOTROPY;
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return D3D10_MAX_MAXANISOTROPY;
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_MAX_MAXANISOTROPY;
// From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2: return 16;
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ return 16;
- case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY;
+ case D3D_FEATURE_LEVEL_9_1:
+ return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY;
- default: UNREACHABLE(); return 0;
+ default:
+ UNREACHABLE();
+ return 0;
}
}
-static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel)
+bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0:
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return true;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return true;
- // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateQuery
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2: return true;
- case D3D_FEATURE_LEVEL_9_1: return false;
+ // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx
+ // ID3D11Device::CreateQuery
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ return true;
+ case D3D_FEATURE_LEVEL_9_1:
+ return false;
- default: UNREACHABLE(); return false;
+ default:
+ UNREACHABLE();
+ return false;
}
}
-static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel)
+bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel)
{
- // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateQuery
+ // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx
+ // ID3D11Device::CreateQuery
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0:
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0:
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return true;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return true;
- default: UNREACHABLE(); return false;
+ default:
+ UNREACHABLE();
+ return false;
}
}
-static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel)
+bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel)
{
- // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout
+ // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx
+ // ID3D11Device::CreateInputLayout
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0:
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return true;
-
- // Feature Level 9_3 supports instancing, but slot 0 in the input layout must not be instanced.
- // D3D9 has a similar restriction, where stream 0 must not be instanced.
- // This restriction can be worked around by remapping any non-instanced slot to slot 0.
- // This works because HLSL uses shader semantics to match the vertex inputs to the elements in the input layout, rather than the slots.
- // Note that we only support instancing via ANGLE_instanced_array on 9_3, since 9_3 doesn't support OpenGL ES 3.0
- case D3D_FEATURE_LEVEL_9_3: return true;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return true;
+
+ // Feature Level 9_3 supports instancing, but slot 0 in the input layout must not be
+ // instanced.
+ // D3D9 has a similar restriction, where stream 0 must not be instanced.
+ // This restriction can be worked around by remapping any non-instanced slot to slot
+ // 0.
+ // This works because HLSL uses shader semantics to match the vertex inputs to the
+ // elements in the input layout, rather than the slots.
+ // Note that we only support instancing via ANGLE_instanced_array on 9_3, since 9_3
+ // doesn't support OpenGL ES 3.0
+ case D3D_FEATURE_LEVEL_9_3:
+ return true;
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return false;
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return false;
- default: UNREACHABLE(); return false;
+ default:
+ UNREACHABLE();
+ return false;
}
}
-static bool GetFramebufferMultisampleSupport(D3D_FEATURE_LEVEL featureLevel)
+bool GetFramebufferMultisampleSupport(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0:
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return true;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return true;
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return false;
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return false;
- default: UNREACHABLE(); return false;
+ default:
+ UNREACHABLE();
+ return false;
}
}
-static bool GetFramebufferBlitSupport(D3D_FEATURE_LEVEL featureLevel)
+bool GetFramebufferBlitSupport(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0:
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return true;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return true;
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return false;
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return false;
- default: UNREACHABLE(); return false;
+ default:
+ UNREACHABLE();
+ return false;
}
}
-static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel)
+bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel)
{
- // http://msdn.microsoft.com/en-us/library/windows/desktop/bb509588.aspx states that shader model
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/bb509588.aspx states that
+ // shader model
// ps_2_x is required for the ddx (and other derivative functions).
- // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx states that feature level
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx states that
+ // feature level
// 9.3 supports shader model ps_2_x.
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0:
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0:
- case D3D_FEATURE_LEVEL_9_3: return true;
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return false;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ case D3D_FEATURE_LEVEL_9_3:
+ return true;
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return false;
- default: UNREACHABLE(); return false;
+ default:
+ UNREACHABLE();
+ return false;
}
}
-static bool GetShaderTextureLODSupport(D3D_FEATURE_LEVEL featureLevel)
+bool GetShaderTextureLODSupport(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0:
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return true;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return true;
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return false;
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return false;
- default: UNREACHABLE(); return false;
+ default:
+ UNREACHABLE();
+ return false;
}
}
-static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel)
+size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel)
{
- // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout
+ // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx
+ // ID3D11Device::CreateInputLayout
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT;
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT;
- case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT;
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT;
+ case D3D_FEATURE_LEVEL_9_3:
+ return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT;
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT;
- default: UNREACHABLE(); return 0;
+ default:
+ UNREACHABLE();
+ return 0;
}
}
-static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel)
+size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
- case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+ case D3D_FEATURE_LEVEL_9_3:
+ return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
- default: UNREACHABLE(); return 0;
+ default:
+ UNREACHABLE();
+ return 0;
}
}
-static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel)
+size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
-#if defined(ANGLE_ENABLE_D3D11_1)
- case D3D_FEATURE_LEVEL_11_1:
-#endif
- case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURECUBE_DIMENSION;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_REQ_TEXTURECUBE_DIMENSION;
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURECUBE_DIMENSION;
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_REQ_TEXTURECUBE_DIMENSION;
- case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION;
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION;
+ case D3D_FEATURE_LEVEL_9_3:
+ return D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION;
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION;
- default: UNREACHABLE(); return 0;
+ default:
+ UNREACHABLE();
+ return 0;
}
}
-static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel)
+size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
-#if defined(ANGLE_ENABLE_D3D11_1)
- case D3D_FEATURE_LEVEL_11_1:
-#endif
- case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return 0;
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 0;
- default: UNREACHABLE(); return 0;
+ default:
+ UNREACHABLE();
+ return 0;
}
}
-static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel)
+size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
- default: UNREACHABLE(); return 0;
+ default:
+ UNREACHABLE();
+ return 0;
}
}
-static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel)
+size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0: return D3D11_VIEWPORT_BOUNDS_MAX;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_VIEWPORT_BOUNDS_MAX;
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return D3D10_VIEWPORT_BOUNDS_MAX;
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_VIEWPORT_BOUNDS_MAX;
- // No constants for D3D11 Feature Level 9 viewport size limits, use the maximum texture sizes
- case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+ // No constants for D3D11 Feature Level 9 viewport size limits, use the maximum
+ // texture sizes
+ case D3D_FEATURE_LEVEL_9_3:
+ return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
- default: UNREACHABLE(); return 0;
+ default:
+ UNREACHABLE();
+ return 0;
}
}
-static size_t GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel)
+size_t GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel)
{
- // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since that's what's
+ // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since
+ // that's what's
// returned from glGetInteger
- static_assert(D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value.");
- static_assert(D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value.");
+ static_assert(D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32,
+ "Unexpected D3D11 constant value.");
+ static_assert(D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32,
+ "Unexpected D3D11 constant value.");
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0:
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return std::numeric_limits<GLint>::max();
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return std::numeric_limits<GLint>::max();
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2: return D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT;
- case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT;
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ return D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT;
+ case D3D_FEATURE_LEVEL_9_1:
+ return D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT;
- default: UNREACHABLE(); return 0;
+ default:
+ UNREACHABLE();
+ return 0;
}
}
-static size_t GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel)
+size_t GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel)
{
- // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since that's what's
+ // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since
+ // that's what's
// returned from glGetInteger
static_assert(D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value.");
static_assert(D3D10_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value.");
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0:
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return std::numeric_limits<GLint>::max();
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return std::numeric_limits<GLint>::max();
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2: return D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT;
- case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT;
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ return D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT;
+ case D3D_FEATURE_LEVEL_9_1:
+ return D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT;
- default: UNREACHABLE(); return 0;
+ default:
+ UNREACHABLE();
+ return 0;
}
}
-static size_t GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel)
+size_t GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0: return D3D11_STANDARD_VERTEX_ELEMENT_COUNT;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_STANDARD_VERTEX_ELEMENT_COUNT;
- case D3D_FEATURE_LEVEL_10_1: return D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT;
- case D3D_FEATURE_LEVEL_10_0: return D3D10_STANDARD_VERTEX_ELEMENT_COUNT;
+ case D3D_FEATURE_LEVEL_10_1:
+ return D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT;
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_STANDARD_VERTEX_ELEMENT_COUNT;
- // From http://http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx "Max Input Slots"
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return 16;
+ // From http://http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
+ // "Max Input Slots"
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 16;
- default: UNREACHABLE(); return 0;
+ default:
+ UNREACHABLE();
+ return 0;
}
}
-static size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel)
+size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel)
{
- // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return 1024; // D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
- // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx ID3D11DeviceContext::VSSetConstantBuffers
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1:
- return 255 - d3d11_gl::GetReservedVertexUniformVectors(featureLevel);
+ // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx
+ // ID3D11DeviceContext::VSSetConstantBuffers
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 255 - d3d11_gl::GetReservedVertexUniformVectors(featureLevel);
- default: UNREACHABLE(); return 0;
+ default:
+ UNREACHABLE();
+ return 0;
}
}
-static size_t GetReservedVertexUniformBuffers()
-{
- // Reserve one buffer for the application uniforms, and one for driver uniforms
- return 2;
-}
-
-static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
+size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers();
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
+ d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers();
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
+ d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
- // Uniform blocks not supported on D3D11 Feature Level 9
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return 0;
+ // Uniform blocks not supported on D3D11 Feature Level 9
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 0;
- default: UNREACHABLE(); return 0;
+ default:
+ UNREACHABLE();
+ return 0;
}
}
-static size_t GetReservedVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)
+size_t GetReservedVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)
{
- // According to The OpenGL ES Shading Language specifications
+ // According to The OpenGL ES Shading Language specifications
// (Language Version 1.00 section 10.16, Language Version 3.10 section 12.21)
// built-in special variables (e.g. gl_FragCoord, or gl_PointCoord)
- // which are statically used in the shader should be included in the variable packing algorithm.
+ // which are statically used in the shader should be included in the variable packing
+ // algorithm.
// Therefore, we should not reserve output vectors for them.
switch (featureLevel)
{
- // We must reserve one output vector for dx_Position.
- // We also reserve one for gl_Position, which we unconditionally output on Feature Levels 10_0+,
- // even if it's unused in the shader (e.g. for transform feedback). TODO: This could be improved.
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0:
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return 2;
+ // We must reserve one output vector for dx_Position.
+ // We also reserve one for gl_Position, which we unconditionally output on Feature
+ // Levels 10_0+,
+ // even if it's unused in the shader (e.g. for transform feedback). TODO: This could
+ // be improved.
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return 2;
- // Just reserve dx_Position on Feature Level 9, since we don't ever need to output gl_Position.
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return 1;
+ // Just reserve dx_Position on Feature Level 9, since we don't ever need to output
+ // gl_Position.
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 1;
- default: UNREACHABLE(); return 0;
+ default:
+ UNREACHABLE();
+ return 0;
}
-
- return 1;
}
-static size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)
+size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)
{
- static_assert(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT, "Unexpected D3D11 constant value.");
+ static_assert(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT,
+ "Unexpected D3D11 constant value.");
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0: return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
- case D3D_FEATURE_LEVEL_10_1: return D3D10_1_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
- case D3D_FEATURE_LEVEL_10_0: return D3D10_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
+ case D3D_FEATURE_LEVEL_10_1:
+ return D3D10_1_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
- // Use Shader Model 2.X limits
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return 8 - GetReservedVertexOutputVectors(featureLevel);
+ // Use Shader Model 2.X limits
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 8 - GetReservedVertexOutputVectors(featureLevel);
- default: UNREACHABLE(); return 0;
+ default:
+ UNREACHABLE();
+ return 0;
}
}
-static size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel)
+size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT;
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT;
- // Vertex textures not supported on D3D11 Feature Level 9 according to
- // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx
- // ID3D11DeviceContext::VSSetSamplers and ID3D11DeviceContext::VSSetShaderResources
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return 0;
+ // Vertex textures not supported on D3D11 Feature Level 9 according to
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx
+ // ID3D11DeviceContext::VSSetSamplers and ID3D11DeviceContext::VSSetShaderResources
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 0;
- default: UNREACHABLE(); return 0;
+ default:
+ UNREACHABLE();
+ return 0;
}
}
-static size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel)
+size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel)
{
// TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return 1024; // D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return 1024; // D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
- // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx ID3D11DeviceContext::PSSetConstantBuffers
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1:
- return 32 - d3d11_gl::GetReservedFragmentUniformVectors(featureLevel);
+ // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx
+ // ID3D11DeviceContext::PSSetConstantBuffers
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 32 - d3d11_gl::GetReservedFragmentUniformVectors(featureLevel);
- default: UNREACHABLE(); return 0;
+ default:
+ UNREACHABLE();
+ return 0;
}
}
-static size_t GetReservedPixelUniformBuffers()
+size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
{
- // Reserve one buffer for the application uniforms, and one for driver uniforms
- return 2;
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
+ d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
+ d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
+
+ // Uniform blocks not supported on D3D11 Feature Level 9
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 0;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+size_t GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
+
+ // Use Shader Model 2.X limits
+ case D3D_FEATURE_LEVEL_9_3:
+ return 8 - GetReservedVertexOutputVectors(featureLevel);
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 8 - GetReservedVertexOutputVectors(featureLevel);
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
}
-static size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
+size_t GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers();
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers();
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT;
- // Uniform blocks not supported on D3D11 Feature Level 9
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return 0;
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx
+ // ID3D11DeviceContext::PSSetShaderResources
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 16;
- default: UNREACHABLE(); return 0;
+ default:
+ UNREACHABLE();
+ return 0;
}
}
-static size_t GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel)
+std::array<GLuint, 3> GetMaxComputeWorkGroupCount(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0: return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return {{D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION,
+ D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION,
+ D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION}};
+ break;
+ default:
+ return {{0, 0, 0}};
+ }
+}
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return D3D10_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
+std::array<GLuint, 3> GetMaxComputeWorkGroupSize(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return {{D3D11_CS_THREAD_GROUP_MAX_X, D3D11_CS_THREAD_GROUP_MAX_Y,
+ D3D11_CS_THREAD_GROUP_MAX_Z}};
+ break;
+ default:
+ return {{0, 0, 0}};
+ }
+}
- // Use Shader Model 2.X limits
- case D3D_FEATURE_LEVEL_9_3: return 8 - GetReservedVertexOutputVectors(featureLevel);
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return 8 - GetReservedVertexOutputVectors(featureLevel);
+size_t GetMaxComputeWorkGroupInvocations(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP;
+ default:
+ return 0;
+ }
+}
- default: UNREACHABLE(); return 0;
+size_t GetMaximumComputeUniformVectors(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
+ default:
+ return 0;
}
}
-static size_t GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel)
+size_t GetMaximumComputeUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
+ d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
+ default:
+ return 0;
+ }
+}
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT;
+size_t GetMaximumComputeTextureUnits(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
+ default:
+ return 0;
+ }
+}
- // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx ID3D11DeviceContext::PSSetShaderResources
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return 16;
+size_t GetMaximumImageUnits(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ // TODO(xinghua.cao@intel.com): Get a more accurate limit. For now using
+ // the minimum requirement for GLES 3.1.
+ return 4;
+ default:
+ return 0;
+ }
+}
- default: UNREACHABLE(); return 0;
+size_t GetMaximumComputeImageUniforms(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ // TODO(xinghua.cao@intel.com): Get a more accurate limit. For now using
+ // the minimum requirement for GLES 3.1.
+ return 4;
+ default:
+ return 0;
}
}
-static int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
+int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE;
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE;
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE;
- // Sampling functions with offsets are not available below shader model 4.0.
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return 0;
+ // Sampling functions with offsets are not available below shader model 4.0.
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 0;
- default: UNREACHABLE(); return 0;
+ default:
+ UNREACHABLE();
+ return 0;
}
}
-static int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
+int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE;
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE;
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE;
- // Sampling functions with offsets are not available below shader model 4.0.
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return 0;
+ // Sampling functions with offsets are not available below shader model 4.0.
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 0;
- default: UNREACHABLE(); return 0;
+ default:
+ UNREACHABLE();
+ return 0;
}
}
-static size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel)
+size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel)
{
- // Returns a size_t despite the limit being a GLuint64 because size_t is the maximum size of
+ // Returns a size_t despite the limit being a GLuint64 because size_t is the maximum
+ // size of
// any buffer that could be allocated.
const size_t bytesPerComponent = 4 * sizeof(float);
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent;
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent;
+
+ // Limits from http://msdn.microsoft.com/en-us/library/windows/desktop/ff476501.aspx
+ // remarks section
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 4096 * bytesPerComponent;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_SO_BUFFER_SLOT_COUNT;
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent;
+ case D3D_FEATURE_LEVEL_10_1:
+ return D3D10_1_SO_BUFFER_SLOT_COUNT;
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_SO_BUFFER_SLOT_COUNT;
+
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 0;
- // Limits from http://msdn.microsoft.com/en-us/library/windows/desktop/ff476501.aspx remarks section
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return 4096 * bytesPerComponent;
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+size_t GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return GetMaximumVertexOutputVectors(featureLevel) * 4;
+
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 0;
- default: UNREACHABLE(); return 0;
+ default:
+ UNREACHABLE();
+ return 0;
}
}
-static size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel)
+size_t GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0: return D3D11_SO_BUFFER_SLOT_COUNT;
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return GetMaximumStreamOutputInterleavedComponents(featureLevel) /
+ GetMaximumStreamOutputBuffers(featureLevel);
- case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SO_BUFFER_SLOT_COUNT;
- case D3D_FEATURE_LEVEL_10_0: return D3D10_SO_BUFFER_SLOT_COUNT;
+ // D3D 10 and 10.1 only allow one output per output slot if an output slot other
+ // than zero is used.
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return 4;
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return 0;
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 0;
- default: UNREACHABLE(); return 0;
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+size_t GetMaximumRenderToBufferWindowSize(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_REQ_RENDER_TO_BUFFER_WINDOW_WIDTH;
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_REQ_RENDER_TO_BUFFER_WINDOW_WIDTH;
+
+ // REQ_RENDER_TO_BUFFER_WINDOW_WIDTH not supported on D3D11 Feature Level 9,
+ // use the maximum texture sizes
+ case D3D_FEATURE_LEVEL_9_3:
+ return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+
+ default:
+ UNREACHABLE();
+ return 0;
}
}
-static size_t GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL featureLevel)
+IntelDriverVersion GetIntelDriverVersion(const Optional<LARGE_INTEGER> driverVersion)
+{
+ if (!driverVersion.valid())
+ return IntelDriverVersion(0);
+
+ // According to http://www.intel.com/content/www/us/en/support/graphics-drivers/000005654.html,
+ // only the fourth part is necessary since it stands for the driver specific unique version
+ // number.
+ WORD part = LOWORD(driverVersion.value().LowPart);
+ return IntelDriverVersion(part);
+}
+
+} // anonymous namespace
+
+unsigned int GetReservedVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return 0;
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return GetMaximumVertexOutputVectors(featureLevel) * 4;
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 3; // dx_ViewAdjust, dx_ViewCoords and dx_ViewScale
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return 0;
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+unsigned int GetReservedFragmentUniformVectors(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return 0;
+
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 3;
- default: UNREACHABLE(); return 0;
+ default:
+ UNREACHABLE();
+ return 0;
}
}
-static size_t GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL featureLevel)
+gl::Version GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
- case D3D_FEATURE_LEVEL_11_1:
- case D3D_FEATURE_LEVEL_11_0: return GetMaximumStreamOutputInterleavedComponents(featureLevel) /
- GetMaximumStreamOutputBuffers(featureLevel);
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return gl::Version(3, 1);
+ case D3D_FEATURE_LEVEL_10_1:
+ return gl::Version(3, 0);
+ case D3D_FEATURE_LEVEL_10_0:
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return gl::Version(2, 0);
- // D3D 10 and 10.1 only allow one output per output slot if an output slot other than zero is used.
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return 4;
+ default:
+ UNREACHABLE();
+ return gl::Version(0, 0);
+ }
+}
+
+unsigned int GetMaxViewportAndScissorRectanglesPerPipeline(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 1;
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return 0;
+bool IsMultiviewSupported(D3D_FEATURE_LEVEL featureLevel)
+{
+ // The ANGLE_multiview extension can always be supported in D3D11 through geometry shaders.
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return true;
+ default:
+ return false;
+ }
+}
- default: UNREACHABLE(); return 0;
+unsigned int GetMaxSampleMaskWords(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ // D3D10+ only allows 1 sample mask.
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return 1u;
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 0u;
+ default:
+ UNREACHABLE();
+ return 0u;
}
}
void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, const Renderer11DeviceCaps &renderer11DeviceCaps, gl::Caps *caps,
gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions, gl::Limitations *limitations)
{
- GLuint maxSamples = 0;
D3D_FEATURE_LEVEL featureLevel = renderer11DeviceCaps.featureLevel;
const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats();
- for (gl::FormatSet::const_iterator internalFormat = allFormats.begin(); internalFormat != allFormats.end(); ++internalFormat)
+ for (GLenum internalFormat : allFormats)
{
- gl::TextureCaps textureCaps = GenerateTextureFormatCaps(GetMaximumClientVersion(featureLevel), *internalFormat, device, renderer11DeviceCaps);
- textureCapsMap->insert(*internalFormat, textureCaps);
+ gl::TextureCaps textureCaps = GenerateTextureFormatCaps(
+ GetMaximumClientVersion(featureLevel), internalFormat, device, renderer11DeviceCaps);
+ textureCapsMap->insert(internalFormat, textureCaps);
- maxSamples = std::max(maxSamples, textureCaps.getMaxSamples());
-
- if (gl::GetInternalFormatInfo(*internalFormat).compressed)
+ if (gl::GetSizedInternalFormatInfo(internalFormat).compressed)
{
- caps->compressedTextureFormats.push_back(*internalFormat);
+ caps->compressedTextureFormats.push_back(internalFormat);
}
}
@@ -1226,6 +1346,14 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons
caps->maxVertexTextureImageUnits =
static_cast<GLuint>(GetMaximumVertexTextureUnits(featureLevel));
+ // Vertex Attribute Bindings are emulated on D3D11.
+ caps->maxVertexAttribBindings = caps->maxVertexAttributes;
+ // Experimental testing confirmed there is no explicit limit on maximum buffer offset in D3D11.
+ caps->maxVertexAttribRelativeOffset = std::numeric_limits<GLint>::max();
+ // Experimental testing confirmed 2048 is the maximum stride that D3D11 can support on all
+ // platforms.
+ caps->maxVertexAttribStride = 2048;
+
// Fragment shader limits
caps->maxFragmentUniformComponents =
static_cast<GLuint>(GetMaximumPixelUniformVectors(featureLevel)) * 4;
@@ -1239,10 +1367,28 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons
caps->minProgramTexelOffset = GetMinimumTexelOffset(featureLevel);
caps->maxProgramTexelOffset = GetMaximumTexelOffset(featureLevel);
+ // Compute shader limits
+ caps->maxComputeWorkGroupCount = GetMaxComputeWorkGroupCount(featureLevel);
+ caps->maxComputeWorkGroupSize = GetMaxComputeWorkGroupSize(featureLevel);
+ caps->maxComputeWorkGroupInvocations =
+ static_cast<GLuint>(GetMaxComputeWorkGroupInvocations(featureLevel));
+ caps->maxComputeUniformComponents =
+ static_cast<GLuint>(GetMaximumComputeUniformVectors(featureLevel)) * 4;
+ caps->maxComputeUniformBlocks =
+ static_cast<GLuint>(GetMaximumComputeUniformBlocks(featureLevel));
+ caps->maxComputeTextureImageUnits =
+ static_cast<GLuint>(GetMaximumComputeTextureUnits(featureLevel));
+ caps->maxImageUnits = static_cast<GLuint>(GetMaximumImageUnits(featureLevel));
+ caps->maxComputeImageUniforms =
+ static_cast<GLuint>(GetMaximumComputeImageUniforms(featureLevel));
+
// Aggregate shader limits
caps->maxUniformBufferBindings = caps->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks;
caps->maxUniformBlockSize = GetMaximumConstantBufferSize(featureLevel);
+ // TODO(oetuaho): Get a more accurate limit. For now using the minimum requirement for GLES 3.1.
+ caps->maxUniformLocations = 1024;
+
// With DirectX 11.1, constant buffer offset and size must be a multiple of 16 constants of 16 bytes each.
// https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx
// With DirectX 11.0, we emulate UBO offsets using copies of ranges of the UBO however
@@ -1254,6 +1400,9 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons
static_cast<GLint64>(caps->maxVertexUniformComponents);
caps->maxCombinedFragmentUniformComponents = (static_cast<GLint64>(caps->maxFragmentUniformBlocks) * static_cast<GLint64>(caps->maxUniformBlockSize / 4)) +
static_cast<GLint64>(caps->maxFragmentUniformComponents);
+ caps->maxCombinedComputeUniformComponents =
+ static_cast<GLuint>(caps->maxComputeUniformBlocks * (caps->maxUniformBlockSize / 4) +
+ caps->maxComputeUniformComponents);
caps->maxVaryingComponents =
static_cast<GLuint>(GetMaximumVertexOutputVectors(featureLevel)) * 4;
caps->maxVaryingVectors = static_cast<GLuint>(GetMaximumVertexOutputVectors(featureLevel));
@@ -1267,8 +1416,21 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons
caps->maxTransformFeedbackSeparateComponents =
static_cast<GLuint>(GetMaximumStreamOutputSeparateComponents(featureLevel));
- // Multisample limits
- caps->maxSamples = maxSamples;
+ // Defer the computation of multisample limits to Context::updateCaps() where max*Samples values
+ // are determined according to available sample counts for each individual format.
+ caps->maxSamples = std::numeric_limits<GLint>::max();
+ caps->maxColorTextureSamples = std::numeric_limits<GLint>::max();
+ caps->maxDepthTextureSamples = std::numeric_limits<GLint>::max();
+ caps->maxIntegerSamples = std::numeric_limits<GLint>::max();
+
+ // Sample mask words limits
+ caps->maxSampleMaskWords = GetMaxSampleMaskWords(featureLevel);
+
+ // Framebuffer limits
+ caps->maxFramebufferSamples = std::numeric_limits<GLint>::max();
+ caps->maxFramebufferWidth =
+ static_cast<GLuint>(GetMaximumRenderToBufferWindowSize(featureLevel));
+ caps->maxFramebufferHeight = caps->maxFramebufferWidth;
// GL extension support
extensions->setTextureExtensionSupport(*textureCapsMap);
@@ -1286,12 +1448,15 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons
extensions->maxTextureAnisotropy = GetMaximumAnisotropy(featureLevel);
extensions->occlusionQueryBoolean = GetOcclusionQuerySupport(featureLevel);
extensions->fence = GetEventQuerySupport(featureLevel);
- extensions->timerQuery = false; // Unimplemented
extensions->disjointTimerQuery = true;
extensions->queryCounterBitsTimeElapsed = 64;
extensions->queryCounterBitsTimestamp =
0; // Timestamps cannot be supported due to D3D11 limitations
extensions->robustness = true;
+ // Direct3D guarantees to return zero for any resource that is accessed out of bounds.
+ // See https://msdn.microsoft.com/en-us/library/windows/desktop/ff476332(v=vs.85).aspx
+ // and https://msdn.microsoft.com/en-us/library/windows/desktop/ff476900(v=vs.85).aspx
+ extensions->robustBufferAccessBehavior = true;
extensions->blendMinMax = true;
extensions->framebufferBlit = GetFramebufferBlitSupport(featureLevel);
extensions->framebufferMultisample = GetFramebufferMultisampleSupport(featureLevel);
@@ -1300,17 +1465,29 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons
extensions->standardDerivatives = GetDerivativeInstructionSupport(featureLevel);
extensions->shaderTextureLOD = GetShaderTextureLODSupport(featureLevel);
extensions->fragDepth = true;
+ extensions->multiview = IsMultiviewSupported(featureLevel);
+ if (extensions->multiview)
+ {
+ extensions->maxViews =
+ std::min(static_cast<GLuint>(gl::IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS),
+ std::min(static_cast<GLuint>(GetMaximum2DTextureArraySize(featureLevel)),
+ GetMaxViewportAndScissorRectanglesPerPipeline(featureLevel)));
+ }
extensions->textureUsage = true; // This could be false since it has no effect in D3D11
extensions->discardFramebuffer = true;
extensions->translatedShaderSource = true;
extensions->fboRenderMipmap = false;
extensions->debugMarker = true;
extensions->eglImage = true;
+ extensions->eglImageExternal = true;
+ extensions->eglImageExternalEssl3 = true;
+ extensions->eglStreamConsumerExternal = true;
extensions->unpackSubimage = true;
extensions->packSubimage = true;
- extensions->vertexArrayObject = true;
- extensions->noError = true;
extensions->lossyETCDecode = true;
+ extensions->syncQuery = GetEventQuerySupport(featureLevel);
+ extensions->copyTexture = true;
+ extensions->copyCompressedTexture = true;
// D3D11 Feature Level 10_0+ uses SV_IsFrontFace in HLSL to emulate gl_FrontFacing.
// D3D11 Feature Level 9_3 doesn't support SV_IsFrontFace, and has no equivalent, so can't support gl_FrontFacing.
@@ -1340,8 +1517,355 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons
#endif
}
+void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy)
+{
+ size_t indexKey = static_cast<size_t>(ceil(log(sampleCount)));
+ ASSERT(indexKey < kSamplePositions.size() &&
+ (2 * index + 1) < kSamplePositions[indexKey].size());
+
+ xy[0] = kSamplePositions[indexKey][2 * index];
+ xy[1] = kSamplePositions[indexKey][2 * index + 1];
+}
+
} // namespace d3d11_gl
+namespace gl_d3d11
+{
+
+D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha)
+{
+ D3D11_BLEND d3dBlend = D3D11_BLEND_ZERO;
+
+ switch (glBlend)
+ {
+ case GL_ZERO:
+ d3dBlend = D3D11_BLEND_ZERO;
+ break;
+ case GL_ONE:
+ d3dBlend = D3D11_BLEND_ONE;
+ break;
+ case GL_SRC_COLOR:
+ d3dBlend = (isAlpha ? D3D11_BLEND_SRC_ALPHA : D3D11_BLEND_SRC_COLOR);
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC_ALPHA : D3D11_BLEND_INV_SRC_COLOR);
+ break;
+ case GL_DST_COLOR:
+ d3dBlend = (isAlpha ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_DEST_COLOR);
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ d3dBlend = (isAlpha ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_INV_DEST_COLOR);
+ break;
+ case GL_SRC_ALPHA:
+ d3dBlend = D3D11_BLEND_SRC_ALPHA;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ d3dBlend = D3D11_BLEND_INV_SRC_ALPHA;
+ break;
+ case GL_DST_ALPHA:
+ d3dBlend = D3D11_BLEND_DEST_ALPHA;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ d3dBlend = D3D11_BLEND_INV_DEST_ALPHA;
+ break;
+ case GL_CONSTANT_COLOR:
+ d3dBlend = D3D11_BLEND_BLEND_FACTOR;
+ break;
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR;
+ break;
+ case GL_CONSTANT_ALPHA:
+ d3dBlend = D3D11_BLEND_BLEND_FACTOR;
+ break;
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR;
+ break;
+ case GL_SRC_ALPHA_SATURATE:
+ d3dBlend = D3D11_BLEND_SRC_ALPHA_SAT;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return d3dBlend;
+}
+
+D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp)
+{
+ D3D11_BLEND_OP d3dBlendOp = D3D11_BLEND_OP_ADD;
+
+ switch (glBlendOp)
+ {
+ case GL_FUNC_ADD:
+ d3dBlendOp = D3D11_BLEND_OP_ADD;
+ break;
+ case GL_FUNC_SUBTRACT:
+ d3dBlendOp = D3D11_BLEND_OP_SUBTRACT;
+ break;
+ case GL_FUNC_REVERSE_SUBTRACT:
+ d3dBlendOp = D3D11_BLEND_OP_REV_SUBTRACT;
+ break;
+ case GL_MIN:
+ d3dBlendOp = D3D11_BLEND_OP_MIN;
+ break;
+ case GL_MAX:
+ d3dBlendOp = D3D11_BLEND_OP_MAX;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return d3dBlendOp;
+}
+
+UINT8 ConvertColorMask(bool red, bool green, bool blue, bool alpha)
+{
+ UINT8 mask = 0;
+ if (red)
+ {
+ mask |= D3D11_COLOR_WRITE_ENABLE_RED;
+ }
+ if (green)
+ {
+ mask |= D3D11_COLOR_WRITE_ENABLE_GREEN;
+ }
+ if (blue)
+ {
+ mask |= D3D11_COLOR_WRITE_ENABLE_BLUE;
+ }
+ if (alpha)
+ {
+ mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
+ }
+ return mask;
+}
+
+D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, gl::CullFaceMode cullMode)
+{
+ D3D11_CULL_MODE cull = D3D11_CULL_NONE;
+
+ if (cullEnabled)
+ {
+ switch (cullMode)
+ {
+ case gl::CullFaceMode::Front:
+ cull = D3D11_CULL_FRONT;
+ break;
+ case gl::CullFaceMode::Back:
+ cull = D3D11_CULL_BACK;
+ break;
+ case gl::CullFaceMode::FrontAndBack:
+ cull = D3D11_CULL_NONE;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ else
+ {
+ cull = D3D11_CULL_NONE;
+ }
+
+ return cull;
+}
+
+D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison)
+{
+ D3D11_COMPARISON_FUNC d3dComp = D3D11_COMPARISON_NEVER;
+ switch (comparison)
+ {
+ case GL_NEVER:
+ d3dComp = D3D11_COMPARISON_NEVER;
+ break;
+ case GL_ALWAYS:
+ d3dComp = D3D11_COMPARISON_ALWAYS;
+ break;
+ case GL_LESS:
+ d3dComp = D3D11_COMPARISON_LESS;
+ break;
+ case GL_LEQUAL:
+ d3dComp = D3D11_COMPARISON_LESS_EQUAL;
+ break;
+ case GL_EQUAL:
+ d3dComp = D3D11_COMPARISON_EQUAL;
+ break;
+ case GL_GREATER:
+ d3dComp = D3D11_COMPARISON_GREATER;
+ break;
+ case GL_GEQUAL:
+ d3dComp = D3D11_COMPARISON_GREATER_EQUAL;
+ break;
+ case GL_NOTEQUAL:
+ d3dComp = D3D11_COMPARISON_NOT_EQUAL;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return d3dComp;
+}
+
+D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled)
+{
+ return depthWriteEnabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
+}
+
+UINT8 ConvertStencilMask(GLuint stencilmask)
+{
+ return static_cast<UINT8>(stencilmask);
+}
+
+D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp)
+{
+ D3D11_STENCIL_OP d3dStencilOp = D3D11_STENCIL_OP_KEEP;
+
+ switch (stencilOp)
+ {
+ case GL_ZERO:
+ d3dStencilOp = D3D11_STENCIL_OP_ZERO;
+ break;
+ case GL_KEEP:
+ d3dStencilOp = D3D11_STENCIL_OP_KEEP;
+ break;
+ case GL_REPLACE:
+ d3dStencilOp = D3D11_STENCIL_OP_REPLACE;
+ break;
+ case GL_INCR:
+ d3dStencilOp = D3D11_STENCIL_OP_INCR_SAT;
+ break;
+ case GL_DECR:
+ d3dStencilOp = D3D11_STENCIL_OP_DECR_SAT;
+ break;
+ case GL_INVERT:
+ d3dStencilOp = D3D11_STENCIL_OP_INVERT;
+ break;
+ case GL_INCR_WRAP:
+ d3dStencilOp = D3D11_STENCIL_OP_INCR;
+ break;
+ case GL_DECR_WRAP:
+ d3dStencilOp = D3D11_STENCIL_OP_DECR;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return d3dStencilOp;
+}
+
+D3D11_FILTER ConvertFilter(GLenum minFilter,
+ GLenum magFilter,
+ float maxAnisotropy,
+ GLenum comparisonMode)
+{
+ bool comparison = comparisonMode != GL_NONE;
+
+ if (maxAnisotropy > 1.0f)
+ {
+ return D3D11_ENCODE_ANISOTROPIC_FILTER(static_cast<D3D11_COMPARISON_FUNC>(comparison));
+ }
+ else
+ {
+ D3D11_FILTER_TYPE dxMin = D3D11_FILTER_TYPE_POINT;
+ D3D11_FILTER_TYPE dxMip = D3D11_FILTER_TYPE_POINT;
+ switch (minFilter)
+ {
+ case GL_NEAREST:
+ dxMin = D3D11_FILTER_TYPE_POINT;
+ dxMip = D3D11_FILTER_TYPE_POINT;
+ break;
+ case GL_LINEAR:
+ dxMin = D3D11_FILTER_TYPE_LINEAR;
+ dxMip = D3D11_FILTER_TYPE_POINT;
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ dxMin = D3D11_FILTER_TYPE_POINT;
+ dxMip = D3D11_FILTER_TYPE_POINT;
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ dxMin = D3D11_FILTER_TYPE_LINEAR;
+ dxMip = D3D11_FILTER_TYPE_POINT;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ dxMin = D3D11_FILTER_TYPE_POINT;
+ dxMip = D3D11_FILTER_TYPE_LINEAR;
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ dxMin = D3D11_FILTER_TYPE_LINEAR;
+ dxMip = D3D11_FILTER_TYPE_LINEAR;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ D3D11_FILTER_TYPE dxMag = D3D11_FILTER_TYPE_POINT;
+ switch (magFilter)
+ {
+ case GL_NEAREST:
+ dxMag = D3D11_FILTER_TYPE_POINT;
+ break;
+ case GL_LINEAR:
+ dxMag = D3D11_FILTER_TYPE_LINEAR;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return D3D11_ENCODE_BASIC_FILTER(dxMin, dxMag, dxMip,
+ static_cast<D3D11_COMPARISON_FUNC>(comparison));
+ }
+}
+
+D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap)
+{
+ switch (wrap)
+ {
+ case GL_REPEAT:
+ return D3D11_TEXTURE_ADDRESS_WRAP;
+ case GL_CLAMP_TO_EDGE:
+ return D3D11_TEXTURE_ADDRESS_CLAMP;
+ case GL_MIRRORED_REPEAT:
+ return D3D11_TEXTURE_ADDRESS_MIRROR;
+ default:
+ UNREACHABLE();
+ }
+
+ return D3D11_TEXTURE_ADDRESS_WRAP;
+}
+
+UINT ConvertMaxAnisotropy(float maxAnisotropy, D3D_FEATURE_LEVEL featureLevel)
+{
+ return static_cast<UINT>(std::min(maxAnisotropy, d3d11_gl::GetMaximumAnisotropy(featureLevel)));
+}
+
+D3D11_QUERY ConvertQueryType(GLenum queryType)
+{
+ switch (queryType)
+ {
+ case GL_ANY_SAMPLES_PASSED_EXT:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+ return D3D11_QUERY_OCCLUSION;
+ case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+ return D3D11_QUERY_SO_STATISTICS;
+ case GL_TIME_ELAPSED_EXT:
+ // Two internal queries are also created for begin/end timestamps
+ return D3D11_QUERY_TIMESTAMP_DISJOINT;
+ case GL_COMMANDS_COMPLETED_CHROMIUM:
+ return D3D11_QUERY_EVENT;
+ default:
+ UNREACHABLE();
+ return D3D11_QUERY_EVENT;
+ }
+}
+
+// Get the D3D11 write mask covering all color channels of a given format
+UINT8 GetColorMask(const gl::InternalFormat &format)
+{
+ return ConvertColorMask(format.redBits > 0, format.greenBits > 0, format.blueBits > 0,
+ format.alphaBits > 0);
+}
+
+} // namespace gl_d3d11
+
namespace d3d11
{
@@ -1352,9 +1876,7 @@ ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device)
IDXGIDevice *dxgiDevice = nullptr;
IDXGIAdapter *dxgiAdapter = nullptr;
-#if defined(ANGLE_ENABLE_D3D11_1)
IDXGIAdapter2 *dxgiAdapter2 = nullptr;
-#endif
ANGLED3D11DeviceType retDeviceType = ANGLE_D3D11_DEVICE_TYPE_UNKNOWN;
@@ -1365,7 +1887,6 @@ ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device)
if (SUCCEEDED(hr))
{
std::wstring adapterString;
-#if defined(ANGLE_ENABLE_D3D11_1)
HRESULT adapter2hr =
dxgiAdapter->QueryInterface(__uuidof(dxgiAdapter2), (void **)&dxgiAdapter2);
if (SUCCEEDED(adapter2hr))
@@ -1378,7 +1899,6 @@ ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device)
adapterString = std::wstring(adapterDesc2.Description);
}
else
-#endif
{
DXGI_ADAPTER_DESC adapterDesc;
dxgiAdapter->GetDesc(&adapterDesc);
@@ -1410,16 +1930,14 @@ ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device)
SafeRelease(dxgiDevice);
SafeRelease(dxgiAdapter);
-#if defined(ANGLE_ENABLE_D3D11_1)
SafeRelease(dxgiAdapter2);
-#endif
return retDeviceType;
}
void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset)
{
- const DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format);
+ const DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(format);
int upsampleCount = 0;
// Don't expand the size of full textures that are at least (blockWidth x blockHeight) already.
@@ -1433,7 +1951,10 @@ void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsi
upsampleCount++;
}
}
- *levelOffset = upsampleCount;
+ if (levelOffset)
+ {
+ *levelOffset = upsampleCount;
+ }
}
void GenerateInitialTextureData(GLint internalFormat,
@@ -1445,10 +1966,11 @@ void GenerateInitialTextureData(GLint internalFormat,
std::vector<D3D11_SUBRESOURCE_DATA> *outSubresourceData,
std::vector<std::vector<BYTE>> *outData)
{
- const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(internalFormat, renderer11DeviceCaps);
- ASSERT(d3dFormatInfo.dataInitializerFunction != NULL);
+ const d3d11::Format &d3dFormatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps);
+ ASSERT(d3dFormatInfo.dataInitializerFunction != nullptr);
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3dFormatInfo.texFormat);
+ const d3d11::DXGIFormatSize &dxgiFormatInfo =
+ d3d11::GetDXGIFormatSizeInfo(d3dFormatInfo.texFormat);
outSubresourceData->resize(mipLevels);
outData->resize(mipLevels);
@@ -1495,6 +2017,36 @@ void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, flo
vertex->s = s;
}
+BlendStateKey::BlendStateKey()
+{
+ memset(this, 0, sizeof(BlendStateKey));
+}
+
+bool operator==(const BlendStateKey &a, const BlendStateKey &b)
+{
+ return memcmp(&a, &b, sizeof(BlendStateKey)) == 0;
+}
+
+bool operator!=(const BlendStateKey &a, const BlendStateKey &b)
+{
+ return !(a == b);
+}
+
+RasterizerStateKey::RasterizerStateKey()
+{
+ memset(this, 0, sizeof(RasterizerStateKey));
+}
+
+bool operator==(const RasterizerStateKey &a, const RasterizerStateKey &b)
+{
+ return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0;
+}
+
+bool operator!=(const RasterizerStateKey &a, const RasterizerStateKey &b)
+{
+ return !(a == b);
+}
+
HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name)
{
#if defined(_DEBUG)
@@ -1533,34 +2085,66 @@ HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name)
#endif
}
+// Keep this in cpp file where it has visibility of Renderer11.h, otherwise calling
+// allocateResource is only compatible with Clang and MSVS, which support calling a
+// method on a forward declared class in a template.
+template <ResourceType ResourceT>
+gl::Error LazyResource<ResourceT>::resolveImpl(Renderer11 *renderer,
+ const GetDescType<ResourceT> &desc,
+ GetInitDataType<ResourceT> *initData,
+ const char *name)
+{
+ if (!mResource.valid())
+ {
+ ANGLE_TRY(renderer->allocateResource(desc, initData, &mResource));
+ mResource.setDebugName(name);
+ }
+ return gl::NoError();
+}
+
+template gl::Error LazyResource<ResourceType::BlendState>::resolveImpl(Renderer11 *renderer,
+ const D3D11_BLEND_DESC &desc,
+ void *initData,
+ const char *name);
+template gl::Error LazyResource<ResourceType::ComputeShader>::resolveImpl(Renderer11 *renderer,
+ const ShaderData &desc,
+ void *initData,
+ const char *name);
+template gl::Error LazyResource<ResourceType::GeometryShader>::resolveImpl(
+ Renderer11 *renderer,
+ const ShaderData &desc,
+ const std::vector<D3D11_SO_DECLARATION_ENTRY> *initData,
+ const char *name);
+template gl::Error LazyResource<ResourceType::InputLayout>::resolveImpl(
+ Renderer11 *renderer,
+ const InputElementArray &desc,
+ const ShaderData *initData,
+ const char *name);
+template gl::Error LazyResource<ResourceType::PixelShader>::resolveImpl(Renderer11 *renderer,
+ const ShaderData &desc,
+ void *initData,
+ const char *name);
+template gl::Error LazyResource<ResourceType::VertexShader>::resolveImpl(Renderer11 *renderer,
+ const ShaderData &desc,
+ void *initData,
+ const char *name);
+
LazyInputLayout::LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc,
size_t inputDescLen,
const BYTE *byteCode,
size_t byteCodeLen,
const char *debugName)
- : mInputDesc(inputDescLen),
- mByteCodeLen(byteCodeLen),
- mByteCode(byteCode),
- mDebugName(debugName)
+ : mInputDesc(inputDesc, inputDescLen), mByteCode(byteCode, byteCodeLen), mDebugName(debugName)
{
- memcpy(&mInputDesc[0], inputDesc, sizeof(D3D11_INPUT_ELEMENT_DESC) * inputDescLen);
}
-ID3D11InputLayout *LazyInputLayout::resolve(ID3D11Device *device)
+LazyInputLayout::~LazyInputLayout()
{
- checkAssociatedDevice(device);
-
- if (mResource == nullptr)
- {
- HRESULT result =
- device->CreateInputLayout(&mInputDesc[0], static_cast<UINT>(mInputDesc.size()),
- mByteCode, mByteCodeLen, &mResource);
- ASSERT(SUCCEEDED(result));
- UNUSED_ASSERTION_VARIABLE(result);
- d3d11::SetDebugName(mResource, mDebugName);
- }
+}
- return mResource;
+gl::Error LazyInputLayout::resolve(Renderer11 *renderer)
+{
+ return resolveImpl(renderer, mInputDesc, &mByteCode, mDebugName);
}
LazyBlendState::LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName)
@@ -1568,213 +2152,270 @@ LazyBlendState::LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugNa
{
}
-ID3D11BlendState *LazyBlendState::resolve(ID3D11Device *device)
+gl::Error LazyBlendState::resolve(Renderer11 *renderer)
+{
+ return resolveImpl(renderer, mDesc, nullptr, mDebugName);
+}
+
+angle::WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps,
+ const DXGI_ADAPTER_DESC &adapterDesc)
{
- checkAssociatedDevice(device);
+ bool is9_3 = (deviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
- if (mResource == nullptr)
+ angle::WorkaroundsD3D workarounds;
+ workarounds.mrtPerfWorkaround = true;
+ workarounds.setDataFasterThanImageUpload = true;
+ workarounds.zeroMaxLodWorkaround = is9_3;
+ workarounds.useInstancedPointSpriteEmulation = is9_3;
+
+ // TODO(jmadill): Narrow problematic driver range.
+ if (IsNvidia(adapterDesc.VendorId))
{
- HRESULT result = device->CreateBlendState(&mDesc, &mResource);
- ASSERT(SUCCEEDED(result));
- UNUSED_ASSERTION_VARIABLE(result);
- d3d11::SetDebugName(mResource, mDebugName);
+ if (deviceCaps.driverVersion.valid())
+ {
+ WORD part1 = HIWORD(deviceCaps.driverVersion.value().LowPart);
+ WORD part2 = LOWORD(deviceCaps.driverVersion.value().LowPart);
+
+ // Disable the workaround to fix a second driver bug on newer NVIDIA.
+ workarounds.depthStencilBlitExtraCopy = (part1 <= 13u && part2 < 6881);
+ }
+ else
+ {
+ workarounds.depthStencilBlitExtraCopy = true;
+ }
}
- return mResource;
+ // TODO(jmadill): Disable workaround when we have a fixed compiler DLL.
+ workarounds.expandIntegerPowExpressions = true;
+
+ workarounds.flushAfterEndingTransformFeedback = IsNvidia(adapterDesc.VendorId);
+ workarounds.getDimensionsIgnoresBaseLevel = IsNvidia(adapterDesc.VendorId);
+
+ if (IsIntel(adapterDesc.VendorId))
+ {
+ IntelDriverVersion capsVersion = d3d11_gl::GetIntelDriverVersion(deviceCaps.driverVersion);
+
+ workarounds.preAddTexelFetchOffsets = true;
+ workarounds.useSystemMemoryForConstantBuffers = true;
+ workarounds.disableB5G6R5Support = capsVersion < IntelDriverVersion(4539);
+ workarounds.addDummyTextureNoRenderTarget = capsVersion < IntelDriverVersion(4815);
+ if (IsSkylake(adapterDesc.DeviceId))
+ {
+ workarounds.callClearTwice = capsVersion < IntelDriverVersion(4771);
+ workarounds.emulateIsnanFloat = capsVersion < IntelDriverVersion(4542);
+ }
+ else if (IsBroadwell(adapterDesc.DeviceId) || IsHaswell(adapterDesc.DeviceId))
+ {
+ workarounds.rewriteUnaryMinusOperator = capsVersion < IntelDriverVersion(4624);
+ }
+ }
+
+ // TODO(jmadill): Disable when we have a fixed driver version.
+ workarounds.emulateTinyStencilTextures = IsAMD(adapterDesc.VendorId);
+
+ // The tiny stencil texture workaround involves using CopySubresource or UpdateSubresource on a
+ // depth stencil texture. This is not allowed until feature level 10.1 but since it is not
+ // possible to support ES3 on these devices, there is no need for the workaround to begin with
+ // (anglebug.com/1572).
+ if (deviceCaps.featureLevel < D3D_FEATURE_LEVEL_10_1)
+ {
+ workarounds.emulateTinyStencilTextures = false;
+ }
+
+ // If the VPAndRTArrayIndexFromAnyShaderFeedingRasterizer feature is not available, we have to
+ // select the viewport / RT array index in the geometry shader.
+ workarounds.selectViewInGeometryShader =
+ (deviceCaps.supportsVpRtIndexWriteFromVertexShader == false);
+
+ // Call platform hooks for testing overrides.
+ auto *platform = ANGLEPlatformCurrent();
+ platform->overrideWorkaroundsD3D(platform, &workarounds);
+
+ return workarounds;
}
-WorkaroundsD3D GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel)
+void InitConstantBufferDesc(D3D11_BUFFER_DESC *constantBufferDescription, size_t byteWidth)
{
- WorkaroundsD3D workarounds;
- workarounds.mrtPerfWorkaround = true;
- workarounds.setDataFasterThanImageUpload = true;
- workarounds.zeroMaxLodWorkaround = (featureLevel <= D3D_FEATURE_LEVEL_9_3);
- workarounds.useInstancedPointSpriteEmulation = (featureLevel <= D3D_FEATURE_LEVEL_9_3);
- return workarounds;
+ constantBufferDescription->ByteWidth = static_cast<UINT>(byteWidth);
+ constantBufferDescription->Usage = D3D11_USAGE_DYNAMIC;
+ constantBufferDescription->BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ constantBufferDescription->CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ constantBufferDescription->MiscFlags = 0;
+ constantBufferDescription->StructureByteStride = 0;
}
} // namespace d3d11
-TextureHelper11::TextureHelper11()
- : mTextureType(GL_NONE),
- mFormat(DXGI_FORMAT_UNKNOWN),
- mSampleCount(0),
- mTexture2D(nullptr),
- mTexture3D(nullptr)
+// TextureHelper11 implementation.
+TextureHelper11::TextureHelper11() : mFormatSet(nullptr), mSampleCount(0)
{
}
-TextureHelper11::TextureHelper11(TextureHelper11 &&toCopy)
- : mTextureType(toCopy.mTextureType),
- mExtents(toCopy.mExtents),
- mFormat(toCopy.mFormat),
- mSampleCount(toCopy.mSampleCount),
- mTexture2D(toCopy.mTexture2D),
- mTexture3D(toCopy.mTexture3D)
+TextureHelper11::TextureHelper11(TextureHelper11 &&toCopy) : TextureHelper11()
{
- toCopy.reset();
+ *this = std::move(toCopy);
}
-// static
-TextureHelper11 TextureHelper11::MakeAndReference(ID3D11Resource *genericResource)
+TextureHelper11::TextureHelper11(const TextureHelper11 &other)
+ : mFormatSet(other.mFormatSet), mExtents(other.mExtents), mSampleCount(other.mSampleCount)
{
- TextureHelper11 newHelper;
- newHelper.mTexture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(genericResource);
- newHelper.mTexture3D = d3d11::DynamicCastComObject<ID3D11Texture3D>(genericResource);
- newHelper.mTextureType = newHelper.mTexture2D ? GL_TEXTURE_2D : GL_TEXTURE_3D;
- newHelper.initDesc();
- return newHelper;
+ mData = other.mData;
}
-// static
-TextureHelper11 TextureHelper11::MakeAndPossess2D(ID3D11Texture2D *texToOwn)
+TextureHelper11::~TextureHelper11()
{
- TextureHelper11 newHelper;
- newHelper.mTexture2D = texToOwn;
- newHelper.mTextureType = GL_TEXTURE_2D;
- newHelper.initDesc();
- return newHelper;
}
-// static
-TextureHelper11 TextureHelper11::MakeAndPossess3D(ID3D11Texture3D *texToOwn)
+void TextureHelper11::getDesc(D3D11_TEXTURE2D_DESC *desc) const
{
- TextureHelper11 newHelper;
- newHelper.mTexture3D = texToOwn;
- newHelper.mTextureType = GL_TEXTURE_3D;
- newHelper.initDesc();
- return newHelper;
+ static_cast<ID3D11Texture2D *>(mData->object)->GetDesc(desc);
}
-void TextureHelper11::initDesc()
+void TextureHelper11::getDesc(D3D11_TEXTURE3D_DESC *desc) const
{
- if (mTextureType == GL_TEXTURE_2D)
- {
- ASSERT(!mTexture3D);
- D3D11_TEXTURE2D_DESC desc2D;
- mTexture2D->GetDesc(&desc2D);
+ static_cast<ID3D11Texture3D *>(mData->object)->GetDesc(desc);
+}
- mExtents.width = static_cast<int>(desc2D.Width);
- mExtents.height = static_cast<int>(desc2D.Height);
- mExtents.depth = 1;
- mFormat = desc2D.Format;
- mSampleCount = desc2D.SampleDesc.Count;
- }
- else
- {
- ASSERT(mTexture3D && mTextureType == GL_TEXTURE_3D);
- D3D11_TEXTURE3D_DESC desc3D;
- mTexture3D->GetDesc(&desc3D);
+void TextureHelper11::initDesc(const D3D11_TEXTURE2D_DESC &desc2D)
+{
+ mData->resourceType = ResourceType::Texture2D;
+ mExtents.width = static_cast<int>(desc2D.Width);
+ mExtents.height = static_cast<int>(desc2D.Height);
+ mExtents.depth = 1;
+ mSampleCount = desc2D.SampleDesc.Count;
+}
- mExtents.width = static_cast<int>(desc3D.Width);
- mExtents.height = static_cast<int>(desc3D.Height);
- mExtents.depth = static_cast<int>(desc3D.Depth);
- mFormat = desc3D.Format;
- mSampleCount = 1;
- }
+void TextureHelper11::initDesc(const D3D11_TEXTURE3D_DESC &desc3D)
+{
+ mData->resourceType = ResourceType::Texture3D;
+ mExtents.width = static_cast<int>(desc3D.Width);
+ mExtents.height = static_cast<int>(desc3D.Height);
+ mExtents.depth = static_cast<int>(desc3D.Depth);
+ mSampleCount = 1;
}
-TextureHelper11::~TextureHelper11()
+TextureHelper11 &TextureHelper11::operator=(TextureHelper11 &&other)
{
- SafeRelease(mTexture2D);
- SafeRelease(mTexture3D);
+ std::swap(mData, other.mData);
+ std::swap(mExtents, other.mExtents);
+ std::swap(mFormatSet, other.mFormatSet);
+ std::swap(mSampleCount, other.mSampleCount);
+ return *this;
}
-ID3D11Resource *TextureHelper11::getResource() const
+TextureHelper11 &TextureHelper11::operator=(const TextureHelper11 &other)
{
- return mTexture2D ? static_cast<ID3D11Resource *>(mTexture2D)
- : static_cast<ID3D11Resource *>(mTexture3D);
+ mData = other.mData;
+ mExtents = other.mExtents;
+ mFormatSet = other.mFormatSet;
+ mSampleCount = other.mSampleCount;
+ return *this;
}
-TextureHelper11 &TextureHelper11::operator=(TextureHelper11 &&texture)
+bool TextureHelper11::operator==(const TextureHelper11 &other) const
{
- SafeRelease(mTexture2D);
- SafeRelease(mTexture3D);
+ return mData->object == other.mData->object;
+}
- mTextureType = texture.mTextureType;
- mExtents = texture.mExtents;
- mFormat = texture.mFormat;
- mSampleCount = texture.mSampleCount;
- mTexture2D = texture.mTexture2D;
- mTexture3D = texture.mTexture3D;
- texture.reset();
- return *this;
+bool TextureHelper11::operator!=(const TextureHelper11 &other) const
+{
+ return mData->object != other.mData->object;
}
-void TextureHelper11::reset()
+bool UsePresentPathFast(const Renderer11 *renderer,
+ const gl::FramebufferAttachment *framebufferAttachment)
+{
+ if (framebufferAttachment == nullptr)
+ {
+ return false;
+ }
+
+ return (framebufferAttachment->type() == GL_FRAMEBUFFER_DEFAULT &&
+ renderer->presentPathFastEnabled());
+}
+
+bool UsePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled, GLenum type)
{
- mTextureType = GL_NONE;
- mExtents = gl::Extents();
- mFormat = DXGI_FORMAT_UNKNOWN;
- mSampleCount = 0;
- mTexture2D = nullptr;
- mTexture3D = nullptr;
+ // We should never have to deal with primitive restart workaround issue with GL_UNSIGNED_INT
+ // indices, since we restrict it via MAX_ELEMENT_INDEX.
+ return (!primitiveRestartFixedIndexEnabled && type == GL_UNSIGNED_SHORT);
}
-gl::ErrorOrResult<TextureHelper11> CreateStagingTexture(GLenum textureType,
- DXGI_FORMAT dxgiFormat,
- const gl::Extents &size,
- ID3D11Device *device)
+bool IsStreamingIndexData(const gl::Context *context, GLenum srcType)
{
- if (textureType == GL_TEXTURE_2D)
+ const auto &glState = context->getGLState();
+ gl::Buffer *glBuffer = glState.getVertexArray()->getElementArrayBuffer().get();
+
+ // Case 1: the indices are passed by pointer, which forces the streaming of index data
+ if (glBuffer == nullptr)
{
- D3D11_TEXTURE2D_DESC stagingDesc;
- stagingDesc.Width = size.width;
- stagingDesc.Height = size.height;
- stagingDesc.MipLevels = 1;
- stagingDesc.ArraySize = 1;
- stagingDesc.Format = dxgiFormat;
- stagingDesc.SampleDesc.Count = 1;
- stagingDesc.SampleDesc.Quality = 0;
- stagingDesc.Usage = D3D11_USAGE_STAGING;
- stagingDesc.BindFlags = 0;
- stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
- stagingDesc.MiscFlags = 0;
+ return true;
+ }
- ID3D11Texture2D *stagingTex = nullptr;
- HRESULT result = device->CreateTexture2D(&stagingDesc, nullptr, &stagingTex);
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "CreateStagingTextureFor failed, HRESULT: 0x%X.",
- result);
- }
+ bool primitiveRestartWorkaround =
+ UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), srcType);
+
+ BufferD3D *buffer = GetImplAs<BufferD3D>(glBuffer);
+ const GLenum dstType = (srcType == GL_UNSIGNED_INT || primitiveRestartWorkaround)
+ ? GL_UNSIGNED_INT
+ : GL_UNSIGNED_SHORT;
- return TextureHelper11::MakeAndPossess2D(stagingTex);
+ // Case 2a: the buffer can be used directly
+ if (buffer->supportsDirectBinding() && dstType == srcType)
+ {
+ return false;
}
- ASSERT(textureType == GL_TEXTURE_3D);
- D3D11_TEXTURE3D_DESC stagingDesc;
- stagingDesc.Width = size.width;
- stagingDesc.Height = size.height;
- stagingDesc.Depth = 1;
- stagingDesc.MipLevels = 1;
- stagingDesc.Format = dxgiFormat;
- stagingDesc.Usage = D3D11_USAGE_STAGING;
- stagingDesc.BindFlags = 0;
- stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
- stagingDesc.MiscFlags = 0;
+ // Case 2b: use a static translated copy or fall back to streaming
+ StaticIndexBufferInterface *staticBuffer = buffer->getStaticIndexBuffer();
+ if (staticBuffer == nullptr)
+ {
+ return true;
+ }
- ID3D11Texture3D *stagingTex = nullptr;
- HRESULT result = device->CreateTexture3D(&stagingDesc, nullptr, &stagingTex);
- if (FAILED(result))
+ if ((staticBuffer->getBufferSize() == 0) || (staticBuffer->getIndexType() != dstType))
{
- return gl::Error(GL_OUT_OF_MEMORY, "CreateStagingTextureFor failed, HRESULT: 0x%X.",
- result);
+ return true;
}
- return TextureHelper11::MakeAndPossess3D(stagingTex);
+ return false;
}
-bool UsePresentPathFast(const Renderer11 *renderer,
- const gl::FramebufferAttachment *framebufferAttachment)
+IndexStorageType ClassifyIndexStorage(const gl::State &glState,
+ const gl::Buffer *elementArrayBuffer,
+ GLenum elementType,
+ GLenum destElementType,
+ unsigned int offset,
+ bool *needsTranslation)
{
- if (framebufferAttachment == nullptr)
+ // No buffer bound means we are streaming from a client pointer.
+ if (!elementArrayBuffer || !IsOffsetAligned(elementType, offset))
{
- return false;
+ *needsTranslation = true;
+ return IndexStorageType::Dynamic;
}
- return (framebufferAttachment->type() == GL_FRAMEBUFFER_DEFAULT &&
- renderer->presentPathFastEnabled());
+ // The buffer can be used directly if the storage supports it and no translation needed.
+ BufferD3D *bufferD3D = GetImplAs<BufferD3D>(elementArrayBuffer);
+ if (bufferD3D->supportsDirectBinding() && destElementType == elementType)
+ {
+ *needsTranslation = false;
+ return IndexStorageType::Direct;
+ }
+
+ // Use a static copy when available.
+ StaticIndexBufferInterface *staticBuffer = bufferD3D->getStaticIndexBuffer();
+ if (staticBuffer != nullptr)
+ {
+ // Need to re-translate the static data if has never been used, or changed type.
+ *needsTranslation =
+ (staticBuffer->getBufferSize() == 0 || staticBuffer->getIndexType() != destElementType);
+ return IndexStorageType::Static;
+ }
+
+ // Static buffer not available, fall back to streaming.
+ *needsTranslation = true;
+ return IndexStorageType::Dynamic;
}
} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h
index 4925a2d227..3af51bb0f6 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h
@@ -11,12 +11,16 @@
#define LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_
#include <array>
+#include <functional>
#include <vector>
-#include "libANGLE/angletypes.h"
+#include "common/Color.h"
+
#include "libANGLE/Caps.h"
#include "libANGLE/Error.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
namespace gl
{
@@ -27,10 +31,10 @@ namespace rx
{
class Renderer11;
class RenderTarget11;
-struct WorkaroundsD3D;
struct Renderer11DeviceCaps;
-using RenderTargetArray = std::array<ID3D11RenderTargetView *, gl::IMPLEMENTATION_MAX_DRAW_BUFFERS>;
+using RenderTargetArray = std::array<RenderTarget11 *, gl::IMPLEMENTATION_MAX_DRAW_BUFFERS>;
+using RTVArray = std::array<ID3D11RenderTargetView *, gl::IMPLEMENTATION_MAX_DRAW_BUFFERS>;
namespace gl_d3d11
{
@@ -39,7 +43,7 @@ D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha);
D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp);
UINT8 ConvertColorMask(bool maskRed, bool maskGreen, bool maskBlue, bool maskAlpha);
-D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode);
+D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, gl::CullFaceMode cullMode);
D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison);
D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled);
@@ -48,9 +52,12 @@ D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp);
D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy, GLenum comparisonMode);
D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap);
+UINT ConvertMaxAnisotropy(float maxAnisotropy, D3D_FEATURE_LEVEL featureLevel);
D3D11_QUERY ConvertQueryType(GLenum queryType);
+UINT8 GetColorMask(const gl::InternalFormat &formatInfo);
+
} // namespace gl_d3d11
namespace d3d11_gl
@@ -60,10 +67,12 @@ unsigned int GetReservedVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel);
unsigned int GetReservedFragmentUniformVectors(D3D_FEATURE_LEVEL featureLevel);
-GLint GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel);
+gl::Version GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel);
void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, const Renderer11DeviceCaps &renderer11DeviceCaps, gl::Caps *caps,
gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions, gl::Limitations *limitations);
+void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy);
+
} // namespace d3d11_gl
namespace d3d11
@@ -108,32 +117,45 @@ struct PositionLayerTexCoord3DVertex
void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, float x, float y,
unsigned int layer, float u, float v, float s);
-template <typename T>
-struct PositionDepthColorVertex
+struct PositionVertex
{
- float x, y, z;
- T r, g, b, a;
+ float x, y, z, w;
};
-template <typename T>
-void SetPositionDepthColorVertex(PositionDepthColorVertex<T>* vertex, float x, float y, float z,
- const gl::Color<T> &color)
+struct BlendStateKey final
{
- vertex->x = x;
- vertex->y = y;
- vertex->z = z;
- vertex->r = color.red;
- vertex->g = color.green;
- vertex->b = color.blue;
- vertex->a = color.alpha;
-}
+ // This will zero-initialize the struct, including padding.
+ BlendStateKey();
+
+ gl::BlendState blendState;
+
+ // An int so struct size rounds nicely.
+ uint32_t rtvMax;
+
+ uint8_t rtvMasks[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
+};
+
+bool operator==(const BlendStateKey &a, const BlendStateKey &b);
+bool operator!=(const BlendStateKey &a, const BlendStateKey &b);
+
+struct RasterizerStateKey final
+{
+ // This will zero-initialize the struct, including padding.
+ RasterizerStateKey();
+
+ gl::RasterizerState rasterizerState;
-HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name);
+ // Use a 32-bit int to round the struct nicely.
+ uint32_t scissorEnabled;
+};
+
+bool operator==(const RasterizerStateKey &a, const RasterizerStateKey &b);
+bool operator!=(const RasterizerStateKey &a, const RasterizerStateKey &b);
template <typename outType>
outType* DynamicCastComObject(IUnknown* object)
{
- outType *outObject = NULL;
+ outType *outObject = nullptr;
HRESULT result = object->QueryInterface(__uuidof(outType), reinterpret_cast<void**>(&outObject));
if (SUCCEEDED(result))
{
@@ -142,7 +164,7 @@ outType* DynamicCastComObject(IUnknown* object)
else
{
SafeRelease(outObject);
- return NULL;
+ return nullptr;
}
}
@@ -161,143 +183,63 @@ inline bool isDeviceLostError(HRESULT errorCode)
}
}
-inline ID3D11VertexShader *CompileVS(ID3D11Device *device, const BYTE *byteCode, size_t N, const char *name)
-{
- ID3D11VertexShader *vs = nullptr;
- HRESULT result = device->CreateVertexShader(byteCode, N, nullptr, &vs);
- ASSERT(SUCCEEDED(result));
- if (SUCCEEDED(result))
- {
- SetDebugName(vs, name);
- return vs;
- }
- return nullptr;
-}
-
-template <unsigned int N>
-ID3D11VertexShader *CompileVS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name)
-{
- return CompileVS(device, byteCode, N, name);
-}
-
-inline ID3D11GeometryShader *CompileGS(ID3D11Device *device, const BYTE *byteCode, size_t N, const char *name)
-{
- ID3D11GeometryShader *gs = nullptr;
- HRESULT result = device->CreateGeometryShader(byteCode, N, nullptr, &gs);
- ASSERT(SUCCEEDED(result));
- if (SUCCEEDED(result))
- {
- SetDebugName(gs, name);
- return gs;
- }
- return nullptr;
-}
-
-template <unsigned int N>
-ID3D11GeometryShader *CompileGS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name)
+template <ResourceType ResourceT>
+class LazyResource : angle::NonCopyable
{
- return CompileGS(device, byteCode, N, name);
-}
+ public:
+ constexpr LazyResource() : mResource() {}
+ virtual ~LazyResource() {}
-inline ID3D11PixelShader *CompilePS(ID3D11Device *device, const BYTE *byteCode, size_t N, const char *name)
-{
- ID3D11PixelShader *ps = nullptr;
- HRESULT result = device->CreatePixelShader(byteCode, N, nullptr, &ps);
- ASSERT(SUCCEEDED(result));
- if (SUCCEEDED(result))
+ virtual gl::Error resolve(Renderer11 *renderer) = 0;
+ void reset() { mResource.reset(); }
+ GetD3D11Type<ResourceT> *get() const
{
- SetDebugName(ps, name);
- return ps;
+ ASSERT(mResource.valid());
+ return mResource.get();
}
- return nullptr;
-}
-
-template <unsigned int N>
-ID3D11PixelShader *CompilePS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name)
-{
- return CompilePS(device, byteCode, N, name);
-}
-
-template <typename ResourceType>
-class LazyResource : public angle::NonCopyable
-{
- public:
- LazyResource() : mResource(nullptr), mAssociatedDevice(nullptr) {}
- virtual ~LazyResource() { release(); }
- virtual ResourceType *resolve(ID3D11Device *device) = 0;
- void release() { SafeRelease(mResource); }
+ const Resource11<GetD3D11Type<ResourceT>> &getObj() const { return mResource; }
protected:
- void checkAssociatedDevice(ID3D11Device *device);
+ LazyResource(LazyResource &&other) : mResource(std::move(other.mResource)) {}
- ResourceType *mResource;
- ID3D11Device *mAssociatedDevice;
-};
+ // Specialized in the cpp file to avoid MSVS/Clang specific code.
+ gl::Error resolveImpl(Renderer11 *renderer,
+ const GetDescType<ResourceT> &desc,
+ GetInitDataType<ResourceT> *initData,
+ const char *name);
-template <typename ResourceType>
-void LazyResource<ResourceType>::checkAssociatedDevice(ID3D11Device *device)
-{
- ASSERT(mAssociatedDevice == nullptr || device == mAssociatedDevice);
- mAssociatedDevice = device;
-}
+ Resource11<GetD3D11Type<ResourceT>> mResource;
+};
template <typename D3D11ShaderType>
-class LazyShader final : public LazyResource<D3D11ShaderType>
+class LazyShader final : public LazyResource<GetResourceTypeFromD3D11<D3D11ShaderType>()>
{
public:
// All parameters must be constexpr. Not supported in VS2013.
- LazyShader(const BYTE *byteCode,
- size_t byteCodeSize,
- const char *name)
- : mByteCode(byteCode),
- mByteCodeSize(byteCodeSize),
- mName(name)
+ constexpr LazyShader(const BYTE *byteCode, size_t byteCodeSize, const char *name)
+ : mByteCode(byteCode, byteCodeSize), mName(name)
{
}
- D3D11ShaderType *resolve(ID3D11Device *device) override;
-
- private:
- const BYTE *mByteCode;
- size_t mByteCodeSize;
- const char *mName;
-};
-
-template <>
-inline ID3D11VertexShader *LazyShader<ID3D11VertexShader>::resolve(ID3D11Device *device)
-{
- checkAssociatedDevice(device);
- if (mResource == nullptr)
+ constexpr LazyShader(LazyShader &&shader)
+ : LazyResource<GetResourceTypeFromD3D11<D3D11ShaderType>()>(std::move(shader)),
+ mByteCode(std::move(shader.mByteCode)),
+ mName(shader.mName)
{
- mResource = CompileVS(device, mByteCode, mByteCodeSize, mName);
}
- return mResource;
-}
-template <>
-inline ID3D11GeometryShader *LazyShader<ID3D11GeometryShader>::resolve(ID3D11Device *device)
-{
- checkAssociatedDevice(device);
- if (mResource == nullptr)
+ gl::Error resolve(Renderer11 *renderer) override
{
- mResource = CompileGS(device, mByteCode, mByteCodeSize, mName);
+ return this->resolveImpl(renderer, mByteCode, nullptr, mName);
}
- return mResource;
-}
-template <>
-inline ID3D11PixelShader *LazyShader<ID3D11PixelShader>::resolve(ID3D11Device *device)
-{
- checkAssociatedDevice(device);
- if (mResource == nullptr)
- {
- mResource = CompilePS(device, mByteCode, mByteCodeSize, mName);
- }
- return mResource;
-}
+ private:
+ ShaderData mByteCode;
+ const char *mName;
+};
-class LazyInputLayout final : public LazyResource<ID3D11InputLayout>
+class LazyInputLayout final : public LazyResource<ResourceType::InputLayout>
{
public:
LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc,
@@ -305,22 +247,22 @@ class LazyInputLayout final : public LazyResource<ID3D11InputLayout>
const BYTE *byteCode,
size_t byteCodeLen,
const char *debugName);
+ ~LazyInputLayout() override;
- ID3D11InputLayout *resolve(ID3D11Device *device) override;
+ gl::Error resolve(Renderer11 *renderer) override;
private:
- std::vector<D3D11_INPUT_ELEMENT_DESC> mInputDesc;
- size_t mByteCodeLen;
- const BYTE *mByteCode;
+ InputElementArray mInputDesc;
+ ShaderData mByteCode;
const char *mDebugName;
};
-class LazyBlendState final : public LazyResource<ID3D11BlendState>
+class LazyBlendState final : public LazyResource<ResourceType::BlendState>
{
public:
LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName);
- ID3D11BlendState *resolve(ID3D11Device *device) override;
+ gl::Error resolve(Renderer11 *renderer) override;
private:
D3D11_BLEND_DESC mDesc;
@@ -342,48 +284,147 @@ void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBuffer, c
}
}
-WorkaroundsD3D GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel);
+angle::WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps,
+ const DXGI_ADAPTER_DESC &adapterDesc);
+
+enum ReservedConstantBufferSlot
+{
+ RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK = 0,
+ RESERVED_CONSTANT_BUFFER_SLOT_DRIVER = 1,
+
+ RESERVED_CONSTANT_BUFFER_SLOT_COUNT = 2
+};
+
+void InitConstantBufferDesc(D3D11_BUFFER_DESC *constantBufferDescription, size_t byteWidth);
} // namespace d3d11
+struct GenericData
+{
+ GenericData() {}
+ ~GenericData()
+ {
+ if (object)
+ {
+ // We can have a nullptr factory when holding passed-in resources.
+ if (manager)
+ {
+ manager->onReleaseGeneric(resourceType, object);
+ manager = nullptr;
+ }
+ object->Release();
+ object = nullptr;
+ }
+ }
+
+ ResourceType resourceType = ResourceType::Last;
+ ID3D11Resource *object = nullptr;
+ ResourceManager11 *manager = nullptr;
+};
+
// A helper class which wraps a 2D or 3D texture.
-class TextureHelper11 : angle::NonCopyable
+class TextureHelper11 : public Resource11Base<ID3D11Resource, std::shared_ptr, GenericData>
{
public:
TextureHelper11();
- TextureHelper11(TextureHelper11 &&toCopy);
- ~TextureHelper11();
- TextureHelper11 &operator=(TextureHelper11 &&texture);
-
- static TextureHelper11 MakeAndReference(ID3D11Resource *genericResource);
- static TextureHelper11 MakeAndPossess2D(ID3D11Texture2D *texToOwn);
- static TextureHelper11 MakeAndPossess3D(ID3D11Texture3D *texToOwn);
-
- GLenum getTextureType() const { return mTextureType; }
+ TextureHelper11(TextureHelper11 &&other);
+ TextureHelper11(const TextureHelper11 &other);
+ ~TextureHelper11() override;
+ TextureHelper11 &operator=(TextureHelper11 &&other);
+ TextureHelper11 &operator=(const TextureHelper11 &other);
+
+ bool is2D() const { return mData->resourceType == ResourceType::Texture2D; }
+ bool is3D() const { return mData->resourceType == ResourceType::Texture3D; }
+ ResourceType getTextureType() const { return mData->resourceType; }
gl::Extents getExtents() const { return mExtents; }
- DXGI_FORMAT getFormat() const { return mFormat; }
+ DXGI_FORMAT getFormat() const { return mFormatSet->texFormat; }
+ const d3d11::Format &getFormatSet() const { return *mFormatSet; }
int getSampleCount() const { return mSampleCount; }
- ID3D11Texture2D *getTexture2D() const { return mTexture2D; }
- ID3D11Texture3D *getTexture3D() const { return mTexture3D; }
- ID3D11Resource *getResource() const;
+
+ template <typename DescT, typename ResourceT>
+ void init(Resource11<ResourceT> &&texture, const DescT &desc, const d3d11::Format &format)
+ {
+ std::swap(mData->manager, texture.mData->manager);
+
+ // Can't use std::swap because texture is typed, and here we use ID3D11Resource.
+ ID3D11Resource *temp = mData->object;
+ mData->object = texture.mData->object;
+ texture.mData->object = static_cast<ResourceT *>(temp);
+
+ mFormatSet = &format;
+ initDesc(desc);
+ }
+
+ template <typename ResourceT>
+ void set(ResourceT *object, const d3d11::Format &format)
+ {
+ ASSERT(!valid());
+ mFormatSet = &format;
+ mData->object = object;
+ mData->manager = nullptr;
+
+ GetDescFromD3D11<ResourceT> desc;
+ getDesc(&desc);
+ initDesc(desc);
+ }
+
+ bool operator==(const TextureHelper11 &other) const;
+ bool operator!=(const TextureHelper11 &other) const;
+
+ void getDesc(D3D11_TEXTURE2D_DESC *desc) const;
+ void getDesc(D3D11_TEXTURE3D_DESC *desc) const;
private:
- void reset();
- void initDesc();
+ void initDesc(const D3D11_TEXTURE2D_DESC &desc2D);
+ void initDesc(const D3D11_TEXTURE3D_DESC &desc3D);
- GLenum mTextureType;
+ const d3d11::Format *mFormatSet;
gl::Extents mExtents;
- DXGI_FORMAT mFormat;
int mSampleCount;
- ID3D11Texture2D *mTexture2D;
- ID3D11Texture3D *mTexture3D;
};
-gl::ErrorOrResult<TextureHelper11> CreateStagingTexture(GLenum textureType,
- DXGI_FORMAT dxgiFormat,
- const gl::Extents &size,
- ID3D11Device *device);
+enum class StagingAccess
+{
+ READ,
+ READ_WRITE,
+};
bool UsePresentPathFast(const Renderer11 *renderer, const gl::FramebufferAttachment *colorbuffer);
+bool UsePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled, GLenum type);
+bool IsStreamingIndexData(const gl::Context *context, GLenum srcType);
+
+enum class IndexStorageType
+{
+ // Dynamic indexes are re-streamed every frame. They come from a client data pointer or
+ // from buffers that are updated frequently.
+ Dynamic,
+
+ // Static indexes are translated from the original storage once, and re-used multiple times.
+ Static,
+
+ // Direct indexes are never transated and are used directly from the source buffer. They are
+ // the fastest available path.
+ Direct,
+
+ // Not a real storage type.
+ Invalid,
+};
+
+IndexStorageType ClassifyIndexStorage(const gl::State &glState,
+ const gl::Buffer *elementArrayBuffer,
+ GLenum elementType,
+ GLenum destElementType,
+ unsigned int offset,
+ bool *needsTranslation);
+
+// Used for state change notifications between buffers and vertex arrays.
+using OnBufferDataDirtyBinding = angle::ChannelBinding<size_t, const gl::Context *>;
+using OnBufferDataDirtyChannel = angle::BroadcastChannel<size_t, const gl::Context *>;
+using OnBufferDataDirtyReceiver = angle::SignalReceiver<size_t, const gl::Context *>;
+
+// Used for state change notifications between RenderTarget11 and Framebuffer11.
+using OnRenderTargetDirtyBinding = angle::ChannelBinding<size_t, const gl::Context *>;
+using OnRenderTargetDirtyChannel = angle::BroadcastChannel<size_t, const gl::Context *>;
+using OnRenderTargetDirtyReceiver = angle::SignalReceiver<size_t, const gl::Context *>;
} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl
index 2b3e1ebe4c..48f5b427ec 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl
@@ -1,13 +1,152 @@
-// Assume we are in SM4+, which has 8 color outputs
+//
+// Copyright (c) 2017 The ANGLE Project. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
-void VS_ClearFloat( in float3 inPosition : POSITION, in float4 inColor : COLOR,
- out float4 outPosition : SV_POSITION, out float4 outColor : COLOR)
+// Clear11.hlsl: Shaders for clearing RTVs and DSVs using draw calls and
+// specifying float depth values and either float, uint or sint clear colors.
+// Notes:
+// - UINT & SINT clears can only be compiled with FL10+
+// - VS_Clear_FL9 requires a VB to be bound with vertices to create
+// a primitive covering the entire surface (in clip co-ordinates)
+
+// Constants
+static const float2 g_Corners[6] =
+{
+ float2(-1.0f, 1.0f),
+ float2( 1.0f, -1.0f),
+ float2(-1.0f, -1.0f),
+ float2(-1.0f, 1.0f),
+ float2( 1.0f, 1.0f),
+ float2( 1.0f, -1.0f),
+};
+
+// Vertex Shaders
+void VS_Clear(in uint id : SV_VertexID,
+ out float4 outPosition : SV_POSITION)
+{
+ float2 corner = g_Corners[id];
+ outPosition = float4(corner.x, corner.y, 0.0f, 1.0f);
+}
+
+void VS_Multiview_Clear(in uint id : SV_VertexID,
+ in uint instanceID : SV_InstanceID,
+ out float4 outPosition : SV_POSITION,
+ out uint outLayerID : TEXCOORD0)
+{
+ float2 corner = g_Corners[id];
+ outPosition = float4(corner.x, corner.y, 0.0f, 1.0f);
+ outLayerID = instanceID;
+}
+
+void VS_Clear_FL9( in float4 inPosition : POSITION,
+ out float4 outPosition : SV_POSITION)
+{
+ outPosition = inPosition;
+}
+
+// Geometry shader for clearing multiview layered textures
+struct GS_INPUT
+{
+ float4 inPosition : SV_Position;
+ uint inLayerID : TEXCOORD0;
+};
+
+struct GS_OUTPUT
{
- outPosition = float4(inPosition, 1.0f);
- outColor = inColor;
+ float4 outPosition : SV_Position;
+ uint outLayerID : SV_RenderTargetArrayIndex;
+};
+
+[maxvertexcount(3)]
+void GS_Multiview_Clear(triangle GS_INPUT input[3], inout TriangleStream<GS_OUTPUT> outStream)
+{
+ GS_OUTPUT output = (GS_OUTPUT)0;
+ for (int i = 0; i < 3; i++)
+ {
+ output.outPosition = input[i].inPosition;
+ output.outLayerID = input[i].inLayerID;
+ outStream.Append(output);
+ }
+ outStream.RestartStrip();
+}
+
+// Pixel Shader Constant Buffers
+cbuffer ColorAndDepthDataFloat : register(b0)
+{
+ float4 color_Float : packoffset(c0);
+ float zValueF_Float : packoffset(c1);
+}
+
+cbuffer ColorAndDepthDataSint : register(b0)
+{
+ int4 color_Sint : packoffset(c0);
+ float zValueF_Sint : packoffset(c1);
+}
+
+cbuffer ColorAndDepthDataUint : register(b0)
+{
+ uint4 color_Uint : packoffset(c0);
+ float zValueF_Uint : packoffset(c1);
}
-struct PS_OutputFloat
+cbuffer DepthOnlyData : register(b0)
+{
+ float zValue_Depth : packoffset(c1);
+}
+
+// Pixel Shader Output Structs
+struct PS_OutputFloat_FL9
+{
+ float4 color0 : SV_TARGET0;
+ float4 color1 : SV_TARGET1;
+ float4 color2 : SV_TARGET2;
+ float4 color3 : SV_TARGET3;
+ float depth : SV_DEPTH;
+};
+
+struct PS_OutputFloat1
+{
+ float4 color0 : SV_TARGET0;
+ float depth : SV_DEPTH;
+};
+
+struct PS_OutputFloat2
+{
+ float4 color0 : SV_TARGET0;
+ float4 color1 : SV_TARGET1;
+ float depth : SV_DEPTH;
+};
+
+struct PS_OutputFloat3
+{
+ float4 color0 : SV_TARGET0;
+ float4 color1 : SV_TARGET1;
+ float4 color2 : SV_TARGET2;
+ float depth : SV_DEPTH;
+};
+
+struct PS_OutputFloat4
+{
+ float4 color0 : SV_TARGET0;
+ float4 color1 : SV_TARGET1;
+ float4 color2 : SV_TARGET2;
+ float4 color3 : SV_TARGET3;
+ float depth : SV_DEPTH;
+};
+
+struct PS_OutputFloat5
+{
+ float4 color0 : SV_TARGET0;
+ float4 color1 : SV_TARGET1;
+ float4 color2 : SV_TARGET2;
+ float4 color3 : SV_TARGET3;
+ float4 color4 : SV_TARGET4;
+ float depth : SV_DEPTH;
+};
+
+struct PS_OutputFloat6
{
float4 color0 : SV_TARGET0;
float4 color1 : SV_TARGET1;
@@ -15,50 +154,98 @@ struct PS_OutputFloat
float4 color3 : SV_TARGET3;
float4 color4 : SV_TARGET4;
float4 color5 : SV_TARGET5;
- float4 color6 : SV_TARGET6;
- float4 color7 : SV_TARGET7;
+ float depth : SV_DEPTH;
};
-PS_OutputFloat PS_ClearFloat(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR)
+struct PS_OutputFloat7
{
- PS_OutputFloat outColor;
- outColor.color0 = inColor;
- outColor.color1 = inColor;
- outColor.color2 = inColor;
- outColor.color3 = inColor;
- outColor.color4 = inColor;
- outColor.color5 = inColor;
- outColor.color6 = inColor;
- outColor.color7 = inColor;
- return outColor;
-}
+ float4 color0 : SV_TARGET0;
+ float4 color1 : SV_TARGET1;
+ float4 color2 : SV_TARGET2;
+ float4 color3 : SV_TARGET3;
+ float4 color4 : SV_TARGET4;
+ float4 color5 : SV_TARGET5;
+ float4 color6 : SV_TARGET6;
+ float depth : SV_DEPTH;
+};
-struct PS_OutputFloat_FL9
+struct PS_OutputFloat8
{
float4 color0 : SV_TARGET0;
float4 color1 : SV_TARGET1;
float4 color2 : SV_TARGET2;
float4 color3 : SV_TARGET3;
+ float4 color4 : SV_TARGET4;
+ float4 color5 : SV_TARGET5;
+ float4 color6 : SV_TARGET6;
+ float4 color7 : SV_TARGET7;
+ float depth : SV_DEPTH;
};
-PS_OutputFloat_FL9 PS_ClearFloat_FL9(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR)
+struct PS_OutputUint1
{
- PS_OutputFloat_FL9 outColor;
- outColor.color0 = inColor;
- outColor.color1 = inColor;
- outColor.color2 = inColor;
- outColor.color3 = inColor;
- return outColor;
-}
+ uint4 color0 : SV_TARGET0;
+ float depth : SV_DEPTH;
+};
-void VS_ClearUint( in float3 inPosition : POSITION, in uint4 inColor : COLOR,
- out float4 outPosition : SV_POSITION, out uint4 outColor : COLOR)
+struct PS_OutputUint2
{
- outPosition = float4(inPosition, 1.0f);
- outColor = inColor;
-}
+ uint4 color0 : SV_TARGET0;
+ uint4 color1 : SV_TARGET1;
+ float depth : SV_DEPTH;
+};
+
+struct PS_OutputUint3
+{
+ uint4 color0 : SV_TARGET0;
+ uint4 color1 : SV_TARGET1;
+ uint4 color2 : SV_TARGET2;
+ float depth : SV_DEPTH;
+};
+
+struct PS_OutputUint4
+{
+ uint4 color0 : SV_TARGET0;
+ uint4 color1 : SV_TARGET1;
+ uint4 color2 : SV_TARGET2;
+ uint4 color3 : SV_TARGET3;
+ float depth : SV_DEPTH;
+};
+
+struct PS_OutputUint5
+{
+ uint4 color0 : SV_TARGET0;
+ uint4 color1 : SV_TARGET1;
+ uint4 color2 : SV_TARGET2;
+ uint4 color3 : SV_TARGET3;
+ uint4 color4 : SV_TARGET4;
+ float depth : SV_DEPTH;
+};
+
+struct PS_OutputUint6
+{
+ uint4 color0 : SV_TARGET0;
+ uint4 color1 : SV_TARGET1;
+ uint4 color2 : SV_TARGET2;
+ uint4 color3 : SV_TARGET3;
+ uint4 color4 : SV_TARGET4;
+ uint4 color5 : SV_TARGET5;
+ float depth : SV_DEPTH;
+};
+
+struct PS_OutputUint7
+{
+ uint4 color0 : SV_TARGET0;
+ uint4 color1 : SV_TARGET1;
+ uint4 color2 : SV_TARGET2;
+ uint4 color3 : SV_TARGET3;
+ uint4 color4 : SV_TARGET4;
+ uint4 color5 : SV_TARGET5;
+ uint4 color6 : SV_TARGET6;
+ float depth : SV_DEPTH;
+};
-struct PS_OutputUint
+struct PS_OutputUint8
{
uint4 color0 : SV_TARGET0;
uint4 color1 : SV_TARGET1;
@@ -68,31 +255,73 @@ struct PS_OutputUint
uint4 color5 : SV_TARGET5;
uint4 color6 : SV_TARGET6;
uint4 color7 : SV_TARGET7;
+ float depth : SV_DEPTH;
};
-PS_OutputUint PS_ClearUint(in float4 inPosition : SV_POSITION, in uint4 inColor : COLOR)
+struct PS_OutputSint1
{
- PS_OutputUint outColor;
- outColor.color0 = inColor;
- outColor.color1 = inColor;
- outColor.color2 = inColor;
- outColor.color3 = inColor;
- outColor.color4 = inColor;
- outColor.color5 = inColor;
- outColor.color6 = inColor;
- outColor.color7 = inColor;
- return outColor;
-}
+ int4 color0 : SV_TARGET0;
+ float depth : SV_DEPTH;
+};
+struct PS_OutputSint2
+{
+ int4 color0 : SV_TARGET0;
+ int4 color1 : SV_TARGET1;
+ float depth : SV_DEPTH;
+};
-void VS_ClearSint( in float3 inPosition : POSITION, in int4 inColor : COLOR,
- out float4 outPosition : SV_POSITION, out int4 outColor : COLOR)
+struct PS_OutputSint3
{
- outPosition = float4(inPosition, 1.0f);
- outColor = inColor;
-}
+ int4 color0 : SV_TARGET0;
+ int4 color1 : SV_TARGET1;
+ int4 color2 : SV_TARGET2;
+ float depth : SV_DEPTH;
+};
+
+struct PS_OutputSint4
+{
+ int4 color0 : SV_TARGET0;
+ int4 color1 : SV_TARGET1;
+ int4 color2 : SV_TARGET2;
+ int4 color3 : SV_TARGET3;
+ float depth : SV_DEPTH;
+};
+
+struct PS_OutputSint5
+{
+ int4 color0 : SV_TARGET0;
+ int4 color1 : SV_TARGET1;
+ int4 color2 : SV_TARGET2;
+ int4 color3 : SV_TARGET3;
+ int4 color4 : SV_TARGET4;
+ float depth : SV_DEPTH;
+};
+
+struct PS_OutputSint6
+{
+ int4 color0 : SV_TARGET0;
+ int4 color1 : SV_TARGET1;
+ int4 color2 : SV_TARGET2;
+ int4 color3 : SV_TARGET3;
+ int4 color4 : SV_TARGET4;
+ int4 color5 : SV_TARGET5;
+ float depth : SV_DEPTH;
+};
+
+struct PS_OutputSint7
+{
+ int4 color0 : SV_TARGET0;
+ int4 color1 : SV_TARGET1;
+ int4 color2 : SV_TARGET2;
+ int4 color3 : SV_TARGET3;
+ int4 color4 : SV_TARGET4;
+ int4 color5 : SV_TARGET5;
+ int4 color6 : SV_TARGET6;
+ float depth : SV_DEPTH;
+};
-struct PS_OutputSint
+struct PS_OutputSint8
{
int4 color0 : SV_TARGET0;
int4 color1 : SV_TARGET1;
@@ -102,18 +331,305 @@ struct PS_OutputSint
int4 color5 : SV_TARGET5;
int4 color6 : SV_TARGET6;
int4 color7 : SV_TARGET7;
+ float depth : SV_DEPTH;
+};
+
+struct PS_OutputDepth
+{
+ float depth : SV_DEPTH;
};
-PS_OutputSint PS_ClearSint(in float4 inPosition : SV_POSITION, in int4 inColor : COLOR)
+// Pixel Shaders
+PS_OutputFloat_FL9 PS_ClearFloat_FL9(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputFloat_FL9 outData;
+ outData.color0 = color_Float;
+ outData.color1 = color_Float;
+ outData.color2 = color_Float;
+ outData.color3 = color_Float;
+ outData.depth = zValueF_Float;
+ return outData;
+}
+
+PS_OutputFloat1 PS_ClearFloat1(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputFloat1 outData;
+ outData.color0 = color_Float;
+ outData.depth = zValueF_Float;
+ return outData;
+}
+
+PS_OutputFloat2 PS_ClearFloat2(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputFloat2 outData;
+ outData.color0 = color_Float;
+ outData.color1 = color_Float;
+ outData.depth = zValueF_Float;
+ return outData;
+}
+
+PS_OutputFloat3 PS_ClearFloat3(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputFloat3 outData;
+ outData.color0 = color_Float;
+ outData.color1 = color_Float;
+ outData.color2 = color_Float;
+ outData.depth = zValueF_Float;
+ return outData;
+}
+
+PS_OutputFloat4 PS_ClearFloat4(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputFloat4 outData;
+ outData.color0 = color_Float;
+ outData.color1 = color_Float;
+ outData.color2 = color_Float;
+ outData.color3 = color_Float;
+ outData.depth = zValueF_Float;
+ return outData;
+}
+
+PS_OutputFloat5 PS_ClearFloat5(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputFloat5 outData;
+ outData.color0 = color_Float;
+ outData.color1 = color_Float;
+ outData.color2 = color_Float;
+ outData.color3 = color_Float;
+ outData.color4 = color_Float;
+ outData.depth = zValueF_Float;
+ return outData;
+}
+
+PS_OutputFloat6 PS_ClearFloat6(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputFloat6 outData;
+ outData.color0 = color_Float;
+ outData.color1 = color_Float;
+ outData.color2 = color_Float;
+ outData.color3 = color_Float;
+ outData.color4 = color_Float;
+ outData.color5 = color_Float;
+ outData.depth = zValueF_Float;
+ return outData;
+}
+
+PS_OutputFloat7 PS_ClearFloat7(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputFloat7 outData;
+ outData.color0 = color_Float;
+ outData.color1 = color_Float;
+ outData.color2 = color_Float;
+ outData.color3 = color_Float;
+ outData.color4 = color_Float;
+ outData.color5 = color_Float;
+ outData.color6 = color_Float;
+ outData.depth = zValueF_Float;
+ return outData;
+}
+
+PS_OutputFloat8 PS_ClearFloat8(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputFloat8 outData;
+ outData.color0 = color_Float;
+ outData.color1 = color_Float;
+ outData.color2 = color_Float;
+ outData.color3 = color_Float;
+ outData.color4 = color_Float;
+ outData.color5 = color_Float;
+ outData.color6 = color_Float;
+ outData.color7 = color_Float;
+ outData.depth = zValueF_Float;
+ return outData;
+}
+
+PS_OutputUint1 PS_ClearUint1(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputUint1 outData;
+ outData.color0 = color_Uint;
+ outData.depth = zValueF_Uint;
+ return outData;
+}
+
+PS_OutputUint2 PS_ClearUint2(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputUint2 outData;
+ outData.color0 = color_Uint;
+ outData.color1 = color_Uint;
+ outData.depth = zValueF_Uint;
+ return outData;
+}
+
+PS_OutputUint3 PS_ClearUint3(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputUint3 outData;
+ outData.color0 = color_Uint;
+ outData.color1 = color_Uint;
+ outData.color2 = color_Uint;
+ outData.depth = zValueF_Uint;
+ return outData;
+}
+
+PS_OutputUint4 PS_ClearUint4(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputUint4 outData;
+ outData.color0 = color_Uint;
+ outData.color1 = color_Uint;
+ outData.color2 = color_Uint;
+ outData.color3 = color_Uint;
+ outData.depth = zValueF_Uint;
+ return outData;
+}
+
+PS_OutputUint5 PS_ClearUint5(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputUint5 outData;
+ outData.color0 = color_Uint;
+ outData.color1 = color_Uint;
+ outData.color2 = color_Uint;
+ outData.color3 = color_Uint;
+ outData.color4 = color_Uint;
+ outData.depth = zValueF_Uint;
+ return outData;
+}
+
+PS_OutputUint6 PS_ClearUint6(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputUint6 outData;
+ outData.color0 = color_Uint;
+ outData.color1 = color_Uint;
+ outData.color2 = color_Uint;
+ outData.color3 = color_Uint;
+ outData.color4 = color_Uint;
+ outData.color5 = color_Uint;
+ outData.depth = zValueF_Uint;
+ return outData;
+}
+
+PS_OutputUint7 PS_ClearUint7(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputUint7 outData;
+ outData.color0 = color_Uint;
+ outData.color1 = color_Uint;
+ outData.color2 = color_Uint;
+ outData.color3 = color_Uint;
+ outData.color4 = color_Uint;
+ outData.color5 = color_Uint;
+ outData.color6 = color_Uint;
+ outData.depth = zValueF_Uint;
+ return outData;
+}
+
+PS_OutputUint8 PS_ClearUint8(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputUint8 outData;
+ outData.color0 = color_Uint;
+ outData.color1 = color_Uint;
+ outData.color2 = color_Uint;
+ outData.color3 = color_Uint;
+ outData.color4 = color_Uint;
+ outData.color5 = color_Uint;
+ outData.color6 = color_Uint;
+ outData.color7 = color_Uint;
+ outData.depth = zValueF_Uint;
+ return outData;
+}
+
+PS_OutputSint1 PS_ClearSint1(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputSint1 outData;
+ outData.color0 = color_Sint;
+ outData.depth = zValueF_Sint;
+ return outData;
+}
+
+PS_OutputSint2 PS_ClearSint2(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputSint2 outData;
+ outData.color0 = color_Sint;
+ outData.color1 = color_Sint;
+ outData.depth = zValueF_Sint;
+ return outData;
+}
+
+PS_OutputSint3 PS_ClearSint3(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputSint3 outData;
+ outData.color0 = color_Sint;
+ outData.color1 = color_Sint;
+ outData.color2 = color_Sint;
+ outData.depth = zValueF_Sint;
+ return outData;
+}
+
+PS_OutputSint4 PS_ClearSint4(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputSint4 outData;
+ outData.color0 = color_Sint;
+ outData.color1 = color_Sint;
+ outData.color2 = color_Sint;
+ outData.color3 = color_Sint;
+ outData.depth = zValueF_Sint;
+ return outData;
+}
+
+PS_OutputSint5 PS_ClearSint5(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputSint5 outData;
+ outData.color0 = color_Sint;
+ outData.color1 = color_Sint;
+ outData.color2 = color_Sint;
+ outData.color3 = color_Sint;
+ outData.color4 = color_Sint;
+ outData.depth = zValueF_Sint;
+ return outData;
+}
+
+PS_OutputSint6 PS_ClearSint6(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputSint6 outData;
+ outData.color0 = color_Sint;
+ outData.color1 = color_Sint;
+ outData.color2 = color_Sint;
+ outData.color3 = color_Sint;
+ outData.color4 = color_Sint;
+ outData.color5 = color_Sint;
+ outData.depth = zValueF_Sint;
+ return outData;
+}
+
+PS_OutputSint7 PS_ClearSint7(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputSint7 outData;
+ outData.color0 = color_Sint;
+ outData.color1 = color_Sint;
+ outData.color2 = color_Sint;
+ outData.color3 = color_Sint;
+ outData.color4 = color_Sint;
+ outData.color5 = color_Sint;
+ outData.color6 = color_Sint;
+ outData.depth = zValueF_Sint;
+ return outData;
+}
+
+PS_OutputSint8 PS_ClearSint8(in float4 inPosition : SV_POSITION)
+{
+ PS_OutputSint8 outData;
+ outData.color0 = color_Sint;
+ outData.color1 = color_Sint;
+ outData.color2 = color_Sint;
+ outData.color3 = color_Sint;
+ outData.color4 = color_Sint;
+ outData.color5 = color_Sint;
+ outData.color6 = color_Sint;
+ outData.color7 = color_Sint;
+ outData.depth = zValueF_Sint;
+ return outData;
+}
+
+PS_OutputDepth PS_ClearDepth(in float4 inPosition : SV_POSITION)
{
- PS_OutputSint outColor;
- outColor.color0 = inColor;
- outColor.color1 = inColor;
- outColor.color2 = inColor;
- outColor.color3 = inColor;
- outColor.color4 = inColor;
- outColor.color5 = inColor;
- outColor.color6 = inColor;
- outColor.color7 = inColor;
- return outColor;
+ PS_OutputDepth outData;
+ outData.depth = zValue_Depth;
+ return outData;
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/MultiplyAlpha.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/MultiplyAlpha.hlsl
new file mode 100644
index 0000000000..0d10b8eafa
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/MultiplyAlpha.hlsl
@@ -0,0 +1,131 @@
+Texture2D<float4> TextureF : register(t0);
+Texture2D<uint4> TextureUI : register(t0);
+
+SamplerState Sampler : register(s0);
+
+// Notation:
+// PM: premultiply, UM: unmulitply, PT: passthrough
+// F: float, U: uint
+
+// Float to float LUMA
+float4 PS_FtoF_PM_LUMA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ float4 color = TextureF.Sample(Sampler, inTexCoord).rgba;
+ color.rgb = color.r * color.a;
+ color.a = 1.0f;
+ return color;
+}
+float4 PS_FtoF_UM_LUMA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ float4 color = TextureF.Sample(Sampler, inTexCoord).rgba;
+ if (color.a > 0.0f)
+ {
+ color.rgb = color.r / color.a;
+ }
+ color.a = 1.0f;
+ return color;
+}
+
+// Float to float LUMAALPHA
+float4 PS_FtoF_PM_LUMAALPHA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ float4 color = TextureF.Sample(Sampler, inTexCoord).rgba;
+ color.rgb = color.r * color.a;
+ return color;
+}
+
+float4 PS_FtoF_UM_LUMAALPHA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ float4 color = TextureF.Sample(Sampler, inTexCoord).rgba;
+ if (color.a > 0.0f)
+ {
+ color.rgb = color.r / color.a;
+ }
+ return color;
+}
+
+// Float to float RGBA
+float4 PS_FtoF_PM_RGBA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ float4 color = TextureF.Sample(Sampler, inTexCoord).rgba;
+ color.rgb *= color.a;
+ return color;
+}
+
+float4 PS_FtoF_UM_RGBA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ float4 color = TextureF.Sample(Sampler, inTexCoord).rgba;
+ if (color.a > 0.0f)
+ {
+ color.rgb /= color.a;
+ }
+ return color;
+}
+
+// Float to float RGB
+float4 PS_FtoF_PM_RGB(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ float4 color = TextureF.Sample(Sampler, inTexCoord).rgba;
+ color.rgb *= color.a;
+ color.a = 1.0f;
+ return color;
+}
+
+float4 PS_FtoF_UM_RGB(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ float4 color = TextureF.Sample(Sampler, inTexCoord).rgba;
+ if (color.a > 0.0f)
+ {
+ color.rgb /= color.a;
+ }
+ color.a = 1.0f;
+ return color;
+}
+
+// Float to uint RGBA
+uint4 PS_FtoU_PT_RGBA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ float4 color = TextureF.Sample(Sampler, inTexCoord).rgba;
+ return uint4(color * 255);
+}
+
+uint4 PS_FtoU_PM_RGBA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ float4 color = TextureF.Sample(Sampler, inTexCoord).rgba;
+ color.rgb *= color.a;
+ return uint4(color * 255);
+}
+
+uint4 PS_FtoU_UM_RGBA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ float4 color = TextureF.Sample(Sampler, inTexCoord).rgba;
+ if (color.a > 0.0f)
+ {
+ color.rgb /= color.a;
+ }
+ return uint4(color * 255);
+}
+
+// Float to uint RGB
+uint4 PS_FtoU_PT_RGB(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ float4 color = TextureF.Sample(Sampler, inTexCoord).rgba;
+ return uint4(color.rgb * 255, 1);
+}
+
+uint4 PS_FtoU_PM_RGB(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ float4 color = TextureF.Sample(Sampler, inTexCoord).rgba;
+ color.rgb *= color.a;
+ return uint4(color.rgb * 255, 1);
+}
+
+uint4 PS_FtoU_UM_RGB(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ float4 color = TextureF.Sample(Sampler, inTexCoord).rgba;
+ if (color.a > 0.0f)
+ {
+ color.rgb /= color.a;
+ }
+ return uint4(color.rgb * 255, 1);
+}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl
index 8671c39fb7..0b1a5ad169 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl
@@ -1,4 +1,5 @@
Texture2D<float4> TextureF : register(t0);
+Texture2DMS<float4> TextureF_MS: register(t0);
Texture2D<uint4> TextureUI : register(t0);
Texture2D<int4> TextureI : register(t0);
@@ -21,6 +22,16 @@ float4 PS_PassthroughRGBA2D(in float4 inPosition : SV_POSITION, in float2 inTexC
return TextureF.Sample(Sampler, inTexCoord).rgba;
}
+float4 PS_PassthroughA2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ return float4(0.0f, 0.0f, 0.0f, TextureF.Sample(Sampler, inTexCoord).a);
+}
+
+float4 PS_PassthroughRGBA2DMS(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCORD0, in uint inSampleIndex : SV_SAMPLEINDEX) : SV_TARGET0
+{
+ return TextureF_MS.sample[inSampleIndex][inTexCoord].rgba;
+}
+
uint4 PS_PassthroughRGBA2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
{
uint2 size;
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/ResolveDepthStencil.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/ResolveDepthStencil.hlsl
new file mode 100644
index 0000000000..7dc40d4b6a
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/ResolveDepthStencil.hlsl
@@ -0,0 +1,56 @@
+static const float2 g_Corners[6] =
+{
+ float2(-1.0f, 1.0f),
+ float2( 1.0f, -1.0f),
+ float2(-1.0f, -1.0f),
+ float2(-1.0f, 1.0f),
+ float2( 1.0f, 1.0f),
+ float2( 1.0f, -1.0f),
+};
+
+void VS_ResolveDepthStencil(in uint id : SV_VertexID,
+ out float4 position : SV_Position,
+ out float2 texCoord : TEXCOORD0)
+{
+ float2 corner = g_Corners[id];
+ position = float4(corner.x, corner.y, 0.0f, 1.0f);
+ texCoord = float2((corner.x + 1.0f) * 0.5f, (-corner.y + 1.0f) * 0.5f);
+}
+
+Texture2DMS<float> Depth : register(t0);
+Texture2DMS<uint2> Stencil : register(t1);
+
+void PS_ResolveDepth(in float4 position : SV_Position,
+ in float2 texCoord : TEXCOORD0,
+ out float depth : SV_Depth)
+{
+ // MS samplers must use Load
+ uint width, height, samples;
+ Depth.GetDimensions(width, height, samples);
+ uint2 coord = uint2(texCoord.x * float(width), texCoord.y * float(height));
+ depth = Depth.Load(coord, 0).r;
+}
+
+void PS_ResolveDepthStencil(in float4 position : SV_Position,
+ in float2 texCoord : TEXCOORD0,
+ out float2 depthStencil : SV_Target0)
+{
+ // MS samplers must use Load
+ uint width, height, samples;
+ Depth.GetDimensions(width, height, samples);
+ uint2 coord = uint2(texCoord.x * float(width), texCoord.y * float(height));
+ depthStencil.r = Depth.Load(coord, 0).r;
+ depthStencil.g = float(Stencil.Load(coord, 0).g);
+}
+
+void PS_ResolveStencil(in float4 position : SV_Position,
+ in float2 texCoord : TEXCOORD0,
+ out float2 stencil : SV_Target0)
+{
+ // MS samplers must use Load
+ uint width, height, samples;
+ Stencil.GetDimensions(width, height, samples);
+ uint2 coord = uint2(texCoord.x * float(width), texCoord.y * float(height));
+ stencil.r = 0.0f;
+ stencil.g = float(Stencil.Load(coord, 0).g);
+}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dms11ps.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dms11ps.h
new file mode 100644
index 0000000000..a5cccdc98e
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dms11ps.h
@@ -0,0 +1,155 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureF_MS texture float4 2dMS t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCORD 0 xy 1 NONE float xy
+// SV_SAMPLEINDEX 0 x 2 SAMPLE uint x
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+// Pixel Shader runs at sample frequency
+//
+ps_4_1
+dcl_globalFlags refactoringAllowed
+dcl_resource_texture2dms(0) (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_input_ps_sgv constant v2.x, sampleIndex
+dcl_output o0.xyzw
+dcl_temps 1
+ftou r0.xy, v1.xyxx
+mov r0.zw, l(0,0,0,0)
+ldms o0.xyzw, r0.xyzw, t0.xyzw, v2.x
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBA2DMS[] =
+{
+ 68, 88, 66, 67, 206, 115,
+ 73, 27, 160, 237, 59, 223,
+ 179, 180, 28, 146, 74, 174,
+ 29, 197, 1, 0, 0, 0,
+ 136, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 172, 0, 0, 0, 40, 1,
+ 0, 0, 92, 1, 0, 0,
+ 12, 2, 0, 0, 82, 68,
+ 69, 70, 112, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 28, 0, 0, 0, 1, 4,
+ 255, 255, 0, 1, 0, 0,
+ 72, 0, 0, 0, 60, 0,
+ 0, 0, 2, 0, 0, 0,
+ 5, 0, 0, 0, 6, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 84, 101, 120, 116, 117, 114,
+ 101, 70, 95, 77, 83, 0,
+ 77, 105, 99, 114, 111, 115,
+ 111, 102, 116, 32, 40, 82,
+ 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101,
+ 114, 32, 67, 111, 109, 112,
+ 105, 108, 101, 114, 32, 49,
+ 48, 46, 49, 0, 73, 83,
+ 71, 78, 116, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0,
+ 0, 0, 80, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 92, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 3, 3,
+ 0, 0, 100, 0, 0, 0,
+ 0, 0, 0, 0, 10, 0,
+ 0, 0, 1, 0, 0, 0,
+ 2, 0, 0, 0, 1, 1,
+ 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79,
+ 78, 0, 84, 69, 88, 67,
+ 79, 82, 68, 0, 83, 86,
+ 95, 83, 65, 77, 80, 76,
+ 69, 73, 78, 68, 69, 88,
+ 0, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0,
+ 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 83, 86, 95, 84, 65, 82,
+ 71, 69, 84, 0, 171, 171,
+ 83, 72, 68, 82, 168, 0,
+ 0, 0, 65, 0, 0, 0,
+ 42, 0, 0, 0, 106, 8,
+ 0, 1, 88, 32, 0, 4,
+ 0, 112, 16, 0, 0, 0,
+ 0, 0, 85, 85, 0, 0,
+ 98, 16, 0, 3, 50, 16,
+ 16, 0, 1, 0, 0, 0,
+ 99, 8, 0, 4, 18, 16,
+ 16, 0, 2, 0, 0, 0,
+ 10, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0,
+ 28, 0, 0, 5, 50, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 1, 0,
+ 0, 0, 54, 0, 0, 8,
+ 194, 0, 16, 0, 0, 0,
+ 0, 0, 2, 64, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 46, 0,
+ 0, 9, 242, 32, 16, 0,
+ 0, 0, 0, 0, 70, 14,
+ 16, 0, 0, 0, 0, 0,
+ 70, 126, 16, 0, 0, 0,
+ 0, 0, 10, 16, 16, 0,
+ 2, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 4, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0
+};
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_data.json b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_data.json
deleted file mode 100644
index 3e9e6877d9..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_data.json
+++ /dev/null
@@ -1,77 +0,0 @@
-{
- "GL_UNSIGNED_NORMALIZED": {
- "8": {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM"
- },
- "16": {
- "texFormat": "DXGI_FORMAT_R16G16B16A16_UNORM",
- "srvFormat": "DXGI_FORMAT_R16G16B16A16_UNORM",
- "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UNORM"
- },
- "24": {
- "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
- "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
- "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT"
- },
- "32": {
- "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
- "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
- "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT"
- }
- },
- "GL_SIGNED_NORMALIZED": {
- "8": {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_SNORM",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_SNORM",
- "rtvFormat": "DXGI_FORMAT_R8G8B8A8_SNORM"
- }
- },
- "GL_FLOAT": {
- "16": {
- "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT"
- },
- "32": {
- "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
- "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
- "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT"
- }
- },
- "GL_UNSIGNED_INT": {
- "8": {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
- "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UINT"
- },
- "16": {
- "texFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
- "srvFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
- "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UINT"
- },
- "32": {
- "texFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
- "srvFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
- "rtvFormat": "DXGI_FORMAT_R32G32B32A32_UINT"
- }
- },
- "GL_INT": {
- "8": {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
- "rtvFormat": "DXGI_FORMAT_R8G8B8A8_SINT"
- },
- "16": {
- "texFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
- "srvFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
- "rtvFormat": "DXGI_FORMAT_R16G16B16A16_SINT"
- },
- "32": {
- "texFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
- "srvFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
- "rtvFormat": "DXGI_FORMAT_R32G32B32A32_SINT"
- }
- }
-} \ No newline at end of file
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h
deleted file mode 100644
index df9a30ff50..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h
+++ /dev/null
@@ -1,51 +0,0 @@
-//
-// Copyright 2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// swizzle_format_info:
-// Provides information for swizzle format and a map from type->formatinfo
-//
-
-#ifndef LIBANGLE_RENDERER_D3D_D3D11_SWIZZLEFORMATINFO_H_
-#define LIBANGLE_RENDERER_D3D_D3D11_SWIZZLEFORMATINFO_H_
-
-#include <GLES2/gl2.h>
-#include <map>
-
-#include "common/platform.h"
-
-namespace rx
-{
-
-namespace d3d11
-{
-
-struct SwizzleSizeType
-{
- size_t maxComponentSize;
- GLenum componentType;
-
- SwizzleSizeType();
- SwizzleSizeType(size_t maxComponentSize, GLenum componentType);
-
- bool operator<(const SwizzleSizeType &other) const;
-};
-
-struct SwizzleFormatInfo
-{
- DXGI_FORMAT mTexFormat;
- DXGI_FORMAT mSRVFormat;
- DXGI_FORMAT mRTVFormat;
-
- SwizzleFormatInfo();
- SwizzleFormatInfo(DXGI_FORMAT texFormat, DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat);
-};
-
-const SwizzleFormatInfo &GetSwizzleFormatInfo(GLuint maxBits, GLenum componentType);
-
-} // namespace d3d11
-
-} // namespace rx
-
-#endif // LIBANGLE_RENDERER_D3D_D3D11_SWIZZLEFORMATINFO_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info_autogen.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info_autogen.cpp
deleted file mode 100644
index 84d6fada97..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info_autogen.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-// GENERATED FILE - DO NOT EDIT
-// Generated by gen_swizzle_format_table.py using data from swizzle_format_data.json
-//
-// Copyright 2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// swizzle_format_info:
-// Provides information for swizzle format and a map from type->formatinfo
-//
-
-#include "libANGLE/renderer/d3d/d3d11/swizzle_format_info.h"
-
-#include <GLES3/gl3.h>
-
-namespace rx
-{
-
-namespace d3d11
-{
-
-SwizzleSizeType::SwizzleSizeType() : maxComponentSize(0), componentType(GL_NONE)
-{
-}
-
-SwizzleSizeType::SwizzleSizeType(size_t maxComponentSize, GLenum componentType)
- : maxComponentSize(maxComponentSize), componentType(componentType)
-{
-}
-
-bool SwizzleSizeType::operator<(const SwizzleSizeType &other) const
-{
- return (maxComponentSize != other.maxComponentSize)
- ? (maxComponentSize < other.maxComponentSize)
- : (componentType < other.componentType);
-}
-
-SwizzleFormatInfo::SwizzleFormatInfo()
- : mTexFormat(DXGI_FORMAT_UNKNOWN),
- mSRVFormat(DXGI_FORMAT_UNKNOWN),
- mRTVFormat(DXGI_FORMAT_UNKNOWN)
-{
-}
-
-SwizzleFormatInfo::SwizzleFormatInfo(DXGI_FORMAT texFormat,
- DXGI_FORMAT srvFormat,
- DXGI_FORMAT rtvFormat)
- : mTexFormat(texFormat), mSRVFormat(srvFormat), mRTVFormat(rtvFormat)
-{
-}
-
-const SwizzleFormatInfo &GetSwizzleFormatInfo(GLuint maxBits, GLenum componentType)
-{
- // clang-format off
- switch (componentType)
- {
- case GL_FLOAT:
- {
- switch (maxBits)
- {
- case 16:
- {
- static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT,
- DXGI_FORMAT_R16G16B16A16_FLOAT,
- DXGI_FORMAT_R16G16B16A16_FLOAT);
- return formatInfo;
- }
- case 32:
- {
- static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT,
- DXGI_FORMAT_R32G32B32A32_FLOAT,
- DXGI_FORMAT_R32G32B32A32_FLOAT);
- return formatInfo;
- }
- default:
- break;
- }
- }
- case GL_INT:
- {
- switch (maxBits)
- {
- case 16:
- {
- static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R16G16B16A16_SINT,
- DXGI_FORMAT_R16G16B16A16_SINT,
- DXGI_FORMAT_R16G16B16A16_SINT);
- return formatInfo;
- }
- case 32:
- {
- static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R32G32B32A32_SINT,
- DXGI_FORMAT_R32G32B32A32_SINT,
- DXGI_FORMAT_R32G32B32A32_SINT);
- return formatInfo;
- }
- case 8:
- {
- static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R8G8B8A8_SINT,
- DXGI_FORMAT_R8G8B8A8_SINT,
- DXGI_FORMAT_R8G8B8A8_SINT);
- return formatInfo;
- }
- default:
- break;
- }
- }
- case GL_SIGNED_NORMALIZED:
- {
- switch (maxBits)
- {
- case 8:
- {
- static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R8G8B8A8_SNORM,
- DXGI_FORMAT_R8G8B8A8_SNORM,
- DXGI_FORMAT_R8G8B8A8_SNORM);
- return formatInfo;
- }
- default:
- break;
- }
- }
- case GL_UNSIGNED_INT:
- {
- switch (maxBits)
- {
- case 16:
- {
- static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R16G16B16A16_UINT,
- DXGI_FORMAT_R16G16B16A16_UINT,
- DXGI_FORMAT_R16G16B16A16_UINT);
- return formatInfo;
- }
- case 32:
- {
- static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R32G32B32A32_UINT,
- DXGI_FORMAT_R32G32B32A32_UINT,
- DXGI_FORMAT_R32G32B32A32_UINT);
- return formatInfo;
- }
- case 8:
- {
- static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R8G8B8A8_UINT,
- DXGI_FORMAT_R8G8B8A8_UINT,
- DXGI_FORMAT_R8G8B8A8_UINT);
- return formatInfo;
- }
- default:
- break;
- }
- }
- case GL_UNSIGNED_NORMALIZED:
- {
- switch (maxBits)
- {
- case 16:
- {
- static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R16G16B16A16_UNORM,
- DXGI_FORMAT_R16G16B16A16_UNORM,
- DXGI_FORMAT_R16G16B16A16_UNORM);
- return formatInfo;
- }
- case 24:
- {
- static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT,
- DXGI_FORMAT_R32G32B32A32_FLOAT,
- DXGI_FORMAT_R32G32B32A32_FLOAT);
- return formatInfo;
- }
- case 32:
- {
- static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT,
- DXGI_FORMAT_R32G32B32A32_FLOAT,
- DXGI_FORMAT_R32G32B32A32_FLOAT);
- return formatInfo;
- }
- case 8:
- {
- static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM);
- return formatInfo;
- }
- default:
- break;
- }
- }
-
- default:
- {
- static const SwizzleFormatInfo defaultInfo(DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return defaultInfo;
- }
- }
- // clang-format on
-
-} // GetSwizzleFormatInfo
-
-} // namespace d3d11
-
-} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json
index 87d303437f..61cd44a62b 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json
@@ -1,692 +1,523 @@
{
- "GL_ALPHA": [
- {
- "texFormat": "DXGI_FORMAT_A8_UNORM",
- "srvFormat": "DXGI_FORMAT_A8_UNORM",
- "rtvFormat": "DXGI_FORMAT_A8_UNORM",
- "requirementsFcn": "OnlyFL10Plus"
- },
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "requirementsFcn": "OnlyFL9_3"
- }
- ],
- "GL_ALPHA16F_EXT": [
- {
- "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT"
- }
- ],
- "GL_ALPHA32F_EXT": [
- {
- "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
- "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
- "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT"
- }
- ],
- "GL_ALPHA8_EXT": [
- {
- "texFormat": "DXGI_FORMAT_A8_UNORM",
- "srvFormat": "DXGI_FORMAT_A8_UNORM",
- "rtvFormat": "DXGI_FORMAT_A8_UNORM",
- "requirementsFcn": "OnlyFL10Plus"
- },
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "requirementsFcn": "OnlyFL9_3"
- }
- ],
- "GL_BGR5_A1_ANGLEX": [
- {
- "texFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
- "srvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
- "rtvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM"
- }
- ],
- "GL_BGRA4_ANGLEX": [
- {
- "texFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
- "srvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
- "rtvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM"
- }
- ],
- "GL_BGRA8_EXT": [
- {
- "texFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
- "srvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
- "rtvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM"
- }
- ],
- "GL_BGRA_EXT": [
- {
- "texFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
- "srvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
- "rtvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM"
- }
- ],
- "GL_COMPRESSED_R11_EAC": [
- {
- "texFormat": "DXGI_FORMAT_R8_UNORM",
- "srvFormat": "DXGI_FORMAT_R8_UNORM",
- "requirementsFcn": "OnlyFL10Plus"
- }
- ],
- "GL_COMPRESSED_RG11_EAC": [
- {
- "texFormat": "DXGI_FORMAT_R8G8_UNORM",
- "srvFormat": "DXGI_FORMAT_R8G8_UNORM",
- "requirementsFcn": "OnlyFL10Plus"
- }
- ],
- "GL_COMPRESSED_RGB8_ETC2": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "requirementsFcn": "OnlyFL10Plus"
- }
- ],
- "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "requirementsFcn": "OnlyFL10Plus"
- }
- ],
- "GL_COMPRESSED_RGBA8_ETC2_EAC": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "requirementsFcn": "OnlyFL10Plus"
- }
- ],
- "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT": [
- {
- "texFormat": "DXGI_FORMAT_BC1_UNORM",
- "srvFormat": "DXGI_FORMAT_BC1_UNORM"
- }
- ],
- "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE": [
- {
- "texFormat": "DXGI_FORMAT_BC2_UNORM",
- "srvFormat": "DXGI_FORMAT_BC2_UNORM"
- }
- ],
- "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE": [
- {
- "texFormat": "DXGI_FORMAT_BC3_UNORM",
- "srvFormat": "DXGI_FORMAT_BC3_UNORM"
- }
- ],
- "GL_COMPRESSED_RGB_S3TC_DXT1_EXT": [
- {
- "texFormat": "DXGI_FORMAT_BC1_UNORM",
- "srvFormat": "DXGI_FORMAT_BC1_UNORM"
- }
- ],
- "GL_COMPRESSED_SIGNED_R11_EAC": [
- {
- "texFormat": "DXGI_FORMAT_R8_SNORM",
- "srvFormat": "DXGI_FORMAT_R8_SNORM",
- "requirementsFcn": "OnlyFL10Plus"
- }
- ],
- "GL_COMPRESSED_SIGNED_RG11_EAC": [
- {
- "texFormat": "DXGI_FORMAT_R8G8_SNORM",
- "srvFormat": "DXGI_FORMAT_R8G8_SNORM",
- "requirementsFcn": "OnlyFL10Plus"
- }
- ],
- "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
- "requirementsFcn": "OnlyFL10Plus"
- }
- ],
- "GL_COMPRESSED_SRGB8_ETC2": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
- "requirementsFcn": "OnlyFL10Plus"
- }
- ],
- "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
- "requirementsFcn": "OnlyFL10Plus"
- }
- ],
- "GL_DEPTH24_STENCIL8": [
- {
+ "NONE": {
+ },
+ "A8_UNORM": {
+ "texFormat": "DXGI_FORMAT_A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_A8_UNORM",
+ "channels": "a",
+ "componentType": "unorm",
+ "bits": { "alpha": 8 },
+ "supportTest": "OnlyFL10Plus(deviceCaps)",
+ "fallbackFormat": "R8G8B8A8_UNORM"
+ },
+ "R8G8B8A8_UNORM": {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "channels": "rgba",
+ "componentType": "unorm",
+ "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 },
+ "glInternalFormat": "GL_RGBA8"
+ },
+ "R16G16B16A16_UNORM": {
+ "texFormat": "DXGI_FORMAT_R16G16B16A16_UNORM",
+ "srvFormat": "DXGI_FORMAT_R16G16B16A16_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UNORM",
+ "channels": "rgba",
+ "componentType": "unorm",
+ "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 },
+ "glInternalFormat": "GL_RGBA16_EXT"
+ },
+ "R16G16B16A16_FLOAT": {
+ "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "channels": "rgba",
+ "componentType": "float",
+ "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 },
+ "glInternalFormat": "GL_RGBA16F"
+ },
+ "R32G32B32A32_FLOAT": {
+ "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "channels": "rgba",
+ "componentType": "float",
+ "bits": { "red": 32, "green": 32, "blue": 32, "alpha": 32 },
+ "glInternalFormat": "GL_RGBA32F"
+ },
+ "B8G8R8A8_UNORM": {
+ "texFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
+ "srvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM",
+ "channels": "bgra",
+ "componentType": "unorm",
+ "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 },
+ "glInternalFormat": "GL_BGRA8_EXT"
+ },
+ "B8G8R8A8_UNORM_SRGB": {
+ "texFormat": "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB",
+ "srvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB",
+ "rtvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB",
+ "channels": "bgra",
+ "componentType": "unorm",
+ "bits": {"red": 8, "green": 8, "blue": 8,"alpha": 8},
+ "siwzzleFormat": "GL_RGBA8"
+ },
+ "BC1_RGBA_UNORM_BLOCK": {
+ "texFormat": "DXGI_FORMAT_BC1_UNORM",
+ "srvFormat": "DXGI_FORMAT_BC1_UNORM",
+ "channels": "rgba",
+ "componentType": "unorm",
+ "swizzleFormat": "GL_RGBA8"
+ },
+ "BC1_RGB_UNORM_BLOCK": {
+ "texFormat": "DXGI_FORMAT_BC1_UNORM",
+ "srvFormat": "DXGI_FORMAT_BC1_UNORM",
+ "channels": "rgba",
+ "componentType": "unorm",
+ "swizzleFormat": "GL_RGBA8"
+ },
+ "BC2_RGBA_UNORM_BLOCK": {
+ "texFormat": "DXGI_FORMAT_BC2_UNORM",
+ "srvFormat": "DXGI_FORMAT_BC2_UNORM",
+ "channels": "rgba",
+ "componentType": "unorm",
+ "swizzleFormat": "GL_RGBA8"
+ },
+ "BC3_RGBA_UNORM_BLOCK": {
+ "texFormat": "DXGI_FORMAT_BC3_UNORM",
+ "srvFormat": "DXGI_FORMAT_BC3_UNORM",
+ "channels": "rgba",
+ "componentType": "unorm",
+ "swizzleFormat": "GL_RGBA8"
+ },
+ "BC1_RGBA_UNORM_SRGB_BLOCK": {
+ "texFormat": "DXGI_FORMAT_BC1_UNORM_SRGB",
+ "srvFormat": "DXGI_FORMAT_BC1_UNORM_SRGB",
+ "channels": "rgba",
+ "componentType": "unorm",
+ "swizzleFormat": "GL_RGBA8"
+ },
+ "BC1_RGB_UNORM_SRGB_BLOCK": {
+ "texFormat": "DXGI_FORMAT_BC1_UNORM_SRGB",
+ "srvFormat": "DXGI_FORMAT_BC1_UNORM_SRGB",
+ "channels": "rgba",
+ "componentType": "unorm",
+ "swizzleFormat": "GL_RGBA8"
+ },
+ "BC2_RGBA_UNORM_SRGB_BLOCK": {
+ "texFormat": "DXGI_FORMAT_BC2_UNORM_SRGB",
+ "srvFormat": "DXGI_FORMAT_BC2_UNORM_SRGB",
+ "channels": "rgba",
+ "componentType": "unorm",
+ "swizzleFormat": "GL_RGBA8"
+ },
+ "BC3_RGBA_UNORM_SRGB_BLOCK": {
+ "texFormat": "DXGI_FORMAT_BC3_UNORM_SRGB",
+ "srvFormat": "DXGI_FORMAT_BC3_UNORM_SRGB",
+ "channels": "rgba",
+ "componentType": "unorm",
+ "swizzleFormat": "GL_RGBA8"
+ },
+ "D24_UNORM_S8_UINT": {
+ "FL10Plus": {
"texFormat": "DXGI_FORMAT_R24G8_TYPELESS",
- "srvFormat": "DXGI_FORMAT_R24_UNORM_X8_TYPELESS",
- "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
- "requirementsFcn": "OnlyFL10Plus"
+ "srvFormat": "DXGI_FORMAT_R24_UNORM_X8_TYPELESS"
},
- {
- "texFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
- "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
- "requirementsFcn": "OnlyFL9_3"
- }
- ],
- "GL_DEPTH32F_STENCIL8": [
- {
- "texFormat": "DXGI_FORMAT_R32G8X24_TYPELESS",
- "srvFormat": "DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS",
- "dsvFormat": "DXGI_FORMAT_D32_FLOAT_S8X24_UINT",
- "requirementsFcn": "OnlyFL10Plus"
+ "FL9_3": {
+ "texFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT"
},
- {
- "requirementsFcn": "OnlyFL9_3"
- }
- ],
- "GL_DEPTH_COMPONENT16": [
- {
+ "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
+ "channels": "ds",
+ "bits": { "depth": 24, "stencil": 8 },
+ "glInternalFormat": "GL_DEPTH24_STENCIL8_OES"
+ },
+ "D32_FLOAT_S8X24_UINT": {
+ "texFormat": "DXGI_FORMAT_R32G8X24_TYPELESS",
+ "srvFormat": "DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS",
+ "dsvFormat": "DXGI_FORMAT_D32_FLOAT_S8X24_UINT",
+ "channels": "ds",
+ "bits": { "depth": 32, "stencil": 8 },
+ "glInternalFormat": "GL_DEPTH32F_STENCIL8"
+ },
+ "D16_UNORM": {
+ "FL10Plus": {
"texFormat": "DXGI_FORMAT_R16_TYPELESS",
- "srvFormat": "DXGI_FORMAT_R16_UNORM",
- "dsvFormat": "DXGI_FORMAT_D16_UNORM",
- "requirementsFcn": "OnlyFL10Plus"
- },
- {
- "texFormat": "DXGI_FORMAT_D16_UNORM",
- "dsvFormat": "DXGI_FORMAT_D16_UNORM",
- "requirementsFcn": "OnlyFL9_3"
- }
- ],
- "GL_DEPTH_COMPONENT24": [
- {
- "texFormat": "DXGI_FORMAT_R24G8_TYPELESS",
- "srvFormat": "DXGI_FORMAT_R24_UNORM_X8_TYPELESS",
- "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
- "requirementsFcn": "OnlyFL10Plus"
- },
- {
- "texFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
- "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
- "requirementsFcn": "OnlyFL9_3"
- }
- ],
- "GL_DEPTH_COMPONENT32F": [
- {
- "texFormat": "DXGI_FORMAT_R32_TYPELESS",
- "srvFormat": "DXGI_FORMAT_R32_FLOAT",
- "dsvFormat": "DXGI_FORMAT_D32_FLOAT",
- "requirementsFcn": "OnlyFL10Plus"
+ "srvFormat": "DXGI_FORMAT_R16_UNORM"
},
- {
- "requirementsFcn": "OnlyFL9_3"
- }
- ],
- "GL_DEPTH_COMPONENT32_OES": [
- {
- "texFormat": "DXGI_FORMAT_R24G8_TYPELESS",
- "srvFormat": "DXGI_FORMAT_R24_UNORM_X8_TYPELESS",
- "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
- "requirementsFcn": "OnlyFL10Plus"
- }
- ],
- "GL_ETC1_RGB8_OES": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM"
- }
- ],
- "GL_ETC1_RGB8_LOSSY_DECODE_ANGLE": [
- {
- "texFormat": "DXGI_FORMAT_BC1_UNORM",
- "srvFormat": "DXGI_FORMAT_BC1_UNORM"
- }
- ],
- "GL_LUMINANCE": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM"
- }
- ],
- "GL_LUMINANCE16F_EXT": [
- {
- "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT"
- }
- ],
- "GL_LUMINANCE32F_EXT": [
- {
- "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
- "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
- "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT"
- }
- ],
- "GL_LUMINANCE8_ALPHA8_EXT": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM"
- }
- ],
- "GL_LUMINANCE8_EXT": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM"
- }
- ],
- "GL_LUMINANCE_ALPHA": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM"
- }
- ],
- "GL_LUMINANCE_ALPHA16F_EXT": [
- {
- "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT"
- }
- ],
- "GL_LUMINANCE_ALPHA32F_EXT": [
- {
- "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
- "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
- "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT"
- }
- ],
- "GL_NONE": [
- {
- }
- ],
- "GL_R11F_G11F_B10F": [
- {
- "texFormat": "DXGI_FORMAT_R11G11B10_FLOAT",
- "srvFormat": "DXGI_FORMAT_R11G11B10_FLOAT",
- "rtvFormat": "DXGI_FORMAT_R11G11B10_FLOAT"
- }
- ],
- "GL_R16F": [
- {
- "texFormat": "DXGI_FORMAT_R16_FLOAT",
- "srvFormat": "DXGI_FORMAT_R16_FLOAT",
- "rtvFormat": "DXGI_FORMAT_R16_FLOAT"
- }
- ],
- "GL_R16I": [
- {
- "texFormat": "DXGI_FORMAT_R16_SINT",
- "srvFormat": "DXGI_FORMAT_R16_SINT",
- "rtvFormat": "DXGI_FORMAT_R16_SINT"
- }
- ],
- "GL_R16UI": [
- {
- "texFormat": "DXGI_FORMAT_R16_UINT",
- "srvFormat": "DXGI_FORMAT_R16_UINT",
- "rtvFormat": "DXGI_FORMAT_R16_UINT"
- }
- ],
- "GL_R32F": [
- {
- "texFormat": "DXGI_FORMAT_R32_FLOAT",
- "srvFormat": "DXGI_FORMAT_R32_FLOAT",
- "rtvFormat": "DXGI_FORMAT_R32_FLOAT"
- }
- ],
- "GL_R32I": [
- {
- "texFormat": "DXGI_FORMAT_R32_SINT",
- "srvFormat": "DXGI_FORMAT_R32_SINT",
- "rtvFormat": "DXGI_FORMAT_R32_SINT"
- }
- ],
- "GL_R32UI": [
- {
- "texFormat": "DXGI_FORMAT_R32_UINT",
- "srvFormat": "DXGI_FORMAT_R32_UINT",
- "rtvFormat": "DXGI_FORMAT_R32_UINT"
- }
- ],
- "GL_R8": [
- {
- "texFormat": "DXGI_FORMAT_R8_UNORM",
- "srvFormat": "DXGI_FORMAT_R8_UNORM",
- "rtvFormat": "DXGI_FORMAT_R8_UNORM"
- }
- ],
- "GL_R8I": [
- {
- "texFormat": "DXGI_FORMAT_R8_SINT",
- "srvFormat": "DXGI_FORMAT_R8_SINT",
- "rtvFormat": "DXGI_FORMAT_R8_SINT"
- }
- ],
- "GL_R8UI": [
- {
- "texFormat": "DXGI_FORMAT_R8_UINT",
- "srvFormat": "DXGI_FORMAT_R8_UINT",
- "rtvFormat": "DXGI_FORMAT_R8_UINT"
- }
- ],
- "GL_R8_SNORM": [
- {
- "texFormat": "DXGI_FORMAT_R8_SNORM",
- "srvFormat": "DXGI_FORMAT_R8_SNORM"
- }
- ],
- "GL_RG16F": [
- {
- "texFormat": "DXGI_FORMAT_R16G16_FLOAT",
- "srvFormat": "DXGI_FORMAT_R16G16_FLOAT",
- "rtvFormat": "DXGI_FORMAT_R16G16_FLOAT"
- }
- ],
- "GL_RG16I": [
- {
- "texFormat": "DXGI_FORMAT_R16G16_SINT",
- "srvFormat": "DXGI_FORMAT_R16G16_SINT",
- "rtvFormat": "DXGI_FORMAT_R16G16_SINT"
- }
- ],
- "GL_RG16UI": [
- {
- "texFormat": "DXGI_FORMAT_R16G16_UINT",
- "srvFormat": "DXGI_FORMAT_R16G16_UINT",
- "rtvFormat": "DXGI_FORMAT_R16G16_UINT"
- }
- ],
- "GL_RG32F": [
- {
- "texFormat": "DXGI_FORMAT_R32G32_FLOAT",
- "srvFormat": "DXGI_FORMAT_R32G32_FLOAT",
- "rtvFormat": "DXGI_FORMAT_R32G32_FLOAT"
- }
- ],
- "GL_RG32I": [
- {
- "texFormat": "DXGI_FORMAT_R32G32_SINT",
- "srvFormat": "DXGI_FORMAT_R32G32_SINT",
- "rtvFormat": "DXGI_FORMAT_R32G32_SINT"
- }
- ],
- "GL_RG32UI": [
- {
- "texFormat": "DXGI_FORMAT_R32G32_UINT",
- "srvFormat": "DXGI_FORMAT_R32G32_UINT",
- "rtvFormat": "DXGI_FORMAT_R32G32_UINT"
- }
- ],
- "GL_RG8": [
- {
- "texFormat": "DXGI_FORMAT_R8G8_UNORM",
- "srvFormat": "DXGI_FORMAT_R8G8_UNORM",
- "rtvFormat": "DXGI_FORMAT_R8G8_UNORM"
- }
- ],
- "GL_RG8I": [
- {
- "texFormat": "DXGI_FORMAT_R8G8_SINT",
- "srvFormat": "DXGI_FORMAT_R8G8_SINT",
- "rtvFormat": "DXGI_FORMAT_R8G8_SINT"
- }
- ],
- "GL_RG8UI": [
- {
- "texFormat": "DXGI_FORMAT_R8G8_UINT",
- "srvFormat": "DXGI_FORMAT_R8G8_UINT",
- "rtvFormat": "DXGI_FORMAT_R8G8_UINT"
- }
- ],
- "GL_RG8_SNORM": [
- {
- "texFormat": "DXGI_FORMAT_R8G8_SNORM",
- "srvFormat": "DXGI_FORMAT_R8G8_SNORM"
- }
- ],
- "GL_RGB": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM"
- }
- ],
- "GL_RGB10_A2": [
- {
- "texFormat": "DXGI_FORMAT_R10G10B10A2_UNORM",
- "srvFormat": "DXGI_FORMAT_R10G10B10A2_UNORM",
- "rtvFormat": "DXGI_FORMAT_R10G10B10A2_UNORM"
- }
- ],
- "GL_RGB10_A2UI": [
- {
- "texFormat": "DXGI_FORMAT_R10G10B10A2_UINT",
- "srvFormat": "DXGI_FORMAT_R10G10B10A2_UINT",
- "rtvFormat": "DXGI_FORMAT_R10G10B10A2_UINT"
- }
- ],
- "GL_RGB16F": [
- {
- "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT"
- }
- ],
- "GL_RGB16I": [
- {
- "texFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
- "srvFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
- "rtvFormat": "DXGI_FORMAT_R16G16B16A16_SINT"
- }
- ],
- "GL_RGB16UI": [
- {
- "texFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
- "srvFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
- "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UINT"
- }
- ],
- "GL_RGB32F": [
- {
- "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
- "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
- "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT"
- }
- ],
- "GL_RGB32I": [
- {
- "texFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
- "srvFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
- "rtvFormat": "DXGI_FORMAT_R32G32B32A32_SINT"
- }
- ],
- "GL_RGB32UI": [
- {
- "texFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
- "srvFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
- "rtvFormat": "DXGI_FORMAT_R32G32B32A32_UINT"
- }
- ],
- "GL_RGB565": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "requirementsFcn": "SupportsFormat<DXGI_FORMAT_B5G6R5_UNORM,false>"
- },
- {
- "texFormat": "DXGI_FORMAT_B5G6R5_UNORM",
- "srvFormat": "DXGI_FORMAT_B5G6R5_UNORM",
- "rtvFormat": "DXGI_FORMAT_B5G6R5_UNORM",
- "requirementsFcn": "SupportsFormat<DXGI_FORMAT_B5G6R5_UNORM,true>"
- }
- ],
- "GL_RGB5_A1": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "requirementsFcn": "SupportsFormat<DXGI_FORMAT_B5G5R5A1_UNORM,false>"
- },
- {
- "texFormat": "DXGI_FORMAT_B5G5R5A1_UNORM",
- "srvFormat": "DXGI_FORMAT_B5G5R5A1_UNORM",
- "rtvFormat": "DXGI_FORMAT_B5G5R5A1_UNORM",
- "requirementsFcn": "SupportsFormat<DXGI_FORMAT_B5G5R5A1_UNORM,true>"
- }
- ],
- "GL_RGB8": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM"
- }
- ],
- "GL_RGB8I": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
- "rtvFormat": "DXGI_FORMAT_R8G8B8A8_SINT"
- }
- ],
- "GL_RGB8UI": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
- "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UINT"
- }
- ],
- "GL_RGB8_SNORM": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_SNORM",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_SNORM"
- }
- ],
- "GL_RGB9_E5": [
- {
- "texFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP",
- "srvFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP"
- }
- ],
- "GL_RGBA": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM"
- }
- ],
- "GL_RGBA16F": [
- {
- "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
- "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT"
- }
- ],
- "GL_RGBA16I": [
- {
- "texFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
- "srvFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
- "rtvFormat": "DXGI_FORMAT_R16G16B16A16_SINT"
- }
- ],
- "GL_RGBA16UI": [
- {
- "texFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
- "srvFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
- "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UINT"
- }
- ],
- "GL_RGBA32F": [
- {
- "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
- "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT",
- "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT"
- }
- ],
- "GL_RGBA32I": [
- {
- "texFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
- "srvFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
- "rtvFormat": "DXGI_FORMAT_R32G32B32A32_SINT"
- }
- ],
- "GL_RGBA32UI": [
- {
- "texFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
- "srvFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
- "rtvFormat": "DXGI_FORMAT_R32G32B32A32_UINT"
- }
- ],
- "GL_RGBA4": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "requirementsFcn": "SupportsFormat<DXGI_FORMAT_B4G4R4A4_UNORM,false>"
- },
- {
- "texFormat": "DXGI_FORMAT_B4G4R4A4_UNORM",
- "srvFormat": "DXGI_FORMAT_B4G4R4A4_UNORM",
- "rtvFormat": "DXGI_FORMAT_B4G4R4A4_UNORM",
- "requirementsFcn": "SupportsFormat<DXGI_FORMAT_B4G4R4A4_UNORM,true>"
- }
- ],
- "GL_RGBA8": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM",
- "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM"
- }
- ],
- "GL_RGBA8I": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
- "rtvFormat": "DXGI_FORMAT_R8G8B8A8_SINT"
- }
- ],
- "GL_RGBA8UI": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
- "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UINT"
- }
- ],
- "GL_RGBA8_SNORM": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_SNORM",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_SNORM"
- }
- ],
- "GL_SRGB8": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB"
- }
- ],
- "GL_SRGB8_ALPHA8": [
- {
- "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
- "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
- "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB"
- }
- ],
- "GL_STENCIL_INDEX8": [
- {
- "texFormat": "DXGI_FORMAT_R24G8_TYPELESS",
- "srvFormat": "DXGI_FORMAT_X24_TYPELESS_G8_UINT",
- "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
- "requirementsFcn": "OnlyFL10Plus"
+ "FL9_3": {
+ "texFormat": "DXGI_FORMAT_D16_UNORM"
},
- {
- "texFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
- "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT",
- "requirementsFcn": "OnlyFL9_3"
- }
- ]
+ "dsvFormat": "DXGI_FORMAT_D16_UNORM",
+ "channels": "d",
+ "componentType": "unorm",
+ "bits": { "depth": 16 },
+ "glInternalFormat": "GL_DEPTH_COMPONENT16"
+ },
+ "D32_FLOAT": {
+ "texFormat": "DXGI_FORMAT_R32_TYPELESS",
+ "srvFormat": "DXGI_FORMAT_R32_FLOAT",
+ "dsvFormat": "DXGI_FORMAT_D32_FLOAT",
+ "channels": "d",
+ "componentType": "float",
+ "bits": { "depth": 32 },
+ "glInternalFormat": "GL_DEPTH_COMPONENT32F"
+ },
+ "R11G11B10_FLOAT": {
+ "texFormat": "DXGI_FORMAT_R11G11B10_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R11G11B10_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R11G11B10_FLOAT",
+ "channels": "rgb",
+ "componentType": "float",
+ "bits": { "red": 11, "green": 11, "blue": 10 },
+ "glInternalFormat": "GL_R11F_G11F_B10F"
+ },
+ "R16_FLOAT": {
+ "texFormat": "DXGI_FORMAT_R16_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R16_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R16_FLOAT",
+ "channels": "r",
+ "componentType": "float",
+ "bits": { "red": 16 },
+ "glInternalFormat": "GL_R16F"
+ },
+ "R16_SINT": {
+ "texFormat": "DXGI_FORMAT_R16_SINT",
+ "srvFormat": "DXGI_FORMAT_R16_SINT",
+ "rtvFormat": "DXGI_FORMAT_R16_SINT",
+ "channels": "r",
+ "componentType": "int",
+ "bits": { "red": 16 },
+ "glInternalFormat": "GL_R16I"
+ },
+ "R16_UINT": {
+ "texFormat": "DXGI_FORMAT_R16_UINT",
+ "srvFormat": "DXGI_FORMAT_R16_UINT",
+ "rtvFormat": "DXGI_FORMAT_R16_UINT",
+ "channels": "r",
+ "componentType": "uint",
+ "bits": { "red": 16 },
+ "glInternalFormat": "GL_R16UI"
+ },
+ "R32_FLOAT": {
+ "texFormat": "DXGI_FORMAT_R32_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R32_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R32_FLOAT",
+ "channels": "r",
+ "componentType": "float",
+ "bits": { "red": 32 },
+ "glInternalFormat": "GL_R32F"
+ },
+ "R32_SINT": {
+ "texFormat": "DXGI_FORMAT_R32_SINT",
+ "srvFormat": "DXGI_FORMAT_R32_SINT",
+ "rtvFormat": "DXGI_FORMAT_R32_SINT",
+ "channels": "r",
+ "componentType": "int",
+ "bits": { "red": 32 },
+ "glInternalFormat": "GL_R32I"
+ },
+ "R32_UINT": {
+ "texFormat": "DXGI_FORMAT_R32_UINT",
+ "srvFormat": "DXGI_FORMAT_R32_UINT",
+ "rtvFormat": "DXGI_FORMAT_R32_UINT",
+ "channels": "r",
+ "componentType": "uint",
+ "bits": { "red": 32 },
+ "glInternalFormat": "GL_R32UI"
+ },
+ "R8_UNORM": {
+ "texFormat": "DXGI_FORMAT_R8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R8_UNORM",
+ "channels": "r",
+ "componentType": "unorm",
+ "bits": { "red": 8 },
+ "glInternalFormat": "GL_R8"
+ },
+ "R8_SINT": {
+ "texFormat": "DXGI_FORMAT_R8_SINT",
+ "srvFormat": "DXGI_FORMAT_R8_SINT",
+ "rtvFormat": "DXGI_FORMAT_R8_SINT",
+ "channels": "r",
+ "componentType": "int",
+ "bits": { "red": 8 },
+ "glInternalFormat": "GL_R8I"
+ },
+ "R8_UINT": {
+ "texFormat": "DXGI_FORMAT_R8_UINT",
+ "srvFormat": "DXGI_FORMAT_R8_UINT",
+ "rtvFormat": "DXGI_FORMAT_R8_UINT",
+ "channels": "r",
+ "componentType": "uint",
+ "bits": { "red": 8 },
+ "glInternalFormat": "GL_R8UI"
+ },
+ "R8_SNORM": {
+ "texFormat": "DXGI_FORMAT_R8_SNORM",
+ "srvFormat": "DXGI_FORMAT_R8_SNORM",
+ "channels": "r",
+ "componentType": "snorm",
+ "bits": { "red": 8 },
+ "glInternalFormat": "GL_R8_SNORM"
+ },
+ "R16G16_FLOAT": {
+ "texFormat": "DXGI_FORMAT_R16G16_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R16G16_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R16G16_FLOAT",
+ "channels": "rg",
+ "componentType": "float",
+ "bits": { "red": 16, "green": 16 },
+ "glInternalFormat": "GL_RG16F"
+ },
+ "R16G16_SINT": {
+ "texFormat": "DXGI_FORMAT_R16G16_SINT",
+ "srvFormat": "DXGI_FORMAT_R16G16_SINT",
+ "rtvFormat": "DXGI_FORMAT_R16G16_SINT",
+ "channels": "rg",
+ "componentType": "int",
+ "bits": { "red": 16, "green": 16 },
+ "glInternalFormat": "GL_RG16I"
+ },
+ "R16G16_UINT": {
+ "texFormat": "DXGI_FORMAT_R16G16_UINT",
+ "srvFormat": "DXGI_FORMAT_R16G16_UINT",
+ "rtvFormat": "DXGI_FORMAT_R16G16_UINT",
+ "channels": "rg",
+ "componentType": "uint",
+ "bits": { "red": 16, "green": 16 },
+ "glInternalFormat": "GL_RG16UI"
+ },
+ "R32G32_FLOAT": {
+ "texFormat": "DXGI_FORMAT_R32G32_FLOAT",
+ "srvFormat": "DXGI_FORMAT_R32G32_FLOAT",
+ "rtvFormat": "DXGI_FORMAT_R32G32_FLOAT",
+ "channels": "rg",
+ "componentType": "float",
+ "bits": { "red": 32, "green": 32 },
+ "glInternalFormat": "GL_RG32F"
+ },
+ "R32G32_SINT": {
+ "texFormat": "DXGI_FORMAT_R32G32_SINT",
+ "srvFormat": "DXGI_FORMAT_R32G32_SINT",
+ "rtvFormat": "DXGI_FORMAT_R32G32_SINT",
+ "channels": "rg",
+ "componentType": "int",
+ "bits": { "red": 32, "green": 32 },
+ "glInternalFormat": "GL_RG32I"
+ },
+ "R32G32_UINT": {
+ "texFormat": "DXGI_FORMAT_R32G32_UINT",
+ "srvFormat": "DXGI_FORMAT_R32G32_UINT",
+ "rtvFormat": "DXGI_FORMAT_R32G32_UINT",
+ "channels": "rg",
+ "componentType": "uint",
+ "bits": { "red": 32, "green": 32 },
+ "glInternalFormat": "GL_RG32UI"
+ },
+ "R8G8_UNORM": {
+ "texFormat": "DXGI_FORMAT_R8G8_UNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R8G8_UNORM",
+ "channels": "rg",
+ "componentType": "unorm",
+ "bits": { "red": 8, "green": 8 },
+ "glInternalFormat": "GL_RG8"
+ },
+ "R8G8_SINT": {
+ "texFormat": "DXGI_FORMAT_R8G8_SINT",
+ "srvFormat": "DXGI_FORMAT_R8G8_SINT",
+ "rtvFormat": "DXGI_FORMAT_R8G8_SINT",
+ "channels": "rg",
+ "componentType": "int",
+ "bits": { "red": 8, "green": 8 },
+ "glInternalFormat": "GL_RG8I"
+ },
+ "R8G8_UINT": {
+ "texFormat": "DXGI_FORMAT_R8G8_UINT",
+ "srvFormat": "DXGI_FORMAT_R8G8_UINT",
+ "rtvFormat": "DXGI_FORMAT_R8G8_UINT",
+ "channels": "rg",
+ "componentType": "uint",
+ "bits": { "red": 8, "green": 8 },
+ "glInternalFormat": "GL_RG8UI"
+ },
+ "R8G8_SNORM": {
+ "texFormat": "DXGI_FORMAT_R8G8_SNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8_SNORM",
+ "channels": "rg",
+ "componentType": "snorm",
+ "bits": { "red": 8, "green": 8 },
+ "glInternalFormat": "GL_RG8_SNORM"
+ },
+ "R10G10B10A2_UNORM": {
+ "texFormat": "DXGI_FORMAT_R10G10B10A2_UNORM",
+ "srvFormat": "DXGI_FORMAT_R10G10B10A2_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R10G10B10A2_UNORM",
+ "channels": "rgba",
+ "componentType": "unorm",
+ "bits": { "red": 10, "green": 10, "blue": 10, "alpha": 2 },
+ "glInternalFormat": "GL_RGB10_A2"
+ },
+ "R10G10B10A2_UINT": {
+ "texFormat": "DXGI_FORMAT_R10G10B10A2_UINT",
+ "srvFormat": "DXGI_FORMAT_R10G10B10A2_UINT",
+ "rtvFormat": "DXGI_FORMAT_R10G10B10A2_UINT",
+ "channels": "rgba",
+ "componentType": "uint",
+ "bits": { "red": 10, "green": 10, "blue": 10, "alpha": 2 },
+ "glInternalFormat": "GL_RGB10_A2UI"
+ },
+ "R16G16B16A16_SINT": {
+ "texFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
+ "srvFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
+ "rtvFormat": "DXGI_FORMAT_R16G16B16A16_SINT",
+ "channels": "rgba",
+ "componentType": "int",
+ "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 },
+ "glInternalFormat": "GL_RGBA16I"
+ },
+ "R16G16B16A16_UINT": {
+ "texFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
+ "srvFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
+ "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UINT",
+ "channels": "rgba",
+ "componentType": "uint",
+ "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 },
+ "glInternalFormat": "GL_RGBA16UI"
+ },
+ "R32G32B32A32_SINT": {
+ "texFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
+ "srvFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
+ "rtvFormat": "DXGI_FORMAT_R32G32B32A32_SINT",
+ "channels": "rgba",
+ "componentType": "int",
+ "bits": { "red": 32, "green": 32, "blue": 32, "alpha": 32 },
+ "glInternalFormat": "GL_RGBA32I"
+ },
+ "R32G32B32A32_UINT": {
+ "texFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
+ "srvFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
+ "rtvFormat": "DXGI_FORMAT_R32G32B32A32_UINT",
+ "channels": "rgba",
+ "componentType": "uint",
+ "bits": { "red": 32, "green": 32, "blue": 32, "alpha": 32 },
+ "glInternalFormat": "GL_RGBA32UI"
+ },
+ "B5G6R5_UNORM": {
+ "texFormat": "DXGI_FORMAT_B5G6R5_UNORM",
+ "srvFormat": "DXGI_FORMAT_B5G6R5_UNORM",
+ "rtvFormat": "DXGI_FORMAT_B5G6R5_UNORM",
+ "channels": "bgr",
+ "componentType": "unorm",
+ "bits": { "red": 5, "green": 6, "blue": 5 },
+ "supportTest": "SupportsFormat(DXGI_FORMAT_B5G6R5_UNORM, deviceCaps)",
+ "fallbackFormat": "R8G8B8A8_UNORM"
+ },
+ "B5G5R5A1_UNORM": {
+ "texFormat": "DXGI_FORMAT_B5G5R5A1_UNORM",
+ "srvFormat": "DXGI_FORMAT_B5G5R5A1_UNORM",
+ "rtvFormat": "DXGI_FORMAT_B5G5R5A1_UNORM",
+ "channels": "bgra",
+ "componentType": "unorm",
+ "bits": { "red": 5, "green": 5, "blue": 5, "alpha": 1 },
+ "supportTest": "SupportsFormat(DXGI_FORMAT_B5G5R5A1_UNORM, deviceCaps)",
+ "fallbackFormat": "R8G8B8A8_UNORM"
+ },
+ "R8G8B8A8_SINT": {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_SINT",
+ "channels": "rgba",
+ "componentType": "int",
+ "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 },
+ "glInternalFormat": "GL_RGBA8I"
+ },
+ "R8G8B8A8_UINT": {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UINT",
+ "channels": "rgba",
+ "componentType": "uint",
+ "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 },
+ "glInternalFormat": "GL_RGBA8UI"
+ },
+ "R8G8B8A8_SNORM": {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_SNORM",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_SNORM",
+ "channels": "rgba",
+ "componentType": "snorm",
+ "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 },
+ "glInternalFormat": "GL_RGBA8_SNORM"
+ },
+ "R9G9B9E5_SHAREDEXP": {
+ "texFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP",
+ "srvFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP",
+ "channels": "rgb",
+ "componentType": "float",
+ "bits": { "red": 9, "green": 9, "blue": 9, "shared": 5 }
+ },
+ "B4G4R4A4_UNORM": {
+ "texFormat": "DXGI_FORMAT_B4G4R4A4_UNORM",
+ "srvFormat": "DXGI_FORMAT_B4G4R4A4_UNORM",
+ "rtvFormat": "DXGI_FORMAT_B4G4R4A4_UNORM",
+ "channels": "bgra",
+ "componentType": "unorm",
+ "bits": { "red": 4, "green": 4, "blue": 4, "alpha": 4 },
+ "supportTest": "SupportsFormat(DXGI_FORMAT_B4G4R4A4_UNORM, deviceCaps)",
+ "fallbackFormat": "R8G8B8A8_UNORM"
+ },
+ "R8G8B8A8_UNORM_SRGB": {
+ "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+ "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+ "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+ "channels": "rgba",
+ "componentType": "unorm",
+ "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 },
+ "glInternalFormat": "GL_SRGB8_ALPHA8"
+ },
+ "R16_UNORM": {
+ "texFormat": "DXGI_FORMAT_R16_UNORM",
+ "srvFormat": "DXGI_FORMAT_R16_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R16_UNORM",
+ "channels": "r",
+ "componentType": "unorm",
+ "bits": { "red": 16 },
+ "glInternalFormat": "GL_R16_EXT"
+ },
+ "R16G16_UNORM": {
+ "texFormat": "DXGI_FORMAT_R16G16_UNORM",
+ "srvFormat": "DXGI_FORMAT_R16G16_UNORM",
+ "rtvFormat": "DXGI_FORMAT_R16G16_UNORM",
+ "channels": "rg",
+ "componentType": "unorm",
+ "bits": { "red": 16, "green": 16 },
+ "glInternalFormat": "GL_RG16_EXT"
+ },
+ "R16_SNORM": {
+ "texFormat": "DXGI_FORMAT_R16_SNORM",
+ "srvFormat": "DXGI_FORMAT_R16_SNORM",
+ "channels": "r",
+ "componentType": "snorm",
+ "bits": { "red": 16 },
+ "glInternalFormat": "GL_R16_SNORM_EXT"
+ },
+ "R16G16_SNORM": {
+ "texFormat": "DXGI_FORMAT_R16G16_SNORM",
+ "srvFormat": "DXGI_FORMAT_R16G16_SNORM",
+ "channels": "rg",
+ "componentType": "snorm",
+ "bits": { "red": 16, "green": 16 },
+ "glInternalFormat": "GL_RG16_SNORM_EXT"
+ },
+ "R16G16B16A16_SNORM": {
+ "texFormat": "DXGI_FORMAT_R16G16B16A16_SNORM",
+ "srvFormat": "DXGI_FORMAT_R16G16B16A16_SNORM",
+ "channels": "rgba",
+ "componentType": "snorm",
+ "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 },
+ "glInternalFormat": "GL_RGBA16_SNORM_EXT"
+ }
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json
new file mode 100644
index 0000000000..3ef2355645
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json
@@ -0,0 +1,78 @@
+{
+ "GL_ALPHA16F_EXT": "R16G16B16A16_FLOAT",
+ "GL_ALPHA32F_EXT": "R32G32B32A32_FLOAT",
+ "GL_BGR5_A1_ANGLEX": "B8G8R8A8_UNORM",
+ "GL_BGRA4_ANGLEX": "B8G8R8A8_UNORM",
+ "GL_BGRA8_SRGB_ANGLEX": "B8G8R8A8_UNORM_SRGB",
+ "GL_COMPRESSED_R11_EAC": "R8_UNORM",
+ "GL_COMPRESSED_RG11_EAC": "R8G8_UNORM",
+ "GL_COMPRESSED_RGB8_ETC2": "R8G8B8A8_UNORM",
+ "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2": "R8G8B8A8_UNORM",
+ "GL_COMPRESSED_RGBA8_ETC2_EAC": "R8G8B8A8_UNORM",
+ "GL_COMPRESSED_RGBA_ASTC_4x4_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_5x4_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_5x5_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_6x5_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_6x6_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_8x5_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_8x6_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_8x8_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_10x5_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_10x6_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_10x8_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_10x10_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_12x10_KHR": "NONE",
+ "GL_COMPRESSED_RGBA_ASTC_12x12_KHR": "NONE",
+ "GL_COMPRESSED_SIGNED_R11_EAC": "R8_SNORM",
+ "GL_COMPRESSED_SIGNED_RG11_EAC": "R8G8_SNORM",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR": "NONE",
+ "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC": "R8G8B8A8_UNORM_SRGB",
+ "GL_COMPRESSED_SRGB8_ETC2": "R8G8B8A8_UNORM_SRGB",
+ "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2": "R8G8B8A8_UNORM_SRGB",
+ "GL_DEPTH_COMPONENT24": "D24_UNORM_S8_UINT",
+ "GL_DEPTH_COMPONENT32_OES": "D24_UNORM_S8_UINT",
+ "GL_ETC1_RGB8_OES": "R8G8B8A8_UNORM",
+ "GL_ETC1_RGB8_LOSSY_DECODE_ANGLE": "BC1_RGB_UNORM_BLOCK",
+ "GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE": "BC1_RGB_UNORM_BLOCK",
+ "GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE": "BC1_RGB_UNORM_SRGB_BLOCK",
+ "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE": "BC1_RGBA_UNORM_BLOCK",
+ "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE": "BC1_RGBA_UNORM_SRGB_BLOCK",
+ "GL_LUMINANCE16F_EXT": "R16G16B16A16_FLOAT",
+ "GL_LUMINANCE32F_EXT": "R32G32B32A32_FLOAT",
+ "GL_LUMINANCE8_ALPHA8_EXT": "R8G8B8A8_UNORM",
+ "GL_LUMINANCE8_EXT": "R8G8B8A8_UNORM",
+ "GL_LUMINANCE_ALPHA16F_EXT": "R16G16B16A16_FLOAT",
+ "GL_LUMINANCE_ALPHA32F_EXT": "R32G32B32A32_FLOAT",
+ "GL_RGB": "R8G8B8A8_UNORM",
+ "GL_RGB16F": "R16G16B16A16_FLOAT",
+ "GL_RGB16I": "R16G16B16A16_SINT",
+ "GL_RGB16UI": "R16G16B16A16_UINT",
+ "GL_RGB565": "B5G6R5_UNORM",
+ "GL_RGB5_A1": "B5G5R5A1_UNORM",
+ "GL_RGB8": "R8G8B8A8_UNORM",
+ "GL_RGB8I": "R8G8B8A8_SINT",
+ "GL_RGB8UI": "R8G8B8A8_UINT",
+ "GL_RGB8_SNORM": "R8G8B8A8_SNORM",
+ "GL_RGBA4": "B4G4R4A4_UNORM",
+ "GL_SRGB8": "R8G8B8A8_UNORM_SRGB",
+ "GL_STENCIL_INDEX8": "D24_UNORM_S8_UINT",
+ "GL_RGB16_EXT": "R16G16B16A16_UNORM",
+ "GL_RGBA16_EXT": "R16G16B16A16_UNORM",
+ "GL_RGB16_SNORM_EXT": "R16G16B16A16_SNORM",
+ "GL_RGB32F": "R32G32B32A32_FLOAT",
+ "GL_RGB32I": "R32G32B32A32_SINT",
+ "GL_RGB32UI": "R32G32B32A32_UINT"
+}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp
new file mode 100644
index 0000000000..a9dfec56b8
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp
@@ -0,0 +1,35 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Helper routines for the D3D11 texture format table.
+
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+
+#include "libANGLE/renderer/load_functions_table.h"
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+const Format &Format::getSwizzleFormat(const Renderer11DeviceCaps &deviceCaps) const
+{
+ return (swizzleFormat == internalFormat ? *this : Format::Get(swizzleFormat, deviceCaps));
+}
+
+LoadFunctionMap Format::getLoadFunctions() const
+{
+ return GetLoadFunctionsMap(internalFormat, formatID);
+}
+
+const angle::Format &Format::format() const
+{
+ return angle::Format::Get(formatID);
+}
+
+} // namespace d3d11
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h
index 1606a28a73..3efcb81adb 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h
@@ -12,50 +12,91 @@
#include <map>
+#include "common/angleutils.h"
#include "common/platform.h"
+#include "libANGLE/renderer/Format.h"
+#include "libANGLE/renderer/renderer_utils.h"
#include "libANGLE/renderer/d3d/formatutilsD3D.h"
-#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
namespace rx
{
-namespace d3d11
-{
+struct Renderer11DeviceCaps;
-struct LoadImageFunctionInfo
+namespace d3d11
{
- LoadImageFunctionInfo() : loadFunction(nullptr), requiresConversion(false) {}
- LoadImageFunctionInfo(LoadImageFunction loadFunction, bool requiresConversion)
- : loadFunction(loadFunction), requiresConversion(requiresConversion)
- {
- }
-
- LoadImageFunction loadFunction;
- bool requiresConversion;
-};
-struct TextureFormat
+// For sized GL internal formats, there are several possible corresponding D3D11 formats depending
+// on device capabilities.
+// This structure allows querying for the DXGI texture formats to use for textures, SRVs, RTVs and
+// DSVs given a GL internal format.
+struct Format final : private angle::NonCopyable
{
- TextureFormat();
+ constexpr Format();
+ constexpr Format(GLenum internalFormat,
+ angle::Format::ID formatID,
+ DXGI_FORMAT texFormat,
+ DXGI_FORMAT srvFormat,
+ DXGI_FORMAT rtvFormat,
+ DXGI_FORMAT dsvFormat,
+ DXGI_FORMAT blitSRVFormat,
+ GLenum swizzleFormat,
+ InitializeTextureDataFunction internalFormatInitializer);
+
+ static const Format &Get(GLenum internalFormat, const Renderer11DeviceCaps &deviceCaps);
+
+ const Format &getSwizzleFormat(const Renderer11DeviceCaps &deviceCaps) const;
+ LoadFunctionMap getLoadFunctions() const;
+ const angle::Format &format() const;
+
+ GLenum internalFormat;
+ angle::Format::ID formatID;
DXGI_FORMAT texFormat;
DXGI_FORMAT srvFormat;
DXGI_FORMAT rtvFormat;
DXGI_FORMAT dsvFormat;
- DXGI_FORMAT renderFormat;
- DXGI_FORMAT swizzleTexFormat;
- DXGI_FORMAT swizzleSRVFormat;
- DXGI_FORMAT swizzleRTVFormat;
+ DXGI_FORMAT blitSRVFormat;
- InitializeTextureDataFunction dataInitializerFunction;
- typedef std::map<GLenum, LoadImageFunctionInfo> LoadFunctionMap;
+ GLenum swizzleFormat;
- LoadFunctionMap loadFunctions;
+ InitializeTextureDataFunction dataInitializerFunction;
};
-const TextureFormat &GetTextureFormatInfo(GLenum internalformat,
- const Renderer11DeviceCaps &renderer11DeviceCaps);
+constexpr Format::Format()
+ : internalFormat(GL_NONE),
+ formatID(angle::Format::ID::NONE),
+ texFormat(DXGI_FORMAT_UNKNOWN),
+ srvFormat(DXGI_FORMAT_UNKNOWN),
+ rtvFormat(DXGI_FORMAT_UNKNOWN),
+ dsvFormat(DXGI_FORMAT_UNKNOWN),
+ blitSRVFormat(DXGI_FORMAT_UNKNOWN),
+ swizzleFormat(GL_NONE),
+ dataInitializerFunction(nullptr)
+{
+}
+
+constexpr Format::Format(GLenum internalFormat,
+ angle::Format::ID formatID,
+ DXGI_FORMAT texFormat,
+ DXGI_FORMAT srvFormat,
+ DXGI_FORMAT rtvFormat,
+ DXGI_FORMAT dsvFormat,
+ DXGI_FORMAT blitSRVFormat,
+ GLenum swizzleFormat,
+ InitializeTextureDataFunction internalFormatInitializer)
+ : internalFormat(internalFormat),
+ formatID(formatID),
+ texFormat(texFormat),
+ srvFormat(srvFormat),
+ rtvFormat(rtvFormat),
+ dsvFormat(dsvFormat),
+ blitSRVFormat(blitSRVFormat),
+ swizzleFormat(swizzleFormat),
+ dataInitializerFunction(internalFormatInitializer)
+{
+}
} // namespace d3d11
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp
index 0b214c9756..3c1c2bcd50 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp
@@ -1,7 +1,7 @@
// GENERATED FILE - DO NOT EDIT.
// Generated by gen_texture_format_table.py using data from texture_format_data.json
//
-// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -11,12 +11,15 @@
#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "image_util/copyimage.h"
+#include "image_util/generatemip.h"
+#include "image_util/loadimage.h"
+
#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
-#include "libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h"
-#include "libANGLE/renderer/d3d/d3d11/load_functions_table.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
-#include "libANGLE/renderer/d3d/d3d11/swizzle_format_info.h"
-#include "libANGLE/renderer/d3d/loadimage.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h"
+
+using namespace angle;
namespace rx
{
@@ -24,1756 +27,1899 @@ namespace rx
namespace d3d11
{
-namespace
-{
-
-typedef bool (*FormatSupportFunction)(const Renderer11DeviceCaps &);
-
-bool AnyDevice(const Renderer11DeviceCaps &deviceCaps)
-{
- return true;
-}
-
-bool OnlyFL10Plus(const Renderer11DeviceCaps &deviceCaps)
-{
- return (deviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0);
-}
-
-bool OnlyFL9_3(const Renderer11DeviceCaps &deviceCaps)
-{
- return (deviceCaps.featureLevel == D3D_FEATURE_LEVEL_9_3);
-}
-
-template <DXGI_FORMAT format, bool requireSupport>
-bool SupportsFormat(const Renderer11DeviceCaps &deviceCaps)
-{
- // Must support texture, SRV and RTV support
- UINT mustSupport = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE |
- D3D11_FORMAT_SUPPORT_SHADER_SAMPLE | D3D11_FORMAT_SUPPORT_MIP |
- D3D11_FORMAT_SUPPORT_RENDER_TARGET;
-
- if (d3d11_gl::GetMaximumClientVersion(deviceCaps.featureLevel) > 2)
- {
- mustSupport |= D3D11_FORMAT_SUPPORT_TEXTURE3D;
- }
-
- bool fullSupport = false;
- if (format == DXGI_FORMAT_B5G6R5_UNORM)
- {
- // All hardware that supports DXGI_FORMAT_B5G6R5_UNORM should support autogen mipmaps, but
- // check anyway.
- mustSupport |= D3D11_FORMAT_SUPPORT_MIP_AUTOGEN;
- fullSupport = ((deviceCaps.B5G6R5support & mustSupport) == mustSupport);
- }
- else if (format == DXGI_FORMAT_B4G4R4A4_UNORM)
- {
- fullSupport = ((deviceCaps.B4G4R4A4support & mustSupport) == mustSupport);
- }
- else if (format == DXGI_FORMAT_B5G5R5A1_UNORM)
- {
- fullSupport = ((deviceCaps.B5G5R5A1support & mustSupport) == mustSupport);
- }
- else
- {
- UNREACHABLE();
- return false;
- }
-
- // This 'SupportsFormat' function is used by individual entries in the D3D11 Format Map below,
- // which maps GL formats to DXGI formats.
- if (requireSupport)
- {
- // This means that ANGLE would like to use the entry in the map if the inputted DXGI format
- // *IS* supported.
- // e.g. the entry might map GL_RGB5_A1 to DXGI_FORMAT_B5G5R5A1, which should only be used if
- // DXGI_FORMAT_B5G5R5A1 is supported.
- // In this case, we should only return 'true' if the format *IS* supported.
- return fullSupport;
- }
- else
- {
- // This means that ANGLE would like to use the entry in the map if the inputted DXGI format
- // *ISN'T* supported.
- // This might be a fallback entry. e.g. for ANGLE to use DXGI_FORMAT_R8G8B8A8_UNORM if
- // DXGI_FORMAT_B5G5R5A1 isn't supported.
- // In this case, we should only return 'true' if the format *ISN'T* supported.
- return !fullSupport;
- }
-}
-
-// End Format Support Functions
-
-// For sized GL internal formats, there are several possible corresponding D3D11 formats depending
-// on device capabilities.
-// This function allows querying for the DXGI texture formats to use for textures, SRVs, RTVs and
-// DSVs given a GL internal format.
-const TextureFormat GetD3D11FormatInfo(GLenum internalFormat,
- DXGI_FORMAT texFormat,
- DXGI_FORMAT srvFormat,
- DXGI_FORMAT rtvFormat,
- DXGI_FORMAT dsvFormat)
-{
- TextureFormat info;
- info.texFormat = texFormat;
- info.srvFormat = srvFormat;
- info.rtvFormat = rtvFormat;
- info.dsvFormat = dsvFormat;
-
- // Given a GL internal format, the renderFormat is the DSV format if it is depth- or
- // stencil-renderable,
- // the RTV format if it is color-renderable, and the (nonrenderable) texture format otherwise.
- if (dsvFormat != DXGI_FORMAT_UNKNOWN)
- {
- info.renderFormat = dsvFormat;
- }
- else if (rtvFormat != DXGI_FORMAT_UNKNOWN)
- {
- info.renderFormat = rtvFormat;
- }
- else if (texFormat != DXGI_FORMAT_UNKNOWN)
- {
- info.renderFormat = texFormat;
- }
- else
- {
- info.renderFormat = DXGI_FORMAT_UNKNOWN;
- }
-
- // Compute the swizzle formats
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
- if (internalFormat != GL_NONE && formatInfo.pixelBytes > 0)
- {
- if (formatInfo.componentCount != 4 || texFormat == DXGI_FORMAT_UNKNOWN ||
- srvFormat == DXGI_FORMAT_UNKNOWN || rtvFormat == DXGI_FORMAT_UNKNOWN)
- {
- // Get the maximum sized component
- unsigned int maxBits = 1;
- if (formatInfo.compressed)
- {
- unsigned int compressedBitsPerBlock = formatInfo.pixelBytes * 8;
- unsigned int blockSize =
- formatInfo.compressedBlockWidth * formatInfo.compressedBlockHeight;
- maxBits = std::max(compressedBitsPerBlock / blockSize, maxBits);
- }
- else
- {
- maxBits = std::max(maxBits, formatInfo.alphaBits);
- maxBits = std::max(maxBits, formatInfo.redBits);
- maxBits = std::max(maxBits, formatInfo.greenBits);
- maxBits = std::max(maxBits, formatInfo.blueBits);
- maxBits = std::max(maxBits, formatInfo.luminanceBits);
- maxBits = std::max(maxBits, formatInfo.depthBits);
- }
-
- maxBits = roundUp(maxBits, 8U);
-
- const SwizzleFormatInfo &swizzleInfo =
- GetSwizzleFormatInfo(maxBits, formatInfo.componentType);
- info.swizzleTexFormat = swizzleInfo.mTexFormat;
- info.swizzleSRVFormat = swizzleInfo.mSRVFormat;
- info.swizzleRTVFormat = swizzleInfo.mRTVFormat;
- }
- else
- {
- // The original texture format is suitable for swizzle operations
- info.swizzleTexFormat = texFormat;
- info.swizzleSRVFormat = srvFormat;
- info.swizzleRTVFormat = rtvFormat;
- }
- }
- else
- {
- // Not possible to swizzle with this texture format since it is either unsized or GL_NONE
- info.swizzleTexFormat = DXGI_FORMAT_UNKNOWN;
- info.swizzleSRVFormat = DXGI_FORMAT_UNKNOWN;
- info.swizzleRTVFormat = DXGI_FORMAT_UNKNOWN;
- }
-
- // Check if there is an initialization function for this texture format
- info.dataInitializerFunction = GetInternalFormatInitializer(internalFormat, texFormat);
- // Gather all the load functions for this internal format
- info.loadFunctions = GetLoadFunctionsMap(internalFormat, texFormat);
-
- ASSERT(info.loadFunctions.size() != 0 || internalFormat == GL_NONE);
-
- return info;
-}
-
-} // namespace
-
-TextureFormat::TextureFormat()
- : texFormat(DXGI_FORMAT_UNKNOWN),
- srvFormat(DXGI_FORMAT_UNKNOWN),
- rtvFormat(DXGI_FORMAT_UNKNOWN),
- dsvFormat(DXGI_FORMAT_UNKNOWN),
- renderFormat(DXGI_FORMAT_UNKNOWN),
- swizzleTexFormat(DXGI_FORMAT_UNKNOWN),
- swizzleSRVFormat(DXGI_FORMAT_UNKNOWN),
- swizzleRTVFormat(DXGI_FORMAT_UNKNOWN),
- dataInitializerFunction(NULL),
- loadFunctions()
-{
-}
-
-const TextureFormat &GetTextureFormatInfo(GLenum internalFormat,
- const Renderer11DeviceCaps &renderer11DeviceCaps)
+// static
+const Format &Format::Get(GLenum internalFormat, const Renderer11DeviceCaps &deviceCaps)
{
// clang-format off
switch (internalFormat)
{
- case GL_ALPHA:
- {
- if (OnlyFL10Plus(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_A8_UNORM,
- DXGI_FORMAT_A8_UNORM,
- DXGI_FORMAT_A8_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else if (OnlyFL9_3(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
- }
case GL_ALPHA16F_EXT:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R16G16B16A16_FLOAT,
- DXGI_FORMAT_R16G16B16A16_FLOAT,
- DXGI_FORMAT_R16G16B16A16_FLOAT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_ALPHA16F_EXT,
+ angle::Format::ID::R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ GL_RGBA16F,
+ nullptr);
+ return info;
}
case GL_ALPHA32F_EXT:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R32G32B32A32_FLOAT,
- DXGI_FORMAT_R32G32B32A32_FLOAT,
- DXGI_FORMAT_R32G32B32A32_FLOAT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_ALPHA32F_EXT,
+ angle::Format::ID::R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ GL_RGBA32F,
+ nullptr);
+ return info;
}
case GL_ALPHA8_EXT:
{
- if (OnlyFL10Plus(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_A8_UNORM,
- DXGI_FORMAT_A8_UNORM,
- DXGI_FORMAT_A8_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else if (OnlyFL9_3(renderer11DeviceCaps))
+ if (OnlyFL10Plus(deviceCaps))
{
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
+ static constexpr Format info(GL_ALPHA8_EXT,
+ angle::Format::ID::A8_UNORM,
+ DXGI_FORMAT_A8_UNORM,
+ DXGI_FORMAT_A8_UNORM,
+ DXGI_FORMAT_A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_A8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
}
else
{
- break;
+ static constexpr Format info(GL_ALPHA8_EXT,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
}
}
- case GL_BGR5_A1_ANGLEX:
+ case GL_BGR565_ANGLEX:
{
- if (AnyDevice(renderer11DeviceCaps))
+ if (SupportsFormat(DXGI_FORMAT_B5G6R5_UNORM, deviceCaps))
{
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_B8G8R8A8_UNORM,
- DXGI_FORMAT_B8G8R8A8_UNORM,
- DXGI_FORMAT_B8G8R8A8_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
+ static constexpr Format info(GL_BGR565_ANGLEX,
+ angle::Format::ID::B5G6R5_UNORM,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
}
else
{
- break;
+ static constexpr Format info(GL_BGR565_ANGLEX,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
}
}
- case GL_BGRA4_ANGLEX:
+ case GL_BGR5_A1_ANGLEX:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_B8G8R8A8_UNORM,
- DXGI_FORMAT_B8G8R8A8_UNORM,
- DXGI_FORMAT_B8G8R8A8_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_BGR5_A1_ANGLEX,
+ angle::Format::ID::B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ GL_BGRA8_EXT,
+ nullptr);
+ return info;
}
- case GL_BGRA8_EXT:
+ case GL_BGRA4_ANGLEX:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_B8G8R8A8_UNORM,
- DXGI_FORMAT_B8G8R8A8_UNORM,
- DXGI_FORMAT_B8G8R8A8_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_BGRA4_ANGLEX,
+ angle::Format::ID::B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ GL_BGRA8_EXT,
+ nullptr);
+ return info;
}
- case GL_BGRA_EXT:
+ case GL_BGRA8_EXT:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_B8G8R8A8_UNORM,
- DXGI_FORMAT_B8G8R8A8_UNORM,
- DXGI_FORMAT_B8G8R8A8_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_BGRA8_EXT,
+ angle::Format::ID::B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ GL_BGRA8_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_BGRA8_SRGB_ANGLEX:
+ {
+ static constexpr Format info(GL_BGRA8_SRGB_ANGLEX,
+ angle::Format::ID::B8G8R8A8_UNORM_SRGB,
+ DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
+ DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
+ DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
+ GL_BGRA8_SRGB_ANGLEX,
+ nullptr);
+ return info;
}
case GL_COMPRESSED_R11_EAC:
{
- if (OnlyFL10Plus(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8_UNORM,
- DXGI_FORMAT_R8_UNORM,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_COMPRESSED_R11_EAC,
+ angle::Format::ID::R8_UNORM,
+ DXGI_FORMAT_R8_UNORM,
+ DXGI_FORMAT_R8_UNORM,
+ DXGI_FORMAT_R8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
}
case GL_COMPRESSED_RG11_EAC:
{
- if (OnlyFL10Plus(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8_UNORM,
- DXGI_FORMAT_R8G8_UNORM,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_COMPRESSED_RG11_EAC,
+ angle::Format::ID::R8G8_UNORM,
+ DXGI_FORMAT_R8G8_UNORM,
+ DXGI_FORMAT_R8G8_UNORM,
+ DXGI_FORMAT_R8G8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
}
case GL_COMPRESSED_RGB8_ETC2:
{
- if (OnlyFL10Plus(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_COMPRESSED_RGB8_ETC2,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
+ }
+ case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE,
+ angle::Format::ID::BC1_RGB_UNORM_BLOCK,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC1_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
}
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
{
- if (OnlyFL10Plus(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
+ }
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE,
+ angle::Format::ID::BC1_RGBA_UNORM_BLOCK,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC1_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
}
case GL_COMPRESSED_RGBA8_ETC2_EAC:
{
- if (OnlyFL10Plus(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_COMPRESSED_RGBA8_ETC2_EAC,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x10_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x5_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x6_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x8_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_12x10_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_12x12_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_4x4_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_5x4_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_5x5_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_6x5_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_6x6_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_8x5_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_8x6_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_8x8_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
}
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_BC1_UNORM,
- DXGI_FORMAT_BC1_UNORM,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
+ angle::Format::ID::BC1_RGBA_UNORM_BLOCK,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC1_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
}
case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_BC2_UNORM,
- DXGI_FORMAT_BC2_UNORM,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE,
+ angle::Format::ID::BC2_RGBA_UNORM_BLOCK,
+ DXGI_FORMAT_BC2_UNORM,
+ DXGI_FORMAT_BC2_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC2_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
}
case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_BC3_UNORM,
- DXGI_FORMAT_BC3_UNORM,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE,
+ angle::Format::ID::BC3_RGBA_UNORM_BLOCK,
+ DXGI_FORMAT_BC3_UNORM,
+ DXGI_FORMAT_BC3_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC3_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
}
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_BC1_UNORM,
- DXGI_FORMAT_BC1_UNORM,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
+ angle::Format::ID::BC1_RGB_UNORM_BLOCK,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC1_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
}
case GL_COMPRESSED_SIGNED_R11_EAC:
{
- if (OnlyFL10Plus(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8_SNORM,
- DXGI_FORMAT_R8_SNORM,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_COMPRESSED_SIGNED_R11_EAC,
+ angle::Format::ID::R8_SNORM,
+ DXGI_FORMAT_R8_SNORM,
+ DXGI_FORMAT_R8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8_SNORM,
+ GL_RGBA8_SNORM,
+ nullptr);
+ return info;
}
case GL_COMPRESSED_SIGNED_RG11_EAC:
{
- if (OnlyFL10Plus(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8_SNORM,
- DXGI_FORMAT_R8G8_SNORM,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_COMPRESSED_SIGNED_RG11_EAC,
+ angle::Format::ID::R8G8_SNORM,
+ DXGI_FORMAT_R8G8_SNORM,
+ DXGI_FORMAT_R8G8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8_SNORM,
+ GL_RGBA8_SNORM,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
}
case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
{
- if (OnlyFL10Plus(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
- DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,
+ angle::Format::ID::R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ GL_SRGB8_ALPHA8,
+ nullptr);
+ return info;
}
case GL_COMPRESSED_SRGB8_ETC2:
{
- if (OnlyFL10Plus(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
- DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ETC2,
+ angle::Format::ID::R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ GL_SRGB8_ALPHA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE,
+ angle::Format::ID::BC1_RGB_UNORM_SRGB_BLOCK,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ GL_RGBA8,
+ nullptr);
+ return info;
}
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
{
- if (OnlyFL10Plus(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
- DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
+ angle::Format::ID::R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ GL_SRGB8_ALPHA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE,
+ angle::Format::ID::BC1_RGBA_UNORM_SRGB_BLOCK,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,
+ angle::Format::ID::BC1_RGBA_UNORM_SRGB_BLOCK,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,
+ angle::Format::ID::BC2_RGBA_UNORM_SRGB_BLOCK,
+ DXGI_FORMAT_BC2_UNORM_SRGB,
+ DXGI_FORMAT_BC2_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC2_UNORM_SRGB,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,
+ angle::Format::ID::BC3_RGBA_UNORM_SRGB_BLOCK,
+ DXGI_FORMAT_BC3_UNORM_SRGB,
+ DXGI_FORMAT_BC3_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC3_UNORM_SRGB,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT,
+ angle::Format::ID::BC1_RGB_UNORM_SRGB_BLOCK,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ GL_RGBA8,
+ nullptr);
+ return info;
}
case GL_DEPTH24_STENCIL8:
{
- if (OnlyFL9_3(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_D24_UNORM_S8_UINT,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_D24_UNORM_S8_UINT);
- return textureFormat;
- }
- else if (OnlyFL10Plus(renderer11DeviceCaps))
+ if (OnlyFL10Plus(deviceCaps))
{
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R24G8_TYPELESS,
- DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_D24_UNORM_S8_UINT);
- return textureFormat;
+ static constexpr Format info(GL_DEPTH24_STENCIL8,
+ angle::Format::ID::D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24G8_TYPELESS,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ GL_RGBA32F,
+ nullptr);
+ return info;
}
else
{
- break;
+ static constexpr Format info(GL_DEPTH24_STENCIL8,
+ angle::Format::ID::D24_UNORM_S8_UINT,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA32F,
+ nullptr);
+ return info;
}
}
case GL_DEPTH32F_STENCIL8:
{
- if (OnlyFL9_3(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else if (OnlyFL10Plus(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R32G8X24_TYPELESS,
- DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_D32_FLOAT_S8X24_UINT);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_DEPTH32F_STENCIL8,
+ angle::Format::ID::D32_FLOAT_S8X24_UINT,
+ DXGI_FORMAT_R32G8X24_TYPELESS,
+ DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D32_FLOAT_S8X24_UINT,
+ DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS,
+ GL_RGBA32F,
+ nullptr);
+ return info;
}
case GL_DEPTH_COMPONENT16:
{
- if (OnlyFL9_3(renderer11DeviceCaps))
+ if (OnlyFL10Plus(deviceCaps))
{
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_D16_UNORM,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_D16_UNORM);
- return textureFormat;
- }
- else if (OnlyFL10Plus(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R16_TYPELESS,
- DXGI_FORMAT_R16_UNORM,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_D16_UNORM);
- return textureFormat;
+ static constexpr Format info(GL_DEPTH_COMPONENT16,
+ angle::Format::ID::D16_UNORM,
+ DXGI_FORMAT_R16_TYPELESS,
+ DXGI_FORMAT_R16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D16_UNORM,
+ DXGI_FORMAT_R16_UNORM,
+ GL_RGBA16_EXT,
+ nullptr);
+ return info;
}
else
{
- break;
+ static constexpr Format info(GL_DEPTH_COMPONENT16,
+ angle::Format::ID::D16_UNORM,
+ DXGI_FORMAT_D16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA16_EXT,
+ nullptr);
+ return info;
}
}
case GL_DEPTH_COMPONENT24:
{
- if (OnlyFL9_3(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_D24_UNORM_S8_UINT,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_D24_UNORM_S8_UINT);
- return textureFormat;
- }
- else if (OnlyFL10Plus(renderer11DeviceCaps))
+ if (OnlyFL10Plus(deviceCaps))
{
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R24G8_TYPELESS,
- DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_D24_UNORM_S8_UINT);
- return textureFormat;
+ static constexpr Format info(GL_DEPTH_COMPONENT24,
+ angle::Format::ID::D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24G8_TYPELESS,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ GL_RGBA32F,
+ nullptr);
+ return info;
}
else
{
- break;
+ static constexpr Format info(GL_DEPTH_COMPONENT24,
+ angle::Format::ID::D24_UNORM_S8_UINT,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA32F,
+ nullptr);
+ return info;
}
}
case GL_DEPTH_COMPONENT32F:
{
- if (OnlyFL9_3(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else if (OnlyFL10Plus(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R32_TYPELESS,
- DXGI_FORMAT_R32_FLOAT,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_D32_FLOAT);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_DEPTH_COMPONENT32F,
+ angle::Format::ID::D32_FLOAT,
+ DXGI_FORMAT_R32_TYPELESS,
+ DXGI_FORMAT_R32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D32_FLOAT,
+ DXGI_FORMAT_R32_FLOAT,
+ GL_RGBA32F,
+ nullptr);
+ return info;
}
case GL_DEPTH_COMPONENT32_OES:
{
- if (OnlyFL10Plus(renderer11DeviceCaps))
+ if (OnlyFL10Plus(deviceCaps))
{
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R24G8_TYPELESS,
- DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_D24_UNORM_S8_UINT);
- return textureFormat;
+ static constexpr Format info(GL_DEPTH_COMPONENT32_OES,
+ angle::Format::ID::D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24G8_TYPELESS,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ GL_RGBA32F,
+ nullptr);
+ return info;
}
else
{
- break;
+ static constexpr Format info(GL_DEPTH_COMPONENT32_OES,
+ angle::Format::ID::D24_UNORM_S8_UINT,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA32F,
+ nullptr);
+ return info;
}
}
case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_BC1_UNORM,
- DXGI_FORMAT_BC1_UNORM,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_ETC1_RGB8_LOSSY_DECODE_ANGLE,
+ angle::Format::ID::BC1_RGB_UNORM_BLOCK,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC1_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
}
case GL_ETC1_RGB8_OES:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
- }
- case GL_LUMINANCE:
- {
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_ETC1_RGB8_OES,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
}
case GL_LUMINANCE16F_EXT:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R16G16B16A16_FLOAT,
- DXGI_FORMAT_R16G16B16A16_FLOAT,
- DXGI_FORMAT_R16G16B16A16_FLOAT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_LUMINANCE16F_EXT,
+ angle::Format::ID::R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ GL_RGBA16F,
+ Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>);
+ return info;
}
case GL_LUMINANCE32F_EXT:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R32G32B32A32_FLOAT,
- DXGI_FORMAT_R32G32B32A32_FLOAT,
- DXGI_FORMAT_R32G32B32A32_FLOAT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_LUMINANCE32F_EXT,
+ angle::Format::ID::R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ GL_RGBA32F,
+ Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000, gl::Float32One>);
+ return info;
}
case GL_LUMINANCE8_ALPHA8_EXT:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_LUMINANCE8_ALPHA8_EXT,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
}
case GL_LUMINANCE8_EXT:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
- }
- case GL_LUMINANCE_ALPHA:
- {
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_LUMINANCE8_EXT,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
}
case GL_LUMINANCE_ALPHA16F_EXT:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R16G16B16A16_FLOAT,
- DXGI_FORMAT_R16G16B16A16_FLOAT,
- DXGI_FORMAT_R16G16B16A16_FLOAT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_LUMINANCE_ALPHA16F_EXT,
+ angle::Format::ID::R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ GL_RGBA16F,
+ nullptr);
+ return info;
}
case GL_LUMINANCE_ALPHA32F_EXT:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R32G32B32A32_FLOAT,
- DXGI_FORMAT_R32G32B32A32_FLOAT,
- DXGI_FORMAT_R32G32B32A32_FLOAT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_LUMINANCE_ALPHA32F_EXT,
+ angle::Format::ID::R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ GL_RGBA32F,
+ nullptr);
+ return info;
}
case GL_NONE:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_NONE,
+ angle::Format::ID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
}
case GL_R11F_G11F_B10F:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R11G11B10_FLOAT,
- DXGI_FORMAT_R11G11B10_FLOAT,
- DXGI_FORMAT_R11G11B10_FLOAT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_R11F_G11F_B10F,
+ angle::Format::ID::R11G11B10_FLOAT,
+ DXGI_FORMAT_R11G11B10_FLOAT,
+ DXGI_FORMAT_R11G11B10_FLOAT,
+ DXGI_FORMAT_R11G11B10_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R11G11B10_FLOAT,
+ GL_RGBA16F_EXT,
+ nullptr);
+ return info;
}
case GL_R16F:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R16_FLOAT,
- DXGI_FORMAT_R16_FLOAT,
- DXGI_FORMAT_R16_FLOAT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_R16F,
+ angle::Format::ID::R16_FLOAT,
+ DXGI_FORMAT_R16_FLOAT,
+ DXGI_FORMAT_R16_FLOAT,
+ DXGI_FORMAT_R16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_FLOAT,
+ GL_RGBA16F_EXT,
+ nullptr);
+ return info;
}
case GL_R16I:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R16_SINT,
- DXGI_FORMAT_R16_SINT,
- DXGI_FORMAT_R16_SINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_R16I,
+ angle::Format::ID::R16_SINT,
+ DXGI_FORMAT_R16_SINT,
+ DXGI_FORMAT_R16_SINT,
+ DXGI_FORMAT_R16_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_SINT,
+ GL_RGBA16I,
+ nullptr);
+ return info;
}
case GL_R16UI:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R16_UINT,
- DXGI_FORMAT_R16_UINT,
- DXGI_FORMAT_R16_UINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_R16UI,
+ angle::Format::ID::R16_UINT,
+ DXGI_FORMAT_R16_UINT,
+ DXGI_FORMAT_R16_UINT,
+ DXGI_FORMAT_R16_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_UINT,
+ GL_RGBA16I,
+ nullptr);
+ return info;
+ }
+ case GL_R16_EXT:
+ {
+ static constexpr Format info(GL_R16_EXT,
+ angle::Format::ID::R16_UNORM,
+ DXGI_FORMAT_R16_UNORM,
+ DXGI_FORMAT_R16_UNORM,
+ DXGI_FORMAT_R16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_UNORM,
+ GL_RGBA16_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_R16_SNORM_EXT:
+ {
+ static constexpr Format info(GL_R16_SNORM_EXT,
+ angle::Format::ID::R16_SNORM,
+ DXGI_FORMAT_R16_SNORM,
+ DXGI_FORMAT_R16_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_SNORM,
+ GL_RGBA16_SNORM_EXT,
+ nullptr);
+ return info;
}
case GL_R32F:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R32_FLOAT,
- DXGI_FORMAT_R32_FLOAT,
- DXGI_FORMAT_R32_FLOAT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_R32F,
+ angle::Format::ID::R32_FLOAT,
+ DXGI_FORMAT_R32_FLOAT,
+ DXGI_FORMAT_R32_FLOAT,
+ DXGI_FORMAT_R32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32_FLOAT,
+ GL_RGBA32F,
+ nullptr);
+ return info;
}
case GL_R32I:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R32_SINT,
- DXGI_FORMAT_R32_SINT,
- DXGI_FORMAT_R32_SINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_R32I,
+ angle::Format::ID::R32_SINT,
+ DXGI_FORMAT_R32_SINT,
+ DXGI_FORMAT_R32_SINT,
+ DXGI_FORMAT_R32_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32_SINT,
+ GL_RGBA32I,
+ nullptr);
+ return info;
}
case GL_R32UI:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R32_UINT,
- DXGI_FORMAT_R32_UINT,
- DXGI_FORMAT_R32_UINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_R32UI,
+ angle::Format::ID::R32_UINT,
+ DXGI_FORMAT_R32_UINT,
+ DXGI_FORMAT_R32_UINT,
+ DXGI_FORMAT_R32_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32_UINT,
+ GL_RGBA32I,
+ nullptr);
+ return info;
}
case GL_R8:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8_UNORM,
- DXGI_FORMAT_R8_UNORM,
- DXGI_FORMAT_R8_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_R8,
+ angle::Format::ID::R8_UNORM,
+ DXGI_FORMAT_R8_UNORM,
+ DXGI_FORMAT_R8_UNORM,
+ DXGI_FORMAT_R8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
}
case GL_R8I:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8_SINT,
- DXGI_FORMAT_R8_SINT,
- DXGI_FORMAT_R8_SINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_R8I,
+ angle::Format::ID::R8_SINT,
+ DXGI_FORMAT_R8_SINT,
+ DXGI_FORMAT_R8_SINT,
+ DXGI_FORMAT_R8_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8_SINT,
+ GL_RGBA8I,
+ nullptr);
+ return info;
}
case GL_R8UI:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8_UINT,
- DXGI_FORMAT_R8_UINT,
- DXGI_FORMAT_R8_UINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_R8UI,
+ angle::Format::ID::R8_UINT,
+ DXGI_FORMAT_R8_UINT,
+ DXGI_FORMAT_R8_UINT,
+ DXGI_FORMAT_R8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8_UINT,
+ GL_RGBA8I,
+ nullptr);
+ return info;
}
case GL_R8_SNORM:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8_SNORM,
- DXGI_FORMAT_R8_SNORM,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_R8_SNORM,
+ angle::Format::ID::R8_SNORM,
+ DXGI_FORMAT_R8_SNORM,
+ DXGI_FORMAT_R8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8_SNORM,
+ GL_RGBA8_SNORM,
+ nullptr);
+ return info;
}
case GL_RG16F:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R16G16_FLOAT,
- DXGI_FORMAT_R16G16_FLOAT,
- DXGI_FORMAT_R16G16_FLOAT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RG16F,
+ angle::Format::ID::R16G16_FLOAT,
+ DXGI_FORMAT_R16G16_FLOAT,
+ DXGI_FORMAT_R16G16_FLOAT,
+ DXGI_FORMAT_R16G16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_FLOAT,
+ GL_RGBA16F_EXT,
+ nullptr);
+ return info;
}
case GL_RG16I:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R16G16_SINT,
- DXGI_FORMAT_R16G16_SINT,
- DXGI_FORMAT_R16G16_SINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RG16I,
+ angle::Format::ID::R16G16_SINT,
+ DXGI_FORMAT_R16G16_SINT,
+ DXGI_FORMAT_R16G16_SINT,
+ DXGI_FORMAT_R16G16_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_SINT,
+ GL_RGBA16I,
+ nullptr);
+ return info;
}
case GL_RG16UI:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R16G16_UINT,
- DXGI_FORMAT_R16G16_UINT,
- DXGI_FORMAT_R16G16_UINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RG16UI,
+ angle::Format::ID::R16G16_UINT,
+ DXGI_FORMAT_R16G16_UINT,
+ DXGI_FORMAT_R16G16_UINT,
+ DXGI_FORMAT_R16G16_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_UINT,
+ GL_RGBA16I,
+ nullptr);
+ return info;
+ }
+ case GL_RG16_EXT:
+ {
+ static constexpr Format info(GL_RG16_EXT,
+ angle::Format::ID::R16G16_UNORM,
+ DXGI_FORMAT_R16G16_UNORM,
+ DXGI_FORMAT_R16G16_UNORM,
+ DXGI_FORMAT_R16G16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_UNORM,
+ GL_RGBA16_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_RG16_SNORM_EXT:
+ {
+ static constexpr Format info(GL_RG16_SNORM_EXT,
+ angle::Format::ID::R16G16_SNORM,
+ DXGI_FORMAT_R16G16_SNORM,
+ DXGI_FORMAT_R16G16_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_SNORM,
+ GL_RGBA16_SNORM_EXT,
+ nullptr);
+ return info;
}
case GL_RG32F:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R32G32_FLOAT,
- DXGI_FORMAT_R32G32_FLOAT,
- DXGI_FORMAT_R32G32_FLOAT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RG32F,
+ angle::Format::ID::R32G32_FLOAT,
+ DXGI_FORMAT_R32G32_FLOAT,
+ DXGI_FORMAT_R32G32_FLOAT,
+ DXGI_FORMAT_R32G32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32_FLOAT,
+ GL_RGBA32F,
+ nullptr);
+ return info;
}
case GL_RG32I:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R32G32_SINT,
- DXGI_FORMAT_R32G32_SINT,
- DXGI_FORMAT_R32G32_SINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RG32I,
+ angle::Format::ID::R32G32_SINT,
+ DXGI_FORMAT_R32G32_SINT,
+ DXGI_FORMAT_R32G32_SINT,
+ DXGI_FORMAT_R32G32_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32_SINT,
+ GL_RGBA32I,
+ nullptr);
+ return info;
}
case GL_RG32UI:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R32G32_UINT,
- DXGI_FORMAT_R32G32_UINT,
- DXGI_FORMAT_R32G32_UINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RG32UI,
+ angle::Format::ID::R32G32_UINT,
+ DXGI_FORMAT_R32G32_UINT,
+ DXGI_FORMAT_R32G32_UINT,
+ DXGI_FORMAT_R32G32_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32_UINT,
+ GL_RGBA32I,
+ nullptr);
+ return info;
}
case GL_RG8:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8_UNORM,
- DXGI_FORMAT_R8G8_UNORM,
- DXGI_FORMAT_R8G8_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RG8,
+ angle::Format::ID::R8G8_UNORM,
+ DXGI_FORMAT_R8G8_UNORM,
+ DXGI_FORMAT_R8G8_UNORM,
+ DXGI_FORMAT_R8G8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
}
case GL_RG8I:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8_SINT,
- DXGI_FORMAT_R8G8_SINT,
- DXGI_FORMAT_R8G8_SINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RG8I,
+ angle::Format::ID::R8G8_SINT,
+ DXGI_FORMAT_R8G8_SINT,
+ DXGI_FORMAT_R8G8_SINT,
+ DXGI_FORMAT_R8G8_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8_SINT,
+ GL_RGBA8I,
+ nullptr);
+ return info;
}
case GL_RG8UI:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8_UINT,
- DXGI_FORMAT_R8G8_UINT,
- DXGI_FORMAT_R8G8_UINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RG8UI,
+ angle::Format::ID::R8G8_UINT,
+ DXGI_FORMAT_R8G8_UINT,
+ DXGI_FORMAT_R8G8_UINT,
+ DXGI_FORMAT_R8G8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8_UINT,
+ GL_RGBA8I,
+ nullptr);
+ return info;
}
case GL_RG8_SNORM:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8_SNORM,
- DXGI_FORMAT_R8G8_SNORM,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RG8_SNORM,
+ angle::Format::ID::R8G8_SNORM,
+ DXGI_FORMAT_R8G8_SNORM,
+ DXGI_FORMAT_R8G8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8_SNORM,
+ GL_RGBA8_SNORM,
+ nullptr);
+ return info;
}
case GL_RGB:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGB,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
}
case GL_RGB10_A2:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R10G10B10A2_UNORM,
- DXGI_FORMAT_R10G10B10A2_UNORM,
- DXGI_FORMAT_R10G10B10A2_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGB10_A2,
+ angle::Format::ID::R10G10B10A2_UNORM,
+ DXGI_FORMAT_R10G10B10A2_UNORM,
+ DXGI_FORMAT_R10G10B10A2_UNORM,
+ DXGI_FORMAT_R10G10B10A2_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R10G10B10A2_UNORM,
+ GL_RGBA16_EXT,
+ nullptr);
+ return info;
}
case GL_RGB10_A2UI:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R10G10B10A2_UINT,
- DXGI_FORMAT_R10G10B10A2_UINT,
- DXGI_FORMAT_R10G10B10A2_UINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGB10_A2UI,
+ angle::Format::ID::R10G10B10A2_UINT,
+ DXGI_FORMAT_R10G10B10A2_UINT,
+ DXGI_FORMAT_R10G10B10A2_UINT,
+ DXGI_FORMAT_R10G10B10A2_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R10G10B10A2_UINT,
+ GL_RGBA16I,
+ nullptr);
+ return info;
}
case GL_RGB16F:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R16G16B16A16_FLOAT,
- DXGI_FORMAT_R16G16B16A16_FLOAT,
- DXGI_FORMAT_R16G16B16A16_FLOAT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGB16F,
+ angle::Format::ID::R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ GL_RGBA16F,
+ Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>);
+ return info;
}
case GL_RGB16I:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R16G16B16A16_SINT,
- DXGI_FORMAT_R16G16B16A16_SINT,
- DXGI_FORMAT_R16G16B16A16_SINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGB16I,
+ angle::Format::ID::R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ GL_RGBA16I,
+ Initialize4ComponentData<GLshort, 0x0000, 0x0000, 0x0000, 0x0001>);
+ return info;
}
case GL_RGB16UI:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R16G16B16A16_UINT,
- DXGI_FORMAT_R16G16B16A16_UINT,
- DXGI_FORMAT_R16G16B16A16_UINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGB16UI,
+ angle::Format::ID::R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ GL_RGBA16UI,
+ Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x0001>);
+ return info;
+ }
+ case GL_RGB16_EXT:
+ {
+ static constexpr Format info(GL_RGB16_EXT,
+ angle::Format::ID::R16G16B16A16_UNORM,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ GL_RGBA16_EXT,
+ Initialize4ComponentData<GLubyte, 0x0000, 0x0000, 0x0000, 0xFFFF>);
+ return info;
+ }
+ case GL_RGB16_SNORM_EXT:
+ {
+ static constexpr Format info(GL_RGB16_SNORM_EXT,
+ angle::Format::ID::R16G16B16A16_SNORM,
+ DXGI_FORMAT_R16G16B16A16_SNORM,
+ DXGI_FORMAT_R16G16B16A16_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_SNORM,
+ GL_RGBA16_SNORM_EXT,
+ Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x7FFF>);
+ return info;
}
case GL_RGB32F:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R32G32B32A32_FLOAT,
- DXGI_FORMAT_R32G32B32A32_FLOAT,
- DXGI_FORMAT_R32G32B32A32_FLOAT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGB32F,
+ angle::Format::ID::R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ GL_RGBA32F,
+ Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000, gl::Float32One>);
+ return info;
}
case GL_RGB32I:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R32G32B32A32_SINT,
- DXGI_FORMAT_R32G32B32A32_SINT,
- DXGI_FORMAT_R32G32B32A32_SINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGB32I,
+ angle::Format::ID::R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ GL_RGBA32I,
+ Initialize4ComponentData<GLint, 0x00000000, 0x00000000, 0x00000000, 0x00000001>);
+ return info;
}
case GL_RGB32UI:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R32G32B32A32_UINT,
- DXGI_FORMAT_R32G32B32A32_UINT,
- DXGI_FORMAT_R32G32B32A32_UINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGB32UI,
+ angle::Format::ID::R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ GL_RGBA32UI,
+ Initialize4ComponentData<GLuint, 0x00000000, 0x00000000, 0x00000000, 0x00000001>);
+ return info;
}
case GL_RGB565:
{
- if (SupportsFormat<DXGI_FORMAT_B5G6R5_UNORM,false>(renderer11DeviceCaps))
+ if (SupportsFormat(DXGI_FORMAT_B5G6R5_UNORM, deviceCaps))
{
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else if (SupportsFormat<DXGI_FORMAT_B5G6R5_UNORM,true>(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_B5G6R5_UNORM,
- DXGI_FORMAT_B5G6R5_UNORM,
- DXGI_FORMAT_B5G6R5_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
+ static constexpr Format info(GL_RGB565,
+ angle::Format::ID::B5G6R5_UNORM,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
}
else
{
- break;
+ static constexpr Format info(GL_RGB565,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
}
}
case GL_RGB5_A1:
{
- if (SupportsFormat<DXGI_FORMAT_B5G5R5A1_UNORM,false>(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else if (SupportsFormat<DXGI_FORMAT_B5G5R5A1_UNORM,true>(renderer11DeviceCaps))
+ if (SupportsFormat(DXGI_FORMAT_B5G5R5A1_UNORM, deviceCaps))
{
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_B5G5R5A1_UNORM,
- DXGI_FORMAT_B5G5R5A1_UNORM,
- DXGI_FORMAT_B5G5R5A1_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
+ static constexpr Format info(GL_RGB5_A1,
+ angle::Format::ID::B5G5R5A1_UNORM,
+ DXGI_FORMAT_B5G5R5A1_UNORM,
+ DXGI_FORMAT_B5G5R5A1_UNORM,
+ DXGI_FORMAT_B5G5R5A1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B5G5R5A1_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
}
else
{
- break;
+ static constexpr Format info(GL_RGB5_A1,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
}
}
case GL_RGB8:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGB8,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
}
case GL_RGB8I:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_SINT,
- DXGI_FORMAT_R8G8B8A8_SINT,
- DXGI_FORMAT_R8G8B8A8_SINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGB8I,
+ angle::Format::ID::R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ GL_RGBA8I,
+ Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x01>);
+ return info;
}
case GL_RGB8UI:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_UINT,
- DXGI_FORMAT_R8G8B8A8_UINT,
- DXGI_FORMAT_R8G8B8A8_UINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGB8UI,
+ angle::Format::ID::R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ GL_RGBA8UI,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0x01>);
+ return info;
}
case GL_RGB8_SNORM:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_SNORM,
- DXGI_FORMAT_R8G8B8A8_SNORM,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGB8_SNORM,
+ angle::Format::ID::R8G8B8A8_SNORM,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ GL_RGBA8_SNORM,
+ Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x7F>);
+ return info;
}
case GL_RGB9_E5:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
- DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGB9_E5,
+ angle::Format::ID::R9G9B9E5_SHAREDEXP,
+ DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
+ DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
+ GL_RGBA16F_EXT,
+ nullptr);
+ return info;
}
case GL_RGBA:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGBA,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
}
case GL_RGBA16F:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R16G16B16A16_FLOAT,
- DXGI_FORMAT_R16G16B16A16_FLOAT,
- DXGI_FORMAT_R16G16B16A16_FLOAT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGBA16F,
+ angle::Format::ID::R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ GL_RGBA16F,
+ nullptr);
+ return info;
}
case GL_RGBA16I:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R16G16B16A16_SINT,
- DXGI_FORMAT_R16G16B16A16_SINT,
- DXGI_FORMAT_R16G16B16A16_SINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGBA16I,
+ angle::Format::ID::R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ GL_RGBA16I,
+ nullptr);
+ return info;
}
case GL_RGBA16UI:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R16G16B16A16_UINT,
- DXGI_FORMAT_R16G16B16A16_UINT,
- DXGI_FORMAT_R16G16B16A16_UINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGBA16UI,
+ angle::Format::ID::R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ GL_RGBA16UI,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA16_EXT:
+ {
+ static constexpr Format info(GL_RGBA16_EXT,
+ angle::Format::ID::R16G16B16A16_UNORM,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ GL_RGBA16_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA16_SNORM_EXT:
+ {
+ static constexpr Format info(GL_RGBA16_SNORM_EXT,
+ angle::Format::ID::R16G16B16A16_SNORM,
+ DXGI_FORMAT_R16G16B16A16_SNORM,
+ DXGI_FORMAT_R16G16B16A16_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_SNORM,
+ GL_RGBA16_SNORM_EXT,
+ nullptr);
+ return info;
}
case GL_RGBA32F:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R32G32B32A32_FLOAT,
- DXGI_FORMAT_R32G32B32A32_FLOAT,
- DXGI_FORMAT_R32G32B32A32_FLOAT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGBA32F,
+ angle::Format::ID::R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ GL_RGBA32F,
+ nullptr);
+ return info;
}
case GL_RGBA32I:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R32G32B32A32_SINT,
- DXGI_FORMAT_R32G32B32A32_SINT,
- DXGI_FORMAT_R32G32B32A32_SINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGBA32I,
+ angle::Format::ID::R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ GL_RGBA32I,
+ nullptr);
+ return info;
}
case GL_RGBA32UI:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R32G32B32A32_UINT,
- DXGI_FORMAT_R32G32B32A32_UINT,
- DXGI_FORMAT_R32G32B32A32_UINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGBA32UI,
+ angle::Format::ID::R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ GL_RGBA32UI,
+ nullptr);
+ return info;
}
case GL_RGBA4:
{
- if (SupportsFormat<DXGI_FORMAT_B4G4R4A4_UNORM,false>(renderer11DeviceCaps))
+ if (SupportsFormat(DXGI_FORMAT_B4G4R4A4_UNORM, deviceCaps))
{
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else if (SupportsFormat<DXGI_FORMAT_B4G4R4A4_UNORM,true>(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_B4G4R4A4_UNORM,
- DXGI_FORMAT_B4G4R4A4_UNORM,
- DXGI_FORMAT_B4G4R4A4_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
+ static constexpr Format info(GL_RGBA4,
+ angle::Format::ID::B4G4R4A4_UNORM,
+ DXGI_FORMAT_B4G4R4A4_UNORM,
+ DXGI_FORMAT_B4G4R4A4_UNORM,
+ DXGI_FORMAT_B4G4R4A4_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B4G4R4A4_UNORM,
+ GL_RGBA4,
+ nullptr);
+ return info;
}
else
{
- break;
+ static constexpr Format info(GL_RGBA4,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
}
}
case GL_RGBA8:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_R8G8B8A8_UNORM,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGBA8,
+ angle::Format::ID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ GL_RGBA8,
+ nullptr);
+ return info;
}
case GL_RGBA8I:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_SINT,
- DXGI_FORMAT_R8G8B8A8_SINT,
- DXGI_FORMAT_R8G8B8A8_SINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGBA8I,
+ angle::Format::ID::R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ GL_RGBA8I,
+ nullptr);
+ return info;
}
case GL_RGBA8UI:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_UINT,
- DXGI_FORMAT_R8G8B8A8_UINT,
- DXGI_FORMAT_R8G8B8A8_UINT,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGBA8UI,
+ angle::Format::ID::R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ GL_RGBA8UI,
+ nullptr);
+ return info;
}
case GL_RGBA8_SNORM:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_SNORM,
- DXGI_FORMAT_R8G8B8A8_SNORM,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_RGBA8_SNORM,
+ angle::Format::ID::R8G8B8A8_SNORM,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ GL_RGBA8_SNORM,
+ nullptr);
+ return info;
}
case GL_SRGB8:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
- DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_SRGB8,
+ angle::Format::ID::R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ GL_SRGB8_ALPHA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
}
case GL_SRGB8_ALPHA8:
{
- if (AnyDevice(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
- DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
- DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
- DXGI_FORMAT_UNKNOWN);
- return textureFormat;
- }
- else
- {
- break;
- }
+ static constexpr Format info(GL_SRGB8_ALPHA8,
+ angle::Format::ID::R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ GL_SRGB8_ALPHA8,
+ nullptr);
+ return info;
}
case GL_STENCIL_INDEX8:
{
- if (OnlyFL9_3(renderer11DeviceCaps))
+ if (OnlyFL10Plus(deviceCaps))
{
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_D24_UNORM_S8_UINT,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_D24_UNORM_S8_UINT);
- return textureFormat;
- }
- else if (OnlyFL10Plus(renderer11DeviceCaps))
- {
- static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat,
- DXGI_FORMAT_R24G8_TYPELESS,
- DXGI_FORMAT_X24_TYPELESS_G8_UINT,
- DXGI_FORMAT_UNKNOWN,
- DXGI_FORMAT_D24_UNORM_S8_UINT);
- return textureFormat;
+ static constexpr Format info(GL_STENCIL_INDEX8,
+ angle::Format::ID::D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24G8_TYPELESS,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ GL_RGBA32F,
+ nullptr);
+ return info;
}
else
{
- break;
+ static constexpr Format info(GL_STENCIL_INDEX8,
+ angle::Format::ID::D24_UNORM_S8_UINT,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA32F,
+ nullptr);
+ return info;
}
}
@@ -1782,9 +1928,10 @@ const TextureFormat &GetTextureFormatInfo(GLenum internalFormat,
}
// clang-format on
- static const TextureFormat defaultInfo;
+ UNREACHABLE();
+ static constexpr Format defaultInfo;
return defaultInfo;
-} // GetTextureFormatInfo
+}
} // namespace d3d11
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h
new file mode 100644
index 0000000000..d5351ff882
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h
@@ -0,0 +1,85 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Helper routines for the D3D11 texture format table.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_TEXTURE_FORMAT_TABLE_UTILS_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_TEXTURE_FORMAT_TABLE_UTILS_H_
+
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+using FormatSupportFunction = bool (*)(const Renderer11DeviceCaps &);
+
+inline bool OnlyFL10Plus(const Renderer11DeviceCaps &deviceCaps)
+{
+ return (deviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0);
+}
+
+inline bool OnlyFL9_3(const Renderer11DeviceCaps &deviceCaps)
+{
+ return (deviceCaps.featureLevel == D3D_FEATURE_LEVEL_9_3);
+}
+
+inline bool SupportsFormat(DXGI_FORMAT format, const Renderer11DeviceCaps &deviceCaps)
+{
+ // Must support texture, SRV and RTV support
+ UINT mustSupport = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE |
+ D3D11_FORMAT_SUPPORT_SHADER_SAMPLE | D3D11_FORMAT_SUPPORT_MIP |
+ D3D11_FORMAT_SUPPORT_RENDER_TARGET;
+ UINT minimumRequiredSamples = 0;
+
+ if (d3d11_gl::GetMaximumClientVersion(deviceCaps.featureLevel).major > 2)
+ {
+ mustSupport |= D3D11_FORMAT_SUPPORT_TEXTURE3D;
+
+ // RGBA4, RGB5A1 and RGB565 are all required multisampled renderbuffer formats in ES3 and
+ // need to support a minimum of 4 samples.
+ minimumRequiredSamples = 4;
+ }
+
+ bool fullSupport = false;
+ if (format == DXGI_FORMAT_B5G6R5_UNORM)
+ {
+ // All hardware that supports DXGI_FORMAT_B5G6R5_UNORM should support autogen mipmaps, but
+ // check anyway.
+ mustSupport |= D3D11_FORMAT_SUPPORT_MIP_AUTOGEN;
+ fullSupport = ((deviceCaps.B5G6R5support & mustSupport) == mustSupport) &&
+ deviceCaps.B5G6R5maxSamples >= minimumRequiredSamples;
+ }
+ else if (format == DXGI_FORMAT_B4G4R4A4_UNORM)
+ {
+ fullSupport = ((deviceCaps.B4G4R4A4support & mustSupport) == mustSupport) &&
+ deviceCaps.B4G4R4A4maxSamples >= minimumRequiredSamples;
+ }
+ else if (format == DXGI_FORMAT_B5G5R5A1_UNORM)
+ {
+ fullSupport = ((deviceCaps.B5G5R5A1support & mustSupport) == mustSupport) &&
+ deviceCaps.B5G5R5A1maxSamples >= minimumRequiredSamples;
+ }
+ else
+ {
+ UNREACHABLE();
+ return false;
+ }
+
+ // This means that ANGLE would like to use the entry in the map if the inputted DXGI format
+ // *IS* supported.
+ // e.g. the entry might map GL_RGB5_A1 to DXGI_FORMAT_B5G5R5A1, which should only be used if
+ // DXGI_FORMAT_B5G5R5A1 is supported.
+ // In this case, we should only return 'true' if the format *IS* supported.
+ return fullSupport;
+}
+
+} // namespace d3d11
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_TEXTURE_FORMAT_TABLE_UTILS_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
deleted file mode 100644
index da6460b136..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
+++ /dev/null
@@ -1,220 +0,0 @@
-//
-// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// NativeWindow.cpp: Handler for managing HWND native window types.
-
-#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h"
-#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
-
-#include "common/debug.h"
-
-#include <initguid.h>
-#if !defined(__MINGW32__)
-#include <dcomp.h>
-#endif
-
-namespace rx
-{
-
-NativeWindow::NativeWindow(EGLNativeWindowType window,
- const egl::Config *config,
- bool directComposition)
- : mWindow(window),
- mDirectComposition(directComposition),
- mDevice(nullptr),
- mCompositionTarget(nullptr),
- mVisual(nullptr),
- mConfig(config)
-{
-}
-
-NativeWindow::~NativeWindow()
-{
-#if !defined(__MINGW32__)
- SafeRelease(mCompositionTarget);
- SafeRelease(mDevice);
- SafeRelease(mVisual);
-#endif
-}
-
-bool NativeWindow::initialize()
-{
- return true;
-}
-
-bool NativeWindow::getClientRect(LPRECT rect)
-{
- return GetClientRect(mWindow, rect) == TRUE;
-}
-
-bool NativeWindow::isIconic()
-{
- return IsIconic(mWindow) == TRUE;
-}
-
-bool NativeWindow::isValidNativeWindow(EGLNativeWindowType window)
-{
- return IsWindow(window) == TRUE;
-}
-
-#if defined(ANGLE_ENABLE_D3D11)
-HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory,
- DXGI_FORMAT format, unsigned int width, unsigned int height,
- DXGISwapChain** swapChain)
-{
- if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0)
- {
- return E_INVALIDARG;
- }
-
-#if !defined(__MINGW32__)
- if (mDirectComposition)
- {
- HMODULE dcomp = ::GetModuleHandle(TEXT("dcomp.dll"));
- if (!dcomp)
- {
- return E_INVALIDARG;
- }
-
- typedef HRESULT(WINAPI * PFN_DCOMPOSITION_CREATE_DEVICE)(
- IDXGIDevice * dxgiDevice, REFIID iid, void **dcompositionDevice);
- PFN_DCOMPOSITION_CREATE_DEVICE createDComp =
- reinterpret_cast<PFN_DCOMPOSITION_CREATE_DEVICE>(
- GetProcAddress(dcomp, "DCompositionCreateDevice"));
- if (!createDComp)
- {
- return E_INVALIDARG;
- }
-
- if (!mDevice)
- {
- IDXGIDevice *dxgiDevice = d3d11::DynamicCastComObject<IDXGIDevice>(device);
- HRESULT result = createDComp(dxgiDevice, __uuidof(IDCompositionDevice),
- reinterpret_cast<void **>(&mDevice));
- SafeRelease(dxgiDevice);
-
- if (FAILED(result))
- {
- return result;
- }
- }
-
- if (!mCompositionTarget)
- {
- HRESULT result = mDevice->CreateTargetForHwnd(mWindow, TRUE, &mCompositionTarget);
- if (FAILED(result))
- {
- return result;
- }
- }
-
- if (!mVisual)
- {
- HRESULT result = mDevice->CreateVisual(&mVisual);
- if (FAILED(result))
- {
- return result;
- }
- }
-
- IDXGIFactory2 *factory2 = d3d11::DynamicCastComObject<IDXGIFactory2>(factory);
- DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
- swapChainDesc.Width = width;
- swapChainDesc.Height = height;
- swapChainDesc.Format = format;
- swapChainDesc.Stereo = FALSE;
- swapChainDesc.SampleDesc.Count = 1;
- swapChainDesc.SampleDesc.Quality = 0;
- swapChainDesc.BufferUsage =
- DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_SHADER_INPUT;
- swapChainDesc.BufferCount = 2;
- swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
- swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
- swapChainDesc.AlphaMode =
- mConfig->alphaSize == 0 ? DXGI_ALPHA_MODE_IGNORE : DXGI_ALPHA_MODE_PREMULTIPLIED;
- swapChainDesc.Flags = 0;
- IDXGISwapChain1 *swapChain1 = nullptr;
- HRESULT result =
- factory2->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, &swapChain1);
- if (SUCCEEDED(result))
- {
- *swapChain = static_cast<DXGISwapChain *>(swapChain1);
- }
- mVisual->SetContent(swapChain1);
- mCompositionTarget->SetRoot(mVisual);
- SafeRelease(factory2);
- return result;
- }
-
- // Use IDXGIFactory2::CreateSwapChainForHwnd if DXGI 1.2 is available to create a DXGI_SWAP_EFFECT_SEQUENTIAL swap chain.
- IDXGIFactory2 *factory2 = d3d11::DynamicCastComObject<IDXGIFactory2>(factory);
- if (factory2 != nullptr)
- {
- DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 };
- swapChainDesc.Width = width;
- swapChainDesc.Height = height;
- swapChainDesc.Format = format;
- swapChainDesc.Stereo = FALSE;
- swapChainDesc.SampleDesc.Count = 1;
- swapChainDesc.SampleDesc.Quality = 0;
- swapChainDesc.BufferUsage =
- DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER;
- swapChainDesc.BufferCount = 1;
- swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
- swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL;
- swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
- swapChainDesc.Flags = 0;
- IDXGISwapChain1 *swapChain1 = nullptr;
- HRESULT result = factory2->CreateSwapChainForHwnd(device, mWindow, &swapChainDesc, nullptr, nullptr, &swapChain1);
- if (SUCCEEDED(result))
- {
- const HRESULT makeWindowAssociationResult = factory->MakeWindowAssociation(mWindow, DXGI_MWA_NO_ALT_ENTER);
- UNUSED_VARIABLE(makeWindowAssociationResult);
- *swapChain = static_cast<DXGISwapChain*>(swapChain1);
- }
- SafeRelease(factory2);
- return result;
- }
-#endif // !__MINGW32__
-
- DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
- swapChainDesc.BufferCount = 1;
- swapChainDesc.BufferDesc.Format = format;
- swapChainDesc.BufferDesc.Width = width;
- swapChainDesc.BufferDesc.Height = height;
- swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
- swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
- swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
- swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
- swapChainDesc.BufferUsage =
- DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER;
- swapChainDesc.Flags = 0;
- swapChainDesc.OutputWindow = mWindow;
- swapChainDesc.SampleDesc.Count = 1;
- swapChainDesc.SampleDesc.Quality = 0;
- swapChainDesc.Windowed = TRUE;
- swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
-
- const HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, swapChain);
- if (SUCCEEDED(result))
- {
- const HRESULT makeWindowAssociationResult = factory->MakeWindowAssociation(mWindow, DXGI_MWA_NO_ALT_ENTER);
- UNUSED_VARIABLE(makeWindowAssociationResult);
- }
- return result;
-}
-#endif
-
-void NativeWindow::commitChange()
-{
-#if !defined(__MINGW32__)
- if (mDevice)
- {
- mDevice->Commit();
- }
-#endif
-}
-}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp
new file mode 100644
index 0000000000..5394e3d3e7
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp
@@ -0,0 +1,217 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// NativeWindow11Win32.cpp: Implementation of NativeWindow11 using win32 window APIs.
+
+#include "libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+#include "common/debug.h"
+
+#include <initguid.h>
+#include <dcomp.h>
+
+namespace rx
+{
+
+NativeWindow11Win32::NativeWindow11Win32(EGLNativeWindowType window,
+ bool hasAlpha,
+ bool directComposition)
+ : NativeWindow11(window),
+ mDirectComposition(directComposition),
+ mHasAlpha(hasAlpha),
+ mDevice(nullptr),
+ mCompositionTarget(nullptr),
+ mVisual(nullptr)
+{
+}
+
+NativeWindow11Win32::~NativeWindow11Win32()
+{
+ SafeRelease(mCompositionTarget);
+ SafeRelease(mDevice);
+ SafeRelease(mVisual);
+}
+
+bool NativeWindow11Win32::initialize()
+{
+ return true;
+}
+
+bool NativeWindow11Win32::getClientRect(LPRECT rect) const
+{
+ return GetClientRect(getNativeWindow(), rect) == TRUE;
+}
+
+bool NativeWindow11Win32::isIconic() const
+{
+ return IsIconic(getNativeWindow()) == TRUE;
+}
+
+HRESULT NativeWindow11Win32::createSwapChain(ID3D11Device *device,
+ IDXGIFactory *factory,
+ DXGI_FORMAT format,
+ UINT width,
+ UINT height,
+ UINT samples,
+ IDXGISwapChain **swapChain)
+{
+ if (device == nullptr || factory == nullptr || swapChain == nullptr || width == 0 ||
+ height == 0)
+ {
+ return E_INVALIDARG;
+ }
+
+ if (mDirectComposition)
+ {
+ HMODULE dcomp = ::GetModuleHandle(TEXT("dcomp.dll"));
+ if (!dcomp)
+ {
+ return E_INVALIDARG;
+ }
+
+ typedef HRESULT(WINAPI * PFN_DCOMPOSITION_CREATE_DEVICE)(
+ IDXGIDevice * dxgiDevice, REFIID iid, void **dcompositionDevice);
+ PFN_DCOMPOSITION_CREATE_DEVICE createDComp =
+ reinterpret_cast<PFN_DCOMPOSITION_CREATE_DEVICE>(
+ GetProcAddress(dcomp, "DCompositionCreateDevice"));
+ if (!createDComp)
+ {
+ return E_INVALIDARG;
+ }
+
+ if (!mDevice)
+ {
+ IDXGIDevice *dxgiDevice = d3d11::DynamicCastComObject<IDXGIDevice>(device);
+ HRESULT result = createDComp(dxgiDevice, __uuidof(IDCompositionDevice),
+ reinterpret_cast<void **>(&mDevice));
+ SafeRelease(dxgiDevice);
+
+ if (FAILED(result))
+ {
+ return result;
+ }
+ }
+
+ if (!mCompositionTarget)
+ {
+ HRESULT result =
+ mDevice->CreateTargetForHwnd(getNativeWindow(), TRUE, &mCompositionTarget);
+ if (FAILED(result))
+ {
+ return result;
+ }
+ }
+
+ if (!mVisual)
+ {
+ HRESULT result = mDevice->CreateVisual(&mVisual);
+ if (FAILED(result))
+ {
+ return result;
+ }
+ }
+
+ IDXGIFactory2 *factory2 = d3d11::DynamicCastComObject<IDXGIFactory2>(factory);
+ DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
+ swapChainDesc.Width = width;
+ swapChainDesc.Height = height;
+ swapChainDesc.Format = format;
+ swapChainDesc.Stereo = FALSE;
+ swapChainDesc.SampleDesc.Count = 1;
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.BufferUsage =
+ DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_SHADER_INPUT;
+ swapChainDesc.BufferCount = 2;
+ swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+ swapChainDesc.AlphaMode =
+ mHasAlpha ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE;
+ swapChainDesc.Flags = 0;
+ IDXGISwapChain1 *swapChain1 = nullptr;
+ HRESULT result =
+ factory2->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, &swapChain1);
+ if (SUCCEEDED(result))
+ {
+ *swapChain = static_cast<IDXGISwapChain *>(swapChain1);
+ }
+ mVisual->SetContent(swapChain1);
+ mCompositionTarget->SetRoot(mVisual);
+ SafeRelease(factory2);
+ return result;
+ }
+
+ // Use IDXGIFactory2::CreateSwapChainForHwnd if DXGI 1.2 is available to create a
+ // DXGI_SWAP_EFFECT_SEQUENTIAL swap chain.
+ IDXGIFactory2 *factory2 = d3d11::DynamicCastComObject<IDXGIFactory2>(factory);
+ if (factory2 != nullptr)
+ {
+ DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
+ swapChainDesc.Width = width;
+ swapChainDesc.Height = height;
+ swapChainDesc.Format = format;
+ swapChainDesc.Stereo = FALSE;
+ swapChainDesc.SampleDesc.Count = samples;
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.BufferUsage =
+ DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER;
+ swapChainDesc.BufferCount = 1;
+ swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL;
+ swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
+ swapChainDesc.Flags = 0;
+ IDXGISwapChain1 *swapChain1 = nullptr;
+ HRESULT result = factory2->CreateSwapChainForHwnd(device, getNativeWindow(), &swapChainDesc,
+ nullptr, nullptr, &swapChain1);
+ if (SUCCEEDED(result))
+ {
+ factory2->MakeWindowAssociation(getNativeWindow(), DXGI_MWA_NO_ALT_ENTER);
+ *swapChain = static_cast<IDXGISwapChain *>(swapChain1);
+ }
+ SafeRelease(factory2);
+ return result;
+ }
+
+ DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
+ swapChainDesc.BufferCount = 1;
+ swapChainDesc.BufferDesc.Format = format;
+ swapChainDesc.BufferDesc.Width = width;
+ swapChainDesc.BufferDesc.Height = height;
+ swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
+ swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
+ swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
+ swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
+ swapChainDesc.BufferUsage =
+ DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER;
+ swapChainDesc.Flags = 0;
+ swapChainDesc.OutputWindow = getNativeWindow();
+ swapChainDesc.SampleDesc.Count = samples;
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.Windowed = TRUE;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+
+ HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, swapChain);
+ if (SUCCEEDED(result))
+ {
+ factory->MakeWindowAssociation(getNativeWindow(), DXGI_MWA_NO_ALT_ENTER);
+ }
+ return result;
+}
+
+void NativeWindow11Win32::commitChange()
+{
+ if (mDevice)
+ {
+ mDevice->Commit();
+ }
+}
+
+// static
+bool NativeWindow11Win32::IsValidNativeWindow(EGLNativeWindowType window)
+{
+ return IsWindow(window) == TRUE;
+}
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h
new file mode 100644
index 0000000000..baeba6a347
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h
@@ -0,0 +1,53 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// NativeWindow11Win32.h: Implementation of NativeWindow11 using win32 window APIs.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_WIN32_NATIVEWINDOW11WIN32_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_WIN32_NATIVEWINDOW11WIN32_H_
+
+#include "libANGLE/renderer/d3d/d3d11/NativeWindow11.h"
+
+typedef interface IDCompositionDevice IDCompositionDevice;
+typedef interface IDCompositionTarget IDCompositionTarget;
+typedef interface IDCompositionVisual IDCompositionVisual;
+
+namespace rx
+{
+
+class NativeWindow11Win32 : public NativeWindow11
+{
+ public:
+ NativeWindow11Win32(EGLNativeWindowType window, bool hasAlpha, bool directComposition);
+ ~NativeWindow11Win32() override;
+
+ bool initialize() override;
+ bool getClientRect(LPRECT rect) const override;
+ bool isIconic() const override;
+
+ HRESULT createSwapChain(ID3D11Device *device,
+ IDXGIFactory *factory,
+ DXGI_FORMAT format,
+ UINT width,
+ UINT height,
+ UINT samples,
+ IDXGISwapChain **swapChain) override;
+
+ void commitChange() override;
+
+ static bool IsValidNativeWindow(EGLNativeWindowType window);
+
+ private:
+ bool mDirectComposition;
+ bool mHasAlpha;
+ IDCompositionDevice *mDevice;
+ IDCompositionTarget *mCompositionTarget;
+ IDCompositionVisual *mVisual;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_WIN32_NATIVEWINDOW11WIN32_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
index f401db614b..1ef90e7b09 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
@@ -8,6 +8,8 @@
#include "libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h"
+#include <windows.graphics.display.h>
+
using namespace ABI::Windows::Foundation::Collections;
namespace rx
@@ -19,7 +21,6 @@ CoreWindowNativeWindow::~CoreWindowNativeWindow()
bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet)
{
- mOrientationChangedEventToken.value = 0;
ComPtr<IPropertySet> props = propertySet;
ComPtr<IInspectable> win = window;
SIZE swapChainSize = {};
@@ -63,7 +64,8 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet
// A EGLRenderSurfaceSizeProperty and a EGLRenderResolutionScaleProperty can't both be specified
if (mSwapChainScaleSpecified && mSwapChainSizeSpecified)
{
- ERR("It is invalid to specify both an EGLRenderSurfaceSizeProperty and a EGLRenderResolutionScaleProperty.");
+ ERR() << "It is invalid to specify both an EGLRenderSurfaceSizeProperty and a "
+ "EGLRenderResolutionScaleProperty.";
return false;
}
}
@@ -87,28 +89,18 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet
}
else
{
- SIZE coreWindowSize;
+ Size coreWindowSize;
result = GetCoreWindowSizeInPixels(mCoreWindow, &coreWindowSize);
if (SUCCEEDED(result))
{
- mClientRect = { 0, 0, static_cast<long>(coreWindowSize.cx * mSwapChainScale), static_cast<long>(coreWindowSize.cy * mSwapChainScale) };
+ mClientRect = clientRect(coreWindowSize);
}
}
}
if (SUCCEEDED(result))
{
- ComPtr<ABI::Windows::Graphics::Display::IDisplayInformationStatics> displayInformation;
- result = GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayInformation).Get(), &displayInformation);
- if (SUCCEEDED(result))
- {
- result = displayInformation->GetForCurrentView(&mDisplayInformation);
- }
- }
-
- if (SUCCEEDED(result))
- {
mNewClientRect = mClientRect;
mClientRectChanged = false;
return registerForSizeChangeEvents();
@@ -126,16 +118,6 @@ bool CoreWindowNativeWindow::registerForSizeChangeEvents()
result = mCoreWindow->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken);
}
-#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
- ComPtr<IDisplayOrientationEventHandler> orientationChangedHandler;
- result = sizeChangedHandler.As(&orientationChangedHandler);
- if (SUCCEEDED(result))
- {
- result = mDisplayInformation->add_OrientationChanged(orientationChangedHandler.Get(), &mOrientationChangedEventToken);
- orientationChangedHandler->Invoke(mDisplayInformation.Get(), nullptr);
- }
-#endif
-
if (SUCCEEDED(result))
{
return true;
@@ -150,34 +132,26 @@ void CoreWindowNativeWindow::unregisterForSizeChangeEvents()
{
(void)mCoreWindow->remove_SizeChanged(mSizeChangedEventToken);
}
-
-#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
- if (mDisplayInformation)
- {
- (void)mDisplayInformation->remove_OrientationChanged(mOrientationChangedEventToken);
- }
-#endif
-
mSizeChangedEventToken.value = 0;
- mOrientationChangedEventToken.value = 0;
}
HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device,
- DXGIFactory *factory,
+ IDXGIFactory2 *factory,
DXGI_FORMAT format,
unsigned int width,
unsigned int height,
bool containsAlpha,
- DXGISwapChain **swapChain)
+ IDXGISwapChain1 **swapChain)
{
- if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0)
+ if (device == nullptr || factory == nullptr || swapChain == nullptr || width == 0 ||
+ height == 0)
{
return E_INVALIDARG;
}
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 };
- swapChainDesc.Width = mRotationFlags ? height : width;
- swapChainDesc.Height = mRotationFlags ? width : height;
+ swapChainDesc.Width = width;
+ swapChainDesc.Height = height;
swapChainDesc.Format = format;
swapChainDesc.Stereo = FALSE;
swapChainDesc.SampleDesc.Count = 1;
@@ -195,17 +169,6 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device,
HRESULT result = factory->CreateSwapChainForCoreWindow(device, mCoreWindow.Get(), &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf());
if (SUCCEEDED(result))
{
-
-#if 0 //(WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) // Qt: allow Windows Phone to resize, but don't modify the backing texture in the swap chain.
- // Test if swapchain supports resize. On Windows Phone devices, this will return DXGI_ERROR_UNSUPPORTED. On
- // other devices DXGI_ERROR_INVALID_CALL should be returned because the combination of flags passed
- // (DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) are invalid flag combinations.
- if (newSwapChain->ResizeBuffers(swapChainDesc.BufferCount, swapChainDesc.Width, swapChainDesc.Height, swapChainDesc.Format, DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) == DXGI_ERROR_UNSUPPORTED)
- {
- mSupportsSwapChainResize = false;
- }
-#endif // (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
-
result = newSwapChain.CopyTo(swapChain);
}
@@ -222,14 +185,16 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device,
return result;
}
-inline HRESULT CoreWindowNativeWindow::scaleSwapChain(const Size &windowSize, const RECT &clientRect)
+inline HRESULT CoreWindowNativeWindow::scaleSwapChain(const Size &windowSize,
+ const RECT &clientRect)
{
// We don't need to do any additional work to scale CoreWindow swapchains.
// Using DXGI_SCALING_STRETCH to create the swapchain above does all the necessary work.
return S_OK;
}
-HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWindow>& coreWindow, SIZE *windowSize)
+HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWindow> &coreWindow,
+ Size *windowSize)
{
ABI::Windows::Foundation::Rect bounds;
HRESULT result = coreWindow->get_Bounds(&bounds);
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h
index fc1cd124a1..21855c2c3b 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h
@@ -12,10 +12,10 @@
#include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h"
#include <memory>
-#include <windows.graphics.display.h>
+
+#include <EGL/eglplatform.h>
typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowSizeChangedEventArgs_t IWindowSizeChangedEventHandler;
-typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CGraphics__CDisplay__CDisplayInformation_IInspectable_t IDisplayOrientationEventHandler;
namespace rx
{
@@ -26,12 +26,12 @@ class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enabl
bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) override;
HRESULT createSwapChain(ID3D11Device *device,
- DXGIFactory *factory,
+ IDXGIFactory2 *factory,
DXGI_FORMAT format,
unsigned int width,
unsigned int height,
bool containsAlpha,
- DXGISwapChain **swapChain) override;
+ IDXGISwapChain1 **swapChain) override;
protected:
HRESULT scaleSwapChain(const Size &windowSize, const RECT &clientRect) override;
@@ -42,13 +42,11 @@ class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enabl
private:
ComPtr<ABI::Windows::UI::Core::ICoreWindow> mCoreWindow;
ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap;
- ComPtr<ABI::Windows::Graphics::Display::IDisplayInformation> mDisplayInformation;
- EventRegistrationToken mOrientationChangedEventToken;
};
[uuid(7F924F66-EBAE-40E5-A10B-B8F35E245190)]
class CoreWindowSizeChangedHandler :
- public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, IWindowSizeChangedEventHandler, IDisplayOrientationEventHandler>
+ public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, IWindowSizeChangedEventHandler>
{
public:
CoreWindowSizeChangedHandler() { }
@@ -72,47 +70,21 @@ class CoreWindowSizeChangedHandler :
ABI::Windows::Foundation::Size windowSize;
if (SUCCEEDED(sizeChangedEventArgs->get_Size(&windowSize)))
{
- host->setNewClientSize(windowSize);
+ Size windowSizeInPixels = {ConvertDipsToPixels(windowSize.Width),
+ ConvertDipsToPixels(windowSize.Height)};
+ host->setNewClientSize(windowSizeInPixels);
}
}
return S_OK;
}
- IFACEMETHOD(Invoke)(ABI::Windows::Graphics::Display::IDisplayInformation *displayInformation, IInspectable *)
- {
- #if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
- NativeWindow::RotationFlags flags = NativeWindow::RotateNone;
- ABI::Windows::Graphics::Display::DisplayOrientations orientation;
- if (SUCCEEDED(displayInformation->get_CurrentOrientation(&orientation)))
- {
- switch (orientation)
- {
- case ABI::Windows::Graphics::Display::DisplayOrientations_Landscape:
- flags = NativeWindow::RotateLeft;
- break;
- case ABI::Windows::Graphics::Display::DisplayOrientations_LandscapeFlipped:
- flags = NativeWindow::RotateRight;
- break;
- default:
- break;
- }
- }
- std::shared_ptr<InspectableNativeWindow> host = mHost.lock();
- if (host)
- {
- host->setRotationFlags(flags);
- }
- #endif
- return S_OK;
- }
-
-
private:
std::weak_ptr<InspectableNativeWindow> mHost;
};
-HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWindow>& coreWindow, SIZE *windowSize);
+HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWindow> &coreWindow,
+ Size *windowSize);
}
#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_COREWINDOWNATIVEWINDOW_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
index aacfadd2f0..1bd796e58f 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
@@ -11,108 +11,6 @@
namespace rx
{
-NativeWindow::NativeWindow(EGLNativeWindowType window,
- const egl::Config *config,
- bool directComposition)
-{
- mWindow = window;
- mConfig = config;
-}
-
-NativeWindow::~NativeWindow()
-{
-}
-
-void NativeWindow::commitChange()
-{
-}
-
-bool NativeWindow::initialize()
-{
- // If the native window type is a IPropertySet, extract the
- // EGLNativeWindowType (IInspectable) and initialize the
- // proper host with this IPropertySet.
- ComPtr<ABI::Windows::Foundation::Collections::IPropertySet> propertySet;
- ComPtr<IInspectable> eglNativeWindow;
- if (IsEGLConfiguredPropertySet(mWindow, &propertySet, &eglNativeWindow))
- {
- // A property set was found and the EGLNativeWindowType was
- // retrieved. The mWindow member of the host to must be updated
- // to use the EGLNativeWindowType specified in the property set.
- // mWindow is treated as a raw pointer not an AddRef'd interface, so
- // the old mWindow does not need a Release() before this assignment.
- mWindow = eglNativeWindow.Get();
- }
-
- ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWindow;
- ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> swapChainPanel;
- if (IsCoreWindow(mWindow, &coreWindow))
- {
- mImpl = std::make_shared<CoreWindowNativeWindow>();
- if (mImpl)
- {
- return mImpl->initialize(mWindow, propertySet.Get());
- }
- }
- else if (IsSwapChainPanel(mWindow, &swapChainPanel))
- {
- mImpl = std::make_shared<SwapChainPanelNativeWindow>();
- if (mImpl)
- {
- return mImpl->initialize(mWindow, propertySet.Get());
- }
- }
- else
- {
- ERR("Invalid IInspectable EGLNativeWindowType detected. Valid IInspectables include ICoreWindow, ISwapChainPanel and IPropertySet");
- }
-
- return false;
-}
-
-bool NativeWindow::getClientRect(RECT *rect)
-{
- if (mImpl)
- {
- return mImpl->getClientRect(rect);
- }
-
- return false;
-}
-
-#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
-NativeWindow::RotationFlags NativeWindow::rotationFlags() const
-{
- if (mImpl)
- {
- return mImpl->rotationFlags();
- }
-
- return NativeWindow::RotateNone;
-}
-#endif
-
-bool NativeWindow::isIconic()
-{
- return false;
-}
-
-bool NativeWindow::isValidNativeWindow(EGLNativeWindowType window)
-{
- return IsValidEGLNativeWindowType(window);
-}
-
-HRESULT NativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain)
-{
- if (mImpl)
- {
- bool containsAlpha = (mConfig->alphaSize > 0);
- return mImpl->createSwapChain(device, factory, format, width, height, containsAlpha,
- swapChain);
- }
-
- return E_UNEXPECTED;
-}
bool IsCoreWindow(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Core::ICoreWindow> *coreWindow)
{
@@ -127,7 +25,7 @@ bool IsCoreWindow(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Core::ICo
{
if (coreWindow != nullptr)
{
- *coreWindow = coreWin.Detach();
+ *coreWindow = coreWin;
}
return true;
}
@@ -148,7 +46,7 @@ bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Xaml:
{
if (swapChainPanel != nullptr)
{
- *swapChainPanel = panel.Detach();
+ *swapChainPanel = panel;
}
return true;
}
@@ -185,7 +83,8 @@ bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Founda
// considered invalid.
if (SUCCEEDED(result) && !hasEglNativeWindowPropertyKey)
{
- ERR("Could not find EGLNativeWindowTypeProperty in IPropertySet. Valid EGLNativeWindowTypeProperty values include ICoreWindow");
+ ERR() << "Could not find EGLNativeWindowTypeProperty in IPropertySet. Valid "
+ "EGLNativeWindowTypeProperty values include ICoreWindow";
return false;
}
@@ -219,18 +118,6 @@ bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Founda
return false;
}
-// A Valid EGLNativeWindowType IInspectable can only be:
-//
-// ICoreWindow
-// ISwapChainPanel
-// IPropertySet
-//
-// Anything else will be rejected as an invalid IInspectable.
-bool IsValidEGLNativeWindowType(EGLNativeWindowType window)
-{
- return IsCoreWindow(window) || IsSwapChainPanel(window) || IsEGLConfiguredPropertySet(window);
-}
-
// Retrieve an optional property from a property set
HRESULT GetOptionalPropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> &propertyMap,
const wchar_t *propertyName,
@@ -381,7 +268,13 @@ HRESULT GetOptionalSinglePropertyValue(const ComPtr<ABI::Windows::Foundation::Co
return result;
}
-static float GetLogicalDpi()
+RECT InspectableNativeWindow::clientRect(const Size &size)
+{
+ return {0, 0, static_cast<long>(ConvertDipsToPixels(size.Width)),
+ static_cast<long>(ConvertDipsToPixels(size.Height))};
+}
+
+float GetLogicalDpi()
{
ComPtr<ABI::Windows::Graphics::Display::IDisplayPropertiesStatics> displayProperties;
float dpi = 96.0f;
@@ -396,7 +289,7 @@ static float GetLogicalDpi()
return dpi;
}
-long ConvertDipsToPixels(float dips)
+float ConvertDipsToPixels(float dips)
{
static const float dipsPerInch = 96.0f;
return lround((dips * GetLogicalDpi() / dipsPerInch));
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h
index 2d58f1c00a..d81c3e5fb9 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h
@@ -10,14 +10,18 @@
#ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_
#define LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_
-#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h"
-
+#include "common/debug.h"
#include "common/platform.h"
#include "angle_windowsstore.h"
+#include <EGL/eglplatform.h>
+
+#include <windows.applicationmodel.core.h>
#include <windows.ui.xaml.h>
#include <windows.ui.xaml.media.dxinterop.h>
+#include <wrl.h>
+#include <wrl/wrappers/corewrappers.h>
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
@@ -26,7 +30,8 @@ using namespace ABI::Windows::Foundation::Collections;
namespace rx
{
-long ConvertDipsToPixels(float dips);
+float ConvertDipsToPixels(float dips);
+float GetLogicalDpi();
class InspectableNativeWindow
{
@@ -35,24 +40,25 @@ class InspectableNativeWindow
mSupportsSwapChainResize(true),
mSwapChainSizeSpecified(false),
mSwapChainScaleSpecified(false),
- mSwapChainScale(1.0f),
mClientRectChanged(false),
mClientRect({0,0,0,0}),
- mNewClientRect({0,0,0,0}),
- mRotationFlags(NativeWindow::RotateNone)
+ mNewClientRect({0,0,0,0})
{
mSizeChangedEventToken.value = 0;
+ mSwapChainScale = 96.0f / GetLogicalDpi();
+ if (mSwapChainScale != 1.0f)
+ mSwapChainScaleSpecified = true;
}
virtual ~InspectableNativeWindow(){}
virtual bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) = 0;
virtual HRESULT createSwapChain(ID3D11Device *device,
- DXGIFactory *factory,
+ IDXGIFactory2 *factory,
DXGI_FORMAT format,
unsigned int width,
unsigned int height,
bool containsAlpha,
- DXGISwapChain **swapChain) = 0;
+ IDXGISwapChain1 **swapChain) = 0;
bool getClientRect(RECT *rect)
{
@@ -77,8 +83,7 @@ class InspectableNativeWindow
// If the swapchain size was specified then we should ignore this call too
if (!mSwapChainSizeSpecified)
{
- // We don't have to check if a swapchain scale was specified here; the default value is 1.0f which will have no effect.
- mNewClientRect = { 0, 0, ConvertDipsToPixels(newWindowSize.Width), ConvertDipsToPixels(newWindowSize.Height) };
+ mNewClientRect = clientRect(newWindowSize);
mClientRectChanged = true;
// If a scale was specified, then now is the time to apply the scale matrix for the new swapchain size and window size
@@ -97,18 +102,9 @@ class InspectableNativeWindow
}
}
- NativeWindow::RotationFlags rotationFlags() const
- {
- return mRotationFlags;
- }
-
- void setRotationFlags(NativeWindow::RotationFlags flags)
- {
- mRotationFlags = flags;
- }
-
protected:
virtual HRESULT scaleSwapChain(const Size &windowSize, const RECT &clientRect) = 0;
+ RECT clientRect(const Size &size);
bool mSupportsSwapChainResize; // Support for IDXGISwapChain::ResizeBuffers method
bool mSwapChainSizeSpecified; // If an EGLRenderSurfaceSizeProperty was specified
@@ -117,12 +113,10 @@ class InspectableNativeWindow
RECT mClientRect;
RECT mNewClientRect;
bool mClientRectChanged;
- NativeWindow::RotationFlags mRotationFlags;
EventRegistrationToken mSizeChangedEventToken;
};
-bool IsValidEGLNativeWindowType(EGLNativeWindowType window);
bool IsCoreWindow(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Core::ICoreWindow> *coreWindow = nullptr);
bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> *swapChainPanel = nullptr);
bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet = nullptr, IInspectable **inspectable = nullptr);
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.cpp
new file mode 100644
index 0000000000..655b23be83
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.cpp
@@ -0,0 +1,126 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// NativeWindow11WinRT.cpp: NativeWindow base class for managing IInspectable native window types.
+
+#include "libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h"
+
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h"
+#include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h"
+#include "libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h"
+
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+
+namespace rx
+{
+NativeWindow11WinRT::NativeWindow11WinRT(EGLNativeWindowType window, bool hasAlpha)
+ : NativeWindow11(window), mHasAlpha(hasAlpha)
+{
+}
+
+bool NativeWindow11WinRT::initialize()
+{
+ EGLNativeWindowType window = getNativeWindow();
+
+ // If the native window type is a IPropertySet, extract the
+ // EGLNativeWindowType (IInspectable) and initialize the
+ // proper host with this IPropertySet.
+ ComPtr<ABI::Windows::Foundation::Collections::IPropertySet> propertySet;
+ ComPtr<IInspectable> eglNativeWindow;
+ if (IsEGLConfiguredPropertySet(window, &propertySet, &eglNativeWindow))
+ {
+ // A property set was found and the EGLNativeWindowType was
+ // retrieved. The mWindow member of the host to must be updated
+ // to use the EGLNativeWindowType specified in the property set.
+ // mWindow is treated as a raw pointer not an AddRef'd interface, so
+ // the old mWindow does not need a Release() before this assignment.
+ window = eglNativeWindow.Get();
+ }
+
+ ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWindow;
+ ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> swapChainPanel;
+ if (IsCoreWindow(window, &coreWindow))
+ {
+ mImpl = std::make_shared<CoreWindowNativeWindow>();
+ if (mImpl)
+ {
+ return mImpl->initialize(window, propertySet.Get());
+ }
+ }
+ else if (IsSwapChainPanel(window, &swapChainPanel))
+ {
+ mImpl = std::make_shared<SwapChainPanelNativeWindow>();
+ if (mImpl)
+ {
+ return mImpl->initialize(window, propertySet.Get());
+ }
+ }
+ else
+ {
+ ERR() << "Invalid IInspectable EGLNativeWindowType detected. Valid IInspectables include "
+ "ICoreWindow, ISwapChainPanel and IPropertySet";
+ }
+
+ return false;
+}
+
+bool NativeWindow11WinRT::getClientRect(LPRECT rect) const
+{
+ if (mImpl)
+ {
+ return mImpl->getClientRect(rect);
+ }
+
+ return false;
+}
+
+bool NativeWindow11WinRT::isIconic() const
+{
+ return false;
+}
+
+HRESULT NativeWindow11WinRT::createSwapChain(ID3D11Device *device,
+ IDXGIFactory *factory,
+ DXGI_FORMAT format,
+ UINT width,
+ UINT height,
+ UINT samples,
+ IDXGISwapChain **swapChain)
+{
+ if (mImpl)
+ {
+ IDXGIFactory2 *factory2 = d3d11::DynamicCastComObject<IDXGIFactory2>(factory);
+ IDXGISwapChain1 *swapChain1 = nullptr;
+ HRESULT result =
+ mImpl->createSwapChain(device, factory2, format, width, height, mHasAlpha, &swapChain1);
+ SafeRelease(factory2);
+ *swapChain = static_cast<IDXGISwapChain *>(swapChain1);
+ return result;
+ }
+
+ return E_UNEXPECTED;
+}
+
+void NativeWindow11WinRT::commitChange()
+{
+}
+
+// static
+bool NativeWindow11WinRT::IsValidNativeWindow(EGLNativeWindowType window)
+{
+ // A Valid EGLNativeWindowType IInspectable can only be:
+ //
+ // ICoreWindow
+ // ISwapChainPanel
+ // IPropertySet
+ //
+ // Anything else will be rejected as an invalid IInspectable.
+ return IsCoreWindow(window) || IsSwapChainPanel(window) || IsEGLConfiguredPropertySet(window);
+}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h
new file mode 100644
index 0000000000..c4ac997a55
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h
@@ -0,0 +1,51 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// NativeWindow11WinRT.h: NativeWindow base class for managing IInspectable native window types.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_NATIVEWINDOW11WINRT_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_WINRT_NATIVEWINDOW11WINRT_H_
+
+#include "libANGLE/renderer/d3d/d3d11/NativeWindow11.h"
+
+#include <memory>
+#include <windows.applicationmodel.core.h>
+#include <wrl.h>
+#include <wrl/wrappers/corewrappers.h>
+
+namespace rx
+{
+class InspectableNativeWindow;
+
+class NativeWindow11WinRT : public NativeWindow11
+{
+ public:
+ NativeWindow11WinRT(EGLNativeWindowType window, bool hasAlpha);
+
+ bool initialize() override;
+ bool getClientRect(LPRECT rect) const override;
+ bool isIconic() const override;
+
+ HRESULT createSwapChain(ID3D11Device *device,
+ IDXGIFactory *factory,
+ DXGI_FORMAT format,
+ UINT width,
+ UINT height,
+ UINT samples,
+ IDXGISwapChain **swapChain) override;
+
+ void commitChange() override;
+
+ static bool IsValidNativeWindow(EGLNativeWindowType window);
+
+ private:
+ bool mHasAlpha;
+ std::shared_ptr<InspectableNativeWindow> mImpl;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_NATIVEWINDOW11WINRT_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp
index 548b4602fd..3425fad95d 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp
@@ -49,7 +49,8 @@ HRESULT RunOnUIThread(CODE &&code, const ComPtr<ICoreDispatcher> &dispatcher)
}
else
{
- Event waitEvent(CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS));
+ Event waitEvent(
+ CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS));
if (!waitEvent.IsValid())
{
return E_FAIL;
@@ -78,7 +79,8 @@ HRESULT RunOnUIThread(CODE &&code, const ComPtr<ICoreDispatcher> &dispatcher)
// unrecoverable state (probably deadlocked). We therefore terminate the application
// entirely. This also prevents stack corruption if the async operation is eventually
// run.
- ERR("Timeout waiting for async action on UI thread. The UI thread might be blocked.");
+ ERR()
+ << "Timeout waiting for async action on UI thread. The UI thread might be blocked.";
std::terminate();
return E_FAIL;
}
@@ -132,7 +134,8 @@ bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropert
// A EGLRenderSurfaceSizeProperty and a EGLRenderResolutionScaleProperty can't both be specified
if (mSwapChainScaleSpecified && mSwapChainSizeSpecified)
{
- ERR("It is invalid to specify both an EGLRenderSurfaceSizeProperty and a EGLRenderResolutionScaleProperty.");
+ ERR() << "It is invalid to specify both an EGLRenderSurfaceSizeProperty and a "
+ "EGLRenderResolutionScaleProperty.";
return false;
}
}
@@ -169,17 +172,14 @@ bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropert
}
else
{
- SIZE swapChainPanelSize;
+ Size swapChainPanelSize;
result = GetSwapChainPanelSize(mSwapChainPanel, mSwapChainPanelDispatcher,
- &swapChainPanelSize, &mSwapChainScale);
- if (mSwapChainScale != 1.0f)
- mSwapChainScaleSpecified = true;
+ &swapChainPanelSize);
if (SUCCEEDED(result))
{
// Update the client rect to account for any swapchain scale factor
- mClientRect = { 0, 0, static_cast<long>(ConvertDipsToPixels(swapChainPanelSize.cx * mSwapChainScale)),
- static_cast<long>(ConvertDipsToPixels(swapChainPanelSize.cy * mSwapChainScale)) };
+ mClientRect = clientRect(swapChainPanelSize);
}
}
}
@@ -241,14 +241,15 @@ void SwapChainPanelNativeWindow::unregisterForSizeChangeEvents()
}
HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device,
- DXGIFactory *factory,
+ IDXGIFactory2 *factory,
DXGI_FORMAT format,
unsigned int width,
unsigned int height,
bool containsAlpha,
- DXGISwapChain **swapChain)
+ IDXGISwapChain1 **swapChain)
{
- if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0)
+ if (device == nullptr || factory == nullptr || swapChain == nullptr || width == 0 ||
+ height == 0)
{
return E_INVALIDARG;
}
@@ -272,6 +273,7 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device,
ComPtr<IDXGISwapChain1> newSwapChain;
ComPtr<ISwapChainPanelNative> swapChainPanelNative;
+ Size currentPanelSize = {};
HRESULT result = factory->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf());
@@ -306,14 +308,14 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device,
{
if (mSwapChainSizeSpecified || mSwapChainScaleSpecified)
{
- ComPtr<ABI::Windows::UI::Xaml::IUIElement> uiElement;
- result = mSwapChainPanel.As(&uiElement);
- ASSERT(SUCCEEDED(result));
-
- Size currentSize;
- result = uiElement->get_RenderSize(&currentSize);
- ASSERT(SUCCEEDED(result));
- result = scaleSwapChain(currentSize, mClientRect);
+ result = GetSwapChainPanelSize(mSwapChainPanel, mSwapChainPanelDispatcher,
+ &currentPanelSize);
+
+ // Scale the swapchain to fit inside the contents of the panel.
+ if (SUCCEEDED(result))
+ {
+ result = scaleSwapChain(currentPanelSize, mClientRect);
+ }
}
}
@@ -342,31 +344,14 @@ HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const Size &windowSize, const
HRESULT GetSwapChainPanelSize(
const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel,
const ComPtr<ICoreDispatcher> &dispatcher,
- SIZE *windowSize, float *scaleFactor)
+ Size *windowSize)
{
ComPtr<IUIElement> uiElement;
- Size renderSize = {0, 0};
HRESULT result = swapChainPanel.As(&uiElement);
if (SUCCEEDED(result))
{
result = RunOnUIThread(
- [uiElement, &renderSize]
- {
- return uiElement->get_RenderSize(&renderSize);
- },
- dispatcher);
- }
-
- if (SUCCEEDED(result))
- {
- long width = ConvertDipsToPixels(renderSize.Width);
- long height = ConvertDipsToPixels(renderSize.Height);
- *windowSize = { width, height };
-
- if (scaleFactor)
- {
- *scaleFactor = renderSize.Width / width;
- }
+ [uiElement, windowSize] { return uiElement->get_RenderSize(windowSize); }, dispatcher);
}
return result;
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h
index 09d87ad523..f9a2fc0e4b 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h
@@ -11,6 +11,8 @@
#include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h"
+#include <memory>
+
namespace rx
{
class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<SwapChainPanelNativeWindow>
@@ -20,12 +22,12 @@ class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::e
bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) override;
HRESULT createSwapChain(ID3D11Device *device,
- DXGIFactory *factory,
+ IDXGIFactory2 *factory,
DXGI_FORMAT format,
unsigned int width,
unsigned int height,
bool containsAlpha,
- DXGISwapChain **swapChain) override;
+ IDXGISwapChain1 **swapChain) override;
protected:
HRESULT scaleSwapChain(const Size &windowSize, const RECT &clientRect) override;
@@ -37,7 +39,7 @@ class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::e
ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> mSwapChainPanel;
ComPtr<ABI::Windows::UI::Core::ICoreDispatcher> mSwapChainPanelDispatcher;
ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap;
- ComPtr<DXGISwapChain> mSwapChain;
+ ComPtr<IDXGISwapChain1> mSwapChain;
};
[uuid(8ACBD974-8187-4508-AD80-AEC77F93CF36)]
@@ -86,6 +88,6 @@ class SwapChainPanelSizeChangedHandler :
HRESULT GetSwapChainPanelSize(
const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel,
const ComPtr<ABI::Windows::UI::Core::ICoreDispatcher> &dispatcher,
- SIZE *windowSize, float *scaleFactor);
+ Size *windowSize);
}
#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp
index 2ac8ee3a29..36f2bd0db8 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp
@@ -7,6 +7,8 @@
// Blit9.cpp: Surface copy utility class.
#include "libANGLE/renderer/d3d/d3d9/Blit9.h"
+
+#include "libANGLE/renderer/d3d/TextureD3D.h"
#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
@@ -20,27 +22,34 @@ namespace
{
// Precompiled shaders
#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/standardvs.h"
-#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/flipyvs.h"
#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/passthroughps.h"
#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceps.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/luminancepremultps.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceunmultps.h"
#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskpremultps.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskunmultps.h"
-const BYTE* const g_shaderCode[] =
-{
+const BYTE *const g_shaderCode[] = {
g_vs20_standardvs,
- g_vs20_flipyvs,
g_ps20_passthroughps,
g_ps20_luminanceps,
- g_ps20_componentmaskps
+ g_ps20_luminancepremultps,
+ g_ps20_luminanceunmultps,
+ g_ps20_componentmaskps,
+ g_ps20_componentmaskpremultps,
+ g_ps20_componentmaskunmultps,
};
-const size_t g_shaderSize[] =
-{
+const size_t g_shaderSize[] = {
sizeof(g_vs20_standardvs),
- sizeof(g_vs20_flipyvs),
sizeof(g_ps20_passthroughps),
sizeof(g_ps20_luminanceps),
- sizeof(g_ps20_componentmaskps)
+ sizeof(g_ps20_luminancepremultps),
+ sizeof(g_ps20_luminanceunmultps),
+ sizeof(g_ps20_componentmaskps),
+ sizeof(g_ps20_componentmaskpremultps),
+ sizeof(g_ps20_componentmaskunmultps),
};
}
@@ -50,11 +59,11 @@ namespace rx
Blit9::Blit9(Renderer9 *renderer)
: mRenderer(renderer),
mGeometryLoaded(false),
- mQuadVertexBuffer(NULL),
- mQuadVertexDeclaration(NULL),
- mSavedStateBlock(NULL),
- mSavedRenderTarget(NULL),
- mSavedDepthStencil(NULL)
+ mQuadVertexBuffer(nullptr),
+ mQuadVertexDeclaration(nullptr),
+ mSavedStateBlock(nullptr),
+ mSavedRenderTarget(nullptr),
+ mSavedDepthStencil(nullptr)
{
memset(mCompiledShaders, 0, sizeof(mCompiledShaders));
}
@@ -75,7 +84,7 @@ gl::Error Blit9::initialize()
{
if (mGeometryLoaded)
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
static const float quad[] =
@@ -88,22 +97,25 @@ gl::Error Blit9::initialize()
IDirect3DDevice9 *device = mRenderer->getDevice();
- HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL);
+ HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0,
+ D3DPOOL_DEFAULT, &mQuadVertexBuffer, nullptr);
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal blit vertex shader, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to create internal blit vertex shader, "
+ << gl::FmtHR(result);
}
- void *lockPtr = NULL;
+ void *lockPtr = nullptr;
result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0);
- if (FAILED(result) || lockPtr == NULL)
+ if (FAILED(result) || lockPtr == nullptr)
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
SafeRelease(mQuadVertexBuffer);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal blit vertex shader, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to lock internal blit vertex shader, "
+ << gl::FmtHR(result);
}
memcpy(lockPtr, quad, sizeof(quad));
@@ -121,11 +133,12 @@ gl::Error Blit9::initialize()
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
SafeRelease(mQuadVertexBuffer);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal blit vertex declaration, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to lock internal blit vertex declaration, "
+ << gl::FmtHR(result);
}
mGeometryLoaded = true;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
template <class D3DShaderType>
@@ -137,7 +150,7 @@ gl::Error Blit9::setShader(ShaderId source, const char *profile,
D3DShaderType *shader = nullptr;
- if (mCompiledShaders[source] != NULL)
+ if (mCompiledShaders[source] != nullptr)
{
shader = static_cast<D3DShaderType*>(mCompiledShaders[source]);
}
@@ -145,23 +158,17 @@ gl::Error Blit9::setShader(ShaderId source, const char *profile,
{
const BYTE* shaderCode = g_shaderCode[source];
size_t shaderSize = g_shaderSize[source];
-
- gl::Error error = (mRenderer->*createShader)(reinterpret_cast<const DWORD*>(shaderCode), shaderSize, &shader);
- if (error.isError())
- {
- return error;
- }
-
+ ANGLE_TRY((mRenderer->*createShader)(reinterpret_cast<const DWORD*>(shaderCode), shaderSize, &shader));
mCompiledShaders[source] = shader;
}
HRESULT hr = (device->*setShader)(shader);
if (FAILED(hr))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to set shader for blit operation, result: 0x%X.", hr);
+ return gl::OutOfMemory() << "Failed to set shader for blit operation, " << gl::FmtHR(hr);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error Blit9::setVertexShader(ShaderId shader)
@@ -188,20 +195,20 @@ RECT Blit9::getSurfaceRect(IDirect3DSurface9 *surface) const
return rect;
}
+gl::Extents Blit9::getSurfaceSize(IDirect3DSurface9 *surface) const
+{
+ D3DSURFACE_DESC desc;
+ surface->GetDesc(&desc);
+
+ return gl::Extents(desc.Width, desc.Height, 1);
+}
+
gl::Error Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
{
- gl::Error error = initialize();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(initialize());
- IDirect3DTexture9 *texture = NULL;
- error = copySurfaceToTexture(source, getSurfaceRect(source), &texture);
- if (error.isError())
- {
- return error;
- }
+ IDirect3DBaseTexture9 *texture = nullptr;
+ ANGLE_TRY(copySurfaceToTexture(source, getSurfaceRect(source), &texture));
IDirect3DDevice9 *device = mRenderer->getDevice();
@@ -210,14 +217,15 @@ gl::Error Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
device->SetTexture(0, texture);
device->SetRenderTarget(0, dest);
- setVertexShader(SHADER_VS_STANDARD);
- setPixelShader(SHADER_PS_PASSTHROUGH);
+ ANGLE_TRY(setVertexShader(SHADER_VS_STANDARD));
+ ANGLE_TRY(setPixelShader(SHADER_PS_PASSTHROUGH));
setCommonBlitState();
device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
- setViewport(getSurfaceRect(dest), gl::Offset(0, 0, 0));
+ setViewportAndShaderConstants(getSurfaceRect(source), getSurfaceSize(source),
+ getSurfaceRect(dest), false);
render();
@@ -225,34 +233,32 @@ gl::Error Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
restoreState();
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Blit9::copy2D(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLint level)
+gl::Error Blit9::copy2D(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const RECT &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level)
{
- gl::Error error = initialize();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(initialize());
const gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0);
ASSERT(colorbuffer);
RenderTarget9 *renderTarget9 = nullptr;
- error = colorbuffer->getRenderTarget(&renderTarget9);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(colorbuffer->getRenderTarget(context, &renderTarget9));
ASSERT(renderTarget9);
IDirect3DSurface9 *source = renderTarget9->getSurface();
ASSERT(source);
- IDirect3DSurface9 *destSurface = NULL;
+ IDirect3DSurface9 *destSurface = nullptr;
TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage);
- error = storage9->getSurfaceLevel(GL_TEXTURE_2D, level, true, &destSurface);
+ gl::Error error = storage9->getSurfaceLevel(context, GL_TEXTURE_2D, level, true, &destSurface);
if (error.isError())
{
SafeRelease(source);
@@ -260,7 +266,8 @@ gl::Error Blit9::copy2D(const gl::Framebuffer *framebuffer, const RECT &sourceRe
}
ASSERT(destSurface);
- gl::Error result = copy(source, sourceRect, destFormat, destOffset, destSurface);
+ gl::Error result =
+ copy(source, nullptr, sourceRect, destFormat, destOffset, destSurface, false, false, false);
SafeRelease(destSurface);
SafeRelease(source);
@@ -268,7 +275,14 @@ gl::Error Blit9::copy2D(const gl::Framebuffer *framebuffer, const RECT &sourceRe
return result;
}
-gl::Error Blit9::copyCube(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level)
+gl::Error Blit9::copyCube(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const RECT &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLenum target,
+ GLint level)
{
gl::Error error = initialize();
if (error.isError())
@@ -280,7 +294,7 @@ gl::Error Blit9::copyCube(const gl::Framebuffer *framebuffer, const RECT &source
ASSERT(colorbuffer);
RenderTarget9 *renderTarget9 = nullptr;
- error = colorbuffer->getRenderTarget(&renderTarget9);
+ error = colorbuffer->getRenderTarget(context, &renderTarget9);
if (error.isError())
{
return error;
@@ -290,9 +304,9 @@ gl::Error Blit9::copyCube(const gl::Framebuffer *framebuffer, const RECT &source
IDirect3DSurface9 *source = renderTarget9->getSurface();
ASSERT(source);
- IDirect3DSurface9 *destSurface = NULL;
+ IDirect3DSurface9 *destSurface = nullptr;
TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage);
- error = storage9->getSurfaceLevel(target, level, true, &destSurface);
+ error = storage9->getSurfaceLevel(context, target, level, true, &destSurface);
if (error.isError())
{
SafeRelease(source);
@@ -300,7 +314,8 @@ gl::Error Blit9::copyCube(const gl::Framebuffer *framebuffer, const RECT &source
}
ASSERT(destSurface);
- gl::Error result = copy(source, sourceRect, destFormat, destOffset, destSurface);
+ gl::Error result =
+ copy(source, nullptr, sourceRect, destFormat, destOffset, destSurface, false, false, false);
SafeRelease(destSurface);
SafeRelease(source);
@@ -308,9 +323,69 @@ gl::Error Blit9::copyCube(const gl::Framebuffer *framebuffer, const RECT &source
return result;
}
-gl::Error Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest)
+gl::Error Blit9::copyTexture(const gl::Context *context,
+ const gl::Texture *source,
+ GLint sourceLevel,
+ const RECT &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLenum destTarget,
+ GLint destLevel,
+ bool flipY,
+ bool premultiplyAlpha,
+ bool unmultiplyAlpha)
+{
+ ANGLE_TRY(initialize());
+
+ const TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
+
+ TextureStorage *sourceStorage = nullptr;
+ ANGLE_TRY(const_cast<TextureD3D *>(sourceD3D)->getNativeTexture(context, &sourceStorage));
+
+ TextureStorage9_2D *sourceStorage9 = GetAs<TextureStorage9_2D>(sourceStorage);
+ ASSERT(sourceStorage9);
+
+ TextureStorage9 *destStorage9 = GetAs<TextureStorage9>(storage);
+ ASSERT(destStorage9);
+
+ ASSERT(sourceLevel == 0);
+ IDirect3DBaseTexture9 *sourceTexture = nullptr;
+ ANGLE_TRY(sourceStorage9->getBaseTexture(context, &sourceTexture));
+
+ IDirect3DSurface9 *sourceSurface = nullptr;
+ ANGLE_TRY(
+ sourceStorage9->getSurfaceLevel(context, GL_TEXTURE_2D, sourceLevel, true, &sourceSurface));
+
+ IDirect3DSurface9 *destSurface = nullptr;
+ gl::Error error =
+ destStorage9->getSurfaceLevel(context, destTarget, destLevel, true, &destSurface);
+ if (error.isError())
+ {
+ SafeRelease(sourceSurface);
+ return error;
+ }
+
+ error = copy(sourceSurface, sourceTexture, sourceRect, destFormat, destOffset, destSurface,
+ flipY, premultiplyAlpha, unmultiplyAlpha);
+
+ SafeRelease(sourceSurface);
+ SafeRelease(destSurface);
+
+ return error;
+}
+
+gl::Error Blit9::copy(IDirect3DSurface9 *source,
+ IDirect3DBaseTexture9 *sourceTexture,
+ const RECT &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ IDirect3DSurface9 *dest,
+ bool flipY,
+ bool premultiplyAlpha,
+ bool unmultiplyAlpha)
{
- ASSERT(source != NULL && dest != NULL);
+ ASSERT(source != nullptr && dest != nullptr);
IDirect3DDevice9 *device = mRenderer->getDevice();
@@ -319,8 +394,10 @@ gl::Error Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum
source->GetDesc(&sourceDesc);
dest->GetDesc(&destDesc);
- if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET &&
- d3d9_gl::IsFormatChannelEquivalent(destDesc.Format, destFormat)) // Can use StretchRect
+ // Check if it's possible to use StetchRect
+ if (sourceDesc.Format == destDesc.Format && (destDesc.Usage & D3DUSAGE_RENDERTARGET) &&
+ d3d9_gl::IsFormatChannelEquivalent(destDesc.Format, destFormat) && !flipY &&
+ premultiplyAlpha == unmultiplyAlpha)
{
RECT destRect = { destOffset.x, destOffset.y, destOffset.x + (sourceRect.right - sourceRect.left), destOffset.y + (sourceRect.bottom - sourceRect.top)};
HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT);
@@ -328,85 +405,135 @@ gl::Error Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to blit between textures, StretchRect result: 0x%X.", result);
+ return gl::OutOfMemory()
+ << "Failed to blit between textures, StretchRect " << gl::FmtHR(result);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
else
{
- return formatConvert(source, sourceRect, destFormat, destOffset, dest);
- }
-}
+ IDirect3DBaseTexture9 *texture = sourceTexture;
+ RECT adjustedSourceRect = sourceRect;
+ gl::Extents sourceSize(sourceDesc.Width, sourceDesc.Height, 1);
-gl::Error Blit9::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest)
-{
- gl::Error error = initialize();
- if (error.isError())
- {
- return error;
- }
+ if (texture == nullptr)
+ {
+ ANGLE_TRY(copySurfaceToTexture(source, sourceRect, &texture));
+
+ // copySurfaceToTexture only copies in the sourceRect area of the source surface.
+ // Adjust sourceRect so that it is now covering the entire source texture
+ adjustedSourceRect.left = 0;
+ adjustedSourceRect.right = sourceRect.right - sourceRect.left;
+ adjustedSourceRect.top = 0;
+ adjustedSourceRect.bottom = sourceRect.bottom - sourceRect.top;
+
+ sourceSize.width = sourceRect.right - sourceRect.left;
+ sourceSize.height = sourceRect.bottom - sourceRect.top;
+ }
+ else
+ {
+ texture->AddRef();
+ }
+
+ gl::Error error = formatConvert(texture, adjustedSourceRect, sourceSize, destFormat,
+ destOffset, dest, flipY, premultiplyAlpha, unmultiplyAlpha);
+
+ SafeRelease(texture);
- IDirect3DTexture9 *texture = NULL;
- error = copySurfaceToTexture(source, sourceRect, &texture);
- if (error.isError())
- {
return error;
}
+}
+
+gl::Error Blit9::formatConvert(IDirect3DBaseTexture9 *source,
+ const RECT &sourceRect,
+ const gl::Extents &sourceSize,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ IDirect3DSurface9 *dest,
+ bool flipY,
+ bool premultiplyAlpha,
+ bool unmultiplyAlpha)
+{
+ ANGLE_TRY(initialize());
IDirect3DDevice9 *device = mRenderer->getDevice();
saveState();
- device->SetTexture(0, texture);
+ device->SetTexture(0, source);
device->SetRenderTarget(0, dest);
- setViewport(sourceRect, destOffset);
+ RECT destRect;
+ destRect.left = destOffset.x;
+ destRect.right = destOffset.x + (sourceRect.right - sourceRect.left);
+ destRect.top = destOffset.y;
+ destRect.bottom = destOffset.y + (sourceRect.bottom - sourceRect.top);
+
+ setViewportAndShaderConstants(sourceRect, sourceSize, destRect, flipY);
setCommonBlitState();
- error = setFormatConvertShaders(destFormat);
+ gl::Error error = setFormatConvertShaders(destFormat, flipY, premultiplyAlpha, unmultiplyAlpha);
if (!error.isError())
{
render();
}
- SafeRelease(texture);
-
restoreState();
return error;
}
-gl::Error Blit9::setFormatConvertShaders(GLenum destFormat)
+gl::Error Blit9::setFormatConvertShaders(GLenum destFormat,
+ bool flipY,
+ bool premultiplyAlpha,
+ bool unmultiplyAlpha)
{
- gl::Error error = setVertexShader(SHADER_VS_STANDARD);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(setVertexShader(SHADER_VS_STANDARD));
switch (destFormat)
{
- default: UNREACHABLE();
case GL_RGBA:
case GL_BGRA_EXT:
case GL_RGB:
case GL_RG_EXT:
case GL_RED_EXT:
case GL_ALPHA:
- error = setPixelShader(SHADER_PS_COMPONENTMASK);
- break;
+ if (premultiplyAlpha == unmultiplyAlpha)
+ {
+ ANGLE_TRY(setPixelShader(SHADER_PS_COMPONENTMASK));
+ }
+ else if (premultiplyAlpha)
+ {
+ ANGLE_TRY(setPixelShader(SHADER_PS_COMPONENTMASK_PREMULTIPLY_ALPHA));
+ }
+ else
+ {
+ ASSERT(unmultiplyAlpha);
+ ANGLE_TRY(setPixelShader(SHADER_PS_COMPONENTMASK_UNMULTIPLY_ALPHA));
+ }
+ break;
case GL_LUMINANCE:
case GL_LUMINANCE_ALPHA:
- error = setPixelShader(SHADER_PS_LUMINANCE);
- break;
- }
-
- if (error.isError())
- {
- return error;
+ if (premultiplyAlpha == unmultiplyAlpha)
+ {
+ ANGLE_TRY(setPixelShader(SHADER_PS_LUMINANCE));
+ }
+ else if (premultiplyAlpha)
+ {
+ ANGLE_TRY(setPixelShader(SHADER_PS_LUMINANCE_PREMULTIPLY_ALPHA));
+ }
+ else
+ {
+ ASSERT(unmultiplyAlpha);
+ ANGLE_TRY(setPixelShader(SHADER_PS_LUMINANCE_UNMULTIPLY_ALPHA));
+ }
+ break;
+
+ default:
+ UNREACHABLE();
}
enum { X = 0, Y = 1, Z = 2, W = 3 };
@@ -502,10 +629,12 @@ gl::Error Blit9::setFormatConvertShaders(GLenum destFormat)
mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst, 2);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect, IDirect3DTexture9 **outTexture)
+gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface,
+ const RECT &sourceRect,
+ IDirect3DBaseTexture9 **outTexture)
{
ASSERT(surface);
@@ -516,12 +645,15 @@ gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &so
// Copy the render target into a texture
IDirect3DTexture9 *texture;
- HRESULT result = device->CreateTexture(sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, 1, D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, NULL);
+ HRESULT result = device->CreateTexture(
+ sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, 1,
+ D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, nullptr);
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal texture for blit, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to allocate internal texture for blit, "
+ << gl::FmtHR(result);
}
IDirect3DSurface9 *textureSurface;
@@ -531,11 +663,12 @@ gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &so
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
SafeRelease(texture);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to query surface of internal blit texture, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to query surface of internal blit texture, "
+ << gl::FmtHR(result);
}
mRenderer->endScene();
- result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE);
+ result = device->StretchRect(surface, &sourceRect, textureSurface, nullptr, D3DTEXF_NONE);
SafeRelease(textureSurface);
@@ -543,35 +676,50 @@ gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &so
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
SafeRelease(texture);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to copy between internal blit textures, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to copy between internal blit textures, "
+ << gl::FmtHR(result);
}
*outTexture = texture;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-void Blit9::setViewport(const RECT &sourceRect, const gl::Offset &offset)
+void Blit9::setViewportAndShaderConstants(const RECT &sourceRect,
+ const gl::Extents &sourceSize,
+ const RECT &destRect,
+ bool flipY)
{
IDirect3DDevice9 *device = mRenderer->getDevice();
D3DVIEWPORT9 vp;
- vp.X = offset.x;
- vp.Y = offset.y;
- vp.Width = sourceRect.right - sourceRect.left;
- vp.Height = sourceRect.bottom - sourceRect.top;
+ vp.X = destRect.left;
+ vp.Y = destRect.top;
+ vp.Width = destRect.right - destRect.left;
+ vp.Height = destRect.bottom - destRect.top;
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
device->SetViewport(&vp);
- float halfPixelAdjust[4] = { -1.0f/vp.Width, 1.0f/vp.Height, 0, 0 };
- device->SetVertexShaderConstantF(0, halfPixelAdjust, 1);
+ float vertexConstants[8] = {
+ // halfPixelAdjust
+ -1.0f / vp.Width, 1.0f / vp.Height, 0, 0,
+ // texcoordOffset
+ static_cast<float>(sourceRect.left) / sourceSize.width,
+ static_cast<float>(flipY ? sourceRect.bottom : sourceRect.top) / sourceSize.height,
+ static_cast<float>(sourceRect.right - sourceRect.left) / sourceSize.width,
+ static_cast<float>(flipY ? sourceRect.top - sourceRect.bottom
+ : sourceRect.bottom - sourceRect.top) /
+ sourceSize.height,
+ };
+
+ device->SetVertexShaderConstantF(0, vertexConstants, 2);
}
void Blit9::setCommonBlitState()
{
IDirect3DDevice9 *device = mRenderer->getDevice();
- device->SetDepthStencilSurface(NULL);
+ device->SetDepthStencilSurface(nullptr);
device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
@@ -617,7 +765,7 @@ void Blit9::saveState()
device->GetDepthStencilSurface(&mSavedDepthStencil);
device->GetRenderTarget(0, &mSavedRenderTarget);
- if (mSavedStateBlock == NULL)
+ if (mSavedStateBlock == nullptr)
{
hr = device->BeginStateBlock();
ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
@@ -626,9 +774,9 @@ void Blit9::saveState()
static const float dummyConst[8] = { 0 };
- device->SetVertexShader(NULL);
+ device->SetVertexShader(nullptr);
device->SetVertexShaderConstantF(0, dummyConst, 2);
- device->SetPixelShader(NULL);
+ device->SetPixelShader(nullptr);
device->SetPixelShaderConstantF(0, dummyConst, 2);
D3DVIEWPORT9 dummyVp;
@@ -641,7 +789,7 @@ void Blit9::saveState()
device->SetViewport(&dummyVp);
- device->SetTexture(0, NULL);
+ device->SetTexture(0, nullptr);
device->SetStreamSource(0, mQuadVertexBuffer, 0, 0);
@@ -651,9 +799,9 @@ void Blit9::saveState()
ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
}
- ASSERT(mSavedStateBlock != NULL);
+ ASSERT(mSavedStateBlock != nullptr);
- if (mSavedStateBlock != NULL)
+ if (mSavedStateBlock != nullptr)
{
hr = mSavedStateBlock->Capture();
ASSERT(SUCCEEDED(hr));
@@ -670,9 +818,9 @@ void Blit9::restoreState()
device->SetRenderTarget(0, mSavedRenderTarget);
SafeRelease(mSavedRenderTarget);
- ASSERT(mSavedStateBlock != NULL);
+ ASSERT(mSavedStateBlock != nullptr);
- if (mSavedStateBlock != NULL)
+ if (mSavedStateBlock != nullptr)
{
mSavedStateBlock->Apply();
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h
index 586abd2580..026874f8ae 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h
@@ -16,7 +16,10 @@
namespace gl
{
+class Context;
class Framebuffer;
+class Texture;
+struct Extents;
struct Offset;
}
@@ -35,13 +38,33 @@ class Blit9 : angle::NonCopyable
// Copy from source surface to dest surface.
// sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left)
- gl::Error copy2D(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLint level);
- gl::Error copyCube(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level);
-
- // Copy from source surface to dest surface.
- // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left)
- // source is interpreted as RGBA and destFormat specifies the desired result format. For example, if destFormat = GL_RGB, the alpha channel will be forced to 0.
- gl::Error formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest);
+ gl::Error copy2D(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const RECT &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level);
+ gl::Error copyCube(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const RECT &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLenum target,
+ GLint level);
+ gl::Error copyTexture(const gl::Context *context,
+ const gl::Texture *source,
+ GLint sourceLevel,
+ const RECT &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLenum destTarget,
+ GLint destLevel,
+ bool flipY,
+ bool premultiplyAlpha,
+ bool unmultiplyAlpha);
// 2x2 box filter sample from source to dest.
// Requires that source is RGB(A) and dest has the same format as source.
@@ -54,23 +77,56 @@ class Blit9 : angle::NonCopyable
IDirect3DVertexBuffer9 *mQuadVertexBuffer;
IDirect3DVertexDeclaration9 *mQuadVertexDeclaration;
- gl::Error setFormatConvertShaders(GLenum destFormat);
-
- gl::Error copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest);
- gl::Error copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect, IDirect3DTexture9 **outTexture);
- void setViewport(const RECT &sourceRect, const gl::Offset &offset);
+ // Copy from source texture to dest surface.
+ // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left)
+ // source is interpreted as RGBA and destFormat specifies the desired result format. For
+ // example, if destFormat = GL_RGB, the alpha channel will be forced to 0.
+ gl::Error formatConvert(IDirect3DBaseTexture9 *source,
+ const RECT &sourceRect,
+ const gl::Extents &sourceSize,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ IDirect3DSurface9 *dest,
+ bool flipY,
+ bool premultiplyAlpha,
+ bool unmultiplyAlpha);
+ gl::Error setFormatConvertShaders(GLenum destFormat,
+ bool flipY,
+ bool premultiplyAlpha,
+ bool unmultiplyAlpha);
+
+ gl::Error copy(IDirect3DSurface9 *source,
+ IDirect3DBaseTexture9 *sourceTexture,
+ const RECT &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ IDirect3DSurface9 *dest,
+ bool flipY,
+ bool premultiplyAlpha,
+ bool unmultiplyAlpha);
+ gl::Error copySurfaceToTexture(IDirect3DSurface9 *surface,
+ const RECT &sourceRect,
+ IDirect3DBaseTexture9 **outTexture);
+ void setViewportAndShaderConstants(const RECT &sourceRect,
+ const gl::Extents &sourceSize,
+ const RECT &destRect,
+ bool flipY);
void setCommonBlitState();
RECT getSurfaceRect(IDirect3DSurface9 *surface) const;
+ gl::Extents getSurfaceSize(IDirect3DSurface9 *surface) const;
// This enum is used to index mCompiledShaders and mShaderSource.
enum ShaderId
{
SHADER_VS_STANDARD,
- SHADER_VS_FLIPY,
SHADER_PS_PASSTHROUGH,
SHADER_PS_LUMINANCE,
+ SHADER_PS_LUMINANCE_PREMULTIPLY_ALPHA,
+ SHADER_PS_LUMINANCE_UNMULTIPLY_ALPHA,
SHADER_PS_COMPONENTMASK,
- SHADER_COUNT
+ SHADER_PS_COMPONENTMASK_PREMULTIPLY_ALPHA,
+ SHADER_PS_COMPONENTMASK_UNMULTIPLY_ALPHA,
+ SHADER_COUNT,
};
// This actually contains IDirect3DVertexShader9 or IDirect3DPixelShader9 casted to IUnknown.
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp
index 804b6971ce..dc308e7752 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp
@@ -12,23 +12,37 @@
namespace rx
{
-Buffer9::Buffer9(Renderer9 *renderer)
- : BufferD3D(renderer),
- mSize(0)
-{}
+Buffer9::Buffer9(const gl::BufferState &state, Renderer9 *renderer)
+ : BufferD3D(state, renderer), mSize(0)
+{
+}
Buffer9::~Buffer9()
{
mSize = 0;
}
-gl::Error Buffer9::setData(const void* data, size_t size, GLenum usage)
+size_t Buffer9::getSize() const
+{
+ return mSize;
+}
+
+bool Buffer9::supportsDirectBinding() const
+{
+ return false;
+}
+
+gl::Error Buffer9::setData(const gl::Context *context,
+ gl::BufferBinding /*target*/,
+ const void *data,
+ size_t size,
+ gl::BufferUsage usage)
{
if (size > mMemory.size())
{
if (!mMemory.resize(size))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal buffer.");
+ return gl::OutOfMemory() << "Failed to resize internal buffer.";
}
}
@@ -38,25 +52,30 @@ gl::Error Buffer9::setData(const void* data, size_t size, GLenum usage)
memcpy(mMemory.data(), data, size);
}
- invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE);
+ updateD3DBufferUsage(context, usage);
- updateD3DBufferUsage(usage);
- return gl::Error(GL_NO_ERROR);
+ invalidateStaticData(context);
+
+ return gl::NoError();
}
-gl::Error Buffer9::getData(const uint8_t **outData)
+gl::Error Buffer9::getData(const gl::Context *context, const uint8_t **outData)
{
*outData = mMemory.data();
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Buffer9::setSubData(const void* data, size_t size, size_t offset)
+gl::Error Buffer9::setSubData(const gl::Context *context,
+ gl::BufferBinding /*target*/,
+ const void *data,
+ size_t size,
+ size_t offset)
{
if (offset + size > mMemory.size())
{
if (!mMemory.resize(offset + size))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal buffer.");
+ return gl::OutOfMemory() << "Failed to resize internal buffer.";
}
}
@@ -66,46 +85,55 @@ gl::Error Buffer9::setSubData(const void* data, size_t size, size_t offset)
memcpy(mMemory.data() + offset, data, size);
}
- invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE);
+ invalidateStaticData(context);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Buffer9::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size)
+gl::Error Buffer9::copySubData(const gl::Context *context,
+ BufferImpl *source,
+ GLintptr sourceOffset,
+ GLintptr destOffset,
+ GLsizeiptr size)
{
// Note: this method is currently unreachable
- Buffer9* sourceBuffer = GetAs<Buffer9>(source);
+ Buffer9 *sourceBuffer = GetAs<Buffer9>(source);
ASSERT(sourceBuffer);
memcpy(mMemory.data() + destOffset, sourceBuffer->mMemory.data() + sourceOffset, size);
- invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE);
+ invalidateStaticData(context);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
// We do not support buffer mapping in D3D9
-gl::Error Buffer9::map(GLenum access, GLvoid **mapPtr)
+gl::Error Buffer9::map(const gl::Context *context, GLenum access, void **mapPtr)
{
UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION);
+ return gl::InternalError();
}
-gl::Error Buffer9::mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr)
+gl::Error Buffer9::mapRange(const gl::Context *context,
+ size_t offset,
+ size_t length,
+ GLbitfield access,
+ void **mapPtr)
{
UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION);
+ return gl::InternalError();
}
-gl::Error Buffer9::unmap(GLboolean *result)
+gl::Error Buffer9::unmap(const gl::Context *context, GLboolean *result)
{
UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION);
+ return gl::InternalError();
}
-void Buffer9::markTransformFeedbackUsage()
+gl::Error Buffer9::markTransformFeedbackUsage(const gl::Context *context)
{
UNREACHABLE();
+ return gl::InternalError();
}
-}
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h
index 44a524ba28..960b2a2474 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h
@@ -20,28 +20,44 @@ class Renderer9;
class Buffer9 : public BufferD3D
{
public:
- Buffer9(Renderer9 *renderer);
- virtual ~Buffer9();
+ Buffer9(const gl::BufferState &state, Renderer9 *renderer);
+ ~Buffer9() override;
// BufferD3D implementation
- virtual size_t getSize() const { return mSize; }
- virtual bool supportsDirectBinding() const { return false; }
- gl::Error getData(const uint8_t **outData) override;
+ size_t getSize() const override;
+ bool supportsDirectBinding() const override;
+ gl::Error getData(const gl::Context *context, const uint8_t **outData) override;
// BufferImpl implementation
- virtual gl::Error setData(const void* data, size_t size, GLenum usage);
- virtual gl::Error setSubData(const void* data, size_t size, size_t offset);
- virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size);
- virtual gl::Error map(GLenum access, GLvoid **mapPtr);
- virtual gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr);
- virtual gl::Error unmap(GLboolean *result);
- virtual void markTransformFeedbackUsage();
+ gl::Error setData(const gl::Context *context,
+ gl::BufferBinding target,
+ const void *data,
+ size_t size,
+ gl::BufferUsage usage) override;
+ gl::Error setSubData(const gl::Context *context,
+ gl::BufferBinding target,
+ const void *data,
+ size_t size,
+ size_t offset) override;
+ gl::Error copySubData(const gl::Context *context,
+ BufferImpl *source,
+ GLintptr sourceOffset,
+ GLintptr destOffset,
+ GLsizeiptr size) override;
+ gl::Error map(const gl::Context *context, GLenum access, void **mapPtr) override;
+ gl::Error mapRange(const gl::Context *context,
+ size_t offset,
+ size_t length,
+ GLbitfield access,
+ void **mapPtr) override;
+ gl::Error unmap(const gl::Context *context, GLboolean *result) override;
+ gl::Error markTransformFeedbackUsage(const gl::Context *context) override;
private:
- MemoryBuffer mMemory;
+ angle::MemoryBuffer mMemory;
size_t mSize;
};
-}
+} // namespace rx
-#endif // LIBANGLE_RENDERER_D3D_D3D9_BUFFER9_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D9_BUFFER9_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Context9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Context9.cpp
new file mode 100644
index 0000000000..1b9874cc20
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Context9.cpp
@@ -0,0 +1,303 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Context9:
+// D3D9-specific functionality associated with a GL Context.
+//
+
+#include "libANGLE/renderer/d3d/d3d9/Context9.h"
+
+#include "common/string_utils.h"
+#include "libANGLE/renderer/d3d/CompilerD3D.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/SamplerD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/Buffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Fence9.h"
+#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Query9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/StateManager9.h"
+#include "libANGLE/renderer/d3d/d3d9/VertexArray9.h"
+
+namespace rx
+{
+
+Context9::Context9(const gl::ContextState &state, Renderer9 *renderer)
+ : ContextImpl(state), mRenderer(renderer)
+{
+}
+
+Context9::~Context9()
+{
+}
+
+gl::Error Context9::initialize()
+{
+ return gl::NoError();
+}
+
+CompilerImpl *Context9::createCompiler()
+{
+ return new CompilerD3D(SH_HLSL_3_0_OUTPUT);
+}
+
+ShaderImpl *Context9::createShader(const gl::ShaderState &data)
+{
+ return new ShaderD3D(data, mRenderer->getWorkarounds(), mRenderer->getNativeExtensions());
+}
+
+ProgramImpl *Context9::createProgram(const gl::ProgramState &data)
+{
+ return new ProgramD3D(data, mRenderer);
+}
+
+FramebufferImpl *Context9::createFramebuffer(const gl::FramebufferState &data)
+{
+ return new Framebuffer9(data, mRenderer);
+}
+
+TextureImpl *Context9::createTexture(const gl::TextureState &state)
+{
+ switch (state.getTarget())
+ {
+ case GL_TEXTURE_2D:
+ return new TextureD3D_2D(state, mRenderer);
+ case GL_TEXTURE_CUBE_MAP:
+ return new TextureD3D_Cube(state, mRenderer);
+ case GL_TEXTURE_EXTERNAL_OES:
+ return new TextureD3D_External(state, mRenderer);
+ default:
+ UNREACHABLE();
+ }
+ return nullptr;
+}
+
+RenderbufferImpl *Context9::createRenderbuffer()
+{
+ return new RenderbufferD3D(mRenderer);
+}
+
+BufferImpl *Context9::createBuffer(const gl::BufferState &state)
+{
+ return new Buffer9(state, mRenderer);
+}
+
+VertexArrayImpl *Context9::createVertexArray(const gl::VertexArrayState &data)
+{
+ return new VertexArray9(data);
+}
+
+QueryImpl *Context9::createQuery(GLenum type)
+{
+ return new Query9(mRenderer, type);
+}
+
+FenceNVImpl *Context9::createFenceNV()
+{
+ return new FenceNV9(mRenderer);
+}
+
+SyncImpl *Context9::createSync()
+{
+ // D3D9 doesn't support ES 3.0 and its sync objects.
+ UNREACHABLE();
+ return nullptr;
+}
+
+TransformFeedbackImpl *Context9::createTransformFeedback(const gl::TransformFeedbackState &state)
+{
+ UNREACHABLE();
+ return nullptr;
+}
+
+SamplerImpl *Context9::createSampler(const gl::SamplerState &state)
+{
+ return new SamplerD3D(state);
+}
+
+ProgramPipelineImpl *Context9::createProgramPipeline(const gl::ProgramPipelineState &data)
+{
+ UNREACHABLE();
+ return nullptr;
+}
+
+std::vector<PathImpl *> Context9::createPaths(GLsizei)
+{
+ return std::vector<PathImpl *>();
+}
+
+gl::Error Context9::flush(const gl::Context *context)
+{
+ return mRenderer->flush();
+}
+
+gl::Error Context9::finish(const gl::Context *context)
+{
+ return mRenderer->finish();
+}
+
+gl::Error Context9::drawArrays(const gl::Context *context, GLenum mode, GLint first, GLsizei count)
+{
+ return mRenderer->genericDrawArrays(context, mode, first, count, 0);
+}
+
+gl::Error Context9::drawArraysInstanced(const gl::Context *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount)
+{
+ return mRenderer->genericDrawArrays(context, mode, first, count, instanceCount);
+}
+
+gl::Error Context9::drawElements(const gl::Context *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices)
+{
+ return mRenderer->genericDrawElements(context, mode, count, type, indices, 0);
+}
+
+gl::Error Context9::drawElementsInstanced(const gl::Context *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei instances)
+{
+ return mRenderer->genericDrawElements(context, mode, count, type, indices, instances);
+}
+
+gl::Error Context9::drawRangeElements(const gl::Context *context,
+ GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const void *indices)
+{
+ return mRenderer->genericDrawElements(context, mode, count, type, indices, 0);
+}
+
+gl::Error Context9::drawArraysIndirect(const gl::Context *context,
+ GLenum mode,
+ const void *indirect)
+{
+ UNREACHABLE();
+ return gl::InternalError() << "D3D9 doesn't support ES 3.1 DrawArraysIndirect API";
+}
+
+gl::Error Context9::drawElementsIndirect(const gl::Context *context,
+ GLenum mode,
+ GLenum type,
+ const void *indirect)
+{
+ UNREACHABLE();
+ return gl::InternalError() << "D3D9 doesn't support ES 3.1 DrawElementsIndirect API";
+}
+
+GLenum Context9::getResetStatus()
+{
+ return mRenderer->getResetStatus();
+}
+
+std::string Context9::getVendorString() const
+{
+ return mRenderer->getVendorString();
+}
+
+std::string Context9::getRendererDescription() const
+{
+ return mRenderer->getRendererDescription();
+}
+
+void Context9::insertEventMarker(GLsizei length, const char *marker)
+{
+ auto optionalString = angle::WidenString(static_cast<size_t>(length), marker);
+ if (optionalString.valid())
+ {
+ mRenderer->getAnnotator()->setMarker(optionalString.value().data());
+ }
+}
+
+void Context9::pushGroupMarker(GLsizei length, const char *marker)
+{
+ auto optionalString = angle::WidenString(static_cast<size_t>(length), marker);
+ if (optionalString.valid())
+ {
+ mRenderer->getAnnotator()->beginEvent(optionalString.value().data());
+ }
+}
+
+void Context9::popGroupMarker()
+{
+ mRenderer->getAnnotator()->endEvent();
+}
+
+void Context9::pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message)
+{
+ // Fall through to the EXT_debug_marker functions
+ pushGroupMarker(length, message);
+}
+
+void Context9::popDebugGroup()
+{
+ // Fall through to the EXT_debug_marker functions
+ popGroupMarker();
+}
+
+void Context9::syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits)
+{
+ mRenderer->getStateManager()->syncState(mState.getState(), dirtyBits);
+}
+
+GLint Context9::getGPUDisjoint()
+{
+ return mRenderer->getGPUDisjoint();
+}
+
+GLint64 Context9::getTimestamp()
+{
+ return mRenderer->getTimestamp();
+}
+
+void Context9::onMakeCurrent(const gl::Context *context)
+{
+}
+
+const gl::Caps &Context9::getNativeCaps() const
+{
+ return mRenderer->getNativeCaps();
+}
+
+const gl::TextureCapsMap &Context9::getNativeTextureCaps() const
+{
+ return mRenderer->getNativeTextureCaps();
+}
+
+const gl::Extensions &Context9::getNativeExtensions() const
+{
+ return mRenderer->getNativeExtensions();
+}
+
+const gl::Limitations &Context9::getNativeLimitations() const
+{
+ return mRenderer->getNativeLimitations();
+}
+
+gl::Error Context9::dispatchCompute(const gl::Context *context,
+ GLuint numGroupsX,
+ GLuint numGroupsY,
+ GLuint numGroupsZ)
+{
+ UNREACHABLE();
+ return gl::InternalError() << "D3D9 doesn't support ES 3.1 DispatchCompute API";
+}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Context9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Context9.h
new file mode 100644
index 0000000000..d681bfde89
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Context9.h
@@ -0,0 +1,151 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Context9:
+// D3D9-specific functionality associated with a GL Context.
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_CONTEXT9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_CONTEXT9_H_
+
+#include "libANGLE/renderer/ContextImpl.h"
+
+namespace rx
+{
+class Renderer9;
+
+class Context9 : public ContextImpl
+{
+ public:
+ Context9(const gl::ContextState &state, Renderer9 *renderer);
+ ~Context9() override;
+
+ gl::Error initialize() override;
+
+ // Shader creation
+ CompilerImpl *createCompiler() override;
+ ShaderImpl *createShader(const gl::ShaderState &data) override;
+ ProgramImpl *createProgram(const gl::ProgramState &data) override;
+
+ // Framebuffer creation
+ FramebufferImpl *createFramebuffer(const gl::FramebufferState &data) override;
+
+ // Texture creation
+ TextureImpl *createTexture(const gl::TextureState &state) override;
+
+ // Renderbuffer creation
+ RenderbufferImpl *createRenderbuffer() override;
+
+ // Buffer creation
+ BufferImpl *createBuffer(const gl::BufferState &state) override;
+
+ // Vertex Array creation
+ VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data) override;
+
+ // Query and Fence creation
+ QueryImpl *createQuery(GLenum type) override;
+ FenceNVImpl *createFenceNV() override;
+ SyncImpl *createSync() override;
+
+ // Transform Feedback creation
+ TransformFeedbackImpl *createTransformFeedback(
+ const gl::TransformFeedbackState &state) override;
+
+ // Sampler object creation
+ SamplerImpl *createSampler(const gl::SamplerState &state) override;
+
+ // Program Pipeline object creation
+ ProgramPipelineImpl *createProgramPipeline(const gl::ProgramPipelineState &data) override;
+
+ // Path object creation
+ std::vector<PathImpl *> createPaths(GLsizei) override;
+
+ // Flush and finish.
+ gl::Error flush(const gl::Context *context) override;
+ gl::Error finish(const gl::Context *context) override;
+
+ // Drawing methods.
+ gl::Error drawArrays(const gl::Context *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count) override;
+ gl::Error drawArraysInstanced(const gl::Context *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount) override;
+
+ gl::Error drawElements(const gl::Context *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices) override;
+ gl::Error drawElementsInstanced(const gl::Context *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei instances) override;
+ gl::Error drawRangeElements(const gl::Context *context,
+ GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const void *indices) override;
+ gl::Error drawArraysIndirect(const gl::Context *context,
+ GLenum mode,
+ const void *indirect) override;
+ gl::Error drawElementsIndirect(const gl::Context *context,
+ GLenum mode,
+ GLenum type,
+ const void *indirect) override;
+
+ // Device loss
+ GLenum getResetStatus() override;
+
+ // Vendor and description strings.
+ std::string getVendorString() const override;
+ std::string getRendererDescription() const override;
+
+ // EXT_debug_marker
+ void insertEventMarker(GLsizei length, const char *marker) override;
+ void pushGroupMarker(GLsizei length, const char *marker) override;
+ void popGroupMarker() override;
+
+ // KHR_debug
+ void pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message) override;
+ void popDebugGroup() override;
+
+ // State sync with dirty bits.
+ void syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits) override;
+
+ // Disjoint timer queries
+ GLint getGPUDisjoint() override;
+ GLint64 getTimestamp() override;
+
+ // Context switching
+ void onMakeCurrent(const gl::Context *context) override;
+
+ // Caps queries
+ const gl::Caps &getNativeCaps() const override;
+ const gl::TextureCapsMap &getNativeTextureCaps() const override;
+ const gl::Extensions &getNativeExtensions() const override;
+ const gl::Limitations &getNativeLimitations() const override;
+
+ gl::Error dispatchCompute(const gl::Context *context,
+ GLuint numGroupsX,
+ GLuint numGroupsY,
+ GLuint numGroupsZ) override;
+
+ Renderer9 *getRenderer() const { return mRenderer; }
+
+ private:
+ Renderer9 *mRenderer;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_CONTEXT9_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h
index 54e3bb9490..b28008335f 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h
@@ -9,12 +9,12 @@
#ifndef LIBANGLE_RENDERER_D3D_D3D9_DEBUGANNOTATOR9_H_
#define LIBANGLE_RENDERER_D3D_D3D9_DEBUGANNOTATOR9_H_
-#include "common/debug.h"
+#include "libANGLE/LoggingAnnotator.h"
namespace rx
{
-class DebugAnnotator9 : public gl::DebugAnnotator
+class DebugAnnotator9 : public angle::LoggingAnnotator
{
public:
DebugAnnotator9() {}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp
index 3300681277..bff3881655 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp
@@ -13,10 +13,7 @@
namespace rx
{
-FenceNV9::FenceNV9(Renderer9 *renderer)
- : FenceNVImpl(),
- mRenderer(renderer),
- mQuery(NULL)
+FenceNV9::FenceNV9(Renderer9 *renderer) : FenceNVImpl(), mRenderer(renderer), mQuery(nullptr)
{
}
@@ -41,10 +38,10 @@ gl::Error FenceNV9::set(GLenum condition)
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
SafeRelease(mQuery);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to end event query, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to end event query, " << gl::FmtHR(result);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error FenceNV9::test(GLboolean *outFinished)
@@ -66,7 +63,7 @@ gl::Error FenceNV9::finish()
Sleep(0);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error FenceNV9::testHelper(bool flushCommandBuffer, GLboolean *outFinished)
@@ -74,21 +71,21 @@ gl::Error FenceNV9::testHelper(bool flushCommandBuffer, GLboolean *outFinished)
ASSERT(mQuery);
DWORD getDataFlags = (flushCommandBuffer ? D3DGETDATA_FLUSH : 0);
- HRESULT result = mQuery->GetData(NULL, 0, getDataFlags);
+ HRESULT result = mQuery->GetData(nullptr, 0, getDataFlags);
if (d3d9::isDeviceLostError(result))
{
mRenderer->notifyDeviceLost();
- return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while querying result of an event query.");
+ return gl::OutOfMemory() << "Device was lost while querying result of an event query.";
}
else if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to get query data, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to get query data, " << gl::FmtHR(result);
}
ASSERT(result == S_OK || result == S_FALSE);
*outFinished = ((result == S_OK) ? GL_TRUE : GL_FALSE);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h
index 200ac68d27..de0ff20774 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h
@@ -10,7 +10,7 @@
#define LIBANGLE_RENDERER_D3D_D3D9_FENCE9_H_
#include "libANGLE/renderer/FenceNVImpl.h"
-#include "libANGLE/renderer/FenceSyncImpl.h"
+#include "libANGLE/renderer/SyncImpl.h"
namespace rx
{
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
index 9c269a8565..dff12e03f8 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
@@ -7,21 +7,25 @@
// Framebuffer9.cpp: Implements the Framebuffer9 class.
#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"
-#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
-#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
-#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
-#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
-#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
-#include "libANGLE/renderer/d3d/TextureD3D.h"
-#include "libANGLE/formatutils.h"
+
+#include "libANGLE/Context.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/renderer_utils.h"
namespace rx
{
-Framebuffer9::Framebuffer9(const gl::Framebuffer::Data &data, Renderer9 *renderer)
+Framebuffer9::Framebuffer9(const gl::FramebufferState &data, Renderer9 *renderer)
: FramebufferD3D(data, renderer), mRenderer(renderer)
{
ASSERT(mRenderer != nullptr);
@@ -31,66 +35,61 @@ Framebuffer9::~Framebuffer9()
{
}
-gl::Error Framebuffer9::discard(size_t, const GLenum *)
+gl::Error Framebuffer9::discard(const gl::Context *context, size_t, const GLenum *)
{
// Extension not implemented in D3D9 renderer
UNREACHABLE();
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Framebuffer9::invalidate(size_t, const GLenum *)
+gl::Error Framebuffer9::invalidate(const gl::Context *context, size_t, const GLenum *)
{
// Shouldn't ever reach here in D3D9
UNREACHABLE();
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Framebuffer9::invalidateSub(size_t, const GLenum *, const gl::Rectangle &)
+gl::Error Framebuffer9::invalidateSub(const gl::Context *context,
+ size_t,
+ const GLenum *,
+ const gl::Rectangle &)
{
// Shouldn't ever reach here in D3D9
UNREACHABLE();
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Framebuffer9::clear(const gl::Data &data, const ClearParameters &clearParams)
+gl::Error Framebuffer9::clearImpl(const gl::Context *context, const ClearParameters &clearParams)
{
- const gl::FramebufferAttachment *colorAttachment = mData.getColorAttachment(0);
- const gl::FramebufferAttachment *depthStencilAttachment = mData.getDepthOrStencilAttachment();
+ const gl::FramebufferAttachment *colorAttachment = mState.getColorAttachment(0);
+ const gl::FramebufferAttachment *depthStencilAttachment = mState.getDepthOrStencilAttachment();
- gl::Error error = mRenderer->applyRenderTarget(colorAttachment, depthStencilAttachment);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mRenderer->applyRenderTarget(context, colorAttachment, depthStencilAttachment));
- float nearZ = data.state->getNearPlane();
- float farZ = data.state->getFarPlane();
- mRenderer->setViewport(data.caps, data.state->getViewport(), nearZ, farZ, GL_TRIANGLES,
- data.state->getRasterizerState().frontFace, true);
+ const gl::State &glState = context->getGLState();
+ float nearZ = glState.getNearPlane();
+ float farZ = glState.getFarPlane();
+ mRenderer->setViewport(glState.getViewport(), nearZ, farZ, GL_TRIANGLES,
+ glState.getRasterizerState().frontFace, true);
- mRenderer->setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled());
+ mRenderer->setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());
- return mRenderer->clear(clearParams, colorAttachment, depthStencilAttachment);
+ return mRenderer->clear(context, clearParams, colorAttachment, depthStencilAttachment);
}
-gl::Error Framebuffer9::readPixelsImpl(const gl::Rectangle &area,
+gl::Error Framebuffer9::readPixelsImpl(const gl::Context *context,
+ const gl::Rectangle &area,
GLenum format,
GLenum type,
size_t outputPitch,
const gl::PixelPackState &pack,
- uint8_t *pixels) const
+ uint8_t *pixels)
{
- ASSERT(pack.pixelBuffer.get() == nullptr);
-
- const gl::FramebufferAttachment *colorbuffer = mData.getColorAttachment(0);
+ const gl::FramebufferAttachment *colorbuffer = mState.getColorAttachment(0);
ASSERT(colorbuffer);
RenderTarget9 *renderTarget = nullptr;
- gl::Error error = colorbuffer->getRenderTarget(&renderTarget);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(colorbuffer->getRenderTarget(context, &renderTarget));
ASSERT(renderTarget);
IDirect3DSurface9 *surface = renderTarget->getSurface();
@@ -103,7 +102,8 @@ gl::Error Framebuffer9::readPixelsImpl(const gl::Rectangle &area,
{
UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
SafeRelease(surface);
- return gl::Error(GL_OUT_OF_MEMORY, "ReadPixels is unimplemented for multisampled framebuffer attachments.");
+ return gl::OutOfMemory()
+ << "ReadPixels is unimplemented for multisampled framebuffer attachments.";
}
IDirect3DDevice9 *device = mRenderer->getDevice();
@@ -135,7 +135,7 @@ gl::Error Framebuffer9::readPixelsImpl(const gl::Rectangle &area,
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
SafeRelease(surface);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal texture for ReadPixels.");
+ return gl::OutOfMemory() << "Failed to allocate internal texture for ReadPixels.";
}
}
@@ -157,13 +157,13 @@ gl::Error Framebuffer9::readPixelsImpl(const gl::Rectangle &area,
UNREACHABLE();
}
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to read internal render target data.");
+ return gl::OutOfMemory() << "Failed to read internal render target data.";
}
if (directToPixels)
{
SafeRelease(systemSurface);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
RECT rect;
@@ -180,85 +180,42 @@ gl::Error Framebuffer9::readPixelsImpl(const gl::Rectangle &area,
UNREACHABLE();
SafeRelease(systemSurface);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal render target.");
+ return gl::OutOfMemory() << "Failed to lock internal render target.";
}
- uint8_t *source;
- int inputPitch;
- if (pack.reverseRowOrder)
- {
- source = reinterpret_cast<uint8_t*>(lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1);
- inputPitch = -lock.Pitch;
- }
- else
- {
- source = reinterpret_cast<uint8_t*>(lock.pBits);
- inputPitch = lock.Pitch;
- }
+ uint8_t *source = reinterpret_cast<uint8_t *>(lock.pBits);
+ int inputPitch = lock.Pitch;
const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
- const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(d3dFormatInfo.internalFormat);
- if (sourceFormatInfo.format == format && sourceFormatInfo.type == type)
- {
- // Direct copy possible
- for (int y = 0; y < rect.bottom - rect.top; y++)
- {
- memcpy(pixels + y * outputPitch, source + y * inputPitch, (rect.right - rect.left) * sourceFormatInfo.pixelBytes);
- }
- }
- else
- {
- const d3d9::D3DFormat &sourceD3DFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
- ColorCopyFunction fastCopyFunc = sourceD3DFormatInfo.getFastCopyFunction(format, type);
-
- GLenum sizedDestInternalFormat = gl::GetSizedInternalFormat(format, type);
- const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(sizedDestInternalFormat);
-
- if (fastCopyFunc)
- {
- // Fast copy is possible through some special function
- for (int y = 0; y < rect.bottom - rect.top; y++)
- {
- for (int x = 0; x < rect.right - rect.left; x++)
- {
- uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes;
- const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes;
+ gl::FormatType formatType(format, type);
- fastCopyFunc(src, dest);
- }
- }
- }
- else
- {
- ColorReadFunction colorReadFunction = sourceD3DFormatInfo.colorReadFunction;
- ColorWriteFunction colorWriteFunction = GetColorWriteFunction(format, type);
+ PackPixelsParams packParams;
+ packParams.area.x = rect.left;
+ packParams.area.y = rect.top;
+ packParams.area.width = rect.right - rect.left;
+ packParams.area.height = rect.bottom - rect.top;
+ packParams.format = format;
+ packParams.type = type;
+ packParams.outputPitch = static_cast<GLuint>(outputPitch);
+ packParams.pack = pack;
- uint8_t temp[sizeof(gl::ColorF)];
- for (int y = 0; y < rect.bottom - rect.top; y++)
- {
- for (int x = 0; x < rect.right - rect.left; x++)
- {
- uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes;
- const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes;
-
- // readFunc and writeFunc will be using the same type of color, CopyTexImage
- // will not allow the copy otherwise.
- colorReadFunction(src, temp);
- colorWriteFunction(temp, dest);
- }
- }
- }
- }
+ PackPixels(packParams, d3dFormatInfo.info(), inputPitch, source, pixels);
systemSurface->UnlockRect();
SafeRelease(systemSurface);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Framebuffer9::blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor,
- bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter,
- const gl::Framebuffer *sourceFramebuffer)
+gl::Error Framebuffer9::blitImpl(const gl::Context *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ const gl::Rectangle *scissor,
+ bool blitRenderTarget,
+ bool blitDepth,
+ bool blitStencil,
+ GLenum filter,
+ const gl::Framebuffer *sourceFramebuffer)
{
ASSERT(filter == GL_NEAREST);
@@ -273,18 +230,18 @@ gl::Error Framebuffer9::blit(const gl::Rectangle &sourceArea, const gl::Rectangl
ASSERT(readBuffer);
RenderTarget9 *readRenderTarget = nullptr;
- gl::Error error = readBuffer->getRenderTarget(&readRenderTarget);
+ gl::Error error = readBuffer->getRenderTarget(context, &readRenderTarget);
if (error.isError())
{
return error;
}
ASSERT(readRenderTarget);
- const gl::FramebufferAttachment *drawBuffer = mData.getColorAttachment(0);
+ const gl::FramebufferAttachment *drawBuffer = mState.getColorAttachment(0);
ASSERT(drawBuffer);
RenderTarget9 *drawRenderTarget = nullptr;
- error = drawBuffer->getRenderTarget(&drawRenderTarget);
+ error = drawBuffer->getRenderTarget(context, &drawRenderTarget);
if (error.isError())
{
return error;
@@ -389,7 +346,7 @@ gl::Error Framebuffer9::blit(const gl::Rectangle &sourceArea, const gl::Rectangl
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result);
+ return gl::OutOfMemory() << "Internal blit failed, StretchRect " << gl::FmtHR(result);
}
}
@@ -399,18 +356,18 @@ gl::Error Framebuffer9::blit(const gl::Rectangle &sourceArea, const gl::Rectangl
ASSERT(readBuffer);
RenderTarget9 *readDepthStencil = nullptr;
- gl::Error error = readBuffer->getRenderTarget(&readDepthStencil);
+ gl::Error error = readBuffer->getRenderTarget(context, &readDepthStencil);
if (error.isError())
{
return error;
}
ASSERT(readDepthStencil);
- const gl::FramebufferAttachment *drawBuffer = mData.getDepthOrStencilAttachment();
+ const gl::FramebufferAttachment *drawBuffer = mState.getDepthOrStencilAttachment();
ASSERT(drawBuffer);
RenderTarget9 *drawDepthStencil = nullptr;
- error = drawBuffer->getRenderTarget(&drawDepthStencil);
+ error = drawBuffer->getRenderTarget(context, &drawDepthStencil);
if (error.isError())
{
return error;
@@ -431,18 +388,24 @@ gl::Error Framebuffer9::blit(const gl::Rectangle &sourceArea, const gl::Rectangl
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result);
+ return gl::OutOfMemory() << "Internal blit failed, StretchRect " << gl::FmtHR(result);
}
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
GLenum Framebuffer9::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const
{
RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTarget);
const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(renderTarget9->getD3DFormat());
- return d3dFormatInfo.internalFormat;
+ return d3dFormatInfo.info().glInternalFormat;
}
+gl::Error Framebuffer9::getSamplePosition(size_t index, GLfloat *xy) const
+{
+ UNREACHABLE();
+ return gl::InternalError() << "getSamplePosition is unsupported to d3d9.";
}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h
index fe12079ae0..d2b46435ee 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h
@@ -18,26 +18,40 @@ class Renderer9;
class Framebuffer9 : public FramebufferD3D
{
public:
- Framebuffer9(const gl::Framebuffer::Data &data, Renderer9 *renderer);
- virtual ~Framebuffer9();
+ Framebuffer9(const gl::FramebufferState &data, Renderer9 *renderer);
+ ~Framebuffer9() override;
- gl::Error discard(size_t count, const GLenum *attachments) override;
- gl::Error invalidate(size_t count, const GLenum *attachments) override;
- gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override;
+ gl::Error discard(const gl::Context *context, size_t count, const GLenum *attachments) override;
+ gl::Error invalidate(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments) override;
+ gl::Error invalidateSub(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments,
+ const gl::Rectangle &area) override;
+
+ gl::Error getSamplePosition(size_t index, GLfloat *xy) const override;
private:
- gl::Error clear(const gl::Data &data, const ClearParameters &clearParams) override;
+ gl::Error clearImpl(const gl::Context *context, const ClearParameters &clearParams) override;
- gl::Error readPixelsImpl(const gl::Rectangle &area,
+ gl::Error readPixelsImpl(const gl::Context *context,
+ const gl::Rectangle &area,
GLenum format,
GLenum type,
size_t outputPitch,
const gl::PixelPackState &pack,
- uint8_t *pixels) const override;
-
- gl::Error blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor,
- bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter,
- const gl::Framebuffer *sourceFramebuffer) override;
+ uint8_t *pixels) override;
+
+ gl::Error blitImpl(const gl::Context *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ const gl::Rectangle *scissor,
+ bool blitRenderTarget,
+ bool blitDepth,
+ bool blitStencil,
+ GLenum filter,
+ const gl::Framebuffer *sourceFramebuffer) override;
GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const override;
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
index fec7e3e19d..179629b362 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
@@ -24,8 +24,8 @@ namespace rx
Image9::Image9(Renderer9 *renderer)
{
- mSurface = NULL;
- mRenderer = NULL;
+ mSurface = nullptr;
+ mRenderer = nullptr;
mD3DPool = D3DPOOL_SYSTEMMEM;
mD3DFormat = D3DFMT_UNKNOWN;
@@ -45,7 +45,9 @@ gl::Error Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9
ASSERT(SUCCEEDED(result));
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the source surface description for mipmap generation, result: 0x%X.", result);
+ return gl::OutOfMemory()
+ << "Failed to query the source surface description for mipmap generation, "
+ << gl::FmtHR(result);
}
D3DSURFACE_DESC sourceDesc;
@@ -53,7 +55,9 @@ gl::Error Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9
ASSERT(SUCCEEDED(result));
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the destination surface description for mipmap generation, result: 0x%X.", result);
+ return gl::OutOfMemory()
+ << "Failed to query the destination surface description for mipmap generation, "
+ << gl::FmtHR(result);
}
ASSERT(sourceDesc.Format == destDesc.Format);
@@ -61,23 +65,25 @@ gl::Error Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9
ASSERT(sourceDesc.Height == 1 || sourceDesc.Height / 2 == destDesc.Height);
const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(sourceDesc.Format);
- ASSERT(d3dFormatInfo.mipGenerationFunction != NULL);
+ ASSERT(d3dFormatInfo.info().mipGenerationFunction != nullptr);
D3DLOCKED_RECT sourceLocked = {0};
- result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY);
+ result = sourceSurface->LockRect(&sourceLocked, nullptr, D3DLOCK_READONLY);
ASSERT(SUCCEEDED(result));
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock the source surface for mipmap generation, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to lock the source surface for mipmap generation, "
+ << gl::FmtHR(result);
}
D3DLOCKED_RECT destLocked = {0};
- result = destSurface->LockRect(&destLocked, NULL, 0);
+ result = destSurface->LockRect(&destLocked, nullptr, 0);
ASSERT(SUCCEEDED(result));
if (FAILED(result))
{
sourceSurface->UnlockRect();
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock the destination surface for mipmap generation, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to lock the destination surface for mipmap generation, "
+ << gl::FmtHR(result);
}
const uint8_t *sourceData = reinterpret_cast<const uint8_t*>(sourceLocked.pBits);
@@ -85,40 +91,29 @@ gl::Error Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9
ASSERT(sourceData && destData);
- d3dFormatInfo.mipGenerationFunction(sourceDesc.Width, sourceDesc.Height, 1, sourceData, sourceLocked.Pitch, 0,
- destData, destLocked.Pitch, 0);
+ d3dFormatInfo.info().mipGenerationFunction(sourceDesc.Width, sourceDesc.Height, 1, sourceData,
+ sourceLocked.Pitch, 0, destData, destLocked.Pitch,
+ 0);
destSurface->UnlockRect();
sourceSurface->UnlockRect();
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error Image9::generateMipmap(Image9 *dest, Image9 *source)
{
- IDirect3DSurface9 *sourceSurface = NULL;
- gl::Error error = source->getSurface(&sourceSurface);
- if (error.isError())
- {
- return error;
- }
+ IDirect3DSurface9 *sourceSurface = nullptr;
+ ANGLE_TRY(source->getSurface(&sourceSurface));
- IDirect3DSurface9 *destSurface = NULL;
- error = dest->getSurface(&destSurface);
- if (error.isError())
- {
- return error;
- }
+ IDirect3DSurface9 *destSurface = nullptr;
+ ANGLE_TRY(dest->getSurface(&destSurface));
- error = generateMip(destSurface, sourceSurface);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(generateMip(destSurface, sourceSurface));
dest->markDirty();
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source)
@@ -128,17 +123,17 @@ gl::Error Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface
HRESULT result;
- result = source->LockRect(&sourceLock, NULL, 0);
+ result = source->LockRect(&sourceLock, nullptr, 0);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock source surface for copy, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to lock source surface for copy, " << gl::FmtHR(result);
}
- result = dest->LockRect(&destLock, NULL, 0);
+ result = dest->LockRect(&destLock, nullptr, 0);
if (FAILED(result))
{
source->UnlockRect();
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock source surface for copy, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to lock source surface for copy, " << gl::FmtHR(result);
}
ASSERT(sourceLock.pBits && destLock.pBits);
@@ -161,7 +156,85 @@ gl::Error Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface
source->UnlockRect();
dest->UnlockRect();
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
+}
+
+// static
+gl::Error Image9::CopyImage(const gl::Context *context,
+ Image9 *dest,
+ Image9 *source,
+ const gl::Rectangle &sourceRect,
+ const gl::Offset &destOffset,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha)
+{
+ IDirect3DSurface9 *sourceSurface = nullptr;
+ ANGLE_TRY(source->getSurface(&sourceSurface));
+
+ IDirect3DSurface9 *destSurface = nullptr;
+ ANGLE_TRY(dest->getSurface(&destSurface));
+
+ D3DSURFACE_DESC destDesc;
+ HRESULT result = destSurface->GetDesc(&destDesc);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::OutOfMemory()
+ << "Failed to query the source surface description for mipmap generation, "
+ << gl::FmtHR(result);
+ }
+ const d3d9::D3DFormat &destD3DFormatInfo = d3d9::GetD3DFormatInfo(destDesc.Format);
+
+ D3DSURFACE_DESC sourceDesc;
+ result = sourceSurface->GetDesc(&sourceDesc);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::OutOfMemory()
+ << "Failed to query the destination surface description for mipmap generation, "
+ << gl::FmtHR(result);
+ }
+ const d3d9::D3DFormat &sourceD3DFormatInfo = d3d9::GetD3DFormatInfo(sourceDesc.Format);
+
+ D3DLOCKED_RECT sourceLocked = {0};
+ result = sourceSurface->LockRect(&sourceLocked, nullptr, D3DLOCK_READONLY);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::OutOfMemory() << "Failed to lock the source surface for CopyImage, "
+ << gl::FmtHR(result);
+ }
+
+ D3DLOCKED_RECT destLocked = {0};
+ result = destSurface->LockRect(&destLocked, nullptr, 0);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ sourceSurface->UnlockRect();
+ return gl::OutOfMemory() << "Failed to lock the destination surface for CopyImage, "
+ << gl::FmtHR(result);
+ }
+
+ const uint8_t *sourceData = reinterpret_cast<const uint8_t *>(sourceLocked.pBits) +
+ sourceRect.x * sourceD3DFormatInfo.pixelBytes +
+ sourceRect.y * sourceLocked.Pitch;
+ uint8_t *destData = reinterpret_cast<uint8_t *>(destLocked.pBits) +
+ destOffset.x * destD3DFormatInfo.pixelBytes +
+ destOffset.y * destLocked.Pitch;
+ ASSERT(sourceData && destData);
+
+ CopyImageCHROMIUM(sourceData, sourceLocked.Pitch, sourceD3DFormatInfo.pixelBytes,
+ sourceD3DFormatInfo.info().colorReadFunction, destData, destLocked.Pitch,
+ destD3DFormatInfo.pixelBytes, destD3DFormatInfo.info().colorWriteFunction,
+ gl::GetUnsizedFormat(dest->getInternalFormat()),
+ destD3DFormatInfo.info().componentType, sourceRect.width, sourceRect.height,
+ unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
+
+ destSurface->UnlockRect();
+ sourceSurface->UnlockRect();
+
+ return gl::NoError();
}
bool Image9::redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease)
@@ -189,7 +262,7 @@ bool Image9::redefine(GLenum target, GLenum internalformat, const gl::Extents &s
mRenderable = (d3d9FormatInfo.renderFormat != D3DFMT_UNKNOWN);
SafeRelease(mSurface);
- mDirty = (d3d9FormatInfo.dataInitializerFunction != NULL);
+ mDirty = (d3d9FormatInfo.dataInitializerFunction != nullptr);
return true;
}
@@ -201,11 +274,11 @@ gl::Error Image9::createSurface()
{
if (mSurface)
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
- IDirect3DTexture9 *newTexture = NULL;
- IDirect3DSurface9 *newSurface = NULL;
+ IDirect3DTexture9 *newTexture = nullptr;
+ IDirect3DSurface9 *newSurface = nullptr;
const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM;
const D3DFORMAT d3dFormat = getD3DFormat();
@@ -218,20 +291,20 @@ gl::Error Image9::createSurface()
IDirect3DDevice9 *device = mRenderer->getDevice();
- HRESULT result = device->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, 0, d3dFormat,
- poolToUse, &newTexture, NULL);
+ HRESULT result = device->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, 0,
+ d3dFormat, poolToUse, &newTexture, nullptr);
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create image surface, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to create image surface, " << gl::FmtHR(result);
}
newTexture->GetSurfaceLevel(levelToFetch, &newSurface);
SafeRelease(newTexture);
const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
- if (d3dFormatInfo.dataInitializerFunction != NULL)
+ if (d3dFormatInfo.dataInitializerFunction != nullptr)
{
RECT entireRect;
entireRect.left = 0;
@@ -244,7 +317,7 @@ gl::Error Image9::createSurface()
ASSERT(SUCCEEDED(result));
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock image surface, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to lock image surface, " << gl::FmtHR(result);
}
d3dFormatInfo.dataInitializerFunction(mWidth, mHeight, 1, reinterpret_cast<uint8_t*>(lockedRect.pBits),
@@ -254,7 +327,7 @@ gl::Error Image9::createSurface()
ASSERT(SUCCEEDED(result));
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock image surface, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to unlock image surface, " << gl::FmtHR(result);
}
}
}
@@ -263,7 +336,7 @@ gl::Error Image9::createSurface()
mDirty = false;
mD3DPool = poolToUse;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error Image9::lock(D3DLOCKED_RECT *lockedRect, const RECT &rect)
@@ -280,13 +353,13 @@ gl::Error Image9::lock(D3DLOCKED_RECT *lockedRect, const RECT &rect)
ASSERT(SUCCEEDED(result));
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock image surface, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to lock image surface, " << gl::FmtHR(result);
}
mDirty = true;
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
void Image9::unlock()
@@ -294,7 +367,6 @@ void Image9::unlock()
if (mSurface)
{
HRESULT result = mSurface->UnlockRect();
- UNUSED_ASSERTION_VARIABLE(result);
ASSERT(SUCCEEDED(result));
}
}
@@ -312,7 +384,9 @@ bool Image9::isDirty() const
{
// Make sure to that this image is marked as dirty even if the staging texture hasn't been created yet
// if initialization is required before use.
- return (mSurface || d3d9::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL) && mDirty;
+ return (mSurface ||
+ d3d9::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != nullptr) &&
+ mDirty;
}
gl::Error Image9::getSurface(IDirect3DSurface9 **outSurface)
@@ -324,14 +398,16 @@ gl::Error Image9::getSurface(IDirect3DSurface9 **outSurface)
}
*outSurface = mSurface;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Image9::setManagedSurface2D(TextureStorage *storage, int level)
+gl::Error Image9::setManagedSurface2D(const gl::Context *context,
+ TextureStorage *storage,
+ int level)
{
- IDirect3DSurface9 *surface = NULL;
+ IDirect3DSurface9 *surface = nullptr;
TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage);
- gl::Error error = storage9->getSurfaceLevel(GL_TEXTURE_2D, level, false, &surface);
+ gl::Error error = storage9->getSurfaceLevel(context, GL_TEXTURE_2D, level, false, &surface);
if (error.isError())
{
return error;
@@ -339,12 +415,15 @@ gl::Error Image9::setManagedSurface2D(TextureStorage *storage, int level)
return setManagedSurface(surface);
}
-gl::Error Image9::setManagedSurfaceCube(TextureStorage *storage, int face, int level)
+gl::Error Image9::setManagedSurfaceCube(const gl::Context *context,
+ TextureStorage *storage,
+ int face,
+ int level)
{
- IDirect3DSurface9 *surface = NULL;
+ IDirect3DSurface9 *surface = nullptr;
TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage);
- gl::Error error =
- storage9->getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false, &surface);
+ gl::Error error = storage9->getSurfaceLevel(context, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face,
+ level, false, &surface);
if (error.isError())
{
return error;
@@ -374,10 +453,13 @@ gl::Error Image9::setManagedSurface(IDirect3DSurface9 *surface)
mD3DPool = desc.Pool;
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Image9::copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region)
+gl::Error Image9::copyToStorage(const gl::Context *context,
+ TextureStorage *storage,
+ const gl::ImageIndex &index,
+ const gl::Box &region)
{
gl::Error error = createSurface();
if (error.isError())
@@ -387,11 +469,12 @@ gl::Error Image9::copyToStorage(TextureStorage *storage, const gl::ImageIndex &i
TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage);
- IDirect3DSurface9 *destSurface = NULL;
+ IDirect3DSurface9 *destSurface = nullptr;
if (index.type == GL_TEXTURE_2D)
{
- error = storage9->getSurfaceLevel(GL_TEXTURE_2D, index.mipIndex, true, &destSurface);
+ error =
+ storage9->getSurfaceLevel(context, GL_TEXTURE_2D, index.mipIndex, true, &destSurface);
if (error.isError())
{
return error;
@@ -400,7 +483,7 @@ gl::Error Image9::copyToStorage(TextureStorage *storage, const gl::ImageIndex &i
else
{
ASSERT(gl::IsCubeMapTextureTarget(index.type));
- error = storage9->getSurfaceLevel(index.type, index.mipIndex, true, &destSurface);
+ error = storage9->getSurfaceLevel(context, index.type, index.mipIndex, true, &destSurface);
if (error.isError())
{
return error;
@@ -417,7 +500,7 @@ gl::Error Image9::copyToSurface(IDirect3DSurface9 *destSurface, const gl::Box &a
ASSERT(area.width > 0 && area.height > 0 && area.depth == 1);
ASSERT(destSurface);
- IDirect3DSurface9 *sourceSurface = NULL;
+ IDirect3DSurface9 *sourceSurface = nullptr;
gl::Error error = getSurface(&sourceSurface);
if (error.isError())
{
@@ -442,19 +525,22 @@ gl::Error Image9::copyToSurface(IDirect3DSurface9 *destSurface, const gl::Box &a
sourceSurface->GetDesc(&desc);
IDirect3DSurface9 *surf = 0;
- HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL);
+ HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
+ D3DPOOL_SYSTEMMEM, &surf, nullptr);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Internal CreateOffscreenPlainSurface call failed, result: 0x%X.", result);
+ return gl::OutOfMemory()
+ << "Internal CreateOffscreenPlainSurface call failed, " << gl::FmtHR(result);
}
- copyLockableSurfaces(surf, sourceSurface);
+ auto err = copyLockableSurfaces(surf, sourceSurface);
result = device->UpdateSurface(surf, &rect, destSurface, &point);
SafeRelease(surf);
+ ANGLE_TRY(err);
ASSERT(SUCCEEDED(result));
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Internal UpdateSurface call failed, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Internal UpdateSurface call failed, " << gl::FmtHR(result);
}
}
else
@@ -464,27 +550,36 @@ gl::Error Image9::copyToSurface(IDirect3DSurface9 *destSurface, const gl::Box &a
ASSERT(SUCCEEDED(result));
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Internal UpdateSurface call failed, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Internal UpdateSurface call failed, " << gl::FmtHR(result);
}
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
// into the target pixel rectangle.
-gl::Error Image9::loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input)
+gl::Error Image9::loadData(const gl::Context *context,
+ const gl::Box &area,
+ const gl::PixelUnpackState &unpack,
+ GLenum type,
+ const void *input,
+ bool applySkipImages)
{
// 3D textures are not supported by the D3D9 backend.
ASSERT(area.z == 0 && area.depth == 1);
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
- GLsizei inputRowPitch = formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength);
- GLsizei inputSkipBytes = formatInfo.computeSkipPixels(inputRowPitch, 0, unpack.skipImages,
- unpack.skipRows, unpack.skipPixels);
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat);
+ GLuint inputRowPitch = 0;
+ ANGLE_TRY_RESULT(
+ formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength),
+ inputRowPitch);
+ ASSERT(!applySkipImages);
+ ASSERT(unpack.skipPixels == 0);
+ ASSERT(unpack.skipRows == 0);
const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
- ASSERT(d3dFormatInfo.loadFunction != NULL);
+ ASSERT(d3dFormatInfo.loadFunction != nullptr);
RECT lockRect =
{
@@ -500,31 +595,34 @@ gl::Error Image9::loadData(const gl::Box &area, const gl::PixelUnpackState &unpa
}
d3dFormatInfo.loadFunction(area.width, area.height, area.depth,
- reinterpret_cast<const uint8_t *>(input) + inputSkipBytes,
- inputRowPitch, 0, reinterpret_cast<uint8_t *>(locked.pBits),
- locked.Pitch, 0);
+ reinterpret_cast<const uint8_t *>(input), inputRowPitch, 0,
+ reinterpret_cast<uint8_t *>(locked.pBits), locked.Pitch, 0);
unlock();
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Image9::loadCompressedData(const gl::Box &area, const void *input)
+gl::Error Image9::loadCompressedData(const gl::Context *context,
+ const gl::Box &area,
+ const void *input)
{
// 3D textures are not supported by the D3D9 backend.
ASSERT(area.z == 0 && area.depth == 1);
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
- GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0);
- GLsizei inputDepthPitch =
- formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0, 0);
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat);
+ GLsizei inputRowPitch = 0;
+ ANGLE_TRY_RESULT(formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0), inputRowPitch);
+ GLsizei inputDepthPitch = 0;
+ ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(area.height, 0, inputDepthPitch),
+ inputDepthPitch);
const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
ASSERT(area.x % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockWidth == 0);
ASSERT(area.y % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockHeight == 0);
- ASSERT(d3d9FormatInfo.loadFunction != NULL);
+ ASSERT(d3d9FormatInfo.loadFunction != nullptr);
RECT lockRect =
{
@@ -545,7 +643,7 @@ gl::Error Image9::loadCompressedData(const gl::Box &area, const void *input)
unlock();
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures
@@ -565,16 +663,19 @@ gl::Error Image9::copyFromRTInternal(const gl::Offset &destOffset,
IDirect3DDevice9 *device = mRenderer->getDevice();
- IDirect3DSurface9 *renderTargetData = NULL;
+ IDirect3DSurface9 *renderTargetData = nullptr;
D3DSURFACE_DESC description;
surface->GetDesc(&description);
- HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL);
+ HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height,
+ description.Format, D3DPOOL_SYSTEMMEM,
+ &renderTargetData, nullptr);
if (FAILED(result))
{
SafeRelease(surface);
- return gl::Error(GL_OUT_OF_MEMORY, "Could not create matching destination surface, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Could not create matching destination surface, "
+ << gl::FmtHR(result);
}
result = device->GetRenderTargetData(surface, renderTargetData);
@@ -583,7 +684,8 @@ gl::Error Image9::copyFromRTInternal(const gl::Offset &destOffset,
{
SafeRelease(renderTargetData);
SafeRelease(surface);
- return gl::Error(GL_OUT_OF_MEMORY, "GetRenderTargetData unexpectedly failed, result: 0x%X.", result);
+ return gl::OutOfMemory() << "GetRenderTargetData unexpectedly failed, "
+ << gl::FmtHR(result);
}
int width = sourceArea.width;
@@ -599,7 +701,9 @@ gl::Error Image9::copyFromRTInternal(const gl::Offset &destOffset,
{
SafeRelease(renderTargetData);
SafeRelease(surface);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock the source surface (rectangle might be invalid), result: 0x%X.", result);
+ return gl::OutOfMemory()
+ << "Failed to lock the source surface (rectangle might be invalid), "
+ << gl::FmtHR(result);
}
D3DLOCKED_RECT destLock = {0};
@@ -776,13 +880,15 @@ gl::Error Image9::copyFromRTInternal(const gl::Offset &destOffset,
SafeRelease(surface);
mDirty = true;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Image9::copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source)
+gl::Error Image9::copyFromTexStorage(const gl::Context *context,
+ const gl::ImageIndex &imageIndex,
+ TextureStorage *source)
{
RenderTargetD3D *renderTarget = nullptr;
- gl::Error error = source->getRenderTarget(imageIndex, &renderTarget);
+ gl::Error error = source->getRenderTarget(context, imageIndex, &renderTarget);
if (error.isError())
{
return error;
@@ -792,15 +898,16 @@ gl::Error Image9::copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureSt
return copyFromRTInternal(gl::Offset(), sourceArea, renderTarget);
}
-gl::Error Image9::copyFromFramebuffer(const gl::Offset &destOffset,
+gl::Error Image9::copyFromFramebuffer(const gl::Context *context,
+ const gl::Offset &destOffset,
const gl::Rectangle &sourceArea,
const gl::Framebuffer *source)
{
const gl::FramebufferAttachment *srcAttachment = source->getReadColorbuffer();
ASSERT(srcAttachment);
- RenderTargetD3D *renderTarget = NULL;
- gl::Error error = srcAttachment->getRenderTarget(&renderTarget);
+ RenderTargetD3D *renderTarget = nullptr;
+ gl::Error error = srcAttachment->getRenderTarget(context, &renderTarget);
if (error.isError())
{
return error;
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h
index 91448cc849..01c60dc4fb 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h
@@ -26,27 +26,53 @@ class Image9 : public ImageD3D
{
public:
Image9(Renderer9 *renderer);
- ~Image9();
+ ~Image9() override;
static gl::Error generateMipmap(Image9 *dest, Image9 *source);
static gl::Error generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface);
static gl::Error copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source);
+ static gl::Error CopyImage(const gl::Context *context,
+ Image9 *dest,
+ Image9 *source,
+ const gl::Rectangle &sourceRect,
+ const gl::Offset &destOffset,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha);
bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) override;
D3DFORMAT getD3DFormat() const;
- virtual bool isDirty() const;
-
- virtual gl::Error setManagedSurface2D(TextureStorage *storage, int level);
- virtual gl::Error setManagedSurfaceCube(TextureStorage *storage, int face, int level);
- virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region);
-
- virtual gl::Error loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input);
- virtual gl::Error loadCompressedData(const gl::Box &area, const void *input);
-
- gl::Error copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source) override;
- gl::Error copyFromFramebuffer(const gl::Offset &destOffset,
+ bool isDirty() const override;
+
+ gl::Error setManagedSurface2D(const gl::Context *context,
+ TextureStorage *storage,
+ int level) override;
+ gl::Error setManagedSurfaceCube(const gl::Context *context,
+ TextureStorage *storage,
+ int face,
+ int level) override;
+ gl::Error copyToStorage(const gl::Context *context,
+ TextureStorage *storage,
+ const gl::ImageIndex &index,
+ const gl::Box &region) override;
+
+ gl::Error loadData(const gl::Context *context,
+ const gl::Box &area,
+ const gl::PixelUnpackState &unpack,
+ GLenum type,
+ const void *input,
+ bool applySkipImages) override;
+ gl::Error loadCompressedData(const gl::Context *context,
+ const gl::Box &area,
+ const void *input) override;
+
+ gl::Error copyFromTexStorage(const gl::Context *context,
+ const gl::ImageIndex &imageIndex,
+ TextureStorage *source) override;
+ gl::Error copyFromFramebuffer(const gl::Context *context,
+ const gl::Offset &destOffset,
const gl::Rectangle &sourceArea,
const gl::Framebuffer *source) override;
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp
index 97c7f72136..df86331766 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp
@@ -14,7 +14,7 @@ namespace rx
IndexBuffer9::IndexBuffer9(Renderer9 *const renderer) : mRenderer(renderer)
{
- mIndexBuffer = NULL;
+ mIndexBuffer = nullptr;
mBufferSize = 0;
mIndexType = 0;
mDynamic = false;
@@ -40,7 +40,7 @@ gl::Error IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bo
}
else if (indexType == GL_UNSIGNED_INT)
{
- ASSERT(mRenderer->getRendererExtensions().elementIndexUint);
+ ASSERT(mRenderer->getNativeExtensions().elementIndexUint);
format = D3DFMT_INDEX32;
}
else UNREACHABLE();
@@ -54,7 +54,8 @@ gl::Error IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bo
HRESULT result = mRenderer->createIndexBuffer(bufferSize, usageFlags, format, &mIndexBuffer);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal index buffer of size, %lu.", bufferSize);
+ return gl::OutOfMemory()
+ << "Failed to allocate internal index buffer of size " << bufferSize;
}
}
@@ -62,43 +63,43 @@ gl::Error IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bo
mIndexType = indexType;
mDynamic = dynamic;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error IndexBuffer9::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory)
{
if (!mIndexBuffer)
{
- return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
+ return gl::OutOfMemory() << "Internal index buffer is not initialized.";
}
DWORD lockFlags = mDynamic ? D3DLOCK_NOOVERWRITE : 0;
- void *mapPtr = NULL;
+ void *mapPtr = nullptr;
HRESULT result = mIndexBuffer->Lock(offset, size, &mapPtr, lockFlags);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal index buffer, HRESULT: 0x%08x.", result);
+ return gl::OutOfMemory() << "Failed to lock internal index buffer, " << gl::FmtHR(result);
}
*outMappedMemory = mapPtr;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error IndexBuffer9::unmapBuffer()
{
if (!mIndexBuffer)
{
- return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
+ return gl::OutOfMemory() << "Internal index buffer is not initialized.";
}
HRESULT result = mIndexBuffer->Unlock();
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal index buffer, HRESULT: 0x%08x.", result);
+ return gl::OutOfMemory() << "Failed to unlock internal index buffer, " << gl::FmtHR(result);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
GLenum IndexBuffer9::getIndexType() const
@@ -119,7 +120,7 @@ gl::Error IndexBuffer9::setSize(unsigned int bufferSize, GLenum indexType)
}
else
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
}
@@ -127,7 +128,7 @@ gl::Error IndexBuffer9::discard()
{
if (!mIndexBuffer)
{
- return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized.");
+ return gl::OutOfMemory() << "Internal index buffer is not initialized.";
}
void *dummy;
@@ -136,16 +137,16 @@ gl::Error IndexBuffer9::discard()
result = mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal index buffer, HRESULT: 0x%08x.", result);
+ return gl::OutOfMemory() << "Failed to lock internal index buffer, " << gl::FmtHR(result);
}
result = mIndexBuffer->Unlock();
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal index buffer, HRESULT: 0x%08x.", result);
+ return gl::OutOfMemory() << "Failed to unlock internal index buffer, " << gl::FmtHR(result);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
D3DFORMAT IndexBuffer9::getIndexFormat() const
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h
index ba03ba703f..5921d2a859 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h
@@ -19,18 +19,18 @@ class IndexBuffer9 : public IndexBuffer
{
public:
explicit IndexBuffer9(Renderer9 *const renderer);
- virtual ~IndexBuffer9();
+ ~IndexBuffer9() override;
- virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic);
+ gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) override;
- virtual gl::Error mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory);
- virtual gl::Error unmapBuffer();
+ gl::Error mapBuffer(unsigned int offset, unsigned int size, void **outMappedMemory) override;
+ gl::Error unmapBuffer() override;
- virtual GLenum getIndexType() const;
- virtual unsigned int getBufferSize() const;
- virtual gl::Error setSize(unsigned int bufferSize, GLenum indexType);
+ GLenum getIndexType() const override;
+ unsigned int getBufferSize() const override;
+ gl::Error setSize(unsigned int bufferSize, GLenum indexType) override;
- virtual gl::Error discard();
+ gl::Error discard() override;
D3DFORMAT getIndexFormat() const;
IDirect3DIndexBuffer9 *getBuffer() const;
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.cpp
new file mode 100644
index 0000000000..388b8aa168
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.cpp
@@ -0,0 +1,39 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// NativeWindow9.cpp: Defines NativeWindow9, a class for managing and
+// performing operations on an EGLNativeWindowType for the D3D9 renderer.
+
+#include "libANGLE/renderer/d3d/d3d9/NativeWindow9.h"
+
+namespace rx
+{
+NativeWindow9::NativeWindow9(EGLNativeWindowType window) : NativeWindowD3D(window)
+{
+}
+
+bool NativeWindow9::initialize()
+{
+ return true;
+}
+
+bool NativeWindow9::getClientRect(LPRECT rect) const
+{
+ return GetClientRect(getNativeWindow(), rect) == TRUE;
+}
+
+bool NativeWindow9::isIconic() const
+{
+ return IsIconic(getNativeWindow()) == TRUE;
+}
+
+// static
+bool NativeWindow9::IsValidNativeWindow(EGLNativeWindowType window)
+{
+ return IsWindow(window) == TRUE;
+}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.h
new file mode 100644
index 0000000000..a56b08dc81
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.h
@@ -0,0 +1,35 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// NativeWindow9.h: Defines NativeWindow9, a class for managing and
+// performing operations on an EGLNativeWindowType for the D3D9 renderer.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_NATIVEWINDOW9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_NATIVEWINDOW9_H_
+
+#include "common/debug.h"
+#include "common/platform.h"
+
+#include "libANGLE/renderer/d3d/NativeWindowD3D.h"
+
+namespace rx
+{
+
+class NativeWindow9 : public NativeWindowD3D
+{
+ public:
+ explicit NativeWindow9(EGLNativeWindowType window);
+
+ bool initialize() override;
+ bool getClientRect(LPRECT rect) const override;
+ bool isIconic() const override;
+
+ static bool IsValidNativeWindow(EGLNativeWindowType window);
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_NATIVEWINDOW9_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp
index c826abf81c..4ba053e6bd 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp
@@ -19,7 +19,7 @@ Query9::Query9(Renderer9 *renderer, GLenum type)
mResult(GL_FALSE),
mQueryFinished(false),
mRenderer(renderer),
- mQuery(NULL)
+ mQuery(nullptr)
{
}
@@ -30,23 +30,27 @@ Query9::~Query9()
gl::Error Query9::begin()
{
- if (mQuery == NULL)
+ D3DQUERYTYPE d3dQueryType = gl_d3d9::ConvertQueryType(getType());
+ if (mQuery == nullptr)
{
- HRESULT result = mRenderer->getDevice()->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery);
+ HRESULT result = mRenderer->getDevice()->CreateQuery(d3dQueryType, &mQuery);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Internal query creation failed, " << gl::FmtHR(result);
}
}
- HRESULT result = mQuery->Issue(D3DISSUE_BEGIN);
- ASSERT(SUCCEEDED(result));
- if (FAILED(result))
+ if (d3dQueryType != D3DQUERYTYPE_EVENT)
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to begin internal query, result: 0x%X.", result);
+ HRESULT result = mQuery->Issue(D3DISSUE_BEGIN);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ return gl::OutOfMemory() << "Failed to begin internal query, " << gl::FmtHR(result);
+ }
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error Query9::end()
@@ -57,19 +61,19 @@ gl::Error Query9::end()
ASSERT(SUCCEEDED(result));
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to end internal query, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to end internal query, " << gl::FmtHR(result);
}
mQueryFinished = false;
mResult = GL_FALSE;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error Query9::queryCounter()
{
UNIMPLEMENTED();
- return gl::Error(GL_INVALID_OPERATION, "Unimplemented");
+ return gl::InternalError() << "Unimplemented";
}
template <typename T>
@@ -91,7 +95,7 @@ gl::Error Query9::getResultBase(T *params)
ASSERT(mQueryFinished);
*params = static_cast<T>(mResult);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error Query9::getResult(GLint *params)
@@ -124,7 +128,7 @@ gl::Error Query9::isResultAvailable(bool *available)
*available = mQueryFinished;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error Query9::testQuery()
@@ -133,38 +137,52 @@ gl::Error Query9::testQuery()
{
ASSERT(mQuery);
- DWORD numPixels = 0;
-
- HRESULT hres = mQuery->GetData(&numPixels, sizeof(DWORD), D3DGETDATA_FLUSH);
- if (hres == S_OK)
+ HRESULT result = S_OK;
+ switch (getType())
{
- mQueryFinished = true;
+ case GL_ANY_SAMPLES_PASSED_EXT:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+ {
+ DWORD numPixels = 0;
+ result = mQuery->GetData(&numPixels, sizeof(numPixels), D3DGETDATA_FLUSH);
+ if (result == S_OK)
+ {
+ mQueryFinished = true;
+ mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE;
+ }
+ break;
+ }
- switch (getType())
+ case GL_COMMANDS_COMPLETED_CHROMIUM:
{
- case GL_ANY_SAMPLES_PASSED_EXT:
- case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
- mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE;
+ BOOL completed = FALSE;
+ result = mQuery->GetData(&completed, sizeof(completed), D3DGETDATA_FLUSH);
+ if (result == S_OK)
+ {
+ mQueryFinished = true;
+ mResult = (completed == TRUE) ? GL_TRUE : GL_FALSE;
+ }
break;
+ }
- default:
+ default:
UNREACHABLE();
break;
- }
}
- else if (d3d9::isDeviceLostError(hres))
+
+ if (d3d9::isDeviceLostError(result))
{
mRenderer->notifyDeviceLost();
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost.");
+ return gl::OutOfMemory() << "Failed to test get query result, device is lost.";
}
else if (mRenderer->testDeviceLost())
{
mRenderer->notifyDeviceLost();
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost.");
+ return gl::OutOfMemory() << "Failed to test get query result, device is lost.";
}
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h
index 9d17711a00..6c7c22f096 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h
@@ -19,16 +19,16 @@ class Query9 : public QueryImpl
{
public:
Query9(Renderer9 *renderer, GLenum type);
- virtual ~Query9();
-
- virtual gl::Error begin();
- virtual gl::Error end();
- virtual gl::Error queryCounter();
- virtual gl::Error getResult(GLint *params);
- virtual gl::Error getResult(GLuint *params);
- virtual gl::Error getResult(GLint64 *params);
- virtual gl::Error getResult(GLuint64 *params);
- virtual gl::Error isResultAvailable(bool *available);
+ ~Query9() override;
+
+ gl::Error begin() override;
+ gl::Error end() override;
+ gl::Error queryCounter() override;
+ gl::Error getResult(GLint *params) override;
+ gl::Error getResult(GLuint *params) override;
+ gl::Error getResult(GLint64 *params) override;
+ gl::Error getResult(GLuint64 *params) override;
+ gl::Error isResultAvailable(bool *available) override;
private:
gl::Error testQuery();
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp
index 419bff1f63..3e54c27f43 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp
@@ -130,7 +130,8 @@ GLsizei SurfaceRenderTarget9::getDepth() const
GLenum SurfaceRenderTarget9::getInternalFormat() const
{
- return (mDepth ? mSwapChain->GetDepthBufferInternalFormat() : mSwapChain->GetRenderTargetInternalFormat());
+ return (mDepth ? mSwapChain->getDepthBufferInternalFormat()
+ : mSwapChain->getRenderTargetInternalFormat());
}
GLsizei SurfaceRenderTarget9::getSamples() const
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h
index f19c54de7b..bb3b5a4ee4 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h
@@ -21,7 +21,7 @@ class RenderTarget9 : public RenderTargetD3D
{
public:
RenderTarget9() { }
- virtual ~RenderTarget9() { }
+ ~RenderTarget9() override {}
// Retrieve the texture that backs this render target, may be null for swap chain render
// targets.
virtual IDirect3DBaseTexture9 *getTexture() const = 0;
@@ -43,7 +43,7 @@ class TextureRenderTarget9 : public RenderTarget9
GLsizei height,
GLsizei depth,
GLsizei samples);
- virtual ~TextureRenderTarget9();
+ ~TextureRenderTarget9() override;
GLsizei getWidth() const override;
GLsizei getHeight() const override;
@@ -74,7 +74,7 @@ class SurfaceRenderTarget9 : public RenderTarget9
{
public:
SurfaceRenderTarget9(SwapChain9 *swapChain, bool depth);
- virtual ~SurfaceRenderTarget9();
+ ~SurfaceRenderTarget9() override;
GLsizei getWidth() const override;
GLsizei getHeight() const override;
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
index 6bb975b0e4..75c6298868 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
@@ -8,51 +8,51 @@
#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
-#include <sstream>
#include <EGL/eglext.h>
+#include <sstream>
#include "common/utilities.h"
-#include "libANGLE/angletypes.h"
#include "libANGLE/Buffer.h"
+#include "libANGLE/Context.h"
#include "libANGLE/Display.h"
-#include "libANGLE/features.h"
-#include "libANGLE/formatutils.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/Program.h"
#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/State.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/features.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/CompilerD3D.h"
+#include "libANGLE/renderer/d3d/DeviceD3D.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
#include "libANGLE/renderer/d3d/d3d9/Blit9.h"
#include "libANGLE/renderer/d3d/d3d9/Buffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Context9.h"
#include "libANGLE/renderer/d3d/d3d9/Fence9.h"
-#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"
#include "libANGLE/renderer/d3d/d3d9/Image9.h"
#include "libANGLE/renderer/d3d/d3d9/IndexBuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/NativeWindow9.h"
#include "libANGLE/renderer/d3d/d3d9/Query9.h"
-#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
#include "libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h"
#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
#include "libANGLE/renderer/d3d/d3d9/VertexArray9.h"
#include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h"
-#include "libANGLE/renderer/d3d/CompilerD3D.h"
-#include "libANGLE/renderer/d3d/DeviceD3D.h"
-#include "libANGLE/renderer/d3d/FramebufferD3D.h"
-#include "libANGLE/renderer/d3d/IndexDataManager.h"
-#include "libANGLE/renderer/d3d/ProgramD3D.h"
-#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
-#include "libANGLE/renderer/d3d/ShaderD3D.h"
-#include "libANGLE/renderer/d3d/SurfaceD3D.h"
-#include "libANGLE/renderer/d3d/TextureD3D.h"
-#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h"
-#include "libANGLE/State.h"
-#include "libANGLE/Surface.h"
-#include "libANGLE/Texture.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
#include "third_party/trace_event/trace_event.h"
-
-
#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3
#endif
@@ -69,69 +69,69 @@ namespace rx
enum
{
MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256,
- MAX_PIXEL_CONSTANT_VECTORS_SM2 = 32,
- MAX_PIXEL_CONSTANT_VECTORS_SM3 = 224,
- MAX_VARYING_VECTORS_SM2 = 8,
- MAX_VARYING_VECTORS_SM3 = 10,
+ MAX_PIXEL_CONSTANT_VECTORS_SM2 = 32,
+ MAX_PIXEL_CONSTANT_VECTORS_SM3 = 224,
+ MAX_VARYING_VECTORS_SM2 = 8,
+ MAX_VARYING_VECTORS_SM3 = 10,
MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4
};
Renderer9::Renderer9(egl::Display *display) : RendererD3D(display), mStateManager(this)
{
- mD3d9Module = NULL;
+ mD3d9Module = nullptr;
- mD3d9 = NULL;
- mD3d9Ex = NULL;
- mDevice = NULL;
- mDeviceEx = NULL;
- mDeviceWindow = NULL;
- mBlit = NULL;
+ mD3d9 = nullptr;
+ mD3d9Ex = nullptr;
+ mDevice = nullptr;
+ mDeviceEx = nullptr;
+ mDeviceWindow = nullptr;
+ mBlit = nullptr;
mAdapter = D3DADAPTER_DEFAULT;
const egl::AttributeMap &attributes = display->getAttributeMap();
- EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
- EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
+ EGLint requestedDeviceType = static_cast<EGLint>(attributes.get(
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE));
switch (requestedDeviceType)
{
- case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
- mDeviceType = D3DDEVTYPE_HAL;
- break;
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
+ mDeviceType = D3DDEVTYPE_HAL;
+ break;
- case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE:
- mDeviceType = D3DDEVTYPE_REF;
- break;
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE:
+ mDeviceType = D3DDEVTYPE_REF;
+ break;
- case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
- mDeviceType = D3DDEVTYPE_NULLREF;
- break;
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
+ mDeviceType = D3DDEVTYPE_NULLREF;
+ break;
- default:
- UNREACHABLE();
+ default:
+ UNREACHABLE();
}
- mMaskedClearSavedState = NULL;
+ mMaskedClearSavedState = nullptr;
- mVertexDataManager = NULL;
- mIndexDataManager = NULL;
- mLineLoopIB = NULL;
- mCountingIB = NULL;
+ mVertexDataManager = nullptr;
+ mIndexDataManager = nullptr;
+ mLineLoopIB = nullptr;
+ mCountingIB = nullptr;
mMaxNullColorbufferLRU = 0;
for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
{
mNullColorbufferCache[i].lruCount = 0;
- mNullColorbufferCache[i].width = 0;
- mNullColorbufferCache[i].height = 0;
- mNullColorbufferCache[i].buffer = NULL;
+ mNullColorbufferCache[i].width = 0;
+ mNullColorbufferCache[i].height = 0;
+ mNullColorbufferCache[i].buffer = nullptr;
}
- mAppliedVertexShader = NULL;
- mAppliedPixelShader = NULL;
+ mAppliedVertexShader = nullptr;
+ mAppliedPixelShader = nullptr;
mAppliedProgramSerial = 0;
- initializeDebugAnnotator();
+ gl::InitializeDebugAnnotations(&mAnnotator);
mEGLDevice = nullptr;
}
@@ -154,6 +154,10 @@ void Renderer9::release()
{
RendererD3D::cleanup();
+ gl::UninitializeDebugAnnotations();
+
+ mTranslatedAttribCache.clear();
+
releaseDeviceResources();
SafeDelete(mEGLDevice);
@@ -167,10 +171,10 @@ void Renderer9::release()
if (mDeviceWindow)
{
DestroyWindow(mDeviceWindow);
- mDeviceWindow = NULL;
+ mDeviceWindow = nullptr;
}
- mD3d9Module = NULL;
+ mD3d9Module = nullptr;
}
egl::Error Renderer9::initialize()
@@ -178,22 +182,25 @@ egl::Error Renderer9::initialize()
TRACE_EVENT0("gpu.angle", "GetModuleHandle_d3d9");
mD3d9Module = GetModuleHandle(TEXT("d3d9.dll"));
- if (mD3d9Module == NULL)
+ if (mD3d9Module == nullptr)
{
- return egl::Error(EGL_NOT_INITIALIZED, D3D9_INIT_MISSING_DEP, "No D3D9 module found.");
+ return egl::EglNotInitialized(D3D9_INIT_MISSING_DEP) << "No D3D9 module found.";
}
- typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**);
- Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
+ typedef HRESULT(WINAPI * Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex **);
+ Direct3DCreate9ExFunc Direct3DCreate9ExPtr =
+ reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
// Use Direct3D9Ex if available. Among other things, this version is less
// inclined to report a lost context, for example when the user switches
- // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available.
- if (ANGLE_D3D9EX == ANGLE_ENABLED && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
+ // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are
+ // available.
+ if (ANGLE_D3D9EX == ANGLE_ENABLED && Direct3DCreate9ExPtr &&
+ SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
{
TRACE_EVENT0("gpu.angle", "D3d9Ex_QueryInterface");
ASSERT(mD3d9Ex);
- mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
+ mD3d9Ex->QueryInterface(__uuidof(IDirect3D9), reinterpret_cast<void **>(&mD3d9));
ASSERT(mD3d9);
}
else
@@ -204,12 +211,13 @@ egl::Error Renderer9::initialize()
if (!mD3d9)
{
- return egl::Error(EGL_NOT_INITIALIZED, D3D9_INIT_MISSING_DEP, "Could not create D3D9 device.");
+ return egl::EglNotInitialized(D3D9_INIT_MISSING_DEP) << "Could not create D3D9 device.";
}
if (mDisplay->getNativeDisplayId() != nullptr)
{
- // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to
+ // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context
+ // corresponds to
}
HRESULT result;
@@ -226,13 +234,14 @@ egl::Error Renderer9::initialize()
}
else if (result == D3DERR_NOTAVAILABLE)
{
- Sleep(100); // Give the driver some time to initialize/recover
+ Sleep(100); // Give the driver some time to initialize/recover
}
- else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from
+ else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY,
+ // D3DERR_INVALIDDEVICE, or another error we can't recover
+ // from
{
- return egl::Error(EGL_NOT_INITIALIZED,
- D3D9_INIT_OTHER_ERROR,
- "Failed to get device caps: Error code 0x%x\n", result);
+ return egl::EglNotInitialized(D3D9_INIT_OTHER_ERROR)
+ << "Failed to get device caps, " << gl::FmtHR(result);
}
}
}
@@ -245,18 +254,17 @@ egl::Error Renderer9::initialize()
if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(minShaderModel, 0))
{
- return egl::Error(EGL_NOT_INITIALIZED,
- D3D9_INIT_UNSUPPORTED_VERSION,
- "Renderer does not support PS %u.%u.aborting!", minShaderModel, 0);
+ return egl::EglNotInitialized(D3D9_INIT_UNSUPPORTED_VERSION)
+ << "Renderer does not support PS " << minShaderModel << ".0, aborting!";
}
- // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported.
- // This is required by Texture2D::ensureRenderTarget.
+ // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture
+ // to a render target texture is not supported. This is required by
+ // Texture2D::ensureRenderTarget.
if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0)
{
- return egl::Error(EGL_NOT_INITIALIZED,
- D3D9_INIT_UNSUPPORTED_STRETCHRECT,
- "Renderer does not support StretctRect from textures.");
+ return egl::EglNotInitialized(D3D9_INIT_UNSUPPORTED_STRETCHRECT)
+ << "Renderer does not support StretctRect from textures.";
}
{
@@ -265,43 +273,52 @@ egl::Error Renderer9::initialize()
}
static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
- static const TCHAR className[] = TEXT("STATIC");
+ static const TCHAR className[] = TEXT("STATIC");
{
TRACE_EVENT0("gpu.angle", "CreateWindowEx");
- mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
+ mDeviceWindow =
+ CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1,
+ 1, HWND_MESSAGE, nullptr, GetModuleHandle(nullptr), nullptr);
}
D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
- DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES | D3DCREATE_MULTITHREADED;
+ DWORD behaviorFlags =
+ D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES | D3DCREATE_MULTITHREADED;
{
TRACE_EVENT0("gpu.angle", "D3d9_CreateDevice");
- result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
+ result = mD3d9->CreateDevice(
+ mAdapter, mDeviceType, mDeviceWindow,
+ behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE,
+ &presentParameters, &mDevice);
}
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST)
{
- return egl::Error(EGL_BAD_ALLOC, D3D9_INIT_OUT_OF_MEMORY,
- "CreateDevice failed: device lost of out of memory");
+ return egl::EglBadAlloc(D3D9_INIT_OUT_OF_MEMORY)
+ << "CreateDevice failed: device lost of out of memory";
}
if (FAILED(result))
{
TRACE_EVENT0("gpu.angle", "D3d9_CreateDevice2");
- result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);
+ result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow,
+ behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING,
+ &presentParameters, &mDevice);
if (FAILED(result))
{
- ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST);
- return egl::Error(EGL_BAD_ALLOC, D3D9_INIT_OUT_OF_MEMORY,
- "CreateDevice2 failed: device lost, not available, or of out of memory");
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY ||
+ result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST);
+ return egl::EglBadAlloc(D3D9_INIT_OUT_OF_MEMORY)
+ << "CreateDevice2 failed: device lost, not available, or of out of memory";
}
}
if (mD3d9Ex)
{
TRACE_EVENT0("gpu.angle", "mDevice_QueryInterface");
- result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**)&mDeviceEx);
+ result = mDevice->QueryInterface(__uuidof(IDirect3DDevice9Ex), (void **)&mDeviceEx);
ASSERT(SUCCEEDED(result));
}
@@ -318,18 +335,19 @@ egl::Error Renderer9::initialize()
// Only Direct3D 10 ready devices support all the necessary vertex texture formats.
// We test this using D3D9 by checking support for the R16F format.
mVertexTextureSupport = mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0) &&
- SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
- D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F));
+ SUCCEEDED(mD3d9->CheckDeviceFormat(
+ mAdapter, mDeviceType, currentDisplayMode.Format,
+ D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F));
- initializeDevice();
+ ANGLE_TRY(initializeDevice());
- return egl::Error(EGL_SUCCESS);
+ return egl::NoError();
}
// do any one-time device initialization
// NOTE: this is also needed after a device lost/reset
// to reset the scene status and ensure the default states are reset.
-void Renderer9::initializeDevice()
+egl::Error Renderer9::initializeDevice()
{
// Permanent non-default states
mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
@@ -337,14 +355,14 @@ void Renderer9::initializeDevice()
if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0))
{
- mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD&)mDeviceCaps.MaxPointSize);
+ mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD &)mDeviceCaps.MaxPointSize);
}
else
{
- mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000); // 1.0f
+ mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000); // 1.0f
}
- const gl::Caps &rendererCaps = getRendererCaps();
+ const gl::Caps &rendererCaps = getNativeCaps();
mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
mCurPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits);
@@ -358,50 +376,55 @@ void Renderer9::initializeDevice()
ASSERT(!mBlit);
mBlit = new Blit9(this);
- mBlit->initialize();
+ ANGLE_TRY(mBlit->initialize());
ASSERT(!mVertexDataManager && !mIndexDataManager);
mVertexDataManager = new VertexDataManager(this);
- mIndexDataManager = new IndexDataManager(this, getRendererClass());
+ mIndexDataManager = new IndexDataManager(this);
+
+ if (mVertexDataManager->initialize().isError())
+ {
+ return egl::EglBadAlloc() << "Error initializing VertexDataManager";
+ }
+
+ mTranslatedAttribCache.resize(getNativeCaps().maxVertexAttributes);
+
+ mStateManager.initialize();
- // TODO(jmadill): use context caps, and place in common D3D location
- mTranslatedAttribCache.resize(getRendererCaps().maxVertexAttributes);
+ return egl::NoError();
}
D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters()
{
D3DPRESENT_PARAMETERS presentParameters = {0};
- // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters.
+ // The default swap chain is never actually used. Surface will create a new swap chain with the
+ // proper parameters.
presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
- presentParameters.BackBufferCount = 1;
- presentParameters.BackBufferFormat = D3DFMT_UNKNOWN;
- presentParameters.BackBufferWidth = 1;
- presentParameters.BackBufferHeight = 1;
+ presentParameters.BackBufferCount = 1;
+ presentParameters.BackBufferFormat = D3DFMT_UNKNOWN;
+ presentParameters.BackBufferWidth = 1;
+ presentParameters.BackBufferHeight = 1;
presentParameters.EnableAutoDepthStencil = FALSE;
- presentParameters.Flags = 0;
- presentParameters.hDeviceWindow = mDeviceWindow;
- presentParameters.MultiSampleQuality = 0;
- presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
- presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
- presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
- presentParameters.Windowed = TRUE;
+ presentParameters.Flags = 0;
+ presentParameters.hDeviceWindow = mDeviceWindow;
+ presentParameters.MultiSampleQuality = 0;
+ presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
+ presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ presentParameters.Windowed = TRUE;
return presentParameters;
}
-egl::ConfigSet Renderer9::generateConfigs() const
+egl::ConfigSet Renderer9::generateConfigs()
{
- static const GLenum colorBufferFormats[] =
- {
- GL_BGR5_A1_ANGLEX,
- GL_BGRA8_EXT,
- GL_RGB565,
+ static const GLenum colorBufferFormats[] = {
+ GL_BGR5_A1_ANGLEX, GL_BGRA8_EXT, GL_RGB565,
};
- static const GLenum depthStencilBufferFormats[] =
- {
+ static const GLenum depthStencilBufferFormats[] = {
GL_NONE,
GL_DEPTH_COMPONENT32_OES,
GL_DEPTH24_STENCIL8_OES,
@@ -409,8 +432,8 @@ egl::ConfigSet Renderer9::generateConfigs() const
GL_DEPTH_COMPONENT16,
};
- const gl::Caps &rendererCaps = getRendererCaps();
- const gl::TextureCapsMap &rendererTextureCaps = getRendererTextureCaps();
+ const gl::Caps &rendererCaps = getNativeCaps();
+ const gl::TextureCapsMap &rendererTextureCaps = getNativeTextureCaps();
D3DDISPLAYMODE currentDisplayMode;
mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
@@ -449,56 +472,72 @@ egl::ConfigSet Renderer9::generateConfigs() const
for (size_t formatIndex = 0; formatIndex < ArraySize(colorBufferFormats); formatIndex++)
{
GLenum colorBufferInternalFormat = colorBufferFormats[formatIndex];
- const gl::TextureCaps &colorBufferFormatCaps = rendererTextureCaps.get(colorBufferInternalFormat);
+ const gl::TextureCaps &colorBufferFormatCaps =
+ rendererTextureCaps.get(colorBufferInternalFormat);
if (colorBufferFormatCaps.renderable)
{
- for (size_t depthStencilIndex = 0; depthStencilIndex < ArraySize(depthStencilBufferFormats); depthStencilIndex++)
+ for (size_t depthStencilIndex = 0;
+ depthStencilIndex < ArraySize(depthStencilBufferFormats); depthStencilIndex++)
{
- GLenum depthStencilBufferInternalFormat = depthStencilBufferFormats[depthStencilIndex];
- const gl::TextureCaps &depthStencilBufferFormatCaps = rendererTextureCaps.get(depthStencilBufferInternalFormat);
- if (depthStencilBufferFormatCaps.renderable || depthStencilBufferInternalFormat == GL_NONE)
+ GLenum depthStencilBufferInternalFormat =
+ depthStencilBufferFormats[depthStencilIndex];
+ const gl::TextureCaps &depthStencilBufferFormatCaps =
+ rendererTextureCaps.get(depthStencilBufferInternalFormat);
+ if (depthStencilBufferFormatCaps.renderable ||
+ depthStencilBufferInternalFormat == GL_NONE)
{
- const gl::InternalFormat &colorBufferFormatInfo = gl::GetInternalFormatInfo(colorBufferInternalFormat);
- const gl::InternalFormat &depthStencilBufferFormatInfo = gl::GetInternalFormatInfo(depthStencilBufferInternalFormat);
- const d3d9::TextureFormat &d3d9ColorBufferFormatInfo = d3d9::GetTextureFormatInfo(colorBufferInternalFormat);
+ const gl::InternalFormat &colorBufferFormatInfo =
+ gl::GetSizedInternalFormatInfo(colorBufferInternalFormat);
+ const gl::InternalFormat &depthStencilBufferFormatInfo =
+ gl::GetSizedInternalFormatInfo(depthStencilBufferInternalFormat);
+ const d3d9::TextureFormat &d3d9ColorBufferFormatInfo =
+ d3d9::GetTextureFormatInfo(colorBufferInternalFormat);
egl::Config config;
config.renderTargetFormat = colorBufferInternalFormat;
config.depthStencilFormat = depthStencilBufferInternalFormat;
- config.bufferSize = colorBufferFormatInfo.pixelBytes * 8;
- config.redSize = colorBufferFormatInfo.redBits;
- config.greenSize = colorBufferFormatInfo.greenBits;
- config.blueSize = colorBufferFormatInfo.blueBits;
- config.luminanceSize = colorBufferFormatInfo.luminanceBits;
- config.alphaSize = colorBufferFormatInfo.alphaBits;
- config.alphaMaskSize = 0;
- config.bindToTextureRGB = (colorBufferFormatInfo.format == GL_RGB);
- config.bindToTextureRGBA = (colorBufferFormatInfo.format == GL_RGBA || colorBufferFormatInfo.format == GL_BGRA_EXT);
+ config.bufferSize = colorBufferFormatInfo.pixelBytes * 8;
+ config.redSize = colorBufferFormatInfo.redBits;
+ config.greenSize = colorBufferFormatInfo.greenBits;
+ config.blueSize = colorBufferFormatInfo.blueBits;
+ config.luminanceSize = colorBufferFormatInfo.luminanceBits;
+ config.alphaSize = colorBufferFormatInfo.alphaBits;
+ config.alphaMaskSize = 0;
+ config.bindToTextureRGB = (colorBufferFormatInfo.format == GL_RGB);
+ config.bindToTextureRGBA = (colorBufferFormatInfo.format == GL_RGBA ||
+ colorBufferFormatInfo.format == GL_BGRA_EXT);
config.colorBufferType = EGL_RGB_BUFFER;
// Mark as slow if blits to the back-buffer won't be straight forward
- config.configCaveat = (currentDisplayMode.Format == d3d9ColorBufferFormatInfo.renderFormat) ? EGL_NONE : EGL_SLOW_CONFIG;
- config.configID = static_cast<EGLint>(configs.size() + 1);
- config.conformant = EGL_OPENGL_ES2_BIT;
- config.depthSize = depthStencilBufferFormatInfo.depthBits;
- config.level = 0;
+ config.configCaveat =
+ (currentDisplayMode.Format == d3d9ColorBufferFormatInfo.renderFormat)
+ ? EGL_NONE
+ : EGL_SLOW_CONFIG;
+ config.configID = static_cast<EGLint>(configs.size() + 1);
+ config.conformant = EGL_OPENGL_ES2_BIT;
+ config.depthSize = depthStencilBufferFormatInfo.depthBits;
+ config.level = 0;
config.matchNativePixmap = EGL_NONE;
- config.maxPBufferWidth = rendererCaps.max2DTextureSize;
- config.maxPBufferHeight = rendererCaps.max2DTextureSize;
- config.maxPBufferPixels = rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize;
- config.maxSwapInterval = maxSwapInterval;
- config.minSwapInterval = minSwapInterval;
+ config.maxPBufferWidth = rendererCaps.max2DTextureSize;
+ config.maxPBufferHeight = rendererCaps.max2DTextureSize;
+ config.maxPBufferPixels =
+ rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize;
+ config.maxSwapInterval = maxSwapInterval;
+ config.minSwapInterval = minSwapInterval;
config.nativeRenderable = EGL_FALSE;
- config.nativeVisualID = 0;
+ config.nativeVisualID = 0;
config.nativeVisualType = EGL_NONE;
- config.renderableType = EGL_OPENGL_ES2_BIT;
- config.sampleBuffers = 0; // FIXME: enumerate multi-sampling
- config.samples = 0;
- config.stencilSize = depthStencilBufferFormatInfo.stencilBits;
- config.surfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
- config.transparentType = EGL_NONE;
- config.transparentRedValue = 0;
+ config.renderableType = EGL_OPENGL_ES2_BIT;
+ config.sampleBuffers = 0; // FIXME: enumerate multi-sampling
+ config.samples = 0;
+ config.stencilSize = depthStencilBufferFormatInfo.stencilBits;
+ config.surfaceType =
+ EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
+ config.transparentType = EGL_NONE;
+ config.transparentRedValue = 0;
config.transparentGreenValue = 0;
- config.transparentBlueValue = 0;
+ config.transparentBlueValue = 0;
+ config.colorComponentType = gl_egl::GLComponentTypeToEGLColorComponentType(
+ colorBufferFormatInfo.componentType);
configs.add(config);
}
@@ -519,13 +558,12 @@ void Renderer9::generateDisplayExtensions(egl::DisplayExtensions *outExtensions)
outExtensions->d3dShareHandleClientBuffer = true;
outExtensions->surfaceD3DTexture2DShareHandle = true;
}
+ outExtensions->d3dTextureClientBuffer = true;
outExtensions->querySurfacePointer = true;
outExtensions->windowFixedSize = true;
outExtensions->postSubBuffer = true;
- outExtensions->createContext = true;
outExtensions->deviceQuery = true;
- outExtensions->createContextNoError = true;
outExtensions->image = true;
outExtensions->imageBase = true;
@@ -533,6 +571,14 @@ void Renderer9::generateDisplayExtensions(egl::DisplayExtensions *outExtensions)
outExtensions->glRenderbufferImage = true;
outExtensions->flexibleSurfaceCompatibility = true;
+
+ // Contexts are virtualized so textures can be shared globally
+ outExtensions->displayTextureShareGroup = true;
+
+ // D3D9 can be used without an output surface
+ outExtensions->surfacelessContext = true;
+
+ outExtensions->robustResourceInitialization = true;
}
void Renderer9::startScene()
@@ -540,7 +586,8 @@ void Renderer9::startScene()
if (!mSceneStarted)
{
long result = mDevice->BeginScene();
- if (SUCCEEDED(result)) {
+ if (SUCCEEDED(result))
+ {
// This is defensive checking against the device being
// lost at unexpected times.
mSceneStarted = true;
@@ -561,8 +608,8 @@ void Renderer9::endScene()
gl::Error Renderer9::flush()
{
- IDirect3DQuery9* query = NULL;
- gl::Error error = allocateEventQuery(&query);
+ IDirect3DQuery9 *query = nullptr;
+ gl::Error error = allocateEventQuery(&query);
if (error.isError())
{
return error;
@@ -572,11 +619,11 @@ gl::Error Renderer9::flush()
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to issue event query, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to issue event query, " << gl::FmtHR(result);
}
// Grab the query data once
- result = query->GetData(NULL, 0, D3DGETDATA_FLUSH);
+ result = query->GetData(nullptr, 0, D3DGETDATA_FLUSH);
freeEventQuery(query);
if (FAILED(result))
{
@@ -585,16 +632,16 @@ gl::Error Renderer9::flush()
notifyDeviceLost();
}
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to get event query data, " << gl::FmtHR(result);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error Renderer9::finish()
{
- IDirect3DQuery9* query = NULL;
- gl::Error error = allocateEventQuery(&query);
+ IDirect3DQuery9 *query = nullptr;
+ gl::Error error = allocateEventQuery(&query);
if (error.isError())
{
return error;
@@ -604,11 +651,11 @@ gl::Error Renderer9::finish()
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to issue event query, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to issue event query, " << gl::FmtHR(result);
}
// Grab the query data once
- result = query->GetData(NULL, 0, D3DGETDATA_FLUSH);
+ result = query->GetData(nullptr, 0, D3DGETDATA_FLUSH);
if (FAILED(result))
{
if (d3d9::isDeviceLostError(result))
@@ -617,7 +664,7 @@ gl::Error Renderer9::finish()
}
freeEventQuery(query);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to get event query data, " << gl::FmtHR(result);
}
// Loop until the query completes
@@ -626,7 +673,7 @@ gl::Error Renderer9::finish()
// Keep polling, but allow other threads to do something useful first
ScheduleYield();
- result = query->GetData(NULL, 0, D3DGETDATA_FLUSH);
+ result = query->GetData(nullptr, 0, D3DGETDATA_FLUSH);
// explicitly check for device loss
// some drivers seem to return S_FALSE even if the device is lost
@@ -644,34 +691,146 @@ gl::Error Renderer9::finish()
}
freeEventQuery(query);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to get event query data, " << gl::FmtHR(result);
}
-
}
freeEventQuery(query);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
+}
+
+bool Renderer9::isValidNativeWindow(EGLNativeWindowType window) const
+{
+ return NativeWindow9::IsValidNativeWindow(window);
+}
+
+NativeWindowD3D *Renderer9::createNativeWindow(EGLNativeWindowType window,
+ const egl::Config *,
+ const egl::AttributeMap &) const
+{
+ return new NativeWindow9(window);
}
-SwapChainD3D *Renderer9::createSwapChain(NativeWindow nativeWindow,
+SwapChainD3D *Renderer9::createSwapChain(NativeWindowD3D *nativeWindow,
HANDLE shareHandle,
+ IUnknown *d3dTexture,
GLenum backBufferFormat,
GLenum depthBufferFormat,
- EGLint orientation)
+ EGLint orientation,
+ EGLint samples)
{
- return new SwapChain9(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat,
- orientation);
+ return new SwapChain9(this, GetAs<NativeWindow9>(nativeWindow), shareHandle, d3dTexture,
+ backBufferFormat, depthBufferFormat, orientation);
}
-CompilerImpl *Renderer9::createCompiler()
+egl::Error Renderer9::getD3DTextureInfo(const egl::Config *config,
+ IUnknown *d3dTexture,
+ EGLint *width,
+ EGLint *height,
+ GLenum *fboFormat) const
{
- return new CompilerD3D(SH_HLSL_3_0_OUTPUT);
+ IDirect3DTexture9 *texture = nullptr;
+ if (FAILED(d3dTexture->QueryInterface(&texture)))
+ {
+ return egl::EglBadParameter() << "Client buffer is not a IDirect3DTexture9";
+ }
+
+ IDirect3DDevice9 *textureDevice = nullptr;
+ texture->GetDevice(&textureDevice);
+ if (textureDevice != mDevice)
+ {
+ SafeRelease(texture);
+ return egl::EglBadParameter() << "Texture's device does not match.";
+ }
+ SafeRelease(textureDevice);
+
+ D3DSURFACE_DESC desc;
+ texture->GetLevelDesc(0, &desc);
+ SafeRelease(texture);
+
+ if (width)
+ {
+ *width = static_cast<EGLint>(desc.Width);
+ }
+ if (height)
+ {
+ *height = static_cast<EGLint>(desc.Height);
+ }
+
+ // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
+ switch (desc.Format)
+ {
+ case D3DFMT_R8G8B8:
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_A16B16G16R16F:
+ case D3DFMT_A32B32G32R32F:
+ break;
+
+ default:
+ return egl::EglBadParameter()
+ << "Unknown client buffer texture format: " << desc.Format;
+ }
+
+ if (fboFormat)
+ {
+ const auto &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
+ ASSERT(d3dFormatInfo.info().id != angle::Format::ID::NONE);
+ *fboFormat = d3dFormatInfo.info().fboImplementationInternalFormat;
+ }
+
+ return egl::NoError();
+}
+
+egl::Error Renderer9::validateShareHandle(const egl::Config *config,
+ HANDLE shareHandle,
+ const egl::AttributeMap &attribs) const
+{
+ if (shareHandle == nullptr)
+ {
+ return egl::EglBadParameter() << "NULL share handle.";
+ }
+
+ EGLint width = attribs.getAsInt(EGL_WIDTH, 0);
+ EGLint height = attribs.getAsInt(EGL_HEIGHT, 0);
+ ASSERT(width != 0 && height != 0);
+
+ const d3d9::TextureFormat &backBufferd3dFormatInfo =
+ d3d9::GetTextureFormatInfo(config->renderTargetFormat);
+
+ IDirect3DTexture9 *texture = nullptr;
+ HRESULT result = mDevice->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET,
+ backBufferd3dFormatInfo.texFormat, D3DPOOL_DEFAULT,
+ &texture, &shareHandle);
+ if (FAILED(result))
+ {
+ return egl::EglBadParameter() << "Failed to open share handle, " << gl::FmtHR(result);
+ }
+
+ DWORD levelCount = texture->GetLevelCount();
+
+ D3DSURFACE_DESC desc;
+ texture->GetLevelDesc(0, &desc);
+ SafeRelease(texture);
+
+ if (levelCount != 1 || desc.Width != static_cast<UINT>(width) ||
+ desc.Height != static_cast<UINT>(height) ||
+ desc.Format != backBufferd3dFormatInfo.texFormat)
+ {
+ return egl::EglBadParameter() << "Invalid texture parameters in share handle texture.";
+ }
+
+ return egl::NoError();
+}
+
+ContextImpl *Renderer9::createContext(const gl::ContextState &state)
+{
+ return new Context9(state, this);
}
void *Renderer9::getD3DDevice()
{
- return reinterpret_cast<void*>(mDevice);
+ return reinterpret_cast<void *>(mDevice);
}
gl::Error Renderer9::allocateEventQuery(IDirect3DQuery9 **outQuery)
@@ -682,7 +841,7 @@ gl::Error Renderer9::allocateEventQuery(IDirect3DQuery9 **outQuery)
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate event query, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to allocate event query, " << gl::FmtHR(result);
}
}
else
@@ -691,10 +850,10 @@ gl::Error Renderer9::allocateEventQuery(IDirect3DQuery9 **outQuery)
mEventQueryPool.pop_back();
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-void Renderer9::freeEventQuery(IDirect3DQuery9* query)
+void Renderer9::freeEventQuery(IDirect3DQuery9 *query)
{
if (mEventQueryPool.size() > 1000)
{
@@ -706,20 +865,26 @@ void Renderer9::freeEventQuery(IDirect3DQuery9* query)
}
}
-gl::Error Renderer9::createVertexShader(const DWORD *function, size_t length, IDirect3DVertexShader9 **outShader)
+gl::Error Renderer9::createVertexShader(const DWORD *function,
+ size_t length,
+ IDirect3DVertexShader9 **outShader)
{
return mVertexShaderCache.create(function, length, outShader);
}
-gl::Error Renderer9::createPixelShader(const DWORD *function, size_t length, IDirect3DPixelShader9 **outShader)
+gl::Error Renderer9::createPixelShader(const DWORD *function,
+ size_t length,
+ IDirect3DPixelShader9 **outShader)
{
return mPixelShaderCache.create(function, length, outShader);
}
-HRESULT Renderer9::createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer)
+HRESULT Renderer9::createVertexBuffer(UINT Length,
+ DWORD Usage,
+ IDirect3DVertexBuffer9 **ppVertexBuffer)
{
D3DPOOL Pool = getBufferPool(Usage);
- return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, NULL);
+ return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, nullptr);
}
VertexBuffer *Renderer9::createVertexBuffer()
@@ -727,10 +892,13 @@ VertexBuffer *Renderer9::createVertexBuffer()
return new VertexBuffer9(this);
}
-HRESULT Renderer9::createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer)
+HRESULT Renderer9::createIndexBuffer(UINT Length,
+ DWORD Usage,
+ D3DFORMAT Format,
+ IDirect3DIndexBuffer9 **ppIndexBuffer)
{
D3DPOOL Pool = getBufferPool(Usage);
- return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, NULL);
+ return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, nullptr);
}
IndexBuffer *Renderer9::createIndexBuffer()
@@ -738,36 +906,13 @@ IndexBuffer *Renderer9::createIndexBuffer()
return new IndexBuffer9(this);
}
-BufferImpl *Renderer9::createBuffer()
-{
- return new Buffer9(this);
-}
-
-VertexArrayImpl *Renderer9::createVertexArray(const gl::VertexArray::Data &data)
-{
- return new VertexArray9(data);
-}
-
-QueryImpl *Renderer9::createQuery(GLenum type)
-{
- return new Query9(this, type);
-}
-
-FenceNVImpl *Renderer9::createFenceNV()
-{
- return new FenceNV9(this);
-}
-
-FenceSyncImpl *Renderer9::createFenceSync()
+StreamProducerImpl *Renderer9::createStreamProducerD3DTextureNV12(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs)
{
- // Renderer9 doesn't support ES 3.0 and its sync objects.
+ // Streams are not supported under D3D9
UNREACHABLE();
- return NULL;
-}
-
-TransformFeedbackImpl* Renderer9::createTransformFeedback()
-{
- return new TransformFeedbackD3D();
+ return nullptr;
}
bool Renderer9::supportsFastCopyBufferToTexture(GLenum internalFormat) const
@@ -776,22 +921,24 @@ bool Renderer9::supportsFastCopyBufferToTexture(GLenum internalFormat) const
return false;
}
-gl::Error Renderer9::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget,
- GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea)
+gl::Error Renderer9::fastCopyBufferToTexture(const gl::Context *context,
+ const gl::PixelUnpackState &unpack,
+ unsigned int offset,
+ RenderTargetD3D *destRenderTarget,
+ GLenum destinationFormat,
+ GLenum sourcePixelsType,
+ const gl::Box &destArea)
{
// Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3.
UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION);
-}
-
-gl::Error Renderer9::generateSwizzle(gl::Texture *texture)
-{
- // Swizzled textures are not available in ES2 or D3D9
- UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION);
+ return gl::InternalError();
}
-gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &samplerState)
+gl::Error Renderer9::setSamplerState(const gl::Context *context,
+ gl::SamplerType type,
+ int index,
+ gl::Texture *texture,
+ const gl::SamplerState &samplerState)
{
CurSamplerState &appliedSampler = (type == gl::SAMPLER_PIXEL) ? mCurPixelSamplerStates[index]
: mCurVertexSamplerStates[index];
@@ -800,11 +947,7 @@ gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, gl::Textur
TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
TextureStorage *storage = nullptr;
- gl::Error error = textureD3D->getNativeTexture(&storage);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(textureD3D->getNativeTexture(context, &storage));
// Storage should exist, texture should be complete
ASSERT(storage);
@@ -815,12 +958,16 @@ gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, gl::Textur
memcmp(&samplerState, &appliedSampler, sizeof(gl::SamplerState)) != 0)
{
int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
- int d3dSampler = index + d3dSamplerOffset;
+ int d3dSampler = index + d3dSamplerOffset;
- mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, gl_d3d9::ConvertTextureWrap(samplerState.wrapS));
- mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, gl_d3d9::ConvertTextureWrap(samplerState.wrapT));
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU,
+ gl_d3d9::ConvertTextureWrap(samplerState.wrapS));
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV,
+ gl_d3d9::ConvertTextureWrap(samplerState.wrapT));
- mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, gl_d3d9::ConvertMagFilter(samplerState.magFilter, samplerState.maxAnisotropy));
+ mDevice->SetSamplerState(
+ d3dSampler, D3DSAMP_MAGFILTER,
+ gl_d3d9::ConvertMagFilter(samplerState.magFilter, samplerState.maxAnisotropy));
D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
float lodBias;
@@ -830,52 +977,50 @@ gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, gl::Textur
mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, baseLevel);
mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPMAPLODBIAS, static_cast<DWORD>(lodBias));
- if (getRendererExtensions().textureFilterAnisotropic)
+ if (getNativeExtensions().textureFilterAnisotropic)
{
- mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy);
+ DWORD maxAnisotropy =
+ std::min(mDeviceCaps.MaxAnisotropy, static_cast<DWORD>(samplerState.maxAnisotropy));
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, maxAnisotropy);
}
}
- appliedSampler.forceSet = false;
+ appliedSampler.forceSet = false;
appliedSampler.samplerState = samplerState;
- appliedSampler.baseLevel = baseLevel;
+ appliedSampler.baseLevel = baseLevel;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
+gl::Error Renderer9::setTexture(const gl::Context *context,
+ gl::SamplerType type,
+ int index,
+ gl::Texture *texture)
{
- int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
- int d3dSampler = index + d3dSamplerOffset;
- IDirect3DBaseTexture9 *d3dTexture = NULL;
- bool forceSetTexture = false;
+ int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
+ int d3dSampler = index + d3dSamplerOffset;
+ IDirect3DBaseTexture9 *d3dTexture = nullptr;
+ bool forceSetTexture = false;
- std::vector<uintptr_t> &appliedTextures = (type == gl::SAMPLER_PIXEL) ? mCurPixelTextures : mCurVertexTextures;
+ std::vector<uintptr_t> &appliedTextures =
+ (type == gl::SAMPLER_PIXEL) ? mCurPixelTextures : mCurVertexTextures;
if (texture)
{
TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture);
TextureStorage *texStorage = nullptr;
- gl::Error error = textureImpl->getNativeTexture(&texStorage);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage));
// Texture should be complete and have a storage
ASSERT(texStorage);
TextureStorage9 *storage9 = GetAs<TextureStorage9>(texStorage);
- error = storage9->getBaseTexture(&d3dTexture);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(storage9->getBaseTexture(context, &d3dTexture));
// If we get NULL back from getBaseTexture here, something went wrong
// in the texture class and we're unexpectedly missing the d3d texture
- ASSERT(d3dTexture != NULL);
+ ASSERT(d3dTexture != nullptr);
forceSetTexture = textureImpl->hasDirtyImages();
textureImpl->resetDirty();
@@ -888,60 +1033,50 @@ gl::Error Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *te
appliedTextures[index] = reinterpret_cast<uintptr_t>(d3dTexture);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Renderer9::setUniformBuffers(const gl::Data &/*data*/,
- const std::vector<GLint> &/*vertexUniformBuffers*/,
- const std::vector<GLint> &/*fragmentUniformBuffers*/)
+gl::Error Renderer9::updateState(const gl::Context *context, GLenum drawMode)
{
- // No effect in ES2/D3D9
- return gl::Error(GL_NO_ERROR);
-}
+ const auto &glState = context->getGLState();
-void Renderer9::syncState(const gl::State &state, const gl::State::DirtyBits &bitmask)
-{
- mStateManager.syncState(state, bitmask);
-}
-
-gl::Error Renderer9::updateState(const gl::Data &data, GLenum drawMode)
-{
// Applies the render target surface, depth stencil surface, viewport rectangle and
// scissor rectangle to the renderer
- const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer();
- ASSERT(framebufferObject && framebufferObject->checkStatus(data) == GL_FRAMEBUFFER_COMPLETE);
+ gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
+ ASSERT(framebuffer && !framebuffer->hasAnyDirtyBit() && framebuffer->cachedComplete());
- gl::Error error = applyRenderTarget(framebufferObject);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(applyRenderTarget(context, framebuffer));
// Setting viewport state
- setViewport(data.caps, data.state->getViewport(), data.state->getNearPlane(),
- data.state->getFarPlane(), drawMode, data.state->getRasterizerState().frontFace,
- false);
+ setViewport(glState.getViewport(), glState.getNearPlane(), glState.getFarPlane(), drawMode,
+ glState.getRasterizerState().frontFace, false);
// Setting scissors state
- setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled());
+ setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());
// Setting blend, depth stencil, and rasterizer states
- int samples = framebufferObject->getSamples(data);
- gl::RasterizerState rasterizer = data.state->getRasterizerState();
+ // Since framebuffer->getSamples will return the original samples which may be different with
+ // the sample counts that we set in render target view, here we use renderTarget->getSamples to
+ // get the actual samples.
+ GLsizei samples = 0;
+ const gl::FramebufferAttachment *firstColorAttachment = framebuffer->getFirstColorbuffer();
+ if (firstColorAttachment)
+ {
+ ASSERT(firstColorAttachment->isAttached());
+ RenderTarget9 *renderTarget = nullptr;
+ ANGLE_TRY(firstColorAttachment->getRenderTarget(context, &renderTarget));
+ samples = renderTarget->getSamples();
+ }
+ gl::RasterizerState rasterizer = glState.getRasterizerState();
rasterizer.pointDrawMode = (drawMode == GL_POINTS);
rasterizer.multiSample = (samples != 0);
- unsigned int mask = GetBlendSampleMask(data, samples);
- error = setBlendDepthRasterStates(data, mask);
-
- if (error.isError())
- {
- return error;
- }
+ unsigned int mask = GetBlendSampleMask(glState, samples);
+ ANGLE_TRY(setBlendDepthRasterStates(context, mask));
mStateManager.resetDirtyBits();
- return error;
+ return gl::NoError();
}
void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
@@ -949,71 +1084,85 @@ void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
mStateManager.setScissorState(scissor, enabled);
}
-gl::Error Renderer9::setBlendDepthRasterStates(const gl::Data &glData, GLenum drawMode)
+gl::Error Renderer9::setBlendDepthRasterStates(const gl::Context *context, GLenum drawMode)
{
- int samples = glData.state->getDrawFramebuffer()->getSamples(glData);
- gl::RasterizerState rasterizer = glData.state->getRasterizerState();
+ const auto &glState = context->getGLState();
+ gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
+ ASSERT(!drawFramebuffer->hasAnyDirtyBit());
+ // Since framebuffer->getSamples will return the original samples which may be different with
+ // the sample counts that we set in render target view, here we use renderTarget->getSamples to
+ // get the actual samples.
+ GLsizei samples = 0;
+ const gl::FramebufferAttachment *firstColorAttachment = drawFramebuffer->getFirstColorbuffer();
+ if (firstColorAttachment)
+ {
+ ASSERT(firstColorAttachment->isAttached());
+ RenderTarget9 *renderTarget = nullptr;
+ ANGLE_TRY(firstColorAttachment->getRenderTarget(context, &renderTarget));
+ samples = renderTarget->getSamples();
+ }
+ gl::RasterizerState rasterizer = glState.getRasterizerState();
rasterizer.pointDrawMode = (drawMode == GL_POINTS);
rasterizer.multiSample = (samples != 0);
- unsigned int mask = GetBlendSampleMask(glData, samples);
- return mStateManager.setBlendDepthRasterStates(*glData.state, mask);
+ unsigned int mask = GetBlendSampleMask(glState, samples);
+ return mStateManager.setBlendDepthRasterStates(glState, mask);
}
-void Renderer9::setViewport(const gl::Caps *caps,
- const gl::Rectangle &viewport,
+void Renderer9::setViewport(const gl::Rectangle &viewport,
float zNear,
float zFar,
GLenum drawMode,
GLenum frontFace,
bool ignoreViewport)
{
- mStateManager.setViewportState(caps, viewport, zNear, zFar, drawMode, frontFace,
- ignoreViewport);
+ mStateManager.setViewportState(viewport, zNear, zFar, drawMode, frontFace, ignoreViewport);
}
bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize)
{
switch (mode)
{
- case GL_POINTS:
- mPrimitiveType = D3DPT_POINTLIST;
- mPrimitiveCount = count;
- break;
- case GL_LINES:
- mPrimitiveType = D3DPT_LINELIST;
- mPrimitiveCount = count / 2;
- break;
- case GL_LINE_LOOP:
- mPrimitiveType = D3DPT_LINESTRIP;
- mPrimitiveCount = count - 1; // D3D doesn't support line loops, so we draw the last line separately
- break;
- case GL_LINE_STRIP:
- mPrimitiveType = D3DPT_LINESTRIP;
- mPrimitiveCount = count - 1;
- break;
- case GL_TRIANGLES:
- mPrimitiveType = D3DPT_TRIANGLELIST;
- mPrimitiveCount = count / 3;
- break;
- case GL_TRIANGLE_STRIP:
- mPrimitiveType = D3DPT_TRIANGLESTRIP;
- mPrimitiveCount = count - 2;
- break;
- case GL_TRIANGLE_FAN:
- mPrimitiveType = D3DPT_TRIANGLEFAN;
- mPrimitiveCount = count - 2;
- break;
- default:
- UNREACHABLE();
- return false;
+ case GL_POINTS:
+ mPrimitiveType = D3DPT_POINTLIST;
+ mPrimitiveCount = count;
+ break;
+ case GL_LINES:
+ mPrimitiveType = D3DPT_LINELIST;
+ mPrimitiveCount = count / 2;
+ break;
+ case GL_LINE_LOOP:
+ mPrimitiveType = D3DPT_LINESTRIP;
+ mPrimitiveCount =
+ count - 1; // D3D doesn't support line loops, so we draw the last line separately
+ break;
+ case GL_LINE_STRIP:
+ mPrimitiveType = D3DPT_LINESTRIP;
+ mPrimitiveCount = count - 1;
+ break;
+ case GL_TRIANGLES:
+ mPrimitiveType = D3DPT_TRIANGLELIST;
+ mPrimitiveCount = count / 3;
+ break;
+ case GL_TRIANGLE_STRIP:
+ mPrimitiveType = D3DPT_TRIANGLESTRIP;
+ mPrimitiveCount = count - 2;
+ break;
+ case GL_TRIANGLE_FAN:
+ mPrimitiveType = D3DPT_TRIANGLEFAN;
+ mPrimitiveCount = count - 2;
+ break;
+ default:
+ UNREACHABLE();
+ return false;
}
return mPrimitiveCount > 0;
}
-
-gl::Error Renderer9::getNullColorbuffer(const gl::FramebufferAttachment *depthbuffer, const gl::FramebufferAttachment **outColorBuffer)
+gl::Error Renderer9::getNullColorbuffer(const gl::Context *context,
+ const gl::FramebufferAttachment *depthbuffer,
+ const gl::FramebufferAttachment **outColorBuffer)
{
ASSERT(depthbuffer);
@@ -1022,25 +1171,28 @@ gl::Error Renderer9::getNullColorbuffer(const gl::FramebufferAttachment *depthbu
// search cached nullcolorbuffers
for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
{
- if (mNullColorbufferCache[i].buffer != NULL &&
+ if (mNullColorbufferCache[i].buffer != nullptr &&
mNullColorbufferCache[i].width == size.width &&
mNullColorbufferCache[i].height == size.height)
{
mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU;
- *outColorBuffer = mNullColorbufferCache[i].buffer;
- return gl::Error(GL_NO_ERROR);
+ *outColorBuffer = mNullColorbufferCache[i].buffer;
+ return gl::NoError();
}
}
- gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(createRenderbuffer(), 0);
- gl::Error error = nullRenderbuffer->setStorage(GL_NONE, size.width, size.height);
+ auto *implFactory = context->getImplementation();
+
+ gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(implFactory->createRenderbuffer(), 0);
+ gl::Error error = nullRenderbuffer->setStorage(context, GL_NONE, size.width, size.height);
if (error.isError())
{
SafeDelete(nullRenderbuffer);
return error;
}
- gl::FramebufferAttachment *nullbuffer = new gl::FramebufferAttachment(GL_RENDERBUFFER, GL_NONE, gl::ImageIndex::MakeInvalid(), nullRenderbuffer);
+ gl::FramebufferAttachment *nullbuffer = new gl::FramebufferAttachment(
+ context, GL_RENDERBUFFER, GL_NONE, gl::ImageIndex::MakeInvalid(), nullRenderbuffer);
// add nullbuffer to the cache
NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0];
@@ -1053,46 +1205,38 @@ gl::Error Renderer9::getNullColorbuffer(const gl::FramebufferAttachment *depthbu
}
delete oldest->buffer;
- oldest->buffer = nullbuffer;
+ oldest->buffer = nullbuffer;
oldest->lruCount = ++mMaxNullColorbufferLRU;
oldest->width = size.width;
oldest->height = size.height;
*outColorBuffer = nullbuffer;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Renderer9::applyRenderTarget(const gl::FramebufferAttachment *colorAttachment,
+gl::Error Renderer9::applyRenderTarget(const gl::Context *context,
+ const gl::FramebufferAttachment *colorAttachment,
const gl::FramebufferAttachment *depthStencilAttachment)
{
const gl::FramebufferAttachment *renderAttachment = colorAttachment;
- gl::Error error(GL_NO_ERROR);
// if there is no color attachment we must synthesize a NULL colorattachment
// to keep the D3D runtime happy. This should only be possible if depth texturing.
if (renderAttachment == nullptr)
{
- error = getNullColorbuffer(depthStencilAttachment, &renderAttachment);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(getNullColorbuffer(context, depthStencilAttachment, &renderAttachment));
}
ASSERT(renderAttachment != nullptr);
- size_t renderTargetWidth = 0;
- size_t renderTargetHeight = 0;
+ size_t renderTargetWidth = 0;
+ size_t renderTargetHeight = 0;
D3DFORMAT renderTargetFormat = D3DFMT_UNKNOWN;
RenderTarget9 *renderTarget = nullptr;
- error = renderAttachment->getRenderTarget(&renderTarget);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(renderAttachment->getRenderTarget(context, &renderTarget));
ASSERT(renderTarget);
- bool renderTargetChanged = false;
+ bool renderTargetChanged = false;
unsigned int renderTargetSerial = renderTarget->getSerial();
if (renderTargetSerial != mAppliedRenderTargetSerial)
{
@@ -1103,24 +1247,20 @@ gl::Error Renderer9::applyRenderTarget(const gl::FramebufferAttachment *colorAtt
mDevice->SetRenderTarget(0, renderTargetSurface);
SafeRelease(renderTargetSurface);
- renderTargetWidth = renderTarget->getWidth();
+ renderTargetWidth = renderTarget->getWidth();
renderTargetHeight = renderTarget->getHeight();
renderTargetFormat = renderTarget->getD3DFormat();
mAppliedRenderTargetSerial = renderTargetSerial;
- renderTargetChanged = true;
+ renderTargetChanged = true;
}
RenderTarget9 *depthStencilRenderTarget = nullptr;
- unsigned int depthStencilSerial = 0;
+ unsigned int depthStencilSerial = 0;
if (depthStencilAttachment != nullptr)
{
- error = depthStencilAttachment->getRenderTarget(&depthStencilRenderTarget);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(depthStencilAttachment->getRenderTarget(context, &depthStencilRenderTarget));
ASSERT(depthStencilRenderTarget);
depthStencilSerial = depthStencilRenderTarget->getSerial();
@@ -1128,7 +1268,7 @@ gl::Error Renderer9::applyRenderTarget(const gl::FramebufferAttachment *colorAtt
if (depthStencilSerial != mAppliedDepthStencilSerial || !mDepthStencilInitialized)
{
- unsigned int depthSize = 0;
+ unsigned int depthSize = 0;
unsigned int stencilSize = 0;
// Apply the depth stencil on the device
@@ -1140,19 +1280,19 @@ gl::Error Renderer9::applyRenderTarget(const gl::FramebufferAttachment *colorAtt
mDevice->SetDepthStencilSurface(depthStencilSurface);
SafeRelease(depthStencilSurface);
- depthSize = depthStencilAttachment->getDepthSize();
+ depthSize = depthStencilAttachment->getDepthSize();
stencilSize = depthStencilAttachment->getStencilSize();
}
else
{
- mDevice->SetDepthStencilSurface(NULL);
+ mDevice->SetDepthStencilSurface(nullptr);
}
mStateManager.updateDepthSizeIfChanged(mDepthStencilInitialized, depthSize);
mStateManager.updateStencilSizeIfChanged(mDepthStencilInitialized, stencilSize);
mAppliedDepthStencilSerial = depthStencilSerial;
- mDepthStencilInitialized = true;
+ mDepthStencilInitialized = true;
}
if (renderTargetChanged || !mRenderTargetDescInitialized)
@@ -1163,83 +1303,84 @@ gl::Error Renderer9::applyRenderTarget(const gl::FramebufferAttachment *colorAtt
mRenderTargetDescInitialized = true;
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Renderer9::applyRenderTarget(const gl::Framebuffer *framebuffer)
+gl::Error Renderer9::applyRenderTarget(const gl::Context *context,
+ const gl::Framebuffer *framebuffer)
{
- return applyRenderTarget(framebuffer->getColorbuffer(0), framebuffer->getDepthOrStencilbuffer());
+ return applyRenderTarget(context, framebuffer->getColorbuffer(0),
+ framebuffer->getDepthOrStencilbuffer());
}
-gl::Error Renderer9::applyVertexBuffer(const gl::State &state,
+gl::Error Renderer9::applyVertexBuffer(const gl::Context *context,
GLenum mode,
GLint first,
GLsizei count,
GLsizei instances,
TranslatedIndexData * /*indexInfo*/)
{
- gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, &mTranslatedAttribCache, instances);
+ const gl::State &state = context->getGLState();
+ gl::Error error = mVertexDataManager->prepareVertexData(context, first, count,
+ &mTranslatedAttribCache, instances);
if (error.isError())
{
return error;
}
- return mVertexDeclarationCache.applyDeclaration(mDevice, mTranslatedAttribCache, state.getProgram(), instances, &mRepeatDraw);
+ return mVertexDeclarationCache.applyDeclaration(
+ mDevice, mTranslatedAttribCache, state.getProgram(), first, instances, &mRepeatDraw);
}
// Applies the indices and element array bindings to the Direct3D 9 device
-gl::Error Renderer9::applyIndexBuffer(const gl::Data &data,
- const GLvoid *indices,
+gl::Error Renderer9::applyIndexBuffer(const gl::Context *context,
+ const void *indices,
GLsizei count,
GLenum mode,
GLenum type,
TranslatedIndexData *indexInfo)
{
- gl::VertexArray *vao = data.state->getVertexArray();
+ gl::VertexArray *vao = context->getGLState().getVertexArray();
gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
- gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices,
- indexInfo, false);
- if (error.isError())
- {
- return error;
- }
+ const auto &lazyIndexRange = context->getParams<gl::HasIndexRange>();
+
+ GLenum dstType = GetIndexTranslationDestType(type, lazyIndexRange, false);
+
+ ANGLE_TRY(mIndexDataManager->prepareIndexData(context, type, dstType, count, elementArrayBuffer,
+ indices, indexInfo));
// Directly binding the storage buffer is not supported for d3d9
- ASSERT(indexInfo->storage == NULL);
+ ASSERT(indexInfo->storage == nullptr);
if (indexInfo->serial != mAppliedIBSerial)
{
- IndexBuffer9* indexBuffer = GetAs<IndexBuffer9>(indexInfo->indexBuffer);
+ IndexBuffer9 *indexBuffer = GetAs<IndexBuffer9>(indexInfo->indexBuffer);
mDevice->SetIndices(indexBuffer->getBuffer());
mAppliedIBSerial = indexInfo->serial;
}
- return gl::Error(GL_NO_ERROR);
-}
-
-void Renderer9::applyTransformFeedbackBuffers(const gl::State& state)
-{
- ASSERT(!state.isTransformFeedbackActiveUnpaused());
+ return gl::NoError();
}
-gl::Error Renderer9::drawArraysImpl(const gl::Data &data,
+gl::Error Renderer9::drawArraysImpl(const gl::Context *context,
GLenum mode,
+ GLint startVertex,
GLsizei count,
GLsizei instances)
{
- ASSERT(!data.state->isTransformFeedbackActiveUnpaused());
+ ASSERT(!context->getGLState().isTransformFeedbackActiveUnpaused());
startScene();
if (mode == GL_LINE_LOOP)
{
- return drawLineLoop(count, GL_NONE, NULL, 0, NULL);
+ return drawLineLoop(context, count, GL_NONE, nullptr, 0, nullptr);
}
else if (instances > 0)
{
- StaticIndexBufferInterface *countingIB = NULL;
- gl::Error error = getCountingIB(count, &countingIB);
+ StaticIndexBufferInterface *countingIB = nullptr;
+ gl::Error error = getCountingIB(count, &countingIB);
if (error.isError())
{
return error;
@@ -1258,60 +1399,73 @@ gl::Error Renderer9::drawArraysImpl(const gl::Data &data,
mDevice->DrawIndexedPrimitive(mPrimitiveType, 0, 0, count, 0, mPrimitiveCount);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
- else // Regular case
+ else // Regular case
{
mDevice->DrawPrimitive(mPrimitiveType, 0, mPrimitiveCount);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
}
-gl::Error Renderer9::drawElementsImpl(const gl::Data &data,
- const TranslatedIndexData &indexInfo,
+gl::Error Renderer9::drawElementsImpl(const gl::Context *context,
GLenum mode,
GLsizei count,
GLenum type,
- const GLvoid *indices,
- GLsizei /*instances*/)
+ const void *indices,
+ GLsizei instances)
{
+ TranslatedIndexData indexInfo;
+
+ ANGLE_TRY(applyIndexBuffer(context, indices, count, mode, type, &indexInfo));
+
+ const auto &lazyIndexRange = context->getParams<gl::HasIndexRange>();
+ const gl::IndexRange &indexRange = lazyIndexRange.getIndexRange().value();
+ size_t vertexCount = indexRange.vertexCount();
+ ANGLE_TRY(applyVertexBuffer(context, mode, static_cast<GLsizei>(indexRange.start),
+ static_cast<GLsizei>(vertexCount), instances, &indexInfo));
+
startScene();
- int minIndex = static_cast<int>(indexInfo.indexRange.start);
+ int minIndex = static_cast<int>(indexRange.start);
- gl::VertexArray *vao = data.state->getVertexArray();
+ gl::VertexArray *vao = context->getGLState().getVertexArray();
gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
if (mode == GL_POINTS)
{
- return drawIndexedPoints(count, type, indices, minIndex, elementArrayBuffer);
+ return drawIndexedPoints(context, count, type, indices, minIndex, elementArrayBuffer);
}
else if (mode == GL_LINE_LOOP)
{
- return drawLineLoop(count, type, indices, minIndex, elementArrayBuffer);
+ return drawLineLoop(context, count, type, indices, minIndex, elementArrayBuffer);
}
else
{
- size_t vertexCount = indexInfo.indexRange.vertexCount();
for (int i = 0; i < mRepeatDraw; i++)
{
mDevice->DrawIndexedPrimitive(mPrimitiveType, -minIndex, minIndex,
static_cast<UINT>(vertexCount), indexInfo.startIndex,
mPrimitiveCount);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
}
-gl::Error Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
+gl::Error Renderer9::drawLineLoop(const gl::Context *context,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ int minIndex,
+ gl::Buffer *elementArrayBuffer)
{
// Get the raw indices for an indexed draw
if (type != GL_NONE && elementArrayBuffer)
{
- BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
- intptr_t offset = reinterpret_cast<intptr_t>(indices);
- const uint8_t *bufferData = NULL;
- gl::Error error = storage->getData(&bufferData);
+ BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
+ intptr_t offset = reinterpret_cast<intptr_t>(indices);
+ const uint8_t *bufferData = nullptr;
+ gl::Error error = storage->getData(context, &bufferData);
if (error.isError())
{
return error;
@@ -1321,12 +1475,13 @@ gl::Error Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indi
unsigned int startIndex = 0;
- if (getRendererExtensions().elementIndexUint)
+ if (getNativeExtensions().elementIndexUint)
{
if (!mLineLoopIB)
{
mLineLoopIB = new StreamingIndexBufferInterface(this);
- gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
+ gl::Error error =
+ mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
if (error.isError())
{
SafeDelete(mLineLoopIB);
@@ -1337,60 +1492,64 @@ gl::Error Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indi
// Checked by Renderer9::applyPrimitiveType
ASSERT(count >= 0);
- if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
+ if (static_cast<unsigned int>(count) + 1 >
+ (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
+ return gl::OutOfMemory() << "Failed to create a 32-bit looping index buffer for "
+ "GL_LINE_LOOP, too many indices required.";
}
- const unsigned int spaceNeeded = (static_cast<unsigned int>(count)+1) * sizeof(unsigned int);
+ const unsigned int spaceNeeded =
+ (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int);
gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT);
if (error.isError())
{
return error;
}
- void* mappedMemory = NULL;
+ void *mappedMemory = nullptr;
unsigned int offset = 0;
- error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset);
+ error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset);
if (error.isError())
{
return error;
}
- startIndex = static_cast<unsigned int>(offset) / 4;
- unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
+ startIndex = static_cast<unsigned int>(offset) / 4;
+ unsigned int *data = reinterpret_cast<unsigned int *>(mappedMemory);
switch (type)
{
- case GL_NONE: // Non-indexed draw
- for (int i = 0; i < count; i++)
- {
- data[i] = i;
- }
- data[count] = 0;
- break;
- case GL_UNSIGNED_BYTE:
- for (int i = 0; i < count; i++)
- {
- data[i] = static_cast<const GLubyte*>(indices)[i];
- }
- data[count] = static_cast<const GLubyte*>(indices)[0];
- break;
- case GL_UNSIGNED_SHORT:
- for (int i = 0; i < count; i++)
- {
- data[i] = static_cast<const GLushort*>(indices)[i];
- }
- data[count] = static_cast<const GLushort*>(indices)[0];
- break;
- case GL_UNSIGNED_INT:
- for (int i = 0; i < count; i++)
- {
- data[i] = static_cast<const GLuint*>(indices)[i];
- }
- data[count] = static_cast<const GLuint*>(indices)[0];
- break;
- default: UNREACHABLE();
+ case GL_NONE: // Non-indexed draw
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = i;
+ }
+ data[count] = 0;
+ break;
+ case GL_UNSIGNED_BYTE:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLubyte *>(indices)[i];
+ }
+ data[count] = static_cast<const GLubyte *>(indices)[0];
+ break;
+ case GL_UNSIGNED_SHORT:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLushort *>(indices)[i];
+ }
+ data[count] = static_cast<const GLushort *>(indices)[0];
+ break;
+ case GL_UNSIGNED_INT:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLuint *>(indices)[i];
+ }
+ data[count] = static_cast<const GLuint *>(indices)[0];
+ break;
+ default:
+ UNREACHABLE();
}
error = mLineLoopIB->unmapBuffer();
@@ -1404,7 +1563,8 @@ gl::Error Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indi
if (!mLineLoopIB)
{
mLineLoopIB = new StreamingIndexBufferInterface(this);
- gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT);
+ gl::Error error =
+ mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT);
if (error.isError())
{
SafeDelete(mLineLoopIB);
@@ -1415,19 +1575,22 @@ gl::Error Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indi
// Checked by Renderer9::applyPrimitiveType
ASSERT(count >= 0);
- if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned short>::max() / sizeof(unsigned short)))
+ if (static_cast<unsigned int>(count) + 1 >
+ (std::numeric_limits<unsigned short>::max() / sizeof(unsigned short)))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a 16-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
+ return gl::OutOfMemory() << "Failed to create a 16-bit looping index buffer for "
+ "GL_LINE_LOOP, too many indices required.";
}
- const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned short);
+ const unsigned int spaceNeeded =
+ (static_cast<unsigned int>(count) + 1) * sizeof(unsigned short);
gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT);
if (error.isError())
{
return error;
}
- void* mappedMemory = NULL;
+ void *mappedMemory = nullptr;
unsigned int offset;
error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset);
if (error.isError())
@@ -1435,40 +1598,41 @@ gl::Error Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indi
return error;
}
- startIndex = static_cast<unsigned int>(offset) / 2;
- unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory);
+ startIndex = static_cast<unsigned int>(offset) / 2;
+ unsigned short *data = reinterpret_cast<unsigned short *>(mappedMemory);
switch (type)
{
- case GL_NONE: // Non-indexed draw
- for (int i = 0; i < count; i++)
- {
- data[i] = static_cast<unsigned short>(i);
- }
- data[count] = 0;
- break;
- case GL_UNSIGNED_BYTE:
- for (int i = 0; i < count; i++)
- {
- data[i] = static_cast<const GLubyte*>(indices)[i];
- }
- data[count] = static_cast<const GLubyte*>(indices)[0];
- break;
- case GL_UNSIGNED_SHORT:
- for (int i = 0; i < count; i++)
- {
- data[i] = static_cast<const GLushort*>(indices)[i];
- }
- data[count] = static_cast<const GLushort*>(indices)[0];
- break;
- case GL_UNSIGNED_INT:
- for (int i = 0; i < count; i++)
- {
- data[i] = static_cast<unsigned short>(static_cast<const GLuint*>(indices)[i]);
- }
- data[count] = static_cast<unsigned short>(static_cast<const GLuint*>(indices)[0]);
- break;
- default: UNREACHABLE();
+ case GL_NONE: // Non-indexed draw
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<unsigned short>(i);
+ }
+ data[count] = 0;
+ break;
+ case GL_UNSIGNED_BYTE:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLubyte *>(indices)[i];
+ }
+ data[count] = static_cast<const GLubyte *>(indices)[0];
+ break;
+ case GL_UNSIGNED_SHORT:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLushort *>(indices)[i];
+ }
+ data[count] = static_cast<const GLushort *>(indices)[0];
+ break;
+ case GL_UNSIGNED_INT:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<unsigned short>(static_cast<const GLuint *>(indices)[i]);
+ }
+ data[count] = static_cast<unsigned short>(static_cast<const GLuint *>(indices)[0]);
+ break;
+ default:
+ UNREACHABLE();
}
error = mLineLoopIB->unmapBuffer();
@@ -1488,22 +1652,31 @@ gl::Error Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indi
mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
template <typename T>
-static gl::Error drawPoints(IDirect3DDevice9* device, GLsizei count, const GLvoid *indices, int minIndex)
+static gl::Error drawPoints(IDirect3DDevice9 *device,
+ GLsizei count,
+ const void *indices,
+ int minIndex)
{
for (int i = 0; i < count; i++)
{
- unsigned int indexValue = static_cast<unsigned int>(static_cast<const T*>(indices)[i]) - minIndex;
+ unsigned int indexValue =
+ static_cast<unsigned int>(static_cast<const T *>(indices)[i]) - minIndex;
device->DrawPrimitive(D3DPT_POINTLIST, indexValue, 1);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
+gl::Error Renderer9::drawIndexedPoints(const gl::Context *context,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ int minIndex,
+ gl::Buffer *elementArrayBuffer)
{
// Drawing index point lists is unsupported in d3d9, fall back to a regular DrawPrimitive call
// for each individual point. This call is not expected to happen often.
@@ -1511,10 +1684,10 @@ gl::Error Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid
if (elementArrayBuffer)
{
BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
- intptr_t offset = reinterpret_cast<intptr_t>(indices);
+ intptr_t offset = reinterpret_cast<intptr_t>(indices);
- const uint8_t *bufferData = NULL;
- gl::Error error = storage->getData(&bufferData);
+ const uint8_t *bufferData = nullptr;
+ gl::Error error = storage->getData(context, &bufferData);
if (error.isError())
{
return error;
@@ -1525,17 +1698,22 @@ gl::Error Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid
switch (type)
{
- case GL_UNSIGNED_BYTE: return drawPoints<GLubyte>(mDevice, count, indices, minIndex);
- case GL_UNSIGNED_SHORT: return drawPoints<GLushort>(mDevice, count, indices, minIndex);
- case GL_UNSIGNED_INT: return drawPoints<GLuint>(mDevice, count, indices, minIndex);
- default: UNREACHABLE(); return gl::Error(GL_INVALID_OPERATION);
+ case GL_UNSIGNED_BYTE:
+ return drawPoints<GLubyte>(mDevice, count, indices, minIndex);
+ case GL_UNSIGNED_SHORT:
+ return drawPoints<GLushort>(mDevice, count, indices, minIndex);
+ case GL_UNSIGNED_INT:
+ return drawPoints<GLuint>(mDevice, count, indices, minIndex);
+ default:
+ UNREACHABLE();
+ return gl::InternalError();
}
}
gl::Error Renderer9::getCountingIB(size_t count, StaticIndexBufferInterface **outIB)
{
// Update the counting index buffer if it is not large enough or has not been created yet.
- if (count <= 65536) // 16-bit indices
+ if (count <= 65536) // 16-bit indices
{
const unsigned int spaceNeeded = static_cast<unsigned int>(count) * sizeof(unsigned short);
@@ -1543,29 +1721,21 @@ gl::Error Renderer9::getCountingIB(size_t count, StaticIndexBufferInterface **ou
{
SafeDelete(mCountingIB);
mCountingIB = new StaticIndexBufferInterface(this);
- mCountingIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT);
+ ANGLE_TRY(mCountingIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT));
- void *mappedMemory = NULL;
- gl::Error error = mCountingIB->mapBuffer(spaceNeeded, &mappedMemory, NULL);
- if (error.isError())
- {
- return error;
- }
+ void *mappedMemory = nullptr;
+ ANGLE_TRY(mCountingIB->mapBuffer(spaceNeeded, &mappedMemory, nullptr));
- unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory);
+ unsigned short *data = reinterpret_cast<unsigned short *>(mappedMemory);
for (size_t i = 0; i < count; i++)
{
data[i] = static_cast<unsigned short>(i);
}
- error = mCountingIB->unmapBuffer();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mCountingIB->unmapBuffer());
}
}
- else if (getRendererExtensions().elementIndexUint)
+ else if (getNativeExtensions().elementIndexUint)
{
const unsigned int spaceNeeded = static_cast<unsigned int>(count) * sizeof(unsigned int);
@@ -1573,59 +1743,53 @@ gl::Error Renderer9::getCountingIB(size_t count, StaticIndexBufferInterface **ou
{
SafeDelete(mCountingIB);
mCountingIB = new StaticIndexBufferInterface(this);
- mCountingIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT);
+ ANGLE_TRY(mCountingIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT));
- void *mappedMemory = NULL;
- gl::Error error = mCountingIB->mapBuffer(spaceNeeded, &mappedMemory, NULL);
- if (error.isError())
- {
- return error;
- }
+ void *mappedMemory = nullptr;
+ ANGLE_TRY(mCountingIB->mapBuffer(spaceNeeded, &mappedMemory, nullptr));
- unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
+ unsigned int *data = reinterpret_cast<unsigned int *>(mappedMemory);
for (unsigned int i = 0; i < count; i++)
{
data[i] = i;
}
- error = mCountingIB->unmapBuffer();
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(mCountingIB->unmapBuffer());
}
}
else
{
- return gl::Error(GL_OUT_OF_MEMORY, "Could not create a counting index buffer for glDrawArraysInstanced.");
+ return gl::OutOfMemory()
+ << "Could not create a counting index buffer for glDrawArraysInstanced.";
}
*outIB = mCountingIB;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error Renderer9::applyShadersImpl(const gl::Data &data, GLenum /*drawMode*/)
+gl::Error Renderer9::applyShaders(const gl::Context *context, GLenum drawMode)
{
- ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram());
- const auto &inputLayout = programD3D->getCachedInputLayout();
+ const gl::State &state = context->getContextState().getState();
+ // This method is called single-threaded.
+ ANGLE_TRY(ensureHLSLCompilerInitialized());
- ShaderExecutableD3D *vertexExe = NULL;
- gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe, nullptr);
- if (error.isError())
- {
- return error;
- }
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(state.getProgram());
+ VertexArray9 *vao = GetImplAs<VertexArray9>(state.getVertexArray());
+ programD3D->updateCachedInputLayout(vao->getCurrentStateSerial(), state);
- const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer();
- ShaderExecutableD3D *pixelExe = NULL;
- error = programD3D->getPixelExecutableForFramebuffer(drawFramebuffer, &pixelExe);
- if (error.isError())
- {
- return error;
- }
+ ShaderExecutableD3D *vertexExe = nullptr;
+ ANGLE_TRY(programD3D->getVertexExecutableForCachedInputLayout(&vertexExe, nullptr));
+
+ const gl::Framebuffer *drawFramebuffer = state.getDrawFramebuffer();
+ programD3D->updateCachedOutputLayout(context, drawFramebuffer);
+
+ ShaderExecutableD3D *pixelExe = nullptr;
+ ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(&pixelExe, nullptr));
- IDirect3DVertexShader9 *vertexShader = (vertexExe ? GetAs<ShaderExecutable9>(vertexExe)->getVertexShader() : nullptr);
- IDirect3DPixelShader9 *pixelShader = (pixelExe ? GetAs<ShaderExecutable9>(pixelExe)->getPixelShader() : nullptr);
+ IDirect3DVertexShader9 *vertexShader =
+ (vertexExe ? GetAs<ShaderExecutable9>(vertexExe)->getVertexShader() : nullptr);
+ IDirect3DPixelShader9 *pixelShader =
+ (pixelExe ? GetAs<ShaderExecutable9>(pixelExe)->getPixelShader() : nullptr);
if (vertexShader != mAppliedVertexShader)
{
@@ -1652,25 +1816,39 @@ gl::Error Renderer9::applyShadersImpl(const gl::Data &data, GLenum /*drawMode*/)
mAppliedProgramSerial = programSerial;
}
- return gl::Error(GL_NO_ERROR);
+ ANGLE_TRY(applyUniforms(programD3D));
+
+ // Driver uniforms
+ mStateManager.setShaderConstants();
+
+ return gl::NoError();
}
-gl::Error Renderer9::applyUniforms(const ProgramD3D &programD3D,
- GLenum /*drawMode*/,
- const std::vector<D3DUniform *> &uniformArray)
+gl::Error Renderer9::applyUniforms(ProgramD3D *programD3D)
{
+ // Skip updates if we're not dirty. Note that D3D9 cannot have compute.
+ if (!programD3D->areVertexUniformsDirty() && !programD3D->areFragmentUniformsDirty())
+ {
+ return gl::NoError();
+ }
+
+ const auto &uniformArray = programD3D->getD3DUniforms();
+
for (const D3DUniform *targetUniform : uniformArray)
{
- if (!targetUniform->dirty)
+ // Built-in uniforms must be skipped.
+ if (!targetUniform->isReferencedByFragmentShader() &&
+ !targetUniform->isReferencedByVertexShader())
continue;
- GLfloat *f = (GLfloat *)targetUniform->data;
- GLint *i = (GLint *)targetUniform->data;
+ const GLfloat *f = reinterpret_cast<const GLfloat *>(targetUniform->firstNonNullData());
+ const GLint *i = reinterpret_cast<const GLint *>(targetUniform->firstNonNullData());
- switch (targetUniform->type)
+ switch (targetUniform->typeInfo.type)
{
case GL_SAMPLER_2D:
case GL_SAMPLER_CUBE:
+ case GL_SAMPLER_EXTERNAL_OES:
break;
case GL_BOOL:
case GL_BOOL_VEC2:
@@ -1698,22 +1876,22 @@ gl::Error Renderer9::applyUniforms(const ProgramD3D &programD3D,
}
}
- // Driver uniforms
- mStateManager.setShaderConstants();
-
- return gl::Error(GL_NO_ERROR);
+ programD3D->markUniformsClean();
+ return gl::NoError();
}
void Renderer9::applyUniformnfv(const D3DUniform *targetUniform, const GLfloat *v)
{
if (targetUniform->isReferencedByFragmentShader())
{
- mDevice->SetPixelShaderConstantF(targetUniform->psRegisterIndex, v, targetUniform->registerCount);
+ mDevice->SetPixelShaderConstantF(targetUniform->psRegisterIndex, v,
+ targetUniform->registerCount);
}
if (targetUniform->isReferencedByVertexShader())
{
- mDevice->SetVertexShaderConstantF(targetUniform->vsRegisterIndex, v, targetUniform->registerCount);
+ mDevice->SetVertexShaderConstantF(targetUniform->vsRegisterIndex, v,
+ targetUniform->registerCount);
}
}
@@ -1730,7 +1908,7 @@ void Renderer9::applyUniformniv(const D3DUniform *targetUniform, const GLint *v)
vector[i][3] = (GLfloat)v[4 * i + 3];
}
- applyUniformnfv(targetUniform, (GLfloat*)vector);
+ applyUniformnfv(targetUniform, (GLfloat *)vector);
}
void Renderer9::applyUniformnbv(const D3DUniform *targetUniform, const GLint *v)
@@ -1746,18 +1924,19 @@ void Renderer9::applyUniformnbv(const D3DUniform *targetUniform, const GLint *v)
vector[i][3] = (v[4 * i + 3] == GL_FALSE) ? 0.0f : 1.0f;
}
- applyUniformnfv(targetUniform, (GLfloat*)vector);
+ applyUniformnfv(targetUniform, (GLfloat *)vector);
}
-gl::Error Renderer9::clear(const ClearParameters &clearParams,
+gl::Error Renderer9::clear(const gl::Context *context,
+ const ClearParameters &clearParams,
const gl::FramebufferAttachment *colorBuffer,
const gl::FramebufferAttachment *depthStencilBuffer)
{
- if (clearParams.colorClearType != GL_FLOAT)
+ if (clearParams.colorType != GL_FLOAT)
{
// Clearing buffers with non-float values is not supported by Renderer9 and ES 2.0
UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION);
+ return gl::InternalError();
}
bool clearColor = clearParams.clearColor[0];
@@ -1765,14 +1944,15 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams,
{
if (clearParams.clearColor[i] != clearColor)
{
- // Clearing individual buffers other than buffer zero is not supported by Renderer9 and ES 2.0
+ // Clearing individual buffers other than buffer zero is not supported by Renderer9 and
+ // ES 2.0
UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION);
+ return gl::InternalError();
}
}
- float depth = gl::clamp01(clearParams.depthClearValue);
- DWORD stencil = clearParams.stencilClearValue & 0x000000FF;
+ float depth = gl::clamp01(clearParams.depthValue);
+ DWORD stencil = clearParams.stencilValue & 0x000000FF;
unsigned int stencilUnmasked = 0x0;
if (clearParams.clearStencil && depthStencilBuffer->getStencilSize() > 0)
@@ -1780,7 +1960,7 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams,
ASSERT(depthStencilBuffer != nullptr);
RenderTargetD3D *stencilRenderTarget = nullptr;
- gl::Error error = depthStencilBuffer->getRenderTarget(&stencilRenderTarget);
+ gl::Error error = depthStencilBuffer->getRenderTarget(context, &stencilRenderTarget);
if (error.isError())
{
return error;
@@ -1789,21 +1969,23 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams,
RenderTarget9 *stencilRenderTarget9 = GetAs<RenderTarget9>(stencilRenderTarget);
ASSERT(stencilRenderTarget9);
- const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(stencilRenderTarget9->getD3DFormat());
+ const d3d9::D3DFormat &d3dFormatInfo =
+ d3d9::GetD3DFormatInfo(stencilRenderTarget9->getD3DFormat());
stencilUnmasked = (0x1 << d3dFormatInfo.stencilBits) - 1;
}
- const bool needMaskedStencilClear = clearParams.clearStencil &&
- (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
+ const bool needMaskedStencilClear =
+ clearParams.clearStencil &&
+ (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
bool needMaskedColorClear = false;
- D3DCOLOR color = D3DCOLOR_ARGB(255, 0, 0, 0);
+ D3DCOLOR color = D3DCOLOR_ARGB(255, 0, 0, 0);
if (clearColor)
{
ASSERT(colorBuffer != nullptr);
- RenderTargetD3D *colorRenderTarget = NULL;
- gl::Error error = colorBuffer->getRenderTarget(&colorRenderTarget);
+ RenderTargetD3D *colorRenderTarget = nullptr;
+ gl::Error error = colorBuffer->getRenderTarget(context, &colorRenderTarget);
if (error.isError())
{
return error;
@@ -1812,17 +1994,27 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams,
RenderTarget9 *colorRenderTarget9 = GetAs<RenderTarget9>(colorRenderTarget);
ASSERT(colorRenderTarget9);
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(colorBuffer->getInternalFormat());
- const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(colorRenderTarget9->getD3DFormat());
-
- color = D3DCOLOR_ARGB(gl::unorm<8>((formatInfo.alphaBits == 0 && d3dFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha),
- gl::unorm<8>((formatInfo.redBits == 0 && d3dFormatInfo.redBits > 0) ? 0.0f : clearParams.colorFClearValue.red),
- gl::unorm<8>((formatInfo.greenBits == 0 && d3dFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green),
- gl::unorm<8>((formatInfo.blueBits == 0 && d3dFormatInfo.blueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue));
-
- if ((formatInfo.redBits > 0 && !clearParams.colorMaskRed) ||
+ const gl::InternalFormat &formatInfo = *colorBuffer->getFormat().info;
+ const d3d9::D3DFormat &d3dFormatInfo =
+ d3d9::GetD3DFormatInfo(colorRenderTarget9->getD3DFormat());
+
+ color =
+ D3DCOLOR_ARGB(gl::unorm<8>((formatInfo.alphaBits == 0 && d3dFormatInfo.alphaBits > 0)
+ ? 1.0f
+ : clearParams.colorF.alpha),
+ gl::unorm<8>((formatInfo.redBits == 0 && d3dFormatInfo.redBits > 0)
+ ? 0.0f
+ : clearParams.colorF.red),
+ gl::unorm<8>((formatInfo.greenBits == 0 && d3dFormatInfo.greenBits > 0)
+ ? 0.0f
+ : clearParams.colorF.green),
+ gl::unorm<8>((formatInfo.blueBits == 0 && d3dFormatInfo.blueBits > 0)
+ ? 0.0f
+ : clearParams.colorF.blue));
+
+ if ((formatInfo.redBits > 0 && !clearParams.colorMaskRed) ||
(formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) ||
- (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) ||
+ (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) ||
(formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha))
{
needMaskedColorClear = true;
@@ -1835,7 +2027,7 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams,
// State which is altered in only some paths will be flagged dirty in the case that
// that path is taken.
HRESULT hr;
- if (mMaskedClearSavedState == NULL)
+ if (mMaskedClearSavedState == nullptr)
{
hr = mDevice->BeginStateBlock();
ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
@@ -1850,10 +2042,10 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams,
mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
- mDevice->SetPixelShader(NULL);
- mDevice->SetVertexShader(NULL);
+ mDevice->SetPixelShader(nullptr);
+ mDevice->SetVertexShader(nullptr);
mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
- mDevice->SetStreamSource(0, NULL, 0, 0);
+ mDevice->SetStreamSource(0, nullptr, 0, 0);
mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
@@ -1862,7 +2054,7 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams,
mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
- for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
{
mDevice->SetStreamSourceFreq(i, 1);
}
@@ -1871,9 +2063,9 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams,
ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
}
- ASSERT(mMaskedClearSavedState != NULL);
+ ASSERT(mMaskedClearSavedState != nullptr);
- if (mMaskedClearSavedState != NULL)
+ if (mMaskedClearSavedState != nullptr)
{
hr = mMaskedClearSavedState->Capture();
ASSERT(SUCCEEDED(hr));
@@ -1890,11 +2082,10 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams,
if (clearColor)
{
- mDevice->SetRenderState(D3DRS_COLORWRITEENABLE,
- gl_d3d9::ConvertColorMask(clearParams.colorMaskRed,
- clearParams.colorMaskGreen,
- clearParams.colorMaskBlue,
- clearParams.colorMaskAlpha));
+ mDevice->SetRenderState(
+ D3DRS_COLORWRITEENABLE,
+ gl_d3d9::ConvertColorMask(clearParams.colorMaskRed, clearParams.colorMaskGreen,
+ clearParams.colorMaskBlue, clearParams.colorMaskAlpha));
}
else
{
@@ -1917,8 +2108,8 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams,
mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
}
- mDevice->SetPixelShader(NULL);
- mDevice->SetVertexShader(NULL);
+ mDevice->SetPixelShader(nullptr);
+ mDevice->SetVertexShader(nullptr);
mDevice->SetFVF(D3DFVF_XYZRHW);
mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
@@ -1928,7 +2119,7 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams,
mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
- for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
{
mDevice->SetStreamSourceFreq(i, 1);
}
@@ -1936,7 +2127,7 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams,
int renderTargetWidth = mStateManager.getRenderTargetWidth();
int renderTargetHeight = mStateManager.getRenderTargetHeight();
- float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges
+ float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges
quad[0][0] = -0.5f;
quad[0][1] = renderTargetHeight - 0.5f;
quad[0][2] = 0.0f;
@@ -1964,10 +2155,10 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams,
{
mDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
- mDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
+ mDevice->Clear(0, nullptr, D3DCLEAR_ZBUFFER, color, depth, stencil);
}
- if (mMaskedClearSavedState != NULL)
+ if (mMaskedClearSavedState != nullptr)
{
mMaskedClearSavedState->Apply();
}
@@ -1988,17 +2179,17 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams,
dxClearFlags |= D3DCLEAR_STENCIL;
}
- mDevice->Clear(0, NULL, dxClearFlags, color, depth, stencil);
+ mDevice->Clear(0, nullptr, dxClearFlags, color, depth, stencil);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
void Renderer9::markAllStateDirty()
{
- mAppliedRenderTargetSerial = 0;
- mAppliedDepthStencilSerial = 0;
- mDepthStencilInitialized = false;
+ mAppliedRenderTargetSerial = 0;
+ mAppliedDepthStencilSerial = 0;
+ mDepthStencilInitialized = false;
mRenderTargetDescInitialized = false;
mStateManager.forceSetRasterState();
@@ -2021,9 +2212,9 @@ void Renderer9::markAllStateDirty()
mCurPixelTextures[i] = angle::DirtyPointer;
}
- mAppliedIBSerial = 0;
- mAppliedVertexShader = NULL;
- mAppliedPixelShader = NULL;
+ mAppliedIBSerial = 0;
+ mAppliedVertexShader = nullptr;
+ mAppliedPixelShader = nullptr;
mAppliedProgramSerial = 0;
mStateManager.forceSetDXUniformsState();
@@ -2051,6 +2242,10 @@ void Renderer9::releaseDeviceResources()
for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
{
+ if (mNullColorbufferCache[i].buffer)
+ {
+ mNullColorbufferCache[i].buffer->detach(mDisplay->getProxyContext());
+ }
SafeDelete(mNullColorbufferCache[i].buffer);
}
}
@@ -2059,19 +2254,7 @@ void Renderer9::releaseDeviceResources()
bool Renderer9::testDeviceLost()
{
HRESULT status = getDeviceStatusCode();
- bool isLost = FAILED(status);
-
- if (isLost)
- {
- // ensure we note the device loss --
- // we'll probably get this done again by notifyDeviceLost
- // but best to remember it!
- // Note that we don't want to clear the device loss status here
- // -- this needs to be done by resetDevice
- mDeviceLost = true;
- }
-
- return isLost;
+ return FAILED(status);
}
HRESULT Renderer9::getDeviceStatusCode()
@@ -2080,7 +2263,7 @@ HRESULT Renderer9::getDeviceStatusCode()
if (mDeviceEx)
{
- status = mDeviceEx->CheckDeviceState(NULL);
+ status = mDeviceEx->CheckDeviceState(nullptr);
}
else if (mDevice)
{
@@ -2096,16 +2279,16 @@ bool Renderer9::testDeviceResettable()
// DEVICEREMOVED indicates the device has been stopped and must be recreated
switch (getDeviceStatusCode())
{
- case D3DERR_DEVICENOTRESET:
- case D3DERR_DEVICEHUNG:
- return true;
- case D3DERR_DEVICELOST:
- return (mDeviceEx != NULL);
- case D3DERR_DEVICEREMOVED:
- ASSERT(mDeviceEx != NULL);
- return isRemovedDeviceResettable();
- default:
- return false;
+ case D3DERR_DEVICENOTRESET:
+ case D3DERR_DEVICEHUNG:
+ return true;
+ case D3DERR_DEVICELOST:
+ return (mDeviceEx != nullptr);
+ case D3DERR_DEVICEREMOVED:
+ ASSERT(mDeviceEx != nullptr);
+ return isRemovedDeviceResettable();
+ default:
+ return false;
}
}
@@ -2115,12 +2298,12 @@ bool Renderer9::resetDevice()
D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
- HRESULT result = D3D_OK;
- bool lost = testDeviceLost();
+ HRESULT result = D3D_OK;
+ bool lost = testDeviceLost();
bool removedDevice = (getDeviceStatusCode() == D3DERR_DEVICEREMOVED);
// Device Removed is a feature which is only present with D3D9Ex
- ASSERT(mDeviceEx != NULL || !removedDevice);
+ ASSERT(mDeviceEx != nullptr || !removedDevice);
for (int attempts = 3; lost && attempts > 0; attempts--)
{
@@ -2134,16 +2317,16 @@ bool Renderer9::resetDevice()
}
else if (mDeviceEx)
{
- Sleep(500); // Give the graphics driver some CPU time
- result = mDeviceEx->ResetEx(&presentParameters, NULL);
- lost = testDeviceLost();
+ Sleep(500); // Give the graphics driver some CPU time
+ result = mDeviceEx->ResetEx(&presentParameters, nullptr);
+ lost = testDeviceLost();
}
else
{
result = mDevice->TestCooperativeLevel();
while (result == D3DERR_DEVICELOST)
{
- Sleep(100); // Give the graphics driver some CPU time
+ Sleep(100); // Give the graphics driver some CPU time
result = mDevice->TestCooperativeLevel();
}
@@ -2157,13 +2340,13 @@ bool Renderer9::resetDevice()
if (FAILED(result))
{
- ERR("Reset/ResetEx failed multiple times: 0x%08X", result);
+ ERR() << "Reset/ResetEx failed multiple times, " << gl::FmtHR(result);
return false;
}
if (removedDevice && lost)
{
- ERR("Device lost reset failed multiple times");
+ ERR() << "Device lost reset failed multiple times";
return false;
}
@@ -2171,11 +2354,12 @@ bool Renderer9::resetDevice()
if (!removedDevice)
{
// reset device defaults
- initializeDevice();
+ if (initializeDevice().isError())
+ {
+ return false;
+ }
}
- mDeviceLost = false;
-
return true;
}
@@ -2184,15 +2368,16 @@ bool Renderer9::isRemovedDeviceResettable() const
bool success = false;
#if ANGLE_D3D9EX == ANGLE_ENABLED
- IDirect3D9Ex *d3d9Ex = NULL;
- typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**);
- Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
+ IDirect3D9Ex *d3d9Ex = nullptr;
+ typedef HRESULT(WINAPI * Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex **);
+ Direct3DCreate9ExFunc Direct3DCreate9ExPtr =
+ reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
if (Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &d3d9Ex)))
{
D3DCAPS9 deviceCaps;
HRESULT result = d3d9Ex->GetDeviceCaps(mAdapter, mDeviceType, &deviceCaps);
- success = SUCCEEDED(result);
+ success = SUCCEEDED(result);
}
SafeRelease(d3d9Ex);
@@ -2232,20 +2417,22 @@ std::string Renderer9::getRendererDescription() const
rendererString << " Direct3D9";
}
- rendererString << " vs_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.VertexShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.VertexShaderVersion);
- rendererString << " ps_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion);
+ rendererString << " vs_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.VertexShaderVersion) << "_"
+ << D3DSHADER_VERSION_MINOR(mDeviceCaps.VertexShaderVersion);
+ rendererString << " ps_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion) << "_"
+ << D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion);
return rendererString.str();
}
DeviceIdentifier Renderer9::getAdapterIdentifier() const
{
- DeviceIdentifier deviceIdentifier = { 0 };
- deviceIdentifier.VendorId = static_cast<UINT>(mAdapterIdentifier.VendorId);
- deviceIdentifier.DeviceId = static_cast<UINT>(mAdapterIdentifier.DeviceId);
- deviceIdentifier.SubSysId = static_cast<UINT>(mAdapterIdentifier.SubSysId);
- deviceIdentifier.Revision = static_cast<UINT>(mAdapterIdentifier.Revision);
- deviceIdentifier.FeatureLevel = 0;
+ DeviceIdentifier deviceIdentifier = {0};
+ deviceIdentifier.VendorId = static_cast<UINT>(mAdapterIdentifier.VendorId);
+ deviceIdentifier.DeviceId = static_cast<UINT>(mAdapterIdentifier.DeviceId);
+ deviceIdentifier.SubSysId = static_cast<UINT>(mAdapterIdentifier.SubSysId);
+ deviceIdentifier.Revision = static_cast<UINT>(mAdapterIdentifier.Revision);
+ deviceIdentifier.FeatureLevel = 0;
return deviceIdentifier;
}
@@ -2260,20 +2447,10 @@ unsigned int Renderer9::getReservedFragmentUniformVectors() const
return d3d9_gl::GetReservedFragmentUniformVectors();
}
-unsigned int Renderer9::getReservedVertexUniformBuffers() const
-{
- return 0;
-}
-
-unsigned int Renderer9::getReservedFragmentUniformBuffers() const
-{
- return 0;
-}
-
bool Renderer9::getShareHandleSupport() const
{
// PIX doesn't seem to support using share handles, so disable them.
- return (mD3d9Ex != NULL) && !gl::DebugAnnotationsActive();
+ return (mD3d9Ex != nullptr) && !gl::DebugAnnotationsActive();
}
int Renderer9::getMajorShaderModel() const
@@ -2298,7 +2475,7 @@ DWORD Renderer9::getCapsDeclTypes() const
D3DPOOL Renderer9::getBufferPool(DWORD usage) const
{
- if (mD3d9Ex != NULL)
+ if (mD3d9Ex != nullptr)
{
return D3DPOOL_DEFAULT;
}
@@ -2313,66 +2490,126 @@ D3DPOOL Renderer9::getBufferPool(DWORD usage) const
return D3DPOOL_DEFAULT;
}
-gl::Error Renderer9::copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- const gl::Offset &destOffset, TextureStorage *storage, GLint level)
+gl::Error Renderer9::copyImage2D(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level)
{
RECT rect;
- rect.left = sourceRect.x;
- rect.top = sourceRect.y;
- rect.right = sourceRect.x + sourceRect.width;
+ rect.left = sourceRect.x;
+ rect.top = sourceRect.y;
+ rect.right = sourceRect.x + sourceRect.width;
rect.bottom = sourceRect.y + sourceRect.height;
- return mBlit->copy2D(framebuffer, rect, destFormat, destOffset, storage, level);
+ return mBlit->copy2D(context, framebuffer, rect, destFormat, destOffset, storage, level);
}
-gl::Error Renderer9::copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level)
+gl::Error Renderer9::copyImageCube(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLenum target,
+ GLint level)
{
RECT rect;
- rect.left = sourceRect.x;
- rect.top = sourceRect.y;
- rect.right = sourceRect.x + sourceRect.width;
+ rect.left = sourceRect.x;
+ rect.top = sourceRect.y;
+ rect.right = sourceRect.x + sourceRect.width;
rect.bottom = sourceRect.y + sourceRect.height;
- return mBlit->copyCube(framebuffer, rect, destFormat, destOffset, storage, target, level);
+ return mBlit->copyCube(context, framebuffer, rect, destFormat, destOffset, storage, target,
+ level);
}
-gl::Error Renderer9::copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- const gl::Offset &destOffset, TextureStorage *storage, GLint level)
+gl::Error Renderer9::copyImage3D(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level)
{
// 3D textures are not available in the D3D9 backend.
UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION);
+ return gl::InternalError();
}
-gl::Error Renderer9::copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- const gl::Offset &destOffset, TextureStorage *storage, GLint level)
+gl::Error Renderer9::copyImage2DArray(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level)
{
// 2D array textures are not available in the D3D9 backend.
UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION);
+ return gl::InternalError();
+}
+
+gl::Error Renderer9::copyTexture(const gl::Context *context,
+ const gl::Texture *source,
+ GLint sourceLevel,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLenum destTarget,
+ GLint destLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha)
+{
+ RECT rect;
+ rect.left = sourceRect.x;
+ rect.top = sourceRect.y;
+ rect.right = sourceRect.x + sourceRect.width;
+ rect.bottom = sourceRect.y + sourceRect.height;
+
+ return mBlit->copyTexture(context, source, sourceLevel, rect, destFormat, destOffset, storage,
+ destTarget, destLevel, unpackFlipY, unpackPremultiplyAlpha,
+ unpackUnmultiplyAlpha);
}
-gl::Error Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT)
+gl::Error Renderer9::copyCompressedTexture(const gl::Context *context,
+ const gl::Texture *source,
+ GLint sourceLevel,
+ TextureStorage *storage,
+ GLint destLevel)
+{
+ UNIMPLEMENTED();
+ return gl::InternalError();
+}
+
+gl::Error Renderer9::createRenderTarget(int width,
+ int height,
+ GLenum format,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
{
const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(format);
- const gl::TextureCaps &textureCaps = getRendererTextureCaps().get(format);
- GLuint supportedSamples = textureCaps.getNearestSamples(samples);
+ const gl::TextureCaps &textureCaps = getNativeTextureCaps().get(format);
+ GLuint supportedSamples = textureCaps.getNearestSamples(samples);
IDirect3DTexture9 *texture = nullptr;
- IDirect3DSurface9 *renderTarget = NULL;
+ IDirect3DSurface9 *renderTarget = nullptr;
if (width > 0 && height > 0)
{
bool requiresInitialization = false;
- HRESULT result = D3DERR_INVALIDCALL;
+ HRESULT result = D3DERR_INVALIDCALL;
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format);
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(format);
if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
{
- result = mDevice->CreateDepthStencilSurface(width, height, d3d9FormatInfo.renderFormat,
- gl_d3d9::GetMultisampleType(supportedSamples),
- 0, FALSE, &renderTarget, NULL);
+ result = mDevice->CreateDepthStencilSurface(
+ width, height, d3d9FormatInfo.renderFormat,
+ gl_d3d9::GetMultisampleType(supportedSamples), 0, FALSE, &renderTarget, nullptr);
}
else
{
@@ -2398,25 +2635,25 @@ gl::Error Renderer9::createRenderTarget(int width, int height, GLenum format, GL
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to create render target, " << gl::FmtHR(result);
}
if (requiresInitialization)
{
- // This format requires that the data be initialized before the render target can be used
- // Unfortunately this requires a Get call on the d3d device but it is far better than having
- // to mark the render target as lockable and copy data to the gpu.
- IDirect3DSurface9 *prevRenderTarget = NULL;
+ // This format requires that the data be initialized before the render target can be
+ // used Unfortunately this requires a Get call on the d3d device but it is far better
+ // than having to mark the render target as lockable and copy data to the gpu.
+ IDirect3DSurface9 *prevRenderTarget = nullptr;
mDevice->GetRenderTarget(0, &prevRenderTarget);
mDevice->SetRenderTarget(0, renderTarget);
- mDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 0.0f, 0);
+ mDevice->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 0.0f, 0);
mDevice->SetRenderTarget(0, prevRenderTarget);
}
}
*outRT = new TextureRenderTarget9(texture, 0, renderTarget, format, width, height, 1,
supportedSamples);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error Renderer9::createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT)
@@ -2424,7 +2661,7 @@ gl::Error Renderer9::createRenderTargetCopy(RenderTargetD3D *source, RenderTarge
ASSERT(source != nullptr);
RenderTargetD3D *newRT = nullptr;
- gl::Error error = createRenderTarget(source->getWidth(), source->getHeight(),
+ gl::Error error = createRenderTarget(source->getWidth(), source->getHeight(),
source->getInternalFormat(), source->getSamples(), &newRT);
if (error.isError())
{
@@ -2439,31 +2676,16 @@ gl::Error Renderer9::createRenderTargetCopy(RenderTargetD3D *source, RenderTarge
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to copy render target, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to copy render target, " << gl::FmtHR(result);
}
*outRT = newRT;
- return gl::Error(GL_NO_ERROR);
-}
-
-FramebufferImpl *Renderer9::createFramebuffer(const gl::Framebuffer::Data &data)
-{
- return new Framebuffer9(data, this);
-}
-
-ShaderImpl *Renderer9::createShader(const gl::Shader::Data &data)
-{
- return new ShaderD3D(data);
+ return gl::NoError();
}
-ProgramImpl *Renderer9::createProgram(const gl::Program::Data &data)
-{
- return new ProgramD3D(data, this);
-}
-
-gl::Error Renderer9::loadExecutable(const void *function,
+gl::Error Renderer9::loadExecutable(const uint8_t *function,
size_t length,
- ShaderType type,
+ gl::ShaderType type,
const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers,
ShaderExecutableD3D **outExecutable)
@@ -2473,10 +2695,10 @@ gl::Error Renderer9::loadExecutable(const void *function,
switch (type)
{
- case SHADER_VERTEX:
+ case gl::SHADER_VERTEX:
{
- IDirect3DVertexShader9 *vshader = NULL;
- gl::Error error = createVertexShader((DWORD*)function, length, &vshader);
+ IDirect3DVertexShader9 *vshader = nullptr;
+ gl::Error error = createVertexShader((DWORD *)function, length, &vshader);
if (error.isError())
{
return error;
@@ -2484,10 +2706,10 @@ gl::Error Renderer9::loadExecutable(const void *function,
*outExecutable = new ShaderExecutable9(function, length, vshader);
}
break;
- case SHADER_PIXEL:
+ case gl::SHADER_FRAGMENT:
{
- IDirect3DPixelShader9 *pshader = NULL;
- gl::Error error = createPixelShader((DWORD*)function, length, &pshader);
+ IDirect3DPixelShader9 *pshader = nullptr;
+ gl::Error error = createPixelShader((DWORD *)function, length, &pshader);
if (error.isError())
{
return error;
@@ -2495,41 +2717,45 @@ gl::Error Renderer9::loadExecutable(const void *function,
*outExecutable = new ShaderExecutable9(function, length, pshader);
}
break;
- default:
- UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION);
+ default:
+ UNREACHABLE();
+ return gl::InternalError();
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog,
const std::string &shaderHLSL,
- ShaderType type,
+ gl::ShaderType type,
const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers,
- const D3DCompilerWorkarounds &workarounds,
+ const angle::CompilerWorkaroundsD3D &workarounds,
ShaderExecutableD3D **outExectuable)
{
// Transform feedback is not supported in ES2 or D3D9
ASSERT(streamOutVaryings.empty());
- const char *profileType = NULL;
+ std::stringstream profileStream;
+
switch (type)
{
- case SHADER_VERTEX:
- profileType = "vs";
- break;
- case SHADER_PIXEL:
- profileType = "ps";
- break;
- default:
- UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION);
+ case gl::SHADER_VERTEX:
+ profileStream << "vs";
+ break;
+ case gl::SHADER_FRAGMENT:
+ profileStream << "ps";
+ break;
+ default:
+ UNREACHABLE();
+ return gl::InternalError();
}
- unsigned int profileMajorVersion = (getMajorShaderModel() >= 3) ? 3 : 2;
- unsigned int profileMinorVersion = 0;
- std::string profile = FormatString("%s_%u_%u", profileType, profileMajorVersion, profileMinorVersion);
+
+ profileStream << "_" << ((getMajorShaderModel() >= 3) ? 3 : 2);
+ profileStream << "_"
+ << "0";
+
+ std::string profile = profileStream.str();
UINT flags = ANGLE_COMPILE_OPTIMIZATION_LEVEL;
@@ -2551,31 +2777,35 @@ gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog,
flags |= D3DCOMPILE_DEBUG;
}
- // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options.
- // Try the default flags first and if compilation fails, try some alternatives.
+ // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders
+ // when it would otherwise pass with alternative options. Try the default flags first and if
+ // compilation fails, try some alternatives.
std::vector<CompileConfig> configs;
- configs.push_back(CompileConfig(flags, "default" ));
- configs.push_back(CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control" ));
+ configs.push_back(CompileConfig(flags, "default"));
+ configs.push_back(CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control"));
configs.push_back(CompileConfig(flags | D3DCOMPILE_PREFER_FLOW_CONTROL, "prefer flow control"));
- ID3DBlob *binary = NULL;
+ ID3DBlob *binary = nullptr;
std::string debugInfo;
- gl::Error error = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, NULL, &binary, &debugInfo);
+ gl::Error error = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, nullptr,
+ &binary, &debugInfo);
if (error.isError())
{
return error;
}
- // It's possible that binary is NULL if the compiler failed in all configurations. Set the executable to NULL
- // and return GL_NO_ERROR to signify that there was a link error but the internal state is still OK.
+ // It's possible that binary is NULL if the compiler failed in all configurations. Set the
+ // executable to NULL and return GL_NO_ERROR to signify that there was a link error but the
+ // internal state is still OK.
if (!binary)
{
- *outExectuable = NULL;
- return gl::Error(GL_NO_ERROR);
+ *outExectuable = nullptr;
+ return gl::NoError();
}
- error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
- streamOutVaryings, separatedOutputBuffers, outExectuable);
+ error = loadExecutable(reinterpret_cast<const uint8_t *>(binary->GetBufferPointer()),
+ binary->GetBufferSize(), type, streamOutVaryings, separatedOutputBuffers,
+ outExectuable);
SafeRelease(binary);
if (error.isError())
@@ -2588,7 +2818,12 @@ gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog,
(*outExectuable)->appendDebugInfo(debugInfo);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
+}
+
+gl::Error Renderer9::ensureHLSLCompilerInitialized()
+{
+ return mCompiler.ensureInitialized();
}
UniformStorageD3D *Renderer9::createUniformStorage(size_t storageSize)
@@ -2603,7 +2838,7 @@ gl::Error Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *des
D3DPOOL Renderer9::getTexturePool(DWORD usage) const
{
- if (mD3d9Ex != NULL)
+ if (mD3d9Ex != nullptr)
{
return D3DPOOL_DEFAULT;
}
@@ -2618,7 +2853,9 @@ D3DPOOL Renderer9::getTexturePool(DWORD usage) const
return D3DPOOL_DEFAULT;
}
-gl::Error Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged)
+gl::Error Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest,
+ IDirect3DSurface9 *source,
+ bool fromManaged)
{
ASSERT(source && dest);
@@ -2630,28 +2867,34 @@ gl::Error Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurfac
source->GetDesc(&desc);
IDirect3DSurface9 *surf = 0;
- result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL);
+ result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
+ D3DPOOL_SYSTEMMEM, &surf, nullptr);
if (SUCCEEDED(result))
{
- Image9::copyLockableSurfaces(surf, source);
- result = mDevice->UpdateSurface(surf, NULL, dest, NULL);
+ ANGLE_TRY(Image9::copyLockableSurfaces(surf, source));
+ result = mDevice->UpdateSurface(surf, nullptr, dest, nullptr);
SafeRelease(surf);
}
}
else
{
endScene();
- result = mDevice->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
+ result = mDevice->StretchRect(source, nullptr, dest, nullptr, D3DTEXF_NONE);
}
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to blit internal texture, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to blit internal texture, " << gl::FmtHR(result);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
+}
+
+RendererClass Renderer9::getRendererClass() const
+{
+ return RENDERER_D3D9;
}
ImageD3D *Renderer9::createImage()
@@ -2659,18 +2902,34 @@ ImageD3D *Renderer9::createImage()
return new Image9(this);
}
-gl::Error Renderer9::generateMipmap(ImageD3D *dest, ImageD3D *src)
+gl::Error Renderer9::generateMipmap(const gl::Context *context, ImageD3D *dest, ImageD3D *src)
{
Image9 *src9 = GetAs<Image9>(src);
Image9 *dst9 = GetAs<Image9>(dest);
return Image9::generateMipmap(dst9, src9);
}
-gl::Error Renderer9::generateMipmapsUsingD3D(TextureStorage *storage,
- const gl::TextureState &textureState)
+gl::Error Renderer9::generateMipmapUsingD3D(const gl::Context *context,
+ TextureStorage *storage,
+ const gl::TextureState &textureState)
{
UNREACHABLE();
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
+}
+
+gl::Error Renderer9::copyImage(const gl::Context *context,
+ ImageD3D *dest,
+ ImageD3D *source,
+ const gl::Rectangle &sourceRect,
+ const gl::Offset &destOffset,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha)
+{
+ Image9 *dest9 = GetAs<Image9>(dest);
+ Image9 *src9 = GetAs<Image9>(source);
+ return Image9::CopyImage(context, dest9, src9, sourceRect, destOffset, unpackFlipY,
+ unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
}
TextureStorage *Renderer9::createTextureStorage2D(SwapChainD3D *swapChain)
@@ -2679,59 +2938,83 @@ TextureStorage *Renderer9::createTextureStorage2D(SwapChainD3D *swapChain)
return new TextureStorage9_2D(this, swapChain9);
}
-TextureStorage *Renderer9::createTextureStorageEGLImage(EGLImageD3D *eglImage)
+TextureStorage *Renderer9::createTextureStorageEGLImage(EGLImageD3D *eglImage,
+ RenderTargetD3D *renderTargetD3D)
+{
+ return new TextureStorage9_EGLImage(this, eglImage, GetAs<RenderTarget9>(renderTargetD3D));
+}
+
+TextureStorage *Renderer9::createTextureStorageExternal(
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc)
{
- return new TextureStorage9_EGLImage(this, eglImage);
+ UNIMPLEMENTED();
+ return nullptr;
}
-TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly)
+TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ bool hintLevelZeroOnly)
{
return new TextureStorage9_2D(this, internalformat, renderTarget, width, height, levels);
}
-TextureStorage *Renderer9::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly)
+TextureStorage *Renderer9::createTextureStorageCube(GLenum internalformat,
+ bool renderTarget,
+ int size,
+ int levels,
+ bool hintLevelZeroOnly)
{
- return new TextureStorage9_Cube(this, internalformat, renderTarget, size, levels, hintLevelZeroOnly);
+ return new TextureStorage9_Cube(this, internalformat, renderTarget, size, levels,
+ hintLevelZeroOnly);
}
-TextureStorage *Renderer9::createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels)
+TextureStorage *Renderer9::createTextureStorage3D(GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels)
{
// 3D textures are not supported by the D3D9 backend.
UNREACHABLE();
- return NULL;
+ return nullptr;
}
-TextureStorage *Renderer9::createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels)
+TextureStorage *Renderer9::createTextureStorage2DArray(GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels)
{
// 2D array textures are not supported by the D3D9 backend.
UNREACHABLE();
- return NULL;
+ return nullptr;
}
-TextureImpl *Renderer9::createTexture(GLenum target)
+TextureStorage *Renderer9::createTextureStorage2DMultisample(GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ int samples,
+ bool fixedSampleLocations)
{
- switch(target)
- {
- case GL_TEXTURE_2D: return new TextureD3D_2D(this);
- case GL_TEXTURE_CUBE_MAP: return new TextureD3D_Cube(this);
- default: UNREACHABLE();
- }
+ // 2D multisampled textures are not supported by the D3D9 backend.
+ UNREACHABLE();
return NULL;
}
-RenderbufferImpl *Renderer9::createRenderbuffer()
-{
- RenderbufferD3D *renderbuffer = new RenderbufferD3D(this);
- return renderbuffer;
-}
-
bool Renderer9::getLUID(LUID *adapterLuid) const
{
adapterLuid->HighPart = 0;
- adapterLuid->LowPart = 0;
+ adapterLuid->LowPart = 0;
if (mD3d9Ex)
{
@@ -2752,6 +3035,40 @@ GLenum Renderer9::getVertexComponentType(gl::VertexFormatType vertexFormatType)
return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormatType).componentType;
}
+gl::ErrorOrResult<unsigned int> Renderer9::getVertexSpaceRequired(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ GLsizei count,
+ GLsizei instances) const
+{
+ if (!attrib.enabled)
+ {
+ return 16u;
+ }
+
+ gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, GL_FLOAT);
+ const d3d9::VertexFormat &d3d9VertexInfo =
+ d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormatType);
+
+ unsigned int elementCount = 0;
+ const unsigned int divisor = binding.getDivisor();
+ if (instances == 0 || divisor == 0)
+ {
+ elementCount = static_cast<unsigned int>(count);
+ }
+ else
+ {
+ // Round up to divisor, if possible
+ elementCount = UnsignedCeilDivide(static_cast<unsigned int>(instances), divisor);
+ }
+
+ if (d3d9VertexInfo.outputElementSize > std::numeric_limits<unsigned int>::max() / elementCount)
+ {
+ return gl::OutOfMemory() << "New vertex buffer size would result in an overflow.";
+ }
+
+ return static_cast<unsigned int>(d3d9VertexInfo.outputElementSize) * elementCount;
+}
+
void Renderer9::generateCaps(gl::Caps *outCaps,
gl::TextureCapsMap *outTextureCaps,
gl::Extensions *outExtensions,
@@ -2761,31 +3078,11 @@ void Renderer9::generateCaps(gl::Caps *outCaps,
outExtensions, outLimitations);
}
-WorkaroundsD3D Renderer9::generateWorkarounds() const
+angle::WorkaroundsD3D Renderer9::generateWorkarounds() const
{
return d3d9::GenerateWorkarounds();
}
-void Renderer9::createAnnotator()
-{
- mAnnotator = new DebugAnnotator9();
-}
-
-gl::Error Renderer9::clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd)
-{
- // TODO(jmadill): faster way?
- for (size_t samplerIndex = rangeStart; samplerIndex < rangeEnd; samplerIndex++)
- {
- gl::Error error = setTexture(samplerType, static_cast<int>(samplerIndex), nullptr);
- if (error.isError())
- {
- return error;
- }
- }
-
- return gl::Error(GL_NO_ERROR);
-}
-
egl::Error Renderer9::getEGLDevice(DeviceImpl **device)
{
if (mEGLDevice == nullptr)
@@ -2803,14 +3100,211 @@ egl::Error Renderer9::getEGLDevice(DeviceImpl **device)
}
*device = static_cast<DeviceImpl *>(mEGLDevice);
- return egl::Error(EGL_SUCCESS);
+ return egl::NoError();
}
Renderer9::CurSamplerState::CurSamplerState()
- : forceSet(true),
- baseLevel(std::numeric_limits<size_t>::max()),
- samplerState()
+ : forceSet(true), baseLevel(std::numeric_limits<size_t>::max()), samplerState()
+{
+}
+
+gl::Error Renderer9::genericDrawElements(const gl::Context *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei instances)
+{
+ const auto &data = context->getContextState();
+ gl::Program *program = context->getGLState().getProgram();
+ ASSERT(program != nullptr);
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+ bool usesPointSize = programD3D->usesPointSize();
+
+ programD3D->updateSamplerMapping();
+
+ if (!applyPrimitiveType(mode, count, usesPointSize))
+ {
+ return gl::NoError();
+ }
+
+ ANGLE_TRY(updateState(context, mode));
+ ANGLE_TRY(applyTextures(context));
+ ANGLE_TRY(applyShaders(context, mode));
+
+ if (!skipDraw(data.getState(), mode))
+ {
+ ANGLE_TRY(drawElementsImpl(context, mode, count, type, indices, instances));
+ }
+
+ return gl::NoError();
+}
+
+gl::Error Renderer9::genericDrawArrays(const gl::Context *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instances)
+{
+ gl::Program *program = context->getGLState().getProgram();
+ ASSERT(program != nullptr);
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+ bool usesPointSize = programD3D->usesPointSize();
+
+ programD3D->updateSamplerMapping();
+
+ if (!applyPrimitiveType(mode, count, usesPointSize))
+ {
+ return gl::NoError();
+ }
+
+ ANGLE_TRY(updateState(context, mode));
+ ANGLE_TRY(applyVertexBuffer(context, mode, first, count, instances, nullptr));
+ ANGLE_TRY(applyTextures(context));
+ ANGLE_TRY(applyShaders(context, mode));
+
+ if (!skipDraw(context->getGLState(), mode))
+ {
+ ANGLE_TRY(drawArraysImpl(context, mode, first, count, instances));
+ }
+
+ return gl::NoError();
+}
+
+FramebufferImpl *Renderer9::createDefaultFramebuffer(const gl::FramebufferState &state)
{
+ return new Framebuffer9(state, this);
}
+gl::Version Renderer9::getMaxSupportedESVersion() const
+{
+ return gl::Version(2, 0);
+}
+
+gl::Error Renderer9::clearRenderTarget(RenderTargetD3D *renderTarget,
+ const gl::ColorF &clearColorValue,
+ const float clearDepthValue,
+ const unsigned int clearStencilValue)
+{
+ D3DCOLOR color =
+ D3DCOLOR_ARGB(gl::unorm<8>(clearColorValue.alpha), gl::unorm<8>(clearColorValue.red),
+ gl::unorm<8>(clearColorValue.green), gl::unorm<8>(clearColorValue.blue));
+ float depth = clearDepthValue;
+ DWORD stencil = clearStencilValue & 0x000000FF;
+
+ unsigned int renderTargetSerial = renderTarget->getSerial();
+ RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTarget);
+ IDirect3DSurface9 *renderTargetSurface = renderTarget9->getSurface();
+ ASSERT(renderTargetSurface);
+
+ DWORD dxClearFlags = 0;
+
+ const gl::InternalFormat &internalFormatInfo =
+ gl::GetSizedInternalFormatInfo(renderTarget->getInternalFormat());
+ if (internalFormatInfo.depthBits > 0 || internalFormatInfo.stencilBits > 0)
+ {
+ dxClearFlags = D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL;
+ if (mAppliedDepthStencilSerial != renderTargetSerial)
+ {
+ mDevice->SetDepthStencilSurface(renderTargetSurface);
+ }
+ }
+ else
+ {
+ dxClearFlags = D3DCLEAR_TARGET;
+ if (mAppliedRenderTargetSerial != renderTargetSerial)
+ {
+ mDevice->SetRenderTarget(0, renderTargetSurface);
+ }
+ }
+ SafeRelease(renderTargetSurface);
+
+ D3DVIEWPORT9 viewport;
+ viewport.X = 0;
+ viewport.Y = 0;
+ viewport.Width = renderTarget->getWidth();
+ viewport.Height = renderTarget->getHeight();
+ mDevice->SetViewport(&viewport);
+
+ mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
+
+ mDevice->Clear(0, nullptr, dxClearFlags, color, depth, stencil);
+
+ markAllStateDirty();
+
+ return gl::NoError();
}
+
+bool Renderer9::canSelectViewInVertexShader() const
+{
+ return false;
+}
+
+// For each Direct3D sampler of either the pixel or vertex stage,
+// looks up the corresponding OpenGL texture image unit and texture type,
+// and sets the texture and its addressing/filtering state (or NULL when inactive).
+// Sampler mapping needs to be up-to-date on the program object before this is called.
+gl::Error Renderer9::applyTextures(const gl::Context *context, gl::SamplerType shaderType)
+{
+ const auto &glState = context->getGLState();
+ const auto &caps = context->getCaps();
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
+
+ ASSERT(!programD3D->isSamplerMappingDirty());
+
+ // TODO(jmadill): Use the Program's sampler bindings.
+ const auto &completeTextures = glState.getCompleteTextureCache();
+
+ unsigned int samplerRange = programD3D->getUsedSamplerRange(shaderType);
+ for (unsigned int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
+ {
+ GLint textureUnit = programD3D->getSamplerMapping(shaderType, samplerIndex, caps);
+ ASSERT(textureUnit != -1);
+ gl::Texture *texture = completeTextures[textureUnit];
+
+ // A nullptr texture indicates incomplete.
+ if (texture)
+ {
+ gl::Sampler *samplerObject = glState.getSampler(textureUnit);
+
+ const gl::SamplerState &samplerState =
+ samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState();
+
+ ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, texture, samplerState));
+ ANGLE_TRY(setTexture(context, shaderType, samplerIndex, texture));
+ }
+ else
+ {
+ GLenum textureType = programD3D->getSamplerTextureType(shaderType, samplerIndex);
+
+ // Texture is not sampler complete or it is in use by the framebuffer. Bind the
+ // incomplete texture.
+ gl::Texture *incompleteTexture = nullptr;
+ ANGLE_TRY(getIncompleteTexture(context, textureType, &incompleteTexture));
+ ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, incompleteTexture,
+ incompleteTexture->getSamplerState()));
+ ANGLE_TRY(setTexture(context, shaderType, samplerIndex, incompleteTexture));
+ }
+ }
+
+ // Set all the remaining textures to NULL
+ size_t samplerCount = (shaderType == gl::SAMPLER_PIXEL) ? caps.maxTextureImageUnits
+ : caps.maxVertexTextureImageUnits;
+
+ // TODO(jmadill): faster way?
+ for (size_t samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++)
+ {
+ ANGLE_TRY(setTexture(context, shaderType, static_cast<int>(samplerIndex), nullptr));
+ }
+
+ return gl::NoError();
+}
+
+gl::Error Renderer9::applyTextures(const gl::Context *context)
+{
+ ANGLE_TRY(applyTextures(context, gl::SAMPLER_VERTEX));
+ ANGLE_TRY(applyTextures(context, gl::SAMPLER_PIXEL));
+ return gl::NoError();
+}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
index a0dfecb02e..9ddee45f0f 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
@@ -12,12 +12,13 @@
#include "common/angleutils.h"
#include "common/mathutil.h"
#include "libANGLE/renderer/d3d/HLSLCompiler.h"
-#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h"
#include "libANGLE/renderer/d3d/d3d9/ShaderCache.h"
-#include "libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h"
#include "libANGLE/renderer/d3d/d3d9/StateManager9.h"
+#include "libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h"
+#include "libANGLE/renderer/driver_utils.h"
namespace gl
{
@@ -32,6 +33,7 @@ class AttributeMap;
namespace rx
{
class Blit9;
+class Context9;
class IndexDataManager;
class ProgramD3D;
class StreamingIndexBufferInterface;
@@ -65,184 +67,270 @@ class Renderer9 : public RendererD3D
{
public:
explicit Renderer9(egl::Display *display);
- virtual ~Renderer9();
+ ~Renderer9() override;
egl::Error initialize() override;
- virtual bool resetDevice();
+ bool resetDevice() override;
- egl::ConfigSet generateConfigs() const override;
+ egl::ConfigSet generateConfigs() override;
void generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const override;
void startScene();
void endScene();
- gl::Error flush() override;
- gl::Error finish() override;
+ gl::Error flush();
+ gl::Error finish();
- SwapChainD3D *createSwapChain(NativeWindow nativeWindow,
+ bool isValidNativeWindow(EGLNativeWindowType window) const override;
+ NativeWindowD3D *createNativeWindow(EGLNativeWindowType window,
+ const egl::Config *config,
+ const egl::AttributeMap &attribs) const override;
+
+ SwapChainD3D *createSwapChain(NativeWindowD3D *nativeWindow,
HANDLE shareHandle,
+ IUnknown *d3dTexture,
GLenum backBufferFormat,
GLenum depthBufferFormat,
- EGLint orientation) override;
-
- CompilerImpl *createCompiler() override;
+ EGLint orientation,
+ EGLint samples) override;
+ egl::Error getD3DTextureInfo(const egl::Config *configuration,
+ IUnknown *d3dTexture,
+ EGLint *width,
+ EGLint *height,
+ GLenum *fboFormat) const override;
+ egl::Error validateShareHandle(const egl::Config *config,
+ HANDLE shareHandle,
+ const egl::AttributeMap &attribs) const override;
+
+ ContextImpl *createContext(const gl::ContextState &state) override;
gl::Error allocateEventQuery(IDirect3DQuery9 **outQuery);
- void freeEventQuery(IDirect3DQuery9* query);
+ void freeEventQuery(IDirect3DQuery9 *query);
// resource creation
- gl::Error createVertexShader(const DWORD *function, size_t length, IDirect3DVertexShader9 **outShader);
- gl::Error createPixelShader(const DWORD *function, size_t length, IDirect3DPixelShader9 **outShader);
+ gl::Error createVertexShader(const DWORD *function,
+ size_t length,
+ IDirect3DVertexShader9 **outShader);
+ gl::Error createPixelShader(const DWORD *function,
+ size_t length,
+ IDirect3DPixelShader9 **outShader);
HRESULT createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer);
- HRESULT createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer);
- virtual gl::Error generateSwizzle(gl::Texture *texture);
- virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler);
- virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture);
-
- gl::Error setUniformBuffers(const gl::Data &data,
- const std::vector<GLint> &vertexUniformBuffers,
- const std::vector<GLint> &fragmentUniformBuffers) override;
-
- gl::Error updateState(const gl::Data &data, GLenum drawMode) override;
+ HRESULT createIndexBuffer(UINT Length,
+ DWORD Usage,
+ D3DFORMAT Format,
+ IDirect3DIndexBuffer9 **ppIndexBuffer);
+ gl::Error setSamplerState(const gl::Context *context,
+ gl::SamplerType type,
+ int index,
+ gl::Texture *texture,
+ const gl::SamplerState &sampler);
+ gl::Error setTexture(const gl::Context *context,
+ gl::SamplerType type,
+ int index,
+ gl::Texture *texture);
+
+ gl::Error updateState(const gl::Context *context, GLenum drawMode);
void setScissorRectangle(const gl::Rectangle &scissor, bool enabled);
- void setViewport(const gl::Caps *caps,
- const gl::Rectangle &viewport,
+ void setViewport(const gl::Rectangle &viewport,
float zNear,
float zFar,
GLenum drawMode,
GLenum frontFace,
bool ignoreViewport);
- gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) override;
- gl::Error applyRenderTarget(const gl::FramebufferAttachment *colorAttachment,
+ gl::Error applyRenderTarget(const gl::Context *context, const gl::Framebuffer *frameBuffer);
+ gl::Error applyRenderTarget(const gl::Context *context,
+ const gl::FramebufferAttachment *colorAttachment,
const gl::FramebufferAttachment *depthStencilAttachment);
- gl::Error applyUniforms(const ProgramD3D &programD3D,
- GLenum drawMode,
- const std::vector<D3DUniform *> &uniformArray) override;
- virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize);
- virtual gl::Error applyVertexBuffer(const gl::State &state,
- GLenum mode,
- GLint first,
- GLsizei count,
- GLsizei instances,
- TranslatedIndexData *indexInfo);
- gl::Error applyIndexBuffer(const gl::Data &data,
- const GLvoid *indices,
+ gl::Error applyUniforms(ProgramD3D *programD3D);
+ bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize);
+ gl::Error applyVertexBuffer(const gl::Context *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instances,
+ TranslatedIndexData *indexInfo);
+ gl::Error applyIndexBuffer(const gl::Context *context,
+ const void *indices,
GLsizei count,
GLenum mode,
GLenum type,
- TranslatedIndexData *indexInfo) override;
+ TranslatedIndexData *indexInfo);
- void applyTransformFeedbackBuffers(const gl::State &state) override;
-
- gl::Error clear(const ClearParameters &clearParams,
+ gl::Error clear(const gl::Context *context,
+ const ClearParameters &clearParams,
const gl::FramebufferAttachment *colorBuffer,
const gl::FramebufferAttachment *depthStencilBuffer);
- virtual void markAllStateDirty();
+ void markAllStateDirty();
// lost device
bool testDeviceLost() override;
bool testDeviceResettable() override;
VendorID getVendorId() const;
- std::string getRendererDescription() const override;
+ std::string getRendererDescription() const;
DeviceIdentifier getAdapterIdentifier() const override;
IDirect3DDevice9 *getDevice() { return mDevice; }
void *getD3DDevice() override;
- virtual unsigned int getReservedVertexUniformVectors() const;
- virtual unsigned int getReservedFragmentUniformVectors() const;
- virtual unsigned int getReservedVertexUniformBuffers() const;
- virtual unsigned int getReservedFragmentUniformBuffers() const;
+ unsigned int getReservedVertexUniformVectors() const;
+ unsigned int getReservedFragmentUniformVectors() const;
bool getShareHandleSupport() const;
- virtual int getMajorShaderModel() const;
+ int getMajorShaderModel() const override;
int getMinorShaderModel() const override;
std::string getShaderModelSuffix() const override;
DWORD getCapsDeclTypes() const;
// Pixel operations
- virtual gl::Error copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- const gl::Offset &destOffset, TextureStorage *storage, GLint level);
- virtual gl::Error copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level);
- virtual gl::Error copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- const gl::Offset &destOffset, TextureStorage *storage, GLint level);
- virtual gl::Error copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- const gl::Offset &destOffset, TextureStorage *storage, GLint level);
+ gl::Error copyImage2D(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level) override;
+ gl::Error copyImageCube(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLenum target,
+ GLint level) override;
+ gl::Error copyImage3D(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level) override;
+ gl::Error copyImage2DArray(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level) override;
+
+ gl::Error copyTexture(const gl::Context *context,
+ const gl::Texture *source,
+ GLint sourceLevel,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLenum destTarget,
+ GLint destLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha) override;
+ gl::Error copyCompressedTexture(const gl::Context *context,
+ const gl::Texture *source,
+ GLint sourceLevel,
+ TextureStorage *storage,
+ GLint destLevel) override;
// RenderTarget creation
- virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT);
+ gl::Error createRenderTarget(int width,
+ int height,
+ GLenum format,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
gl::Error createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) override;
- // Framebuffer creation
- FramebufferImpl *createFramebuffer(const gl::Framebuffer::Data &data) override;
-
- // Shader creation
- ShaderImpl *createShader(const gl::Shader::Data &data) override;
- ProgramImpl *createProgram(const gl::Program::Data &data) override;
-
// Shader operations
- gl::Error loadExecutable(const void *function,
+ gl::Error loadExecutable(const uint8_t *function,
size_t length,
- ShaderType type,
+ gl::ShaderType type,
const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers,
ShaderExecutableD3D **outExecutable) override;
gl::Error compileToExecutable(gl::InfoLog &infoLog,
const std::string &shaderHLSL,
- ShaderType type,
+ gl::ShaderType type,
const std::vector<D3DVarying> &streamOutVaryings,
bool separatedOutputBuffers,
- const D3DCompilerWorkarounds &workarounds,
+ const angle::CompilerWorkaroundsD3D &workarounds,
ShaderExecutableD3D **outExectuable) override;
+ gl::Error ensureHLSLCompilerInitialized() override;
+
UniformStorageD3D *createUniformStorage(size_t storageSize) override;
// Image operations
- virtual ImageD3D *createImage();
- gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override;
- gl::Error generateMipmapsUsingD3D(TextureStorage *storage,
- const gl::TextureState &textureState) override;
- virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain);
- TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage) override;
- virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly);
- virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly);
- virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels);
- virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels);
-
- // Texture creation
- virtual TextureImpl *createTexture(GLenum target);
-
- // Renderbuffer creation
- virtual RenderbufferImpl *createRenderbuffer();
+ ImageD3D *createImage() override;
+ gl::Error generateMipmap(const gl::Context *context, ImageD3D *dest, ImageD3D *source) override;
+ gl::Error generateMipmapUsingD3D(const gl::Context *context,
+ TextureStorage *storage,
+ const gl::TextureState &textureState) override;
+ gl::Error copyImage(const gl::Context *context,
+ ImageD3D *dest,
+ ImageD3D *source,
+ const gl::Rectangle &sourceRect,
+ const gl::Offset &destOffset,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha) override;
+ TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain) override;
+ TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage,
+ RenderTargetD3D *renderTargetD3D) override;
+ TextureStorage *createTextureStorageExternal(
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc) override;
+ TextureStorage *createTextureStorage2D(GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ bool hintLevelZeroOnly) override;
+ TextureStorage *createTextureStorageCube(GLenum internalformat,
+ bool renderTarget,
+ int size,
+ int levels,
+ bool hintLevelZeroOnly) override;
+ TextureStorage *createTextureStorage3D(GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels) override;
+ TextureStorage *createTextureStorage2DArray(GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels) override;
+
+ TextureStorage *createTextureStorage2DMultisample(GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ int samples,
+ bool fixedSampleLocations) override;
// Buffer creation
- virtual BufferImpl *createBuffer();
- virtual VertexBuffer *createVertexBuffer();
- virtual IndexBuffer *createIndexBuffer();
+ VertexBuffer *createVertexBuffer() override;
+ IndexBuffer *createIndexBuffer() override;
- // Vertex Array creation
- VertexArrayImpl *createVertexArray(const gl::VertexArray::Data &data) override;
-
- // Query and Fence creation
- virtual QueryImpl *createQuery(GLenum type);
- virtual FenceNVImpl *createFenceNV();
- virtual FenceSyncImpl *createFenceSync();
-
- // Transform Feedback creation
- virtual TransformFeedbackImpl* createTransformFeedback();
+ // Stream Creation
+ StreamProducerImpl *createStreamProducerD3DTextureNV12(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs) override;
// Buffer-to-texture and Texture-to-buffer copies
- virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const;
- virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget,
- GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea);
-
- void syncState(const gl::State &state, const gl::State::DirtyBits &bitmask) override;
+ bool supportsFastCopyBufferToTexture(GLenum internalFormat) const override;
+ gl::Error fastCopyBufferToTexture(const gl::Context *context,
+ const gl::PixelUnpackState &unpack,
+ unsigned int offset,
+ RenderTargetD3D *destRenderTarget,
+ GLenum destinationFormat,
+ GLenum sourcePixelsType,
+ const gl::Box &destArea) override;
// D3D9-renderer specific methods
gl::Error boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest);
@@ -250,42 +338,82 @@ class Renderer9 : public RendererD3D
D3DPOOL getTexturePool(DWORD usage) const;
bool getLUID(LUID *adapterLuid) const override;
- VertexConversionType getVertexConversionType(gl::VertexFormatType vertexFormatType) const override;
+ VertexConversionType getVertexConversionType(
+ gl::VertexFormatType vertexFormatType) const override;
GLenum getVertexComponentType(gl::VertexFormatType vertexFormatType) const override;
- gl::Error copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged);
+ // Warning: you should ensure binding really matches attrib.bindingIndex before using this
+ // function.
+ gl::ErrorOrResult<unsigned int> getVertexSpaceRequired(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ GLsizei count,
+ GLsizei instances) const override;
- RendererClass getRendererClass() const override { return RENDERER_D3D9; }
+ gl::Error copyToRenderTarget(IDirect3DSurface9 *dest,
+ IDirect3DSurface9 *source,
+ bool fromManaged);
+
+ RendererClass getRendererClass() const override;
D3DDEVTYPE getD3D9DeviceType() const { return mDeviceType; }
egl::Error getEGLDevice(DeviceImpl **device) override;
- protected:
- void createAnnotator() override;
- gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) override;
- gl::Error applyShadersImpl(const gl::Data &data, GLenum drawMode) override;
+ StateManager9 *getStateManager() { return &mStateManager; }
+
+ gl::Error genericDrawArrays(const gl::Context *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instances);
+
+ gl::Error genericDrawElements(const gl::Context *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei instances);
+
+ // Necessary hack for default framebuffers in D3D.
+ FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
+
+ DebugAnnotator9 *getAnnotator() { return &mAnnotator; }
+
+ gl::Version getMaxSupportedESVersion() const override;
+
+ gl::Error clearRenderTarget(RenderTargetD3D *renderTarget,
+ const gl::ColorF &clearColorValue,
+ const float clearDepthValue,
+ const unsigned int clearStencilValue) override;
+
+ bool canSelectViewInVertexShader() const override;
private:
- gl::Error drawArraysImpl(const gl::Data &data,
+ gl::Error drawArraysImpl(const gl::Context *context,
GLenum mode,
+ GLint startVertex,
GLsizei count,
- GLsizei instances) override;
- gl::Error drawElementsImpl(const gl::Data &data,
- const TranslatedIndexData &indexInfo,
+ GLsizei instances);
+ gl::Error drawElementsImpl(const gl::Context *context,
GLenum mode,
GLsizei count,
GLenum type,
- const GLvoid *indices,
- GLsizei instances) override;
+ const void *indices,
+ GLsizei instances);
- void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps,
+ gl::Error applyShaders(const gl::Context *context, GLenum drawMode);
+
+ gl::Error applyTextures(const gl::Context *context);
+ gl::Error applyTextures(const gl::Context *context, gl::SamplerType shaderType);
+
+ void generateCaps(gl::Caps *outCaps,
+ gl::TextureCapsMap *outTextureCaps,
gl::Extensions *outExtensions,
gl::Limitations *outLimitations) const override;
- WorkaroundsD3D generateWorkarounds() const override;
+ angle::WorkaroundsD3D generateWorkarounds() const override;
- gl::Error setBlendDepthRasterStates(const gl::Data &glData, GLenum drawMode);
+ gl::Error setBlendDepthRasterStates(const gl::Context *context, GLenum drawMode);
void release();
@@ -293,18 +421,30 @@ class Renderer9 : public RendererD3D
void applyUniformniv(const D3DUniform *targetUniform, const GLint *v);
void applyUniformnbv(const D3DUniform *targetUniform, const GLint *v);
- gl::Error drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer);
- gl::Error drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer);
+ gl::Error drawLineLoop(const gl::Context *context,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ int minIndex,
+ gl::Buffer *elementArrayBuffer);
+ gl::Error drawIndexedPoints(const gl::Context *context,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ int minIndex,
+ gl::Buffer *elementArrayBuffer);
gl::Error getCountingIB(size_t count, StaticIndexBufferInterface **outIB);
- gl::Error getNullColorbuffer(const gl::FramebufferAttachment *depthbuffer, const gl::FramebufferAttachment **outColorBuffer);
+ gl::Error getNullColorbuffer(const gl::Context *context,
+ const gl::FramebufferAttachment *depthbuffer,
+ const gl::FramebufferAttachment **outColorBuffer);
D3DPOOL getBufferPool(DWORD usage) const;
HMODULE mD3d9Module;
- void initializeDevice();
+ egl::Error initializeDevice();
D3DPRESENT_PARAMETERS getDefaultPresentParameters();
void releaseDeviceResources();
@@ -314,7 +454,7 @@ class Renderer9 : public RendererD3D
UINT mAdapter;
D3DDEVTYPE mDeviceType;
- IDirect3D9 *mD3d9; // Always valid after successful initialization.
+ IDirect3D9 *mD3d9; // Always valid after successful initialization.
IDirect3D9Ex *mD3d9Ex; // Might be null if D3D9Ex is not supported.
IDirect3DDevice9 *mDevice;
IDirect3DDevice9Ex *mDeviceEx; // Might be null if D3D9Ex is not supported.
@@ -368,7 +508,7 @@ class Renderer9 : public RendererD3D
unsigned int mAppliedProgramSerial;
// A pool of event queries that are currently unused.
- std::vector<IDirect3DQuery9*> mEventQueryPool;
+ std::vector<IDirect3DQuery9 *> mEventQueryPool;
VertexShaderCache mVertexShaderCache;
PixelShaderCache mPixelShaderCache;
@@ -379,7 +519,10 @@ class Renderer9 : public RendererD3D
StreamingIndexBufferInterface *mLineLoopIB;
StaticIndexBufferInterface *mCountingIB;
- enum { NUM_NULL_COLORBUFFER_CACHE_ENTRIES = 12 };
+ enum
+ {
+ NUM_NULL_COLORBUFFER_CACHE_ENTRIES = 12
+ };
struct NullColorbufferCacheEntry
{
UINT lruCount;
@@ -390,7 +533,11 @@ class Renderer9 : public RendererD3D
UINT mMaxNullColorbufferLRU;
DeviceD3D *mEGLDevice;
+ std::vector<TranslatedAttribute> mTranslatedAttribCache;
+
+ DebugAnnotator9 mAnnotator;
};
-}
-#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERER9_H_
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERER9_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h
index cf831c62fa..399770dd8d 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h
@@ -24,9 +24,7 @@ template <typename ShaderObject>
class ShaderCache : angle::NonCopyable
{
public:
- ShaderCache() : mDevice(NULL)
- {
- }
+ ShaderCache() : mDevice(nullptr) {}
~ShaderCache()
{
@@ -47,14 +45,14 @@ class ShaderCache : angle::NonCopyable
{
it->second->AddRef();
*outShaderObject = it->second;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
ShaderObject *shader;
HRESULT result = createShader(function, &shader);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create shader, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to create shader, " << gl::FmtHR(result);
}
// Random eviction policy.
@@ -68,7 +66,7 @@ class ShaderCache : angle::NonCopyable
mMap[key] = shader;
*outShaderObject = shader;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
void clear()
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp
index 28a486056b..362c6c60a3 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp
@@ -18,14 +18,14 @@ ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirec
: ShaderExecutableD3D(function, length)
{
mPixelExecutable = executable;
- mVertexExecutable = NULL;
+ mVertexExecutable = nullptr;
}
ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable)
: ShaderExecutableD3D(function, length)
{
mVertexExecutable = executable;
- mPixelExecutable = NULL;
+ mPixelExecutable = nullptr;
}
ShaderExecutable9::~ShaderExecutable9()
@@ -44,4 +44,4 @@ IDirect3DPixelShader9 *ShaderExecutable9::getPixelShader() const
return mPixelExecutable;
}
-} \ No newline at end of file
+}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h
index 382a68c820..0b6b87947e 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h
@@ -20,7 +20,7 @@ class ShaderExecutable9 : public ShaderExecutableD3D
public:
ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable);
ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable);
- virtual ~ShaderExecutable9();
+ ~ShaderExecutable9() override;
IDirect3DPixelShader9 *getPixelShader() const;
IDirect3DVertexShader9 *getVertexShader() const;
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp
index c4c600aedb..a3bdc14efb 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp
@@ -7,7 +7,7 @@
// StateManager9.cpp: Defines a class for caching D3D9 state
#include "libANGLE/renderer/d3d/d3d9/StateManager9.h"
-#include "common/BitSetIterator.h"
+#include "common/bitset_utils.h"
#include "common/utilities.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
@@ -18,7 +18,8 @@ namespace rx
{
StateManager9::StateManager9(Renderer9 *renderer9)
- : mCurBlendState(),
+ : mUsingZeroColorMaskWorkaround(false),
+ mCurBlendState(),
mCurBlendColor(0, 0, 0, 0),
mCurSampleMask(0),
mCurRasterState(),
@@ -67,6 +68,11 @@ StateManager9::~StateManager9()
{
}
+void StateManager9::initialize()
+{
+ mUsingZeroColorMaskWorkaround = IsAMD(mRenderer9->getVendorId());
+}
+
void StateManager9::forceSetBlendState()
{
mDirtyBits |= mBlendStateDirtyBits;
@@ -114,7 +120,7 @@ void StateManager9::syncState(const gl::State &state, const gl::State::DirtyBits
return;
}
- for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
+ for (auto dirtyBit : dirtyBits)
{
switch (dirtyBit)
{
@@ -125,6 +131,12 @@ void StateManager9::syncState(const gl::State &state, const gl::State::DirtyBits
// BlendColor and funcs and equations has to be set if blend is enabled
mDirtyBits.set(DIRTY_BIT_BLEND_COLOR);
mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS);
+
+ // The color mask may have to be updated if the blend state changes
+ if (mUsingZeroColorMaskWorkaround)
+ {
+ mDirtyBits.set(DIRTY_BIT_COLOR_MASK);
+ }
}
break;
case gl::State::DIRTY_BIT_BLEND_FUNCS:
@@ -138,6 +150,12 @@ void StateManager9::syncState(const gl::State &state, const gl::State::DirtyBits
mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS);
// BlendColor depends on the values of blend funcs
mDirtyBits.set(DIRTY_BIT_BLEND_COLOR);
+
+ // The color mask may have to be updated if the blend funcs change
+ if (mUsingZeroColorMaskWorkaround)
+ {
+ mDirtyBits.set(DIRTY_BIT_COLOR_MASK);
+ }
}
break;
}
@@ -148,6 +166,12 @@ void StateManager9::syncState(const gl::State &state, const gl::State::DirtyBits
blendState.blendEquationAlpha != mCurBlendState.blendEquationAlpha)
{
mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS);
+
+ // The color mask may have to be updated if the blend funcs change
+ if (mUsingZeroColorMaskWorkaround)
+ {
+ mDirtyBits.set(DIRTY_BIT_COLOR_MASK);
+ }
}
break;
}
@@ -167,6 +191,14 @@ void StateManager9::syncState(const gl::State &state, const gl::State::DirtyBits
blendState.colorMaskAlpha != mCurBlendState.colorMaskAlpha)
{
mDirtyBits.set(DIRTY_BIT_COLOR_MASK);
+
+ // The color mask can cause the blend state to get out of sync when using the
+ // zero color mask workaround
+ if (mUsingZeroColorMaskWorkaround)
+ {
+ mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED);
+ mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS);
+ }
}
break;
}
@@ -364,7 +396,7 @@ gl::Error StateManager9::setBlendDepthRasterStates(const gl::State &glState,
mCurFrontFaceCCW = frontFaceCCW;
}
- for (auto dirtyBit : angle::IterateBitSet(mDirtyBits))
+ for (auto dirtyBit : mDirtyBits)
{
switch (dirtyBit)
{
@@ -438,11 +470,10 @@ gl::Error StateManager9::setBlendDepthRasterStates(const gl::State &glState,
setSampleMask(sampleMask);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-void StateManager9::setViewportState(const gl::Caps *caps,
- const gl::Rectangle &viewport,
+void StateManager9::setViewportState(const gl::Rectangle &viewport,
float zNear,
float zFar,
GLenum drawMode,
@@ -698,6 +729,7 @@ void StateManager9::setStencilTestEnabled(bool stencilTestEnabled)
if (stencilTestEnabled && mCurStencilSize > 0)
{
mRenderer9->getDevice()->SetRenderState(D3DRS_STENCILENABLE, TRUE);
+ mRenderer9->getDevice()->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
}
else
{
@@ -718,7 +750,7 @@ void StateManager9::setSampleAlphaToCoverage(bool enabled)
{
if (enabled)
{
- FIXME("Sample alpha to coverage is unimplemented.");
+ UNREACHABLE();
}
}
@@ -800,42 +832,52 @@ void StateManager9::setColorMask(const gl::Framebuffer *framebuffer,
bool alpha)
{
// Set the color mask
- bool zeroColorMaskAllowed = mRenderer9->getVendorId() != VENDOR_ID_AMD;
- // Apparently some ATI cards have a bug where a draw with a zero color
- // write mask can cause later draws to have incorrect results. Instead,
- // set a nonzero color write mask but modify the blend state so that no
- // drawing is done.
- // http://code.google.com/p/angleproject/issues/detail?id=169
- const gl::FramebufferAttachment *attachment = framebuffer->getFirstColorbuffer();
- GLenum internalFormat = attachment ? attachment->getInternalFormat() : GL_NONE;
-
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
+ const auto *attachment = framebuffer->getFirstColorbuffer();
+ const auto &format = attachment ? attachment->getFormat() : gl::Format::Invalid();
DWORD colorMask = gl_d3d9::ConvertColorMask(
- formatInfo.redBits > 0 && red, formatInfo.greenBits > 0 && green,
- formatInfo.blueBits > 0 && blue, formatInfo.alphaBits > 0 && alpha);
-
- if (colorMask == 0 && !zeroColorMaskAllowed)
+ format.info->redBits > 0 && red, format.info->greenBits > 0 && green,
+ format.info->blueBits > 0 && blue, format.info->alphaBits > 0 && alpha);
+
+ // Apparently some ATI cards have a bug where a draw with a zero color write mask can cause
+ // later draws to have incorrect results. Instead, set a nonzero color write mask but modify the
+ // blend state so that no drawing is done.
+ // http://anglebug.com/169
+ if (colorMask == 0 && mUsingZeroColorMaskWorkaround)
{
IDirect3DDevice9 *device = mRenderer9->getDevice();
// Enable green channel, but set blending so nothing will be drawn.
device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN);
+
device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
+
+ mCurBlendState.colorMaskRed = false;
+ mCurBlendState.colorMaskGreen = true;
+ mCurBlendState.colorMaskBlue = false;
+ mCurBlendState.colorMaskAlpha = false;
+
+ mCurBlendState.blend = true;
+ mCurBlendState.sourceBlendRGB = GL_ZERO;
+ mCurBlendState.sourceBlendAlpha = GL_ZERO;
+ mCurBlendState.destBlendRGB = GL_ONE;
+ mCurBlendState.destBlendAlpha = GL_ONE;
+ mCurBlendState.blendEquationRGB = GL_FUNC_ADD;
+ mCurBlendState.blendEquationAlpha = GL_FUNC_ADD;
}
else
{
mRenderer9->getDevice()->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask);
- }
- mCurBlendState.colorMaskRed = red;
- mCurBlendState.colorMaskGreen = green;
- mCurBlendState.colorMaskBlue = blue;
- mCurBlendState.colorMaskAlpha = alpha;
+ mCurBlendState.colorMaskRed = red;
+ mCurBlendState.colorMaskGreen = green;
+ mCurBlendState.colorMaskBlue = blue;
+ mCurBlendState.colorMaskAlpha = alpha;
+ }
}
void StateManager9::setSampleMask(unsigned int sampleMask)
@@ -848,7 +890,7 @@ void StateManager9::setSampleMask(unsigned int sampleMask)
mCurSampleMask = sampleMask;
}
-void StateManager9::setCullMode(bool cullFace, GLenum cullMode, GLenum frontFace)
+void StateManager9::setCullMode(bool cullFace, gl::CullFaceMode cullMode, GLenum frontFace)
{
if (cullFace)
{
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h
index d8c1eb9812..63ce17cb1e 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h
@@ -10,7 +10,7 @@
#define LIBANGLE_RENDERER_D3D9_STATEMANAGER9_H_
#include "libANGLE/angletypes.h"
-#include "libANGLE/Data.h"
+#include "libANGLE/ContextState.h"
#include "libANGLE/State.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
@@ -39,12 +39,13 @@ class StateManager9 final : angle::NonCopyable
StateManager9(Renderer9 *renderer9);
~StateManager9();
+ void initialize();
+
void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits);
gl::Error setBlendDepthRasterStates(const gl::State &glState, unsigned int sampleMask);
void setScissorState(const gl::Rectangle &scissor, bool enabled);
- void setViewportState(const gl::Caps *caps,
- const gl::Rectangle &viewport,
+ void setViewportState(const gl::Rectangle &viewport,
float zNear,
float zFar,
GLenum drawMode,
@@ -85,7 +86,7 @@ class StateManager9 final : angle::NonCopyable
void setSampleMask(unsigned int sampleMask);
// Current raster state functions
- void setCullMode(bool cullFace, GLenum cullMode, GLenum frontFace);
+ void setCullMode(bool cullFace, gl::CullFaceMode cullMode, GLenum frontFace);
void setDepthBias(bool polygonOffsetFill,
GLfloat polygonOffsetFactor,
GLfloat polygonOffsetUnits);
@@ -154,7 +155,9 @@ class StateManager9 final : angle::NonCopyable
DIRTY_BIT_MAX
};
- typedef std::bitset<DIRTY_BIT_MAX> DirtyBits;
+ using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
+
+ bool mUsingZeroColorMaskWorkaround;
// Currently applied blend state
gl::BlendState mCurBlendState;
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp
index be6a9c424c..bc81aa18ec 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp
@@ -7,25 +7,29 @@
// SwapChain9.cpp: Implements a back-end specific class for the D3D9 swap chain.
#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
-#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+
+#include "libANGLE/features.h"
#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/NativeWindow9.h"
#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
-#include "libANGLE/features.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
namespace rx
{
SwapChain9::SwapChain9(Renderer9 *renderer,
- NativeWindow nativeWindow,
+ NativeWindow9 *nativeWindow,
HANDLE shareHandle,
+ IUnknown *d3dTexture,
GLenum backBufferFormat,
GLenum depthBufferFormat,
EGLint orientation)
- : SwapChainD3D(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat),
+ : SwapChainD3D(shareHandle, d3dTexture, backBufferFormat, depthBufferFormat),
mRenderer(renderer),
mWidth(-1),
mHeight(-1),
mSwapInterval(-1),
+ mNativeWindow(nativeWindow),
mSwapChain(nullptr),
mBackBuffer(nullptr),
mRenderTarget(nullptr),
@@ -50,9 +54,9 @@ void SwapChain9::release()
SafeRelease(mRenderTarget);
SafeRelease(mOffscreenTexture);
- if (mNativeWindow.getNativeWindow())
+ if (mNativeWindow->getNativeWindow())
{
- mShareHandle = NULL;
+ mShareHandle = nullptr;
}
}
@@ -75,17 +79,20 @@ static DWORD convertInterval(EGLint interval)
#endif
}
-EGLint SwapChain9::resize(int backbufferWidth, int backbufferHeight)
+EGLint SwapChain9::resize(const gl::Context *context, int backbufferWidth, int backbufferHeight)
{
// D3D9 does not support resizing swap chains without recreating them
- return reset(backbufferWidth, backbufferHeight, mSwapInterval);
+ return reset(context, backbufferWidth, backbufferHeight, mSwapInterval);
}
-EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
+EGLint SwapChain9::reset(const gl::Context *context,
+ int backbufferWidth,
+ int backbufferHeight,
+ EGLint swapInterval)
{
IDirect3DDevice9 *device = mRenderer->getDevice();
- if (device == NULL)
+ if (device == nullptr)
{
return EGL_BAD_ACCESS;
}
@@ -103,28 +110,37 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI
SafeRelease(mOffscreenTexture);
SafeRelease(mDepthStencil);
- HANDLE *pShareHandle = NULL;
- if (!mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport())
+ const d3d9::TextureFormat &backBufferd3dFormatInfo =
+ d3d9::GetTextureFormatInfo(mOffscreenRenderTargetFormat);
+ if (mD3DTexture != nullptr)
{
- pShareHandle = &mShareHandle;
+ result = mD3DTexture->QueryInterface(&mOffscreenTexture);
+ ASSERT(SUCCEEDED(result));
}
-
- const d3d9::TextureFormat &backBufferd3dFormatInfo = d3d9::GetTextureFormatInfo(mOffscreenRenderTargetFormat);
- result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET,
- backBufferd3dFormatInfo.texFormat, D3DPOOL_DEFAULT, &mOffscreenTexture,
- pShareHandle);
- if (FAILED(result))
+ else
{
- ERR("Could not create offscreen texture: %08lX", result);
- release();
-
- if (d3d9::isDeviceLostError(result))
+ HANDLE *pShareHandle = nullptr;
+ if (!mNativeWindow->getNativeWindow() && mRenderer->getShareHandleSupport())
{
- return EGL_CONTEXT_LOST;
+ pShareHandle = &mShareHandle;
}
- else
+
+ result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET,
+ backBufferd3dFormatInfo.texFormat, D3DPOOL_DEFAULT,
+ &mOffscreenTexture, pShareHandle);
+ if (FAILED(result))
{
- return EGL_BAD_ALLOC;
+ ERR() << "Could not create offscreen texture, " << gl::FmtHR(result);
+ release();
+
+ if (d3d9::isDeviceLostError(result))
+ {
+ return EGL_CONTEXT_LOST;
+ }
+ else
+ {
+ return EGL_BAD_ALLOC;
+ }
}
}
@@ -163,7 +179,7 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI
// Don't create a swapchain for NULLREF devices
D3DDEVTYPE deviceType = mRenderer->getD3D9DeviceType();
- EGLNativeWindowType window = mNativeWindow.getNativeWindow();
+ EGLNativeWindowType window = mNativeWindow->getNativeWindow();
if (window && deviceType != D3DDEVTYPE_NULLREF)
{
D3DPRESENT_PARAMETERS presentParameters = {0};
@@ -189,7 +205,7 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI
//
// Some non-switchable AMD GPUs / drivers do not respect the source rectangle to Present. Therefore, when the vendor ID
// is not Intel, the back buffer width must be exactly the same width as the window or horizontal scaling will occur.
- if (mRenderer->getVendorId() == VENDOR_ID_INTEL)
+ if (IsIntel(mRenderer->getVendorId()))
{
presentParameters.BackBufferWidth = (presentParameters.BackBufferWidth + 63) / 64 * 64;
}
@@ -200,7 +216,8 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST);
- ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
+ ERR() << "Could not create additional swap chains or offscreen surfaces, "
+ << gl::FmtHR(result);
release();
if (d3d9::isDeviceLostError(result))
@@ -215,20 +232,21 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI
result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
ASSERT(SUCCEEDED(result));
- InvalidateRect(window, NULL, FALSE);
+ InvalidateRect(window, nullptr, FALSE);
}
if (mDepthBufferFormat != GL_NONE)
{
- result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight,
- depthBufferd3dFormatInfo.renderFormat,
- D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, NULL);
+ result = device->CreateDepthStencilSurface(
+ backbufferWidth, backbufferHeight, depthBufferd3dFormatInfo.renderFormat,
+ D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, nullptr);
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL);
- ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
+ ERR() << "Could not create depthstencil surface for new swap chain, "
+ << gl::FmtHR(result);
release();
if (d3d9::isDeviceLostError(result))
@@ -250,7 +268,11 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI
}
// parameters should be validated/clamped by caller
-EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+EGLint SwapChain9::swapRect(const gl::Context *context,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height)
{
if (!mSwapChain)
{
@@ -270,11 +292,11 @@ EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
- device->SetPixelShader(NULL);
- device->SetVertexShader(NULL);
+ device->SetPixelShader(nullptr);
+ device->SetVertexShader(nullptr);
device->SetRenderTarget(0, mBackBuffer);
- device->SetDepthStencilSurface(NULL);
+ device->SetDepthStencilSurface(nullptr);
device->SetTexture(0, mOffscreenTexture);
device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
@@ -313,7 +335,7 @@ EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float));
mRenderer->endScene();
- device->SetTexture(0, NULL);
+ device->SetTexture(0, nullptr);
RECT rect =
{
@@ -321,7 +343,7 @@ EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
static_cast<LONG>(x + width), static_cast<LONG>(mHeight - y)
};
- HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0);
+ HRESULT result = mSwapChain->Present(&rect, &rect, nullptr, nullptr, 0);
mRenderer->markAllStateDirty();
@@ -333,7 +355,7 @@ EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
// On Windows 8 systems, IDirect3DSwapChain9::Present sometimes returns 0x88760873 when the windows is
// in the process of entering/exiting fullscreen. This code doesn't seem to have any documentation. The
// device appears to be ok after emitting this error so simply return a failure to swap.
- if (result == 0x88760873)
+ if (result == static_cast<HRESULT>(0x88760873))
{
return EGL_BAD_MATCH;
}
@@ -395,6 +417,12 @@ void *SwapChain9::getKeyedMutex()
return nullptr;
}
+egl::Error SwapChain9::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
+{
+ UNREACHABLE();
+ return egl::EglBadSurface();
+}
+
void SwapChain9::recreate()
{
if (!mSwapChain)
@@ -403,7 +431,7 @@ void SwapChain9::recreate()
}
IDirect3DDevice9 *device = mRenderer->getDevice();
- if (device == NULL)
+ if (device == nullptr)
{
return;
}
@@ -412,7 +440,7 @@ void SwapChain9::recreate()
HRESULT result = mSwapChain->GetPresentParameters(&presentParameters);
ASSERT(SUCCEEDED(result));
- IDirect3DSwapChain9* newSwapChain = NULL;
+ IDirect3DSwapChain9 *newSwapChain = nullptr;
result = device->CreateAdditionalSwapChain(&presentParameters, &newSwapChain);
if (FAILED(result))
{
@@ -427,4 +455,13 @@ void SwapChain9::recreate()
ASSERT(SUCCEEDED(result));
}
+RenderTargetD3D *SwapChain9::getColorRenderTarget()
+{
+ return &mColorRenderTarget;
+}
+
+RenderTargetD3D *SwapChain9::getDepthStencilRenderTarget()
+{
+ return &mDepthStencilRenderTarget;
+}
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h
index 55a700c2d6..5753637c47 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h
@@ -15,26 +15,36 @@
namespace rx
{
+class NativeWindow9;
class Renderer9;
class SwapChain9 : public SwapChainD3D
{
public:
SwapChain9(Renderer9 *renderer,
- NativeWindow nativeWindow,
+ NativeWindow9 *nativeWindow,
HANDLE shareHandle,
+ IUnknown *d3dTexture,
GLenum backBufferFormat,
GLenum depthBufferFormat,
EGLint orientation);
- virtual ~SwapChain9();
+ ~SwapChain9() override;
- EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight);
- virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval);
- virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
- virtual void recreate();
+ EGLint resize(const gl::Context *context, EGLint backbufferWidth, EGLint backbufferHeight)
+ override;
+ EGLint reset(const gl::Context *context,
+ EGLint backbufferWidth,
+ EGLint backbufferHeight,
+ EGLint swapInterval) override;
+ EGLint swapRect(const gl::Context *context,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height) override;
+ void recreate() override;
- RenderTargetD3D *getColorRenderTarget() override { return &mColorRenderTarget; }
- RenderTargetD3D *getDepthStencilRenderTarget() override { return &mDepthStencilRenderTarget; }
+ RenderTargetD3D *getColorRenderTarget() override;
+ RenderTargetD3D *getDepthStencilRenderTarget() override;
virtual IDirect3DSurface9 *getRenderTarget();
virtual IDirect3DSurface9 *getDepthStencil();
@@ -45,6 +55,8 @@ class SwapChain9 : public SwapChainD3D
void *getKeyedMutex() override;
+ egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override;
+
private:
void release();
@@ -53,6 +65,8 @@ class SwapChain9 : public SwapChainD3D
EGLint mHeight;
EGLint mSwapInterval;
+ NativeWindow9 *mNativeWindow;
+
IDirect3DSwapChain9 *mSwapChain;
IDirect3DSurface9 *mBackBuffer;
IDirect3DSurface9 *mRenderTarget;
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp
index b28d5076b5..6404af6bba 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp
@@ -43,7 +43,7 @@ DWORD TextureStorage9::GetTextureUsage(GLenum internalformat, bool renderTarget)
{
DWORD d3dusage = 0;
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
{
@@ -93,11 +93,16 @@ int TextureStorage9::getLevelCount() const
return static_cast<int>(mMipLevels) - mTopLevel;
}
-gl::Error TextureStorage9::setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type,
- const gl::PixelUnpackState &unpack, const uint8_t *pixelData)
+gl::Error TextureStorage9::setData(const gl::Context *context,
+ const gl::ImageIndex &index,
+ ImageD3D *image,
+ const gl::Box *destBox,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixelData)
{
UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION);
+ return gl::InternalError();
}
TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchain)
@@ -107,7 +112,7 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchai
mTexture = surfaceTexture;
mMipLevels = surfaceTexture->GetLevelCount();
- mInternalFormat = swapchain->GetRenderTargetInternalFormat();
+ mInternalFormat = swapchain->getRenderTargetInternalFormat();
D3DSURFACE_DESC surfaceDesc;
surfaceTexture->GetLevelDesc(0, &surfaceDesc);
@@ -121,7 +126,7 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchai
TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels)
: TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget))
{
- mTexture = NULL;
+ mTexture = nullptr;
mInternalFormat = internalformat;
@@ -139,7 +144,7 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, GLenum internalforma
TextureStorage9_2D::~TextureStorage9_2D()
{
SafeRelease(mTexture);
- for (auto &renderTarget : mRenderTargets)
+ for (RenderTargetD3D *renderTarget : mRenderTargets)
{
SafeDelete(renderTarget);
}
@@ -147,16 +152,16 @@ TextureStorage9_2D::~TextureStorage9_2D()
// Increments refcount on surface.
// caller must Release() the returned surface
-gl::Error TextureStorage9_2D::getSurfaceLevel(GLenum target,
+gl::Error TextureStorage9_2D::getSurfaceLevel(const gl::Context *context,
+ GLenum target,
int level,
bool dirty,
IDirect3DSurface9 **outSurface)
{
ASSERT(target == GL_TEXTURE_2D);
- UNUSED_ASSERTION_VARIABLE(target);
- IDirect3DBaseTexture9 *baseTexture = NULL;
- gl::Error error = getBaseTexture(&baseTexture);
+ IDirect3DBaseTexture9 *baseTexture = nullptr;
+ gl::Error error = getBaseTexture(context, &baseTexture);
if (error.isError())
{
return error;
@@ -169,33 +174,36 @@ gl::Error TextureStorage9_2D::getSurfaceLevel(GLenum target,
ASSERT(SUCCEEDED(result));
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the surface from a texture, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to get the surface from a texture, "
+ << gl::FmtHR(result);
}
// With managed textures the driver needs to be informed of updates to the lower mipmap levels
if (level + mTopLevel != 0 && isManaged() && dirty)
{
- texture->AddDirtyRect(NULL);
+ texture->AddDirtyRect(nullptr);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+gl::Error TextureStorage9_2D::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT)
{
ASSERT(index.mipIndex < getLevelCount());
if (!mRenderTargets[index.mipIndex] && isRenderTarget())
{
- IDirect3DBaseTexture9 *baseTexture = NULL;
- gl::Error error = getBaseTexture(&baseTexture);
+ IDirect3DBaseTexture9 *baseTexture = nullptr;
+ gl::Error error = getBaseTexture(context, &baseTexture);
if (error.isError())
{
return error;
}
- IDirect3DSurface9 *surface = NULL;
- error = getSurfaceLevel(GL_TEXTURE_2D, index.mipIndex, false, &surface);
+ IDirect3DSurface9 *surface = nullptr;
+ error = getSurfaceLevel(context, GL_TEXTURE_2D, index.mipIndex, false, &surface);
if (error.isError())
{
return error;
@@ -213,20 +221,22 @@ gl::Error TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &index, Rende
ASSERT(outRT);
*outRT = mRenderTargets[index.mipIndex];
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage9_2D::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex)
+gl::Error TextureStorage9_2D::generateMipmap(const gl::Context *context,
+ const gl::ImageIndex &sourceIndex,
+ const gl::ImageIndex &destIndex)
{
- IDirect3DSurface9 *upper = NULL;
- gl::Error error = getSurfaceLevel(GL_TEXTURE_2D, sourceIndex.mipIndex, false, &upper);
+ IDirect3DSurface9 *upper = nullptr;
+ gl::Error error = getSurfaceLevel(context, GL_TEXTURE_2D, sourceIndex.mipIndex, false, &upper);
if (error.isError())
{
return error;
}
- IDirect3DSurface9 *lower = NULL;
- error = getSurfaceLevel(GL_TEXTURE_2D, destIndex.mipIndex, true, &lower);
+ IDirect3DSurface9 *lower = nullptr;
+ error = getSurfaceLevel(context, GL_TEXTURE_2D, destIndex.mipIndex, true, &lower);
if (error.isError())
{
SafeRelease(upper);
@@ -242,32 +252,34 @@ gl::Error TextureStorage9_2D::generateMipmap(const gl::ImageIndex &sourceIndex,
return error;
}
-gl::Error TextureStorage9_2D::getBaseTexture(IDirect3DBaseTexture9 **outTexture)
+gl::Error TextureStorage9_2D::getBaseTexture(const gl::Context *context,
+ IDirect3DBaseTexture9 **outTexture)
{
// if the width or height is not positive this should be treated as an incomplete texture
// we handle that here by skipping the d3d texture creation
- if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0)
+ if (mTexture == nullptr && mTextureWidth > 0 && mTextureHeight > 0)
{
ASSERT(mMipLevels > 0);
IDirect3DDevice9 *device = mRenderer->getDevice();
- HRESULT result = device->CreateTexture(static_cast<unsigned int>(mTextureWidth),
+ HRESULT result = device->CreateTexture(static_cast<unsigned int>(mTextureWidth),
static_cast<unsigned int>(mTextureHeight),
static_cast<unsigned int>(mMipLevels), getUsage(),
- mTextureFormat, getPool(), &mTexture, NULL);
+ mTextureFormat, getPool(), &mTexture, nullptr);
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D storage texture, result: 0x%X.", result);
+ return gl::OutOfMemory()
+ << "Failed to create 2D storage texture, " << gl::FmtHR(result);
}
}
*outTexture = mTexture;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage9_2D::copyToStorage(TextureStorage *destStorage)
+gl::Error TextureStorage9_2D::copyToStorage(const gl::Context *context, TextureStorage *destStorage)
{
ASSERT(destStorage);
@@ -276,15 +288,15 @@ gl::Error TextureStorage9_2D::copyToStorage(TextureStorage *destStorage)
int levels = getLevelCount();
for (int i = 0; i < levels; ++i)
{
- IDirect3DSurface9 *srcSurf = NULL;
- gl::Error error = getSurfaceLevel(GL_TEXTURE_2D, i, false, &srcSurf);
+ IDirect3DSurface9 *srcSurf = nullptr;
+ gl::Error error = getSurfaceLevel(context, GL_TEXTURE_2D, i, false, &srcSurf);
if (error.isError())
{
return error;
}
- IDirect3DSurface9 *dstSurf = NULL;
- error = dest9->getSurfaceLevel(GL_TEXTURE_2D, i, true, &dstSurf);
+ IDirect3DSurface9 *dstSurf = nullptr;
+ error = dest9->getSurfaceLevel(context, GL_TEXTURE_2D, i, true, &dstSurf);
if (error.isError())
{
SafeRelease(srcSurf);
@@ -302,17 +314,14 @@ gl::Error TextureStorage9_2D::copyToStorage(TextureStorage *destStorage)
}
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-TextureStorage9_EGLImage::TextureStorage9_EGLImage(Renderer9 *renderer, EGLImageD3D *image)
+TextureStorage9_EGLImage::TextureStorage9_EGLImage(Renderer9 *renderer,
+ EGLImageD3D *image,
+ RenderTarget9 *renderTarget9)
: TextureStorage9(renderer, D3DUSAGE_RENDERTARGET), mImage(image)
{
- RenderTargetD3D *renderTargetD3D = nullptr;
- mImage->getRenderTarget(&renderTargetD3D);
-
- RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTargetD3D);
-
mInternalFormat = renderTarget9->getInternalFormat();
mTextureFormat = renderTarget9->getD3DFormat();
mTextureWidth = renderTarget9->getWidth();
@@ -325,18 +334,17 @@ TextureStorage9_EGLImage::~TextureStorage9_EGLImage()
{
}
-gl::Error TextureStorage9_EGLImage::getSurfaceLevel(GLenum target,
+gl::Error TextureStorage9_EGLImage::getSurfaceLevel(const gl::Context *context,
+ GLenum target,
int level,
bool,
IDirect3DSurface9 **outSurface)
{
ASSERT(target == GL_TEXTURE_2D);
ASSERT(level == 0);
- UNUSED_ASSERTION_VARIABLE(target);
- UNUSED_ASSERTION_VARIABLE(level);
RenderTargetD3D *renderTargetD3D = nullptr;
- gl::Error error = mImage->getRenderTarget(&renderTargetD3D);
+ gl::Error error = mImage->getRenderTarget(context, &renderTargetD3D);
if (error.isError())
{
return error;
@@ -345,23 +353,24 @@ gl::Error TextureStorage9_EGLImage::getSurfaceLevel(GLenum target,
RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTargetD3D);
*outSurface = renderTarget9->getSurface();
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage9_EGLImage::getRenderTarget(const gl::ImageIndex &index,
+gl::Error TextureStorage9_EGLImage::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
RenderTargetD3D **outRT)
{
ASSERT(!index.hasLayer());
ASSERT(index.mipIndex == 0);
- UNUSED_ASSERTION_VARIABLE(index);
- return mImage->getRenderTarget(outRT);
+ return mImage->getRenderTarget(context, outRT);
}
-gl::Error TextureStorage9_EGLImage::getBaseTexture(IDirect3DBaseTexture9 **outTexture)
+gl::Error TextureStorage9_EGLImage::getBaseTexture(const gl::Context *context,
+ IDirect3DBaseTexture9 **outTexture)
{
RenderTargetD3D *renderTargetD3D = nullptr;
- gl::Error error = mImage->getRenderTarget(&renderTargetD3D);
+ gl::Error error = mImage->getRenderTarget(context, &renderTargetD3D);
if (error.isError())
{
return error;
@@ -371,16 +380,19 @@ gl::Error TextureStorage9_EGLImage::getBaseTexture(IDirect3DBaseTexture9 **outTe
*outTexture = renderTarget9->getTexture();
ASSERT(*outTexture != nullptr);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage9_EGLImage::generateMipmap(const gl::ImageIndex &, const gl::ImageIndex &)
+gl::Error TextureStorage9_EGLImage::generateMipmap(const gl::Context *context,
+ const gl::ImageIndex &,
+ const gl::ImageIndex &)
{
UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION);
+ return gl::InternalError();
}
-gl::Error TextureStorage9_EGLImage::copyToStorage(TextureStorage *destStorage)
+gl::Error TextureStorage9_EGLImage::copyToStorage(const gl::Context *context,
+ TextureStorage *destStorage)
{
ASSERT(destStorage);
ASSERT(getLevelCount() == 1);
@@ -388,7 +400,7 @@ gl::Error TextureStorage9_EGLImage::copyToStorage(TextureStorage *destStorage)
TextureStorage9 *dest9 = GetAs<TextureStorage9>(destStorage);
IDirect3DBaseTexture9 *destBaseTexture9 = nullptr;
- gl::Error error = dest9->getBaseTexture(&destBaseTexture9);
+ gl::Error error = dest9->getBaseTexture(context, &destBaseTexture9);
if (error.isError())
{
return error;
@@ -400,12 +412,12 @@ gl::Error TextureStorage9_EGLImage::copyToStorage(TextureStorage *destStorage)
HRESULT result = destTexture9->GetSurfaceLevel(destStorage->getTopLevel(), &destSurface);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY,
- "Failed to get the surface from a texture, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to get the surface from a texture, "
+ << gl::FmtHR(result);
}
RenderTargetD3D *sourceRenderTarget = nullptr;
- error = mImage->getRenderTarget(&sourceRenderTarget);
+ error = mImage->getRenderTarget(context, &sourceRenderTarget);
if (error.isError())
{
SafeRelease(destSurface);
@@ -427,16 +439,16 @@ gl::Error TextureStorage9_EGLImage::copyToStorage(TextureStorage *destStorage)
}
SafeRelease(destSurface);
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
TextureStorage9_Cube::TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly)
: TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget))
{
- mTexture = NULL;
- for (int i = 0; i < CUBE_FACE_COUNT; ++i)
+ mTexture = nullptr;
+ for (size_t i = 0; i < gl::CUBE_FACE_COUNT; ++i)
{
- mRenderTarget[i] = NULL;
+ mRenderTarget[i] = nullptr;
}
mInternalFormat = internalformat;
@@ -455,7 +467,7 @@ TextureStorage9_Cube::~TextureStorage9_Cube()
{
SafeRelease(mTexture);
- for (int i = 0; i < CUBE_FACE_COUNT; ++i)
+ for (size_t i = 0; i < gl::CUBE_FACE_COUNT; ++i)
{
SafeDelete(mRenderTarget[i]);
}
@@ -463,13 +475,14 @@ TextureStorage9_Cube::~TextureStorage9_Cube()
// Increments refcount on surface.
// caller must Release() the returned surface
-gl::Error TextureStorage9_Cube::getSurfaceLevel(GLenum target,
+gl::Error TextureStorage9_Cube::getSurfaceLevel(const gl::Context *context,
+ GLenum target,
int level,
bool dirty,
IDirect3DSurface9 **outSurface)
{
- IDirect3DBaseTexture9 *baseTexture = NULL;
- gl::Error error = getBaseTexture(&baseTexture);
+ IDirect3DBaseTexture9 *baseTexture = nullptr;
+ gl::Error error = getBaseTexture(context, &baseTexture);
if (error.isError())
{
return error;
@@ -483,35 +496,38 @@ gl::Error TextureStorage9_Cube::getSurfaceLevel(GLenum target,
ASSERT(SUCCEEDED(result));
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the surface from a texture, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to get the surface from a texture, "
+ << gl::FmtHR(result);
}
// With managed textures the driver needs to be informed of updates to the lower mipmap levels
if (level != 0 && isManaged() && dirty)
{
- texture->AddDirtyRect(face, NULL);
+ texture->AddDirtyRect(face, nullptr);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
+gl::Error TextureStorage9_Cube::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT)
{
ASSERT(outRT);
ASSERT(index.mipIndex == 0);
- ASSERT(index.layerIndex >= 0 && index.layerIndex < CUBE_FACE_COUNT);
+ ASSERT(index.layerIndex >= 0 && static_cast<size_t>(index.layerIndex) < gl::CUBE_FACE_COUNT);
- if (mRenderTarget[index.layerIndex] == NULL && isRenderTarget())
+ if (mRenderTarget[index.layerIndex] == nullptr && isRenderTarget())
{
- IDirect3DBaseTexture9 *baseTexture = NULL;
- gl::Error error = getBaseTexture(&baseTexture);
+ IDirect3DBaseTexture9 *baseTexture = nullptr;
+ gl::Error error = getBaseTexture(context, &baseTexture);
if (error.isError())
{
return error;
}
- IDirect3DSurface9 *surface = NULL;
- error = getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + index.layerIndex,
+ IDirect3DSurface9 *surface = nullptr;
+ error = getSurfaceLevel(context, GL_TEXTURE_CUBE_MAP_POSITIVE_X + index.layerIndex,
mTopLevel + index.mipIndex, false, &surface);
if (error.isError())
{
@@ -525,20 +541,23 @@ gl::Error TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index, Ren
}
*outRT = mRenderTarget[index.layerIndex];
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage9_Cube::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex)
+gl::Error TextureStorage9_Cube::generateMipmap(const gl::Context *context,
+ const gl::ImageIndex &sourceIndex,
+ const gl::ImageIndex &destIndex)
{
- IDirect3DSurface9 *upper = NULL;
- gl::Error error = getSurfaceLevel(sourceIndex.type, sourceIndex.mipIndex, false, &upper);
+ IDirect3DSurface9 *upper = nullptr;
+ gl::Error error =
+ getSurfaceLevel(context, sourceIndex.type, sourceIndex.mipIndex, false, &upper);
if (error.isError())
{
return error;
}
- IDirect3DSurface9 *lower = NULL;
- error = getSurfaceLevel(destIndex.type, destIndex.mipIndex, true, &lower);
+ IDirect3DSurface9 *lower = nullptr;
+ error = getSurfaceLevel(context, destIndex.type, destIndex.mipIndex, true, &lower);
if (error.isError())
{
SafeRelease(upper);
@@ -554,52 +573,56 @@ gl::Error TextureStorage9_Cube::generateMipmap(const gl::ImageIndex &sourceIndex
return error;
}
-gl::Error TextureStorage9_Cube::getBaseTexture(IDirect3DBaseTexture9 **outTexture)
+gl::Error TextureStorage9_Cube::getBaseTexture(const gl::Context *context,
+ IDirect3DBaseTexture9 **outTexture)
{
// if the size is not positive this should be treated as an incomplete texture
// we handle that here by skipping the d3d texture creation
- if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0)
+ if (mTexture == nullptr && mTextureWidth > 0 && mTextureHeight > 0)
{
ASSERT(mMipLevels > 0);
ASSERT(mTextureWidth == mTextureHeight);
IDirect3DDevice9 *device = mRenderer->getDevice();
- HRESULT result = device->CreateCubeTexture(
+ HRESULT result = device->CreateCubeTexture(
static_cast<unsigned int>(mTextureWidth), static_cast<unsigned int>(mMipLevels),
- getUsage(), mTextureFormat, getPool(), &mTexture, NULL);
+ getUsage(), mTextureFormat, getPool(), &mTexture, nullptr);
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube storage texture, result: 0x%X.", result);
+ return gl::OutOfMemory()
+ << "Failed to create cube storage texture, " << gl::FmtHR(result);
}
}
*outTexture = mTexture;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
-gl::Error TextureStorage9_Cube::copyToStorage(TextureStorage *destStorage)
+gl::Error TextureStorage9_Cube::copyToStorage(const gl::Context *context,
+ TextureStorage *destStorage)
{
ASSERT(destStorage);
TextureStorage9_Cube *dest9 = GetAs<TextureStorage9_Cube>(destStorage);
int levels = getLevelCount();
- for (int f = 0; f < CUBE_FACE_COUNT; f++)
+ for (int f = 0; f < static_cast<int>(gl::CUBE_FACE_COUNT); f++)
{
for (int i = 0; i < levels; i++)
{
- IDirect3DSurface9 *srcSurf = NULL;
+ IDirect3DSurface9 *srcSurf = nullptr;
gl::Error error =
- getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false, &srcSurf);
+ getSurfaceLevel(context, GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false, &srcSurf);
if (error.isError())
{
return error;
}
- IDirect3DSurface9 *dstSurf = NULL;
- error = dest9->getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true, &dstSurf);
+ IDirect3DSurface9 *dstSurf = nullptr;
+ error = dest9->getSurfaceLevel(context, GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true,
+ &dstSurf);
if (error.isError())
{
SafeRelease(srcSurf);
@@ -618,7 +641,7 @@ gl::Error TextureStorage9_Cube::copyToStorage(TextureStorage *destStorage)
}
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h
index 50e63a6f14..2f51901931 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h
@@ -25,28 +25,34 @@ class RenderTarget9;
class TextureStorage9 : public TextureStorage
{
public:
- virtual ~TextureStorage9();
+ ~TextureStorage9() override;
static DWORD GetTextureUsage(GLenum internalformat, bool renderTarget);
D3DPOOL getPool() const;
DWORD getUsage() const;
- virtual gl::Error getSurfaceLevel(GLenum target,
+ virtual gl::Error getSurfaceLevel(const gl::Context *context,
+ GLenum target,
int level,
bool dirty,
IDirect3DSurface9 **outSurface) = 0;
- virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture) = 0;
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0;
+ virtual gl::Error getBaseTexture(const gl::Context *context,
+ IDirect3DBaseTexture9 **outTexture) = 0;
- virtual int getTopLevel() const;
- virtual bool isRenderTarget() const;
- virtual bool isManaged() const;
+ int getTopLevel() const override;
+ bool isRenderTarget() const override;
+ bool isManaged() const override;
bool supportsNativeMipmapFunction() const override;
- virtual int getLevelCount() const;
+ int getLevelCount() const override;
- virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type,
- const gl::PixelUnpackState &unpack, const uint8_t *pixelData);
+ gl::Error setData(const gl::Context *context,
+ const gl::ImageIndex &index,
+ ImageD3D *image,
+ const gl::Box *destBox,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixelData) override;
protected:
int mTopLevel;
@@ -70,16 +76,22 @@ class TextureStorage9_2D : public TextureStorage9
public:
TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchain);
TextureStorage9_2D(Renderer9 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels);
- virtual ~TextureStorage9_2D();
+ ~TextureStorage9_2D() override;
- gl::Error getSurfaceLevel(GLenum target,
+ gl::Error getSurfaceLevel(const gl::Context *context,
+ GLenum target,
int level,
bool dirty,
IDirect3DSurface9 **outSurface) override;
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
- virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture);
- virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex);
- virtual gl::Error copyToStorage(TextureStorage *destStorage);
+ gl::Error getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT) override;
+ gl::Error getBaseTexture(const gl::Context *context,
+ IDirect3DBaseTexture9 **outTexture) override;
+ gl::Error generateMipmap(const gl::Context *context,
+ const gl::ImageIndex &sourceIndex,
+ const gl::ImageIndex &destIndex) override;
+ gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
private:
IDirect3DTexture9 *mTexture;
@@ -89,18 +101,23 @@ class TextureStorage9_2D : public TextureStorage9
class TextureStorage9_EGLImage final : public TextureStorage9
{
public:
- TextureStorage9_EGLImage(Renderer9 *renderer, EGLImageD3D *image);
+ TextureStorage9_EGLImage(Renderer9 *renderer, EGLImageD3D *image, RenderTarget9 *renderTarget9);
~TextureStorage9_EGLImage() override;
- gl::Error getSurfaceLevel(GLenum target,
+ gl::Error getSurfaceLevel(const gl::Context *context,
+ GLenum target,
int level,
bool dirty,
IDirect3DSurface9 **outSurface) override;
- gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
- gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture) override;
- gl::Error generateMipmap(const gl::ImageIndex &sourceIndex,
+ gl::Error getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT) override;
+ gl::Error getBaseTexture(const gl::Context *context,
+ IDirect3DBaseTexture9 **outTexture) override;
+ gl::Error generateMipmap(const gl::Context *context,
+ const gl::ImageIndex &sourceIndex,
const gl::ImageIndex &destIndex) override;
- gl::Error copyToStorage(TextureStorage *destStorage) override;
+ gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
private:
EGLImageD3D *mImage;
@@ -110,25 +127,28 @@ class TextureStorage9_Cube : public TextureStorage9
{
public:
TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly);
- virtual ~TextureStorage9_Cube();
+ ~TextureStorage9_Cube() override;
- gl::Error getSurfaceLevel(GLenum target,
+ gl::Error getSurfaceLevel(const gl::Context *context,
+ GLenum target,
int level,
bool dirty,
IDirect3DSurface9 **outSurface) override;
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
- virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture);
- virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex);
- virtual gl::Error copyToStorage(TextureStorage *destStorage);
+ gl::Error getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ RenderTargetD3D **outRT) override;
+ gl::Error getBaseTexture(const gl::Context *context,
+ IDirect3DBaseTexture9 **outTexture) override;
+ gl::Error generateMipmap(const gl::Context *context,
+ const gl::ImageIndex &sourceIndex,
+ const gl::ImageIndex &destIndex) override;
+ gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
private:
- static const size_t CUBE_FACE_COUNT = 6;
-
IDirect3DCubeTexture9 *mTexture;
- RenderTarget9 *mRenderTarget[CUBE_FACE_COUNT];
+ RenderTarget9 *mRenderTarget[gl::CUBE_FACE_COUNT];
};
}
#endif // LIBANGLE_RENDERER_D3D_D3D9_TEXTURESTORAGE9_H_
-
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h
index 992201737f..0f4410b8de 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h
@@ -9,7 +9,9 @@
#ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_
#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_
+#include "libANGLE/Context.h"
#include "libANGLE/renderer/VertexArrayImpl.h"
+#include "libANGLE/renderer/d3d/d3d9/Context9.h"
#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
namespace rx
@@ -19,14 +21,26 @@ class Renderer9;
class VertexArray9 : public VertexArrayImpl
{
public:
- VertexArray9(const gl::VertexArray::Data &data)
- : VertexArrayImpl(data)
- {
- }
+ VertexArray9(const gl::VertexArrayState &data) : VertexArrayImpl(data) {}
- virtual ~VertexArray9() { }
+ void syncState(const gl::Context *context,
+ const gl::VertexArray::DirtyBits &dirtyBits) override;
+
+ ~VertexArray9() override {}
+
+ Serial getCurrentStateSerial() const { return mCurrentStateSerial; }
+
+ private:
+ Serial mCurrentStateSerial;
};
+inline void VertexArray9::syncState(const gl::Context *context,
+ const gl::VertexArray::DirtyBits &dirtyBits)
+{
+ ASSERT(dirtyBits.any());
+ Renderer9 *renderer = GetImplAs<Context9>(context)->getRenderer();
+ mCurrentStateSerial = renderer->generateSerial();
+}
}
#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp
index bfdf137126..c0b80a847c 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp
@@ -19,7 +19,7 @@ namespace rx
VertexBuffer9::VertexBuffer9(Renderer9 *renderer) : mRenderer(renderer)
{
- mVertexBuffer = NULL;
+ mVertexBuffer = nullptr;
mBufferSize = 0;
mDynamicUsage = false;
}
@@ -47,16 +47,18 @@ gl::Error VertexBuffer9::initialize(unsigned int size, bool dynamicUsage)
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal vertex buffer of size, %lu.", size);
+ return gl::OutOfMemory()
+ << "Failed to allocate internal vertex buffer of size " << size;
}
}
mBufferSize = size;
mDynamicUsage = dynamicUsage;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
GLenum currentValueType,
GLint start,
GLsizei count,
@@ -66,32 +68,33 @@ gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib
{
if (!mVertexBuffer)
{
- return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
+ return gl::OutOfMemory() << "Internal vertex buffer is not initialized.";
}
- int inputStride = static_cast<int>(gl::ComputeVertexAttributeStride(attrib));
+ int inputStride = static_cast<int>(gl::ComputeVertexAttributeStride(attrib, binding));
int elementSize = static_cast<int>(gl::ComputeVertexAttributeTypeSize(attrib));
DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
- uint8_t *mapPtr = NULL;
+ uint8_t *mapPtr = nullptr;
- unsigned int mapSize;
- gl::Error error = spaceRequired(attrib, count, instances, &mapSize);
- if (error.isError())
+ auto errorOrMapSize = mRenderer->getVertexSpaceRequired(attrib, binding, count, instances);
+ if (errorOrMapSize.isError())
{
- return error;
+ return errorOrMapSize.getError();
}
+ unsigned int mapSize = errorOrMapSize.getResult();
+
HRESULT result = mVertexBuffer->Lock(offset, mapSize, reinterpret_cast<void**>(&mapPtr), lockFlags);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal vertex buffer, HRESULT: 0x%08x.", result);
+ return gl::OutOfMemory() << "Failed to lock internal vertex buffer, " << gl::FmtHR(result);
}
const uint8_t *input = sourceData;
- if (instances == 0 || attrib.divisor == 0)
+ if (instances == 0 || binding.getDivisor() == 0)
{
input += inputStride * start;
}
@@ -112,13 +115,7 @@ gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib
mVertexBuffer->Unlock();
- return gl::Error(GL_NO_ERROR);
-}
-
-gl::Error VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances,
- unsigned int *outSpaceRequired) const
-{
- return spaceRequired(attrib, count, instances, outSpaceRequired);
+ return gl::NoError();
}
unsigned int VertexBuffer9::getBufferSize() const
@@ -134,7 +131,7 @@ gl::Error VertexBuffer9::setBufferSize(unsigned int size)
}
else
{
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
}
@@ -142,7 +139,7 @@ gl::Error VertexBuffer9::discard()
{
if (!mVertexBuffer)
{
- return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
+ return gl::OutOfMemory() << "Internal vertex buffer is not initialized.";
}
void *dummy;
@@ -151,65 +148,22 @@ gl::Error VertexBuffer9::discard()
result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal buffer for discarding, HRESULT: 0x%08x", result);
+ return gl::OutOfMemory() << "Failed to lock internal buffer for discarding, "
+ << gl::FmtHR(result);
}
result = mVertexBuffer->Unlock();
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal buffer for discarding, HRESULT: 0x%08x", result);
+ return gl::OutOfMemory() << "Failed to unlock internal buffer for discarding, "
+ << gl::FmtHR(result);
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const
{
return mVertexBuffer;
}
-
-gl::Error VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances,
- unsigned int *outSpaceRequired) const
-{
- gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, GL_FLOAT);
- const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormatType);
-
- if (attrib.enabled)
- {
- unsigned int elementCount = 0;
- if (instances == 0 || attrib.divisor == 0)
- {
- elementCount = static_cast<unsigned int>(count);
- }
- else
- {
- // Round up to divisor, if possible
- elementCount = UnsignedCeilDivide(static_cast<unsigned int>(instances), attrib.divisor);
- }
-
- if (d3d9VertexInfo.outputElementSize <= std::numeric_limits<unsigned int>::max() / elementCount)
- {
- if (outSpaceRequired)
- {
- *outSpaceRequired =
- static_cast<unsigned int>(d3d9VertexInfo.outputElementSize) * elementCount;
- }
- return gl::Error(GL_NO_ERROR);
- }
- else
- {
- return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow.");
- }
- }
- else
- {
- const unsigned int elementSize = 4;
- if (outSpaceRequired)
- {
- *outSpaceRequired = elementSize * 4;
- }
- return gl::Error(GL_NO_ERROR);
- }
-}
-
-}
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h
index 64271cbe2a..983616f4e4 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h
@@ -19,11 +19,13 @@ class VertexBuffer9 : public VertexBuffer
{
public:
explicit VertexBuffer9(Renderer9 *renderer);
- virtual ~VertexBuffer9();
- virtual gl::Error initialize(unsigned int size, bool dynamicUsage);
+ gl::Error initialize(unsigned int size, bool dynamicUsage) override;
+ // Warning: you should ensure binding really matches attrib.bindingIndex before using this
+ // function.
gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
GLenum currentValueType,
GLint start,
GLsizei count,
@@ -31,23 +33,19 @@ class VertexBuffer9 : public VertexBuffer
unsigned int offset,
const uint8_t *sourceData) override;
- virtual gl::Error getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, unsigned int *outSpaceRequired) const;
-
- virtual unsigned int getBufferSize() const;
- virtual gl::Error setBufferSize(unsigned int size);
- virtual gl::Error discard();
+ unsigned int getBufferSize() const override;
+ gl::Error setBufferSize(unsigned int size) override;
+ gl::Error discard() override;
IDirect3DVertexBuffer9 *getBuffer() const;
private:
+ ~VertexBuffer9() override;
Renderer9 *mRenderer;
IDirect3DVertexBuffer9 *mVertexBuffer;
unsigned int mBufferSize;
bool mDynamicUsage;
-
- gl::Error spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances,
- unsigned int *outSpaceRequired) const;
};
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp
index a23ab4a290..abadf5c0b5 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp
@@ -21,7 +21,7 @@ VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0)
{
for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
{
- mVertexDeclCache[i].vertexDeclaration = NULL;
+ mVertexDeclCache[i].vertexDeclaration = nullptr;
mVertexDeclCache[i].lruCount = 0;
}
@@ -30,7 +30,7 @@ VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0)
mAppliedVBs[i].serial = 0;
}
- mLastSetVDecl = NULL;
+ mLastSetVDecl = nullptr;
mInstancingEnabled = true;
}
@@ -42,11 +42,13 @@ VertexDeclarationCache::~VertexDeclarationCache()
}
}
-gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device,
- const std::vector<TranslatedAttribute> &attributes,
- gl::Program *program,
- GLsizei instances,
- GLsizei *repeatDraw)
+gl::Error VertexDeclarationCache::applyDeclaration(
+ IDirect3DDevice9 *device,
+ const std::vector<TranslatedAttribute> &attributes,
+ gl::Program *program,
+ GLint start,
+ GLsizei instances,
+ GLsizei *repeatDraw)
{
ASSERT(gl::MAX_VERTEX_ATTRIBS >= attributes.size());
@@ -102,14 +104,14 @@ gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device,
D3DVERTEXELEMENT9 *element = &elements[0];
ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
- const auto &semanticIndexes = programD3D->getSemanticIndexes();
+ const auto &semanticIndexes = programD3D->getAttribLocationToD3DSemantics();
for (size_t i = 0; i < attributes.size(); i++)
{
if (attributes[i].active)
{
// Directly binding the storage buffer is not supported for d3d9
- ASSERT(attributes[i].storage == NULL);
+ ASSERT(attributes[i].storage == nullptr);
int stream = static_cast<int>(i);
@@ -147,19 +149,24 @@ gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device,
}
}
- VertexBuffer9 *vertexBuffer = GetAs<VertexBuffer9>(attributes[i].vertexBuffer);
+ VertexBuffer9 *vertexBuffer = GetAs<VertexBuffer9>(attributes[i].vertexBuffer.get());
+
+ unsigned int offset = 0;
+ ANGLE_TRY_RESULT(attributes[i].computeOffset(start), offset);
if (mAppliedVBs[stream].serial != attributes[i].serial ||
mAppliedVBs[stream].stride != attributes[i].stride ||
- mAppliedVBs[stream].offset != attributes[i].offset)
+ mAppliedVBs[stream].offset != offset)
{
- device->SetStreamSource(stream, vertexBuffer->getBuffer(), attributes[i].offset, attributes[i].stride);
+ device->SetStreamSource(stream, vertexBuffer->getBuffer(), offset,
+ attributes[i].stride);
mAppliedVBs[stream].serial = attributes[i].serial;
mAppliedVBs[stream].stride = attributes[i].stride;
- mAppliedVBs[stream].offset = attributes[i].offset;
+ mAppliedVBs[stream].offset = offset;
}
- gl::VertexFormatType vertexformatType = gl::GetVertexFormatType(*attributes[i].attribute, GL_FLOAT);
+ gl::VertexFormatType vertexformatType =
+ gl::GetVertexFormatType(*attributes[i].attribute, GL_FLOAT);
const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(caps.DeclTypes, vertexformatType);
element->Stream = static_cast<WORD>(stream);
@@ -200,7 +207,7 @@ gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device,
mLastSetVDecl = entry->vertexDeclaration;
}
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
}
@@ -214,7 +221,7 @@ gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device,
}
}
- if (lastCache->vertexDeclaration != NULL)
+ if (lastCache->vertexDeclaration != nullptr)
{
SafeRelease(lastCache->vertexDeclaration);
// mLastSetVDecl is set to the replacement, so we don't have to worry
@@ -225,14 +232,15 @@ gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device,
HRESULT result = device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration);
if (FAILED(result))
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal vertex declaration, result: 0x%X.", result);
+ return gl::OutOfMemory() << "Failed to create internal vertex declaration, "
+ << gl::FmtHR(result);
}
device->SetVertexDeclaration(lastCache->vertexDeclaration);
mLastSetVDecl = lastCache->vertexDeclaration;
lastCache->lruCount = ++mMaxLru;
- return gl::Error(GL_NO_ERROR);
+ return gl::NoError();
}
void VertexDeclarationCache::markStateDirty()
@@ -242,7 +250,7 @@ void VertexDeclarationCache::markStateDirty()
mAppliedVBs[i].serial = 0;
}
- mLastSetVDecl = NULL;
+ mLastSetVDecl = nullptr;
mInstancingEnabled = true; // Forces it to be disabled when not used
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h
index bad4de4d6b..7bd7cabae4 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h
@@ -30,6 +30,7 @@ class VertexDeclarationCache
gl::Error applyDeclaration(IDirect3DDevice9 *device,
const std::vector<TranslatedAttribute> &attributes,
gl::Program *program,
+ GLint start,
GLsizei instances,
GLsizei *repeatDraw);
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp
index b672a60e3c..d10fa1ee87 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp
@@ -7,12 +7,16 @@
// formatutils9.cpp: Queries for GL image formats and their translations to D3D9
// formats.
-#include "libANGLE/renderer/d3d/copyimage.h"
#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+
+#include "image_util/copyimage.h"
+#include "image_util/generatemip.h"
+#include "image_util/loadimage.h"
+
#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
#include "libANGLE/renderer/d3d/d3d9/vertexconversion.h"
-#include "libANGLE/renderer/d3d/generatemip.h"
-#include "libANGLE/renderer/d3d/loadimage.h"
+
+using namespace angle;
namespace rx
{
@@ -20,35 +24,8 @@ namespace rx
namespace d3d9
{
-const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I', 'N', 'T', 'Z')));
-const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N', 'U', 'L', 'L')));
-
-struct D3D9FastCopyFormat
-{
- GLenum destFormat;
- GLenum destType;
- ColorCopyFunction copyFunction;
-
- D3D9FastCopyFormat(GLenum destFormat, GLenum destType, ColorCopyFunction copyFunction)
- : destFormat(destFormat), destType(destType), copyFunction(copyFunction)
- { }
-
- bool operator<(const D3D9FastCopyFormat& other) const
- {
- return memcmp(this, &other, sizeof(D3D9FastCopyFormat)) < 0;
- }
-};
-
-typedef std::multimap<D3DFORMAT, D3D9FastCopyFormat> D3D9FastCopyMap;
-
-static D3D9FastCopyMap BuildFastCopyMap()
-{
- D3D9FastCopyMap map;
-
- map.insert(std::make_pair(D3DFMT_A8R8G8B8, D3D9FastCopyFormat(GL_RGBA, GL_UNSIGNED_BYTE, CopyBGRA8ToRGBA8)));
-
- return map;
-}
+constexpr D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I', 'N', 'T', 'Z')));
+constexpr D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N', 'U', 'L', 'L')));
// A map to determine the pixel size and mip generation function of a given D3D format
typedef std::map<D3DFORMAT, D3DFormat> D3D9FormatInfoMap;
@@ -64,109 +41,188 @@ D3DFormat::D3DFormat()
luminanceBits(0),
depthBits(0),
stencilBits(0),
- internalFormat(GL_NONE),
- mipGenerationFunction(NULL),
- colorReadFunction(NULL),
- fastCopyFunctions()
+ formatID(angle::Format::ID::NONE)
{
}
-ColorCopyFunction D3DFormat::getFastCopyFunction(GLenum format, GLenum type) const
+D3DFormat::D3DFormat(GLuint bits,
+ GLuint blockWidth,
+ GLuint blockHeight,
+ GLuint redBits,
+ GLuint greenBits,
+ GLuint blueBits,
+ GLuint alphaBits,
+ GLuint lumBits,
+ GLuint depthBits,
+ GLuint stencilBits,
+ Format::ID formatID)
+ : pixelBytes(bits / 8),
+ blockWidth(blockWidth),
+ blockHeight(blockHeight),
+ redBits(redBits),
+ greenBits(greenBits),
+ blueBits(blueBits),
+ alphaBits(alphaBits),
+ luminanceBits(lumBits),
+ depthBits(depthBits),
+ stencilBits(stencilBits),
+ formatID(formatID)
{
- FastCopyFunctionMap::const_iterator iter = fastCopyFunctions.find(std::make_pair(format, type));
- return (iter != fastCopyFunctions.end()) ? iter->second : NULL;
}
-static inline void InsertD3DFormatInfo(D3D9FormatInfoMap *map, D3DFORMAT format, GLuint bits, GLuint blockWidth,
- GLuint blockHeight, GLuint redBits, GLuint greenBits, GLuint blueBits,
- GLuint alphaBits, GLuint lumBits, GLuint depthBits, GLuint stencilBits,
- GLenum internalFormat, MipGenerationFunction mipFunc,
- ColorReadFunction colorReadFunc)
+const D3DFormat &GetD3DFormatInfo(D3DFORMAT format)
{
- D3DFormat info;
- info.pixelBytes = bits / 8;
- info.blockWidth = blockWidth;
- info.blockHeight = blockHeight;
- info.redBits = redBits;
- info.greenBits = greenBits;
- info.blueBits = blueBits;
- info.alphaBits = alphaBits;
- info.luminanceBits = lumBits;
- info.depthBits = depthBits;
- info.stencilBits = stencilBits;
- info.internalFormat = internalFormat;
- info.mipGenerationFunction = mipFunc;
- info.colorReadFunction = colorReadFunc;
-
- static const D3D9FastCopyMap fastCopyMap = BuildFastCopyMap();
- std::pair<D3D9FastCopyMap::const_iterator, D3D9FastCopyMap::const_iterator> fastCopyIter = fastCopyMap.equal_range(format);
- for (D3D9FastCopyMap::const_iterator i = fastCopyIter.first; i != fastCopyIter.second; i++)
+ if (format == D3DFMT_NULL)
{
- info.fastCopyFunctions.insert(std::make_pair(std::make_pair(i->second.destFormat, i->second.destType), i->second.copyFunction));
+ static const D3DFormat info(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Format::ID::NONE);
+ return info;
}
- map->insert(std::make_pair(format, info));
-}
-
-static D3D9FormatInfoMap BuildD3D9FormatInfoMap()
-{
- D3D9FormatInfoMap map;
-
- // | D3DFORMAT | S |W |H | R | G | B | A | L | D | S | Internal format | Mip generation function | Color read function |
- InsertD3DFormatInfo(&map, D3DFMT_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, GL_NONE, NULL, NULL );
- InsertD3DFormatInfo(&map, D3DFMT_UNKNOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, GL_NONE, NULL, NULL );
-
- InsertD3DFormatInfo(&map, D3DFMT_L8, 8, 1, 1, 0, 0, 0, 0, 8, 0, 0, GL_LUMINANCE8_EXT, GenerateMip<L8>, ReadColor<L8, GLfloat> );
- InsertD3DFormatInfo(&map, D3DFMT_A8, 8, 1, 1, 0, 0, 0, 8, 0, 0, 0, GL_ALPHA8_EXT, GenerateMip<A8>, ReadColor<A8, GLfloat> );
- InsertD3DFormatInfo(&map, D3DFMT_A8L8, 16, 1, 1, 0, 0, 0, 8, 8, 0, 0, GL_LUMINANCE8_ALPHA8_EXT, GenerateMip<A8L8>, ReadColor<A8L8, GLfloat> );
- InsertD3DFormatInfo(&map, D3DFMT_A4R4G4B4, 16, 1, 1, 4, 4, 4, 4, 0, 0, 0, GL_BGRA4_ANGLEX, GenerateMip<A4R4G4B4>, ReadColor<A4R4G4B4, GLfloat> );
- InsertD3DFormatInfo(&map, D3DFMT_A1R5G5B5, 16, 1, 1, 5, 5, 5, 1, 0, 0, 0, GL_BGR5_A1_ANGLEX, GenerateMip<A1R5G5B5>, ReadColor<A1R5G5B5, GLfloat> );
- InsertD3DFormatInfo(&map, D3DFMT_R5G6B5, 16, 1, 1, 5, 6, 5, 0, 0, 0, 0, GL_RGB565, GenerateMip<R5G6B5>, ReadColor<R5G6B5, GLfloat> );
- InsertD3DFormatInfo(&map, D3DFMT_X8R8G8B8, 32, 1, 1, 8, 8, 8, 0, 0, 0, 0, GL_BGRA8_EXT, GenerateMip<B8G8R8X8>, ReadColor<B8G8R8X8, GLfloat> );
- InsertD3DFormatInfo(&map, D3DFMT_A8R8G8B8, 32, 1, 1, 8, 8, 8, 8, 0, 0, 0, GL_BGRA8_EXT, GenerateMip<B8G8R8A8>, ReadColor<B8G8R8A8, GLfloat> );
- InsertD3DFormatInfo(&map, D3DFMT_R16F, 16, 1, 1, 16, 0, 0, 0, 0, 0, 0, GL_R16F_EXT, GenerateMip<R16F>, ReadColor<R16F, GLfloat> );
- InsertD3DFormatInfo(&map, D3DFMT_G16R16F, 32, 1, 1, 16, 16, 0, 0, 0, 0, 0, GL_RG16F_EXT, GenerateMip<R16G16F>, ReadColor<R16G16F, GLfloat> );
- InsertD3DFormatInfo(&map, D3DFMT_A16B16G16R16F, 64, 1, 1, 16, 16, 16, 16, 0, 0, 0, GL_RGBA16F_EXT, GenerateMip<R16G16B16A16F>, ReadColor<R16G16B16A16F, GLfloat>);
- InsertD3DFormatInfo(&map, D3DFMT_R32F, 32, 1, 1, 32, 0, 0, 0, 0, 0, 0, GL_R32F_EXT, GenerateMip<R32F>, ReadColor<R32F, GLfloat> );
- InsertD3DFormatInfo(&map, D3DFMT_G32R32F, 64, 1, 1, 32, 32, 0, 0, 0, 0, 0, GL_RG32F_EXT, GenerateMip<R32G32F>, ReadColor<R32G32F, GLfloat> );
- InsertD3DFormatInfo(&map, D3DFMT_A32B32G32R32F, 128, 1, 1, 32, 32, 32, 32, 0, 0, 0, GL_RGBA32F_EXT, GenerateMip<R32G32B32A32F>, ReadColor<R32G32B32A32F, GLfloat>);
-
- InsertD3DFormatInfo(&map, D3DFMT_D16, 16, 1, 1, 0, 0, 0, 0, 0, 16, 0, GL_DEPTH_COMPONENT16, NULL, NULL );
- InsertD3DFormatInfo(&map, D3DFMT_D24S8, 32, 1, 1, 0, 0, 0, 0, 0, 24, 8, GL_DEPTH24_STENCIL8_OES, NULL, NULL );
- InsertD3DFormatInfo(&map, D3DFMT_D24X8, 32, 1, 1, 0, 0, 0, 0, 0, 24, 0, GL_DEPTH_COMPONENT16, NULL, NULL );
- InsertD3DFormatInfo(&map, D3DFMT_D32, 32, 1, 1, 0, 0, 0, 0, 0, 32, 0, GL_DEPTH_COMPONENT32_OES, NULL, NULL );
-
- InsertD3DFormatInfo(&map, D3DFMT_INTZ, 32, 1, 1, 0, 0, 0, 0, 0, 24, 8, GL_DEPTH24_STENCIL8_OES, NULL, NULL );
-
- InsertD3DFormatInfo(&map, D3DFMT_DXT1, 64, 4, 4, 0, 0, 0, 0, 0, 0, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, NULL, NULL );
- InsertD3DFormatInfo(&map, D3DFMT_DXT3, 128, 4, 4, 0, 0, 0, 0, 0, 0, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, NULL, NULL );
- InsertD3DFormatInfo(&map, D3DFMT_DXT5, 128, 4, 4, 0, 0, 0, 0, 0, 0, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, NULL, NULL );
-
- return map;
-}
-
-const D3DFormat &GetD3DFormatInfo(D3DFORMAT format)
-{
- static const D3D9FormatInfoMap infoMap = BuildD3D9FormatInfoMap();
- D3D9FormatInfoMap::const_iterator iter = infoMap.find(format);
- if (iter != infoMap.end())
+ if (format == D3DFMT_INTZ)
{
- return iter->second;
+ static const D3DFormat info(32, 1, 1, 0, 0, 0, 0, 0, 24, 8, Format::ID::D24_UNORM_S8_UINT);
+ return info;
}
- else
+
+ switch (format)
{
- static const D3DFormat defaultInfo;
- return defaultInfo;
- }
-}
+ case D3DFMT_UNKNOWN:
+ {
+ static const D3DFormat info(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Format::ID::NONE);
+ return info;
+ }
+ case D3DFMT_L8:
+ {
+ static const D3DFormat info(8, 1, 1, 0, 0, 0, 0, 8, 0, 0, Format::ID::L8_UNORM);
+ return info;
+ }
+ case D3DFMT_A8:
+ {
+ static const D3DFormat info(8, 1, 1, 0, 0, 0, 8, 0, 0, 0, Format::ID::A8_UNORM);
+ return info;
+ }
+ case D3DFMT_A8L8:
+ {
+ static const D3DFormat info(16, 1, 1, 0, 0, 0, 8, 8, 0, 0, Format::ID::L8A8_UNORM);
+ return info;
+ }
+ case D3DFMT_A4R4G4B4:
+ {
+ static const D3DFormat info(16, 1, 1, 4, 4, 4, 4, 0, 0, 0, Format::ID::B4G4R4A4_UNORM);
+ return info;
+ }
+ case D3DFMT_A1R5G5B5:
+ {
+ static const D3DFormat info(16, 1, 1, 5, 5, 5, 1, 0, 0, 0, Format::ID::B5G5R5A1_UNORM);
+ return info;
+ }
+ case D3DFMT_R5G6B5:
+ {
+ static const D3DFormat info(16, 1, 1, 5, 6, 5, 0, 0, 0, 0, Format::ID::R5G6B5_UNORM);
+ return info;
+ }
+ case D3DFMT_X8R8G8B8:
+ {
+ static const D3DFormat info(32, 1, 1, 8, 8, 8, 0, 0, 0, 0, Format::ID::B8G8R8X8_UNORM);
+ return info;
+ }
+ case D3DFMT_A8R8G8B8:
+ {
+ static const D3DFormat info(32, 1, 1, 8, 8, 8, 8, 0, 0, 0, Format::ID::B8G8R8A8_UNORM);
+ return info;
+ }
+
+ case D3DFMT_R16F:
+ {
+ static const D3DFormat info(16, 1, 1, 16, 0, 0, 0, 0, 0, 0, Format::ID::R16_FLOAT);
+ return info;
+ }
+ case D3DFMT_G16R16F:
+ {
+ static const D3DFormat info(32, 1, 1, 16, 16, 0, 0, 0, 0, 0, Format::ID::R16G16_FLOAT);
+ return info;
+ }
+ case D3DFMT_A16B16G16R16F:
+ {
+ static const D3DFormat info(64, 1, 1, 16, 16, 16, 16, 0, 0, 0,
+ Format::ID::R16G16B16A16_FLOAT);
+ return info;
+ }
+ case D3DFMT_R32F:
+ {
+ static const D3DFormat info(32, 1, 1, 32, 0, 0, 0, 0, 0, 0, Format::ID::R32_FLOAT);
+ return info;
+ }
+ case D3DFMT_G32R32F:
+ {
+ static const D3DFormat info(64, 1, 1, 32, 32, 0, 0, 0, 0, 0, Format::ID::R32G32_FLOAT);
+ return info;
+ }
+ case D3DFMT_A32B32G32R32F:
+ {
+ static const D3DFormat info(128, 1, 1, 32, 32, 32, 32, 0, 0, 0,
+ Format::ID::R32G32B32A32_FLOAT);
+ return info;
+ }
+
+ case D3DFMT_D16:
+ {
+ static const D3DFormat info(16, 1, 1, 0, 0, 0, 0, 0, 16, 0, Format::ID::D16_UNORM);
+ return info;
+ }
+ case D3DFMT_D24S8:
+ {
+ static const D3DFormat info(32, 1, 1, 0, 0, 0, 0, 0, 24, 8,
+ Format::ID::D24_UNORM_S8_UINT);
+ return info;
+ }
+ case D3DFMT_D24X8:
+ {
+ static const D3DFormat info(32, 1, 1, 0, 0, 0, 0, 0, 24, 0, Format::ID::D16_UNORM);
+ return info;
+ }
+ case D3DFMT_D32:
+ {
+ static const D3DFormat info(32, 1, 1, 0, 0, 0, 0, 0, 32, 0, Format::ID::D32_UNORM);
+ return info;
+ }
+
+ case D3DFMT_DXT1:
+ {
+ static const D3DFormat info(64, 4, 4, 0, 0, 0, 0, 0, 0, 0,
+ Format::ID::BC1_RGBA_UNORM_BLOCK);
+ return info;
+ }
+ case D3DFMT_DXT3:
+ {
+ static const D3DFormat info(128, 4, 4, 0, 0, 0, 0, 0, 0, 0,
+ Format::ID::BC2_RGBA_UNORM_BLOCK);
+ return info;
+ }
+ case D3DFMT_DXT5:
+ {
+ static const D3DFormat info(128, 4, 4, 0, 0, 0, 0, 0, 0, 0,
+ Format::ID::BC3_RGBA_UNORM_BLOCK);
+ return info;
+ }
+
+ default:
+ {
+ static const D3DFormat defaultInfo;
+ return defaultInfo;
+ }
+ }
+}
typedef std::pair<GLint, InitializeTextureDataFunction> InternalFormatInitialzerPair;
typedef std::map<GLint, InitializeTextureDataFunction> InternalFormatInitialzerMap;
static InternalFormatInitialzerMap BuildInternalFormatInitialzerMap()
{
+ using namespace angle; // For image initialization functions
+
InternalFormatInitialzerMap map;
map.insert(InternalFormatInitialzerPair(GL_RGB16F, Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>));
@@ -175,28 +231,6 @@ static InternalFormatInitialzerMap BuildInternalFormatInitialzerMap()
return map;
}
-// Each GL internal format corresponds to one D3D format and data loading function.
-// Due to not all formats being available all the time, some of the function/format types are wrapped
-// in templates that perform format support queries on a Renderer9 object which is supplied
-// when requesting the function or format.
-
-typedef bool(*FallbackPredicateFunction)();
-
-template <FallbackPredicateFunction pred, LoadImageFunction prefered, LoadImageFunction fallback>
-static void FallbackLoad(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- if (pred())
- {
- prefered(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch);
- }
- else
- {
- fallback(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch);
- }
-}
-
static void UnreachableLoad(size_t width, size_t height, size_t depth,
const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
@@ -210,7 +244,7 @@ typedef std::map<GLenum, TextureFormat> D3D9FormatMap;
TextureFormat::TextureFormat()
: texFormat(D3DFMT_UNKNOWN),
renderFormat(D3DFMT_UNKNOWN),
- dataInitializerFunction(NULL),
+ dataInitializerFunction(nullptr),
loadFunction(UnreachableLoad)
{
}
@@ -224,7 +258,8 @@ static inline void InsertD3D9FormatInfo(D3D9FormatMap *map, GLenum internalForma
static const InternalFormatInitialzerMap dataInitializationMap = BuildInternalFormatInitialzerMap();
InternalFormatInitialzerMap::const_iterator dataInitIter = dataInitializationMap.find(internalFormat);
- info.dataInitializerFunction = (dataInitIter != dataInitializationMap.end()) ? dataInitIter->second : NULL;
+ info.dataInitializerFunction =
+ (dataInitIter != dataInitializationMap.end()) ? dataInitIter->second : nullptr;
info.loadFunction = loadFunction;
@@ -233,8 +268,11 @@ static inline void InsertD3D9FormatInfo(D3D9FormatMap *map, GLenum internalForma
static D3D9FormatMap BuildD3D9FormatMap()
{
+ using namespace angle; // For image loading functions
+
D3D9FormatMap map;
+ // clang-format off
// | Internal format | Texture format | Render format | Load function |
InsertD3D9FormatInfo(&map, GL_NONE, D3DFMT_NULL, D3DFMT_NULL, UnreachableLoad );
@@ -268,11 +306,11 @@ static D3D9FormatMap BuildD3D9FormatMap()
InsertD3D9FormatInfo(&map, GL_LUMINANCE16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadL16FToRGBA16F );
InsertD3D9FormatInfo(&map, GL_LUMINANCE_ALPHA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadLA16FToRGBA16F );
- InsertD3D9FormatInfo(&map, GL_ALPHA8_EXT, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FallbackLoad<gl::supportsSSE2, LoadA8ToBGRA8_SSE2, LoadA8ToBGRA8>);
+ InsertD3D9FormatInfo(&map, GL_ALPHA8_EXT, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadA8ToBGRA8 );
InsertD3D9FormatInfo(&map, GL_RGB8_OES, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadRGB8ToBGRX8 );
InsertD3D9FormatInfo(&map, GL_RGB565, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadR5G6B5ToBGRA8 );
- InsertD3D9FormatInfo(&map, GL_RGBA8_OES, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FallbackLoad<gl::supportsSSE2, LoadRGBA8ToBGRA8_SSE2, LoadRGBA8ToBGRA8>);
+ InsertD3D9FormatInfo(&map, GL_RGBA8_OES, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGBA8ToBGRA8 );
InsertD3D9FormatInfo(&map, GL_RGBA4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGBA4ToBGRA8 );
InsertD3D9FormatInfo(&map, GL_RGB5_A1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGB5A1ToBGRA8 );
InsertD3D9FormatInfo(&map, GL_R8_EXT, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadR8ToBGRX8 );
@@ -291,6 +329,7 @@ static D3D9FormatMap BuildD3D9FormatMap()
// then changing the format and loading function appropriately.
InsertD3D9FormatInfo(&map, GL_LUMINANCE8_EXT, D3DFMT_L8, D3DFMT_UNKNOWN, LoadToNative<GLubyte, 1> );
InsertD3D9FormatInfo(&map, GL_LUMINANCE8_ALPHA8_EXT, D3DFMT_A8L8, D3DFMT_UNKNOWN, LoadToNative<GLubyte, 2> );
+ // clang-format on
return map;
}
@@ -503,7 +542,7 @@ public:
VertexFormat::VertexFormat()
: conversionType(VERTEX_CONVERT_NONE),
outputElementSize(0),
- copyFunction(NULL),
+ copyFunction(nullptr),
nativeFormat(D3DDECLTYPE_UNUSED),
componentType(GL_NONE)
{
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h
index c55010760d..1bef320b53 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h
@@ -15,6 +15,8 @@
#include "common/platform.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/Format.h"
+#include "libANGLE/renderer/renderer_utils.h"
#include "libANGLE/renderer/d3d/formatutilsD3D.h"
namespace rx
@@ -25,11 +27,22 @@ class Renderer9;
namespace d3d9
{
-typedef std::map<std::pair<GLenum, GLenum>, ColorCopyFunction> FastCopyFunctionMap;
-
struct D3DFormat
{
D3DFormat();
+ D3DFormat(GLuint pixelBytes,
+ GLuint blockWidth,
+ GLuint blockHeight,
+ GLuint redBits,
+ GLuint greenBits,
+ GLuint blueBits,
+ GLuint alphaBits,
+ GLuint luminanceBits,
+ GLuint depthBits,
+ GLuint stencilBits,
+ angle::Format::ID formatID);
+
+ const angle::Format &info() const { return angle::Format::Get(formatID); }
GLuint pixelBytes;
GLuint blockWidth;
@@ -44,14 +57,9 @@ struct D3DFormat
GLuint depthBits;
GLuint stencilBits;
- GLenum internalFormat;
-
- MipGenerationFunction mipGenerationFunction;
- ColorReadFunction colorReadFunction;
-
- FastCopyFunctionMap fastCopyFunctions;
- ColorCopyFunction getFastCopyFunction(GLenum format, GLenum type) const;
+ angle::Format::ID formatID;
};
+
const D3DFormat &GetD3DFormatInfo(D3DFORMAT format);
struct VertexFormat
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
index 8622dc4d13..fd451a6e51 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
@@ -17,7 +17,9 @@
#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
#include "libANGLE/renderer/d3d/FramebufferD3D.h"
-#include "libANGLE/renderer/d3d/WorkaroundsD3D.h"
+#include "libANGLE/renderer/driver_utils.h"
+#include "platform/Platform.h"
+#include "platform/WorkaroundsD3D.h"
#include "third_party/systeminfo/SystemInfo.h"
@@ -133,21 +135,22 @@ D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap)
return d3dWrap;
}
-D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace)
+D3DCULL ConvertCullMode(gl::CullFaceMode cullFace, GLenum frontFace)
{
D3DCULL cull = D3DCULL_CCW;
switch (cullFace)
{
- case GL_FRONT:
- cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW);
- break;
- case GL_BACK:
- cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW);
- break;
- case GL_FRONT_AND_BACK:
- cull = D3DCULL_NONE; // culling will be handled during draw
- break;
- default: UNREACHABLE();
+ case gl::CullFaceMode::Front:
+ cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW);
+ break;
+ case gl::CullFaceMode::Back:
+ cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW);
+ break;
+ case gl::CullFaceMode::FrontAndBack:
+ cull = D3DCULL_NONE; // culling will be handled during draw
+ break;
+ default:
+ UNREACHABLE();
}
return cull;
@@ -264,6 +267,21 @@ void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DT
}
}
+D3DQUERYTYPE ConvertQueryType(GLenum queryType)
+{
+ switch (queryType)
+ {
+ case GL_ANY_SAMPLES_PASSED_EXT:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+ return D3DQUERYTYPE_OCCLUSION;
+ case GL_COMMANDS_COMPLETED_CHROMIUM:
+ return D3DQUERYTYPE_EVENT;
+ default:
+ UNREACHABLE();
+ return static_cast<D3DQUERYTYPE>(0);
+ }
+}
+
D3DMULTISAMPLE_TYPE GetMultisampleType(GLuint samples)
{
return (samples > 1) ? static_cast<D3DMULTISAMPLE_TYPE>(samples) : D3DMULTISAMPLE_NONE;
@@ -291,8 +309,8 @@ GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type)
bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format)
{
- GLenum internalFormat = d3d9::GetD3DFormatInfo(d3dformat).internalFormat;
- GLenum convertedFormat = gl::GetInternalFormatInfo(internalFormat).format;
+ GLenum internalFormat = d3d9::GetD3DFormatInfo(d3dformat).info().glInternalFormat;
+ GLenum convertedFormat = gl::GetSizedInternalFormatInfo(internalFormat).format;
return convertedFormat == format;
}
@@ -302,7 +320,7 @@ static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, IDirect3
gl::TextureCaps textureCaps;
const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalFormat);
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
if (d3dFormatInfo.texFormat != D3DFMT_UNKNOWN)
{
@@ -333,7 +351,8 @@ static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, IDirect3
{
D3DMULTISAMPLE_TYPE multisampleType = D3DMULTISAMPLE_TYPE(i);
- HRESULT result = d3d9->CheckDeviceMultiSampleType(adapter, deviceType, d3dFormatInfo.renderFormat, TRUE, multisampleType, NULL);
+ HRESULT result = d3d9->CheckDeviceMultiSampleType(
+ adapter, deviceType, d3dFormatInfo.renderFormat, TRUE, multisampleType, nullptr);
if (SUCCEEDED(result))
{
textureCaps.sampleCounts.insert(i);
@@ -364,18 +383,17 @@ void GenerateCaps(IDirect3D9 *d3d9,
d3d9->GetAdapterDisplayMode(adapter, &currentDisplayMode);
GLuint maxSamples = 0;
- const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats();
- for (gl::FormatSet::const_iterator internalFormat = allFormats.begin(); internalFormat != allFormats.end(); ++internalFormat)
+ for (GLenum internalFormat : gl::GetAllSizedInternalFormats())
{
- gl::TextureCaps textureCaps = GenerateTextureFormatCaps(*internalFormat, d3d9, deviceType, adapter,
- currentDisplayMode.Format);
- textureCapsMap->insert(*internalFormat, textureCaps);
+ gl::TextureCaps textureCaps = GenerateTextureFormatCaps(internalFormat, d3d9, deviceType,
+ adapter, currentDisplayMode.Format);
+ textureCapsMap->insert(internalFormat, textureCaps);
maxSamples = std::max(maxSamples, textureCaps.getMaxSamples());
- if (gl::GetInternalFormatInfo(*internalFormat).compressed)
+ if (gl::GetSizedInternalFormatInfo(internalFormat).compressed)
{
- caps->compressedTextureFormats.push_back(*internalFormat);
+ caps->compressedTextureFormats.push_back(internalFormat);
}
}
@@ -444,6 +462,8 @@ void GenerateCaps(IDirect3D9 *d3d9,
// Vertex shader limits
caps->maxVertexAttributes = 16;
+ // Vertex Attrib Binding not supported.
+ caps->maxVertexAttribBindings = caps->maxVertexAttributes;
const size_t MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256;
caps->maxVertexUniformVectors =
@@ -525,12 +545,12 @@ void GenerateCaps(IDirect3D9 *d3d9,
{
// ATI cards on XP have problems with non-power-of-two textures.
extensions->textureNPOT = !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
- !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
- !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) &&
- !(!isWindowsVistaOrGreater() && adapterId.VendorId == VENDOR_ID_AMD);
+ !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
+ !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) &&
+ !(!isWindowsVistaOrGreater() && IsAMD(adapterId.VendorId));
// Disable depth texture support on AMD cards (See ANGLE issue 839)
- if (adapterId.VendorId == VENDOR_ID_AMD)
+ if (IsAMD(adapterId.VendorId))
{
extensions->depthTextures = false;
}
@@ -548,18 +568,21 @@ void GenerateCaps(IDirect3D9 *d3d9,
extensions->maxTextureAnisotropy = static_cast<GLfloat>(deviceCaps.MaxAnisotropy);
// Check occlusion query support by trying to create one
- IDirect3DQuery9 *occlusionQuery = NULL;
+ IDirect3DQuery9 *occlusionQuery = nullptr;
extensions->occlusionQueryBoolean = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery;
SafeRelease(occlusionQuery);
// Check event query support by trying to create one
- IDirect3DQuery9 *eventQuery = NULL;
+ IDirect3DQuery9 *eventQuery = nullptr;
extensions->fence = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery;
SafeRelease(eventQuery);
- extensions->timerQuery = false; // Unimplemented
extensions->disjointTimerQuery = false;
extensions->robustness = true;
+ // It seems that only DirectX 10 and higher enforce the well-defined behavior of always
+ // returning zero values when out-of-bounds reads. See
+ // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_robustness.txt
+ extensions->robustBufferAccessBehavior = false;
extensions->blendMinMax = true;
extensions->framebufferBlit = true;
extensions->framebufferMultisample = true;
@@ -575,10 +598,11 @@ void GenerateCaps(IDirect3D9 *d3d9,
extensions->colorBufferFloat = false;
extensions->debugMarker = true;
extensions->eglImage = true;
+ extensions->eglImageExternal = true;
extensions->unpackSubimage = true;
extensions->packSubimage = true;
- extensions->vertexArrayObject = true;
- extensions->noError = true;
+ extensions->syncQuery = extensions->fence;
+ extensions->copyTexture = true;
// D3D9 has no concept of separate masks and refs for front and back faces in the depth stencil
// state.
@@ -625,15 +649,23 @@ void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsize
*levelOffset = upsampleCount;
}
-WorkaroundsD3D GenerateWorkarounds()
+angle::WorkaroundsD3D GenerateWorkarounds()
{
- WorkaroundsD3D workarounds;
+ angle::WorkaroundsD3D workarounds;
workarounds.mrtPerfWorkaround = true;
workarounds.setDataFasterThanImageUpload = false;
workarounds.useInstancedPointSpriteEmulation = false;
+
+ // TODO(jmadill): Disable workaround when we have a fixed compiler DLL.
+ workarounds.expandIntegerPowExpressions = true;
+
+ // Call platform hooks for testing overrides.
+ auto *platform = ANGLEPlatformCurrent();
+ platform->overrideWorkaroundsD3D(platform, &workarounds);
+
return workarounds;
}
-}
+} // namespace d3d9
-}
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h
index aa494adb62..5b65b8910a 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h
@@ -10,9 +10,10 @@
#ifndef LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_
#define LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_
-#include "libANGLE/angletypes.h"
+#include "common/Color.h"
#include "libANGLE/Caps.h"
#include "libANGLE/Error.h"
+#include "platform/WorkaroundsD3D.h"
namespace gl
{
@@ -22,7 +23,6 @@ class FramebufferAttachment;
namespace rx
{
class RenderTarget9;
-struct WorkaroundsD3D;
namespace gl_d3d9
{
@@ -33,12 +33,13 @@ D3DBLEND ConvertBlendFunc(GLenum blend);
D3DBLENDOP ConvertBlendOp(GLenum blendOp);
D3DSTENCILOP ConvertStencilOp(GLenum stencilOp);
D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap);
-D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace);
+D3DCULL ConvertCullMode(gl::CullFaceMode cullFace, GLenum frontFace);
D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace);
DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha);
D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy);
void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter,
float *d3dLodBias, float maxAnisotropy, size_t baseLevel);
+D3DQUERYTYPE ConvertQueryType(GLenum queryType);
D3DMULTISAMPLE_TYPE GetMultisampleType(GLuint samples);
@@ -86,9 +87,9 @@ inline bool isDeviceLostError(HRESULT errorCode)
}
}
-WorkaroundsD3D GenerateWorkarounds();
+angle::WorkaroundsD3D GenerateWorkarounds();
}
-}
+} // namespace d3d9
#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps
index dc357d0fa6..ecc593cc78 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps
@@ -24,6 +24,23 @@ float4 luminanceps(float4 texcoord : TEXCOORD0) : COLOR
return (tex2D(tex, texcoord.xy).xw * mult.xw + add.xw).xxxy;
};
+float4 luminancepremultps(float4 texcoord : TEXCOORD0) : COLOR
+{
+ float4 luma = tex2D(tex, texcoord.xy).xxxw;
+ luma.rgb *= luma.a;
+ return luma * mult + add;
+};
+
+float4 luminanceunmultps(float4 texcoord : TEXCOORD0) : COLOR
+{
+ float4 luma = tex2D(tex, texcoord.xy).xxxw;
+ if (luma.a > 0.0f)
+ {
+ luma.rgb /= luma.a;
+ }
+ return luma * mult + add;
+};
+
// RGB/A Component Mask Pixel Shader
// Performs a mad operation using the texture's RGBA data with mult.xyzw and add.xyzw.
// Returns data in the form of rgba
@@ -31,3 +48,20 @@ float4 componentmaskps(float4 texcoord : TEXCOORD0) : COLOR
{
return tex2D(tex, texcoord.xy) * mult + add;
};
+
+float4 componentmaskpremultps(float4 texcoord : TEXCOORD0) : COLOR
+{
+ float4 color = tex2D(tex, texcoord.xy);
+ color.rgb *= color.a;
+ return color * mult + add;
+};
+
+float4 componentmaskunmultps(float4 texcoord : TEXCOORD0) : COLOR
+{
+ float4 color = tex2D(tex, texcoord.xy);
+ if (color.a > 0.0f)
+ {
+ color.rgb /= color.a;
+ }
+ return color * mult + add;
+};
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs
index 3a36980b93..c68395a69c 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs
@@ -11,6 +11,7 @@ struct VS_OUTPUT
};
uniform float4 halfPixelSize : c0;
+uniform float4 texcoordOffset : c1;
// Standard Vertex Shader
// Input 0 is the homogenous position.
@@ -22,22 +23,7 @@ VS_OUTPUT standardvs(in float4 position : POSITION)
VS_OUTPUT Out;
Out.position = position + halfPixelSize;
- Out.texcoord = position * float4(0.5, -0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0);
-
- return Out;
-};
-
-// Flip Y Vertex Shader
-// Input 0 is the homogenous position.
-// Outputs the homogenous position as-is.
-// Outputs a tex coord with (0,1) in the upper-left corner of the screen and (1,0) in the bottom right.
-// C0.XY must be the half-pixel width and height. C0.ZW must be 0.
-VS_OUTPUT flipyvs(in float4 position : POSITION)
-{
- VS_OUTPUT Out;
-
- Out.position = position + halfPixelSize;
- Out.texcoord = position * float4(0.5, 0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0);
+ Out.texcoord = ((position * float4(0.5, -0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0)) * float4(texcoordOffset.zw, 1.0, 1.0)) + float4(texcoordOffset.xy, 0, 0);
return Out;
};
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.cpp
deleted file mode 100644
index e1c955eb06..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-//
-// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// formatutils9.cpp: Queries for GL image formats and their translations to D3D
-// formats.
-
-#include "libANGLE/renderer/d3d/formatutilsD3D.h"
-
-#include <map>
-
-#include "common/debug.h"
-#include "libANGLE/renderer/d3d/imageformats.h"
-#include "libANGLE/renderer/d3d/copyimage.h"
-
-namespace rx
-{
-
-typedef std::pair<GLenum, GLenum> FormatTypePair;
-typedef std::pair<FormatTypePair, ColorWriteFunction> FormatWriteFunctionPair;
-typedef std::map<FormatTypePair, ColorWriteFunction> FormatWriteFunctionMap;
-
-static inline void InsertFormatWriteFunctionMapping(FormatWriteFunctionMap *map, GLenum format, GLenum type,
- ColorWriteFunction writeFunc)
-{
- map->insert(FormatWriteFunctionPair(FormatTypePair(format, type), writeFunc));
-}
-
-static FormatWriteFunctionMap BuildFormatWriteFunctionMap()
-{
- FormatWriteFunctionMap map;
-
- // | Format | Type | Color write function |
- InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_BYTE, WriteColor<R8G8B8A8, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_BYTE, WriteColor<R8G8B8A8S, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, WriteColor<R4G4B4A4, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, WriteColor<R5G5B5A1, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, WriteColor<R10G10B10A2, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_FLOAT, WriteColor<R32G32B32A32F, GLfloat>);
- InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_HALF_FLOAT, WriteColor<R16G16B16A16F, GLfloat>);
- InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_HALF_FLOAT_OES, WriteColor<R16G16B16A16F, GLfloat>);
-
- InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, WriteColor<R8G8B8A8, GLuint> );
- InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_BYTE, WriteColor<R8G8B8A8S, GLint> );
- InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, WriteColor<R16G16B16A16, GLuint> );
- InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_SHORT, WriteColor<R16G16B16A16S, GLint> );
- InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT, WriteColor<R32G32B32A32, GLuint> );
- InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_INT, WriteColor<R32G32B32A32S, GLint> );
- InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, WriteColor<R10G10B10A2, GLuint> );
-
- InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_BYTE, WriteColor<R8G8B8, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_BYTE, WriteColor<R8G8B8S, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, WriteColor<R5G6B5, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, WriteColor<R11G11B10F, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, WriteColor<R9G9B9E5, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_FLOAT, WriteColor<R32G32B32F, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_HALF_FLOAT, WriteColor<R16G16B16F, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_HALF_FLOAT_OES, WriteColor<R16G16B16F, GLfloat> );
-
- InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, WriteColor<R8G8B8, GLuint> );
- InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_BYTE, WriteColor<R8G8B8S, GLint> );
- InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, WriteColor<R16G16B16, GLuint> );
- InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_SHORT, WriteColor<R16G16B16S, GLint> );
- InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_INT, WriteColor<R32G32B32, GLuint> );
- InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_INT, WriteColor<R32G32B32S, GLint> );
-
- InsertFormatWriteFunctionMapping(&map, GL_RG, GL_UNSIGNED_BYTE, WriteColor<R8G8, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_RG, GL_BYTE, WriteColor<R8G8S, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_RG, GL_FLOAT, WriteColor<R32G32F, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_RG, GL_HALF_FLOAT, WriteColor<R16G16F, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_RG, GL_HALF_FLOAT_OES, WriteColor<R16G16F, GLfloat> );
-
- InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_BYTE, WriteColor<R8G8, GLuint> );
- InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_BYTE, WriteColor<R8G8S, GLint> );
- InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_SHORT, WriteColor<R16G16, GLuint> );
- InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_SHORT, WriteColor<R16G16S, GLint> );
- InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_INT, WriteColor<R32G32, GLuint> );
- InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_INT, WriteColor<R32G32S, GLint> );
-
- InsertFormatWriteFunctionMapping(&map, GL_RED, GL_UNSIGNED_BYTE, WriteColor<R8, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_RED, GL_BYTE, WriteColor<R8S, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_RED, GL_FLOAT, WriteColor<R32F, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_RED, GL_HALF_FLOAT, WriteColor<R16F, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_RED, GL_HALF_FLOAT_OES, WriteColor<R16F, GLfloat> );
-
- InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_BYTE, WriteColor<R8, GLuint> );
- InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_BYTE, WriteColor<R8S, GLint> );
- InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_SHORT, WriteColor<R16, GLuint> );
- InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_SHORT, WriteColor<R16S, GLint> );
- InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_INT, WriteColor<R32, GLuint> );
- InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_INT, WriteColor<R32S, GLint> );
-
- InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, WriteColor<L8A8, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, WriteColor<L8, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_UNSIGNED_BYTE, WriteColor<A8, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, WriteColor<L32A32F, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_FLOAT, WriteColor<L32F, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_FLOAT, WriteColor<A32F, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, WriteColor<L16A16F, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, WriteColor<L16A16F, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT, WriteColor<L16F, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, WriteColor<L16F, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_HALF_FLOAT, WriteColor<A16F, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_HALF_FLOAT_OES, WriteColor<A16F, GLfloat> );
-
- InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_BYTE, WriteColor<B8G8R8A8, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, WriteColor<A4R4G4B4, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, WriteColor<A1R5G5B5, GLfloat> );
-
- InsertFormatWriteFunctionMapping(&map, GL_SRGB_EXT, GL_UNSIGNED_BYTE, WriteColor<R8G8B8, GLfloat> );
- InsertFormatWriteFunctionMapping(&map, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, WriteColor<R8G8B8A8, GLfloat> );
-
- InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, NULL );
- InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, NULL );
- InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, NULL );
- InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, NULL );
-
- InsertFormatWriteFunctionMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL );
- InsertFormatWriteFunctionMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL );
- InsertFormatWriteFunctionMapping(&map, GL_DEPTH_COMPONENT, GL_FLOAT, NULL );
-
- InsertFormatWriteFunctionMapping(&map, GL_STENCIL, GL_UNSIGNED_BYTE, NULL );
-
- InsertFormatWriteFunctionMapping(&map, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL );
- InsertFormatWriteFunctionMapping(&map, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, NULL );
-
- return map;
-}
-
-ColorWriteFunction GetColorWriteFunction(GLenum format, GLenum type)
-{
- static const FormatWriteFunctionMap formatTypeMap = BuildFormatWriteFunctionMap();
- FormatWriteFunctionMap::const_iterator iter = formatTypeMap.find(FormatTypePair(format, type));
- ASSERT(iter != formatTypeMap.end());
- if (iter != formatTypeMap.end())
- {
- return iter->second;
- }
- else
- {
- return NULL;
- }
-}
-
-}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h
index 6dd59ca94b..a245a0432f 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h
@@ -15,24 +15,15 @@
#include <cstddef>
#include <stdint.h>
-namespace rx
-{
-
-typedef void (*MipGenerationFunction)(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
- const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
- uint8_t *destData, size_t destRowPitch, size_t destDepthPitch);
+#include <map>
-typedef void (*LoadImageFunction)(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-typedef void (*InitializeTextureDataFunction)(size_t width, size_t height, size_t depth,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-typedef void (*ColorReadFunction)(const uint8_t *source, uint8_t *dest);
-typedef void (*ColorWriteFunction)(const uint8_t *source, uint8_t *dest);
-typedef void (*ColorCopyFunction)(const uint8_t *source, uint8_t *dest);
+namespace gl
+{
+struct FormatType;
+}
+namespace rx
+{
typedef void (*VertexCopyFunction)(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
enum VertexConversionType
@@ -42,9 +33,6 @@ enum VertexConversionType
VERTEX_CONVERT_GPU = 2,
VERTEX_CONVERT_BOTH = 3
};
-
-ColorWriteFunction GetColorWriteFunction(GLenum format, GLenum type);
-
-}
+} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_FORMATUTILSD3D_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.h
deleted file mode 100644
index 398ef26b30..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.h
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// generatemip.h: Defines the GenerateMip function, templated on the format
-// type of the image for which mip levels are being generated.
-
-#ifndef LIBANGLE_RENDERER_D3D_GENERATEMIP_H_
-#define LIBANGLE_RENDERER_D3D_GENERATEMIP_H_
-
-#include "libANGLE/renderer/d3d/imageformats.h"
-#include "libANGLE/angletypes.h"
-
-namespace rx
-{
-
-template <typename T>
-inline void GenerateMip(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
- const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
- uint8_t *destData, size_t destRowPitch, size_t destDepthPitch);
-
-}
-
-#include "generatemip.inl"
-
-#endif // LIBANGLE_RENDERER_D3D_GENERATEMIP_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.inl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.inl
deleted file mode 100644
index 265783641e..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.inl
+++ /dev/null
@@ -1,266 +0,0 @@
-//
-// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// generatemip.inl: Defines the GenerateMip function, templated on the format
-// type of the image for which mip levels are being generated.
-
-#include "common/mathutil.h"
-
-namespace rx
-{
-
-namespace priv
-{
-
-template <typename T>
-static inline T *GetPixel(uint8_t *data, size_t x, size_t y, size_t z, size_t rowPitch, size_t depthPitch)
-{
- return reinterpret_cast<T*>(data + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch));
-}
-
-template <typename T>
-static inline const T *GetPixel(const uint8_t *data, size_t x, size_t y, size_t z, size_t rowPitch, size_t depthPitch)
-{
- return reinterpret_cast<const T*>(data + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch));
-}
-
-template <typename T>
-static void GenerateMip_Y(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
- const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
- size_t destWidth, size_t destHeight, size_t destDepth,
- uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
-{
- ASSERT(sourceWidth == 1);
- ASSERT(sourceHeight > 1);
- ASSERT(sourceDepth == 1);
-
- for (size_t y = 0; y < destHeight; y++)
- {
- const T *src0 = GetPixel<T>(sourceData, 0, y * 2, 0, sourceRowPitch, sourceDepthPitch);
- const T *src1 = GetPixel<T>(sourceData, 0, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch);
- T *dst = GetPixel<T>(destData, 0, y, 0, destRowPitch, destDepthPitch);
-
- T::average(dst, src0, src1);
- }
-}
-
-template <typename T>
-static void GenerateMip_X(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
- const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
- size_t destWidth, size_t destHeight, size_t destDepth,
- uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
-{
- ASSERT(sourceWidth > 1);
- ASSERT(sourceHeight == 1);
- ASSERT(sourceDepth == 1);
-
- for (size_t x = 0; x < destWidth; x++)
- {
- const T *src0 = GetPixel<T>(sourceData, x * 2, 0, 0, sourceRowPitch, sourceDepthPitch);
- const T *src1 = GetPixel<T>(sourceData, x * 2 + 1, 0, 0, sourceRowPitch, sourceDepthPitch);
- T *dst = GetPixel<T>(destData, x, 0, 0, destRowPitch, destDepthPitch);
-
- T::average(dst, src0, src1);
- }
-}
-
-template <typename T>
-static void GenerateMip_Z(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
- const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
- size_t destWidth, size_t destHeight, size_t destDepth,
- uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
-{
- ASSERT(sourceWidth == 1);
- ASSERT(sourceHeight == 1);
- ASSERT(sourceDepth > 1);
-
- for (size_t z = 0; z < destDepth; z++)
- {
- const T *src0 = GetPixel<T>(sourceData, 0, 0, z * 2, sourceRowPitch, sourceDepthPitch);
- const T *src1 = GetPixel<T>(sourceData, 0, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
- T *dst = GetPixel<T>(destData, 0, 0, z, destRowPitch, destDepthPitch);
-
- T::average(dst, src0, src1);
- }
-}
-
-template <typename T>
-static void GenerateMip_XY(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
- const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
- size_t destWidth, size_t destHeight, size_t destDepth,
- uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
-{
- ASSERT(sourceWidth > 1);
- ASSERT(sourceHeight > 1);
- ASSERT(sourceDepth == 1);
-
- for (size_t y = 0; y < destHeight; y++)
- {
- for (size_t x = 0; x < destWidth; x++)
- {
- const T *src0 = GetPixel<T>(sourceData, x * 2, y * 2, 0, sourceRowPitch, sourceDepthPitch);
- const T *src1 = GetPixel<T>(sourceData, x * 2, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch);
- const T *src2 = GetPixel<T>(sourceData, x * 2 + 1, y * 2, 0, sourceRowPitch, sourceDepthPitch);
- const T *src3 = GetPixel<T>(sourceData, x * 2 + 1, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch);
- T *dst = GetPixel<T>(destData, x, y, 0, destRowPitch, destDepthPitch);
-
- T tmp0, tmp1;
-
- T::average(&tmp0, src0, src1);
- T::average(&tmp1, src2, src3);
- T::average(dst, &tmp0, &tmp1);
- }
- }
-}
-
-template <typename T>
-static void GenerateMip_YZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
- const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
- size_t destWidth, size_t destHeight, size_t destDepth,
- uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
-{
- ASSERT(sourceWidth == 1);
- ASSERT(sourceHeight > 1);
- ASSERT(sourceDepth > 1);
-
- for (size_t z = 0; z < destDepth; z++)
- {
- for (size_t y = 0; y < destHeight; y++)
- {
- const T *src0 = GetPixel<T>(sourceData, 0, y * 2, z * 2, sourceRowPitch, sourceDepthPitch);
- const T *src1 = GetPixel<T>(sourceData, 0, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
- const T *src2 = GetPixel<T>(sourceData, 0, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch);
- const T *src3 = GetPixel<T>(sourceData, 0, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
- T *dst = GetPixel<T>(destData, 0, y, z, destRowPitch, destDepthPitch);
-
- T tmp0, tmp1;
-
- T::average(&tmp0, src0, src1);
- T::average(&tmp1, src2, src3);
- T::average(dst, &tmp0, &tmp1);
- }
- }
-}
-
-template <typename T>
-static void GenerateMip_XZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
- const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
- size_t destWidth, size_t destHeight, size_t destDepth,
- uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
-{
- ASSERT(sourceWidth > 1);
- ASSERT(sourceHeight == 1);
- ASSERT(sourceDepth > 1);
-
- for (size_t z = 0; z < destDepth; z++)
- {
- for (size_t x = 0; x < destWidth; x++)
- {
- const T *src0 = GetPixel<T>(sourceData, x * 2, 0, z * 2, sourceRowPitch, sourceDepthPitch);
- const T *src1 = GetPixel<T>(sourceData, x * 2, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
- const T *src2 = GetPixel<T>(sourceData, x * 2 + 1, 0, z * 2, sourceRowPitch, sourceDepthPitch);
- const T *src3 = GetPixel<T>(sourceData, x * 2 + 1, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
- T *dst = GetPixel<T>(destData, x, 0, z, destRowPitch, destDepthPitch);
-
- T tmp0, tmp1;
-
- T::average(&tmp0, src0, src1);
- T::average(&tmp1, src2, src3);
- T::average(dst, &tmp0, &tmp1);
- }
- }
-}
-
-template <typename T>
-static void GenerateMip_XYZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
- const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
- size_t destWidth, size_t destHeight, size_t destDepth,
- uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
-{
- ASSERT(sourceWidth > 1);
- ASSERT(sourceHeight > 1);
- ASSERT(sourceDepth > 1);
-
- for (size_t z = 0; z < destDepth; z++)
- {
- for (size_t y = 0; y < destHeight; y++)
- {
- for (size_t x = 0; x < destWidth; x++)
- {
- const T *src0 = GetPixel<T>(sourceData, x * 2, y * 2, z * 2, sourceRowPitch, sourceDepthPitch);
- const T *src1 = GetPixel<T>(sourceData, x * 2, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
- const T *src2 = GetPixel<T>(sourceData, x * 2, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch);
- const T *src3 = GetPixel<T>(sourceData, x * 2, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
- const T *src4 = GetPixel<T>(sourceData, x * 2 + 1, y * 2, z * 2, sourceRowPitch, sourceDepthPitch);
- const T *src5 = GetPixel<T>(sourceData, x * 2 + 1, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
- const T *src6 = GetPixel<T>(sourceData, x * 2 + 1, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch);
- const T *src7 = GetPixel<T>(sourceData, x * 2 + 1, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch);
- T *dst = GetPixel<T>(destData, x, y, z, destRowPitch, destDepthPitch);
-
- T tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
-
- T::average(&tmp0, src0, src1);
- T::average(&tmp1, src2, src3);
- T::average(&tmp2, src4, src5);
- T::average(&tmp3, src6, src7);
-
- T::average(&tmp4, &tmp0, &tmp1);
- T::average(&tmp5, &tmp2, &tmp3);
-
- T::average(dst, &tmp4, &tmp5);
- }
- }
- }
-}
-
-
-typedef void (*MipGenerationFunction)(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
- const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
- size_t destWidth, size_t destHeight, size_t destDepth,
- uint8_t *destData, size_t destRowPitch, size_t destDepthPitch);
-
-template <typename T>
-static MipGenerationFunction GetMipGenerationFunction(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth)
-{
- uint8_t index = ((sourceWidth > 1) ? 1 : 0) |
- ((sourceHeight > 1) ? 2 : 0) |
- ((sourceDepth > 1) ? 4 : 0);
-
- switch (index)
- {
- case 0: return NULL;
- case 1: return GenerateMip_X<T>; // W x 1 x 1
- case 2: return GenerateMip_Y<T>; // 1 x H x 1
- case 3: return GenerateMip_XY<T>; // W x H x 1
- case 4: return GenerateMip_Z<T>; // 1 x 1 x D
- case 5: return GenerateMip_XZ<T>; // W x 1 x D
- case 6: return GenerateMip_YZ<T>; // 1 x H x D
- case 7: return GenerateMip_XYZ<T>; // W x H x D
- }
-
- UNREACHABLE();
- return NULL;
-}
-
-}
-
-template <typename T>
-inline void GenerateMip(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
- const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
- uint8_t *destData, size_t destRowPitch, size_t destDepthPitch)
-{
- size_t mipWidth = std::max<size_t>(1, sourceWidth >> 1);
- size_t mipHeight = std::max<size_t>(1, sourceHeight >> 1);
- size_t mipDepth = std::max<size_t>(1, sourceDepth >> 1);
-
- priv::MipGenerationFunction generationFunction = priv::GetMipGenerationFunction<T>(sourceWidth, sourceHeight, sourceDepth);
- ASSERT(generationFunction != NULL);
-
- generationFunction(sourceWidth, sourceHeight, sourceDepth, sourceData, sourceRowPitch, sourceDepthPitch,
- mipWidth, mipHeight, mipDepth, destData, destRowPitch, destDepthPitch);
-}
-
-}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/imageformats.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/imageformats.h
deleted file mode 100644
index 76f1830e64..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/imageformats.h
+++ /dev/null
@@ -1,1999 +0,0 @@
-//
-// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// imageformats.h: Defines image format types with functions for mip generation
-// and copying.
-
-#ifndef LIBANGLE_RENDERER_D3D_IMAGEFORMATS_H_
-#define LIBANGLE_RENDERER_D3D_IMAGEFORMATS_H_
-
-#include "libANGLE/angletypes.h"
-
-#include "common/mathutil.h"
-
-namespace rx
-{
-
-// Several structures share functionality for reading, writing or mipmapping but the layout
-// must match the texture format which the structure represents. If collapsing or typedefing
-// structs in this header, make sure the functionality and memory layout is exactly the same.
-
-struct L8
-{
- unsigned char L;
-
- static void readColor(gl::ColorF *dst, const L8 *src)
- {
- const float lum = gl::normalizedToFloat(src->L);
- dst->red = lum;
- dst->green = lum;
- dst->blue = lum;
- dst->alpha = 1.0f;
- }
-
- static void writeColor(L8 *dst, const gl::ColorF *src)
- {
- dst->L = gl::floatToNormalized<unsigned char>((src->red + src->green + src->blue) / 3.0f);
- }
-
- static void average(L8 *dst, const L8 *src1, const L8 *src2)
- {
- dst->L = gl::average(src1->L, src2->L);
- }
-};
-
-struct R8
-{
- unsigned char R;
-
- static void readColor(gl::ColorF *dst, const R8 *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = 0.0f;
- dst->blue = 0.0f;
- dst->alpha = 1.0f;
- }
-
- static void readColor(gl::ColorUI *dst, const R8 *src)
- {
- dst->red = src->R;
- dst->green = 0;
- dst->blue = 0;
- dst->alpha = 1;
- }
-
- static void writeColor(R8 *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<unsigned char>(src->red);
- }
-
- static void writeColor(R8 *dst, const gl::ColorUI *src)
- {
- dst->R = static_cast<unsigned char>(src->red);
- }
-
- static void average(R8 *dst, const R8 *src1, const R8 *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- }
-};
-
-struct A8
-{
- unsigned char A;
-
- static void readColor(gl::ColorF *dst, const A8 *src)
- {
- dst->red = 0.0f;
- dst->green = 0.0f;
- dst->blue = 0.0f;
- dst->alpha = gl::normalizedToFloat(src->A);
- }
-
- static void writeColor(A8 *dst, const gl::ColorF *src)
- {
- dst->A = gl::floatToNormalized<unsigned char>(src->alpha);
- }
-
- static void average(A8 *dst, const A8 *src1, const A8 *src2)
- {
- dst->A = gl::average(src1->A, src2->A);
- }
-};
-
-struct L8A8
-{
- unsigned char L;
- unsigned char A;
-
- static void readColor(gl::ColorF *dst, const L8A8 *src)
- {
- const float lum = gl::normalizedToFloat(src->L);
- dst->red = lum;
- dst->green = lum;
- dst->blue = lum;
- dst->alpha = gl::normalizedToFloat(src->A);
- }
-
- static void writeColor(L8A8 *dst, const gl::ColorF *src)
- {
- dst->L = gl::floatToNormalized<unsigned char>((src->red + src->green + src->blue) / 3.0f);
- dst->A = gl::floatToNormalized<unsigned char>(src->alpha);
- }
-
- static void average(L8A8 *dst, const L8A8 *src1, const L8A8 *src2)
- {
- *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2);
- }
-};
-
-struct A8L8
-{
- unsigned char A;
- unsigned char L;
-
- static void readColor(gl::ColorF *dst, const A8L8 *src)
- {
- const float lum = gl::normalizedToFloat(src->L);
- dst->red = lum;
- dst->green = lum;
- dst->blue = lum;
- dst->alpha = gl::normalizedToFloat(src->A);
- }
-
- static void writeColor(A8L8 *dst, const gl::ColorF *src)
- {
- dst->L = gl::floatToNormalized<unsigned char>((src->red + src->green + src->blue) / 3.0f);
- dst->A = gl::floatToNormalized<unsigned char>(src->alpha);
- }
-
- static void average(A8L8 *dst, const A8L8 *src1, const A8L8 *src2)
- {
- *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2);
- }
-};
-
-struct R8G8
-{
- unsigned char R;
- unsigned char G;
-
- static void readColor(gl::ColorF *dst, const R8G8 *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = gl::normalizedToFloat(src->G);
- dst->blue = 0.0f;
- dst->alpha = 1.0f;
- }
-
- static void readColor(gl::ColorUI *dst, const R8G8 *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = 0;
- dst->alpha = 1;
- }
-
- static void writeColor(R8G8 *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<unsigned char>(src->red);
- dst->G = gl::floatToNormalized<unsigned char>(src->green);
- }
-
- static void writeColor(R8G8 *dst, const gl::ColorUI *src)
- {
- dst->R = static_cast<unsigned char>(src->red);
- dst->G = static_cast<unsigned char>(src->green);
- }
-
- static void average(R8G8 *dst, const R8G8 *src1, const R8G8 *src2)
- {
- *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2);
- }
-};
-
-struct R8G8B8
-{
- unsigned char R;
- unsigned char G;
- unsigned char B;
-
- static void readColor(gl::ColorF *dst, const R8G8B8 *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = gl::normalizedToFloat(src->G);
- dst->blue = gl::normalizedToFloat(src->B);
- dst->alpha = 1.0f;
- }
-
- static void readColor(gl::ColorUI *dst, const R8G8B8 *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = src->G;
- dst->alpha = 1;
- }
-
- static void writeColor(R8G8B8 *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<unsigned char>(src->red);
- dst->G = gl::floatToNormalized<unsigned char>(src->green);
- dst->B = gl::floatToNormalized<unsigned char>(src->blue);
- }
-
- static void writeColor(R8G8B8 *dst, const gl::ColorUI *src)
- {
- dst->R = static_cast<unsigned char>(src->red);
- dst->G = static_cast<unsigned char>(src->green);
- dst->B = static_cast<unsigned char>(src->blue);
- }
-
- static void average(R8G8B8 *dst, const R8G8B8 *src1, const R8G8B8 *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- dst->G = gl::average(src1->G, src2->G);
- dst->B = gl::average(src1->B, src2->B);
- }
-};
-
-struct B8G8R8
-{
- unsigned char B;
- unsigned char G;
- unsigned char R;
-
- static void readColor(gl::ColorF *dst, const B8G8R8 *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = gl::normalizedToFloat(src->G);
- dst->blue = gl::normalizedToFloat(src->B);
- dst->alpha = 1.0f;
- }
-
- static void readColor(gl::ColorUI *dst, const B8G8R8 *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = src->G;
- dst->alpha = 1;
- }
-
- static void writeColor(B8G8R8 *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<unsigned char>(src->red);
- dst->G = gl::floatToNormalized<unsigned char>(src->green);
- dst->B = gl::floatToNormalized<unsigned char>(src->blue);
- }
-
- static void writeColor(B8G8R8 *dst, const gl::ColorUI *src)
- {
- dst->R = static_cast<unsigned char>(src->red);
- dst->G = static_cast<unsigned char>(src->green);
- dst->B = static_cast<unsigned char>(src->blue);
- }
-
- static void average(B8G8R8 *dst, const B8G8R8 *src1, const B8G8R8 *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- dst->G = gl::average(src1->G, src2->G);
- dst->B = gl::average(src1->B, src2->B);
- }
-};
-
-struct R5G6B5
-{
- // OpenGL ES 2.0.25 spec Section 3.6.2: "Components are packed with the first component in the most significant
- // bits of the bitfield, and successive component occupying progressively less significant locations"
- unsigned short RGB;
-
- static void readColor(gl::ColorF *dst, const R5G6B5 *src)
- {
- dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 11>(src->RGB));
- dst->green = gl::normalizedToFloat<6>(gl::getShiftedData<6, 5>(src->RGB));
- dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->RGB));
- dst->alpha = 1.0f;
- }
-
- static void writeColor(R5G6B5 *dst, const gl::ColorF *src)
- {
- dst->RGB = gl::shiftData<5, 11>(gl::floatToNormalized<5, unsigned short>(src->red)) |
- gl::shiftData<6, 5>(gl::floatToNormalized<6, unsigned short>(src->green)) |
- gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->blue));
- }
-
- static void average(R5G6B5 *dst, const R5G6B5 *src1, const R5G6B5 *src2)
- {
- dst->RGB = gl::shiftData<5, 11>(gl::average(gl::getShiftedData<5, 11>(src1->RGB), gl::getShiftedData<5, 11>(src2->RGB))) |
- gl::shiftData<6, 5>(gl::average(gl::getShiftedData<6, 5>(src1->RGB), gl::getShiftedData<6, 5>(src2->RGB))) |
- gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->RGB), gl::getShiftedData<5, 0>(src2->RGB)));
- }
-};
-
-struct A8R8G8B8
-{
- unsigned char A;
- unsigned char R;
- unsigned char G;
- unsigned char B;
-
- static void readColor(gl::ColorF *dst, const A8R8G8B8 *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = gl::normalizedToFloat(src->G);
- dst->blue = gl::normalizedToFloat(src->B);
- dst->alpha = gl::normalizedToFloat(src->A);
- }
-
- static void readColor(gl::ColorUI *dst, const A8R8G8B8 *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = src->B;
- dst->alpha = src->A;
- }
-
- static void writeColor(A8R8G8B8 *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<unsigned char>(src->red);
- dst->G = gl::floatToNormalized<unsigned char>(src->green);
- dst->B = gl::floatToNormalized<unsigned char>(src->blue);
- dst->A = gl::floatToNormalized<unsigned char>(src->alpha);
- }
-
- static void writeColor(A8R8G8B8 *dst, const gl::ColorUI *src)
- {
- dst->R = static_cast<unsigned char>(src->red);
- dst->G = static_cast<unsigned char>(src->green);
- dst->B = static_cast<unsigned char>(src->blue);
- dst->A = static_cast<unsigned char>(src->alpha);
- }
-
- static void average(A8R8G8B8 *dst, const A8R8G8B8 *src1, const A8R8G8B8 *src2)
- {
- *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2);
- }
-};
-
-struct R8G8B8A8
-{
- unsigned char R;
- unsigned char G;
- unsigned char B;
- unsigned char A;
-
- static void readColor(gl::ColorF *dst, const R8G8B8A8 *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = gl::normalizedToFloat(src->G);
- dst->blue = gl::normalizedToFloat(src->B);
- dst->alpha = gl::normalizedToFloat(src->A);
- }
-
- static void readColor(gl::ColorUI *dst, const R8G8B8A8 *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = src->B;
- dst->alpha = src->A;
- }
-
- static void writeColor(R8G8B8A8 *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<unsigned char>(src->red);
- dst->G = gl::floatToNormalized<unsigned char>(src->green);
- dst->B = gl::floatToNormalized<unsigned char>(src->blue);
- dst->A = gl::floatToNormalized<unsigned char>(src->alpha);
- }
-
- static void writeColor(R8G8B8A8 *dst, const gl::ColorUI *src)
- {
- dst->R = static_cast<unsigned char>(src->red);
- dst->G = static_cast<unsigned char>(src->green);
- dst->B = static_cast<unsigned char>(src->blue);
- dst->A = static_cast<unsigned char>(src->alpha);
- }
-
- static void average(R8G8B8A8 *dst, const R8G8B8A8 *src1, const R8G8B8A8 *src2)
- {
- *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2);
- }
-};
-
-struct B8G8R8A8
-{
- unsigned char B;
- unsigned char G;
- unsigned char R;
- unsigned char A;
-
- static void readColor(gl::ColorF *dst, const B8G8R8A8 *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = gl::normalizedToFloat(src->G);
- dst->blue = gl::normalizedToFloat(src->B);
- dst->alpha = gl::normalizedToFloat(src->A);
- }
-
- static void readColor(gl::ColorUI *dst, const B8G8R8A8 *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = src->B;
- dst->alpha = src->A;
- }
-
- static void writeColor(B8G8R8A8 *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<unsigned char>(src->red);
- dst->G = gl::floatToNormalized<unsigned char>(src->green);
- dst->B = gl::floatToNormalized<unsigned char>(src->blue);
- dst->A = gl::floatToNormalized<unsigned char>(src->alpha);
- }
-
- static void writeColor(B8G8R8A8 *dst, const gl::ColorUI *src)
- {
- dst->R = static_cast<unsigned char>(src->red);
- dst->G = static_cast<unsigned char>(src->green);
- dst->B = static_cast<unsigned char>(src->blue);
- dst->A = static_cast<unsigned char>(src->alpha);
- }
-
- static void average(B8G8R8A8 *dst, const B8G8R8A8 *src1, const B8G8R8A8 *src2)
- {
- *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2);
- }
-};
-
-struct B8G8R8X8
-{
- unsigned char B;
- unsigned char G;
- unsigned char R;
- unsigned char X;
-
- static void readColor(gl::ColorF *dst, const B8G8R8X8 *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = gl::normalizedToFloat(src->G);
- dst->blue = gl::normalizedToFloat(src->B);
- dst->alpha = 1.0f;
- }
-
- static void readColor(gl::ColorUI *dst, const B8G8R8X8 *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = src->B;
- dst->alpha = 1;
- }
-
- static void writeColor(B8G8R8X8 *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<unsigned char>(src->red);
- dst->G = gl::floatToNormalized<unsigned char>(src->green);
- dst->B = gl::floatToNormalized<unsigned char>(src->blue);
- dst->X = 255;
- }
-
- static void writeColor(B8G8R8X8 *dst, const gl::ColorUI *src)
- {
- dst->R = static_cast<unsigned char>(src->red);
- dst->G = static_cast<unsigned char>(src->green);
- dst->B = static_cast<unsigned char>(src->blue);
- dst->X = 255;
- }
-
- static void average(B8G8R8X8 *dst, const B8G8R8X8 *src1, const B8G8R8X8 *src2)
- {
- *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2);
- dst->X = 255;
- }
-};
-
-struct A1R5G5B5
-{
- unsigned short ARGB;
-
- static void readColor(gl::ColorF *dst, const A1R5G5B5 *src)
- {
- dst->alpha = gl::normalizedToFloat<1>(gl::getShiftedData<1, 15>(src->ARGB));
- dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 10>(src->ARGB));
- dst->green = gl::normalizedToFloat<5>(gl::getShiftedData<5, 5>(src->ARGB));
- dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->ARGB));
- }
-
- static void writeColor(A1R5G5B5 *dst, const gl::ColorF *src)
- {
- dst->ARGB = gl::shiftData<1, 15>(gl::floatToNormalized<1, unsigned short>(src->alpha)) |
- gl::shiftData<5, 10>(gl::floatToNormalized<5, unsigned short>(src->red)) |
- gl::shiftData<5, 5>(gl::floatToNormalized<5, unsigned short>(src->green)) |
- gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->blue));
- }
-
- static void average(A1R5G5B5 *dst, const A1R5G5B5 *src1, const A1R5G5B5 *src2)
- {
- dst->ARGB = gl::shiftData<1, 15>(gl::average(gl::getShiftedData<1, 15>(src1->ARGB), gl::getShiftedData<1, 15>(src2->ARGB))) |
- gl::shiftData<5, 10>(gl::average(gl::getShiftedData<5, 10>(src1->ARGB), gl::getShiftedData<5, 10>(src2->ARGB))) |
- gl::shiftData<5, 5>(gl::average(gl::getShiftedData<5, 5>(src1->ARGB), gl::getShiftedData<5, 5>(src2->ARGB))) |
- gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->ARGB), gl::getShiftedData<5, 0>(src2->ARGB)));
- }
-};
-
-struct R5G5B5A1
-{
- // OpenGL ES 2.0.25 spec Section 3.6.2: "Components are packed with the first component in the most significant
- // bits of the bitfield, and successive component occupying progressively less significant locations"
- unsigned short RGBA;
-
- static void readColor(gl::ColorF *dst, const R5G5B5A1 *src)
- {
- dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 11>(src->RGBA));
- dst->green = gl::normalizedToFloat<5>(gl::getShiftedData<5, 6>(src->RGBA));
- dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 1>(src->RGBA));
- dst->alpha = gl::normalizedToFloat<1>(gl::getShiftedData<1, 0>(src->RGBA));
- }
-
- static void writeColor(R5G5B5A1 *dst, const gl::ColorF *src)
- {
- dst->RGBA = gl::shiftData<5, 11>(gl::floatToNormalized<5, unsigned short>(src->red)) |
- gl::shiftData<5, 6>(gl::floatToNormalized<5, unsigned short>(src->green)) |
- gl::shiftData<5, 1>(gl::floatToNormalized<5, unsigned short>(src->blue)) |
- gl::shiftData<1, 0>(gl::floatToNormalized<1, unsigned short>(src->alpha));
- }
-
- static void average(R5G5B5A1 *dst, const R5G5B5A1 *src1, const R5G5B5A1 *src2)
- {
- dst->RGBA = gl::shiftData<5, 11>(gl::average(gl::getShiftedData<5, 11>(src1->RGBA), gl::getShiftedData<5, 11>(src2->RGBA))) |
- gl::shiftData<5, 6>(gl::average(gl::getShiftedData<5, 6>(src1->RGBA), gl::getShiftedData<5, 6>(src2->RGBA))) |
- gl::shiftData<5, 1>(gl::average(gl::getShiftedData<5, 1>(src1->RGBA), gl::getShiftedData<5, 1>(src2->RGBA))) |
- gl::shiftData<1, 0>(gl::average(gl::getShiftedData<1, 0>(src1->RGBA), gl::getShiftedData<1, 0>(src2->RGBA)));
- }
-};
-
-struct R4G4B4A4
-{
- // OpenGL ES 2.0.25 spec Section 3.6.2: "Components are packed with the first component in the most significant
- // bits of the bitfield, and successive component occupying progressively less significant locations"
- unsigned short RGBA;
-
- static void readColor(gl::ColorF *dst, const R4G4B4A4 *src)
- {
- dst->red = gl::normalizedToFloat<4>(gl::getShiftedData<4, 12>(src->RGBA));
- dst->green = gl::normalizedToFloat<4>(gl::getShiftedData<4, 8>(src->RGBA));
- dst->blue = gl::normalizedToFloat<4>(gl::getShiftedData<4, 4>(src->RGBA));
- dst->alpha = gl::normalizedToFloat<4>(gl::getShiftedData<4, 0>(src->RGBA));
- }
-
- static void writeColor(R4G4B4A4 *dst, const gl::ColorF *src)
- {
- dst->RGBA = gl::shiftData<4, 12>(gl::floatToNormalized<4, unsigned short>(src->red)) |
- gl::shiftData<4, 8>(gl::floatToNormalized<4, unsigned short>(src->green)) |
- gl::shiftData<4, 4>(gl::floatToNormalized<4, unsigned short>(src->blue)) |
- gl::shiftData<4, 0>(gl::floatToNormalized<4, unsigned short>(src->alpha));
- }
-
- static void average(R4G4B4A4 *dst, const R4G4B4A4 *src1, const R4G4B4A4 *src2)
- {
- dst->RGBA = gl::shiftData<4, 12>(gl::average(gl::getShiftedData<4, 12>(src1->RGBA), gl::getShiftedData<4, 12>(src2->RGBA))) |
- gl::shiftData<4, 8>(gl::average(gl::getShiftedData<4, 8>(src1->RGBA), gl::getShiftedData<4, 8>(src2->RGBA))) |
- gl::shiftData<4, 4>(gl::average(gl::getShiftedData<4, 4>(src1->RGBA), gl::getShiftedData<4, 4>(src2->RGBA))) |
- gl::shiftData<4, 0>(gl::average(gl::getShiftedData<4, 0>(src1->RGBA), gl::getShiftedData<4, 0>(src2->RGBA)));
- }
-};
-
-struct A4R4G4B4
-{
- unsigned short ARGB;
-
- static void readColor(gl::ColorF *dst, const A4R4G4B4 *src)
- {
- dst->alpha = gl::normalizedToFloat<4>(gl::getShiftedData<4, 12>(src->ARGB));
- dst->red = gl::normalizedToFloat<4>(gl::getShiftedData<4, 8>(src->ARGB));
- dst->green = gl::normalizedToFloat<4>(gl::getShiftedData<4, 4>(src->ARGB));
- dst->blue = gl::normalizedToFloat<4>(gl::getShiftedData<4, 0>(src->ARGB));
- }
-
- static void writeColor(A4R4G4B4 *dst, const gl::ColorF *src)
- {
- dst->ARGB = gl::shiftData<4, 12>(gl::floatToNormalized<4, unsigned short>(src->alpha)) |
- gl::shiftData<4, 8>(gl::floatToNormalized<4, unsigned short>(src->red)) |
- gl::shiftData<4, 4>(gl::floatToNormalized<4, unsigned short>(src->green)) |
- gl::shiftData<4, 0>(gl::floatToNormalized<4, unsigned short>(src->blue));
- }
-
- static void average(A4R4G4B4 *dst, const A4R4G4B4 *src1, const A4R4G4B4 *src2)
- {
- dst->ARGB = gl::shiftData<4, 12>(gl::average(gl::getShiftedData<4, 12>(src1->ARGB), gl::getShiftedData<4, 12>(src2->ARGB))) |
- gl::shiftData<4, 8>(gl::average(gl::getShiftedData<4, 8>(src1->ARGB), gl::getShiftedData<4, 8>(src2->ARGB))) |
- gl::shiftData<4, 4>(gl::average(gl::getShiftedData<4, 4>(src1->ARGB), gl::getShiftedData<4, 4>(src2->ARGB))) |
- gl::shiftData<4, 0>(gl::average(gl::getShiftedData<4, 0>(src1->ARGB), gl::getShiftedData<4, 0>(src2->ARGB)));
- }
-};
-
-struct R16
-{
- unsigned short R;
-
- static void readColor(gl::ColorF *dst, const R16 *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = 0.0f;
- dst->blue = 0.0f;
- dst->alpha = 1.0f;
- }
-
- static void readColor(gl::ColorUI *dst, const R16 *src)
- {
- dst->red = src->R;
- dst->green = 0;
- dst->blue = 0;
- dst->alpha = 1;
- }
-
- static void writeColor(R16 *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<unsigned short>(src->red);
- }
-
- static void writeColor(R16 *dst, const gl::ColorUI *src)
- {
- dst->R = static_cast<unsigned short>(src->red);
- }
-
- static void average(R16 *dst, const R16 *src1, const R16 *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- }
-};
-
-struct R16G16
-{
- unsigned short R;
- unsigned short G;
-
- static void readColor(gl::ColorF *dst, const R16G16 *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = gl::normalizedToFloat(src->G);
- dst->blue = 0.0f;
- dst->alpha = 1.0f;
- }
-
- static void readColor(gl::ColorUI *dst, const R16G16 *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = 0;
- dst->alpha = 1;
- }
-
- static void writeColor(R16G16 *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<unsigned short>(src->red);
- dst->G = gl::floatToNormalized<unsigned short>(src->green);
- }
-
- static void writeColor(R16G16 *dst, const gl::ColorUI *src)
- {
- dst->R = static_cast<unsigned short>(src->red);
- dst->G = static_cast<unsigned short>(src->green);
- }
-
- static void average(R16G16 *dst, const R16G16 *src1, const R16G16 *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- dst->G = gl::average(src1->G, src2->G);
- }
-};
-
-struct R16G16B16
-{
- unsigned short R;
- unsigned short G;
- unsigned short B;
-
- static void readColor(gl::ColorF *dst, const R16G16B16 *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = gl::normalizedToFloat(src->G);
- dst->blue = gl::normalizedToFloat(src->B);
- dst->alpha = 1.0f;
- }
-
- static void readColor(gl::ColorUI *dst, const R16G16B16 *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = src->B;
- dst->alpha = 1;
- }
-
- static void writeColor(R16G16B16 *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<unsigned short>(src->red);
- dst->G = gl::floatToNormalized<unsigned short>(src->green);
- dst->B = gl::floatToNormalized<unsigned short>(src->blue);
- }
-
- static void writeColor(R16G16B16 *dst, const gl::ColorUI *src)
- {
- dst->R = static_cast<unsigned short>(src->red);
- dst->G = static_cast<unsigned short>(src->green);
- dst->B = static_cast<unsigned short>(src->blue);
- }
-
- static void average(R16G16B16 *dst, const R16G16B16 *src1, const R16G16B16 *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- dst->G = gl::average(src1->G, src2->G);
- dst->B = gl::average(src1->B, src2->B);
- }
-};
-
-struct R16G16B16A16
-{
- unsigned short R;
- unsigned short G;
- unsigned short B;
- unsigned short A;
-
- static void readColor(gl::ColorF *dst, const R16G16B16A16 *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = gl::normalizedToFloat(src->G);
- dst->blue = gl::normalizedToFloat(src->B);
- dst->alpha = gl::normalizedToFloat(src->A);
- }
-
- static void readColor(gl::ColorUI *dst, const R16G16B16A16 *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = src->B;
- dst->alpha = src->A;
- }
-
- static void writeColor(R16G16B16A16 *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<unsigned short>(src->red);
- dst->G = gl::floatToNormalized<unsigned short>(src->green);
- dst->B = gl::floatToNormalized<unsigned short>(src->blue);
- dst->A = gl::floatToNormalized<unsigned short>(src->alpha);
- }
-
- static void writeColor(R16G16B16A16 *dst, const gl::ColorUI *src)
- {
- dst->R = static_cast<unsigned short>(src->red);
- dst->G = static_cast<unsigned short>(src->green);
- dst->B = static_cast<unsigned short>(src->blue);
- dst->A = static_cast<unsigned short>(src->alpha);
- }
-
- static void average(R16G16B16A16 *dst, const R16G16B16A16 *src1, const R16G16B16A16 *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- dst->G = gl::average(src1->G, src2->G);
- dst->B = gl::average(src1->B, src2->B);
- dst->A = gl::average(src1->A, src2->A);
- }
-};
-
-struct R32
-{
- unsigned int R;
-
- static void readColor(gl::ColorF *dst, const R32 *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = 0.0f;
- dst->blue = 0.0f;
- dst->alpha = 1.0f;
- }
-
- static void readColor(gl::ColorUI *dst, const R32 *src)
- {
- dst->red = src->R;
- dst->green = 0;
- dst->blue = 0;
- dst->alpha = 1;
- }
-
- static void writeColor(R32 *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<unsigned int>(src->red);
- }
-
- static void writeColor(R32 *dst, const gl::ColorUI *src)
- {
- dst->R = static_cast<unsigned int>(src->red);
- }
-
- static void average(R32 *dst, const R32 *src1, const R32 *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- }
-};
-
-struct R32G32
-{
- unsigned int R;
- unsigned int G;
-
- static void readColor(gl::ColorF *dst, const R32G32 *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = gl::normalizedToFloat(src->G);
- dst->blue = 0.0f;
- dst->alpha = 1.0f;
- }
-
- static void readColor(gl::ColorUI *dst, const R32G32 *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = 0;
- dst->alpha = 1;
- }
-
- static void writeColor(R32G32 *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<unsigned int>(src->red);
- dst->G = gl::floatToNormalized<unsigned int>(src->green);
- }
-
- static void writeColor(R32G32 *dst, const gl::ColorUI *src)
- {
- dst->R = static_cast<unsigned int>(src->red);
- dst->G = static_cast<unsigned int>(src->green);
- }
-
- static void average(R32G32 *dst, const R32G32 *src1, const R32G32 *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- dst->G = gl::average(src1->G, src2->G);
- }
-};
-
-struct R32G32B32
-{
- unsigned int R;
- unsigned int G;
- unsigned int B;
-
- static void readColor(gl::ColorF *dst, const R32G32B32 *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = gl::normalizedToFloat(src->G);
- dst->blue = gl::normalizedToFloat(src->B);
- dst->alpha = 1.0f;
- }
-
- static void readColor(gl::ColorUI *dst, const R32G32B32 *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = src->B;
- dst->alpha = 1;
- }
-
- static void writeColor(R32G32B32 *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<unsigned int>(src->red);
- dst->G = gl::floatToNormalized<unsigned int>(src->green);
- dst->B = gl::floatToNormalized<unsigned int>(src->blue);
- }
-
- static void writeColor(R32G32B32 *dst, const gl::ColorUI *src)
- {
- dst->R = static_cast<unsigned int>(src->red);
- dst->G = static_cast<unsigned int>(src->green);
- dst->B = static_cast<unsigned int>(src->blue);
- }
-
- static void average(R32G32B32 *dst, const R32G32B32 *src1, const R32G32B32 *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- dst->G = gl::average(src1->G, src2->G);
- dst->B = gl::average(src1->B, src2->B);
- }
-};
-
-struct R32G32B32A32
-{
- unsigned int R;
- unsigned int G;
- unsigned int B;
- unsigned int A;
-
- static void readColor(gl::ColorF *dst, const R32G32B32A32 *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = gl::normalizedToFloat(src->G);
- dst->blue = gl::normalizedToFloat(src->B);
- dst->alpha = gl::normalizedToFloat(src->A);
- }
-
- static void readColor(gl::ColorUI *dst, const R32G32B32A32 *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = src->B;
- dst->alpha = src->A;
- }
-
- static void writeColor(R32G32B32A32 *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<unsigned int>(src->red);
- dst->G = gl::floatToNormalized<unsigned int>(src->green);
- dst->B = gl::floatToNormalized<unsigned int>(src->blue);
- dst->A = gl::floatToNormalized<unsigned int>(src->alpha);
- }
-
- static void writeColor(R32G32B32A32 *dst, const gl::ColorUI *src)
- {
- dst->R = static_cast<unsigned int>(src->red);
- dst->G = static_cast<unsigned int>(src->green);
- dst->B = static_cast<unsigned int>(src->blue);
- dst->A = static_cast<unsigned int>(src->alpha);
- }
-
- static void average(R32G32B32A32 *dst, const R32G32B32A32 *src1, const R32G32B32A32 *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- dst->G = gl::average(src1->G, src2->G);
- dst->B = gl::average(src1->B, src2->B);
- dst->A = gl::average(src1->A, src2->A);
- }
-};
-
-struct R8S
-{
- char R;
-
- static void readColor(gl::ColorF *dst, const R8S *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = 0.0f;
- dst->blue = 0.0f;
- dst->alpha = 1.0f;
- }
-
- static void readColor(gl::ColorI *dst, const R8S *src)
- {
- dst->red = src->R;
- dst->green = 0;
- dst->blue = 0;
- dst->alpha = 1;
- }
-
- static void writeColor(R8S *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<char>(src->red);
- }
-
- static void writeColor(R8S *dst, const gl::ColorI *src)
- {
- dst->R = static_cast<char>(src->red);
- }
-
- static void average(R8S *dst, const R8S *src1, const R8S *src2)
- {
- dst->R = static_cast<char>(gl::average(src1->R, src2->R));
- }
-};
-
-struct R8G8S
-{
- char R;
- char G;
-
- static void readColor(gl::ColorF *dst, const R8G8S *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = gl::normalizedToFloat(src->G);
- dst->blue = 0.0f;
- dst->alpha = 1.0f;
- }
-
- static void readColor(gl::ColorI *dst, const R8G8S *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = 0;
- dst->alpha = 1;
- }
-
- static void writeColor(R8G8S *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<char>(src->red);
- dst->G = gl::floatToNormalized<char>(src->green);
- }
-
- static void writeColor(R8G8S *dst, const gl::ColorI *src)
- {
- dst->R = static_cast<char>(src->red);
- dst->G = static_cast<char>(src->green);
- }
-
- static void average(R8G8S *dst, const R8G8S *src1, const R8G8S *src2)
- {
- dst->R = static_cast<char>(gl::average(src1->R, src2->R));
- dst->G = static_cast<char>(gl::average(src1->G, src2->G));
- }
-};
-
-struct R8G8B8S
-{
- char R;
- char G;
- char B;
-
- static void readColor(gl::ColorF *dst, const R8G8B8S *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = gl::normalizedToFloat(src->G);
- dst->blue = gl::normalizedToFloat(src->B);
- dst->alpha = 1.0f;
- }
-
- static void readColor(gl::ColorI *dst, const R8G8B8S *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = src->B;
- dst->alpha = 1;
- }
-
- static void writeColor(R8G8B8S *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<char>(src->red);
- dst->G = gl::floatToNormalized<char>(src->green);
- dst->B = gl::floatToNormalized<char>(src->blue);
- }
-
- static void writeColor(R8G8B8S *dst, const gl::ColorI *src)
- {
- dst->R = static_cast<char>(src->red);
- dst->G = static_cast<char>(src->green);
- dst->B = static_cast<char>(src->blue);
- }
-
- static void average(R8G8B8S *dst, const R8G8B8S *src1, const R8G8B8S *src2)
- {
- dst->R = static_cast<char>(gl::average(src1->R, src2->R));
- dst->G = static_cast<char>(gl::average(src1->G, src2->G));
- dst->B = static_cast<char>(gl::average(src1->B, src2->B));
- }
-};
-
-struct R8G8B8A8S
-{
- char R;
- char G;
- char B;
- char A;
-
- static void readColor(gl::ColorF *dst, const R8G8B8A8S *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = gl::normalizedToFloat(src->G);
- dst->blue = gl::normalizedToFloat(src->B);
- dst->alpha = gl::normalizedToFloat(src->A);
- }
-
- static void readColor(gl::ColorI *dst, const R8G8B8A8S *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = src->B;
- dst->alpha = src->A;
- }
-
- static void writeColor(R8G8B8A8S *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<char>(src->red);
- dst->G = gl::floatToNormalized<char>(src->green);
- dst->B = gl::floatToNormalized<char>(src->blue);
- dst->A = gl::floatToNormalized<char>(src->alpha);
- }
-
- static void writeColor(R8G8B8A8S *dst, const gl::ColorI *src)
- {
- dst->R = static_cast<char>(src->red);
- dst->G = static_cast<char>(src->green);
- dst->B = static_cast<char>(src->blue);
- dst->A = static_cast<char>(src->alpha);
- }
-
- static void average(R8G8B8A8S *dst, const R8G8B8A8S *src1, const R8G8B8A8S *src2)
- {
- dst->R = static_cast<char>(gl::average(src1->R, src2->R));
- dst->G = static_cast<char>(gl::average(src1->G, src2->G));
- dst->B = static_cast<char>(gl::average(src1->B, src2->B));
- dst->A = static_cast<char>(gl::average(src1->A, src2->A));
- }
-};
-
-struct R16S
-{
- short R;
-
- static void readColor(gl::ColorF *dst, const R16S *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = 0.0f;
- dst->blue = 0.0f;
- dst->alpha = 1.0f;
- }
-
- static void readColor(gl::ColorI *dst, const R16S *src)
- {
- dst->red = src->R;
- dst->green = 0;
- dst->blue = 0;
- dst->alpha = 1;
- }
-
- static void writeColor(R16S *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<short>(src->red);
- }
-
- static void writeColor(R16S *dst, const gl::ColorI *src)
- {
- dst->R = static_cast<short>(src->red);
- }
-
- static void average(R16S *dst, const R16S *src1, const R16S *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- }
-};
-
-struct R16G16S
-{
- short R;
- short G;
-
- static void readColor(gl::ColorF *dst, const R16G16S *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = gl::normalizedToFloat(src->G);
- dst->blue = 0.0f;
- dst->alpha = 1.0f;
- }
-
- static void readColor(gl::ColorI *dst, const R16G16S *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = 0;
- dst->alpha = 1;
- }
-
- static void writeColor(R16G16S *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<short>(src->red);
- dst->G = gl::floatToNormalized<short>(src->green);
- }
-
- static void writeColor(R16G16S *dst, const gl::ColorI *src)
- {
- dst->R = static_cast<short>(src->red);
- dst->G = static_cast<short>(src->green);
- }
-
- static void average(R16G16S *dst, const R16G16S *src1, const R16G16S *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- dst->G = gl::average(src1->G, src2->G);
- }
-};
-
-struct R16G16B16S
-{
- short R;
- short G;
- short B;
-
- static void readColor(gl::ColorF *dst, const R16G16B16S *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = gl::normalizedToFloat(src->G);
- dst->blue = gl::normalizedToFloat(src->B);
- dst->alpha = 1.0f;
- }
-
- static void readColor(gl::ColorI *dst, const R16G16B16S *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = src->B;
- dst->alpha = 1;
- }
-
- static void writeColor(R16G16B16S *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<short>(src->red);
- dst->G = gl::floatToNormalized<short>(src->green);
- dst->B = gl::floatToNormalized<short>(src->blue);
- }
-
- static void writeColor(R16G16B16S *dst, const gl::ColorI *src)
- {
- dst->R = static_cast<short>(src->red);
- dst->G = static_cast<short>(src->green);
- dst->B = static_cast<short>(src->blue);
- }
-
- static void average(R16G16B16S *dst, const R16G16B16S *src1, const R16G16B16S *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- dst->G = gl::average(src1->G, src2->G);
- dst->B = gl::average(src1->B, src2->B);
- }
-};
-
-struct R16G16B16A16S
-{
- short R;
- short G;
- short B;
- short A;
-
- static void readColor(gl::ColorF *dst, const R16G16B16A16S *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = gl::normalizedToFloat(src->G);
- dst->blue = gl::normalizedToFloat(src->B);
- dst->alpha = gl::normalizedToFloat(src->A);
- }
-
- static void readColor(gl::ColorI *dst, const R16G16B16A16S *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = src->B;
- dst->alpha = src->A;
- }
-
- static void writeColor(R16G16B16A16S *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<short>(src->red);
- dst->G = gl::floatToNormalized<short>(src->green);
- dst->B = gl::floatToNormalized<short>(src->blue);
- dst->A = gl::floatToNormalized<short>(src->alpha);
- }
-
- static void writeColor(R16G16B16A16S *dst, const gl::ColorI *src)
- {
- dst->R = static_cast<short>(src->red);
- dst->G = static_cast<short>(src->green);
- dst->B = static_cast<short>(src->blue);
- dst->A = static_cast<short>(src->alpha);
- }
-
- static void average(R16G16B16A16S *dst, const R16G16B16A16S *src1, const R16G16B16A16S *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- dst->G = gl::average(src1->G, src2->G);
- dst->B = gl::average(src1->B, src2->B);
- dst->A = gl::average(src1->A, src2->A);
- }
-};
-
-struct R32S
-{
- int R;
-
- static void readColor(gl::ColorF *dst, const R32S *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = 0.0f;
- dst->blue = 0.0f;
- dst->alpha = 1.0f;
- }
-
- static void readColor(gl::ColorI *dst, const R32S *src)
- {
- dst->red = src->R;
- dst->green = 0;
- dst->blue = 0;
- dst->alpha = 1;
- }
-
- static void writeColor(R32S *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<int>(src->red);
- }
-
- static void writeColor(R32S *dst, const gl::ColorI *src)
- {
- dst->R = static_cast<int>(src->red);
- }
-
- static void average(R32S *dst, const R32S *src1, const R32S *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- }
-};
-
-struct R32G32S
-{
- int R;
- int G;
-
- static void readColor(gl::ColorF *dst, const R32G32S *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = gl::normalizedToFloat(src->G);
- dst->blue = 0.0f;
- dst->alpha = 1.0f;
- }
-
- static void readColor(gl::ColorI *dst, const R32G32S *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = 0;
- dst->alpha = 1;
- }
-
- static void writeColor(R32G32S *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<int>(src->red);
- dst->G = gl::floatToNormalized<int>(src->green);
- }
-
- static void writeColor(R32G32S *dst, const gl::ColorI *src)
- {
- dst->R = static_cast<int>(src->red);
- dst->G = static_cast<int>(src->green);
- }
-
- static void average(R32G32S *dst, const R32G32S *src1, const R32G32S *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- dst->G = gl::average(src1->G, src2->G);
- }
-};
-
-struct R32G32B32S
-{
- int R;
- int G;
- int B;
-
- static void readColor(gl::ColorF *dst, const R32G32B32S *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = gl::normalizedToFloat(src->G);
- dst->blue = gl::normalizedToFloat(src->B);
- dst->alpha = 1.0f;
- }
-
- static void readColor(gl::ColorI *dst, const R32G32B32S *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = src->B;
- dst->alpha = 1;
- }
-
- static void writeColor(R32G32B32S *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<int>(src->red);
- dst->G = gl::floatToNormalized<int>(src->green);
- dst->B = gl::floatToNormalized<int>(src->blue);
- }
-
- static void writeColor(R32G32B32S *dst, const gl::ColorI *src)
- {
- dst->R = static_cast<int>(src->red);
- dst->G = static_cast<int>(src->green);
- dst->B = static_cast<int>(src->blue);
- }
-
- static void average(R32G32B32S *dst, const R32G32B32S *src1, const R32G32B32S *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- dst->G = gl::average(src1->G, src2->G);
- dst->B = gl::average(src1->B, src2->B);
- }
-};
-
-struct R32G32B32A32S
-{
- int R;
- int G;
- int B;
- int A;
-
- static void readColor(gl::ColorF *dst, const R32G32B32A32S *src)
- {
- dst->red = gl::normalizedToFloat(src->R);
- dst->green = gl::normalizedToFloat(src->G);
- dst->blue = gl::normalizedToFloat(src->B);
- dst->alpha = gl::normalizedToFloat(src->A);
- }
-
- static void readColor(gl::ColorI *dst, const R32G32B32A32S *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = src->B;
- dst->alpha = src->A;
- }
-
- static void writeColor(R32G32B32A32S *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<int>(src->red);
- dst->G = gl::floatToNormalized<int>(src->green);
- dst->B = gl::floatToNormalized<int>(src->blue);
- dst->A = gl::floatToNormalized<int>(src->alpha);
- }
-
- static void writeColor(R32G32B32A32S *dst, const gl::ColorI *src)
- {
- dst->R = static_cast<int>(src->red);
- dst->G = static_cast<int>(src->green);
- dst->B = static_cast<int>(src->blue);
- dst->A = static_cast<int>(src->alpha);
- }
-
- static void average(R32G32B32A32S *dst, const R32G32B32A32S *src1, const R32G32B32A32S *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- dst->G = gl::average(src1->G, src2->G);
- dst->B = gl::average(src1->B, src2->B);
- dst->A = gl::average(src1->A, src2->A);
- }
-};
-
-struct A16B16G16R16F
-{
- unsigned short A;
- unsigned short R;
- unsigned short G;
- unsigned short B;
-
- static void readColor(gl::ColorF *dst, const A16B16G16R16F *src)
- {
- dst->red = gl::float16ToFloat32(src->R);
- dst->green = gl::float16ToFloat32(src->G);
- dst->blue = gl::float16ToFloat32(src->B);
- dst->alpha = gl::float16ToFloat32(src->A);
- }
-
- static void writeColor(A16B16G16R16F *dst, const gl::ColorF *src)
- {
- dst->R = gl::float32ToFloat16(src->red);
- dst->G = gl::float32ToFloat16(src->green);
- dst->B = gl::float32ToFloat16(src->blue);
- dst->A = gl::float32ToFloat16(src->alpha);
- }
-
- static void average(A16B16G16R16F *dst, const A16B16G16R16F *src1, const A16B16G16R16F *src2)
- {
- dst->R = gl::averageHalfFloat(src1->R, src2->R);
- dst->G = gl::averageHalfFloat(src1->G, src2->G);
- dst->B = gl::averageHalfFloat(src1->B, src2->B);
- dst->A = gl::averageHalfFloat(src1->A, src2->A);
- }
-};
-
-struct R16G16B16A16F
-{
- unsigned short R;
- unsigned short G;
- unsigned short B;
- unsigned short A;
-
- static void readColor(gl::ColorF *dst, const R16G16B16A16F *src)
- {
- dst->red = gl::float16ToFloat32(src->R);
- dst->green = gl::float16ToFloat32(src->G);
- dst->blue = gl::float16ToFloat32(src->B);
- dst->alpha = gl::float16ToFloat32(src->A);
- }
-
- static void writeColor(R16G16B16A16F *dst, const gl::ColorF *src)
- {
- dst->R = gl::float32ToFloat16(src->red);
- dst->G = gl::float32ToFloat16(src->green);
- dst->B = gl::float32ToFloat16(src->blue);
- dst->A = gl::float32ToFloat16(src->alpha);
- }
-
- static void average(R16G16B16A16F *dst, const R16G16B16A16F *src1, const R16G16B16A16F *src2)
- {
- dst->R = gl::averageHalfFloat(src1->R, src2->R);
- dst->G = gl::averageHalfFloat(src1->G, src2->G);
- dst->B = gl::averageHalfFloat(src1->B, src2->B);
- dst->A = gl::averageHalfFloat(src1->A, src2->A);
- }
-};
-
-struct R16F
-{
- unsigned short R;
-
- static void readColor(gl::ColorF *dst, const R16F *src)
- {
- dst->red = gl::float16ToFloat32(src->R);
- dst->green = 0.0f;
- dst->blue = 0.0f;
- dst->alpha = 1.0f;
- }
-
- static void writeColor(R16F *dst, const gl::ColorF *src)
- {
- dst->R = gl::float32ToFloat16(src->red);
- }
-
- static void average(R16F *dst, const R16F *src1, const R16F *src2)
- {
- dst->R = gl::averageHalfFloat(src1->R, src2->R);
- }
-};
-
-struct A16F
-{
- unsigned short A;
-
- static void readColor(gl::ColorF *dst, const A16F *src)
- {
- dst->red = 0.0f;
- dst->green = 0.0f;
- dst->blue = 0.0f;
- dst->alpha = gl::float16ToFloat32(src->A);
- }
-
- static void writeColor(A16F *dst, const gl::ColorF *src)
- {
- dst->A = gl::float32ToFloat16(src->alpha);
- }
-
- static void average(A16F *dst, const A16F *src1, const A16F *src2)
- {
- dst->A = gl::averageHalfFloat(src1->A, src2->A);
- }
-};
-
-struct L16F
-{
- unsigned short L;
-
- static void readColor(gl::ColorF *dst, const L16F *src)
- {
- float lum = gl::float16ToFloat32(src->L);
- dst->red = lum;
- dst->green = lum;
- dst->blue = lum;
- dst->alpha = 1.0f;
- }
-
- static void writeColor(L16F *dst, const gl::ColorF *src)
- {
- dst->L = gl::float32ToFloat16((src->red + src->green + src->blue) / 3.0f);
- }
-
- static void average(L16F *dst, const L16F *src1, const L16F *src2)
- {
- dst->L = gl::averageHalfFloat(src1->L, src2->L);
- }
-};
-
-struct L16A16F
-{
- unsigned short L;
- unsigned short A;
-
- static void readColor(gl::ColorF *dst, const L16A16F *src)
- {
- float lum = gl::float16ToFloat32(src->L);
- dst->red = lum;
- dst->green = lum;
- dst->blue = lum;
- dst->alpha = gl::float16ToFloat32(src->A);
- }
-
- static void writeColor(L16A16F *dst, const gl::ColorF *src)
- {
- dst->L = gl::float32ToFloat16((src->red + src->green + src->blue) / 3.0f);
- dst->A = gl::float32ToFloat16(src->alpha);
- }
-
- static void average(L16A16F *dst, const L16A16F *src1, const L16A16F *src2)
- {
- dst->L = gl::averageHalfFloat(src1->L, src2->L);
- dst->A = gl::averageHalfFloat(src1->A, src2->A);
- }
-};
-
-struct R16G16F
-{
- unsigned short R;
- unsigned short G;
-
- static void readColor(gl::ColorF *dst, const R16G16F *src)
- {
- dst->red = gl::float16ToFloat32(src->R);
- dst->green = gl::float16ToFloat32(src->G);
- dst->blue = 0.0f;
- dst->alpha = 1.0f;
- }
-
- static void writeColor(R16G16F *dst, const gl::ColorF *src)
- {
- dst->R = gl::float32ToFloat16(src->red);
- dst->G = gl::float32ToFloat16(src->green);
- }
-
- static void average(R16G16F *dst, const R16G16F *src1, const R16G16F *src2)
- {
- dst->R = gl::averageHalfFloat(src1->R, src2->R);
- dst->G = gl::averageHalfFloat(src1->G, src2->G);
- }
-};
-
-struct R16G16B16F
-{
- unsigned short R;
- unsigned short G;
- unsigned short B;
-
- static void readColor(gl::ColorF *dst, const R16G16B16F *src)
- {
- dst->red = gl::float16ToFloat32(src->R);
- dst->green = gl::float16ToFloat32(src->G);
- dst->blue = gl::float16ToFloat32(src->B);
- dst->alpha = 1.0f;
- }
-
- static void writeColor(R16G16B16F *dst, const gl::ColorF *src)
- {
- dst->R = gl::float32ToFloat16(src->red);
- dst->G = gl::float32ToFloat16(src->green);
- dst->B = gl::float32ToFloat16(src->blue);
- }
-
- static void average(R16G16B16F *dst, const R16G16B16F *src1, const R16G16B16F *src2)
- {
- dst->R = gl::averageHalfFloat(src1->R, src2->R);
- dst->G = gl::averageHalfFloat(src1->G, src2->G);
- dst->B = gl::averageHalfFloat(src1->B, src2->B);
- }
-};
-
-struct A32B32G32R32F
-{
- float A;
- float R;
- float G;
- float B;
-
- static void readColor(gl::ColorF *dst, const A32B32G32R32F *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = src->B;
- dst->alpha = src->A;
- }
-
- static void writeColor(A32B32G32R32F *dst, const gl::ColorF *src)
- {
- dst->R = src->red;
- dst->G = src->green;
- dst->B = src->blue;
- dst->A = src->alpha;
- }
-
- static void average(A32B32G32R32F *dst, const A32B32G32R32F *src1, const A32B32G32R32F *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- dst->G = gl::average(src1->G, src2->G);
- dst->B = gl::average(src1->B, src2->B);
- dst->A = gl::average(src1->A, src2->A);
- }
-};
-
-struct R32G32B32A32F
-{
- float R;
- float G;
- float B;
- float A;
-
- static void readColor(gl::ColorF *dst, const R32G32B32A32F *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = src->B;
- dst->alpha = src->A;
- }
-
- static void writeColor(R32G32B32A32F *dst, const gl::ColorF *src)
- {
- dst->R = src->red;
- dst->G = src->green;
- dst->B = src->blue;
- dst->A = src->alpha;
- }
-
- static void average(R32G32B32A32F *dst, const R32G32B32A32F *src1, const R32G32B32A32F *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- dst->G = gl::average(src1->G, src2->G);
- dst->B = gl::average(src1->B, src2->B);
- dst->A = gl::average(src1->A, src2->A);
- }
-};
-
-struct R32F
-{
- float R;
-
- static void readColor(gl::ColorF *dst, const R32F *src)
- {
- dst->red = src->R;
- dst->green = 0.0f;
- dst->blue = 0.0f;
- dst->alpha = 1.0f;
- }
-
- static void writeColor(R32F *dst, const gl::ColorF *src)
- {
- dst->R = src->red;
- }
-
- static void average(R32F *dst, const R32F *src1, const R32F *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- }
-};
-
-struct A32F
-{
- float A;
-
- static void readColor(gl::ColorF *dst, const A32F *src)
- {
- dst->red = 0.0f;
- dst->green = 0.0f;
- dst->blue = 0.0f;
- dst->alpha = src->A;
- }
-
- static void writeColor(A32F *dst, const gl::ColorF *src)
- {
- dst->A = src->alpha;
- }
-
- static void average(A32F *dst, const A32F *src1, const A32F *src2)
- {
- dst->A = gl::average(src1->A, src2->A);
- }
-};
-
-struct L32F
-{
- float L;
-
- static void readColor(gl::ColorF *dst, const L32F *src)
- {
- dst->red = src->L;
- dst->green = src->L;
- dst->blue = src->L;
- dst->alpha = 1.0f;
- }
-
- static void writeColor(L32F *dst, const gl::ColorF *src)
- {
- dst->L = (src->red + src->green + src->blue) / 3.0f;
- }
-
- static void average(L32F *dst, const L32F *src1, const L32F *src2)
- {
- dst->L = gl::average(src1->L, src2->L);
- }
-};
-
-struct L32A32F
-{
- float L;
- float A;
-
- static void readColor(gl::ColorF *dst, const L32A32F *src)
- {
- dst->red = src->L;
- dst->green = src->L;
- dst->blue = src->L;
- dst->alpha = src->A;
- }
-
- static void writeColor(L32A32F *dst, const gl::ColorF *src)
- {
- dst->L = (src->red + src->green + src->blue) / 3.0f;
- dst->A = src->alpha;
- }
-
- static void average(L32A32F *dst, const L32A32F *src1, const L32A32F *src2)
- {
- dst->L = gl::average(src1->L, src2->L);
- dst->A = gl::average(src1->A, src2->A);
- }
-};
-
-struct R32G32F
-{
- float R;
- float G;
-
- static void readColor(gl::ColorF *dst, const R32G32F *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = 0.0f;
- dst->alpha = 1.0f;
- }
-
- static void writeColor(R32G32F *dst, const gl::ColorF *src)
- {
- dst->R = src->red;
- dst->G = src->green;
- }
-
- static void average(R32G32F *dst, const R32G32F *src1, const R32G32F *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- dst->G = gl::average(src1->G, src2->G);
- }
-};
-
-struct R32G32B32F
-{
- float R;
- float G;
- float B;
-
- static void readColor(gl::ColorF *dst, const R32G32B32F *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = src->B;
- dst->alpha = 1.0f;
- }
-
- static void writeColor(R32G32B32F *dst, const gl::ColorF *src)
- {
- dst->R = src->red;
- dst->G = src->green;
- dst->B = src->blue;
- }
-
- static void average(R32G32B32F *dst, const R32G32B32F *src1, const R32G32B32F *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- dst->G = gl::average(src1->G, src2->G);
- dst->B = gl::average(src1->B, src2->B);
- }
-};
-
-struct R10G10B10A2
-{
- unsigned int R : 10;
- unsigned int G : 10;
- unsigned int B : 10;
- unsigned int A : 2;
-
- static void readColor(gl::ColorF *dst, const R10G10B10A2 *src)
- {
- dst->red = gl::normalizedToFloat<10>(src->R);
- dst->green = gl::normalizedToFloat<10>(src->G);
- dst->blue = gl::normalizedToFloat<10>(src->B);
- dst->alpha = gl::normalizedToFloat< 2>(src->A);
- }
-
- static void readColor(gl::ColorUI *dst, const R10G10B10A2 *src)
- {
- dst->red = src->R;
- dst->green = src->G;
- dst->blue = src->B;
- dst->alpha = src->A;
- }
-
- static void writeColor(R10G10B10A2 *dst, const gl::ColorF *src)
- {
- dst->R = gl::floatToNormalized<10, unsigned int>(src->red);
- dst->G = gl::floatToNormalized<10, unsigned int>(src->green);
- dst->B = gl::floatToNormalized<10, unsigned int>(src->blue);
- dst->A = gl::floatToNormalized< 2, unsigned int>(src->alpha);
- }
-
- static void writeColor(R10G10B10A2 *dst, const gl::ColorUI *src)
- {
- dst->R = static_cast<unsigned int>(src->red);
- dst->G = static_cast<unsigned int>(src->green);
- dst->B = static_cast<unsigned int>(src->blue);
- dst->A = static_cast<unsigned int>(src->alpha);
- }
-
- static void average(R10G10B10A2 *dst, const R10G10B10A2 *src1, const R10G10B10A2 *src2)
- {
- dst->R = gl::average(src1->R, src2->R);
- dst->G = gl::average(src1->G, src2->G);
- dst->B = gl::average(src1->B, src2->B);
- dst->A = gl::average(src1->A, src2->A);
- }
-};
-
-struct R9G9B9E5
-{
- unsigned int R : 9;
- unsigned int G : 9;
- unsigned int B : 9;
- unsigned int E : 5;
-
- static void readColor(gl::ColorF *dst, const R9G9B9E5 *src)
- {
- gl::convert999E5toRGBFloats(gl::bitCast<unsigned int>(*src), &dst->red, &dst->green, &dst->blue);
- dst->alpha = 1.0f;
- }
-
- static void writeColor(R9G9B9E5 *dst, const gl::ColorF *src)
- {
- *reinterpret_cast<unsigned int*>(dst) = gl::convertRGBFloatsTo999E5(src->red,
- src->green,
- src->blue);
- }
-
- static void average(R9G9B9E5 *dst, const R9G9B9E5 *src1, const R9G9B9E5 *src2)
- {
- float r1, g1, b1;
- gl::convert999E5toRGBFloats(*reinterpret_cast<const unsigned int*>(src1), &r1, &g1, &b1);
-
- float r2, g2, b2;
- gl::convert999E5toRGBFloats(*reinterpret_cast<const unsigned int*>(src2), &r2, &g2, &b2);
-
- *reinterpret_cast<unsigned int*>(dst) = gl::convertRGBFloatsTo999E5(gl::average(r1, r2),
- gl::average(g1, g2),
- gl::average(b1, b2));
- }
-};
-
-struct R11G11B10F
-{
- unsigned int R : 11;
- unsigned int G : 11;
- unsigned int B : 10;
-
- static void readColor(gl::ColorF *dst, const R11G11B10F *src)
- {
- dst->red = gl::float11ToFloat32(src->R);
- dst->green = gl::float11ToFloat32(src->G);
- dst->blue = gl::float10ToFloat32(src->B);
- dst->alpha = 1.0f;
- }
-
- static void writeColor(R11G11B10F *dst, const gl::ColorF *src)
- {
- dst->R = gl::float32ToFloat11(src->red);
- dst->G = gl::float32ToFloat11(src->green);
- dst->B = gl::float32ToFloat10(src->blue);
- }
-
- static void average(R11G11B10F *dst, const R11G11B10F *src1, const R11G11B10F *src2)
- {
- dst->R = gl::averageFloat11(src1->R, src2->R);
- dst->G = gl::averageFloat11(src1->G, src2->G);
- dst->B = gl::averageFloat10(src1->B, src2->B);
- }
-};
-
-}
-
-#endif // LIBANGLE_RENDERER_D3D_IMAGEFORMATS_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.cpp
deleted file mode 100644
index b9b9e5e4ab..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.cpp
+++ /dev/null
@@ -1,697 +0,0 @@
-//
-// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// loadimage.cpp: Defines image loading functions.
-
-#include "libANGLE/renderer/d3d/loadimage.h"
-
-namespace rx
-{
-
-void LoadA8ToRGBA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- dest[x] = static_cast<uint32_t>(source[x]) << 24;
- }
- }
- }
-}
-
-void LoadA8ToBGRA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- // Same as loading to RGBA
- LoadA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch);
-}
-
-void LoadA32FToRGBA32F(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
- float *dest = OffsetDataPointer<float>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- dest[4 * x + 0] = 0.0f;
- dest[4 * x + 1] = 0.0f;
- dest[4 * x + 2] = 0.0f;
- dest[4 * x + 3] = source[x];
- }
- }
- }
-}
-
-void LoadA16FToRGBA16F(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- dest[4 * x + 0] = 0;
- dest[4 * x + 1] = 0;
- dest[4 * x + 2] = 0;
- dest[4 * x + 3] = source[x];
- }
- }
- }
-}
-
-void LoadL8ToRGBA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- uint8_t sourceVal = source[x];
- dest[4 * x + 0] = sourceVal;
- dest[4 * x + 1] = sourceVal;
- dest[4 * x + 2] = sourceVal;
- dest[4 * x + 3] = 0xFF;
- }
- }
- }
-}
-
-void LoadL8ToBGRA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- // Same as loading to RGBA
- LoadL8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch);
-}
-
-void LoadL32FToRGBA32F(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
- float *dest = OffsetDataPointer<float>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- dest[4 * x + 0] = source[x];
- dest[4 * x + 1] = source[x];
- dest[4 * x + 2] = source[x];
- dest[4 * x + 3] = 1.0f;
- }
- }
- }
-}
-
-void LoadL16FToRGBA16F(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- dest[4 * x + 0] = source[x];
- dest[4 * x + 1] = source[x];
- dest[4 * x + 2] = source[x];
- dest[4 * x + 3] = gl::Float16One;
- }
- }
- }
-}
-
-void LoadLA8ToRGBA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- dest[4 * x + 0] = source[2 * x + 0];
- dest[4 * x + 1] = source[2 * x + 0];
- dest[4 * x + 2] = source[2 * x + 0];
- dest[4 * x + 3] = source[2 * x + 1];
- }
- }
- }
-}
-
-void LoadLA8ToBGRA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- // Same as loading to RGBA
- LoadLA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch);
-}
-
-void LoadLA32FToRGBA32F(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
- float *dest = OffsetDataPointer<float>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- dest[4 * x + 0] = source[2 * x + 0];
- dest[4 * x + 1] = source[2 * x + 0];
- dest[4 * x + 2] = source[2 * x + 0];
- dest[4 * x + 3] = source[2 * x + 1];
- }
- }
- }
-}
-
-void LoadLA16FToRGBA16F(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- dest[4 * x + 0] = source[2 * x + 0];
- dest[4 * x + 1] = source[2 * x + 0];
- dest[4 * x + 2] = source[2 * x + 0];
- dest[4 * x + 3] = source[2 * x + 1];
- }
- }
- }
-}
-
-void LoadRGB8ToBGRX8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- dest[4 * x + 0] = source[x * 3 + 2];
- dest[4 * x + 1] = source[x * 3 + 1];
- dest[4 * x + 2] = source[x * 3 + 0];
- dest[4 * x + 3] = 0xFF;
- }
- }
- }
-}
-
-void LoadRG8ToBGRX8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- dest[4 * x + 0] = 0x00;
- dest[4 * x + 1] = source[x * 2 + 1];
- dest[4 * x + 2] = source[x * 2 + 0];
- dest[4 * x + 3] = 0xFF;
- }
- }
- }
-}
-
-void LoadR8ToBGRX8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- dest[4 * x + 0] = 0x00;
- dest[4 * x + 1] = 0x00;
- dest[4 * x + 2] = source[x];
- dest[4 * x + 3] = 0xFF;
- }
- }
- }
-}
-
-void LoadR5G6B5ToBGRA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- uint16_t rgb = source[x];
- dest[4 * x + 0] = static_cast<uint8_t>(((rgb & 0x001F) << 3) | ((rgb & 0x001F) >> 2));
- dest[4 * x + 1] = static_cast<uint8_t>(((rgb & 0x07E0) >> 3) | ((rgb & 0x07E0) >> 9));
- dest[4 * x + 2] = static_cast<uint8_t>(((rgb & 0xF800) >> 8) | ((rgb & 0xF800) >> 13));
- dest[4 * x + 3] = 0xFF;
- }
- }
- }
-}
-
-void LoadR5G6B5ToRGBA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- uint16_t rgb = source[x];
- dest[4 * x + 0] = static_cast<uint8_t>(((rgb & 0xF800) >> 8) | ((rgb & 0xF800) >> 13));
- dest[4 * x + 1] = static_cast<uint8_t>(((rgb & 0x07E0) >> 3) | ((rgb & 0x07E0) >> 9));
- dest[4 * x + 2] = static_cast<uint8_t>(((rgb & 0x001F) << 3) | ((rgb & 0x001F) >> 2));
- dest[4 * x + 3] = 0xFF;
- }
- }
- }
-}
-
-void LoadRGBA8ToBGRA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint32_t *source = OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- uint32_t rgba = source[x];
- dest[x] = (ANGLE_ROTL(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
- }
- }
- }
-}
-
-void LoadRGBA4ToARGB4(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- dest[x] = ANGLE_ROTR16(source[x], 4);
- }
- }
- }
-}
-
-void LoadRGBA4ToBGRA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- uint16_t rgba = source[x];
- dest[4 * x + 0] = static_cast<uint8_t>(((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4));
- dest[4 * x + 1] = static_cast<uint8_t>(((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8));
- dest[4 * x + 2] = static_cast<uint8_t>(((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12));
- dest[4 * x + 3] = static_cast<uint8_t>(((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0));
- }
- }
- }
-}
-
-void LoadRGBA4ToRGBA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- uint16_t rgba = source[x];
- dest[4 * x + 0] = static_cast<uint8_t>(((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12));
- dest[4 * x + 1] = static_cast<uint8_t>(((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8));
- dest[4 * x + 2] = static_cast<uint8_t>(((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4));
- dest[4 * x + 3] = static_cast<uint8_t>(((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0));
- }
- }
- }
-}
-
-void LoadBGRA4ToBGRA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- uint16_t bgra = source[x];
- dest[4 * x + 0] = static_cast<uint8_t>(((bgra & 0xF000) >> 8) | ((bgra & 0xF000) >> 12));
- dest[4 * x + 1] = static_cast<uint8_t>(((bgra & 0x0F00) >> 4) | ((bgra & 0x0F00) >> 8));
- dest[4 * x + 2] = static_cast<uint8_t>(((bgra & 0x00F0) << 0) | ((bgra & 0x00F0) >> 4));
- dest[4 * x + 3] = static_cast<uint8_t>(((bgra & 0x000F) << 4) | ((bgra & 0x000F) >> 0));
- }
- }
- }
-}
-
-void LoadRGB5A1ToA1RGB5(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- dest[x] = ANGLE_ROTR16(source[x], 1);
- }
- }
- }
-}
-
-void LoadRGB5A1ToBGRA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- uint16_t rgba = source[x];
- dest[4 * x + 0] = static_cast<uint8_t>(((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3));
- dest[4 * x + 1] = static_cast<uint8_t>(((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8));
- dest[4 * x + 2] = static_cast<uint8_t>(((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13));
- dest[4 * x + 3] = static_cast<uint8_t>((rgba & 0x0001) ? 0xFF : 0);
- }
- }
- }
-}
-
-void LoadRGB5A1ToRGBA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- uint16_t rgba = source[x];
- dest[4 * x + 0] = static_cast<uint8_t>(((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13));
- dest[4 * x + 1] = static_cast<uint8_t>(((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8));
- dest[4 * x + 2] = static_cast<uint8_t>(((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3));
- dest[4 * x + 3] = static_cast<uint8_t>((rgba & 0x0001) ? 0xFF : 0);
- }
- }
- }
-}
-
-void LoadBGR5A1ToBGRA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- uint16_t bgra = source[x];
- dest[4 * x + 0] = static_cast<uint8_t>(((bgra & 0xF800) >> 8) | ((bgra & 0xF800) >> 13));
- dest[4 * x + 1] = static_cast<uint8_t>(((bgra & 0x07C0) >> 3) | ((bgra & 0x07C0) >> 8));
- dest[4 * x + 2] = static_cast<uint8_t>(((bgra & 0x003E) << 2) | ((bgra & 0x003E) >> 3));
- dest[4 * x + 3] = static_cast<uint8_t>((bgra & 0x0001) ? 0xFF : 0);
- }
- }
- }
-}
-
-void LoadRGB10A2ToRGBA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint32_t *source = OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- uint32_t rgba = source[x];
- dest[4 * x + 0] = static_cast<uint8_t>((rgba & 0x000003FF) >> 2);
- dest[4 * x + 1] = static_cast<uint8_t>((rgba & 0x000FFC00) >> 12);
- dest[4 * x + 2] = static_cast<uint8_t>((rgba & 0x3FF00000) >> 22);
- dest[4 * x + 3] = static_cast<uint8_t>(((rgba & 0xC0000000) >> 30) * 0x55);
- }
- }
- }
-}
-
-void LoadRGB16FToRGB9E5(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- dest[x] = gl::convertRGBFloatsTo999E5(gl::float16ToFloat32(source[x * 3 + 0]),
- gl::float16ToFloat32(source[x * 3 + 1]),
- gl::float16ToFloat32(source[x * 3 + 2]));
- }
- }
- }
-}
-
-void LoadRGB32FToRGB9E5(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
- uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- dest[x] = gl::convertRGBFloatsTo999E5(source[x * 3 + 0], source[x * 3 + 1], source[x * 3 + 2]);
- }
- }
- }
-}
-
-void LoadRGB16FToRG11B10F(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint16_t *source = OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- dest[x] = (gl::float32ToFloat11(gl::float16ToFloat32(source[x * 3 + 0])) << 0) |
- (gl::float32ToFloat11(gl::float16ToFloat32(source[x * 3 + 1])) << 11) |
- (gl::float32ToFloat10(gl::float16ToFloat32(source[x * 3 + 2])) << 22);
- }
- }
- }
-}
-
-void LoadRGB32FToRG11B10F(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
- uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- dest[x] = (gl::float32ToFloat11(source[x * 3 + 0]) << 0) |
- (gl::float32ToFloat11(source[x * 3 + 1]) << 11) |
- (gl::float32ToFloat10(source[x * 3 + 2]) << 22);
- }
- }
- }
-}
-
-void LoadG8R24ToR24G8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint32_t *source = OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- uint32_t d = source[x] >> 8;
- uint8_t s = source[x] & 0xFF;
- dest[x] = d | (s << 24);
- }
- }
- }
-}
-
-void LoadRGB32FToRGBA16F(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
- uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- dest[x * 4 + 0] = gl::float32ToFloat16(source[x * 3 + 0]);
- dest[x * 4 + 1] = gl::float32ToFloat16(source[x * 3 + 1]);
- dest[x * 4 + 2] = gl::float32ToFloat16(source[x * 3 + 2]);
- dest[x * 4 + 3] = gl::Float16One;
- }
- }
- }
-}
-
-void LoadR32ToR16(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint32_t *source = OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- dest[x] = source[x] >> 16;
- }
- }
- }
-}
-
-void LoadR32ToR24G8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint32_t *source = OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
-
- for (size_t x = 0; x < width; x++)
- {
- dest[x] = source[x] >> 8;
- }
- }
- }
-}
-
-}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.h
deleted file mode 100644
index 6c5118365e..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.h
+++ /dev/null
@@ -1,201 +0,0 @@
-//
-// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// loadimage.h: Defines image loading functions
-
-#ifndef LIBANGLE_RENDERER_D3D_LOADIMAGE_H_
-#define LIBANGLE_RENDERER_D3D_LOADIMAGE_H_
-
-#include "libANGLE/angletypes.h"
-
-#include <stdint.h>
-
-namespace rx
-{
-
-void LoadA8ToRGBA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadA8ToBGRA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadA32FToRGBA32F(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadA16FToRGBA16F(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadL8ToRGBA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadL8ToBGRA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadL32FToRGBA32F(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadL16FToRGBA16F(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadLA8ToRGBA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadLA8ToBGRA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadLA32FToRGBA32F(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadLA16FToRGBA16F(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadRGB8ToBGRX8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadRG8ToBGRX8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadR8ToBGRX8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadR5G6B5ToBGRA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadR5G6B5ToRGBA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadRGBA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadRGBA8ToBGRA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadRGBA4ToARGB4(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadRGBA4ToBGRA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadRGBA4ToRGBA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadBGRA4ToBGRA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadRGB5A1ToA1RGB5(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadRGB5A1ToBGRA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadRGB5A1ToRGBA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadBGR5A1ToBGRA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadRGB10A2ToRGBA8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadRGB16FToRGB9E5(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadRGB32FToRGB9E5(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadRGB16FToRG11B10F(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadRGB32FToRG11B10F(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadG8R24ToR24G8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-template <typename type, size_t componentCount>
-inline void LoadToNative(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-template <typename type, uint32_t fourthComponentBits>
-inline void LoadToNative3To4(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-template <size_t componentCount>
-inline void Load32FTo16F(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadRGB32FToRGBA16F(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-template <size_t blockWidth, size_t blockHeight, size_t blockSize>
-inline void LoadCompressedToNative(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadR32ToR16(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-template <typename type, uint32_t firstBits, uint32_t secondBits, uint32_t thirdBits, uint32_t fourthBits>
-inline void Initialize4ComponentData(size_t width, size_t height, size_t depth,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-void LoadR32ToR24G8(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-template <typename T>
-inline T *OffsetDataPointer(uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch);
-
-template <typename T>
-inline const T *OffsetDataPointer(const uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch);
-
-}
-
-#include "loadimage.inl"
-
-#endif // LIBANGLE_RENDERER_D3D_LOADIMAGE_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.inl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.inl
deleted file mode 100644
index 920e667db1..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.inl
+++ /dev/null
@@ -1,156 +0,0 @@
-//
-// Copyright (c) 2014-2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "common/mathutil.h"
-
-namespace rx
-{
-
-template <typename T>
-inline T *OffsetDataPointer(uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch)
-{
- return reinterpret_cast<T*>(data + (y * rowPitch) + (z * depthPitch));
-}
-
-template <typename T>
-inline const T *OffsetDataPointer(const uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch)
-{
- return reinterpret_cast<const T*>(data + (y * rowPitch) + (z * depthPitch));
-}
-
-template <typename type, size_t componentCount>
-inline void LoadToNative(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- const size_t rowSize = width * sizeof(type) * componentCount;
- const size_t layerSize = rowSize * height;
- const size_t imageSize = layerSize * depth;
-
- if (layerSize == inputDepthPitch && layerSize == outputDepthPitch)
- {
- ASSERT(rowSize == inputRowPitch && rowSize == outputRowPitch);
- memcpy(output, input, imageSize);
- }
- else if (rowSize == inputRowPitch && rowSize == outputRowPitch)
- {
- for (size_t z = 0; z < depth; z++)
- {
- const type *source = OffsetDataPointer<type>(input, 0, z, inputRowPitch, inputDepthPitch);
- type *dest = OffsetDataPointer<type>(output, 0, z, outputRowPitch, outputDepthPitch);
-
- memcpy(dest, source, layerSize);
- }
- }
- else
- {
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const type *source = OffsetDataPointer<type>(input, y, z, inputRowPitch, inputDepthPitch);
- type *dest = OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch);
- memcpy(dest, source, width * sizeof(type) * componentCount);
- }
- }
- }
-}
-
-template <typename type, uint32_t fourthComponentBits>
-inline void LoadToNative3To4(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- const type fourthValue = gl::bitCast<type>(fourthComponentBits);
-
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const type *source = OffsetDataPointer<type>(input, y, z, inputRowPitch, inputDepthPitch);
- type *dest = OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- dest[x * 4 + 0] = source[x * 3 + 0];
- dest[x * 4 + 1] = source[x * 3 + 1];
- dest[x * 4 + 2] = source[x * 3 + 2];
- dest[x * 4 + 3] = fourthValue;
- }
- }
- }
-}
-
-template <size_t componentCount>
-inline void Load32FTo16F(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- const size_t elementWidth = componentCount * width;
-
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const float *source = OffsetDataPointer<float>(input, y, z, inputRowPitch, inputDepthPitch);
- uint16_t *dest = OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
-
- for (size_t x = 0; x < elementWidth; x++)
- {
- dest[x] = gl::float32ToFloat16(source[x]);
- }
- }
- }
-}
-
-template <size_t blockWidth, size_t blockHeight, size_t blockSize>
-inline void LoadCompressedToNative(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- const size_t columns = (width + (blockWidth - 1)) / blockWidth;
- const size_t rows = (height + (blockHeight - 1)) / blockHeight;
-
- for (size_t z = 0; z < depth; ++z)
- {
- for (size_t y = 0; y < rows; ++y)
- {
- const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint8_t *dest = OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
- memcpy(dest, source, columns * blockSize);
- }
- }
-}
-
-template <typename type, uint32_t firstBits, uint32_t secondBits, uint32_t thirdBits, uint32_t fourthBits>
-inline void Initialize4ComponentData(size_t width, size_t height, size_t depth,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
- type writeValues[4] =
- {
- gl::bitCast<type>(firstBits),
- gl::bitCast<type>(secondBits),
- gl::bitCast<type>(thirdBits),
- gl::bitCast<type>(fourthBits),
- };
-
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- type *destRow = OffsetDataPointer<type>(output, y, z, outputRowPitch, outputDepthPitch);
- for (size_t x = 0; x < width; x++)
- {
- type* destPixel = destRow + x * 4;
-
- // This could potentially be optimized by generating an entire row of initialization
- // data and copying row by row instead of pixel by pixel.
- memcpy(destPixel, writeValues, sizeof(type) * 4);
- }
- }
- }
-}
-
-}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimageSSE2.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimageSSE2.cpp
deleted file mode 100644
index c87d35c82b..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimageSSE2.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-//
-// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// loadimageSSE2.cpp: Defines image loading functions. It's
-// in a separated file for GCC, which can enable SSE usage only per-file,
-// not for code blocks that use SSE2 explicitly.
-
-#include "libANGLE/renderer/d3d/loadimage.h"
-
-#include "common/platform.h"
-
-#ifdef ANGLE_USE_SSE
-#include <emmintrin.h>
-#endif
-
-namespace rx
-{
-
-void LoadA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
-#if defined(ANGLE_USE_SSE)
- __m128i zeroWide = _mm_setzero_si128();
-
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint8_t *source = OffsetDataPointer<uint8_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
-
- size_t x = 0;
-
- // Make output writes aligned
- for (; ((reinterpret_cast<intptr_t>(&dest[x]) & 0xF) != 0 && x < width); x++)
- {
- dest[x] = static_cast<uint32_t>(source[x]) << 24;
- }
-
- for (; x + 7 < width; x += 8)
- {
- __m128i sourceData = _mm_loadl_epi64(reinterpret_cast<const __m128i*>(&source[x]));
- // Interleave each byte to 16bit, make the lower byte to zero
- sourceData = _mm_unpacklo_epi8(zeroWide, sourceData);
- // Interleave each 16bit to 32bit, make the lower 16bit to zero
- __m128i lo = _mm_unpacklo_epi16(zeroWide, sourceData);
- __m128i hi = _mm_unpackhi_epi16(zeroWide, sourceData);
-
- _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), lo);
- _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x + 4]), hi);
- }
-
- // Handle the remainder
- for (; x < width; x++)
- {
- dest[x] = static_cast<uint32_t>(source[x]) << 24;
- }
- }
- }
-#else
- // Ensure that this function is reported as not implemented for ARM builds because
- // the instructions below are not present for that architecture.
- UNIMPLEMENTED();
- return;
-#endif
-}
-
-void LoadRGBA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
-{
-#if defined(ANGLE_USE_SSE)
- __m128i brMask = _mm_set1_epi32(0x00ff00ff);
-
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y++)
- {
- const uint32_t *source = OffsetDataPointer<uint32_t>(input, y, z, inputRowPitch, inputDepthPitch);
- uint32_t *dest = OffsetDataPointer<uint32_t>(output, y, z, outputRowPitch, outputDepthPitch);
-
- size_t x = 0;
-
- // Make output writes aligned
- for (; ((reinterpret_cast<intptr_t>(&dest[x]) & 15) != 0) && x < width; x++)
- {
- uint32_t rgba = source[x];
- dest[x] = (ANGLE_ROTL(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
- }
-
- for (; x + 3 < width; x += 4)
- {
- __m128i sourceData = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&source[x]));
- // Mask out g and a, which don't change
- __m128i gaComponents = _mm_andnot_si128(brMask, sourceData);
- // Mask out b and r
- __m128i brComponents = _mm_and_si128(sourceData, brMask);
- // Swap b and r
- __m128i brSwapped = _mm_shufflehi_epi16(_mm_shufflelo_epi16(brComponents, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1));
- __m128i result = _mm_or_si128(gaComponents, brSwapped);
- _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), result);
- }
-
- // Perform leftover writes
- for (; x < width; x++)
- {
- uint32_t rgba = source[x];
- dest[x] = (ANGLE_ROTL(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
- }
- }
- }
-#else
- // Ensure that this function is reported as not implemented for ARM builds because
- // the instructions below are not present for that architecture.
- UNIMPLEMENTED();
- return;
-#endif
-}
-
-}
-
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage_etc.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage_etc.cpp
deleted file mode 100644
index 26a3b32ce0..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage_etc.cpp
+++ /dev/null
@@ -1,1435 +0,0 @@
-//
-// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// loadimage_etc.cpp: Decodes ETC and EAC encoded textures.
-
-#include "libANGLE/renderer/d3d/loadimage_etc.h"
-
-#include "libANGLE/renderer/d3d/loadimage.h"
-#include "libANGLE/renderer/d3d/imageformats.h"
-
-namespace rx
-{
-namespace
-{
-// Table 3.17.2 sorted according to table 3.17.3
-// clang-format off
-static const int intensityModifierDefault[][4] =
-{
- { 2, 8, -2, -8 },
- { 5, 17, -5, -17 },
- { 9, 29, -9, -29 },
- { 13, 42, -13, -42 },
- { 18, 60, -18, -60 },
- { 24, 80, -24, -80 },
- { 33, 106, -33, -106 },
- { 47, 183, -47, -183 },
-};
-// clang-format on
-
-// Table C.12, intensity modifier for non opaque punchthrough alpha
-// clang-format off
-static const int intensityModifierNonOpaque[][4] =
-{
- { 0, 8, 0, -8 },
- { 0, 17, 0, -17 },
- { 0, 29, 0, -29 },
- { 0, 42, 0, -42 },
- { 0, 60, 0, -60 },
- { 0, 80, 0, -80 },
- { 0, 106, 0, -106 },
- { 0, 183, 0, -183 },
-};
-// clang-format on
-
-// Table C.7, mapping from pixel index values to modifier value orders
-// clang-format off
-static const int valueMappingTable[] =
-{
- 2, 3, 1, 0
-};
-// clang-format on
-
-struct ETC2Block
-{
- // Decodes unsigned single or dual channel block to bytes
- void decodeAsSingleChannel(uint8_t *dest,
- size_t x,
- size_t y,
- size_t w,
- size_t h,
- size_t destPixelStride,
- size_t destRowPitch,
- bool isSigned) const
- {
- for (size_t j = 0; j < 4 && (y + j) < h; j++)
- {
- uint8_t *row = dest + (j * destRowPitch);
- for (size_t i = 0; i < 4 && (x + i) < w; i++)
- {
- uint8_t *pixel = row + (i * destPixelStride);
- if (isSigned)
- {
- *pixel = clampSByte(getSingleChannel(i, j, isSigned));
- }
- else
- {
- *pixel = clampByte(getSingleChannel(i, j, isSigned));
- }
- }
- }
- }
-
- // Decodes RGB block to rgba8
- void decodeAsRGB(uint8_t *dest,
- size_t x,
- size_t y,
- size_t w,
- size_t h,
- size_t destRowPitch,
- const uint8_t alphaValues[4][4],
- bool punchThroughAlpha) const
- {
- bool opaqueBit = u.idht.mode.idm.diffbit;
- bool nonOpaquePunchThroughAlpha = punchThroughAlpha && !opaqueBit;
- // Select mode
- if (u.idht.mode.idm.diffbit || punchThroughAlpha)
- {
- const auto &block = u.idht.mode.idm.colors.diff;
- int r = (block.R + block.dR);
- int g = (block.G + block.dG);
- int b = (block.B + block.dB);
- if (r < 0 || r > 31)
- {
- decodeTBlock(dest, x, y, w, h, destRowPitch, alphaValues,
- nonOpaquePunchThroughAlpha);
- }
- else if (g < 0 || g > 31)
- {
- decodeHBlock(dest, x, y, w, h, destRowPitch, alphaValues,
- nonOpaquePunchThroughAlpha);
- }
- else if (b < 0 || b > 31)
- {
- decodePlanarBlock(dest, x, y, w, h, destRowPitch, alphaValues);
- }
- else
- {
- decodeDifferentialBlock(dest, x, y, w, h, destRowPitch, alphaValues,
- nonOpaquePunchThroughAlpha);
- }
- }
- else
- {
- decodeIndividualBlock(dest, x, y, w, h, destRowPitch, alphaValues,
- nonOpaquePunchThroughAlpha);
- }
- }
-
- // Transcodes RGB block to BC1
- void transcodeAsBC1(uint8_t *dest,
- size_t x,
- size_t y,
- size_t w,
- size_t h,
- const uint8_t alphaValues[4][4],
- bool punchThroughAlpha) const
- {
- bool opaqueBit = u.idht.mode.idm.diffbit;
- bool nonOpaquePunchThroughAlpha = punchThroughAlpha && !opaqueBit;
- // Select mode
- if (u.idht.mode.idm.diffbit || punchThroughAlpha)
- {
- const auto &block = u.idht.mode.idm.colors.diff;
- int r = (block.R + block.dR);
- int g = (block.G + block.dG);
- int b = (block.B + block.dB);
- if (r < 0 || r > 31)
- {
- transcodeTBlockToBC1(dest, x, y, w, h, alphaValues, nonOpaquePunchThroughAlpha);
- }
- else if (g < 0 || g > 31)
- {
- transcodeHBlockToBC1(dest, x, y, w, h, alphaValues, nonOpaquePunchThroughAlpha);
- }
- else if (b < 0 || b > 31)
- {
- transcodePlanarBlockToBC1(dest, x, y, w, h, alphaValues);
- }
- else
- {
- transcodeDifferentialBlockToBC1(dest, x, y, w, h, alphaValues,
- nonOpaquePunchThroughAlpha);
- }
- }
- else
- {
- transcodeIndividualBlockToBC1(dest, x, y, w, h, alphaValues,
- nonOpaquePunchThroughAlpha);
- }
- }
-
- private:
- union
- {
- // Individual, differential, H and T modes
- struct
- {
- union
- {
- // Individual and differential modes
- struct
- {
- union
- {
- struct // Individual colors
- {
- unsigned char R2 : 4;
- unsigned char R1 : 4;
- unsigned char G2 : 4;
- unsigned char G1 : 4;
- unsigned char B2 : 4;
- unsigned char B1 : 4;
- } indiv;
- struct // Differential colors
- {
- signed char dR : 3;
- unsigned char R : 5;
- signed char dG : 3;
- unsigned char G : 5;
- signed char dB : 3;
- unsigned char B : 5;
- } diff;
- } colors;
- bool flipbit : 1;
- bool diffbit : 1;
- unsigned char cw2 : 3;
- unsigned char cw1 : 3;
- } idm;
- // T mode
- struct
- {
- // Byte 1
- unsigned char TR1b : 2;
- unsigned char TdummyB : 1;
- unsigned char TR1a : 2;
- unsigned char TdummyA : 3;
- // Byte 2
- unsigned char TB1 : 4;
- unsigned char TG1 : 4;
- // Byte 3
- unsigned char TG2 : 4;
- unsigned char TR2 : 4;
- // Byte 4
- unsigned char Tdb : 1;
- bool Tflipbit : 1;
- unsigned char Tda : 2;
- unsigned char TB2 : 4;
- } tm;
- // H mode
- struct
- {
- // Byte 1
- unsigned char HG1a : 3;
- unsigned char HR1 : 4;
- unsigned char HdummyA : 1;
- // Byte 2
- unsigned char HB1b : 2;
- unsigned char HdummyC : 1;
- unsigned char HB1a : 1;
- unsigned char HG1b : 1;
- unsigned char HdummyB : 3;
- // Byte 3
- unsigned char HG2a : 3;
- unsigned char HR2 : 4;
- unsigned char HB1c : 1;
- // Byte 4
- unsigned char Hdb : 1;
- bool Hflipbit : 1;
- unsigned char Hda : 1;
- unsigned char HB2 : 4;
- unsigned char HG2b : 1;
- } hm;
- } mode;
- unsigned char pixelIndexMSB[2];
- unsigned char pixelIndexLSB[2];
- } idht;
- // planar mode
- struct
- {
- // Byte 1
- unsigned char GO1 : 1;
- unsigned char RO : 6;
- unsigned char PdummyA : 1;
- // Byte 2
- unsigned char BO1 : 1;
- unsigned char GO2 : 6;
- unsigned char PdummyB : 1;
- // Byte 3
- unsigned char BO3a : 2;
- unsigned char PdummyD : 1;
- unsigned char BO2 : 2;
- unsigned char PdummyC : 3;
- // Byte 4
- unsigned char RH2 : 1;
- bool Pflipbit : 1;
- unsigned char RH1 : 5;
- unsigned char BO3b : 1;
- // Byte 5
- unsigned char BHa : 1;
- unsigned char GH : 7;
- // Byte 6
- unsigned char RVa : 3;
- unsigned char BHb : 5;
- // Byte 7
- unsigned char GVa : 5;
- unsigned char RVb : 3;
- // Byte 8
- unsigned char BV : 6;
- unsigned char GVb : 2;
- } pblk;
- // Single channel block
- struct
- {
- union
- {
- unsigned char us;
- signed char s;
- } base_codeword;
- unsigned char table_index : 4;
- unsigned char multiplier : 4;
- unsigned char mc1 : 2;
- unsigned char mb : 3;
- unsigned char ma : 3;
- unsigned char mf1 : 1;
- unsigned char me : 3;
- unsigned char md : 3;
- unsigned char mc2 : 1;
- unsigned char mh : 3;
- unsigned char mg : 3;
- unsigned char mf2 : 2;
- unsigned char mk1 : 2;
- unsigned char mj : 3;
- unsigned char mi : 3;
- unsigned char mn1 : 1;
- unsigned char mm : 3;
- unsigned char ml : 3;
- unsigned char mk2 : 1;
- unsigned char mp : 3;
- unsigned char mo : 3;
- unsigned char mn2 : 2;
- } scblk;
- } u;
-
- static unsigned char clampByte(int value)
- {
- return static_cast<unsigned char>(gl::clamp(value, 0, 255));
- }
-
- static signed char clampSByte(int value)
- {
- return static_cast<signed char>(gl::clamp(value, -128, 127));
- }
-
- static R8G8B8A8 createRGBA(int red, int green, int blue, int alpha)
- {
- R8G8B8A8 rgba;
- rgba.R = clampByte(red);
- rgba.G = clampByte(green);
- rgba.B = clampByte(blue);
- rgba.A = clampByte(alpha);
- return rgba;
- }
-
- static R8G8B8A8 createRGBA(int red, int green, int blue)
- {
- return createRGBA(red, green, blue, 255);
- }
-
- static int extend_4to8bits(int x) { return (x << 4) | x; }
- static int extend_5to8bits(int x) { return (x << 3) | (x >> 2); }
- static int extend_6to8bits(int x) { return (x << 2) | (x >> 4); }
- static int extend_7to8bits(int x) { return (x << 1) | (x >> 6); }
-
- void decodeIndividualBlock(uint8_t *dest,
- size_t x,
- size_t y,
- size_t w,
- size_t h,
- size_t destRowPitch,
- const uint8_t alphaValues[4][4],
- bool nonOpaquePunchThroughAlpha) const
- {
- const auto &block = u.idht.mode.idm.colors.indiv;
- int r1 = extend_4to8bits(block.R1);
- int g1 = extend_4to8bits(block.G1);
- int b1 = extend_4to8bits(block.B1);
- int r2 = extend_4to8bits(block.R2);
- int g2 = extend_4to8bits(block.G2);
- int b2 = extend_4to8bits(block.B2);
- decodeIndividualOrDifferentialBlock(dest, x, y, w, h, destRowPitch, r1, g1, b1, r2, g2, b2,
- alphaValues, nonOpaquePunchThroughAlpha);
- }
-
- void decodeDifferentialBlock(uint8_t *dest,
- size_t x,
- size_t y,
- size_t w,
- size_t h,
- size_t destRowPitch,
- const uint8_t alphaValues[4][4],
- bool nonOpaquePunchThroughAlpha) const
- {
- const auto &block = u.idht.mode.idm.colors.diff;
- int b1 = extend_5to8bits(block.B);
- int g1 = extend_5to8bits(block.G);
- int r1 = extend_5to8bits(block.R);
- int r2 = extend_5to8bits(block.R + block.dR);
- int g2 = extend_5to8bits(block.G + block.dG);
- int b2 = extend_5to8bits(block.B + block.dB);
- decodeIndividualOrDifferentialBlock(dest, x, y, w, h, destRowPitch, r1, g1, b1, r2, g2, b2,
- alphaValues, nonOpaquePunchThroughAlpha);
- }
-
- void decodeIndividualOrDifferentialBlock(uint8_t *dest,
- size_t x,
- size_t y,
- size_t w,
- size_t h,
- size_t destRowPitch,
- int r1,
- int g1,
- int b1,
- int r2,
- int g2,
- int b2,
- const uint8_t alphaValues[4][4],
- bool nonOpaquePunchThroughAlpha) const
- {
- const auto intensityModifier =
- nonOpaquePunchThroughAlpha ? intensityModifierNonOpaque : intensityModifierDefault;
-
- R8G8B8A8 subblockColors0[4];
- R8G8B8A8 subblockColors1[4];
- for (size_t modifierIdx = 0; modifierIdx < 4; modifierIdx++)
- {
- const int i1 = intensityModifier[u.idht.mode.idm.cw1][modifierIdx];
- subblockColors0[modifierIdx] = createRGBA(r1 + i1, g1 + i1, b1 + i1);
-
- const int i2 = intensityModifier[u.idht.mode.idm.cw2][modifierIdx];
- subblockColors1[modifierIdx] = createRGBA(r2 + i2, g2 + i2, b2 + i2);
- }
-
- if (u.idht.mode.idm.flipbit)
- {
- uint8_t *curPixel = dest;
- for (size_t j = 0; j < 2 && (y + j) < h; j++)
- {
- R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
- for (size_t i = 0; i < 4 && (x + i) < w; i++)
- {
- row[i] = subblockColors0[getIndex(i, j)];
- row[i].A = alphaValues[j][i];
- }
- curPixel += destRowPitch;
- }
- for (size_t j = 2; j < 4 && (y + j) < h; j++)
- {
- R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
- for (size_t i = 0; i < 4 && (x + i) < w; i++)
- {
- row[i] = subblockColors1[getIndex(i, j)];
- row[i].A = alphaValues[j][i];
- }
- curPixel += destRowPitch;
- }
- }
- else
- {
- uint8_t *curPixel = dest;
- for (size_t j = 0; j < 4 && (y + j) < h; j++)
- {
- R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
- for (size_t i = 0; i < 2 && (x + i) < w; i++)
- {
- row[i] = subblockColors0[getIndex(i, j)];
- row[i].A = alphaValues[j][i];
- }
- for (size_t i = 2; i < 4 && (x + i) < w; i++)
- {
- row[i] = subblockColors1[getIndex(i, j)];
- row[i].A = alphaValues[j][i];
- }
- curPixel += destRowPitch;
- }
- }
- if (nonOpaquePunchThroughAlpha)
- {
- decodePunchThroughAlphaBlock(dest, x, y, w, h, destRowPitch);
- }
- }
-
- void decodeTBlock(uint8_t *dest,
- size_t x,
- size_t y,
- size_t w,
- size_t h,
- size_t destRowPitch,
- const uint8_t alphaValues[4][4],
- bool nonOpaquePunchThroughAlpha) const
- {
- // Table C.8, distance index for T and H modes
- const auto &block = u.idht.mode.tm;
-
- int r1 = extend_4to8bits(block.TR1a << 2 | block.TR1b);
- int g1 = extend_4to8bits(block.TG1);
- int b1 = extend_4to8bits(block.TB1);
- int r2 = extend_4to8bits(block.TR2);
- int g2 = extend_4to8bits(block.TG2);
- int b2 = extend_4to8bits(block.TB2);
-
- static int distance[8] = {3, 6, 11, 16, 23, 32, 41, 64};
- const int d = distance[block.Tda << 1 | block.Tdb];
-
- const R8G8B8A8 paintColors[4] = {
- createRGBA(r1, g1, b1), createRGBA(r2 + d, g2 + d, b2 + d), createRGBA(r2, g2, b2),
- createRGBA(r2 - d, g2 - d, b2 - d),
- };
-
- uint8_t *curPixel = dest;
- for (size_t j = 0; j < 4 && (y + j) < h; j++)
- {
- R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
- for (size_t i = 0; i < 4 && (x + i) < w; i++)
- {
- row[i] = paintColors[getIndex(i, j)];
- row[i].A = alphaValues[j][i];
- }
- curPixel += destRowPitch;
- }
-
- if (nonOpaquePunchThroughAlpha)
- {
- decodePunchThroughAlphaBlock(dest, x, y, w, h, destRowPitch);
- }
- }
-
- void decodeHBlock(uint8_t *dest,
- size_t x,
- size_t y,
- size_t w,
- size_t h,
- size_t destRowPitch,
- const uint8_t alphaValues[4][4],
- bool nonOpaquePunchThroughAlpha) const
- {
- // Table C.8, distance index for T and H modes
- const auto &block = u.idht.mode.hm;
-
- int r1 = extend_4to8bits(block.HR1);
- int g1 = extend_4to8bits(block.HG1a << 1 | block.HG1b);
- int b1 = extend_4to8bits(block.HB1a << 3 | block.HB1b << 1 | block.HB1c);
- int r2 = extend_4to8bits(block.HR2);
- int g2 = extend_4to8bits(block.HG2a << 1 | block.HG2b);
- int b2 = extend_4to8bits(block.HB2);
-
- static const int distance[8] = {3, 6, 11, 16, 23, 32, 41, 64};
- const int d = distance[(block.Hda << 2) | (block.Hdb << 1) |
- ((r1 << 16 | g1 << 8 | b1) >= (r2 << 16 | g2 << 8 | b2) ? 1 : 0)];
-
- const R8G8B8A8 paintColors[4] = {
- createRGBA(r1 + d, g1 + d, b1 + d), createRGBA(r1 - d, g1 - d, b1 - d),
- createRGBA(r2 + d, g2 + d, b2 + d), createRGBA(r2 - d, g2 - d, b2 - d),
- };
-
- uint8_t *curPixel = dest;
- for (size_t j = 0; j < 4 && (y + j) < h; j++)
- {
- R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
- for (size_t i = 0; i < 4 && (x + i) < w; i++)
- {
- row[i] = paintColors[getIndex(i, j)];
- row[i].A = alphaValues[j][i];
- }
- curPixel += destRowPitch;
- }
-
- if (nonOpaquePunchThroughAlpha)
- {
- decodePunchThroughAlphaBlock(dest, x, y, w, h, destRowPitch);
- }
- }
-
- void decodePlanarBlock(uint8_t *dest,
- size_t x,
- size_t y,
- size_t w,
- size_t h,
- size_t pitch,
- const uint8_t alphaValues[4][4]) const
- {
- int ro = extend_6to8bits(u.pblk.RO);
- int go = extend_7to8bits(u.pblk.GO1 << 6 | u.pblk.GO2);
- int bo =
- extend_6to8bits(u.pblk.BO1 << 5 | u.pblk.BO2 << 3 | u.pblk.BO3a << 1 | u.pblk.BO3b);
- int rh = extend_6to8bits(u.pblk.RH1 << 1 | u.pblk.RH2);
- int gh = extend_7to8bits(u.pblk.GH);
- int bh = extend_6to8bits(u.pblk.BHa << 5 | u.pblk.BHb);
- int rv = extend_6to8bits(u.pblk.RVa << 3 | u.pblk.RVb);
- int gv = extend_7to8bits(u.pblk.GVa << 2 | u.pblk.GVb);
- int bv = extend_6to8bits(u.pblk.BV);
-
- uint8_t *curPixel = dest;
- for (size_t j = 0; j < 4 && (y + j) < h; j++)
- {
- R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
-
- int ry = static_cast<int>(j) * (rv - ro) + 2;
- int gy = static_cast<int>(j) * (gv - go) + 2;
- int by = static_cast<int>(j) * (bv - bo) + 2;
- for (size_t i = 0; i < 4 && (x + i) < w; i++)
- {
- row[i] = createRGBA(((static_cast<int>(i) * (rh - ro) + ry) >> 2) + ro,
- ((static_cast<int>(i) * (gh - go) + gy) >> 2) + go,
- ((static_cast<int>(i) * (bh - bo) + by) >> 2) + bo,
- alphaValues[j][i]);
- }
- curPixel += pitch;
- }
- }
-
- // Index for individual, differential, H and T modes
- size_t getIndex(size_t x, size_t y) const
- {
- size_t bitIndex = x * 4 + y;
- size_t bitOffset = bitIndex & 7;
- size_t lsb = (u.idht.pixelIndexLSB[1 - (bitIndex >> 3)] >> bitOffset) & 1;
- size_t msb = (u.idht.pixelIndexMSB[1 - (bitIndex >> 3)] >> bitOffset) & 1;
- return (msb << 1) | lsb;
- }
-
- void decodePunchThroughAlphaBlock(uint8_t *dest,
- size_t x,
- size_t y,
- size_t w,
- size_t h,
- size_t destRowPitch) const
- {
- uint8_t *curPixel = dest;
- for (size_t j = 0; j < 4 && (y + j) < h; j++)
- {
- R8G8B8A8 *row = reinterpret_cast<R8G8B8A8 *>(curPixel);
- for (size_t i = 0; i < 4 && (x + i) < w; i++)
- {
- if (getIndex(i, j) == 2) // msb == 1 && lsb == 0
- {
- row[i] = createRGBA(0, 0, 0, 0);
- }
- }
- curPixel += destRowPitch;
- }
- }
-
- uint16_t RGB8ToRGB565(const R8G8B8A8 &rgba) const
- {
- return (static_cast<uint16_t>(rgba.R >> 3) << 11) |
- (static_cast<uint16_t>(rgba.G >> 2) << 5) |
- (static_cast<uint16_t>(rgba.B >> 3) << 0);
- }
-
- uint32_t matchBC1Bits(const R8G8B8A8 *rgba,
- const R8G8B8A8 &minColor,
- const R8G8B8A8 &maxColor,
- bool opaque) const
- {
- // Project each pixel on the (maxColor, minColor) line to decide which
- // BC1 code to assign to it.
-
- uint8_t decodedColors[2][3] = {{maxColor.R, maxColor.G, maxColor.B},
- {minColor.R, minColor.G, minColor.B}};
-
- int direction[3];
- for (int ch = 0; ch < 3; ch++)
- {
- direction[ch] = decodedColors[0][ch] - decodedColors[1][ch];
- }
-
- int stops[2];
- for (int i = 0; i < 2; i++)
- {
- stops[i] = decodedColors[i][0] * direction[0] + decodedColors[i][1] * direction[1] +
- decodedColors[i][2] * direction[2];
- }
-
- uint32_t bits = 0;
- if (opaque)
- {
- for (int i = 15; i >= 0; i--)
- {
- // In opaque mode, the code is from 0 to 3.
-
- bits <<= 2;
- const int dot =
- rgba[i].R * direction[0] + rgba[i].G * direction[1] + rgba[i].B * direction[2];
- const int factor = gl::clamp(
- static_cast<int>(
- (static_cast<float>(dot - stops[1]) / (stops[0] - stops[1])) * 3 + 0.5f),
- 0, 3);
- switch (factor)
- {
- case 0:
- bits |= 1;
- break;
- case 1:
- bits |= 3;
- break;
- case 2:
- bits |= 2;
- break;
- case 3:
- default:
- bits |= 0;
- break;
- }
- }
- }
- else
- {
- for (int i = 15; i >= 0; i--)
- {
- // In non-opaque mode, 3 is for tranparent pixels.
-
- bits <<= 2;
- if (0 == rgba[i].A)
- {
- bits |= 3;
- }
- else
- {
- const int dot = rgba[i].R * direction[0] + rgba[i].G * direction[1] +
- rgba[i].B * direction[2];
- const int factor = gl::clamp(
- static_cast<int>(
- (static_cast<float>(dot - stops[1]) / (stops[0] - stops[1])) * 2 +
- 0.5f),
- 0, 2);
- switch (factor)
- {
- case 0:
- bits |= 0;
- break;
- case 1:
- bits |= 2;
- break;
- case 2:
- default:
- bits |= 1;
- break;
- }
- }
- }
- }
-
- return bits;
- }
-
- void packBC1(void *bc1,
- const R8G8B8A8 *rgba,
- R8G8B8A8 &minColor,
- R8G8B8A8 &maxColor,
- bool opaque) const
- {
- uint32_t bits;
- uint16_t max16 = RGB8ToRGB565(maxColor);
- uint16_t min16 = RGB8ToRGB565(minColor);
- if (max16 != min16)
- {
- // Find the best BC1 code for each pixel
- bits = matchBC1Bits(rgba, minColor, maxColor, opaque);
- }
- else
- {
- // Same colors, BC1 index 0 is the color in both opaque and transparent mode
- bits = 0;
- // BC1 index 3 is transparent
- if (!opaque)
- {
- for (int i = 0; i < 16; i++)
- {
- if (0 == rgba[i].A)
- {
- bits |= (3 << (i * 2));
- }
- }
- }
- }
-
- if (max16 < min16)
- {
- std::swap(max16, min16);
-
- uint32_t xorMask = 0;
- if (opaque)
- {
- // In opaque mode switching the two colors is doing the
- // following code swaps: 0 <-> 1 and 2 <-> 3. This is
- // equivalent to flipping the first bit of each code
- // (5 = 0b0101)
- xorMask = 0x55555555;
- }
- else
- {
- // In transparent mode switching the colors is doing the
- // following code swap: 0 <-> 1. 0xA selects the second bit of
- // each code, bits >> 1 selects the first bit of the code when
- // the seconds bit is set (case 2 and 3). We invert all the
- // non-selected bits, that is the first bit when the code is
- // 0 or 1.
- xorMask = ~((bits >> 1) | 0xAAAAAAAA);
- }
- bits ^= xorMask;
- }
-
- struct BC1Block
- {
- uint16_t color0;
- uint16_t color1;
- uint32_t bits;
- };
-
- // Encode the opaqueness in the order of the two BC1 colors
- BC1Block *dest = reinterpret_cast<BC1Block *>(bc1);
- if (opaque)
- {
- dest->color0 = max16;
- dest->color1 = min16;
- }
- else
- {
- dest->color0 = min16;
- dest->color1 = max16;
- }
- dest->bits = bits;
- }
-
- void transcodeIndividualBlockToBC1(uint8_t *dest,
- size_t x,
- size_t y,
- size_t w,
- size_t h,
- const uint8_t alphaValues[4][4],
- bool nonOpaquePunchThroughAlpha) const
- {
- const auto &block = u.idht.mode.idm.colors.indiv;
- int r1 = extend_4to8bits(block.R1);
- int g1 = extend_4to8bits(block.G1);
- int b1 = extend_4to8bits(block.B1);
- int r2 = extend_4to8bits(block.R2);
- int g2 = extend_4to8bits(block.G2);
- int b2 = extend_4to8bits(block.B2);
- transcodeIndividualOrDifferentialBlockToBC1(dest, x, y, w, h, r1, g1, b1, r2, g2, b2,
- alphaValues, nonOpaquePunchThroughAlpha);
- }
-
- void transcodeDifferentialBlockToBC1(uint8_t *dest,
- size_t x,
- size_t y,
- size_t w,
- size_t h,
- const uint8_t alphaValues[4][4],
- bool nonOpaquePunchThroughAlpha) const
- {
- const auto &block = u.idht.mode.idm.colors.diff;
- int b1 = extend_5to8bits(block.B);
- int g1 = extend_5to8bits(block.G);
- int r1 = extend_5to8bits(block.R);
- int r2 = extend_5to8bits(block.R + block.dR);
- int g2 = extend_5to8bits(block.G + block.dG);
- int b2 = extend_5to8bits(block.B + block.dB);
- transcodeIndividualOrDifferentialBlockToBC1(dest, x, y, w, h, r1, g1, b1, r2, g2, b2,
- alphaValues, nonOpaquePunchThroughAlpha);
- }
-
- void decodeSubblock(R8G8B8A8 *rgbaBlock,
- size_t pixelRange[2][2],
- size_t x,
- size_t y,
- size_t w,
- size_t h,
- const uint8_t alphaValues[4][4],
- bool flipbit,
- size_t subblockIdx,
- const R8G8B8A8 subblockColors[2][4]) const
- {
- size_t dxBegin = 0;
- size_t dxEnd = 4;
- size_t dyBegin = subblockIdx * 2;
- size_t dyEnd = dyBegin + 2;
- if (!flipbit)
- {
- std::swap(dxBegin, dyBegin);
- std::swap(dxEnd, dyEnd);
- }
-
- for (size_t j = dyBegin; j < dyEnd && (y + j) < h; j++)
- {
- R8G8B8A8 *row = &rgbaBlock[j * 4];
- for (size_t i = dxBegin; i < dxEnd && (x + i) < w; i++)
- {
- const size_t pixelIndex = getIndex(i, j);
- if (valueMappingTable[pixelIndex] < valueMappingTable[pixelRange[subblockIdx][0]])
- {
- pixelRange[subblockIdx][0] = pixelIndex;
- }
- if (valueMappingTable[pixelIndex] > valueMappingTable[pixelRange[subblockIdx][1]])
- {
- pixelRange[subblockIdx][1] = pixelIndex;
- }
-
- row[i] = subblockColors[subblockIdx][pixelIndex];
- row[i].A = alphaValues[j][i];
- }
- }
- }
-
- void transcodeIndividualOrDifferentialBlockToBC1(uint8_t *dest,
- size_t x,
- size_t y,
- size_t w,
- size_t h,
- int r1,
- int g1,
- int b1,
- int r2,
- int g2,
- int b2,
- const uint8_t alphaValues[4][4],
- bool nonOpaquePunchThroughAlpha) const
- {
- // A BC1 block has 2 endpoints, pixels is encoded as linear
- // interpolations of them. A ETC1/ETC2 individual or differential block
- // has 2 subblocks. Each subblock has one color and a modifier. We
- // compute the max intensity and min intensity pixel values to use as
- // our two BC1 endpoints and then map pixels to BC1 by projecting on the
- // line between the two endpoints and choosing the right fraction.
- //
- // In the future, we have 2 potential improvements to this algorithm.
- // 1. We don't actually need to decode ETC blocks to RGBs. Instead,
- // the subblock colors and pixel indices alreay contains enough
- // information for transcode. A direct mapping would be more
- // efficient here.
- // 2. Currently the BC1 endpoints come from the max and min intensity
- // of ETC colors. A principal component analysis (PCA) on them might
- // give us better quality results, with limited costs
-
- const auto intensityModifier =
- nonOpaquePunchThroughAlpha ? intensityModifierNonOpaque : intensityModifierDefault;
-
- // Compute the colors that pixels can have in each subblock both for
- // the decoding of the RGBA data and BC1 encoding
- R8G8B8A8 subblockColors[2][4];
- for (size_t modifierIdx = 0; modifierIdx < 4; modifierIdx++)
- {
- const int i1 = intensityModifier[u.idht.mode.idm.cw1][modifierIdx];
- subblockColors[0][modifierIdx] = createRGBA(r1 + i1, g1 + i1, b1 + i1);
-
- const int i2 = intensityModifier[u.idht.mode.idm.cw2][modifierIdx];
- subblockColors[1][modifierIdx] = createRGBA(r2 + i2, g2 + i2, b2 + i2);
- }
-
- // 1 and 3 are the argmax and argmin of valueMappingTable
- size_t pixelRange[2][2] = {{1, 3}, {1, 3}};
- R8G8B8A8 rgbaBlock[16];
- // Decode the block in rgbaBlock and store the inverse valueTableMapping
- // of {min(modifier index), max(modifier index)}
- for (size_t blockIdx = 0; blockIdx < 2; blockIdx++)
- {
- decodeSubblock(rgbaBlock, pixelRange, x, y, w, h, alphaValues, u.idht.mode.idm.flipbit,
- blockIdx, subblockColors);
- }
- if (nonOpaquePunchThroughAlpha)
- {
- decodePunchThroughAlphaBlock(reinterpret_cast<uint8_t *>(rgbaBlock), x, y, w, h,
- sizeof(R8G8B8A8) * 4);
- }
-
- // Get the "min" and "max" pixel colors that have been used.
- R8G8B8A8 minColor;
- const R8G8B8A8 &minColor0 = subblockColors[0][pixelRange[0][0]];
- const R8G8B8A8 &minColor1 = subblockColors[1][pixelRange[1][0]];
- if (minColor0.R + minColor0.G + minColor0.B < minColor1.R + minColor1.G + minColor1.B)
- {
- minColor = minColor0;
- }
- else
- {
- minColor = minColor1;
- }
-
- R8G8B8A8 maxColor;
- const R8G8B8A8 &maxColor0 = subblockColors[0][pixelRange[0][1]];
- const R8G8B8A8 &maxColor1 = subblockColors[1][pixelRange[1][1]];
- if (maxColor0.R + maxColor0.G + maxColor0.B < maxColor1.R + maxColor1.G + maxColor1.B)
- {
- maxColor = maxColor1;
- }
- else
- {
- maxColor = maxColor0;
- }
-
- packBC1(dest, rgbaBlock, minColor, maxColor, !nonOpaquePunchThroughAlpha);
- }
-
- void transcodeTBlockToBC1(uint8_t *dest,
- size_t x,
- size_t y,
- size_t w,
- size_t h,
- const uint8_t alphaValues[4][4],
- bool nonOpaquePunchThroughAlpha) const
- {
- // TODO (mgong): Will be implemented soon
- UNIMPLEMENTED();
- }
-
- void transcodeHBlockToBC1(uint8_t *dest,
- size_t x,
- size_t y,
- size_t w,
- size_t h,
- const uint8_t alphaValues[4][4],
- bool nonOpaquePunchThroughAlpha) const
- {
- // TODO (mgong): Will be implemented soon
- UNIMPLEMENTED();
- }
-
- void transcodePlanarBlockToBC1(uint8_t *dest,
- size_t x,
- size_t y,
- size_t w,
- size_t h,
- const uint8_t alphaValues[4][4]) const
- {
- // TODO (mgong): Will be implemented soon
- UNIMPLEMENTED();
- }
-
- // Single channel utility functions
- int getSingleChannel(size_t x, size_t y, bool isSigned) const
- {
- int codeword = isSigned ? u.scblk.base_codeword.s : u.scblk.base_codeword.us;
- return codeword + getSingleChannelModifier(x, y) * u.scblk.multiplier;
- }
-
- int getSingleChannelIndex(size_t x, size_t y) const
- {
- ASSERT(x < 4 && y < 4);
-
- // clang-format off
- switch (x * 4 + y)
- {
- case 0: return u.scblk.ma;
- case 1: return u.scblk.mb;
- case 2: return u.scblk.mc1 << 1 | u.scblk.mc2;
- case 3: return u.scblk.md;
- case 4: return u.scblk.me;
- case 5: return u.scblk.mf1 << 2 | u.scblk.mf2;
- case 6: return u.scblk.mg;
- case 7: return u.scblk.mh;
- case 8: return u.scblk.mi;
- case 9: return u.scblk.mj;
- case 10: return u.scblk.mk1 << 1 | u.scblk.mk2;
- case 11: return u.scblk.ml;
- case 12: return u.scblk.mm;
- case 13: return u.scblk.mn1 << 2 | u.scblk.mn2;
- case 14: return u.scblk.mo;
- case 15: return u.scblk.mp;
- default: UNREACHABLE(); return 0;
- }
- // clang-format on
- }
-
- int getSingleChannelModifier(size_t x, size_t y) const
- {
- // clang-format off
- static const int modifierTable[16][8] =
- {
- { -3, -6, -9, -15, 2, 5, 8, 14 },
- { -3, -7, -10, -13, 2, 6, 9, 12 },
- { -2, -5, -8, -13, 1, 4, 7, 12 },
- { -2, -4, -6, -13, 1, 3, 5, 12 },
- { -3, -6, -8, -12, 2, 5, 7, 11 },
- { -3, -7, -9, -11, 2, 6, 8, 10 },
- { -4, -7, -8, -11, 3, 6, 7, 10 },
- { -3, -5, -8, -11, 2, 4, 7, 10 },
- { -2, -6, -8, -10, 1, 5, 7, 9 },
- { -2, -5, -8, -10, 1, 4, 7, 9 },
- { -2, -4, -8, -10, 1, 3, 7, 9 },
- { -2, -5, -7, -10, 1, 4, 6, 9 },
- { -3, -4, -7, -10, 2, 3, 6, 9 },
- { -1, -2, -3, -10, 0, 1, 2, 9 },
- { -4, -6, -8, -9, 3, 5, 7, 8 },
- { -3, -5, -7, -9, 2, 4, 6, 8 }
- };
- // clang-format on
-
- return modifierTable[u.scblk.table_index][getSingleChannelIndex(x, y)];
- }
-};
-
-// clang-format off
-static const uint8_t DefaultETCAlphaValues[4][4] =
-{
- { 255, 255, 255, 255 },
- { 255, 255, 255, 255 },
- { 255, 255, 255, 255 },
- { 255, 255, 255, 255 },
-};
-// clang-format on
-
-void LoadR11EACToR8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch,
- bool isSigned)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y += 4)
- {
- const ETC2Block *sourceRow =
- OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
- uint8_t *destRow =
- OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
-
- for (size_t x = 0; x < width; x += 4)
- {
- const ETC2Block *sourceBlock = sourceRow + (x / 4);
- uint8_t *destPixels = destRow + x;
-
- sourceBlock->decodeAsSingleChannel(destPixels, x, y, width, height, 1,
- outputRowPitch, isSigned);
- }
- }
- }
-}
-
-void LoadRG11EACToRG8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch,
- bool isSigned)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y += 4)
- {
- const ETC2Block *sourceRow =
- OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
- uint8_t *destRow =
- OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
-
- for (size_t x = 0; x < width; x += 4)
- {
- uint8_t *destPixelsRed = destRow + (x * 2);
- const ETC2Block *sourceBlockRed = sourceRow + (x / 2);
- sourceBlockRed->decodeAsSingleChannel(destPixelsRed, x, y, width, height, 2,
- outputRowPitch, isSigned);
-
- uint8_t *destPixelsGreen = destPixelsRed + 1;
- const ETC2Block *sourceBlockGreen = sourceBlockRed + 1;
- sourceBlockGreen->decodeAsSingleChannel(destPixelsGreen, x, y, width, height, 2,
- outputRowPitch, isSigned);
- }
- }
- }
-}
-
-void LoadETC2RGB8ToRGBA8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch,
- bool punchthroughAlpha)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y += 4)
- {
- const ETC2Block *sourceRow =
- OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
- uint8_t *destRow =
- OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
-
- for (size_t x = 0; x < width; x += 4)
- {
- const ETC2Block *sourceBlock = sourceRow + (x / 4);
- uint8_t *destPixels = destRow + (x * 4);
-
- sourceBlock->decodeAsRGB(destPixels, x, y, width, height, outputRowPitch,
- DefaultETCAlphaValues, punchthroughAlpha);
- }
- }
- }
-}
-
-void LoadETC2RGB8ToBC1(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch,
- bool punchthroughAlpha)
-{
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y += 4)
- {
- const ETC2Block *sourceRow =
- OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
- uint8_t *destRow =
- OffsetDataPointer<uint8_t>(output, y / 4, z, outputRowPitch, outputDepthPitch);
-
- for (size_t x = 0; x < width; x += 4)
- {
- const ETC2Block *sourceBlock = sourceRow + (x / 4);
- uint8_t *destPixels = destRow + (x * 2);
-
- sourceBlock->transcodeAsBC1(destPixels, x, y, width, height, DefaultETCAlphaValues,
- punchthroughAlpha);
- }
- }
- }
-}
-
-void LoadETC2RGBA8ToRGBA8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch,
- bool srgb)
-{
- uint8_t decodedAlphaValues[4][4];
-
- for (size_t z = 0; z < depth; z++)
- {
- for (size_t y = 0; y < height; y += 4)
- {
- const ETC2Block *sourceRow =
- OffsetDataPointer<ETC2Block>(input, y / 4, z, inputRowPitch, inputDepthPitch);
- uint8_t *destRow =
- OffsetDataPointer<uint8_t>(output, y, z, outputRowPitch, outputDepthPitch);
-
- for (size_t x = 0; x < width; x += 4)
- {
- const ETC2Block *sourceBlockAlpha = sourceRow + (x / 2);
- sourceBlockAlpha->decodeAsSingleChannel(
- reinterpret_cast<uint8_t *>(decodedAlphaValues), x, y, width, height, 1, 4,
- false);
-
- uint8_t *destPixels = destRow + (x * 4);
- const ETC2Block *sourceBlockRGB = sourceBlockAlpha + 1;
- sourceBlockRGB->decodeAsRGB(destPixels, x, y, width, height, outputRowPitch,
- decodedAlphaValues, false);
- }
- }
- }
-}
-
-} // anonymous namespace
-
-void LoadETC1RGB8ToRGBA8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch)
-{
- LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
- outputRowPitch, outputDepthPitch, false);
-}
-
-void LoadETC1RGB8ToBC1(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch)
-{
- LoadETC2RGB8ToBC1(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
- outputRowPitch, outputDepthPitch, false);
-}
-
-void LoadEACR11ToR8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch)
-{
- LoadR11EACToR8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
- outputRowPitch, outputDepthPitch, false);
-}
-
-void LoadEACR11SToR8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch)
-{
- LoadR11EACToR8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
- outputRowPitch, outputDepthPitch, true);
-}
-
-void LoadEACRG11ToRG8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch)
-{
- LoadRG11EACToRG8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
- outputRowPitch, outputDepthPitch, false);
-}
-
-void LoadEACRG11SToRG8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch)
-{
- LoadRG11EACToRG8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
- outputRowPitch, outputDepthPitch, true);
-}
-
-void LoadETC2RGB8ToRGBA8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch)
-{
- LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
- outputRowPitch, outputDepthPitch, false);
-}
-
-void LoadETC2SRGB8ToRGBA8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch)
-{
- LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
- outputRowPitch, outputDepthPitch, false);
-}
-
-void LoadETC2RGB8A1ToRGBA8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch)
-{
- LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
- outputRowPitch, outputDepthPitch, true);
-}
-
-void LoadETC2SRGB8A1ToRGBA8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch)
-{
- LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
- outputRowPitch, outputDepthPitch, true);
-}
-
-void LoadETC2RGBA8ToRGBA8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch)
-{
- LoadETC2RGBA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
- outputRowPitch, outputDepthPitch, false);
-}
-
-void LoadETC2SRGBA8ToSRGBA8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch)
-{
- LoadETC2RGBA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output,
- outputRowPitch, outputDepthPitch, true);
-}
-
-} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage_etc.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage_etc.h
deleted file mode 100644
index dc64e0461b..0000000000
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage_etc.h
+++ /dev/null
@@ -1,140 +0,0 @@
-//
-// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// loadimage_etc.h: Decodes ETC and EAC encoded textures.
-
-#ifndef LIBANGLE_RENDERER_D3D_LOADIMAGE_ETC_H_
-#define LIBANGLE_RENDERER_D3D_LOADIMAGE_ETC_H_
-
-#include "libANGLE/angletypes.h"
-
-#include <stdint.h>
-
-namespace rx
-{
-
-void LoadETC1RGB8ToRGBA8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch);
-
-void LoadETC1RGB8ToBC1(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch);
-
-void LoadEACR11ToR8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch);
-
-void LoadEACR11SToR8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch);
-
-void LoadEACRG11ToRG8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch);
-
-void LoadEACRG11SToRG8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch);
-
-void LoadETC2RGB8ToRGBA8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch);
-
-void LoadETC2SRGB8ToRGBA8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch);
-
-void LoadETC2RGB8A1ToRGBA8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch);
-
-void LoadETC2SRGB8A1ToRGBA8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch);
-
-void LoadETC2RGBA8ToRGBA8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch);
-
-void LoadETC2SRGBA8ToSRGBA8(size_t width,
- size_t height,
- size_t depth,
- const uint8_t *input,
- size_t inputRowPitch,
- size_t inputDepthPitch,
- uint8_t *output,
- size_t outputRowPitch,
- size_t outputDepthPitch);
-}
-
-#endif // LIBANGLE_RENDERER_D3D_LOADIMAGE_ETC_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/driver_utils.cpp b/src/3rdparty/angle/src/libANGLE/renderer/driver_utils.cpp
new file mode 100644
index 0000000000..d97b8e7c22
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/driver_utils.cpp
@@ -0,0 +1,120 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// driver_utils.h : provides more information about current driver.
+
+#include <algorithm>
+
+#include "libANGLE/renderer/driver_utils.h"
+
+namespace rx
+{
+// Intel
+// Referenced from https://cgit.freedesktop.org/vaapi/intel-driver/tree/src/i965_pciids.h
+namespace
+{
+// gen7
+const uint32_t Haswell[] = {
+ 0x0402, 0x0406, 0x040A, 0x040B, 0x040E, 0x0C02, 0x0C06, 0x0C0A, 0x0C0B, 0x0C0E,
+ 0x0A02, 0x0A06, 0x0A0A, 0x0A0B, 0x0A0E, 0x0D02, 0x0D06, 0x0D0A, 0x0D0B, 0x0D0E, // hsw_gt1
+ 0x0412, 0x0416, 0x041A, 0x041B, 0x041E, 0x0C12, 0x0C16, 0x0C1A, 0x0C1B, 0x0C1E,
+ 0x0A12, 0x0A16, 0x0A1A, 0x0A1B, 0x0A1E, 0x0D12, 0x0D16, 0x0D1A, 0x0D1B, 0x0D1E, // hsw_gt2
+ 0x0422, 0x0426, 0x042A, 0x042B, 0x042E, 0x0C22, 0x0C26, 0x0C2A, 0x0C2B, 0x0C2E,
+ 0x0A22, 0x0A26, 0x0A2A, 0x0A2B, 0x0A2E, 0x0D22, 0x0D26, 0x0D2A, 0x0D2B, 0x0D2E // hsw_gt3
+};
+
+// gen8
+const uint32_t Broadwell[] = {0x1602, 0x1606, 0x160A, 0x160B, 0x160D, 0x160E,
+ 0x1612, 0x1616, 0x161A, 0x161B, 0x161D, 0x161E,
+ 0x1622, 0x1626, 0x162A, 0x162B, 0x162D, 0x162E};
+
+const uint32_t CherryView[] = {0x22B0, 0x22B1, 0x22B2, 0x22B3};
+
+// gen9
+const uint32_t Skylake[] = {0x1902, 0x1906, 0x190A, 0x190B, 0x190E, 0x1912, 0x1913, 0x1915, 0x1916,
+ 0x1917, 0x191A, 0x191B, 0x191D, 0x191E, 0x1921, 0x1923, 0x1926, 0x1927,
+ 0x192A, 0x192B, 0x192D, 0x1932, 0x193A, 0x193B, 0x193D};
+
+const uint32_t Broxton[] = {0x0A84, 0x1A84, 0x1A85, 0x5A84, 0x5A85};
+
+// gen9p5
+const uint32_t Kabylake[] = {0x5916, 0x5913, 0x5906, 0x5926, 0x5921, 0x5915, 0x590E,
+ 0x591E, 0x5912, 0x5917, 0x5902, 0x591B, 0x593B, 0x590B,
+ 0x591A, 0x590A, 0x591D, 0x5908, 0x5923, 0x5927};
+
+} // anonymous namespace
+
+IntelDriverVersion::IntelDriverVersion(uint16_t lastPart) : mVersionPart(lastPart)
+{
+}
+
+bool IntelDriverVersion::operator==(const IntelDriverVersion &version)
+{
+ return mVersionPart == version.mVersionPart;
+}
+
+bool IntelDriverVersion::operator!=(const IntelDriverVersion &version)
+{
+ return !(*this == version);
+}
+
+bool IntelDriverVersion::operator<(const IntelDriverVersion &version)
+{
+ // See http://www.intel.com/content/www/us/en/support/graphics-drivers/000005654.html to
+ // understand the Intel graphics driver version number on Windows.
+ // mVersionPart1 changes with OS version. mVersionPart2 changes with DirectX version.
+ // mVersionPart3 stands for release year. mVersionPart4 is driver specific unique version
+ // number.
+ // For example: Intel driver version '20.19.15.4539'
+ // 20 -> windows 10 driver
+ // 19 -> DirectX 12 first version(12.0) supported
+ // 15 -> Driver released in 2015
+ // 4539 -> Driver specific unique version number
+ // For linux, Intel graphics driver version is the mesa version. The version number has three
+ // parts: major revision, minor revision, release number. So, for linux, we need to compare
+ // three parts.
+ // Currently, it's only used in windows. So, checking the last part is enough. Once it's needed
+ // in other platforms, it's easy to be extended.
+ return mVersionPart < version.mVersionPart;
+}
+
+bool IntelDriverVersion::operator>=(const IntelDriverVersion &version)
+{
+ return !(*this < version);
+}
+
+bool IsHaswell(uint32_t DeviceId)
+{
+ return std::find(std::begin(Haswell), std::end(Haswell), DeviceId) != std::end(Haswell);
+}
+
+bool IsBroadwell(uint32_t DeviceId)
+{
+ return std::find(std::begin(Broadwell), std::end(Broadwell), DeviceId) != std::end(Broadwell);
+}
+
+bool IsCherryView(uint32_t DeviceId)
+{
+ return std::find(std::begin(CherryView), std::end(CherryView), DeviceId) !=
+ std::end(CherryView);
+}
+
+bool IsSkylake(uint32_t DeviceId)
+{
+ return std::find(std::begin(Skylake), std::end(Skylake), DeviceId) != std::end(Skylake);
+}
+
+bool IsBroxton(uint32_t DeviceId)
+{
+ return std::find(std::begin(Broxton), std::end(Broxton), DeviceId) != std::end(Broxton);
+}
+
+bool IsKabylake(uint32_t DeviceId)
+{
+ return std::find(std::begin(Kabylake), std::end(Kabylake), DeviceId) != std::end(Kabylake);
+}
+
+} // namespace rx \ No newline at end of file
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/driver_utils.h b/src/3rdparty/angle/src/libANGLE/renderer/driver_utils.h
new file mode 100644
index 0000000000..62bdc502fc
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/driver_utils.h
@@ -0,0 +1,73 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// driver_utils.h : provides more information about current driver.
+
+#ifndef LIBANGLE_RENDERER_DRIVER_UTILS_H_
+#define LIBANGLE_RENDERER_DRIVER_UTILS_H_
+
+#include "libANGLE/angletypes.h"
+
+namespace rx
+{
+
+enum VendorID : uint32_t
+{
+ VENDOR_ID_UNKNOWN = 0x0,
+ VENDOR_ID_AMD = 0x1002,
+ VENDOR_ID_INTEL = 0x8086,
+ VENDOR_ID_NVIDIA = 0x10DE,
+ // This is Qualcomm PCI Vendor ID.
+ // Android doesn't have a PCI bus, but all we need is a unique id.
+ VENDOR_ID_QUALCOMM = 0x5143,
+};
+
+inline bool IsAMD(uint32_t vendor_id)
+{
+ return vendor_id == VENDOR_ID_AMD;
+}
+
+inline bool IsIntel(uint32_t vendor_id)
+{
+ return vendor_id == VENDOR_ID_INTEL;
+}
+
+inline bool IsNvidia(uint32_t vendor_id)
+{
+ return vendor_id == VENDOR_ID_NVIDIA;
+}
+
+inline bool IsQualcomm(uint32_t vendor_id)
+{
+ return vendor_id == VENDOR_ID_QUALCOMM;
+}
+
+// Intel
+class IntelDriverVersion
+{
+ public:
+ // Currently, We only provide the constructor with one parameter. It mainly used in Intel
+ // version number on windows. If you want to use this class on other platforms, it's easy to
+ // be extended.
+ IntelDriverVersion(uint16_t lastPart);
+ bool operator==(const IntelDriverVersion &);
+ bool operator!=(const IntelDriverVersion &);
+ bool operator<(const IntelDriverVersion &);
+ bool operator>=(const IntelDriverVersion &);
+
+ private:
+ uint16_t mVersionPart;
+};
+
+bool IsHaswell(uint32_t DeviceId);
+bool IsBroadwell(uint32_t DeviceId);
+bool IsCherryView(uint32_t DeviceId);
+bool IsSkylake(uint32_t DeviceId);
+bool IsBroxton(uint32_t DeviceId);
+bool IsKabylake(uint32_t DeviceId);
+
+} // namespace rx
+#endif // LIBANGLE_RENDERER_DRIVER_UTILS_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/load_functions_data.json b/src/3rdparty/angle/src/libANGLE/renderer/load_functions_data.json
new file mode 100644
index 0000000000..198274998c
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/load_functions_data.json
@@ -0,0 +1,602 @@
+{
+ "GL_RG8_SNORM": {
+ "R8G8_SNORM": {
+ "GL_BYTE": "LoadToNative<GLbyte, 2>"
+ }
+ },
+ "GL_SRGB8": {
+ "R8G8B8A8_UNORM_SRGB": {
+ "GL_UNSIGNED_BYTE": "LoadToNative3To4<GLubyte, 0xFF>"
+ }
+ },
+ "GL_RGBA8I": {
+ "R8G8B8A8_SINT": {
+ "GL_BYTE": "LoadToNative<GLbyte, 4>"
+ }
+ },
+ "GL_R8_SNORM": {
+ "R8_SNORM": {
+ "GL_BYTE": "LoadToNative<GLbyte, 1>"
+ }
+ },
+ "GL_RGBA8_SNORM": {
+ "R8G8B8A8_SNORM": {
+ "GL_BYTE": "LoadToNative<GLbyte, 4>"
+ }
+ },
+ "GL_R16I": {
+ "R16_SINT": {
+ "GL_SHORT": "LoadToNative<GLshort, 1>"
+ }
+ },
+ "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC": {
+ "R8G8B8A8_UNORM_SRGB": {
+ "GL_UNSIGNED_BYTE": "LoadETC2SRGBA8ToSRGBA8"
+ }
+ },
+ "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2": {
+ "R8G8B8A8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadETC2RGB8A1ToRGBA8"
+ }
+ },
+ "GL_RGB32UI": {
+ "R32G32B32A32_UINT": {
+ "GL_UNSIGNED_INT": "LoadToNative3To4<GLuint, 0x00000001>"
+ }
+ },
+ "GL_ALPHA32F_EXT": {
+ "NONE": {
+ "GL_FLOAT": "LoadA32FToRGBA32F"
+ }
+ },
+ "GL_R16UI": {
+ "R16_UINT": {
+ "GL_UNSIGNED_SHORT": "LoadToNative<GLushort, 1>"
+ }
+ },
+ "GL_RGB9_E5": {
+ "R9G9B9E5_SHAREDEXP": {
+ "GL_HALF_FLOAT": "LoadRGB16FToRGB9E5",
+ "GL_UNSIGNED_INT_5_9_9_9_REV": "LoadToNative<GLuint, 1>",
+ "GL_FLOAT": "LoadRGB32FToRGB9E5",
+ "GL_HALF_FLOAT_OES": "LoadRGB16FToRGB9E5"
+ }
+ },
+ "GL_COMPRESSED_R11_EAC": {
+ "R8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadEACR11ToR8"
+ }
+ },
+ "GL_RGBA32UI": {
+ "R32G32B32A32_UINT": {
+ "GL_UNSIGNED_INT": "LoadToNative<GLuint, 4>"
+ }
+ },
+ "GL_RG8UI": {
+ "R8G8_UINT": {
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 2>"
+ }
+ },
+ "GL_LUMINANCE32F_EXT": {
+ "NONE": {
+ "GL_FLOAT": "LoadL32FToRGBA32F"
+ }
+ },
+ "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2": {
+ "R8G8B8A8_UNORM_SRGB": {
+ "GL_UNSIGNED_BYTE": "LoadETC2SRGB8A1ToRGBA8"
+ }
+ },
+ "GL_R16F": {
+ "R16_FLOAT": {
+ "GL_HALF_FLOAT": "LoadToNative<GLhalf, 1>",
+ "GL_FLOAT": "Load32FTo16F<1>",
+ "GL_HALF_FLOAT_OES": "LoadToNative<GLhalf, 1>"
+ }
+ },
+ "GL_RGBA8UI": {
+ "R8G8B8A8_UINT": {
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 4>"
+ }
+ },
+ "GL_BGRA4_ANGLEX": {
+ "NONE": {
+ "GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT": "LoadRGBA4ToRGBA8",
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 4>"
+ }
+ },
+ "GL_RGBA16F": {
+ "R16G16B16A16_FLOAT": {
+ "GL_HALF_FLOAT": "LoadToNative<GLhalf, 4>",
+ "GL_FLOAT": "Load32FTo16F<4>",
+ "GL_HALF_FLOAT_OES": "LoadToNative<GLhalf, 4>"
+ }
+ },
+ "GL_LUMINANCE8_EXT": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "LoadL8ToRGBA8"
+ }
+ },
+ "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "LoadCompressedToNative<4, 4, 16>"
+ }
+ },
+ "GL_RGB": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "UnreachableLoadFunction",
+ "GL_UNSIGNED_SHORT_5_6_5": "UnreachableLoadFunction"
+ }
+ },
+ "GL_RGB5_A1": {
+ "R8G8B8A8_UNORM": {
+ "GL_UNSIGNED_INT_2_10_10_10_REV": "LoadRGB10A2ToRGBA8",
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 4>",
+ "GL_UNSIGNED_SHORT_5_5_5_1": "LoadRGB5A1ToRGBA8"
+ },
+ "B5G5R5A1_UNORM": {
+ "GL_UNSIGNED_INT_2_10_10_10_REV": "LoadRGB10A2ToBGR5A1",
+ "GL_UNSIGNED_BYTE": "LoadRGBA8ToBGR5A1",
+ "GL_UNSIGNED_SHORT_5_5_5_1": "LoadRGB5A1ToA1RGB5"
+ }
+ },
+ "GL_RGB16UI": {
+ "R16G16B16A16_UINT": {
+ "GL_UNSIGNED_SHORT": "LoadToNative3To4<GLushort, 0x0001>"
+ }
+ },
+ "GL_BGRA_EXT": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "UnreachableLoadFunction"
+ }
+ },
+ "GL_COMPRESSED_RGB8_ETC2": {
+ "R8G8B8A8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadETC2RGB8ToRGBA8"
+ }
+ },
+ "GL_RGBA32F": {
+ "R32G32B32A32_FLOAT": {
+ "GL_FLOAT": "LoadToNative<GLfloat, 4>"
+ }
+ },
+ "GL_RGBA32I": {
+ "R32G32B32A32_SINT": {
+ "GL_INT": "LoadToNative<GLint, 4>"
+ }
+ },
+ "GL_LUMINANCE8_ALPHA8_EXT": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "LoadLA8ToRGBA8"
+ }
+ },
+ "GL_RG8": {
+ "R8G8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 2>"
+ }
+ },
+ "GL_RGB10_A2": {
+ "R10G10B10A2_UNORM": {
+ "GL_UNSIGNED_INT_2_10_10_10_REV": "LoadToNative<GLuint, 1>"
+ }
+ },
+ "GL_COMPRESSED_SIGNED_RG11_EAC": {
+ "R8G8_SNORM": {
+ "GL_UNSIGNED_BYTE": "LoadEACRG11SToRG8"
+ }
+ },
+ "GL_DEPTH_COMPONENT16": {
+ "D16_UNORM": {
+ "GL_UNSIGNED_INT": "LoadR32ToR16",
+ "GL_UNSIGNED_SHORT": "LoadToNative<GLushort, 1>"
+ }
+ },
+ "GL_RGB32I": {
+ "R32G32B32A32_SINT": {
+ "GL_INT": "LoadToNative3To4<GLint, 0x00000001>"
+ }
+ },
+ "GL_R8": {
+ "R8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 1>"
+ }
+ },
+ "GL_RGB32F": {
+ "R32G32B32A32_FLOAT": {
+ "GL_FLOAT": "LoadToNative3To4<GLfloat, gl::Float32One>"
+ }
+ },
+ "GL_R11F_G11F_B10F": {
+ "R11G11B10_FLOAT": {
+ "GL_UNSIGNED_INT_10F_11F_11F_REV": "LoadToNative<GLuint, 1>",
+ "GL_HALF_FLOAT": "LoadRGB16FToRG11B10F",
+ "GL_FLOAT": "LoadRGB32FToRG11B10F",
+ "GL_HALF_FLOAT_OES": "LoadRGB16FToRG11B10F"
+ }
+ },
+ "GL_RGB8": {
+ "R8G8B8A8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadToNative3To4<GLubyte, 0xFF>"
+ }
+ },
+ "GL_LUMINANCE_ALPHA": {
+ "R16G16B16A16_FLOAT": {
+ "GL_HALF_FLOAT": "LoadLA16FToRGBA16F",
+ "GL_HALF_FLOAT_OES": "LoadLA16FToRGBA16F"
+ },
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "UnreachableLoadFunction"
+ },
+ "R32G32B32A32_FLOAT": {
+ "GL_FLOAT": "LoadLA32FToRGBA32F"
+ }
+ },
+ "GL_RGBA16I": {
+ "R16G16B16A16_SINT": {
+ "GL_SHORT": "LoadToNative<GLshort, 4>"
+ }
+ },
+ "GL_R8I": {
+ "R8_SINT": {
+ "GL_BYTE": "LoadToNative<GLbyte, 1>"
+ }
+ },
+ "GL_RGB8_SNORM": {
+ "R8G8B8A8_SNORM": {
+ "GL_BYTE": "LoadToNative3To4<GLbyte, 0x7F>"
+ }
+ },
+ "GL_RG32F": {
+ "R32G32_FLOAT": {
+ "GL_FLOAT": "LoadToNative<GLfloat, 2>"
+ }
+ },
+ "GL_DEPTH_COMPONENT32F": {
+ "D32_FLOAT": {
+ "GL_FLOAT": "LoadD32FToD32F"
+ }
+ },
+ "GL_RG32I": {
+ "R32G32_SINT": {
+ "GL_INT": "LoadToNative<GLint, 2>"
+ }
+ },
+ "GL_ALPHA8_EXT": {
+ "A8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 1>"
+ },
+ "R8G8B8A8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadA8ToRGBA8"
+ }
+ },
+ "GL_RG32UI": {
+ "R32G32_UINT": {
+ "GL_UNSIGNED_INT": "LoadToNative<GLuint, 2>"
+ }
+ },
+ "GL_RGBA16UI": {
+ "R16G16B16A16_UINT": {
+ "GL_UNSIGNED_SHORT": "LoadToNative<GLushort, 4>"
+ }
+ },
+ "GL_COMPRESSED_RGBA8_ETC2_EAC": {
+ "R8G8B8A8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadETC2RGBA8ToRGBA8"
+ }
+ },
+ "GL_RGB8I": {
+ "R8G8B8A8_SINT": {
+ "GL_BYTE": "LoadToNative3To4<GLbyte, 0x01>"
+ }
+ },
+ "GL_COMPRESSED_SRGB8_ETC2": {
+ "R8G8B8A8_UNORM_SRGB": {
+ "GL_UNSIGNED_BYTE": "LoadETC2SRGB8ToRGBA8"
+ }
+ },
+ "GL_DEPTH32F_STENCIL8": {
+ "D32_FLOAT_S8X24_UINT": {
+ "GL_FLOAT_32_UNSIGNED_INT_24_8_REV": "LoadD32FS8X24ToD32FS8X24"
+ }
+ },
+ "GL_RG8I": {
+ "R8G8_SINT": {
+ "GL_BYTE": "LoadToNative<GLbyte, 2>"
+ }
+ },
+ "GL_R32UI": {
+ "R32_UINT": {
+ "GL_UNSIGNED_INT": "LoadToNative<GLuint, 1>"
+ }
+ },
+ "GL_BGR5_A1_ANGLEX": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 4>",
+ "GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT": "LoadRGB5A1ToRGBA8"
+ }
+ },
+ "GL_BGR565_ANGLEX": {
+ "B5G6R5_UNORM": {
+ "GL_UNSIGNED_SHORT_5_6_5": "LoadRGB565ToBGR565",
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLushort, 1>"
+ }
+ },
+ "GL_COMPRESSED_RG11_EAC": {
+ "R8G8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadEACRG11ToRG8"
+ }
+ },
+ "GL_SRGB8_ALPHA8": {
+ "R8G8B8A8_UNORM_SRGB": {
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 4>"
+ }
+ },
+ "GL_LUMINANCE_ALPHA16F_EXT": {
+ "NONE": {
+ "GL_HALF_FLOAT": "LoadLA16FToRGBA16F",
+ "GL_HALF_FLOAT_OES": "LoadLA16FToRGBA16F"
+ }
+ },
+ "GL_RGBA": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "UnreachableLoadFunction",
+ "GL_UNSIGNED_SHORT_4_4_4_4": "UnreachableLoadFunction",
+ "GL_UNSIGNED_SHORT_5_5_5_1": "UnreachableLoadFunction"
+ }
+ },
+ "GL_DEPTH24_STENCIL8": {
+ "D24_UNORM_S8_UINT": {
+ "GL_UNSIGNED_INT_24_8": "LoadR32ToR24G8"
+ }
+ },
+ "GL_RGB16I": {
+ "R16G16B16A16_SINT": {
+ "GL_SHORT": "LoadToNative3To4<GLshort, 0x0001>"
+ }
+ },
+ "GL_R8UI": {
+ "R8_UINT": {
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 1>"
+ }
+ },
+ "GL_ALPHA": {
+ "R16G16B16A16_FLOAT": {
+ "GL_HALF_FLOAT": "LoadA16FToRGBA16F",
+ "GL_HALF_FLOAT_OES": "LoadA16FToRGBA16F"
+ },
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "UnreachableLoadFunction"
+ },
+ "R32G32B32A32_FLOAT": {
+ "GL_FLOAT": "LoadA32FToRGBA32F"
+ }
+ },
+ "GL_RGB16F": {
+ "R16G16B16A16_FLOAT": {
+ "GL_HALF_FLOAT": "LoadToNative3To4<GLhalf, gl::Float16One>",
+ "GL_FLOAT": "LoadRGB32FToRGBA16F",
+ "GL_HALF_FLOAT_OES": "LoadToNative3To4<GLhalf, gl::Float16One>"
+ }
+ },
+ "GL_COMPRESSED_SIGNED_R11_EAC": {
+ "R8_SNORM": {
+ "GL_UNSIGNED_BYTE": "LoadEACR11SToR8"
+ }
+ },
+ "GL_COMPRESSED_RGB_S3TC_DXT1_EXT": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "LoadCompressedToNative<4, 4, 8>"
+ }
+ },
+ "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "LoadCompressedToNative<4, 4, 8>"
+ }
+ },
+ "GL_STENCIL_INDEX8": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "UnimplementedLoadFunction"
+ }
+ },
+ "GL_LUMINANCE_ALPHA32F_EXT": {
+ "NONE": {
+ "GL_FLOAT": "LoadLA32FToRGBA32F"
+ }
+ },
+ "GL_RGB8UI": {
+ "R8G8B8A8_UINT": {
+ "GL_UNSIGNED_BYTE": "LoadToNative3To4<GLubyte, 0x01>"
+ }
+ },
+ "GL_DEPTH_COMPONENT24": {
+ "D24_UNORM_S8_UINT": {
+ "GL_UNSIGNED_INT": "LoadR32ToR24G8"
+ }
+ },
+ "GL_R32I": {
+ "R32_SINT": {
+ "GL_INT": "LoadToNative<GLint, 1>"
+ }
+ },
+ "GL_DEPTH_COMPONENT32_OES": {
+ "NONE": {
+ "GL_UNSIGNED_INT": "LoadR32ToR24G8"
+ }
+ },
+ "GL_R32F": {
+ "R32_FLOAT": {
+ "GL_FLOAT": "LoadToNative<GLfloat, 1>"
+ }
+ },
+ "GL_RG16F": {
+ "R16G16_FLOAT": {
+ "GL_HALF_FLOAT": "LoadToNative<GLhalf, 2>",
+ "GL_FLOAT": "Load32FTo16F<2>",
+ "GL_HALF_FLOAT_OES": "LoadToNative<GLhalf, 2>"
+ }
+ },
+ "GL_RGB565": {
+ "R8G8B8A8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadToNative3To4<GLubyte, 0xFF>",
+ "GL_UNSIGNED_SHORT_5_6_5": "LoadR5G6B5ToRGBA8"
+ },
+ "B5G6R5_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadRGB8ToBGR565",
+ "GL_UNSIGNED_SHORT_5_6_5": "LoadToNative<GLushort, 1>"
+ }
+ },
+ "GL_LUMINANCE16F_EXT": {
+ "NONE": {
+ "GL_HALF_FLOAT": "LoadL16FToRGBA16F",
+ "GL_HALF_FLOAT_OES": "LoadL16FToRGBA16F"
+ }
+ },
+ "GL_RG16UI": {
+ "R16G16_UINT": {
+ "GL_UNSIGNED_SHORT": "LoadToNative<GLushort, 2>"
+ }
+ },
+ "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "LoadCompressedToNative<4, 4, 16>"
+ }
+ },
+ "GL_RG16I": {
+ "R16G16_SINT": {
+ "GL_SHORT": "LoadToNative<GLshort, 2>"
+ }
+ },
+ "GL_BGRA8_EXT": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 4>"
+ }
+ },
+ "GL_ALPHA16F_EXT": {
+ "NONE": {
+ "GL_HALF_FLOAT": "LoadA16FToRGBA16F",
+ "GL_HALF_FLOAT_OES": "LoadA16FToRGBA16F"
+ }
+ },
+ "GL_RGBA4": {
+ "R8G8B8A8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 4>",
+ "GL_UNSIGNED_SHORT_4_4_4_4": "LoadRGBA4ToRGBA8"
+ },
+ "B4G4R4A4_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadRGBA8ToBGRA4",
+ "GL_UNSIGNED_SHORT_4_4_4_4": "LoadRGBA4ToARGB4"
+ }
+ },
+ "GL_RGBA8": {
+ "R8G8B8A8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadToNative<GLubyte, 4>"
+ }
+ },
+ "GL_LUMINANCE": {
+ "R16G16B16A16_FLOAT": {
+ "GL_HALF_FLOAT": "LoadL16FToRGBA16F",
+ "GL_HALF_FLOAT_OES": "LoadL16FToRGBA16F"
+ },
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "UnreachableLoadFunction"
+ },
+ "R32G32B32A32_FLOAT": {
+ "GL_FLOAT": "LoadL32FToRGBA32F"
+ }
+ },
+ "GL_RGB10_A2UI": {
+ "R10G10B10A2_UINT": {
+ "GL_UNSIGNED_INT_2_10_10_10_REV": "LoadToNative<GLuint, 1>"
+ }
+ },
+ "GL_ETC1_RGB8_OES": {
+ "R8G8B8A8_UNORM": {
+ "GL_UNSIGNED_BYTE": "LoadETC1RGB8ToRGBA8"
+ }
+ },
+ "GL_ETC1_RGB8_LOSSY_DECODE_ANGLE": {
+ "BC1_RGB_UNORM_BLOCK": {
+ "GL_UNSIGNED_BYTE": "LoadETC1RGB8ToBC1"
+ }
+ },
+ "GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE": {
+ "BC1_RGB_UNORM_BLOCK": {
+ "GL_UNSIGNED_BYTE": "LoadETC2RGB8ToBC1"
+ }
+ },
+ "GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE": {
+ "BC1_RGB_UNORM_SRGB_BLOCK": {
+ "GL_UNSIGNED_BYTE": "LoadETC2SRGB8ToBC1"
+ }
+ },
+ "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE": {
+ "BC1_RGBA_UNORM_BLOCK": {
+ "GL_UNSIGNED_BYTE": "LoadETC2RGB8A1ToBC1"
+ }
+ },
+ "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE": {
+ "BC1_RGBA_UNORM_SRGB_BLOCK": {
+ "GL_UNSIGNED_BYTE": "LoadETC2SRGB8A1ToBC1"
+ }
+ },
+ "GL_R16_EXT": {
+ "R16_UNORM": {
+ "GL_UNSIGNED_SHORT": "LoadToNative<GLushort, 1>"
+ }
+ },
+ "GL_RG16_EXT": {
+ "R16G16_UNORM": {
+ "GL_UNSIGNED_SHORT": "LoadToNative<GLushort, 2>"
+ }
+ },
+ "GL_RGB16_EXT": {
+ "R16G16B16A16_UNORM": {
+ "GL_UNSIGNED_SHORT": "LoadToNative3To4<GLushort, 0xFFFF>"
+ }
+ },
+ "GL_RGBA16_EXT": {
+ "R16G16B16A16_UNORM": {
+ "GL_UNSIGNED_SHORT": "LoadToNative<GLushort, 4>"
+ }
+ },
+ "GL_R16_SNORM_EXT": {
+ "R16_SNORM": {
+ "GL_SHORT": "LoadToNative<GLushort, 1>"
+ }
+ },
+ "GL_RG16_SNORM_EXT": {
+ "R16G16_SNORM": {
+ "GL_SHORT": "LoadToNative<GLushort, 2>"
+ }
+ },
+ "GL_RGB16_SNORM_EXT": {
+ "R16G16B16A16_SNORM": {
+ "GL_SHORT": "LoadToNative3To4<GLushort, 0x7FFF>"
+ }
+ },
+ "GL_RGBA16_SNORM_EXT": {
+ "R16G16B16A16_SNORM": {
+ "GL_SHORT": "LoadToNative<GLushort, 4>"
+ }
+ },
+ "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "LoadCompressedToNative<4, 4, 16>"
+ }
+ },
+ "GL_COMPRESSED_SRGB_S3TC_DXT1_EXT": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "LoadCompressedToNative<4, 4, 8>"
+ }
+ },
+ "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "LoadCompressedToNative<4, 4, 8>"
+ }
+ },
+ "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT": {
+ "NONE": {
+ "GL_UNSIGNED_BYTE": "LoadCompressedToNative<4, 4, 16>"
+ }
+ }
+}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/load_functions_table.h b/src/3rdparty/angle/src/libANGLE/renderer/load_functions_table.h
new file mode 100644
index 0000000000..f3da31c100
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/load_functions_table.h
@@ -0,0 +1,22 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// load_functions_table:
+// Contains load functions table depending on internal format and ANGLE format.
+//
+
+#ifndef LIBANGLE_RENDERER_LOADFUNCTIONSTABLE_H_
+#define LIBANGLE_RENDERER_LOADFUNCTIONSTABLE_H_
+
+#include "libANGLE/renderer/Format.h"
+
+namespace angle
+{
+
+rx::LoadFunctionMap GetLoadFunctionsMap(GLenum internalFormat, Format::ID angleFormat);
+
+} // namespace angle
+
+#endif // LIBANGLE_RENDERER_LOADFUNCTIONSTABLE_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/load_functions_table_autogen.cpp b/src/3rdparty/angle/src/libANGLE/renderer/load_functions_table_autogen.cpp
new file mode 100644
index 0000000000..ed9fe2864c
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/load_functions_table_autogen.cpp
@@ -0,0 +1,2459 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_load_functions_table.py using data from load_functions_data.json
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// load_functions_table:
+// Contains the GetLoadFunctionsMap for texture_format_util.h
+//
+
+#include "libANGLE/renderer/load_functions_table.h"
+
+#include "image_util/copyimage.h"
+#include "image_util/generatemip.h"
+#include "image_util/loadimage.h"
+
+using namespace rx;
+
+namespace angle
+{
+
+namespace
+{
+
+// ES3 image loading functions vary based on:
+// - the GL internal format (supplied to glTex*Image*D)
+// - the GL data type given (supplied to glTex*Image*D)
+// - the target DXGI_FORMAT that the image will be loaded into (which is chosen based on the D3D
+// device's capabilities)
+// This map type determines which loading function to use, based on these three parameters.
+// Source formats and types are taken from Tables 3.2 and 3.3 of the ES 3 spec.
+void UnimplementedLoadFunction(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ UNIMPLEMENTED();
+}
+
+void UnreachableLoadFunction(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ UNREACHABLE();
+}
+
+LoadImageFunctionInfo ALPHA_to_R16G16B16A16_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadA16FToRGBA16F, true);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadA16FToRGBA16F, true);
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo ALPHA_to_R32G32B32A32_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadA32FToRGBA32F, true);
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo ALPHA_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo ALPHA16F_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadA16FToRGBA16F, true);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadA16FToRGBA16F, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo ALPHA32F_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadA32FToRGBA32F, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo ALPHA8_EXT_to_A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo ALPHA8_EXT_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadA8ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo BGR565_ANGLEX_to_B5G6R5_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 1>, false);
+ case GL_UNSIGNED_SHORT_5_6_5:
+ return LoadImageFunctionInfo(LoadRGB565ToBGR565, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo BGR5_A1_ANGLEX_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+ return LoadImageFunctionInfo(LoadRGB5A1ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo BGRA4_ANGLEX_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+ return LoadImageFunctionInfo(LoadRGBA4ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo BGRA8_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo BGRA_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_R11_EAC_to_R8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadEACR11ToR8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RG11_EAC_to_R8G8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadEACRG11ToRG8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGB8_ETC2_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC2RGB8ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGB_UNORM_BLOCK(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC2RGB8ToBC1, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC2RGB8A1ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo
+COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGBA_UNORM_BLOCK(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC2RGB8A1ToBC1, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA8_ETC2_EAC_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC2RGBA8ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_S3TC_DXT1_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_S3TC_DXT3_ANGLE_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_S3TC_DXT5_ANGLE_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGB_S3TC_DXT1_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SIGNED_R11_EAC_to_R8_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadEACR11SToR8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SIGNED_RG11_EAC_to_R8G8_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadEACRG11SToRG8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ETC2_EAC_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC2SRGBA8ToSRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ETC2_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC2SRGB8ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGB_UNORM_SRGB_BLOCK(
+ GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC2SRGB8ToBC1, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC2SRGB8A1ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo
+COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGBA_UNORM_SRGB_BLOCK(
+ GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC2SRGB8A1ToBC1, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB_S3TC_DXT1_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo DEPTH24_STENCIL8_to_D24_UNORM_S8_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT_24_8:
+ return LoadImageFunctionInfo(LoadR32ToR24G8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo DEPTH32F_STENCIL8_to_D32_FLOAT_S8X24_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+ return LoadImageFunctionInfo(LoadD32FS8X24ToD32FS8X24, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo DEPTH_COMPONENT16_to_D16_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT:
+ return LoadImageFunctionInfo(LoadR32ToR16, true);
+ case GL_UNSIGNED_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo DEPTH_COMPONENT24_to_D24_UNORM_S8_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT:
+ return LoadImageFunctionInfo(LoadR32ToR24G8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo DEPTH_COMPONENT32F_to_D32_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadD32FToD32F, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo DEPTH_COMPONENT32_OES_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT:
+ return LoadImageFunctionInfo(LoadR32ToR24G8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo ETC1_RGB8_LOSSY_DECODE_ANGLE_to_BC1_RGB_UNORM_BLOCK(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC1RGB8ToBC1, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo ETC1_RGB8_OES_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC1RGB8ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE_to_R16G16B16A16_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadL16FToRGBA16F, true);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadL16FToRGBA16F, true);
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE_to_R32G32B32A32_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadL32FToRGBA32F, true);
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE16F_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadL16FToRGBA16F, true);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadL16FToRGBA16F, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE32F_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadL32FToRGBA32F, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE8_ALPHA8_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadLA8ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE8_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadL8ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE_ALPHA_to_R16G16B16A16_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadLA16FToRGBA16F, true);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadLA16FToRGBA16F, true);
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE_ALPHA_to_R32G32B32A32_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadLA32FToRGBA32F, true);
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE_ALPHA_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE_ALPHA16F_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadLA16FToRGBA16F, true);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadLA16FToRGBA16F, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE_ALPHA32F_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadLA32FToRGBA32F, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R11F_G11F_B10F_to_R11G11B10_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadRGB32FToRG11B10F, true);
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadRGB16FToRG11B10F, true);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadRGB16FToRG11B10F, true);
+ case GL_UNSIGNED_INT_10F_11F_11F_REV:
+ return LoadImageFunctionInfo(LoadToNative<GLuint, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R16F_to_R16_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(Load32FTo16F<1>, true);
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadToNative<GLhalf, 1>, false);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadToNative<GLhalf, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R16I_to_R16_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLshort, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R16UI_to_R16_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R16_EXT_to_R16_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R16_SNORM_EXT_to_R16_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R32F_to_R32_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadToNative<GLfloat, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R32I_to_R32_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_INT:
+ return LoadImageFunctionInfo(LoadToNative<GLint, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R32UI_to_R32_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT:
+ return LoadImageFunctionInfo(LoadToNative<GLuint, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R8_to_R8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R8I_to_R8_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLbyte, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R8UI_to_R8_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R8_SNORM_to_R8_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLbyte, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG16F_to_R16G16_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(Load32FTo16F<2>, true);
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadToNative<GLhalf, 2>, false);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadToNative<GLhalf, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG16I_to_R16G16_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLshort, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG16UI_to_R16G16_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG16_EXT_to_R16G16_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG16_SNORM_EXT_to_R16G16_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG32F_to_R32G32_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadToNative<GLfloat, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG32I_to_R32G32_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_INT:
+ return LoadImageFunctionInfo(LoadToNative<GLint, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG32UI_to_R32G32_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT:
+ return LoadImageFunctionInfo(LoadToNative<GLuint, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG8_to_R8G8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG8I_to_R8G8_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLbyte, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG8UI_to_R8G8_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG8_SNORM_to_R8G8_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLbyte, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ case GL_UNSIGNED_SHORT_5_6_5:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB10_A2_to_R10G10B10A2_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return LoadImageFunctionInfo(LoadToNative<GLuint, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB10_A2UI_to_R10G10B10A2_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return LoadImageFunctionInfo(LoadToNative<GLuint, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB16F_to_R16G16B16A16_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadRGB32FToRGBA16F, true);
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLhalf, gl::Float16One>, true);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLhalf, gl::Float16One>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB16I_to_R16G16B16A16_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_SHORT:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLshort, 0x0001>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB16UI_to_R16G16B16A16_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLushort, 0x0001>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB16_EXT_to_R16G16B16A16_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLushort, 0xFFFF>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB16_SNORM_EXT_to_R16G16B16A16_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_SHORT:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLushort, 0x7FFF>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB32F_to_R32G32B32A32_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLfloat, gl::Float32One>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB32I_to_R32G32B32A32_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_INT:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLint, 0x00000001>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB32UI_to_R32G32B32A32_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLuint, 0x00000001>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB565_to_B5G6R5_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadRGB8ToBGR565, true);
+ case GL_UNSIGNED_SHORT_5_6_5:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB565_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLubyte, 0xFF>, true);
+ case GL_UNSIGNED_SHORT_5_6_5:
+ return LoadImageFunctionInfo(LoadR5G6B5ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB5_A1_to_B5G5R5A1_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadRGBA8ToBGR5A1, true);
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return LoadImageFunctionInfo(LoadRGB10A2ToBGR5A1, true);
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ return LoadImageFunctionInfo(LoadRGB5A1ToA1RGB5, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB5_A1_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return LoadImageFunctionInfo(LoadRGB10A2ToRGBA8, true);
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ return LoadImageFunctionInfo(LoadRGB5A1ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB8_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLubyte, 0xFF>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB8I_to_R8G8B8A8_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BYTE:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLbyte, 0x01>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB8UI_to_R8G8B8A8_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLubyte, 0x01>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB8_SNORM_to_R8G8B8A8_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BYTE:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLbyte, 0x7F>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB9_E5_to_R9G9B9E5_SHAREDEXP(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadRGB32FToRGB9E5, true);
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadRGB16FToRGB9E5, true);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadRGB16FToRGB9E5, true);
+ case GL_UNSIGNED_INT_5_9_9_9_REV:
+ return LoadImageFunctionInfo(LoadToNative<GLuint, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA16F_to_R16G16B16A16_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(Load32FTo16F<4>, true);
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadToNative<GLhalf, 4>, false);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadToNative<GLhalf, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA16I_to_R16G16B16A16_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLshort, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA16UI_to_R16G16B16A16_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA16_EXT_to_R16G16B16A16_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA16_SNORM_EXT_to_R16G16B16A16_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA32F_to_R32G32B32A32_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadToNative<GLfloat, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA32I_to_R32G32B32A32_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_INT:
+ return LoadImageFunctionInfo(LoadToNative<GLint, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA32UI_to_R32G32B32A32_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT:
+ return LoadImageFunctionInfo(LoadToNative<GLuint, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA4_to_B4G4R4A4_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadRGBA8ToBGRA4, true);
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ return LoadImageFunctionInfo(LoadRGBA4ToARGB4, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA4_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ return LoadImageFunctionInfo(LoadRGBA4ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA8_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA8I_to_R8G8B8A8_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLbyte, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA8UI_to_R8G8B8A8_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA8_SNORM_to_R8G8B8A8_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLbyte, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo SRGB8_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLubyte, 0xFF>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo SRGB8_ALPHA8_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo STENCIL_INDEX8_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnimplementedLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+} // namespace
+
+LoadFunctionMap GetLoadFunctionsMap(GLenum internalFormat, Format::ID angleFormat)
+{
+ // clang-format off
+ switch (internalFormat)
+ {
+ case GL_ALPHA:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_FLOAT:
+ return ALPHA_to_R16G16B16A16_FLOAT;
+ case Format::ID::R32G32B32A32_FLOAT:
+ return ALPHA_to_R32G32B32A32_FLOAT;
+ default:
+ return ALPHA_to_default;
+ }
+ }
+ case GL_ALPHA16F_EXT:
+ return ALPHA16F_EXT_to_default;
+ case GL_ALPHA32F_EXT:
+ return ALPHA32F_EXT_to_default;
+ case GL_ALPHA8_EXT:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::A8_UNORM:
+ return ALPHA8_EXT_to_A8_UNORM;
+ case Format::ID::R8G8B8A8_UNORM:
+ return ALPHA8_EXT_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_BGR565_ANGLEX:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::B5G6R5_UNORM:
+ return BGR565_ANGLEX_to_B5G6R5_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_BGR5_A1_ANGLEX:
+ return BGR5_A1_ANGLEX_to_default;
+ case GL_BGRA4_ANGLEX:
+ return BGRA4_ANGLEX_to_default;
+ case GL_BGRA8_EXT:
+ return BGRA8_EXT_to_default;
+ case GL_BGRA_EXT:
+ return BGRA_EXT_to_default;
+ case GL_COMPRESSED_R11_EAC:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8_UNORM:
+ return COMPRESSED_R11_EAC_to_R8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_RG11_EAC:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8_UNORM:
+ return COMPRESSED_RG11_EAC_to_R8G8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_RGB8_ETC2:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UNORM:
+ return COMPRESSED_RGB8_ETC2_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::BC1_RGB_UNORM_BLOCK:
+ return COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGB_UNORM_BLOCK;
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UNORM:
+ return COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::BC1_RGBA_UNORM_BLOCK:
+ return COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGBA_UNORM_BLOCK;
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_RGBA8_ETC2_EAC:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UNORM:
+ return COMPRESSED_RGBA8_ETC2_EAC_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ return COMPRESSED_RGBA_S3TC_DXT1_EXT_to_default;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ return COMPRESSED_RGBA_S3TC_DXT3_ANGLE_to_default;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ return COMPRESSED_RGBA_S3TC_DXT5_ANGLE_to_default;
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ return COMPRESSED_RGB_S3TC_DXT1_EXT_to_default;
+ case GL_COMPRESSED_SIGNED_R11_EAC:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8_SNORM:
+ return COMPRESSED_SIGNED_R11_EAC_to_R8_SNORM;
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_SIGNED_RG11_EAC:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8_SNORM:
+ return COMPRESSED_SIGNED_RG11_EAC_to_R8G8_SNORM;
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UNORM_SRGB:
+ return COMPRESSED_SRGB8_ALPHA8_ETC2_EAC_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_ETC2:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UNORM_SRGB:
+ return COMPRESSED_SRGB8_ETC2_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::BC1_RGB_UNORM_SRGB_BLOCK:
+ return COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGB_UNORM_SRGB_BLOCK;
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UNORM_SRGB:
+ return COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::BC1_RGBA_UNORM_SRGB_BLOCK:
+ return COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGBA_UNORM_SRGB_BLOCK;
+ default:
+ break;
+ }
+ }
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ return COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT_to_default;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ return COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT_to_default;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ return COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT_to_default;
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ return COMPRESSED_SRGB_S3TC_DXT1_EXT_to_default;
+ case GL_DEPTH24_STENCIL8:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::D24_UNORM_S8_UINT:
+ return DEPTH24_STENCIL8_to_D24_UNORM_S8_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_DEPTH32F_STENCIL8:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::D32_FLOAT_S8X24_UINT:
+ return DEPTH32F_STENCIL8_to_D32_FLOAT_S8X24_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_DEPTH_COMPONENT16:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::D16_UNORM:
+ return DEPTH_COMPONENT16_to_D16_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_DEPTH_COMPONENT24:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::D24_UNORM_S8_UINT:
+ return DEPTH_COMPONENT24_to_D24_UNORM_S8_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_DEPTH_COMPONENT32F:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::D32_FLOAT:
+ return DEPTH_COMPONENT32F_to_D32_FLOAT;
+ default:
+ break;
+ }
+ }
+ case GL_DEPTH_COMPONENT32_OES:
+ return DEPTH_COMPONENT32_OES_to_default;
+ case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::BC1_RGB_UNORM_BLOCK:
+ return ETC1_RGB8_LOSSY_DECODE_ANGLE_to_BC1_RGB_UNORM_BLOCK;
+ default:
+ break;
+ }
+ }
+ case GL_ETC1_RGB8_OES:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UNORM:
+ return ETC1_RGB8_OES_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_LUMINANCE:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_FLOAT:
+ return LUMINANCE_to_R16G16B16A16_FLOAT;
+ case Format::ID::R32G32B32A32_FLOAT:
+ return LUMINANCE_to_R32G32B32A32_FLOAT;
+ default:
+ return LUMINANCE_to_default;
+ }
+ }
+ case GL_LUMINANCE16F_EXT:
+ return LUMINANCE16F_EXT_to_default;
+ case GL_LUMINANCE32F_EXT:
+ return LUMINANCE32F_EXT_to_default;
+ case GL_LUMINANCE8_ALPHA8_EXT:
+ return LUMINANCE8_ALPHA8_EXT_to_default;
+ case GL_LUMINANCE8_EXT:
+ return LUMINANCE8_EXT_to_default;
+ case GL_LUMINANCE_ALPHA:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_FLOAT:
+ return LUMINANCE_ALPHA_to_R16G16B16A16_FLOAT;
+ case Format::ID::R32G32B32A32_FLOAT:
+ return LUMINANCE_ALPHA_to_R32G32B32A32_FLOAT;
+ default:
+ return LUMINANCE_ALPHA_to_default;
+ }
+ }
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ return LUMINANCE_ALPHA16F_EXT_to_default;
+ case GL_LUMINANCE_ALPHA32F_EXT:
+ return LUMINANCE_ALPHA32F_EXT_to_default;
+ case GL_R11F_G11F_B10F:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R11G11B10_FLOAT:
+ return R11F_G11F_B10F_to_R11G11B10_FLOAT;
+ default:
+ break;
+ }
+ }
+ case GL_R16F:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16_FLOAT:
+ return R16F_to_R16_FLOAT;
+ default:
+ break;
+ }
+ }
+ case GL_R16I:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16_SINT:
+ return R16I_to_R16_SINT;
+ default:
+ break;
+ }
+ }
+ case GL_R16UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16_UINT:
+ return R16UI_to_R16_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_R16_EXT:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16_UNORM:
+ return R16_EXT_to_R16_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_R16_SNORM_EXT:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16_SNORM:
+ return R16_SNORM_EXT_to_R16_SNORM;
+ default:
+ break;
+ }
+ }
+ case GL_R32F:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R32_FLOAT:
+ return R32F_to_R32_FLOAT;
+ default:
+ break;
+ }
+ }
+ case GL_R32I:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R32_SINT:
+ return R32I_to_R32_SINT;
+ default:
+ break;
+ }
+ }
+ case GL_R32UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R32_UINT:
+ return R32UI_to_R32_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_R8:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8_UNORM:
+ return R8_to_R8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_R8I:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8_SINT:
+ return R8I_to_R8_SINT;
+ default:
+ break;
+ }
+ }
+ case GL_R8UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8_UINT:
+ return R8UI_to_R8_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_R8_SNORM:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8_SNORM:
+ return R8_SNORM_to_R8_SNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RG16F:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16_FLOAT:
+ return RG16F_to_R16G16_FLOAT;
+ default:
+ break;
+ }
+ }
+ case GL_RG16I:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16_SINT:
+ return RG16I_to_R16G16_SINT;
+ default:
+ break;
+ }
+ }
+ case GL_RG16UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16_UINT:
+ return RG16UI_to_R16G16_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_RG16_EXT:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16_UNORM:
+ return RG16_EXT_to_R16G16_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RG16_SNORM_EXT:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16_SNORM:
+ return RG16_SNORM_EXT_to_R16G16_SNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RG32F:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R32G32_FLOAT:
+ return RG32F_to_R32G32_FLOAT;
+ default:
+ break;
+ }
+ }
+ case GL_RG32I:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R32G32_SINT:
+ return RG32I_to_R32G32_SINT;
+ default:
+ break;
+ }
+ }
+ case GL_RG32UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R32G32_UINT:
+ return RG32UI_to_R32G32_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_RG8:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8_UNORM:
+ return RG8_to_R8G8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RG8I:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8_SINT:
+ return RG8I_to_R8G8_SINT;
+ default:
+ break;
+ }
+ }
+ case GL_RG8UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8_UINT:
+ return RG8UI_to_R8G8_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_RG8_SNORM:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8_SNORM:
+ return RG8_SNORM_to_R8G8_SNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RGB:
+ return RGB_to_default;
+ case GL_RGB10_A2:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R10G10B10A2_UNORM:
+ return RGB10_A2_to_R10G10B10A2_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RGB10_A2UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R10G10B10A2_UINT:
+ return RGB10_A2UI_to_R10G10B10A2_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGB16F:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_FLOAT:
+ return RGB16F_to_R16G16B16A16_FLOAT;
+ default:
+ break;
+ }
+ }
+ case GL_RGB16I:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_SINT:
+ return RGB16I_to_R16G16B16A16_SINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGB16UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_UINT:
+ return RGB16UI_to_R16G16B16A16_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGB16_EXT:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_UNORM:
+ return RGB16_EXT_to_R16G16B16A16_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RGB16_SNORM_EXT:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_SNORM:
+ return RGB16_SNORM_EXT_to_R16G16B16A16_SNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RGB32F:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R32G32B32A32_FLOAT:
+ return RGB32F_to_R32G32B32A32_FLOAT;
+ default:
+ break;
+ }
+ }
+ case GL_RGB32I:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R32G32B32A32_SINT:
+ return RGB32I_to_R32G32B32A32_SINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGB32UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R32G32B32A32_UINT:
+ return RGB32UI_to_R32G32B32A32_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGB565:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::B5G6R5_UNORM:
+ return RGB565_to_B5G6R5_UNORM;
+ case Format::ID::R8G8B8A8_UNORM:
+ return RGB565_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RGB5_A1:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::B5G5R5A1_UNORM:
+ return RGB5_A1_to_B5G5R5A1_UNORM;
+ case Format::ID::R8G8B8A8_UNORM:
+ return RGB5_A1_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RGB8:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UNORM:
+ return RGB8_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RGB8I:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_SINT:
+ return RGB8I_to_R8G8B8A8_SINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGB8UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UINT:
+ return RGB8UI_to_R8G8B8A8_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGB8_SNORM:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_SNORM:
+ return RGB8_SNORM_to_R8G8B8A8_SNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RGB9_E5:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R9G9B9E5_SHAREDEXP:
+ return RGB9_E5_to_R9G9B9E5_SHAREDEXP;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA:
+ return RGBA_to_default;
+ case GL_RGBA16F:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_FLOAT:
+ return RGBA16F_to_R16G16B16A16_FLOAT;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA16I:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_SINT:
+ return RGBA16I_to_R16G16B16A16_SINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA16UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_UINT:
+ return RGBA16UI_to_R16G16B16A16_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA16_EXT:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_UNORM:
+ return RGBA16_EXT_to_R16G16B16A16_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA16_SNORM_EXT:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R16G16B16A16_SNORM:
+ return RGBA16_SNORM_EXT_to_R16G16B16A16_SNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA32F:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R32G32B32A32_FLOAT:
+ return RGBA32F_to_R32G32B32A32_FLOAT;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA32I:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R32G32B32A32_SINT:
+ return RGBA32I_to_R32G32B32A32_SINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA32UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R32G32B32A32_UINT:
+ return RGBA32UI_to_R32G32B32A32_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA4:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::B4G4R4A4_UNORM:
+ return RGBA4_to_B4G4R4A4_UNORM;
+ case Format::ID::R8G8B8A8_UNORM:
+ return RGBA4_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA8:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UNORM:
+ return RGBA8_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA8I:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_SINT:
+ return RGBA8I_to_R8G8B8A8_SINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA8UI:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UINT:
+ return RGBA8UI_to_R8G8B8A8_UINT;
+ default:
+ break;
+ }
+ }
+ case GL_RGBA8_SNORM:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_SNORM:
+ return RGBA8_SNORM_to_R8G8B8A8_SNORM;
+ default:
+ break;
+ }
+ }
+ case GL_SRGB8:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UNORM_SRGB:
+ return SRGB8_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ break;
+ }
+ }
+ case GL_SRGB8_ALPHA8:
+ {
+ switch (angleFormat)
+ {
+ case Format::ID::R8G8B8A8_UNORM_SRGB:
+ return SRGB8_ALPHA8_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ break;
+ }
+ }
+ case GL_STENCIL_INDEX8:
+ return STENCIL_INDEX8_to_default;
+
+ default:
+ {
+ static LoadFunctionMap emptyLoadFunctionsMap;
+ return emptyLoadFunctionsMap;
+ }
+ }
+ // clang-format on
+
+} // GetLoadFunctionsMap
+
+} // namespace angle
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/renderer_utils.cpp b/src/3rdparty/angle/src/libANGLE/renderer/renderer_utils.cpp
new file mode 100644
index 0000000000..55471c1d20
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/renderer_utils.cpp
@@ -0,0 +1,549 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// renderer_utils:
+// Helper methods pertaining to most or all back-ends.
+//
+
+#include "libANGLE/renderer/renderer_utils.h"
+
+#include "image_util/copyimage.h"
+#include "image_util/imageformats.h"
+
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/Format.h"
+
+#include <string.h>
+
+namespace rx
+{
+
+namespace
+{
+typedef std::pair<gl::FormatType, ColorWriteFunction> FormatWriteFunctionPair;
+typedef std::map<gl::FormatType, ColorWriteFunction> FormatWriteFunctionMap;
+
+static inline void InsertFormatWriteFunctionMapping(FormatWriteFunctionMap *map,
+ GLenum format,
+ GLenum type,
+ ColorWriteFunction writeFunc)
+{
+ map->insert(FormatWriteFunctionPair(gl::FormatType(format, type), writeFunc));
+}
+
+static FormatWriteFunctionMap BuildFormatWriteFunctionMap()
+{
+ using namespace angle; // For image writing functions
+
+ FormatWriteFunctionMap map;
+
+ // clang-format off
+ // | Format | Type | Color write function |
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_BYTE, WriteColor<R8G8B8A8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_BYTE, WriteColor<R8G8B8A8S, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, WriteColor<R4G4B4A4, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, WriteColor<R5G5B5A1, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, WriteColor<R10G10B10A2, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_FLOAT, WriteColor<R32G32B32A32F, GLfloat>);
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_HALF_FLOAT, WriteColor<R16G16B16A16F, GLfloat>);
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_HALF_FLOAT_OES, WriteColor<R16G16B16A16F, GLfloat>);
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT,
+ WriteColor<R16G16B16A16, GLfloat>);
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_SHORT, WriteColor<R16G16B16A16S, GLfloat>);
+
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, WriteColor<R8G8B8A8, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_BYTE, WriteColor<R8G8B8A8S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, WriteColor<R16G16B16A16, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_SHORT, WriteColor<R16G16B16A16S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT, WriteColor<R32G32B32A32, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_INT, WriteColor<R32G32B32A32S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, WriteColor<R10G10B10A2, GLuint> );
+
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_BYTE, WriteColor<R8G8B8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_BYTE, WriteColor<R8G8B8S, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, WriteColor<R5G6B5, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, WriteColor<R11G11B10F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, WriteColor<R9G9B9E5, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_FLOAT, WriteColor<R32G32B32F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_HALF_FLOAT, WriteColor<R16G16B16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_HALF_FLOAT_OES, WriteColor<R16G16B16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_SHORT,
+ WriteColor<R16G16B16, GLfloat>);
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_SHORT, WriteColor<R16G16B16S, GLfloat>);
+
+ InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, WriteColor<R8G8B8, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_BYTE, WriteColor<R8G8B8S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, WriteColor<R16G16B16, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_SHORT, WriteColor<R16G16B16S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_INT, WriteColor<R32G32B32, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_INT, WriteColor<R32G32B32S, GLint> );
+
+ InsertFormatWriteFunctionMapping(&map, GL_RG, GL_UNSIGNED_BYTE, WriteColor<R8G8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG, GL_BYTE, WriteColor<R8G8S, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG, GL_FLOAT, WriteColor<R32G32F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG, GL_HALF_FLOAT, WriteColor<R16G16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG, GL_HALF_FLOAT_OES, WriteColor<R16G16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG, GL_UNSIGNED_SHORT, WriteColor<R16G16, GLfloat>);
+ InsertFormatWriteFunctionMapping(&map, GL_RG, GL_SHORT, WriteColor<R16G16S, GLfloat>);
+
+ InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_BYTE, WriteColor<R8G8, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_BYTE, WriteColor<R8G8S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_SHORT, WriteColor<R16G16, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_SHORT, WriteColor<R16G16S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_INT, WriteColor<R32G32, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_INT, WriteColor<R32G32S, GLint> );
+
+ InsertFormatWriteFunctionMapping(&map, GL_RED, GL_UNSIGNED_BYTE, WriteColor<R8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED, GL_BYTE, WriteColor<R8S, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED, GL_FLOAT, WriteColor<R32F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED, GL_HALF_FLOAT, WriteColor<R16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED, GL_HALF_FLOAT_OES, WriteColor<R16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED, GL_UNSIGNED_SHORT, WriteColor<R16, GLfloat>);
+ InsertFormatWriteFunctionMapping(&map, GL_RED, GL_SHORT, WriteColor<R16S, GLfloat>);
+
+ InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_BYTE, WriteColor<R8, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_BYTE, WriteColor<R8S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_SHORT, WriteColor<R16, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_SHORT, WriteColor<R16S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_INT, WriteColor<R32, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_INT, WriteColor<R32S, GLint> );
+
+ InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, WriteColor<L8A8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, WriteColor<L8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_UNSIGNED_BYTE, WriteColor<A8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, WriteColor<L32A32F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_FLOAT, WriteColor<L32F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_FLOAT, WriteColor<A32F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, WriteColor<L16A16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, WriteColor<L16A16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT, WriteColor<L16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, WriteColor<L16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_HALF_FLOAT, WriteColor<A16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_HALF_FLOAT_OES, WriteColor<A16F, GLfloat> );
+
+ InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_BYTE, WriteColor<B8G8R8A8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, WriteColor<A4R4G4B4, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, WriteColor<A1R5G5B5, GLfloat> );
+
+ InsertFormatWriteFunctionMapping(&map, GL_SRGB_EXT, GL_UNSIGNED_BYTE, WriteColor<R8G8B8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, WriteColor<R8G8B8A8, GLfloat> );
+
+ InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, nullptr );
+ InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, nullptr );
+ InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, nullptr );
+ InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, nullptr );
+
+ InsertFormatWriteFunctionMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, nullptr );
+ InsertFormatWriteFunctionMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr );
+ InsertFormatWriteFunctionMapping(&map, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr );
+
+ InsertFormatWriteFunctionMapping(&map, GL_STENCIL, GL_UNSIGNED_BYTE, nullptr );
+
+ InsertFormatWriteFunctionMapping(&map, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr );
+ InsertFormatWriteFunctionMapping(&map, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, nullptr );
+ // clang-format on
+
+ return map;
+}
+
+void CopyColor(gl::ColorF *color)
+{
+ // No-op
+}
+
+void PremultiplyAlpha(gl::ColorF *color)
+{
+ color->red *= color->alpha;
+ color->green *= color->alpha;
+ color->blue *= color->alpha;
+}
+
+void UnmultiplyAlpha(gl::ColorF *color)
+{
+ if (color->alpha != 0.0f)
+ {
+ float invAlpha = 1.0f / color->alpha;
+ color->red *= invAlpha;
+ color->green *= invAlpha;
+ color->blue *= invAlpha;
+ }
+}
+
+void ClipChannelsR(gl::ColorF *color)
+{
+ color->green = 0.0f;
+ color->blue = 0.0f;
+ color->alpha = 1.0f;
+}
+
+void ClipChannelsRG(gl::ColorF *color)
+{
+ color->blue = 0.0f;
+ color->alpha = 1.0f;
+}
+
+void ClipChannelsRGB(gl::ColorF *color)
+{
+ color->alpha = 1.0f;
+}
+
+void ClipChannelsLuminance(gl::ColorF *color)
+{
+ color->alpha = 1.0f;
+}
+
+void ClipChannelsAlpha(gl::ColorF *color)
+{
+ color->red = 0.0f;
+ color->green = 0.0f;
+ color->blue = 0.0f;
+}
+
+void ClipChannelsNoOp(gl::ColorF *color)
+{
+}
+
+void WriteUintColor(const gl::ColorF &color,
+ ColorWriteFunction colorWriteFunction,
+ uint8_t *destPixelData)
+{
+ gl::ColorUI destColor(
+ static_cast<unsigned int>(color.red * 255), static_cast<unsigned int>(color.green * 255),
+ static_cast<unsigned int>(color.blue * 255), static_cast<unsigned int>(color.alpha * 255));
+ colorWriteFunction(reinterpret_cast<const uint8_t *>(&destColor), destPixelData);
+}
+
+void WriteFloatColor(const gl::ColorF &color,
+ ColorWriteFunction colorWriteFunction,
+ uint8_t *destPixelData)
+{
+ colorWriteFunction(reinterpret_cast<const uint8_t *>(&color), destPixelData);
+}
+
+} // anonymous namespace
+
+PackPixelsParams::PackPixelsParams()
+ : format(GL_NONE), type(GL_NONE), outputPitch(0), packBuffer(nullptr), offset(0)
+{
+}
+
+PackPixelsParams::PackPixelsParams(const gl::Rectangle &areaIn,
+ GLenum formatIn,
+ GLenum typeIn,
+ GLuint outputPitchIn,
+ const gl::PixelPackState &packIn,
+ gl::Buffer *packBufferIn,
+ ptrdiff_t offsetIn)
+ : area(areaIn),
+ format(formatIn),
+ type(typeIn),
+ outputPitch(outputPitchIn),
+ packBuffer(packBufferIn),
+ pack(),
+ offset(offsetIn)
+{
+ pack.alignment = packIn.alignment;
+ pack.reverseRowOrder = packIn.reverseRowOrder;
+}
+
+void PackPixels(const PackPixelsParams &params,
+ const angle::Format &sourceFormat,
+ int inputPitchIn,
+ const uint8_t *sourceIn,
+ uint8_t *destWithoutOffset)
+{
+ uint8_t *destWithOffset = destWithoutOffset + params.offset;
+
+ const uint8_t *source = sourceIn;
+ int inputPitch = inputPitchIn;
+
+ if (params.pack.reverseRowOrder)
+ {
+ source += inputPitch * (params.area.height - 1);
+ inputPitch = -inputPitch;
+ }
+
+ const auto &sourceGLInfo = gl::GetSizedInternalFormatInfo(sourceFormat.glInternalFormat);
+
+ if (sourceGLInfo.format == params.format && sourceGLInfo.type == params.type)
+ {
+ // Direct copy possible
+ for (int y = 0; y < params.area.height; ++y)
+ {
+ memcpy(destWithOffset + y * params.outputPitch, source + y * inputPitch,
+ params.area.width * sourceGLInfo.pixelBytes);
+ }
+ return;
+ }
+
+ ASSERT(sourceGLInfo.sized);
+
+ gl::FormatType formatType(params.format, params.type);
+ ColorCopyFunction fastCopyFunc =
+ GetFastCopyFunction(sourceFormat.fastCopyFunctions, formatType);
+ const auto &destFormatInfo = gl::GetInternalFormatInfo(formatType.format, formatType.type);
+
+ if (fastCopyFunc)
+ {
+ // Fast copy is possible through some special function
+ for (int y = 0; y < params.area.height; ++y)
+ {
+ for (int x = 0; x < params.area.width; ++x)
+ {
+ uint8_t *dest =
+ destWithOffset + y * params.outputPitch + x * destFormatInfo.pixelBytes;
+ const uint8_t *src = source + y * inputPitch + x * sourceGLInfo.pixelBytes;
+
+ fastCopyFunc(src, dest);
+ }
+ }
+ return;
+ }
+
+ ColorWriteFunction colorWriteFunction = GetColorWriteFunction(formatType);
+
+ // Maximum size of any Color<T> type used.
+ uint8_t temp[16];
+ static_assert(sizeof(temp) >= sizeof(gl::ColorF) && sizeof(temp) >= sizeof(gl::ColorUI) &&
+ sizeof(temp) >= sizeof(gl::ColorI),
+ "Unexpected size of gl::Color struct.");
+
+ const auto &colorReadFunction = sourceFormat.colorReadFunction;
+
+ for (int y = 0; y < params.area.height; ++y)
+ {
+ for (int x = 0; x < params.area.width; ++x)
+ {
+ uint8_t *dest = destWithOffset + y * params.outputPitch + x * destFormatInfo.pixelBytes;
+ const uint8_t *src = source + y * inputPitch + x * sourceGLInfo.pixelBytes;
+
+ // readFunc and writeFunc will be using the same type of color, CopyTexImage
+ // will not allow the copy otherwise.
+ colorReadFunction(src, temp);
+ colorWriteFunction(temp, dest);
+ }
+ }
+}
+
+ColorWriteFunction GetColorWriteFunction(const gl::FormatType &formatType)
+{
+ static const FormatWriteFunctionMap formatTypeMap = BuildFormatWriteFunctionMap();
+ auto iter = formatTypeMap.find(formatType);
+ ASSERT(iter != formatTypeMap.end());
+ if (iter != formatTypeMap.end())
+ {
+ return iter->second;
+ }
+ else
+ {
+ return nullptr;
+ }
+}
+
+ColorCopyFunction GetFastCopyFunction(const FastCopyFunctionMap &fastCopyFunctions,
+ const gl::FormatType &formatType)
+{
+ return fastCopyFunctions.get(formatType);
+}
+
+bool FastCopyFunctionMap::has(const gl::FormatType &formatType) const
+{
+ return (get(formatType) != nullptr);
+}
+
+ColorCopyFunction FastCopyFunctionMap::get(const gl::FormatType &formatType) const
+{
+ for (size_t index = 0; index < mSize; ++index)
+ {
+ if (mData[index].format == formatType.format && mData[index].type == formatType.type)
+ {
+ return mData[index].func;
+ }
+ }
+
+ return nullptr;
+}
+
+bool ShouldUseDebugLayers(const egl::AttributeMap &attribs)
+{
+ EGLAttrib debugSetting =
+ attribs.get(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE, EGL_DONT_CARE);
+
+// Prefer to enable debug layers if compiling in Debug, and disabled in Release.
+#if !defined(NDEBUG)
+ return (debugSetting != EGL_FALSE);
+#else
+ return (debugSetting == EGL_TRUE);
+#endif // !defined(NDEBUG)
+}
+
+void CopyImageCHROMIUM(const uint8_t *sourceData,
+ size_t sourceRowPitch,
+ size_t sourcePixelBytes,
+ ColorReadFunction colorReadFunction,
+ uint8_t *destData,
+ size_t destRowPitch,
+ size_t destPixelBytes,
+ ColorWriteFunction colorWriteFunction,
+ GLenum destUnsizedFormat,
+ GLenum destComponentType,
+ size_t width,
+ size_t height,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha)
+{
+ using ConversionFunction = void (*)(gl::ColorF *);
+ ConversionFunction conversionFunction = CopyColor;
+ if (unpackPremultiplyAlpha != unpackUnmultiplyAlpha)
+ {
+ if (unpackPremultiplyAlpha)
+ {
+ conversionFunction = PremultiplyAlpha;
+ }
+ else
+ {
+ conversionFunction = UnmultiplyAlpha;
+ }
+ }
+
+ auto clipChannelsFunction = ClipChannelsNoOp;
+ switch (destUnsizedFormat)
+ {
+ case GL_RED:
+ clipChannelsFunction = ClipChannelsR;
+ break;
+ case GL_RG:
+ clipChannelsFunction = ClipChannelsRG;
+ break;
+ case GL_RGB:
+ clipChannelsFunction = ClipChannelsRGB;
+ break;
+ case GL_LUMINANCE:
+ clipChannelsFunction = ClipChannelsLuminance;
+ break;
+ case GL_ALPHA:
+ clipChannelsFunction = ClipChannelsAlpha;
+ break;
+ }
+
+ auto writeFunction = (destComponentType == GL_UNSIGNED_INT) ? WriteUintColor : WriteFloatColor;
+
+ for (size_t y = 0; y < height; y++)
+ {
+ for (size_t x = 0; x < width; x++)
+ {
+ const uint8_t *sourcePixelData = sourceData + y * sourceRowPitch + x * sourcePixelBytes;
+
+ gl::ColorF sourceColor;
+ colorReadFunction(sourcePixelData, reinterpret_cast<uint8_t *>(&sourceColor));
+
+ conversionFunction(&sourceColor);
+ clipChannelsFunction(&sourceColor);
+
+ size_t destY = 0;
+ if (unpackFlipY)
+ {
+ destY += (height - 1);
+ destY -= y;
+ }
+ else
+ {
+ destY += y;
+ }
+
+ uint8_t *destPixelData = destData + destY * destRowPitch + x * destPixelBytes;
+ writeFunction(sourceColor, colorWriteFunction, destPixelData);
+ }
+ }
+}
+
+// IncompleteTextureSet implementation.
+IncompleteTextureSet::IncompleteTextureSet()
+{
+}
+
+IncompleteTextureSet::~IncompleteTextureSet()
+{
+}
+
+void IncompleteTextureSet::onDestroy(const gl::Context *context)
+{
+ // Clear incomplete textures.
+ for (auto &incompleteTexture : mIncompleteTextures)
+ {
+ ANGLE_SWALLOW_ERR(incompleteTexture.second->onDestroy(context));
+ incompleteTexture.second.set(context, nullptr);
+ }
+ mIncompleteTextures.clear();
+}
+
+gl::Error IncompleteTextureSet::getIncompleteTexture(
+ const gl::Context *context,
+ GLenum type,
+ MultisampleTextureInitializer *multisampleInitializer,
+ gl::Texture **textureOut)
+{
+ auto iter = mIncompleteTextures.find(type);
+ if (iter != mIncompleteTextures.end())
+ {
+ *textureOut = iter->second.get();
+ return gl::NoError();
+ }
+
+ ContextImpl *implFactory = context->getImplementation();
+
+ const GLubyte color[] = {0, 0, 0, 255};
+ const gl::Extents colorSize(1, 1, 1);
+ gl::PixelUnpackState unpack;
+ unpack.alignment = 1;
+ const gl::Box area(0, 0, 0, 1, 1, 1);
+
+ // If a texture is external use a 2D texture for the incomplete texture
+ GLenum createType = (type == GL_TEXTURE_EXTERNAL_OES) ? GL_TEXTURE_2D : type;
+
+ gl::Texture *tex = new gl::Texture(implFactory, std::numeric_limits<GLuint>::max(), createType);
+ angle::UniqueObjectPointer<gl::Texture, gl::Context> t(tex, context);
+
+ if (createType == GL_TEXTURE_2D_MULTISAMPLE)
+ {
+ ANGLE_TRY(t->setStorageMultisample(context, createType, 1, GL_RGBA8, colorSize, true));
+ }
+ else
+ {
+ ANGLE_TRY(t->setStorage(context, createType, 1, GL_RGBA8, colorSize));
+ }
+
+ if (type == GL_TEXTURE_CUBE_MAP)
+ {
+ for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
+ face++)
+ {
+ ANGLE_TRY(
+ t->setSubImage(context, unpack, face, 0, area, GL_RGBA, GL_UNSIGNED_BYTE, color));
+ }
+ }
+ else if (type == GL_TEXTURE_2D_MULTISAMPLE)
+ {
+ // Call a specialized clear function to init a multisample texture.
+ ANGLE_TRY(multisampleInitializer->initializeMultisampleTextureToBlack(context, t.get()));
+ }
+ else
+ {
+ ANGLE_TRY(
+ t->setSubImage(context, unpack, createType, 0, area, GL_RGBA, GL_UNSIGNED_BYTE, color));
+ }
+
+ t->syncState();
+
+ mIncompleteTextures[type].set(context, t.release());
+ *textureOut = mIncompleteTextures[type].get();
+ return gl::NoError();
+}
+
+} // namespace rx
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/renderer_utils.h b/src/3rdparty/angle/src/libANGLE/renderer/renderer_utils.h
new file mode 100644
index 0000000000..5a1cb38a6a
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/renderer_utils.h
@@ -0,0 +1,254 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// renderer_utils:
+// Helper methods pertaining to most or all back-ends.
+//
+
+#ifndef LIBANGLE_RENDERER_RENDERER_UTILS_H_
+#define LIBANGLE_RENDERER_RENDERER_UTILS_H_
+
+#include <cstdint>
+
+#include <limits>
+#include <map>
+
+#include "common/angleutils.h"
+#include "libANGLE/angletypes.h"
+
+namespace angle
+{
+struct Format;
+} // namespace angle
+
+namespace gl
+{
+struct FormatType;
+struct InternalFormat;
+} // namespace gl
+
+namespace egl
+{
+class AttributeMap;
+} // namespace egl
+
+namespace rx
+{
+
+class ResourceSerial
+{
+ public:
+ constexpr ResourceSerial() : mValue(kDirty) {}
+ explicit constexpr ResourceSerial(uintptr_t value) : mValue(value) {}
+ constexpr bool operator==(ResourceSerial other) const { return mValue == other.mValue; }
+ constexpr bool operator!=(ResourceSerial other) const { return mValue != other.mValue; }
+
+ void dirty() { mValue = kDirty; }
+ void clear() { mValue = kEmpty; }
+
+ constexpr bool valid() const { return mValue != kEmpty && mValue != kDirty; }
+ constexpr bool empty() const { return mValue == kEmpty; }
+
+ private:
+ constexpr static uintptr_t kDirty = std::numeric_limits<uintptr_t>::max();
+ constexpr static uintptr_t kEmpty = 0;
+
+ uintptr_t mValue;
+};
+
+class SerialFactory;
+
+class Serial final
+{
+ public:
+ constexpr Serial() : mValue(kInvalid) {}
+ constexpr Serial(const Serial &other) = default;
+ Serial &operator=(const Serial &other) = default;
+
+ constexpr bool operator==(const Serial &other) const
+ {
+ return mValue != kInvalid && mValue == other.mValue;
+ }
+ constexpr bool operator!=(const Serial &other) const
+ {
+ return mValue == kInvalid || mValue != other.mValue;
+ }
+ constexpr bool operator>(const Serial &other) const { return mValue > other.mValue; }
+ constexpr bool operator>=(const Serial &other) const { return mValue >= other.mValue; }
+ constexpr bool operator<(const Serial &other) const { return mValue < other.mValue; }
+ constexpr bool operator<=(const Serial &other) const { return mValue <= other.mValue; }
+
+ private:
+ friend class SerialFactory;
+ constexpr explicit Serial(uint64_t value) : mValue(value) {}
+ uint64_t mValue;
+ static constexpr uint64_t kInvalid = 0;
+};
+
+class SerialFactory final : angle::NonCopyable
+{
+ public:
+ SerialFactory() : mSerial(1) {}
+
+ Serial generate()
+ {
+ ASSERT(mSerial != std::numeric_limits<uint64_t>::max());
+ return Serial(mSerial++);
+ }
+
+ private:
+ uint64_t mSerial;
+};
+
+using MipGenerationFunction = void (*)(size_t sourceWidth,
+ size_t sourceHeight,
+ size_t sourceDepth,
+ const uint8_t *sourceData,
+ size_t sourceRowPitch,
+ size_t sourceDepthPitch,
+ uint8_t *destData,
+ size_t destRowPitch,
+ size_t destDepthPitch);
+
+typedef void (*ColorReadFunction)(const uint8_t *source, uint8_t *dest);
+typedef void (*ColorWriteFunction)(const uint8_t *source, uint8_t *dest);
+typedef void (*ColorCopyFunction)(const uint8_t *source, uint8_t *dest);
+
+class FastCopyFunctionMap
+{
+ public:
+ struct Entry
+ {
+ GLenum format;
+ GLenum type;
+ ColorCopyFunction func;
+ };
+
+ constexpr FastCopyFunctionMap() : FastCopyFunctionMap(nullptr, 0) {}
+
+ constexpr FastCopyFunctionMap(const Entry *data, size_t size) : mSize(size), mData(data) {}
+
+ bool has(const gl::FormatType &formatType) const;
+ ColorCopyFunction get(const gl::FormatType &formatType) const;
+
+ private:
+ size_t mSize;
+ const Entry *mData;
+};
+
+struct PackPixelsParams
+{
+ PackPixelsParams();
+ PackPixelsParams(const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ GLuint outputPitch,
+ const gl::PixelPackState &pack,
+ gl::Buffer *packBufferIn,
+ ptrdiff_t offset);
+
+ gl::Rectangle area;
+ GLenum format;
+ GLenum type;
+ GLuint outputPitch;
+ gl::Buffer *packBuffer;
+ gl::PixelPackState pack;
+ ptrdiff_t offset;
+};
+
+void PackPixels(const PackPixelsParams &params,
+ const angle::Format &sourceFormat,
+ int inputPitch,
+ const uint8_t *source,
+ uint8_t *destination);
+
+ColorWriteFunction GetColorWriteFunction(const gl::FormatType &formatType);
+ColorCopyFunction GetFastCopyFunction(const FastCopyFunctionMap &fastCopyFunctions,
+ const gl::FormatType &formatType);
+
+using InitializeTextureDataFunction = void (*)(size_t width,
+ size_t height,
+ size_t depth,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+using LoadImageFunction = void (*)(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+struct LoadImageFunctionInfo
+{
+ LoadImageFunctionInfo() : loadFunction(nullptr), requiresConversion(false) {}
+ LoadImageFunctionInfo(LoadImageFunction loadFunction, bool requiresConversion)
+ : loadFunction(loadFunction), requiresConversion(requiresConversion)
+ {
+ }
+
+ LoadImageFunction loadFunction;
+ bool requiresConversion;
+};
+
+using LoadFunctionMap = LoadImageFunctionInfo (*)(GLenum);
+
+bool ShouldUseDebugLayers(const egl::AttributeMap &attribs);
+
+void CopyImageCHROMIUM(const uint8_t *sourceData,
+ size_t sourceRowPitch,
+ size_t sourcePixelBytes,
+ ColorReadFunction readFunction,
+ uint8_t *destData,
+ size_t destRowPitch,
+ size_t destPixelBytes,
+ ColorWriteFunction colorWriteFunction,
+ GLenum destUnsizedFormat,
+ GLenum destComponentType,
+ size_t width,
+ size_t height,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha);
+
+// Incomplete textures are 1x1 textures filled with black, used when samplers are incomplete.
+// This helper class encapsulates handling incomplete textures. Because the GL back-end
+// can take advantage of the driver's incomplete textures, and because clearing multisample
+// textures is so difficult, we can keep an instance of this class in the back-end instead
+// of moving the logic to the Context front-end.
+
+// This interface allows us to call-back to init a multisample texture.
+class MultisampleTextureInitializer
+{
+ public:
+ virtual ~MultisampleTextureInitializer() {}
+ virtual gl::Error initializeMultisampleTextureToBlack(const gl::Context *context,
+ gl::Texture *glTexture) = 0;
+};
+
+class IncompleteTextureSet final : angle::NonCopyable
+{
+ public:
+ IncompleteTextureSet();
+ ~IncompleteTextureSet();
+
+ void onDestroy(const gl::Context *context);
+
+ gl::Error getIncompleteTexture(const gl::Context *context,
+ GLenum type,
+ MultisampleTextureInitializer *multisampleInitializer,
+ gl::Texture **textureOut);
+
+ private:
+ gl::TextureMap mIncompleteTextures;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_RENDERER_UTILS_H_
diff --git a/src/3rdparty/angle/src/libANGLE/signal_utils.h b/src/3rdparty/angle/src/libANGLE/signal_utils.h
new file mode 100644
index 0000000000..3dd1332013
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/signal_utils.h
@@ -0,0 +1,187 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// signal_utils:
+// Helper classes for tracking dependent state changes between objects.
+// These changes are signaled to the dependent class via channels.
+// See design document:
+// https://docs.google.com/document/d/15Edfotqg6_l1skTEL8ADQudF_oIdNa7i8Po43k6jMd4/
+
+#ifndef LIBANGLE_SIGNAL_UTILS_H_
+#define LIBANGLE_SIGNAL_UTILS_H_
+
+#include <set>
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+
+namespace angle
+{
+
+// Interface that the depending class inherits from.
+template <typename ChannelID = uint32_t, typename... MessageT>
+class SignalReceiver
+{
+ public:
+ virtual ~SignalReceiver() = default;
+ virtual void signal(ChannelID channelID, MessageT... message) = 0;
+};
+
+template <typename ChannelID, typename... MessageT>
+class ChannelBinding;
+
+// The host class owns the channel. It uses the channel to fire signals to the receiver.
+template <typename ChannelID = uint32_t, typename... MessageT>
+class BroadcastChannel final : NonCopyable
+{
+ public:
+ BroadcastChannel();
+ ~BroadcastChannel();
+
+ void signal(MessageT... message) const;
+
+ void reset();
+
+ bool empty() const;
+
+ private:
+ // Only the ChannelBinding class should add or remove receivers.
+ friend class ChannelBinding<ChannelID, MessageT...>;
+ void addReceiver(ChannelBinding<ChannelID, MessageT...> *receiver);
+ void removeReceiver(ChannelBinding<ChannelID, MessageT...> *receiver);
+
+ std::vector<ChannelBinding<ChannelID, MessageT...> *> mReceivers;
+};
+
+template <typename ChannelID, typename... MessageT>
+BroadcastChannel<ChannelID, MessageT...>::BroadcastChannel()
+{
+}
+
+template <typename ChannelID, typename... MessageT>
+BroadcastChannel<ChannelID, MessageT...>::~BroadcastChannel()
+{
+ reset();
+}
+
+template <typename ChannelID, typename... MessageT>
+void BroadcastChannel<ChannelID, MessageT...>::addReceiver(
+ ChannelBinding<ChannelID, MessageT...> *receiver)
+{
+ ASSERT(std::find(mReceivers.begin(), mReceivers.end(), receiver) == mReceivers.end());
+ mReceivers.push_back(receiver);
+}
+
+template <typename ChannelID, typename... MessageT>
+void BroadcastChannel<ChannelID, MessageT...>::removeReceiver(
+ ChannelBinding<ChannelID, MessageT...> *receiver)
+{
+ auto iter = std::find(mReceivers.begin(), mReceivers.end(), receiver);
+ ASSERT(iter != mReceivers.end());
+ mReceivers.erase(iter);
+}
+
+template <typename ChannelID, typename... MessageT>
+void BroadcastChannel<ChannelID, MessageT...>::signal(MessageT... message) const
+{
+ if (mReceivers.empty())
+ return;
+
+ for (const auto *receiver : mReceivers)
+ {
+ receiver->signal(message...);
+ }
+}
+
+template <typename ChannelID, typename... MessageT>
+void BroadcastChannel<ChannelID, MessageT...>::reset()
+{
+ for (auto receiver : mReceivers)
+ {
+ receiver->onChannelClosed();
+ }
+ mReceivers.clear();
+}
+
+template <typename ChannelID, typename... MessageT>
+bool BroadcastChannel<ChannelID, MessageT...>::empty() const
+{
+ return mReceivers.empty();
+}
+
+// The dependent class keeps bindings to the host's BroadcastChannel.
+template <typename ChannelID = uint32_t, typename... MessageT>
+class ChannelBinding final
+{
+ public:
+ ChannelBinding(SignalReceiver<ChannelID, MessageT...> *receiver, ChannelID channelID);
+ ~ChannelBinding();
+ ChannelBinding(const ChannelBinding &other) = default;
+ ChannelBinding &operator=(const ChannelBinding &other) = default;
+
+ void bind(BroadcastChannel<ChannelID, MessageT...> *channel);
+ void reset();
+ void signal(MessageT... message) const;
+ void onChannelClosed();
+
+ private:
+ BroadcastChannel<ChannelID, MessageT...> *mChannel;
+ SignalReceiver<ChannelID, MessageT...> *mReceiver;
+ ChannelID mChannelID;
+};
+
+template <typename ChannelID, typename... MessageT>
+ChannelBinding<ChannelID, MessageT...>::ChannelBinding(
+ SignalReceiver<ChannelID, MessageT...> *receiver,
+ ChannelID channelID)
+ : mChannel(nullptr), mReceiver(receiver), mChannelID(channelID)
+{
+ ASSERT(receiver);
+}
+
+template <typename ChannelID, typename... MessageT>
+ChannelBinding<ChannelID, MessageT...>::~ChannelBinding()
+{
+ reset();
+}
+
+template <typename ChannelID, typename... MessageT>
+void ChannelBinding<ChannelID, MessageT...>::bind(BroadcastChannel<ChannelID, MessageT...> *channel)
+{
+ ASSERT(mReceiver);
+ if (mChannel)
+ {
+ mChannel->removeReceiver(this);
+ }
+
+ mChannel = channel;
+
+ if (mChannel)
+ {
+ mChannel->addReceiver(this);
+ }
+}
+
+template <typename ChannelID, typename... MessageT>
+void ChannelBinding<ChannelID, MessageT...>::reset()
+{
+ bind(nullptr);
+}
+
+template <typename ChannelID, typename... MessageT>
+void ChannelBinding<ChannelID, MessageT...>::signal(MessageT... message) const
+{
+ mReceiver->signal(mChannelID, message...);
+}
+
+template <typename ChannelID, typename... MessageT>
+void ChannelBinding<ChannelID, MessageT...>::onChannelClosed()
+{
+ mChannel = nullptr;
+}
+
+} // namespace angle
+
+#endif // LIBANGLE_SIGNAL_UTILS_H_
diff --git a/src/3rdparty/angle/src/libANGLE/validationEGL.cpp b/src/3rdparty/angle/src/libANGLE/validationEGL.cpp
index 903f51b158..13a3a9e280 100644
--- a/src/3rdparty/angle/src/libANGLE/validationEGL.cpp
+++ b/src/3rdparty/angle/src/libANGLE/validationEGL.cpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -14,10 +14,15 @@
#include "libANGLE/Device.h"
#include "libANGLE/Display.h"
#include "libANGLE/Image.h"
+#include "libANGLE/Stream.h"
#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
#include <EGL/eglext.h>
+namespace egl
+{
namespace
{
size_t GetMaximumMipLevel(const gl::Context *context, GLenum target)
@@ -30,6 +35,9 @@ size_t GetMaximumMipLevel(const gl::Context *context, GLenum target)
case GL_TEXTURE_2D:
maxDimension = caps.max2DTextureSize;
break;
+ case GL_TEXTURE_RECTANGLE_ANGLE:
+ maxDimension = caps.maxRectangleTextureSize;
+ break;
case GL_TEXTURE_CUBE_MAP:
maxDimension = caps.maxCubeMapTextureSize;
break;
@@ -56,7 +64,7 @@ bool TextureHasNonZeroMipLevelsSpecified(const gl::Context *context, const gl::T
for (GLenum face = gl::FirstCubeMapTextureTarget; face <= gl::LastCubeMapTextureTarget;
face++)
{
- if (texture->getInternalFormat(face, level) != GL_NONE)
+ if (texture->getFormat(face, level).valid())
{
return true;
}
@@ -64,7 +72,7 @@ bool TextureHasNonZeroMipLevelsSpecified(const gl::Context *context, const gl::T
}
else
{
- if (texture->getInternalFormat(texture->getTarget(), level) != GL_NONE)
+ if (texture->getFormat(texture->getTarget(), level).valid())
{
return true;
}
@@ -79,7 +87,7 @@ bool CubeTextureHasUnspecifiedLevel0Face(const gl::Texture *texture)
ASSERT(texture->getTarget() == GL_TEXTURE_CUBE_MAP);
for (GLenum face = gl::FirstCubeMapTextureTarget; face <= gl::LastCubeMapTextureTarget; face++)
{
- if (texture->getInternalFormat(face, 0) == GL_NONE)
+ if (!texture->getFormat(face, 0).valid())
{
return true;
}
@@ -87,114 +95,482 @@ bool CubeTextureHasUnspecifiedLevel0Face(const gl::Texture *texture)
return false;
}
+
+Error ValidateStreamAttribute(const EGLAttrib attribute,
+ const EGLAttrib value,
+ const DisplayExtensions &extensions)
+{
+ switch (attribute)
+ {
+ case EGL_STREAM_STATE_KHR:
+ case EGL_PRODUCER_FRAME_KHR:
+ case EGL_CONSUMER_FRAME_KHR:
+ return EglBadAccess() << "Attempt to initialize readonly parameter";
+ case EGL_CONSUMER_LATENCY_USEC_KHR:
+ // Technically not in spec but a latency < 0 makes no sense so we check it
+ if (value < 0)
+ {
+ return EglBadParameter() << "Latency must be positive";
+ }
+ break;
+ case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
+ if (!extensions.streamConsumerGLTexture)
+ {
+ return EglBadAttribute() << "Consumer GL extension not enabled";
+ }
+ // Again not in spec but it should be positive anyways
+ if (value < 0)
+ {
+ return EglBadParameter() << "Timeout must be positive";
+ }
+ break;
+ default:
+ return EglBadAttribute() << "Invalid stream attribute";
+ }
+ return NoError();
}
-namespace egl
+Error ValidateCreateImageKHRMipLevelCommon(gl::Context *context,
+ const gl::Texture *texture,
+ EGLAttrib level)
{
+ // Note that the spec EGL_KHR_create_image spec does not explicitly specify an error
+ // when the level is outside the base/max level range, but it does mention that the
+ // level "must be a part of the complete texture object <buffer>". It can be argued
+ // that out-of-range levels are not a part of the complete texture.
+ const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
+ if (level > 0 &&
+ (!texture->isMipmapComplete() || static_cast<GLuint>(level) < effectiveBaseLevel ||
+ static_cast<GLuint>(level) > texture->getTextureState().getMipmapMaxLevel()))
+ {
+ return EglBadParameter() << "texture must be complete if level is non-zero.";
+ }
+
+ if (level == 0 && !texture->isMipmapComplete() &&
+ TextureHasNonZeroMipLevelsSpecified(context, texture))
+ {
+ return EglBadParameter() << "if level is zero and the texture is incomplete, it must "
+ "have no mip levels specified except zero.";
+ }
+
+ return NoError();
+}
+
+Error ValidateConfigAttribute(const Display *display, EGLAttrib attribute)
+{
+ switch (attribute)
+ {
+ case EGL_BUFFER_SIZE:
+ case EGL_ALPHA_SIZE:
+ case EGL_BLUE_SIZE:
+ case EGL_GREEN_SIZE:
+ case EGL_RED_SIZE:
+ case EGL_DEPTH_SIZE:
+ case EGL_STENCIL_SIZE:
+ case EGL_CONFIG_CAVEAT:
+ case EGL_CONFIG_ID:
+ case EGL_LEVEL:
+ case EGL_NATIVE_RENDERABLE:
+ case EGL_NATIVE_VISUAL_ID:
+ case EGL_NATIVE_VISUAL_TYPE:
+ case EGL_SAMPLES:
+ case EGL_SAMPLE_BUFFERS:
+ case EGL_SURFACE_TYPE:
+ case EGL_TRANSPARENT_TYPE:
+ case EGL_TRANSPARENT_BLUE_VALUE:
+ case EGL_TRANSPARENT_GREEN_VALUE:
+ case EGL_TRANSPARENT_RED_VALUE:
+ case EGL_BIND_TO_TEXTURE_RGB:
+ case EGL_BIND_TO_TEXTURE_RGBA:
+ case EGL_MIN_SWAP_INTERVAL:
+ case EGL_MAX_SWAP_INTERVAL:
+ case EGL_LUMINANCE_SIZE:
+ case EGL_ALPHA_MASK_SIZE:
+ case EGL_COLOR_BUFFER_TYPE:
+ case EGL_RENDERABLE_TYPE:
+ case EGL_MATCH_NATIVE_PIXMAP:
+ case EGL_CONFORMANT:
+ case EGL_MAX_PBUFFER_WIDTH:
+ case EGL_MAX_PBUFFER_HEIGHT:
+ case EGL_MAX_PBUFFER_PIXELS:
+ break;
+
+ case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
+ if (!display->getExtensions().surfaceOrientation)
+ {
+ return EglBadAttribute() << "EGL_ANGLE_surface_orientation is not enabled.";
+ }
+ break;
+
+ case EGL_COLOR_COMPONENT_TYPE_EXT:
+ if (!display->getExtensions().pixelFormatFloat)
+ {
+ return EglBadAttribute() << "EGL_EXT_pixel_format_float is not enabled.";
+ }
+ break;
+
+ default:
+ return EglBadAttribute() << "Unknown attribute.";
+ }
+
+ return NoError();
+}
+
+Error ValidateConfigAttributes(const Display *display, const AttributeMap &attributes)
+{
+ for (const auto &attrib : attributes)
+ {
+ ANGLE_TRY(ValidateConfigAttribute(display, attrib.first));
+ }
+
+ return NoError();
+}
+
+Error ValidatePlatformType(const ClientExtensions &clientExtensions, EGLAttrib platformType)
+{
+ switch (platformType)
+ {
+ case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
+ break;
+
+ case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
+ case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
+ if (!clientExtensions.platformANGLED3D)
+ {
+ return EglBadAttribute() << "Direct3D platform is unsupported.";
+ }
+ break;
+
+ case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
+ case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
+ if (!clientExtensions.platformANGLEOpenGL)
+ {
+ return EglBadAttribute() << "OpenGL platform is unsupported.";
+ }
+ break;
+
+ case EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE:
+ if (!clientExtensions.platformANGLENULL)
+ {
+ return EglBadAttribute() << "Display type EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE "
+ "requires EGL_ANGLE_platform_angle_null.";
+ }
+ break;
+
+ case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
+ if (!clientExtensions.platformANGLEVulkan)
+ {
+ return EglBadAttribute() << "Vulkan platform is unsupported.";
+ }
+ break;
+
+ default:
+ return EglBadAttribute() << "Unknown platform type.";
+ }
+
+ return NoError();
+}
+
+Error ValidateGetPlatformDisplayCommon(EGLenum platform,
+ void *native_display,
+ const AttributeMap &attribMap)
+{
+ const ClientExtensions &clientExtensions = Display::GetClientExtensions();
+
+ switch (platform)
+ {
+ case EGL_PLATFORM_ANGLE_ANGLE:
+ if (!clientExtensions.platformANGLE)
+ {
+ return EglBadParameter() << "Platform ANGLE extension is not active";
+ }
+ break;
+ case EGL_PLATFORM_DEVICE_EXT:
+ if (!clientExtensions.platformDevice)
+ {
+ return EglBadParameter() << "Platform Device extension is not active";
+ }
+ break;
+ default:
+ return EglBadConfig() << "Bad platform type.";
+ }
+
+ if (platform == EGL_PLATFORM_ANGLE_ANGLE)
+ {
+ EGLAttrib platformType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
+ EGLAttrib deviceType = EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE;
+ bool enableAutoTrimSpecified = false;
+ bool deviceTypeSpecified = false;
+ bool presentPathSpecified = false;
+
+ Optional<EGLAttrib> majorVersion;
+ Optional<EGLAttrib> minorVersion;
+
+ for (const auto &curAttrib : attribMap)
+ {
+ const EGLAttrib value = curAttrib.second;
+
+ switch (curAttrib.first)
+ {
+ case EGL_PLATFORM_ANGLE_TYPE_ANGLE:
+ {
+ ANGLE_TRY(ValidatePlatformType(clientExtensions, value));
+ platformType = value;
+ break;
+ }
+
+ case EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE:
+ if (value != EGL_DONT_CARE)
+ {
+ majorVersion = value;
+ }
+ break;
+
+ case EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE:
+ if (value != EGL_DONT_CARE)
+ {
+ minorVersion = value;
+ }
+ break;
+
+ case EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE:
+ switch (value)
+ {
+ case EGL_TRUE:
+ case EGL_FALSE:
+ break;
+ default:
+ return EglBadAttribute() << "Invalid automatic trim attribute";
+ }
+ enableAutoTrimSpecified = true;
+ break;
+
+ case EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE:
+ if (!clientExtensions.experimentalPresentPath)
+ {
+ return EglBadAttribute()
+ << "EGL_ANGLE_experimental_present_path extension not active";
+ }
+
+ switch (value)
+ {
+ case EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE:
+ case EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE:
+ break;
+ default:
+ return EglBadAttribute()
+ << "Invalid value for EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE";
+ }
+ presentPathSpecified = true;
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE:
+ switch (value)
+ {
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE:
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE:
+ deviceTypeSpecified = true;
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
+ // This is a hidden option, accepted by the OpenGL back-end.
+ break;
+
+ default:
+ return EglBadAttribute() << "Invalid value for "
+ "EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE "
+ "attrib";
+ }
+ deviceType = value;
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE:
+ if (!clientExtensions.platformANGLE)
+ {
+ return EglBadAttribute() << "EGL_ANGLE_platform_angle extension not active";
+ }
+ if (value != EGL_TRUE && value != EGL_FALSE && value != EGL_DONT_CARE)
+ {
+ return EglBadAttribute() << "EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE "
+ "must be EGL_TRUE, EGL_FALSE, or "
+ "EGL_DONT_CARE.";
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (!majorVersion.valid() && minorVersion.valid())
+ {
+ return EglBadAttribute()
+ << "Must specify major version if you specify a minor version.";
+ }
+
+ if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE &&
+ platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+ {
+ return EglBadAttribute() << "EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE requires a "
+ "device type of EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.";
+ }
+
+ if (enableAutoTrimSpecified && platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+ {
+ return EglBadAttribute() << "EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE "
+ "requires a device type of "
+ "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.";
+ }
+
+ if (presentPathSpecified && platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+ {
+ return EglBadAttribute() << "EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE requires a "
+ "device type of EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.";
+ }
+
+ if (deviceTypeSpecified && platformType != EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE &&
+ platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+ {
+ return EglBadAttribute() << "EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE requires a "
+ "device type of EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE or "
+ "EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE.";
+ }
+
+ if (platformType == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
+ {
+ if ((majorVersion.valid() && majorVersion.value() != 1) ||
+ (minorVersion.valid() && minorVersion.value() != 0))
+ {
+ return EglBadAttribute() << "EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE currently "
+ "only supports Vulkan 1.0.";
+ }
+ }
+ }
+ else if (platform == EGL_PLATFORM_DEVICE_EXT)
+ {
+ Device *eglDevice = reinterpret_cast<Device *>(native_display);
+ if (eglDevice == nullptr || !Device::IsValidDevice(eglDevice))
+ {
+ return EglBadAttribute() << "native_display should be a valid EGL device if "
+ "platform equals EGL_PLATFORM_DEVICE_EXT";
+ }
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+
+ return NoError();
+}
+
+} // namespace
Error ValidateDisplay(const Display *display)
{
if (display == EGL_NO_DISPLAY)
{
- return Error(EGL_BAD_DISPLAY, "display is EGL_NO_DISPLAY.");
+ return EglBadDisplay() << "display is EGL_NO_DISPLAY.";
}
if (!Display::isValidDisplay(display))
{
- return Error(EGL_BAD_DISPLAY, "display is not a valid display.");
+ return EglBadDisplay() << "display is not a valid display.";
}
if (!display->isInitialized())
{
- return Error(EGL_NOT_INITIALIZED, "display is not initialized.");
+ return EglNotInitialized() << "display is not initialized.";
+ }
+
+ if (display->isDeviceLost())
+ {
+ return EglContextLost() << "display had a context loss";
}
- return Error(EGL_SUCCESS);
+ return NoError();
}
-Error ValidateSurface(const Display *display, Surface *surface)
+Error ValidateSurface(const Display *display, const Surface *surface)
{
- Error error = ValidateDisplay(display);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(ValidateDisplay(display));
if (!display->isValidSurface(surface))
{
- return Error(EGL_BAD_SURFACE);
+ return EglBadSurface();
}
- return Error(EGL_SUCCESS);
+ return NoError();
}
Error ValidateConfig(const Display *display, const Config *config)
{
- Error error = ValidateDisplay(display);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(ValidateDisplay(display));
if (!display->isValidConfig(config))
{
- return Error(EGL_BAD_CONFIG);
+ return EglBadConfig();
}
- return Error(EGL_SUCCESS);
+ return NoError();
}
-Error ValidateContext(const Display *display, gl::Context *context)
+Error ValidateContext(const Display *display, const gl::Context *context)
{
- Error error = ValidateDisplay(display);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(ValidateDisplay(display));
if (!display->isValidContext(context))
{
- return Error(EGL_BAD_CONTEXT);
+ return EglBadContext();
}
- return Error(EGL_SUCCESS);
+ return NoError();
}
Error ValidateImage(const Display *display, const Image *image)
{
- Error error = ValidateDisplay(display);
- if (error.isError())
+ ANGLE_TRY(ValidateDisplay(display));
+
+ if (!display->isValidImage(image))
{
- return error;
+ return EglBadParameter() << "image is not valid.";
}
- if (!display->isValidImage(image))
+ return NoError();
+}
+
+Error ValidateStream(const Display *display, const Stream *stream)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.stream)
+ {
+ return EglBadAccess() << "Stream extension not active";
+ }
+
+ if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
{
- return Error(EGL_BAD_PARAMETER, "image is not valid.");
+ return EglBadStream() << "Invalid stream";
}
- return Error(EGL_SUCCESS);
+ return NoError();
}
Error ValidateCreateContext(Display *display, Config *configuration, gl::Context *shareContext,
const AttributeMap& attributes)
{
- Error error = ValidateConfig(display, configuration);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(ValidateConfig(display, configuration));
// Get the requested client version (default is 1) and check it is 2 or 3.
- EGLint clientMajorVersion = 1;
- EGLint clientMinorVersion = 0;
- EGLint contextFlags = 0;
+ EGLAttrib clientMajorVersion = 1;
+ EGLAttrib clientMinorVersion = 0;
+ EGLAttrib contextFlags = 0;
bool resetNotification = false;
- bool robustAccess = false;
for (AttributeMap::const_iterator attributeIter = attributes.begin(); attributeIter != attributes.end(); attributeIter++)
{
- EGLint attribute = attributeIter->first;
- EGLint value = attributeIter->second;
+ EGLAttrib attribute = attributeIter->first;
+ EGLAttrib value = attributeIter->second;
switch (attribute)
{
@@ -215,28 +591,27 @@ Error ValidateCreateContext(Display *display, Config *configuration, gl::Context
case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
// Only valid for OpenGL (non-ES) contexts
- return Error(EGL_BAD_ATTRIBUTE);
+ return EglBadAttribute();
case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
if (!display->getExtensions().createContextRobustness)
{
- return Error(EGL_BAD_ATTRIBUTE);
+ return EglBadAttribute();
}
if (value != EGL_TRUE && value != EGL_FALSE)
{
- return Error(EGL_BAD_ATTRIBUTE);
+ return EglBadAttribute();
}
- robustAccess = (value == EGL_TRUE);
break;
case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
- static_assert(EGL_LOSE_CONTEXT_ON_RESET_EXT == EGL_LOSE_CONTEXT_ON_RESET_KHR, "EGL extension enums not equal.");
- static_assert(EGL_NO_RESET_NOTIFICATION_EXT == EGL_NO_RESET_NOTIFICATION_KHR, "EGL extension enums not equal.");
- // same as EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, fall through
+ return EglBadAttribute() << "EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR is not"
+ << " valid for GLES with EGL 1.4 and KHR_create_context. Use"
+ << " EXT_create_context_robustness.";
case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
if (!display->getExtensions().createContextRobustness)
{
- return Error(EGL_BAD_ATTRIBUTE);
+ return EglBadAttribute();
}
if (value == EGL_LOSE_CONTEXT_ON_RESET_EXT)
{
@@ -244,34 +619,143 @@ Error ValidateCreateContext(Display *display, Config *configuration, gl::Context
}
else if (value != EGL_NO_RESET_NOTIFICATION_EXT)
{
- return Error(EGL_BAD_ATTRIBUTE);
+ return EglBadAttribute();
}
break;
case EGL_CONTEXT_OPENGL_NO_ERROR_KHR:
if (!display->getExtensions().createContextNoError)
{
- return Error(EGL_BAD_ATTRIBUTE, "Invalid Context attribute.");
+ return EglBadAttribute() << "Invalid Context attribute.";
+ }
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ return EglBadAttribute() << "Attribute must be EGL_TRUE or EGL_FALSE.";
+ }
+ break;
+
+ case EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE:
+ if (!display->getExtensions().createContextWebGLCompatibility)
+ {
+ return EglBadAttribute() << "Attribute "
+ "EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE requires "
+ "EGL_ANGLE_create_context_webgl_compatibility.";
+ }
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ return EglBadAttribute()
+ << "EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE must be EGL_TRUE or EGL_FALSE.";
+ }
+ break;
+
+ case EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM:
+ if (!display->getExtensions().createContextBindGeneratesResource)
+ {
+ return EglBadAttribute()
+ << "Attribute EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM requires "
+ "EGL_CHROMIUM_create_context_bind_generates_resource.";
+ }
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ return EglBadAttribute() << "EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM "
+ "must be EGL_TRUE or EGL_FALSE.";
+ }
+ break;
+
+ case EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE:
+ if (!display->getExtensions().displayTextureShareGroup)
+ {
+ return EglBadAttribute() << "Attribute "
+ "EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE requires "
+ "EGL_ANGLE_display_texture_share_group.";
}
if (value != EGL_TRUE && value != EGL_FALSE)
{
- return Error(EGL_BAD_ATTRIBUTE, "Attribute must be EGL_TRUE or EGL_FALSE.");
+ return EglBadAttribute()
+ << "EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE must be EGL_TRUE or EGL_FALSE.";
+ }
+ if (shareContext &&
+ (shareContext->usingDisplayTextureShareGroup() != (value == EGL_TRUE)))
+ {
+ return EglBadAttribute() << "All contexts within a share group must be "
+ "created with the same value of "
+ "EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE.";
+ }
+ break;
+
+ case EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE:
+ if (!display->getExtensions().createContextClientArrays)
+ {
+ return EglBadAttribute()
+ << "Attribute EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE requires "
+ "EGL_ANGLE_create_context_client_arrays.";
+ }
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ return EglBadAttribute() << "EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE must "
+ "be EGL_TRUE or EGL_FALSE.";
+ }
+ break;
+
+ case EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE:
+ if (!display->getExtensions().programCacheControl)
+ {
+ return EglBadAttribute()
+ << "Attribute EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE "
+ "requires EGL_ANGLE_program_cache_control.";
+ }
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ return EglBadAttribute() << "EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE must "
+ "be EGL_TRUE or EGL_FALSE.";
+ }
+ break;
+
+ case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ if (!display->getExtensions().robustResourceInitialization)
+ {
+ return EglBadAttribute() << "Attribute EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
+ "requires EGL_ANGLE_robust_resource_initialization.";
+ }
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ return EglBadAttribute() << "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
+ "either EGL_TRUE or EGL_FALSE.";
}
break;
default:
- return Error(EGL_BAD_ATTRIBUTE);
+ return EglBadAttribute() << "Unknown attribute.";
}
}
- if ((clientMajorVersion != 2 && clientMajorVersion != 3) || clientMinorVersion != 0)
- {
- return Error(EGL_BAD_CONFIG);
- }
-
- if (clientMajorVersion == 3 && !(configuration->conformant & EGL_OPENGL_ES3_BIT_KHR) && !(configuration->configCaveat & EGL_NON_CONFORMANT_CONFIG))
+ switch (clientMajorVersion)
{
- return Error(EGL_BAD_CONFIG);
+ case 2:
+ if (clientMinorVersion != 0)
+ {
+ return EglBadConfig();
+ }
+ break;
+ case 3:
+ if (clientMinorVersion != 0 && clientMinorVersion != 1)
+ {
+ return EglBadConfig();
+ }
+ if (!(configuration->conformant & EGL_OPENGL_ES3_BIT_KHR))
+ {
+ return EglBadConfig();
+ }
+ if (display->getMaxSupportedESVersion() <
+ gl::Version(static_cast<GLuint>(clientMajorVersion),
+ static_cast<GLuint>(clientMinorVersion)))
+ {
+ return EglBadConfig() << "Requested GLES version is not supported.";
+ }
+ break;
+ default:
+ return EglBadConfig();
+ break;
}
// Note: EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR does not apply to ES
@@ -279,18 +763,7 @@ Error ValidateCreateContext(Display *display, Config *configuration, gl::Context
EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR);
if ((contextFlags & ~validContextFlags) != 0)
{
- return Error(EGL_BAD_ATTRIBUTE);
- }
-
- if ((contextFlags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) > 0)
- {
- robustAccess = true;
- }
-
- if (robustAccess)
- {
- // Unimplemented
- return Error(EGL_BAD_CONFIG);
+ return EglBadAttribute();
}
if (shareContext)
@@ -298,43 +771,40 @@ Error ValidateCreateContext(Display *display, Config *configuration, gl::Context
// Shared context is invalid or is owned by another display
if (!display->isValidContext(shareContext))
{
- return Error(EGL_BAD_MATCH);
+ return EglBadMatch();
}
if (shareContext->isResetNotificationEnabled() != resetNotification)
{
- return Error(EGL_BAD_MATCH);
+ return EglBadMatch();
}
- if (shareContext->getClientVersion() != clientMajorVersion)
+ if (shareContext->getClientMajorVersion() != clientMajorVersion ||
+ shareContext->getClientMinorVersion() != clientMinorVersion)
{
- return Error(EGL_BAD_CONTEXT);
+ return EglBadContext();
}
}
- return Error(EGL_SUCCESS);
+ return NoError();
}
Error ValidateCreateWindowSurface(Display *display, Config *config, EGLNativeWindowType window,
const AttributeMap& attributes)
{
- Error error = ValidateConfig(display, config);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(ValidateConfig(display, config));
if (!display->isValidNativeWindow(window))
{
- return Error(EGL_BAD_NATIVE_WINDOW);
+ return EglBadNativeWindow();
}
const DisplayExtensions &displayExtensions = display->getExtensions();
for (AttributeMap::const_iterator attributeIter = attributes.begin(); attributeIter != attributes.end(); attributeIter++)
{
- EGLint attribute = attributeIter->first;
- EGLint value = attributeIter->second;
+ EGLAttrib attribute = attributeIter->first;
+ EGLAttrib value = attributeIter->second;
switch (attribute)
{
@@ -344,23 +814,23 @@ Error ValidateCreateWindowSurface(Display *display, Config *config, EGLNativeWin
case EGL_BACK_BUFFER:
break;
case EGL_SINGLE_BUFFER:
- return Error(EGL_BAD_MATCH); // Rendering directly to front buffer not supported
+ return EglBadMatch(); // Rendering directly to front buffer not supported
default:
- return Error(EGL_BAD_ATTRIBUTE);
+ return EglBadAttribute();
}
break;
case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
if (!displayExtensions.postSubBuffer)
{
- return Error(EGL_BAD_ATTRIBUTE);
+ return EglBadAttribute();
}
break;
case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
if (!displayExtensions.flexibleSurfaceCompatibility)
{
- return Error(EGL_BAD_ATTRIBUTE);
+ return EglBadAttribute();
}
break;
@@ -368,68 +838,77 @@ Error ValidateCreateWindowSurface(Display *display, Config *config, EGLNativeWin
case EGL_HEIGHT:
if (!displayExtensions.windowFixedSize)
{
- return Error(EGL_BAD_ATTRIBUTE);
+ return EglBadAttribute();
}
if (value < 0)
{
- return Error(EGL_BAD_PARAMETER);
+ return EglBadParameter();
}
break;
case EGL_FIXED_SIZE_ANGLE:
if (!displayExtensions.windowFixedSize)
{
- return Error(EGL_BAD_ATTRIBUTE);
+ return EglBadAttribute();
}
break;
case EGL_SURFACE_ORIENTATION_ANGLE:
if (!displayExtensions.surfaceOrientation)
{
- return Error(EGL_BAD_ATTRIBUTE, "EGL_ANGLE_surface_orientation is not enabled.");
+ return EglBadAttribute() << "EGL_ANGLE_surface_orientation is not enabled.";
}
break;
case EGL_VG_COLORSPACE:
- return Error(EGL_BAD_MATCH);
+ return EglBadMatch();
case EGL_VG_ALPHA_FORMAT:
- return Error(EGL_BAD_MATCH);
+ return EglBadMatch();
case EGL_DIRECT_COMPOSITION_ANGLE:
if (!displayExtensions.directComposition)
{
- return Error(EGL_BAD_ATTRIBUTE);
+ return EglBadAttribute();
+ }
+ break;
+
+ case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ if (!display->getExtensions().robustResourceInitialization)
+ {
+ return EglBadAttribute() << "Attribute EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
+ "requires EGL_ANGLE_robust_resource_initialization.";
+ }
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ return EglBadAttribute() << "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
+ "either EGL_TRUE or EGL_FALSE.";
}
break;
default:
- return Error(EGL_BAD_ATTRIBUTE);
+ return EglBadAttribute();
}
}
if (Display::hasExistingWindowSurface(window))
{
- return Error(EGL_BAD_ALLOC);
+ return EglBadAlloc();
}
- return Error(EGL_SUCCESS);
+ return NoError();
}
Error ValidateCreatePbufferSurface(Display *display, Config *config, const AttributeMap& attributes)
{
- Error error = ValidateConfig(display, config);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(ValidateConfig(display, config));
const DisplayExtensions &displayExtensions = display->getExtensions();
for (AttributeMap::const_iterator attributeIter = attributes.begin(); attributeIter != attributes.end(); attributeIter++)
{
- EGLint attribute = attributeIter->first;
- EGLint value = attributeIter->second;
+ EGLAttrib attribute = attributeIter->first;
+ EGLAttrib value = attributeIter->second;
switch (attribute)
{
@@ -437,7 +916,7 @@ Error ValidateCreatePbufferSurface(Display *display, Config *config, const Attri
case EGL_HEIGHT:
if (value < 0)
{
- return Error(EGL_BAD_PARAMETER);
+ return EglBadParameter();
}
break;
@@ -452,7 +931,7 @@ Error ValidateCreatePbufferSurface(Display *display, Config *config, const Attri
case EGL_TEXTURE_RGBA:
break;
default:
- return Error(EGL_BAD_ATTRIBUTE);
+ return EglBadAttribute();
}
break;
@@ -463,7 +942,7 @@ Error ValidateCreatePbufferSurface(Display *display, Config *config, const Attri
case EGL_TEXTURE_2D:
break;
default:
- return Error(EGL_BAD_ATTRIBUTE);
+ return EglBadAttribute();
}
break;
@@ -479,60 +958,66 @@ Error ValidateCreatePbufferSurface(Display *display, Config *config, const Attri
case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
if (!displayExtensions.flexibleSurfaceCompatibility)
{
- return Error(
- EGL_BAD_ATTRIBUTE,
- "EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE cannot be used without "
- "EGL_ANGLE_flexible_surface_compatibility support.");
+ return EglBadAttribute()
+ << "EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE cannot be used "
+ "without EGL_ANGLE_flexible_surface_compatibility support.";
+ }
+ break;
+
+ case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ if (!display->getExtensions().robustResourceInitialization)
+ {
+ return EglBadAttribute() << "Attribute EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
+ "requires EGL_ANGLE_robust_resource_initialization.";
+ }
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ return EglBadAttribute() << "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
+ "either EGL_TRUE or EGL_FALSE.";
}
break;
default:
- return Error(EGL_BAD_ATTRIBUTE);
+ return EglBadAttribute();
}
}
if (!(config->surfaceType & EGL_PBUFFER_BIT))
{
- return Error(EGL_BAD_MATCH);
+ return EglBadMatch();
}
-#if !defined(ANGLE_ENABLE_WINDOWS_STORE) // On Windows Store, we know the originating texture came from D3D11, so bypass this check
const Caps &caps = display->getCaps();
- EGLenum textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
- EGLenum textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
+ EGLAttrib textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
+ EGLAttrib textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
(textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
{
- return Error(EGL_BAD_MATCH);
+ return EglBadMatch();
}
if ((textureFormat == EGL_TEXTURE_RGB && config->bindToTextureRGB != EGL_TRUE) ||
(textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE))
{
- return Error(EGL_BAD_ATTRIBUTE);
+ return EglBadAttribute();
}
- EGLint width = attributes.get(EGL_WIDTH, 0);
- EGLint height = attributes.get(EGL_HEIGHT, 0);
+ EGLint width = static_cast<EGLint>(attributes.get(EGL_WIDTH, 0));
+ EGLint height = static_cast<EGLint>(attributes.get(EGL_HEIGHT, 0));
if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height)))
{
- return Error(EGL_BAD_MATCH);
+ return EglBadMatch();
}
-#endif
- return Error(EGL_SUCCESS);
+ return NoError();
}
Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, EGLClientBuffer buffer,
Config *config, const AttributeMap& attributes)
{
- Error error = ValidateConfig(display, config);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(ValidateConfig(display, config));
const DisplayExtensions &displayExtensions = display->getExtensions();
@@ -541,22 +1026,33 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, E
case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
if (!displayExtensions.d3dShareHandleClientBuffer)
{
- return Error(EGL_BAD_PARAMETER);
+ return EglBadParameter();
}
if (buffer == nullptr)
{
- return Error(EGL_BAD_PARAMETER);
+ return EglBadParameter();
}
break;
+ case EGL_D3D_TEXTURE_ANGLE:
+ if (!displayExtensions.d3dTextureClientBuffer)
+ {
+ return EglBadParameter();
+ }
+ if (buffer == nullptr)
+ {
+ return EglBadParameter();
+ }
+ break;
+
default:
- return Error(EGL_BAD_PARAMETER);
+ return EglBadParameter();
}
for (AttributeMap::const_iterator attributeIter = attributes.begin(); attributeIter != attributes.end(); attributeIter++)
{
- EGLint attribute = attributeIter->first;
- EGLint value = attributeIter->second;
+ EGLAttrib attribute = attributeIter->first;
+ EGLAttrib value = attributeIter->second;
switch (attribute)
{
@@ -564,11 +1060,11 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, E
case EGL_HEIGHT:
if (!displayExtensions.d3dShareHandleClientBuffer)
{
- return Error(EGL_BAD_PARAMETER);
+ return EglBadParameter();
}
if (value < 0)
{
- return Error(EGL_BAD_PARAMETER);
+ return EglBadParameter();
}
break;
@@ -580,7 +1076,7 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, E
case EGL_TEXTURE_RGBA:
break;
default:
- return Error(EGL_BAD_ATTRIBUTE);
+ return EglBadAttribute();
}
break;
@@ -591,7 +1087,7 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, E
case EGL_TEXTURE_2D:
break;
default:
- return Error(EGL_BAD_ATTRIBUTE);
+ return EglBadAttribute();
}
break;
@@ -601,58 +1097,143 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, E
case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
if (!displayExtensions.flexibleSurfaceCompatibility)
{
- return Error(
- EGL_BAD_ATTRIBUTE,
- "EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE cannot be used without "
- "EGL_ANGLE_flexible_surface_compatibility support.");
+ return EglBadAttribute()
+ << "EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE cannot be used "
+ "without EGL_ANGLE_flexible_surface_compatibility support.";
}
break;
default:
- return Error(EGL_BAD_ATTRIBUTE);
+ return EglBadAttribute();
}
}
if (!(config->surfaceType & EGL_PBUFFER_BIT))
{
- return Error(EGL_BAD_MATCH);
+ return EglBadMatch();
}
- EGLenum textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
- EGLenum textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
+ EGLAttrib textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
+ EGLAttrib textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
(textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
{
- return Error(EGL_BAD_MATCH);
+ return EglBadMatch();
}
if ((textureFormat == EGL_TEXTURE_RGB && config->bindToTextureRGB != EGL_TRUE) ||
(textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE))
{
- return Error(EGL_BAD_ATTRIBUTE);
+ return EglBadAttribute();
}
if (buftype == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE)
{
- EGLint width = attributes.get(EGL_WIDTH, 0);
- EGLint height = attributes.get(EGL_HEIGHT, 0);
+ EGLint width = static_cast<EGLint>(attributes.get(EGL_WIDTH, 0));
+ EGLint height = static_cast<EGLint>(attributes.get(EGL_HEIGHT, 0));
if (width == 0 || height == 0)
{
- return Error(EGL_BAD_ATTRIBUTE);
+ return EglBadAttribute();
}
-// On Windows Store, we know the originating texture came from D3D11, so bypass this check
-#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
const Caps &caps = display->getCaps();
if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height)))
{
- return Error(EGL_BAD_MATCH);
+ return EglBadMatch();
+ }
+ }
+
+ ANGLE_TRY(display->validateClientBuffer(config, buftype, buffer, attributes));
+
+ return NoError();
+}
+
+Error ValidateMakeCurrent(Display *display, EGLSurface draw, EGLSurface read, gl::Context *context)
+{
+ if (context == EGL_NO_CONTEXT && (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
+ {
+ return EglBadMatch() << "If ctx is EGL_NO_CONTEXT, surfaces must be EGL_NO_SURFACE";
+ }
+
+ // If ctx is EGL_NO_CONTEXT and either draw or read are not EGL_NO_SURFACE, an EGL_BAD_MATCH
+ // error is generated. EGL_KHR_surfaceless_context allows both surfaces to be EGL_NO_SURFACE.
+ if (context != EGL_NO_CONTEXT && (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE))
+ {
+ if (display->getExtensions().surfacelessContext)
+ {
+ if ((draw == EGL_NO_SURFACE) != (read == EGL_NO_SURFACE))
+ {
+ return EglBadMatch() << "If ctx is not EGL_NOT_CONTEXT, draw or read must "
+ "both be EGL_NO_SURFACE, or both not";
+ }
+ }
+ else
+ {
+ return EglBadMatch()
+ << "If ctx is not EGL_NO_CONTEXT, surfaces must not be EGL_NO_SURFACE";
}
-#endif
}
- return Error(EGL_SUCCESS);
+ // If either of draw or read is a valid surface and the other is EGL_NO_SURFACE, an
+ // EGL_BAD_MATCH error is generated.
+ if ((read == EGL_NO_SURFACE) != (draw == EGL_NO_SURFACE))
+ {
+ return EglBadMatch()
+ << "read and draw must both be valid surfaces, or both be EGL_NO_SURFACE";
+ }
+
+ if (display == EGL_NO_DISPLAY || !Display::isValidDisplay(display))
+ {
+ return EglBadDisplay() << "'dpy' not a valid EGLDisplay handle";
+ }
+
+ // EGL 1.5 spec: dpy can be uninitialized if all other parameters are null
+ if (!display->isInitialized() &&
+ (context != EGL_NO_CONTEXT || draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
+ {
+ return EglNotInitialized() << "'dpy' not initialized";
+ }
+
+ if (context != EGL_NO_CONTEXT)
+ {
+ ANGLE_TRY(ValidateContext(display, context));
+ }
+
+ if (display->isInitialized() && display->testDeviceLost())
+ {
+ return EglContextLost();
+ }
+
+ Surface *drawSurface = static_cast<Surface *>(draw);
+ if (draw != EGL_NO_SURFACE)
+ {
+ ANGLE_TRY(ValidateSurface(display, drawSurface));
+ }
+
+ Surface *readSurface = static_cast<Surface *>(read);
+ if (read != EGL_NO_SURFACE)
+ {
+ ANGLE_TRY(ValidateSurface(display, readSurface));
+ }
+
+ if (readSurface)
+ {
+ ANGLE_TRY(ValidateCompatibleConfigs(display, readSurface->getConfig(), readSurface,
+ context->getConfig(), readSurface->getType()));
+ }
+
+ if (draw != read)
+ {
+ UNIMPLEMENTED(); // FIXME
+
+ if (drawSurface)
+ {
+ ANGLE_TRY(ValidateCompatibleConfigs(display, drawSurface->getConfig(), drawSurface,
+ context->getConfig(), drawSurface->getType()));
+ }
+ }
+ return NoError();
}
Error ValidateCompatibleConfigs(const Display *display,
@@ -669,7 +1250,7 @@ Error ValidateCompatibleConfigs(const Display *display,
bool colorBufferCompat = config1->colorBufferType == config2->colorBufferType;
if (!colorBufferCompat)
{
- return Error(EGL_BAD_MATCH, "Color buffer types are not compatible.");
+ return EglBadMatch() << "Color buffer types are not compatible.";
}
bool colorCompat =
@@ -678,24 +1259,30 @@ Error ValidateCompatibleConfigs(const Display *display,
config1->luminanceSize == config2->luminanceSize;
if (!colorCompat)
{
- return Error(EGL_BAD_MATCH, "Color buffer sizes are not compatible.");
+ return EglBadMatch() << "Color buffer sizes are not compatible.";
+ }
+
+ bool componentTypeCompat = config1->colorComponentType == config2->colorComponentType;
+ if (!componentTypeCompat)
+ {
+ return EglBadMatch() << "Color buffer component types are not compatible.";
}
bool dsCompat = config1->depthSize == config2->depthSize &&
config1->stencilSize == config2->stencilSize;
if (!dsCompat)
{
- return Error(EGL_BAD_MATCH, "Depth-stencil buffer types are not compatible.");
+ return EglBadMatch() << "Depth-stencil buffer types are not compatible.";
}
}
bool surfaceTypeCompat = (config1->surfaceType & config2->surfaceType & surfaceType) != 0;
if (!surfaceTypeCompat)
{
- return Error(EGL_BAD_MATCH, "Surface types are not compatible.");
+ return EglBadMatch() << "Surface types are not compatible.";
}
- return Error(EGL_SUCCESS);
+ return NoError();
}
Error ValidateCreateImageKHR(const Display *display,
@@ -704,11 +1291,7 @@ Error ValidateCreateImageKHR(const Display *display,
EGLClientBuffer buffer,
const AttributeMap &attributes)
{
- Error error = ValidateContext(display, context);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(ValidateContext(display, context));
const DisplayExtensions &displayExtensions = display->getExtensions();
@@ -717,7 +1300,7 @@ Error ValidateCreateImageKHR(const Display *display,
// It is out of spec what happens when calling an extension function when the extension is
// not available.
// EGL_BAD_DISPLAY seems like a reasonable error.
- return Error(EGL_BAD_DISPLAY, "EGL_KHR_image not supported.");
+ return EglBadDisplay() << "EGL_KHR_image not supported.";
}
// TODO(geofflang): Complete validation from EGL_KHR_image_base:
@@ -727,8 +1310,8 @@ Error ValidateCreateImageKHR(const Display *display,
for (AttributeMap::const_iterator attributeIter = attributes.begin();
attributeIter != attributes.end(); attributeIter++)
{
- EGLint attribute = attributeIter->first;
- EGLint value = attributeIter->second;
+ EGLAttrib attribute = attributeIter->first;
+ EGLAttrib value = attributeIter->second;
switch (attribute)
{
@@ -740,8 +1323,8 @@ Error ValidateCreateImageKHR(const Display *display,
break;
default:
- return Error(EGL_BAD_PARAMETER,
- "EGL_IMAGE_PRESERVED_KHR must be EGL_TRUE or EGL_FALSE.");
+ return EglBadParameter()
+ << "EGL_IMAGE_PRESERVED_KHR must be EGL_TRUE or EGL_FALSE.";
}
break;
@@ -749,28 +1332,27 @@ Error ValidateCreateImageKHR(const Display *display,
if (!displayExtensions.glTexture2DImage &&
!displayExtensions.glTextureCubemapImage && !displayExtensions.glTexture3DImage)
{
- return Error(EGL_BAD_PARAMETER,
- "EGL_GL_TEXTURE_LEVEL_KHR cannot be used without "
- "KHR_gl_texture_*_image support.");
+ return EglBadParameter() << "EGL_GL_TEXTURE_LEVEL_KHR cannot be used "
+ "without KHR_gl_texture_*_image support.";
}
if (value < 0)
{
- return Error(EGL_BAD_PARAMETER, "EGL_GL_TEXTURE_LEVEL_KHR cannot be negative.");
+ return EglBadParameter() << "EGL_GL_TEXTURE_LEVEL_KHR cannot be negative.";
}
break;
case EGL_GL_TEXTURE_ZOFFSET_KHR:
if (!displayExtensions.glTexture3DImage)
{
- return Error(EGL_BAD_PARAMETER,
- "EGL_GL_TEXTURE_ZOFFSET_KHR cannot be used without "
- "KHR_gl_texture_3D_image support.");
+ return EglBadParameter() << "EGL_GL_TEXTURE_ZOFFSET_KHR cannot be used "
+ "without KHR_gl_texture_3D_image support.";
}
break;
default:
- return Error(EGL_BAD_PARAMETER, "invalid attribute: 0x%X", attribute);
+ return EglBadParameter()
+ << "invalid attribute: 0x" << std::hex << std::uppercase << attribute;
}
}
@@ -780,48 +1362,35 @@ Error ValidateCreateImageKHR(const Display *display,
{
if (!displayExtensions.glTexture2DImage)
{
- return Error(EGL_BAD_PARAMETER, "KHR_gl_texture_2D_image not supported.");
+ return EglBadParameter() << "KHR_gl_texture_2D_image not supported.";
}
if (buffer == 0)
{
- return Error(EGL_BAD_PARAMETER,
- "buffer cannot reference a 2D texture with the name 0.");
+ return EglBadParameter() << "buffer cannot reference a 2D texture with the name 0.";
}
const gl::Texture *texture =
context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
if (texture == nullptr || texture->getTarget() != GL_TEXTURE_2D)
{
- return Error(EGL_BAD_PARAMETER, "target is not a 2D texture.");
+ return EglBadParameter() << "target is not a 2D texture.";
}
if (texture->getBoundSurface() != nullptr)
{
- return Error(EGL_BAD_ACCESS, "texture has a surface bound to it.");
+ return EglBadAccess() << "texture has a surface bound to it.";
}
- EGLint level = attributes.get(EGL_GL_TEXTURE_LEVEL_KHR, 0);
+ EGLAttrib level = attributes.get(EGL_GL_TEXTURE_LEVEL_KHR, 0);
if (texture->getWidth(GL_TEXTURE_2D, static_cast<size_t>(level)) == 0 ||
texture->getHeight(GL_TEXTURE_2D, static_cast<size_t>(level)) == 0)
{
- return Error(EGL_BAD_PARAMETER,
- "target 2D texture does not have a valid size at specified level.");
- }
-
- if (level > 0 && (!texture->isMipmapComplete() ||
- static_cast<size_t>(level) >= texture->getMipCompleteLevels()))
- {
- return Error(EGL_BAD_PARAMETER, "texture must be complete if level is non-zero.");
+ return EglBadParameter()
+ << "target 2D texture does not have a valid size at specified level.";
}
- if (level == 0 && !texture->isMipmapComplete() &&
- TextureHasNonZeroMipLevelsSpecified(context, texture))
- {
- return Error(EGL_BAD_PARAMETER,
- "if level is zero and the texture is incomplete, it must have no mip "
- "levels specified except zero.");
- }
+ ANGLE_TRY(ValidateCreateImageKHRMipLevelCommon(context, texture, level));
}
break;
@@ -834,57 +1403,44 @@ Error ValidateCreateImageKHR(const Display *display,
{
if (!displayExtensions.glTextureCubemapImage)
{
- return Error(EGL_BAD_PARAMETER, "KHR_gl_texture_cubemap_image not supported.");
+ return EglBadParameter() << "KHR_gl_texture_cubemap_image not supported.";
}
if (buffer == 0)
{
- return Error(EGL_BAD_PARAMETER,
- "buffer cannot reference a cubemap texture with the name 0.");
+ return EglBadParameter()
+ << "buffer cannot reference a cubemap texture with the name 0.";
}
const gl::Texture *texture =
context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
if (texture == nullptr || texture->getTarget() != GL_TEXTURE_CUBE_MAP)
{
- return Error(EGL_BAD_PARAMETER, "target is not a cubemap texture.");
+ return EglBadParameter() << "target is not a cubemap texture.";
}
if (texture->getBoundSurface() != nullptr)
{
- return Error(EGL_BAD_ACCESS, "texture has a surface bound to it.");
+ return EglBadAccess() << "texture has a surface bound to it.";
}
- EGLint level = attributes.get(EGL_GL_TEXTURE_LEVEL_KHR, 0);
+ EGLAttrib level = attributes.get(EGL_GL_TEXTURE_LEVEL_KHR, 0);
GLenum cubeMapFace = egl_gl::EGLCubeMapTargetToGLCubeMapTarget(target);
if (texture->getWidth(cubeMapFace, static_cast<size_t>(level)) == 0 ||
texture->getHeight(cubeMapFace, static_cast<size_t>(level)) == 0)
{
- return Error(EGL_BAD_PARAMETER,
- "target cubemap texture does not have a valid size at specified level "
- "and face.");
- }
-
- if (level > 0 && (!texture->isMipmapComplete() ||
- static_cast<size_t>(level) >= texture->getMipCompleteLevels()))
- {
- return Error(EGL_BAD_PARAMETER, "texture must be complete if level is non-zero.");
+ return EglBadParameter() << "target cubemap texture does not have a valid "
+ "size at specified level and face.";
}
- if (level == 0 && !texture->isMipmapComplete() &&
- TextureHasNonZeroMipLevelsSpecified(context, texture))
- {
- return Error(EGL_BAD_PARAMETER,
- "if level is zero and the texture is incomplete, it must have no mip "
- "levels specified except zero.");
- }
+ ANGLE_TRY(ValidateCreateImageKHRMipLevelCommon(context, texture, level));
if (level == 0 && !texture->isMipmapComplete() &&
CubeTextureHasUnspecifiedLevel0Face(texture))
{
- return Error(EGL_BAD_PARAMETER,
- "if level is zero and the texture is incomplete, it must have all of "
- "its faces specified at level zero.");
+ return EglBadParameter() << "if level is zero and the texture is incomplete, "
+ "it must have all of its faces specified at level "
+ "zero.";
}
}
break;
@@ -893,58 +1449,45 @@ Error ValidateCreateImageKHR(const Display *display,
{
if (!displayExtensions.glTexture3DImage)
{
- return Error(EGL_BAD_PARAMETER, "KHR_gl_texture_3D_image not supported.");
+ return EglBadParameter() << "KHR_gl_texture_3D_image not supported.";
}
if (buffer == 0)
{
- return Error(EGL_BAD_PARAMETER,
- "buffer cannot reference a 3D texture with the name 0.");
+ return EglBadParameter() << "buffer cannot reference a 3D texture with the name 0.";
}
const gl::Texture *texture =
context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
if (texture == nullptr || texture->getTarget() != GL_TEXTURE_3D)
{
- return Error(EGL_BAD_PARAMETER, "target is not a 3D texture.");
+ return EglBadParameter() << "target is not a 3D texture.";
}
if (texture->getBoundSurface() != nullptr)
{
- return Error(EGL_BAD_ACCESS, "texture has a surface bound to it.");
+ return EglBadAccess() << "texture has a surface bound to it.";
}
- EGLint level = attributes.get(EGL_GL_TEXTURE_LEVEL_KHR, 0);
- EGLint zOffset = attributes.get(EGL_GL_TEXTURE_ZOFFSET_KHR, 0);
+ EGLAttrib level = attributes.get(EGL_GL_TEXTURE_LEVEL_KHR, 0);
+ EGLAttrib zOffset = attributes.get(EGL_GL_TEXTURE_ZOFFSET_KHR, 0);
if (texture->getWidth(GL_TEXTURE_3D, static_cast<size_t>(level)) == 0 ||
texture->getHeight(GL_TEXTURE_3D, static_cast<size_t>(level)) == 0 ||
texture->getDepth(GL_TEXTURE_3D, static_cast<size_t>(level)) == 0)
{
- return Error(EGL_BAD_PARAMETER,
- "target 3D texture does not have a valid size at specified level.");
+ return EglBadParameter()
+ << "target 3D texture does not have a valid size at specified level.";
}
if (static_cast<size_t>(zOffset) >=
texture->getDepth(GL_TEXTURE_3D, static_cast<size_t>(level)))
{
- return Error(EGL_BAD_PARAMETER,
- "target 3D texture does not have enough layers for the specified Z "
- "offset at the specified level.");
- }
-
- if (level > 0 && (!texture->isMipmapComplete() ||
- static_cast<size_t>(level) >= texture->getMipCompleteLevels()))
- {
- return Error(EGL_BAD_PARAMETER, "texture must be complete if level is non-zero.");
+ return EglBadParameter() << "target 3D texture does not have enough layers "
+ "for the specified Z offset at the specified "
+ "level.";
}
- if (level == 0 && !texture->isMipmapComplete() &&
- TextureHasNonZeroMipLevelsSpecified(context, texture))
- {
- return Error(EGL_BAD_PARAMETER,
- "if level is zero and the texture is incomplete, it must have no mip "
- "levels specified except zero.");
- }
+ ANGLE_TRY(ValidateCreateImageKHRMipLevelCommon(context, texture, level));
}
break;
@@ -952,75 +1495,71 @@ Error ValidateCreateImageKHR(const Display *display,
{
if (!displayExtensions.glRenderbufferImage)
{
- return Error(EGL_BAD_PARAMETER, "KHR_gl_renderbuffer_image not supported.");
+ return EglBadParameter() << "KHR_gl_renderbuffer_image not supported.";
}
if (attributes.contains(EGL_GL_TEXTURE_LEVEL_KHR))
{
- return Error(EGL_BAD_PARAMETER,
- "EGL_GL_TEXTURE_LEVEL_KHR cannot be used in conjunction with a "
- "renderbuffer target.");
+ return EglBadParameter() << "EGL_GL_TEXTURE_LEVEL_KHR cannot be used in "
+ "conjunction with a renderbuffer target.";
}
if (buffer == 0)
{
- return Error(EGL_BAD_PARAMETER,
- "buffer cannot reference a renderbuffer with the name 0.");
+ return EglBadParameter()
+ << "buffer cannot reference a renderbuffer with the name 0.";
}
const gl::Renderbuffer *renderbuffer =
context->getRenderbuffer(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
if (renderbuffer == nullptr)
{
- return Error(EGL_BAD_PARAMETER, "target is not a renderbuffer.");
+ return EglBadParameter() << "target is not a renderbuffer.";
}
if (renderbuffer->getSamples() > 0)
{
- return Error(EGL_BAD_PARAMETER, "target renderbuffer cannot be multisampled.");
+ return EglBadParameter() << "target renderbuffer cannot be multisampled.";
}
}
break;
default:
- return Error(EGL_BAD_PARAMETER, "invalid target: 0x%X", target);
+ return EglBadParameter()
+ << "invalid target: 0x" << std::hex << std::uppercase << target;
}
- return Error(EGL_SUCCESS);
+ return NoError();
}
Error ValidateDestroyImageKHR(const Display *display, const Image *image)
{
- Error error = ValidateImage(display, image);
- if (error.isError())
- {
- return error;
- }
+ ANGLE_TRY(ValidateImage(display, image));
if (!display->getExtensions().imageBase && !display->getExtensions().image)
{
// It is out of spec what happens when calling an extension function when the extension is
// not available.
// EGL_BAD_DISPLAY seems like a reasonable error.
- return Error(EGL_BAD_DISPLAY);
+ return EglBadDisplay();
}
- return Error(EGL_SUCCESS);
+ return NoError();
}
Error ValidateCreateDeviceANGLE(EGLint device_type,
void *native_device,
const EGLAttrib *attrib_list)
{
- const ClientExtensions &clientExtensions = Display::getClientExtensions();
+ const ClientExtensions &clientExtensions = Display::GetClientExtensions();
if (!clientExtensions.deviceCreation)
{
- return Error(EGL_BAD_ACCESS, "Device creation extension not active");
+ return EglBadAccess() << "Device creation extension not active";
}
if (attrib_list != nullptr && attrib_list[0] != EGL_NONE)
{
- return Error(EGL_BAD_ATTRIBUTE, "Invalid attrib_list parameter");
+ return EglBadAttribute() << "Invalid attrib_list parameter";
}
switch (device_type)
@@ -1028,35 +1567,935 @@ Error ValidateCreateDeviceANGLE(EGLint device_type,
case EGL_D3D11_DEVICE_ANGLE:
if (!clientExtensions.deviceCreationD3D11)
{
- return Error(EGL_BAD_ATTRIBUTE, "D3D11 device creation extension not active");
+ return EglBadAttribute() << "D3D11 device creation extension not active";
}
break;
default:
- return Error(EGL_BAD_ATTRIBUTE, "Invalid device_type parameter");
+ return EglBadAttribute() << "Invalid device_type parameter";
}
- return Error(EGL_SUCCESS);
+ return NoError();
}
Error ValidateReleaseDeviceANGLE(Device *device)
{
- const ClientExtensions &clientExtensions = Display::getClientExtensions();
+ const ClientExtensions &clientExtensions = Display::GetClientExtensions();
if (!clientExtensions.deviceCreation)
{
- return Error(EGL_BAD_ACCESS, "Device creation extension not active");
+ return EglBadAccess() << "Device creation extension not active";
}
if (device == EGL_NO_DEVICE_EXT || !Device::IsValidDevice(device))
{
- return Error(EGL_BAD_DEVICE_EXT, "Invalid device parameter");
+ return EglBadDevice() << "Invalid device parameter";
}
Display *owningDisplay = device->getOwningDisplay();
if (owningDisplay != nullptr)
{
- return Error(EGL_BAD_DEVICE_EXT, "Device must have been created using eglCreateDevice");
+ return EglBadDevice() << "Device must have been created using eglCreateDevice";
+ }
+
+ return NoError();
+}
+
+Error ValidateCreateStreamKHR(const Display *display, const AttributeMap &attributes)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.stream)
+ {
+ return EglBadAlloc() << "Stream extension not active";
+ }
+
+ for (const auto &attributeIter : attributes)
+ {
+ EGLAttrib attribute = attributeIter.first;
+ EGLAttrib value = attributeIter.second;
+
+ ANGLE_TRY(ValidateStreamAttribute(attribute, value, displayExtensions));
+ }
+
+ return NoError();
+}
+
+Error ValidateDestroyStreamKHR(const Display *display, const Stream *stream)
+{
+ ANGLE_TRY(ValidateStream(display, stream));
+ return NoError();
+}
+
+Error ValidateStreamAttribKHR(const Display *display,
+ const Stream *stream,
+ EGLint attribute,
+ EGLint value)
+{
+ ANGLE_TRY(ValidateStream(display, stream));
+
+ if (stream->getState() == EGL_STREAM_STATE_DISCONNECTED_KHR)
+ {
+ return EglBadState() << "Bad stream state";
+ }
+
+ return ValidateStreamAttribute(attribute, value, display->getExtensions());
+}
+
+Error ValidateQueryStreamKHR(const Display *display,
+ const Stream *stream,
+ EGLenum attribute,
+ EGLint *value)
+{
+ ANGLE_TRY(ValidateStream(display, stream));
+
+ switch (attribute)
+ {
+ case EGL_STREAM_STATE_KHR:
+ case EGL_CONSUMER_LATENCY_USEC_KHR:
+ break;
+ case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
+ if (!display->getExtensions().streamConsumerGLTexture)
+ {
+ return EglBadAttribute() << "Consumer GLTexture extension not active";
+ }
+ break;
+ default:
+ return EglBadAttribute() << "Invalid attribute";
}
- return Error(EGL_SUCCESS);
+ return NoError();
}
+
+Error ValidateQueryStreamu64KHR(const Display *display,
+ const Stream *stream,
+ EGLenum attribute,
+ EGLuint64KHR *value)
+{
+ ANGLE_TRY(ValidateStream(display, stream));
+
+ switch (attribute)
+ {
+ case EGL_CONSUMER_FRAME_KHR:
+ case EGL_PRODUCER_FRAME_KHR:
+ break;
+ default:
+ return EglBadAttribute() << "Invalid attribute";
+ }
+
+ return NoError();
}
+
+Error ValidateStreamConsumerGLTextureExternalKHR(const Display *display,
+ gl::Context *context,
+ const Stream *stream)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+ ANGLE_TRY(ValidateContext(display, context));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.streamConsumerGLTexture)
+ {
+ return EglBadAccess() << "Stream consumer extension not active";
+ }
+
+ if (!context->getExtensions().eglStreamConsumerExternal)
+ {
+ return EglBadAccess() << "EGL stream consumer external GL extension not enabled";
+ }
+
+ if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
+ {
+ return EglBadStream() << "Invalid stream";
+ }
+
+ if (stream->getState() != EGL_STREAM_STATE_CREATED_KHR)
+ {
+ return EglBadState() << "Invalid stream state";
+ }
+
+ // Lookup the texture and ensure it is correct
+ gl::Texture *texture = context->getGLState().getTargetTexture(GL_TEXTURE_EXTERNAL_OES);
+ if (texture == nullptr || texture->getId() == 0)
+ {
+ return EglBadAccess() << "No external texture bound";
+ }
+
+ return NoError();
+}
+
+Error ValidateStreamConsumerAcquireKHR(const Display *display,
+ gl::Context *context,
+ const Stream *stream)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.streamConsumerGLTexture)
+ {
+ return EglBadAccess() << "Stream consumer extension not active";
+ }
+
+ if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
+ {
+ return EglBadStream() << "Invalid stream";
+ }
+
+ if (!context)
+ {
+ return EglBadAccess() << "No GL context current to calling thread.";
+ }
+
+ ANGLE_TRY(ValidateContext(display, context));
+
+ if (!stream->isConsumerBoundToContext(context))
+ {
+ return EglBadAccess() << "Current GL context not associated with stream consumer";
+ }
+
+ if (stream->getConsumerType() != Stream::ConsumerType::GLTextureRGB &&
+ stream->getConsumerType() != Stream::ConsumerType::GLTextureYUV)
+ {
+ return EglBadAccess() << "Invalid stream consumer type";
+ }
+
+ // Note: technically EGL_STREAM_STATE_EMPTY_KHR is a valid state when the timeout is non-zero.
+ // However, the timeout is effectively ignored since it has no useful functionality with the
+ // current producers that are implemented, so we don't allow that state
+ if (stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
+ stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
+ {
+ return EglBadState() << "Invalid stream state";
+ }
+
+ return NoError();
+}
+
+Error ValidateStreamConsumerReleaseKHR(const Display *display,
+ gl::Context *context,
+ const Stream *stream)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.streamConsumerGLTexture)
+ {
+ return EglBadAccess() << "Stream consumer extension not active";
+ }
+
+ if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
+ {
+ return EglBadStream() << "Invalid stream";
+ }
+
+ if (!context)
+ {
+ return EglBadAccess() << "No GL context current to calling thread.";
+ }
+
+ ANGLE_TRY(ValidateContext(display, context));
+
+ if (!stream->isConsumerBoundToContext(context))
+ {
+ return EglBadAccess() << "Current GL context not associated with stream consumer";
+ }
+
+ if (stream->getConsumerType() != Stream::ConsumerType::GLTextureRGB &&
+ stream->getConsumerType() != Stream::ConsumerType::GLTextureYUV)
+ {
+ return EglBadAccess() << "Invalid stream consumer type";
+ }
+
+ if (stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
+ stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
+ {
+ return EglBadState() << "Invalid stream state";
+ }
+
+ return NoError();
+}
+
+Error ValidateStreamConsumerGLTextureExternalAttribsNV(const Display *display,
+ gl::Context *context,
+ const Stream *stream,
+ const AttributeMap &attribs)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.streamConsumerGLTexture)
+ {
+ return EglBadAccess() << "Stream consumer extension not active";
+ }
+
+ // Although technically not a requirement in spec, the context needs to be checked for support
+ // for external textures or future logic will cause assertations. This extension is also
+ // effectively useless without external textures.
+ if (!context->getExtensions().eglStreamConsumerExternal)
+ {
+ return EglBadAccess() << "EGL stream consumer external GL extension not enabled";
+ }
+
+ if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
+ {
+ return EglBadStream() << "Invalid stream";
+ }
+
+ if (!context)
+ {
+ return EglBadAccess() << "No GL context current to calling thread.";
+ }
+
+ ANGLE_TRY(ValidateContext(display, context));
+
+ if (stream->getState() != EGL_STREAM_STATE_CREATED_KHR)
+ {
+ return EglBadState() << "Invalid stream state";
+ }
+
+ const gl::Caps &glCaps = context->getCaps();
+
+ EGLAttrib colorBufferType = EGL_RGB_BUFFER;
+ EGLAttrib planeCount = -1;
+ EGLAttrib plane[3];
+ for (int i = 0; i < 3; i++)
+ {
+ plane[i] = -1;
+ }
+ for (const auto &attributeIter : attribs)
+ {
+ EGLAttrib attribute = attributeIter.first;
+ EGLAttrib value = attributeIter.second;
+
+ switch (attribute)
+ {
+ case EGL_COLOR_BUFFER_TYPE:
+ if (value != EGL_RGB_BUFFER && value != EGL_YUV_BUFFER_EXT)
+ {
+ return EglBadParameter() << "Invalid color buffer type";
+ }
+ colorBufferType = value;
+ break;
+ case EGL_YUV_NUMBER_OF_PLANES_EXT:
+ // planeCount = -1 is a tag for the default plane count so the value must be checked
+ // to be positive here to ensure future logic doesn't break on invalid negative
+ // inputs
+ if (value < 0)
+ {
+ return EglBadMatch() << "Invalid plane count";
+ }
+ planeCount = value;
+ break;
+ default:
+ if (attribute >= EGL_YUV_PLANE0_TEXTURE_UNIT_NV &&
+ attribute <= EGL_YUV_PLANE2_TEXTURE_UNIT_NV)
+ {
+ if ((value < 0 ||
+ value >= static_cast<EGLAttrib>(glCaps.maxCombinedTextureImageUnits)) &&
+ value != EGL_NONE)
+ {
+ return EglBadAccess() << "Invalid texture unit";
+ }
+ plane[attribute - EGL_YUV_PLANE0_TEXTURE_UNIT_NV] = value;
+ }
+ else
+ {
+ return EglBadAttribute() << "Invalid attribute";
+ }
+ }
+ }
+
+ if (colorBufferType == EGL_RGB_BUFFER)
+ {
+ if (planeCount > 0)
+ {
+ return EglBadMatch() << "Plane count must be 0 for RGB buffer";
+ }
+ for (int i = 0; i < 3; i++)
+ {
+ if (plane[i] != -1)
+ {
+ return EglBadMatch() << "Planes cannot be specified";
+ }
+ }
+
+ // Lookup the texture and ensure it is correct
+ gl::Texture *texture = context->getGLState().getTargetTexture(GL_TEXTURE_EXTERNAL_OES);
+ if (texture == nullptr || texture->getId() == 0)
+ {
+ return EglBadAccess() << "No external texture bound";
+ }
+ }
+ else
+ {
+ if (planeCount == -1)
+ {
+ planeCount = 2;
+ }
+ if (planeCount < 1 || planeCount > 3)
+ {
+ return EglBadMatch() << "Invalid YUV plane count";
+ }
+ for (EGLAttrib i = planeCount; i < 3; i++)
+ {
+ if (plane[i] != -1)
+ {
+ return EglBadMatch() << "Invalid plane specified";
+ }
+ }
+
+ // Set to ensure no texture is referenced more than once
+ std::set<gl::Texture *> textureSet;
+ for (EGLAttrib i = 0; i < planeCount; i++)
+ {
+ if (plane[i] == -1)
+ {
+ return EglBadMatch() << "Not all planes specified";
+ }
+ if (plane[i] != EGL_NONE)
+ {
+ gl::Texture *texture = context->getGLState().getSamplerTexture(
+ static_cast<unsigned int>(plane[i]), GL_TEXTURE_EXTERNAL_OES);
+ if (texture == nullptr || texture->getId() == 0)
+ {
+ return EglBadAccess()
+ << "No external texture bound at one or more specified texture units";
+ }
+ if (textureSet.find(texture) != textureSet.end())
+ {
+ return EglBadAccess() << "Multiple planes bound to same texture object";
+ }
+ textureSet.insert(texture);
+ }
+ }
+ }
+
+ return NoError();
+}
+
+Error ValidateCreateStreamProducerD3DTextureNV12ANGLE(const Display *display,
+ const Stream *stream,
+ const AttributeMap &attribs)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.streamProducerD3DTextureNV12)
+ {
+ return EglBadAccess() << "Stream producer extension not active";
+ }
+
+ ANGLE_TRY(ValidateStream(display, stream));
+
+ if (!attribs.isEmpty())
+ {
+ return EglBadAttribute() << "Invalid attribute";
+ }
+
+ if (stream->getState() != EGL_STREAM_STATE_CONNECTING_KHR)
+ {
+ return EglBadState() << "Stream not in connecting state";
+ }
+
+ if (stream->getConsumerType() != Stream::ConsumerType::GLTextureYUV ||
+ stream->getPlaneCount() != 2)
+ {
+ return EglBadMatch() << "Incompatible stream consumer type";
+ }
+
+ return NoError();
+}
+
+Error ValidateStreamPostD3DTextureNV12ANGLE(const Display *display,
+ const Stream *stream,
+ void *texture,
+ const AttributeMap &attribs)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.streamProducerD3DTextureNV12)
+ {
+ return EglBadAccess() << "Stream producer extension not active";
+ }
+
+ ANGLE_TRY(ValidateStream(display, stream));
+
+ for (auto &attributeIter : attribs)
+ {
+ EGLAttrib attribute = attributeIter.first;
+ EGLAttrib value = attributeIter.second;
+
+ switch (attribute)
+ {
+ case EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE:
+ if (value < 0)
+ {
+ return EglBadParameter() << "Invalid subresource index";
+ }
+ break;
+ default:
+ return EglBadAttribute() << "Invalid attribute";
+ }
+ }
+
+ if (stream->getState() != EGL_STREAM_STATE_EMPTY_KHR &&
+ stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
+ stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
+ {
+ return EglBadState() << "Stream not fully configured";
+ }
+
+ if (stream->getProducerType() != Stream::ProducerType::D3D11TextureNV12)
+ {
+ return EglBadMatch() << "Incompatible stream producer";
+ }
+
+ if (texture == nullptr)
+ {
+ return EglBadParameter() << "Texture is null";
+ }
+
+ return stream->validateD3D11NV12Texture(texture);
+}
+
+Error ValidateGetSyncValuesCHROMIUM(const Display *display,
+ const Surface *surface,
+ const EGLuint64KHR *ust,
+ const EGLuint64KHR *msc,
+ const EGLuint64KHR *sbc)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.getSyncValues)
+ {
+ return EglBadAccess() << "getSyncValues extension not active";
+ }
+
+ if (display->isDeviceLost())
+ {
+ return EglContextLost() << "Context is lost.";
+ }
+
+ if (surface == EGL_NO_SURFACE)
+ {
+ return EglBadSurface() << "getSyncValues surface cannot be EGL_NO_SURFACE";
+ }
+
+ if (!surface->directComposition())
+ {
+ return EglBadSurface() << "getSyncValues surface requires Direct Composition to be enabled";
+ }
+
+ if (ust == nullptr)
+ {
+ return EglBadParameter() << "ust is null";
+ }
+
+ if (msc == nullptr)
+ {
+ return EglBadParameter() << "msc is null";
+ }
+
+ if (sbc == nullptr)
+ {
+ return EglBadParameter() << "sbc is null";
+ }
+
+ return NoError();
+}
+
+Error ValidateSwapBuffersWithDamageEXT(const Display *display,
+ const Surface *surface,
+ EGLint *rects,
+ EGLint n_rects)
+{
+ Error error = ValidateSurface(display, surface);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (!display->getExtensions().swapBuffersWithDamage)
+ {
+ // It is out of spec what happens when calling an extension function when the extension is
+ // not available. EGL_BAD_DISPLAY seems like a reasonable error.
+ return EglBadDisplay() << "EGL_EXT_swap_buffers_with_damage is not available.";
+ }
+
+ if (surface == EGL_NO_SURFACE)
+ {
+ return EglBadSurface() << "Swap surface cannot be EGL_NO_SURFACE.";
+ }
+
+ if (n_rects < 0)
+ {
+ return EglBadParameter() << "n_rects cannot be negative.";
+ }
+
+ if (n_rects > 0 && rects == nullptr)
+ {
+ return EglBadParameter() << "n_rects cannot be greater than zero when rects is NULL.";
+ }
+
+ // TODO(jmadill): Validate Surface is bound to the thread.
+
+ return NoError();
+}
+
+Error ValidateGetConfigAttrib(const Display *display, const Config *config, EGLint attribute)
+{
+ ANGLE_TRY(ValidateConfig(display, config));
+ ANGLE_TRY(ValidateConfigAttribute(display, static_cast<EGLAttrib>(attribute)));
+ return NoError();
+}
+
+Error ValidateChooseConfig(const Display *display,
+ const AttributeMap &attribs,
+ EGLint configSize,
+ EGLint *numConfig)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+ ANGLE_TRY(ValidateConfigAttributes(display, attribs));
+
+ if (numConfig == nullptr)
+ {
+ return EglBadParameter() << "num_config cannot be null.";
+ }
+
+ return NoError();
+}
+
+Error ValidateGetConfigs(const Display *display, EGLint configSize, EGLint *numConfig)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+
+ if (numConfig == nullptr)
+ {
+ return EglBadParameter() << "num_config cannot be null.";
+ }
+
+ return NoError();
+}
+
+Error ValidateGetPlatformDisplay(EGLenum platform,
+ void *native_display,
+ const EGLAttrib *attrib_list)
+{
+ const auto &attribMap = AttributeMap::CreateFromAttribArray(attrib_list);
+ return ValidateGetPlatformDisplayCommon(platform, native_display, attribMap);
+}
+
+Error ValidateGetPlatformDisplayEXT(EGLenum platform,
+ void *native_display,
+ const EGLint *attrib_list)
+{
+ const auto &attribMap = AttributeMap::CreateFromIntArray(attrib_list);
+ return ValidateGetPlatformDisplayCommon(platform, native_display, attribMap);
+}
+
+Error ValidateProgramCacheGetAttribANGLE(const Display *display, EGLenum attrib)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+
+ if (!display->getExtensions().programCacheControl)
+ {
+ return EglBadAccess() << "Extension not supported";
+ }
+
+ switch (attrib)
+ {
+ case EGL_PROGRAM_CACHE_KEY_LENGTH_ANGLE:
+ case EGL_PROGRAM_CACHE_SIZE_ANGLE:
+ break;
+
+ default:
+ return EglBadParameter() << "Invalid program cache attribute.";
+ }
+
+ return NoError();
+}
+
+Error ValidateProgramCacheQueryANGLE(const Display *display,
+ EGLint index,
+ void *key,
+ EGLint *keysize,
+ void *binary,
+ EGLint *binarysize)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+
+ if (!display->getExtensions().programCacheControl)
+ {
+ return EglBadAccess() << "Extension not supported";
+ }
+
+ if (index < 0 || index >= display->programCacheGetAttrib(EGL_PROGRAM_CACHE_SIZE_ANGLE))
+ {
+ return EglBadParameter() << "Program index out of range.";
+ }
+
+ if (keysize == nullptr || binarysize == nullptr)
+ {
+ return EglBadParameter() << "keysize and binarysize must always be valid pointers.";
+ }
+
+ if (binary && *keysize != static_cast<EGLint>(gl::kProgramHashLength))
+ {
+ return EglBadParameter() << "Invalid program key size.";
+ }
+
+ if ((key == nullptr) != (binary == nullptr))
+ {
+ return EglBadParameter() << "key and binary must both be null or both non-null.";
+ }
+
+ return NoError();
+}
+
+Error ValidateProgramCachePopulateANGLE(const Display *display,
+ const void *key,
+ EGLint keysize,
+ const void *binary,
+ EGLint binarysize)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+
+ if (!display->getExtensions().programCacheControl)
+ {
+ return EglBadAccess() << "Extension not supported";
+ }
+
+ if (keysize != static_cast<EGLint>(gl::kProgramHashLength))
+ {
+ return EglBadParameter() << "Invalid program key size.";
+ }
+
+ if (key == nullptr || binary == nullptr)
+ {
+ return EglBadParameter() << "null pointer in arguments.";
+ }
+
+ // Upper bound for binarysize is arbitrary.
+ if (binarysize <= 0 || binarysize > egl::kProgramCacheSizeAbsoluteMax)
+ {
+ return EglBadParameter() << "binarysize out of valid range.";
+ }
+
+ return NoError();
+}
+
+Error ValidateProgramCacheResizeANGLE(const Display *display, EGLint limit, EGLenum mode)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+
+ if (!display->getExtensions().programCacheControl)
+ {
+ return EglBadAccess() << "Extension not supported";
+ }
+
+ if (limit < 0)
+ {
+ return EglBadParameter() << "limit must be non-negative.";
+ }
+
+ switch (mode)
+ {
+ case EGL_PROGRAM_CACHE_RESIZE_ANGLE:
+ case EGL_PROGRAM_CACHE_TRIM_ANGLE:
+ break;
+
+ default:
+ return EglBadParameter() << "Invalid cache resize mode.";
+ }
+
+ return NoError();
+}
+
+Error ValidateSurfaceAttrib(const Display *display,
+ const Surface *surface,
+ EGLint attribute,
+ EGLint value)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+ ANGLE_TRY(ValidateSurface(display, surface));
+
+ if (surface == EGL_NO_SURFACE)
+ {
+ return EglBadSurface() << "Surface cannot be EGL_NO_SURFACE.";
+ }
+
+ switch (attribute)
+ {
+ case EGL_MIPMAP_LEVEL:
+ break;
+
+ case EGL_MULTISAMPLE_RESOLVE:
+ switch (value)
+ {
+ case EGL_MULTISAMPLE_RESOLVE_DEFAULT:
+ break;
+
+ case EGL_MULTISAMPLE_RESOLVE_BOX:
+ if ((surface->getConfig()->surfaceType & EGL_MULTISAMPLE_RESOLVE_BOX_BIT) == 0)
+ {
+ return EglBadMatch()
+ << "Surface does not support EGL_MULTISAMPLE_RESOLVE_BOX.";
+ }
+ break;
+
+ default:
+ return EglBadAttribute() << "Invalid multisample resolve type.";
+ }
+
+ case EGL_SWAP_BEHAVIOR:
+ switch (value)
+ {
+ case EGL_BUFFER_PRESERVED:
+ if ((surface->getConfig()->surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) == 0)
+ {
+ return EglBadMatch()
+ << "Surface does not support EGL_SWAP_BEHAVIOR_PRESERVED.";
+ }
+ break;
+
+ case EGL_BUFFER_DESTROYED:
+ break;
+
+ default:
+ return EglBadAttribute() << "Invalid swap behaviour.";
+ }
+
+ default:
+ return EglBadAttribute() << "Invalid surface attribute.";
+ }
+
+ return NoError();
+}
+
+Error ValidateQuerySurface(const Display *display,
+ const Surface *surface,
+ EGLint attribute,
+ EGLint *value)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+ ANGLE_TRY(ValidateSurface(display, surface));
+
+ if (surface == EGL_NO_SURFACE)
+ {
+ return EglBadSurface() << "Surface cannot be EGL_NO_SURFACE.";
+ }
+
+ switch (attribute)
+ {
+ case EGL_GL_COLORSPACE:
+ case EGL_VG_ALPHA_FORMAT:
+ case EGL_VG_COLORSPACE:
+ case EGL_CONFIG_ID:
+ case EGL_HEIGHT:
+ case EGL_HORIZONTAL_RESOLUTION:
+ case EGL_LARGEST_PBUFFER:
+ case EGL_MIPMAP_TEXTURE:
+ case EGL_MIPMAP_LEVEL:
+ case EGL_MULTISAMPLE_RESOLVE:
+ case EGL_PIXEL_ASPECT_RATIO:
+ case EGL_RENDER_BUFFER:
+ case EGL_SWAP_BEHAVIOR:
+ case EGL_TEXTURE_FORMAT:
+ case EGL_TEXTURE_TARGET:
+ case EGL_VERTICAL_RESOLUTION:
+ case EGL_WIDTH:
+ break;
+
+ case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
+ if (!display->getExtensions().postSubBuffer)
+ {
+ return EglBadAttribute() << "EGL_POST_SUB_BUFFER_SUPPORTED_NV cannot be used "
+ "without EGL_ANGLE_surface_orientation support.";
+ }
+ break;
+
+ case EGL_FIXED_SIZE_ANGLE:
+ if (!display->getExtensions().windowFixedSize)
+ {
+ return EglBadAttribute() << "EGL_FIXED_SIZE_ANGLE cannot be used without "
+ "EGL_ANGLE_window_fixed_size support.";
+ }
+ break;
+
+ case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
+ if (!display->getExtensions().flexibleSurfaceCompatibility)
+ {
+ return EglBadAttribute()
+ << "EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE cannot be "
+ "used without EGL_ANGLE_flexible_surface_compatibility support.";
+ }
+ break;
+
+ case EGL_SURFACE_ORIENTATION_ANGLE:
+ if (!display->getExtensions().surfaceOrientation)
+ {
+ return EglBadAttribute() << "EGL_SURFACE_ORIENTATION_ANGLE cannot be "
+ "queried without "
+ "EGL_ANGLE_surface_orientation support.";
+ }
+ break;
+
+ case EGL_DIRECT_COMPOSITION_ANGLE:
+ if (!display->getExtensions().directComposition)
+ {
+ return EglBadAttribute() << "EGL_DIRECT_COMPOSITION_ANGLE cannot be "
+ "used without "
+ "EGL_ANGLE_direct_composition support.";
+ }
+ break;
+
+ case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ if (!display->getExtensions().robustResourceInitialization)
+ {
+ return EglBadAttribute() << "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE cannot be "
+ "used without EGL_ANGLE_robust_resource_initialization "
+ "support.";
+ }
+ break;
+
+ default:
+ return EglBadAttribute() << "Invalid surface attribute.";
+ }
+
+ return NoError();
+}
+
+Error ValidateQueryContext(const Display *display,
+ const gl::Context *context,
+ EGLint attribute,
+ EGLint *value)
+{
+ ANGLE_TRY(ValidateDisplay(display));
+ ANGLE_TRY(ValidateContext(display, context));
+
+ switch (attribute)
+ {
+ case EGL_CONFIG_ID:
+ case EGL_CONTEXT_CLIENT_TYPE:
+ case EGL_CONTEXT_CLIENT_VERSION:
+ case EGL_RENDER_BUFFER:
+ break;
+
+ case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ if (!display->getExtensions().robustResourceInitialization)
+ {
+ return EglBadAttribute() << "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE cannot be "
+ "used without EGL_ANGLE_robust_resource_initialization "
+ "support.";
+ }
+ break;
+
+ default:
+ return EglBadAttribute() << "Invalid context attribute.";
+ }
+
+ return NoError();
+}
+
+} // namespace egl
diff --git a/src/3rdparty/angle/src/libANGLE/validationEGL.h b/src/3rdparty/angle/src/libANGLE/validationEGL.h
index eaafddc20d..3ab8232c7f 100644
--- a/src/3rdparty/angle/src/libANGLE/validationEGL.h
+++ b/src/3rdparty/angle/src/libANGLE/validationEGL.h
@@ -12,6 +12,7 @@
#include "libANGLE/Error.h"
#include <EGL/egl.h>
+#include <EGL/eglext.h>
namespace gl
{
@@ -22,17 +23,19 @@ namespace egl
{
class AttributeMap;
+struct ClientExtensions;
struct Config;
class Device;
class Display;
class Image;
+class Stream;
class Surface;
// Object validation
Error ValidateDisplay(const Display *display);
-Error ValidateSurface(const Display *display, Surface *surface);
+Error ValidateSurface(const Display *display, const Surface *surface);
Error ValidateConfig(const Display *display, const Config *config);
-Error ValidateContext(const Display *display, gl::Context *context);
+Error ValidateContext(const Display *display, const gl::Context *context);
Error ValidateImage(const Display *display, const Image *image);
// Entry point validation
@@ -46,6 +49,8 @@ Error ValidateCreatePbufferSurface(Display *display, Config *config, const Attri
Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, EGLClientBuffer buffer,
Config *config, const AttributeMap& attributes);
+Error ValidateMakeCurrent(Display *display, EGLSurface draw, EGLSurface read, gl::Context *context);
+
Error ValidateCreateImageKHR(const Display *display,
gl::Context *context,
EGLenum target,
@@ -58,12 +63,120 @@ Error ValidateCreateDeviceANGLE(EGLint device_type,
const EGLAttrib *attrib_list);
Error ValidateReleaseDeviceANGLE(Device *device);
+Error ValidateCreateStreamKHR(const Display *display, const AttributeMap &attributes);
+Error ValidateDestroyStreamKHR(const Display *display, const Stream *stream);
+Error ValidateStreamAttribKHR(const Display *display,
+ const Stream *stream,
+ EGLint attribute,
+ EGLint value);
+Error ValidateQueryStreamKHR(const Display *display,
+ const Stream *stream,
+ EGLenum attribute,
+ EGLint *value);
+Error ValidateQueryStreamu64KHR(const Display *display,
+ const Stream *stream,
+ EGLenum attribute,
+ EGLuint64KHR *value);
+Error ValidateStreamConsumerGLTextureExternalKHR(const Display *display,
+ gl::Context *context,
+ const Stream *stream);
+Error ValidateStreamConsumerAcquireKHR(const Display *display,
+ gl::Context *context,
+ const Stream *stream);
+Error ValidateStreamConsumerReleaseKHR(const Display *display,
+ gl::Context *context,
+ const Stream *stream);
+Error ValidateStreamConsumerGLTextureExternalAttribsNV(const Display *display,
+ gl::Context *context,
+ const Stream *stream,
+ const AttributeMap &attribs);
+Error ValidateCreateStreamProducerD3DTextureNV12ANGLE(const Display *display,
+ const Stream *stream,
+ const AttributeMap &attribs);
+Error ValidateStreamPostD3DTextureNV12ANGLE(const Display *display,
+ const Stream *stream,
+ void *texture,
+ const AttributeMap &attribs);
+
+Error ValidateGetSyncValuesCHROMIUM(const Display *display,
+ const Surface *surface,
+ const EGLuint64KHR *ust,
+ const EGLuint64KHR *msc,
+ const EGLuint64KHR *sbc);
+
+Error ValidateSwapBuffersWithDamageEXT(const Display *display,
+ const Surface *surface,
+ EGLint *rects,
+ EGLint n_rects);
+
+Error ValidateGetConfigAttrib(const Display *display, const Config *config, EGLint attribute);
+Error ValidateChooseConfig(const Display *display,
+ const AttributeMap &attribs,
+ EGLint configSize,
+ EGLint *numConfig);
+Error ValidateGetConfigs(const Display *display, EGLint configSize, EGLint *numConfig);
+
// Other validation
Error ValidateCompatibleConfigs(const Display *display,
const Config *config1,
const Surface *surface,
const Config *config2,
EGLint surfaceType);
-}
+
+Error ValidateGetPlatformDisplay(EGLenum platform,
+ void *native_display,
+ const EGLAttrib *attrib_list);
+Error ValidateGetPlatformDisplayEXT(EGLenum platform,
+ void *native_display,
+ const EGLint *attrib_list);
+
+Error ValidateProgramCacheGetAttribANGLE(const Display *display, EGLenum attrib);
+
+Error ValidateProgramCacheQueryANGLE(const Display *display,
+ EGLint index,
+ void *key,
+ EGLint *keysize,
+ void *binary,
+ EGLint *binarysize);
+
+Error ValidateProgramCachePopulateANGLE(const Display *display,
+ const void *key,
+ EGLint keysize,
+ const void *binary,
+ EGLint binarysize);
+
+Error ValidateProgramCacheResizeANGLE(const Display *display, EGLint limit, EGLenum mode);
+
+Error ValidateSurfaceAttrib(const Display *display,
+ const Surface *surface,
+ EGLint attribute,
+ EGLint value);
+Error ValidateQuerySurface(const Display *display,
+ const Surface *surface,
+ EGLint attribute,
+ EGLint *value);
+Error ValidateQueryContext(const Display *display,
+ const gl::Context *context,
+ EGLint attribute,
+ EGLint *value);
+
+} // namespace egl
+
+#define ANGLE_EGL_TRY(THREAD, EXPR) \
+ { \
+ auto ANGLE_LOCAL_VAR = (EXPR); \
+ if (ANGLE_LOCAL_VAR.isError()) \
+ return THREAD->setError(ANGLE_LOCAL_VAR); \
+ }
+
+#define ANGLE_EGL_TRY_RETURN(THREAD, EXPR, RETVAL) \
+ { \
+ auto ANGLE_LOCAL_VAR = (EXPR); \
+ if (ANGLE_LOCAL_VAR.isError()) \
+ { \
+ THREAD->setError(ANGLE_LOCAL_VAR); \
+ return RETVAL; \
+ } \
+ }
#endif // LIBANGLE_VALIDATIONEGL_H_
diff --git a/src/3rdparty/angle/src/libANGLE/validationES.cpp b/src/3rdparty/angle/src/libANGLE/validationES.cpp
index 12c76120bd..ae564b7412 100644
--- a/src/3rdparty/angle/src/libANGLE/validationES.cpp
+++ b/src/3rdparty/angle/src/libANGLE/validationES.cpp
@@ -7,136 +7,469 @@
// validationES.h: Validation functions for generic OpenGL ES entry point parameters
#include "libANGLE/validationES.h"
-#include "libANGLE/validationES2.h"
-#include "libANGLE/validationES3.h"
+
#include "libANGLE/Context.h"
#include "libANGLE/Display.h"
-#include "libANGLE/Texture.h"
+#include "libANGLE/ErrorStrings.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/FramebufferAttachment.h"
-#include "libANGLE/formatutils.h"
#include "libANGLE/Image.h"
-#include "libANGLE/Query.h"
#include "libANGLE/Program.h"
-#include "libANGLE/Uniform.h"
+#include "libANGLE/Query.h"
+#include "libANGLE/Texture.h"
#include "libANGLE/TransformFeedback.h"
#include "libANGLE/VertexArray.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/queryconversions.h"
+#include "libANGLE/validationES2.h"
+#include "libANGLE/validationES3.h"
#include "common/mathutil.h"
#include "common/utilities.h"
+using namespace angle;
+
namespace gl
{
-const char *g_ExceedsMaxElementErrorMessage = "Element value exceeds maximum element index.";
-
namespace
{
-bool ValidateDrawAttribs(ValidationContext *context, GLint primcount, GLint maxVertex)
+
+bool ValidateDrawAttribs(ValidationContext *context,
+ GLint primcount,
+ GLint maxVertex,
+ GLint vertexCount)
{
- const gl::State &state = context->getState();
+ const gl::State &state = context->getGLState();
const gl::Program *program = state.getProgram();
+ bool webglCompatibility = context->getExtensions().webglCompatibility;
+
const VertexArray *vao = state.getVertexArray();
const auto &vertexAttribs = vao->getVertexAttributes();
- size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
+ const auto &vertexBindings = vao->getVertexBindings();
+ size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
{
const VertexAttribute &attrib = vertexAttribs[attributeIndex];
- if (program->isAttribLocationActive(attributeIndex) && attrib.enabled)
+
+ // No need to range check for disabled attribs.
+ if (!attrib.enabled)
{
- gl::Buffer *buffer = attrib.buffer.get();
+ continue;
+ }
- if (buffer)
+ // If we have no buffer, then we either get an error, or there are no more checks to be
+ // done.
+ const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
+ gl::Buffer *buffer = binding.getBuffer().get();
+ if (!buffer)
+ {
+ if (webglCompatibility || !state.areClientArraysEnabled())
{
- GLint64 attribStride = static_cast<GLint64>(ComputeVertexAttributeStride(attrib));
- GLint64 maxVertexElement = 0;
-
- if (attrib.divisor > 0)
- {
- maxVertexElement =
- static_cast<GLint64>(primcount) / static_cast<GLint64>(attrib.divisor);
- }
- else
- {
- maxVertexElement = static_cast<GLint64>(maxVertex);
- }
-
- // If we're drawing zero vertices, we have enough data.
- if (maxVertexElement > 0)
- {
- // Note: Last vertex element does not take the full stride!
- GLint64 attribSize =
- static_cast<GLint64>(ComputeVertexAttributeTypeSize(attrib));
- GLint64 attribDataSize = (maxVertexElement - 1) * attribStride + attribSize;
-
- // [OpenGL ES 3.0.2] section 2.9.4 page 40:
- // We can return INVALID_OPERATION if our vertex attribute does not have
- // enough backing data.
- if (attribDataSize > buffer->getSize())
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- }
+ // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
+ // If a vertex attribute is enabled as an array via enableVertexAttribArray but
+ // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
+ // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
+ // error.
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
+ return false;
}
- else if (attrib.pointer == NULL)
+ else if (attrib.pointer == nullptr)
{
// This is an application error that would normally result in a crash,
// but we catch it and return an error
- context->recordError(Error(
- GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer."));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
return false;
}
+ continue;
+ }
+
+ // This needs to come after the check for client arrays as even unused attributes cannot use
+ // client-side arrays
+ if (!program->isAttribLocationActive(attributeIndex))
+ {
+ continue;
+ }
+
+ // If we're drawing zero vertices, we have enough data.
+ if (vertexCount <= 0 || primcount <= 0)
+ {
+ continue;
+ }
+
+ GLint maxVertexElement = 0;
+ GLuint divisor = binding.getDivisor();
+ if (divisor == 0)
+ {
+ maxVertexElement = maxVertex;
+ }
+ else
+ {
+ maxVertexElement = (primcount - 1) / divisor;
+ }
+
+ // We do manual overflow checks here instead of using safe_math.h because it was
+ // a bottleneck. Thanks to some properties of GL we know inequalities that can
+ // help us make the overflow checks faster.
+
+ // The max possible attribSize is 16 for a vector of 4 32 bit values.
+ constexpr uint64_t kMaxAttribSize = 16;
+ constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
+ constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
+
+ // We know attribStride is given as a GLsizei which is typedefed to int.
+ // We also know an upper bound for attribSize.
+ static_assert(std::is_same<int, GLsizei>::value, "");
+ uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
+ uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
+ ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
+
+ // Computing the max offset using uint64_t without attrib.offset is overflow
+ // safe. Note: Last vertex element does not take the full stride!
+ static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
+ uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
+
+ // An overflow can happen when adding the offset, check for it.
+ uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
+ if (attribDataSizeNoOffset > kUint64Max - attribOffset)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
+ return false;
+ }
+ uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
+
+ // [OpenGL ES 3.0.2] section 2.9.4 page 40:
+ // We can return INVALID_OPERATION if our vertex attribute does not have
+ // enough backing data.
+ if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
+ return false;
}
}
return true;
}
-} // anonymous namespace
+bool ValidReadPixelsTypeEnum(ValidationContext *context, GLenum type)
+{
+ switch (type)
+ {
+ // Types referenced in Table 3.4 of the ES 2.0.25 spec
+ case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL_UNSIGNED_SHORT_5_6_5:
+ return context->getClientVersion() >= ES_2_0;
+
+ // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
+ case GL_BYTE:
+ case GL_INT:
+ case GL_SHORT:
+ case GL_UNSIGNED_INT:
+ case GL_UNSIGNED_INT_10F_11F_11F_REV:
+ case GL_UNSIGNED_INT_24_8:
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ case GL_UNSIGNED_INT_5_9_9_9_REV:
+ case GL_UNSIGNED_SHORT:
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+ return context->getClientVersion() >= ES_3_0;
+
+ case GL_FLOAT:
+ return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
+ context->getExtensions().colorBufferHalfFloat;
+
+ case GL_HALF_FLOAT:
+ return context->getClientVersion() >= ES_3_0 ||
+ context->getExtensions().textureHalfFloat;
+
+ case GL_HALF_FLOAT_OES:
+ return context->getExtensions().colorBufferHalfFloat;
+
+ default:
+ return false;
+ }
+}
+
+bool ValidReadPixelsFormatEnum(ValidationContext *context, GLenum format)
+{
+ switch (format)
+ {
+ // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
+ case GL_RGBA:
+ case GL_RGB:
+ case GL_ALPHA:
+ return context->getClientVersion() >= ES_2_0;
+
+ // Formats referenced in Table 3.2 of the ES 3.0.5 spec
+ case GL_RG:
+ case GL_RED:
+ case GL_RGBA_INTEGER:
+ case GL_RGB_INTEGER:
+ case GL_RG_INTEGER:
+ case GL_RED_INTEGER:
+ return context->getClientVersion() >= ES_3_0;
+
+ case GL_SRGB_ALPHA_EXT:
+ case GL_SRGB_EXT:
+ return context->getExtensions().sRGB;
+
+ case GL_BGRA_EXT:
+ return context->getExtensions().readFormatBGRA;
+
+ default:
+ return false;
+ }
+}
-bool ValidCap(const Context *context, GLenum cap)
+bool ValidReadPixelsFormatType(ValidationContext *context,
+ GLenum framebufferComponentType,
+ GLenum format,
+ GLenum type)
{
- switch (cap)
+ switch (framebufferComponentType)
{
- case GL_CULL_FACE:
- case GL_POLYGON_OFFSET_FILL:
- case GL_SAMPLE_ALPHA_TO_COVERAGE:
- case GL_SAMPLE_COVERAGE:
- case GL_SCISSOR_TEST:
- case GL_STENCIL_TEST:
- case GL_DEPTH_TEST:
- case GL_BLEND:
- case GL_DITHER:
- return true;
+ case GL_UNSIGNED_NORMALIZED:
+ // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
+ // ReadPixels with BGRA even if the extension is not present
+ return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
+ (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
+ type == GL_UNSIGNED_BYTE);
- case GL_PRIMITIVE_RESTART_FIXED_INDEX:
- case GL_RASTERIZER_DISCARD:
- return (context->getClientVersion() >= 3);
+ case GL_SIGNED_NORMALIZED:
+ return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
- case GL_DEBUG_OUTPUT_SYNCHRONOUS:
- case GL_DEBUG_OUTPUT:
- return context->getExtensions().debug;
+ case GL_INT:
+ return (format == GL_RGBA_INTEGER && type == GL_INT);
- default:
+ case GL_UNSIGNED_INT:
+ return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
+
+ case GL_FLOAT:
+ return (format == GL_RGBA && type == GL_FLOAT);
+
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+template <typename ParamType>
+bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
+{
+ switch (ConvertToGLenum(params[0]))
+ {
+ case GL_CLAMP_TO_EDGE:
+ break;
+
+ case GL_REPEAT:
+ case GL_MIRRORED_REPEAT:
+ if (restrictedWrapModes)
+ {
+ // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
+ return false;
+ }
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
+ return false;
+ }
+
+ return true;
+}
+
+template <typename ParamType>
+bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
+{
+ switch (ConvertToGLenum(params[0]))
+ {
+ case GL_NEAREST:
+ case GL_LINEAR:
+ break;
+
+ case GL_NEAREST_MIPMAP_NEAREST:
+ case GL_LINEAR_MIPMAP_NEAREST:
+ case GL_NEAREST_MIPMAP_LINEAR:
+ case GL_LINEAR_MIPMAP_LINEAR:
+ if (restrictedMinFilter)
+ {
+ // OES_EGL_image_external specifies this error.
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
+ return false;
+ }
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
+ return false;
+ }
+
+ return true;
+}
+
+template <typename ParamType>
+bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
+{
+ switch (ConvertToGLenum(params[0]))
+ {
+ case GL_NEAREST:
+ case GL_LINEAR:
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
+ return false;
+ }
+
+ return true;
+}
+
+template <typename ParamType>
+bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
+{
+ // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
+ switch (ConvertToGLenum(params[0]))
+ {
+ case GL_NONE:
+ case GL_COMPARE_REF_TO_TEXTURE:
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
+ return false;
+ }
+
+ return true;
+}
+
+template <typename ParamType>
+bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
+{
+ // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
+ switch (ConvertToGLenum(params[0]))
+ {
+ case GL_LEQUAL:
+ case GL_GEQUAL:
+ case GL_LESS:
+ case GL_GREATER:
+ case GL_EQUAL:
+ case GL_NOTEQUAL:
+ case GL_ALWAYS:
+ case GL_NEVER:
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
+ return false;
+ }
+
+ return true;
+}
+
+template <typename ParamType>
+bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
+{
+ if (!context->getExtensions().textureSRGBDecode)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
return false;
}
+
+ switch (ConvertToGLenum(params[0]))
+ {
+ case GL_DECODE_EXT:
+ case GL_SKIP_DECODE_EXT:
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
+ return false;
+ }
+
+ return true;
}
+bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
+{
+ const Program *program = context->getGLState().getProgram();
+ const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
+
+ const auto &programOutputTypes = program->getOutputVariableTypes();
+ for (size_t drawBufferIdx = 0; drawBufferIdx < programOutputTypes.size(); drawBufferIdx++)
+ {
+ GLenum outputType = programOutputTypes[drawBufferIdx];
+ GLenum inputType = framebuffer->getDrawbufferWriteType(drawBufferIdx);
+ if (outputType != GL_NONE && inputType != GL_NONE && inputType != outputType)
+ {
+ context->handleError(InvalidOperation() << "Fragment shader output type does not "
+ "match the bound framebuffer attachment "
+ "type.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
+{
+ const auto &glState = context->getGLState();
+ const Program *program = context->getGLState().getProgram();
+ const VertexArray *vao = context->getGLState().getVertexArray();
+ const auto &vertexAttribs = vao->getVertexAttributes();
+ const auto &currentValues = glState.getVertexAttribCurrentValues();
+
+ for (const sh::Attribute &shaderAttribute : program->getAttributes())
+ {
+ // gl_VertexID and gl_InstanceID are active attributes but don't have a bound attribute.
+ if (shaderAttribute.isBuiltIn())
+ {
+ continue;
+ }
+
+ GLenum shaderInputType = VariableComponentType(shaderAttribute.type);
+
+ const auto &attrib = vertexAttribs[shaderAttribute.location];
+ GLenum vertexType = attrib.enabled ? GetVertexAttributeBaseType(attrib)
+ : currentValues[shaderAttribute.location].Type;
+
+ if (shaderInputType != GL_NONE && vertexType != GL_NONE && shaderInputType != vertexType)
+ {
+ context->handleError(InvalidOperation() << "Vertex shader input type does not "
+ "match the type of the bound vertex "
+ "attribute.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // anonymous namespace
+
bool ValidTextureTarget(const ValidationContext *context, GLenum target)
{
switch (target)
{
- case GL_TEXTURE_2D:
- case GL_TEXTURE_CUBE_MAP:
- return true;
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_CUBE_MAP:
+ return true;
- case GL_TEXTURE_3D:
- case GL_TEXTURE_2D_ARRAY:
- return (context->getClientVersion() >= 3);
+ case GL_TEXTURE_RECTANGLE_ANGLE:
+ return context->getExtensions().textureRectangle;
- default:
- return false;
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_2D_ARRAY:
+ return (context->getClientMajorVersion() >= 3);
+
+ case GL_TEXTURE_2D_MULTISAMPLE:
+ return (context->getClientVersion() >= Version(3, 1));
+
+ default:
+ return false;
}
}
@@ -148,6 +481,9 @@ bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
case GL_TEXTURE_CUBE_MAP:
return true;
+ case GL_TEXTURE_RECTANGLE_ANGLE:
+ return context->getExtensions().textureRectangle;
+
default:
return false;
}
@@ -159,13 +495,22 @@ bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
{
case GL_TEXTURE_3D:
case GL_TEXTURE_2D_ARRAY:
- return (context->getClientVersion() >= 3);
+ return (context->getClientMajorVersion() >= 3);
default:
return false;
}
}
+// Most texture GL calls are not compatible with external textures, so we have a separate validation
+// function for use in the GL calls that do
+bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
+{
+ return (target == GL_TEXTURE_EXTERNAL_OES) &&
+ (context->getExtensions().eglImageExternal ||
+ context->getExtensions().eglStreamConsumerExternal);
+}
+
// This function differs from ValidTextureTarget in that the target must be
// usable as the destination of a 2D operation-- so a cube face is valid, but
// GL_TEXTURE_CUBE_MAP is not.
@@ -174,94 +519,169 @@ bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum ta
{
switch (target)
{
- case GL_TEXTURE_2D:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- return true;
- default:
- return false;
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ return true;
+ case GL_TEXTURE_RECTANGLE_ANGLE:
+ return context->getExtensions().textureRectangle;
+ default:
+ return false;
}
}
-bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
+bool ValidateDrawElementsInstancedBase(ValidationContext *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const GLvoid *indices,
+ GLsizei primcount)
{
- switch (target)
+ if (primcount < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
+ return false;
+ }
+
+ if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
{
- case GL_TEXTURE_3D:
- case GL_TEXTURE_2D_ARRAY:
- return true;
- default:
return false;
}
+
+ // No-op zero primitive count
+ return (primcount > 0);
}
-bool ValidFramebufferTarget(GLenum target)
+bool ValidateDrawArraysInstancedBase(Context *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount)
{
- static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
- "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
+ if (primcount < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
+ return false;
+ }
+
+ if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
+ {
+ return false;
+ }
+
+ // No-op if zero primitive count
+ return (primcount > 0);
+}
+
+bool ValidateDrawInstancedANGLE(ValidationContext *context)
+{
+ // Verify there is at least one active attribute with a divisor of zero
+ const State &state = context->getGLState();
+
+ Program *program = state.getProgram();
+
+ const auto &attribs = state.getVertexArray()->getVertexAttributes();
+ const auto &bindings = state.getVertexArray()->getVertexBindings();
+ for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
+ {
+ const VertexAttribute &attrib = attribs[attributeIndex];
+ const VertexBinding &binding = bindings[attrib.bindingIndex];
+ if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
+ {
+ return true;
+ }
+ }
+
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
+ return false;
+}
+bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
+{
switch (target)
{
- case GL_FRAMEBUFFER: return true;
- case GL_READ_FRAMEBUFFER: return true;
- case GL_DRAW_FRAMEBUFFER: return true;
- default: return false;
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_2D_ARRAY:
+ return true;
+ default:
+ return false;
}
}
-bool ValidBufferTarget(const Context *context, GLenum target)
+bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
{
switch (target)
{
- case GL_ARRAY_BUFFER:
- case GL_ELEMENT_ARRAY_BUFFER:
- return true;
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_2D_ARRAY:
+ case GL_TEXTURE_2D_MULTISAMPLE:
+ return true;
+ case GL_TEXTURE_RECTANGLE_ANGLE:
+ return context->getExtensions().textureRectangle;
+ default:
+ return false;
+ }
+}
- case GL_PIXEL_PACK_BUFFER:
- case GL_PIXEL_UNPACK_BUFFER:
- return (context->getExtensions().pixelBufferObject || context->getClientVersion() >= 3);
+bool ValidFramebufferTarget(const ValidationContext *context, GLenum target)
+{
+ static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
+ GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
+ "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
- case GL_COPY_READ_BUFFER:
- case GL_COPY_WRITE_BUFFER:
- case GL_TRANSFORM_FEEDBACK_BUFFER:
- case GL_UNIFORM_BUFFER:
- return (context->getClientVersion() >= 3);
+ switch (target)
+ {
+ case GL_FRAMEBUFFER:
+ return true;
- default:
- return false;
+ case GL_READ_FRAMEBUFFER:
+ case GL_DRAW_FRAMEBUFFER:
+ return (context->getExtensions().framebufferBlit ||
+ context->getClientMajorVersion() >= 3);
+
+ default:
+ return false;
}
}
-bool ValidBufferParameter(const Context *context, GLenum pname)
+bool ValidBufferType(const ValidationContext *context, BufferBinding target)
{
- const Extensions &extensions = context->getExtensions();
-
- switch (pname)
+ switch (target)
{
- case GL_BUFFER_USAGE:
- case GL_BUFFER_SIZE:
- return true;
+ case BufferBinding::ElementArray:
+ case BufferBinding::Array:
+ return true;
- case GL_BUFFER_ACCESS_OES:
- return extensions.mapBuffer;
+ case BufferBinding::PixelPack:
+ case BufferBinding::PixelUnpack:
+ return (context->getExtensions().pixelBufferObject ||
+ context->getClientMajorVersion() >= 3);
- case GL_BUFFER_MAPPED:
- static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
- return (context->getClientVersion() >= 3) || extensions.mapBuffer || extensions.mapBufferRange;
+ case BufferBinding::CopyRead:
+ case BufferBinding::CopyWrite:
+ case BufferBinding::TransformFeedback:
+ case BufferBinding::Uniform:
+ return (context->getClientMajorVersion() >= 3);
- // GL_BUFFER_MAP_POINTER is a special case, and may only be
- // queried with GetBufferPointerv
- case GL_BUFFER_ACCESS_FLAGS:
- case GL_BUFFER_MAP_OFFSET:
- case GL_BUFFER_MAP_LENGTH:
- return (context->getClientVersion() >= 3) || extensions.mapBufferRange;
+ case BufferBinding::AtomicCounter:
+ case BufferBinding::ShaderStorage:
+ case BufferBinding::DrawIndirect:
+ case BufferBinding::DispatchIndirect:
+ return context->getClientVersion() >= Version(3, 1);
- default:
- return false;
+ default:
+ return false;
}
}
@@ -274,28 +694,34 @@ bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
case GL_TEXTURE_2D:
maxDimension = caps.max2DTextureSize;
break;
- case GL_TEXTURE_CUBE_MAP:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- maxDimension = caps.maxCubeMapTextureSize;
- break;
- case GL_TEXTURE_3D:
- maxDimension = caps.max3DTextureSize;
- break;
- case GL_TEXTURE_2D_ARRAY:
- maxDimension = caps.max2DTextureSize;
- break;
- default: UNREACHABLE();
+ case GL_TEXTURE_CUBE_MAP:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ maxDimension = caps.maxCubeMapTextureSize;
+ break;
+ case GL_TEXTURE_RECTANGLE_ANGLE:
+ return level == 0;
+ case GL_TEXTURE_3D:
+ maxDimension = caps.max3DTextureSize;
+ break;
+ case GL_TEXTURE_2D_ARRAY:
+ maxDimension = caps.max2DTextureSize;
+ break;
+ case GL_TEXTURE_2D_MULTISAMPLE:
+ maxDimension = caps.max2DTextureSize;
+ break;
+ default:
+ UNREACHABLE();
}
- return level <= gl::log2(static_cast<int>(maxDimension));
+ return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
}
-bool ValidImageSizeParameters(const Context *context,
+bool ValidImageSizeParameters(ValidationContext *context,
GLenum target,
GLint level,
GLsizei width,
@@ -303,21 +729,25 @@ bool ValidImageSizeParameters(const Context *context,
GLsizei depth,
bool isSubImage)
{
- if (level < 0 || width < 0 || height < 0 || depth < 0)
+ if (width < 0 || height < 0 || depth < 0)
{
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
return false;
}
-
// TexSubImage parameters can be NPOT without textureNPOT extension,
// as long as the destination texture is POT.
- if (!isSubImage && !context->getExtensions().textureNPOT &&
+ bool hasNPOTSupport =
+ context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
+ if (!isSubImage && !hasNPOTSupport &&
(level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
{
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
return false;
}
if (!ValidMipLevel(context, target, level))
{
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
return false;
}
@@ -334,7 +764,17 @@ bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+ case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
+ case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+ case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+ case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
+ case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
return true;
default:
@@ -342,12 +782,19 @@ bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
}
}
+bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
+{
+ return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
+ (size % blockSize == 0);
+}
+
bool ValidCompressedImageSize(const ValidationContext *context,
GLenum internalFormat,
+ GLint level,
GLsizei width,
GLsizei height)
{
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
if (!formatInfo.compressed)
{
return false;
@@ -360,10 +807,15 @@ bool ValidCompressedImageSize(const ValidationContext *context,
if (CompressedTextureFormatRequiresExactSize(internalFormat))
{
- if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
- width % formatInfo.compressedBlockWidth != 0) ||
- (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
- height % formatInfo.compressedBlockHeight != 0))
+ // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
+ // block size for level 0 but WebGL disallows this.
+ bool smallerThanBlockSizeAllowed =
+ level > 0 || !context->getExtensions().webglCompatibility;
+
+ if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
+ smallerThanBlockSizeAllowed) ||
+ !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
+ smallerThanBlockSizeAllowed))
{
return false;
}
@@ -372,30 +824,193 @@ bool ValidCompressedImageSize(const ValidationContext *context,
return true;
}
+bool ValidCompressedSubImageSize(const ValidationContext *context,
+ GLenum internalFormat,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ size_t textureWidth,
+ size_t textureHeight)
+{
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
+ if (!formatInfo.compressed)
+ {
+ return false;
+ }
+
+ if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
+ {
+ return false;
+ }
+
+ if (CompressedTextureFormatRequiresExactSize(internalFormat))
+ {
+ if (xoffset % formatInfo.compressedBlockWidth != 0 ||
+ yoffset % formatInfo.compressedBlockHeight != 0)
+ {
+ return false;
+ }
+
+ // Allowed to either have data that is a multiple of block size or is smaller than the block
+ // size but fills the entire mip
+ bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
+ static_cast<size_t>(width) == textureWidth &&
+ static_cast<size_t>(height) == textureHeight;
+ bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
+ (height % formatInfo.compressedBlockHeight) == 0;
+ if (!sizeMultipleOfBlockSize && !fillsEntireMip)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidImageDataSize(ValidationContext *context,
+ GLenum textureTarget,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels,
+ GLsizei imageSize)
+{
+ gl::Buffer *pixelUnpackBuffer =
+ context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
+ if (pixelUnpackBuffer == nullptr && imageSize < 0)
+ {
+ // Checks are not required
+ return true;
+ }
+
+ // ...the data would be unpacked from the buffer object such that the memory reads required
+ // would exceed the data store size.
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
+ ASSERT(formatInfo.internalFormat != GL_NONE);
+ const gl::Extents size(width, height, depth);
+ const auto &unpack = context->getGLState().getUnpackState();
+
+ bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
+ auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
+ if (endByteOrErr.isError())
+ {
+ context->handleError(endByteOrErr.getError());
+ return false;
+ }
+
+ GLuint endByte = endByteOrErr.getResult();
+
+ if (pixelUnpackBuffer)
+ {
+ CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
+ CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
+ checkedEndByte += checkedOffset;
+
+ if (!checkedEndByte.IsValid() ||
+ (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
+ {
+ // Overflow past the end of the buffer
+ context->handleError(InvalidOperation());
+ return false;
+ }
+ }
+ else
+ {
+ ASSERT(imageSize >= 0);
+ if (pixels == nullptr && imageSize != 0)
+ {
+ context->handleError(InvalidOperation()
+ << "imageSize must be 0 if no texture data is provided.");
+ return false;
+ }
+
+ if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
+ {
+ context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
+ return false;
+ }
+ }
+
+ return true;
+}
+
bool ValidQueryType(const Context *context, GLenum queryType)
{
- static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT, "GL extension enums not equal.");
- static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, "GL extension enums not equal.");
+ static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
+ "GL extension enums not equal.");
+ static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
+ "GL extension enums not equal.");
switch (queryType)
{
- case GL_ANY_SAMPLES_PASSED:
- case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
- return true;
- case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
- return (context->getClientVersion() >= 3);
- case GL_TIME_ELAPSED_EXT:
- return context->getExtensions().disjointTimerQuery;
- default:
+ case GL_ANY_SAMPLES_PASSED:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
+ return context->getClientMajorVersion() >= 3 ||
+ context->getExtensions().occlusionQueryBoolean;
+ case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+ return (context->getClientMajorVersion() >= 3);
+ case GL_TIME_ELAPSED_EXT:
+ return context->getExtensions().disjointTimerQuery;
+ case GL_COMMANDS_COMPLETED_CHROMIUM:
+ return context->getExtensions().syncQuery;
+ default:
+ return false;
+ }
+}
+
+bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
+ GLenum type,
+ GLboolean normalized,
+ GLsizei stride,
+ const void *ptr,
+ bool pureInteger)
+{
+ ASSERT(context->getExtensions().webglCompatibility);
+ // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
+ // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
+ // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
+ // parameter exceeds 255.
+ constexpr GLsizei kMaxWebGLStride = 255;
+ if (stride > kMaxWebGLStride)
+ {
+ context->handleError(InvalidValue()
+ << "Stride is over the maximum stride allowed by WebGL.");
+ return false;
+ }
+
+ // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
+ // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
+ // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
+ // or an INVALID_OPERATION error is generated.
+ VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
+ size_t typeSize = GetVertexFormatTypeSize(internalType);
+
+ ASSERT(isPow2(typeSize) && typeSize > 0);
+ size_t sizeMask = (typeSize - 1);
+ if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
+ return false;
+ }
+
+ if ((stride & sizeMask) != 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
return false;
}
+
+ return true;
}
-Program *GetValidProgram(Context *context, GLuint id)
+Program *GetValidProgram(ValidationContext *context, GLuint id)
{
- // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the
- // error INVALID_VALUE if the provided name is not the name of either a shader or program object and
- // INVALID_OPERATION if the provided name identifies an object that is not the expected type."
+ // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
+ // generate the error INVALID_VALUE if the provided name is not the name of either a shader
+ // or program object and INVALID_OPERATION if the provided name identifies an object
+ // that is not the expected type."
Program *validProgram = context->getProgram(id);
@@ -403,19 +1018,18 @@ Program *GetValidProgram(Context *context, GLuint id)
{
if (context->getShader(id))
{
- context->recordError(
- Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
}
else
{
- context->recordError(Error(GL_INVALID_VALUE, "Program name is not valid"));
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
}
}
return validProgram;
}
-Shader *GetValidShader(Context *context, GLuint id)
+Shader *GetValidShader(ValidationContext *context, GLuint id)
{
// See ValidProgram for spec details.
@@ -425,12 +1039,11 @@ Shader *GetValidShader(Context *context, GLuint id)
{
if (context->getProgram(id))
{
- context->recordError(
- Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
}
else
{
- context->recordError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
}
}
@@ -439,13 +1052,19 @@ Shader *GetValidShader(Context *context, GLuint id)
bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
{
- if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
+ if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
{
- const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
+ if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
+ return false;
+ }
+ // Color attachment 0 is validated below because it is always valid
+ const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
if (colorAttachment >= context->getCaps().maxColorAttachments)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
return false;
}
}
@@ -453,124 +1072,105 @@ bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
{
switch (attachment)
{
- case GL_DEPTH_ATTACHMENT:
- case GL_STENCIL_ATTACHMENT:
- break;
+ case GL_COLOR_ATTACHMENT0:
+ case GL_DEPTH_ATTACHMENT:
+ case GL_STENCIL_ATTACHMENT:
+ break;
- case GL_DEPTH_STENCIL_ATTACHMENT:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- break;
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ if (!context->getExtensions().webglCompatibility &&
+ context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
+ return false;
+ }
+ break;
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
+ return false;
}
}
return true;
}
-bool ValidateRenderbufferStorageParametersBase(gl::Context *context, GLenum target, GLsizei samples,
- GLenum internalformat, GLsizei width, GLsizei height)
+bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
+ GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
{
switch (target)
{
- case GL_RENDERBUFFER:
- break;
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
+ case GL_RENDERBUFFER:
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
+ return false;
}
if (width < 0 || height < 0 || samples < 0)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
return false;
}
- const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
+ // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
+ GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
+
+ const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
if (!formatCaps.renderable)
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return false;
}
// ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
// sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
// only sized internal formats.
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
- if (formatInfo.pixelBytes == 0)
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
+ if (formatInfo.internalFormat == GL_NONE)
{
- context->recordError(Error(GL_INVALID_ENUM));
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
return false;
}
if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
- GLuint handle = context->getState().getRenderbufferId();
+ GLuint handle = context->getGLState().getRenderbufferId();
if (handle == 0)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
return false;
}
return true;
}
-bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum target, GLsizei samples,
- GLenum internalformat, GLsizei width, GLsizei height)
-{
- ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
-
- // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
- // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
- // generated.
- if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
-
- // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
- // the specified storage. This is different than ES 3.0 in which a sample number higher
- // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
- // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
- if (context->getClientVersion() >= 3)
- {
- const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
- if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
- {
- context->recordError(Error(GL_OUT_OF_MEMORY));
- return false;
- }
- }
-
- return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height);
-}
-
-bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
- GLenum renderbuffertarget, GLuint renderbuffer)
+bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
+ GLenum target,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer)
{
- if (!ValidFramebufferTarget(target))
+ if (!ValidFramebufferTarget(context, target))
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return false;
}
- gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
+ gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
ASSERT(framebuffer);
if (framebuffer->id() == 0)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
return false;
}
@@ -587,7 +1187,7 @@ bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum targ
{
if (!context->getRenderbuffer(renderbuffer))
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
return false;
}
}
@@ -595,7 +1195,7 @@ bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum targ
return true;
}
-bool ValidateBlitFramebufferParameters(gl::Context *context,
+bool ValidateBlitFramebufferParameters(ValidationContext *context,
GLint srcX0,
GLint srcY0,
GLint srcX1,
@@ -609,18 +1209,18 @@ bool ValidateBlitFramebufferParameters(gl::Context *context,
{
switch (filter)
{
- case GL_NEAREST:
- break;
- case GL_LINEAR:
- break;
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
+ case GL_NEAREST:
+ break;
+ case GL_LINEAR:
+ break;
+ default:
+ context->handleError(InvalidEnum());
+ return false;
}
if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
@@ -635,40 +1235,41 @@ bool ValidateBlitFramebufferParameters(gl::Context *context,
// color buffer, leaving only nearest being unfiltered from above
if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
- if (context->getState().getReadFramebuffer()->id() == context->getState().getDrawFramebuffer()->id())
+ const auto &glState = context->getGLState();
+ gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
+ gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
+
+ if (!readFramebuffer || !drawFramebuffer)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidFramebufferOperation());
return false;
}
- const gl::Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
- const gl::Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer();
-
- if (!readFramebuffer || !drawFramebuffer)
+ if (readFramebuffer->id() == drawFramebuffer->id())
{
- context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
- if (!readFramebuffer->checkStatus(context->getData()))
+ if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
{
- context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ context->handleError(InvalidFramebufferOperation());
return false;
}
- if (!drawFramebuffer->checkStatus(context->getData()))
+ if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
{
- context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ context->handleError(InvalidFramebufferOperation());
return false;
}
- if (drawFramebuffer->getSamples(context->getData()) != 0)
+ if (drawFramebuffer->getSamples(context) != 0)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
@@ -677,13 +1278,11 @@ bool ValidateBlitFramebufferParameters(gl::Context *context,
if (mask & GL_COLOR_BUFFER_BIT)
{
const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
- const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
const Extensions &extensions = context->getExtensions();
- if (readColorBuffer && drawColorBuffer)
+ if (readColorBuffer)
{
- GLenum readInternalFormat = readColorBuffer->getInternalFormat();
- const InternalFormat &readFormatInfo = GetInternalFormatInfo(readInternalFormat);
+ const Format &readFormat = readColorBuffer->getFormat();
for (size_t drawbufferIdx = 0;
drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
@@ -692,18 +1291,19 @@ bool ValidateBlitFramebufferParameters(gl::Context *context,
drawFramebuffer->getDrawBuffer(drawbufferIdx);
if (attachment)
{
- GLenum drawInternalFormat = attachment->getInternalFormat();
- const InternalFormat &drawFormatInfo = GetInternalFormatInfo(drawInternalFormat);
+ const Format &drawFormat = attachment->getFormat();
// The GL ES 3.0.2 spec (pg 193) states that:
// 1) If the read buffer is fixed point format, the draw buffer must be as well
- // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
- // 3) If the read buffer is a signed integer format, the draw buffer must be as well
+ // 2) If the read buffer is an unsigned integer format, the draw buffer must be
+ // as well
+ // 3) If the read buffer is a signed integer format, the draw buffer must be as
+ // well
// Changes with EXT_color_buffer_float:
// Case 1) is changed to fixed point OR floating point
- GLenum readComponentType = readFormatInfo.componentType;
- GLenum drawComponentType = drawFormatInfo.componentType;
- bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
+ GLenum readComponentType = readFormat.info->componentType;
+ GLenum drawComponentType = drawFormat.info->componentType;
+ bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
readComponentType == GL_SIGNED_NORMALIZED);
bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
drawComponentType == GL_SIGNED_NORMALIZED);
@@ -715,350 +1315,162 @@ bool ValidateBlitFramebufferParameters(gl::Context *context,
if (readFixedOrFloat != drawFixedOrFloat)
{
- context->recordError(Error(GL_INVALID_OPERATION,
- "If the read buffer contains fixed-point or "
- "floating-point values, the draw buffer "
- "must as well."));
+ context->handleError(InvalidOperation()
+ << "If the read buffer contains fixed-point or "
+ "floating-point values, the draw buffer must "
+ "as well.");
return false;
}
}
else if (readFixedPoint != drawFixedPoint)
{
- context->recordError(Error(GL_INVALID_OPERATION,
- "If the read buffer contains fixed-point "
- "values, the draw buffer must as well."));
+ context->handleError(InvalidOperation()
+ << "If the read buffer contains fixed-point values, "
+ "the draw buffer must as well.");
return false;
}
if (readComponentType == GL_UNSIGNED_INT &&
drawComponentType != GL_UNSIGNED_INT)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
if (readComponentType == GL_INT && drawComponentType != GL_INT)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
+ return false;
+ }
+
+ if (readColorBuffer->getSamples() > 0 &&
+ (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
+ {
+ context->handleError(InvalidOperation());
return false;
}
- if (readColorBuffer->getSamples() > 0 && (readInternalFormat != drawInternalFormat || !sameBounds))
+ if (context->getExtensions().webglCompatibility &&
+ *readColorBuffer == *attachment)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(
+ InvalidOperation()
+ << "Read and write color attachments cannot be the same image.");
return false;
}
}
}
- if ((readFormatInfo.componentType == GL_INT || readFormatInfo.componentType == GL_UNSIGNED_INT) && filter == GL_LINEAR)
+ if ((readFormat.info->componentType == GL_INT ||
+ readFormat.info->componentType == GL_UNSIGNED_INT) &&
+ filter == GL_LINEAR)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
}
+ // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
+ // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
+ // attachment and WebGL defines it to be an error. We do the check unconditionally as the
+ // situation is an application error that would lead to a crash in ANGLE.
+ else if (drawFramebuffer->hasEnabledDrawBuffer())
+ {
+ context->handleError(
+ InvalidOperation()
+ << "Attempt to read from a missing color attachment of a complete framebuffer.");
+ return false;
+ }
}
- GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
+ GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
for (size_t i = 0; i < 2; i++)
{
if (mask & masks[i])
{
- const gl::FramebufferAttachment *readBuffer = readFramebuffer->getAttachment(attachments[i]);
- const gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getAttachment(attachments[i]);
+ const gl::FramebufferAttachment *readBuffer =
+ readFramebuffer->getAttachment(attachments[i]);
+ const gl::FramebufferAttachment *drawBuffer =
+ drawFramebuffer->getAttachment(attachments[i]);
if (readBuffer && drawBuffer)
{
- if (readBuffer->getInternalFormat() != drawBuffer->getInternalFormat())
+ if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
if (readBuffer->getSamples() > 0 && !sameBounds)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
+ return false;
+ }
+
+ if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
+ {
+ context->handleError(
+ InvalidOperation()
+ << "Read and write depth stencil attachments cannot be the same image.");
return false;
}
}
+ // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
+ else if (drawBuffer)
+ {
+ context->handleError(InvalidOperation() << "Attempt to read from a missing "
+ "depth/stencil attachment of a "
+ "complete framebuffer.");
+ return false;
+ }
}
}
- return true;
-}
-
-bool ValidateGetVertexAttribParameters(Context *context, GLenum pname)
-{
- switch (pname)
+ // ANGLE_multiview, Revision 1:
+ // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
+ // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
+ if (readFramebuffer->getMultiviewLayout() != GL_NONE)
{
- case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
- case GL_VERTEX_ATTRIB_ARRAY_SIZE:
- case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
- case GL_VERTEX_ATTRIB_ARRAY_TYPE:
- case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
- case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
- case GL_CURRENT_VERTEX_ATTRIB:
- return true;
-
- case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
- // Don't verify ES3 context because GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE uses
- // the same constant.
- static_assert(GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
- "ANGLE extension enums not equal to GL enums.");
- return true;
-
- case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- return true;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidFramebufferOperation()
+ << "Attempt to read from a multi-view framebuffer.");
return false;
}
-}
-
-bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param)
-{
- switch (pname)
+ if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
{
- case GL_TEXTURE_WRAP_R:
- case GL_TEXTURE_SWIZZLE_R:
- case GL_TEXTURE_SWIZZLE_G:
- case GL_TEXTURE_SWIZZLE_B:
- case GL_TEXTURE_SWIZZLE_A:
- case GL_TEXTURE_BASE_LEVEL:
- case GL_TEXTURE_MAX_LEVEL:
- case GL_TEXTURE_COMPARE_MODE:
- case GL_TEXTURE_COMPARE_FUNC:
- case GL_TEXTURE_MIN_LOD:
- case GL_TEXTURE_MAX_LOD:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- break;
-
- default: break;
- }
-
- switch (pname)
- {
- case GL_TEXTURE_WRAP_S:
- case GL_TEXTURE_WRAP_T:
- case GL_TEXTURE_WRAP_R:
- switch (param)
- {
- case GL_REPEAT:
- case GL_CLAMP_TO_EDGE:
- case GL_MIRRORED_REPEAT:
- return true;
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
-
- case GL_TEXTURE_MIN_FILTER:
- switch (param)
- {
- case GL_NEAREST:
- case GL_LINEAR:
- case GL_NEAREST_MIPMAP_NEAREST:
- case GL_LINEAR_MIPMAP_NEAREST:
- case GL_NEAREST_MIPMAP_LINEAR:
- case GL_LINEAR_MIPMAP_LINEAR:
- return true;
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- break;
-
- case GL_TEXTURE_MAG_FILTER:
- switch (param)
- {
- case GL_NEAREST:
- case GL_LINEAR:
- return true;
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- break;
-
- case GL_TEXTURE_USAGE_ANGLE:
- switch (param)
- {
- case GL_NONE:
- case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
- return true;
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- break;
-
- case GL_TEXTURE_MAX_ANISOTROPY_EXT:
- if (!context->getExtensions().textureFilterAnisotropic)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
-
- // we assume the parameter passed to this validation method is truncated, not rounded
- if (param < 1)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
- return true;
-
- case GL_TEXTURE_MIN_LOD:
- case GL_TEXTURE_MAX_LOD:
- // any value is permissible
- return true;
-
- case GL_TEXTURE_COMPARE_MODE:
- // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
- switch (param)
- {
- case GL_NONE:
- case GL_COMPARE_REF_TO_TEXTURE:
- return true;
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- break;
-
- case GL_TEXTURE_COMPARE_FUNC:
- // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
- switch (param)
- {
- case GL_LEQUAL:
- case GL_GEQUAL:
- case GL_LESS:
- case GL_GREATER:
- case GL_EQUAL:
- case GL_NOTEQUAL:
- case GL_ALWAYS:
- case GL_NEVER:
- return true;
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- break;
-
- case GL_TEXTURE_SWIZZLE_R:
- case GL_TEXTURE_SWIZZLE_G:
- case GL_TEXTURE_SWIZZLE_B:
- case GL_TEXTURE_SWIZZLE_A:
- switch (param)
- {
- case GL_RED:
- case GL_GREEN:
- case GL_BLUE:
- case GL_ALPHA:
- case GL_ZERO:
- case GL_ONE:
- return true;
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- break;
-
- case GL_TEXTURE_BASE_LEVEL:
- case GL_TEXTURE_MAX_LEVEL:
- if (param < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
- return true;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidFramebufferOperation()
+ << "Attempt to write to a multi-view framebuffer.");
return false;
}
-}
-
-bool ValidateSamplerObjectParameter(gl::Context *context, GLenum pname)
-{
- switch (pname)
- {
- case GL_TEXTURE_MIN_FILTER:
- case GL_TEXTURE_MAG_FILTER:
- case GL_TEXTURE_WRAP_S:
- case GL_TEXTURE_WRAP_T:
- case GL_TEXTURE_WRAP_R:
- case GL_TEXTURE_MIN_LOD:
- case GL_TEXTURE_MAX_LOD:
- case GL_TEXTURE_COMPARE_MODE:
- case GL_TEXTURE_COMPARE_FUNC:
- return true;
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
+ return true;
}
-bool ValidateReadPixels(Context *context,
- GLint x,
- GLint y,
- GLsizei width,
- GLsizei height,
- GLenum format,
- GLenum type,
- GLvoid *pixels)
+bool ValidateReadPixelsRobustANGLE(Context *context,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *pixels)
{
- if (width < 0 || height < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE, "width and height must be positive"));
- return false;
- }
-
- Framebuffer *framebuffer = context->getState().getReadFramebuffer();
- ASSERT(framebuffer);
-
- if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
- {
- context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
- return false;
- }
-
- if (context->getState().getReadFramebuffer()->id() != 0 &&
- framebuffer->getSamples(context->getData()) != 0)
+ if (!ValidateRobustEntryPoint(context, bufSize))
{
- context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
- const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
- if (!readBuffer)
+ if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
+ columns, rows, pixels))
{
- context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
- GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
- GLenum currentType = framebuffer->getImplementationColorReadType();
- GLenum currentInternalFormat = readBuffer->getInternalFormat();
- GLuint clientVersion = context->getClientVersion();
-
- bool validReadFormat = (clientVersion < 3) ? ValidES2ReadFormatType(context, format, type) :
- ValidES3ReadFormatType(context, currentInternalFormat, format, type);
-
- if (!(currentFormat == format && currentType == type) && !validReadFormat)
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
{
- context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
@@ -1073,88 +1485,97 @@ bool ValidateReadnPixelsEXT(Context *context,
GLenum format,
GLenum type,
GLsizei bufSize,
- GLvoid *pixels)
+ void *pixels)
{
if (bufSize < 0)
{
- context->recordError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
return false;
}
- GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
- const InternalFormat &sizedFormatInfo = GetInternalFormatInfo(sizedInternalFormat);
+ return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
+ nullptr, nullptr, pixels);
+}
- GLsizei outputPitch =
- sizedFormatInfo.computeRowPitch(type, width, context->getState().getPackAlignment(),
- context->getState().getPackRowLength());
- // sized query sanity check
- int requiredSize = outputPitch * height;
- if (requiredSize > bufSize)
+bool ValidateReadnPixelsRobustANGLE(Context *context,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *data)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
{
- context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
- return ValidateReadPixels(context, x, y, width, height, format, type, pixels);
-}
+ if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
+ columns, rows, data))
+ {
+ return false;
+ }
-bool ValidateGenQueriesBase(gl::Context *context, GLsizei n, const GLuint *ids)
-{
- if (n < 0)
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
{
- context->recordError(Error(GL_INVALID_VALUE, "Query count < 0"));
return false;
}
return true;
}
-bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
+bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
{
if (!context->getExtensions().occlusionQueryBoolean &&
!context->getExtensions().disjointTimerQuery)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
return false;
}
- return ValidateGenQueriesBase(context, n, ids);
+ return ValidateGenOrDelete(context, n);
}
-bool ValidateDeleteQueriesBase(gl::Context *context, GLsizei n, const GLuint *ids)
+bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
{
- if (n < 0)
+ if (!context->getExtensions().occlusionQueryBoolean &&
+ !context->getExtensions().disjointTimerQuery)
{
- context->recordError(Error(GL_INVALID_VALUE, "Query count < 0"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
return false;
}
- return true;
+ return ValidateGenOrDelete(context, n);
}
-bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
+bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
{
if (!context->getExtensions().occlusionQueryBoolean &&
!context->getExtensions().disjointTimerQuery)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
return false;
}
- return ValidateDeleteQueriesBase(context, n, ids);
+ return true;
}
bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
{
if (!ValidQueryType(context, target))
{
- context->recordError(Error(GL_INVALID_ENUM, "Invalid query target"));
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
return false;
}
if (id == 0)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Query id is 0"));
+ context->handleError(InvalidOperation() << "Query id is 0");
return false;
}
@@ -1174,11 +1595,9 @@ bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
// of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
// no query may be active for either if glBeginQuery targets either.
- // TODO(ewell): I think this needs to be changed for timer and occlusion queries to work at the
- // same time
- if (context->getState().isQueryActive())
+ if (context->getGLState().isQueryActive(target))
{
- context->recordError(Error(GL_INVALID_OPERATION, "Other query is active"));
+ context->handleError(InvalidOperation() << "Other query is active");
return false;
}
@@ -1187,14 +1606,14 @@ bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
// check that name was obtained with glGenQueries
if (!queryObject)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Invalid query id"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
return false;
}
// check for type mismatch
if (queryObject->getType() != target)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
+ context->handleError(InvalidOperation() << "Query type does not match target");
return false;
}
@@ -1204,9 +1623,9 @@ bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
{
if (!context->getExtensions().occlusionQueryBoolean &&
- !context->getExtensions().disjointTimerQuery)
+ !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
return false;
}
@@ -1217,15 +1636,15 @@ bool ValidateEndQueryBase(gl::Context *context, GLenum target)
{
if (!ValidQueryType(context, target))
{
- context->recordError(Error(GL_INVALID_ENUM, "Invalid query target"));
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
return false;
}
- const Query *queryObject = context->getState().getActiveQuery(target);
+ const Query *queryObject = context->getGLState().getActiveQuery(target);
if (queryObject == nullptr)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Query target not active"));
+ context->handleError(InvalidOperation() << "Query target not active");
return false;
}
@@ -1235,9 +1654,9 @@ bool ValidateEndQueryBase(gl::Context *context, GLenum target)
bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
{
if (!context->getExtensions().occlusionQueryBoolean &&
- !context->getExtensions().disjointTimerQuery)
+ !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
return false;
}
@@ -1248,37 +1667,42 @@ bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
{
if (!context->getExtensions().disjointTimerQuery)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
+ context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
return false;
}
if (target != GL_TIMESTAMP_EXT)
{
- context->recordError(Error(GL_INVALID_ENUM, "Invalid query target"));
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
return false;
}
Query *queryObject = context->getQuery(id, true, target);
if (queryObject == nullptr)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Invalid query id"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
return false;
}
- if (context->getState().isQueryActive(queryObject))
+ if (context->getGLState().isQueryActive(queryObject))
{
- context->recordError(Error(GL_INVALID_OPERATION, "Query is active"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
return false;
}
return true;
}
-bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname)
+bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
{
+ if (numParams)
+ {
+ *numParams = 0;
+ }
+
if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
{
- context->recordError(Error(GL_INVALID_ENUM, "Invalid query type"));
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
return false;
}
@@ -1287,8 +1711,7 @@ bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname)
case GL_CURRENT_QUERY_EXT:
if (target == GL_TIMESTAMP_EXT)
{
- context->recordError(
- Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
+ context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
return false;
}
break;
@@ -1296,43 +1719,79 @@ bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname)
if (!context->getExtensions().disjointTimerQuery ||
(target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
{
- context->recordError(Error(GL_INVALID_ENUM, "Invalid pname"));
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
return false;
}
break;
default:
- context->recordError(Error(GL_INVALID_ENUM, "Invalid pname"));
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
return false;
}
+ if (numParams)
+ {
+ // All queries return only one value
+ *numParams = 1;
+ }
+
return true;
}
bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
{
if (!context->getExtensions().occlusionQueryBoolean &&
- !context->getExtensions().disjointTimerQuery)
+ !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateGetQueryivBase(context, target, pname, nullptr);
+}
+
+bool ValidateGetQueryivRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetQueryivBase(context, target, pname, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
{
- context->recordError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
return false;
}
- return ValidateGetQueryivBase(context, target, pname);
+ return true;
}
-bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname)
+bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
{
+ if (numParams)
+ {
+ *numParams = 0;
+ }
+
Query *queryObject = context->getQuery(id, false, GL_NONE);
if (!queryObject)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Query does not exist"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
return false;
}
- if (context->getState().isQueryActive(queryObject))
+ if (context->getGLState().isQueryActive(queryObject))
{
- context->recordError(Error(GL_INVALID_OPERATION, "Query currently active"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
return false;
}
@@ -1343,10 +1802,15 @@ bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname)
break;
default:
- context->recordError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
return false;
}
+ if (numParams)
+ {
+ *numParams = 1;
+ }
+
return true;
}
@@ -1354,59 +1818,190 @@ bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLin
{
if (!context->getExtensions().disjointTimerQuery)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
+ context->handleError(InvalidOperation() << "Timer query extension not enabled");
+ return false;
+ }
+ return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
+}
+
+bool ValidateGetQueryObjectivRobustANGLE(Context *context,
+ GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!context->getExtensions().disjointTimerQuery)
+ {
+ context->handleError(InvalidOperation() << "Timer query extension not enabled");
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
+ {
return false;
}
- return ValidateGetQueryObjectValueBase(context, id, pname);
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
}
bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
{
if (!context->getExtensions().disjointTimerQuery &&
- !context->getExtensions().occlusionQueryBoolean)
+ !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
- return ValidateGetQueryObjectValueBase(context, id, pname);
+ return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
+}
+
+bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
+ GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params)
+{
+ if (!context->getExtensions().disjointTimerQuery &&
+ !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
}
bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
{
if (!context->getExtensions().disjointTimerQuery)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
+ return false;
+ }
+ return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
+}
+
+bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
+ GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *params)
+{
+ if (!context->getExtensions().disjointTimerQuery)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
return false;
}
- return ValidateGetQueryObjectValueBase(context, id, pname);
+
+ if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
}
bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
{
if (!context->getExtensions().disjointTimerQuery)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
- return ValidateGetQueryObjectValueBase(context, id, pname);
+ return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
}
-static bool ValidateUniformCommonBase(gl::Context *context,
- GLenum targetUniformType,
- GLint location,
- GLsizei count,
- const LinkedUniform **uniformOut)
+bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
+ GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint64 *params)
+{
+ if (!context->getExtensions().disjointTimerQuery)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateUniformCommonBase(ValidationContext *context,
+ gl::Program *program,
+ GLint location,
+ GLsizei count,
+ const LinkedUniform **uniformOut)
{
+ // TODO(Jiajia): Add image uniform check in future.
if (count < 0)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
return false;
}
- gl::Program *program = context->getState().getProgram();
if (!program)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
+ return false;
+ }
+
+ if (!program->isLinked())
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
return false;
}
@@ -1416,18 +2011,33 @@ static bool ValidateUniformCommonBase(gl::Context *context,
return false;
}
- if (!program->isValidUniformLocation(location))
+ const auto &uniformLocations = program->getUniformLocations();
+ size_t castedLocation = static_cast<size_t>(location);
+ if (castedLocation >= uniformLocations.size())
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation() << "Invalid uniform location");
return false;
}
- const LinkedUniform &uniform = program->getUniformByLocation(location);
+ const auto &uniformLocation = uniformLocations[castedLocation];
+ if (uniformLocation.ignored)
+ {
+ // Silently ignore the uniform command
+ return false;
+ }
+
+ if (!uniformLocation.used())
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+
+ const auto &uniform = program->getUniformByIndex(uniformLocation.index);
// attempting to write an array to a non-array uniform is an INVALID_OPERATION
if (!uniform.isArray() && count > 1)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
@@ -1435,70 +2045,108 @@ static bool ValidateUniformCommonBase(gl::Context *context,
return true;
}
-bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
+bool ValidateUniform1ivValue(ValidationContext *context,
+ GLenum uniformType,
+ GLsizei count,
+ const GLint *value)
{
- // Check for ES3 uniform entry points
- if (VariableComponentType(uniformType) == GL_UNSIGNED_INT && context->getClientVersion() < 3)
+ // Value type is GL_INT, because we only get here from glUniform1i{v}.
+ // It is compatible with INT or BOOL.
+ // Do these cheap tests first, for a little extra speed.
+ if (GL_INT == uniformType || GL_BOOL == uniformType)
{
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
+ return true;
}
- const LinkedUniform *uniform = nullptr;
- if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform))
+ if (IsSamplerType(uniformType))
{
- return false;
+ // Check that the values are in range.
+ const GLint max = context->getCaps().maxCombinedTextureImageUnits;
+ for (GLsizei i = 0; i < count; ++i)
+ {
+ if (value[i] < 0 || value[i] >= max)
+ {
+ context->handleError(InvalidValue() << "sampler uniform value out of range");
+ return false;
+ }
+ }
+ return true;
}
- GLenum targetBoolType = VariableBoolVectorType(uniformType);
- bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
- if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
+ context->handleError(InvalidOperation() << "wrong type of value for uniform");
+ return false;
+}
+
+bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
+{
+ // Check that the value type is compatible with uniform type.
+ // Do the cheaper test first, for a little extra speed.
+ if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
{
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
+ return true;
}
- return true;
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
+ return false;
}
-bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count,
- GLboolean transpose)
+bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
{
- // Check for ES3 uniform entry points
- int rows = VariableRowCount(matrixType);
- int cols = VariableColumnCount(matrixType);
- if (rows != cols && context->getClientVersion() < 3)
+ // Check that the value type is compatible with uniform type.
+ if (valueType == uniformType)
{
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
+ return true;
}
- if (transpose != GL_FALSE && context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
+ context->handleError(InvalidOperation() << "wrong type of value for uniform");
+ return false;
+}
+bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
+{
const LinkedUniform *uniform = nullptr;
- if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform))
- {
- return false;
- }
+ gl::Program *programObject = context->getGLState().getProgram();
+ return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
+ ValidateUniformValue(context, valueType, uniform->type);
+}
- if (uniform->type != matrixType)
+bool ValidateUniform1iv(ValidationContext *context,
+ GLint location,
+ GLsizei count,
+ const GLint *value)
+{
+ const LinkedUniform *uniform = nullptr;
+ gl::Program *programObject = context->getGLState().getProgram();
+ return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
+ ValidateUniform1ivValue(context, uniform->type, count, value);
+}
+
+bool ValidateUniformMatrix(ValidationContext *context,
+ GLenum valueType,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose)
+{
+ if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidValue());
return false;
}
- return true;
+ const LinkedUniform *uniform = nullptr;
+ gl::Program *programObject = context->getGLState().getProgram();
+ return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
+ ValidateUniformMatrixValue(context, valueType, uniform->type);
}
-bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
+bool ValidateStateQuery(ValidationContext *context,
+ GLenum pname,
+ GLenum *nativeType,
+ unsigned int *numParams)
{
if (!context->getQueryParameterInfo(pname, nativeType, numParams))
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return false;
}
@@ -1510,50 +2158,96 @@ bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType,
if (colorAttachment >= caps.maxDrawBuffers)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
}
switch (pname)
{
- case GL_TEXTURE_BINDING_2D:
- case GL_TEXTURE_BINDING_CUBE_MAP:
- case GL_TEXTURE_BINDING_3D:
- case GL_TEXTURE_BINDING_2D_ARRAY:
- if (context->getState().getActiveSampler() >= caps.maxCombinedTextureImageUnits)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
+ case GL_TEXTURE_BINDING_2D:
+ case GL_TEXTURE_BINDING_CUBE_MAP:
+ case GL_TEXTURE_BINDING_3D:
+ case GL_TEXTURE_BINDING_2D_ARRAY:
+ case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
+ break;
+ case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
+ if (!context->getExtensions().textureRectangle)
+ {
+ context->handleError(InvalidEnum()
+ << "ANGLE_texture_rectangle extension not present");
+ return false;
+ }
+ break;
+ case GL_TEXTURE_BINDING_EXTERNAL_OES:
+ if (!context->getExtensions().eglStreamConsumerExternal &&
+ !context->getExtensions().eglImageExternal)
+ {
+ context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
+ "nor GL_OES_EGL_image_external "
+ "extensions enabled");
+ return false;
+ }
+ break;
- case GL_IMPLEMENTATION_COLOR_READ_TYPE:
- case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
{
- Framebuffer *framebuffer = context->getState().getReadFramebuffer();
+ if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
+ GL_FRAMEBUFFER_COMPLETE)
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+
+ const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
ASSERT(framebuffer);
- if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
+
+ if (framebuffer->getReadBufferState() == GL_NONE)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
return false;
}
const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
if (!attachment)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
}
break;
- default:
- break;
+ default:
+ break;
}
// pname is valid, but there are no parameters to return
- if (numParams == 0)
+ if (*numParams == 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateRobustStateQuery(ValidationContext *context,
+ GLenum pname,
+ GLsizei bufSize,
+ GLenum *nativeType,
+ unsigned int *numParams)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateStateQuery(context, pname, nativeType, numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *numParams))
{
return false;
}
@@ -1574,43 +2268,78 @@ bool ValidateCopyTexImageParametersBase(ValidationContext *context,
GLsizei width,
GLsizei height,
GLint border,
- GLenum *textureFormatOut)
+ Format *textureFormatOut)
{
- if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
+ if (xoffset < 0 || yoffset < 0 || zoffset < 0)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
return false;
}
- if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
+ if (width < 0 || height < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
+ return false;
+ }
+
+ if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
+ std::numeric_limits<GLsizei>::max() - yoffset < height)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
if (border != 0)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
return false;
}
if (!ValidMipLevel(context, target, level))
{
- context->recordError(Error(GL_INVALID_VALUE));
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
return false;
}
- const gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
- if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
+ const auto &state = context->getGLState();
+ Framebuffer *readFramebuffer = state.getReadFramebuffer();
+ if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
{
- context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ context->handleError(InvalidFramebufferOperation());
return false;
}
- const auto &state = context->getState();
- if (state.getReadFramebuffer()->id() != 0 && framebuffer->getSamples(context->getData()) != 0)
+ if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
+ return false;
+ }
+
+ if (readFramebuffer->getReadBufferState() == GL_NONE)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
+ return false;
+ }
+
+ // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
+ // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
+ // attachment and WebGL defines it to be an error. We do the check unconditionally as the
+ // situation is an application error that would lead to a crash in ANGLE.
+ const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
+ if (source == nullptr)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
+ return false;
+ }
+
+ // ANGLE_multiview spec, Revision 1:
+ // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
+ // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
+ // is not NONE.
+ if (source->getMultiviewLayout() != GL_NONE)
+ {
+ context->handleError(InvalidFramebufferOperation()
+ << "The active read framebuffer object has multiview attachments.");
return false;
}
@@ -1619,57 +2348,57 @@ bool ValidateCopyTexImageParametersBase(ValidationContext *context,
GLuint maxDimension = 0;
switch (target)
{
- case GL_TEXTURE_2D:
- maxDimension = caps.max2DTextureSize;
- break;
+ case GL_TEXTURE_2D:
+ maxDimension = caps.max2DTextureSize;
+ break;
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- maxDimension = caps.maxCubeMapTextureSize;
- break;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ maxDimension = caps.maxCubeMapTextureSize;
+ break;
- case GL_TEXTURE_2D_ARRAY:
- maxDimension = caps.max2DTextureSize;
- break;
+ case GL_TEXTURE_RECTANGLE_ANGLE:
+ maxDimension = caps.maxRectangleTextureSize;
+ break;
- case GL_TEXTURE_3D:
- maxDimension = caps.max3DTextureSize;
- break;
+ case GL_TEXTURE_2D_ARRAY:
+ maxDimension = caps.max2DTextureSize;
+ break;
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
+ case GL_TEXTURE_3D:
+ maxDimension = caps.max3DTextureSize;
+ break;
+
+ default:
+ context->handleError(InvalidEnum());
+ return false;
}
gl::Texture *texture =
state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
if (!texture)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
return false;
}
if (texture->getImmutableFormat() && !isSubImage)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
-
- if (formatInfo.depthBits > 0)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
+ const gl::InternalFormat &formatInfo =
+ isSubImage ? *texture->getFormat(target, level).info
+ : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
- if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
+ if (formatInfo.depthBits > 0 || formatInfo.compressed)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
@@ -1679,7 +2408,7 @@ bool ValidateCopyTexImageParametersBase(ValidationContext *context,
static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
}
@@ -1687,118 +2416,193 @@ bool ValidateCopyTexImageParametersBase(ValidationContext *context,
{
if (IsCubeMapTextureTarget(target) && width != height)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
return false;
}
if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
{
- context->recordError(Error(GL_INVALID_ENUM));
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
return false;
}
int maxLevelDimension = (maxDimension >> level);
- if (static_cast<int>(width) > maxLevelDimension || static_cast<int>(height) > maxLevelDimension)
+ if (static_cast<int>(width) > maxLevelDimension ||
+ static_cast<int>(height) > maxLevelDimension)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
+ return false;
+ }
+ }
+
+ if (textureFormatOut)
+ {
+ *textureFormatOut = texture->getFormat(target, level);
+ }
+
+ // Detect texture copying feedback loops for WebGL.
+ if (context->getExtensions().webglCompatibility)
+ {
+ if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
{
- context->recordError(Error(GL_INVALID_VALUE));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
return false;
}
}
- *textureFormatOut = texture->getInternalFormat(target, level);
return true;
}
-static bool ValidateDrawBase(ValidationContext *context,
- GLenum mode,
- GLsizei count,
- GLsizei primcount)
+bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
{
switch (mode)
{
- case GL_POINTS:
- case GL_LINES:
- case GL_LINE_LOOP:
- case GL_LINE_STRIP:
- case GL_TRIANGLES:
- case GL_TRIANGLE_STRIP:
- case GL_TRIANGLE_FAN:
- break;
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
+ case GL_POINTS:
+ case GL_LINES:
+ case GL_LINE_LOOP:
+ case GL_LINE_STRIP:
+ case GL_TRIANGLES:
+ case GL_TRIANGLE_STRIP:
+ case GL_TRIANGLE_FAN:
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
+ return false;
}
if (count < 0)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
return false;
}
- const State &state = context->getState();
+ const State &state = context->getGLState();
+
+ const Extensions &extensions = context->getExtensions();
- // Check for mapped buffers
- if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
+ // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
+ // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
+ // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
+ if (!extensions.webglCompatibility)
{
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
+ // Check for mapped buffers
+ // TODO(jmadill): Optimize this check for non - WebGL contexts.
+ if (state.hasMappedBuffer(BufferBinding::Array))
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
}
- if (context->getLimitations().noSeparateStencilRefsAndMasks)
+ // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
+ // Section 6.10 of the WebGL 1.0 spec.
+ Framebuffer *framebuffer = state.getDrawFramebuffer();
+ if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
{
- const Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
- const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
- GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
- GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
+ const FramebufferAttachment *dsAttachment =
+ framebuffer->getStencilOrDepthStencilAttachment();
+ GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
+ GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
const DepthStencilState &depthStencilState = state.getDepthStencilState();
- if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
- (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
- state.getStencilRef() != state.getStencilBackRef() ||
- (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
- (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
+
+ bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
+ bool differentWritemasks =
+ (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
+ (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
+ bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
+ (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
+
+ if (differentRefs || differentWritemasks || differentMasks)
{
- // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
- // Section 6.10 of the WebGL 1.0 spec
- ERR(
- "This ANGLE implementation does not support separate front/back stencil "
- "writemasks, reference values, or stencil mask values.");
- context->recordError(Error(GL_INVALID_OPERATION));
+ if (!extensions.webglCompatibility)
+ {
+ ERR() << "This ANGLE implementation does not support separate front/back stencil "
+ "writemasks, reference values, or stencil mask values.";
+ }
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
return false;
}
}
- const gl::Framebuffer *fbo = state.getDrawFramebuffer();
- if (!fbo || fbo->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
+ if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
{
- context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ context->handleError(InvalidFramebufferOperation());
return false;
}
gl::Program *program = state.getProgram();
if (!program)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
return false;
}
- if (!program->validateSamplers(NULL, context->getCaps()))
+ // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
+ // vertex shader stage or fragment shader stage is a undefined behaviour.
+ // But ANGLE should clearly generate an INVALID_OPERATION error instead of
+ // produce undefined result.
+ if (program->isLinked() &&
+ (!program->hasLinkedVertexShader() || !program->hasLinkedFragmentShader()))
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
+ "vertex shader stage or fragment shader stage.");
return false;
}
+ if (!program->validateSamplers(nullptr, context->getCaps()))
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+
+ if (extensions.multiview)
+ {
+ const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
+ const int framebufferNumViews = framebuffer->getNumViews();
+ if (framebufferNumViews != programNumViews)
+ {
+ context->handleError(InvalidOperation() << "The number of views in the active program "
+ "and draw framebuffer does not match.");
+ return false;
+ }
+
+ const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
+ if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
+ framebufferNumViews > 1)
+ {
+ context->handleError(InvalidOperation()
+ << "There is an active transform feedback object "
+ "when the number of views in the active draw "
+ "framebuffer is greater than 1.");
+ return false;
+ }
+
+ if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
+ state.isQueryActive(GL_TIME_ELAPSED_EXT))
+ {
+ context->handleError(InvalidOperation() << "There is an active query for target "
+ "GL_TIME_ELAPSED_EXT when the number of "
+ "views in the active draw framebuffer is "
+ "greater than 1.");
+ return false;
+ }
+ }
+
// Uniform buffer validation
- for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
+ for (unsigned int uniformBlockIndex = 0;
+ uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
{
- const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
- GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
+ const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
+ GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
const OffsetBindingPointer<Buffer> &uniformBuffer =
state.getIndexedUniformBuffer(blockBinding);
if (uniformBuffer.get() == nullptr)
{
// undefined behaviour
- context->recordError(Error(GL_INVALID_OPERATION, "It is undefined behaviour to have a used but unbound uniform buffer."));
+ context->handleError(
+ InvalidOperation()
+ << "It is undefined behaviour to have a used but unbound uniform buffer.");
return false;
}
@@ -1812,7 +2616,32 @@ static bool ValidateDrawBase(ValidationContext *context,
if (uniformBufferSize < uniformBlock.dataSize)
{
// undefined behaviour
- context->recordError(Error(GL_INVALID_OPERATION, "It is undefined behaviour to use a uniform buffer that is too small."));
+ context->handleError(
+ InvalidOperation()
+ << "It is undefined behaviour to use a uniform buffer that is too small.");
+ return false;
+ }
+ }
+
+ // Do some additonal WebGL-specific validation
+ if (extensions.webglCompatibility)
+ {
+ // Detect rendering feedback loops for WebGL.
+ if (framebuffer->formsRenderingFeedbackLoopWith(state))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
+ return false;
+ }
+
+ // Detect that the vertex shader input types match the attribute types
+ if (!ValidateVertexShaderAttributeTypeMatch(context))
+ {
+ return false;
+ }
+
+ // Detect that the color buffer types match the fragment shader output types
+ if (!ValidateFragmentShaderColorBufferTypeMatch(context))
+ {
return false;
}
}
@@ -1821,32 +2650,49 @@ static bool ValidateDrawBase(ValidationContext *context,
return (count > 0);
}
-bool ValidateDrawArrays(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
+bool ValidateDrawArraysCommon(ValidationContext *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount)
{
if (first < 0)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
return false;
}
- const State &state = context->getState();
+ const State &state = context->getGLState();
gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
- if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused() &&
- curTransformFeedback->getPrimitiveMode() != mode)
+ if (curTransformFeedback && curTransformFeedback->isActive() &&
+ !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
{
// It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
- // that does not match the current transform feedback object's draw mode (if transform feedback
+ // that does not match the current transform feedback object's draw mode (if transform
+ // feedback
// is active), (3.0.2, section 2.14, pg 86)
- context->recordError(Error(GL_INVALID_OPERATION));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
+ return false;
+ }
+
+ if (!ValidateDrawBase(context, mode, count))
+ {
return false;
}
- if (!ValidateDrawBase(context, mode, count, primcount))
+ // Check the computation of maxVertex doesn't overflow.
+ // - first < 0 or count < 0 have been checked as an error condition
+ // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
+ // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
+ ASSERT(count > 0 && first >= 0);
+ int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
+ if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
{
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
return false;
}
- if (!ValidateDrawAttribs(context, primcount, count))
+ if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
{
return false;
}
@@ -1854,223 +2700,264 @@ bool ValidateDrawArrays(Context *context, GLenum mode, GLint first, GLsizei coun
return true;
}
-bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
+bool ValidateDrawArraysInstancedANGLE(Context *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount)
{
- if (primcount < 0)
+ if (!context->getExtensions().instancedArrays)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
- if (!ValidateDrawArrays(context, mode, first, count, primcount))
+ if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
{
return false;
}
- // No-op if zero primitive count
- return (primcount > 0);
+ return ValidateDrawInstancedANGLE(context);
}
-static bool ValidateDrawInstancedANGLE(Context *context)
+bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
{
- // Verify there is at least one active attribute with a divisor of zero
- const gl::State& state = context->getState();
-
- gl::Program *program = state.getProgram();
-
- const VertexArray *vao = state.getVertexArray();
- for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
+ switch (type)
{
- const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
- if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
- {
- return true;
- }
+ case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_SHORT:
+ break;
+ case GL_UNSIGNED_INT:
+ if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
+ return false;
+ }
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
+ return false;
}
- context->recordError(Error(GL_INVALID_OPERATION, "ANGLE_instanced_arrays requires that at least one active attribute"
- "has a divisor of zero."));
- return false;
-}
+ const State &state = context->getGLState();
-bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
-{
- if (!ValidateDrawInstancedANGLE(context))
+ gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
+ if (curTransformFeedback && curTransformFeedback->isActive() &&
+ !curTransformFeedback->isPaused())
{
+ // It is an invalid operation to call DrawElements, DrawRangeElements or
+ // DrawElementsInstanced
+ // while transform feedback is active, (3.0.2, section 2.14, pg 86)
+ context->handleError(InvalidOperation());
return false;
}
- return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
+ return true;
}
-bool ValidateDrawElements(ValidationContext *context,
- GLenum mode,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- GLsizei primcount,
- IndexRange *indexRangeOut)
+bool ValidateDrawElementsCommon(ValidationContext *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei primcount)
{
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- case GL_UNSIGNED_SHORT:
- break;
- case GL_UNSIGNED_INT:
- if (context->getClientVersion() < 3 && !context->getExtensions().elementIndexUint)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- break;
- default:
- context->recordError(Error(GL_INVALID_ENUM));
+ if (!ValidateDrawElementsBase(context, type))
return false;
- }
- const State &state = context->getState();
+ const State &state = context->getGLState();
- gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
- if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused())
+ if (!ValidateDrawBase(context, mode, count))
{
- // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced
- // while transform feedback is active, (3.0.2, section 2.14, pg 86)
- context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
- // Check for mapped buffers
- if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
+ // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
+ // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
+ // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
+ if (!context->getExtensions().webglCompatibility)
{
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
+ // Check for mapped buffers
+ // TODO(jmadill): Optimize this check for non - WebGL contexts.
+ if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
+ {
+ context->handleError(InvalidOperation() << "Index buffer is mapped.");
+ return false;
+ }
}
- const gl::VertexArray *vao = state.getVertexArray();
+ const gl::VertexArray *vao = state.getVertexArray();
gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
- if (!indices && !elementArrayBuffer)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- if (elementArrayBuffer)
- {
- const gl::Type &typeInfo = gl::GetTypeInfo(type);
-
- GLint64 offset = reinterpret_cast<GLint64>(indices);
- GLint64 byteCount = static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count)+offset;
+ GLuint typeBytes = gl::GetTypeInfo(type).bytes;
- // check for integer overflows
- if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
- byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
+ if (context->getExtensions().webglCompatibility)
+ {
+ ASSERT(isPow2(typeBytes) && typeBytes > 0);
+ if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
{
- context->recordError(Error(GL_OUT_OF_MEMORY));
+ // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
+ // The offset arguments to drawElements and [...], must be a multiple of the size of the
+ // data type passed to the call, or an INVALID_OPERATION error is generated.
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
return false;
}
- // Check for reading past the end of the bound buffer object
- if (byteCount > elementArrayBuffer->getSize())
+ // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
+ // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
+ // error is generated.
+ if (reinterpret_cast<intptr_t>(indices) < 0)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
return false;
}
}
- else if (!indices)
+
+ if (context->getExtensions().webglCompatibility ||
+ !context->getGLState().areClientArraysEnabled())
{
- // Catch this programming error here
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
+ if (!elementArrayBuffer && count > 0)
+ {
+ // [WebGL 1.0] Section 6.2 No Client Side Arrays
+ // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
+ // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
+ return false;
+ }
}
- if (!ValidateDrawBase(context, mode, count, primcount))
+ if (count > 0)
{
- return false;
+ if (elementArrayBuffer)
+ {
+ // The max possible type size is 8 and count is on 32 bits so doing the multiplication
+ // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
+ static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
+ constexpr uint64_t kMaxTypeSize = 8;
+ constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
+ constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
+ static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
+
+ uint64_t typeSize = typeBytes;
+ uint64_t elementCount = static_cast<uint64_t>(count);
+ ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
+
+ // Doing the multiplication here is overflow-safe
+ uint64_t elementDataSizeNoOffset = typeSize * elementCount;
+
+ // The offset can be any value, check for overflows
+ uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
+ if (elementDataSizeNoOffset > kUint64Max - offset)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
+ return false;
+ }
+
+ uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
+ if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
+ return false;
+ }
+
+ ASSERT(isPow2(typeSize) && typeSize > 0);
+ if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
+ return false;
+ }
+ }
+ else if (!indices)
+ {
+ // This is an application error that would normally result in a crash,
+ // but we catch it and return an error
+ context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
+ return false;
+ }
}
- // Use max index to validate if our vertex buffers are large enough for the pull.
- // TODO: offer fast path, with disabled index validation.
- // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
- if (elementArrayBuffer)
+ if (context->getExtensions().robustBufferAccessBehavior)
{
- uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
- Error error =
- elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
- state.isPrimitiveRestartEnabled(), indexRangeOut);
- if (error.isError())
+ // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
+ // access is enabled.
+ if (!ValidateDrawAttribs(context, primcount, 0, 1))
{
- context->recordError(error);
return false;
}
}
else
{
- *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
- }
+ // Use the parameter buffer to retrieve and cache the index range.
+ const auto &params = context->getParams<HasIndexRange>();
+ const auto &indexRangeOpt = params.getIndexRange();
+ if (!indexRangeOpt.valid())
+ {
+ // Unexpected error.
+ return false;
+ }
- // If we use an index greater than our maximum supported index range, return an error.
- // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
- // return an error if possible here.
- if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
- {
- context->recordError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
- return false;
- }
+ // If we use an index greater than our maximum supported index range, return an error.
+ // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
+ // return an error if possible here.
+ if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
+ return false;
+ }
- if (!ValidateDrawAttribs(context, primcount, static_cast<GLsizei>(indexRangeOut->end)))
- {
- return false;
+ if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
+ static_cast<GLint>(indexRangeOpt.value().vertexCount())))
+ {
+ return false;
+ }
+
+ // No op if there are no real indices in the index data (all are primitive restart).
+ return (indexRangeOpt.value().vertexIndexCount > 0);
}
- // No op if there are no real indices in the index data (all are primitive restart).
- return (indexRangeOut->vertexIndexCount > 0);
+ return true;
}
-bool ValidateDrawElementsInstanced(Context *context,
- GLenum mode,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- GLsizei primcount,
- IndexRange *indexRangeOut)
+bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei primcount)
{
- if (primcount < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
-
- if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
- {
- return false;
- }
-
- // No-op zero primitive count
- return (primcount > 0);
+ return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
}
bool ValidateDrawElementsInstancedANGLE(Context *context,
GLenum mode,
GLsizei count,
GLenum type,
- const GLvoid *indices,
- GLsizei primcount,
- IndexRange *indexRangeOut)
+ const void *indices,
+ GLsizei primcount)
{
- if (!ValidateDrawInstancedANGLE(context))
+ if (!context->getExtensions().instancedArrays)
{
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
- return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, indexRangeOut);
+ if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
+ {
+ return false;
+ }
+
+ return ValidateDrawInstancedANGLE(context);
}
-bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
- GLuint texture, GLint level)
+bool ValidateFramebufferTextureBase(Context *context,
+ GLenum target,
+ GLenum attachment,
+ GLuint texture,
+ GLint level)
{
- if (!ValidFramebufferTarget(target))
+ if (!ValidFramebufferTarget(context, target))
{
- context->recordError(Error(GL_INVALID_ENUM));
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
return false;
}
@@ -2085,198 +2972,199 @@ bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum atta
if (tex == NULL)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
if (level < 0)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
}
- const gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
+ const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
ASSERT(framebuffer);
if (framebuffer->id() == 0)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
return false;
}
return true;
}
-bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment,
- GLenum textarget, GLuint texture, GLint level)
+bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
{
- // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap extension
- if (context->getClientVersion() < 3 && !context->getExtensions().fboRenderMipmap && level != 0)
+ if (program == 0)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
- if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
+ gl::Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
{
return false;
}
- if (texture != 0)
+ if (!programObject || !programObject->isLinked())
{
- gl::Texture *tex = context->getTexture(texture);
- ASSERT(tex);
-
- const gl::Caps &caps = context->getCaps();
-
- switch (textarget)
- {
- case GL_TEXTURE_2D:
- {
- if (level > gl::log2(caps.max2DTextureSize))
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
- if (tex->getTarget() != GL_TEXTURE_2D)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- }
- break;
-
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- {
- if (level > gl::log2(caps.maxCubeMapTextureSize))
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
- if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- }
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
+ return false;
+ }
- const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(tex->getInternalFormat(textarget, level));
- if (internalFormatInfo.compressed)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
+ if (!programObject->isValidUniformLocation(location))
+ {
+ context->handleError(InvalidOperation());
+ return false;
}
return true;
}
-bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
+static bool ValidateSizedGetUniform(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length)
{
- if (program == 0)
+ if (length)
{
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
+ *length = 0;
}
- gl::Program *programObject = GetValidProgram(context, program);
- if (!programObject)
+ if (!ValidateGetUniformBase(context, program, location))
{
return false;
}
- if (!programObject || !programObject->isLinked())
+ if (bufSize < 0)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
return false;
}
- if (!programObject->isValidUniformLocation(location))
+ gl::Program *programObject = context->getProgram(program);
+ ASSERT(programObject);
+
+ // sized queries -- ensure the provided buffer is large enough
+ const LinkedUniform &uniform = programObject->getUniformByLocation(location);
+ size_t requiredBytes = VariableExternalSize(uniform.type);
+ if (static_cast<size_t>(bufSize) < requiredBytes)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
return false;
}
+ if (length)
+ {
+ *length = VariableComponentCount(uniform.type);
+ }
+
return true;
}
-bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params)
+bool ValidateGetnUniformfvEXT(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLfloat *params)
{
- return ValidateGetUniformBase(context, program, location);
+ return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
}
-bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params)
+bool ValidateGetnUniformivEXT(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLint *params)
{
- return ValidateGetUniformBase(context, program, location);
+ return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
}
-static bool ValidateSizedGetUniform(Context *context, GLuint program, GLint location, GLsizei bufSize)
+bool ValidateGetUniformfvRobustANGLE(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params)
{
- if (!ValidateGetUniformBase(context, program, location))
+ if (!ValidateRobustEntryPoint(context, bufSize))
{
return false;
}
- gl::Program *programObject = context->getProgram(program);
- ASSERT(programObject);
+ // bufSize is validated in ValidateSizedGetUniform
+ return ValidateSizedGetUniform(context, program, location, bufSize, length);
+}
- // sized queries -- ensure the provided buffer is large enough
- const LinkedUniform &uniform = programObject->getUniformByLocation(location);
- size_t requiredBytes = VariableExternalSize(uniform.type);
- if (static_cast<size_t>(bufSize) < requiredBytes)
+bool ValidateGetUniformivRobustANGLE(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
{
- context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
- return true;
+ // bufSize is validated in ValidateSizedGetUniform
+ return ValidateSizedGetUniform(context, program, location, bufSize, length);
}
-bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
+bool ValidateGetUniformuivRobustANGLE(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params)
{
- return ValidateSizedGetUniform(context, program, location, bufSize);
-}
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
-bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params)
-{
- return ValidateSizedGetUniform(context, program, location, bufSize);
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ // bufSize is validated in ValidateSizedGetUniform
+ return ValidateSizedGetUniform(context, program, location, bufSize, length);
}
-bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments,
- const GLenum *attachments, bool defaultFramebuffer)
+bool ValidateDiscardFramebufferBase(Context *context,
+ GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ bool defaultFramebuffer)
{
if (numAttachments < 0)
{
- context->recordError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
return false;
}
for (GLsizei i = 0; i < numAttachments; ++i)
{
- if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15)
+ if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
{
if (defaultFramebuffer)
{
- context->recordError(Error(GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
return false;
}
if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
{
- context->recordError(Error(GL_INVALID_OPERATION,
- "Requested color attachment is greater than the maximum supported color attachments"));
+ context->handleError(InvalidOperation() << "Requested color attachment is "
+ "greater than the maximum supported "
+ "color attachments");
return false;
}
}
@@ -2284,27 +3172,29 @@ bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei num
{
switch (attachments[i])
{
- case GL_DEPTH_ATTACHMENT:
- case GL_STENCIL_ATTACHMENT:
- case GL_DEPTH_STENCIL_ATTACHMENT:
- if (defaultFramebuffer)
- {
- context->recordError(Error(GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
- return false;
- }
- break;
- case GL_COLOR:
- case GL_DEPTH:
- case GL_STENCIL:
- if (!defaultFramebuffer)
- {
- context->recordError(Error(GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is not bound"));
+ case GL_DEPTH_ATTACHMENT:
+ case GL_STENCIL_ATTACHMENT:
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ if (defaultFramebuffer)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(),
+ DefaultFramebufferInvalidAttachment);
+ return false;
+ }
+ break;
+ case GL_COLOR:
+ case GL_DEPTH:
+ case GL_STENCIL:
+ if (!defaultFramebuffer)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(),
+ DefaultFramebufferInvalidAttachment);
+ return false;
+ }
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
return false;
- }
- break;
- default:
- context->recordError(Error(GL_INVALID_ENUM, "Invalid attachment"));
- return false;
}
}
}
@@ -2347,44 +3237,58 @@ bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *ma
}
bool ValidateEGLImageTargetTexture2DOES(Context *context,
- egl::Display *display,
GLenum target,
egl::Image *image)
{
if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
switch (target)
{
case GL_TEXTURE_2D:
+ if (!context->getExtensions().eglImage)
+ {
+ context->handleError(InvalidEnum()
+ << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
+ }
+ break;
+
+ case GL_TEXTURE_EXTERNAL_OES:
+ if (!context->getExtensions().eglImageExternal)
+ {
+ context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
+ "requires GL_OES_EGL_image_external.");
+ }
break;
default:
- context->recordError(Error(GL_INVALID_ENUM, "invalid texture target."));
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
return false;
}
- if (!display->isValidImage(image))
+ ASSERT(context->getCurrentDisplay());
+ if (!context->getCurrentDisplay()->isValidImage(image))
{
- context->recordError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
+ context->handleError(InvalidValue() << "EGL image is not valid.");
return false;
}
if (image->getSamples() > 0)
{
- context->recordError(Error(GL_INVALID_OPERATION,
- "cannot create a 2D texture from a multisampled EGL image."));
+ context->handleError(InvalidOperation()
+ << "cannot create a 2D texture from a multisampled EGL image.");
return false;
}
- const TextureCaps &textureCaps = context->getTextureCaps().get(image->getInternalFormat());
+ const TextureCaps &textureCaps =
+ context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
if (!textureCaps.texturable)
{
- context->recordError(Error(GL_INVALID_OPERATION,
- "EGL image internal format is not supported as a texture."));
+ context->handleError(InvalidOperation()
+ << "EGL image internal format is not supported as a texture.");
return false;
}
@@ -2392,13 +3296,12 @@ bool ValidateEGLImageTargetTexture2DOES(Context *context,
}
bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
- egl::Display *display,
GLenum target,
egl::Image *image)
{
if (!context->getExtensions().eglImage)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
@@ -2408,21 +3311,23 @@ bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
break;
default:
- context->recordError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
return false;
}
- if (!display->isValidImage(image))
+ ASSERT(context->getCurrentDisplay());
+ if (!context->getCurrentDisplay()->isValidImage(image))
{
- context->recordError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
+ context->handleError(InvalidValue() << "EGL image is not valid.");
return false;
}
- const TextureCaps &textureCaps = context->getTextureCaps().get(image->getInternalFormat());
+ const TextureCaps &textureCaps =
+ context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
if (!textureCaps.renderable)
{
- context->recordError(Error(
- GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
+ context->handleError(InvalidOperation()
+ << "EGL image internal format is not supported as a renderbuffer.");
return false;
}
@@ -2435,29 +3340,7 @@ bool ValidateBindVertexArrayBase(Context *context, GLuint array)
{
// The default VAO should always exist
ASSERT(array != 0);
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
-
- return true;
-}
-
-bool ValidateDeleteVertexArraysBase(Context *context, GLsizei n)
-{
- if (n < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
-
- return true;
-}
-
-bool ValidateGenVertexArraysBase(Context *context, GLsizei n)
-{
- if (n < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidOperation());
return false;
}
@@ -2480,7 +3363,16 @@ bool ValidateProgramBinaryBase(Context *context,
if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
programBinaryFormats.end())
{
- context->recordError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
+ context->handleError(InvalidEnum() << "Program binary format is not valid.");
+ return false;
+ }
+
+ if (context->hasActiveTransformFeedback(program))
+ {
+ // ES 3.0.4 section 2.15 page 91
+ context->handleError(InvalidOperation() << "Cannot change program binary while program "
+ "is associated with an active transform "
+ "feedback object.");
return false;
}
@@ -2502,63 +3394,35 @@ bool ValidateGetProgramBinaryBase(Context *context,
if (!programObject->isLinked())
{
- context->recordError(Error(GL_INVALID_OPERATION, "Program is not linked."));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
return false;
}
- return true;
-}
-
-bool ValidateCopyTexImage2D(ValidationContext *context,
- GLenum target,
- GLint level,
- GLenum internalformat,
- GLint x,
- GLint y,
- GLsizei width,
- GLsizei height,
- GLint border)
-{
- if (context->getClientVersion() < 3)
- {
- return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
- 0, x, y, width, height, border);
- }
-
- ASSERT(context->getClientVersion() == 3);
- return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
- 0, x, y, width, height, border);
-}
-
-bool ValidateFramebufferRenderbuffer(Context *context,
- GLenum target,
- GLenum attachment,
- GLenum renderbuffertarget,
- GLuint renderbuffer)
-{
- if (!ValidFramebufferTarget(target) ||
- (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
+ if (context->getCaps().programBinaryFormats.empty())
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidOperation() << "No program binary formats supported.");
return false;
}
- return ValidateFramebufferRenderbufferParameters(context, target, attachment,
- renderbuffertarget, renderbuffer);
+ return true;
}
bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
{
// INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
- if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
+ if (n < 0)
{
- context->recordError(
- Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
+ return false;
+ }
+ if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
return false;
}
- ASSERT(context->getState().getDrawFramebuffer());
- GLuint frameBufferId = context->getState().getDrawFramebuffer()->id();
+ ASSERT(context->getGLState().getDrawFramebuffer());
+ GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
// This should come first before the check for the default frame buffer
@@ -2569,13 +3433,21 @@ bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum
const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
- (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0_EXT ||
- bufs[colorAttachment] >= maxColorAttachment))
+ (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
+ bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
{
// Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
- // In the 3.0 specs, the error should return GL_INVALID_OPERATION.
- // When we move to 3.1 specs, we should change the error to be GL_INVALID_ENUM
- context->recordError(Error(GL_INVALID_OPERATION, "Invalid buffer value"));
+ // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
+ // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
+ // 3.1 is still a bit ambiguous about the error, but future specs are
+ // expected to clarify that GL_INVALID_ENUM is the correct error.
+ context->handleError(InvalidEnum() << "Invalid buffer value");
+ return false;
+ }
+ else if (bufs[colorAttachment] >= maxColorAttachment)
+ {
+ context->handleError(InvalidOperation()
+ << "Buffer value is greater than MAX_DRAW_BUFFERS");
return false;
}
else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
@@ -2583,8 +3455,8 @@ bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum
{
// INVALID_OPERATION-GL is bound to buffer and ith argument
// is not COLOR_ATTACHMENTi or NONE
- context->recordError(
- Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
+ context->handleError(InvalidOperation()
+ << "Ith value does not match COLOR_ATTACHMENTi or NONE");
return false;
}
}
@@ -2595,16 +3467,16 @@ bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum
{
if (n != 1)
{
- context->recordError(Error(GL_INVALID_OPERATION,
- "n must be 1 when GL is bound to the default framebuffer"));
+ context->handleError(InvalidOperation()
+ << "n must be 1 when GL is bound to the default framebuffer");
return false;
}
if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
{
- context->recordError(Error(
- GL_INVALID_OPERATION,
- "Only NONE or BACK are valid values when drawing to the default framebuffer"));
+ context->handleError(
+ InvalidOperation()
+ << "Only NONE or BACK are valid values when drawing to the default framebuffer");
return false;
}
}
@@ -2612,24 +3484,2345 @@ bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum
return true;
}
-bool ValidateCopyTexSubImage2D(Context *context,
- GLenum target,
- GLint level,
- GLint xoffset,
- GLint yoffset,
- GLint x,
- GLint y,
- GLsizei width,
- GLsizei height)
+bool ValidateGetBufferPointervBase(Context *context,
+ BufferBinding target,
+ GLenum pname,
+ GLsizei *length,
+ void **params)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
+ {
+ context->handleError(
+ InvalidOperation()
+ << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
+ return false;
+ }
+
+ if (!ValidBufferType(context, target))
+ {
+ context->handleError(InvalidEnum() << "Buffer target not valid");
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_BUFFER_MAP_POINTER:
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+
+ // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
+ // target bound to zero generate an INVALID_OPERATION error."
+ // GLES 3.1 section 6.6 explicitly specifies this error.
+ if (context->getGLState().getTargetBuffer(target) == nullptr)
+ {
+ context->handleError(InvalidOperation()
+ << "Can not get pointer for reserved buffer name zero.");
+ return false;
+ }
+
+ if (length)
+ {
+ *length = 1;
+ }
+
+ return true;
+}
+
+bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
+{
+ if (!ValidBufferType(context, target))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
+ return false;
+ }
+
+ Buffer *buffer = context->getGLState().getTargetBuffer(target);
+
+ if (buffer == nullptr || !buffer->isMapped())
+ {
+ context->handleError(InvalidOperation() << "Buffer not mapped.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateMapBufferRangeBase(Context *context,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access)
+{
+ if (!ValidBufferType(context, target))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
+ return false;
+ }
+
+ if (offset < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
+ return false;
+ }
+
+ if (length < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
+ return false;
+ }
+
+ Buffer *buffer = context->getGLState().getTargetBuffer(target);
+
+ if (!buffer)
+ {
+ context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
+ return false;
+ }
+
+ // Check for buffer overflow
+ CheckedNumeric<size_t> checkedOffset(offset);
+ auto checkedSize = checkedOffset + length;
+
+ if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
+ {
+ context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
+ return false;
+ }
+
+ // Check for invalid bits in the mask
+ GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
+ GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
+ GL_MAP_UNSYNCHRONIZED_BIT;
+
+ if (access & ~(allAccessBits))
+ {
+ context->handleError(InvalidValue()
+ << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
+ return false;
+ }
+
+ if (length == 0)
+ {
+ context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
+ return false;
+ }
+
+ if (buffer->isMapped())
+ {
+ context->handleError(InvalidOperation() << "Buffer is already mapped.");
+ return false;
+ }
+
+ // Check for invalid bit combinations
+ if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
+ {
+ context->handleError(InvalidOperation()
+ << "Need to map buffer for either reading or writing.");
+ return false;
+ }
+
+ GLbitfield writeOnlyBits =
+ GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
+
+ if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
+ {
+ context->handleError(InvalidOperation()
+ << "Invalid access bits when mapping buffer for reading: 0x"
+ << std::hex << std::uppercase << access);
+ return false;
+ }
+
+ if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
+ {
+ context->handleError(
+ InvalidOperation()
+ << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
+ return false;
+ }
+
+ return ValidateMapBufferBase(context, target);
+}
+
+bool ValidateFlushMappedBufferRangeBase(Context *context,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length)
{
- if (context->getClientVersion() < 3)
+ if (offset < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
+ return false;
+ }
+
+ if (length < 0)
{
- return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
- yoffset, x, y, width, height, 0);
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
+ return false;
}
- return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
- yoffset, 0, x, y, width, height, 0);
+ if (!ValidBufferType(context, target))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
+ return false;
+ }
+
+ Buffer *buffer = context->getGLState().getTargetBuffer(target);
+
+ if (buffer == nullptr)
+ {
+ context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
+ return false;
+ }
+
+ if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
+ {
+ context->handleError(InvalidOperation()
+ << "Attempted to flush a buffer not mapped for explicit flushing.");
+ return false;
+ }
+
+ // Check for buffer overflow
+ CheckedNumeric<size_t> checkedOffset(offset);
+ auto checkedSize = checkedOffset + length;
+
+ if (!checkedSize.IsValid() ||
+ checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
+ {
+ context->handleError(InvalidValue()
+ << "Flushed range does not fit into buffer mapping dimensions.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGenOrDelete(Context *context, GLint n)
+{
+ if (n < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
+{
+ if (!context->getExtensions().robustClientMemory)
+ {
+ context->handleError(InvalidOperation()
+ << "GL_ANGLE_robust_client_memory is not available.");
+ return false;
+ }
+
+ if (bufSize < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
+{
+ if (bufSize < numParams)
+ {
+ context->handleError(InvalidOperation() << numParams << " parameters are required but "
+ << bufSize << " were provided.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLsizei *numParams)
+{
+ if (!ValidFramebufferTarget(context, target))
+ {
+ context->handleError(InvalidEnum());
+ return false;
+ }
+
+ int clientVersion = context->getClientMajorVersion();
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
+ if (clientVersion < 3 || !context->getExtensions().multiview)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
+ if (clientVersion < 3 && !context->getExtensions().sRGB)
+ {
+ context->handleError(InvalidEnum());
+ return false;
+ }
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
+ case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
+ case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
+ case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
+ case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
+ case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
+ case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
+ if (clientVersion < 3)
+ {
+ context->handleError(InvalidEnum());
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(InvalidEnum());
+ return false;
+ }
+
+ // Determine if the attachment is a valid enum
+ switch (attachment)
+ {
+ case GL_BACK:
+ case GL_DEPTH:
+ case GL_STENCIL:
+ if (clientVersion < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
+ return false;
+ }
+ break;
+
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ if (clientVersion < 3 && !context->isWebGL1())
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
+ return false;
+ }
+ break;
+
+ case GL_COLOR_ATTACHMENT0:
+ case GL_DEPTH_ATTACHMENT:
+ case GL_STENCIL_ATTACHMENT:
+ break;
+
+ default:
+ if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
+ attachment < GL_COLOR_ATTACHMENT0_EXT ||
+ (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
+ return false;
+ }
+ break;
+ }
+
+ const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (framebuffer->id() == 0)
+ {
+ if (clientVersion < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
+ return false;
+ }
+
+ switch (attachment)
+ {
+ case GL_BACK:
+ case GL_DEPTH:
+ case GL_STENCIL:
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
+ return false;
+ }
+ }
+ else
+ {
+ if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
+ {
+ // Valid attachment query
+ }
+ else
+ {
+ switch (attachment)
+ {
+ case GL_DEPTH_ATTACHMENT:
+ case GL_STENCIL_ATTACHMENT:
+ break;
+
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
+ return false;
+ }
+ }
+ }
+
+ const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
+ if (attachmentObject)
+ {
+ ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
+ attachmentObject->type() == GL_TEXTURE ||
+ attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+ if (attachmentObject->type() != GL_RENDERBUFFER &&
+ attachmentObject->type() != GL_TEXTURE)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
+ return false;
+ }
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
+ if (attachmentObject->type() != GL_TEXTURE)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
+ return false;
+ }
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
+ if (attachmentObject->type() != GL_TEXTURE)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
+ return false;
+ }
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
+ if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
+ return false;
+ }
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
+ if (attachmentObject->type() != GL_TEXTURE)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
+ return false;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
+ // is NONE, then querying any other pname will generate INVALID_ENUM.
+
+ // ES 3.0.2 spec pg 235 states that if the attachment type is none,
+ // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
+ // INVALID_OPERATION for all other pnames
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+ if (clientVersion < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(),
+ InvalidFramebufferAttachmentParameter);
+ return false;
+ }
+ break;
+
+ default:
+ if (clientVersion < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(),
+ InvalidFramebufferAttachmentParameter);
+ return false;
+ }
+ else
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(),
+ InvalidFramebufferAttachmentParameter);
+ return false;
+ }
+ }
+ }
+
+ if (numParams)
+ {
+ if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
+ {
+ // Only when the viewport offsets are queried we can have a varying number of output
+ // parameters.
+ const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
+ *numParams = numViews * 2;
+ }
+ else
+ {
+ // For all other queries we can have only one output parameter.
+ *numParams = 1;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *numParams)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
+ numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *numParams))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
+ BufferBinding target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
+ BufferBinding target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetProgramivBase(ValidationContext *context,
+ GLuint program,
+ GLenum pname,
+ GLsizei *numParams)
+{
+ // Currently, all GetProgramiv queries return 1 parameter
+ if (numParams)
+ {
+ *numParams = 1;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_DELETE_STATUS:
+ case GL_LINK_STATUS:
+ case GL_VALIDATE_STATUS:
+ case GL_INFO_LOG_LENGTH:
+ case GL_ATTACHED_SHADERS:
+ case GL_ACTIVE_ATTRIBUTES:
+ case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
+ case GL_ACTIVE_UNIFORMS:
+ case GL_ACTIVE_UNIFORM_MAX_LENGTH:
+ break;
+
+ case GL_PROGRAM_BINARY_LENGTH:
+ if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
+ {
+ context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
+ "requires GL_OES_get_program_binary or "
+ "ES 3.0.");
+ return false;
+ }
+ break;
+
+ case GL_ACTIVE_UNIFORM_BLOCKS:
+ case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
+ case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
+ case GL_TRANSFORM_FEEDBACK_VARYINGS:
+ case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
+ case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
+ return false;
+ }
+ break;
+
+ case GL_PROGRAM_SEPARABLE:
+ case GL_COMPUTE_WORK_GROUP_SIZE:
+ case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
+ if (context->getClientVersion() < Version(3, 1))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
+ return false;
+ }
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetProgramivRobustANGLE(Context *context,
+ GLuint program,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *numParams)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetProgramivBase(context, program, pname, numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *numParams))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetShaderivRobustANGLE(Context *context,
+ GLuint shader,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetShaderivBase(context, shader, pname, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetTexParameterfvRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetTexParameterBase(context, target, pname, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetTexParameterivRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetTexParameterBase(context, target, pname, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateTexParameterfvRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLfloat *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ return ValidateTexParameterBase(context, target, pname, bufSize, params);
+}
+
+bool ValidateTexParameterivRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ return ValidateTexParameterBase(context, target, pname, bufSize, params);
+}
+
+bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ GLuint bufSize,
+ GLsizei *length,
+ GLfloat *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ GLuint bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateSamplerParameterfvRobustANGLE(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLfloat *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
+}
+
+bool ValidateSamplerParameterivRobustANGLE(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
+}
+
+bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetVertexAttribivRobustANGLE(Context *context,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ void **pointer)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
+ GLuint program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetInternalFormativRobustANGLE(Context *context,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateVertexFormatBase(ValidationContext *context,
+ GLuint attribIndex,
+ GLint size,
+ GLenum type,
+ GLboolean pureInteger)
+{
+ const Caps &caps = context->getCaps();
+ if (attribIndex >= caps.maxVertexAttributes)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
+ return false;
+ }
+
+ if (size < 1 || size > 4)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
+ return false;
+ }
+
+ switch (type)
+ {
+ case GL_BYTE:
+ case GL_UNSIGNED_BYTE:
+ case GL_SHORT:
+ case GL_UNSIGNED_SHORT:
+ break;
+
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(InvalidEnum()
+ << "Vertex type not supported before OpenGL ES 3.0.");
+ return false;
+ }
+ break;
+
+ case GL_FIXED:
+ case GL_FLOAT:
+ if (pureInteger)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
+ return false;
+ }
+ break;
+
+ case GL_HALF_FLOAT:
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(InvalidEnum()
+ << "Vertex type not supported before OpenGL ES 3.0.");
+ return false;
+ }
+ if (pureInteger)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
+ return false;
+ }
+ break;
+
+ case GL_INT_2_10_10_10_REV:
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(InvalidEnum()
+ << "Vertex type not supported before OpenGL ES 3.0.");
+ return false;
+ }
+ if (pureInteger)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
+ return false;
+ }
+ if (size != 4)
+ {
+ context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
+ "UNSIGNED_INT_2_10_10_10_REV and "
+ "size is not 4.");
+ return false;
+ }
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
+ return false;
+ }
+
+ return true;
+}
+
+// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
+// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
+// specified clear value and the type of a buffer that is being cleared generates an
+// INVALID_OPERATION error instead of producing undefined results
+bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
+ GLint drawbuffer,
+ const GLenum *validComponentTypes,
+ size_t validComponentTypeCount)
+{
+ const FramebufferAttachment *attachment =
+ context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
+ if (attachment)
+ {
+ GLenum componentType = attachment->getFormat().info->componentType;
+ const GLenum *end = validComponentTypes + validComponentTypeCount;
+ if (std::find(validComponentTypes, end, componentType) == end)
+ {
+ context->handleError(
+ InvalidOperation()
+ << "No defined conversion between clear value and attachment format.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
+ GLsizei imageSize,
+ GLsizei dataSize)
+{
+ if (!ValidateRobustEntryPoint(context, dataSize))
+ {
+ return false;
+ }
+
+ gl::Buffer *pixelUnpackBuffer =
+ context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
+ if (pixelUnpackBuffer == nullptr)
+ {
+ if (dataSize < imageSize)
+ {
+ context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
+ }
+ }
+ return true;
+}
+
+bool ValidateGetBufferParameterBase(ValidationContext *context,
+ BufferBinding target,
+ GLenum pname,
+ bool pointerVersion,
+ GLsizei *numParams)
+{
+ if (numParams)
+ {
+ *numParams = 0;
+ }
+
+ if (!ValidBufferType(context, target))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
+ return false;
+ }
+
+ const Buffer *buffer = context->getGLState().getTargetBuffer(target);
+ if (!buffer)
+ {
+ // A null buffer means that "0" is bound to the requested buffer target
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
+ return false;
+ }
+
+ const Extensions &extensions = context->getExtensions();
+
+ switch (pname)
+ {
+ case GL_BUFFER_USAGE:
+ case GL_BUFFER_SIZE:
+ break;
+
+ case GL_BUFFER_ACCESS_OES:
+ if (!extensions.mapBuffer)
+ {
+ context->handleError(InvalidEnum()
+ << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
+ return false;
+ }
+ break;
+
+ case GL_BUFFER_MAPPED:
+ static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
+ if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
+ !extensions.mapBufferRange)
+ {
+ context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
+ "GL_OES_mapbuffer or "
+ "GL_EXT_map_buffer_range.");
+ return false;
+ }
+ break;
+
+ case GL_BUFFER_MAP_POINTER:
+ if (!pointerVersion)
+ {
+ context->handleError(
+ InvalidEnum()
+ << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
+ return false;
+ }
+ break;
+
+ case GL_BUFFER_ACCESS_FLAGS:
+ case GL_BUFFER_MAP_OFFSET:
+ case GL_BUFFER_MAP_LENGTH:
+ if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
+ {
+ context->handleError(InvalidEnum()
+ << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
+ return false;
+ }
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+
+ // All buffer parameter queries return one value.
+ if (numParams)
+ {
+ *numParams = 1;
+ }
+
+ return true;
+}
+
+bool ValidateGetRenderbufferParameterivBase(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei *length)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (target != GL_RENDERBUFFER)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
+ return false;
+ }
+
+ Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
+ if (renderbuffer == nullptr)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_RENDERBUFFER_WIDTH:
+ case GL_RENDERBUFFER_HEIGHT:
+ case GL_RENDERBUFFER_INTERNAL_FORMAT:
+ case GL_RENDERBUFFER_RED_SIZE:
+ case GL_RENDERBUFFER_GREEN_SIZE:
+ case GL_RENDERBUFFER_BLUE_SIZE:
+ case GL_RENDERBUFFER_ALPHA_SIZE:
+ case GL_RENDERBUFFER_DEPTH_SIZE:
+ case GL_RENDERBUFFER_STENCIL_SIZE:
+ break;
+
+ case GL_RENDERBUFFER_SAMPLES_ANGLE:
+ if (!context->getExtensions().framebufferMultisample)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
+ return false;
+ }
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+
+ if (length)
+ {
+ *length = 1;
+ }
+ return true;
+}
+
+bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (GetValidShader(context, shader) == nullptr)
+ {
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_SHADER_TYPE:
+ case GL_DELETE_STATUS:
+ case GL_COMPILE_STATUS:
+ case GL_INFO_LOG_LENGTH:
+ case GL_SHADER_SOURCE_LENGTH:
+ break;
+
+ case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
+ if (!context->getExtensions().translatedShaderSource)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
+ return false;
+ }
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+
+ if (length)
+ {
+ *length = 1;
+ }
+ return true;
+}
+
+bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
+ return false;
+ }
+
+ if (context->getTargetTexture(target) == nullptr)
+ {
+ // Should only be possible for external textures
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_MAG_FILTER:
+ case GL_TEXTURE_MIN_FILTER:
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ break;
+
+ case GL_TEXTURE_USAGE_ANGLE:
+ if (!context->getExtensions().textureUsage)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (!context->getExtensions().textureFilterAnisotropic)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_IMMUTABLE_FORMAT:
+ if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_WRAP_R:
+ case GL_TEXTURE_IMMUTABLE_LEVELS:
+ case GL_TEXTURE_SWIZZLE_R:
+ case GL_TEXTURE_SWIZZLE_G:
+ case GL_TEXTURE_SWIZZLE_B:
+ case GL_TEXTURE_SWIZZLE_A:
+ case GL_TEXTURE_BASE_LEVEL:
+ case GL_TEXTURE_MAX_LEVEL:
+ case GL_TEXTURE_MIN_LOD:
+ case GL_TEXTURE_MAX_LOD:
+ case GL_TEXTURE_COMPARE_MODE:
+ case GL_TEXTURE_COMPARE_FUNC:
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ if (!context->getExtensions().textureSRGBDecode)
+ {
+ context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
+ return false;
+ }
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+
+ if (length)
+ {
+ *length = 1;
+ }
+ return true;
+}
+
+bool ValidateGetVertexAttribBase(Context *context,
+ GLuint index,
+ GLenum pname,
+ GLsizei *length,
+ bool pointer,
+ bool pureIntegerEntryPoint)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
+ {
+ context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
+ return false;
+ }
+
+ if (index >= context->getCaps().maxVertexAttributes)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
+ return false;
+ }
+
+ if (pointer)
+ {
+ if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+ }
+ else
+ {
+ switch (pname)
+ {
+ case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
+ case GL_VERTEX_ATTRIB_ARRAY_SIZE:
+ case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
+ case GL_VERTEX_ATTRIB_ARRAY_TYPE:
+ case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
+ case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
+ case GL_CURRENT_VERTEX_ATTRIB:
+ break;
+
+ case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
+ static_assert(
+ GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
+ "ANGLE extension enums not equal to GL enums.");
+ if (context->getClientMajorVersion() < 3 &&
+ !context->getExtensions().instancedArrays)
+ {
+ context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
+ "requires OpenGL ES 3.0 or "
+ "GL_ANGLE_instanced_arrays.");
+ return false;
+ }
+ break;
+
+ case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->handleError(
+ InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
+ return false;
+ }
+ break;
+
+ case GL_VERTEX_ATTRIB_BINDING:
+ case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->handleError(InvalidEnum()
+ << "Vertex Attrib Bindings require OpenGL ES 3.1.");
+ return false;
+ }
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+ }
+
+ if (length)
+ {
+ if (pname == GL_CURRENT_VERTEX_ATTRIB)
+ {
+ *length = 4;
+ }
+ else
+ {
+ *length = 1;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateReadPixelsBase(Context *context,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *pixels)
+{
+ if (length != nullptr)
+ {
+ *length = 0;
+ }
+ if (rows != nullptr)
+ {
+ *rows = 0;
+ }
+ if (columns != nullptr)
+ {
+ *columns = 0;
+ }
+
+ if (width < 0 || height < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
+ return false;
+ }
+
+ Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
+
+ if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
+ {
+ context->handleError(InvalidFramebufferOperation());
+ return false;
+ }
+
+ if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+
+ const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
+ ASSERT(framebuffer);
+
+ if (framebuffer->getReadBufferState() == GL_NONE)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
+ return false;
+ }
+
+ const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
+ // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
+ // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
+ // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
+ // situation is an application error that would lead to a crash in ANGLE.
+ if (readBuffer == nullptr)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
+ return false;
+ }
+
+ // ANGLE_multiview, Revision 1:
+ // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
+ // current read framebuffer is not NONE.
+ if (readBuffer->getMultiviewLayout() != GL_NONE)
+ {
+ context->handleError(InvalidFramebufferOperation()
+ << "Attempting to read from a multi-view framebuffer.");
+ return false;
+ }
+
+ if (context->getExtensions().webglCompatibility)
+ {
+ // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
+ // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
+ // and type before validating the combination of format and type. However, the
+ // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
+ // verifies that GL_INVALID_OPERATION is generated.
+ // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
+ // dEQP/WebGL.
+ if (!ValidReadPixelsFormatEnum(context, format))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
+ return false;
+ }
+
+ if (!ValidReadPixelsTypeEnum(context, type))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
+ return false;
+ }
+ }
+
+ GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
+ GLenum currentType = framebuffer->getImplementationColorReadType(context);
+ GLenum currentComponentType = readBuffer->getFormat().info->componentType;
+
+ bool validFormatTypeCombination =
+ ValidReadPixelsFormatType(context, currentComponentType, format, type);
+
+ if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
+ return false;
+ }
+
+ // Check for pixel pack buffer related API errors
+ gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
+ if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
+ {
+ // ...the buffer object's data store is currently mapped.
+ context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
+ return false;
+ }
+
+ // .. the data would be packed to the buffer object such that the memory writes required
+ // would exceed the data store size.
+ const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
+ const gl::Extents size(width, height, 1);
+ const auto &pack = context->getGLState().getPackState();
+
+ auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
+ if (endByteOrErr.isError())
+ {
+ context->handleError(endByteOrErr.getError());
+ return false;
+ }
+
+ size_t endByte = endByteOrErr.getResult();
+ if (bufSize >= 0)
+ {
+ if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
+ return false;
+ }
+ }
+
+ if (pixelPackBuffer != nullptr)
+ {
+ CheckedNumeric<size_t> checkedEndByte(endByte);
+ CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
+ checkedEndByte += checkedOffset;
+
+ if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
+ {
+ // Overflow past the end of the buffer
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
+ return false;
+ }
+ }
+
+ if (pixelPackBuffer == nullptr && length != nullptr)
+ {
+ if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
+ return false;
+ }
+
+ *length = static_cast<GLsizei>(endByte);
+ }
+
+ auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
+ angle::CheckedNumeric<int> clippedExtent(length);
+ if (start < 0)
+ {
+ // "subtract" the area that is less than 0
+ clippedExtent += start;
+ }
+
+ const int readExtent = start + length;
+ if (readExtent > bufferSize)
+ {
+ // Subtract the region to the right of the read buffer
+ clippedExtent -= (readExtent - bufferSize);
+ }
+
+ if (!clippedExtent.IsValid())
+ {
+ return 0;
+ }
+
+ return std::max(clippedExtent.ValueOrDie(), 0);
+ };
+
+ if (columns != nullptr)
+ {
+ *columns = getClippedExtent(x, width, readBuffer->getSize().width);
+ }
+
+ if (rows != nullptr)
+ {
+ *rows = getClippedExtent(y, height, readBuffer->getSize().height);
+ }
+
+ return true;
+}
+
+template <typename ParamType>
+bool ValidateTexParameterBase(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ const ParamType *params)
+{
+ if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
+ return false;
+ }
+
+ if (context->getTargetTexture(target) == nullptr)
+ {
+ // Should only be possible for external textures
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
+ return false;
+ }
+
+ const GLsizei minBufSize = 1;
+ if (bufSize >= 0 && bufSize < minBufSize)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_WRAP_R:
+ case GL_TEXTURE_SWIZZLE_R:
+ case GL_TEXTURE_SWIZZLE_G:
+ case GL_TEXTURE_SWIZZLE_B:
+ case GL_TEXTURE_SWIZZLE_A:
+ case GL_TEXTURE_BASE_LEVEL:
+ case GL_TEXTURE_MAX_LEVEL:
+ case GL_TEXTURE_COMPARE_MODE:
+ case GL_TEXTURE_COMPARE_FUNC:
+ case GL_TEXTURE_MIN_LOD:
+ case GL_TEXTURE_MAX_LOD:
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
+ return false;
+ }
+ if (target == GL_TEXTURE_EXTERNAL_OES &&
+ !context->getExtensions().eglImageExternalEssl3)
+ {
+ context->handleError(InvalidEnum() << "ES3 texture parameters are not "
+ "available without "
+ "GL_OES_EGL_image_external_essl3.");
+ return false;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (target == GL_TEXTURE_2D_MULTISAMPLE)
+ {
+ switch (pname)
+ {
+ case GL_TEXTURE_MIN_FILTER:
+ case GL_TEXTURE_MAG_FILTER:
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ case GL_TEXTURE_WRAP_R:
+ case GL_TEXTURE_MIN_LOD:
+ case GL_TEXTURE_MAX_LOD:
+ case GL_TEXTURE_COMPARE_MODE:
+ case GL_TEXTURE_COMPARE_FUNC:
+ context->handleError(InvalidEnum()
+ << "Invalid parameter for 2D multisampled textures.");
+ return false;
+ }
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ case GL_TEXTURE_WRAP_R:
+ {
+ bool restrictedWrapModes =
+ target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
+ if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
+ {
+ return false;
+ }
+ }
+ break;
+
+ case GL_TEXTURE_MIN_FILTER:
+ {
+ bool restrictedMinFilter =
+ target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
+ if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
+ {
+ return false;
+ }
+ }
+ break;
+
+ case GL_TEXTURE_MAG_FILTER:
+ if (!ValidateTextureMagFilterValue(context, params))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_USAGE_ANGLE:
+ if (!context->getExtensions().textureUsage)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+
+ switch (ConvertToGLenum(params[0]))
+ {
+ case GL_NONE:
+ case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (!context->getExtensions().textureFilterAnisotropic)
+ {
+ context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
+ return false;
+ }
+
+ // we assume the parameter passed to this validation method is truncated, not rounded
+ if (params[0] < 1)
+ {
+ context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_MIN_LOD:
+ case GL_TEXTURE_MAX_LOD:
+ // any value is permissible
+ break;
+
+ case GL_TEXTURE_COMPARE_MODE:
+ if (!ValidateTextureCompareModeValue(context, params))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_COMPARE_FUNC:
+ if (!ValidateTextureCompareFuncValue(context, params))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_SWIZZLE_R:
+ case GL_TEXTURE_SWIZZLE_G:
+ case GL_TEXTURE_SWIZZLE_B:
+ case GL_TEXTURE_SWIZZLE_A:
+ switch (ConvertToGLenum(params[0]))
+ {
+ case GL_RED:
+ case GL_GREEN:
+ case GL_BLUE:
+ case GL_ALPHA:
+ case GL_ZERO:
+ case GL_ONE:
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_BASE_LEVEL:
+ if (ConvertToGLint(params[0]) < 0)
+ {
+ context->handleError(InvalidValue() << "Base level must be at least 0.");
+ return false;
+ }
+ if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
+ {
+ context->handleError(InvalidOperation()
+ << "Base level must be 0 for external textures.");
+ return false;
+ }
+ if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
+ {
+ context->handleError(InvalidOperation()
+ << "Base level must be 0 for multisampled textures.");
+ return false;
+ }
+ if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
+ {
+ context->handleError(InvalidOperation()
+ << "Base level must be 0 for rectangle textures.");
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_MAX_LEVEL:
+ if (ConvertToGLint(params[0]) < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
+ return false;
+ }
+ break;
+
+ case GL_DEPTH_STENCIL_TEXTURE_MODE:
+ if (context->getClientVersion() < Version(3, 1))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
+ return false;
+ }
+ switch (ConvertToGLenum(params[0]))
+ {
+ case GL_DEPTH_COMPONENT:
+ case GL_STENCIL_INDEX:
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ if (!ValidateTextureSRGBDecodeValue(context, params))
+ {
+ return false;
+ }
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+
+ return true;
+}
+
+template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
+template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
+
+bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
+{
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetActiveUniformBlockivBase(Context *context,
+ GLuint program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLsizei *length)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
+ {
+ context->handleError(InvalidValue()
+ << "uniformBlockIndex exceeds active uniform block count.");
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_UNIFORM_BLOCK_BINDING:
+ case GL_UNIFORM_BLOCK_DATA_SIZE:
+ case GL_UNIFORM_BLOCK_NAME_LENGTH:
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+
+ if (length)
+ {
+ if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
+ {
+ const InterfaceBlock &uniformBlock =
+ programObject->getUniformBlockByIndex(uniformBlockIndex);
+ *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
+ }
+ else
+ {
+ *length = 1;
+ }
+ }
+
+ return true;
+}
+
+template <typename ParamType>
+bool ValidateSamplerParameterBase(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ ParamType *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if (!context->isSampler(sampler))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
+ return false;
+ }
+
+ const GLsizei minBufSize = 1;
+ if (bufSize >= 0 && bufSize < minBufSize)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ case GL_TEXTURE_WRAP_R:
+ if (!ValidateTextureWrapModeValue(context, params, false))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_MIN_FILTER:
+ if (!ValidateTextureMinFilterValue(context, params, false))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_MAG_FILTER:
+ if (!ValidateTextureMagFilterValue(context, params))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_MIN_LOD:
+ case GL_TEXTURE_MAX_LOD:
+ // any value is permissible
+ break;
+
+ case GL_TEXTURE_COMPARE_MODE:
+ if (!ValidateTextureCompareModeValue(context, params))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_COMPARE_FUNC:
+ if (!ValidateTextureCompareFuncValue(context, params))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ if (!ValidateTextureSRGBDecodeValue(context, params))
+ {
+ return false;
+ }
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+
+ return true;
+}
+
+template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
+template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
+
+bool ValidateGetSamplerParameterBase(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ GLsizei *length)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if (!context->isSampler(sampler))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ case GL_TEXTURE_WRAP_R:
+ case GL_TEXTURE_MIN_FILTER:
+ case GL_TEXTURE_MAG_FILTER:
+ case GL_TEXTURE_MIN_LOD:
+ case GL_TEXTURE_MAX_LOD:
+ case GL_TEXTURE_COMPARE_MODE:
+ case GL_TEXTURE_COMPARE_FUNC:
+ break;
+
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ if (!context->getExtensions().textureSRGBDecode)
+ {
+ context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
+ return false;
+ }
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+
+ if (length)
+ {
+ *length = 1;
+ }
+ return true;
+}
+
+bool ValidateGetInternalFormativBase(Context *context,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *numParams)
+{
+ if (numParams)
+ {
+ *numParams = 0;
+ }
+
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
+ if (!formatCaps.renderable)
+ {
+ context->handleError(InvalidEnum() << "Internal format is not renderable.");
+ return false;
+ }
+
+ switch (target)
+ {
+ case GL_RENDERBUFFER:
+ break;
+
+ case GL_TEXTURE_2D_MULTISAMPLE:
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->handleError(InvalidOperation()
+ << "Texture target requires at least OpenGL ES 3.1.");
+ return false;
+ }
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
+ return false;
+ }
+
+ if (bufSize < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
+ return false;
+ }
+
+ GLsizei maxWriteParams = 0;
+ switch (pname)
+ {
+ case GL_NUM_SAMPLE_COUNTS:
+ maxWriteParams = 1;
+ break;
+
+ case GL_SAMPLES:
+ maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+
+ if (numParams)
+ {
+ // glGetInternalFormativ will not overflow bufSize
+ *numParams = std::min(bufSize, maxWriteParams);
+ }
+
+ return true;
}
} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/validationES.h b/src/3rdparty/angle/src/libANGLE/validationES.h
index 5d8486a6ab..e29432b8c3 100644
--- a/src/3rdparty/angle/src/libANGLE/validationES.h
+++ b/src/3rdparty/angle/src/libANGLE/validationES.h
@@ -10,9 +10,11 @@
#define LIBANGLE_VALIDATION_ES_H_
#include "common/mathutil.h"
+#include "libANGLE/PackedGLEnums.h"
#include <GLES2/gl2.h>
#include <GLES3/gl3.h>
+#include <GLES3/gl31.h>
namespace egl
{
@@ -23,21 +25,24 @@ class Image;
namespace gl
{
class Context;
+struct Format;
+struct LinkedUniform;
class Program;
class Shader;
class ValidationContext;
-bool ValidCap(const Context *context, GLenum cap);
bool ValidTextureTarget(const ValidationContext *context, GLenum target);
bool ValidTexture2DTarget(const ValidationContext *context, GLenum target);
bool ValidTexture3DTarget(const ValidationContext *context, GLenum target);
+bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target);
bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target);
bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target);
-bool ValidFramebufferTarget(GLenum target);
-bool ValidBufferTarget(const Context *context, GLenum target);
-bool ValidBufferParameter(const Context *context, GLenum pname);
+bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target);
+bool ValidFramebufferTarget(const ValidationContext *context, GLenum target);
+bool ValidBufferType(const ValidationContext *context, BufferBinding target);
+bool ValidBufferParameter(const ValidationContext *context, GLenum pname, GLsizei *numParams);
bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level);
-bool ValidImageSizeParameters(const Context *context,
+bool ValidImageSizeParameters(ValidationContext *context,
GLenum target,
GLint level,
GLsizei width,
@@ -46,30 +51,60 @@ bool ValidImageSizeParameters(const Context *context,
bool isSubImage);
bool ValidCompressedImageSize(const ValidationContext *context,
GLenum internalFormat,
+ GLint level,
GLsizei width,
GLsizei height);
+bool ValidCompressedSubImageSize(const ValidationContext *context,
+ GLenum internalFormat,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ size_t textureWidth,
+ size_t textureHeight);
+bool ValidImageDataSize(ValidationContext *context,
+ GLenum textureTarget,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels,
+ GLsizei imageSize);
+
bool ValidQueryType(const Context *context, GLenum queryType);
+bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
+ GLenum type,
+ GLboolean normalized,
+ GLsizei stride,
+ const void *ptr,
+ bool pureInteger);
+
// Returns valid program if id is a valid program name
// Errors INVALID_OPERATION if valid shader is given and returns NULL
// Errors INVALID_VALUE otherwise and returns NULL
-Program *GetValidProgram(Context *context, GLuint id);
+Program *GetValidProgram(ValidationContext *context, GLuint id);
// Returns valid shader if id is a valid shader name
// Errors INVALID_OPERATION if valid program is given and returns NULL
// Errors INVALID_VALUE otherwise and returns NULL
-Shader *GetValidShader(Context *context, GLuint id);
+Shader *GetValidShader(ValidationContext *context, GLuint id);
bool ValidateAttachmentTarget(Context *context, GLenum attachment);
-bool ValidateRenderbufferStorageParametersBase(Context *context, GLenum target, GLsizei samples,
- GLenum internalformat, GLsizei width, GLsizei height);
-bool ValidateRenderbufferStorageParametersANGLE(Context *context, GLenum target, GLsizei samples,
- GLenum internalformat, GLsizei width, GLsizei height);
-
-bool ValidateFramebufferRenderbufferParameters(Context *context, GLenum target, GLenum attachment,
- GLenum renderbuffertarget, GLuint renderbuffer);
-
-bool ValidateBlitFramebufferParameters(Context *context,
+bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
+ GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+bool ValidateFramebufferRenderbufferParameters(Context *context,
+ GLenum target,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer);
+
+bool ValidateBlitFramebufferParameters(ValidationContext *context,
GLint srcX0,
GLint srcY0,
GLint srcX1,
@@ -81,20 +116,30 @@ bool ValidateBlitFramebufferParameters(Context *context,
GLbitfield mask,
GLenum filter);
-bool ValidateGetVertexAttribParameters(Context *context, GLenum pname);
-
-bool ValidateTexParamParameters(Context *context, GLenum pname, GLint param);
-
-bool ValidateSamplerObjectParameter(Context *context, GLenum pname);
-
-bool ValidateReadPixels(Context *context,
- GLint x,
- GLint y,
- GLsizei width,
- GLsizei height,
- GLenum format,
- GLenum type,
- GLvoid *pixels);
+bool ValidateReadPixelsBase(Context *context,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *pixels);
+bool ValidateReadPixelsRobustANGLE(Context *context,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *pixels);
bool ValidateReadnPixelsEXT(Context *context,
GLint x,
GLint y,
@@ -103,30 +148,97 @@ bool ValidateReadnPixelsEXT(Context *context,
GLenum format,
GLenum type,
GLsizei bufSize,
- GLvoid *pixels);
-
-bool ValidateGenQueriesBase(gl::Context *context, GLsizei n, const GLuint *ids);
-bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids);
-bool ValidateDeleteQueriesBase(gl::Context *context, GLsizei n, const GLuint *ids);
+ void *pixels);
+bool ValidateReadnPixelsRobustANGLE(Context *context,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *data);
+
+bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids);
bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids);
+bool ValidateIsQueryEXT(gl::Context *context, GLuint id);
bool ValidateBeginQueryBase(Context *context, GLenum target, GLuint id);
bool ValidateBeginQueryEXT(Context *context, GLenum target, GLuint id);
bool ValidateEndQueryBase(Context *context, GLenum target);
bool ValidateEndQueryEXT(Context *context, GLenum target);
bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target);
-bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname);
+bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams);
bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params);
-bool ValidateGetQueryObjectValueBase(Context *context, GLenum target, GLenum pname);
+bool ValidateGetQueryivRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+bool ValidateGetQueryObjectValueBase(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei *numParams);
bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params);
+bool ValidateGetQueryObjectivRobustANGLE(Context *context,
+ GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params);
+bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
+ GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params);
bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params);
+bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
+ GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *params);
bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params);
-
-bool ValidateUniform(Context *context, GLenum uniformType, GLint location, GLsizei count);
-bool ValidateUniformMatrix(Context *context, GLenum matrixType, GLint location, GLsizei count,
+bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
+ GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint64 *params);
+
+bool ValidateUniformCommonBase(ValidationContext *context,
+ gl::Program *program,
+ GLint location,
+ GLsizei count,
+ const LinkedUniform **uniformOut);
+bool ValidateUniform1ivValue(ValidationContext *context,
+ GLenum uniformType,
+ GLsizei count,
+ const GLint *value);
+bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType);
+bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType);
+bool ValidateUniform(ValidationContext *context, GLenum uniformType, GLint location, GLsizei count);
+bool ValidateUniformMatrix(ValidationContext *context,
+ GLenum matrixType,
+ GLint location,
+ GLsizei count,
GLboolean transpose);
-bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams);
+bool ValidateStateQuery(ValidationContext *context,
+ GLenum pname,
+ GLenum *nativeType,
+ unsigned int *numParams);
+
+bool ValidateRobustStateQuery(ValidationContext *context,
+ GLenum pname,
+ GLsizei bufSize,
+ GLenum *nativeType,
+ unsigned int *numParams);
bool ValidateCopyTexImageParametersBase(ValidationContext *context,
GLenum target,
@@ -141,69 +253,99 @@ bool ValidateCopyTexImageParametersBase(ValidationContext *context,
GLsizei width,
GLsizei height,
GLint border,
- GLenum *textureInternalFormatOut);
-
-bool ValidateDrawArrays(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount);
-bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount);
-bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount);
-
-bool ValidateDrawElements(ValidationContext *context,
- GLenum mode,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- GLsizei primcount,
- IndexRange *indexRangeOut);
-
-bool ValidateDrawElementsInstanced(Context *context,
- GLenum mode,
- GLsizei count,
- GLenum type,
- const GLvoid *indices,
- GLsizei primcount,
- IndexRange *indexRangeOut);
+ Format *textureFormatOut);
+
+bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count);
+bool ValidateDrawArraysCommon(ValidationContext *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount);
+bool ValidateDrawArraysInstancedBase(Context *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount);
+bool ValidateDrawArraysInstancedANGLE(Context *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount);
+
+bool ValidateDrawElementsBase(ValidationContext *context, GLenum type);
+bool ValidateDrawElementsCommon(ValidationContext *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei primcount);
+
+bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei primcount);
bool ValidateDrawElementsInstancedANGLE(Context *context,
GLenum mode,
GLsizei count,
GLenum type,
- const GLvoid *indices,
- GLsizei primcount,
- IndexRange *indexRangeOut);
-
-bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
- GLuint texture, GLint level);
-bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment,
- GLenum textarget, GLuint texture, GLint level);
-bool ValidateFramebufferRenderbuffer(Context *context,
- GLenum target,
- GLenum attachment,
- GLenum renderbuffertarget,
- GLuint renderbuffer);
+ const void *indices,
+ GLsizei primcount);
-bool ValidateGetUniformBase(Context *context, GLuint program, GLint location);
-bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params);
-bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params);
-bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params);
-bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params);
+bool ValidateFramebufferTextureBase(Context *context,
+ GLenum target,
+ GLenum attachment,
+ GLuint texture,
+ GLint level);
-bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments,
- const GLenum *attachments, bool defaultFramebuffer);
+bool ValidateGetUniformBase(Context *context, GLuint program, GLint location);
+bool ValidateGetnUniformfvEXT(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLfloat *params);
+bool ValidateGetnUniformivEXT(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLint *params);
+bool ValidateGetUniformfvRobustANGLE(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params);
+bool ValidateGetUniformivRobustANGLE(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+bool ValidateGetUniformuivRobustANGLE(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params);
+
+bool ValidateDiscardFramebufferBase(Context *context,
+ GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ bool defaultFramebuffer);
bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker);
bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker);
bool ValidateEGLImageTargetTexture2DOES(Context *context,
- egl::Display *display,
GLenum target,
egl::Image *image);
bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
- egl::Display *display,
GLenum target,
egl::Image *image);
bool ValidateBindVertexArrayBase(Context *context, GLuint array);
-bool ValidateDeleteVertexArraysBase(Context *context, GLsizei n);
-bool ValidateGenVertexArraysBase(Context *context, GLsizei n);
bool ValidateProgramBinaryBase(Context *context,
GLuint program,
@@ -217,28 +359,243 @@ bool ValidateGetProgramBinaryBase(Context *context,
GLenum *binaryFormat,
void *binary);
-bool ValidateCopyTexImage2D(ValidationContext *context,
- GLenum target,
- GLint level,
- GLenum internalformat,
- GLint x,
- GLint y,
- GLsizei width,
- GLsizei height,
- GLint border);
bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs);
-bool ValidateCopyTexSubImage2D(Context *context,
- GLenum target,
- GLint level,
- GLint xoffset,
- GLint yoffset,
- GLint x,
- GLint y,
- GLsizei width,
- GLsizei height);
-
-// Error messages shared here for use in testing.
-extern const char *g_ExceedsMaxElementErrorMessage;
+
+bool ValidateGetBufferPointervBase(Context *context,
+ BufferBinding target,
+ GLenum pname,
+ GLsizei *length,
+ void **params);
+bool ValidateUnmapBufferBase(Context *context, BufferBinding target);
+bool ValidateMapBufferRangeBase(Context *context,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access);
+bool ValidateFlushMappedBufferRangeBase(Context *context,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length);
+
+bool ValidateGenOrDelete(Context *context, GLint n);
+
+bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize);
+bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams);
+
+bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLsizei *numParams);
+bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *numParams);
+
+bool ValidateGetBufferParameterBase(ValidationContext *context,
+ BufferBinding target,
+ GLenum pname,
+ bool pointerVersion,
+ GLsizei *numParams);
+bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
+ BufferBinding target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+
+bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
+ BufferBinding target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *params);
+
+bool ValidateGetProgramivBase(ValidationContext *context,
+ GLuint program,
+ GLenum pname,
+ GLsizei *numParams);
+bool ValidateGetProgramivRobustANGLE(Context *context,
+ GLuint program,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *numParams);
+
+bool ValidateGetRenderbufferParameterivBase(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei *length);
+bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+
+bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length);
+bool ValidateGetShaderivRobustANGLE(Context *context,
+ GLuint shader,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+
+bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length);
+bool ValidateGetTexParameterfvRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params);
+bool ValidateGetTexParameterivRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+
+template <typename ParamType>
+bool ValidateTexParameterBase(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ const ParamType *params);
+bool ValidateTexParameterfvRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLfloat *params);
+bool ValidateTexParameterivRobustANGLE(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *params);
+
+bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ GLuint bufSize,
+ GLsizei *length,
+ GLfloat *params);
+bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ GLuint bufSize,
+ GLsizei *length,
+ GLint *params);
+
+bool ValidateSamplerParameterfvRobustANGLE(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLfloat *params);
+bool ValidateSamplerParameterivRobustANGLE(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *params);
+
+bool ValidateGetVertexAttribBase(Context *context,
+ GLuint index,
+ GLenum pname,
+ GLsizei *length,
+ bool pointer,
+ bool pureIntegerEntryPoint);
+bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params);
+
+bool ValidateGetVertexAttribivRobustANGLE(Context *context,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+
+bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ void **pointer);
+
+bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+
+bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params);
+
+bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
+ GLuint program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+
+bool ValidateGetInternalFormativRobustANGLE(Context *context,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+
+bool ValidateVertexFormatBase(ValidationContext *context,
+ GLuint attribIndex,
+ GLint size,
+ GLenum type,
+ GLboolean pureInteger);
+
+bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
+ GLint drawbuffer,
+ const GLenum *validComponentTypes,
+ size_t validComponentTypeCount);
+
+bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
+ GLsizei imageSize,
+ GLsizei dataSize);
+
+bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index);
+
+bool ValidateGetActiveUniformBlockivBase(Context *context,
+ GLuint program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLsizei *length);
+
+bool ValidateGetSamplerParameterBase(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ GLsizei *length);
+
+template <typename ParamType>
+bool ValidateSamplerParameterBase(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ ParamType *params);
+
+bool ValidateGetInternalFormativBase(Context *context,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *numParams);
+
} // namespace gl
-#endif // LIBANGLE_VALIDATION_ES_H_
+#endif // LIBANGLE_VALIDATION_ES_H_
diff --git a/src/3rdparty/angle/src/libANGLE/validationES2.cpp b/src/3rdparty/angle/src/libANGLE/validationES2.cpp
index 2e5b955e99..5e505aa607 100644
--- a/src/3rdparty/angle/src/libANGLE/validationES2.cpp
+++ b/src/3rdparty/angle/src/libANGLE/validationES2.cpp
@@ -7,16 +7,24 @@
// validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters
#include "libANGLE/validationES2.h"
-#include "libANGLE/validationES.h"
+
+#include <cstdint>
+
+#include "common/mathutil.h"
+#include "common/string_utils.h"
+#include "common/utilities.h"
#include "libANGLE/Context.h"
-#include "libANGLE/Texture.h"
+#include "libANGLE/ErrorStrings.h"
#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/VertexArray.h"
#include "libANGLE/formatutils.h"
-#include "libANGLE/FramebufferAttachment.h"
-
-#include "common/mathutil.h"
-#include "common/utilities.h"
+#include "libANGLE/validationES.h"
+#include "libANGLE/validationES3.h"
namespace gl
{
@@ -45,9 +53,9 @@ bool IsPartialBlit(gl::Context *context,
return true;
}
- if (context->getState().isScissorTestEnabled())
+ if (context->getGLState().isScissorTestEnabled())
{
- const Rectangle &scissor = context->getState().getScissor();
+ const Rectangle &scissor = context->getGLState().getScissor();
return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
scissor.height < writeSize.height;
}
@@ -55,35 +63,999 @@ bool IsPartialBlit(gl::Context *context,
return false;
}
+template <typename T>
+bool ValidatePathInstances(gl::Context *context,
+ GLsizei numPaths,
+ const void *paths,
+ GLuint pathBase)
+{
+ const auto *array = static_cast<const T *>(paths);
+
+ for (GLsizei i = 0; i < numPaths; ++i)
+ {
+ const GLuint pathName = array[i] + pathBase;
+ if (context->hasPath(pathName) && !context->hasPathData(pathName))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ValidateInstancedPathParameters(gl::Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
+ return false;
+ }
+
+ if (paths == nullptr)
+ {
+ context->handleError(InvalidValue() << "No path name array.");
+ return false;
+ }
+
+ if (numPaths < 0)
+ {
+ context->handleError(InvalidValue() << "Invalid (negative) numPaths.");
+ return false;
+ }
+
+ if (!angle::IsValueInRangeForNumericType<std::uint32_t>(numPaths))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
+ return false;
+ }
+
+ std::uint32_t pathNameTypeSize = 0;
+ std::uint32_t componentCount = 0;
+
+ switch (pathNameType)
+ {
+ case GL_UNSIGNED_BYTE:
+ pathNameTypeSize = sizeof(GLubyte);
+ if (!ValidatePathInstances<GLubyte>(context, numPaths, paths, pathBase))
+ return false;
+ break;
+
+ case GL_BYTE:
+ pathNameTypeSize = sizeof(GLbyte);
+ if (!ValidatePathInstances<GLbyte>(context, numPaths, paths, pathBase))
+ return false;
+ break;
+
+ case GL_UNSIGNED_SHORT:
+ pathNameTypeSize = sizeof(GLushort);
+ if (!ValidatePathInstances<GLushort>(context, numPaths, paths, pathBase))
+ return false;
+ break;
+
+ case GL_SHORT:
+ pathNameTypeSize = sizeof(GLshort);
+ if (!ValidatePathInstances<GLshort>(context, numPaths, paths, pathBase))
+ return false;
+ break;
+
+ case GL_UNSIGNED_INT:
+ pathNameTypeSize = sizeof(GLuint);
+ if (!ValidatePathInstances<GLuint>(context, numPaths, paths, pathBase))
+ return false;
+ break;
+
+ case GL_INT:
+ pathNameTypeSize = sizeof(GLint);
+ if (!ValidatePathInstances<GLint>(context, numPaths, paths, pathBase))
+ return false;
+ break;
+
+ default:
+ context->handleError(InvalidEnum() << "Invalid path name type.");
+ return false;
+ }
+
+ switch (transformType)
+ {
+ case GL_NONE:
+ componentCount = 0;
+ break;
+ case GL_TRANSLATE_X_CHROMIUM:
+ case GL_TRANSLATE_Y_CHROMIUM:
+ componentCount = 1;
+ break;
+ case GL_TRANSLATE_2D_CHROMIUM:
+ componentCount = 2;
+ break;
+ case GL_TRANSLATE_3D_CHROMIUM:
+ componentCount = 3;
+ break;
+ case GL_AFFINE_2D_CHROMIUM:
+ case GL_TRANSPOSE_AFFINE_2D_CHROMIUM:
+ componentCount = 6;
+ break;
+ case GL_AFFINE_3D_CHROMIUM:
+ case GL_TRANSPOSE_AFFINE_3D_CHROMIUM:
+ componentCount = 12;
+ break;
+ default:
+ context->handleError(InvalidEnum() << "Invalid transformation.");
+ return false;
+ }
+ if (componentCount != 0 && transformValues == nullptr)
+ {
+ context->handleError(InvalidValue() << "No transform array given.");
+ return false;
+ }
+
+ angle::CheckedNumeric<std::uint32_t> checkedSize(0);
+ checkedSize += (numPaths * pathNameTypeSize);
+ checkedSize += (numPaths * sizeof(GLfloat) * componentCount);
+ if (!checkedSize.IsValid())
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
+ return false;
+ }
+
+ return true;
+}
+
+bool IsValidCopyTextureSourceInternalFormatEnum(GLenum internalFormat)
+{
+ // Table 1.1 from the CHROMIUM_copy_texture spec
+ switch (GetUnsizedFormat(internalFormat))
+ {
+ case GL_RED:
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGB:
+ case GL_RGBA:
+ case GL_RGB8:
+ case GL_RGBA8:
+ case GL_BGRA_EXT:
+ case GL_BGRA8_EXT:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool IsValidCopySubTextureSourceInternalFormat(GLenum internalFormat)
+{
+ return IsValidCopyTextureSourceInternalFormatEnum(internalFormat);
+}
+
+bool IsValidCopyTextureDestinationInternalFormatEnum(GLint internalFormat)
+{
+ // Table 1.0 from the CHROMIUM_copy_texture spec
+ switch (internalFormat)
+ {
+ case GL_RGB:
+ case GL_RGBA:
+ case GL_RGB8:
+ case GL_RGBA8:
+ case GL_BGRA_EXT:
+ case GL_BGRA8_EXT:
+ case GL_SRGB_EXT:
+ case GL_SRGB_ALPHA_EXT:
+ case GL_R8:
+ case GL_R8UI:
+ case GL_RG8:
+ case GL_RG8UI:
+ case GL_SRGB8:
+ case GL_RGB565:
+ case GL_RGB8UI:
+ case GL_RGB10_A2:
+ case GL_SRGB8_ALPHA8:
+ case GL_RGB5_A1:
+ case GL_RGBA4:
+ case GL_RGBA8UI:
+ case GL_RGB9_E5:
+ case GL_R16F:
+ case GL_R32F:
+ case GL_RG16F:
+ case GL_RG32F:
+ case GL_RGB16F:
+ case GL_RGB32F:
+ case GL_RGBA16F:
+ case GL_RGBA32F:
+ case GL_R11F_G11F_B10F:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_ALPHA:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool IsValidCopySubTextureDestionationInternalFormat(GLenum internalFormat)
+{
+ return IsValidCopyTextureDestinationInternalFormatEnum(internalFormat);
+}
+
+bool IsValidCopyTextureDestinationFormatType(Context *context, GLint internalFormat, GLenum type)
+{
+ if (!IsValidCopyTextureDestinationInternalFormatEnum(internalFormat))
+ {
+ return false;
+ }
+
+ if (!ValidES3FormatCombination(GetUnsizedFormat(internalFormat), type, internalFormat))
+ {
+ context->handleError(InvalidOperation()
+ << "Invalid combination of type and internalFormat.");
+ return false;
+ }
+
+ const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
+ if (!internalFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool IsValidCopyTextureDestinationTargetEnum(Context *context, GLenum target)
+{
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ return true;
+
+ case GL_TEXTURE_RECTANGLE_ANGLE:
+ return context->getExtensions().textureRectangle;
+
+ default:
+ return false;
+ }
+}
+
+bool IsValidCopyTextureDestinationTarget(Context *context, GLenum textureType, GLenum target)
+{
+ if (IsCubeMapTextureTarget(target))
+ {
+ return textureType == GL_TEXTURE_CUBE_MAP;
+ }
+ else
+ {
+ return textureType == target;
+ }
+}
+
+bool IsValidCopyTextureSourceTarget(Context *context, GLenum target)
+{
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ return true;
+ case GL_TEXTURE_RECTANGLE_ANGLE:
+ return context->getExtensions().textureRectangle;
+
+ // TODO(geofflang): accept GL_TEXTURE_EXTERNAL_OES if the texture_external extension is
+ // supported
+
+ default:
+ return false;
+ }
+}
+
+bool IsValidCopyTextureSourceLevel(Context *context, GLenum target, GLint level)
+{
+ if (!ValidMipLevel(context, target, level))
+ {
+ return false;
+ }
+
+ if (level > 0 && context->getClientVersion() < ES_3_0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool IsValidCopyTextureDestinationLevel(Context *context,
+ GLenum target,
+ GLint level,
+ GLsizei width,
+ GLsizei height)
+{
+ if (!ValidMipLevel(context, target, level))
+ {
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ if (target == GL_TEXTURE_2D)
+ {
+ if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
+ static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
+ {
+ return false;
+ }
+ }
+ else if (target == GL_TEXTURE_RECTANGLE_ANGLE)
+ {
+ ASSERT(level == 0);
+ if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
+ static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
+ {
+ return false;
+ }
+ }
+ else if (IsCubeMapTextureTarget(target))
+ {
+ if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
+ static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool IsValidStencilFunc(GLenum func)
+{
+ switch (func)
+ {
+ case GL_NEVER:
+ case GL_ALWAYS:
+ case GL_LESS:
+ case GL_LEQUAL:
+ case GL_EQUAL:
+ case GL_GEQUAL:
+ case GL_GREATER:
+ case GL_NOTEQUAL:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool IsValidStencilFace(GLenum face)
+{
+ switch (face)
+ {
+ case GL_FRONT:
+ case GL_BACK:
+ case GL_FRONT_AND_BACK:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool IsValidStencilOp(GLenum op)
+{
+ switch (op)
+ {
+ case GL_ZERO:
+ case GL_KEEP:
+ case GL_REPLACE:
+ case GL_INCR:
+ case GL_DECR:
+ case GL_INVERT:
+ case GL_INCR_WRAP:
+ case GL_DECR_WRAP:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool ValidateES2CopyTexImageParameters(ValidationContext *context,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ bool isSubImage,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border)
+{
+ if (!ValidTexture2DDestinationTarget(context, target))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
+ return false;
+ }
+
+ if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
+ {
+ context->handleError(InvalidValue() << "Invalid texture dimensions.");
+ return false;
+ }
+
+ Format textureFormat = Format::Invalid();
+ if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
+ xoffset, yoffset, 0, x, y, width, height, border,
+ &textureFormat))
+ {
+ return false;
+ }
+
+ const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
+ GLenum colorbufferFormat =
+ framebuffer->getReadColorbuffer()->getFormat().info->sizedInternalFormat;
+ const auto &formatInfo = *textureFormat.info;
+
+ // [OpenGL ES 2.0.24] table 3.9
+ if (isSubImage)
+ {
+ switch (formatInfo.format)
+ {
+ case GL_ALPHA:
+ if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
+ colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
+ colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
+ return false;
+ }
+ break;
+ case GL_LUMINANCE:
+ if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
+ colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
+ colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
+ colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGRA8_EXT &&
+ colorbufferFormat != GL_BGR5_A1_ANGLEX)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
+ return false;
+ }
+ break;
+ case GL_RED_EXT:
+ if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
+ colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
+ colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
+ colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
+ colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
+ colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
+ colorbufferFormat != GL_BGR5_A1_ANGLEX)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
+ return false;
+ }
+ break;
+ case GL_RG_EXT:
+ if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
+ colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
+ colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
+ colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
+ colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
+ colorbufferFormat != GL_BGR5_A1_ANGLEX)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
+ return false;
+ }
+ break;
+ case GL_RGB:
+ if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
+ colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
+ colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
+ colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
+ colorbufferFormat != GL_BGR5_A1_ANGLEX)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
+ return false;
+ }
+ break;
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGBA:
+ if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
+ colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F &&
+ colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ case GL_ETC1_RGB8_OES:
+ case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+ case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
+ case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+ case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
+ return false;
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_STENCIL_OES:
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
+ return false;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
+ return false;
+ }
+
+ if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
+ return false;
+ }
+ }
+ else
+ {
+ switch (internalformat)
+ {
+ case GL_ALPHA:
+ if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
+ colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
+ colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
+ return false;
+ }
+ break;
+ case GL_LUMINANCE:
+ if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
+ colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
+ colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
+ colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
+ colorbufferFormat != GL_BGR5_A1_ANGLEX)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
+ return false;
+ }
+ break;
+ case GL_RED_EXT:
+ if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
+ colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
+ colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
+ colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
+ colorbufferFormat != GL_BGR5_A1_ANGLEX)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
+ return false;
+ }
+ break;
+ case GL_RG_EXT:
+ if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
+ colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
+ colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
+ colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
+ return false;
+ }
+ break;
+ case GL_RGB:
+ if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
+ colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
+ colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
+ colorbufferFormat != GL_BGR5_A1_ANGLEX)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
+ return false;
+ }
+ break;
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGBA:
+ if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
+ colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
+ colorbufferFormat != GL_BGR5_A1_ANGLEX)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ if (context->getExtensions().textureCompressionDXT1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
+ return false;
+ }
+ else
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ if (context->getExtensions().textureCompressionDXT3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
+ return false;
+ }
+ else
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ if (context->getExtensions().textureCompressionDXT5)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
+ return false;
+ }
+ else
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+ break;
+ case GL_ETC1_RGB8_OES:
+ if (context->getExtensions().compressedETC1RGB8Texture)
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+ else
+ {
+ context->handleError(InvalidEnum());
+ return false;
+ }
+ break;
+ case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+ case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
+ case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+ case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+ if (context->getExtensions().lossyETCDecode)
+ {
+ context->handleError(InvalidOperation()
+ << "ETC lossy decode formats can't be copied to.");
+ return false;
+ }
+ else
+ {
+ context->handleError(InvalidEnum()
+ << "ANGLE_lossy_etc_decode extension is not supported.");
+ return false;
+ }
+ break;
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH_COMPONENT32_OES:
+ case GL_DEPTH_STENCIL_OES:
+ case GL_DEPTH24_STENCIL8_OES:
+ if (context->getExtensions().depthTextures)
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+ else
+ {
+ context->handleError(InvalidEnum());
+ return false;
+ }
+ default:
+ context->handleError(InvalidEnum());
+ return false;
+ }
+ }
+
+ // If width or height is zero, it is a no-op. Return false without setting an error.
+ return (width > 0 && height > 0);
+}
+
+bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
+{
+ switch (cap)
+ {
+ // EXT_multisample_compatibility
+ case GL_MULTISAMPLE_EXT:
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+ return context->getExtensions().multisampleCompatibility;
+
+ case GL_CULL_FACE:
+ case GL_POLYGON_OFFSET_FILL:
+ case GL_SAMPLE_ALPHA_TO_COVERAGE:
+ case GL_SAMPLE_COVERAGE:
+ case GL_SCISSOR_TEST:
+ case GL_STENCIL_TEST:
+ case GL_DEPTH_TEST:
+ case GL_BLEND:
+ case GL_DITHER:
+ return true;
+
+ case GL_PRIMITIVE_RESTART_FIXED_INDEX:
+ case GL_RASTERIZER_DISCARD:
+ return (context->getClientMajorVersion() >= 3);
+
+ case GL_DEBUG_OUTPUT_SYNCHRONOUS:
+ case GL_DEBUG_OUTPUT:
+ return context->getExtensions().debug;
+
+ case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
+ return queryOnly && context->getExtensions().bindGeneratesResource;
+
+ case GL_CLIENT_ARRAYS_ANGLE:
+ return queryOnly && context->getExtensions().clientArrays;
+
+ case GL_FRAMEBUFFER_SRGB_EXT:
+ return context->getExtensions().sRGBWriteControl;
+
+ case GL_SAMPLE_MASK:
+ return context->getClientVersion() >= Version(3, 1);
+
+ case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ return queryOnly && context->getExtensions().robustResourceInitialization;
+
+ default:
+ return false;
+ }
+}
+
+// Return true if a character belongs to the ASCII subset as defined in GLSL ES 1.0 spec section
+// 3.1.
+bool IsValidESSLCharacter(unsigned char c)
+{
+ // Printing characters are valid except " $ ` @ \ ' DEL.
+ if (c >= 32 && c <= 126 && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' &&
+ c != '\'')
+ {
+ return true;
+ }
+
+ // Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid.
+ if (c >= 9 && c <= 13)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+bool IsValidESSLString(const char *str, size_t len)
+{
+ for (size_t i = 0; i < len; i++)
+ {
+ if (!IsValidESSLCharacter(str[i]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool IsValidESSLShaderSourceString(const char *str, size_t len, bool lineContinuationAllowed)
+{
+ enum class ParseState
+ {
+ // Have not seen an ASCII non-whitespace character yet on
+ // this line. Possible that we might see a preprocessor
+ // directive.
+ BEGINING_OF_LINE,
+
+ // Have seen at least one ASCII non-whitespace character
+ // on this line.
+ MIDDLE_OF_LINE,
+
+ // Handling a preprocessor directive. Passes through all
+ // characters up to the end of the line. Disables comment
+ // processing.
+ IN_PREPROCESSOR_DIRECTIVE,
+
+ // Handling a single-line comment. The comment text is
+ // replaced with a single space.
+ IN_SINGLE_LINE_COMMENT,
+
+ // Handling a multi-line comment. Newlines are passed
+ // through to preserve line numbers.
+ IN_MULTI_LINE_COMMENT
+ };
+
+ ParseState state = ParseState::BEGINING_OF_LINE;
+ size_t pos = 0;
+
+ while (pos < len)
+ {
+ char c = str[pos];
+ char next = pos + 1 < len ? str[pos + 1] : 0;
+
+ // Check for newlines
+ if (c == '\n' || c == '\r')
+ {
+ if (state != ParseState::IN_MULTI_LINE_COMMENT)
+ {
+ state = ParseState::BEGINING_OF_LINE;
+ }
+
+ pos++;
+ continue;
+ }
+
+ switch (state)
+ {
+ case ParseState::BEGINING_OF_LINE:
+ if (c == ' ')
+ {
+ // Maintain the BEGINING_OF_LINE state until a non-space is seen
+ pos++;
+ }
+ else if (c == '#')
+ {
+ state = ParseState::IN_PREPROCESSOR_DIRECTIVE;
+ pos++;
+ }
+ else
+ {
+ // Don't advance, re-process this character with the MIDDLE_OF_LINE state
+ state = ParseState::MIDDLE_OF_LINE;
+ }
+ break;
+
+ case ParseState::MIDDLE_OF_LINE:
+ if (c == '/' && next == '/')
+ {
+ state = ParseState::IN_SINGLE_LINE_COMMENT;
+ pos++;
+ }
+ else if (c == '/' && next == '*')
+ {
+ state = ParseState::IN_MULTI_LINE_COMMENT;
+ pos++;
+ }
+ else if (lineContinuationAllowed && c == '\\' && (next == '\n' || next == '\r'))
+ {
+ // Skip line continuation characters
+ }
+ else if (!IsValidESSLCharacter(c))
+ {
+ return false;
+ }
+ pos++;
+ break;
+
+ case ParseState::IN_PREPROCESSOR_DIRECTIVE:
+ // Line-continuation characters may not be permitted.
+ // Otherwise, just pass it through. Do not parse comments in this state.
+ if (!lineContinuationAllowed && c == '\\')
+ {
+ return false;
+ }
+ pos++;
+ break;
+
+ case ParseState::IN_SINGLE_LINE_COMMENT:
+ // Line-continuation characters are processed before comment processing.
+ // Advance string if a new line character is immediately behind
+ // line-continuation character.
+ if (c == '\\' && (next == '\n' || next == '\r'))
+ {
+ pos++;
+ }
+ pos++;
+ break;
+
+ case ParseState::IN_MULTI_LINE_COMMENT:
+ if (c == '*' && next == '/')
+ {
+ state = ParseState::MIDDLE_OF_LINE;
+ pos++;
+ }
+ pos++;
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateWebGLNamePrefix(ValidationContext *context, const GLchar *name)
+{
+ ASSERT(context->isWebGL());
+
+ // WebGL 1.0 [Section 6.16] GLSL Constructs
+ // Identifiers starting with "webgl_" and "_webgl_" are reserved for use by WebGL.
+ if (strncmp(name, "webgl_", 6) == 0 || strncmp(name, "_webgl_", 7) == 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), WebglBindAttribLocationReservedPrefix);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateWebGLNameLength(ValidationContext *context, size_t length)
+{
+ ASSERT(context->isWebGL());
+
+ if (context->isWebGL1() && length > 256)
+ {
+ // WebGL 1.0 [Section 6.21] Maxmimum Uniform and Attribute Location Lengths
+ // WebGL imposes a limit of 256 characters on the lengths of uniform and attribute
+ // locations.
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), WebglNameLengthLimitExceeded);
+
+ return false;
+ }
+ else if (length > 1024)
+ {
+ // WebGL 2.0 [Section 4.3.2] WebGL 2.0 imposes a limit of 1024 characters on the lengths of
+ // uniform and attribute locations.
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), Webgl2NameLengthLimitExceeded);
+ return false;
+ }
+
+ return true;
+}
+
} // anonymous namespace
-bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
- GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- GLint border, GLenum format, GLenum type, const GLvoid *pixels)
+bool ValidateES2TexImageParameters(Context *context,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ bool isCompressed,
+ bool isSubImage,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei imageSize,
+ const void *pixels)
{
if (!ValidTexture2DDestinationTarget(context, target))
{
- context->recordError(Error(GL_INVALID_ENUM));
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
return false;
}
if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
+ return false;
+ }
+
+ if (!ValidMipLevel(context, target, level))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
return false;
}
- if (level < 0 || xoffset < 0 ||
- std::numeric_limits<GLsizei>::max() - xoffset < width ||
+ if (xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
std::numeric_limits<GLsizei>::max() - yoffset < height)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
return false;
}
- if (!isSubImage && !isCompressed && internalformat != format)
+ // From GL_CHROMIUM_color_buffer_float_rgb[a]:
+ // GL_RGB[A] / GL_RGB[A]32F becomes an allowable format / internalformat parameter pair for
+ // TexImage2D. The restriction in section 3.7.1 of the OpenGL ES 2.0 spec that the
+ // internalformat parameter and format parameter of TexImage2D must match is lifted for this
+ // case.
+ bool nonEqualFormatsAllowed =
+ (internalformat == GL_RGB32F && context->getExtensions().colorBufferFloatRGB) ||
+ (internalformat == GL_RGBA32F && context->getExtensions().colorBufferFloatRGBA);
+
+ if (!isSubImage && !isCompressed && internalformat != format && !nonEqualFormatsAllowed)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
@@ -94,7 +1066,23 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level,
if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
+ return false;
+ }
+ }
+ else if (target == GL_TEXTURE_RECTANGLE_ANGLE)
+ {
+ ASSERT(level == 0);
+ if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
+ static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+ if (isCompressed)
+ {
+ context->handleError(InvalidEnum()
+ << "Rectangle texture cannot have a compressed format.");
return false;
}
}
@@ -102,37 +1090,46 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level,
{
if (!isSubImage && width != height)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapFacesEqualDimensions);
return false;
}
if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
}
else
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return false;
}
- gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+ gl::Texture *texture =
+ context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
if (!texture)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
return false;
}
if (isSubImage)
{
+ const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
+ if (textureInternalFormat.internalFormat == GL_NONE)
+ {
+ context->handleError(InvalidOperation() << "Texture level does not exist.");
+ return false;
+ }
+
if (format != GL_NONE)
{
- if (gl::GetSizedInternalFormat(format, type) != texture->getInternalFormat(target, level))
+ if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
+ textureInternalFormat.sizedInternalFormat)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), TypeMismatch);
return false;
}
}
@@ -140,7 +1137,14 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level,
if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
+ return false;
+ }
+
+ if (width > 0 && height > 0 && pixels == nullptr &&
+ context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack) == nullptr)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), PixelDataNull);
return false;
}
}
@@ -148,7 +1152,7 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level,
{
if (texture->getImmutableFormat())
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
}
@@ -156,62 +1160,100 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level,
// Verify zero border
if (border != 0)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
return false;
}
if (isCompressed)
{
GLenum actualInternalFormat =
- isSubImage ? texture->getInternalFormat(target, level) : internalformat;
+ isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
+ : internalformat;
switch (actualInternalFormat)
{
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- if (!context->getExtensions().textureCompressionDXT1)
- {
- context->recordError(Error(GL_INVALID_ENUM));
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ if (!context->getExtensions().textureCompressionDXT1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ if (!context->getExtensions().textureCompressionDXT3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ if (!context->getExtensions().textureCompressionDXT5)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ if (!context->getExtensions().textureCompressionS3TCsRGB)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
+ return false;
+ }
+ break;
+ case GL_ETC1_RGB8_OES:
+ if (!context->getExtensions().compressedETC1RGB8Texture)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
+ return false;
+ }
+ if (isSubImage)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
+ return false;
+ }
+ break;
+ case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+ case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
+ case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+ case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+ if (!context->getExtensions().lossyETCDecode)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
+ return false;
+ }
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
return false;
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
- if (!context->getExtensions().textureCompressionDXT1)
+ }
+
+ if (isSubImage)
+ {
+ if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
+ height, texture->getWidth(target, level),
+ texture->getHeight(target, level)))
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
return false;
}
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
- if (!context->getExtensions().textureCompressionDXT5)
+
+ if (format != actualInternalFormat)
{
- context->recordError(Error(GL_INVALID_ENUM));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
return false;
}
- break;
- case GL_ETC1_RGB8_OES:
- if (!context->getExtensions().compressedETC1RGB8Texture)
+ }
+ else
+ {
+ if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
return false;
}
- break;
- case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
- if (!context->getExtensions().lossyETCDecode)
- {
- context->recordError(
- Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported"));
- return false;
- }
- break;
- default:
- context->recordError(Error(
- GL_INVALID_ENUM, "internalformat is not a supported compressed internal format"));
- return false;
- }
- if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
}
}
else
@@ -219,19 +1261,19 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level,
// validate <type> by itself (used as secondary key below)
switch (type)
{
- case GL_UNSIGNED_BYTE:
- case GL_UNSIGNED_SHORT_5_6_5:
- case GL_UNSIGNED_SHORT_4_4_4_4:
- case GL_UNSIGNED_SHORT_5_5_5_1:
- case GL_UNSIGNED_SHORT:
- case GL_UNSIGNED_INT:
- case GL_UNSIGNED_INT_24_8_OES:
- case GL_HALF_FLOAT_OES:
- case GL_FLOAT:
- break;
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
+ case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL_UNSIGNED_SHORT:
+ case GL_UNSIGNED_INT:
+ case GL_UNSIGNED_INT_24_8_OES:
+ case GL_HALF_FLOAT_OES:
+ case GL_FLOAT:
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
+ return false;
}
// validate <format> + <type> combinations
@@ -239,217 +1281,286 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level,
// - invalid <format>+<type> combination -> sets INVALID_OPERATION
switch (format)
{
- case GL_ALPHA:
- case GL_LUMINANCE:
- case GL_LUMINANCE_ALPHA:
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- case GL_FLOAT:
- case GL_HALF_FLOAT_OES:
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_FLOAT:
+ case GL_HALF_FLOAT_OES:
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
+ return false;
+ }
break;
- default:
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_RED:
- case GL_RG:
- if (!context->getExtensions().textureRG)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- case GL_FLOAT:
- case GL_HALF_FLOAT_OES:
- break;
- default:
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_RGB:
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- case GL_UNSIGNED_SHORT_5_6_5:
- case GL_FLOAT:
- case GL_HALF_FLOAT_OES:
+ case GL_RED:
+ case GL_RG:
+ if (!context->getExtensions().textureRG)
+ {
+ context->handleError(InvalidEnum());
+ return false;
+ }
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ break;
+ case GL_FLOAT:
+ case GL_HALF_FLOAT_OES:
+ if (!context->getExtensions().textureFloat)
+ {
+ context->handleError(InvalidEnum());
+ return false;
+ }
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
+ return false;
+ }
break;
- default:
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_RGBA:
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- case GL_UNSIGNED_SHORT_4_4_4_4:
- case GL_UNSIGNED_SHORT_5_5_5_1:
- case GL_FLOAT:
- case GL_HALF_FLOAT_OES:
+ case GL_RGB:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_FLOAT:
+ case GL_HALF_FLOAT_OES:
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
+ return false;
+ }
break;
- default:
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_BGRA_EXT:
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
+ case GL_RGBA:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL_FLOAT:
+ case GL_HALF_FLOAT_OES:
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
+ return false;
+ }
break;
- default:
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_SRGB_EXT:
- case GL_SRGB_ALPHA_EXT:
- if (!context->getExtensions().sRGB)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
+ case GL_BGRA_EXT:
+ if (!context->getExtensions().textureFormatBGRA8888)
+ {
+ context->handleError(InvalidEnum());
+ return false;
+ }
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
+ return false;
+ }
break;
- default:
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
- break;
- case GL_DEPTH_COMPONENT:
- switch (type)
- {
- case GL_UNSIGNED_SHORT:
- case GL_UNSIGNED_INT:
+ case GL_SRGB_EXT:
+ case GL_SRGB_ALPHA_EXT:
+ if (!context->getExtensions().sRGB)
+ {
+ context->handleError(InvalidEnum());
+ return false;
+ }
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
+ return false;
+ }
break;
- default:
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_DEPTH_STENCIL_OES:
- switch (type)
- {
- case GL_UNSIGNED_INT_24_8_OES:
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
+ // handled below
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ break;
+ case GL_DEPTH_COMPONENT:
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ case GL_UNSIGNED_INT:
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
+ return false;
+ }
+ break;
+ case GL_DEPTH_STENCIL_OES:
+ switch (type)
+ {
+ case GL_UNSIGNED_INT_24_8_OES:
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
+ return false;
+ }
break;
- default:
- context->recordError(Error(GL_INVALID_OPERATION));
+ default:
+ context->handleError(InvalidEnum());
return false;
- }
- break;
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
}
switch (format)
{
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- if (context->getExtensions().textureCompressionDXT1)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- else
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
- if (context->getExtensions().textureCompressionDXT3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- else
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
- if (context->getExtensions().textureCompressionDXT5)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- else
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- break;
- case GL_ETC1_RGB8_OES:
- if (context->getExtensions().compressedETC1RGB8Texture)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- else
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- break;
- case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
- if (context->getExtensions().lossyETCDecode)
- {
- context->recordError(
- Error(GL_INVALID_OPERATION,
- "ETC1_RGB8_LOSSY_DECODE_ANGLE can't work with this type."));
- return false;
- }
- else
- {
- context->recordError(
- Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
- return false;
- }
- break;
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_STENCIL_OES:
- if (!context->getExtensions().depthTextures)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
- if (target != GL_TEXTURE_2D)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- // OES_depth_texture supports loading depth data and multiple levels,
- // but ANGLE_depth_texture does not
- if (pixels != NULL || level != 0)
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ if (context->getExtensions().textureCompressionDXT1)
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+ else
+ {
+ context->handleError(InvalidEnum());
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ if (context->getExtensions().textureCompressionDXT3)
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+ else
+ {
+ context->handleError(InvalidEnum());
+ return false;
+ }
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ if (context->getExtensions().textureCompressionDXT5)
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+ else
+ {
+ context->handleError(InvalidEnum());
+ return false;
+ }
+ break;
+ case GL_ETC1_RGB8_OES:
+ if (context->getExtensions().compressedETC1RGB8Texture)
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+ else
+ {
+ context->handleError(InvalidEnum());
+ return false;
+ }
+ break;
+ case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+ case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
+ case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+ case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+ if (context->getExtensions().lossyETCDecode)
+ {
+ context->handleError(InvalidOperation()
+ << "ETC lossy decode formats can't work with this type.");
+ return false;
+ }
+ else
+ {
+ context->handleError(InvalidEnum()
+ << "ANGLE_lossy_etc_decode extension is not supported.");
+ return false;
+ }
+ break;
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_STENCIL_OES:
+ if (!context->getExtensions().depthTextures)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+ if (target != GL_TEXTURE_2D)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTargetAndFormat);
+ return false;
+ }
+ // OES_depth_texture supports loading depth data and multiple levels,
+ // but ANGLE_depth_texture does not
+ if (pixels != nullptr)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelDataNotNull);
+ return false;
+ }
+ if (level != 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), LevelNotZero);
+ return false;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!isSubImage)
+ {
+ switch (internalformat)
{
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
+ case GL_RGBA32F:
+ if (!context->getExtensions().colorBufferFloatRGBA)
+ {
+ context->handleError(InvalidValue()
+ << "Sized GL_RGBA32F internal format requires "
+ "GL_CHROMIUM_color_buffer_float_rgba");
+ return false;
+ }
+ if (type != GL_FLOAT)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
+ return false;
+ }
+ if (format != GL_RGBA)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
+ return false;
+ }
+ break;
+
+ case GL_RGB32F:
+ if (!context->getExtensions().colorBufferFloatRGB)
+ {
+ context->handleError(InvalidValue()
+ << "Sized GL_RGB32F internal format requires "
+ "GL_CHROMIUM_color_buffer_float_rgb");
+ return false;
+ }
+ if (type != GL_FLOAT)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
+ return false;
+ }
+ if (format != GL_RGB)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
+ return false;
+ }
+ break;
+
+ default:
+ break;
}
- break;
- default:
- break;
}
if (type == GL_FLOAT)
{
if (!context->getExtensions().textureFloat)
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return false;
}
}
@@ -457,561 +1568,246 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level,
{
if (!context->getExtensions().textureHalfFloat)
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return false;
}
}
}
+ GLenum sizeCheckFormat = isSubImage ? format : internalformat;
+ if (!ValidImageDataSize(context, target, width, height, 1, sizeCheckFormat, type, pixels,
+ imageSize))
+ {
+ return false;
+ }
+
return true;
}
-bool ValidateES2CopyTexImageParameters(ValidationContext *context,
- GLenum target,
- GLint level,
- GLenum internalformat,
- bool isSubImage,
- GLint xoffset,
- GLint yoffset,
- GLint x,
- GLint y,
- GLsizei width,
- GLsizei height,
- GLint border)
+bool ValidateES2TexStorageParameters(Context *context,
+ GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
{
- GLenum textureInternalFormat = GL_NONE;
+ if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP &&
+ target != GL_TEXTURE_RECTANGLE_ANGLE)
+ {
+ context->handleError(InvalidEnum());
+ return false;
+ }
- if (!ValidTexture2DDestinationTarget(context, target))
+ if (width < 1 || height < 1 || levels < 1)
{
- context->recordError(Error(GL_INVALID_ENUM, "Invalid texture target"));
+ context->handleError(InvalidValue());
return false;
}
- if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
- xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat))
+ if (target == GL_TEXTURE_CUBE_MAP && width != height)
{
+ context->handleError(InvalidValue());
return false;
}
- const gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
- GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat();
- const auto &internalFormatInfo = gl::GetInternalFormatInfo(textureInternalFormat);
- GLenum textureFormat = internalFormatInfo.format;
+ if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
- // [OpenGL ES 2.0.24] table 3.9
- if (isSubImage)
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
+ if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
{
- switch (textureFormat)
- {
- case GL_ALPHA:
- if (colorbufferFormat != GL_ALPHA8_EXT &&
- colorbufferFormat != GL_RGBA4 &&
- colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_RGBA8_OES)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_LUMINANCE:
- if (colorbufferFormat != GL_R8_EXT &&
- colorbufferFormat != GL_RG8_EXT &&
- colorbufferFormat != GL_RGB565 &&
- colorbufferFormat != GL_RGB8_OES &&
- colorbufferFormat != GL_RGBA4 &&
- colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_RGBA8_OES)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_RED_EXT:
- if (colorbufferFormat != GL_R8_EXT &&
- colorbufferFormat != GL_RG8_EXT &&
- colorbufferFormat != GL_RGB565 &&
- colorbufferFormat != GL_RGB8_OES &&
- colorbufferFormat != GL_RGBA4 &&
- colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_RGBA8_OES &&
- colorbufferFormat != GL_R32F &&
- colorbufferFormat != GL_RG32F &&
- colorbufferFormat != GL_RGB32F &&
- colorbufferFormat != GL_RGBA32F)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_RG_EXT:
- if (colorbufferFormat != GL_RG8_EXT &&
- colorbufferFormat != GL_RGB565 &&
- colorbufferFormat != GL_RGB8_OES &&
- colorbufferFormat != GL_RGBA4 &&
- colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_RGBA8_OES &&
- colorbufferFormat != GL_RG32F &&
- colorbufferFormat != GL_RGB32F &&
- colorbufferFormat != GL_RGBA32F)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_RGB:
- if (colorbufferFormat != GL_RGB565 &&
- colorbufferFormat != GL_RGB8_OES &&
- colorbufferFormat != GL_RGBA4 &&
- colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_RGBA8_OES &&
- colorbufferFormat != GL_RGB32F &&
- colorbufferFormat != GL_RGBA32F)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_LUMINANCE_ALPHA:
- case GL_RGBA:
- if (colorbufferFormat != GL_RGBA4 &&
- colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_RGBA8_OES &&
- colorbufferFormat != GL_RGBA32F)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
- case GL_ETC1_RGB8_OES:
- case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_STENCIL_OES:
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- default:
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
-
- if (internalFormatInfo.type == GL_FLOAT &&
- !context->getExtensions().textureFloat)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidEnum());
+ return false;
+ }
+
+ const gl::Caps &caps = context->getCaps();
+
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
+ static_cast<GLuint>(height) > caps.max2DTextureSize)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+ break;
+ case GL_TEXTURE_RECTANGLE_ANGLE:
+ if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
+ static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+ if (formatInfo.compressed)
+ {
+ context->handleError(InvalidEnum()
+ << "Rectangle texture cannot have a compressed format.");
+ return false;
+ }
+ break;
+ case GL_TEXTURE_CUBE_MAP:
+ if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
+ static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+ break;
+ default:
+ context->handleError(InvalidEnum());
return false;
- }
}
- else
+
+ if (levels != 1 && !context->getExtensions().textureNPOT)
{
- switch (internalformat)
+ if (!gl::isPow2(width) || !gl::isPow2(height))
{
- case GL_ALPHA:
- if (colorbufferFormat != GL_ALPHA8_EXT &&
- colorbufferFormat != GL_RGBA4 &&
- colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_BGRA8_EXT &&
- colorbufferFormat != GL_RGBA8_OES &&
- colorbufferFormat != GL_BGR5_A1_ANGLEX)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_LUMINANCE:
- if (colorbufferFormat != GL_R8_EXT &&
- colorbufferFormat != GL_RG8_EXT &&
- colorbufferFormat != GL_RGB565 &&
- colorbufferFormat != GL_RGB8_OES &&
- colorbufferFormat != GL_RGBA4 &&
- colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_BGRA8_EXT &&
- colorbufferFormat != GL_RGBA8_OES &&
- colorbufferFormat != GL_BGR5_A1_ANGLEX)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_RED_EXT:
- if (colorbufferFormat != GL_R8_EXT &&
- colorbufferFormat != GL_RG8_EXT &&
- colorbufferFormat != GL_RGB565 &&
- colorbufferFormat != GL_RGB8_OES &&
- colorbufferFormat != GL_RGBA4 &&
- colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_BGRA8_EXT &&
- colorbufferFormat != GL_RGBA8_OES &&
- colorbufferFormat != GL_BGR5_A1_ANGLEX)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_RG_EXT:
- if (colorbufferFormat != GL_RG8_EXT &&
- colorbufferFormat != GL_RGB565 &&
- colorbufferFormat != GL_RGB8_OES &&
- colorbufferFormat != GL_RGBA4 &&
- colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_BGRA8_EXT &&
- colorbufferFormat != GL_RGBA8_OES &&
- colorbufferFormat != GL_BGR5_A1_ANGLEX)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_RGB:
- if (colorbufferFormat != GL_RGB565 &&
- colorbufferFormat != GL_RGB8_OES &&
- colorbufferFormat != GL_RGBA4 &&
- colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_BGRA8_EXT &&
- colorbufferFormat != GL_RGBA8_OES &&
- colorbufferFormat != GL_BGR5_A1_ANGLEX)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_LUMINANCE_ALPHA:
- case GL_RGBA:
- if (colorbufferFormat != GL_RGBA4 &&
- colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_BGRA8_EXT &&
- colorbufferFormat != GL_RGBA8_OES &&
- colorbufferFormat != GL_BGR5_A1_ANGLEX)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- if (context->getExtensions().textureCompressionDXT1)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
+ return false;
+ }
+ }
+
+ switch (internalformat)
+ {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ if (!context->getExtensions().textureCompressionDXT1)
+ {
+ context->handleError(InvalidEnum());
return false;
}
- else
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ if (!context->getExtensions().textureCompressionDXT3)
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return false;
}
break;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
- if (context->getExtensions().textureCompressionDXT3)
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ if (!context->getExtensions().textureCompressionDXT5)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidEnum());
return false;
}
- else
+ break;
+ case GL_ETC1_RGB8_OES:
+ if (!context->getExtensions().compressedETC1RGB8Texture)
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return false;
}
break;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
- if (context->getExtensions().textureCompressionDXT5)
+ case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+ case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
+ case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+ case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+ if (!context->getExtensions().lossyETCDecode)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidEnum()
+ << "ANGLE_lossy_etc_decode extension is not supported.");
return false;
}
- else
+ break;
+ case GL_RGBA32F_EXT:
+ case GL_RGB32F_EXT:
+ case GL_ALPHA32F_EXT:
+ case GL_LUMINANCE32F_EXT:
+ case GL_LUMINANCE_ALPHA32F_EXT:
+ if (!context->getExtensions().textureFloat)
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return false;
}
break;
- case GL_ETC1_RGB8_OES:
- if (context->getExtensions().compressedETC1RGB8Texture)
+ case GL_RGBA16F_EXT:
+ case GL_RGB16F_EXT:
+ case GL_ALPHA16F_EXT:
+ case GL_LUMINANCE16F_EXT:
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ if (!context->getExtensions().textureHalfFloat)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidEnum());
return false;
}
- else
+ break;
+ case GL_R8_EXT:
+ case GL_RG8_EXT:
+ if (!context->getExtensions().textureRG)
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return false;
}
break;
- case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
- if (context->getExtensions().lossyETCDecode)
- {
- context->recordError(Error(GL_INVALID_OPERATION,
- "ETC1_RGB8_LOSSY_DECODE_ANGLE can't be copied to."));
- return false;
- }
- else
- {
- context->recordError(
- Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
- return false;
- }
- break;
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_COMPONENT16:
- case GL_DEPTH_COMPONENT32_OES:
- case GL_DEPTH_STENCIL_OES:
- case GL_DEPTH24_STENCIL8_OES:
- if (context->getExtensions().depthTextures)
+ case GL_R16F_EXT:
+ case GL_RG16F_EXT:
+ if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidEnum());
return false;
}
- else
+ break;
+ case GL_R32F_EXT:
+ case GL_RG32F_EXT:
+ if (!context->getExtensions().textureRG || !context->getExtensions().textureFloat)
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return false;
}
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- }
-
- // If width or height is zero, it is a no-op. Return false without setting an error.
- return (width > 0 && height > 0);
-}
-
-bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
- GLsizei width, GLsizei height)
-{
- if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
-
- if (width < 1 || height < 1 || levels < 1)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
-
- if (target == GL_TEXTURE_CUBE_MAP && width != height)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
-
- if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
-
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
- if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
-
- const gl::Caps &caps = context->getCaps();
-
- switch (target)
- {
- case GL_TEXTURE_2D:
- if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
- static_cast<GLuint>(height) > caps.max2DTextureSize)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
- break;
- case GL_TEXTURE_CUBE_MAP:
- if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
- static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
- break;
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
-
- if (levels != 1 && !context->getExtensions().textureNPOT)
- {
- if (!gl::isPow2(width) || !gl::isPow2(height))
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- }
-
- switch (internalformat)
- {
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- if (!context->getExtensions().textureCompressionDXT1)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
- if (!context->getExtensions().textureCompressionDXT3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
- if (!context->getExtensions().textureCompressionDXT5)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- break;
- case GL_ETC1_RGB8_OES:
- if (!context->getExtensions().compressedETC1RGB8Texture)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- break;
- case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
- if (!context->getExtensions().lossyETCDecode)
- {
- context->recordError(
- Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
- return false;
- }
- break;
- case GL_RGBA32F_EXT:
- case GL_RGB32F_EXT:
- case GL_ALPHA32F_EXT:
- case GL_LUMINANCE32F_EXT:
- case GL_LUMINANCE_ALPHA32F_EXT:
- if (!context->getExtensions().textureFloat)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- break;
- case GL_RGBA16F_EXT:
- case GL_RGB16F_EXT:
- case GL_ALPHA16F_EXT:
- case GL_LUMINANCE16F_EXT:
- case GL_LUMINANCE_ALPHA16F_EXT:
- if (!context->getExtensions().textureHalfFloat)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- break;
- case GL_R8_EXT:
- case GL_RG8_EXT:
- case GL_R16F_EXT:
- case GL_RG16F_EXT:
- case GL_R32F_EXT:
- case GL_RG32F_EXT:
- if (!context->getExtensions().textureRG)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- break;
- case GL_DEPTH_COMPONENT16:
- case GL_DEPTH_COMPONENT32_OES:
- case GL_DEPTH24_STENCIL8_OES:
- if (!context->getExtensions().depthTextures)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
- }
- if (target != GL_TEXTURE_2D)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- // ANGLE_depth_texture only supports 1-level textures
- if (levels != 1)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- break;
- default:
- break;
+ break;
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH_COMPONENT32_OES:
+ case GL_DEPTH24_STENCIL8_OES:
+ if (!context->getExtensions().depthTextures)
+ {
+ context->handleError(InvalidEnum());
+ return false;
+ }
+ if (target != GL_TEXTURE_2D)
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+ // ANGLE_depth_texture only supports 1-level textures
+ if (levels != 1)
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+ break;
+ default:
+ break;
}
gl::Texture *texture = context->getTargetTexture(target);
if (!texture || texture->id() == 0)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
if (texture->getImmutableFormat())
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
return true;
}
-// check for combinations of format and type that are valid for ReadPixels
-bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type)
-{
- switch (format)
- {
- case GL_RGBA:
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- break;
- default:
- return false;
- }
- break;
- case GL_BGRA_EXT:
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
- case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
- break;
- default:
- return false;
- }
- break;
- case GL_RG_EXT:
- case GL_RED_EXT:
- if (!context->getExtensions().textureRG)
- {
- return false;
- }
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- break;
- default:
- return false;
- }
- break;
-
- default:
- return false;
- }
- return true;
-}
-
-bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments,
+bool ValidateDiscardFramebufferEXT(Context *context,
+ GLenum target,
+ GLsizei numAttachments,
const GLenum *attachments)
{
if (!context->getExtensions().discardFramebuffer)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
@@ -1019,55 +1815,57 @@ bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numA
switch (target)
{
- case GL_FRAMEBUFFER:
- defaultFramebuffer = (context->getState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
- break;
- default:
- context->recordError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
- return false;
+ case GL_FRAMEBUFFER:
+ defaultFramebuffer =
+ (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
+ return false;
}
- return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
+ return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
+ defaultFramebuffer);
}
bool ValidateBindVertexArrayOES(Context *context, GLuint array)
{
if (!context->getExtensions().vertexArrayObject)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
return ValidateBindVertexArrayBase(context, array);
}
-bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n)
+bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n, const GLuint *arrays)
{
if (!context->getExtensions().vertexArrayObject)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
- return ValidateDeleteVertexArraysBase(context, n);
+ return ValidateGenOrDelete(context, n);
}
-bool ValidateGenVertexArraysOES(Context *context, GLsizei n)
+bool ValidateGenVertexArraysOES(Context *context, GLsizei n, GLuint *arrays)
{
if (!context->getExtensions().vertexArrayObject)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
- return ValidateGenVertexArraysBase(context, n);
+ return ValidateGenOrDelete(context, n);
}
-bool ValidateIsVertexArrayOES(Context *context)
+bool ValidateIsVertexArrayOES(Context *context, GLuint array)
{
if (!context->getExtensions().vertexArrayObject)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
@@ -1082,7 +1880,7 @@ bool ValidateProgramBinaryOES(Context *context,
{
if (!context->getExtensions().getProgramBinary)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
@@ -1098,7 +1896,7 @@ bool ValidateGetProgramBinaryOES(Context *context,
{
if (!context->getExtensions().getProgramBinary)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
@@ -1170,25 +1968,25 @@ bool ValidateDebugMessageControlKHR(Context *context,
{
if (!context->getExtensions().debug)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
{
- context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source."));
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
return false;
}
if (!ValidDebugType(type) && type != GL_DONT_CARE)
{
- context->recordError(Error(GL_INVALID_ENUM, "Invalid debug type."));
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugType);
return false;
}
if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
{
- context->recordError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSeverity);
return false;
}
@@ -1196,17 +1994,17 @@ bool ValidateDebugMessageControlKHR(Context *context,
{
if (source == GL_DONT_CARE || type == GL_DONT_CARE)
{
- context->recordError(Error(
- GL_INVALID_OPERATION,
- "If count is greater than zero, source and severity cannot be GL_DONT_CARE."));
+ context->handleError(
+ InvalidOperation()
+ << "If count is greater than zero, source and severity cannot be GL_DONT_CARE.");
return false;
}
if (severity != GL_DONT_CARE)
{
- context->recordError(
- Error(GL_INVALID_OPERATION,
- "If count is greater than zero, severity must be GL_DONT_CARE."));
+ context->handleError(
+ InvalidOperation()
+ << "If count is greater than zero, severity must be GL_DONT_CARE.");
return false;
}
}
@@ -1224,11 +2022,11 @@ bool ValidateDebugMessageInsertKHR(Context *context,
{
if (!context->getExtensions().debug)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
- if (!context->getState().getDebug().isOutputEnabled())
+ if (!context->getGLState().getDebug().isOutputEnabled())
{
// If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
// not generate an error.
@@ -1237,27 +2035,27 @@ bool ValidateDebugMessageInsertKHR(Context *context,
if (!ValidDebugSeverity(severity))
{
- context->recordError(Error(GL_INVALID_ENUM, "Invalid debug severity."));
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
return false;
}
if (!ValidDebugType(type))
{
- context->recordError(Error(GL_INVALID_ENUM, "Invalid debug type."));
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugType);
return false;
}
if (!ValidDebugSource(source, true))
{
- context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source."));
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
return false;
}
size_t messageLength = (length < 0) ? strlen(buf) : length;
if (messageLength > context->getExtensions().maxDebugMessageLength)
{
- context->recordError(
- Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
+ context->handleError(InvalidValue()
+ << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
return false;
}
@@ -1270,7 +2068,7 @@ bool ValidateDebugMessageCallbackKHR(Context *context,
{
if (!context->getExtensions().debug)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
@@ -1289,14 +2087,13 @@ bool ValidateGetDebugMessageLogKHR(Context *context,
{
if (!context->getExtensions().debug)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
if (bufSize < 0 && messageLog != nullptr)
{
- context->recordError(
- Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null."));
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
return false;
}
@@ -1311,30 +2108,30 @@ bool ValidatePushDebugGroupKHR(Context *context,
{
if (!context->getExtensions().debug)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
if (!ValidDebugSource(source, true))
{
- context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source."));
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
return false;
}
size_t messageLength = (length < 0) ? strlen(message) : length;
if (messageLength > context->getExtensions().maxDebugMessageLength)
{
- context->recordError(
- Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH."));
+ context->handleError(InvalidValue()
+ << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
return false;
}
- size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
+ size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
{
- context->recordError(
- Error(GL_STACK_OVERFLOW,
- "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups."));
+ context
+ ->handleError(StackOverflow()
+ << "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups.");
return false;
}
@@ -1345,14 +2142,14 @@ bool ValidatePopDebugGroupKHR(Context *context)
{
if (!context->getExtensions().debug)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
- size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
+ size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
if (currentStackSize <= 1)
{
- context->recordError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group."));
+ context->handleError(StackUnderflow() << "Cannot pop the default debug group.");
return false;
}
@@ -1366,7 +2163,7 @@ static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier,
case GL_BUFFER:
if (context->getBuffer(name) == nullptr)
{
- context->recordError(Error(GL_INVALID_VALUE, "name is not a valid buffer."));
+ context->handleError(InvalidValue() << "name is not a valid buffer.");
return false;
}
return true;
@@ -1374,7 +2171,7 @@ static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier,
case GL_SHADER:
if (context->getShader(name) == nullptr)
{
- context->recordError(Error(GL_INVALID_VALUE, "name is not a valid shader."));
+ context->handleError(InvalidValue() << "name is not a valid shader.");
return false;
}
return true;
@@ -1382,7 +2179,7 @@ static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier,
case GL_PROGRAM:
if (context->getProgram(name) == nullptr)
{
- context->recordError(Error(GL_INVALID_VALUE, "name is not a valid program."));
+ context->handleError(InvalidValue() << "name is not a valid program.");
return false;
}
return true;
@@ -1390,7 +2187,7 @@ static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier,
case GL_VERTEX_ARRAY:
if (context->getVertexArray(name) == nullptr)
{
- context->recordError(Error(GL_INVALID_VALUE, "name is not a valid vertex array."));
+ context->handleError(InvalidValue() << "name is not a valid vertex array.");
return false;
}
return true;
@@ -1398,7 +2195,7 @@ static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier,
case GL_QUERY:
if (context->getQuery(name) == nullptr)
{
- context->recordError(Error(GL_INVALID_VALUE, "name is not a valid query."));
+ context->handleError(InvalidValue() << "name is not a valid query.");
return false;
}
return true;
@@ -1406,8 +2203,7 @@ static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier,
case GL_TRANSFORM_FEEDBACK:
if (context->getTransformFeedback(name) == nullptr)
{
- context->recordError(
- Error(GL_INVALID_VALUE, "name is not a valid transform feedback."));
+ context->handleError(InvalidValue() << "name is not a valid transform feedback.");
return false;
}
return true;
@@ -1415,7 +2211,7 @@ static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier,
case GL_SAMPLER:
if (context->getSampler(name) == nullptr)
{
- context->recordError(Error(GL_INVALID_VALUE, "name is not a valid sampler."));
+ context->handleError(InvalidValue() << "name is not a valid sampler.");
return false;
}
return true;
@@ -1423,7 +2219,7 @@ static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier,
case GL_TEXTURE:
if (context->getTexture(name) == nullptr)
{
- context->recordError(Error(GL_INVALID_VALUE, "name is not a valid texture."));
+ context->handleError(InvalidValue() << "name is not a valid texture.");
return false;
}
return true;
@@ -1431,7 +2227,7 @@ static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier,
case GL_RENDERBUFFER:
if (context->getRenderbuffer(name) == nullptr)
{
- context->recordError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer."));
+ context->handleError(InvalidValue() << "name is not a valid renderbuffer.");
return false;
}
return true;
@@ -1439,15 +2235,38 @@ static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier,
case GL_FRAMEBUFFER:
if (context->getFramebuffer(name) == nullptr)
{
- context->recordError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer."));
+ context->handleError(InvalidValue() << "name is not a valid framebuffer.");
return false;
}
return true;
default:
- context->recordError(Error(GL_INVALID_ENUM, "Invalid identifier."));
+ context->handleError(InvalidEnum() << "Invalid identifier.");
return false;
}
+}
+
+static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
+{
+ size_t labelLength = 0;
+
+ if (length < 0)
+ {
+ if (label != nullptr)
+ {
+ labelLength = strlen(label);
+ }
+ }
+ else
+ {
+ labelLength = static_cast<size_t>(length);
+ }
+
+ if (labelLength > context->getExtensions().maxLabelLength)
+ {
+ context->handleError(InvalidValue() << "Label length is larger than GL_MAX_LABEL_LENGTH.");
+ return false;
+ }
return true;
}
@@ -1460,7 +2279,7 @@ bool ValidateObjectLabelKHR(Context *context,
{
if (!context->getExtensions().debug)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
@@ -1469,11 +2288,8 @@ bool ValidateObjectLabelKHR(Context *context,
return false;
}
- size_t labelLength = (length < 0) ? strlen(label) : length;
- if (labelLength > context->getExtensions().maxLabelLength)
+ if (!ValidateLabelLength(context, length, label))
{
- context->recordError(
- Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
return false;
}
@@ -1489,13 +2305,13 @@ bool ValidateGetObjectLabelKHR(Context *context,
{
if (!context->getExtensions().debug)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
if (bufSize < 0)
{
- context->recordError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
return false;
}
@@ -1504,15 +2320,14 @@ bool ValidateGetObjectLabelKHR(Context *context,
return false;
}
- // Can no-op if bufSize is zero.
- return bufSize > 0;
+ return true;
}
static bool ValidateObjectPtrName(Context *context, const void *ptr)
{
- if (context->getFenceSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
+ if (context->getSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
{
- context->recordError(Error(GL_INVALID_VALUE, "name is not a valid sync."));
+ context->handleError(InvalidValue() << "name is not a valid sync.");
return false;
}
@@ -1526,7 +2341,7 @@ bool ValidateObjectPtrLabelKHR(Context *context,
{
if (!context->getExtensions().debug)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
@@ -1535,11 +2350,8 @@ bool ValidateObjectPtrLabelKHR(Context *context,
return false;
}
- size_t labelLength = (length < 0) ? strlen(label) : length;
- if (labelLength > context->getExtensions().maxLabelLength)
+ if (!ValidateLabelLength(context, length, label))
{
- context->recordError(
- Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH."));
return false;
}
@@ -1554,13 +2366,13 @@ bool ValidateGetObjectPtrLabelKHR(Context *context,
{
if (!context->getExtensions().debug)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
if (bufSize < 0)
{
- context->recordError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
return false;
}
@@ -1569,15 +2381,14 @@ bool ValidateGetObjectPtrLabelKHR(Context *context,
return false;
}
- // Can no-op if bufSize is zero.
- return bufSize > 0;
+ return true;
}
bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
{
if (!context->getExtensions().debug)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
@@ -1589,7 +2400,7 @@ bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
break;
default:
- context->recordError(Error(GL_INVALID_ENUM, "Invalid pname."));
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
return false;
}
@@ -1610,27 +2421,27 @@ bool ValidateBlitFramebufferANGLE(Context *context,
{
if (!context->getExtensions().framebufferBlit)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Blit extension not available."));
+ context->handleError(InvalidOperation() << "Blit extension not available.");
return false;
}
if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
{
// TODO(jmadill): Determine if this should be available on other implementations.
- context->recordError(Error(
- GL_INVALID_OPERATION,
- "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."));
+ context->handleError(InvalidOperation() << "Scaling and flipping in "
+ "BlitFramebufferANGLE not supported by this "
+ "implementation.");
return false;
}
if (filter == GL_LINEAR)
{
- context->recordError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension"));
+ context->handleError(InvalidEnum() << "Linear blit not supported in this extension");
return false;
}
- const Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
- const Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer();
+ Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
+ Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
if (mask & GL_COLOR_BUFFER_BIT)
{
@@ -1644,7 +2455,7 @@ bool ValidateBlitFramebufferANGLE(Context *context,
readColorAttachment->type() != GL_RENDERBUFFER &&
readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
@@ -1660,26 +2471,25 @@ bool ValidateBlitFramebufferANGLE(Context *context,
attachment->type() != GL_RENDERBUFFER &&
attachment->type() != GL_FRAMEBUFFER_DEFAULT)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
// Return an error if the destination formats do not match
- if (attachment->getInternalFormat() != readColorAttachment->getInternalFormat())
+ if (!Format::EquivalentForBlit(attachment->getFormat(),
+ readColorAttachment->getFormat()))
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
}
}
- int readSamples = readFramebuffer->getSamples(context->getData());
-
- if (readSamples != 0 &&
+ if (readFramebuffer->getSamples(context) != 0 &&
IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
}
@@ -1702,16 +2512,15 @@ bool ValidateBlitFramebufferANGLE(Context *context,
dstX0, dstY0, dstX1, dstY1))
{
// only whole-buffer copies are permitted
- ERR(
- "Only whole-buffer depth and stencil blits are supported by this "
- "implementation.");
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation() << "Only whole-buffer depth and "
+ "stencil blits are supported by "
+ "this extension.");
return false;
}
if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
}
@@ -1724,21 +2533,35 @@ bool ValidateBlitFramebufferANGLE(Context *context,
bool ValidateClear(ValidationContext *context, GLbitfield mask)
{
- const Framebuffer *framebufferObject = context->getState().getDrawFramebuffer();
- ASSERT(framebufferObject);
-
- if (framebufferObject->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
+ Framebuffer *fbo = context->getGLState().getDrawFramebuffer();
+ if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
{
- context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ context->handleError(InvalidFramebufferOperation());
return false;
}
if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidClearMask);
return false;
}
+ if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
+ {
+ constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
+ GL_SIGNED_NORMALIZED};
+
+ for (GLuint drawBufferIdx = 0; drawBufferIdx < fbo->getDrawbufferStateCount();
+ drawBufferIdx++)
+ {
+ if (!ValidateWebGLFramebufferAttachmentClearType(
+ context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
+ {
+ return false;
+ }
+ }
+ }
+
return true;
}
@@ -1746,11 +2569,3783 @@ bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum
{
if (!context->getExtensions().drawBuffers)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Extension not supported."));
+ context->handleError(InvalidOperation() << "Extension not supported.");
return false;
}
return ValidateDrawBuffersBase(context, n, bufs);
}
+bool ValidateTexImage2D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
+ 0, 0, width, height, border, format, type, -1, pixels);
+ }
+
+ ASSERT(context->getClientMajorVersion() >= 3);
+ return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
+ 0, 0, width, height, 1, border, format, type, -1,
+ pixels);
+}
+
+bool ValidateTexImage2DRobust(Context *context,
+ GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (context->getClientMajorVersion() < 3)
+ {
+ return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
+ 0, 0, width, height, border, format, type, bufSize,
+ pixels);
+ }
+
+ ASSERT(context->getClientMajorVersion() >= 3);
+ return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
+ 0, 0, width, height, 1, border, format, type, bufSize,
+ pixels);
+}
+
+bool ValidateTexSubImage2D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+
+ if (context->getClientMajorVersion() < 3)
+ {
+ return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
+ yoffset, width, height, 0, format, type, -1, pixels);
+ }
+
+ ASSERT(context->getClientMajorVersion() >= 3);
+ return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
+ yoffset, 0, width, height, 1, 0, format, type, -1,
+ pixels);
+}
+
+bool ValidateTexSubImage2DRobustANGLE(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (context->getClientMajorVersion() < 3)
+ {
+ return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
+ yoffset, width, height, 0, format, type, bufSize,
+ pixels);
+ }
+
+ ASSERT(context->getClientMajorVersion() >= 3);
+ return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
+ yoffset, 0, width, height, 1, 0, format, type, bufSize,
+ pixels);
+}
+
+bool ValidateCompressedTexImage2D(Context *context,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ const void *data)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
+ 0, width, height, border, GL_NONE, GL_NONE, -1, data))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ ASSERT(context->getClientMajorVersion() >= 3);
+ if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
+ 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
+ data))
+ {
+ return false;
+ }
+ }
+
+ const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
+ auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, 1));
+ if (blockSizeOrErr.isError())
+ {
+ context->handleError(blockSizeOrErr.getError());
+ return false;
+ }
+
+ if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), CompressedTextureDimensionsMustMatchData);
+ return false;
+ }
+
+ if (target == GL_TEXTURE_RECTANGLE_ANGLE)
+ {
+ context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const void *data)
+{
+ if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
+ {
+ return false;
+ }
+
+ return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
+ border, imageSize, data);
+}
+bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const void *data)
+{
+ if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
+ {
+ return false;
+ }
+
+ return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
+ format, imageSize, data);
+}
+
+bool ValidateCompressedTexSubImage2D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
+ yoffset, width, height, 0, format, GL_NONE, -1, data))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ ASSERT(context->getClientMajorVersion() >= 3);
+ if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
+ yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
+ data))
+ {
+ return false;
+ }
+ }
+
+ const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
+ auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, 1));
+ if (blockSizeOrErr.isError())
+ {
+ context->handleError(blockSizeOrErr.getError());
+ return false;
+ }
+
+ if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetBufferPointervOES(Context *context,
+ BufferBinding target,
+ GLenum pname,
+ void **params)
+{
+ return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
+}
+
+bool ValidateMapBufferOES(Context *context, BufferBinding target, GLenum access)
+{
+ if (!context->getExtensions().mapBuffer)
+ {
+ context->handleError(InvalidOperation() << "Map buffer extension not available.");
+ return false;
+ }
+
+ if (!ValidBufferType(context, target))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
+ return false;
+ }
+
+ Buffer *buffer = context->getGLState().getTargetBuffer(target);
+
+ if (buffer == nullptr)
+ {
+ context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
+ return false;
+ }
+
+ if (access != GL_WRITE_ONLY_OES)
+ {
+ context->handleError(InvalidEnum() << "Non-write buffer mapping not supported.");
+ return false;
+ }
+
+ if (buffer->isMapped())
+ {
+ context->handleError(InvalidOperation() << "Buffer is already mapped.");
+ return false;
+ }
+
+ return ValidateMapBufferBase(context, target);
+}
+
+bool ValidateUnmapBufferOES(Context *context, BufferBinding target)
+{
+ if (!context->getExtensions().mapBuffer)
+ {
+ context->handleError(InvalidOperation() << "Map buffer extension not available.");
+ return false;
+ }
+
+ return ValidateUnmapBufferBase(context, target);
+}
+
+bool ValidateMapBufferRangeEXT(Context *context,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access)
+{
+ if (!context->getExtensions().mapBufferRange)
+ {
+ context->handleError(InvalidOperation() << "Map buffer range extension not available.");
+ return false;
+ }
+
+ return ValidateMapBufferRangeBase(context, target, offset, length, access);
+}
+
+bool ValidateMapBufferBase(Context *context, BufferBinding target)
+{
+ Buffer *buffer = context->getGLState().getTargetBuffer(target);
+ ASSERT(buffer != nullptr);
+
+ // Check if this buffer is currently being used as a transform feedback output buffer
+ TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
+ if (transformFeedback != nullptr && transformFeedback->isActive())
+ {
+ for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
+ {
+ const auto &transformFeedbackBuffer = transformFeedback->getIndexedBuffer(i);
+ if (transformFeedbackBuffer.get() == buffer)
+ {
+ context->handleError(InvalidOperation()
+ << "Buffer is currently bound for transform feedback.");
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool ValidateFlushMappedBufferRangeEXT(Context *context,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length)
+{
+ if (!context->getExtensions().mapBufferRange)
+ {
+ context->handleError(InvalidOperation() << "Map buffer range extension not available.");
+ return false;
+ }
+
+ return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
+}
+
+bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
+{
+ Texture *textureObject = context->getTexture(texture);
+ if (textureObject && textureObject->getTarget() != target && texture != 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), TypeMismatch);
+ return false;
+ }
+
+ if (!context->getGLState().isBindGeneratesResourceEnabled() &&
+ !context->isTextureGenerated(texture))
+ {
+ context->handleError(InvalidOperation() << "Texture was not generated");
+ return false;
+ }
+
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_CUBE_MAP:
+ break;
+
+ case GL_TEXTURE_RECTANGLE_ANGLE:
+ if (!context->getExtensions().textureRectangle)
+ {
+ context->handleError(InvalidEnum()
+ << "Context does not support GL_ANGLE_texture_rectangle");
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_2D_ARRAY:
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_2D_MULTISAMPLE:
+ if (context->getClientVersion() < Version(3, 1))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_EXTERNAL_OES:
+ if (!context->getExtensions().eglImageExternal &&
+ !context->getExtensions().eglStreamConsumerExternal)
+ {
+ context->handleError(InvalidEnum() << "External texture extension not enabled");
+ return false;
+ }
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBindUniformLocationCHROMIUM(Context *context,
+ GLuint program,
+ GLint location,
+ const GLchar *name)
+{
+ if (!context->getExtensions().bindUniformLocation)
+ {
+ context->handleError(InvalidOperation()
+ << "GL_CHROMIUM_bind_uniform_location is not available.");
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (location < 0)
+ {
+ context->handleError(InvalidValue() << "Location cannot be less than 0.");
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ if (static_cast<size_t>(location) >=
+ (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
+ {
+ context->handleError(InvalidValue() << "Location must be less than "
+ "(MAX_VERTEX_UNIFORM_VECTORS + "
+ "MAX_FRAGMENT_UNIFORM_VECTORS) * 4");
+ return false;
+ }
+
+ // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
+ // shader-related entry points
+ if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
+ return false;
+ }
+
+ if (strncmp(name, "gl_", 3) == 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NameBeginsWithGL);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
+{
+ if (!context->getExtensions().framebufferMixedSamples)
+ {
+ context->handleError(InvalidOperation()
+ << "GL_CHROMIUM_framebuffer_mixed_samples is not available.");
+ return false;
+ }
+ switch (components)
+ {
+ case GL_RGB:
+ case GL_RGBA:
+ case GL_ALPHA:
+ case GL_NONE:
+ break;
+ default:
+ context->handleError(
+ InvalidEnum()
+ << "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE.");
+ return false;
+ }
+
+ return true;
+}
+
+// CHROMIUM_path_rendering
+
+bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
+ return false;
+ }
+ if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMatrixMode);
+ return false;
+ }
+ if (matrix == nullptr)
+ {
+ context->handleError(InvalidOperation() << "Invalid matrix.");
+ return false;
+ }
+ return true;
+}
+
+bool ValidateMatrixMode(Context *context, GLenum matrixMode)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
+ return false;
+ }
+ if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMatrixMode);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateGenPaths(Context *context, GLsizei range)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
+ return false;
+ }
+
+ // range = 0 is undefined in NV_path_rendering.
+ // we add stricter semantic check here and require a non zero positive range.
+ if (range <= 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRange);
+ return false;
+ }
+
+ if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
+ return false;
+ }
+
+ // range = 0 is undefined in NV_path_rendering.
+ // we add stricter semantic check here and require a non zero positive range.
+ if (range <= 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRange);
+ return false;
+ }
+
+ angle::CheckedNumeric<std::uint32_t> checkedRange(path);
+ checkedRange += range;
+
+ if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
+ return false;
+ }
+ return true;
+}
+
+bool ValidatePathCommands(Context *context,
+ GLuint path,
+ GLsizei numCommands,
+ const GLubyte *commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const void *coords)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
+ return false;
+ }
+ if (!context->hasPath(path))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
+ return false;
+ }
+
+ if (numCommands < 0)
+ {
+ context->handleError(InvalidValue() << "Invalid number of commands.");
+ return false;
+ }
+ else if (numCommands > 0)
+ {
+ if (!commands)
+ {
+ context->handleError(InvalidValue() << "No commands array given.");
+ return false;
+ }
+ }
+
+ if (numCoords < 0)
+ {
+ context->handleError(InvalidValue() << "Invalid number of coordinates.");
+ return false;
+ }
+ else if (numCoords > 0)
+ {
+ if (!coords)
+ {
+ context->handleError(InvalidValue() << "No coordinate array given.");
+ return false;
+ }
+ }
+
+ std::uint32_t coordTypeSize = 0;
+ switch (coordType)
+ {
+ case GL_BYTE:
+ coordTypeSize = sizeof(GLbyte);
+ break;
+
+ case GL_UNSIGNED_BYTE:
+ coordTypeSize = sizeof(GLubyte);
+ break;
+
+ case GL_SHORT:
+ coordTypeSize = sizeof(GLshort);
+ break;
+
+ case GL_UNSIGNED_SHORT:
+ coordTypeSize = sizeof(GLushort);
+ break;
+
+ case GL_FLOAT:
+ coordTypeSize = sizeof(GLfloat);
+ break;
+
+ default:
+ context->handleError(InvalidEnum() << "Invalid coordinate type.");
+ return false;
+ }
+
+ angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
+ checkedSize += (coordTypeSize * numCoords);
+ if (!checkedSize.IsValid())
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
+ return false;
+ }
+
+ // early return skips command data validation when it doesn't exist.
+ if (!commands)
+ return true;
+
+ GLsizei expectedNumCoords = 0;
+ for (GLsizei i = 0; i < numCommands; ++i)
+ {
+ switch (commands[i])
+ {
+ case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
+ break;
+ case GL_MOVE_TO_CHROMIUM:
+ case GL_LINE_TO_CHROMIUM:
+ expectedNumCoords += 2;
+ break;
+ case GL_QUADRATIC_CURVE_TO_CHROMIUM:
+ expectedNumCoords += 4;
+ break;
+ case GL_CUBIC_CURVE_TO_CHROMIUM:
+ expectedNumCoords += 6;
+ break;
+ case GL_CONIC_CURVE_TO_CHROMIUM:
+ expectedNumCoords += 5;
+ break;
+ default:
+ context->handleError(InvalidEnum() << "Invalid command.");
+ return false;
+ }
+ }
+ if (expectedNumCoords != numCoords)
+ {
+ context->handleError(InvalidValue() << "Invalid number of coordinates.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
+ return false;
+ }
+ if (!context->hasPath(path))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_PATH_STROKE_WIDTH_CHROMIUM:
+ if (value < 0.0f)
+ {
+ context->handleError(InvalidValue() << "Invalid stroke width.");
+ return false;
+ }
+ break;
+ case GL_PATH_END_CAPS_CHROMIUM:
+ switch (static_cast<GLenum>(value))
+ {
+ case GL_FLAT_CHROMIUM:
+ case GL_SQUARE_CHROMIUM:
+ case GL_ROUND_CHROMIUM:
+ break;
+ default:
+ context->handleError(InvalidEnum() << "Invalid end caps.");
+ return false;
+ }
+ break;
+ case GL_PATH_JOIN_STYLE_CHROMIUM:
+ switch (static_cast<GLenum>(value))
+ {
+ case GL_MITER_REVERT_CHROMIUM:
+ case GL_BEVEL_CHROMIUM:
+ case GL_ROUND_CHROMIUM:
+ break;
+ default:
+ context->handleError(InvalidEnum() << "Invalid join style.");
+ return false;
+ }
+ case GL_PATH_MITER_LIMIT_CHROMIUM:
+ if (value < 0.0f)
+ {
+ context->handleError(InvalidValue() << "Invalid miter limit.");
+ return false;
+ }
+ break;
+
+ case GL_PATH_STROKE_BOUND_CHROMIUM:
+ // no errors, only clamping.
+ break;
+
+ default:
+ context->handleError(InvalidEnum() << "Invalid path parameter.");
+ return false;
+ }
+ return true;
+}
+
+bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
+ return false;
+ }
+
+ if (!context->hasPath(path))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
+ return false;
+ }
+ if (!value)
+ {
+ context->handleError(InvalidValue() << "No value array.");
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_PATH_STROKE_WIDTH_CHROMIUM:
+ case GL_PATH_END_CAPS_CHROMIUM:
+ case GL_PATH_JOIN_STYLE_CHROMIUM:
+ case GL_PATH_MITER_LIMIT_CHROMIUM:
+ case GL_PATH_STROKE_BOUND_CHROMIUM:
+ break;
+
+ default:
+ context->handleError(InvalidEnum() << "Invalid path parameter.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
+ return false;
+ }
+
+ switch (func)
+ {
+ case GL_NEVER:
+ case GL_ALWAYS:
+ case GL_LESS:
+ case GL_LEQUAL:
+ case GL_EQUAL:
+ case GL_GEQUAL:
+ case GL_GREATER:
+ case GL_NOTEQUAL:
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
+ return false;
+ }
+
+ return true;
+}
+
+// Note that the spec specifies that for the path drawing commands
+// if the path object is not an existing path object the command
+// does nothing and no error is generated.
+// However if the path object exists but has not been specified any
+// commands then an error is generated.
+
+bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
+ return false;
+ }
+ if (context->hasPath(path) && !context->hasPathData(path))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
+ return false;
+ }
+
+ switch (fillMode)
+ {
+ case GL_COUNT_UP_CHROMIUM:
+ case GL_COUNT_DOWN_CHROMIUM:
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
+ return false;
+ }
+
+ if (!isPow2(mask + 1))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
+ return false;
+ }
+ if (context->hasPath(path) && !context->hasPathData(path))
+ {
+ context->handleError(InvalidOperation() << "No such path or path has no data.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
+ return false;
+ }
+ if (context->hasPath(path) && !context->hasPathData(path))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
+ return false;
+ }
+
+ switch (coverMode)
+ {
+ case GL_CONVEX_HULL_CHROMIUM:
+ case GL_BOUNDING_BOX_CHROMIUM:
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateStencilThenCoverFillPath(Context *context,
+ GLuint path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode)
+{
+ return ValidateStencilFillPath(context, path, fillMode, mask) &&
+ ValidateCoverPath(context, path, coverMode);
+}
+
+bool ValidateStencilThenCoverStrokePath(Context *context,
+ GLuint path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode)
+{
+ return ValidateStencilStrokePath(context, path, reference, mask) &&
+ ValidateCoverPath(context, path, coverMode);
+}
+
+bool ValidateIsPath(Context *context)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
+ return false;
+ }
+ return true;
+}
+
+bool ValidateCoverFillPathInstanced(Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
+ transformType, transformValues))
+ return false;
+
+ switch (coverMode)
+ {
+ case GL_CONVEX_HULL_CHROMIUM:
+ case GL_BOUNDING_BOX_CHROMIUM:
+ case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCoverStrokePathInstanced(Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
+ transformType, transformValues))
+ return false;
+
+ switch (coverMode)
+ {
+ case GL_CONVEX_HULL_CHROMIUM:
+ case GL_BOUNDING_BOX_CHROMIUM:
+ case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStencilFillPathInstanced(Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+
+ if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
+ transformType, transformValues))
+ return false;
+
+ switch (fillMode)
+ {
+ case GL_COUNT_UP_CHROMIUM:
+ case GL_COUNT_DOWN_CHROMIUM:
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
+ return false;
+ }
+ if (!isPow2(mask + 1))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateStencilStrokePathInstanced(Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
+ transformType, transformValues))
+ return false;
+
+ // no more validation here.
+
+ return true;
+}
+
+bool ValidateStencilThenCoverFillPathInstanced(Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
+ transformType, transformValues))
+ return false;
+
+ switch (coverMode)
+ {
+ case GL_CONVEX_HULL_CHROMIUM:
+ case GL_BOUNDING_BOX_CHROMIUM:
+ case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
+ return false;
+ }
+
+ switch (fillMode)
+ {
+ case GL_COUNT_UP_CHROMIUM:
+ case GL_COUNT_DOWN_CHROMIUM:
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
+ return false;
+ }
+ if (!isPow2(mask + 1))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
+ transformType, transformValues))
+ return false;
+
+ switch (coverMode)
+ {
+ case GL_CONVEX_HULL_CHROMIUM:
+ case GL_BOUNDING_BOX_CHROMIUM:
+ case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBindFragmentInputLocation(Context *context,
+ GLuint program,
+ GLint location,
+ const GLchar *name)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
+ return false;
+ }
+
+ const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
+ if (location >= MaxLocation)
+ {
+ context->handleError(InvalidValue() << "Location exceeds max varying.");
+ return false;
+ }
+
+ const auto *programObject = context->getProgram(program);
+ if (!programObject)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
+ return false;
+ }
+
+ if (!name)
+ {
+ context->handleError(InvalidValue() << "No name given.");
+ return false;
+ }
+
+ if (angle::BeginsWith(name, "gl_"))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), NameBeginsWithGL);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateProgramPathFragmentInputGen(Context *context,
+ GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs)
+{
+ if (!context->getExtensions().pathRendering)
+ {
+ context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
+ return false;
+ }
+
+ const auto *programObject = context->getProgram(program);
+ if (!programObject || programObject->isFlaggedForDeletion())
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramDoesNotExist);
+ return false;
+ }
+
+ if (!programObject->isLinked())
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
+ return false;
+ }
+
+ switch (genMode)
+ {
+ case GL_NONE:
+ if (components != 0)
+ {
+ context->handleError(InvalidValue() << "Invalid components.");
+ return false;
+ }
+ break;
+
+ case GL_OBJECT_LINEAR_CHROMIUM:
+ case GL_EYE_LINEAR_CHROMIUM:
+ case GL_CONSTANT_CHROMIUM:
+ if (components < 1 || components > 4)
+ {
+ context->handleError(InvalidValue() << "Invalid components.");
+ return false;
+ }
+ if (!coeffs)
+ {
+ context->handleError(InvalidValue() << "No coefficients array given.");
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(InvalidEnum() << "Invalid gen mode.");
+ return false;
+ }
+
+ // If the location is -1 then the command is silently ignored
+ // and no further validation is needed.
+ if (location == -1)
+ return true;
+
+ const auto &binding = programObject->getFragmentInputBindingInfo(context, location);
+
+ if (!binding.valid)
+ {
+ context->handleError(InvalidOperation() << "No such binding.");
+ return false;
+ }
+
+ if (binding.type != GL_NONE)
+ {
+ GLint expectedComponents = 0;
+ switch (binding.type)
+ {
+ case GL_FLOAT:
+ expectedComponents = 1;
+ break;
+ case GL_FLOAT_VEC2:
+ expectedComponents = 2;
+ break;
+ case GL_FLOAT_VEC3:
+ expectedComponents = 3;
+ break;
+ case GL_FLOAT_VEC4:
+ expectedComponents = 4;
+ break;
+ default:
+ context->handleError(
+ InvalidOperation()
+ << "Fragment input type is not a floating point scalar or vector.");
+ return false;
+ }
+ if (expectedComponents != components && genMode != GL_NONE)
+ {
+ context->handleError(InvalidOperation() << "Unexpected number of components");
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ValidateCopyTextureCHROMIUM(Context *context,
+ GLuint sourceId,
+ GLint sourceLevel,
+ GLenum destTarget,
+ GLuint destId,
+ GLint destLevel,
+ GLint internalFormat,
+ GLenum destType,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha)
+{
+ if (!context->getExtensions().copyTexture)
+ {
+ context->handleError(InvalidOperation()
+ << "GL_CHROMIUM_copy_texture extension not available.");
+ return false;
+ }
+
+ const Texture *source = context->getTexture(sourceId);
+ if (source == nullptr)
+ {
+ context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
+ return false;
+ }
+
+ if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
+ {
+ context->handleError(InvalidValue() << "Source texture a valid texture type.");
+ return false;
+ }
+
+ GLenum sourceTarget = source->getTarget();
+ ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
+
+ if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
+ {
+ context->handleError(InvalidValue() << "Source texture level is not valid.");
+ return false;
+ }
+
+ GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
+ GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
+ if (sourceWidth == 0 || sourceHeight == 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
+ return false;
+ }
+
+ const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
+ if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
+ {
+ context->handleError(InvalidOperation() << "Source texture internal format is invalid.");
+ return false;
+ }
+
+ if (!IsValidCopyTextureDestinationTargetEnum(context, destTarget))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
+ return false;
+ }
+
+ const Texture *dest = context->getTexture(destId);
+ if (dest == nullptr)
+ {
+ context->handleError(InvalidValue()
+ << "Destination texture is not a valid texture object.");
+ return false;
+ }
+
+ if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
+ {
+ context->handleError(InvalidValue() << "Destination texture a valid texture type.");
+ return false;
+ }
+
+ if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, sourceWidth,
+ sourceHeight))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
+ return false;
+ }
+
+ if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
+ return false;
+ }
+
+ if (IsCubeMapTextureTarget(destTarget) && sourceWidth != sourceHeight)
+ {
+ context->handleError(
+ InvalidValue() << "Destination width and height must be equal for cube map textures.");
+ return false;
+ }
+
+ if (dest->getImmutableFormat())
+ {
+ context->handleError(InvalidOperation() << "Destination texture is immutable.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCopySubTextureCHROMIUM(Context *context,
+ GLuint sourceId,
+ GLint sourceLevel,
+ GLenum destTarget,
+ GLuint destId,
+ GLint destLevel,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha)
+{
+ if (!context->getExtensions().copyTexture)
+ {
+ context->handleError(InvalidOperation()
+ << "GL_CHROMIUM_copy_texture extension not available.");
+ return false;
+ }
+
+ const Texture *source = context->getTexture(sourceId);
+ if (source == nullptr)
+ {
+ context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
+ return false;
+ }
+
+ if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
+ {
+ context->handleError(InvalidValue() << "Source texture a valid texture type.");
+ return false;
+ }
+
+ GLenum sourceTarget = source->getTarget();
+ ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
+
+ if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
+ return false;
+ }
+
+ if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
+ source->getHeight(sourceTarget, sourceLevel) == 0)
+ {
+ context->handleError(InvalidValue()
+ << "The source level of the source texture must be defined.");
+ return false;
+ }
+
+ if (x < 0 || y < 0)
+ {
+ context->handleError(InvalidValue() << "x and y cannot be negative.");
+ return false;
+ }
+
+ if (width < 0 || height < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
+ return false;
+ }
+
+ if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
+ static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), SourceTextureTooSmall);
+ return false;
+ }
+
+ const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
+ if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
+ return false;
+ }
+
+ if (!IsValidCopyTextureDestinationTargetEnum(context, destTarget))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
+ return false;
+ }
+
+ const Texture *dest = context->getTexture(destId);
+ if (dest == nullptr)
+ {
+ context->handleError(InvalidValue()
+ << "Destination texture is not a valid texture object.");
+ return false;
+ }
+
+ if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
+ {
+ context->handleError(InvalidValue() << "Destination texture a valid texture type.");
+ return false;
+ }
+
+ if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, width, height))
+ {
+ context->handleError(InvalidValue() << "Destination texture level is not valid.");
+ return false;
+ }
+
+ if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
+ {
+ context
+ ->handleError(InvalidOperation()
+ << "The destination level of the destination texture must be defined.");
+ return false;
+ }
+
+ const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
+ if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
+ {
+ context->handleError(InvalidOperation()
+ << "Destination internal format and type combination is not valid.");
+ return false;
+ }
+
+ if (xoffset < 0 || yoffset < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
+ return false;
+ }
+
+ if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
+ static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
+ {
+ context->handleError(InvalidValue() << "Destination texture not large enough to copy to.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
+{
+ if (!context->getExtensions().copyCompressedTexture)
+ {
+ context->handleError(InvalidOperation()
+ << "GL_CHROMIUM_copy_compressed_texture extension not available.");
+ return false;
+ }
+
+ const gl::Texture *source = context->getTexture(sourceId);
+ if (source == nullptr)
+ {
+ context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
+ return false;
+ }
+
+ if (source->getTarget() != GL_TEXTURE_2D)
+ {
+ context->handleError(InvalidValue() << "Source texture must be of type GL_TEXTURE_2D.");
+ return false;
+ }
+
+ if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
+ {
+ context->handleError(InvalidValue() << "Source texture must level 0 defined.");
+ return false;
+ }
+
+ const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
+ if (!sourceFormat.info->compressed)
+ {
+ context->handleError(InvalidOperation()
+ << "Source texture must have a compressed internal format.");
+ return false;
+ }
+
+ const gl::Texture *dest = context->getTexture(destId);
+ if (dest == nullptr)
+ {
+ context->handleError(InvalidValue()
+ << "Destination texture is not a valid texture object.");
+ return false;
+ }
+
+ if (dest->getTarget() != GL_TEXTURE_2D)
+ {
+ context->handleError(InvalidValue()
+ << "Destination texture must be of type GL_TEXTURE_2D.");
+ return false;
+ }
+
+ if (dest->getImmutableFormat())
+ {
+ context->handleError(InvalidOperation() << "Destination cannot be immutable.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCreateShader(Context *context, GLenum type)
+{
+ switch (type)
+ {
+ case GL_VERTEX_SHADER:
+ case GL_FRAGMENT_SHADER:
+ break;
+
+ case GL_COMPUTE_SHADER:
+ if (context->getClientVersion() < Version(3, 1))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
+ return false;
+ }
+ break;
+
+ case GL_GEOMETRY_SHADER_EXT:
+ if (!context->getExtensions().geometryShader)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
+ return false;
+ }
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBufferData(ValidationContext *context,
+ BufferBinding target,
+ GLsizeiptr size,
+ const void *data,
+ BufferUsage usage)
+{
+ if (size < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
+ return false;
+ }
+
+ switch (usage)
+ {
+ case BufferUsage::StreamDraw:
+ case BufferUsage::StaticDraw:
+ case BufferUsage::DynamicDraw:
+ break;
+
+ case BufferUsage::StreamRead:
+ case BufferUsage::StaticRead:
+ case BufferUsage::DynamicRead:
+ case BufferUsage::StreamCopy:
+ case BufferUsage::StaticCopy:
+ case BufferUsage::DynamicCopy:
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
+ return false;
+ }
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
+ return false;
+ }
+
+ if (!ValidBufferType(context, target))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
+ return false;
+ }
+
+ Buffer *buffer = context->getGLState().getTargetBuffer(target);
+
+ if (!buffer)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBufferSubData(ValidationContext *context,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr size,
+ const void *data)
+{
+ if (size < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
+ return false;
+ }
+
+ if (offset < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
+ return false;
+ }
+
+ if (!ValidBufferType(context, target))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
+ return false;
+ }
+
+ Buffer *buffer = context->getGLState().getTargetBuffer(target);
+
+ if (!buffer)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
+ return false;
+ }
+
+ if (buffer->isMapped())
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+
+ // Check for possible overflow of size + offset
+ angle::CheckedNumeric<size_t> checkedSize(size);
+ checkedSize += offset;
+ if (!checkedSize.IsValid())
+ {
+ context->handleError(OutOfMemory());
+ return false;
+ }
+
+ if (size + offset > buffer->getSize())
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateRequestExtensionANGLE(Context *context, const GLchar *name)
+{
+ if (!context->getExtensions().requestExtension)
+ {
+ context->handleError(InvalidOperation() << "GL_ANGLE_request_extension is not available.");
+ return false;
+ }
+
+ if (!context->isExtensionRequestable(name))
+ {
+ context->handleError(InvalidOperation() << "Extension " << name << " is not requestable.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
+{
+ if (texture < GL_TEXTURE0 ||
+ texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
+ {
+ context->handleError(InvalidEnum());
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
+{
+ Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ Shader *shaderObject = GetValidShader(context, shader);
+ if (!shaderObject)
+ {
+ return false;
+ }
+
+ switch (shaderObject->getType())
+ {
+ case GL_VERTEX_SHADER:
+ {
+ if (programObject->getAttachedVertexShader())
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
+ return false;
+ }
+ break;
+ }
+ case GL_FRAGMENT_SHADER:
+ {
+ if (programObject->getAttachedFragmentShader())
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
+ return false;
+ }
+ break;
+ }
+ case GL_COMPUTE_SHADER:
+ {
+ if (programObject->getAttachedComputeShader())
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
+ return false;
+ }
+ break;
+ }
+ case GL_GEOMETRY_SHADER_EXT:
+ {
+ if (programObject->getAttachedGeometryShader())
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
+ return false;
+ }
+ break;
+ }
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ return true;
+}
+
+bool ValidateBindAttribLocation(ValidationContext *context,
+ GLuint program,
+ GLuint index,
+ const GLchar *name)
+{
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
+ return false;
+ }
+
+ if (strncmp(name, "gl_", 3) == 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), NameBeginsWithGL);
+ return false;
+ }
+
+ if (context->isWebGL())
+ {
+ const size_t length = strlen(name);
+
+ if (!IsValidESSLString(name, length))
+ {
+ // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters
+ // for shader-related entry points
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
+ return false;
+ }
+
+ if (!ValidateWebGLNameLength(context, length) || !ValidateWebGLNamePrefix(context, name))
+ {
+ return false;
+ }
+ }
+
+ return GetValidProgram(context, program) != nullptr;
+}
+
+bool ValidateBindBuffer(ValidationContext *context, BufferBinding target, GLuint buffer)
+{
+ if (!ValidBufferType(context, target))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
+ return false;
+ }
+
+ if (!context->getGLState().isBindGeneratesResourceEnabled() &&
+ !context->isBufferGenerated(buffer))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
+{
+ if (!ValidFramebufferTarget(context, target))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
+ return false;
+ }
+
+ if (!context->getGLState().isBindGeneratesResourceEnabled() &&
+ !context->isFramebufferGenerated(framebuffer))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
+{
+ if (target != GL_RENDERBUFFER)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
+ return false;
+ }
+
+ if (!context->getGLState().isBindGeneratesResourceEnabled() &&
+ !context->isRenderbufferGenerated(renderbuffer))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
+ return false;
+ }
+
+ return true;
+}
+
+static bool ValidBlendEquationMode(const ValidationContext *context, GLenum mode)
+{
+ switch (mode)
+ {
+ case GL_FUNC_ADD:
+ case GL_FUNC_SUBTRACT:
+ case GL_FUNC_REVERSE_SUBTRACT:
+ return true;
+
+ case GL_MIN:
+ case GL_MAX:
+ return context->getClientVersion() >= ES_3_0 || context->getExtensions().blendMinMax;
+
+ default:
+ return false;
+ }
+}
+
+bool ValidateBlendColor(ValidationContext *context,
+ GLfloat red,
+ GLfloat green,
+ GLfloat blue,
+ GLfloat alpha)
+{
+ return true;
+}
+
+bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
+{
+ if (!ValidBlendEquationMode(context, mode))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
+{
+ if (!ValidBlendEquationMode(context, modeRGB))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
+ return false;
+ }
+
+ if (!ValidBlendEquationMode(context, modeAlpha))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
+{
+ return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
+}
+
+static bool ValidSrcBlendFunc(GLenum srcBlend)
+{
+ switch (srcBlend)
+ {
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_CONSTANT_COLOR:
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ case GL_CONSTANT_ALPHA:
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ case GL_SRC_ALPHA_SATURATE:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
+{
+ switch (dstBlend)
+ {
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_CONSTANT_COLOR:
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ case GL_CONSTANT_ALPHA:
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ return true;
+
+ case GL_SRC_ALPHA_SATURATE:
+ return (contextMajorVersion >= 3);
+
+ default:
+ return false;
+ }
+}
+
+bool ValidateBlendFuncSeparate(ValidationContext *context,
+ GLenum srcRGB,
+ GLenum dstRGB,
+ GLenum srcAlpha,
+ GLenum dstAlpha)
+{
+ if (!ValidSrcBlendFunc(srcRGB))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
+ return false;
+ }
+
+ if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
+ return false;
+ }
+
+ if (!ValidSrcBlendFunc(srcAlpha))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
+ return false;
+ }
+
+ if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
+ return false;
+ }
+
+ if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
+ context->getExtensions().webglCompatibility)
+ {
+ bool constantColorUsed =
+ (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
+ dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
+
+ bool constantAlphaUsed =
+ (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
+ dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
+
+ if (constantColorUsed && constantAlphaUsed)
+ {
+ const char *msg;
+ if (context->getExtensions().webglCompatibility)
+ {
+ msg = kErrorInvalidConstantColor;
+ }
+ else
+ {
+ msg =
+ "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
+ "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
+ "implementation.";
+ ERR() << msg;
+ }
+ context->handleError(InvalidOperation() << msg);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGetString(Context *context, GLenum name)
+{
+ switch (name)
+ {
+ case GL_VENDOR:
+ case GL_RENDERER:
+ case GL_VERSION:
+ case GL_SHADING_LANGUAGE_VERSION:
+ case GL_EXTENSIONS:
+ break;
+
+ case GL_REQUESTABLE_EXTENSIONS_ANGLE:
+ if (!context->getExtensions().requestExtension)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
+ return false;
+ }
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateLineWidth(ValidationContext *context, GLfloat width)
+{
+ if (width <= 0.0f || isNaN(width))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidWidth);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateVertexAttribPointer(ValidationContext *context,
+ GLuint index,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLsizei stride,
+ const void *ptr)
+{
+ if (!ValidateVertexFormatBase(context, index, size, type, false))
+ {
+ return false;
+ }
+
+ if (stride < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ if (context->getClientVersion() >= ES_3_1)
+ {
+ if (stride > caps.maxVertexAttribStride)
+ {
+ context->handleError(InvalidValue()
+ << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
+ return false;
+ }
+
+ if (index >= caps.maxVertexAttribBindings)
+ {
+ context->handleError(InvalidValue()
+ << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
+ return false;
+ }
+ }
+
+ // [OpenGL ES 3.0.2] Section 2.8 page 24:
+ // An INVALID_OPERATION error is generated when a non-zero vertex array object
+ // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
+ // and the pointer argument is not NULL.
+ bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
+ context->getGLState().getVertexArray()->id() == 0;
+ if (!nullBufferAllowed && context->getGLState().getTargetBuffer(BufferBinding::Array) == 0 &&
+ ptr != nullptr)
+ {
+ context
+ ->handleError(InvalidOperation()
+ << "Client data cannot be used with a non-default vertex array object.");
+ return false;
+ }
+
+ if (context->getExtensions().webglCompatibility)
+ {
+ // WebGL 1.0 [Section 6.14] Fixed point support
+ // The WebGL API does not support the GL_FIXED data type.
+ if (type == GL_FIXED)
+ {
+ context->handleError(InvalidEnum() << "GL_FIXED is not supported in WebGL.");
+ return false;
+ }
+
+ if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
+{
+ if (context->getExtensions().webglCompatibility && zNear > zFar)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDepthRange);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateRenderbufferStorage(ValidationContext *context,
+ GLenum target,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
+ height);
+}
+
+bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
+ GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ if (!context->getExtensions().framebufferMultisample)
+ {
+ context->handleError(InvalidOperation()
+ << "GL_ANGLE_framebuffer_multisample not available");
+ return false;
+ }
+
+ // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
+ // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
+ // generated.
+ if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+
+ // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
+ // the specified storage. This is different than ES 3.0 in which a sample number higher
+ // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
+ // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
+ if (context->getClientMajorVersion() >= 3)
+ {
+ const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
+ if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
+ {
+ context->handleError(OutOfMemory());
+ return false;
+ }
+ }
+
+ return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
+ width, height);
+}
+
+bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
+{
+ if (!ValidFramebufferTarget(context, target))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateClearColor(ValidationContext *context,
+ GLfloat red,
+ GLfloat green,
+ GLfloat blue,
+ GLfloat alpha)
+{
+ return true;
+}
+
+bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
+{
+ return true;
+}
+
+bool ValidateClearStencil(ValidationContext *context, GLint s)
+{
+ return true;
+}
+
+bool ValidateColorMask(ValidationContext *context,
+ GLboolean red,
+ GLboolean green,
+ GLboolean blue,
+ GLboolean alpha)
+{
+ return true;
+}
+
+bool ValidateCompileShader(ValidationContext *context, GLuint shader)
+{
+ return true;
+}
+
+bool ValidateCreateProgram(ValidationContext *context)
+{
+ return true;
+}
+
+bool ValidateCullFace(ValidationContext *context, CullFaceMode mode)
+{
+ switch (mode)
+ {
+ case CullFaceMode::Front:
+ case CullFaceMode::Back:
+ case CullFaceMode::FrontAndBack:
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCullMode);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
+{
+ if (program == 0)
+ {
+ return false;
+ }
+
+ if (!context->getProgram(program))
+ {
+ if (context->getShader(program))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
+ return false;
+ }
+ else
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
+{
+ if (shader == 0)
+ {
+ return false;
+ }
+
+ if (!context->getShader(shader))
+ {
+ if (context->getProgram(shader))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidShaderName);
+ return false;
+ }
+ else
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), ExpectedShaderName);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateDepthFunc(ValidationContext *context, GLenum func)
+{
+ switch (func)
+ {
+ case GL_NEVER:
+ case GL_ALWAYS:
+ case GL_LESS:
+ case GL_LEQUAL:
+ case GL_EQUAL:
+ case GL_GREATER:
+ case GL_GEQUAL:
+ case GL_NOTEQUAL:
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
+{
+ return true;
+}
+
+bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
+{
+ Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ Shader *shaderObject = GetValidShader(context, shader);
+ if (!shaderObject)
+ {
+ return false;
+ }
+
+ const Shader *attachedShader = nullptr;
+
+ switch (shaderObject->getType())
+ {
+ case GL_VERTEX_SHADER:
+ {
+ attachedShader = programObject->getAttachedVertexShader();
+ break;
+ }
+ case GL_FRAGMENT_SHADER:
+ {
+ attachedShader = programObject->getAttachedFragmentShader();
+ break;
+ }
+ case GL_COMPUTE_SHADER:
+ {
+ attachedShader = programObject->getAttachedComputeShader();
+ break;
+ }
+ case GL_GEOMETRY_SHADER_EXT:
+ {
+ attachedShader = programObject->getAttachedGeometryShader();
+ break;
+ }
+ default:
+ UNREACHABLE();
+ return false;
+ }
+
+ if (attachedShader != shaderObject)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderToDetachMustBeAttached);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
+{
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
+{
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateFinish(ValidationContext *context)
+{
+ return true;
+}
+
+bool ValidateFlush(ValidationContext *context)
+{
+ return true;
+}
+
+bool ValidateFrontFace(ValidationContext *context, GLenum mode)
+{
+ switch (mode)
+ {
+ case GL_CW:
+ case GL_CCW:
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetActiveAttrib(ValidationContext *context,
+ GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name)
+{
+ if (bufsize < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxActiveUniform);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetActiveUniform(ValidationContext *context,
+ GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name)
+{
+ if (bufsize < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxActiveUniform);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetAttachedShaders(ValidationContext *context,
+ GLuint program,
+ GLsizei maxcount,
+ GLsizei *count,
+ GLuint *shaders)
+{
+ if (maxcount < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeMaxCount);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+
+ if (!programObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
+{
+ // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
+ // shader-related entry points
+ if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+
+ if (!programObject)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
+ return false;
+ }
+
+ if (!programObject->isLinked())
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
+{
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ return ValidateStateQuery(context, pname, &nativeType, &numParams);
+}
+
+bool ValidateGetError(ValidationContext *context)
+{
+ return true;
+}
+
+bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
+{
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ return ValidateStateQuery(context, pname, &nativeType, &numParams);
+}
+
+bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
+{
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ return ValidateStateQuery(context, pname, &nativeType, &numParams);
+}
+
+bool ValidateGetProgramInfoLog(ValidationContext *context,
+ GLuint program,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLchar *infolog)
+{
+ if (bufsize < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetShaderInfoLog(ValidationContext *context,
+ GLuint shader,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLchar *infolog)
+{
+ if (bufsize < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
+ return false;
+ }
+
+ Shader *shaderObject = GetValidShader(context, shader);
+ if (!shaderObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
+ GLenum shadertype,
+ GLenum precisiontype,
+ GLint *range,
+ GLint *precision)
+{
+ switch (shadertype)
+ {
+ case GL_VERTEX_SHADER:
+ case GL_FRAGMENT_SHADER:
+ break;
+ case GL_COMPUTE_SHADER:
+ context->handleError(InvalidOperation()
+ << "compute shader precision not yet implemented.");
+ return false;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
+ return false;
+ }
+
+ switch (precisiontype)
+ {
+ case GL_LOW_FLOAT:
+ case GL_MEDIUM_FLOAT:
+ case GL_HIGH_FLOAT:
+ case GL_LOW_INT:
+ case GL_MEDIUM_INT:
+ case GL_HIGH_INT:
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPrecision);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetShaderSource(ValidationContext *context,
+ GLuint shader,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLchar *source)
+{
+ if (bufsize < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
+ return false;
+ }
+
+ Shader *shaderObject = GetValidShader(context, shader);
+ if (!shaderObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
+{
+ if (strstr(name, "gl_") == name)
+ {
+ return false;
+ }
+
+ // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
+ // shader-related entry points
+ if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (!programObject->isLinked())
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
+{
+ switch (mode)
+ {
+ case GL_FASTEST:
+ case GL_NICEST:
+ case GL_DONT_CARE:
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+
+ switch (target)
+ {
+ case GL_GENERATE_MIPMAP_HINT:
+ break;
+
+ case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
+ if (context->getClientVersion() < ES_3_0 &&
+ !context->getExtensions().standardDerivatives)
+ {
+ context->handleError(InvalidEnum() << "hint requires OES_standard_derivatives.");
+ return false;
+ }
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
+{
+ return true;
+}
+
+bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
+{
+ return true;
+}
+
+bool ValidateIsProgram(ValidationContext *context, GLuint program)
+{
+ return true;
+}
+
+bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
+{
+ return true;
+}
+
+bool ValidateIsShader(ValidationContext *context, GLuint shader)
+{
+ return true;
+}
+
+bool ValidateIsTexture(ValidationContext *context, GLuint texture)
+{
+ return true;
+}
+
+bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ switch (pname)
+ {
+ case GL_UNPACK_IMAGE_HEIGHT:
+ case GL_UNPACK_SKIP_IMAGES:
+ context->handleError(InvalidEnum());
+ return false;
+
+ case GL_UNPACK_ROW_LENGTH:
+ case GL_UNPACK_SKIP_ROWS:
+ case GL_UNPACK_SKIP_PIXELS:
+ if (!context->getExtensions().unpackSubimage)
+ {
+ context->handleError(InvalidEnum());
+ return false;
+ }
+ break;
+
+ case GL_PACK_ROW_LENGTH:
+ case GL_PACK_SKIP_ROWS:
+ case GL_PACK_SKIP_PIXELS:
+ if (!context->getExtensions().packSubimage)
+ {
+ context->handleError(InvalidEnum());
+ return false;
+ }
+ break;
+ }
+ }
+
+ if (param < 0)
+ {
+ context->handleError(InvalidValue() << "Cannot use negative values in PixelStorei");
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_UNPACK_ALIGNMENT:
+ if (param != 1 && param != 2 && param != 4 && param != 8)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
+ return false;
+ }
+ break;
+
+ case GL_PACK_ALIGNMENT:
+ if (param != 1 && param != 2 && param != 4 && param != 8)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
+ return false;
+ }
+ break;
+
+ case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
+ if (!context->getExtensions().packReverseRowOrder)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ }
+ break;
+
+ case GL_UNPACK_ROW_LENGTH:
+ case GL_UNPACK_IMAGE_HEIGHT:
+ case GL_UNPACK_SKIP_IMAGES:
+ case GL_UNPACK_SKIP_ROWS:
+ case GL_UNPACK_SKIP_PIXELS:
+ case GL_PACK_ROW_LENGTH:
+ case GL_PACK_SKIP_ROWS:
+ case GL_PACK_SKIP_PIXELS:
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
+{
+ return true;
+}
+
+bool ValidateReleaseShaderCompiler(ValidationContext *context)
+{
+ return true;
+}
+
+bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
+{
+ return true;
+}
+
+bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ if (width < 0 || height < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateShaderBinary(ValidationContext *context,
+ GLsizei n,
+ const GLuint *shaders,
+ GLenum binaryformat,
+ const void *binary,
+ GLsizei length)
+{
+ const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
+ if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
+ shaderBinaryFormats.end())
+ {
+ context->handleError(InvalidEnum() << "Invalid shader binary format.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateShaderSource(ValidationContext *context,
+ GLuint shader,
+ GLsizei count,
+ const GLchar *const *string,
+ const GLint *length)
+{
+ if (count < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
+ return false;
+ }
+
+ // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
+ // shader-related entry points
+ if (context->getExtensions().webglCompatibility)
+ {
+ for (GLsizei i = 0; i < count; i++)
+ {
+ size_t len =
+ (length && length[i] >= 0) ? static_cast<size_t>(length[i]) : strlen(string[i]);
+
+ // Backslash as line-continuation is allowed in WebGL 2.0.
+ if (!IsValidESSLShaderSourceString(string[i], len,
+ context->getClientVersion() >= ES_3_0))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), ShaderSourceInvalidCharacters);
+ return false;
+ }
+ }
+ }
+
+ Shader *shaderObject = GetValidShader(context, shader);
+ if (!shaderObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
+{
+ if (!IsValidStencilFunc(func))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStencilFuncSeparate(ValidationContext *context,
+ GLenum face,
+ GLenum func,
+ GLint ref,
+ GLuint mask)
+{
+ if (!IsValidStencilFace(face))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
+ return false;
+ }
+
+ if (!IsValidStencilFunc(func))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStencilMask(ValidationContext *context, GLuint mask)
+{
+ return true;
+}
+
+bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
+{
+ if (!IsValidStencilFace(face))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
+{
+ if (!IsValidStencilOp(fail))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
+ return false;
+ }
+
+ if (!IsValidStencilOp(zfail))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
+ return false;
+ }
+
+ if (!IsValidStencilOp(zpass))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStencilOpSeparate(ValidationContext *context,
+ GLenum face,
+ GLenum fail,
+ GLenum zfail,
+ GLenum zpass)
+{
+ if (!IsValidStencilFace(face))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
+ return false;
+ }
+
+ return ValidateStencilOp(context, fail, zfail, zpass);
+}
+
+bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
+{
+ return ValidateUniform(context, GL_FLOAT, location, 1);
+}
+
+bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
+{
+ return ValidateUniform(context, GL_FLOAT, location, count);
+}
+
+bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
+{
+ return ValidateUniform1iv(context, location, 1, &x);
+}
+
+bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
+{
+ return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
+}
+
+bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
+{
+ return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
+}
+
+bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
+{
+ return ValidateUniform(context, GL_INT_VEC2, location, 1);
+}
+
+bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
+{
+ return ValidateUniform(context, GL_INT_VEC2, location, count);
+}
+
+bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
+{
+ return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
+}
+
+bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
+{
+ return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
+}
+
+bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
+{
+ return ValidateUniform(context, GL_INT_VEC3, location, 1);
+}
+
+bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
+{
+ return ValidateUniform(context, GL_INT_VEC3, location, count);
+}
+
+bool ValidateUniform4f(ValidationContext *context,
+ GLint location,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z,
+ GLfloat w)
+{
+ return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
+}
+
+bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
+{
+ return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
+}
+
+bool ValidateUniform4i(ValidationContext *context,
+ GLint location,
+ GLint x,
+ GLint y,
+ GLint z,
+ GLint w)
+{
+ return ValidateUniform(context, GL_INT_VEC4, location, 1);
+}
+
+bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
+{
+ return ValidateUniform(context, GL_INT_VEC4, location, count);
+}
+
+bool ValidateUniformMatrix2fv(ValidationContext *context,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
+}
+
+bool ValidateUniformMatrix3fv(ValidationContext *context,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
+}
+
+bool ValidateUniformMatrix4fv(ValidationContext *context,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
+}
+
+bool ValidateValidateProgram(ValidationContext *context, GLuint program)
+{
+ Program *programObject = GetValidProgram(context, program);
+
+ if (!programObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
+{
+ return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
+{
+ return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
+{
+ return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
+{
+ return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateVertexAttrib3f(ValidationContext *context,
+ GLuint index,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z)
+{
+ return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
+{
+ return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateVertexAttrib4f(ValidationContext *context,
+ GLuint index,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z,
+ GLfloat w)
+{
+ return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
+{
+ return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ if (width < 0 || height < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), ViewportNegativeSize);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
+{
+ return ValidateDrawArraysCommon(context, mode, first, count, 1);
+}
+
+bool ValidateDrawElements(ValidationContext *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices)
+{
+ return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
+}
+
+bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLint *params)
+{
+ return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
+ nullptr);
+}
+
+bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
+{
+ return ValidateGetProgramivBase(context, program, pname, nullptr);
+}
+
+bool ValidateCopyTexImage2D(ValidationContext *context,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
+ 0, x, y, width, height, border);
+ }
+
+ ASSERT(context->getClientMajorVersion() == 3);
+ return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
+ 0, x, y, width, height, border);
+}
+
+bool ValidateCopyTexSubImage2D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
+ yoffset, x, y, width, height, 0);
+ }
+
+ return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
+ yoffset, 0, x, y, width, height, 0);
+}
+
+bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
+{
+ return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
+{
+ return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
+{
+ return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
+{
+ return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateDisable(Context *context, GLenum cap)
+{
+ if (!ValidCap(context, cap, false))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateEnable(Context *context, GLenum cap)
+{
+ if (!ValidCap(context, cap, false))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+
+ if (context->getLimitations().noSampleAlphaToCoverageSupport &&
+ cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
+ {
+ const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
+ context->handleError(InvalidOperation() << errorMessage);
+
+ // We also output an error message to the debugger window if tracing is active, so that
+ // developers can see the error message.
+ ERR() << errorMessage;
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateFramebufferRenderbuffer(Context *context,
+ GLenum target,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer)
+{
+ if (!ValidFramebufferTarget(context, target))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
+ return false;
+ }
+
+ if (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
+ return false;
+ }
+
+ return ValidateFramebufferRenderbufferParameters(context, target, attachment,
+ renderbuffertarget, renderbuffer);
+}
+
+bool ValidateFramebufferTexture2D(Context *context,
+ GLenum target,
+ GLenum attachment,
+ GLenum textarget,
+ GLuint texture,
+ GLint level)
+{
+ // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
+ // extension
+ if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
+ level != 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidFramebufferTextureLevel);
+ return false;
+ }
+
+ if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
+ {
+ return false;
+ }
+
+ if (texture != 0)
+ {
+ gl::Texture *tex = context->getTexture(texture);
+ ASSERT(tex);
+
+ const gl::Caps &caps = context->getCaps();
+
+ switch (textarget)
+ {
+ case GL_TEXTURE_2D:
+ {
+ if (level > gl::log2(caps.max2DTextureSize))
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+ if (tex->getTarget() != GL_TEXTURE_2D)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidTextureTarget);
+ return false;
+ }
+ }
+ break;
+
+ case GL_TEXTURE_RECTANGLE_ANGLE:
+ {
+ if (level != 0)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+ if (tex->getTarget() != GL_TEXTURE_RECTANGLE_ANGLE)
+ {
+ context->handleError(InvalidOperation()
+ << "Textarget must match the texture target type.");
+ return false;
+ }
+ }
+ break;
+
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ {
+ if (level > gl::log2(caps.maxCubeMapTextureSize))
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+ if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
+ {
+ context->handleError(InvalidOperation()
+ << "Textarget must match the texture target type.");
+ return false;
+ }
+ }
+ break;
+
+ case GL_TEXTURE_2D_MULTISAMPLE:
+ {
+ if (context->getClientVersion() < ES_3_1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ if (level != 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), LevelNotZero);
+ return false;
+ }
+ if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
+ {
+ context->handleError(InvalidOperation()
+ << "Textarget must match the texture target type.");
+ return false;
+ }
+ }
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
+ return false;
+ }
+
+ const Format &format = tex->getFormat(textarget, level);
+ if (format.info->compressed)
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
+{
+ return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
+{
+ return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
+{
+ return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateGenTextures(Context *context, GLint n, GLuint *)
+{
+ return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateGenerateMipmap(Context *context, GLenum target)
+{
+ if (!ValidTextureTarget(context, target))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
+ return false;
+ }
+
+ Texture *texture = context->getTargetTexture(target);
+
+ if (texture == nullptr)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
+ return false;
+ }
+
+ const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
+
+ // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
+ // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
+ if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+
+ GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
+ const auto &format = *(texture->getFormat(baseTarget, effectiveBaseLevel).info);
+ if (format.sizedInternalFormat == GL_NONE || format.compressed || format.depthBits > 0 ||
+ format.stencilBits > 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
+ return false;
+ }
+
+ // GenerateMipmap accepts formats that are unsized or both color renderable and filterable.
+ bool formatUnsized = !format.sized;
+ bool formatColorRenderableAndFilterable =
+ format.filterSupport(context->getClientVersion(), context->getExtensions()) &&
+ format.renderSupport(context->getClientVersion(), context->getExtensions());
+ if (!formatUnsized && !formatColorRenderableAndFilterable)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
+ return false;
+ }
+
+ // GL_EXT_sRGB adds an unsized SRGB (no alpha) format which has explicitly disabled mipmap
+ // generation
+ if (format.colorEncoding == GL_SRGB && format.format == GL_RGB)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
+ return false;
+ }
+
+ // ES3 and WebGL grant mipmap generation for sRGBA (with alpha) textures but GL_EXT_sRGB does
+ // not.
+ bool supportsSRGBMipmapGeneration =
+ context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
+ if (!supportsSRGBMipmapGeneration && format.colorEncoding == GL_SRGB)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
+ return false;
+ }
+
+ // Non-power of 2 ES2 check
+ if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
+ (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
+ !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
+ {
+ ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ANGLE ||
+ target == GL_TEXTURE_CUBE_MAP);
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotPow2);
+ return false;
+ }
+
+ // Cube completeness check
+ if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), CubemapIncomplete);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetBufferParameteriv(ValidationContext *context,
+ BufferBinding target,
+ GLenum pname,
+ GLint *params)
+{
+ return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
+}
+
+bool ValidateGetRenderbufferParameteriv(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLint *params)
+{
+ return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
+}
+
+bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
+{
+ return ValidateGetShaderivBase(context, shader, pname, nullptr);
+}
+
+bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
+{
+ return ValidateGetTexParameterBase(context, target, pname, nullptr);
+}
+
+bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
+{
+ return ValidateGetTexParameterBase(context, target, pname, nullptr);
+}
+
+bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
+{
+ return ValidateGetUniformBase(context, program, location);
+}
+
+bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
+{
+ return ValidateGetUniformBase(context, program, location);
+}
+
+bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
+{
+ return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
+}
+
+bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
+{
+ return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
+}
+
+bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
+{
+ return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
+}
+
+bool ValidateIsEnabled(Context *context, GLenum cap)
+{
+ if (!ValidCap(context, cap, true))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateLinkProgram(Context *context, GLuint program)
+{
+ if (context->hasActiveTransformFeedback(program))
+ {
+ // ES 3.0.4 section 2.15 page 91
+ context->handleError(InvalidOperation() << "Cannot link program while program is "
+ "associated with an active transform "
+ "feedback object.");
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateReadPixels(Context *context,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ void *pixels)
+{
+ return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
+ nullptr, pixels);
+}
+
+bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
+{
+ return ValidateTexParameterBase(context, target, pname, -1, &param);
+}
+
+bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
+{
+ return ValidateTexParameterBase(context, target, pname, -1, params);
+}
+
+bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
+{
+ return ValidateTexParameterBase(context, target, pname, -1, &param);
+}
+
+bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
+{
+ return ValidateTexParameterBase(context, target, pname, -1, params);
+}
+
+bool ValidateUseProgram(Context *context, GLuint program)
+{
+ if (program != 0)
+ {
+ Program *programObject = context->getProgram(program);
+ if (!programObject)
+ {
+ // ES 3.1.0 section 7.3 page 72
+ if (context->getShader(program))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
+ return false;
+ }
+ else
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
+ return false;
+ }
+ }
+ if (!programObject->isLinked())
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
+ return false;
+ }
+ }
+ if (context->getGLState().isTransformFeedbackActiveUnpaused())
+ {
+ // ES 3.0.4 section 2.15 page 91
+ context
+ ->handleError(InvalidOperation()
+ << "Cannot change active program while transform feedback is unpaused.");
+ return false;
+ }
+
+ return true;
+}
+
} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/validationES2.h b/src/3rdparty/angle/src/libANGLE/validationES2.h
index 1b2cf13f60..5dc09176a1 100644
--- a/src/3rdparty/angle/src/libANGLE/validationES2.h
+++ b/src/3rdparty/angle/src/libANGLE/validationES2.h
@@ -9,6 +9,8 @@
#ifndef LIBANGLE_VALIDATION_ES2_H_
#define LIBANGLE_VALIDATION_ES2_H_
+#include "libANGLE/PackedGLEnums.h"
+
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
@@ -17,37 +19,24 @@ namespace gl
class Context;
class ValidationContext;
-bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
- GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- GLint border, GLenum format, GLenum type, const GLvoid *pixels);
-
-bool ValidateES2CopyTexImageParameters(ValidationContext *context,
- GLenum target,
- GLint level,
- GLenum internalformat,
- bool isSubImage,
- GLint xoffset,
- GLint yoffset,
- GLint x,
- GLint y,
- GLsizei width,
- GLsizei height,
- GLint border);
-
-bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
- GLsizei width, GLsizei height);
-
-bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type);
-
-bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments,
+bool ValidateES2TexStorageParameters(Context *context,
+ GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+
+bool ValidateDiscardFramebufferEXT(Context *context,
+ GLenum target,
+ GLsizei numAttachments,
const GLenum *attachments);
bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs);
bool ValidateBindVertexArrayOES(Context *context, GLuint array);
-bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n);
-bool ValidateGenVertexArraysOES(Context *context, GLsizei n);
-bool ValidateIsVertexArrayOES(Context *context);
+bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n, const GLuint *arrays);
+bool ValidateGenVertexArraysOES(Context *context, GLsizei n, GLuint *arrays);
+bool ValidateIsVertexArrayOES(Context *context, GLuint array);
bool ValidateProgramBinaryOES(Context *context,
GLuint program,
@@ -128,7 +117,571 @@ bool ValidateBlitFramebufferANGLE(Context *context,
GLenum filter);
bool ValidateClear(ValidationContext *context, GLbitfield mask);
+bool ValidateTexImage2D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+bool ValidateTexImage2DRobust(Context *context,
+ GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels);
+bool ValidateTexSubImage2D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+bool ValidateTexSubImage2DRobustANGLE(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels);
+bool ValidateCompressedTexImage2D(Context *context,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ const void *data);
+bool ValidateCompressedTexSubImage2D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data);
+bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const void *data);
+bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const void *data);
+
+bool ValidateBindTexture(Context *context, GLenum target, GLuint texture);
+
+bool ValidateGetBufferPointervOES(Context *context,
+ BufferBinding target,
+ GLenum pname,
+ void **params);
+bool ValidateMapBufferOES(Context *context, BufferBinding target, GLenum access);
+bool ValidateUnmapBufferOES(Context *context, BufferBinding target);
+bool ValidateMapBufferRangeEXT(Context *context,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access);
+bool ValidateMapBufferBase(Context *context, BufferBinding target);
+bool ValidateFlushMappedBufferRangeEXT(Context *context,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length);
+
+bool ValidateBindUniformLocationCHROMIUM(Context *context,
+ GLuint program,
+ GLint location,
+ const GLchar *name);
+
+bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components);
+
+// CHROMIUM_path_rendering
+bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix);
+bool ValidateMatrixMode(Context *context, GLenum matrixMode);
+bool ValidateGenPaths(Context *context, GLsizei range);
+bool ValidateDeletePaths(Context *context, GLuint first, GLsizei range);
+bool ValidatePathCommands(Context *context,
+ GLuint path,
+ GLsizei numCommands,
+ const GLubyte *commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const void *coords);
+bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value);
+bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value);
+bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask);
+bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask);
+bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask);
+bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode);
+bool ValidateStencilThenCoverFillPath(Context *context,
+ GLuint path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode);
+bool ValidateStencilThenCoverStrokePath(Context *context,
+ GLuint path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode);
+bool ValidateIsPath(Context *context);
+bool ValidateCoverFillPathInstanced(Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+bool ValidateCoverStrokePathInstanced(Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+bool ValidateStencilFillPathInstanced(Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBAse,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+bool ValidateStencilStrokePathInstanced(Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+bool ValidateStencilThenCoverFillPathInstanced(Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
+ GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+bool ValidateBindFragmentInputLocation(Context *context,
+ GLuint program,
+ GLint location,
+ const GLchar *name);
+bool ValidateProgramPathFragmentInputGen(Context *context,
+ GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs);
+
+bool ValidateCopyTextureCHROMIUM(Context *context,
+ GLuint sourceId,
+ GLint sourceLevel,
+ GLenum destTarget,
+ GLuint destId,
+ GLint destLevel,
+ GLint internalFormat,
+ GLenum destType,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha);
+bool ValidateCopySubTextureCHROMIUM(Context *context,
+ GLuint sourceId,
+ GLint sourceLevel,
+ GLenum destTarget,
+ GLuint destId,
+ GLint destLevel,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha);
+bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId);
+
+bool ValidateCreateShader(Context *context, GLenum type);
+bool ValidateBufferData(ValidationContext *context,
+ BufferBinding target,
+ GLsizeiptr size,
+ const void *data,
+ BufferUsage usage);
+bool ValidateBufferSubData(ValidationContext *context,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr size,
+ const void *data);
+
+bool ValidateRequestExtensionANGLE(Context *context, const GLchar *name);
+
+bool ValidateActiveTexture(ValidationContext *context, GLenum texture);
+bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader);
+bool ValidateBindAttribLocation(ValidationContext *context,
+ GLuint program,
+ GLuint index,
+ const GLchar *name);
+bool ValidateBindBuffer(ValidationContext *context, BufferBinding target, GLuint buffer);
+bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer);
+bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer);
+bool ValidateBlendColor(ValidationContext *context,
+ GLclampf red,
+ GLclampf green,
+ GLclampf blue,
+ GLclampf alpha);
+bool ValidateBlendEquation(ValidationContext *context, GLenum mode);
+bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha);
+bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor);
+bool ValidateBlendFuncSeparate(ValidationContext *context,
+ GLenum srcRGB,
+ GLenum dstRGB,
+ GLenum srcAlpha,
+ GLenum dstAlpha);
+
+bool ValidateGetString(Context *context, GLenum name);
+bool ValidateLineWidth(ValidationContext *context, GLfloat width);
+bool ValidateVertexAttribPointer(ValidationContext *context,
+ GLuint index,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLsizei stride,
+ const void *ptr);
+
+bool ValidateDepthRangef(ValidationContext *context, GLclampf zNear, GLclampf zFar);
+bool ValidateRenderbufferStorage(ValidationContext *context,
+ GLenum target,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
+ GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+
+bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target);
+bool ValidateClearColor(ValidationContext *context,
+ GLclampf red,
+ GLclampf green,
+ GLclampf blue,
+ GLclampf alpha);
+bool ValidateClearDepthf(ValidationContext *context, GLclampf depth);
+bool ValidateClearStencil(ValidationContext *context, GLint s);
+bool ValidateColorMask(ValidationContext *context,
+ GLboolean red,
+ GLboolean green,
+ GLboolean blue,
+ GLboolean alpha);
+bool ValidateCompileShader(ValidationContext *context, GLuint shader);
+bool ValidateCreateProgram(ValidationContext *context);
+bool ValidateCullFace(ValidationContext *context, CullFaceMode mode);
+bool ValidateDeleteProgram(ValidationContext *context, GLuint program);
+bool ValidateDeleteShader(ValidationContext *context, GLuint shader);
+bool ValidateDepthFunc(ValidationContext *context, GLenum func);
+bool ValidateDepthMask(ValidationContext *context, GLboolean flag);
+bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader);
+bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index);
+bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index);
+bool ValidateFinish(ValidationContext *context);
+bool ValidateFlush(ValidationContext *context);
+bool ValidateFrontFace(ValidationContext *context, GLenum mode);
+bool ValidateGetActiveAttrib(ValidationContext *context,
+ GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name);
+bool ValidateGetActiveUniform(ValidationContext *context,
+ GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name);
+bool ValidateGetAttachedShaders(ValidationContext *context,
+ GLuint program,
+ GLsizei maxcount,
+ GLsizei *count,
+ GLuint *shaders);
+bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name);
+bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params);
+bool ValidateGetError(ValidationContext *context);
+bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params);
+bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params);
+bool ValidateGetProgramInfoLog(ValidationContext *context,
+ GLuint program,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLchar *infolog);
+bool ValidateGetShaderInfoLog(ValidationContext *context,
+ GLuint shader,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLchar *infolog);
+bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
+ GLenum shadertype,
+ GLenum precisiontype,
+ GLint *range,
+ GLint *precision);
+bool ValidateGetShaderSource(ValidationContext *context,
+ GLuint shader,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLchar *source);
+bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name);
+bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode);
+bool ValidateIsBuffer(ValidationContext *context, GLuint buffer);
+bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer);
+bool ValidateIsProgram(ValidationContext *context, GLuint program);
+bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer);
+bool ValidateIsShader(ValidationContext *context, GLuint shader);
+bool ValidateIsTexture(ValidationContext *context, GLuint texture);
+bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param);
+bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units);
+bool ValidateReleaseShaderCompiler(ValidationContext *context);
+bool ValidateSampleCoverage(ValidationContext *context, GLclampf value, GLboolean invert);
+bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height);
+bool ValidateShaderBinary(ValidationContext *context,
+ GLsizei n,
+ const GLuint *shaders,
+ GLenum binaryformat,
+ const void *binary,
+ GLsizei length);
+bool ValidateShaderSource(ValidationContext *context,
+ GLuint shader,
+ GLsizei count,
+ const GLchar *const *string,
+ const GLint *length);
+bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask);
+bool ValidateStencilFuncSeparate(ValidationContext *context,
+ GLenum face,
+ GLenum func,
+ GLint ref,
+ GLuint mask);
+bool ValidateStencilMask(ValidationContext *context, GLuint mask);
+bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask);
+bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass);
+bool ValidateStencilOpSeparate(ValidationContext *context,
+ GLenum face,
+ GLenum fail,
+ GLenum zfail,
+ GLenum zpass);
+bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x);
+bool ValidateUniform1fv(ValidationContext *context,
+ GLint location,
+ GLsizei count,
+ const GLfloat *v);
+bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x);
+bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y);
+bool ValidateUniform2fv(ValidationContext *context,
+ GLint location,
+ GLsizei count,
+ const GLfloat *v);
+bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y);
+bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v);
+bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z);
+bool ValidateUniform3fv(ValidationContext *context,
+ GLint location,
+ GLsizei count,
+ const GLfloat *v);
+bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z);
+bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v);
+bool ValidateUniform4f(ValidationContext *context,
+ GLint location,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z,
+ GLfloat w);
+bool ValidateUniform4fv(ValidationContext *context,
+ GLint location,
+ GLsizei count,
+ const GLfloat *v);
+bool ValidateUniform4i(ValidationContext *context,
+ GLint location,
+ GLint x,
+ GLint y,
+ GLint z,
+ GLint w);
+bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v);
+bool ValidateUniformMatrix2fv(ValidationContext *context,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateUniformMatrix3fv(ValidationContext *context,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateUniformMatrix4fv(ValidationContext *context,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateValidateProgram(ValidationContext *context, GLuint program);
+bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x);
+bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values);
+bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y);
+bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values);
+bool ValidateVertexAttrib3f(ValidationContext *context,
+ GLuint index,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z);
+bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values);
+bool ValidateVertexAttrib4f(ValidationContext *context,
+ GLuint index,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z,
+ GLfloat w);
+bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values);
+bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height);
+bool ValidateDrawElements(ValidationContext *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices);
+
+bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count);
+
+bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLint *params);
+bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params);
+
+bool ValidateCopyTexImage2D(ValidationContext *context,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border);
+
+bool ValidateCopyTexSubImage2D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+
+bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *buffers);
+bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *framebuffers);
+bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *renderbuffers);
+bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *textures);
+bool ValidateDisable(Context *context, GLenum cap);
+bool ValidateEnable(Context *context, GLenum cap);
+bool ValidateFramebufferRenderbuffer(Context *context,
+ GLenum target,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer);
+bool ValidateFramebufferTexture2D(Context *context,
+ GLenum target,
+ GLenum attachment,
+ GLenum textarget,
+ GLuint texture,
+ GLint level);
+bool ValidateGenBuffers(Context *context, GLint n, GLuint *buffers);
+bool ValidateGenerateMipmap(Context *context, GLenum target);
+bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *framebuffers);
+bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *renderbuffers);
+bool ValidateGenTextures(Context *context, GLint n, GLuint *textures);
+bool ValidateGetBufferParameteriv(ValidationContext *context,
+ BufferBinding target,
+ GLenum pname,
+ GLint *params);
+bool ValidateGetRenderbufferParameteriv(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLint *params);
+bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params);
+bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params);
+bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params);
+bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params);
+bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params);
+bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params);
+bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params);
+bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer);
+bool ValidateIsEnabled(Context *context, GLenum cap);
+bool ValidateLinkProgram(Context *context, GLuint program);
+bool ValidateReadPixels(Context *context,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ void *pixels);
+bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param);
+bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params);
+bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param);
+bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params);
+bool ValidateUniform1iv(ValidationContext *context,
+ GLint location,
+ GLsizei count,
+ const GLint *value);
+bool ValidateUseProgram(Context *context, GLuint program);
} // namespace gl
-#endif // LIBANGLE_VALIDATION_ES2_H_
+#endif // LIBANGLE_VALIDATION_ES2_H_
diff --git a/src/3rdparty/angle/src/libANGLE/validationES3.cpp b/src/3rdparty/angle/src/libANGLE/validationES3.cpp
index 2db64ec4cc..1aadfc876e 100644
--- a/src/3rdparty/angle/src/libANGLE/validationES3.cpp
+++ b/src/3rdparty/angle/src/libANGLE/validationES3.cpp
@@ -7,255 +7,190 @@
// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
#include "libANGLE/validationES3.h"
-#include "libANGLE/validationES.h"
+
+#include "anglebase/numerics/safe_conversions.h"
+#include "common/mathutil.h"
+#include "common/utilities.h"
#include "libANGLE/Context.h"
-#include "libANGLE/Texture.h"
+#include "libANGLE/ErrorStrings.h"
#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Texture.h"
#include "libANGLE/formatutils.h"
-#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/validationES.h"
-#include "common/mathutil.h"
-#include "common/utilities.h"
+using namespace angle;
namespace gl
{
-struct ES3FormatCombination
+namespace
{
- GLenum internalFormat;
- GLenum format;
- GLenum type;
-};
+bool ValidateFramebufferTextureMultiviewBaseANGLE(Context *context,
+ GLenum target,
+ GLenum attachment,
+ GLuint texture,
+ GLint level,
+ GLsizei numViews)
+{
+ if (!context->getExtensions().multiview)
+ {
+ context->handleError(InvalidOperation() << "ANGLE_multiview is not available.");
+ return false;
+ }
+
+ if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
+ {
+ return false;
+ }
-bool operator<(const ES3FormatCombination& a, const ES3FormatCombination& b)
-{
- return memcmp(&a, &b, sizeof(ES3FormatCombination)) < 0;
-}
-
-typedef std::set<ES3FormatCombination> ES3FormatCombinationSet;
-
-static inline void InsertES3FormatCombo(ES3FormatCombinationSet *set, GLenum internalFormat, GLenum format, GLenum type)
-{
- ES3FormatCombination info;
- info.internalFormat = internalFormat;
- info.format = format;
- info.type = type;
- set->insert(info);
-}
-
-ES3FormatCombinationSet BuildES3FormatSet()
-{
- ES3FormatCombinationSet set;
-
- // Format combinations from ES 3.0.1 spec, table 3.2
-
- // | Internal format | Format | Type |
- // | | | |
- InsertES3FormatCombo(&set, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_RGBA8_SNORM, GL_RGBA, GL_BYTE );
- InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 );
- InsertES3FormatCombo(&set, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV );
- InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV );
- InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 );
- InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT );
- InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT_OES );
- InsertES3FormatCombo(&set, GL_RGBA32F, GL_RGBA, GL_FLOAT );
- InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_FLOAT );
- InsertES3FormatCombo(&set, GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE );
- InsertES3FormatCombo(&set, GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT );
- InsertES3FormatCombo(&set, GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT );
- InsertES3FormatCombo(&set, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT );
- InsertES3FormatCombo(&set, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT );
- InsertES3FormatCombo(&set, GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV );
- InsertES3FormatCombo(&set, GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_RGB8_SNORM, GL_RGB, GL_BYTE );
- InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 );
- InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV );
- InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV );
- InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT );
- InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT_OES );
- InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT );
- InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT_OES );
- InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT );
- InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT_OES );
- InsertES3FormatCombo(&set, GL_RGB32F, GL_RGB, GL_FLOAT );
- InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_FLOAT );
- InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT );
- InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_FLOAT );
- InsertES3FormatCombo(&set, GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_RGB8I, GL_RGB_INTEGER, GL_BYTE );
- InsertES3FormatCombo(&set, GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT );
- InsertES3FormatCombo(&set, GL_RGB16I, GL_RGB_INTEGER, GL_SHORT );
- InsertES3FormatCombo(&set, GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT );
- InsertES3FormatCombo(&set, GL_RGB32I, GL_RGB_INTEGER, GL_INT );
- InsertES3FormatCombo(&set, GL_RG8, GL_RG, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_RG8_SNORM, GL_RG, GL_BYTE );
- InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT );
- InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT_OES );
- InsertES3FormatCombo(&set, GL_RG32F, GL_RG, GL_FLOAT );
- InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_FLOAT );
- InsertES3FormatCombo(&set, GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_RG8I, GL_RG_INTEGER, GL_BYTE );
- InsertES3FormatCombo(&set, GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT );
- InsertES3FormatCombo(&set, GL_RG16I, GL_RG_INTEGER, GL_SHORT );
- InsertES3FormatCombo(&set, GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT );
- InsertES3FormatCombo(&set, GL_RG32I, GL_RG_INTEGER, GL_INT );
- InsertES3FormatCombo(&set, GL_R8, GL_RED, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_R8_SNORM, GL_RED, GL_BYTE );
- InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT );
- InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT_OES );
- InsertES3FormatCombo(&set, GL_R32F, GL_RED, GL_FLOAT );
- InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_FLOAT );
- InsertES3FormatCombo(&set, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_R8I, GL_RED_INTEGER, GL_BYTE );
- InsertES3FormatCombo(&set, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT );
- InsertES3FormatCombo(&set, GL_R16I, GL_RED_INTEGER, GL_SHORT );
- InsertES3FormatCombo(&set, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT );
- InsertES3FormatCombo(&set, GL_R32I, GL_RED_INTEGER, GL_INT );
-
- // Unsized formats
- InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 );
- InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 );
- InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 );
- InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_SRGB_ALPHA_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_SRGB_EXT, GL_SRGB_EXT, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_FLOAT );
- InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_HALF_FLOAT );
- InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_HALF_FLOAT_OES );
- InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_FLOAT );
- InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_HALF_FLOAT );
- InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_HALF_FLOAT_OES );
- InsertES3FormatCombo(&set, GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 );
-
- // Depth stencil formats
- InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT );
- InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT );
- InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT );
- InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT );
- InsertES3FormatCombo(&set, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 );
- InsertES3FormatCombo(&set, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
-
- // From GL_EXT_sRGB
- InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_SRGB8, GL_SRGB_EXT, GL_UNSIGNED_BYTE );
-
- // From GL_OES_texture_float
- InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_FLOAT );
- InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_FLOAT );
- InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT );
- InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT );
- InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_FLOAT );
-
- // From GL_OES_texture_half_float
- InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT );
- InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES );
- InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT );
- InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES );
- InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT );
- InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES );
-
- // From GL_EXT_texture_format_BGRA8888
- InsertES3FormatCombo(&set, GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
-
- // From GL_EXT_texture_storage
- // | Internal format | Format | Type |
- // | | | |
- InsertES3FormatCombo(&set, GL_ALPHA8_EXT, GL_ALPHA, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_LUMINANCE8_EXT, GL_LUMINANCE, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT );
- InsertES3FormatCombo(&set, GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT );
- InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT );
- InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT );
- InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT_OES );
- InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT );
- InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT_OES );
- InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT );
- InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES );
-
- // From GL_EXT_texture_storage and GL_EXT_texture_format_BGRA8888
- InsertES3FormatCombo(&set, GL_BGRA8_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT);
- InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
- InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT);
- InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE );
-
- // From GL_ANGLE_depth_texture
- InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32_OES, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8_OES );
-
- return set;
-}
-
-static bool ValidateTexImageFormatCombination(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type)
+ if (texture != 0 && numViews < 1)
+ {
+ context->handleError(InvalidValue() << "numViews cannot be less than 1.");
+ return false;
+ }
+
+ const Extensions &extensions = context->getExtensions();
+ if (static_cast<GLuint>(numViews) > extensions.maxViews)
+ {
+ context->handleError(InvalidValue()
+ << "numViews cannot be greater than GL_MAX_VIEWS_ANGLE.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateFramebufferTextureMultiviewLevelAndFormat(Context *context,
+ Texture *texture,
+ GLint level)
{
- // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
- // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
- // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
- // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
- if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
+ GLenum texTarget = texture->getTarget();
+ if (!ValidMipLevel(context, texTarget, level))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
+ return false;
+ }
+
+ const auto &format = texture->getFormat(texTarget, level);
+ if (format.info->compressed)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), CompressedTexturesNotAttachable);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateUniformES3(Context *context, GLenum uniformType, GLint location, GLint count)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ return ValidateUniform(context, uniformType, location, count);
+}
+
+bool ValidateUniformMatrixES3(Context *context,
+ GLenum valueType,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose)
+{
+ // Check for ES3 uniform entry points
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ return ValidateUniformMatrix(context, valueType, location, count, transpose);
+}
+
+bool ValidateGenOrDeleteES3(Context *context, GLint n)
+{
+ if (context->getClientMajorVersion() < 3)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
return false;
}
+ return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+ if (count < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
+ return false;
+ }
+ return true;
+}
+
+} // anonymous namespace
+
+static bool ValidateTexImageFormatCombination(gl::Context *context,
+ GLenum target,
+ GLenum internalFormat,
+ GLenum format,
+ GLenum type)
+{
// The type and format are valid if any supported internal format has that type and format
- bool formatSupported = false;
- bool typeSupported = false;
+ if (!ValidES3Format(format))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
+ return false;
+ }
- static const ES3FormatCombinationSet es3FormatSet = BuildES3FormatSet();
- for (ES3FormatCombinationSet::const_iterator i = es3FormatSet.begin(); i != es3FormatSet.end(); i++)
+ if (!ValidES3Type(type))
{
- if (i->format == format || i->type == type)
- {
- const gl::InternalFormat &info = gl::GetInternalFormatInfo(i->internalFormat);
- bool supported = info.textureSupport(context->getClientVersion(), context->getExtensions());
- if (supported && i->type == type)
- {
- typeSupported = true;
- }
- if (supported && i->format == format)
- {
- formatSupported = true;
- }
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
+ return false;
+ }
- // Early-out if both type and format are supported now
- if (typeSupported && formatSupported)
- {
- break;
- }
- }
+ // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
+ // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
+ // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
+ // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
+ if (!ValidES3InternalFormat(internalFormat))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidInternalFormat);
+ return false;
}
- if (!typeSupported || !formatSupported)
+ // From the ES 3.0 spec section 3.8.3:
+ // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
+ // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
+ // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
+ // INVALID_OPERATION error.
+ if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidOperation() << "Format cannot be GL_DEPTH_COMPONENT or "
+ "GL_DEPTH_STENCIL if target is "
+ "GL_TEXTURE_3D");
return false;
}
// Check if this is a valid format combination to load texture data
- ES3FormatCombination searchFormat;
- searchFormat.internalFormat = internalFormat;
- searchFormat.format = format;
- searchFormat.type = type;
+ if (!ValidES3FormatCombination(format, type, internalFormat))
+ {
+ context->handleError(InvalidOperation()
+ << "Invalid combination of format, type and internalFormat.");
+ return false;
+ }
- if (es3FormatSet.find(searchFormat) == es3FormatSet.end())
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
+ if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation() << "Unsupported internal format.");
return false;
}
@@ -277,19 +212,20 @@ bool ValidateES3TexImageParametersBase(Context *context,
GLint border,
GLenum format,
GLenum type,
- const GLvoid *pixels)
+ GLsizei imageSize,
+ const void *pixels)
{
// Validate image size
if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage))
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
// Verify zero border
if (border != 0)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
@@ -298,7 +234,7 @@ bool ValidateES3TexImageParametersBase(Context *context,
std::numeric_limits<GLsizei>::max() - yoffset < height ||
std::numeric_limits<GLsizei>::max() - zoffset < depth)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
@@ -306,112 +242,158 @@ bool ValidateES3TexImageParametersBase(Context *context,
switch (target)
{
- case GL_TEXTURE_2D:
- if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
- static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
- break;
+ case GL_TEXTURE_2D:
+ if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
+ static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+ break;
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- if (!isSubImage && width != height)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
+ case GL_TEXTURE_RECTANGLE_ANGLE:
+ ASSERT(level == 0);
+ if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
+ static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+ if (isCompressed)
+ {
+ context->handleError(InvalidEnum()
+ << "Rectangle texture cannot have a compressed format.");
+ return false;
+ }
+ break;
- if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
- break;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ if (!isSubImage && width != height)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
- case GL_TEXTURE_3D:
- if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
- static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
- static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
- break;
+ if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+ break;
- case GL_TEXTURE_2D_ARRAY:
- if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
- static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
- static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
- break;
+ case GL_TEXTURE_3D:
+ if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
+ static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
+ static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+ break;
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
+ case GL_TEXTURE_2D_ARRAY:
+ if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
+ static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
+ static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+ break;
+
+ default:
+ context->handleError(InvalidEnum());
+ return false;
}
- gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+ gl::Texture *texture =
+ context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
if (!texture)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
if (texture->getImmutableFormat() && !isSubImage)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
// Validate texture formats
- GLenum actualInternalFormat = isSubImage ? texture->getInternalFormat(target, level) : internalformat;
- const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
+ GLenum actualInternalFormat =
+ isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
+ if (isSubImage && actualInternalFormat == GL_NONE)
+ {
+ context->handleError(InvalidOperation() << "Texture level does not exist.");
+ return false;
+ }
+
+ const gl::InternalFormat &actualFormatInfo = isSubImage
+ ? *texture->getFormat(target, level).info
+ : GetInternalFormatInfo(internalformat, type);
if (isCompressed)
{
if (!actualFormatInfo.compressed)
{
- context->recordError(Error(
- GL_INVALID_ENUM, "internalformat is not a supported compressed internal format."));
+ context->handleError(
+ InvalidEnum() << "internalformat is not a supported compressed internal format.");
return false;
}
- if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
+ if (isSubImage)
{
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
+ if (!ValidCompressedSubImageSize(
+ context, actualFormatInfo.internalFormat, xoffset, yoffset, width, height,
+ texture->getWidth(target, level), texture->getHeight(target, level)))
+ {
+ context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
+ return false;
+ }
+
+ if (format != actualInternalFormat)
+ {
+ context->handleError(InvalidOperation()
+ << "Format must match the internal format of the texture.");
+ return false;
+ }
+
+ if (actualInternalFormat == GL_ETC1_RGB8_OES)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
+ return false;
+ }
+ }
+ else
+ {
+ if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
+ {
+ context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
+ return false;
+ }
}
if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return false;
}
if (target == GL_TEXTURE_3D)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
}
else
{
- if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type))
- {
- return false;
- }
-
- if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
+ if (!ValidateTexImageFormatCombination(context, target, actualInternalFormat, format, type))
{
- context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
@@ -421,18 +403,13 @@ bool ValidateES3TexImageParametersBase(Context *context,
{
if (isCompressed != actualFormatInfo.compressed)
{
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
-
- if (width == 0 || height == 0 || depth == 0)
- {
+ context->handleError(InvalidOperation());
return false;
}
if (xoffset < 0 || yoffset < 0 || zoffset < 0)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
@@ -440,7 +417,7 @@ bool ValidateES3TexImageParametersBase(Context *context,
std::numeric_limits<GLsizei>::max() - yoffset < height ||
std::numeric_limits<GLsizei>::max() - zoffset < depth)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
@@ -448,54 +425,42 @@ bool ValidateES3TexImageParametersBase(Context *context,
static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
- }
- // Check for pixel unpack buffer related API errors
- gl::Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
- if (pixelUnpackBuffer != NULL)
- {
- // ...the data would be unpacked from the buffer object such that the memory reads required
- // would exceed the data store size.
- size_t widthSize = static_cast<size_t>(width);
- size_t heightSize = static_cast<size_t>(height);
- size_t depthSize = static_cast<size_t>(depth);
- GLenum sizedFormat = GetSizedInternalFormat(actualInternalFormat, type);
-
- size_t pixelBytes = static_cast<size_t>(gl::GetInternalFormatInfo(sizedFormat).pixelBytes);
-
- if (!rx::IsUnsignedMultiplicationSafe(widthSize, heightSize) ||
- !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize, depthSize) ||
- !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize * depthSize, pixelBytes))
+ if (width > 0 && height > 0 && depth > 0 && pixels == nullptr &&
+ context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack) == nullptr)
{
- // Overflow past the end of the buffer
- context->recordError(Error(GL_INVALID_OPERATION));
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), PixelDataNull);
return false;
}
+ }
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
- size_t copyBytes = formatInfo.computeBlockSize(type, width, height);
- size_t offset = reinterpret_cast<size_t>(pixels);
-
- if (!rx::IsUnsignedAdditionSafe(offset, copyBytes) ||
- ((offset + copyBytes) > static_cast<size_t>(pixelUnpackBuffer->getSize())))
- {
- // Overflow past the end of the buffer
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
+ GLenum sizeCheckFormat = isSubImage ? format : internalformat;
+ if (!ValidImageDataSize(context, target, width, height, depth, sizeCheckFormat, type, pixels,
+ imageSize))
+ {
+ return false;
+ }
- // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
+ // Check for pixel unpack buffer related API errors
+ gl::Buffer *pixelUnpackBuffer =
+ context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
+ if (pixelUnpackBuffer != nullptr)
+ {
+ // ...data is not evenly divisible into the number of bytes needed to store in memory a
+ // datum
// indicated by type.
if (!isCompressed)
{
+ size_t offset = reinterpret_cast<size_t>(pixels);
size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
if ((offset % dataBytesPerPixel) != 0)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation()
+ << "Reads would overflow the pixel unpack buffer.");
return false;
}
}
@@ -503,7 +468,7 @@ bool ValidateES3TexImageParametersBase(Context *context,
// ...the buffer object's data store is currently mapped.
if (pixelUnpackBuffer->isMapped())
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation() << "Pixel unpack buffer is mapped.");
return false;
}
}
@@ -526,17 +491,18 @@ bool ValidateES3TexImage2DParameters(Context *context,
GLint border,
GLenum format,
GLenum type,
- const GLvoid *pixels)
+ GLsizei imageSize,
+ const void *pixels)
{
if (!ValidTexture2DDestinationTarget(context, target))
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return false;
}
return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
isSubImage, xoffset, yoffset, zoffset, width, height,
- depth, border, format, type, pixels);
+ depth, border, format, type, imageSize, pixels);
}
bool ValidateES3TexImage3DParameters(Context *context,
@@ -554,301 +520,260 @@ bool ValidateES3TexImage3DParameters(Context *context,
GLint border,
GLenum format,
GLenum type,
- const GLvoid *pixels)
+ GLsizei bufSize,
+ const void *pixels)
{
if (!ValidTexture3DDestinationTarget(context, target))
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return false;
}
return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
isSubImage, xoffset, yoffset, zoffset, width, height,
- depth, border, format, type, pixels);
+ depth, border, format, type, bufSize, pixels);
}
struct EffectiveInternalFormatInfo
{
- GLenum mEffectiveFormat;
- GLenum mDestFormat;
- GLuint mMinRedBits;
- GLuint mMaxRedBits;
- GLuint mMinGreenBits;
- GLuint mMaxGreenBits;
- GLuint mMinBlueBits;
- GLuint mMaxBlueBits;
- GLuint mMinAlphaBits;
- GLuint mMaxAlphaBits;
-
- EffectiveInternalFormatInfo(GLenum effectiveFormat, GLenum destFormat, GLuint minRedBits, GLuint maxRedBits,
- GLuint minGreenBits, GLuint maxGreenBits, GLuint minBlueBits, GLuint maxBlueBits,
- GLuint minAlphaBits, GLuint maxAlphaBits)
- : mEffectiveFormat(effectiveFormat), mDestFormat(destFormat), mMinRedBits(minRedBits),
- mMaxRedBits(maxRedBits), mMinGreenBits(minGreenBits), mMaxGreenBits(maxGreenBits),
- mMinBlueBits(minBlueBits), mMaxBlueBits(maxBlueBits), mMinAlphaBits(minAlphaBits),
- mMaxAlphaBits(maxAlphaBits) {};
+ GLenum effectiveFormat;
+ GLenum destFormat;
+ GLuint minRedBits;
+ GLuint maxRedBits;
+ GLuint minGreenBits;
+ GLuint maxGreenBits;
+ GLuint minBlueBits;
+ GLuint maxBlueBits;
+ GLuint minAlphaBits;
+ GLuint maxAlphaBits;
};
-typedef std::vector<EffectiveInternalFormatInfo> EffectiveInternalFormatList;
-
-static EffectiveInternalFormatList BuildSizedEffectiveInternalFormatList()
+static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
+ GLenum targetFormat,
+ const EffectiveInternalFormatInfo *list,
+ size_t size,
+ GLenum *outEffectiveFormat)
{
- EffectiveInternalFormatList list;
-
- // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
- // linear source buffer component sizes.
- // | Source channel min/max sizes |
- // Effective Internal Format | N/A | R | G | B | A |
- list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8));
- list.push_back(EffectiveInternalFormatInfo(GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0));
- list.push_back(EffectiveInternalFormatInfo(GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0));
- list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0));
- list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0));
- list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4));
- list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1));
- list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8));
- list.push_back(EffectiveInternalFormatInfo(GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2));
+ for (size_t curFormat = 0; curFormat < size; ++curFormat)
+ {
+ const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
+ if ((formatInfo.destFormat == targetFormat) &&
+ (formatInfo.minRedBits <= srcFormat.redBits &&
+ formatInfo.maxRedBits >= srcFormat.redBits) &&
+ (formatInfo.minGreenBits <= srcFormat.greenBits &&
+ formatInfo.maxGreenBits >= srcFormat.greenBits) &&
+ (formatInfo.minBlueBits <= srcFormat.blueBits &&
+ formatInfo.maxBlueBits >= srcFormat.blueBits) &&
+ (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
+ formatInfo.maxAlphaBits >= srcFormat.alphaBits))
+ {
+ *outEffectiveFormat = formatInfo.effectiveFormat;
+ return true;
+ }
+ }
- return list;
+ *outEffectiveFormat = GL_NONE;
+ return false;
}
-static EffectiveInternalFormatList BuildUnsizedEffectiveInternalFormatList()
+bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
+ GLenum *outEffectiveFormat)
{
- EffectiveInternalFormatList list;
-
- // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and
- // linear source buffer component sizes.
- // | Source channel min/max sizes |
- // Effective Internal Format | Dest Format | R | G | B | A |
- list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_ALPHA, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
- list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX));
- list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 1, 8));
- list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, UINT_MAX));
- list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, UINT_MAX));
- list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4));
- list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1));
- list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8));
+ // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
+ // Effective internal format coresponding to destination internal format and linear source
+ // buffer component sizes.
+ // | Source channel min/max sizes |
+ // Effective Internal Format | N/A | R | G | B | A |
+ // clang-format off
+ constexpr EffectiveInternalFormatInfo list[] = {
+ { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
+ { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
+ { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
+ { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
+ { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
+ { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
+ { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
+ { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
+ { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
+ };
+ // clang-format on
+
+ return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
+}
- return list;
+bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
+ const InternalFormat &destFormat,
+ GLenum *outEffectiveFormat)
+{
+ constexpr GLuint umax = UINT_MAX;
+
+ // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
+ // Effective internal format coresponding to destination internal format andlinear source buffer
+ // component sizes.
+ // | Source channel min/max sizes |
+ // Effective Internal Format | Dest Format | R | G | B | A |
+ // clang-format off
+ constexpr EffectiveInternalFormatInfo list[] = {
+ { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
+ { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
+ { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
+ { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
+ { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
+ { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
+ { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
+ { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
+ };
+ // clang-format on
+
+ return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
+ outEffectiveFormat);
}
-static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat,
+static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
+ const InternalFormat &destFormat,
GLenum *outEffectiveFormat)
{
- const EffectiveInternalFormatList *list = NULL;
- GLenum targetFormat = GL_NONE;
-
- if (destFormat.pixelBytes > 0)
+ if (destFormat.sized)
{
- static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList();
- list = &sizedList;
+ return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
}
else
{
- static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList();
- list = &unsizedList;
- targetFormat = destFormat.format;
- }
-
- for (size_t curFormat = 0; curFormat < list->size(); ++curFormat)
- {
- const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat);
- if ((formatInfo.mDestFormat == targetFormat) &&
- (formatInfo.mMinRedBits <= srcFormat.redBits && formatInfo.mMaxRedBits >= srcFormat.redBits) &&
- (formatInfo.mMinGreenBits <= srcFormat.greenBits && formatInfo.mMaxGreenBits >= srcFormat.greenBits) &&
- (formatInfo.mMinBlueBits <= srcFormat.blueBits && formatInfo.mMaxBlueBits >= srcFormat.blueBits) &&
- (formatInfo.mMinAlphaBits <= srcFormat.alphaBits && formatInfo.mMaxAlphaBits >= srcFormat.alphaBits))
- {
- *outEffectiveFormat = formatInfo.mEffectiveFormat;
- return true;
- }
+ return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
}
+}
- return false;
+static bool EqualOrFirstZero(GLuint first, GLuint second)
+{
+ return first == 0 || first == second;
}
-struct CopyConversion
+static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
+ const InternalFormat &framebufferFormatInfo,
+ GLuint readBufferHandle)
{
- GLenum mTextureFormat;
- GLenum mFramebufferFormat;
+ if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
+ {
+ return false;
+ }
- CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
- : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { }
+ // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
+ // must both be signed, unsigned, or fixed point and both source and destinations
+ // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
+ // conversion between fixed and floating point.
- bool operator<(const CopyConversion& other) const
+ if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
+ (framebufferFormatInfo.colorEncoding == GL_SRGB))
{
- return memcmp(this, &other, sizeof(CopyConversion)) < 0;
+ return false;
}
-};
-typedef std::set<CopyConversion> CopyConversionSet;
-
-static CopyConversionSet BuildValidES3CopyTexImageCombinations()
-{
- CopyConversionSet set;
-
- // From ES 3.0.1 spec, table 3.15
- set.insert(CopyConversion(GL_ALPHA, GL_RGBA));
- set.insert(CopyConversion(GL_LUMINANCE, GL_RED));
- set.insert(CopyConversion(GL_LUMINANCE, GL_RG));
- set.insert(CopyConversion(GL_LUMINANCE, GL_RGB));
- set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA));
- set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA));
- set.insert(CopyConversion(GL_RED, GL_RED));
- set.insert(CopyConversion(GL_RED, GL_RG));
- set.insert(CopyConversion(GL_RED, GL_RGB));
- set.insert(CopyConversion(GL_RED, GL_RGBA));
- set.insert(CopyConversion(GL_RG, GL_RG));
- set.insert(CopyConversion(GL_RG, GL_RGB));
- set.insert(CopyConversion(GL_RG, GL_RGBA));
- set.insert(CopyConversion(GL_RGB, GL_RGB));
- set.insert(CopyConversion(GL_RGB, GL_RGBA));
- set.insert(CopyConversion(GL_RGBA, GL_RGBA));
-
- // Necessary for ANGLE back-buffers
- set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT));
- set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT));
- set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT));
- set.insert(CopyConversion(GL_RED, GL_BGRA_EXT));
- set.insert(CopyConversion(GL_RG, GL_BGRA_EXT));
- set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT));
- set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT));
-
- set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER));
- set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER));
- set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER));
- set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER));
- set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER));
- set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER));
- set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER));
- set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER));
- set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER));
- set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER));
-
- return set;
-}
-
-static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle)
-{
- const InternalFormat &textureInternalFormatInfo = GetInternalFormatInfo(textureInternalFormat);
- const InternalFormat &framebufferInternalFormatInfo = GetInternalFormatInfo(frameBufferInternalFormat);
-
- static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
- if (conversionSet.find(CopyConversion(textureInternalFormatInfo.format, framebufferInternalFormatInfo.format)) != conversionSet.end())
- {
- // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
- // must both be signed, unsigned, or fixed point and both source and destinations
- // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
- // conversion between fixed and floating point.
-
- if ((textureInternalFormatInfo.colorEncoding == GL_SRGB) != (framebufferInternalFormatInfo.colorEncoding == GL_SRGB))
- {
- return false;
- }
+ if (((textureFormatInfo.componentType == GL_INT) !=
+ (framebufferFormatInfo.componentType == GL_INT)) ||
+ ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
+ (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
+ {
+ return false;
+ }
+
+ if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
+ textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
+ textureFormatInfo.componentType == GL_FLOAT) &&
+ !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
+ framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
+ framebufferFormatInfo.componentType == GL_FLOAT))
+ {
+ return false;
+ }
- if (((textureInternalFormatInfo.componentType == GL_INT) != (framebufferInternalFormatInfo.componentType == GL_INT )) ||
- ((textureInternalFormatInfo.componentType == GL_UNSIGNED_INT) != (framebufferInternalFormatInfo.componentType == GL_UNSIGNED_INT)))
+ // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
+ // The effective internal format of the source buffer is determined with the following rules
+ // applied in order:
+ // * If the source buffer is a texture or renderbuffer that was created with a sized internal
+ // format then the effective internal format is the source buffer's sized internal format.
+ // * If the source buffer is a texture that was created with an unsized base internal format,
+ // then the effective internal format is the source image array's effective internal
+ // format, as specified by table 3.12, which is determined from the <format> and <type>
+ // that were used when the source image array was specified by TexImage*.
+ // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
+ // where Destination Internal Format matches internalformat and where the [source channel
+ // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
+ // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
+ // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
+ const InternalFormat *sourceEffectiveFormat = nullptr;
+ if (readBufferHandle != 0)
+ {
+ // Not the default framebuffer, therefore the read buffer must be a user-created texture or
+ // renderbuffer
+ if (framebufferFormatInfo.sized)
{
- return false;
+ sourceEffectiveFormat = &framebufferFormatInfo;
}
-
- if ((textureInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
- textureInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
- textureInternalFormatInfo.componentType == GL_FLOAT) &&
- !(framebufferInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
- framebufferInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
- framebufferInternalFormatInfo.componentType == GL_FLOAT))
+ else
{
- return false;
+ // Renderbuffers cannot be created with an unsized internal format, so this must be an
+ // unsized-format texture. We can use the same table we use when creating textures to
+ // get its effective sized format.
+ sourceEffectiveFormat =
+ &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
}
-
- // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
- // The effective internal format of the source buffer is determined with the following rules applied in order:
- // * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the
- // effective internal format is the source buffer's sized internal format.
- // * If the source buffer is a texture that was created with an unsized base internal format, then the
- // effective internal format is the source image array's effective internal format, as specified by table
- // 3.12, which is determined from the <format> and <type> that were used when the source image array was
- // specified by TexImage*.
- // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where
- // Destination Internal Format matches internalformat and where the [source channel sizes] are consistent
- // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the
- // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING
- // is SRGB.
- InternalFormat sourceEffectiveFormat;
- if (readBufferHandle != 0)
+ }
+ else
+ {
+ // The effective internal format must be derived from the source framebuffer's channel
+ // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
+ if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
{
- // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
- if (framebufferInternalFormatInfo.pixelBytes > 0)
+ GLenum effectiveFormat;
+ if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
+ &effectiveFormat))
{
- sourceEffectiveFormat = framebufferInternalFormatInfo;
+ sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
}
else
{
- // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
- // texture. We can use the same table we use when creating textures to get its effective sized format.
- GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferInternalFormatInfo.format, framebufferInternalFormatInfo.type);
- sourceEffectiveFormat = GetInternalFormatInfo(sizedInternalFormat);
+ return false;
}
}
- else
+ else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
{
- // The effective internal format must be derived from the source framebuffer's channel sizes.
- // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
- if (framebufferInternalFormatInfo.colorEncoding == GL_LINEAR)
- {
- GLenum effectiveFormat;
- if (GetEffectiveInternalFormat(framebufferInternalFormatInfo, textureInternalFormatInfo, &effectiveFormat))
- {
- sourceEffectiveFormat = GetInternalFormatInfo(effectiveFormat);
- }
- else
- {
- return false;
- }
- }
- else if (framebufferInternalFormatInfo.colorEncoding == GL_SRGB)
+ // SRGB buffers can only be copied to sized format destinations according to table 3.18
+ if (textureFormatInfo.sized &&
+ (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
+ (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
+ (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
+ (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
{
- // SRGB buffers can only be copied to sized format destinations according to table 3.18
- if ((textureInternalFormatInfo.pixelBytes > 0) &&
- (framebufferInternalFormatInfo.redBits >= 1 && framebufferInternalFormatInfo.redBits <= 8) &&
- (framebufferInternalFormatInfo.greenBits >= 1 && framebufferInternalFormatInfo.greenBits <= 8) &&
- (framebufferInternalFormatInfo.blueBits >= 1 && framebufferInternalFormatInfo.blueBits <= 8) &&
- (framebufferInternalFormatInfo.alphaBits >= 1 && framebufferInternalFormatInfo.alphaBits <= 8))
- {
- sourceEffectiveFormat = GetInternalFormatInfo(GL_SRGB8_ALPHA8);
- }
- else
- {
- return false;
- }
+ sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
}
else
{
- UNREACHABLE();
return false;
}
}
-
- if (textureInternalFormatInfo.pixelBytes > 0)
+ else
{
- // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is sized,
- // component sizes of the source and destination formats must exactly match
- if (textureInternalFormatInfo.redBits != sourceEffectiveFormat.redBits ||
- textureInternalFormatInfo.greenBits != sourceEffectiveFormat.greenBits ||
- textureInternalFormatInfo.blueBits != sourceEffectiveFormat.blueBits ||
- textureInternalFormatInfo.alphaBits != sourceEffectiveFormat.alphaBits)
- {
- return false;
- }
+ UNREACHABLE();
+ return false;
}
+ }
-
- return true; // A conversion function exists, and no rule in the specification has precluded conversion
- // between these formats.
+ if (textureFormatInfo.sized)
+ {
+ // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
+ // sized, component sizes of the source and destination formats must exactly match if the
+ // destination format exists.
+ if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
+ !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
+ !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
+ !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
+ {
+ return false;
+ }
}
- return false;
+ return true; // A conversion function exists, and no rule in the specification has precluded
+ // conversion between these formats.
}
bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
@@ -865,48 +790,50 @@ bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
GLsizei height,
GLint border)
{
- GLenum textureInternalFormat;
+ Format textureFormat = Format::Invalid();
if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
- xoffset, yoffset, zoffset, x, y, width, height,
- border, &textureInternalFormat))
+ xoffset, yoffset, zoffset, x, y, width, height, border,
+ &textureFormat))
{
return false;
}
+ ASSERT(textureFormat.valid() || !isSubImage);
- const auto &state = context->getState();
- const gl::Framebuffer *framebuffer = state.getReadFramebuffer();
- GLuint readFramebufferID = framebuffer->id();
+ const auto &state = context->getGLState();
+ gl::Framebuffer *framebuffer = state.getReadFramebuffer();
+ GLuint readFramebufferID = framebuffer->id();
- if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
+ if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
{
- context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ context->handleError(InvalidFramebufferOperation());
return false;
}
- if (readFramebufferID != 0 && framebuffer->getSamples(context->getData()) != 0)
+ if (readFramebufferID != 0 && framebuffer->getSamples(context) != 0)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
- const gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer();
- GLenum colorbufferInternalFormat = source->getInternalFormat();
+ const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
if (isSubImage)
{
- if (!IsValidES3CopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat,
+ if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
readFramebufferID))
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
}
else
{
- if (!gl::IsValidES3CopyTexImageCombination(internalformat, colorbufferInternalFormat,
- readFramebufferID))
+ // Use format/type from the source FBO. (Might not be perfect for all cases?)
+ const InternalFormat &framebufferFormat = *source->getFormat().info;
+ const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
+ if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
}
@@ -931,7 +858,7 @@ bool ValidateES3CopyTexImage2DParameters(ValidationContext *context,
{
if (!ValidTexture2DDestinationTarget(context, target))
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return false;
}
@@ -956,7 +883,7 @@ bool ValidateES3CopyTexImage3DParameters(ValidationContext *context,
{
if (!ValidTexture3DDestinationTarget(context, target))
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return false;
}
@@ -975,7 +902,7 @@ bool ValidateES3TexStorageParametersBase(Context *context,
{
if (width < 1 || height < 1 || depth < 1 || levels < 1)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
@@ -987,7 +914,7 @@ bool ValidateES3TexStorageParametersBase(Context *context,
if (levels > gl::log2(maxDim) + 1)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
@@ -995,85 +922,102 @@ bool ValidateES3TexStorageParametersBase(Context *context,
switch (target)
{
- case GL_TEXTURE_2D:
+ case GL_TEXTURE_2D:
{
if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
static_cast<GLuint>(height) > caps.max2DTextureSize)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
}
break;
- case GL_TEXTURE_CUBE_MAP:
+ case GL_TEXTURE_RECTANGLE_ANGLE:
+ {
+ if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
+ static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+ }
+ break;
+
+ case GL_TEXTURE_CUBE_MAP:
{
if (width != height)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
}
break;
- case GL_TEXTURE_3D:
+ case GL_TEXTURE_3D:
{
if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
static_cast<GLuint>(height) > caps.max3DTextureSize ||
static_cast<GLuint>(depth) > caps.max3DTextureSize)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
}
break;
- case GL_TEXTURE_2D_ARRAY:
+ case GL_TEXTURE_2D_ARRAY:
{
if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
static_cast<GLuint>(height) > caps.max2DTextureSize ||
static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
}
break;
- default:
- UNREACHABLE();
- return false;
+ default:
+ UNREACHABLE();
+ return false;
}
gl::Texture *texture = context->getTargetTexture(target);
if (!texture || texture->id() == 0)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
if (texture->getImmutableFormat())
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return false;
}
- if (formatInfo.pixelBytes == 0)
+ if (!formatInfo.sized)
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
+ return false;
+ }
+
+ if (formatInfo.compressed && target == GL_TEXTURE_RECTANGLE_ANGLE)
+ {
+ context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
return false;
}
@@ -1090,7 +1034,7 @@ bool ValidateES3TexStorage2DParameters(Context *context,
{
if (!ValidTexture2DTarget(context, target))
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return false;
}
@@ -1108,7 +1052,7 @@ bool ValidateES3TexStorage3DParameters(Context *context,
{
if (!ValidTexture3DTarget(context, target))
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return false;
}
@@ -1116,33 +1060,11 @@ bool ValidateES3TexStorage3DParameters(Context *context,
height, depth);
}
-bool ValidateGenQueries(gl::Context *context, GLsizei n, const GLuint *ids)
-{
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
- return false;
- }
-
- return ValidateGenQueriesBase(context, n, ids);
-}
-
-bool ValidateDeleteQueries(gl::Context *context, GLsizei n, const GLuint *ids)
-{
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
- return false;
- }
-
- return ValidateDeleteQueriesBase(context, n, ids);
-}
-
bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
{
- if (context->getClientVersion() < 3)
+ if (context->getClientMajorVersion() < 3)
{
- context->recordError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
return false;
}
@@ -1151,9 +1073,9 @@ bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
bool ValidateEndQuery(gl::Context *context, GLenum target)
{
- if (context->getClientVersion() < 3)
+ if (context->getClientMajorVersion() < 3)
{
- context->recordError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
return false;
}
@@ -1162,38 +1084,36 @@ bool ValidateEndQuery(gl::Context *context, GLenum target)
bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params)
{
- if (context->getClientVersion() < 3)
+ if (context->getClientMajorVersion() < 3)
{
- context->recordError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
return false;
}
- return ValidateGetQueryivBase(context, target, pname);
+ return ValidateGetQueryivBase(context, target, pname, nullptr);
}
bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
{
- if (context->getClientVersion() < 3)
+ if (context->getClientMajorVersion() < 3)
{
- context->recordError(Error(GL_INVALID_OPERATION, "GLES version < 3.0"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
return false;
}
- return ValidateGetQueryObjectValueBase(context, id, pname);
+ return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
}
-bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
- GLuint texture, GLint level, GLint layer)
+bool ValidateFramebufferTextureLayer(Context *context,
+ GLenum target,
+ GLenum attachment,
+ GLuint texture,
+ GLint level,
+ GLint layer)
{
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
-
- if (layer < 0)
+ if (context->getClientMajorVersion() < 3)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
return false;
}
@@ -1205,52 +1125,58 @@ bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum att
const gl::Caps &caps = context->getCaps();
if (texture != 0)
{
+ if (layer < 0)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+
gl::Texture *tex = context->getTexture(texture);
ASSERT(tex);
switch (tex->getTarget())
{
- case GL_TEXTURE_2D_ARRAY:
+ case GL_TEXTURE_2D_ARRAY:
{
if (level > gl::log2(caps.max2DTextureSize))
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
}
break;
- case GL_TEXTURE_3D:
+ case GL_TEXTURE_3D:
{
if (level > gl::log2(caps.max3DTextureSize))
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
}
break;
- default:
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
+ default:
+ context->handleError(InvalidOperation());
+ return false;
}
- const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(tex->getInternalFormat(tex->getTarget(), level));
- if (internalFormatInfo.compressed)
+ const auto &format = tex->getFormat(tex->getTarget(), level);
+ if (format.info->compressed)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return false;
}
}
@@ -1258,161 +1184,114 @@ bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum att
return true;
}
-bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum format, GLenum type)
+bool ValidateInvalidateFramebuffer(Context *context,
+ GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments)
{
- const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
- switch (format)
+ bool defaultFramebuffer = false;
+
+ switch (target)
{
- case GL_RGBA:
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- break;
- case GL_UNSIGNED_INT_2_10_10_10_REV:
- if (internalFormat != GL_RGB10_A2)
- {
- return false;
- }
- break;
- case GL_FLOAT:
- if (internalFormatInfo.componentType != GL_FLOAT)
- {
- return false;
- }
- break;
- default:
- return false;
- }
- break;
- case GL_RGBA_INTEGER:
- switch (type)
- {
- case GL_INT:
- if (internalFormatInfo.componentType != GL_INT)
- {
- return false;
- }
+ case GL_DRAW_FRAMEBUFFER:
+ case GL_FRAMEBUFFER:
+ defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
break;
- case GL_UNSIGNED_INT:
- if (internalFormatInfo.componentType != GL_UNSIGNED_INT)
- {
- return false;
- }
- break;
- default:
- return false;
- }
- break;
- case GL_BGRA_EXT:
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
- case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
- break;
- default:
- return false;
- }
- break;
- case GL_RG_EXT:
- case GL_RED_EXT:
- if (!context->getExtensions().textureRG)
- {
- return false;
- }
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
+ case GL_READ_FRAMEBUFFER:
+ defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
break;
default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
return false;
- }
- break;
- default:
- return false;
}
- return true;
+
+ return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
+ defaultFramebuffer);
}
-bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
- GLenum internalformat, GLsizei width, GLsizei height)
+bool ValidateInvalidateSubFramebuffer(Context *context,
+ GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
{
- if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height))
- {
- return false;
- }
+ return ValidateInvalidateFramebuffer(context, target, numAttachments, attachments);
+}
- //The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer format if samples is greater than zero.
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
- if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
+bool ValidateClearBuffer(ValidationContext *context)
+{
+ if (context->getClientMajorVersion() < 3)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
return false;
}
- // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
- const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
- if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
+ if (context->getGLState().getDrawFramebuffer()->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidFramebufferOperation());
return false;
}
return true;
}
-bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
- const GLenum *attachments)
+bool ValidateDrawRangeElements(Context *context,
+ GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const void *indices)
{
- if (context->getClientVersion() < 3)
+ if (context->getClientMajorVersion() < 3)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above"));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
return false;
}
- bool defaultFramebuffer = false;
-
- switch (target)
+ if (end < start)
{
- case GL_DRAW_FRAMEBUFFER:
- case GL_FRAMEBUFFER:
- defaultFramebuffer = context->getState().getDrawFramebuffer()->id() == 0;
- break;
- case GL_READ_FRAMEBUFFER:
- defaultFramebuffer = context->getState().getReadFramebuffer()->id() == 0;
- break;
- default:
- context->recordError(Error(GL_INVALID_ENUM, "Invalid framebuffer target"));
+ context->handleError(InvalidValue() << "end < start");
return false;
}
- return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer);
-}
-
-bool ValidateClearBuffer(ValidationContext *context)
-{
- if (context->getClientVersion() < 3)
+ if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
{
- context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
- const gl::Framebuffer *fbo = context->getState().getDrawFramebuffer();
- if (!fbo || fbo->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
+ // Use the parameter buffer to retrieve and cache the index range.
+ const auto &params = context->getParams<HasIndexRange>();
+ const auto &indexRangeOpt = params.getIndexRange();
+ if (!indexRangeOpt.valid())
{
- context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ // Unexpected error.
return false;
}
+ if (indexRangeOpt.value().end > end || indexRangeOpt.value().start < start)
+ {
+ // GL spec says that behavior in this case is undefined - generating an error is fine.
+ context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
+ return false;
+ }
return true;
}
-bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params)
+bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
{
- if (context->getClientVersion() < 3)
+ if (context->getClientMajorVersion() < 3)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
return false;
}
@@ -1421,17 +1300,17 @@ bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLu
bool ValidateReadBuffer(Context *context, GLenum src)
{
- if (context->getClientVersion() < 3)
+ if (context->getClientMajorVersion() < 3)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
return false;
}
- Framebuffer *readFBO = context->getState().getReadFramebuffer();
+ const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
if (readFBO == nullptr)
{
- context->recordError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
+ context->handleError(InvalidOperation() << "No active read framebuffer.");
return false;
}
@@ -1440,9 +1319,9 @@ bool ValidateReadBuffer(Context *context, GLenum src)
return true;
}
- if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT15))
+ if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
{
- context->recordError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
+ context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
return false;
}
@@ -1450,8 +1329,9 @@ bool ValidateReadBuffer(Context *context, GLenum src)
{
if (src != GL_BACK)
{
- const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
- context->recordError(gl::Error(GL_INVALID_OPERATION, errorMsg));
+ context->handleError(
+ InvalidOperation()
+ << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
return false;
}
}
@@ -1461,8 +1341,7 @@ bool ValidateReadBuffer(Context *context, GLenum src)
if (drawBuffer >= context->getCaps().maxDrawBuffers)
{
- const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
- context->recordError(gl::Error(GL_INVALID_OPERATION, errorMsg));
+ context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
return false;
}
}
@@ -1479,34 +1358,57 @@ bool ValidateCompressedTexImage3D(Context *context,
GLsizei depth,
GLint border,
GLsizei imageSize,
- const GLvoid *data)
+ const void *data)
{
- if (context->getClientVersion() < 3)
+ if (context->getClientMajorVersion() < 3)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
return false;
}
- const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
- if (imageSize < 0 ||
- static_cast<GLuint>(imageSize) !=
- formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
+ if (!ValidTextureTarget(context, target))
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidEnum());
+ return false;
+ }
+
+ // Validate image size
+ if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+
+ const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
+ if (!formatInfo.compressed)
+ {
+ context->handleError(InvalidEnum() << "Not a valid compressed texture format");
+ return false;
+ }
+
+ auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
+ if (blockSizeOrErr.isError())
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+ if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
+ {
+ context->handleError(InvalidValue());
return false;
}
// 3D texture target validation
if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY)
{
- context->recordError(
- Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target"));
+ context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
return false;
}
// validateES3TexImageFormat sets the error code if there is an error
if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
- 0, width, height, depth, border, GL_NONE, GL_NONE, data))
+ 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
+ data))
{
return false;
}
@@ -1514,59 +1416,207 @@ bool ValidateCompressedTexImage3D(Context *context,
return true;
}
-bool ValidateBindVertexArray(Context *context, GLuint array)
+bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const void *data)
{
- if (context->getClientVersion() < 3)
+ if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
{
- context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
- return ValidateBindVertexArrayBase(context, array);
+ return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
+ depth, border, imageSize, data);
}
-bool ValidateDeleteVertexArrays(Context *context, GLsizei n)
+bool ValidateBindVertexArray(Context *context, GLuint array)
{
- if (context->getClientVersion() < 3)
+ if (context->getClientMajorVersion() < 3)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
return false;
}
- return ValidateDeleteVertexArraysBase(context, n);
+ return ValidateBindVertexArrayBase(context, array);
}
-bool ValidateGenVertexArrays(Context *context, GLsizei n)
+bool ValidateIsVertexArray(Context *context, GLuint array)
{
- if (context->getClientVersion() < 3)
+ if (context->getClientMajorVersion() < 3)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
return false;
}
- return ValidateGenVertexArraysBase(context, n);
+ return true;
}
-bool ValidateIsVertexArray(Context *context)
+static bool ValidateBindBufferCommon(Context *context,
+ BufferBinding target,
+ GLuint index,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizeiptr size)
{
- if (context->getClientVersion() < 3)
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if (buffer != 0 && offset < 0)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
return false;
}
+ if (!context->getGLState().isBindGeneratesResourceEnabled() &&
+ !context->isBufferGenerated(buffer))
+ {
+ context->handleError(InvalidOperation() << "Buffer was not generated.");
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ switch (target)
+ {
+ case BufferBinding::TransformFeedback:
+ {
+ if (index >= caps.maxTransformFeedbackSeparateAttributes)
+ {
+ context->handleError(InvalidValue() << "index is greater than or equal to the "
+ "number of TRANSFORM_FEEDBACK_BUFFER "
+ "indexed binding points.");
+ return false;
+ }
+ if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
+ {
+ context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
+ return false;
+ }
+
+ TransformFeedback *curTransformFeedback =
+ context->getGLState().getCurrentTransformFeedback();
+ if (curTransformFeedback && curTransformFeedback->isActive())
+ {
+ context->handleError(InvalidOperation()
+ << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
+ "feedback is currently active.");
+ return false;
+ }
+ break;
+ }
+ case BufferBinding::Uniform:
+ {
+ if (index >= caps.maxUniformBufferBindings)
+ {
+ context->handleError(InvalidValue() << "index is greater than or equal to the "
+ "number of UNIFORM_BUFFER indexed "
+ "binding points.");
+ return false;
+ }
+
+ if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
+ {
+ context->handleError(
+ InvalidValue()
+ << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
+ return false;
+ }
+ break;
+ }
+ case BufferBinding::AtomicCounter:
+ {
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->handleError(InvalidEnum()
+ << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
+ return false;
+ }
+ if (index >= caps.maxAtomicCounterBufferBindings)
+ {
+ context->handleError(InvalidValue() << "index is greater than or equal to the "
+ "number of ATOMIC_COUNTER_BUFFER "
+ "indexed binding points.");
+ return false;
+ }
+ if (buffer != 0 && (offset % 4) != 0)
+ {
+ context->handleError(InvalidValue() << "offset must be a multiple of 4.");
+ return false;
+ }
+ break;
+ }
+ case BufferBinding::ShaderStorage:
+ {
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->handleError(InvalidEnum()
+ << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
+ return false;
+ }
+ if (index >= caps.maxShaderStorageBufferBindings)
+ {
+ context->handleError(InvalidValue() << "index is greater than or equal to the "
+ "number of SHADER_STORAGE_BUFFER "
+ "indexed binding points.");
+ return false;
+ }
+ if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
+ {
+ context->handleError(InvalidValue() << "offset must be multiple of value of "
+ "SHADER_STORAGE_BUFFER_OFFSET_"
+ "ALIGNMENT.");
+ return false;
+ }
+ break;
+ }
+ default:
+ context->handleError(InvalidEnum() << "the target is not supported.");
+ return false;
+ }
+
return true;
}
+bool ValidateBindBufferBase(Context *context, BufferBinding target, GLuint index, GLuint buffer)
+{
+ return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
+}
+
+bool ValidateBindBufferRange(Context *context,
+ BufferBinding target,
+ GLuint index,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizeiptr size)
+{
+ if (buffer != 0 && size <= 0)
+ {
+ context->handleError(InvalidValue()
+ << "buffer is non-zero and size is less than or equal to zero.");
+ return false;
+ }
+ return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
+}
+
bool ValidateProgramBinary(Context *context,
GLuint program,
GLenum binaryFormat,
const void *binary,
GLint length)
{
- if (context->getClientVersion() < 3)
+ if (context->getClientMajorVersion() < 3)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
return false;
}
@@ -1580,20 +1630,20 @@ bool ValidateGetProgramBinary(Context *context,
GLenum *binaryFormat,
void *binary)
{
- if (context->getClientVersion() < 3)
+ if (context->getClientMajorVersion() < 3)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
return false;
}
return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
}
-bool ValidateProgramParameter(Context *context, GLuint program, GLenum pname, GLint value)
+bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
{
- if (context->getClientVersion() < 3)
+ if (context->getClientMajorVersion() < 3)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
return false;
}
@@ -1605,10 +1655,33 @@ bool ValidateProgramParameter(Context *context, GLuint program, GLenum pname, GL
switch (pname)
{
case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
+ if (value != GL_FALSE && value != GL_TRUE)
+ {
+ context->handleError(InvalidValue()
+ << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
+ return false;
+ }
+ break;
+
+ case GL_PROGRAM_SEPARABLE:
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->handleError(InvalidEnum()
+ << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
+ return false;
+ }
+
+ if (value != GL_FALSE && value != GL_TRUE)
+ {
+ context->handleError(InvalidValue()
+ << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
+ return false;
+ }
break;
default:
- context->recordError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
+ context->handleError(InvalidEnum()
+ << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
return false;
}
@@ -1627,9 +1700,9 @@ bool ValidateBlitFramebuffer(Context *context,
GLbitfield mask,
GLenum filter)
{
- if (context->getClientVersion() < 3)
+ if (context->getClientMajorVersion() < 3)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
return false;
}
@@ -1648,21 +1721,30 @@ bool ValidateClearBufferiv(ValidationContext *context,
if (drawbuffer < 0 ||
static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
+ if (context->getExtensions().webglCompatibility)
+ {
+ constexpr GLenum validComponentTypes[] = {GL_INT};
+ if (!ValidateWebGLFramebufferAttachmentClearType(
+ context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
+ {
+ return false;
+ }
+ }
break;
case GL_STENCIL:
if (drawbuffer != 0)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
break;
default:
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return false;
}
@@ -1680,13 +1762,22 @@ bool ValidateClearBufferuiv(ValidationContext *context,
if (drawbuffer < 0 ||
static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
+ if (context->getExtensions().webglCompatibility)
+ {
+ constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
+ if (!ValidateWebGLFramebufferAttachmentClearType(
+ context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
+ {
+ return false;
+ }
+ }
break;
default:
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return false;
}
@@ -1704,21 +1795,31 @@ bool ValidateClearBufferfv(ValidationContext *context,
if (drawbuffer < 0 ||
static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
+ if (context->getExtensions().webglCompatibility)
+ {
+ constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
+ GL_SIGNED_NORMALIZED};
+ if (!ValidateWebGLFramebufferAttachmentClearType(
+ context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
+ {
+ return false;
+ }
+ }
break;
case GL_DEPTH:
if (drawbuffer != 0)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
break;
default:
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return false;
}
@@ -1736,13 +1837,13 @@ bool ValidateClearBufferfi(ValidationContext *context,
case GL_DEPTH_STENCIL:
if (drawbuffer != 0)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return false;
}
break;
default:
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return false;
}
@@ -1751,9 +1852,9 @@ bool ValidateClearBufferfi(ValidationContext *context,
bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs)
{
- if (context->getClientVersion() < 3)
+ if (context->getClientMajorVersion() < 3)
{
- context->recordError(Error(GL_INVALID_OPERATION, "Context does not support GLES3."));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
return false;
}
@@ -1771,9 +1872,9 @@ bool ValidateCopyTexSubImage3D(Context *context,
GLsizei width,
GLsizei height)
{
- if (context->getClientVersion() < 3)
+ if (context->getClientMajorVersion() < 3)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
return false;
}
@@ -1781,4 +1882,1821 @@ bool ValidateCopyTexSubImage3D(Context *context,
yoffset, zoffset, x, y, width, height, 0);
}
+bool ValidateTexImage3D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
+ 0, 0, width, height, depth, border, format, type, -1,
+ pixels);
+}
+
+bool ValidateTexImage3DRobustANGLE(Context *context,
+ GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
+ 0, 0, width, height, depth, border, format, type,
+ bufSize, pixels);
+}
+
+bool ValidateTexSubImage3D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
+ yoffset, zoffset, width, height, depth, 0, format, type,
+ -1, pixels);
+}
+
+bool ValidateTexSubImage3DRobustANGLE(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
+ yoffset, zoffset, width, height, depth, 0, format, type,
+ bufSize, pixels);
+}
+
+bool ValidateCompressedTexSubImage3D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
+ if (!formatInfo.compressed)
+ {
+ context->handleError(InvalidEnum() << "Not a valid compressed texture format");
+ return false;
+ }
+
+ auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
+ if (blockSizeOrErr.isError())
+ {
+ context->handleError(blockSizeOrErr.getError());
+ return false;
+ }
+ if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+
+ if (!data)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+
+ return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, xoffset,
+ yoffset, zoffset, width, height, depth, 0, format,
+ GL_NONE, -1, data);
+}
+bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const void *data)
+{
+ if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
+ {
+ return false;
+ }
+
+ return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
+ height, depth, format, imageSize, data);
+}
+
+bool ValidateGenQueries(Context *context, GLint n, GLuint *)
+{
+ return ValidateGenOrDeleteES3(context, n);
+}
+
+bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
+{
+ return ValidateGenOrDeleteES3(context, n);
+}
+
+bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
+{
+ return ValidateGenOrDeleteCountES3(context, count);
+}
+
+bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
+{
+ return ValidateGenOrDeleteCountES3(context, count);
+}
+
+bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
+{
+ return ValidateGenOrDeleteES3(context, n);
+}
+
+bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
+{
+ if (!ValidateGenOrDeleteES3(context, n))
+ {
+ return false;
+ }
+ for (GLint i = 0; i < n; ++i)
+ {
+ auto *transformFeedback = context->getTransformFeedback(ids[i]);
+ if (transformFeedback != nullptr && transformFeedback->isActive())
+ {
+ // ES 3.0.4 section 2.15.1 page 86
+ context->handleError(InvalidOperation()
+ << "Attempt to delete active transform feedback.");
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
+{
+ return ValidateGenOrDeleteES3(context, n);
+}
+
+bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
+{
+ return ValidateGenOrDeleteES3(context, n);
+}
+
+bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+ switch (primitiveMode)
+ {
+ case GL_TRIANGLES:
+ case GL_LINES:
+ case GL_POINTS:
+ break;
+
+ default:
+ context->handleError(InvalidEnum() << "Invalid primitive mode.");
+ return false;
+ }
+
+ TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
+ ASSERT(transformFeedback != nullptr);
+
+ if (transformFeedback->isActive())
+ {
+ context->handleError(InvalidOperation() << "Transform feedback is already active.");
+ return false;
+ }
+
+ for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
+ {
+ const auto &buffer = transformFeedback->getIndexedBuffer(i);
+ if (buffer.get() && buffer->isMapped())
+ {
+ context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
+ return false;
+ }
+ }
+
+ Program *program = context->getGLState().getProgram();
+
+ if (!program)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
+ return false;
+ }
+
+ if (program->getTransformFeedbackVaryingCount() == 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoTransformFeedbackOutputVariables);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetBufferPointerv(Context *context, BufferBinding target, GLenum pname, void **params)
+{
+ return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
+}
+
+bool ValidateGetBufferPointervRobustANGLE(Context *context,
+ BufferBinding target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ void **params)
+{
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetBufferPointervBase(context, target, pname, length, params))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateUnmapBuffer(Context *context, BufferBinding target)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ return ValidateUnmapBufferBase(context, target);
+}
+
+bool ValidateMapBufferRange(Context *context,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ return ValidateMapBufferRangeBase(context, target, offset, length, access);
+}
+
+bool ValidateFlushMappedBufferRange(Context *context,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
+}
+
+bool ValidateIndexedStateQuery(ValidationContext *context,
+ GLenum pname,
+ GLuint index,
+ GLsizei *length)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ GLenum nativeType;
+ unsigned int numParams;
+ if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
+ {
+ context->handleError(InvalidEnum());
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ switch (pname)
+ {
+ case GL_TRANSFORM_FEEDBACK_BUFFER_START:
+ case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
+ case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ if (index >= caps.maxTransformFeedbackSeparateAttributes)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+ break;
+
+ case GL_UNIFORM_BUFFER_START:
+ case GL_UNIFORM_BUFFER_SIZE:
+ case GL_UNIFORM_BUFFER_BINDING:
+ if (index >= caps.maxUniformBufferBindings)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+ break;
+
+ case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
+ case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
+ if (index >= 3u)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+ break;
+
+ case GL_ATOMIC_COUNTER_BUFFER_START:
+ case GL_ATOMIC_COUNTER_BUFFER_SIZE:
+ case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->handleError(
+ InvalidEnum()
+ << "Atomic Counter buffers are not supported in this version of GL");
+ return false;
+ }
+ if (index >= caps.maxAtomicCounterBufferBindings)
+ {
+ context->handleError(
+ InvalidValue()
+ << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
+ return false;
+ }
+ break;
+
+ case GL_SHADER_STORAGE_BUFFER_START:
+ case GL_SHADER_STORAGE_BUFFER_SIZE:
+ case GL_SHADER_STORAGE_BUFFER_BINDING:
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->handleError(
+ InvalidEnum()
+ << "Shader storage buffers are not supported in this version of GL");
+ return false;
+ }
+ if (index >= caps.maxShaderStorageBufferBindings)
+ {
+ context->handleError(
+ InvalidValue()
+ << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
+ return false;
+ }
+ break;
+
+ case GL_VERTEX_BINDING_BUFFER:
+ case GL_VERTEX_BINDING_DIVISOR:
+ case GL_VERTEX_BINDING_OFFSET:
+ case GL_VERTEX_BINDING_STRIDE:
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->handleError(
+ InvalidEnum()
+ << "Vertex Attrib Bindings are not supported in this version of GL");
+ return false;
+ }
+ if (index >= caps.maxVertexAttribBindings)
+ {
+ context->handleError(
+ InvalidValue()
+ << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
+ return false;
+ }
+ break;
+ case GL_SAMPLE_MASK_VALUE:
+ if (context->getClientVersion() < ES_3_1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
+ return false;
+ }
+ if (index >= caps.maxSampleMaskWords)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
+ return false;
+ }
+ break;
+ default:
+ context->handleError(InvalidEnum());
+ return false;
+ }
+
+ if (length)
+ {
+ *length = 1;
+ }
+
+ return true;
+}
+
+bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data)
+{
+ if (context->getClientVersion() < ES_3_0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+ return ValidateIndexedStateQuery(context, target, index, nullptr);
+}
+
+bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *data)
+{
+ if (context->getClientVersion() < ES_3_0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateIndexedStateQuery(context, target, index, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetInteger64i_v(ValidationContext *context, GLenum target, GLuint index, GLint64 *data)
+{
+ if (context->getClientVersion() < ES_3_0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+ return ValidateIndexedStateQuery(context, target, index, nullptr);
+}
+
+bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *data)
+{
+ if (context->getClientVersion() < ES_3_0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateIndexedStateQuery(context, target, index, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCopyBufferSubData(ValidationContext *context,
+ BufferBinding readTarget,
+ BufferBinding writeTarget,
+ GLintptr readOffset,
+ GLintptr writeOffset,
+ GLsizeiptr size)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if (!ValidBufferType(context, readTarget) || !ValidBufferType(context, writeTarget))
+ {
+ context->handleError(InvalidEnum() << "Invalid buffer target");
+ return false;
+ }
+
+ Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
+ Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
+
+ if (!readBuffer || !writeBuffer)
+ {
+ context->handleError(InvalidOperation() << "No buffer bound to target");
+ return false;
+ }
+
+ // Verify that readBuffer and writeBuffer are not currently mapped
+ if (readBuffer->isMapped() || writeBuffer->isMapped())
+ {
+ context->handleError(InvalidOperation()
+ << "Cannot call CopyBufferSubData on a mapped buffer");
+ return false;
+ }
+
+ CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
+ CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
+ CheckedNumeric<GLintptr> checkedSize(size);
+
+ auto checkedReadSum = checkedReadOffset + checkedSize;
+ auto checkedWriteSum = checkedWriteOffset + checkedSize;
+
+ if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
+ !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
+ !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
+ {
+ context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
+ return false;
+ }
+
+ if (readOffset < 0 || writeOffset < 0 || size < 0)
+ {
+ context->handleError(InvalidValue()
+ << "readOffset, writeOffset and size must all be non-negative");
+ return false;
+ }
+
+ if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
+ checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
+ {
+ context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
+ return false;
+ }
+
+ if (readBuffer == writeBuffer)
+ {
+ auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
+ if (!checkedOffsetDiff.IsValid())
+ {
+ // This shold not be possible.
+ UNREACHABLE();
+ context->handleError(InvalidValue()
+ << "Integer overflow when validating same buffer copy.");
+ return false;
+ }
+
+ if (checkedOffsetDiff.ValueOrDie() < size)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ switch (name)
+ {
+ case GL_EXTENSIONS:
+ if (index >= context->getExtensionStringCount())
+ {
+ context->handleError(InvalidValue()
+ << "index must be less than the number of extension strings.");
+ return false;
+ }
+ break;
+
+ case GL_REQUESTABLE_EXTENSIONS_ANGLE:
+ if (!context->getExtensions().requestExtension)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
+ return false;
+ }
+ if (index >= context->getRequestableExtensionStringCount())
+ {
+ context->handleError(
+ InvalidValue()
+ << "index must be less than the number of requestable extension strings.");
+ return false;
+ }
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
+ GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
+ height))
+ {
+ return false;
+ }
+
+ // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
+ // format if samples is greater than zero.
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
+ if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) &&
+ samples > 0)
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+
+ // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
+ const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
+ if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
+ {
+ context->handleError(
+ InvalidOperation()
+ << "Samples must not be greater than maximum supported value for the format.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateVertexAttribIPointer(ValidationContext *context,
+ GLuint index,
+ GLint size,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if (!ValidateVertexFormatBase(context, index, size, type, true))
+ {
+ return false;
+ }
+
+ if (stride < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ if (context->getClientVersion() >= ES_3_1)
+ {
+ if (stride > caps.maxVertexAttribStride)
+ {
+ context->handleError(InvalidValue()
+ << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
+ return false;
+ }
+
+ // [OpenGL ES 3.1] Section 10.3.1 page 245:
+ // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
+ // validation should be inherited.
+ if (index >= caps.maxVertexAttribBindings)
+ {
+ context->handleError(InvalidValue()
+ << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
+ return false;
+ }
+ }
+
+ // [OpenGL ES 3.0.2] Section 2.8 page 24:
+ // An INVALID_OPERATION error is generated when a non-zero vertex array object
+ // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
+ // and the pointer argument is not NULL.
+ if (context->getGLState().getVertexArrayId() != 0 &&
+ context->getGLState().getTargetBuffer(BufferBinding::Array) == 0 && pointer != nullptr)
+ {
+ context
+ ->handleError(InvalidOperation()
+ << "Client data cannot be used with a non-default vertex array object.");
+ return false;
+ }
+
+ if (context->getExtensions().webglCompatibility)
+ {
+ if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGetSynciv(Context *context,
+ GLsync sync,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *values)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if (bufSize < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
+ return false;
+ }
+
+ Sync *syncObject = context->getSync(sync);
+ if (!syncObject)
+ {
+ context->handleError(InvalidValue() << "Invalid sync object.");
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_OBJECT_TYPE:
+ case GL_SYNC_CONDITION:
+ case GL_SYNC_FLAGS:
+ case GL_SYNC_STATUS:
+ break;
+
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDrawElementsInstanced(ValidationContext *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei instanceCount)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
+}
+
+bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
+ GLenum target,
+ GLenum attachment,
+ GLuint texture,
+ GLint level,
+ GLint baseViewIndex,
+ GLsizei numViews)
+{
+
+ if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
+ numViews))
+ {
+ return false;
+ }
+
+ if (texture != 0)
+ {
+ if (baseViewIndex < 0)
+ {
+ context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
+ return false;
+ }
+
+ Texture *tex = context->getTexture(texture);
+ ASSERT(tex);
+
+ switch (tex->getTarget())
+ {
+ case GL_TEXTURE_2D_ARRAY:
+ {
+ const Caps &caps = context->getCaps();
+ if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
+ {
+ context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
+ "greater than "
+ "GL_MAX_ARRAY_TEXTURE_LAYERS.");
+ return false;
+ }
+ }
+ break;
+ default:
+ context->handleError(InvalidOperation()
+ << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
+ return false;
+ }
+
+ if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
+ GLenum target,
+ GLenum attachment,
+ GLuint texture,
+ GLint level,
+ GLsizei numViews,
+ const GLint *viewportOffsets)
+{
+ if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
+ numViews))
+ {
+ return false;
+ }
+
+ if (texture != 0)
+ {
+ const GLsizei numViewportOffsetValues = numViews * 2;
+ for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
+ {
+ if (viewportOffsets[i] < 0)
+ {
+ context->handleError(InvalidValue()
+ << "viewportOffsets cannot contain negative values.");
+ return false;
+ }
+ }
+
+ Texture *tex = context->getTexture(texture);
+ ASSERT(tex);
+
+ switch (tex->getTarget())
+ {
+ case GL_TEXTURE_2D:
+ break;
+ default:
+ context->handleError(InvalidOperation()
+ << "Texture's target must be GL_TEXTURE_2D.");
+ return false;
+ }
+
+ if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
+{
+ return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
+}
+
+bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
+{
+ return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
+}
+
+bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
+{
+ return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
+}
+
+bool ValidateUniform4ui(Context *context,
+ GLint location,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
+}
+
+bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
+{
+ return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
+}
+
+bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
+{
+ return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
+}
+
+bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
+{
+ return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
+}
+
+bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
+{
+ return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
+}
+
+bool ValidateIsQuery(Context *context, GLuint id)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateUniformMatrix2x3fv(Context *context,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
+}
+
+bool ValidateUniformMatrix3x2fv(Context *context,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
+}
+
+bool ValidateUniformMatrix2x4fv(Context *context,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
+}
+
+bool ValidateUniformMatrix4x2fv(Context *context,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
+}
+
+bool ValidateUniformMatrix3x4fv(Context *context,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
+}
+
+bool ValidateUniformMatrix4x3fv(Context *context,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
+}
+
+bool ValidateEndTransformFeedback(Context *context)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
+ ASSERT(transformFeedback != nullptr);
+
+ if (!transformFeedback->isActive())
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateTransformFeedbackVaryings(Context *context,
+ GLuint program,
+ GLsizei count,
+ const GLchar *const *varyings,
+ GLenum bufferMode)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if (count < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
+ return false;
+ }
+
+ switch (bufferMode)
+ {
+ case GL_INTERLEAVED_ATTRIBS:
+ break;
+ case GL_SEPARATE_ATTRIBS:
+ {
+ const Caps &caps = context->getCaps();
+ if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+ break;
+ }
+ default:
+ context->handleError(InvalidEnum());
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetTransformFeedbackVarying(Context *context,
+ GLuint program,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *size,
+ GLenum *type,
+ GLchar *name)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if (bufSize < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ switch (target)
+ {
+ case GL_TRANSFORM_FEEDBACK:
+ {
+ // Cannot bind a transform feedback object if the current one is started and not
+ // paused (3.0.2 pg 85 section 2.14.1)
+ TransformFeedback *curTransformFeedback =
+ context->getGLState().getCurrentTransformFeedback();
+ if (curTransformFeedback && curTransformFeedback->isActive() &&
+ !curTransformFeedback->isPaused())
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+
+ // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
+ // 2.14.1)
+ if (!context->isTransformFeedbackGenerated(id))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
+ return false;
+ }
+ }
+ break;
+
+ default:
+ context->handleError(InvalidEnum());
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateIsTransformFeedback(Context *context, GLuint id)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidatePauseTransformFeedback(Context *context)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
+ ASSERT(transformFeedback != nullptr);
+
+ // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
+ if (!transformFeedback->isActive() || transformFeedback->isPaused())
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateResumeTransformFeedback(Context *context)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
+ ASSERT(transformFeedback != nullptr);
+
+ // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
+ if (!transformFeedback->isActive() || !transformFeedback->isPaused())
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateVertexAttribI4ui(Context *context,
+ GLuint index,
+ GLuint x,
+ GLuint y,
+ GLuint z,
+ GLuint w)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (!programObject->isLinked())
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetUniformIndices(Context *context,
+ GLuint program,
+ GLsizei uniformCount,
+ const GLchar *const *uniformNames,
+ GLuint *uniformIndices)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if (uniformCount < 0)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetActiveUniformsiv(Context *context,
+ GLuint program,
+ GLsizei uniformCount,
+ const GLuint *uniformIndices,
+ GLenum pname,
+ GLint *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if (uniformCount < 0)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_UNIFORM_TYPE:
+ case GL_UNIFORM_SIZE:
+ case GL_UNIFORM_NAME_LENGTH:
+ case GL_UNIFORM_BLOCK_INDEX:
+ case GL_UNIFORM_OFFSET:
+ case GL_UNIFORM_ARRAY_STRIDE:
+ case GL_UNIFORM_MATRIX_STRIDE:
+ case GL_UNIFORM_IS_ROW_MAJOR:
+ break;
+
+ default:
+ context->handleError(InvalidEnum());
+ return false;
+ }
+
+ if (uniformCount > programObject->getActiveUniformCount())
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+
+ for (int uniformId = 0; uniformId < uniformCount; uniformId++)
+ {
+ const GLuint index = uniformIndices[uniformId];
+
+ if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetActiveUniformBlockiv(Context *context,
+ GLuint program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLint *params)
+{
+ return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
+}
+
+bool ValidateGetActiveUniformBlockName(Context *context,
+ GLuint program,
+ GLuint uniformBlockIndex,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *uniformBlockName)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateUniformBlockBinding(Context *context,
+ GLuint program,
+ GLuint uniformBlockIndex,
+ GLuint uniformBlockBinding)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ // if never linked, there won't be any uniform blocks
+ if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDrawArraysInstanced(Context *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
+}
+
+bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
+ {
+ context->handleError(InvalidEnum());
+ return false;
+ }
+
+ if (flags != 0)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateIsSync(Context *context, GLsync sync)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDeleteSync(Context *context, GLsync sync)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+
+ Sync *clientWaitSync = context->getSync(sync);
+ if (!clientWaitSync)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if (flags != 0)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+
+ if (timeout != GL_TIMEOUT_IGNORED)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+
+ Sync *waitSync = context->getSync(sync);
+ if (!waitSync)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ GLenum nativeType = GL_NONE;
+ unsigned int numParams = 0;
+ if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateIsSampler(Context *context, GLuint sampler)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBindSampler(Context *context, GLuint unit, GLuint sampler)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if (sampler != 0 && !context->isSampler(sampler))
+ {
+ context->handleError(InvalidOperation());
+ return false;
+ }
+
+ if (unit >= context->getCaps().maxCombinedTextureImageUnits)
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateVertexAttribDivisor(Context *context, GLuint index, GLuint divisor)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ return ValidateVertexAttribIndex(context, index);
+}
+
+bool ValidateTexStorage2D(Context *context,
+ GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width, height,
+ 1))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateTexStorage3D(Context *context,
+ GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
+ return false;
+ }
+
+ if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
+ depth))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetBufferParameteri64v(ValidationContext *context,
+ BufferBinding target,
+ GLenum pname,
+ GLint64 *params)
+{
+ return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
+}
+
+bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
+{
+ return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
+}
+
+bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
+{
+ return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
+}
+
+bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
+{
+ return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
+}
+
+bool ValidateSamplerParameterfv(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ const GLfloat *params)
+{
+ return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
+}
+
+bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
+{
+ return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
+}
+
+bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
+{
+ return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
+}
+
+bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
+{
+ return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
+}
+
+bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
+{
+ return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
+}
+
+bool ValidateGetInternalformativ(Context *context,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLint *params)
+{
+ return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
+ nullptr);
+}
+
} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/validationES3.h b/src/3rdparty/angle/src/libANGLE/validationES3.h
index 7bc657790a..631b1ca43a 100644
--- a/src/3rdparty/angle/src/libANGLE/validationES3.h
+++ b/src/3rdparty/angle/src/libANGLE/validationES3.h
@@ -9,11 +9,14 @@
#ifndef LIBANGLE_VALIDATION_ES3_H_
#define LIBANGLE_VALIDATION_ES3_H_
+#include "libANGLE/PackedGLEnums.h"
+
#include <GLES3/gl3.h>
namespace gl
{
class Context;
+struct IndexRange;
class ValidationContext;
bool ValidateES3TexImageParametersBase(ValidationContext *context,
@@ -31,7 +34,8 @@ bool ValidateES3TexImageParametersBase(ValidationContext *context,
GLint border,
GLenum format,
GLenum type,
- const GLvoid *pixels);
+ GLsizei imageSize,
+ const void *pixels);
bool ValidateES3TexStorageParameters(Context *context,
GLenum target,
@@ -56,7 +60,8 @@ bool ValidateES3TexImage2DParameters(Context *context,
GLint border,
GLenum format,
GLenum type,
- const GLvoid *pixels);
+ GLsizei imageSize,
+ const void *pixels);
bool ValidateES3TexImage3DParameters(Context *context,
GLenum target,
@@ -73,7 +78,8 @@ bool ValidateES3TexImage3DParameters(Context *context,
GLint border,
GLenum format,
GLenum type,
- const GLvoid *pixels);
+ GLsizei bufSize,
+ const void *pixels);
bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
GLenum target,
@@ -141,10 +147,6 @@ bool ValidateES3TexStorage3DParameters(Context *context,
GLsizei height,
GLsizei depth);
-bool ValidateGenQueries(Context *context, GLsizei n, const GLuint *ids);
-
-bool ValidateDeleteQueries(Context *context, GLsizei n, const GLuint *ids);
-
bool ValidateBeginQuery(Context *context, GLenum target, GLuint id);
bool ValidateEndQuery(Context *context, GLenum target);
@@ -153,20 +155,38 @@ bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *pa
bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params);
-bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
- GLuint texture, GLint level, GLint layer);
-
-bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum format, GLenum type);
-
-bool ValidateES3RenderbufferStorageParameters(Context *context, GLenum target, GLsizei samples,
- GLenum internalformat, GLsizei width, GLsizei height);
+bool ValidateFramebufferTextureLayer(Context *context,
+ GLenum target,
+ GLenum attachment,
+ GLuint texture,
+ GLint level,
+ GLint layer);
-bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments,
+bool ValidateInvalidateFramebuffer(Context *context,
+ GLenum target,
+ GLsizei numAttachments,
const GLenum *attachments);
+bool ValidateInvalidateSubFramebuffer(Context *context,
+ GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+
bool ValidateClearBuffer(ValidationContext *context);
-bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params);
+bool ValidateDrawRangeElements(Context *context,
+ GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const void *indices);
+
+bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params);
bool ValidateReadBuffer(Context *context, GLenum mode);
@@ -179,12 +199,29 @@ bool ValidateCompressedTexImage3D(Context *context,
GLsizei depth,
GLint border,
GLsizei imageSize,
- const GLvoid *data);
+ const void *data);
+bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const void *data);
bool ValidateBindVertexArray(Context *context, GLuint array);
-bool ValidateDeleteVertexArrays(Context *context, GLsizei n);
-bool ValidateGenVertexArrays(Context *context, GLsizei n);
-bool ValidateIsVertexArray(Context *context);
+bool ValidateIsVertexArray(Context *context, GLuint array);
+
+bool ValidateBindBufferBase(Context *context, BufferBinding target, GLuint index, GLuint buffer);
+bool ValidateBindBufferRange(Context *context,
+ BufferBinding target,
+ GLuint index,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizeiptr size);
bool ValidateProgramBinary(Context *context,
GLuint program,
@@ -197,7 +234,7 @@ bool ValidateGetProgramBinary(Context *context,
GLsizei *length,
GLenum *binaryFormat,
void *binary);
-bool ValidateProgramParameter(Context *context, GLuint program, GLenum pname, GLint value);
+bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value);
bool ValidateBlitFramebuffer(Context *context,
GLint srcX0,
GLint srcY0,
@@ -237,7 +274,341 @@ bool ValidateCopyTexSubImage3D(Context *context,
GLint y,
GLsizei width,
GLsizei height);
+bool ValidateTexImage3D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+bool ValidateTexImage3DRobustANGLE(Context *context,
+ GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels);
+bool ValidateTexSubImage3D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+bool ValidateTexSubImage3DRobustANGLE(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels);
+bool ValidateCompressedTexSubImage3D(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data);
+bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const void *data);
+
+bool ValidateGenQueries(Context *context, GLint n, GLuint *ids);
+bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *ids);
+bool ValidateGenSamplers(Context *context, GLint count, GLuint *samplers);
+bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *samplers);
+bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *ids);
+bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids);
+bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *arrays);
+bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *arrays);
+
+bool ValidateBeginTransformFeedback(Context *context, GLenum primitiveMode);
+
+bool ValidateGetBufferPointerv(Context *context, BufferBinding target, GLenum pname, void **params);
+bool ValidateGetBufferPointervRobustANGLE(Context *context,
+ BufferBinding target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ void **params);
+bool ValidateUnmapBuffer(Context *context, BufferBinding target);
+bool ValidateMapBufferRange(Context *context,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access);
+bool ValidateFlushMappedBufferRange(Context *context,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length);
+
+bool ValidateIndexedStateQuery(ValidationContext *context,
+ GLenum pname,
+ GLuint index,
+ GLsizei *length);
+bool ValidateGetIntegeri_v(ValidationContext *context, GLenum target, GLuint index, GLint *data);
+bool ValidateGetIntegeri_vRobustANGLE(ValidationContext *context,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *data);
+bool ValidateGetInteger64i_v(ValidationContext *context,
+ GLenum target,
+ GLuint index,
+ GLint64 *data);
+bool ValidateGetInteger64i_vRobustANGLE(ValidationContext *context,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *data);
+
+bool ValidateCopyBufferSubData(ValidationContext *context,
+ BufferBinding readTarget,
+ BufferBinding writeTarget,
+ GLintptr readOffset,
+ GLintptr writeOffset,
+ GLsizeiptr size);
+
+bool ValidateGetStringi(Context *context, GLenum name, GLuint index);
+bool ValidateRenderbufferStorageMultisample(ValidationContext *context,
+ GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+
+bool ValidateVertexAttribIPointer(ValidationContext *context,
+ GLuint index,
+ GLint size,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer);
+
+bool ValidateGetSynciv(Context *context,
+ GLsync sync,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *values);
+
+bool ValidateDrawElementsInstanced(ValidationContext *context,
+ GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei instanceCount);
+
+bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
+ GLenum target,
+ GLenum attachment,
+ GLuint texture,
+ GLint level,
+ GLint baseViewIndex,
+ GLsizei numViews);
+
+bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
+ GLenum target,
+ GLenum attachment,
+ GLuint texture,
+ GLint level,
+ GLsizei numViews,
+ const GLint *viewportOffsets);
+
+bool ValidateIsQuery(Context *context, GLuint id);
+
+bool ValidateUniform1ui(Context *context, GLint location, GLuint v0);
+bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1);
+bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2);
+bool ValidateUniform4ui(Context *context,
+ GLint location,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3);
+
+bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value);
+bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value);
+bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value);
+bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value);
+
+bool ValidateUniformMatrix2x3fv(Context *context,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateUniformMatrix3x2fv(Context *context,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateUniformMatrix2x4fv(Context *context,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateUniformMatrix4x2fv(Context *context,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateUniformMatrix3x4fv(Context *context,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateUniformMatrix4x3fv(Context *context,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+
+bool ValidateEndTransformFeedback(Context *context);
+bool ValidateTransformFeedbackVaryings(Context *context,
+ GLuint program,
+ GLsizei count,
+ const GLchar *const *varyings,
+ GLenum bufferMode);
+bool ValidateGetTransformFeedbackVarying(Context *context,
+ GLuint program,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *size,
+ GLenum *type,
+ GLchar *name);
+bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id);
+bool ValidateIsTransformFeedback(Context *context, GLuint id);
+bool ValidatePauseTransformFeedback(Context *context);
+bool ValidateResumeTransformFeedback(Context *context);
+bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w);
+bool ValidateVertexAttribI4ui(Context *context,
+ GLuint index,
+ GLuint x,
+ GLuint y,
+ GLuint z,
+ GLuint w);
+bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v);
+bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v);
+bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name);
+bool ValidateGetUniformIndices(Context *context,
+ GLuint program,
+ GLsizei uniformCount,
+ const GLchar *const *uniformNames,
+ GLuint *uniformIndices);
+bool ValidateGetActiveUniformsiv(Context *context,
+ GLuint program,
+ GLsizei uniformCount,
+ const GLuint *uniformIndices,
+ GLenum pname,
+ GLint *params);
+bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName);
+bool ValidateGetActiveUniformBlockiv(Context *context,
+ GLuint program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLint *params);
+bool ValidateGetActiveUniformBlockName(Context *context,
+ GLuint program,
+ GLuint uniformBlockIndex,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *uniformBlockName);
+bool ValidateUniformBlockBinding(Context *context,
+ GLuint program,
+ GLuint uniformBlockIndex,
+ GLuint uniformBlockBinding);
+bool ValidateDrawArraysInstanced(Context *context,
+ GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount);
+
+bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags);
+bool ValidateIsSync(Context *context, GLsync sync);
+bool ValidateDeleteSync(Context *context, GLsync sync);
+bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout);
+bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout);
+bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params);
+
+bool ValidateIsSampler(Context *context, GLuint sampler);
+bool ValidateBindSampler(Context *context, GLuint unit, GLuint sampler);
+bool ValidateVertexAttribDivisor(Context *context, GLuint index, GLuint divisor);
+bool ValidateTexStorage2D(Context *context,
+ GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+bool ValidateTexStorage3D(Context *context,
+ GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+
+bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params);
+bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params);
+bool ValidateGetBufferParameteri64v(ValidationContext *context,
+ BufferBinding target,
+ GLenum pname,
+ GLint64 *params);
+bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param);
+bool ValidateSamplerParameteriv(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ const GLint *params);
+bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param);
+bool ValidateSamplerParameterfv(Context *context,
+ GLuint sampler,
+ GLenum pname,
+ const GLfloat *params);
+bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params);
+bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params);
+bool ValidateGetInternalformativ(Context *context,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLint *params);
} // namespace gl
-#endif // LIBANGLE_VALIDATION_ES3_H_
+#endif // LIBANGLE_VALIDATION_ES3_H_
diff --git a/src/3rdparty/angle/src/libANGLE/validationES31.cpp b/src/3rdparty/angle/src/libANGLE/validationES31.cpp
new file mode 100644
index 0000000000..b1bdccacf7
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/validationES31.cpp
@@ -0,0 +1,1786 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// validationES31.cpp: Validation functions for OpenGL ES 3.1 entry point parameters
+
+#include "libANGLE/validationES31.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/ErrorStrings.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/validationES.h"
+#include "libANGLE/validationES2.h"
+#include "libANGLE/validationES3.h"
+
+#include "common/utilities.h"
+
+using namespace angle;
+
+namespace gl
+{
+
+namespace
+{
+
+bool ValidateNamedProgramInterface(GLenum programInterface)
+{
+ switch (programInterface)
+ {
+ case GL_UNIFORM:
+ case GL_UNIFORM_BLOCK:
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ case GL_BUFFER_VARIABLE:
+ case GL_SHADER_STORAGE_BLOCK:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool ValidateLocationProgramInterface(GLenum programInterface)
+{
+ switch (programInterface)
+ {
+ case GL_UNIFORM:
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool ValidateProgramInterface(GLenum programInterface)
+{
+ return (programInterface == GL_ATOMIC_COUNTER_BUFFER ||
+ ValidateNamedProgramInterface(programInterface));
+}
+
+bool ValidateProgramResourceProperty(GLenum prop)
+{
+ switch (prop)
+ {
+ case GL_ACTIVE_VARIABLES:
+ case GL_BUFFER_BINDING:
+ case GL_NUM_ACTIVE_VARIABLES:
+
+ case GL_ARRAY_SIZE:
+
+ case GL_ARRAY_STRIDE:
+ case GL_BLOCK_INDEX:
+ case GL_IS_ROW_MAJOR:
+ case GL_MATRIX_STRIDE:
+
+ case GL_ATOMIC_COUNTER_BUFFER_INDEX:
+
+ case GL_BUFFER_DATA_SIZE:
+
+ case GL_LOCATION:
+
+ case GL_NAME_LENGTH:
+
+ case GL_OFFSET:
+
+ case GL_REFERENCED_BY_VERTEX_SHADER:
+ case GL_REFERENCED_BY_FRAGMENT_SHADER:
+ case GL_REFERENCED_BY_COMPUTE_SHADER:
+
+ case GL_TOP_LEVEL_ARRAY_SIZE:
+ case GL_TOP_LEVEL_ARRAY_STRIDE:
+
+ case GL_TYPE:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+// GLES 3.10 spec: Page 82 -- Table 7.2
+bool ValidateProgramResourcePropertyByInterface(GLenum prop, GLenum programInterface)
+{
+ switch (prop)
+ {
+ case GL_ACTIVE_VARIABLES:
+ case GL_BUFFER_BINDING:
+ case GL_NUM_ACTIVE_VARIABLES:
+ {
+ switch (programInterface)
+ {
+ case GL_ATOMIC_COUNTER_BUFFER:
+ case GL_SHADER_STORAGE_BLOCK:
+ case GL_UNIFORM_BLOCK:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ case GL_ARRAY_SIZE:
+ {
+ switch (programInterface)
+ {
+ case GL_BUFFER_VARIABLE:
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ case GL_UNIFORM:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ case GL_ARRAY_STRIDE:
+ case GL_BLOCK_INDEX:
+ case GL_IS_ROW_MAJOR:
+ case GL_MATRIX_STRIDE:
+ {
+ switch (programInterface)
+ {
+ case GL_BUFFER_VARIABLE:
+ case GL_UNIFORM:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ case GL_ATOMIC_COUNTER_BUFFER_INDEX:
+ {
+ if (programInterface == GL_UNIFORM)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ case GL_BUFFER_DATA_SIZE:
+ {
+ switch (programInterface)
+ {
+ case GL_ATOMIC_COUNTER_BUFFER:
+ case GL_SHADER_STORAGE_BLOCK:
+ case GL_UNIFORM_BLOCK:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ case GL_LOCATION:
+ {
+ return ValidateLocationProgramInterface(programInterface);
+ }
+
+ case GL_NAME_LENGTH:
+ {
+ return ValidateNamedProgramInterface(programInterface);
+ }
+
+ case GL_OFFSET:
+ {
+ switch (programInterface)
+ {
+ case GL_BUFFER_VARIABLE:
+ case GL_UNIFORM:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ case GL_REFERENCED_BY_VERTEX_SHADER:
+ case GL_REFERENCED_BY_FRAGMENT_SHADER:
+ case GL_REFERENCED_BY_COMPUTE_SHADER:
+ {
+ switch (programInterface)
+ {
+ case GL_ATOMIC_COUNTER_BUFFER:
+ case GL_BUFFER_VARIABLE:
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ case GL_SHADER_STORAGE_BLOCK:
+ case GL_UNIFORM:
+ case GL_UNIFORM_BLOCK:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ case GL_TOP_LEVEL_ARRAY_SIZE:
+ case GL_TOP_LEVEL_ARRAY_STRIDE:
+ {
+ if (programInterface == GL_BUFFER_VARIABLE)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ case GL_TYPE:
+ {
+ switch (programInterface)
+ {
+ case GL_BUFFER_VARIABLE:
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ case GL_UNIFORM:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ default:
+ return false;
+ }
+}
+
+bool ValidateProgramResourceIndex(const Program *programObject,
+ GLenum programInterface,
+ GLuint index)
+{
+ switch (programInterface)
+ {
+ case GL_PROGRAM_INPUT:
+ return (index < static_cast<GLuint>(programObject->getActiveAttributeCount()));
+
+ case GL_PROGRAM_OUTPUT:
+ return (index < static_cast<GLuint>(programObject->getOutputResourceCount()));
+
+ case GL_UNIFORM:
+ return (index < static_cast<GLuint>(programObject->getActiveUniformCount()));
+
+ case GL_BUFFER_VARIABLE:
+ return (index < static_cast<GLuint>(programObject->getActiveBufferVariableCount()));
+
+ case GL_SHADER_STORAGE_BLOCK:
+ return (index < static_cast<GLuint>(programObject->getActiveShaderStorageBlockCount()));
+
+ case GL_UNIFORM_BLOCK:
+ return (index < programObject->getActiveUniformBlockCount());
+
+ case GL_ATOMIC_COUNTER_BUFFER:
+ return (index < programObject->getActiveAtomicCounterBufferCount());
+
+ // TODO(jie.a.chen@intel.com): more interfaces.
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ UNIMPLEMENTED();
+ return false;
+
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+bool ValidateProgramUniform(gl::Context *context,
+ GLenum valueType,
+ GLuint program,
+ GLint location,
+ GLsizei count)
+{
+ // Check for ES31 program uniform entry points
+ if (context->getClientVersion() < Version(3, 1))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ const LinkedUniform *uniform = nullptr;
+ gl::Program *programObject = GetValidProgram(context, program);
+ return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
+ ValidateUniformValue(context, valueType, uniform->type);
+}
+
+bool ValidateProgramUniformMatrix(gl::Context *context,
+ GLenum valueType,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose)
+{
+ // Check for ES31 program uniform entry points
+ if (context->getClientVersion() < Version(3, 1))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ const LinkedUniform *uniform = nullptr;
+ gl::Program *programObject = GetValidProgram(context, program);
+ return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
+ ValidateUniformMatrixValue(context, valueType, uniform->type);
+}
+
+bool ValidateVertexAttribFormatCommon(ValidationContext *context,
+ GLuint attribIndex,
+ GLint size,
+ GLenum type,
+ GLuint relativeOffset,
+ GLboolean pureInteger)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ if (relativeOffset > static_cast<GLuint>(caps.maxVertexAttribRelativeOffset))
+ {
+ context->handleError(
+ InvalidValue()
+ << "relativeOffset cannot be greater than MAX_VERTEX_ATTRIB_RELATIVE_OFFSET.");
+ return false;
+ }
+
+ // [OpenGL ES 3.1] Section 10.3.1 page 243:
+ // An INVALID_OPERATION error is generated if the default vertex array object is bound.
+ if (context->getGLState().getVertexArrayId() == 0)
+ {
+ context->handleError(InvalidOperation() << "Default vertex array object is bound.");
+ return false;
+ }
+
+ return ValidateVertexFormatBase(context, attribIndex, size, type, pureInteger);
+}
+
+} // anonymous namespace
+
+bool ValidateGetBooleani_v(Context *context, GLenum target, GLuint index, GLboolean *data)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ if (!ValidateIndexedStateQuery(context, target, index, nullptr))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetBooleani_vRobustANGLE(Context *context,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLboolean *data)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateIndexedStateQuery(context, target, index, length))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, bufSize, *length))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDrawIndirectBase(Context *context, GLenum mode, const void *indirect)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ // Here the third parameter 1 is only to pass the count validation.
+ if (!ValidateDrawBase(context, mode, 1))
+ {
+ return false;
+ }
+
+ const State &state = context->getGLState();
+
+ // An INVALID_OPERATION error is generated if zero is bound to VERTEX_ARRAY_BINDING,
+ // DRAW_INDIRECT_BUFFER or to any enabled vertex array.
+ if (!state.getVertexArrayId())
+ {
+ context->handleError(InvalidOperation() << "zero is bound to VERTEX_ARRAY_BINDING");
+ return false;
+ }
+
+ gl::Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
+ if (!drawIndirectBuffer)
+ {
+ context->handleError(InvalidOperation() << "zero is bound to DRAW_INDIRECT_BUFFER");
+ return false;
+ }
+
+ // An INVALID_VALUE error is generated if indirect is not a multiple of the size, in basic
+ // machine units, of uint.
+ GLint64 offset = reinterpret_cast<GLint64>(indirect);
+ if ((static_cast<GLuint>(offset) % sizeof(GLuint)) != 0)
+ {
+ context->handleError(
+ InvalidValue()
+ << "indirect is not a multiple of the size, in basic machine units, of uint");
+ return false;
+ }
+
+ // ANGLE_multiview spec, revision 1:
+ // An INVALID_OPERATION is generated by DrawArraysIndirect and DrawElementsIndirect if the
+ // number of views in the draw framebuffer is greater than 1.
+ const Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
+ ASSERT(drawFramebuffer != nullptr);
+ if (drawFramebuffer->getNumViews() > 1)
+ {
+ context->handleError(
+ InvalidOperation()
+ << "The number of views in the active draw framebuffer is greater than 1.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDrawArraysIndirect(Context *context, GLenum mode, const void *indirect)
+{
+ const State &state = context->getGLState();
+ gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
+ if (curTransformFeedback && curTransformFeedback->isActive() &&
+ !curTransformFeedback->isPaused())
+ {
+ // An INVALID_OPERATION error is generated if transform feedback is active and not paused.
+ context->handleError(InvalidOperation() << "transform feedback is active and not paused.");
+ return false;
+ }
+
+ if (!ValidateDrawIndirectBase(context, mode, indirect))
+ return false;
+
+ gl::Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
+ CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
+ // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawArraysIndirectCommand
+ // which's size is 4 * sizeof(uint).
+ auto checkedSum = checkedOffset + 4 * sizeof(GLuint);
+ if (!checkedSum.IsValid() ||
+ checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
+ {
+ context->handleError(
+ InvalidOperation()
+ << "the command would source data beyond the end of the buffer object.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDrawElementsIndirect(Context *context, GLenum mode, GLenum type, const void *indirect)
+{
+ if (!ValidateDrawElementsBase(context, type))
+ return false;
+
+ const State &state = context->getGLState();
+ const VertexArray *vao = state.getVertexArray();
+ gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
+ if (!elementArrayBuffer)
+ {
+ context->handleError(InvalidOperation() << "zero is bound to ELEMENT_ARRAY_BUFFER");
+ return false;
+ }
+
+ if (!ValidateDrawIndirectBase(context, mode, indirect))
+ return false;
+
+ gl::Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
+ CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
+ // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawElementsIndirectCommand
+ // which's size is 5 * sizeof(uint).
+ auto checkedSum = checkedOffset + 5 * sizeof(GLuint);
+ if (!checkedSum.IsValid() ||
+ checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
+ {
+ context->handleError(
+ InvalidOperation()
+ << "the command would source data beyond the end of the buffer object.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateProgramUniform1i(Context *context, GLuint program, GLint location, GLint v0)
+{
+ return ValidateProgramUniform1iv(context, program, location, 1, &v0);
+}
+
+bool ValidateProgramUniform2i(Context *context, GLuint program, GLint location, GLint v0, GLint v1)
+{
+ GLint xy[2] = {v0, v1};
+ return ValidateProgramUniform2iv(context, program, location, 1, xy);
+}
+
+bool ValidateProgramUniform3i(Context *context,
+ GLuint program,
+ GLint location,
+ GLint v0,
+ GLint v1,
+ GLint v2)
+{
+ GLint xyz[3] = {v0, v1, v2};
+ return ValidateProgramUniform3iv(context, program, location, 1, xyz);
+}
+
+bool ValidateProgramUniform4i(Context *context,
+ GLuint program,
+ GLint location,
+ GLint v0,
+ GLint v1,
+ GLint v2,
+ GLint v3)
+{
+ GLint xyzw[4] = {v0, v1, v2, v3};
+ return ValidateProgramUniform4iv(context, program, location, 1, xyzw);
+}
+
+bool ValidateProgramUniform1ui(Context *context, GLuint program, GLint location, GLuint v0)
+{
+ return ValidateProgramUniform1uiv(context, program, location, 1, &v0);
+}
+
+bool ValidateProgramUniform2ui(Context *context,
+ GLuint program,
+ GLint location,
+ GLuint v0,
+ GLuint v1)
+{
+ GLuint xy[2] = {v0, v1};
+ return ValidateProgramUniform2uiv(context, program, location, 1, xy);
+}
+
+bool ValidateProgramUniform3ui(Context *context,
+ GLuint program,
+ GLint location,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLuint xyz[3] = {v0, v1, v2};
+ return ValidateProgramUniform3uiv(context, program, location, 1, xyz);
+}
+
+bool ValidateProgramUniform4ui(Context *context,
+ GLuint program,
+ GLint location,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLuint xyzw[4] = {v0, v1, v2, v3};
+ return ValidateProgramUniform4uiv(context, program, location, 1, xyzw);
+}
+
+bool ValidateProgramUniform1f(Context *context, GLuint program, GLint location, GLfloat v0)
+{
+ return ValidateProgramUniform1fv(context, program, location, 1, &v0);
+}
+
+bool ValidateProgramUniform2f(Context *context,
+ GLuint program,
+ GLint location,
+ GLfloat v0,
+ GLfloat v1)
+{
+ GLfloat xy[2] = {v0, v1};
+ return ValidateProgramUniform2fv(context, program, location, 1, xy);
+}
+
+bool ValidateProgramUniform3f(Context *context,
+ GLuint program,
+ GLint location,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2)
+{
+ GLfloat xyz[3] = {v0, v1, v2};
+ return ValidateProgramUniform3fv(context, program, location, 1, xyz);
+}
+
+bool ValidateProgramUniform4f(Context *context,
+ GLuint program,
+ GLint location,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2,
+ GLfloat v3)
+{
+ GLfloat xyzw[4] = {v0, v1, v2, v3};
+ return ValidateProgramUniform4fv(context, program, location, 1, xyzw);
+}
+
+bool ValidateProgramUniform1iv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLint *value)
+{
+ // Check for ES31 program uniform entry points
+ if (context->getClientVersion() < Version(3, 1))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ const LinkedUniform *uniform = nullptr;
+ gl::Program *programObject = GetValidProgram(context, program);
+ return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
+ ValidateUniform1ivValue(context, uniform->type, count, value);
+}
+
+bool ValidateProgramUniform2iv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLint *value)
+{
+ return ValidateProgramUniform(context, GL_INT_VEC2, program, location, count);
+}
+
+bool ValidateProgramUniform3iv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLint *value)
+{
+ return ValidateProgramUniform(context, GL_INT_VEC3, program, location, count);
+}
+
+bool ValidateProgramUniform4iv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLint *value)
+{
+ return ValidateProgramUniform(context, GL_INT_VEC4, program, location, count);
+}
+
+bool ValidateProgramUniform1uiv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLuint *value)
+{
+ return ValidateProgramUniform(context, GL_UNSIGNED_INT, program, location, count);
+}
+
+bool ValidateProgramUniform2uiv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLuint *value)
+{
+ return ValidateProgramUniform(context, GL_UNSIGNED_INT_VEC2, program, location, count);
+}
+
+bool ValidateProgramUniform3uiv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLuint *value)
+{
+ return ValidateProgramUniform(context, GL_UNSIGNED_INT_VEC3, program, location, count);
+}
+
+bool ValidateProgramUniform4uiv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLuint *value)
+{
+ return ValidateProgramUniform(context, GL_UNSIGNED_INT_VEC4, program, location, count);
+}
+
+bool ValidateProgramUniform1fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLfloat *value)
+{
+ return ValidateProgramUniform(context, GL_FLOAT, program, location, count);
+}
+
+bool ValidateProgramUniform2fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLfloat *value)
+{
+ return ValidateProgramUniform(context, GL_FLOAT_VEC2, program, location, count);
+}
+
+bool ValidateProgramUniform3fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLfloat *value)
+{
+ return ValidateProgramUniform(context, GL_FLOAT_VEC3, program, location, count);
+}
+
+bool ValidateProgramUniform4fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLfloat *value)
+{
+ return ValidateProgramUniform(context, GL_FLOAT_VEC4, program, location, count);
+}
+
+bool ValidateProgramUniformMatrix2fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT2, program, location, count,
+ transpose);
+}
+
+bool ValidateProgramUniformMatrix3fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT3, program, location, count,
+ transpose);
+}
+
+bool ValidateProgramUniformMatrix4fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT4, program, location, count,
+ transpose);
+}
+
+bool ValidateProgramUniformMatrix2x3fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT2x3, program, location, count,
+ transpose);
+}
+
+bool ValidateProgramUniformMatrix3x2fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT3x2, program, location, count,
+ transpose);
+}
+
+bool ValidateProgramUniformMatrix2x4fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT2x4, program, location, count,
+ transpose);
+}
+
+bool ValidateProgramUniformMatrix4x2fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT4x2, program, location, count,
+ transpose);
+}
+
+bool ValidateProgramUniformMatrix3x4fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT3x4, program, location, count,
+ transpose);
+}
+
+bool ValidateProgramUniformMatrix4x3fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT4x3, program, location, count,
+ transpose);
+}
+
+bool ValidateGetTexLevelParameterBase(Context *context,
+ GLenum target,
+ GLint level,
+ GLenum pname,
+ GLsizei *length)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (!ValidTexLevelDestinationTarget(context, target))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
+ return false;
+ }
+
+ if (context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target) ==
+ nullptr)
+ {
+ context->handleError(InvalidEnum() << "No texture bound.");
+ return false;
+ }
+
+ if (!ValidMipLevel(context, target, level))
+ {
+ context->handleError(InvalidValue());
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_RED_TYPE:
+ case GL_TEXTURE_GREEN_TYPE:
+ case GL_TEXTURE_BLUE_TYPE:
+ case GL_TEXTURE_ALPHA_TYPE:
+ case GL_TEXTURE_DEPTH_TYPE:
+ break;
+ case GL_TEXTURE_RED_SIZE:
+ case GL_TEXTURE_GREEN_SIZE:
+ case GL_TEXTURE_BLUE_SIZE:
+ case GL_TEXTURE_ALPHA_SIZE:
+ case GL_TEXTURE_DEPTH_SIZE:
+ case GL_TEXTURE_STENCIL_SIZE:
+ case GL_TEXTURE_SHARED_SIZE:
+ break;
+ case GL_TEXTURE_INTERNAL_FORMAT:
+ case GL_TEXTURE_WIDTH:
+ case GL_TEXTURE_HEIGHT:
+ case GL_TEXTURE_DEPTH:
+ break;
+ case GL_TEXTURE_SAMPLES:
+ case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
+ break;
+ case GL_TEXTURE_COMPRESSED:
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
+ return false;
+ }
+
+ if (length)
+ {
+ *length = 1;
+ }
+ return true;
+}
+
+bool ValidateGetTexLevelParameterfv(Context *context,
+ GLenum target,
+ GLint level,
+ GLenum pname,
+ GLfloat *params)
+{
+ return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
+}
+
+bool ValidateGetTexLevelParameteriv(Context *context,
+ GLenum target,
+ GLint level,
+ GLenum pname,
+ GLint *params)
+{
+ return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
+}
+
+bool ValidateTexStorage2DMultisample(Context *context,
+ GLenum target,
+ GLsizei samples,
+ GLint internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedSampleLocations)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ if (target != GL_TEXTURE_2D_MULTISAMPLE)
+ {
+ context->handleError(InvalidEnum() << "Target must be TEXTURE_2D_MULTISAMPLE.");
+ return false;
+ }
+
+ if (width < 1 || height < 1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
+ static_cast<GLuint>(height) > caps.max2DTextureSize)
+ {
+ context
+ ->handleError(InvalidValue()
+ << "Width and height must be less than or equal to GL_MAX_TEXTURE_SIZE.");
+ return false;
+ }
+
+ if (samples == 0)
+ {
+ context->handleError(InvalidValue() << "Samples may not be zero.");
+ return false;
+ }
+
+ const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
+ if (!formatCaps.renderable)
+ {
+ context->handleError(InvalidEnum() << "SizedInternalformat must be color-renderable, "
+ "depth-renderable, or stencil-renderable.");
+ return false;
+ }
+
+ // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
+ // is one of the unsized base internalformats listed in table 8.11.
+ const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
+ if (formatInfo.internalFormat == GL_NONE)
+ {
+ context->handleError(
+ InvalidEnum()
+ << "Internalformat is one of the unsupported unsized base internalformats.");
+ return false;
+ }
+
+ if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
+ {
+ context->handleError(
+ InvalidOperation()
+ << "Samples must not be greater than maximum supported value for the format.");
+ return false;
+ }
+
+ Texture *texture = context->getTargetTexture(target);
+ if (!texture || texture->id() == 0)
+ {
+ context->handleError(InvalidOperation() << "Zero is bound to target.");
+ return false;
+ }
+
+ if (texture->getImmutableFormat())
+ {
+ context->handleError(InvalidOperation() << "The value of TEXTURE_IMMUTABLE_FORMAT for "
+ "the texture currently bound to target on "
+ "the active texture unit is true.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetMultisamplefv(Context *context, GLenum pname, GLuint index, GLfloat *val)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ if (pname != GL_SAMPLE_POSITION)
+ {
+ context->handleError(InvalidEnum() << "Pname must be SAMPLE_POSITION.");
+ return false;
+ }
+
+ Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
+
+ if (index >= static_cast<GLuint>(framebuffer->getSamples(context)))
+ {
+ context->handleError(InvalidValue() << "Index must be less than the value of SAMPLES.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateFramebufferParameteri(Context *context, GLenum target, GLenum pname, GLint param)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ if (!ValidFramebufferTarget(context, target))
+ {
+ context->handleError(InvalidEnum() << "Invalid framebuffer target.");
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_DEFAULT_WIDTH:
+ {
+ GLint maxWidth = context->getCaps().maxFramebufferWidth;
+ if (param < 0 || param > maxWidth)
+ {
+ context->handleError(
+ InvalidValue()
+ << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_WIDTH.");
+ return false;
+ }
+ break;
+ }
+ case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
+ {
+ GLint maxHeight = context->getCaps().maxFramebufferHeight;
+ if (param < 0 || param > maxHeight)
+ {
+ context->handleError(
+ InvalidValue()
+ << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_HEIGHT.");
+ return false;
+ }
+ break;
+ }
+ case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
+ {
+ GLint maxSamples = context->getCaps().maxFramebufferSamples;
+ if (param < 0 || param > maxSamples)
+ {
+ context->handleError(
+ InvalidValue()
+ << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_SAMPLES.");
+ return false;
+ }
+ break;
+ }
+ case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
+ {
+ break;
+ }
+ default:
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
+ return false;
+ }
+ }
+
+ const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+ if (framebuffer->id() == 0)
+ {
+ context->handleError(InvalidOperation() << "Default framebuffer is bound to target.");
+ return false;
+ }
+ return true;
+}
+
+bool ValidateGetFramebufferParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ if (!ValidFramebufferTarget(context, target))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_DEFAULT_WIDTH:
+ case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
+ case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
+ case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
+ break;
+ default:
+ ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
+ return false;
+ }
+
+ const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (framebuffer->id() == 0)
+ {
+ context->handleError(InvalidOperation() << "Default framebuffer is bound to target.");
+ return false;
+ }
+ return true;
+}
+
+bool ValidateGetProgramResourceIndex(Context *context,
+ GLuint program,
+ GLenum programInterface,
+ const GLchar *name)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+ if (programObject == nullptr)
+ {
+ return false;
+ }
+
+ if (!ValidateNamedProgramInterface(programInterface))
+ {
+ context->handleError(InvalidEnum() << "Invalid program interface: 0x" << std::hex
+ << std::uppercase << programInterface);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBindVertexBuffer(ValidationContext *context,
+ GLuint bindingIndex,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizei stride)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ if (!context->isBufferGenerated(buffer))
+ {
+ context->handleError(InvalidOperation() << "Buffer is not generated.");
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ if (bindingIndex >= caps.maxVertexAttribBindings)
+ {
+ context->handleError(InvalidValue()
+ << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
+ return false;
+ }
+
+ if (offset < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
+ return false;
+ }
+
+ if (stride < 0 || stride > caps.maxVertexAttribStride)
+ {
+ context->handleError(InvalidValue()
+ << "stride must be between 0 and MAX_VERTEX_ATTRIB_STRIDE.");
+ return false;
+ }
+
+ // [OpenGL ES 3.1] Section 10.3.1 page 244:
+ // An INVALID_OPERATION error is generated if the default vertex array object is bound.
+ if (context->getGLState().getVertexArrayId() == 0)
+ {
+ context->handleError(InvalidOperation() << "Default vertex array buffer is bound.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateVertexBindingDivisor(ValidationContext *context, GLuint bindingIndex, GLuint divisor)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ if (bindingIndex >= caps.maxVertexAttribBindings)
+ {
+ context->handleError(InvalidValue()
+ << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
+ return false;
+ }
+
+ // [OpenGL ES 3.1] Section 10.3.1 page 243:
+ // An INVALID_OPERATION error is generated if the default vertex array object is bound.
+ if (context->getGLState().getVertexArrayId() == 0)
+ {
+ context->handleError(InvalidOperation() << "Default vertex array object is bound.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateVertexAttribFormat(ValidationContext *context,
+ GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLuint relativeoffset)
+{
+ return ValidateVertexAttribFormatCommon(context, attribindex, size, type, relativeoffset,
+ false);
+}
+
+bool ValidateVertexAttribIFormat(ValidationContext *context,
+ GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLuint relativeoffset)
+{
+ return ValidateVertexAttribFormatCommon(context, attribindex, size, type, relativeoffset, true);
+}
+
+bool ValidateVertexAttribBinding(ValidationContext *context,
+ GLuint attribIndex,
+ GLuint bindingIndex)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ // [OpenGL ES 3.1] Section 10.3.1 page 243:
+ // An INVALID_OPERATION error is generated if the default vertex array object is bound.
+ if (context->getGLState().getVertexArrayId() == 0)
+ {
+ context->handleError(InvalidOperation() << "Default vertex array object is bound.");
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ if (attribIndex >= caps.maxVertexAttributes)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
+ return false;
+ }
+
+ if (bindingIndex >= caps.maxVertexAttribBindings)
+ {
+ context->handleError(InvalidValue()
+ << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetProgramResourceName(Context *context,
+ GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+ if (programObject == nullptr)
+ {
+ return false;
+ }
+
+ if (!ValidateNamedProgramInterface(programInterface))
+ {
+ context->handleError(InvalidEnum() << "Invalid program interface: 0x" << std::hex
+ << std::uppercase << programInterface);
+ return false;
+ }
+
+ if (!ValidateProgramResourceIndex(programObject, programInterface, index))
+ {
+ context->handleError(InvalidValue() << "Invalid index: " << index);
+ return false;
+ }
+
+ if (bufSize < 0)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDispatchCompute(Context *context,
+ GLuint numGroupsX,
+ GLuint numGroupsY,
+ GLuint numGroupsZ)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ const State &state = context->getGLState();
+ Program *program = state.getProgram();
+
+ if (program == nullptr)
+ {
+ context->handleError(InvalidOperation()
+ << "No active program object for the compute shader stage.");
+ return false;
+ }
+
+ if (!program->isLinked() || !program->hasLinkedComputeShader())
+ {
+ context->handleError(
+ InvalidOperation()
+ << "Program has not been successfully linked, or program contains no compute shaders.");
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ if (numGroupsX > caps.maxComputeWorkGroupCount[0])
+ {
+ context->handleError(
+ InvalidValue() << "num_groups_x cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[0]="
+ << caps.maxComputeWorkGroupCount[0]);
+ return false;
+ }
+ if (numGroupsY > caps.maxComputeWorkGroupCount[1])
+ {
+ context->handleError(
+ InvalidValue() << "num_groups_y cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[1]="
+ << caps.maxComputeWorkGroupCount[1]);
+ return false;
+ }
+ if (numGroupsZ > caps.maxComputeWorkGroupCount[2])
+ {
+ context->handleError(
+ InvalidValue() << "num_groups_z cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[2]="
+ << caps.maxComputeWorkGroupCount[2]);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDispatchComputeIndirect(Context *context, GLintptr indirect)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateBindImageTexture(Context *context,
+ GLuint unit,
+ GLuint texture,
+ GLint level,
+ GLboolean layered,
+ GLint layer,
+ GLenum access,
+ GLenum format)
+{
+ GLuint maxImageUnits = context->getCaps().maxImageUnits;
+ if (unit >= maxImageUnits)
+ {
+ context->handleError(InvalidValue()
+ << "unit cannot be greater than or equal than MAX_IMAGE_UNITS = "
+ << maxImageUnits);
+ return false;
+ }
+
+ if (level < 0)
+ {
+ context->handleError(InvalidValue() << "level is negative.");
+ return false;
+ }
+
+ if (layer < 0)
+ {
+ context->handleError(InvalidValue() << "layer is negative.");
+ return false;
+ }
+
+ if (access != GL_READ_ONLY && access != GL_WRITE_ONLY && access != GL_READ_WRITE)
+ {
+ context->handleError(InvalidEnum() << "access is not one of the supported tokens.");
+ return false;
+ }
+
+ switch (format)
+ {
+ case GL_RGBA32F:
+ case GL_RGBA16F:
+ case GL_R32F:
+ case GL_RGBA32UI:
+ case GL_RGBA16UI:
+ case GL_RGBA8UI:
+ case GL_R32UI:
+ case GL_RGBA32I:
+ case GL_RGBA16I:
+ case GL_RGBA8I:
+ case GL_R32I:
+ case GL_RGBA8:
+ case GL_RGBA8_SNORM:
+ break;
+ default:
+ context->handleError(InvalidValue()
+ << "format is not one of supported image unit formats.");
+ return false;
+ }
+
+ if (texture != 0)
+ {
+ Texture *tex = context->getTexture(texture);
+
+ if (tex == nullptr)
+ {
+ context->handleError(InvalidValue()
+ << "texture is not the name of an existing texture object.");
+ return false;
+ }
+
+ if (!tex->getImmutableFormat())
+ {
+ context->handleError(InvalidOperation()
+ << "texture is not the name of an immutable texture object.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGetProgramResourceLocation(Context *context,
+ GLuint program,
+ GLenum programInterface,
+ const GLchar *name)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+ if (programObject == nullptr)
+ {
+ return false;
+ }
+
+ if (!programObject->isLinked())
+ {
+ context->handleError(InvalidOperation() << "Program is not successfully linked.");
+ return false;
+ }
+
+ if (!ValidateLocationProgramInterface(programInterface))
+ {
+ context->handleError(InvalidEnum() << "Invalid program interface.");
+ return false;
+ }
+ return true;
+}
+
+bool ValidateGetProgramResourceiv(Context *context,
+ GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum *props,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+ if (programObject == nullptr)
+ {
+ return false;
+ }
+ if (!ValidateProgramInterface(programInterface))
+ {
+ context->handleError(InvalidEnum() << "Invalid program interface.");
+ return false;
+ }
+ if (propCount <= 0)
+ {
+ context->handleError(InvalidValue() << "Invalid propCount.");
+ return false;
+ }
+ if (bufSize < 0)
+ {
+ context->handleError(InvalidValue() << "Invalid bufSize.");
+ return false;
+ }
+ if (!ValidateProgramResourceIndex(programObject, programInterface, index))
+ {
+ context->handleError(InvalidValue() << "Invalid index: " << index);
+ return false;
+ }
+ for (GLsizei i = 0; i < propCount; i++)
+ {
+ if (!ValidateProgramResourceProperty(props[i]))
+ {
+ context->handleError(InvalidEnum() << "Invalid prop.");
+ return false;
+ }
+ if (!ValidateProgramResourcePropertyByInterface(props[i], programInterface))
+ {
+ context->handleError(InvalidOperation() << "Not an allowed prop for interface");
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ValidateGetProgramInterfaceiv(Context *context,
+ GLuint program,
+ GLenum programInterface,
+ GLenum pname,
+ GLint *params)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, program);
+ if (programObject == nullptr)
+ {
+ return false;
+ }
+
+ if (!ValidateProgramInterface(programInterface))
+ {
+ context->handleError(InvalidEnum() << "Invalid program interface.");
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_ACTIVE_RESOURCES:
+ case GL_MAX_NAME_LENGTH:
+ case GL_MAX_NUM_ACTIVE_VARIABLES:
+ break;
+
+ default:
+ context->handleError(InvalidEnum() << "Unknown property of program interface.");
+ return false;
+ }
+
+ if (pname == GL_MAX_NAME_LENGTH && programInterface == GL_ATOMIC_COUNTER_BUFFER)
+ {
+ context->handleError(InvalidOperation()
+ << "Active atomic counter resources are not assigned name strings.");
+ return false;
+ }
+
+ if (pname == GL_MAX_NUM_ACTIVE_VARIABLES)
+ {
+ switch (programInterface)
+ {
+ case GL_ATOMIC_COUNTER_BUFFER:
+ case GL_SHADER_STORAGE_BLOCK:
+ case GL_UNIFORM_BLOCK:
+ break;
+
+ default:
+ context->handleError(
+ InvalidOperation()
+ << "MAX_NUM_ACTIVE_VARIABLES requires a buffer or block interface.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool ValidateGenOrDeleteES31(Context *context, GLint n)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ return ValidateGenOrDelete(context, n);
+}
+
+bool ValidateGenProgramPipelines(Context *context, GLint n, GLuint *)
+{
+ return ValidateGenOrDeleteES31(context, n);
+}
+
+bool ValidateDeleteProgramPipelines(Context *context, GLint n, const GLuint *)
+{
+ return ValidateGenOrDeleteES31(context, n);
+}
+
+bool ValidateBindProgramPipeline(Context *context, GLuint pipeline)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ if (!context->isProgramPipelineGenerated(pipeline))
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateIsProgramPipeline(Context *context, GLuint pipeline)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateUseProgramStages(Context *context, GLuint pipeline, GLbitfield stages, GLuint program)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateActiveShaderProgram(Context *context, GLuint pipeline, GLuint program)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateCreateShaderProgramv(Context *context,
+ GLenum type,
+ GLsizei count,
+ const GLchar *const *strings)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateGetProgramPipelineiv(Context *context, GLuint pipeline, GLenum pname, GLint *params)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateValidateProgramPipeline(Context *context, GLuint pipeline)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateGetProgramPipelineInfoLog(Context *context,
+ GLuint pipeline,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *infoLog)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateMemoryBarrier(Context *context, GLbitfield barriers)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateMemoryBarrierByRegion(Context *context, GLbitfield barriers)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateSampleMaski(Context *context, GLuint maskNumber, GLbitfield mask)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
+ return false;
+ }
+
+ if (maskNumber >= context->getCaps().maxSampleMaskWords)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libANGLE/validationES31.h b/src/3rdparty/angle/src/libANGLE/validationES31.h
new file mode 100644
index 0000000000..a0b76a5bcb
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/validationES31.h
@@ -0,0 +1,325 @@
+//
+// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// validationES31.h: Validation functions for OpenGL ES 3.1 entry point parameters
+
+#ifndef LIBANGLE_VALIDATION_ES31_H_
+#define LIBANGLE_VALIDATION_ES31_H_
+
+#include <GLES3/gl31.h>
+
+namespace gl
+{
+class Context;
+class ValidationContext;
+
+bool ValidateGetBooleani_v(Context *context, GLenum target, GLuint index, GLboolean *data);
+bool ValidateGetBooleani_vRobustANGLE(Context *context,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLboolean *data);
+
+bool ValidateGetTexLevelParameterfv(Context *context,
+ GLenum target,
+ GLint level,
+ GLenum pname,
+ GLfloat *params);
+bool ValidateGetTexLevelParameteriv(Context *context,
+ GLenum target,
+ GLint level,
+ GLenum pname,
+ GLint *param);
+
+bool ValidateTexStorage2DMultisample(Context *context,
+ GLenum target,
+ GLsizei samples,
+ GLint internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedSampleLocations);
+bool ValidateGetMultisamplefv(Context *context, GLenum pname, GLuint index, GLfloat *val);
+
+bool ValidateDrawIndirectBase(Context *context, GLenum mode, const void *indirect);
+bool ValidateDrawArraysIndirect(Context *context, GLenum mode, const void *indirect);
+bool ValidateDrawElementsIndirect(Context *context, GLenum mode, GLenum type, const void *indirect);
+
+bool ValidateProgramUniform1i(Context *context, GLuint program, GLint location, GLint v0);
+bool ValidateProgramUniform2i(Context *context, GLuint program, GLint location, GLint v0, GLint v1);
+bool ValidateProgramUniform3i(Context *context,
+ GLuint program,
+ GLint location,
+ GLint v0,
+ GLint v1,
+ GLint v2);
+bool ValidateProgramUniform4i(Context *context,
+ GLuint program,
+ GLint location,
+ GLint v0,
+ GLint v1,
+ GLint v2,
+ GLint v3);
+bool ValidateProgramUniform1ui(Context *context, GLuint program, GLint location, GLuint v0);
+bool ValidateProgramUniform2ui(Context *context,
+ GLuint program,
+ GLint location,
+ GLuint v0,
+ GLuint v1);
+bool ValidateProgramUniform3ui(Context *context,
+ GLuint program,
+ GLint location,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2);
+bool ValidateProgramUniform4ui(Context *context,
+ GLuint program,
+ GLint location,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3);
+bool ValidateProgramUniform1f(Context *context, GLuint program, GLint location, GLfloat v0);
+bool ValidateProgramUniform2f(Context *context,
+ GLuint program,
+ GLint location,
+ GLfloat v0,
+ GLfloat v1);
+bool ValidateProgramUniform3f(Context *context,
+ GLuint program,
+ GLint location,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2);
+bool ValidateProgramUniform4f(Context *context,
+ GLuint program,
+ GLint location,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2,
+ GLfloat v3);
+
+bool ValidateProgramUniform1iv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLint *value);
+bool ValidateProgramUniform2iv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLint *value);
+bool ValidateProgramUniform3iv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLint *value);
+bool ValidateProgramUniform4iv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLint *value);
+bool ValidateProgramUniform1uiv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLuint *value);
+bool ValidateProgramUniform2uiv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLuint *value);
+bool ValidateProgramUniform3uiv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLuint *value);
+bool ValidateProgramUniform4uiv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLuint *value);
+bool ValidateProgramUniform1fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLfloat *value);
+bool ValidateProgramUniform2fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLfloat *value);
+bool ValidateProgramUniform3fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLfloat *value);
+bool ValidateProgramUniform4fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix2fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix2fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix3fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix4fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix2x3fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix3x2fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix2x4fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix4x2fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix3x4fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix4x3fv(Context *context,
+ GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+
+bool ValidateFramebufferParameteri(Context *context, GLenum target, GLenum pname, GLint param);
+bool ValidateGetFramebufferParameteriv(Context *context,
+ GLenum target,
+ GLenum pname,
+ GLint *params);
+
+bool ValidateGetProgramResourceIndex(Context *context,
+ GLuint program,
+ GLenum programInterface,
+ const GLchar *name);
+bool ValidateGetProgramResourceName(Context *context,
+ GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name);
+bool ValidateGetProgramResourceLocation(Context *context,
+ GLuint program,
+ GLenum programInterface,
+ const GLchar *name);
+
+bool ValidateGetProgramResourceiv(Context *context,
+ GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum *props,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+
+bool ValidateGetProgramInterfaceiv(Context *context,
+ GLuint program,
+ GLenum programInterface,
+ GLenum pname,
+ GLint *params);
+
+bool ValidateBindVertexBuffer(ValidationContext *context,
+ GLuint bindingIndex,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizei stride);
+bool ValidateVertexAttribFormat(ValidationContext *context,
+ GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLuint relativeoffset);
+bool ValidateVertexAttribIFormat(ValidationContext *context,
+ GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLuint relativeoffset);
+bool ValidateVertexAttribBinding(ValidationContext *context,
+ GLuint attribIndex,
+ GLuint bindingIndex);
+bool ValidateVertexBindingDivisor(ValidationContext *context, GLuint bindingIndex, GLuint divisor);
+
+bool ValidateDispatchCompute(Context *context,
+ GLuint numGroupsX,
+ GLuint numGroupsY,
+ GLuint numGroupsZ);
+bool ValidateDispatchComputeIndirect(Context *context, GLintptr indirect);
+
+bool ValidateBindImageTexture(Context *context,
+ GLuint unit,
+ GLuint texture,
+ GLint level,
+ GLboolean layered,
+ GLint layer,
+ GLenum access,
+ GLenum format);
+
+bool ValidateGenProgramPipelines(Context *context, GLint n, GLuint *pipelines);
+bool ValidateDeleteProgramPipelines(Context *context, GLint n, const GLuint *pipelines);
+bool ValidateBindProgramPipeline(Context *context, GLuint pipeline);
+bool ValidateIsProgramPipeline(Context *context, GLuint pipeline);
+bool ValidateUseProgramStages(Context *context, GLuint pipeline, GLbitfield stages, GLuint program);
+bool ValidateActiveShaderProgram(Context *context, GLuint pipeline, GLuint program);
+bool ValidateCreateShaderProgramv(Context *context,
+ GLenum type,
+ GLsizei count,
+ const GLchar *const *strings);
+bool ValidateGetProgramPipelineiv(Context *context, GLuint pipeline, GLenum pname, GLint *params);
+bool ValidateValidateProgramPipeline(Context *context, GLuint pipeline);
+bool ValidateGetProgramPipelineInfoLog(Context *context,
+ GLuint pipeline,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *infoLog);
+
+bool ValidateMemoryBarrier(Context *context, GLbitfield barriers);
+bool ValidateMemoryBarrierByRegion(Context *context, GLbitfield barriers);
+
+bool ValidateSampleMaski(Context *context, GLuint maskNumber, GLbitfield mask);
+
+} // namespace gl
+
+#endif // LIBANGLE_VALIDATION_ES31_H_
diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp
index f28f40fcf5..efe0b0c124 100644
--- a/src/3rdparty/angle/src/libEGL/libEGL.cpp
+++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp
@@ -288,4 +288,121 @@ __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress(const cha
return egl::GetProcAddress(procname);
}
+EGLStreamKHR EGLAPIENTRY eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
+{
+ return egl::CreateStreamKHR(dpy, attrib_list);
+}
+
+EGLBoolean EGLAPIENTRY eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
+{
+ return egl::DestroyStreamKHR(dpy, stream);
+}
+
+EGLBoolean EGLAPIENTRY eglStreamAttribKHR(EGLDisplay dpy,
+ EGLStreamKHR stream,
+ EGLenum attribute,
+ EGLint value)
+{
+ return egl::StreamAttribKHR(dpy, stream, attribute, value);
+}
+
+EGLBoolean EGLAPIENTRY eglQueryStreamKHR(EGLDisplay dpy,
+ EGLStreamKHR stream,
+ EGLenum attribute,
+ EGLint *value)
+{
+ return egl::QueryStreamKHR(dpy, stream, attribute, value);
+}
+
+EGLBoolean EGLAPIENTRY eglQueryStreamu64KHR(EGLDisplay dpy,
+ EGLStreamKHR stream,
+ EGLenum attribute,
+ EGLuint64KHR *value)
+{
+ return egl::QueryStreamu64KHR(dpy, stream, attribute, value);
+}
+
+EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy, EGLStreamKHR stream)
+{
+ return egl::StreamConsumerGLTextureExternalKHR(dpy, stream);
+}
+
+EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireKHR(EGLDisplay dpy, EGLStreamKHR stream)
+{
+ return egl::StreamConsumerAcquireKHR(dpy, stream);
+}
+
+EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseKHR(EGLDisplay dpy, EGLStreamKHR stream)
+{
+ return egl::StreamConsumerReleaseKHR(dpy, stream);
+}
+
+EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalAttribsNV(EGLDisplay dpy,
+ EGLStreamKHR stream,
+ EGLAttrib *attrib_list)
+{
+ return egl::StreamConsumerGLTextureExternalAttribsNV(dpy, stream, attrib_list);
}
+
+EGLBoolean EGLAPIENTRY eglCreateStreamProducerD3DTextureNV12ANGLE(EGLDisplay dpy,
+ EGLStreamKHR stream,
+ const EGLAttrib *attrib_list)
+{
+ return egl::CreateStreamProducerD3DTextureNV12ANGLE(dpy, stream, attrib_list);
+}
+
+EGLBoolean EGLAPIENTRY eglStreamPostD3DTextureNV12ANGLE(EGLDisplay dpy,
+ EGLStreamKHR stream,
+ void *texture,
+ const EGLAttrib *attrib_list)
+{
+ return egl::StreamPostD3DTextureNV12ANGLE(dpy, stream, texture, attrib_list);
+}
+
+EGLBoolean EGLAPIENTRY eglGetSyncValuesCHROMIUM(EGLDisplay dpy,
+ EGLSurface surface,
+ EGLuint64KHR *ust,
+ EGLuint64KHR *msc,
+ EGLuint64KHR *sbc)
+{
+ return egl::GetSyncValuesCHROMIUM(dpy, surface, ust, msc, sbc);
+}
+
+EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageEXT(EGLDisplay dpy,
+ EGLSurface surface,
+ EGLint *rects,
+ EGLint n_rects)
+{
+ return egl::SwapBuffersWithDamageEXT(dpy, surface, rects, n_rects);
+}
+
+EGLint EGLAPIENTRY eglProgramCacheGetAttribANGLE(EGLDisplay dpy, EGLenum attrib)
+{
+ return egl::ProgramCacheGetAttribANGLE(dpy, attrib);
+}
+
+void EGLAPIENTRY eglProgramCacheQueryANGLE(EGLDisplay dpy,
+ EGLint index,
+ void *key,
+ EGLint *keysize,
+ void *binary,
+ EGLint *binarysize)
+{
+ egl::ProgramCacheQueryANGLE(dpy, index, key, keysize, binary, binarysize);
+}
+
+void EGLAPIENTRY eglProgramCachePopulateANGLE(EGLDisplay dpy,
+ const void *key,
+ EGLint keysize,
+ const void *binary,
+ EGLint binarysize)
+{
+ egl::ProgramCachePopulateANGLE(dpy, key, keysize, binary, binarysize);
+}
+
+EGLint EGLAPIENTRY eglProgramCacheResizeANGLE(EGLDisplay dpy, EGLint limit, EGLenum mode)
+{
+ return egl::ProgramCacheResizeANGLE(dpy, limit, mode);
+}
+
+} // extern "C"
diff --git a/src/3rdparty/angle/src/libEGL/libEGL.def b/src/3rdparty/angle/src/libEGL/libEGL.def
index 74b7c2ae14..e68d27295e 100644
--- a/src/3rdparty/angle/src/libEGL/libEGL.def
+++ b/src/3rdparty/angle/src/libEGL/libEGL.def
@@ -1,60 +1,77 @@
LIBRARY libEGL
EXPORTS
- eglBindAPI @14
- eglBindTexImage @20
- eglChooseConfig @7
- eglCopyBuffers @33
- eglCreateContext @23
- eglCreatePbufferFromClientBuffer @18
- eglCreatePbufferSurface @10
- eglCreatePixmapSurface @11
- eglCreateWindowSurface @9
- eglDestroyContext @24
- eglDestroySurface @12
- eglGetConfigAttrib @8
- eglGetConfigs @6
- eglGetCurrentContext @26
- eglGetCurrentDisplay @28
- eglGetCurrentSurface @27
- eglGetDisplay @2
- eglGetError @1
- eglGetProcAddress @34
- eglInitialize @3
- eglMakeCurrent @25
- eglQueryAPI @15
- eglQueryContext @29
- eglQueryString @5
- eglQuerySurface @13
- eglReleaseTexImage @21
- eglReleaseThread @17
- eglSurfaceAttrib @19
- eglSwapBuffers @32
- eglSwapInterval @22
- eglTerminate @4
- eglWaitClient @16
- eglWaitGL @30
- eglWaitNative @31
+ eglBindAPI @14
+ eglBindTexImage @20
+ eglChooseConfig @7
+ eglCopyBuffers @33
+ eglCreateContext @23
+ eglCreatePbufferFromClientBuffer @18
+ eglCreatePbufferSurface @10
+ eglCreatePixmapSurface @11
+ eglCreateWindowSurface @9
+ eglDestroyContext @24
+ eglDestroySurface @12
+ eglGetConfigAttrib @8
+ eglGetConfigs @6
+ eglGetCurrentContext @26
+ eglGetCurrentDisplay @28
+ eglGetCurrentSurface @27
+ eglGetDisplay @2
+ eglGetError @1
+ eglGetProcAddress @34
+ eglInitialize @3
+ eglMakeCurrent @25
+ eglQueryAPI @15
+ eglQueryContext @29
+ eglQueryString @5
+ eglQuerySurface @13
+ eglReleaseTexImage @21
+ eglReleaseThread @17
+ eglSurfaceAttrib @19
+ eglSwapBuffers @32
+ eglSwapInterval @22
+ eglTerminate @4
+ eglWaitClient @16
+ eglWaitGL @30
+ eglWaitNative @31
; Extensions
- eglGetPlatformDisplayEXT @35
- eglQuerySurfacePointerANGLE @36
- eglPostSubBufferNV @37
- eglQueryDisplayAttribEXT @48
- eglQueryDeviceAttribEXT @49
- eglQueryDeviceStringEXT @50
- eglCreateImageKHR @51
- eglDestroyImageKHR @52
- eglCreateDeviceANGLE @53
- eglReleaseDeviceANGLE @54
+ eglGetPlatformDisplayEXT @35
+ eglQuerySurfacePointerANGLE @36
+ eglPostSubBufferNV @37
+ eglQueryDisplayAttribEXT @48
+ eglQueryDeviceAttribEXT @49
+ eglQueryDeviceStringEXT @50
+ eglCreateImageKHR @51
+ eglDestroyImageKHR @52
+ eglCreateDeviceANGLE @53
+ eglReleaseDeviceANGLE @54
+ eglCreateStreamKHR @55
+ eglDestroyStreamKHR @56
+ eglStreamAttribKHR @57
+ eglQueryStreamKHR @58
+ eglQueryStreamu64KHR @59
+ eglStreamConsumerGLTextureExternalKHR @60
+ eglStreamConsumerAcquireKHR @61
+ eglStreamConsumerReleaseKHR @62
+ eglStreamConsumerGLTextureExternalAttribsNV @63
+ eglCreateStreamProducerD3DTextureNV12ANGLE @64
+ eglStreamPostD3DTextureNV12ANGLE @65
+ eglGetSyncValuesCHROMIUM @66
+ eglSwapBuffersWithDamageEXT @67
+ eglProgramCacheGetAttribANGLE @68
+ eglProgramCachePopulateANGLE @69
+ eglProgramCacheQueryANGLE @70
+ eglProgramCacheResizeANGLE @71
; 1.5 entry points
- eglCreateSync @38
- eglDestroySync @39
- eglClientWaitSync @40
- eglGetSyncAttrib @41
- eglCreateImage @42
- eglDestroyImage @43
- eglGetPlatformDisplay @44
- eglCreatePlatformWindowSurface @45
- eglCreatePlatformPixmapSurface @46
- eglWaitSync @47
+ eglCreateSync @38
+ eglDestroySync @39
+ eglClientWaitSync @40
+ eglGetSyncAttrib @41
+ eglCreateImage @42
+ eglDestroyImage @43
+ eglGetPlatformDisplay @44
+ eglCreatePlatformWindowSurface @45
+ eglCreatePlatformPixmapSurface @46
+ eglWaitSync @47
diff --git a/src/3rdparty/angle/src/libEGL/libEGL_mingw32.def b/src/3rdparty/angle/src/libEGL/libEGL_mingw32.def
index d8fcf51620..e68d27295e 100644
--- a/src/3rdparty/angle/src/libEGL/libEGL_mingw32.def
+++ b/src/3rdparty/angle/src/libEGL/libEGL_mingw32.def
@@ -1,60 +1,77 @@
LIBRARY libEGL
EXPORTS
- eglBindAPI@4 @14
- eglBindTexImage@12 @20
- eglChooseConfig@20 @7
- eglCopyBuffers@12 @33
- eglCreateContext@16 @23
- eglCreatePbufferFromClientBuffer@20 @18
- eglCreatePbufferSurface@12 @10
- eglCreatePixmapSurface@16 @11
- eglCreateWindowSurface@16 @9
- eglDestroyContext@8 @24
- eglDestroySurface@8 @12
- eglGetConfigAttrib@16 @8
- eglGetConfigs@16 @6
- eglGetCurrentContext@0 @26
- eglGetCurrentDisplay@0 @28
- eglGetCurrentSurface@4 @27
- eglGetDisplay@4 @2
- eglGetError@0 @1
- eglGetProcAddress@4 @34
- eglInitialize@12 @3
- eglMakeCurrent@16 @25
- eglQueryAPI@0 @15
- eglQueryContext@16 @29
- eglQueryString@8 @5
- eglQuerySurface@16 @13
- eglReleaseTexImage@12 @21
- eglReleaseThread@0 @17
- eglSurfaceAttrib@16 @19
- eglSwapBuffers@8 @32
- eglSwapInterval@8 @22
- eglTerminate@4 @4
- eglWaitClient@0 @16
- eglWaitGL@0 @30
- eglWaitNative@4 @31
+ eglBindAPI @14
+ eglBindTexImage @20
+ eglChooseConfig @7
+ eglCopyBuffers @33
+ eglCreateContext @23
+ eglCreatePbufferFromClientBuffer @18
+ eglCreatePbufferSurface @10
+ eglCreatePixmapSurface @11
+ eglCreateWindowSurface @9
+ eglDestroyContext @24
+ eglDestroySurface @12
+ eglGetConfigAttrib @8
+ eglGetConfigs @6
+ eglGetCurrentContext @26
+ eglGetCurrentDisplay @28
+ eglGetCurrentSurface @27
+ eglGetDisplay @2
+ eglGetError @1
+ eglGetProcAddress @34
+ eglInitialize @3
+ eglMakeCurrent @25
+ eglQueryAPI @15
+ eglQueryContext @29
+ eglQueryString @5
+ eglQuerySurface @13
+ eglReleaseTexImage @21
+ eglReleaseThread @17
+ eglSurfaceAttrib @19
+ eglSwapBuffers @32
+ eglSwapInterval @22
+ eglTerminate @4
+ eglWaitClient @16
+ eglWaitGL @30
+ eglWaitNative @31
; Extensions
- eglGetPlatformDisplayEXT@12 @35
- eglQuerySurfacePointerANGLE@16 @36
- eglPostSubBufferNV@24 @37
- eglQueryDisplayAttribEXT@12 @48
- eglQueryDeviceAttribEXT@12 @49
- eglQueryDeviceStringEXT@8 @50
- eglCreateImageKHR@20 @51
- eglDestroyImageKHR@8 @52
- eglCreateDeviceANGLE@12 @53
- eglReleaseDeviceANGLE@4 @54
+ eglGetPlatformDisplayEXT @35
+ eglQuerySurfacePointerANGLE @36
+ eglPostSubBufferNV @37
+ eglQueryDisplayAttribEXT @48
+ eglQueryDeviceAttribEXT @49
+ eglQueryDeviceStringEXT @50
+ eglCreateImageKHR @51
+ eglDestroyImageKHR @52
+ eglCreateDeviceANGLE @53
+ eglReleaseDeviceANGLE @54
+ eglCreateStreamKHR @55
+ eglDestroyStreamKHR @56
+ eglStreamAttribKHR @57
+ eglQueryStreamKHR @58
+ eglQueryStreamu64KHR @59
+ eglStreamConsumerGLTextureExternalKHR @60
+ eglStreamConsumerAcquireKHR @61
+ eglStreamConsumerReleaseKHR @62
+ eglStreamConsumerGLTextureExternalAttribsNV @63
+ eglCreateStreamProducerD3DTextureNV12ANGLE @64
+ eglStreamPostD3DTextureNV12ANGLE @65
+ eglGetSyncValuesCHROMIUM @66
+ eglSwapBuffersWithDamageEXT @67
+ eglProgramCacheGetAttribANGLE @68
+ eglProgramCachePopulateANGLE @69
+ eglProgramCacheQueryANGLE @70
+ eglProgramCacheResizeANGLE @71
; 1.5 entry points
- eglCreateSync @38
- eglDestroySync @39
- eglClientWaitSync @40
- eglGetSyncAttrib @41
- eglCreateImage @42
- eglDestroyImage @43
- eglGetPlatformDisplay @44
- eglCreatePlatformWindowSurface @45
- eglCreatePlatformPixmapSurface @46
- eglWaitSync @47
+ eglCreateSync @38
+ eglDestroySync @39
+ eglClientWaitSync @40
+ eglGetSyncAttrib @41
+ eglCreateImage @42
+ eglDestroyImage @43
+ eglGetPlatformDisplay @44
+ eglCreatePlatformWindowSurface @45
+ eglCreatePlatformPixmapSurface @46
+ eglWaitSync @47
diff --git a/src/3rdparty/angle/src/libEGL/libEGLd.def b/src/3rdparty/angle/src/libEGL/libEGLd.def
index 318e04cfa6..e6a8b1bac7 100644
--- a/src/3rdparty/angle/src/libEGL/libEGLd.def
+++ b/src/3rdparty/angle/src/libEGL/libEGLd.def
@@ -1,60 +1,77 @@
LIBRARY libEGLd
EXPORTS
- eglBindAPI @14
- eglBindTexImage @20
- eglChooseConfig @7
- eglCopyBuffers @33
- eglCreateContext @23
- eglCreatePbufferFromClientBuffer @18
- eglCreatePbufferSurface @10
- eglCreatePixmapSurface @11
- eglCreateWindowSurface @9
- eglDestroyContext @24
- eglDestroySurface @12
- eglGetConfigAttrib @8
- eglGetConfigs @6
- eglGetCurrentContext @26
- eglGetCurrentDisplay @28
- eglGetCurrentSurface @27
- eglGetDisplay @2
- eglGetError @1
- eglGetProcAddress @34
- eglInitialize @3
- eglMakeCurrent @25
- eglQueryAPI @15
- eglQueryContext @29
- eglQueryString @5
- eglQuerySurface @13
- eglReleaseTexImage @21
- eglReleaseThread @17
- eglSurfaceAttrib @19
- eglSwapBuffers @32
- eglSwapInterval @22
- eglTerminate @4
- eglWaitClient @16
- eglWaitGL @30
- eglWaitNative @31
+ eglBindAPI @14
+ eglBindTexImage @20
+ eglChooseConfig @7
+ eglCopyBuffers @33
+ eglCreateContext @23
+ eglCreatePbufferFromClientBuffer @18
+ eglCreatePbufferSurface @10
+ eglCreatePixmapSurface @11
+ eglCreateWindowSurface @9
+ eglDestroyContext @24
+ eglDestroySurface @12
+ eglGetConfigAttrib @8
+ eglGetConfigs @6
+ eglGetCurrentContext @26
+ eglGetCurrentDisplay @28
+ eglGetCurrentSurface @27
+ eglGetDisplay @2
+ eglGetError @1
+ eglGetProcAddress @34
+ eglInitialize @3
+ eglMakeCurrent @25
+ eglQueryAPI @15
+ eglQueryContext @29
+ eglQueryString @5
+ eglQuerySurface @13
+ eglReleaseTexImage @21
+ eglReleaseThread @17
+ eglSurfaceAttrib @19
+ eglSwapBuffers @32
+ eglSwapInterval @22
+ eglTerminate @4
+ eglWaitClient @16
+ eglWaitGL @30
+ eglWaitNative @31
; Extensions
- eglGetPlatformDisplayEXT @35
- eglQuerySurfacePointerANGLE @36
- eglPostSubBufferNV @37
- eglQueryDisplayAttribEXT @48
- eglQueryDeviceAttribEXT @49
- eglQueryDeviceStringEXT @50
- eglCreateImageKHR @51
- eglDestroyImageKHR @52
- eglCreateDeviceANGLE @53
- eglReleaseDeviceANGLE @54
+ eglGetPlatformDisplayEXT @35
+ eglQuerySurfacePointerANGLE @36
+ eglPostSubBufferNV @37
+ eglQueryDisplayAttribEXT @48
+ eglQueryDeviceAttribEXT @49
+ eglQueryDeviceStringEXT @50
+ eglCreateImageKHR @51
+ eglDestroyImageKHR @52
+ eglCreateDeviceANGLE @53
+ eglReleaseDeviceANGLE @54
+ eglCreateStreamKHR @55
+ eglDestroyStreamKHR @56
+ eglStreamAttribKHR @57
+ eglQueryStreamKHR @58
+ eglQueryStreamu64KHR @59
+ eglStreamConsumerGLTextureExternalKHR @60
+ eglStreamConsumerAcquireKHR @61
+ eglStreamConsumerReleaseKHR @62
+ eglStreamConsumerGLTextureExternalAttribsNV @63
+ eglCreateStreamProducerD3DTextureNV12ANGLE @64
+ eglStreamPostD3DTextureNV12ANGLE @65
+ eglGetSyncValuesCHROMIUM @66
+ eglSwapBuffersWithDamageEXT @67
+ eglProgramCacheGetAttribANGLE @68
+ eglProgramCachePopulateANGLE @69
+ eglProgramCacheQueryANGLE @70
+ eglProgramCacheResizeANGLE @71
; 1.5 entry points
- eglCreateSync @38
- eglDestroySync @39
- eglClientWaitSync @40
- eglGetSyncAttrib @41
- eglCreateImage @42
- eglDestroyImage @43
- eglGetPlatformDisplay @44
- eglCreatePlatformWindowSurface @45
- eglCreatePlatformPixmapSurface @46
- eglWaitSync @47
+ eglCreateSync @38
+ eglDestroySync @39
+ eglClientWaitSync @40
+ eglGetSyncAttrib @41
+ eglCreateImage @42
+ eglDestroyImage @43
+ eglGetPlatformDisplay @44
+ eglCreatePlatformWindowSurface @45
+ eglCreatePlatformPixmapSurface @46
+ eglWaitSync @47
diff --git a/src/3rdparty/angle/src/libEGL/libEGLd_mingw32.def b/src/3rdparty/angle/src/libEGL/libEGLd_mingw32.def
index d322cf67de..e68d27295e 100644
--- a/src/3rdparty/angle/src/libEGL/libEGLd_mingw32.def
+++ b/src/3rdparty/angle/src/libEGL/libEGLd_mingw32.def
@@ -1,48 +1,77 @@
-LIBRARY libEGLd
+LIBRARY libEGL
EXPORTS
- eglBindAPI@4 @14
- eglBindTexImage@12 @20
- eglChooseConfig@20 @7
- eglCopyBuffers@12 @33
- eglCreateContext@16 @23
- eglCreatePbufferFromClientBuffer@20 @18
- eglCreatePbufferSurface@12 @10
- eglCreatePixmapSurface@16 @11
- eglCreateWindowSurface@16 @9
- eglDestroyContext@8 @24
- eglDestroySurface@8 @12
- eglGetConfigAttrib@16 @8
- eglGetConfigs@16 @6
- eglGetCurrentContext@0 @26
- eglGetCurrentDisplay@0 @28
- eglGetCurrentSurface@4 @27
- eglGetDisplay@4 @2
- eglGetError@0 @1
- eglGetProcAddress@4 @34
- eglInitialize@12 @3
- eglMakeCurrent@16 @25
- eglQueryAPI@0 @15
- eglQueryContext@16 @29
- eglQueryString@8 @5
- eglQuerySurface@16 @13
- eglReleaseTexImage@12 @21
- eglReleaseThread@0 @17
- eglSurfaceAttrib@16 @19
- eglSwapBuffers@8 @32
- eglSwapInterval@8 @22
- eglTerminate@4 @4
- eglWaitClient@0 @16
- eglWaitGL@0 @30
- eglWaitNative@4 @31
+ eglBindAPI @14
+ eglBindTexImage @20
+ eglChooseConfig @7
+ eglCopyBuffers @33
+ eglCreateContext @23
+ eglCreatePbufferFromClientBuffer @18
+ eglCreatePbufferSurface @10
+ eglCreatePixmapSurface @11
+ eglCreateWindowSurface @9
+ eglDestroyContext @24
+ eglDestroySurface @12
+ eglGetConfigAttrib @8
+ eglGetConfigs @6
+ eglGetCurrentContext @26
+ eglGetCurrentDisplay @28
+ eglGetCurrentSurface @27
+ eglGetDisplay @2
+ eglGetError @1
+ eglGetProcAddress @34
+ eglInitialize @3
+ eglMakeCurrent @25
+ eglQueryAPI @15
+ eglQueryContext @29
+ eglQueryString @5
+ eglQuerySurface @13
+ eglReleaseTexImage @21
+ eglReleaseThread @17
+ eglSurfaceAttrib @19
+ eglSwapBuffers @32
+ eglSwapInterval @22
+ eglTerminate @4
+ eglWaitClient @16
+ eglWaitGL @30
+ eglWaitNative @31
; Extensions
- eglGetPlatformDisplayEXT@12 @35
- eglQuerySurfacePointerANGLE@16 @36
- eglPostSubBufferNV@24 @37
- eglQueryDisplayAttribEXT@12 @48
- eglQueryDeviceAttribEXT@12 @49
- eglQueryDeviceStringEXT@8 @50
- eglCreateImageKHR@20 @51
- eglDestroyImageKHR@8 @52
- eglCreateDeviceANGLE@12 @53
- eglReleaseDeviceANGLE@4 @54
+ eglGetPlatformDisplayEXT @35
+ eglQuerySurfacePointerANGLE @36
+ eglPostSubBufferNV @37
+ eglQueryDisplayAttribEXT @48
+ eglQueryDeviceAttribEXT @49
+ eglQueryDeviceStringEXT @50
+ eglCreateImageKHR @51
+ eglDestroyImageKHR @52
+ eglCreateDeviceANGLE @53
+ eglReleaseDeviceANGLE @54
+ eglCreateStreamKHR @55
+ eglDestroyStreamKHR @56
+ eglStreamAttribKHR @57
+ eglQueryStreamKHR @58
+ eglQueryStreamu64KHR @59
+ eglStreamConsumerGLTextureExternalKHR @60
+ eglStreamConsumerAcquireKHR @61
+ eglStreamConsumerReleaseKHR @62
+ eglStreamConsumerGLTextureExternalAttribsNV @63
+ eglCreateStreamProducerD3DTextureNV12ANGLE @64
+ eglStreamPostD3DTextureNV12ANGLE @65
+ eglGetSyncValuesCHROMIUM @66
+ eglSwapBuffersWithDamageEXT @67
+ eglProgramCacheGetAttribANGLE @68
+ eglProgramCachePopulateANGLE @69
+ eglProgramCacheQueryANGLE @70
+ eglProgramCacheResizeANGLE @71
+
+ ; 1.5 entry points
+ eglCreateSync @38
+ eglDestroySync @39
+ eglClientWaitSync @40
+ eglGetSyncAttrib @41
+ eglCreateImage @42
+ eglDestroyImage @43
+ eglGetPlatformDisplay @44
+ eglCreatePlatformWindowSurface @45
+ eglCreatePlatformPixmapSurface @46
+ eglWaitSync @47
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_egl.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_egl.cpp
index 6f9770c57c..97546ee900 100644
--- a/src/3rdparty/angle/src/libGLESv2/entry_points_egl.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_egl.cpp
@@ -7,33 +7,59 @@
// entry_points_egl.cpp : Implements the EGL entry points.
#include "libGLESv2/entry_points_egl.h"
-#include "libGLESv2/entry_points_egl_ext.h"
-#include "libGLESv2/entry_points_gles_2_0.h"
-#include "libGLESv2/entry_points_gles_2_0_ext.h"
-#include "libGLESv2/entry_points_gles_3_0.h"
-#include "libGLESv2/global_state.h"
+#include "common/debug.h"
+#include "common/version.h"
#include "libANGLE/Context.h"
#include "libANGLE/Display.h"
-#include "libANGLE/Texture.h"
#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Thread.h"
+#include "libANGLE/queryutils.h"
#include "libANGLE/validationEGL.h"
-
-#include "common/debug.h"
-#include "common/version.h"
+#include "libGLESv2/global_state.h"
+#include "libGLESv2/proc_table.h"
#include <EGL/eglext.h>
namespace egl
{
+namespace
+{
+
+bool CompareProc(const ProcEntry &a, const char *b)
+{
+ return strcmp(a.first, b) < 0;
+}
+
+void ClipConfigs(const std::vector<const Config *> &filteredConfigs,
+ EGLConfig *output_configs,
+ EGLint config_size,
+ EGLint *num_config)
+{
+ EGLint result_size = static_cast<EGLint>(filteredConfigs.size());
+ if (output_configs)
+ {
+ result_size = std::max(std::min(result_size, config_size), 0);
+ for (EGLint i = 0; i < result_size; i++)
+ {
+ output_configs[i] = const_cast<Config *>(filteredConfigs[i]);
+ }
+ }
+ *num_config = result_size;
+}
+
+} // anonymous namespace
+
// EGL 1.0
EGLint EGLAPIENTRY GetError(void)
{
EVENT("()");
+ Thread *thread = GetCurrentThread();
- EGLint error = GetGlobalError();
- SetGlobalError(Error(EGL_SUCCESS));
+ EGLint error = thread->getError();
+ thread->setError(NoError());
return error;
}
@@ -41,445 +67,367 @@ EGLDisplay EGLAPIENTRY GetDisplay(EGLNativeDisplayType display_id)
{
EVENT("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id);
- return Display::GetDisplayFromAttribs(reinterpret_cast<void *>(display_id), AttributeMap());
+ return Display::GetDisplayFromNativeDisplay(display_id, AttributeMap());
}
EGLBoolean EGLAPIENTRY Initialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint *major = 0x%0.8p, EGLint *minor = 0x%0.8p)",
- dpy, major, minor);
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint *major = 0x%0.8p, EGLint *minor = 0x%0.8p)", dpy,
+ major, minor);
+ Thread *thread = GetCurrentThread();
Display *display = static_cast<Display *>(dpy);
if (dpy == EGL_NO_DISPLAY || !Display::isValidDisplay(display))
{
- SetGlobalError(Error(EGL_BAD_DISPLAY));
+ thread->setError(EglBadDisplay());
return EGL_FALSE;
}
Error error = display->initialize();
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
- if (major) *major = 1;
- if (minor) *minor = 4;
+ if (major)
+ *major = 1;
+ if (minor)
+ *minor = 4;
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return EGL_TRUE;
}
EGLBoolean EGLAPIENTRY Terminate(EGLDisplay dpy)
{
EVENT("(EGLDisplay dpy = 0x%0.8p)", dpy);
+ Thread *thread = GetCurrentThread();
Display *display = static_cast<Display *>(dpy);
if (dpy == EGL_NO_DISPLAY || !Display::isValidDisplay(display))
{
- SetGlobalError(Error(EGL_BAD_DISPLAY));
+ thread->setError(EglBadDisplay());
return EGL_FALSE;
}
- gl::Context *context = GetGlobalContext();
-
- if (display->isValidContext(context))
+ if (display->isValidContext(thread->getContext()))
{
- SetGlobalContext(NULL);
- SetGlobalDisplay(NULL);
+ thread->setCurrent(nullptr);
}
- display->terminate();
+ Error error = display->terminate();
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_FALSE;
+ }
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return EGL_TRUE;
}
const char *EGLAPIENTRY QueryString(EGLDisplay dpy, EGLint name)
{
EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint name = %d)", dpy, name);
+ Thread *thread = GetCurrentThread();
- Display *display = static_cast<Display*>(dpy);
+ Display *display = static_cast<Display *>(dpy);
if (!(display == EGL_NO_DISPLAY && name == EGL_EXTENSIONS))
{
Error error = ValidateDisplay(display);
if (error.isError())
{
- SetGlobalError(error);
- return NULL;
+ thread->setError(error);
+ return nullptr;
}
}
const char *result;
switch (name)
{
- case EGL_CLIENT_APIS:
- result = "OpenGL_ES";
- break;
- case EGL_EXTENSIONS:
- if (display == EGL_NO_DISPLAY)
- {
- result = Display::getClientExtensionString().c_str();
- }
- else
- {
- result = display->getExtensionString().c_str();
- }
- break;
- case EGL_VENDOR:
- result = display->getVendorString().c_str();
- break;
- case EGL_VERSION:
- result = "1.4 (ANGLE " ANGLE_VERSION_STRING ")";
- break;
- default:
- SetGlobalError(Error(EGL_BAD_PARAMETER));
- return NULL;
- }
-
- SetGlobalError(Error(EGL_SUCCESS));
+ case EGL_CLIENT_APIS:
+ result = "OpenGL_ES";
+ break;
+ case EGL_EXTENSIONS:
+ if (display == EGL_NO_DISPLAY)
+ {
+ result = Display::GetClientExtensionString().c_str();
+ }
+ else
+ {
+ result = display->getExtensionString().c_str();
+ }
+ break;
+ case EGL_VENDOR:
+ result = display->getVendorString().c_str();
+ break;
+ case EGL_VERSION:
+ result = "1.4 (ANGLE " ANGLE_VERSION_STRING ")";
+ break;
+ default:
+ thread->setError(EglBadParameter());
+ return nullptr;
+ }
+
+ thread->setError(NoError());
return result;
}
-EGLBoolean EGLAPIENTRY GetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
+EGLBoolean EGLAPIENTRY GetConfigs(EGLDisplay dpy,
+ EGLConfig *configs,
+ EGLint config_size,
+ EGLint *num_config)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig *configs = 0x%0.8p, "
- "EGLint config_size = %d, EGLint *num_config = 0x%0.8p)",
- dpy, configs, config_size, num_config);
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLConfig *configs = 0x%0.8p, "
+ "EGLint config_size = %d, EGLint *num_config = 0x%0.8p)",
+ dpy, configs, config_size, num_config);
+ Thread *thread = GetCurrentThread();
- Display *display = static_cast<Display*>(dpy);
+ Display *display = static_cast<Display *>(dpy);
- Error error = ValidateDisplay(display);
+ Error error = ValidateGetConfigs(display, config_size, num_config);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
- if (!num_config)
- {
- SetGlobalError(Error(EGL_BAD_PARAMETER));
- return EGL_FALSE;
- }
+ ClipConfigs(display->getConfigs(AttributeMap()), configs, config_size, num_config);
- std::vector<const Config*> filteredConfigs = display->getConfigs(AttributeMap());
- if (configs)
- {
- filteredConfigs.resize(std::min<size_t>(filteredConfigs.size(), config_size));
- for (size_t i = 0; i < filteredConfigs.size(); i++)
- {
- configs[i] = const_cast<Config*>(filteredConfigs[i]);
- }
- }
- *num_config = static_cast<EGLint>(filteredConfigs.size());
-
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return EGL_TRUE;
}
-EGLBoolean EGLAPIENTRY ChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
+EGLBoolean EGLAPIENTRY ChooseConfig(EGLDisplay dpy,
+ const EGLint *attrib_list,
+ EGLConfig *configs,
+ EGLint config_size,
+ EGLint *num_config)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p, "
- "EGLConfig *configs = 0x%0.8p, EGLint config_size = %d, EGLint *num_config = 0x%0.8p)",
- dpy, attrib_list, configs, config_size, num_config);
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p, "
+ "EGLConfig *configs = 0x%0.8p, EGLint config_size = %d, EGLint *num_config = 0x%0.8p)",
+ dpy, attrib_list, configs, config_size, num_config);
+ Thread *thread = GetCurrentThread();
- Display *display = static_cast<Display*>(dpy);
+ Display *display = static_cast<Display *>(dpy);
+ AttributeMap attribMap = AttributeMap::CreateFromIntArray(attrib_list);
- Error error = ValidateDisplay(display);
+ Error error = ValidateChooseConfig(display, attribMap, config_size, num_config);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
- if (!num_config)
- {
- SetGlobalError(Error(EGL_BAD_PARAMETER));
- return EGL_FALSE;
- }
-
- std::vector<const Config*> filteredConfigs = display->getConfigs(AttributeMap(attrib_list));
- if (configs)
- {
- filteredConfigs.resize(std::min<size_t>(filteredConfigs.size(), config_size));
- for (size_t i = 0; i < filteredConfigs.size(); i++)
- {
- configs[i] = const_cast<Config*>(filteredConfigs[i]);
- }
- }
- *num_config = static_cast<EGLint>(filteredConfigs.size());
+ ClipConfigs(display->getConfigs(attribMap), configs, config_size, num_config);
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return EGL_TRUE;
}
-EGLBoolean EGLAPIENTRY GetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
+EGLBoolean EGLAPIENTRY GetConfigAttrib(EGLDisplay dpy,
+ EGLConfig config,
+ EGLint attribute,
+ EGLint *value)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
- dpy, config, attribute, value);
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLint attribute = %d, EGLint "
+ "*value = 0x%0.8p)",
+ dpy, config, attribute, value);
+ Thread *thread = GetCurrentThread();
- Display *display = static_cast<Display*>(dpy);
- Config *configuration = static_cast<Config*>(config);
+ Display *display = static_cast<Display *>(dpy);
+ Config *configuration = static_cast<Config *>(config);
- Error error = ValidateConfig(display, configuration);
+ Error error = ValidateGetConfigAttrib(display, configuration, attribute);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
- if (!display->getConfigAttrib(configuration, attribute, value))
- {
- SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
- return EGL_FALSE;
- }
+ QueryConfigAttrib(configuration, attribute, value);
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return EGL_TRUE;
}
-EGLSurface EGLAPIENTRY CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
+EGLSurface EGLAPIENTRY CreateWindowSurface(EGLDisplay dpy,
+ EGLConfig config,
+ EGLNativeWindowType win,
+ const EGLint *attrib_list)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativeWindowType win = 0x%0.8p, "
- "const EGLint *attrib_list = 0x%0.8p)", dpy, config, win, attrib_list);
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativeWindowType win = 0x%0.8p, "
+ "const EGLint *attrib_list = 0x%0.8p)",
+ dpy, config, win, attrib_list);
+ Thread *thread = GetCurrentThread();
- Display *display = static_cast<Display*>(dpy);
- Config *configuration = static_cast<Config*>(config);
- AttributeMap attributes(attrib_list);
+ Display *display = static_cast<Display *>(dpy);
+ Config *configuration = static_cast<Config *>(config);
+ AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list);
Error error = ValidateCreateWindowSurface(display, configuration, win, attributes);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_NO_SURFACE;
}
egl::Surface *surface = nullptr;
- error = display->createWindowSurface(configuration, win, attributes, &surface);
+ error = display->createWindowSurface(configuration, win, attributes, &surface);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_NO_SURFACE;
}
return static_cast<EGLSurface>(surface);
}
-EGLSurface EGLAPIENTRY CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
+EGLSurface EGLAPIENTRY CreatePbufferSurface(EGLDisplay dpy,
+ EGLConfig config,
+ const EGLint *attrib_list)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",
- dpy, config, attrib_list);
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, const EGLint *attrib_list = "
+ "0x%0.8p)",
+ dpy, config, attrib_list);
+ Thread *thread = GetCurrentThread();
- Display *display = static_cast<Display*>(dpy);
- Config *configuration = static_cast<Config*>(config);
- AttributeMap attributes(attrib_list);
+ Display *display = static_cast<Display *>(dpy);
+ Config *configuration = static_cast<Config *>(config);
+ AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list);
Error error = ValidateCreatePbufferSurface(display, configuration, attributes);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_NO_SURFACE;
}
egl::Surface *surface = nullptr;
- error = display->createPbufferSurface(configuration, attributes, &surface);
+ error = display->createPbufferSurface(configuration, attributes, &surface);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_NO_SURFACE;
}
return static_cast<EGLSurface>(surface);
}
-EGLSurface EGLAPIENTRY CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
+EGLSurface EGLAPIENTRY CreatePixmapSurface(EGLDisplay dpy,
+ EGLConfig config,
+ EGLNativePixmapType pixmap,
+ const EGLint *attrib_list)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativePixmapType pixmap = 0x%0.8p, "
- "const EGLint *attrib_list = 0x%0.8p)", dpy, config, pixmap, attrib_list);
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativePixmapType pixmap = "
+ "0x%0.8p, "
+ "const EGLint *attrib_list = 0x%0.8p)",
+ dpy, config, pixmap, attrib_list);
+ Thread *thread = GetCurrentThread();
- Display *display = static_cast<Display*>(dpy);
- Config *configuration = static_cast<Config*>(config);
+ Display *display = static_cast<Display *>(dpy);
+ Config *configuration = static_cast<Config *>(config);
Error error = ValidateConfig(display, configuration);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_NO_SURFACE;
}
- UNIMPLEMENTED(); // FIXME
+ UNIMPLEMENTED(); // FIXME
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return EGL_NO_SURFACE;
}
EGLBoolean EGLAPIENTRY DestroySurface(EGLDisplay dpy, EGLSurface surface)
{
EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface);
+ Thread *thread = GetCurrentThread();
- Display *display = static_cast<Display*>(dpy);
- Surface *eglSurface = static_cast<Surface*>(surface);
+ Display *display = static_cast<Display *>(dpy);
+ Surface *eglSurface = static_cast<Surface *>(surface);
Error error = ValidateSurface(display, eglSurface);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
if (surface == EGL_NO_SURFACE)
{
- SetGlobalError(Error(EGL_BAD_SURFACE));
+ thread->setError(EglBadSurface());
return EGL_FALSE;
}
- display->destroySurface((Surface*)surface);
+ error = display->destroySurface(reinterpret_cast<Surface *>(surface));
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_FALSE;
+ }
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return EGL_TRUE;
}
-EGLBoolean EGLAPIENTRY QuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
+EGLBoolean EGLAPIENTRY QuerySurface(EGLDisplay dpy,
+ EGLSurface surface,
+ EGLint attribute,
+ EGLint *value)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
- dpy, surface, attribute, value);
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint "
+ "*value = 0x%0.8p)",
+ dpy, surface, attribute, value);
+ Thread *thread = GetCurrentThread();
- Display *display = static_cast<Display*>(dpy);
- Surface *eglSurface = (Surface*)surface;
+ const Display *display = static_cast<const Display *>(dpy);
+ const Surface *eglSurface = static_cast<const Surface *>(surface);
- Error error = ValidateSurface(display, eglSurface);
+ Error error = ValidateQuerySurface(display, eglSurface, attribute, value);
if (error.isError())
{
- SetGlobalError(error);
- return EGL_FALSE;
- }
-
- if (surface == EGL_NO_SURFACE)
- {
- SetGlobalError(Error(EGL_BAD_SURFACE));
+ thread->setError(error);
return EGL_FALSE;
}
- switch (attribute)
- {
- case EGL_VG_ALPHA_FORMAT:
- UNIMPLEMENTED(); // FIXME
- break;
- case EGL_VG_COLORSPACE:
- UNIMPLEMENTED(); // FIXME
- break;
- case EGL_CONFIG_ID:
- *value = eglSurface->getConfig()->configID;
- break;
- case EGL_HEIGHT:
- *value = eglSurface->getHeight();
- break;
- case EGL_HORIZONTAL_RESOLUTION:
- UNIMPLEMENTED(); // FIXME
- break;
- case EGL_LARGEST_PBUFFER:
- UNIMPLEMENTED(); // FIXME
- break;
- case EGL_MIPMAP_TEXTURE:
- UNIMPLEMENTED(); // FIXME
- break;
- case EGL_MIPMAP_LEVEL:
- UNIMPLEMENTED(); // FIXME
- break;
- case EGL_MULTISAMPLE_RESOLVE:
- UNIMPLEMENTED(); // FIXME
- break;
- case EGL_PIXEL_ASPECT_RATIO:
- *value = eglSurface->getPixelAspectRatio();
- break;
- case EGL_RENDER_BUFFER:
- *value = eglSurface->getRenderBuffer();
- break;
- case EGL_SWAP_BEHAVIOR:
- *value = eglSurface->getSwapBehavior();
- break;
- case EGL_TEXTURE_FORMAT:
- *value = eglSurface->getTextureFormat();
- break;
- case EGL_TEXTURE_TARGET:
- *value = eglSurface->getTextureTarget();
- break;
- case EGL_VERTICAL_RESOLUTION:
- UNIMPLEMENTED(); // FIXME
- break;
- case EGL_WIDTH:
- *value = eglSurface->getWidth();
- break;
- case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
- if (!display->getExtensions().postSubBuffer)
- {
- SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
- return EGL_FALSE;
- }
- *value = eglSurface->isPostSubBufferSupported();
- break;
- case EGL_FIXED_SIZE_ANGLE:
- if (!display->getExtensions().windowFixedSize)
- {
- SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
- return EGL_FALSE;
- }
- *value = eglSurface->isFixedSize();
- break;
- case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
- if (!display->getExtensions().flexibleSurfaceCompatibility)
- {
- SetGlobalError(
- Error(EGL_BAD_ATTRIBUTE,
- "EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE cannot be used without "
- "EGL_ANGLE_flexible_surface_compatibility support."));
- return EGL_FALSE;
- }
- *value = eglSurface->flexibleSurfaceCompatibilityRequested();
- break;
- case EGL_SURFACE_ORIENTATION_ANGLE:
- if (!display->getExtensions().surfaceOrientation)
- {
- SetGlobalError(Error(EGL_BAD_ATTRIBUTE,
- "EGL_SURFACE_ORIENTATION_ANGLE cannot be queried without "
- "EGL_ANGLE_surface_orientation support."));
- return EGL_FALSE;
- }
- *value = eglSurface->getOrientation();
- break;
- case EGL_DIRECT_COMPOSITION_ANGLE:
- if (!display->getExtensions().directComposition)
- {
- SetGlobalError(Error(EGL_BAD_ATTRIBUTE,
- "EGL_DIRECT_COMPOSITION_ANGLE cannot be used without "
- "EGL_ANGLE_direct_composition support."));
- return EGL_FALSE;
- }
- *value = eglSurface->directComposition();
- break;
- default:
- SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
- return EGL_FALSE;
- }
+ QuerySurfaceAttrib(eglSurface, attribute, value);
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return EGL_TRUE;
}
-EGLContext EGLAPIENTRY CreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
+EGLContext EGLAPIENTRY CreateContext(EGLDisplay dpy,
+ EGLConfig config,
+ EGLContext share_context,
+ const EGLint *attrib_list)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLContext share_context = 0x%0.8p, "
- "const EGLint *attrib_list = 0x%0.8p)", dpy, config, share_context, attrib_list);
-
- Display *display = static_cast<Display*>(dpy);
- Config *configuration = static_cast<Config*>(config);
- gl::Context* sharedGLContext = static_cast<gl::Context*>(share_context);
- AttributeMap attributes(attrib_list);
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLContext share_context = "
+ "0x%0.8p, "
+ "const EGLint *attrib_list = 0x%0.8p)",
+ dpy, config, share_context, attrib_list);
+ Thread *thread = GetCurrentThread();
+
+ Display *display = static_cast<Display *>(dpy);
+ Config *configuration = static_cast<Config *>(config);
+ gl::Context *sharedGLContext = static_cast<gl::Context *>(share_context);
+ AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list);
Error error = ValidateCreateContext(display, configuration, sharedGLContext, attributes);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_NO_CONTEXT;
}
@@ -487,208 +435,115 @@ EGLContext EGLAPIENTRY CreateContext(EGLDisplay dpy, EGLConfig config, EGLContex
error = display->createContext(configuration, sharedGLContext, attributes, &context);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_NO_CONTEXT;
}
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return static_cast<EGLContext>(context);
}
EGLBoolean EGLAPIENTRY DestroyContext(EGLDisplay dpy, EGLContext ctx)
{
EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p)", dpy, ctx);
+ Thread *thread = GetCurrentThread();
- Display *display = static_cast<Display*>(dpy);
- gl::Context *context = static_cast<gl::Context*>(ctx);
+ Display *display = static_cast<Display *>(dpy);
+ gl::Context *context = static_cast<gl::Context *>(ctx);
Error error = ValidateContext(display, context);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
if (ctx == EGL_NO_CONTEXT)
{
- SetGlobalError(Error(EGL_BAD_CONTEXT));
+ thread->setError(EglBadContext());
return EGL_FALSE;
}
- if (context == GetGlobalContext())
+ if (context == thread->getContext())
{
- SetGlobalDisplay(NULL);
- SetGlobalContext(NULL);
+ thread->setCurrent(nullptr);
}
- display->destroyContext(context);
+ error = display->destroyContext(context);
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_FALSE;
+ }
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return EGL_TRUE;
}
EGLBoolean EGLAPIENTRY MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface draw = 0x%0.8p, EGLSurface read = 0x%0.8p, EGLContext ctx = 0x%0.8p)",
- dpy, draw, read, ctx);
-
- Display *display = static_cast<Display*>(dpy);
- gl::Context *context = static_cast<gl::Context*>(ctx);
-
- // If ctx is EGL_NO_CONTEXT and either draw or read are not EGL_NO_SURFACE, an EGL_BAD_MATCH
- // error is generated.
- if (ctx == EGL_NO_CONTEXT && (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
- {
- SetGlobalError(Error(EGL_BAD_MATCH));
- return EGL_FALSE;
- }
-
- if (ctx != EGL_NO_CONTEXT && draw == EGL_NO_SURFACE && read == EGL_NO_SURFACE)
- {
- SetGlobalError(Error(EGL_BAD_MATCH));
- return EGL_FALSE;
- }
-
- // If either of draw or read is a valid surface and the other is EGL_NO_SURFACE, an
- // EGL_BAD_MATCH error is generated.
- if ((read == EGL_NO_SURFACE) != (draw == EGL_NO_SURFACE))
- {
- SetGlobalError(Error(
- EGL_BAD_MATCH, "read and draw must both be valid surfaces, or both be EGL_NO_SURFACE"));
- return EGL_FALSE;
- }
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLSurface draw = 0x%0.8p, EGLSurface read = 0x%0.8p, "
+ "EGLContext ctx = 0x%0.8p)",
+ dpy, draw, read, ctx);
+ Thread *thread = GetCurrentThread();
- if (dpy == EGL_NO_DISPLAY || !Display::isValidDisplay(display))
- {
- SetGlobalError(Error(EGL_BAD_DISPLAY, "'dpy' not a valid EGLDisplay handle"));
- return EGL_FALSE;
- }
+ Display *display = static_cast<Display *>(dpy);
+ gl::Context *context = static_cast<gl::Context *>(ctx);
- // EGL 1.5 spec: dpy can be uninitialized if all other parameters are null
- if (!display->isInitialized() && (ctx != EGL_NO_CONTEXT || draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
+ Error error = ValidateMakeCurrent(display, draw, read, context);
+ if (error.isError())
{
- SetGlobalError(Error(EGL_NOT_INITIALIZED, "'dpy' not initialized"));
+ thread->setError(error);
return EGL_FALSE;
}
- if (ctx != EGL_NO_CONTEXT)
- {
- Error error = ValidateContext(display, context);
- if (error.isError())
- {
- SetGlobalError(error);
- return EGL_FALSE;
- }
- }
-
- if (display->isInitialized())
- {
- if (display->testDeviceLost())
- {
- display->notifyDeviceLost();
- return EGL_FALSE;
- }
-
- if (display->isDeviceLost())
- {
- SetGlobalError(Error(EGL_CONTEXT_LOST));
- return EGL_FALSE;
- }
- }
-
- Surface *drawSurface = static_cast<Surface*>(draw);
- if (draw != EGL_NO_SURFACE)
- {
- Error error = ValidateSurface(display, drawSurface);
- if (error.isError())
- {
- SetGlobalError(error);
- return EGL_FALSE;
- }
- }
-
- Surface *readSurface = static_cast<Surface*>(read);
- if (read != EGL_NO_SURFACE)
- {
- Error error = ValidateSurface(display, readSurface);
- if (error.isError())
- {
- SetGlobalError(error);
- return EGL_FALSE;
- }
- }
-
- if (readSurface)
- {
- Error readCompatError =
- ValidateCompatibleConfigs(display, readSurface->getConfig(), readSurface,
- context->getConfig(), readSurface->getType());
- if (readCompatError.isError())
- {
- SetGlobalError(readCompatError);
- return EGL_FALSE;
- }
- }
-
- if (draw != read)
- {
- UNIMPLEMENTED(); // FIXME
-
- if (drawSurface)
- {
- Error drawCompatError =
- ValidateCompatibleConfigs(display, drawSurface->getConfig(), drawSurface,
- context->getConfig(), drawSurface->getType());
- if (drawCompatError.isError())
- {
- SetGlobalError(drawCompatError);
- return EGL_FALSE;
- }
- }
- }
-
+ Surface *readSurface = static_cast<Surface *>(read);
+ Surface *drawSurface = static_cast<Surface *>(draw);
Error makeCurrentError = display->makeCurrent(drawSurface, readSurface, context);
if (makeCurrentError.isError())
{
- SetGlobalError(makeCurrentError);
+ thread->setError(makeCurrentError);
return EGL_FALSE;
}
- gl::Context *previousContext = GetGlobalContext();
-
- SetGlobalDisplay(display);
- SetGlobalDrawSurface(drawSurface);
- SetGlobalReadSurface(readSurface);
- SetGlobalContext(context);
+ gl::Context *previousContext = thread->getContext();
+ thread->setCurrent(context);
// Release the surface from the previously-current context, to allow
// destroyed surfaces to delete themselves.
if (previousContext != nullptr && context != previousContext)
{
- previousContext->releaseSurface();
+ auto err = previousContext->releaseSurface(display);
+ if (err.isError())
+ {
+ thread->setError(err);
+ return EGL_FALSE;
+ }
}
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return EGL_TRUE;
}
EGLSurface EGLAPIENTRY GetCurrentSurface(EGLint readdraw)
{
EVENT("(EGLint readdraw = %d)", readdraw);
+ Thread *thread = GetCurrentThread();
if (readdraw == EGL_READ)
{
- SetGlobalError(Error(EGL_SUCCESS));
- return GetGlobalReadSurface();
+ thread->setError(NoError());
+ return thread->getCurrentReadSurface();
}
else if (readdraw == EGL_DRAW)
{
- SetGlobalError(Error(EGL_SUCCESS));
- return GetGlobalDrawSurface();
+ thread->setError(NoError());
+ return thread->getCurrentDrawSurface();
}
else
{
- SetGlobalError(Error(EGL_BAD_PARAMETER));
+ thread->setError(EglBadParameter());
return EGL_NO_SURFACE;
}
}
@@ -696,283 +551,294 @@ EGLSurface EGLAPIENTRY GetCurrentSurface(EGLint readdraw)
EGLDisplay EGLAPIENTRY GetCurrentDisplay(void)
{
EVENT("()");
+ Thread *thread = GetCurrentThread();
- EGLDisplay dpy = GetGlobalDisplay();
-
- SetGlobalError(Error(EGL_SUCCESS));
- return dpy;
+ thread->setError(NoError());
+ if (thread->getContext() != nullptr)
+ {
+ return thread->getContext()->getCurrentDisplay();
+ }
+ return EGL_NO_DISPLAY;
}
EGLBoolean EGLAPIENTRY QueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
- dpy, ctx, attribute, value);
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLint attribute = %d, EGLint *value "
+ "= 0x%0.8p)",
+ dpy, ctx, attribute, value);
+ Thread *thread = GetCurrentThread();
- Display *display = static_cast<Display*>(dpy);
- gl::Context *context = static_cast<gl::Context*>(ctx);
+ Display *display = static_cast<Display *>(dpy);
+ gl::Context *context = static_cast<gl::Context *>(ctx);
- Error error = ValidateContext(display, context);
+ Error error = ValidateQueryContext(display, context, attribute, value);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
- switch (attribute)
- {
- case EGL_CONFIG_ID:
- *value = context->getConfig()->configID;
- break;
- case EGL_CONTEXT_CLIENT_TYPE:
- *value = context->getClientType();
- break;
- case EGL_CONTEXT_CLIENT_VERSION:
- *value = context->getClientVersion();
- break;
- case EGL_RENDER_BUFFER:
- *value = context->getRenderBuffer();
- break;
- default:
- SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
- return EGL_FALSE;
- }
+ QueryContextAttrib(context, attribute, value);
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return EGL_TRUE;
}
EGLBoolean EGLAPIENTRY WaitGL(void)
{
EVENT("()");
+ Thread *thread = GetCurrentThread();
- Display *display = GetGlobalDisplay();
+ Display *display = thread->getCurrentDisplay();
Error error = ValidateDisplay(display);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
// eglWaitGL like calling eglWaitClient with the OpenGL ES API bound. Since we only implement
// OpenGL ES we can do the call directly.
- error = display->waitClient();
+ error = display->waitClient(thread->getContext());
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return EGL_TRUE;
}
EGLBoolean EGLAPIENTRY WaitNative(EGLint engine)
{
EVENT("(EGLint engine = %d)", engine);
+ Thread *thread = GetCurrentThread();
- Display *display = GetGlobalDisplay();
+ Display *display = thread->getCurrentDisplay();
Error error = ValidateDisplay(display);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
if (engine != EGL_CORE_NATIVE_ENGINE)
{
- SetGlobalError(
- Error(EGL_BAD_PARAMETER, "the 'engine' parameter has an unrecognized value"));
+ thread->setError(EglBadParameter() << "the 'engine' parameter has an unrecognized value");
}
- error = display->waitNative(engine, GetGlobalDrawSurface(), GetGlobalReadSurface());
+ error = display->waitNative(thread->getContext(), engine);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return EGL_TRUE;
}
EGLBoolean EGLAPIENTRY SwapBuffers(EGLDisplay dpy, EGLSurface surface)
{
EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface);
+ Thread *thread = GetCurrentThread();
- Display *display = static_cast<Display*>(dpy);
- Surface *eglSurface = (Surface*)surface;
+ Display *display = static_cast<Display *>(dpy);
+ Surface *eglSurface = (Surface *)surface;
Error error = ValidateSurface(display, eglSurface);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
- if (display->isDeviceLost())
+ if (display->testDeviceLost())
{
- SetGlobalError(Error(EGL_CONTEXT_LOST));
+ thread->setError(EglContextLost());
return EGL_FALSE;
}
if (surface == EGL_NO_SURFACE)
{
- SetGlobalError(Error(EGL_BAD_SURFACE));
+ thread->setError(EglBadSurface());
return EGL_FALSE;
}
- error = eglSurface->swap();
+ if (!thread->getContext() || thread->getCurrentDrawSurface() != eglSurface)
+ {
+ thread->setError(EglBadSurface());
+ return EGL_FALSE;
+ }
+
+ error = eglSurface->swap(thread->getContext());
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return EGL_TRUE;
}
EGLBoolean EGLAPIENTRY CopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLNativePixmapType target = 0x%0.8p)", dpy, surface, target);
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLNativePixmapType target = "
+ "0x%0.8p)",
+ dpy, surface, target);
+ Thread *thread = GetCurrentThread();
- Display *display = static_cast<Display*>(dpy);
- Surface *eglSurface = static_cast<Surface*>(surface);
+ Display *display = static_cast<Display *>(dpy);
+ Surface *eglSurface = static_cast<Surface *>(surface);
Error error = ValidateSurface(display, eglSurface);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
- if (display->isDeviceLost())
+ if (display->testDeviceLost())
{
- SetGlobalError(Error(EGL_CONTEXT_LOST));
+ thread->setError(EglContextLost());
return EGL_FALSE;
}
- UNIMPLEMENTED(); // FIXME
+ UNIMPLEMENTED(); // FIXME
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return 0;
}
// EGL 1.1
EGLBoolean EGLAPIENTRY BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer);
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy,
+ surface, buffer);
+ Thread *thread = GetCurrentThread();
- Display *display = static_cast<Display*>(dpy);
- Surface *eglSurface = static_cast<Surface*>(surface);
+ Display *display = static_cast<Display *>(dpy);
+ Surface *eglSurface = static_cast<Surface *>(surface);
Error error = ValidateSurface(display, eglSurface);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
if (buffer != EGL_BACK_BUFFER)
{
- SetGlobalError(Error(EGL_BAD_PARAMETER));
+ thread->setError(EglBadParameter());
return EGL_FALSE;
}
if (surface == EGL_NO_SURFACE || eglSurface->getType() == EGL_WINDOW_BIT)
{
- SetGlobalError(Error(EGL_BAD_SURFACE));
+ thread->setError(EglBadSurface());
return EGL_FALSE;
}
if (eglSurface->getBoundTexture())
{
- SetGlobalError(Error(EGL_BAD_ACCESS));
+ thread->setError(EglBadAccess());
return EGL_FALSE;
}
if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
{
- SetGlobalError(Error(EGL_BAD_MATCH));
+ thread->setError(EglBadMatch());
return EGL_FALSE;
}
- gl::Context *context = GetGlobalContext();
+ gl::Context *context = thread->getContext();
if (context)
{
gl::Texture *textureObject = context->getTargetTexture(GL_TEXTURE_2D);
- ASSERT(textureObject != NULL);
+ ASSERT(textureObject != nullptr);
if (textureObject->getImmutableFormat())
{
- SetGlobalError(Error(EGL_BAD_MATCH));
+ thread->setError(EglBadMatch());
return EGL_FALSE;
}
- error = eglSurface->bindTexImage(textureObject, buffer);
+ error = eglSurface->bindTexImage(context, textureObject, buffer);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
}
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return EGL_TRUE;
}
-EGLBoolean EGLAPIENTRY SurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
+EGLBoolean EGLAPIENTRY SurfaceAttrib(EGLDisplay dpy,
+ EGLSurface surface,
+ EGLint attribute,
+ EGLint value)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint value = %d)",
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint "
+ "value = %d)",
dpy, surface, attribute, value);
+ Thread *thread = GetCurrentThread();
- Display *display = static_cast<Display*>(dpy);
- Surface *eglSurface = static_cast<Surface*>(surface);
+ Display *display = static_cast<Display *>(dpy);
+ Surface *eglSurface = static_cast<Surface *>(surface);
- Error error = ValidateSurface(display, eglSurface);
+ Error error = ValidateSurfaceAttrib(display, eglSurface, attribute, value);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
- UNIMPLEMENTED(); // FIXME
+ SetSurfaceAttrib(eglSurface, attribute, value);
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return EGL_TRUE;
}
EGLBoolean EGLAPIENTRY ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer);
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy,
+ surface, buffer);
+ Thread *thread = GetCurrentThread();
- Display *display = static_cast<Display*>(dpy);
- Surface *eglSurface = static_cast<Surface*>(surface);
+ Display *display = static_cast<Display *>(dpy);
+ Surface *eglSurface = static_cast<Surface *>(surface);
Error error = ValidateSurface(display, eglSurface);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
if (buffer != EGL_BACK_BUFFER)
{
- SetGlobalError(Error(EGL_BAD_PARAMETER));
+ thread->setError(EglBadParameter());
return EGL_FALSE;
}
if (surface == EGL_NO_SURFACE || eglSurface->getType() == EGL_WINDOW_BIT)
{
- SetGlobalError(Error(EGL_BAD_SURFACE));
+ thread->setError(EglBadSurface());
return EGL_FALSE;
}
if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
{
- SetGlobalError(Error(EGL_BAD_MATCH));
+ thread->setError(EglBadMatch());
return EGL_FALSE;
}
@@ -980,105 +846,116 @@ EGLBoolean EGLAPIENTRY ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLin
if (texture)
{
- error = eglSurface->releaseTexImage(buffer);
+ error = eglSurface->releaseTexImage(thread->getContext(), buffer);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
}
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return EGL_TRUE;
}
EGLBoolean EGLAPIENTRY SwapInterval(EGLDisplay dpy, EGLint interval)
{
EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint interval = %d)", dpy, interval);
+ Thread *thread = GetCurrentThread();
- Display *display = static_cast<Display*>(dpy);
+ Display *display = static_cast<Display *>(dpy);
Error error = ValidateDisplay(display);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
- Surface *draw_surface = static_cast<Surface*>(GetGlobalDrawSurface());
+ Surface *draw_surface = static_cast<Surface *>(thread->getCurrentDrawSurface());
- if (draw_surface == NULL)
+ if (draw_surface == nullptr)
{
- SetGlobalError(Error(EGL_BAD_SURFACE));
+ thread->setError(EglBadSurface());
return EGL_FALSE;
}
const egl::Config *surfaceConfig = draw_surface->getConfig();
- EGLint clampedInterval = std::min(std::max(interval, surfaceConfig->minSwapInterval), surfaceConfig->maxSwapInterval);
+ EGLint clampedInterval = std::min(std::max(interval, surfaceConfig->minSwapInterval),
+ surfaceConfig->maxSwapInterval);
draw_surface->setSwapInterval(clampedInterval);
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return EGL_TRUE;
}
-
// EGL 1.2
EGLBoolean EGLAPIENTRY BindAPI(EGLenum api)
{
EVENT("(EGLenum api = 0x%X)", api);
+ Thread *thread = GetCurrentThread();
switch (api)
{
- case EGL_OPENGL_API:
- case EGL_OPENVG_API:
- SetGlobalError(Error(EGL_BAD_PARAMETER));
- return EGL_FALSE; // Not supported by this implementation
- case EGL_OPENGL_ES_API:
- break;
- default:
- SetGlobalError(Error(EGL_BAD_PARAMETER));
- return EGL_FALSE;
+ case EGL_OPENGL_API:
+ case EGL_OPENVG_API:
+ thread->setError(EglBadParameter());
+ return EGL_FALSE; // Not supported by this implementation
+ case EGL_OPENGL_ES_API:
+ break;
+ default:
+ thread->setError(EglBadParameter());
+ return EGL_FALSE;
}
- SetGlobalAPI(api);
+ thread->setAPI(api);
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return EGL_TRUE;
}
EGLenum EGLAPIENTRY QueryAPI(void)
{
EVENT("()");
+ Thread *thread = GetCurrentThread();
- EGLenum API = GetGlobalAPI();
+ EGLenum API = thread->getAPI();
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return API;
}
-EGLSurface EGLAPIENTRY CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
+EGLSurface EGLAPIENTRY CreatePbufferFromClientBuffer(EGLDisplay dpy,
+ EGLenum buftype,
+ EGLClientBuffer buffer,
+ EGLConfig config,
+ const EGLint *attrib_list)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = 0x%0.8p, "
- "EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",
- dpy, buftype, buffer, config, attrib_list);
-
- Display *display = static_cast<Display*>(dpy);
- Config *configuration = static_cast<Config*>(config);
- AttributeMap attributes(attrib_list);
-
- Error error = ValidateCreatePbufferFromClientBuffer(display, buftype, buffer, configuration, attributes);
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = 0x%0.8p, "
+ "EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",
+ dpy, buftype, buffer, config, attrib_list);
+ Thread *thread = GetCurrentThread();
+
+ Display *display = static_cast<Display *>(dpy);
+ Config *configuration = static_cast<Config *>(config);
+ AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list);
+
+ Error error =
+ ValidateCreatePbufferFromClientBuffer(display, buftype, buffer, configuration, attributes);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_NO_SURFACE;
}
egl::Surface *surface = nullptr;
- error = display->createPbufferFromClientBuffer(configuration, buffer, attributes, &surface);
+ error = display->createPbufferFromClientBuffer(configuration, buftype, buffer, attributes,
+ &surface);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_NO_SURFACE;
}
@@ -1088,34 +965,36 @@ EGLSurface EGLAPIENTRY CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buf
EGLBoolean EGLAPIENTRY ReleaseThread(void)
{
EVENT("()");
+ Thread *thread = GetCurrentThread();
MakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return EGL_TRUE;
}
EGLBoolean EGLAPIENTRY WaitClient(void)
{
EVENT("()");
+ Thread *thread = GetCurrentThread();
- Display *display = GetGlobalDisplay();
+ Display *display = thread->getCurrentDisplay();
Error error = ValidateDisplay(display);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
- error = display->waitClient();
+ error = display->waitClient(thread->getContext());
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return EGL_TRUE;
}
@@ -1123,540 +1002,185 @@ EGLBoolean EGLAPIENTRY WaitClient(void)
EGLContext EGLAPIENTRY GetCurrentContext(void)
{
EVENT("()");
+ Thread *thread = GetCurrentThread();
- gl::Context *context = GetGlobalContext();
+ gl::Context *context = thread->getContext();
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return static_cast<EGLContext>(context);
}
// EGL 1.5
EGLSync EGLAPIENTRY CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum type = 0x%X, const EGLint* attrib_list = 0x%0.8p)", dpy, type, attrib_list);
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum type = 0x%X, const EGLint* attrib_list = 0x%0.8p)",
+ dpy, type, attrib_list);
+ Thread *thread = GetCurrentThread();
UNIMPLEMENTED();
+ thread->setError(EglBadDisplay() << "eglCreateSync unimplemented.");
return EGL_NO_SYNC;
}
EGLBoolean EGLAPIENTRY DestroySync(EGLDisplay dpy, EGLSync sync)
{
EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSync sync = 0x%0.8p)", dpy, sync);
+ Thread *thread = GetCurrentThread();
UNIMPLEMENTED();
+ thread->setError(EglBadDisplay() << "eglDestroySync unimplemented.");
return EGL_FALSE;
}
EGLint EGLAPIENTRY ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSync sync = 0x%0.8p, EGLint flags = 0x%X, EGLTime timeout = %d)", dpy, sync, flags, timeout);
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLSync sync = 0x%0.8p, EGLint flags = 0x%X, EGLTime timeout = "
+ "%d)",
+ dpy, sync, flags, timeout);
+ Thread *thread = GetCurrentThread();
UNIMPLEMENTED();
+ thread->setError(EglBadDisplay() << "eglClientWaitSync unimplemented.");
return 0;
}
-EGLBoolean EGLAPIENTRY GetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value)
+EGLBoolean EGLAPIENTRY GetSyncAttrib(EGLDisplay dpy,
+ EGLSync sync,
+ EGLint attribute,
+ EGLAttrib *value)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSync sync = 0x%0.8p, EGLint attribute = 0x%X, EGLAttrib *value = 0x%0.8p)", dpy, sync, attribute, value);
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLSync sync = 0x%0.8p, EGLint attribute = 0x%X, EGLAttrib "
+ "*value = 0x%0.8p)",
+ dpy, sync, attribute, value);
+ Thread *thread = GetCurrentThread();
UNIMPLEMENTED();
+ thread->setError(EglBadDisplay() << "eglSyncAttrib unimplemented.");
return EGL_FALSE;
}
-EGLImage EGLAPIENTRY CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list)
+EGLImage EGLAPIENTRY CreateImage(EGLDisplay dpy,
+ EGLContext ctx,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const EGLAttrib *attrib_list)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLenum target = 0x%X, "
- "EGLClientBuffer buffer = 0x%0.8p, const EGLAttrib *attrib_list = 0x%0.8p)",
- dpy, ctx, target, buffer, attrib_list);
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLenum target = 0x%X, "
+ "EGLClientBuffer buffer = 0x%0.8p, const EGLAttrib *attrib_list = 0x%0.8p)",
+ dpy, ctx, target, buffer, attrib_list);
+ Thread *thread = GetCurrentThread();
UNIMPLEMENTED();
+ thread->setError(EglBadDisplay() << "eglCreateImage unimplemented.");
return EGL_NO_IMAGE;
}
EGLBoolean EGLAPIENTRY DestroyImage(EGLDisplay dpy, EGLImage image)
{
EVENT("(EGLDisplay dpy = 0x%0.8p, EGLImage image = 0x%0.8p)", dpy, image);
+ Thread *thread = GetCurrentThread();
UNIMPLEMENTED();
+ thread->setError(EglBadDisplay() << "eglDestroyImage unimplemented.");
return EGL_FALSE;
}
-EGLDisplay EGLAPIENTRY GetPlatformDisplay(EGLenum platform, void *native_display, const EGLAttrib *attrib_list)
+EGLDisplay EGLAPIENTRY GetPlatformDisplay(EGLenum platform,
+ void *native_display,
+ const EGLAttrib *attrib_list)
{
- EVENT("(EGLenum platform = %d, void* native_display = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)",
- platform, native_display, attrib_list);
+ EVENT(
+ "(EGLenum platform = %d, void* native_display = 0x%0.8p, const EGLint* attrib_list = "
+ "0x%0.8p)",
+ platform, native_display, attrib_list);
+ Thread *thread = GetCurrentThread();
- UNIMPLEMENTED();
- return EGL_NO_DISPLAY;
+ Error err = ValidateGetPlatformDisplay(platform, native_display, attrib_list);
+ thread->setError(err);
+ if (err.isError())
+ {
+ return EGL_NO_DISPLAY;
+ }
+
+ const auto &attribMap = AttributeMap::CreateFromAttribArray(attrib_list);
+ if (platform == EGL_PLATFORM_ANGLE_ANGLE)
+ {
+ return Display::GetDisplayFromNativeDisplay(
+ gl::bitCast<EGLNativeDisplayType>(native_display), attribMap);
+ }
+ else if (platform == EGL_PLATFORM_DEVICE_EXT)
+ {
+ Device *eglDevice = reinterpret_cast<Device *>(native_display);
+ return Display::GetDisplayFromDevice(eglDevice, attribMap);
+ }
+ else
+ {
+ UNREACHABLE();
+ return EGL_NO_DISPLAY;
+ }
}
-EGLSurface EGLAPIENTRY CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list)
+EGLSurface EGLAPIENTRY CreatePlatformWindowSurface(EGLDisplay dpy,
+ EGLConfig config,
+ void *native_window,
+ const EGLAttrib *attrib_list)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, void* native_window = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)",
- dpy, config, native_window, attrib_list);
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, void* native_window = 0x%0.8p, "
+ "const EGLint* attrib_list = 0x%0.8p)",
+ dpy, config, native_window, attrib_list);
+ Thread *thread = GetCurrentThread();
UNIMPLEMENTED();
+ thread->setError(EglBadDisplay() << "eglCreatePlatformWindowSurface unimplemented.");
return EGL_NO_SURFACE;
}
-EGLSurface EGLAPIENTRY CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list)
+EGLSurface EGLAPIENTRY CreatePlatformPixmapSurface(EGLDisplay dpy,
+ EGLConfig config,
+ void *native_pixmap,
+ const EGLAttrib *attrib_list)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, void* native_pixmap = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)",
- dpy, config, native_pixmap, attrib_list);
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, void* native_pixmap = 0x%0.8p, "
+ "const EGLint* attrib_list = 0x%0.8p)",
+ dpy, config, native_pixmap, attrib_list);
+ Thread *thread = GetCurrentThread();
UNIMPLEMENTED();
+ thread->setError(EglBadDisplay() << "eglCreatePlatformPixmapSurface unimplemented.");
return EGL_NO_SURFACE;
}
EGLBoolean EGLAPIENTRY WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSync sync = 0x%0.8p, EGLint flags = 0x%X)", dpy, sync, flags);
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSync sync = 0x%0.8p, EGLint flags = 0x%X)", dpy, sync,
+ flags);
+ Thread *thread = GetCurrentThread();
UNIMPLEMENTED();
+ thread->setError(EglBadDisplay() << "eglWaitSync unimplemented.");
return EGL_FALSE;
}
__eglMustCastToProperFunctionPointerType EGLAPIENTRY GetProcAddress(const char *procname)
{
EVENT("(const char *procname = \"%s\")", procname);
+ Thread *thread = GetCurrentThread();
- typedef std::map<std::string, __eglMustCastToProperFunctionPointerType> ProcAddressMap;
- auto generateProcAddressMap = []()
- {
- ProcAddressMap map;
-#define INSERT_PROC_ADDRESS(ns, proc) \
- map[#ns #proc] = reinterpret_cast<__eglMustCastToProperFunctionPointerType>(ns::proc)
-
- // GLES2 core
- INSERT_PROC_ADDRESS(gl, ActiveTexture);
- INSERT_PROC_ADDRESS(gl, AttachShader);
- INSERT_PROC_ADDRESS(gl, BindAttribLocation);
- INSERT_PROC_ADDRESS(gl, BindBuffer);
- INSERT_PROC_ADDRESS(gl, BindFramebuffer);
- INSERT_PROC_ADDRESS(gl, BindRenderbuffer);
- INSERT_PROC_ADDRESS(gl, BindTexture);
- INSERT_PROC_ADDRESS(gl, BlendColor);
- INSERT_PROC_ADDRESS(gl, BlendEquation);
- INSERT_PROC_ADDRESS(gl, BlendEquationSeparate);
- INSERT_PROC_ADDRESS(gl, BlendFunc);
- INSERT_PROC_ADDRESS(gl, BlendFuncSeparate);
- INSERT_PROC_ADDRESS(gl, BufferData);
- INSERT_PROC_ADDRESS(gl, BufferSubData);
- INSERT_PROC_ADDRESS(gl, CheckFramebufferStatus);
- INSERT_PROC_ADDRESS(gl, Clear);
- INSERT_PROC_ADDRESS(gl, ClearColor);
- INSERT_PROC_ADDRESS(gl, ClearDepthf);
- INSERT_PROC_ADDRESS(gl, ClearStencil);
- INSERT_PROC_ADDRESS(gl, ColorMask);
- INSERT_PROC_ADDRESS(gl, CompileShader);
- INSERT_PROC_ADDRESS(gl, CompressedTexImage2D);
- INSERT_PROC_ADDRESS(gl, CompressedTexSubImage2D);
- INSERT_PROC_ADDRESS(gl, CopyTexImage2D);
- INSERT_PROC_ADDRESS(gl, CopyTexSubImage2D);
- INSERT_PROC_ADDRESS(gl, CreateProgram);
- INSERT_PROC_ADDRESS(gl, CreateShader);
- INSERT_PROC_ADDRESS(gl, CullFace);
- INSERT_PROC_ADDRESS(gl, DeleteBuffers);
- INSERT_PROC_ADDRESS(gl, DeleteFramebuffers);
- INSERT_PROC_ADDRESS(gl, DeleteProgram);
- INSERT_PROC_ADDRESS(gl, DeleteRenderbuffers);
- INSERT_PROC_ADDRESS(gl, DeleteShader);
- INSERT_PROC_ADDRESS(gl, DeleteTextures);
- INSERT_PROC_ADDRESS(gl, DepthFunc);
- INSERT_PROC_ADDRESS(gl, DepthMask);
- INSERT_PROC_ADDRESS(gl, DepthRangef);
- INSERT_PROC_ADDRESS(gl, DetachShader);
- INSERT_PROC_ADDRESS(gl, Disable);
- INSERT_PROC_ADDRESS(gl, DisableVertexAttribArray);
- INSERT_PROC_ADDRESS(gl, DrawArrays);
- INSERT_PROC_ADDRESS(gl, DrawElements);
- INSERT_PROC_ADDRESS(gl, Enable);
- INSERT_PROC_ADDRESS(gl, EnableVertexAttribArray);
- INSERT_PROC_ADDRESS(gl, Finish);
- INSERT_PROC_ADDRESS(gl, Flush);
- INSERT_PROC_ADDRESS(gl, FramebufferRenderbuffer);
- INSERT_PROC_ADDRESS(gl, FramebufferTexture2D);
- INSERT_PROC_ADDRESS(gl, FrontFace);
- INSERT_PROC_ADDRESS(gl, GenBuffers);
- INSERT_PROC_ADDRESS(gl, GenerateMipmap);
- INSERT_PROC_ADDRESS(gl, GenFramebuffers);
- INSERT_PROC_ADDRESS(gl, GenRenderbuffers);
- INSERT_PROC_ADDRESS(gl, GenTextures);
- INSERT_PROC_ADDRESS(gl, GetActiveAttrib);
- INSERT_PROC_ADDRESS(gl, GetActiveUniform);
- INSERT_PROC_ADDRESS(gl, GetAttachedShaders);
- INSERT_PROC_ADDRESS(gl, GetAttribLocation);
- INSERT_PROC_ADDRESS(gl, GetBooleanv);
- INSERT_PROC_ADDRESS(gl, GetBufferParameteriv);
- INSERT_PROC_ADDRESS(gl, GetError);
- INSERT_PROC_ADDRESS(gl, GetFloatv);
- INSERT_PROC_ADDRESS(gl, GetFramebufferAttachmentParameteriv);
- INSERT_PROC_ADDRESS(gl, GetIntegerv);
- INSERT_PROC_ADDRESS(gl, GetProgramiv);
- INSERT_PROC_ADDRESS(gl, GetProgramInfoLog);
- INSERT_PROC_ADDRESS(gl, GetRenderbufferParameteriv);
- INSERT_PROC_ADDRESS(gl, GetShaderiv);
- INSERT_PROC_ADDRESS(gl, GetShaderInfoLog);
- INSERT_PROC_ADDRESS(gl, GetShaderPrecisionFormat);
- INSERT_PROC_ADDRESS(gl, GetShaderSource);
- INSERT_PROC_ADDRESS(gl, GetString);
- INSERT_PROC_ADDRESS(gl, GetTexParameterfv);
- INSERT_PROC_ADDRESS(gl, GetTexParameteriv);
- INSERT_PROC_ADDRESS(gl, GetUniformfv);
- INSERT_PROC_ADDRESS(gl, GetUniformiv);
- INSERT_PROC_ADDRESS(gl, GetUniformLocation);
- INSERT_PROC_ADDRESS(gl, GetVertexAttribfv);
- INSERT_PROC_ADDRESS(gl, GetVertexAttribiv);
- INSERT_PROC_ADDRESS(gl, GetVertexAttribPointerv);
- INSERT_PROC_ADDRESS(gl, Hint);
- INSERT_PROC_ADDRESS(gl, IsBuffer);
- INSERT_PROC_ADDRESS(gl, IsEnabled);
- INSERT_PROC_ADDRESS(gl, IsFramebuffer);
- INSERT_PROC_ADDRESS(gl, IsProgram);
- INSERT_PROC_ADDRESS(gl, IsRenderbuffer);
- INSERT_PROC_ADDRESS(gl, IsShader);
- INSERT_PROC_ADDRESS(gl, IsTexture);
- INSERT_PROC_ADDRESS(gl, LineWidth);
- INSERT_PROC_ADDRESS(gl, LinkProgram);
- INSERT_PROC_ADDRESS(gl, PixelStorei);
- INSERT_PROC_ADDRESS(gl, PolygonOffset);
- INSERT_PROC_ADDRESS(gl, ReadPixels);
- INSERT_PROC_ADDRESS(gl, ReleaseShaderCompiler);
- INSERT_PROC_ADDRESS(gl, RenderbufferStorage);
- INSERT_PROC_ADDRESS(gl, SampleCoverage);
- INSERT_PROC_ADDRESS(gl, Scissor);
- INSERT_PROC_ADDRESS(gl, ShaderBinary);
- INSERT_PROC_ADDRESS(gl, ShaderSource);
- INSERT_PROC_ADDRESS(gl, StencilFunc);
- INSERT_PROC_ADDRESS(gl, StencilFuncSeparate);
- INSERT_PROC_ADDRESS(gl, StencilMask);
- INSERT_PROC_ADDRESS(gl, StencilMaskSeparate);
- INSERT_PROC_ADDRESS(gl, StencilOp);
- INSERT_PROC_ADDRESS(gl, StencilOpSeparate);
- INSERT_PROC_ADDRESS(gl, TexImage2D);
- INSERT_PROC_ADDRESS(gl, TexParameterf);
- INSERT_PROC_ADDRESS(gl, TexParameterfv);
- INSERT_PROC_ADDRESS(gl, TexParameteri);
- INSERT_PROC_ADDRESS(gl, TexParameteriv);
- INSERT_PROC_ADDRESS(gl, TexSubImage2D);
- INSERT_PROC_ADDRESS(gl, Uniform1f);
- INSERT_PROC_ADDRESS(gl, Uniform1fv);
- INSERT_PROC_ADDRESS(gl, Uniform1i);
- INSERT_PROC_ADDRESS(gl, Uniform1iv);
- INSERT_PROC_ADDRESS(gl, Uniform2f);
- INSERT_PROC_ADDRESS(gl, Uniform2fv);
- INSERT_PROC_ADDRESS(gl, Uniform2i);
- INSERT_PROC_ADDRESS(gl, Uniform2iv);
- INSERT_PROC_ADDRESS(gl, Uniform3f);
- INSERT_PROC_ADDRESS(gl, Uniform3fv);
- INSERT_PROC_ADDRESS(gl, Uniform3i);
- INSERT_PROC_ADDRESS(gl, Uniform3iv);
- INSERT_PROC_ADDRESS(gl, Uniform4f);
- INSERT_PROC_ADDRESS(gl, Uniform4fv);
- INSERT_PROC_ADDRESS(gl, Uniform4i);
- INSERT_PROC_ADDRESS(gl, Uniform4iv);
- INSERT_PROC_ADDRESS(gl, UniformMatrix2fv);
- INSERT_PROC_ADDRESS(gl, UniformMatrix3fv);
- INSERT_PROC_ADDRESS(gl, UniformMatrix4fv);
- INSERT_PROC_ADDRESS(gl, UseProgram);
- INSERT_PROC_ADDRESS(gl, ValidateProgram);
- INSERT_PROC_ADDRESS(gl, VertexAttrib1f);
- INSERT_PROC_ADDRESS(gl, VertexAttrib1fv);
- INSERT_PROC_ADDRESS(gl, VertexAttrib2f);
- INSERT_PROC_ADDRESS(gl, VertexAttrib2fv);
- INSERT_PROC_ADDRESS(gl, VertexAttrib3f);
- INSERT_PROC_ADDRESS(gl, VertexAttrib3fv);
- INSERT_PROC_ADDRESS(gl, VertexAttrib4f);
- INSERT_PROC_ADDRESS(gl, VertexAttrib4fv);
- INSERT_PROC_ADDRESS(gl, VertexAttribPointer);
- INSERT_PROC_ADDRESS(gl, Viewport);
-
- // GL_ANGLE_framebuffer_blit
- INSERT_PROC_ADDRESS(gl, BlitFramebufferANGLE);
-
- // GL_ANGLE_framebuffer_multisample
- INSERT_PROC_ADDRESS(gl, RenderbufferStorageMultisampleANGLE);
-
- // GL_EXT_discard_framebuffer
- INSERT_PROC_ADDRESS(gl, DiscardFramebufferEXT);
-
- // GL_NV_fence
- INSERT_PROC_ADDRESS(gl, DeleteFencesNV);
- INSERT_PROC_ADDRESS(gl, GenFencesNV);
- INSERT_PROC_ADDRESS(gl, IsFenceNV);
- INSERT_PROC_ADDRESS(gl, TestFenceNV);
- INSERT_PROC_ADDRESS(gl, GetFenceivNV);
- INSERT_PROC_ADDRESS(gl, FinishFenceNV);
- INSERT_PROC_ADDRESS(gl, SetFenceNV);
-
- // GL_ANGLE_translated_shader_source
- INSERT_PROC_ADDRESS(gl, GetTranslatedShaderSourceANGLE);
-
- // GL_EXT_texture_storage
- INSERT_PROC_ADDRESS(gl, TexStorage2DEXT);
-
- // GL_EXT_robustness
- INSERT_PROC_ADDRESS(gl, GetGraphicsResetStatusEXT);
- INSERT_PROC_ADDRESS(gl, ReadnPixelsEXT);
- INSERT_PROC_ADDRESS(gl, GetnUniformfvEXT);
- INSERT_PROC_ADDRESS(gl, GetnUniformivEXT);
-
- // GL_EXT_occlusion_query_boolean
- INSERT_PROC_ADDRESS(gl, GenQueriesEXT);
- INSERT_PROC_ADDRESS(gl, DeleteQueriesEXT);
- INSERT_PROC_ADDRESS(gl, IsQueryEXT);
- INSERT_PROC_ADDRESS(gl, BeginQueryEXT);
- INSERT_PROC_ADDRESS(gl, EndQueryEXT);
- INSERT_PROC_ADDRESS(gl, GetQueryivEXT);
- INSERT_PROC_ADDRESS(gl, GetQueryObjectuivEXT);
-
- // GL_EXT_draw_buffers
- INSERT_PROC_ADDRESS(gl, DrawBuffersEXT);
-
- // GL_ANGLE_instanced_arrays
- INSERT_PROC_ADDRESS(gl, DrawArraysInstancedANGLE);
- INSERT_PROC_ADDRESS(gl, DrawElementsInstancedANGLE);
- INSERT_PROC_ADDRESS(gl, VertexAttribDivisorANGLE);
-
- // GL_OES_get_program_binary
- INSERT_PROC_ADDRESS(gl, GetProgramBinaryOES);
- INSERT_PROC_ADDRESS(gl, ProgramBinaryOES);
-
- // GL_OES_mapbuffer
- INSERT_PROC_ADDRESS(gl, MapBufferOES);
- INSERT_PROC_ADDRESS(gl, UnmapBufferOES);
- INSERT_PROC_ADDRESS(gl, GetBufferPointervOES);
-
- // GL_EXT_map_buffer_range
- INSERT_PROC_ADDRESS(gl, MapBufferRangeEXT);
- INSERT_PROC_ADDRESS(gl, FlushMappedBufferRangeEXT);
-
- // GL_EXT_debug_marker
- INSERT_PROC_ADDRESS(gl, InsertEventMarkerEXT);
- INSERT_PROC_ADDRESS(gl, PushGroupMarkerEXT);
- INSERT_PROC_ADDRESS(gl, PopGroupMarkerEXT);
-
- // GL_OES_EGL_image
- INSERT_PROC_ADDRESS(gl, EGLImageTargetTexture2DOES);
- INSERT_PROC_ADDRESS(gl, EGLImageTargetRenderbufferStorageOES);
-
- // GL_OES_vertex_array_object
- INSERT_PROC_ADDRESS(gl, BindVertexArrayOES);
- INSERT_PROC_ADDRESS(gl, DeleteVertexArraysOES);
- INSERT_PROC_ADDRESS(gl, GenVertexArraysOES);
- INSERT_PROC_ADDRESS(gl, IsVertexArrayOES);
-
- // GL_KHR_debug
- INSERT_PROC_ADDRESS(gl, DebugMessageControlKHR);
- INSERT_PROC_ADDRESS(gl, DebugMessageInsertKHR);
- INSERT_PROC_ADDRESS(gl, DebugMessageCallbackKHR);
- INSERT_PROC_ADDRESS(gl, GetDebugMessageLogKHR);
- INSERT_PROC_ADDRESS(gl, PushDebugGroupKHR);
- INSERT_PROC_ADDRESS(gl, PopDebugGroupKHR);
- INSERT_PROC_ADDRESS(gl, ObjectLabelKHR);
- INSERT_PROC_ADDRESS(gl, GetObjectLabelKHR);
- INSERT_PROC_ADDRESS(gl, ObjectPtrLabelKHR);
- INSERT_PROC_ADDRESS(gl, GetObjectPtrLabelKHR);
- INSERT_PROC_ADDRESS(gl, GetPointervKHR);
-
- // GLES3 core
- INSERT_PROC_ADDRESS(gl, ReadBuffer);
- INSERT_PROC_ADDRESS(gl, DrawRangeElements);
- INSERT_PROC_ADDRESS(gl, TexImage3D);
- INSERT_PROC_ADDRESS(gl, TexSubImage3D);
- INSERT_PROC_ADDRESS(gl, CopyTexSubImage3D);
- INSERT_PROC_ADDRESS(gl, CompressedTexImage3D);
- INSERT_PROC_ADDRESS(gl, CompressedTexSubImage3D);
- INSERT_PROC_ADDRESS(gl, GenQueries);
- INSERT_PROC_ADDRESS(gl, DeleteQueries);
- INSERT_PROC_ADDRESS(gl, IsQuery);
- INSERT_PROC_ADDRESS(gl, BeginQuery);
- INSERT_PROC_ADDRESS(gl, EndQuery);
- INSERT_PROC_ADDRESS(gl, GetQueryiv);
- INSERT_PROC_ADDRESS(gl, GetQueryObjectuiv);
- INSERT_PROC_ADDRESS(gl, UnmapBuffer);
- INSERT_PROC_ADDRESS(gl, GetBufferPointerv);
- INSERT_PROC_ADDRESS(gl, DrawBuffers);
- INSERT_PROC_ADDRESS(gl, UniformMatrix2x3fv);
- INSERT_PROC_ADDRESS(gl, UniformMatrix3x2fv);
- INSERT_PROC_ADDRESS(gl, UniformMatrix2x4fv);
- INSERT_PROC_ADDRESS(gl, UniformMatrix4x2fv);
- INSERT_PROC_ADDRESS(gl, UniformMatrix3x4fv);
- INSERT_PROC_ADDRESS(gl, UniformMatrix4x3fv);
- INSERT_PROC_ADDRESS(gl, BlitFramebuffer);
- INSERT_PROC_ADDRESS(gl, RenderbufferStorageMultisample);
- INSERT_PROC_ADDRESS(gl, FramebufferTextureLayer);
- INSERT_PROC_ADDRESS(gl, MapBufferRange);
- INSERT_PROC_ADDRESS(gl, FlushMappedBufferRange);
- INSERT_PROC_ADDRESS(gl, BindVertexArray);
- INSERT_PROC_ADDRESS(gl, DeleteVertexArrays);
- INSERT_PROC_ADDRESS(gl, GenVertexArrays);
- INSERT_PROC_ADDRESS(gl, IsVertexArray);
- INSERT_PROC_ADDRESS(gl, GetIntegeri_v);
- INSERT_PROC_ADDRESS(gl, BeginTransformFeedback);
- INSERT_PROC_ADDRESS(gl, EndTransformFeedback);
- INSERT_PROC_ADDRESS(gl, BindBufferRange);
- INSERT_PROC_ADDRESS(gl, BindBufferBase);
- INSERT_PROC_ADDRESS(gl, TransformFeedbackVaryings);
- INSERT_PROC_ADDRESS(gl, GetTransformFeedbackVarying);
- INSERT_PROC_ADDRESS(gl, VertexAttribIPointer);
- INSERT_PROC_ADDRESS(gl, GetVertexAttribIiv);
- INSERT_PROC_ADDRESS(gl, GetVertexAttribIuiv);
- INSERT_PROC_ADDRESS(gl, VertexAttribI4i);
- INSERT_PROC_ADDRESS(gl, VertexAttribI4ui);
- INSERT_PROC_ADDRESS(gl, VertexAttribI4iv);
- INSERT_PROC_ADDRESS(gl, VertexAttribI4uiv);
- INSERT_PROC_ADDRESS(gl, GetUniformuiv);
- INSERT_PROC_ADDRESS(gl, GetFragDataLocation);
- INSERT_PROC_ADDRESS(gl, Uniform1ui);
- INSERT_PROC_ADDRESS(gl, Uniform2ui);
- INSERT_PROC_ADDRESS(gl, Uniform3ui);
- INSERT_PROC_ADDRESS(gl, Uniform4ui);
- INSERT_PROC_ADDRESS(gl, Uniform1uiv);
- INSERT_PROC_ADDRESS(gl, Uniform2uiv);
- INSERT_PROC_ADDRESS(gl, Uniform3uiv);
- INSERT_PROC_ADDRESS(gl, Uniform4uiv);
- INSERT_PROC_ADDRESS(gl, ClearBufferiv);
- INSERT_PROC_ADDRESS(gl, ClearBufferuiv);
- INSERT_PROC_ADDRESS(gl, ClearBufferfv);
- INSERT_PROC_ADDRESS(gl, ClearBufferfi);
- INSERT_PROC_ADDRESS(gl, GetStringi);
- INSERT_PROC_ADDRESS(gl, CopyBufferSubData);
- INSERT_PROC_ADDRESS(gl, GetUniformIndices);
- INSERT_PROC_ADDRESS(gl, GetActiveUniformsiv);
- INSERT_PROC_ADDRESS(gl, GetUniformBlockIndex);
- INSERT_PROC_ADDRESS(gl, GetActiveUniformBlockiv);
- INSERT_PROC_ADDRESS(gl, GetActiveUniformBlockName);
- INSERT_PROC_ADDRESS(gl, UniformBlockBinding);
- INSERT_PROC_ADDRESS(gl, DrawArraysInstanced);
- INSERT_PROC_ADDRESS(gl, DrawElementsInstanced);
- map["glFenceSync"] =
- reinterpret_cast<__eglMustCastToProperFunctionPointerType>(gl::FenceSync_);
- INSERT_PROC_ADDRESS(gl, IsSync);
- INSERT_PROC_ADDRESS(gl, DeleteSync);
- INSERT_PROC_ADDRESS(gl, ClientWaitSync);
- INSERT_PROC_ADDRESS(gl, WaitSync);
- INSERT_PROC_ADDRESS(gl, GetInteger64v);
- INSERT_PROC_ADDRESS(gl, GetSynciv);
- INSERT_PROC_ADDRESS(gl, GetInteger64i_v);
- INSERT_PROC_ADDRESS(gl, GetBufferParameteri64v);
- INSERT_PROC_ADDRESS(gl, GenSamplers);
- INSERT_PROC_ADDRESS(gl, DeleteSamplers);
- INSERT_PROC_ADDRESS(gl, IsSampler);
- INSERT_PROC_ADDRESS(gl, BindSampler);
- INSERT_PROC_ADDRESS(gl, SamplerParameteri);
- INSERT_PROC_ADDRESS(gl, SamplerParameteriv);
- INSERT_PROC_ADDRESS(gl, SamplerParameterf);
- INSERT_PROC_ADDRESS(gl, SamplerParameterfv);
- INSERT_PROC_ADDRESS(gl, GetSamplerParameteriv);
- INSERT_PROC_ADDRESS(gl, GetSamplerParameterfv);
- INSERT_PROC_ADDRESS(gl, VertexAttribDivisor);
- INSERT_PROC_ADDRESS(gl, BindTransformFeedback);
- INSERT_PROC_ADDRESS(gl, DeleteTransformFeedbacks);
- INSERT_PROC_ADDRESS(gl, GenTransformFeedbacks);
- INSERT_PROC_ADDRESS(gl, IsTransformFeedback);
- INSERT_PROC_ADDRESS(gl, PauseTransformFeedback);
- INSERT_PROC_ADDRESS(gl, ResumeTransformFeedback);
- INSERT_PROC_ADDRESS(gl, GetProgramBinary);
- INSERT_PROC_ADDRESS(gl, ProgramBinary);
- INSERT_PROC_ADDRESS(gl, ProgramParameteri);
- INSERT_PROC_ADDRESS(gl, InvalidateFramebuffer);
- INSERT_PROC_ADDRESS(gl, InvalidateSubFramebuffer);
- INSERT_PROC_ADDRESS(gl, TexStorage2D);
- INSERT_PROC_ADDRESS(gl, TexStorage3D);
- INSERT_PROC_ADDRESS(gl, GetInternalformativ);
-
- // EGL 1.0
- INSERT_PROC_ADDRESS(egl, ChooseConfig);
- INSERT_PROC_ADDRESS(egl, CopyBuffers);
- INSERT_PROC_ADDRESS(egl, CreateContext);
- INSERT_PROC_ADDRESS(egl, CreatePbufferSurface);
- INSERT_PROC_ADDRESS(egl, CreatePixmapSurface);
- INSERT_PROC_ADDRESS(egl, CreateWindowSurface);
- INSERT_PROC_ADDRESS(egl, DestroyContext);
- INSERT_PROC_ADDRESS(egl, DestroySurface);
- INSERT_PROC_ADDRESS(egl, GetConfigAttrib);
- INSERT_PROC_ADDRESS(egl, GetConfigs);
- INSERT_PROC_ADDRESS(egl, GetCurrentDisplay);
- INSERT_PROC_ADDRESS(egl, GetCurrentSurface);
- INSERT_PROC_ADDRESS(egl, GetDisplay);
- INSERT_PROC_ADDRESS(egl, GetError);
- INSERT_PROC_ADDRESS(egl, GetProcAddress);
- INSERT_PROC_ADDRESS(egl, Initialize);
- INSERT_PROC_ADDRESS(egl, MakeCurrent);
- INSERT_PROC_ADDRESS(egl, QueryContext);
- INSERT_PROC_ADDRESS(egl, QueryString);
- INSERT_PROC_ADDRESS(egl, QuerySurface);
- INSERT_PROC_ADDRESS(egl, SwapBuffers);
- INSERT_PROC_ADDRESS(egl, Terminate);
- INSERT_PROC_ADDRESS(egl, WaitGL);
- INSERT_PROC_ADDRESS(egl, WaitNative);
-
- // EGL 1.1
- INSERT_PROC_ADDRESS(egl, BindTexImage);
- INSERT_PROC_ADDRESS(egl, ReleaseTexImage);
- INSERT_PROC_ADDRESS(egl, SurfaceAttrib);
- INSERT_PROC_ADDRESS(egl, SwapInterval);
-
- // EGL 1.2
- INSERT_PROC_ADDRESS(egl, BindAPI);
- INSERT_PROC_ADDRESS(egl, QueryAPI);
- INSERT_PROC_ADDRESS(egl, CreatePbufferFromClientBuffer);
- INSERT_PROC_ADDRESS(egl, ReleaseThread);
- INSERT_PROC_ADDRESS(egl, WaitClient);
-
- // EGL 1.4
- INSERT_PROC_ADDRESS(egl, GetCurrentContext);
-
- // EGL 1.5
- INSERT_PROC_ADDRESS(egl, CreateSync);
- INSERT_PROC_ADDRESS(egl, DestroySync);
- INSERT_PROC_ADDRESS(egl, ClientWaitSync);
- INSERT_PROC_ADDRESS(egl, GetSyncAttrib);
- INSERT_PROC_ADDRESS(egl, CreateImage);
- INSERT_PROC_ADDRESS(egl, DestroyImage);
- INSERT_PROC_ADDRESS(egl, GetPlatformDisplay);
- INSERT_PROC_ADDRESS(egl, CreatePlatformWindowSurface);
- INSERT_PROC_ADDRESS(egl, CreatePlatformPixmapSurface);
- INSERT_PROC_ADDRESS(egl, WaitSync);
-
- // EGL_ANGLE_query_surface_pointer
- INSERT_PROC_ADDRESS(egl, QuerySurfacePointerANGLE);
-
- // EGL_NV_post_sub_buffer
- INSERT_PROC_ADDRESS(egl, PostSubBufferNV);
-
- // EGL_EXT_platform_base
- INSERT_PROC_ADDRESS(egl, GetPlatformDisplayEXT);
-
- // EGL_EXT_device_query
- INSERT_PROC_ADDRESS(egl, QueryDisplayAttribEXT);
- INSERT_PROC_ADDRESS(egl, QueryDeviceAttribEXT);
- INSERT_PROC_ADDRESS(egl, QueryDeviceStringEXT);
-
- // EGL_KHR_image_base/EGL_KHR_image
- INSERT_PROC_ADDRESS(egl, CreateImageKHR);
- INSERT_PROC_ADDRESS(egl, DestroyImageKHR);
-
- // EGL_EXT_device_creation
- INSERT_PROC_ADDRESS(egl, CreateDeviceANGLE);
- INSERT_PROC_ADDRESS(egl, ReleaseDeviceANGLE);
-
-#undef INSERT_PROC_ADDRESS
- return map;
- };
-
- static const ProcAddressMap procAddressMap = generateProcAddressMap();
-
- auto iter = procAddressMap.find(procname);
- if (iter != procAddressMap.end())
- {
- return iter->second;
- }
- else
+ ProcEntry *entry =
+ std::lower_bound(&g_procTable[0], &g_procTable[g_numProcs], procname, CompareProc);
+
+ thread->setError(NoError());
+
+ if (entry == &g_procTable[g_numProcs] || strcmp(entry->first, procname) != 0)
{
return nullptr;
}
-}
+ return entry->second;
+}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp
index 6c7e2ffc3d..ee8cdb94dc 100644
--- a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp
@@ -9,9 +9,12 @@
#include "libGLESv2/entry_points_egl_ext.h"
#include "libGLESv2/global_state.h"
+#include "libANGLE/Context.h"
#include "libANGLE/Display.h"
#include "libANGLE/Device.h"
#include "libANGLE/Surface.h"
+#include "libANGLE/Stream.h"
+#include "libANGLE/Thread.h"
#include "libANGLE/validationEGL.h"
#include "common/debug.h"
@@ -24,6 +27,7 @@ EGLBoolean EGLAPIENTRY QuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surfa
{
EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, void **value = 0x%0.8p)",
dpy, surface, attribute, value);
+ Thread *thread = GetCurrentThread();
Display *display = static_cast<Display*>(dpy);
Surface *eglSurface = static_cast<Surface*>(surface);
@@ -31,19 +35,19 @@ EGLBoolean EGLAPIENTRY QuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surfa
Error error = ValidateSurface(display, eglSurface);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
if (!display->getExtensions().querySurfacePointer)
{
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return EGL_FALSE;
}
if (surface == EGL_NO_SURFACE)
{
- SetGlobalError(Error(EGL_BAD_SURFACE));
+ thread->setError(EglBadSurface());
return EGL_FALSE;
}
@@ -55,24 +59,24 @@ EGLBoolean EGLAPIENTRY QuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surfa
case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
if (!display->getExtensions().surfaceD3DTexture2DShareHandle)
{
- SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
+ thread->setError(EglBadAttribute());
return EGL_FALSE;
}
break;
case EGL_DXGI_KEYED_MUTEX_ANGLE:
if (!display->getExtensions().keyedMutex)
{
- SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
+ thread->setError(EglBadAttribute());
return EGL_FALSE;
}
break;
default:
- SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
- return EGL_FALSE;
+ thread->setError(EglBadAttribute());
+ return EGL_FALSE;
}
error = eglSurface->querySurfacePointerANGLE(attribute, value);
- SetGlobalError(error);
+ thread->setError(error);
return (error.isError() ? EGL_FALSE : EGL_TRUE);
}
@@ -81,10 +85,11 @@ EGLBoolean EGLAPIENTRY QuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surfa
EGLBoolean EGLAPIENTRY PostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height)
{
EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint x = %d, EGLint y = %d, EGLint width = %d, EGLint height = %d)", dpy, surface, x, y, width, height);
+ Thread *thread = GetCurrentThread();
if (x < 0 || y < 0 || width < 0 || height < 0)
{
- SetGlobalError(Error(EGL_BAD_PARAMETER));
+ thread->setError(EglBadParameter());
return EGL_FALSE;
}
@@ -94,39 +99,38 @@ EGLBoolean EGLAPIENTRY PostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLin
Error error = ValidateSurface(display, eglSurface);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
- if (display->isDeviceLost())
+ if (display->testDeviceLost())
{
- SetGlobalError(Error(EGL_CONTEXT_LOST));
+ thread->setError(EglContextLost());
return EGL_FALSE;
}
if (surface == EGL_NO_SURFACE)
{
- SetGlobalError(Error(EGL_BAD_SURFACE));
+ thread->setError(EglBadSurface());
return EGL_FALSE;
}
-#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (defined(ANGLE_ENABLE_WINDOWS_STORE) && WINAPI_FAMILY == WINAPI_FAMILY_PC_APP) // Qt WP: Allow this entry point as a workaround
if (!display->getExtensions().postSubBuffer)
{
// Spec is not clear about how this should be handled.
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return EGL_TRUE;
}
-#endif
- error = eglSurface->postSubBuffer(x, y, width, height);
+ // TODO(jmadill): Validate Surface is bound to the thread.
+ error = eglSurface->postSubBuffer(thread->getContext(), x, y, width, height);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return EGL_TRUE;
}
@@ -135,215 +139,25 @@ EGLDisplay EGLAPIENTRY GetPlatformDisplayEXT(EGLenum platform, void *native_disp
{
EVENT("(EGLenum platform = %d, void* native_display = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)",
platform, native_display, attrib_list);
+ Thread *thread = GetCurrentThread();
- const ClientExtensions &clientExtensions = Display::getClientExtensions();
-
- switch (platform)
+ Error err = ValidateGetPlatformDisplayEXT(platform, native_display, attrib_list);
+ thread->setError(err);
+ if (err.isError())
{
- case EGL_PLATFORM_ANGLE_ANGLE:
- if (!clientExtensions.platformANGLE)
- {
- SetGlobalError(Error(EGL_BAD_PARAMETER));
- return EGL_NO_DISPLAY;
- }
- break;
- case EGL_PLATFORM_DEVICE_EXT:
- if (!clientExtensions.platformDevice)
- {
- SetGlobalError(Error(EGL_BAD_PARAMETER, "Platform Device extension is not active"));
- return EGL_NO_DISPLAY;
- }
- break;
- default:
- SetGlobalError(Error(EGL_BAD_CONFIG));
return EGL_NO_DISPLAY;
}
+ const auto &attribMap = AttributeMap::CreateFromIntArray(attrib_list);
if (platform == EGL_PLATFORM_ANGLE_ANGLE)
{
- EGLint platformType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
- EGLint deviceType = EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE;
- bool majorVersionSpecified = false;
- bool minorVersionSpecified = false;
- bool enableAutoTrimSpecified = false;
- bool deviceTypeSpecified = false;
- bool presentPathSpecified = false;
-
- if (attrib_list)
- {
- for (const EGLint *curAttrib = attrib_list; curAttrib[0] != EGL_NONE; curAttrib += 2)
- {
- switch (curAttrib[0])
- {
- case EGL_PLATFORM_ANGLE_TYPE_ANGLE:
- switch (curAttrib[1])
- {
- case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
- break;
-
- case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
- case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
- if (!clientExtensions.platformANGLED3D)
- {
- SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
- return EGL_NO_DISPLAY;
- }
- break;
-
- case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
- case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
- if (!clientExtensions.platformANGLEOpenGL)
- {
- SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
- return EGL_NO_DISPLAY;
- }
- break;
-
- default:
- SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
- return EGL_NO_DISPLAY;
- }
- platformType = curAttrib[1];
- break;
-
- case EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE:
- if (curAttrib[1] != EGL_DONT_CARE)
- {
- majorVersionSpecified = true;
- }
- break;
-
- case EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE:
- if (curAttrib[1] != EGL_DONT_CARE)
- {
- minorVersionSpecified = true;
- }
- break;
-
- case EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE:
- switch (curAttrib[1])
- {
- case EGL_TRUE:
- case EGL_FALSE:
- break;
- default:
- SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
- return EGL_NO_DISPLAY;
- }
- enableAutoTrimSpecified = true;
- break;
-
- case EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE:
- if (!clientExtensions.experimentalPresentPath)
- {
- SetGlobalError(
- Error(EGL_BAD_ATTRIBUTE,
- "EGL_ANGLE_experimental_present_path extension not active"));
- return EGL_NO_DISPLAY;
- }
-
- switch (curAttrib[1])
- {
- case EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE:
- case EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE:
- break;
- default:
- SetGlobalError(
- Error(EGL_BAD_ATTRIBUTE,
- "Invalid value for EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE"));
- return EGL_NO_DISPLAY;
- }
- presentPathSpecified = true;
- break;
-
- case EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE:
- switch (curAttrib[1])
- {
- case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
- case EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE:
- case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE:
- deviceTypeSpecified = true;
- break;
-
- case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
- // This is a hidden option, accepted by the OpenGL back-end.
- break;
-
- default:
- SetGlobalError(Error(EGL_BAD_ATTRIBUTE,
- "Invalid value for "
- "EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE "
- "attrib"));
- return EGL_NO_DISPLAY;
- }
- deviceType = curAttrib[1];
- break;
-
- default:
- break;
- }
- }
- }
-
- if (!majorVersionSpecified && minorVersionSpecified)
- {
- SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
- return EGL_NO_DISPLAY;
- }
-
- if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE &&
- platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
- {
- SetGlobalError(
- Error(EGL_BAD_ATTRIBUTE,
- "EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE requires a device type of "
- "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE."));
- return EGL_NO_DISPLAY;
- }
-
- if (enableAutoTrimSpecified && platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
- {
- SetGlobalError(
- Error(EGL_BAD_ATTRIBUTE,
- "EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE requires a device type of "
- "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE."));
- return EGL_NO_DISPLAY;
- }
-
- if (presentPathSpecified && platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
- {
- SetGlobalError(Error(EGL_BAD_ATTRIBUTE,
- "EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE requires a device type of "
- "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE."));
- return EGL_NO_DISPLAY;
- }
-
- if (deviceTypeSpecified && platformType != EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE &&
- platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
- {
- SetGlobalError(
- Error(EGL_BAD_ATTRIBUTE,
- "EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE requires a device type of "
- "EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE or EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE."));
- return EGL_NO_DISPLAY;
- }
-
- SetGlobalError(Error(EGL_SUCCESS));
- return Display::GetDisplayFromAttribs(native_display, AttributeMap(attrib_list));
+ return Display::GetDisplayFromNativeDisplay(
+ gl::bitCast<EGLNativeDisplayType>(native_display), attribMap);
}
else if (platform == EGL_PLATFORM_DEVICE_EXT)
{
Device *eglDevice = reinterpret_cast<Device *>(native_display);
- if (eglDevice == nullptr || !Device::IsValidDevice(eglDevice))
- {
- SetGlobalError(Error(EGL_BAD_ATTRIBUTE,
- "native_display should be a valid EGL device if platform equals "
- "EGL_PLATFORM_DEVICE_EXT"));
- return EGL_NO_DISPLAY;
- }
-
- SetGlobalError(Error(EGL_SUCCESS));
- return Display::GetDisplayFromDevice(native_display);
+ return Display::GetDisplayFromDevice(eglDevice, attribMap);
}
else
{
@@ -357,11 +171,12 @@ EGLBoolean EGLAPIENTRY QueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribut
{
EVENT("(EGLDeviceEXT device = 0x%0.8p, EGLint attribute = %d, EGLAttrib *value = 0x%0.8p)",
device, attribute, value);
+ Thread *thread = GetCurrentThread();
Device *dev = static_cast<Device*>(device);
if (dev == EGL_NO_DEVICE_EXT || !Device::IsValidDevice(dev))
{
- SetGlobalError(Error(EGL_BAD_ACCESS));
+ thread->setError(EglBadAccess());
return EGL_FALSE;
}
@@ -370,13 +185,13 @@ EGLBoolean EGLAPIENTRY QueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribut
Display *owningDisplay = dev->getOwningDisplay();
if (owningDisplay != nullptr && !owningDisplay->getExtensions().deviceQuery)
{
- SetGlobalError(Error(EGL_BAD_ACCESS,
- "Device wasn't created using eglCreateDeviceANGLE, and the Display "
- "that created it doesn't support device querying"));
+ thread->setError(EglBadAccess() << "Device wasn't created using eglCreateDeviceANGLE, "
+ "and the Display that created it doesn't support "
+ "device querying");
return EGL_FALSE;
}
- Error error(EGL_SUCCESS);
+ Error error(NoError());
// validate the attribute parameter
switch (attribute)
@@ -385,17 +200,17 @@ EGLBoolean EGLAPIENTRY QueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribut
case EGL_D3D9_DEVICE_ANGLE:
if (!dev->getExtensions().deviceD3D || dev->getType() != attribute)
{
- SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
+ thread->setError(EglBadAttribute());
return EGL_FALSE;
}
error = dev->getDevice(value);
break;
default:
- SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
- return EGL_FALSE;
+ thread->setError(EglBadAttribute());
+ return EGL_FALSE;
}
- SetGlobalError(error);
+ thread->setError(error);
return (error.isError() ? EGL_FALSE : EGL_TRUE);
}
@@ -404,11 +219,12 @@ const char * EGLAPIENTRY QueryDeviceStringEXT(EGLDeviceEXT device, EGLint name)
{
EVENT("(EGLDeviceEXT device = 0x%0.8p, EGLint name = %d)",
device, name);
+ Thread *thread = GetCurrentThread();
Device *dev = static_cast<Device*>(device);
if (dev == EGL_NO_DEVICE_EXT || !Device::IsValidDevice(dev))
{
- SetGlobalError(Error(EGL_BAD_DEVICE_EXT));
+ thread->setError(EglBadDevice());
return nullptr;
}
@@ -419,11 +235,11 @@ const char * EGLAPIENTRY QueryDeviceStringEXT(EGLDeviceEXT device, EGLint name)
result = dev->getExtensionString().c_str();
break;
default:
- SetGlobalError(Error(EGL_BAD_DEVICE_EXT));
- return nullptr;
+ thread->setError(EglBadDevice());
+ return nullptr;
}
- SetGlobalError(Error(EGL_SUCCESS));
+ thread->setError(NoError());
return result;
}
@@ -432,13 +248,20 @@ EGLBoolean EGLAPIENTRY QueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute, E
{
EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint attribute = %d, EGLAttrib *value = 0x%0.8p)",
dpy, attribute, value);
+ Thread *thread = GetCurrentThread();
Display *display = static_cast<Display*>(dpy);
- Error error(EGL_SUCCESS);
+
+ Error error = ValidateDisplay(display);
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_FALSE;
+ }
if (!display->getExtensions().deviceQuery)
{
- SetGlobalError(Error(EGL_BAD_ACCESS));
+ thread->setError(EglBadAccess());
return EGL_FALSE;
}
@@ -450,11 +273,11 @@ EGLBoolean EGLAPIENTRY QueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute, E
break;
default:
- SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
- return EGL_FALSE;
+ thread->setError(EglBadAttribute());
+ return EGL_FALSE;
}
- SetGlobalError(error);
+ thread->setError(error);
return (error.isError() ? EGL_FALSE : EGL_TRUE);
}
@@ -468,23 +291,24 @@ ANGLE_EXPORT EGLImageKHR EGLAPIENTRY CreateImageKHR(EGLDisplay dpy,
"(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLenum target = 0x%X, "
"EGLClientBuffer buffer = 0x%0.8p, const EGLAttrib *attrib_list = 0x%0.8p)",
dpy, ctx, target, buffer, attrib_list);
+ Thread *thread = GetCurrentThread();
Display *display = static_cast<Display *>(dpy);
gl::Context *context = static_cast<gl::Context *>(ctx);
- AttributeMap attributes(attrib_list);
+ AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list);
Error error = ValidateCreateImageKHR(display, context, target, buffer, attributes);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_NO_IMAGE;
}
Image *image = nullptr;
- error = display->createImage(context, target, buffer, attributes, &image);
+ error = display->createImage(context, target, buffer, attributes, &image);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_NO_IMAGE;
}
@@ -494,6 +318,7 @@ ANGLE_EXPORT EGLImageKHR EGLAPIENTRY CreateImageKHR(EGLDisplay dpy,
ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
{
EVENT("(EGLDisplay dpy = 0x%0.8p, EGLImage image = 0x%0.8p)", dpy, image);
+ Thread *thread = GetCurrentThread();
Display *display = static_cast<Display *>(dpy);
Image *img = static_cast<Image *>(image);
@@ -501,7 +326,7 @@ ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroyImageKHR(EGLDisplay dpy, EGLImageKHR
Error error = ValidateDestroyImageKHR(display, img);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
@@ -518,11 +343,12 @@ ANGLE_EXPORT EGLDeviceEXT EGLAPIENTRY CreateDeviceANGLE(EGLint device_type,
"(EGLint device_type = %d, void* native_device = 0x%0.8p, const EGLAttrib* attrib_list = "
"0x%0.8p)",
device_type, native_device, attrib_list);
+ Thread *thread = GetCurrentThread();
Error error = ValidateCreateDeviceANGLE(device_type, native_device, attrib_list);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_NO_DEVICE_EXT;
}
@@ -531,7 +357,7 @@ ANGLE_EXPORT EGLDeviceEXT EGLAPIENTRY CreateDeviceANGLE(EGLint device_type,
if (error.isError())
{
ASSERT(device == nullptr);
- SetGlobalError(error);
+ thread->setError(error);
return EGL_NO_DEVICE_EXT;
}
@@ -541,13 +367,14 @@ ANGLE_EXPORT EGLDeviceEXT EGLAPIENTRY CreateDeviceANGLE(EGLint device_type,
ANGLE_EXPORT EGLBoolean EGLAPIENTRY ReleaseDeviceANGLE(EGLDeviceEXT device)
{
EVENT("(EGLDeviceEXT device = 0x%0.8p)", device);
+ Thread *thread = GetCurrentThread();
Device *dev = static_cast<Device *>(device);
Error error = ValidateReleaseDeviceANGLE(dev);
if (error.isError())
{
- SetGlobalError(error);
+ thread->setError(error);
return EGL_FALSE;
}
@@ -555,4 +382,475 @@ ANGLE_EXPORT EGLBoolean EGLAPIENTRY ReleaseDeviceANGLE(EGLDeviceEXT device)
return EGL_TRUE;
}
+
+// EGL_KHR_stream
+EGLStreamKHR EGLAPIENTRY CreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, const EGLAttrib* attrib_list = 0x%0.8p)", dpy, attrib_list);
+ Thread *thread = GetCurrentThread();
+
+ Display *display = static_cast<Display *>(dpy);
+ AttributeMap attributes = AttributeMap::CreateFromIntArray(attrib_list);
+
+ Error error = ValidateCreateStreamKHR(display, attributes);
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_NO_STREAM_KHR;
+ }
+
+ Stream *stream;
+ error = display->createStream(attributes, &stream);
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_NO_STREAM_KHR;
+ }
+
+ thread->setError(error);
+ return static_cast<EGLStreamKHR>(stream);
+}
+
+EGLBoolean EGLAPIENTRY DestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR = 0x%0.8p)", dpy, stream);
+ Thread *thread = GetCurrentThread();
+
+ Display *display = static_cast<Display *>(dpy);
+ Stream *streamObject = static_cast<Stream *>(stream);
+
+ Error error = ValidateDestroyStreamKHR(display, streamObject);
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_FALSE;
+ }
+
+ display->destroyStream(streamObject);
+ thread->setError(error);
+ return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY StreamAttribKHR(EGLDisplay dpy,
+ EGLStreamKHR stream,
+ EGLenum attribute,
+ EGLint value)
+{
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR stream = 0x%0.8p, EGLenum attribute = 0x%X, "
+ "EGLint value = 0x%X)",
+ dpy, stream, attribute, value);
+ Thread *thread = GetCurrentThread();
+
+ Display *display = static_cast<Display *>(dpy);
+ Stream *streamObject = static_cast<Stream *>(stream);
+
+ Error error = ValidateStreamAttribKHR(display, streamObject, attribute, value);
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_FALSE;
+ }
+
+ switch (attribute)
+ {
+ case EGL_CONSUMER_LATENCY_USEC_KHR:
+ streamObject->setConsumerLatency(value);
+ break;
+ case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
+ streamObject->setConsumerAcquireTimeout(value);
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ thread->setError(error);
+ return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY QueryStreamKHR(EGLDisplay dpy,
+ EGLStreamKHR stream,
+ EGLenum attribute,
+ EGLint *value)
+{
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR stream = 0x%0.8p, EGLenum attribute = 0x%X, "
+ "EGLint value = 0x%0.8p)",
+ dpy, stream, attribute, value);
+ Thread *thread = GetCurrentThread();
+
+ Display *display = static_cast<Display *>(dpy);
+ Stream *streamObject = static_cast<Stream *>(stream);
+
+ Error error = ValidateQueryStreamKHR(display, streamObject, attribute, value);
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_FALSE;
+ }
+
+ switch (attribute)
+ {
+ case EGL_STREAM_STATE_KHR:
+ *value = streamObject->getState();
+ break;
+ case EGL_CONSUMER_LATENCY_USEC_KHR:
+ *value = streamObject->getConsumerLatency();
+ break;
+ case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
+ *value = streamObject->getConsumerAcquireTimeout();
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ thread->setError(error);
+ return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY QueryStreamu64KHR(EGLDisplay dpy,
+ EGLStreamKHR stream,
+ EGLenum attribute,
+ EGLuint64KHR *value)
+{
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR stream = 0x%0.8p, EGLenum attribute = 0x%X, "
+ "EGLuint64KHR value = 0x%0.8p)",
+ dpy, stream, attribute, value);
+ Thread *thread = GetCurrentThread();
+
+ Display *display = static_cast<Display *>(dpy);
+ Stream *streamObject = static_cast<Stream *>(stream);
+
+ Error error = ValidateQueryStreamu64KHR(display, streamObject, attribute, value);
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_FALSE;
+ }
+
+ switch (attribute)
+ {
+ case EGL_PRODUCER_FRAME_KHR:
+ *value = streamObject->getProducerFrame();
+ break;
+ case EGL_CONSUMER_FRAME_KHR:
+ *value = streamObject->getConsumerFrame();
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ thread->setError(error);
+ return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY StreamConsumerGLTextureExternalKHR(EGLDisplay dpy, EGLStreamKHR stream)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR = 0x%0.8p)", dpy, stream);
+ Thread *thread = GetCurrentThread();
+
+ Display *display = static_cast<Display *>(dpy);
+ Stream *streamObject = static_cast<Stream *>(stream);
+ gl::Context *context = gl::GetValidGlobalContext();
+
+ Error error = ValidateStreamConsumerGLTextureExternalKHR(display, context, streamObject);
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_FALSE;
+ }
+
+ error = streamObject->createConsumerGLTextureExternal(AttributeMap(), context);
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_FALSE;
+ }
+
+ thread->setError(error);
+ return EGL_TRUE;
}
+
+EGLBoolean EGLAPIENTRY StreamConsumerAcquireKHR(EGLDisplay dpy, EGLStreamKHR stream)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR = 0x%0.8p)", dpy, stream);
+ Thread *thread = GetCurrentThread();
+
+ Display *display = static_cast<Display *>(dpy);
+ Stream *streamObject = static_cast<Stream *>(stream);
+ gl::Context *context = gl::GetValidGlobalContext();
+
+ Error error = ValidateStreamConsumerAcquireKHR(display, context, streamObject);
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_FALSE;
+ }
+
+ error = streamObject->consumerAcquire(context);
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_FALSE;
+ }
+
+ thread->setError(error);
+ return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY StreamConsumerReleaseKHR(EGLDisplay dpy, EGLStreamKHR stream)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR = 0x%0.8p)", dpy, stream);
+ Thread *thread = GetCurrentThread();
+
+ Display *display = static_cast<Display *>(dpy);
+ Stream *streamObject = static_cast<Stream *>(stream);
+ gl::Context *context = gl::GetValidGlobalContext();
+
+ Error error = ValidateStreamConsumerReleaseKHR(display, context, streamObject);
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_FALSE;
+ }
+
+ error = streamObject->consumerRelease(context);
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_FALSE;
+ }
+
+ thread->setError(error);
+ return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY StreamConsumerGLTextureExternalAttribsNV(EGLDisplay dpy,
+ EGLStreamKHR stream,
+ const EGLAttrib *attrib_list)
+{
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR stream = 0x%0.8p, EGLAttrib attrib_list = 0x%0.8p",
+ dpy, stream, attrib_list);
+ Thread *thread = GetCurrentThread();
+
+ Display *display = static_cast<Display *>(dpy);
+ Stream *streamObject = static_cast<Stream *>(stream);
+ gl::Context *context = gl::GetValidGlobalContext();
+ AttributeMap attributes = AttributeMap::CreateFromAttribArray(attrib_list);
+
+ Error error = ValidateStreamConsumerGLTextureExternalAttribsNV(display, context, streamObject,
+ attributes);
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_FALSE;
+ }
+
+ error = streamObject->createConsumerGLTextureExternal(attributes, context);
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_FALSE;
+ }
+
+ thread->setError(error);
+ return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY CreateStreamProducerD3DTextureNV12ANGLE(EGLDisplay dpy,
+ EGLStreamKHR stream,
+ const EGLAttrib *attrib_list)
+{
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR stream = 0x%0.8p, EGLAttrib attrib_list = 0x%0.8p",
+ dpy, stream, attrib_list);
+ Thread *thread = GetCurrentThread();
+
+ Display *display = static_cast<Display *>(dpy);
+ Stream *streamObject = static_cast<Stream *>(stream);
+ AttributeMap attributes = AttributeMap::CreateFromAttribArray(attrib_list);
+
+ Error error =
+ ValidateCreateStreamProducerD3DTextureNV12ANGLE(display, streamObject, attributes);
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_FALSE;
+ }
+
+ error = streamObject->createProducerD3D11TextureNV12(attributes);
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_FALSE;
+ }
+
+ thread->setError(error);
+ return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY StreamPostD3DTextureNV12ANGLE(EGLDisplay dpy,
+ EGLStreamKHR stream,
+ void *texture,
+ const EGLAttrib *attrib_list)
+{
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLStreamKHR stream = 0x%0.8p, void* texture = 0x%0.8p, "
+ "EGLAttrib attrib_list = 0x%0.8p",
+ dpy, stream, texture, attrib_list);
+ Thread *thread = GetCurrentThread();
+
+ Display *display = static_cast<Display *>(dpy);
+ Stream *streamObject = static_cast<Stream *>(stream);
+ AttributeMap attributes = AttributeMap::CreateFromAttribArray(attrib_list);
+
+ Error error = ValidateStreamPostD3DTextureNV12ANGLE(display, streamObject, texture, attributes);
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_FALSE;
+ }
+
+ error = streamObject->postD3D11NV12Texture(texture, attributes);
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_FALSE;
+ }
+
+ thread->setError(error);
+ return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY GetSyncValuesCHROMIUM(EGLDisplay dpy,
+ EGLSurface surface,
+ EGLuint64KHR *ust,
+ EGLuint64KHR *msc,
+ EGLuint64KHR *sbc)
+{
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLuint64KHR* ust = 0x%0.8p, "
+ "EGLuint64KHR* msc = 0x%0.8p, EGLuint64KHR* sbc = 0x%0.8p",
+ dpy, surface, ust, msc, sbc);
+ Thread *thread = GetCurrentThread();
+
+ Display *display = static_cast<Display *>(dpy);
+ Surface *eglSurface = static_cast<Surface *>(surface);
+
+ Error error = ValidateGetSyncValuesCHROMIUM(display, eglSurface, ust, msc, sbc);
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_FALSE;
+ }
+
+ error = eglSurface->getSyncValues(ust, msc, sbc);
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_FALSE;
+ }
+
+ thread->setError(error);
+ return EGL_TRUE;
+}
+
+ANGLE_EXPORT EGLBoolean SwapBuffersWithDamageEXT(EGLDisplay dpy,
+ EGLSurface surface,
+ EGLint *rects,
+ EGLint n_rects)
+{
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint *rects = 0x%0.8p, EGLint "
+ "n_rects = %d)",
+ dpy, surface, rects, n_rects);
+ Thread *thread = GetCurrentThread();
+
+ Display *display = static_cast<Display *>(dpy);
+ Surface *eglSurface = static_cast<Surface *>(surface);
+
+ Error error = ValidateSwapBuffersWithDamageEXT(display, eglSurface, rects, n_rects);
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_FALSE;
+ }
+
+ error = eglSurface->swapWithDamage(thread->getContext(), rects, n_rects);
+ if (error.isError())
+ {
+ thread->setError(error);
+ return EGL_FALSE;
+ }
+
+ return EGL_TRUE;
+}
+
+EGLint EGLAPIENTRY ProgramCacheGetAttribANGLE(EGLDisplay dpy, EGLenum attrib)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum attrib = 0x%X)", dpy, attrib);
+
+ Display *display = static_cast<Display *>(dpy);
+ Thread *thread = GetCurrentThread();
+
+ ANGLE_EGL_TRY_RETURN(thread, ValidateProgramCacheGetAttribANGLE(display, attrib), 0);
+
+ return display->programCacheGetAttrib(attrib);
+}
+
+void EGLAPIENTRY ProgramCacheQueryANGLE(EGLDisplay dpy,
+ EGLint index,
+ void *key,
+ EGLint *keysize,
+ void *binary,
+ EGLint *binarysize)
+{
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, EGLint index = %d, void *key = 0x%0.8p, EGLint *keysize = "
+ "0x%0.8p, void *binary = 0x%0.8p, EGLint *size = 0x%0.8p)",
+ dpy, index, key, keysize, binary, binarysize);
+
+ Display *display = static_cast<Display *>(dpy);
+ Thread *thread = GetCurrentThread();
+
+ ANGLE_EGL_TRY(thread,
+ ValidateProgramCacheQueryANGLE(display, index, key, keysize, binary, binarysize));
+
+ ANGLE_EGL_TRY(thread, display->programCacheQuery(index, key, keysize, binary, binarysize));
+}
+
+void EGLAPIENTRY ProgramCachePopulateANGLE(EGLDisplay dpy,
+ const void *key,
+ EGLint keysize,
+ const void *binary,
+ EGLint binarysize)
+{
+ EVENT(
+ "(EGLDisplay dpy = 0x%0.8p, void *key = 0x%0.8p, EGLint keysize = %d, void *binary = "
+ "0x%0.8p, EGLint *size = 0x%0.8p)",
+ dpy, key, keysize, binary, binarysize);
+
+ Display *display = static_cast<Display *>(dpy);
+ Thread *thread = GetCurrentThread();
+
+ ANGLE_EGL_TRY(thread,
+ ValidateProgramCachePopulateANGLE(display, key, keysize, binary, binarysize));
+
+ ANGLE_EGL_TRY(thread, display->programCachePopulate(key, keysize, binary, binarysize));
+}
+
+EGLint EGLAPIENTRY ProgramCacheResizeANGLE(EGLDisplay dpy, EGLint limit, EGLenum mode)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint limit = %d, EGLenum mode = 0x%X)", dpy, limit, mode);
+
+ Display *display = static_cast<Display *>(dpy);
+ Thread *thread = GetCurrentThread();
+
+ ANGLE_EGL_TRY_RETURN(thread, ValidateProgramCacheResizeANGLE(display, limit, mode), 0);
+
+ return display->programCacheResize(limit, mode);
+}
+
+} // namespace egl
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.h b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.h
index d64fa6e483..3cde6ec9c6 100644
--- a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.h
+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.h
@@ -43,6 +43,71 @@ ANGLE_EXPORT EGLDeviceEXT EGLAPIENTRY CreateDeviceANGLE(EGLint device_type,
void *native_device,
const EGLAttrib *attrib_list);
ANGLE_EXPORT EGLBoolean EGLAPIENTRY ReleaseDeviceANGLE(EGLDeviceEXT device);
-}
+
+// EGL_KHR_stream
+ANGLE_EXPORT EGLStreamKHR EGLAPIENTRY CreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY StreamAttribKHR(EGLDisplay dpy,
+ EGLStreamKHR stream,
+ EGLenum attribute,
+ EGLint value);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY QueryStreamKHR(EGLDisplay dpy,
+ EGLStreamKHR stream,
+ EGLenum attribute,
+ EGLint *value);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY QueryStreamu64KHR(EGLDisplay dpy,
+ EGLStreamKHR stream,
+ EGLenum attribute,
+ EGLuint64KHR *value);
+
+// EGL_KHR_stream_consumer_gltexture
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY StreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
+ EGLStreamKHR stream);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY StreamConsumerAcquireKHR(EGLDisplay dpy, EGLStreamKHR stream);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY StreamConsumerReleaseKHR(EGLDisplay dpy, EGLStreamKHR stream);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY
+StreamConsumerGLTextureExternalAttribsNV(EGLDisplay dpy,
+ EGLStreamKHR stream,
+ const EGLAttrib *attrib_list);
+
+// EGL_ANGLE_stream_producer_d3d_texture_nv12
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY
+CreateStreamProducerD3DTextureNV12ANGLE(EGLDisplay dpy,
+ EGLStreamKHR stream,
+ const EGLAttrib *attrib_list);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY StreamPostD3DTextureNV12ANGLE(EGLDisplay dpy,
+ EGLStreamKHR stream,
+ void *texture,
+ const EGLAttrib *attrib_list);
+
+// EGL_CHROMIUM_get_sync_values
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY GetSyncValuesCHROMIUM(EGLDisplay dpy,
+ EGLSurface surface,
+ EGLuint64KHR *ust,
+ EGLuint64KHR *msc,
+ EGLuint64KHR *sbc);
+
+// EGL_EXT_swap_buffers_with_damage
+ANGLE_EXPORT EGLBoolean SwapBuffersWithDamageEXT(EGLDisplay dpy,
+ EGLSurface surface,
+ EGLint *rects,
+ EGLint n_rects);
+
+//
+ANGLE_EXPORT EGLint EGLAPIENTRY ProgramCacheGetAttribANGLE(EGLDisplay dpy, EGLenum attrib);
+ANGLE_EXPORT void EGLAPIENTRY ProgramCacheQueryANGLE(EGLDisplay dpy,
+ EGLint index,
+ void *key,
+ EGLint *keysize,
+ void *binary,
+ EGLint *binarysize);
+ANGLE_EXPORT void EGLAPIENTRY ProgramCachePopulateANGLE(EGLDisplay dpy,
+ const void *key,
+ EGLint keysize,
+ const void *binary,
+ EGLint binarysize);
+ANGLE_EXPORT EGLint EGLAPIENTRY ProgramCacheResizeANGLE(EGLDisplay dpy, EGLint limit, EGLenum mode);
+
+} // namespace egl
#endif // LIBGLESV2_ENTRYPOINTSEGLEXT_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.cpp
deleted file mode 100644
index 336b320ba5..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.cpp
+++ /dev/null
@@ -1,4155 +0,0 @@
-//
-// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// entry_points_gles_2_0.cpp : Implements the GLES 2.0 entry points.
-
-#include "libGLESv2/entry_points_gles_2_0.h"
-#include "libGLESv2/global_state.h"
-
-#include "libANGLE/formatutils.h"
-#include "libANGLE/Buffer.h"
-#include "libANGLE/Compiler.h"
-#include "libANGLE/Context.h"
-#include "libANGLE/Error.h"
-#include "libANGLE/Framebuffer.h"
-#include "libANGLE/Renderbuffer.h"
-#include "libANGLE/Shader.h"
-#include "libANGLE/Program.h"
-#include "libANGLE/Texture.h"
-#include "libANGLE/VertexArray.h"
-#include "libANGLE/VertexAttribute.h"
-#include "libANGLE/FramebufferAttachment.h"
-
-#include "libANGLE/validationES.h"
-#include "libANGLE/validationES2.h"
-#include "libANGLE/validationES3.h"
-#include "libANGLE/queryconversions.h"
-
-#include "common/debug.h"
-#include "common/utilities.h"
-#include "common/version.h"
-
-namespace gl
-{
-
-void GL_APIENTRY ActiveTexture(GLenum texture)
-{
- EVENT("(GLenum texture = 0x%X)", texture);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- context->getState().setActiveSampler(texture - GL_TEXTURE0);
- }
-}
-
-void GL_APIENTRY AttachShader(GLuint program, GLuint shader)
-{
- EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- Program *programObject = GetValidProgram(context, program);
- if (!programObject)
- {
- return;
- }
-
- Shader *shaderObject = GetValidShader(context, shader);
- if (!shaderObject)
- {
- return;
- }
-
- if (!programObject->attachShader(shaderObject))
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
- }
-}
-
-void GL_APIENTRY BindAttribLocation(GLuint program, GLuint index, const GLchar* name)
-{
- EVENT("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- Program *programObject = GetValidProgram(context, program);
-
- if (!programObject)
- {
- return;
- }
-
- if (strncmp(name, "gl_", 3) == 0)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- programObject->bindAttributeLocation(index, name);
- }
-}
-
-void GL_APIENTRY BindBuffer(GLenum target, GLuint buffer)
-{
- EVENT("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidBufferTarget(context, target))
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (target)
- {
- case GL_ARRAY_BUFFER:
- context->bindArrayBuffer(buffer);
- return;
- case GL_ELEMENT_ARRAY_BUFFER:
- context->bindElementArrayBuffer(buffer);
- return;
- case GL_COPY_READ_BUFFER:
- context->bindCopyReadBuffer(buffer);
- return;
- case GL_COPY_WRITE_BUFFER:
- context->bindCopyWriteBuffer(buffer);
- return;
- case GL_PIXEL_PACK_BUFFER:
- context->bindPixelPackBuffer(buffer);
- return;
- case GL_PIXEL_UNPACK_BUFFER:
- context->bindPixelUnpackBuffer(buffer);
- return;
- case GL_UNIFORM_BUFFER:
- context->bindGenericUniformBuffer(buffer);
- return;
- case GL_TRANSFORM_FEEDBACK_BUFFER:
- context->bindGenericTransformFeedbackBuffer(buffer);
- return;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- }
-}
-
-void GL_APIENTRY BindFramebuffer(GLenum target, GLuint framebuffer)
-{
- EVENT("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidFramebufferTarget(target))
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- if (target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
- {
- context->bindReadFramebuffer(framebuffer);
- }
-
- if (target == GL_DRAW_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
- {
- context->bindDrawFramebuffer(framebuffer);
- }
- }
-}
-
-void GL_APIENTRY BindRenderbuffer(GLenum target, GLuint renderbuffer)
-{
- EVENT("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (target != GL_RENDERBUFFER)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- context->bindRenderbuffer(renderbuffer);
- }
-}
-
-void GL_APIENTRY BindTexture(GLenum target, GLuint texture)
-{
- EVENT("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- Texture *textureObject = context->getTexture(texture);
-
- if (textureObject && textureObject->getTarget() != target && texture != 0)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- switch (target)
- {
- case GL_TEXTURE_2D:
- case GL_TEXTURE_CUBE_MAP:
- break;
-
- case GL_TEXTURE_3D:
- case GL_TEXTURE_2D_ARRAY:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- context->bindTexture(target, texture);
- }
-}
-
-void GL_APIENTRY BlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
-{
- EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
- red, green, blue, alpha);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- context->getState().setBlendColor(clamp01(red), clamp01(green), clamp01(blue), clamp01(alpha));
- }
-}
-
-void GL_APIENTRY BlendEquation(GLenum mode)
-{
- BlendEquationSeparate(mode, mode);
-}
-
-void GL_APIENTRY BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
-{
- EVENT("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- switch (modeRGB)
- {
- case GL_FUNC_ADD:
- case GL_FUNC_SUBTRACT:
- case GL_FUNC_REVERSE_SUBTRACT:
- case GL_MIN:
- case GL_MAX:
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (modeAlpha)
- {
- case GL_FUNC_ADD:
- case GL_FUNC_SUBTRACT:
- case GL_FUNC_REVERSE_SUBTRACT:
- case GL_MIN:
- case GL_MAX:
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- context->getState().setBlendEquation(modeRGB, modeAlpha);
- }
-}
-
-void GL_APIENTRY BlendFunc(GLenum sfactor, GLenum dfactor)
-{
- BlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
-}
-
-void GL_APIENTRY BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
-{
- EVENT("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",
- srcRGB, dstRGB, srcAlpha, dstAlpha);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- switch (srcRGB)
- {
- case GL_ZERO:
- case GL_ONE:
- case GL_SRC_COLOR:
- case GL_ONE_MINUS_SRC_COLOR:
- case GL_DST_COLOR:
- case GL_ONE_MINUS_DST_COLOR:
- case GL_SRC_ALPHA:
- case GL_ONE_MINUS_SRC_ALPHA:
- case GL_DST_ALPHA:
- case GL_ONE_MINUS_DST_ALPHA:
- case GL_CONSTANT_COLOR:
- case GL_ONE_MINUS_CONSTANT_COLOR:
- case GL_CONSTANT_ALPHA:
- case GL_ONE_MINUS_CONSTANT_ALPHA:
- case GL_SRC_ALPHA_SATURATE:
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (dstRGB)
- {
- case GL_ZERO:
- case GL_ONE:
- case GL_SRC_COLOR:
- case GL_ONE_MINUS_SRC_COLOR:
- case GL_DST_COLOR:
- case GL_ONE_MINUS_DST_COLOR:
- case GL_SRC_ALPHA:
- case GL_ONE_MINUS_SRC_ALPHA:
- case GL_DST_ALPHA:
- case GL_ONE_MINUS_DST_ALPHA:
- case GL_CONSTANT_COLOR:
- case GL_ONE_MINUS_CONSTANT_COLOR:
- case GL_CONSTANT_ALPHA:
- case GL_ONE_MINUS_CONSTANT_ALPHA:
- break;
-
- case GL_SRC_ALPHA_SATURATE:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (srcAlpha)
- {
- case GL_ZERO:
- case GL_ONE:
- case GL_SRC_COLOR:
- case GL_ONE_MINUS_SRC_COLOR:
- case GL_DST_COLOR:
- case GL_ONE_MINUS_DST_COLOR:
- case GL_SRC_ALPHA:
- case GL_ONE_MINUS_SRC_ALPHA:
- case GL_DST_ALPHA:
- case GL_ONE_MINUS_DST_ALPHA:
- case GL_CONSTANT_COLOR:
- case GL_ONE_MINUS_CONSTANT_COLOR:
- case GL_CONSTANT_ALPHA:
- case GL_ONE_MINUS_CONSTANT_ALPHA:
- case GL_SRC_ALPHA_SATURATE:
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (dstAlpha)
- {
- case GL_ZERO:
- case GL_ONE:
- case GL_SRC_COLOR:
- case GL_ONE_MINUS_SRC_COLOR:
- case GL_DST_COLOR:
- case GL_ONE_MINUS_DST_COLOR:
- case GL_SRC_ALPHA:
- case GL_ONE_MINUS_SRC_ALPHA:
- case GL_DST_ALPHA:
- case GL_ONE_MINUS_DST_ALPHA:
- case GL_CONSTANT_COLOR:
- case GL_ONE_MINUS_CONSTANT_COLOR:
- case GL_CONSTANT_ALPHA:
- case GL_ONE_MINUS_CONSTANT_ALPHA:
- break;
-
- case GL_SRC_ALPHA_SATURATE:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc)
- {
- bool constantColorUsed =
- (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
- dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
-
- bool constantAlphaUsed =
- (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
- dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
-
- if (constantColorUsed && constantAlphaUsed)
- {
- ERR(
- "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
- "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
- "implementation.");
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
- }
-
- context->getState().setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
- }
-}
-
-void GL_APIENTRY BufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
-{
- EVENT("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)",
- target, size, data, usage);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (size < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- switch (usage)
- {
- case GL_STREAM_DRAW:
- case GL_STATIC_DRAW:
- case GL_DYNAMIC_DRAW:
- break;
-
- case GL_STREAM_READ:
- case GL_STREAM_COPY:
- case GL_STATIC_READ:
- case GL_STATIC_COPY:
- case GL_DYNAMIC_READ:
- case GL_DYNAMIC_COPY:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- if (!ValidBufferTarget(context, target))
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- Buffer *buffer = context->getState().getTargetBuffer(target);
-
- if (!buffer)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- Error error = buffer->bufferData(data, size, usage);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
-{
- EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)",
- target, offset, size, data);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (size < 0 || offset < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- if (!ValidBufferTarget(context, target))
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- Buffer *buffer = context->getState().getTargetBuffer(target);
-
- if (!buffer)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (buffer->isMapped())
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- // Check for possible overflow of size + offset
- if (!rx::IsUnsignedAdditionSafe<size_t>(size, offset))
- {
- context->recordError(Error(GL_OUT_OF_MEMORY));
- return;
- }
-
- if (size + offset > buffer->getSize())
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- if (data == NULL)
- {
- return;
- }
-
- Error error = buffer->bufferSubData(data, size, offset);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-GLenum GL_APIENTRY CheckFramebufferStatus(GLenum target)
-{
- EVENT("(GLenum target = 0x%X)", target);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidFramebufferTarget(target))
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return 0;
- }
-
- Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
- ASSERT(framebuffer);
-
- return framebuffer->checkStatus(context->getData());
- }
-
- return 0;
-}
-
-void GL_APIENTRY Clear(GLbitfield mask)
-{
- EVENT("(GLbitfield mask = 0x%X)", mask);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!context->skipValidation() && !ValidateClear(context, mask))
- {
- return;
- }
-
- context->clear(mask);
- }
-}
-
-void GL_APIENTRY ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
-{
- EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
- red, green, blue, alpha);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- context->getState().setColorClearValue(red, green, blue, alpha);
- }
-}
-
-void GL_APIENTRY ClearDepthf(GLclampf depth)
-{
- EVENT("(GLclampf depth = %f)", depth);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- context->getState().setDepthClearValue(depth);
- }
-}
-
-void GL_APIENTRY ClearStencil(GLint s)
-{
- EVENT("(GLint s = %d)", s);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- context->getState().setStencilClearValue(s);
- }
-}
-
-void GL_APIENTRY ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
-{
- EVENT("(GLboolean red = %d, GLboolean green = %u, GLboolean blue = %u, GLboolean alpha = %u)",
- red, green, blue, alpha);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- context->getState().setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE);
- }
-}
-
-void GL_APIENTRY CompileShader(GLuint shader)
-{
- EVENT("(GLuint shader = %d)", shader);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- Shader *shaderObject = GetValidShader(context, shader);
- if (!shaderObject)
- {
- return;
- }
- shaderObject->compile(context->getCompiler());
- }
-}
-
-void GL_APIENTRY CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
- GLint border, GLsizei imageSize, const GLvoid* data)
-{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
- "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
- target, level, internalformat, width, height, border, imageSize, data);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3 &&
- !ValidateES2TexImageParameters(context, target, level, internalformat, true, false,
- 0, 0, width, height, border, GL_NONE, GL_NONE, data))
- {
- return;
- }
-
- if (context->getClientVersion() >= 3 &&
- !ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
- 0, 0, width, height, 1, border, GL_NONE, GL_NONE,
- data))
- {
- return;
- }
-
- const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
- if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- Extents size(width, height, 1);
- Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
- Error error =
- texture->setCompressedImage(context, target, level, internalformat, size, imageSize,
- reinterpret_cast<const uint8_t *>(data));
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- GLenum format, GLsizei imageSize, const GLvoid* data)
-{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
- "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
- "GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
- target, level, xoffset, yoffset, width, height, format, imageSize, data);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3 &&
- !ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true,
- xoffset, yoffset, width, height, 0, GL_NONE, GL_NONE, data))
- {
- return;
- }
-
- if (context->getClientVersion() >= 3 &&
- !ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
- yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE,
- data))
- {
- return;
- }
-
- const InternalFormat &formatInfo = GetInternalFormatInfo(format);
- if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- Box area(xoffset, yoffset, 0, width, height, 1);
- Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
- Error error =
- texture->setCompressedSubImage(context, target, level, area, format, imageSize,
- reinterpret_cast<const uint8_t *>(data));
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
-{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
- "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
- target, level, internalformat, x, y, width, height, border);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!context->skipValidation() &&
- !ValidateCopyTexImage2D(context, target, level, internalformat, x, y, width, height,
- border))
- {
- return;
- }
- context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
- }
-}
-
-void GL_APIENTRY CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
-{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
- "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
- target, level, xoffset, yoffset, x, y, width, height);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!context->skipValidation() &&
- !ValidateCopyTexSubImage2D(context, target, level, xoffset, yoffset, x, y, width,
- height))
- {
- return;
- }
-
- context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
- }
-}
-
-GLuint GL_APIENTRY CreateProgram(void)
-{
- EVENT("()");
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- return context->createProgram();
- }
-
- return 0;
-}
-
-GLuint GL_APIENTRY CreateShader(GLenum type)
-{
- EVENT("(GLenum type = 0x%X)", type);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- switch (type)
- {
- case GL_FRAGMENT_SHADER:
- case GL_VERTEX_SHADER:
- return context->createShader(type);
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return 0;
- }
- }
-
- return 0;
-}
-
-void GL_APIENTRY CullFace(GLenum mode)
-{
- EVENT("(GLenum mode = 0x%X)", mode);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- switch (mode)
- {
- case GL_FRONT:
- case GL_BACK:
- case GL_FRONT_AND_BACK:
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- context->getState().setCullMode(mode);
- }
-}
-
-void GL_APIENTRY DeleteBuffers(GLsizei n, const GLuint* buffers)
-{
- EVENT("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (n < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int i = 0; i < n; i++)
- {
- context->deleteBuffer(buffers[i]);
- }
- }
-}
-
-void GL_APIENTRY DeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
-{
- EVENT("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (n < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int i = 0; i < n; i++)
- {
- if (framebuffers[i] != 0)
- {
- context->deleteFramebuffer(framebuffers[i]);
- }
- }
- }
-}
-
-void GL_APIENTRY DeleteProgram(GLuint program)
-{
- EVENT("(GLuint program = %d)", program);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (program == 0)
- {
- return;
- }
-
- if (!context->getProgram(program))
- {
- if(context->getShader(program))
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
- else
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
- }
-
- context->deleteProgram(program);
- }
-}
-
-void GL_APIENTRY DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
-{
- EVENT("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (n < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int i = 0; i < n; i++)
- {
- context->deleteRenderbuffer(renderbuffers[i]);
- }
- }
-}
-
-void GL_APIENTRY DeleteShader(GLuint shader)
-{
- EVENT("(GLuint shader = %d)", shader);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (shader == 0)
- {
- return;
- }
-
- if (!context->getShader(shader))
- {
- if(context->getProgram(shader))
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
- else
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
- }
-
- context->deleteShader(shader);
- }
-}
-
-void GL_APIENTRY DeleteTextures(GLsizei n, const GLuint* textures)
-{
- EVENT("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (n < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int i = 0; i < n; i++)
- {
- if (textures[i] != 0)
- {
- context->deleteTexture(textures[i]);
- }
- }
- }
-}
-
-void GL_APIENTRY DepthFunc(GLenum func)
-{
- EVENT("(GLenum func = 0x%X)", func);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- switch (func)
- {
- case GL_NEVER:
- case GL_ALWAYS:
- case GL_LESS:
- case GL_LEQUAL:
- case GL_EQUAL:
- case GL_GREATER:
- case GL_GEQUAL:
- case GL_NOTEQUAL:
- context->getState().setDepthFunc(func);
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- }
-}
-
-void GL_APIENTRY DepthMask(GLboolean flag)
-{
- EVENT("(GLboolean flag = %u)", flag);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- context->getState().setDepthMask(flag != GL_FALSE);
- }
-}
-
-void GL_APIENTRY DepthRangef(GLclampf zNear, GLclampf zFar)
-{
- EVENT("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- context->getState().setDepthRange(zNear, zFar);
- }
-}
-
-void GL_APIENTRY DetachShader(GLuint program, GLuint shader)
-{
- EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- Program *programObject = GetValidProgram(context, program);
- if (!programObject)
- {
- return;
- }
-
- Shader *shaderObject = GetValidShader(context, shader);
- if (!shaderObject)
- {
- return;
- }
-
- if (!programObject->detachShader(shaderObject))
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
- }
-}
-
-void GL_APIENTRY Disable(GLenum cap)
-{
- EVENT("(GLenum cap = 0x%X)", cap);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidCap(context, cap))
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- context->getState().setEnableFeature(cap, false);
- }
-}
-
-void GL_APIENTRY DisableVertexAttribArray(GLuint index)
-{
- EVENT("(GLuint index = %d)", index);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- context->getState().setEnableVertexAttribArray(index, false);
- }
-}
-
-void GL_APIENTRY DrawArrays(GLenum mode, GLint first, GLsizei count)
-{
- EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateDrawArrays(context, mode, first, count, 0))
- {
- return;
- }
-
- Error error = context->drawArrays(mode, first, count);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
-{
- EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)",
- mode, count, type, indices);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- IndexRange indexRange;
- if (!ValidateDrawElements(context, mode, count, type, indices, 0, &indexRange))
- {
- return;
- }
-
- Error error = context->drawElements(mode, count, type, indices, indexRange);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY Enable(GLenum cap)
-{
- EVENT("(GLenum cap = 0x%X)", cap);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidCap(context, cap))
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- if (context->getLimitations().noSampleAlphaToCoverageSupport)
- {
- if (cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
- {
- const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
- context->recordError(Error(GL_INVALID_OPERATION, errorMessage));
-
- // We also output an error message to the debugger window if tracing is active, so that developers can see the error message.
- ERR("%s", errorMessage);
-
- return;
- }
- }
-
- context->getState().setEnableFeature(cap, true);
- }
-}
-
-void GL_APIENTRY EnableVertexAttribArray(GLuint index)
-{
- EVENT("(GLuint index = %d)", index);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- context->getState().setEnableVertexAttribArray(index, true);
- }
-}
-
-void GL_APIENTRY Finish(void)
-{
- EVENT("()");
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- Error error = context->finish();
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY Flush(void)
-{
- EVENT("()");
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- Error error = context->flush();
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
-{
- EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
- "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!context->skipValidation() &&
- !ValidateFramebufferRenderbuffer(context, target, attachment, renderbuffertarget,
- renderbuffer))
- {
- return;
- }
-
- context->framebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
- }
-}
-
-void GL_APIENTRY FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
-{
- EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
- "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!context->skipValidation() &&
- !ValidateFramebufferTexture2D(context, target, attachment, textarget, texture, level))
- {
- return;
- }
-
- context->framebufferTexture2D(target, attachment, textarget, texture, level);
- }
-}
-
-void GL_APIENTRY FrontFace(GLenum mode)
-{
- EVENT("(GLenum mode = 0x%X)", mode);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- switch (mode)
- {
- case GL_CW:
- case GL_CCW:
- context->getState().setFrontFace(mode);
- break;
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- }
-}
-
-void GL_APIENTRY GenBuffers(GLsizei n, GLuint* buffers)
-{
- EVENT("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (n < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int i = 0; i < n; i++)
- {
- buffers[i] = context->createBuffer();
- }
- }
-}
-
-void GL_APIENTRY GenerateMipmap(GLenum target)
-{
- EVENT("(GLenum target = 0x%X)", target);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidTextureTarget(context, target))
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- Texture *texture = context->getTargetTexture(target);
-
- if (texture == NULL)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
- GLenum internalFormat = texture->getInternalFormat(baseTarget, 0);
- const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
- const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat);
-
- // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
- // unsized formats or that are color renderable and filterable. Since we do not track if
- // the texture was created with sized or unsized format (only sized formats are stored),
- // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
- // be able to) because they aren't color renderable. Simply do a special case for LUMA
- // textures since they're the only texture format that can be created with unsized formats
- // that is not color renderable. New unsized formats are unlikely to be added, since ES2
- // was the last version to use add them.
- bool isLUMA = internalFormat == GL_LUMINANCE8_EXT ||
- internalFormat == GL_LUMINANCE8_ALPHA8_EXT ||
- internalFormat == GL_ALPHA8_EXT;
-
- if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0 || !formatCaps.filterable ||
- (!formatCaps.renderable && !isLUMA) || formatInfo.compressed)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- // GL_EXT_sRGB does not support mipmap generation on sRGB textures
- if (context->getClientVersion() == 2 && formatInfo.colorEncoding == GL_SRGB)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- // Non-power of 2 ES2 check
- if (!context->getExtensions().textureNPOT &&
- (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
- !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
- {
- ASSERT(context->getClientVersion() <= 2 && (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP));
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- // Cube completeness check
- if (target == GL_TEXTURE_CUBE_MAP && !texture->isCubeComplete())
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- Error error = texture->generateMipmaps();
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY GenFramebuffers(GLsizei n, GLuint* framebuffers)
-{
- EVENT("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (n < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int i = 0; i < n; i++)
- {
- framebuffers[i] = context->createFramebuffer();
- }
- }
-}
-
-void GL_APIENTRY GenRenderbuffers(GLsizei n, GLuint* renderbuffers)
-{
- EVENT("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (n < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int i = 0; i < n; i++)
- {
- renderbuffers[i] = context->createRenderbuffer();
- }
- }
-}
-
-void GL_APIENTRY GenTextures(GLsizei n, GLuint* textures)
-{
- EVENT("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (n < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int i = 0; i < n; i++)
- {
- textures[i] = context->createTexture();
- }
- }
-}
-
-void GL_APIENTRY GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
-{
- EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = 0x%0.8p, "
- "GLint *size = 0x%0.8p, GLenum *type = %0.8p, GLchar *name = %0.8p)",
- program, index, bufsize, length, size, type, name);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (bufsize < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- Program *programObject = GetValidProgram(context, program);
-
- if (!programObject)
- {
- return;
- }
-
- if (index >= (GLuint)programObject->getActiveAttributeCount())
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- programObject->getActiveAttribute(index, bufsize, length, size, type, name);
- }
-}
-
-void GL_APIENTRY GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
-{
- EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
- "GLsizei* length = 0x%0.8p, GLint* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)",
- program, index, bufsize, length, size, type, name);
-
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (bufsize < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- Program *programObject = GetValidProgram(context, program);
-
- if (!programObject)
- {
- return;
- }
-
- if (index >= (GLuint)programObject->getActiveUniformCount())
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- programObject->getActiveUniform(index, bufsize, length, size, type, name);
- }
-}
-
-void GL_APIENTRY GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
-{
- EVENT("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)",
- program, maxcount, count, shaders);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (maxcount < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- Program *programObject = GetValidProgram(context, program);
-
- if (!programObject)
- {
- return;
- }
-
- return programObject->getAttachedShaders(maxcount, count, shaders);
- }
-}
-
-GLint GL_APIENTRY GetAttribLocation(GLuint program, const GLchar* name)
-{
- EVENT("(GLuint program = %d, const GLchar* name = %s)", program, name);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- Program *programObject = GetValidProgram(context, program);
-
- if (!programObject)
- {
- return -1;
- }
-
- if (!programObject->isLinked())
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return -1;
- }
-
- return programObject->getAttributeLocation(name);
- }
-
- return -1;
-}
-
-void GL_APIENTRY GetBooleanv(GLenum pname, GLboolean* params)
-{
- EVENT("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)", pname, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- GLenum nativeType;
- unsigned int numParams = 0;
- if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
- {
- return;
- }
-
- if (nativeType == GL_BOOL)
- {
- context->getBooleanv(pname, params);
- }
- else
- {
- CastStateValues(context, nativeType, pname, numParams, params);
- }
- }
-}
-
-void GL_APIENTRY GetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
-{
- EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidBufferTarget(context, target))
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- if (!ValidBufferParameter(context, pname))
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- Buffer *buffer = context->getState().getTargetBuffer(target);
-
- if (!buffer)
- {
- // A null buffer means that "0" is bound to the requested buffer target
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- switch (pname)
- {
- case GL_BUFFER_USAGE:
- *params = static_cast<GLint>(buffer->getUsage());
- break;
- case GL_BUFFER_SIZE:
- *params = clampCast<GLint>(buffer->getSize());
- break;
- case GL_BUFFER_ACCESS_FLAGS:
- *params = buffer->getAccessFlags();
- break;
- case GL_BUFFER_ACCESS_OES:
- *params = buffer->getAccess();
- break;
- case GL_BUFFER_MAPPED:
- static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
- *params = static_cast<GLint>(buffer->isMapped());
- break;
- case GL_BUFFER_MAP_OFFSET:
- *params = clampCast<GLint>(buffer->getMapOffset());
- break;
- case GL_BUFFER_MAP_LENGTH:
- *params = clampCast<GLint>(buffer->getMapLength());
- break;
- default: UNREACHABLE(); break;
- }
- }
-}
-
-GLenum GL_APIENTRY GetError(void)
-{
- EVENT("()");
-
- Context *context = GetGlobalContext();
-
- if (context)
- {
- return context->getError();
- }
-
- return GL_NO_ERROR;
-}
-
-void GL_APIENTRY GetFloatv(GLenum pname, GLfloat* params)
-{
- EVENT("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- GLenum nativeType;
- unsigned int numParams = 0;
- if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
- {
- return;
- }
-
- if (nativeType == GL_FLOAT)
- {
- context->getFloatv(pname, params);
- }
- else
- {
- CastStateValues(context, nativeType, pname, numParams, params);
- }
- }
-}
-
-void GL_APIENTRY GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
-{
- EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
- target, attachment, pname, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidFramebufferTarget(target))
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- int clientVersion = context->getClientVersion();
-
- switch (pname)
- {
- case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
- case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
- case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
- case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
- if (clientVersion < 3 && !context->getExtensions().sRGB)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
- case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
- case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
- case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
- case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
- case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
- case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
- case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
- if (clientVersion < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- // Determine if the attachment is a valid enum
- switch (attachment)
- {
- case GL_BACK:
- case GL_FRONT:
- case GL_DEPTH:
- case GL_STENCIL:
- case GL_DEPTH_STENCIL_ATTACHMENT:
- if (clientVersion < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- break;
-
- case GL_DEPTH_ATTACHMENT:
- case GL_STENCIL_ATTACHMENT:
- break;
-
- default:
- if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
- (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- break;
- }
-
- const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
- ASSERT(framebuffer);
-
- if (framebuffer->id() == 0)
- {
- if (clientVersion < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- switch (attachment)
- {
- case GL_BACK:
- case GL_DEPTH:
- case GL_STENCIL:
- break;
-
- default:
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
- }
- else
- {
- if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
- {
- // Valid attachment query
- }
- else
- {
- switch (attachment)
- {
- case GL_DEPTH_ATTACHMENT:
- case GL_STENCIL_ATTACHMENT:
- break;
-
- case GL_DEPTH_STENCIL_ATTACHMENT:
- if (framebuffer->hasValidDepthStencil())
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
- break;
-
- default:
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
- }
- }
-
- const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
- if (attachmentObject)
- {
- ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
- attachmentObject->type() == GL_TEXTURE ||
- attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
-
- switch (pname)
- {
- case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
- *params = attachmentObject->type();
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
- if (attachmentObject->type() != GL_RENDERBUFFER && attachmentObject->type() != GL_TEXTURE)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = attachmentObject->id();
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
- if (attachmentObject->type() != GL_TEXTURE)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = attachmentObject->mipLevel();
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
- if (attachmentObject->type() != GL_TEXTURE)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = attachmentObject->cubeMapFace();
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
- *params = attachmentObject->getRedSize();
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
- *params = attachmentObject->getGreenSize();
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
- *params = attachmentObject->getBlueSize();
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
- *params = attachmentObject->getAlphaSize();
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
- *params = attachmentObject->getDepthSize();
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
- *params = attachmentObject->getStencilSize();
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
- if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
- *params = attachmentObject->getComponentType();
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
- *params = attachmentObject->getColorEncoding();
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
- if (attachmentObject->type() != GL_TEXTURE)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = attachmentObject->layer();
- break;
-
- default:
- UNREACHABLE();
- break;
- }
- }
- else
- {
- // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
- // is NONE, then querying any other pname will generate INVALID_ENUM.
-
- // ES 3.0.2 spec pg 235 states that if the attachment type is none,
- // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
- // INVALID_OPERATION for all other pnames
-
- switch (pname)
- {
- case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
- *params = GL_NONE;
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
- if (clientVersion < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = 0;
- break;
-
- default:
- if (clientVersion < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- else
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
- }
- }
- }
-}
-
-void GL_APIENTRY GetIntegerv(GLenum pname, GLint* params)
-{
- EVENT("(GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pname, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- GLenum nativeType;
- unsigned int numParams = 0;
-
- if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
- {
- return;
- }
-
- if (nativeType == GL_INT)
- {
- context->getIntegerv(pname, params);
- }
- else
- {
- CastStateValues(context, nativeType, pname, numParams, params);
- }
- }
-}
-
-void GL_APIENTRY GetProgramiv(GLuint program, GLenum pname, GLint* params)
-{
- EVENT("(GLuint program = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", program, pname, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- Program *programObject = GetValidProgram(context, program);
-
- if (!programObject)
- {
- return;
- }
-
- if (context->getClientVersion() < 3)
- {
- switch (pname)
- {
- case GL_ACTIVE_UNIFORM_BLOCKS:
- case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
- case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
- case GL_TRANSFORM_FEEDBACK_VARYINGS:
- case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
- case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- }
-
- switch (pname)
- {
- case GL_DELETE_STATUS:
- *params = programObject->isFlaggedForDeletion();
- return;
- case GL_LINK_STATUS:
- *params = programObject->isLinked();
- return;
- case GL_VALIDATE_STATUS:
- *params = programObject->isValidated();
- return;
- case GL_INFO_LOG_LENGTH:
- *params = programObject->getInfoLogLength();
- return;
- case GL_ATTACHED_SHADERS:
- *params = programObject->getAttachedShadersCount();
- return;
- case GL_ACTIVE_ATTRIBUTES:
- *params = programObject->getActiveAttributeCount();
- return;
- case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
- *params = programObject->getActiveAttributeMaxLength();
- return;
- case GL_ACTIVE_UNIFORMS:
- *params = programObject->getActiveUniformCount();
- return;
- case GL_ACTIVE_UNIFORM_MAX_LENGTH:
- *params = programObject->getActiveUniformMaxLength();
- return;
- case GL_PROGRAM_BINARY_LENGTH_OES:
- *params = programObject->getBinaryLength();
- return;
- case GL_ACTIVE_UNIFORM_BLOCKS:
- *params = programObject->getActiveUniformBlockCount();
- return;
- case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
- *params = programObject->getActiveUniformBlockMaxLength();
- break;
- case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
- *params = programObject->getTransformFeedbackBufferMode();
- break;
- case GL_TRANSFORM_FEEDBACK_VARYINGS:
- *params = programObject->getTransformFeedbackVaryingCount();
- break;
- case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
- *params = programObject->getTransformFeedbackVaryingMaxLength();
- break;
- case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
- *params = programObject->getBinaryRetrievableHint();
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- }
-}
-
-void GL_APIENTRY GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
-{
- EVENT("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
- program, bufsize, length, infolog);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (bufsize < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- Program *programObject = GetValidProgram(context, program);
- if (!programObject)
- {
- return;
- }
-
- programObject->getInfoLog(bufsize, length, infolog);
- }
-}
-
-void GL_APIENTRY GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
-{
- EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (target != GL_RENDERBUFFER)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- if (context->getState().getRenderbufferId() == 0)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- Renderbuffer *renderbuffer = context->getRenderbuffer(context->getState().getRenderbufferId());
-
- switch (pname)
- {
- case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
- case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
- case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getInternalFormat(); break;
- case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break;
- case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break;
- case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break;
- case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break;
- case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break;
- case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break;
-
- case GL_RENDERBUFFER_SAMPLES_ANGLE:
- if (!context->getExtensions().framebufferMultisample)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = renderbuffer->getSamples();
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- }
-}
-
-void GL_APIENTRY GetShaderiv(GLuint shader, GLenum pname, GLint* params)
-{
- EVENT("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- Shader *shaderObject = GetValidShader(context, shader);
- if (!shaderObject)
- {
- return;
- }
-
- switch (pname)
- {
- case GL_SHADER_TYPE:
- *params = shaderObject->getType();
- return;
- case GL_DELETE_STATUS:
- *params = shaderObject->isFlaggedForDeletion();
- return;
- case GL_COMPILE_STATUS:
- *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
- return;
- case GL_INFO_LOG_LENGTH:
- *params = shaderObject->getInfoLogLength();
- return;
- case GL_SHADER_SOURCE_LENGTH:
- *params = shaderObject->getSourceLength();
- return;
- case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
- *params = shaderObject->getTranslatedSourceWithDebugInfoLength();
- return;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- }
-}
-
-void GL_APIENTRY GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
-{
- EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
- shader, bufsize, length, infolog);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (bufsize < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- Shader *shaderObject = GetValidShader(context, shader);
- if (!shaderObject)
- {
- return;
- }
-
- shaderObject->getInfoLog(bufsize, length, infolog);
- }
-}
-
-void GL_APIENTRY GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
-{
- EVENT("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)",
- shadertype, precisiontype, range, precision);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- switch (shadertype)
- {
- case GL_VERTEX_SHADER:
- switch (precisiontype)
- {
- case GL_LOW_FLOAT:
- context->getCaps().vertexLowpFloat.get(range, precision);
- break;
- case GL_MEDIUM_FLOAT:
- context->getCaps().vertexMediumpFloat.get(range, precision);
- break;
- case GL_HIGH_FLOAT:
- context->getCaps().vertexHighpFloat.get(range, precision);
- break;
-
- case GL_LOW_INT:
- context->getCaps().vertexLowpInt.get(range, precision);
- break;
- case GL_MEDIUM_INT:
- context->getCaps().vertexMediumpInt.get(range, precision);
- break;
- case GL_HIGH_INT:
- context->getCaps().vertexHighpInt.get(range, precision);
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- break;
- case GL_FRAGMENT_SHADER:
- switch (precisiontype)
- {
- case GL_LOW_FLOAT:
- context->getCaps().fragmentLowpFloat.get(range, precision);
- break;
- case GL_MEDIUM_FLOAT:
- context->getCaps().fragmentMediumpFloat.get(range, precision);
- break;
- case GL_HIGH_FLOAT:
- context->getCaps().fragmentHighpFloat.get(range, precision);
- break;
-
- case GL_LOW_INT:
- context->getCaps().fragmentLowpInt.get(range, precision);
- break;
- case GL_MEDIUM_INT:
- context->getCaps().fragmentMediumpInt.get(range, precision);
- break;
- case GL_HIGH_INT:
- context->getCaps().fragmentHighpInt.get(range, precision);
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- break;
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- }
-}
-
-void GL_APIENTRY GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
-{
- EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
- shader, bufsize, length, source);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (bufsize < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- Shader *shaderObject = GetValidShader(context, shader);
- if (!shaderObject)
- {
- return;
- }
-
- shaderObject->getSource(bufsize, length, source);
- }
-}
-
-const GLubyte *GL_APIENTRY GetString(GLenum name)
-{
- EVENT("(GLenum name = 0x%X)", name);
-
- Context *context = GetValidGlobalContext();
-
- if (context)
- {
- switch (name)
- {
- case GL_VENDOR:
- return reinterpret_cast<const GLubyte *>("Google Inc.");
-
- case GL_RENDERER:
- return reinterpret_cast<const GLubyte *>(context->getRendererString().c_str());
-
- case GL_VERSION:
- if (context->getClientVersion() == 2)
- {
- return reinterpret_cast<const GLubyte *>(
- "OpenGL ES 2.0 (ANGLE " ANGLE_VERSION_STRING ")");
- }
- else
- {
- return reinterpret_cast<const GLubyte *>(
- "OpenGL ES 3.0 (ANGLE " ANGLE_VERSION_STRING ")");
- }
-
- case GL_SHADING_LANGUAGE_VERSION:
- if (context->getClientVersion() == 2)
- {
- return reinterpret_cast<const GLubyte *>(
- "OpenGL ES GLSL ES 1.00 (ANGLE " ANGLE_VERSION_STRING ")");
- }
- else
- {
- return reinterpret_cast<const GLubyte *>(
- "OpenGL ES GLSL ES 3.00 (ANGLE " ANGLE_VERSION_STRING ")");
- }
-
- case GL_EXTENSIONS:
- return reinterpret_cast<const GLubyte *>(context->getExtensionString().c_str());
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return nullptr;
- }
- }
-
- return nullptr;
-}
-
-void GL_APIENTRY GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
-{
- EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidTextureTarget(context, target))
- {
- context->recordError(Error(GL_INVALID_ENUM, "Invalid texture target"));
- return;
- }
-
- Texture *texture = context->getTargetTexture(target);
-
- if (!texture)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (pname)
- {
- case GL_TEXTURE_MAG_FILTER:
- *params = (GLfloat)texture->getMagFilter();
- break;
- case GL_TEXTURE_MIN_FILTER:
- *params = (GLfloat)texture->getMinFilter();
- break;
- case GL_TEXTURE_WRAP_S:
- *params = (GLfloat)texture->getWrapS();
- break;
- case GL_TEXTURE_WRAP_T:
- *params = (GLfloat)texture->getWrapT();
- break;
- case GL_TEXTURE_WRAP_R:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = (GLfloat)texture->getWrapR();
- break;
- case GL_TEXTURE_IMMUTABLE_FORMAT:
- // Exposed to ES2.0 through EXT_texture_storage, no client version validation.
- *params = (GLfloat)(texture->getImmutableFormat() ? GL_TRUE : GL_FALSE);
- break;
- case GL_TEXTURE_IMMUTABLE_LEVELS:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = (GLfloat)texture->getImmutableLevels();
- break;
- case GL_TEXTURE_USAGE_ANGLE:
- *params = (GLfloat)texture->getUsage();
- break;
- case GL_TEXTURE_MAX_ANISOTROPY_EXT:
- if (!context->getExtensions().textureFilterAnisotropic)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = (GLfloat)texture->getMaxAnisotropy();
- break;
- case GL_TEXTURE_SWIZZLE_R:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = (GLfloat)texture->getSwizzleRed();
- break;
- case GL_TEXTURE_SWIZZLE_G:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = (GLfloat)texture->getSwizzleGreen();
- break;
- case GL_TEXTURE_SWIZZLE_B:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = (GLfloat)texture->getSwizzleBlue();
- break;
- case GL_TEXTURE_SWIZZLE_A:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = (GLfloat)texture->getSwizzleAlpha();
- break;
- case GL_TEXTURE_BASE_LEVEL:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = (GLfloat)texture->getBaseLevel();
- break;
- case GL_TEXTURE_MAX_LEVEL:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = (GLfloat)texture->getMaxLevel();
- break;
- case GL_TEXTURE_MIN_LOD:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = texture->getSamplerState().minLod;
- break;
- case GL_TEXTURE_MAX_LOD:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = texture->getSamplerState().maxLod;
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- }
-}
-
-void GL_APIENTRY GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
-{
- EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidTextureTarget(context, target))
- {
- context->recordError(Error(GL_INVALID_ENUM, "Invalid texture target"));
- return;
- }
-
- Texture *texture = context->getTargetTexture(target);
-
- if (!texture)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (pname)
- {
- case GL_TEXTURE_MAG_FILTER:
- *params = texture->getSamplerState().magFilter;
- break;
- case GL_TEXTURE_MIN_FILTER:
- *params = texture->getSamplerState().minFilter;
- break;
- case GL_TEXTURE_WRAP_S:
- *params = texture->getSamplerState().wrapS;
- break;
- case GL_TEXTURE_WRAP_T:
- *params = texture->getSamplerState().wrapT;
- break;
- case GL_TEXTURE_WRAP_R:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = texture->getSamplerState().wrapR;
- break;
- case GL_TEXTURE_IMMUTABLE_FORMAT:
- // Exposed to ES2.0 through EXT_texture_storage, no client version validation.
- *params = texture->getImmutableFormat() ? GL_TRUE : GL_FALSE;
- break;
- case GL_TEXTURE_IMMUTABLE_LEVELS:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = static_cast<GLint>(texture->getImmutableLevels());
- break;
- case GL_TEXTURE_USAGE_ANGLE:
- *params = texture->getUsage();
- break;
- case GL_TEXTURE_MAX_ANISOTROPY_EXT:
- if (!context->getExtensions().textureFilterAnisotropic)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = (GLint)texture->getMaxAnisotropy();
- break;
- case GL_TEXTURE_SWIZZLE_R:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = texture->getSwizzleRed();
- break;
- case GL_TEXTURE_SWIZZLE_G:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = texture->getSwizzleGreen();
- break;
- case GL_TEXTURE_SWIZZLE_B:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = texture->getSwizzleBlue();
- break;
- case GL_TEXTURE_SWIZZLE_A:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = texture->getSwizzleAlpha();
- break;
- case GL_TEXTURE_BASE_LEVEL:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = texture->getBaseLevel();
- break;
- case GL_TEXTURE_MAX_LEVEL:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = texture->getMaxLevel();
- break;
- case GL_TEXTURE_MIN_LOD:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = (GLint)texture->getMinLod();
- break;
- case GL_TEXTURE_MAX_LOD:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- *params = (GLint)texture->getMaxLod();
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- }
-}
-
-void GL_APIENTRY GetUniformfv(GLuint program, GLint location, GLfloat* params)
-{
- EVENT("(GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p)", program, location, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateGetUniformfv(context, program, location, params))
- {
- return;
- }
-
- Program *programObject = context->getProgram(program);
- ASSERT(programObject);
-
- programObject->getUniformfv(location, params);
- }
-}
-
-void GL_APIENTRY GetUniformiv(GLuint program, GLint location, GLint* params)
-{
- EVENT("(GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p)", program, location, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateGetUniformiv(context, program, location, params))
- {
- return;
- }
-
- Program *programObject = context->getProgram(program);
- ASSERT(programObject);
-
- programObject->getUniformiv(location, params);
- }
-}
-
-GLint GL_APIENTRY GetUniformLocation(GLuint program, const GLchar* name)
-{
- EVENT("(GLuint program = %d, const GLchar* name = 0x%0.8p)", program, name);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (strstr(name, "gl_") == name)
- {
- return -1;
- }
-
- Program *programObject = GetValidProgram(context, program);
-
- if (!programObject)
- {
- return -1;
- }
-
- if (!programObject->isLinked())
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return -1;
- }
-
- return programObject->getUniformLocation(name);
- }
-
- return -1;
-}
-
-void GL_APIENTRY GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
-{
- EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- if (!ValidateGetVertexAttribParameters(context, pname))
- {
- return;
- }
-
- if (pname == GL_CURRENT_VERTEX_ATTRIB)
- {
- const VertexAttribCurrentValueData &currentValueData = context->getState().getVertexAttribCurrentValue(index);
- for (int i = 0; i < 4; ++i)
- {
- params[i] = currentValueData.FloatValues[i];
- }
- }
- else
- {
- const VertexAttribute &attribState = context->getState().getVertexArray()->getVertexAttribute(index);
- *params = QuerySingleVertexAttributeParameter<GLfloat>(attribState, pname);
- }
- }
-}
-
-void GL_APIENTRY GetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
-{
- EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- if (!ValidateGetVertexAttribParameters(context, pname))
- {
- return;
- }
-
- if (pname == GL_CURRENT_VERTEX_ATTRIB)
- {
- const VertexAttribCurrentValueData &currentValueData = context->getState().getVertexAttribCurrentValue(index);
- for (int i = 0; i < 4; ++i)
- {
- float currentValue = currentValueData.FloatValues[i];
- params[i] = iround<GLint>(currentValue);
- }
- }
- else
- {
- const VertexAttribute &attribState = context->getState().getVertexArray()->getVertexAttribute(index);
- *params = QuerySingleVertexAttributeParameter<GLint>(attribState, pname);
- }
- }
-}
-
-void GL_APIENTRY GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
-{
- EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = 0x%0.8p)", index, pname, pointer);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- *pointer = const_cast<GLvoid*>(context->getState().getVertexAttribPointer(index));
- }
-}
-
-void GL_APIENTRY Hint(GLenum target, GLenum mode)
-{
- EVENT("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- switch (mode)
- {
- case GL_FASTEST:
- case GL_NICEST:
- case GL_DONT_CARE:
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (target)
- {
- case GL_GENERATE_MIPMAP_HINT:
- context->getState().setGenerateMipmapHint(mode);
- break;
-
- case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
- context->getState().setFragmentShaderDerivativeHint(mode);
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- }
-}
-
-GLboolean GL_APIENTRY IsBuffer(GLuint buffer)
-{
- EVENT("(GLuint buffer = %d)", buffer);
-
- Context *context = GetValidGlobalContext();
- if (context && buffer)
- {
- Buffer *bufferObject = context->getBuffer(buffer);
-
- if (bufferObject)
- {
- return GL_TRUE;
- }
- }
-
- return GL_FALSE;
-}
-
-GLboolean GL_APIENTRY IsEnabled(GLenum cap)
-{
- EVENT("(GLenum cap = 0x%X)", cap);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidCap(context, cap))
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return GL_FALSE;
- }
-
- return context->getState().getEnableFeature(cap);
- }
-
- return false;
-}
-
-GLboolean GL_APIENTRY IsFramebuffer(GLuint framebuffer)
-{
- EVENT("(GLuint framebuffer = %d)", framebuffer);
-
- Context *context = GetValidGlobalContext();
- if (context && framebuffer)
- {
- Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
-
- if (framebufferObject)
- {
- return GL_TRUE;
- }
- }
-
- return GL_FALSE;
-}
-
-GLboolean GL_APIENTRY IsProgram(GLuint program)
-{
- EVENT("(GLuint program = %d)", program);
-
- Context *context = GetValidGlobalContext();
- if (context && program)
- {
- Program *programObject = context->getProgram(program);
-
- if (programObject)
- {
- return GL_TRUE;
- }
- }
-
- return GL_FALSE;
-}
-
-GLboolean GL_APIENTRY IsRenderbuffer(GLuint renderbuffer)
-{
- EVENT("(GLuint renderbuffer = %d)", renderbuffer);
-
- Context *context = GetValidGlobalContext();
- if (context && renderbuffer)
- {
- Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
-
- if (renderbufferObject)
- {
- return GL_TRUE;
- }
- }
-
- return GL_FALSE;
-}
-
-GLboolean GL_APIENTRY IsShader(GLuint shader)
-{
- EVENT("(GLuint shader = %d)", shader);
-
- Context *context = GetValidGlobalContext();
- if (context && shader)
- {
- Shader *shaderObject = context->getShader(shader);
-
- if (shaderObject)
- {
- return GL_TRUE;
- }
- }
-
- return GL_FALSE;
-}
-
-GLboolean GL_APIENTRY IsTexture(GLuint texture)
-{
- EVENT("(GLuint texture = %d)", texture);
-
- Context *context = GetValidGlobalContext();
- if (context && texture)
- {
- Texture *textureObject = context->getTexture(texture);
-
- if (textureObject)
- {
- return GL_TRUE;
- }
- }
-
- return GL_FALSE;
-}
-
-void GL_APIENTRY LineWidth(GLfloat width)
-{
- EVENT("(GLfloat width = %f)", width);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (width <= 0.0f)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- context->getState().setLineWidth(width);
- }
-}
-
-void GL_APIENTRY LinkProgram(GLuint program)
-{
- EVENT("(GLuint program = %d)", program);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- Program *programObject = GetValidProgram(context, program);
- if (!programObject)
- {
- return;
- }
-
- Error error = programObject->link(context->getData());
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY PixelStorei(GLenum pname, GLint param)
-{
- EVENT("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- switch (pname)
- {
- case GL_UNPACK_IMAGE_HEIGHT:
- case GL_UNPACK_SKIP_IMAGES:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
-
- case GL_UNPACK_ROW_LENGTH:
- case GL_UNPACK_SKIP_ROWS:
- case GL_UNPACK_SKIP_PIXELS:
- if (!context->getExtensions().unpackSubimage)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- break;
-
- case GL_PACK_ROW_LENGTH:
- case GL_PACK_SKIP_ROWS:
- case GL_PACK_SKIP_PIXELS:
- if (!context->getExtensions().packSubimage)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- break;
- }
- }
-
- if (param < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE, "Cannot use negative values in PixelStorei"));
- return;
- }
-
- State &state = context->getState();
-
- switch (pname)
- {
- case GL_UNPACK_ALIGNMENT:
- if (param != 1 && param != 2 && param != 4 && param != 8)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- state.setUnpackAlignment(param);
- break;
-
- case GL_PACK_ALIGNMENT:
- if (param != 1 && param != 2 && param != 4 && param != 8)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- state.setPackAlignment(param);
- break;
-
- case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
- state.setPackReverseRowOrder(param != 0);
- break;
-
- case GL_UNPACK_ROW_LENGTH:
- ASSERT((context->getClientVersion() >= 3) || context->getExtensions().unpackSubimage);
- state.setUnpackRowLength(param);
- break;
-
- case GL_UNPACK_IMAGE_HEIGHT:
- ASSERT(context->getClientVersion() >= 3);
- state.setUnpackImageHeight(param);
- break;
-
- case GL_UNPACK_SKIP_IMAGES:
- ASSERT(context->getClientVersion() >= 3);
- state.setUnpackSkipImages(param);
- break;
-
- case GL_UNPACK_SKIP_ROWS:
- ASSERT((context->getClientVersion() >= 3) || context->getExtensions().unpackSubimage);
- state.setUnpackSkipRows(param);
- break;
-
- case GL_UNPACK_SKIP_PIXELS:
- ASSERT((context->getClientVersion() >= 3) || context->getExtensions().unpackSubimage);
- state.setUnpackSkipPixels(param);
- break;
-
- case GL_PACK_ROW_LENGTH:
- ASSERT((context->getClientVersion() >= 3) || context->getExtensions().packSubimage);
- state.setPackRowLength(param);
- break;
-
- case GL_PACK_SKIP_ROWS:
- ASSERT((context->getClientVersion() >= 3) || context->getExtensions().packSubimage);
- state.setPackSkipRows(param);
- break;
-
- case GL_PACK_SKIP_PIXELS:
- ASSERT((context->getClientVersion() >= 3) || context->getExtensions().packSubimage);
- state.setPackSkipPixels(param);
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- }
-}
-
-void GL_APIENTRY PolygonOffset(GLfloat factor, GLfloat units)
-{
- EVENT("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- context->getState().setPolygonOffsetParams(factor, units);
- }
-}
-
-void GL_APIENTRY ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
- GLenum format, GLenum type, GLvoid* pixels)
-{
- EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
- "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = 0x%0.8p)",
- x, y, width, height, format, type, pixels);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!context->skipValidation() &&
- !ValidateReadPixels(context, x, y, width, height, format, type, pixels))
- {
- return;
- }
-
- context->readPixels(x, y, width, height, format, type, pixels);
- }
-}
-
-void GL_APIENTRY ReleaseShaderCompiler(void)
-{
- EVENT("()");
-
- Context *context = GetValidGlobalContext();
-
- if (context)
- {
- Compiler *compiler = context->getCompiler();
- Error error = compiler->release();
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
-{
- EVENT("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
- target, internalformat, width, height);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateRenderbufferStorageParametersANGLE(context, target, 0, internalformat,
- width, height))
- {
- return;
- }
-
- Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer();
- Error error = renderbuffer->setStorage(internalformat, width, height);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY SampleCoverage(GLclampf value, GLboolean invert)
-{
- EVENT("(GLclampf value = %f, GLboolean invert = %u)", value, invert);
-
- Context* context = GetValidGlobalContext();
-
- if (context)
- {
- context->getState().setSampleCoverageParams(clamp01(value), invert == GL_TRUE);
- }
-}
-
-void GL_APIENTRY Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
-{
- EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
-
- Context* context = GetValidGlobalContext();
- if (context)
- {
- if (width < 0 || height < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- context->getState().setScissorParams(x, y, width, height);
- }
-}
-
-void GL_APIENTRY ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
-{
- EVENT("(GLsizei n = %d, const GLuint* shaders = 0x%0.8p, GLenum binaryformat = 0x%X, "
- "const GLvoid* binary = 0x%0.8p, GLsizei length = %d)",
- n, shaders, binaryformat, binary, length);
-
- Context* context = GetValidGlobalContext();
- if (context)
- {
- const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
- if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) == shaderBinaryFormats.end())
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- // No binary shader formats are supported.
- UNIMPLEMENTED();
- }
-}
-
-void GL_APIENTRY ShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length)
-{
- EVENT("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)",
- shader, count, string, length);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (count < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- Shader *shaderObject = GetValidShader(context, shader);
- if (!shaderObject)
- {
- return;
- }
- shaderObject->setSource(count, string, length);
- }
-}
-
-void GL_APIENTRY StencilFunc(GLenum func, GLint ref, GLuint mask)
-{
- StencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
-}
-
-void GL_APIENTRY StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
-{
- EVENT("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- switch (face)
- {
- case GL_FRONT:
- case GL_BACK:
- case GL_FRONT_AND_BACK:
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (func)
- {
- case GL_NEVER:
- case GL_ALWAYS:
- case GL_LESS:
- case GL_LEQUAL:
- case GL_EQUAL:
- case GL_GEQUAL:
- case GL_GREATER:
- case GL_NOTEQUAL:
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
- {
- context->getState().setStencilParams(func, ref, mask);
- }
-
- if (face == GL_BACK || face == GL_FRONT_AND_BACK)
- {
- context->getState().setStencilBackParams(func, ref, mask);
- }
- }
-}
-
-void GL_APIENTRY StencilMask(GLuint mask)
-{
- StencilMaskSeparate(GL_FRONT_AND_BACK, mask);
-}
-
-void GL_APIENTRY StencilMaskSeparate(GLenum face, GLuint mask)
-{
- EVENT("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- switch (face)
- {
- case GL_FRONT:
- case GL_BACK:
- case GL_FRONT_AND_BACK:
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
- {
- context->getState().setStencilWritemask(mask);
- }
-
- if (face == GL_BACK || face == GL_FRONT_AND_BACK)
- {
- context->getState().setStencilBackWritemask(mask);
- }
- }
-}
-
-void GL_APIENTRY StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
-{
- StencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
-}
-
-void GL_APIENTRY StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
-{
- EVENT("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
- face, fail, zfail, zpass);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- switch (face)
- {
- case GL_FRONT:
- case GL_BACK:
- case GL_FRONT_AND_BACK:
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (fail)
- {
- case GL_ZERO:
- case GL_KEEP:
- case GL_REPLACE:
- case GL_INCR:
- case GL_DECR:
- case GL_INVERT:
- case GL_INCR_WRAP:
- case GL_DECR_WRAP:
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (zfail)
- {
- case GL_ZERO:
- case GL_KEEP:
- case GL_REPLACE:
- case GL_INCR:
- case GL_DECR:
- case GL_INVERT:
- case GL_INCR_WRAP:
- case GL_DECR_WRAP:
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (zpass)
- {
- case GL_ZERO:
- case GL_KEEP:
- case GL_REPLACE:
- case GL_INCR:
- case GL_DECR:
- case GL_INVERT:
- case GL_INCR_WRAP:
- case GL_DECR_WRAP:
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
- {
- context->getState().setStencilOperations(fail, zfail, zpass);
- }
-
- if (face == GL_BACK || face == GL_FRONT_AND_BACK)
- {
- context->getState().setStencilBackOperations(fail, zfail, zpass);
- }
- }
-}
-
-void GL_APIENTRY TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
- GLint border, GLenum format, GLenum type, const GLvoid* pixels)
-{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
- "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
- target, level, internalformat, width, height, border, format, type, pixels);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3 &&
- !ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
- 0, 0, width, height, border, format, type, pixels))
- {
- return;
- }
-
- if (context->getClientVersion() >= 3 &&
- !ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false,
- 0, 0, 0, width, height, 1, border, format, type,
- pixels))
- {
- return;
- }
-
- Extents size(width, height, 1);
- Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
- Error error = texture->setImage(context, target, level, internalformat, size, format, type,
- reinterpret_cast<const uint8_t *>(pixels));
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY TexParameterf(GLenum target, GLenum pname, GLfloat param)
-{
- EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %f)", target, pname, param);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidTextureTarget(context, target))
- {
- context->recordError(Error(GL_INVALID_ENUM, "Invalid texture target"));
- return;
- }
-
- if (!ValidateTexParamParameters(context, pname, static_cast<GLint>(param)))
- {
- return;
- }
-
- Texture *texture = context->getTargetTexture(target);
-
- if (!texture)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- // clang-format off
- switch (pname)
- {
- case GL_TEXTURE_WRAP_S: texture->setWrapS(uiround<GLenum>(param)); break;
- case GL_TEXTURE_WRAP_T: texture->setWrapT(uiround<GLenum>(param)); break;
- case GL_TEXTURE_WRAP_R: texture->setWrapR(uiround<GLenum>(param)); break;
- case GL_TEXTURE_MIN_FILTER: texture->setMinFilter(uiround<GLenum>(param)); break;
- case GL_TEXTURE_MAG_FILTER: texture->setMagFilter(uiround<GLenum>(param)); break;
- case GL_TEXTURE_USAGE_ANGLE: texture->setUsage(uiround<GLenum>(param)); break;
- case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->setMaxAnisotropy(std::min(param, context->getExtensions().maxTextureAnisotropy)); break;
- case GL_TEXTURE_COMPARE_MODE: texture->setCompareMode(uiround<GLenum>(param)); break;
- case GL_TEXTURE_COMPARE_FUNC: texture->setCompareFunc(uiround<GLenum>(param)); break;
- case GL_TEXTURE_SWIZZLE_R: texture->setSwizzleRed(uiround<GLenum>(param)); break;
- case GL_TEXTURE_SWIZZLE_G: texture->setSwizzleGreen(uiround<GLenum>(param)); break;
- case GL_TEXTURE_SWIZZLE_B: texture->setSwizzleBlue(uiround<GLenum>(param)); break;
- case GL_TEXTURE_SWIZZLE_A: texture->setSwizzleAlpha(uiround<GLenum>(param)); break;
- case GL_TEXTURE_BASE_LEVEL: texture->setBaseLevel(uiround<GLuint>(param)); break;
- case GL_TEXTURE_MAX_LEVEL: texture->setMaxLevel(uiround<GLuint>(param)); break;
- case GL_TEXTURE_MIN_LOD: texture->setMinLod(param); break;
- case GL_TEXTURE_MAX_LOD: texture->setMaxLod(param); break;
- default: UNREACHABLE(); break;
- }
- // clang-format on
- }
-}
-
-void GL_APIENTRY TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
-{
- TexParameterf(target, pname, (GLfloat)*params);
-}
-
-void GL_APIENTRY TexParameteri(GLenum target, GLenum pname, GLint param)
-{
- EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidTextureTarget(context, target))
- {
- context->recordError(Error(GL_INVALID_ENUM, "Invalid Texture target"));
- return;
- }
-
- if (!ValidateTexParamParameters(context, pname, param))
- {
- return;
- }
-
- Texture *texture = context->getTargetTexture(target);
-
- if (!texture)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- // clang-format off
- switch (pname)
- {
- case GL_TEXTURE_WRAP_S: texture->setWrapS(static_cast<GLenum>(param)); break;
- case GL_TEXTURE_WRAP_T: texture->setWrapT(static_cast<GLenum>(param)); break;
- case GL_TEXTURE_WRAP_R: texture->setWrapR(static_cast<GLenum>(param)); break;
- case GL_TEXTURE_MIN_FILTER: texture->setMinFilter(static_cast<GLenum>(param)); break;
- case GL_TEXTURE_MAG_FILTER: texture->setMagFilter(static_cast<GLenum>(param)); break;
- case GL_TEXTURE_USAGE_ANGLE: texture->setUsage(static_cast<GLenum>(param)); break;
- case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->setMaxAnisotropy(std::min(static_cast<GLfloat>(param), context->getExtensions().maxTextureAnisotropy)); break;
- case GL_TEXTURE_COMPARE_MODE: texture->setCompareMode(static_cast<GLenum>(param)); break;
- case GL_TEXTURE_COMPARE_FUNC: texture->setCompareFunc(static_cast<GLenum>(param)); break;
- case GL_TEXTURE_SWIZZLE_R: texture->setSwizzleRed(static_cast<GLenum>(param)); break;
- case GL_TEXTURE_SWIZZLE_G: texture->setSwizzleGreen(static_cast<GLenum>(param)); break;
- case GL_TEXTURE_SWIZZLE_B: texture->setSwizzleBlue(static_cast<GLenum>(param)); break;
- case GL_TEXTURE_SWIZZLE_A: texture->setSwizzleAlpha(static_cast<GLenum>(param)); break;
- case GL_TEXTURE_BASE_LEVEL: texture->setBaseLevel(static_cast<GLuint>(param)); break;
- case GL_TEXTURE_MAX_LEVEL: texture->setMaxLevel(static_cast<GLuint>(param)); break;
- case GL_TEXTURE_MIN_LOD: texture->setMinLod(static_cast<GLfloat>(param)); break;
- case GL_TEXTURE_MAX_LOD: texture->setMaxLod(static_cast<GLfloat>(param)); break;
- default: UNREACHABLE(); break;
- }
- // clang-format on
- }
-}
-
-void GL_APIENTRY TexParameteriv(GLenum target, GLenum pname, const GLint* params)
-{
- TexParameteri(target, pname, *params);
-}
-
-void GL_APIENTRY TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- GLenum format, GLenum type, const GLvoid* pixels)
-{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
- "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
- "const GLvoid* pixels = 0x%0.8p)",
- target, level, xoffset, yoffset, width, height, format, type, pixels);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3 &&
- !ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true,
- xoffset, yoffset, width, height, 0, format, type, pixels))
- {
- return;
- }
-
- if (context->getClientVersion() >= 3 &&
- !ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
- yoffset, 0, width, height, 1, 0, format, type, pixels))
- {
- return;
- }
-
- // Zero sized uploads are valid but no-ops
- if (width == 0 || height == 0)
- {
- return;
- }
-
- Box area(xoffset, yoffset, 0, width, height, 1);
- Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
- Error error = texture->setSubImage(context, target, level, area, format, type,
- reinterpret_cast<const uint8_t *>(pixels));
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY Uniform1f(GLint location, GLfloat x)
-{
- Uniform1fv(location, 1, &x);
-}
-
-void GL_APIENTRY Uniform1fv(GLint location, GLsizei count, const GLfloat* v)
-{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateUniform(context, GL_FLOAT, location, count))
- {
- return;
- }
-
- Program *program = context->getState().getProgram();
- program->setUniform1fv(location, count, v);
- }
-}
-
-void GL_APIENTRY Uniform1i(GLint location, GLint x)
-{
- Uniform1iv(location, 1, &x);
-}
-
-void GL_APIENTRY Uniform1iv(GLint location, GLsizei count, const GLint* v)
-{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateUniform(context, GL_INT, location, count))
- {
- return;
- }
-
- Program *program = context->getState().getProgram();
- program->setUniform1iv(location, count, v);
- }
-}
-
-void GL_APIENTRY Uniform2f(GLint location, GLfloat x, GLfloat y)
-{
- GLfloat xy[2] = {x, y};
-
- Uniform2fv(location, 1, xy);
-}
-
-void GL_APIENTRY Uniform2fv(GLint location, GLsizei count, const GLfloat* v)
-{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateUniform(context, GL_FLOAT_VEC2, location, count))
- {
- return;
- }
-
- Program *program = context->getState().getProgram();
- program->setUniform2fv(location, count, v);
- }
-}
-
-void GL_APIENTRY Uniform2i(GLint location, GLint x, GLint y)
-{
- GLint xy[2] = {x, y};
-
- Uniform2iv(location, 1, xy);
-}
-
-void GL_APIENTRY Uniform2iv(GLint location, GLsizei count, const GLint* v)
-{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateUniform(context, GL_INT_VEC2, location, count))
- {
- return;
- }
-
- Program *program = context->getState().getProgram();
- program->setUniform2iv(location, count, v);
- }
-}
-
-void GL_APIENTRY Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
-{
- GLfloat xyz[3] = {x, y, z};
-
- Uniform3fv(location, 1, xyz);
-}
-
-void GL_APIENTRY Uniform3fv(GLint location, GLsizei count, const GLfloat* v)
-{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateUniform(context, GL_FLOAT_VEC3, location, count))
- {
- return;
- }
-
- Program *program = context->getState().getProgram();
- program->setUniform3fv(location, count, v);
- }
-}
-
-void GL_APIENTRY Uniform3i(GLint location, GLint x, GLint y, GLint z)
-{
- GLint xyz[3] = {x, y, z};
-
- Uniform3iv(location, 1, xyz);
-}
-
-void GL_APIENTRY Uniform3iv(GLint location, GLsizei count, const GLint* v)
-{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateUniform(context, GL_INT_VEC3, location, count))
- {
- return;
- }
-
- Program *program = context->getState().getProgram();
- program->setUniform3iv(location, count, v);
- }
-}
-
-void GL_APIENTRY Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-{
- GLfloat xyzw[4] = {x, y, z, w};
-
- Uniform4fv(location, 1, xyzw);
-}
-
-void GL_APIENTRY Uniform4fv(GLint location, GLsizei count, const GLfloat* v)
-{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateUniform(context, GL_FLOAT_VEC4, location, count))
- {
- return;
- }
-
- Program *program = context->getState().getProgram();
- program->setUniform4fv(location, count, v);
- }
-}
-
-void GL_APIENTRY Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
-{
- GLint xyzw[4] = {x, y, z, w};
-
- Uniform4iv(location, 1, xyzw);
-}
-
-void GL_APIENTRY Uniform4iv(GLint location, GLsizei count, const GLint* v)
-{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateUniform(context, GL_INT_VEC4, location, count))
- {
- return;
- }
-
- Program *program = context->getState().getProgram();
- program->setUniform4iv(location, count, v);
- }
-}
-
-void GL_APIENTRY UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
-{
- EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
- location, count, transpose, value);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose))
- {
- return;
- }
-
- Program *program = context->getState().getProgram();
- program->setUniformMatrix2fv(location, count, transpose, value);
- }
-}
-
-void GL_APIENTRY UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
-{
- EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
- location, count, transpose, value);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose))
- {
- return;
- }
-
- Program *program = context->getState().getProgram();
- program->setUniformMatrix3fv(location, count, transpose, value);
- }
-}
-
-void GL_APIENTRY UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
-{
- EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
- location, count, transpose, value);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose))
- {
- return;
- }
-
- Program *program = context->getState().getProgram();
- program->setUniformMatrix4fv(location, count, transpose, value);
- }
-}
-
-void GL_APIENTRY UseProgram(GLuint program)
-{
- EVENT("(GLuint program = %d)", program);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- Program *programObject = context->getProgram(program);
-
- if (!programObject && program != 0)
- {
- if (context->getShader(program))
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
- else
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
- }
-
- if (program != 0 && !programObject->isLinked())
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- context->useProgram(program);
- }
-}
-
-void GL_APIENTRY ValidateProgram(GLuint program)
-{
- EVENT("(GLuint program = %d)", program);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- Program *programObject = GetValidProgram(context, program);
-
- if (!programObject)
- {
- return;
- }
-
- programObject->validate(context->getCaps());
- }
-}
-
-void GL_APIENTRY VertexAttrib1f(GLuint index, GLfloat x)
-{
- EVENT("(GLuint index = %d, GLfloat x = %f)", index, x);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- GLfloat vals[4] = { x, 0, 0, 1 };
- context->getState().setVertexAttribf(index, vals);
- }
-}
-
-void GL_APIENTRY VertexAttrib1fv(GLuint index, const GLfloat* values)
-{
- EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- GLfloat vals[4] = { values[0], 0, 0, 1 };
- context->getState().setVertexAttribf(index, vals);
- }
-}
-
-void GL_APIENTRY VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
-{
- EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- GLfloat vals[4] = { x, y, 0, 1 };
- context->getState().setVertexAttribf(index, vals);
- }
-}
-
-void GL_APIENTRY VertexAttrib2fv(GLuint index, const GLfloat* values)
-{
- EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- GLfloat vals[4] = { values[0], values[1], 0, 1 };
- context->getState().setVertexAttribf(index, vals);
- }
-}
-
-void GL_APIENTRY VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
-{
- EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- GLfloat vals[4] = { x, y, z, 1 };
- context->getState().setVertexAttribf(index, vals);
- }
-}
-
-void GL_APIENTRY VertexAttrib3fv(GLuint index, const GLfloat* values)
-{
- EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- GLfloat vals[4] = { values[0], values[1], values[2], 1 };
- context->getState().setVertexAttribf(index, vals);
- }
-}
-
-void GL_APIENTRY VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-{
- EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- GLfloat vals[4] = { x, y, z, w };
- context->getState().setVertexAttribf(index, vals);
- }
-}
-
-void GL_APIENTRY VertexAttrib4fv(GLuint index, const GLfloat* values)
-{
- EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- context->getState().setVertexAttribf(index, values);
- }
-}
-
-void GL_APIENTRY VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
-{
- EVENT("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
- "GLboolean normalized = %u, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)",
- index, size, type, normalized, stride, ptr);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- if (size < 1 || size > 4)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- switch (type)
- {
- case GL_BYTE:
- case GL_UNSIGNED_BYTE:
- case GL_SHORT:
- case GL_UNSIGNED_SHORT:
- case GL_FIXED:
- case GL_FLOAT:
- break;
-
- case GL_HALF_FLOAT:
- case GL_INT:
- case GL_UNSIGNED_INT:
- case GL_INT_2_10_10_10_REV:
- case GL_UNSIGNED_INT_2_10_10_10_REV:
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- if (stride < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- // [OpenGL ES 3.0.2] Section 2.8 page 24:
- // An INVALID_OPERATION error is generated when a non-zero vertex array object
- // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
- // and the pointer argument is not NULL.
- if (context->getState().getVertexArray()->id() != 0 && context->getState().getArrayBufferId() == 0 && ptr != NULL)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- context->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type,
- normalized == GL_TRUE, false, stride, ptr);
- }
-}
-
-void GL_APIENTRY Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
-{
- EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (width < 0 || height < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- context->getState().setViewportParams(x, y, width, height);
- }
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.h b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.h
deleted file mode 100644
index eee5fb5468..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.h
+++ /dev/null
@@ -1,163 +0,0 @@
-//
-// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// entry_points_gles_2_0.h : Defines the GLES 2.0 entry points.
-
-#ifndef LIBGLESV2_ENTRYPOINTGLES20_H_
-#define LIBGLESV2_ENTRYPOINTGLES20_H_
-
-#include <GLES2/gl2.h>
-#include <export.h>
-
-namespace gl
-{
-
-ANGLE_EXPORT void GL_APIENTRY ActiveTexture(GLenum texture);
-ANGLE_EXPORT void GL_APIENTRY AttachShader(GLuint program, GLuint shader);
-ANGLE_EXPORT void GL_APIENTRY BindAttribLocation(GLuint program, GLuint index, const GLchar* name);
-ANGLE_EXPORT void GL_APIENTRY BindBuffer(GLenum target, GLuint buffer);
-ANGLE_EXPORT void GL_APIENTRY BindFramebuffer(GLenum target, GLuint framebuffer);
-ANGLE_EXPORT void GL_APIENTRY BindRenderbuffer(GLenum target, GLuint renderbuffer);
-ANGLE_EXPORT void GL_APIENTRY BindTexture(GLenum target, GLuint texture);
-ANGLE_EXPORT void GL_APIENTRY BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
-ANGLE_EXPORT void GL_APIENTRY BlendEquation(GLenum mode);
-ANGLE_EXPORT void GL_APIENTRY BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
-ANGLE_EXPORT void GL_APIENTRY BlendFunc(GLenum sfactor, GLenum dfactor);
-ANGLE_EXPORT void GL_APIENTRY BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
-ANGLE_EXPORT void GL_APIENTRY BufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
-ANGLE_EXPORT void GL_APIENTRY BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
-ANGLE_EXPORT GLenum GL_APIENTRY CheckFramebufferStatus(GLenum target);
-ANGLE_EXPORT void GL_APIENTRY Clear(GLbitfield mask);
-ANGLE_EXPORT void GL_APIENTRY ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
-ANGLE_EXPORT void GL_APIENTRY ClearDepthf(GLfloat depth);
-ANGLE_EXPORT void GL_APIENTRY ClearStencil(GLint s);
-ANGLE_EXPORT void GL_APIENTRY ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
-ANGLE_EXPORT void GL_APIENTRY CompileShader(GLuint shader);
-ANGLE_EXPORT void GL_APIENTRY CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data);
-ANGLE_EXPORT void GL_APIENTRY CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
-ANGLE_EXPORT void GL_APIENTRY CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
-ANGLE_EXPORT void GL_APIENTRY CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
-ANGLE_EXPORT GLuint GL_APIENTRY CreateProgram(void);
-ANGLE_EXPORT GLuint GL_APIENTRY CreateShader(GLenum type);
-ANGLE_EXPORT void GL_APIENTRY CullFace(GLenum mode);
-ANGLE_EXPORT void GL_APIENTRY DeleteBuffers(GLsizei n, const GLuint* buffers);
-ANGLE_EXPORT void GL_APIENTRY DeleteFramebuffers(GLsizei n, const GLuint* framebuffers);
-ANGLE_EXPORT void GL_APIENTRY DeleteProgram(GLuint program);
-ANGLE_EXPORT void GL_APIENTRY DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers);
-ANGLE_EXPORT void GL_APIENTRY DeleteShader(GLuint shader);
-ANGLE_EXPORT void GL_APIENTRY DeleteTextures(GLsizei n, const GLuint* textures);
-ANGLE_EXPORT void GL_APIENTRY DepthFunc(GLenum func);
-ANGLE_EXPORT void GL_APIENTRY DepthMask(GLboolean flag);
-ANGLE_EXPORT void GL_APIENTRY DepthRangef(GLfloat n, GLfloat f);
-ANGLE_EXPORT void GL_APIENTRY DetachShader(GLuint program, GLuint shader);
-ANGLE_EXPORT void GL_APIENTRY Disable(GLenum cap);
-ANGLE_EXPORT void GL_APIENTRY DisableVertexAttribArray(GLuint index);
-ANGLE_EXPORT void GL_APIENTRY DrawArrays(GLenum mode, GLint first, GLsizei count);
-ANGLE_EXPORT void GL_APIENTRY DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
-ANGLE_EXPORT void GL_APIENTRY Enable(GLenum cap);
-ANGLE_EXPORT void GL_APIENTRY EnableVertexAttribArray(GLuint index);
-ANGLE_EXPORT void GL_APIENTRY Finish(void);
-ANGLE_EXPORT void GL_APIENTRY Flush(void);
-ANGLE_EXPORT void GL_APIENTRY FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
-ANGLE_EXPORT void GL_APIENTRY FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
-ANGLE_EXPORT void GL_APIENTRY FrontFace(GLenum mode);
-ANGLE_EXPORT void GL_APIENTRY GenBuffers(GLsizei n, GLuint* buffers);
-ANGLE_EXPORT void GL_APIENTRY GenerateMipmap(GLenum target);
-ANGLE_EXPORT void GL_APIENTRY GenFramebuffers(GLsizei n, GLuint* framebuffers);
-ANGLE_EXPORT void GL_APIENTRY GenRenderbuffers(GLsizei n, GLuint* renderbuffers);
-ANGLE_EXPORT void GL_APIENTRY GenTextures(GLsizei n, GLuint* textures);
-ANGLE_EXPORT void GL_APIENTRY GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
-ANGLE_EXPORT void GL_APIENTRY GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
-ANGLE_EXPORT void GL_APIENTRY GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
-ANGLE_EXPORT GLint GL_APIENTRY GetAttribLocation(GLuint program, const GLchar* name);
-ANGLE_EXPORT void GL_APIENTRY GetBooleanv(GLenum pname, GLboolean* params);
-ANGLE_EXPORT void GL_APIENTRY GetBufferParameteriv(GLenum target, GLenum pname, GLint* params);
-ANGLE_EXPORT GLenum GL_APIENTRY GetError(void);
-ANGLE_EXPORT void GL_APIENTRY GetFloatv(GLenum pname, GLfloat* params);
-ANGLE_EXPORT void GL_APIENTRY GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params);
-ANGLE_EXPORT void GL_APIENTRY GetIntegerv(GLenum pname, GLint* params);
-ANGLE_EXPORT void GL_APIENTRY GetProgramiv(GLuint program, GLenum pname, GLint* params);
-ANGLE_EXPORT void GL_APIENTRY GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
-ANGLE_EXPORT void GL_APIENTRY GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params);
-ANGLE_EXPORT void GL_APIENTRY GetShaderiv(GLuint shader, GLenum pname, GLint* params);
-ANGLE_EXPORT void GL_APIENTRY GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog);
-ANGLE_EXPORT void GL_APIENTRY GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
-ANGLE_EXPORT void GL_APIENTRY GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
-ANGLE_EXPORT const GLubyte *GL_APIENTRY GetString(GLenum name);
-ANGLE_EXPORT void GL_APIENTRY GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
-ANGLE_EXPORT void GL_APIENTRY GetTexParameteriv(GLenum target, GLenum pname, GLint* params);
-ANGLE_EXPORT void GL_APIENTRY GetUniformfv(GLuint program, GLint location, GLfloat* params);
-ANGLE_EXPORT void GL_APIENTRY GetUniformiv(GLuint program, GLint location, GLint* params);
-ANGLE_EXPORT GLint GL_APIENTRY GetUniformLocation(GLuint program, const GLchar* name);
-ANGLE_EXPORT void GL_APIENTRY GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params);
-ANGLE_EXPORT void GL_APIENTRY GetVertexAttribiv(GLuint index, GLenum pname, GLint* params);
-ANGLE_EXPORT void GL_APIENTRY GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer);
-ANGLE_EXPORT void GL_APIENTRY Hint(GLenum target, GLenum mode);
-ANGLE_EXPORT GLboolean GL_APIENTRY IsBuffer(GLuint buffer);
-ANGLE_EXPORT GLboolean GL_APIENTRY IsEnabled(GLenum cap);
-ANGLE_EXPORT GLboolean GL_APIENTRY IsFramebuffer(GLuint framebuffer);
-ANGLE_EXPORT GLboolean GL_APIENTRY IsProgram(GLuint program);
-ANGLE_EXPORT GLboolean GL_APIENTRY IsRenderbuffer(GLuint renderbuffer);
-ANGLE_EXPORT GLboolean GL_APIENTRY IsShader(GLuint shader);
-ANGLE_EXPORT GLboolean GL_APIENTRY IsTexture(GLuint texture);
-ANGLE_EXPORT void GL_APIENTRY LineWidth(GLfloat width);
-ANGLE_EXPORT void GL_APIENTRY LinkProgram(GLuint program);
-ANGLE_EXPORT void GL_APIENTRY PixelStorei(GLenum pname, GLint param);
-ANGLE_EXPORT void GL_APIENTRY PolygonOffset(GLfloat factor, GLfloat units);
-ANGLE_EXPORT void GL_APIENTRY ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
-ANGLE_EXPORT void GL_APIENTRY ReleaseShaderCompiler(void);
-ANGLE_EXPORT void GL_APIENTRY RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
-ANGLE_EXPORT void GL_APIENTRY SampleCoverage(GLfloat value, GLboolean invert);
-ANGLE_EXPORT void GL_APIENTRY Scissor(GLint x, GLint y, GLsizei width, GLsizei height);
-ANGLE_EXPORT void GL_APIENTRY ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length);
-ANGLE_EXPORT void GL_APIENTRY ShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length);
-ANGLE_EXPORT void GL_APIENTRY StencilFunc(GLenum func, GLint ref, GLuint mask);
-ANGLE_EXPORT void GL_APIENTRY StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
-ANGLE_EXPORT void GL_APIENTRY StencilMask(GLuint mask);
-ANGLE_EXPORT void GL_APIENTRY StencilMaskSeparate(GLenum face, GLuint mask);
-ANGLE_EXPORT void GL_APIENTRY StencilOp(GLenum fail, GLenum zfail, GLenum zpass);
-ANGLE_EXPORT void GL_APIENTRY StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
-ANGLE_EXPORT void GL_APIENTRY TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
-ANGLE_EXPORT void GL_APIENTRY TexParameterf(GLenum target, GLenum pname, GLfloat param);
-ANGLE_EXPORT void GL_APIENTRY TexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
-ANGLE_EXPORT void GL_APIENTRY TexParameteri(GLenum target, GLenum pname, GLint param);
-ANGLE_EXPORT void GL_APIENTRY TexParameteriv(GLenum target, GLenum pname, const GLint* params);
-ANGLE_EXPORT void GL_APIENTRY TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels);
-ANGLE_EXPORT void GL_APIENTRY Uniform1f(GLint location, GLfloat x);
-ANGLE_EXPORT void GL_APIENTRY Uniform1fv(GLint location, GLsizei count, const GLfloat* v);
-ANGLE_EXPORT void GL_APIENTRY Uniform1i(GLint location, GLint x);
-ANGLE_EXPORT void GL_APIENTRY Uniform1iv(GLint location, GLsizei count, const GLint* v);
-ANGLE_EXPORT void GL_APIENTRY Uniform2f(GLint location, GLfloat x, GLfloat y);
-ANGLE_EXPORT void GL_APIENTRY Uniform2fv(GLint location, GLsizei count, const GLfloat* v);
-ANGLE_EXPORT void GL_APIENTRY Uniform2i(GLint location, GLint x, GLint y);
-ANGLE_EXPORT void GL_APIENTRY Uniform2iv(GLint location, GLsizei count, const GLint* v);
-ANGLE_EXPORT void GL_APIENTRY Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z);
-ANGLE_EXPORT void GL_APIENTRY Uniform3fv(GLint location, GLsizei count, const GLfloat* v);
-ANGLE_EXPORT void GL_APIENTRY Uniform3i(GLint location, GLint x, GLint y, GLint z);
-ANGLE_EXPORT void GL_APIENTRY Uniform3iv(GLint location, GLsizei count, const GLint* v);
-ANGLE_EXPORT void GL_APIENTRY Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-ANGLE_EXPORT void GL_APIENTRY Uniform4fv(GLint location, GLsizei count, const GLfloat* v);
-ANGLE_EXPORT void GL_APIENTRY Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w);
-ANGLE_EXPORT void GL_APIENTRY Uniform4iv(GLint location, GLsizei count, const GLint* v);
-ANGLE_EXPORT void GL_APIENTRY UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
-ANGLE_EXPORT void GL_APIENTRY UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
-ANGLE_EXPORT void GL_APIENTRY UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
-ANGLE_EXPORT void GL_APIENTRY UseProgram(GLuint program);
-ANGLE_EXPORT void GL_APIENTRY ValidateProgram(GLuint program);
-ANGLE_EXPORT void GL_APIENTRY VertexAttrib1f(GLuint indx, GLfloat x);
-ANGLE_EXPORT void GL_APIENTRY VertexAttrib1fv(GLuint indx, const GLfloat* values);
-ANGLE_EXPORT void GL_APIENTRY VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y);
-ANGLE_EXPORT void GL_APIENTRY VertexAttrib2fv(GLuint indx, const GLfloat* values);
-ANGLE_EXPORT void GL_APIENTRY VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z);
-ANGLE_EXPORT void GL_APIENTRY VertexAttrib3fv(GLuint indx, const GLfloat* values);
-ANGLE_EXPORT void GL_APIENTRY VertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-ANGLE_EXPORT void GL_APIENTRY VertexAttrib4fv(GLuint indx, const GLfloat* values);
-ANGLE_EXPORT void GL_APIENTRY VertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
-ANGLE_EXPORT void GL_APIENTRY Viewport(GLint x, GLint y, GLsizei width, GLsizei height);
-
-}
-
-#endif // LIBGLESV2_ENTRYPOINTGLES20_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_autogen.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_autogen.cpp
new file mode 100644
index 0000000000..ae0e944406
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_autogen.cpp
@@ -0,0 +1,2612 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// entry_points_gles_2_0_autogen.cpp:
+// Defines the GLES 2.0 entry points.
+
+#include "libANGLE/Context.h"
+#include "libANGLE/validationES2.h"
+#include "libGLESv2/global_state.h"
+
+namespace gl
+{
+void GL_APIENTRY ActiveTexture(GLenum texture)
+{
+ EVENT("(GLenum texture = 0x%X)", texture);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ActiveTexture>(texture);
+
+ if (context->skipValidation() || ValidateActiveTexture(context, texture))
+ {
+ context->activeTexture(texture);
+ }
+ }
+}
+
+void GL_APIENTRY AttachShader(GLuint program, GLuint shader)
+{
+ EVENT("(GLuint program = %u, GLuint shader = %u)", program, shader);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::AttachShader>(program, shader);
+
+ if (context->skipValidation() || ValidateAttachShader(context, program, shader))
+ {
+ context->attachShader(program, shader);
+ }
+ }
+}
+
+void GL_APIENTRY BindAttribLocation(GLuint program, GLuint index, const GLchar *name)
+{
+ EVENT("(GLuint program = %u, GLuint index = %u, const GLchar *name = 0x%0.8p)", program, index,
+ name);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::BindAttribLocation>(program, index, name);
+
+ if (context->skipValidation() || ValidateBindAttribLocation(context, program, index, name))
+ {
+ context->bindAttribLocation(program, index, name);
+ }
+ }
+}
+
+void GL_APIENTRY BindBuffer(GLenum target, GLuint buffer)
+{
+ EVENT("(GLenum target = 0x%X, GLuint buffer = %u)", target, buffer);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
+ context->gatherParams<EntryPoint::BindBuffer>(targetPacked, buffer);
+
+ if (context->skipValidation() || ValidateBindBuffer(context, targetPacked, buffer))
+ {
+ context->bindBuffer(targetPacked, buffer);
+ }
+ }
+}
+
+void GL_APIENTRY BindFramebuffer(GLenum target, GLuint framebuffer)
+{
+ EVENT("(GLenum target = 0x%X, GLuint framebuffer = %u)", target, framebuffer);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::BindFramebuffer>(target, framebuffer);
+
+ if (context->skipValidation() || ValidateBindFramebuffer(context, target, framebuffer))
+ {
+ context->bindFramebuffer(target, framebuffer);
+ }
+ }
+}
+
+void GL_APIENTRY BindRenderbuffer(GLenum target, GLuint renderbuffer)
+{
+ EVENT("(GLenum target = 0x%X, GLuint renderbuffer = %u)", target, renderbuffer);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::BindRenderbuffer>(target, renderbuffer);
+
+ if (context->skipValidation() || ValidateBindRenderbuffer(context, target, renderbuffer))
+ {
+ context->bindRenderbuffer(target, renderbuffer);
+ }
+ }
+}
+
+void GL_APIENTRY BindTexture(GLenum target, GLuint texture)
+{
+ EVENT("(GLenum target = 0x%X, GLuint texture = %u)", target, texture);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::BindTexture>(target, texture);
+
+ if (context->skipValidation() || ValidateBindTexture(context, target, texture))
+ {
+ context->bindTexture(target, texture);
+ }
+ }
+}
+
+void GL_APIENTRY BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+{
+ EVENT("(GLfloat red = %f, GLfloat green = %f, GLfloat blue = %f, GLfloat alpha = %f)", red,
+ green, blue, alpha);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::BlendColor>(red, green, blue, alpha);
+
+ if (context->skipValidation() || ValidateBlendColor(context, red, green, blue, alpha))
+ {
+ context->blendColor(red, green, blue, alpha);
+ }
+ }
+}
+
+void GL_APIENTRY BlendEquation(GLenum mode)
+{
+ EVENT("(GLenum mode = 0x%X)", mode);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::BlendEquation>(mode);
+
+ if (context->skipValidation() || ValidateBlendEquation(context, mode))
+ {
+ context->blendEquation(mode);
+ }
+ }
+}
+
+void GL_APIENTRY BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
+{
+ EVENT("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::BlendEquationSeparate>(modeRGB, modeAlpha);
+
+ if (context->skipValidation() || ValidateBlendEquationSeparate(context, modeRGB, modeAlpha))
+ {
+ context->blendEquationSeparate(modeRGB, modeAlpha);
+ }
+ }
+}
+
+void GL_APIENTRY BlendFunc(GLenum sfactor, GLenum dfactor)
+{
+ EVENT("(GLenum sfactor = 0x%X, GLenum dfactor = 0x%X)", sfactor, dfactor);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::BlendFunc>(sfactor, dfactor);
+
+ if (context->skipValidation() || ValidateBlendFunc(context, sfactor, dfactor))
+ {
+ context->blendFunc(sfactor, dfactor);
+ }
+ }
+}
+
+void GL_APIENTRY BlendFuncSeparate(GLenum sfactorRGB,
+ GLenum dfactorRGB,
+ GLenum sfactorAlpha,
+ GLenum dfactorAlpha)
+{
+ EVENT(
+ "(GLenum sfactorRGB = 0x%X, GLenum dfactorRGB = 0x%X, GLenum sfactorAlpha = 0x%X, GLenum "
+ "dfactorAlpha = 0x%X)",
+ sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::BlendFuncSeparate>(sfactorRGB, dfactorRGB, sfactorAlpha,
+ dfactorAlpha);
+
+ if (context->skipValidation() ||
+ ValidateBlendFuncSeparate(context, sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha))
+ {
+ context->blendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
+ }
+ }
+}
+
+void GL_APIENTRY BufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLsizeiptr size = %d, const void *data = 0x%0.8p, GLenum usage = "
+ "0x%X)",
+ target, size, data, usage);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
+ BufferUsage usagePacked = FromGLenum<BufferUsage>(usage);
+ context->gatherParams<EntryPoint::BufferData>(targetPacked, size, data, usagePacked);
+
+ if (context->skipValidation() ||
+ ValidateBufferData(context, targetPacked, size, data, usagePacked))
+ {
+ context->bufferData(targetPacked, size, data, usagePacked);
+ }
+ }
+}
+
+void GL_APIENTRY BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void *data)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const void *data = "
+ "0x%0.8p)",
+ target, offset, size, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
+ context->gatherParams<EntryPoint::BufferSubData>(targetPacked, offset, size, data);
+
+ if (context->skipValidation() ||
+ ValidateBufferSubData(context, targetPacked, offset, size, data))
+ {
+ context->bufferSubData(targetPacked, offset, size, data);
+ }
+ }
+}
+
+GLenum GL_APIENTRY CheckFramebufferStatus(GLenum target)
+{
+ EVENT("(GLenum target = 0x%X)", target);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::CheckFramebufferStatus>(target);
+
+ if (context->skipValidation() || ValidateCheckFramebufferStatus(context, target))
+ {
+ return context->checkFramebufferStatus(target);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::CheckFramebufferStatus, GLenum>();
+}
+
+void GL_APIENTRY Clear(GLbitfield mask)
+{
+ EVENT("(GLbitfield mask = 0x%X)", mask);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Clear>(mask);
+
+ if (context->skipValidation() || ValidateClear(context, mask))
+ {
+ context->clear(mask);
+ }
+ }
+}
+
+void GL_APIENTRY ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+{
+ EVENT("(GLfloat red = %f, GLfloat green = %f, GLfloat blue = %f, GLfloat alpha = %f)", red,
+ green, blue, alpha);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ClearColor>(red, green, blue, alpha);
+
+ if (context->skipValidation() || ValidateClearColor(context, red, green, blue, alpha))
+ {
+ context->clearColor(red, green, blue, alpha);
+ }
+ }
+}
+
+void GL_APIENTRY ClearDepthf(GLfloat d)
+{
+ EVENT("(GLfloat d = %f)", d);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ClearDepthf>(d);
+
+ if (context->skipValidation() || ValidateClearDepthf(context, d))
+ {
+ context->clearDepthf(d);
+ }
+ }
+}
+
+void GL_APIENTRY ClearStencil(GLint s)
+{
+ EVENT("(GLint s = %d)", s);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ClearStencil>(s);
+
+ if (context->skipValidation() || ValidateClearStencil(context, s))
+ {
+ context->clearStencil(s);
+ }
+ }
+}
+
+void GL_APIENTRY ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+{
+ EVENT("(GLboolean red = %u, GLboolean green = %u, GLboolean blue = %u, GLboolean alpha = %u)",
+ red, green, blue, alpha);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ColorMask>(red, green, blue, alpha);
+
+ if (context->skipValidation() || ValidateColorMask(context, red, green, blue, alpha))
+ {
+ context->colorMask(red, green, blue, alpha);
+ }
+ }
+}
+
+void GL_APIENTRY CompileShader(GLuint shader)
+{
+ EVENT("(GLuint shader = %u)", shader);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::CompileShader>(shader);
+
+ if (context->skipValidation() || ValidateCompileShader(context, shader))
+ {
+ context->compileShader(shader);
+ }
+ }
+}
+
+void GL_APIENTRY CompressedTexImage2D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ const void *data)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = "
+ "%d, GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const void *data = "
+ "0x%0.8p)",
+ target, level, internalformat, width, height, border, imageSize, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::CompressedTexImage2D>(
+ target, level, internalformat, width, height, border, imageSize, data);
+
+ if (context->skipValidation() ||
+ ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
+ border, imageSize, data))
+ {
+ context->compressedTexImage2D(target, level, internalformat, width, height, border,
+ imageSize, data);
+ }
+ }
+}
+
+void GL_APIENTRY CompressedTexSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, GLsizei "
+ "width = %d, GLsizei height = %d, GLenum format = 0x%X, GLsizei imageSize = %d, const void "
+ "*data = 0x%0.8p)",
+ target, level, xoffset, yoffset, width, height, format, imageSize, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::CompressedTexSubImage2D>(
+ target, level, xoffset, yoffset, width, height, format, imageSize, data);
+
+ if (context->skipValidation() ||
+ ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
+ format, imageSize, data))
+ {
+ context->compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format,
+ imageSize, data);
+ }
+ }
+}
+
+void GL_APIENTRY CopyTexImage2D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLint x = %d, "
+ "GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
+ target, level, internalformat, x, y, width, height, border);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::CopyTexImage2D>(target, level, internalformat, x, y,
+ width, height, border);
+
+ if (context->skipValidation() ||
+ ValidateCopyTexImage2D(context, target, level, internalformat, x, y, width, height,
+ border))
+ {
+ context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
+ }
+ }
+}
+
+void GL_APIENTRY CopyTexSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, GLint x "
+ "= %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
+ target, level, xoffset, yoffset, x, y, width, height);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::CopyTexSubImage2D>(target, level, xoffset, yoffset, x, y,
+ width, height);
+
+ if (context->skipValidation() || ValidateCopyTexSubImage2D(context, target, level, xoffset,
+ yoffset, x, y, width, height))
+ {
+ context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
+ }
+ }
+}
+
+GLuint GL_APIENTRY CreateProgram()
+{
+ EVENT("()");
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::CreateProgram>();
+
+ if (context->skipValidation() || ValidateCreateProgram(context))
+ {
+ return context->createProgram();
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::CreateProgram, GLuint>();
+}
+
+GLuint GL_APIENTRY CreateShader(GLenum type)
+{
+ EVENT("(GLenum type = 0x%X)", type);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::CreateShader>(type);
+
+ if (context->skipValidation() || ValidateCreateShader(context, type))
+ {
+ return context->createShader(type);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::CreateShader, GLuint>();
+}
+
+void GL_APIENTRY CullFace(GLenum mode)
+{
+ EVENT("(GLenum mode = 0x%X)", mode);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ CullFaceMode modePacked = FromGLenum<CullFaceMode>(mode);
+ context->gatherParams<EntryPoint::CullFace>(modePacked);
+
+ if (context->skipValidation() || ValidateCullFace(context, modePacked))
+ {
+ context->cullFace(modePacked);
+ }
+ }
+}
+
+void GL_APIENTRY DeleteBuffers(GLsizei n, const GLuint *buffers)
+{
+ EVENT("(GLsizei n = %d, const GLuint *buffers = 0x%0.8p)", n, buffers);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DeleteBuffers>(n, buffers);
+
+ if (context->skipValidation() || ValidateDeleteBuffers(context, n, buffers))
+ {
+ context->deleteBuffers(n, buffers);
+ }
+ }
+}
+
+void GL_APIENTRY DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
+{
+ EVENT("(GLsizei n = %d, const GLuint *framebuffers = 0x%0.8p)", n, framebuffers);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DeleteFramebuffers>(n, framebuffers);
+
+ if (context->skipValidation() || ValidateDeleteFramebuffers(context, n, framebuffers))
+ {
+ context->deleteFramebuffers(n, framebuffers);
+ }
+ }
+}
+
+void GL_APIENTRY DeleteProgram(GLuint program)
+{
+ EVENT("(GLuint program = %u)", program);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DeleteProgram>(program);
+
+ if (context->skipValidation() || ValidateDeleteProgram(context, program))
+ {
+ context->deleteProgram(program);
+ }
+ }
+}
+
+void GL_APIENTRY DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
+{
+ EVENT("(GLsizei n = %d, const GLuint *renderbuffers = 0x%0.8p)", n, renderbuffers);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DeleteRenderbuffers>(n, renderbuffers);
+
+ if (context->skipValidation() || ValidateDeleteRenderbuffers(context, n, renderbuffers))
+ {
+ context->deleteRenderbuffers(n, renderbuffers);
+ }
+ }
+}
+
+void GL_APIENTRY DeleteShader(GLuint shader)
+{
+ EVENT("(GLuint shader = %u)", shader);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DeleteShader>(shader);
+
+ if (context->skipValidation() || ValidateDeleteShader(context, shader))
+ {
+ context->deleteShader(shader);
+ }
+ }
+}
+
+void GL_APIENTRY DeleteTextures(GLsizei n, const GLuint *textures)
+{
+ EVENT("(GLsizei n = %d, const GLuint *textures = 0x%0.8p)", n, textures);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DeleteTextures>(n, textures);
+
+ if (context->skipValidation() || ValidateDeleteTextures(context, n, textures))
+ {
+ context->deleteTextures(n, textures);
+ }
+ }
+}
+
+void GL_APIENTRY DepthFunc(GLenum func)
+{
+ EVENT("(GLenum func = 0x%X)", func);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DepthFunc>(func);
+
+ if (context->skipValidation() || ValidateDepthFunc(context, func))
+ {
+ context->depthFunc(func);
+ }
+ }
+}
+
+void GL_APIENTRY DepthMask(GLboolean flag)
+{
+ EVENT("(GLboolean flag = %u)", flag);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DepthMask>(flag);
+
+ if (context->skipValidation() || ValidateDepthMask(context, flag))
+ {
+ context->depthMask(flag);
+ }
+ }
+}
+
+void GL_APIENTRY DepthRangef(GLfloat n, GLfloat f)
+{
+ EVENT("(GLfloat n = %f, GLfloat f = %f)", n, f);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DepthRangef>(n, f);
+
+ if (context->skipValidation() || ValidateDepthRangef(context, n, f))
+ {
+ context->depthRangef(n, f);
+ }
+ }
+}
+
+void GL_APIENTRY DetachShader(GLuint program, GLuint shader)
+{
+ EVENT("(GLuint program = %u, GLuint shader = %u)", program, shader);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DetachShader>(program, shader);
+
+ if (context->skipValidation() || ValidateDetachShader(context, program, shader))
+ {
+ context->detachShader(program, shader);
+ }
+ }
+}
+
+void GL_APIENTRY Disable(GLenum cap)
+{
+ EVENT("(GLenum cap = 0x%X)", cap);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Disable>(cap);
+
+ if (context->skipValidation() || ValidateDisable(context, cap))
+ {
+ context->disable(cap);
+ }
+ }
+}
+
+void GL_APIENTRY DisableVertexAttribArray(GLuint index)
+{
+ EVENT("(GLuint index = %u)", index);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DisableVertexAttribArray>(index);
+
+ if (context->skipValidation() || ValidateDisableVertexAttribArray(context, index))
+ {
+ context->disableVertexAttribArray(index);
+ }
+ }
+}
+
+void GL_APIENTRY DrawArrays(GLenum mode, GLint first, GLsizei count)
+{
+ EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DrawArrays>(mode, first, count);
+
+ if (context->skipValidation() || ValidateDrawArrays(context, mode, first, count))
+ {
+ context->drawArrays(mode, first, count);
+ }
+ }
+}
+
+void GL_APIENTRY DrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)
+{
+ EVENT(
+ "(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = "
+ "0x%0.8p)",
+ mode, count, type, indices);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DrawElements>(mode, count, type, indices);
+
+ if (context->skipValidation() || ValidateDrawElements(context, mode, count, type, indices))
+ {
+ context->drawElements(mode, count, type, indices);
+ }
+ }
+}
+
+void GL_APIENTRY Enable(GLenum cap)
+{
+ EVENT("(GLenum cap = 0x%X)", cap);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Enable>(cap);
+
+ if (context->skipValidation() || ValidateEnable(context, cap))
+ {
+ context->enable(cap);
+ }
+ }
+}
+
+void GL_APIENTRY EnableVertexAttribArray(GLuint index)
+{
+ EVENT("(GLuint index = %u)", index);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::EnableVertexAttribArray>(index);
+
+ if (context->skipValidation() || ValidateEnableVertexAttribArray(context, index))
+ {
+ context->enableVertexAttribArray(index);
+ }
+ }
+}
+
+void GL_APIENTRY Finish()
+{
+ EVENT("()");
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Finish>();
+
+ if (context->skipValidation() || ValidateFinish(context))
+ {
+ context->finish();
+ }
+ }
+}
+
+void GL_APIENTRY Flush()
+{
+ EVENT("()");
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Flush>();
+
+ if (context->skipValidation() || ValidateFlush(context))
+ {
+ context->flush();
+ }
+ }
+}
+
+void GL_APIENTRY FramebufferRenderbuffer(GLenum target,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, GLuint "
+ "renderbuffer = %u)",
+ target, attachment, renderbuffertarget, renderbuffer);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::FramebufferRenderbuffer>(
+ target, attachment, renderbuffertarget, renderbuffer);
+
+ if (context->skipValidation() ||
+ ValidateFramebufferRenderbuffer(context, target, attachment, renderbuffertarget,
+ renderbuffer))
+ {
+ context->framebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
+ }
+ }
+}
+
+void GL_APIENTRY FramebufferTexture2D(GLenum target,
+ GLenum attachment,
+ GLenum textarget,
+ GLuint texture,
+ GLint level)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, GLuint texture "
+ "= %u, GLint level = %d)",
+ target, attachment, textarget, texture, level);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::FramebufferTexture2D>(target, attachment, textarget,
+ texture, level);
+
+ if (context->skipValidation() ||
+ ValidateFramebufferTexture2D(context, target, attachment, textarget, texture, level))
+ {
+ context->framebufferTexture2D(target, attachment, textarget, texture, level);
+ }
+ }
+}
+
+void GL_APIENTRY FrontFace(GLenum mode)
+{
+ EVENT("(GLenum mode = 0x%X)", mode);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::FrontFace>(mode);
+
+ if (context->skipValidation() || ValidateFrontFace(context, mode))
+ {
+ context->frontFace(mode);
+ }
+ }
+}
+
+void GL_APIENTRY GenBuffers(GLsizei n, GLuint *buffers)
+{
+ EVENT("(GLsizei n = %d, GLuint *buffers = 0x%0.8p)", n, buffers);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GenBuffers>(n, buffers);
+
+ if (context->skipValidation() || ValidateGenBuffers(context, n, buffers))
+ {
+ context->genBuffers(n, buffers);
+ }
+ }
+}
+
+void GL_APIENTRY GenerateMipmap(GLenum target)
+{
+ EVENT("(GLenum target = 0x%X)", target);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GenerateMipmap>(target);
+
+ if (context->skipValidation() || ValidateGenerateMipmap(context, target))
+ {
+ context->generateMipmap(target);
+ }
+ }
+}
+
+void GL_APIENTRY GenFramebuffers(GLsizei n, GLuint *framebuffers)
+{
+ EVENT("(GLsizei n = %d, GLuint *framebuffers = 0x%0.8p)", n, framebuffers);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GenFramebuffers>(n, framebuffers);
+
+ if (context->skipValidation() || ValidateGenFramebuffers(context, n, framebuffers))
+ {
+ context->genFramebuffers(n, framebuffers);
+ }
+ }
+}
+
+void GL_APIENTRY GenRenderbuffers(GLsizei n, GLuint *renderbuffers)
+{
+ EVENT("(GLsizei n = %d, GLuint *renderbuffers = 0x%0.8p)", n, renderbuffers);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GenRenderbuffers>(n, renderbuffers);
+
+ if (context->skipValidation() || ValidateGenRenderbuffers(context, n, renderbuffers))
+ {
+ context->genRenderbuffers(n, renderbuffers);
+ }
+ }
+}
+
+void GL_APIENTRY GenTextures(GLsizei n, GLuint *textures)
+{
+ EVENT("(GLsizei n = %d, GLuint *textures = 0x%0.8p)", n, textures);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GenTextures>(n, textures);
+
+ if (context->skipValidation() || ValidateGenTextures(context, n, textures))
+ {
+ context->genTextures(n, textures);
+ }
+ }
+}
+
+void GL_APIENTRY GetActiveAttrib(GLuint program,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name)
+{
+ EVENT(
+ "(GLuint program = %u, GLuint index = %u, GLsizei bufSize = %d, GLsizei *length = 0x%0.8p, "
+ "GLint *size = 0x%0.8p, GLenum *type = 0x%0.8p, GLchar *name = 0x%0.8p)",
+ program, index, bufSize, length, size, type, name);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetActiveAttrib>(program, index, bufSize, length, size,
+ type, name);
+
+ if (context->skipValidation() ||
+ ValidateGetActiveAttrib(context, program, index, bufSize, length, size, type, name))
+ {
+ context->getActiveAttrib(program, index, bufSize, length, size, type, name);
+ }
+ }
+}
+
+void GL_APIENTRY GetActiveUniform(GLuint program,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name)
+{
+ EVENT(
+ "(GLuint program = %u, GLuint index = %u, GLsizei bufSize = %d, GLsizei *length = 0x%0.8p, "
+ "GLint *size = 0x%0.8p, GLenum *type = 0x%0.8p, GLchar *name = 0x%0.8p)",
+ program, index, bufSize, length, size, type, name);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetActiveUniform>(program, index, bufSize, length, size,
+ type, name);
+
+ if (context->skipValidation() ||
+ ValidateGetActiveUniform(context, program, index, bufSize, length, size, type, name))
+ {
+ context->getActiveUniform(program, index, bufSize, length, size, type, name);
+ }
+ }
+}
+
+void GL_APIENTRY GetAttachedShaders(GLuint program,
+ GLsizei maxCount,
+ GLsizei *count,
+ GLuint *shaders)
+{
+ EVENT(
+ "(GLuint program = %u, GLsizei maxCount = %d, GLsizei *count = 0x%0.8p, GLuint *shaders = "
+ "0x%0.8p)",
+ program, maxCount, count, shaders);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetAttachedShaders>(program, maxCount, count, shaders);
+
+ if (context->skipValidation() ||
+ ValidateGetAttachedShaders(context, program, maxCount, count, shaders))
+ {
+ context->getAttachedShaders(program, maxCount, count, shaders);
+ }
+ }
+}
+
+GLint GL_APIENTRY GetAttribLocation(GLuint program, const GLchar *name)
+{
+ EVENT("(GLuint program = %u, const GLchar *name = 0x%0.8p)", program, name);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetAttribLocation>(program, name);
+
+ if (context->skipValidation() || ValidateGetAttribLocation(context, program, name))
+ {
+ return context->getAttribLocation(program, name);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::GetAttribLocation, GLint>();
+}
+
+void GL_APIENTRY GetBooleanv(GLenum pname, GLboolean *data)
+{
+ EVENT("(GLenum pname = 0x%X, GLboolean *data = 0x%0.8p)", pname, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetBooleanv>(pname, data);
+
+ if (context->skipValidation() || ValidateGetBooleanv(context, pname, data))
+ {
+ context->getBooleanv(pname, data);
+ }
+ }
+}
+
+void GL_APIENTRY GetBufferParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname,
+ params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
+ context->gatherParams<EntryPoint::GetBufferParameteriv>(targetPacked, pname, params);
+
+ if (context->skipValidation() ||
+ ValidateGetBufferParameteriv(context, targetPacked, pname, params))
+ {
+ context->getBufferParameteriv(targetPacked, pname, params);
+ }
+ }
+}
+
+GLenum GL_APIENTRY GetError()
+{
+ EVENT("()");
+
+ Context *context = GetGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetError>();
+
+ if (context->skipValidation() || ValidateGetError(context))
+ {
+ return context->getError();
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::GetError, GLenum>();
+}
+
+void GL_APIENTRY GetFloatv(GLenum pname, GLfloat *data)
+{
+ EVENT("(GLenum pname = 0x%X, GLfloat *data = 0x%0.8p)", pname, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetFloatv>(pname, data);
+
+ if (context->skipValidation() || ValidateGetFloatv(context, pname, data))
+ {
+ context->getFloatv(pname, data);
+ }
+ }
+}
+
+void GL_APIENTRY GetFramebufferAttachmentParameteriv(GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLint *params)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint *params = "
+ "0x%0.8p)",
+ target, attachment, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetFramebufferAttachmentParameteriv>(target, attachment,
+ pname, params);
+
+ if (context->skipValidation() ||
+ ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, params))
+ {
+ context->getFramebufferAttachmentParameteriv(target, attachment, pname, params);
+ }
+ }
+}
+
+void GL_APIENTRY GetIntegerv(GLenum pname, GLint *data)
+{
+ EVENT("(GLenum pname = 0x%X, GLint *data = 0x%0.8p)", pname, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetIntegerv>(pname, data);
+
+ if (context->skipValidation() || ValidateGetIntegerv(context, pname, data))
+ {
+ context->getIntegerv(pname, data);
+ }
+ }
+}
+
+void GL_APIENTRY GetProgramiv(GLuint program, GLenum pname, GLint *params)
+{
+ EVENT("(GLuint program = %u, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", program, pname,
+ params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetProgramiv>(program, pname, params);
+
+ if (context->skipValidation() || ValidateGetProgramiv(context, program, pname, params))
+ {
+ context->getProgramiv(program, pname, params);
+ }
+ }
+}
+
+void GL_APIENTRY GetProgramInfoLog(GLuint program,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *infoLog)
+{
+ EVENT(
+ "(GLuint program = %u, GLsizei bufSize = %d, GLsizei *length = 0x%0.8p, GLchar *infoLog = "
+ "0x%0.8p)",
+ program, bufSize, length, infoLog);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetProgramInfoLog>(program, bufSize, length, infoLog);
+
+ if (context->skipValidation() ||
+ ValidateGetProgramInfoLog(context, program, bufSize, length, infoLog))
+ {
+ context->getProgramInfoLog(program, bufSize, length, infoLog);
+ }
+ }
+}
+
+void GL_APIENTRY GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname,
+ params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetRenderbufferParameteriv>(target, pname, params);
+
+ if (context->skipValidation() ||
+ ValidateGetRenderbufferParameteriv(context, target, pname, params))
+ {
+ context->getRenderbufferParameteriv(target, pname, params);
+ }
+ }
+}
+
+void GL_APIENTRY GetShaderiv(GLuint shader, GLenum pname, GLint *params)
+{
+ EVENT("(GLuint shader = %u, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", shader, pname,
+ params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetShaderiv>(shader, pname, params);
+
+ if (context->skipValidation() || ValidateGetShaderiv(context, shader, pname, params))
+ {
+ context->getShaderiv(shader, pname, params);
+ }
+ }
+}
+
+void GL_APIENTRY GetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog)
+{
+ EVENT(
+ "(GLuint shader = %u, GLsizei bufSize = %d, GLsizei *length = 0x%0.8p, GLchar *infoLog = "
+ "0x%0.8p)",
+ shader, bufSize, length, infoLog);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetShaderInfoLog>(shader, bufSize, length, infoLog);
+
+ if (context->skipValidation() ||
+ ValidateGetShaderInfoLog(context, shader, bufSize, length, infoLog))
+ {
+ context->getShaderInfoLog(shader, bufSize, length, infoLog);
+ }
+ }
+}
+
+void GL_APIENTRY GetShaderPrecisionFormat(GLenum shadertype,
+ GLenum precisiontype,
+ GLint *range,
+ GLint *precision)
+{
+ EVENT(
+ "(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint *range = 0x%0.8p, GLint "
+ "*precision = 0x%0.8p)",
+ shadertype, precisiontype, range, precision);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetShaderPrecisionFormat>(shadertype, precisiontype,
+ range, precision);
+
+ if (context->skipValidation() ||
+ ValidateGetShaderPrecisionFormat(context, shadertype, precisiontype, range, precision))
+ {
+ context->getShaderPrecisionFormat(shadertype, precisiontype, range, precision);
+ }
+ }
+}
+
+void GL_APIENTRY GetShaderSource(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source)
+{
+ EVENT(
+ "(GLuint shader = %u, GLsizei bufSize = %d, GLsizei *length = 0x%0.8p, GLchar *source = "
+ "0x%0.8p)",
+ shader, bufSize, length, source);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetShaderSource>(shader, bufSize, length, source);
+
+ if (context->skipValidation() ||
+ ValidateGetShaderSource(context, shader, bufSize, length, source))
+ {
+ context->getShaderSource(shader, bufSize, length, source);
+ }
+ }
+}
+
+const GLubyte *GL_APIENTRY GetString(GLenum name)
+{
+ EVENT("(GLenum name = 0x%X)", name);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetString>(name);
+
+ if (context->skipValidation() || ValidateGetString(context, name))
+ {
+ return context->getString(name);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::GetString, const GLubyte *>();
+}
+
+void GL_APIENTRY GetTexParameterfv(GLenum target, GLenum pname, GLfloat *params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat *params = 0x%0.8p)", target, pname,
+ params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetTexParameterfv>(target, pname, params);
+
+ if (context->skipValidation() || ValidateGetTexParameterfv(context, target, pname, params))
+ {
+ context->getTexParameterfv(target, pname, params);
+ }
+ }
+}
+
+void GL_APIENTRY GetTexParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname,
+ params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetTexParameteriv>(target, pname, params);
+
+ if (context->skipValidation() || ValidateGetTexParameteriv(context, target, pname, params))
+ {
+ context->getTexParameteriv(target, pname, params);
+ }
+ }
+}
+
+void GL_APIENTRY GetUniformfv(GLuint program, GLint location, GLfloat *params)
+{
+ EVENT("(GLuint program = %u, GLint location = %d, GLfloat *params = 0x%0.8p)", program,
+ location, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetUniformfv>(program, location, params);
+
+ if (context->skipValidation() || ValidateGetUniformfv(context, program, location, params))
+ {
+ context->getUniformfv(program, location, params);
+ }
+ }
+}
+
+void GL_APIENTRY GetUniformiv(GLuint program, GLint location, GLint *params)
+{
+ EVENT("(GLuint program = %u, GLint location = %d, GLint *params = 0x%0.8p)", program, location,
+ params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetUniformiv>(program, location, params);
+
+ if (context->skipValidation() || ValidateGetUniformiv(context, program, location, params))
+ {
+ context->getUniformiv(program, location, params);
+ }
+ }
+}
+
+GLint GL_APIENTRY GetUniformLocation(GLuint program, const GLchar *name)
+{
+ EVENT("(GLuint program = %u, const GLchar *name = 0x%0.8p)", program, name);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetUniformLocation>(program, name);
+
+ if (context->skipValidation() || ValidateGetUniformLocation(context, program, name))
+ {
+ return context->getUniformLocation(program, name);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::GetUniformLocation, GLint>();
+}
+
+void GL_APIENTRY GetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params)
+{
+ EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLfloat *params = 0x%0.8p)", index, pname,
+ params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetVertexAttribfv>(index, pname, params);
+
+ if (context->skipValidation() || ValidateGetVertexAttribfv(context, index, pname, params))
+ {
+ context->getVertexAttribfv(index, pname, params);
+ }
+ }
+}
+
+void GL_APIENTRY GetVertexAttribiv(GLuint index, GLenum pname, GLint *params)
+{
+ EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", index, pname,
+ params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetVertexAttribiv>(index, pname, params);
+
+ if (context->skipValidation() || ValidateGetVertexAttribiv(context, index, pname, params))
+ {
+ context->getVertexAttribiv(index, pname, params);
+ }
+ }
+}
+
+void GL_APIENTRY GetVertexAttribPointerv(GLuint index, GLenum pname, void **pointer)
+{
+ EVENT("(GLuint index = %u, GLenum pname = 0x%X, void **pointer = 0x%0.8p)", index, pname,
+ pointer);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetVertexAttribPointerv>(index, pname, pointer);
+
+ if (context->skipValidation() ||
+ ValidateGetVertexAttribPointerv(context, index, pname, pointer))
+ {
+ context->getVertexAttribPointerv(index, pname, pointer);
+ }
+ }
+}
+
+void GL_APIENTRY Hint(GLenum target, GLenum mode)
+{
+ EVENT("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Hint>(target, mode);
+
+ if (context->skipValidation() || ValidateHint(context, target, mode))
+ {
+ context->hint(target, mode);
+ }
+ }
+}
+
+GLboolean GL_APIENTRY IsBuffer(GLuint buffer)
+{
+ EVENT("(GLuint buffer = %u)", buffer);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::IsBuffer>(buffer);
+
+ if (context->skipValidation() || ValidateIsBuffer(context, buffer))
+ {
+ return context->isBuffer(buffer);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::IsBuffer, GLboolean>();
+}
+
+GLboolean GL_APIENTRY IsEnabled(GLenum cap)
+{
+ EVENT("(GLenum cap = 0x%X)", cap);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::IsEnabled>(cap);
+
+ if (context->skipValidation() || ValidateIsEnabled(context, cap))
+ {
+ return context->isEnabled(cap);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::IsEnabled, GLboolean>();
+}
+
+GLboolean GL_APIENTRY IsFramebuffer(GLuint framebuffer)
+{
+ EVENT("(GLuint framebuffer = %u)", framebuffer);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::IsFramebuffer>(framebuffer);
+
+ if (context->skipValidation() || ValidateIsFramebuffer(context, framebuffer))
+ {
+ return context->isFramebuffer(framebuffer);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::IsFramebuffer, GLboolean>();
+}
+
+GLboolean GL_APIENTRY IsProgram(GLuint program)
+{
+ EVENT("(GLuint program = %u)", program);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::IsProgram>(program);
+
+ if (context->skipValidation() || ValidateIsProgram(context, program))
+ {
+ return context->isProgram(program);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::IsProgram, GLboolean>();
+}
+
+GLboolean GL_APIENTRY IsRenderbuffer(GLuint renderbuffer)
+{
+ EVENT("(GLuint renderbuffer = %u)", renderbuffer);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::IsRenderbuffer>(renderbuffer);
+
+ if (context->skipValidation() || ValidateIsRenderbuffer(context, renderbuffer))
+ {
+ return context->isRenderbuffer(renderbuffer);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::IsRenderbuffer, GLboolean>();
+}
+
+GLboolean GL_APIENTRY IsShader(GLuint shader)
+{
+ EVENT("(GLuint shader = %u)", shader);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::IsShader>(shader);
+
+ if (context->skipValidation() || ValidateIsShader(context, shader))
+ {
+ return context->isShader(shader);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::IsShader, GLboolean>();
+}
+
+GLboolean GL_APIENTRY IsTexture(GLuint texture)
+{
+ EVENT("(GLuint texture = %u)", texture);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::IsTexture>(texture);
+
+ if (context->skipValidation() || ValidateIsTexture(context, texture))
+ {
+ return context->isTexture(texture);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::IsTexture, GLboolean>();
+}
+
+void GL_APIENTRY LineWidth(GLfloat width)
+{
+ EVENT("(GLfloat width = %f)", width);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::LineWidth>(width);
+
+ if (context->skipValidation() || ValidateLineWidth(context, width))
+ {
+ context->lineWidth(width);
+ }
+ }
+}
+
+void GL_APIENTRY LinkProgram(GLuint program)
+{
+ EVENT("(GLuint program = %u)", program);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::LinkProgram>(program);
+
+ if (context->skipValidation() || ValidateLinkProgram(context, program))
+ {
+ context->linkProgram(program);
+ }
+ }
+}
+
+void GL_APIENTRY PixelStorei(GLenum pname, GLint param)
+{
+ EVENT("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::PixelStorei>(pname, param);
+
+ if (context->skipValidation() || ValidatePixelStorei(context, pname, param))
+ {
+ context->pixelStorei(pname, param);
+ }
+ }
+}
+
+void GL_APIENTRY PolygonOffset(GLfloat factor, GLfloat units)
+{
+ EVENT("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::PolygonOffset>(factor, units);
+
+ if (context->skipValidation() || ValidatePolygonOffset(context, factor, units))
+ {
+ context->polygonOffset(factor, units);
+ }
+ }
+}
+
+void GL_APIENTRY ReadPixels(GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ void *pixels)
+{
+ EVENT(
+ "(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLenum format = "
+ "0x%X, GLenum type = 0x%X, void *pixels = 0x%0.8p)",
+ x, y, width, height, format, type, pixels);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ReadPixels>(x, y, width, height, format, type, pixels);
+
+ if (context->skipValidation() ||
+ ValidateReadPixels(context, x, y, width, height, format, type, pixels))
+ {
+ context->readPixels(x, y, width, height, format, type, pixels);
+ }
+ }
+}
+
+void GL_APIENTRY ReleaseShaderCompiler()
+{
+ EVENT("()");
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ReleaseShaderCompiler>();
+
+ if (context->skipValidation() || ValidateReleaseShaderCompiler(context))
+ {
+ context->releaseShaderCompiler();
+ }
+ }
+}
+
+void GL_APIENTRY RenderbufferStorage(GLenum target,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = "
+ "%d)",
+ target, internalformat, width, height);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::RenderbufferStorage>(target, internalformat, width,
+ height);
+
+ if (context->skipValidation() ||
+ ValidateRenderbufferStorage(context, target, internalformat, width, height))
+ {
+ context->renderbufferStorage(target, internalformat, width, height);
+ }
+ }
+}
+
+void GL_APIENTRY SampleCoverage(GLfloat value, GLboolean invert)
+{
+ EVENT("(GLfloat value = %f, GLboolean invert = %u)", value, invert);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::SampleCoverage>(value, invert);
+
+ if (context->skipValidation() || ValidateSampleCoverage(context, value, invert))
+ {
+ context->sampleCoverage(value, invert);
+ }
+ }
+}
+
+void GL_APIENTRY Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width,
+ height);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Scissor>(x, y, width, height);
+
+ if (context->skipValidation() || ValidateScissor(context, x, y, width, height))
+ {
+ context->scissor(x, y, width, height);
+ }
+ }
+}
+
+void GL_APIENTRY ShaderBinary(GLsizei count,
+ const GLuint *shaders,
+ GLenum binaryformat,
+ const void *binary,
+ GLsizei length)
+{
+ EVENT(
+ "(GLsizei count = %d, const GLuint *shaders = 0x%0.8p, GLenum binaryformat = 0x%X, const "
+ "void *binary = 0x%0.8p, GLsizei length = %d)",
+ count, shaders, binaryformat, binary, length);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ShaderBinary>(count, shaders, binaryformat, binary,
+ length);
+
+ if (context->skipValidation() ||
+ ValidateShaderBinary(context, count, shaders, binaryformat, binary, length))
+ {
+ context->shaderBinary(count, shaders, binaryformat, binary, length);
+ }
+ }
+}
+
+void GL_APIENTRY ShaderSource(GLuint shader,
+ GLsizei count,
+ const GLchar *const *string,
+ const GLint *length)
+{
+ EVENT(
+ "(GLuint shader = %u, GLsizei count = %d, const GLchar *const*string = 0x%0.8p, const "
+ "GLint *length = 0x%0.8p)",
+ shader, count, string, length);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ShaderSource>(shader, count, string, length);
+
+ if (context->skipValidation() ||
+ ValidateShaderSource(context, shader, count, string, length))
+ {
+ context->shaderSource(shader, count, string, length);
+ }
+ }
+}
+
+void GL_APIENTRY StencilFunc(GLenum func, GLint ref, GLuint mask)
+{
+ EVENT("(GLenum func = 0x%X, GLint ref = %d, GLuint mask = %u)", func, ref, mask);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::StencilFunc>(func, ref, mask);
+
+ if (context->skipValidation() || ValidateStencilFunc(context, func, ref, mask))
+ {
+ context->stencilFunc(func, ref, mask);
+ }
+ }
+}
+
+void GL_APIENTRY StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
+{
+ EVENT("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %u)", face, func,
+ ref, mask);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::StencilFuncSeparate>(face, func, ref, mask);
+
+ if (context->skipValidation() ||
+ ValidateStencilFuncSeparate(context, face, func, ref, mask))
+ {
+ context->stencilFuncSeparate(face, func, ref, mask);
+ }
+ }
+}
+
+void GL_APIENTRY StencilMask(GLuint mask)
+{
+ EVENT("(GLuint mask = %u)", mask);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::StencilMask>(mask);
+
+ if (context->skipValidation() || ValidateStencilMask(context, mask))
+ {
+ context->stencilMask(mask);
+ }
+ }
+}
+
+void GL_APIENTRY StencilMaskSeparate(GLenum face, GLuint mask)
+{
+ EVENT("(GLenum face = 0x%X, GLuint mask = %u)", face, mask);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::StencilMaskSeparate>(face, mask);
+
+ if (context->skipValidation() || ValidateStencilMaskSeparate(context, face, mask))
+ {
+ context->stencilMaskSeparate(face, mask);
+ }
+ }
+}
+
+void GL_APIENTRY StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
+{
+ EVENT("(GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpass = 0x%X)", fail, zfail, zpass);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::StencilOp>(fail, zfail, zpass);
+
+ if (context->skipValidation() || ValidateStencilOp(context, fail, zfail, zpass))
+ {
+ context->stencilOp(fail, zfail, zpass);
+ }
+ }
+}
+
+void GL_APIENTRY StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass)
+{
+ EVENT("(GLenum face = 0x%X, GLenum sfail = 0x%X, GLenum dpfail = 0x%X, GLenum dppass = 0x%X)",
+ face, sfail, dpfail, dppass);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::StencilOpSeparate>(face, sfail, dpfail, dppass);
+
+ if (context->skipValidation() ||
+ ValidateStencilOpSeparate(context, face, sfail, dpfail, dppass))
+ {
+ context->stencilOpSeparate(face, sfail, dpfail, dppass);
+ }
+ }
+}
+
+void GL_APIENTRY TexImage2D(GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, "
+ "GLsizei height = %d, GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const "
+ "void *pixels = 0x%0.8p)",
+ target, level, internalformat, width, height, border, format, type, pixels);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::TexImage2D>(target, level, internalformat, width, height,
+ border, format, type, pixels);
+
+ if (context->skipValidation() ||
+ ValidateTexImage2D(context, target, level, internalformat, width, height, border,
+ format, type, pixels))
+ {
+ context->texImage2D(target, level, internalformat, width, height, border, format, type,
+ pixels);
+ }
+ }
+}
+
+void GL_APIENTRY TexParameterf(GLenum target, GLenum pname, GLfloat param)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat param = %f)", target, pname, param);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::TexParameterf>(target, pname, param);
+
+ if (context->skipValidation() || ValidateTexParameterf(context, target, pname, param))
+ {
+ context->texParameterf(target, pname, param);
+ }
+ }
+}
+
+void GL_APIENTRY TexParameterfv(GLenum target, GLenum pname, const GLfloat *params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, const GLfloat *params = 0x%0.8p)", target,
+ pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::TexParameterfv>(target, pname, params);
+
+ if (context->skipValidation() || ValidateTexParameterfv(context, target, pname, params))
+ {
+ context->texParameterfv(target, pname, params);
+ }
+ }
+}
+
+void GL_APIENTRY TexParameteri(GLenum target, GLenum pname, GLint param)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::TexParameteri>(target, pname, param);
+
+ if (context->skipValidation() || ValidateTexParameteri(context, target, pname, param))
+ {
+ context->texParameteri(target, pname, param);
+ }
+ }
+}
+
+void GL_APIENTRY TexParameteriv(GLenum target, GLenum pname, const GLint *params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, const GLint *params = 0x%0.8p)", target,
+ pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::TexParameteriv>(target, pname, params);
+
+ if (context->skipValidation() || ValidateTexParameteriv(context, target, pname, params))
+ {
+ context->texParameteriv(target, pname, params);
+ }
+ }
+}
+
+void GL_APIENTRY TexSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, GLsizei "
+ "width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, const void "
+ "*pixels = 0x%0.8p)",
+ target, level, xoffset, yoffset, width, height, format, type, pixels);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::TexSubImage2D>(target, level, xoffset, yoffset, width,
+ height, format, type, pixels);
+
+ if (context->skipValidation() ||
+ ValidateTexSubImage2D(context, target, level, xoffset, yoffset, width, height, format,
+ type, pixels))
+ {
+ context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type,
+ pixels);
+ }
+ }
+}
+
+void GL_APIENTRY Uniform1f(GLint location, GLfloat v0)
+{
+ EVENT("(GLint location = %d, GLfloat v0 = %f)", location, v0);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Uniform1f>(location, v0);
+
+ if (context->skipValidation() || ValidateUniform1f(context, location, v0))
+ {
+ context->uniform1f(location, v0);
+ }
+ }
+}
+
+void GL_APIENTRY Uniform1fv(GLint location, GLsizei count, const GLfloat *value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat *value = 0x%0.8p)", location,
+ count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Uniform1fv>(location, count, value);
+
+ if (context->skipValidation() || ValidateUniform1fv(context, location, count, value))
+ {
+ context->uniform1fv(location, count, value);
+ }
+ }
+}
+
+void GL_APIENTRY Uniform1i(GLint location, GLint v0)
+{
+ EVENT("(GLint location = %d, GLint v0 = %d)", location, v0);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Uniform1i>(location, v0);
+
+ if (context->skipValidation() || ValidateUniform1i(context, location, v0))
+ {
+ context->uniform1i(location, v0);
+ }
+ }
+}
+
+void GL_APIENTRY Uniform1iv(GLint location, GLsizei count, const GLint *value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLint *value = 0x%0.8p)", location,
+ count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Uniform1iv>(location, count, value);
+
+ if (context->skipValidation() || ValidateUniform1iv(context, location, count, value))
+ {
+ context->uniform1iv(location, count, value);
+ }
+ }
+}
+
+void GL_APIENTRY Uniform2f(GLint location, GLfloat v0, GLfloat v1)
+{
+ EVENT("(GLint location = %d, GLfloat v0 = %f, GLfloat v1 = %f)", location, v0, v1);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Uniform2f>(location, v0, v1);
+
+ if (context->skipValidation() || ValidateUniform2f(context, location, v0, v1))
+ {
+ context->uniform2f(location, v0, v1);
+ }
+ }
+}
+
+void GL_APIENTRY Uniform2fv(GLint location, GLsizei count, const GLfloat *value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat *value = 0x%0.8p)", location,
+ count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Uniform2fv>(location, count, value);
+
+ if (context->skipValidation() || ValidateUniform2fv(context, location, count, value))
+ {
+ context->uniform2fv(location, count, value);
+ }
+ }
+}
+
+void GL_APIENTRY Uniform2i(GLint location, GLint v0, GLint v1)
+{
+ EVENT("(GLint location = %d, GLint v0 = %d, GLint v1 = %d)", location, v0, v1);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Uniform2i>(location, v0, v1);
+
+ if (context->skipValidation() || ValidateUniform2i(context, location, v0, v1))
+ {
+ context->uniform2i(location, v0, v1);
+ }
+ }
+}
+
+void GL_APIENTRY Uniform2iv(GLint location, GLsizei count, const GLint *value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLint *value = 0x%0.8p)", location,
+ count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Uniform2iv>(location, count, value);
+
+ if (context->skipValidation() || ValidateUniform2iv(context, location, count, value))
+ {
+ context->uniform2iv(location, count, value);
+ }
+ }
+}
+
+void GL_APIENTRY Uniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
+{
+ EVENT("(GLint location = %d, GLfloat v0 = %f, GLfloat v1 = %f, GLfloat v2 = %f)", location, v0,
+ v1, v2);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Uniform3f>(location, v0, v1, v2);
+
+ if (context->skipValidation() || ValidateUniform3f(context, location, v0, v1, v2))
+ {
+ context->uniform3f(location, v0, v1, v2);
+ }
+ }
+}
+
+void GL_APIENTRY Uniform3fv(GLint location, GLsizei count, const GLfloat *value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat *value = 0x%0.8p)", location,
+ count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Uniform3fv>(location, count, value);
+
+ if (context->skipValidation() || ValidateUniform3fv(context, location, count, value))
+ {
+ context->uniform3fv(location, count, value);
+ }
+ }
+}
+
+void GL_APIENTRY Uniform3i(GLint location, GLint v0, GLint v1, GLint v2)
+{
+ EVENT("(GLint location = %d, GLint v0 = %d, GLint v1 = %d, GLint v2 = %d)", location, v0, v1,
+ v2);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Uniform3i>(location, v0, v1, v2);
+
+ if (context->skipValidation() || ValidateUniform3i(context, location, v0, v1, v2))
+ {
+ context->uniform3i(location, v0, v1, v2);
+ }
+ }
+}
+
+void GL_APIENTRY Uniform3iv(GLint location, GLsizei count, const GLint *value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLint *value = 0x%0.8p)", location,
+ count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Uniform3iv>(location, count, value);
+
+ if (context->skipValidation() || ValidateUniform3iv(context, location, count, value))
+ {
+ context->uniform3iv(location, count, value);
+ }
+ }
+}
+
+void GL_APIENTRY Uniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
+{
+ EVENT(
+ "(GLint location = %d, GLfloat v0 = %f, GLfloat v1 = %f, GLfloat v2 = %f, GLfloat v3 = %f)",
+ location, v0, v1, v2, v3);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Uniform4f>(location, v0, v1, v2, v3);
+
+ if (context->skipValidation() || ValidateUniform4f(context, location, v0, v1, v2, v3))
+ {
+ context->uniform4f(location, v0, v1, v2, v3);
+ }
+ }
+}
+
+void GL_APIENTRY Uniform4fv(GLint location, GLsizei count, const GLfloat *value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat *value = 0x%0.8p)", location,
+ count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Uniform4fv>(location, count, value);
+
+ if (context->skipValidation() || ValidateUniform4fv(context, location, count, value))
+ {
+ context->uniform4fv(location, count, value);
+ }
+ }
+}
+
+void GL_APIENTRY Uniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
+{
+ EVENT("(GLint location = %d, GLint v0 = %d, GLint v1 = %d, GLint v2 = %d, GLint v3 = %d)",
+ location, v0, v1, v2, v3);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Uniform4i>(location, v0, v1, v2, v3);
+
+ if (context->skipValidation() || ValidateUniform4i(context, location, v0, v1, v2, v3))
+ {
+ context->uniform4i(location, v0, v1, v2, v3);
+ }
+ }
+}
+
+void GL_APIENTRY Uniform4iv(GLint location, GLsizei count, const GLint *value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLint *value = 0x%0.8p)", location,
+ count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Uniform4iv>(location, count, value);
+
+ if (context->skipValidation() || ValidateUniform4iv(context, location, count, value))
+ {
+ context->uniform4iv(location, count, value);
+ }
+ }
+}
+
+void GL_APIENTRY UniformMatrix2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ EVENT(
+ "(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat *value "
+ "= 0x%0.8p)",
+ location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::UniformMatrix2fv>(location, count, transpose, value);
+
+ if (context->skipValidation() ||
+ ValidateUniformMatrix2fv(context, location, count, transpose, value))
+ {
+ context->uniformMatrix2fv(location, count, transpose, value);
+ }
+ }
+}
+
+void GL_APIENTRY UniformMatrix3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ EVENT(
+ "(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat *value "
+ "= 0x%0.8p)",
+ location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::UniformMatrix3fv>(location, count, transpose, value);
+
+ if (context->skipValidation() ||
+ ValidateUniformMatrix3fv(context, location, count, transpose, value))
+ {
+ context->uniformMatrix3fv(location, count, transpose, value);
+ }
+ }
+}
+
+void GL_APIENTRY UniformMatrix4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ EVENT(
+ "(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat *value "
+ "= 0x%0.8p)",
+ location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::UniformMatrix4fv>(location, count, transpose, value);
+
+ if (context->skipValidation() ||
+ ValidateUniformMatrix4fv(context, location, count, transpose, value))
+ {
+ context->uniformMatrix4fv(location, count, transpose, value);
+ }
+ }
+}
+
+void GL_APIENTRY UseProgram(GLuint program)
+{
+ EVENT("(GLuint program = %u)", program);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::UseProgram>(program);
+
+ if (context->skipValidation() || ValidateUseProgram(context, program))
+ {
+ context->useProgram(program);
+ }
+ }
+}
+
+void GL_APIENTRY ValidateProgram(GLuint program)
+{
+ EVENT("(GLuint program = %u)", program);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ValidateProgram>(program);
+
+ if (context->skipValidation() || ValidateValidateProgram(context, program))
+ {
+ context->validateProgram(program);
+ }
+ }
+}
+
+void GL_APIENTRY VertexAttrib1f(GLuint index, GLfloat x)
+{
+ EVENT("(GLuint index = %u, GLfloat x = %f)", index, x);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::VertexAttrib1f>(index, x);
+
+ if (context->skipValidation() || ValidateVertexAttrib1f(context, index, x))
+ {
+ context->vertexAttrib1f(index, x);
+ }
+ }
+}
+
+void GL_APIENTRY VertexAttrib1fv(GLuint index, const GLfloat *v)
+{
+ EVENT("(GLuint index = %u, const GLfloat *v = 0x%0.8p)", index, v);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::VertexAttrib1fv>(index, v);
+
+ if (context->skipValidation() || ValidateVertexAttrib1fv(context, index, v))
+ {
+ context->vertexAttrib1fv(index, v);
+ }
+ }
+}
+
+void GL_APIENTRY VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
+{
+ EVENT("(GLuint index = %u, GLfloat x = %f, GLfloat y = %f)", index, x, y);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::VertexAttrib2f>(index, x, y);
+
+ if (context->skipValidation() || ValidateVertexAttrib2f(context, index, x, y))
+ {
+ context->vertexAttrib2f(index, x, y);
+ }
+ }
+}
+
+void GL_APIENTRY VertexAttrib2fv(GLuint index, const GLfloat *v)
+{
+ EVENT("(GLuint index = %u, const GLfloat *v = 0x%0.8p)", index, v);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::VertexAttrib2fv>(index, v);
+
+ if (context->skipValidation() || ValidateVertexAttrib2fv(context, index, v))
+ {
+ context->vertexAttrib2fv(index, v);
+ }
+ }
+}
+
+void GL_APIENTRY VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
+{
+ EVENT("(GLuint index = %u, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::VertexAttrib3f>(index, x, y, z);
+
+ if (context->skipValidation() || ValidateVertexAttrib3f(context, index, x, y, z))
+ {
+ context->vertexAttrib3f(index, x, y, z);
+ }
+ }
+}
+
+void GL_APIENTRY VertexAttrib3fv(GLuint index, const GLfloat *v)
+{
+ EVENT("(GLuint index = %u, const GLfloat *v = 0x%0.8p)", index, v);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::VertexAttrib3fv>(index, v);
+
+ if (context->skipValidation() || ValidateVertexAttrib3fv(context, index, v))
+ {
+ context->vertexAttrib3fv(index, v);
+ }
+ }
+}
+
+void GL_APIENTRY VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ EVENT("(GLuint index = %u, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)",
+ index, x, y, z, w);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::VertexAttrib4f>(index, x, y, z, w);
+
+ if (context->skipValidation() || ValidateVertexAttrib4f(context, index, x, y, z, w))
+ {
+ context->vertexAttrib4f(index, x, y, z, w);
+ }
+ }
+}
+
+void GL_APIENTRY VertexAttrib4fv(GLuint index, const GLfloat *v)
+{
+ EVENT("(GLuint index = %u, const GLfloat *v = 0x%0.8p)", index, v);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::VertexAttrib4fv>(index, v);
+
+ if (context->skipValidation() || ValidateVertexAttrib4fv(context, index, v))
+ {
+ context->vertexAttrib4fv(index, v);
+ }
+ }
+}
+
+void GL_APIENTRY VertexAttribPointer(GLuint index,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLsizei stride,
+ const void *pointer)
+{
+ EVENT(
+ "(GLuint index = %u, GLint size = %d, GLenum type = 0x%X, GLboolean normalized = %u, "
+ "GLsizei stride = %d, const void *pointer = 0x%0.8p)",
+ index, size, type, normalized, stride, pointer);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::VertexAttribPointer>(index, size, type, normalized,
+ stride, pointer);
+
+ if (context->skipValidation() ||
+ ValidateVertexAttribPointer(context, index, size, type, normalized, stride, pointer))
+ {
+ context->vertexAttribPointer(index, size, type, normalized, stride, pointer);
+ }
+ }
+}
+
+void GL_APIENTRY Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width,
+ height);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Viewport>(x, y, width, height);
+
+ if (context->skipValidation() || ValidateViewport(context, x, y, width, height))
+ {
+ context->viewport(x, y, width, height);
+ }
+ }
+}
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_autogen.h b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_autogen.h
new file mode 100644
index 0000000000..7735b46fa4
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_autogen.h
@@ -0,0 +1,297 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// entry_points_gles_2_0_autogen.h:
+// Defines the GLES 2.0 entry points.
+
+#ifndef LIBGLESV2_ENTRYPOINTSGLES20_AUTOGEN_H_
+#define LIBGLESV2_ENTRYPOINTSGLES20_AUTOGEN_H_
+
+#include <GLES2/gl2.h>
+#include <export.h>
+
+namespace gl
+{
+ANGLE_EXPORT void GL_APIENTRY ActiveTexture(GLenum texture);
+ANGLE_EXPORT void GL_APIENTRY AttachShader(GLuint program, GLuint shader);
+ANGLE_EXPORT void GL_APIENTRY BindAttribLocation(GLuint program, GLuint index, const GLchar *name);
+ANGLE_EXPORT void GL_APIENTRY BindBuffer(GLenum target, GLuint buffer);
+ANGLE_EXPORT void GL_APIENTRY BindFramebuffer(GLenum target, GLuint framebuffer);
+ANGLE_EXPORT void GL_APIENTRY BindRenderbuffer(GLenum target, GLuint renderbuffer);
+ANGLE_EXPORT void GL_APIENTRY BindTexture(GLenum target, GLuint texture);
+ANGLE_EXPORT void GL_APIENTRY BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+ANGLE_EXPORT void GL_APIENTRY BlendEquation(GLenum mode);
+ANGLE_EXPORT void GL_APIENTRY BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
+ANGLE_EXPORT void GL_APIENTRY BlendFunc(GLenum sfactor, GLenum dfactor);
+ANGLE_EXPORT void GL_APIENTRY BlendFuncSeparate(GLenum sfactorRGB,
+ GLenum dfactorRGB,
+ GLenum sfactorAlpha,
+ GLenum dfactorAlpha);
+ANGLE_EXPORT void GL_APIENTRY BufferData(GLenum target,
+ GLsizeiptr size,
+ const void *data,
+ GLenum usage);
+ANGLE_EXPORT void GL_APIENTRY BufferSubData(GLenum target,
+ GLintptr offset,
+ GLsizeiptr size,
+ const void *data);
+ANGLE_EXPORT GLenum GL_APIENTRY CheckFramebufferStatus(GLenum target);
+ANGLE_EXPORT void GL_APIENTRY Clear(GLbitfield mask);
+ANGLE_EXPORT void GL_APIENTRY ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+ANGLE_EXPORT void GL_APIENTRY ClearDepthf(GLfloat d);
+ANGLE_EXPORT void GL_APIENTRY ClearStencil(GLint s);
+ANGLE_EXPORT void GL_APIENTRY ColorMask(GLboolean red,
+ GLboolean green,
+ GLboolean blue,
+ GLboolean alpha);
+ANGLE_EXPORT void GL_APIENTRY CompileShader(GLuint shader);
+ANGLE_EXPORT void GL_APIENTRY CompressedTexImage2D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ const void *data);
+ANGLE_EXPORT void GL_APIENTRY CompressedTexSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data);
+ANGLE_EXPORT void GL_APIENTRY CopyTexImage2D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border);
+ANGLE_EXPORT void GL_APIENTRY CopyTexSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+ANGLE_EXPORT GLuint GL_APIENTRY CreateProgram();
+ANGLE_EXPORT GLuint GL_APIENTRY CreateShader(GLenum type);
+ANGLE_EXPORT void GL_APIENTRY CullFace(GLenum mode);
+ANGLE_EXPORT void GL_APIENTRY DeleteBuffers(GLsizei n, const GLuint *buffers);
+ANGLE_EXPORT void GL_APIENTRY DeleteFramebuffers(GLsizei n, const GLuint *framebuffers);
+ANGLE_EXPORT void GL_APIENTRY DeleteProgram(GLuint program);
+ANGLE_EXPORT void GL_APIENTRY DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers);
+ANGLE_EXPORT void GL_APIENTRY DeleteShader(GLuint shader);
+ANGLE_EXPORT void GL_APIENTRY DeleteTextures(GLsizei n, const GLuint *textures);
+ANGLE_EXPORT void GL_APIENTRY DepthFunc(GLenum func);
+ANGLE_EXPORT void GL_APIENTRY DepthMask(GLboolean flag);
+ANGLE_EXPORT void GL_APIENTRY DepthRangef(GLfloat n, GLfloat f);
+ANGLE_EXPORT void GL_APIENTRY DetachShader(GLuint program, GLuint shader);
+ANGLE_EXPORT void GL_APIENTRY Disable(GLenum cap);
+ANGLE_EXPORT void GL_APIENTRY DisableVertexAttribArray(GLuint index);
+ANGLE_EXPORT void GL_APIENTRY DrawArrays(GLenum mode, GLint first, GLsizei count);
+ANGLE_EXPORT void GL_APIENTRY DrawElements(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices);
+ANGLE_EXPORT void GL_APIENTRY Enable(GLenum cap);
+ANGLE_EXPORT void GL_APIENTRY EnableVertexAttribArray(GLuint index);
+ANGLE_EXPORT void GL_APIENTRY Finish();
+ANGLE_EXPORT void GL_APIENTRY Flush();
+ANGLE_EXPORT void GL_APIENTRY FramebufferRenderbuffer(GLenum target,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer);
+ANGLE_EXPORT void GL_APIENTRY FramebufferTexture2D(GLenum target,
+ GLenum attachment,
+ GLenum textarget,
+ GLuint texture,
+ GLint level);
+ANGLE_EXPORT void GL_APIENTRY FrontFace(GLenum mode);
+ANGLE_EXPORT void GL_APIENTRY GenBuffers(GLsizei n, GLuint *buffers);
+ANGLE_EXPORT void GL_APIENTRY GenerateMipmap(GLenum target);
+ANGLE_EXPORT void GL_APIENTRY GenFramebuffers(GLsizei n, GLuint *framebuffers);
+ANGLE_EXPORT void GL_APIENTRY GenRenderbuffers(GLsizei n, GLuint *renderbuffers);
+ANGLE_EXPORT void GL_APIENTRY GenTextures(GLsizei n, GLuint *textures);
+ANGLE_EXPORT void GL_APIENTRY GetActiveAttrib(GLuint program,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name);
+ANGLE_EXPORT void GL_APIENTRY GetActiveUniform(GLuint program,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name);
+ANGLE_EXPORT void GL_APIENTRY GetAttachedShaders(GLuint program,
+ GLsizei maxCount,
+ GLsizei *count,
+ GLuint *shaders);
+ANGLE_EXPORT GLint GL_APIENTRY GetAttribLocation(GLuint program, const GLchar *name);
+ANGLE_EXPORT void GL_APIENTRY GetBooleanv(GLenum pname, GLboolean *data);
+ANGLE_EXPORT void GL_APIENTRY GetBufferParameteriv(GLenum target, GLenum pname, GLint *params);
+ANGLE_EXPORT GLenum GL_APIENTRY GetError();
+ANGLE_EXPORT void GL_APIENTRY GetFloatv(GLenum pname, GLfloat *data);
+ANGLE_EXPORT void GL_APIENTRY GetFramebufferAttachmentParameteriv(GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetIntegerv(GLenum pname, GLint *data);
+ANGLE_EXPORT void GL_APIENTRY GetProgramiv(GLuint program, GLenum pname, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetProgramInfoLog(GLuint program,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *infoLog);
+ANGLE_EXPORT void GL_APIENTRY GetRenderbufferParameteriv(GLenum target,
+ GLenum pname,
+ GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetShaderiv(GLuint shader, GLenum pname, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetShaderInfoLog(GLuint shader,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *infoLog);
+ANGLE_EXPORT void GL_APIENTRY GetShaderPrecisionFormat(GLenum shadertype,
+ GLenum precisiontype,
+ GLint *range,
+ GLint *precision);
+ANGLE_EXPORT void GL_APIENTRY GetShaderSource(GLuint shader,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *source);
+ANGLE_EXPORT const GLubyte *GL_APIENTRY GetString(GLenum name);
+ANGLE_EXPORT void GL_APIENTRY GetTexParameterfv(GLenum target, GLenum pname, GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY GetTexParameteriv(GLenum target, GLenum pname, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetUniformfv(GLuint program, GLint location, GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY GetUniformiv(GLuint program, GLint location, GLint *params);
+ANGLE_EXPORT GLint GL_APIENTRY GetUniformLocation(GLuint program, const GLchar *name);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribPointerv(GLuint index, GLenum pname, void **pointer);
+ANGLE_EXPORT void GL_APIENTRY Hint(GLenum target, GLenum mode);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsBuffer(GLuint buffer);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsEnabled(GLenum cap);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsFramebuffer(GLuint framebuffer);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsProgram(GLuint program);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsRenderbuffer(GLuint renderbuffer);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsShader(GLuint shader);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsTexture(GLuint texture);
+ANGLE_EXPORT void GL_APIENTRY LineWidth(GLfloat width);
+ANGLE_EXPORT void GL_APIENTRY LinkProgram(GLuint program);
+ANGLE_EXPORT void GL_APIENTRY PixelStorei(GLenum pname, GLint param);
+ANGLE_EXPORT void GL_APIENTRY PolygonOffset(GLfloat factor, GLfloat units);
+ANGLE_EXPORT void GL_APIENTRY ReadPixels(GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ void *pixels);
+ANGLE_EXPORT void GL_APIENTRY ReleaseShaderCompiler();
+ANGLE_EXPORT void GL_APIENTRY RenderbufferStorage(GLenum target,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+ANGLE_EXPORT void GL_APIENTRY SampleCoverage(GLfloat value, GLboolean invert);
+ANGLE_EXPORT void GL_APIENTRY Scissor(GLint x, GLint y, GLsizei width, GLsizei height);
+ANGLE_EXPORT void GL_APIENTRY ShaderBinary(GLsizei count,
+ const GLuint *shaders,
+ GLenum binaryformat,
+ const void *binary,
+ GLsizei length);
+ANGLE_EXPORT void GL_APIENTRY ShaderSource(GLuint shader,
+ GLsizei count,
+ const GLchar *const *string,
+ const GLint *length);
+ANGLE_EXPORT void GL_APIENTRY StencilFunc(GLenum func, GLint ref, GLuint mask);
+ANGLE_EXPORT void GL_APIENTRY StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
+ANGLE_EXPORT void GL_APIENTRY StencilMask(GLuint mask);
+ANGLE_EXPORT void GL_APIENTRY StencilMaskSeparate(GLenum face, GLuint mask);
+ANGLE_EXPORT void GL_APIENTRY StencilOp(GLenum fail, GLenum zfail, GLenum zpass);
+ANGLE_EXPORT void GL_APIENTRY StencilOpSeparate(GLenum face,
+ GLenum sfail,
+ GLenum dpfail,
+ GLenum dppass);
+ANGLE_EXPORT void GL_APIENTRY TexImage2D(GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+ANGLE_EXPORT void GL_APIENTRY TexParameterf(GLenum target, GLenum pname, GLfloat param);
+ANGLE_EXPORT void GL_APIENTRY TexParameterfv(GLenum target, GLenum pname, const GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY TexParameteri(GLenum target, GLenum pname, GLint param);
+ANGLE_EXPORT void GL_APIENTRY TexParameteriv(GLenum target, GLenum pname, const GLint *params);
+ANGLE_EXPORT void GL_APIENTRY TexSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+ANGLE_EXPORT void GL_APIENTRY Uniform1f(GLint location, GLfloat v0);
+ANGLE_EXPORT void GL_APIENTRY Uniform1fv(GLint location, GLsizei count, const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY Uniform1i(GLint location, GLint v0);
+ANGLE_EXPORT void GL_APIENTRY Uniform1iv(GLint location, GLsizei count, const GLint *value);
+ANGLE_EXPORT void GL_APIENTRY Uniform2f(GLint location, GLfloat v0, GLfloat v1);
+ANGLE_EXPORT void GL_APIENTRY Uniform2fv(GLint location, GLsizei count, const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY Uniform2i(GLint location, GLint v0, GLint v1);
+ANGLE_EXPORT void GL_APIENTRY Uniform2iv(GLint location, GLsizei count, const GLint *value);
+ANGLE_EXPORT void GL_APIENTRY Uniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+ANGLE_EXPORT void GL_APIENTRY Uniform3fv(GLint location, GLsizei count, const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY Uniform3i(GLint location, GLint v0, GLint v1, GLint v2);
+ANGLE_EXPORT void GL_APIENTRY Uniform3iv(GLint location, GLsizei count, const GLint *value);
+ANGLE_EXPORT void GL_APIENTRY
+Uniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+ANGLE_EXPORT void GL_APIENTRY Uniform4fv(GLint location, GLsizei count, const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY Uniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+ANGLE_EXPORT void GL_APIENTRY Uniform4iv(GLint location, GLsizei count, const GLint *value);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY UseProgram(GLuint program);
+ANGLE_EXPORT void GL_APIENTRY ValidateProgram(GLuint program);
+ANGLE_EXPORT void GL_APIENTRY VertexAttrib1f(GLuint index, GLfloat x);
+ANGLE_EXPORT void GL_APIENTRY VertexAttrib1fv(GLuint index, const GLfloat *v);
+ANGLE_EXPORT void GL_APIENTRY VertexAttrib2f(GLuint index, GLfloat x, GLfloat y);
+ANGLE_EXPORT void GL_APIENTRY VertexAttrib2fv(GLuint index, const GLfloat *v);
+ANGLE_EXPORT void GL_APIENTRY VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z);
+ANGLE_EXPORT void GL_APIENTRY VertexAttrib3fv(GLuint index, const GLfloat *v);
+ANGLE_EXPORT void GL_APIENTRY
+VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ANGLE_EXPORT void GL_APIENTRY VertexAttrib4fv(GLuint index, const GLfloat *v);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribPointer(GLuint index,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLsizei stride,
+ const void *pointer);
+ANGLE_EXPORT void GL_APIENTRY Viewport(GLint x, GLint y, GLsizei width, GLsizei height);
+} // namespace gl
+
+#endif // LIBGLESV2_ENTRYPOINTSGLES20_AUTOGEN_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.cpp
index 7df6fcb0cd..d4459ec287 100644
--- a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.cpp
@@ -12,14 +12,20 @@
#include "libANGLE/Buffer.h"
#include "libANGLE/Context.h"
#include "libANGLE/Error.h"
+#include "libANGLE/ErrorStrings.h"
#include "libANGLE/Fence.h"
#include "libANGLE/Framebuffer.h"
-#include "libANGLE/Shader.h"
#include "libANGLE/Query.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/Thread.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/queryconversions.h"
+#include "libANGLE/queryutils.h"
#include "libANGLE/validationES.h"
#include "libANGLE/validationES2.h"
#include "libANGLE/validationES3.h"
+#include "libANGLE/validationES31.h"
#include "common/debug.h"
#include "common/utilities.h"
@@ -27,6 +33,19 @@
namespace gl
{
+namespace
+{
+
+void SetRobustLengthParam(GLsizei *length, GLsizei value)
+{
+ if (length)
+ {
+ *length = value;
+ }
+}
+
+} // anonymous namespace
+
void GL_APIENTRY GenQueriesEXT(GLsizei n, GLuint *ids)
{
EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
@@ -34,15 +53,12 @@ void GL_APIENTRY GenQueriesEXT(GLsizei n, GLuint *ids)
Context *context = GetValidGlobalContext();
if (context)
{
- if (!ValidateGenQueriesEXT(context, n, ids))
+ if (!context->skipValidation() && !ValidateGenQueriesEXT(context, n, ids))
{
return;
}
- for (GLsizei i = 0; i < n; i++)
- {
- ids[i] = context->createQuery();
- }
+ context->genQueries(n, ids);
}
}
@@ -53,15 +69,12 @@ void GL_APIENTRY DeleteQueriesEXT(GLsizei n, const GLuint *ids)
Context *context = GetValidGlobalContext();
if (context)
{
- if (!ValidateDeleteQueriesEXT(context, n, ids))
+ if (!context->skipValidation() && !ValidateDeleteQueriesEXT(context, n, ids))
{
return;
}
- for (int i = 0; i < n; i++)
- {
- context->deleteQuery(ids[i]);
- }
+ context->deleteQueries(n, ids);
}
}
@@ -72,7 +85,12 @@ GLboolean GL_APIENTRY IsQueryEXT(GLuint id)
Context *context = GetValidGlobalContext();
if (context)
{
- return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE;
+ if (!context->skipValidation() && !ValidateIsQueryEXT(context, id))
+ {
+ return GL_FALSE;
+ }
+
+ return context->isQuery(id);
}
return GL_FALSE;
@@ -85,17 +103,12 @@ void GL_APIENTRY BeginQueryEXT(GLenum target, GLuint id)
Context *context = GetValidGlobalContext();
if (context)
{
- if (!ValidateBeginQueryEXT(context, target, id))
+ if (!context->skipValidation() && !ValidateBeginQueryEXT(context, target, id))
{
return;
}
- Error error = context->beginQuery(target, id);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
+ context->beginQuery(target, id);
}
}
@@ -106,17 +119,12 @@ void GL_APIENTRY EndQueryEXT(GLenum target)
Context *context = GetValidGlobalContext();
if (context)
{
- if (!ValidateEndQueryEXT(context, target))
+ if (!context->skipValidation() && !ValidateEndQueryEXT(context, target))
{
return;
}
- Error error = context->endQuery(target);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
+ context->endQuery(target);
}
}
@@ -127,17 +135,12 @@ void GL_APIENTRY QueryCounterEXT(GLuint id, GLenum target)
Context *context = GetValidGlobalContext();
if (context)
{
- if (!ValidateQueryCounterEXT(context, id, target))
+ if (!context->skipValidation() && !ValidateQueryCounterEXT(context, id, target))
{
return;
}
- Error error = context->queryCounter(id, target);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
+ context->queryCounter(id, target);
}
}
@@ -170,12 +173,7 @@ void GL_APIENTRY GetQueryObjectivEXT(GLuint id, GLenum pname, GLint *params)
return;
}
- Error error = context->getQueryObjectiv(id, pname, params);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
+ context->getQueryObjectiv(id, pname, params);
}
}
@@ -191,12 +189,7 @@ void GL_APIENTRY GetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params)
return;
}
- Error error = context->getQueryObjectuiv(id, pname, params);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
+ context->getQueryObjectuiv(id, pname, params);
}
}
@@ -212,12 +205,7 @@ void GL_APIENTRY GetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64 *params)
return;
}
- Error error = context->getQueryObjecti64v(id, pname, params);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
+ context->getQueryObjecti64v(id, pname, params);
}
}
@@ -233,12 +221,7 @@ void GL_APIENTRY GetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64 *param
return;
}
- Error error = context->getQueryObjectui64v(id, pname, params);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
+ context->getQueryObjectui64v(id, pname, params);
}
}
@@ -251,7 +234,7 @@ void GL_APIENTRY DeleteFencesNV(GLsizei n, const GLuint *fences)
{
if (n < 0)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return;
}
@@ -278,43 +261,34 @@ void GL_APIENTRY DrawArraysInstancedANGLE(GLenum mode,
return;
}
- Error error = context->drawArraysInstanced(mode, first, count, primcount);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
+ context->drawArraysInstanced(mode, first, count, primcount);
}
}
void GL_APIENTRY DrawElementsInstancedANGLE(GLenum mode,
GLsizei count,
GLenum type,
- const GLvoid *indices,
+ const void *indices,
GLsizei primcount)
{
EVENT(
- "(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = "
+ "(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void* indices = "
"0x%0.8p, GLsizei primcount = %d)",
mode, count, type, indices, primcount);
Context *context = GetValidGlobalContext();
if (context)
{
- IndexRange indexRange;
- if (!ValidateDrawElementsInstancedANGLE(context, mode, count, type, indices, primcount,
- &indexRange))
- {
- return;
- }
+ context->gatherParams<EntryPoint::DrawElementsInstancedANGLE>(mode, count, type, indices,
+ primcount);
- Error error =
- context->drawElementsInstanced(mode, count, type, indices, primcount, indexRange);
- if (error.isError())
+ if (!context->skipValidation() &&
+ !ValidateDrawElementsInstancedANGLE(context, mode, count, type, indices, primcount))
{
- context->recordError(error);
return;
}
+
+ context->drawElementsInstanced(mode, count, type, indices, primcount);
}
}
@@ -327,19 +301,19 @@ void GL_APIENTRY FinishFenceNV(GLuint fence)
{
FenceNV *fenceObject = context->getFenceNV(fence);
- if (fenceObject == NULL)
+ if (fenceObject == nullptr)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return;
}
if (fenceObject->isSet() != GL_TRUE)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return;
}
- fenceObject->finish();
+ context->handleError(fenceObject->finish());
}
}
@@ -352,7 +326,7 @@ void GL_APIENTRY GenFencesNV(GLsizei n, GLuint *fences)
{
if (n < 0)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return;
}
@@ -365,39 +339,41 @@ void GL_APIENTRY GenFencesNV(GLsizei n, GLuint *fences)
void GL_APIENTRY GetFenceivNV(GLuint fence, GLenum pname, GLint *params)
{
- EVENT("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname, params);
+ EVENT("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname,
+ params);
Context *context = GetValidGlobalContext();
if (context)
{
FenceNV *fenceObject = context->getFenceNV(fence);
- if (fenceObject == NULL)
+ if (fenceObject == nullptr)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return;
}
if (fenceObject->isSet() != GL_TRUE)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return;
}
switch (pname)
{
- case GL_FENCE_STATUS_NV:
+ case GL_FENCE_STATUS_NV:
{
// GL_NV_fence spec:
- // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV
- // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
+ // Once the status of a fence has been finished (via FinishFenceNV) or tested and
+ // the returned status is TRUE (via either TestFenceNV or GetFenceivNV querying the
+ // FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
GLboolean status = GL_TRUE;
if (fenceObject->getStatus() != GL_TRUE)
{
Error error = fenceObject->test(&status);
if (error.isError())
{
- context->recordError(error);
+ context->handleError(error);
return;
}
}
@@ -405,15 +381,15 @@ void GL_APIENTRY GetFenceivNV(GLuint fence, GLenum pname, GLint *params)
break;
}
- case GL_FENCE_CONDITION_NV:
+ case GL_FENCE_CONDITION_NV:
{
*params = static_cast<GLint>(fenceObject->getCondition());
break;
}
- default:
+ default:
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return;
}
}
@@ -434,17 +410,22 @@ GLenum GL_APIENTRY GetGraphicsResetStatusEXT(void)
return GL_NO_ERROR;
}
-void GL_APIENTRY GetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
+void GL_APIENTRY GetTranslatedShaderSourceANGLE(GLuint shader,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLchar *source)
{
- EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
- shader, bufsize, length, source);
+ EVENT(
+ "(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = "
+ "0x%0.8p)",
+ shader, bufsize, length, source);
Context *context = GetValidGlobalContext();
if (context)
{
if (bufsize < 0)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return;
}
@@ -452,18 +433,20 @@ void GL_APIENTRY GetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize,
if (!shaderObject)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return;
}
- shaderObject->getTranslatedSourceWithDebugInfo(bufsize, length, source);
+ shaderObject->getTranslatedSourceWithDebugInfo(context, bufsize, length, source);
}
}
-void GL_APIENTRY GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
+void GL_APIENTRY GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat *params)
{
- EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = 0x%0.8p)",
- program, location, bufSize, params);
+ EVENT(
+ "(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = "
+ "0x%0.8p)",
+ program, location, bufSize, params);
Context *context = GetValidGlobalContext();
if (context)
@@ -476,14 +459,15 @@ void GL_APIENTRY GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSiz
Program *programObject = context->getProgram(program);
ASSERT(programObject);
- programObject->getUniformfv(location, params);
+ programObject->getUniformfv(context, location, params);
}
}
-void GL_APIENTRY GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
+void GL_APIENTRY GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint *params)
{
- EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)",
- program, location, bufSize, params);
+ EVENT(
+ "(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)",
+ program, location, bufSize, params);
Context *context = GetValidGlobalContext();
if (context)
@@ -496,7 +480,7 @@ void GL_APIENTRY GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSiz
Program *programObject = context->getProgram(program);
ASSERT(programObject);
- programObject->getUniformiv(location, params);
+ programObject->getUniformiv(context, location, params);
}
}
@@ -509,26 +493,33 @@ GLboolean GL_APIENTRY IsFenceNV(GLuint fence)
{
FenceNV *fenceObject = context->getFenceNV(fence);
- if (fenceObject == NULL)
+ if (fenceObject == nullptr)
{
return GL_FALSE;
}
// GL_NV_fence spec:
- // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence.
+ // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an
+ // existing fence.
return fenceObject->isSet();
}
return GL_FALSE;
}
-void GL_APIENTRY ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
- GLenum format, GLenum type, GLsizei bufSize,
- GLvoid *data)
+void GL_APIENTRY ReadnPixelsEXT(GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *data)
{
- EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
- "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = 0x%0.8p)",
- x, y, width, height, format, type, bufSize, data);
+ EVENT(
+ "(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
+ "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, void *data = 0x%0.8p)",
+ x, y, width, height, format, type, bufSize, data);
Context *context = GetValidGlobalContext();
if (context)
@@ -543,27 +534,28 @@ void GL_APIENTRY ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
}
}
-void GL_APIENTRY RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+void GL_APIENTRY RenderbufferStorageMultisampleANGLE(GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
{
- EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
+ EVENT(
+ "(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width "
+ "= %d, GLsizei height = %d)",
target, samples, internalformat, width, height);
Context *context = GetValidGlobalContext();
if (context)
{
- if (!ValidateRenderbufferStorageParametersANGLE(context, target, samples, internalformat,
- width, height))
+ if (!context->skipValidation() &&
+ !ValidateRenderbufferStorageMultisampleANGLE(context, target, samples, internalformat,
+ width, height))
{
return;
}
- Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer();
- Error error = renderbuffer->setStorageMultisample(samples, internalformat, width, height);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
+ context->renderbufferStorageMultisample(target, samples, internalformat, width, height);
}
}
@@ -576,22 +568,22 @@ void GL_APIENTRY SetFenceNV(GLuint fence, GLenum condition)
{
if (condition != GL_ALL_COMPLETED_NV)
{
- context->recordError(Error(GL_INVALID_ENUM));
+ context->handleError(InvalidEnum());
return;
}
FenceNV *fenceObject = context->getFenceNV(fence);
- if (fenceObject == NULL)
+ if (fenceObject == nullptr)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return;
}
Error error = fenceObject->set(condition);
if (error.isError())
{
- context->recordError(error);
+ context->handleError(error);
return;
}
}
@@ -606,15 +598,15 @@ GLboolean GL_APIENTRY TestFenceNV(GLuint fence)
{
FenceNV *fenceObject = context->getFenceNV(fence);
- if (fenceObject == NULL)
+ if (fenceObject == nullptr)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return GL_TRUE;
}
if (fenceObject->isSet() != GL_TRUE)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return GL_TRUE;
}
@@ -622,7 +614,7 @@ GLboolean GL_APIENTRY TestFenceNV(GLuint fence)
Error error = fenceObject->test(&result);
if (error.isError())
{
- context->recordError(error);
+ context->handleError(error);
return GL_TRUE;
}
@@ -632,41 +624,38 @@ GLboolean GL_APIENTRY TestFenceNV(GLuint fence)
return GL_TRUE;
}
-void GL_APIENTRY TexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+void GL_APIENTRY
+TexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
{
- EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
- target, levels, internalformat, width, height);
+ EVENT(
+ "(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = "
+ "%d, GLsizei height = %d)",
+ target, levels, internalformat, width, height);
Context *context = GetValidGlobalContext();
if (context)
{
if (!context->getExtensions().textureStorage)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->handleError(InvalidOperation());
return;
}
- if (context->getClientVersion() < 3 &&
- !ValidateES2TexStorageParameters(context, target, levels, internalformat, width, height))
+ if (context->getClientMajorVersion() < 3 &&
+ !ValidateES2TexStorageParameters(context, target, levels, internalformat, width,
+ height))
{
return;
}
- if (context->getClientVersion() >= 3 &&
+ if (context->getClientMajorVersion() >= 3 &&
!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width,
height, 1))
{
return;
}
- Extents size(width, height, 1);
- Texture *texture = context->getTargetTexture(target);
- Error error = texture->setStorage(target, levels, internalformat, size);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
+ context->texStorage2D(target, levels, internalformat, width, height);
}
}
@@ -677,9 +666,15 @@ void GL_APIENTRY VertexAttribDivisorANGLE(GLuint index, GLuint divisor)
Context *context = GetValidGlobalContext();
if (context)
{
+ if (!context->getExtensions().instancedArrays)
+ {
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
+ return;
+ }
+
if (index >= MAX_VERTEX_ATTRIBS)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->handleError(InvalidValue());
return;
}
@@ -687,28 +682,41 @@ void GL_APIENTRY VertexAttribDivisorANGLE(GLuint index, GLuint divisor)
{
if (index == 0 && divisor != 0)
{
- const char *errorMessage = "The current context doesn't support setting a non-zero divisor on the attribute with index zero. "
- "Please reorder the attributes in your vertex shader so that attribute zero can have a zero divisor.";
- context->recordError(Error(GL_INVALID_OPERATION, errorMessage));
+ const char *errorMessage =
+ "The current context doesn't support setting a non-zero divisor on the "
+ "attribute with index zero. "
+ "Please reorder the attributes in your vertex shader so that attribute zero "
+ "can have a zero divisor.";
+ context->handleError(InvalidOperation() << errorMessage);
- // We also output an error message to the debugger window if tracing is active, so that developers can see the error message.
- ERR("%s", errorMessage);
+ // We also output an error message to the debugger window if tracing is active, so
+ // that developers can see the error message.
+ ERR() << errorMessage;
return;
}
}
- context->setVertexAttribDivisor(index, divisor);
+ context->vertexAttribDivisor(index, divisor);
}
}
-void GL_APIENTRY BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLbitfield mask, GLenum filter)
+void GL_APIENTRY BlitFramebufferANGLE(GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter)
{
- EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
- "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
- "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
- srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+ EVENT(
+ "(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
+ "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
+ "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
+ srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
Context *context = GetValidGlobalContext();
if (context)
@@ -725,9 +733,12 @@ void GL_APIENTRY BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLi
}
}
-void GL_APIENTRY DiscardFramebufferEXT(GLenum target, GLsizei numAttachments, const GLenum *attachments)
+void GL_APIENTRY DiscardFramebufferEXT(GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments)
{
- EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, attachments = 0x%0.8p)", target, numAttachments, attachments);
+ EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, attachments = 0x%0.8p)", target,
+ numAttachments, attachments);
Context *context = GetValidGlobalContext();
if (context)
@@ -742,64 +753,68 @@ void GL_APIENTRY DiscardFramebufferEXT(GLenum target, GLsizei numAttachments, co
}
}
-void GL_APIENTRY TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
- GLint border, GLenum format, GLenum type, const GLvoid* pixels)
+void GL_APIENTRY TexImage3DOES(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
- "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
- "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)",
- target, level, internalformat, width, height, depth, border, format, type, pixels);
+ EVENT(
+ "(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
+ "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
+ "GLenum format = 0x%X, GLenum type = 0x%x, const void* pixels = 0x%0.8p)",
+ target, level, internalformat, width, height, depth, border, format, type, pixels);
- UNIMPLEMENTED(); // FIXME
+ UNIMPLEMENTED(); // FIXME
}
-void GL_APIENTRY GetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary)
+void GL_APIENTRY GetProgramBinaryOES(GLuint program,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary)
{
- EVENT("(GLenum program = 0x%X, bufSize = %d, length = 0x%0.8p, binaryFormat = 0x%0.8p, binary = 0x%0.8p)",
- program, bufSize, length, binaryFormat, binary);
+ EVENT(
+ "(GLenum program = 0x%X, bufSize = %d, length = 0x%0.8p, binaryFormat = 0x%0.8p, binary = "
+ "0x%0.8p)",
+ program, bufSize, length, binaryFormat, binary);
Context *context = GetValidGlobalContext();
if (context)
{
- if (!ValidateGetProgramBinaryOES(context, program, bufSize, length, binaryFormat, binary))
+ if (!context->skipValidation() &&
+ !ValidateGetProgramBinaryOES(context, program, bufSize, length, binaryFormat, binary))
{
return;
}
- Program *programObject = context->getProgram(program);
- ASSERT(programObject != nullptr);
-
- Error error = programObject->saveBinary(binaryFormat, binary, bufSize, length);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
+ context->getProgramBinary(program, bufSize, length, binaryFormat, binary);
}
}
-void GL_APIENTRY ProgramBinaryOES(GLuint program, GLenum binaryFormat, const void *binary, GLint length)
+void GL_APIENTRY ProgramBinaryOES(GLuint program,
+ GLenum binaryFormat,
+ const void *binary,
+ GLint length)
{
- EVENT("(GLenum program = 0x%X, binaryFormat = 0x%x, binary = 0x%0.8p, length = %d)",
- program, binaryFormat, binary, length);
+ EVENT("(GLenum program = 0x%X, binaryFormat = 0x%x, binary = 0x%0.8p, length = %d)", program,
+ binaryFormat, binary, length);
Context *context = GetValidGlobalContext();
if (context)
{
- if (!ValidateProgramBinaryOES(context, program, binaryFormat, binary, length))
+ if (!context->skipValidation() &&
+ !ValidateProgramBinaryOES(context, program, binaryFormat, binary, length))
{
return;
}
- Program *programObject = context->getProgram(program);
- ASSERT(programObject != nullptr);
-
- Error error = programObject->loadBinary(binaryFormat, binary, length);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
+ context->programBinary(program, binaryFormat, binary, length);
}
}
@@ -819,35 +834,23 @@ void GL_APIENTRY DrawBuffersEXT(GLsizei n, const GLenum *bufs)
}
}
-void GL_APIENTRY GetBufferPointervOES(GLenum target, GLenum pname, void** params)
+void GL_APIENTRY GetBufferPointervOES(GLenum target, GLenum pname, void **params)
{
- EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params);
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, void** params = 0x%0.8p)", target, pname,
+ params);
Context *context = GetValidGlobalContext();
if (context)
{
- if (!ValidBufferTarget(context, target))
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
+ BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
- if (pname != GL_BUFFER_MAP_POINTER)
+ if (!context->skipValidation() &&
+ !ValidateGetBufferPointervOES(context, targetPacked, pname, params))
{
- context->recordError(Error(GL_INVALID_ENUM));
return;
}
- Buffer *buffer = context->getState().getTargetBuffer(target);
-
- if (!buffer || !buffer->isMapped())
- {
- *params = NULL;
- }
- else
- {
- *params = buffer->getMapPointer();
- }
+ context->getBufferPointerv(targetPacked, pname, params);
}
}
@@ -858,43 +861,17 @@ void *GL_APIENTRY MapBufferOES(GLenum target, GLenum access)
Context *context = GetValidGlobalContext();
if (context)
{
- if (!ValidBufferTarget(context, target))
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return NULL;
- }
-
- Buffer *buffer = context->getState().getTargetBuffer(target);
+ BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
- if (buffer == NULL)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return NULL;
- }
-
- if (access != GL_WRITE_ONLY_OES)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return NULL;
- }
-
- if (buffer->isMapped())
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return NULL;
- }
-
- Error error = buffer->map(access);
- if (error.isError())
+ if (!context->skipValidation() && !ValidateMapBufferOES(context, targetPacked, access))
{
- context->recordError(error);
- return NULL;
+ return nullptr;
}
- return buffer->getMapPointer();
+ return context->mapBuffer(targetPacked, access);
}
- return NULL;
+ return nullptr;
}
GLboolean GL_APIENTRY UnmapBufferOES(GLenum target)
@@ -904,174 +881,63 @@ GLboolean GL_APIENTRY UnmapBufferOES(GLenum target)
Context *context = GetValidGlobalContext();
if (context)
{
- if (!ValidBufferTarget(context, target))
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return GL_FALSE;
- }
-
- Buffer *buffer = context->getState().getTargetBuffer(target);
-
- if (buffer == NULL || !buffer->isMapped())
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return GL_FALSE;
- }
+ BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
- GLboolean result;
- Error error = buffer->unmap(&result);
- if (error.isError())
+ if (!context->skipValidation() && !ValidateUnmapBufferOES(context, targetPacked))
{
- context->recordError(error);
return GL_FALSE;
}
- return result;
+ return context->unmapBuffer(targetPacked);
}
return GL_FALSE;
}
-void *GL_APIENTRY MapBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
+void *GL_APIENTRY MapBufferRangeEXT(GLenum target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access)
{
- EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)",
- target, offset, length, access);
+ EVENT(
+ "(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = "
+ "0x%X)",
+ target, offset, length, access);
Context *context = GetValidGlobalContext();
if (context)
{
- if (!ValidBufferTarget(context, target))
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return NULL;
- }
-
- if (offset < 0 || length < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return NULL;
- }
-
- Buffer *buffer = context->getState().getTargetBuffer(target);
-
- if (buffer == NULL)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return NULL;
- }
-
- // Check for buffer overflow
- size_t offsetSize = static_cast<size_t>(offset);
- size_t lengthSize = static_cast<size_t>(length);
-
- if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) ||
- offsetSize + lengthSize > static_cast<size_t>(buffer->getSize()))
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return NULL;
- }
-
- // Check for invalid bits in the mask
- GLbitfield allAccessBits = GL_MAP_READ_BIT |
- GL_MAP_WRITE_BIT |
- GL_MAP_INVALIDATE_RANGE_BIT |
- GL_MAP_INVALIDATE_BUFFER_BIT |
- GL_MAP_FLUSH_EXPLICIT_BIT |
- GL_MAP_UNSYNCHRONIZED_BIT;
-
- if (access & ~(allAccessBits))
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return NULL;
- }
-
- if (length == 0 || buffer->isMapped())
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return NULL;
- }
-
- // Check for invalid bit combinations
- if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return NULL;
- }
-
- GLbitfield writeOnlyBits = GL_MAP_INVALIDATE_RANGE_BIT |
- GL_MAP_INVALIDATE_BUFFER_BIT |
- GL_MAP_UNSYNCHRONIZED_BIT;
-
- if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return NULL;
- }
-
- if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return NULL;
- }
+ BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
- Error error = buffer->mapRange(offset, length, access);
- if (error.isError())
+ if (!context->skipValidation() &&
+ !ValidateMapBufferRangeEXT(context, targetPacked, offset, length, access))
{
- context->recordError(error);
- return NULL;
+ return nullptr;
}
- return buffer->getMapPointer();
+ return context->mapBufferRange(targetPacked, offset, length, access);
}
- return NULL;
+ return nullptr;
}
void GL_APIENTRY FlushMappedBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length)
{
- EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length);
+ EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset,
+ length);
Context *context = GetValidGlobalContext();
if (context)
{
- if (offset < 0 || length < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- if (!ValidBufferTarget(context, target))
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- Buffer *buffer = context->getState().getTargetBuffer(target);
-
- if (buffer == NULL)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- // Check for buffer overflow
- size_t offsetSize = static_cast<size_t>(offset);
- size_t lengthSize = static_cast<size_t>(length);
+ BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
- if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) ||
- offsetSize + lengthSize > static_cast<size_t>(buffer->getMapLength()))
+ if (!context->skipValidation() &&
+ !ValidateFlushMappedBufferRangeEXT(context, targetPacked, offset, length))
{
- context->recordError(Error(GL_INVALID_VALUE));
return;
}
- // We do not currently support a non-trivial implementation of FlushMappedBufferRange
+ context->flushMappedBufferRange(targetPacked, offset, length);
}
}
@@ -1087,7 +953,7 @@ void GL_APIENTRY InsertEventMarkerEXT(GLsizei length, const char *marker)
{
// The debug marker calls should not set error state
// However, it seems reasonable to set an error state if the extension is not enabled
- context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ context->handleError(InvalidOperation() << "Extension not enabled");
return;
}
@@ -1112,7 +978,7 @@ void GL_APIENTRY PushGroupMarkerEXT(GLsizei length, const char *marker)
{
// The debug marker calls should not set error state
// However, it seems reasonable to set an error state if the extension is not enabled
- context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ context->handleError(InvalidOperation() << "Extension not enabled");
return;
}
@@ -1146,7 +1012,7 @@ void GL_APIENTRY PopGroupMarkerEXT()
{
// The debug marker calls should not set error state
// However, it seems reasonable to set an error state if the extension is not enabled
- context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled"));
+ context->handleError(InvalidOperation() << "Extension not enabled");
return;
}
@@ -1161,18 +1027,17 @@ ANGLE_EXPORT void GL_APIENTRY EGLImageTargetTexture2DOES(GLenum target, GLeglIma
Context *context = GetValidGlobalContext();
if (context)
{
- egl::Display *display = egl::GetGlobalDisplay();
egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
- if (!ValidateEGLImageTargetTexture2DOES(context, display, target, imageObject))
+ if (!ValidateEGLImageTargetTexture2DOES(context, target, imageObject))
{
return;
}
Texture *texture = context->getTargetTexture(target);
- Error error = texture->setEGLImageTarget(target, imageObject);
+ Error error = texture->setEGLImageTarget(context, target, imageObject);
if (error.isError())
{
- context->recordError(error);
+ context->handleError(error);
return;
}
}
@@ -1186,18 +1051,17 @@ ANGLE_EXPORT void GL_APIENTRY EGLImageTargetRenderbufferStorageOES(GLenum target
Context *context = GetValidGlobalContext();
if (context)
{
- egl::Display *display = egl::GetGlobalDisplay();
egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
- if (!ValidateEGLImageTargetRenderbufferStorageOES(context, display, target, imageObject))
+ if (!ValidateEGLImageTargetRenderbufferStorageOES(context, target, imageObject))
{
return;
}
- Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer();
- Error error = renderbuffer->setStorageEGLImageTarget(imageObject);
+ Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
+ Error error = renderbuffer->setStorageEGLImageTarget(context, imageObject);
if (error.isError())
{
- context->recordError(error);
+ context->handleError(error);
return;
}
}
@@ -1210,7 +1074,7 @@ void GL_APIENTRY BindVertexArrayOES(GLuint array)
Context *context = GetValidGlobalContext();
if (context)
{
- if (!ValidateBindVertexArrayOES(context, array))
+ if (!context->skipValidation() && !ValidateBindVertexArrayOES(context, array))
{
return;
}
@@ -1226,18 +1090,12 @@ void GL_APIENTRY DeleteVertexArraysOES(GLsizei n, const GLuint *arrays)
Context *context = GetValidGlobalContext();
if (context)
{
- if (!ValidateDeleteVertexArraysOES(context, n))
+ if (!context->skipValidation() && !ValidateDeleteVertexArraysOES(context, n, arrays))
{
return;
}
- for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
- {
- if (arrays[arrayIndex] != 0)
- {
- context->deleteVertexArray(arrays[arrayIndex]);
- }
- }
+ context->deleteVertexArrays(n, arrays);
}
}
@@ -1248,15 +1106,12 @@ void GL_APIENTRY GenVertexArraysOES(GLsizei n, GLuint *arrays)
Context *context = GetValidGlobalContext();
if (context)
{
- if (!ValidateGenVertexArraysOES(context, n))
+ if (!context->skipValidation() && !ValidateGenVertexArraysOES(context, n, arrays))
{
return;
}
- for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
- {
- arrays[arrayIndex] = context->createVertexArray();
- }
+ context->genVertexArrays(n, arrays);
}
}
@@ -1267,19 +1122,12 @@ GLboolean GL_APIENTRY IsVertexArrayOES(GLuint array)
Context *context = GetValidGlobalContext();
if (context)
{
- if (!ValidateIsVertexArrayOES(context))
- {
- return GL_FALSE;
- }
-
- if (array == 0)
+ if (!context->skipValidation() && !ValidateIsVertexArrayOES(context, array))
{
return GL_FALSE;
}
- VertexArray *vao = context->getVertexArray(array);
-
- return (vao != nullptr ? GL_TRUE : GL_FALSE);
+ return context->isVertexArray(array);
}
return GL_FALSE;
@@ -1305,9 +1153,7 @@ void GL_APIENTRY DebugMessageControlKHR(GLenum source,
return;
}
- std::vector<GLuint> idVector(ids, ids + count);
- context->getState().getDebug().setMessageControl(
- source, type, severity, std::move(idVector), (enabled != GL_FALSE));
+ context->debugMessageControl(source, type, severity, count, ids, enabled);
}
}
@@ -1331,8 +1177,7 @@ void GL_APIENTRY DebugMessageInsertKHR(GLenum source,
return;
}
- std::string msg(buf, (length > 0) ? static_cast<size_t>(length) : strlen(buf));
- context->getState().getDebug().insertMessage(source, type, id, severity, std::move(msg));
+ context->debugMessageInsert(source, type, id, severity, length, buf);
}
}
@@ -1349,7 +1194,7 @@ void GL_APIENTRY DebugMessageCallbackKHR(GLDEBUGPROCKHR callback, const void *us
return;
}
- context->getState().getDebug().setCallback(callback, userParam);
+ context->debugMessageCallback(callback, userParam);
}
}
@@ -1377,8 +1222,8 @@ GLuint GL_APIENTRY GetDebugMessageLogKHR(GLuint count,
return 0;
}
- return static_cast<GLuint>(context->getState().getDebug().getMessages(
- count, bufSize, sources, types, ids, severities, lengths, messageLog));
+ return context->getDebugMessageLog(count, bufSize, sources, types, ids, severities, lengths,
+ messageLog);
}
return 0;
@@ -1400,7 +1245,7 @@ void GL_APIENTRY PushDebugGroupKHR(GLenum source, GLuint id, GLsizei length, con
}
std::string msg(message, (length > 0) ? static_cast<size_t>(length) : strlen(message));
- context->getState().getDebug().pushGroup(source, id, std::move(msg));
+ context->pushDebugGroup(source, id, length, message);
}
}
@@ -1416,7 +1261,7 @@ void GL_APIENTRY PopDebugGroupKHR(void)
return;
}
- context->getState().getDebug().popGroup();
+ context->popDebugGroup();
}
}
@@ -1435,11 +1280,7 @@ void GL_APIENTRY ObjectLabelKHR(GLenum identifier, GLuint name, GLsizei length,
return;
}
- LabeledObject *object = context->getLabeledObject(identifier, name);
- ASSERT(object != nullptr);
-
- std::string lbl(label, (length > 0) ? static_cast<size_t>(length) : strlen(label));
- object->setLabel(lbl);
+ context->objectLabel(identifier, name, length, label);
}
}
@@ -1459,14 +1300,7 @@ GetObjectLabelKHR(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *leng
return;
}
- LabeledObject *object = context->getLabeledObject(identifier, name);
- ASSERT(object != nullptr);
-
- const std::string &objectLabel = object->getLabel();
- size_t writeLength = std::min(static_cast<size_t>(bufSize) - 1, objectLabel.length());
- std::copy(objectLabel.begin(), objectLabel.begin() + writeLength, label);
- label[writeLength] = '\0';
- *length = static_cast<GLsizei>(writeLength);
+ context->getObjectLabel(identifier, name, bufSize, length, label);
}
}
@@ -1483,11 +1317,7 @@ void GL_APIENTRY ObjectPtrLabelKHR(const void *ptr, GLsizei length, const GLchar
return;
}
- LabeledObject *object = context->getLabeledObjectFromPtr(ptr);
- ASSERT(object != nullptr);
-
- std::string lbl(label, (length > 0) ? static_cast<size_t>(length) : strlen(label));
- object->setLabel(lbl);
+ context->objectPtrLabel(ptr, length, label);
}
}
@@ -1509,14 +1339,7 @@ void GL_APIENTRY GetObjectPtrLabelKHR(const void *ptr,
return;
}
- LabeledObject *object = context->getLabeledObjectFromPtr(ptr);
- ASSERT(object != nullptr);
-
- const std::string &objectLabel = object->getLabel();
- size_t writeLength = std::min(static_cast<size_t>(bufSize) - 1, objectLabel.length());
- std::copy(objectLabel.begin(), objectLabel.begin() + writeLength, label);
- label[writeLength] = '\0';
- *length = static_cast<GLsizei>(writeLength);
+ context->getObjectPtrLabel(ptr, bufSize, length, label);
}
}
@@ -1535,4 +1358,2201 @@ void GL_APIENTRY GetPointervKHR(GLenum pname, void **params)
context->getPointerv(pname, params);
}
}
+
+ANGLE_EXPORT void GL_APIENTRY BindUniformLocationCHROMIUM(GLuint program,
+ GLint location,
+ const GLchar *name)
+{
+ EVENT("(GLuint program = %u, GLint location = %d, const GLchar *name = 0x%0.8p)", program,
+ location, name);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateBindUniformLocationCHROMIUM(context, program, location, name))
+ {
+ return;
+ }
+
+ context->bindUniformLocation(program, location, name);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY CoverageModulationCHROMIUM(GLenum components)
+{
+ EVENT("(GLenum components = %u)", components);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateCoverageModulationCHROMIUM(context, components))
+ {
+ return;
+ }
+ context->setCoverageModulation(components);
+ }
+}
+
+// CHROMIUM_path_rendering
+ANGLE_EXPORT void GL_APIENTRY MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat *matrix)
+{
+ EVENT("(GLenum matrixMode = %u)", matrixMode);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() && !ValidateMatrix(context, matrixMode, matrix))
+ {
+ return;
+ }
+ context->loadPathRenderingMatrix(matrixMode, matrix);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY MatrixLoadIdentityCHROMIUM(GLenum matrixMode)
+{
+ EVENT("(GLenum matrixMode = %u)", matrixMode);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() && !ValidateMatrixMode(context, matrixMode))
+ {
+ return;
+ }
+ context->loadPathRenderingIdentityMatrix(matrixMode);
+ }
+}
+
+ANGLE_EXPORT GLuint GL_APIENTRY GenPathsCHROMIUM(GLsizei range)
+{
+ EVENT("(GLsizei range = %d)", range);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() && !ValidateGenPaths(context, range))
+ {
+ return 0;
+ }
+ return context->createPaths(range);
+ }
+ return 0;
+}
+
+ANGLE_EXPORT void GL_APIENTRY DeletePathsCHROMIUM(GLuint first, GLsizei range)
+{
+ EVENT("(GLuint first = %u, GLsizei range = %d)", first, range);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() && !ValidateDeletePaths(context, first, range))
+ {
+ return;
+ }
+ context->deletePaths(first, range);
+ }
+}
+
+ANGLE_EXPORT GLboolean GL_APIENTRY IsPathCHROMIUM(GLuint path)
+{
+ EVENT("(GLuint path = %u)", path);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() && !ValidateIsPath(context))
+ {
+ return GL_FALSE;
+ }
+ return context->hasPathData(path);
+ }
+ return GL_FALSE;
+}
+
+ANGLE_EXPORT void GL_APIENTRY PathCommandsCHROMIUM(GLuint path,
+ GLsizei numCommands,
+ const GLubyte *commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const void *coords)
+{
+ EVENT(
+ "(GLuint path = %u, GLsizei numCommands = %d, commands = %p, "
+ "GLsizei numCoords = %d, GLenum coordType = %u, void* coords = %p)",
+ path, numCommands, commands, numCoords, coordType, coords);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation())
+ {
+ if (!ValidatePathCommands(context, path, numCommands, commands, numCoords, coordType,
+ coords))
+ {
+ return;
+ }
+ }
+ context->setPathCommands(path, numCommands, commands, numCoords, coordType, coords);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY PathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value)
+{
+ EVENT("(GLuint path = %u, GLenum pname = %u, GLfloat value = %f)", path, pname, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() && !ValidateSetPathParameter(context, path, pname, value))
+ {
+ return;
+ }
+ context->setPathParameterf(path, pname, value);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY PathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value)
+{
+ PathParameterfCHROMIUM(path, pname, static_cast<GLfloat>(value));
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetPathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat *value)
+{
+ EVENT("(GLuint path = %u, GLenum pname = %u)", path, pname);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() && !ValidateGetPathParameter(context, path, pname, value))
+ {
+ return;
+ }
+ context->getPathParameterfv(path, pname, value);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetPathParameteriCHROMIUM(GLuint path, GLenum pname, GLint *value)
+{
+ GLfloat val = 0.0f;
+ GetPathParameterfCHROMIUM(path, pname, value != nullptr ? &val : nullptr);
+ if (value)
+ *value = static_cast<GLint>(val);
+}
+
+ANGLE_EXPORT void GL_APIENTRY PathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask)
+{
+ EVENT("(GLenum func = %u, GLint ref = %d, GLuint mask = %u)", func, ref, mask);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() && !ValidatePathStencilFunc(context, func, ref, mask))
+ {
+ return;
+ }
+ context->setPathStencilFunc(func, ref, mask);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY StencilFillPathCHROMIUM(GLuint path, GLenum fillMode, GLuint mask)
+{
+ EVENT("(GLuint path = %u, GLenum fillMode = %u, GLuint mask = %u)", path, fillMode, mask);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() && !ValidateStencilFillPath(context, path, fillMode, mask))
+ {
+ return;
+ }
+ context->stencilFillPath(path, fillMode, mask);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY StencilStrokePathCHROMIUM(GLuint path, GLint reference, GLuint mask)
+{
+ EVENT("(GLuint path = %u, GLint ference = %d, GLuint mask = %u)", path, reference, mask);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() &&
+ !ValidateStencilStrokePath(context, path, reference, mask))
+ {
+ return;
+ }
+ context->stencilStrokePath(path, reference, mask);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY CoverFillPathCHROMIUM(GLuint path, GLenum coverMode)
+{
+ EVENT("(GLuint path = %u, GLenum coverMode = %u)", path, coverMode);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() && !ValidateCoverPath(context, path, coverMode))
+ {
+ return;
+ }
+ context->coverFillPath(path, coverMode);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY CoverStrokePathCHROMIUM(GLuint path, GLenum coverMode)
+{
+ EVENT("(GLuint path = %u, GLenum coverMode = %u)", path, coverMode);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() && !ValidateCoverPath(context, path, coverMode))
+ {
+ return;
+ }
+ context->coverStrokePath(path, coverMode);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY StencilThenCoverFillPathCHROMIUM(GLuint path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode)
+{
+ EVENT("(GLuint path = %u, GLenum fillMode = %u, GLuint mask = %u, GLenum coverMode = %u)", path,
+ fillMode, mask, coverMode);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() &&
+ !ValidateStencilThenCoverFillPath(context, path, fillMode, mask, coverMode))
+ {
+ return;
+ }
+ context->stencilThenCoverFillPath(path, fillMode, mask, coverMode);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY StencilThenCoverStrokePathCHROMIUM(GLuint path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode)
+{
+ EVENT("(GLuint path = %u, GLint reference = %d, GLuint mask = %u, GLenum coverMode = %u)", path,
+ reference, mask, coverMode);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() &&
+ !ValidateStencilThenCoverStrokePath(context, path, reference, mask, coverMode))
+ {
+ return;
+ }
+ context->stencilThenCoverStrokePath(path, reference, mask, coverMode);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY CoverFillPathInstancedCHROMIUM(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ EVENT(
+ "(GLsizei numPaths = %d, GLenum pathNameType = %u, const void *paths = %p "
+ "GLuint pathBase = %u, GLenum coverMode = %u, GLenum transformType = %u "
+ "const GLfloat *transformValues = %p)",
+ numPaths, pathNameType, paths, pathBase, coverMode, transformType, transformValues);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() &&
+ !ValidateCoverFillPathInstanced(context, numPaths, pathNameType, paths, pathBase,
+ coverMode, transformType, transformValues))
+ {
+ return;
+ }
+ context->coverFillPathInstanced(numPaths, pathNameType, paths, pathBase, coverMode,
+ transformType, transformValues);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY CoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ EVENT(
+ "(GLsizei numPaths = %d, GLenum pathNameType = %u, const void *paths = %p "
+ "GLuint pathBase = %u, GLenum coverMode = %u, GLenum transformType = %u "
+ "const GLfloat *transformValues = %p)",
+ numPaths, pathNameType, paths, pathBase, coverMode, transformType, transformValues);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() &&
+ !ValidateCoverStrokePathInstanced(context, numPaths, pathNameType, paths, pathBase,
+ coverMode, transformType, transformValues))
+ {
+ return;
+ }
+ context->coverStrokePathInstanced(numPaths, pathNameType, paths, pathBase, coverMode,
+ transformType, transformValues);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY StencilStrokePathInstancedCHROMIUM(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ EVENT(
+ "(GLsizei numPaths = %u, GLenum pathNameType = %u, const void *paths = %p "
+ "GLuint pathBase = %u, GLint reference = %d GLuint mask = %u GLenum transformType = %u "
+ "const GLfloat *transformValues = %p)",
+ numPaths, pathNameType, paths, pathBase, reference, mask, transformType, transformValues);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() &&
+ !ValidateStencilStrokePathInstanced(context, numPaths, pathNameType, paths, pathBase,
+ reference, mask, transformType, transformValues))
+ {
+ return;
+ }
+ context->stencilStrokePathInstanced(numPaths, pathNameType, paths, pathBase, reference,
+ mask, transformType, transformValues);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY StencilFillPathInstancedCHROMIUM(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ EVENT(
+ "(GLsizei numPaths = %u, GLenum pathNameType = %u const void *paths = %p "
+ "GLuint pathBase = %u, GLenum fillMode = %u, GLuint mask = %u, GLenum transformType = %u "
+ "const GLfloat *transformValues = %p)",
+ numPaths, pathNameType, paths, pathBase, fillMode, mask, transformType, transformValues);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() &&
+ !ValidateStencilFillPathInstanced(context, numPaths, pathNameType, paths, pathBase,
+ fillMode, mask, transformType, transformValues))
+ {
+ return;
+ }
+ context->stencilFillPathInstanced(numPaths, pathNameType, paths, pathBase, fillMode, mask,
+ transformType, transformValues);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY
+StencilThenCoverFillPathInstancedCHROMIUM(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ EVENT(
+ "(GLsizei numPaths = %u, GLenum pathNameType = %u const void *paths = %p "
+ "GLuint pathBase = %u, GLenum coverMode = %u, GLuint mask = %u, GLenum transformType = %u "
+ "const GLfloat *transformValues = %p)",
+ numPaths, pathNameType, paths, pathBase, coverMode, mask, transformType, transformValues);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() &&
+ !ValidateStencilThenCoverFillPathInstanced(context, numPaths, pathNameType, paths,
+ pathBase, fillMode, mask, coverMode,
+ transformType, transformValues))
+ {
+ return;
+ }
+ context->stencilThenCoverFillPathInstanced(numPaths, pathNameType, paths, pathBase,
+ fillMode, mask, coverMode, transformType,
+ transformValues);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY
+StencilThenCoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ EVENT(
+ "(GLsizei numPaths = %u, GLenum pathNameType = %u, const void *paths = %p "
+ "GLuint pathBase = %u GLenum coverMode = %u GLint reference = %d GLuint mask = %u GLenum "
+ "transformType = %u "
+ "const GLfloat *transformValues = %p)",
+ numPaths, pathNameType, paths, pathBase, coverMode, reference, mask, transformType,
+ transformValues);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() &&
+ !ValidateStencilThenCoverStrokePathInstanced(context, numPaths, pathNameType, paths,
+ pathBase, reference, mask, coverMode,
+ transformType, transformValues))
+ {
+ return;
+ }
+ context->stencilThenCoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
+ reference, mask, coverMode, transformType,
+ transformValues);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY BindFragmentInputLocationCHROMIUM(GLuint program,
+ GLint location,
+ const GLchar *name)
+{
+ EVENT("(GLuint program = %u, GLint location = %d, const GLchar *name = %p)", program, location,
+ name);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() &&
+ !ValidateBindFragmentInputLocation(context, program, location, name))
+ {
+ return;
+ }
+ context->bindFragmentInputLocation(program, location, name);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY ProgramPathFragmentInputGenCHROMIUM(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location %d, GLenum genMode = %u, GLint components = %d, "
+ "const GLfloat * coeffs = %p)",
+ program, location, genMode, components, coeffs);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() &&
+ !ValidateProgramPathFragmentInputGen(context, program, location, genMode, components,
+ coeffs))
+ {
+ return;
+ }
+ context->programPathFragmentInputGen(program, location, genMode, components, coeffs);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY CopyTextureCHROMIUM(GLuint sourceId,
+ GLint sourceLevel,
+ GLenum destTarget,
+ GLuint destId,
+ GLint destLevel,
+ GLint internalFormat,
+ GLenum destType,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha)
+{
+ EVENT(
+ "(GLuint sourceId = %u, GLint sourceLevel = %d, GLenum destTarget = 0x%X, GLuint destId = "
+ "%u, GLint destLevel = %d, GLint internalFormat = 0x%X, GLenum destType = "
+ "0x%X, GLboolean unpackFlipY = %u, GLboolean unpackPremultiplyAlpha = %u, GLboolean "
+ "unpackUnmultiplyAlpha = %u)",
+ sourceId, sourceLevel, destTarget, destId, destLevel, internalFormat, destType, unpackFlipY,
+ unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() &&
+ !ValidateCopyTextureCHROMIUM(context, sourceId, sourceLevel, destTarget, destId,
+ destLevel, internalFormat, destType, unpackFlipY,
+ unpackPremultiplyAlpha, unpackUnmultiplyAlpha))
+ {
+ return;
+ }
+
+ context->copyTextureCHROMIUM(sourceId, sourceLevel, destTarget, destId, destLevel,
+ internalFormat, destType, unpackFlipY, unpackPremultiplyAlpha,
+ unpackUnmultiplyAlpha);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY CopySubTextureCHROMIUM(GLuint sourceId,
+ GLint sourceLevel,
+ GLenum destTarget,
+ GLuint destId,
+ GLint destLevel,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha)
+{
+ EVENT(
+ "(GLuint sourceId = %u, GLint sourceLevel = %d, GLenum destTarget = 0x%X, GLuint destId = "
+ "%u, GLint destLevel = %d, GLint xoffset = "
+ "%d, GLint yoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = "
+ "%d, GLboolean unpackPremultiplyAlpha = %u, GLboolean unpackUnmultiplyAlpha = %u)",
+ sourceId, sourceLevel, destTarget, destId, destLevel, xoffset, yoffset, x, y, width, height,
+ unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() &&
+ !ValidateCopySubTextureCHROMIUM(
+ context, sourceId, sourceLevel, destTarget, destId, destLevel, xoffset, yoffset, x,
+ y, width, height, unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha))
+ {
+ return;
+ }
+
+ context->copySubTextureCHROMIUM(sourceId, sourceLevel, destTarget, destId, destLevel,
+ xoffset, yoffset, x, y, width, height, unpackFlipY,
+ unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY CompressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId)
+{
+ EVENT("(GLuint sourceId = %u, GLuint destId = %u)", sourceId, destId);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() &&
+ !ValidateCompressedCopyTextureCHROMIUM(context, sourceId, destId))
+ {
+ return;
+ }
+
+ context->compressedCopyTextureCHROMIUM(sourceId, destId);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY RequestExtensionANGLE(const GLchar *name)
+{
+ EVENT("(const GLchar *name = %p)", name);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() && !ValidateRequestExtensionANGLE(context, name))
+ {
+ return;
+ }
+
+ context->requestExtension(name);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetBooleanvRobustANGLE(GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLboolean *params)
+{
+ EVENT(
+ "(GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLboolean* params "
+ "= 0x%0.8p)",
+ pname, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
+ {
+ return;
+ }
+
+ context->getBooleanv(pname, params);
+ SetRobustLengthParam(length, numParams);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetBufferParameterivRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname,
+ params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
+
+ GLsizei numParams = 0;
+ if (!ValidateGetBufferParameterivRobustANGLE(context, targetPacked, pname, bufSize,
+ &numParams, params))
+ {
+ return;
+ }
+
+ Buffer *buffer = context->getGLState().getTargetBuffer(targetPacked);
+ QueryBufferParameteriv(buffer, pname, params);
+ SetRobustLengthParam(length, numParams);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetFloatvRobustANGLE(GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params)
+{
+ EVENT(
+ "(GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLfloat* params = "
+ "0x%0.8p)",
+ pname, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
+ {
+ return;
+ }
+
+ context->getFloatv(pname, params);
+ SetRobustLengthParam(length, numParams);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetFramebufferAttachmentParameterivRobustANGLE(GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = "
+ "%d, GLsizei* length = 0x%0.8p, GLint* params = 0x%0.8p)",
+ target, attachment, pname, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei numParams = 0;
+ if (!ValidateGetFramebufferAttachmentParameterivRobustANGLE(context, target, attachment,
+ pname, bufSize, &numParams))
+ {
+ return;
+ }
+
+ const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
+ QueryFramebufferAttachmentParameteriv(framebuffer, attachment, pname, params);
+ SetRobustLengthParam(length, numParams);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetIntegervRobustANGLE(GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *data)
+{
+ EVENT(
+ "(GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLint* params = "
+ "0x%0.8p)",
+ pname, bufSize, length, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
+ {
+ return;
+ }
+
+ context->getIntegerv(pname, data);
+ SetRobustLengthParam(length, numParams);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetProgramivRobustANGLE(GLuint program,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ EVENT(
+ "(GLuint program = %d, GLenum pname = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
+ "GLint* params = 0x%0.8p)",
+ program, pname, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei numParams = 0;
+ if (!ValidateGetProgramivRobustANGLE(context, program, pname, bufSize, &numParams))
+ {
+ return;
+ }
+
+ Program *programObject = context->getProgram(program);
+ QueryProgramiv(context, programObject, pname, params);
+ SetRobustLengthParam(length, numParams);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetRenderbufferParameterivRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+ "0x%0.8p, GLint* params = 0x%0.8p)",
+ target, pname, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei numParams = 0;
+ if (!ValidateGetRenderbufferParameterivRobustANGLE(context, target, pname, bufSize,
+ &numParams, params))
+ {
+ return;
+ }
+
+ Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
+ QueryRenderbufferiv(context, renderbuffer, pname, params);
+ SetRobustLengthParam(length, numParams);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY
+GetShaderivRobustANGLE(GLuint shader, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params)
+{
+ EVENT(
+ "(GLuint shader = %d, GLenum pname = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
+ "GLint* params = 0x%0.8p)",
+ shader, pname, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei numParams = 0;
+ if (!ValidateGetShaderivRobustANGLE(context, shader, pname, bufSize, &numParams, params))
+ {
+ return;
+ }
+
+ Shader *shaderObject = context->getShader(shader);
+ QueryShaderiv(context, shaderObject, pname, params);
+ SetRobustLengthParam(length, numParams);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetTexParameterfvRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+ "0x%0.8p, GLfloat* params = 0x%0.8p)",
+ target, pname, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei numParams = 0;
+ if (!ValidateGetTexParameterfvRobustANGLE(context, target, pname, bufSize, &numParams,
+ params))
+ {
+ return;
+ }
+
+ Texture *texture = context->getTargetTexture(target);
+ QueryTexParameterfv(texture, pname, params);
+ SetRobustLengthParam(length, numParams);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetTexParameterivRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+ "0x%0.8p, GLfloat* params = 0x%0.8p)",
+ target, pname, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei numParams = 0;
+ if (!ValidateGetTexParameterivRobustANGLE(context, target, pname, bufSize, &numParams,
+ params))
+ {
+ return;
+ }
+
+ Texture *texture = context->getTargetTexture(target);
+ QueryTexParameteriv(texture, pname, params);
+ SetRobustLengthParam(length, numParams);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetUniformfvRobustANGLE(GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params)
+{
+ EVENT(
+ "(GLuint program = %d, GLint location = %d, GLsizei bufsize = %d, GLsizei* length = "
+ "0x%0.8p, GLfloat* params = 0x%0.8p)",
+ program, location, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei writeLength = 0;
+ if (!ValidateGetUniformfvRobustANGLE(context, program, location, bufSize, &writeLength,
+ params))
+ {
+ return;
+ }
+
+ Program *programObject = context->getProgram(program);
+ ASSERT(programObject);
+
+ programObject->getUniformfv(context, location, params);
+ SetRobustLengthParam(length, writeLength);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetUniformivRobustANGLE(GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ EVENT(
+ "(GLuint program = %d, GLint location = %d, GLsizei bufsize = %d, GLsizei* length = "
+ "0x%0.8p, GLint* params = 0x%0.8p)",
+ program, location, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei writeLength = 0;
+ if (!ValidateGetUniformivRobustANGLE(context, program, location, bufSize, &writeLength,
+ params))
+ {
+ return;
+ }
+
+ Program *programObject = context->getProgram(program);
+ ASSERT(programObject);
+
+ programObject->getUniformiv(context, location, params);
+ SetRobustLengthParam(length, writeLength);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribfvRobustANGLE(GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params)
+{
+ EVENT(
+ "(GLuint index = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
+ "GLfloat* params = 0x%0.8p)",
+ index, pname, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei writeLength = 0;
+ if (!ValidateGetVertexAttribfvRobustANGLE(context, index, pname, bufSize, &writeLength,
+ params))
+ {
+ return;
+ }
+
+ context->getVertexAttribfv(index, pname, params);
+ SetRobustLengthParam(length, writeLength);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribivRobustANGLE(GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ EVENT(
+ "(GLuint index = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
+ "GLint* params = 0x%0.8p)",
+ index, pname, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei writeLength = 0;
+ if (!ValidateGetVertexAttribivRobustANGLE(context, index, pname, bufSize, &writeLength,
+ params))
+ {
+ return;
+ }
+
+ context->getVertexAttribiv(index, pname, params);
+ SetRobustLengthParam(length, writeLength);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribPointervRobustANGLE(GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ void **pointer)
+{
+ EVENT(
+ "(GLuint index = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
+ "void** pointer = 0x%0.8p)",
+ index, pname, bufSize, length, pointer);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei writeLength = 0;
+ if (!ValidateGetVertexAttribPointervRobustANGLE(context, index, pname, bufSize,
+ &writeLength, pointer))
+ {
+ return;
+ }
+
+ context->getVertexAttribPointerv(index, pname, pointer);
+ SetRobustLengthParam(length, writeLength);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY ReadPixelsRobustANGLE(GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *pixels)
+{
+ EVENT(
+ "(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
+ "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+ "0x%0.8p, GLsizei* columns = 0x%0.8p, GLsizei* rows = 0x%0.8p, void* pixels = 0x%0.8p)",
+ x, y, width, height, format, type, bufSize, length, columns, rows, pixels);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei writeLength = 0;
+ GLsizei writeColumns = 0;
+ GLsizei writeRows = 0;
+ if (!ValidateReadPixelsRobustANGLE(context, x, y, width, height, format, type, bufSize,
+ &writeLength, &writeColumns, &writeRows, pixels))
+ {
+ return;
+ }
+
+ context->readPixels(x, y, width, height, format, type, pixels);
+
+ SetRobustLengthParam(length, writeLength);
+ SetRobustLengthParam(columns, writeColumns);
+ SetRobustLengthParam(rows, writeRows);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY TexImage2DRobustANGLE(GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, "
+ "GLsizei height = %d, GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, GLsizei "
+ "bufSize = %d, const void* pixels = 0x%0.8p)",
+ target, level, internalformat, width, height, border, format, type, bufSize, pixels);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateTexImage2DRobust(context, target, level, internalformat, width, height, border,
+ format, type, bufSize, pixels))
+ {
+ return;
+ }
+
+ context->texImage2D(target, level, internalformat, width, height, border, format, type,
+ pixels);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY TexParameterfvRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLfloat *params)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLfloat* params = "
+ "0x%0.8p)",
+ target, pname, bufSize, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateTexParameterfvRobustANGLE(context, target, pname, bufSize, params))
+ {
+ return;
+ }
+
+ Texture *texture = context->getTargetTexture(target);
+ SetTexParameterfv(context, texture, pname, params);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY TexParameterivRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *params)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLfloat* params = "
+ "0x%0.8p)",
+ target, pname, bufSize, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateTexParameterivRobustANGLE(context, target, pname, bufSize, params))
+ {
+ return;
+ }
+
+ Texture *texture = context->getTargetTexture(target);
+ SetTexParameteriv(context, texture, pname, params);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY TexSubImage2DRobustANGLE(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+ "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
+ "GLsizei bufsize = %d, const void* pixels = 0x%0.8p)",
+ target, level, xoffset, yoffset, width, height, format, type, bufSize, pixels);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateTexSubImage2DRobustANGLE(context, target, level, xoffset, yoffset, width,
+ height, format, type, bufSize, pixels))
+ {
+ return;
+ }
+
+ context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type,
+ pixels);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY TexImage3DRobustANGLE(GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, "
+ "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLenum format = 0x%X, "
+ "GLenum type = 0x%X, GLsizei bufsize = %d, const void* pixels = 0x%0.8p)",
+ target, level, internalformat, width, height, depth, border, format, type, bufSize, pixels);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateTexImage3DRobustANGLE(context, target, level, internalformat, width, height,
+ depth, border, format, type, bufSize, pixels))
+ {
+ return;
+ }
+
+ context->texImage3D(target, level, internalformat, width, height, depth, border, format,
+ type, pixels);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY TexSubImage3DRobustANGLE(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+ "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
+ "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufsize = %d, const void* pixels = "
+ "0x%0.8p)",
+ target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, bufSize,
+ pixels);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateTexSubImage3DRobustANGLE(context, target, level, xoffset, yoffset, zoffset,
+ width, height, depth, format, type, bufSize, pixels))
+ {
+ return;
+ }
+
+ context->texSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth,
+ format, type, pixels);
+ }
+}
+
+void GL_APIENTRY CompressedTexImage2DRobustANGLE(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const GLvoid *data)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = "
+ "%d, "
+ "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, GLsizei dataSize = %d, "
+ "const GLvoid* data = 0x%0.8p)",
+ target, level, internalformat, width, height, border, imageSize, dataSize, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() &&
+ !ValidateCompressedTexImage2DRobustANGLE(context, target, level, internalformat, width,
+ height, border, imageSize, dataSize, data))
+ {
+ return;
+ }
+
+ context->compressedTexImage2D(target, level, internalformat, width, height, border,
+ imageSize, data);
+ }
}
+
+void GL_APIENTRY CompressedTexSubImage2DRobustANGLE(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const GLvoid *data)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+ "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
+ "GLsizei imageSize = %d, GLsizei dataSize = %d, const GLvoid* data = 0x%0.8p)",
+ target, level, xoffset, yoffset, width, height, format, imageSize, dataSize, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() && !ValidateCompressedTexSubImage2DRobustANGLE(
+ context, target, level, xoffset, yoffset, width,
+ height, format, imageSize, dataSize, data))
+ {
+ return;
+ }
+
+ context->compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format,
+ imageSize, data);
+ }
+}
+
+void GL_APIENTRY CompressedTexImage3DRobustANGLE(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const GLvoid *data)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = "
+ "%d, "
+ "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, "
+ "GLsizei dataSize = %d, const GLvoid* data = 0x%0.8p)",
+ target, level, internalformat, width, height, depth, border, imageSize, dataSize, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() && !ValidateCompressedTexImage3DRobustANGLE(
+ context, target, level, internalformat, width, height,
+ depth, border, imageSize, dataSize, data))
+ {
+ return;
+ }
+
+ context->compressedTexImage3D(target, level, internalformat, width, height, depth, border,
+ imageSize, data);
+ }
+}
+
+void GL_APIENTRY CompressedTexSubImage3DRobustANGLE(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const GLvoid *data)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+ "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
+ "GLenum format = 0x%X, GLsizei imageSize = %d, GLsizei dataSize = %d, const GLvoid* data = "
+ "0x%0.8p)",
+ target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, dataSize,
+ data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() &&
+ !ValidateCompressedTexSubImage3DRobustANGLE(context, target, level, xoffset, yoffset,
+ zoffset, width, height, depth, format,
+ imageSize, dataSize, data))
+ {
+ return;
+ }
+
+ context->compressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height,
+ depth, format, imageSize, data);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY
+GetQueryivRobustANGLE(GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+ "0x%0.8p, GLint* params = 0x%0.8p)",
+ target, pname, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei numParams = 0;
+ if (!ValidateGetQueryivRobustANGLE(context, target, pname, bufSize, &numParams, params))
+ {
+ return;
+ }
+
+ context->getQueryiv(target, pname, params);
+ SetRobustLengthParam(length, numParams);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjectuivRobustANGLE(GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params)
+{
+ EVENT(
+ "(GLuint id = %u, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
+ "GLint* params = 0x%0.8p)",
+ id, pname, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei numParams = 0;
+ if (!ValidateGetQueryObjectuivRobustANGLE(context, id, pname, bufSize, &numParams, params))
+ {
+ return;
+ }
+
+ context->getQueryObjectuiv(id, pname, params);
+ SetRobustLengthParam(length, numParams);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetBufferPointervRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ void **params)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+ "0x%0.8p, void** params = 0x%0.8p)",
+ target, pname, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
+
+ GLsizei numParams = 0;
+ if (!ValidateGetBufferPointervRobustANGLE(context, targetPacked, pname, bufSize, &numParams,
+ params))
+ {
+ return;
+ }
+
+ context->getBufferPointerv(targetPacked, pname, params);
+ SetRobustLengthParam(length, numParams);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY
+GetIntegeri_vRobustANGLE(GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, GLint *data)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLuint index = %u, GLsizei bufsize = %d, GLsizei* length = "
+ "0x%0.8p, GLint* data = 0x%0.8p)",
+ target, index, bufSize, length, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei numParams = 0;
+ if (!ValidateGetIntegeri_vRobustANGLE(context, target, index, bufSize, &numParams, data))
+ {
+ return;
+ }
+
+ context->getIntegeri_v(target, index, data);
+ SetRobustLengthParam(length, numParams);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetInternalformativRobustANGLE(GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize "
+ "= %d, GLsizei* length = 0x%0.8p, GLint* params = 0x%0.8p)",
+ target, internalformat, pname, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei numParams = 0;
+ if (!ValidateGetInternalFormativRobustANGLE(context, target, internalformat, pname, bufSize,
+ &numParams, params))
+ {
+ return;
+ }
+
+ const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
+ QueryInternalFormativ(formatCaps, pname, bufSize, params);
+ SetRobustLengthParam(length, numParams);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIivRobustANGLE(GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ EVENT(
+ "(GLuint index = %u, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
+ "GLint* params = 0x%0.8p)",
+ index, pname, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei writeLength = 0;
+ if (!ValidateGetVertexAttribIivRobustANGLE(context, index, pname, bufSize, &writeLength,
+ params))
+ {
+ return;
+ }
+
+ context->getVertexAttribIiv(index, pname, params);
+ SetRobustLengthParam(length, writeLength);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIuivRobustANGLE(GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params)
+{
+ EVENT(
+ "(GLuint index = %u, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
+ "GLuint* params = 0x%0.8p)",
+ index, pname, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei writeLength = 0;
+ if (!ValidateGetVertexAttribIuivRobustANGLE(context, index, pname, bufSize, &writeLength,
+ params))
+ {
+ return;
+ }
+
+ context->getVertexAttribIuiv(index, pname, params);
+ SetRobustLengthParam(length, writeLength);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetUniformuivRobustANGLE(GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLsizei bufsize = %d, GLsizei* length = "
+ "0x%0.8p, GLuint* params = 0x%0.8p)",
+ program, location, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei writeLength = 0;
+ if (!ValidateGetUniformuivRobustANGLE(context, program, location, bufSize, &writeLength,
+ params))
+ {
+ return;
+ }
+
+ Program *programObject = context->getProgram(program);
+ ASSERT(programObject);
+
+ programObject->getUniformuiv(context, location, params);
+ SetRobustLengthParam(length, writeLength);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetActiveUniformBlockivRobustANGLE(GLuint program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ EVENT(
+ "(GLuint program = %u, GLuint uniformBlockIndex = %u, GLenum pname = 0x%X, GLsizei bufsize "
+ "= %d, GLsizei* length = 0x%0.8p, GLint* params = 0x%0.8p)",
+ program, uniformBlockIndex, pname, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei writeLength = 0;
+ if (!ValidateGetActiveUniformBlockivRobustANGLE(context, program, uniformBlockIndex, pname,
+ bufSize, &writeLength, params))
+ {
+ return;
+ }
+
+ const Program *programObject = context->getProgram(program);
+ QueryActiveUniformBlockiv(programObject, uniformBlockIndex, pname, params);
+ SetRobustLengthParam(length, writeLength);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetInteger64vRobustANGLE(GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *data)
+{
+ EVENT(
+ "(GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLint64* params = "
+ "0x%0.8p)",
+ pname, bufSize, length, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
+ {
+ return;
+ }
+
+ if (nativeType == GL_INT_64_ANGLEX)
+ {
+ context->getInteger64v(pname, data);
+ }
+ else
+ {
+ CastStateValues(context, nativeType, pname, numParams, data);
+ }
+ SetRobustLengthParam(length, numParams);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetInteger64i_vRobustANGLE(GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *data)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLuint index = %u, GLsizei bufsize = %d, GLsizei* length = "
+ "0x%0.8p, GLint64* data = 0x%0.8p)",
+ target, index, bufSize, length, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei numParams = 0;
+ if (!ValidateGetInteger64i_vRobustANGLE(context, target, index, bufSize, &numParams, data))
+ {
+ return;
+ }
+
+ context->getInteger64i_v(target, index, data);
+ SetRobustLengthParam(length, numParams);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetBufferParameteri64vRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64* params = 0x%0.8p)", target, pname,
+ bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
+
+ GLsizei numParams = 0;
+ if (!ValidateGetBufferParameteri64vRobustANGLE(context, targetPacked, pname, bufSize,
+ &numParams, params))
+ {
+ return;
+ }
+
+ Buffer *buffer = context->getGLState().getTargetBuffer(targetPacked);
+ QueryBufferParameteri64v(buffer, pname, params);
+ SetRobustLengthParam(length, numParams);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterivRobustANGLE(GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *param)
+{
+ EVENT(
+ "(GLuint sampler = %u, GLenum pname = 0x%X, GLsizei bufsize = %d, const GLint* params = "
+ "0x%0.8p)",
+ sampler, pname, bufSize, param);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateSamplerParameterivRobustANGLE(context, sampler, pname, bufSize, param))
+ {
+ return;
+ }
+
+ context->samplerParameteriv(sampler, pname, param);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterfvRobustANGLE(GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLfloat *param)
+{
+ EVENT(
+ "(GLuint sampler = %u, GLenum pname = 0x%X, GLsizei bufsize = %d, const GLfloat* params = "
+ "0x%0.8p)",
+ sampler, pname, bufSize, param);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateSamplerParameterfvRobustANGLE(context, sampler, pname, bufSize, param))
+ {
+ return;
+ }
+
+ context->samplerParameterfv(sampler, pname, param);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterivRobustANGLE(GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ EVENT(
+ "(GLuint sampler = %u, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+ "0x%0.8p, GLint* params = 0x%0.8p)",
+ sampler, pname, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei numParams = 0;
+ if (!ValidateGetSamplerParameterivRobustANGLE(context, sampler, pname, bufSize, &numParams,
+ params))
+ {
+ return;
+ }
+
+ context->getSamplerParameteriv(sampler, pname, params);
+ SetRobustLengthParam(length, numParams);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterfvRobustANGLE(GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params)
+{
+ EVENT(
+ "(GLuint sample = %ur, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+ "0x%0.8p, GLfloat* params = 0x%0.8p)",
+ sampler, pname, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei numParams = 0;
+ if (!ValidateGetSamplerParameterfvRobustANGLE(context, sampler, pname, bufSize, &numParams,
+ params))
+ {
+ return;
+ }
+
+ context->getSamplerParameterfv(sampler, pname, params);
+ SetRobustLengthParam(length, numParams);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetFramebufferParameterivRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+ "0x%0.8p, GLint* params = 0x%0.8p)",
+ target, pname, bufSize, length, params);
+ UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetProgramInterfaceivRobustANGLE(GLuint program,
+ GLenum programInterface,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ EVENT(
+ "(GLuint program = %u, GLenum programInterface = 0x%X, GLenum pname = 0x%X, GLsizei "
+ "bufsize = %d, GLsizei* length = 0x%0.8p, GLint* params = 0x%0.8p)",
+ program, programInterface, pname, bufSize, length, params);
+ UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetBooleani_vRobustANGLE(GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLboolean *data)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLuint index = %u, GLsizei bufsize = %d, GLsizei* length = "
+ "0x%0.8p, GLboolean* data = 0x%0.8p)",
+ target, index, bufSize, length, data);
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei numParams = 0;
+ if (!ValidateGetBooleani_vRobustANGLE(context, target, index, bufSize, &numParams, data))
+ {
+ return;
+ }
+
+ context->getBooleani_v(target, index, data);
+ SetRobustLengthParam(length, numParams);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetMultisamplefvRobustANGLE(GLenum pname,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *val)
+{
+ EVENT(
+ "(GLenum pname = 0x%X, GLuint index = %u, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
+ "GLfloat* val = 0x%0.8p)",
+ pname, index, bufSize, length, val);
+ UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetTexLevelParameterivRobustANGLE(GLenum target,
+ GLint level,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLint level = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, "
+ "GLsizei* length = 0x%0.8p, GLint* params = 0x%0.8p)",
+ target, level, pname, bufSize, length, params);
+ UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetTexLevelParameterfvRobustANGLE(GLenum target,
+ GLint level,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLint level = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, "
+ "GLsizei* length = 0x%0.8p, GLfloat* params = 0x%0.8p)",
+ target, level, pname, bufSize, length, params);
+ UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetPointervRobustANGLERobustANGLE(GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ void **params)
+{
+ EVENT(
+ "(GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, void **params = "
+ "0x%0.8p)",
+ pname, bufSize, length, params);
+ UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY ReadnPixelsRobustANGLE(GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *data)
+{
+ EVENT(
+ "(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
+ "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+ "0x%0.8p, GLsizei* columns = 0x%0.8p, GLsizei* rows = 0x%0.8p, void *data = 0x%0.8p)",
+ x, y, width, height, format, type, bufSize, length, columns, rows, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei writeLength = 0;
+ GLsizei writeColumns = 0;
+ GLsizei writeRows = 0;
+ if (!ValidateReadnPixelsRobustANGLE(context, x, y, width, height, format, type, bufSize,
+ &writeLength, &writeColumns, &writeRows, data))
+ {
+ return;
+ }
+
+ context->readPixels(x, y, width, height, format, type, data);
+
+ SetRobustLengthParam(length, writeLength);
+ SetRobustLengthParam(columns, writeColumns);
+ SetRobustLengthParam(rows, writeRows);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetnUniformfvRobustANGLE(GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params)
+{
+ EVENT(
+ "(GLuint program = %d, GLint location = %d, GLsizei bufsize = %d, GLsizei* length = "
+ "0x%0.8p, GLfloat* params = 0x%0.8p)",
+ program, location, bufSize, length, params);
+ UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetnUniformivRobustANGLE(GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ EVENT(
+ "(GLuint program = %d, GLint location = %d, GLsizei bufsize = %d, GLsizei* length = "
+ "0x%0.8p, GLint* params = 0x%0.8p)",
+ program, location, bufSize, length, params);
+ UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetnUniformuivRobustANGLE(GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLsizei bufsize = %d, GLsizei* length = "
+ "0x%0.8p, GLuint* params = 0x%0.8p)",
+ program, location, bufSize, length, params);
+ UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY TexParameterIivRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *params)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, const GLint *params = "
+ "0x%0.8p)",
+ target, pname, bufSize, params);
+ UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY TexParameterIuivRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLuint *params)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, const GLuint *params = "
+ "0x%0.8p)",
+ target, pname, bufSize, params);
+ UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetTexParameterIivRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+ "0x%0.8p, GLint *params = 0x%0.8p)",
+ target, pname, bufSize, length, params);
+ UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetTexParameterIuivRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+ "0x%0.8p, GLuint *params = 0x%0.8p)",
+ target, pname, bufSize, length, params);
+ UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterIivRobustANGLE(GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *param)
+{
+ EVENT(
+ "(GLuint sampler = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, const GLint *param = "
+ "0x%0.8p)",
+ sampler, pname, bufSize, param);
+ UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterIuivRobustANGLE(GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLuint *param)
+{
+ EVENT(
+ "(GLuint sampler = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, const GLuint *param = "
+ "0x%0.8p)",
+ sampler, pname, bufSize, param);
+ UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterIivRobustANGLE(GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ EVENT(
+ "(GLuint sampler = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+ "0x%0.8p, GLint *params = 0x%0.8p)",
+ sampler, pname, bufSize, length, params);
+ UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterIuivRobustANGLE(GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params)
+{
+ EVENT(
+ "(GLuint sampler = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
+ "0x%0.8p, GLuint *params = 0x%0.8p)",
+ sampler, pname, bufSize, length, params);
+ UNIMPLEMENTED();
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjectivRobustANGLE(GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ EVENT(
+ "(GLuint id = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
+ "GLuint *params = 0x%0.8p)",
+ id, pname, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei numParams = 0;
+ if (!ValidateGetQueryObjectivRobustANGLE(context, id, pname, bufSize, &numParams, params))
+ {
+ return;
+ }
+
+ context->getQueryObjectiv(id, pname, params);
+ SetRobustLengthParam(length, numParams);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjecti64vRobustANGLE(GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *params)
+{
+ EVENT(
+ "(GLuint id = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
+ "GLint64 *params = 0x%0.8p)",
+ id, pname, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei numParams = 0;
+ if (!ValidateGetQueryObjecti64vRobustANGLE(context, id, pname, bufSize, &numParams, params))
+ {
+ return;
+ }
+
+ context->getQueryObjecti64v(id, pname, params);
+ SetRobustLengthParam(length, numParams);
+ }
+}
+
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjectui64vRobustANGLE(GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint64 *params)
+{
+ EVENT(
+ "(GLuint id = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
+ "GLuint64 *params = 0x%0.8p)",
+ id, pname, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLsizei numParams = 0;
+ if (!ValidateGetQueryObjectui64vRobustANGLE(context, id, pname, bufSize, &numParams,
+ params))
+ {
+ return;
+ }
+
+ context->getQueryObjectui64v(id, pname, params);
+ SetRobustLengthParam(length, numParams);
+ }
+}
+
+GL_APICALL void GL_APIENTRY FramebufferTextureMultiviewLayeredANGLE(GLenum target,
+ GLenum attachment,
+ GLuint texture,
+ GLint level,
+ GLint baseViewIndex,
+ GLsizei numViews)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %u, GLint level = %d, "
+ "GLint baseViewIndex = %d, GLsizei numViews = %d)",
+ target, attachment, texture, level, baseViewIndex, numViews);
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() &&
+ !ValidateFramebufferTextureMultiviewLayeredANGLE(context, target, attachment, texture,
+ level, baseViewIndex, numViews))
+ {
+ return;
+ }
+ context->framebufferTextureMultiviewLayeredANGLE(target, attachment, texture, level,
+ baseViewIndex, numViews);
+ }
+}
+
+GL_APICALL void GL_APIENTRY FramebufferTextureMultiviewSideBySideANGLE(GLenum target,
+ GLenum attachment,
+ GLuint texture,
+ GLint level,
+ GLsizei numViews,
+ const GLint *viewportOffsets)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %u, GLint level = %d, "
+ "GLsizei numViews = %d, GLsizei* viewportOffsets = 0x%0.8p)",
+ target, attachment, texture, level, numViews, viewportOffsets);
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->skipValidation() &&
+ !ValidateFramebufferTextureMultiviewSideBySideANGLE(
+ context, target, attachment, texture, level, numViews, viewportOffsets))
+ {
+ return;
+ }
+ context->framebufferTextureMultiviewSideBySideANGLE(target, attachment, texture, level,
+ numViews, viewportOffsets);
+ }
+}
+
+} // gl
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.h b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.h
index a2fb9c5e80..2a3fa607cf 100644
--- a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.h
+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.h
@@ -17,17 +17,32 @@ namespace gl
{
// GL_ANGLE_framebuffer_blit
-ANGLE_EXPORT void GL_APIENTRY BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+ANGLE_EXPORT void GL_APIENTRY BlitFramebufferANGLE(GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter);
// GL_ANGLE_framebuffer_multisample
-ANGLE_EXPORT void GL_APIENTRY RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+ANGLE_EXPORT void GL_APIENTRY RenderbufferStorageMultisampleANGLE(GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
// GL_EXT_discard_framebuffer
-ANGLE_EXPORT void GL_APIENTRY DiscardFramebufferEXT(GLenum target, GLsizei numAttachments, const GLenum *attachments);
+ANGLE_EXPORT void GL_APIENTRY DiscardFramebufferEXT(GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments);
// GL_NV_fence
-ANGLE_EXPORT void GL_APIENTRY DeleteFencesNV(GLsizei n, const GLuint* fences);
-ANGLE_EXPORT void GL_APIENTRY GenFencesNV(GLsizei n, GLuint* fences);
+ANGLE_EXPORT void GL_APIENTRY DeleteFencesNV(GLsizei n, const GLuint *fences);
+ANGLE_EXPORT void GL_APIENTRY GenFencesNV(GLsizei n, GLuint *fences);
ANGLE_EXPORT GLboolean GL_APIENTRY IsFenceNV(GLuint fence);
ANGLE_EXPORT GLboolean GL_APIENTRY TestFenceNV(GLuint fence);
ANGLE_EXPORT void GL_APIENTRY GetFenceivNV(GLuint fence, GLenum pname, GLint *params);
@@ -35,16 +50,36 @@ ANGLE_EXPORT void GL_APIENTRY FinishFenceNV(GLuint fence);
ANGLE_EXPORT void GL_APIENTRY SetFenceNV(GLuint fence, GLenum condition);
// GL_ANGLE_translated_shader_source
-ANGLE_EXPORT void GL_APIENTRY GetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source);
+ANGLE_EXPORT void GL_APIENTRY GetTranslatedShaderSourceANGLE(GLuint shader,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLchar *source);
// GL_EXT_texture_storage
-ANGLE_EXPORT void GL_APIENTRY TexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+ANGLE_EXPORT void GL_APIENTRY TexStorage2DEXT(GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
// GL_EXT_robustness
ANGLE_EXPORT GLenum GL_APIENTRY GetGraphicsResetStatusEXT(void);
-ANGLE_EXPORT void GL_APIENTRY ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
-ANGLE_EXPORT void GL_APIENTRY GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, float *params);
-ANGLE_EXPORT void GL_APIENTRY GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY ReadnPixelsEXT(GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *data);
+ANGLE_EXPORT void GL_APIENTRY GetnUniformfvEXT(GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ float *params);
+ANGLE_EXPORT void GL_APIENTRY GetnUniformivEXT(GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLint *params);
// GL_EXT_occlusion_query_boolean
ANGLE_EXPORT void GL_APIENTRY GenQueriesEXT(GLsizei n, GLuint *ids);
@@ -65,22 +100,41 @@ ANGLE_EXPORT void GL_APIENTRY GetQueryObjectui64vEXT(GLuint id, GLenum pname, GL
ANGLE_EXPORT void GL_APIENTRY DrawBuffersEXT(GLsizei n, const GLenum *bufs);
// GL_ANGLE_instanced_arrays
-ANGLE_EXPORT void GL_APIENTRY DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount);
-ANGLE_EXPORT void GL_APIENTRY DrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+ANGLE_EXPORT void GL_APIENTRY DrawArraysInstancedANGLE(GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount);
+ANGLE_EXPORT void GL_APIENTRY DrawElementsInstancedANGLE(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei primcount);
ANGLE_EXPORT void GL_APIENTRY VertexAttribDivisorANGLE(GLuint index, GLuint divisor);
// GL_OES_get_program_binary
-ANGLE_EXPORT void GL_APIENTRY GetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary);
-ANGLE_EXPORT void GL_APIENTRY ProgramBinaryOES(GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length);
+ANGLE_EXPORT void GL_APIENTRY GetProgramBinaryOES(GLuint program,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary);
+ANGLE_EXPORT void GL_APIENTRY ProgramBinaryOES(GLuint program,
+ GLenum binaryFormat,
+ const void *binary,
+ GLint length);
// GL_OES_mapbuffer
ANGLE_EXPORT void *GL_APIENTRY MapBufferOES(GLenum target, GLenum access);
ANGLE_EXPORT GLboolean GL_APIENTRY UnmapBufferOES(GLenum target);
-ANGLE_EXPORT void GL_APIENTRY GetBufferPointervOES(GLenum target, GLenum pname, GLvoid **params);
+ANGLE_EXPORT void GL_APIENTRY GetBufferPointervOES(GLenum target, GLenum pname, void **params);
// GL_EXT_map_buffer_range
-ANGLE_EXPORT void *GL_APIENTRY MapBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
-ANGLE_EXPORT void GL_APIENTRY FlushMappedBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length);
+ANGLE_EXPORT void *GL_APIENTRY MapBufferRangeEXT(GLenum target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access);
+ANGLE_EXPORT void GL_APIENTRY FlushMappedBufferRangeEXT(GLenum target,
+ GLintptr offset,
+ GLsizeiptr length);
// GL_EXT_debug_marker
ANGLE_EXPORT void GL_APIENTRY InsertEventMarkerEXT(GLsizei length, const char *marker);
@@ -140,6 +194,524 @@ ANGLE_EXPORT void GL_APIENTRY GetObjectPtrLabelKHR(const void *ptr,
GLsizei *length,
GLchar *label);
ANGLE_EXPORT void GL_APIENTRY GetPointervKHR(GLenum pname, void **params);
-}
-#endif // LIBGLESV2_ENTRYPOINTGLES20EXT_H_
+// GL_CHROMIUM_bind_uniform_location
+ANGLE_EXPORT void GL_APIENTRY BindUniformLocationCHROMIUM(GLuint program,
+ GLint location,
+ const GLchar *name);
+
+// GL_CHROMIUM_framebuffer_mixed_samples
+ANGLE_EXPORT void GL_APIENTRY MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat *matrix);
+ANGLE_EXPORT void GL_APIENTRY MatrixLoadIdentityCHROMIUM(GLenum matrixMode);
+
+ANGLE_EXPORT void GL_APIENTRY CoverageModulationCHROMIUM(GLenum components);
+
+// GL_CHROMIUM_path_rendering
+ANGLE_EXPORT GLuint GL_APIENTRY GenPathsCHROMIUM(GLsizei chromium);
+ANGLE_EXPORT void GL_APIENTRY DeletePathsCHROMIUM(GLuint first, GLsizei range);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsPathCHROMIUM(GLuint path);
+ANGLE_EXPORT void GL_APIENTRY PathCommandsCHROMIUM(GLuint path,
+ GLsizei numCommands,
+ const GLubyte *commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const void *coords);
+ANGLE_EXPORT void GL_APIENTRY PathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value);
+ANGLE_EXPORT void GL_APIENTRY PathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value);
+ANGLE_EXPORT void GL_APIENTRY GetPathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY GetPathParameteriCHROMIUM(GLuint path, GLenum pname, GLint *value);
+ANGLE_EXPORT void GL_APIENTRY PathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask);
+ANGLE_EXPORT void GL_APIENTRY StencilFillPathCHROMIUM(GLuint path, GLenum fillMode, GLuint mask);
+ANGLE_EXPORT void GL_APIENTRY StencilStrokePathCHROMIUM(GLuint path, GLint reference, GLuint mask);
+ANGLE_EXPORT void GL_APIENTRY CoverFillPathCHROMIUM(GLuint path, GLenum coverMode);
+ANGLE_EXPORT void GL_APIENTRY CoverStrokePathCHROMIUM(GLuint path, GLenum coverMode);
+ANGLE_EXPORT void GL_APIENTRY StencilThenCoverFillPathCHROMIUM(GLuint path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode);
+ANGLE_EXPORT void GL_APIENTRY StencilThenCoverStrokePathCHROMIUM(GLuint path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode);
+ANGLE_EXPORT void GL_APIENTRY CoverFillPathInstancedCHROMIUM(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ANGLE_EXPORT void GL_APIENTRY CoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ANGLE_EXPORT void GL_APIENTRY StencilFillPathInstancedCHROMIUM(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBAse,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ANGLE_EXPORT void GL_APIENTRY StencilStrokePathInstancedCHROMIUM(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ANGLE_EXPORT void GL_APIENTRY
+StencilThenCoverFillPathInstancedCHROMIUM(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ANGLE_EXPORT void GL_APIENTRY
+StencilThenCoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues);
+ANGLE_EXPORT void GL_APIENTRY BindFragmentInputLocationCHROMIUM(GLuint program,
+ GLint location,
+ const GLchar *name);
+ANGLE_EXPORT void GL_APIENTRY ProgramPathFragmentInputGenCHROMIUM(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs);
+
+// GL_CHROMIUM_copy_texture
+ANGLE_EXPORT void GL_APIENTRY CopyTextureCHROMIUM(GLuint sourceId,
+ GLint sourceLevel,
+ GLenum destTarget,
+ GLuint destId,
+ GLint destLevel,
+ GLint internalFormat,
+ GLenum destType,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha);
+
+ANGLE_EXPORT void GL_APIENTRY CopySubTextureCHROMIUM(GLuint sourceId,
+ GLint sourceLevel,
+ GLenum destTarget,
+ GLuint destId,
+ GLint destLevel,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha);
+
+// GL_CHROMIUM_copy_compressed_texture
+ANGLE_EXPORT void GL_APIENTRY CompressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId);
+
+// GL_ANGLE_request_extension
+ANGLE_EXPORT void GL_APIENTRY RequestExtensionANGLE(const GLchar *name);
+
+// GL_ANGLE_robust_client_memory
+ANGLE_EXPORT void GL_APIENTRY GetBooleanvRobustANGLE(GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLboolean *data);
+ANGLE_EXPORT void GL_APIENTRY GetBufferParameterivRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetFloatvRobustANGLE(GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *data);
+ANGLE_EXPORT void GL_APIENTRY GetFramebufferAttachmentParameterivRobustANGLE(GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetIntegervRobustANGLE(GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *data);
+ANGLE_EXPORT void GL_APIENTRY GetProgramivRobustANGLE(GLuint program,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetRenderbufferParameterivRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetShaderivRobustANGLE(GLuint shader,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetTexParameterfvRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY GetTexParameterivRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetUniformfvRobustANGLE(GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY GetUniformivRobustANGLE(GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribfvRobustANGLE(GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribivRobustANGLE(GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribPointervRobustANGLE(GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ void **pointer);
+ANGLE_EXPORT void GL_APIENTRY ReadPixelsRobustANGLE(GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *pixels);
+ANGLE_EXPORT void GL_APIENTRY TexImage2DRobustANGLE(GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels);
+ANGLE_EXPORT void GL_APIENTRY TexParameterfvRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY TexParameterivRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *params);
+ANGLE_EXPORT void GL_APIENTRY TexSubImage2DRobustANGLE(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels);
+
+ANGLE_EXPORT void GL_APIENTRY TexImage3DRobustANGLE(GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels);
+ANGLE_EXPORT void GL_APIENTRY TexSubImage3DRobustANGLE(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels);
+
+ANGLE_EXPORT void GL_APIENTRY CompressedTexImage2DRobustANGLE(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const GLvoid *data);
+ANGLE_EXPORT void GL_APIENTRY CompressedTexSubImage2DRobustANGLE(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const GLvoid *data);
+ANGLE_EXPORT void GL_APIENTRY CompressedTexImage3DRobustANGLE(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const GLvoid *data);
+ANGLE_EXPORT void GL_APIENTRY CompressedTexSubImage3DRobustANGLE(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const GLvoid *data);
+
+ANGLE_EXPORT void GL_APIENTRY
+GetQueryivRobustANGLE(GLenum target, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjectuivRobustANGLE(GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params);
+ANGLE_EXPORT void GL_APIENTRY GetBufferPointervRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ void **params);
+ANGLE_EXPORT void GL_APIENTRY GetIntegeri_vRobustANGLE(GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *data);
+ANGLE_EXPORT void GL_APIENTRY GetInternalformativRobustANGLE(GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIivRobustANGLE(GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIuivRobustANGLE(GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params);
+ANGLE_EXPORT void GL_APIENTRY GetUniformuivRobustANGLE(GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params);
+ANGLE_EXPORT void GL_APIENTRY GetActiveUniformBlockivRobustANGLE(GLuint program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetInteger64vRobustANGLE(GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *data);
+ANGLE_EXPORT void GL_APIENTRY GetInteger64i_vRobustANGLE(GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *data);
+ANGLE_EXPORT void GL_APIENTRY GetBufferParameteri64vRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *params);
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterivRobustANGLE(GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *param);
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterfvRobustANGLE(GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLfloat *param);
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterivRobustANGLE(GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterfvRobustANGLE(GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params);
+
+ANGLE_EXPORT void GL_APIENTRY GetFramebufferParameterivRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetProgramInterfaceivRobustANGLE(GLuint program,
+ GLenum programInterface,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetBooleani_vRobustANGLE(GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLboolean *data);
+ANGLE_EXPORT void GL_APIENTRY GetMultisamplefvRobustANGLE(GLenum pname,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *val);
+ANGLE_EXPORT void GL_APIENTRY GetTexLevelParameterivRobustANGLE(GLenum target,
+ GLint level,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetTexLevelParameterfvRobustANGLE(GLenum target,
+ GLint level,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params);
+
+ANGLE_EXPORT void GL_APIENTRY GetPointervRobustANGLERobustANGLE(GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ void **params);
+ANGLE_EXPORT void GL_APIENTRY ReadnPixelsRobustANGLE(GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *data);
+ANGLE_EXPORT void GL_APIENTRY GetnUniformfvRobustANGLE(GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY GetnUniformivRobustANGLE(GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetnUniformuivRobustANGLE(GLuint program,
+ GLint location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params);
+ANGLE_EXPORT void GL_APIENTRY TexParameterIivRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *params);
+ANGLE_EXPORT void GL_APIENTRY TexParameterIuivRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLuint *params);
+ANGLE_EXPORT void GL_APIENTRY GetTexParameterIivRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetTexParameterIuivRobustANGLE(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params);
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterIivRobustANGLE(GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *param);
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterIuivRobustANGLE(GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLuint *param);
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterIivRobustANGLE(GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterIuivRobustANGLE(GLuint sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params);
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjectivRobustANGLE(GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjecti64vRobustANGLE(GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *params);
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjectui64vRobustANGLE(GLuint id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint64 *params);
+
+// GL_ANGLE_multiview
+ANGLE_EXPORT void GL_APIENTRY FramebufferTextureMultiviewLayeredANGLE(GLenum target,
+ GLenum attachment,
+ GLuint texture,
+ GLint level,
+ GLint baseViewIndex,
+ GLsizei numViews);
+ANGLE_EXPORT void GL_APIENTRY
+FramebufferTextureMultiviewSideBySideANGLE(GLenum target,
+ GLenum attachment,
+ GLuint texture,
+ GLint level,
+ GLsizei numViews,
+ const GLint *viewportOffsets);
+} // namespace gl
+
+#endif // LIBGLESV2_ENTRYPOINTGLES20EXT_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.cpp
deleted file mode 100644
index 856129aa07..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.cpp
+++ /dev/null
@@ -1,3057 +0,0 @@
-//
-// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// entry_points_gles_3_0.cpp : Implements the GLES 3.0 entry points.
-
-#include "libGLESv2/entry_points_gles_3_0.h"
-#include "libGLESv2/entry_points_gles_2_0_ext.h"
-#include "libGLESv2/global_state.h"
-
-#include "libANGLE/formatutils.h"
-#include "libANGLE/Buffer.h"
-#include "libANGLE/Context.h"
-#include "libANGLE/Error.h"
-#include "libANGLE/Fence.h"
-#include "libANGLE/Framebuffer.h"
-#include "libANGLE/Query.h"
-#include "libANGLE/VertexArray.h"
-
-#include "libANGLE/validationES.h"
-#include "libANGLE/validationES3.h"
-#include "libANGLE/queryconversions.h"
-
-#include "common/debug.h"
-
-namespace gl
-{
-
-void GL_APIENTRY ReadBuffer(GLenum mode)
-{
- EVENT("(GLenum mode = 0x%X)", mode);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!context->skipValidation() && !ValidateReadBuffer(context, mode))
- {
- return;
- }
-
- context->readBuffer(mode);
- }
-}
-
-void GL_APIENTRY DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices)
-{
- EVENT("(GLenum mode = 0x%X, GLuint start = %u, GLuint end = %u, GLsizei count = %d, GLenum type = 0x%X, "
- "const GLvoid* indices = 0x%0.8p)", mode, start, end, count, type, indices);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- IndexRange indexRange;
- if (!ValidateDrawElements(context, mode, count, type, indices, 0, &indexRange))
- {
- return;
- }
- if (indexRange.end > end || indexRange.start < start)
- {
- // GL spec says that behavior in this case is undefined - generating an error is fine.
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- // As long as index validation is done, it doesn't matter whether the context receives a drawElements or
- // a drawRangeElements call - the GL back-end is free to choose to call drawRangeElements based on the
- // validated index range. If index validation is removed, adding drawRangeElements to the context interface
- // should be reconsidered.
- Error error =
- context->drawRangeElements(mode, start, end, count, type, indices, indexRange);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY TexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
-{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, "
- "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLenum format = 0x%X, "
- "GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
- target, level, internalformat, width, height, depth, border, format, type, pixels);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- // validateES3TexImageFormat sets the error code if there is an error
- if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false,
- 0, 0, 0, width, height, depth, border, format, type,
- pixels))
- {
- return;
- }
-
- Extents size(width, height, depth);
- Texture *texture = context->getTargetTexture(target);
- Error error = texture->setImage(context, target, level, internalformat, size, format, type,
- reinterpret_cast<const uint8_t *>(pixels));
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels)
-{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
- "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
- "GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
- target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- // validateES3TexImageFormat sets the error code if there is an error
- if (!ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
- yoffset, zoffset, width, height, depth, 0, format,
- type, pixels))
- {
- return;
- }
-
- // Zero sized uploads are valid but no-ops
- if (width == 0 || height == 0 || depth == 0)
- {
- return;
- }
-
- Box area(xoffset, yoffset, zoffset, width, height, depth);
- Texture *texture = context->getTargetTexture(target);
- Error error = texture->setSubImage(context, target, level, area, format, type,
- reinterpret_cast<const uint8_t *>(pixels));
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY CopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
-{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
- "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
- target, level, xoffset, yoffset, zoffset, x, y, width, height);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!context->skipValidation() &&
- !ValidateCopyTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, x, y,
- width, height))
- {
- return;
- }
-
- context->copyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height);
- }
-}
-
-void GL_APIENTRY CompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data)
-{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
- "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, "
- "const GLvoid* data = 0x%0.8p)",
- target, level, internalformat, width, height, depth, border, imageSize, data);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
- depth, border, imageSize, data))
- {
- return;
- }
-
- Extents size(width, height, depth);
- Texture *texture = context->getTargetTexture(target);
- Error error =
- texture->setCompressedImage(context, target, level, internalformat, size, imageSize,
- reinterpret_cast<const uint8_t *>(data));
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data)
-{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
- "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
- "GLenum format = 0x%X, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
- target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- const InternalFormat &formatInfo = GetInternalFormatInfo(format);
- if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- if (!data)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- // validateES3TexImageFormat sets the error code if there is an error
- if (!ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, 0, 0, 0,
- width, height, depth, 0, GL_NONE, GL_NONE, data))
- {
- return;
- }
-
- // Zero sized uploads are valid but no-ops
- if (width == 0 || height == 0)
- {
- return;
- }
-
- Box area(xoffset, yoffset, zoffset, width, height, depth);
- Texture *texture = context->getTargetTexture(target);
- Error error =
- texture->setCompressedSubImage(context, target, level, area, format, imageSize,
- reinterpret_cast<const uint8_t *>(data));
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY GenQueries(GLsizei n, GLuint* ids)
-{
- EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateGenQueries(context, n, ids))
- {
- return;
- }
-
- for (GLsizei i = 0; i < n; i++)
- {
- ids[i] = context->createQuery();
- }
- }
-}
-
-void GL_APIENTRY DeleteQueries(GLsizei n, const GLuint* ids)
-{
- EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateDeleteQueries(context, n, ids))
- {
- return;
- }
-
- for (int i = 0; i < n; i++)
- {
- context->deleteQuery(ids[i]);
- }
- }
-}
-
-GLboolean GL_APIENTRY IsQuery(GLuint id)
-{
- EVENT("(GLuint id = %u)", id);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return GL_FALSE;
- }
-
- return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE;
- }
-
- return GL_FALSE;
-}
-
-void GL_APIENTRY BeginQuery(GLenum target, GLuint id)
-{
- EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateBeginQuery(context, target, id))
- {
- return;
- }
-
- Error error = context->beginQuery(target, id);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY EndQuery(GLenum target)
-{
- EVENT("(GLenum target = 0x%X)", target);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateEndQuery(context, target))
- {
- return;
- }
-
- Error error = context->endQuery(target);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY GetQueryiv(GLenum target, GLenum pname, GLint* params)
-{
- EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateGetQueryiv(context, target, pname, params))
- {
- return;
- }
-
- context->getQueryiv(target, pname, params);
- }
-}
-
-void GL_APIENTRY GetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params)
-{
- EVENT("(GLuint id = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", id, pname, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateGetQueryObjectuiv(context, id, pname, params))
- {
- return;
- }
-
- Error error = context->getQueryObjectuiv(id, pname, params);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-GLboolean GL_APIENTRY UnmapBuffer(GLenum target)
-{
- EVENT("(GLenum target = 0x%X)", target);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return GL_FALSE;
- }
-
- return UnmapBufferOES(target);
- }
-
- return GL_FALSE;
-}
-
-void GL_APIENTRY GetBufferPointerv(GLenum target, GLenum pname, GLvoid** params)
-{
- EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- GetBufferPointervOES(target, pname, params);
- }
-}
-
-void GL_APIENTRY DrawBuffers(GLsizei n, const GLenum* bufs)
-{
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!context->skipValidation() && !ValidateDrawBuffers(context, n, bufs))
- {
- return;
- }
-
- context->drawBuffers(n, bufs);
- }
-}
-
-void GL_APIENTRY UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
-{
- EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
- location, count, transpose, value);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x3, location, count, transpose))
- {
- return;
- }
-
- Program *program = context->getState().getProgram();
- program->setUniformMatrix2x3fv(location, count, transpose, value);
- }
-}
-
-void GL_APIENTRY UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
-{
- EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
- location, count, transpose, value);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x2, location, count, transpose))
- {
- return;
- }
-
- Program *program = context->getState().getProgram();
- program->setUniformMatrix3x2fv(location, count, transpose, value);
- }
-}
-
-void GL_APIENTRY UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
-{
- EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
- location, count, transpose, value);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x4, location, count, transpose))
- {
- return;
- }
-
- Program *program = context->getState().getProgram();
- program->setUniformMatrix2x4fv(location, count, transpose, value);
- }
-}
-
-void GL_APIENTRY UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
-{
- EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
- location, count, transpose, value);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x2, location, count, transpose))
- {
- return;
- }
-
- Program *program = context->getState().getProgram();
- program->setUniformMatrix4x2fv(location, count, transpose, value);
- }
-}
-
-void GL_APIENTRY UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
-{
- EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
- location, count, transpose, value);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x4, location, count, transpose))
- {
- return;
- }
-
- Program *program = context->getState().getProgram();
- program->setUniformMatrix3x4fv(location, count, transpose, value);
- }
-}
-
-void GL_APIENTRY UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
-{
- EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
- location, count, transpose, value);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x3, location, count, transpose))
- {
- return;
- }
-
- Program *program = context->getState().getProgram();
- program->setUniformMatrix4x3fv(location, count, transpose, value);
- }
-}
-
-void GL_APIENTRY BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
-{
- EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, GLint dstX0 = %d, "
- "GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
- srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!context->skipValidation() &&
- !ValidateBlitFramebuffer(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1,
- dstY1, mask, filter))
- {
- return;
- }
-
- context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask,
- filter);
- }
-}
-
-void GL_APIENTRY RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
-{
- EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
- target, samples, internalformat, width, height);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!ValidateES3RenderbufferStorageParameters(context, target, samples, internalformat, width, height))
- {
- return;
- }
-
- Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer();
- renderbuffer->setStorageMultisample(samples, internalformat, width, height);
- }
-}
-
-void GL_APIENTRY FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
-{
- EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %u, GLint level = %d, GLint layer = %d)",
- target, attachment, texture, level, layer);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!context->skipValidation() &&
- !ValidateFramebufferTextureLayer(context, target, attachment, texture, level, layer))
- {
- return;
- }
-
- context->framebufferTextureLayer(target, attachment, texture, level, layer);
- }
-}
-
-GLvoid *GL_APIENTRY MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
-{
- EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)",
- target, offset, length, access);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return NULL;
- }
-
- return MapBufferRangeEXT(target, offset, length, access);
- }
-
- return NULL;
-}
-
-void GL_APIENTRY FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
-{
- EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- FlushMappedBufferRangeEXT(target, offset, length);
- }
-}
-
-void GL_APIENTRY BindVertexArray(GLuint array)
-{
- EVENT("(GLuint array = %u)", array);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateBindVertexArray(context, array))
- {
- return;
- }
-
- context->bindVertexArray(array);
- }
-}
-
-void GL_APIENTRY DeleteVertexArrays(GLsizei n, const GLuint* arrays)
-{
- EVENT("(GLsizei n = %d, const GLuint* arrays = 0x%0.8p)", n, arrays);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateDeleteVertexArrays(context, n))
- {
- return;
- }
-
- for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
- {
- if (arrays[arrayIndex] != 0)
- {
- context->deleteVertexArray(arrays[arrayIndex]);
- }
- }
- }
-}
-
-void GL_APIENTRY GenVertexArrays(GLsizei n, GLuint* arrays)
-{
- EVENT("(GLsizei n = %d, GLuint* arrays = 0x%0.8p)", n, arrays);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateGenVertexArrays(context, n))
- {
- return;
- }
-
- for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
- {
- arrays[arrayIndex] = context->createVertexArray();
- }
- }
-}
-
-GLboolean GL_APIENTRY IsVertexArray(GLuint array)
-{
- EVENT("(GLuint array = %u)", array);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateIsVertexArray(context))
- {
- return GL_FALSE;
- }
-
- if (array == 0)
- {
- return GL_FALSE;
- }
-
- VertexArray *vao = context->getVertexArray(array);
-
- return (vao != NULL ? GL_TRUE : GL_FALSE);
- }
-
- return GL_FALSE;
-}
-
-void GL_APIENTRY GetIntegeri_v(GLenum target, GLuint index, GLint* data)
-{
- EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint* data = 0x%0.8p)",
- target, index, data);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- const Caps &caps = context->getCaps();
- switch (target)
- {
- case GL_TRANSFORM_FEEDBACK_BUFFER_START:
- case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
- case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
- if (index >= caps.maxTransformFeedbackSeparateAttributes)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
- break;
-
- case GL_UNIFORM_BUFFER_START:
- case GL_UNIFORM_BUFFER_SIZE:
- case GL_UNIFORM_BUFFER_BINDING:
- if (index >= caps.maxCombinedUniformBlocks)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- if (!(context->getIndexedIntegerv(target, index, data)))
- {
- GLenum nativeType;
- unsigned int numParams = 0;
- if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams))
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- if (numParams == 0)
- {
- return; // it is known that pname is valid, but there are no parameters to return
- }
-
- if (nativeType == GL_INT_64_ANGLEX)
- {
- GLint64 minIntValue = static_cast<GLint64>(std::numeric_limits<int>::min());
- GLint64 maxIntValue = static_cast<GLint64>(std::numeric_limits<int>::max());
- GLint64 *int64Params = new GLint64[numParams];
-
- context->getIndexedInteger64v(target, index, int64Params);
-
- for (unsigned int i = 0; i < numParams; ++i)
- {
- GLint64 clampedValue = std::max(std::min(int64Params[i], maxIntValue), minIntValue);
- data[i] = static_cast<GLint>(clampedValue);
- }
-
- delete [] int64Params;
- }
- else
- {
- UNREACHABLE();
- }
- }
- }
-}
-
-void GL_APIENTRY BeginTransformFeedback(GLenum primitiveMode)
-{
- EVENT("(GLenum primitiveMode = 0x%X)", primitiveMode);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- switch (primitiveMode)
- {
- case GL_TRIANGLES:
- case GL_LINES:
- case GL_POINTS:
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
- ASSERT(transformFeedback != NULL);
-
- if (transformFeedback->isActive())
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (transformFeedback->isPaused())
- {
- transformFeedback->resume();
- }
- else
- {
- transformFeedback->begin(primitiveMode);
- }
- }
-}
-
-void GL_APIENTRY EndTransformFeedback(void)
-{
- EVENT("(void)");
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
- ASSERT(transformFeedback != NULL);
-
- if (!transformFeedback->isActive())
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- transformFeedback->end();
- }
-}
-
-void GL_APIENTRY BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
-{
- EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u, GLintptr offset = %d, GLsizeiptr size = %d)",
- target, index, buffer, offset, size);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- const Caps &caps = context->getCaps();
- switch (target)
- {
- case GL_TRANSFORM_FEEDBACK_BUFFER:
- if (index >= caps.maxTransformFeedbackSeparateAttributes)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
- break;
-
- case GL_UNIFORM_BUFFER:
- if (index >= caps.maxUniformBufferBindings)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- if (buffer != 0 && size <= 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- switch (target)
- {
- case GL_TRANSFORM_FEEDBACK_BUFFER:
- {
- // size and offset must be a multiple of 4
- if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- // Cannot bind a transform feedback buffer if the current transform feedback is active (3.0.4 pg 91 section 2.15.2)
- TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback();
- if (curTransformFeedback && curTransformFeedback->isActive())
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- context->bindIndexedTransformFeedbackBuffer(buffer, index, offset, size);
- context->bindGenericTransformFeedbackBuffer(buffer);
- break;
- }
-
- case GL_UNIFORM_BUFFER:
-
- // it is an error to bind an offset not a multiple of the alignment
- if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- context->bindIndexedUniformBuffer(buffer, index, offset, size);
- context->bindGenericUniformBuffer(buffer);
- break;
-
- default:
- UNREACHABLE();
- }
- }
-}
-
-void GL_APIENTRY BindBufferBase(GLenum target, GLuint index, GLuint buffer)
-{
- EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u)",
- target, index, buffer);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- const Caps &caps = context->getCaps();
- switch (target)
- {
- case GL_TRANSFORM_FEEDBACK_BUFFER:
- if (index >= caps.maxTransformFeedbackSeparateAttributes)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
- break;
-
- case GL_UNIFORM_BUFFER:
- if (index >= caps.maxUniformBufferBindings)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (target)
- {
- case GL_TRANSFORM_FEEDBACK_BUFFER:
- {
- // Cannot bind a transform feedback buffer if the current transform feedback is active (3.0.4 pg 91 section 2.15.2)
- TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback();
- if (curTransformFeedback && curTransformFeedback->isActive())
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- context->bindIndexedTransformFeedbackBuffer(buffer, index, 0, 0);
- context->bindGenericTransformFeedbackBuffer(buffer);
- break;
- }
- case GL_UNIFORM_BUFFER:
- context->bindIndexedUniformBuffer(buffer, index, 0, 0);
- context->bindGenericUniformBuffer(buffer);
- break;
-
- default:
- UNREACHABLE();
- }
- }
-}
-
-void GL_APIENTRY TransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode)
-{
- EVENT("(GLuint program = %u, GLsizei count = %d, const GLchar* const* varyings = 0x%0.8p, GLenum bufferMode = 0x%X)",
- program, count, varyings, bufferMode);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (count < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- const Caps &caps = context->getCaps();
- switch (bufferMode)
- {
- case GL_INTERLEAVED_ATTRIBS:
- break;
- case GL_SEPARATE_ATTRIBS:
- if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
- break;
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- Program *programObject = GetValidProgram(context, program);
- if (!programObject)
- {
- return;
- }
-
- programObject->setTransformFeedbackVaryings(count, varyings, bufferMode);
- }
-}
-
-void GL_APIENTRY GetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name)
-{
- EVENT("(GLuint program = %u, GLuint index = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, "
- "GLsizei* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)",
- program, index, bufSize, length, size, type, name);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (bufSize < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- Program *programObject = GetValidProgram(context, program);
- if (!programObject)
- {
- return;
- }
-
- if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name);
- }
-}
-
-void GL_APIENTRY VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer)
-{
- EVENT("(GLuint index = %u, GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid* pointer = 0x%0.8p)",
- index, size, type, stride, pointer);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- if (size < 1 || size > 4)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- switch (type)
- {
- case GL_BYTE:
- case GL_UNSIGNED_BYTE:
- case GL_SHORT:
- case GL_UNSIGNED_SHORT:
- case GL_INT:
- case GL_UNSIGNED_INT:
- case GL_INT_2_10_10_10_REV:
- case GL_UNSIGNED_INT_2_10_10_10_REV:
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- if (stride < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- // [OpenGL ES 3.0.2] Section 2.8 page 24:
- // An INVALID_OPERATION error is generated when a non-zero vertex array object
- // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
- // and the pointer argument is not NULL.
- if (context->getState().getVertexArray()->id() != 0 && context->getState().getArrayBufferId() == 0 && pointer != NULL)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- context->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type, false, true,
- stride, pointer);
- }
-}
-
-void GL_APIENTRY GetVertexAttribIiv(GLuint index, GLenum pname, GLint* params)
-{
- EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
- index, pname, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- if (!ValidateGetVertexAttribParameters(context, pname))
- {
- return;
- }
-
- if (pname == GL_CURRENT_VERTEX_ATTRIB)
- {
- const VertexAttribCurrentValueData &currentValueData = context->getState().getVertexAttribCurrentValue(index);
- for (int i = 0; i < 4; ++i)
- {
- params[i] = currentValueData.IntValues[i];
- }
- }
- else
- {
- const VertexAttribute &attribState = context->getState().getVertexArray()->getVertexAttribute(index);
- *params = QuerySingleVertexAttributeParameter<GLint>(attribState, pname);
- }
- }
-}
-
-void GL_APIENTRY GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params)
-{
- EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLuint* params = 0x%0.8p)",
- index, pname, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- if (!ValidateGetVertexAttribParameters(context, pname))
- {
- return;
- }
-
- if (pname == GL_CURRENT_VERTEX_ATTRIB)
- {
- const VertexAttribCurrentValueData &currentValueData = context->getState().getVertexAttribCurrentValue(index);
- for (int i = 0; i < 4; ++i)
- {
- params[i] = currentValueData.UnsignedIntValues[i];
- }
- }
- else
- {
- const VertexAttribute &attribState = context->getState().getVertexArray()->getVertexAttribute(index);
- *params = QuerySingleVertexAttributeParameter<GLuint>(attribState, pname);
- }
- }
-}
-
-void GL_APIENTRY VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
-{
- EVENT("(GLuint index = %u, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)",
- index, x, y, z, w);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- GLint vals[4] = { x, y, z, w };
- context->getState().setVertexAttribi(index, vals);
- }
-}
-
-void GL_APIENTRY VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
-{
- EVENT("(GLuint index = %u, GLuint x = %u, GLuint y = %u, GLuint z = %u, GLuint w = %u)",
- index, x, y, z, w);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- GLuint vals[4] = { x, y, z, w };
- context->getState().setVertexAttribu(index, vals);
- }
-}
-
-void GL_APIENTRY VertexAttribI4iv(GLuint index, const GLint* v)
-{
- EVENT("(GLuint index = %u, const GLint* v = 0x%0.8p)", index, v);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- context->getState().setVertexAttribi(index, v);
- }
-}
-
-void GL_APIENTRY VertexAttribI4uiv(GLuint index, const GLuint* v)
-{
- EVENT("(GLuint index = %u, const GLuint* v = 0x%0.8p)", index, v);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- context->getState().setVertexAttribu(index, v);
- }
-}
-
-void GL_APIENTRY GetUniformuiv(GLuint program, GLint location, GLuint* params)
-{
- EVENT("(GLuint program = %u, GLint location = %d, GLuint* params = 0x%0.8p)",
- program, location, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateGetUniformuiv(context, program, location, params))
- {
- return;
- }
-
- Program *programObject = context->getProgram(program);
- ASSERT(programObject);
-
- programObject->getUniformuiv(location, params);
- }
-}
-
-GLint GL_APIENTRY GetFragDataLocation(GLuint program, const GLchar *name)
-{
- EVENT("(GLuint program = %u, const GLchar *name = 0x%0.8p)",
- program, name);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return -1;
- }
-
- if (program == 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return -1;
- }
-
- Program *programObject = context->getProgram(program);
-
- if (!programObject || !programObject->isLinked())
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return -1;
- }
-
- return programObject->getFragDataLocation(name);
- }
-
- return 0;
-}
-
-void GL_APIENTRY Uniform1ui(GLint location, GLuint v0)
-{
- Uniform1uiv(location, 1, &v0);
-}
-
-void GL_APIENTRY Uniform2ui(GLint location, GLuint v0, GLuint v1)
-{
- const GLuint xy[] = { v0, v1 };
- Uniform2uiv(location, 1, xy);
-}
-
-void GL_APIENTRY Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
-{
- const GLuint xyz[] = { v0, v1, v2 };
- Uniform3uiv(location, 1, xyz);
-}
-
-void GL_APIENTRY Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
-{
- const GLuint xyzw[] = { v0, v1, v2, v3 };
- Uniform4uiv(location, 1, xyzw);
-}
-
-void GL_APIENTRY Uniform1uiv(GLint location, GLsizei count, const GLuint* value)
-{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)",
- location, count, value);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateUniform(context, GL_UNSIGNED_INT, location, count))
- {
- return;
- }
-
- Program *program = context->getState().getProgram();
- program->setUniform1uiv(location, count, value);
- }
-}
-
-void GL_APIENTRY Uniform2uiv(GLint location, GLsizei count, const GLuint* value)
-{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)",
- location, count, value);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC2, location, count))
- {
- return;
- }
-
- Program *program = context->getState().getProgram();
- program->setUniform2uiv(location, count, value);
- }
-}
-
-void GL_APIENTRY Uniform3uiv(GLint location, GLsizei count, const GLuint* value)
-{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value)",
- location, count, value);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC3, location, count))
- {
- return;
- }
-
- Program *program = context->getState().getProgram();
- program->setUniform3uiv(location, count, value);
- }
-}
-
-void GL_APIENTRY Uniform4uiv(GLint location, GLsizei count, const GLuint* value)
-{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)",
- location, count, value);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC4, location, count))
- {
- return;
- }
-
- Program *program = context->getState().getProgram();
- program->setUniform4uiv(location, count, value);
- }
-}
-
-void GL_APIENTRY ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value)
-{
- EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint* value = 0x%0.8p)",
- buffer, drawbuffer, value);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!context->skipValidation() &&
- !ValidateClearBufferiv(context, buffer, drawbuffer, value))
- {
- return;
- }
-
- context->clearBufferiv(buffer, drawbuffer, value);
- }
-}
-
-void GL_APIENTRY ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value)
-{
- EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint* value = 0x%0.8p)",
- buffer, drawbuffer, value);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!context->skipValidation() &&
- !ValidateClearBufferuiv(context, buffer, drawbuffer, value))
- {
- return;
- }
-
- context->clearBufferuiv(buffer, drawbuffer, value);
- }
-}
-
-void GL_APIENTRY ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value)
-{
- EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat* value = 0x%0.8p)",
- buffer, drawbuffer, value);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!context->skipValidation() &&
- !ValidateClearBufferfv(context, buffer, drawbuffer, value))
- {
- return;
- }
-
- context->clearBufferfv(buffer, drawbuffer, value);
- }
-}
-
-void GL_APIENTRY ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
-{
- EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth, GLint stencil = %d)",
- buffer, drawbuffer, depth, stencil);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!context->skipValidation() &&
- !ValidateClearBufferfi(context, buffer, drawbuffer, depth, stencil))
- {
- return;
- }
-
- context->clearBufferfi(buffer, drawbuffer, depth, stencil);
- }
-}
-
-const GLubyte *GL_APIENTRY GetStringi(GLenum name, GLuint index)
-{
- EVENT("(GLenum name = 0x%X, GLuint index = %u)", name, index);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return NULL;
- }
-
- if (name != GL_EXTENSIONS)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return NULL;
- }
-
- if (index >= context->getExtensionStringCount())
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return NULL;
- }
-
- return reinterpret_cast<const GLubyte*>(context->getExtensionString(index).c_str());
- }
-
- return NULL;
-}
-
-void GL_APIENTRY CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
-{
- EVENT("(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X, GLintptr readOffset = %d, GLintptr writeOffset = %d, GLsizeiptr size = %d)",
- readTarget, writeTarget, readOffset, writeOffset, size);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- Buffer *readBuffer = context->getState().getTargetBuffer(readTarget);
- Buffer *writeBuffer = context->getState().getTargetBuffer(writeTarget);
-
- if (!readBuffer || !writeBuffer)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- // Verify that readBuffer and writeBuffer are not currently mapped
- if (readBuffer->isMapped() || writeBuffer->isMapped())
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (readOffset < 0 || writeOffset < 0 || size < 0 ||
- static_cast<unsigned int>(readOffset + size) > readBuffer->getSize() ||
- static_cast<unsigned int>(writeOffset + size) > writeBuffer->getSize())
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- if (readBuffer == writeBuffer && std::abs(readOffset - writeOffset) < size)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- // if size is zero, the copy is a successful no-op
- if (size > 0)
- {
- Error error = writeBuffer->copyBufferSubData(readBuffer, readOffset, writeOffset, size);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- }
-}
-
-void GL_APIENTRY GetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices)
-{
- EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLchar* const* uniformNames = 0x%0.8p, GLuint* uniformIndices = 0x%0.8p)",
- program, uniformCount, uniformNames, uniformIndices);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (uniformCount < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- Program *programObject = GetValidProgram(context, program);
-
- if (!programObject)
- {
- return;
- }
-
- if (!programObject->isLinked())
- {
- for (int uniformId = 0; uniformId < uniformCount; uniformId++)
- {
- uniformIndices[uniformId] = GL_INVALID_INDEX;
- }
- }
- else
- {
- for (int uniformId = 0; uniformId < uniformCount; uniformId++)
- {
- uniformIndices[uniformId] = programObject->getUniformIndex(uniformNames[uniformId]);
- }
- }
- }
-}
-
-void GL_APIENTRY GetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params)
-{
- EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLuint* uniformIndices = 0x%0.8p, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
- program, uniformCount, uniformIndices, pname, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (uniformCount < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- Program *programObject = GetValidProgram(context, program);
-
- if (!programObject)
- {
- return;
- }
-
- switch (pname)
- {
- case GL_UNIFORM_TYPE:
- case GL_UNIFORM_SIZE:
- case GL_UNIFORM_NAME_LENGTH:
- case GL_UNIFORM_BLOCK_INDEX:
- case GL_UNIFORM_OFFSET:
- case GL_UNIFORM_ARRAY_STRIDE:
- case GL_UNIFORM_MATRIX_STRIDE:
- case GL_UNIFORM_IS_ROW_MAJOR:
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- if (uniformCount > programObject->getActiveUniformCount())
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int uniformId = 0; uniformId < uniformCount; uniformId++)
- {
- const GLuint index = uniformIndices[uniformId];
-
- if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
- }
-
- for (int uniformId = 0; uniformId < uniformCount; uniformId++)
- {
- const GLuint index = uniformIndices[uniformId];
- params[uniformId] = programObject->getActiveUniformi(index, pname);
- }
- }
-}
-
-GLuint GL_APIENTRY GetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName)
-{
- EVENT("(GLuint program = %u, const GLchar* uniformBlockName = 0x%0.8p)", program, uniformBlockName);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return GL_INVALID_INDEX;
- }
-
- Program *programObject = GetValidProgram(context, program);
- if (!programObject)
- {
- return GL_INVALID_INDEX;
- }
-
- return programObject->getUniformBlockIndex(uniformBlockName);
- }
-
- return 0;
-}
-
-void GL_APIENTRY GetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params)
-{
- EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
- program, uniformBlockIndex, pname, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
- Program *programObject = GetValidProgram(context, program);
-
- if (!programObject)
- {
- return;
- }
-
- if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- switch (pname)
- {
- case GL_UNIFORM_BLOCK_BINDING:
- *params = static_cast<GLint>(programObject->getUniformBlockBinding(uniformBlockIndex));
- break;
-
- case GL_UNIFORM_BLOCK_DATA_SIZE:
- case GL_UNIFORM_BLOCK_NAME_LENGTH:
- case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
- case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
- case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
- case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
- programObject->getActiveUniformBlockiv(uniformBlockIndex, pname, params);
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- }
-}
-
-void GL_APIENTRY GetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName)
-{
- EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLchar* uniformBlockName = 0x%0.8p)",
- program, uniformBlockIndex, bufSize, length, uniformBlockName);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- Program *programObject = GetValidProgram(context, program);
-
- if (!programObject)
- {
- return;
- }
-
- if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- programObject->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName);
- }
-}
-
-void GL_APIENTRY UniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)
-{
- EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLuint uniformBlockBinding = %u)",
- program, uniformBlockIndex, uniformBlockBinding);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- Program *programObject = GetValidProgram(context, program);
-
- if (!programObject)
- {
- return;
- }
-
- // if never linked, there won't be any uniform blocks
- if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding);
- }
-}
-
-void GL_APIENTRY DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
-{
- EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
- mode, first, count, instanceCount);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!ValidateDrawArraysInstanced(context, mode, first, count, instanceCount))
- {
- return;
- }
-
- Error error = context->drawArraysInstanced(mode, first, count, instanceCount);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount)
-{
- EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei instanceCount = %d)",
- mode, count, type, indices, instanceCount);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- IndexRange indexRange;
- if (!ValidateDrawElementsInstanced(context, mode, count, type, indices, instanceCount, &indexRange))
- {
- return;
- }
-
- Error error =
- context->drawElementsInstanced(mode, count, type, indices, instanceCount, indexRange);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-GLsync GL_APIENTRY FenceSync_(GLenum condition, GLbitfield flags)
-{
- EVENT("(GLenum condition = 0x%X, GLbitfield flags = 0x%X)", condition, flags);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return 0;
- }
-
- if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return 0;
- }
-
- if (flags != 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return 0;
- }
-
- GLsync fenceSync = context->createFenceSync();
-
- FenceSync *fenceSyncObject = context->getFenceSync(fenceSync);
- Error error = fenceSyncObject->set(condition, flags);
- if (error.isError())
- {
- context->deleteFenceSync(fenceSync);
- context->recordError(error);
- return NULL;
- }
-
- return fenceSync;
- }
-
- return NULL;
-}
-
-GLboolean GL_APIENTRY IsSync(GLsync sync)
-{
- EVENT("(GLsync sync = 0x%0.8p)", sync);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return GL_FALSE;
- }
-
- return (context->getFenceSync(sync) != NULL);
- }
-
- return GL_FALSE;
-}
-
-void GL_APIENTRY DeleteSync(GLsync sync)
-{
- EVENT("(GLsync sync = 0x%0.8p)", sync);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (sync != static_cast<GLsync>(0) && !context->getFenceSync(sync))
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- context->deleteFenceSync(sync);
- }
-}
-
-GLenum GL_APIENTRY ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
-{
- EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)",
- sync, flags, timeout);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return GL_WAIT_FAILED;
- }
-
- if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return GL_WAIT_FAILED;
- }
-
- FenceSync *fenceSync = context->getFenceSync(sync);
-
- if (!fenceSync)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return GL_WAIT_FAILED;
- }
-
- GLenum result = GL_WAIT_FAILED;
- Error error = fenceSync->clientWait(flags, timeout, &result);
- if (error.isError())
- {
- context->recordError(error);
- return GL_WAIT_FAILED;
- }
-
- return result;
- }
-
- return GL_FALSE;
-}
-
-void GL_APIENTRY WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
-{
- EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)",
- sync, flags, timeout);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (flags != 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- if (timeout != GL_TIMEOUT_IGNORED)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- FenceSync *fenceSync = context->getFenceSync(sync);
-
- if (!fenceSync)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- Error error = fenceSync->serverWait(flags, timeout);
- if (error.isError())
- {
- context->recordError(error);
- }
- }
-}
-
-void GL_APIENTRY GetInteger64v(GLenum pname, GLint64* params)
-{
- EVENT("(GLenum pname = 0x%X, GLint64* params = 0x%0.8p)",
- pname, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- GLenum nativeType;
- unsigned int numParams = 0;
- if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
- {
- return;
- }
-
- if (nativeType == GL_INT_64_ANGLEX)
- {
- context->getInteger64v(pname, params);
- }
- else
- {
- CastStateValues(context, nativeType, pname, numParams, params);
- }
- }
-}
-
-void GL_APIENTRY GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values)
-{
- EVENT("(GLsync sync = 0x%0.8p, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLint* values = 0x%0.8p)",
- sync, pname, bufSize, length, values);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (bufSize < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- FenceSync *fenceSync = context->getFenceSync(sync);
-
- if (!fenceSync)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- switch (pname)
- {
- case GL_OBJECT_TYPE: values[0] = static_cast<GLint>(GL_SYNC_FENCE); break;
- case GL_SYNC_CONDITION: values[0] = static_cast<GLint>(fenceSync->getCondition()); break;
- case GL_SYNC_FLAGS: values[0] = static_cast<GLint>(fenceSync->getFlags()); break;
-
- case GL_SYNC_STATUS:
- {
- Error error = fenceSync->getStatus(values);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- break;
- }
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- }
-}
-
-void GL_APIENTRY GetInteger64i_v(GLenum target, GLuint index, GLint64* data)
-{
- EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint64* data = 0x%0.8p)",
- target, index, data);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- const Caps &caps = context->getCaps();
- switch (target)
- {
- case GL_TRANSFORM_FEEDBACK_BUFFER_START:
- case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
- case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
- if (index >= caps.maxTransformFeedbackSeparateAttributes)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
- break;
-
- case GL_UNIFORM_BUFFER_START:
- case GL_UNIFORM_BUFFER_SIZE:
- case GL_UNIFORM_BUFFER_BINDING:
- if (index >= caps.maxUniformBufferBindings)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- if (!(context->getIndexedInteger64v(target, index, data)))
- {
- GLenum nativeType;
- unsigned int numParams = 0;
- if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams))
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- if (numParams == 0)
- return; // it is known that pname is valid, but there are no parameters to return
-
- if (nativeType == GL_INT)
- {
- GLint *intParams = new GLint[numParams];
-
- context->getIndexedIntegerv(target, index, intParams);
-
- for (unsigned int i = 0; i < numParams; ++i)
- {
- data[i] = static_cast<GLint64>(intParams[i]);
- }
-
- delete [] intParams;
- }
- else
- {
- UNREACHABLE();
- }
- }
- }
-}
-
-void GL_APIENTRY GetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params)
-{
- EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64* params = 0x%0.8p)",
- target, pname, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!ValidBufferTarget(context, target))
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- if (!ValidBufferParameter(context, pname))
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- Buffer *buffer = context->getState().getTargetBuffer(target);
-
- if (!buffer)
- {
- // A null buffer means that "0" is bound to the requested buffer target
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- switch (pname)
- {
- case GL_BUFFER_USAGE:
- *params = static_cast<GLint64>(buffer->getUsage());
- break;
- case GL_BUFFER_SIZE:
- *params = buffer->getSize();
- break;
- case GL_BUFFER_ACCESS_FLAGS:
- *params = static_cast<GLint64>(buffer->getAccessFlags());
- break;
- case GL_BUFFER_MAPPED:
- *params = static_cast<GLint64>(buffer->isMapped());
- break;
- case GL_BUFFER_MAP_OFFSET:
- *params = buffer->getMapOffset();
- break;
- case GL_BUFFER_MAP_LENGTH:
- *params = buffer->getMapLength();
- break;
- default: UNREACHABLE(); break;
- }
- }
-}
-
-void GL_APIENTRY GenSamplers(GLsizei count, GLuint* samplers)
-{
- EVENT("(GLsizei count = %d, GLuint* samplers = 0x%0.8p)", count, samplers);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (count < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int i = 0; i < count; i++)
- {
- samplers[i] = context->createSampler();
- }
- }
-}
-
-void GL_APIENTRY DeleteSamplers(GLsizei count, const GLuint* samplers)
-{
- EVENT("(GLsizei count = %d, const GLuint* samplers = 0x%0.8p)", count, samplers);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (count < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int i = 0; i < count; i++)
- {
- context->deleteSampler(samplers[i]);
- }
- }
-}
-
-GLboolean GL_APIENTRY IsSampler(GLuint sampler)
-{
- EVENT("(GLuint sampler = %u)", sampler);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return GL_FALSE;
- }
-
- return context->isSampler(sampler);
- }
-
- return GL_FALSE;
-}
-
-void GL_APIENTRY BindSampler(GLuint unit, GLuint sampler)
-{
- EVENT("(GLuint unit = %u, GLuint sampler = %u)", unit, sampler);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (sampler != 0 && !context->isSampler(sampler))
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (unit >= context->getCaps().maxCombinedTextureImageUnits)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- context->bindSampler(unit, sampler);
- }
-}
-
-void GL_APIENTRY SamplerParameteri(GLuint sampler, GLenum pname, GLint param)
-{
- EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint param = %d)", sampler, pname, param);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!ValidateSamplerObjectParameter(context, pname))
- {
- return;
- }
-
- if (!ValidateTexParamParameters(context, pname, param))
- {
- return;
- }
-
- if (!context->isSampler(sampler))
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- context->samplerParameteri(sampler, pname, param);
- }
-}
-
-void GL_APIENTRY SamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param)
-{
- SamplerParameteri(sampler, pname, *param);
-}
-
-void GL_APIENTRY SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
-{
- EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLfloat param = %g)", sampler, pname, param);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!ValidateSamplerObjectParameter(context, pname))
- {
- return;
- }
-
- if (!ValidateTexParamParameters(context, pname, static_cast<GLint>(param)))
- {
- return;
- }
-
- if (!context->isSampler(sampler))
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- context->samplerParameterf(sampler, pname, param);
- }
-}
-
-void GL_APIENTRY SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param)
-{
- SamplerParameterf(sampler, pname, *param);
-}
-
-void GL_APIENTRY GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params)
-{
- EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", sampler, pname, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!ValidateSamplerObjectParameter(context, pname))
- {
- return;
- }
-
- if (!context->isSampler(sampler))
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- *params = context->getSamplerParameteri(sampler, pname);
- }
-}
-
-void GL_APIENTRY GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params)
-{
- EVENT("(GLuint sample = %ur, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", sampler, pname, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!ValidateSamplerObjectParameter(context, pname))
- {
- return;
- }
-
- if (!context->isSampler(sampler))
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- *params = context->getSamplerParameterf(sampler, pname);
- }
-}
-
-void GL_APIENTRY VertexAttribDivisor(GLuint index, GLuint divisor)
-{
- EVENT("(GLuint index = %u, GLuint divisor = %u)", index, divisor);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- context->setVertexAttribDivisor(index, divisor);
- }
-}
-
-void GL_APIENTRY BindTransformFeedback(GLenum target, GLuint id)
-{
- EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- switch (target)
- {
- case GL_TRANSFORM_FEEDBACK:
- {
- // Cannot bind a transform feedback object if the current one is started and not paused (3.0.2 pg 85 section 2.14.1)
- TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback();
- if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused())
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section 2.14.1)
- if (!context->isTransformFeedbackGenerated(id))
- {
- context->recordError(
- Error(GL_INVALID_OPERATION,
- "Cannot bind a transform feedback object that does not exist."));
- return;
- }
-
- context->bindTransformFeedback(id);
- }
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- }
-}
-
-void GL_APIENTRY DeleteTransformFeedbacks(GLsizei n, const GLuint* ids)
-{
- EVENT("(GLsizei n = %d, const GLuint* ids = 0x%0.8p)", n, ids);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- for (int i = 0; i < n; i++)
- {
- context->deleteTransformFeedback(ids[i]);
- }
- }
-}
-
-void GL_APIENTRY GenTransformFeedbacks(GLsizei n, GLuint* ids)
-{
- EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- for (int i = 0; i < n; i++)
- {
- ids[i] = context->createTransformFeedback();
- }
- }
-}
-
-GLboolean GL_APIENTRY IsTransformFeedback(GLuint id)
-{
- EVENT("(GLuint id = %u)", id);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return GL_FALSE;
- }
-
- if (id == 0)
- {
- // The 3.0.4 spec [section 6.1.11] states that if ID is zero, IsTransformFeedback
- // returns FALSE
- return GL_FALSE;
- }
-
- const TransformFeedback *transformFeedback = context->getTransformFeedback(id);
- return ((transformFeedback != nullptr) ? GL_TRUE : GL_FALSE);
- }
-
- return GL_FALSE;
-}
-
-void GL_APIENTRY PauseTransformFeedback(void)
-{
- EVENT("(void)");
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
- ASSERT(transformFeedback != NULL);
-
- // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
- if (!transformFeedback->isActive() || transformFeedback->isPaused())
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- transformFeedback->pause();
- }
-}
-
-void GL_APIENTRY ResumeTransformFeedback(void)
-{
- EVENT("(void)");
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
- ASSERT(transformFeedback != NULL);
-
- // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
- if (!transformFeedback->isActive() || !transformFeedback->isPaused())
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- transformFeedback->resume();
- }
-}
-
-void GL_APIENTRY GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary)
-{
- EVENT("(GLuint program = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLenum* binaryFormat = 0x%0.8p, GLvoid* binary = 0x%0.8p)",
- program, bufSize, length, binaryFormat, binary);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateGetProgramBinary(context, program, bufSize, length, binaryFormat, binary))
- {
- return;
- }
-
- Program *programObject = context->getProgram(program);
- ASSERT(programObject != nullptr);
-
- Error error = programObject->saveBinary(binaryFormat, binary, bufSize, length);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY ProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length)
-{
- EVENT("(GLuint program = %u, GLenum binaryFormat = 0x%X, const GLvoid* binary = 0x%0.8p, GLsizei length = %d)",
- program, binaryFormat, binary, length);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateProgramBinary(context, program, binaryFormat, binary, length))
- {
- return;
- }
-
- Program *programObject = context->getProgram(program);
- ASSERT(programObject != nullptr);
-
- Error error = programObject->loadBinary(binaryFormat, binary, length);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY ProgramParameteri(GLuint program, GLenum pname, GLint value)
-{
- EVENT("(GLuint program = %u, GLenum pname = 0x%X, GLint value = %d)",
- program, pname, value);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!ValidateProgramParameter(context, program, pname, value))
- {
- return;
- }
-
- gl::Program *programObject = context->getProgram(program);
- ASSERT(programObject != nullptr);
-
- switch (pname)
- {
- case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
- programObject->setBinaryRetrievableHint(value != GL_FALSE);
- break;
-
- default:
- UNREACHABLE();
- }
- }
-}
-
-void GL_APIENTRY InvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments)
-{
- EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p)",
- target, numAttachments, attachments);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!context->skipValidation() &&
- !ValidateInvalidateFramebuffer(context, target, numAttachments, attachments))
- {
- return;
- }
-
- context->invalidateFramebuffer(target, numAttachments, attachments);
- }
-}
-
-void GL_APIENTRY InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height)
-{
- EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p, GLint x = %d, "
- "GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
- target, numAttachments, attachments, x, y, width, height);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (!context->skipValidation() &&
- !ValidateInvalidateFramebuffer(context, target, numAttachments, attachments))
- {
- return;
- }
-
- context->invalidateSubFramebuffer(target, numAttachments, attachments, x, y, width, height);
- }
-}
-
-void GL_APIENTRY TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
-{
- EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
- target, levels, internalformat, width, height);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width,
- height, 1))
- {
- return;
- }
-
- Extents size(width, height, 1);
- Texture *texture = context->getTargetTexture(target);
- Error error = texture->setStorage(target, levels, internalformat, size);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
-{
- EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
- "GLsizei height = %d, GLsizei depth = %d)",
- target, levels, internalformat, width, height, depth);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width,
- height, depth))
- {
- return;
- }
-
- Extents size(width, height, depth);
- Texture *texture = context->getTargetTexture(target);
- Error error = texture->setStorage(target, levels, internalformat, size);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params)
-{
- EVENT("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, "
- "GLint* params = 0x%0.8p)",
- target, internalformat, pname, bufSize, params);
-
- Context *context = GetValidGlobalContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return;
- }
-
- const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
- if (!formatCaps.renderable)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- if (target != GL_RENDERBUFFER)
- {
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
-
- if (bufSize < 0)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return;
- }
-
- switch (pname)
- {
- case GL_NUM_SAMPLE_COUNTS:
- if (bufSize != 0)
- {
- *params = static_cast<GLint>(formatCaps.sampleCounts.size());
- }
- break;
-
- case GL_SAMPLES:
- {
- size_t returnCount = std::min<size_t>(bufSize, formatCaps.sampleCounts.size());
- auto sampleReverseIt = formatCaps.sampleCounts.rbegin();
- for (size_t sampleIndex = 0; sampleIndex < returnCount; ++sampleIndex)
- {
- params[sampleIndex] = *sampleReverseIt++;;
- }
- }
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return;
- }
- }
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.h b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.h
deleted file mode 100644
index 09ca0e4641..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.h
+++ /dev/null
@@ -1,125 +0,0 @@
-//
-// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// entry_points_gles_3_0.h : Defines the GLES 3.0 entry points.
-
-#ifndef LIBGLESV2_ENTRYPOINTGLES30_H_
-#define LIBGLESV2_ENTRYPOINTGLES30_H_
-
-#include <GLES3/gl3.h>
-#include <export.h>
-
-namespace gl
-{
-
-ANGLE_EXPORT void GL_APIENTRY ReadBuffer(GLenum mode);
-ANGLE_EXPORT void GL_APIENTRY DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices);
-ANGLE_EXPORT void GL_APIENTRY TexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
-ANGLE_EXPORT void GL_APIENTRY TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels);
-ANGLE_EXPORT void GL_APIENTRY CopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
-ANGLE_EXPORT void GL_APIENTRY CompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data);
-ANGLE_EXPORT void GL_APIENTRY CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data);
-ANGLE_EXPORT void GL_APIENTRY GenQueries(GLsizei n, GLuint* ids);
-ANGLE_EXPORT void GL_APIENTRY DeleteQueries(GLsizei n, const GLuint* ids);
-ANGLE_EXPORT GLboolean GL_APIENTRY IsQuery(GLuint id);
-ANGLE_EXPORT void GL_APIENTRY BeginQuery(GLenum target, GLuint id);
-ANGLE_EXPORT void GL_APIENTRY EndQuery(GLenum target);
-ANGLE_EXPORT void GL_APIENTRY GetQueryiv(GLenum target, GLenum pname, GLint* params);
-ANGLE_EXPORT void GL_APIENTRY GetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params);
-ANGLE_EXPORT GLboolean GL_APIENTRY UnmapBuffer(GLenum target);
-ANGLE_EXPORT void GL_APIENTRY GetBufferPointerv(GLenum target, GLenum pname, GLvoid** params);
-ANGLE_EXPORT void GL_APIENTRY DrawBuffers(GLsizei n, const GLenum* bufs);
-ANGLE_EXPORT void GL_APIENTRY UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
-ANGLE_EXPORT void GL_APIENTRY UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
-ANGLE_EXPORT void GL_APIENTRY UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
-ANGLE_EXPORT void GL_APIENTRY UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
-ANGLE_EXPORT void GL_APIENTRY UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
-ANGLE_EXPORT void GL_APIENTRY UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
-ANGLE_EXPORT void GL_APIENTRY BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
-ANGLE_EXPORT void GL_APIENTRY RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
-ANGLE_EXPORT void GL_APIENTRY FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
-ANGLE_EXPORT GLvoid* GL_APIENTRY MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
-ANGLE_EXPORT void GL_APIENTRY FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length);
-ANGLE_EXPORT void GL_APIENTRY BindVertexArray(GLuint array);
-ANGLE_EXPORT void GL_APIENTRY DeleteVertexArrays(GLsizei n, const GLuint* arrays);
-ANGLE_EXPORT void GL_APIENTRY GenVertexArrays(GLsizei n, GLuint* arrays);
-ANGLE_EXPORT GLboolean GL_APIENTRY IsVertexArray(GLuint array);
-ANGLE_EXPORT void GL_APIENTRY GetIntegeri_v(GLenum target, GLuint index, GLint* data);
-ANGLE_EXPORT void GL_APIENTRY BeginTransformFeedback(GLenum primitiveMode);
-ANGLE_EXPORT void GL_APIENTRY EndTransformFeedback(void);
-ANGLE_EXPORT void GL_APIENTRY BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
-ANGLE_EXPORT void GL_APIENTRY BindBufferBase(GLenum target, GLuint index, GLuint buffer);
-ANGLE_EXPORT void GL_APIENTRY TransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode);
-ANGLE_EXPORT void GL_APIENTRY GetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name);
-ANGLE_EXPORT void GL_APIENTRY VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer);
-ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIiv(GLuint index, GLenum pname, GLint* params);
-ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params);
-ANGLE_EXPORT void GL_APIENTRY VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w);
-ANGLE_EXPORT void GL_APIENTRY VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
-ANGLE_EXPORT void GL_APIENTRY VertexAttribI4iv(GLuint index, const GLint* v);
-ANGLE_EXPORT void GL_APIENTRY VertexAttribI4uiv(GLuint index, const GLuint* v);
-ANGLE_EXPORT void GL_APIENTRY GetUniformuiv(GLuint program, GLint location, GLuint* params);
-ANGLE_EXPORT GLint GL_APIENTRY GetFragDataLocation(GLuint program, const GLchar *name);
-ANGLE_EXPORT void GL_APIENTRY Uniform1ui(GLint location, GLuint v0);
-ANGLE_EXPORT void GL_APIENTRY Uniform2ui(GLint location, GLuint v0, GLuint v1);
-ANGLE_EXPORT void GL_APIENTRY Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2);
-ANGLE_EXPORT void GL_APIENTRY Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
-ANGLE_EXPORT void GL_APIENTRY Uniform1uiv(GLint location, GLsizei count, const GLuint* value);
-ANGLE_EXPORT void GL_APIENTRY Uniform2uiv(GLint location, GLsizei count, const GLuint* value);
-ANGLE_EXPORT void GL_APIENTRY Uniform3uiv(GLint location, GLsizei count, const GLuint* value);
-ANGLE_EXPORT void GL_APIENTRY Uniform4uiv(GLint location, GLsizei count, const GLuint* value);
-ANGLE_EXPORT void GL_APIENTRY ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value);
-ANGLE_EXPORT void GL_APIENTRY ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value);
-ANGLE_EXPORT void GL_APIENTRY ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value);
-ANGLE_EXPORT void GL_APIENTRY ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
-ANGLE_EXPORT const GLubyte *GL_APIENTRY GetStringi(GLenum name, GLuint index);
-ANGLE_EXPORT void GL_APIENTRY CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
-ANGLE_EXPORT void GL_APIENTRY GetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices);
-ANGLE_EXPORT void GL_APIENTRY GetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params);
-ANGLE_EXPORT GLuint GL_APIENTRY GetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName);
-ANGLE_EXPORT void GL_APIENTRY GetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params);
-ANGLE_EXPORT void GL_APIENTRY GetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName);
-ANGLE_EXPORT void GL_APIENTRY UniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
-ANGLE_EXPORT void GL_APIENTRY DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount);
-ANGLE_EXPORT void GL_APIENTRY DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount);
-ANGLE_EXPORT GLsync GL_APIENTRY FenceSync_(GLenum condition, GLbitfield flags);
-ANGLE_EXPORT GLboolean GL_APIENTRY IsSync(GLsync sync);
-ANGLE_EXPORT void GL_APIENTRY DeleteSync(GLsync sync);
-ANGLE_EXPORT GLenum GL_APIENTRY ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout);
-ANGLE_EXPORT void GL_APIENTRY WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout);
-ANGLE_EXPORT void GL_APIENTRY GetInteger64v(GLenum pname, GLint64* params);
-ANGLE_EXPORT void GL_APIENTRY GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values);
-ANGLE_EXPORT void GL_APIENTRY GetInteger64i_v(GLenum target, GLuint index, GLint64* data);
-ANGLE_EXPORT void GL_APIENTRY GetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params);
-ANGLE_EXPORT void GL_APIENTRY GenSamplers(GLsizei count, GLuint* samplers);
-ANGLE_EXPORT void GL_APIENTRY DeleteSamplers(GLsizei count, const GLuint* samplers);
-ANGLE_EXPORT GLboolean GL_APIENTRY IsSampler(GLuint sampler);
-ANGLE_EXPORT void GL_APIENTRY BindSampler(GLuint unit, GLuint sampler);
-ANGLE_EXPORT void GL_APIENTRY SamplerParameteri(GLuint sampler, GLenum pname, GLint param);
-ANGLE_EXPORT void GL_APIENTRY SamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param);
-ANGLE_EXPORT void GL_APIENTRY SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param);
-ANGLE_EXPORT void GL_APIENTRY SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param);
-ANGLE_EXPORT void GL_APIENTRY GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params);
-ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params);
-ANGLE_EXPORT void GL_APIENTRY VertexAttribDivisor(GLuint index, GLuint divisor);
-ANGLE_EXPORT void GL_APIENTRY BindTransformFeedback(GLenum target, GLuint id);
-ANGLE_EXPORT void GL_APIENTRY DeleteTransformFeedbacks(GLsizei n, const GLuint* ids);
-ANGLE_EXPORT void GL_APIENTRY GenTransformFeedbacks(GLsizei n, GLuint* ids);
-ANGLE_EXPORT GLboolean GL_APIENTRY IsTransformFeedback(GLuint id);
-ANGLE_EXPORT void GL_APIENTRY PauseTransformFeedback(void);
-ANGLE_EXPORT void GL_APIENTRY ResumeTransformFeedback(void);
-ANGLE_EXPORT void GL_APIENTRY GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary);
-ANGLE_EXPORT void GL_APIENTRY ProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length);
-ANGLE_EXPORT void GL_APIENTRY ProgramParameteri(GLuint program, GLenum pname, GLint value);
-ANGLE_EXPORT void GL_APIENTRY InvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments);
-ANGLE_EXPORT void GL_APIENTRY InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height);
-ANGLE_EXPORT void GL_APIENTRY TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
-ANGLE_EXPORT void GL_APIENTRY TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
-ANGLE_EXPORT void GL_APIENTRY GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params);
-
-}
-
-#endif // LIBGLESV2_ENTRYPOINTGLES30_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_autogen.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_autogen.cpp
new file mode 100644
index 0000000000..439f920bab
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_autogen.cpp
@@ -0,0 +1,2084 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// entry_points_gles_3_0_autogen.cpp:
+// Defines the GLES 3.0 entry points.
+
+#include "libANGLE/Context.h"
+#include "libANGLE/validationES3.h"
+#include "libGLESv2/global_state.h"
+
+namespace gl
+{
+void GL_APIENTRY ReadBuffer(GLenum src)
+{
+ EVENT("(GLenum src = 0x%X)", src);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ReadBuffer>(src);
+
+ if (context->skipValidation() || ValidateReadBuffer(context, src))
+ {
+ context->readBuffer(src);
+ }
+ }
+}
+
+void GL_APIENTRY DrawRangeElements(GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const void *indices)
+{
+ EVENT(
+ "(GLenum mode = 0x%X, GLuint start = %u, GLuint end = %u, GLsizei count = %d, GLenum type "
+ "= 0x%X, const void *indices = 0x%0.8p)",
+ mode, start, end, count, type, indices);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DrawRangeElements>(mode, start, end, count, type,
+ indices);
+
+ if (context->skipValidation() ||
+ ValidateDrawRangeElements(context, mode, start, end, count, type, indices))
+ {
+ context->drawRangeElements(mode, start, end, count, type, indices);
+ }
+ }
+}
+
+void GL_APIENTRY TexImage3D(GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, "
+ "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLenum format = 0x%X, GLenum "
+ "type = 0x%X, const void *pixels = 0x%0.8p)",
+ target, level, internalformat, width, height, depth, border, format, type, pixels);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::TexImage3D>(target, level, internalformat, width, height,
+ depth, border, format, type, pixels);
+
+ if (context->skipValidation() ||
+ ValidateTexImage3D(context, target, level, internalformat, width, height, depth, border,
+ format, type, pixels))
+ {
+ context->texImage3D(target, level, internalformat, width, height, depth, border, format,
+ type, pixels);
+ }
+ }
+}
+
+void GL_APIENTRY TexSubImage3D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, GLint "
+ "zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLenum format "
+ "= 0x%X, GLenum type = 0x%X, const void *pixels = 0x%0.8p)",
+ target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::TexSubImage3D>(
+ target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
+
+ if (context->skipValidation() ||
+ ValidateTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width, height,
+ depth, format, type, pixels))
+ {
+ context->texSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth,
+ format, type, pixels);
+ }
+ }
+}
+
+void GL_APIENTRY CopyTexSubImage3D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, GLint "
+ "zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
+ target, level, xoffset, yoffset, zoffset, x, y, width, height);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::CopyTexSubImage3D>(target, level, xoffset, yoffset,
+ zoffset, x, y, width, height);
+
+ if (context->skipValidation() ||
+ ValidateCopyTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, x, y,
+ width, height))
+ {
+ context->copyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width,
+ height);
+ }
+ }
+}
+
+void GL_APIENTRY CompressedTexImage3D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ const void *data)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = "
+ "%d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, "
+ "const void *data = 0x%0.8p)",
+ target, level, internalformat, width, height, depth, border, imageSize, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::CompressedTexImage3D>(
+ target, level, internalformat, width, height, depth, border, imageSize, data);
+
+ if (context->skipValidation() ||
+ ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
+ depth, border, imageSize, data))
+ {
+ context->compressedTexImage3D(target, level, internalformat, width, height, depth,
+ border, imageSize, data);
+ }
+ }
+}
+
+void GL_APIENTRY CompressedTexSubImage3D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, GLint "
+ "zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLenum format "
+ "= 0x%X, GLsizei imageSize = %d, const void *data = 0x%0.8p)",
+ target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::CompressedTexSubImage3D>(target, level, xoffset, yoffset,
+ zoffset, width, height, depth,
+ format, imageSize, data);
+
+ if (context->skipValidation() ||
+ ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset,
+ width, height, depth, format, imageSize, data))
+ {
+ context->compressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width,
+ height, depth, format, imageSize, data);
+ }
+ }
+}
+
+void GL_APIENTRY GenQueries(GLsizei n, GLuint *ids)
+{
+ EVENT("(GLsizei n = %d, GLuint *ids = 0x%0.8p)", n, ids);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GenQueries>(n, ids);
+
+ if (context->skipValidation() || ValidateGenQueries(context, n, ids))
+ {
+ context->genQueries(n, ids);
+ }
+ }
+}
+
+void GL_APIENTRY DeleteQueries(GLsizei n, const GLuint *ids)
+{
+ EVENT("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DeleteQueries>(n, ids);
+
+ if (context->skipValidation() || ValidateDeleteQueries(context, n, ids))
+ {
+ context->deleteQueries(n, ids);
+ }
+ }
+}
+
+GLboolean GL_APIENTRY IsQuery(GLuint id)
+{
+ EVENT("(GLuint id = %u)", id);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::IsQuery>(id);
+
+ if (context->skipValidation() || ValidateIsQuery(context, id))
+ {
+ return context->isQuery(id);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::IsQuery, GLboolean>();
+}
+
+void GL_APIENTRY BeginQuery(GLenum target, GLuint id)
+{
+ EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::BeginQuery>(target, id);
+
+ if (context->skipValidation() || ValidateBeginQuery(context, target, id))
+ {
+ context->beginQuery(target, id);
+ }
+ }
+}
+
+void GL_APIENTRY EndQuery(GLenum target)
+{
+ EVENT("(GLenum target = 0x%X)", target);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::EndQuery>(target);
+
+ if (context->skipValidation() || ValidateEndQuery(context, target))
+ {
+ context->endQuery(target);
+ }
+ }
+}
+
+void GL_APIENTRY GetQueryiv(GLenum target, GLenum pname, GLint *params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname,
+ params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetQueryiv>(target, pname, params);
+
+ if (context->skipValidation() || ValidateGetQueryiv(context, target, pname, params))
+ {
+ context->getQueryiv(target, pname, params);
+ }
+ }
+}
+
+void GL_APIENTRY GetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params)
+{
+ EVENT("(GLuint id = %u, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)", id, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetQueryObjectuiv>(id, pname, params);
+
+ if (context->skipValidation() || ValidateGetQueryObjectuiv(context, id, pname, params))
+ {
+ context->getQueryObjectuiv(id, pname, params);
+ }
+ }
+}
+
+GLboolean GL_APIENTRY UnmapBuffer(GLenum target)
+{
+ EVENT("(GLenum target = 0x%X)", target);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
+ context->gatherParams<EntryPoint::UnmapBuffer>(targetPacked);
+
+ if (context->skipValidation() || ValidateUnmapBuffer(context, targetPacked))
+ {
+ return context->unmapBuffer(targetPacked);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::UnmapBuffer, GLboolean>();
+}
+
+void GL_APIENTRY GetBufferPointerv(GLenum target, GLenum pname, void **params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, void **params = 0x%0.8p)", target, pname,
+ params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
+ context->gatherParams<EntryPoint::GetBufferPointerv>(targetPacked, pname, params);
+
+ if (context->skipValidation() ||
+ ValidateGetBufferPointerv(context, targetPacked, pname, params))
+ {
+ context->getBufferPointerv(targetPacked, pname, params);
+ }
+ }
+}
+
+void GL_APIENTRY DrawBuffers(GLsizei n, const GLenum *bufs)
+{
+ EVENT("(GLsizei n = %d, const GLenum *bufs = 0x%0.8p)", n, bufs);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DrawBuffers>(n, bufs);
+
+ if (context->skipValidation() || ValidateDrawBuffers(context, n, bufs))
+ {
+ context->drawBuffers(n, bufs);
+ }
+ }
+}
+
+void GL_APIENTRY UniformMatrix2x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ EVENT(
+ "(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat *value "
+ "= 0x%0.8p)",
+ location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::UniformMatrix2x3fv>(location, count, transpose, value);
+
+ if (context->skipValidation() ||
+ ValidateUniformMatrix2x3fv(context, location, count, transpose, value))
+ {
+ context->uniformMatrix2x3fv(location, count, transpose, value);
+ }
+ }
+}
+
+void GL_APIENTRY UniformMatrix3x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ EVENT(
+ "(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat *value "
+ "= 0x%0.8p)",
+ location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::UniformMatrix3x2fv>(location, count, transpose, value);
+
+ if (context->skipValidation() ||
+ ValidateUniformMatrix3x2fv(context, location, count, transpose, value))
+ {
+ context->uniformMatrix3x2fv(location, count, transpose, value);
+ }
+ }
+}
+
+void GL_APIENTRY UniformMatrix2x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ EVENT(
+ "(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat *value "
+ "= 0x%0.8p)",
+ location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::UniformMatrix2x4fv>(location, count, transpose, value);
+
+ if (context->skipValidation() ||
+ ValidateUniformMatrix2x4fv(context, location, count, transpose, value))
+ {
+ context->uniformMatrix2x4fv(location, count, transpose, value);
+ }
+ }
+}
+
+void GL_APIENTRY UniformMatrix4x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ EVENT(
+ "(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat *value "
+ "= 0x%0.8p)",
+ location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::UniformMatrix4x2fv>(location, count, transpose, value);
+
+ if (context->skipValidation() ||
+ ValidateUniformMatrix4x2fv(context, location, count, transpose, value))
+ {
+ context->uniformMatrix4x2fv(location, count, transpose, value);
+ }
+ }
+}
+
+void GL_APIENTRY UniformMatrix3x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ EVENT(
+ "(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat *value "
+ "= 0x%0.8p)",
+ location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::UniformMatrix3x4fv>(location, count, transpose, value);
+
+ if (context->skipValidation() ||
+ ValidateUniformMatrix3x4fv(context, location, count, transpose, value))
+ {
+ context->uniformMatrix3x4fv(location, count, transpose, value);
+ }
+ }
+}
+
+void GL_APIENTRY UniformMatrix4x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ EVENT(
+ "(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat *value "
+ "= 0x%0.8p)",
+ location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::UniformMatrix4x3fv>(location, count, transpose, value);
+
+ if (context->skipValidation() ||
+ ValidateUniformMatrix4x3fv(context, location, count, transpose, value))
+ {
+ context->uniformMatrix4x3fv(location, count, transpose, value);
+ }
+ }
+}
+
+void GL_APIENTRY BlitFramebuffer(GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter)
+{
+ EVENT(
+ "(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, GLint dstX0 = "
+ "%d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, GLbitfield mask = 0x%X, GLenum "
+ "filter = 0x%X)",
+ srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::BlitFramebuffer>(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
+ dstX1, dstY1, mask, filter);
+
+ if (context->skipValidation() ||
+ ValidateBlitFramebuffer(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
+ mask, filter))
+ {
+ context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask,
+ filter);
+ }
+ }
+}
+
+void GL_APIENTRY RenderbufferStorageMultisample(GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width "
+ "= %d, GLsizei height = %d)",
+ target, samples, internalformat, width, height);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::RenderbufferStorageMultisample>(
+ target, samples, internalformat, width, height);
+
+ if (context->skipValidation() ||
+ ValidateRenderbufferStorageMultisample(context, target, samples, internalformat, width,
+ height))
+ {
+ context->renderbufferStorageMultisample(target, samples, internalformat, width, height);
+ }
+ }
+}
+
+void GL_APIENTRY
+FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %u, GLint level = %d, "
+ "GLint layer = %d)",
+ target, attachment, texture, level, layer);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::FramebufferTextureLayer>(target, attachment, texture,
+ level, layer);
+
+ if (context->skipValidation() ||
+ ValidateFramebufferTextureLayer(context, target, attachment, texture, level, layer))
+ {
+ context->framebufferTextureLayer(target, attachment, texture, level, layer);
+ }
+ }
+}
+
+void *GL_APIENTRY MapBufferRange(GLenum target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = "
+ "0x%X)",
+ target, offset, length, access);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
+ context->gatherParams<EntryPoint::MapBufferRange>(targetPacked, offset, length, access);
+
+ if (context->skipValidation() ||
+ ValidateMapBufferRange(context, targetPacked, offset, length, access))
+ {
+ return context->mapBufferRange(targetPacked, offset, length, access);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::MapBufferRange, void *>();
+}
+
+void GL_APIENTRY FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
+{
+ EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset,
+ length);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
+ context->gatherParams<EntryPoint::FlushMappedBufferRange>(targetPacked, offset, length);
+
+ if (context->skipValidation() ||
+ ValidateFlushMappedBufferRange(context, targetPacked, offset, length))
+ {
+ context->flushMappedBufferRange(targetPacked, offset, length);
+ }
+ }
+}
+
+void GL_APIENTRY BindVertexArray(GLuint array)
+{
+ EVENT("(GLuint array = %u)", array);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::BindVertexArray>(array);
+
+ if (context->skipValidation() || ValidateBindVertexArray(context, array))
+ {
+ context->bindVertexArray(array);
+ }
+ }
+}
+
+void GL_APIENTRY DeleteVertexArrays(GLsizei n, const GLuint *arrays)
+{
+ EVENT("(GLsizei n = %d, const GLuint *arrays = 0x%0.8p)", n, arrays);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DeleteVertexArrays>(n, arrays);
+
+ if (context->skipValidation() || ValidateDeleteVertexArrays(context, n, arrays))
+ {
+ context->deleteVertexArrays(n, arrays);
+ }
+ }
+}
+
+void GL_APIENTRY GenVertexArrays(GLsizei n, GLuint *arrays)
+{
+ EVENT("(GLsizei n = %d, GLuint *arrays = 0x%0.8p)", n, arrays);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GenVertexArrays>(n, arrays);
+
+ if (context->skipValidation() || ValidateGenVertexArrays(context, n, arrays))
+ {
+ context->genVertexArrays(n, arrays);
+ }
+ }
+}
+
+GLboolean GL_APIENTRY IsVertexArray(GLuint array)
+{
+ EVENT("(GLuint array = %u)", array);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::IsVertexArray>(array);
+
+ if (context->skipValidation() || ValidateIsVertexArray(context, array))
+ {
+ return context->isVertexArray(array);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::IsVertexArray, GLboolean>();
+}
+
+void GL_APIENTRY GetIntegeri_v(GLenum target, GLuint index, GLint *data)
+{
+ EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint *data = 0x%0.8p)", target, index, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetIntegeri_v>(target, index, data);
+
+ if (context->skipValidation() || ValidateGetIntegeri_v(context, target, index, data))
+ {
+ context->getIntegeri_v(target, index, data);
+ }
+ }
+}
+
+void GL_APIENTRY BeginTransformFeedback(GLenum primitiveMode)
+{
+ EVENT("(GLenum primitiveMode = 0x%X)", primitiveMode);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::BeginTransformFeedback>(primitiveMode);
+
+ if (context->skipValidation() || ValidateBeginTransformFeedback(context, primitiveMode))
+ {
+ context->beginTransformFeedback(primitiveMode);
+ }
+ }
+}
+
+void GL_APIENTRY EndTransformFeedback()
+{
+ EVENT("()");
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::EndTransformFeedback>();
+
+ if (context->skipValidation() || ValidateEndTransformFeedback(context))
+ {
+ context->endTransformFeedback();
+ }
+ }
+}
+
+void GL_APIENTRY
+BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u, GLintptr offset = %d, "
+ "GLsizeiptr size = %d)",
+ target, index, buffer, offset, size);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
+ context->gatherParams<EntryPoint::BindBufferRange>(targetPacked, index, buffer, offset,
+ size);
+
+ if (context->skipValidation() ||
+ ValidateBindBufferRange(context, targetPacked, index, buffer, offset, size))
+ {
+ context->bindBufferRange(targetPacked, index, buffer, offset, size);
+ }
+ }
+}
+
+void GL_APIENTRY BindBufferBase(GLenum target, GLuint index, GLuint buffer)
+{
+ EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u)", target, index, buffer);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
+ context->gatherParams<EntryPoint::BindBufferBase>(targetPacked, index, buffer);
+
+ if (context->skipValidation() ||
+ ValidateBindBufferBase(context, targetPacked, index, buffer))
+ {
+ context->bindBufferBase(targetPacked, index, buffer);
+ }
+ }
+}
+
+void GL_APIENTRY TransformFeedbackVaryings(GLuint program,
+ GLsizei count,
+ const GLchar *const *varyings,
+ GLenum bufferMode)
+{
+ EVENT(
+ "(GLuint program = %u, GLsizei count = %d, const GLchar *const*varyings = 0x%0.8p, GLenum "
+ "bufferMode = 0x%X)",
+ program, count, varyings, bufferMode);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::TransformFeedbackVaryings>(program, count, varyings,
+ bufferMode);
+
+ if (context->skipValidation() ||
+ ValidateTransformFeedbackVaryings(context, program, count, varyings, bufferMode))
+ {
+ context->transformFeedbackVaryings(program, count, varyings, bufferMode);
+ }
+ }
+}
+
+void GL_APIENTRY GetTransformFeedbackVarying(GLuint program,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *size,
+ GLenum *type,
+ GLchar *name)
+{
+ EVENT(
+ "(GLuint program = %u, GLuint index = %u, GLsizei bufSize = %d, GLsizei *length = 0x%0.8p, "
+ "GLsizei *size = 0x%0.8p, GLenum *type = 0x%0.8p, GLchar *name = 0x%0.8p)",
+ program, index, bufSize, length, size, type, name);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetTransformFeedbackVarying>(program, index, bufSize,
+ length, size, type, name);
+
+ if (context->skipValidation() ||
+ ValidateGetTransformFeedbackVarying(context, program, index, bufSize, length, size,
+ type, name))
+ {
+ context->getTransformFeedbackVarying(program, index, bufSize, length, size, type, name);
+ }
+ }
+}
+
+void GL_APIENTRY
+VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer)
+{
+ EVENT(
+ "(GLuint index = %u, GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const void "
+ "*pointer = 0x%0.8p)",
+ index, size, type, stride, pointer);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::VertexAttribIPointer>(index, size, type, stride, pointer);
+
+ if (context->skipValidation() ||
+ ValidateVertexAttribIPointer(context, index, size, type, stride, pointer))
+ {
+ context->vertexAttribIPointer(index, size, type, stride, pointer);
+ }
+ }
+}
+
+void GL_APIENTRY GetVertexAttribIiv(GLuint index, GLenum pname, GLint *params)
+{
+ EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", index, pname,
+ params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetVertexAttribIiv>(index, pname, params);
+
+ if (context->skipValidation() || ValidateGetVertexAttribIiv(context, index, pname, params))
+ {
+ context->getVertexAttribIiv(index, pname, params);
+ }
+ }
+}
+
+void GL_APIENTRY GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params)
+{
+ EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)", index, pname,
+ params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetVertexAttribIuiv>(index, pname, params);
+
+ if (context->skipValidation() || ValidateGetVertexAttribIuiv(context, index, pname, params))
+ {
+ context->getVertexAttribIuiv(index, pname, params);
+ }
+ }
+}
+
+void GL_APIENTRY VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
+{
+ EVENT("(GLuint index = %u, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)", index, x,
+ y, z, w);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::VertexAttribI4i>(index, x, y, z, w);
+
+ if (context->skipValidation() || ValidateVertexAttribI4i(context, index, x, y, z, w))
+ {
+ context->vertexAttribI4i(index, x, y, z, w);
+ }
+ }
+}
+
+void GL_APIENTRY VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
+{
+ EVENT("(GLuint index = %u, GLuint x = %u, GLuint y = %u, GLuint z = %u, GLuint w = %u)", index,
+ x, y, z, w);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::VertexAttribI4ui>(index, x, y, z, w);
+
+ if (context->skipValidation() || ValidateVertexAttribI4ui(context, index, x, y, z, w))
+ {
+ context->vertexAttribI4ui(index, x, y, z, w);
+ }
+ }
+}
+
+void GL_APIENTRY VertexAttribI4iv(GLuint index, const GLint *v)
+{
+ EVENT("(GLuint index = %u, const GLint *v = 0x%0.8p)", index, v);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::VertexAttribI4iv>(index, v);
+
+ if (context->skipValidation() || ValidateVertexAttribI4iv(context, index, v))
+ {
+ context->vertexAttribI4iv(index, v);
+ }
+ }
+}
+
+void GL_APIENTRY VertexAttribI4uiv(GLuint index, const GLuint *v)
+{
+ EVENT("(GLuint index = %u, const GLuint *v = 0x%0.8p)", index, v);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::VertexAttribI4uiv>(index, v);
+
+ if (context->skipValidation() || ValidateVertexAttribI4uiv(context, index, v))
+ {
+ context->vertexAttribI4uiv(index, v);
+ }
+ }
+}
+
+void GL_APIENTRY GetUniformuiv(GLuint program, GLint location, GLuint *params)
+{
+ EVENT("(GLuint program = %u, GLint location = %d, GLuint *params = 0x%0.8p)", program, location,
+ params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetUniformuiv>(program, location, params);
+
+ if (context->skipValidation() || ValidateGetUniformuiv(context, program, location, params))
+ {
+ context->getUniformuiv(program, location, params);
+ }
+ }
+}
+
+GLint GL_APIENTRY GetFragDataLocation(GLuint program, const GLchar *name)
+{
+ EVENT("(GLuint program = %u, const GLchar *name = 0x%0.8p)", program, name);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetFragDataLocation>(program, name);
+
+ if (context->skipValidation() || ValidateGetFragDataLocation(context, program, name))
+ {
+ return context->getFragDataLocation(program, name);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::GetFragDataLocation, GLint>();
+}
+
+void GL_APIENTRY Uniform1ui(GLint location, GLuint v0)
+{
+ EVENT("(GLint location = %d, GLuint v0 = %u)", location, v0);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Uniform1ui>(location, v0);
+
+ if (context->skipValidation() || ValidateUniform1ui(context, location, v0))
+ {
+ context->uniform1ui(location, v0);
+ }
+ }
+}
+
+void GL_APIENTRY Uniform2ui(GLint location, GLuint v0, GLuint v1)
+{
+ EVENT("(GLint location = %d, GLuint v0 = %u, GLuint v1 = %u)", location, v0, v1);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Uniform2ui>(location, v0, v1);
+
+ if (context->skipValidation() || ValidateUniform2ui(context, location, v0, v1))
+ {
+ context->uniform2ui(location, v0, v1);
+ }
+ }
+}
+
+void GL_APIENTRY Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
+{
+ EVENT("(GLint location = %d, GLuint v0 = %u, GLuint v1 = %u, GLuint v2 = %u)", location, v0, v1,
+ v2);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Uniform3ui>(location, v0, v1, v2);
+
+ if (context->skipValidation() || ValidateUniform3ui(context, location, v0, v1, v2))
+ {
+ context->uniform3ui(location, v0, v1, v2);
+ }
+ }
+}
+
+void GL_APIENTRY Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+{
+ EVENT("(GLint location = %d, GLuint v0 = %u, GLuint v1 = %u, GLuint v2 = %u, GLuint v3 = %u)",
+ location, v0, v1, v2, v3);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Uniform4ui>(location, v0, v1, v2, v3);
+
+ if (context->skipValidation() || ValidateUniform4ui(context, location, v0, v1, v2, v3))
+ {
+ context->uniform4ui(location, v0, v1, v2, v3);
+ }
+ }
+}
+
+void GL_APIENTRY Uniform1uiv(GLint location, GLsizei count, const GLuint *value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLuint *value = 0x%0.8p)", location,
+ count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Uniform1uiv>(location, count, value);
+
+ if (context->skipValidation() || ValidateUniform1uiv(context, location, count, value))
+ {
+ context->uniform1uiv(location, count, value);
+ }
+ }
+}
+
+void GL_APIENTRY Uniform2uiv(GLint location, GLsizei count, const GLuint *value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLuint *value = 0x%0.8p)", location,
+ count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Uniform2uiv>(location, count, value);
+
+ if (context->skipValidation() || ValidateUniform2uiv(context, location, count, value))
+ {
+ context->uniform2uiv(location, count, value);
+ }
+ }
+}
+
+void GL_APIENTRY Uniform3uiv(GLint location, GLsizei count, const GLuint *value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLuint *value = 0x%0.8p)", location,
+ count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Uniform3uiv>(location, count, value);
+
+ if (context->skipValidation() || ValidateUniform3uiv(context, location, count, value))
+ {
+ context->uniform3uiv(location, count, value);
+ }
+ }
+}
+
+void GL_APIENTRY Uniform4uiv(GLint location, GLsizei count, const GLuint *value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLuint *value = 0x%0.8p)", location,
+ count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::Uniform4uiv>(location, count, value);
+
+ if (context->skipValidation() || ValidateUniform4uiv(context, location, count, value))
+ {
+ context->uniform4uiv(location, count, value);
+ }
+ }
+}
+
+void GL_APIENTRY ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
+{
+ EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint *value = 0x%0.8p)", buffer,
+ drawbuffer, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ClearBufferiv>(buffer, drawbuffer, value);
+
+ if (context->skipValidation() || ValidateClearBufferiv(context, buffer, drawbuffer, value))
+ {
+ context->clearBufferiv(buffer, drawbuffer, value);
+ }
+ }
+}
+
+void GL_APIENTRY ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
+{
+ EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint *value = 0x%0.8p)", buffer,
+ drawbuffer, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ClearBufferuiv>(buffer, drawbuffer, value);
+
+ if (context->skipValidation() || ValidateClearBufferuiv(context, buffer, drawbuffer, value))
+ {
+ context->clearBufferuiv(buffer, drawbuffer, value);
+ }
+ }
+}
+
+void GL_APIENTRY ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
+{
+ EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat *value = 0x%0.8p)", buffer,
+ drawbuffer, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ClearBufferfv>(buffer, drawbuffer, value);
+
+ if (context->skipValidation() || ValidateClearBufferfv(context, buffer, drawbuffer, value))
+ {
+ context->clearBufferfv(buffer, drawbuffer, value);
+ }
+ }
+}
+
+void GL_APIENTRY ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
+{
+ EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth = %f, GLint stencil = %d)",
+ buffer, drawbuffer, depth, stencil);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ClearBufferfi>(buffer, drawbuffer, depth, stencil);
+
+ if (context->skipValidation() ||
+ ValidateClearBufferfi(context, buffer, drawbuffer, depth, stencil))
+ {
+ context->clearBufferfi(buffer, drawbuffer, depth, stencil);
+ }
+ }
+}
+
+const GLubyte *GL_APIENTRY GetStringi(GLenum name, GLuint index)
+{
+ EVENT("(GLenum name = 0x%X, GLuint index = %u)", name, index);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetStringi>(name, index);
+
+ if (context->skipValidation() || ValidateGetStringi(context, name, index))
+ {
+ return context->getStringi(name, index);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::GetStringi, const GLubyte *>();
+}
+
+void GL_APIENTRY CopyBufferSubData(GLenum readTarget,
+ GLenum writeTarget,
+ GLintptr readOffset,
+ GLintptr writeOffset,
+ GLsizeiptr size)
+{
+ EVENT(
+ "(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X, GLintptr readOffset = %d, GLintptr "
+ "writeOffset = %d, GLsizeiptr size = %d)",
+ readTarget, writeTarget, readOffset, writeOffset, size);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ BufferBinding readTargetPacked = FromGLenum<BufferBinding>(readTarget);
+ BufferBinding writeTargetPacked = FromGLenum<BufferBinding>(writeTarget);
+ context->gatherParams<EntryPoint::CopyBufferSubData>(readTargetPacked, writeTargetPacked,
+ readOffset, writeOffset, size);
+
+ if (context->skipValidation() ||
+ ValidateCopyBufferSubData(context, readTargetPacked, writeTargetPacked, readOffset,
+ writeOffset, size))
+ {
+ context->copyBufferSubData(readTargetPacked, writeTargetPacked, readOffset, writeOffset,
+ size);
+ }
+ }
+}
+
+void GL_APIENTRY GetUniformIndices(GLuint program,
+ GLsizei uniformCount,
+ const GLchar *const *uniformNames,
+ GLuint *uniformIndices)
+{
+ EVENT(
+ "(GLuint program = %u, GLsizei uniformCount = %d, const GLchar *const*uniformNames = "
+ "0x%0.8p, GLuint *uniformIndices = 0x%0.8p)",
+ program, uniformCount, uniformNames, uniformIndices);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetUniformIndices>(program, uniformCount, uniformNames,
+ uniformIndices);
+
+ if (context->skipValidation() ||
+ ValidateGetUniformIndices(context, program, uniformCount, uniformNames, uniformIndices))
+ {
+ context->getUniformIndices(program, uniformCount, uniformNames, uniformIndices);
+ }
+ }
+}
+
+void GL_APIENTRY GetActiveUniformsiv(GLuint program,
+ GLsizei uniformCount,
+ const GLuint *uniformIndices,
+ GLenum pname,
+ GLint *params)
+{
+ EVENT(
+ "(GLuint program = %u, GLsizei uniformCount = %d, const GLuint *uniformIndices = 0x%0.8p, "
+ "GLenum pname = 0x%X, GLint *params = 0x%0.8p)",
+ program, uniformCount, uniformIndices, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetActiveUniformsiv>(program, uniformCount,
+ uniformIndices, pname, params);
+
+ if (context->skipValidation() || ValidateGetActiveUniformsiv(context, program, uniformCount,
+ uniformIndices, pname, params))
+ {
+ context->getActiveUniformsiv(program, uniformCount, uniformIndices, pname, params);
+ }
+ }
+}
+
+GLuint GL_APIENTRY GetUniformBlockIndex(GLuint program, const GLchar *uniformBlockName)
+{
+ EVENT("(GLuint program = %u, const GLchar *uniformBlockName = 0x%0.8p)", program,
+ uniformBlockName);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetUniformBlockIndex>(program, uniformBlockName);
+
+ if (context->skipValidation() ||
+ ValidateGetUniformBlockIndex(context, program, uniformBlockName))
+ {
+ return context->getUniformBlockIndex(program, uniformBlockName);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::GetUniformBlockIndex, GLuint>();
+}
+
+void GL_APIENTRY GetActiveUniformBlockiv(GLuint program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLint *params)
+{
+ EVENT(
+ "(GLuint program = %u, GLuint uniformBlockIndex = %u, GLenum pname = 0x%X, GLint *params = "
+ "0x%0.8p)",
+ program, uniformBlockIndex, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetActiveUniformBlockiv>(program, uniformBlockIndex,
+ pname, params);
+
+ if (context->skipValidation() ||
+ ValidateGetActiveUniformBlockiv(context, program, uniformBlockIndex, pname, params))
+ {
+ context->getActiveUniformBlockiv(program, uniformBlockIndex, pname, params);
+ }
+ }
+}
+
+void GL_APIENTRY GetActiveUniformBlockName(GLuint program,
+ GLuint uniformBlockIndex,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *uniformBlockName)
+{
+ EVENT(
+ "(GLuint program = %u, GLuint uniformBlockIndex = %u, GLsizei bufSize = %d, GLsizei "
+ "*length = 0x%0.8p, GLchar *uniformBlockName = 0x%0.8p)",
+ program, uniformBlockIndex, bufSize, length, uniformBlockName);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetActiveUniformBlockName>(
+ program, uniformBlockIndex, bufSize, length, uniformBlockName);
+
+ if (context->skipValidation() ||
+ ValidateGetActiveUniformBlockName(context, program, uniformBlockIndex, bufSize, length,
+ uniformBlockName))
+ {
+ context->getActiveUniformBlockName(program, uniformBlockIndex, bufSize, length,
+ uniformBlockName);
+ }
+ }
+}
+
+void GL_APIENTRY UniformBlockBinding(GLuint program,
+ GLuint uniformBlockIndex,
+ GLuint uniformBlockBinding)
+{
+ EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLuint uniformBlockBinding = %u)",
+ program, uniformBlockIndex, uniformBlockBinding);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::UniformBlockBinding>(program, uniformBlockIndex,
+ uniformBlockBinding);
+
+ if (context->skipValidation() ||
+ ValidateUniformBlockBinding(context, program, uniformBlockIndex, uniformBlockBinding))
+ {
+ context->uniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding);
+ }
+ }
+}
+
+void GL_APIENTRY DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount)
+{
+ EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instancecount = %d)",
+ mode, first, count, instancecount);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DrawArraysInstanced>(mode, first, count, instancecount);
+
+ if (context->skipValidation() ||
+ ValidateDrawArraysInstanced(context, mode, first, count, instancecount))
+ {
+ context->drawArraysInstanced(mode, first, count, instancecount);
+ }
+ }
+}
+
+void GL_APIENTRY DrawElementsInstanced(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei instancecount)
+{
+ EVENT(
+ "(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const void *indices = "
+ "0x%0.8p, GLsizei instancecount = %d)",
+ mode, count, type, indices, instancecount);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DrawElementsInstanced>(mode, count, type, indices,
+ instancecount);
+
+ if (context->skipValidation() ||
+ ValidateDrawElementsInstanced(context, mode, count, type, indices, instancecount))
+ {
+ context->drawElementsInstanced(mode, count, type, indices, instancecount);
+ }
+ }
+}
+
+GLsync GL_APIENTRY FenceSync(GLenum condition, GLbitfield flags)
+{
+ EVENT("(GLenum condition = 0x%X, GLbitfield flags = 0x%X)", condition, flags);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::FenceSync>(condition, flags);
+
+ if (context->skipValidation() || ValidateFenceSync(context, condition, flags))
+ {
+ return context->fenceSync(condition, flags);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::FenceSync, GLsync>();
+}
+
+GLboolean GL_APIENTRY IsSync(GLsync sync)
+{
+ EVENT("(GLsync sync = 0x%0.8p)", sync);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::IsSync>(sync);
+
+ if (context->skipValidation() || ValidateIsSync(context, sync))
+ {
+ return context->isSync(sync);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::IsSync, GLboolean>();
+}
+
+void GL_APIENTRY DeleteSync(GLsync sync)
+{
+ EVENT("(GLsync sync = 0x%0.8p)", sync);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DeleteSync>(sync);
+
+ if (context->skipValidation() || ValidateDeleteSync(context, sync))
+ {
+ context->deleteSync(sync);
+ }
+ }
+}
+
+GLenum GL_APIENTRY ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
+{
+ EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)", sync, flags,
+ timeout);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ClientWaitSync>(sync, flags, timeout);
+
+ if (context->skipValidation() || ValidateClientWaitSync(context, sync, flags, timeout))
+ {
+ return context->clientWaitSync(sync, flags, timeout);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::ClientWaitSync, GLenum>();
+}
+
+void GL_APIENTRY WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
+{
+ EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)", sync, flags,
+ timeout);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::WaitSync>(sync, flags, timeout);
+
+ if (context->skipValidation() || ValidateWaitSync(context, sync, flags, timeout))
+ {
+ context->waitSync(sync, flags, timeout);
+ }
+ }
+}
+
+void GL_APIENTRY GetInteger64v(GLenum pname, GLint64 *data)
+{
+ EVENT("(GLenum pname = 0x%X, GLint64 *data = 0x%0.8p)", pname, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetInteger64v>(pname, data);
+
+ if (context->skipValidation() || ValidateGetInteger64v(context, pname, data))
+ {
+ context->getInteger64v(pname, data);
+ }
+ }
+}
+
+void GL_APIENTRY
+GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values)
+{
+ EVENT(
+ "(GLsync sync = 0x%0.8p, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei *length = "
+ "0x%0.8p, GLint *values = 0x%0.8p)",
+ sync, pname, bufSize, length, values);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetSynciv>(sync, pname, bufSize, length, values);
+
+ if (context->skipValidation() ||
+ ValidateGetSynciv(context, sync, pname, bufSize, length, values))
+ {
+ context->getSynciv(sync, pname, bufSize, length, values);
+ }
+ }
+}
+
+void GL_APIENTRY GetInteger64i_v(GLenum target, GLuint index, GLint64 *data)
+{
+ EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint64 *data = 0x%0.8p)", target, index,
+ data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetInteger64i_v>(target, index, data);
+
+ if (context->skipValidation() || ValidateGetInteger64i_v(context, target, index, data))
+ {
+ context->getInteger64i_v(target, index, data);
+ }
+ }
+}
+
+void GL_APIENTRY GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64 *params = 0x%0.8p)", target, pname,
+ params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ BufferBinding targetPacked = FromGLenum<BufferBinding>(target);
+ context->gatherParams<EntryPoint::GetBufferParameteri64v>(targetPacked, pname, params);
+
+ if (context->skipValidation() ||
+ ValidateGetBufferParameteri64v(context, targetPacked, pname, params))
+ {
+ context->getBufferParameteri64v(targetPacked, pname, params);
+ }
+ }
+}
+
+void GL_APIENTRY GenSamplers(GLsizei count, GLuint *samplers)
+{
+ EVENT("(GLsizei count = %d, GLuint *samplers = 0x%0.8p)", count, samplers);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GenSamplers>(count, samplers);
+
+ if (context->skipValidation() || ValidateGenSamplers(context, count, samplers))
+ {
+ context->genSamplers(count, samplers);
+ }
+ }
+}
+
+void GL_APIENTRY DeleteSamplers(GLsizei count, const GLuint *samplers)
+{
+ EVENT("(GLsizei count = %d, const GLuint *samplers = 0x%0.8p)", count, samplers);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DeleteSamplers>(count, samplers);
+
+ if (context->skipValidation() || ValidateDeleteSamplers(context, count, samplers))
+ {
+ context->deleteSamplers(count, samplers);
+ }
+ }
+}
+
+GLboolean GL_APIENTRY IsSampler(GLuint sampler)
+{
+ EVENT("(GLuint sampler = %u)", sampler);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::IsSampler>(sampler);
+
+ if (context->skipValidation() || ValidateIsSampler(context, sampler))
+ {
+ return context->isSampler(sampler);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::IsSampler, GLboolean>();
+}
+
+void GL_APIENTRY BindSampler(GLuint unit, GLuint sampler)
+{
+ EVENT("(GLuint unit = %u, GLuint sampler = %u)", unit, sampler);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::BindSampler>(unit, sampler);
+
+ if (context->skipValidation() || ValidateBindSampler(context, unit, sampler))
+ {
+ context->bindSampler(unit, sampler);
+ }
+ }
+}
+
+void GL_APIENTRY SamplerParameteri(GLuint sampler, GLenum pname, GLint param)
+{
+ EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint param = %d)", sampler, pname, param);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::SamplerParameteri>(sampler, pname, param);
+
+ if (context->skipValidation() || ValidateSamplerParameteri(context, sampler, pname, param))
+ {
+ context->samplerParameteri(sampler, pname, param);
+ }
+ }
+}
+
+void GL_APIENTRY SamplerParameteriv(GLuint sampler, GLenum pname, const GLint *param)
+{
+ EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, const GLint *param = 0x%0.8p)", sampler,
+ pname, param);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::SamplerParameteriv>(sampler, pname, param);
+
+ if (context->skipValidation() || ValidateSamplerParameteriv(context, sampler, pname, param))
+ {
+ context->samplerParameteriv(sampler, pname, param);
+ }
+ }
+}
+
+void GL_APIENTRY SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
+{
+ EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLfloat param = %f)", sampler, pname, param);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::SamplerParameterf>(sampler, pname, param);
+
+ if (context->skipValidation() || ValidateSamplerParameterf(context, sampler, pname, param))
+ {
+ context->samplerParameterf(sampler, pname, param);
+ }
+ }
+}
+
+void GL_APIENTRY SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *param)
+{
+ EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, const GLfloat *param = 0x%0.8p)", sampler,
+ pname, param);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::SamplerParameterfv>(sampler, pname, param);
+
+ if (context->skipValidation() || ValidateSamplerParameterfv(context, sampler, pname, param))
+ {
+ context->samplerParameterfv(sampler, pname, param);
+ }
+ }
+}
+
+void GL_APIENTRY GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
+{
+ EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", sampler, pname,
+ params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetSamplerParameteriv>(sampler, pname, params);
+
+ if (context->skipValidation() ||
+ ValidateGetSamplerParameteriv(context, sampler, pname, params))
+ {
+ context->getSamplerParameteriv(sampler, pname, params);
+ }
+ }
+}
+
+void GL_APIENTRY GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params)
+{
+ EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLfloat *params = 0x%0.8p)", sampler, pname,
+ params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetSamplerParameterfv>(sampler, pname, params);
+
+ if (context->skipValidation() ||
+ ValidateGetSamplerParameterfv(context, sampler, pname, params))
+ {
+ context->getSamplerParameterfv(sampler, pname, params);
+ }
+ }
+}
+
+void GL_APIENTRY VertexAttribDivisor(GLuint index, GLuint divisor)
+{
+ EVENT("(GLuint index = %u, GLuint divisor = %u)", index, divisor);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::VertexAttribDivisor>(index, divisor);
+
+ if (context->skipValidation() || ValidateVertexAttribDivisor(context, index, divisor))
+ {
+ context->vertexAttribDivisor(index, divisor);
+ }
+ }
+}
+
+void GL_APIENTRY BindTransformFeedback(GLenum target, GLuint id)
+{
+ EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::BindTransformFeedback>(target, id);
+
+ if (context->skipValidation() || ValidateBindTransformFeedback(context, target, id))
+ {
+ context->bindTransformFeedback(target, id);
+ }
+ }
+}
+
+void GL_APIENTRY DeleteTransformFeedbacks(GLsizei n, const GLuint *ids)
+{
+ EVENT("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DeleteTransformFeedbacks>(n, ids);
+
+ if (context->skipValidation() || ValidateDeleteTransformFeedbacks(context, n, ids))
+ {
+ context->deleteTransformFeedbacks(n, ids);
+ }
+ }
+}
+
+void GL_APIENTRY GenTransformFeedbacks(GLsizei n, GLuint *ids)
+{
+ EVENT("(GLsizei n = %d, GLuint *ids = 0x%0.8p)", n, ids);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GenTransformFeedbacks>(n, ids);
+
+ if (context->skipValidation() || ValidateGenTransformFeedbacks(context, n, ids))
+ {
+ context->genTransformFeedbacks(n, ids);
+ }
+ }
+}
+
+GLboolean GL_APIENTRY IsTransformFeedback(GLuint id)
+{
+ EVENT("(GLuint id = %u)", id);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::IsTransformFeedback>(id);
+
+ if (context->skipValidation() || ValidateIsTransformFeedback(context, id))
+ {
+ return context->isTransformFeedback(id);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::IsTransformFeedback, GLboolean>();
+}
+
+void GL_APIENTRY PauseTransformFeedback()
+{
+ EVENT("()");
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::PauseTransformFeedback>();
+
+ if (context->skipValidation() || ValidatePauseTransformFeedback(context))
+ {
+ context->pauseTransformFeedback();
+ }
+ }
+}
+
+void GL_APIENTRY ResumeTransformFeedback()
+{
+ EVENT("()");
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ResumeTransformFeedback>();
+
+ if (context->skipValidation() || ValidateResumeTransformFeedback(context))
+ {
+ context->resumeTransformFeedback();
+ }
+ }
+}
+
+void GL_APIENTRY GetProgramBinary(GLuint program,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary)
+{
+ EVENT(
+ "(GLuint program = %u, GLsizei bufSize = %d, GLsizei *length = 0x%0.8p, GLenum "
+ "*binaryFormat = 0x%0.8p, void *binary = 0x%0.8p)",
+ program, bufSize, length, binaryFormat, binary);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetProgramBinary>(program, bufSize, length, binaryFormat,
+ binary);
+
+ if (context->skipValidation() ||
+ ValidateGetProgramBinary(context, program, bufSize, length, binaryFormat, binary))
+ {
+ context->getProgramBinary(program, bufSize, length, binaryFormat, binary);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramBinary(GLuint program,
+ GLenum binaryFormat,
+ const void *binary,
+ GLsizei length)
+{
+ EVENT(
+ "(GLuint program = %u, GLenum binaryFormat = 0x%X, const void *binary = 0x%0.8p, GLsizei "
+ "length = %d)",
+ program, binaryFormat, binary, length);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramBinary>(program, binaryFormat, binary, length);
+
+ if (context->skipValidation() ||
+ ValidateProgramBinary(context, program, binaryFormat, binary, length))
+ {
+ context->programBinary(program, binaryFormat, binary, length);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramParameteri(GLuint program, GLenum pname, GLint value)
+{
+ EVENT("(GLuint program = %u, GLenum pname = 0x%X, GLint value = %d)", program, pname, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramParameteri>(program, pname, value);
+
+ if (context->skipValidation() || ValidateProgramParameteri(context, program, pname, value))
+ {
+ context->programParameteri(program, pname, value);
+ }
+ }
+}
+
+void GL_APIENTRY InvalidateFramebuffer(GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum *attachments = 0x%0.8p)",
+ target, numAttachments, attachments);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::InvalidateFramebuffer>(target, numAttachments,
+ attachments);
+
+ if (context->skipValidation() ||
+ ValidateInvalidateFramebuffer(context, target, numAttachments, attachments))
+ {
+ context->invalidateFramebuffer(target, numAttachments, attachments);
+ }
+ }
+}
+
+void GL_APIENTRY InvalidateSubFramebuffer(GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum *attachments = 0x%0.8p, "
+ "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
+ target, numAttachments, attachments, x, y, width, height);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::InvalidateSubFramebuffer>(
+ target, numAttachments, attachments, x, y, width, height);
+
+ if (context->skipValidation() ||
+ ValidateInvalidateSubFramebuffer(context, target, numAttachments, attachments, x, y,
+ width, height))
+ {
+ context->invalidateSubFramebuffer(target, numAttachments, attachments, x, y, width,
+ height);
+ }
+ }
+}
+
+void GL_APIENTRY
+TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = "
+ "%d, GLsizei height = %d)",
+ target, levels, internalformat, width, height);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::TexStorage2D>(target, levels, internalformat, width,
+ height);
+
+ if (context->skipValidation() ||
+ ValidateTexStorage2D(context, target, levels, internalformat, width, height))
+ {
+ context->texStorage2D(target, levels, internalformat, width, height);
+ }
+ }
+}
+
+void GL_APIENTRY TexStorage3D(GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = "
+ "%d, GLsizei height = %d, GLsizei depth = %d)",
+ target, levels, internalformat, width, height, depth);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::TexStorage3D>(target, levels, internalformat, width,
+ height, depth);
+
+ if (context->skipValidation() ||
+ ValidateTexStorage3D(context, target, levels, internalformat, width, height, depth))
+ {
+ context->texStorage3D(target, levels, internalformat, width, height, depth);
+ }
+ }
+}
+
+void GL_APIENTRY GetInternalformativ(GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLint *params)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize "
+ "= %d, GLint *params = 0x%0.8p)",
+ target, internalformat, pname, bufSize, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetInternalformativ>(target, internalformat, pname,
+ bufSize, params);
+
+ if (context->skipValidation() ||
+ ValidateGetInternalformativ(context, target, internalformat, pname, bufSize, params))
+ {
+ context->getInternalformativ(target, internalformat, pname, bufSize, params);
+ }
+ }
+}
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_autogen.h b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_autogen.h
new file mode 100644
index 0000000000..e93dde96ed
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_autogen.h
@@ -0,0 +1,284 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// entry_points_gles_3_0_autogen.h:
+// Defines the GLES 3.0 entry points.
+
+#ifndef LIBGLESV2_ENTRYPOINTSGLES30_AUTOGEN_H_
+#define LIBGLESV2_ENTRYPOINTSGLES30_AUTOGEN_H_
+
+#include <GLES3/gl3.h>
+#include <export.h>
+
+namespace gl
+{
+ANGLE_EXPORT void GL_APIENTRY ReadBuffer(GLenum src);
+ANGLE_EXPORT void GL_APIENTRY DrawRangeElements(GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const void *indices);
+ANGLE_EXPORT void GL_APIENTRY TexImage3D(GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+ANGLE_EXPORT void GL_APIENTRY TexSubImage3D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+ANGLE_EXPORT void GL_APIENTRY CopyTexSubImage3D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+ANGLE_EXPORT void GL_APIENTRY CompressedTexImage3D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ const void *data);
+ANGLE_EXPORT void GL_APIENTRY CompressedTexSubImage3D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data);
+ANGLE_EXPORT void GL_APIENTRY GenQueries(GLsizei n, GLuint *ids);
+ANGLE_EXPORT void GL_APIENTRY DeleteQueries(GLsizei n, const GLuint *ids);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsQuery(GLuint id);
+ANGLE_EXPORT void GL_APIENTRY BeginQuery(GLenum target, GLuint id);
+ANGLE_EXPORT void GL_APIENTRY EndQuery(GLenum target);
+ANGLE_EXPORT void GL_APIENTRY GetQueryiv(GLenum target, GLenum pname, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params);
+ANGLE_EXPORT GLboolean GL_APIENTRY UnmapBuffer(GLenum target);
+ANGLE_EXPORT void GL_APIENTRY GetBufferPointerv(GLenum target, GLenum pname, void **params);
+ANGLE_EXPORT void GL_APIENTRY DrawBuffers(GLsizei n, const GLenum *bufs);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix2x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix3x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix2x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix4x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix3x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix4x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY BlitFramebuffer(GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter);
+ANGLE_EXPORT void GL_APIENTRY RenderbufferStorageMultisample(GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+ANGLE_EXPORT void GL_APIENTRY
+FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+ANGLE_EXPORT void *GL_APIENTRY MapBufferRange(GLenum target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access);
+ANGLE_EXPORT void GL_APIENTRY FlushMappedBufferRange(GLenum target,
+ GLintptr offset,
+ GLsizeiptr length);
+ANGLE_EXPORT void GL_APIENTRY BindVertexArray(GLuint array);
+ANGLE_EXPORT void GL_APIENTRY DeleteVertexArrays(GLsizei n, const GLuint *arrays);
+ANGLE_EXPORT void GL_APIENTRY GenVertexArrays(GLsizei n, GLuint *arrays);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsVertexArray(GLuint array);
+ANGLE_EXPORT void GL_APIENTRY GetIntegeri_v(GLenum target, GLuint index, GLint *data);
+ANGLE_EXPORT void GL_APIENTRY BeginTransformFeedback(GLenum primitiveMode);
+ANGLE_EXPORT void GL_APIENTRY EndTransformFeedback();
+ANGLE_EXPORT void GL_APIENTRY
+BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+ANGLE_EXPORT void GL_APIENTRY BindBufferBase(GLenum target, GLuint index, GLuint buffer);
+ANGLE_EXPORT void GL_APIENTRY TransformFeedbackVaryings(GLuint program,
+ GLsizei count,
+ const GLchar *const *varyings,
+ GLenum bufferMode);
+ANGLE_EXPORT void GL_APIENTRY GetTransformFeedbackVarying(GLuint program,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *size,
+ GLenum *type,
+ GLchar *name);
+ANGLE_EXPORT void GL_APIENTRY
+VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIiv(GLuint index, GLenum pname, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w);
+ANGLE_EXPORT void GL_APIENTRY
+VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribI4iv(GLuint index, const GLint *v);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribI4uiv(GLuint index, const GLuint *v);
+ANGLE_EXPORT void GL_APIENTRY GetUniformuiv(GLuint program, GLint location, GLuint *params);
+ANGLE_EXPORT GLint GL_APIENTRY GetFragDataLocation(GLuint program, const GLchar *name);
+ANGLE_EXPORT void GL_APIENTRY Uniform1ui(GLint location, GLuint v0);
+ANGLE_EXPORT void GL_APIENTRY Uniform2ui(GLint location, GLuint v0, GLuint v1);
+ANGLE_EXPORT void GL_APIENTRY Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2);
+ANGLE_EXPORT void GL_APIENTRY
+Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+ANGLE_EXPORT void GL_APIENTRY Uniform1uiv(GLint location, GLsizei count, const GLuint *value);
+ANGLE_EXPORT void GL_APIENTRY Uniform2uiv(GLint location, GLsizei count, const GLuint *value);
+ANGLE_EXPORT void GL_APIENTRY Uniform3uiv(GLint location, GLsizei count, const GLuint *value);
+ANGLE_EXPORT void GL_APIENTRY Uniform4uiv(GLint location, GLsizei count, const GLuint *value);
+ANGLE_EXPORT void GL_APIENTRY ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value);
+ANGLE_EXPORT void GL_APIENTRY ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value);
+ANGLE_EXPORT void GL_APIENTRY ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ClearBufferfi(GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil);
+ANGLE_EXPORT const GLubyte *GL_APIENTRY GetStringi(GLenum name, GLuint index);
+ANGLE_EXPORT void GL_APIENTRY CopyBufferSubData(GLenum readTarget,
+ GLenum writeTarget,
+ GLintptr readOffset,
+ GLintptr writeOffset,
+ GLsizeiptr size);
+ANGLE_EXPORT void GL_APIENTRY GetUniformIndices(GLuint program,
+ GLsizei uniformCount,
+ const GLchar *const *uniformNames,
+ GLuint *uniformIndices);
+ANGLE_EXPORT void GL_APIENTRY GetActiveUniformsiv(GLuint program,
+ GLsizei uniformCount,
+ const GLuint *uniformIndices,
+ GLenum pname,
+ GLint *params);
+ANGLE_EXPORT GLuint GL_APIENTRY GetUniformBlockIndex(GLuint program,
+ const GLchar *uniformBlockName);
+ANGLE_EXPORT void GL_APIENTRY GetActiveUniformBlockiv(GLuint program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetActiveUniformBlockName(GLuint program,
+ GLuint uniformBlockIndex,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *uniformBlockName);
+ANGLE_EXPORT void GL_APIENTRY UniformBlockBinding(GLuint program,
+ GLuint uniformBlockIndex,
+ GLuint uniformBlockBinding);
+ANGLE_EXPORT void GL_APIENTRY DrawArraysInstanced(GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instancecount);
+ANGLE_EXPORT void GL_APIENTRY DrawElementsInstanced(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei instancecount);
+ANGLE_EXPORT GLsync GL_APIENTRY FenceSync(GLenum condition, GLbitfield flags);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsSync(GLsync sync);
+ANGLE_EXPORT void GL_APIENTRY DeleteSync(GLsync sync);
+ANGLE_EXPORT GLenum GL_APIENTRY ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout);
+ANGLE_EXPORT void GL_APIENTRY WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout);
+ANGLE_EXPORT void GL_APIENTRY GetInteger64v(GLenum pname, GLint64 *data);
+ANGLE_EXPORT void GL_APIENTRY
+GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+ANGLE_EXPORT void GL_APIENTRY GetInteger64i_v(GLenum target, GLuint index, GLint64 *data);
+ANGLE_EXPORT void GL_APIENTRY GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params);
+ANGLE_EXPORT void GL_APIENTRY GenSamplers(GLsizei count, GLuint *samplers);
+ANGLE_EXPORT void GL_APIENTRY DeleteSamplers(GLsizei count, const GLuint *samplers);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsSampler(GLuint sampler);
+ANGLE_EXPORT void GL_APIENTRY BindSampler(GLuint unit, GLuint sampler);
+ANGLE_EXPORT void GL_APIENTRY SamplerParameteri(GLuint sampler, GLenum pname, GLint param);
+ANGLE_EXPORT void GL_APIENTRY SamplerParameteriv(GLuint sampler, GLenum pname, const GLint *param);
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param);
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterfv(GLuint sampler,
+ GLenum pname,
+ const GLfloat *param);
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribDivisor(GLuint index, GLuint divisor);
+ANGLE_EXPORT void GL_APIENTRY BindTransformFeedback(GLenum target, GLuint id);
+ANGLE_EXPORT void GL_APIENTRY DeleteTransformFeedbacks(GLsizei n, const GLuint *ids);
+ANGLE_EXPORT void GL_APIENTRY GenTransformFeedbacks(GLsizei n, GLuint *ids);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsTransformFeedback(GLuint id);
+ANGLE_EXPORT void GL_APIENTRY PauseTransformFeedback();
+ANGLE_EXPORT void GL_APIENTRY ResumeTransformFeedback();
+ANGLE_EXPORT void GL_APIENTRY GetProgramBinary(GLuint program,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary);
+ANGLE_EXPORT void GL_APIENTRY ProgramBinary(GLuint program,
+ GLenum binaryFormat,
+ const void *binary,
+ GLsizei length);
+ANGLE_EXPORT void GL_APIENTRY ProgramParameteri(GLuint program, GLenum pname, GLint value);
+ANGLE_EXPORT void GL_APIENTRY InvalidateFramebuffer(GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments);
+ANGLE_EXPORT void GL_APIENTRY InvalidateSubFramebuffer(GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+ANGLE_EXPORT void GL_APIENTRY
+TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+ANGLE_EXPORT void GL_APIENTRY TexStorage3D(GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+ANGLE_EXPORT void GL_APIENTRY GetInternalformativ(GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLint *params);
+} // namespace gl
+
+#endif // LIBGLESV2_ENTRYPOINTSGLES30_AUTOGEN_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.cpp
deleted file mode 100644
index 6f6983fd91..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-//
-// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// entry_points_gles_3_0_ext.cpp : Implements the GLES 3.0 extension entry points.
-
-#include "libGLESv2/entry_points_gles_3_0_ext.h"
-#include "libGLESv2/global_state.h"
-
-namespace gl
-{
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.h b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.h
deleted file mode 100644
index fec4c1298a..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.h
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// entry_points_gles_3_0_ext.h : Defines the GLES 3.0 extension entry points.
-
-#ifndef LIBGLESV2_ENTRYPOINTGLES30EXT_H_
-#define LIBGLESV2_ENTRYPOINTGLES30EXT_H_
-
-#include <GLES3/gl3.h>
-#include <GLES3/gl3ext.h>
-#include <export.h>
-
-namespace gl
-{
-
-// No GLES 3.0 extensions yet
-
-}
-
-#endif // LIBGLESV2_ENTRYPOINTGLES30EXT_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_1_autogen.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_1_autogen.cpp
new file mode 100644
index 0000000000..5d836872d6
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_1_autogen.cpp
@@ -0,0 +1,1430 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// entry_points_gles_3_1_autogen.cpp:
+// Defines the GLES 3.1 entry points.
+
+#include "libANGLE/Context.h"
+#include "libANGLE/validationES31.h"
+#include "libGLESv2/global_state.h"
+
+namespace gl
+{
+void GL_APIENTRY DispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z)
+{
+ EVENT("(GLuint num_groups_x = %u, GLuint num_groups_y = %u, GLuint num_groups_z = %u)",
+ num_groups_x, num_groups_y, num_groups_z);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DispatchCompute>(num_groups_x, num_groups_y,
+ num_groups_z);
+
+ if (context->skipValidation() ||
+ ValidateDispatchCompute(context, num_groups_x, num_groups_y, num_groups_z))
+ {
+ context->dispatchCompute(num_groups_x, num_groups_y, num_groups_z);
+ }
+ }
+}
+
+void GL_APIENTRY DispatchComputeIndirect(GLintptr indirect)
+{
+ EVENT("(GLintptr indirect = %d)", indirect);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DispatchComputeIndirect>(indirect);
+
+ if (context->skipValidation() || ValidateDispatchComputeIndirect(context, indirect))
+ {
+ context->dispatchComputeIndirect(indirect);
+ }
+ }
+}
+
+void GL_APIENTRY DrawArraysIndirect(GLenum mode, const void *indirect)
+{
+ EVENT("(GLenum mode = 0x%X, const void *indirect = 0x%0.8p)", mode, indirect);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DrawArraysIndirect>(mode, indirect);
+
+ if (context->skipValidation() || ValidateDrawArraysIndirect(context, mode, indirect))
+ {
+ context->drawArraysIndirect(mode, indirect);
+ }
+ }
+}
+
+void GL_APIENTRY DrawElementsIndirect(GLenum mode, GLenum type, const void *indirect)
+{
+ EVENT("(GLenum mode = 0x%X, GLenum type = 0x%X, const void *indirect = 0x%0.8p)", mode, type,
+ indirect);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DrawElementsIndirect>(mode, type, indirect);
+
+ if (context->skipValidation() ||
+ ValidateDrawElementsIndirect(context, mode, type, indirect))
+ {
+ context->drawElementsIndirect(mode, type, indirect);
+ }
+ }
+}
+
+void GL_APIENTRY FramebufferParameteri(GLenum target, GLenum pname, GLint param)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::FramebufferParameteri>(target, pname, param);
+
+ if (context->skipValidation() ||
+ ValidateFramebufferParameteri(context, target, pname, param))
+ {
+ context->framebufferParameteri(target, pname, param);
+ }
+ }
+}
+
+void GL_APIENTRY GetFramebufferParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname,
+ params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetFramebufferParameteriv>(target, pname, params);
+
+ if (context->skipValidation() ||
+ ValidateGetFramebufferParameteriv(context, target, pname, params))
+ {
+ context->getFramebufferParameteriv(target, pname, params);
+ }
+ }
+}
+
+void GL_APIENTRY GetProgramInterfaceiv(GLuint program,
+ GLenum programInterface,
+ GLenum pname,
+ GLint *params)
+{
+ EVENT(
+ "(GLuint program = %u, GLenum programInterface = 0x%X, GLenum pname = 0x%X, GLint *params "
+ "= 0x%0.8p)",
+ program, programInterface, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetProgramInterfaceiv>(program, programInterface, pname,
+ params);
+
+ if (context->skipValidation() ||
+ ValidateGetProgramInterfaceiv(context, program, programInterface, pname, params))
+ {
+ context->getProgramInterfaceiv(program, programInterface, pname, params);
+ }
+ }
+}
+
+GLuint GL_APIENTRY GetProgramResourceIndex(GLuint program,
+ GLenum programInterface,
+ const GLchar *name)
+{
+ EVENT("(GLuint program = %u, GLenum programInterface = 0x%X, const GLchar *name = 0x%0.8p)",
+ program, programInterface, name);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetProgramResourceIndex>(program, programInterface, name);
+
+ if (context->skipValidation() ||
+ ValidateGetProgramResourceIndex(context, program, programInterface, name))
+ {
+ return context->getProgramResourceIndex(program, programInterface, name);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::GetProgramResourceIndex, GLuint>();
+}
+
+void GL_APIENTRY GetProgramResourceName(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name)
+{
+ EVENT(
+ "(GLuint program = %u, GLenum programInterface = 0x%X, GLuint index = %u, GLsizei bufSize "
+ "= %d, GLsizei *length = 0x%0.8p, GLchar *name = 0x%0.8p)",
+ program, programInterface, index, bufSize, length, name);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetProgramResourceName>(program, programInterface, index,
+ bufSize, length, name);
+
+ if (context->skipValidation() ||
+ ValidateGetProgramResourceName(context, program, programInterface, index, bufSize,
+ length, name))
+ {
+ context->getProgramResourceName(program, programInterface, index, bufSize, length,
+ name);
+ }
+ }
+}
+
+void GL_APIENTRY GetProgramResourceiv(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum *props,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ EVENT(
+ "(GLuint program = %u, GLenum programInterface = 0x%X, GLuint index = %u, GLsizei "
+ "propCount = %d, const GLenum *props = 0x%0.8p, GLsizei bufSize = %d, GLsizei *length = "
+ "0x%0.8p, GLint *params = 0x%0.8p)",
+ program, programInterface, index, propCount, props, bufSize, length, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetProgramResourceiv>(
+ program, programInterface, index, propCount, props, bufSize, length, params);
+
+ if (context->skipValidation() ||
+ ValidateGetProgramResourceiv(context, program, programInterface, index, propCount,
+ props, bufSize, length, params))
+ {
+ context->getProgramResourceiv(program, programInterface, index, propCount, props,
+ bufSize, length, params);
+ }
+ }
+}
+
+GLint GL_APIENTRY GetProgramResourceLocation(GLuint program,
+ GLenum programInterface,
+ const GLchar *name)
+{
+ EVENT("(GLuint program = %u, GLenum programInterface = 0x%X, const GLchar *name = 0x%0.8p)",
+ program, programInterface, name);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetProgramResourceLocation>(program, programInterface,
+ name);
+
+ if (context->skipValidation() ||
+ ValidateGetProgramResourceLocation(context, program, programInterface, name))
+ {
+ return context->getProgramResourceLocation(program, programInterface, name);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::GetProgramResourceLocation, GLint>();
+}
+
+void GL_APIENTRY UseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program)
+{
+ EVENT("(GLuint pipeline = %u, GLbitfield stages = 0x%X, GLuint program = %u)", pipeline, stages,
+ program);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::UseProgramStages>(pipeline, stages, program);
+
+ if (context->skipValidation() ||
+ ValidateUseProgramStages(context, pipeline, stages, program))
+ {
+ context->useProgramStages(pipeline, stages, program);
+ }
+ }
+}
+
+void GL_APIENTRY ActiveShaderProgram(GLuint pipeline, GLuint program)
+{
+ EVENT("(GLuint pipeline = %u, GLuint program = %u)", pipeline, program);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ActiveShaderProgram>(pipeline, program);
+
+ if (context->skipValidation() || ValidateActiveShaderProgram(context, pipeline, program))
+ {
+ context->activeShaderProgram(pipeline, program);
+ }
+ }
+}
+
+GLuint GL_APIENTRY CreateShaderProgramv(GLenum type, GLsizei count, const GLchar *const *strings)
+{
+ EVENT("(GLenum type = 0x%X, GLsizei count = %d, const GLchar *const*strings = 0x%0.8p)", type,
+ count, strings);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::CreateShaderProgramv>(type, count, strings);
+
+ if (context->skipValidation() ||
+ ValidateCreateShaderProgramv(context, type, count, strings))
+ {
+ return context->createShaderProgramv(type, count, strings);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::CreateShaderProgramv, GLuint>();
+}
+
+void GL_APIENTRY BindProgramPipeline(GLuint pipeline)
+{
+ EVENT("(GLuint pipeline = %u)", pipeline);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::BindProgramPipeline>(pipeline);
+
+ if (context->skipValidation() || ValidateBindProgramPipeline(context, pipeline))
+ {
+ context->bindProgramPipeline(pipeline);
+ }
+ }
+}
+
+void GL_APIENTRY DeleteProgramPipelines(GLsizei n, const GLuint *pipelines)
+{
+ EVENT("(GLsizei n = %d, const GLuint *pipelines = 0x%0.8p)", n, pipelines);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::DeleteProgramPipelines>(n, pipelines);
+
+ if (context->skipValidation() || ValidateDeleteProgramPipelines(context, n, pipelines))
+ {
+ context->deleteProgramPipelines(n, pipelines);
+ }
+ }
+}
+
+void GL_APIENTRY GenProgramPipelines(GLsizei n, GLuint *pipelines)
+{
+ EVENT("(GLsizei n = %d, GLuint *pipelines = 0x%0.8p)", n, pipelines);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GenProgramPipelines>(n, pipelines);
+
+ if (context->skipValidation() || ValidateGenProgramPipelines(context, n, pipelines))
+ {
+ context->genProgramPipelines(n, pipelines);
+ }
+ }
+}
+
+GLboolean GL_APIENTRY IsProgramPipeline(GLuint pipeline)
+{
+ EVENT("(GLuint pipeline = %u)", pipeline);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::IsProgramPipeline>(pipeline);
+
+ if (context->skipValidation() || ValidateIsProgramPipeline(context, pipeline))
+ {
+ return context->isProgramPipeline(pipeline);
+ }
+ }
+
+ return GetDefaultReturnValue<EntryPoint::IsProgramPipeline, GLboolean>();
+}
+
+void GL_APIENTRY GetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *params)
+{
+ EVENT("(GLuint pipeline = %u, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", pipeline, pname,
+ params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetProgramPipelineiv>(pipeline, pname, params);
+
+ if (context->skipValidation() ||
+ ValidateGetProgramPipelineiv(context, pipeline, pname, params))
+ {
+ context->getProgramPipelineiv(pipeline, pname, params);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniform1i(GLuint program, GLint location, GLint v0)
+{
+ EVENT("(GLuint program = %u, GLint location = %d, GLint v0 = %d)", program, location, v0);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniform1i>(program, location, v0);
+
+ if (context->skipValidation() || ValidateProgramUniform1i(context, program, location, v0))
+ {
+ context->programUniform1i(program, location, v0);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniform2i(GLuint program, GLint location, GLint v0, GLint v1)
+{
+ EVENT("(GLuint program = %u, GLint location = %d, GLint v0 = %d, GLint v1 = %d)", program,
+ location, v0, v1);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniform2i>(program, location, v0, v1);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniform2i(context, program, location, v0, v1))
+ {
+ context->programUniform2i(program, location, v0, v1);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniform3i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2)
+{
+ EVENT("(GLuint program = %u, GLint location = %d, GLint v0 = %d, GLint v1 = %d, GLint v2 = %d)",
+ program, location, v0, v1, v2);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniform3i>(program, location, v0, v1, v2);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniform3i(context, program, location, v0, v1, v2))
+ {
+ context->programUniform3i(program, location, v0, v1, v2);
+ }
+ }
+}
+
+void GL_APIENTRY
+ProgramUniform4i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLint v0 = %d, GLint v1 = %d, GLint v2 = %d, "
+ "GLint v3 = %d)",
+ program, location, v0, v1, v2, v3);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniform4i>(program, location, v0, v1, v2, v3);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniform4i(context, program, location, v0, v1, v2, v3))
+ {
+ context->programUniform4i(program, location, v0, v1, v2, v3);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniform1ui(GLuint program, GLint location, GLuint v0)
+{
+ EVENT("(GLuint program = %u, GLint location = %d, GLuint v0 = %u)", program, location, v0);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniform1ui>(program, location, v0);
+
+ if (context->skipValidation() || ValidateProgramUniform1ui(context, program, location, v0))
+ {
+ context->programUniform1ui(program, location, v0);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniform2ui(GLuint program, GLint location, GLuint v0, GLuint v1)
+{
+ EVENT("(GLuint program = %u, GLint location = %d, GLuint v0 = %u, GLuint v1 = %u)", program,
+ location, v0, v1);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniform2ui>(program, location, v0, v1);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniform2ui(context, program, location, v0, v1))
+ {
+ context->programUniform2ui(program, location, v0, v1);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniform3ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLuint v0 = %u, GLuint v1 = %u, GLuint v2 = "
+ "%u)",
+ program, location, v0, v1, v2);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniform3ui>(program, location, v0, v1, v2);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniform3ui(context, program, location, v0, v1, v2))
+ {
+ context->programUniform3ui(program, location, v0, v1, v2);
+ }
+ }
+}
+
+void GL_APIENTRY
+ProgramUniform4ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLuint v0 = %u, GLuint v1 = %u, GLuint v2 = "
+ "%u, GLuint v3 = %u)",
+ program, location, v0, v1, v2, v3);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniform4ui>(program, location, v0, v1, v2, v3);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniform4ui(context, program, location, v0, v1, v2, v3))
+ {
+ context->programUniform4ui(program, location, v0, v1, v2, v3);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniform1f(GLuint program, GLint location, GLfloat v0)
+{
+ EVENT("(GLuint program = %u, GLint location = %d, GLfloat v0 = %f)", program, location, v0);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniform1f>(program, location, v0);
+
+ if (context->skipValidation() || ValidateProgramUniform1f(context, program, location, v0))
+ {
+ context->programUniform1f(program, location, v0);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniform2f(GLuint program, GLint location, GLfloat v0, GLfloat v1)
+{
+ EVENT("(GLuint program = %u, GLint location = %d, GLfloat v0 = %f, GLfloat v1 = %f)", program,
+ location, v0, v1);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniform2f>(program, location, v0, v1);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniform2f(context, program, location, v0, v1))
+ {
+ context->programUniform2f(program, location, v0, v1);
+ }
+ }
+}
+
+void GL_APIENTRY
+ProgramUniform3f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLfloat v0 = %f, GLfloat v1 = %f, GLfloat v2 = "
+ "%f)",
+ program, location, v0, v1, v2);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniform3f>(program, location, v0, v1, v2);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniform3f(context, program, location, v0, v1, v2))
+ {
+ context->programUniform3f(program, location, v0, v1, v2);
+ }
+ }
+}
+
+void GL_APIENTRY
+ProgramUniform4f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLfloat v0 = %f, GLfloat v1 = %f, GLfloat v2 = "
+ "%f, GLfloat v3 = %f)",
+ program, location, v0, v1, v2, v3);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniform4f>(program, location, v0, v1, v2, v3);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniform4f(context, program, location, v0, v1, v2, v3))
+ {
+ context->programUniform4f(program, location, v0, v1, v2, v3);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniform1iv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLint *value)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLsizei count = %d, const GLint *value = "
+ "0x%0.8p)",
+ program, location, count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniform1iv>(program, location, count, value);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniform1iv(context, program, location, count, value))
+ {
+ context->programUniform1iv(program, location, count, value);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniform2iv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLint *value)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLsizei count = %d, const GLint *value = "
+ "0x%0.8p)",
+ program, location, count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniform2iv>(program, location, count, value);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniform2iv(context, program, location, count, value))
+ {
+ context->programUniform2iv(program, location, count, value);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniform3iv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLint *value)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLsizei count = %d, const GLint *value = "
+ "0x%0.8p)",
+ program, location, count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniform3iv>(program, location, count, value);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniform3iv(context, program, location, count, value))
+ {
+ context->programUniform3iv(program, location, count, value);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniform4iv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLint *value)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLsizei count = %d, const GLint *value = "
+ "0x%0.8p)",
+ program, location, count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniform4iv>(program, location, count, value);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniform4iv(context, program, location, count, value))
+ {
+ context->programUniform4iv(program, location, count, value);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniform1uiv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLuint *value)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLsizei count = %d, const GLuint *value = "
+ "0x%0.8p)",
+ program, location, count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniform1uiv>(program, location, count, value);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniform1uiv(context, program, location, count, value))
+ {
+ context->programUniform1uiv(program, location, count, value);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniform2uiv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLuint *value)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLsizei count = %d, const GLuint *value = "
+ "0x%0.8p)",
+ program, location, count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniform2uiv>(program, location, count, value);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniform2uiv(context, program, location, count, value))
+ {
+ context->programUniform2uiv(program, location, count, value);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniform3uiv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLuint *value)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLsizei count = %d, const GLuint *value = "
+ "0x%0.8p)",
+ program, location, count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniform3uiv>(program, location, count, value);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniform3uiv(context, program, location, count, value))
+ {
+ context->programUniform3uiv(program, location, count, value);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniform4uiv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLuint *value)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLsizei count = %d, const GLuint *value = "
+ "0x%0.8p)",
+ program, location, count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniform4uiv>(program, location, count, value);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniform4uiv(context, program, location, count, value))
+ {
+ context->programUniform4uiv(program, location, count, value);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniform1fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLfloat *value)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLsizei count = %d, const GLfloat *value = "
+ "0x%0.8p)",
+ program, location, count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniform1fv>(program, location, count, value);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniform1fv(context, program, location, count, value))
+ {
+ context->programUniform1fv(program, location, count, value);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniform2fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLfloat *value)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLsizei count = %d, const GLfloat *value = "
+ "0x%0.8p)",
+ program, location, count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniform2fv>(program, location, count, value);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniform2fv(context, program, location, count, value))
+ {
+ context->programUniform2fv(program, location, count, value);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniform3fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLfloat *value)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLsizei count = %d, const GLfloat *value = "
+ "0x%0.8p)",
+ program, location, count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniform3fv>(program, location, count, value);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniform3fv(context, program, location, count, value))
+ {
+ context->programUniform3fv(program, location, count, value);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniform4fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLfloat *value)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLsizei count = %d, const GLfloat *value = "
+ "0x%0.8p)",
+ program, location, count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniform4fv>(program, location, count, value);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniform4fv(context, program, location, count, value))
+ {
+ context->programUniform4fv(program, location, count, value);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniformMatrix2fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, "
+ "const GLfloat *value = 0x%0.8p)",
+ program, location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniformMatrix2fv>(program, location, count,
+ transpose, value);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniformMatrix2fv(context, program, location, count, transpose, value))
+ {
+ context->programUniformMatrix2fv(program, location, count, transpose, value);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniformMatrix3fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, "
+ "const GLfloat *value = 0x%0.8p)",
+ program, location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniformMatrix3fv>(program, location, count,
+ transpose, value);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniformMatrix3fv(context, program, location, count, transpose, value))
+ {
+ context->programUniformMatrix3fv(program, location, count, transpose, value);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniformMatrix4fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, "
+ "const GLfloat *value = 0x%0.8p)",
+ program, location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniformMatrix4fv>(program, location, count,
+ transpose, value);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniformMatrix4fv(context, program, location, count, transpose, value))
+ {
+ context->programUniformMatrix4fv(program, location, count, transpose, value);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniformMatrix2x3fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, "
+ "const GLfloat *value = 0x%0.8p)",
+ program, location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniformMatrix2x3fv>(program, location, count,
+ transpose, value);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniformMatrix2x3fv(context, program, location, count, transpose, value))
+ {
+ context->programUniformMatrix2x3fv(program, location, count, transpose, value);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniformMatrix3x2fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, "
+ "const GLfloat *value = 0x%0.8p)",
+ program, location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniformMatrix3x2fv>(program, location, count,
+ transpose, value);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniformMatrix3x2fv(context, program, location, count, transpose, value))
+ {
+ context->programUniformMatrix3x2fv(program, location, count, transpose, value);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniformMatrix2x4fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, "
+ "const GLfloat *value = 0x%0.8p)",
+ program, location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniformMatrix2x4fv>(program, location, count,
+ transpose, value);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniformMatrix2x4fv(context, program, location, count, transpose, value))
+ {
+ context->programUniformMatrix2x4fv(program, location, count, transpose, value);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniformMatrix4x2fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, "
+ "const GLfloat *value = 0x%0.8p)",
+ program, location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniformMatrix4x2fv>(program, location, count,
+ transpose, value);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniformMatrix4x2fv(context, program, location, count, transpose, value))
+ {
+ context->programUniformMatrix4x2fv(program, location, count, transpose, value);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniformMatrix3x4fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, "
+ "const GLfloat *value = 0x%0.8p)",
+ program, location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniformMatrix3x4fv>(program, location, count,
+ transpose, value);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniformMatrix3x4fv(context, program, location, count, transpose, value))
+ {
+ context->programUniformMatrix3x4fv(program, location, count, transpose, value);
+ }
+ }
+}
+
+void GL_APIENTRY ProgramUniformMatrix4x3fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ EVENT(
+ "(GLuint program = %u, GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, "
+ "const GLfloat *value = 0x%0.8p)",
+ program, location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ProgramUniformMatrix4x3fv>(program, location, count,
+ transpose, value);
+
+ if (context->skipValidation() ||
+ ValidateProgramUniformMatrix4x3fv(context, program, location, count, transpose, value))
+ {
+ context->programUniformMatrix4x3fv(program, location, count, transpose, value);
+ }
+ }
+}
+
+void GL_APIENTRY ValidateProgramPipeline(GLuint pipeline)
+{
+ EVENT("(GLuint pipeline = %u)", pipeline);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::ValidateProgramPipeline>(pipeline);
+
+ if (context->skipValidation() || ValidateValidateProgramPipeline(context, pipeline))
+ {
+ context->validateProgramPipeline(pipeline);
+ }
+ }
+}
+
+void GL_APIENTRY GetProgramPipelineInfoLog(GLuint pipeline,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *infoLog)
+{
+ EVENT(
+ "(GLuint pipeline = %u, GLsizei bufSize = %d, GLsizei *length = 0x%0.8p, GLchar *infoLog = "
+ "0x%0.8p)",
+ pipeline, bufSize, length, infoLog);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetProgramPipelineInfoLog>(pipeline, bufSize, length,
+ infoLog);
+
+ if (context->skipValidation() ||
+ ValidateGetProgramPipelineInfoLog(context, pipeline, bufSize, length, infoLog))
+ {
+ context->getProgramPipelineInfoLog(pipeline, bufSize, length, infoLog);
+ }
+ }
+}
+
+void GL_APIENTRY BindImageTexture(GLuint unit,
+ GLuint texture,
+ GLint level,
+ GLboolean layered,
+ GLint layer,
+ GLenum access,
+ GLenum format)
+{
+ EVENT(
+ "(GLuint unit = %u, GLuint texture = %u, GLint level = %d, GLboolean layered = %u, GLint "
+ "layer = %d, GLenum access = 0x%X, GLenum format = 0x%X)",
+ unit, texture, level, layered, layer, access, format);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::BindImageTexture>(unit, texture, level, layered, layer,
+ access, format);
+
+ if (context->skipValidation() ||
+ ValidateBindImageTexture(context, unit, texture, level, layered, layer, access, format))
+ {
+ context->bindImageTexture(unit, texture, level, layered, layer, access, format);
+ }
+ }
+}
+
+void GL_APIENTRY GetBooleani_v(GLenum target, GLuint index, GLboolean *data)
+{
+ EVENT("(GLenum target = 0x%X, GLuint index = %u, GLboolean *data = 0x%0.8p)", target, index,
+ data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetBooleani_v>(target, index, data);
+
+ if (context->skipValidation() || ValidateGetBooleani_v(context, target, index, data))
+ {
+ context->getBooleani_v(target, index, data);
+ }
+ }
+}
+
+void GL_APIENTRY MemoryBarrier(GLbitfield barriers)
+{
+ EVENT("(GLbitfield barriers = 0x%X)", barriers);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::MemoryBarrier>(barriers);
+
+ if (context->skipValidation() || ValidateMemoryBarrier(context, barriers))
+ {
+ context->memoryBarrier(barriers);
+ }
+ }
+}
+
+void GL_APIENTRY MemoryBarrierByRegion(GLbitfield barriers)
+{
+ EVENT("(GLbitfield barriers = 0x%X)", barriers);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::MemoryBarrierByRegion>(barriers);
+
+ if (context->skipValidation() || ValidateMemoryBarrierByRegion(context, barriers))
+ {
+ context->memoryBarrierByRegion(barriers);
+ }
+ }
+}
+
+void GL_APIENTRY TexStorage2DMultisample(GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedsamplelocations)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width "
+ "= %d, GLsizei height = %d, GLboolean fixedsamplelocations = %u)",
+ target, samples, internalformat, width, height, fixedsamplelocations);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::TexStorage2DMultisample>(
+ target, samples, internalformat, width, height, fixedsamplelocations);
+
+ if (context->skipValidation() ||
+ ValidateTexStorage2DMultisample(context, target, samples, internalformat, width, height,
+ fixedsamplelocations))
+ {
+ context->texStorage2DMultisample(target, samples, internalformat, width, height,
+ fixedsamplelocations);
+ }
+ }
+}
+
+void GL_APIENTRY GetMultisamplefv(GLenum pname, GLuint index, GLfloat *val)
+{
+ EVENT("(GLenum pname = 0x%X, GLuint index = %u, GLfloat *val = 0x%0.8p)", pname, index, val);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetMultisamplefv>(pname, index, val);
+
+ if (context->skipValidation() || ValidateGetMultisamplefv(context, pname, index, val))
+ {
+ context->getMultisamplefv(pname, index, val);
+ }
+ }
+}
+
+void GL_APIENTRY SampleMaski(GLuint maskNumber, GLbitfield mask)
+{
+ EVENT("(GLuint maskNumber = %u, GLbitfield mask = 0x%X)", maskNumber, mask);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::SampleMaski>(maskNumber, mask);
+
+ if (context->skipValidation() || ValidateSampleMaski(context, maskNumber, mask))
+ {
+ context->sampleMaski(maskNumber, mask);
+ }
+ }
+}
+
+void GL_APIENTRY GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params)
+{
+ EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)",
+ target, level, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetTexLevelParameteriv>(target, level, pname, params);
+
+ if (context->skipValidation() ||
+ ValidateGetTexLevelParameteriv(context, target, level, pname, params))
+ {
+ context->getTexLevelParameteriv(target, level, pname, params);
+ }
+ }
+}
+
+void GL_APIENTRY GetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat *params)
+{
+ EVENT(
+ "(GLenum target = 0x%X, GLint level = %d, GLenum pname = 0x%X, GLfloat *params = 0x%0.8p)",
+ target, level, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::GetTexLevelParameterfv>(target, level, pname, params);
+
+ if (context->skipValidation() ||
+ ValidateGetTexLevelParameterfv(context, target, level, pname, params))
+ {
+ context->getTexLevelParameterfv(target, level, pname, params);
+ }
+ }
+}
+
+void GL_APIENTRY BindVertexBuffer(GLuint bindingindex,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizei stride)
+{
+ EVENT(
+ "(GLuint bindingindex = %u, GLuint buffer = %u, GLintptr offset = %d, GLsizei stride = %d)",
+ bindingindex, buffer, offset, stride);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::BindVertexBuffer>(bindingindex, buffer, offset, stride);
+
+ if (context->skipValidation() ||
+ ValidateBindVertexBuffer(context, bindingindex, buffer, offset, stride))
+ {
+ context->bindVertexBuffer(bindingindex, buffer, offset, stride);
+ }
+ }
+}
+
+void GL_APIENTRY VertexAttribFormat(GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLuint relativeoffset)
+{
+ EVENT(
+ "(GLuint attribindex = %u, GLint size = %d, GLenum type = 0x%X, GLboolean normalized = %u, "
+ "GLuint relativeoffset = %u)",
+ attribindex, size, type, normalized, relativeoffset);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::VertexAttribFormat>(attribindex, size, type, normalized,
+ relativeoffset);
+
+ if (context->skipValidation() ||
+ ValidateVertexAttribFormat(context, attribindex, size, type, normalized,
+ relativeoffset))
+ {
+ context->vertexAttribFormat(attribindex, size, type, normalized, relativeoffset);
+ }
+ }
+}
+
+void GL_APIENTRY VertexAttribIFormat(GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLuint relativeoffset)
+{
+ EVENT(
+ "(GLuint attribindex = %u, GLint size = %d, GLenum type = 0x%X, GLuint relativeoffset = "
+ "%u)",
+ attribindex, size, type, relativeoffset);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::VertexAttribIFormat>(attribindex, size, type,
+ relativeoffset);
+
+ if (context->skipValidation() ||
+ ValidateVertexAttribIFormat(context, attribindex, size, type, relativeoffset))
+ {
+ context->vertexAttribIFormat(attribindex, size, type, relativeoffset);
+ }
+ }
+}
+
+void GL_APIENTRY VertexAttribBinding(GLuint attribindex, GLuint bindingindex)
+{
+ EVENT("(GLuint attribindex = %u, GLuint bindingindex = %u)", attribindex, bindingindex);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::VertexAttribBinding>(attribindex, bindingindex);
+
+ if (context->skipValidation() ||
+ ValidateVertexAttribBinding(context, attribindex, bindingindex))
+ {
+ context->vertexAttribBinding(attribindex, bindingindex);
+ }
+ }
+}
+
+void GL_APIENTRY VertexBindingDivisor(GLuint bindingindex, GLuint divisor)
+{
+ EVENT("(GLuint bindingindex = %u, GLuint divisor = %u)", bindingindex, divisor);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->gatherParams<EntryPoint::VertexBindingDivisor>(bindingindex, divisor);
+
+ if (context->skipValidation() ||
+ ValidateVertexBindingDivisor(context, bindingindex, divisor))
+ {
+ context->vertexBindingDivisor(bindingindex, divisor);
+ }
+ }
+}
+} // namespace gl
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_1_autogen.h b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_1_autogen.h
new file mode 100644
index 0000000000..e11d5a10bf
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_1_autogen.h
@@ -0,0 +1,228 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// entry_points_gles_3_1_autogen.h:
+// Defines the GLES 3.1 entry points.
+
+#ifndef LIBGLESV2_ENTRYPOINTSGLES31_AUTOGEN_H_
+#define LIBGLESV2_ENTRYPOINTSGLES31_AUTOGEN_H_
+
+#include <GLES3/gl31.h>
+#include <export.h>
+
+#include "common/platform.h"
+
+namespace gl
+{
+ANGLE_EXPORT void GL_APIENTRY DispatchCompute(GLuint num_groups_x,
+ GLuint num_groups_y,
+ GLuint num_groups_z);
+ANGLE_EXPORT void GL_APIENTRY DispatchComputeIndirect(GLintptr indirect);
+ANGLE_EXPORT void GL_APIENTRY DrawArraysIndirect(GLenum mode, const void *indirect);
+ANGLE_EXPORT void GL_APIENTRY DrawElementsIndirect(GLenum mode, GLenum type, const void *indirect);
+ANGLE_EXPORT void GL_APIENTRY FramebufferParameteri(GLenum target, GLenum pname, GLint param);
+ANGLE_EXPORT void GL_APIENTRY GetFramebufferParameteriv(GLenum target, GLenum pname, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetProgramInterfaceiv(GLuint program,
+ GLenum programInterface,
+ GLenum pname,
+ GLint *params);
+ANGLE_EXPORT GLuint GL_APIENTRY GetProgramResourceIndex(GLuint program,
+ GLenum programInterface,
+ const GLchar *name);
+ANGLE_EXPORT void GL_APIENTRY GetProgramResourceName(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name);
+ANGLE_EXPORT void GL_APIENTRY GetProgramResourceiv(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum *props,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+ANGLE_EXPORT GLint GL_APIENTRY GetProgramResourceLocation(GLuint program,
+ GLenum programInterface,
+ const GLchar *name);
+ANGLE_EXPORT void GL_APIENTRY UseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program);
+ANGLE_EXPORT void GL_APIENTRY ActiveShaderProgram(GLuint pipeline, GLuint program);
+ANGLE_EXPORT GLuint GL_APIENTRY CreateShaderProgramv(GLenum type,
+ GLsizei count,
+ const GLchar *const *strings);
+ANGLE_EXPORT void GL_APIENTRY BindProgramPipeline(GLuint pipeline);
+ANGLE_EXPORT void GL_APIENTRY DeleteProgramPipelines(GLsizei n, const GLuint *pipelines);
+ANGLE_EXPORT void GL_APIENTRY GenProgramPipelines(GLsizei n, GLuint *pipelines);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsProgramPipeline(GLuint pipeline);
+ANGLE_EXPORT void GL_APIENTRY GetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform1i(GLuint program, GLint location, GLint v0);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform2i(GLuint program, GLint location, GLint v0, GLint v1);
+ANGLE_EXPORT void GL_APIENTRY
+ProgramUniform3i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+ANGLE_EXPORT void GL_APIENTRY
+ProgramUniform4i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform1ui(GLuint program, GLint location, GLuint v0);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform2ui(GLuint program,
+ GLint location,
+ GLuint v0,
+ GLuint v1);
+ANGLE_EXPORT void GL_APIENTRY
+ProgramUniform3ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+ANGLE_EXPORT void GL_APIENTRY
+ProgramUniform4ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform1f(GLuint program, GLint location, GLfloat v0);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform2f(GLuint program,
+ GLint location,
+ GLfloat v0,
+ GLfloat v1);
+ANGLE_EXPORT void GL_APIENTRY
+ProgramUniform3f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+ANGLE_EXPORT void GL_APIENTRY
+ProgramUniform4f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform1iv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLint *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform2iv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLint *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform3iv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLint *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform4iv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLint *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform1uiv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLuint *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform2uiv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLuint *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform3uiv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLuint *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform4uiv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLuint *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform1fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform2fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform3fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniform4fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniformMatrix2fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniformMatrix3fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniformMatrix4fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniformMatrix2x3fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniformMatrix3x2fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniformMatrix2x4fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniformMatrix4x2fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniformMatrix3x4fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ProgramUniformMatrix4x3fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ANGLE_EXPORT void GL_APIENTRY ValidateProgramPipeline(GLuint pipeline);
+ANGLE_EXPORT void GL_APIENTRY GetProgramPipelineInfoLog(GLuint pipeline,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *infoLog);
+ANGLE_EXPORT void GL_APIENTRY BindImageTexture(GLuint unit,
+ GLuint texture,
+ GLint level,
+ GLboolean layered,
+ GLint layer,
+ GLenum access,
+ GLenum format);
+ANGLE_EXPORT void GL_APIENTRY GetBooleani_v(GLenum target, GLuint index, GLboolean *data);
+ANGLE_EXPORT void GL_APIENTRY MemoryBarrier(GLbitfield barriers);
+ANGLE_EXPORT void GL_APIENTRY MemoryBarrierByRegion(GLbitfield barriers);
+ANGLE_EXPORT void GL_APIENTRY TexStorage2DMultisample(GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedsamplelocations);
+ANGLE_EXPORT void GL_APIENTRY GetMultisamplefv(GLenum pname, GLuint index, GLfloat *val);
+ANGLE_EXPORT void GL_APIENTRY SampleMaski(GLuint maskNumber, GLbitfield mask);
+ANGLE_EXPORT void GL_APIENTRY GetTexLevelParameteriv(GLenum target,
+ GLint level,
+ GLenum pname,
+ GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetTexLevelParameterfv(GLenum target,
+ GLint level,
+ GLenum pname,
+ GLfloat *params);
+ANGLE_EXPORT void GL_APIENTRY BindVertexBuffer(GLuint bindingindex,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizei stride);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribFormat(GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLuint relativeoffset);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribIFormat(GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLuint relativeoffset);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribBinding(GLuint attribindex, GLuint bindingindex);
+ANGLE_EXPORT void GL_APIENTRY VertexBindingDivisor(GLuint bindingindex, GLuint divisor);
+} // namespace gl
+
+#endif // LIBGLESV2_ENTRYPOINTSGLES31_AUTOGEN_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/global_state.cpp b/src/3rdparty/angle/src/libGLESv2/global_state.cpp
index b99c3e1ca9..c5f3dfe4e1 100644
--- a/src/3rdparty/angle/src/libGLESv2/global_state.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/global_state.cpp
@@ -8,229 +8,141 @@
#include "libGLESv2/global_state.h"
-#include "libANGLE/Context.h"
-#include "libANGLE/Error.h"
-
#include "common/debug.h"
#include "common/platform.h"
#include "common/tls.h"
-namespace
-{
-
-static TLSIndex currentTLS = TLS_INVALID_INDEX;
-
-struct Current
-{
- EGLint error;
- EGLenum API;
- egl::Display *display;
- egl::Surface *drawSurface;
- egl::Surface *readSurface;
- gl::Context *context;
-};
-
-Current *AllocateCurrent()
-{
- ASSERT(currentTLS != TLS_INVALID_INDEX);
- if (currentTLS == TLS_INVALID_INDEX)
- {
- return NULL;
- }
-
- Current *current = new Current();
- current->error = EGL_SUCCESS;
- current->API = EGL_OPENGL_ES_API;
- current->display = reinterpret_cast<egl::Display*>(EGL_NO_DISPLAY);
- current->drawSurface = reinterpret_cast<egl::Surface*>(EGL_NO_SURFACE);
- current->readSurface = reinterpret_cast<egl::Surface*>(EGL_NO_SURFACE);
- current->context = reinterpret_cast<gl::Context*>(EGL_NO_CONTEXT);
-
- if (!SetTLSValue(currentTLS, current))
- {
- ERR("Could not set thread local storage.");
- return NULL;
- }
+#include "libANGLE/Thread.h"
- return current;
-}
-
-Current *GetCurrentData()
+namespace gl
{
- // Create a TLS index if one has not been created for this DLL
- if (currentTLS == TLS_INVALID_INDEX)
- {
- currentTLS = CreateTLSIndex();
- }
- Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS));
-
- // ANGLE issue 488: when the dll is loaded after thread initialization,
- // thread local storage (current) might not exist yet.
- return (current ? current : AllocateCurrent());
-}
-
-#ifdef ANGLE_PLATFORM_WINDOWS
-
-void DeallocateCurrent()
+Context *GetGlobalContext()
{
- Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS));
- SafeDelete(current);
- SetTLSValue(currentTLS, NULL);
+ egl::Thread *thread = egl::GetCurrentThread();
+ return thread->getContext();
}
-extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD reason, LPVOID)
+Context *GetValidGlobalContext()
{
- switch (reason)
- {
- case DLL_PROCESS_ATTACH:
- currentTLS = CreateTLSIndex();
- if (currentTLS == TLS_INVALID_INDEX)
- {
- return FALSE;
- }
- AllocateCurrent();
- break;
-
- case DLL_THREAD_ATTACH:
- AllocateCurrent();
- break;
-
- case DLL_THREAD_DETACH:
- DeallocateCurrent();
- break;
-
- case DLL_PROCESS_DETACH:
- DeallocateCurrent();
- if (currentTLS != TLS_INVALID_INDEX)
- {
- DestroyTLSIndex(currentTLS);
- currentTLS = TLS_INVALID_INDEX;
- }
- break;
- }
-
- return TRUE;
+ egl::Thread *thread = egl::GetCurrentThread();
+ return thread->getValidContext();
}
-#endif
-}
+} // namespace gl
-namespace gl
+namespace egl
{
-Context *GetGlobalContext()
+namespace
{
- Current *current = GetCurrentData();
- return current->context;
-}
+static TLSIndex threadTLS = TLS_INVALID_INDEX;
-Context *GetValidGlobalContext()
+Thread *AllocateCurrentThread()
{
- gl::Context *context = GetGlobalContext();
- if (context)
+ ASSERT(threadTLS != TLS_INVALID_INDEX);
+ if (threadTLS == TLS_INVALID_INDEX)
{
- if (context->isContextLost())
- {
- context->recordError(gl::Error(GL_OUT_OF_MEMORY, "Context has been lost."));
- return nullptr;
- }
- else
- {
- return context;
- }
+ return nullptr;
+ }
+
+ Thread *thread = new Thread();
+ if (!SetTLSValue(threadTLS, thread))
+ {
+ ERR() << "Could not set thread local storage.";
+ return nullptr;
}
- return nullptr;
-}
+ return thread;
}
-namespace egl
-{
+} // anonymous namespace
-void SetGlobalError(const Error &error)
+Thread *GetCurrentThread()
{
- Current *current = GetCurrentData();
-
- current->error = error.getCode();
-}
+ // Create a TLS index if one has not been created for this DLL
+ if (threadTLS == TLS_INVALID_INDEX)
+ {
+ threadTLS = CreateTLSIndex();
+ }
-EGLint GetGlobalError()
-{
- Current *current = GetCurrentData();
+ Thread *current = static_cast<Thread *>(GetTLSValue(threadTLS));
- return current->error;
+ // ANGLE issue 488: when the dll is loaded after thread initialization,
+ // thread local storage (current) might not exist yet.
+ return (current ? current : AllocateCurrentThread());
}
-EGLenum GetGlobalAPI()
-{
- Current *current = GetCurrentData();
-
- return current->API;
-}
+} // namespace egl
-void SetGlobalAPI(EGLenum API)
+#ifdef ANGLE_PLATFORM_WINDOWS
+namespace egl
{
- Current *current = GetCurrentData();
-
- current->API = API;
-}
-void SetGlobalDisplay(Display *dpy)
+namespace
{
- Current *current = GetCurrentData();
-
- current->display = dpy;
-}
-Display *GetGlobalDisplay()
+bool DeallocateCurrentThread()
{
- Current *current = GetCurrentData();
-
- return current->display;
+ Thread *thread = static_cast<Thread *>(GetTLSValue(threadTLS));
+ SafeDelete(thread);
+ return SetTLSValue(threadTLS, nullptr);
}
-void SetGlobalDrawSurface(Surface *surface)
+bool InitializeProcess()
{
- Current *current = GetCurrentData();
+ threadTLS = CreateTLSIndex();
+ if (threadTLS == TLS_INVALID_INDEX)
+ {
+ return false;
+ }
- current->drawSurface = surface;
+ return AllocateCurrentThread() != nullptr;
}
-Surface *GetGlobalDrawSurface()
+bool TerminateProcess()
{
- Current *current = GetCurrentData();
+ if (!DeallocateCurrentThread())
+ {
+ return false;
+ }
- return current->drawSurface;
-}
+ if (threadTLS != TLS_INVALID_INDEX)
+ {
+ TLSIndex tlsCopy = threadTLS;
+ threadTLS = TLS_INVALID_INDEX;
-void SetGlobalReadSurface(Surface *surface)
-{
- Current *current = GetCurrentData();
+ if (!DestroyTLSIndex(tlsCopy))
+ {
+ return false;
+ }
+ }
- current->readSurface = surface;
+ return true;
}
-Surface *GetGlobalReadSurface()
-{
- Current *current = GetCurrentData();
+} // anonymous namespace
- return current->readSurface;
-}
+} // namespace egl
-void SetGlobalContext(gl::Context *context)
+extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD reason, LPVOID)
{
- Current *current = GetCurrentData();
+ switch (reason)
+ {
+ case DLL_PROCESS_ATTACH:
+ return static_cast<BOOL>(egl::InitializeProcess());
- current->context = context;
-}
+ case DLL_THREAD_ATTACH:
+ return static_cast<BOOL>(egl::AllocateCurrentThread() != nullptr);
-gl::Context *GetGlobalContext()
-{
- Current *current = GetCurrentData();
+ case DLL_THREAD_DETACH:
+ return static_cast<BOOL>(egl::DeallocateCurrentThread());
- return current->context;
-}
+ case DLL_PROCESS_DETACH:
+ return static_cast<BOOL>(egl::TerminateProcess());
+ }
+ return TRUE;
}
+#endif // ANGLE_PLATFORM_WINDOWS
diff --git a/src/3rdparty/angle/src/libGLESv2/global_state.h b/src/3rdparty/angle/src/libGLESv2/global_state.h
index db202539cb..3e3740c90e 100644
--- a/src/3rdparty/angle/src/libGLESv2/global_state.h
+++ b/src/3rdparty/angle/src/libGLESv2/global_state.h
@@ -9,8 +9,6 @@
#ifndef LIBGLESV2_GLOBALSTATE_H_
#define LIBGLESV2_GLOBALSTATE_H_
-#include <EGL/egl.h>
-
namespace gl
{
class Context;
@@ -18,32 +16,14 @@ class Context;
Context *GetGlobalContext();
Context *GetValidGlobalContext();
-}
+} // namespace gl
namespace egl
{
-class Error;
-class Display;
-class Surface;
-
-void SetGlobalError(const Error &error);
-EGLint GetGlobalError();
-
-void SetGlobalAPI(EGLenum API);
-EGLenum GetGlobalAPI();
-
-void SetGlobalDisplay(Display *dpy);
-Display *GetGlobalDisplay();
-
-void SetGlobalDrawSurface(Surface *surface);
-Surface *GetGlobalDrawSurface();
-
-void SetGlobalReadSurface(Surface *surface);
-Surface *GetGlobalReadSurface();
+class Thread;
-void SetGlobalContext(gl::Context *context);
-gl::Context *GetGlobalContext();
+Thread *GetCurrentThread();
-}
+} // namespace egl
#endif // LIBGLESV2_GLOBALSTATE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp
index 42b749f373..ffd78a2ac0 100644
--- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp
@@ -6,14 +6,14 @@
// libGLESv2.cpp: Implements the exported OpenGL ES 2.0 functions.
-#include "libGLESv2/entry_points_gles_2_0.h"
+#include "libGLESv2/entry_points_gles_2_0_autogen.h"
#include "libGLESv2/entry_points_gles_2_0_ext.h"
-#include "libGLESv2/entry_points_gles_3_0.h"
+#include "libGLESv2/entry_points_gles_3_0_autogen.h"
+#include "libGLESv2/entry_points_gles_3_1_autogen.h"
#include "common/event_tracer.h"
-extern "C"
-{
+extern "C" {
void GL_APIENTRY glActiveTexture(GLenum texture)
{
@@ -25,7 +25,7 @@ void GL_APIENTRY glAttachShader(GLuint program, GLuint shader)
return gl::AttachShader(program, shader);
}
-void GL_APIENTRY glBindAttribLocation(GLuint program, GLuint index, const GLchar* name)
+void GL_APIENTRY glBindAttribLocation(GLuint program, GLuint index, const GLchar *name)
{
return gl::BindAttribLocation(program, index, name);
}
@@ -75,12 +75,12 @@ void GL_APIENTRY glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlp
return gl::BlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
}
-void GL_APIENTRY glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
+void GL_APIENTRY glBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage)
{
return gl::BufferData(target, size, data, usage);
}
-void GL_APIENTRY glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
+void GL_APIENTRY glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void *data)
{
return gl::BufferSubData(target, offset, size, data);
}
@@ -120,22 +120,53 @@ void GL_APIENTRY glCompileShader(GLuint shader)
return gl::CompileShader(shader);
}
-void GL_APIENTRY glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data)
+void GL_APIENTRY glCompressedTexImage2D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ const void *data)
{
- return gl::CompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
+ return gl::CompressedTexImage2D(target, level, internalformat, width, height, border, imageSize,
+ data);
}
-void GL_APIENTRY glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data)
+void GL_APIENTRY glCompressedTexSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data)
{
- return gl::CompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
+ return gl::CompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format,
+ imageSize, data);
}
-void GL_APIENTRY glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
+void GL_APIENTRY glCopyTexImage2D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border)
{
return gl::CopyTexImage2D(target, level, internalformat, x, y, width, height, border);
}
-void GL_APIENTRY glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+void GL_APIENTRY glCopyTexSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
{
return gl::CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
}
@@ -155,12 +186,12 @@ void GL_APIENTRY glCullFace(GLenum mode)
return gl::CullFace(mode);
}
-void GL_APIENTRY glDeleteBuffers(GLsizei n, const GLuint* buffers)
+void GL_APIENTRY glDeleteBuffers(GLsizei n, const GLuint *buffers)
{
return gl::DeleteBuffers(n, buffers);
}
-void GL_APIENTRY glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
+void GL_APIENTRY glDeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
{
return gl::DeleteFramebuffers(n, framebuffers);
}
@@ -170,7 +201,7 @@ void GL_APIENTRY glDeleteProgram(GLuint program)
return gl::DeleteProgram(program);
}
-void GL_APIENTRY glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
+void GL_APIENTRY glDeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
{
return gl::DeleteRenderbuffers(n, renderbuffers);
}
@@ -180,7 +211,7 @@ void GL_APIENTRY glDeleteShader(GLuint shader)
return gl::DeleteShader(shader);
}
-void GL_APIENTRY glDeleteTextures(GLsizei n, const GLuint* textures)
+void GL_APIENTRY glDeleteTextures(GLsizei n, const GLuint *textures)
{
return gl::DeleteTextures(n, textures);
}
@@ -220,7 +251,7 @@ void GL_APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count)
return gl::DrawArrays(mode, first, count);
}
-void GL_APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
+void GL_APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)
{
return gl::DrawElements(mode, count, type, indices);
}
@@ -245,12 +276,19 @@ void GL_APIENTRY glFlush(void)
return gl::Flush();
}
-void GL_APIENTRY glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+void GL_APIENTRY glFramebufferRenderbuffer(GLenum target,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer)
{
return gl::FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
}
-void GL_APIENTRY glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+void GL_APIENTRY glFramebufferTexture2D(GLenum target,
+ GLenum attachment,
+ GLenum textarget,
+ GLuint texture,
+ GLint level)
{
return gl::FramebufferTexture2D(target, attachment, textarget, texture, level);
}
@@ -260,7 +298,7 @@ void GL_APIENTRY glFrontFace(GLenum mode)
return gl::FrontFace(mode);
}
-void GL_APIENTRY glGenBuffers(GLsizei n, GLuint* buffers)
+void GL_APIENTRY glGenBuffers(GLsizei n, GLuint *buffers)
{
return gl::GenBuffers(n, buffers);
}
@@ -270,47 +308,62 @@ void GL_APIENTRY glGenerateMipmap(GLenum target)
return gl::GenerateMipmap(target);
}
-void GL_APIENTRY glGenFramebuffers(GLsizei n, GLuint* framebuffers)
+void GL_APIENTRY glGenFramebuffers(GLsizei n, GLuint *framebuffers)
{
return gl::GenFramebuffers(n, framebuffers);
}
-void GL_APIENTRY glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
+void GL_APIENTRY glGenRenderbuffers(GLsizei n, GLuint *renderbuffers)
{
return gl::GenRenderbuffers(n, renderbuffers);
}
-void GL_APIENTRY glGenTextures(GLsizei n, GLuint* textures)
+void GL_APIENTRY glGenTextures(GLsizei n, GLuint *textures)
{
return gl::GenTextures(n, textures);
}
-void GL_APIENTRY glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
+void GL_APIENTRY glGetActiveAttrib(GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name)
{
return gl::GetActiveAttrib(program, index, bufsize, length, size, type, name);
}
-void GL_APIENTRY glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
+void GL_APIENTRY glGetActiveUniform(GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name)
{
return gl::GetActiveUniform(program, index, bufsize, length, size, type, name);
}
-void GL_APIENTRY glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
+void GL_APIENTRY glGetAttachedShaders(GLuint program,
+ GLsizei maxcount,
+ GLsizei *count,
+ GLuint *shaders)
{
return gl::GetAttachedShaders(program, maxcount, count, shaders);
}
-GLint GL_APIENTRY glGetAttribLocation(GLuint program, const GLchar* name)
+GLint GL_APIENTRY glGetAttribLocation(GLuint program, const GLchar *name)
{
return gl::GetAttribLocation(program, name);
}
-void GL_APIENTRY glGetBooleanv(GLenum pname, GLboolean* params)
+void GL_APIENTRY glGetBooleanv(GLenum pname, GLboolean *params)
{
return gl::GetBooleanv(pname, params);
}
-void GL_APIENTRY glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
+void GL_APIENTRY glGetBufferParameteriv(GLenum target, GLenum pname, GLint *params)
{
return gl::GetBufferParameteriv(target, pname, params);
}
@@ -320,97 +373,109 @@ GLenum GL_APIENTRY glGetError(void)
return gl::GetError();
}
-void GL_APIENTRY glGetFloatv(GLenum pname, GLfloat* params)
+void GL_APIENTRY glGetFloatv(GLenum pname, GLfloat *params)
{
return gl::GetFloatv(pname, params);
}
-void GL_APIENTRY glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
+void GL_APIENTRY glGetFramebufferAttachmentParameteriv(GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLint *params)
{
return gl::GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
}
-void GL_APIENTRY glGetIntegerv(GLenum pname, GLint* params)
+void GL_APIENTRY glGetIntegerv(GLenum pname, GLint *params)
{
return gl::GetIntegerv(pname, params);
}
-void GL_APIENTRY glGetProgramiv(GLuint program, GLenum pname, GLint* params)
+void GL_APIENTRY glGetProgramiv(GLuint program, GLenum pname, GLint *params)
{
return gl::GetProgramiv(program, pname, params);
}
-void GL_APIENTRY glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
+void GL_APIENTRY glGetProgramInfoLog(GLuint program,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLchar *infolog)
{
return gl::GetProgramInfoLog(program, bufsize, length, infolog);
}
-void GL_APIENTRY glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
+void GL_APIENTRY glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
{
return gl::GetRenderbufferParameteriv(target, pname, params);
}
-void GL_APIENTRY glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
+void GL_APIENTRY glGetShaderiv(GLuint shader, GLenum pname, GLint *params)
{
return gl::GetShaderiv(shader, pname, params);
}
-void GL_APIENTRY glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
+void GL_APIENTRY glGetShaderInfoLog(GLuint shader,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLchar *infolog)
{
return gl::GetShaderInfoLog(shader, bufsize, length, infolog);
}
-void GL_APIENTRY glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
+void GL_APIENTRY glGetShaderPrecisionFormat(GLenum shadertype,
+ GLenum precisiontype,
+ GLint *range,
+ GLint *precision)
{
return gl::GetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
}
-void GL_APIENTRY glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
+void GL_APIENTRY glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source)
{
return gl::GetShaderSource(shader, bufsize, length, source);
}
-const GLubyte* GL_APIENTRY glGetString(GLenum name)
+const GLubyte *GL_APIENTRY glGetString(GLenum name)
{
return gl::GetString(name);
}
-void GL_APIENTRY glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
+void GL_APIENTRY glGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params)
{
return gl::GetTexParameterfv(target, pname, params);
}
-void GL_APIENTRY glGetTexParameteriv(GLenum target, GLenum pname, GLint* params)
+void GL_APIENTRY glGetTexParameteriv(GLenum target, GLenum pname, GLint *params)
{
return gl::GetTexParameteriv(target, pname, params);
}
-void GL_APIENTRY glGetUniformfv(GLuint program, GLint location, GLfloat* params)
+void GL_APIENTRY glGetUniformfv(GLuint program, GLint location, GLfloat *params)
{
return gl::GetUniformfv(program, location, params);
}
-void GL_APIENTRY glGetUniformiv(GLuint program, GLint location, GLint* params)
+void GL_APIENTRY glGetUniformiv(GLuint program, GLint location, GLint *params)
{
return gl::GetUniformiv(program, location, params);
}
-GLint GL_APIENTRY glGetUniformLocation(GLuint program, const GLchar* name)
+GLint GL_APIENTRY glGetUniformLocation(GLuint program, const GLchar *name)
{
return gl::GetUniformLocation(program, name);
}
-void GL_APIENTRY glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
+void GL_APIENTRY glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params)
{
return gl::GetVertexAttribfv(index, pname, params);
}
-void GL_APIENTRY glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
+void GL_APIENTRY glGetVertexAttribiv(GLuint index, GLenum pname, GLint *params)
{
return gl::GetVertexAttribiv(index, pname, params);
}
-void GL_APIENTRY glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
+void GL_APIENTRY glGetVertexAttribPointerv(GLuint index, GLenum pname, void **pointer)
{
return gl::GetVertexAttribPointerv(index, pname, pointer);
}
@@ -475,7 +540,13 @@ void GL_APIENTRY glPolygonOffset(GLfloat factor, GLfloat units)
return gl::PolygonOffset(factor, units);
}
-void GL_APIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
+void GL_APIENTRY glReadPixels(GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ void *pixels)
{
return gl::ReadPixels(x, y, width, height, format, type, pixels);
}
@@ -485,7 +556,10 @@ void GL_APIENTRY glReleaseShaderCompiler(void)
return gl::ReleaseShaderCompiler();
}
-void GL_APIENTRY glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+void GL_APIENTRY glRenderbufferStorage(GLenum target,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
{
return gl::RenderbufferStorage(target, internalformat, width, height);
}
@@ -500,12 +574,19 @@ void GL_APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
return gl::Scissor(x, y, width, height);
}
-void GL_APIENTRY glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
+void GL_APIENTRY glShaderBinary(GLsizei n,
+ const GLuint *shaders,
+ GLenum binaryformat,
+ const void *binary,
+ GLsizei length)
{
return gl::ShaderBinary(n, shaders, binaryformat, binary, length);
}
-void GL_APIENTRY glShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length)
+void GL_APIENTRY glShaderSource(GLuint shader,
+ GLsizei count,
+ const GLchar *const *string,
+ const GLint *length)
{
return gl::ShaderSource(shader, count, string, length);
}
@@ -540,9 +621,18 @@ void GL_APIENTRY glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLe
return gl::StencilOpSeparate(face, fail, zfail, zpass);
}
-void GL_APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
+void GL_APIENTRY glTexImage2D(GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
{
- return gl::TexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
+ return gl::TexImage2D(target, level, internalformat, width, height, border, format, type,
+ pixels);
}
void GL_APIENTRY glTexParameterf(GLenum target, GLenum pname, GLfloat param)
@@ -550,7 +640,7 @@ void GL_APIENTRY glTexParameterf(GLenum target, GLenum pname, GLfloat param)
return gl::TexParameterf(target, pname, param);
}
-void GL_APIENTRY glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
+void GL_APIENTRY glTexParameterfv(GLenum target, GLenum pname, const GLfloat *params)
{
return gl::TexParameterfv(target, pname, params);
}
@@ -560,12 +650,20 @@ void GL_APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param)
return gl::TexParameteri(target, pname, param);
}
-void GL_APIENTRY glTexParameteriv(GLenum target, GLenum pname, const GLint* params)
+void GL_APIENTRY glTexParameteriv(GLenum target, GLenum pname, const GLint *params)
{
return gl::TexParameteriv(target, pname, params);
}
-void GL_APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels)
+void GL_APIENTRY glTexSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
{
return gl::TexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
}
@@ -575,7 +673,7 @@ void GL_APIENTRY glUniform1f(GLint location, GLfloat x)
return gl::Uniform1f(location, x);
}
-void GL_APIENTRY glUniform1fv(GLint location, GLsizei count, const GLfloat* v)
+void GL_APIENTRY glUniform1fv(GLint location, GLsizei count, const GLfloat *v)
{
return gl::Uniform1fv(location, count, v);
}
@@ -585,7 +683,7 @@ void GL_APIENTRY glUniform1i(GLint location, GLint x)
return gl::Uniform1i(location, x);
}
-void GL_APIENTRY glUniform1iv(GLint location, GLsizei count, const GLint* v)
+void GL_APIENTRY glUniform1iv(GLint location, GLsizei count, const GLint *v)
{
return gl::Uniform1iv(location, count, v);
}
@@ -595,7 +693,7 @@ void GL_APIENTRY glUniform2f(GLint location, GLfloat x, GLfloat y)
return gl::Uniform2f(location, x, y);
}
-void GL_APIENTRY glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
+void GL_APIENTRY glUniform2fv(GLint location, GLsizei count, const GLfloat *v)
{
return gl::Uniform2fv(location, count, v);
}
@@ -605,7 +703,7 @@ void GL_APIENTRY glUniform2i(GLint location, GLint x, GLint y)
return gl::Uniform2i(location, x, y);
}
-void GL_APIENTRY glUniform2iv(GLint location, GLsizei count, const GLint* v)
+void GL_APIENTRY glUniform2iv(GLint location, GLsizei count, const GLint *v)
{
return gl::Uniform2iv(location, count, v);
}
@@ -615,7 +713,7 @@ void GL_APIENTRY glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
return gl::Uniform3f(location, x, y, z);
}
-void GL_APIENTRY glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
+void GL_APIENTRY glUniform3fv(GLint location, GLsizei count, const GLfloat *v)
{
return gl::Uniform3fv(location, count, v);
}
@@ -625,7 +723,7 @@ void GL_APIENTRY glUniform3i(GLint location, GLint x, GLint y, GLint z)
return gl::Uniform3i(location, x, y, z);
}
-void GL_APIENTRY glUniform3iv(GLint location, GLsizei count, const GLint* v)
+void GL_APIENTRY glUniform3iv(GLint location, GLsizei count, const GLint *v)
{
return gl::Uniform3iv(location, count, v);
}
@@ -635,7 +733,7 @@ void GL_APIENTRY glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GL
return gl::Uniform4f(location, x, y, z, w);
}
-void GL_APIENTRY glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
+void GL_APIENTRY glUniform4fv(GLint location, GLsizei count, const GLfloat *v)
{
return gl::Uniform4fv(location, count, v);
}
@@ -645,22 +743,31 @@ void GL_APIENTRY glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
return gl::Uniform4i(location, x, y, z, w);
}
-void GL_APIENTRY glUniform4iv(GLint location, GLsizei count, const GLint* v)
+void GL_APIENTRY glUniform4iv(GLint location, GLsizei count, const GLint *v)
{
return gl::Uniform4iv(location, count, v);
}
-void GL_APIENTRY glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+void GL_APIENTRY glUniformMatrix2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
{
return gl::UniformMatrix2fv(location, count, transpose, value);
}
-void GL_APIENTRY glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+void GL_APIENTRY glUniformMatrix3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
{
return gl::UniformMatrix3fv(location, count, transpose, value);
}
-void GL_APIENTRY glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+void GL_APIENTRY glUniformMatrix4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
{
return gl::UniformMatrix4fv(location, count, transpose, value);
}
@@ -680,7 +787,7 @@ void GL_APIENTRY glVertexAttrib1f(GLuint indx, GLfloat x)
return gl::VertexAttrib1f(indx, x);
}
-void GL_APIENTRY glVertexAttrib1fv(GLuint indx, const GLfloat* values)
+void GL_APIENTRY glVertexAttrib1fv(GLuint indx, const GLfloat *values)
{
return gl::VertexAttrib1fv(indx, values);
}
@@ -690,7 +797,7 @@ void GL_APIENTRY glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
return gl::VertexAttrib2f(indx, x, y);
}
-void GL_APIENTRY glVertexAttrib2fv(GLuint indx, const GLfloat* values)
+void GL_APIENTRY glVertexAttrib2fv(GLuint indx, const GLfloat *values)
{
return gl::VertexAttrib2fv(indx, values);
}
@@ -700,7 +807,7 @@ void GL_APIENTRY glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
return gl::VertexAttrib3f(indx, x, y, z);
}
-void GL_APIENTRY glVertexAttrib3fv(GLuint indx, const GLfloat* values)
+void GL_APIENTRY glVertexAttrib3fv(GLuint indx, const GLfloat *values)
{
return gl::VertexAttrib3fv(indx, values);
}
@@ -710,12 +817,17 @@ void GL_APIENTRY glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z,
return gl::VertexAttrib4f(indx, x, y, z, w);
}
-void GL_APIENTRY glVertexAttrib4fv(GLuint indx, const GLfloat* values)
+void GL_APIENTRY glVertexAttrib4fv(GLuint indx, const GLfloat *values)
{
return gl::VertexAttrib4fv(indx, values);
}
-void GL_APIENTRY glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
+void GL_APIENTRY glVertexAttribPointer(GLuint indx,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLsizei stride,
+ const void *ptr)
{
return gl::VertexAttribPointer(indx, size, type, normalized, stride, ptr);
}
@@ -730,42 +842,96 @@ void GL_APIENTRY glReadBuffer(GLenum mode)
return gl::ReadBuffer(mode);
}
-void GL_APIENTRY glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices)
+void GL_APIENTRY glDrawRangeElements(GLenum mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ GLenum type,
+ const void *indices)
{
return gl::DrawRangeElements(mode, start, end, count, type, indices);
}
-void GL_APIENTRY glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
-{
- return gl::TexImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels);
-}
-
-void GL_APIENTRY glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels)
-{
- return gl::TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
-}
-
-void GL_APIENTRY glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+void GL_APIENTRY glTexImage3D(GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ return gl::TexImage3D(target, level, internalformat, width, height, depth, border, format, type,
+ pixels);
+}
+
+void GL_APIENTRY glTexSubImage3D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ return gl::TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format,
+ type, pixels);
+}
+
+void GL_APIENTRY glCopyTexSubImage3D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
{
return gl::CopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height);
}
-void GL_APIENTRY glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data)
+void GL_APIENTRY glCompressedTexImage3D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ const void *data)
{
- return gl::CompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data);
+ return gl::CompressedTexImage3D(target, level, internalformat, width, height, depth, border,
+ imageSize, data);
}
-void GL_APIENTRY glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data)
+void GL_APIENTRY glCompressedTexSubImage3D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data)
{
- return gl::CompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
+ return gl::CompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height,
+ depth, format, imageSize, data);
}
-void GL_APIENTRY glGenQueries(GLsizei n, GLuint* ids)
+void GL_APIENTRY glGenQueries(GLsizei n, GLuint *ids)
{
return gl::GenQueries(n, ids);
}
-void GL_APIENTRY glDeleteQueries(GLsizei n, const GLuint* ids)
+void GL_APIENTRY glDeleteQueries(GLsizei n, const GLuint *ids)
{
return gl::DeleteQueries(n, ids);
}
@@ -785,12 +951,12 @@ void GL_APIENTRY glEndQuery(GLenum target)
return gl::EndQuery(target);
}
-void GL_APIENTRY glGetQueryiv(GLenum target, GLenum pname, GLint* params)
+void GL_APIENTRY glGetQueryiv(GLenum target, GLenum pname, GLint *params)
{
return gl::GetQueryiv(target, pname, params);
}
-void GL_APIENTRY glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params)
+void GL_APIENTRY glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params)
{
return gl::GetQueryObjectuiv(id, pname, params);
}
@@ -800,62 +966,101 @@ GLboolean GL_APIENTRY glUnmapBuffer(GLenum target)
return gl::UnmapBuffer(target);
}
-void GL_APIENTRY glGetBufferPointerv(GLenum target, GLenum pname, GLvoid** params)
+void GL_APIENTRY glGetBufferPointerv(GLenum target, GLenum pname, void **params)
{
return gl::GetBufferPointerv(target, pname, params);
}
-void GL_APIENTRY glDrawBuffers(GLsizei n, const GLenum* bufs)
+void GL_APIENTRY glDrawBuffers(GLsizei n, const GLenum *bufs)
{
return gl::DrawBuffers(n, bufs);
}
-void GL_APIENTRY glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+void GL_APIENTRY glUniformMatrix2x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
{
return gl::UniformMatrix2x3fv(location, count, transpose, value);
}
-void GL_APIENTRY glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+void GL_APIENTRY glUniformMatrix3x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
{
return gl::UniformMatrix3x2fv(location, count, transpose, value);
}
-void GL_APIENTRY glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+void GL_APIENTRY glUniformMatrix2x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
{
return gl::UniformMatrix2x4fv(location, count, transpose, value);
}
-void GL_APIENTRY glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+void GL_APIENTRY glUniformMatrix4x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
{
return gl::UniformMatrix4x2fv(location, count, transpose, value);
}
-void GL_APIENTRY glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+void GL_APIENTRY glUniformMatrix3x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
{
return gl::UniformMatrix3x4fv(location, count, transpose, value);
}
-void GL_APIENTRY glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+void GL_APIENTRY glUniformMatrix4x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
{
return gl::UniformMatrix4x3fv(location, count, transpose, value);
}
-void GL_APIENTRY glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
+void GL_APIENTRY glBlitFramebuffer(GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter)
{
- return gl::BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+ return gl::BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask,
+ filter);
}
-void GL_APIENTRY glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+void GL_APIENTRY glRenderbufferStorageMultisample(GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
{
return gl::RenderbufferStorageMultisample(target, samples, internalformat, width, height);
}
-void GL_APIENTRY glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
+void GL_APIENTRY glFramebufferTextureLayer(GLenum target,
+ GLenum attachment,
+ GLuint texture,
+ GLint level,
+ GLint layer)
{
return gl::FramebufferTextureLayer(target, attachment, texture, level, layer);
}
-GLvoid* GL_APIENTRY glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
+void *GL_APIENTRY glMapBufferRange(GLenum target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access)
{
return gl::MapBufferRange(target, offset, length, access);
}
@@ -870,12 +1075,12 @@ void GL_APIENTRY glBindVertexArray(GLuint array)
return gl::BindVertexArray(array);
}
-void GL_APIENTRY glDeleteVertexArrays(GLsizei n, const GLuint* arrays)
+void GL_APIENTRY glDeleteVertexArrays(GLsizei n, const GLuint *arrays)
{
return gl::DeleteVertexArrays(n, arrays);
}
-void GL_APIENTRY glGenVertexArrays(GLsizei n, GLuint* arrays)
+void GL_APIENTRY glGenVertexArrays(GLsizei n, GLuint *arrays)
{
return gl::GenVertexArrays(n, arrays);
}
@@ -885,7 +1090,7 @@ GLboolean GL_APIENTRY glIsVertexArray(GLuint array)
return gl::IsVertexArray(array);
}
-void GL_APIENTRY glGetIntegeri_v(GLenum target, GLuint index, GLint* data)
+void GL_APIENTRY glGetIntegeri_v(GLenum target, GLuint index, GLint *data)
{
return gl::GetIntegeri_v(target, index, data);
}
@@ -900,7 +1105,8 @@ void GL_APIENTRY glEndTransformFeedback(void)
return gl::EndTransformFeedback();
}
-void GL_APIENTRY glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
+void GL_APIENTRY
+glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
{
return gl::BindBufferRange(target, index, buffer, offset, size);
}
@@ -910,27 +1116,37 @@ void GL_APIENTRY glBindBufferBase(GLenum target, GLuint index, GLuint buffer)
return gl::BindBufferBase(target, index, buffer);
}
-void GL_APIENTRY glTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode)
+void GL_APIENTRY glTransformFeedbackVaryings(GLuint program,
+ GLsizei count,
+ const GLchar *const *varyings,
+ GLenum bufferMode)
{
return gl::TransformFeedbackVaryings(program, count, varyings, bufferMode);
}
-void GL_APIENTRY glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name)
+void GL_APIENTRY glGetTransformFeedbackVarying(GLuint program,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *size,
+ GLenum *type,
+ GLchar *name)
{
return gl::GetTransformFeedbackVarying(program, index, bufSize, length, size, type, name);
}
-void GL_APIENTRY glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer)
+void GL_APIENTRY
+glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer)
{
return gl::VertexAttribIPointer(index, size, type, stride, pointer);
}
-void GL_APIENTRY glGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params)
+void GL_APIENTRY glGetVertexAttribIiv(GLuint index, GLenum pname, GLint *params)
{
return gl::GetVertexAttribIiv(index, pname, params);
}
-void GL_APIENTRY glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params)
+void GL_APIENTRY glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params)
{
return gl::GetVertexAttribIuiv(index, pname, params);
}
@@ -945,17 +1161,17 @@ void GL_APIENTRY glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z,
return gl::VertexAttribI4ui(index, x, y, z, w);
}
-void GL_APIENTRY glVertexAttribI4iv(GLuint index, const GLint* v)
+void GL_APIENTRY glVertexAttribI4iv(GLuint index, const GLint *v)
{
return gl::VertexAttribI4iv(index, v);
}
-void GL_APIENTRY glVertexAttribI4uiv(GLuint index, const GLuint* v)
+void GL_APIENTRY glVertexAttribI4uiv(GLuint index, const GLuint *v)
{
return gl::VertexAttribI4uiv(index, v);
}
-void GL_APIENTRY glGetUniformuiv(GLuint program, GLint location, GLuint* params)
+void GL_APIENTRY glGetUniformuiv(GLuint program, GLint location, GLuint *params)
{
return gl::GetUniformuiv(program, location, params);
}
@@ -985,37 +1201,37 @@ void GL_APIENTRY glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, G
return gl::Uniform4ui(location, v0, v1, v2, v3);
}
-void GL_APIENTRY glUniform1uiv(GLint location, GLsizei count, const GLuint* value)
+void GL_APIENTRY glUniform1uiv(GLint location, GLsizei count, const GLuint *value)
{
return gl::Uniform1uiv(location, count, value);
}
-void GL_APIENTRY glUniform2uiv(GLint location, GLsizei count, const GLuint* value)
+void GL_APIENTRY glUniform2uiv(GLint location, GLsizei count, const GLuint *value)
{
return gl::Uniform2uiv(location, count, value);
}
-void GL_APIENTRY glUniform3uiv(GLint location, GLsizei count, const GLuint* value)
+void GL_APIENTRY glUniform3uiv(GLint location, GLsizei count, const GLuint *value)
{
return gl::Uniform3uiv(location, count, value);
}
-void GL_APIENTRY glUniform4uiv(GLint location, GLsizei count, const GLuint* value)
+void GL_APIENTRY glUniform4uiv(GLint location, GLsizei count, const GLuint *value)
{
return gl::Uniform4uiv(location, count, value);
}
-void GL_APIENTRY glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value)
+void GL_APIENTRY glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
{
return gl::ClearBufferiv(buffer, drawbuffer, value);
}
-void GL_APIENTRY glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value)
+void GL_APIENTRY glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
{
return gl::ClearBufferuiv(buffer, drawbuffer, value);
}
-void GL_APIENTRY glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value)
+void GL_APIENTRY glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
{
return gl::ClearBufferfv(buffer, drawbuffer, value);
}
@@ -1025,59 +1241,87 @@ void GL_APIENTRY glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth,
return gl::ClearBufferfi(buffer, drawbuffer, depth, stencil);
}
-const GLubyte* GL_APIENTRY glGetStringi(GLenum name, GLuint index)
+const GLubyte *GL_APIENTRY glGetStringi(GLenum name, GLuint index)
{
return gl::GetStringi(name, index);
}
-void GL_APIENTRY glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
+void GL_APIENTRY glCopyBufferSubData(GLenum readTarget,
+ GLenum writeTarget,
+ GLintptr readOffset,
+ GLintptr writeOffset,
+ GLsizeiptr size)
{
return gl::CopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size);
}
-void GL_APIENTRY glGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices)
+void GL_APIENTRY glGetUniformIndices(GLuint program,
+ GLsizei uniformCount,
+ const GLchar *const *uniformNames,
+ GLuint *uniformIndices)
{
return gl::GetUniformIndices(program, uniformCount, uniformNames, uniformIndices);
}
-void GL_APIENTRY glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params)
+void GL_APIENTRY glGetActiveUniformsiv(GLuint program,
+ GLsizei uniformCount,
+ const GLuint *uniformIndices,
+ GLenum pname,
+ GLint *params)
{
return gl::GetActiveUniformsiv(program, uniformCount, uniformIndices, pname, params);
}
-GLuint GL_APIENTRY glGetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName)
+GLuint GL_APIENTRY glGetUniformBlockIndex(GLuint program, const GLchar *uniformBlockName)
{
return gl::GetUniformBlockIndex(program, uniformBlockName);
}
-void GL_APIENTRY glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params)
+void GL_APIENTRY glGetActiveUniformBlockiv(GLuint program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLint *params)
{
return gl::GetActiveUniformBlockiv(program, uniformBlockIndex, pname, params);
}
-void GL_APIENTRY glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName)
+void GL_APIENTRY glGetActiveUniformBlockName(GLuint program,
+ GLuint uniformBlockIndex,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *uniformBlockName)
{
- return gl::GetActiveUniformBlockName(program, uniformBlockIndex, bufSize, length, uniformBlockName);
+ return gl::GetActiveUniformBlockName(program, uniformBlockIndex, bufSize, length,
+ uniformBlockName);
}
-void GL_APIENTRY glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)
+void GL_APIENTRY glUniformBlockBinding(GLuint program,
+ GLuint uniformBlockIndex,
+ GLuint uniformBlockBinding)
{
return gl::UniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding);
}
-void GL_APIENTRY glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
+void GL_APIENTRY glDrawArraysInstanced(GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount)
{
return gl::DrawArraysInstanced(mode, first, count, instanceCount);
}
-void GL_APIENTRY glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount)
+void GL_APIENTRY glDrawElementsInstanced(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei instanceCount)
{
return gl::DrawElementsInstanced(mode, count, type, indices, instanceCount);
}
GLsync GL_APIENTRY glFenceSync(GLenum condition, GLbitfield flags)
{
- return gl::FenceSync_(condition, flags);
+ return gl::FenceSync(condition, flags);
}
GLboolean GL_APIENTRY glIsSync(GLsync sync)
@@ -1100,32 +1344,33 @@ void GL_APIENTRY glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
return gl::WaitSync(sync, flags, timeout);
}
-void GL_APIENTRY glGetInteger64v(GLenum pname, GLint64* params)
+void GL_APIENTRY glGetInteger64v(GLenum pname, GLint64 *params)
{
return gl::GetInteger64v(pname, params);
}
-void GL_APIENTRY glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values)
+void GL_APIENTRY
+glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values)
{
return gl::GetSynciv(sync, pname, bufSize, length, values);
}
-void GL_APIENTRY glGetInteger64i_v(GLenum target, GLuint index, GLint64* data)
+void GL_APIENTRY glGetInteger64i_v(GLenum target, GLuint index, GLint64 *data)
{
return gl::GetInteger64i_v(target, index, data);
}
-void GL_APIENTRY glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params)
+void GL_APIENTRY glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params)
{
return gl::GetBufferParameteri64v(target, pname, params);
}
-void GL_APIENTRY glGenSamplers(GLsizei count, GLuint* samplers)
+void GL_APIENTRY glGenSamplers(GLsizei count, GLuint *samplers)
{
return gl::GenSamplers(count, samplers);
}
-void GL_APIENTRY glDeleteSamplers(GLsizei count, const GLuint* samplers)
+void GL_APIENTRY glDeleteSamplers(GLsizei count, const GLuint *samplers)
{
return gl::DeleteSamplers(count, samplers);
}
@@ -1145,7 +1390,7 @@ void GL_APIENTRY glSamplerParameteri(GLuint sampler, GLenum pname, GLint param)
return gl::SamplerParameteri(sampler, pname, param);
}
-void GL_APIENTRY glSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param)
+void GL_APIENTRY glSamplerParameteriv(GLuint sampler, GLenum pname, const GLint *param)
{
return gl::SamplerParameteriv(sampler, pname, param);
}
@@ -1155,17 +1400,17 @@ void GL_APIENTRY glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param
return gl::SamplerParameterf(sampler, pname, param);
}
-void GL_APIENTRY glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param)
+void GL_APIENTRY glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat *param)
{
return gl::SamplerParameterfv(sampler, pname, param);
}
-void GL_APIENTRY glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params)
+void GL_APIENTRY glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params)
{
return gl::GetSamplerParameteriv(sampler, pname, params);
}
-void GL_APIENTRY glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params)
+void GL_APIENTRY glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params)
{
return gl::GetSamplerParameterfv(sampler, pname, params);
}
@@ -1180,12 +1425,12 @@ void GL_APIENTRY glBindTransformFeedback(GLenum target, GLuint id)
return gl::BindTransformFeedback(target, id);
}
-void GL_APIENTRY glDeleteTransformFeedbacks(GLsizei n, const GLuint* ids)
+void GL_APIENTRY glDeleteTransformFeedbacks(GLsizei n, const GLuint *ids)
{
return gl::DeleteTransformFeedbacks(n, ids);
}
-void GL_APIENTRY glGenTransformFeedbacks(GLsizei n, GLuint* ids)
+void GL_APIENTRY glGenTransformFeedbacks(GLsizei n, GLuint *ids)
{
return gl::GenTransformFeedbacks(n, ids);
}
@@ -1205,12 +1450,19 @@ void GL_APIENTRY glResumeTransformFeedback(void)
return gl::ResumeTransformFeedback();
}
-void GL_APIENTRY glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary)
+void GL_APIENTRY glGetProgramBinary(GLuint program,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary)
{
return gl::GetProgramBinary(program, bufSize, length, binaryFormat, binary);
}
-void GL_APIENTRY glProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length)
+void GL_APIENTRY glProgramBinary(GLuint program,
+ GLenum binaryFormat,
+ const void *binary,
+ GLsizei length)
{
return gl::ProgramBinary(program, binaryFormat, binary, length);
}
@@ -1220,52 +1472,86 @@ void GL_APIENTRY glProgramParameteri(GLuint program, GLenum pname, GLint value)
return gl::ProgramParameteri(program, pname, value);
}
-void GL_APIENTRY glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments)
+void GL_APIENTRY glInvalidateFramebuffer(GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments)
{
return gl::InvalidateFramebuffer(target, numAttachments, attachments);
}
-void GL_APIENTRY glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height)
+void GL_APIENTRY glInvalidateSubFramebuffer(GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
{
return gl::InvalidateSubFramebuffer(target, numAttachments, attachments, x, y, width, height);
}
-void GL_APIENTRY glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+void GL_APIENTRY
+glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
{
return gl::TexStorage2D(target, levels, internalformat, width, height);
}
-void GL_APIENTRY glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+void GL_APIENTRY glTexStorage3D(GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth)
{
return gl::TexStorage3D(target, levels, internalformat, width, height, depth);
}
-void GL_APIENTRY glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params)
+void GL_APIENTRY glGetInternalformativ(GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLint *params)
{
return gl::GetInternalformativ(target, internalformat, pname, bufSize, params);
}
-void GL_APIENTRY glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
+void GL_APIENTRY glBlitFramebufferANGLE(GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter)
{
- return gl::BlitFramebufferANGLE(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+ return gl::BlitFramebufferANGLE(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask,
+ filter);
}
-void GL_APIENTRY glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+void GL_APIENTRY glRenderbufferStorageMultisampleANGLE(GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
{
return gl::RenderbufferStorageMultisampleANGLE(target, samples, internalformat, width, height);
}
-void GL_APIENTRY glDiscardFramebufferEXT(GLenum target, GLsizei numAttachments, const GLenum *attachments)
+void GL_APIENTRY glDiscardFramebufferEXT(GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments)
{
return gl::DiscardFramebufferEXT(target, numAttachments, attachments);
}
-void GL_APIENTRY glDeleteFencesNV(GLsizei n, const GLuint* fences)
+void GL_APIENTRY glDeleteFencesNV(GLsizei n, const GLuint *fences)
{
return gl::DeleteFencesNV(n, fences);
}
-void GL_APIENTRY glGenFencesNV(GLsizei n, GLuint* fences)
+void GL_APIENTRY glGenFencesNV(GLsizei n, GLuint *fences)
{
return gl::GenFencesNV(n, fences);
}
@@ -1295,12 +1581,19 @@ void GL_APIENTRY glSetFenceNV(GLuint fence, GLenum condition)
return gl::SetFenceNV(fence, condition);
}
-void GL_APIENTRY glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source)
+void GL_APIENTRY glGetTranslatedShaderSourceANGLE(GLuint shader,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLchar *source)
{
return gl::GetTranslatedShaderSourceANGLE(shader, bufsize, length, source);
}
-void GL_APIENTRY glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+void GL_APIENTRY glTexStorage2DEXT(GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
{
return gl::TexStorage2DEXT(target, levels, internalformat, width, height);
}
@@ -1310,7 +1603,14 @@ GLenum GL_APIENTRY glGetGraphicsResetStatusEXT(void)
return gl::GetGraphicsResetStatusEXT();
}
-void GL_APIENTRY glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data)
+void GL_APIENTRY glReadnPixelsEXT(GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *data)
{
return gl::ReadnPixelsEXT(x, y, width, height, format, type, bufSize, data);
}
@@ -1385,12 +1685,19 @@ void GL_APIENTRY glDrawBuffersEXT(GLsizei n, const GLenum *bufs)
return gl::DrawBuffersEXT(n, bufs);
}
-void GL_APIENTRY glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
+void GL_APIENTRY glDrawArraysInstancedANGLE(GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount)
{
return gl::DrawArraysInstancedANGLE(mode, first, count, primcount);
}
-void GL_APIENTRY glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount)
+void GL_APIENTRY glDrawElementsInstancedANGLE(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void *indices,
+ GLsizei primcount)
{
return gl::DrawElementsInstancedANGLE(mode, count, type, indices, primcount);
}
@@ -1400,17 +1707,24 @@ void GL_APIENTRY glVertexAttribDivisorANGLE(GLuint index, GLuint divisor)
return gl::VertexAttribDivisorANGLE(index, divisor);
}
-void GL_APIENTRY glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary)
+void GL_APIENTRY glGetProgramBinaryOES(GLuint program,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary)
{
return gl::GetProgramBinaryOES(program, bufSize, length, binaryFormat, binary);
}
-void GL_APIENTRY glProgramBinaryOES(GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length)
+void GL_APIENTRY glProgramBinaryOES(GLuint program,
+ GLenum binaryFormat,
+ const void *binary,
+ GLint length)
{
return gl::ProgramBinaryOES(program, binaryFormat, binary, length);
}
-void* GL_APIENTRY glMapBufferOES(GLenum target, GLenum access)
+void *GL_APIENTRY glMapBufferOES(GLenum target, GLenum access)
{
return gl::MapBufferOES(target, access);
}
@@ -1420,12 +1734,15 @@ GLboolean GL_APIENTRY glUnmapBufferOES(GLenum target)
return gl::UnmapBufferOES(target);
}
-void GL_APIENTRY glGetBufferPointervOES(GLenum target, GLenum pname, GLvoid **params)
+void GL_APIENTRY glGetBufferPointervOES(GLenum target, GLenum pname, void **params)
{
return gl::GetBufferPointervOES(target, pname, params);
}
-void* GL_APIENTRY glMapBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
+void *GL_APIENTRY glMapBufferRangeEXT(GLenum target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access)
{
return gl::MapBufferRangeEXT(target, offset, length, access);
}
@@ -1562,4 +1879,697 @@ void GL_APIENTRY glGetPointervKHR(GLenum pname, void **params)
{
return gl::GetPointervKHR(pname, params);
}
+
+void GL_APIENTRY glBindUniformLocationCHROMIUM(GLuint program, GLint location, const GLchar *name)
+{
+ return gl::BindUniformLocationCHROMIUM(program, location, name);
+}
+
+void GL_APIENTRY glCoverageModulationCHROMIUM(GLenum components)
+{
+ return gl::CoverageModulationCHROMIUM(components);
+}
+
+// CHROMIUM_path_rendendering
+void GL_APIENTRY glMatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat *matrix)
+{
+ gl::MatrixLoadfCHROMIUM(matrixMode, matrix);
+}
+
+void GL_APIENTRY glMatrixLoadIdentityCHROMIUM(GLenum matrixMode)
+{
+ gl::MatrixLoadIdentityCHROMIUM(matrixMode);
+}
+
+GLuint GL_APIENTRY glGenPathsCHROMIUM(GLsizei range)
+{
+ return gl::GenPathsCHROMIUM(range);
+}
+
+void GL_APIENTRY glDeletePathsCHROMIUM(GLuint first, GLsizei range)
+{
+ gl::DeletePathsCHROMIUM(first, range);
+}
+
+GLboolean GL_APIENTRY glIsPathCHROMIUM(GLuint path)
+{
+ return gl::IsPathCHROMIUM(path);
+}
+
+void GL_APIENTRY glPathCommandsCHROMIUM(GLuint path,
+ GLsizei numCommands,
+ const GLubyte *commands,
+ GLsizei numCoords,
+ GLenum coordType,
+ const void *coords)
+{
+ gl::PathCommandsCHROMIUM(path, numCommands, commands, numCoords, coordType, coords);
+}
+
+void GL_APIENTRY glPathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value)
+{
+ gl::PathParameterfCHROMIUM(path, pname, value);
+}
+
+void GL_APIENTRY glPathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value)
+{
+ gl::PathParameteriCHROMIUM(path, pname, value);
+}
+
+void GL_APIENTRY glGetPathParameterfvCHROMIUM(GLuint path, GLenum pname, GLfloat *value)
+{
+ gl::GetPathParameterfCHROMIUM(path, pname, value);
+}
+
+void GL_APIENTRY glGetPathParameterivCHROMIUM(GLuint path, GLenum pname, GLint *value)
+{
+ gl::GetPathParameteriCHROMIUM(path, pname, value);
+}
+
+void GL_APIENTRY glPathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask)
+{
+ gl::PathStencilFuncCHROMIUM(func, ref, mask);
+}
+
+void GL_APIENTRY glStencilFillPathCHROMIUM(GLuint path, GLenum fillMode, GLuint mask)
+{
+ gl::StencilFillPathCHROMIUM(path, fillMode, mask);
+}
+
+void GL_APIENTRY glStencilStrokePathCHROMIUM(GLuint path, GLint reference, GLuint mask)
+{
+ gl::StencilStrokePathCHROMIUM(path, reference, mask);
+}
+
+void GL_APIENTRY glCoverFillPathCHROMIUM(GLuint path, GLenum coverMode)
+{
+ gl::CoverFillPathCHROMIUM(path, coverMode);
+}
+
+void GL_APIENTRY glCoverStrokePathCHROMIUM(GLuint path, GLenum coverMode)
+{
+ gl::CoverStrokePathCHROMIUM(path, coverMode);
+}
+
+void GL_APIENTRY glStencilThenCoverFillPathCHROMIUM(GLuint path,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode)
+{
+ gl::StencilThenCoverFillPathCHROMIUM(path, fillMode, mask, coverMode);
+}
+
+void GL_APIENTRY glStencilThenCoverStrokePathCHROMIUM(GLuint path,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode)
+{
+ gl::StencilThenCoverStrokePathCHROMIUM(path, reference, mask, coverMode);
+}
+
+void GL_APIENTRY glCoverFillPathInstancedCHROMIUM(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ gl::CoverFillPathInstancedCHROMIUM(numPaths, pathNameType, paths, pathBase, coverMode,
+ transformType, transformValues);
+}
+
+void GL_APIENTRY glCoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ gl::CoverStrokePathInstancedCHROMIUM(numPaths, pathNameType, paths, pathBase, coverMode,
+ transformType, transformValues);
+}
+
+void GL_APIENTRY glStencilFillPathInstancedCHROMIUM(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ gl::StencilFillPathInstancedCHROMIUM(numPaths, pathNameType, paths, pathBase, fillMode, mask,
+ transformType, transformValues);
+}
+
+void GL_APIENTRY glStencilStrokePathInstancedCHROMIUM(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ gl::StencilStrokePathInstancedCHROMIUM(numPaths, pathNameType, paths, pathBase, reference, mask,
+ transformType, transformValues);
+}
+
+void GL_APIENTRY glStencilThenCoverFillPathInstancedCHROMIUM(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLenum fillMode,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ gl::StencilThenCoverFillPathInstancedCHROMIUM(numPaths, pathNameType, paths, pathBase, fillMode,
+ mask, coverMode, transformType, transformValues);
+}
+
+void GL_APIENTRY glStencilThenCoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
+ GLenum pathNameType,
+ const void *paths,
+ GLuint pathBase,
+ GLint reference,
+ GLuint mask,
+ GLenum coverMode,
+ GLenum transformType,
+ const GLfloat *transformValues)
+{
+ gl::StencilThenCoverStrokePathInstancedCHROMIUM(numPaths, pathNameType, paths, pathBase,
+ reference, mask, coverMode, transformType,
+ transformValues);
+}
+
+void GL_APIENTRY glBindFragmentInputLocationCHROMIUM(GLuint program,
+ GLint location,
+ const GLchar *name)
+{
+ gl::BindFragmentInputLocationCHROMIUM(program, location, name);
+}
+
+void GL_APIENTRY glProgramPathFragmentInputGenCHROMIUM(GLuint program,
+ GLint location,
+ GLenum genMode,
+ GLint components,
+ const GLfloat *coeffs)
+{
+ gl::ProgramPathFragmentInputGenCHROMIUM(program, location, genMode, components, coeffs);
+}
+
+// GLES 3.1
+void GL_APIENTRY glDispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ)
+{
+ gl::DispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
+}
+
+void GL_APIENTRY glDispatchComputeIndirect(GLintptr indirect)
+{
+ gl::DispatchComputeIndirect(indirect);
+}
+
+void GL_APIENTRY glDrawArraysIndirect(GLenum mode, const void *indirect)
+{
+ gl::DrawArraysIndirect(mode, indirect);
+}
+
+void GL_APIENTRY glDrawElementsIndirect(GLenum mode, GLenum type, const void *indirect)
+{
+ gl::DrawElementsIndirect(mode, type, indirect);
+}
+
+void GL_APIENTRY glFramebufferParameteri(GLenum target, GLenum pname, GLint param)
+{
+ gl::FramebufferParameteri(target, pname, param);
+}
+
+void GL_APIENTRY glGetFramebufferParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+ gl::GetFramebufferParameteriv(target, pname, params);
+}
+
+void GL_APIENTRY glGetProgramInterfaceiv(GLuint program,
+ GLenum programInterface,
+ GLenum pname,
+ GLint *params)
+{
+ gl::GetProgramInterfaceiv(program, programInterface, pname, params);
+}
+
+GLuint GL_APIENTRY glGetProgramResourceIndex(GLuint program,
+ GLenum programInterface,
+ const GLchar *name)
+{
+ return gl::GetProgramResourceIndex(program, programInterface, name);
+}
+
+void GL_APIENTRY glGetProgramResourceName(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name)
+{
+ gl::GetProgramResourceName(program, programInterface, index, bufSize, length, name);
+}
+
+void GL_APIENTRY glGetProgramResourceiv(GLuint program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum *props,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ gl::GetProgramResourceiv(program, programInterface, index, propCount, props, bufSize, length,
+ params);
+}
+
+GLint GL_APIENTRY glGetProgramResourceLocation(GLuint program,
+ GLenum programInterface,
+ const GLchar *name)
+{
+ return gl::GetProgramResourceLocation(program, programInterface, name);
+}
+
+void GL_APIENTRY glUseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program)
+{
+ gl::UseProgramStages(pipeline, stages, program);
+}
+
+void GL_APIENTRY glActiveShaderProgram(GLuint pipeline, GLuint program)
+{
+ gl::ActiveShaderProgram(pipeline, program);
+}
+
+GLuint GL_APIENTRY glCreateShaderProgramv(GLenum type, GLsizei count, const GLchar *const *strings)
+{
+ return gl::CreateShaderProgramv(type, count, strings);
+}
+
+void GL_APIENTRY glBindProgramPipeline(GLuint pipeline)
+{
+ gl::BindProgramPipeline(pipeline);
+}
+
+void GL_APIENTRY glDeleteProgramPipelines(GLsizei n, const GLuint *pipelines)
+{
+ gl::DeleteProgramPipelines(n, pipelines);
+}
+
+void GL_APIENTRY glGenProgramPipelines(GLsizei n, GLuint *pipelines)
+{
+ gl::GenProgramPipelines(n, pipelines);
+}
+
+GLboolean GL_APIENTRY glIsProgramPipeline(GLuint pipeline)
+{
+ return gl::IsProgramPipeline(pipeline);
+}
+
+void GL_APIENTRY glGetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint *params)
+{
+ gl::GetProgramPipelineiv(pipeline, pname, params);
+}
+
+void GL_APIENTRY glProgramUniform1i(GLuint program, GLint location, GLint v0)
+{
+ gl::ProgramUniform1i(program, location, v0);
+}
+
+void GL_APIENTRY glProgramUniform2i(GLuint program, GLint location, GLint v0, GLint v1)
+{
+ gl::ProgramUniform2i(program, location, v0, v1);
}
+
+void GL_APIENTRY glProgramUniform3i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2)
+{
+ gl::ProgramUniform3i(program, location, v0, v1, v2);
+}
+
+void GL_APIENTRY
+glProgramUniform4i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
+{
+ gl::ProgramUniform4i(program, location, v0, v1, v2, v3);
+}
+
+void GL_APIENTRY glProgramUniform1ui(GLuint program, GLint location, GLuint v0)
+{
+ gl::ProgramUniform1ui(program, location, v0);
+}
+
+void GL_APIENTRY glProgramUniform2ui(GLuint program, GLint location, GLuint v0, GLuint v1)
+{
+ gl::ProgramUniform2ui(program, location, v0, v1);
+}
+
+void GL_APIENTRY
+glProgramUniform3ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2)
+{
+ gl::ProgramUniform3ui(program, location, v0, v1, v2);
+}
+
+void GL_APIENTRY
+glProgramUniform4ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+{
+ gl::ProgramUniform4ui(program, location, v0, v1, v2, v3);
+}
+
+void GL_APIENTRY glProgramUniform1f(GLuint program, GLint location, GLfloat v0)
+{
+ gl::ProgramUniform1f(program, location, v0);
+}
+
+void GL_APIENTRY glProgramUniform2f(GLuint program, GLint location, GLfloat v0, GLfloat v1)
+{
+ gl::ProgramUniform2f(program, location, v0, v1);
+}
+
+void GL_APIENTRY
+glProgramUniform3f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
+{
+ gl::ProgramUniform3f(program, location, v0, v1, v2);
+}
+
+void GL_APIENTRY
+glProgramUniform4f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
+{
+ gl::ProgramUniform4f(program, location, v0, v1, v2, v3);
+}
+
+void GL_APIENTRY glProgramUniform1iv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLint *value)
+{
+ gl::ProgramUniform1iv(program, location, count, value);
+}
+
+void GL_APIENTRY glProgramUniform2iv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLint *value)
+{
+ gl::ProgramUniform2iv(program, location, count, value);
+}
+
+void GL_APIENTRY glProgramUniform3iv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLint *value)
+{
+ gl::ProgramUniform3iv(program, location, count, value);
+}
+
+void GL_APIENTRY glProgramUniform4iv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLint *value)
+{
+ gl::ProgramUniform4iv(program, location, count, value);
+}
+
+void GL_APIENTRY glProgramUniform1uiv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLuint *value)
+{
+ gl::ProgramUniform1uiv(program, location, count, value);
+}
+
+void GL_APIENTRY glProgramUniform2uiv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLuint *value)
+{
+ gl::ProgramUniform2uiv(program, location, count, value);
+}
+
+void GL_APIENTRY glProgramUniform3uiv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLuint *value)
+{
+ gl::ProgramUniform3uiv(program, location, count, value);
+}
+
+void GL_APIENTRY glProgramUniform4uiv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLuint *value)
+{
+ gl::ProgramUniform4uiv(program, location, count, value);
+}
+
+void GL_APIENTRY glProgramUniform1fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLfloat *value)
+{
+ gl::ProgramUniform1fv(program, location, count, value);
+}
+
+void GL_APIENTRY glProgramUniform2fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLfloat *value)
+{
+ gl::ProgramUniform2fv(program, location, count, value);
+}
+
+void GL_APIENTRY glProgramUniform3fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLfloat *value)
+{
+ gl::ProgramUniform3fv(program, location, count, value);
+}
+
+void GL_APIENTRY glProgramUniform4fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ const GLfloat *value)
+{
+ gl::ProgramUniform4fv(program, location, count, value);
+}
+
+void GL_APIENTRY glProgramUniformMatrix2fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ gl::ProgramUniformMatrix2fv(program, location, count, transpose, value);
+}
+
+void GL_APIENTRY glProgramUniformMatrix3fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ gl::ProgramUniformMatrix3fv(program, location, count, transpose, value);
+}
+
+void GL_APIENTRY glProgramUniformMatrix4fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ gl::ProgramUniformMatrix4fv(program, location, count, transpose, value);
+}
+
+void GL_APIENTRY glProgramUniformMatrix2x3fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ gl::ProgramUniformMatrix2x3fv(program, location, count, transpose, value);
+}
+
+void GL_APIENTRY glProgramUniformMatrix3x2fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ gl::ProgramUniformMatrix3x2fv(program, location, count, transpose, value);
+}
+
+void GL_APIENTRY glProgramUniformMatrix2x4fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ gl::ProgramUniformMatrix2x4fv(program, location, count, transpose, value);
+}
+
+void GL_APIENTRY glProgramUniformMatrix4x2fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ gl::ProgramUniformMatrix4x2fv(program, location, count, transpose, value);
+}
+
+void GL_APIENTRY glProgramUniformMatrix3x4fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ gl::ProgramUniformMatrix3x4fv(program, location, count, transpose, value);
+}
+
+void GL_APIENTRY glProgramUniformMatrix4x3fv(GLuint program,
+ GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ gl::ProgramUniformMatrix4x3fv(program, location, count, transpose, value);
+}
+
+void GL_APIENTRY glValidateProgramPipeline(GLuint pipeline)
+{
+ gl::ValidateProgramPipeline(pipeline);
+}
+
+void GL_APIENTRY glGetProgramPipelineInfoLog(GLuint pipeline,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *infoLog)
+{
+ gl::GetProgramPipelineInfoLog(pipeline, bufSize, length, infoLog);
+}
+
+void GL_APIENTRY glBindImageTexture(GLuint unit,
+ GLuint texture,
+ GLint level,
+ GLboolean layered,
+ GLint layer,
+ GLenum access,
+ GLenum format)
+{
+ gl::BindImageTexture(unit, texture, level, layered, layer, access, format);
+}
+
+void GL_APIENTRY glGetBooleani_v(GLenum target, GLuint index, GLboolean *data)
+{
+ gl::GetBooleani_v(target, index, data);
+}
+
+void GL_APIENTRY glMemoryBarrier(GLbitfield barriers)
+{
+ gl::MemoryBarrier(barriers);
+}
+
+void GL_APIENTRY glMemoryBarrierByRegion(GLbitfield barriers)
+{
+ gl::MemoryBarrierByRegion(barriers);
+}
+
+void GL_APIENTRY glTexStorage2DMultisample(GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedsamplelocations)
+{
+ gl::TexStorage2DMultisample(target, samples, internalformat, width, height,
+ fixedsamplelocations);
+}
+
+void GL_APIENTRY glGetMultisamplefv(GLenum pname, GLuint index, GLfloat *val)
+{
+ gl::GetMultisamplefv(pname, index, val);
+}
+
+void GL_APIENTRY glSampleMaski(GLuint maskNumber, GLbitfield mask)
+{
+ gl::SampleMaski(maskNumber, mask);
+}
+
+void GL_APIENTRY glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params)
+{
+ gl::GetTexLevelParameteriv(target, level, pname, params);
+}
+
+void GL_APIENTRY glGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat *params)
+{
+ gl::GetTexLevelParameterfv(target, level, pname, params);
+}
+
+void GL_APIENTRY glBindVertexBuffer(GLuint bindingindex,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizei stride)
+{
+ gl::BindVertexBuffer(bindingindex, buffer, offset, stride);
+}
+
+void GL_APIENTRY glVertexAttribFormat(GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLuint relativeoffset)
+{
+ gl::VertexAttribFormat(attribindex, size, type, normalized, relativeoffset);
+}
+
+void GL_APIENTRY glVertexAttribIFormat(GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLuint relativeoffset)
+{
+ gl::VertexAttribIFormat(attribindex, size, type, relativeoffset);
+}
+
+void GL_APIENTRY glVertexAttribBinding(GLuint attribindex, GLuint bindingindex)
+{
+ gl::VertexAttribBinding(attribindex, bindingindex);
+}
+
+void GL_APIENTRY glVertexBindingDivisor(GLuint bindingindex, GLuint divisor)
+{
+ gl::VertexBindingDivisor(bindingindex, divisor);
+}
+
+void GL_APIENTRY glFramebufferTextureMultiviewLayeredANGLE(GLenum target,
+ GLenum attachment,
+ GLuint texture,
+ GLint level,
+ GLint baseViewIndex,
+ GLsizei numViews)
+{
+ gl::FramebufferTextureMultiviewLayeredANGLE(target, attachment, texture, level, baseViewIndex,
+ numViews);
+}
+
+void GL_APIENTRY glFramebufferTextureMultiviewSideBySideANGLE(GLenum target,
+ GLenum attachment,
+ GLuint texture,
+ GLint level,
+ GLsizei numViews,
+ const GLint *viewportOffsets)
+{
+ gl::FramebufferTextureMultiviewSideBySideANGLE(target, attachment, texture, level, numViews,
+ viewportOffsets);
+}
+
+void GL_APIENTRY glRequestExtensionANGLE(const GLchar *name)
+{
+ gl::RequestExtensionANGLE(name);
+}
+
+} // extern "C"
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def
index 0aebb6c864..2ff4cc0579 100644
--- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def
+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def
@@ -202,6 +202,38 @@ EXPORTS
glGetQueryObjectivEXT @315
glGetQueryObjecti64vEXT @316
glGetQueryObjectui64vEXT @317
+ glBindUniformLocationCHROMIUM @318
+ glCoverageModulationCHROMIUM @319
+
+ glMatrixLoadfCHROMIUM @320
+ glMatrixLoadIdentityCHROMIUM @321
+ glGenPathsCHROMIUM @322
+ glDeletePathsCHROMIUM @323
+ glIsPathCHROMIUM @324
+ glPathCommandsCHROMIUM @325
+ glPathParameterfCHROMIUM @326
+ glPathParameteriCHROMIUM @327
+ glGetPathParameterfvCHROMIUM @328
+ glGetPathParameterivCHROMIUM @329
+ glPathStencilFuncCHROMIUM @330
+ glStencilFillPathCHROMIUM @331
+ glStencilStrokePathCHROMIUM @332
+ glCoverFillPathCHROMIUM @333
+ glCoverStrokePathCHROMIUM @334
+ glStencilThenCoverFillPathCHROMIUM @335
+ glStencilThenCoverStrokePathCHROMIUM @336
+ glCoverFillPathInstancedCHROMIUM @337
+ glCoverStrokePathInstancedCHROMIUM @338
+ glStencilStrokePathInstancedCHROMIUM @339
+ glStencilFillPathInstancedCHROMIUM @340
+ glStencilThenCoverFillPathInstancedCHROMIUM @341
+ glStencilThenCoverStrokePathInstancedCHROMIUM @342
+ glBindFragmentInputLocationCHROMIUM @343
+ glProgramPathFragmentInputGenCHROMIUM @344
+
+ glFramebufferTextureMultiviewLayeredANGLE @413
+ glFramebufferTextureMultiviewSideBySideANGLE @414
+ glRequestExtensionANGLE @415
; GLES 3.0 Functions
glReadBuffer @180
@@ -309,7 +341,72 @@ EXPORTS
glTexStorage3D @282
glGetInternalformativ @283
- ; ANGLE Platform Implementation
- ANGLEPlatformCurrent @290
- ANGLEPlatformInitialize @291
- ANGLEPlatformShutdown @292
+ ; GLES 3.1 Functions
+ glDispatchCompute @345
+ glDispatchComputeIndirect @346
+ glDrawArraysIndirect @347
+ glDrawElementsIndirect @348
+ glFramebufferParameteri @349
+ glGetFramebufferParameteriv @350
+ glGetProgramInterfaceiv @351
+ glGetProgramResourceIndex @352
+ glGetProgramResourceName @353
+ glGetProgramResourceiv @354
+ glGetProgramResourceLocation @355
+ glUseProgramStages @356
+ glActiveShaderProgram @357
+ glCreateShaderProgramv @358
+ glBindProgramPipeline @359
+ glDeleteProgramPipelines @360
+ glGenProgramPipelines @361
+ glIsProgramPipeline @362
+ glGetProgramPipelineiv @363
+ glProgramUniform1i @364
+ glProgramUniform2i @365
+ glProgramUniform3i @366
+ glProgramUniform4i @367
+ glProgramUniform1ui @368
+ glProgramUniform2ui @369
+ glProgramUniform3ui @370
+ glProgramUniform4ui @371
+ glProgramUniform1f @372
+ glProgramUniform2f @373
+ glProgramUniform3f @374
+ glProgramUniform4f @375
+ glProgramUniform1iv @376
+ glProgramUniform2iv @377
+ glProgramUniform3iv @378
+ glProgramUniform4iv @379
+ glProgramUniform1uiv @380
+ glProgramUniform2uiv @381
+ glProgramUniform3uiv @382
+ glProgramUniform4uiv @383
+ glProgramUniform1fv @384
+ glProgramUniform2fv @385
+ glProgramUniform3fv @386
+ glProgramUniform4fv @387
+ glProgramUniformMatrix2fv @388
+ glProgramUniformMatrix3fv @389
+ glProgramUniformMatrix4fv @390
+ glProgramUniformMatrix2x3fv @391
+ glProgramUniformMatrix3x2fv @392
+ glProgramUniformMatrix2x4fv @393
+ glProgramUniformMatrix4x2fv @394
+ glProgramUniformMatrix3x4fv @395
+ glProgramUniformMatrix4x3fv @396
+ glValidateProgramPipeline @397
+ glGetProgramPipelineInfoLog @398
+ glBindImageTexture @399
+ glGetBooleani_v @400
+ glMemoryBarrier @401
+ glMemoryBarrierByRegion @402
+ glTexStorage2DMultisample @403
+ glGetMultisamplefv @404
+ glSampleMaski @405
+ glGetTexLevelParameteriv @406
+ glGetTexLevelParameterfv @407
+ glBindVertexBuffer @408
+ glVertexAttribFormat @409
+ glVertexAttribIFormat @410
+ glVertexAttribBinding @411
+ glVertexBindingDivisor @412
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def
index db17bb487b..2ff4cc0579 100644
--- a/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def
+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def
@@ -1,316 +1,412 @@
LIBRARY libGLESv2
EXPORTS
- glActiveTexture@4 @1
- glAttachShader@8 @2
- glBindAttribLocation@12 @3
- glBindBuffer@8 @4
- glBindFramebuffer@8 @5
- glBindRenderbuffer@8 @6
- glBindTexture@8 @7
- glBlendColor@16 @8
- glBlendEquation@4 @9
- glBlendEquationSeparate@8 @10
- glBlendFunc@8 @11
- glBlendFuncSeparate@16 @12
- glBufferData@16 @13
- glBufferSubData@16 @14
- glCheckFramebufferStatus@4 @15
- glClear@4 @16
- glClearColor@16 @17
- glClearDepthf@4 @18
- glClearStencil@4 @19
- glColorMask@16 @20
- glCompileShader@4 @21
- glCompressedTexImage2D@32 @22
- glCompressedTexSubImage2D@36 @23
- glCopyTexImage2D@32 @24
- glCopyTexSubImage2D@32 @25
- glCreateProgram@0 @26
- glCreateShader@4 @27
- glCullFace@4 @28
- glDeleteBuffers@8 @29
- glDeleteFramebuffers@8 @30
- glDeleteProgram@4 @32
- glDeleteRenderbuffers@8 @33
- glDeleteShader@4 @34
- glDeleteTextures@8 @31
- glDepthFunc@4 @36
- glDepthMask@4 @37
- glDepthRangef@8 @38
- glDetachShader@8 @35
- glDisable@4 @39
- glDisableVertexAttribArray@4 @40
- glDrawArrays@12 @41
- glDrawElements@16 @42
- glEnable@4 @43
- glEnableVertexAttribArray@4 @44
- glFinish@0 @45
- glFlush@0 @46
- glFramebufferRenderbuffer@16 @47
- glFramebufferTexture2D@20 @48
- glFrontFace@4 @49
- glGenBuffers@8 @50
- glGenFramebuffers@8 @52
- glGenRenderbuffers@8 @53
- glGenTextures@8 @54
- glGenerateMipmap@4 @51
- glGetActiveAttrib@28 @55
- glGetActiveUniform@28 @56
- glGetAttachedShaders@16 @57
- glGetAttribLocation@8 @58
- glGetBooleanv@8 @59
- glGetBufferParameteriv@12 @60
- glGetError@0 @61
- glGetFloatv@8 @62
- glGetFramebufferAttachmentParameteriv@16 @63
- glGetIntegerv@8 @64
- glGetProgramInfoLog@16 @66
- glGetProgramiv@12 @65
- glGetRenderbufferParameteriv@12 @67
- glGetShaderInfoLog@16 @69
- glGetShaderPrecisionFormat@16 @70
- glGetShaderSource@16 @71
- glGetShaderiv@12 @68
- glGetString@4 @72
- glGetTexParameterfv@12 @73
- glGetTexParameteriv@12 @74
- glGetUniformLocation@8 @77
- glGetUniformfv@12 @75
- glGetUniformiv@12 @76
- glGetVertexAttribPointerv@12 @80
- glGetVertexAttribfv@12 @78
- glGetVertexAttribiv@12 @79
- glHint@8 @81
- glIsBuffer@4 @82
- glIsEnabled@4 @83
- glIsFramebuffer@4 @84
- glIsProgram@4 @85
- glIsRenderbuffer@4 @86
- glIsShader@4 @87
- glIsTexture@4 @88
- glLineWidth@4 @89
- glLinkProgram@4 @90
- glPixelStorei@8 @91
- glPolygonOffset@8 @92
- glReadPixels@28 @93
- glReleaseShaderCompiler@0 @94
- glRenderbufferStorage@16 @95
- glSampleCoverage@8 @96
- glScissor@16 @97
- glShaderBinary@20 @98
- glShaderSource@16 @99
- glStencilFunc@12 @100
- glStencilFuncSeparate@16 @101
- glStencilMask@4 @102
- glStencilMaskSeparate@8 @103
- glStencilOp@12 @104
- glStencilOpSeparate@16 @105
- glTexImage2D@36 @106
- glTexParameterf@12 @107
- glTexParameterfv@12 @108
- glTexParameteri@12 @109
- glTexParameteriv@12 @110
- glTexSubImage2D@36 @111
- glUniform1f@8 @112
- glUniform1fv@12 @113
- glUniform1i@8 @114
- glUniform1iv@12 @115
- glUniform2f@12 @116
- glUniform2fv@12 @117
- glUniform2i@12 @118
- glUniform2iv@12 @119
- glUniform3f@16 @120
- glUniform3fv@12 @121
- glUniform3i@16 @122
- glUniform3iv@12 @123
- glUniform4f@20 @124
- glUniform4fv@12 @125
- glUniform4i@20 @126
- glUniform4iv@12 @127
- glUniformMatrix2fv@16 @128
- glUniformMatrix3fv@16 @129
- glUniformMatrix4fv@16 @130
- glUseProgram@4 @131
- glValidateProgram@4 @132
- glVertexAttrib1f@8 @133
- glVertexAttrib1fv@8 @134
- glVertexAttrib2f@12 @135
- glVertexAttrib2fv@8 @136
- glVertexAttrib3f@16 @137
- glVertexAttrib3fv@8 @138
- glVertexAttrib4f@20 @139
- glVertexAttrib4fv@8 @140
- glVertexAttribPointer@24 @141
- glViewport@16 @142
+ glActiveTexture @1
+ glAttachShader @2
+ glBindAttribLocation @3
+ glBindBuffer @4
+ glBindFramebuffer @5
+ glBindRenderbuffer @6
+ glBindTexture @7
+ glBlendColor @8
+ glBlendEquation @9
+ glBlendEquationSeparate @10
+ glBlendFunc @11
+ glBlendFuncSeparate @12
+ glBufferData @13
+ glBufferSubData @14
+ glCheckFramebufferStatus @15
+ glClear @16
+ glClearColor @17
+ glClearDepthf @18
+ glClearStencil @19
+ glColorMask @20
+ glCompileShader @21
+ glCompressedTexImage2D @22
+ glCompressedTexSubImage2D @23
+ glCopyTexImage2D @24
+ glCopyTexSubImage2D @25
+ glCreateProgram @26
+ glCreateShader @27
+ glCullFace @28
+ glDeleteBuffers @29
+ glDeleteFramebuffers @30
+ glDeleteProgram @32
+ glDeleteRenderbuffers @33
+ glDeleteShader @34
+ glDeleteTextures @31
+ glDepthFunc @36
+ glDepthMask @37
+ glDepthRangef @38
+ glDetachShader @35
+ glDisable @39
+ glDisableVertexAttribArray @40
+ glDrawArrays @41
+ glDrawElements @42
+ glEnable @43
+ glEnableVertexAttribArray @44
+ glFinish @45
+ glFlush @46
+ glFramebufferRenderbuffer @47
+ glFramebufferTexture2D @48
+ glFrontFace @49
+ glGenBuffers @50
+ glGenFramebuffers @52
+ glGenRenderbuffers @53
+ glGenTextures @54
+ glGenerateMipmap @51
+ glGetActiveAttrib @55
+ glGetActiveUniform @56
+ glGetAttachedShaders @57
+ glGetAttribLocation @58
+ glGetBooleanv @59
+ glGetBufferParameteriv @60
+ glGetError @61
+ glGetFloatv @62
+ glGetFramebufferAttachmentParameteriv @63
+ glGetIntegerv @64
+ glGetProgramInfoLog @66
+ glGetProgramiv @65
+ glGetRenderbufferParameteriv @67
+ glGetShaderInfoLog @69
+ glGetShaderPrecisionFormat @70
+ glGetShaderSource @71
+ glGetShaderiv @68
+ glGetString @72
+ glGetTexParameterfv @73
+ glGetTexParameteriv @74
+ glGetUniformLocation @77
+ glGetUniformfv @75
+ glGetUniformiv @76
+ glGetVertexAttribPointerv @80
+ glGetVertexAttribfv @78
+ glGetVertexAttribiv @79
+ glHint @81
+ glIsBuffer @82
+ glIsEnabled @83
+ glIsFramebuffer @84
+ glIsProgram @85
+ glIsRenderbuffer @86
+ glIsShader @87
+ glIsTexture @88
+ glLineWidth @89
+ glLinkProgram @90
+ glPixelStorei @91
+ glPolygonOffset @92
+ glReadPixels @93
+ glReleaseShaderCompiler @94
+ glRenderbufferStorage @95
+ glSampleCoverage @96
+ glScissor @97
+ glShaderBinary @98
+ glShaderSource @99
+ glStencilFunc @100
+ glStencilFuncSeparate @101
+ glStencilMask @102
+ glStencilMaskSeparate @103
+ glStencilOp @104
+ glStencilOpSeparate @105
+ glTexImage2D @106
+ glTexParameterf @107
+ glTexParameterfv @108
+ glTexParameteri @109
+ glTexParameteriv @110
+ glTexSubImage2D @111
+ glUniform1f @112
+ glUniform1fv @113
+ glUniform1i @114
+ glUniform1iv @115
+ glUniform2f @116
+ glUniform2fv @117
+ glUniform2i @118
+ glUniform2iv @119
+ glUniform3f @120
+ glUniform3fv @121
+ glUniform3i @122
+ glUniform3iv @123
+ glUniform4f @124
+ glUniform4fv @125
+ glUniform4i @126
+ glUniform4iv @127
+ glUniformMatrix2fv @128
+ glUniformMatrix3fv @129
+ glUniformMatrix4fv @130
+ glUseProgram @131
+ glValidateProgram @132
+ glVertexAttrib1f @133
+ glVertexAttrib1fv @134
+ glVertexAttrib2f @135
+ glVertexAttrib2fv @136
+ glVertexAttrib3f @137
+ glVertexAttrib3fv @138
+ glVertexAttrib4f @139
+ glVertexAttrib4fv @140
+ glVertexAttribPointer @141
+ glViewport @142
; Extensions
- glBlitFramebufferANGLE@40 @149
- glRenderbufferStorageMultisampleANGLE@20 @150
- glDeleteFencesNV@8 @151
- glFinishFenceNV@4 @152
- glGenFencesNV@8 @153
- glGetFenceivNV@12 @154
- glIsFenceNV@4 @155
- glSetFenceNV@8 @156
- glTestFenceNV@4 @157
- glGetTranslatedShaderSourceANGLE@16 @159
- glTexStorage2DEXT@20 @160
- glGetGraphicsResetStatusEXT@0 @161
- glReadnPixelsEXT@32 @162
- glGetnUniformfvEXT@16 @163
- glGetnUniformivEXT@16 @164
- glGenQueriesEXT@8 @165
- glDeleteQueriesEXT@8 @166
- glIsQueryEXT@4 @167
- glBeginQueryEXT@8 @168
- glEndQueryEXT@4 @169
- glGetQueryivEXT@12 @170
- glGetQueryObjectuivEXT@12 @171
- glVertexAttribDivisorANGLE@8 @172
- glDrawArraysInstancedANGLE@16 @173
- glDrawElementsInstancedANGLE@20 @174
- glProgramBinaryOES@16 @175
- glGetProgramBinaryOES@20 @176
- glDrawBuffersEXT@8 @179
- glMapBufferOES@8 @285
- glUnmapBufferOES@4 @286
- glGetBufferPointervOES@12 @287
- glMapBufferRangeEXT@16 @288
- glFlushMappedBufferRangeEXT@12 @289
- glDiscardFramebufferEXT@12 @293
- glInsertEventMarkerEXT@8 @294
- glPushGroupMarkerEXT@8 @295
- glPopGroupMarkerEXT@0 @296
- glEGLImageTargetTexture2DOES@8 @297
- glEGLImageTargetRenderbufferStorageOES@8 @298
- glBindVertexArrayOES@4 @299
- glDeleteVertexArraysOES@8 @300
- glGenVertexArraysOES@8 @301
- glIsVertexArrayOES@4 @302
- glDebugMessageControlKHR@24 @303
- glDebugMessageInsertKHR@24 @304
- glDebugMessageCallbackKHR@8 @305
- glGetDebugMessageLogKHR@32 @306
- glPushDebugGroupKHR@16 @307
- glPopDebugGroupKHR@0 @308
- glObjectLabelKHR@16 @309
- glGetObjectLabelKHR@20 @310
- glObjectPtrLabelKHR@12 @311
- glGetObjectPtrLabelKHR@16 @312
- glGetPointervKHR@8 @313
- glQueryCounterEXT@8 @314
- glGetQueryObjectivEXT@12 @315
- glGetQueryObjecti64vEXT@12 @316
- glGetQueryObjectui64vEXT@12 @317
+ glBlitFramebufferANGLE @149
+ glRenderbufferStorageMultisampleANGLE @150
+ glDeleteFencesNV @151
+ glFinishFenceNV @152
+ glGenFencesNV @153
+ glGetFenceivNV @154
+ glIsFenceNV @155
+ glSetFenceNV @156
+ glTestFenceNV @157
+ glGetTranslatedShaderSourceANGLE @159
+ glTexStorage2DEXT @160
+ glGetGraphicsResetStatusEXT @161
+ glReadnPixelsEXT @162
+ glGetnUniformfvEXT @163
+ glGetnUniformivEXT @164
+ glGenQueriesEXT @165
+ glDeleteQueriesEXT @166
+ glIsQueryEXT @167
+ glBeginQueryEXT @168
+ glEndQueryEXT @169
+ glGetQueryivEXT @170
+ glGetQueryObjectuivEXT @171
+ glVertexAttribDivisorANGLE @172
+ glDrawArraysInstancedANGLE @173
+ glDrawElementsInstancedANGLE @174
+ glProgramBinaryOES @175
+ glGetProgramBinaryOES @176
+ glDrawBuffersEXT @179
+ glMapBufferOES @285
+ glUnmapBufferOES @286
+ glGetBufferPointervOES @287
+ glMapBufferRangeEXT @288
+ glFlushMappedBufferRangeEXT @289
+ glDiscardFramebufferEXT @293
+ glInsertEventMarkerEXT @294
+ glPushGroupMarkerEXT @295
+ glPopGroupMarkerEXT @296
+ glEGLImageTargetTexture2DOES @297
+ glEGLImageTargetRenderbufferStorageOES @298
+ glBindVertexArrayOES @299
+ glDeleteVertexArraysOES @300
+ glGenVertexArraysOES @301
+ glIsVertexArrayOES @302
+ glDebugMessageControlKHR @303
+ glDebugMessageInsertKHR @304
+ glDebugMessageCallbackKHR @305
+ glGetDebugMessageLogKHR @306
+ glPushDebugGroupKHR @307
+ glPopDebugGroupKHR @308
+ glObjectLabelKHR @309
+ glGetObjectLabelKHR @310
+ glObjectPtrLabelKHR @311
+ glGetObjectPtrLabelKHR @312
+ glGetPointervKHR @313
+ glQueryCounterEXT @314
+ glGetQueryObjectivEXT @315
+ glGetQueryObjecti64vEXT @316
+ glGetQueryObjectui64vEXT @317
+ glBindUniformLocationCHROMIUM @318
+ glCoverageModulationCHROMIUM @319
+
+ glMatrixLoadfCHROMIUM @320
+ glMatrixLoadIdentityCHROMIUM @321
+ glGenPathsCHROMIUM @322
+ glDeletePathsCHROMIUM @323
+ glIsPathCHROMIUM @324
+ glPathCommandsCHROMIUM @325
+ glPathParameterfCHROMIUM @326
+ glPathParameteriCHROMIUM @327
+ glGetPathParameterfvCHROMIUM @328
+ glGetPathParameterivCHROMIUM @329
+ glPathStencilFuncCHROMIUM @330
+ glStencilFillPathCHROMIUM @331
+ glStencilStrokePathCHROMIUM @332
+ glCoverFillPathCHROMIUM @333
+ glCoverStrokePathCHROMIUM @334
+ glStencilThenCoverFillPathCHROMIUM @335
+ glStencilThenCoverStrokePathCHROMIUM @336
+ glCoverFillPathInstancedCHROMIUM @337
+ glCoverStrokePathInstancedCHROMIUM @338
+ glStencilStrokePathInstancedCHROMIUM @339
+ glStencilFillPathInstancedCHROMIUM @340
+ glStencilThenCoverFillPathInstancedCHROMIUM @341
+ glStencilThenCoverStrokePathInstancedCHROMIUM @342
+ glBindFragmentInputLocationCHROMIUM @343
+ glProgramPathFragmentInputGenCHROMIUM @344
+
+ glFramebufferTextureMultiviewLayeredANGLE @413
+ glFramebufferTextureMultiviewSideBySideANGLE @414
+ glRequestExtensionANGLE @415
; GLES 3.0 Functions
- glReadBuffer@4 @180
- glDrawRangeElements@24 @181
- glTexImage3D@40 @182
- glTexSubImage3D@44 @183
- glCopyTexSubImage3D@36 @184
- glCompressedTexImage3D@36 @185
- glCompressedTexSubImage3D@44 @186
- glGenQueries@8 @187
- glDeleteQueries@8 @188
- glIsQuery@4 @189
- glBeginQuery@8 @190
- glEndQuery@4 @191
- glGetQueryiv@12 @192
- glGetQueryObjectuiv@12 @193
- glUnmapBuffer@4 @194
- glGetBufferPointerv@12 @195
- glDrawBuffers@8 @196
- glUniformMatrix2x3fv@16 @197
- glUniformMatrix3x2fv@16 @198
- glUniformMatrix2x4fv@16 @199
- glUniformMatrix4x2fv@16 @200
- glUniformMatrix3x4fv@16 @201
- glUniformMatrix4x3fv@16 @202
- glBlitFramebuffer@40 @203
- glRenderbufferStorageMultisample@20 @204
- glFramebufferTextureLayer@20 @205
- glMapBufferRange@16 @206
- glFlushMappedBufferRange@12 @207
- glBindVertexArray@4 @208
- glDeleteVertexArrays@8 @209
- glGenVertexArrays@8 @210
- glIsVertexArray@4 @211
- glGetIntegeri_v@12 @212
- glBeginTransformFeedback@4 @213
- glEndTransformFeedback@0 @214
- glBindBufferRange@20 @215
- glBindBufferBase@12 @216
- glTransformFeedbackVaryings@16 @217
- glGetTransformFeedbackVarying@28 @218
- glVertexAttribIPointer@20 @219
- glGetVertexAttribIiv@12 @220
- glGetVertexAttribIuiv@12 @221
- glVertexAttribI4i@20 @222
- glVertexAttribI4ui@20 @223
- glVertexAttribI4iv@8 @224
- glVertexAttribI4uiv@8 @225
- glGetUniformuiv@12 @226
- glGetFragDataLocation@8 @227
- glUniform1ui@8 @228
- glUniform2ui@12 @229
- glUniform3ui@16 @230
- glUniform4ui@20 @231
- glUniform1uiv@12 @232
- glUniform2uiv@12 @233
- glUniform3uiv@12 @234
- glUniform4uiv@12 @235
- glClearBufferiv@12 @236
- glClearBufferuiv@12 @237
- glClearBufferfv@12 @238
- glClearBufferfi@16 @239
- glGetStringi@8 @240
- glCopyBufferSubData@20 @241
- glGetUniformIndices@16 @242
- glGetActiveUniformsiv@20 @243
- glGetUniformBlockIndex@8 @244
- glGetActiveUniformBlockiv@16 @245
- glGetActiveUniformBlockName@20 @246
- glUniformBlockBinding@12 @247
- glDrawArraysInstanced@16 @248
- glDrawElementsInstanced@20 @249
- glFenceSync@8 @250
- glIsSync@4 @251
- glDeleteSync@4 @252
- glClientWaitSync@16 @253
- glWaitSync@16 @254
- glGetInteger64v@8 @255
- glGetSynciv@20 @256
- glGetInteger64i_v@12 @257
- glGetBufferParameteri64v@12 @258
- glGenSamplers@8 @259
- glDeleteSamplers@8 @260
- glIsSampler@4 @261
- glBindSampler@8 @262
- glSamplerParameteri@12 @263
- glSamplerParameteriv@12 @264
- glSamplerParameterf@12 @265
- glSamplerParameterfv@12 @266
- glGetSamplerParameteriv@12 @267
- glGetSamplerParameterfv@12 @268
- glVertexAttribDivisor@8 @269
- glBindTransformFeedback@8 @270
- glDeleteTransformFeedbacks@8 @271
- glGenTransformFeedbacks@8 @272
- glIsTransformFeedback@4 @273
- glPauseTransformFeedback@0 @274
- glResumeTransformFeedback@0 @275
- glGetProgramBinary@20 @276
- glProgramBinary@16 @277
- glProgramParameteri@12 @278
- glInvalidateFramebuffer@12 @279
- glInvalidateSubFramebuffer@28 @280
- glTexStorage2D@20 @281
- glTexStorage3D@24 @282
- glGetInternalformativ@20 @283
+ glReadBuffer @180
+ glDrawRangeElements @181
+ glTexImage3D @182
+ glTexSubImage3D @183
+ glCopyTexSubImage3D @184
+ glCompressedTexImage3D @185
+ glCompressedTexSubImage3D @186
+ glGenQueries @187
+ glDeleteQueries @188
+ glIsQuery @189
+ glBeginQuery @190
+ glEndQuery @191
+ glGetQueryiv @192
+ glGetQueryObjectuiv @193
+ glUnmapBuffer @194
+ glGetBufferPointerv @195
+ glDrawBuffers @196
+ glUniformMatrix2x3fv @197
+ glUniformMatrix3x2fv @198
+ glUniformMatrix2x4fv @199
+ glUniformMatrix4x2fv @200
+ glUniformMatrix3x4fv @201
+ glUniformMatrix4x3fv @202
+ glBlitFramebuffer @203
+ glRenderbufferStorageMultisample @204
+ glFramebufferTextureLayer @205
+ glMapBufferRange @206
+ glFlushMappedBufferRange @207
+ glBindVertexArray @208
+ glDeleteVertexArrays @209
+ glGenVertexArrays @210
+ glIsVertexArray @211
+ glGetIntegeri_v @212
+ glBeginTransformFeedback @213
+ glEndTransformFeedback @214
+ glBindBufferRange @215
+ glBindBufferBase @216
+ glTransformFeedbackVaryings @217
+ glGetTransformFeedbackVarying @218
+ glVertexAttribIPointer @219
+ glGetVertexAttribIiv @220
+ glGetVertexAttribIuiv @221
+ glVertexAttribI4i @222
+ glVertexAttribI4ui @223
+ glVertexAttribI4iv @224
+ glVertexAttribI4uiv @225
+ glGetUniformuiv @226
+ glGetFragDataLocation @227
+ glUniform1ui @228
+ glUniform2ui @229
+ glUniform3ui @230
+ glUniform4ui @231
+ glUniform1uiv @232
+ glUniform2uiv @233
+ glUniform3uiv @234
+ glUniform4uiv @235
+ glClearBufferiv @236
+ glClearBufferuiv @237
+ glClearBufferfv @238
+ glClearBufferfi @239
+ glGetStringi @240
+ glCopyBufferSubData @241
+ glGetUniformIndices @242
+ glGetActiveUniformsiv @243
+ glGetUniformBlockIndex @244
+ glGetActiveUniformBlockiv @245
+ glGetActiveUniformBlockName @246
+ glUniformBlockBinding @247
+ glDrawArraysInstanced @248
+ glDrawElementsInstanced @249
+ glFenceSync @250
+ glIsSync @251
+ glDeleteSync @252
+ glClientWaitSync @253
+ glWaitSync @254
+ glGetInteger64v @255
+ glGetSynciv @256
+ glGetInteger64i_v @257
+ glGetBufferParameteri64v @258
+ glGenSamplers @259
+ glDeleteSamplers @260
+ glIsSampler @261
+ glBindSampler @262
+ glSamplerParameteri @263
+ glSamplerParameteriv @264
+ glSamplerParameterf @265
+ glSamplerParameterfv @266
+ glGetSamplerParameteriv @267
+ glGetSamplerParameterfv @268
+ glVertexAttribDivisor @269
+ glBindTransformFeedback @270
+ glDeleteTransformFeedbacks @271
+ glGenTransformFeedbacks @272
+ glIsTransformFeedback @273
+ glPauseTransformFeedback @274
+ glResumeTransformFeedback @275
+ glGetProgramBinary @276
+ glProgramBinary @277
+ glProgramParameteri @278
+ glInvalidateFramebuffer @279
+ glInvalidateSubFramebuffer @280
+ glTexStorage2D @281
+ glTexStorage3D @282
+ glGetInternalformativ @283
- ; ANGLE Platform Implementation
- ANGLEPlatformCurrent@0 @290
- ANGLEPlatformInitialize@4 @291
- ANGLEPlatformShutdown@0 @292
- \ No newline at end of file
+ ; GLES 3.1 Functions
+ glDispatchCompute @345
+ glDispatchComputeIndirect @346
+ glDrawArraysIndirect @347
+ glDrawElementsIndirect @348
+ glFramebufferParameteri @349
+ glGetFramebufferParameteriv @350
+ glGetProgramInterfaceiv @351
+ glGetProgramResourceIndex @352
+ glGetProgramResourceName @353
+ glGetProgramResourceiv @354
+ glGetProgramResourceLocation @355
+ glUseProgramStages @356
+ glActiveShaderProgram @357
+ glCreateShaderProgramv @358
+ glBindProgramPipeline @359
+ glDeleteProgramPipelines @360
+ glGenProgramPipelines @361
+ glIsProgramPipeline @362
+ glGetProgramPipelineiv @363
+ glProgramUniform1i @364
+ glProgramUniform2i @365
+ glProgramUniform3i @366
+ glProgramUniform4i @367
+ glProgramUniform1ui @368
+ glProgramUniform2ui @369
+ glProgramUniform3ui @370
+ glProgramUniform4ui @371
+ glProgramUniform1f @372
+ glProgramUniform2f @373
+ glProgramUniform3f @374
+ glProgramUniform4f @375
+ glProgramUniform1iv @376
+ glProgramUniform2iv @377
+ glProgramUniform3iv @378
+ glProgramUniform4iv @379
+ glProgramUniform1uiv @380
+ glProgramUniform2uiv @381
+ glProgramUniform3uiv @382
+ glProgramUniform4uiv @383
+ glProgramUniform1fv @384
+ glProgramUniform2fv @385
+ glProgramUniform3fv @386
+ glProgramUniform4fv @387
+ glProgramUniformMatrix2fv @388
+ glProgramUniformMatrix3fv @389
+ glProgramUniformMatrix4fv @390
+ glProgramUniformMatrix2x3fv @391
+ glProgramUniformMatrix3x2fv @392
+ glProgramUniformMatrix2x4fv @393
+ glProgramUniformMatrix4x2fv @394
+ glProgramUniformMatrix3x4fv @395
+ glProgramUniformMatrix4x3fv @396
+ glValidateProgramPipeline @397
+ glGetProgramPipelineInfoLog @398
+ glBindImageTexture @399
+ glGetBooleani_v @400
+ glMemoryBarrier @401
+ glMemoryBarrierByRegion @402
+ glTexStorage2DMultisample @403
+ glGetMultisamplefv @404
+ glSampleMaski @405
+ glGetTexLevelParameteriv @406
+ glGetTexLevelParameterfv @407
+ glBindVertexBuffer @408
+ glVertexAttribFormat @409
+ glVertexAttribIFormat @410
+ glVertexAttribBinding @411
+ glVertexBindingDivisor @412
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def
index e0c3823abf..9a00a9f8ae 100644
--- a/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def
+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def
@@ -202,6 +202,38 @@ EXPORTS
glGetQueryObjectivEXT @315
glGetQueryObjecti64vEXT @316
glGetQueryObjectui64vEXT @317
+ glBindUniformLocationCHROMIUM @318
+ glCoverageModulationCHROMIUM @319
+
+ glMatrixLoadfCHROMIUM @320
+ glMatrixLoadIdentityCHROMIUM @321
+ glGenPathsCHROMIUM @322
+ glDeletePathsCHROMIUM @323
+ glIsPathCHROMIUM @324
+ glPathCommandsCHROMIUM @325
+ glPathParameterfCHROMIUM @326
+ glPathParameteriCHROMIUM @327
+ glGetPathParameterfvCHROMIUM @328
+ glGetPathParameterivCHROMIUM @329
+ glPathStencilFuncCHROMIUM @330
+ glStencilFillPathCHROMIUM @331
+ glStencilStrokePathCHROMIUM @332
+ glCoverFillPathCHROMIUM @333
+ glCoverStrokePathCHROMIUM @334
+ glStencilThenCoverFillPathCHROMIUM @335
+ glStencilThenCoverStrokePathCHROMIUM @336
+ glCoverFillPathInstancedCHROMIUM @337
+ glCoverStrokePathInstancedCHROMIUM @338
+ glStencilStrokePathInstancedCHROMIUM @339
+ glStencilFillPathInstancedCHROMIUM @340
+ glStencilThenCoverFillPathInstancedCHROMIUM @341
+ glStencilThenCoverStrokePathInstancedCHROMIUM @342
+ glBindFragmentInputLocationCHROMIUM @343
+ glProgramPathFragmentInputGenCHROMIUM @344
+
+ glFramebufferTextureMultiviewLayeredANGLE @413
+ glFramebufferTextureMultiviewSideBySideANGLE @414
+ glRequestExtensionANGLE @415
; GLES 3.0 Functions
glReadBuffer @180
@@ -309,7 +341,72 @@ EXPORTS
glTexStorage3D @282
glGetInternalformativ @283
- ; ANGLE Platform Implementation
- ANGLEPlatformCurrent @290
- ANGLEPlatformInitialize @291
- ANGLEPlatformShutdown @292
+ ; GLES 3.1 Functions
+ glDispatchCompute @345
+ glDispatchComputeIndirect @346
+ glDrawArraysIndirect @347
+ glDrawElementsIndirect @348
+ glFramebufferParameteri @349
+ glGetFramebufferParameteriv @350
+ glGetProgramInterfaceiv @351
+ glGetProgramResourceIndex @352
+ glGetProgramResourceName @353
+ glGetProgramResourceiv @354
+ glGetProgramResourceLocation @355
+ glUseProgramStages @356
+ glActiveShaderProgram @357
+ glCreateShaderProgramv @358
+ glBindProgramPipeline @359
+ glDeleteProgramPipelines @360
+ glGenProgramPipelines @361
+ glIsProgramPipeline @362
+ glGetProgramPipelineiv @363
+ glProgramUniform1i @364
+ glProgramUniform2i @365
+ glProgramUniform3i @366
+ glProgramUniform4i @367
+ glProgramUniform1ui @368
+ glProgramUniform2ui @369
+ glProgramUniform3ui @370
+ glProgramUniform4ui @371
+ glProgramUniform1f @372
+ glProgramUniform2f @373
+ glProgramUniform3f @374
+ glProgramUniform4f @375
+ glProgramUniform1iv @376
+ glProgramUniform2iv @377
+ glProgramUniform3iv @378
+ glProgramUniform4iv @379
+ glProgramUniform1uiv @380
+ glProgramUniform2uiv @381
+ glProgramUniform3uiv @382
+ glProgramUniform4uiv @383
+ glProgramUniform1fv @384
+ glProgramUniform2fv @385
+ glProgramUniform3fv @386
+ glProgramUniform4fv @387
+ glProgramUniformMatrix2fv @388
+ glProgramUniformMatrix3fv @389
+ glProgramUniformMatrix4fv @390
+ glProgramUniformMatrix2x3fv @391
+ glProgramUniformMatrix3x2fv @392
+ glProgramUniformMatrix2x4fv @393
+ glProgramUniformMatrix4x2fv @394
+ glProgramUniformMatrix3x4fv @395
+ glProgramUniformMatrix4x3fv @396
+ glValidateProgramPipeline @397
+ glGetProgramPipelineInfoLog @398
+ glBindImageTexture @399
+ glGetBooleani_v @400
+ glMemoryBarrier @401
+ glMemoryBarrierByRegion @402
+ glTexStorage2DMultisample @403
+ glGetMultisamplefv @404
+ glSampleMaski @405
+ glGetTexLevelParameteriv @406
+ glGetTexLevelParameterfv @407
+ glBindVertexBuffer @408
+ glVertexAttribFormat @409
+ glVertexAttribIFormat @410
+ glVertexAttribBinding @411
+ glVertexBindingDivisor @412
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def
index 5a4966f66d..2ff4cc0579 100644
--- a/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def
+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def
@@ -1,316 +1,412 @@
-LIBRARY libGLESv2d
+LIBRARY libGLESv2
EXPORTS
- glActiveTexture@4 @1
- glAttachShader@8 @2
- glBindAttribLocation@12 @3
- glBindBuffer@8 @4
- glBindFramebuffer@8 @5
- glBindRenderbuffer@8 @6
- glBindTexture@8 @7
- glBlendColor@16 @8
- glBlendEquation@4 @9
- glBlendEquationSeparate@8 @10
- glBlendFunc@8 @11
- glBlendFuncSeparate@16 @12
- glBufferData@16 @13
- glBufferSubData@16 @14
- glCheckFramebufferStatus@4 @15
- glClear@4 @16
- glClearColor@16 @17
- glClearDepthf@4 @18
- glClearStencil@4 @19
- glColorMask@16 @20
- glCompileShader@4 @21
- glCompressedTexImage2D@32 @22
- glCompressedTexSubImage2D@36 @23
- glCopyTexImage2D@32 @24
- glCopyTexSubImage2D@32 @25
- glCreateProgram@0 @26
- glCreateShader@4 @27
- glCullFace@4 @28
- glDeleteBuffers@8 @29
- glDeleteFramebuffers@8 @30
- glDeleteProgram@4 @32
- glDeleteRenderbuffers@8 @33
- glDeleteShader@4 @34
- glDeleteTextures@8 @31
- glDepthFunc@4 @36
- glDepthMask@4 @37
- glDepthRangef@8 @38
- glDetachShader@8 @35
- glDisable@4 @39
- glDisableVertexAttribArray@4 @40
- glDrawArrays@12 @41
- glDrawElements@16 @42
- glEnable@4 @43
- glEnableVertexAttribArray@4 @44
- glFinish@0 @45
- glFlush@0 @46
- glFramebufferRenderbuffer@16 @47
- glFramebufferTexture2D@20 @48
- glFrontFace@4 @49
- glGenBuffers@8 @50
- glGenFramebuffers@8 @52
- glGenRenderbuffers@8 @53
- glGenTextures@8 @54
- glGenerateMipmap@4 @51
- glGetActiveAttrib@28 @55
- glGetActiveUniform@28 @56
- glGetAttachedShaders@16 @57
- glGetAttribLocation@8 @58
- glGetBooleanv@8 @59
- glGetBufferParameteriv@12 @60
- glGetError@0 @61
- glGetFloatv@8 @62
- glGetFramebufferAttachmentParameteriv@16 @63
- glGetIntegerv@8 @64
- glGetProgramInfoLog@16 @66
- glGetProgramiv@12 @65
- glGetRenderbufferParameteriv@12 @67
- glGetShaderInfoLog@16 @69
- glGetShaderPrecisionFormat@16 @70
- glGetShaderSource@16 @71
- glGetShaderiv@12 @68
- glGetString@4 @72
- glGetTexParameterfv@12 @73
- glGetTexParameteriv@12 @74
- glGetUniformLocation@8 @77
- glGetUniformfv@12 @75
- glGetUniformiv@12 @76
- glGetVertexAttribPointerv@12 @80
- glGetVertexAttribfv@12 @78
- glGetVertexAttribiv@12 @79
- glHint@8 @81
- glIsBuffer@4 @82
- glIsEnabled@4 @83
- glIsFramebuffer@4 @84
- glIsProgram@4 @85
- glIsRenderbuffer@4 @86
- glIsShader@4 @87
- glIsTexture@4 @88
- glLineWidth@4 @89
- glLinkProgram@4 @90
- glPixelStorei@8 @91
- glPolygonOffset@8 @92
- glReadPixels@28 @93
- glReleaseShaderCompiler@0 @94
- glRenderbufferStorage@16 @95
- glSampleCoverage@8 @96
- glScissor@16 @97
- glShaderBinary@20 @98
- glShaderSource@16 @99
- glStencilFunc@12 @100
- glStencilFuncSeparate@16 @101
- glStencilMask@4 @102
- glStencilMaskSeparate@8 @103
- glStencilOp@12 @104
- glStencilOpSeparate@16 @105
- glTexImage2D@36 @106
- glTexParameterf@12 @107
- glTexParameterfv@12 @108
- glTexParameteri@12 @109
- glTexParameteriv@12 @110
- glTexSubImage2D@36 @111
- glUniform1f@8 @112
- glUniform1fv@12 @113
- glUniform1i@8 @114
- glUniform1iv@12 @115
- glUniform2f@12 @116
- glUniform2fv@12 @117
- glUniform2i@12 @118
- glUniform2iv@12 @119
- glUniform3f@16 @120
- glUniform3fv@12 @121
- glUniform3i@16 @122
- glUniform3iv@12 @123
- glUniform4f@20 @124
- glUniform4fv@12 @125
- glUniform4i@20 @126
- glUniform4iv@12 @127
- glUniformMatrix2fv@16 @128
- glUniformMatrix3fv@16 @129
- glUniformMatrix4fv@16 @130
- glUseProgram@4 @131
- glValidateProgram@4 @132
- glVertexAttrib1f@8 @133
- glVertexAttrib1fv@8 @134
- glVertexAttrib2f@12 @135
- glVertexAttrib2fv@8 @136
- glVertexAttrib3f@16 @137
- glVertexAttrib3fv@8 @138
- glVertexAttrib4f@20 @139
- glVertexAttrib4fv@8 @140
- glVertexAttribPointer@24 @141
- glViewport@16 @142
+ glActiveTexture @1
+ glAttachShader @2
+ glBindAttribLocation @3
+ glBindBuffer @4
+ glBindFramebuffer @5
+ glBindRenderbuffer @6
+ glBindTexture @7
+ glBlendColor @8
+ glBlendEquation @9
+ glBlendEquationSeparate @10
+ glBlendFunc @11
+ glBlendFuncSeparate @12
+ glBufferData @13
+ glBufferSubData @14
+ glCheckFramebufferStatus @15
+ glClear @16
+ glClearColor @17
+ glClearDepthf @18
+ glClearStencil @19
+ glColorMask @20
+ glCompileShader @21
+ glCompressedTexImage2D @22
+ glCompressedTexSubImage2D @23
+ glCopyTexImage2D @24
+ glCopyTexSubImage2D @25
+ glCreateProgram @26
+ glCreateShader @27
+ glCullFace @28
+ glDeleteBuffers @29
+ glDeleteFramebuffers @30
+ glDeleteProgram @32
+ glDeleteRenderbuffers @33
+ glDeleteShader @34
+ glDeleteTextures @31
+ glDepthFunc @36
+ glDepthMask @37
+ glDepthRangef @38
+ glDetachShader @35
+ glDisable @39
+ glDisableVertexAttribArray @40
+ glDrawArrays @41
+ glDrawElements @42
+ glEnable @43
+ glEnableVertexAttribArray @44
+ glFinish @45
+ glFlush @46
+ glFramebufferRenderbuffer @47
+ glFramebufferTexture2D @48
+ glFrontFace @49
+ glGenBuffers @50
+ glGenFramebuffers @52
+ glGenRenderbuffers @53
+ glGenTextures @54
+ glGenerateMipmap @51
+ glGetActiveAttrib @55
+ glGetActiveUniform @56
+ glGetAttachedShaders @57
+ glGetAttribLocation @58
+ glGetBooleanv @59
+ glGetBufferParameteriv @60
+ glGetError @61
+ glGetFloatv @62
+ glGetFramebufferAttachmentParameteriv @63
+ glGetIntegerv @64
+ glGetProgramInfoLog @66
+ glGetProgramiv @65
+ glGetRenderbufferParameteriv @67
+ glGetShaderInfoLog @69
+ glGetShaderPrecisionFormat @70
+ glGetShaderSource @71
+ glGetShaderiv @68
+ glGetString @72
+ glGetTexParameterfv @73
+ glGetTexParameteriv @74
+ glGetUniformLocation @77
+ glGetUniformfv @75
+ glGetUniformiv @76
+ glGetVertexAttribPointerv @80
+ glGetVertexAttribfv @78
+ glGetVertexAttribiv @79
+ glHint @81
+ glIsBuffer @82
+ glIsEnabled @83
+ glIsFramebuffer @84
+ glIsProgram @85
+ glIsRenderbuffer @86
+ glIsShader @87
+ glIsTexture @88
+ glLineWidth @89
+ glLinkProgram @90
+ glPixelStorei @91
+ glPolygonOffset @92
+ glReadPixels @93
+ glReleaseShaderCompiler @94
+ glRenderbufferStorage @95
+ glSampleCoverage @96
+ glScissor @97
+ glShaderBinary @98
+ glShaderSource @99
+ glStencilFunc @100
+ glStencilFuncSeparate @101
+ glStencilMask @102
+ glStencilMaskSeparate @103
+ glStencilOp @104
+ glStencilOpSeparate @105
+ glTexImage2D @106
+ glTexParameterf @107
+ glTexParameterfv @108
+ glTexParameteri @109
+ glTexParameteriv @110
+ glTexSubImage2D @111
+ glUniform1f @112
+ glUniform1fv @113
+ glUniform1i @114
+ glUniform1iv @115
+ glUniform2f @116
+ glUniform2fv @117
+ glUniform2i @118
+ glUniform2iv @119
+ glUniform3f @120
+ glUniform3fv @121
+ glUniform3i @122
+ glUniform3iv @123
+ glUniform4f @124
+ glUniform4fv @125
+ glUniform4i @126
+ glUniform4iv @127
+ glUniformMatrix2fv @128
+ glUniformMatrix3fv @129
+ glUniformMatrix4fv @130
+ glUseProgram @131
+ glValidateProgram @132
+ glVertexAttrib1f @133
+ glVertexAttrib1fv @134
+ glVertexAttrib2f @135
+ glVertexAttrib2fv @136
+ glVertexAttrib3f @137
+ glVertexAttrib3fv @138
+ glVertexAttrib4f @139
+ glVertexAttrib4fv @140
+ glVertexAttribPointer @141
+ glViewport @142
; Extensions
- glBlitFramebufferANGLE@40 @149
- glRenderbufferStorageMultisampleANGLE@20 @150
- glDeleteFencesNV@8 @151
- glFinishFenceNV@4 @152
- glGenFencesNV@8 @153
- glGetFenceivNV@12 @154
- glIsFenceNV@4 @155
- glSetFenceNV@8 @156
- glTestFenceNV@4 @157
- glGetTranslatedShaderSourceANGLE@16 @159
- glTexStorage2DEXT@20 @160
- glGetGraphicsResetStatusEXT@0 @161
- glReadnPixelsEXT@32 @162
- glGetnUniformfvEXT@16 @163
- glGetnUniformivEXT@16 @164
- glGenQueriesEXT@8 @165
- glDeleteQueriesEXT@8 @166
- glIsQueryEXT@4 @167
- glBeginQueryEXT@8 @168
- glEndQueryEXT@4 @169
- glGetQueryivEXT@12 @170
- glGetQueryObjectuivEXT@12 @171
- glVertexAttribDivisorANGLE@8 @172
- glDrawArraysInstancedANGLE@16 @173
- glDrawElementsInstancedANGLE@20 @174
- glProgramBinaryOES@16 @175
- glGetProgramBinaryOES@20 @176
- glDrawBuffersEXT@8 @179
- glMapBufferOES@8 @285
- glUnmapBufferOES@4 @286
- glGetBufferPointervOES@12 @287
- glMapBufferRangeEXT@16 @288
- glFlushMappedBufferRangeEXT@12 @289
- glDiscardFramebufferEXT@12 @293
- glInsertEventMarkerEXT@8 @294
- glPushGroupMarkerEXT@8 @295
- glPopGroupMarkerEXT@0 @296
- glEGLImageTargetTexture2DOES@8 @297
- glEGLImageTargetRenderbufferStorageOES@8 @298
- glBindVertexArrayOES@4 @299
- glDeleteVertexArraysOES@8 @300
- glGenVertexArraysOES@8 @301
- glIsVertexArrayOES@4 @302
- glDebugMessageControlKHR@24 @303
- glDebugMessageInsertKHR@24 @304
- glDebugMessageCallbackKHR@8 @305
- glGetDebugMessageLogKHR@32 @306
- glPushDebugGroupKHR@16 @307
- glPopDebugGroupKHR@0 @308
- glObjectLabelKHR@16 @309
- glGetObjectLabelKHR@20 @310
- glObjectPtrLabelKHR@12 @311
- glGetObjectPtrLabelKHR@16 @312
- glGetPointervKHR@8 @313
- glQueryCounterEXT@8 @314
- glGetQueryObjectivEXT@12 @315
- glGetQueryObjecti64vEXT@12 @316
- glGetQueryObjectui64vEXT@12 @317
+ glBlitFramebufferANGLE @149
+ glRenderbufferStorageMultisampleANGLE @150
+ glDeleteFencesNV @151
+ glFinishFenceNV @152
+ glGenFencesNV @153
+ glGetFenceivNV @154
+ glIsFenceNV @155
+ glSetFenceNV @156
+ glTestFenceNV @157
+ glGetTranslatedShaderSourceANGLE @159
+ glTexStorage2DEXT @160
+ glGetGraphicsResetStatusEXT @161
+ glReadnPixelsEXT @162
+ glGetnUniformfvEXT @163
+ glGetnUniformivEXT @164
+ glGenQueriesEXT @165
+ glDeleteQueriesEXT @166
+ glIsQueryEXT @167
+ glBeginQueryEXT @168
+ glEndQueryEXT @169
+ glGetQueryivEXT @170
+ glGetQueryObjectuivEXT @171
+ glVertexAttribDivisorANGLE @172
+ glDrawArraysInstancedANGLE @173
+ glDrawElementsInstancedANGLE @174
+ glProgramBinaryOES @175
+ glGetProgramBinaryOES @176
+ glDrawBuffersEXT @179
+ glMapBufferOES @285
+ glUnmapBufferOES @286
+ glGetBufferPointervOES @287
+ glMapBufferRangeEXT @288
+ glFlushMappedBufferRangeEXT @289
+ glDiscardFramebufferEXT @293
+ glInsertEventMarkerEXT @294
+ glPushGroupMarkerEXT @295
+ glPopGroupMarkerEXT @296
+ glEGLImageTargetTexture2DOES @297
+ glEGLImageTargetRenderbufferStorageOES @298
+ glBindVertexArrayOES @299
+ glDeleteVertexArraysOES @300
+ glGenVertexArraysOES @301
+ glIsVertexArrayOES @302
+ glDebugMessageControlKHR @303
+ glDebugMessageInsertKHR @304
+ glDebugMessageCallbackKHR @305
+ glGetDebugMessageLogKHR @306
+ glPushDebugGroupKHR @307
+ glPopDebugGroupKHR @308
+ glObjectLabelKHR @309
+ glGetObjectLabelKHR @310
+ glObjectPtrLabelKHR @311
+ glGetObjectPtrLabelKHR @312
+ glGetPointervKHR @313
+ glQueryCounterEXT @314
+ glGetQueryObjectivEXT @315
+ glGetQueryObjecti64vEXT @316
+ glGetQueryObjectui64vEXT @317
+ glBindUniformLocationCHROMIUM @318
+ glCoverageModulationCHROMIUM @319
+
+ glMatrixLoadfCHROMIUM @320
+ glMatrixLoadIdentityCHROMIUM @321
+ glGenPathsCHROMIUM @322
+ glDeletePathsCHROMIUM @323
+ glIsPathCHROMIUM @324
+ glPathCommandsCHROMIUM @325
+ glPathParameterfCHROMIUM @326
+ glPathParameteriCHROMIUM @327
+ glGetPathParameterfvCHROMIUM @328
+ glGetPathParameterivCHROMIUM @329
+ glPathStencilFuncCHROMIUM @330
+ glStencilFillPathCHROMIUM @331
+ glStencilStrokePathCHROMIUM @332
+ glCoverFillPathCHROMIUM @333
+ glCoverStrokePathCHROMIUM @334
+ glStencilThenCoverFillPathCHROMIUM @335
+ glStencilThenCoverStrokePathCHROMIUM @336
+ glCoverFillPathInstancedCHROMIUM @337
+ glCoverStrokePathInstancedCHROMIUM @338
+ glStencilStrokePathInstancedCHROMIUM @339
+ glStencilFillPathInstancedCHROMIUM @340
+ glStencilThenCoverFillPathInstancedCHROMIUM @341
+ glStencilThenCoverStrokePathInstancedCHROMIUM @342
+ glBindFragmentInputLocationCHROMIUM @343
+ glProgramPathFragmentInputGenCHROMIUM @344
+
+ glFramebufferTextureMultiviewLayeredANGLE @413
+ glFramebufferTextureMultiviewSideBySideANGLE @414
+ glRequestExtensionANGLE @415
; GLES 3.0 Functions
- glReadBuffer@4 @180
- glDrawRangeElements@24 @181
- glTexImage3D@40 @182
- glTexSubImage3D@44 @183
- glCopyTexSubImage3D@36 @184
- glCompressedTexImage3D@36 @185
- glCompressedTexSubImage3D@44 @186
- glGenQueries@8 @187
- glDeleteQueries@8 @188
- glIsQuery@4 @189
- glBeginQuery@8 @190
- glEndQuery@4 @191
- glGetQueryiv@12 @192
- glGetQueryObjectuiv@12 @193
- glUnmapBuffer@4 @194
- glGetBufferPointerv@12 @195
- glDrawBuffers@8 @196
- glUniformMatrix2x3fv@16 @197
- glUniformMatrix3x2fv@16 @198
- glUniformMatrix2x4fv@16 @199
- glUniformMatrix4x2fv@16 @200
- glUniformMatrix3x4fv@16 @201
- glUniformMatrix4x3fv@16 @202
- glBlitFramebuffer@40 @203
- glRenderbufferStorageMultisample@20 @204
- glFramebufferTextureLayer@20 @205
- glMapBufferRange@16 @206
- glFlushMappedBufferRange@12 @207
- glBindVertexArray@4 @208
- glDeleteVertexArrays@8 @209
- glGenVertexArrays@8 @210
- glIsVertexArray@4 @211
- glGetIntegeri_v@12 @212
- glBeginTransformFeedback@4 @213
- glEndTransformFeedback@0 @214
- glBindBufferRange@20 @215
- glBindBufferBase@12 @216
- glTransformFeedbackVaryings@16 @217
- glGetTransformFeedbackVarying@28 @218
- glVertexAttribIPointer@20 @219
- glGetVertexAttribIiv@12 @220
- glGetVertexAttribIuiv@12 @221
- glVertexAttribI4i@20 @222
- glVertexAttribI4ui@20 @223
- glVertexAttribI4iv@8 @224
- glVertexAttribI4uiv@8 @225
- glGetUniformuiv@12 @226
- glGetFragDataLocation@8 @227
- glUniform1ui@8 @228
- glUniform2ui@12 @229
- glUniform3ui@16 @230
- glUniform4ui@20 @231
- glUniform1uiv@12 @232
- glUniform2uiv@12 @233
- glUniform3uiv@12 @234
- glUniform4uiv@12 @235
- glClearBufferiv@12 @236
- glClearBufferuiv@12 @237
- glClearBufferfv@12 @238
- glClearBufferfi@16 @239
- glGetStringi@8 @240
- glCopyBufferSubData@20 @241
- glGetUniformIndices@16 @242
- glGetActiveUniformsiv@20 @243
- glGetUniformBlockIndex@8 @244
- glGetActiveUniformBlockiv@16 @245
- glGetActiveUniformBlockName@20 @246
- glUniformBlockBinding@12 @247
- glDrawArraysInstanced@16 @248
- glDrawElementsInstanced@20 @249
- glFenceSync@8 @250
- glIsSync@4 @251
- glDeleteSync@4 @252
- glClientWaitSync@16 @253
- glWaitSync@16 @254
- glGetInteger64v@8 @255
- glGetSynciv@20 @256
- glGetInteger64i_v@12 @257
- glGetBufferParameteri64v@12 @258
- glGenSamplers@8 @259
- glDeleteSamplers@8 @260
- glIsSampler@4 @261
- glBindSampler@8 @262
- glSamplerParameteri@12 @263
- glSamplerParameteriv@12 @264
- glSamplerParameterf@12 @265
- glSamplerParameterfv@12 @266
- glGetSamplerParameteriv@12 @267
- glGetSamplerParameterfv@12 @268
- glVertexAttribDivisor@8 @269
- glBindTransformFeedback@8 @270
- glDeleteTransformFeedbacks@8 @271
- glGenTransformFeedbacks@8 @272
- glIsTransformFeedback@4 @273
- glPauseTransformFeedback@0 @274
- glResumeTransformFeedback@0 @275
- glGetProgramBinary@20 @276
- glProgramBinary@16 @277
- glProgramParameteri@12 @278
- glInvalidateFramebuffer@12 @279
- glInvalidateSubFramebuffer@28 @280
- glTexStorage2D@20 @281
- glTexStorage3D@24 @282
- glGetInternalformativ@20 @283
+ glReadBuffer @180
+ glDrawRangeElements @181
+ glTexImage3D @182
+ glTexSubImage3D @183
+ glCopyTexSubImage3D @184
+ glCompressedTexImage3D @185
+ glCompressedTexSubImage3D @186
+ glGenQueries @187
+ glDeleteQueries @188
+ glIsQuery @189
+ glBeginQuery @190
+ glEndQuery @191
+ glGetQueryiv @192
+ glGetQueryObjectuiv @193
+ glUnmapBuffer @194
+ glGetBufferPointerv @195
+ glDrawBuffers @196
+ glUniformMatrix2x3fv @197
+ glUniformMatrix3x2fv @198
+ glUniformMatrix2x4fv @199
+ glUniformMatrix4x2fv @200
+ glUniformMatrix3x4fv @201
+ glUniformMatrix4x3fv @202
+ glBlitFramebuffer @203
+ glRenderbufferStorageMultisample @204
+ glFramebufferTextureLayer @205
+ glMapBufferRange @206
+ glFlushMappedBufferRange @207
+ glBindVertexArray @208
+ glDeleteVertexArrays @209
+ glGenVertexArrays @210
+ glIsVertexArray @211
+ glGetIntegeri_v @212
+ glBeginTransformFeedback @213
+ glEndTransformFeedback @214
+ glBindBufferRange @215
+ glBindBufferBase @216
+ glTransformFeedbackVaryings @217
+ glGetTransformFeedbackVarying @218
+ glVertexAttribIPointer @219
+ glGetVertexAttribIiv @220
+ glGetVertexAttribIuiv @221
+ glVertexAttribI4i @222
+ glVertexAttribI4ui @223
+ glVertexAttribI4iv @224
+ glVertexAttribI4uiv @225
+ glGetUniformuiv @226
+ glGetFragDataLocation @227
+ glUniform1ui @228
+ glUniform2ui @229
+ glUniform3ui @230
+ glUniform4ui @231
+ glUniform1uiv @232
+ glUniform2uiv @233
+ glUniform3uiv @234
+ glUniform4uiv @235
+ glClearBufferiv @236
+ glClearBufferuiv @237
+ glClearBufferfv @238
+ glClearBufferfi @239
+ glGetStringi @240
+ glCopyBufferSubData @241
+ glGetUniformIndices @242
+ glGetActiveUniformsiv @243
+ glGetUniformBlockIndex @244
+ glGetActiveUniformBlockiv @245
+ glGetActiveUniformBlockName @246
+ glUniformBlockBinding @247
+ glDrawArraysInstanced @248
+ glDrawElementsInstanced @249
+ glFenceSync @250
+ glIsSync @251
+ glDeleteSync @252
+ glClientWaitSync @253
+ glWaitSync @254
+ glGetInteger64v @255
+ glGetSynciv @256
+ glGetInteger64i_v @257
+ glGetBufferParameteri64v @258
+ glGenSamplers @259
+ glDeleteSamplers @260
+ glIsSampler @261
+ glBindSampler @262
+ glSamplerParameteri @263
+ glSamplerParameteriv @264
+ glSamplerParameterf @265
+ glSamplerParameterfv @266
+ glGetSamplerParameteriv @267
+ glGetSamplerParameterfv @268
+ glVertexAttribDivisor @269
+ glBindTransformFeedback @270
+ glDeleteTransformFeedbacks @271
+ glGenTransformFeedbacks @272
+ glIsTransformFeedback @273
+ glPauseTransformFeedback @274
+ glResumeTransformFeedback @275
+ glGetProgramBinary @276
+ glProgramBinary @277
+ glProgramParameteri @278
+ glInvalidateFramebuffer @279
+ glInvalidateSubFramebuffer @280
+ glTexStorage2D @281
+ glTexStorage3D @282
+ glGetInternalformativ @283
- ; ANGLE Platform Implementation
- ANGLEPlatformCurrent@0 @290
- ANGLEPlatformInitialize@4 @291
- ANGLEPlatformShutdown@0 @292
- \ No newline at end of file
+ ; GLES 3.1 Functions
+ glDispatchCompute @345
+ glDispatchComputeIndirect @346
+ glDrawArraysIndirect @347
+ glDrawElementsIndirect @348
+ glFramebufferParameteri @349
+ glGetFramebufferParameteriv @350
+ glGetProgramInterfaceiv @351
+ glGetProgramResourceIndex @352
+ glGetProgramResourceName @353
+ glGetProgramResourceiv @354
+ glGetProgramResourceLocation @355
+ glUseProgramStages @356
+ glActiveShaderProgram @357
+ glCreateShaderProgramv @358
+ glBindProgramPipeline @359
+ glDeleteProgramPipelines @360
+ glGenProgramPipelines @361
+ glIsProgramPipeline @362
+ glGetProgramPipelineiv @363
+ glProgramUniform1i @364
+ glProgramUniform2i @365
+ glProgramUniform3i @366
+ glProgramUniform4i @367
+ glProgramUniform1ui @368
+ glProgramUniform2ui @369
+ glProgramUniform3ui @370
+ glProgramUniform4ui @371
+ glProgramUniform1f @372
+ glProgramUniform2f @373
+ glProgramUniform3f @374
+ glProgramUniform4f @375
+ glProgramUniform1iv @376
+ glProgramUniform2iv @377
+ glProgramUniform3iv @378
+ glProgramUniform4iv @379
+ glProgramUniform1uiv @380
+ glProgramUniform2uiv @381
+ glProgramUniform3uiv @382
+ glProgramUniform4uiv @383
+ glProgramUniform1fv @384
+ glProgramUniform2fv @385
+ glProgramUniform3fv @386
+ glProgramUniform4fv @387
+ glProgramUniformMatrix2fv @388
+ glProgramUniformMatrix3fv @389
+ glProgramUniformMatrix4fv @390
+ glProgramUniformMatrix2x3fv @391
+ glProgramUniformMatrix3x2fv @392
+ glProgramUniformMatrix2x4fv @393
+ glProgramUniformMatrix4x2fv @394
+ glProgramUniformMatrix3x4fv @395
+ glProgramUniformMatrix4x3fv @396
+ glValidateProgramPipeline @397
+ glGetProgramPipelineInfoLog @398
+ glBindImageTexture @399
+ glGetBooleani_v @400
+ glMemoryBarrier @401
+ glMemoryBarrierByRegion @402
+ glTexStorage2DMultisample @403
+ glGetMultisamplefv @404
+ glSampleMaski @405
+ glGetTexLevelParameteriv @406
+ glGetTexLevelParameterfv @407
+ glBindVertexBuffer @408
+ glVertexAttribFormat @409
+ glVertexAttribIFormat @410
+ glVertexAttribBinding @411
+ glVertexBindingDivisor @412
diff --git a/src/3rdparty/angle/src/libGLESv2/proc_table.h b/src/3rdparty/angle/src/libGLESv2/proc_table.h
new file mode 100644
index 0000000000..f718291be7
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/proc_table.h
@@ -0,0 +1,24 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// getProcAddress loader table:
+// Mapping from a string entry point name to function address.
+//
+
+#ifndef LIBGLESV2_PROC_TABLE_H_
+#define LIBGLESV2_PROC_TABLE_H_
+
+#include <EGL/egl.h>
+#include <utility>
+
+namespace egl
+{
+using ProcEntry = std::pair<const char *, __eglMustCastToProperFunctionPointerType>;
+
+extern ProcEntry g_procTable[];
+extern size_t g_numProcs;
+} // namespace egl
+
+#endif // LIBGLESV2_PROC_TABLE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/proc_table_autogen.cpp b/src/3rdparty/angle/src/libGLESv2/proc_table_autogen.cpp
new file mode 100644
index 0000000000..f294c1edc3
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/proc_table_autogen.cpp
@@ -0,0 +1,548 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_proc_table.py using data from proc_table_data.json.
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// getProcAddress loader table:
+// Mapping from a string entry point name to function address.
+//
+
+#include "libGLESv2/proc_table.h"
+
+#include "libGLESv2/entry_points_egl.h"
+#include "libGLESv2/entry_points_egl_ext.h"
+#include "libGLESv2/entry_points_gles_2_0_autogen.h"
+#include "libGLESv2/entry_points_gles_2_0_ext.h"
+#include "libGLESv2/entry_points_gles_3_0_autogen.h"
+#include "libGLESv2/entry_points_gles_3_1_autogen.h"
+#include "platform/Platform.h"
+
+#define P(FUNC) reinterpret_cast<__eglMustCastToProperFunctionPointerType>(FUNC)
+
+namespace egl
+{
+ProcEntry g_procTable[] = {
+ {"ANGLEGetDisplayPlatform", P(ANGLEGetDisplayPlatform)},
+ {"ANGLEResetDisplayPlatform", P(ANGLEResetDisplayPlatform)},
+ {"eglBindAPI", P(egl::BindAPI)},
+ {"eglBindTexImage", P(egl::BindTexImage)},
+ {"eglChooseConfig", P(egl::ChooseConfig)},
+ {"eglClientWaitSync", P(egl::ClientWaitSync)},
+ {"eglCopyBuffers", P(egl::CopyBuffers)},
+ {"eglCreateContext", P(egl::CreateContext)},
+ {"eglCreateDeviceANGLE", P(egl::CreateDeviceANGLE)},
+ {"eglCreateImage", P(egl::CreateImage)},
+ {"eglCreateImageKHR", P(egl::CreateImageKHR)},
+ {"eglCreatePbufferFromClientBuffer", P(egl::CreatePbufferFromClientBuffer)},
+ {"eglCreatePbufferSurface", P(egl::CreatePbufferSurface)},
+ {"eglCreatePixmapSurface", P(egl::CreatePixmapSurface)},
+ {"eglCreatePlatformPixmapSurface", P(egl::CreatePlatformPixmapSurface)},
+ {"eglCreatePlatformWindowSurface", P(egl::CreatePlatformWindowSurface)},
+ {"eglCreateStreamKHR", P(egl::CreateStreamKHR)},
+ {"eglCreateStreamProducerD3DTextureNV12ANGLE", P(egl::CreateStreamProducerD3DTextureNV12ANGLE)},
+ {"eglCreateSync", P(egl::CreateSync)},
+ {"eglCreateWindowSurface", P(egl::CreateWindowSurface)},
+ {"eglDestroyContext", P(egl::DestroyContext)},
+ {"eglDestroyImage", P(egl::DestroyImage)},
+ {"eglDestroyImageKHR", P(egl::DestroyImageKHR)},
+ {"eglDestroyStreamKHR", P(egl::DestroyStreamKHR)},
+ {"eglDestroySurface", P(egl::DestroySurface)},
+ {"eglDestroySync", P(egl::DestroySync)},
+ {"eglGetConfigAttrib", P(egl::GetConfigAttrib)},
+ {"eglGetConfigs", P(egl::GetConfigs)},
+ {"eglGetCurrentContext", P(egl::GetCurrentContext)},
+ {"eglGetCurrentDisplay", P(egl::GetCurrentDisplay)},
+ {"eglGetCurrentSurface", P(egl::GetCurrentSurface)},
+ {"eglGetDisplay", P(egl::GetDisplay)},
+ {"eglGetError", P(egl::GetError)},
+ {"eglGetPlatformDisplay", P(egl::GetPlatformDisplay)},
+ {"eglGetPlatformDisplayEXT", P(egl::GetPlatformDisplayEXT)},
+ {"eglGetProcAddress", P(egl::GetProcAddress)},
+ {"eglGetSyncAttrib", P(egl::GetSyncAttrib)},
+ {"eglGetSyncValuesCHROMIUM", P(egl::GetSyncValuesCHROMIUM)},
+ {"eglInitialize", P(egl::Initialize)},
+ {"eglMakeCurrent", P(egl::MakeCurrent)},
+ {"eglPostSubBufferNV", P(egl::PostSubBufferNV)},
+ {"eglProgramCacheGetAttribANGLE", P(egl::ProgramCacheGetAttribANGLE)},
+ {"eglProgramCachePopulateANGLE", P(egl::ProgramCachePopulateANGLE)},
+ {"eglProgramCacheQueryANGLE", P(egl::ProgramCacheQueryANGLE)},
+ {"eglProgramCacheResizeANGLE", P(egl::ProgramCacheResizeANGLE)},
+ {"eglQueryAPI", P(egl::QueryAPI)},
+ {"eglQueryContext", P(egl::QueryContext)},
+ {"eglQueryDeviceAttribEXT", P(egl::QueryDeviceAttribEXT)},
+ {"eglQueryDeviceStringEXT", P(egl::QueryDeviceStringEXT)},
+ {"eglQueryDisplayAttribEXT", P(egl::QueryDisplayAttribEXT)},
+ {"eglQueryStreamKHR", P(egl::QueryStreamKHR)},
+ {"eglQueryStreamu64KHR", P(egl::QueryStreamu64KHR)},
+ {"eglQueryString", P(egl::QueryString)},
+ {"eglQuerySurface", P(egl::QuerySurface)},
+ {"eglQuerySurfacePointerANGLE", P(egl::QuerySurfacePointerANGLE)},
+ {"eglReleaseDeviceANGLE", P(egl::ReleaseDeviceANGLE)},
+ {"eglReleaseTexImage", P(egl::ReleaseTexImage)},
+ {"eglReleaseThread", P(egl::ReleaseThread)},
+ {"eglStreamAttribKHR", P(egl::StreamAttribKHR)},
+ {"eglStreamConsumerAcquireKHR", P(egl::StreamConsumerAcquireKHR)},
+ {"eglStreamConsumerGLTextureExternalAttribsNV",
+ P(egl::StreamConsumerGLTextureExternalAttribsNV)},
+ {"eglStreamConsumerGLTextureExternalKHR", P(egl::StreamConsumerGLTextureExternalKHR)},
+ {"eglStreamConsumerReleaseKHR", P(egl::StreamConsumerReleaseKHR)},
+ {"eglStreamPostD3DTextureNV12ANGLE", P(egl::StreamPostD3DTextureNV12ANGLE)},
+ {"eglSurfaceAttrib", P(egl::SurfaceAttrib)},
+ {"eglSwapBuffers", P(egl::SwapBuffers)},
+ {"eglSwapBuffersWithDamageEXT", P(egl::SwapBuffersWithDamageEXT)},
+ {"eglSwapInterval", P(egl::SwapInterval)},
+ {"eglTerminate", P(egl::Terminate)},
+ {"eglWaitClient", P(egl::WaitClient)},
+ {"eglWaitGL", P(egl::WaitGL)},
+ {"eglWaitNative", P(egl::WaitNative)},
+ {"eglWaitSync", P(egl::WaitSync)},
+ {"glActiveShaderProgram", P(gl::ActiveShaderProgram)},
+ {"glActiveTexture", P(gl::ActiveTexture)},
+ {"glAttachShader", P(gl::AttachShader)},
+ {"glBeginQuery", P(gl::BeginQuery)},
+ {"glBeginQueryEXT", P(gl::BeginQueryEXT)},
+ {"glBeginTransformFeedback", P(gl::BeginTransformFeedback)},
+ {"glBindAttribLocation", P(gl::BindAttribLocation)},
+ {"glBindBuffer", P(gl::BindBuffer)},
+ {"glBindBufferBase", P(gl::BindBufferBase)},
+ {"glBindBufferRange", P(gl::BindBufferRange)},
+ {"glBindFramebuffer", P(gl::BindFramebuffer)},
+ {"glBindImageTexture", P(gl::BindImageTexture)},
+ {"glBindProgramPipeline", P(gl::BindProgramPipeline)},
+ {"glBindRenderbuffer", P(gl::BindRenderbuffer)},
+ {"glBindSampler", P(gl::BindSampler)},
+ {"glBindTexture", P(gl::BindTexture)},
+ {"glBindTransformFeedback", P(gl::BindTransformFeedback)},
+ {"glBindUniformLocationCHROMIUM", P(gl::BindUniformLocationCHROMIUM)},
+ {"glBindVertexArray", P(gl::BindVertexArray)},
+ {"glBindVertexArrayOES", P(gl::BindVertexArrayOES)},
+ {"glBindVertexBuffer", P(gl::BindVertexBuffer)},
+ {"glBlendColor", P(gl::BlendColor)},
+ {"glBlendEquation", P(gl::BlendEquation)},
+ {"glBlendEquationSeparate", P(gl::BlendEquationSeparate)},
+ {"glBlendFunc", P(gl::BlendFunc)},
+ {"glBlendFuncSeparate", P(gl::BlendFuncSeparate)},
+ {"glBlitFramebuffer", P(gl::BlitFramebuffer)},
+ {"glBlitFramebufferANGLE", P(gl::BlitFramebufferANGLE)},
+ {"glBufferData", P(gl::BufferData)},
+ {"glBufferSubData", P(gl::BufferSubData)},
+ {"glCheckFramebufferStatus", P(gl::CheckFramebufferStatus)},
+ {"glClear", P(gl::Clear)},
+ {"glClearBufferfi", P(gl::ClearBufferfi)},
+ {"glClearBufferfv", P(gl::ClearBufferfv)},
+ {"glClearBufferiv", P(gl::ClearBufferiv)},
+ {"glClearBufferuiv", P(gl::ClearBufferuiv)},
+ {"glClearColor", P(gl::ClearColor)},
+ {"glClearDepthf", P(gl::ClearDepthf)},
+ {"glClearStencil", P(gl::ClearStencil)},
+ {"glClientWaitSync", P(gl::ClientWaitSync)},
+ {"glColorMask", P(gl::ColorMask)},
+ {"glCompileShader", P(gl::CompileShader)},
+ {"glCompressedCopyTextureCHROMIUM", P(gl::CompressedCopyTextureCHROMIUM)},
+ {"glCompressedTexImage2D", P(gl::CompressedTexImage2D)},
+ {"glCompressedTexImage2DRobustANGLE", P(gl::CompressedTexImage2DRobustANGLE)},
+ {"glCompressedTexImage3D", P(gl::CompressedTexImage3D)},
+ {"glCompressedTexImage3DRobustANGLE", P(gl::CompressedTexImage3DRobustANGLE)},
+ {"glCompressedTexSubImage2D", P(gl::CompressedTexSubImage2D)},
+ {"glCompressedTexSubImage2DRobustANGLE", P(gl::CompressedTexSubImage2DRobustANGLE)},
+ {"glCompressedTexSubImage3D", P(gl::CompressedTexSubImage3D)},
+ {"glCompressedTexSubImage3DRobustANGLE", P(gl::CompressedTexSubImage3DRobustANGLE)},
+ {"glCopyBufferSubData", P(gl::CopyBufferSubData)},
+ {"glCopySubTextureCHROMIUM", P(gl::CopySubTextureCHROMIUM)},
+ {"glCopyTexImage2D", P(gl::CopyTexImage2D)},
+ {"glCopyTexSubImage2D", P(gl::CopyTexSubImage2D)},
+ {"glCopyTexSubImage3D", P(gl::CopyTexSubImage3D)},
+ {"glCopyTextureCHROMIUM", P(gl::CopyTextureCHROMIUM)},
+ {"glCreateProgram", P(gl::CreateProgram)},
+ {"glCreateShader", P(gl::CreateShader)},
+ {"glCreateShaderProgramv", P(gl::CreateShaderProgramv)},
+ {"glCullFace", P(gl::CullFace)},
+ {"glDebugMessageCallbackKHR", P(gl::DebugMessageCallbackKHR)},
+ {"glDebugMessageControlKHR", P(gl::DebugMessageControlKHR)},
+ {"glDebugMessageInsertKHR", P(gl::DebugMessageInsertKHR)},
+ {"glDeleteBuffers", P(gl::DeleteBuffers)},
+ {"glDeleteFencesNV", P(gl::DeleteFencesNV)},
+ {"glDeleteFramebuffers", P(gl::DeleteFramebuffers)},
+ {"glDeleteProgram", P(gl::DeleteProgram)},
+ {"glDeleteProgramPipelines", P(gl::DeleteProgramPipelines)},
+ {"glDeleteQueries", P(gl::DeleteQueries)},
+ {"glDeleteQueriesEXT", P(gl::DeleteQueriesEXT)},
+ {"glDeleteRenderbuffers", P(gl::DeleteRenderbuffers)},
+ {"glDeleteSamplers", P(gl::DeleteSamplers)},
+ {"glDeleteShader", P(gl::DeleteShader)},
+ {"glDeleteSync", P(gl::DeleteSync)},
+ {"glDeleteTextures", P(gl::DeleteTextures)},
+ {"glDeleteTransformFeedbacks", P(gl::DeleteTransformFeedbacks)},
+ {"glDeleteVertexArrays", P(gl::DeleteVertexArrays)},
+ {"glDeleteVertexArraysOES", P(gl::DeleteVertexArraysOES)},
+ {"glDepthFunc", P(gl::DepthFunc)},
+ {"glDepthMask", P(gl::DepthMask)},
+ {"glDepthRangef", P(gl::DepthRangef)},
+ {"glDetachShader", P(gl::DetachShader)},
+ {"glDisable", P(gl::Disable)},
+ {"glDisableVertexAttribArray", P(gl::DisableVertexAttribArray)},
+ {"glDiscardFramebufferEXT", P(gl::DiscardFramebufferEXT)},
+ {"glDispatchCompute", P(gl::DispatchCompute)},
+ {"glDispatchComputeIndirect", P(gl::DispatchComputeIndirect)},
+ {"glDrawArrays", P(gl::DrawArrays)},
+ {"glDrawArraysIndirect", P(gl::DrawArraysIndirect)},
+ {"glDrawArraysInstanced", P(gl::DrawArraysInstanced)},
+ {"glDrawArraysInstancedANGLE", P(gl::DrawArraysInstancedANGLE)},
+ {"glDrawBuffers", P(gl::DrawBuffers)},
+ {"glDrawBuffersEXT", P(gl::DrawBuffersEXT)},
+ {"glDrawElements", P(gl::DrawElements)},
+ {"glDrawElementsIndirect", P(gl::DrawElementsIndirect)},
+ {"glDrawElementsInstanced", P(gl::DrawElementsInstanced)},
+ {"glDrawElementsInstancedANGLE", P(gl::DrawElementsInstancedANGLE)},
+ {"glDrawRangeElements", P(gl::DrawRangeElements)},
+ {"glEGLImageTargetRenderbufferStorageOES", P(gl::EGLImageTargetRenderbufferStorageOES)},
+ {"glEGLImageTargetTexture2DOES", P(gl::EGLImageTargetTexture2DOES)},
+ {"glEnable", P(gl::Enable)},
+ {"glEnableVertexAttribArray", P(gl::EnableVertexAttribArray)},
+ {"glEndQuery", P(gl::EndQuery)},
+ {"glEndQueryEXT", P(gl::EndQueryEXT)},
+ {"glEndTransformFeedback", P(gl::EndTransformFeedback)},
+ {"glFenceSync", P(gl::FenceSync)},
+ {"glFinish", P(gl::Finish)},
+ {"glFinishFenceNV", P(gl::FinishFenceNV)},
+ {"glFlush", P(gl::Flush)},
+ {"glFlushMappedBufferRange", P(gl::FlushMappedBufferRange)},
+ {"glFlushMappedBufferRangeEXT", P(gl::FlushMappedBufferRangeEXT)},
+ {"glFramebufferParameteri", P(gl::FramebufferParameteri)},
+ {"glFramebufferRenderbuffer", P(gl::FramebufferRenderbuffer)},
+ {"glFramebufferTexture2D", P(gl::FramebufferTexture2D)},
+ {"glFramebufferTextureLayer", P(gl::FramebufferTextureLayer)},
+ {"glFramebufferTextureMultiviewLayeredANGLE", P(gl::FramebufferTextureMultiviewLayeredANGLE)},
+ {"glFramebufferTextureMultiviewSideBySideANGLE",
+ P(gl::FramebufferTextureMultiviewSideBySideANGLE)},
+ {"glFrontFace", P(gl::FrontFace)},
+ {"glGenBuffers", P(gl::GenBuffers)},
+ {"glGenFencesNV", P(gl::GenFencesNV)},
+ {"glGenFramebuffers", P(gl::GenFramebuffers)},
+ {"glGenProgramPipelines", P(gl::GenProgramPipelines)},
+ {"glGenQueries", P(gl::GenQueries)},
+ {"glGenQueriesEXT", P(gl::GenQueriesEXT)},
+ {"glGenRenderbuffers", P(gl::GenRenderbuffers)},
+ {"glGenSamplers", P(gl::GenSamplers)},
+ {"glGenTextures", P(gl::GenTextures)},
+ {"glGenTransformFeedbacks", P(gl::GenTransformFeedbacks)},
+ {"glGenVertexArrays", P(gl::GenVertexArrays)},
+ {"glGenVertexArraysOES", P(gl::GenVertexArraysOES)},
+ {"glGenerateMipmap", P(gl::GenerateMipmap)},
+ {"glGetActiveAttrib", P(gl::GetActiveAttrib)},
+ {"glGetActiveUniform", P(gl::GetActiveUniform)},
+ {"glGetActiveUniformBlockName", P(gl::GetActiveUniformBlockName)},
+ {"glGetActiveUniformBlockiv", P(gl::GetActiveUniformBlockiv)},
+ {"glGetActiveUniformBlockivRobustANGLE", P(gl::GetActiveUniformBlockivRobustANGLE)},
+ {"glGetActiveUniformsiv", P(gl::GetActiveUniformsiv)},
+ {"glGetAttachedShaders", P(gl::GetAttachedShaders)},
+ {"glGetAttribLocation", P(gl::GetAttribLocation)},
+ {"glGetBooleani_v", P(gl::GetBooleani_v)},
+ {"glGetBooleani_vRobustANGLE", P(gl::GetBooleani_vRobustANGLE)},
+ {"glGetBooleanv", P(gl::GetBooleanv)},
+ {"glGetBooleanvRobustANGLE", P(gl::GetBooleanvRobustANGLE)},
+ {"glGetBufferParameteri64v", P(gl::GetBufferParameteri64v)},
+ {"glGetBufferParameteri64vRobustANGLE", P(gl::GetBufferParameteri64vRobustANGLE)},
+ {"glGetBufferParameteriv", P(gl::GetBufferParameteriv)},
+ {"glGetBufferParameterivRobustANGLE", P(gl::GetBufferParameterivRobustANGLE)},
+ {"glGetBufferPointerv", P(gl::GetBufferPointerv)},
+ {"glGetBufferPointervOES", P(gl::GetBufferPointervOES)},
+ {"glGetBufferPointervRobustANGLE", P(gl::GetBufferPointervRobustANGLE)},
+ {"glGetDebugMessageLogKHR", P(gl::GetDebugMessageLogKHR)},
+ {"glGetError", P(gl::GetError)},
+ {"glGetFenceivNV", P(gl::GetFenceivNV)},
+ {"glGetFloatv", P(gl::GetFloatv)},
+ {"glGetFloatvRobustANGLE", P(gl::GetFloatvRobustANGLE)},
+ {"glGetFragDataLocation", P(gl::GetFragDataLocation)},
+ {"glGetFramebufferAttachmentParameteriv", P(gl::GetFramebufferAttachmentParameteriv)},
+ {"glGetFramebufferAttachmentParameterivRobustANGLE",
+ P(gl::GetFramebufferAttachmentParameterivRobustANGLE)},
+ {"glGetFramebufferParameteriv", P(gl::GetFramebufferParameteriv)},
+ {"glGetFramebufferParameterivRobustANGLE", P(gl::GetFramebufferParameterivRobustANGLE)},
+ {"glGetGraphicsResetStatusEXT", P(gl::GetGraphicsResetStatusEXT)},
+ {"glGetInteger64i_v", P(gl::GetInteger64i_v)},
+ {"glGetInteger64i_vRobustANGLE", P(gl::GetInteger64i_vRobustANGLE)},
+ {"glGetInteger64v", P(gl::GetInteger64v)},
+ {"glGetInteger64vRobustANGLE", P(gl::GetInteger64vRobustANGLE)},
+ {"glGetIntegeri_v", P(gl::GetIntegeri_v)},
+ {"glGetIntegeri_vRobustANGLE", P(gl::GetIntegeri_vRobustANGLE)},
+ {"glGetIntegerv", P(gl::GetIntegerv)},
+ {"glGetIntegervRobustANGLE", P(gl::GetIntegervRobustANGLE)},
+ {"glGetInternalformativ", P(gl::GetInternalformativ)},
+ {"glGetInternalformativRobustANGLE", P(gl::GetInternalformativRobustANGLE)},
+ {"glGetMultisamplefv", P(gl::GetMultisamplefv)},
+ {"glGetMultisamplefvRobustANGLE", P(gl::GetMultisamplefvRobustANGLE)},
+ {"glGetObjectLabelKHR", P(gl::GetObjectLabelKHR)},
+ {"glGetObjectPtrLabelKHR", P(gl::GetObjectPtrLabelKHR)},
+ {"glGetPointervKHR", P(gl::GetPointervKHR)},
+ {"glGetPointervRobustANGLERobustANGLE", P(gl::GetPointervRobustANGLERobustANGLE)},
+ {"glGetProgramBinary", P(gl::GetProgramBinary)},
+ {"glGetProgramBinaryOES", P(gl::GetProgramBinaryOES)},
+ {"glGetProgramInfoLog", P(gl::GetProgramInfoLog)},
+ {"glGetProgramInterfaceiv", P(gl::GetProgramInterfaceiv)},
+ {"glGetProgramInterfaceivRobustANGLE", P(gl::GetProgramInterfaceivRobustANGLE)},
+ {"glGetProgramPipelineInfoLog", P(gl::GetProgramPipelineInfoLog)},
+ {"glGetProgramPipelineiv", P(gl::GetProgramPipelineiv)},
+ {"glGetProgramResourceIndex", P(gl::GetProgramResourceIndex)},
+ {"glGetProgramResourceLocation", P(gl::GetProgramResourceLocation)},
+ {"glGetProgramResourceName", P(gl::GetProgramResourceName)},
+ {"glGetProgramResourceiv", P(gl::GetProgramResourceiv)},
+ {"glGetProgramiv", P(gl::GetProgramiv)},
+ {"glGetProgramivRobustANGLE", P(gl::GetProgramivRobustANGLE)},
+ {"glGetQueryObjecti64vEXT", P(gl::GetQueryObjecti64vEXT)},
+ {"glGetQueryObjecti64vRobustANGLE", P(gl::GetQueryObjecti64vRobustANGLE)},
+ {"glGetQueryObjectivEXT", P(gl::GetQueryObjectivEXT)},
+ {"glGetQueryObjectivRobustANGLE", P(gl::GetQueryObjectivRobustANGLE)},
+ {"glGetQueryObjectui64vEXT", P(gl::GetQueryObjectui64vEXT)},
+ {"glGetQueryObjectui64vRobustANGLE", P(gl::GetQueryObjectui64vRobustANGLE)},
+ {"glGetQueryObjectuiv", P(gl::GetQueryObjectuiv)},
+ {"glGetQueryObjectuivEXT", P(gl::GetQueryObjectuivEXT)},
+ {"glGetQueryObjectuivRobustANGLE", P(gl::GetQueryObjectuivRobustANGLE)},
+ {"glGetQueryiv", P(gl::GetQueryiv)},
+ {"glGetQueryivEXT", P(gl::GetQueryivEXT)},
+ {"glGetQueryivRobustANGLE", P(gl::GetQueryivRobustANGLE)},
+ {"glGetRenderbufferParameteriv", P(gl::GetRenderbufferParameteriv)},
+ {"glGetRenderbufferParameterivRobustANGLE", P(gl::GetRenderbufferParameterivRobustANGLE)},
+ {"glGetSamplerParameterIivRobustANGLE", P(gl::GetSamplerParameterIivRobustANGLE)},
+ {"glGetSamplerParameterIuivRobustANGLE", P(gl::GetSamplerParameterIuivRobustANGLE)},
+ {"glGetSamplerParameterfv", P(gl::GetSamplerParameterfv)},
+ {"glGetSamplerParameterfvRobustANGLE", P(gl::GetSamplerParameterfvRobustANGLE)},
+ {"glGetSamplerParameteriv", P(gl::GetSamplerParameteriv)},
+ {"glGetSamplerParameterivRobustANGLE", P(gl::GetSamplerParameterivRobustANGLE)},
+ {"glGetShaderInfoLog", P(gl::GetShaderInfoLog)},
+ {"glGetShaderPrecisionFormat", P(gl::GetShaderPrecisionFormat)},
+ {"glGetShaderSource", P(gl::GetShaderSource)},
+ {"glGetShaderiv", P(gl::GetShaderiv)},
+ {"glGetShaderivRobustANGLE", P(gl::GetShaderivRobustANGLE)},
+ {"glGetString", P(gl::GetString)},
+ {"glGetStringi", P(gl::GetStringi)},
+ {"glGetSynciv", P(gl::GetSynciv)},
+ {"glGetTexLevelParameterfv", P(gl::GetTexLevelParameterfv)},
+ {"glGetTexLevelParameterfvRobustANGLE", P(gl::GetTexLevelParameterfvRobustANGLE)},
+ {"glGetTexLevelParameteriv", P(gl::GetTexLevelParameteriv)},
+ {"glGetTexLevelParameterivRobustANGLE", P(gl::GetTexLevelParameterivRobustANGLE)},
+ {"glGetTexParameterIivRobustANGLE", P(gl::GetTexParameterIivRobustANGLE)},
+ {"glGetTexParameterIuivRobustANGLE", P(gl::GetTexParameterIuivRobustANGLE)},
+ {"glGetTexParameterfv", P(gl::GetTexParameterfv)},
+ {"glGetTexParameterfvRobustANGLE", P(gl::GetTexParameterfvRobustANGLE)},
+ {"glGetTexParameteriv", P(gl::GetTexParameteriv)},
+ {"glGetTexParameterivRobustANGLE", P(gl::GetTexParameterivRobustANGLE)},
+ {"glGetTransformFeedbackVarying", P(gl::GetTransformFeedbackVarying)},
+ {"glGetTranslatedShaderSourceANGLE", P(gl::GetTranslatedShaderSourceANGLE)},
+ {"glGetUniformBlockIndex", P(gl::GetUniformBlockIndex)},
+ {"glGetUniformIndices", P(gl::GetUniformIndices)},
+ {"glGetUniformLocation", P(gl::GetUniformLocation)},
+ {"glGetUniformfv", P(gl::GetUniformfv)},
+ {"glGetUniformfvRobustANGLE", P(gl::GetUniformfvRobustANGLE)},
+ {"glGetUniformiv", P(gl::GetUniformiv)},
+ {"glGetUniformivRobustANGLE", P(gl::GetUniformivRobustANGLE)},
+ {"glGetUniformuiv", P(gl::GetUniformuiv)},
+ {"glGetUniformuivRobustANGLE", P(gl::GetUniformuivRobustANGLE)},
+ {"glGetVertexAttribIiv", P(gl::GetVertexAttribIiv)},
+ {"glGetVertexAttribIivRobustANGLE", P(gl::GetVertexAttribIivRobustANGLE)},
+ {"glGetVertexAttribIuiv", P(gl::GetVertexAttribIuiv)},
+ {"glGetVertexAttribIuivRobustANGLE", P(gl::GetVertexAttribIuivRobustANGLE)},
+ {"glGetVertexAttribPointerv", P(gl::GetVertexAttribPointerv)},
+ {"glGetVertexAttribPointervRobustANGLE", P(gl::GetVertexAttribPointervRobustANGLE)},
+ {"glGetVertexAttribfv", P(gl::GetVertexAttribfv)},
+ {"glGetVertexAttribfvRobustANGLE", P(gl::GetVertexAttribfvRobustANGLE)},
+ {"glGetVertexAttribiv", P(gl::GetVertexAttribiv)},
+ {"glGetVertexAttribivRobustANGLE", P(gl::GetVertexAttribivRobustANGLE)},
+ {"glGetnUniformfvEXT", P(gl::GetnUniformfvEXT)},
+ {"glGetnUniformfvRobustANGLE", P(gl::GetnUniformfvRobustANGLE)},
+ {"glGetnUniformivEXT", P(gl::GetnUniformivEXT)},
+ {"glGetnUniformivRobustANGLE", P(gl::GetnUniformivRobustANGLE)},
+ {"glGetnUniformuivRobustANGLE", P(gl::GetnUniformuivRobustANGLE)},
+ {"glHint", P(gl::Hint)},
+ {"glInsertEventMarkerEXT", P(gl::InsertEventMarkerEXT)},
+ {"glInvalidateFramebuffer", P(gl::InvalidateFramebuffer)},
+ {"glInvalidateSubFramebuffer", P(gl::InvalidateSubFramebuffer)},
+ {"glIsBuffer", P(gl::IsBuffer)},
+ {"glIsEnabled", P(gl::IsEnabled)},
+ {"glIsFenceNV", P(gl::IsFenceNV)},
+ {"glIsFramebuffer", P(gl::IsFramebuffer)},
+ {"glIsProgram", P(gl::IsProgram)},
+ {"glIsProgramPipeline", P(gl::IsProgramPipeline)},
+ {"glIsQuery", P(gl::IsQuery)},
+ {"glIsQueryEXT", P(gl::IsQueryEXT)},
+ {"glIsRenderbuffer", P(gl::IsRenderbuffer)},
+ {"glIsSampler", P(gl::IsSampler)},
+ {"glIsShader", P(gl::IsShader)},
+ {"glIsSync", P(gl::IsSync)},
+ {"glIsTexture", P(gl::IsTexture)},
+ {"glIsTransformFeedback", P(gl::IsTransformFeedback)},
+ {"glIsVertexArray", P(gl::IsVertexArray)},
+ {"glIsVertexArrayOES", P(gl::IsVertexArrayOES)},
+ {"glLineWidth", P(gl::LineWidth)},
+ {"glLinkProgram", P(gl::LinkProgram)},
+ {"glMapBufferOES", P(gl::MapBufferOES)},
+ {"glMapBufferRange", P(gl::MapBufferRange)},
+ {"glMapBufferRangeEXT", P(gl::MapBufferRangeEXT)},
+ {"glMemoryBarrier", P(gl::MemoryBarrier)},
+ {"glMemoryBarrierByRegion", P(gl::MemoryBarrierByRegion)},
+ {"glObjectLabelKHR", P(gl::ObjectLabelKHR)},
+ {"glObjectPtrLabelKHR", P(gl::ObjectPtrLabelKHR)},
+ {"glPauseTransformFeedback", P(gl::PauseTransformFeedback)},
+ {"glPixelStorei", P(gl::PixelStorei)},
+ {"glPolygonOffset", P(gl::PolygonOffset)},
+ {"glPopDebugGroupKHR", P(gl::PopDebugGroupKHR)},
+ {"glPopGroupMarkerEXT", P(gl::PopGroupMarkerEXT)},
+ {"glProgramBinary", P(gl::ProgramBinary)},
+ {"glProgramBinaryOES", P(gl::ProgramBinaryOES)},
+ {"glProgramParameteri", P(gl::ProgramParameteri)},
+ {"glProgramUniform1f", P(gl::ProgramUniform1f)},
+ {"glProgramUniform1fv", P(gl::ProgramUniform1fv)},
+ {"glProgramUniform1i", P(gl::ProgramUniform1i)},
+ {"glProgramUniform1iv", P(gl::ProgramUniform1iv)},
+ {"glProgramUniform1ui", P(gl::ProgramUniform1ui)},
+ {"glProgramUniform1uiv", P(gl::ProgramUniform1uiv)},
+ {"glProgramUniform2f", P(gl::ProgramUniform2f)},
+ {"glProgramUniform2fv", P(gl::ProgramUniform2fv)},
+ {"glProgramUniform2i", P(gl::ProgramUniform2i)},
+ {"glProgramUniform2iv", P(gl::ProgramUniform2iv)},
+ {"glProgramUniform2ui", P(gl::ProgramUniform2ui)},
+ {"glProgramUniform2uiv", P(gl::ProgramUniform2uiv)},
+ {"glProgramUniform3f", P(gl::ProgramUniform3f)},
+ {"glProgramUniform3fv", P(gl::ProgramUniform3fv)},
+ {"glProgramUniform3i", P(gl::ProgramUniform3i)},
+ {"glProgramUniform3iv", P(gl::ProgramUniform3iv)},
+ {"glProgramUniform3ui", P(gl::ProgramUniform3ui)},
+ {"glProgramUniform3uiv", P(gl::ProgramUniform3uiv)},
+ {"glProgramUniform4f", P(gl::ProgramUniform4f)},
+ {"glProgramUniform4fv", P(gl::ProgramUniform4fv)},
+ {"glProgramUniform4i", P(gl::ProgramUniform4i)},
+ {"glProgramUniform4iv", P(gl::ProgramUniform4iv)},
+ {"glProgramUniform4ui", P(gl::ProgramUniform4ui)},
+ {"glProgramUniform4uiv", P(gl::ProgramUniform4uiv)},
+ {"glProgramUniformMatrix2fv", P(gl::ProgramUniformMatrix2fv)},
+ {"glProgramUniformMatrix2x3fv", P(gl::ProgramUniformMatrix2x3fv)},
+ {"glProgramUniformMatrix2x4fv", P(gl::ProgramUniformMatrix2x4fv)},
+ {"glProgramUniformMatrix3fv", P(gl::ProgramUniformMatrix3fv)},
+ {"glProgramUniformMatrix3x2fv", P(gl::ProgramUniformMatrix3x2fv)},
+ {"glProgramUniformMatrix3x4fv", P(gl::ProgramUniformMatrix3x4fv)},
+ {"glProgramUniformMatrix4fv", P(gl::ProgramUniformMatrix4fv)},
+ {"glProgramUniformMatrix4x2fv", P(gl::ProgramUniformMatrix4x2fv)},
+ {"glProgramUniformMatrix4x3fv", P(gl::ProgramUniformMatrix4x3fv)},
+ {"glPushDebugGroupKHR", P(gl::PushDebugGroupKHR)},
+ {"glPushGroupMarkerEXT", P(gl::PushGroupMarkerEXT)},
+ {"glQueryCounterEXT", P(gl::QueryCounterEXT)},
+ {"glReadBuffer", P(gl::ReadBuffer)},
+ {"glReadPixels", P(gl::ReadPixels)},
+ {"glReadPixelsRobustANGLE", P(gl::ReadPixelsRobustANGLE)},
+ {"glReadnPixelsEXT", P(gl::ReadnPixelsEXT)},
+ {"glReadnPixelsRobustANGLE", P(gl::ReadnPixelsRobustANGLE)},
+ {"glReleaseShaderCompiler", P(gl::ReleaseShaderCompiler)},
+ {"glRenderbufferStorage", P(gl::RenderbufferStorage)},
+ {"glRenderbufferStorageMultisample", P(gl::RenderbufferStorageMultisample)},
+ {"glRenderbufferStorageMultisampleANGLE", P(gl::RenderbufferStorageMultisampleANGLE)},
+ {"glRequestExtensionANGLE", P(gl::RequestExtensionANGLE)},
+ {"glResumeTransformFeedback", P(gl::ResumeTransformFeedback)},
+ {"glSampleCoverage", P(gl::SampleCoverage)},
+ {"glSampleMaski", P(gl::SampleMaski)},
+ {"glSamplerParameterIivRobustANGLE", P(gl::SamplerParameterIivRobustANGLE)},
+ {"glSamplerParameterIuivRobustANGLE", P(gl::SamplerParameterIuivRobustANGLE)},
+ {"glSamplerParameterf", P(gl::SamplerParameterf)},
+ {"glSamplerParameterfv", P(gl::SamplerParameterfv)},
+ {"glSamplerParameterfvRobustANGLE", P(gl::SamplerParameterfvRobustANGLE)},
+ {"glSamplerParameteri", P(gl::SamplerParameteri)},
+ {"glSamplerParameteriv", P(gl::SamplerParameteriv)},
+ {"glSamplerParameterivRobustANGLE", P(gl::SamplerParameterivRobustANGLE)},
+ {"glScissor", P(gl::Scissor)},
+ {"glSetFenceNV", P(gl::SetFenceNV)},
+ {"glShaderBinary", P(gl::ShaderBinary)},
+ {"glShaderSource", P(gl::ShaderSource)},
+ {"glStencilFunc", P(gl::StencilFunc)},
+ {"glStencilFuncSeparate", P(gl::StencilFuncSeparate)},
+ {"glStencilMask", P(gl::StencilMask)},
+ {"glStencilMaskSeparate", P(gl::StencilMaskSeparate)},
+ {"glStencilOp", P(gl::StencilOp)},
+ {"glStencilOpSeparate", P(gl::StencilOpSeparate)},
+ {"glTestFenceNV", P(gl::TestFenceNV)},
+ {"glTexImage2D", P(gl::TexImage2D)},
+ {"glTexImage2DRobustANGLE", P(gl::TexImage2DRobustANGLE)},
+ {"glTexImage3D", P(gl::TexImage3D)},
+ {"glTexImage3DRobustANGLE", P(gl::TexImage3DRobustANGLE)},
+ {"glTexParameterIivRobustANGLE", P(gl::TexParameterIivRobustANGLE)},
+ {"glTexParameterIuivRobustANGLE", P(gl::TexParameterIuivRobustANGLE)},
+ {"glTexParameterf", P(gl::TexParameterf)},
+ {"glTexParameterfv", P(gl::TexParameterfv)},
+ {"glTexParameterfvRobustANGLE", P(gl::TexParameterfvRobustANGLE)},
+ {"glTexParameteri", P(gl::TexParameteri)},
+ {"glTexParameteriv", P(gl::TexParameteriv)},
+ {"glTexParameterivRobustANGLE", P(gl::TexParameterivRobustANGLE)},
+ {"glTexStorage2D", P(gl::TexStorage2D)},
+ {"glTexStorage2DEXT", P(gl::TexStorage2DEXT)},
+ {"glTexStorage2DMultisample", P(gl::TexStorage2DMultisample)},
+ {"glTexStorage3D", P(gl::TexStorage3D)},
+ {"glTexSubImage2D", P(gl::TexSubImage2D)},
+ {"glTexSubImage2DRobustANGLE", P(gl::TexSubImage2DRobustANGLE)},
+ {"glTexSubImage3D", P(gl::TexSubImage3D)},
+ {"glTexSubImage3DRobustANGLE", P(gl::TexSubImage3DRobustANGLE)},
+ {"glTransformFeedbackVaryings", P(gl::TransformFeedbackVaryings)},
+ {"glUniform1f", P(gl::Uniform1f)},
+ {"glUniform1fv", P(gl::Uniform1fv)},
+ {"glUniform1i", P(gl::Uniform1i)},
+ {"glUniform1iv", P(gl::Uniform1iv)},
+ {"glUniform1ui", P(gl::Uniform1ui)},
+ {"glUniform1uiv", P(gl::Uniform1uiv)},
+ {"glUniform2f", P(gl::Uniform2f)},
+ {"glUniform2fv", P(gl::Uniform2fv)},
+ {"glUniform2i", P(gl::Uniform2i)},
+ {"glUniform2iv", P(gl::Uniform2iv)},
+ {"glUniform2ui", P(gl::Uniform2ui)},
+ {"glUniform2uiv", P(gl::Uniform2uiv)},
+ {"glUniform3f", P(gl::Uniform3f)},
+ {"glUniform3fv", P(gl::Uniform3fv)},
+ {"glUniform3i", P(gl::Uniform3i)},
+ {"glUniform3iv", P(gl::Uniform3iv)},
+ {"glUniform3ui", P(gl::Uniform3ui)},
+ {"glUniform3uiv", P(gl::Uniform3uiv)},
+ {"glUniform4f", P(gl::Uniform4f)},
+ {"glUniform4fv", P(gl::Uniform4fv)},
+ {"glUniform4i", P(gl::Uniform4i)},
+ {"glUniform4iv", P(gl::Uniform4iv)},
+ {"glUniform4ui", P(gl::Uniform4ui)},
+ {"glUniform4uiv", P(gl::Uniform4uiv)},
+ {"glUniformBlockBinding", P(gl::UniformBlockBinding)},
+ {"glUniformMatrix2fv", P(gl::UniformMatrix2fv)},
+ {"glUniformMatrix2x3fv", P(gl::UniformMatrix2x3fv)},
+ {"glUniformMatrix2x4fv", P(gl::UniformMatrix2x4fv)},
+ {"glUniformMatrix3fv", P(gl::UniformMatrix3fv)},
+ {"glUniformMatrix3x2fv", P(gl::UniformMatrix3x2fv)},
+ {"glUniformMatrix3x4fv", P(gl::UniformMatrix3x4fv)},
+ {"glUniformMatrix4fv", P(gl::UniformMatrix4fv)},
+ {"glUniformMatrix4x2fv", P(gl::UniformMatrix4x2fv)},
+ {"glUniformMatrix4x3fv", P(gl::UniformMatrix4x3fv)},
+ {"glUnmapBuffer", P(gl::UnmapBuffer)},
+ {"glUnmapBufferOES", P(gl::UnmapBufferOES)},
+ {"glUseProgram", P(gl::UseProgram)},
+ {"glUseProgramStages", P(gl::UseProgramStages)},
+ {"glValidateProgram", P(gl::ValidateProgram)},
+ {"glValidateProgramPipeline", P(gl::ValidateProgramPipeline)},
+ {"glVertexAttrib1f", P(gl::VertexAttrib1f)},
+ {"glVertexAttrib1fv", P(gl::VertexAttrib1fv)},
+ {"glVertexAttrib2f", P(gl::VertexAttrib2f)},
+ {"glVertexAttrib2fv", P(gl::VertexAttrib2fv)},
+ {"glVertexAttrib3f", P(gl::VertexAttrib3f)},
+ {"glVertexAttrib3fv", P(gl::VertexAttrib3fv)},
+ {"glVertexAttrib4f", P(gl::VertexAttrib4f)},
+ {"glVertexAttrib4fv", P(gl::VertexAttrib4fv)},
+ {"glVertexAttribBinding", P(gl::VertexAttribBinding)},
+ {"glVertexAttribDivisor", P(gl::VertexAttribDivisor)},
+ {"glVertexAttribDivisorANGLE", P(gl::VertexAttribDivisorANGLE)},
+ {"glVertexAttribFormat", P(gl::VertexAttribFormat)},
+ {"glVertexAttribI4i", P(gl::VertexAttribI4i)},
+ {"glVertexAttribI4iv", P(gl::VertexAttribI4iv)},
+ {"glVertexAttribI4ui", P(gl::VertexAttribI4ui)},
+ {"glVertexAttribI4uiv", P(gl::VertexAttribI4uiv)},
+ {"glVertexAttribIFormat", P(gl::VertexAttribIFormat)},
+ {"glVertexAttribIPointer", P(gl::VertexAttribIPointer)},
+ {"glVertexAttribPointer", P(gl::VertexAttribPointer)},
+ {"glVertexBindingDivisor", P(gl::VertexBindingDivisor)},
+ {"glViewport", P(gl::Viewport)},
+ {"glWaitSync", P(gl::WaitSync)}};
+
+size_t g_numProcs = 516;
+} // namespace egl
diff --git a/src/3rdparty/angle/src/libGLESv2/proc_table_data.json b/src/3rdparty/angle/src/libGLESv2/proc_table_data.json
new file mode 100644
index 0000000000..5ce1d433a8
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/proc_table_data.json
@@ -0,0 +1,662 @@
+{
+ "GLES2 core": [
+ "glActiveTexture",
+ "glAttachShader",
+ "glBindAttribLocation",
+ "glBindBuffer",
+ "glBindFramebuffer",
+ "glBindRenderbuffer",
+ "glBindTexture",
+ "glBlendColor",
+ "glBlendEquation",
+ "glBlendEquationSeparate",
+ "glBlendFunc",
+ "glBlendFuncSeparate",
+ "glBufferData",
+ "glBufferSubData",
+ "glCheckFramebufferStatus",
+ "glClear",
+ "glClearColor",
+ "glClearDepthf",
+ "glClearStencil",
+ "glCompileShader",
+ "glColorMask",
+ "glCompressedTexImage2D",
+ "glCompressedTexSubImage2D",
+ "glCopyTexImage2D",
+ "glCopyTexSubImage2D",
+ "glCreateProgram",
+ "glCreateShader",
+ "glCullFace",
+ "glDeleteBuffers",
+ "glDeleteFramebuffers",
+ "glDeleteProgram",
+ "glDeleteRenderbuffers",
+ "glDeleteShader",
+ "glDeleteTextures",
+ "glDepthFunc",
+ "glDepthMask",
+ "glDepthRangef",
+ "glDetachShader",
+ "glDisable",
+ "glDisableVertexAttribArray",
+ "glDrawArrays",
+ "glDrawElements",
+ "glEnable",
+ "glEnableVertexAttribArray",
+ "glFinish",
+ "glFlush",
+ "glFramebufferRenderbuffer",
+ "glFramebufferTexture2D",
+ "glFrontFace",
+ "glGenBuffers",
+ "glGenerateMipmap",
+ "glGenFramebuffers",
+ "glGenRenderbuffers",
+ "glGenTextures",
+ "glGetActiveAttrib",
+ "glGetActiveUniform",
+ "glGetAttachedShaders",
+ "glGetAttribLocation",
+ "glGetBooleanv",
+ "glGetBufferParameteriv",
+ "glGetError",
+ "glGetFloatv",
+ "glGetFramebufferAttachmentParameteriv",
+ "glGetIntegerv",
+ "glGetProgramiv",
+ "glGetProgramInfoLog",
+ "glGetRenderbufferParameteriv",
+ "glGetShaderiv",
+ "glGetShaderInfoLog",
+ "glGetShaderPrecisionFormat",
+ "glGetShaderSource",
+ "glGetString",
+ "glGetTexParameterfv",
+ "glGetTexParameteriv",
+ "glGetUniformfv",
+ "glGetUniformiv",
+ "glGetUniformLocation",
+ "glGetVertexAttribfv",
+ "glGetVertexAttribiv",
+ "glGetVertexAttribPointerv",
+ "glHint",
+ "glIsBuffer",
+ "glIsEnabled",
+ "glIsFramebuffer",
+ "glIsProgram",
+ "glIsRenderbuffer",
+ "glIsShader",
+ "glIsTexture",
+ "glLineWidth",
+ "glLinkProgram",
+ "glPixelStorei",
+ "glPolygonOffset",
+ "glReadPixels",
+ "glReleaseShaderCompiler",
+ "glRenderbufferStorage",
+ "glSampleCoverage",
+ "glScissor",
+ "glShaderBinary",
+ "glShaderSource",
+ "glStencilFunc",
+ "glStencilFuncSeparate",
+ "glStencilMask",
+ "glStencilMaskSeparate",
+ "glStencilOp",
+ "glStencilOpSeparate",
+ "glTexImage2D",
+ "glTexParameterf",
+ "glTexParameterfv",
+ "glTexParameteri",
+ "glTexParameteriv",
+ "glTexSubImage2D",
+ "glUniform1f",
+ "glUniform1fv",
+ "glUniform1i",
+ "glUniform1iv",
+ "glUniform2f",
+ "glUniform2fv",
+ "glUniform2i",
+ "glUniform2iv",
+ "glUniform3f",
+ "glUniform3fv",
+ "glUniform3i",
+ "glUniform3iv",
+ "glUniform4f",
+ "glUniform4fv",
+ "glUniform4i",
+ "glUniform4iv",
+ "glUniformMatrix2fv",
+ "glUniformMatrix3fv",
+ "glUniformMatrix4fv",
+ "glUseProgram",
+ "glValidateProgram",
+ "glVertexAttrib1f",
+ "glVertexAttrib1fv",
+ "glVertexAttrib2f",
+ "glVertexAttrib2fv",
+ "glVertexAttrib3f",
+ "glVertexAttrib3fv",
+ "glVertexAttrib4f",
+ "glVertexAttrib4fv",
+ "glVertexAttribPointer",
+ "glViewport"
+ ],
+
+ "GL_ANGLE_framebuffer_blit": [
+ "glBlitFramebufferANGLE"
+ ],
+
+ "GL_ANGLE_framebuffer_multisample": [
+ "glRenderbufferStorageMultisampleANGLE"
+ ],
+
+ "GL_EXT_discard_framebuffer": [
+ "glDiscardFramebufferEXT"
+ ],
+
+ "GL_NV_fence": [
+ "glDeleteFencesNV",
+ "glGenFencesNV",
+ "glIsFenceNV",
+ "glTestFenceNV",
+ "glGetFenceivNV",
+ "glFinishFenceNV",
+ "glSetFenceNV"
+ ],
+
+ "GL_ANGLE_translated_shader_source": [
+ "glGetTranslatedShaderSourceANGLE"
+ ],
+
+ "GL_EXT_texture_storage": [
+ "glTexStorage2DEXT"
+ ],
+
+ "GL_EXT_robustness": [
+ "glGetGraphicsResetStatusEXT",
+ "glReadnPixelsEXT",
+ "glGetnUniformfvEXT",
+ "glGetnUniformivEXT"
+ ],
+
+ "GL_EXT_occlusion_query_boolean": [
+ "glGenQueriesEXT",
+ "glDeleteQueriesEXT",
+ "glIsQueryEXT",
+ "glBeginQueryEXT",
+ "glEndQueryEXT",
+ "glGetQueryivEXT",
+ "glGetQueryObjectuivEXT"
+ ],
+
+ "GL_EXT_disjoint_timer_query": [
+ "glGenQueriesEXT",
+ "glDeleteQueriesEXT",
+ "glIsQueryEXT",
+ "glBeginQueryEXT",
+ "glEndQueryEXT",
+ "glQueryCounterEXT",
+ "glGetQueryivEXT",
+ "glGetQueryObjectivEXT",
+ "glGetQueryObjectuivEXT",
+ "glGetQueryObjecti64vEXT",
+ "glGetQueryObjectui64vEXT"
+ ],
+
+ "GL_EXT_draw_buffers": [
+ "glDrawBuffersEXT"
+ ],
+
+ "GL_ANGLE_instanced_arrays": [
+ "glDrawArraysInstancedANGLE",
+ "glDrawElementsInstancedANGLE",
+ "glVertexAttribDivisorANGLE"
+ ],
+
+ "GL_OES_get_program_binary": [
+ "glGetProgramBinaryOES",
+ "glProgramBinaryOES"
+ ],
+
+ "GL_OES_mapbuffer": [
+ "glMapBufferOES",
+ "glUnmapBufferOES",
+ "glGetBufferPointervOES"
+ ],
+
+ "GL_EXT_map_buffer_range": [
+ "glMapBufferRangeEXT",
+ "glFlushMappedBufferRangeEXT"
+ ],
+
+ "GL_EXT_debug_marker": [
+ "glInsertEventMarkerEXT",
+ "glPushGroupMarkerEXT",
+ "glPopGroupMarkerEXT"
+ ],
+
+ "GL_OES_EGL_image": [
+ "glEGLImageTargetTexture2DOES",
+ "glEGLImageTargetRenderbufferStorageOES"
+ ],
+
+ "GL_OES_vertex_array_object": [
+ "glBindVertexArrayOES",
+ "glDeleteVertexArraysOES",
+ "glGenVertexArraysOES",
+ "glIsVertexArrayOES"
+ ],
+
+ "GL_KHR_debug": [
+ "glDebugMessageControlKHR",
+ "glDebugMessageInsertKHR",
+ "glDebugMessageCallbackKHR",
+ "glGetDebugMessageLogKHR",
+ "glPushDebugGroupKHR",
+ "glPopDebugGroupKHR",
+ "glObjectLabelKHR",
+ "glGetObjectLabelKHR",
+ "glObjectPtrLabelKHR",
+ "glGetObjectPtrLabelKHR",
+ "glGetPointervKHR"
+ ],
+
+ "GL_CHROMIUM_bind_uniform_location": [
+ "glBindUniformLocationCHROMIUM"
+ ],
+
+ "GL_CHROMIUM_copy_texture": [
+ "glCopyTextureCHROMIUM",
+ "glCopySubTextureCHROMIUM"
+ ],
+
+ "GL_CHROMIUM_copy_compressed_texture": [
+ "glCompressedCopyTextureCHROMIUM"
+ ],
+
+ "GL_ANGLE_request_extension": [
+ "glRequestExtensionANGLE"
+ ],
+
+ "GL_ANGLE_robust_client_memory": [
+ "glGetBooleanvRobustANGLE",
+ "glGetBufferParameterivRobustANGLE",
+ "glGetFloatvRobustANGLE",
+ "glGetFramebufferAttachmentParameterivRobustANGLE",
+ "glGetIntegervRobustANGLE",
+ "glGetProgramivRobustANGLE",
+ "glGetRenderbufferParameterivRobustANGLE",
+ "glGetShaderivRobustANGLE",
+ "glGetTexParameterfvRobustANGLE",
+ "glGetTexParameterivRobustANGLE",
+ "glGetUniformfvRobustANGLE",
+ "glGetUniformivRobustANGLE",
+ "glGetVertexAttribfvRobustANGLE",
+ "glGetVertexAttribivRobustANGLE",
+ "glGetVertexAttribPointervRobustANGLE",
+ "glReadPixelsRobustANGLE",
+ "glTexImage2DRobustANGLE",
+ "glTexParameterfvRobustANGLE",
+ "glTexParameterivRobustANGLE",
+ "glTexSubImage2DRobustANGLE",
+ "glTexImage3DRobustANGLE",
+ "glTexSubImage3DRobustANGLE",
+ "glCompressedTexImage2DRobustANGLE",
+ "glCompressedTexSubImage2DRobustANGLE",
+ "glCompressedTexImage3DRobustANGLE",
+ "glCompressedTexSubImage3DRobustANGLE",
+ "glGetQueryivRobustANGLE",
+ "glGetQueryObjectuivRobustANGLE",
+ "glGetBufferPointervRobustANGLE",
+ "glGetIntegeri_vRobustANGLE",
+ "glGetInternalformativRobustANGLE",
+ "glGetVertexAttribIivRobustANGLE",
+ "glGetVertexAttribIuivRobustANGLE",
+ "glGetUniformuivRobustANGLE",
+ "glGetActiveUniformBlockivRobustANGLE",
+ "glGetInteger64vRobustANGLE",
+ "glGetInteger64i_vRobustANGLE",
+ "glGetBufferParameteri64vRobustANGLE",
+ "glSamplerParameterivRobustANGLE",
+ "glSamplerParameterfvRobustANGLE",
+ "glGetSamplerParameterivRobustANGLE",
+ "glGetSamplerParameterfvRobustANGLE",
+ "glGetFramebufferParameterivRobustANGLE",
+ "glGetProgramInterfaceivRobustANGLE",
+ "glGetBooleani_vRobustANGLE",
+ "glGetMultisamplefvRobustANGLE",
+ "glGetTexLevelParameterivRobustANGLE",
+ "glGetTexLevelParameterfvRobustANGLE",
+ "glGetPointervRobustANGLERobustANGLE",
+ "glReadnPixelsRobustANGLE",
+ "glGetnUniformfvRobustANGLE",
+ "glGetnUniformivRobustANGLE",
+ "glGetnUniformuivRobustANGLE",
+ "glTexParameterIivRobustANGLE",
+ "glTexParameterIuivRobustANGLE",
+ "glGetTexParameterIivRobustANGLE",
+ "glGetTexParameterIuivRobustANGLE",
+ "glSamplerParameterIivRobustANGLE",
+ "glSamplerParameterIuivRobustANGLE",
+ "glGetSamplerParameterIivRobustANGLE",
+ "glGetSamplerParameterIuivRobustANGLE",
+ "glGetQueryObjectivRobustANGLE",
+ "glGetQueryObjecti64vRobustANGLE",
+ "glGetQueryObjectui64vRobustANGLE"
+ ],
+
+ "GL_ANGLE_multiview": [
+ "glFramebufferTextureMultiviewLayeredANGLE",
+ "glFramebufferTextureMultiviewSideBySideANGLE"
+ ],
+
+ "GLES3 core": [
+ "glReadBuffer",
+ "glDrawRangeElements",
+ "glTexImage3D",
+ "glTexSubImage3D",
+ "glCopyTexSubImage3D",
+ "glCompressedTexImage3D",
+ "glCompressedTexSubImage3D",
+ "glGenQueries",
+ "glDeleteQueries",
+ "glIsQuery",
+ "glBeginQuery",
+ "glEndQuery",
+ "glGetQueryiv",
+ "glGetQueryObjectuiv",
+ "glUnmapBuffer",
+ "glGetBufferPointerv",
+ "glDrawBuffers",
+ "glUniformMatrix2x3fv",
+ "glUniformMatrix3x2fv",
+ "glUniformMatrix2x4fv",
+ "glUniformMatrix4x2fv",
+ "glUniformMatrix3x4fv",
+ "glUniformMatrix4x3fv",
+ "glBlitFramebuffer",
+ "glRenderbufferStorageMultisample",
+ "glFramebufferTextureLayer",
+ "glMapBufferRange",
+ "glFlushMappedBufferRange",
+ "glBindVertexArray",
+ "glDeleteVertexArrays",
+ "glGenVertexArrays",
+ "glIsVertexArray",
+ "glGetIntegeri_v",
+ "glBeginTransformFeedback",
+ "glEndTransformFeedback",
+ "glBindBufferRange",
+ "glBindBufferBase",
+ "glTransformFeedbackVaryings",
+ "glGetTransformFeedbackVarying",
+ "glVertexAttribIPointer",
+ "glGetVertexAttribIiv",
+ "glGetVertexAttribIuiv",
+ "glVertexAttribI4i",
+ "glVertexAttribI4ui",
+ "glVertexAttribI4iv",
+ "glVertexAttribI4uiv",
+ "glGetUniformuiv",
+ "glGetFragDataLocation",
+ "glUniform1ui",
+ "glUniform2ui",
+ "glUniform3ui",
+ "glUniform4ui",
+ "glUniform1uiv",
+ "glUniform2uiv",
+ "glUniform3uiv",
+ "glUniform4uiv",
+ "glClearBufferiv",
+ "glClearBufferuiv",
+ "glClearBufferfv",
+ "glClearBufferfi",
+ "glGetStringi",
+ "glCopyBufferSubData",
+ "glGetUniformIndices",
+ "glGetActiveUniformsiv",
+ "glGetUniformBlockIndex",
+ "glGetActiveUniformBlockiv",
+ "glGetActiveUniformBlockName",
+ "glUniformBlockBinding",
+ "glDrawArraysInstanced",
+ "glDrawElementsInstanced",
+ "glFenceSync",
+ "glIsSync",
+ "glDeleteSync",
+ "glClientWaitSync",
+ "glWaitSync",
+ "glGetInteger64v",
+ "glGetSynciv",
+ "glGetInteger64i_v",
+ "glGetBufferParameteri64v",
+ "glGenSamplers",
+ "glDeleteSamplers",
+ "glIsSampler",
+ "glBindSampler",
+ "glSamplerParameteri",
+ "glSamplerParameteriv",
+ "glSamplerParameterf",
+ "glSamplerParameterfv",
+ "glGetSamplerParameteriv",
+ "glGetSamplerParameterfv",
+ "glVertexAttribDivisor",
+ "glBindTransformFeedback",
+ "glDeleteTransformFeedbacks",
+ "glGenTransformFeedbacks",
+ "glIsTransformFeedback",
+ "glPauseTransformFeedback",
+ "glResumeTransformFeedback",
+ "glGetProgramBinary",
+ "glProgramBinary",
+ "glProgramParameteri",
+ "glInvalidateFramebuffer",
+ "glInvalidateSubFramebuffer",
+ "glTexStorage2D",
+ "glTexStorage3D",
+ "glGetInternalformativ"
+ ],
+
+ "GLES31 core": [
+ "glDispatchCompute",
+ "glDispatchComputeIndirect",
+ "glDrawArraysIndirect",
+ "glDrawElementsIndirect",
+ "glFramebufferParameteri",
+ "glGetFramebufferParameteriv",
+ "glGetProgramInterfaceiv",
+ "glGetProgramResourceIndex",
+ "glGetProgramResourceName",
+ "glGetProgramResourceiv",
+ "glGetProgramResourceLocation",
+ "glUseProgramStages",
+ "glActiveShaderProgram",
+ "glCreateShaderProgramv",
+ "glBindProgramPipeline",
+ "glDeleteProgramPipelines",
+ "glGenProgramPipelines",
+ "glIsProgramPipeline",
+ "glGetProgramPipelineiv",
+ "glProgramUniform1i",
+ "glProgramUniform2i",
+ "glProgramUniform3i",
+ "glProgramUniform4i",
+ "glProgramUniform1ui",
+ "glProgramUniform2ui",
+ "glProgramUniform3ui",
+ "glProgramUniform4ui",
+ "glProgramUniform1f",
+ "glProgramUniform2f",
+ "glProgramUniform3f",
+ "glProgramUniform4f",
+ "glProgramUniform1iv",
+ "glProgramUniform2iv",
+ "glProgramUniform3iv",
+ "glProgramUniform4iv",
+ "glProgramUniform1uiv",
+ "glProgramUniform2uiv",
+ "glProgramUniform3uiv",
+ "glProgramUniform4uiv",
+ "glProgramUniform1fv",
+ "glProgramUniform2fv",
+ "glProgramUniform3fv",
+ "glProgramUniform4fv",
+ "glProgramUniformMatrix2fv",
+ "glProgramUniformMatrix3fv",
+ "glProgramUniformMatrix4fv",
+ "glProgramUniformMatrix2x3fv",
+ "glProgramUniformMatrix3x2fv",
+ "glProgramUniformMatrix2x4fv",
+ "glProgramUniformMatrix4x2fv",
+ "glProgramUniformMatrix3x4fv",
+ "glProgramUniformMatrix4x3fv",
+ "glValidateProgramPipeline",
+ "glGetProgramPipelineInfoLog",
+ "glBindImageTexture",
+ "glGetBooleani_v",
+ "glMemoryBarrier",
+ "glMemoryBarrierByRegion",
+ "glTexStorage2DMultisample",
+ "glGetMultisamplefv",
+ "glSampleMaski",
+ "glGetTexLevelParameteriv",
+ "glGetTexLevelParameterfv",
+ "glBindVertexBuffer",
+ "glVertexAttribFormat",
+ "glVertexAttribIFormat",
+ "glVertexAttribBinding",
+ "glVertexBindingDivisor"
+ ],
+
+ "EGL 1.0": [
+ "eglChooseConfig",
+ "eglCopyBuffers",
+ "eglCreateContext",
+ "eglCreatePbufferSurface",
+ "eglCreatePixmapSurface",
+ "eglCreateWindowSurface",
+ "eglDestroyContext",
+ "eglDestroySurface",
+ "eglGetConfigAttrib",
+ "eglGetConfigs",
+ "eglGetCurrentDisplay",
+ "eglGetCurrentSurface",
+ "eglGetDisplay",
+ "eglGetError",
+ "eglGetProcAddress",
+ "eglInitialize",
+ "eglMakeCurrent",
+ "eglQueryContext",
+ "eglQueryString",
+ "eglQuerySurface",
+ "eglSwapBuffers",
+ "eglTerminate",
+ "eglWaitGL",
+ "eglWaitNative"
+ ],
+
+ "EGL 1.1": [
+ "eglBindTexImage",
+ "eglReleaseTexImage",
+ "eglSurfaceAttrib",
+ "eglSwapInterval"
+ ],
+
+ "EGL 1.2": [
+ "eglBindAPI",
+ "eglQueryAPI",
+ "eglCreatePbufferFromClientBuffer",
+ "eglReleaseThread",
+ "eglWaitClient"
+ ],
+
+ "EGL 1.4": [
+ "eglGetCurrentContext"
+ ],
+
+ "EGL 1.5": [
+ "eglCreateSync",
+ "eglDestroySync",
+ "eglClientWaitSync",
+ "eglGetSyncAttrib",
+ "eglCreateImage",
+ "eglDestroyImage",
+ "eglGetPlatformDisplay",
+ "eglCreatePlatformWindowSurface",
+ "eglCreatePlatformPixmapSurface",
+ "eglWaitSync"
+ ],
+
+ "EGL_ANGLE_query_surface_pointer": [
+ "eglQuerySurfacePointerANGLE"
+ ],
+
+ "EGL_NV_post_sub_buffer": [
+ "eglPostSubBufferNV"
+ ],
+
+ "EGL_EXT_platform_base": [
+ "eglGetPlatformDisplayEXT"
+ ],
+
+ "EGL_EXT_device_query": [
+ "eglQueryDisplayAttribEXT",
+ "eglQueryDeviceAttribEXT",
+ "eglQueryDeviceStringEXT"
+ ],
+
+ "EGL_KHR_image_base/EGL_KHR_image": [
+ "eglCreateImageKHR",
+ "eglDestroyImageKHR"
+ ],
+
+ "EGL_EXT_device_creation": [
+ "eglCreateDeviceANGLE",
+ "eglReleaseDeviceANGLE"
+ ],
+
+ "EGL_KHR_stream": [
+ "eglCreateStreamKHR",
+ "eglDestroyStreamKHR",
+ "eglStreamAttribKHR",
+ "eglQueryStreamKHR",
+ "eglQueryStreamu64KHR"
+ ],
+
+ "EGL_KHR_stream_consumer_gltexture": [
+ "eglStreamConsumerGLTextureExternalKHR",
+ "eglStreamConsumerAcquireKHR",
+ "eglStreamConsumerReleaseKHR"
+ ],
+
+ "EGL_NV_stream_consumer_gltexture_yuv": [
+ "eglStreamConsumerGLTextureExternalAttribsNV"
+ ],
+
+ "EGL_ANGLE_stream_producer_d3d_texture_nv12": [
+ "eglCreateStreamProducerD3DTextureNV12ANGLE",
+ "eglStreamPostD3DTextureNV12ANGLE"
+ ],
+
+ "EGL_CHROMIUM_get_sync_values": [
+ "eglGetSyncValuesCHROMIUM"
+ ],
+
+ "EGL_EXT_swap_buffers_with_damage": [
+ "eglSwapBuffersWithDamageEXT"
+ ],
+
+ "EGL_ANGLE_program_cache_control": [
+ "eglProgramCacheGetAttribANGLE",
+ "eglProgramCacheQueryANGLE",
+ "eglProgramCachePopulateANGLE",
+ "eglProgramCacheResizeANGLE"
+ ],
+
+ "angle::Platform related entry points": [
+ "ANGLEGetDisplayPlatform",
+ "ANGLEResetDisplayPlatform"
+ ]
+}
diff --git a/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.cpp b/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.cpp
index fa6c8b8d79..17e272301a 100644
--- a/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.cpp
+++ b/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.cpp
@@ -25,6 +25,8 @@
#include "third_party/compiler/ArrayBoundsClamper.h"
+#include "compiler/translator/IntermTraverse.h"
+
// The built-in 'clamp' instruction only accepts floats and returns a float. I
// iterated a few times with our driver team who examined the output from our
// compiler - they said the multiple casts generates more code than a single
@@ -38,7 +40,11 @@ const char* kIntClampBegin = "// BEGIN: Generated code for array bounds clamping
const char* kIntClampEnd = "// END: Generated code for array bounds clamping\n\n";
const char* kIntClampDefinition = "int webgl_int_clamp(int value, int minValue, int maxValue) { return ((value < minValue) ? minValue : ((value > maxValue) ? maxValue : value)); }\n\n";
-namespace {
+namespace sh
+{
+
+namespace
+{
class ArrayBoundsClamperMarker : public TIntermTraverser {
public:
@@ -105,3 +111,5 @@ void ArrayBoundsClamper::OutputClampingFunctionDefinition(TInfoSinkBase& out) co
}
out << kIntClampBegin << kIntClampDefinition << kIntClampEnd;
}
+
+} // namespace sh
diff --git a/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h b/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h
index 27917e6eec..a4c407f760 100644
--- a/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h
+++ b/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h
@@ -29,8 +29,12 @@
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h"
-class ArrayBoundsClamper {
-public:
+namespace sh
+{
+
+class ArrayBoundsClamper
+{
+ public:
ArrayBoundsClamper();
// Must be set before compiling any shaders to ensure consistency
@@ -57,4 +61,6 @@ private:
bool mArrayBoundsClampDefinitionNeeded;
};
+} // namespace sh
+
#endif // THIRD_PARTY_COMPILER_ARRAYBOUNDSCLAMPER_H_
diff --git a/src/3rdparty/angle/src/third_party/libXNVCtrl/LICENSE b/src/3rdparty/angle/src/third_party/libXNVCtrl/LICENSE
new file mode 100644
index 0000000000..74324c0c6f
--- /dev/null
+++ b/src/3rdparty/angle/src/third_party/libXNVCtrl/LICENSE
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2008 NVIDIA, Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */ \ No newline at end of file
diff --git a/src/3rdparty/angle/src/third_party/libXNVCtrl/NVCtrl.c b/src/3rdparty/angle/src/third_party/libXNVCtrl/NVCtrl.c
new file mode 100644
index 0000000000..e984373947
--- /dev/null
+++ b/src/3rdparty/angle/src/third_party/libXNVCtrl/NVCtrl.c
@@ -0,0 +1,1240 @@
+/*
+ * Copyright (c) 2008 NVIDIA, Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * Make sure that XTHREADS is defined, so that the
+ * LockDisplay/UnlockDisplay macros are expanded properly and the
+ * libXNVCtrl library properly protects the Display connection.
+ */
+
+#if !defined(XTHREADS)
+#define XTHREADS
+#endif /* XTHREADS */
+
+#define NEED_EVENTS
+#define NEED_REPLIES
+#include <stdint.h>
+#include <stdlib.h>
+#include <X11/Xlibint.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/extutil.h>
+#include "NVCtrlLib.h"
+#include "nv_control.h"
+
+#define NVCTRL_EXT_EXISTS 1
+#define NVCTRL_EXT_NEED_TARGET_SWAP 2
+#define NVCTRL_EXT_64_BIT_ATTRIBUTES 4
+#define NVCTRL_EXT_NEED_CHECK (1 << (sizeof(XPointer) - 1))
+
+static XExtensionInfo _nvctrl_ext_info_data;
+static XExtensionInfo *nvctrl_ext_info = &_nvctrl_ext_info_data;
+static const char *nvctrl_extension_name = NV_CONTROL_NAME;
+
+#define XNVCTRLCheckExtension(dpy,i,val) \
+ XextCheckExtension (dpy, i, nvctrl_extension_name, val)
+#define XNVCTRLSimpleCheckExtension(dpy,i) \
+ XextSimpleCheckExtension (dpy, i, nvctrl_extension_name)
+
+static int close_display();
+static uintptr_t version_flags(Display *dpy, XExtDisplayInfo *info);
+static Bool wire_to_event();
+static /* const */ XExtensionHooks nvctrl_extension_hooks = {
+ NULL, /* create_gc */
+ NULL, /* copy_gc */
+ NULL, /* flush_gc */
+ NULL, /* free_gc */
+ NULL, /* create_font */
+ NULL, /* free_font */
+ close_display, /* close_display */
+ wire_to_event, /* wire_to_event */
+ NULL, /* event_to_wire */
+ NULL, /* error */
+ NULL, /* error_string */
+};
+
+static XEXT_GENERATE_FIND_DISPLAY (find_display, nvctrl_ext_info,
+ nvctrl_extension_name,
+ &nvctrl_extension_hooks,
+ NV_CONTROL_EVENTS,
+ (XPointer)NVCTRL_EXT_NEED_CHECK)
+
+static XEXT_GENERATE_CLOSE_DISPLAY (close_display, nvctrl_ext_info)
+
+/*
+ * NV-CONTROL versions 1.8 and 1.9 pack the target_type and target_id
+ * fields in reversed order. In order to talk to one of these servers,
+ * we need to swap these fields.
+ */
+
+static void XNVCTRLCheckTargetData(Display *dpy, XExtDisplayInfo *info,
+ int *target_type, int *target_id)
+{
+ uintptr_t flags = version_flags(dpy, info);
+
+ /* We need to swap the target_type and target_id */
+ if (flags & NVCTRL_EXT_NEED_TARGET_SWAP) {
+ int tmp;
+ tmp = *target_type;
+ *target_type = *target_id;
+ *target_id = tmp;
+ }
+}
+
+
+Bool XNVCTRLQueryExtension (
+ Display *dpy,
+ int *event_basep,
+ int *error_basep
+){
+ XExtDisplayInfo *info = find_display (dpy);
+
+ if (XextHasExtension(info)) {
+ if (event_basep) *event_basep = info->codes->first_event;
+ if (error_basep) *error_basep = info->codes->first_error;
+ return True;
+ } else {
+ return False;
+ }
+}
+
+/*
+ * Retrieve any cached flags that depend on the version of the NV-CONTROL
+ * extension.
+ */
+
+static uintptr_t version_flags(Display *dpy, XExtDisplayInfo *info)
+{
+ uintptr_t data = (uintptr_t)info->data;
+
+ /* If necessary, determine the NV-CONTROL version */
+ if (data & NVCTRL_EXT_NEED_CHECK) {
+ int major, minor;
+ data = 0;
+ if (XNVCTRLQueryVersion(dpy, &major, &minor)) {
+ data |= NVCTRL_EXT_EXISTS;
+ if (major == 1 && (minor == 8 || minor == 9)) {
+ data |= NVCTRL_EXT_NEED_TARGET_SWAP;
+ }
+ if ((major > 1) || ((major == 1) && (minor > 20))) {
+ data |= NVCTRL_EXT_64_BIT_ATTRIBUTES;
+ }
+ }
+
+ info->data = (XPointer)data;
+ }
+
+ return data;
+}
+
+Bool XNVCTRLQueryVersion (
+ Display *dpy,
+ int *major,
+ int *minor
+){
+ XExtDisplayInfo *info = find_display (dpy);
+ xnvCtrlQueryExtensionReply rep;
+ xnvCtrlQueryExtensionReq *req;
+
+ if(!XextHasExtension(info))
+ return False;
+
+ XNVCTRLCheckExtension (dpy, info, False);
+
+ LockDisplay (dpy);
+ GetReq (nvCtrlQueryExtension, req);
+ req->reqType = info->codes->major_opcode;
+ req->nvReqType = X_nvCtrlQueryExtension;
+ if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return False;
+ }
+ if (major) *major = rep.major;
+ if (minor) *minor = rep.minor;
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return True;
+}
+
+
+Bool XNVCTRLIsNvScreen (
+ Display *dpy,
+ int screen
+){
+ XExtDisplayInfo *info = find_display (dpy);
+ xnvCtrlIsNvReply rep;
+ xnvCtrlIsNvReq *req;
+ Bool isnv;
+
+ if(!XextHasExtension(info))
+ return False;
+
+ XNVCTRLCheckExtension (dpy, info, False);
+
+ LockDisplay (dpy);
+ GetReq (nvCtrlIsNv, req);
+ req->reqType = info->codes->major_opcode;
+ req->nvReqType = X_nvCtrlIsNv;
+ req->screen = screen;
+ if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return False;
+ }
+ isnv = rep.isnv;
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return isnv;
+}
+
+
+Bool XNVCTRLQueryTargetCount (
+ Display *dpy,
+ int target_type,
+ int *value
+){
+ XExtDisplayInfo *info = find_display (dpy);
+ xnvCtrlQueryTargetCountReply rep;
+ xnvCtrlQueryTargetCountReq *req;
+
+ if(!XextHasExtension(info))
+ return False;
+
+ XNVCTRLCheckExtension (dpy, info, False);
+
+ LockDisplay (dpy);
+ GetReq (nvCtrlQueryTargetCount, req);
+ req->reqType = info->codes->major_opcode;
+ req->nvReqType = X_nvCtrlQueryTargetCount;
+ req->target_type = target_type;
+ if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return False;
+ }
+ if (value) *value = rep.count;
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return True;
+}
+
+
+void XNVCTRLSetTargetAttribute (
+ Display *dpy,
+ int target_type,
+ int target_id,
+ unsigned int display_mask,
+ unsigned int attribute,
+ int value
+){
+ XExtDisplayInfo *info = find_display (dpy);
+ xnvCtrlSetAttributeReq *req;
+
+ XNVCTRLSimpleCheckExtension (dpy, info);
+ XNVCTRLCheckTargetData(dpy, info, &target_type, &target_id);
+
+ LockDisplay (dpy);
+ GetReq (nvCtrlSetAttribute, req);
+ req->reqType = info->codes->major_opcode;
+ req->nvReqType = X_nvCtrlSetAttribute;
+ req->target_type = target_type;
+ req->target_id = target_id;
+ req->display_mask = display_mask;
+ req->attribute = attribute;
+ req->value = value;
+ UnlockDisplay (dpy);
+ SyncHandle ();
+}
+
+void XNVCTRLSetAttribute (
+ Display *dpy,
+ int screen,
+ unsigned int display_mask,
+ unsigned int attribute,
+ int value
+){
+ XNVCTRLSetTargetAttribute (dpy, NV_CTRL_TARGET_TYPE_X_SCREEN, screen,
+ display_mask, attribute, value);
+}
+
+
+Bool XNVCTRLSetTargetAttributeAndGetStatus (
+ Display *dpy,
+ int target_type,
+ int target_id,
+ unsigned int display_mask,
+ unsigned int attribute,
+ int value
+){
+ XExtDisplayInfo *info = find_display (dpy);
+ xnvCtrlSetAttributeAndGetStatusReq *req;
+ xnvCtrlSetAttributeAndGetStatusReply rep;
+ Bool success;
+
+ if(!XextHasExtension(info))
+ return False;
+
+ XNVCTRLCheckExtension (dpy, info, False);
+
+ LockDisplay (dpy);
+ GetReq (nvCtrlSetAttributeAndGetStatus, req);
+ req->reqType = info->codes->major_opcode;
+ req->nvReqType = X_nvCtrlSetAttributeAndGetStatus;
+ req->target_type = target_type;
+ req->target_id = target_id;
+ req->display_mask = display_mask;
+ req->attribute = attribute;
+ req->value = value;
+ if (!_XReply (dpy, (xReply *) &rep, 0, False)) {
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return False;
+ }
+ UnlockDisplay (dpy);
+ SyncHandle ();
+
+ success = rep.flags;
+ return success;
+}
+
+Bool XNVCTRLSetAttributeAndGetStatus (
+ Display *dpy,
+ int screen,
+ unsigned int display_mask,
+ unsigned int attribute,
+ int value
+){
+ return XNVCTRLSetTargetAttributeAndGetStatus(dpy,
+ NV_CTRL_TARGET_TYPE_X_SCREEN,
+ screen, display_mask,
+ attribute, value);
+}
+
+
+Bool XNVCTRLQueryTargetAttribute (
+ Display *dpy,
+ int target_type,
+ int target_id,
+ unsigned int display_mask,
+ unsigned int attribute,
+ int *value
+){
+ XExtDisplayInfo *info = find_display (dpy);
+ xnvCtrlQueryAttributeReply rep;
+ xnvCtrlQueryAttributeReq *req;
+ Bool exists;
+
+ if(!XextHasExtension(info))
+ return False;
+
+ XNVCTRLCheckExtension (dpy, info, False);
+ XNVCTRLCheckTargetData(dpy, info, &target_type, &target_id);
+
+ LockDisplay (dpy);
+ GetReq (nvCtrlQueryAttribute, req);
+ req->reqType = info->codes->major_opcode;
+ req->nvReqType = X_nvCtrlQueryAttribute;
+ req->target_type = target_type;
+ req->target_id = target_id;
+ req->display_mask = display_mask;
+ req->attribute = attribute;
+ if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return False;
+ }
+ exists = rep.flags;
+ if (exists && value) *value = rep.value;
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return exists;
+}
+
+Bool XNVCTRLQueryAttribute (
+ Display *dpy,
+ int screen,
+ unsigned int display_mask,
+ unsigned int attribute,
+ int *value
+){
+ return XNVCTRLQueryTargetAttribute(dpy, NV_CTRL_TARGET_TYPE_X_SCREEN,
+ screen, display_mask, attribute, value);
+}
+
+
+Bool XNVCTRLQueryTargetAttribute64 (
+ Display *dpy,
+ int target_type,
+ int target_id,
+ unsigned int display_mask,
+ unsigned int attribute,
+ int64_t *value
+){
+ XExtDisplayInfo *info = find_display(dpy);
+ xnvCtrlQueryAttribute64Reply rep;
+ xnvCtrlQueryAttributeReq *req;
+ Bool exists;
+
+ if (!XextHasExtension(info))
+ return False;
+
+ XNVCTRLCheckExtension(dpy, info, False);
+ XNVCTRLCheckTargetData(dpy, info, &target_type, &target_id);
+
+ LockDisplay(dpy);
+ GetReq(nvCtrlQueryAttribute, req);
+ req->reqType = info->codes->major_opcode;
+ req->nvReqType = X_nvCtrlQueryAttribute64;
+ req->target_type = target_type;
+ req->target_id = target_id;
+ req->display_mask = display_mask;
+ req->attribute = attribute;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xTrue)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+ exists = rep.flags;
+ if (exists && value) *value = rep.value_64;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return exists;
+}
+
+
+Bool XNVCTRLQueryTargetStringAttribute (
+ Display *dpy,
+ int target_type,
+ int target_id,
+ unsigned int display_mask,
+ unsigned int attribute,
+ char **ptr
+){
+ XExtDisplayInfo *info = find_display (dpy);
+ xnvCtrlQueryStringAttributeReply rep;
+ xnvCtrlQueryStringAttributeReq *req;
+ Bool exists;
+ int length, numbytes, slop;
+
+ if (!ptr) return False;
+
+ if(!XextHasExtension(info))
+ return False;
+
+ XNVCTRLCheckExtension (dpy, info, False);
+ XNVCTRLCheckTargetData(dpy, info, &target_type, &target_id);
+
+ LockDisplay (dpy);
+ GetReq (nvCtrlQueryStringAttribute, req);
+ req->reqType = info->codes->major_opcode;
+ req->nvReqType = X_nvCtrlQueryStringAttribute;
+ req->target_type = target_type;
+ req->target_id = target_id;
+ req->display_mask = display_mask;
+ req->attribute = attribute;
+ if (!_XReply (dpy, (xReply *) &rep, 0, False)) {
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return False;
+ }
+ length = rep.length;
+ numbytes = rep.n;
+ slop = numbytes & 3;
+ exists = rep.flags;
+ if (exists) {
+ *ptr = (char *) Xmalloc(numbytes);
+ }
+ if (!exists || !*ptr) {
+ _XEatData(dpy, length);
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return False;
+ } else {
+ _XRead(dpy, (char *) *ptr, numbytes);
+ if (slop) _XEatData(dpy, 4-slop);
+ }
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return exists;
+}
+
+Bool XNVCTRLQueryStringAttribute (
+ Display *dpy,
+ int screen,
+ unsigned int display_mask,
+ unsigned int attribute,
+ char **ptr
+){
+ return XNVCTRLQueryTargetStringAttribute(dpy, NV_CTRL_TARGET_TYPE_X_SCREEN,
+ screen, display_mask,
+ attribute, ptr);
+}
+
+
+Bool XNVCTRLSetTargetStringAttribute (
+ Display *dpy,
+ int target_type,
+ int target_id,
+ unsigned int display_mask,
+ unsigned int attribute,
+ char *ptr
+){
+ XExtDisplayInfo *info = find_display (dpy);
+ xnvCtrlSetStringAttributeReq *req;
+ xnvCtrlSetStringAttributeReply rep;
+ int size;
+ Bool success;
+
+ if(!XextHasExtension(info))
+ return False;
+
+ XNVCTRLCheckExtension (dpy, info, False);
+
+ size = strlen(ptr)+1;
+
+ LockDisplay (dpy);
+ GetReq (nvCtrlSetStringAttribute, req);
+ req->reqType = info->codes->major_opcode;
+ req->nvReqType = X_nvCtrlSetStringAttribute;
+ req->target_type = target_type;
+ req->target_id = target_id;
+ req->display_mask = display_mask;
+ req->attribute = attribute;
+ req->length += ((size + 3) & ~3) >> 2;
+ req->num_bytes = size;
+ Data(dpy, ptr, size);
+
+ if (!_XReply (dpy, (xReply *) &rep, 0, False)) {
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return False;
+ }
+ UnlockDisplay (dpy);
+ SyncHandle ();
+
+ success = rep.flags;
+ return success;
+}
+
+Bool XNVCTRLSetStringAttribute (
+ Display *dpy,
+ int screen,
+ unsigned int display_mask,
+ unsigned int attribute,
+ char *ptr
+){
+ return XNVCTRLSetTargetStringAttribute(dpy, NV_CTRL_TARGET_TYPE_X_SCREEN,
+ screen, display_mask,
+ attribute, ptr);
+}
+
+
+static Bool XNVCTRLQueryValidTargetAttributeValues32 (
+ Display *dpy,
+ XExtDisplayInfo *info,
+ int target_type,
+ int target_id,
+ unsigned int display_mask,
+ unsigned int attribute,
+ NVCTRLAttributeValidValuesRec *values
+){
+ xnvCtrlQueryValidAttributeValuesReply rep;
+ xnvCtrlQueryValidAttributeValuesReq *req;
+ Bool exists;
+
+ LockDisplay (dpy);
+ GetReq (nvCtrlQueryValidAttributeValues, req);
+ req->reqType = info->codes->major_opcode;
+ req->nvReqType = X_nvCtrlQueryValidAttributeValues;
+ req->target_type = target_type;
+ req->target_id = target_id;
+ req->display_mask = display_mask;
+ req->attribute = attribute;
+ if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return False;
+ }
+ exists = rep.flags;
+ if (exists) {
+ values->type = rep.attr_type;
+ if (rep.attr_type == ATTRIBUTE_TYPE_RANGE) {
+ values->u.range.min = rep.min;
+ values->u.range.max = rep.max;
+ }
+ if (rep.attr_type == ATTRIBUTE_TYPE_INT_BITS) {
+ values->u.bits.ints = rep.bits;
+ }
+ values->permissions = rep.perms;
+ }
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return exists;
+}
+
+
+Bool XNVCTRLQueryValidTargetStringAttributeValues (
+ Display *dpy,
+ int target_type,
+ int target_id,
+ unsigned int display_mask,
+ unsigned int attribute,
+ NVCTRLAttributeValidValuesRec *values
+){
+ XExtDisplayInfo *info = find_display(dpy);
+ Bool exists;
+ xnvCtrlQueryValidAttributeValuesReply rep;
+ xnvCtrlQueryValidAttributeValuesReq *req;
+
+ if (!values) return False;
+
+ if (!XextHasExtension(info))
+ return False;
+
+ XNVCTRLCheckExtension(dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq (nvCtrlQueryValidAttributeValues, req);
+ req->reqType = info->codes->major_opcode;
+ req->nvReqType = X_nvCtrlQueryValidStringAttributeValues;
+ req->target_type = target_type;
+ req->target_id = target_id;
+ req->display_mask = display_mask;
+ req->attribute = attribute;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xTrue)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+ exists = rep.flags;
+ if (exists) {
+ values->type = rep.attr_type;
+ values->permissions = rep.perms;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return exists;
+}
+
+
+static Bool XNVCTRLQueryValidTargetAttributeValues64 (
+ Display *dpy,
+ XExtDisplayInfo *info,
+ int target_type,
+ int target_id,
+ unsigned int display_mask,
+ unsigned int attribute,
+ NVCTRLAttributeValidValuesRec *values
+){
+ xnvCtrlQueryValidAttributeValues64Reply rep;
+ xnvCtrlQueryValidAttributeValuesReq *req;
+ Bool exists;
+
+ LockDisplay(dpy);
+ GetReq(nvCtrlQueryValidAttributeValues, req);
+ req->reqType = info->codes->major_opcode;
+ req->nvReqType = X_nvCtrlQueryValidAttributeValues64;
+ req->target_type = target_type;
+ req->target_id = target_id;
+ req->display_mask = display_mask;
+ req->attribute = attribute;
+ if (!_XReply(dpy, (xReply *)&rep,
+ sz_xnvCtrlQueryValidAttributeValues64Reply_extra,
+ xTrue)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+ exists = rep.flags;
+ if (exists) {
+ values->type = rep.attr_type;
+ if (rep.attr_type == ATTRIBUTE_TYPE_RANGE) {
+ values->u.range.min = rep.min_64;
+ values->u.range.max = rep.max_64;
+ }
+ if (rep.attr_type == ATTRIBUTE_TYPE_INT_BITS) {
+ values->u.bits.ints = rep.bits_64;
+ }
+ values->permissions = rep.perms;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return exists;
+}
+
+Bool XNVCTRLQueryValidTargetAttributeValues (
+ Display *dpy,
+ int target_type,
+ int target_id,
+ unsigned int display_mask,
+ unsigned int attribute,
+ NVCTRLAttributeValidValuesRec *values
+){
+ XExtDisplayInfo *info = find_display(dpy);
+ Bool exists;
+ uintptr_t flags;
+
+ if (!values) return False;
+
+ if (!XextHasExtension(info))
+ return False;
+
+ XNVCTRLCheckExtension(dpy, info, False);
+ XNVCTRLCheckTargetData(dpy, info, &target_type, &target_id);
+
+ flags = version_flags(dpy,info);
+
+ if (!(flags & NVCTRL_EXT_EXISTS))
+ return False;
+
+ if (flags & NVCTRL_EXT_64_BIT_ATTRIBUTES) {
+ exists = XNVCTRLQueryValidTargetAttributeValues64(dpy, info,
+ target_type,
+ target_id,
+ display_mask,
+ attribute,
+ values);
+ } else {
+ exists = XNVCTRLQueryValidTargetAttributeValues32(dpy, info,
+ target_type,
+ target_id,
+ display_mask,
+ attribute,
+ values);
+ }
+ return exists;
+}
+
+
+Bool XNVCTRLQueryValidAttributeValues (
+ Display *dpy,
+ int screen,
+ unsigned int display_mask,
+ unsigned int attribute,
+ NVCTRLAttributeValidValuesRec *values
+){
+ return XNVCTRLQueryValidTargetAttributeValues(dpy,
+ NV_CTRL_TARGET_TYPE_X_SCREEN,
+ screen, display_mask,
+ attribute, values);
+}
+
+
+static Bool QueryAttributePermissionsInternal (
+ Display *dpy,
+ unsigned int attribute,
+ NVCTRLAttributePermissionsRec *permissions,
+ unsigned int reqType
+){
+ XExtDisplayInfo *info = find_display (dpy);
+ xnvCtrlQueryAttributePermissionsReply rep;
+ xnvCtrlQueryAttributePermissionsReq *req;
+ Bool exists;
+
+ if(!XextHasExtension(info))
+ return False;
+
+ XNVCTRLCheckExtension (dpy, info, False);
+
+ LockDisplay(dpy);
+ GetReq(nvCtrlQueryAttributePermissions, req);
+ req->reqType = info->codes->major_opcode;
+ req->nvReqType = reqType;
+ req->attribute = attribute;
+ if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
+ UnlockDisplay (dpy);
+ SyncHandle();
+ return False;
+ }
+ exists = rep.flags;
+ if (exists && permissions) {
+ permissions->type = rep.attr_type;
+ permissions->permissions = rep.perms;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return exists;
+}
+
+
+Bool XNVCTRLQueryAttributePermissions (
+ Display *dpy,
+ unsigned int attribute,
+ NVCTRLAttributePermissionsRec *permissions
+){
+ return QueryAttributePermissionsInternal(dpy,
+ attribute,
+ permissions,
+ X_nvCtrlQueryAttributePermissions);
+}
+
+
+Bool XNVCTRLQueryStringAttributePermissions (
+ Display *dpy,
+ unsigned int attribute,
+ NVCTRLAttributePermissionsRec *permissions
+){
+ return QueryAttributePermissionsInternal(dpy,
+ attribute,
+ permissions,
+ X_nvCtrlQueryStringAttributePermissions);
+}
+
+
+Bool XNVCTRLQueryBinaryDataAttributePermissions (
+ Display *dpy,
+ unsigned int attribute,
+ NVCTRLAttributePermissionsRec *permissions
+){
+ return QueryAttributePermissionsInternal(dpy,
+ attribute,
+ permissions,
+ X_nvCtrlQueryBinaryDataAttributePermissions);
+}
+
+
+Bool XNVCTRLQueryStringOperationAttributePermissions (
+ Display *dpy,
+ unsigned int attribute,
+ NVCTRLAttributePermissionsRec *permissions
+){
+ return QueryAttributePermissionsInternal(dpy,
+ attribute,
+ permissions,
+ X_nvCtrlQueryStringOperationAttributePermissions);
+}
+
+
+void XNVCTRLSetGvoColorConversion (
+ Display *dpy,
+ int screen,
+ float colorMatrix[3][3],
+ float colorOffset[3],
+ float colorScale[3]
+){
+ XExtDisplayInfo *info = find_display (dpy);
+ xnvCtrlSetGvoColorConversionReq *req;
+
+ XNVCTRLSimpleCheckExtension (dpy, info);
+
+ LockDisplay (dpy);
+ GetReq (nvCtrlSetGvoColorConversion, req);
+ req->reqType = info->codes->major_opcode;
+ req->nvReqType = X_nvCtrlSetGvoColorConversion;
+ req->screen = screen;
+
+ req->cscMatrix_y_r = colorMatrix[0][0];
+ req->cscMatrix_y_g = colorMatrix[0][1];
+ req->cscMatrix_y_b = colorMatrix[0][2];
+
+ req->cscMatrix_cr_r = colorMatrix[1][0];
+ req->cscMatrix_cr_g = colorMatrix[1][1];
+ req->cscMatrix_cr_b = colorMatrix[1][2];
+
+ req->cscMatrix_cb_r = colorMatrix[2][0];
+ req->cscMatrix_cb_g = colorMatrix[2][1];
+ req->cscMatrix_cb_b = colorMatrix[2][2];
+
+ req->cscOffset_y = colorOffset[0];
+ req->cscOffset_cr = colorOffset[1];
+ req->cscOffset_cb = colorOffset[2];
+
+ req->cscScale_y = colorScale[0];
+ req->cscScale_cr = colorScale[1];
+ req->cscScale_cb = colorScale[2];
+
+ UnlockDisplay (dpy);
+ SyncHandle ();
+}
+
+
+Bool XNVCTRLQueryGvoColorConversion (
+ Display *dpy,
+ int screen,
+ float colorMatrix[3][3],
+ float colorOffset[3],
+ float colorScale[3]
+){
+ XExtDisplayInfo *info = find_display (dpy);
+ xnvCtrlQueryGvoColorConversionReply rep;
+ xnvCtrlQueryGvoColorConversionReq *req;
+
+ if(!XextHasExtension(info))
+ return False;
+
+ XNVCTRLCheckExtension (dpy, info, False);
+
+ LockDisplay (dpy);
+
+ GetReq (nvCtrlQueryGvoColorConversion, req);
+ req->reqType = info->codes->major_opcode;
+ req->nvReqType = X_nvCtrlQueryGvoColorConversion;
+ req->screen = screen;
+
+ if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return False;
+ }
+
+ _XRead(dpy, (char *)(colorMatrix), 36);
+ _XRead(dpy, (char *)(colorOffset), 12);
+ _XRead(dpy, (char *)(colorScale), 12);
+
+ UnlockDisplay (dpy);
+ SyncHandle ();
+
+ return True;
+}
+
+
+Bool XNVCtrlSelectTargetNotify (
+ Display *dpy,
+ int target_type,
+ int target_id,
+ int notify_type,
+ Bool onoff
+){
+ XExtDisplayInfo *info = find_display (dpy);
+ xnvCtrlSelectTargetNotifyReq *req;
+
+ if(!XextHasExtension (info))
+ return False;
+
+ XNVCTRLCheckExtension (dpy, info, False);
+
+ LockDisplay (dpy);
+ GetReq (nvCtrlSelectTargetNotify, req);
+ req->reqType = info->codes->major_opcode;
+ req->nvReqType = X_nvCtrlSelectTargetNotify;
+ req->target_type = target_type;
+ req->target_id = target_id;
+ req->notifyType = notify_type;
+ req->onoff = onoff;
+ UnlockDisplay (dpy);
+ SyncHandle ();
+
+ return True;
+}
+
+
+Bool XNVCtrlSelectNotify (
+ Display *dpy,
+ int screen,
+ int type,
+ Bool onoff
+){
+ XExtDisplayInfo *info = find_display (dpy);
+ xnvCtrlSelectNotifyReq *req;
+
+ if(!XextHasExtension (info))
+ return False;
+
+ XNVCTRLCheckExtension (dpy, info, False);
+
+ LockDisplay (dpy);
+ GetReq (nvCtrlSelectNotify, req);
+ req->reqType = info->codes->major_opcode;
+ req->nvReqType = X_nvCtrlSelectNotify;
+ req->screen = screen;
+ req->notifyType = type;
+ req->onoff = onoff;
+ UnlockDisplay (dpy);
+ SyncHandle ();
+
+ return True;
+}
+
+Bool XNVCTRLQueryTargetBinaryData (
+ Display *dpy,
+ int target_type,
+ int target_id,
+ unsigned int display_mask,
+ unsigned int attribute,
+ unsigned char **ptr,
+ int *len
+){
+ XExtDisplayInfo *info = find_display (dpy);
+ xnvCtrlQueryBinaryDataReply rep;
+ xnvCtrlQueryBinaryDataReq *req;
+ Bool exists;
+ int length, numbytes, slop;
+
+ if (!ptr) return False;
+
+ if(!XextHasExtension(info))
+ return False;
+
+ XNVCTRLCheckExtension (dpy, info, False);
+ XNVCTRLCheckTargetData(dpy, info, &target_type, &target_id);
+
+ LockDisplay (dpy);
+ GetReq (nvCtrlQueryBinaryData, req);
+ req->reqType = info->codes->major_opcode;
+ req->nvReqType = X_nvCtrlQueryBinaryData;
+ req->target_type = target_type;
+ req->target_id = target_id;
+ req->display_mask = display_mask;
+ req->attribute = attribute;
+ if (!_XReply (dpy, (xReply *) &rep, 0, False)) {
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return False;
+ }
+ length = rep.length;
+ numbytes = rep.n;
+ slop = numbytes & 3;
+ exists = rep.flags;
+ if (exists) {
+ *ptr = (unsigned char *) Xmalloc(numbytes);
+ }
+ if (!exists || !*ptr) {
+ _XEatData(dpy, length);
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return False;
+ } else {
+ _XRead(dpy, (char *) *ptr, numbytes);
+ if (slop) _XEatData(dpy, 4-slop);
+ }
+ if (len) *len = numbytes;
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return exists;
+}
+
+Bool XNVCTRLQueryBinaryData (
+ Display *dpy,
+ int screen,
+ unsigned int display_mask,
+ unsigned int attribute,
+ unsigned char **ptr,
+ int *len
+){
+ return XNVCTRLQueryTargetBinaryData(dpy, NV_CTRL_TARGET_TYPE_X_SCREEN,
+ screen, display_mask,
+ attribute, ptr, len);
+}
+
+Bool XNVCTRLStringOperation (
+ Display *dpy,
+ int target_type,
+ int target_id,
+ unsigned int display_mask,
+ unsigned int attribute,
+ char *pIn,
+ char **ppOut
+) {
+ XExtDisplayInfo *info = find_display(dpy);
+ xnvCtrlStringOperationReq *req;
+ xnvCtrlStringOperationReply rep;
+ Bool ret;
+ int inSize, outSize, length, slop;
+
+ if (!XextHasExtension(info))
+ return False;
+
+ if (!ppOut)
+ return False;
+
+ *ppOut = NULL;
+
+ XNVCTRLCheckExtension(dpy, info, False);
+ XNVCTRLCheckTargetData(dpy, info, &target_type, &target_id);
+
+ if (pIn) {
+ inSize = strlen(pIn) + 1;
+ } else {
+ inSize = 0;
+ }
+
+ LockDisplay(dpy);
+ GetReq(nvCtrlStringOperation, req);
+
+ req->reqType = info->codes->major_opcode;
+ req->nvReqType = X_nvCtrlStringOperation;
+ req->target_type = target_type;
+ req->target_id = target_id;
+ req->display_mask = display_mask;
+ req->attribute = attribute;
+
+ req->length += ((inSize + 3) & ~3) >> 2;
+ req->num_bytes = inSize;
+
+ if (pIn) {
+ Data(dpy, pIn, inSize);
+ }
+
+ if (!_XReply (dpy, (xReply *) &rep, 0, False)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+
+ length = rep.length;
+ outSize = rep.num_bytes;
+ slop = outSize & 3;
+
+ if (outSize) *ppOut = (char *) Xmalloc(outSize);
+
+ if (!*ppOut) {
+ _XEatData(dpy, length);
+ } else {
+ _XRead(dpy, (char *) *ppOut, outSize);
+ if (slop) _XEatData(dpy, 4-slop);
+ }
+
+ ret = rep.ret;
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ return ret;
+}
+
+
+static Bool wire_to_event (Display *dpy, XEvent *host, xEvent *wire)
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ XNVCtrlEvent *re;
+ xnvctrlEvent *event;
+ XNVCtrlEventTarget *reTarget;
+ xnvctrlEventTarget *eventTarget;
+ XNVCtrlEventTargetAvailability *reTargetAvailability;
+ XNVCtrlStringEventTarget *reTargetString;
+ XNVCtrlBinaryEventTarget *reTargetBinary;
+
+ XNVCTRLCheckExtension (dpy, info, False);
+
+ switch ((wire->u.u.type & 0x7F) - info->codes->first_event) {
+ case ATTRIBUTE_CHANGED_EVENT:
+ re = (XNVCtrlEvent *) host;
+ event = (xnvctrlEvent *) wire;
+ re->attribute_changed.type = event->u.u.type & 0x7F;
+ re->attribute_changed.serial =
+ _XSetLastRequestRead(dpy, (xGenericReply*) event);
+ re->attribute_changed.send_event = ((event->u.u.type & 0x80) != 0);
+ re->attribute_changed.display = dpy;
+ re->attribute_changed.time = event->u.attribute_changed.time;
+ re->attribute_changed.screen = event->u.attribute_changed.screen;
+ re->attribute_changed.display_mask =
+ event->u.attribute_changed.display_mask;
+ re->attribute_changed.attribute = event->u.attribute_changed.attribute;
+ re->attribute_changed.value = event->u.attribute_changed.value;
+ break;
+ case TARGET_ATTRIBUTE_CHANGED_EVENT:
+ reTarget = (XNVCtrlEventTarget *) host;
+ eventTarget = (xnvctrlEventTarget *) wire;
+ reTarget->attribute_changed.type = eventTarget->u.u.type & 0x7F;
+ reTarget->attribute_changed.serial =
+ _XSetLastRequestRead(dpy, (xGenericReply*) eventTarget);
+ reTarget->attribute_changed.send_event =
+ ((eventTarget->u.u.type & 0x80) != 0);
+ reTarget->attribute_changed.display = dpy;
+ reTarget->attribute_changed.time =
+ eventTarget->u.attribute_changed.time;
+ reTarget->attribute_changed.target_type =
+ eventTarget->u.attribute_changed.target_type;
+ reTarget->attribute_changed.target_id =
+ eventTarget->u.attribute_changed.target_id;
+ reTarget->attribute_changed.display_mask =
+ eventTarget->u.attribute_changed.display_mask;
+ reTarget->attribute_changed.attribute =
+ eventTarget->u.attribute_changed.attribute;
+ reTarget->attribute_changed.value =
+ eventTarget->u.attribute_changed.value;
+ break;
+ case TARGET_ATTRIBUTE_AVAILABILITY_CHANGED_EVENT:
+ reTargetAvailability = (XNVCtrlEventTargetAvailability *) host;
+ eventTarget = (xnvctrlEventTarget *) wire;
+ reTargetAvailability->attribute_changed.type =
+ eventTarget->u.u.type & 0x7F;
+ reTargetAvailability->attribute_changed.serial =
+ _XSetLastRequestRead(dpy, (xGenericReply*) eventTarget);
+ reTargetAvailability->attribute_changed.send_event =
+ ((eventTarget->u.u.type & 0x80) != 0);
+ reTargetAvailability->attribute_changed.display = dpy;
+ reTargetAvailability->attribute_changed.time =
+ eventTarget->u.availability_changed.time;
+ reTargetAvailability->attribute_changed.target_type =
+ eventTarget->u.availability_changed.target_type;
+ reTargetAvailability->attribute_changed.target_id =
+ eventTarget->u.availability_changed.target_id;
+ reTargetAvailability->attribute_changed.display_mask =
+ eventTarget->u.availability_changed.display_mask;
+ reTargetAvailability->attribute_changed.attribute =
+ eventTarget->u.availability_changed.attribute;
+ reTargetAvailability->attribute_changed.availability =
+ eventTarget->u.availability_changed.availability;
+ reTargetAvailability->attribute_changed.value =
+ eventTarget->u.availability_changed.value;
+ break;
+ case TARGET_STRING_ATTRIBUTE_CHANGED_EVENT:
+ reTargetString = (XNVCtrlStringEventTarget *) host;
+ eventTarget = (xnvctrlEventTarget *) wire;
+ reTargetString->attribute_changed.type = eventTarget->u.u.type & 0x7F;
+ reTargetString->attribute_changed.serial =
+ _XSetLastRequestRead(dpy, (xGenericReply*) eventTarget);
+ reTargetString->attribute_changed.send_event =
+ ((eventTarget->u.u.type & 0x80) != 0);
+ reTargetString->attribute_changed.display = dpy;
+ reTargetString->attribute_changed.time =
+ eventTarget->u.attribute_changed.time;
+ reTargetString->attribute_changed.target_type =
+ eventTarget->u.attribute_changed.target_type;
+ reTargetString->attribute_changed.target_id =
+ eventTarget->u.attribute_changed.target_id;
+ reTargetString->attribute_changed.display_mask =
+ eventTarget->u.attribute_changed.display_mask;
+ reTargetString->attribute_changed.attribute =
+ eventTarget->u.attribute_changed.attribute;
+ break;
+ case TARGET_BINARY_ATTRIBUTE_CHANGED_EVENT:
+ reTargetBinary = (XNVCtrlBinaryEventTarget *) host;
+ eventTarget = (xnvctrlEventTarget *) wire;
+ reTargetBinary->attribute_changed.type = eventTarget->u.u.type & 0x7F;
+ reTargetBinary->attribute_changed.serial =
+ _XSetLastRequestRead(dpy, (xGenericReply*) eventTarget);
+ reTargetBinary->attribute_changed.send_event =
+ ((eventTarget->u.u.type & 0x80) != 0);
+ reTargetBinary->attribute_changed.display = dpy;
+ reTargetBinary->attribute_changed.time =
+ eventTarget->u.attribute_changed.time;
+ reTargetBinary->attribute_changed.target_type =
+ eventTarget->u.attribute_changed.target_type;
+ reTargetBinary->attribute_changed.target_id =
+ eventTarget->u.attribute_changed.target_id;
+ reTargetBinary->attribute_changed.display_mask =
+ eventTarget->u.attribute_changed.display_mask;
+ reTargetBinary->attribute_changed.attribute =
+ eventTarget->u.attribute_changed.attribute;
+ break;
+
+ default:
+ return False;
+ }
+
+ return True;
+}
+
diff --git a/src/3rdparty/angle/src/third_party/libXNVCtrl/NVCtrl.h b/src/3rdparty/angle/src/third_party/libXNVCtrl/NVCtrl.h
new file mode 100644
index 0000000000..7bd7ab7a33
--- /dev/null
+++ b/src/3rdparty/angle/src/third_party/libXNVCtrl/NVCtrl.h
@@ -0,0 +1,4365 @@
+/*
+ * Copyright (c) 2010 NVIDIA, Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __NVCTRL_H
+#define __NVCTRL_H
+
+#include <stdint.h>
+
+/**************************************************************************/
+
+/*
+ * Attribute Targets
+ *
+ * Targets define attribute groups. For example, some attributes are only
+ * valid to set on a GPU, others are only valid when talking about an
+ * X Screen. Target types are then what is used to identify the target
+ * group of the attribute you wish to set/query.
+ *
+ * Here are the supported target types:
+ */
+
+#define NV_CTRL_TARGET_TYPE_X_SCREEN 0
+#define NV_CTRL_TARGET_TYPE_GPU 1
+#define NV_CTRL_TARGET_TYPE_FRAMELOCK 2
+#define NV_CTRL_TARGET_TYPE_VCSC 3 /* Visual Computing System */
+#define NV_CTRL_TARGET_TYPE_GVI 4
+#define NV_CTRL_TARGET_TYPE_COOLER 5 /* e.g., fan */
+#define NV_CTRL_TARGET_TYPE_THERMAL_SENSOR 6
+#define NV_CTRL_TARGET_TYPE_3D_VISION_PRO_TRANSCEIVER 7
+#define NV_CTRL_TARGET_TYPE_DISPLAY 8
+
+/**************************************************************************/
+
+/*
+ * Attributes
+ *
+ * Some attributes may only be read; some may require a display_mask
+ * argument and others may be valid only for specific target types.
+ * This information is encoded in the "permission" comment after each
+ * attribute #define, and can be queried at run time with
+ * XNVCTRLQueryValidAttributeValues() and/or
+ * XNVCTRLQueryValidTargetAttributeValues()
+ *
+ * Key to Integer Attribute "Permissions":
+ *
+ * R: The attribute is readable (in general, all attributes will be
+ * readable)
+ *
+ * W: The attribute is writable (attributes may not be writable for
+ * various reasons: they represent static system information, they
+ * can only be changed by changing an XF86Config option, etc).
+ *
+ * D: The attribute requires the display mask argument. The
+ * attributes NV_CTRL_CONNECTED_DISPLAYS and NV_CTRL_ENABLED_DISPLAYS
+ * will be a bitmask of what display devices are connected and what
+ * display devices are enabled for use in X, respectively. Each bit
+ * in the bitmask represents a display device; it is these bits which
+ * should be used as the display_mask when dealing with attributes
+ * designated with "D" below. For attributes that do not require the
+ * display mask, the argument is ignored.
+ *
+ * Alternatively, NV-CONTROL versions 1.27 and greater allow these
+ * attributes to be accessed via display target types, in which case
+ * the display_mask is ignored.
+ *
+ * G: The attribute may be queried using an NV_CTRL_TARGET_TYPE_GPU
+ * target type via XNVCTRLQueryTargetAttribute().
+ *
+ * F: The attribute may be queried using an NV_CTRL_TARGET_TYPE_FRAMELOCK
+ * target type via XNVCTRLQueryTargetAttribute().
+ *
+ * X: When Xinerama is enabled, this attribute is kept consistent across
+ * all Physical X Screens; assignment of this attribute will be
+ * broadcast by the NVIDIA X Driver to all X Screens.
+ *
+ * V: The attribute may be queried using an NV_CTRL_TARGET_TYPE_VCSC
+ * target type via XNVCTRLQueryTargetAttribute().
+ *
+ * I: The attribute may be queried using an NV_CTRL_TARGET_TYPE_GVI target type
+ * via XNVCTRLQueryTargetAttribute().
+ *
+ * Q: The attribute is a 64-bit integer attribute; use the 64-bit versions
+ * of the appropriate query interfaces.
+ *
+ * C: The attribute may be queried using an NV_CTRL_TARGET_TYPE_COOLER target
+ * type via XNVCTRLQueryTargetAttribute().
+ *
+ * S: The attribute may be queried using an NV_CTRL_TARGET_TYPE_THERMAL_SENSOR
+ * target type via XNVCTRLQueryTargetAttribute().
+ *
+ * T: The attribute may be queried using an
+ * NV_CTRL_TARGET_TYPE_3D_VISION_PRO_TRANSCEIVER target type
+ * via XNVCTRLQueryTargetAttribute().
+ *
+ * NOTE: Unless mentioned otherwise, all attributes may be queried using
+ * an NV_CTRL_TARGET_TYPE_X_SCREEN target type via
+ * XNVCTRLQueryTargetAttribute().
+ */
+
+/**************************************************************************/
+
+/*
+ * Integer attributes:
+ *
+ * Integer attributes can be queried through the XNVCTRLQueryAttribute() and
+ * XNVCTRLQueryTargetAttribute() function calls.
+ *
+ * Integer attributes can be set through the XNVCTRLSetAttribute() and
+ * XNVCTRLSetTargetAttribute() function calls.
+ *
+ * Unless otherwise noted, all integer attributes can be queried/set
+ * using an NV_CTRL_TARGET_TYPE_X_SCREEN target. Attributes that cannot
+ * take an NV_CTRL_TARGET_TYPE_X_SCREEN also cannot be queried/set through
+ * XNVCTRLQueryAttribute()/XNVCTRLSetAttribute() (Since these assume
+ * an X Screen target).
+ */
+
+/*
+ * NV_CTRL_FLATPANEL_SCALING - not supported
+ */
+
+#define NV_CTRL_FLATPANEL_SCALING 2 /* RWDG */
+#define NV_CTRL_FLATPANEL_SCALING_DEFAULT 0
+#define NV_CTRL_FLATPANEL_SCALING_NATIVE 1
+#define NV_CTRL_FLATPANEL_SCALING_SCALED 2
+#define NV_CTRL_FLATPANEL_SCALING_CENTERED 3
+#define NV_CTRL_FLATPANEL_SCALING_ASPECT_SCALED 4
+
+/*
+ * NV_CTRL_FLATPANEL_DITHERING is deprecated; NV_CTRL_DITHERING should
+ * be used instead.
+ */
+
+#define NV_CTRL_FLATPANEL_DITHERING 3 /* RWDG */
+#define NV_CTRL_FLATPANEL_DITHERING_DEFAULT 0
+#define NV_CTRL_FLATPANEL_DITHERING_ENABLED 1
+#define NV_CTRL_FLATPANEL_DITHERING_DISABLED 2
+
+/*
+ * NV_CTRL_DITHERING - the requested dithering configuration;
+ * possible values are:
+ *
+ * 0: auto (the driver will decide when to dither)
+ * 1: enabled (the driver will always dither when possible)
+ * 2: disabled (the driver will never dither)
+ */
+
+#define NV_CTRL_DITHERING 3 /* RWDG */
+#define NV_CTRL_DITHERING_AUTO 0
+#define NV_CTRL_DITHERING_ENABLED 1
+#define NV_CTRL_DITHERING_DISABLED 2
+
+/*
+ * NV_CTRL_DIGITAL_VIBRANCE - sets the digital vibrance level for the
+ * specified display device.
+ */
+
+#define NV_CTRL_DIGITAL_VIBRANCE 4 /* RWDG */
+
+/*
+ * NV_CTRL_BUS_TYPE - returns the bus type through which the specified device
+ * is connected to the computer.
+ * When this attribute is queried on an X screen target, the bus type of the
+ * GPU driving the X screen is returned.
+ */
+
+#define NV_CTRL_BUS_TYPE 5 /* R--GI */
+#define NV_CTRL_BUS_TYPE_AGP 0
+#define NV_CTRL_BUS_TYPE_PCI 1
+#define NV_CTRL_BUS_TYPE_PCI_EXPRESS 2
+#define NV_CTRL_BUS_TYPE_INTEGRATED 3
+
+/*
+ * NV_CTRL_VIDEO_RAM - returns the total amount of memory available
+ * to the specified GPU (or the GPU driving the specified X
+ * screen). Note: if the GPU supports TurboCache(TM), the value
+ * reported may exceed the amount of video memory installed on the
+ * GPU. The value reported for integrated GPUs may likewise exceed
+ * the amount of dedicated system memory set aside by the system
+ * BIOS for use by the integrated GPU.
+ */
+
+#define NV_CTRL_VIDEO_RAM 6 /* R--G */
+
+/*
+ * NV_CTRL_IRQ - returns the interrupt request line used by the specified
+ * device.
+ * When this attribute is queried on an X screen target, the IRQ of the GPU
+ * driving the X screen is returned.
+ */
+
+#define NV_CTRL_IRQ 7 /* R--GI */
+
+/*
+ * NV_CTRL_OPERATING_SYSTEM - returns the operating system on which
+ * the X server is running.
+ */
+
+#define NV_CTRL_OPERATING_SYSTEM 8 /* R--G */
+#define NV_CTRL_OPERATING_SYSTEM_LINUX 0
+#define NV_CTRL_OPERATING_SYSTEM_FREEBSD 1
+#define NV_CTRL_OPERATING_SYSTEM_SUNOS 2
+
+/*
+ * NV_CTRL_SYNC_TO_VBLANK - enables sync to vblank for OpenGL clients.
+ * This setting is only applied to OpenGL clients that are started
+ * after this setting is applied.
+ */
+
+#define NV_CTRL_SYNC_TO_VBLANK 9 /* RW-X */
+#define NV_CTRL_SYNC_TO_VBLANK_OFF 0
+#define NV_CTRL_SYNC_TO_VBLANK_ON 1
+
+/*
+ * NV_CTRL_LOG_ANISO - enables anisotropic filtering for OpenGL
+ * clients; on some NVIDIA hardware, this can only be enabled or
+ * disabled; on other hardware different levels of anisotropic
+ * filtering can be specified. This setting is only applied to OpenGL
+ * clients that are started after this setting is applied.
+ */
+
+#define NV_CTRL_LOG_ANISO 10 /* RW-X */
+
+/*
+ * NV_CTRL_FSAA_MODE - the FSAA setting for OpenGL clients; possible
+ * FSAA modes:
+ *
+ * NV_CTRL_FSAA_MODE_2x "2x Bilinear Multisampling"
+ * NV_CTRL_FSAA_MODE_2x_5t "2x Quincunx Multisampling"
+ * NV_CTRL_FSAA_MODE_15x15 "1.5 x 1.5 Supersampling"
+ * NV_CTRL_FSAA_MODE_2x2 "2 x 2 Supersampling"
+ * NV_CTRL_FSAA_MODE_4x "4x Bilinear Multisampling"
+ * NV_CTRL_FSAA_MODE_4x_9t "4x Gaussian Multisampling"
+ * NV_CTRL_FSAA_MODE_8x "2x Bilinear Multisampling by 4x Supersampling"
+ * NV_CTRL_FSAA_MODE_16x "4x Bilinear Multisampling by 4x Supersampling"
+ * NV_CTRL_FSAA_MODE_8xS "4x Multisampling by 2x Supersampling"
+ *
+ * This setting is only applied to OpenGL clients that are started
+ * after this setting is applied.
+ */
+
+#define NV_CTRL_FSAA_MODE 11 /* RW-X */
+#define NV_CTRL_FSAA_MODE_NONE 0
+#define NV_CTRL_FSAA_MODE_2x 1
+#define NV_CTRL_FSAA_MODE_2x_5t 2
+#define NV_CTRL_FSAA_MODE_15x15 3
+#define NV_CTRL_FSAA_MODE_2x2 4
+#define NV_CTRL_FSAA_MODE_4x 5
+#define NV_CTRL_FSAA_MODE_4x_9t 6
+#define NV_CTRL_FSAA_MODE_8x 7
+#define NV_CTRL_FSAA_MODE_16x 8
+#define NV_CTRL_FSAA_MODE_8xS 9
+#define NV_CTRL_FSAA_MODE_8xQ 10
+#define NV_CTRL_FSAA_MODE_16xS 11
+#define NV_CTRL_FSAA_MODE_16xQ 12
+#define NV_CTRL_FSAA_MODE_32xS 13
+#define NV_CTRL_FSAA_MODE_32x 14
+#define NV_CTRL_FSAA_MODE_64xS 15
+#define NV_CTRL_FSAA_MODE_MAX NV_CTRL_FSAA_MODE_64xS
+
+/*
+ * NV_CTRL_TEXTURE_SHARPEN - enables texture sharpening for OpenGL
+ * clients. This setting is only applied to OpenGL clients that are
+ * started after this setting is applied.
+ */
+
+#define NV_CTRL_TEXTURE_SHARPEN 12 /* RW-X */
+#define NV_CTRL_TEXTURE_SHARPEN_OFF 0
+#define NV_CTRL_TEXTURE_SHARPEN_ON 1
+
+/*
+ * NV_CTRL_UBB - returns whether UBB is enabled for the specified X
+ * screen.
+ */
+
+#define NV_CTRL_UBB 13 /* R-- */
+#define NV_CTRL_UBB_OFF 0
+#define NV_CTRL_UBB_ON 1
+
+/*
+ * NV_CTRL_OVERLAY - returns whether the RGB overlay is enabled for
+ * the specified X screen.
+ */
+
+#define NV_CTRL_OVERLAY 14 /* R-- */
+#define NV_CTRL_OVERLAY_OFF 0
+#define NV_CTRL_OVERLAY_ON 1
+
+/*
+ * NV_CTRL_STEREO - returns whether stereo (and what type) is enabled
+ * for the specified X screen.
+ */
+
+#define NV_CTRL_STEREO 16 /* R-- */
+#define NV_CTRL_STEREO_OFF 0
+#define NV_CTRL_STEREO_DDC 1
+#define NV_CTRL_STEREO_BLUELINE 2
+#define NV_CTRL_STEREO_DIN 3
+#define NV_CTRL_STEREO_PASSIVE_EYE_PER_DPY 4
+#define NV_CTRL_STEREO_VERTICAL_INTERLACED 5
+#define NV_CTRL_STEREO_COLOR_INTERLACED 6
+#define NV_CTRL_STEREO_HORIZONTAL_INTERLACED 7
+#define NV_CTRL_STEREO_CHECKERBOARD_PATTERN 8
+#define NV_CTRL_STEREO_INVERSE_CHECKERBOARD_PATTERN 9
+#define NV_CTRL_STEREO_3D_VISION 10
+#define NV_CTRL_STEREO_3D_VISION_PRO 11
+
+/*
+ * NV_CTRL_EMULATE - controls OpenGL software emulation of future
+ * NVIDIA GPUs.
+ */
+
+#define NV_CTRL_EMULATE 17 /* RW- */
+#define NV_CTRL_EMULATE_NONE 0
+
+/*
+ * NV_CTRL_TWINVIEW - returns whether TwinView is enabled for the
+ * specified X screen.
+ */
+
+#define NV_CTRL_TWINVIEW 18 /* R-- */
+#define NV_CTRL_TWINVIEW_NOT_ENABLED 0
+#define NV_CTRL_TWINVIEW_ENABLED 1
+
+/*
+ * NV_CTRL_CONNECTED_DISPLAYS - returns a display mask indicating the last
+ * cached state of the display devices connected to the GPU or GPU driving
+ * the specified X screen.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_CONNECTED_DISPLAYS 19 /* R--G */
+
+/*
+ * NV_CTRL_ENABLED_DISPLAYS - returns a display mask indicating what
+ * display devices are enabled for use on the specified X screen or
+ * GPU.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_ENABLED_DISPLAYS 20 /* R--G */
+
+/**************************************************************************/
+/*
+ * Integer attributes specific to configuring Frame Lock on boards that
+ * support it.
+ */
+
+/*
+ * NV_CTRL_FRAMELOCK - returns whether the underlying GPU supports
+ * Frame Lock. All of the other frame lock attributes are only
+ * applicable if NV_CTRL_FRAMELOCK is _SUPPORTED.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_FRAMELOCK 21 /* R--G */
+#define NV_CTRL_FRAMELOCK_NOT_SUPPORTED 0
+#define NV_CTRL_FRAMELOCK_SUPPORTED 1
+
+/*
+ * NV_CTRL_FRAMELOCK_MASTER - get/set which display device to use
+ * as the frame lock master for the entire sync group. Note that only
+ * one node in the sync group should be configured as the master.
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU target. This attribute cannot be
+ * queried using a NV_CTRL_TARGET_TYPE_X_SCREEN.
+ */
+
+#define NV_CTRL_FRAMELOCK_MASTER 22 /* RW-G */
+
+/* These are deprecated. NV_CTRL_FRAMELOCK_MASTER now takes and
+ returns a display mask as value. */
+#define NV_CTRL_FRAMELOCK_MASTER_FALSE 0
+#define NV_CTRL_FRAMELOCK_MASTER_TRUE 1
+
+/*
+ * NV_CTRL_FRAMELOCK_POLARITY - sync either to the rising edge of the
+ * frame lock pulse, the falling edge of the frame lock pulse or both.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ */
+
+#define NV_CTRL_FRAMELOCK_POLARITY 23 /* RW-F */
+#define NV_CTRL_FRAMELOCK_POLARITY_RISING_EDGE 0x1
+#define NV_CTRL_FRAMELOCK_POLARITY_FALLING_EDGE 0x2
+#define NV_CTRL_FRAMELOCK_POLARITY_BOTH_EDGES 0x3
+
+/*
+ * NV_CTRL_FRAMELOCK_SYNC_DELAY - delay between the frame lock pulse
+ * and the GPU sync. This value must be multiplied by
+ * NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION to determine the sync delay in
+ * nanoseconds.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ *
+ * USAGE NODE: NV_CTRL_FRAMELOCK_SYNC_DELAY_MAX and
+ * NV_CTRL_FRAMELOCK_SYNC_DELAY_FACTOR are deprecated.
+ * The Sync Delay _MAX and _FACTOR are different for different
+ * GSync products and so, to be correct, the valid values for
+ * NV_CTRL_FRAMELOCK_SYNC_DELAY must be queried to get the range
+ * of acceptable sync delay values, and
+ * NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION must be queried to
+ * obtain the correct factor.
+ */
+
+#define NV_CTRL_FRAMELOCK_SYNC_DELAY 24 /* RW-F */
+#define NV_CTRL_FRAMELOCK_SYNC_DELAY_MAX 2047 // deprecated
+#define NV_CTRL_FRAMELOCK_SYNC_DELAY_FACTOR 7.81 // deprecated
+
+/*
+ * NV_CTRL_FRAMELOCK_SYNC_INTERVAL - how many house sync pulses
+ * between the frame lock sync generation (0 == sync every house sync);
+ * this only applies to the master when receiving house sync.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ */
+
+#define NV_CTRL_FRAMELOCK_SYNC_INTERVAL 25 /* RW-F */
+
+/*
+ * NV_CTRL_FRAMELOCK_PORT0_STATUS - status of the rj45 port0.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ */
+
+#define NV_CTRL_FRAMELOCK_PORT0_STATUS 26 /* R--F */
+#define NV_CTRL_FRAMELOCK_PORT0_STATUS_INPUT 0
+#define NV_CTRL_FRAMELOCK_PORT0_STATUS_OUTPUT 1
+
+/*
+ * NV_CTRL_FRAMELOCK_PORT1_STATUS - status of the rj45 port1.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ */
+
+#define NV_CTRL_FRAMELOCK_PORT1_STATUS 27 /* R--F */
+#define NV_CTRL_FRAMELOCK_PORT1_STATUS_INPUT 0
+#define NV_CTRL_FRAMELOCK_PORT1_STATUS_OUTPUT 1
+
+/*
+ * NV_CTRL_FRAMELOCK_HOUSE_STATUS - returns whether or not the house
+ * sync signal was detected on the BNC connector of the frame lock
+ * board.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ */
+
+#define NV_CTRL_FRAMELOCK_HOUSE_STATUS 28 /* R--F */
+#define NV_CTRL_FRAMELOCK_HOUSE_STATUS_NOT_DETECTED 0
+#define NV_CTRL_FRAMELOCK_HOUSE_STATUS_DETECTED 1
+
+/*
+ * NV_CTRL_FRAMELOCK_SYNC - enable/disable the syncing of display
+ * devices to the frame lock pulse as specified by previous calls to
+ * NV_CTRL_FRAMELOCK_MASTER and NV_CTRL_FRAMELOCK_SLAVES.
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU target. This attribute cannot be
+ * queried using a NV_CTRL_TARGET_TYPE_X_SCREEN.
+ */
+
+#define NV_CTRL_FRAMELOCK_SYNC 29 /* RW-G */
+#define NV_CTRL_FRAMELOCK_SYNC_DISABLE 0
+#define NV_CTRL_FRAMELOCK_SYNC_ENABLE 1
+
+/*
+ * NV_CTRL_FRAMELOCK_SYNC_READY - reports whether a frame lock
+ * board is receiving sync (regardless of whether or not any display
+ * devices are using the sync).
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ */
+
+#define NV_CTRL_FRAMELOCK_SYNC_READY 30 /* R--F */
+#define NV_CTRL_FRAMELOCK_SYNC_READY_FALSE 0
+#define NV_CTRL_FRAMELOCK_SYNC_READY_TRUE 1
+
+/*
+ * NV_CTRL_FRAMELOCK_STEREO_SYNC - this indicates that the GPU stereo
+ * signal is in sync with the frame lock stereo signal.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ */
+
+#define NV_CTRL_FRAMELOCK_STEREO_SYNC 31 /* R--G */
+#define NV_CTRL_FRAMELOCK_STEREO_SYNC_FALSE 0
+#define NV_CTRL_FRAMELOCK_STEREO_SYNC_TRUE 1
+
+/*
+ * NV_CTRL_FRAMELOCK_TEST_SIGNAL - to test the connections in the sync
+ * group, tell the master to enable a test signal, then query port[01]
+ * status and sync_ready on all slaves. When done, tell the master to
+ * disable the test signal. Test signal should only be manipulated
+ * while NV_CTRL_FRAMELOCK_SYNC is enabled.
+ *
+ * The TEST_SIGNAL is also used to reset the Universal Frame Count (as
+ * returned by the glXQueryFrameCountNV() function in the
+ * GLX_NV_swap_group extension). Note: for best accuracy of the
+ * Universal Frame Count, it is recommended to toggle the TEST_SIGNAL
+ * on and off after enabling frame lock.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_FRAMELOCK_TEST_SIGNAL 32 /* RW-G */
+#define NV_CTRL_FRAMELOCK_TEST_SIGNAL_DISABLE 0
+#define NV_CTRL_FRAMELOCK_TEST_SIGNAL_ENABLE 1
+
+/*
+ * NV_CTRL_FRAMELOCK_ETHERNET_DETECTED - The frame lock boards are
+ * cabled together using regular cat5 cable, connecting to rj45 ports
+ * on the backplane of the card. There is some concern that users may
+ * think these are ethernet ports and connect them to a
+ * router/hub/etc. The hardware can detect this and will shut off to
+ * prevent damage (either to itself or to the router).
+ * NV_CTRL_FRAMELOCK_ETHERNET_DETECTED may be called to find out if
+ * ethernet is connected to one of the rj45 ports. An appropriate
+ * error message should then be displayed. The _PORT0 and _PORT1
+ * values may be or'ed together.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ */
+
+#define NV_CTRL_FRAMELOCK_ETHERNET_DETECTED 33 /* R--F */
+#define NV_CTRL_FRAMELOCK_ETHERNET_DETECTED_NONE 0
+#define NV_CTRL_FRAMELOCK_ETHERNET_DETECTED_PORT0 0x1
+#define NV_CTRL_FRAMELOCK_ETHERNET_DETECTED_PORT1 0x2
+
+/*
+ * NV_CTRL_FRAMELOCK_VIDEO_MODE - get/set what video mode is used
+ * to interperate the house sync signal. This should only be set
+ * on the master.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ */
+
+#define NV_CTRL_FRAMELOCK_VIDEO_MODE 34 /* RW-F */
+#define NV_CTRL_FRAMELOCK_VIDEO_MODE_NONE 0
+#define NV_CTRL_FRAMELOCK_VIDEO_MODE_TTL 1
+#define NV_CTRL_FRAMELOCK_VIDEO_MODE_NTSCPALSECAM 2
+#define NV_CTRL_FRAMELOCK_VIDEO_MODE_HDTV 3
+
+/*
+ * During FRAMELOCK bring-up, the above values were redefined to
+ * these:
+ */
+
+#define NV_CTRL_FRAMELOCK_VIDEO_MODE_COMPOSITE_AUTO 0
+#define NV_CTRL_FRAMELOCK_VIDEO_MODE_TTL 1
+#define NV_CTRL_FRAMELOCK_VIDEO_MODE_COMPOSITE_BI_LEVEL 2
+#define NV_CTRL_FRAMELOCK_VIDEO_MODE_COMPOSITE_TRI_LEVEL 3
+
+/*
+ * NV_CTRL_FRAMELOCK_SYNC_RATE - this is the refresh rate that the
+ * frame lock board is sending to the GPU, in milliHz.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ */
+
+#define NV_CTRL_FRAMELOCK_SYNC_RATE 35 /* R--F */
+
+/**************************************************************************/
+
+/*
+ * NV_CTRL_FORCE_GENERIC_CPU - inhibit the use of CPU specific
+ * features such as MMX, SSE, or 3DNOW! for OpenGL clients; this
+ * option may result in performance loss, but may be useful in
+ * conjunction with software such as the Valgrind memory debugger.
+ * This setting is only applied to OpenGL clients that are started
+ * after this setting is applied.
+ *
+ * USAGE NOTE: This attribute is deprecated. CPU compatibility is now
+ * checked each time during initialization.
+ */
+
+#define NV_CTRL_FORCE_GENERIC_CPU 37 /* RW-X */
+#define NV_CTRL_FORCE_GENERIC_CPU_DISABLE 0
+#define NV_CTRL_FORCE_GENERIC_CPU_ENABLE 1
+
+/*
+ * NV_CTRL_OPENGL_AA_LINE_GAMMA - for OpenGL clients, allow
+ * Gamma-corrected antialiased lines to consider variances in the
+ * color display capabilities of output devices when rendering smooth
+ * lines. Only available on recent Quadro GPUs. This setting is only
+ * applied to OpenGL clients that are started after this setting is
+ * applied.
+ */
+
+#define NV_CTRL_OPENGL_AA_LINE_GAMMA 38 /* RW-X */
+#define NV_CTRL_OPENGL_AA_LINE_GAMMA_DISABLE 0
+#define NV_CTRL_OPENGL_AA_LINE_GAMMA_ENABLE 1
+
+/*
+ * NV_CTRL_FRAMELOCK_TIMING - this is TRUE when the gpu is both receiving
+ * and locked to an input timing signal. Timing information may come from
+ * the following places: Another frame lock device that is set to master,
+ * the house sync signal, or the GPU's internal timing from a display
+ * device.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_FRAMELOCK_TIMING 39 /* R--G */
+#define NV_CTRL_FRAMELOCK_TIMING_FALSE 0
+#define NV_CTRL_FRAMELOCK_TIMING_TRUE 1
+
+/*
+ * NV_CTRL_FLIPPING_ALLOWED - when TRUE, OpenGL will swap by flipping
+ * when possible; when FALSE, OpenGL will alway swap by blitting.
+ */
+
+#define NV_CTRL_FLIPPING_ALLOWED 40 /* RW-X */
+#define NV_CTRL_FLIPPING_ALLOWED_FALSE 0
+#define NV_CTRL_FLIPPING_ALLOWED_TRUE 1
+
+/*
+ * NV_CTRL_ARCHITECTURE - returns the architecture on which the X server is
+ * running.
+ */
+
+#define NV_CTRL_ARCHITECTURE 41 /* R-- */
+#define NV_CTRL_ARCHITECTURE_X86 0
+#define NV_CTRL_ARCHITECTURE_X86_64 1
+#define NV_CTRL_ARCHITECTURE_IA64 2
+
+/*
+ * NV_CTRL_TEXTURE_CLAMPING - texture clamping mode in OpenGL. By
+ * default, _SPEC is used, which forces OpenGL texture clamping to
+ * conform with the OpenGL specification. _EDGE forces NVIDIA's
+ * OpenGL implementation to remap GL_CLAMP to GL_CLAMP_TO_EDGE,
+ * which is not strictly conformant, but some applications rely on
+ * the non-conformant behavior.
+ */
+
+#define NV_CTRL_TEXTURE_CLAMPING 42 /* RW-X */
+#define NV_CTRL_TEXTURE_CLAMPING_EDGE 0
+#define NV_CTRL_TEXTURE_CLAMPING_SPEC 1
+
+#define NV_CTRL_CURSOR_SHADOW 43 /* RW- */
+#define NV_CTRL_CURSOR_SHADOW_DISABLE 0
+#define NV_CTRL_CURSOR_SHADOW_ENABLE 1
+
+#define NV_CTRL_CURSOR_SHADOW_ALPHA 44 /* RW- */
+#define NV_CTRL_CURSOR_SHADOW_RED 45 /* RW- */
+#define NV_CTRL_CURSOR_SHADOW_GREEN 46 /* RW- */
+#define NV_CTRL_CURSOR_SHADOW_BLUE 47 /* RW- */
+
+#define NV_CTRL_CURSOR_SHADOW_X_OFFSET 48 /* RW- */
+#define NV_CTRL_CURSOR_SHADOW_Y_OFFSET 49 /* RW- */
+
+/*
+ * When Application Control for FSAA is enabled, then what the
+ * application requests is used, and NV_CTRL_FSAA_MODE is ignored. If
+ * this is disabled, then any application setting is overridden with
+ * NV_CTRL_FSAA_MODE
+ */
+
+#define NV_CTRL_FSAA_APPLICATION_CONTROLLED 50 /* RW-X */
+#define NV_CTRL_FSAA_APPLICATION_CONTROLLED_ENABLED 1
+#define NV_CTRL_FSAA_APPLICATION_CONTROLLED_DISABLED 0
+
+/*
+ * When Application Control for LogAniso is enabled, then what the
+ * application requests is used, and NV_CTRL_LOG_ANISO is ignored. If
+ * this is disabled, then any application setting is overridden with
+ * NV_CTRL_LOG_ANISO
+ */
+
+#define NV_CTRL_LOG_ANISO_APPLICATION_CONTROLLED 51 /* RW-X */
+#define NV_CTRL_LOG_ANISO_APPLICATION_CONTROLLED_ENABLED 1
+#define NV_CTRL_LOG_ANISO_APPLICATION_CONTROLLED_DISABLED 0
+
+/*
+ * IMAGE_SHARPENING adjusts the sharpness of the display's image
+ * quality by amplifying high frequency content. Valid values will
+ * normally be in the range [0,32). Only available on GeForceFX or
+ * newer.
+ */
+
+#define NV_CTRL_IMAGE_SHARPENING 52 /* RWDG */
+
+/*
+ * NV_CTRL_TV_OVERSCAN adjusts the amount of overscan on the specified
+ * display device.
+ */
+
+#define NV_CTRL_TV_OVERSCAN 53 /* RWDG */
+
+/*
+ * NV_CTRL_TV_FLICKER_FILTER adjusts the amount of flicker filter on
+ * the specified display device.
+ */
+
+#define NV_CTRL_TV_FLICKER_FILTER 54 /* RWDG */
+
+/*
+ * NV_CTRL_TV_BRIGHTNESS adjusts the amount of brightness on the
+ * specified display device.
+ */
+
+#define NV_CTRL_TV_BRIGHTNESS 55 /* RWDG */
+
+/*
+ * NV_CTRL_TV_HUE adjusts the amount of hue on the specified display
+ * device.
+ */
+
+#define NV_CTRL_TV_HUE 56 /* RWDG */
+
+/*
+ * NV_CTRL_TV_CONTRAST adjusts the amount of contrast on the specified
+ * display device.
+ */
+
+#define NV_CTRL_TV_CONTRAST 57 /* RWDG */
+
+/*
+ * NV_CTRL_TV_SATURATION adjusts the amount of saturation on the
+ * specified display device.
+ */
+
+#define NV_CTRL_TV_SATURATION 58 /* RWDG */
+
+/*
+ * NV_CTRL_TV_RESET_SETTINGS - this write-only attribute can be used
+ * to request that all TV Settings be reset to their default values;
+ * typical usage would be that this attribute be sent, and then all
+ * the TV attributes be queried to retrieve their new values.
+ */
+
+#define NV_CTRL_TV_RESET_SETTINGS 59 /* -WDG */
+
+/*
+ * NV_CTRL_GPU_CORE_TEMPERATURE reports the current core temperature
+ * of the GPU driving the X screen.
+ */
+
+#define NV_CTRL_GPU_CORE_TEMPERATURE 60 /* R--G */
+
+/*
+ * NV_CTRL_GPU_CORE_THRESHOLD reports the current GPU core slowdown
+ * threshold temperature, NV_CTRL_GPU_DEFAULT_CORE_THRESHOLD and
+ * NV_CTRL_GPU_MAX_CORE_THRESHOLD report the default and MAX core
+ * slowdown threshold temperatures.
+ *
+ * NV_CTRL_GPU_CORE_THRESHOLD reflects the temperature at which the
+ * GPU is throttled to prevent overheating.
+ */
+
+#define NV_CTRL_GPU_CORE_THRESHOLD 61 /* R--G */
+#define NV_CTRL_GPU_DEFAULT_CORE_THRESHOLD 62 /* R--G */
+#define NV_CTRL_GPU_MAX_CORE_THRESHOLD 63 /* R--G */
+
+/*
+ * NV_CTRL_AMBIENT_TEMPERATURE reports the current temperature in the
+ * immediate neighbourhood of the GPU driving the X screen.
+ */
+
+#define NV_CTRL_AMBIENT_TEMPERATURE 64 /* R--G */
+
+/*
+ * NV_CTRL_PBUFFER_SCANOUT_SUPPORTED - returns whether this X screen
+ * supports scanout of FP pbuffers;
+ *
+ * if this screen does not support PBUFFER_SCANOUT, then all other
+ * PBUFFER_SCANOUT attributes are unavailable.
+ *
+ * PBUFFER_SCANOUT is supported if and only if:
+ * - Twinview is configured with clone mode. The secondary screen is used to
+ * scanout the pbuffer.
+ * - The desktop is running in with 16 bits per pixel.
+ */
+#define NV_CTRL_PBUFFER_SCANOUT_SUPPORTED 65 /* R-- */
+#define NV_CTRL_PBUFFER_SCANOUT_FALSE 0
+#define NV_CTRL_PBUFFER_SCANOUT_TRUE 1
+
+/*
+ * NV_CTRL_PBUFFER_SCANOUT_XID indicates the XID of the pbuffer used for
+ * scanout.
+ */
+#define NV_CTRL_PBUFFER_SCANOUT_XID 66 /* RW- */
+
+/**************************************************************************/
+/*
+ * The NV_CTRL_GVO_* integer attributes are used to configure GVO
+ * (Graphics to Video Out). This functionality is available, for
+ * example, on the Quadro FX 4000 SDI graphics board.
+ *
+ * The following is a typical usage pattern for the GVO attributes:
+ *
+ * - query NV_CTRL_GVO_SUPPORTED to determine if the X screen supports GV0.
+ *
+ * - specify NV_CTRL_GVO_SYNC_MODE (one of FREE_RUNNING, GENLOCK, or
+ * FRAMELOCK); if you specify GENLOCK or FRAMELOCK, you should also
+ * specify NV_CTRL_GVO_SYNC_SOURCE.
+ *
+ * - Use NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECTED and
+ * NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED to detect what input syncs are
+ * present.
+ *
+ * (If no analog sync is detected but it is known that a valid
+ * bi-level or tri-level sync is connected set
+ * NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECT_MODE appropriately and
+ * retest with NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECTED).
+ *
+ * - if syncing to input sync, query the
+ * NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT attribute; note that Input video
+ * format can only be queried after SYNC_SOURCE is specified.
+ *
+ * - specify the NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT
+ *
+ * - specify the NV_CTRL_GVO_DATA_FORMAT
+ *
+ * - specify any custom Color Space Conversion (CSC) matrix, offset,
+ * and scale with XNVCTRLSetGvoColorConversion().
+ *
+ * - if using the GLX_NV_video_out extension to display one or more
+ * pbuffers, call glXGetVideoDeviceNV() to lock the GVO output for use
+ * by the GLX client; then bind the pbuffer(s) to the GVO output with
+ * glXBindVideoImageNV() and send pbuffers to the GVO output with
+ * glXSendPbufferToVideoNV(); see the GLX_NV_video_out spec for more
+ * details.
+ *
+ * - if using the GLX_NV_present_video extension, call
+ * glXBindVideoDeviceNV() to bind the GVO video device to current
+ * OpenGL context.
+ *
+ * Note that setting most GVO attributes only causes the value to be
+ * cached in the X server. The values will be flushed to the hardware
+ * either when the next MetaMode is set that uses the GVO display
+ * device, or when a GLX pbuffer is bound to the GVO output (with
+ * glXBindVideoImageNV()).
+ *
+ * Note that GLX_NV_video_out/GLX_NV_present_video and X screen use
+ * are mutually exclusive. If a MetaMode is currently using the GVO
+ * device, then glXGetVideoDeviceNV and glXBindVideoImageNV() will
+ * fail. Similarly, if a GLX client has locked the GVO output (via
+ * glXGetVideoDeviceNV or glXBindVideoImageNV), then setting a
+ * MetaMode that uses the GVO device will fail. The
+ * NV_CTRL_GVO_GLX_LOCKED event will be sent when a GLX client locks
+ * the GVO output.
+ *
+ */
+
+/*
+ * NV_CTRL_GVO_SUPPORTED - returns whether this X screen supports GVO;
+ * if this screen does not support GVO output, then all other GVO
+ * attributes are unavailable.
+ */
+
+#define NV_CTRL_GVO_SUPPORTED 67 /* R-- */
+#define NV_CTRL_GVO_SUPPORTED_FALSE 0
+#define NV_CTRL_GVO_SUPPORTED_TRUE 1
+
+/*
+ * NV_CTRL_GVO_SYNC_MODE - selects the GVO sync mode; possible values
+ * are:
+ *
+ * FREE_RUNNING - GVO does not sync to any external signal
+ *
+ * GENLOCK - the GVO output is genlocked to an incoming sync signal;
+ * genlocking locks at hsync. This requires that the output video
+ * format exactly match the incoming sync video format.
+ *
+ * FRAMELOCK - the GVO output is frame locked to an incoming sync
+ * signal; frame locking locks at vsync. This requires that the output
+ * video format have the same refresh rate as the incoming sync video
+ * format.
+ */
+
+#define NV_CTRL_GVO_SYNC_MODE 68 /* RW- */
+#define NV_CTRL_GVO_SYNC_MODE_FREE_RUNNING 0
+#define NV_CTRL_GVO_SYNC_MODE_GENLOCK 1
+#define NV_CTRL_GVO_SYNC_MODE_FRAMELOCK 2
+
+/*
+ * NV_CTRL_GVO_SYNC_SOURCE - if NV_CTRL_GVO_SYNC_MODE is set to either
+ * GENLOCK or FRAMELOCK, this controls which sync source is used as
+ * the incoming sync signal (either Composite or SDI). If
+ * NV_CTRL_GVO_SYNC_MODE is FREE_RUNNING, this attribute has no
+ * effect.
+ */
+
+#define NV_CTRL_GVO_SYNC_SOURCE 69 /* RW- */
+#define NV_CTRL_GVO_SYNC_SOURCE_COMPOSITE 0
+#define NV_CTRL_GVO_SYNC_SOURCE_SDI 1
+
+/*
+ * NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT - specifies the desired output video
+ * format for GVO devices or the desired input video format for GVI devices.
+ *
+ * Note that for GVO, the valid video formats may vary depending on
+ * the NV_CTRL_GVO_SYNC_MODE and the incoming sync video format. See
+ * the definition of NV_CTRL_GVO_SYNC_MODE.
+ *
+ * Note that when querying the ValidValues for this data type, the
+ * values are reported as bits within a bitmask
+ * (ATTRIBUTE_TYPE_INT_BITS); unfortunately, there are more valid
+ * value bits than will fit in a single 32-bit value. To solve this,
+ * query the ValidValues for NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT to
+ * check which of the first 31 VIDEO_FORMATS are valid, query the
+ * ValidValues for NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT2 to check which
+ * of the 32-63 VIDEO_FORMATS are valid, and query the ValidValues of
+ * NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT3 to check which of the 64-95
+ * VIDEO_FORMATS are valid.
+ *
+ * Note: Setting this attribute on a GVI device may also result in the
+ * following NV-CONTROL attributes being reset on that device (to
+ * ensure the configuration remains valid):
+ * NV_CTRL_GVI_REQUESTED_STREAM_BITS_PER_COMPONENT
+ * NV_CTRL_GVI_REQUESTED_STREAM_COMPONENT_SAMPLING
+ */
+
+#define NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT 70 /* RW--I */
+
+#define NV_CTRL_GVIO_VIDEO_FORMAT_NONE 0
+#define NV_CTRL_GVIO_VIDEO_FORMAT_487I_59_94_SMPTE259_NTSC 1
+#define NV_CTRL_GVIO_VIDEO_FORMAT_576I_50_00_SMPTE259_PAL 2
+#define NV_CTRL_GVIO_VIDEO_FORMAT_720P_59_94_SMPTE296 3
+#define NV_CTRL_GVIO_VIDEO_FORMAT_720P_60_00_SMPTE296 4
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1035I_59_94_SMPTE260 5
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1035I_60_00_SMPTE260 6
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_50_00_SMPTE295 7
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_50_00_SMPTE274 8
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_59_94_SMPTE274 9
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_60_00_SMPTE274 10
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_23_976_SMPTE274 11
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_24_00_SMPTE274 12
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_25_00_SMPTE274 13
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_29_97_SMPTE274 14
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_30_00_SMPTE274 15
+#define NV_CTRL_GVIO_VIDEO_FORMAT_720P_50_00_SMPTE296 16
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_48_00_SMPTE274 17
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_47_96_SMPTE274 18
+#define NV_CTRL_GVIO_VIDEO_FORMAT_720P_30_00_SMPTE296 19
+#define NV_CTRL_GVIO_VIDEO_FORMAT_720P_29_97_SMPTE296 20
+#define NV_CTRL_GVIO_VIDEO_FORMAT_720P_25_00_SMPTE296 21
+#define NV_CTRL_GVIO_VIDEO_FORMAT_720P_24_00_SMPTE296 22
+#define NV_CTRL_GVIO_VIDEO_FORMAT_720P_23_98_SMPTE296 23
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_25_00_SMPTE274 24
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_29_97_SMPTE274 25
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_30_00_SMPTE274 26
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_24_00_SMPTE274 27
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080PSF_23_98_SMPTE274 28
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_30_00_SMPTE372 29
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_29_97_SMPTE372 30
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_60_00_SMPTE372 31
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_59_94_SMPTE372 32
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_25_00_SMPTE372 33
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_50_00_SMPTE372 34
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_24_00_SMPTE372 35
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_23_98_SMPTE372 36
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_48_00_SMPTE372 37
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_47_96_SMPTE372 38
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_50_00_3G_LEVEL_A_SMPTE274 39
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_59_94_3G_LEVEL_A_SMPTE274 40
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_60_00_3G_LEVEL_A_SMPTE274 41
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_60_00_3G_LEVEL_B_SMPTE274 42
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_60_00_3G_LEVEL_B_SMPTE274 43
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_60_00_3G_LEVEL_B_SMPTE372 44
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_50_00_3G_LEVEL_B_SMPTE274 45
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_50_00_3G_LEVEL_B_SMPTE274 46
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_50_00_3G_LEVEL_B_SMPTE372 47
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_30_00_3G_LEVEL_B_SMPTE274 48
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_30_00_3G_LEVEL_B_SMPTE372 49
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_25_00_3G_LEVEL_B_SMPTE274 50
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_25_00_3G_LEVEL_B_SMPTE372 51
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_24_00_3G_LEVEL_B_SMPTE274 52
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_24_00_3G_LEVEL_B_SMPTE372 53
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_48_00_3G_LEVEL_B_SMPTE274 54
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_48_00_3G_LEVEL_B_SMPTE372 55
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_59_94_3G_LEVEL_B_SMPTE274 56
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_59_94_3G_LEVEL_B_SMPTE274 57
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_59_94_3G_LEVEL_B_SMPTE372 58
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_29_97_3G_LEVEL_B_SMPTE274 59
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_29_97_3G_LEVEL_B_SMPTE372 60
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080P_23_98_3G_LEVEL_B_SMPTE274 61
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048P_23_98_3G_LEVEL_B_SMPTE372 62
+#define NV_CTRL_GVIO_VIDEO_FORMAT_1080I_47_96_3G_LEVEL_B_SMPTE274 63
+#define NV_CTRL_GVIO_VIDEO_FORMAT_2048I_47_96_3G_LEVEL_B_SMPTE372 64
+
+/*
+ * The following are deprecated; NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT and the
+ * corresponding NV_CTRL_GVIO_* formats should be used instead.
+ */
+#define NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT 70 /* RW- */
+
+#define NV_CTRL_GVO_VIDEO_FORMAT_NONE 0
+#define NV_CTRL_GVO_VIDEO_FORMAT_487I_59_94_SMPTE259_NTSC 1
+#define NV_CTRL_GVO_VIDEO_FORMAT_576I_50_00_SMPTE259_PAL 2
+#define NV_CTRL_GVO_VIDEO_FORMAT_720P_59_94_SMPTE296 3
+#define NV_CTRL_GVO_VIDEO_FORMAT_720P_60_00_SMPTE296 4
+#define NV_CTRL_GVO_VIDEO_FORMAT_1035I_59_94_SMPTE260 5
+#define NV_CTRL_GVO_VIDEO_FORMAT_1035I_60_00_SMPTE260 6
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080I_50_00_SMPTE295 7
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080I_50_00_SMPTE274 8
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080I_59_94_SMPTE274 9
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080I_60_00_SMPTE274 10
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080P_23_976_SMPTE274 11
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080P_24_00_SMPTE274 12
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080P_25_00_SMPTE274 13
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080P_29_97_SMPTE274 14
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080P_30_00_SMPTE274 15
+#define NV_CTRL_GVO_VIDEO_FORMAT_720P_50_00_SMPTE296 16
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080I_48_00_SMPTE274 17
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080I_47_96_SMPTE274 18
+#define NV_CTRL_GVO_VIDEO_FORMAT_720P_30_00_SMPTE296 19
+#define NV_CTRL_GVO_VIDEO_FORMAT_720P_29_97_SMPTE296 20
+#define NV_CTRL_GVO_VIDEO_FORMAT_720P_25_00_SMPTE296 21
+#define NV_CTRL_GVO_VIDEO_FORMAT_720P_24_00_SMPTE296 22
+#define NV_CTRL_GVO_VIDEO_FORMAT_720P_23_98_SMPTE296 23
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_25_00_SMPTE274 24
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_29_97_SMPTE274 25
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_30_00_SMPTE274 26
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_24_00_SMPTE274 27
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_23_98_SMPTE274 28
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048P_30_00_SMPTE372 29
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048P_29_97_SMPTE372 30
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048I_60_00_SMPTE372 31
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048I_59_94_SMPTE372 32
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048P_25_00_SMPTE372 33
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048I_50_00_SMPTE372 34
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048P_24_00_SMPTE372 35
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048P_23_98_SMPTE372 36
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048I_48_00_SMPTE372 37
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048I_47_96_SMPTE372 38
+
+/*
+ * NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT - indicates the input video format
+ * detected for GVO or GVI devices; the possible values are the
+ * NV_CTRL_GVIO_VIDEO_FORMAT constants.
+ *
+ * For GVI devices, the jack number should be specified in the lower
+ * 16 bits of the "display_mask" parameter, while the channel number should be
+ * specified in the upper 16 bits.
+ */
+
+#define NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT 71 /* R--I */
+
+/*
+ * The following is deprecated. Use NV_CTRL_GVIO_DETECTED_VIDEO_FORMAT,
+ * instead.
+ */
+#define NV_CTRL_GVO_INPUT_VIDEO_FORMAT 71 /* R-- */
+
+/*
+ * NV_CTRL_GVO_DATA_FORMAT - This controls how the data in the source
+ * (either the X screen or the GLX pbuffer) is interpretted and
+ * displayed.
+ *
+ * Note: some of the below DATA_FORMATS have been renamed. For
+ * example, R8G8B8_TO_RGB444 has been renamed to X8X8X8_444_PASSTHRU.
+ * This is to more accurately reflect DATA_FORMATS where the
+ * per-channel data could be either RGB or YCrCb -- the point is that
+ * the driver and GVO hardware do not perform any implicit color space
+ * conversion on the data; it is passed through to the SDI out.
+ */
+
+#define NV_CTRL_GVO_DATA_FORMAT 72 /* RW- */
+#define NV_CTRL_GVO_DATA_FORMAT_R8G8B8_TO_YCRCB444 0
+#define NV_CTRL_GVO_DATA_FORMAT_R8G8B8A8_TO_YCRCBA4444 1
+#define NV_CTRL_GVO_DATA_FORMAT_R8G8B8Z10_TO_YCRCBZ4444 2
+#define NV_CTRL_GVO_DATA_FORMAT_R8G8B8_TO_YCRCB422 3
+#define NV_CTRL_GVO_DATA_FORMAT_R8G8B8A8_TO_YCRCBA4224 4
+#define NV_CTRL_GVO_DATA_FORMAT_R8G8B8Z10_TO_YCRCBZ4224 5
+#define NV_CTRL_GVO_DATA_FORMAT_R8G8B8_TO_RGB444 6 // renamed
+#define NV_CTRL_GVO_DATA_FORMAT_X8X8X8_444_PASSTHRU 6
+#define NV_CTRL_GVO_DATA_FORMAT_R8G8B8A8_TO_RGBA4444 7 // renamed
+#define NV_CTRL_GVO_DATA_FORMAT_X8X8X8A8_4444_PASSTHRU 7
+#define NV_CTRL_GVO_DATA_FORMAT_R8G8B8Z10_TO_RGBZ4444 8 // renamed
+#define NV_CTRL_GVO_DATA_FORMAT_X8X8X8Z8_4444_PASSTHRU 8
+#define NV_CTRL_GVO_DATA_FORMAT_Y10CR10CB10_TO_YCRCB444 9 // renamed
+#define NV_CTRL_GVO_DATA_FORMAT_X10X10X10_444_PASSTHRU 9
+#define NV_CTRL_GVO_DATA_FORMAT_Y10CR8CB8_TO_YCRCB444 10 // renamed
+#define NV_CTRL_GVO_DATA_FORMAT_X10X8X8_444_PASSTHRU 10
+#define NV_CTRL_GVO_DATA_FORMAT_Y10CR8CB8A10_TO_YCRCBA4444 11 // renamed
+#define NV_CTRL_GVO_DATA_FORMAT_X10X8X8A10_4444_PASSTHRU 11
+#define NV_CTRL_GVO_DATA_FORMAT_Y10CR8CB8Z10_TO_YCRCBZ4444 12 // renamed
+#define NV_CTRL_GVO_DATA_FORMAT_X10X8X8Z10_4444_PASSTHRU 12
+#define NV_CTRL_GVO_DATA_FORMAT_DUAL_R8G8B8_TO_DUAL_YCRCB422 13
+#define NV_CTRL_GVO_DATA_FORMAT_DUAL_Y8CR8CB8_TO_DUAL_YCRCB422 14 // renamed
+#define NV_CTRL_GVO_DATA_FORMAT_DUAL_X8X8X8_TO_DUAL_422_PASSTHRU 14
+#define NV_CTRL_GVO_DATA_FORMAT_R10G10B10_TO_YCRCB422 15
+#define NV_CTRL_GVO_DATA_FORMAT_R10G10B10_TO_YCRCB444 16
+#define NV_CTRL_GVO_DATA_FORMAT_Y12CR12CB12_TO_YCRCB444 17 // renamed
+#define NV_CTRL_GVO_DATA_FORMAT_X12X12X12_444_PASSTHRU 17
+#define NV_CTRL_GVO_DATA_FORMAT_R12G12B12_TO_YCRCB444 18
+#define NV_CTRL_GVO_DATA_FORMAT_X8X8X8_422_PASSTHRU 19
+#define NV_CTRL_GVO_DATA_FORMAT_X8X8X8A8_4224_PASSTHRU 20
+#define NV_CTRL_GVO_DATA_FORMAT_X8X8X8Z8_4224_PASSTHRU 21
+#define NV_CTRL_GVO_DATA_FORMAT_X10X10X10_422_PASSTHRU 22
+#define NV_CTRL_GVO_DATA_FORMAT_X10X8X8_422_PASSTHRU 23
+#define NV_CTRL_GVO_DATA_FORMAT_X10X8X8A10_4224_PASSTHRU 24
+#define NV_CTRL_GVO_DATA_FORMAT_X10X8X8Z10_4224_PASSTHRU 25
+#define NV_CTRL_GVO_DATA_FORMAT_X12X12X12_422_PASSTHRU 26
+#define NV_CTRL_GVO_DATA_FORMAT_R12G12B12_TO_YCRCB422 27
+
+/*
+ * NV_CTRL_GVO_DISPLAY_X_SCREEN - no longer supported
+ */
+
+#define NV_CTRL_GVO_DISPLAY_X_SCREEN 73 /* RW- */
+#define NV_CTRL_GVO_DISPLAY_X_SCREEN_ENABLE 1
+#define NV_CTRL_GVO_DISPLAY_X_SCREEN_DISABLE 0
+
+/*
+ * NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECTED - indicates whether
+ * Composite Sync input is detected.
+ */
+
+#define NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECTED 74 /* R-- */
+#define NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECTED_FALSE 0
+#define NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECTED_TRUE 1
+
+/*
+ * NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECT_MODE - get/set the
+ * Composite Sync input detect mode.
+ */
+
+#define NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECT_MODE 75 /* RW- */
+#define NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECT_MODE_AUTO 0
+#define NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECT_MODE_BI_LEVEL 1
+#define NV_CTRL_GVO_COMPOSITE_SYNC_INPUT_DETECT_MODE_TRI_LEVEL 2
+
+/*
+ * NV_CTRL_GVO_SYNC_INPUT_DETECTED - indicates whether SDI Sync input
+ * is detected, and what type.
+ */
+
+#define NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED 76 /* R-- */
+#define NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED_NONE 0
+#define NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED_HD 1
+#define NV_CTRL_GVO_SDI_SYNC_INPUT_DETECTED_SD 2
+
+/*
+ * NV_CTRL_GVO_VIDEO_OUTPUTS - indicates which GVO video output
+ * connectors are currently outputing data.
+ */
+
+#define NV_CTRL_GVO_VIDEO_OUTPUTS 77 /* R-- */
+#define NV_CTRL_GVO_VIDEO_OUTPUTS_NONE 0
+#define NV_CTRL_GVO_VIDEO_OUTPUTS_VIDEO1 1
+#define NV_CTRL_GVO_VIDEO_OUTPUTS_VIDEO2 2
+#define NV_CTRL_GVO_VIDEO_OUTPUTS_VIDEO_BOTH 3
+
+/*
+ * NV_CTRL_GVO_FPGA_VERSION - indicates the version of the Firmware on
+ * the GVO device. Deprecated; use
+ * NV_CTRL_STRING_GVIO_FIRMWARE_VERSION instead.
+ */
+
+#define NV_CTRL_GVO_FIRMWARE_VERSION 78 /* R-- */
+
+/*
+ * NV_CTRL_GVO_SYNC_DELAY_PIXELS - controls the delay between the
+ * input sync and the output sync in numbers of pixels from hsync;
+ * this is a 12 bit value.
+ *
+ * If the NV_CTRL_GVO_CAPABILITIES_ADVANCE_SYNC_SKEW bit is set,
+ * then setting this value will set an advance instead of a delay.
+ */
+
+#define NV_CTRL_GVO_SYNC_DELAY_PIXELS 79 /* RW- */
+
+/*
+ * NV_CTRL_GVO_SYNC_DELAY_LINES - controls the delay between the input
+ * sync and the output sync in numbers of lines from vsync; this is a
+ * 12 bit value.
+ *
+ * If the NV_CTRL_GVO_CAPABILITIES_ADVANCE_SYNC_SKEW bit is set,
+ * then setting this value will set an advance instead of a delay.
+ */
+
+#define NV_CTRL_GVO_SYNC_DELAY_LINES 80 /* RW- */
+
+/*
+ * NV_CTRL_GVO_INPUT_VIDEO_FORMAT_REACQUIRE - must be set for a period
+ * of about 2 seconds for the new InputVideoFormat to be properly
+ * locked to. In nvidia-settings, we do a reacquire whenever genlock
+ * or frame lock mode is entered into, when the user clicks the
+ * "detect" button. This value can be written, but always reads back
+ * _FALSE.
+ */
+
+#define NV_CTRL_GVO_INPUT_VIDEO_FORMAT_REACQUIRE 81 /* -W- */
+#define NV_CTRL_GVO_INPUT_VIDEO_FORMAT_REACQUIRE_FALSE 0
+#define NV_CTRL_GVO_INPUT_VIDEO_FORMAT_REACQUIRE_TRUE 1
+
+/*
+ * NV_CTRL_GVO_GLX_LOCKED - indicates that GVO configurability is
+ * locked by GLX; this occurs when either glXGetVideoDeviceNV (part of
+ * GLX_NV_video_out) or glXBindVideoDeviceNV (part of
+ * GLX_NV_present_video) is called. All GVO output resources are
+ * locked until released by the GLX_NV_video_out/GLX_NV_present_video
+ * client.
+ *
+ * When GVO is locked, setting of the following GVO NV-CONTROL attributes will
+ * not happen immediately and will instead be cached. The GVO resource will
+ * need to be disabled/released and re-enabled/claimed for the values to be
+ * flushed. These attributes are:
+ * NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT
+ * NV_CTRL_GVO_DATA_FORMAT
+ * NV_CTRL_GVO_FLIP_QUEUE_SIZE
+ *
+ * This attribute is deprecated and may be removed in a future release. Its
+ * functionality has been replaced by NV_CTRL_GVO_LOCK_OWNER.
+ */
+
+#define NV_CTRL_GVO_GLX_LOCKED 82 /* R-- */
+#define NV_CTRL_GVO_GLX_LOCKED_FALSE 0
+#define NV_CTRL_GVO_GLX_LOCKED_TRUE 1
+
+/*
+ * NV_CTRL_GVIO_VIDEO_FORMAT_{WIDTH,HEIGHT,REFRESH_RATE} - query the
+ * width, height, and refresh rate for the specified
+ * NV_CTRL_GVIO_VIDEO_FORMAT_*. So that this can be queried with
+ * existing interfaces, XNVCTRLQueryAttribute() should be used, and
+ * the video format specified in the display_mask field; eg:
+ *
+ * XNVCTRLQueryAttribute (dpy,
+ * screen,
+ * NV_CTRL_GVIO_VIDEO_FORMAT_487I_59_94_SMPTE259_NTSC,
+ * NV_CTRL_GVIO_VIDEO_FORMAT_WIDTH,
+ * &value);
+ *
+ * Note that Refresh Rate is in milliHertz values
+ */
+
+#define NV_CTRL_GVIO_VIDEO_FORMAT_WIDTH 83 /* R--I */
+#define NV_CTRL_GVIO_VIDEO_FORMAT_HEIGHT 84 /* R--I */
+#define NV_CTRL_GVIO_VIDEO_FORMAT_REFRESH_RATE 85 /* R--I */
+
+/* The following are deprecated; use the NV_CTRL_GVIO_* versions, instead */
+#define NV_CTRL_GVO_VIDEO_FORMAT_WIDTH 83 /* R-- */
+#define NV_CTRL_GVO_VIDEO_FORMAT_HEIGHT 84 /* R-- */
+#define NV_CTRL_GVO_VIDEO_FORMAT_REFRESH_RATE 85 /* R-- */
+
+/*
+ * NV_CTRL_GVO_X_SCREEN_PAN_[XY] - no longer supported
+ */
+
+#define NV_CTRL_GVO_X_SCREEN_PAN_X 86 /* RW- */
+#define NV_CTRL_GVO_X_SCREEN_PAN_Y 87 /* RW- */
+
+/*
+ * NV_CTRL_GPU_OVERCLOCKING_STATE - query the current or set a new
+ * overclocking state; the value of this attribute controls the
+ * availability of additional overclocking attributes (see below).
+ *
+ * Note: this attribute is unavailable unless overclocking support
+ * has been enabled in the X server (by the user).
+ */
+
+#define NV_CTRL_GPU_OVERCLOCKING_STATE 88 /* RW-G */
+#define NV_CTRL_GPU_OVERCLOCKING_STATE_NONE 0
+#define NV_CTRL_GPU_OVERCLOCKING_STATE_MANUAL 1
+
+/*
+ * NV_CTRL_GPU_{2,3}D_CLOCK_FREQS - query or set the GPU and memory
+ * clocks of the device driving the X screen. New clock frequencies
+ * are tested before being applied, and may be rejected.
+ *
+ * Note: if the target clocks are too aggressive, their testing may
+ * render the system unresponsive.
+ *
+ * Note: while this attribute can always be queried, it can't be set
+ * unless NV_CTRL_GPU_OVERCLOCKING_STATE is set to _MANUAL. Since
+ * the target clocks may be rejected, the requester should read this
+ * attribute after the set to determine success or failure.
+ *
+ * NV_CTRL_GPU_{2,3}D_CLOCK_FREQS are "packed" integer attributes; the
+ * GPU clock is stored in the upper 16 bits of the integer, and the
+ * memory clock is stored in the lower 16 bits of the integer. All
+ * clock values are in MHz.
+ */
+
+#define NV_CTRL_GPU_2D_CLOCK_FREQS 89 /* RW-G */
+#define NV_CTRL_GPU_3D_CLOCK_FREQS 90 /* RW-G */
+
+/*
+ * NV_CTRL_GPU_DEFAULT_{2,3}D_CLOCK_FREQS - query the default memory
+ * and GPU core clocks of the device driving the X screen.
+ *
+ * NV_CTRL_GPU_DEFAULT_{2,3}D_CLOCK_FREQS are "packed" integer
+ * attributes; the GPU clock is stored in the upper 16 bits of the
+ * integer, and the memory clock is stored in the lower 16 bits of the
+ * integer. All clock values are in MHz.
+ */
+
+#define NV_CTRL_GPU_DEFAULT_2D_CLOCK_FREQS 91 /* R--G */
+#define NV_CTRL_GPU_DEFAULT_3D_CLOCK_FREQS 92 /* R--G */
+
+/*
+ * NV_CTRL_GPU_CURRENT_CLOCK_FREQS - query the current GPU and memory
+ * clocks of the graphics device driving the X screen.
+ *
+ * NV_CTRL_GPU_CURRENT_CLOCK_FREQS is a "packed" integer attribute;
+ * the GPU clock is stored in the upper 16 bits of the integer, and
+ * the memory clock is stored in the lower 16 bits of the integer.
+ * All clock values are in MHz. All clock values are in MHz.
+ */
+
+#define NV_CTRL_GPU_CURRENT_CLOCK_FREQS 93 /* R--G */
+
+/*
+ * NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS - Holds the last calculated
+ * optimal 3D clock frequencies found by the
+ * NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION process. Querying this
+ * attribute before having probed for the optimal clocks will return
+ * NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_INVALID
+ *
+ * Note: unless NV_CTRL_GPU_OVERCLOCKING_STATE is set to _MANUAL, the
+ * optimal clock detection process is unavailable.
+ */
+
+#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS 94 /* R--G */
+#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_INVALID 0
+
+/*
+ * NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION - set to _START to
+ * initiate testing for the optimal 3D clock frequencies. Once
+ * found, the optimal clock frequencies will be returned by the
+ * NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS attribute asynchronously
+ * (using an X event, see XNVCtrlSelectNotify).
+ *
+ * To cancel an ongoing test for the optimal clocks, set the
+ * NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION attribute to _CANCEL
+ *
+ * Note: unless NV_CTRL_GPU_OVERCLOCKING_STATE is set to _MANUAL, the
+ * optimal clock detection process is unavailable.
+ */
+
+#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION 95 /* -W-G */
+#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_START 0
+#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_CANCEL 1
+
+/*
+ * NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE - query this
+ * variable to know if a test is currently being run to
+ * determine the optimal 3D clock frequencies. _BUSY means a
+ * test is currently running, _IDLE means the test is not running.
+ *
+ * Note: unless NV_CTRL_GPU_OVERCLOCKING_STATE is set to _MANUAL, the
+ * optimal clock detection process is unavailable.
+ */
+
+#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE 96 /* R--G */
+#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE_IDLE 0
+#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE_BUSY 1
+
+/*
+ * NV_CTRL_FLATPANEL_CHIP_LOCATION - for the specified display device,
+ * report whether the flat panel is driven by the on-chip controller,
+ * or a separate controller chip elsewhere on the graphics board.
+ * This attribute is only available for flat panels.
+ */
+
+#define NV_CTRL_FLATPANEL_CHIP_LOCATION 215 /* R-DG */
+#define NV_CTRL_FLATPANEL_CHIP_LOCATION_INTERNAL 0
+#define NV_CTRL_FLATPANEL_CHIP_LOCATION_EXTERNAL 1
+
+/*
+ * NV_CTRL_FLATPANEL_LINK - report the number of links for a DVI connection, or
+ * the main link's active lane count for DisplayPort.
+ * This attribute is only available for flat panels.
+ */
+
+#define NV_CTRL_FLATPANEL_LINK 216 /* R-DG */
+#define NV_CTRL_FLATPANEL_LINK_SINGLE 0
+#define NV_CTRL_FLATPANEL_LINK_DUAL 1
+#define NV_CTRL_FLATPANEL_LINK_QUAD 3
+
+/*
+ * NV_CTRL_FLATPANEL_SIGNAL - for the specified display device, report
+ * whether the flat panel is driven by an LVDS, TMDS, or DisplayPort signal.
+ * This attribute is only available for flat panels.
+ */
+
+#define NV_CTRL_FLATPANEL_SIGNAL 217 /* R-DG */
+#define NV_CTRL_FLATPANEL_SIGNAL_LVDS 0
+#define NV_CTRL_FLATPANEL_SIGNAL_TMDS 1
+#define NV_CTRL_FLATPANEL_SIGNAL_DISPLAYPORT 2
+
+/*
+ * NV_CTRL_USE_HOUSE_SYNC - when TRUE, the server (master) frame lock
+ * device will propagate the incoming house sync signal as the outgoing
+ * frame lock sync signal. If the frame lock device cannot detect a
+ * frame lock sync signal, it will default to using the internal timings
+ * from the GPU connected to the primary connector.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ */
+
+#define NV_CTRL_USE_HOUSE_SYNC 218 /* RW-F */
+#define NV_CTRL_USE_HOUSE_SYNC_FALSE 0
+#define NV_CTRL_USE_HOUSE_SYNC_TRUE 1
+
+/*
+ * NV_CTRL_EDID_AVAILABLE - report if an EDID is available for the
+ * specified display device.
+ *
+ * This attribute may also be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN
+ * target.
+ */
+
+#define NV_CTRL_EDID_AVAILABLE 219 /* R-DG */
+#define NV_CTRL_EDID_AVAILABLE_FALSE 0
+#define NV_CTRL_EDID_AVAILABLE_TRUE 1
+
+/*
+ * NV_CTRL_FORCE_STEREO - when TRUE, OpenGL will force stereo flipping
+ * even when no stereo drawables are visible (if the device is configured
+ * to support it, see the "Stereo" X config option).
+ * When false, fall back to the default behavior of only flipping when a
+ * stereo drawable is visible.
+ */
+
+#define NV_CTRL_FORCE_STEREO 220 /* RW- */
+#define NV_CTRL_FORCE_STEREO_FALSE 0
+#define NV_CTRL_FORCE_STEREO_TRUE 1
+
+/*
+ * NV_CTRL_IMAGE_SETTINGS - the image quality setting for OpenGL clients.
+ *
+ * This setting is only applied to OpenGL clients that are started
+ * after this setting is applied.
+ */
+
+#define NV_CTRL_IMAGE_SETTINGS 221 /* RW-X */
+#define NV_CTRL_IMAGE_SETTINGS_HIGH_QUALITY 0
+#define NV_CTRL_IMAGE_SETTINGS_QUALITY 1
+#define NV_CTRL_IMAGE_SETTINGS_PERFORMANCE 2
+#define NV_CTRL_IMAGE_SETTINGS_HIGH_PERFORMANCE 3
+
+/*
+ * NV_CTRL_XINERAMA - return whether xinerama is enabled
+ */
+
+#define NV_CTRL_XINERAMA 222 /* R--G */
+#define NV_CTRL_XINERAMA_OFF 0
+#define NV_CTRL_XINERAMA_ON 1
+
+/*
+ * NV_CTRL_XINERAMA_STEREO - when TRUE, OpenGL will allow stereo flipping
+ * on multiple X screens configured with Xinerama.
+ * When FALSE, flipping is allowed only on one X screen at a time.
+ */
+
+#define NV_CTRL_XINERAMA_STEREO 223 /* RW- */
+#define NV_CTRL_XINERAMA_STEREO_FALSE 0
+#define NV_CTRL_XINERAMA_STEREO_TRUE 1
+
+/*
+ * NV_CTRL_BUS_RATE - if the bus type of the specified device is AGP, then
+ * NV_CTRL_BUS_RATE returns the configured AGP transfer rate. If the bus type
+ * is PCI Express, then this attribute returns the maximum link width.
+ * When this attribute is queried on an X screen target, the bus rate of the
+ * GPU driving the X screen is returned.
+ */
+
+#define NV_CTRL_BUS_RATE 224 /* R--GI */
+
+/*
+ * NV_CTRL_GPU_PCIE_MAX_LINK_WIDTH - returns the maximum
+ * PCIe link width, in number of lanes.
+ */
+#define NV_CTRL_GPU_PCIE_MAX_LINK_WIDTH NV_CTRL_BUS_RATE
+
+/*
+ * NV_CTRL_SHOW_SLI_HUD - when TRUE, OpenGL will draw information about the
+ * current SLI mode.
+ * Renamed this attribute to NV_CTRL_SHOW_SLI_VISUAL_INDICATOR
+ */
+
+#define NV_CTRL_SHOW_SLI_HUD NV_CTRL_SHOW_SLI_VISUAL_INDICATOR
+#define NV_CTRL_SHOW_SLI_HUD_FALSE NV_CTRL_SHOW_SLI_VISUAL_INDICATOR_FALSE
+#define NV_CTRL_SHOW_SLI_HUD_TRUE NV_CTRL_SHOW_SLI_VISUAL_INDICATOR_TRUE
+
+/*
+ * NV_CTRL_SHOW_SLI_VISUAL_INDICATOR - when TRUE, OpenGL will draw information
+ * about the current SLI mode.
+ */
+
+#define NV_CTRL_SHOW_SLI_VISUAL_INDICATOR 225 /* RW-X */
+#define NV_CTRL_SHOW_SLI_VISUAL_INDICATOR_FALSE 0
+#define NV_CTRL_SHOW_SLI_VISUAL_INDICATOR_TRUE 1
+
+/*
+ * NV_CTRL_XV_SYNC_TO_DISPLAY - this control is valid when TwinView and
+ * XVideo Sync To VBlank are enabled.
+ * It controls which display device will be synched to.
+ */
+
+#define NV_CTRL_XV_SYNC_TO_DISPLAY 226 /* RW- */
+
+/*
+ * NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT2 - this attribute is only
+ * intended to be used to query the ValidValues for
+ * NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT for VIDEO_FORMAT values between
+ * 31 and 63. See NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT for details.
+ */
+
+#define NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT2 227 /* ---GI */
+
+/*
+ * The following is deprecated; use NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT2,
+ * instead
+ */
+#define NV_CTRL_GVO_OUTPUT_VIDEO_FORMAT2 227 /* --- */
+
+/*
+ * NV_CTRL_GVO_OVERRIDE_HW_CSC - Override the SDI hardware's Color Space
+ * Conversion with the values controlled through
+ * XNVCTRLSetGvoColorConversion() and XNVCTRLGetGvoColorConversion(). If
+ * this attribute is FALSE, then the values specified through
+ * XNVCTRLSetGvoColorConversion() are ignored.
+ */
+
+#define NV_CTRL_GVO_OVERRIDE_HW_CSC 228 /* RW- */
+#define NV_CTRL_GVO_OVERRIDE_HW_CSC_FALSE 0
+#define NV_CTRL_GVO_OVERRIDE_HW_CSC_TRUE 1
+
+/*
+ * NV_CTRL_GVO_CAPABILITIES - this read-only attribute describes GVO
+ * capabilities that differ between NVIDIA SDI products. This value
+ * is a bitmask where each bit indicates whether that capability is
+ * available.
+ *
+ * APPLY_CSC_IMMEDIATELY - whether the CSC matrix, offset, and scale
+ * specified through XNVCTRLSetGvoColorConversion() will take affect
+ * immediately, or only after SDI output is disabled and enabled
+ * again.
+ *
+ * APPLY_CSC_TO_X_SCREEN - whether the CSC matrix, offset, and scale
+ * specified through XNVCTRLSetGvoColorConversion() will also apply
+ * to GVO output of an X screen, or only to OpenGL GVO output, as
+ * enabled through the GLX_NV_video_out extension.
+ *
+ * COMPOSITE_TERMINATION - whether the 75 ohm termination of the
+ * SDI composite input signal can be programmed through the
+ * NV_CTRL_GVO_COMPOSITE_TERMINATION attribute.
+ *
+ * SHARED_SYNC_BNC - whether the SDI device has a single BNC
+ * connector used for both (SDI & Composite) incoming signals.
+ *
+ * MULTIRATE_SYNC - whether the SDI device supports synchronization
+ * of input and output video modes that match in being odd or even
+ * modes (ie, AA.00 Hz modes can be synched to other BB.00 Hz modes and
+ * AA.XX Hz can match to BB.YY Hz where .XX and .YY are not .00)
+ */
+
+#define NV_CTRL_GVO_CAPABILITIES 229 /* R-- */
+#define NV_CTRL_GVO_CAPABILITIES_APPLY_CSC_IMMEDIATELY 0x00000001
+#define NV_CTRL_GVO_CAPABILITIES_APPLY_CSC_TO_X_SCREEN 0x00000002
+#define NV_CTRL_GVO_CAPABILITIES_COMPOSITE_TERMINATION 0x00000004
+#define NV_CTRL_GVO_CAPABILITIES_SHARED_SYNC_BNC 0x00000008
+#define NV_CTRL_GVO_CAPABILITIES_MULTIRATE_SYNC 0x00000010
+#define NV_CTRL_GVO_CAPABILITIES_ADVANCE_SYNC_SKEW 0x00000020
+
+/*
+ * NV_CTRL_GVO_COMPOSITE_TERMINATION - enable or disable 75 ohm
+ * termination of the SDI composite input signal.
+ */
+
+#define NV_CTRL_GVO_COMPOSITE_TERMINATION 230 /* RW- */
+#define NV_CTRL_GVO_COMPOSITE_TERMINATION_ENABLE 1
+#define NV_CTRL_GVO_COMPOSITE_TERMINATION_DISABLE 0
+
+/*
+ * NV_CTRL_ASSOCIATED_DISPLAY_DEVICES - display device mask indicating
+ * which display devices are "associated" with the specified X screen
+ * (ie: are available to the X screen for displaying the X screen).
+ */
+
+#define NV_CTRL_ASSOCIATED_DISPLAY_DEVICES 231 /* RW- */
+
+/*
+ * NV_CTRL_FRAMELOCK_SLAVES - get/set whether the display device(s)
+ * given should listen or ignore the master's sync signal.
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU target. This attribute cannot be
+ * queried using a NV_CTRL_TARGET_TYPE_X_SCREEN.
+ */
+
+#define NV_CTRL_FRAMELOCK_SLAVES 232 /* RW-G */
+
+/*
+ * NV_CTRL_FRAMELOCK_MASTERABLE - Can any of the given display devices
+ * be set as master of the frame lock group. Returns a bitmask of the
+ * corresponding display devices that can be set as master.
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU target. This attribute cannot be
+ * queried using a NV_CTRL_TARGET_TYPE_X_SCREEN.
+ */
+
+#define NV_CTRL_FRAMELOCK_MASTERABLE 233 /* R-DG */
+
+/*
+ * NV_CTRL_PROBE_DISPLAYS - re-probes the hardware to detect what
+ * display devices are connected to the GPU or GPU driving the
+ * specified X screen. Returns a display mask.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_PROBE_DISPLAYS 234 /* R--G */
+
+/*
+ * NV_CTRL_REFRESH_RATE - Returns the refresh rate of the specified
+ * display device in 100 * Hz (ie. to get the refresh rate in Hz, divide
+ * the returned value by 100.)
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_REFRESH_RATE 235 /* R-DG */
+
+/*
+ * NV_CTRL_GVO_FLIP_QUEUE_SIZE - The Graphics to Video Out interface
+ * exposed through NV-CONTROL and the GLX_NV_video_out extension uses
+ * an internal flip queue when pbuffers are sent to the video device
+ * (via glXSendPbufferToVideoNV()). The NV_CTRL_GVO_FLIP_QUEUE_SIZE
+ * can be used to query and assign the flip queue size. This
+ * attribute is applied to GLX when glXGetVideoDeviceNV() is called by
+ * the application.
+ */
+
+#define NV_CTRL_GVO_FLIP_QUEUE_SIZE 236 /* RW- */
+
+/*
+ * NV_CTRL_CURRENT_SCANLINE - query the current scanline for the
+ * specified display device.
+ */
+
+#define NV_CTRL_CURRENT_SCANLINE 237 /* R-DG */
+
+/*
+ * NV_CTRL_INITIAL_PIXMAP_PLACEMENT - Controls where X pixmaps are initially
+ * created.
+ *
+ * NV_CTRL_INITIAL_PIXMAP_PLACEMENT_FORCE_SYSMEM causes pixmaps to stay in
+ * system memory. These pixmaps can't be accelerated by the NVIDIA driver; this
+ * will cause blank windows if used with an OpenGL compositing manager.
+ * NV_CTRL_INITIAL_PIXMAP_PLACEMENT_SYSMEM creates pixmaps in system memory
+ * initially, but allows them to migrate to video memory.
+ * NV_CTRL_INITIAL_PIXMAP_PLACEMENT_VIDMEM creates pixmaps in video memory
+ * when enough resources are available.
+ * NV_CTRL_INITIAL_PIXMAP_PLACEMENT_RESERVED is currently reserved for future
+ * use. Behavior is undefined.
+ * NV_CTRL_INITIAL_PIXMAP_PLACEMENT_GPU_SYSMEM creates pixmaps in GPU accessible
+ * system memory when enough resources are available.
+ */
+
+#define NV_CTRL_INITIAL_PIXMAP_PLACEMENT 238 /* RW- */
+#define NV_CTRL_INITIAL_PIXMAP_PLACEMENT_FORCE_SYSMEM 0
+#define NV_CTRL_INITIAL_PIXMAP_PLACEMENT_SYSMEM 1
+#define NV_CTRL_INITIAL_PIXMAP_PLACEMENT_VIDMEM 2
+#define NV_CTRL_INITIAL_PIXMAP_PLACEMENT_RESERVED 3
+#define NV_CTRL_INITIAL_PIXMAP_PLACEMENT_GPU_SYSMEM 4
+
+/*
+ * NV_CTRL_PCI_BUS - Returns the PCI bus number the specified device is using.
+ */
+
+#define NV_CTRL_PCI_BUS 239 /* R--GI */
+
+/*
+ * NV_CTRL_PCI_DEVICE - Returns the PCI device number the specified device is
+ * using.
+ */
+
+#define NV_CTRL_PCI_DEVICE 240 /* R--GI */
+
+/*
+ * NV_CTRL_PCI_FUNCTION - Returns the PCI function number the specified device
+ * is using.
+ */
+
+#define NV_CTRL_PCI_FUNCTION 241 /* R--GI */
+
+/*
+ * NV_CTRL_FRAMELOCK_FPGA_REVISION - Querys the FPGA revision of the
+ * Frame Lock device.
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK target.
+ */
+
+#define NV_CTRL_FRAMELOCK_FPGA_REVISION 242 /* R--F */
+
+/*
+ * NV_CTRL_MAX_SCREEN_{WIDTH,HEIGHT} - the maximum allowable size, in
+ * pixels, of either the specified X screen (if the target_type of the
+ * query is an X screen), or any X screen on the specified GPU (if the
+ * target_type of the query is a GPU).
+ */
+
+#define NV_CTRL_MAX_SCREEN_WIDTH 243 /* R--G */
+#define NV_CTRL_MAX_SCREEN_HEIGHT 244 /* R--G */
+
+/*
+ * NV_CTRL_MAX_DISPLAYS - the maximum number of display devices that
+ * can be driven simultaneously on a GPU (e.g., that can be used in a
+ * MetaMode at once). Note that this does not indicate the maximum
+ * number of bits that can be set in NV_CTRL_CONNECTED_DISPLAYS,
+ * because more display devices can be connected than are actively in
+ * use.
+ */
+
+#define NV_CTRL_MAX_DISPLAYS 245 /* R--G */
+
+/*
+ * NV_CTRL_DYNAMIC_TWINVIEW - Returns whether or not the screen
+ * supports dynamic twinview.
+ */
+
+#define NV_CTRL_DYNAMIC_TWINVIEW 246 /* R-- */
+
+/*
+ * NV_CTRL_MULTIGPU_DISPLAY_OWNER - Returns the (NV-CONTROL) GPU ID of
+ * the GPU that has the display device(s) used for showing the X Screen.
+ */
+
+#define NV_CTRL_MULTIGPU_DISPLAY_OWNER 247 /* R-- */
+
+/*
+ * NV_CTRL_GPU_SCALING - not supported
+ */
+
+#define NV_CTRL_GPU_SCALING 248 /* RWDG */
+
+#define NV_CTRL_GPU_SCALING_TARGET_INVALID 0
+#define NV_CTRL_GPU_SCALING_TARGET_FLATPANEL_BEST_FIT 1
+#define NV_CTRL_GPU_SCALING_TARGET_FLATPANEL_NATIVE 2
+
+#define NV_CTRL_GPU_SCALING_METHOD_INVALID 0
+#define NV_CTRL_GPU_SCALING_METHOD_STRETCHED 1
+#define NV_CTRL_GPU_SCALING_METHOD_CENTERED 2
+#define NV_CTRL_GPU_SCALING_METHOD_ASPECT_SCALED 3
+
+/*
+ * NV_CTRL_FRONTEND_RESOLUTION - not supported
+ */
+
+#define NV_CTRL_FRONTEND_RESOLUTION 249 /* R-DG */
+
+/*
+ * NV_CTRL_BACKEND_RESOLUTION - not supported
+ */
+
+#define NV_CTRL_BACKEND_RESOLUTION 250 /* R-DG */
+
+/*
+ * NV_CTRL_FLATPANEL_NATIVE_RESOLUTION - Returns the dimensions of the
+ * native resolution of the flat panel as determined by the
+ * NVIDIA X Driver.
+ *
+ * The native resolution is the resolution at which a flat panel
+ * must display any image. All other resolutions must be scaled to this
+ * resolution through GPU scaling or the DFP's native scaling capabilities
+ * in order to be displayed.
+ *
+ * This attribute is only valid for flat panel (DFP) display devices.
+ *
+ * This attribute is a packed integer; the width is packed in the upper
+ * 16-bits and the height is packed in the lower 16-bits.
+ */
+
+#define NV_CTRL_FLATPANEL_NATIVE_RESOLUTION 251 /* R-DG */
+
+/*
+ * NV_CTRL_FLATPANEL_BEST_FIT_RESOLUTION - not supported
+ */
+
+#define NV_CTRL_FLATPANEL_BEST_FIT_RESOLUTION 252 /* R-DG */
+
+/*
+ * NV_CTRL_GPU_SCALING_ACTIVE - not supported
+ */
+
+#define NV_CTRL_GPU_SCALING_ACTIVE 253 /* R-DG */
+
+/*
+ * NV_CTRL_DFP_SCALING_ACTIVE - not supported
+ */
+
+#define NV_CTRL_DFP_SCALING_ACTIVE 254 /* R-DG */
+
+/*
+ * NV_CTRL_FSAA_APPLICATION_ENHANCED - Controls how the NV_CTRL_FSAA_MODE
+ * is applied when NV_CTRL_FSAA_APPLICATION_CONTROLLED is set to
+ * NV_CTRL_APPLICATION_CONTROLLED_DISABLED. When
+ * NV_CTRL_FSAA_APPLICATION_ENHANCED is _DISABLED, OpenGL applications will
+ * be forced to use the FSAA mode specified by NV_CTRL_FSAA_MODE. when set
+ * to _ENABLED, only those applications that have selected a multisample
+ * FBConfig will be made to use the NV_CTRL_FSAA_MODE specified.
+ *
+ * This attribute is ignored when NV_CTRL_FSAA_APPLICATION_CONTROLLED is
+ * set to NV_CTRL_FSAA_APPLICATION_CONTROLLED_ENABLED.
+ */
+
+#define NV_CTRL_FSAA_APPLICATION_ENHANCED 255 /* RW-X */
+#define NV_CTRL_FSAA_APPLICATION_ENHANCED_ENABLED 1
+#define NV_CTRL_FSAA_APPLICATION_ENHANCED_DISABLED 0
+
+/*
+ * NV_CTRL_FRAMELOCK_SYNC_RATE_4 - This is the refresh rate that the
+ * frame lock board is sending to the GPU with 4 digits of precision.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK.
+ */
+
+#define NV_CTRL_FRAMELOCK_SYNC_RATE_4 256 /* R--F */
+
+/*
+ * NV_CTRL_GVO_LOCK_OWNER - indicates that the GVO device is available
+ * or in use (by GLX or an X screen).
+ *
+ * The GVO device is locked by GLX when either glXGetVideoDeviceNV
+ * (part of GLX_NV_video_out) or glXBindVideoDeviceNV (part of
+ * GLX_NV_present_video) is called. All GVO output resources are
+ * locked until released by the GLX_NV_video_out/GLX_NV_present_video
+ * client.
+ *
+ * The GVO device is locked/unlocked by an X screen, when the GVO device is
+ * used in a MetaMode on an X screen.
+ *
+ * When the GVO device is locked, setting of the following GVO NV-CONTROL
+ * attributes will not happen immediately and will instead be cached. The
+ * GVO resource will need to be disabled/released and re-enabled/claimed for
+ * the values to be flushed. These attributes are:
+ *
+ * NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT
+ * NV_CTRL_GVO_DATA_FORMAT
+ * NV_CTRL_GVO_FLIP_QUEUE_SIZE
+ */
+
+#define NV_CTRL_GVO_LOCK_OWNER 257 /* R-- */
+#define NV_CTRL_GVO_LOCK_OWNER_NONE 0
+#define NV_CTRL_GVO_LOCK_OWNER_GLX 1
+#define NV_CTRL_GVO_LOCK_OWNER_CLONE /* no longer supported */ 2
+#define NV_CTRL_GVO_LOCK_OWNER_X_SCREEN 3
+
+/*
+ * NV_CTRL_HWOVERLAY - when a workstation overlay is in use, reports
+ * whether the hardware overlay is used, or if the overlay is emulated.
+ */
+
+#define NV_CTRL_HWOVERLAY 258 /* R-- */
+#define NV_CTRL_HWOVERLAY_FALSE 0
+#define NV_CTRL_HWOVERLAY_TRUE 1
+
+/*
+ * NV_CTRL_NUM_GPU_ERRORS_RECOVERED - Returns the number of GPU errors
+ * occured. This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_NUM_GPU_ERRORS_RECOVERED 259 /* R--- */
+
+/*
+ * NV_CTRL_REFRESH_RATE_3 - Returns the refresh rate of the specified
+ * display device in 1000 * Hz (ie. to get the refresh rate in Hz, divide
+ * the returned value by 1000.)
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_REFRESH_RATE_3 260 /* R-DG */
+
+/*
+ * NV_CTRL_ONDEMAND_VBLANK_INTERRUPTS - if the OnDemandVBlankInterrupts
+ * X driver option is set to true, this attribute can be used to
+ * determine if on-demand VBlank interrupt control is enabled on the
+ * specified GPU, as well as to enable or disable this feature.
+ */
+
+#define NV_CTRL_ONDEMAND_VBLANK_INTERRUPTS 261 /* RW-G */
+#define NV_CTRL_ONDEMAND_VBLANK_INTERRUPTS_OFF 0
+#define NV_CTRL_ONDEMAND_VBLANK_INTERRUPTS_ON 1
+
+/*
+ * NV_CTRL_GPU_POWER_SOURCE reports the type of power source
+ * of the GPU driving the X screen.
+ */
+
+#define NV_CTRL_GPU_POWER_SOURCE 262 /* R--G */
+#define NV_CTRL_GPU_POWER_SOURCE_AC 0
+#define NV_CTRL_GPU_POWER_SOURCE_BATTERY 1
+
+/*
+ * NV_CTRL_GPU_CURRENT_PERFORMANCE_MODE is deprecated
+ */
+
+#define NV_CTRL_GPU_CURRENT_PERFORMANCE_MODE 263 /* R--G */
+#define NV_CTRL_GPU_CURRENT_PERFORMANCE_MODE_DESKTOP 0
+#define NV_CTRL_GPU_CURRENT_PERFORMANCE_MODE_MAXPERF 1
+
+/* NV_CTRL_GLYPH_CACHE - Enables RENDER Glyph Caching to VRAM */
+
+#define NV_CTRL_GLYPH_CACHE 264 /* RW- */
+#define NV_CTRL_GLYPH_CACHE_DISABLED 0
+#define NV_CTRL_GLYPH_CACHE_ENABLED 1
+
+/*
+ * NV_CTRL_GPU_CURRENT_PERFORMANCE_LEVEL reports the current
+ * Performance level of the GPU driving the X screen. Each
+ * Performance level has associated NVClock and Mem Clock values.
+ */
+
+#define NV_CTRL_GPU_CURRENT_PERFORMANCE_LEVEL 265 /* R--G */
+
+/*
+ * NV_CTRL_GPU_ADAPTIVE_CLOCK_STATE reports if Adaptive Clocking
+ * is Enabled on the GPU driving the X screen.
+ */
+
+#define NV_CTRL_GPU_ADAPTIVE_CLOCK_STATE 266 /* R--G */
+#define NV_CTRL_GPU_ADAPTIVE_CLOCK_STATE_DISABLED 0
+#define NV_CTRL_GPU_ADAPTIVE_CLOCK_STATE_ENABLED 1
+
+/*
+ * NV_CTRL_GVO_OUTPUT_VIDEO_LOCKED - Returns whether or not the GVO output
+ * video is locked to the GPU.
+ */
+
+#define NV_CTRL_GVO_OUTPUT_VIDEO_LOCKED 267 /* R--- */
+#define NV_CTRL_GVO_OUTPUT_VIDEO_LOCKED_FALSE 0
+#define NV_CTRL_GVO_OUTPUT_VIDEO_LOCKED_TRUE 1
+
+/*
+ * NV_CTRL_GVO_SYNC_LOCK_STATUS - Returns whether or not the GVO device
+ * is locked to the input ref signal. If the sync mode is set to
+ * NV_CTRL_GVO_SYNC_MODE_GENLOCK, then this returns the genlock
+ * sync status, and if the sync mode is set to NV_CTRL_GVO_SYNC_MODE_FRAMELOCK,
+ * then this reports the frame lock status.
+ */
+
+#define NV_CTRL_GVO_SYNC_LOCK_STATUS 268 /* R--- */
+#define NV_CTRL_GVO_SYNC_LOCK_STATUS_UNLOCKED 0
+#define NV_CTRL_GVO_SYNC_LOCK_STATUS_LOCKED 1
+
+/*
+ * NV_CTRL_GVO_ANC_TIME_CODE_GENERATION - Allows SDI device to generate
+ * time codes in the ANC region of the SDI video output stream.
+ */
+
+#define NV_CTRL_GVO_ANC_TIME_CODE_GENERATION 269 /* RW-- */
+#define NV_CTRL_GVO_ANC_TIME_CODE_GENERATION_DISABLE 0
+#define NV_CTRL_GVO_ANC_TIME_CODE_GENERATION_ENABLE 1
+
+/*
+ * NV_CTRL_GVO_COMPOSITE - Enables/Disables SDI compositing. This attribute
+ * is only available when an SDI input source is detected and is in genlock
+ * mode.
+ */
+
+#define NV_CTRL_GVO_COMPOSITE 270 /* RW-- */
+#define NV_CTRL_GVO_COMPOSITE_DISABLE 0
+#define NV_CTRL_GVO_COMPOSITE_ENABLE 1
+
+/*
+ * NV_CTRL_GVO_COMPOSITE_ALPHA_KEY - When compositing is enabled, this
+ * enables/disables alpha blending.
+ */
+
+#define NV_CTRL_GVO_COMPOSITE_ALPHA_KEY 271 /* RW-- */
+#define NV_CTRL_GVO_COMPOSITE_ALPHA_KEY_DISABLE 0
+#define NV_CTRL_GVO_COMPOSITE_ALPHA_KEY_ENABLE 1
+
+/*
+ * NV_CTRL_GVO_COMPOSITE_LUMA_KEY_RANGE - Set the values of a luma
+ * channel range. This is a packed int that has the following format
+ * (in order of high-bits to low bits):
+ *
+ * Range # (11 bits), (Enabled 1 bit), min value (10 bits), max value (10 bits)
+ *
+ * To query the current values, pass the range # throught the display_mask
+ * variable.
+ */
+
+#define NV_CTRL_GVO_COMPOSITE_LUMA_KEY_RANGE 272 /* RW-- */
+
+#define NV_CTRL_GVO_COMPOSITE_MAKE_RANGE(range, enable, min, max) \
+ ((((min)&0x3FF) << 0) | (((max)&0x3FF) << 10) | (((enable)&0x1) << 20) | \
+ (((range)&0x7FF) << 21))
+
+#define NV_CTRL_GVO_COMPOSITE_GET_RANGE(val, range, enable, min, max) \
+ (min) = ((val) >> 0) & 0x3FF; \
+ (max) = ((val) >> 10) & 0x3FF; \
+ (enable) = ((val) >> 20) & 0x1; \
+ (range) = ((val) >> 21) & 0x7FF;
+
+/*
+ * NV_CTRL_GVO_COMPOSITE_CR_KEY_RANGE - Set the values of a CR
+ * channel range. This is a packed int that has the following format
+ * (in order of high-bits to low bits):
+ *
+ * Range # (11 bits), (Enabled 1 bit), min value (10 bits), max value (10 bits)
+ *
+ * To query the current values, pass the range # throught he display_mask
+ * variable.
+ */
+
+#define NV_CTRL_GVO_COMPOSITE_CR_KEY_RANGE 273 /* RW-- */
+
+/*
+ * NV_CTRL_GVO_COMPOSITE_CB_KEY_RANGE - Set the values of a CB
+ * channel range. This is a packed int that has the following format
+ * (in order of high-bits to low bits):
+ *
+ * Range # (11 bits), (Enabled 1 bit), min value (10 bits), max value (10 bits)
+ *
+ * To query the current values, pass the range # throught he display_mask
+ * variable.
+ */
+
+#define NV_CTRL_GVO_COMPOSITE_CB_KEY_RANGE 274 /* RW-- */
+
+/*
+ * NV_CTRL_GVO_COMPOSITE_NUM_KEY_RANGES - Returns the number of ranges
+ * available for each channel (Y/Luma, Cr, and Cb.)
+ */
+
+#define NV_CTRL_GVO_COMPOSITE_NUM_KEY_RANGES 275 /* R--- */
+
+/*
+ * NV_CTRL_SWITCH_TO_DISPLAYS - Can be used to select which displays
+ * to switch to (as a hotkey event).
+ */
+
+#define NV_CTRL_SWITCH_TO_DISPLAYS 276 /* -W- */
+
+/*
+ * NV_CTRL_NOTEBOOK_DISPLAY_CHANGE_LID_EVENT - Event that notifies
+ * when a notebook lid change occurs (i.e. when the lid is opened or
+ * closed.) This attribute can be queried to retrieve the current
+ * notebook lid status (opened/closed.)
+ */
+
+#define NV_CTRL_NOTEBOOK_DISPLAY_CHANGE_LID_EVENT 277 /* RW- */
+#define NV_CTRL_NOTEBOOK_DISPLAY_CHANGE_LID_EVENT_CLOSE 0
+#define NV_CTRL_NOTEBOOK_DISPLAY_CHANGE_LID_EVENT_OPEN 1
+
+/*
+ * NV_CTRL_NOTEBOOK_INTERNAL_LCD - Returns the display device mask of
+ * the intenal LCD of a notebook.
+ */
+
+#define NV_CTRL_NOTEBOOK_INTERNAL_LCD 278 /* R-- */
+
+/*
+ * NV_CTRL_DEPTH_30_ALLOWED - returns whether the NVIDIA X driver supports
+ * depth 30 on the specified X screen or GPU.
+ */
+
+#define NV_CTRL_DEPTH_30_ALLOWED 279 /* R--G */
+
+/*
+ * NV_CTRL_MODE_SET_EVENT This attribute is sent as an event
+ * when hotkey, ctrl-alt-+/- or randr event occurs. Note that
+ * This attribute cannot be set or queried and is meant to
+ * be received by clients that wish to be notified of when
+ * mode set events occur.
+ */
+
+#define NV_CTRL_MODE_SET_EVENT 280 /* --- */
+
+/*
+ * NV_CTRL_OPENGL_AA_LINE_GAMMA_VALUE - the gamma value used by
+ * OpenGL when NV_CTRL_OPENGL_AA_LINE_GAMMA is enabled
+ */
+
+#define NV_CTRL_OPENGL_AA_LINE_GAMMA_VALUE 281 /* RW-X */
+
+/*
+ * NV_CTRL_VCSC_HIGH_PERF_MODE - Is used to both query High Performance Mode
+ * status on the Visual Computing System, and also to enable or disable High
+ * Performance Mode.
+ */
+
+#define NV_CTRL_VCSC_HIGH_PERF_MODE 282 /* RW-V */
+#define NV_CTRL_VCSC_HIGH_PERF_MODE_DISABLE 0
+#define NV_CTRL_VCSC_HIGH_PERF_MODE_ENABLE 1
+
+/*
+ * NV_CTRL_DISPLAYPORT_LINK_RATE - returns the negotiated lane bandwidth of the
+ * DisplayPort main link.
+ * This attribute is only available for DisplayPort flat panels.
+ */
+
+#define NV_CTRL_DISPLAYPORT_LINK_RATE 291 /* R-DG */
+#define NV_CTRL_DISPLAYPORT_LINK_RATE_DISABLED 0x0
+#define NV_CTRL_DISPLAYPORT_LINK_RATE_1_62GBPS 0x6
+#define NV_CTRL_DISPLAYPORT_LINK_RATE_2_70GBPS 0xA
+
+/*
+ * NV_CTRL_STEREO_EYES_EXCHANGE - Controls whether or not the left and right
+ * eyes of a stereo image are flipped.
+ */
+
+#define NV_CTRL_STEREO_EYES_EXCHANGE 292 /* RW-X */
+#define NV_CTRL_STEREO_EYES_EXCHANGE_OFF 0
+#define NV_CTRL_STEREO_EYES_EXCHANGE_ON 1
+
+/*
+ * NV_CTRL_NO_SCANOUT - returns whether the special "NoScanout" mode is
+ * enabled on the specified X screen or GPU; for details on this mode,
+ * see the description of the "none" value for the "UseDisplayDevice"
+ * X configuration option in the NVIDIA driver README.
+ */
+
+#define NV_CTRL_NO_SCANOUT 293 /* R--G */
+#define NV_CTRL_NO_SCANOUT_DISABLED 0
+#define NV_CTRL_NO_SCANOUT_ENABLED 1
+
+/*
+ * NV_CTRL_GVO_CSC_CHANGED_EVENT This attribute is sent as an event
+ * when the color space conversion matrix has been altered by another
+ * client.
+ */
+
+#define NV_CTRL_GVO_CSC_CHANGED_EVENT 294 /* --- */
+
+/*
+ * NV_CTRL_FRAMELOCK_SLAVEABLE - Returns a bitmask of the display devices
+ * that are (currently) allowed to be selected as slave devices for the
+ * given GPU
+ */
+
+#define NV_CTRL_FRAMELOCK_SLAVEABLE 295 /* R-DG */
+
+/*
+ * NV_CTRL_GVO_SYNC_TO_DISPLAY This attribute controls whether or not
+ * the non-SDI display device will be sync'ed to the SDI display device
+ * (when configured in TwinView, Clone Mode or when using the SDI device
+ * with OpenGL).
+ */
+
+#define NV_CTRL_GVO_SYNC_TO_DISPLAY 296 /* --- */
+#define NV_CTRL_GVO_SYNC_TO_DISPLAY_DISABLE 0
+#define NV_CTRL_GVO_SYNC_TO_DISPLAY_ENABLE 1
+
+/*
+ * NV_CTRL_X_SERVER_UNIQUE_ID - returns a pseudo-unique identifier for this
+ * X server. Intended for use in cases where an NV-CONTROL client communicates
+ * with multiple X servers, and wants some level of confidence that two
+ * X Display connections correspond to the same or different X servers.
+ */
+
+#define NV_CTRL_X_SERVER_UNIQUE_ID 297 /* R--- */
+
+/*
+ * NV_CTRL_PIXMAP_CACHE - This attribute controls whether the driver attempts to
+ * store video memory pixmaps in a cache. The cache speeds up allocation and
+ * deallocation of pixmaps, but could use more memory than when the cache is
+ * disabled.
+ */
+
+#define NV_CTRL_PIXMAP_CACHE 298 /* RW-X */
+#define NV_CTRL_PIXMAP_CACHE_DISABLE 0
+#define NV_CTRL_PIXMAP_CACHE_ENABLE 1
+
+/*
+ * NV_CTRL_PIXMAP_CACHE_ROUNDING_SIZE_KB - When the pixmap cache is enabled and
+ * there is not enough free space in the cache to fit a new pixmap, the driver
+ * will round up to the next multiple of this number of kilobytes when
+ * allocating more memory for the cache.
+ */
+
+#define NV_CTRL_PIXMAP_CACHE_ROUNDING_SIZE_KB 299 /* RW-X */
+
+/*
+ * NV_CTRL_IS_GVO_DISPLAY - returns whether or not a given display is an
+ * SDI device.
+ */
+
+#define NV_CTRL_IS_GVO_DISPLAY 300 /* R-D */
+#define NV_CTRL_IS_GVO_DISPLAY_FALSE 0
+#define NV_CTRL_IS_GVO_DISPLAY_TRUE 1
+
+/*
+ * NV_CTRL_PCI_ID - Returns the PCI vendor and device ID of the specified
+ * device.
+ *
+ * NV_CTRL_PCI_ID is a "packed" integer attribute; the PCI vendor ID is stored
+ * in the upper 16 bits of the integer, and the PCI device ID is stored in the
+ * lower 16 bits of the integer.
+ */
+
+#define NV_CTRL_PCI_ID 301 /* R--GI */
+
+/*
+ * NV_CTRL_GVO_FULL_RANGE_COLOR - Allow full range color data [4-1019]
+ * without clamping to [64-940].
+ */
+
+#define NV_CTRL_GVO_FULL_RANGE_COLOR 302 /* RW- */
+#define NV_CTRL_GVO_FULL_RANGE_COLOR_DISABLED 0
+#define NV_CTRL_GVO_FULL_RANGE_COLOR_ENABLED 1
+
+/*
+ * NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE - Returns whether or not
+ * SLI Mosaic Mode supported.
+ */
+
+#define NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE 303 /* R-- */
+#define NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE_FALSE 0
+#define NV_CTRL_SLI_MOSAIC_MODE_AVAILABLE_TRUE 1
+
+/*
+ * NV_CTRL_GVO_ENABLE_RGB_DATA - Allows clients to specify when
+ * the GVO board should process colors as RGB when the output data
+ * format is one of the NV_CTRL_GVO_DATA_FORMAT_???_PASSTRHU modes.
+ */
+
+#define NV_CTRL_GVO_ENABLE_RGB_DATA 304 /* RW- */
+#define NV_CTRL_GVO_ENABLE_RGB_DATA_DISABLE 0
+#define NV_CTRL_GVO_ENABLE_RGB_DATA_ENABLE 1
+
+/*
+ * NV_CTRL_IMAGE_SHARPENING_DEFAULT - Returns default value of
+ * Image Sharpening.
+ */
+
+#define NV_CTRL_IMAGE_SHARPENING_DEFAULT 305 /* R-- */
+
+/*
+ * NV_CTRL_PCI_DOMAIN - Returns the PCI domain number the specified device is
+ * using.
+ */
+
+#define NV_CTRL_PCI_DOMAIN 306 /* R--GI */
+
+/*
+ * NV_CTRL_GVI_NUM_JACKS - Returns the number of input BNC jacks available
+ * on a GVI device.
+ */
+
+#define NV_CTRL_GVI_NUM_JACKS 307 /* R--I */
+
+/*
+ * NV_CTRL_GVI_MAX_LINKS_PER_STREAM - Returns the maximum supported number of
+ * links that can be tied to one stream.
+ */
+
+#define NV_CTRL_GVI_MAX_LINKS_PER_STREAM 308 /* R--I */
+
+/*
+ * NV_CTRL_GVI_DETECTED_CHANNEL_BITS_PER_COMPONENT - Returns the detected
+ * number of bits per component (BPC) of data on the given input jack+
+ * channel.
+ *
+ * The jack number should be specified in the lower 16 bits of the
+ * "display_mask" parameter, while the channel number should be specified in
+ * the upper 16 bits.
+ */
+
+#define NV_CTRL_GVI_DETECTED_CHANNEL_BITS_PER_COMPONENT 309 /* R--I */
+#define NV_CTRL_GVI_BITS_PER_COMPONENT_UNKNOWN 0
+#define NV_CTRL_GVI_BITS_PER_COMPONENT_8 1
+#define NV_CTRL_GVI_BITS_PER_COMPONENT_10 2
+#define NV_CTRL_GVI_BITS_PER_COMPONENT_12 3
+
+/*
+ * NV_CTRL_GVI_REQUESTED_STREAM_BITS_PER_COMPONENT - Specify the number of
+ * bits per component (BPC) of data for the captured stream.
+ * The stream number should be specified in the "display_mask" parameter.
+ *
+ * Note: Setting this attribute may also result in the following
+ * NV-CONTROL attributes being reset on the GVI device (to ensure
+ * the configuration remains valid):
+ * NV_CTRL_GVI_REQUESTED_STREAM_COMPONENT_SAMPLING
+ */
+
+#define NV_CTRL_GVI_REQUESTED_STREAM_BITS_PER_COMPONENT 310 /* RW-I */
+
+/*
+ * NV_CTRL_GVI_DETECTED_CHANNEL_COMPONENT_SAMPLING - Returns the detected
+ * sampling format for the input jack+channel.
+ *
+ * The jack number should be specified in the lower 16 bits of the
+ * "display_mask" parameter, while the channel number should be specified in
+ * the upper 16 bits.
+ */
+
+#define NV_CTRL_GVI_DETECTED_CHANNEL_COMPONENT_SAMPLING 311 /* R--I */
+#define NV_CTRL_GVI_COMPONENT_SAMPLING_UNKNOWN 0
+#define NV_CTRL_GVI_COMPONENT_SAMPLING_4444 1
+#define NV_CTRL_GVI_COMPONENT_SAMPLING_4224 2
+#define NV_CTRL_GVI_COMPONENT_SAMPLING_444 3
+#define NV_CTRL_GVI_COMPONENT_SAMPLING_422 4
+#define NV_CTRL_GVI_COMPONENT_SAMPLING_420 5
+
+/*
+ * NV_CTRL_GVI_REQUESTED_COMPONENT_SAMPLING - Specify the sampling format for
+ * the captured stream.
+ * The possible values are the NV_CTRL_GVI_DETECTED_COMPONENT_SAMPLING
+ * constants.
+ * The stream number should be specified in the "display_mask" parameter.
+ */
+
+#define NV_CTRL_GVI_REQUESTED_STREAM_COMPONENT_SAMPLING 312 /* RW-I */
+
+/*
+ * NV_CTRL_GVI_CHROMA_EXPAND - Enable or disable 4:2:2 -> 4:4:4 chroma
+ * expansion for the captured stream. This value is ignored when a
+ * COMPONENT_SAMPLING format is selected that does not use chroma subsampling,
+ * or if a BITS_PER_COMPONENT value is selected that is not supported.
+ * The stream number should be specified in the "display_mask" parameter.
+ */
+
+#define NV_CTRL_GVI_REQUESTED_STREAM_CHROMA_EXPAND 313 /* RW-I */
+#define NV_CTRL_GVI_CHROMA_EXPAND_FALSE 0
+#define NV_CTRL_GVI_CHROMA_EXPAND_TRUE 1
+
+/*
+ * NV_CTRL_GVI_DETECTED_CHANNEL_COLOR_SPACE - Returns the detected color space
+ * of the input jack+channel.
+ *
+ * The jack number should be specified in the lower 16 bits of the
+ * "display_mask" parameter, while the channel number should be specified in
+ * the upper 16 bits.
+ */
+
+#define NV_CTRL_GVI_DETECTED_CHANNEL_COLOR_SPACE 314 /* R--I */
+#define NV_CTRL_GVI_COLOR_SPACE_UNKNOWN 0
+#define NV_CTRL_GVI_COLOR_SPACE_GBR 1
+#define NV_CTRL_GVI_COLOR_SPACE_GBRA 2
+#define NV_CTRL_GVI_COLOR_SPACE_GBRD 3
+#define NV_CTRL_GVI_COLOR_SPACE_YCBCR 4
+#define NV_CTRL_GVI_COLOR_SPACE_YCBCRA 5
+#define NV_CTRL_GVI_COLOR_SPACE_YCBCRD 6
+
+/*
+ * NV_CTRL_GVI_DETECTED_CHANNEL_LINK_ID - Returns the detected link identifier
+ * for the given input jack+channel.
+ *
+ * The jack number should be specified in the lower 16 bits of the
+ * "display_mask" parameter, while the channel number should be specified in
+ * the upper 16 bits.
+ */
+
+#define NV_CTRL_GVI_DETECTED_CHANNEL_LINK_ID 315 /* R--I */
+#define NV_CTRL_GVI_LINK_ID_UNKNOWN 0xFFFF
+
+/*
+ * NV_CTRL_GVI_DETECTED_CHANNEL_SMPTE352_IDENTIFIER - Returns the 4-byte
+ * SMPTE 352 identifier from the given input jack+channel.
+ *
+ * The jack number should be specified in the lower 16 bits of the
+ * "display_mask" parameter, while the channel number should be specified in
+ * the upper 16 bits.
+ */
+
+#define NV_CTRL_GVI_DETECTED_CHANNEL_SMPTE352_IDENTIFIER 316 /* R--I */
+
+/*
+ * NV_CTRL_GVI_GLOBAL_IDENTIFIER - Returns a global identifier for the
+ * GVI device. This identifier can be used to relate GVI devices named
+ * in NV-CONTROL with those enumerated in OpenGL.
+ */
+
+#define NV_CTRL_GVI_GLOBAL_IDENTIFIER 317 /* R--I */
+
+/*
+ * NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION - Returns the number of nanoseconds
+ * that one unit of NV_CTRL_FRAMELOCK_SYNC_DELAY corresponds to.
+ */
+#define NV_CTRL_FRAMELOCK_SYNC_DELAY_RESOLUTION 318 /* R-- */
+
+/*
+ * NV_CTRL_GPU_COOLER_MANUAL_CONTROL - Query the current or set a new
+ * cooler control state; the value of this attribute controls the
+ * availability of additional cooler control attributes (see below).
+ *
+ * Note: this attribute is unavailable unless cooler control support
+ * has been enabled in the X server (by the user).
+ */
+
+#define NV_CTRL_GPU_COOLER_MANUAL_CONTROL 319 /* RW-G */
+#define NV_CTRL_GPU_COOLER_MANUAL_CONTROL_FALSE 0
+#define NV_CTRL_GPU_COOLER_MANUAL_CONTROL_TRUE 1
+
+/*
+ * NV_CTRL_THERMAL_COOLER_LEVEL - Returns cooler's current operating
+ * level.
+ */
+
+#define NV_CTRL_THERMAL_COOLER_LEVEL 320 /* RW-C */
+
+/* NV_CTRL_THERMAL_COOLER_LEVEL_SET_DEFAULT - Sets default values of
+ * cooler.
+ */
+
+#define NV_CTRL_THERMAL_COOLER_LEVEL_SET_DEFAULT 321 /* -W-C */
+
+/*
+ * NV_CTRL_THERMAL_COOLER_CONTROL_TYPE -
+ * Returns a cooler's control signal characteristics.
+ * The possible types are restricted, Variable and Toggle.
+ */
+
+#define NV_CTRL_THERMAL_COOLER_CONTROL_TYPE 322 /* R--C */
+#define NV_CTRL_THERMAL_COOLER_CONTROL_TYPE_NONE 0
+#define NV_CTRL_THERMAL_COOLER_CONTROL_TYPE_TOGGLE 1
+#define NV_CTRL_THERMAL_COOLER_CONTROL_TYPE_VARIABLE 2
+
+/*
+ * NV_CTRL_THERMAL_COOLER_TARGET - Returns objects that cooler cools.
+ * Targets may be GPU, Memory, Power Supply or All of these.
+ * GPU_RELATED = GPU | MEMORY | POWER_SUPPLY
+ *
+ */
+
+#define NV_CTRL_THERMAL_COOLER_TARGET 323 /* R--C */
+#define NV_CTRL_THERMAL_COOLER_TARGET_NONE 0
+#define NV_CTRL_THERMAL_COOLER_TARGET_GPU 1
+#define NV_CTRL_THERMAL_COOLER_TARGET_MEMORY 2
+#define NV_CTRL_THERMAL_COOLER_TARGET_POWER_SUPPLY 4
+#define NV_CTRL_THERMAL_COOLER_TARGET_GPU_RELATED \
+ (NV_CTRL_THERMAL_COOLER_TARGET_GPU | NV_CTRL_THERMAL_COOLER_TARGET_MEMORY | \
+ NV_CTRL_THERMAL_COOLER_TARGET_POWER_SUPPLY)
+
+/*
+ * NV_CTRL_GPU_ECC_SUPPORTED - Reports whether ECC is supported by the
+ * targeted GPU.
+ */
+#define NV_CTRL_GPU_ECC_SUPPORTED 324 /* R--G */
+#define NV_CTRL_GPU_ECC_SUPPORTED_FALSE 0
+#define NV_CTRL_GPU_ECC_SUPPORTED_TRUE 1
+
+/*
+ * NV_CTRL_GPU_ECC_STATUS - Returns the current hardware ECC setting
+ * for the targeted GPU.
+ */
+#define NV_CTRL_GPU_ECC_STATUS 325 /* R--G */
+#define NV_CTRL_GPU_ECC_STATUS_DISABLED 0
+#define NV_CTRL_GPU_ECC_STATUS_ENABLED 1
+
+/*
+ * NV_CTRL_GPU_ECC_CONFIGURATION - Reports whether ECC can be configured
+ * dynamically for the GPU in question.
+ */
+#define NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED 326 /* R--G */
+#define NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED_FALSE 0
+#define NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED_TRUE 1
+
+/*
+ * NV_CTRL_GPU_ECC_CONFIGURATION_SETTING - Returns the current ECC
+ * configuration setting or specifies new settings. New settings do not
+ * take effect until the next POST.
+ */
+#define NV_CTRL_GPU_ECC_CONFIGURATION 327 /* RW-G */
+#define NV_CTRL_GPU_ECC_CONFIGURATION_DISABLED 0
+#define NV_CTRL_GPU_ECC_CONFIGURATION_ENABLED 1
+
+/*
+ * NV_CTRL_GPU_ECC_DEFAULT_CONFIGURATION_SETTING - Returns the default
+ * ECC configuration setting.
+ */
+#define NV_CTRL_GPU_ECC_DEFAULT_CONFIGURATION 328 /* R--G */
+#define NV_CTRL_GPU_ECC_DEFAULT_CONFIGURATION_DISABLED 0
+#define NV_CTRL_GPU_ECC_DEFAULT_CONFIGURATION_ENABLED 1
+
+/*
+ * NV_CTRL_GPU_ECC_SINGLE_BIT_ERRORS - Returns the number of single-bit
+ * ECC errors detected by the targeted GPU since the last POST.
+ * Note: this attribute is a 64-bit integer attribute.
+ */
+#define NV_CTRL_GPU_ECC_SINGLE_BIT_ERRORS 329 /* R--GQ */
+
+/*
+ * NV_CTRL_GPU_ECC_DOUBLE_BIT_ERRORS - Returns the number of double-bit
+ * ECC errors detected by the targeted GPU since the last POST.
+ * Note: this attribute is a 64-bit integer attribute.
+ */
+#define NV_CTRL_GPU_ECC_DOUBLE_BIT_ERRORS 330 /* R--GQ */
+
+/*
+ * NV_CTRL_GPU_ECC_AGGREGATE_SINGLE_BIT_ERRORS - Returns the number of
+ * single-bit ECC errors detected by the targeted GPU since the
+ * last counter reset.
+ * Note: this attribute is a 64-bit integer attribute.
+ */
+#define NV_CTRL_GPU_ECC_AGGREGATE_SINGLE_BIT_ERRORS 331 /* R--GQ */
+
+/*
+ * NV_CTRL_GPU_ECC_AGGREGATE_DOUBLE_BIT_ERRORS - Returns the number of
+ * double-bit ECC errors detected by the targeted GPU since the
+ * last counter reset.
+ * Note: this attribute is a 64-bit integer attribute.
+ */
+#define NV_CTRL_GPU_ECC_AGGREGATE_DOUBLE_BIT_ERRORS 332 /* R--GQ */
+
+/*
+ * NV_CTRL_GPU_ECC_RESET_ERROR_STATUS - Resets the volatile/aggregate
+ * single-bit and double-bit error counters. This attribute is a
+ * bitmask attribute.
+ */
+#define NV_CTRL_GPU_ECC_RESET_ERROR_STATUS 333 /* -W-G */
+#define NV_CTRL_GPU_ECC_RESET_ERROR_STATUS_VOLATILE 0x00000001
+#define NV_CTRL_GPU_ECC_RESET_ERROR_STATUS_AGGREGATE 0x00000002
+
+/*
+ * NV_CTRL_GPU_POWER_MIZER_MODE - Provides a hint to the driver
+ * as to how to manage the performance of the GPU.
+ *
+ * ADAPTIVE - adjust GPU clocks based on GPU
+ * utilization
+ * PREFER_MAXIMUM_PERFORMANCE - raise GPU clocks to favor
+ * maximum performance, to the extent
+ * that thermal and other constraints
+ * allow
+ */
+#define NV_CTRL_GPU_POWER_MIZER_MODE 334 /* RW-G */
+#define NV_CTRL_GPU_POWER_MIZER_MODE_ADAPTIVE 0
+#define NV_CTRL_GPU_POWER_MIZER_MODE_PREFER_MAXIMUM_PERFORMANCE 1
+
+/*
+ * NV_CTRL_GVI_SYNC_OUTPUT_FORMAT - Returns the output sync signal
+ * from the GVI device.
+ */
+
+#define NV_CTRL_GVI_SYNC_OUTPUT_FORMAT 335 /* R--I */
+
+/*
+ * NV_CTRL_GVI_MAX_CHANNELS_PER_JACK - Returns the maximum
+ * supported number of (logical) channels within a single physical jack of
+ * a GVI device. For most SDI video formats, there is only one channel
+ * (channel 0). But for 3G video formats (as specified in SMPTE 425),
+ * as an example, there are two channels (channel 0 and channel 1) per
+ * physical jack.
+ */
+
+#define NV_CTRL_GVI_MAX_CHANNELS_PER_JACK 336 /* R--I */
+
+/*
+ * NV_CTRL_GVI_MAX_STREAMS - Returns the maximum number of streams
+ * that can be configured on the GVI device.
+ */
+
+#define NV_CTRL_GVI_MAX_STREAMS 337 /* R--I */
+
+/*
+ * NV_CTRL_GVI_NUM_CAPTURE_SURFACES - The GVI interface exposed through
+ * NV-CONTROL and the GLX_NV_video_input extension uses internal capture
+ * surfaces when frames are read from the GVI device. The
+ * NV_CTRL_GVI_NUM_CAPTURE_SURFACES can be used to query and assign the
+ * number of capture surfaces. This attribute is applied when
+ * glXBindVideoCaptureDeviceNV() is called by the application.
+ *
+ * A lower number of capture surfaces will mean less video memory is used,
+ * but can result in frames being dropped if the application cannot keep up
+ * with the capture device. A higher number will prevent frames from being
+ * dropped, making capture more reliable but will consume move video memory.
+ */
+#define NV_CTRL_GVI_NUM_CAPTURE_SURFACES 338 /* RW-I */
+
+/*
+ * NV_CTRL_OVERSCAN_COMPENSATION - not supported
+ */
+#define NV_CTRL_OVERSCAN_COMPENSATION 339 /* RWDG */
+
+/*
+ * NV_CTRL_GPU_PCIE_GENERATION - Reports the current PCIe generation.
+ */
+#define NV_CTRL_GPU_PCIE_GENERATION 341 /* R--GI */
+#define NV_CTRL_GPU_PCIE_GENERATION1 0x00000001
+#define NV_CTRL_GPU_PCIE_GENERATION2 0x00000002
+#define NV_CTRL_GPU_PCIE_GENERATION3 0x00000003
+
+/*
+ * NV_CTRL_GVI_BOUND_GPU - Returns the NV_CTRL_TARGET_TYPE_GPU target_id of
+ * the GPU currently bound to the GVI device. Returns -1 if no GPU is
+ * currently bound to the GVI device.
+ */
+#define NV_CTRL_GVI_BOUND_GPU 342 /* R--I */
+
+/*
+ * NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT3 - this attribute is only
+ * intended to be used to query the ValidValues for
+ * NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT for VIDEO_FORMAT values between
+ * 64 and 95. See NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT for details.
+ */
+
+#define NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT3 343 /* ---GI */
+
+/*
+ * NV_CTRL_ACCELERATE_TRAPEZOIDS - Toggles RENDER Trapezoid acceleration
+ */
+
+#define NV_CTRL_ACCELERATE_TRAPEZOIDS 344 /* RW- */
+#define NV_CTRL_ACCELERATE_TRAPEZOIDS_DISABLE 0
+#define NV_CTRL_ACCELERATE_TRAPEZOIDS_ENABLE 1
+
+/*
+ * NV_CTRL_GPU_CORES - Returns number of GPU cores supported by the graphics
+ * pipeline.
+ */
+
+#define NV_CTRL_GPU_CORES 345 /* R--G */
+
+/*
+ * NV_CTRL_GPU_MEMORY_BUS_WIDTH - Returns memory bus bandwidth on the associated
+ * subdevice.
+ */
+
+#define NV_CTRL_GPU_MEMORY_BUS_WIDTH 346 /* R--G */
+
+/*
+ * NV_CTRL_GVI_TEST_MODE - This attribute controls the GVI test mode. When
+ * enabled, the GVI device will generate fake data as quickly as possible. All
+ * GVI settings are still valid when this is enabled (e.g., the requested video
+ * format is honored and sets the video size).
+ * This may be used to test the pipeline.
+ */
+
+#define NV_CTRL_GVI_TEST_MODE 347 /* R--I */
+#define NV_CTRL_GVI_TEST_MODE_DISABLE 0
+#define NV_CTRL_GVI_TEST_MODE_ENABLE 1
+
+/*
+ * NV_CTRL_COLOR_SPACE - This option sets color space of the video
+ * signal.
+ */
+#define NV_CTRL_COLOR_SPACE 348 /* RWDG */
+#define NV_CTRL_COLOR_SPACE_RGB 0
+#define NV_CTRL_COLOR_SPACE_YCbCr422 1
+#define NV_CTRL_COLOR_SPACE_YCbCr444 2
+
+/*
+ * NV_CTRL_COLOR_RANGE - This option sets color range of the video
+ * signal.
+ */
+#define NV_CTRL_COLOR_RANGE 349 /* RWDG */
+#define NV_CTRL_COLOR_RANGE_FULL 0
+#define NV_CTRL_COLOR_RANGE_LIMITED 1
+
+/*
+ * NV_CTRL_GPU_SCALING_DEFAULT_TARGET - not supported
+ *
+ * NV_CTRL_GPU_SCALING_DEFAULT_METHOD - not supported
+ */
+#define NV_CTRL_GPU_SCALING_DEFAULT_TARGET 350 /* R-DG */
+#define NV_CTRL_GPU_SCALING_DEFAULT_METHOD 351 /* R-DG */
+
+/*
+ * NV_CTRL_DITHERING_MODE - Controls the dithering mode, when
+ * NV_CTRL_CURRENT_DITHERING is Enabled.
+ *
+ * AUTO: allow the driver to choose the dithering mode automatically.
+ *
+ * DYNAMIC_2X2: use a 2x2 matrix to dither from the GPU's pixel
+ * pipeline to the bit depth of the flat panel. The matrix values
+ * are changed from frame to frame.
+ *
+ * STATIC_2X2: use a 2x2 matrix to dither from the GPU's pixel
+ * pipeline to the bit depth of the flat panel. The matrix values
+ * do not change from frame to frame.
+ *
+ * TEMPORAL: use a pseudorandom value from a uniform distribution calculated at
+ * every pixel to achieve stochastic dithering. This method produces a better
+ * visual result than 2x2 matrix approaches.
+ */
+#define NV_CTRL_DITHERING_MODE 352 /* RWDG */
+#define NV_CTRL_DITHERING_MODE_AUTO 0
+#define NV_CTRL_DITHERING_MODE_DYNAMIC_2X2 1
+#define NV_CTRL_DITHERING_MODE_STATIC_2X2 2
+#define NV_CTRL_DITHERING_MODE_TEMPORAL 3
+
+/*
+ * NV_CTRL_CURRENT_DITHERING - Returns the current dithering state.
+ */
+#define NV_CTRL_CURRENT_DITHERING 353 /* R-DG */
+#define NV_CTRL_CURRENT_DITHERING_DISABLED 0
+#define NV_CTRL_CURRENT_DITHERING_ENABLED 1
+
+/*
+ * NV_CTRL_CURRENT_DITHERING_MODE - Returns the current dithering
+ * mode.
+ */
+#define NV_CTRL_CURRENT_DITHERING_MODE 354 /* R-DG */
+#define NV_CTRL_CURRENT_DITHERING_MODE_NONE 0
+#define NV_CTRL_CURRENT_DITHERING_MODE_DYNAMIC_2X2 1
+#define NV_CTRL_CURRENT_DITHERING_MODE_STATIC_2X2 2
+#define NV_CTRL_CURRENT_DITHERING_MODE_TEMPORAL 3
+
+/*
+ * NV_CTRL_THERMAL_SENSOR_READING - Returns the thermal sensor's current
+ * reading.
+ */
+#define NV_CTRL_THERMAL_SENSOR_READING 355 /* R--S */
+
+/*
+ * NV_CTRL_THERMAL_SENSOR_PROVIDER - Returns the hardware device that
+ * provides the thermal sensor.
+ */
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER 356 /* R--S */
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_NONE 0
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_GPU_INTERNAL 1
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_ADM1032 2
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_ADT7461 3
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_MAX6649 4
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_MAX1617 5
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_LM99 6
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_LM89 7
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_LM64 8
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_G781 9
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_ADT7473 10
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_SBMAX6649 11
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_VBIOSEVT 12
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_OS 13
+#define NV_CTRL_THERMAL_SENSOR_PROVIDER_UNKNOWN 0xFFFFFFFF
+
+/*
+ * NV_CTRL_THERMAL_SENSOR_TARGET - Returns what hardware component
+ * the thermal sensor is measuring.
+ */
+#define NV_CTRL_THERMAL_SENSOR_TARGET 357 /* R--S */
+#define NV_CTRL_THERMAL_SENSOR_TARGET_NONE 0
+#define NV_CTRL_THERMAL_SENSOR_TARGET_GPU 1
+#define NV_CTRL_THERMAL_SENSOR_TARGET_MEMORY 2
+#define NV_CTRL_THERMAL_SENSOR_TARGET_POWER_SUPPLY 4
+#define NV_CTRL_THERMAL_SENSOR_TARGET_BOARD 8
+#define NV_CTRL_THERMAL_SENSOR_TARGET_UNKNOWN 0xFFFFFFFF
+
+/*
+ * NV_CTRL_SHOW_MULTIGPU_VISUAL_INDICATOR - when TRUE, OpenGL will
+ * draw information about the current MULTIGPU mode.
+ */
+#define NV_CTRL_SHOW_MULTIGPU_VISUAL_INDICATOR 358 /* RW-X */
+#define NV_CTRL_SHOW_MULTIGPU_VISUAL_INDICATOR_FALSE 0
+#define NV_CTRL_SHOW_MULTIGPU_VISUAL_INDICATOR_TRUE 1
+
+/*
+ * NV_CTRL_GPU_CURRENT_PROCESSOR_CLOCK_FREQS - Returns GPU's processor
+ * clock freqs.
+ */
+#define NV_CTRL_GPU_CURRENT_PROCESSOR_CLOCK_FREQS 359 /* RW-G */
+
+/*
+ * NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS - query the flags (various information
+ * for the specified NV_CTRL_GVIO_VIDEO_FORMAT_*. So that this can be
+ * queried with existing interfaces, the video format should be specified
+ * in the display_mask field; eg:
+ *
+ * XNVCTRLQueryTargetAttribute(dpy,
+ * NV_CTRL_TARGET_TYPE_GVI,
+ * gvi,
+ * NV_CTRL_GVIO_VIDEO_FORMAT_720P_60_00_SMPTE296,
+ * NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS,
+ * &flags);
+ *
+ * Note: The NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_1080P_NO_12BPC flag is set
+ * for those 1080P 3G modes (level A and B) that do not support
+ * 12 bits per component (when configuring a GVI stream.)
+ */
+
+#define NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS 360 /* R--I */
+#define NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_NONE 0x00000000
+#define NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_INTERLACED 0x00000001
+#define NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_PROGRESSIVE 0x00000002
+#define NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_PSF 0x00000004
+#define NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_LEVEL_A 0x00000008
+#define NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_LEVEL_B 0x00000010
+#define NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G \
+ ((NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_LEVEL_A) | (NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_LEVEL_B))
+#define NV_CTRL_GVIO_VIDEO_FORMAT_FLAGS_3G_1080P_NO_12BPC 0x00000020
+
+/*
+ * NV_CTRL_GPU_PCIE_MAX_LINK_SPEED - returns maximum PCIe link speed,
+ * in gigatransfers per second (GT/s).
+ */
+
+#define NV_CTRL_GPU_PCIE_MAX_LINK_SPEED 361 /* R--GI */
+
+/*
+ * NV_CTRL_3D_VISION_PRO_RESET_TRANSCEIVER_TO_FACTORY_SETTINGS - Resets the
+ * 3D Vision Pro transceiver to its factory settings.
+ */
+#define NV_CTRL_3D_VISION_PRO_RESET_TRANSCEIVER_TO_FACTORY_SETTINGS 363 /* -W-T */
+
+/*
+ * NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL - Controls the channel that is
+ * currently used by the 3D Vision Pro transceiver.
+ */
+#define NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL 364 /* RW-T */
+
+/*
+ * NV_CTRL_3D_VISION_PRO_TRANSCEIVER_MODE - Controls the mode in which the
+ * 3D Vision Pro transceiver operates.
+ * NV_CTRL_3D_VISION_PRO_TM_LOW_RANGE is bidirectional
+ * NV_CTRL_3D_VISION_PRO_TM_MEDIUM_RANGE is bidirectional
+ * NV_CTRL_3D_VISION_PRO_TM_HIGH_RANGE may be bidirectional just up to a
+ * given range, and unidirectional beyond it
+ * NV_CTRL_3D_VISION_PRO_TM_COUNT is the total number of
+ * 3D Vision Pro transceiver modes
+ */
+#define NV_CTRL_3D_VISION_PRO_TRANSCEIVER_MODE 365 /* RW-T */
+#define NV_CTRL_3D_VISION_PRO_TRANSCEIVER_MODE_INVALID 0
+#define NV_CTRL_3D_VISION_PRO_TRANSCEIVER_MODE_LOW_RANGE 1
+#define NV_CTRL_3D_VISION_PRO_TRANSCEIVER_MODE_MEDIUM_RANGE 2
+#define NV_CTRL_3D_VISION_PRO_TRANSCEIVER_MODE_HIGH_RANGE 3
+#define NV_CTRL_3D_VISION_PRO_TRANSCEIVER_MODE_COUNT 4
+
+/*
+ * NV_CTRL_SYNCHRONOUS_PALETTE_UPDATES - controls whether updates to the color
+ * lookup table (LUT) are synchronous with respect to X rendering. For example,
+ * if an X client sends XStoreColors followed by XFillRectangle, the driver will
+ * guarantee that the FillRectangle request is not processed until after the
+ * updated LUT colors are actually visible on the screen if
+ * NV_CTRL_SYNCHRONOUS_PALETTE_UPDATES is enabled. Otherwise, the rendering may
+ * occur first.
+ *
+ * This makes a difference for applications that use the LUT to animate, such as
+ * XPilot. If you experience flickering in applications that use LUT
+ * animations, try enabling this attribute.
+ *
+ * When synchronous updates are enabled, XStoreColors requests will be processed
+ * at your screen's refresh rate.
+ */
+
+#define NV_CTRL_SYNCHRONOUS_PALETTE_UPDATES 367 /* RWDG */
+#define NV_CTRL_SYNCHRONOUS_PALETTE_UPDATES_DISABLE 0
+#define NV_CTRL_SYNCHRONOUS_PALETTE_UPDATES_ENABLE 1
+
+/*
+ * NV_CTRL_DITHERING_DEPTH - Controls the dithering depth when
+ * NV_CTRL_CURRENT_DITHERING is ENABLED. Some displays connected
+ * to the GPU via the DVI or LVDS interfaces cannot display the
+ * full color range of ten bits per channel, so the GPU will
+ * dither to either 6 or 8 bits per channel.
+ */
+#define NV_CTRL_DITHERING_DEPTH 368 /* RWDG */
+#define NV_CTRL_DITHERING_DEPTH_AUTO 0
+#define NV_CTRL_DITHERING_DEPTH_6_BITS 1
+#define NV_CTRL_DITHERING_DEPTH_8_BITS 2
+
+/*
+ * NV_CTRL_CURRENT_DITHERING_DEPTH - Returns the current dithering
+ * depth value.
+ */
+#define NV_CTRL_CURRENT_DITHERING_DEPTH 369 /* R-DG */
+#define NV_CTRL_CURRENT_DITHERING_DEPTH_NONE 0
+#define NV_CTRL_CURRENT_DITHERING_DEPTH_6_BITS 1
+#define NV_CTRL_CURRENT_DITHERING_DEPTH_8_BITS 2
+
+/*
+ * NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL_FREQUENCY - Returns the
+ * frequency of the channel(in kHz) of the 3D Vision Pro transceiver.
+ * Use the display_mask parameter to specify the channel number.
+ */
+#define NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL_FREQUENCY 370 /* R--T */
+
+/*
+ * NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL_QUALITY - Returns the
+ * quality of the channel(in percentage) of the 3D Vision Pro transceiver.
+ * Use the display_mask parameter to specify the channel number.
+ */
+#define NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL_QUALITY 371 /* R--T */
+
+/*
+ * NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL_COUNT - Returns the number of
+ * channels on the 3D Vision Pro transceiver.
+ */
+#define NV_CTRL_3D_VISION_PRO_TRANSCEIVER_CHANNEL_COUNT 372 /* R--T */
+
+/*
+ * NV_CTRL_3D_VISION_PRO_PAIR_GLASSES - Puts the 3D Vision Pro
+ * transceiver into pairing mode to gather additional glasses.
+ * NV_CTRL_3D_VISION_PRO_PAIR_GLASSES_STOP - stops any pairing
+ * NV_CTRL_3D_VISION_PRO_PAIR_GLASSES_BEACON - starts continuous
+ * pairing via beacon mode
+ * Any other value, N - Puts the 3D Vision Pro transceiver into
+ * authenticated pairing mode for N seconds.
+ */
+#define NV_CTRL_3D_VISION_PRO_PAIR_GLASSES 373 /* -W-T */
+#define NV_CTRL_3D_VISION_PRO_PAIR_GLASSES_STOP 0
+#define NV_CTRL_3D_VISION_PRO_PAIR_GLASSES_BEACON 0xFFFFFFFF
+
+/*
+ * NV_CTRL_3D_VISION_PRO_UNPAIR_GLASSES - Tells a specific pair
+ * of glasses to unpair. The glasses will "forget" the address
+ * of the 3D Vision Pro transceiver to which they have been paired.
+ * To unpair all the currently paired glasses, specify
+ * the glasses id as 0.
+ */
+#define NV_CTRL_3D_VISION_PRO_UNPAIR_GLASSES 374 /* -W-T */
+
+/*
+ * NV_CTRL_3D_VISION_PRO_DISCOVER_GLASSES - Tells the 3D Vision Pro
+ * transceiver about the glasses that have been paired using
+ * NV_CTRL_3D_VISION_PRO_PAIR_GLASSES_BEACON. Unless this is done,
+ * the 3D Vision Pro transceiver will not know about glasses paired in
+ * beacon mode.
+ */
+#define NV_CTRL_3D_VISION_PRO_DISCOVER_GLASSES 375 /* -W-T */
+
+/*
+ * NV_CTRL_3D_VISION_PRO_IDENTIFY_GLASSES - Causes glasses LEDs to
+ * flash for a short period of time.
+ */
+#define NV_CTRL_3D_VISION_PRO_IDENTIFY_GLASSES 376 /* -W-T */
+
+/*
+ * NV_CTRL_3D_VISION_PRO_GLASSES_SYNC_CYCLE - Controls the
+ * sync cycle duration(in milliseconds) of the glasses.
+ * Use the display_mask parameter to specify the glasses id.
+ */
+#define NV_CTRL_3D_VISION_PRO_GLASSES_SYNC_CYCLE 378 /* RW-T */
+
+/*
+ * NV_CTRL_3D_VISION_PRO_GLASSES_MISSED_SYNC_CYCLES - Returns the
+ * number of state sync cycles recently missed by the glasses.
+ * Use the display_mask parameter to specify the glasses id.
+ */
+#define NV_CTRL_3D_VISION_PRO_GLASSES_MISSED_SYNC_CYCLES 379 /* R--T */
+
+/*
+ * NV_CTRL_3D_VISION_PRO_GLASSES_BATTERY_LEVEL - Returns the
+ * battery level(in percentage) of the glasses.
+ * Use the display_mask parameter to specify the glasses id.
+ */
+#define NV_CTRL_3D_VISION_PRO_GLASSES_BATTERY_LEVEL 380 /* R--T */
+
+/*
+ * NV_CTRL_GVO_ANC_PARITY_COMPUTATION - Controls the SDI device's computation
+ * of the parity bit (bit 8) for ANC data words.
+ */
+
+#define NV_CTRL_GVO_ANC_PARITY_COMPUTATION 381 /* RW--- */
+#define NV_CTRL_GVO_ANC_PARITY_COMPUTATION_AUTO 0
+#define NV_CTRL_GVO_ANC_PARITY_COMPUTATION_ON 1
+#define NV_CTRL_GVO_ANC_PARITY_COMPUTATION_OFF 2
+
+/*
+ * NV_CTRL_3D_VISION_PRO_GLASSES_PAIR_EVENT - This attribute is sent
+ * as an event when glasses get paired in response to pair command
+ * from any of the clients.
+ */
+#define NV_CTRL_3D_VISION_PRO_GLASSES_PAIR_EVENT 382 /* ---T */
+
+/*
+ * NV_CTRL_3D_VISION_PRO_GLASSES_UNPAIR_EVENT - This attribute is sent
+ * as an event when glasses get unpaired in response to unpair command
+ * from any of the clients.
+ */
+#define NV_CTRL_3D_VISION_PRO_GLASSES_UNPAIR_EVENT 383 /* ---T */
+
+/*
+ * NV_CTRL_GPU_PCIE_CURRENT_LINK_WIDTH - returns the current
+ * PCIe link width, in number of lanes.
+ */
+#define NV_CTRL_GPU_PCIE_CURRENT_LINK_WIDTH 384 /* R--GI */
+
+/*
+ * NV_CTRL_GPU_PCIE_CURRENT_LINK_SPEED - returns the current
+ * PCIe link speed, in megatransfers per second (GT/s).
+ */
+#define NV_CTRL_GPU_PCIE_CURRENT_LINK_SPEED 385 /* R--GI */
+
+/*
+ * NV_CTRL_GVO_AUDIO_BLANKING - specifies whether the GVO device should delete
+ * audio ancillary data packets when frames are repeated.
+ *
+ * When a new frame is not ready in time, the current frame, including all
+ * ancillary data packets, is repeated. When this data includes audio packets,
+ * this can result in stutters or clicks. When this option is enabled, the GVO
+ * device will detect when frames are repeated, identify audio ancillary data
+ * packets, and mark them for deletion.
+ *
+ * This option is applied when the GVO device is bound.
+ */
+#define NV_CTRL_GVO_AUDIO_BLANKING 386 /* RW- */
+#define NV_CTRL_GVO_AUDIO_BLANKING_DISABLE 0
+#define NV_CTRL_GVO_AUDIO_BLANKING_ENABLE 1
+
+/*
+ * NV_CTRL_CURRENT_METAMODE_ID - switch modes to the MetaMode with
+ * the specified ID.
+ */
+#define NV_CTRL_CURRENT_METAMODE_ID 387 /* RW- */
+
+/*
+ * NV_CTRL_DISPLAY_ENABLED - Returns whether or not the display device
+ * is currently enabled.
+ */
+#define NV_CTRL_DISPLAY_ENABLED 388 /* R-D */
+#define NV_CTRL_DISPLAY_ENABLED_TRUE 1
+#define NV_CTRL_DISPLAY_ENABLED_FALSE 0
+
+#define NV_CTRL_LAST_ATTRIBUTE NV_CTRL_DISPLAY_ENABLED
+
+/**************************************************************************/
+
+/*
+ * String Attributes:
+ *
+ * String attributes can be queryied through the XNVCTRLQueryStringAttribute()
+ * and XNVCTRLQueryTargetStringAttribute() function calls.
+ *
+ * String attributes can be set through the XNVCTRLSetStringAttribute()
+ * function call. (There are currently no string attributes that can be
+ * set on non-X Screen targets.)
+ *
+ * Unless otherwise noted, all string attributes can be queried/set using an
+ * NV_CTRL_TARGET_TYPE_X_SCREEN target. Attributes that cannot take an
+ * NV_CTRL_TARGET_TYPE_X_SCREEN target also cannot be queried/set through
+ * XNVCTRLQueryStringAttribute()/XNVCTRLSetStringAttribute() (Since
+ * these assume an X Screen target).
+ */
+
+/*
+ * NV_CTRL_STRING_PRODUCT_NAME - the GPU product name on which the
+ * specified X screen is running.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_STRING_PRODUCT_NAME 0 /* R--G */
+
+/*
+ * NV_CTRL_STRING_VBIOS_VERSION - the video bios version on the GPU on
+ * which the specified X screen is running.
+ */
+
+#define NV_CTRL_STRING_VBIOS_VERSION 1 /* R--G */
+
+/*
+ * NV_CTRL_STRING_NVIDIA_DRIVER_VERSION - string representation of the
+ * NVIDIA driver version number for the NVIDIA X driver in use.
+ */
+
+#define NV_CTRL_STRING_NVIDIA_DRIVER_VERSION 3 /* R--G */
+
+/*
+ * NV_CTRL_STRING_DISPLAY_DEVICE_NAME - name of the display device
+ * specified in the display_mask argument.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_STRING_DISPLAY_DEVICE_NAME 4 /* R-DG */
+
+/*
+ * NV_CTRL_STRING_TV_ENCODER_NAME - name of the TV encoder used by the
+ * specified display device; only valid if the display device is a TV.
+ */
+
+#define NV_CTRL_STRING_TV_ENCODER_NAME 5 /* R-DG */
+
+/*
+ * NV_CTRL_STRING_GVIO_FIRMWARE_VERSION - indicates the version of the
+ * Firmware on the GVIO device.
+ */
+
+#define NV_CTRL_STRING_GVIO_FIRMWARE_VERSION 8 /* R--I */
+
+/*
+ * The following is deprecated; use NV_CTRL_STRING_GVIO_FIRMWARE_VERSION,
+ * instead
+ */
+#define NV_CTRL_STRING_GVO_FIRMWARE_VERSION 8 /* R-- */
+
+/*
+ * NV_CTRL_STRING_CURRENT_MODELINE - Return the ModeLine currently
+ * being used by the specified display device.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetStringAttribute()
+ * using an NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ *
+ * The ModeLine string may be prepended with a comma-separated list of
+ * "token=value" pairs, separated from the ModeLine string by "::".
+ * This "token=value" syntax is the same as that used in
+ * NV_CTRL_BINARY_DATA_MODELINES
+ */
+
+#define NV_CTRL_STRING_CURRENT_MODELINE 9 /* R-DG */
+
+/*
+ * NV_CTRL_STRING_ADD_MODELINE - Adds a ModeLine to the specified
+ * display device. The ModeLine is not added if validation fails.
+ *
+ * The ModeLine string should have the same syntax as a ModeLine in
+ * the X configuration file; e.g.,
+ *
+ * "1600x1200" 229.5 1600 1664 1856 2160 1200 1201 1204 1250 +HSync +VSync
+ */
+
+#define NV_CTRL_STRING_ADD_MODELINE 10 /* -WDG */
+
+/*
+ * NV_CTRL_STRING_DELETE_MODELINE - Deletes an existing ModeLine
+ * from the specified display device. The currently selected
+ * ModeLine cannot be deleted. (This also means you cannot delete
+ * the last ModeLine.)
+ *
+ * The ModeLine string should have the same syntax as a ModeLine in
+ * the X configuration file; e.g.,
+ *
+ * "1600x1200" 229.5 1600 1664 1856 2160 1200 1201 1204 1250 +HSync +VSync
+ */
+
+#define NV_CTRL_STRING_DELETE_MODELINE 11 /* -WDG */
+
+/*
+ * NV_CTRL_STRING_CURRENT_METAMODE - Returns the metamode currently
+ * being used by the specified X screen. The MetaMode string has the
+ * same syntax as the MetaMode X configuration option, as documented
+ * in the NVIDIA driver README.
+ *
+ * The returned string may be prepended with a comma-separated list of
+ * "token=value" pairs, separated from the MetaMode string by "::".
+ * This "token=value" syntax is the same as that used in
+ * NV_CTRL_BINARY_DATA_METAMODES.
+ */
+
+#define NV_CTRL_STRING_CURRENT_METAMODE 12 /* RW-- */
+#define NV_CTRL_STRING_CURRENT_METAMODE_VERSION_1 NV_CTRL_STRING_CURRENT_METAMODE
+
+/*
+ * NV_CTRL_STRING_ADD_METAMODE - Adds a MetaMode to the specified
+ * X Screen.
+ *
+ * It is recommended to not use this attribute, but instead use
+ * NV_CTRL_STRING_OPERATION_ADD_METAMODE.
+ */
+
+#define NV_CTRL_STRING_ADD_METAMODE 13 /* -W-- */
+
+/*
+ * NV_CTRL_STRING_DELETE_METAMODE - Deletes an existing MetaMode from
+ * the specified X Screen. The currently selected MetaMode cannot be
+ * deleted. (This also means you cannot delete the last MetaMode).
+ * The MetaMode string should have the same syntax as the MetaMode X
+ * configuration option, as documented in the NVIDIA driver README.
+ */
+
+#define NV_CTRL_STRING_DELETE_METAMODE 14 /* -WD-- */
+
+/*
+ * NV_CTRL_STRING_VCSC_PRODUCT_NAME - Querys the product name of the
+ * VCSC device.
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ */
+
+#define NV_CTRL_STRING_VCSC_PRODUCT_NAME 15 /* R---V */
+
+/*
+ * NV_CTRL_STRING_VCSC_PRODUCT_ID - Querys the product ID of the VCSC device.
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ */
+
+#define NV_CTRL_STRING_VCSC_PRODUCT_ID 16 /* R---V */
+
+/*
+ * NV_CTRL_STRING_VCSC_SERIAL_NUMBER - Querys the unique serial number
+ * of the VCS device.
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ */
+
+#define NV_CTRL_STRING_VCSC_SERIAL_NUMBER 17 /* R---V */
+
+/*
+ * NV_CTRL_STRING_VCSC_BUILD_DATE - Querys the date of the VCS device.
+ * the returned string is in the following format: "Week.Year"
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ */
+
+#define NV_CTRL_STRING_VCSC_BUILD_DATE 18 /* R---V */
+
+/*
+ * NV_CTRL_STRING_VCSC_FIRMWARE_VERSION - Querys the firmware version
+ * of the VCS device.
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ */
+
+#define NV_CTRL_STRING_VCSC_FIRMWARE_VERSION 19 /* R---V */
+
+/*
+ * NV_CTRL_STRING_VCSC_FIRMWARE_REVISION - Querys the firmware revision
+ * of the VCS device.
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCS target.
+ */
+
+#define NV_CTRL_STRING_VCSC_FIRMWARE_REVISION 20 /* R---V */
+
+/*
+ * NV_CTRL_STRING_VCSC_HARDWARE_VERSION - Querys the hardware version
+ * of the VCS device.
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ */
+
+#define NV_CTRL_STRING_VCSC_HARDWARE_VERSION 21 /* R---V */
+
+/*
+ * NV_CTRL_STRING_VCSC_HARDWARE_REVISION - Querys the hardware revision
+ * of the VCS device.
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ */
+
+#define NV_CTRL_STRING_VCSC_HARDWARE_REVISION 22 /* R---V */
+
+/*
+ * NV_CTRL_STRING_MOVE_METAMODE - Moves a MetaMode to the specified
+ * index location. The MetaMode must already exist in the X Screen's
+ * list of MetaModes (as returned by the NV_CTRL_BINARY_DATA_METAMODES
+ * attribute). If the index is larger than the number of MetaModes in
+ * the list, the MetaMode is moved to the end of the list. The
+ * MetaMode string should have the same syntax as the MetaMode X
+ * configuration option, as documented in the NVIDIA driver README.
+
+ * The MetaMode string must be prepended with a comma-separated list
+ * of "token=value" pairs, separated from the MetaMode string by "::".
+ * Currently, the only valid token is "index", which indicates where
+ * in the MetaMode list the MetaMode should be moved to.
+ *
+ * Other tokens may be added in the future.
+ *
+ * E.g.,
+ * "index=5 :: CRT-0: 1024x768 @1024x768 +0+0"
+ */
+
+#define NV_CTRL_STRING_MOVE_METAMODE 23 /* -W-- */
+
+/*
+ * NV_CTRL_STRING_VALID_HORIZ_SYNC_RANGES - returns the valid
+ * horizontal sync ranges used to perform mode validation for the
+ * specified display device. The ranges are in the same format as the
+ * "HorizSync" X config option:
+ *
+ * "horizsync-range may be a comma separated list of either discrete
+ * values or ranges of values. A range of values is two values
+ * separated by a dash."
+ *
+ * The values are in kHz.
+ *
+ * Additionally, the string may be prepended with a comma-separated
+ * list of "token=value" pairs, separated from the HorizSync string by
+ * "::". Valid tokens:
+ *
+ * Token Value
+ * "source" "edid" - HorizSync is from the display device's EDID
+ * "xconfig" - HorizSync is from the "HorizSync" entry in
+ * the Monitor section of the X config file
+ * "option" - HorizSync is from the "HorizSync" NVIDIA X
+ * config option
+ * "twinview" - HorizSync is from the "SecondMonitorHorizSync"
+ * NVIDIA X config option
+ * "builtin" - HorizSync is from NVIDIA X driver builtin
+ * default values
+ *
+ * Additional tokens and/or values may be added in the future.
+ *
+ * Example: "source=edid :: 30.000-62.000"
+ */
+
+#define NV_CTRL_STRING_VALID_HORIZ_SYNC_RANGES 24 /* R-DG */
+
+/*
+ * NV_CTRL_STRING_VALID_VERT_REFRESH_RANGES - returns the valid
+ * vertical refresh ranges used to perform mode validation for the
+ * specified display device. The ranges are in the same format as the
+ * "VertRefresh" X config option:
+ *
+ * "vertrefresh-range may be a comma separated list of either discrete
+ * values or ranges of values. A range of values is two values
+ * separated by a dash."
+ *
+ * The values are in Hz.
+ *
+ * Additionally, the string may be prepended with a comma-separated
+ * list of "token=value" pairs, separated from the VertRefresh string by
+ * "::". Valid tokens:
+ *
+ * Token Value
+ * "source" "edid" - VertRefresh is from the display device's EDID
+ * "xconfig" - VertRefresh is from the "VertRefresh" entry in
+ * the Monitor section of the X config file
+ * "option" - VertRefresh is from the "VertRefresh" NVIDIA X
+ * config option
+ * "twinview" - VertRefresh is from the "SecondMonitorVertRefresh"
+ * NVIDIA X config option
+ * "builtin" - VertRefresh is from NVIDIA X driver builtin
+ * default values
+ *
+ * Additional tokens and/or values may be added in the future.
+ *
+ * Example: "source=edid :: 50.000-75.000"
+ */
+
+#define NV_CTRL_STRING_VALID_VERT_REFRESH_RANGES 25 /* R-DG */
+
+/*
+ * NV_CTRL_STRING_XINERAMA_SCREEN_INFO - returns the physical X Screen's
+ * initial position and size (in absolute coordinates) within the Xinerama
+ * desktop as the "token=value" string: "x=#, y=#, width=#, height=#"
+ *
+ * Querying this attribute returns FALSE if NV_CTRL_XINERAMA is not
+ * NV_CTRL_XINERAMA_ON.
+ */
+
+#define NV_CTRL_STRING_XINERAMA_SCREEN_INFO 26 /* R--- */
+
+/*
+ * NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER - used to specify the
+ * order that display devices will be returned via Xinerama when
+ * nvidiaXineramaInfo is enabled. Follows the same syntax as the
+ * nvidiaXineramaInfoOrder X config option.
+ */
+
+#define NV_CTRL_STRING_NVIDIA_XINERAMA_INFO_ORDER 27 /* RW-- */
+
+#define NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER \
+ NV_CTRL_STRING_NVIDIA_XINERAMA_INFO_ORDER /* for backwards compatibility: */
+
+/*
+ * NV_CTRL_STRING_SLI_MODE - returns a string describing the current
+ * SLI mode, if any, or FALSE if SLI is not currently enabled.
+ *
+ * This string should be used for informational purposes only, and
+ * should not be used to distinguish between SLI modes, other than to
+ * recognize when SLI is disabled (FALSE is returned) or
+ * enabled (the returned string is non-NULL and describes the current
+ * SLI configuration).
+ */
+
+#define NV_CTRL_STRING_SLI_MODE 28 /* R---*/
+
+/*
+ * NV_CTRL_STRING_PERFORMANCE_MODES - returns a string with all the
+ * performance modes defined for this GPU along with their associated
+ * NV Clock and Memory Clock values.
+ *
+ * Each performance modes are returned as a comma-separated list of
+ * "token=value" pairs. Each set of performance mode tokens are separated
+ * by a ";". Valid tokens:
+ *
+ * Token Value
+ * "perf" integer - the Performance level
+ * "nvclock" integer - the GPU clocks (in MHz) for the perf level
+ * "memclock" integer - the memory clocks (in MHz) for the perf level
+ *
+ *
+ * Example:
+ *
+ * perf=0, nvclock=500, memclock=505 ; perf=1, nvclock=650, memclock=505
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_STRING_PERFORMANCE_MODES 29 /* R--G */
+
+/*
+ * NV_CTRL_STRING_VCSC_FAN_STATUS - returns a string with status of all the
+ * fans in the Visual Computing System, if such a query is supported. Fan
+ * information is reported along with its tachometer reading (in RPM) and a
+ * flag indicating whether the fan has failed or not.
+ *
+ * Valid tokens:
+ *
+ * Token Value
+ * "fan" integer - the Fan index
+ * "speed" integer - the tachometer reading of the fan in rpm
+ * "fail" integer - flag to indicate whether the fan has failed
+ *
+ * Example:
+ *
+ * fan=0, speed=694, fail=0 ; fan=1, speed=693, fail=0
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ *
+ */
+
+#define NV_CTRL_STRING_VCSC_FAN_STATUS 30 /* R---V */
+
+/*
+ * NV_CTRL_STRING_VCSC_TEMPERATURES - returns a string with all Temperature
+ * readings in the Visual Computing System, if such a query is supported.
+ * Intake, Exhaust and Board Temperature values are reported in Celcius.
+ *
+ * Valid tokens:
+ *
+ * Token Value
+ * "intake" integer - the intake temperature for the VCS
+ * "exhaust" integer - the exhaust temperature for the VCS
+ * "board" integer - the board temperature of the VCS
+ *
+ * Example:
+ *
+ * intake=29, exhaust=46, board=41
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ *
+ */
+
+#define NV_CTRL_STRING_VCSC_TEMPERATURES 31 /* R---V */
+
+/*
+ * NV_CTRL_STRING_VCSC_PSU_INFO - returns a string with all Power Supply Unit
+ * related readings in the Visual Computing System, if such a query is
+ * supported. Current in amperes, Power in watts, Voltage in volts and PSU
+ * state may be reported. Not all PSU types support all of these values, and
+ * therefore some readings may be unknown.
+ *
+ * Valid tokens:
+ *
+ * Token Value
+ * "current" integer - the current drawn in amperes by the VCS
+ * "power" integer - the power drawn in watts by the VCS
+ * "voltage" integer - the voltage reading of the VCS
+ * "state" integer - flag to indicate whether PSU is operating normally
+ *
+ * Example:
+ *
+ * current=10, power=15, voltage=unknown, state=normal
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ *
+ */
+
+#define NV_CTRL_STRING_VCSC_PSU_INFO 32 /* R---V */
+
+/*
+ * NV_CTRL_STRING_GVIO_VIDEO_FORMAT_NAME - query the name for the specified
+ * NV_CTRL_GVIO_VIDEO_FORMAT_*. So that this can be queried with existing
+ * interfaces, XNVCTRLQueryStringAttribute() should be used, and the video
+ * format specified in the display_mask field; eg:
+ *
+ * XNVCTRLQueryStringAttribute(dpy,
+ * screen,
+ * NV_CTRL_GVIO_VIDEO_FORMAT_720P_60_00_SMPTE296,
+ * NV_CTRL_GVIO_VIDEO_FORMAT_NAME,
+ * &name);
+ */
+
+#define NV_CTRL_STRING_GVIO_VIDEO_FORMAT_NAME 33 /* R--GI */
+
+/*
+ * The following is deprecated; use NV_CTRL_STRING_GVIO_VIDEO_FORMAT_NAME,
+ * instead
+ */
+#define NV_CTRL_STRING_GVO_VIDEO_FORMAT_NAME 33 /* R--- */
+
+/*
+ * NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS - returns a string with the
+ * associated NV Clock, Memory Clock and Processor Clock values.
+ *
+ * Current valid tokens are "nvclock", "memclock", and "processorclock".
+ * Not all tokens will be reported on all GPUs, and additional tokens
+ * may be added in the future.
+ *
+ * Clock values are returned as a comma-separated list of
+ * "token=value" pairs.
+ * Valid tokens:
+ *
+ * Token Value
+ * "nvclock" integer - the GPU clocks (in MHz) for the current
+ * perf level
+ * "memclock" integer - the memory clocks (in MHz) for the current
+ * perf level
+ * "processorclock" integer - the processor clocks (in MHz) for the perf level
+ *
+ *
+ * Example:
+ *
+ * nvclock=459, memclock=400, processorclock=918
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetStringAttribute()
+ * using an NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS 34 /* RW-G */
+
+/*
+ * NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_HARDWARE_REVISION - Returns the
+ * hardware revision of the 3D Vision Pro transceiver.
+ */
+#define NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_HARDWARE_REVISION 35 /* R--T */
+
+/*
+ * NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_FIRMWARE_VERSION_A - Returns the
+ * firmware version of chip A of the 3D Vision Pro transceiver.
+ */
+#define NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_FIRMWARE_VERSION_A 36 /* R--T */
+
+/*
+ * NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_FIRMWARE_DATE_A - Returns the
+ * date of the firmware of chip A of the 3D Vision Pro transceiver.
+ */
+#define NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_FIRMWARE_DATE_A 37 /* R--T */
+
+/*
+ * NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_FIRMWARE_VERSION_B - Returns the
+ * firmware version of chip B of the 3D Vision Pro transceiver.
+ */
+#define NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_FIRMWARE_VERSION_B 38 /* R--T */
+
+/*
+ * NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_FIRMWARE_DATE_B - Returns the
+ * date of the firmware of chip B of the 3D Vision Pro transceiver.
+ */
+#define NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_FIRMWARE_DATE_B 39 /* R--T */
+
+/*
+ * NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_ADDRESS - Returns the RF address
+ * of the 3D Vision Pro transceiver.
+ */
+#define NV_CTRL_STRING_3D_VISION_PRO_TRANSCEIVER_ADDRESS 40 /* R--T */
+
+/*
+ * NV_CTRL_STRING_3D_VISION_PRO_GLASSES_FIRMWARE_VERSION_A - Returns the
+ * firmware version of chip A of the glasses.
+ * Use the display_mask parameter to specify the glasses id.
+ */
+#define NV_CTRL_STRING_3D_VISION_PRO_GLASSES_FIRMWARE_VERSION_A 41 /* R--T */
+
+/*
+ * NV_CTRL_STRING_3D_VISION_PRO_GLASSES_FIRMWARE_DATE_A - Returns the
+ * date of the firmware of chip A of the glasses.
+ * Use the display_mask parameter to specify the glasses id.
+ */
+#define NV_CTRL_STRING_3D_VISION_PRO_GLASSES_FIRMWARE_DATE_A 42 /* R--T */
+
+/*
+ * NV_CTRL_STRING_3D_VISION_PRO_GLASSES_ADDRESS - Returns the RF address
+ * of the glasses.
+ * Use the display_mask parameter to specify the glasses id.
+ */
+#define NV_CTRL_STRING_3D_VISION_PRO_GLASSES_ADDRESS 43 /* R--T */
+
+/*
+ * NV_CTRL_STRING_3D_VISION_PRO_GLASSES_NAME - Controls the name the
+ * glasses should use.
+ * Use the display_mask parameter to specify the glasses id.
+ * Glasses' name should start and end with an alpha-numeric character.
+ */
+#define NV_CTRL_STRING_3D_VISION_PRO_GLASSES_NAME 44 /* RW-T */
+
+/*
+ * NV_CTRL_STRING_CURRENT_METAMODE_VERSION_2 - Returns the metamode currently
+ * being used by the specified X screen. The MetaMode string has the same
+ * syntax as the MetaMode X configuration option, as documented in the NVIDIA
+ * driver README. Also, see NV_CTRL_BINARY_DATA_METAMODES_VERSION_2 for more
+ * details on the base syntax.
+ *
+ * The returned string may also be prepended with a comma-separated list of
+ * "token=value" pairs, separated from the MetaMode string by "::".
+ */
+#define NV_CTRL_STRING_CURRENT_METAMODE_VERSION_2 45 /* RW-- */
+
+/*
+ * NV_CTRL_STRING_DISPLAY_NAME_TYPE_BASENAME - Returns a type name for the
+ * display device ("CRT", "DFP", or "TV"). However, note that the determination
+ * of the name is based on the protocol through which the X driver communicates
+ * to the display device. E.g., if the driver communicates using VGA ,then the
+ * basename is "CRT"; if the driver communicates using TMDS, LVDS, or DP, then
+ * the name is "DFP".
+ */
+#define NV_CTRL_STRING_DISPLAY_NAME_TYPE_BASENAME 46 /* R-D- */
+
+/*
+ * NV_CTRL_STRING_DISPLAY_NAME_TYPE_ID - Returns the type-based name + ID for
+ * the display device, e.g. "CRT-0", "DFP-1", "TV-2". If this device is a
+ * DisplayPort 1.2 device, then this name will also be prepended with the
+ * device's port address like so: "DFP-1.0.1.2.3". See
+ * NV_CTRL_STRING_DISPLAY_NAME_TYPE_BASENAME for more information about the
+ * construction of type-based names.
+ */
+#define NV_CTRL_STRING_DISPLAY_NAME_TYPE_ID 47 /* R-D- */
+
+/*
+ * NV_CTRL_STRING_DISPLAY_NAME_DP_GUID - Returns the GUID of the DisplayPort
+ * display device. e.g. "DP-GUID-f16a5bde-79f3-11e1-b2ae-8b5a8969ba9c"
+ *
+ * The display device must be a DisplayPort 1.2 device.
+ */
+#define NV_CTRL_STRING_DISPLAY_NAME_DP_GUID 48 /* R-D- */
+
+/*
+ * NV_CTRL_STRING_DISPLAY_NAME_EDID_HASH - Returns the SHA-1 hash of the
+ * display device's EDID in 8-4-4-4-12 UID format. e.g.
+ * "DPY-EDID-f16a5bde-79f3-11e1-b2ae-8b5a8969ba9c"
+ *
+ * The display device must have a valid EDID.
+ */
+#define NV_CTRL_STRING_DISPLAY_NAME_EDID_HASH 49 /* R-D- */
+
+/*
+ * NV_CTRL_STRING_DISPLAY_NAME_TARGET_INDEX - Returns the current NV-CONTROL
+ * target ID (name) of the display device. e.g. "DPY-1", "DPY-4"
+ *
+ * This name for the display device is not guarenteed to be the same between
+ * different runs of the X server.
+ */
+#define NV_CTRL_STRING_DISPLAY_NAME_TARGET_INDEX 50 /* R-D- */
+
+/*
+ * NV_CTRL_STRING_DISPLAY_NAME_RANDR - Returns the RandR output name for the
+ * display device. e.g. "VGA-1", "DVI-I-0", "DVI-D-3", "LVDS-1", "DP-2",
+ * "HDMI-3", "eDP-6". This name should match If this device is a DisplayPort
+ * 1.2 device, then this name will also be prepended with the device's port
+ * address like so: "DVI-I-3.0.1.2.3"
+ */
+#define NV_CTRL_STRING_DISPLAY_NAME_RANDR 51 /* R-D- */
+
+#define NV_CTRL_STRING_LAST_ATTRIBUTE NV_CTRL_STRING_DISPLAY_NAME_RANDR
+
+/**************************************************************************/
+
+/*
+ * Binary Data Attributes:
+ *
+ * Binary data attributes can be queryied through the XNVCTRLQueryBinaryData()
+ * and XNVCTRLQueryTargetBinaryData() function calls.
+ *
+ * There are currently no binary data attributes that can be set.
+ *
+ * Unless otherwise noted, all Binary data attributes can be queried
+ * using an NV_CTRL_TARGET_TYPE_X_SCREEN target. Attributes that cannot take
+ * an NV_CTRL_TARGET_TYPE_X_SCREEN target also cannot be queried through
+ * XNVCTRLQueryBinaryData() (Since an X Screen target is assumed).
+ */
+
+/*
+ * NV_CTRL_BINARY_DATA_EDID - Returns a display device's EDID information
+ * data.
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_BINARY_DATA_EDID 0 /* R-DG */
+
+/*
+ * NV_CTRL_BINARY_DATA_MODELINES - Returns a display device's supported
+ * ModeLines. ModeLines are returned in a buffer, separated by a single
+ * '\0' and terminated by two consecutive '\0' s like so:
+ *
+ * "ModeLine 1\0ModeLine 2\0ModeLine 3\0Last ModeLine\0\0"
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ *
+ * Each ModeLine string may be prepended with a comma-separated list
+ * of "token=value" pairs, separated from the ModeLine string with a
+ * "::". Valid tokens:
+ *
+ * Token Value
+ * "source" "xserver" - the ModeLine is from the core X server
+ * "xconfig" - the ModeLine was specified in the X config file
+ * "builtin" - the NVIDIA driver provided this builtin ModeLine
+ * "vesa" - this is a VESA standard ModeLine
+ * "edid" - the ModeLine was in the display device's EDID
+ * "nv-control" - the ModeLine was specified via NV-CONTROL
+ *
+ * "xconfig-name" - for ModeLines that were specified in the X config
+ * file, this is the name the X config file
+ * gave for the ModeLine.
+ *
+ * Note that a ModeLine can have several sources; the "source" token
+ * can appear multiple times in the "token=value" pairs list.
+ * Additional source values may be specified in the future.
+ *
+ * Additional tokens may be added in the future, so it is recommended
+ * that any token parser processing the returned string from
+ * NV_CTRL_BINARY_DATA_MODELINES be implemented to gracefully ignore
+ * unrecognized tokens.
+ *
+ * E.g.,
+ *
+ * "source=xserver, source=vesa, source=edid :: "1024x768_70" 75.0 1024 1048 1184 1328 768 771
+ * 777 806 -HSync -VSync"
+ * "source=xconfig, xconfig-name=1600x1200_60.00 :: "1600x1200_60_0" 161.0 1600 1704 1880 2160
+ * 1200 1201 1204 1242 -HSync +VSync"
+ */
+
+#define NV_CTRL_BINARY_DATA_MODELINES 1 /* R-DG */
+
+/*
+ * NV_CTRL_BINARY_DATA_METAMODES - Returns an X Screen's supported
+ * MetaModes. MetaModes are returned in a buffer separated by a
+ * single '\0' and terminated by two consecutive '\0' s like so:
+ *
+ * "MetaMode 1\0MetaMode 2\0MetaMode 3\0Last MetaMode\0\0"
+ *
+ * The MetaMode string should have the same syntax as the MetaMode X
+ * configuration option, as documented in the NVIDIA driver README.
+
+ * Each MetaMode string may be prepended with a comma-separated list
+ * of "token=value" pairs, separated from the MetaMode string with
+ * "::". Currently, valid tokens are:
+ *
+ * Token Value
+ * "id" <number> - the id of this MetaMode; this is stored in
+ * the Vertical Refresh field, as viewed
+ * by the XRandR and XF86VidMode X *
+ * extensions.
+ *
+ * "switchable" "yes"/"no" - whether this MetaMode may be switched to via
+ * ctrl-alt-+/-; Implicit MetaModes (see
+ * the "IncludeImplicitMetaModes" X
+ * config option), for example, are not
+ * normally made available through
+ * ctrl-alt-+/-.
+ *
+ * "source" "xconfig" - the MetaMode was specified in the X
+ * config file.
+ * "implicit" - the MetaMode was implicitly added; see the
+ * "IncludeImplicitMetaModes" X config option
+ * for details.
+ * "nv-control" - the MetaMode was added via the NV-CONTROL X
+ * extension to the currently running X server.
+ * "RandR" - the MetaMode was modified in response to an
+ * RandR RRSetCrtcConfig request.
+ *
+ * Additional tokens may be added in the future, so it is recommended
+ * that any token parser processing the returned string from
+ * NV_CTRL_BINARY_DATA_METAMODES be implemented to gracefully ignore
+ * unrecognized tokens.
+ *
+ * E.g.,
+ *
+ * "id=50, switchable=yes, source=xconfig :: CRT-0: 1024x768 @1024x768 +0+0"
+ */
+
+#define NV_CTRL_BINARY_DATA_METAMODES 2 /* R-D- */
+#define NV_CTRL_BINARY_DATA_METAMODES_VERSION_1 NV_CTRL_BINARY_DATA_METAMODES
+
+/*
+ * NV_CTRL_BINARY_DATA_XSCREENS_USING_GPU - Returns the list of X
+ * screens currently driven by the given GPU.
+ *
+ * The format of the returned data is:
+ *
+ * 4 CARD32 number of screens
+ * 4 * n CARD32 screen indices
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_GPU target. This attribute cannot be
+ * queried using a NV_CTRL_TARGET_TYPE_X_SCREEN.
+ */
+
+#define NV_CTRL_BINARY_DATA_XSCREENS_USING_GPU 3 /* R-DG */
+
+/*
+ * NV_CTRL_BINARY_DATA_GPUS_USED_BY_XSCREEN - Returns the list of GPUs
+ * currently in use by the given X screen.
+ *
+ * The format of the returned data is:
+ *
+ * 4 CARD32 number of GPUs
+ * 4 * n CARD32 GPU indices
+ */
+
+#define NV_CTRL_BINARY_DATA_GPUS_USED_BY_XSCREEN 4 /* R--- */
+
+/*
+ * NV_CTRL_BINARY_DATA_GPUS_USING_FRAMELOCK - Returns the list of
+ * GPUs currently connected to the given frame lock board.
+ *
+ * The format of the returned data is:
+ *
+ * 4 CARD32 number of GPUs
+ * 4 * n CARD32 GPU indices
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK target. This attribute cannot be
+ * queried using a NV_CTRL_TARGET_TYPE_X_SCREEN.
+ */
+
+#define NV_CTRL_BINARY_DATA_GPUS_USING_FRAMELOCK 5 /* R-DF */
+
+/*
+ * NV_CTRL_BINARY_DATA_DISPLAY_VIEWPORT - Returns the Display Device's
+ * viewport box into the given X Screen (in X Screen coordinates.)
+ *
+ * The format of the returned data is:
+ *
+ * 4 CARD32 Offset X
+ * 4 CARD32 Offset Y
+ * 4 CARD32 Width
+ * 4 CARD32 Height
+ */
+
+#define NV_CTRL_BINARY_DATA_DISPLAY_VIEWPORT 6 /* R-DG */
+
+/*
+ * NV_CTRL_BINARY_DATA_FRAMELOCKS_USED_BY_GPU - Returns the list of
+ * Framelock devices currently connected to the given GPU.
+ *
+ * The format of the returned data is:
+ *
+ * 4 CARD32 number of Framelocks
+ * 4 * n CARD32 Framelock indices
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_GPU target. This attribute cannot be
+ * queried using a NV_CTRL_TARGET_TYPE_X_SCREEN.
+ */
+
+#define NV_CTRL_BINARY_DATA_FRAMELOCKS_USED_BY_GPU 7 /* R-DG */
+
+/*
+ * NV_CTRL_BINARY_DATA_GPUS_USING_VCSC - Returns the list of
+ * GPU devices connected to the given VCS.
+ *
+ * The format of the returned data is:
+ *
+ * 4 CARD32 number of GPUs
+ * 4 * n CARD32 GPU indices
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target. This attribute cannot be
+ * queried using a NV_CTRL_TARGET_TYPE_X_SCREEN and cannot be queried using
+ * a NV_CTRL_TARGET_TYPE_X_GPU
+ */
+
+#define NV_CTRL_BINARY_DATA_GPUS_USING_VCSC 8 /* R-DV */
+
+/*
+ * NV_CTRL_BINARY_DATA_VCSCS_USED_BY_GPU - Returns the VCSC device
+ * that is controlling the given GPU.
+ *
+ * The format of the returned data is:
+ *
+ * 4 CARD32 number of VCS (always 1)
+ * 4 * n CARD32 VCS indices
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_GPU target. This attribute cannot be
+ * queried using a NV_CTRL_TARGET_TYPE_X_SCREEN
+ */
+
+#define NV_CTRL_BINARY_DATA_VCSCS_USED_BY_GPU 9 /* R-DG */
+
+/*
+ * NV_CTRL_BINARY_DATA_COOLERS_USED_BY_GPU - Returns the coolers that
+ * are cooling the given GPU.
+ *
+ * The format of the returned data is:
+ *
+ * 4 CARD32 number of COOLER
+ * 4 * n CARD32 COOLER indices
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_GPU target. This attribute cannot be
+ * queried using a NV_CTRL_TARGET_TYPE_X_SCREEN
+ */
+
+#define NV_CTRL_BINARY_DATA_COOLERS_USED_BY_GPU 10 /* R-DG */
+
+/*
+ * NV_CTRL_BINARY_DATA_GPUS_USED_BY_LOGICAL_XSCREEN - Returns the list of
+ * GPUs currently driving the given X screen. If Xinerama is enabled, this
+ * will return all GPUs that are driving any X screen.
+ *
+ * The format of the returned data is:
+ *
+ * 4 CARD32 number of GPUs
+ * 4 * n CARD32 GPU indices
+ */
+
+#define NV_CTRL_BINARY_DATA_GPUS_USED_BY_LOGICAL_XSCREEN 11 /* R--- */
+
+/*
+ * NV_CTRL_BINARY_DATA_THERMAL_SENSORS_USED_BY_GPU - Returns the sensors that
+ * are attached to the given GPU.
+ *
+ * The format of the returned data is:
+ *
+ * 4 CARD32 number of SENSOR
+ * 4 * n CARD32 SENSOR indices
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_GPU target. This attribute cannot be
+ * queried using a NV_CTRL_TARGET_TYPE_X_SCREEN
+ */
+
+#define NV_CTRL_BINARY_DATA_THERMAL_SENSORS_USED_BY_GPU 12 /* R--G */
+
+/*
+ * NV_CTRL_BINARY_DATA_GLASSES_PAIRED_TO_3D_VISION_PRO_TRANSCEIVER - Returns
+ * the id of the glasses that are currently paired to the given
+ * 3D Vision Pro transceiver.
+ *
+ * The format of the returned data is:
+ *
+ * 4 CARD32 number of glasses
+ * 4 * n CARD32 id of glasses
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_3D_VISION_PRO_TRANSCEIVER target.
+ */
+#define NV_CTRL_BINARY_DATA_GLASSES_PAIRED_TO_3D_VISION_PRO_TRANSCEIVER 13 /* R--T */
+
+/*
+ * NV_CTRL_BINARY_DATA_DISPLAY_TARGETS - Returns all the display devices
+ * currently connected to any GPU on the X server.
+ *
+ * The format of the returned data is:
+ *
+ * 4 CARD32 number of display devices
+ * 4 * n CARD32 display device indices
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetBinaryData().
+ */
+
+#define NV_CTRL_BINARY_DATA_DISPLAY_TARGETS 14 /* R--- */
+
+/*
+ * NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU - Returns the list of
+ * display devices that are connected to the GPU target.
+ *
+ * The format of the returned data is:
+ *
+ * 4 CARD32 number of display devices
+ * 4 * n CARD32 display device indices
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_GPU target.
+ */
+
+#define NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU 15 /* R--G */
+
+/*
+ * NV_CTRL_BINARY_DATA_METAMODES_VERSION_2 - Returns values similar to
+ * NV_CTRL_BINARY_DATA_METAMODES(_VERSION_1) but also returns extended syntax
+ * information to indicate a specific display device, as well as other per-
+ * display deviceflags as "token=value" pairs. For example:
+ *
+ * "DPY-1: 1280x1024 {Stereo=PassiveLeft},
+ * DPY-2: 1280x1024 {Stereo=PassiveRight},"
+ *
+ * The display device names have the form "DPY-%d", where the integer
+ * part of the name is the NV-CONTROL target ID for that display device
+ * for this instance of the X server. Note that display device NV-CONTROL
+ * target IDs are not guaranteed to be the same from one run of the X
+ * server to the next.
+ */
+
+#define NV_CTRL_BINARY_DATA_METAMODES_VERSION_2 16 /* R-D- */
+
+/*
+ * NV_CTRL_BINARY_DATA_DISPLAYS_ENABLED_ON_XSCREEN - Returns the list of
+ * display devices that are currently scanning out the X screen target.
+ *
+ * The format of the returned data is:
+ *
+ * 4 CARD32 number of display devices
+ * 4 * n CARD32 display device indices
+ *
+ * This attribute can only be queried through XNVCTRLQueryTargetBinaryData()
+ * using a NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+#define NV_CTRL_BINARY_DATA_DISPLAYS_ENABLED_ON_XSCREEN 17 /* R--- */
+
+#define NV_CTRL_BINARY_DATA_LAST_ATTRIBUTE NV_CTRL_BINARY_DATA_DISPLAYS_ENABLED_ON_XSCREEN
+
+/**************************************************************************/
+
+/*
+ * String Operation Attributes:
+ *
+ * These attributes are used with the XNVCTRLStringOperation()
+ * function; a string is specified as input, and a string is returned
+ * as output.
+ *
+ * Unless otherwise noted, all attributes can be operated upon using
+ * an NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+/*
+ * NV_CTRL_STRING_OPERATION_ADD_METAMODE - provide a MetaMode string
+ * as input, and returns a string containing comma-separated list of
+ * "token=value" pairs as output. Currently, the only output token is
+ * "id", which indicates the id that was assigned to the MetaMode.
+ *
+ * All ModeLines referenced in the MetaMode must already exist for
+ * each display device (as returned by the
+ * NV_CTRL_BINARY_DATA_MODELINES attribute).
+ *
+ * The MetaMode string should have the same syntax as the MetaMode X
+ * configuration option, as documented in the NVIDIA driver README.
+ *
+ * The input string can optionally be prepended with a string of
+ * comma-separated "token=value" pairs, separated from the MetaMode
+ * string by "::". Currently, the only valid token is "index" which
+ * indicates the insertion index for the MetaMode.
+ *
+ * E.g.,
+ *
+ * Input: "index=5 :: 1600x1200+0+0, 1600x1200+1600+0"
+ * Output: "id=58"
+ *
+ * which causes the MetaMode to be inserted at position 5 in the
+ * MetaMode list (all entries after 5 will be shifted down one slot in
+ * the list), and the X server's containing mode stores 58 as the
+ * VRefresh, so that the MetaMode can be uniquely identifed through
+ * XRandR and XF86VidMode.
+ */
+
+#define NV_CTRL_STRING_OPERATION_ADD_METAMODE 0
+
+/*
+ * NV_CTRL_STRING_OPERATION_GTF_MODELINE - provide as input a string
+ * of comma-separated "token=value" pairs, and returns a ModeLine
+ * string, computed using the GTF formula using the parameters from
+ * the input string. Valid tokens for the input string are "width",
+ * "height", and "refreshrate".
+ *
+ * E.g.,
+ *
+ * Input: "width=1600, height=1200, refreshrate=60"
+ * Output: "160.96 1600 1704 1880 2160 1200 1201 1204 1242 -HSync +VSync"
+ *
+ * This operation does not have any impact on any display device's
+ * modePool, and the ModeLine is not validated; it is simply intended
+ * for generating ModeLines.
+ */
+
+#define NV_CTRL_STRING_OPERATION_GTF_MODELINE 1
+
+/*
+ * NV_CTRL_STRING_OPERATION_CVT_MODELINE - provide as input a string
+ * of comma-separated "token=value" pairs, and returns a ModeLine
+ * string, computed using the CVT formula using the parameters from
+ * the input string. Valid tokens for the input string are "width",
+ * "height", "refreshrate", and "reduced-blanking". The
+ * "reduced-blanking" argument can be "0" or "1", to enable or disable
+ * use of reduced blanking for the CVT formula.
+ *
+ * E.g.,
+ *
+ * Input: "width=1600, height=1200, refreshrate=60, reduced-blanking=1"
+ * Output: "130.25 1600 1648 1680 1760 1200 1203 1207 1235 +HSync -VSync"
+ *
+ * This operation does not have any impact on any display device's
+ * modePool, and the ModeLine is not validated; it is simply intended
+ * for generating ModeLines.
+ */
+
+#define NV_CTRL_STRING_OPERATION_CVT_MODELINE 2
+
+/*
+ * NV_CTRL_STRING_OPERATION_BUILD_MODEPOOL - build a ModePool for the
+ * specified display device on the specified target (either an X
+ * screen or a GPU). This is typically used to generate a ModePool
+ * for a display device on a GPU on which no X screens are present.
+ *
+ * Currently, a display device's ModePool is static for the life of
+ * the X server, so XNVCTRLStringOperation will return FALSE if
+ * requested to build a ModePool on a display device that already has
+ * a ModePool.
+ *
+ * The string input to BUILD_MODEPOOL may be NULL. If it is not NULL,
+ * then it is interpreted as a double-colon ("::") separated list
+ * of "option=value" pairs, where the options and the syntax of their
+ * values are the X configuration options that impact the behavior of
+ * modePool construction; namely:
+ *
+ * "ModeValidation"
+ * "HorizSync"
+ * "VertRefresh"
+ * "FlatPanelProperties"
+ * "TVStandard"
+ * "ExactModeTimingsDVI"
+ * "UseEdidFreqs"
+ *
+ * An example input string might look like:
+ *
+ * "ModeValidation=NoVesaModes :: HorizSync=50-110 :: VertRefresh=50-150"
+ *
+ * This request currently does not return a string.
+ */
+
+#define NV_CTRL_STRING_OPERATION_BUILD_MODEPOOL 3 /* DG */
+
+/*
+ * NV_CTRL_STRING_OPERATION_GVI_CONFIGURE_STREAMS - Configure the streams-
+ * to-jack+channel topology for a GVI (Graphics capture board).
+ *
+ * The string input to GVI_CONFIGURE_STREAMS may be NULL. If this is the
+ * case, then the current topology is returned.
+ *
+ * If the input string to GVI_CONFIGURE_STREAMS is not NULL, the string
+ * is interpreted as a semicolon (";") separated list of comma-separated
+ * lists of "option=value" pairs that define a stream's composition. The
+ * available options and their values are:
+ *
+ * "stream": Defines which stream this comma-separated list describes.
+ * Valid values are the integers between 0 and
+ * NV_CTRL_GVI_NUM_STREAMS-1 (inclusive).
+ *
+ * "linkN": Defines a jack+channel pair to use for the given link N.
+ * Valid options are the string "linkN", where N is an integer
+ * between 0 and NV_CTRL_GVI_MAX_LINKS_PER_STREAM-1 (inclusive).
+ * Valid values for these options are strings of the form
+ * "jackX" and/or "jackX.Y", where X is an integer between 0 and
+ * NV_CTRL_GVI_NUM_JACKS-1 (inclusive), and Y (optional) is an
+ * integer between 0 and NV_CTRL_GVI_MAX_CHANNELS_PER_JACK-1
+ * (inclusive).
+ *
+ * An example input string might look like:
+ *
+ * "stream=0, link0=jack0, link1=jack1; stream=1, link0=jack2.1"
+ *
+ * This example specifies two streams, stream 0 and stream 1. Stream 0
+ * is defined to capture link0 data from the first channel (channel 0) of
+ * BNC jack 0 and link1 data from the first channel of BNC jack 1. The
+ * second stream (Stream 1) is defined to capture link0 data from channel 1
+ * (second channel) of BNC jack 2.
+ *
+ * This example shows a possible configuration for capturing 3G input:
+ *
+ * "stream=0, link0=jack0.0, link1=jack0.1"
+ *
+ * Applications should query the following attributes to determine
+ * possible combinations:
+ *
+ * NV_CTRL_GVI_MAX_STREAMS
+ * NV_CTRL_GVI_MAX_LINKS_PER_STREAM
+ * NV_CTRL_GVI_NUM_JACKS
+ * NV_CTRL_GVI_MAX_CHANNELS_PER_JACK
+ *
+ * Note: A jack+channel pair can only be tied to one link/stream.
+ *
+ * Upon successful configuration or querying of this attribute, a string
+ * representing the current topology for all known streams on the device
+ * will be returned. On failure, NULL is returned.
+ *
+ * Note: Setting this attribute may also result in the following
+ * NV-CONTROL attributes being reset on the GVI device (to ensure
+ * the configuration remains valid):
+ * NV_CTRL_GVIO_REQUESTED_VIDEO_FORMAT
+ * NV_CTRL_GVI_REQUESTED_STREAM_BITS_PER_COMPONENT
+ * NV_CTRL_GVI_REQUESTED_STREAM_COMPONENT_SAMPLING
+ */
+
+#define NV_CTRL_STRING_OPERATION_GVI_CONFIGURE_STREAMS 4 /* RW-I */
+
+#define NV_CTRL_STRING_OPERATION_LAST_ATTRIBUTE NV_CTRL_STRING_OPERATION_GVI_CONFIGURE_STREAMS
+
+/**************************************************************************/
+
+/*
+ * CTRLAttributeValidValuesRec -
+ *
+ * structure and related defines used by
+ * XNVCTRLQueryValidAttributeValues() to describe the valid values of
+ * a particular attribute. The type field will be one of:
+ *
+ * ATTRIBUTE_TYPE_INTEGER : the attribute is an integer value; there
+ * is no fixed range of valid values.
+ *
+ * ATTRIBUTE_TYPE_BITMASK : the attribute is an integer value,
+ * interpretted as a bitmask.
+ *
+ * ATTRIBUTE_TYPE_BOOL : the attribute is a boolean, valid values are
+ * either 1 (on/true) or 0 (off/false).
+ *
+ * ATTRIBUTE_TYPE_RANGE : the attribute can have any integer value
+ * between NVCTRLAttributeValidValues.u.range.min and
+ * NVCTRLAttributeValidValues.u.range.max (inclusive).
+ *
+ * ATTRIBUTE_TYPE_INT_BITS : the attribute can only have certain
+ * integer values, indicated by which bits in
+ * NVCTRLAttributeValidValues.u.bits.ints are on (for example: if bit
+ * 0 is on, then 0 is a valid value; if bit 5 is on, then 5 is a valid
+ * value, etc). This is useful for attributes like NV_CTRL_FSAA_MODE,
+ * which can only have certain values, depending on GPU.
+ *
+ * ATTRIBUTE_TYPE_64BIT_INTEGER : the attribute is a 64 bit integer value;
+ * there is no fixed range of valid values.
+ *
+ * ATTRIBUTE_TYPE_STRING : the attribute is a string value; there is no fixed
+ * range of valid values.
+ *
+ * ATTRIBUTE_TYPE_BINARY_DATA : the attribute is binary data; there is
+ * no fixed range of valid values.
+ *
+ * ATTRIBUTE_TYPE_STRING_OPERATION : the attribute is a string; there is
+ * no fixed range of valid values.
+ *
+ *
+ * The permissions field of NVCTRLAttributeValidValuesRec is a bitmask
+ * that may contain:
+ *
+ * ATTRIBUTE_TYPE_READ - Attribute may be read (queried.)
+ * ATTRIBUTE_TYPE_WRITE - Attribute may be written to (set.)
+ * ATTRIBUTE_TYPE_DISPLAY - Attribute is valid for display target types
+ * (requires a display_mask if queried via
+ * a GPU or X screen.)
+ * ATTRIBUTE_TYPE_GPU - Attribute is valid for GPU target types.
+ * ATTRIBUTE_TYPE_FRAMELOCK - Attribute is valid for Frame Lock target types.
+ * ATTRIBUTE_TYPE_X_SCREEN - Attribute is valid for X Screen target types.
+ * ATTRIBUTE_TYPE_XINERAMA - Attribute will be made consistent for all
+ * X Screens when the Xinerama extension is enabled.
+ * ATTRIBUTE_TYPE_VCSC - Attribute is valid for Visual Computing System
+ * target types.
+ * ATTRIBUTE_TYPE_GVI - Attribute is valid for Graphics Video In target
+ * types.
+ * ATTRIBUTE_TYPE_COOLER - Attribute is valid for Cooler target types.
+ * ATTRIBUTE_TYPE_3D_VISION_PRO_TRANSCEIVER - Attribute is valid for 3D Vision
+ * Pro Transceiver target types.
+ *
+ * See 'Key to Integer Attribute "Permissions"' at the top of this
+ * file for a description of what these permission bits mean.
+ */
+
+#define ATTRIBUTE_TYPE_UNKNOWN 0
+#define ATTRIBUTE_TYPE_INTEGER 1
+#define ATTRIBUTE_TYPE_BITMASK 2
+#define ATTRIBUTE_TYPE_BOOL 3
+#define ATTRIBUTE_TYPE_RANGE 4
+#define ATTRIBUTE_TYPE_INT_BITS 5
+#define ATTRIBUTE_TYPE_64BIT_INTEGER 6
+#define ATTRIBUTE_TYPE_STRING 7
+#define ATTRIBUTE_TYPE_BINARY_DATA 8
+#define ATTRIBUTE_TYPE_STRING_OPERATION 9
+
+#define ATTRIBUTE_TYPE_READ 0x001
+#define ATTRIBUTE_TYPE_WRITE 0x002
+#define ATTRIBUTE_TYPE_DISPLAY 0x004
+#define ATTRIBUTE_TYPE_GPU 0x008
+#define ATTRIBUTE_TYPE_FRAMELOCK 0x010
+#define ATTRIBUTE_TYPE_X_SCREEN 0x020
+#define ATTRIBUTE_TYPE_XINERAMA 0x040
+#define ATTRIBUTE_TYPE_VCSC 0x080
+#define ATTRIBUTE_TYPE_GVI 0x100
+#define ATTRIBUTE_TYPE_COOLER 0x200
+#define ATTRIBUTE_TYPE_THERMAL_SENSOR 0x400
+#define ATTRIBUTE_TYPE_3D_VISION_PRO_TRANSCEIVER 0x800
+
+#define ATTRIBUTE_TYPE_ALL_TARGETS \
+ ((ATTRIBUTE_TYPE_DISPLAY) | (ATTRIBUTE_TYPE_GPU) | (ATTRIBUTE_TYPE_FRAMELOCK) | \
+ (ATTRIBUTE_TYPE_X_SCREEN) | (ATTRIBUTE_TYPE_VCSC) | (ATTRIBUTE_TYPE_GVI) | \
+ (ATTRIBUTE_TYPE_COOLER) | (ATTRIBUTE_TYPE_THERMAL_SENSOR) | \
+ (ATTRIBUTE_TYPE_3D_VISION_PRO_TRANSCEIVER))
+
+typedef struct _NVCTRLAttributeValidValues
+{
+ int type;
+ union
+ {
+ struct
+ {
+ int64_t min;
+ int64_t max;
+ } range;
+ struct
+ {
+ unsigned int ints;
+ } bits;
+ } u;
+ unsigned int permissions;
+} NVCTRLAttributeValidValuesRec;
+
+typedef struct _NVCTRLAttributePermissions
+{
+ int type;
+ unsigned int permissions;
+} NVCTRLAttributePermissionsRec;
+
+/**************************************************************************/
+
+/*
+ * NV-CONTROL X event notification.
+ *
+ * To receive X event notifications dealing with NV-CONTROL, you should
+ * call XNVCtrlSelectNotify() with one of the following set as the type
+ * of event to receive (see NVCtrlLib.h for more information):
+ */
+
+#define ATTRIBUTE_CHANGED_EVENT 0
+#define TARGET_ATTRIBUTE_CHANGED_EVENT 1
+#define TARGET_ATTRIBUTE_AVAILABILITY_CHANGED_EVENT 2
+#define TARGET_STRING_ATTRIBUTE_CHANGED_EVENT 3
+#define TARGET_BINARY_ATTRIBUTE_CHANGED_EVENT 4
+
+#endif /* __NVCTRL_H */
diff --git a/src/3rdparty/angle/src/third_party/libXNVCtrl/NVCtrlLib.h b/src/3rdparty/angle/src/third_party/libXNVCtrl/NVCtrlLib.h
new file mode 100644
index 0000000000..1a5d5decfa
--- /dev/null
+++ b/src/3rdparty/angle/src/third_party/libXNVCtrl/NVCtrlLib.h
@@ -0,0 +1,707 @@
+/*
+ * Copyright (c) 2008 NVIDIA, Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __NVCTRLLIB_H
+#define __NVCTRLLIB_H
+
+#include "NVCtrl.h"
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+/*
+ * XNVCTRLQueryExtension -
+ *
+ * Returns True if the extension exists, returns False otherwise.
+ * event_basep and error_basep are the extension event and error
+ * bases. Currently, no extension specific errors or events are
+ * defined.
+ */
+
+Bool XNVCTRLQueryExtension(Display *dpy, int *event_basep, int *error_basep);
+
+/*
+ * XNVCTRLQueryVersion -
+ *
+ * Returns True if the extension exists, returns False otherwise.
+ * major and minor are the extension's major and minor version
+ * numbers.
+ */
+
+Bool XNVCTRLQueryVersion(Display *dpy, int *major, int *minor);
+
+/*
+ * XNVCTRLIsNvScreen
+ *
+ * Returns True is the specified screen is controlled by the NVIDIA
+ * driver. Returns False otherwise.
+ */
+
+Bool XNVCTRLIsNvScreen(Display *dpy, int screen);
+
+/*
+ * XNVCTRLQueryTargetCount -
+ *
+ * Returns True if the target type exists. Returns False otherwise.
+ * If XNVCTRLQueryTargetCount returns True, value will contain the
+ * count of existing targets on the server of the specified target
+ * type.
+ *
+ * Please see "Attribute Targets" in NVCtrl.h for the list of valid
+ * target types.
+ *
+ * Possible errors:
+ * BadValue - The target doesn't exist.
+ */
+
+Bool XNVCTRLQueryTargetCount(Display *dpy, int target_type, int *value);
+
+/*
+ * XNVCTRLSetAttribute -
+ *
+ * Sets the attribute to the given value. The attributes and their
+ * possible values are listed in NVCtrl.h.
+ *
+ * Not all attributes require the display_mask parameter; see
+ * NVCtrl.h for details.
+ *
+ * Calling this function is equivalent to calling XNVCTRLSetTargetAttribute()
+ * with the target_type set to NV_CTRL_TARGET_TYPE_X_SCREEN and
+ * target_id set to 'screen'.
+ *
+ * Possible errors:
+ * BadValue - The screen or attribute doesn't exist.
+ * BadMatch - The NVIDIA driver is not present on that screen.
+ */
+
+void XNVCTRLSetAttribute(Display *dpy,
+ int screen,
+ unsigned int display_mask,
+ unsigned int attribute,
+ int value);
+
+/*
+ * XNVCTRLSetTargetAttribute -
+ *
+ * Sets the attribute to the given value. The attributes and their
+ * possible values are listed in NVCtrl.h.
+ *
+ * Not all attributes require the display_mask parameter; see
+ * NVCtrl.h for details.
+ *
+ * Possible errors:
+ * BadValue - The target or attribute doesn't exist.
+ * BadMatch - The NVIDIA driver is not present on that target.
+ */
+
+void XNVCTRLSetTargetAttribute(Display *dpy,
+ int target_type,
+ int target_id,
+ unsigned int display_mask,
+ unsigned int attribute,
+ int value);
+
+/*
+ * XNVCTRLSetAttributeAndGetStatus -
+ *
+ * Same as XNVCTRLSetAttribute().
+ * In addition, XNVCTRLSetAttributeAndGetStatus() returns
+ * True if the operation succeeds, False otherwise.
+ *
+ */
+
+Bool XNVCTRLSetAttributeAndGetStatus(Display *dpy,
+ int screen,
+ unsigned int display_mask,
+ unsigned int attribute,
+ int value);
+
+/*
+ * XNVCTRLSetTargetAttributeAndGetStatus -
+ *
+ * Same as XNVCTRLSetTargetAttribute().
+ * In addition, XNVCTRLSetTargetAttributeAndGetStatus() returns
+ * True if the operation succeeds, False otherwise.
+ *
+ */
+
+Bool XNVCTRLSetTargetAttributeAndGetStatus(Display *dpy,
+ int target_type,
+ int target_id,
+ unsigned int display_mask,
+ unsigned int attribute,
+ int value);
+
+/*
+ * XNVCTRLQueryAttribute -
+ *
+ * Returns True if the attribute exists. Returns False otherwise.
+ * If XNVCTRLQueryAttribute returns True, value will contain the
+ * value of the specified attribute.
+ *
+ * Not all attributes require the display_mask parameter; see
+ * NVCtrl.h for details.
+ *
+ * Calling this function is equivalent to calling
+ * XNVCTRLQueryTargetAttribute() with the target_type set to
+ * NV_CTRL_TARGET_TYPE_X_SCREEN and target_id set to 'screen'.
+ *
+ * Possible errors:
+ * BadValue - The screen doesn't exist.
+ * BadMatch - The NVIDIA driver is not present on that screen.
+ */
+
+Bool XNVCTRLQueryAttribute(Display *dpy,
+ int screen,
+ unsigned int display_mask,
+ unsigned int attribute,
+ int *value);
+
+/*
+ * XNVCTRLQueryTargetAttribute -
+ *
+ * Returns True if the attribute exists. Returns False otherwise.
+ * If XNVCTRLQueryTargetAttribute returns True, value will contain the
+ * value of the specified attribute.
+ *
+ * Not all attributes require the display_mask parameter; see
+ * NVCtrl.h for details.
+ *
+ * Possible errors:
+ * BadValue - The target doesn't exist.
+ * BadMatch - The NVIDIA driver does not control the target.
+ */
+
+Bool XNVCTRLQueryTargetAttribute(Display *dpy,
+ int target_Type,
+ int target_id,
+ unsigned int display_mask,
+ unsigned int attribute,
+ int *value);
+
+/*
+ * XNVCTRLQueryTargetAttribute64 -
+ *
+ * Returns True if the attribute exists. Returns False otherwise.
+ * If XNVCTRLQueryTargetAttribute returns True, value will contain the
+ * value of the specified attribute.
+ *
+ * Not all attributes require the display_mask parameter; see
+ * NVCtrl.h for details.
+ *
+ * Note: this function behaves like XNVCTRLQueryTargetAttribute(),
+ * but supports 64-bit integer attributes.
+ *
+ * Possible errors:
+ * BadValue - The target doesn't exist.
+ * BadMatch - The NVIDIA driver does not control the target.
+ */
+
+Bool XNVCTRLQueryTargetAttribute64(Display *dpy,
+ int target_Type,
+ int target_id,
+ unsigned int display_mask,
+ unsigned int attribute,
+ int64_t *value);
+
+/*
+ * XNVCTRLQueryStringAttribute -
+ *
+ * Returns True if the attribute exists. Returns False otherwise.
+ * If XNVCTRLQueryStringAttribute returns True, *ptr will point to an
+ * allocated string containing the string attribute requested. It is
+ * the caller's responsibility to free the string when done.
+ *
+ * Calling this function is equivalent to calling
+ * XNVCTRLQueryTargetStringAttribute() with the target_type set to
+ * NV_CTRL_TARGET_TYPE_X_SCREEN and target_id set to 'screen'.
+ *
+ * Possible errors:
+ * BadValue - The screen doesn't exist.
+ * BadMatch - The NVIDIA driver is not present on that screen.
+ * BadAlloc - Insufficient resources to fulfill the request.
+ */
+
+Bool XNVCTRLQueryStringAttribute(Display *dpy,
+ int screen,
+ unsigned int display_mask,
+ unsigned int attribute,
+ char **ptr);
+
+/*
+ * XNVCTRLQueryTargetStringAttribute -
+ *
+ * Returns True if the attribute exists. Returns False otherwise.
+ * If XNVCTRLQueryTargetStringAttribute returns True, *ptr will point
+ * to an allocated string containing the string attribute requested.
+ * It is the caller's responsibility to free the string when done.
+ *
+ * Possible errors:
+ * BadValue - The target doesn't exist.
+ * BadMatch - The NVIDIA driver does not control the target.
+ * BadAlloc - Insufficient resources to fulfill the request.
+ */
+
+Bool XNVCTRLQueryTargetStringAttribute(Display *dpy,
+ int target_type,
+ int target_id,
+ unsigned int display_mask,
+ unsigned int attribute,
+ char **ptr);
+
+/*
+ * XNVCTRLSetStringAttribute -
+ *
+ * Returns True if the operation succeded. Returns False otherwise.
+ *
+ * Possible X errors:
+ * BadValue - The screen doesn't exist.
+ * BadMatch - The NVIDIA driver is not present on that screen.
+ * BadAlloc - Insufficient resources to fulfill the request.
+ */
+
+Bool XNVCTRLSetStringAttribute(Display *dpy,
+ int screen,
+ unsigned int display_mask,
+ unsigned int attribute,
+ char *ptr);
+
+/*
+ * XNVCTRLSetTargetStringAttribute -
+ *
+ * Returns True if the operation succeded. Returns False otherwise.
+ *
+ * Possible X errors:
+ * BadValue - The screen doesn't exist.
+ * BadMatch - The NVIDIA driver is not present on that screen.
+ * BadAlloc - Insufficient resources to fulfill the request.
+ */
+
+Bool XNVCTRLSetTargetStringAttribute(Display *dpy,
+ int target_type,
+ int target_id,
+ unsigned int display_mask,
+ unsigned int attribute,
+ char *ptr);
+
+/*
+ * XNVCTRLQueryValidAttributeValues -
+ *
+ * Returns True if the attribute exists. Returns False otherwise. If
+ * XNVCTRLQueryValidAttributeValues returns True, values will indicate
+ * the valid values for the specified attribute; see the description
+ * of NVCTRLAttributeValidValues in NVCtrl.h.
+ *
+ * Calling this function is equivalent to calling
+ * XNVCTRLQueryValidTargetAttributeValues() with the target_type set to
+ * NV_CTRL_TARGET_TYPE_X_SCREEN and target_id set to 'screen'.
+ */
+
+Bool XNVCTRLQueryValidAttributeValues(Display *dpy,
+ int screen,
+ unsigned int display_mask,
+ unsigned int attribute,
+ NVCTRLAttributeValidValuesRec *values);
+
+/*
+ * XNVCTRLQueryValidTargetAttributeValues -
+ *
+ * Returns True if the attribute exists. Returns False otherwise. If
+ * XNVCTRLQueryValidTargetAttributeValues returns True, values will indicate
+ * the valid values for the specified attribute.
+ */
+
+Bool XNVCTRLQueryValidTargetAttributeValues(Display *dpy,
+ int target_type,
+ int target_id,
+ unsigned int display_mask,
+ unsigned int attribute,
+ NVCTRLAttributeValidValuesRec *values);
+
+/*
+ * XNVCTRLQueryValidTargetStringAttributeValues -
+ *
+ * Returns True if the attribute exists. Returns False otherwise. If
+ * XNVCTRLQueryValidTargetStringAttributeValues returns True, values will
+ * indicate the valid values for the specified attribute.
+ */
+
+Bool XNVCTRLQueryValidTargetStringAttributeValues(Display *dpy,
+ int target_type,
+ int target_id,
+ unsigned int display_mask,
+ unsigned int attribute,
+ NVCTRLAttributeValidValuesRec *values);
+
+/*
+ * XNVCTRLQueryAttributePermissions -
+ *
+ * Returns True if the attribute exists. Returns False otherwise. If
+ * XNVCTRLQueryAttributePermissions returns True, permissions will
+ * indicate the permission flags for the attribute.
+ */
+
+Bool XNVCTRLQueryAttributePermissions(Display *dpy,
+ unsigned int attribute,
+ NVCTRLAttributePermissionsRec *permissions);
+
+/*
+ * XNVCTRLQueryStringAttributePermissions -
+ *
+ * Returns True if the attribute exists. Returns False otherwise. If
+ * XNVCTRLQueryStringAttributePermissions returns True, permissions will
+ * indicate the permission flags for the attribute.
+ */
+
+Bool XNVCTRLQueryStringAttributePermissions(Display *dpy,
+ unsigned int attribute,
+ NVCTRLAttributePermissionsRec *permissions);
+
+/*
+ * XNVCTRLQueryBinaryDataAttributePermissions -
+ *
+ * Returns True if the attribute exists. Returns False otherwise. If
+ * XNVCTRLQueryBinaryDataAttributePermissions returns True, permissions
+ * will indicate the permission flags for the attribute.
+ */
+
+Bool XNVCTRLQueryBinaryDataAttributePermissions(Display *dpy,
+ unsigned int attribute,
+ NVCTRLAttributePermissionsRec *permissions);
+
+/*
+ * XNVCTRLQueryStringOperationAttributePermissions -
+ *
+ * Returns True if the attribute exists. Returns False otherwise. If
+ * XNVCTRLQueryStringOperationAttributePermissions returns True,
+ * permissions will indicate the permission flags for the attribute.
+ */
+
+Bool XNVCTRLQueryStringOperationAttributePermissions(Display *dpy,
+ unsigned int attribute,
+ NVCTRLAttributePermissionsRec *permissions);
+
+/*
+ * XNVCTRLSetGvoColorConversion -
+ *
+ * Sets the color conversion matrix, offset, and scale that should be
+ * used for GVO (Graphic to Video Out).
+ *
+ * The Color Space Conversion data is ordered like this:
+ *
+ * colorMatrix[0][0] // r.Y
+ * colorMatrix[0][1] // g.Y
+ * colorMatrix[0][2] // b.Y
+ *
+ * colorMatrix[1][0] // r.Cr
+ * colorMatrix[1][1] // g.Cr
+ * colorMatrix[1][2] // b.Cr
+ *
+ * colorMatrix[2][0] // r.Cb
+ * colorMatrix[2][1] // g.Cb
+ * colorMatrix[2][2] // b.Cb
+ *
+ * colorOffset[0] // Y
+ * colorOffset[1] // Cr
+ * colorOffset[2] // Cb
+ *
+ * colorScale[0] // Y
+ * colorScale[1] // Cr
+ * colorScale[2] // Cb
+ *
+ * where the data is used according to the following formulae:
+ *
+ * Y = colorOffset[0] + colorScale[0] *
+ * (R * colorMatrix[0][0] +
+ * G * colorMatrix[0][1] +
+ * B * colorMatrix[0][2]);
+ *
+ * Cr = colorOffset[1] + colorScale[1] *
+ * (R * colorMatrix[1][0] +
+ * G * colorMatrix[1][1] +
+ * B * colorMatrix[1][2]);
+ *
+ * Cb = colorOffset[2] + colorScale[2] *
+ * (R * colorMatrix[2][0] +
+ * G * colorMatrix[2][1] +
+ * B * colorMatrix[2][2]);
+ *
+ * Possible errors:
+ * BadMatch - The NVIDIA driver is not present on that screen.
+ * BadImplementation - GVO is not available on that screen.
+ */
+
+void XNVCTRLSetGvoColorConversion(Display *dpy,
+ int screen,
+ float colorMatrix[3][3],
+ float colorOffset[3],
+ float colorScale[3]);
+
+/*
+ * XNVCTRLQueryGvoColorConversion -
+ *
+ * Retrieves the color conversion matrix and color offset
+ * that are currently being used for GVO (Graphic to Video Out).
+ *
+ * The values are ordered within the arrays according to the comments
+ * for XNVCTRLSetGvoColorConversion().
+ *
+ * Possible errors:
+ * BadMatch - The NVIDIA driver is not present on that screen.
+ * BadImplementation - GVO is not available on that screen.
+ */
+
+Bool XNVCTRLQueryGvoColorConversion(Display *dpy,
+ int screen,
+ float colorMatrix[3][3],
+ float colorOffset[3],
+ float colorScale[3]);
+
+/*
+ * XNVCTRLQueryBinaryData -
+ *
+ * Returns True if the attribute exists. Returns False otherwise.
+ * If XNVCTRLQueryBinaryData returns True, *ptr will point to an
+ * allocated block of memory containing the binary data attribute
+ * requested. It is the caller's responsibility to free the data
+ * when done. len will list the length of the binary data.
+ *
+ * Calling this function is equivalent to calling
+ * XNVCTRLQueryTargetBinaryData() with the target_type set to
+ * NV_CTRL_TARGET_TYPE_X_SCREEN and target_id set to 'screen'.
+ *
+ * Possible errors:
+ * BadValue - The screen doesn't exist.
+ * BadMatch - The NVIDIA driver is not present on that screen.
+ * BadAlloc - Insufficient resources to fulfill the request.
+ */
+
+Bool XNVCTRLQueryBinaryData(Display *dpy,
+ int screen,
+ unsigned int display_mask,
+ unsigned int attribute,
+ unsigned char **ptr,
+ int *len);
+
+/*
+ * XNVCTRLQueryTargetBinaryData -
+ *
+ * Returns True if the attribute exists. Returns False otherwise.
+ * If XNVCTRLQueryTargetBinaryData returns True, *ptr will point to an
+ * allocated block of memory containing the binary data attribute
+ * requested. It is the caller's responsibility to free the data
+ * when done. len will list the length of the binary data.
+ *
+ * Possible errors:
+ * BadValue - The target doesn't exist.
+ * BadMatch - The NVIDIA driver does not control the target.
+ * BadAlloc - Insufficient resources to fulfill the request.
+ */
+
+Bool XNVCTRLQueryTargetBinaryData(Display *dpy,
+ int target_type,
+ int target_id,
+ unsigned int display_mask,
+ unsigned int attribute,
+ unsigned char **ptr,
+ int *len);
+
+/*
+ * XNVCTRLStringOperation -
+ *
+ * Takes a string as input and returns a Xmalloc'ed string as output.
+ * Returns True on success and False on failure.
+ */
+
+Bool XNVCTRLStringOperation(Display *dpy,
+ int target_type,
+ int target_id,
+ unsigned int display_mask,
+ unsigned int attribute,
+ char *pIn,
+ char **ppOut);
+
+/*
+ * XNVCtrlSelectNotify -
+ *
+ * This enables/disables receiving of NV-CONTROL events. The type
+ * specifies the type of event to enable (currently, the only
+ * type that can be requested per-screen with XNVCtrlSelectNotify()
+ * is ATTRIBUTE_CHANGED_EVENT); onoff controls whether receiving this
+ * type of event should be enabled (True) or disabled (False).
+ *
+ * Returns True if successful, or False if the screen is not
+ * controlled by the NVIDIA driver.
+ */
+
+Bool XNVCtrlSelectNotify(Display *dpy, int screen, int type, Bool onoff);
+
+/*
+ * XNVCtrlSelectTargetNotify -
+ *
+ * This enables/disables receiving of NV-CONTROL events that happen on
+ * the specified target. The notify_type specifies the type of event to
+ * enable (currently, the only type that can be requested per-target with
+ * XNVCtrlSelectTargetNotify() is TARGET_ATTRIBUTE_CHANGED_EVENT); onoff
+ * controls whether receiving this type of event should be enabled (True)
+ * or disabled (False).
+ *
+ * Returns True if successful, or False if the target is not
+ * controlled by the NVIDIA driver.
+ */
+
+Bool XNVCtrlSelectTargetNotify(Display *dpy,
+ int target_type,
+ int target_id,
+ int notify_type,
+ Bool onoff);
+
+/*
+ * XNVCtrlEvent structure
+ */
+
+typedef struct
+{
+ int type;
+ unsigned long serial;
+ Bool send_event; /* always FALSE, we don't allow send_events */
+ Display *display;
+ Time time;
+ int screen;
+ unsigned int display_mask;
+ unsigned int attribute;
+ int value;
+} XNVCtrlAttributeChangedEvent;
+
+typedef union
+{
+ int type;
+ XNVCtrlAttributeChangedEvent attribute_changed;
+ long pad[24];
+} XNVCtrlEvent;
+
+/*
+ * XNVCtrlEventTarget structure
+ */
+
+typedef struct
+{
+ int type;
+ unsigned long serial;
+ Bool send_event; /* always FALSE, we don't allow send_events */
+ Display *display;
+ Time time;
+ int target_type;
+ int target_id;
+ unsigned int display_mask;
+ unsigned int attribute;
+ int value;
+} XNVCtrlAttributeChangedEventTarget;
+
+typedef union
+{
+ int type;
+ XNVCtrlAttributeChangedEventTarget attribute_changed;
+ long pad[24];
+} XNVCtrlEventTarget;
+
+/*
+ * XNVCtrlEventTargetAvailability structure
+ */
+
+typedef struct
+{
+ int type;
+ unsigned long serial;
+ Bool send_event; /* always FALSE, we don't allow send_events */
+ Display *display;
+ Time time;
+ int target_type;
+ int target_id;
+ unsigned int display_mask;
+ unsigned int attribute;
+ int value;
+ Bool availability;
+} XNVCtrlAttributeChangedEventTargetAvailability;
+
+typedef union
+{
+ int type;
+ XNVCtrlAttributeChangedEventTargetAvailability attribute_changed;
+ long pad[24];
+} XNVCtrlEventTargetAvailability;
+
+/*
+ * XNVCtrlStringEventTarget structure
+ */
+
+typedef struct
+{
+ int type;
+ unsigned long serial;
+ Bool send_event; /* always FALSE, we don't allow send_events */
+ Display *display;
+ Time time;
+ int target_type;
+ int target_id;
+ unsigned int display_mask;
+ unsigned int attribute;
+} XNVCtrlStringAttributeChangedEventTarget;
+
+typedef union
+{
+ int type;
+ XNVCtrlStringAttributeChangedEventTarget attribute_changed;
+ long pad[24];
+} XNVCtrlStringEventTarget;
+
+/*
+ * XNVCtrlBinaryEventTarget structure
+ */
+
+typedef struct
+{
+ int type;
+ unsigned long serial;
+ Bool send_event; /* always FALSE, we don't allow send_events */
+ Display *display;
+ Time time;
+ int target_type;
+ int target_id;
+ unsigned int display_mask;
+ unsigned int attribute;
+} XNVCtrlBinaryAttributeChangedEventTarget;
+
+typedef union
+{
+ int type;
+ XNVCtrlBinaryAttributeChangedEventTarget attribute_changed;
+ long pad[24];
+} XNVCtrlBinaryEventTarget;
+
+#if defined __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* __NVCTRLLIB_H */
diff --git a/src/3rdparty/angle/src/third_party/libXNVCtrl/README.angle b/src/3rdparty/angle/src/third_party/libXNVCtrl/README.angle
new file mode 100644
index 0000000000..22b9bd0aac
--- /dev/null
+++ b/src/3rdparty/angle/src/third_party/libXNVCtrl/README.angle
@@ -0,0 +1,14 @@
+Name: NVidia Control X Extension Library
+Short Name: libXNVCtrl
+URL: http://cgit.freedesktop.org/~aplattner/nvidia-settings/
+Version: unknown
+Date: 2008
+License: MIT
+Security Critical: no
+
+Description:
+This package provides access to NVidia Control X Extension. It is used to determine the version of the NVIDIA driver in use.
+
+The current version is pulled from nvidia-settings-302.17.
+
+Local Modifications:
diff --git a/src/3rdparty/angle/src/third_party/libXNVCtrl/nv_control.h b/src/3rdparty/angle/src/third_party/libXNVCtrl/nv_control.h
new file mode 100644
index 0000000000..5023c9b58c
--- /dev/null
+++ b/src/3rdparty/angle/src/third_party/libXNVCtrl/nv_control.h
@@ -0,0 +1,652 @@
+/*
+ * Copyright (c) 2008 NVIDIA, Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *
+ * NV-CONTROL Protocol Version History
+ *
+ * 1.0 - 1.5 NVIDIA Internal development versions
+ * 1.6 Initial public version
+ * 1.7 Added QueryBinaryData request
+ * 1.8 Added TargetTypes
+ * 1.9 Added QueryTargetCount request
+ * 1.10 Fixed target type/id byte ordering for compatibility with
+ * pre-1.8 NV-CONTROL clients
+ * 1.11 NVIDIA Internal development version
+ * 1.12 Added StringOperation request
+ * 1.13 NVIDIA Internal development version
+ * 1.14 Fixed an NV_CTRL_BINARY_DATA_MODELINES double scan modeline
+ * reporting bug (vsyncstart, vsyncend, and vtotal were incorrectly
+ * doubled)
+ * 1.15 Added AVAILABILITY_TARGET_ATTRIBUTE_CHANGED_EVENT
+ * 1.16 Added TARGET_STRING_ATTRIBUTE_CHANGED_EVENT
+ * 1.17 Added TARGET_BINARY_ATTRIBUTE_CHANGED_EVENT
+ * 1.18 Updated QueryTargetCount to return a count of 0, rather than
+ * BadMatch, if an unknown TargetType is specified
+ * 1.19 Added TargetType support for SetAttributeAndGetStatus and
+ * SetStringAttribute requests
+ * 1.20 Added COOLER TargetType
+ * 1.21 Added initial 64-bit integer attribute support (read-only)
+ * 1.22 Added X_nvCtrlQueryValidStringAttributeValues to check
+ * string attribute permissions.
+ * 1.23 Added SENSOR TargetType
+ * 1.24 Fixed a bug where SLI_MOSAIC_MODE_AVAILABLE attribute would
+ * report false positives via the GPU and X screen target types
+ * 1.25 Added 3D_VISION_PRO_TRANSCEIVER TargetType
+ * 1.26 Added XNVCTRLQueryXXXAttributePermissions.
+ * 1.27 Added DISPLAY TargetType
+ * 1.28 Added NV_CTRL_CURRENT_METAMODE_ID: clients should use this
+ * attribute to switch MetaModes, rather than pass the MetaMode ID
+ * through the RRSetScreenConfig protocol request.
+ */
+
+#ifndef __NVCONTROL_H
+#define __NVCONTROL_H
+
+#define NV_CONTROL_ERRORS 0
+#define NV_CONTROL_EVENTS 5
+#define NV_CONTROL_NAME "NV-CONTROL"
+
+#define NV_CONTROL_MAJOR 1
+#define NV_CONTROL_MINOR 28
+
+#define X_nvCtrlQueryExtension 0
+#define X_nvCtrlIsNv 1
+#define X_nvCtrlQueryAttribute 2
+#define X_nvCtrlSetAttribute 3
+#define X_nvCtrlQueryStringAttribute 4
+#define X_nvCtrlQueryValidAttributeValues 5
+#define X_nvCtrlSelectNotify 6
+#define X_nvCtrlSetGvoColorConversionDeprecated 7
+#define X_nvCtrlQueryGvoColorConversionDeprecated 8
+#define X_nvCtrlSetStringAttribute 9
+/* STUB X_nvCtrlQueryDDCCILutSize 10 */
+/* STUB X_nvCtrlQueryDDCCISinglePointLutOperation 11 */
+/* STUB X_nvCtrlSetDDCCISinglePointLutOperation 12 */
+/* STUB X_nvCtrlQueryDDCCIBlockLutOperation 13 */
+/* STUB X_nvCtrlSetDDCCIBlockLutOperation 14 */
+/* STUB X_nvCtrlSetDDCCIRemoteProcedureCall 15 */
+/* STUB X_nvCtrlQueryDDCCIDisplayControllerType 16 */
+/* STUB X_nvCtrlQueryDDCCICapabilities 17 */
+/* STUB X_nvCtrlQueryDDCCITimingReport 18 */
+#define X_nvCtrlSetAttributeAndGetStatus 19
+#define X_nvCtrlQueryBinaryData 20
+#define X_nvCtrlSetGvoColorConversion 21
+#define X_nvCtrlQueryGvoColorConversion 22
+#define X_nvCtrlSelectTargetNotify 23
+#define X_nvCtrlQueryTargetCount 24
+#define X_nvCtrlStringOperation 25
+#define X_nvCtrlQueryValidAttributeValues64 26
+#define X_nvCtrlQueryAttribute64 27
+#define X_nvCtrlQueryValidStringAttributeValues 28
+#define X_nvCtrlQueryAttributePermissions 29
+#define X_nvCtrlQueryStringAttributePermissions 30
+#define X_nvCtrlQueryBinaryDataAttributePermissions 31
+#define X_nvCtrlQueryStringOperationAttributePermissions 32
+
+#define X_nvCtrlLastRequest (X_nvCtrlQueryStringOperationAttributePermissions + 1)
+
+/* Define 32 bit floats */
+typedef float FLOAT32;
+#ifndef F32
+#define F32
+#endif
+
+typedef struct
+{
+ CARD8 reqType;
+ CARD8 nvReqType;
+ CARD16 length B16;
+} xnvCtrlQueryExtensionReq;
+#define sz_xnvCtrlQueryExtensionReq 4
+
+typedef struct
+{
+ BYTE type; /* X_Reply */
+ CARD8 padb1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD16 major B16;
+ CARD16 minor B16;
+ CARD32 padl4 B32;
+ CARD32 padl5 B32;
+ CARD32 padl6 B32;
+ CARD32 padl7 B32;
+ CARD32 padl8 B32;
+} xnvCtrlQueryExtensionReply;
+#define sz_xnvCtrlQueryExtensionReply 32
+
+typedef struct
+{
+ CARD8 reqType;
+ CARD8 nvReqType;
+ CARD16 length B16;
+ CARD32 screen B32;
+} xnvCtrlIsNvReq;
+#define sz_xnvCtrlIsNvReq 8
+
+typedef struct
+{
+ BYTE type; /* X_Reply */
+ CARD8 padb1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 isnv B32;
+ CARD32 padl4 B32;
+ CARD32 padl5 B32;
+ CARD32 padl6 B32;
+ CARD32 padl7 B32;
+ CARD32 padl8 B32;
+} xnvCtrlIsNvReply;
+#define sz_xnvCtrlIsNvReply 32
+
+typedef struct
+{
+ CARD8 reqType;
+ CARD8 nvReqType;
+ CARD16 length B16;
+ CARD32 target_type B32;
+} xnvCtrlQueryTargetCountReq;
+#define sz_xnvCtrlQueryTargetCountReq 8
+
+typedef struct
+{
+ BYTE type; /* X_Reply */
+ CARD8 padb1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 count B32;
+ CARD32 padl4 B32;
+ CARD32 padl5 B32;
+ CARD32 padl6 B32;
+ CARD32 padl7 B32;
+ CARD32 padl8 B32;
+} xnvCtrlQueryTargetCountReply;
+#define sz_xnvCtrlQueryTargetCountReply 32
+
+typedef struct
+{
+ CARD8 reqType;
+ CARD8 nvReqType;
+ CARD16 length B16;
+ CARD16 target_id B16; /* X screen number or GPU number */
+ CARD16 target_type B16; /* X screen or GPU */
+ CARD32 display_mask B32;
+ CARD32 attribute B32;
+} xnvCtrlQueryAttributeReq;
+#define sz_xnvCtrlQueryAttributeReq 16
+
+typedef struct
+{
+ BYTE type;
+ BYTE pad0;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 flags B32;
+ INT32 value B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+} xnvCtrlQueryAttributeReply;
+#define sz_xnvCtrlQueryAttributeReply 32
+
+typedef struct
+{
+ BYTE type;
+ BYTE pad0;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 flags B32;
+ CARD32 pad3 B32;
+ int64_t value_64;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+} xnvCtrlQueryAttribute64Reply;
+#define sz_xnvCtrlQueryAttribute64Reply 32
+
+typedef struct
+{
+ CARD8 reqType;
+ CARD8 nvReqType;
+ CARD16 length B16;
+ CARD16 target_id B16;
+ CARD16 target_type B16;
+ CARD32 display_mask B32;
+ CARD32 attribute B32;
+ INT32 value B32;
+} xnvCtrlSetAttributeReq;
+#define sz_xnvCtrlSetAttributeReq 20
+
+typedef struct
+{
+ CARD8 reqType;
+ CARD8 nvReqType;
+ CARD16 length B16;
+ CARD16 target_id B16;
+ CARD16 target_type B16;
+ CARD32 display_mask B32;
+ CARD32 attribute B32;
+ INT32 value B32;
+} xnvCtrlSetAttributeAndGetStatusReq;
+#define sz_xnvCtrlSetAttributeAndGetStatusReq 20
+
+typedef struct
+{
+ BYTE type;
+ BYTE pad0;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 flags B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+} xnvCtrlSetAttributeAndGetStatusReply;
+#define sz_xnvCtrlSetAttributeAndGetStatusReply 32
+
+typedef struct
+{
+ CARD8 reqType;
+ CARD8 nvReqType;
+ CARD16 length B16;
+ CARD16 target_id B16; /* X screen number or GPU number */
+ CARD16 target_type B16; /* X screen or GPU */
+ CARD32 display_mask B32;
+ CARD32 attribute B32;
+} xnvCtrlQueryStringAttributeReq;
+#define sz_xnvCtrlQueryStringAttributeReq 16
+
+typedef struct
+{
+ BYTE type;
+ BYTE pad0;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 flags B32;
+ CARD32 n B32; /* Length of string */
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+} xnvCtrlQueryStringAttributeReply;
+#define sz_xnvCtrlQueryStringAttributeReply 32
+
+typedef struct
+{
+ CARD8 reqType;
+ CARD8 nvReqType;
+ CARD16 length B16;
+ CARD16 target_id B16;
+ CARD16 target_type B16;
+ CARD32 display_mask B32;
+ CARD32 attribute B32;
+ CARD32 num_bytes B32;
+} xnvCtrlSetStringAttributeReq;
+#define sz_xnvCtrlSetStringAttributeReq 20
+
+typedef struct
+{
+ BYTE type;
+ BYTE pad0;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 flags B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+} xnvCtrlSetStringAttributeReply;
+#define sz_xnvCtrlSetStringAttributeReply 32
+
+typedef struct
+{
+ CARD8 reqType;
+ CARD8 nvReqType;
+ CARD16 length B16;
+ CARD16 target_id B16; /* X screen number or GPU number */
+ CARD16 target_type B16; /* X screen or GPU */
+ CARD32 display_mask B32;
+ CARD32 attribute B32;
+} xnvCtrlQueryValidAttributeValuesReq;
+#define sz_xnvCtrlQueryValidAttributeValuesReq 16
+
+typedef struct
+{
+ BYTE type;
+ BYTE pad0;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 flags B32;
+ INT32 attr_type B32;
+ INT32 min B32;
+ INT32 max B32;
+ CARD32 bits B32;
+ CARD32 perms B32;
+} xnvCtrlQueryValidAttributeValuesReply;
+#define sz_xnvCtrlQueryValidAttributeValuesReply 32
+
+typedef struct
+{
+ BYTE type;
+ BYTE pad0;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 flags B32;
+ INT32 attr_type B32;
+ int64_t min_64;
+ int64_t max_64;
+ CARD64 bits_64;
+ CARD32 perms B32;
+ CARD32 pad1 B32;
+} xnvCtrlQueryValidAttributeValues64Reply;
+#define sz_xnvCtrlQueryValidAttributeValues64Reply 48
+#define sz_xnvCtrlQueryValidAttributeValues64Reply_extra ((48 - 32) >> 2)
+
+typedef struct
+{
+ CARD8 reqType;
+ CARD8 nvReqType;
+ CARD16 length B16;
+ CARD32 attribute B32;
+} xnvCtrlQueryAttributePermissionsReq;
+#define sz_xnvCtrlQueryAttributePermissionsReq 8
+
+typedef struct
+{
+ BYTE type;
+ BYTE pad0;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 flags B32;
+ INT32 attr_type B32;
+ CARD32 perms B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+ CARD32 pad8 B32;
+} xnvCtrlQueryAttributePermissionsReply;
+#define sz_xnvCtrlQueryAttributePermissionsReply 32
+
+/* Set GVO Color Conversion request (deprecated) */
+typedef struct
+{
+ CARD8 reqType;
+ CARD8 nvReqType;
+ CARD16 length B16;
+ CARD32 screen B32;
+ FLOAT32 row1_col1 F32;
+ FLOAT32 row1_col2 F32;
+ FLOAT32 row1_col3 F32;
+ FLOAT32 row1_col4 F32;
+ FLOAT32 row2_col1 F32;
+ FLOAT32 row2_col2 F32;
+ FLOAT32 row2_col3 F32;
+ FLOAT32 row2_col4 F32;
+ FLOAT32 row3_col1 F32;
+ FLOAT32 row3_col2 F32;
+ FLOAT32 row3_col3 F32;
+ FLOAT32 row3_col4 F32;
+} xnvCtrlSetGvoColorConversionDeprecatedReq;
+#define sz_xnvCtrlSetGvoColorConversionDeprecatedReq 56
+
+/* Query GVO Color Conversion request (deprecated) */
+typedef struct
+{
+ CARD8 reqType;
+ CARD8 nvReqType;
+ CARD16 length B16;
+ CARD32 screen B32;
+} xnvCtrlQueryGvoColorConversionDeprecatedReq;
+#define sz_xnvCtrlQueryGvoColorConversionDeprecatedReq 8
+
+/* Query GVO Color Conversion reply (deprecated) */
+typedef struct
+{
+ BYTE type; /* X_Reply */
+ BYTE pad0;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+ CARD32 pad8 B32;
+} xnvCtrlQueryGvoColorConversionDeprecatedReply;
+#define sz_xnvCtrlQueryGvoColorConversionDeprecatedReply 32
+
+/* Set GVO Color Conversion request */
+typedef struct
+{
+ CARD8 reqType;
+ CARD8 nvReqType;
+ CARD16 length B16;
+ CARD32 screen B32;
+
+ FLOAT32 cscMatrix_y_r F32;
+ FLOAT32 cscMatrix_y_g F32;
+ FLOAT32 cscMatrix_y_b F32;
+
+ FLOAT32 cscMatrix_cr_r F32;
+ FLOAT32 cscMatrix_cr_g F32;
+ FLOAT32 cscMatrix_cr_b F32;
+
+ FLOAT32 cscMatrix_cb_r F32;
+ FLOAT32 cscMatrix_cb_g F32;
+ FLOAT32 cscMatrix_cb_b F32;
+
+ FLOAT32 cscOffset_y F32;
+ FLOAT32 cscOffset_cr F32;
+ FLOAT32 cscOffset_cb F32;
+
+ FLOAT32 cscScale_y F32;
+ FLOAT32 cscScale_cr F32;
+ FLOAT32 cscScale_cb F32;
+
+} xnvCtrlSetGvoColorConversionReq;
+#define sz_xnvCtrlSetGvoColorConversionReq 68
+
+/* Query GVO Color Conversion request */
+typedef struct
+{
+ CARD8 reqType;
+ CARD8 nvReqType;
+ CARD16 length B16;
+ CARD32 screen B32;
+} xnvCtrlQueryGvoColorConversionReq;
+#define sz_xnvCtrlQueryGvoColorConversionReq 8
+
+/* Query GVO Color Conversion reply */
+typedef struct
+{
+ BYTE type; /* X_Reply */
+ BYTE pad0;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+ CARD32 pad8 B32;
+} xnvCtrlQueryGvoColorConversionReply;
+#define sz_xnvCtrlQueryGvoColorConversionReply 32
+
+typedef struct
+{
+ CARD8 reqType;
+ CARD8 nvReqType;
+ CARD16 length B16;
+ CARD16 target_id B16; /* X screen number or GPU number */
+ CARD16 target_type B16; /* X screen or GPU */
+ CARD32 display_mask B32;
+ CARD32 attribute B32;
+} xnvCtrlQueryBinaryDataReq;
+#define sz_xnvCtrlQueryBinaryDataReq 16
+
+typedef struct
+{
+ BYTE type;
+ BYTE pad0;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 flags B32;
+ CARD32 n B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+} xnvCtrlQueryBinaryDataReply;
+#define sz_xnvCtrlQueryBinaryDataReply 32
+
+typedef struct
+{
+ CARD8 reqType;
+ CARD8 nvReqType;
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD16 notifyType B16;
+ CARD16 onoff B16;
+} xnvCtrlSelectNotifyReq;
+#define sz_xnvCtrlSelectNotifyReq 12
+
+typedef struct
+{
+ CARD8 reqType;
+ CARD8 nvReqType;
+ CARD16 length B16;
+ CARD16 target_id B16; /* X screen number or GPU number */
+ CARD16 target_type B16; /* X screen or GPU */
+ CARD32 display_mask B32;
+ CARD32 attribute B32;
+ CARD32 num_bytes B32; /* Length of string */
+} xnvCtrlStringOperationReq;
+#define sz_xnvCtrlStringOperationReq 20
+
+typedef struct
+{
+ BYTE type; /* X_Reply */
+ CARD8 padb1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 ret B32;
+ CARD32 num_bytes B32; /* Length of string */
+ CARD32 padl4 B32;
+ CARD32 padl5 B32;
+ CARD32 padl6 B32;
+ CARD32 padl7 B32;
+} xnvCtrlStringOperationReply;
+#define sz_xnvCtrlStringOperationReply 32
+
+typedef struct
+{
+ union
+ {
+ struct
+ {
+ BYTE type;
+ BYTE detail;
+ CARD16 sequenceNumber B16;
+ } u;
+ struct
+ {
+ BYTE type;
+ BYTE detail;
+ CARD16 sequenceNumber B16;
+ CARD32 time B32;
+ CARD32 screen B32;
+ CARD32 display_mask B32;
+ CARD32 attribute B32;
+ CARD32 value B32;
+ CARD32 pad0 B32;
+ CARD32 pad1 B32;
+ } attribute_changed;
+ } u;
+} xnvctrlEvent;
+
+/*
+ * Leave target_type before target_id for the
+ * xnvCtrlSelectTargetNotifyReq and xnvctrlEventTarget
+ * structures, even though other request protocol structures
+ * store target_id in the bottom 16-bits of the second DWORD of the
+ * structures. The event-related structures were added in version
+ * 1.8, and so there is no prior version with which to maintain
+ * compatibility.
+ */
+typedef struct
+{
+ CARD8 reqType;
+ CARD8 nvReqType;
+ CARD16 length B16;
+ CARD16 target_type B16; /* Don't swap these */
+ CARD16 target_id B16;
+ CARD16 notifyType B16;
+ CARD16 onoff B16;
+} xnvCtrlSelectTargetNotifyReq;
+#define sz_xnvCtrlSelectTargetNotifyReq 12
+
+typedef struct
+{
+ union
+ {
+ struct
+ {
+ BYTE type;
+ BYTE detail;
+ CARD16 sequenceNumber B16;
+ } u;
+ struct
+ {
+ BYTE type;
+ BYTE detail;
+ CARD16 sequenceNumber B16;
+ CARD32 time B32;
+ CARD16 target_type B16; /* Don't swap these */
+ CARD16 target_id B16;
+ CARD32 display_mask B32;
+ CARD32 attribute B32;
+ CARD32 value B32;
+ CARD32 pad0 B32;
+ CARD32 pad1 B32;
+ } attribute_changed;
+ struct
+ {
+ BYTE type;
+ BYTE detail;
+ CARD16 sequenceNumber B16;
+ CARD32 time B32;
+ CARD16 target_type B16; /* Don't swap these */
+ CARD16 target_id B16;
+ CARD32 display_mask B32;
+ CARD32 attribute B32;
+ CARD32 value B32;
+ CARD8 availability;
+ CARD8 pad0;
+ CARD16 pad1 B16;
+ CARD32 pad2 B32;
+ } availability_changed;
+ } u;
+} xnvctrlEventTarget;
+
+#endif /* __NVCONTROL_H */
diff --git a/src/3rdparty/angle/src/third_party/murmurhash/LICENSE b/src/3rdparty/angle/src/third_party/murmurhash/LICENSE
deleted file mode 100644
index 6a385f0f07..0000000000
--- a/src/3rdparty/angle/src/third_party/murmurhash/LICENSE
+++ /dev/null
@@ -1,2 +0,0 @@
-// MurmurHash3 was written by Austin Appleby, and is placed in the public
-// domain. The author hereby disclaims copyright to this source code. \ No newline at end of file
diff --git a/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.cpp b/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.cpp
deleted file mode 100644
index aa7982d3ee..0000000000
--- a/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.cpp
+++ /dev/null
@@ -1,335 +0,0 @@
-//-----------------------------------------------------------------------------
-// MurmurHash3 was written by Austin Appleby, and is placed in the public
-// domain. The author hereby disclaims copyright to this source code.
-
-// Note - The x86 and x64 versions do _not_ produce the same results, as the
-// algorithms are optimized for their respective platforms. You can still
-// compile and run any of them on any platform, but your performance with the
-// non-native version will be less than optimal.
-
-#include "MurmurHash3.h"
-
-//-----------------------------------------------------------------------------
-// Platform-specific functions and macros
-
-// Microsoft Visual Studio
-
-#if defined(_MSC_VER)
-
-#define FORCE_INLINE __forceinline
-
-#include <stdlib.h>
-
-#define ROTL32(x,y) _rotl(x,y)
-#define ROTL64(x,y) _rotl64(x,y)
-
-#define BIG_CONSTANT(x) (x)
-
-// Other compilers
-
-#else // defined(_MSC_VER)
-
-#define FORCE_INLINE inline __attribute__((always_inline))
-
-inline uint32_t rotl32 ( uint32_t x, int8_t r )
-{
- return (x << r) | (x >> (32 - r));
-}
-
-inline uint64_t rotl64 ( uint64_t x, int8_t r )
-{
- return (x << r) | (x >> (64 - r));
-}
-
-#define ROTL32(x,y) rotl32(x,y)
-#define ROTL64(x,y) rotl64(x,y)
-
-#define BIG_CONSTANT(x) (x##LLU)
-
-#endif // !defined(_MSC_VER)
-
-//-----------------------------------------------------------------------------
-// Block read - if your platform needs to do endian-swapping or can only
-// handle aligned reads, do the conversion here
-
-FORCE_INLINE uint32_t getblock32 ( const uint32_t * p, int i )
-{
- return p[i];
-}
-
-FORCE_INLINE uint64_t getblock64 ( const uint64_t * p, int i )
-{
- return p[i];
-}
-
-//-----------------------------------------------------------------------------
-// Finalization mix - force all bits of a hash block to avalanche
-
-FORCE_INLINE uint32_t fmix32 ( uint32_t h )
-{
- h ^= h >> 16;
- h *= 0x85ebca6b;
- h ^= h >> 13;
- h *= 0xc2b2ae35;
- h ^= h >> 16;
-
- return h;
-}
-
-//----------
-
-FORCE_INLINE uint64_t fmix64 ( uint64_t k )
-{
- k ^= k >> 33;
- k *= BIG_CONSTANT(0xff51afd7ed558ccd);
- k ^= k >> 33;
- k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);
- k ^= k >> 33;
-
- return k;
-}
-
-//-----------------------------------------------------------------------------
-
-void MurmurHash3_x86_32 ( const void * key, int len,
- uint32_t seed, void * out )
-{
- const uint8_t * data = (const uint8_t*)key;
- const int nblocks = len / 4;
-
- uint32_t h1 = seed;
-
- const uint32_t c1 = 0xcc9e2d51;
- const uint32_t c2 = 0x1b873593;
-
- //----------
- // body
-
- const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
-
- for(int i = -nblocks; i; i++)
- {
- uint32_t k1 = getblock32(blocks,i);
-
- k1 *= c1;
- k1 = ROTL32(k1,15);
- k1 *= c2;
-
- h1 ^= k1;
- h1 = ROTL32(h1,13);
- h1 = h1*5+0xe6546b64;
- }
-
- //----------
- // tail
-
- const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
-
- uint32_t k1 = 0;
-
- switch(len & 3)
- {
- case 3: k1 ^= tail[2] << 16;
- case 2: k1 ^= tail[1] << 8;
- case 1: k1 ^= tail[0];
- k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
- };
-
- //----------
- // finalization
-
- h1 ^= len;
-
- h1 = fmix32(h1);
-
- *(uint32_t*)out = h1;
-}
-
-//-----------------------------------------------------------------------------
-
-void MurmurHash3_x86_128 ( const void * key, const int len,
- uint32_t seed, void * out )
-{
- const uint8_t * data = (const uint8_t*)key;
- const int nblocks = len / 16;
-
- uint32_t h1 = seed;
- uint32_t h2 = seed;
- uint32_t h3 = seed;
- uint32_t h4 = seed;
-
- const uint32_t c1 = 0x239b961b;
- const uint32_t c2 = 0xab0e9789;
- const uint32_t c3 = 0x38b34ae5;
- const uint32_t c4 = 0xa1e38b93;
-
- //----------
- // body
-
- const uint32_t * blocks = (const uint32_t *)(data + nblocks*16);
-
- for(int i = -nblocks; i; i++)
- {
- uint32_t k1 = getblock32(blocks,i*4+0);
- uint32_t k2 = getblock32(blocks,i*4+1);
- uint32_t k3 = getblock32(blocks,i*4+2);
- uint32_t k4 = getblock32(blocks,i*4+3);
-
- k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
-
- h1 = ROTL32(h1,19); h1 += h2; h1 = h1*5+0x561ccd1b;
-
- k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
-
- h2 = ROTL32(h2,17); h2 += h3; h2 = h2*5+0x0bcaa747;
-
- k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
-
- h3 = ROTL32(h3,15); h3 += h4; h3 = h3*5+0x96cd1c35;
-
- k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
-
- h4 = ROTL32(h4,13); h4 += h1; h4 = h4*5+0x32ac3b17;
- }
-
- //----------
- // tail
-
- const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
-
- uint32_t k1 = 0;
- uint32_t k2 = 0;
- uint32_t k3 = 0;
- uint32_t k4 = 0;
-
- switch(len & 15)
- {
- case 15: k4 ^= tail[14] << 16;
- case 14: k4 ^= tail[13] << 8;
- case 13: k4 ^= tail[12] << 0;
- k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
-
- case 12: k3 ^= tail[11] << 24;
- case 11: k3 ^= tail[10] << 16;
- case 10: k3 ^= tail[ 9] << 8;
- case 9: k3 ^= tail[ 8] << 0;
- k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
-
- case 8: k2 ^= tail[ 7] << 24;
- case 7: k2 ^= tail[ 6] << 16;
- case 6: k2 ^= tail[ 5] << 8;
- case 5: k2 ^= tail[ 4] << 0;
- k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
-
- case 4: k1 ^= tail[ 3] << 24;
- case 3: k1 ^= tail[ 2] << 16;
- case 2: k1 ^= tail[ 1] << 8;
- case 1: k1 ^= tail[ 0] << 0;
- k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
- };
-
- //----------
- // finalization
-
- h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len;
-
- h1 += h2; h1 += h3; h1 += h4;
- h2 += h1; h3 += h1; h4 += h1;
-
- h1 = fmix32(h1);
- h2 = fmix32(h2);
- h3 = fmix32(h3);
- h4 = fmix32(h4);
-
- h1 += h2; h1 += h3; h1 += h4;
- h2 += h1; h3 += h1; h4 += h1;
-
- ((uint32_t*)out)[0] = h1;
- ((uint32_t*)out)[1] = h2;
- ((uint32_t*)out)[2] = h3;
- ((uint32_t*)out)[3] = h4;
-}
-
-//-----------------------------------------------------------------------------
-
-void MurmurHash3_x64_128 ( const void * key, const int len,
- const uint32_t seed, void * out )
-{
- const uint8_t * data = (const uint8_t*)key;
- const int nblocks = len / 16;
-
- uint64_t h1 = seed;
- uint64_t h2 = seed;
-
- const uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5);
- const uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f);
-
- //----------
- // body
-
- const uint64_t * blocks = (const uint64_t *)(data);
-
- for(int i = 0; i < nblocks; i++)
- {
- uint64_t k1 = getblock64(blocks,i*2+0);
- uint64_t k2 = getblock64(blocks,i*2+1);
-
- k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
-
- h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;
-
- k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
-
- h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
- }
-
- //----------
- // tail
-
- const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
-
- uint64_t k1 = 0;
- uint64_t k2 = 0;
-
- switch(len & 15)
- {
- case 15: k2 ^= ((uint64_t)tail[14]) << 48;
- case 14: k2 ^= ((uint64_t)tail[13]) << 40;
- case 13: k2 ^= ((uint64_t)tail[12]) << 32;
- case 12: k2 ^= ((uint64_t)tail[11]) << 24;
- case 11: k2 ^= ((uint64_t)tail[10]) << 16;
- case 10: k2 ^= ((uint64_t)tail[ 9]) << 8;
- case 9: k2 ^= ((uint64_t)tail[ 8]) << 0;
- k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
-
- case 8: k1 ^= ((uint64_t)tail[ 7]) << 56;
- case 7: k1 ^= ((uint64_t)tail[ 6]) << 48;
- case 6: k1 ^= ((uint64_t)tail[ 5]) << 40;
- case 5: k1 ^= ((uint64_t)tail[ 4]) << 32;
- case 4: k1 ^= ((uint64_t)tail[ 3]) << 24;
- case 3: k1 ^= ((uint64_t)tail[ 2]) << 16;
- case 2: k1 ^= ((uint64_t)tail[ 1]) << 8;
- case 1: k1 ^= ((uint64_t)tail[ 0]) << 0;
- k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
- };
-
- //----------
- // finalization
-
- h1 ^= len; h2 ^= len;
-
- h1 += h2;
- h2 += h1;
-
- h1 = fmix64(h1);
- h2 = fmix64(h2);
-
- h1 += h2;
- h2 += h1;
-
- ((uint64_t*)out)[0] = h1;
- ((uint64_t*)out)[1] = h2;
-}
-
-//-----------------------------------------------------------------------------
-
diff --git a/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h b/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h
deleted file mode 100644
index e1c6d34976..0000000000
--- a/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h
+++ /dev/null
@@ -1,37 +0,0 @@
-//-----------------------------------------------------------------------------
-// MurmurHash3 was written by Austin Appleby, and is placed in the public
-// domain. The author hereby disclaims copyright to this source code.
-
-#ifndef _MURMURHASH3_H_
-#define _MURMURHASH3_H_
-
-//-----------------------------------------------------------------------------
-// Platform-specific functions and macros
-
-// Microsoft Visual Studio
-
-#if defined(_MSC_VER) && (_MSC_VER < 1600)
-
-typedef unsigned char uint8_t;
-typedef unsigned int uint32_t;
-typedef unsigned __int64 uint64_t;
-
-// Other compilers
-
-#else // defined(_MSC_VER)
-
-#include <stdint.h>
-
-#endif // !defined(_MSC_VER)
-
-//-----------------------------------------------------------------------------
-
-void MurmurHash3_x86_32 ( const void * key, int len, uint32_t seed, void * out );
-
-void MurmurHash3_x86_128 ( const void * key, int len, uint32_t seed, void * out );
-
-void MurmurHash3_x64_128 ( const void * key, int len, uint32_t seed, void * out );
-
-//-----------------------------------------------------------------------------
-
-#endif // _MURMURHASH3_H_
diff --git a/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.cpp b/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.cpp
index fc05526681..97dfcaac51 100644
--- a/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.cpp
+++ b/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.cpp
@@ -26,7 +26,7 @@
#include <windows.h>
#include "common/platform.h"
-#if _WIN32_WINNT_WINBLUE && WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
+#if _WIN32_WINNT_WINBLUE
#include <versionhelpers.h>
#endif
diff --git a/src/3rdparty/angle/src/third_party/trace_event/trace_event.h b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h
index 3c85d22efa..bdb8804428 100644
--- a/src/3rdparty/angle/src/third_party/trace_event/trace_event.h
+++ b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h
@@ -690,27 +690,27 @@ static inline void setTraceValue(const std::string& arg,
// store pointers to the internal c_str and pass through to the tracing API, the
// arg values must live throughout these procedures.
-static inline angle::Platform::TraceEventHandle addTraceEvent(
- char phase,
- const unsigned char* categoryEnabled,
- const char* name,
- unsigned long long id,
- unsigned char flags) {
+static inline angle::TraceEventHandle addTraceEvent(char phase,
+ const unsigned char *categoryEnabled,
+ const char *name,
+ unsigned long long id,
+ unsigned char flags)
+{
return TRACE_EVENT_API_ADD_TRACE_EVENT(
phase, categoryEnabled, name, id,
zeroNumArgs, 0, 0, 0,
flags);
}
-template<class ARG1_TYPE>
-static inline angle::Platform::TraceEventHandle addTraceEvent(
- char phase,
- const unsigned char* categoryEnabled,
- const char* name,
- unsigned long long id,
- unsigned char flags,
- const char* arg1Name,
- const ARG1_TYPE& arg1Val) {
+template <class ARG1_TYPE>
+static inline angle::TraceEventHandle addTraceEvent(char phase,
+ const unsigned char *categoryEnabled,
+ const char *name,
+ unsigned long long id,
+ unsigned char flags,
+ const char *arg1Name,
+ const ARG1_TYPE &arg1Val)
+{
const int numArgs = 1;
unsigned char argTypes[1];
unsigned long long argValues[1];
@@ -721,17 +721,17 @@ static inline angle::Platform::TraceEventHandle addTraceEvent(
flags);
}
-template<class ARG1_TYPE, class ARG2_TYPE>
-static inline angle::Platform::TraceEventHandle addTraceEvent(
- char phase,
- const unsigned char* categoryEnabled,
- const char* name,
- unsigned long long id,
- unsigned char flags,
- const char* arg1Name,
- const ARG1_TYPE& arg1Val,
- const char* arg2Name,
- const ARG2_TYPE& arg2Val) {
+template <class ARG1_TYPE, class ARG2_TYPE>
+static inline angle::TraceEventHandle addTraceEvent(char phase,
+ const unsigned char *categoryEnabled,
+ const char *name,
+ unsigned long long id,
+ unsigned char flags,
+ const char *arg1Name,
+ const ARG1_TYPE &arg1Val,
+ const char *arg2Name,
+ const ARG2_TYPE &arg2Val)
+{
const int numArgs = 2;
const char* argNames[2] = { arg1Name, arg2Name };
unsigned char argTypes[2];
diff --git a/src/3rdparty/double-conversion/bignum-dtoa.cc b/src/3rdparty/double-conversion/bignum-dtoa.cc
index f1ad7a5ae8..526f96edf5 100644
--- a/src/3rdparty/double-conversion/bignum-dtoa.cc
+++ b/src/3rdparty/double-conversion/bignum-dtoa.cc
@@ -25,12 +25,12 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#include <math.h>
+#include <cmath>
-#include "bignum-dtoa.h"
+#include <double-conversion/bignum-dtoa.h>
-#include "bignum.h"
-#include "ieee.h"
+#include <double-conversion/bignum.h>
+#include <double-conversion/ieee.h>
namespace double_conversion {
diff --git a/src/3rdparty/double-conversion/bignum-dtoa.h b/src/3rdparty/double-conversion/bignum-dtoa.h
index 34b961992d..9d15ce3dce 100644
--- a/src/3rdparty/double-conversion/bignum-dtoa.h
+++ b/src/3rdparty/double-conversion/bignum-dtoa.h
@@ -28,7 +28,7 @@
#ifndef DOUBLE_CONVERSION_BIGNUM_DTOA_H_
#define DOUBLE_CONVERSION_BIGNUM_DTOA_H_
-#include "utils.h"
+#include <double-conversion/utils.h>
namespace double_conversion {
diff --git a/src/3rdparty/double-conversion/bignum.cc b/src/3rdparty/double-conversion/bignum.cc
index 2743d67e8d..a7bc86d0c0 100644
--- a/src/3rdparty/double-conversion/bignum.cc
+++ b/src/3rdparty/double-conversion/bignum.cc
@@ -25,13 +25,13 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#include "bignum.h"
-#include "utils.h"
+#include <double-conversion/bignum.h>
+#include <double-conversion/utils.h>
namespace double_conversion {
Bignum::Bignum()
- : bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) {
+ : bigits_buffer_(), bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) {
for (int i = 0; i < kBigitCapacity; ++i) {
bigits_[i] = 0;
}
@@ -104,7 +104,7 @@ void Bignum::AssignDecimalString(Vector<const char> value) {
const int kMaxUint64DecimalDigits = 19;
Zero();
int length = value.length();
- int pos = 0;
+ unsigned int pos = 0;
// Let's just say that each digit needs 4 bits.
while (length >= kMaxUint64DecimalDigits) {
uint64_t digits = ReadUInt64(value, pos, kMaxUint64DecimalDigits);
@@ -445,26 +445,27 @@ void Bignum::AssignPowerUInt16(uint16_t base, int power_exponent) {
mask >>= 2;
uint64_t this_value = base;
- bool delayed_multipliciation = false;
+ bool delayed_multiplication = false;
const uint64_t max_32bits = 0xFFFFFFFF;
while (mask != 0 && this_value <= max_32bits) {
this_value = this_value * this_value;
// Verify that there is enough space in this_value to perform the
// multiplication. The first bit_size bits must be 0.
if ((power_exponent & mask) != 0) {
+ ASSERT(bit_size > 0);
uint64_t base_bits_mask =
~((static_cast<uint64_t>(1) << (64 - bit_size)) - 1);
bool high_bits_zero = (this_value & base_bits_mask) == 0;
if (high_bits_zero) {
this_value *= base;
} else {
- delayed_multipliciation = true;
+ delayed_multiplication = true;
}
}
mask >>= 1;
}
AssignUInt64(this_value);
- if (delayed_multipliciation) {
+ if (delayed_multiplication) {
MultiplyByUInt32(base);
}
diff --git a/src/3rdparty/double-conversion/bignum.h b/src/3rdparty/double-conversion/bignum.h
index 5ec3544f57..238a351196 100644
--- a/src/3rdparty/double-conversion/bignum.h
+++ b/src/3rdparty/double-conversion/bignum.h
@@ -28,7 +28,7 @@
#ifndef DOUBLE_CONVERSION_BIGNUM_H_
#define DOUBLE_CONVERSION_BIGNUM_H_
-#include "utils.h"
+#include <double-conversion/utils.h>
namespace double_conversion {
@@ -49,7 +49,6 @@ class Bignum {
void AssignPowerUInt16(uint16_t base, int exponent);
- void AddUInt16(uint16_t operand);
void AddUInt64(uint64_t operand);
void AddBignum(const Bignum& other);
// Precondition: this >= other.
@@ -137,7 +136,7 @@ class Bignum {
// The Bignum's value equals value(bigits_) * 2^(exponent_ * kBigitSize).
int exponent_;
- DISALLOW_COPY_AND_ASSIGN(Bignum);
+ DC_DISALLOW_COPY_AND_ASSIGN(Bignum);
};
} // namespace double_conversion
diff --git a/src/3rdparty/double-conversion/cached-powers.cc b/src/3rdparty/double-conversion/cached-powers.cc
index 9536f26927..6f771e9c73 100644
--- a/src/3rdparty/double-conversion/cached-powers.cc
+++ b/src/3rdparty/double-conversion/cached-powers.cc
@@ -25,13 +25,13 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#include <stdarg.h>
-#include <limits.h>
-#include <math.h>
+#include <climits>
+#include <cmath>
+#include <cstdarg>
-#include "utils.h"
+#include <double-conversion/utils.h>
-#include "cached-powers.h"
+#include <double-conversion/cached-powers.h>
namespace double_conversion {
@@ -131,7 +131,6 @@ static const CachedPower kCachedPowers[] = {
{UINT64_2PART_C(0xaf87023b, 9bf0ee6b), 1066, 340},
};
-static const int kCachedPowersLength = ARRAY_SIZE(kCachedPowers);
static const int kCachedPowersOffset = 348; // -1 * the first decimal_exponent.
static const double kD_1_LOG2_10 = 0.30102999566398114; // 1 / lg(10)
// Difference between the decimal exponents in the table above.
@@ -144,14 +143,12 @@ void PowersOfTenCache::GetCachedPowerForBinaryExponentRange(
int max_exponent,
DiyFp* power,
int* decimal_exponent) {
- (void)max_exponent; // Silence unused parameter warning in release builds
- (void)kCachedPowersLength; // Silence unused parameter warning in release builds
int kQ = DiyFp::kSignificandSize;
double k = ceil((min_exponent + kQ - 1) * kD_1_LOG2_10);
int foo = kCachedPowersOffset;
int index =
(foo + static_cast<int>(k) - 1) / kDecimalExponentDistance + 1;
- ASSERT(0 <= index && index < kCachedPowersLength);
+ ASSERT(0 <= index && index < static_cast<int>(ARRAY_SIZE(kCachedPowers)));
CachedPower cached_power = kCachedPowers[index];
ASSERT(min_exponent <= cached_power.binary_exponent);
(void) max_exponent; // Mark variable as used.
diff --git a/src/3rdparty/double-conversion/cached-powers.h b/src/3rdparty/double-conversion/cached-powers.h
index 61a50614cf..eabff4a15a 100644
--- a/src/3rdparty/double-conversion/cached-powers.h
+++ b/src/3rdparty/double-conversion/cached-powers.h
@@ -28,7 +28,7 @@
#ifndef DOUBLE_CONVERSION_CACHED_POWERS_H_
#define DOUBLE_CONVERSION_CACHED_POWERS_H_
-#include "diy-fp.h"
+#include <double-conversion/diy-fp.h>
namespace double_conversion {
diff --git a/src/3rdparty/double-conversion/diy-fp.cc b/src/3rdparty/double-conversion/diy-fp.cc
index ddd1891b16..82b0d08af4 100644
--- a/src/3rdparty/double-conversion/diy-fp.cc
+++ b/src/3rdparty/double-conversion/diy-fp.cc
@@ -26,8 +26,8 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#include "diy-fp.h"
-#include "utils.h"
+#include <double-conversion/diy-fp.h>
+#include <double-conversion/utils.h>
namespace double_conversion {
diff --git a/src/3rdparty/double-conversion/diy-fp.h b/src/3rdparty/double-conversion/diy-fp.h
index 9dcf8fbdba..e2011d43e5 100644
--- a/src/3rdparty/double-conversion/diy-fp.h
+++ b/src/3rdparty/double-conversion/diy-fp.h
@@ -28,7 +28,7 @@
#ifndef DOUBLE_CONVERSION_DIY_FP_H_
#define DOUBLE_CONVERSION_DIY_FP_H_
-#include "utils.h"
+#include <double-conversion/utils.h>
namespace double_conversion {
@@ -42,7 +42,7 @@ class DiyFp {
static const int kSignificandSize = 64;
DiyFp() : f_(0), e_(0) {}
- DiyFp(uint64_t f, int e) : f_(f), e_(e) {}
+ DiyFp(uint64_t significand, int exponent) : f_(significand), e_(exponent) {}
// this = this - other.
// The exponents of both numbers must be the same and the significand of this
@@ -76,22 +76,22 @@ class DiyFp {
void Normalize() {
ASSERT(f_ != 0);
- uint64_t f = f_;
- int e = e_;
+ uint64_t significand = f_;
+ int exponent = e_;
// This method is mainly called for normalizing boundaries. In general
// boundaries need to be shifted by 10 bits. We thus optimize for this case.
const uint64_t k10MSBits = UINT64_2PART_C(0xFFC00000, 00000000);
- while ((f & k10MSBits) == 0) {
- f <<= 10;
- e -= 10;
+ while ((significand & k10MSBits) == 0) {
+ significand <<= 10;
+ exponent -= 10;
}
- while ((f & kUint64MSB) == 0) {
- f <<= 1;
- e--;
+ while ((significand & kUint64MSB) == 0) {
+ significand <<= 1;
+ exponent--;
}
- f_ = f;
- e_ = e;
+ f_ = significand;
+ e_ = exponent;
}
static DiyFp Normalize(const DiyFp& a) {
diff --git a/src/3rdparty/double-conversion/double-conversion.cc b/src/3rdparty/double-conversion/double-conversion.cc
index 909985be82..ecd1a5ef3f 100644
--- a/src/3rdparty/double-conversion/double-conversion.cc
+++ b/src/3rdparty/double-conversion/double-conversion.cc
@@ -25,17 +25,18 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#include <limits.h>
-#include <math.h>
+#include <climits>
+#include <locale>
+#include <cmath>
-#include "double-conversion.h"
+#include <double-conversion/double-conversion.h>
-#include "bignum-dtoa.h"
-#include "fast-dtoa.h"
-#include "fixed-dtoa.h"
-#include "ieee.h"
-#include "strtod.h"
-#include "utils.h"
+#include <double-conversion/bignum-dtoa.h>
+#include <double-conversion/fast-dtoa.h>
+#include <double-conversion/fixed-dtoa.h>
+#include <double-conversion/ieee.h>
+#include <double-conversion/strtod.h>
+#include <double-conversion/utils.h>
namespace double_conversion {
@@ -118,7 +119,7 @@ void DoubleToStringConverter::CreateDecimalRepresentation(
StringBuilder* result_builder) const {
// Create a representation that is padded with zeros if needed.
if (decimal_point <= 0) {
- // "0.00000decimal_rep".
+ // "0.00000decimal_rep" or "0.000decimal_rep00".
result_builder->AddCharacter('0');
if (digits_after_point > 0) {
result_builder->AddCharacter('.');
@@ -129,7 +130,7 @@ void DoubleToStringConverter::CreateDecimalRepresentation(
result_builder->AddPadding('0', remaining_digits);
}
} else if (decimal_point >= length) {
- // "decimal_rep0000.00000" or "decimal_rep.0000"
+ // "decimal_rep0000.00000" or "decimal_rep.0000".
result_builder->AddSubstring(decimal_digits, length);
result_builder->AddPadding('0', decimal_point - length);
if (digits_after_point > 0) {
@@ -137,7 +138,7 @@ void DoubleToStringConverter::CreateDecimalRepresentation(
result_builder->AddPadding('0', digits_after_point);
}
} else {
- // "decima.l_rep000"
+ // "decima.l_rep000".
ASSERT(digits_after_point > 0);
result_builder->AddSubstring(decimal_digits, decimal_point);
result_builder->AddCharacter('.');
@@ -414,21 +415,55 @@ void DoubleToStringConverter::DoubleToAscii(double v,
}
+namespace {
+
+inline char ToLower(char ch) {
+ static const std::ctype<char>& cType =
+ std::use_facet<std::ctype<char> >(std::locale::classic());
+ return cType.tolower(ch);
+}
+
+inline char Pass(char ch) {
+ return ch;
+}
+
+template <class Iterator, class Converter>
+static inline bool ConsumeSubStringImpl(Iterator* current,
+ Iterator end,
+ const char* substring,
+ Converter converter) {
+ ASSERT(converter(**current) == *substring);
+ for (substring++; *substring != '\0'; substring++) {
+ ++*current;
+ if (*current == end || converter(**current) != *substring) {
+ return false;
+ }
+ }
+ ++*current;
+ return true;
+}
+
// Consumes the given substring from the iterator.
// Returns false, if the substring does not match.
template <class Iterator>
static bool ConsumeSubString(Iterator* current,
Iterator end,
- const char* substring) {
- ASSERT(**current == *substring);
- for (substring++; *substring != '\0'; substring++) {
- ++*current;
- if (*current == end || **current != *substring) return false;
+ const char* substring,
+ bool allow_case_insensibility) {
+ if (allow_case_insensibility) {
+ return ConsumeSubStringImpl(current, end, substring, ToLower);
+ } else {
+ return ConsumeSubStringImpl(current, end, substring, Pass);
}
- ++*current;
- return true;
}
+// Consumes first character of the str is equal to ch
+inline bool ConsumeFirstCharacter(char ch,
+ const char* str,
+ bool case_insensibility) {
+ return case_insensibility ? ToLower(ch) == str[0] : ch == str[0];
+}
+} // namespace
// Maximum number of significant digits in decimal representation.
// The longest possible double in decimal representation is
@@ -494,10 +529,17 @@ static double SignedZero(bool sign) {
// because it constant-propagated the radix and concluded that the last
// condition was always true. By moving it into a separate function the
// compiler wouldn't warn anymore.
+#if _MSC_VER
+#pragma optimize("",off)
static bool IsDecimalDigitForRadix(int c, int radix) {
return '0' <= c && c <= '9' && (c - '0') < radix;
}
-
+#pragma optimize("",on)
+#else
+static bool inline IsDecimalDigitForRadix(int c, int radix) {
+ return '0' <= c && c <= '9' && (c - '0') < radix;
+}
+#endif
// Returns true if 'c' is a character digit that is valid for the given radix.
// The 'a_character' should be 'a' or 'A'.
//
@@ -509,17 +551,86 @@ static bool IsCharacterDigitForRadix(int c, int radix, char a_character) {
return radix > 10 && c >= a_character && c < a_character + radix - 10;
}
+// Returns true, when the iterator is equal to end.
+template<class Iterator>
+static bool Advance (Iterator* it, char separator, int base, Iterator& end) {
+ if (separator == StringToDoubleConverter::kNoSeparator) {
+ ++(*it);
+ return *it == end;
+ }
+ if (!isDigit(**it, base)) {
+ ++(*it);
+ return *it == end;
+ }
+ ++(*it);
+ if (*it == end) return true;
+ if (*it + 1 == end) return false;
+ if (**it == separator && isDigit(*(*it + 1), base)) {
+ ++(*it);
+ }
+ return *it == end;
+}
+
+// Checks whether the string in the range start-end is a hex-float string.
+// This function assumes that the leading '0x'/'0X' is already consumed.
+//
+// Hex float strings are of one of the following forms:
+// - hex_digits+ 'p' ('+'|'-')? exponent_digits+
+// - hex_digits* '.' hex_digits+ 'p' ('+'|'-')? exponent_digits+
+// - hex_digits+ '.' 'p' ('+'|'-')? exponent_digits+
+template<class Iterator>
+static bool IsHexFloatString(Iterator start,
+ Iterator end,
+ char separator,
+ bool allow_trailing_junk) {
+ ASSERT(start != end);
+
+ Iterator current = start;
+
+ bool saw_digit = false;
+ while (isDigit(*current, 16)) {
+ saw_digit = true;
+ if (Advance(&current, separator, 16, end)) return false;
+ }
+ if (*current == '.') {
+ if (Advance(&current, separator, 16, end)) return false;
+ while (isDigit(*current, 16)) {
+ saw_digit = true;
+ if (Advance(&current, separator, 16, end)) return false;
+ }
+ if (!saw_digit) return false; // Only the '.', but no digits.
+ }
+ if (*current != 'p' && *current != 'P') return false;
+ if (Advance(&current, separator, 16, end)) return false;
+ if (*current == '+' || *current == '-') {
+ if (Advance(&current, separator, 16, end)) return false;
+ }
+ if (!isDigit(*current, 10)) return false;
+ if (Advance(&current, separator, 16, end)) return true;
+ while (isDigit(*current, 10)) {
+ if (Advance(&current, separator, 16, end)) return true;
+ }
+ return allow_trailing_junk || !AdvanceToNonspace(&current, end);
+}
+
// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
+//
+// If parse_as_hex_float is true, then the string must be a valid
+// hex-float.
template <int radix_log_2, class Iterator>
static double RadixStringToIeee(Iterator* current,
Iterator end,
bool sign,
+ char separator,
+ bool parse_as_hex_float,
bool allow_trailing_junk,
double junk_string_value,
bool read_as_double,
bool* result_is_junk) {
ASSERT(*current != end);
+ ASSERT(!parse_as_hex_float ||
+ IsHexFloatString(*current, end, separator, allow_trailing_junk));
const int kDoubleSize = Double::kSignificandSize;
const int kSingleSize = Single::kSignificandSize;
@@ -527,27 +638,39 @@ static double RadixStringToIeee(Iterator* current,
*result_is_junk = true;
+ int64_t number = 0;
+ int exponent = 0;
+ const int radix = (1 << radix_log_2);
+ // Whether we have encountered a '.' and are parsing the decimal digits.
+ // Only relevant if parse_as_hex_float is true.
+ bool post_decimal = false;
+
// Skip leading 0s.
while (**current == '0') {
- ++(*current);
- if (*current == end) {
+ if (Advance(current, separator, radix, end)) {
*result_is_junk = false;
return SignedZero(sign);
}
}
- int64_t number = 0;
- int exponent = 0;
- const int radix = (1 << radix_log_2);
-
- do {
+ while (true) {
int digit;
if (IsDecimalDigitForRadix(**current, radix)) {
digit = static_cast<char>(**current) - '0';
+ if (post_decimal) exponent -= radix_log_2;
} else if (IsCharacterDigitForRadix(**current, radix, 'a')) {
digit = static_cast<char>(**current) - 'a' + 10;
+ if (post_decimal) exponent -= radix_log_2;
} else if (IsCharacterDigitForRadix(**current, radix, 'A')) {
digit = static_cast<char>(**current) - 'A' + 10;
+ if (post_decimal) exponent -= radix_log_2;
+ } else if (parse_as_hex_float && **current == '.') {
+ post_decimal = true;
+ Advance(current, separator, radix, end);
+ ASSERT(*current != end);
+ continue;
+ } else if (parse_as_hex_float && (**current == 'p' || **current == 'P')) {
+ break;
} else {
if (allow_trailing_junk || !AdvanceToNonspace(current, end)) {
break;
@@ -570,17 +693,26 @@ static double RadixStringToIeee(Iterator* current,
int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
number >>= overflow_bits_count;
- exponent = overflow_bits_count;
+ exponent += overflow_bits_count;
bool zero_tail = true;
for (;;) {
- ++(*current);
- if (*current == end || !isDigit(**current, radix)) break;
+ if (Advance(current, separator, radix, end)) break;
+ if (parse_as_hex_float && **current == '.') {
+ // Just run over the '.'. We are just trying to see whether there is
+ // a non-zero digit somewhere.
+ Advance(current, separator, radix, end);
+ ASSERT(*current != end);
+ post_decimal = true;
+ }
+ if (!isDigit(**current, radix)) break;
zero_tail = zero_tail && **current == '0';
- exponent += radix_log_2;
+ if (!post_decimal) exponent += radix_log_2;
}
- if (!allow_trailing_junk && AdvanceToNonspace(current, end)) {
+ if (!parse_as_hex_float &&
+ !allow_trailing_junk &&
+ AdvanceToNonspace(current, end)) {
return junk_string_value;
}
@@ -602,15 +734,37 @@ static double RadixStringToIeee(Iterator* current,
}
break;
}
- ++(*current);
- } while (*current != end);
+ if (Advance(current, separator, radix, end)) break;
+ }
ASSERT(number < ((int64_t)1 << kSignificandSize));
ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
*result_is_junk = false;
- if (exponent == 0) {
+ if (parse_as_hex_float) {
+ ASSERT(**current == 'p' || **current == 'P');
+ Advance(current, separator, radix, end);
+ ASSERT(*current != end);
+ bool is_negative = false;
+ if (**current == '+') {
+ Advance(current, separator, radix, end);
+ ASSERT(*current != end);
+ } else if (**current == '-') {
+ is_negative = true;
+ Advance(current, separator, radix, end);
+ ASSERT(*current != end);
+ }
+ int written_exponent = 0;
+ while (IsDecimalDigitForRadix(**current, 10)) {
+ written_exponent = 10 * written_exponent + **current - '0';
+ if (Advance(current, separator, radix, end)) break;
+ }
+ if (is_negative) written_exponent = -written_exponent;
+ exponent += written_exponent;
+ }
+
+ if (exponent == 0 || number == 0) {
if (sign) {
if (number == 0) return -0.0;
number = -number;
@@ -619,10 +773,10 @@ static double RadixStringToIeee(Iterator* current,
}
ASSERT(number != 0);
- return Double(DiyFp(number, exponent)).value();
+ double result = Double(DiyFp(number, exponent)).value();
+ return sign ? -result : result;
}
-
template <class Iterator>
double StringToDoubleConverter::StringToIeee(
Iterator input,
@@ -638,6 +792,7 @@ double StringToDoubleConverter::StringToIeee(
const bool allow_leading_spaces = (flags_ & ALLOW_LEADING_SPACES) != 0;
const bool allow_trailing_spaces = (flags_ & ALLOW_TRAILING_SPACES) != 0;
const bool allow_spaces_after_sign = (flags_ & ALLOW_SPACES_AFTER_SIGN) != 0;
+ const bool allow_case_insensibility = (flags_ & ALLOW_CASE_INSENSIBILITY) != 0;
// To make sure that iterator dereferencing is valid the following
// convention is used:
@@ -687,8 +842,8 @@ double StringToDoubleConverter::StringToIeee(
}
if (infinity_symbol_ != NULL) {
- if (*current == infinity_symbol_[0]) {
- if (!ConsumeSubString(&current, end, infinity_symbol_)) {
+ if (ConsumeFirstCharacter(*current, infinity_symbol_, allow_case_insensibility)) {
+ if (!ConsumeSubString(&current, end, infinity_symbol_, allow_case_insensibility)) {
return junk_string_value_;
}
@@ -706,8 +861,8 @@ double StringToDoubleConverter::StringToIeee(
}
if (nan_symbol_ != NULL) {
- if (*current == nan_symbol_[0]) {
- if (!ConsumeSubString(&current, end, nan_symbol_)) {
+ if (ConsumeFirstCharacter(*current, nan_symbol_, allow_case_insensibility)) {
+ if (!ConsumeSubString(&current, end, nan_symbol_, allow_case_insensibility)) {
return junk_string_value_;
}
@@ -726,8 +881,7 @@ double StringToDoubleConverter::StringToIeee(
bool leading_zero = false;
if (*current == '0') {
- ++current;
- if (current == end) {
+ if (Advance(&current, separator_, 10, end)) {
*processed_characters_count = static_cast<int>(current - input);
return SignedZero(sign);
}
@@ -735,16 +889,24 @@ double StringToDoubleConverter::StringToIeee(
leading_zero = true;
// It could be hexadecimal value.
- if ((flags_ & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
+ if (((flags_ & ALLOW_HEX) || (flags_ & ALLOW_HEX_FLOATS)) &&
+ (*current == 'x' || *current == 'X')) {
++current;
- if (current == end || !isDigit(*current, 16)) {
- return junk_string_value_; // "0x".
+
+ bool parse_as_hex_float = (flags_ & ALLOW_HEX_FLOATS) &&
+ IsHexFloatString(current, end, separator_, allow_trailing_junk);
+
+ if (current == end) return junk_string_value_; // "0x"
+ if (!parse_as_hex_float && !isDigit(*current, 16)) {
+ return junk_string_value_;
}
bool result_is_junk;
double result = RadixStringToIeee<4>(&current,
end,
sign,
+ separator_,
+ parse_as_hex_float,
allow_trailing_junk,
junk_string_value_,
read_as_double,
@@ -758,8 +920,7 @@ double StringToDoubleConverter::StringToIeee(
// Ignore leading zeros in the integer part.
while (*current == '0') {
- ++current;
- if (current == end) {
+ if (Advance(&current, separator_, 10, end)) {
*processed_characters_count = static_cast<int>(current - input);
return SignedZero(sign);
}
@@ -780,8 +941,7 @@ double StringToDoubleConverter::StringToIeee(
nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
}
octal = octal && *current < '8';
- ++current;
- if (current == end) goto parsing_done;
+ if (Advance(&current, separator_, 10, end)) goto parsing_done;
}
if (significant_digits == 0) {
@@ -792,8 +952,7 @@ double StringToDoubleConverter::StringToIeee(
if (octal && !allow_trailing_junk) return junk_string_value_;
if (octal) goto parsing_done;
- ++current;
- if (current == end) {
+ if (Advance(&current, separator_, 10, end)) {
if (significant_digits == 0 && !leading_zero) {
return junk_string_value_;
} else {
@@ -806,8 +965,7 @@ double StringToDoubleConverter::StringToIeee(
// Integer part consists of 0 or is absent. Significant digits start after
// leading zeros (if any).
while (*current == '0') {
- ++current;
- if (current == end) {
+ if (Advance(&current, separator_, 10, end)) {
*processed_characters_count = static_cast<int>(current - input);
return SignedZero(sign);
}
@@ -827,8 +985,7 @@ double StringToDoubleConverter::StringToIeee(
// Ignore insignificant digits in the fractional part.
nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
}
- ++current;
- if (current == end) goto parsing_done;
+ if (Advance(&current, separator_, 10, end)) goto parsing_done;
}
}
@@ -844,20 +1001,23 @@ double StringToDoubleConverter::StringToIeee(
if (*current == 'e' || *current == 'E') {
if (octal && !allow_trailing_junk) return junk_string_value_;
if (octal) goto parsing_done;
+ Iterator junk_begin = current;
++current;
if (current == end) {
if (allow_trailing_junk) {
+ current = junk_begin;
goto parsing_done;
} else {
return junk_string_value_;
}
}
- char sign = '+';
+ char exponen_sign = '+';
if (*current == '+' || *current == '-') {
- sign = static_cast<char>(*current);
+ exponen_sign = static_cast<char>(*current);
++current;
if (current == end) {
if (allow_trailing_junk) {
+ current = junk_begin;
goto parsing_done;
} else {
return junk_string_value_;
@@ -867,6 +1027,7 @@ double StringToDoubleConverter::StringToIeee(
if (current == end || *current < '0' || *current > '9') {
if (allow_trailing_junk) {
+ current = junk_begin;
goto parsing_done;
} else {
return junk_string_value_;
@@ -888,7 +1049,7 @@ double StringToDoubleConverter::StringToIeee(
++current;
} while (current != end && *current >= '0' && *current <= '9');
- exponent += (sign == '-' ? -num : num);
+ exponent += (exponen_sign == '-' ? -num : num);
}
if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
@@ -911,6 +1072,8 @@ double StringToDoubleConverter::StringToIeee(
result = RadixStringToIeee<3>(&start,
buffer + buffer_pos,
sign,
+ separator_,
+ false, // Don't parse as hex_float.
allow_trailing_junk,
junk_string_value_,
read_as_double,
diff --git a/src/3rdparty/double-conversion/double-conversion.pri b/src/3rdparty/double-conversion/double-conversion.pri
index 3207169689..6564f960d4 100644
--- a/src/3rdparty/double-conversion/double-conversion.pri
+++ b/src/3rdparty/double-conversion/double-conversion.pri
@@ -1,4 +1,4 @@
-INCLUDEPATH += $$PWD/include $$PWD/include/double-conversion
+INCLUDEPATH += $$PWD/.. $$PWD/include $$PWD/include/double-conversion
SOURCES += \
$$PWD/bignum.cc \
$$PWD/bignum-dtoa.cc \
diff --git a/src/3rdparty/double-conversion/fast-dtoa.cc b/src/3rdparty/double-conversion/fast-dtoa.cc
index 61350383a9..e5c222291f 100644
--- a/src/3rdparty/double-conversion/fast-dtoa.cc
+++ b/src/3rdparty/double-conversion/fast-dtoa.cc
@@ -25,11 +25,11 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#include "fast-dtoa.h"
+#include <double-conversion/fast-dtoa.h>
-#include "cached-powers.h"
-#include "diy-fp.h"
-#include "ieee.h"
+#include <double-conversion/cached-powers.h>
+#include <double-conversion/diy-fp.h>
+#include <double-conversion/ieee.h>
namespace double_conversion {
diff --git a/src/3rdparty/double-conversion/fast-dtoa.h b/src/3rdparty/double-conversion/fast-dtoa.h
index 5f1e8eee5e..ac4317c04d 100644
--- a/src/3rdparty/double-conversion/fast-dtoa.h
+++ b/src/3rdparty/double-conversion/fast-dtoa.h
@@ -28,7 +28,7 @@
#ifndef DOUBLE_CONVERSION_FAST_DTOA_H_
#define DOUBLE_CONVERSION_FAST_DTOA_H_
-#include "utils.h"
+#include <double-conversion/utils.h>
namespace double_conversion {
diff --git a/src/3rdparty/double-conversion/fixed-dtoa.cc b/src/3rdparty/double-conversion/fixed-dtoa.cc
index aef65fdc21..8c111aca64 100644
--- a/src/3rdparty/double-conversion/fixed-dtoa.cc
+++ b/src/3rdparty/double-conversion/fixed-dtoa.cc
@@ -25,10 +25,10 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#include <math.h>
+#include <cmath>
-#include "fixed-dtoa.h"
-#include "ieee.h"
+#include <double-conversion/fixed-dtoa.h>
+#include <double-conversion/ieee.h>
namespace double_conversion {
@@ -98,7 +98,7 @@ class UInt128 {
return high_bits_ == 0 && low_bits_ == 0;
}
- int BitAt(int position) {
+ int BitAt(int position) const {
if (position >= 64) {
return static_cast<int>(high_bits_ >> (position - 64)) & 1;
} else {
@@ -259,7 +259,8 @@ static void FillFractionals(uint64_t fractionals, int exponent,
fractionals -= static_cast<uint64_t>(digit) << point;
}
// If the first bit after the point is set we have to round up.
- if (((fractionals >> (point - 1)) & 1) == 1) {
+ ASSERT(fractionals == 0 || point - 1 >= 0);
+ if ((fractionals != 0) && ((fractionals >> (point - 1)) & 1) == 1) {
RoundUp(buffer, length, decimal_point);
}
} else { // We need 128 bits.
diff --git a/src/3rdparty/double-conversion/fixed-dtoa.h b/src/3rdparty/double-conversion/fixed-dtoa.h
index 3bdd08e21f..a9436fc9f6 100644
--- a/src/3rdparty/double-conversion/fixed-dtoa.h
+++ b/src/3rdparty/double-conversion/fixed-dtoa.h
@@ -28,7 +28,7 @@
#ifndef DOUBLE_CONVERSION_FIXED_DTOA_H_
#define DOUBLE_CONVERSION_FIXED_DTOA_H_
-#include "utils.h"
+#include <double-conversion/utils.h>
namespace double_conversion {
diff --git a/src/3rdparty/double-conversion/ieee.h b/src/3rdparty/double-conversion/ieee.h
index 661141d1a8..baaeced31c 100644
--- a/src/3rdparty/double-conversion/ieee.h
+++ b/src/3rdparty/double-conversion/ieee.h
@@ -28,7 +28,7 @@
#ifndef DOUBLE_CONVERSION_DOUBLE_H_
#define DOUBLE_CONVERSION_DOUBLE_H_
-#include "diy-fp.h"
+#include <double-conversion/diy-fp.h>
namespace double_conversion {
@@ -99,7 +99,7 @@ class Double {
}
double PreviousDouble() const {
- if (d64_ == (kInfinity | kSignMask)) return -Double::Infinity();
+ if (d64_ == (kInfinity | kSignMask)) return -Infinity();
if (Sign() < 0) {
return Double(d64_ + 1).value();
} else {
@@ -257,7 +257,7 @@ class Double {
(biased_exponent << kPhysicalSignificandSize);
}
- DISALLOW_COPY_AND_ASSIGN(Double);
+ DC_DISALLOW_COPY_AND_ASSIGN(Double);
};
class Single {
@@ -394,7 +394,7 @@ class Single {
const uint32_t d32_;
- DISALLOW_COPY_AND_ASSIGN(Single);
+ DC_DISALLOW_COPY_AND_ASSIGN(Single);
};
} // namespace double_conversion
diff --git a/src/3rdparty/double-conversion/include/double-conversion/double-conversion.h b/src/3rdparty/double-conversion/include/double-conversion/double-conversion.h
index 6bdfa8d25d..7495d17a1d 100644
--- a/src/3rdparty/double-conversion/include/double-conversion/double-conversion.h
+++ b/src/3rdparty/double-conversion/include/double-conversion/double-conversion.h
@@ -28,7 +28,7 @@
#ifndef DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_
#define DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_
-#include "utils.h"
+#include <double-conversion/utils.h>
namespace double_conversion {
@@ -294,13 +294,18 @@ class DoubleToStringConverter {
// should be at least kBase10MaximalLength + 1 characters long.
static const int kBase10MaximalLength = 17;
- // Converts the given double 'v' to ascii. 'v' must not be NaN, +Infinity, or
- // -Infinity. In SHORTEST_SINGLE-mode this restriction also applies to 'v'
- // after it has been casted to a single-precision float. That is, in this
- // mode static_cast<float>(v) must not be NaN, +Infinity or -Infinity.
+ // Converts the given double 'v' to digit characters. 'v' must not be NaN,
+ // +Infinity, or -Infinity. In SHORTEST_SINGLE-mode this restriction also
+ // applies to 'v' after it has been casted to a single-precision float. That
+ // is, in this mode static_cast<float>(v) must not be NaN, +Infinity or
+ // -Infinity.
//
// The result should be interpreted as buffer * 10^(point-length).
//
+ // The digits are written to the buffer in the platform's charset, which is
+ // often UTF-8 (with ASCII-range digits) but may be another charset, such
+ // as EBCDIC.
+ //
// The output depends on the given mode:
// - SHORTEST: produce the least amount of digits for which the internal
// identity requirement is still satisfied. If the digits are printed
@@ -374,7 +379,7 @@ class DoubleToStringConverter {
const int max_leading_padding_zeroes_in_precision_mode_;
const int max_trailing_padding_zeroes_in_precision_mode_;
- DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter);
+ DC_DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter);
};
@@ -389,9 +394,13 @@ class StringToDoubleConverter {
ALLOW_TRAILING_JUNK = 4,
ALLOW_LEADING_SPACES = 8,
ALLOW_TRAILING_SPACES = 16,
- ALLOW_SPACES_AFTER_SIGN = 32
+ ALLOW_SPACES_AFTER_SIGN = 32,
+ ALLOW_CASE_INSENSIBILITY = 64,
+ ALLOW_HEX_FLOATS = 128,
};
+ static const uc16 kNoSeparator = '\0';
+
// Flags should be a bit-or combination of the possible Flags-enum.
// - NO_FLAGS: no special flags.
// - ALLOW_HEX: recognizes the prefix "0x". Hex numbers may only be integers.
@@ -421,6 +430,13 @@ class StringToDoubleConverter {
// - ALLOW_SPACES_AFTER_SIGN: ignore whitespace after the sign.
// Ex: StringToDouble("- 123.2") -> -123.2.
// StringToDouble("+ 123.2") -> 123.2
+ // - ALLOW_CASE_INSENSIBILITY: ignore case of characters for special values:
+ // infinity and nan.
+ // - ALLOW_HEX_FLOATS: allows hexadecimal float literals.
+ // This *must* start with "0x" and separate the exponent with "p".
+ // Examples: 0x1.2p3 == 9.0
+ // 0x10.1p0 == 16.0625
+ // ALLOW_HEX and ALLOW_HEX_FLOATS are indendent.
//
// empty_string_value is returned when an empty string is given as input.
// If ALLOW_LEADING_SPACES or ALLOW_TRAILING_SPACES are set, then a string
@@ -445,6 +461,12 @@ class StringToDoubleConverter {
// - they must not have the same first character.
// - they must not start with digits.
//
+ // If the separator character is not kNoSeparator, then that specific
+ // character is ignored when in between two valid digits of the significant.
+ // It is not allowed to appear in the exponent.
+ // It is not allowed to lead or trail the number.
+ // It is not allowed to appear twice next to each other.
+ //
// Examples:
// flags = ALLOW_HEX | ALLOW_TRAILING_JUNK,
// empty_string_value = 0.0,
@@ -484,16 +506,26 @@ class StringToDoubleConverter {
// StringToDouble("01239E45") -> 1239e45.
// StringToDouble("-infinity") -> NaN // junk_string_value.
// StringToDouble("NaN") -> NaN // junk_string_value.
+ //
+ // flags = NO_FLAGS,
+ // separator = ' ':
+ // StringToDouble("1 2 3 4") -> 1234.0
+ // StringToDouble("1 2") -> NaN // junk_string_value
+ // StringToDouble("1 000 000.0") -> 1000000.0
+ // StringToDouble("1.000 000") -> 1.0
+ // StringToDouble("1.0e1 000") -> NaN // junk_string_value
StringToDoubleConverter(int flags,
double empty_string_value,
double junk_string_value,
const char* infinity_symbol,
- const char* nan_symbol)
+ const char* nan_symbol,
+ uc16 separator = kNoSeparator)
: flags_(flags),
empty_string_value_(empty_string_value),
junk_string_value_(junk_string_value),
infinity_symbol_(infinity_symbol),
- nan_symbol_(nan_symbol) {
+ nan_symbol_(nan_symbol),
+ separator_(separator) {
}
// Performs the conversion.
@@ -528,6 +560,7 @@ class StringToDoubleConverter {
const double junk_string_value_;
const char* const infinity_symbol_;
const char* const nan_symbol_;
+ const uc16 separator_;
template <class Iterator>
double StringToIeee(Iterator start_pointer,
@@ -535,7 +568,7 @@ class StringToDoubleConverter {
bool read_as_double,
int* processed_characters_count) const;
- DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter);
+ DC_DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter);
};
} // namespace double_conversion
diff --git a/src/3rdparty/double-conversion/include/double-conversion/utils.h b/src/3rdparty/double-conversion/include/double-conversion/utils.h
index 20bfd36c84..7622fe6162 100644
--- a/src/3rdparty/double-conversion/include/double-conversion/utils.h
+++ b/src/3rdparty/double-conversion/include/double-conversion/utils.h
@@ -28,25 +28,35 @@
#ifndef DOUBLE_CONVERSION_UTILS_H_
#define DOUBLE_CONVERSION_UTILS_H_
-#include <stdlib.h>
-#include <string.h>
+#include <cstdlib>
+#include <cstring>
-#include <assert.h>
+#include <cassert>
#ifndef ASSERT
-# if defined(WINCE) || defined(_WIN32_WCE)
-# define ASSERT(condition)
-# else
-# define ASSERT(condition) \
+#define ASSERT(condition) \
assert(condition);
-# endif
#endif
#ifndef UNIMPLEMENTED
-# define UNIMPLEMENTED() (exit(-1))
+#define UNIMPLEMENTED() (abort())
+#endif
+#ifndef DOUBLE_CONVERSION_NO_RETURN
+#ifdef _MSC_VER
+#define DOUBLE_CONVERSION_NO_RETURN __declspec(noreturn)
+#else
+#define DOUBLE_CONVERSION_NO_RETURN __attribute__((noreturn))
+#endif
#endif
#ifndef UNREACHABLE
-# define UNREACHABLE() (exit(-1))
+#ifdef _MSC_VER
+void DOUBLE_CONVERSION_NO_RETURN abort_noreturn();
+inline void abort_noreturn() { abort(); }
+#define UNREACHABLE() (abort_noreturn())
+#else
+#define UNREACHABLE() (abort())
+#endif
#endif
+
// Double operations detection based on target architecture.
// Linux uses a 80bit wide floating point stack on x86. This induces double
// rounding, which in turn leads to wrong results.
@@ -57,16 +67,38 @@
// the output of the division with the expected result. (Inlining must be
// disabled.)
// On Linux,x86 89255e-22 != Div_double(89255.0/1e22)
+//
+// For example:
+/*
+// -- in div.c
+double Div_double(double x, double y) { return x / y; }
+
+// -- in main.c
+double Div_double(double x, double y); // Forward declaration.
+
+int main(int argc, char** argv) {
+ return Div_double(89255.0, 1e22) == 89255e-22;
+}
+*/
+// Run as follows ./main || echo "correct"
+//
+// If it prints "correct" then the architecture should be here, in the "correct" section.
#if defined(_M_X64) || defined(__x86_64__) || \
- defined(__ARMEL__) || defined(__avr32__) || _M_ARM_FP || \
+ defined(__ARMEL__) || defined(__avr32__) || defined(_M_ARM) || defined(_M_ARM64) || \
defined(__hppa__) || defined(__ia64__) || \
defined(__mips__) || \
defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \
+ defined(_POWER) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
defined(__sparc__) || defined(__sparc) || defined(__s390__) || \
defined(__SH4__) || defined(__alpha__) || \
defined(_MIPS_ARCH_MIPS32R2) || \
- defined(__AARCH64EL__)
+ defined(__AARCH64EL__) || defined(__aarch64__) || defined(__AARCH64EB__) || \
+ defined(__riscv) || defined(__EMSCRIPTEN__) || \
+ defined(__or1k__)
#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
+#elif defined(__mc68000__) || \
+ defined(__pnacl__) || defined(__native_client__)
+#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
#elif defined(_M_IX86) || defined(__i386__) || defined(__i386)
#if defined(_WIN32)
// Windows uses a 64bit wide floating point stack.
@@ -81,12 +113,6 @@
#error Target architecture was not detected as supported by Double-Conversion.
#endif
-#if defined(__GNUC__)
-#define DOUBLE_CONVERSION_UNUSED __attribute__((unused))
-#else
-#define DOUBLE_CONVERSION_UNUSED
-#endif
-
#if defined(_WIN32) && !defined(__MINGW32__)
typedef signed char int8_t;
@@ -125,8 +151,8 @@ typedef uint16_t uc16;
// A macro to disallow the evil copy constructor and operator= functions
// This should be used in the private: declarations for a class
-#ifndef DISALLOW_COPY_AND_ASSIGN
-#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+#ifndef DC_DISALLOW_COPY_AND_ASSIGN
+#define DC_DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
#endif
@@ -137,10 +163,10 @@ typedef uint16_t uc16;
// This should be used in the private: declarations for a class
// that wants to prevent anyone from instantiating it. This is
// especially useful for classes containing only static methods.
-#ifndef DISALLOW_IMPLICIT_CONSTRUCTORS
-#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
+#ifndef DC_DISALLOW_IMPLICIT_CONSTRUCTORS
+#define DC_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
TypeName(); \
- DISALLOW_COPY_AND_ASSIGN(TypeName)
+ DC_DISALLOW_COPY_AND_ASSIGN(TypeName)
#endif
namespace double_conversion {
@@ -172,8 +198,8 @@ template <typename T>
class Vector {
public:
Vector() : start_(NULL), length_(0) {}
- Vector(T* data, int length) : start_(data), length_(length) {
- ASSERT(length == 0 || (length > 0 && data != NULL));
+ Vector(T* data, int len) : start_(data), length_(len) {
+ ASSERT(len == 0 || (len > 0 && data != NULL));
}
// Returns a vector using the same backing storage as this one,
@@ -215,8 +241,8 @@ class Vector {
// buffer bounds on all operations in debug mode.
class StringBuilder {
public:
- StringBuilder(char* buffer, int size)
- : buffer_(buffer, size), position_(0) { }
+ StringBuilder(char* buffer, int buffer_size)
+ : buffer_(buffer, buffer_size), position_(0) { }
~StringBuilder() { if (!is_finalized()) Finalize(); }
@@ -282,7 +308,7 @@ class StringBuilder {
bool is_finalized() const { return position_ < 0; }
- DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
+ DC_DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
};
// The type-based aliasing rule allows the compiler to assume that pointers of
@@ -313,8 +339,12 @@ template <class Dest, class Source>
inline Dest BitCast(const Source& source) {
// Compile time assertion: sizeof(Dest) == sizeof(Source)
// A compile error here means your Dest and Source have different sizes.
- DOUBLE_CONVERSION_UNUSED
- typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
+#if __cplusplus >= 201103L
+ static_assert(sizeof(Dest) == sizeof(Source),
+ "source and destination size mismatch");
+#else
+ typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
+#endif
Dest dest;
memmove(&dest, &source, sizeof(dest));
diff --git a/src/3rdparty/double-conversion/qt_attribution.json b/src/3rdparty/double-conversion/qt_attribution.json
index 92118ac779..1d244a69b4 100644
--- a/src/3rdparty/double-conversion/qt_attribution.json
+++ b/src/3rdparty/double-conversion/qt_attribution.json
@@ -5,8 +5,8 @@
"QtUsage": "Used in Qt Core. Configure with -system-doubleconversion or -no-doubleconversion to avoid.",
"Homepage": "https://github.com/google/double-conversion",
- "Version": "2.0.1",
- "DownloadLocation": "https://github.com/google/double-conversion/commit/2fb03de56faa32bbba5e02222528e7b760f71d77",
+ "Version": "3.1.1",
+ "DownloadLocation": "https://github.com/google/double-conversion/commit/4199ef3d456ed0549e5665cf4186f0ee6210db3b",
"License": "BSD 3-clause \"New\" or \"Revised\" License",
"LicenseId": "BSD-3-Clause",
"LicenseFile": "LICENSE",
diff --git a/src/3rdparty/double-conversion/strtod.cc b/src/3rdparty/double-conversion/strtod.cc
index 34717562bd..e8cc13f2de 100644
--- a/src/3rdparty/double-conversion/strtod.cc
+++ b/src/3rdparty/double-conversion/strtod.cc
@@ -25,13 +25,13 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#include <stdarg.h>
-#include <limits.h>
+#include <climits>
+#include <cstdarg>
-#include "strtod.h"
-#include "bignum.h"
-#include "cached-powers.h"
-#include "ieee.h"
+#include <double-conversion/bignum.h>
+#include <double-conversion/cached-powers.h>
+#include <double-conversion/ieee.h>
+#include <double-conversion/strtod.h>
namespace double_conversion {
@@ -205,7 +205,7 @@ static bool DoubleStrtod(Vector<const char> trimmed,
// Note that the ARM simulator is compiled for 32bits. It therefore exhibits
// the same problem.
return false;
-#endif
+#else
if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) {
int read_digits;
// The trimmed input fits into a double.
@@ -243,6 +243,7 @@ static bool DoubleStrtod(Vector<const char> trimmed,
}
}
return false;
+#endif
}
@@ -286,7 +287,7 @@ static bool DiyFpStrtod(Vector<const char> buffer,
const int kDenominator = 1 << kDenominatorLog;
// Move the remaining decimals into the exponent.
exponent += remaining_decimals;
- int error = (remaining_decimals == 0 ? 0 : kDenominator / 2);
+ uint64_t error = (remaining_decimals == 0 ? 0 : kDenominator / 2);
int old_e = input.e();
input.Normalize();
@@ -471,6 +472,30 @@ double Strtod(Vector<const char> buffer, int exponent) {
}
}
+static float SanitizedDoubletof(double d) {
+ ASSERT(d >= 0.0);
+ // ASAN has a sanitize check that disallows casting doubles to floats if
+ // they are too big.
+ // https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#available-checks
+ // The behavior should be covered by IEEE 754, but some projects use this
+ // flag, so work around it.
+ float max_finite = 3.4028234663852885981170418348451692544e+38;
+ // The half-way point between the max-finite and infinity value.
+ // Since infinity has an even significand everything equal or greater than
+ // this value should become infinity.
+ double half_max_finite_infinity =
+ 3.40282356779733661637539395458142568448e+38;
+ if (d >= max_finite) {
+ if (d >= half_max_finite_infinity) {
+ return Single::Infinity();
+ } else {
+ return max_finite;
+ }
+ } else {
+ return static_cast<float>(d);
+ }
+}
+
float Strtof(Vector<const char> buffer, int exponent) {
char copy_buffer[kMaxSignificantDecimalDigits];
Vector<const char> trimmed;
@@ -482,7 +507,7 @@ float Strtof(Vector<const char> buffer, int exponent) {
double double_guess;
bool is_correct = ComputeGuess(trimmed, exponent, &double_guess);
- float float_guess = static_cast<float>(double_guess);
+ float float_guess = SanitizedDoubletof(double_guess);
if (float_guess == double_guess) {
// This shortcut triggers for integer values.
return float_guess;
@@ -505,15 +530,15 @@ float Strtof(Vector<const char> buffer, int exponent) {
double double_next = Double(double_guess).NextDouble();
double double_previous = Double(double_guess).PreviousDouble();
- float f1 = static_cast<float>(double_previous);
+ float f1 = SanitizedDoubletof(double_previous);
float f2 = float_guess;
- float f3 = static_cast<float>(double_next);
+ float f3 = SanitizedDoubletof(double_next);
float f4;
if (is_correct) {
f4 = f3;
} else {
double double_next2 = Double(double_next).NextDouble();
- f4 = static_cast<float>(double_next2);
+ f4 = SanitizedDoubletof(double_next2);
}
(void) f2; // Mark variable as used.
ASSERT(f1 <= f2 && f2 <= f3 && f3 <= f4);
@@ -528,7 +553,7 @@ float Strtof(Vector<const char> buffer, int exponent) {
(f1 == f2 && f2 != f3 && f3 == f4) ||
(f1 == f2 && f2 == f3 && f3 != f4));
- // guess and next are the two possible canditates (in the same way that
+ // guess and next are the two possible candidates (in the same way that
// double_guess was the lower candidate for a double-precision guess).
float guess = f1;
float next = f4;
diff --git a/src/3rdparty/double-conversion/strtod.h b/src/3rdparty/double-conversion/strtod.h
index ed0293b8f5..322651621f 100644
--- a/src/3rdparty/double-conversion/strtod.h
+++ b/src/3rdparty/double-conversion/strtod.h
@@ -28,7 +28,7 @@
#ifndef DOUBLE_CONVERSION_STRTOD_H_
#define DOUBLE_CONVERSION_STRTOD_H_
-#include "utils.h"
+#include <double-conversion/utils.h>
namespace double_conversion {
diff --git a/src/3rdparty/freetype/qt_attribution.json b/src/3rdparty/freetype/qt_attribution.json
index 4be86e92b6..f46541cf2e 100644
--- a/src/3rdparty/freetype/qt_attribution.json
+++ b/src/3rdparty/freetype/qt_attribution.json
@@ -7,6 +7,8 @@
"Description": "FreeType is a freely available software library to render fonts.",
"Homepage": "http://www.freetype.org",
+ "Version": "2.6.1",
+
"License": "Freetype Project License or GNU General Public License v2.0 only",
"LicenseId": "FTL OR GPL-2.0",
"LicenseFile": "LICENSE.txt",
diff --git a/src/3rdparty/gradle/gradle/wrapper/gradle-wrapper.jar b/src/3rdparty/gradle/gradle/wrapper/gradle-wrapper.jar
index 2b338a935b..f6b961fd5a 100644
--- a/src/3rdparty/gradle/gradle/wrapper/gradle-wrapper.jar
+++ b/src/3rdparty/gradle/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/src/3rdparty/gradle/gradle/wrapper/gradle-wrapper.properties b/src/3rdparty/gradle/gradle/wrapper/gradle-wrapper.properties
index 4244097b7b..bf3de21830 100644
--- a/src/3rdparty/gradle/gradle/wrapper/gradle-wrapper.properties
+++ b/src/3rdparty/gradle/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,5 @@
-#Mon Feb 20 10:43:22 EST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-3.4-bin.zip
diff --git a/src/3rdparty/gradle/gradlew b/src/3rdparty/gradle/gradlew
index eeff5ccf0e..cccdd3d517 100755
--- a/src/3rdparty/gradle/gradlew
+++ b/src/3rdparty/gradle/gradlew
@@ -28,16 +28,16 @@ APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS="-Xmx1024m -Dfile.encoding=UTF-8"
+DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
-warn ( ) {
+warn () {
echo "$*"
}
-die ( ) {
+die () {
echo
echo "$*"
echo
@@ -155,7 +155,7 @@ if $cygwin ; then
fi
# Escape application args
-save ( ) {
+save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
diff --git a/src/3rdparty/gradle/gradlew.bat b/src/3rdparty/gradle/gradlew.bat
index 65b35a4602..f9553162f1 100644
--- a/src/3rdparty/gradle/gradlew.bat
+++ b/src/3rdparty/gradle/gradlew.bat
@@ -14,7 +14,7 @@ set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=-Xmx1024m -Dfile.encoding=UTF-8
+set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
diff --git a/src/3rdparty/harfbuzz-ng/qt_attribution.json b/src/3rdparty/harfbuzz-ng/qt_attribution.json
index 0cf6a746f5..2f1aed8a87 100644
--- a/src/3rdparty/harfbuzz-ng/qt_attribution.json
+++ b/src/3rdparty/harfbuzz-ng/qt_attribution.json
@@ -2,7 +2,7 @@
"Id": "harfbuzz-ng",
"Name": "HarfBuzz-NG",
"QDocModule": "qtgui",
- "QtUsage": "Optionally used in Qt GUI. Configure with -system-harfbuzz or -qt-harfbuzz to avoid.",
+ "QtUsage": "Optionally used in Qt GUI. Configure with -system-harfbuzz to force the use of the system library, or -qt-harfbuzz to link statically to the library that is bundled with your Qt version.",
"Description": "HarfBuzz is an OpenType text shaping engine.",
"Homepage": "http://harfbuzz.org",
diff --git a/src/3rdparty/harfbuzz/qt_attribution.json b/src/3rdparty/harfbuzz/qt_attribution.json
index 51449f2adb..986171fb7b 100644
--- a/src/3rdparty/harfbuzz/qt_attribution.json
+++ b/src/3rdparty/harfbuzz/qt_attribution.json
@@ -2,7 +2,7 @@
"Id": "harfbuzz",
"Name": "HarfBuzz",
"QDocModule": "qtgui",
- "QtUsage": "Optionally used in Qt GUI. Configure with -system-harfbuzz or -qt-harfbuzz to avoid.",
+ "QtUsage": "Optionally used in Qt GUI. Configure with -system-harfbuzz to force the use of the system library, or -no-harfbuzz to disable the use of HarfBuzz entirely.",
"License": "MIT License",
"LicenseId": "MIT",
diff --git a/src/3rdparty/libjpeg.pri b/src/3rdparty/libjpeg.pri
index a61f28dc5a..5effbe9d26 100644
--- a/src/3rdparty/libjpeg.pri
+++ b/src/3rdparty/libjpeg.pri
@@ -1,19 +1,13 @@
winrt: DEFINES += NO_GETENV
-DEFINES += \
- C_ARITH_CODING_SUPPORTED=1 \
- D_ARITH_CODING_SUPPORTED=1 \
- BITS_IN_JSAMPLE=8 \
- JPEG_LIB_VERSION=80 \
- SIZEOF_SIZE_T=__SIZEOF_SIZE_T__
+# Disable warnings in 3rdparty code due to unused arguments
+gcc: QMAKE_CFLAGS_WARN_ON += -Wno-unused-parameter -Wno-main
-#Disable warnings in 3rdparty code due to unused arguments
-contains(QMAKE_CC, gcc): {
- QMAKE_CFLAGS_WARN_ON += -Wno-unused-parameter -Wno-main
-}
+INCLUDEPATH += \
+ $$PWD/libjpeg \
+ $$PWD/libjpeg/src
-INCLUDEPATH += $$PWD/libjpeg/src
SOURCES += \
$$PWD/libjpeg/src/jaricom.c \
$$PWD/libjpeg/src/jcapimin.c \
diff --git a/src/3rdparty/libjpeg/LICENSE b/src/3rdparty/libjpeg/LICENSE
index 0572390635..0f6ec4b30a 100644
--- a/src/3rdparty/libjpeg/LICENSE
+++ b/src/3rdparty/libjpeg/LICENSE
@@ -11,7 +11,8 @@ libjpeg-turbo is covered by three compatible BSD-style open source licenses:
- The Modified (3-clause) BSD License, which is listed below
- This license covers the TurboJPEG API library and associated programs.
+ This license covers the TurboJPEG API library and associated programs, as
+ well as the build system.
- The zlib License, which is listed below
@@ -137,3 +138,16 @@ freely, subject to the following restrictions:
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
+
+
+Why Three Licenses?
+===================
+
+The zlib License could have been used instead of the Modified (3-clause) BSD
+License, and since the IJG License effectively subsumes the distribution
+conditions of the zlib License, this would have effectively placed
+libjpeg-turbo binary distributions under the IJG License. However, the IJG
+License specifically refers to the Independent JPEG Group and does not extend
+attribution and endorsement protections to other entities. Thus, it was
+desirable to choose a license that granted us the same protections for new code
+that were granted to the IJG for code derived from their software.
diff --git a/src/3rdparty/libjpeg/import_from_libjpeg_tarball.sh b/src/3rdparty/libjpeg/import_from_libjpeg_tarball.sh
index b22f6b0d47..8dafbda64d 100755
--- a/src/3rdparty/libjpeg/import_from_libjpeg_tarball.sh
+++ b/src/3rdparty/libjpeg/import_from_libjpeg_tarball.sh
@@ -42,7 +42,7 @@
# into 3rdparty/libjpeg/.
if [ $# -ne 2 ]; then
- echo "Usage: $0 LIBJPEG_tarball_dir/ \$QTDIR/src/3rdparty/LIBJPEG/"
+ echo "Usage: $0 LIBJPEG_tarball_dir/ \$QTDIR/src/3rdparty/libjpeg/"
exit 1
fi
@@ -75,14 +75,14 @@ copy_file() {
}
copy_file "LICENSE.md" "LICENSE"
-copy_file "jconfig.txt" "src/jconfig.h"
-copy_file "win/jconfigint.h.in" "src/jconfigint.h"
FILES="
change.log
ChangeLog.md
README.md
README.ijg
+ jconfig.h.in
+ jconfigint.h.in
jaricom.c
jcapimin.c
@@ -163,3 +163,5 @@ FILES="
for i in $FILES; do
copy_file "$i" "src/$i"
done
+
+echo Done. $TARGET_DIR/jconfig.h and jconfigint.h may need manual updating.
diff --git a/src/3rdparty/libjpeg/jconfig.h b/src/3rdparty/libjpeg/jconfig.h
new file mode 100644
index 0000000000..bcfef5f0b6
--- /dev/null
+++ b/src/3rdparty/libjpeg/jconfig.h
@@ -0,0 +1,23 @@
+// Definitions for building in Qt source, ref. src/jconfig.h.in
+
+#define JPEG_LIB_VERSION 80
+
+#define LIBJPEG_TURBO_VERSION 2.0.0
+
+#define LIBJPEG_TURBO_VERSION_NUMBER 2000000
+
+#define C_ARITH_CODING_SUPPORTED
+
+#define D_ARITH_CODING_SUPPORTED
+
+#define MEM_SRCDST_SUPPORTED
+
+#define BITS_IN_JSAMPLE 8
+
+#define HAVE_STDDEF_H
+
+#define HAVE_STDLIB_H
+
+#define HAVE_UNSIGNED_CHAR
+
+#define HAVE_UNSIGNED_SHORT
diff --git a/src/3rdparty/libjpeg/jconfigint.h b/src/3rdparty/libjpeg/jconfigint.h
new file mode 100644
index 0000000000..c3549bfd25
--- /dev/null
+++ b/src/3rdparty/libjpeg/jconfigint.h
@@ -0,0 +1,17 @@
+// Definitions for building in Qt source, ref. src/jconfigint.h.in
+
+#include <stdint.h>
+
+#define BUILD ""
+
+#define INLINE inline
+
+#define PACKAGE_NAME "libjpeg-turbo"
+
+#define VERSION "2.0.0"
+
+#if SIZE_MAX == 0xffffffff
+#define SIZEOF_SIZE_T 4
+#elif SIZE_MAX == 0xffffffffffffffff
+#define SIZEOF_SIZE_T 8
+#endif
diff --git a/src/3rdparty/libjpeg/qt_attribution.json b/src/3rdparty/libjpeg/qt_attribution.json
index 9bfc14f29d..57c5001f6c 100644
--- a/src/3rdparty/libjpeg/qt_attribution.json
+++ b/src/3rdparty/libjpeg/qt_attribution.json
@@ -6,13 +6,14 @@
"Description": "The Independent JPEG Group's JPEG software",
"Homepage": "http://libjpeg-turbo.virtualgl.org/",
- "Version": "1.5.3",
+ "Version": "2.0.0",
"License": "Independent JPEG Group License",
"LicenseId": "IJG",
"LicenseFile": "LICENSE",
- "Copyright": "Copyright (C) 2009-2017 D. R. Commander
+ "Copyright": "Copyright (C) 2009-2018 D. R. Commander
Copyright (C) 2011-2016 Siarhei Siamashka
-Copyright (C) 2015-2016 Matthieu Darbois
+Copyright (C) 2015-2016, 2018 Matthieu Darbois
+Copyright (C) 2015 Intel Corporation
Copyright (C) 2015 Google, Inc.
Copyright (C) 2013-2014 MIPS Technologies, Inc.
Copyright (C) 2013 Linaro Limited
diff --git a/src/3rdparty/libjpeg/src/ChangeLog.md b/src/3rdparty/libjpeg/src/ChangeLog.md
index f5fe44bf85..8f0d11b1a6 100644
--- a/src/3rdparty/libjpeg/src/ChangeLog.md
+++ b/src/3rdparty/libjpeg/src/ChangeLog.md
@@ -1,3 +1,195 @@
+2.0.0
+=====
+
+### Significant changes relative to 2.0 beta1:
+
+1. The TurboJPEG API can now decompress CMYK JPEG images that have subsampled M
+and Y components (not to be confused with YCCK JPEG images, in which the C/M/Y
+components have been transformed into luma and chroma.) Previously, an error
+was generated ("Could not determine subsampling type for JPEG image") when such
+an image was passed to `tjDecompressHeader3()`, `tjTransform()`,
+`tjDecompressToYUVPlanes()`, `tjDecompressToYUV2()`, or the equivalent Java
+methods.
+
+2. Fixed an issue (CVE-2018-11813) whereby a specially-crafted malformed input
+file (specifically, a file with a valid Targa header but incomplete pixel data)
+would cause cjpeg to generate a JPEG file that was potentially thousands of
+times larger than the input file. The Targa reader in cjpeg was not properly
+detecting that the end of the input file had been reached prematurely, so after
+all valid pixels had been read from the input, the reader injected dummy pixels
+with values of 255 into the JPEG compressor until the number of pixels
+specified in the Targa header had been compressed. The Targa reader in cjpeg
+now behaves like the PPM reader and aborts compression if the end of the input
+file is reached prematurely. Because this issue only affected cjpeg and not
+the underlying library, and because it did not involve any out-of-bounds reads
+or other exploitable behaviors, it was not believed to represent a security
+threat.
+
+3. Fixed an issue whereby the `tjLoadImage()` and `tjSaveImage()` functions
+would produce a "Bogus message code" error message if the underlying bitmap and
+PPM readers/writers threw an error that was specific to the readers/writers
+(as opposed to a general libjpeg API error.)
+
+4. Fixed an issue whereby a specially-crafted malformed BMP file, one in which
+the header specified an image width of 1073741824 pixels, would trigger a
+floating point exception (division by zero) in the `tjLoadImage()` function
+when attempting to load the BMP file into a 4-component image buffer.
+
+5. Fixed an issue whereby certain combinations of calls to
+`jpeg_skip_scanlines()` and `jpeg_read_scanlines()` could trigger an infinite
+loop when decompressing progressive JPEG images that use vertical chroma
+subsampling (for instance, 4:2:0 or 4:4:0.)
+
+6. Fixed a segfault in `jpeg_skip_scanlines()` that occurred when decompressing
+a 4:2:2 or 4:2:0 JPEG image using the merged (non-fancy) upsampling algorithms
+(that is, when setting `cinfo.do_fancy_upsampling` to `FALSE`.)
+
+7. The new CMake-based build system will now disable the MIPS DSPr2 SIMD
+extensions if it detects that the compiler does not support DSPr2 instructions.
+
+8. Fixed out-of-bounds read in cjpeg that occurred when attempting to compress
+a specially-crafted malformed color-index (8-bit-per-sample) BMP file in which
+some of the samples (color indices) exceeded the bounds of the BMP file's color
+table.
+
+9. Fixed a signed integer overflow in the progressive Huffman decoder, detected
+by the Clang and GCC undefined behavior sanitizers, that could be triggered by
+attempting to decompress a specially-crafted malformed JPEG image. This issue
+did not pose a security threat, but removing the warning made it easier to
+detect actual security issues, should they arise in the future.
+
+
+1.5.90 (2.0 beta1)
+==================
+
+### Significant changes relative to 1.5.3:
+
+1. Added AVX2 SIMD implementations of the colorspace conversion, chroma
+downsampling and upsampling, integer quantization and sample conversion, and
+slow integer DCT/IDCT algorithms. When using the slow integer DCT/IDCT
+algorithms on AVX2-equipped CPUs, the compression of RGB images is
+approximately 13-36% (avg. 22%) faster (relative to libjpeg-turbo 1.5.x) with
+64-bit code and 11-21% (avg. 17%) faster with 32-bit code, and the
+decompression of RGB images is approximately 9-35% (avg. 17%) faster with
+64-bit code and 7-17% (avg. 12%) faster with 32-bit code. (As tested on a
+3 GHz Intel Core i7. Actual mileage may vary.)
+
+2. Overhauled the build system to use CMake on all platforms, and removed the
+autotools-based build system. This decision resulted from extensive
+discussions within the libjpeg-turbo community. libjpeg-turbo traditionally
+used CMake only for Windows builds, but there was an increasing amount of
+demand to extend CMake support to other platforms. However, because of the
+unique nature of our code base (the need to support different assemblers on
+each platform, the need for Java support, etc.), providing dual build systems
+as other OSS imaging libraries do (including libpng and libtiff) would have
+created a maintenance burden. The use of CMake greatly simplifies some aspects
+of our build system, owing to CMake's built-in support for various assemblers,
+Java, and unit testing, as well as generally fewer quirks that have to be
+worked around in order to implement our packaging system. Eliminating
+autotools puts our project slightly at odds with the traditional practices of
+the OSS community, since most "system libraries" tend to be built with
+autotools, but it is believed that the benefits of this move outweigh the
+risks. In addition to providing a unified build environment, switching to
+CMake allows for the use of various build tools and IDEs that aren't supported
+under autotools, including XCode, Ninja, and Eclipse. It also eliminates the
+need to install autotools via MacPorts/Homebrew on OS X and allows
+libjpeg-turbo to be configured without the use of a terminal/command prompt.
+Extensive testing was conducted to ensure that all features provided by the
+autotools-based build system are provided by the new build system.
+
+3. The libjpeg API in this version of libjpeg-turbo now includes two additional
+functions, `jpeg_read_icc_profile()` and `jpeg_write_icc_profile()`, that can
+be used to extract ICC profile data from a JPEG file while decompressing or to
+embed ICC profile data in a JPEG file while compressing or transforming. This
+eliminates the need for downstream projects, such as color management libraries
+and browsers, to include their own glueware for accomplishing this.
+
+4. Improved error handling in the TurboJPEG API library:
+
+ - Introduced a new function (`tjGetErrorStr2()`) in the TurboJPEG C API
+that allows compression/decompression/transform error messages to be retrieved
+in a thread-safe manner. Retrieving error messages from global functions, such
+as `tjInitCompress()` or `tjBufSize()`, is still thread-unsafe, but since those
+functions will only throw errors if passed an invalid argument or if a memory
+allocation failure occurs, thread safety is not as much of a concern.
+ - Introduced a new function (`tjGetErrorCode()`) in the TurboJPEG C API
+and a new method (`TJException.getErrorCode()`) in the TurboJPEG Java API that
+can be used to determine the severity of the last
+compression/decompression/transform error. This allows applications to
+choose whether to ignore warnings (non-fatal errors) from the underlying
+libjpeg API or to treat them as fatal.
+ - Introduced a new flag (`TJFLAG_STOPONWARNING` in the TurboJPEG C API and
+`TJ.FLAG_STOPONWARNING` in the TurboJPEG Java API) that causes the library to
+immediately halt a compression/decompression/transform operation if it
+encounters a warning from the underlying libjpeg API (the default behavior is
+to allow the operation to complete unless a fatal error is encountered.)
+
+5. Introduced a new flag in the TurboJPEG C and Java APIs (`TJFLAG_PROGRESSIVE`
+and `TJ.FLAG_PROGRESSIVE`, respectively) that causes the library to use
+progressive entropy coding in JPEG images generated by compression and
+transform operations. Additionally, a new transform option
+(`TJXOPT_PROGRESSIVE` in the C API and `TJTransform.OPT_PROGRESSIVE` in the
+Java API) has been introduced, allowing progressive entropy coding to be
+enabled for selected transforms in a multi-transform operation.
+
+6. Introduced a new transform option in the TurboJPEG API (`TJXOPT_COPYNONE` in
+the C API and `TJTransform.OPT_COPYNONE` in the Java API) that allows the
+copying of markers (including EXIF and ICC profile data) to be disabled for a
+particular transform.
+
+7. Added two functions to the TurboJPEG C API (`tjLoadImage()` and
+`tjSaveImage()`) that can be used to load/save a BMP or PPM/PGM image to/from a
+memory buffer with a specified pixel format and layout. These functions
+replace the project-private (and slow) bmp API, which was previously used by
+TJBench, and they also provide a convenient way for first-time users of
+libjpeg-turbo to quickly develop a complete JPEG compression/decompression
+program.
+
+8. The TurboJPEG C API now includes a new convenience array (`tjAlphaOffset[]`)
+that contains the alpha component index for each pixel format (or -1 if the
+pixel format lacks an alpha component.) The TurboJPEG Java API now includes a
+new method (`TJ.getAlphaOffset()`) that returns the same value. In addition,
+the `tjRedOffset[]`, `tjGreenOffset[]`, and `tjBlueOffset[]` arrays-- and the
+corresponding `TJ.getRedOffset()`, `TJ.getGreenOffset()`, and
+`TJ.getBlueOffset()` methods-- now return -1 for `TJPF_GRAY`/`TJ.PF_GRAY`
+rather than 0. This allows programs to easily determine whether a pixel format
+has red, green, blue, and alpha components.
+
+9. Added a new example (tjexample.c) that demonstrates the basic usage of the
+TurboJPEG C API. This example mirrors the functionality of TJExample.java.
+Both files are now included in the libjpeg-turbo documentation.
+
+10. Fixed two signed integer overflows in the arithmetic decoder, detected by
+the Clang undefined behavior sanitizer, that could be triggered by attempting
+to decompress a specially-crafted malformed JPEG image. These issues did not
+pose a security threat, but removing the warnings makes it easier to detect
+actual security issues, should they arise in the future.
+
+11. Fixed a bug in the merged 4:2:0 upsampling/dithered RGB565 color conversion
+algorithm that caused incorrect dithering in the output image. This algorithm
+now produces bitwise-identical results to the unmerged algorithms.
+
+12. The SIMD function symbols for x86[-64]/ELF, MIPS/ELF, macOS/x86[-64] (if
+libjpeg-turbo is built with YASM), and iOS/ARM[64] builds are now private.
+This prevents those symbols from being exposed in applications or shared
+libraries that link statically with libjpeg-turbo.
+
+13. Added Loongson MMI SIMD implementations of the RGB-to-YCbCr and
+YCbCr-to-RGB colorspace conversion, 4:2:0 chroma downsampling, 4:2:0 fancy
+chroma upsampling, integer quantization, and slow integer DCT/IDCT algorithms.
+When using the slow integer DCT/IDCT, this speeds up the compression of RGB
+images by approximately 70-100% and the decompression of RGB images by
+approximately 2-3.5x.
+
+14. Fixed a build error when building with older MinGW releases (regression
+caused by 1.5.1[7].)
+
+15. Added SIMD acceleration for progressive Huffman encoding on SSE2-capable
+x86 and x86-64 platforms. This speeds up the compression of full-color
+progressive JPEGs by about 85-90% on average (relative to libjpeg-turbo 1.5.x)
+when using modern Intel and AMD CPUs.
+
+
1.5.3
=====
@@ -174,8 +366,8 @@ specified.)
2x2 luminance sampling factors and 2x1 or 1x2 chrominance sampling factors.
This is a non-standard way of specifying 2x subsampling (normally 4:2:2 JPEGs
have 2x1 luminance and 1x1 chrominance sampling factors, and 4:4:0 JPEGs have
-1x2 luminance and 1x1 chrominance sampling factors), but the JPEG specification
-and the libjpeg API both allow it.
+1x2 luminance and 1x1 chrominance sampling factors), but the JPEG format and
+the libjpeg API both allow it.
7. Fixed an unsigned integer overflow in the libjpeg memory manager, detected
by the Clang undefined behavior sanitizer, that could be triggered by
diff --git a/src/3rdparty/libjpeg/src/README.ijg b/src/3rdparty/libjpeg/src/README.ijg
index 9c450ceb07..2e39f965c2 100644
--- a/src/3rdparty/libjpeg/src/README.ijg
+++ b/src/3rdparty/libjpeg/src/README.ijg
@@ -43,7 +43,7 @@ User documentation:
change.log Version-to-version change highlights.
Programmer and internal documentation:
libjpeg.txt How to use the JPEG library in your own programs.
- example.c Sample code for calling the JPEG library.
+ example.txt Sample code for calling the JPEG library.
structure.txt Overview of the JPEG library's internal structure.
coderules.txt Coding style rules --- please read if you contribute code.
@@ -159,12 +159,6 @@ commercial products, provided that all warranty or liability claims are
assumed by the product vendor.
-The Unix configuration script "configure" was produced with GNU Autoconf.
-It is copyright by the Free Software Foundation but is freely distributable.
-The same holds for its supporting scripts (config.guess, config.sub,
-ltmain.sh). Another support script, install-sh, is copyright by X Consortium
-but is also freely distributable.
-
The IJG distribution formerly included code to read and write GIF files.
To avoid entanglement with the Unisys LZW patent (now expired), GIF reading
support has been removed altogether, and the GIF writer has been simplified
@@ -185,8 +179,8 @@ We recommend reading one or more of these references before trying to
understand the innards of the JPEG software.
The best short technical introduction to the JPEG compression algorithm is
- Wallace, Gregory K. "The JPEG Still Picture Compression Standard",
- Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44.
+ Wallace, Gregory K. "The JPEG Still Picture Compression Standard",
+ Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44.
(Adjacent articles in that issue discuss MPEG motion picture compression,
applications of JPEG, and related topics.) If you don't have the CACM issue
handy, a PDF file containing a revised version of Wallace's article is
@@ -220,14 +214,14 @@ Continuous-tone Still Images, Part 2: Compliance testing" and has document
numbers ISO/IEC IS 10918-2, ITU-T T.83.
The JPEG standard does not specify all details of an interchangeable file
-format. For the omitted details we follow the "JFIF" conventions, revision
-1.02. JFIF 1.02 has been adopted as an Ecma International Technical Report
-and thus received a formal publication status. It is available as a free
-download in PDF format from
-http://www.ecma-international.org/publications/techreports/E-TR-098.htm.
-A PostScript version of the JFIF document is available at
-http://www.ijg.org/files/jfif.ps.gz. There is also a plain text version at
-http://www.ijg.org/files/jfif.txt.gz, but it is missing the figures.
+format. For the omitted details, we follow the "JFIF" conventions, revision
+1.02. JFIF version 1 has been adopted as ISO/IEC 10918-5 (05/2013) and
+Recommendation ITU-T T.871 (05/2011): Information technology - Digital
+compression and coding of continuous-tone still images: JPEG File Interchange
+Format (JFIF). It is available as a free download in PDF file format from
+https://www.iso.org/standard/54989.html and http://www.itu.int/rec/T-REC-T.871.
+A PDF file of the older JFIF 1.02 specification is available at
+http://www.w3.org/Graphics/JPEG/jfif3.pdf.
The TIFF 6.0 file format specification can be obtained by FTP from
ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme
@@ -255,22 +249,26 @@ and other news.answers archive sites, including the official news.answers
archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/.
If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu
with body
- send usenet/news.answers/jpeg-faq/part1
- send usenet/news.answers/jpeg-faq/part2
-
-
-FILE FORMAT WARS
-================
-
-The ISO/IEC JTC1/SC29/WG1 standards committee (also known as JPEG, together
-with ITU-T SG16) currently promotes different formats containing the name
-"JPEG" which are incompatible with original DCT-based JPEG. IJG therefore does
-not support these formats (see REFERENCES). Indeed, one of the original
-reasons for developing this free software was to help force convergence on
-common, interoperable format standards for JPEG files.
-Don't use an incompatible file format!
-(In any case, our decoder will remain capable of reading existing JPEG
-image files indefinitely.)
+ send usenet/news.answers/jpeg-faq/part1
+ send usenet/news.answers/jpeg-faq/part2
+
+
+FILE FORMAT COMPATIBILITY
+=========================
+
+This software implements ITU T.81 | ISO/IEC 10918 with some extensions from
+ITU T.871 | ISO/IEC 10918-5 (JPEG File Interchange Format-- see REFERENCES).
+Informally, the term "JPEG image" or "JPEG file" most often refers to JFIF or
+a subset thereof, but there are other formats containing the name "JPEG" that
+are incompatible with the DCT-based JPEG standard or with JFIF (for instance,
+JPEG 2000 and JPEG XR). This software therefore does not support these
+formats. Indeed, one of the original reasons for developing this free software
+was to help force convergence on a common, interoperable format standard for
+JPEG files.
+
+JFIF is a minimal or "low end" representation. TIFF/JPEG (TIFF revision 6.0 as
+modified by TIFF Technical Note #2) can be used for "high end" applications
+that need to record a lot of additional data about an image.
TO DO
diff --git a/src/3rdparty/libjpeg/src/README.md b/src/3rdparty/libjpeg/src/README.md
index 74e6eac45a..a769259891 100755..100644
--- a/src/3rdparty/libjpeg/src/README.md
+++ b/src/3rdparty/libjpeg/src/README.md
@@ -2,8 +2,9 @@ Background
==========
libjpeg-turbo is a JPEG image codec that uses SIMD instructions (MMX, SSE2,
-NEON, AltiVec) to accelerate baseline JPEG compression and decompression on
-x86, x86-64, ARM, and PowerPC systems. On such systems, libjpeg-turbo is
+AVX2, NEON, AltiVec) to accelerate baseline JPEG compression and decompression
+on x86, x86-64, ARM, and PowerPC systems, as well as progressive JPEG
+compression on x86 and x86-64 systems. On such systems, libjpeg-turbo is
generally 2-6x as fast as libjpeg, all else being equal. On other types of
systems, libjpeg-turbo can still outperform libjpeg by a significant amount, by
virtue of its highly-optimized Huffman coding routines. In many cases, the
@@ -48,7 +49,10 @@ JPEG images:
straightforward to achieve using the underlying libjpeg API, such as
generating planar YUV images and performing multiple simultaneous lossless
transforms on an image. The Java interface for libjpeg-turbo is written on
- top of the TurboJPEG API.
+ top of the TurboJPEG API. The TurboJPEG API is recommended for first-time
+ users of libjpeg-turbo. Refer to [tjexample.c](tjexample.c) and
+ [TJExample.java](java/TJExample.java) for examples of its usage and to
+ <http://libjpeg-turbo.org/Documentation/Documentation> for API documentation.
- **libjpeg API**<br>
This is the de facto industry-standard API for compressing and decompressing
@@ -56,7 +60,8 @@ JPEG images:
more powerful. The libjpeg API implementation in libjpeg-turbo is both
API/ABI-compatible and mathematically compatible with libjpeg v6b. It can
also optionally be configured to be API/ABI-compatible with libjpeg v7 and v8
- (see below.)
+ (see below.) Refer to [cjpeg.c](cjpeg.c) and [djpeg.c](djpeg.c) for examples
+ of its usage and to [libjpeg.txt](libjpeg.txt) for API documentation.
There is no significant performance advantage to either API when both are used
to perform similar operations.
diff --git a/src/3rdparty/libjpeg/src/jaricom.c b/src/3rdparty/libjpeg/src/jaricom.c
index 3bb557f7a3..215640cc44 100644
--- a/src/3rdparty/libjpeg/src/jaricom.c
+++ b/src/3rdparty/libjpeg/src/jaricom.c
@@ -4,16 +4,16 @@
* This file was part of the Independent JPEG Group's software:
* Developed 1997-2009 by Guido Vollbeding.
* libjpeg-turbo Modifications:
- * Copyright (C) 2015, D. R. Commander.
+ * Copyright (C) 2015, 2018, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
* This file contains probability estimation tables for common use in
* arithmetic entropy encoding and decoding routines.
*
- * This data represents Table D.2 in the JPEG spec (ISO/IEC IS 10918-1
- * and CCITT Recommendation ITU-T T.81) and Table 24 in the JBIG spec
- * (ISO/IEC IS 11544 and CCITT Recommendation ITU-T T.82).
+ * This data represents Table D.2 in
+ * Recommendation ITU-T T.81 (1992) | ISO/IEC 10918-1:1994 and Table 24 in
+ * Recommendation ITU-T T.82 (1993) | ISO/IEC 11544:1993.
*/
#define JPEG_INTERNALS
@@ -29,9 +29,10 @@
* implementation (jbig_tab.c).
*/
-#define V(i,a,b,c,d) (((JLONG)a << 16) | ((JLONG)c << 8) | ((JLONG)d << 7) | b)
+#define V(i, a, b, c, d) \
+ (((JLONG)a << 16) | ((JLONG)c << 8) | ((JLONG)d << 7) | b)
-const JLONG jpeg_aritab[113+1] = {
+const JLONG jpeg_aritab[113 + 1] = {
/*
* Index, Qe_Value, Next_Index_LPS, Next_Index_MPS, Switch_MPS
*/
diff --git a/src/3rdparty/libjpeg/src/jcapimin.c b/src/3rdparty/libjpeg/src/jcapimin.c
index 15674be54a..178c55ba47 100644
--- a/src/3rdparty/libjpeg/src/jcapimin.c
+++ b/src/3rdparty/libjpeg/src/jcapimin.c
@@ -31,7 +31,7 @@
*/
GLOBAL(void)
-jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize)
+jpeg_CreateCompress(j_compress_ptr cinfo, int version, size_t structsize)
{
int i;
@@ -41,7 +41,7 @@ jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize)
ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
if (structsize != sizeof(struct jpeg_compress_struct))
ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,
- (int) sizeof(struct jpeg_compress_struct), (int) structsize);
+ (int)sizeof(struct jpeg_compress_struct), (int)structsize);
/* For debugging purposes, we zero the whole master structure.
* But the application has already set the err pointer, and may have set
@@ -59,7 +59,7 @@ jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize)
cinfo->is_decompressor = FALSE;
/* Initialize a memory manager instance for this object */
- jinit_memory_mgr((j_common_ptr) cinfo);
+ jinit_memory_mgr((j_common_ptr)cinfo);
/* Zero out pointers to permanent structures. */
cinfo->progress = NULL;
@@ -83,7 +83,7 @@ jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize)
/* Must do it here for emit_dqt in case jpeg_write_tables is used */
cinfo->block_size = DCTSIZE;
cinfo->natural_order = jpeg_natural_order;
- cinfo->lim_Se = DCTSIZE2-1;
+ cinfo->lim_Se = DCTSIZE2 - 1;
#endif
cinfo->script_space = NULL;
@@ -100,9 +100,9 @@ jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize)
*/
GLOBAL(void)
-jpeg_destroy_compress (j_compress_ptr cinfo)
+jpeg_destroy_compress(j_compress_ptr cinfo)
{
- jpeg_destroy((j_common_ptr) cinfo); /* use common routine */
+ jpeg_destroy((j_common_ptr)cinfo); /* use common routine */
}
@@ -112,9 +112,9 @@ jpeg_destroy_compress (j_compress_ptr cinfo)
*/
GLOBAL(void)
-jpeg_abort_compress (j_compress_ptr cinfo)
+jpeg_abort_compress(j_compress_ptr cinfo)
{
- jpeg_abort((j_common_ptr) cinfo); /* use common routine */
+ jpeg_abort((j_common_ptr)cinfo); /* use common routine */
}
@@ -131,7 +131,7 @@ jpeg_abort_compress (j_compress_ptr cinfo)
*/
GLOBAL(void)
-jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress)
+jpeg_suppress_tables(j_compress_ptr cinfo, boolean suppress)
{
int i;
JQUANT_TBL *qtbl;
@@ -159,7 +159,7 @@ jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress)
*/
GLOBAL(void)
-jpeg_finish_compress (j_compress_ptr cinfo)
+jpeg_finish_compress(j_compress_ptr cinfo)
{
JDIMENSION iMCU_row;
@@ -172,18 +172,18 @@ jpeg_finish_compress (j_compress_ptr cinfo)
} else if (cinfo->global_state != CSTATE_WRCOEFS)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
/* Perform any remaining passes */
- while (! cinfo->master->is_last_pass) {
+ while (!cinfo->master->is_last_pass) {
(*cinfo->master->prepare_for_pass) (cinfo);
for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) {
if (cinfo->progress != NULL) {
- cinfo->progress->pass_counter = (long) iMCU_row;
- cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows;
- (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ cinfo->progress->pass_counter = (long)iMCU_row;
+ cinfo->progress->pass_limit = (long)cinfo->total_iMCU_rows;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr)cinfo);
}
/* We bypass the main controller and invoke coef controller directly;
* all work is being done from the coefficient buffer.
*/
- if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL))
+ if (!(*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE)NULL))
ERREXIT(cinfo, JERR_CANT_SUSPEND);
}
(*cinfo->master->finish_pass) (cinfo);
@@ -192,7 +192,7 @@ jpeg_finish_compress (j_compress_ptr cinfo)
(*cinfo->marker->write_file_trailer) (cinfo);
(*cinfo->dest->term_destination) (cinfo);
/* We can use jpeg_abort to release memory and reset global_state */
- jpeg_abort((j_common_ptr) cinfo);
+ jpeg_abort((j_common_ptr)cinfo);
}
@@ -204,8 +204,8 @@ jpeg_finish_compress (j_compress_ptr cinfo)
*/
GLOBAL(void)
-jpeg_write_marker (j_compress_ptr cinfo, int marker,
- const JOCTET *dataptr, unsigned int datalen)
+jpeg_write_marker(j_compress_ptr cinfo, int marker, const JOCTET *dataptr,
+ unsigned int datalen)
{
void (*write_marker_byte) (j_compress_ptr info, int val);
@@ -226,7 +226,7 @@ jpeg_write_marker (j_compress_ptr cinfo, int marker,
/* Same, but piecemeal. */
GLOBAL(void)
-jpeg_write_m_header (j_compress_ptr cinfo, int marker, unsigned int datalen)
+jpeg_write_m_header(j_compress_ptr cinfo, int marker, unsigned int datalen)
{
if (cinfo->next_scanline != 0 ||
(cinfo->global_state != CSTATE_SCANNING &&
@@ -238,7 +238,7 @@ jpeg_write_m_header (j_compress_ptr cinfo, int marker, unsigned int datalen)
}
GLOBAL(void)
-jpeg_write_m_byte (j_compress_ptr cinfo, int val)
+jpeg_write_m_byte(j_compress_ptr cinfo, int val)
{
(*cinfo->marker->write_marker_byte) (cinfo, val);
}
@@ -266,13 +266,13 @@ jpeg_write_m_byte (j_compress_ptr cinfo, int val)
*/
GLOBAL(void)
-jpeg_write_tables (j_compress_ptr cinfo)
+jpeg_write_tables(j_compress_ptr cinfo)
{
if (cinfo->global_state != CSTATE_START)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
/* (Re)initialize error mgr and destination modules */
- (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
+ (*cinfo->err->reset_error_mgr) ((j_common_ptr)cinfo);
(*cinfo->dest->init_destination) (cinfo);
/* Initialize the marker writer ... bit of a crock to do it here. */
jinit_marker_writer(cinfo);
diff --git a/src/3rdparty/libjpeg/src/jcapistd.c b/src/3rdparty/libjpeg/src/jcapistd.c
index 5c6d0be255..aa2aad9f66 100644
--- a/src/3rdparty/libjpeg/src/jcapistd.c
+++ b/src/3rdparty/libjpeg/src/jcapistd.c
@@ -36,7 +36,7 @@
*/
GLOBAL(void)
-jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables)
+jpeg_start_compress(j_compress_ptr cinfo, boolean write_all_tables)
{
if (cinfo->global_state != CSTATE_START)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
@@ -45,7 +45,7 @@ jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables)
jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */
/* (Re)initialize error mgr and destination modules */
- (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
+ (*cinfo->err->reset_error_mgr) ((j_common_ptr)cinfo);
(*cinfo->dest->init_destination) (cinfo);
/* Perform master selection of active modules */
jinit_compress_master(cinfo);
@@ -75,8 +75,8 @@ jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables)
*/
GLOBAL(JDIMENSION)
-jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines,
- JDIMENSION num_lines)
+jpeg_write_scanlines(j_compress_ptr cinfo, JSAMPARRAY scanlines,
+ JDIMENSION num_lines)
{
JDIMENSION row_ctr, rows_left;
@@ -87,9 +87,9 @@ jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines,
/* Call progress monitor hook if present */
if (cinfo->progress != NULL) {
- cinfo->progress->pass_counter = (long) cinfo->next_scanline;
- cinfo->progress->pass_limit = (long) cinfo->image_height;
- (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ cinfo->progress->pass_counter = (long)cinfo->next_scanline;
+ cinfo->progress->pass_limit = (long)cinfo->image_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr)cinfo);
}
/* Give master control module another chance if this is first call to
@@ -118,8 +118,8 @@ jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines,
*/
GLOBAL(JDIMENSION)
-jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data,
- JDIMENSION num_lines)
+jpeg_write_raw_data(j_compress_ptr cinfo, JSAMPIMAGE data,
+ JDIMENSION num_lines)
{
JDIMENSION lines_per_iMCU_row;
@@ -132,9 +132,9 @@ jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data,
/* Call progress monitor hook if present */
if (cinfo->progress != NULL) {
- cinfo->progress->pass_counter = (long) cinfo->next_scanline;
- cinfo->progress->pass_limit = (long) cinfo->image_height;
- (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ cinfo->progress->pass_counter = (long)cinfo->next_scanline;
+ cinfo->progress->pass_limit = (long)cinfo->image_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr)cinfo);
}
/* Give master control module another chance if this is first call to
@@ -151,7 +151,7 @@ jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data,
ERREXIT(cinfo, JERR_BUFFER_SIZE);
/* Directly compress the row. */
- if (! (*cinfo->coef->compress_data) (cinfo, data)) {
+ if (!(*cinfo->coef->compress_data) (cinfo, data)) {
/* If compressor did not consume the whole row, suspend processing. */
return 0;
}
diff --git a/src/3rdparty/libjpeg/src/jcarith.c b/src/3rdparty/libjpeg/src/jcarith.c
index 6d3b8af5b4..b6d093f70e 100644
--- a/src/3rdparty/libjpeg/src/jcarith.c
+++ b/src/3rdparty/libjpeg/src/jcarith.c
@@ -4,16 +4,19 @@
* This file was part of the Independent JPEG Group's software:
* Developed 1997-2009 by Guido Vollbeding.
* libjpeg-turbo Modifications:
- * Copyright (C) 2015, D. R. Commander.
+ * Copyright (C) 2015, 2018, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
* This file contains portable arithmetic entropy encoding routines for JPEG
- * (implementing the ISO/IEC IS 10918-1 and CCITT Recommendation ITU-T T.81).
+ * (implementing Recommendation ITU-T T.81 | ISO/IEC 10918-1).
*
* Both sequential and progressive modes are supported in this single module.
*
* Suspension is not currently supported in this module.
+ *
+ * NOTE: All referenced figures are from
+ * Recommendation ITU-T T.81 (1992) | ISO/IEC 10918-1:1994.
*/
#define JPEG_INTERNALS
@@ -63,8 +66,8 @@ typedef arith_entropy_encoder *arith_entropy_ptr;
* in the lower bits (mask 0x7F).
*/
-#define DC_STAT_BINS 64
-#define AC_STAT_BINS 256
+#define DC_STAT_BINS 64
+#define AC_STAT_BINS 256
/* NOTE: Uncomment the following #define if you want to use the
* given formula for calculating the AC conditioning parameter Kx
@@ -105,25 +108,25 @@ typedef arith_entropy_encoder *arith_entropy_ptr;
#ifdef RIGHT_SHIFT_IS_UNSIGNED
#define ISHIFT_TEMPS int ishift_temp;
-#define IRIGHT_SHIFT(x,shft) \
- ((ishift_temp = (x)) < 0 ? \
- (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \
- (ishift_temp >> (shft)))
+#define IRIGHT_SHIFT(x, shft) \
+ ((ishift_temp = (x)) < 0 ? \
+ (ishift_temp >> (shft)) | ((~0) << (16 - (shft))) : \
+ (ishift_temp >> (shft)))
#else
#define ISHIFT_TEMPS
-#define IRIGHT_SHIFT(x,shft) ((x) >> (shft))
+#define IRIGHT_SHIFT(x, shft) ((x) >> (shft))
#endif
LOCAL(void)
-emit_byte (int val, j_compress_ptr cinfo)
+emit_byte(int val, j_compress_ptr cinfo)
/* Write next output byte; we do not support suspension in this module. */
{
struct jpeg_destination_mgr *dest = cinfo->dest;
- *dest->next_output_byte++ = (JOCTET) val;
+ *dest->next_output_byte++ = (JOCTET)val;
if (--dest->free_in_buffer == 0)
- if (! (*dest->empty_output_buffer) (cinfo))
+ if (!(*dest->empty_output_buffer) (cinfo))
ERREXIT(cinfo, JERR_CANT_SUSPEND);
}
@@ -133,22 +136,22 @@ emit_byte (int val, j_compress_ptr cinfo)
*/
METHODDEF(void)
-finish_pass (j_compress_ptr cinfo)
+finish_pass(j_compress_ptr cinfo)
{
- arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr e = (arith_entropy_ptr)cinfo->entropy;
JLONG temp;
/* Section D.1.8: Termination of encoding */
/* Find the e->c in the coding interval with the largest
* number of trailing zero bits */
- if ((temp = (e->a - 1 + e->c) & 0xFFFF0000L) < e->c)
+ if ((temp = (e->a - 1 + e->c) & 0xFFFF0000UL) < e->c)
e->c = temp + 0x8000L;
else
e->c = temp;
/* Send remaining bytes to output */
e->c <<= e->ct;
- if (e->c & 0xF8000000L) {
+ if (e->c & 0xF8000000UL) {
/* One final overflow has to be handled */
if (e->buffer >= 0) {
if (e->zc)
@@ -219,9 +222,9 @@ finish_pass (j_compress_ptr cinfo)
*/
LOCAL(void)
-arith_encode (j_compress_ptr cinfo, unsigned char *st, int val)
+arith_encode(j_compress_ptr cinfo, unsigned char *st, int val)
{
- register arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy;
+ register arith_entropy_ptr e = (arith_entropy_ptr)cinfo->entropy;
register unsigned char nl, nm;
register JLONG qe, temp;
register int sv;
@@ -231,8 +234,8 @@ arith_encode (j_compress_ptr cinfo, unsigned char *st, int val)
*/
sv = *st;
qe = jpeg_aritab[sv & 0x7F]; /* => Qe_Value */
- nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */
- nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */
+ nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */
+ nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */
/* Encode & estimation procedures per sections D.1.4 & D.1.5 */
e->a -= qe;
@@ -319,9 +322,9 @@ arith_encode (j_compress_ptr cinfo, unsigned char *st, int val)
*/
LOCAL(void)
-emit_restart (j_compress_ptr cinfo, int restart_num)
+emit_restart(j_compress_ptr cinfo, int restart_num)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
int ci;
jpeg_component_info *compptr;
@@ -362,9 +365,9 @@ emit_restart (j_compress_ptr cinfo, int restart_num)
*/
METHODDEF(boolean)
-encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+encode_mcu_DC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
JBLOCKROW block;
unsigned char *st;
int blkn, ci, tbl;
@@ -391,7 +394,7 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
/* Compute the DC value after the required point transform by Al.
* This is simply an arithmetic right shift.
*/
- m = IRIGHT_SHIFT((int) ((*block)[0]), cinfo->Al);
+ m = IRIGHT_SHIFT((int)((*block)[0]), cinfo->Al);
/* Sections F.1.4.1 & F.1.4.4.1: Encoding of DC coefficients */
@@ -432,9 +435,9 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
}
arith_encode(cinfo, st, 0);
/* Section F.1.4.4.1.2: Establish dc_context conditioning category */
- if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1))
+ if (m < (int)((1L << cinfo->arith_dc_L[tbl]) >> 1))
entropy->dc_context[ci] = 0; /* zero diff category */
- else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1))
+ else if (m > (int)((1L << cinfo->arith_dc_U[tbl]) >> 1))
entropy->dc_context[ci] += 8; /* large diff category */
/* Figure F.9: Encoding the magnitude bit pattern of v */
st += 14;
@@ -453,9 +456,9 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
*/
METHODDEF(boolean)
-encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+encode_mcu_AC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
JBLOCKROW block;
unsigned char *st;
int tbl, k, ke;
@@ -510,7 +513,7 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
break;
}
}
- arith_encode(cinfo, st + 1, 0); st += 3; k++;
+ arith_encode(cinfo, st + 1, 0); st += 3; k++;
}
st += 2;
/* Figure F.8: Encoding the magnitude category of v */
@@ -552,9 +555,9 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
*/
METHODDEF(boolean)
-encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+encode_mcu_DC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
unsigned char *st;
int Al, blkn;
@@ -587,9 +590,9 @@ encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
*/
METHODDEF(boolean)
-encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+encode_mcu_AC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
JBLOCKROW block;
unsigned char *st;
int tbl, k, ke, kex;
@@ -662,7 +665,7 @@ encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
break;
}
}
- arith_encode(cinfo, st + 1, 0); st += 3; k++;
+ arith_encode(cinfo, st + 1, 0); st += 3; k++;
}
}
/* Encode EOB decision only if k <= cinfo->Se */
@@ -680,9 +683,9 @@ encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
*/
METHODDEF(boolean)
-encode_mcu (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+encode_mcu(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
jpeg_component_info *compptr;
JBLOCKROW block;
unsigned char *st;
@@ -747,9 +750,9 @@ encode_mcu (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
}
arith_encode(cinfo, st, 0);
/* Section F.1.4.4.1.2: Establish dc_context conditioning category */
- if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1))
+ if (m < (int)((1L << cinfo->arith_dc_L[tbl]) >> 1))
entropy->dc_context[ci] = 0; /* zero diff category */
- else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1))
+ else if (m > (int)((1L << cinfo->arith_dc_U[tbl]) >> 1))
entropy->dc_context[ci] += 8; /* large diff category */
/* Figure F.9: Encoding the magnitude bit pattern of v */
st += 14;
@@ -770,7 +773,7 @@ encode_mcu (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
st = entropy->ac_stats[tbl] + 3 * (k - 1);
arith_encode(cinfo, st, 0); /* EOB decision */
while ((v = (*block)[jpeg_natural_order[k]]) == 0) {
- arith_encode(cinfo, st + 1, 0); st += 3; k++;
+ arith_encode(cinfo, st + 1, 0); st += 3; k++;
}
arith_encode(cinfo, st + 1, 1);
/* Figure F.6: Encoding nonzero value v */
@@ -822,9 +825,9 @@ encode_mcu (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
*/
METHODDEF(void)
-start_pass (j_compress_ptr cinfo, boolean gather_statistics)
+start_pass(j_compress_ptr cinfo, boolean gather_statistics)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
int ci, tbl;
jpeg_component_info *compptr;
@@ -862,8 +865,8 @@ start_pass (j_compress_ptr cinfo, boolean gather_statistics)
if (tbl < 0 || tbl >= NUM_ARITH_TBLS)
ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl);
if (entropy->dc_stats[tbl] == NULL)
- entropy->dc_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small)
- ((j_common_ptr) cinfo, JPOOL_IMAGE, DC_STAT_BINS);
+ entropy->dc_stats[tbl] = (unsigned char *)(*cinfo->mem->alloc_small)
+ ((j_common_ptr)cinfo, JPOOL_IMAGE, DC_STAT_BINS);
MEMZERO(entropy->dc_stats[tbl], DC_STAT_BINS);
/* Initialize DC predictions to 0 */
entropy->last_dc_val[ci] = 0;
@@ -875,13 +878,14 @@ start_pass (j_compress_ptr cinfo, boolean gather_statistics)
if (tbl < 0 || tbl >= NUM_ARITH_TBLS)
ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl);
if (entropy->ac_stats[tbl] == NULL)
- entropy->ac_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small)
- ((j_common_ptr) cinfo, JPOOL_IMAGE, AC_STAT_BINS);
+ entropy->ac_stats[tbl] = (unsigned char *)(*cinfo->mem->alloc_small)
+ ((j_common_ptr)cinfo, JPOOL_IMAGE, AC_STAT_BINS);
MEMZERO(entropy->ac_stats[tbl], AC_STAT_BINS);
#ifdef CALCULATE_SPECTRAL_CONDITIONING
if (cinfo->progressive_mode)
/* Section G.1.3.2: Set appropriate arithmetic conditioning value Kx */
- cinfo->arith_ac_K[tbl] = cinfo->Ss + ((8 + cinfo->Se - cinfo->Ss) >> 4);
+ cinfo->arith_ac_K[tbl] = cinfo->Ss +
+ ((8 + cinfo->Se - cinfo->Ss) >> 4);
#endif
}
}
@@ -905,15 +909,15 @@ start_pass (j_compress_ptr cinfo, boolean gather_statistics)
*/
GLOBAL(void)
-jinit_arith_encoder (j_compress_ptr cinfo)
+jinit_arith_encoder(j_compress_ptr cinfo)
{
arith_entropy_ptr entropy;
int i;
entropy = (arith_entropy_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(arith_entropy_encoder));
- cinfo->entropy = (struct jpeg_entropy_encoder *) entropy;
+ cinfo->entropy = (struct jpeg_entropy_encoder *)entropy;
entropy->pub.start_pass = start_pass;
entropy->pub.finish_pass = finish_pass;
diff --git a/src/3rdparty/libjpeg/src/jccoefct.c b/src/3rdparty/libjpeg/src/jccoefct.c
index a08d6e3230..068232a527 100644
--- a/src/3rdparty/libjpeg/src/jccoefct.c
+++ b/src/3rdparty/libjpeg/src/jccoefct.c
@@ -58,21 +58,19 @@ typedef my_coef_controller *my_coef_ptr;
/* Forward declarations */
-METHODDEF(boolean) compress_data
- (j_compress_ptr cinfo, JSAMPIMAGE input_buf);
+METHODDEF(boolean) compress_data(j_compress_ptr cinfo, JSAMPIMAGE input_buf);
#ifdef FULL_COEF_BUFFER_SUPPORTED
-METHODDEF(boolean) compress_first_pass
- (j_compress_ptr cinfo, JSAMPIMAGE input_buf);
-METHODDEF(boolean) compress_output
- (j_compress_ptr cinfo, JSAMPIMAGE input_buf);
+METHODDEF(boolean) compress_first_pass(j_compress_ptr cinfo,
+ JSAMPIMAGE input_buf);
+METHODDEF(boolean) compress_output(j_compress_ptr cinfo, JSAMPIMAGE input_buf);
#endif
LOCAL(void)
-start_iMCU_row (j_compress_ptr cinfo)
+start_iMCU_row(j_compress_ptr cinfo)
/* Reset within-iMCU-row counters for a new row */
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
/* In an interleaved scan, an MCU row is the same as an iMCU row.
* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
@@ -81,7 +79,7 @@ start_iMCU_row (j_compress_ptr cinfo)
if (cinfo->comps_in_scan > 1) {
coef->MCU_rows_per_iMCU_row = 1;
} else {
- if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1))
+ if (coef->iMCU_row_num < (cinfo->total_iMCU_rows - 1))
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
else
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
@@ -97,9 +95,9 @@ start_iMCU_row (j_compress_ptr cinfo)
*/
METHODDEF(void)
-start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+start_pass_coef(j_compress_ptr cinfo, J_BUF_MODE pass_mode)
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
coef->iMCU_row_num = 0;
start_iMCU_row(cinfo);
@@ -140,9 +138,9 @@ start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
*/
METHODDEF(boolean)
-compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+compress_data(j_compress_ptr cinfo, JSAMPIMAGE input_buf)
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
JDIMENSION MCU_col_num; /* index of current MCU within row */
JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
@@ -167,31 +165,33 @@ compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
blkn = 0;
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
- blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
- : compptr->last_col_width;
+ blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width :
+ compptr->last_col_width;
xpos = MCU_col_num * compptr->MCU_sample_width;
ypos = yoffset * DCTSIZE; /* ypos == (yoffset+yindex) * DCTSIZE */
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
if (coef->iMCU_row_num < last_iMCU_row ||
- yoffset+yindex < compptr->last_row_height) {
+ yoffset + yindex < compptr->last_row_height) {
(*cinfo->fdct->forward_DCT) (cinfo, compptr,
input_buf[compptr->component_index],
coef->MCU_buffer[blkn],
- ypos, xpos, (JDIMENSION) blockcnt);
+ ypos, xpos, (JDIMENSION)blockcnt);
if (blockcnt < compptr->MCU_width) {
/* Create some dummy blocks at the right edge of the image. */
- jzero_far((void *) coef->MCU_buffer[blkn + blockcnt],
+ jzero_far((void *)coef->MCU_buffer[blkn + blockcnt],
(compptr->MCU_width - blockcnt) * sizeof(JBLOCK));
for (bi = blockcnt; bi < compptr->MCU_width; bi++) {
- coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0];
+ coef->MCU_buffer[blkn + bi][0][0] =
+ coef->MCU_buffer[blkn + bi - 1][0][0];
}
}
} else {
/* Create a row of dummy blocks at the bottom of the image. */
- jzero_far((void *) coef->MCU_buffer[blkn],
+ jzero_far((void *)coef->MCU_buffer[blkn],
compptr->MCU_width * sizeof(JBLOCK));
for (bi = 0; bi < compptr->MCU_width; bi++) {
- coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0];
+ coef->MCU_buffer[blkn + bi][0][0] =
+ coef->MCU_buffer[blkn - 1][0][0];
}
}
blkn += compptr->MCU_width;
@@ -201,7 +201,7 @@ compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
/* Try to write the MCU. In event of a suspension failure, we will
* re-DCT the MCU on restart (a bit inefficient, could be fixed...)
*/
- if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
+ if (!(*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
/* Suspension forced; update state counters and exit */
coef->MCU_vert_offset = yoffset;
coef->mcu_ctr = MCU_col_num;
@@ -242,9 +242,9 @@ compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
*/
METHODDEF(boolean)
-compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+compress_first_pass(j_compress_ptr cinfo, JSAMPIMAGE input_buf)
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
JDIMENSION blocks_across, MCUs_across, MCUindex;
int bi, ci, h_samp_factor, block_row, block_rows, ndummy;
@@ -257,21 +257,21 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
ci++, compptr++) {
/* Align the virtual buffer for this component. */
buffer = (*cinfo->mem->access_virt_barray)
- ((j_common_ptr) cinfo, coef->whole_image[ci],
+ ((j_common_ptr)cinfo, coef->whole_image[ci],
coef->iMCU_row_num * compptr->v_samp_factor,
- (JDIMENSION) compptr->v_samp_factor, TRUE);
+ (JDIMENSION)compptr->v_samp_factor, TRUE);
/* Count non-dummy DCT block rows in this iMCU row. */
if (coef->iMCU_row_num < last_iMCU_row)
block_rows = compptr->v_samp_factor;
else {
/* NB: can't use last_row_height here, since may not be set! */
- block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
+ block_rows = (int)(compptr->height_in_blocks % compptr->v_samp_factor);
if (block_rows == 0) block_rows = compptr->v_samp_factor;
}
blocks_across = compptr->width_in_blocks;
h_samp_factor = compptr->h_samp_factor;
/* Count number of dummy blocks to be added at the right margin. */
- ndummy = (int) (blocks_across % h_samp_factor);
+ ndummy = (int)(blocks_across % h_samp_factor);
if (ndummy > 0)
ndummy = h_samp_factor - ndummy;
/* Perform DCT for all non-dummy blocks in this iMCU row. Each call
@@ -281,12 +281,12 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
thisblockrow = buffer[block_row];
(*cinfo->fdct->forward_DCT) (cinfo, compptr,
input_buf[ci], thisblockrow,
- (JDIMENSION) (block_row * DCTSIZE),
- (JDIMENSION) 0, blocks_across);
+ (JDIMENSION)(block_row * DCTSIZE),
+ (JDIMENSION)0, blocks_across);
if (ndummy > 0) {
/* Create dummy blocks at the right edge of the image. */
thisblockrow += blocks_across; /* => first dummy block */
- jzero_far((void *) thisblockrow, ndummy * sizeof(JBLOCK));
+ jzero_far((void *)thisblockrow, ndummy * sizeof(JBLOCK));
lastDC = thisblockrow[-1][0];
for (bi = 0; bi < ndummy; bi++) {
thisblockrow[bi][0] = lastDC;
@@ -304,11 +304,11 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
for (block_row = block_rows; block_row < compptr->v_samp_factor;
block_row++) {
thisblockrow = buffer[block_row];
- lastblockrow = buffer[block_row-1];
- jzero_far((void *) thisblockrow,
- (size_t) (blocks_across * sizeof(JBLOCK)));
+ lastblockrow = buffer[block_row - 1];
+ jzero_far((void *)thisblockrow,
+ (size_t)(blocks_across * sizeof(JBLOCK)));
for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) {
- lastDC = lastblockrow[h_samp_factor-1][0];
+ lastDC = lastblockrow[h_samp_factor - 1][0];
for (bi = 0; bi < h_samp_factor; bi++) {
thisblockrow[bi][0] = lastDC;
}
@@ -338,9 +338,9 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
*/
METHODDEF(boolean)
-compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+compress_output(j_compress_ptr cinfo, JSAMPIMAGE input_buf)
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
JDIMENSION MCU_col_num; /* index of current MCU within row */
int blkn, ci, xindex, yindex, yoffset;
JDIMENSION start_col;
@@ -355,9 +355,9 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
buffer[ci] = (*cinfo->mem->access_virt_barray)
- ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
+ ((j_common_ptr)cinfo, coef->whole_image[compptr->component_index],
coef->iMCU_row_num * compptr->v_samp_factor,
- (JDIMENSION) compptr->v_samp_factor, FALSE);
+ (JDIMENSION)compptr->v_samp_factor, FALSE);
}
/* Loop to process one whole iMCU row */
@@ -371,14 +371,14 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
compptr = cinfo->cur_comp_info[ci];
start_col = MCU_col_num * compptr->MCU_width;
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
- buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
+ buffer_ptr = buffer[ci][yindex + yoffset] + start_col;
for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
coef->MCU_buffer[blkn++] = buffer_ptr++;
}
}
}
/* Try to write the MCU. */
- if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
+ if (!(*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
/* Suspension forced; update state counters and exit */
coef->MCU_vert_offset = yoffset;
coef->mcu_ctr = MCU_col_num;
@@ -402,14 +402,14 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
*/
GLOBAL(void)
-jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer)
+jinit_c_coef_controller(j_compress_ptr cinfo, boolean need_full_buffer)
{
my_coef_ptr coef;
coef = (my_coef_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_coef_controller));
- cinfo->coef = (struct jpeg_c_coef_controller *) coef;
+ cinfo->coef = (struct jpeg_c_coef_controller *)coef;
coef->pub.start_pass = start_pass_coef;
/* Create the coefficient buffer. */
@@ -423,12 +423,12 @@ jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer)
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
- ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
- (JDIMENSION) jround_up((long) compptr->width_in_blocks,
- (long) compptr->h_samp_factor),
- (JDIMENSION) jround_up((long) compptr->height_in_blocks,
- (long) compptr->v_samp_factor),
- (JDIMENSION) compptr->v_samp_factor);
+ ((j_common_ptr)cinfo, JPOOL_IMAGE, FALSE,
+ (JDIMENSION)jround_up((long)compptr->width_in_blocks,
+ (long)compptr->h_samp_factor),
+ (JDIMENSION)jround_up((long)compptr->height_in_blocks,
+ (long)compptr->v_samp_factor),
+ (JDIMENSION)compptr->v_samp_factor);
}
#else
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
@@ -439,7 +439,7 @@ jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer)
int i;
buffer = (JBLOCKROW)
- (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_large) ((j_common_ptr)cinfo, JPOOL_IMAGE,
C_MAX_BLOCKS_IN_MCU * sizeof(JBLOCK));
for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) {
coef->MCU_buffer[i] = buffer + i;
diff --git a/src/3rdparty/libjpeg/src/jccolext.c b/src/3rdparty/libjpeg/src/jccolext.c
index 479b320446..19c955c9d6 100644
--- a/src/3rdparty/libjpeg/src/jccolext.c
+++ b/src/3rdparty/libjpeg/src/jccolext.c
@@ -29,13 +29,13 @@
INLINE
LOCAL(void)
-rgb_ycc_convert_internal (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows)
+rgb_ycc_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf, JDIMENSION output_row,
+ int num_rows)
{
- my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int r, g, b;
- register JLONG * ctab = cconvert->rgb_ycc_tab;
+ register JLONG *ctab = cconvert->rgb_ycc_tab;
register JSAMPROW inptr;
register JSAMPROW outptr0, outptr1, outptr2;
register JDIMENSION col;
@@ -58,17 +58,14 @@ rgb_ycc_convert_internal (j_compress_ptr cinfo,
* need the general RIGHT_SHIFT macro.
*/
/* Y */
- outptr0[col] = (JSAMPLE)
- ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
- >> SCALEBITS);
+ outptr0[col] = (JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] +
+ ctab[b + B_Y_OFF]) >> SCALEBITS);
/* Cb */
- outptr1[col] = (JSAMPLE)
- ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
- >> SCALEBITS);
+ outptr1[col] = (JSAMPLE)((ctab[r + R_CB_OFF] + ctab[g + G_CB_OFF] +
+ ctab[b + B_CB_OFF]) >> SCALEBITS);
/* Cr */
- outptr2[col] = (JSAMPLE)
- ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
- >> SCALEBITS);
+ outptr2[col] = (JSAMPLE)((ctab[r + R_CR_OFF] + ctab[g + G_CR_OFF] +
+ ctab[b + B_CR_OFF]) >> SCALEBITS);
}
}
}
@@ -86,13 +83,13 @@ rgb_ycc_convert_internal (j_compress_ptr cinfo,
INLINE
LOCAL(void)
-rgb_gray_convert_internal (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows)
+rgb_gray_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf, JDIMENSION output_row,
+ int num_rows)
{
- my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int r, g, b;
- register JLONG * ctab = cconvert->rgb_ycc_tab;
+ register JLONG *ctab = cconvert->rgb_ycc_tab;
register JSAMPROW inptr;
register JSAMPROW outptr;
register JDIMENSION col;
@@ -108,9 +105,8 @@ rgb_gray_convert_internal (j_compress_ptr cinfo,
b = GETJSAMPLE(inptr[RGB_BLUE]);
inptr += RGB_PIXELSIZE;
/* Y */
- outptr[col] = (JSAMPLE)
- ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
- >> SCALEBITS);
+ outptr[col] = (JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] +
+ ctab[b + B_Y_OFF]) >> SCALEBITS);
}
}
}
@@ -123,9 +119,9 @@ rgb_gray_convert_internal (j_compress_ptr cinfo,
INLINE
LOCAL(void)
-rgb_rgb_convert_internal (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows)
+rgb_rgb_convert_internal(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf, JDIMENSION output_row,
+ int num_rows)
{
register JSAMPROW inptr;
register JSAMPROW outptr0, outptr1, outptr2;
diff --git a/src/3rdparty/libjpeg/src/jccolor.c b/src/3rdparty/libjpeg/src/jccolor.c
index b973d101d6..036f6016d1 100644
--- a/src/3rdparty/libjpeg/src/jccolor.c
+++ b/src/3rdparty/libjpeg/src/jccolor.c
@@ -63,9 +63,9 @@ typedef my_color_converter *my_cconvert_ptr;
*/
#define SCALEBITS 16 /* speediest right-shift on some machines */
-#define CBCR_OFFSET ((JLONG) CENTERJSAMPLE << SCALEBITS)
-#define ONE_HALF ((JLONG) 1 << (SCALEBITS-1))
-#define FIX(x) ((JLONG) ((x) * (1L<<SCALEBITS) + 0.5))
+#define CBCR_OFFSET ((JLONG)CENTERJSAMPLE << SCALEBITS)
+#define ONE_HALF ((JLONG)1 << (SCALEBITS - 1))
+#define FIX(x) ((JLONG)((x) * (1L << SCALEBITS) + 0.5))
/* We allocate one big table and divide it up into eight parts, instead of
* doing eight alloc_small requests. This lets us use a single table base
@@ -74,15 +74,15 @@ typedef my_color_converter *my_cconvert_ptr;
*/
#define R_Y_OFF 0 /* offset to R => Y section */
-#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */
-#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */
-#define R_CB_OFF (3*(MAXJSAMPLE+1))
-#define G_CB_OFF (4*(MAXJSAMPLE+1))
-#define B_CB_OFF (5*(MAXJSAMPLE+1))
+#define G_Y_OFF (1 * (MAXJSAMPLE + 1)) /* offset to G => Y section */
+#define B_Y_OFF (2 * (MAXJSAMPLE + 1)) /* etc. */
+#define R_CB_OFF (3 * (MAXJSAMPLE + 1))
+#define G_CB_OFF (4 * (MAXJSAMPLE + 1))
+#define B_CB_OFF (5 * (MAXJSAMPLE + 1))
#define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */
-#define G_CR_OFF (6*(MAXJSAMPLE+1))
-#define B_CR_OFF (7*(MAXJSAMPLE+1))
-#define TABLE_SIZE (8*(MAXJSAMPLE+1))
+#define G_CR_OFF (6 * (MAXJSAMPLE + 1))
+#define B_CR_OFF (7 * (MAXJSAMPLE + 1))
+#define TABLE_SIZE (8 * (MAXJSAMPLE + 1))
/* Include inline routines for colorspace extensions */
@@ -93,13 +93,13 @@ typedef my_color_converter *my_cconvert_ptr;
#undef RGB_BLUE
#undef RGB_PIXELSIZE
-#define RGB_RED EXT_RGB_RED
-#define RGB_GREEN EXT_RGB_GREEN
-#define RGB_BLUE EXT_RGB_BLUE
-#define RGB_PIXELSIZE EXT_RGB_PIXELSIZE
-#define rgb_ycc_convert_internal extrgb_ycc_convert_internal
-#define rgb_gray_convert_internal extrgb_gray_convert_internal
-#define rgb_rgb_convert_internal extrgb_rgb_convert_internal
+#define RGB_RED EXT_RGB_RED
+#define RGB_GREEN EXT_RGB_GREEN
+#define RGB_BLUE EXT_RGB_BLUE
+#define RGB_PIXELSIZE EXT_RGB_PIXELSIZE
+#define rgb_ycc_convert_internal extrgb_ycc_convert_internal
+#define rgb_gray_convert_internal extrgb_gray_convert_internal
+#define rgb_rgb_convert_internal extrgb_rgb_convert_internal
#include "jccolext.c"
#undef RGB_RED
#undef RGB_GREEN
@@ -109,13 +109,13 @@ typedef my_color_converter *my_cconvert_ptr;
#undef rgb_gray_convert_internal
#undef rgb_rgb_convert_internal
-#define RGB_RED EXT_RGBX_RED
-#define RGB_GREEN EXT_RGBX_GREEN
-#define RGB_BLUE EXT_RGBX_BLUE
-#define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE
-#define rgb_ycc_convert_internal extrgbx_ycc_convert_internal
-#define rgb_gray_convert_internal extrgbx_gray_convert_internal
-#define rgb_rgb_convert_internal extrgbx_rgb_convert_internal
+#define RGB_RED EXT_RGBX_RED
+#define RGB_GREEN EXT_RGBX_GREEN
+#define RGB_BLUE EXT_RGBX_BLUE
+#define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE
+#define rgb_ycc_convert_internal extrgbx_ycc_convert_internal
+#define rgb_gray_convert_internal extrgbx_gray_convert_internal
+#define rgb_rgb_convert_internal extrgbx_rgb_convert_internal
#include "jccolext.c"
#undef RGB_RED
#undef RGB_GREEN
@@ -125,13 +125,13 @@ typedef my_color_converter *my_cconvert_ptr;
#undef rgb_gray_convert_internal
#undef rgb_rgb_convert_internal
-#define RGB_RED EXT_BGR_RED
-#define RGB_GREEN EXT_BGR_GREEN
-#define RGB_BLUE EXT_BGR_BLUE
-#define RGB_PIXELSIZE EXT_BGR_PIXELSIZE
-#define rgb_ycc_convert_internal extbgr_ycc_convert_internal
-#define rgb_gray_convert_internal extbgr_gray_convert_internal
-#define rgb_rgb_convert_internal extbgr_rgb_convert_internal
+#define RGB_RED EXT_BGR_RED
+#define RGB_GREEN EXT_BGR_GREEN
+#define RGB_BLUE EXT_BGR_BLUE
+#define RGB_PIXELSIZE EXT_BGR_PIXELSIZE
+#define rgb_ycc_convert_internal extbgr_ycc_convert_internal
+#define rgb_gray_convert_internal extbgr_gray_convert_internal
+#define rgb_rgb_convert_internal extbgr_rgb_convert_internal
#include "jccolext.c"
#undef RGB_RED
#undef RGB_GREEN
@@ -141,13 +141,13 @@ typedef my_color_converter *my_cconvert_ptr;
#undef rgb_gray_convert_internal
#undef rgb_rgb_convert_internal
-#define RGB_RED EXT_BGRX_RED
-#define RGB_GREEN EXT_BGRX_GREEN
-#define RGB_BLUE EXT_BGRX_BLUE
-#define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE
-#define rgb_ycc_convert_internal extbgrx_ycc_convert_internal
-#define rgb_gray_convert_internal extbgrx_gray_convert_internal
-#define rgb_rgb_convert_internal extbgrx_rgb_convert_internal
+#define RGB_RED EXT_BGRX_RED
+#define RGB_GREEN EXT_BGRX_GREEN
+#define RGB_BLUE EXT_BGRX_BLUE
+#define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE
+#define rgb_ycc_convert_internal extbgrx_ycc_convert_internal
+#define rgb_gray_convert_internal extbgrx_gray_convert_internal
+#define rgb_rgb_convert_internal extbgrx_rgb_convert_internal
#include "jccolext.c"
#undef RGB_RED
#undef RGB_GREEN
@@ -157,13 +157,13 @@ typedef my_color_converter *my_cconvert_ptr;
#undef rgb_gray_convert_internal
#undef rgb_rgb_convert_internal
-#define RGB_RED EXT_XBGR_RED
-#define RGB_GREEN EXT_XBGR_GREEN
-#define RGB_BLUE EXT_XBGR_BLUE
-#define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE
-#define rgb_ycc_convert_internal extxbgr_ycc_convert_internal
-#define rgb_gray_convert_internal extxbgr_gray_convert_internal
-#define rgb_rgb_convert_internal extxbgr_rgb_convert_internal
+#define RGB_RED EXT_XBGR_RED
+#define RGB_GREEN EXT_XBGR_GREEN
+#define RGB_BLUE EXT_XBGR_BLUE
+#define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE
+#define rgb_ycc_convert_internal extxbgr_ycc_convert_internal
+#define rgb_gray_convert_internal extxbgr_gray_convert_internal
+#define rgb_rgb_convert_internal extxbgr_rgb_convert_internal
#include "jccolext.c"
#undef RGB_RED
#undef RGB_GREEN
@@ -173,13 +173,13 @@ typedef my_color_converter *my_cconvert_ptr;
#undef rgb_gray_convert_internal
#undef rgb_rgb_convert_internal
-#define RGB_RED EXT_XRGB_RED
-#define RGB_GREEN EXT_XRGB_GREEN
-#define RGB_BLUE EXT_XRGB_BLUE
-#define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE
-#define rgb_ycc_convert_internal extxrgb_ycc_convert_internal
-#define rgb_gray_convert_internal extxrgb_gray_convert_internal
-#define rgb_rgb_convert_internal extxrgb_rgb_convert_internal
+#define RGB_RED EXT_XRGB_RED
+#define RGB_GREEN EXT_XRGB_GREEN
+#define RGB_BLUE EXT_XRGB_BLUE
+#define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE
+#define rgb_ycc_convert_internal extxrgb_ycc_convert_internal
+#define rgb_gray_convert_internal extxrgb_gray_convert_internal
+#define rgb_rgb_convert_internal extxrgb_rgb_convert_internal
#include "jccolext.c"
#undef RGB_RED
#undef RGB_GREEN
@@ -195,33 +195,33 @@ typedef my_color_converter *my_cconvert_ptr;
*/
METHODDEF(void)
-rgb_ycc_start (j_compress_ptr cinfo)
+rgb_ycc_start(j_compress_ptr cinfo)
{
- my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
JLONG *rgb_ycc_tab;
JLONG i;
/* Allocate and fill in the conversion tables. */
cconvert->rgb_ycc_tab = rgb_ycc_tab = (JLONG *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
(TABLE_SIZE * sizeof(JLONG)));
for (i = 0; i <= MAXJSAMPLE; i++) {
- rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i;
- rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i;
- rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF;
- rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i;
- rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i;
+ rgb_ycc_tab[i + R_Y_OFF] = FIX(0.29900) * i;
+ rgb_ycc_tab[i + G_Y_OFF] = FIX(0.58700) * i;
+ rgb_ycc_tab[i + B_Y_OFF] = FIX(0.11400) * i + ONE_HALF;
+ rgb_ycc_tab[i + R_CB_OFF] = (-FIX(0.16874)) * i;
+ rgb_ycc_tab[i + G_CB_OFF] = (-FIX(0.33126)) * i;
/* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
* This ensures that the maximum output will round to MAXJSAMPLE
* not MAXJSAMPLE+1, and thus that we don't have to range-limit.
*/
- rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1;
+ rgb_ycc_tab[i + B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF - 1;
/* B=>Cb and R=>Cr tables are the same
- rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1;
+ rgb_ycc_tab[i + R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF - 1;
*/
- rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i;
- rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i;
+ rgb_ycc_tab[i + G_CR_OFF] = (-FIX(0.41869)) * i;
+ rgb_ycc_tab[i + B_CR_OFF] = (-FIX(0.08131)) * i;
}
}
@@ -231,43 +231,42 @@ rgb_ycc_start (j_compress_ptr cinfo)
*/
METHODDEF(void)
-rgb_ycc_convert (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows)
+rgb_ycc_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)
{
switch (cinfo->in_color_space) {
- case JCS_EXT_RGB:
- extrgb_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_RGBX:
- case JCS_EXT_RGBA:
- extrgbx_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_BGR:
- extbgr_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_BGRX:
- case JCS_EXT_BGRA:
- extbgrx_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_XBGR:
- case JCS_EXT_ABGR:
- extxbgr_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_XRGB:
- case JCS_EXT_ARGB:
- extxrgb_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- default:
- rgb_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
+ case JCS_EXT_RGB:
+ extrgb_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_RGBX:
+ case JCS_EXT_RGBA:
+ extrgbx_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_BGR:
+ extbgr_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_BGRX:
+ case JCS_EXT_BGRA:
+ extbgrx_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_XBGR:
+ case JCS_EXT_ABGR:
+ extxbgr_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_XRGB:
+ case JCS_EXT_ARGB:
+ extxrgb_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ default:
+ rgb_ycc_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
}
}
@@ -280,43 +279,42 @@ rgb_ycc_convert (j_compress_ptr cinfo,
*/
METHODDEF(void)
-rgb_gray_convert (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows)
+rgb_gray_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)
{
switch (cinfo->in_color_space) {
- case JCS_EXT_RGB:
- extrgb_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_RGBX:
- case JCS_EXT_RGBA:
- extrgbx_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_BGR:
- extbgr_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_BGRX:
- case JCS_EXT_BGRA:
- extbgrx_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_XBGR:
- case JCS_EXT_ABGR:
- extxbgr_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_XRGB:
- case JCS_EXT_ARGB:
- extxrgb_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- default:
- rgb_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
+ case JCS_EXT_RGB:
+ extrgb_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_RGBX:
+ case JCS_EXT_RGBA:
+ extrgbx_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_BGR:
+ extbgr_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_BGRX:
+ case JCS_EXT_BGRA:
+ extbgrx_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_XBGR:
+ case JCS_EXT_ABGR:
+ extxbgr_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_XRGB:
+ case JCS_EXT_ARGB:
+ extxrgb_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ default:
+ rgb_gray_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
}
}
@@ -326,43 +324,42 @@ rgb_gray_convert (j_compress_ptr cinfo,
*/
METHODDEF(void)
-rgb_rgb_convert (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows)
+rgb_rgb_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)
{
switch (cinfo->in_color_space) {
- case JCS_EXT_RGB:
- extrgb_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_RGBX:
- case JCS_EXT_RGBA:
- extrgbx_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_BGR:
- extbgr_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_BGRX:
- case JCS_EXT_BGRA:
- extbgrx_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_XBGR:
- case JCS_EXT_ABGR:
- extxbgr_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- case JCS_EXT_XRGB:
- case JCS_EXT_ARGB:
- extxrgb_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
- default:
- rgb_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
- num_rows);
- break;
+ case JCS_EXT_RGB:
+ extrgb_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_RGBX:
+ case JCS_EXT_RGBA:
+ extrgbx_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_BGR:
+ extbgr_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_BGRX:
+ case JCS_EXT_BGRA:
+ extbgrx_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_XBGR:
+ case JCS_EXT_ABGR:
+ extxbgr_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ case JCS_EXT_XRGB:
+ case JCS_EXT_ARGB:
+ extxrgb_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
+ default:
+ rgb_rgb_convert_internal(cinfo, input_buf, output_buf, output_row,
+ num_rows);
+ break;
}
}
@@ -376,11 +373,10 @@ rgb_rgb_convert (j_compress_ptr cinfo,
*/
METHODDEF(void)
-cmyk_ycck_convert (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows)
+cmyk_ycck_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)
{
- my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int r, g, b;
register JLONG *ctab = cconvert->rgb_ycc_tab;
register JSAMPROW inptr;
@@ -408,17 +404,14 @@ cmyk_ycck_convert (j_compress_ptr cinfo,
* need the general RIGHT_SHIFT macro.
*/
/* Y */
- outptr0[col] = (JSAMPLE)
- ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
- >> SCALEBITS);
+ outptr0[col] = (JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] +
+ ctab[b + B_Y_OFF]) >> SCALEBITS);
/* Cb */
- outptr1[col] = (JSAMPLE)
- ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
- >> SCALEBITS);
+ outptr1[col] = (JSAMPLE)((ctab[r + R_CB_OFF] + ctab[g + G_CB_OFF] +
+ ctab[b + B_CB_OFF]) >> SCALEBITS);
/* Cr */
- outptr2[col] = (JSAMPLE)
- ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
- >> SCALEBITS);
+ outptr2[col] = (JSAMPLE)((ctab[r + R_CR_OFF] + ctab[g + G_CR_OFF] +
+ ctab[b + B_CR_OFF]) >> SCALEBITS);
}
}
}
@@ -431,9 +424,8 @@ cmyk_ycck_convert (j_compress_ptr cinfo,
*/
METHODDEF(void)
-grayscale_convert (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows)
+grayscale_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)
{
register JSAMPROW inptr;
register JSAMPROW outptr;
@@ -460,9 +452,8 @@ grayscale_convert (j_compress_ptr cinfo,
*/
METHODDEF(void)
-null_convert (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows)
+null_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows)
{
register JSAMPROW inptr;
register JSAMPROW outptr, outptr0, outptr1, outptr2, outptr3;
@@ -522,7 +513,7 @@ null_convert (j_compress_ptr cinfo,
*/
METHODDEF(void)
-null_method (j_compress_ptr cinfo)
+null_method(j_compress_ptr cinfo)
{
/* no work needed */
}
@@ -533,14 +524,14 @@ null_method (j_compress_ptr cinfo)
*/
GLOBAL(void)
-jinit_color_converter (j_compress_ptr cinfo)
+jinit_color_converter(j_compress_ptr cinfo)
{
my_cconvert_ptr cconvert;
cconvert = (my_cconvert_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_color_converter));
- cinfo->cconvert = (struct jpeg_color_converter *) cconvert;
+ cinfo->cconvert = (struct jpeg_color_converter *)cconvert;
/* set start_pass to null method until we find out differently */
cconvert->pub.start_pass = null_method;
diff --git a/src/3rdparty/libjpeg/src/jcdctmgr.c b/src/3rdparty/libjpeg/src/jcdctmgr.c
index 6e3b19bcb3..c04058e6ce 100644
--- a/src/3rdparty/libjpeg/src/jcdctmgr.c
+++ b/src/3rdparty/libjpeg/src/jcdctmgr.c
@@ -41,7 +41,7 @@ typedef void (*float_quantize_method_ptr) (JCOEFPTR coef_block,
FAST_FLOAT *divisors,
FAST_FLOAT *workspace);
-METHODDEF(void) quantize (JCOEFPTR, DCTELEM *, DCTELEM *);
+METHODDEF(void) quantize(JCOEFPTR, DCTELEM *, DCTELEM *);
typedef struct {
struct jpeg_forward_dct pub; /* public fields */
@@ -80,7 +80,7 @@ typedef my_fdct_controller *my_fdct_ptr;
*/
LOCAL(int)
-flss (UINT16 val)
+flss(UINT16 val)
{
int bit;
@@ -170,7 +170,7 @@ flss (UINT16 val)
*/
LOCAL(int)
-compute_reciprocal (UINT16 divisor, DCTELEM *dtbl)
+compute_reciprocal(UINT16 divisor, DCTELEM *dtbl)
{
UDCTELEM2 fq, fr;
UDCTELEM c;
@@ -182,10 +182,10 @@ compute_reciprocal (UINT16 divisor, DCTELEM *dtbl)
* identity function. Since only the C quantization algorithm is used in
* these cases, the scale value is irrelevant.
*/
- dtbl[DCTSIZE2 * 0] = (DCTELEM) 1; /* reciprocal */
- dtbl[DCTSIZE2 * 1] = (DCTELEM) 0; /* correction */
- dtbl[DCTSIZE2 * 2] = (DCTELEM) 1; /* scale */
- dtbl[DCTSIZE2 * 3] = -(DCTELEM) (sizeof(DCTELEM) * 8); /* shift */
+ dtbl[DCTSIZE2 * 0] = (DCTELEM)1; /* reciprocal */
+ dtbl[DCTSIZE2 * 1] = (DCTELEM)0; /* correction */
+ dtbl[DCTSIZE2 * 2] = (DCTELEM)1; /* scale */
+ dtbl[DCTSIZE2 * 3] = -(DCTELEM)(sizeof(DCTELEM) * 8); /* shift */
return 0;
}
@@ -195,26 +195,26 @@ compute_reciprocal (UINT16 divisor, DCTELEM *dtbl)
fq = ((UDCTELEM2)1 << r) / divisor;
fr = ((UDCTELEM2)1 << r) % divisor;
- c = divisor / 2; /* for rounding */
+ c = divisor / 2; /* for rounding */
- if (fr == 0) { /* divisor is power of two */
+ if (fr == 0) { /* divisor is power of two */
/* fq will be one bit too large to fit in DCTELEM, so adjust */
fq >>= 1;
r--;
- } else if (fr <= (divisor / 2U)) { /* fractional part is < 0.5 */
+ } else if (fr <= (divisor / 2U)) { /* fractional part is < 0.5 */
c++;
- } else { /* fractional part is > 0.5 */
+ } else { /* fractional part is > 0.5 */
fq++;
}
- dtbl[DCTSIZE2 * 0] = (DCTELEM) fq; /* reciprocal */
- dtbl[DCTSIZE2 * 1] = (DCTELEM) c; /* correction + roundfactor */
+ dtbl[DCTSIZE2 * 0] = (DCTELEM)fq; /* reciprocal */
+ dtbl[DCTSIZE2 * 1] = (DCTELEM)c; /* correction + roundfactor */
#ifdef WITH_SIMD
- dtbl[DCTSIZE2 * 2] = (DCTELEM) (1 << (sizeof(DCTELEM)*8*2 - r)); /* scale */
+ dtbl[DCTSIZE2 * 2] = (DCTELEM)(1 << (sizeof(DCTELEM) * 8 * 2 - r)); /* scale */
#else
dtbl[DCTSIZE2 * 2] = 1;
#endif
- dtbl[DCTSIZE2 * 3] = (DCTELEM) r - sizeof(DCTELEM)*8; /* shift */
+ dtbl[DCTSIZE2 * 3] = (DCTELEM)r - sizeof(DCTELEM) * 8; /* shift */
if (r <= 16) return 0;
else return 1;
@@ -233,9 +233,9 @@ compute_reciprocal (UINT16 divisor, DCTELEM *dtbl)
*/
METHODDEF(void)
-start_pass_fdctmgr (j_compress_ptr cinfo)
+start_pass_fdctmgr(j_compress_ptr cinfo)
{
- my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
+ my_fdct_ptr fdct = (my_fdct_ptr)cinfo->fdct;
int ci, qtblno, i;
jpeg_component_info *compptr;
JQUANT_TBL *qtbl;
@@ -259,7 +259,7 @@ start_pass_fdctmgr (j_compress_ptr cinfo)
*/
if (fdct->divisors[qtblno] == NULL) {
fdct->divisors[qtblno] = (DCTELEM *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
(DCTSIZE2 * 4) * sizeof(DCTELEM));
}
dtbl = fdct->divisors[qtblno];
@@ -269,7 +269,7 @@ start_pass_fdctmgr (j_compress_ptr cinfo)
fdct->quantize == jsimd_quantize)
fdct->quantize = quantize;
#else
- dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3;
+ dtbl[i] = ((DCTELEM)qtbl->quantval[i]) << 3;
#endif
}
break;
@@ -283,7 +283,7 @@ start_pass_fdctmgr (j_compress_ptr cinfo)
* scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
* We apply a further scale factor of 8.
*/
-#define CONST_BITS 14
+#define CONST_BITS 14
static const INT16 aanscales[DCTSIZE2] = {
/* precomputed values scaled up by 14 bits */
16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
@@ -299,23 +299,23 @@ start_pass_fdctmgr (j_compress_ptr cinfo)
if (fdct->divisors[qtblno] == NULL) {
fdct->divisors[qtblno] = (DCTELEM *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
(DCTSIZE2 * 4) * sizeof(DCTELEM));
}
dtbl = fdct->divisors[qtblno];
for (i = 0; i < DCTSIZE2; i++) {
#if BITS_IN_JSAMPLE == 8
if (!compute_reciprocal(
- DESCALE(MULTIPLY16V16((JLONG) qtbl->quantval[i],
- (JLONG) aanscales[i]),
- CONST_BITS-3), &dtbl[i]) &&
+ DESCALE(MULTIPLY16V16((JLONG)qtbl->quantval[i],
+ (JLONG)aanscales[i]),
+ CONST_BITS - 3), &dtbl[i]) &&
fdct->quantize == jsimd_quantize)
fdct->quantize = quantize;
#else
- dtbl[i] = (DCTELEM)
- DESCALE(MULTIPLY16V16((JLONG) qtbl->quantval[i],
- (JLONG) aanscales[i]),
- CONST_BITS-3);
+ dtbl[i] = (DCTELEM)
+ DESCALE(MULTIPLY16V16((JLONG)qtbl->quantval[i],
+ (JLONG)aanscales[i]),
+ CONST_BITS - 3);
#endif
}
}
@@ -341,7 +341,7 @@ start_pass_fdctmgr (j_compress_ptr cinfo)
if (fdct->float_divisors[qtblno] == NULL) {
fdct->float_divisors[qtblno] = (FAST_FLOAT *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
DCTSIZE2 * sizeof(FAST_FLOAT));
}
fdtbl = fdct->float_divisors[qtblno];
@@ -349,7 +349,7 @@ start_pass_fdctmgr (j_compress_ptr cinfo)
for (row = 0; row < DCTSIZE; row++) {
for (col = 0; col < DCTSIZE; col++) {
fdtbl[i] = (FAST_FLOAT)
- (1.0 / (((double) qtbl->quantval[i] *
+ (1.0 / (((double)qtbl->quantval[i] *
aanscalefactor[row] * aanscalefactor[col] * 8.0)));
i++;
}
@@ -370,7 +370,7 @@ start_pass_fdctmgr (j_compress_ptr cinfo)
*/
METHODDEF(void)
-convsamp (JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM *workspace)
+convsamp(JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM *workspace)
{
register DCTELEM *workspaceptr;
register JSAMPROW elemptr;
@@ -405,7 +405,7 @@ convsamp (JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM *workspace)
*/
METHODDEF(void)
-quantize (JCOEFPTR coef_block, DCTELEM *divisors, DCTELEM *workspace)
+quantize(JCOEFPTR coef_block, DCTELEM *divisors, DCTELEM *workspace)
{
int i;
DCTELEM temp;
@@ -426,15 +426,15 @@ quantize (JCOEFPTR coef_block, DCTELEM *divisors, DCTELEM *workspace)
if (temp < 0) {
temp = -temp;
product = (UDCTELEM2)(temp + corr) * recip;
- product >>= shift + sizeof(DCTELEM)*8;
+ product >>= shift + sizeof(DCTELEM) * 8;
temp = (DCTELEM)product;
temp = -temp;
} else {
product = (UDCTELEM2)(temp + corr) * recip;
- product >>= shift + sizeof(DCTELEM)*8;
+ product >>= shift + sizeof(DCTELEM) * 8;
temp = (DCTELEM)product;
}
- output_ptr[i] = (JCOEF) temp;
+ output_ptr[i] = (JCOEF)temp;
}
#else
@@ -457,20 +457,20 @@ quantize (JCOEFPTR coef_block, DCTELEM *divisors, DCTELEM *workspace)
* If your machine's division is fast enough, define FAST_DIVIDE.
*/
#ifdef FAST_DIVIDE
-#define DIVIDE_BY(a,b) a /= b
+#define DIVIDE_BY(a, b) a /= b
#else
-#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0
+#define DIVIDE_BY(a, b) if (a >= b) a /= b; else a = 0
#endif
if (temp < 0) {
temp = -temp;
- temp += qval>>1; /* for rounding */
+ temp += qval >> 1; /* for rounding */
DIVIDE_BY(temp, qval);
temp = -temp;
} else {
- temp += qval>>1; /* for rounding */
+ temp += qval >> 1; /* for rounding */
DIVIDE_BY(temp, qval);
}
- output_ptr[i] = (JCOEF) temp;
+ output_ptr[i] = (JCOEF)temp;
}
#endif
@@ -487,14 +487,13 @@ quantize (JCOEFPTR coef_block, DCTELEM *divisors, DCTELEM *workspace)
*/
METHODDEF(void)
-forward_DCT (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
- JDIMENSION start_row, JDIMENSION start_col,
- JDIMENSION num_blocks)
+forward_DCT(j_compress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
+ JDIMENSION start_row, JDIMENSION start_col, JDIMENSION num_blocks)
/* This version is used for integer DCT implementations. */
{
/* This routine is heavily used, so it's worth coding it tightly. */
- my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
+ my_fdct_ptr fdct = (my_fdct_ptr)cinfo->fdct;
DCTELEM *divisors = fdct->divisors[compptr->quant_tbl_no];
DCTELEM *workspace;
JDIMENSION bi;
@@ -522,9 +521,9 @@ forward_DCT (j_compress_ptr cinfo, jpeg_component_info *compptr,
#ifdef DCT_FLOAT_SUPPORTED
-
METHODDEF(void)
-convsamp_float (JSAMPARRAY sample_data, JDIMENSION start_col, FAST_FLOAT *workspace)
+convsamp_float(JSAMPARRAY sample_data, JDIMENSION start_col,
+ FAST_FLOAT *workspace)
{
register FAST_FLOAT *workspaceptr;
register JSAMPROW elemptr;
@@ -555,7 +554,8 @@ convsamp_float (JSAMPARRAY sample_data, JDIMENSION start_col, FAST_FLOAT *worksp
METHODDEF(void)
-quantize_float (JCOEFPTR coef_block, FAST_FLOAT *divisors, FAST_FLOAT *workspace)
+quantize_float(JCOEFPTR coef_block, FAST_FLOAT *divisors,
+ FAST_FLOAT *workspace)
{
register FAST_FLOAT temp;
register int i;
@@ -571,20 +571,20 @@ quantize_float (JCOEFPTR coef_block, FAST_FLOAT *divisors, FAST_FLOAT *workspace
* The maximum coefficient size is +-16K (for 12-bit data), so this
* code should work for either 16-bit or 32-bit ints.
*/
- output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384);
+ output_ptr[i] = (JCOEF)((int)(temp + (FAST_FLOAT)16384.5) - 16384);
}
}
METHODDEF(void)
-forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
- JDIMENSION start_row, JDIMENSION start_col,
- JDIMENSION num_blocks)
+forward_DCT_float(j_compress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
+ JDIMENSION start_row, JDIMENSION start_col,
+ JDIMENSION num_blocks)
/* This version is used for floating-point DCT implementations. */
{
/* This routine is heavily used, so it's worth coding it tightly. */
- my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
+ my_fdct_ptr fdct = (my_fdct_ptr)cinfo->fdct;
FAST_FLOAT *divisors = fdct->float_divisors[compptr->quant_tbl_no];
FAST_FLOAT *workspace;
JDIMENSION bi;
@@ -618,15 +618,15 @@ forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info *compptr,
*/
GLOBAL(void)
-jinit_forward_dct (j_compress_ptr cinfo)
+jinit_forward_dct(j_compress_ptr cinfo)
{
my_fdct_ptr fdct;
int i;
fdct = (my_fdct_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_fdct_controller));
- cinfo->fdct = (struct jpeg_forward_dct *) fdct;
+ cinfo->fdct = (struct jpeg_forward_dct *)fdct;
fdct->pub.start_pass = start_pass_fdctmgr;
/* First determine the DCT... */
@@ -703,12 +703,12 @@ jinit_forward_dct (j_compress_ptr cinfo)
#ifdef DCT_FLOAT_SUPPORTED
if (cinfo->dct_method == JDCT_FLOAT)
fdct->float_workspace = (FAST_FLOAT *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(FAST_FLOAT) * DCTSIZE2);
else
#endif
fdct->workspace = (DCTELEM *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(DCTELEM) * DCTSIZE2);
/* Mark divisor tables unallocated */
diff --git a/src/3rdparty/libjpeg/src/jchuff.c b/src/3rdparty/libjpeg/src/jchuff.c
index fffaacebce..939b3e76a1 100644
--- a/src/3rdparty/libjpeg/src/jchuff.c
+++ b/src/3rdparty/libjpeg/src/jchuff.c
@@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1997, Thomas G. Lane.
* libjpeg-turbo Modifications:
- * Copyright (C) 2009-2011, 2014-2016, D. R. Commander.
+ * Copyright (C) 2009-2011, 2014-2016, 2018, D. R. Commander.
* Copyright (C) 2015, Matthieu Darbois.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
@@ -16,6 +16,9 @@
* back up to the start of the current MCU. To do this, we copy state
* variables into local working storage, and update them back to the
* permanent JPEG objects only upon successful completion of an MCU.
+ *
+ * NOTE: All referenced figures are from
+ * Recommendation ITU-T T.81 (1992) | ISO/IEC 10918-1:1994.
*/
#define JPEG_INTERNALS
@@ -47,16 +50,12 @@
#endif
#ifdef USE_CLZ_INTRINSIC
-#define JPEG_NBITS_NONZERO(x) (32 - __builtin_clz(x))
-#define JPEG_NBITS(x) (x ? JPEG_NBITS_NONZERO(x) : 0)
+#define JPEG_NBITS_NONZERO(x) (32 - __builtin_clz(x))
+#define JPEG_NBITS(x) (x ? JPEG_NBITS_NONZERO(x) : 0)
#else
#include "jpeg_nbits_table.h"
-#define JPEG_NBITS(x) (jpeg_nbits_table[x])
-#define JPEG_NBITS_NONZERO(x) JPEG_NBITS(x)
-#endif
-
-#ifndef min
- #define min(a,b) ((a)<(b)?(a):(b))
+#define JPEG_NBITS(x) (jpeg_nbits_table[x])
+#define JPEG_NBITS_NONZERO(x) JPEG_NBITS(x)
#endif
@@ -67,9 +66,9 @@
*/
typedef struct {
- size_t put_buffer; /* current bit-accumulation buffer */
- int put_bits; /* # of bits now in it */
- int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
+ size_t put_buffer; /* current bit-accumulation buffer */
+ int put_bits; /* # of bits now in it */
+ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
} savable_state;
/* This macro is to work around compilers with missing or broken
@@ -78,16 +77,16 @@ typedef struct {
*/
#ifndef NO_STRUCT_ASSIGN
-#define ASSIGN_STATE(dest,src) ((dest) = (src))
+#define ASSIGN_STATE(dest, src) ((dest) = (src))
#else
#if MAX_COMPS_IN_SCAN == 4
-#define ASSIGN_STATE(dest,src) \
- ((dest).put_buffer = (src).put_buffer, \
- (dest).put_bits = (src).put_bits, \
- (dest).last_dc_val[0] = (src).last_dc_val[0], \
- (dest).last_dc_val[1] = (src).last_dc_val[1], \
- (dest).last_dc_val[2] = (src).last_dc_val[2], \
- (dest).last_dc_val[3] = (src).last_dc_val[3])
+#define ASSIGN_STATE(dest, src) \
+ ((dest).put_buffer = (src).put_buffer, \
+ (dest).put_bits = (src).put_bits, \
+ (dest).last_dc_val[0] = (src).last_dc_val[0], \
+ (dest).last_dc_val[1] = (src).last_dc_val[1], \
+ (dest).last_dc_val[2] = (src).last_dc_val[2], \
+ (dest).last_dc_val[3] = (src).last_dc_val[3])
#endif
#endif
@@ -128,12 +127,12 @@ typedef struct {
/* Forward declarations */
-METHODDEF(boolean) encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data);
-METHODDEF(void) finish_pass_huff (j_compress_ptr cinfo);
+METHODDEF(boolean) encode_mcu_huff(j_compress_ptr cinfo, JBLOCKROW *MCU_data);
+METHODDEF(void) finish_pass_huff(j_compress_ptr cinfo);
#ifdef ENTROPY_OPT_SUPPORTED
-METHODDEF(boolean) encode_mcu_gather (j_compress_ptr cinfo,
- JBLOCKROW *MCU_data);
-METHODDEF(void) finish_pass_gather (j_compress_ptr cinfo);
+METHODDEF(boolean) encode_mcu_gather(j_compress_ptr cinfo,
+ JBLOCKROW *MCU_data);
+METHODDEF(void) finish_pass_gather(j_compress_ptr cinfo);
#endif
@@ -144,9 +143,9 @@ METHODDEF(void) finish_pass_gather (j_compress_ptr cinfo);
*/
METHODDEF(void)
-start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics)
+start_pass_huff(j_compress_ptr cinfo, boolean gather_statistics)
{
- huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
int ci, dctbl, actbl;
jpeg_component_info *compptr;
@@ -180,12 +179,12 @@ start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics)
/* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
if (entropy->dc_count_ptrs[dctbl] == NULL)
entropy->dc_count_ptrs[dctbl] = (long *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
257 * sizeof(long));
MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * sizeof(long));
if (entropy->ac_count_ptrs[actbl] == NULL)
entropy->ac_count_ptrs[actbl] = (long *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
257 * sizeof(long));
MEMZERO(entropy->ac_count_ptrs[actbl], 257 * sizeof(long));
#endif
@@ -193,9 +192,9 @@ start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics)
/* Compute derived values for Huffman tables */
/* We may do this more than once for a table, but it's not expensive */
jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl,
- & entropy->dc_derived_tbls[dctbl]);
+ &entropy->dc_derived_tbls[dctbl]);
jpeg_make_c_derived_tbl(cinfo, FALSE, actbl,
- & entropy->ac_derived_tbls[actbl]);
+ &entropy->ac_derived_tbls[actbl]);
}
/* Initialize DC predictions to 0 */
entropy->saved.last_dc_val[ci] = 0;
@@ -219,8 +218,8 @@ start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics)
*/
GLOBAL(void)
-jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno,
- c_derived_tbl **pdtbl)
+jpeg_make_c_derived_tbl(j_compress_ptr cinfo, boolean isDC, int tblno,
+ c_derived_tbl **pdtbl)
{
JHUFF_TBL *htbl;
c_derived_tbl *dtbl;
@@ -244,7 +243,7 @@ jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno,
/* Allocate a workspace if we haven't already done so. */
if (*pdtbl == NULL)
*pdtbl = (c_derived_tbl *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(c_derived_tbl));
dtbl = *pdtbl;
@@ -252,11 +251,11 @@ jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno,
p = 0;
for (l = 1; l <= 16; l++) {
- i = (int) htbl->bits[l];
+ i = (int)htbl->bits[l];
if (i < 0 || p + i > 256) /* protect against table overrun */
ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
while (i--)
- huffsize[p++] = (char) l;
+ huffsize[p++] = (char)l;
}
huffsize[p] = 0;
lastp = p;
@@ -268,14 +267,14 @@ jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno,
si = huffsize[0];
p = 0;
while (huffsize[p]) {
- while (((int) huffsize[p]) == si) {
+ while (((int)huffsize[p]) == si) {
huffcode[p++] = code;
code++;
}
/* code is now 1 more than the last code used for codelength si; but
* it must still fit in si bits, since no code is allowed to be all ones.
*/
- if (((JLONG) code) >= (((JLONG) 1) << si))
+ if (((JLONG)code) >= (((JLONG)1) << si))
ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
code <<= 1;
si++;
@@ -310,20 +309,21 @@ jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno,
/* Outputting bytes to the file */
/* Emit a byte, taking 'action' if must suspend. */
-#define emit_byte(state,val,action) \
- { *(state)->next_output_byte++ = (JOCTET) (val); \
- if (--(state)->free_in_buffer == 0) \
- if (! dump_buffer(state)) \
- { action; } }
+#define emit_byte(state, val, action) { \
+ *(state)->next_output_byte++ = (JOCTET)(val); \
+ if (--(state)->free_in_buffer == 0) \
+ if (!dump_buffer(state)) \
+ { action; } \
+}
LOCAL(boolean)
-dump_buffer (working_state *state)
+dump_buffer(working_state *state)
/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */
{
struct jpeg_destination_mgr *dest = state->cinfo->dest;
- if (! (*dest->empty_output_buffer) (state->cinfo))
+ if (!(*dest->empty_output_buffer) (state->cinfo))
return FALSE;
/* After a successful buffer dump, must reset buffer pointers */
state->next_output_byte = dest->next_output_byte;
@@ -349,7 +349,7 @@ dump_buffer (working_state *state)
*buffer++ = c; \
if (c == 0xFF) /* need to stuff a zero byte? */ \
*buffer++ = 0; \
- }
+}
#define PUT_BITS(code, size) { \
put_bits += size; \
@@ -387,7 +387,7 @@ dump_buffer (working_state *state)
#error Cannot determine word size
#endif
-#if SIZEOF_SIZE_T==8 || defined(_WIN64)
+#if SIZEOF_SIZE_T == 8 || defined(_WIN64)
#define EMIT_BITS(code, size) { \
CHECKBUF47() \
@@ -395,11 +395,11 @@ dump_buffer (working_state *state)
}
#define EMIT_CODE(code, size) { \
- temp2 &= (((JLONG) 1)<<nbits) - 1; \
+ temp2 &= (((JLONG)1) << nbits) - 1; \
CHECKBUF31() \
PUT_BITS(code, size) \
PUT_BITS(temp2, nbits) \
- }
+}
#else
@@ -409,12 +409,12 @@ dump_buffer (working_state *state)
}
#define EMIT_CODE(code, size) { \
- temp2 &= (((JLONG) 1)<<nbits) - 1; \
+ temp2 &= (((JLONG)1) << nbits) - 1; \
PUT_BITS(code, size) \
CHECKBUF15() \
PUT_BITS(temp2, nbits) \
CHECKBUF15() \
- }
+}
#endif
@@ -428,40 +428,39 @@ dump_buffer (working_state *state)
* scanning order-- 1, 8, 16, etc.), then this will produce an encoded block
* larger than 200 bytes.
*/
-#define BUFSIZE (DCTSIZE2 * 4)
+#define BUFSIZE (DCTSIZE2 * 4)
#define LOAD_BUFFER() { \
if (state->free_in_buffer < BUFSIZE) { \
localbuf = 1; \
buffer = _buffer; \
- } \
- else buffer = state->next_output_byte; \
- }
+ } else \
+ buffer = state->next_output_byte; \
+}
#define STORE_BUFFER() { \
if (localbuf) { \
bytes = buffer - _buffer; \
buffer = _buffer; \
while (bytes > 0) { \
- bytestocopy = min(bytes, state->free_in_buffer); \
+ bytestocopy = MIN(bytes, state->free_in_buffer); \
MEMCOPY(state->next_output_byte, buffer, bytestocopy); \
state->next_output_byte += bytestocopy; \
buffer += bytestocopy; \
state->free_in_buffer -= bytestocopy; \
if (state->free_in_buffer == 0) \
- if (! dump_buffer(state)) return FALSE; \
+ if (!dump_buffer(state)) return FALSE; \
bytes -= bytestocopy; \
} \
- } \
- else { \
+ } else { \
state->free_in_buffer -= (buffer - state->next_output_byte); \
state->next_output_byte = buffer; \
} \
- }
+}
LOCAL(boolean)
-flush_bits (working_state *state)
+flush_bits(working_state *state)
{
JOCTET _buffer[BUFSIZE], *buffer;
size_t put_buffer; int put_bits;
@@ -486,8 +485,8 @@ flush_bits (working_state *state)
/* Encode a single block's worth of coefficients */
LOCAL(boolean)
-encode_one_block_simd (working_state *state, JCOEFPTR block, int last_dc_val,
- c_derived_tbl *dctbl, c_derived_tbl *actbl)
+encode_one_block_simd(working_state *state, JCOEFPTR block, int last_dc_val,
+ c_derived_tbl *dctbl, c_derived_tbl *actbl)
{
JOCTET _buffer[BUFSIZE], *buffer;
size_t bytes, bytestocopy; int localbuf = 0;
@@ -503,8 +502,8 @@ encode_one_block_simd (working_state *state, JCOEFPTR block, int last_dc_val,
}
LOCAL(boolean)
-encode_one_block (working_state *state, JCOEFPTR block, int last_dc_val,
- c_derived_tbl *dctbl, c_derived_tbl *actbl)
+encode_one_block(working_state *state, JCOEFPTR block, int last_dc_val,
+ c_derived_tbl *dctbl, c_derived_tbl *actbl)
{
int temp, temp2, temp3;
int nbits;
@@ -522,11 +521,11 @@ encode_one_block (working_state *state, JCOEFPTR block, int last_dc_val,
temp = temp2 = block[0] - last_dc_val;
- /* This is a well-known technique for obtaining the absolute value without a
- * branch. It is derived from an assembly language technique presented in
- * "How to Optimize for the Pentium Processors", Copyright (c) 1996, 1997 by
- * Agner Fog.
- */
+ /* This is a well-known technique for obtaining the absolute value without a
+ * branch. It is derived from an assembly language technique presented in
+ * "How to Optimize for the Pentium Processors", Copyright (c) 1996, 1997 by
+ * Agner Fog.
+ */
temp3 = temp >> (CHAR_BIT * sizeof(int) - 1);
temp ^= temp3;
temp -= temp3;
@@ -544,7 +543,7 @@ encode_one_block (working_state *state, JCOEFPTR block, int last_dc_val,
EMIT_BITS(code, size)
/* Mask off any extra bits in code */
- temp2 &= (((JLONG) 1)<<nbits) - 1;
+ temp2 &= (((JLONG)1) << nbits) - 1;
/* Emit that number of bits of the value, if positive, */
/* or the complement of its magnitude, if negative. */
@@ -558,7 +557,7 @@ encode_one_block (working_state *state, JCOEFPTR block, int last_dc_val,
* improves performance greatly on systems with a limited number of
* registers (such as x86.)
*/
-#define kloop(jpeg_natural_order_of_k) { \
+#define kloop(jpeg_natural_order_of_k) { \
if ((temp = block[jpeg_natural_order_of_k]) == 0) { \
r++; \
} else { \
@@ -575,11 +574,11 @@ encode_one_block (working_state *state, JCOEFPTR block, int last_dc_val,
r -= 16; \
} \
/* Emit Huffman symbol for run length / number of bits */ \
- temp3 = (r << 4) + nbits; \
+ temp3 = (r << 4) + nbits; \
code = actbl->ehufco[temp3]; \
size = actbl->ehufsi[temp3]; \
EMIT_CODE(code, size) \
- r = 0; \
+ r = 0; \
} \
}
@@ -616,11 +615,11 @@ encode_one_block (working_state *state, JCOEFPTR block, int last_dc_val,
*/
LOCAL(boolean)
-emit_restart (working_state *state, int restart_num)
+emit_restart(working_state *state, int restart_num)
{
int ci;
- if (! flush_bits(state))
+ if (!flush_bits(state))
return FALSE;
emit_byte(state, 0xFF, return FALSE);
@@ -641,9 +640,9 @@ emit_restart (working_state *state, int restart_num)
*/
METHODDEF(boolean)
-encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+encode_mcu_huff(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
- huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
working_state state;
int blkn, ci;
jpeg_component_info *compptr;
@@ -657,7 +656,7 @@ encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
/* Emit restart marker if needed */
if (cinfo->restart_interval) {
if (entropy->restarts_to_go == 0)
- if (! emit_restart(&state, entropy->next_restart_num))
+ if (!emit_restart(&state, entropy->next_restart_num))
return FALSE;
}
@@ -666,10 +665,10 @@ encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
ci = cinfo->MCU_membership[blkn];
compptr = cinfo->cur_comp_info[ci];
- if (! encode_one_block_simd(&state,
- MCU_data[blkn][0], state.cur.last_dc_val[ci],
- entropy->dc_derived_tbls[compptr->dc_tbl_no],
- entropy->ac_derived_tbls[compptr->ac_tbl_no]))
+ if (!encode_one_block_simd(&state,
+ MCU_data[blkn][0], state.cur.last_dc_val[ci],
+ entropy->dc_derived_tbls[compptr->dc_tbl_no],
+ entropy->ac_derived_tbls[compptr->ac_tbl_no]))
return FALSE;
/* Update last_dc_val */
state.cur.last_dc_val[ci] = MCU_data[blkn][0][0];
@@ -678,10 +677,10 @@ encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
ci = cinfo->MCU_membership[blkn];
compptr = cinfo->cur_comp_info[ci];
- if (! encode_one_block(&state,
- MCU_data[blkn][0], state.cur.last_dc_val[ci],
- entropy->dc_derived_tbls[compptr->dc_tbl_no],
- entropy->ac_derived_tbls[compptr->ac_tbl_no]))
+ if (!encode_one_block(&state,
+ MCU_data[blkn][0], state.cur.last_dc_val[ci],
+ entropy->dc_derived_tbls[compptr->dc_tbl_no],
+ entropy->ac_derived_tbls[compptr->ac_tbl_no]))
return FALSE;
/* Update last_dc_val */
state.cur.last_dc_val[ci] = MCU_data[blkn][0][0];
@@ -712,9 +711,9 @@ encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
*/
METHODDEF(void)
-finish_pass_huff (j_compress_ptr cinfo)
+finish_pass_huff(j_compress_ptr cinfo)
{
- huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
working_state state;
/* Load up working state ... flush_bits needs it */
@@ -724,7 +723,7 @@ finish_pass_huff (j_compress_ptr cinfo)
state.cinfo = cinfo;
/* Flush out the last data */
- if (! flush_bits(&state))
+ if (!flush_bits(&state))
ERREXIT(cinfo, JERR_CANT_SUSPEND);
/* Update state */
@@ -751,8 +750,8 @@ finish_pass_huff (j_compress_ptr cinfo)
/* Process a single block's worth of coefficients */
LOCAL(void)
-htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val,
- long dc_counts[], long ac_counts[])
+htest_one_block(j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val,
+ long dc_counts[], long ac_counts[])
{
register int temp;
register int nbits;
@@ -773,7 +772,7 @@ htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val,
/* Check for out-of-range coefficient values.
* Since we're encoding a difference, the range limit is twice as much.
*/
- if (nbits > MAX_COEF_BITS+1)
+ if (nbits > MAX_COEF_BITS + 1)
ERREXIT(cinfo, JERR_BAD_DCT_COEF);
/* Count the Huffman symbol for the number of bits */
@@ -824,9 +823,9 @@ htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val,
*/
METHODDEF(boolean)
-encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+encode_mcu_gather(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
- huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
int blkn, ci;
jpeg_component_info *compptr;
@@ -863,13 +862,14 @@ encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
* one bits (so that padding bits added at the end of a compressed segment
* can't look like a valid code). Because of the canonical ordering of
* codewords, this just means that there must be an unused slot in the
- * longest codeword length category. Section K.2 of the JPEG spec suggests
- * reserving such a slot by pretending that symbol 256 is a valid symbol
- * with count 1. In theory that's not optimal; giving it count zero but
- * including it in the symbol set anyway should give a better Huffman code.
- * But the theoretically better code actually seems to come out worse in
- * practice, because it produces more all-ones bytes (which incur stuffed
- * zero bytes in the final file). In any case the difference is tiny.
+ * longest codeword length category. Annex K (Clause K.2) of
+ * Rec. ITU-T T.81 (1992) | ISO/IEC 10918-1:1994 suggests reserving such a slot
+ * by pretending that symbol 256 is a valid symbol with count 1. In theory
+ * that's not optimal; giving it count zero but including it in the symbol set
+ * anyway should give a better Huffman code. But the theoretically better code
+ * actually seems to come out worse in practice, because it produces more
+ * all-ones bytes (which incur stuffed zero bytes in the final file). In any
+ * case the difference is tiny.
*
* The JPEG standard requires Huffman codes to be no more than 16 bits long.
* If some symbols have a very small but nonzero probability, the Huffman tree
@@ -884,10 +884,10 @@ encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
*/
GLOBAL(void)
-jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[])
+jpeg_gen_optimal_table(j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[])
{
-#define MAX_CLEN 32 /* assumed maximum initial code length */
- UINT8 bits[MAX_CLEN+1]; /* bits[k] = # of symbols with code length k */
+#define MAX_CLEN 32 /* assumed maximum initial code length */
+ UINT8 bits[MAX_CLEN + 1]; /* bits[k] = # of symbols with code length k */
int codesize[257]; /* codesize[k] = code length of symbol k */
int others[257]; /* next symbol in current branch of tree */
int c1, c2;
@@ -971,13 +971,13 @@ jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[])
/* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure
* Huffman procedure assigned any such lengths, we must adjust the coding.
- * Here is what the JPEG spec says about how this next bit works:
- * Since symbols are paired for the longest Huffman code, the symbols are
- * removed from this length category two at a time. The prefix for the pair
- * (which is one bit shorter) is allocated to one of the pair; then,
- * skipping the BITS entry for that prefix length, a code word from the next
- * shortest nonzero BITS entry is converted into a prefix for two code words
- * one bit longer.
+ * Here is what Rec. ITU-T T.81 | ISO/IEC 10918-1 says about how this next
+ * bit works: Since symbols are paired for the longest Huffman code, the
+ * symbols are removed from this length category two at a time. The prefix
+ * for the pair (which is one bit shorter) is allocated to one of the pair;
+ * then, skipping the BITS entry for that prefix length, a code word from the
+ * next shortest nonzero BITS entry is converted into a prefix for two code
+ * words one bit longer.
*/
for (i = MAX_CLEN; i > 16; i--) {
@@ -987,8 +987,8 @@ jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[])
j--;
bits[i] -= 2; /* remove two symbols */
- bits[i-1]++; /* one goes in this length */
- bits[j+1] += 2; /* two new symbols in this length */
+ bits[i - 1]++; /* one goes in this length */
+ bits[j + 1] += 2; /* two new symbols in this length */
bits[j]--; /* symbol of this length is now a prefix */
}
}
@@ -1003,13 +1003,14 @@ jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[])
/* Return a list of the symbols sorted by code length */
/* It's not real clear to me why we don't need to consider the codelength
- * changes made above, but the JPEG spec seems to think this works.
+ * changes made above, but Rec. ITU-T T.81 | ISO/IEC 10918-1 seems to think
+ * this works.
*/
p = 0;
for (i = 1; i <= MAX_CLEN; i++) {
for (j = 0; j <= 255; j++) {
if (codesize[j] == i) {
- htbl->huffval[p] = (UINT8) j;
+ htbl->huffval[p] = (UINT8)j;
p++;
}
}
@@ -1025,9 +1026,9 @@ jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[])
*/
METHODDEF(void)
-finish_pass_gather (j_compress_ptr cinfo)
+finish_pass_gather(j_compress_ptr cinfo)
{
- huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
int ci, dctbl, actbl;
jpeg_component_info *compptr;
JHUFF_TBL **htblptr;
@@ -1044,17 +1045,17 @@ finish_pass_gather (j_compress_ptr cinfo)
compptr = cinfo->cur_comp_info[ci];
dctbl = compptr->dc_tbl_no;
actbl = compptr->ac_tbl_no;
- if (! did_dc[dctbl]) {
- htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl];
+ if (!did_dc[dctbl]) {
+ htblptr = &cinfo->dc_huff_tbl_ptrs[dctbl];
if (*htblptr == NULL)
- *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr)cinfo);
jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]);
did_dc[dctbl] = TRUE;
}
- if (! did_ac[actbl]) {
- htblptr = & cinfo->ac_huff_tbl_ptrs[actbl];
+ if (!did_ac[actbl]) {
+ htblptr = &cinfo->ac_huff_tbl_ptrs[actbl];
if (*htblptr == NULL)
- *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr)cinfo);
jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]);
did_ac[actbl] = TRUE;
}
@@ -1070,15 +1071,15 @@ finish_pass_gather (j_compress_ptr cinfo)
*/
GLOBAL(void)
-jinit_huff_encoder (j_compress_ptr cinfo)
+jinit_huff_encoder(j_compress_ptr cinfo)
{
huff_entropy_ptr entropy;
int i;
entropy = (huff_entropy_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(huff_entropy_encoder));
- cinfo->entropy = (struct jpeg_entropy_encoder *) entropy;
+ cinfo->entropy = (struct jpeg_entropy_encoder *)entropy;
entropy->pub.start_pass = start_pass_huff;
/* Mark tables unallocated */
diff --git a/src/3rdparty/libjpeg/src/jchuff.h b/src/3rdparty/libjpeg/src/jchuff.h
index 4236089adc..314a2325c9 100644
--- a/src/3rdparty/libjpeg/src/jchuff.h
+++ b/src/3rdparty/libjpeg/src/jchuff.h
@@ -20,9 +20,9 @@
*/
#if BITS_IN_JSAMPLE == 8
-#define MAX_COEF_BITS 10
+#define MAX_COEF_BITS 10
#else
-#define MAX_COEF_BITS 14
+#define MAX_COEF_BITS 14
#endif
/* Derived data constructed for each Huffman table */
@@ -34,10 +34,9 @@ typedef struct {
} c_derived_tbl;
/* Expand a Huffman table definition into the derived format */
-EXTERN(void) jpeg_make_c_derived_tbl
- (j_compress_ptr cinfo, boolean isDC, int tblno,
- c_derived_tbl ** pdtbl);
+EXTERN(void) jpeg_make_c_derived_tbl(j_compress_ptr cinfo, boolean isDC,
+ int tblno, c_derived_tbl **pdtbl);
/* Generate an optimal table definition given the specified counts */
-EXTERN(void) jpeg_gen_optimal_table
- (j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[]);
+EXTERN(void) jpeg_gen_optimal_table(j_compress_ptr cinfo, JHUFF_TBL *htbl,
+ long freq[]);
diff --git a/src/3rdparty/libjpeg/src/jcinit.c b/src/3rdparty/libjpeg/src/jcinit.c
index 463bd8c6dd..78aa465786 100644
--- a/src/3rdparty/libjpeg/src/jcinit.c
+++ b/src/3rdparty/libjpeg/src/jcinit.c
@@ -28,13 +28,13 @@
*/
GLOBAL(void)
-jinit_compress_master (j_compress_ptr cinfo)
+jinit_compress_master(j_compress_ptr cinfo)
{
/* Initialize master control (includes parameter checking/processing) */
jinit_c_master_control(cinfo, FALSE /* full compression */);
/* Preprocessing */
- if (! cinfo->raw_data_in) {
+ if (!cinfo->raw_data_in) {
jinit_color_converter(cinfo);
jinit_downsampler(cinfo);
jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */);
@@ -60,14 +60,14 @@ jinit_compress_master (j_compress_ptr cinfo)
}
/* Need a full-image coefficient buffer in any multi-pass mode. */
- jinit_c_coef_controller(cinfo,
- (boolean) (cinfo->num_scans > 1 || cinfo->optimize_coding));
+ jinit_c_coef_controller(cinfo, (boolean)(cinfo->num_scans > 1 ||
+ cinfo->optimize_coding));
jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */);
jinit_marker_writer(cinfo);
/* We can now tell the memory manager to allocate virtual arrays. */
- (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
+ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr)cinfo);
/* Write the datastream header (SOI) immediately.
* Frame and scan headers are postponed till later.
diff --git a/src/3rdparty/libjpeg/src/jcmainct.c b/src/3rdparty/libjpeg/src/jcmainct.c
index d01f46364b..3f23028c46 100644
--- a/src/3rdparty/libjpeg/src/jcmainct.c
+++ b/src/3rdparty/libjpeg/src/jcmainct.c
@@ -39,9 +39,10 @@ typedef my_main_controller *my_main_ptr;
/* Forward declarations */
-METHODDEF(void) process_data_simple_main
- (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
- JDIMENSION in_rows_avail);
+METHODDEF(void) process_data_simple_main(j_compress_ptr cinfo,
+ JSAMPARRAY input_buf,
+ JDIMENSION *in_row_ctr,
+ JDIMENSION in_rows_avail);
/*
@@ -49,9 +50,9 @@ METHODDEF(void) process_data_simple_main
*/
METHODDEF(void)
-start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+start_pass_main(j_compress_ptr cinfo, J_BUF_MODE pass_mode)
{
- my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
+ my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
/* Do nothing in raw-data mode. */
if (cinfo->raw_data_in)
@@ -75,19 +76,18 @@ start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
*/
METHODDEF(void)
-process_data_simple_main (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
- JDIMENSION in_rows_avail)
+process_data_simple_main(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)
{
- my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
+ my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
while (main_ptr->cur_iMCU_row < cinfo->total_iMCU_rows) {
/* Read input data if we haven't filled the main buffer yet */
if (main_ptr->rowgroup_ctr < DCTSIZE)
- (*cinfo->prep->pre_process_data) (cinfo,
- input_buf, in_row_ctr, in_rows_avail,
- main_ptr->buffer, &main_ptr->rowgroup_ctr,
- (JDIMENSION) DCTSIZE);
+ (*cinfo->prep->pre_process_data) (cinfo, input_buf, in_row_ctr,
+ in_rows_avail, main_ptr->buffer,
+ &main_ptr->rowgroup_ctr,
+ (JDIMENSION)DCTSIZE);
/* If we don't have a full iMCU row buffered, return to application for
* more data. Note that preprocessor will always pad to fill the iMCU row
@@ -97,14 +97,14 @@ process_data_simple_main (j_compress_ptr cinfo,
return;
/* Send the completed row to the compressor */
- if (! (*cinfo->coef->compress_data) (cinfo, main_ptr->buffer)) {
+ if (!(*cinfo->coef->compress_data) (cinfo, main_ptr->buffer)) {
/* If compressor did not consume the whole row, then we must need to
* suspend processing and return to the application. In this situation
* we pretend we didn't yet consume the last input row; otherwise, if
* it happened to be the last row of the image, the application would
* think we were done.
*/
- if (! main_ptr->suspended) {
+ if (!main_ptr->suspended) {
(*in_row_ctr)--;
main_ptr->suspended = TRUE;
}
@@ -128,16 +128,16 @@ process_data_simple_main (j_compress_ptr cinfo,
*/
GLOBAL(void)
-jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer)
+jinit_c_main_controller(j_compress_ptr cinfo, boolean need_full_buffer)
{
my_main_ptr main_ptr;
int ci;
jpeg_component_info *compptr;
main_ptr = (my_main_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_main_controller));
- cinfo->main = (struct jpeg_c_main_controller *) main_ptr;
+ cinfo->main = (struct jpeg_c_main_controller *)main_ptr;
main_ptr->pub.start_pass = start_pass_main;
/* We don't need to create a buffer in raw-data mode. */
@@ -154,9 +154,9 @@ jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer)
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
main_ptr->buffer[ci] = (*cinfo->mem->alloc_sarray)
- ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ ((j_common_ptr)cinfo, JPOOL_IMAGE,
compptr->width_in_blocks * DCTSIZE,
- (JDIMENSION) (compptr->v_samp_factor * DCTSIZE));
+ (JDIMENSION)(compptr->v_samp_factor * DCTSIZE));
}
}
}
diff --git a/src/3rdparty/libjpeg/src/jcmarker.c b/src/3rdparty/libjpeg/src/jcmarker.c
index 463f665927..801fbab4ef 100644
--- a/src/3rdparty/libjpeg/src/jcmarker.c
+++ b/src/3rdparty/libjpeg/src/jcmarker.c
@@ -110,30 +110,30 @@ typedef my_marker_writer *my_marker_ptr;
*/
LOCAL(void)
-emit_byte (j_compress_ptr cinfo, int val)
+emit_byte(j_compress_ptr cinfo, int val)
/* Emit a byte */
{
struct jpeg_destination_mgr *dest = cinfo->dest;
- *(dest->next_output_byte)++ = (JOCTET) val;
+ *(dest->next_output_byte)++ = (JOCTET)val;
if (--dest->free_in_buffer == 0) {
- if (! (*dest->empty_output_buffer) (cinfo))
+ if (!(*dest->empty_output_buffer) (cinfo))
ERREXIT(cinfo, JERR_CANT_SUSPEND);
}
}
LOCAL(void)
-emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark)
+emit_marker(j_compress_ptr cinfo, JPEG_MARKER mark)
/* Emit a marker code */
{
emit_byte(cinfo, 0xFF);
- emit_byte(cinfo, (int) mark);
+ emit_byte(cinfo, (int)mark);
}
LOCAL(void)
-emit_2bytes (j_compress_ptr cinfo, int value)
+emit_2bytes(j_compress_ptr cinfo, int value)
/* Emit a 2-byte integer; these are always MSB first in JPEG files */
{
emit_byte(cinfo, (value >> 8) & 0xFF);
@@ -146,7 +146,7 @@ emit_2bytes (j_compress_ptr cinfo, int value)
*/
LOCAL(int)
-emit_dqt (j_compress_ptr cinfo, int index)
+emit_dqt(j_compress_ptr cinfo, int index)
/* Emit a DQT marker */
/* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */
{
@@ -163,19 +163,19 @@ emit_dqt (j_compress_ptr cinfo, int index)
prec = 1;
}
- if (! qtbl->sent_table) {
+ if (!qtbl->sent_table) {
emit_marker(cinfo, M_DQT);
- emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2);
+ emit_2bytes(cinfo, prec ? DCTSIZE2 * 2 + 1 + 2 : DCTSIZE2 + 1 + 2);
- emit_byte(cinfo, index + (prec<<4));
+ emit_byte(cinfo, index + (prec << 4));
for (i = 0; i < DCTSIZE2; i++) {
/* The table entries must be emitted in zigzag order. */
unsigned int qval = qtbl->quantval[jpeg_natural_order[i]];
if (prec)
- emit_byte(cinfo, (int) (qval >> 8));
- emit_byte(cinfo, (int) (qval & 0xFF));
+ emit_byte(cinfo, (int)(qval >> 8));
+ emit_byte(cinfo, (int)(qval & 0xFF));
}
qtbl->sent_table = TRUE;
@@ -186,7 +186,7 @@ emit_dqt (j_compress_ptr cinfo, int index)
LOCAL(void)
-emit_dht (j_compress_ptr cinfo, int index, boolean is_ac)
+emit_dht(j_compress_ptr cinfo, int index, boolean is_ac)
/* Emit a DHT marker */
{
JHUFF_TBL *htbl;
@@ -202,7 +202,7 @@ emit_dht (j_compress_ptr cinfo, int index, boolean is_ac)
if (htbl == NULL)
ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index);
- if (! htbl->sent_table) {
+ if (!htbl->sent_table) {
emit_marker(cinfo, M_DHT);
length = 0;
@@ -224,7 +224,7 @@ emit_dht (j_compress_ptr cinfo, int index, boolean is_ac)
LOCAL(void)
-emit_dac (j_compress_ptr cinfo)
+emit_dac(j_compress_ptr cinfo)
/* Emit a DAC marker */
/* Since the useful info is so small, we want to emit all the tables in */
/* one DAC marker. Therefore this routine does its own scan of the table. */
@@ -255,12 +255,12 @@ emit_dac (j_compress_ptr cinfo)
if (length) {
emit_marker(cinfo, M_DAC);
- emit_2bytes(cinfo, length*2 + 2);
+ emit_2bytes(cinfo, length * 2 + 2);
for (i = 0; i < NUM_ARITH_TBLS; i++) {
if (dc_in_use[i]) {
emit_byte(cinfo, i);
- emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4));
+ emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i] << 4));
}
if (ac_in_use[i]) {
emit_byte(cinfo, i + 0x10);
@@ -273,19 +273,19 @@ emit_dac (j_compress_ptr cinfo)
LOCAL(void)
-emit_dri (j_compress_ptr cinfo)
+emit_dri(j_compress_ptr cinfo)
/* Emit a DRI marker */
{
emit_marker(cinfo, M_DRI);
emit_2bytes(cinfo, 4); /* fixed length */
- emit_2bytes(cinfo, (int) cinfo->restart_interval);
+ emit_2bytes(cinfo, (int)cinfo->restart_interval);
}
LOCAL(void)
-emit_sof (j_compress_ptr cinfo, JPEG_MARKER code)
+emit_sof(j_compress_ptr cinfo, JPEG_MARKER code)
/* Emit a SOF marker */
{
int ci;
@@ -296,13 +296,12 @@ emit_sof (j_compress_ptr cinfo, JPEG_MARKER code)
emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */
/* Make sure image isn't bigger than SOF field can handle */
- if ((long) cinfo->_jpeg_height > 65535L ||
- (long) cinfo->_jpeg_width > 65535L)
- ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535);
+ if ((long)cinfo->_jpeg_height > 65535L || (long)cinfo->_jpeg_width > 65535L)
+ ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int)65535);
emit_byte(cinfo, cinfo->data_precision);
- emit_2bytes(cinfo, (int) cinfo->_jpeg_height);
- emit_2bytes(cinfo, (int) cinfo->_jpeg_width);
+ emit_2bytes(cinfo, (int)cinfo->_jpeg_height);
+ emit_2bytes(cinfo, (int)cinfo->_jpeg_width);
emit_byte(cinfo, cinfo->num_components);
@@ -316,7 +315,7 @@ emit_sof (j_compress_ptr cinfo, JPEG_MARKER code)
LOCAL(void)
-emit_sos (j_compress_ptr cinfo)
+emit_sos(j_compress_ptr cinfo)
/* Emit a SOS marker */
{
int i, td, ta;
@@ -351,7 +350,7 @@ emit_sos (j_compress_ptr cinfo)
LOCAL(void)
-emit_jfif_app0 (j_compress_ptr cinfo)
+emit_jfif_app0(j_compress_ptr cinfo)
/* Emit a JFIF-compliant APP0 marker */
{
/*
@@ -378,15 +377,15 @@ emit_jfif_app0 (j_compress_ptr cinfo)
emit_byte(cinfo, cinfo->JFIF_major_version); /* Version fields */
emit_byte(cinfo, cinfo->JFIF_minor_version);
emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */
- emit_2bytes(cinfo, (int) cinfo->X_density);
- emit_2bytes(cinfo, (int) cinfo->Y_density);
+ emit_2bytes(cinfo, (int)cinfo->X_density);
+ emit_2bytes(cinfo, (int)cinfo->Y_density);
emit_byte(cinfo, 0); /* No thumbnail image */
emit_byte(cinfo, 0);
}
LOCAL(void)
-emit_adobe_app14 (j_compress_ptr cinfo)
+emit_adobe_app14(j_compress_ptr cinfo)
/* Emit an Adobe APP14 marker */
{
/*
@@ -440,19 +439,19 @@ emit_adobe_app14 (j_compress_ptr cinfo)
*/
METHODDEF(void)
-write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen)
+write_marker_header(j_compress_ptr cinfo, int marker, unsigned int datalen)
/* Emit an arbitrary marker header */
{
- if (datalen > (unsigned int) 65533) /* safety check */
+ if (datalen > (unsigned int)65533) /* safety check */
ERREXIT(cinfo, JERR_BAD_LENGTH);
- emit_marker(cinfo, (JPEG_MARKER) marker);
+ emit_marker(cinfo, (JPEG_MARKER)marker);
- emit_2bytes(cinfo, (int) (datalen + 2)); /* total length */
+ emit_2bytes(cinfo, (int)(datalen + 2)); /* total length */
}
METHODDEF(void)
-write_marker_byte (j_compress_ptr cinfo, int val)
+write_marker_byte(j_compress_ptr cinfo, int val)
/* Emit one byte of marker parameters following write_marker_header */
{
emit_byte(cinfo, val);
@@ -471,9 +470,9 @@ write_marker_byte (j_compress_ptr cinfo, int val)
*/
METHODDEF(void)
-write_file_header (j_compress_ptr cinfo)
+write_file_header(j_compress_ptr cinfo)
{
- my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+ my_marker_ptr marker = (my_marker_ptr)cinfo->marker;
emit_marker(cinfo, M_SOI); /* first the SOI */
@@ -496,7 +495,7 @@ write_file_header (j_compress_ptr cinfo)
*/
METHODDEF(void)
-write_frame_header (j_compress_ptr cinfo)
+write_frame_header(j_compress_ptr cinfo)
{
int ci, prec;
boolean is_baseline;
@@ -556,9 +555,9 @@ write_frame_header (j_compress_ptr cinfo)
*/
METHODDEF(void)
-write_scan_header (j_compress_ptr cinfo)
+write_scan_header(j_compress_ptr cinfo)
{
- my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+ my_marker_ptr marker = (my_marker_ptr)cinfo->marker;
int i;
jpeg_component_info *compptr;
@@ -600,7 +599,7 @@ write_scan_header (j_compress_ptr cinfo)
*/
METHODDEF(void)
-write_file_trailer (j_compress_ptr cinfo)
+write_file_trailer(j_compress_ptr cinfo)
{
emit_marker(cinfo, M_EOI);
}
@@ -614,7 +613,7 @@ write_file_trailer (j_compress_ptr cinfo)
*/
METHODDEF(void)
-write_tables_only (j_compress_ptr cinfo)
+write_tables_only(j_compress_ptr cinfo)
{
int i;
@@ -622,10 +621,10 @@ write_tables_only (j_compress_ptr cinfo)
for (i = 0; i < NUM_QUANT_TBLS; i++) {
if (cinfo->quant_tbl_ptrs[i] != NULL)
- (void) emit_dqt(cinfo, i);
+ (void)emit_dqt(cinfo, i);
}
- if (! cinfo->arith_code) {
+ if (!cinfo->arith_code) {
for (i = 0; i < NUM_HUFF_TBLS; i++) {
if (cinfo->dc_huff_tbl_ptrs[i] != NULL)
emit_dht(cinfo, i, FALSE);
@@ -643,15 +642,15 @@ write_tables_only (j_compress_ptr cinfo)
*/
GLOBAL(void)
-jinit_marker_writer (j_compress_ptr cinfo)
+jinit_marker_writer(j_compress_ptr cinfo)
{
my_marker_ptr marker;
/* Create the subobject */
marker = (my_marker_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_marker_writer));
- cinfo->marker = (struct jpeg_marker_writer *) marker;
+ cinfo->marker = (struct jpeg_marker_writer *)marker;
/* Initialize method pointers */
marker->pub.write_file_header = write_file_header;
marker->pub.write_frame_header = write_frame_header;
diff --git a/src/3rdparty/libjpeg/src/jcmaster.c b/src/3rdparty/libjpeg/src/jcmaster.c
index 03a8b40ea9..93b3de6826 100644
--- a/src/3rdparty/libjpeg/src/jcmaster.c
+++ b/src/3rdparty/libjpeg/src/jcmaster.c
@@ -5,7 +5,7 @@
* Copyright (C) 1991-1997, Thomas G. Lane.
* Modified 2003-2010 by Guido Vollbeding.
* libjpeg-turbo Modifications:
- * Copyright (C) 2010, 2016, D. R. Commander.
+ * Copyright (C) 2010, 2016, 2018, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -25,9 +25,9 @@
/* Private state */
typedef enum {
- main_pass, /* input data, also do first output step */
- huff_opt_pass, /* Huffman code optimization pass */
- output_pass /* data output pass */
+ main_pass, /* input data, also do first output step */
+ huff_opt_pass, /* Huffman code optimization pass */
+ output_pass /* data output pass */
} c_pass_type;
typedef struct {
@@ -66,7 +66,7 @@ typedef my_comp_master *my_master_ptr;
*/
GLOBAL(void)
-jpeg_calc_jpeg_dimensions (j_compress_ptr cinfo)
+jpeg_calc_jpeg_dimensions(j_compress_ptr cinfo)
/* Do computations that are needed before master selection phase */
{
/* Hardwire it to "no scaling" */
@@ -79,7 +79,7 @@ jpeg_calc_jpeg_dimensions (j_compress_ptr cinfo)
LOCAL(void)
-initial_setup (j_compress_ptr cinfo, boolean transcode_only)
+initial_setup(j_compress_ptr cinfo, boolean transcode_only)
/* Do computations that are needed before master selection phase */
{
int ci;
@@ -95,19 +95,19 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only)
#endif
/* Sanity check on image dimensions */
- if (cinfo->_jpeg_height <= 0 || cinfo->_jpeg_width <= 0
- || cinfo->num_components <= 0 || cinfo->input_components <= 0)
+ if (cinfo->_jpeg_height <= 0 || cinfo->_jpeg_width <= 0 ||
+ cinfo->num_components <= 0 || cinfo->input_components <= 0)
ERREXIT(cinfo, JERR_EMPTY_IMAGE);
/* Make sure image isn't bigger than I can handle */
- if ((long) cinfo->_jpeg_height > (long) JPEG_MAX_DIMENSION ||
- (long) cinfo->_jpeg_width > (long) JPEG_MAX_DIMENSION)
- ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
+ if ((long)cinfo->_jpeg_height > (long)JPEG_MAX_DIMENSION ||
+ (long)cinfo->_jpeg_width > (long)JPEG_MAX_DIMENSION)
+ ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int)JPEG_MAX_DIMENSION);
/* Width of an input scanline must be representable as JDIMENSION. */
- samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components;
- jd_samplesperrow = (JDIMENSION) samplesperrow;
- if ((long) jd_samplesperrow != samplesperrow)
+ samplesperrow = (long)cinfo->image_width * (long)cinfo->input_components;
+ jd_samplesperrow = (JDIMENSION)samplesperrow;
+ if ((long)jd_samplesperrow != samplesperrow)
ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
/* For now, precision must match compiled-in value... */
@@ -124,8 +124,10 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only)
cinfo->max_v_samp_factor = 1;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
- if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
- compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
+ if (compptr->h_samp_factor <= 0 ||
+ compptr->h_samp_factor > MAX_SAMP_FACTOR ||
+ compptr->v_samp_factor <= 0 ||
+ compptr->v_samp_factor > MAX_SAMP_FACTOR)
ERREXIT(cinfo, JERR_BAD_SAMPLING);
cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
compptr->h_samp_factor);
@@ -146,18 +148,18 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only)
#endif
/* Size in DCT blocks */
compptr->width_in_blocks = (JDIMENSION)
- jdiv_round_up((long) cinfo->_jpeg_width * (long) compptr->h_samp_factor,
- (long) (cinfo->max_h_samp_factor * DCTSIZE));
+ jdiv_round_up((long)cinfo->_jpeg_width * (long)compptr->h_samp_factor,
+ (long)(cinfo->max_h_samp_factor * DCTSIZE));
compptr->height_in_blocks = (JDIMENSION)
- jdiv_round_up((long) cinfo->_jpeg_height * (long) compptr->v_samp_factor,
- (long) (cinfo->max_v_samp_factor * DCTSIZE));
+ jdiv_round_up((long)cinfo->_jpeg_height * (long)compptr->v_samp_factor,
+ (long)(cinfo->max_v_samp_factor * DCTSIZE));
/* Size in samples */
compptr->downsampled_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->_jpeg_width * (long) compptr->h_samp_factor,
- (long) cinfo->max_h_samp_factor);
+ jdiv_round_up((long)cinfo->_jpeg_width * (long)compptr->h_samp_factor,
+ (long)cinfo->max_h_samp_factor);
compptr->downsampled_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->_jpeg_height * (long) compptr->v_samp_factor,
- (long) cinfo->max_v_samp_factor);
+ jdiv_round_up((long)cinfo->_jpeg_height * (long)compptr->v_samp_factor,
+ (long)cinfo->max_v_samp_factor);
/* Mark component needed (this flag isn't actually used for compression) */
compptr->component_needed = TRUE;
}
@@ -166,15 +168,15 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only)
* main controller will call coefficient controller).
*/
cinfo->total_iMCU_rows = (JDIMENSION)
- jdiv_round_up((long) cinfo->_jpeg_height,
- (long) (cinfo->max_v_samp_factor*DCTSIZE));
+ jdiv_round_up((long)cinfo->_jpeg_height,
+ (long)(cinfo->max_v_samp_factor * DCTSIZE));
}
#ifdef C_MULTISCAN_FILES_SUPPORTED
LOCAL(void)
-validate_script (j_compress_ptr cinfo)
+validate_script(j_compress_ptr cinfo)
/* Verify that the scan script in cinfo->scan_info[] is valid; also
* determine whether it uses progressive JPEG, and set cinfo->progressive_mode.
*/
@@ -196,10 +198,10 @@ validate_script (j_compress_ptr cinfo)
* for progressive JPEG, no scan can have this.
*/
scanptr = cinfo->scan_info;
- if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) {
+ if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2 - 1) {
#ifdef C_PROGRESSIVE_SUPPORTED
cinfo->progressive_mode = TRUE;
- last_bitpos_ptr = & last_bitpos[0][0];
+ last_bitpos_ptr = &last_bitpos[0][0];
for (ci = 0; ci < cinfo->num_components; ci++)
for (coefi = 0; coefi < DCTSIZE2; coefi++)
*last_bitpos_ptr++ = -1;
@@ -222,7 +224,7 @@ validate_script (j_compress_ptr cinfo)
if (thisi < 0 || thisi >= cinfo->num_components)
ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
/* Components must appear in SOF order within each scan */
- if (ci > 0 && thisi <= scanptr->component_index[ci-1])
+ if (ci > 0 && thisi <= scanptr->component_index[ci - 1])
ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
}
/* Validate progression parameters */
@@ -232,17 +234,17 @@ validate_script (j_compress_ptr cinfo)
Al = scanptr->Al;
if (cinfo->progressive_mode) {
#ifdef C_PROGRESSIVE_SUPPORTED
- /* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that
- * seems wrong: the upper bound ought to depend on data precision.
- * Perhaps they really meant 0..N+1 for N-bit precision.
+ /* Rec. ITU-T T.81 | ISO/IEC 10918-1 simply gives the ranges 0..13 for Ah
+ * and Al, but that seems wrong: the upper bound ought to depend on data
+ * precision. Perhaps they really meant 0..N+1 for N-bit precision.
* Here we allow 0..10 for 8-bit data; Al larger than 10 results in
* out-of-range reconstructed DC values during the first DC scan,
* which might cause problems for some decoders.
*/
#if BITS_IN_JSAMPLE == 8
-#define MAX_AH_AL 10
+#define MAX_AH_AL 10
#else
-#define MAX_AH_AL 13
+#define MAX_AH_AL 13
#endif
if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 ||
Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL)
@@ -255,7 +257,7 @@ validate_script (j_compress_ptr cinfo)
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
}
for (ci = 0; ci < ncomps; ci++) {
- last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0];
+ last_bitpos_ptr = &last_bitpos[scanptr->component_index[ci]][0];
if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
for (coefi = Ss; coefi <= Se; coefi++) {
@@ -265,7 +267,7 @@ validate_script (j_compress_ptr cinfo)
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
} else {
/* not first scan */
- if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1)
+ if (Ah != last_bitpos_ptr[coefi] || Al != Ah - 1)
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
}
last_bitpos_ptr[coefi] = Al;
@@ -274,7 +276,7 @@ validate_script (j_compress_ptr cinfo)
#endif
} else {
/* For sequential JPEG, all progression parameters must be these: */
- if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0)
+ if (Ss != 0 || Se != DCTSIZE2 - 1 || Ah != 0 || Al != 0)
ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
/* Make sure components are not sent twice */
for (ci = 0; ci < ncomps; ci++) {
@@ -301,7 +303,7 @@ validate_script (j_compress_ptr cinfo)
#endif
} else {
for (ci = 0; ci < cinfo->num_components; ci++) {
- if (! component_sent[ci])
+ if (!component_sent[ci])
ERREXIT(cinfo, JERR_MISSING_DATA);
}
}
@@ -311,7 +313,7 @@ validate_script (j_compress_ptr cinfo)
LOCAL(void)
-select_scan_parameters (j_compress_ptr cinfo)
+select_scan_parameters(j_compress_ptr cinfo)
/* Set up the scan parameters for the current scan */
{
int ci;
@@ -319,7 +321,7 @@ select_scan_parameters (j_compress_ptr cinfo)
#ifdef C_MULTISCAN_FILES_SUPPORTED
if (cinfo->scan_info != NULL) {
/* Prepare for current scan --- the script is already validated */
- my_master_ptr master = (my_master_ptr) cinfo->master;
+ my_master_ptr master = (my_master_ptr)cinfo->master;
const jpeg_scan_info *scanptr = cinfo->scan_info + master->scan_number;
cinfo->comps_in_scan = scanptr->comps_in_scan;
@@ -331,8 +333,7 @@ select_scan_parameters (j_compress_ptr cinfo)
cinfo->Se = scanptr->Se;
cinfo->Ah = scanptr->Ah;
cinfo->Al = scanptr->Al;
- }
- else
+ } else
#endif
{
/* Prepare for single sequential-JPEG scan containing all components */
@@ -344,7 +345,7 @@ select_scan_parameters (j_compress_ptr cinfo)
cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
}
cinfo->Ss = 0;
- cinfo->Se = DCTSIZE2-1;
+ cinfo->Se = DCTSIZE2 - 1;
cinfo->Ah = 0;
cinfo->Al = 0;
}
@@ -352,7 +353,7 @@ select_scan_parameters (j_compress_ptr cinfo)
LOCAL(void)
-per_scan_setup (j_compress_ptr cinfo)
+per_scan_setup(j_compress_ptr cinfo)
/* Do computations that are needed before processing a JPEG scan */
/* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */
{
@@ -377,7 +378,7 @@ per_scan_setup (j_compress_ptr cinfo)
/* For noninterleaved scans, it is convenient to define last_row_height
* as the number of block rows present in the last iMCU row.
*/
- tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
+ tmp = (int)(compptr->height_in_blocks % compptr->v_samp_factor);
if (tmp == 0) tmp = compptr->v_samp_factor;
compptr->last_row_height = tmp;
@@ -394,11 +395,11 @@ per_scan_setup (j_compress_ptr cinfo)
/* Overall image size in MCUs */
cinfo->MCUs_per_row = (JDIMENSION)
- jdiv_round_up((long) cinfo->_jpeg_width,
- (long) (cinfo->max_h_samp_factor*DCTSIZE));
+ jdiv_round_up((long)cinfo->_jpeg_width,
+ (long)(cinfo->max_h_samp_factor * DCTSIZE));
cinfo->MCU_rows_in_scan = (JDIMENSION)
- jdiv_round_up((long) cinfo->_jpeg_height,
- (long) (cinfo->max_v_samp_factor*DCTSIZE));
+ jdiv_round_up((long)cinfo->_jpeg_height,
+ (long)(cinfo->max_v_samp_factor * DCTSIZE));
cinfo->blocks_in_MCU = 0;
@@ -410,10 +411,10 @@ per_scan_setup (j_compress_ptr cinfo)
compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE;
/* Figure number of non-dummy blocks in last MCU column & row */
- tmp = (int) (compptr->width_in_blocks % compptr->MCU_width);
+ tmp = (int)(compptr->width_in_blocks % compptr->MCU_width);
if (tmp == 0) tmp = compptr->MCU_width;
compptr->last_col_width = tmp;
- tmp = (int) (compptr->height_in_blocks % compptr->MCU_height);
+ tmp = (int)(compptr->height_in_blocks % compptr->MCU_height);
if (tmp == 0) tmp = compptr->MCU_height;
compptr->last_row_height = tmp;
/* Prepare array describing MCU composition */
@@ -430,8 +431,8 @@ per_scan_setup (j_compress_ptr cinfo)
/* Convert restart specified in rows to actual MCU count. */
/* Note that count must fit in 16 bits, so we provide limiting. */
if (cinfo->restart_in_rows > 0) {
- long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row;
- cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L);
+ long nominal = (long)cinfo->restart_in_rows * (long)cinfo->MCUs_per_row;
+ cinfo->restart_interval = (unsigned int)MIN(nominal, 65535L);
}
}
@@ -445,9 +446,9 @@ per_scan_setup (j_compress_ptr cinfo)
*/
METHODDEF(void)
-prepare_for_pass (j_compress_ptr cinfo)
+prepare_for_pass(j_compress_ptr cinfo)
{
- my_master_ptr master = (my_master_ptr) cinfo->master;
+ my_master_ptr master = (my_master_ptr)cinfo->master;
switch (master->pass_type) {
case main_pass:
@@ -456,7 +457,7 @@ prepare_for_pass (j_compress_ptr cinfo)
*/
select_scan_parameters(cinfo);
per_scan_setup(cinfo);
- if (! cinfo->raw_data_in) {
+ if (!cinfo->raw_data_in) {
(*cinfo->cconvert->start_pass) (cinfo);
(*cinfo->downsample->start_pass) (cinfo);
(*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU);
@@ -496,7 +497,7 @@ prepare_for_pass (j_compress_ptr cinfo)
case output_pass:
/* Do a data-output pass. */
/* We need not repeat per-scan setup if prior optimization pass did it. */
- if (! cinfo->optimize_coding) {
+ if (!cinfo->optimize_coding) {
select_scan_parameters(cinfo);
per_scan_setup(cinfo);
}
@@ -512,7 +513,7 @@ prepare_for_pass (j_compress_ptr cinfo)
ERREXIT(cinfo, JERR_NOT_COMPILED);
}
- master->pub.is_last_pass = (master->pass_number == master->total_passes-1);
+ master->pub.is_last_pass = (master->pass_number == master->total_passes - 1);
/* Set up progress monitor's pass info if present */
if (cinfo->progress != NULL) {
@@ -533,7 +534,7 @@ prepare_for_pass (j_compress_ptr cinfo)
*/
METHODDEF(void)
-pass_startup (j_compress_ptr cinfo)
+pass_startup(j_compress_ptr cinfo)
{
cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */
@@ -547,9 +548,9 @@ pass_startup (j_compress_ptr cinfo)
*/
METHODDEF(void)
-finish_pass_master (j_compress_ptr cinfo)
+finish_pass_master(j_compress_ptr cinfo)
{
- my_master_ptr master = (my_master_ptr) cinfo->master;
+ my_master_ptr master = (my_master_ptr)cinfo->master;
/* The entropy coder always needs an end-of-pass call,
* either to analyze statistics or to flush its output buffer.
@@ -563,7 +564,7 @@ finish_pass_master (j_compress_ptr cinfo)
* or output of scan 1 (if no optimization).
*/
master->pass_type = output_pass;
- if (! cinfo->optimize_coding)
+ if (!cinfo->optimize_coding)
master->scan_number++;
break;
case huff_opt_pass:
@@ -587,14 +588,14 @@ finish_pass_master (j_compress_ptr cinfo)
*/
GLOBAL(void)
-jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only)
+jinit_c_master_control(j_compress_ptr cinfo, boolean transcode_only)
{
my_master_ptr master;
master = (my_master_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- sizeof(my_comp_master));
- cinfo->master = (struct jpeg_comp_master *) master;
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ sizeof(my_comp_master));
+ cinfo->master = (struct jpeg_comp_master *)master;
master->pub.prepare_for_pass = prepare_for_pass;
master->pub.pass_startup = pass_startup;
master->pub.finish_pass = finish_pass_master;
diff --git a/src/3rdparty/libjpeg/src/jcomapi.c b/src/3rdparty/libjpeg/src/jcomapi.c
index 6e5bf3dba9..efbb8357b0 100644
--- a/src/3rdparty/libjpeg/src/jcomapi.c
+++ b/src/3rdparty/libjpeg/src/jcomapi.c
@@ -29,7 +29,7 @@
*/
GLOBAL(void)
-jpeg_abort (j_common_ptr cinfo)
+jpeg_abort(j_common_ptr cinfo)
{
int pool;
@@ -40,7 +40,7 @@ jpeg_abort (j_common_ptr cinfo)
/* Releasing pools in reverse order might help avoid fragmentation
* with some (brain-damaged) malloc libraries.
*/
- for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) {
+ for (pool = JPOOL_NUMPOOLS - 1; pool > JPOOL_PERMANENT; pool--) {
(*cinfo->mem->free_pool) (cinfo, pool);
}
@@ -50,7 +50,7 @@ jpeg_abort (j_common_ptr cinfo)
/* Try to keep application from accessing now-deleted marker list.
* A bit kludgy to do it here, but this is the most central place.
*/
- ((j_decompress_ptr) cinfo)->marker_list = NULL;
+ ((j_decompress_ptr)cinfo)->marker_list = NULL;
} else {
cinfo->global_state = CSTATE_START;
}
@@ -69,7 +69,7 @@ jpeg_abort (j_common_ptr cinfo)
*/
GLOBAL(void)
-jpeg_destroy (j_common_ptr cinfo)
+jpeg_destroy(j_common_ptr cinfo)
{
/* We need only tell the memory manager to release everything. */
/* NB: mem pointer is NULL if memory mgr failed to initialize. */
@@ -86,7 +86,7 @@ jpeg_destroy (j_common_ptr cinfo)
*/
GLOBAL(JQUANT_TBL *)
-jpeg_alloc_quant_table (j_common_ptr cinfo)
+jpeg_alloc_quant_table(j_common_ptr cinfo)
{
JQUANT_TBL *tbl;
@@ -98,7 +98,7 @@ jpeg_alloc_quant_table (j_common_ptr cinfo)
GLOBAL(JHUFF_TBL *)
-jpeg_alloc_huff_table (j_common_ptr cinfo)
+jpeg_alloc_huff_table(j_common_ptr cinfo)
{
JHUFF_TBL *tbl;
diff --git a/src/3rdparty/libjpeg/src/jconfig.h b/src/3rdparty/libjpeg/src/jconfig.h
deleted file mode 100644
index 808f87fcd4..0000000000
--- a/src/3rdparty/libjpeg/src/jconfig.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * jconfig.txt
- *
- * This file was part of the Independent JPEG Group's software:
- * Copyright (C) 1991-1994, Thomas G. Lane.
- * It was modified by The libjpeg-turbo Project to include only code relevant
- * to libjpeg-turbo.
- * For conditions of distribution and use, see the accompanying README.ijg
- * file.
- *
- * This file documents the configuration options that are required to
- * customize the JPEG software for a particular system.
- *
- * The actual configuration options for a particular installation are stored
- * in jconfig.h. On many machines, jconfig.h can be generated automatically
- * or copied from one of the "canned" jconfig files that we supply. But if
- * you need to generate a jconfig.h file by hand, this file tells you how.
- *
- * DO NOT EDIT THIS FILE --- IT WON'T ACCOMPLISH ANYTHING.
- * EDIT A COPY NAMED JCONFIG.H.
- */
-
-
-/*
- * These symbols indicate the properties of your machine or compiler.
- * #define the symbol if yes, #undef it if no.
- */
-
-/* Does your compiler support the declaration "unsigned char" ?
- * How about "unsigned short" ?
- */
-#define HAVE_UNSIGNED_CHAR
-#define HAVE_UNSIGNED_SHORT
-
-/* Define "void" as "char" if your compiler doesn't know about type void.
- * NOTE: be sure to define void such that "void *" represents the most general
- * pointer type, e.g., that returned by malloc().
- */
-/* #define void char */
-
-/* Define "const" as empty if your compiler doesn't know the "const" keyword.
- */
-/* #define const */
-
-/* Define this if an ordinary "char" type is unsigned.
- * If you're not sure, leaving it undefined will work at some cost in speed.
- * If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal.
- */
-#undef __CHAR_UNSIGNED__
-
-/* Define this if your system has an ANSI-conforming <stddef.h> file.
- */
-#define HAVE_STDDEF_H
-
-/* Define this if your system has an ANSI-conforming <stdlib.h> file.
- */
-#define HAVE_STDLIB_H
-
-/* Define this if your system does not have an ANSI/SysV <string.h>,
- * but does have a BSD-style <strings.h>.
- */
-#undef NEED_BSD_STRINGS
-
-/* Define this if your system does not provide typedef size_t in any of the
- * ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in
- * <sys/types.h> instead.
- */
-#undef NEED_SYS_TYPES_H
-
-/* Although a real ANSI C compiler can deal perfectly well with pointers to
- * unspecified structures (see "incomplete types" in the spec), a few pre-ANSI
- * and pseudo-ANSI compilers get confused. To keep one of these bozos happy,
- * define INCOMPLETE_TYPES_BROKEN. This is not recommended unless you
- * actually get "missing structure definition" warnings or errors while
- * compiling the JPEG code.
- */
-#undef INCOMPLETE_TYPES_BROKEN
-
-/* Define "boolean" as unsigned char, not int, on Windows systems.
- */
-#ifdef _WIN32
-#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */
-typedef unsigned char boolean;
-#endif
-#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */
-#endif
-
-
-/*
- * The following options affect code selection within the JPEG library,
- * but they don't need to be visible to applications using the library.
- * To minimize application namespace pollution, the symbols won't be
- * defined unless JPEG_INTERNALS has been defined.
- */
-
-#ifdef JPEG_INTERNALS
-
-/* Define this if your compiler implements ">>" on signed values as a logical
- * (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift,
- * which is the normal and rational definition.
- */
-#undef RIGHT_SHIFT_IS_UNSIGNED
-
-
-#endif /* JPEG_INTERNALS */
-
-
-/*
- * The remaining options do not affect the JPEG library proper,
- * but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c).
- * Other applications can ignore these.
- */
-
-#ifdef JPEG_CJPEG_DJPEG
-
-/* These defines indicate which image (non-JPEG) file formats are allowed. */
-
-#define BMP_SUPPORTED /* BMP image file format */
-#define GIF_SUPPORTED /* GIF image file format */
-#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
-#undef RLE_SUPPORTED /* Utah RLE image file format */
-#define TARGA_SUPPORTED /* Targa image file format */
-
-/* Define this if you want to name both input and output files on the command
- * line, rather than using stdout and optionally stdin. You MUST do this if
- * your system can't cope with binary I/O to stdin/stdout. See comments at
- * head of cjpeg.c or djpeg.c.
- */
-#undef TWO_FILE_COMMANDLINE
-
-/* By default, we open image files with fopen(...,"rb") or fopen(...,"wb").
- * This is necessary on systems that distinguish text files from binary files,
- * and is harmless on most systems that don't. If you have one of the rare
- * systems that complains about the "b" spec, define this symbol.
- */
-#undef DONT_USE_B_MODE
-
-/* Define this if you want percent-done progress reports from cjpeg/djpeg.
- */
-#undef PROGRESS_REPORT
-
-
-#endif /* JPEG_CJPEG_DJPEG */
diff --git a/src/3rdparty/libjpeg/src/jconfig.h.in b/src/3rdparty/libjpeg/src/jconfig.h.in
new file mode 100644
index 0000000000..28427548e8
--- /dev/null
+++ b/src/3rdparty/libjpeg/src/jconfig.h.in
@@ -0,0 +1,73 @@
+/* Version ID for the JPEG library.
+ * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60".
+ */
+#define JPEG_LIB_VERSION @JPEG_LIB_VERSION@
+
+/* libjpeg-turbo version */
+#define LIBJPEG_TURBO_VERSION @VERSION@
+
+/* libjpeg-turbo version in integer form */
+#define LIBJPEG_TURBO_VERSION_NUMBER @LIBJPEG_TURBO_VERSION_NUMBER@
+
+/* Support arithmetic encoding */
+#cmakedefine C_ARITH_CODING_SUPPORTED
+
+/* Support arithmetic decoding */
+#cmakedefine D_ARITH_CODING_SUPPORTED
+
+/* Support in-memory source/destination managers */
+#cmakedefine MEM_SRCDST_SUPPORTED
+
+/* Use accelerated SIMD routines. */
+#cmakedefine WITH_SIMD
+
+/*
+ * Define BITS_IN_JSAMPLE as either
+ * 8 for 8-bit sample values (the usual setting)
+ * 12 for 12-bit sample values
+ * Only 8 and 12 are legal data precisions for lossy JPEG according to the
+ * JPEG standard, and the IJG code does not support anything else!
+ * We do not support run-time selection of data precision, sorry.
+ */
+
+#define BITS_IN_JSAMPLE @BITS_IN_JSAMPLE@ /* use 8 or 12 */
+
+/* Define to 1 if you have the <locale.h> header file. */
+#cmakedefine HAVE_LOCALE_H
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#cmakedefine HAVE_STDDEF_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#cmakedefine HAVE_STDLIB_H
+
+/* Define if you need to include <sys/types.h> to get size_t. */
+#cmakedefine NEED_SYS_TYPES_H
+
+/* Define if you have BSD-like bzero and bcopy in <strings.h> rather than
+ memset/memcpy in <string.h>. */
+#cmakedefine NEED_BSD_STRINGS
+
+/* Define to 1 if the system has the type `unsigned char'. */
+#cmakedefine HAVE_UNSIGNED_CHAR
+
+/* Define to 1 if the system has the type `unsigned short'. */
+#cmakedefine HAVE_UNSIGNED_SHORT
+
+/* Compiler does not support pointers to undefined structures. */
+#cmakedefine INCOMPLETE_TYPES_BROKEN
+
+/* Define if your (broken) compiler shifts signed values as if they were
+ unsigned. */
+#cmakedefine RIGHT_SHIFT_IS_UNSIGNED
+
+/* Define to 1 if type `char' is unsigned and you are not using gcc. */
+#ifndef __CHAR_UNSIGNED__
+ #cmakedefine __CHAR_UNSIGNED__
+#endif
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
diff --git a/src/3rdparty/libjpeg/src/jconfigint.h b/src/3rdparty/libjpeg/src/jconfigint.h
deleted file mode 100644
index 2131bf52a1..0000000000
--- a/src/3rdparty/libjpeg/src/jconfigint.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#define VERSION "@VERSION@"
-#define BUILD "@BUILD@"
-#define PACKAGE_NAME "@CMAKE_PROJECT_NAME@"
-
-#ifndef INLINE
-#if defined(__GNUC__)
-#define INLINE inline __attribute__((always_inline))
-#elif defined(_MSC_VER)
-#define INLINE __forceinline
-#else
-#define INLINE
-#endif
-#endif
diff --git a/src/3rdparty/libjpeg/src/jconfigint.h.in b/src/3rdparty/libjpeg/src/jconfigint.h.in
new file mode 100644
index 0000000000..55df053676
--- /dev/null
+++ b/src/3rdparty/libjpeg/src/jconfigint.h.in
@@ -0,0 +1,31 @@
+/* libjpeg-turbo build number */
+#define BUILD "@BUILD@"
+
+/* Compiler's inline keyword */
+#undef inline
+
+/* How to obtain function inlining. */
+#define INLINE @INLINE@
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "@CMAKE_PROJECT_NAME@"
+
+/* Version number of package */
+#define VERSION "@VERSION@"
+
+/* The size of `size_t', as computed by sizeof. */
+#define SIZEOF_SIZE_T @SIZE_T@
+
+/* Define if your compiler has __builtin_ctzl() and sizeof(unsigned long) == sizeof(size_t). */
+#cmakedefine HAVE_BUILTIN_CTZL
+
+/* Define to 1 if you have the <intrin.h> header file. */
+#cmakedefine HAVE_INTRIN_H
+
+#if defined(_MSC_VER) && defined(HAVE_INTRIN_H)
+#if (SIZEOF_SIZE_T == 8)
+#define HAVE_BITSCANFORWARD64
+#elif (SIZEOF_SIZE_T == 4)
+#define HAVE_BITSCANFORWARD
+#endif
+#endif
diff --git a/src/3rdparty/libjpeg/src/jcparam.c b/src/3rdparty/libjpeg/src/jcparam.c
index 18b2d487ae..5bc7174dcb 100644
--- a/src/3rdparty/libjpeg/src/jcparam.c
+++ b/src/3rdparty/libjpeg/src/jcparam.c
@@ -5,7 +5,7 @@
* Copyright (C) 1991-1998, Thomas G. Lane.
* Modified 2003-2008 by Guido Vollbeding.
* libjpeg-turbo Modifications:
- * Copyright (C) 2009-2011, D. R. Commander.
+ * Copyright (C) 2009-2011, 2018, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -25,9 +25,9 @@
*/
GLOBAL(void)
-jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl,
- const unsigned int *basic_table,
- int scale_factor, boolean force_baseline)
+jpeg_add_quant_table(j_compress_ptr cinfo, int which_tbl,
+ const unsigned int *basic_table, int scale_factor,
+ boolean force_baseline)
/* Define a quantization table equal to the basic_table times
* a scale factor (given as a percentage).
* If force_baseline is TRUE, the computed quantization table entries
@@ -45,19 +45,19 @@ jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl,
if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS)
ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl);
- qtblptr = & cinfo->quant_tbl_ptrs[which_tbl];
+ qtblptr = &cinfo->quant_tbl_ptrs[which_tbl];
if (*qtblptr == NULL)
- *qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo);
+ *qtblptr = jpeg_alloc_quant_table((j_common_ptr)cinfo);
for (i = 0; i < DCTSIZE2; i++) {
- temp = ((long) basic_table[i] * scale_factor + 50L) / 100L;
+ temp = ((long)basic_table[i] * scale_factor + 50L) / 100L;
/* limit the values to the valid range */
if (temp <= 0L) temp = 1L;
if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */
if (force_baseline && temp > 255L)
temp = 255L; /* limit to baseline range if requested */
- (*qtblptr)->quantval[i] = (UINT16) temp;
+ (*qtblptr)->quantval[i] = (UINT16)temp;
}
/* Initialize sent_table FALSE so table will be written to JPEG file. */
@@ -65,7 +65,8 @@ jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl,
}
-/* These are the sample quantization tables given in JPEG spec section K.1.
+/* These are the sample quantization tables given in Annex K (Clause K.1) of
+ * Recommendation ITU-T T.81 (1992) | ISO/IEC 10918-1:1994.
* The spec says that the values given produce "good" quality, and
* when divided by 2, "very good" quality.
*/
@@ -93,7 +94,7 @@ static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = {
#if JPEG_LIB_VERSION >= 70
GLOBAL(void)
-jpeg_default_qtables (j_compress_ptr cinfo, boolean force_baseline)
+jpeg_default_qtables(j_compress_ptr cinfo, boolean force_baseline)
/* Set or change the 'quality' (quantization) setting, using default tables
* and straight percentage-scaling quality scales.
* This entry point allows different scalings for luminance and chrominance.
@@ -109,8 +110,8 @@ jpeg_default_qtables (j_compress_ptr cinfo, boolean force_baseline)
GLOBAL(void)
-jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor,
- boolean force_baseline)
+jpeg_set_linear_quality(j_compress_ptr cinfo, int scale_factor,
+ boolean force_baseline)
/* Set or change the 'quality' (quantization) setting, using default tables
* and a straight percentage-scaling quality scale. In most cases it's better
* to use jpeg_set_quality (below); this entry point is provided for
@@ -126,7 +127,7 @@ jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor,
GLOBAL(int)
-jpeg_quality_scaling (int quality)
+jpeg_quality_scaling(int quality)
/* Convert a user-specified quality rating to a percentage scaling factor
* for an underlying quantization table, using our recommended scaling curve.
* The input 'quality' factor should be 0 (terrible) to 100 (very good).
@@ -145,14 +146,14 @@ jpeg_quality_scaling (int quality)
if (quality < 50)
quality = 5000 / quality;
else
- quality = 200 - quality*2;
+ quality = 200 - quality * 2;
return quality;
}
GLOBAL(void)
-jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline)
+jpeg_set_quality(j_compress_ptr cinfo, int quality, boolean force_baseline)
/* Set or change the 'quality' (quantization) setting, using default tables.
* This is the standard quality-adjusting entry point for typical user
* interfaces; only those who want detailed control over quantization tables
@@ -178,7 +179,7 @@ jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline)
*/
GLOBAL(void)
-jpeg_set_defaults (j_compress_ptr cinfo)
+jpeg_set_defaults(j_compress_ptr cinfo)
{
int i;
@@ -192,7 +193,7 @@ jpeg_set_defaults (j_compress_ptr cinfo)
*/
if (cinfo->comp_info == NULL)
cinfo->comp_info = (jpeg_component_info *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
MAX_COMPONENTS * sizeof(jpeg_component_info));
/* Initialize everything not dependent on the color space */
@@ -205,7 +206,7 @@ jpeg_set_defaults (j_compress_ptr cinfo)
/* Set up two quantization tables using default quality of 75 */
jpeg_set_quality(cinfo, 75, TRUE);
/* Set up two Huffman tables */
- std_huff_tables((j_common_ptr) cinfo);
+ std_huff_tables((j_common_ptr)cinfo);
/* Initialize default arithmetic coding conditioning */
for (i = 0; i < NUM_ARITH_TBLS; i++) {
@@ -278,7 +279,7 @@ jpeg_set_defaults (j_compress_ptr cinfo)
*/
GLOBAL(void)
-jpeg_default_colorspace (j_compress_ptr cinfo)
+jpeg_default_colorspace(j_compress_ptr cinfo)
{
switch (cinfo->in_color_space) {
case JCS_GRAYSCALE:
@@ -320,12 +321,12 @@ jpeg_default_colorspace (j_compress_ptr cinfo)
*/
GLOBAL(void)
-jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
+jpeg_set_colorspace(j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
{
jpeg_component_info *compptr;
int ci;
-#define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) \
+#define SET_COMP(index, id, hsamp, vsamp, quant, dctbl, actbl) \
(compptr = &cinfo->comp_info[index], \
compptr->component_id = (id), \
compptr->h_samp_factor = (hsamp), \
@@ -352,39 +353,39 @@ jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
cinfo->num_components = 1;
/* JFIF specifies component ID 1 */
- SET_COMP(0, 1, 1,1, 0, 0,0);
+ SET_COMP(0, 1, 1, 1, 0, 0, 0);
break;
case JCS_RGB:
cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */
cinfo->num_components = 3;
- SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0);
- SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0);
- SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0);
+ SET_COMP(0, 0x52 /* 'R' */, 1, 1, 0, 0, 0);
+ SET_COMP(1, 0x47 /* 'G' */, 1, 1, 0, 0, 0);
+ SET_COMP(2, 0x42 /* 'B' */, 1, 1, 0, 0, 0);
break;
case JCS_YCbCr:
cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
cinfo->num_components = 3;
/* JFIF specifies component IDs 1,2,3 */
/* We default to 2x2 subsamples of chrominance */
- SET_COMP(0, 1, 2,2, 0, 0,0);
- SET_COMP(1, 2, 1,1, 1, 1,1);
- SET_COMP(2, 3, 1,1, 1, 1,1);
+ SET_COMP(0, 1, 2, 2, 0, 0, 0);
+ SET_COMP(1, 2, 1, 1, 1, 1, 1);
+ SET_COMP(2, 3, 1, 1, 1, 1, 1);
break;
case JCS_CMYK:
cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */
cinfo->num_components = 4;
- SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0);
- SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0);
- SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0);
- SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0);
+ SET_COMP(0, 0x43 /* 'C' */, 1, 1, 0, 0, 0);
+ SET_COMP(1, 0x4D /* 'M' */, 1, 1, 0, 0, 0);
+ SET_COMP(2, 0x59 /* 'Y' */, 1, 1, 0, 0, 0);
+ SET_COMP(3, 0x4B /* 'K' */, 1, 1, 0, 0, 0);
break;
case JCS_YCCK:
cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */
cinfo->num_components = 4;
- SET_COMP(0, 1, 2,2, 0, 0,0);
- SET_COMP(1, 2, 1,1, 1, 1,1);
- SET_COMP(2, 3, 1,1, 1, 1,1);
- SET_COMP(3, 4, 2,2, 0, 0,0);
+ SET_COMP(0, 1, 2, 2, 0, 0, 0);
+ SET_COMP(1, 2, 1, 1, 1, 1, 1);
+ SET_COMP(2, 3, 1, 1, 1, 1, 1);
+ SET_COMP(3, 4, 2, 2, 0, 0, 0);
break;
case JCS_UNKNOWN:
cinfo->num_components = cinfo->input_components;
@@ -392,7 +393,7 @@ jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
MAX_COMPONENTS);
for (ci = 0; ci < cinfo->num_components; ci++) {
- SET_COMP(ci, ci, 1,1, 0, 0,0);
+ SET_COMP(ci, ci, 1, 1, 0, 0, 0);
}
break;
default:
@@ -404,8 +405,7 @@ jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
#ifdef C_PROGRESSIVE_SUPPORTED
LOCAL(jpeg_scan_info *)
-fill_a_scan (jpeg_scan_info *scanptr, int ci,
- int Ss, int Se, int Ah, int Al)
+fill_a_scan(jpeg_scan_info *scanptr, int ci, int Ss, int Se, int Ah, int Al)
/* Support routine: generate one scan for specified component */
{
scanptr->comps_in_scan = 1;
@@ -419,8 +419,7 @@ fill_a_scan (jpeg_scan_info *scanptr, int ci,
}
LOCAL(jpeg_scan_info *)
-fill_scans (jpeg_scan_info *scanptr, int ncomps,
- int Ss, int Se, int Ah, int Al)
+fill_scans(jpeg_scan_info *scanptr, int ncomps, int Ss, int Se, int Ah, int Al)
/* Support routine: generate one scan for each component */
{
int ci;
@@ -438,7 +437,7 @@ fill_scans (jpeg_scan_info *scanptr, int ncomps,
}
LOCAL(jpeg_scan_info *)
-fill_dc_scans (jpeg_scan_info *scanptr, int ncomps, int Ah, int Al)
+fill_dc_scans(jpeg_scan_info *scanptr, int ncomps, int Ah, int Al)
/* Support routine: generate interleaved DC scan if possible, else N scans */
{
int ci;
@@ -466,7 +465,7 @@ fill_dc_scans (jpeg_scan_info *scanptr, int ncomps, int Ah, int Al)
*/
GLOBAL(void)
-jpeg_simple_progression (j_compress_ptr cinfo)
+jpeg_simple_progression(j_compress_ptr cinfo)
{
int ncomps = cinfo->num_components;
int nscans;
@@ -498,7 +497,7 @@ jpeg_simple_progression (j_compress_ptr cinfo)
if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) {
cinfo->script_space_size = MAX(nscans, 10);
cinfo->script_space = (jpeg_scan_info *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
cinfo->script_space_size * sizeof(jpeg_scan_info));
}
scanptr = cinfo->script_space;
diff --git a/src/3rdparty/libjpeg/src/jcphuff.c b/src/3rdparty/libjpeg/src/jcphuff.c
index 046e2e18d4..024d3af0fb 100644
--- a/src/3rdparty/libjpeg/src/jcphuff.c
+++ b/src/3rdparty/libjpeg/src/jcphuff.c
@@ -4,7 +4,8 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1995-1997, Thomas G. Lane.
* libjpeg-turbo Modifications:
- * Copyright (C) 2015, D. R. Commander.
+ * Copyright (C) 2011, 2015, 2018, D. R. Commander.
+ * Copyright (C) 2016, 2018, Matthieu Darbois.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -18,15 +19,69 @@
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
-#include "jchuff.h" /* Declarations shared with jchuff.c */
+#include "jsimd.h"
+#include "jconfigint.h"
+#include <limits.h>
+
+#ifdef HAVE_INTRIN_H
+#include <intrin.h>
+#ifdef _MSC_VER
+#ifdef HAVE_BITSCANFORWARD64
+#pragma intrinsic(_BitScanForward64)
+#endif
+#ifdef HAVE_BITSCANFORWARD
+#pragma intrinsic(_BitScanForward)
+#endif
+#endif
+#endif
#ifdef C_PROGRESSIVE_SUPPORTED
+/*
+ * NOTE: If USE_CLZ_INTRINSIC is defined, then clz/bsr instructions will be
+ * used for bit counting rather than the lookup table. This will reduce the
+ * memory footprint by 64k, which is important for some mobile applications
+ * that create many isolated instances of libjpeg-turbo (web browsers, for
+ * instance.) This may improve performance on some mobile platforms as well.
+ * This feature is enabled by default only on ARM processors, because some x86
+ * chips have a slow implementation of bsr, and the use of clz/bsr cannot be
+ * shown to have a significant performance impact even on the x86 chips that
+ * have a fast implementation of it. When building for ARMv6, you can
+ * explicitly disable the use of clz/bsr by adding -mthumb to the compiler
+ * flags (this defines __thumb__).
+ */
+
+/* NOTE: Both GCC and Clang define __GNUC__ */
+#if defined __GNUC__ && (defined __arm__ || defined __aarch64__)
+#if !defined __thumb__ || defined __thumb2__
+#define USE_CLZ_INTRINSIC
+#endif
+#endif
+
+#ifdef USE_CLZ_INTRINSIC
+#define JPEG_NBITS_NONZERO(x) (32 - __builtin_clz(x))
+#define JPEG_NBITS(x) (x ? JPEG_NBITS_NONZERO(x) : 0)
+#else
+#include "jpeg_nbits_table.h"
+#define JPEG_NBITS(x) (jpeg_nbits_table[x])
+#define JPEG_NBITS_NONZERO(x) JPEG_NBITS(x)
+#endif
+
+
/* Expanded entropy encoder object for progressive Huffman encoding. */
typedef struct {
struct jpeg_entropy_encoder pub; /* public fields */
+ /* Pointer to routine to prepare data for encode_mcu_AC_first() */
+ void (*AC_first_prepare) (const JCOEF *block,
+ const int *jpeg_natural_order_start, int Sl,
+ int Al, JCOEF *values, size_t *zerobits);
+ /* Pointer to routine to prepare data for encode_mcu_AC_refine() */
+ int (*AC_refine_prepare) (const JCOEF *block,
+ const int *jpeg_natural_order_start, int Sl,
+ int Al, JCOEF *absvalues, size_t *bits);
+
/* Mode flag: TRUE for optimization, FALSE for actual data output */
boolean gather_statistics;
@@ -79,26 +134,60 @@ typedef phuff_entropy_encoder *phuff_entropy_ptr;
#ifdef RIGHT_SHIFT_IS_UNSIGNED
#define ISHIFT_TEMPS int ishift_temp;
-#define IRIGHT_SHIFT(x,shft) \
- ((ishift_temp = (x)) < 0 ? \
- (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \
- (ishift_temp >> (shft)))
+#define IRIGHT_SHIFT(x, shft) \
+ ((ishift_temp = (x)) < 0 ? \
+ (ishift_temp >> (shft)) | ((~0) << (16 - (shft))) : \
+ (ishift_temp >> (shft)))
#else
#define ISHIFT_TEMPS
-#define IRIGHT_SHIFT(x,shft) ((x) >> (shft))
+#define IRIGHT_SHIFT(x, shft) ((x) >> (shft))
#endif
+#define PAD(v, p) ((v + (p) - 1) & (~((p) - 1)))
+
/* Forward declarations */
-METHODDEF(boolean) encode_mcu_DC_first (j_compress_ptr cinfo,
+METHODDEF(boolean) encode_mcu_DC_first(j_compress_ptr cinfo,
+ JBLOCKROW *MCU_data);
+METHODDEF(void) encode_mcu_AC_first_prepare
+ (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al,
+ JCOEF *values, size_t *zerobits);
+METHODDEF(boolean) encode_mcu_AC_first(j_compress_ptr cinfo,
+ JBLOCKROW *MCU_data);
+METHODDEF(boolean) encode_mcu_DC_refine(j_compress_ptr cinfo,
JBLOCKROW *MCU_data);
-METHODDEF(boolean) encode_mcu_AC_first (j_compress_ptr cinfo,
+METHODDEF(int) encode_mcu_AC_refine_prepare
+ (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al,
+ JCOEF *absvalues, size_t *bits);
+METHODDEF(boolean) encode_mcu_AC_refine(j_compress_ptr cinfo,
JBLOCKROW *MCU_data);
-METHODDEF(boolean) encode_mcu_DC_refine (j_compress_ptr cinfo,
- JBLOCKROW *MCU_data);
-METHODDEF(boolean) encode_mcu_AC_refine (j_compress_ptr cinfo,
- JBLOCKROW *MCU_data);
-METHODDEF(void) finish_pass_phuff (j_compress_ptr cinfo);
-METHODDEF(void) finish_pass_gather_phuff (j_compress_ptr cinfo);
+METHODDEF(void) finish_pass_phuff(j_compress_ptr cinfo);
+METHODDEF(void) finish_pass_gather_phuff(j_compress_ptr cinfo);
+
+
+/* Count bit loop zeroes */
+INLINE
+METHODDEF(int)
+count_zeroes(size_t *x)
+{
+ int result;
+#if defined(HAVE_BUILTIN_CTZL)
+ result = __builtin_ctzl(*x);
+ *x >>= result;
+#elif defined(HAVE_BITSCANFORWARD64)
+ _BitScanForward64(&result, *x);
+ *x >>= result;
+#elif defined(HAVE_BITSCANFORWARD)
+ _BitScanForward(&result, *x);
+ *x >>= result;
+#else
+ result = 0;
+ while ((*x & 1) == 0) {
+ ++result;
+ *x >>= 1;
+ }
+#endif
+ return result;
+}
/*
@@ -106,9 +195,9 @@ METHODDEF(void) finish_pass_gather_phuff (j_compress_ptr cinfo);
*/
METHODDEF(void)
-start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics)
+start_pass_phuff(j_compress_ptr cinfo, boolean gather_statistics)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
boolean is_DC_band;
int ci, tbl;
jpeg_component_info *compptr;
@@ -126,15 +215,23 @@ start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics)
entropy->pub.encode_mcu = encode_mcu_DC_first;
else
entropy->pub.encode_mcu = encode_mcu_AC_first;
+ if (jsimd_can_encode_mcu_AC_first_prepare())
+ entropy->AC_first_prepare = jsimd_encode_mcu_AC_first_prepare;
+ else
+ entropy->AC_first_prepare = encode_mcu_AC_first_prepare;
} else {
if (is_DC_band)
entropy->pub.encode_mcu = encode_mcu_DC_refine;
else {
entropy->pub.encode_mcu = encode_mcu_AC_refine;
+ if (jsimd_can_encode_mcu_AC_refine_prepare())
+ entropy->AC_refine_prepare = jsimd_encode_mcu_AC_refine_prepare;
+ else
+ entropy->AC_refine_prepare = encode_mcu_AC_refine_prepare;
/* AC refinement needs a correction bit buffer */
if (entropy->bit_buffer == NULL)
entropy->bit_buffer = (char *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
MAX_CORR_BITS * sizeof(char));
}
}
@@ -167,14 +264,14 @@ start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics)
/* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
if (entropy->count_ptrs[tbl] == NULL)
entropy->count_ptrs[tbl] = (long *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
257 * sizeof(long));
MEMZERO(entropy->count_ptrs[tbl], 257 * sizeof(long));
} else {
/* Compute derived values for Huffman table */
/* We may do this more than once for a table, but it's not expensive */
jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl,
- & entropy->derived_tbls[tbl]);
+ &entropy->derived_tbls[tbl]);
}
}
@@ -198,19 +295,20 @@ start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics)
*/
/* Emit a byte */
-#define emit_byte(entropy,val) \
- { *(entropy)->next_output_byte++ = (JOCTET) (val); \
- if (--(entropy)->free_in_buffer == 0) \
- dump_buffer(entropy); }
+#define emit_byte(entropy, val) { \
+ *(entropy)->next_output_byte++ = (JOCTET)(val); \
+ if (--(entropy)->free_in_buffer == 0) \
+ dump_buffer(entropy); \
+}
LOCAL(void)
-dump_buffer (phuff_entropy_ptr entropy)
+dump_buffer(phuff_entropy_ptr entropy)
/* Empty the output buffer; we do not support suspension in this module. */
{
struct jpeg_destination_mgr *dest = entropy->cinfo->dest;
- if (! (*dest->empty_output_buffer) (entropy->cinfo))
+ if (!(*dest->empty_output_buffer) (entropy->cinfo))
ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND);
/* After a successful buffer dump, must reset buffer pointers */
entropy->next_output_byte = dest->next_output_byte;
@@ -227,11 +325,11 @@ dump_buffer (phuff_entropy_ptr entropy)
*/
LOCAL(void)
-emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size)
+emit_bits(phuff_entropy_ptr entropy, unsigned int code, int size)
/* Emit some bits, unless we are in gather mode */
{
/* This routine is heavily used, so it's worth coding tightly. */
- register size_t put_buffer = (size_t) code;
+ register size_t put_buffer = (size_t)code;
register int put_bits = entropy->put_bits;
/* if size is 0, caller used an invalid Huffman table entry */
@@ -241,7 +339,7 @@ emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size)
if (entropy->gather_statistics)
return; /* do nothing if we're only getting stats */
- put_buffer &= (((size_t) 1)<<size) - 1; /* mask off any extra bits in code */
+ put_buffer &= (((size_t)1) << size) - 1; /* mask off any extra bits in code */
put_bits += size; /* new number of bits in buffer */
@@ -250,7 +348,7 @@ emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size)
put_buffer |= entropy->put_buffer; /* and merge with old buffer contents */
while (put_bits >= 8) {
- int c = (int) ((put_buffer >> 16) & 0xFF);
+ int c = (int)((put_buffer >> 16) & 0xFF);
emit_byte(entropy, c);
if (c == 0xFF) { /* need to stuff a zero byte? */
@@ -266,7 +364,7 @@ emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size)
LOCAL(void)
-flush_bits (phuff_entropy_ptr entropy)
+flush_bits(phuff_entropy_ptr entropy)
{
emit_bits(entropy, 0x7F, 7); /* fill any partial byte with ones */
entropy->put_buffer = 0; /* and reset bit-buffer to empty */
@@ -279,7 +377,7 @@ flush_bits (phuff_entropy_ptr entropy)
*/
LOCAL(void)
-emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol)
+emit_symbol(phuff_entropy_ptr entropy, int tbl_no, int symbol)
{
if (entropy->gather_statistics)
entropy->count_ptrs[tbl_no][symbol]++;
@@ -295,14 +393,14 @@ emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol)
*/
LOCAL(void)
-emit_buffered_bits (phuff_entropy_ptr entropy, char *bufstart,
- unsigned int nbits)
+emit_buffered_bits(phuff_entropy_ptr entropy, char *bufstart,
+ unsigned int nbits)
{
if (entropy->gather_statistics)
return; /* no real work */
while (nbits > 0) {
- emit_bits(entropy, (unsigned int) (*bufstart), 1);
+ emit_bits(entropy, (unsigned int)(*bufstart), 1);
bufstart++;
nbits--;
}
@@ -314,15 +412,13 @@ emit_buffered_bits (phuff_entropy_ptr entropy, char *bufstart,
*/
LOCAL(void)
-emit_eobrun (phuff_entropy_ptr entropy)
+emit_eobrun(phuff_entropy_ptr entropy)
{
register int temp, nbits;
if (entropy->EOBRUN > 0) { /* if there is any pending EOBRUN */
temp = entropy->EOBRUN;
- nbits = 0;
- while ((temp >>= 1))
- nbits++;
+ nbits = JPEG_NBITS_NONZERO(temp) - 1;
/* safety check: shouldn't happen given limited correction-bit buffer */
if (nbits > 14)
ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE);
@@ -345,13 +441,13 @@ emit_eobrun (phuff_entropy_ptr entropy)
*/
LOCAL(void)
-emit_restart (phuff_entropy_ptr entropy, int restart_num)
+emit_restart(phuff_entropy_ptr entropy, int restart_num)
{
int ci;
emit_eobrun(entropy);
- if (! entropy->gather_statistics) {
+ if (!entropy->gather_statistics) {
flush_bits(entropy);
emit_byte(entropy, 0xFF);
emit_byte(entropy, JPEG_RST0 + restart_num);
@@ -375,10 +471,10 @@ emit_restart (phuff_entropy_ptr entropy, int restart_num)
*/
METHODDEF(boolean)
-encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+encode_mcu_DC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
- register int temp, temp2;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
+ register int temp, temp2, temp3;
register int nbits;
int blkn, ci;
int Al = cinfo->Al;
@@ -403,31 +499,31 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
/* Compute the DC value after the required point transform by Al.
* This is simply an arithmetic right shift.
*/
- temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al);
+ temp2 = IRIGHT_SHIFT((int)((*block)[0]), Al);
/* DC differences are figured on the point-transformed values. */
temp = temp2 - entropy->last_dc_val[ci];
entropy->last_dc_val[ci] = temp2;
/* Encode the DC coefficient difference per section G.1.2.1 */
- temp2 = temp;
- if (temp < 0) {
- temp = -temp; /* temp is abs value of input */
- /* For a negative input, want temp2 = bitwise complement of abs(input) */
- /* This code assumes we are on a two's complement machine */
- temp2--;
- }
+
+ /* This is a well-known technique for obtaining the absolute value without
+ * a branch. It is derived from an assembly language technique presented
+ * in "How to Optimize for the Pentium Processors", Copyright (c) 1996,
+ * 1997 by Agner Fog.
+ */
+ temp3 = temp >> (CHAR_BIT * sizeof(int) - 1);
+ temp ^= temp3;
+ temp -= temp3; /* temp is abs value of input */
+ /* For a negative input, want temp2 = bitwise complement of abs(input) */
+ temp2 = temp ^ temp3;
/* Find the number of bits needed for the magnitude of the coefficient */
- nbits = 0;
- while (temp) {
- nbits++;
- temp >>= 1;
- }
+ nbits = JPEG_NBITS(temp);
/* Check for out-of-range coefficient values.
* Since we're encoding a difference, the range limit is twice as much.
*/
- if (nbits > MAX_COEF_BITS+1)
+ if (nbits > MAX_COEF_BITS + 1)
ERREXIT(cinfo, JERR_BAD_DCT_COEF);
/* Count/emit the Huffman-coded symbol for the number of bits */
@@ -436,7 +532,7 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
/* Emit that number of bits of the value, if positive, */
/* or the complement of its magnitude, if negative. */
if (nbits) /* emit_bits rejects calls with size 0 */
- emit_bits(entropy, (unsigned int) temp2, nbits);
+ emit_bits(entropy, (unsigned int)temp2, nbits);
}
cinfo->dest->next_output_byte = entropy->next_output_byte;
@@ -457,20 +553,115 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
/*
+ * Data preparation for encode_mcu_AC_first().
+ */
+
+#define COMPUTE_ABSVALUES_AC_FIRST(Sl) { \
+ for (k = 0; k < Sl; k++) { \
+ temp = block[jpeg_natural_order_start[k]]; \
+ if (temp == 0) \
+ continue; \
+ /* We must apply the point transform by Al. For AC coefficients this \
+ * is an integer division with rounding towards 0. To do this portably \
+ * in C, we shift after obtaining the absolute value; so the code is \
+ * interwoven with finding the abs value (temp) and output bits (temp2). \
+ */ \
+ temp2 = temp >> (CHAR_BIT * sizeof(int) - 1); \
+ temp ^= temp2; \
+ temp -= temp2; /* temp is abs value of input */ \
+ temp >>= Al; /* apply the point transform */ \
+ /* Watch out for case that nonzero coef is zero after point transform */ \
+ if (temp == 0) \
+ continue; \
+ /* For a negative coef, want temp2 = bitwise complement of abs(coef) */ \
+ temp2 ^= temp; \
+ values[k] = temp; \
+ values[k + DCTSIZE2] = temp2; \
+ zerobits |= ((size_t)1U) << k; \
+ } \
+}
+
+METHODDEF(void)
+encode_mcu_AC_first_prepare(const JCOEF *block,
+ const int *jpeg_natural_order_start, int Sl,
+ int Al, JCOEF *values, size_t *bits)
+{
+ register int k, temp, temp2;
+ size_t zerobits = 0U;
+ int Sl0 = Sl;
+
+#if SIZEOF_SIZE_T == 4
+ if (Sl0 > 32)
+ Sl0 = 32;
+#endif
+
+ COMPUTE_ABSVALUES_AC_FIRST(Sl0);
+
+ bits[0] = zerobits;
+#if SIZEOF_SIZE_T == 4
+ zerobits = 0U;
+
+ if (Sl > 32) {
+ Sl -= 32;
+ jpeg_natural_order_start += 32;
+ values += 32;
+
+ COMPUTE_ABSVALUES_AC_FIRST(Sl);
+ }
+ bits[1] = zerobits;
+#endif
+}
+
+/*
* MCU encoding for AC initial scan (either spectral selection,
* or first pass of successive approximation).
*/
+#define ENCODE_COEFS_AC_FIRST(label) { \
+ while (zerobits) { \
+ r = count_zeroes(&zerobits); \
+ cvalue += r; \
+label \
+ temp = cvalue[0]; \
+ temp2 = cvalue[DCTSIZE2]; \
+ \
+ /* if run length > 15, must emit special run-length-16 codes (0xF0) */ \
+ while (r > 15) { \
+ emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); \
+ r -= 16; \
+ } \
+ \
+ /* Find the number of bits needed for the magnitude of the coefficient */ \
+ nbits = JPEG_NBITS_NONZERO(temp); /* there must be at least one 1 bit */ \
+ /* Check for out-of-range coefficient values */ \
+ if (nbits > MAX_COEF_BITS) \
+ ERREXIT(cinfo, JERR_BAD_DCT_COEF); \
+ \
+ /* Count/emit Huffman symbol for run length / number of bits */ \
+ emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits); \
+ \
+ /* Emit that number of bits of the value, if positive, */ \
+ /* or the complement of its magnitude, if negative. */ \
+ emit_bits(entropy, (unsigned int)temp2, nbits); \
+ \
+ cvalue++; \
+ zerobits >>= 1; \
+ } \
+}
+
METHODDEF(boolean)
-encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+encode_mcu_AC_first(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
register int temp, temp2;
- register int nbits;
- register int r, k;
- int Se = cinfo->Se;
+ register int nbits, r;
+ int Sl = cinfo->Se - cinfo->Ss + 1;
int Al = cinfo->Al;
- JBLOCKROW block;
+ JCOEF values_unaligned[2 * DCTSIZE2 + 15];
+ JCOEF *values;
+ const JCOEF *cvalue;
+ size_t zerobits;
+ size_t bits[8 / SIZEOF_SIZE_T];
entropy->next_output_byte = cinfo->dest->next_output_byte;
entropy->free_in_buffer = cinfo->dest->free_in_buffer;
@@ -480,66 +671,48 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
if (entropy->restarts_to_go == 0)
emit_restart(entropy, entropy->next_restart_num);
- /* Encode the MCU data block */
- block = MCU_data[0];
+#ifdef WITH_SIMD
+ cvalue = values = (JCOEF *)PAD((size_t)values_unaligned, 16);
+#else
+ /* Not using SIMD, so alignment is not needed */
+ cvalue = values = values_unaligned;
+#endif
- /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */
+ /* Prepare data */
+ entropy->AC_first_prepare(MCU_data[0][0], jpeg_natural_order + cinfo->Ss,
+ Sl, Al, values, bits);
- r = 0; /* r = run length of zeros */
-
- for (k = cinfo->Ss; k <= Se; k++) {
- if ((temp = (*block)[jpeg_natural_order[k]]) == 0) {
- r++;
- continue;
- }
- /* We must apply the point transform by Al. For AC coefficients this
- * is an integer division with rounding towards 0. To do this portably
- * in C, we shift after obtaining the absolute value; so the code is
- * interwoven with finding the abs value (temp) and output bits (temp2).
- */
- if (temp < 0) {
- temp = -temp; /* temp is abs value of input */
- temp >>= Al; /* apply the point transform */
- /* For a negative coef, want temp2 = bitwise complement of abs(coef) */
- temp2 = ~temp;
- } else {
- temp >>= Al; /* apply the point transform */
- temp2 = temp;
- }
- /* Watch out for case that nonzero coef is zero after point transform */
- if (temp == 0) {
- r++;
- continue;
- }
+ zerobits = bits[0];
+#if SIZEOF_SIZE_T == 4
+ zerobits |= bits[1];
+#endif
- /* Emit any pending EOBRUN */
- if (entropy->EOBRUN > 0)
- emit_eobrun(entropy);
- /* if run length > 15, must emit special run-length-16 codes (0xF0) */
- while (r > 15) {
- emit_symbol(entropy, entropy->ac_tbl_no, 0xF0);
- r -= 16;
- }
+ /* Emit any pending EOBRUN */
+ if (zerobits && (entropy->EOBRUN > 0))
+ emit_eobrun(entropy);
- /* Find the number of bits needed for the magnitude of the coefficient */
- nbits = 1; /* there must be at least one 1 bit */
- while ((temp >>= 1))
- nbits++;
- /* Check for out-of-range coefficient values */
- if (nbits > MAX_COEF_BITS)
- ERREXIT(cinfo, JERR_BAD_DCT_COEF);
+#if SIZEOF_SIZE_T == 4
+ zerobits = bits[0];
+#endif
- /* Count/emit Huffman symbol for run length / number of bits */
- emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits);
+ /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */
- /* Emit that number of bits of the value, if positive, */
- /* or the complement of its magnitude, if negative. */
- emit_bits(entropy, (unsigned int) temp2, nbits);
+ ENCODE_COEFS_AC_FIRST((void)0;);
- r = 0; /* reset zero run length */
+#if SIZEOF_SIZE_T == 4
+ zerobits = bits[1];
+ if (zerobits) {
+ int diff = ((values + DCTSIZE2 / 2) - cvalue);
+ r = count_zeroes(&zerobits);
+ r += diff;
+ cvalue += r;
+ goto first_iter_ac_first;
}
- if (r > 0) { /* If there are trailing zeroes, */
+ ENCODE_COEFS_AC_FIRST(first_iter_ac_first:);
+#endif
+
+ if (cvalue < (values + Sl)) { /* If there are trailing zeroes, */
entropy->EOBRUN++; /* count an EOB */
if (entropy->EOBRUN == 0x7FFF)
emit_eobrun(entropy); /* force it out to avoid overflow */
@@ -569,9 +742,9 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
*/
METHODDEF(boolean)
-encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+encode_mcu_DC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
register int temp;
int blkn;
int Al = cinfo->Al;
@@ -591,7 +764,7 @@ encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
/* We simply emit the Al'th bit of the DC coefficient value. */
temp = (*block)[0];
- emit_bits(entropy, (unsigned int) (temp >> Al), 1);
+ emit_bits(entropy, (unsigned int)(temp >> Al), 1);
}
cinfo->dest->next_output_byte = entropy->next_output_byte;
@@ -612,22 +785,148 @@ encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
/*
+ * Data preparation for encode_mcu_AC_refine().
+ */
+
+#define COMPUTE_ABSVALUES_AC_REFINE(Sl, koffset) { \
+ /* It is convenient to make a pre-pass to determine the transformed \
+ * coefficients' absolute values and the EOB position. \
+ */ \
+ for (k = 0; k < Sl; k++) { \
+ temp = block[jpeg_natural_order_start[k]]; \
+ /* We must apply the point transform by Al. For AC coefficients this \
+ * is an integer division with rounding towards 0. To do this portably \
+ * in C, we shift after obtaining the absolute value. \
+ */ \
+ temp2 = temp >> (CHAR_BIT * sizeof(int) - 1); \
+ temp ^= temp2; \
+ temp -= temp2; /* temp is abs value of input */ \
+ temp >>= Al; /* apply the point transform */ \
+ if (temp != 0) { \
+ zerobits |= ((size_t)1U) << k; \
+ signbits |= ((size_t)(temp2 + 1)) << k; \
+ } \
+ absvalues[k] = (JCOEF)temp; /* save abs value for main pass */ \
+ if (temp == 1) \
+ EOB = k + koffset; /* EOB = index of last newly-nonzero coef */ \
+ } \
+}
+
+METHODDEF(int)
+encode_mcu_AC_refine_prepare(const JCOEF *block,
+ const int *jpeg_natural_order_start, int Sl,
+ int Al, JCOEF *absvalues, size_t *bits)
+{
+ register int k, temp, temp2;
+ int EOB = 0;
+ size_t zerobits = 0U, signbits = 0U;
+ int Sl0 = Sl;
+
+#if SIZEOF_SIZE_T == 4
+ if (Sl0 > 32)
+ Sl0 = 32;
+#endif
+
+ COMPUTE_ABSVALUES_AC_REFINE(Sl0, 0);
+
+ bits[0] = zerobits;
+#if SIZEOF_SIZE_T == 8
+ bits[1] = signbits;
+#else
+ bits[2] = signbits;
+
+ zerobits = 0U;
+ signbits = 0U;
+
+ if (Sl > 32) {
+ Sl -= 32;
+ jpeg_natural_order_start += 32;
+ absvalues += 32;
+
+ COMPUTE_ABSVALUES_AC_REFINE(Sl, 32);
+ }
+
+ bits[1] = zerobits;
+ bits[3] = signbits;
+#endif
+
+ return EOB;
+}
+
+
+/*
* MCU encoding for AC successive approximation refinement scan.
*/
+#define ENCODE_COEFS_AC_REFINE(label) { \
+ while (zerobits) { \
+ int idx = count_zeroes(&zerobits); \
+ r += idx; \
+ cabsvalue += idx; \
+ signbits >>= idx; \
+label \
+ /* Emit any required ZRLs, but not if they can be folded into EOB */ \
+ while (r > 15 && (cabsvalue <= EOBPTR)) { \
+ /* emit any pending EOBRUN and the BE correction bits */ \
+ emit_eobrun(entropy); \
+ /* Emit ZRL */ \
+ emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); \
+ r -= 16; \
+ /* Emit buffered correction bits that must be associated with ZRL */ \
+ emit_buffered_bits(entropy, BR_buffer, BR); \
+ BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ \
+ BR = 0; \
+ } \
+ \
+ temp = *cabsvalue++; \
+ \
+ /* If the coef was previously nonzero, it only needs a correction bit. \
+ * NOTE: a straight translation of the spec's figure G.7 would suggest \
+ * that we also need to test r > 15. But if r > 15, we can only get here \
+ * if k > EOB, which implies that this coefficient is not 1. \
+ */ \
+ if (temp > 1) { \
+ /* The correction bit is the next bit of the absolute value. */ \
+ BR_buffer[BR++] = (char)(temp & 1); \
+ signbits >>= 1; \
+ zerobits >>= 1; \
+ continue; \
+ } \
+ \
+ /* Emit any pending EOBRUN and the BE correction bits */ \
+ emit_eobrun(entropy); \
+ \
+ /* Count/emit Huffman symbol for run length / number of bits */ \
+ emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1); \
+ \
+ /* Emit output bit for newly-nonzero coef */ \
+ temp = signbits & 1; /* ((*block)[jpeg_natural_order_start[k]] < 0) ? 0 : 1 */ \
+ emit_bits(entropy, (unsigned int)temp, 1); \
+ \
+ /* Emit buffered correction bits that must be associated with this code */ \
+ emit_buffered_bits(entropy, BR_buffer, BR); \
+ BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ \
+ BR = 0; \
+ r = 0; /* reset zero run length */ \
+ signbits >>= 1; \
+ zerobits >>= 1; \
+ } \
+}
+
METHODDEF(boolean)
-encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+encode_mcu_AC_refine(j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
- register int temp;
- register int r, k;
- int EOB;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
+ register int temp, r;
char *BR_buffer;
unsigned int BR;
- int Se = cinfo->Se;
+ int Sl = cinfo->Se - cinfo->Ss + 1;
int Al = cinfo->Al;
- JBLOCKROW block;
- int absvalues[DCTSIZE2];
+ JCOEF absvalues_unaligned[DCTSIZE2 + 15];
+ JCOEF *absvalues;
+ const JCOEF *cabsvalue, *EOBPTR;
+ size_t zerobits, signbits;
+ size_t bits[16 / SIZEOF_SIZE_T];
entropy->next_output_byte = cinfo->dest->next_output_byte;
entropy->free_in_buffer = cinfo->dest->free_in_buffer;
@@ -637,26 +936,17 @@ encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
if (entropy->restarts_to_go == 0)
emit_restart(entropy, entropy->next_restart_num);
- /* Encode the MCU data block */
- block = MCU_data[0];
+#ifdef WITH_SIMD
+ cabsvalue = absvalues = (JCOEF *)PAD((size_t)absvalues_unaligned, 16);
+#else
+ /* Not using SIMD, so alignment is not needed */
+ cabsvalue = absvalues = absvalues_unaligned;
+#endif
- /* It is convenient to make a pre-pass to determine the transformed
- * coefficients' absolute values and the EOB position.
- */
- EOB = 0;
- for (k = cinfo->Ss; k <= Se; k++) {
- temp = (*block)[jpeg_natural_order[k]];
- /* We must apply the point transform by Al. For AC coefficients this
- * is an integer division with rounding towards 0. To do this portably
- * in C, we shift after obtaining the absolute value.
- */
- if (temp < 0)
- temp = -temp; /* temp is abs value of input */
- temp >>= Al; /* apply the point transform */
- absvalues[k] = temp; /* save abs value for main pass */
- if (temp == 1)
- EOB = k; /* EOB = index of last newly-nonzero coef */
- }
+ /* Prepare data */
+ EOBPTR = absvalues +
+ entropy->AC_refine_prepare(MCU_data[0][0], jpeg_natural_order + cinfo->Ss,
+ Sl, Al, absvalues, bits);
/* Encode the AC coefficients per section G.1.2.3, fig. G.7 */
@@ -664,52 +954,32 @@ encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
BR = 0; /* BR = count of buffered bits added now */
BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */
- for (k = cinfo->Ss; k <= Se; k++) {
- if ((temp = absvalues[k]) == 0) {
- r++;
- continue;
- }
-
- /* Emit any required ZRLs, but not if they can be folded into EOB */
- while (r > 15 && k <= EOB) {
- /* emit any pending EOBRUN and the BE correction bits */
- emit_eobrun(entropy);
- /* Emit ZRL */
- emit_symbol(entropy, entropy->ac_tbl_no, 0xF0);
- r -= 16;
- /* Emit buffered correction bits that must be associated with ZRL */
- emit_buffered_bits(entropy, BR_buffer, BR);
- BR_buffer = entropy->bit_buffer; /* BE bits are gone now */
- BR = 0;
- }
-
- /* If the coef was previously nonzero, it only needs a correction bit.
- * NOTE: a straight translation of the spec's figure G.7 would suggest
- * that we also need to test r > 15. But if r > 15, we can only get here
- * if k > EOB, which implies that this coefficient is not 1.
- */
- if (temp > 1) {
- /* The correction bit is the next bit of the absolute value. */
- BR_buffer[BR++] = (char) (temp & 1);
- continue;
- }
-
- /* Emit any pending EOBRUN and the BE correction bits */
- emit_eobrun(entropy);
-
- /* Count/emit Huffman symbol for run length / number of bits */
- emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1);
+ zerobits = bits[0];
+#if SIZEOF_SIZE_T == 8
+ signbits = bits[1];
+#else
+ signbits = bits[2];
+#endif
+ ENCODE_COEFS_AC_REFINE((void)0;);
+
+#if SIZEOF_SIZE_T == 4
+ zerobits = bits[1];
+ signbits = bits[3];
+
+ if (zerobits) {
+ int diff = ((absvalues + DCTSIZE2 / 2) - cabsvalue);
+ int idx = count_zeroes(&zerobits);
+ signbits >>= idx;
+ idx += diff;
+ r += idx;
+ cabsvalue += idx;
+ goto first_iter_ac_refine;
+ }
- /* Emit output bit for newly-nonzero coef */
- temp = ((*block)[jpeg_natural_order[k]] < 0) ? 0 : 1;
- emit_bits(entropy, (unsigned int) temp, 1);
+ ENCODE_COEFS_AC_REFINE(first_iter_ac_refine:);
+#endif
- /* Emit buffered correction bits that must be associated with this code */
- emit_buffered_bits(entropy, BR_buffer, BR);
- BR_buffer = entropy->bit_buffer; /* BE bits are gone now */
- BR = 0;
- r = 0; /* reset zero run length */
- }
+ r |= (int)((absvalues + Sl) - cabsvalue);
if (r > 0 || BR > 0) { /* If there are trailing zeroes, */
entropy->EOBRUN++; /* count an EOB */
@@ -718,7 +988,8 @@ encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
* 1. overflow of the EOB counter;
* 2. overflow of the correction bit buffer during the next MCU.
*/
- if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1))
+ if (entropy->EOBRUN == 0x7FFF ||
+ entropy->BE > (MAX_CORR_BITS - DCTSIZE2 + 1))
emit_eobrun(entropy);
}
@@ -744,9 +1015,9 @@ encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
*/
METHODDEF(void)
-finish_pass_phuff (j_compress_ptr cinfo)
+finish_pass_phuff(j_compress_ptr cinfo)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
entropy->next_output_byte = cinfo->dest->next_output_byte;
entropy->free_in_buffer = cinfo->dest->free_in_buffer;
@@ -765,9 +1036,9 @@ finish_pass_phuff (j_compress_ptr cinfo)
*/
METHODDEF(void)
-finish_pass_gather_phuff (j_compress_ptr cinfo)
+finish_pass_gather_phuff(j_compress_ptr cinfo)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
boolean is_DC_band;
int ci, tbl;
jpeg_component_info *compptr;
@@ -793,13 +1064,13 @@ finish_pass_gather_phuff (j_compress_ptr cinfo)
} else {
tbl = compptr->ac_tbl_no;
}
- if (! did[tbl]) {
+ if (!did[tbl]) {
if (is_DC_band)
- htblptr = & cinfo->dc_huff_tbl_ptrs[tbl];
+ htblptr = &cinfo->dc_huff_tbl_ptrs[tbl];
else
- htblptr = & cinfo->ac_huff_tbl_ptrs[tbl];
+ htblptr = &cinfo->ac_huff_tbl_ptrs[tbl];
if (*htblptr == NULL)
- *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr)cinfo);
jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]);
did[tbl] = TRUE;
}
@@ -812,15 +1083,15 @@ finish_pass_gather_phuff (j_compress_ptr cinfo)
*/
GLOBAL(void)
-jinit_phuff_encoder (j_compress_ptr cinfo)
+jinit_phuff_encoder(j_compress_ptr cinfo)
{
phuff_entropy_ptr entropy;
int i;
entropy = (phuff_entropy_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(phuff_entropy_encoder));
- cinfo->entropy = (struct jpeg_entropy_encoder *) entropy;
+ cinfo->entropy = (struct jpeg_entropy_encoder *)entropy;
entropy->pub.start_pass = start_pass_phuff;
/* Mark tables unallocated */
diff --git a/src/3rdparty/libjpeg/src/jcprepct.c b/src/3rdparty/libjpeg/src/jcprepct.c
index e72ebd87d2..d59713ae68 100644
--- a/src/3rdparty/libjpeg/src/jcprepct.c
+++ b/src/3rdparty/libjpeg/src/jcprepct.c
@@ -78,9 +78,9 @@ typedef my_prep_controller *my_prep_ptr;
*/
METHODDEF(void)
-start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+start_pass_prep(j_compress_ptr cinfo, J_BUF_MODE pass_mode)
{
- my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
+ my_prep_ptr prep = (my_prep_ptr)cinfo->prep;
if (pass_mode != JBUF_PASS_THRU)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
@@ -106,14 +106,14 @@ start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
*/
LOCAL(void)
-expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols,
- int input_rows, int output_rows)
+expand_bottom_edge(JSAMPARRAY image_data, JDIMENSION num_cols, int input_rows,
+ int output_rows)
{
register int row;
for (row = input_rows; row < output_rows; row++) {
- jcopy_sample_rows(image_data, input_rows-1, image_data, row,
- 1, num_cols);
+ jcopy_sample_rows(image_data, input_rows - 1, image_data, row, 1,
+ num_cols);
}
}
@@ -128,13 +128,12 @@ expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols,
*/
METHODDEF(void)
-pre_process_data (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
- JDIMENSION in_rows_avail,
- JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
- JDIMENSION out_row_groups_avail)
+pre_process_data(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail,
+ JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
+ JDIMENSION out_row_groups_avail)
{
- my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
+ my_prep_ptr prep = (my_prep_ptr)cinfo->prep;
int numrows, ci;
JDIMENSION inrows;
jpeg_component_info *compptr;
@@ -144,10 +143,10 @@ pre_process_data (j_compress_ptr cinfo,
/* Do color conversion to fill the conversion buffer. */
inrows = in_rows_avail - *in_row_ctr;
numrows = cinfo->max_v_samp_factor - prep->next_buf_row;
- numrows = (int) MIN((JDIMENSION) numrows, inrows);
+ numrows = (int)MIN((JDIMENSION)numrows, inrows);
(*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
prep->color_buf,
- (JDIMENSION) prep->next_buf_row,
+ (JDIMENSION)prep->next_buf_row,
numrows);
*in_row_ctr += numrows;
prep->next_buf_row += numrows;
@@ -164,7 +163,7 @@ pre_process_data (j_compress_ptr cinfo,
/* If we've filled the conversion buffer, empty it. */
if (prep->next_buf_row == cinfo->max_v_samp_factor) {
(*cinfo->downsample->downsample) (cinfo,
- prep->color_buf, (JDIMENSION) 0,
+ prep->color_buf, (JDIMENSION)0,
output_buf, *out_row_group_ctr);
prep->next_buf_row = 0;
(*out_row_group_ctr)++;
@@ -172,14 +171,12 @@ pre_process_data (j_compress_ptr cinfo,
/* If at bottom of image, pad the output to a full iMCU height.
* Note we assume the caller is providing a one-iMCU-height output buffer!
*/
- if (prep->rows_to_go == 0 &&
- *out_row_group_ctr < out_row_groups_avail) {
+ if (prep->rows_to_go == 0 && *out_row_group_ctr < out_row_groups_avail) {
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
- expand_bottom_edge(output_buf[ci],
- compptr->width_in_blocks * DCTSIZE,
- (int) (*out_row_group_ctr * compptr->v_samp_factor),
- (int) (out_row_groups_avail * compptr->v_samp_factor));
+ expand_bottom_edge(output_buf[ci], compptr->width_in_blocks * DCTSIZE,
+ (int)(*out_row_group_ctr * compptr->v_samp_factor),
+ (int)(out_row_groups_avail * compptr->v_samp_factor));
}
*out_row_group_ctr = out_row_groups_avail;
break; /* can exit outer loop without test */
@@ -195,13 +192,12 @@ pre_process_data (j_compress_ptr cinfo,
*/
METHODDEF(void)
-pre_process_context (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
- JDIMENSION in_rows_avail,
- JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
- JDIMENSION out_row_groups_avail)
+pre_process_context(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail,
+ JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
+ JDIMENSION out_row_groups_avail)
{
- my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
+ my_prep_ptr prep = (my_prep_ptr)cinfo->prep;
int numrows, ci;
int buf_height = cinfo->max_v_samp_factor * 3;
JDIMENSION inrows;
@@ -211,19 +207,18 @@ pre_process_context (j_compress_ptr cinfo,
/* Do color conversion to fill the conversion buffer. */
inrows = in_rows_avail - *in_row_ctr;
numrows = prep->next_buf_stop - prep->next_buf_row;
- numrows = (int) MIN((JDIMENSION) numrows, inrows);
+ numrows = (int)MIN((JDIMENSION)numrows, inrows);
(*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
prep->color_buf,
- (JDIMENSION) prep->next_buf_row,
+ (JDIMENSION)prep->next_buf_row,
numrows);
/* Pad at top of image, if first time through */
if (prep->rows_to_go == cinfo->image_height) {
for (ci = 0; ci < cinfo->num_components; ci++) {
int row;
for (row = 1; row <= cinfo->max_v_samp_factor; row++) {
- jcopy_sample_rows(prep->color_buf[ci], 0,
- prep->color_buf[ci], -row,
- 1, cinfo->image_width);
+ jcopy_sample_rows(prep->color_buf[ci], 0, prep->color_buf[ci],
+ -row, 1, cinfo->image_width);
}
}
}
@@ -245,9 +240,8 @@ pre_process_context (j_compress_ptr cinfo,
}
/* If we've gotten enough data, downsample a row group. */
if (prep->next_buf_row == prep->next_buf_stop) {
- (*cinfo->downsample->downsample) (cinfo,
- prep->color_buf,
- (JDIMENSION) prep->this_row_group,
+ (*cinfo->downsample->downsample) (cinfo, prep->color_buf,
+ (JDIMENSION)prep->this_row_group,
output_buf, *out_row_group_ctr);
(*out_row_group_ctr)++;
/* Advance pointers with wraparound as necessary. */
@@ -267,9 +261,9 @@ pre_process_context (j_compress_ptr cinfo,
*/
LOCAL(void)
-create_context_buffer (j_compress_ptr cinfo)
+create_context_buffer(j_compress_ptr cinfo)
{
- my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
+ my_prep_ptr prep = (my_prep_ptr)cinfo->prep;
int rgroup_height = cinfo->max_v_samp_factor;
int ci, i;
jpeg_component_info *compptr;
@@ -279,7 +273,7 @@ create_context_buffer (j_compress_ptr cinfo)
* we need five row groups' worth of pointers for each component.
*/
fake_buffer = (JSAMPARRAY)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
(cinfo->num_components * 5 * rgroup_height) *
sizeof(JSAMPROW));
@@ -290,10 +284,10 @@ create_context_buffer (j_compress_ptr cinfo)
* horizontally within the buffer, if it so chooses.
*/
true_buffer = (*cinfo->mem->alloc_sarray)
- ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *
- cinfo->max_h_samp_factor) / compptr->h_samp_factor),
- (JDIMENSION) (3 * rgroup_height));
+ ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (JDIMENSION)(((long)compptr->width_in_blocks * DCTSIZE *
+ cinfo->max_h_samp_factor) / compptr->h_samp_factor),
+ (JDIMENSION)(3 * rgroup_height));
/* Copy true buffer row pointers into the middle of the fake row array */
MEMCOPY(fake_buffer + rgroup_height, true_buffer,
3 * rgroup_height * sizeof(JSAMPROW));
@@ -315,7 +309,7 @@ create_context_buffer (j_compress_ptr cinfo)
*/
GLOBAL(void)
-jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer)
+jinit_c_prep_controller(j_compress_ptr cinfo, boolean need_full_buffer)
{
my_prep_ptr prep;
int ci;
@@ -325,9 +319,9 @@ jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
prep = (my_prep_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_prep_controller));
- cinfo->prep = (struct jpeg_c_prep_controller *) prep;
+ cinfo->prep = (struct jpeg_c_prep_controller *)prep;
prep->pub.start_pass = start_pass_prep;
/* Allocate the color conversion buffer.
@@ -348,10 +342,10 @@ jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer)
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
prep->color_buf[ci] = (*cinfo->mem->alloc_sarray)
- ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *
- cinfo->max_h_samp_factor) / compptr->h_samp_factor),
- (JDIMENSION) cinfo->max_v_samp_factor);
+ ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (JDIMENSION)(((long)compptr->width_in_blocks * DCTSIZE *
+ cinfo->max_h_samp_factor) / compptr->h_samp_factor),
+ (JDIMENSION)cinfo->max_v_samp_factor);
}
}
}
diff --git a/src/3rdparty/libjpeg/src/jcsample.c b/src/3rdparty/libjpeg/src/jcsample.c
index c4b4991487..bd27b84e06 100644
--- a/src/3rdparty/libjpeg/src/jcsample.c
+++ b/src/3rdparty/libjpeg/src/jcsample.c
@@ -79,7 +79,7 @@ typedef my_downsampler *my_downsample_ptr;
*/
METHODDEF(void)
-start_pass_downsample (j_compress_ptr cinfo)
+start_pass_downsample(j_compress_ptr cinfo)
{
/* no work for now */
}
@@ -91,14 +91,14 @@ start_pass_downsample (j_compress_ptr cinfo)
*/
LOCAL(void)
-expand_right_edge (JSAMPARRAY image_data, int num_rows,
- JDIMENSION input_cols, JDIMENSION output_cols)
+expand_right_edge(JSAMPARRAY image_data, int num_rows, JDIMENSION input_cols,
+ JDIMENSION output_cols)
{
register JSAMPROW ptr;
register JSAMPLE pixval;
register int count;
int row;
- int numcols = (int) (output_cols - input_cols);
+ int numcols = (int)(output_cols - input_cols);
if (numcols > 0) {
for (row = 0; row < num_rows; row++) {
@@ -118,11 +118,11 @@ expand_right_edge (JSAMPARRAY image_data, int num_rows,
*/
METHODDEF(void)
-sep_downsample (j_compress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION in_row_index,
- JSAMPIMAGE output_buf, JDIMENSION out_row_group_index)
+sep_downsample(j_compress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_index, JSAMPIMAGE output_buf,
+ JDIMENSION out_row_group_index)
{
- my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample;
+ my_downsample_ptr downsample = (my_downsample_ptr)cinfo->downsample;
int ci;
jpeg_component_info *compptr;
JSAMPARRAY in_ptr, out_ptr;
@@ -144,8 +144,8 @@ sep_downsample (j_compress_ptr cinfo,
*/
METHODDEF(void)
-int_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data)
+int_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
{
int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v;
JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */
@@ -156,14 +156,14 @@ int_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor;
v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;
numpix = h_expand * v_expand;
- numpix2 = numpix/2;
+ numpix2 = numpix / 2;
/* Expand input data enough to let all the output samples be generated
* by the standard loop. Special-casing padded output would be more
* efficient.
*/
- expand_right_edge(input_data, cinfo->max_v_samp_factor,
- cinfo->image_width, output_cols * h_expand);
+ expand_right_edge(input_data, cinfo->max_v_samp_factor, cinfo->image_width,
+ output_cols * h_expand);
inrow = 0;
for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
@@ -172,12 +172,12 @@ int_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
outcol++, outcol_h += h_expand) {
outvalue = 0;
for (v = 0; v < v_expand; v++) {
- inptr = input_data[inrow+v] + outcol_h;
+ inptr = input_data[inrow + v] + outcol_h;
for (h = 0; h < h_expand; h++) {
- outvalue += (JLONG) GETJSAMPLE(*inptr++);
+ outvalue += (JLONG)GETJSAMPLE(*inptr++);
}
}
- *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix);
+ *outptr++ = (JSAMPLE)((outvalue + numpix2) / numpix);
}
inrow += v_expand;
}
@@ -191,15 +191,15 @@ int_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
*/
METHODDEF(void)
-fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data)
+fullsize_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
{
/* Copy the data */
- jcopy_sample_rows(input_data, 0, output_data, 0,
- cinfo->max_v_samp_factor, cinfo->image_width);
+ jcopy_sample_rows(input_data, 0, output_data, 0, cinfo->max_v_samp_factor,
+ cinfo->image_width);
/* Edge-expand */
- expand_right_edge(output_data, cinfo->max_v_samp_factor,
- cinfo->image_width, compptr->width_in_blocks * DCTSIZE);
+ expand_right_edge(output_data, cinfo->max_v_samp_factor, cinfo->image_width,
+ compptr->width_in_blocks * DCTSIZE);
}
@@ -216,8 +216,8 @@ fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
*/
METHODDEF(void)
-h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data)
+h2v1_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
{
int outrow;
JDIMENSION outcol;
@@ -229,16 +229,16 @@ h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
* by the standard loop. Special-casing padded output would be more
* efficient.
*/
- expand_right_edge(input_data, cinfo->max_v_samp_factor,
- cinfo->image_width, output_cols * 2);
+ expand_right_edge(input_data, cinfo->max_v_samp_factor, cinfo->image_width,
+ output_cols * 2);
for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
outptr = output_data[outrow];
inptr = input_data[outrow];
bias = 0; /* bias = 0,1,0,1,... for successive samples */
for (outcol = 0; outcol < output_cols; outcol++) {
- *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1])
- + bias) >> 1);
+ *outptr++ =
+ (JSAMPLE)((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) + bias) >> 1);
bias ^= 1; /* 0=>1, 1=>0 */
inptr += 2;
}
@@ -253,8 +253,8 @@ h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
*/
METHODDEF(void)
-h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data)
+h2v2_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
{
int inrow, outrow;
JDIMENSION outcol;
@@ -266,21 +266,21 @@ h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
* by the standard loop. Special-casing padded output would be more
* efficient.
*/
- expand_right_edge(input_data, cinfo->max_v_samp_factor,
- cinfo->image_width, output_cols * 2);
+ expand_right_edge(input_data, cinfo->max_v_samp_factor, cinfo->image_width,
+ output_cols * 2);
inrow = 0;
for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
outptr = output_data[outrow];
inptr0 = input_data[inrow];
- inptr1 = input_data[inrow+1];
+ inptr1 = input_data[inrow + 1];
bias = 1; /* bias = 1,2,1,2,... for successive samples */
for (outcol = 0; outcol < output_cols; outcol++) {
- *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
- GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1])
- + bias) >> 2);
+ *outptr++ =
+ (JSAMPLE)((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
+ GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) + bias) >> 2);
bias ^= 3; /* 1=>2, 2=>1 */
- inptr0 += 2; inptr1 += 2;
+ inptr0 += 2; inptr1 += 2;
}
inrow += 2;
}
@@ -296,8 +296,8 @@ h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
*/
METHODDEF(void)
-h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data)
+h2v2_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
{
int inrow, outrow;
JDIMENSION colctr;
@@ -332,9 +332,9 @@ h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
outptr = output_data[outrow];
inptr0 = input_data[inrow];
- inptr1 = input_data[inrow+1];
- above_ptr = input_data[inrow-1];
- below_ptr = input_data[inrow+2];
+ inptr1 = input_data[inrow + 1];
+ above_ptr = input_data[inrow - 1];
+ below_ptr = input_data[inrow + 2];
/* Special case for first column: pretend column -1 is same as column 0 */
membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
@@ -347,8 +347,8 @@ h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) +
GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]);
membersum = membersum * memberscale + neighsum * neighscale;
- *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
- inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
+ *outptr++ = (JSAMPLE)((membersum + 32768) >> 16);
+ inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
for (colctr = output_cols - 2; colctr > 0; colctr--) {
/* sum of pixels directly mapped to this output element */
@@ -367,8 +367,8 @@ h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
/* form final output scaled up by 2^16 */
membersum = membersum * memberscale + neighsum * neighscale;
/* round, descale and output it */
- *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
- inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
+ *outptr++ = (JSAMPLE)((membersum + 32768) >> 16);
+ inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
}
/* Special case for last column */
@@ -382,7 +382,7 @@ h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) +
GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]);
membersum = membersum * memberscale + neighsum * neighscale;
- *outptr = (JSAMPLE) ((membersum + 32768) >> 16);
+ *outptr = (JSAMPLE)((membersum + 32768) >> 16);
inrow += 2;
}
@@ -396,8 +396,8 @@ h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
*/
METHODDEF(void)
-fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data)
+fullsize_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
{
int outrow;
JDIMENSION colctr;
@@ -425,8 +425,8 @@ fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
outptr = output_data[outrow];
inptr = input_data[outrow];
- above_ptr = input_data[outrow-1];
- below_ptr = input_data[outrow+1];
+ above_ptr = input_data[outrow - 1];
+ below_ptr = input_data[outrow + 1];
/* Special case for first column */
colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) +
@@ -436,25 +436,25 @@ fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
GETJSAMPLE(*inptr);
neighsum = colsum + (colsum - membersum) + nextcolsum;
membersum = membersum * memberscale + neighsum * neighscale;
- *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
- lastcolsum = colsum; colsum = nextcolsum;
+ *outptr++ = (JSAMPLE)((membersum + 32768) >> 16);
+ lastcolsum = colsum; colsum = nextcolsum;
for (colctr = output_cols - 2; colctr > 0; colctr--) {
membersum = GETJSAMPLE(*inptr++);
- above_ptr++; below_ptr++;
+ above_ptr++; below_ptr++;
nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
GETJSAMPLE(*inptr);
neighsum = lastcolsum + (colsum - membersum) + nextcolsum;
membersum = membersum * memberscale + neighsum * neighscale;
- *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
- lastcolsum = colsum; colsum = nextcolsum;
+ *outptr++ = (JSAMPLE)((membersum + 32768) >> 16);
+ lastcolsum = colsum; colsum = nextcolsum;
}
/* Special case for last column */
membersum = GETJSAMPLE(*inptr);
neighsum = lastcolsum + (colsum - membersum) + colsum;
membersum = membersum * memberscale + neighsum * neighscale;
- *outptr = (JSAMPLE) ((membersum + 32768) >> 16);
+ *outptr = (JSAMPLE)((membersum + 32768) >> 16);
}
}
@@ -468,7 +468,7 @@ fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
*/
GLOBAL(void)
-jinit_downsampler (j_compress_ptr cinfo)
+jinit_downsampler(j_compress_ptr cinfo)
{
my_downsample_ptr downsample;
int ci;
@@ -476,9 +476,9 @@ jinit_downsampler (j_compress_ptr cinfo)
boolean smoothok = TRUE;
downsample = (my_downsample_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_downsampler));
- cinfo->downsample = (struct jpeg_downsampler *) downsample;
+ cinfo->downsample = (struct jpeg_downsampler *)downsample;
downsample->pub.start_pass = start_pass_downsample;
downsample->pub.downsample = sep_downsample;
downsample->pub.need_context_rows = FALSE;
diff --git a/src/3rdparty/libjpeg/src/jctrans.c b/src/3rdparty/libjpeg/src/jctrans.c
index 6f16b052cf..ce70a30940 100644
--- a/src/3rdparty/libjpeg/src/jctrans.c
+++ b/src/3rdparty/libjpeg/src/jctrans.c
@@ -20,10 +20,10 @@
/* Forward declarations */
-LOCAL(void) transencode_master_selection
- (j_compress_ptr cinfo, jvirt_barray_ptr *coef_arrays);
-LOCAL(void) transencode_coef_controller
- (j_compress_ptr cinfo, jvirt_barray_ptr *coef_arrays);
+LOCAL(void) transencode_master_selection(j_compress_ptr cinfo,
+ jvirt_barray_ptr *coef_arrays);
+LOCAL(void) transencode_coef_controller(j_compress_ptr cinfo,
+ jvirt_barray_ptr *coef_arrays);
/*
@@ -39,14 +39,14 @@ LOCAL(void) transencode_coef_controller
*/
GLOBAL(void)
-jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr *coef_arrays)
+jpeg_write_coefficients(j_compress_ptr cinfo, jvirt_barray_ptr *coef_arrays)
{
if (cinfo->global_state != CSTATE_START)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
/* Mark all tables to be written */
jpeg_suppress_tables(cinfo, FALSE);
/* (Re)initialize error mgr and destination modules */
- (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
+ (*cinfo->err->reset_error_mgr) ((j_common_ptr)cinfo);
(*cinfo->dest->init_destination) (cinfo);
/* Perform master selection of active modules */
transencode_master_selection(cinfo, coef_arrays);
@@ -64,8 +64,7 @@ jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr *coef_arrays)
*/
GLOBAL(void)
-jpeg_copy_critical_parameters (j_decompress_ptr srcinfo,
- j_compress_ptr dstinfo)
+jpeg_copy_critical_parameters(j_decompress_ptr srcinfo, j_compress_ptr dstinfo)
{
JQUANT_TBL **qtblptr;
jpeg_component_info *incomp, *outcomp;
@@ -97,11 +96,10 @@ jpeg_copy_critical_parameters (j_decompress_ptr srcinfo,
/* Copy the source's quantization tables. */
for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
if (srcinfo->quant_tbl_ptrs[tblno] != NULL) {
- qtblptr = & dstinfo->quant_tbl_ptrs[tblno];
+ qtblptr = &dstinfo->quant_tbl_ptrs[tblno];
if (*qtblptr == NULL)
- *qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo);
- MEMCOPY((*qtblptr)->quantval,
- srcinfo->quant_tbl_ptrs[tblno]->quantval,
+ *qtblptr = jpeg_alloc_quant_table((j_common_ptr)dstinfo);
+ MEMCOPY((*qtblptr)->quantval, srcinfo->quant_tbl_ptrs[tblno]->quantval,
sizeof((*qtblptr)->quantval));
(*qtblptr)->sent_table = FALSE;
}
@@ -165,8 +163,8 @@ jpeg_copy_critical_parameters (j_decompress_ptr srcinfo,
*/
LOCAL(void)
-transencode_master_selection (j_compress_ptr cinfo,
- jvirt_barray_ptr *coef_arrays)
+transencode_master_selection(j_compress_ptr cinfo,
+ jvirt_barray_ptr *coef_arrays)
{
/* Although we don't actually use input_components for transcoding,
* jcmaster.c's initial_setup will complain if input_components is 0.
@@ -199,7 +197,7 @@ transencode_master_selection (j_compress_ptr cinfo,
jinit_marker_writer(cinfo);
/* We can now tell the memory manager to allocate virtual arrays. */
- (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
+ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr)cinfo);
/* Write the datastream header (SOI, JFIF) immediately.
* Frame and scan headers are postponed till later.
@@ -238,10 +236,10 @@ typedef my_coef_controller *my_coef_ptr;
LOCAL(void)
-start_iMCU_row (j_compress_ptr cinfo)
+start_iMCU_row(j_compress_ptr cinfo)
/* Reset within-iMCU-row counters for a new row */
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
/* In an interleaved scan, an MCU row is the same as an iMCU row.
* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
@@ -250,7 +248,7 @@ start_iMCU_row (j_compress_ptr cinfo)
if (cinfo->comps_in_scan > 1) {
coef->MCU_rows_per_iMCU_row = 1;
} else {
- if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1))
+ if (coef->iMCU_row_num < (cinfo->total_iMCU_rows - 1))
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
else
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
@@ -266,9 +264,9 @@ start_iMCU_row (j_compress_ptr cinfo)
*/
METHODDEF(void)
-start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+start_pass_coef(j_compress_ptr cinfo, J_BUF_MODE pass_mode)
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
if (pass_mode != JBUF_CRANK_DEST)
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
@@ -289,9 +287,9 @@ start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
*/
METHODDEF(boolean)
-compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+compress_output(j_compress_ptr cinfo, JSAMPIMAGE input_buf)
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
JDIMENSION MCU_col_num; /* index of current MCU within row */
JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
@@ -306,9 +304,9 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
buffer[ci] = (*cinfo->mem->access_virt_barray)
- ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
+ ((j_common_ptr)cinfo, coef->whole_image[compptr->component_index],
coef->iMCU_row_num * compptr->v_samp_factor,
- (JDIMENSION) compptr->v_samp_factor, FALSE);
+ (JDIMENSION)compptr->v_samp_factor, FALSE);
}
/* Loop to process one whole iMCU row */
@@ -321,13 +319,13 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
start_col = MCU_col_num * compptr->MCU_width;
- blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
- : compptr->last_col_width;
+ blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width :
+ compptr->last_col_width;
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
if (coef->iMCU_row_num < last_iMCU_row ||
- yindex+yoffset < compptr->last_row_height) {
+ yindex + yoffset < compptr->last_row_height) {
/* Fill in pointers to real blocks in this row */
- buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
+ buffer_ptr = buffer[ci][yindex + yoffset] + start_col;
for (xindex = 0; xindex < blockcnt; xindex++)
MCU_buffer[blkn++] = buffer_ptr++;
} else {
@@ -342,13 +340,13 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
*/
for (; xindex < compptr->MCU_width; xindex++) {
MCU_buffer[blkn] = coef->dummy_buffer[blkn];
- MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0];
+ MCU_buffer[blkn][0][0] = MCU_buffer[blkn - 1][0][0];
blkn++;
}
}
}
/* Try to write the MCU. */
- if (! (*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) {
+ if (!(*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) {
/* Suspension forced; update state counters and exit */
coef->MCU_vert_offset = yoffset;
coef->mcu_ctr = MCU_col_num;
@@ -374,17 +372,17 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
*/
LOCAL(void)
-transencode_coef_controller (j_compress_ptr cinfo,
- jvirt_barray_ptr *coef_arrays)
+transencode_coef_controller(j_compress_ptr cinfo,
+ jvirt_barray_ptr *coef_arrays)
{
my_coef_ptr coef;
JBLOCKROW buffer;
int i;
coef = (my_coef_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_coef_controller));
- cinfo->coef = (struct jpeg_c_coef_controller *) coef;
+ cinfo->coef = (struct jpeg_c_coef_controller *)coef;
coef->pub.start_pass = start_pass_coef;
coef->pub.compress_data = compress_output;
@@ -393,9 +391,9 @@ transencode_coef_controller (j_compress_ptr cinfo,
/* Allocate and pre-zero space for dummy DCT blocks. */
buffer = (JBLOCKROW)
- (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_large) ((j_common_ptr)cinfo, JPOOL_IMAGE,
C_MAX_BLOCKS_IN_MCU * sizeof(JBLOCK));
- jzero_far((void *) buffer, C_MAX_BLOCKS_IN_MCU * sizeof(JBLOCK));
+ jzero_far((void *)buffer, C_MAX_BLOCKS_IN_MCU * sizeof(JBLOCK));
for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) {
coef->dummy_buffer[i] = buffer + i;
}
diff --git a/src/3rdparty/libjpeg/src/jdapimin.c b/src/3rdparty/libjpeg/src/jdapimin.c
index f80a14667f..21a41d2e9f 100644
--- a/src/3rdparty/libjpeg/src/jdapimin.c
+++ b/src/3rdparty/libjpeg/src/jdapimin.c
@@ -31,7 +31,7 @@
*/
GLOBAL(void)
-jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize)
+jpeg_CreateDecompress(j_decompress_ptr cinfo, int version, size_t structsize)
{
int i;
@@ -41,7 +41,7 @@ jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize)
ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
if (structsize != sizeof(struct jpeg_decompress_struct))
ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,
- (int) sizeof(struct jpeg_decompress_struct), (int) structsize);
+ (int)sizeof(struct jpeg_decompress_struct), (int)structsize);
/* For debugging purposes, we zero the whole master structure.
* But the application has already set the err pointer, and may have set
@@ -50,8 +50,8 @@ jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize)
* complain here.
*/
{
- struct jpeg_error_mgr * err = cinfo->err;
- void * client_data = cinfo->client_data; /* ignore Purify complaint here */
+ struct jpeg_error_mgr *err = cinfo->err;
+ void *client_data = cinfo->client_data; /* ignore Purify complaint here */
MEMZERO(cinfo, sizeof(struct jpeg_decompress_struct));
cinfo->err = err;
cinfo->client_data = client_data;
@@ -59,7 +59,7 @@ jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize)
cinfo->is_decompressor = TRUE;
/* Initialize a memory manager instance for this object */
- jinit_memory_mgr((j_common_ptr) cinfo);
+ jinit_memory_mgr((j_common_ptr)cinfo);
/* Zero out pointers to permanent structures. */
cinfo->progress = NULL;
@@ -89,8 +89,8 @@ jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize)
* here.
*/
cinfo->master = (struct jpeg_decomp_master *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
- sizeof(my_decomp_master));
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
+ sizeof(my_decomp_master));
MEMZERO(cinfo->master, sizeof(my_decomp_master));
}
@@ -100,9 +100,9 @@ jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize)
*/
GLOBAL(void)
-jpeg_destroy_decompress (j_decompress_ptr cinfo)
+jpeg_destroy_decompress(j_decompress_ptr cinfo)
{
- jpeg_destroy((j_common_ptr) cinfo); /* use common routine */
+ jpeg_destroy((j_common_ptr)cinfo); /* use common routine */
}
@@ -112,9 +112,9 @@ jpeg_destroy_decompress (j_decompress_ptr cinfo)
*/
GLOBAL(void)
-jpeg_abort_decompress (j_decompress_ptr cinfo)
+jpeg_abort_decompress(j_decompress_ptr cinfo)
{
- jpeg_abort((j_common_ptr) cinfo); /* use common routine */
+ jpeg_abort((j_common_ptr)cinfo); /* use common routine */
}
@@ -123,7 +123,7 @@ jpeg_abort_decompress (j_decompress_ptr cinfo)
*/
LOCAL(void)
-default_decompress_parms (j_decompress_ptr cinfo)
+default_decompress_parms(j_decompress_ptr cinfo)
{
/* Guess the input colorspace, and set output colorspace accordingly. */
/* (Wish JPEG committee had provided a real way to specify this...) */
@@ -250,7 +250,7 @@ default_decompress_parms (j_decompress_ptr cinfo)
*/
GLOBAL(int)
-jpeg_read_header (j_decompress_ptr cinfo, boolean require_image)
+jpeg_read_header(j_decompress_ptr cinfo, boolean require_image)
{
int retcode;
@@ -271,7 +271,7 @@ jpeg_read_header (j_decompress_ptr cinfo, boolean require_image)
* call jpeg_abort, but we can't change it now for compatibility reasons.
* A side effect is to free any temporary memory (there shouldn't be any).
*/
- jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */
+ jpeg_abort((j_common_ptr)cinfo); /* sets state = DSTATE_START */
retcode = JPEG_HEADER_TABLES_ONLY;
break;
case JPEG_SUSPENDED:
@@ -296,7 +296,7 @@ jpeg_read_header (j_decompress_ptr cinfo, boolean require_image)
*/
GLOBAL(int)
-jpeg_consume_input (j_decompress_ptr cinfo)
+jpeg_consume_input(j_decompress_ptr cinfo)
{
int retcode = JPEG_SUSPENDED;
@@ -343,7 +343,7 @@ jpeg_consume_input (j_decompress_ptr cinfo)
*/
GLOBAL(boolean)
-jpeg_input_complete (j_decompress_ptr cinfo)
+jpeg_input_complete(j_decompress_ptr cinfo)
{
/* Check for valid jpeg object */
if (cinfo->global_state < DSTATE_START ||
@@ -358,7 +358,7 @@ jpeg_input_complete (j_decompress_ptr cinfo)
*/
GLOBAL(boolean)
-jpeg_has_multiple_scans (j_decompress_ptr cinfo)
+jpeg_has_multiple_scans(j_decompress_ptr cinfo)
{
/* Only valid after jpeg_read_header completes */
if (cinfo->global_state < DSTATE_READY ||
@@ -378,10 +378,10 @@ jpeg_has_multiple_scans (j_decompress_ptr cinfo)
*/
GLOBAL(boolean)
-jpeg_finish_decompress (j_decompress_ptr cinfo)
+jpeg_finish_decompress(j_decompress_ptr cinfo)
{
if ((cinfo->global_state == DSTATE_SCANNING ||
- cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) {
+ cinfo->global_state == DSTATE_RAW_OK) && !cinfo->buffered_image) {
/* Terminate final pass of non-buffered mode */
if (cinfo->output_scanline < cinfo->output_height)
ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);
@@ -395,13 +395,13 @@ jpeg_finish_decompress (j_decompress_ptr cinfo)
ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
}
/* Read until EOI */
- while (! cinfo->inputctl->eoi_reached) {
+ while (!cinfo->inputctl->eoi_reached) {
if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
return FALSE; /* Suspend, come back later */
}
/* Do final cleanup */
(*cinfo->src->term_source) (cinfo);
/* We can use jpeg_abort to release memory and reset global_state */
- jpeg_abort((j_common_ptr) cinfo);
+ jpeg_abort((j_common_ptr)cinfo);
return TRUE;
}
diff --git a/src/3rdparty/libjpeg/src/jdapistd.c b/src/3rdparty/libjpeg/src/jdapistd.c
index 105121df2b..2c808fa564 100644
--- a/src/3rdparty/libjpeg/src/jdapistd.c
+++ b/src/3rdparty/libjpeg/src/jdapistd.c
@@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1994-1996, Thomas G. Lane.
* libjpeg-turbo Modifications:
- * Copyright (C) 2010, 2015-2017, D. R. Commander.
+ * Copyright (C) 2010, 2015-2018, D. R. Commander.
* Copyright (C) 2015, Google, Inc.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
@@ -25,7 +25,7 @@
#include "jmemsys.h"
/* Forward declarations */
-LOCAL(boolean) output_pass_setup (j_decompress_ptr cinfo);
+LOCAL(boolean) output_pass_setup(j_decompress_ptr cinfo);
/*
@@ -40,7 +40,7 @@ LOCAL(boolean) output_pass_setup (j_decompress_ptr cinfo);
*/
GLOBAL(boolean)
-jpeg_start_decompress (j_decompress_ptr cinfo)
+jpeg_start_decompress(j_decompress_ptr cinfo)
{
if (cinfo->global_state == DSTATE_READY) {
/* First call: initialize master control, select active modules */
@@ -60,7 +60,7 @@ jpeg_start_decompress (j_decompress_ptr cinfo)
int retcode;
/* Call progress monitor hook if present */
if (cinfo->progress != NULL)
- (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ (*cinfo->progress->progress_monitor) ((j_common_ptr)cinfo);
/* Absorb some more input */
retcode = (*cinfo->inputctl->consume_input) (cinfo);
if (retcode == JPEG_SUSPENDED)
@@ -72,7 +72,7 @@ jpeg_start_decompress (j_decompress_ptr cinfo)
(retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) {
if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) {
/* jdmaster underestimated number of scans; ratchet up one scan */
- cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows;
+ cinfo->progress->pass_limit += (long)cinfo->total_iMCU_rows;
}
}
}
@@ -97,7 +97,7 @@ jpeg_start_decompress (j_decompress_ptr cinfo)
*/
LOCAL(boolean)
-output_pass_setup (j_decompress_ptr cinfo)
+output_pass_setup(j_decompress_ptr cinfo)
{
if (cinfo->global_state != DSTATE_PRESCAN) {
/* First call: do pass setup */
@@ -113,14 +113,14 @@ output_pass_setup (j_decompress_ptr cinfo)
JDIMENSION last_scanline;
/* Call progress monitor hook if present */
if (cinfo->progress != NULL) {
- cinfo->progress->pass_counter = (long) cinfo->output_scanline;
- cinfo->progress->pass_limit = (long) cinfo->output_height;
- (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ cinfo->progress->pass_counter = (long)cinfo->output_scanline;
+ cinfo->progress->pass_limit = (long)cinfo->output_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr)cinfo);
}
/* Process some data */
last_scanline = cinfo->output_scanline;
- (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL,
- &cinfo->output_scanline, (JDIMENSION) 0);
+ (*cinfo->main->process_data) (cinfo, (JSAMPARRAY)NULL,
+ &cinfo->output_scanline, (JDIMENSION)0);
if (cinfo->output_scanline == last_scanline)
return FALSE; /* No progress made, must suspend */
}
@@ -150,8 +150,8 @@ output_pass_setup (j_decompress_ptr cinfo)
*/
GLOBAL(void)
-jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset,
- JDIMENSION *width)
+jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset,
+ JDIMENSION *width)
{
int ci, align, orig_downsampled_width;
JDIMENSION input_xoffset;
@@ -210,11 +210,10 @@ jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset,
/* Set the first and last iMCU columns that we must decompress. These values
* will be used in single-scan decompressions.
*/
- cinfo->master->first_iMCU_col =
- (JDIMENSION) (long) (*xoffset) / (long) align;
+ cinfo->master->first_iMCU_col = (JDIMENSION)(long)(*xoffset) / (long)align;
cinfo->master->last_iMCU_col =
- (JDIMENSION) jdiv_round_up((long) (*xoffset + cinfo->output_width),
- (long) align) - 1;
+ (JDIMENSION)jdiv_round_up((long)(*xoffset + cinfo->output_width),
+ (long)align) - 1;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
@@ -224,9 +223,9 @@ jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset,
/* Set downsampled_width to the new output width. */
orig_downsampled_width = compptr->downsampled_width;
compptr->downsampled_width =
- (JDIMENSION) jdiv_round_up((long) (cinfo->output_width *
- compptr->h_samp_factor),
- (long) cinfo->max_h_samp_factor);
+ (JDIMENSION)jdiv_round_up((long)(cinfo->output_width *
+ compptr->h_samp_factor),
+ (long)cinfo->max_h_samp_factor);
if (compptr->downsampled_width < 2 && orig_downsampled_width >= 2)
reinit_upsampler = TRUE;
@@ -234,11 +233,10 @@ jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset,
* values will be used in multi-scan decompressions.
*/
cinfo->master->first_MCU_col[ci] =
- (JDIMENSION) (long) (*xoffset * hsf) / (long) align;
+ (JDIMENSION)(long)(*xoffset * hsf) / (long)align;
cinfo->master->last_MCU_col[ci] =
- (JDIMENSION) jdiv_round_up((long) ((*xoffset + cinfo->output_width) *
- hsf),
- (long) align) - 1;
+ (JDIMENSION)jdiv_round_up((long)((*xoffset + cinfo->output_width) * hsf),
+ (long)align) - 1;
}
if (reinit_upsampler) {
@@ -263,8 +261,8 @@ jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset,
*/
GLOBAL(JDIMENSION)
-jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines,
- JDIMENSION max_lines)
+jpeg_read_scanlines(j_decompress_ptr cinfo, JSAMPARRAY scanlines,
+ JDIMENSION max_lines)
{
JDIMENSION row_ctr;
@@ -277,9 +275,9 @@ jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines,
/* Call progress monitor hook if present */
if (cinfo->progress != NULL) {
- cinfo->progress->pass_counter = (long) cinfo->output_scanline;
- cinfo->progress->pass_limit = (long) cinfo->output_height;
- (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ cinfo->progress->pass_counter = (long)cinfo->output_scanline;
+ cinfo->progress->pass_limit = (long)cinfo->output_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr)cinfo);
}
/* Process some data */
@@ -292,16 +290,16 @@ jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines,
/* Dummy color convert function used by jpeg_skip_scanlines() */
LOCAL(void)
-noop_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
- JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
+noop_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
}
/* Dummy quantize function used by jpeg_skip_scanlines() */
LOCAL(void)
-noop_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
- JSAMPARRAY output_buf, int num_rows)
+noop_quantize(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
{
}
@@ -315,17 +313,20 @@ noop_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
*/
LOCAL(void)
-read_and_discard_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines)
+read_and_discard_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines)
{
JDIMENSION n;
void (*color_convert) (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
JDIMENSION input_row, JSAMPARRAY output_buf,
- int num_rows);
+ int num_rows) = NULL;
void (*color_quantize) (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
JSAMPARRAY output_buf, int num_rows) = NULL;
- color_convert = cinfo->cconvert->color_convert;
- cinfo->cconvert->color_convert = noop_convert;
+ if (cinfo->cconvert && cinfo->cconvert->color_convert) {
+ color_convert = cinfo->cconvert->color_convert;
+ cinfo->cconvert->color_convert = noop_convert;
+ }
+
if (cinfo->cquantize && cinfo->cquantize->color_quantize) {
color_quantize = cinfo->cquantize->color_quantize;
cinfo->cquantize->color_quantize = noop_quantize;
@@ -334,7 +335,9 @@ read_and_discard_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines)
for (n = 0; n < num_lines; n++)
jpeg_read_scanlines(cinfo, NULL, 1);
- cinfo->cconvert->color_convert = color_convert;
+ if (color_convert)
+ cinfo->cconvert->color_convert = color_convert;
+
if (color_quantize)
cinfo->cquantize->color_quantize = color_quantize;
}
@@ -346,10 +349,10 @@ read_and_discard_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines)
*/
LOCAL(void)
-increment_simple_rowgroup_ctr (j_decompress_ptr cinfo, JDIMENSION rows)
+increment_simple_rowgroup_ctr(j_decompress_ptr cinfo, JDIMENSION rows)
{
JDIMENSION rows_left;
- my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
+ my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
/* Increment the counter to the next row group after the skipped rows. */
main_ptr->rowgroup_ctr += rows / cinfo->max_v_samp_factor;
@@ -375,11 +378,11 @@ increment_simple_rowgroup_ctr (j_decompress_ptr cinfo, JDIMENSION rows)
*/
GLOBAL(JDIMENSION)
-jpeg_skip_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines)
+jpeg_skip_scanlines(j_decompress_ptr cinfo, JDIMENSION num_lines)
{
- my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
JDIMENSION i, x;
int y;
JDIMENSION lines_per_iMCU_row, lines_left_in_iMCU_row, lines_after_iMCU_row;
@@ -481,7 +484,7 @@ jpeg_skip_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines)
if (cinfo->upsample->need_context_rows) {
cinfo->output_scanline += lines_to_skip;
cinfo->output_iMCU_row += lines_to_skip / lines_per_iMCU_row;
- main_ptr->iMCU_row_ctr += lines_after_iMCU_row / lines_per_iMCU_row;
+ main_ptr->iMCU_row_ctr += lines_to_skip / lines_per_iMCU_row;
/* It is complex to properly move to the middle of a context block, so
* read the remaining lines instead of skipping them.
*/
@@ -544,8 +547,8 @@ jpeg_skip_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines)
*/
GLOBAL(JDIMENSION)
-jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data,
- JDIMENSION max_lines)
+jpeg_read_raw_data(j_decompress_ptr cinfo, JSAMPIMAGE data,
+ JDIMENSION max_lines)
{
JDIMENSION lines_per_iMCU_row;
@@ -558,9 +561,9 @@ jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data,
/* Call progress monitor hook if present */
if (cinfo->progress != NULL) {
- cinfo->progress->pass_counter = (long) cinfo->output_scanline;
- cinfo->progress->pass_limit = (long) cinfo->output_height;
- (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ cinfo->progress->pass_counter = (long)cinfo->output_scanline;
+ cinfo->progress->pass_limit = (long)cinfo->output_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr)cinfo);
}
/* Verify that at least one iMCU row can be returned. */
@@ -569,7 +572,7 @@ jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data,
ERREXIT(cinfo, JERR_BUFFER_SIZE);
/* Decompress directly into user's buffer. */
- if (! (*cinfo->coef->decompress_data) (cinfo, data))
+ if (!(*cinfo->coef->decompress_data) (cinfo, data))
return 0; /* suspension forced, can do nothing more */
/* OK, we processed one iMCU row. */
@@ -587,7 +590,7 @@ jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data,
*/
GLOBAL(boolean)
-jpeg_start_output (j_decompress_ptr cinfo, int scan_number)
+jpeg_start_output(j_decompress_ptr cinfo, int scan_number)
{
if (cinfo->global_state != DSTATE_BUFIMAGE &&
cinfo->global_state != DSTATE_PRESCAN)
@@ -595,8 +598,7 @@ jpeg_start_output (j_decompress_ptr cinfo, int scan_number)
/* Limit scan number to valid range */
if (scan_number <= 0)
scan_number = 1;
- if (cinfo->inputctl->eoi_reached &&
- scan_number > cinfo->input_scan_number)
+ if (cinfo->inputctl->eoi_reached && scan_number > cinfo->input_scan_number)
scan_number = cinfo->input_scan_number;
cinfo->output_scan_number = scan_number;
/* Perform any dummy output passes, and set up for the real pass */
@@ -612,7 +614,7 @@ jpeg_start_output (j_decompress_ptr cinfo, int scan_number)
*/
GLOBAL(boolean)
-jpeg_finish_output (j_decompress_ptr cinfo)
+jpeg_finish_output(j_decompress_ptr cinfo)
{
if ((cinfo->global_state == DSTATE_SCANNING ||
cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) {
@@ -626,7 +628,7 @@ jpeg_finish_output (j_decompress_ptr cinfo)
}
/* Read markers looking for SOS or EOI */
while (cinfo->input_scan_number <= cinfo->output_scan_number &&
- ! cinfo->inputctl->eoi_reached) {
+ !cinfo->inputctl->eoi_reached) {
if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
return FALSE; /* Suspend, come back later */
}
diff --git a/src/3rdparty/libjpeg/src/jdarith.c b/src/3rdparty/libjpeg/src/jdarith.c
index ce0f920954..6002481e24 100644
--- a/src/3rdparty/libjpeg/src/jdarith.c
+++ b/src/3rdparty/libjpeg/src/jdarith.c
@@ -4,16 +4,19 @@
* This file was part of the Independent JPEG Group's software:
* Developed 1997-2015 by Guido Vollbeding.
* libjpeg-turbo Modifications:
- * Copyright (C) 2015-2016, D. R. Commander.
+ * Copyright (C) 2015-2018, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
- * This file contains portable arithmetic entropy decoding routines for JPEG
- * (implementing the ISO/IEC IS 10918-1 and CCITT Recommendation ITU-T T.81).
+ * This file contains portable arithmetic entropy encoding routines for JPEG
+ * (implementing Recommendation ITU-T T.81 | ISO/IEC 10918-1).
*
* Both sequential and progressive modes are supported in this single module.
*
* Suspension is not currently supported in this module.
+ *
+ * NOTE: All referenced figures are from
+ * Recommendation ITU-T T.81 (1992) | ISO/IEC 10918-1:1994.
*/
#define JPEG_INTERNALS
@@ -21,7 +24,7 @@
#include "jpeglib.h"
-#define NEG_1 ((unsigned int)-1)
+#define NEG_1 ((unsigned int)-1)
/* Expanded entropy decoder object for arithmetic decoding. */
@@ -63,18 +66,18 @@ typedef arith_entropy_decoder *arith_entropy_ptr;
* in the lower bits (mask 0x7F).
*/
-#define DC_STAT_BINS 64
-#define AC_STAT_BINS 256
+#define DC_STAT_BINS 64
+#define AC_STAT_BINS 256
LOCAL(int)
-get_byte (j_decompress_ptr cinfo)
+get_byte(j_decompress_ptr cinfo)
/* Read next input byte; we do not support suspension in this module. */
{
struct jpeg_source_mgr *src = cinfo->src;
if (src->bytes_in_buffer == 0)
- if (! (*src->fill_input_buffer) (cinfo))
+ if (!(*src->fill_input_buffer) (cinfo))
ERREXIT(cinfo, JERR_CANT_SUSPEND);
src->bytes_in_buffer--;
return GETJOCTET(*src->next_input_byte++);
@@ -109,9 +112,9 @@ get_byte (j_decompress_ptr cinfo)
*/
LOCAL(int)
-arith_decode (j_decompress_ptr cinfo, unsigned char *st)
+arith_decode(j_decompress_ptr cinfo, unsigned char *st)
{
- register arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy;
+ register arith_entropy_ptr e = (arith_entropy_ptr)cinfo->entropy;
register unsigned char nl, nm;
register JLONG qe, temp;
register int sv, data;
@@ -156,8 +159,8 @@ arith_decode (j_decompress_ptr cinfo, unsigned char *st)
*/
sv = *st;
qe = jpeg_aritab[sv & 0x7F]; /* => Qe_Value */
- nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */
- nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */
+ nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */
+ nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */
/* Decode & estimation procedures per sections D.2.4 & D.2.5 */
temp = e->a - qe;
@@ -193,14 +196,14 @@ arith_decode (j_decompress_ptr cinfo, unsigned char *st)
*/
LOCAL(void)
-process_restart (j_decompress_ptr cinfo)
+process_restart(j_decompress_ptr cinfo)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
int ci;
jpeg_component_info *compptr;
/* Advance past the RSTn marker */
- if (! (*cinfo->marker->read_restart_marker) (cinfo))
+ if (!(*cinfo->marker->read_restart_marker) (cinfo))
ERREXIT(cinfo, JERR_CANT_SUSPEND);
/* Re-initialize statistics areas */
@@ -244,9 +247,9 @@ process_restart (j_decompress_ptr cinfo)
*/
METHODDEF(boolean)
-decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+decode_mcu_DC_first(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
JBLOCKROW block;
unsigned char *st;
int blkn, ci, tbl, sign;
@@ -280,7 +283,7 @@ decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
/* Figure F.21: Decoding nonzero value v */
/* Figure F.22: Decoding the sign of v */
sign = arith_decode(cinfo, st + 1);
- st += 2; st += sign;
+ st += 2; st += sign;
/* Figure F.23: Decoding the magnitude category of v */
if ((m = arith_decode(cinfo, st)) != 0) {
st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */
@@ -294,9 +297,9 @@ decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
}
}
/* Section F.1.4.4.1.2: Establish dc_context conditioning category */
- if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1))
+ if (m < (int)((1L << cinfo->arith_dc_L[tbl]) >> 1))
entropy->dc_context[ci] = 0; /* zero diff category */
- else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1))
+ else if (m > (int)((1L << cinfo->arith_dc_U[tbl]) >> 1))
entropy->dc_context[ci] = 12 + (sign * 4); /* large diff category */
else
entropy->dc_context[ci] = 4 + (sign * 4); /* small diff category */
@@ -305,12 +308,12 @@ decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
st += 14;
while (m >>= 1)
if (arith_decode(cinfo, st)) v |= m;
- v += 1; if (sign) v = -v;
- entropy->last_dc_val[ci] += v;
+ v += 1; if (sign) v = -v;
+ entropy->last_dc_val[ci] = (entropy->last_dc_val[ci] + v) & 0xffff;
}
/* Scale and output the DC coefficient (assumes jpeg_natural_order[0]=0) */
- (*block)[0] = (JCOEF) LEFT_SHIFT(entropy->last_dc_val[ci], cinfo->Al);
+ (*block)[0] = (JCOEF)LEFT_SHIFT(entropy->last_dc_val[ci], cinfo->Al);
}
return TRUE;
@@ -323,9 +326,9 @@ decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
*/
METHODDEF(boolean)
-decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+decode_mcu_AC_first(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
JBLOCKROW block;
unsigned char *st;
int tbl, sign, k;
@@ -351,7 +354,7 @@ decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
st = entropy->ac_stats[tbl] + 3 * (k - 1);
if (arith_decode(cinfo, st)) break; /* EOB flag */
while (arith_decode(cinfo, st + 1) == 0) {
- st += 3; k++;
+ st += 3; k++;
if (k > cinfo->Se) {
WARNMS(cinfo, JWRN_ARITH_BAD_CODE);
entropy->ct = -1; /* spectral overflow */
@@ -383,9 +386,9 @@ decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
st += 14;
while (m >>= 1)
if (arith_decode(cinfo, st)) v |= m;
- v += 1; if (sign) v = -v;
+ v += 1; if (sign) v = -v;
/* Scale and output coefficient in natural (dezigzagged) order */
- (*block)[jpeg_natural_order[k]] = (JCOEF) ((unsigned)v << cinfo->Al);
+ (*block)[jpeg_natural_order[k]] = (JCOEF)((unsigned)v << cinfo->Al);
}
return TRUE;
@@ -397,9 +400,9 @@ decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
*/
METHODDEF(boolean)
-decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+decode_mcu_DC_refine(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
unsigned char *st;
int p1, blkn;
@@ -430,9 +433,9 @@ decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
*/
METHODDEF(boolean)
-decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+decode_mcu_AC_refine(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
JBLOCKROW block;
JCOEFPTR thiscoef;
unsigned char *st;
@@ -481,7 +484,7 @@ decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
*thiscoef = p1;
break;
}
- st += 3; k++;
+ st += 3; k++;
if (k > cinfo->Se) {
WARNMS(cinfo, JWRN_ARITH_BAD_CODE);
entropy->ct = -1; /* spectral overflow */
@@ -499,9 +502,9 @@ decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
*/
METHODDEF(boolean)
-decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+decode_mcu(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
jpeg_component_info *compptr;
JBLOCKROW block;
unsigned char *st;
@@ -538,7 +541,7 @@ decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
/* Figure F.21: Decoding nonzero value v */
/* Figure F.22: Decoding the sign of v */
sign = arith_decode(cinfo, st + 1);
- st += 2; st += sign;
+ st += 2; st += sign;
/* Figure F.23: Decoding the magnitude category of v */
if ((m = arith_decode(cinfo, st)) != 0) {
st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */
@@ -552,9 +555,9 @@ decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
}
}
/* Section F.1.4.4.1.2: Establish dc_context conditioning category */
- if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1))
+ if (m < (int)((1L << cinfo->arith_dc_L[tbl]) >> 1))
entropy->dc_context[ci] = 0; /* zero diff category */
- else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1))
+ else if (m > (int)((1L << cinfo->arith_dc_U[tbl]) >> 1))
entropy->dc_context[ci] = 12 + (sign * 4); /* large diff category */
else
entropy->dc_context[ci] = 4 + (sign * 4); /* small diff category */
@@ -563,12 +566,12 @@ decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
st += 14;
while (m >>= 1)
if (arith_decode(cinfo, st)) v |= m;
- v += 1; if (sign) v = -v;
- entropy->last_dc_val[ci] += v;
+ v += 1; if (sign) v = -v;
+ entropy->last_dc_val[ci] = (entropy->last_dc_val[ci] + v) & 0xffff;
}
if (block)
- (*block)[0] = (JCOEF) entropy->last_dc_val[ci];
+ (*block)[0] = (JCOEF)entropy->last_dc_val[ci];
/* Sections F.2.4.2 & F.1.4.4.2: Decoding of AC coefficients */
@@ -579,7 +582,7 @@ decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
st = entropy->ac_stats[tbl] + 3 * (k - 1);
if (arith_decode(cinfo, st)) break; /* EOB flag */
while (arith_decode(cinfo, st + 1) == 0) {
- st += 3; k++;
+ st += 3; k++;
if (k > DCTSIZE2 - 1) {
WARNMS(cinfo, JWRN_ARITH_BAD_CODE);
entropy->ct = -1; /* spectral overflow */
@@ -611,9 +614,9 @@ decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
st += 14;
while (m >>= 1)
if (arith_decode(cinfo, st)) v |= m;
- v += 1; if (sign) v = -v;
+ v += 1; if (sign) v = -v;
if (block)
- (*block)[jpeg_natural_order[k]] = (JCOEF) v;
+ (*block)[jpeg_natural_order[k]] = (JCOEF)v;
}
}
@@ -626,9 +629,9 @@ decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
*/
METHODDEF(void)
-start_pass (j_decompress_ptr cinfo)
+start_pass(j_decompress_ptr cinfo)
{
- arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ arith_entropy_ptr entropy = (arith_entropy_ptr)cinfo->entropy;
int ci, tbl;
jpeg_component_info *compptr;
@@ -647,11 +650,11 @@ start_pass (j_decompress_ptr cinfo)
}
if (cinfo->Ah != 0) {
/* Successive approximation refinement scan: must have Al = Ah-1. */
- if (cinfo->Ah-1 != cinfo->Al)
+ if (cinfo->Ah - 1 != cinfo->Al)
goto bad;
}
if (cinfo->Al > 13) { /* need not check for < 0 */
- bad:
+bad:
ERREXIT4(cinfo, JERR_BAD_PROGRESSION,
cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al);
}
@@ -661,7 +664,7 @@ start_pass (j_decompress_ptr cinfo)
*/
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
int coefi, cindex = cinfo->cur_comp_info[ci]->component_index;
- int *coef_bit_ptr = & cinfo->coef_bits[cindex][0];
+ int *coef_bit_ptr = &cinfo->coef_bits[cindex][0];
if (cinfo->Ss && coef_bit_ptr[0] < 0) /* AC without prior DC scan */
WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0);
for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) {
@@ -702,8 +705,8 @@ start_pass (j_decompress_ptr cinfo)
if (tbl < 0 || tbl >= NUM_ARITH_TBLS)
ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl);
if (entropy->dc_stats[tbl] == NULL)
- entropy->dc_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small)
- ((j_common_ptr) cinfo, JPOOL_IMAGE, DC_STAT_BINS);
+ entropy->dc_stats[tbl] = (unsigned char *)(*cinfo->mem->alloc_small)
+ ((j_common_ptr)cinfo, JPOOL_IMAGE, DC_STAT_BINS);
MEMZERO(entropy->dc_stats[tbl], DC_STAT_BINS);
/* Initialize DC predictions to 0 */
entropy->last_dc_val[ci] = 0;
@@ -714,8 +717,8 @@ start_pass (j_decompress_ptr cinfo)
if (tbl < 0 || tbl >= NUM_ARITH_TBLS)
ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl);
if (entropy->ac_stats[tbl] == NULL)
- entropy->ac_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small)
- ((j_common_ptr) cinfo, JPOOL_IMAGE, AC_STAT_BINS);
+ entropy->ac_stats[tbl] = (unsigned char *)(*cinfo->mem->alloc_small)
+ ((j_common_ptr)cinfo, JPOOL_IMAGE, AC_STAT_BINS);
MEMZERO(entropy->ac_stats[tbl], AC_STAT_BINS);
}
}
@@ -735,15 +738,15 @@ start_pass (j_decompress_ptr cinfo)
*/
GLOBAL(void)
-jinit_arith_decoder (j_decompress_ptr cinfo)
+jinit_arith_decoder(j_decompress_ptr cinfo)
{
arith_entropy_ptr entropy;
int i;
entropy = (arith_entropy_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(arith_entropy_decoder));
- cinfo->entropy = (struct jpeg_entropy_decoder *) entropy;
+ cinfo->entropy = (struct jpeg_entropy_decoder *)entropy;
entropy->pub.start_pass = start_pass;
/* Mark tables unallocated */
@@ -759,9 +762,10 @@ jinit_arith_decoder (j_decompress_ptr cinfo)
/* Create progression status table */
int *coef_bit_ptr, ci;
cinfo->coef_bits = (int (*)[DCTSIZE2])
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- cinfo->num_components*DCTSIZE2*sizeof(int));
- coef_bit_ptr = & cinfo->coef_bits[0][0];
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ cinfo->num_components * DCTSIZE2 *
+ sizeof(int));
+ coef_bit_ptr = &cinfo->coef_bits[0][0];
for (ci = 0; ci < cinfo->num_components; ci++)
for (i = 0; i < DCTSIZE2; i++)
*coef_bit_ptr++ = -1;
diff --git a/src/3rdparty/libjpeg/src/jdatadst.c b/src/3rdparty/libjpeg/src/jdatadst.c
index dcaf6f0f96..3168b9693c 100644
--- a/src/3rdparty/libjpeg/src/jdatadst.c
+++ b/src/3rdparty/libjpeg/src/jdatadst.c
@@ -24,8 +24,8 @@
#include "jerror.h"
#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc(),free() */
-extern void *malloc (size_t size);
-extern void free (void *ptr);
+extern void *malloc(size_t size);
+extern void free(void *ptr);
#endif
@@ -66,14 +66,14 @@ typedef my_mem_destination_mgr *my_mem_dest_ptr;
*/
METHODDEF(void)
-init_destination (j_compress_ptr cinfo)
+init_destination(j_compress_ptr cinfo)
{
- my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+ my_dest_ptr dest = (my_dest_ptr)cinfo->dest;
/* Allocate the output buffer --- it will be released when done with image */
dest->buffer = (JOCTET *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- OUTPUT_BUF_SIZE * sizeof(JOCTET));
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ OUTPUT_BUF_SIZE * sizeof(JOCTET));
dest->pub.next_output_byte = dest->buffer;
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
@@ -81,7 +81,7 @@ init_destination (j_compress_ptr cinfo)
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
METHODDEF(void)
-init_mem_destination (j_compress_ptr cinfo)
+init_mem_destination(j_compress_ptr cinfo)
{
/* no work necessary here */
}
@@ -112,12 +112,12 @@ init_mem_destination (j_compress_ptr cinfo)
*/
METHODDEF(boolean)
-empty_output_buffer (j_compress_ptr cinfo)
+empty_output_buffer(j_compress_ptr cinfo)
{
- my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+ my_dest_ptr dest = (my_dest_ptr)cinfo->dest;
if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) !=
- (size_t) OUTPUT_BUF_SIZE)
+ (size_t)OUTPUT_BUF_SIZE)
ERREXIT(cinfo, JERR_FILE_WRITE);
dest->pub.next_output_byte = dest->buffer;
@@ -128,15 +128,15 @@ empty_output_buffer (j_compress_ptr cinfo)
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
METHODDEF(boolean)
-empty_mem_output_buffer (j_compress_ptr cinfo)
+empty_mem_output_buffer(j_compress_ptr cinfo)
{
size_t nextsize;
JOCTET *nextbuffer;
- my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest;
+ my_mem_dest_ptr dest = (my_mem_dest_ptr)cinfo->dest;
/* Try to allocate new buffer with double size */
nextsize = dest->bufsize * 2;
- nextbuffer = (JOCTET *) malloc(nextsize);
+ nextbuffer = (JOCTET *)malloc(nextsize);
if (nextbuffer == NULL)
ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10);
@@ -169,9 +169,9 @@ empty_mem_output_buffer (j_compress_ptr cinfo)
*/
METHODDEF(void)
-term_destination (j_compress_ptr cinfo)
+term_destination(j_compress_ptr cinfo)
{
- my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+ my_dest_ptr dest = (my_dest_ptr)cinfo->dest;
size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
/* Write any data remaining in the buffer */
@@ -187,9 +187,9 @@ term_destination (j_compress_ptr cinfo)
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
METHODDEF(void)
-term_mem_destination (j_compress_ptr cinfo)
+term_mem_destination(j_compress_ptr cinfo)
{
- my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest;
+ my_mem_dest_ptr dest = (my_mem_dest_ptr)cinfo->dest;
*dest->outbuffer = dest->buffer;
*dest->outsize = (unsigned long)(dest->bufsize - dest->pub.free_in_buffer);
@@ -204,7 +204,7 @@ term_mem_destination (j_compress_ptr cinfo)
*/
GLOBAL(void)
-jpeg_stdio_dest (j_compress_ptr cinfo, FILE *outfile)
+jpeg_stdio_dest(j_compress_ptr cinfo, FILE *outfile)
{
my_dest_ptr dest;
@@ -213,7 +213,7 @@ jpeg_stdio_dest (j_compress_ptr cinfo, FILE *outfile)
*/
if (cinfo->dest == NULL) { /* first time for this JPEG object? */
cinfo->dest = (struct jpeg_destination_mgr *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
sizeof(my_destination_mgr));
} else if (cinfo->dest->init_destination != init_destination) {
/* It is unsafe to reuse the existing destination manager unless it was
@@ -225,7 +225,7 @@ jpeg_stdio_dest (j_compress_ptr cinfo, FILE *outfile)
ERREXIT(cinfo, JERR_BUFFER_SIZE);
}
- dest = (my_dest_ptr) cinfo->dest;
+ dest = (my_dest_ptr)cinfo->dest;
dest->pub.init_destination = init_destination;
dest->pub.empty_output_buffer = empty_output_buffer;
dest->pub.term_destination = term_destination;
@@ -249,8 +249,8 @@ jpeg_stdio_dest (j_compress_ptr cinfo, FILE *outfile)
*/
GLOBAL(void)
-jpeg_mem_dest (j_compress_ptr cinfo,
- unsigned char **outbuffer, unsigned long *outsize)
+jpeg_mem_dest(j_compress_ptr cinfo, unsigned char **outbuffer,
+ unsigned long *outsize)
{
my_mem_dest_ptr dest;
@@ -262,7 +262,7 @@ jpeg_mem_dest (j_compress_ptr cinfo,
*/
if (cinfo->dest == NULL) { /* first time for this JPEG object? */
cinfo->dest = (struct jpeg_destination_mgr *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
sizeof(my_mem_destination_mgr));
} else if (cinfo->dest->init_destination != init_mem_destination) {
/* It is unsafe to reuse the existing destination manager unless it was
@@ -271,7 +271,7 @@ jpeg_mem_dest (j_compress_ptr cinfo,
ERREXIT(cinfo, JERR_BUFFER_SIZE);
}
- dest = (my_mem_dest_ptr) cinfo->dest;
+ dest = (my_mem_dest_ptr)cinfo->dest;
dest->pub.init_destination = init_mem_destination;
dest->pub.empty_output_buffer = empty_mem_output_buffer;
dest->pub.term_destination = term_mem_destination;
@@ -281,7 +281,7 @@ jpeg_mem_dest (j_compress_ptr cinfo,
if (*outbuffer == NULL || *outsize == 0) {
/* Allocate initial buffer */
- dest->newbuffer = *outbuffer = (unsigned char *) malloc(OUTPUT_BUF_SIZE);
+ dest->newbuffer = *outbuffer = (unsigned char *)malloc(OUTPUT_BUF_SIZE);
if (dest->newbuffer == NULL)
ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10);
*outsize = OUTPUT_BUF_SIZE;
diff --git a/src/3rdparty/libjpeg/src/jdatasrc.c b/src/3rdparty/libjpeg/src/jdatasrc.c
index c83183fe19..eadb4a2c90 100644
--- a/src/3rdparty/libjpeg/src/jdatasrc.c
+++ b/src/3rdparty/libjpeg/src/jdatasrc.c
@@ -45,9 +45,9 @@ typedef my_source_mgr *my_src_ptr;
*/
METHODDEF(void)
-init_source (j_decompress_ptr cinfo)
+init_source(j_decompress_ptr cinfo)
{
- my_src_ptr src = (my_src_ptr) cinfo->src;
+ my_src_ptr src = (my_src_ptr)cinfo->src;
/* We reset the empty-input-file flag for each image,
* but we don't clear the input buffer.
@@ -58,7 +58,7 @@ init_source (j_decompress_ptr cinfo)
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
METHODDEF(void)
-init_mem_source (j_decompress_ptr cinfo)
+init_mem_source(j_decompress_ptr cinfo)
{
/* no work necessary here */
}
@@ -99,9 +99,9 @@ init_mem_source (j_decompress_ptr cinfo)
*/
METHODDEF(boolean)
-fill_input_buffer (j_decompress_ptr cinfo)
+fill_input_buffer(j_decompress_ptr cinfo)
{
- my_src_ptr src = (my_src_ptr) cinfo->src;
+ my_src_ptr src = (my_src_ptr)cinfo->src;
size_t nbytes;
nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE);
@@ -111,8 +111,8 @@ fill_input_buffer (j_decompress_ptr cinfo)
ERREXIT(cinfo, JERR_INPUT_EMPTY);
WARNMS(cinfo, JWRN_JPEG_EOF);
/* Insert a fake EOI marker */
- src->buffer[0] = (JOCTET) 0xFF;
- src->buffer[1] = (JOCTET) JPEG_EOI;
+ src->buffer[0] = (JOCTET)0xFF;
+ src->buffer[1] = (JOCTET)JPEG_EOI;
nbytes = 2;
}
@@ -125,10 +125,10 @@ fill_input_buffer (j_decompress_ptr cinfo)
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
METHODDEF(boolean)
-fill_mem_input_buffer (j_decompress_ptr cinfo)
+fill_mem_input_buffer(j_decompress_ptr cinfo)
{
static const JOCTET mybuffer[4] = {
- (JOCTET) 0xFF, (JOCTET) JPEG_EOI, 0, 0
+ (JOCTET)0xFF, (JOCTET)JPEG_EOI, 0, 0
};
/* The whole JPEG data is expected to reside in the supplied memory
@@ -160,7 +160,7 @@ fill_mem_input_buffer (j_decompress_ptr cinfo)
*/
METHODDEF(void)
-skip_input_data (j_decompress_ptr cinfo, long num_bytes)
+skip_input_data(j_decompress_ptr cinfo, long num_bytes)
{
struct jpeg_source_mgr *src = cinfo->src;
@@ -169,15 +169,15 @@ skip_input_data (j_decompress_ptr cinfo, long num_bytes)
* any trouble anyway --- large skips are infrequent.
*/
if (num_bytes > 0) {
- while (num_bytes > (long) src->bytes_in_buffer) {
- num_bytes -= (long) src->bytes_in_buffer;
- (void) (*src->fill_input_buffer) (cinfo);
+ while (num_bytes > (long)src->bytes_in_buffer) {
+ num_bytes -= (long)src->bytes_in_buffer;
+ (void)(*src->fill_input_buffer) (cinfo);
/* note we assume that fill_input_buffer will never return FALSE,
* so suspension need not be handled.
*/
}
- src->next_input_byte += (size_t) num_bytes;
- src->bytes_in_buffer -= (size_t) num_bytes;
+ src->next_input_byte += (size_t)num_bytes;
+ src->bytes_in_buffer -= (size_t)num_bytes;
}
}
@@ -201,7 +201,7 @@ skip_input_data (j_decompress_ptr cinfo, long num_bytes)
*/
METHODDEF(void)
-term_source (j_decompress_ptr cinfo)
+term_source(j_decompress_ptr cinfo)
{
/* no work necessary here */
}
@@ -214,7 +214,7 @@ term_source (j_decompress_ptr cinfo)
*/
GLOBAL(void)
-jpeg_stdio_src (j_decompress_ptr cinfo, FILE *infile)
+jpeg_stdio_src(j_decompress_ptr cinfo, FILE *infile)
{
my_src_ptr src;
@@ -225,11 +225,11 @@ jpeg_stdio_src (j_decompress_ptr cinfo, FILE *infile)
*/
if (cinfo->src == NULL) { /* first time for this JPEG object? */
cinfo->src = (struct jpeg_source_mgr *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
sizeof(my_source_mgr));
- src = (my_src_ptr) cinfo->src;
+ src = (my_src_ptr)cinfo->src;
src->buffer = (JOCTET *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
INPUT_BUF_SIZE * sizeof(JOCTET));
} else if (cinfo->src->init_source != init_source) {
/* It is unsafe to reuse the existing source manager unless it was created
@@ -241,7 +241,7 @@ jpeg_stdio_src (j_decompress_ptr cinfo, FILE *infile)
ERREXIT(cinfo, JERR_BUFFER_SIZE);
}
- src = (my_src_ptr) cinfo->src;
+ src = (my_src_ptr)cinfo->src;
src->pub.init_source = init_source;
src->pub.fill_input_buffer = fill_input_buffer;
src->pub.skip_input_data = skip_input_data;
@@ -260,8 +260,8 @@ jpeg_stdio_src (j_decompress_ptr cinfo, FILE *infile)
*/
GLOBAL(void)
-jpeg_mem_src (j_decompress_ptr cinfo,
- const unsigned char *inbuffer, unsigned long insize)
+jpeg_mem_src(j_decompress_ptr cinfo, const unsigned char *inbuffer,
+ unsigned long insize)
{
struct jpeg_source_mgr *src;
@@ -274,7 +274,7 @@ jpeg_mem_src (j_decompress_ptr cinfo,
*/
if (cinfo->src == NULL) { /* first time for this JPEG object? */
cinfo->src = (struct jpeg_source_mgr *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
sizeof(struct jpeg_source_mgr));
} else if (cinfo->src->init_source != init_mem_source) {
/* It is unsafe to reuse the existing source manager unless it was created
@@ -289,7 +289,7 @@ jpeg_mem_src (j_decompress_ptr cinfo,
src->skip_input_data = skip_input_data;
src->resync_to_restart = jpeg_resync_to_restart; /* use default method */
src->term_source = term_source;
- src->bytes_in_buffer = (size_t) insize;
- src->next_input_byte = (const JOCTET *) inbuffer;
+ src->bytes_in_buffer = (size_t)insize;
+ src->next_input_byte = (const JOCTET *)inbuffer;
}
#endif
diff --git a/src/3rdparty/libjpeg/src/jdcoefct.c b/src/3rdparty/libjpeg/src/jdcoefct.c
index 1a48969b83..723a9ac2be 100644
--- a/src/3rdparty/libjpeg/src/jdcoefct.c
+++ b/src/3rdparty/libjpeg/src/jdcoefct.c
@@ -25,16 +25,15 @@
/* Forward declarations */
-METHODDEF(int) decompress_onepass
- (j_decompress_ptr cinfo, JSAMPIMAGE output_buf);
+METHODDEF(int) decompress_onepass(j_decompress_ptr cinfo,
+ JSAMPIMAGE output_buf);
#ifdef D_MULTISCAN_FILES_SUPPORTED
-METHODDEF(int) decompress_data
- (j_decompress_ptr cinfo, JSAMPIMAGE output_buf);
+METHODDEF(int) decompress_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf);
#endif
#ifdef BLOCK_SMOOTHING_SUPPORTED
-LOCAL(boolean) smoothing_ok (j_decompress_ptr cinfo);
-METHODDEF(int) decompress_smooth_data
- (j_decompress_ptr cinfo, JSAMPIMAGE output_buf);
+LOCAL(boolean) smoothing_ok(j_decompress_ptr cinfo);
+METHODDEF(int) decompress_smooth_data(j_decompress_ptr cinfo,
+ JSAMPIMAGE output_buf);
#endif
@@ -43,7 +42,7 @@ METHODDEF(int) decompress_smooth_data
*/
METHODDEF(void)
-start_input_pass (j_decompress_ptr cinfo)
+start_input_pass(j_decompress_ptr cinfo)
{
cinfo->input_iMCU_row = 0;
start_iMCU_row(cinfo);
@@ -55,10 +54,10 @@ start_input_pass (j_decompress_ptr cinfo)
*/
METHODDEF(void)
-start_output_pass (j_decompress_ptr cinfo)
+start_output_pass(j_decompress_ptr cinfo)
{
#ifdef BLOCK_SMOOTHING_SUPPORTED
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
/* If multipass, check to see whether to use block smoothing on this pass */
if (coef->pub.coef_arrays != NULL) {
@@ -83,9 +82,9 @@ start_output_pass (j_decompress_ptr cinfo)
*/
METHODDEF(int)
-decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
+decompress_onepass(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
JDIMENSION MCU_col_num; /* index of current MCU within row */
JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
@@ -101,9 +100,9 @@ decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col;
MCU_col_num++) {
/* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */
- jzero_far((void *) coef->MCU_buffer[0],
- (size_t) (cinfo->blocks_in_MCU * sizeof(JBLOCK)));
- if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
+ jzero_far((void *)coef->MCU_buffer[0],
+ (size_t)(cinfo->blocks_in_MCU * sizeof(JBLOCK)));
+ if (!(*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
/* Suspension forced; update state counters and exit */
coef->MCU_vert_offset = yoffset;
coef->MCU_ctr = MCU_col_num;
@@ -120,28 +119,28 @@ decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
* incremented past them!). Note the inner loop relies on having
* allocated the MCU_buffer[] blocks sequentially.
*/
- blkn = 0; /* index of current DCT block within MCU */
+ blkn = 0; /* index of current DCT block within MCU */
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
/* Don't bother to IDCT an uninteresting component. */
- if (! compptr->component_needed) {
+ if (!compptr->component_needed) {
blkn += compptr->MCU_blocks;
continue;
}
inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index];
- useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
- : compptr->last_col_width;
+ useful_width = (MCU_col_num < last_MCU_col) ?
+ compptr->MCU_width : compptr->last_col_width;
output_ptr = output_buf[compptr->component_index] +
- yoffset * compptr->_DCT_scaled_size;
+ yoffset * compptr->_DCT_scaled_size;
start_col = (MCU_col_num - cinfo->master->first_iMCU_col) *
- compptr->MCU_sample_width;
+ compptr->MCU_sample_width;
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
if (cinfo->input_iMCU_row < last_iMCU_row ||
- yoffset+yindex < compptr->last_row_height) {
+ yoffset + yindex < compptr->last_row_height) {
output_col = start_col;
for (xindex = 0; xindex < useful_width; xindex++) {
(*inverse_DCT) (cinfo, compptr,
- (JCOEFPTR) coef->MCU_buffer[blkn+xindex],
+ (JCOEFPTR)coef->MCU_buffer[blkn + xindex],
output_ptr, output_col);
output_col += compptr->_DCT_scaled_size;
}
@@ -172,7 +171,7 @@ decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
*/
METHODDEF(int)
-dummy_consume_data (j_decompress_ptr cinfo)
+dummy_consume_data(j_decompress_ptr cinfo)
{
return JPEG_SUSPENDED; /* Always indicate nothing was done */
}
@@ -188,9 +187,9 @@ dummy_consume_data (j_decompress_ptr cinfo)
*/
METHODDEF(int)
-consume_data (j_decompress_ptr cinfo)
+consume_data(j_decompress_ptr cinfo)
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
JDIMENSION MCU_col_num; /* index of current MCU within row */
int blkn, ci, xindex, yindex, yoffset;
JDIMENSION start_col;
@@ -202,9 +201,9 @@ consume_data (j_decompress_ptr cinfo)
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
compptr = cinfo->cur_comp_info[ci];
buffer[ci] = (*cinfo->mem->access_virt_barray)
- ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
+ ((j_common_ptr)cinfo, coef->whole_image[compptr->component_index],
cinfo->input_iMCU_row * compptr->v_samp_factor,
- (JDIMENSION) compptr->v_samp_factor, TRUE);
+ (JDIMENSION)compptr->v_samp_factor, TRUE);
/* Note: entropy decoder expects buffer to be zeroed,
* but this is handled automatically by the memory manager
* because we requested a pre-zeroed array.
@@ -222,14 +221,14 @@ consume_data (j_decompress_ptr cinfo)
compptr = cinfo->cur_comp_info[ci];
start_col = MCU_col_num * compptr->MCU_width;
for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
- buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
+ buffer_ptr = buffer[ci][yindex + yoffset] + start_col;
for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
coef->MCU_buffer[blkn++] = buffer_ptr++;
}
}
}
/* Try to fetch the MCU. */
- if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
+ if (!(*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
/* Suspension forced; update state counters and exit */
coef->MCU_vert_offset = yoffset;
coef->MCU_ctr = MCU_col_num;
@@ -259,9 +258,9 @@ consume_data (j_decompress_ptr cinfo)
*/
METHODDEF(int)
-decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
+decompress_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
JDIMENSION block_num;
int ci, block_row, block_rows;
@@ -276,7 +275,7 @@ decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
while (cinfo->input_scan_number < cinfo->output_scan_number ||
(cinfo->input_scan_number == cinfo->output_scan_number &&
cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) {
- if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED)
+ if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
return JPEG_SUSPENDED;
}
@@ -284,19 +283,19 @@ decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Don't bother to IDCT an uninteresting component. */
- if (! compptr->component_needed)
+ if (!compptr->component_needed)
continue;
/* Align the virtual buffer for this component. */
buffer = (*cinfo->mem->access_virt_barray)
- ((j_common_ptr) cinfo, coef->whole_image[ci],
+ ((j_common_ptr)cinfo, coef->whole_image[ci],
cinfo->output_iMCU_row * compptr->v_samp_factor,
- (JDIMENSION) compptr->v_samp_factor, FALSE);
+ (JDIMENSION)compptr->v_samp_factor, FALSE);
/* Count non-dummy DCT block rows in this iMCU row. */
if (cinfo->output_iMCU_row < last_iMCU_row)
block_rows = compptr->v_samp_factor;
else {
/* NB: can't use last_row_height here; it is input-side-dependent! */
- block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
+ block_rows = (int)(compptr->height_in_blocks % compptr->v_samp_factor);
if (block_rows == 0) block_rows = compptr->v_samp_factor;
}
inverse_DCT = cinfo->idct->inverse_DCT[ci];
@@ -307,8 +306,8 @@ decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
output_col = 0;
for (block_num = cinfo->master->first_MCU_col[ci];
block_num <= cinfo->master->last_MCU_col[ci]; block_num++) {
- (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr,
- output_ptr, output_col);
+ (*inverse_DCT) (cinfo, compptr, (JCOEFPTR)buffer_ptr, output_ptr,
+ output_col);
buffer_ptr++;
output_col += compptr->_DCT_scaled_size;
}
@@ -350,9 +349,9 @@ decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
*/
LOCAL(boolean)
-smoothing_ok (j_decompress_ptr cinfo)
+smoothing_ok(j_decompress_ptr cinfo)
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
boolean smoothing_useful = FALSE;
int ci, coefi;
jpeg_component_info *compptr;
@@ -360,13 +359,13 @@ smoothing_ok (j_decompress_ptr cinfo)
int *coef_bits;
int *coef_bits_latch;
- if (! cinfo->progressive_mode || cinfo->coef_bits == NULL)
+ if (!cinfo->progressive_mode || cinfo->coef_bits == NULL)
return FALSE;
/* Allocate latch area if not already done */
if (coef->coef_bits_latch == NULL)
coef->coef_bits_latch = (int *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
cinfo->num_components *
(SAVED_COEFS * sizeof(int)));
coef_bits_latch = coef->coef_bits_latch;
@@ -406,9 +405,9 @@ smoothing_ok (j_decompress_ptr cinfo)
*/
METHODDEF(int)
-decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
+decompress_smooth_data(j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
JDIMENSION block_num, last_block_column;
int ci, block_row, block_rows, access_rows;
@@ -422,8 +421,8 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
JCOEF *workspace;
int *coef_bits;
JQUANT_TBL *quanttbl;
- JLONG Q00,Q01,Q02,Q10,Q11,Q20, num;
- int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9;
+ JLONG Q00, Q01, Q02, Q10, Q11, Q20, num;
+ int DC1, DC2, DC3, DC4, DC5, DC6, DC7, DC8, DC9;
int Al, pred;
/* Keep a local variable to avoid looking it up more than once */
@@ -431,7 +430,7 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
/* Force some input to be done if we are getting ahead of the input. */
while (cinfo->input_scan_number <= cinfo->output_scan_number &&
- ! cinfo->inputctl->eoi_reached) {
+ !cinfo->inputctl->eoi_reached) {
if (cinfo->input_scan_number == cinfo->output_scan_number) {
/* If input is working on current scan, we ordinarily want it to
* have completed the current row. But if input scan is DC,
@@ -439,10 +438,10 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
* values are up to date.
*/
JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0;
- if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta)
+ if (cinfo->input_iMCU_row > cinfo->output_iMCU_row + delta)
break;
}
- if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED)
+ if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
return JPEG_SUSPENDED;
}
@@ -450,7 +449,7 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Don't bother to IDCT an uninteresting component. */
- if (! compptr->component_needed)
+ if (!compptr->component_needed)
continue;
/* Count non-dummy DCT block rows in this iMCU row. */
if (cinfo->output_iMCU_row < last_iMCU_row) {
@@ -459,7 +458,7 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
last_row = FALSE;
} else {
/* NB: can't use last_row_height here; it is input-side-dependent! */
- block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
+ block_rows = (int)(compptr->height_in_blocks % compptr->v_samp_factor);
if (block_rows == 0) block_rows = compptr->v_samp_factor;
access_rows = block_rows; /* this iMCU row only */
last_row = TRUE;
@@ -468,15 +467,15 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
if (cinfo->output_iMCU_row > 0) {
access_rows += compptr->v_samp_factor; /* prior iMCU row too */
buffer = (*cinfo->mem->access_virt_barray)
- ((j_common_ptr) cinfo, coef->whole_image[ci],
+ ((j_common_ptr)cinfo, coef->whole_image[ci],
(cinfo->output_iMCU_row - 1) * compptr->v_samp_factor,
- (JDIMENSION) access_rows, FALSE);
+ (JDIMENSION)access_rows, FALSE);
buffer += compptr->v_samp_factor; /* point to current iMCU row */
first_row = FALSE;
} else {
buffer = (*cinfo->mem->access_virt_barray)
- ((j_common_ptr) cinfo, coef->whole_image[ci],
- (JDIMENSION) 0, (JDIMENSION) access_rows, FALSE);
+ ((j_common_ptr)cinfo, coef->whole_image[ci],
+ (JDIMENSION)0, (JDIMENSION)access_rows, FALSE);
first_row = TRUE;
}
/* Fetch component-dependent info */
@@ -496,115 +495,115 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
if (first_row && block_row == 0)
prev_block_row = buffer_ptr;
else
- prev_block_row = buffer[block_row-1];
- if (last_row && block_row == block_rows-1)
+ prev_block_row = buffer[block_row - 1];
+ if (last_row && block_row == block_rows - 1)
next_block_row = buffer_ptr;
else
- next_block_row = buffer[block_row+1];
+ next_block_row = buffer[block_row + 1];
/* We fetch the surrounding DC values using a sliding-register approach.
* Initialize all nine here so as to do the right thing on narrow pics.
*/
- DC1 = DC2 = DC3 = (int) prev_block_row[0][0];
- DC4 = DC5 = DC6 = (int) buffer_ptr[0][0];
- DC7 = DC8 = DC9 = (int) next_block_row[0][0];
+ DC1 = DC2 = DC3 = (int)prev_block_row[0][0];
+ DC4 = DC5 = DC6 = (int)buffer_ptr[0][0];
+ DC7 = DC8 = DC9 = (int)next_block_row[0][0];
output_col = 0;
last_block_column = compptr->width_in_blocks - 1;
for (block_num = cinfo->master->first_MCU_col[ci];
block_num <= cinfo->master->last_MCU_col[ci]; block_num++) {
/* Fetch current DCT block into workspace so we can modify it. */
- jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1);
+ jcopy_block_row(buffer_ptr, (JBLOCKROW)workspace, (JDIMENSION)1);
/* Update DC values */
if (block_num < last_block_column) {
- DC3 = (int) prev_block_row[1][0];
- DC6 = (int) buffer_ptr[1][0];
- DC9 = (int) next_block_row[1][0];
+ DC3 = (int)prev_block_row[1][0];
+ DC6 = (int)buffer_ptr[1][0];
+ DC9 = (int)next_block_row[1][0];
}
/* Compute coefficient estimates per K.8.
* An estimate is applied only if coefficient is still zero,
* and is not known to be fully accurate.
*/
/* AC01 */
- if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) {
+ if ((Al = coef_bits[1]) != 0 && workspace[1] == 0) {
num = 36 * Q00 * (DC4 - DC6);
if (num >= 0) {
- pred = (int) (((Q01<<7) + num) / (Q01<<8));
- if (Al > 0 && pred >= (1<<Al))
- pred = (1<<Al)-1;
+ pred = (int)(((Q01 << 7) + num) / (Q01 << 8));
+ if (Al > 0 && pred >= (1 << Al))
+ pred = (1 << Al) - 1;
} else {
- pred = (int) (((Q01<<7) - num) / (Q01<<8));
- if (Al > 0 && pred >= (1<<Al))
- pred = (1<<Al)-1;
+ pred = (int)(((Q01 << 7) - num) / (Q01 << 8));
+ if (Al > 0 && pred >= (1 << Al))
+ pred = (1 << Al) - 1;
pred = -pred;
}
- workspace[1] = (JCOEF) pred;
+ workspace[1] = (JCOEF)pred;
}
/* AC10 */
- if ((Al=coef_bits[2]) != 0 && workspace[8] == 0) {
+ if ((Al = coef_bits[2]) != 0 && workspace[8] == 0) {
num = 36 * Q00 * (DC2 - DC8);
if (num >= 0) {
- pred = (int) (((Q10<<7) + num) / (Q10<<8));
- if (Al > 0 && pred >= (1<<Al))
- pred = (1<<Al)-1;
+ pred = (int)(((Q10 << 7) + num) / (Q10 << 8));
+ if (Al > 0 && pred >= (1 << Al))
+ pred = (1 << Al) - 1;
} else {
- pred = (int) (((Q10<<7) - num) / (Q10<<8));
- if (Al > 0 && pred >= (1<<Al))
- pred = (1<<Al)-1;
+ pred = (int)(((Q10 << 7) - num) / (Q10 << 8));
+ if (Al > 0 && pred >= (1 << Al))
+ pred = (1 << Al) - 1;
pred = -pred;
}
- workspace[8] = (JCOEF) pred;
+ workspace[8] = (JCOEF)pred;
}
/* AC20 */
- if ((Al=coef_bits[3]) != 0 && workspace[16] == 0) {
- num = 9 * Q00 * (DC2 + DC8 - 2*DC5);
+ if ((Al = coef_bits[3]) != 0 && workspace[16] == 0) {
+ num = 9 * Q00 * (DC2 + DC8 - 2 * DC5);
if (num >= 0) {
- pred = (int) (((Q20<<7) + num) / (Q20<<8));
- if (Al > 0 && pred >= (1<<Al))
- pred = (1<<Al)-1;
+ pred = (int)(((Q20 << 7) + num) / (Q20 << 8));
+ if (Al > 0 && pred >= (1 << Al))
+ pred = (1 << Al) - 1;
} else {
- pred = (int) (((Q20<<7) - num) / (Q20<<8));
- if (Al > 0 && pred >= (1<<Al))
- pred = (1<<Al)-1;
+ pred = (int)(((Q20 << 7) - num) / (Q20 << 8));
+ if (Al > 0 && pred >= (1 << Al))
+ pred = (1 << Al) - 1;
pred = -pred;
}
- workspace[16] = (JCOEF) pred;
+ workspace[16] = (JCOEF)pred;
}
/* AC11 */
- if ((Al=coef_bits[4]) != 0 && workspace[9] == 0) {
+ if ((Al = coef_bits[4]) != 0 && workspace[9] == 0) {
num = 5 * Q00 * (DC1 - DC3 - DC7 + DC9);
if (num >= 0) {
- pred = (int) (((Q11<<7) + num) / (Q11<<8));
- if (Al > 0 && pred >= (1<<Al))
- pred = (1<<Al)-1;
+ pred = (int)(((Q11 << 7) + num) / (Q11 << 8));
+ if (Al > 0 && pred >= (1 << Al))
+ pred = (1 << Al) - 1;
} else {
- pred = (int) (((Q11<<7) - num) / (Q11<<8));
- if (Al > 0 && pred >= (1<<Al))
- pred = (1<<Al)-1;
+ pred = (int)(((Q11 << 7) - num) / (Q11 << 8));
+ if (Al > 0 && pred >= (1 << Al))
+ pred = (1 << Al) - 1;
pred = -pred;
}
- workspace[9] = (JCOEF) pred;
+ workspace[9] = (JCOEF)pred;
}
/* AC02 */
- if ((Al=coef_bits[5]) != 0 && workspace[2] == 0) {
- num = 9 * Q00 * (DC4 + DC6 - 2*DC5);
+ if ((Al = coef_bits[5]) != 0 && workspace[2] == 0) {
+ num = 9 * Q00 * (DC4 + DC6 - 2 * DC5);
if (num >= 0) {
- pred = (int) (((Q02<<7) + num) / (Q02<<8));
- if (Al > 0 && pred >= (1<<Al))
- pred = (1<<Al)-1;
+ pred = (int)(((Q02 << 7) + num) / (Q02 << 8));
+ if (Al > 0 && pred >= (1 << Al))
+ pred = (1 << Al) - 1;
} else {
- pred = (int) (((Q02<<7) - num) / (Q02<<8));
- if (Al > 0 && pred >= (1<<Al))
- pred = (1<<Al)-1;
+ pred = (int)(((Q02 << 7) - num) / (Q02 << 8));
+ if (Al > 0 && pred >= (1 << Al))
+ pred = (1 << Al) - 1;
pred = -pred;
}
- workspace[2] = (JCOEF) pred;
+ workspace[2] = (JCOEF)pred;
}
/* OK, do the IDCT */
- (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) workspace,
- output_ptr, output_col);
+ (*inverse_DCT) (cinfo, compptr, (JCOEFPTR)workspace, output_ptr,
+ output_col);
/* Advance for next column */
- DC1 = DC2; DC2 = DC3;
- DC4 = DC5; DC5 = DC6;
- DC7 = DC8; DC8 = DC9;
+ DC1 = DC2; DC2 = DC3;
+ DC4 = DC5; DC5 = DC6;
+ DC7 = DC8; DC8 = DC9;
buffer_ptr++, prev_block_row++, next_block_row++;
output_col += compptr->_DCT_scaled_size;
}
@@ -625,14 +624,14 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
*/
GLOBAL(void)
-jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
+jinit_d_coef_controller(j_decompress_ptr cinfo, boolean need_full_buffer)
{
my_coef_ptr coef;
coef = (my_coef_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_coef_controller));
- cinfo->coef = (struct jpeg_d_coef_controller *) coef;
+ cinfo->coef = (struct jpeg_d_coef_controller *)coef;
coef->pub.start_input_pass = start_input_pass;
coef->pub.start_output_pass = start_output_pass;
#ifdef BLOCK_SMOOTHING_SUPPORTED
@@ -657,12 +656,12 @@ jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
access_rows *= 3;
#endif
coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
- ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE,
- (JDIMENSION) jround_up((long) compptr->width_in_blocks,
- (long) compptr->h_samp_factor),
- (JDIMENSION) jround_up((long) compptr->height_in_blocks,
- (long) compptr->v_samp_factor),
- (JDIMENSION) access_rows);
+ ((j_common_ptr)cinfo, JPOOL_IMAGE, TRUE,
+ (JDIMENSION)jround_up((long)compptr->width_in_blocks,
+ (long)compptr->h_samp_factor),
+ (JDIMENSION)jround_up((long)compptr->height_in_blocks,
+ (long)compptr->v_samp_factor),
+ (JDIMENSION)access_rows);
}
coef->pub.consume_data = consume_data;
coef->pub.decompress_data = decompress_data;
@@ -676,7 +675,7 @@ jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
int i;
buffer = (JBLOCKROW)
- (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_large) ((j_common_ptr)cinfo, JPOOL_IMAGE,
D_MAX_BLOCKS_IN_MCU * sizeof(JBLOCK));
for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) {
coef->MCU_buffer[i] = buffer + i;
@@ -688,6 +687,6 @@ jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
/* Allocate the workspace buffer */
coef->workspace = (JCOEF *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(JCOEF) * DCTSIZE2);
}
diff --git a/src/3rdparty/libjpeg/src/jdcoefct.h b/src/3rdparty/libjpeg/src/jdcoefct.h
index bf6beb274b..c4d1943dd4 100644
--- a/src/3rdparty/libjpeg/src/jdcoefct.h
+++ b/src/3rdparty/libjpeg/src/jdcoefct.h
@@ -59,10 +59,10 @@ typedef my_coef_controller *my_coef_ptr;
LOCAL(void)
-start_iMCU_row (j_decompress_ptr cinfo)
+start_iMCU_row(j_decompress_ptr cinfo)
/* Reset within-iMCU-row counters for a new row (input side) */
{
- my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ my_coef_ptr coef = (my_coef_ptr)cinfo->coef;
/* In an interleaved scan, an MCU row is the same as an iMCU row.
* In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
@@ -71,7 +71,7 @@ start_iMCU_row (j_decompress_ptr cinfo)
if (cinfo->comps_in_scan > 1) {
coef->MCU_rows_per_iMCU_row = 1;
} else {
- if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1))
+ if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows - 1))
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
else
coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
diff --git a/src/3rdparty/libjpeg/src/jdcol565.c b/src/3rdparty/libjpeg/src/jdcol565.c
index 349fce4a66..40068ef84f 100644
--- a/src/3rdparty/libjpeg/src/jdcol565.c
+++ b/src/3rdparty/libjpeg/src/jdcol565.c
@@ -17,22 +17,22 @@
INLINE
LOCAL(void)
-ycc_rgb565_convert_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+ycc_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf,
+ int num_rows)
{
- my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int y, cb, cr;
register JSAMPROW outptr;
register JSAMPROW inptr0, inptr1, inptr2;
register JDIMENSION col;
JDIMENSION num_cols = cinfo->output_width;
/* copy these pointers into registers if possible */
- register JSAMPLE * range_limit = cinfo->sample_range_limit;
- register int * Crrtab = cconvert->Cr_r_tab;
- register int * Cbbtab = cconvert->Cb_b_tab;
- register JLONG * Crgtab = cconvert->Cr_g_tab;
- register JLONG * Cbgtab = cconvert->Cb_g_tab;
+ register JSAMPLE *range_limit = cinfo->sample_range_limit;
+ register int *Crrtab = cconvert->Cr_r_tab;
+ register int *Cbbtab = cconvert->Cb_b_tab;
+ register JLONG *Crgtab = cconvert->Cr_g_tab;
+ register JLONG *Cbgtab = cconvert->Cb_g_tab;
SHIFT_TEMPS
while (--num_rows >= 0) {
@@ -53,7 +53,7 @@ ycc_rgb565_convert_internal (j_decompress_ptr cinfo,
SCALEBITS))];
b = range_limit[y + Cbbtab[cb]];
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
outptr += 2;
num_cols--;
}
@@ -88,7 +88,7 @@ ycc_rgb565_convert_internal (j_decompress_ptr cinfo,
SCALEBITS))];
b = range_limit[y + Cbbtab[cb]];
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
}
}
}
@@ -96,22 +96,22 @@ ycc_rgb565_convert_internal (j_decompress_ptr cinfo,
INLINE
LOCAL(void)
-ycc_rgb565D_convert_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+ycc_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf,
+ int num_rows)
{
- my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int y, cb, cr;
register JSAMPROW outptr;
register JSAMPROW inptr0, inptr1, inptr2;
register JDIMENSION col;
JDIMENSION num_cols = cinfo->output_width;
/* copy these pointers into registers if possible */
- register JSAMPLE * range_limit = cinfo->sample_range_limit;
- register int * Crrtab = cconvert->Cr_r_tab;
- register int * Cbbtab = cconvert->Cb_b_tab;
- register JLONG * Crgtab = cconvert->Cr_g_tab;
- register JLONG * Cbgtab = cconvert->Cb_g_tab;
+ register JSAMPLE *range_limit = cinfo->sample_range_limit;
+ register int *Crrtab = cconvert->Cr_r_tab;
+ register int *Cbbtab = cconvert->Cb_b_tab;
+ register JLONG *Crgtab = cconvert->Cr_g_tab;
+ register JLONG *Cbgtab = cconvert->Cb_g_tab;
JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
SHIFT_TEMPS
@@ -134,7 +134,7 @@ ycc_rgb565D_convert_internal (j_decompress_ptr cinfo,
SCALEBITS)), d0)];
b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)];
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
outptr += 2;
num_cols--;
}
@@ -174,7 +174,7 @@ ycc_rgb565D_convert_internal (j_decompress_ptr cinfo,
SCALEBITS)), d0)];
b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)];
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
}
}
}
@@ -182,9 +182,9 @@ ycc_rgb565D_convert_internal (j_decompress_ptr cinfo,
INLINE
LOCAL(void)
-rgb_rgb565_convert_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+rgb_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf,
+ int num_rows)
{
register JSAMPROW outptr;
register JSAMPROW inptr0, inptr1, inptr2;
@@ -206,7 +206,7 @@ rgb_rgb565_convert_internal (j_decompress_ptr cinfo,
g = GETJSAMPLE(*inptr1++);
b = GETJSAMPLE(*inptr2++);
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
outptr += 2;
num_cols--;
}
@@ -229,7 +229,7 @@ rgb_rgb565_convert_internal (j_decompress_ptr cinfo,
g = GETJSAMPLE(*inptr1);
b = GETJSAMPLE(*inptr2);
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
}
}
}
@@ -237,14 +237,14 @@ rgb_rgb565_convert_internal (j_decompress_ptr cinfo,
INLINE
LOCAL(void)
-rgb_rgb565D_convert_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+rgb_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf,
+ int num_rows)
{
register JSAMPROW outptr;
register JSAMPROW inptr0, inptr1, inptr2;
register JDIMENSION col;
- register JSAMPLE * range_limit = cinfo->sample_range_limit;
+ register JSAMPLE *range_limit = cinfo->sample_range_limit;
JDIMENSION num_cols = cinfo->output_width;
JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
SHIFT_TEMPS
@@ -263,7 +263,7 @@ rgb_rgb565D_convert_internal (j_decompress_ptr cinfo,
g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1++), d0)];
b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2++), d0)];
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
outptr += 2;
num_cols--;
}
@@ -288,7 +288,7 @@ rgb_rgb565D_convert_internal (j_decompress_ptr cinfo,
g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1), d0)];
b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2), d0)];
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
}
}
}
@@ -296,9 +296,9 @@ rgb_rgb565D_convert_internal (j_decompress_ptr cinfo,
INLINE
LOCAL(void)
-gray_rgb565_convert_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+gray_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf,
+ int num_rows)
{
register JSAMPROW inptr, outptr;
register JDIMENSION col;
@@ -313,7 +313,7 @@ gray_rgb565_convert_internal (j_decompress_ptr cinfo,
if (PACK_NEED_ALIGNMENT(outptr)) {
g = *inptr++;
rgb = PACK_SHORT_565(g, g, g);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
outptr += 2;
num_cols--;
}
@@ -328,7 +328,7 @@ gray_rgb565_convert_internal (j_decompress_ptr cinfo,
if (num_cols & 1) {
g = *inptr;
rgb = PACK_SHORT_565(g, g, g);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
}
}
}
@@ -336,13 +336,13 @@ gray_rgb565_convert_internal (j_decompress_ptr cinfo,
INLINE
LOCAL(void)
-gray_rgb565D_convert_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+gray_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf,
+ int num_rows)
{
register JSAMPROW inptr, outptr;
register JDIMENSION col;
- register JSAMPLE * range_limit = cinfo->sample_range_limit;
+ register JSAMPLE *range_limit = cinfo->sample_range_limit;
JDIMENSION num_cols = cinfo->output_width;
JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
@@ -356,7 +356,7 @@ gray_rgb565D_convert_internal (j_decompress_ptr cinfo,
g = *inptr++;
g = range_limit[DITHER_565_R(g, d0)];
rgb = PACK_SHORT_565(g, g, g);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
outptr += 2;
num_cols--;
}
@@ -378,7 +378,7 @@ gray_rgb565D_convert_internal (j_decompress_ptr cinfo,
g = *inptr;
g = range_limit[DITHER_565_R(g, d0)];
rgb = PACK_SHORT_565(g, g, g);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
}
}
}
diff --git a/src/3rdparty/libjpeg/src/jdcolext.c b/src/3rdparty/libjpeg/src/jdcolext.c
index 59b676cc4d..72a5301070 100644
--- a/src/3rdparty/libjpeg/src/jdcolext.c
+++ b/src/3rdparty/libjpeg/src/jdcolext.c
@@ -28,22 +28,22 @@
INLINE
LOCAL(void)
-ycc_rgb_convert_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+ycc_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf,
+ int num_rows)
{
- my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int y, cb, cr;
register JSAMPROW outptr;
register JSAMPROW inptr0, inptr1, inptr2;
register JDIMENSION col;
JDIMENSION num_cols = cinfo->output_width;
/* copy these pointers into registers if possible */
- register JSAMPLE * range_limit = cinfo->sample_range_limit;
- register int * Crrtab = cconvert->Cr_r_tab;
- register int * Cbbtab = cconvert->Cb_b_tab;
- register JLONG * Crgtab = cconvert->Cr_g_tab;
- register JLONG * Cbgtab = cconvert->Cb_g_tab;
+ register JSAMPLE *range_limit = cinfo->sample_range_limit;
+ register int *Crrtab = cconvert->Cr_r_tab;
+ register int *Cbbtab = cconvert->Cb_b_tab;
+ register JLONG *Crgtab = cconvert->Cr_g_tab;
+ register JLONG *Cbgtab = cconvert->Cb_g_tab;
SHIFT_TEMPS
while (--num_rows >= 0) {
@@ -59,8 +59,8 @@ ycc_rgb_convert_internal (j_decompress_ptr cinfo,
/* Range-limiting is essential due to noise introduced by DCT losses. */
outptr[RGB_RED] = range_limit[y + Crrtab[cr]];
outptr[RGB_GREEN] = range_limit[y +
- ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
- SCALEBITS))];
+ ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
+ SCALEBITS))];
outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]];
/* Set unused byte to 0xFF so it can be interpreted as an opaque */
/* alpha channel value */
@@ -81,9 +81,9 @@ ycc_rgb_convert_internal (j_decompress_ptr cinfo,
INLINE
LOCAL(void)
-gray_rgb_convert_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+gray_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf,
+ int num_rows)
{
register JSAMPROW inptr, outptr;
register JDIMENSION col;
@@ -112,9 +112,9 @@ gray_rgb_convert_internal (j_decompress_ptr cinfo,
INLINE
LOCAL(void)
-rgb_rgb_convert_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+rgb_rgb_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf,
+ int num_rows)
{
register JSAMPROW inptr0, inptr1, inptr2;
register JSAMPROW outptr;
diff --git a/src/3rdparty/libjpeg/src/jdcolor.c b/src/3rdparty/libjpeg/src/jdcolor.c
index 05cbf4df1f..fd7f661d5a 100644
--- a/src/3rdparty/libjpeg/src/jdcolor.c
+++ b/src/3rdparty/libjpeg/src/jdcolor.c
@@ -74,8 +74,8 @@ typedef my_color_deconverter *my_cconvert_ptr;
*/
#define SCALEBITS 16 /* speediest right-shift on some machines */
-#define ONE_HALF ((JLONG) 1 << (SCALEBITS-1))
-#define FIX(x) ((JLONG) ((x) * (1L<<SCALEBITS) + 0.5))
+#define ONE_HALF ((JLONG)1 << (SCALEBITS - 1))
+#define FIX(x) ((JLONG)((x) * (1L << SCALEBITS) + 0.5))
/* We allocate one big table for RGB->Y conversion and divide it up into
* three parts, instead of doing three alloc_small requests. This lets us
@@ -85,9 +85,9 @@ typedef my_color_deconverter *my_cconvert_ptr;
*/
#define R_Y_OFF 0 /* offset to R => Y section */
-#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */
-#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */
-#define TABLE_SIZE (3*(MAXJSAMPLE+1))
+#define G_Y_OFF (1 * (MAXJSAMPLE + 1)) /* offset to G => Y section */
+#define B_Y_OFF (2 * (MAXJSAMPLE + 1)) /* etc. */
+#define TABLE_SIZE (3 * (MAXJSAMPLE + 1))
/* Include inline routines for colorspace extensions */
@@ -98,13 +98,13 @@ typedef my_color_deconverter *my_cconvert_ptr;
#undef RGB_BLUE
#undef RGB_PIXELSIZE
-#define RGB_RED EXT_RGB_RED
-#define RGB_GREEN EXT_RGB_GREEN
-#define RGB_BLUE EXT_RGB_BLUE
-#define RGB_PIXELSIZE EXT_RGB_PIXELSIZE
-#define ycc_rgb_convert_internal ycc_extrgb_convert_internal
-#define gray_rgb_convert_internal gray_extrgb_convert_internal
-#define rgb_rgb_convert_internal rgb_extrgb_convert_internal
+#define RGB_RED EXT_RGB_RED
+#define RGB_GREEN EXT_RGB_GREEN
+#define RGB_BLUE EXT_RGB_BLUE
+#define RGB_PIXELSIZE EXT_RGB_PIXELSIZE
+#define ycc_rgb_convert_internal ycc_extrgb_convert_internal
+#define gray_rgb_convert_internal gray_extrgb_convert_internal
+#define rgb_rgb_convert_internal rgb_extrgb_convert_internal
#include "jdcolext.c"
#undef RGB_RED
#undef RGB_GREEN
@@ -114,14 +114,14 @@ typedef my_color_deconverter *my_cconvert_ptr;
#undef gray_rgb_convert_internal
#undef rgb_rgb_convert_internal
-#define RGB_RED EXT_RGBX_RED
-#define RGB_GREEN EXT_RGBX_GREEN
-#define RGB_BLUE EXT_RGBX_BLUE
-#define RGB_ALPHA 3
-#define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE
-#define ycc_rgb_convert_internal ycc_extrgbx_convert_internal
-#define gray_rgb_convert_internal gray_extrgbx_convert_internal
-#define rgb_rgb_convert_internal rgb_extrgbx_convert_internal
+#define RGB_RED EXT_RGBX_RED
+#define RGB_GREEN EXT_RGBX_GREEN
+#define RGB_BLUE EXT_RGBX_BLUE
+#define RGB_ALPHA 3
+#define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE
+#define ycc_rgb_convert_internal ycc_extrgbx_convert_internal
+#define gray_rgb_convert_internal gray_extrgbx_convert_internal
+#define rgb_rgb_convert_internal rgb_extrgbx_convert_internal
#include "jdcolext.c"
#undef RGB_RED
#undef RGB_GREEN
@@ -132,13 +132,13 @@ typedef my_color_deconverter *my_cconvert_ptr;
#undef gray_rgb_convert_internal
#undef rgb_rgb_convert_internal
-#define RGB_RED EXT_BGR_RED
-#define RGB_GREEN EXT_BGR_GREEN
-#define RGB_BLUE EXT_BGR_BLUE
-#define RGB_PIXELSIZE EXT_BGR_PIXELSIZE
-#define ycc_rgb_convert_internal ycc_extbgr_convert_internal
-#define gray_rgb_convert_internal gray_extbgr_convert_internal
-#define rgb_rgb_convert_internal rgb_extbgr_convert_internal
+#define RGB_RED EXT_BGR_RED
+#define RGB_GREEN EXT_BGR_GREEN
+#define RGB_BLUE EXT_BGR_BLUE
+#define RGB_PIXELSIZE EXT_BGR_PIXELSIZE
+#define ycc_rgb_convert_internal ycc_extbgr_convert_internal
+#define gray_rgb_convert_internal gray_extbgr_convert_internal
+#define rgb_rgb_convert_internal rgb_extbgr_convert_internal
#include "jdcolext.c"
#undef RGB_RED
#undef RGB_GREEN
@@ -148,14 +148,14 @@ typedef my_color_deconverter *my_cconvert_ptr;
#undef gray_rgb_convert_internal
#undef rgb_rgb_convert_internal
-#define RGB_RED EXT_BGRX_RED
-#define RGB_GREEN EXT_BGRX_GREEN
-#define RGB_BLUE EXT_BGRX_BLUE
-#define RGB_ALPHA 3
-#define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE
-#define ycc_rgb_convert_internal ycc_extbgrx_convert_internal
-#define gray_rgb_convert_internal gray_extbgrx_convert_internal
-#define rgb_rgb_convert_internal rgb_extbgrx_convert_internal
+#define RGB_RED EXT_BGRX_RED
+#define RGB_GREEN EXT_BGRX_GREEN
+#define RGB_BLUE EXT_BGRX_BLUE
+#define RGB_ALPHA 3
+#define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE
+#define ycc_rgb_convert_internal ycc_extbgrx_convert_internal
+#define gray_rgb_convert_internal gray_extbgrx_convert_internal
+#define rgb_rgb_convert_internal rgb_extbgrx_convert_internal
#include "jdcolext.c"
#undef RGB_RED
#undef RGB_GREEN
@@ -166,14 +166,14 @@ typedef my_color_deconverter *my_cconvert_ptr;
#undef gray_rgb_convert_internal
#undef rgb_rgb_convert_internal
-#define RGB_RED EXT_XBGR_RED
-#define RGB_GREEN EXT_XBGR_GREEN
-#define RGB_BLUE EXT_XBGR_BLUE
-#define RGB_ALPHA 0
-#define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE
-#define ycc_rgb_convert_internal ycc_extxbgr_convert_internal
-#define gray_rgb_convert_internal gray_extxbgr_convert_internal
-#define rgb_rgb_convert_internal rgb_extxbgr_convert_internal
+#define RGB_RED EXT_XBGR_RED
+#define RGB_GREEN EXT_XBGR_GREEN
+#define RGB_BLUE EXT_XBGR_BLUE
+#define RGB_ALPHA 0
+#define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE
+#define ycc_rgb_convert_internal ycc_extxbgr_convert_internal
+#define gray_rgb_convert_internal gray_extxbgr_convert_internal
+#define rgb_rgb_convert_internal rgb_extxbgr_convert_internal
#include "jdcolext.c"
#undef RGB_RED
#undef RGB_GREEN
@@ -184,14 +184,14 @@ typedef my_color_deconverter *my_cconvert_ptr;
#undef gray_rgb_convert_internal
#undef rgb_rgb_convert_internal
-#define RGB_RED EXT_XRGB_RED
-#define RGB_GREEN EXT_XRGB_GREEN
-#define RGB_BLUE EXT_XRGB_BLUE
-#define RGB_ALPHA 0
-#define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE
-#define ycc_rgb_convert_internal ycc_extxrgb_convert_internal
-#define gray_rgb_convert_internal gray_extxrgb_convert_internal
-#define rgb_rgb_convert_internal rgb_extxrgb_convert_internal
+#define RGB_RED EXT_XRGB_RED
+#define RGB_GREEN EXT_XRGB_GREEN
+#define RGB_BLUE EXT_XRGB_BLUE
+#define RGB_ALPHA 0
+#define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE
+#define ycc_rgb_convert_internal ycc_extxrgb_convert_internal
+#define gray_rgb_convert_internal gray_extxrgb_convert_internal
+#define rgb_rgb_convert_internal rgb_extxrgb_convert_internal
#include "jdcolext.c"
#undef RGB_RED
#undef RGB_GREEN
@@ -208,25 +208,25 @@ typedef my_color_deconverter *my_cconvert_ptr;
*/
LOCAL(void)
-build_ycc_rgb_table (j_decompress_ptr cinfo)
+build_ycc_rgb_table(j_decompress_ptr cinfo)
{
- my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
int i;
JLONG x;
SHIFT_TEMPS
cconvert->Cr_r_tab = (int *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (MAXJSAMPLE+1) * sizeof(int));
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE + 1) * sizeof(int));
cconvert->Cb_b_tab = (int *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (MAXJSAMPLE+1) * sizeof(int));
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE + 1) * sizeof(int));
cconvert->Cr_g_tab = (JLONG *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (MAXJSAMPLE+1) * sizeof(JLONG));
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE + 1) * sizeof(JLONG));
cconvert->Cb_g_tab = (JLONG *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (MAXJSAMPLE+1) * sizeof(JLONG));
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE + 1) * sizeof(JLONG));
for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
/* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
@@ -238,10 +238,10 @@ build_ycc_rgb_table (j_decompress_ptr cinfo)
cconvert->Cb_b_tab[i] = (int)
RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
/* Cr=>G value is scaled-up -0.71414 * x */
- cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x;
+ cconvert->Cr_g_tab[i] = (-FIX(0.71414)) * x;
/* Cb=>G value is scaled-up -0.34414 * x */
/* We also add in ONE_HALF so that need not do it in inner loop */
- cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
+ cconvert->Cb_g_tab[i] = (-FIX(0.34414)) * x + ONE_HALF;
}
}
@@ -251,43 +251,42 @@ build_ycc_rgb_table (j_decompress_ptr cinfo)
*/
METHODDEF(void)
-ycc_rgb_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+ycc_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
switch (cinfo->out_color_space) {
- case JCS_EXT_RGB:
- ycc_extrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_RGBX:
- case JCS_EXT_RGBA:
- ycc_extrgbx_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_BGR:
- ycc_extbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_BGRX:
- case JCS_EXT_BGRA:
- ycc_extbgrx_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_XBGR:
- case JCS_EXT_ABGR:
- ycc_extxbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_XRGB:
- case JCS_EXT_ARGB:
- ycc_extxrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- default:
- ycc_rgb_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
+ case JCS_EXT_RGB:
+ ycc_extrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_RGBX:
+ case JCS_EXT_RGBA:
+ ycc_extrgbx_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_BGR:
+ ycc_extbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_BGRX:
+ case JCS_EXT_BGRA:
+ ycc_extbgrx_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_XBGR:
+ case JCS_EXT_ABGR:
+ ycc_extxbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_XRGB:
+ case JCS_EXT_ARGB:
+ ycc_extxrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ default:
+ ycc_rgb_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
}
}
@@ -300,21 +299,21 @@ ycc_rgb_convert (j_decompress_ptr cinfo,
*/
LOCAL(void)
-build_rgb_y_table (j_decompress_ptr cinfo)
+build_rgb_y_table(j_decompress_ptr cinfo)
{
- my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
JLONG *rgb_y_tab;
JLONG i;
/* Allocate and fill in the conversion tables. */
cconvert->rgb_y_tab = rgb_y_tab = (JLONG *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
(TABLE_SIZE * sizeof(JLONG)));
for (i = 0; i <= MAXJSAMPLE; i++) {
- rgb_y_tab[i+R_Y_OFF] = FIX(0.29900) * i;
- rgb_y_tab[i+G_Y_OFF] = FIX(0.58700) * i;
- rgb_y_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF;
+ rgb_y_tab[i + R_Y_OFF] = FIX(0.29900) * i;
+ rgb_y_tab[i + G_Y_OFF] = FIX(0.58700) * i;
+ rgb_y_tab[i + B_Y_OFF] = FIX(0.11400) * i + ONE_HALF;
}
}
@@ -324,11 +323,10 @@ build_rgb_y_table (j_decompress_ptr cinfo)
*/
METHODDEF(void)
-rgb_gray_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+rgb_gray_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
- my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int r, g, b;
register JLONG *ctab = cconvert->rgb_y_tab;
register JSAMPROW outptr;
@@ -347,9 +345,8 @@ rgb_gray_convert (j_decompress_ptr cinfo,
g = GETJSAMPLE(inptr1[col]);
b = GETJSAMPLE(inptr2[col]);
/* Y */
- outptr[col] = (JSAMPLE)
- ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
- >> SCALEBITS);
+ outptr[col] = (JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] +
+ ctab[b + B_Y_OFF]) >> SCALEBITS);
}
}
}
@@ -361,9 +358,8 @@ rgb_gray_convert (j_decompress_ptr cinfo,
*/
METHODDEF(void)
-null_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+null_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
register JSAMPROW inptr, inptr0, inptr1, inptr2, inptr3, outptr;
register JDIMENSION col;
@@ -423,12 +419,11 @@ null_convert (j_decompress_ptr cinfo,
*/
METHODDEF(void)
-grayscale_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+grayscale_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
- jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0,
- num_rows, cinfo->output_width);
+ jcopy_sample_rows(input_buf[0], (int)input_row, output_buf, 0, num_rows,
+ cinfo->output_width);
}
@@ -437,43 +432,42 @@ grayscale_convert (j_decompress_ptr cinfo,
*/
METHODDEF(void)
-gray_rgb_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+gray_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
switch (cinfo->out_color_space) {
- case JCS_EXT_RGB:
- gray_extrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_RGBX:
- case JCS_EXT_RGBA:
- gray_extrgbx_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_BGR:
- gray_extbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_BGRX:
- case JCS_EXT_BGRA:
- gray_extbgrx_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_XBGR:
- case JCS_EXT_ABGR:
- gray_extxbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_XRGB:
- case JCS_EXT_ARGB:
- gray_extxrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- default:
- gray_rgb_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
+ case JCS_EXT_RGB:
+ gray_extrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_RGBX:
+ case JCS_EXT_RGBA:
+ gray_extrgbx_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_BGR:
+ gray_extbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_BGRX:
+ case JCS_EXT_BGRA:
+ gray_extbgrx_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_XBGR:
+ case JCS_EXT_ABGR:
+ gray_extxbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_XRGB:
+ case JCS_EXT_ARGB:
+ gray_extxrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ default:
+ gray_rgb_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
}
}
@@ -483,43 +477,42 @@ gray_rgb_convert (j_decompress_ptr cinfo,
*/
METHODDEF(void)
-rgb_rgb_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+rgb_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
switch (cinfo->out_color_space) {
- case JCS_EXT_RGB:
- rgb_extrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_RGBX:
- case JCS_EXT_RGBA:
- rgb_extrgbx_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_BGR:
- rgb_extbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_BGRX:
- case JCS_EXT_BGRA:
- rgb_extbgrx_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_XBGR:
- case JCS_EXT_ABGR:
- rgb_extxbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- case JCS_EXT_XRGB:
- case JCS_EXT_ARGB:
- rgb_extxrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
- default:
- rgb_rgb_convert_internal(cinfo, input_buf, input_row, output_buf,
- num_rows);
- break;
+ case JCS_EXT_RGB:
+ rgb_extrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_RGBX:
+ case JCS_EXT_RGBA:
+ rgb_extrgbx_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_BGR:
+ rgb_extbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_BGRX:
+ case JCS_EXT_BGRA:
+ rgb_extbgrx_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_XBGR:
+ case JCS_EXT_ABGR:
+ rgb_extxbgr_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ case JCS_EXT_XRGB:
+ case JCS_EXT_ARGB:
+ rgb_extxrgb_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
+ default:
+ rgb_rgb_convert_internal(cinfo, input_buf, input_row, output_buf,
+ num_rows);
+ break;
}
}
@@ -532,11 +525,10 @@ rgb_rgb_convert (j_decompress_ptr cinfo,
*/
METHODDEF(void)
-ycck_cmyk_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+ycck_cmyk_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
- my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
register int y, cb, cr;
register JSAMPROW outptr;
register JSAMPROW inptr0, inptr1, inptr2, inptr3;
@@ -564,7 +556,7 @@ ycck_cmyk_convert (j_decompress_ptr cinfo,
/* Range-limiting is essential due to noise introduced by DCT losses. */
outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */
outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */
- ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
+ ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
SCALEBITS)))];
outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */
/* K passes through unchanged */
@@ -579,16 +571,16 @@ ycck_cmyk_convert (j_decompress_ptr cinfo,
* RGB565 conversion
*/
-#define PACK_SHORT_565_LE(r, g, b) ((((r) << 8) & 0xF800) | \
- (((g) << 3) & 0x7E0) | ((b) >> 3))
-#define PACK_SHORT_565_BE(r, g, b) (((r) & 0xF8) | ((g) >> 5) | \
- (((g) << 11) & 0xE000) | \
- (((b) << 5) & 0x1F00))
+#define PACK_SHORT_565_LE(r, g, b) ((((r) << 8) & 0xF800) | \
+ (((g) << 3) & 0x7E0) | ((b) >> 3))
+#define PACK_SHORT_565_BE(r, g, b) (((r) & 0xF8) | ((g) >> 5) | \
+ (((g) << 11) & 0xE000) | \
+ (((b) << 5) & 0x1F00))
-#define PACK_TWO_PIXELS_LE(l, r) ((r << 16) | l)
-#define PACK_TWO_PIXELS_BE(l, r) ((l << 16) | r)
+#define PACK_TWO_PIXELS_LE(l, r) ((r << 16) | l)
+#define PACK_TWO_PIXELS_BE(l, r) ((l << 16) | r)
-#define PACK_NEED_ALIGNMENT(ptr) (((size_t)(ptr)) & 3)
+#define PACK_NEED_ALIGNMENT(ptr) (((size_t)(ptr)) & 3)
#define WRITE_TWO_ALIGNED_PIXELS(addr, pixels) ((*(int *)(addr)) = pixels)
@@ -624,14 +616,14 @@ static INLINE boolean is_big_endian(void)
/* Include inline routines for RGB565 conversion */
-#define PACK_SHORT_565 PACK_SHORT_565_LE
-#define PACK_TWO_PIXELS PACK_TWO_PIXELS_LE
-#define ycc_rgb565_convert_internal ycc_rgb565_convert_le
-#define ycc_rgb565D_convert_internal ycc_rgb565D_convert_le
-#define rgb_rgb565_convert_internal rgb_rgb565_convert_le
-#define rgb_rgb565D_convert_internal rgb_rgb565D_convert_le
-#define gray_rgb565_convert_internal gray_rgb565_convert_le
-#define gray_rgb565D_convert_internal gray_rgb565D_convert_le
+#define PACK_SHORT_565 PACK_SHORT_565_LE
+#define PACK_TWO_PIXELS PACK_TWO_PIXELS_LE
+#define ycc_rgb565_convert_internal ycc_rgb565_convert_le
+#define ycc_rgb565D_convert_internal ycc_rgb565D_convert_le
+#define rgb_rgb565_convert_internal rgb_rgb565_convert_le
+#define rgb_rgb565D_convert_internal rgb_rgb565D_convert_le
+#define gray_rgb565_convert_internal gray_rgb565_convert_le
+#define gray_rgb565D_convert_internal gray_rgb565D_convert_le
#include "jdcol565.c"
#undef PACK_SHORT_565
#undef PACK_TWO_PIXELS
@@ -642,14 +634,14 @@ static INLINE boolean is_big_endian(void)
#undef gray_rgb565_convert_internal
#undef gray_rgb565D_convert_internal
-#define PACK_SHORT_565 PACK_SHORT_565_BE
-#define PACK_TWO_PIXELS PACK_TWO_PIXELS_BE
-#define ycc_rgb565_convert_internal ycc_rgb565_convert_be
-#define ycc_rgb565D_convert_internal ycc_rgb565D_convert_be
-#define rgb_rgb565_convert_internal rgb_rgb565_convert_be
-#define rgb_rgb565D_convert_internal rgb_rgb565D_convert_be
-#define gray_rgb565_convert_internal gray_rgb565_convert_be
-#define gray_rgb565D_convert_internal gray_rgb565D_convert_be
+#define PACK_SHORT_565 PACK_SHORT_565_BE
+#define PACK_TWO_PIXELS PACK_TWO_PIXELS_BE
+#define ycc_rgb565_convert_internal ycc_rgb565_convert_be
+#define ycc_rgb565D_convert_internal ycc_rgb565D_convert_be
+#define rgb_rgb565_convert_internal rgb_rgb565_convert_be
+#define rgb_rgb565D_convert_internal rgb_rgb565D_convert_be
+#define gray_rgb565_convert_internal gray_rgb565_convert_be
+#define gray_rgb565D_convert_internal gray_rgb565D_convert_be
#include "jdcol565.c"
#undef PACK_SHORT_565
#undef PACK_TWO_PIXELS
@@ -662,9 +654,8 @@ static INLINE boolean is_big_endian(void)
METHODDEF(void)
-ycc_rgb565_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+ycc_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
if (is_big_endian())
ycc_rgb565_convert_be(cinfo, input_buf, input_row, output_buf, num_rows);
@@ -674,9 +665,8 @@ ycc_rgb565_convert (j_decompress_ptr cinfo,
METHODDEF(void)
-ycc_rgb565D_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+ycc_rgb565D_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
if (is_big_endian())
ycc_rgb565D_convert_be(cinfo, input_buf, input_row, output_buf, num_rows);
@@ -686,9 +676,8 @@ ycc_rgb565D_convert (j_decompress_ptr cinfo,
METHODDEF(void)
-rgb_rgb565_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+rgb_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
if (is_big_endian())
rgb_rgb565_convert_be(cinfo, input_buf, input_row, output_buf, num_rows);
@@ -698,9 +687,8 @@ rgb_rgb565_convert (j_decompress_ptr cinfo,
METHODDEF(void)
-rgb_rgb565D_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+rgb_rgb565D_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
if (is_big_endian())
rgb_rgb565D_convert_be(cinfo, input_buf, input_row, output_buf, num_rows);
@@ -710,9 +698,8 @@ rgb_rgb565D_convert (j_decompress_ptr cinfo,
METHODDEF(void)
-gray_rgb565_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+gray_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
if (is_big_endian())
gray_rgb565_convert_be(cinfo, input_buf, input_row, output_buf, num_rows);
@@ -722,9 +709,8 @@ gray_rgb565_convert (j_decompress_ptr cinfo,
METHODDEF(void)
-gray_rgb565D_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+gray_rgb565D_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows)
{
if (is_big_endian())
gray_rgb565D_convert_be(cinfo, input_buf, input_row, output_buf, num_rows);
@@ -738,7 +724,7 @@ gray_rgb565D_convert (j_decompress_ptr cinfo,
*/
METHODDEF(void)
-start_pass_dcolor (j_decompress_ptr cinfo)
+start_pass_dcolor(j_decompress_ptr cinfo)
{
/* no work needed */
}
@@ -749,15 +735,15 @@ start_pass_dcolor (j_decompress_ptr cinfo)
*/
GLOBAL(void)
-jinit_color_deconverter (j_decompress_ptr cinfo)
+jinit_color_deconverter(j_decompress_ptr cinfo)
{
my_cconvert_ptr cconvert;
int ci;
cconvert = (my_cconvert_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_color_deconverter));
- cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert;
+ cinfo->cconvert = (struct jpeg_color_deconverter *)cconvert;
cconvert->pub.start_pass = start_pass_dcolor;
/* Make sure num_components agrees with jpeg_color_space */
@@ -843,11 +829,11 @@ jinit_color_deconverter (j_decompress_ptr cinfo)
cinfo->out_color_components = 3;
if (cinfo->dither_mode == JDITHER_NONE) {
if (cinfo->jpeg_color_space == JCS_YCbCr) {
- if (jsimd_can_ycc_rgb565())
- cconvert->pub.color_convert = jsimd_ycc_rgb565_convert;
- else {
- cconvert->pub.color_convert = ycc_rgb565_convert;
- build_ycc_rgb_table(cinfo);
+ if (jsimd_can_ycc_rgb565())
+ cconvert->pub.color_convert = jsimd_ycc_rgb565_convert;
+ else {
+ cconvert->pub.color_convert = ycc_rgb565_convert;
+ build_ycc_rgb_table(cinfo);
}
} else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
cconvert->pub.color_convert = gray_rgb565_convert;
diff --git a/src/3rdparty/libjpeg/src/jdct.h b/src/3rdparty/libjpeg/src/jdct.h
index faf8e1cf03..66d1718b77 100644
--- a/src/3rdparty/libjpeg/src/jdct.h
+++ b/src/3rdparty/libjpeg/src/jdct.h
@@ -36,7 +36,7 @@ typedef int DCTELEM; /* 16 or 32 bits is fine */
typedef unsigned int UDCTELEM;
typedef unsigned long long UDCTELEM2;
#else
-typedef short DCTELEM; /* prefer 16 bit with SIMD for parellelism */
+typedef short DCTELEM; /* prefer 16 bit with SIMD for parellelism */
typedef unsigned short UDCTELEM;
typedef unsigned int UDCTELEM2;
#endif
@@ -63,15 +63,15 @@ typedef unsigned long long UDCTELEM2;
* Each IDCT routine has its own ideas about the best dct_table element type.
*/
-typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */
+typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */
#if BITS_IN_JSAMPLE == 8
-typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */
-#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */
+typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */
+#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */
#else
-typedef JLONG IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */
-#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */
+typedef JLONG IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */
+#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */
#endif
-typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */
+typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */
/*
@@ -90,64 +90,64 @@ typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */
/* Extern declarations for the forward and inverse DCT routines. */
-EXTERN(void) jpeg_fdct_islow (DCTELEM *data);
-EXTERN(void) jpeg_fdct_ifast (DCTELEM *data);
-EXTERN(void) jpeg_fdct_float (FAST_FLOAT *data);
-
-EXTERN(void) jpeg_idct_islow
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_ifast
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_float
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_7x7
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_6x6
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_5x5
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_4x4
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_3x3
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_2x2
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_1x1
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_9x9
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_10x10
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_11x11
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_12x12
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_13x13
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_14x14
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_15x15
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
-EXTERN(void) jpeg_idct_16x16
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_fdct_islow(DCTELEM *data);
+EXTERN(void) jpeg_fdct_ifast(DCTELEM *data);
+EXTERN(void) jpeg_fdct_float(FAST_FLOAT *data);
+
+EXTERN(void) jpeg_idct_islow(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_ifast(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_float(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_7x7(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_6x6(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_5x5(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_4x4(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_3x3(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_2x2(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_1x1(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_9x9(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_10x10(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_11x11(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_12x12(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_13x13(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_14x14(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_15x15(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jpeg_idct_16x16(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
/*
@@ -160,22 +160,22 @@ EXTERN(void) jpeg_idct_16x16
* and may differ from one module to the next.
*/
-#define ONE ((JLONG) 1)
-#define CONST_SCALE (ONE << CONST_BITS)
+#define ONE ((JLONG)1)
+#define CONST_SCALE (ONE << CONST_BITS)
/* Convert a positive real constant to an integer scaled by CONST_SCALE.
* Caution: some C compilers fail to reduce "FIX(constant)" at compile time,
* thus causing a lot of useless floating-point operations at run time.
*/
-#define FIX(x) ((JLONG) ((x) * CONST_SCALE + 0.5))
+#define FIX(x) ((JLONG)((x) * CONST_SCALE + 0.5))
/* Descale and correctly round a JLONG value that's scaled by N bits.
* We assume RIGHT_SHIFT rounds towards minus infinity, so adding
* the fudge factor is correct for either sign of X.
*/
-#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
+#define DESCALE(x, n) RIGHT_SHIFT((x) + (ONE << ((n) - 1)), n)
/* Multiply a JLONG variable by a JLONG constant to yield a JLONG result.
* This macro is used only when the two inputs will actually be no more than
@@ -187,22 +187,22 @@ EXTERN(void) jpeg_idct_16x16
*/
#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
-#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const)))
+#define MULTIPLY16C16(var, const) (((INT16)(var)) * ((INT16)(const)))
#endif
#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */
-#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((JLONG) (const)))
+#define MULTIPLY16C16(var, const) (((INT16)(var)) * ((JLONG)(const)))
#endif
#ifndef MULTIPLY16C16 /* default definition */
-#define MULTIPLY16C16(var,const) ((var) * (const))
+#define MULTIPLY16C16(var, const) ((var) * (const))
#endif
/* Same except both inputs are variables. */
#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
-#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2)))
+#define MULTIPLY16V16(var1, var2) (((INT16)(var1)) * ((INT16)(var2)))
#endif
#ifndef MULTIPLY16V16 /* default definition */
-#define MULTIPLY16V16(var1,var2) ((var1) * (var2))
+#define MULTIPLY16V16(var1, var2) ((var1) * (var2))
#endif
diff --git a/src/3rdparty/libjpeg/src/jddctmgr.c b/src/3rdparty/libjpeg/src/jddctmgr.c
index 3a5ba7e893..266f446623 100644
--- a/src/3rdparty/libjpeg/src/jddctmgr.c
+++ b/src/3rdparty/libjpeg/src/jddctmgr.c
@@ -94,9 +94,9 @@ typedef union {
*/
METHODDEF(void)
-start_pass (j_decompress_ptr cinfo)
+start_pass(j_decompress_ptr cinfo)
{
- my_idct_ptr idct = (my_idct_ptr) cinfo->idct;
+ my_idct_ptr idct = (my_idct_ptr)cinfo->idct;
int ci, i;
jpeg_component_info *compptr;
int method = 0;
@@ -233,7 +233,7 @@ start_pass (j_decompress_ptr cinfo)
* multiplier table all-zero; we'll be reading zeroes from the
* coefficient controller's buffer anyway.
*/
- if (! compptr->component_needed || idct->cur_method[ci] == method)
+ if (!compptr->component_needed || idct->cur_method[ci] == method)
continue;
qtbl = compptr->quant_table;
if (qtbl == NULL) /* happens if no data yet for component */
@@ -246,9 +246,9 @@ start_pass (j_decompress_ptr cinfo)
/* For LL&M IDCT method, multipliers are equal to raw quantization
* coefficients, but are stored as ints to ensure access efficiency.
*/
- ISLOW_MULT_TYPE *ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ ISLOW_MULT_TYPE *ismtbl = (ISLOW_MULT_TYPE *)compptr->dct_table;
for (i = 0; i < DCTSIZE2; i++) {
- ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i];
+ ismtbl[i] = (ISLOW_MULT_TYPE)qtbl->quantval[i];
}
}
break;
@@ -263,8 +263,8 @@ start_pass (j_decompress_ptr cinfo)
* For integer operation, the multiplier table is to be scaled by
* IFAST_SCALE_BITS.
*/
- IFAST_MULT_TYPE *ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table;
-#define CONST_BITS 14
+ IFAST_MULT_TYPE *ifmtbl = (IFAST_MULT_TYPE *)compptr->dct_table;
+#define CONST_BITS 14
static const INT16 aanscales[DCTSIZE2] = {
/* precomputed values scaled up by 14 bits */
16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
@@ -280,9 +280,9 @@ start_pass (j_decompress_ptr cinfo)
for (i = 0; i < DCTSIZE2; i++) {
ifmtbl[i] = (IFAST_MULT_TYPE)
- DESCALE(MULTIPLY16V16((JLONG) qtbl->quantval[i],
- (JLONG) aanscales[i]),
- CONST_BITS-IFAST_SCALE_BITS);
+ DESCALE(MULTIPLY16V16((JLONG)qtbl->quantval[i],
+ (JLONG)aanscales[i]),
+ CONST_BITS - IFAST_SCALE_BITS);
}
}
break;
@@ -295,7 +295,7 @@ start_pass (j_decompress_ptr cinfo)
* scalefactor[0] = 1
* scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
*/
- FLOAT_MULT_TYPE *fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table;
+ FLOAT_MULT_TYPE *fmtbl = (FLOAT_MULT_TYPE *)compptr->dct_table;
int row, col;
static const double aanscalefactor[DCTSIZE] = {
1.0, 1.387039845, 1.306562965, 1.175875602,
@@ -306,7 +306,7 @@ start_pass (j_decompress_ptr cinfo)
for (row = 0; row < DCTSIZE; row++) {
for (col = 0; col < DCTSIZE; col++) {
fmtbl[i] = (FLOAT_MULT_TYPE)
- ((double) qtbl->quantval[i] *
+ ((double)qtbl->quantval[i] *
aanscalefactor[row] * aanscalefactor[col]);
i++;
}
@@ -327,23 +327,23 @@ start_pass (j_decompress_ptr cinfo)
*/
GLOBAL(void)
-jinit_inverse_dct (j_decompress_ptr cinfo)
+jinit_inverse_dct(j_decompress_ptr cinfo)
{
my_idct_ptr idct;
int ci;
jpeg_component_info *compptr;
idct = (my_idct_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_idct_controller));
- cinfo->idct = (struct jpeg_inverse_dct *) idct;
+ cinfo->idct = (struct jpeg_inverse_dct *)idct;
idct->pub.start_pass = start_pass;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
/* Allocate and pre-zero a multiplier table for each component */
compptr->dct_table =
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(multiplier_table));
MEMZERO(compptr->dct_table, sizeof(multiplier_table));
/* Mark multiplier table not yet set up for any method */
diff --git a/src/3rdparty/libjpeg/src/jdhuff.c b/src/3rdparty/libjpeg/src/jdhuff.c
index bb2b84887c..95f38e547e 100644
--- a/src/3rdparty/libjpeg/src/jdhuff.c
+++ b/src/3rdparty/libjpeg/src/jdhuff.c
@@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1997, Thomas G. Lane.
* libjpeg-turbo Modifications:
- * Copyright (C) 2009-2011, 2016, D. R. Commander.
+ * Copyright (C) 2009-2011, 2016, 2018, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -15,6 +15,9 @@
* up to the start of the current MCU. To do this, we copy state variables
* into local working storage, and update them back to the permanent
* storage only upon successful completion of an MCU.
+ *
+ * NOTE: All referenced figures are from
+ * Recommendation ITU-T T.81 (1992) | ISO/IEC 10918-1:1994.
*/
#define JPEG_INTERNALS
@@ -42,14 +45,14 @@ typedef struct {
*/
#ifndef NO_STRUCT_ASSIGN
-#define ASSIGN_STATE(dest,src) ((dest) = (src))
+#define ASSIGN_STATE(dest, src) ((dest) = (src))
#else
#if MAX_COMPS_IN_SCAN == 4
-#define ASSIGN_STATE(dest,src) \
- ((dest).last_dc_val[0] = (src).last_dc_val[0], \
- (dest).last_dc_val[1] = (src).last_dc_val[1], \
- (dest).last_dc_val[2] = (src).last_dc_val[2], \
- (dest).last_dc_val[3] = (src).last_dc_val[3])
+#define ASSIGN_STATE(dest, src) \
+ ((dest).last_dc_val[0] = (src).last_dc_val[0], \
+ (dest).last_dc_val[1] = (src).last_dc_val[1], \
+ (dest).last_dc_val[2] = (src).last_dc_val[2], \
+ (dest).last_dc_val[3] = (src).last_dc_val[3])
#endif
#endif
@@ -88,9 +91,9 @@ typedef huff_entropy_decoder *huff_entropy_ptr;
*/
METHODDEF(void)
-start_pass_huff_decoder (j_decompress_ptr cinfo)
+start_pass_huff_decoder(j_decompress_ptr cinfo)
{
- huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
int ci, blkn, dctbl, actbl;
d_derived_tbl **pdtbl;
jpeg_component_info *compptr;
@@ -99,7 +102,7 @@ start_pass_huff_decoder (j_decompress_ptr cinfo)
* This ought to be an error condition, but we make it a warning because
* there are some baseline files out there with all zeroes in these bytes.
*/
- if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 ||
+ if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2 - 1 ||
cinfo->Ah != 0 || cinfo->Al != 0)
WARNMS(cinfo, JWRN_NOT_SEQUENTIAL);
@@ -152,8 +155,8 @@ start_pass_huff_decoder (j_decompress_ptr cinfo)
*/
GLOBAL(void)
-jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno,
- d_derived_tbl **pdtbl)
+jpeg_make_d_derived_tbl(j_decompress_ptr cinfo, boolean isDC, int tblno,
+ d_derived_tbl **pdtbl)
{
JHUFF_TBL *htbl;
d_derived_tbl *dtbl;
@@ -178,7 +181,7 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno,
/* Allocate a workspace if we haven't already done so. */
if (*pdtbl == NULL)
*pdtbl = (d_derived_tbl *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(d_derived_tbl));
dtbl = *pdtbl;
dtbl->pub = htbl; /* fill in back link */
@@ -187,11 +190,11 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno,
p = 0;
for (l = 1; l <= 16; l++) {
- i = (int) htbl->bits[l];
+ i = (int)htbl->bits[l];
if (i < 0 || p + i > 256) /* protect against table overrun */
ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
while (i--)
- huffsize[p++] = (char) l;
+ huffsize[p++] = (char)l;
}
huffsize[p] = 0;
numsymbols = p;
@@ -203,14 +206,14 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno,
si = huffsize[0];
p = 0;
while (huffsize[p]) {
- while (((int) huffsize[p]) == si) {
+ while (((int)huffsize[p]) == si) {
huffcode[p++] = code;
code++;
}
/* code is now 1 more than the last code used for codelength si; but
* it must still fit in si bits, since no code is allowed to be all ones.
*/
- if (((JLONG) code) >= (((JLONG) 1) << si))
+ if (((JLONG)code) >= (((JLONG)1) << si))
ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
code <<= 1;
si++;
@@ -224,9 +227,9 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno,
/* valoffset[l] = huffval[] index of 1st symbol of code length l,
* minus the minimum code of length l
*/
- dtbl->valoffset[l] = (JLONG) p - (JLONG) huffcode[p];
+ dtbl->valoffset[l] = (JLONG)p - (JLONG)huffcode[p];
p += htbl->bits[l];
- dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */
+ dtbl->maxcode[l] = huffcode[p - 1]; /* maximum code of length l */
} else {
dtbl->maxcode[l] = -1; /* -1 if no codes of this length */
}
@@ -241,16 +244,16 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno,
* with that code.
*/
- for (i = 0; i < (1 << HUFF_LOOKAHEAD); i++)
- dtbl->lookup[i] = (HUFF_LOOKAHEAD + 1) << HUFF_LOOKAHEAD;
+ for (i = 0; i < (1 << HUFF_LOOKAHEAD); i++)
+ dtbl->lookup[i] = (HUFF_LOOKAHEAD + 1) << HUFF_LOOKAHEAD;
p = 0;
for (l = 1; l <= HUFF_LOOKAHEAD; l++) {
- for (i = 1; i <= (int) htbl->bits[l]; i++, p++) {
+ for (i = 1; i <= (int)htbl->bits[l]; i++, p++) {
/* l = current code's length, p = its index in huffcode[] & huffval[]. */
/* Generate left-justified code followed by all possible bit sequences */
- lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l);
- for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) {
+ lookbits = huffcode[p] << (HUFF_LOOKAHEAD - l);
+ for (ctr = 1 << (HUFF_LOOKAHEAD - l); ctr > 0; ctr--) {
dtbl->lookup[lookbits] = (l << HUFF_LOOKAHEAD) | htbl->huffval[p];
lookbits++;
}
@@ -291,14 +294,14 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno,
#ifdef SLOW_SHIFT_32
#define MIN_GET_BITS 15 /* minimum allowable value */
#else
-#define MIN_GET_BITS (BIT_BUF_SIZE-7)
+#define MIN_GET_BITS (BIT_BUF_SIZE - 7)
#endif
GLOBAL(boolean)
-jpeg_fill_bit_buffer (bitread_working_state *state,
- register bit_buf_type get_buffer, register int bits_left,
- int nbits)
+jpeg_fill_bit_buffer(bitread_working_state *state,
+ register bit_buf_type get_buffer, register int bits_left,
+ int nbits)
/* Load up the bit buffer to a depth of at least nbits */
{
/* Copy heavily used state fields into locals (hopefully registers) */
@@ -316,7 +319,7 @@ jpeg_fill_bit_buffer (bitread_working_state *state,
/* Attempt to read a byte */
if (bytes_in_buffer == 0) {
- if (! (*cinfo->src->fill_input_buffer) (cinfo))
+ if (!(*cinfo->src->fill_input_buffer) (cinfo))
return FALSE;
next_input_byte = cinfo->src->next_input_byte;
bytes_in_buffer = cinfo->src->bytes_in_buffer;
@@ -333,7 +336,7 @@ jpeg_fill_bit_buffer (bitread_working_state *state,
*/
do {
if (bytes_in_buffer == 0) {
- if (! (*cinfo->src->fill_input_buffer) (cinfo))
+ if (!(*cinfo->src->fill_input_buffer) (cinfo))
return FALSE;
next_input_byte = cinfo->src->next_input_byte;
bytes_in_buffer = cinfo->src->bytes_in_buffer;
@@ -365,7 +368,7 @@ jpeg_fill_bit_buffer (bitread_working_state *state,
bits_left += 8;
} /* end while */
} else {
- no_more_bytes:
+no_more_bytes:
/* We get here if we've read the marker that terminates the compressed
* data segment. There should be enough bits in the buffer register
* to satisfy the request; if so, no problem.
@@ -376,7 +379,7 @@ jpeg_fill_bit_buffer (bitread_working_state *state,
* We use a nonvolatile flag to ensure that only one warning message
* appears per data segment.
*/
- if (! cinfo->entropy->insufficient_data) {
+ if (!cinfo->entropy->insufficient_data) {
WARNMS(cinfo, JWRN_HIT_MARKER);
cinfo->entropy->insufficient_data = TRUE;
}
@@ -400,8 +403,7 @@ jpeg_fill_bit_buffer (bitread_working_state *state,
handle markers. We have to hand off any blocks with markers to the
slower routines. */
-#define GET_BYTE \
-{ \
+#define GET_BYTE { \
register int c0, c1; \
c0 = GETJOCTET(*buffer++); \
c1 = GETJOCTET(*buffer); \
@@ -421,7 +423,7 @@ jpeg_fill_bit_buffer (bitread_working_state *state,
} \
}
-#if SIZEOF_SIZE_T==8 || defined(_WIN64)
+#if SIZEOF_SIZE_T == 8 || defined(_WIN64)
/* Pre-fetch 48 bytes, because the holding register is 64-bit */
#define FILL_BIT_BUFFER_FAST \
@@ -446,9 +448,9 @@ jpeg_fill_bit_buffer (bitread_working_state *state,
*/
GLOBAL(int)
-jpeg_huff_decode (bitread_working_state *state,
- register bit_buf_type get_buffer, register int bits_left,
- d_derived_tbl *htbl, int min_bits)
+jpeg_huff_decode(bitread_working_state *state,
+ register bit_buf_type get_buffer, register int bits_left,
+ d_derived_tbl *htbl, int min_bits)
{
register int l = min_bits;
register JLONG code;
@@ -460,7 +462,7 @@ jpeg_huff_decode (bitread_working_state *state,
code = GET_BITS(l);
/* Collect the rest of the Huffman code one bit at a time. */
- /* This is per Figure F.16 in the JPEG spec. */
+ /* This is per Figure F.16. */
while (code > htbl->maxcode[l]) {
code <<= 1;
@@ -480,7 +482,7 @@ jpeg_huff_decode (bitread_working_state *state,
return 0; /* fake a zero as the safest result */
}
- return htbl->pub->huffval[ (int) (code + htbl->valoffset[l]) ];
+ return htbl->pub->huffval[(int)(code + htbl->valoffset[l])];
}
@@ -492,22 +494,26 @@ jpeg_huff_decode (bitread_working_state *state,
#define AVOID_TABLES
#ifdef AVOID_TABLES
-#define NEG_1 ((unsigned int)-1)
-#define HUFF_EXTEND(x,s) ((x) + ((((x) - (1<<((s)-1))) >> 31) & (((NEG_1)<<(s)) + 1)))
+#define NEG_1 ((unsigned int)-1)
+#define HUFF_EXTEND(x, s) \
+ ((x) + ((((x) - (1 << ((s) - 1))) >> 31) & (((NEG_1) << (s)) + 1)))
#else
-#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
+#define HUFF_EXTEND(x, s) \
+ ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
-static const int extend_test[16] = /* entry n is 2**(n-1) */
- { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
- 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
+static const int extend_test[16] = { /* entry n is 2**(n-1) */
+ 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
+ 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000
+};
-static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
- { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
- ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
- ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
- ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
+static const int extend_offset[16] = { /* entry n is (-1 << n) + 1 */
+ 0, ((-1) << 1) + 1, ((-1) << 2) + 1, ((-1) << 3) + 1, ((-1) << 4) + 1,
+ ((-1) << 5) + 1, ((-1) << 6) + 1, ((-1) << 7) + 1, ((-1) << 8) + 1,
+ ((-1) << 9) + 1, ((-1) << 10) + 1, ((-1) << 11) + 1, ((-1) << 12) + 1,
+ ((-1) << 13) + 1, ((-1) << 14) + 1, ((-1) << 15) + 1
+};
#endif /* AVOID_TABLES */
@@ -518,9 +524,9 @@ static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
*/
LOCAL(boolean)
-process_restart (j_decompress_ptr cinfo)
+process_restart(j_decompress_ptr cinfo)
{
- huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
int ci;
/* Throw away any unused bits remaining in bit buffer; */
@@ -529,7 +535,7 @@ process_restart (j_decompress_ptr cinfo)
entropy->bitstate.bits_left = 0;
/* Advance past the RSTn marker */
- if (! (*cinfo->marker->read_restart_marker) (cinfo))
+ if (!(*cinfo->marker->read_restart_marker) (cinfo))
return FALSE;
/* Re-initialize DC predictions to 0 */
@@ -552,16 +558,16 @@ process_restart (j_decompress_ptr cinfo)
LOCAL(boolean)
-decode_mcu_slow (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+decode_mcu_slow(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
- huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
BITREAD_STATE_VARS;
int blkn;
savable_state state;
/* Outer loop handles each block in the MCU */
/* Load up working state */
- BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+ BITREAD_LOAD_STATE(cinfo, entropy->bitstate);
ASSIGN_STATE(state, entropy->saved);
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
@@ -587,7 +593,7 @@ decode_mcu_slow (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
state.last_dc_val[ci] = s;
if (block) {
/* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */
- (*block)[0] = (JCOEF) s;
+ (*block)[0] = (JCOEF)s;
}
}
@@ -610,7 +616,7 @@ decode_mcu_slow (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
* Note: the extra entries in jpeg_natural_order[] will save us
* if k >= DCTSIZE2, which could happen if the data is corrupted.
*/
- (*block)[jpeg_natural_order[k]] = (JCOEF) s;
+ (*block)[jpeg_natural_order[k]] = (JCOEF)s;
} else {
if (r != 15)
break;
@@ -642,16 +648,16 @@ decode_mcu_slow (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
}
/* Completed MCU, so update state */
- BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ BITREAD_SAVE_STATE(cinfo, entropy->bitstate);
ASSIGN_STATE(entropy->saved, state);
return TRUE;
}
LOCAL(boolean)
-decode_mcu_fast (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+decode_mcu_fast(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
- huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
BITREAD_STATE_VARS;
JOCTET *buffer;
int blkn;
@@ -659,8 +665,8 @@ decode_mcu_fast (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
/* Outer loop handles each block in the MCU */
/* Load up working state */
- BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
- buffer = (JOCTET *) br_state.next_input_byte;
+ BITREAD_LOAD_STATE(cinfo, entropy->bitstate);
+ buffer = (JOCTET *)br_state.next_input_byte;
ASSIGN_STATE(state, entropy->saved);
for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
@@ -681,7 +687,7 @@ decode_mcu_fast (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
s += state.last_dc_val[ci];
state.last_dc_val[ci] = s;
if (block)
- (*block)[0] = (JCOEF) s;
+ (*block)[0] = (JCOEF)s;
}
if (entropy->ac_needed[blkn] && block) {
@@ -696,7 +702,7 @@ decode_mcu_fast (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
FILL_BIT_BUFFER_FAST
r = GET_BITS(s);
s = HUFF_EXTEND(r, s);
- (*block)[jpeg_natural_order[k]] = (JCOEF) s;
+ (*block)[jpeg_natural_order[k]] = (JCOEF)s;
} else {
if (r != 15) break;
k += 15;
@@ -729,7 +735,7 @@ decode_mcu_fast (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
br_state.bytes_in_buffer -= (buffer - br_state.next_input_byte);
br_state.next_input_byte = buffer;
- BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ BITREAD_SAVE_STATE(cinfo, entropy->bitstate);
ASSIGN_STATE(entropy->saved, state);
return TRUE;
}
@@ -750,36 +756,35 @@ decode_mcu_fast (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
* this module, since we'll just re-assign them on the next call.)
*/
-#define BUFSIZE (DCTSIZE2 * 8)
+#define BUFSIZE (DCTSIZE2 * 8)
METHODDEF(boolean)
-decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+decode_mcu(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
- huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ huff_entropy_ptr entropy = (huff_entropy_ptr)cinfo->entropy;
int usefast = 1;
/* Process restart marker if needed; may have to suspend */
if (cinfo->restart_interval) {
if (entropy->restarts_to_go == 0)
- if (! process_restart(cinfo))
+ if (!process_restart(cinfo))
return FALSE;
usefast = 0;
}
- if (cinfo->src->bytes_in_buffer < BUFSIZE * (size_t)cinfo->blocks_in_MCU
- || cinfo->unread_marker != 0)
+ if (cinfo->src->bytes_in_buffer < BUFSIZE * (size_t)cinfo->blocks_in_MCU ||
+ cinfo->unread_marker != 0)
usefast = 0;
/* If we've run out of data, just leave the MCU set to zeroes.
* This way, we return uniform gray for the remainder of the segment.
*/
- if (! entropy->pub.insufficient_data) {
+ if (!entropy->pub.insufficient_data) {
if (usefast) {
if (!decode_mcu_fast(cinfo, MCU_data)) goto use_slow;
- }
- else {
- use_slow:
+ } else {
+use_slow:
if (!decode_mcu_slow(cinfo, MCU_data)) return FALSE;
}
@@ -797,7 +802,7 @@ decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
*/
GLOBAL(void)
-jinit_huff_decoder (j_decompress_ptr cinfo)
+jinit_huff_decoder(j_decompress_ptr cinfo)
{
huff_entropy_ptr entropy;
int i;
@@ -806,12 +811,12 @@ jinit_huff_decoder (j_decompress_ptr cinfo)
are the default tables. Thus, if the tables are not set by the time
the Huffman decoder is initialized (usually within the body of
jpeg_start_decompress()), we set them to default values. */
- std_huff_tables((j_common_ptr) cinfo);
+ std_huff_tables((j_common_ptr)cinfo);
entropy = (huff_entropy_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(huff_entropy_decoder));
- cinfo->entropy = (struct jpeg_entropy_decoder *) entropy;
+ cinfo->entropy = (struct jpeg_entropy_decoder *)entropy;
entropy->pub.start_pass = start_pass_huff_decoder;
entropy->pub.decode_mcu = decode_mcu;
diff --git a/src/3rdparty/libjpeg/src/jdhuff.h b/src/3rdparty/libjpeg/src/jdhuff.h
index 87d4465ffb..6a8d90f402 100644
--- a/src/3rdparty/libjpeg/src/jdhuff.h
+++ b/src/3rdparty/libjpeg/src/jdhuff.h
@@ -43,13 +43,12 @@ typedef struct {
* if too long. The next 8 bits of each entry contain the
* symbol.
*/
- int lookup[1<<HUFF_LOOKAHEAD];
+ int lookup[1 << HUFF_LOOKAHEAD];
} d_derived_tbl;
/* Expand a Huffman table definition into the derived format */
-EXTERN(void) jpeg_make_d_derived_tbl
- (j_decompress_ptr cinfo, boolean isDC, int tblno,
- d_derived_tbl ** pdtbl);
+EXTERN(void) jpeg_make_d_derived_tbl(j_decompress_ptr cinfo, boolean isDC,
+ int tblno, d_derived_tbl **pdtbl);
/*
@@ -74,7 +73,7 @@ EXTERN(void) jpeg_make_d_derived_tbl
#error Cannot determine word size
#endif
-#if SIZEOF_SIZE_T==8 || defined(_WIN64)
+#if SIZEOF_SIZE_T == 8 || defined(_WIN64)
typedef size_t bit_buf_type; /* type of bit-extraction buffer */
#define BIT_BUF_SIZE 64 /* size of buffer in bits */
@@ -113,23 +112,23 @@ typedef struct { /* Bitreading working state within an MCU */
} bitread_working_state;
/* Macros to declare and load/save bitread local variables. */
-#define BITREAD_STATE_VARS \
- register bit_buf_type get_buffer; \
- register int bits_left; \
- bitread_working_state br_state
-
-#define BITREAD_LOAD_STATE(cinfop,permstate) \
- br_state.cinfo = cinfop; \
- br_state.next_input_byte = cinfop->src->next_input_byte; \
- br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \
- get_buffer = permstate.get_buffer; \
- bits_left = permstate.bits_left;
-
-#define BITREAD_SAVE_STATE(cinfop,permstate) \
- cinfop->src->next_input_byte = br_state.next_input_byte; \
- cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \
- permstate.get_buffer = get_buffer; \
- permstate.bits_left = bits_left
+#define BITREAD_STATE_VARS \
+ register bit_buf_type get_buffer; \
+ register int bits_left; \
+ bitread_working_state br_state
+
+#define BITREAD_LOAD_STATE(cinfop, permstate) \
+ br_state.cinfo = cinfop; \
+ br_state.next_input_byte = cinfop->src->next_input_byte; \
+ br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \
+ get_buffer = permstate.get_buffer; \
+ bits_left = permstate.bits_left;
+
+#define BITREAD_SAVE_STATE(cinfop, permstate) \
+ cinfop->src->next_input_byte = br_state.next_input_byte; \
+ cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \
+ permstate.get_buffer = get_buffer; \
+ permstate.bits_left = bits_left
/*
* These macros provide the in-line portion of bit fetching.
@@ -137,7 +136,7 @@ typedef struct { /* Bitreading working state within an MCU */
* before using GET_BITS, PEEK_BITS, or DROP_BITS.
* The variables get_buffer and bits_left are assumed to be locals,
* but the state struct might not be (jpeg_huff_decode needs this).
- * CHECK_BIT_BUFFER(state,n,action);
+ * CHECK_BIT_BUFFER(state, n, action);
* Ensure there are N bits in get_buffer; if suspend, take action.
* val = GET_BITS(n);
* Fetch next N bits.
@@ -149,25 +148,27 @@ typedef struct { /* Bitreading working state within an MCU */
* is evaluated multiple times.
*/
-#define CHECK_BIT_BUFFER(state,nbits,action) \
- { if (bits_left < (nbits)) { \
- if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \
- { action; } \
- get_buffer = (state).get_buffer; bits_left = (state).bits_left; } }
+#define CHECK_BIT_BUFFER(state, nbits, action) { \
+ if (bits_left < (nbits)) { \
+ if (!jpeg_fill_bit_buffer(&(state), get_buffer, bits_left, nbits)) \
+ { action; } \
+ get_buffer = (state).get_buffer; bits_left = (state).bits_left; \
+ } \
+}
#define GET_BITS(nbits) \
- (((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1))
+ (((int)(get_buffer >> (bits_left -= (nbits)))) & ((1 << (nbits)) - 1))
#define PEEK_BITS(nbits) \
- (((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1))
+ (((int)(get_buffer >> (bits_left - (nbits)))) & ((1 << (nbits)) - 1))
#define DROP_BITS(nbits) \
- (bits_left -= (nbits))
+ (bits_left -= (nbits))
/* Load up the bit buffer to a depth of at least nbits */
-EXTERN(boolean) jpeg_fill_bit_buffer
- (bitread_working_state *state, register bit_buf_type get_buffer,
- register int bits_left, int nbits);
+EXTERN(boolean) jpeg_fill_bit_buffer(bitread_working_state *state,
+ register bit_buf_type get_buffer,
+ register int bits_left, int nbits);
/*
@@ -187,13 +188,14 @@ EXTERN(boolean) jpeg_fill_bit_buffer
* 3. jpeg_huff_decode returns -1 if forced to suspend.
*/
-#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \
-{ register int nb, look; \
+#define HUFF_DECODE(result, state, htbl, failaction, slowlabel) { \
+ register int nb, look; \
if (bits_left < HUFF_LOOKAHEAD) { \
- if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \
- get_buffer = state.get_buffer; bits_left = state.bits_left; \
+ if (!jpeg_fill_bit_buffer(&state, get_buffer, bits_left, 0)) \
+ { failaction; } \
+ get_buffer = state.get_buffer; bits_left = state.bits_left; \
if (bits_left < HUFF_LOOKAHEAD) { \
- nb = 1; goto slowlabel; \
+ nb = 1; goto slowlabel; \
} \
} \
look = PEEK_BITS(HUFF_LOOKAHEAD); \
@@ -202,13 +204,14 @@ EXTERN(boolean) jpeg_fill_bit_buffer
result = htbl->lookup[look] & ((1 << HUFF_LOOKAHEAD) - 1); \
} else { \
slowlabel: \
- if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \
- { failaction; } \
- get_buffer = state.get_buffer; bits_left = state.bits_left; \
+ if ((result = \
+ jpeg_huff_decode(&state, get_buffer, bits_left, htbl, nb)) < 0) \
+ { failaction; } \
+ get_buffer = state.get_buffer; bits_left = state.bits_left; \
} \
}
-#define HUFF_DECODE_FAST(s,nb,htbl) \
+#define HUFF_DECODE_FAST(s, nb, htbl) \
FILL_BIT_BUFFER_FAST; \
s = PEEK_BITS(HUFF_LOOKAHEAD); \
s = htbl->lookup[s]; \
@@ -225,10 +228,11 @@ slowlabel: \
s |= GET_BITS(1); \
nb++; \
} \
- s = htbl->pub->huffval[ (int) (s + htbl->valoffset[nb]) & 0xFF ]; \
+ s = htbl->pub->huffval[(int)(s + htbl->valoffset[nb]) & 0xFF]; \
}
/* Out-of-line case for Huffman code fetching */
-EXTERN(int) jpeg_huff_decode
- (bitread_working_state *state, register bit_buf_type get_buffer,
- register int bits_left, d_derived_tbl *htbl, int min_bits);
+EXTERN(int) jpeg_huff_decode(bitread_working_state *state,
+ register bit_buf_type get_buffer,
+ register int bits_left, d_derived_tbl *htbl,
+ int min_bits);
diff --git a/src/3rdparty/libjpeg/src/jdinput.c b/src/3rdparty/libjpeg/src/jdinput.c
index 32a6b424e2..deec618f26 100644
--- a/src/3rdparty/libjpeg/src/jdinput.c
+++ b/src/3rdparty/libjpeg/src/jdinput.c
@@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1997, Thomas G. Lane.
* libjpeg-turbo Modifications:
- * Copyright (C) 2010, 2016, D. R. Commander.
+ * Copyright (C) 2010, 2016, 2018, D. R. Commander.
* Copyright (C) 2015, Google, Inc.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
@@ -33,7 +33,7 @@ typedef my_input_controller *my_inputctl_ptr;
/* Forward declarations */
-METHODDEF(int) consume_markers (j_decompress_ptr cinfo);
+METHODDEF(int) consume_markers(j_decompress_ptr cinfo);
/*
@@ -41,16 +41,16 @@ METHODDEF(int) consume_markers (j_decompress_ptr cinfo);
*/
LOCAL(void)
-initial_setup (j_decompress_ptr cinfo)
+initial_setup(j_decompress_ptr cinfo)
/* Called once, when first SOS marker is reached */
{
int ci;
jpeg_component_info *compptr;
/* Make sure image isn't bigger than I can handle */
- if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION ||
- (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION)
- ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
+ if ((long)cinfo->image_height > (long)JPEG_MAX_DIMENSION ||
+ (long)cinfo->image_width > (long)JPEG_MAX_DIMENSION)
+ ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int)JPEG_MAX_DIMENSION);
/* For now, precision must match compiled-in value... */
if (cinfo->data_precision != BITS_IN_JSAMPLE)
@@ -66,8 +66,10 @@ initial_setup (j_decompress_ptr cinfo)
cinfo->max_v_samp_factor = 1;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
ci++, compptr++) {
- if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
- compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
+ if (compptr->h_samp_factor <= 0 ||
+ compptr->h_samp_factor > MAX_SAMP_FACTOR ||
+ compptr->v_samp_factor <= 0 ||
+ compptr->v_samp_factor > MAX_SAMP_FACTOR)
ERREXIT(cinfo, JERR_BAD_SAMPLING);
cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
compptr->h_samp_factor);
@@ -75,10 +77,10 @@ initial_setup (j_decompress_ptr cinfo)
compptr->v_samp_factor);
}
-#if JPEG_LIB_VERSION >=80
- cinfo->block_size = DCTSIZE;
- cinfo->natural_order = jpeg_natural_order;
- cinfo->lim_Se = DCTSIZE2-1;
+#if JPEG_LIB_VERSION >= 80
+ cinfo->block_size = DCTSIZE;
+ cinfo->natural_order = jpeg_natural_order;
+ cinfo->lim_Se = DCTSIZE2 - 1;
#endif
/* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE.
@@ -101,11 +103,11 @@ initial_setup (j_decompress_ptr cinfo)
#endif
/* Size in DCT blocks */
compptr->width_in_blocks = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
- (long) (cinfo->max_h_samp_factor * DCTSIZE));
+ jdiv_round_up((long)cinfo->image_width * (long)compptr->h_samp_factor,
+ (long)(cinfo->max_h_samp_factor * DCTSIZE));
compptr->height_in_blocks = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
- (long) (cinfo->max_v_samp_factor * DCTSIZE));
+ jdiv_round_up((long)cinfo->image_height * (long)compptr->v_samp_factor,
+ (long)(cinfo->max_v_samp_factor * DCTSIZE));
/* Set the first and last MCU columns to decompress from multi-scan images.
* By default, decompress all of the MCU columns.
*/
@@ -117,11 +119,11 @@ initial_setup (j_decompress_ptr cinfo)
*/
/* Size in samples */
compptr->downsampled_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
- (long) cinfo->max_h_samp_factor);
+ jdiv_round_up((long)cinfo->image_width * (long)compptr->h_samp_factor,
+ (long)cinfo->max_h_samp_factor);
compptr->downsampled_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
- (long) cinfo->max_v_samp_factor);
+ jdiv_round_up((long)cinfo->image_height * (long)compptr->v_samp_factor,
+ (long)cinfo->max_v_samp_factor);
/* Mark component needed, until color conversion says otherwise */
compptr->component_needed = TRUE;
/* Mark no quantization table yet saved for component */
@@ -130,8 +132,8 @@ initial_setup (j_decompress_ptr cinfo)
/* Compute number of fully interleaved MCU rows. */
cinfo->total_iMCU_rows = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height,
- (long) (cinfo->max_v_samp_factor*DCTSIZE));
+ jdiv_round_up((long)cinfo->image_height,
+ (long)(cinfo->max_v_samp_factor * DCTSIZE));
/* Decide whether file contains multiple scans */
if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode)
@@ -142,7 +144,7 @@ initial_setup (j_decompress_ptr cinfo)
LOCAL(void)
-per_scan_setup (j_decompress_ptr cinfo)
+per_scan_setup(j_decompress_ptr cinfo)
/* Do computations that are needed before processing a JPEG scan */
/* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */
{
@@ -167,7 +169,7 @@ per_scan_setup (j_decompress_ptr cinfo)
/* For noninterleaved scans, it is convenient to define last_row_height
* as the number of block rows present in the last iMCU row.
*/
- tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
+ tmp = (int)(compptr->height_in_blocks % compptr->v_samp_factor);
if (tmp == 0) tmp = compptr->v_samp_factor;
compptr->last_row_height = tmp;
@@ -184,11 +186,11 @@ per_scan_setup (j_decompress_ptr cinfo)
/* Overall image size in MCUs */
cinfo->MCUs_per_row = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width,
- (long) (cinfo->max_h_samp_factor*DCTSIZE));
+ jdiv_round_up((long)cinfo->image_width,
+ (long)(cinfo->max_h_samp_factor * DCTSIZE));
cinfo->MCU_rows_in_scan = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height,
- (long) (cinfo->max_v_samp_factor*DCTSIZE));
+ jdiv_round_up((long)cinfo->image_height,
+ (long)(cinfo->max_v_samp_factor * DCTSIZE));
cinfo->blocks_in_MCU = 0;
@@ -198,12 +200,13 @@ per_scan_setup (j_decompress_ptr cinfo)
compptr->MCU_width = compptr->h_samp_factor;
compptr->MCU_height = compptr->v_samp_factor;
compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
- compptr->MCU_sample_width = compptr->MCU_width * compptr->_DCT_scaled_size;
+ compptr->MCU_sample_width = compptr->MCU_width *
+ compptr->_DCT_scaled_size;
/* Figure number of non-dummy blocks in last MCU column & row */
- tmp = (int) (compptr->width_in_blocks % compptr->MCU_width);
+ tmp = (int)(compptr->width_in_blocks % compptr->MCU_width);
if (tmp == 0) tmp = compptr->MCU_width;
compptr->last_col_width = tmp;
- tmp = (int) (compptr->height_in_blocks % compptr->MCU_height);
+ tmp = (int)(compptr->height_in_blocks % compptr->MCU_height);
if (tmp == 0) tmp = compptr->MCU_height;
compptr->last_row_height = tmp;
/* Prepare array describing MCU composition */
@@ -231,17 +234,17 @@ per_scan_setup (j_decompress_ptr cinfo)
* means that we have to save away the table actually used for each component.
* We do this by copying the table at the start of the first scan containing
* the component.
- * The JPEG spec prohibits the encoder from changing the contents of a Q-table
- * slot between scans of a component using that slot. If the encoder does so
- * anyway, this decoder will simply use the Q-table values that were current
- * at the start of the first scan for the component.
+ * Rec. ITU-T T.81 | ISO/IEC 10918-1 prohibits the encoder from changing the
+ * contents of a Q-table slot between scans of a component using that slot. If
+ * the encoder does so anyway, this decoder will simply use the Q-table values
+ * that were current at the start of the first scan for the component.
*
* The decompressor output side looks only at the saved quant tables,
* not at the current Q-table slots.
*/
LOCAL(void)
-latch_quant_tables (j_decompress_ptr cinfo)
+latch_quant_tables(j_decompress_ptr cinfo)
{
int ci, qtblno;
jpeg_component_info *compptr;
@@ -259,7 +262,7 @@ latch_quant_tables (j_decompress_ptr cinfo)
ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
/* OK, save away the quantization table */
qtbl = (JQUANT_TBL *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(JQUANT_TBL));
MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], sizeof(JQUANT_TBL));
compptr->quant_table = qtbl;
@@ -275,7 +278,7 @@ latch_quant_tables (j_decompress_ptr cinfo)
*/
METHODDEF(void)
-start_input_pass (j_decompress_ptr cinfo)
+start_input_pass(j_decompress_ptr cinfo)
{
per_scan_setup(cinfo);
latch_quant_tables(cinfo);
@@ -292,7 +295,7 @@ start_input_pass (j_decompress_ptr cinfo)
*/
METHODDEF(void)
-finish_input_pass (j_decompress_ptr cinfo)
+finish_input_pass(j_decompress_ptr cinfo)
{
cinfo->inputctl->consume_input = consume_markers;
}
@@ -309,9 +312,9 @@ finish_input_pass (j_decompress_ptr cinfo)
*/
METHODDEF(int)
-consume_markers (j_decompress_ptr cinfo)
+consume_markers(j_decompress_ptr cinfo)
{
- my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl;
+ my_inputctl_ptr inputctl = (my_inputctl_ptr)cinfo->inputctl;
int val;
if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */
@@ -329,7 +332,7 @@ consume_markers (j_decompress_ptr cinfo)
* responsible for enforcing this sequencing.
*/
} else { /* 2nd or later SOS marker */
- if (! inputctl->pub.has_multiple_scans)
+ if (!inputctl->pub.has_multiple_scans)
ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */
start_input_pass(cinfo);
}
@@ -360,16 +363,16 @@ consume_markers (j_decompress_ptr cinfo)
*/
METHODDEF(void)
-reset_input_controller (j_decompress_ptr cinfo)
+reset_input_controller(j_decompress_ptr cinfo)
{
- my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl;
+ my_inputctl_ptr inputctl = (my_inputctl_ptr)cinfo->inputctl;
inputctl->pub.consume_input = consume_markers;
inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */
inputctl->pub.eoi_reached = FALSE;
inputctl->inheaders = TRUE;
/* Reset other modules */
- (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
+ (*cinfo->err->reset_error_mgr) ((j_common_ptr)cinfo);
(*cinfo->marker->reset_marker_reader) (cinfo);
/* Reset progression state -- would be cleaner if entropy decoder did this */
cinfo->coef_bits = NULL;
@@ -382,15 +385,15 @@ reset_input_controller (j_decompress_ptr cinfo)
*/
GLOBAL(void)
-jinit_input_controller (j_decompress_ptr cinfo)
+jinit_input_controller(j_decompress_ptr cinfo)
{
my_inputctl_ptr inputctl;
/* Create subobject in permanent pool */
inputctl = (my_inputctl_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
sizeof(my_input_controller));
- cinfo->inputctl = (struct jpeg_input_controller *) inputctl;
+ cinfo->inputctl = (struct jpeg_input_controller *)inputctl;
/* Initialize method pointers */
inputctl->pub.consume_input = consume_markers;
inputctl->pub.reset_input_controller = reset_input_controller;
diff --git a/src/3rdparty/libjpeg/src/jdmainct.c b/src/3rdparty/libjpeg/src/jdmainct.c
index ebb069b0f4..50301d6b50 100644
--- a/src/3rdparty/libjpeg/src/jdmainct.c
+++ b/src/3rdparty/libjpeg/src/jdmainct.c
@@ -112,26 +112,29 @@
/* Forward declarations */
-METHODDEF(void) process_data_simple_main
- (j_decompress_ptr cinfo, JSAMPARRAY output_buf,
- JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail);
-METHODDEF(void) process_data_context_main
- (j_decompress_ptr cinfo, JSAMPARRAY output_buf,
- JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail);
+METHODDEF(void) process_data_simple_main(j_decompress_ptr cinfo,
+ JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail);
+METHODDEF(void) process_data_context_main(j_decompress_ptr cinfo,
+ JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail);
#ifdef QUANT_2PASS_SUPPORTED
-METHODDEF(void) process_data_crank_post
- (j_decompress_ptr cinfo, JSAMPARRAY output_buf,
- JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail);
+METHODDEF(void) process_data_crank_post(j_decompress_ptr cinfo,
+ JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail);
#endif
LOCAL(void)
-alloc_funny_pointers (j_decompress_ptr cinfo)
+alloc_funny_pointers(j_decompress_ptr cinfo)
/* Allocate space for the funny pointer lists.
* This is done only once, not once per pass.
*/
{
- my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
+ my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
int ci, rgroup;
int M = cinfo->_min_DCT_scaled_size;
jpeg_component_info *compptr;
@@ -141,7 +144,7 @@ alloc_funny_pointers (j_decompress_ptr cinfo)
* We alloc both arrays with one call to save a few cycles.
*/
main_ptr->xbuffer[0] = (JSAMPIMAGE)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
cinfo->num_components * 2 * sizeof(JSAMPARRAY));
main_ptr->xbuffer[1] = main_ptr->xbuffer[0] + cinfo->num_components;
@@ -153,7 +156,7 @@ alloc_funny_pointers (j_decompress_ptr cinfo)
* We alloc both pointer lists with one call to save a few cycles.
*/
xbuf = (JSAMPARRAY)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
2 * (rgroup * (M + 4)) * sizeof(JSAMPROW));
xbuf += rgroup; /* want one row group at negative offsets */
main_ptr->xbuffer[0][ci] = xbuf;
@@ -164,7 +167,7 @@ alloc_funny_pointers (j_decompress_ptr cinfo)
LOCAL(void)
-make_funny_pointers (j_decompress_ptr cinfo)
+make_funny_pointers(j_decompress_ptr cinfo)
/* Create the funny pointer lists discussed in the comments above.
* The actual workspace is already allocated (in main_ptr->buffer),
* and the space for the pointer lists is allocated too.
@@ -172,7 +175,7 @@ make_funny_pointers (j_decompress_ptr cinfo)
* This will be repeated at the beginning of each pass.
*/
{
- my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
+ my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
int ci, i, rgroup;
int M = cinfo->_min_DCT_scaled_size;
jpeg_component_info *compptr;
@@ -191,8 +194,8 @@ make_funny_pointers (j_decompress_ptr cinfo)
}
/* In the second list, put the last four row groups in swapped order */
for (i = 0; i < rgroup * 2; i++) {
- xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i];
- xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i];
+ xbuf1[rgroup * (M - 2) + i] = buf[rgroup * M + i];
+ xbuf1[rgroup * M + i] = buf[rgroup * (M - 2) + i];
}
/* The wraparound pointers at top and bottom will be filled later
* (see set_wraparound_pointers, below). Initially we want the "above"
@@ -207,13 +210,13 @@ make_funny_pointers (j_decompress_ptr cinfo)
LOCAL(void)
-set_bottom_pointers (j_decompress_ptr cinfo)
+set_bottom_pointers(j_decompress_ptr cinfo)
/* Change the pointer lists to duplicate the last sample row at the bottom
* of the image. whichptr indicates which xbuffer holds the final iMCU row.
* Also sets rowgroups_avail to indicate number of nondummy row groups in row.
*/
{
- my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
+ my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
int ci, i, rgroup, iMCUheight, rows_left;
jpeg_component_info *compptr;
JSAMPARRAY xbuf;
@@ -224,20 +227,20 @@ set_bottom_pointers (j_decompress_ptr cinfo)
iMCUheight = compptr->v_samp_factor * compptr->_DCT_scaled_size;
rgroup = iMCUheight / cinfo->_min_DCT_scaled_size;
/* Count nondummy sample rows remaining for this component */
- rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight);
+ rows_left = (int)(compptr->downsampled_height % (JDIMENSION)iMCUheight);
if (rows_left == 0) rows_left = iMCUheight;
/* Count nondummy row groups. Should get same answer for each component,
* so we need only do it once.
*/
if (ci == 0) {
- main_ptr->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1);
+ main_ptr->rowgroups_avail = (JDIMENSION)((rows_left - 1) / rgroup + 1);
}
/* Duplicate the last real sample row rgroup*2 times; this pads out the
* last partial rowgroup and ensures at least one full rowgroup of context.
*/
xbuf = main_ptr->xbuffer[main_ptr->whichptr][ci];
for (i = 0; i < rgroup * 2; i++) {
- xbuf[rows_left + i] = xbuf[rows_left-1];
+ xbuf[rows_left + i] = xbuf[rows_left - 1];
}
}
}
@@ -248,9 +251,9 @@ set_bottom_pointers (j_decompress_ptr cinfo)
*/
METHODDEF(void)
-start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
+start_pass_main(j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
{
- my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
+ my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
switch (pass_mode) {
case JBUF_PASS_THRU:
@@ -286,22 +289,21 @@ start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
*/
METHODDEF(void)
-process_data_simple_main (j_decompress_ptr cinfo,
- JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
- JDIMENSION out_rows_avail)
+process_data_simple_main(j_decompress_ptr cinfo, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)
{
- my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
+ my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
JDIMENSION rowgroups_avail;
/* Read input data if we haven't filled the main buffer yet */
- if (! main_ptr->buffer_full) {
- if (! (*cinfo->coef->decompress_data) (cinfo, main_ptr->buffer))
+ if (!main_ptr->buffer_full) {
+ if (!(*cinfo->coef->decompress_data) (cinfo, main_ptr->buffer))
return; /* suspension forced, can do nothing more */
main_ptr->buffer_full = TRUE; /* OK, we have an iMCU row to work with */
}
/* There are always min_DCT_scaled_size row groups in an iMCU row. */
- rowgroups_avail = (JDIMENSION) cinfo->_min_DCT_scaled_size;
+ rowgroups_avail = (JDIMENSION)cinfo->_min_DCT_scaled_size;
/* Note: at the bottom of the image, we may pass extra garbage row groups
* to the postprocessor. The postprocessor has to check for bottom
* of image anyway (at row resolution), so no point in us doing it too.
@@ -326,16 +328,15 @@ process_data_simple_main (j_decompress_ptr cinfo,
*/
METHODDEF(void)
-process_data_context_main (j_decompress_ptr cinfo,
- JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
- JDIMENSION out_rows_avail)
+process_data_context_main(j_decompress_ptr cinfo, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)
{
- my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
+ my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
/* Read input data if we haven't filled the main buffer yet */
- if (! main_ptr->buffer_full) {
- if (! (*cinfo->coef->decompress_data) (cinfo,
- main_ptr->xbuffer[main_ptr->whichptr]))
+ if (!main_ptr->buffer_full) {
+ if (!(*cinfo->coef->decompress_data) (cinfo,
+ main_ptr->xbuffer[main_ptr->whichptr]))
return; /* suspension forced, can do nothing more */
main_ptr->buffer_full = TRUE; /* OK, we have an iMCU row to work with */
main_ptr->iMCU_row_ctr++; /* count rows received */
@@ -349,9 +350,11 @@ process_data_context_main (j_decompress_ptr cinfo,
switch (main_ptr->context_state) {
case CTX_POSTPONED_ROW:
/* Call postprocessor using previously set pointers for postponed row */
- (*cinfo->post->post_process_data) (cinfo, main_ptr->xbuffer[main_ptr->whichptr],
- &main_ptr->rowgroup_ctr, main_ptr->rowgroups_avail,
- output_buf, out_row_ctr, out_rows_avail);
+ (*cinfo->post->post_process_data) (cinfo,
+ main_ptr->xbuffer[main_ptr->whichptr],
+ &main_ptr->rowgroup_ctr,
+ main_ptr->rowgroups_avail, output_buf,
+ out_row_ctr, out_rows_avail);
if (main_ptr->rowgroup_ctr < main_ptr->rowgroups_avail)
return; /* Need to suspend */
main_ptr->context_state = CTX_PREPARE_FOR_IMCU;
@@ -361,7 +364,7 @@ process_data_context_main (j_decompress_ptr cinfo,
case CTX_PREPARE_FOR_IMCU:
/* Prepare to process first M-1 row groups of this iMCU row */
main_ptr->rowgroup_ctr = 0;
- main_ptr->rowgroups_avail = (JDIMENSION) (cinfo->_min_DCT_scaled_size - 1);
+ main_ptr->rowgroups_avail = (JDIMENSION)(cinfo->_min_DCT_scaled_size - 1);
/* Check for bottom of image: if so, tweak pointers to "duplicate"
* the last sample row, and adjust rowgroups_avail to ignore padding rows.
*/
@@ -371,9 +374,11 @@ process_data_context_main (j_decompress_ptr cinfo,
/*FALLTHROUGH*/
case CTX_PROCESS_IMCU:
/* Call postprocessor using previously set pointers */
- (*cinfo->post->post_process_data) (cinfo, main_ptr->xbuffer[main_ptr->whichptr],
- &main_ptr->rowgroup_ctr, main_ptr->rowgroups_avail,
- output_buf, out_row_ctr, out_rows_avail);
+ (*cinfo->post->post_process_data) (cinfo,
+ main_ptr->xbuffer[main_ptr->whichptr],
+ &main_ptr->rowgroup_ctr,
+ main_ptr->rowgroups_avail, output_buf,
+ out_row_ctr, out_rows_avail);
if (main_ptr->rowgroup_ctr < main_ptr->rowgroups_avail)
return; /* Need to suspend */
/* After the first iMCU, change wraparound pointers to normal state */
@@ -384,8 +389,8 @@ process_data_context_main (j_decompress_ptr cinfo,
main_ptr->buffer_full = FALSE;
/* Still need to process last row group of this iMCU row, */
/* which is saved at index M+1 of the other xbuffer */
- main_ptr->rowgroup_ctr = (JDIMENSION) (cinfo->_min_DCT_scaled_size + 1);
- main_ptr->rowgroups_avail = (JDIMENSION) (cinfo->_min_DCT_scaled_size + 2);
+ main_ptr->rowgroup_ctr = (JDIMENSION)(cinfo->_min_DCT_scaled_size + 1);
+ main_ptr->rowgroups_avail = (JDIMENSION)(cinfo->_min_DCT_scaled_size + 2);
main_ptr->context_state = CTX_POSTPONED_ROW;
}
}
@@ -400,12 +405,11 @@ process_data_context_main (j_decompress_ptr cinfo,
#ifdef QUANT_2PASS_SUPPORTED
METHODDEF(void)
-process_data_crank_post (j_decompress_ptr cinfo,
- JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
- JDIMENSION out_rows_avail)
+process_data_crank_post(j_decompress_ptr cinfo, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)
{
- (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL,
- (JDIMENSION *) NULL, (JDIMENSION) 0,
+ (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE)NULL,
+ (JDIMENSION *)NULL, (JDIMENSION)0,
output_buf, out_row_ctr, out_rows_avail);
}
@@ -417,16 +421,16 @@ process_data_crank_post (j_decompress_ptr cinfo,
*/
GLOBAL(void)
-jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
+jinit_d_main_controller(j_decompress_ptr cinfo, boolean need_full_buffer)
{
my_main_ptr main_ptr;
int ci, rgroup, ngroups;
jpeg_component_info *compptr;
main_ptr = (my_main_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_main_controller));
- cinfo->main = (struct jpeg_d_main_controller *) main_ptr;
+ cinfo->main = (struct jpeg_d_main_controller *)main_ptr;
main_ptr->pub.start_pass = start_pass_main;
if (need_full_buffer) /* shouldn't happen */
@@ -449,8 +453,8 @@ jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
rgroup = (compptr->v_samp_factor * compptr->_DCT_scaled_size) /
cinfo->_min_DCT_scaled_size; /* height of a row group of component */
main_ptr->buffer[ci] = (*cinfo->mem->alloc_sarray)
- ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ ((j_common_ptr)cinfo, JPOOL_IMAGE,
compptr->width_in_blocks * compptr->_DCT_scaled_size,
- (JDIMENSION) (rgroup * ngroups));
+ (JDIMENSION)(rgroup * ngroups));
}
}
diff --git a/src/3rdparty/libjpeg/src/jdmainct.h b/src/3rdparty/libjpeg/src/jdmainct.h
index 30903019ca..37b201ca88 100644
--- a/src/3rdparty/libjpeg/src/jdmainct.h
+++ b/src/3rdparty/libjpeg/src/jdmainct.h
@@ -44,12 +44,12 @@ typedef my_main_controller *my_main_ptr;
LOCAL(void)
-set_wraparound_pointers (j_decompress_ptr cinfo)
+set_wraparound_pointers(j_decompress_ptr cinfo)
/* Set up the "wraparound" pointers at top and bottom of the pointer lists.
* This changes the pointer list state from top-of-image to the normal state.
*/
{
- my_main_ptr main_ptr = (my_main_ptr) cinfo->main;
+ my_main_ptr main_ptr = (my_main_ptr)cinfo->main;
int ci, i, rgroup;
int M = cinfo->_min_DCT_scaled_size;
jpeg_component_info *compptr;
@@ -62,10 +62,10 @@ set_wraparound_pointers (j_decompress_ptr cinfo)
xbuf0 = main_ptr->xbuffer[0][ci];
xbuf1 = main_ptr->xbuffer[1][ci];
for (i = 0; i < rgroup; i++) {
- xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i];
- xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i];
- xbuf0[rgroup*(M+2) + i] = xbuf0[i];
- xbuf1[rgroup*(M+2) + i] = xbuf1[i];
+ xbuf0[i - rgroup] = xbuf0[rgroup * (M + 1) + i];
+ xbuf1[i - rgroup] = xbuf1[rgroup * (M + 1) + i];
+ xbuf0[rgroup * (M + 2) + i] = xbuf0[i];
+ xbuf1[rgroup * (M + 2) + i] = xbuf1[i];
}
}
}
diff --git a/src/3rdparty/libjpeg/src/jdmarker.c b/src/3rdparty/libjpeg/src/jdmarker.c
index e3b612c9b9..c9c7ef6399 100644
--- a/src/3rdparty/libjpeg/src/jdmarker.c
+++ b/src/3rdparty/libjpeg/src/jdmarker.c
@@ -119,50 +119,50 @@ typedef my_marker_reader *my_marker_ptr;
*/
/* Declare and initialize local copies of input pointer/count */
-#define INPUT_VARS(cinfo) \
- struct jpeg_source_mgr *datasrc = (cinfo)->src; \
- const JOCTET *next_input_byte = datasrc->next_input_byte; \
- size_t bytes_in_buffer = datasrc->bytes_in_buffer
+#define INPUT_VARS(cinfo) \
+ struct jpeg_source_mgr *datasrc = (cinfo)->src; \
+ const JOCTET *next_input_byte = datasrc->next_input_byte; \
+ size_t bytes_in_buffer = datasrc->bytes_in_buffer
/* Unload the local copies --- do this only at a restart boundary */
-#define INPUT_SYNC(cinfo) \
- ( datasrc->next_input_byte = next_input_byte, \
- datasrc->bytes_in_buffer = bytes_in_buffer )
+#define INPUT_SYNC(cinfo) \
+ ( datasrc->next_input_byte = next_input_byte, \
+ datasrc->bytes_in_buffer = bytes_in_buffer )
/* Reload the local copies --- used only in MAKE_BYTE_AVAIL */
-#define INPUT_RELOAD(cinfo) \
- ( next_input_byte = datasrc->next_input_byte, \
- bytes_in_buffer = datasrc->bytes_in_buffer )
+#define INPUT_RELOAD(cinfo) \
+ ( next_input_byte = datasrc->next_input_byte, \
+ bytes_in_buffer = datasrc->bytes_in_buffer )
/* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available.
* Note we do *not* do INPUT_SYNC before calling fill_input_buffer,
* but we must reload the local copies after a successful fill.
*/
-#define MAKE_BYTE_AVAIL(cinfo,action) \
- if (bytes_in_buffer == 0) { \
- if (! (*datasrc->fill_input_buffer) (cinfo)) \
- { action; } \
- INPUT_RELOAD(cinfo); \
- }
+#define MAKE_BYTE_AVAIL(cinfo, action) \
+ if (bytes_in_buffer == 0) { \
+ if (!(*datasrc->fill_input_buffer) (cinfo)) \
+ { action; } \
+ INPUT_RELOAD(cinfo); \
+ }
/* Read a byte into variable V.
* If must suspend, take the specified action (typically "return FALSE").
*/
-#define INPUT_BYTE(cinfo,V,action) \
- MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \
- bytes_in_buffer--; \
- V = GETJOCTET(*next_input_byte++); )
+#define INPUT_BYTE(cinfo, V, action) \
+ MAKESTMT( MAKE_BYTE_AVAIL(cinfo, action); \
+ bytes_in_buffer--; \
+ V = GETJOCTET(*next_input_byte++); )
/* As above, but read two bytes interpreted as an unsigned 16-bit integer.
* V should be declared unsigned int or perhaps JLONG.
*/
-#define INPUT_2BYTES(cinfo,V,action) \
- MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \
- bytes_in_buffer--; \
- V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \
- MAKE_BYTE_AVAIL(cinfo,action); \
- bytes_in_buffer--; \
- V += GETJOCTET(*next_input_byte++); )
+#define INPUT_2BYTES(cinfo, V, action) \
+ MAKESTMT( MAKE_BYTE_AVAIL(cinfo, action); \
+ bytes_in_buffer--; \
+ V = ((unsigned int)GETJOCTET(*next_input_byte++)) << 8; \
+ MAKE_BYTE_AVAIL(cinfo, action); \
+ bytes_in_buffer--; \
+ V += GETJOCTET(*next_input_byte++); )
/*
@@ -197,7 +197,7 @@ typedef my_marker_reader *my_marker_ptr;
LOCAL(boolean)
-get_soi (j_decompress_ptr cinfo)
+get_soi(j_decompress_ptr cinfo)
/* Process an SOI marker */
{
int i;
@@ -237,7 +237,7 @@ get_soi (j_decompress_ptr cinfo)
LOCAL(boolean)
-get_sof (j_decompress_ptr cinfo, boolean is_prog, boolean is_arith)
+get_sof(j_decompress_ptr cinfo, boolean is_prog, boolean is_arith)
/* Process a SOFn marker */
{
JLONG length;
@@ -258,7 +258,7 @@ get_sof (j_decompress_ptr cinfo, boolean is_prog, boolean is_arith)
length -= 8;
TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker,
- (int) cinfo->image_width, (int) cinfo->image_height,
+ (int)cinfo->image_width, (int)cinfo->image_height,
cinfo->num_components);
if (cinfo->marker->saw_SOF)
@@ -267,16 +267,16 @@ get_sof (j_decompress_ptr cinfo, boolean is_prog, boolean is_arith)
/* We don't support files in which the image height is initially specified */
/* as 0 and is later redefined by DNL. As long as we have to check that, */
/* might as well have a general sanity check. */
- if (cinfo->image_height <= 0 || cinfo->image_width <= 0
- || cinfo->num_components <= 0)
+ if (cinfo->image_height <= 0 || cinfo->image_width <= 0 ||
+ cinfo->num_components <= 0)
ERREXIT(cinfo, JERR_EMPTY_IMAGE);
if (length != (cinfo->num_components * 3))
ERREXIT(cinfo, JERR_BAD_LENGTH);
if (cinfo->comp_info == NULL) /* do only once, even if suspend */
- cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small)
- ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ cinfo->comp_info = (jpeg_component_info *)(*cinfo->mem->alloc_small)
+ ((j_common_ptr)cinfo, JPOOL_IMAGE,
cinfo->num_components * sizeof(jpeg_component_info));
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
@@ -301,7 +301,7 @@ get_sof (j_decompress_ptr cinfo, boolean is_prog, boolean is_arith)
LOCAL(boolean)
-get_sos (j_decompress_ptr cinfo)
+get_sos(j_decompress_ptr cinfo)
/* Process a SOS marker */
{
JLONG length;
@@ -309,7 +309,7 @@ get_sos (j_decompress_ptr cinfo)
jpeg_component_info *compptr;
INPUT_VARS(cinfo);
- if (! cinfo->marker->saw_SOF)
+ if (!cinfo->marker->saw_SOF)
ERREXIT(cinfo, JERR_SOS_NO_SOF);
INPUT_2BYTES(cinfo, length, return FALSE);
@@ -341,7 +341,7 @@ get_sos (j_decompress_ptr cinfo)
ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc);
- id_found:
+id_found:
cinfo->cur_comp_info[i] = compptr;
compptr->dc_tbl_no = (c >> 4) & 15;
@@ -384,7 +384,7 @@ get_sos (j_decompress_ptr cinfo)
#ifdef D_ARITH_CODING_SUPPORTED
LOCAL(boolean)
-get_dac (j_decompress_ptr cinfo)
+get_dac(j_decompress_ptr cinfo)
/* Process a DAC marker */
{
JLONG length;
@@ -402,14 +402,14 @@ get_dac (j_decompress_ptr cinfo)
TRACEMS2(cinfo, 1, JTRC_DAC, index, val);
- if (index < 0 || index >= (2*NUM_ARITH_TBLS))
+ if (index < 0 || index >= (2 * NUM_ARITH_TBLS))
ERREXIT1(cinfo, JERR_DAC_INDEX, index);
if (index >= NUM_ARITH_TBLS) { /* define AC table */
- cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val;
+ cinfo->arith_ac_K[index - NUM_ARITH_TBLS] = (UINT8)val;
} else { /* define DC table */
- cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F);
- cinfo->arith_dc_U[index] = (UINT8) (val >> 4);
+ cinfo->arith_dc_L[index] = (UINT8)(val & 0x0F);
+ cinfo->arith_dc_U[index] = (UINT8)(val >> 4);
if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index])
ERREXIT1(cinfo, JERR_DAC_VALUE, val);
}
@@ -422,7 +422,7 @@ get_dac (j_decompress_ptr cinfo)
return TRUE;
}
-#else /* ! D_ARITH_CODING_SUPPORTED */
+#else /* !D_ARITH_CODING_SUPPORTED */
#define get_dac(cinfo) skip_variable(cinfo)
@@ -430,7 +430,7 @@ get_dac (j_decompress_ptr cinfo)
LOCAL(boolean)
-get_dht (j_decompress_ptr cinfo)
+get_dht(j_decompress_ptr cinfo)
/* Process a DHT marker */
{
JLONG length;
@@ -467,7 +467,7 @@ get_dht (j_decompress_ptr cinfo)
/* Here we just do minimal validation of the counts to avoid walking
* off the end of our table space. jdhuff.c will check more carefully.
*/
- if (count > 256 || ((JLONG) count) > length)
+ if (count > 256 || ((JLONG)count) > length)
ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
for (i = 0; i < count; i++)
@@ -489,7 +489,7 @@ get_dht (j_decompress_ptr cinfo)
}
if (*htblptr == NULL)
- *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr)cinfo);
MEMCOPY((*htblptr)->bits, bits, sizeof((*htblptr)->bits));
MEMCOPY((*htblptr)->huffval, huffval, sizeof((*htblptr)->huffval));
@@ -504,7 +504,7 @@ get_dht (j_decompress_ptr cinfo)
LOCAL(boolean)
-get_dqt (j_decompress_ptr cinfo)
+get_dqt(j_decompress_ptr cinfo)
/* Process a DQT marker */
{
JLONG length;
@@ -527,7 +527,7 @@ get_dqt (j_decompress_ptr cinfo)
ERREXIT1(cinfo, JERR_DQT_INDEX, n);
if (cinfo->quant_tbl_ptrs[n] == NULL)
- cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo);
+ cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr)cinfo);
quant_ptr = cinfo->quant_tbl_ptrs[n];
for (i = 0; i < DCTSIZE2; i++) {
@@ -536,20 +536,20 @@ get_dqt (j_decompress_ptr cinfo)
else
INPUT_BYTE(cinfo, tmp, return FALSE);
/* We convert the zigzag-order table to natural array order. */
- quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16) tmp;
+ quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16)tmp;
}
if (cinfo->err->trace_level >= 2) {
for (i = 0; i < DCTSIZE2; i += 8) {
TRACEMS8(cinfo, 2, JTRC_QUANTVALS,
- quant_ptr->quantval[i], quant_ptr->quantval[i+1],
- quant_ptr->quantval[i+2], quant_ptr->quantval[i+3],
- quant_ptr->quantval[i+4], quant_ptr->quantval[i+5],
- quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]);
+ quant_ptr->quantval[i], quant_ptr->quantval[i + 1],
+ quant_ptr->quantval[i + 2], quant_ptr->quantval[i + 3],
+ quant_ptr->quantval[i + 4], quant_ptr->quantval[i + 5],
+ quant_ptr->quantval[i + 6], quant_ptr->quantval[i + 7]);
}
}
- length -= DCTSIZE2+1;
+ length -= DCTSIZE2 + 1;
if (prec) length -= DCTSIZE2;
}
@@ -562,7 +562,7 @@ get_dqt (j_decompress_ptr cinfo)
LOCAL(boolean)
-get_dri (j_decompress_ptr cinfo)
+get_dri(j_decompress_ptr cinfo)
/* Process a DRI marker */
{
JLONG length;
@@ -598,14 +598,14 @@ get_dri (j_decompress_ptr cinfo)
LOCAL(void)
-examine_app0 (j_decompress_ptr cinfo, JOCTET *data,
- unsigned int datalen, JLONG remaining)
+examine_app0(j_decompress_ptr cinfo, JOCTET *data, unsigned int datalen,
+ JLONG remaining)
/* Examine first few bytes from an APP0.
* Take appropriate action if it is a JFIF marker.
* datalen is # of bytes at data[], remaining is length of rest of marker data.
*/
{
- JLONG totallen = (JLONG) datalen + remaining;
+ JLONG totallen = (JLONG)datalen + remaining;
if (datalen >= APP0_DATA_LEN &&
GETJOCTET(data[0]) == 0x4A &&
@@ -639,43 +639,43 @@ examine_app0 (j_decompress_ptr cinfo, JOCTET *data,
GETJOCTET(data[12]), GETJOCTET(data[13]));
totallen -= APP0_DATA_LEN;
if (totallen !=
- ((JLONG)GETJOCTET(data[12]) * (JLONG)GETJOCTET(data[13]) * (JLONG) 3))
- TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen);
+ ((JLONG)GETJOCTET(data[12]) * (JLONG)GETJOCTET(data[13]) * (JLONG)3))
+ TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int)totallen);
} else if (datalen >= 6 &&
- GETJOCTET(data[0]) == 0x4A &&
- GETJOCTET(data[1]) == 0x46 &&
- GETJOCTET(data[2]) == 0x58 &&
- GETJOCTET(data[3]) == 0x58 &&
- GETJOCTET(data[4]) == 0) {
+ GETJOCTET(data[0]) == 0x4A &&
+ GETJOCTET(data[1]) == 0x46 &&
+ GETJOCTET(data[2]) == 0x58 &&
+ GETJOCTET(data[3]) == 0x58 &&
+ GETJOCTET(data[4]) == 0) {
/* Found JFIF "JFXX" extension APP0 marker */
/* The library doesn't actually do anything with these,
* but we try to produce a helpful trace message.
*/
switch (GETJOCTET(data[5])) {
case 0x10:
- TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int) totallen);
+ TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int)totallen);
break;
case 0x11:
- TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen);
+ TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int)totallen);
break;
case 0x13:
- TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen);
+ TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int)totallen);
break;
default:
TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION,
- GETJOCTET(data[5]), (int) totallen);
+ GETJOCTET(data[5]), (int)totallen);
break;
}
} else {
/* Start of APP0 does not match "JFIF" or "JFXX", or too short */
- TRACEMS1(cinfo, 1, JTRC_APP0, (int) totallen);
+ TRACEMS1(cinfo, 1, JTRC_APP0, (int)totallen);
}
}
LOCAL(void)
-examine_app14 (j_decompress_ptr cinfo, JOCTET *data,
- unsigned int datalen, JLONG remaining)
+examine_app14(j_decompress_ptr cinfo, JOCTET *data, unsigned int datalen,
+ JLONG remaining)
/* Examine first few bytes from an APP14.
* Take appropriate action if it is an Adobe marker.
* datalen is # of bytes at data[], remaining is length of rest of marker data.
@@ -696,16 +696,16 @@ examine_app14 (j_decompress_ptr cinfo, JOCTET *data,
transform = GETJOCTET(data[11]);
TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform);
cinfo->saw_Adobe_marker = TRUE;
- cinfo->Adobe_transform = (UINT8) transform;
+ cinfo->Adobe_transform = (UINT8)transform;
} else {
/* Start of APP14 does not match "Adobe", or too short */
- TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining));
+ TRACEMS1(cinfo, 1, JTRC_APP14, (int)(datalen + remaining));
}
}
METHODDEF(boolean)
-get_interesting_appn (j_decompress_ptr cinfo)
+get_interesting_appn(j_decompress_ptr cinfo)
/* Process an APP0 or APP14 marker without saving it */
{
JLONG length;
@@ -720,7 +720,7 @@ get_interesting_appn (j_decompress_ptr cinfo)
if (length >= APPN_DATA_LEN)
numtoread = APPN_DATA_LEN;
else if (length > 0)
- numtoread = (unsigned int) length;
+ numtoread = (unsigned int)length;
else
numtoread = 0;
for (i = 0; i < numtoread; i++)
@@ -730,10 +730,10 @@ get_interesting_appn (j_decompress_ptr cinfo)
/* process it */
switch (cinfo->unread_marker) {
case M_APP0:
- examine_app0(cinfo, (JOCTET *) b, numtoread, length);
+ examine_app0(cinfo, (JOCTET *)b, numtoread, length);
break;
case M_APP14:
- examine_app14(cinfo, (JOCTET *) b, numtoread, length);
+ examine_app14(cinfo, (JOCTET *)b, numtoread, length);
break;
default:
/* can't get here unless jpeg_save_markers chooses wrong processor */
@@ -744,7 +744,7 @@ get_interesting_appn (j_decompress_ptr cinfo)
/* skip any remaining data -- could be lots */
INPUT_SYNC(cinfo);
if (length > 0)
- (*cinfo->src->skip_input_data) (cinfo, (long) length);
+ (*cinfo->src->skip_input_data) (cinfo, (long)length);
return TRUE;
}
@@ -753,10 +753,10 @@ get_interesting_appn (j_decompress_ptr cinfo)
#ifdef SAVE_MARKERS_SUPPORTED
METHODDEF(boolean)
-save_marker (j_decompress_ptr cinfo)
+save_marker(j_decompress_ptr cinfo)
/* Save an APPn or COM marker into the marker list */
{
- my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+ my_marker_ptr marker = (my_marker_ptr)cinfo->marker;
jpeg_saved_marker_ptr cur_marker = marker->cur_marker;
unsigned int bytes_read, data_length;
JOCTET *data;
@@ -770,22 +770,22 @@ save_marker (j_decompress_ptr cinfo)
if (length >= 0) { /* watch out for bogus length word */
/* figure out how much we want to save */
unsigned int limit;
- if (cinfo->unread_marker == (int) M_COM)
+ if (cinfo->unread_marker == (int)M_COM)
limit = marker->length_limit_COM;
else
- limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0];
- if ((unsigned int) length < limit)
- limit = (unsigned int) length;
+ limit = marker->length_limit_APPn[cinfo->unread_marker - (int)M_APP0];
+ if ((unsigned int)length < limit)
+ limit = (unsigned int)length;
/* allocate and initialize the marker item */
cur_marker = (jpeg_saved_marker_ptr)
- (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_large) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(struct jpeg_marker_struct) + limit);
cur_marker->next = NULL;
- cur_marker->marker = (UINT8) cinfo->unread_marker;
- cur_marker->original_length = (unsigned int) length;
+ cur_marker->marker = (UINT8)cinfo->unread_marker;
+ cur_marker->original_length = (unsigned int)length;
cur_marker->data_length = limit;
/* data area is just beyond the jpeg_marker_struct */
- data = cur_marker->data = (JOCTET *) (cur_marker + 1);
+ data = cur_marker->data = (JOCTET *)(cur_marker + 1);
marker->cur_marker = cur_marker;
marker->bytes_read = 0;
bytes_read = 0;
@@ -843,14 +843,14 @@ save_marker (j_decompress_ptr cinfo)
break;
default:
TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker,
- (int) (data_length + length));
+ (int)(data_length + length));
break;
}
/* skip any remaining data -- could be lots */
INPUT_SYNC(cinfo); /* do before skip_input_data */
if (length > 0)
- (*cinfo->src->skip_input_data) (cinfo, (long) length);
+ (*cinfo->src->skip_input_data) (cinfo, (long)length);
return TRUE;
}
@@ -859,7 +859,7 @@ save_marker (j_decompress_ptr cinfo)
METHODDEF(boolean)
-skip_variable (j_decompress_ptr cinfo)
+skip_variable(j_decompress_ptr cinfo)
/* Skip over an unknown or uninteresting variable-length marker */
{
JLONG length;
@@ -868,11 +868,11 @@ skip_variable (j_decompress_ptr cinfo)
INPUT_2BYTES(cinfo, length, return FALSE);
length -= 2;
- TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length);
+ TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int)length);
INPUT_SYNC(cinfo); /* do before skip_input_data */
if (length > 0)
- (*cinfo->src->skip_input_data) (cinfo, (long) length);
+ (*cinfo->src->skip_input_data) (cinfo, (long)length);
return TRUE;
}
@@ -888,7 +888,7 @@ skip_variable (j_decompress_ptr cinfo)
*/
LOCAL(boolean)
-next_marker (j_decompress_ptr cinfo)
+next_marker(j_decompress_ptr cinfo)
{
int c;
INPUT_VARS(cinfo);
@@ -935,7 +935,7 @@ next_marker (j_decompress_ptr cinfo)
LOCAL(boolean)
-first_marker (j_decompress_ptr cinfo)
+first_marker(j_decompress_ptr cinfo)
/* Like next_marker, but used to obtain the initial SOI marker. */
/* For this marker, we do not allow preceding garbage or fill; otherwise,
* we might well scan an entire input file before realizing it ain't JPEG.
@@ -948,7 +948,7 @@ first_marker (j_decompress_ptr cinfo)
INPUT_BYTE(cinfo, c, return FALSE);
INPUT_BYTE(cinfo, c2, return FALSE);
- if (c != 0xFF || c2 != (int) M_SOI)
+ if (c != 0xFF || c2 != (int)M_SOI)
ERREXIT2(cinfo, JERR_NO_SOI, c, c2);
cinfo->unread_marker = c2;
@@ -966,18 +966,18 @@ first_marker (j_decompress_ptr cinfo)
*/
METHODDEF(int)
-read_markers (j_decompress_ptr cinfo)
+read_markers(j_decompress_ptr cinfo)
{
/* Outer loop repeats once for each marker. */
for (;;) {
/* Collect the marker proper, unless we already did. */
/* NB: first_marker() enforces the requirement that SOI appear first. */
if (cinfo->unread_marker == 0) {
- if (! cinfo->marker->saw_SOI) {
- if (! first_marker(cinfo))
+ if (!cinfo->marker->saw_SOI) {
+ if (!first_marker(cinfo))
return JPEG_SUSPENDED;
} else {
- if (! next_marker(cinfo))
+ if (!next_marker(cinfo))
return JPEG_SUSPENDED;
}
}
@@ -987,28 +987,28 @@ read_markers (j_decompress_ptr cinfo)
*/
switch (cinfo->unread_marker) {
case M_SOI:
- if (! get_soi(cinfo))
+ if (!get_soi(cinfo))
return JPEG_SUSPENDED;
break;
case M_SOF0: /* Baseline */
case M_SOF1: /* Extended sequential, Huffman */
- if (! get_sof(cinfo, FALSE, FALSE))
+ if (!get_sof(cinfo, FALSE, FALSE))
return JPEG_SUSPENDED;
break;
case M_SOF2: /* Progressive, Huffman */
- if (! get_sof(cinfo, TRUE, FALSE))
+ if (!get_sof(cinfo, TRUE, FALSE))
return JPEG_SUSPENDED;
break;
case M_SOF9: /* Extended sequential, arithmetic */
- if (! get_sof(cinfo, FALSE, TRUE))
+ if (!get_sof(cinfo, FALSE, TRUE))
return JPEG_SUSPENDED;
break;
case M_SOF10: /* Progressive, arithmetic */
- if (! get_sof(cinfo, TRUE, TRUE))
+ if (!get_sof(cinfo, TRUE, TRUE))
return JPEG_SUSPENDED;
break;
@@ -1026,7 +1026,7 @@ read_markers (j_decompress_ptr cinfo)
break;
case M_SOS:
- if (! get_sos(cinfo))
+ if (!get_sos(cinfo))
return JPEG_SUSPENDED;
cinfo->unread_marker = 0; /* processed the marker */
return JPEG_REACHED_SOS;
@@ -1037,22 +1037,22 @@ read_markers (j_decompress_ptr cinfo)
return JPEG_REACHED_EOI;
case M_DAC:
- if (! get_dac(cinfo))
+ if (!get_dac(cinfo))
return JPEG_SUSPENDED;
break;
case M_DHT:
- if (! get_dht(cinfo))
+ if (!get_dht(cinfo))
return JPEG_SUSPENDED;
break;
case M_DQT:
- if (! get_dqt(cinfo))
+ if (!get_dqt(cinfo))
return JPEG_SUSPENDED;
break;
case M_DRI:
- if (! get_dri(cinfo))
+ if (!get_dri(cinfo))
return JPEG_SUSPENDED;
break;
@@ -1072,13 +1072,13 @@ read_markers (j_decompress_ptr cinfo)
case M_APP13:
case M_APP14:
case M_APP15:
- if (! (*((my_marker_ptr) cinfo->marker)->process_APPn[
- cinfo->unread_marker - (int) M_APP0]) (cinfo))
+ if (!(*((my_marker_ptr)cinfo->marker)->process_APPn[
+ cinfo->unread_marker - (int)M_APP0]) (cinfo))
return JPEG_SUSPENDED;
break;
case M_COM:
- if (! (*((my_marker_ptr) cinfo->marker)->process_COM) (cinfo))
+ if (!(*((my_marker_ptr)cinfo->marker)->process_COM) (cinfo))
return JPEG_SUSPENDED;
break;
@@ -1095,7 +1095,7 @@ read_markers (j_decompress_ptr cinfo)
break;
case M_DNL: /* Ignore DNL ... perhaps the wrong thing */
- if (! skip_variable(cinfo))
+ if (!skip_variable(cinfo))
return JPEG_SUSPENDED;
break;
@@ -1127,25 +1127,25 @@ read_markers (j_decompress_ptr cinfo)
*/
METHODDEF(boolean)
-read_restart_marker (j_decompress_ptr cinfo)
+read_restart_marker(j_decompress_ptr cinfo)
{
/* Obtain a marker unless we already did. */
/* Note that next_marker will complain if it skips any data. */
if (cinfo->unread_marker == 0) {
- if (! next_marker(cinfo))
+ if (!next_marker(cinfo))
return FALSE;
}
if (cinfo->unread_marker ==
- ((int) M_RST0 + cinfo->marker->next_restart_num)) {
+ ((int)M_RST0 + cinfo->marker->next_restart_num)) {
/* Normal case --- swallow the marker and let entropy decoder continue */
TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num);
cinfo->unread_marker = 0;
} else {
/* Uh-oh, the restart markers have been messed up. */
/* Let the data source manager determine how to resync. */
- if (! (*cinfo->src->resync_to_restart) (cinfo,
- cinfo->marker->next_restart_num))
+ if (!(*cinfo->src->resync_to_restart) (cinfo,
+ cinfo->marker->next_restart_num))
return FALSE;
}
@@ -1206,7 +1206,7 @@ read_restart_marker (j_decompress_ptr cinfo)
*/
GLOBAL(boolean)
-jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired)
+jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired)
{
int marker = cinfo->unread_marker;
int action = 1;
@@ -1216,16 +1216,16 @@ jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired)
/* Outer loop handles repeated decision after scanning forward. */
for (;;) {
- if (marker < (int) M_SOF0)
+ if (marker < (int)M_SOF0)
action = 2; /* invalid marker */
- else if (marker < (int) M_RST0 || marker > (int) M_RST7)
+ else if (marker < (int)M_RST0 || marker > (int)M_RST7)
action = 3; /* valid non-restart marker */
else {
- if (marker == ((int) M_RST0 + ((desired+1) & 7)) ||
- marker == ((int) M_RST0 + ((desired+2) & 7)))
+ if (marker == ((int)M_RST0 + ((desired + 1) & 7)) ||
+ marker == ((int)M_RST0 + ((desired + 2) & 7)))
action = 3; /* one of the next two expected restarts */
- else if (marker == ((int) M_RST0 + ((desired-1) & 7)) ||
- marker == ((int) M_RST0 + ((desired-2) & 7)))
+ else if (marker == ((int)M_RST0 + ((desired - 1) & 7)) ||
+ marker == ((int)M_RST0 + ((desired - 2) & 7)))
action = 2; /* a prior restart, so advance */
else
action = 1; /* desired restart or too far away */
@@ -1238,7 +1238,7 @@ jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired)
return TRUE;
case 2:
/* Scan to the next marker, and repeat the decision loop. */
- if (! next_marker(cinfo))
+ if (!next_marker(cinfo))
return FALSE;
marker = cinfo->unread_marker;
break;
@@ -1256,9 +1256,9 @@ jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired)
*/
METHODDEF(void)
-reset_marker_reader (j_decompress_ptr cinfo)
+reset_marker_reader(j_decompress_ptr cinfo)
{
- my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+ my_marker_ptr marker = (my_marker_ptr)cinfo->marker;
cinfo->comp_info = NULL; /* until allocated by get_sof */
cinfo->input_scan_number = 0; /* no SOS seen yet */
@@ -1276,16 +1276,16 @@ reset_marker_reader (j_decompress_ptr cinfo)
*/
GLOBAL(void)
-jinit_marker_reader (j_decompress_ptr cinfo)
+jinit_marker_reader(j_decompress_ptr cinfo)
{
my_marker_ptr marker;
int i;
/* Create subobject in permanent pool */
marker = (my_marker_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_PERMANENT,
sizeof(my_marker_reader));
- cinfo->marker = (struct jpeg_marker_reader *) marker;
+ cinfo->marker = (struct jpeg_marker_reader *)marker;
/* Initialize public method pointers */
marker->pub.reset_marker_reader = reset_marker_reader;
marker->pub.read_markers = read_markers;
@@ -1314,10 +1314,10 @@ jinit_marker_reader (j_decompress_ptr cinfo)
#ifdef SAVE_MARKERS_SUPPORTED
GLOBAL(void)
-jpeg_save_markers (j_decompress_ptr cinfo, int marker_code,
- unsigned int length_limit)
+jpeg_save_markers(j_decompress_ptr cinfo, int marker_code,
+ unsigned int length_limit)
{
- my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+ my_marker_ptr marker = (my_marker_ptr)cinfo->marker;
long maxlength;
jpeg_marker_parser_method processor;
@@ -1325,8 +1325,8 @@ jpeg_save_markers (j_decompress_ptr cinfo, int marker_code,
* (should only be a concern in a 16-bit environment).
*/
maxlength = cinfo->mem->max_alloc_chunk - sizeof(struct jpeg_marker_struct);
- if (((long) length_limit) > maxlength)
- length_limit = (unsigned int) maxlength;
+ if (((long)length_limit) > maxlength)
+ length_limit = (unsigned int)maxlength;
/* Choose processor routine to use.
* APP0/APP14 have special requirements.
@@ -1334,23 +1334,23 @@ jpeg_save_markers (j_decompress_ptr cinfo, int marker_code,
if (length_limit) {
processor = save_marker;
/* If saving APP0/APP14, save at least enough for our internal use. */
- if (marker_code == (int) M_APP0 && length_limit < APP0_DATA_LEN)
+ if (marker_code == (int)M_APP0 && length_limit < APP0_DATA_LEN)
length_limit = APP0_DATA_LEN;
- else if (marker_code == (int) M_APP14 && length_limit < APP14_DATA_LEN)
+ else if (marker_code == (int)M_APP14 && length_limit < APP14_DATA_LEN)
length_limit = APP14_DATA_LEN;
} else {
processor = skip_variable;
/* If discarding APP0/APP14, use our regular on-the-fly processor. */
- if (marker_code == (int) M_APP0 || marker_code == (int) M_APP14)
+ if (marker_code == (int)M_APP0 || marker_code == (int)M_APP14)
processor = get_interesting_appn;
}
- if (marker_code == (int) M_COM) {
+ if (marker_code == (int)M_COM) {
marker->process_COM = processor;
marker->length_limit_COM = length_limit;
- } else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) {
- marker->process_APPn[marker_code - (int) M_APP0] = processor;
- marker->length_limit_APPn[marker_code - (int) M_APP0] = length_limit;
+ } else if (marker_code >= (int)M_APP0 && marker_code <= (int)M_APP15) {
+ marker->process_APPn[marker_code - (int)M_APP0] = processor;
+ marker->length_limit_APPn[marker_code - (int)M_APP0] = length_limit;
} else
ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code);
}
@@ -1363,15 +1363,15 @@ jpeg_save_markers (j_decompress_ptr cinfo, int marker_code,
*/
GLOBAL(void)
-jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code,
- jpeg_marker_parser_method routine)
+jpeg_set_marker_processor(j_decompress_ptr cinfo, int marker_code,
+ jpeg_marker_parser_method routine)
{
- my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+ my_marker_ptr marker = (my_marker_ptr)cinfo->marker;
- if (marker_code == (int) M_COM)
+ if (marker_code == (int)M_COM)
marker->process_COM = routine;
- else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15)
- marker->process_APPn[marker_code - (int) M_APP0] = routine;
+ else if (marker_code >= (int)M_APP0 && marker_code <= (int)M_APP15)
+ marker->process_APPn[marker_code - (int)M_APP0] = routine;
else
ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code);
}
diff --git a/src/3rdparty/libjpeg/src/jdmaster.c b/src/3rdparty/libjpeg/src/jdmaster.c
index 9079dda65c..b20906438e 100644
--- a/src/3rdparty/libjpeg/src/jdmaster.c
+++ b/src/3rdparty/libjpeg/src/jdmaster.c
@@ -31,7 +31,7 @@
*/
LOCAL(boolean)
-use_merged_upsample (j_decompress_ptr cinfo)
+use_merged_upsample(j_decompress_ptr cinfo)
{
#ifdef UPSAMPLE_MERGING_SUPPORTED
/* Merging is the equivalent of plain box-filter upsampling */
@@ -40,22 +40,22 @@ use_merged_upsample (j_decompress_ptr cinfo)
/* jdmerge.c only supports YCC=>RGB and YCC=>RGB565 color conversion */
if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 ||
(cinfo->out_color_space != JCS_RGB &&
- cinfo->out_color_space != JCS_RGB565 &&
- cinfo->out_color_space != JCS_EXT_RGB &&
- cinfo->out_color_space != JCS_EXT_RGBX &&
- cinfo->out_color_space != JCS_EXT_BGR &&
- cinfo->out_color_space != JCS_EXT_BGRX &&
- cinfo->out_color_space != JCS_EXT_XBGR &&
- cinfo->out_color_space != JCS_EXT_XRGB &&
- cinfo->out_color_space != JCS_EXT_RGBA &&
- cinfo->out_color_space != JCS_EXT_BGRA &&
- cinfo->out_color_space != JCS_EXT_ABGR &&
- cinfo->out_color_space != JCS_EXT_ARGB))
+ cinfo->out_color_space != JCS_RGB565 &&
+ cinfo->out_color_space != JCS_EXT_RGB &&
+ cinfo->out_color_space != JCS_EXT_RGBX &&
+ cinfo->out_color_space != JCS_EXT_BGR &&
+ cinfo->out_color_space != JCS_EXT_BGRX &&
+ cinfo->out_color_space != JCS_EXT_XBGR &&
+ cinfo->out_color_space != JCS_EXT_XRGB &&
+ cinfo->out_color_space != JCS_EXT_RGBA &&
+ cinfo->out_color_space != JCS_EXT_BGRA &&
+ cinfo->out_color_space != JCS_EXT_ABGR &&
+ cinfo->out_color_space != JCS_EXT_ARGB))
return FALSE;
if ((cinfo->out_color_space == JCS_RGB565 &&
- cinfo->out_color_components != 3) ||
+ cinfo->out_color_components != 3) ||
(cinfo->out_color_space != JCS_RGB565 &&
- cinfo->out_color_components != rgb_pixelsize[cinfo->out_color_space]))
+ cinfo->out_color_components != rgb_pixelsize[cinfo->out_color_space]))
return FALSE;
/* and it only handles 2h1v or 2h2v sampling ratios */
if (cinfo->comp_info[0].h_samp_factor != 2 ||
@@ -100,7 +100,7 @@ GLOBAL(void)
#else
LOCAL(void)
#endif
-jpeg_core_output_dimensions (j_decompress_ptr cinfo)
+jpeg_core_output_dimensions(j_decompress_ptr cinfo)
/* Do computations that are needed before master selection phase.
* This function is used for transcoding and full decompression.
*/
@@ -113,129 +113,129 @@ jpeg_core_output_dimensions (j_decompress_ptr cinfo)
if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom) {
/* Provide 1/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 1;
cinfo->_min_DCT_v_scaled_size = 1;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 2) {
/* Provide 2/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 2L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 2L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 2L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 2L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 2;
cinfo->_min_DCT_v_scaled_size = 2;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 3) {
/* Provide 3/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 3L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 3L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 3L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 3L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 3;
cinfo->_min_DCT_v_scaled_size = 3;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 4) {
/* Provide 4/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 4L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 4L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 4L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 4L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 4;
cinfo->_min_DCT_v_scaled_size = 4;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 5) {
/* Provide 5/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 5L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 5L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 5L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 5L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 5;
cinfo->_min_DCT_v_scaled_size = 5;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 6) {
/* Provide 6/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 6L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 6L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 6L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 6L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 6;
cinfo->_min_DCT_v_scaled_size = 6;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 7) {
/* Provide 7/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 7L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 7L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 7L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 7L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 7;
cinfo->_min_DCT_v_scaled_size = 7;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 8) {
/* Provide 8/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 8L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 8L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 8L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 8L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 8;
cinfo->_min_DCT_v_scaled_size = 8;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 9) {
/* Provide 9/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 9L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 9L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 9L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 9L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 9;
cinfo->_min_DCT_v_scaled_size = 9;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 10) {
/* Provide 10/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 10L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 10L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 10L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 10L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 10;
cinfo->_min_DCT_v_scaled_size = 10;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 11) {
/* Provide 11/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 11L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 11L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 11L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 11L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 11;
cinfo->_min_DCT_v_scaled_size = 11;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 12) {
/* Provide 12/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 12L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 12L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 12L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 12L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 12;
cinfo->_min_DCT_v_scaled_size = 12;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 13) {
/* Provide 13/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 13L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 13L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 13L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 13L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 13;
cinfo->_min_DCT_v_scaled_size = 13;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 14) {
/* Provide 14/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 14L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 14L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 14L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 14L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 14;
cinfo->_min_DCT_v_scaled_size = 14;
} else if (cinfo->scale_num * DCTSIZE <= cinfo->scale_denom * 15) {
/* Provide 15/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 15L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 15L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 15L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 15L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 15;
cinfo->_min_DCT_v_scaled_size = 15;
} else {
/* Provide 16/block_size scaling */
cinfo->output_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width * 16L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_width * 16L, (long)DCTSIZE);
cinfo->output_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height * 16L, (long) DCTSIZE);
+ jdiv_round_up((long)cinfo->image_height * 16L, (long)DCTSIZE);
cinfo->_min_DCT_h_scaled_size = 16;
cinfo->_min_DCT_v_scaled_size = 16;
}
@@ -268,7 +268,7 @@ jpeg_core_output_dimensions (j_decompress_ptr cinfo)
*/
GLOBAL(void)
-jpeg_calc_output_dimensions (j_decompress_ptr cinfo)
+jpeg_calc_output_dimensions(j_decompress_ptr cinfo)
/* Do computations that are needed before master selection phase */
{
#ifdef IDCT_SCALING_SUPPORTED
@@ -314,13 +314,13 @@ jpeg_calc_output_dimensions (j_decompress_ptr cinfo)
ci++, compptr++) {
/* Size in samples, after IDCT scaling */
compptr->downsampled_width = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_width *
- (long) (compptr->h_samp_factor * compptr->_DCT_scaled_size),
- (long) (cinfo->max_h_samp_factor * DCTSIZE));
+ jdiv_round_up((long)cinfo->image_width *
+ (long)(compptr->h_samp_factor * compptr->_DCT_scaled_size),
+ (long)(cinfo->max_h_samp_factor * DCTSIZE));
compptr->downsampled_height = (JDIMENSION)
- jdiv_round_up((long) cinfo->image_height *
- (long) (compptr->v_samp_factor * compptr->_DCT_scaled_size),
- (long) (cinfo->max_v_samp_factor * DCTSIZE));
+ jdiv_round_up((long)cinfo->image_height *
+ (long)(compptr->v_samp_factor * compptr->_DCT_scaled_size),
+ (long)(cinfo->max_v_samp_factor * DCTSIZE));
}
#else /* !IDCT_SCALING_SUPPORTED */
@@ -417,30 +417,30 @@ jpeg_calc_output_dimensions (j_decompress_ptr cinfo)
*/
LOCAL(void)
-prepare_range_limit_table (j_decompress_ptr cinfo)
+prepare_range_limit_table(j_decompress_ptr cinfo)
/* Allocate and fill in the sample_range_limit table */
{
JSAMPLE *table;
int i;
table = (JSAMPLE *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * sizeof(JSAMPLE));
- table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (5 * (MAXJSAMPLE + 1) + CENTERJSAMPLE) * sizeof(JSAMPLE));
+ table += (MAXJSAMPLE + 1); /* allow negative subscripts of simple table */
cinfo->sample_range_limit = table;
/* First segment of "simple" table: limit[x] = 0 for x < 0 */
- MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * sizeof(JSAMPLE));
+ MEMZERO(table - (MAXJSAMPLE + 1), (MAXJSAMPLE + 1) * sizeof(JSAMPLE));
/* Main part of "simple" table: limit[x] = x */
for (i = 0; i <= MAXJSAMPLE; i++)
- table[i] = (JSAMPLE) i;
+ table[i] = (JSAMPLE)i;
table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */
/* End of simple table, rest of first half of post-IDCT table */
- for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++)
+ for (i = CENTERJSAMPLE; i < 2 * (MAXJSAMPLE + 1); i++)
table[i] = MAXJSAMPLE;
/* Second half of post-IDCT table */
- MEMZERO(table + (2 * (MAXJSAMPLE+1)),
- (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * sizeof(JSAMPLE));
- MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE),
+ MEMZERO(table + (2 * (MAXJSAMPLE + 1)),
+ (2 * (MAXJSAMPLE + 1) - CENTERJSAMPLE) * sizeof(JSAMPLE));
+ MEMCOPY(table + (4 * (MAXJSAMPLE + 1) - CENTERJSAMPLE),
cinfo->sample_range_limit, CENTERJSAMPLE * sizeof(JSAMPLE));
}
@@ -457,9 +457,9 @@ prepare_range_limit_table (j_decompress_ptr cinfo)
*/
LOCAL(void)
-master_selection (j_decompress_ptr cinfo)
+master_selection(j_decompress_ptr cinfo)
{
- my_master_ptr master = (my_master_ptr) cinfo->master;
+ my_master_ptr master = (my_master_ptr)cinfo->master;
boolean use_c_buffer;
long samplesperrow;
JDIMENSION jd_samplesperrow;
@@ -469,9 +469,10 @@ master_selection (j_decompress_ptr cinfo)
prepare_range_limit_table(cinfo);
/* Width of an output scanline must be representable as JDIMENSION. */
- samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components;
- jd_samplesperrow = (JDIMENSION) samplesperrow;
- if ((long) jd_samplesperrow != samplesperrow)
+ samplesperrow = (long)cinfo->output_width *
+ (long)cinfo->out_color_components;
+ jd_samplesperrow = (JDIMENSION)samplesperrow;
+ if ((long)jd_samplesperrow != samplesperrow)
ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
/* Initialize my private state */
@@ -482,7 +483,7 @@ master_selection (j_decompress_ptr cinfo)
master->quantizer_1pass = NULL;
master->quantizer_2pass = NULL;
/* No mode changes if not using buffered-image mode. */
- if (! cinfo->quantize_colors || ! cinfo->buffered_image) {
+ if (!cinfo->quantize_colors || !cinfo->buffered_image) {
cinfo->enable_1pass_quant = FALSE;
cinfo->enable_external_quant = FALSE;
cinfo->enable_2pass_quant = FALSE;
@@ -528,7 +529,7 @@ master_selection (j_decompress_ptr cinfo)
}
/* Post-processing: in particular, color conversion first */
- if (! cinfo->raw_data_out) {
+ if (!cinfo->raw_data_out) {
if (master->using_merged_upsample) {
#ifdef UPSAMPLE_MERGING_SUPPORTED
jinit_merged_upsampler(cinfo); /* does color conversion too */
@@ -565,11 +566,11 @@ master_selection (j_decompress_ptr cinfo)
use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image;
jinit_d_coef_controller(cinfo, use_c_buffer);
- if (! cinfo->raw_data_out)
+ if (!cinfo->raw_data_out)
jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */);
/* We can now tell the memory manager to allocate virtual arrays. */
- (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
+ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr)cinfo);
/* Initialize input side of decompressor to consume first scan. */
(*cinfo->inputctl->start_input_pass) (cinfo);
@@ -585,7 +586,7 @@ master_selection (j_decompress_ptr cinfo)
* progress monitoring appropriately. The input step is counted
* as one pass.
*/
- if (cinfo->progress != NULL && ! cinfo->buffered_image &&
+ if (cinfo->progress != NULL && !cinfo->buffered_image &&
cinfo->inputctl->has_multiple_scans) {
int nscans;
/* Estimate number of scans to set pass_limit. */
@@ -597,7 +598,7 @@ master_selection (j_decompress_ptr cinfo)
nscans = cinfo->num_components;
}
cinfo->progress->pass_counter = 0L;
- cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans;
+ cinfo->progress->pass_limit = (long)cinfo->total_iMCU_rows * nscans;
cinfo->progress->completed_passes = 0;
cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2);
/* Count the input pass as done */
@@ -617,9 +618,9 @@ master_selection (j_decompress_ptr cinfo)
*/
METHODDEF(void)
-prepare_for_output_pass (j_decompress_ptr cinfo)
+prepare_for_output_pass(j_decompress_ptr cinfo)
{
- my_master_ptr master = (my_master_ptr) cinfo->master;
+ my_master_ptr master = (my_master_ptr)cinfo->master;
if (master->pub.is_dummy_pass) {
#ifdef QUANT_2PASS_SUPPORTED
@@ -645,8 +646,8 @@ prepare_for_output_pass (j_decompress_ptr cinfo)
}
(*cinfo->idct->start_pass) (cinfo);
(*cinfo->coef->start_output_pass) (cinfo);
- if (! cinfo->raw_data_out) {
- if (! master->using_merged_upsample)
+ if (!cinfo->raw_data_out) {
+ if (!master->using_merged_upsample)
(*cinfo->cconvert->start_pass) (cinfo);
(*cinfo->upsample->start_pass) (cinfo);
if (cinfo->quantize_colors)
@@ -665,7 +666,7 @@ prepare_for_output_pass (j_decompress_ptr cinfo)
/* In buffered-image mode, we assume one more output pass if EOI not
* yet reached, but no more passes if EOI has been reached.
*/
- if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) {
+ if (cinfo->buffered_image && !cinfo->inputctl->eoi_reached) {
cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1);
}
}
@@ -677,9 +678,9 @@ prepare_for_output_pass (j_decompress_ptr cinfo)
*/
METHODDEF(void)
-finish_output_pass (j_decompress_ptr cinfo)
+finish_output_pass(j_decompress_ptr cinfo)
{
- my_master_ptr master = (my_master_ptr) cinfo->master;
+ my_master_ptr master = (my_master_ptr)cinfo->master;
if (cinfo->quantize_colors)
(*cinfo->cquantize->finish_pass) (cinfo);
@@ -694,9 +695,9 @@ finish_output_pass (j_decompress_ptr cinfo)
*/
GLOBAL(void)
-jpeg_new_colormap (j_decompress_ptr cinfo)
+jpeg_new_colormap(j_decompress_ptr cinfo)
{
- my_master_ptr master = (my_master_ptr) cinfo->master;
+ my_master_ptr master = (my_master_ptr)cinfo->master;
/* Prevent application from calling me at wrong times */
if (cinfo->global_state != DSTATE_BUFIMAGE)
@@ -722,9 +723,9 @@ jpeg_new_colormap (j_decompress_ptr cinfo)
*/
GLOBAL(void)
-jinit_master_decompress (j_decompress_ptr cinfo)
+jinit_master_decompress(j_decompress_ptr cinfo)
{
- my_master_ptr master = (my_master_ptr) cinfo->master;
+ my_master_ptr master = (my_master_ptr)cinfo->master;
master->pub.prepare_for_output_pass = prepare_for_output_pass;
master->pub.finish_output_pass = finish_output_pass;
diff --git a/src/3rdparty/libjpeg/src/jdmerge.c b/src/3rdparty/libjpeg/src/jdmerge.c
index ca6f16c252..d67faec036 100644
--- a/src/3rdparty/libjpeg/src/jdmerge.c
+++ b/src/3rdparty/libjpeg/src/jdmerge.c
@@ -76,8 +76,8 @@ typedef struct {
typedef my_upsampler *my_upsample_ptr;
#define SCALEBITS 16 /* speediest right-shift on some machines */
-#define ONE_HALF ((JLONG) 1 << (SCALEBITS-1))
-#define FIX(x) ((JLONG) ((x) * (1L<<SCALEBITS) + 0.5))
+#define ONE_HALF ((JLONG)1 << (SCALEBITS - 1))
+#define FIX(x) ((JLONG)((x) * (1L << SCALEBITS) + 0.5))
/* Include inline routines for colorspace extensions */
@@ -88,12 +88,12 @@ typedef my_upsampler *my_upsample_ptr;
#undef RGB_BLUE
#undef RGB_PIXELSIZE
-#define RGB_RED EXT_RGB_RED
-#define RGB_GREEN EXT_RGB_GREEN
-#define RGB_BLUE EXT_RGB_BLUE
-#define RGB_PIXELSIZE EXT_RGB_PIXELSIZE
-#define h2v1_merged_upsample_internal extrgb_h2v1_merged_upsample_internal
-#define h2v2_merged_upsample_internal extrgb_h2v2_merged_upsample_internal
+#define RGB_RED EXT_RGB_RED
+#define RGB_GREEN EXT_RGB_GREEN
+#define RGB_BLUE EXT_RGB_BLUE
+#define RGB_PIXELSIZE EXT_RGB_PIXELSIZE
+#define h2v1_merged_upsample_internal extrgb_h2v1_merged_upsample_internal
+#define h2v2_merged_upsample_internal extrgb_h2v2_merged_upsample_internal
#include "jdmrgext.c"
#undef RGB_RED
#undef RGB_GREEN
@@ -102,13 +102,13 @@ typedef my_upsampler *my_upsample_ptr;
#undef h2v1_merged_upsample_internal
#undef h2v2_merged_upsample_internal
-#define RGB_RED EXT_RGBX_RED
-#define RGB_GREEN EXT_RGBX_GREEN
-#define RGB_BLUE EXT_RGBX_BLUE
-#define RGB_ALPHA 3
-#define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE
-#define h2v1_merged_upsample_internal extrgbx_h2v1_merged_upsample_internal
-#define h2v2_merged_upsample_internal extrgbx_h2v2_merged_upsample_internal
+#define RGB_RED EXT_RGBX_RED
+#define RGB_GREEN EXT_RGBX_GREEN
+#define RGB_BLUE EXT_RGBX_BLUE
+#define RGB_ALPHA 3
+#define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE
+#define h2v1_merged_upsample_internal extrgbx_h2v1_merged_upsample_internal
+#define h2v2_merged_upsample_internal extrgbx_h2v2_merged_upsample_internal
#include "jdmrgext.c"
#undef RGB_RED
#undef RGB_GREEN
@@ -118,12 +118,12 @@ typedef my_upsampler *my_upsample_ptr;
#undef h2v1_merged_upsample_internal
#undef h2v2_merged_upsample_internal
-#define RGB_RED EXT_BGR_RED
-#define RGB_GREEN EXT_BGR_GREEN
-#define RGB_BLUE EXT_BGR_BLUE
-#define RGB_PIXELSIZE EXT_BGR_PIXELSIZE
-#define h2v1_merged_upsample_internal extbgr_h2v1_merged_upsample_internal
-#define h2v2_merged_upsample_internal extbgr_h2v2_merged_upsample_internal
+#define RGB_RED EXT_BGR_RED
+#define RGB_GREEN EXT_BGR_GREEN
+#define RGB_BLUE EXT_BGR_BLUE
+#define RGB_PIXELSIZE EXT_BGR_PIXELSIZE
+#define h2v1_merged_upsample_internal extbgr_h2v1_merged_upsample_internal
+#define h2v2_merged_upsample_internal extbgr_h2v2_merged_upsample_internal
#include "jdmrgext.c"
#undef RGB_RED
#undef RGB_GREEN
@@ -132,13 +132,13 @@ typedef my_upsampler *my_upsample_ptr;
#undef h2v1_merged_upsample_internal
#undef h2v2_merged_upsample_internal
-#define RGB_RED EXT_BGRX_RED
-#define RGB_GREEN EXT_BGRX_GREEN
-#define RGB_BLUE EXT_BGRX_BLUE
-#define RGB_ALPHA 3
-#define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE
-#define h2v1_merged_upsample_internal extbgrx_h2v1_merged_upsample_internal
-#define h2v2_merged_upsample_internal extbgrx_h2v2_merged_upsample_internal
+#define RGB_RED EXT_BGRX_RED
+#define RGB_GREEN EXT_BGRX_GREEN
+#define RGB_BLUE EXT_BGRX_BLUE
+#define RGB_ALPHA 3
+#define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE
+#define h2v1_merged_upsample_internal extbgrx_h2v1_merged_upsample_internal
+#define h2v2_merged_upsample_internal extbgrx_h2v2_merged_upsample_internal
#include "jdmrgext.c"
#undef RGB_RED
#undef RGB_GREEN
@@ -148,13 +148,13 @@ typedef my_upsampler *my_upsample_ptr;
#undef h2v1_merged_upsample_internal
#undef h2v2_merged_upsample_internal
-#define RGB_RED EXT_XBGR_RED
-#define RGB_GREEN EXT_XBGR_GREEN
-#define RGB_BLUE EXT_XBGR_BLUE
-#define RGB_ALPHA 0
-#define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE
-#define h2v1_merged_upsample_internal extxbgr_h2v1_merged_upsample_internal
-#define h2v2_merged_upsample_internal extxbgr_h2v2_merged_upsample_internal
+#define RGB_RED EXT_XBGR_RED
+#define RGB_GREEN EXT_XBGR_GREEN
+#define RGB_BLUE EXT_XBGR_BLUE
+#define RGB_ALPHA 0
+#define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE
+#define h2v1_merged_upsample_internal extxbgr_h2v1_merged_upsample_internal
+#define h2v2_merged_upsample_internal extxbgr_h2v2_merged_upsample_internal
#include "jdmrgext.c"
#undef RGB_RED
#undef RGB_GREEN
@@ -164,13 +164,13 @@ typedef my_upsampler *my_upsample_ptr;
#undef h2v1_merged_upsample_internal
#undef h2v2_merged_upsample_internal
-#define RGB_RED EXT_XRGB_RED
-#define RGB_GREEN EXT_XRGB_GREEN
-#define RGB_BLUE EXT_XRGB_BLUE
-#define RGB_ALPHA 0
-#define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE
-#define h2v1_merged_upsample_internal extxrgb_h2v1_merged_upsample_internal
-#define h2v2_merged_upsample_internal extxrgb_h2v2_merged_upsample_internal
+#define RGB_RED EXT_XRGB_RED
+#define RGB_GREEN EXT_XRGB_GREEN
+#define RGB_BLUE EXT_XRGB_BLUE
+#define RGB_ALPHA 0
+#define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE
+#define h2v1_merged_upsample_internal extxrgb_h2v1_merged_upsample_internal
+#define h2v2_merged_upsample_internal extxrgb_h2v2_merged_upsample_internal
#include "jdmrgext.c"
#undef RGB_RED
#undef RGB_GREEN
@@ -187,25 +187,25 @@ typedef my_upsampler *my_upsample_ptr;
*/
LOCAL(void)
-build_ycc_rgb_table (j_decompress_ptr cinfo)
+build_ycc_rgb_table(j_decompress_ptr cinfo)
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
int i;
JLONG x;
SHIFT_TEMPS
upsample->Cr_r_tab = (int *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (MAXJSAMPLE+1) * sizeof(int));
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE + 1) * sizeof(int));
upsample->Cb_b_tab = (int *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (MAXJSAMPLE+1) * sizeof(int));
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE + 1) * sizeof(int));
upsample->Cr_g_tab = (JLONG *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (MAXJSAMPLE+1) * sizeof(JLONG));
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE + 1) * sizeof(JLONG));
upsample->Cb_g_tab = (JLONG *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (MAXJSAMPLE+1) * sizeof(JLONG));
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE + 1) * sizeof(JLONG));
for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
/* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
@@ -217,10 +217,10 @@ build_ycc_rgb_table (j_decompress_ptr cinfo)
upsample->Cb_b_tab[i] = (int)
RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
/* Cr=>G value is scaled-up -0.71414 * x */
- upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x;
+ upsample->Cr_g_tab[i] = (-FIX(0.71414)) * x;
/* Cb=>G value is scaled-up -0.34414 * x */
/* We also add in ONE_HALF so that need not do it in inner loop */
- upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
+ upsample->Cb_g_tab[i] = (-FIX(0.34414)) * x + ONE_HALF;
}
}
@@ -230,9 +230,9 @@ build_ycc_rgb_table (j_decompress_ptr cinfo)
*/
METHODDEF(void)
-start_pass_merged_upsample (j_decompress_ptr cinfo)
+start_pass_merged_upsample(j_decompress_ptr cinfo)
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
/* Mark the spare buffer empty */
upsample->spare_full = FALSE;
@@ -248,14 +248,13 @@ start_pass_merged_upsample (j_decompress_ptr cinfo)
*/
METHODDEF(void)
-merged_2v_upsample (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
- JDIMENSION in_row_groups_avail,
- JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
- JDIMENSION out_rows_avail)
+merged_2v_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)
/* 2:1 vertical sampling case: may need a spare row. */
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
JSAMPROW work_ptrs[2];
JDIMENSION num_rows; /* number of rows returned to caller */
@@ -264,8 +263,8 @@ merged_2v_upsample (j_decompress_ptr cinfo,
JDIMENSION size = upsample->out_row_width;
if (cinfo->out_color_space == JCS_RGB565)
size = cinfo->output_width * 2;
- jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0,
- 1, size);
+ jcopy_sample_rows(&upsample->spare_row, 0, output_buf + *out_row_ctr, 0, 1,
+ size);
num_rows = 1;
upsample->spare_full = FALSE;
} else {
@@ -294,20 +293,19 @@ merged_2v_upsample (j_decompress_ptr cinfo,
*out_row_ctr += num_rows;
upsample->rows_to_go -= num_rows;
/* When the buffer is emptied, declare this input row group consumed */
- if (! upsample->spare_full)
+ if (!upsample->spare_full)
(*in_row_group_ctr)++;
}
METHODDEF(void)
-merged_1v_upsample (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
- JDIMENSION in_row_groups_avail,
- JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
- JDIMENSION out_rows_avail)
+merged_1v_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)
/* 1:1 vertical sampling case: much easier, never need a spare row. */
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
/* Just do the upsampling. */
(*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr,
@@ -333,43 +331,42 @@ merged_1v_upsample (j_decompress_ptr cinfo,
*/
METHODDEF(void)
-h2v1_merged_upsample (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+h2v1_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf)
{
switch (cinfo->out_color_space) {
- case JCS_EXT_RGB:
- extrgb_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
- case JCS_EXT_RGBX:
- case JCS_EXT_RGBA:
- extrgbx_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
- case JCS_EXT_BGR:
- extbgr_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
- case JCS_EXT_BGRX:
- case JCS_EXT_BGRA:
- extbgrx_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
- case JCS_EXT_XBGR:
- case JCS_EXT_ABGR:
- extxbgr_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
- case JCS_EXT_XRGB:
- case JCS_EXT_ARGB:
- extxrgb_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
- default:
- h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
+ case JCS_EXT_RGB:
+ extrgb_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
+ case JCS_EXT_RGBX:
+ case JCS_EXT_RGBA:
+ extrgbx_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
+ case JCS_EXT_BGR:
+ extbgr_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
+ case JCS_EXT_BGRX:
+ case JCS_EXT_BGRA:
+ extbgrx_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
+ case JCS_EXT_XBGR:
+ case JCS_EXT_ABGR:
+ extxbgr_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
+ case JCS_EXT_XRGB:
+ case JCS_EXT_ARGB:
+ extxrgb_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
+ default:
+ h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
}
}
@@ -379,43 +376,42 @@ h2v1_merged_upsample (j_decompress_ptr cinfo,
*/
METHODDEF(void)
-h2v2_merged_upsample (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+h2v2_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf)
{
switch (cinfo->out_color_space) {
- case JCS_EXT_RGB:
- extrgb_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
- case JCS_EXT_RGBX:
- case JCS_EXT_RGBA:
- extrgbx_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
- case JCS_EXT_BGR:
- extbgr_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
- case JCS_EXT_BGRX:
- case JCS_EXT_BGRA:
- extbgrx_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
- case JCS_EXT_XBGR:
- case JCS_EXT_ABGR:
- extxbgr_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
- case JCS_EXT_XRGB:
- case JCS_EXT_ARGB:
- extxrgb_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
- default:
- h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
- output_buf);
- break;
+ case JCS_EXT_RGB:
+ extrgb_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
+ case JCS_EXT_RGBX:
+ case JCS_EXT_RGBA:
+ extrgbx_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
+ case JCS_EXT_BGR:
+ extbgr_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
+ case JCS_EXT_BGRX:
+ case JCS_EXT_BGRA:
+ extbgrx_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
+ case JCS_EXT_XBGR:
+ case JCS_EXT_ABGR:
+ extxbgr_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
+ case JCS_EXT_XRGB:
+ case JCS_EXT_ARGB:
+ extxrgb_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
+ default:
+ h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr,
+ output_buf);
+ break;
}
}
@@ -424,24 +420,24 @@ h2v2_merged_upsample (j_decompress_ptr cinfo,
* RGB565 conversion
*/
-#define PACK_SHORT_565_LE(r, g, b) ((((r) << 8) & 0xF800) | \
- (((g) << 3) & 0x7E0) | ((b) >> 3))
-#define PACK_SHORT_565_BE(r, g, b) (((r) & 0xF8) | ((g) >> 5) | \
- (((g) << 11) & 0xE000) | \
- (((b) << 5) & 0x1F00))
+#define PACK_SHORT_565_LE(r, g, b) ((((r) << 8) & 0xF800) | \
+ (((g) << 3) & 0x7E0) | ((b) >> 3))
+#define PACK_SHORT_565_BE(r, g, b) (((r) & 0xF8) | ((g) >> 5) | \
+ (((g) << 11) & 0xE000) | \
+ (((b) << 5) & 0x1F00))
-#define PACK_TWO_PIXELS_LE(l, r) ((r << 16) | l)
-#define PACK_TWO_PIXELS_BE(l, r) ((l << 16) | r)
+#define PACK_TWO_PIXELS_LE(l, r) ((r << 16) | l)
+#define PACK_TWO_PIXELS_BE(l, r) ((l << 16) | r)
-#define PACK_NEED_ALIGNMENT(ptr) (((size_t)(ptr)) & 3)
+#define PACK_NEED_ALIGNMENT(ptr) (((size_t)(ptr)) & 3)
-#define WRITE_TWO_PIXELS_LE(addr, pixels) { \
- ((INT16*)(addr))[0] = (INT16)(pixels); \
- ((INT16*)(addr))[1] = (INT16)((pixels) >> 16); \
+#define WRITE_TWO_PIXELS_LE(addr, pixels) { \
+ ((INT16 *)(addr))[0] = (INT16)(pixels); \
+ ((INT16 *)(addr))[1] = (INT16)((pixels) >> 16); \
}
-#define WRITE_TWO_PIXELS_BE(addr, pixels) { \
- ((INT16*)(addr))[1] = (INT16)(pixels); \
- ((INT16*)(addr))[0] = (INT16)((pixels) >> 16); \
+#define WRITE_TWO_PIXELS_BE(addr, pixels) { \
+ ((INT16 *)(addr))[1] = (INT16)(pixels); \
+ ((INT16 *)(addr))[0] = (INT16)((pixels) >> 16); \
}
#define DITHER_565_R(r, dither) ((r) + ((dither) & 0xFF))
@@ -467,13 +463,13 @@ static const JLONG dither_matrix[4] = {
/* Include inline routines for RGB565 conversion */
-#define PACK_SHORT_565 PACK_SHORT_565_LE
-#define PACK_TWO_PIXELS PACK_TWO_PIXELS_LE
-#define WRITE_TWO_PIXELS WRITE_TWO_PIXELS_LE
-#define h2v1_merged_upsample_565_internal h2v1_merged_upsample_565_le
-#define h2v1_merged_upsample_565D_internal h2v1_merged_upsample_565D_le
-#define h2v2_merged_upsample_565_internal h2v2_merged_upsample_565_le
-#define h2v2_merged_upsample_565D_internal h2v2_merged_upsample_565D_le
+#define PACK_SHORT_565 PACK_SHORT_565_LE
+#define PACK_TWO_PIXELS PACK_TWO_PIXELS_LE
+#define WRITE_TWO_PIXELS WRITE_TWO_PIXELS_LE
+#define h2v1_merged_upsample_565_internal h2v1_merged_upsample_565_le
+#define h2v1_merged_upsample_565D_internal h2v1_merged_upsample_565D_le
+#define h2v2_merged_upsample_565_internal h2v2_merged_upsample_565_le
+#define h2v2_merged_upsample_565D_internal h2v2_merged_upsample_565D_le
#include "jdmrg565.c"
#undef PACK_SHORT_565
#undef PACK_TWO_PIXELS
@@ -483,13 +479,13 @@ static const JLONG dither_matrix[4] = {
#undef h2v2_merged_upsample_565_internal
#undef h2v2_merged_upsample_565D_internal
-#define PACK_SHORT_565 PACK_SHORT_565_BE
-#define PACK_TWO_PIXELS PACK_TWO_PIXELS_BE
-#define WRITE_TWO_PIXELS WRITE_TWO_PIXELS_BE
-#define h2v1_merged_upsample_565_internal h2v1_merged_upsample_565_be
-#define h2v1_merged_upsample_565D_internal h2v1_merged_upsample_565D_be
-#define h2v2_merged_upsample_565_internal h2v2_merged_upsample_565_be
-#define h2v2_merged_upsample_565D_internal h2v2_merged_upsample_565D_be
+#define PACK_SHORT_565 PACK_SHORT_565_BE
+#define PACK_TWO_PIXELS PACK_TWO_PIXELS_BE
+#define WRITE_TWO_PIXELS WRITE_TWO_PIXELS_BE
+#define h2v1_merged_upsample_565_internal h2v1_merged_upsample_565_be
+#define h2v1_merged_upsample_565D_internal h2v1_merged_upsample_565D_be
+#define h2v2_merged_upsample_565_internal h2v2_merged_upsample_565_be
+#define h2v2_merged_upsample_565D_internal h2v2_merged_upsample_565D_be
#include "jdmrg565.c"
#undef PACK_SHORT_565
#undef PACK_TWO_PIXELS
@@ -510,9 +506,8 @@ static INLINE boolean is_big_endian(void)
METHODDEF(void)
-h2v1_merged_upsample_565 (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+h2v1_merged_upsample_565(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf)
{
if (is_big_endian())
h2v1_merged_upsample_565_be(cinfo, input_buf, in_row_group_ctr,
@@ -520,13 +515,12 @@ h2v1_merged_upsample_565 (j_decompress_ptr cinfo,
else
h2v1_merged_upsample_565_le(cinfo, input_buf, in_row_group_ctr,
output_buf);
- }
+}
METHODDEF(void)
-h2v1_merged_upsample_565D (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+h2v1_merged_upsample_565D(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf)
{
if (is_big_endian())
h2v1_merged_upsample_565D_be(cinfo, input_buf, in_row_group_ctr,
@@ -538,9 +532,8 @@ h2v1_merged_upsample_565D (j_decompress_ptr cinfo,
METHODDEF(void)
-h2v2_merged_upsample_565 (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+h2v2_merged_upsample_565(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf)
{
if (is_big_endian())
h2v2_merged_upsample_565_be(cinfo, input_buf, in_row_group_ctr,
@@ -552,9 +545,8 @@ h2v2_merged_upsample_565 (j_decompress_ptr cinfo,
METHODDEF(void)
-h2v2_merged_upsample_565D (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+h2v2_merged_upsample_565D(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf)
{
if (is_big_endian())
h2v2_merged_upsample_565D_be(cinfo, input_buf, in_row_group_ctr,
@@ -574,14 +566,14 @@ h2v2_merged_upsample_565D (j_decompress_ptr cinfo,
*/
GLOBAL(void)
-jinit_merged_upsampler (j_decompress_ptr cinfo)
+jinit_merged_upsampler(j_decompress_ptr cinfo)
{
my_upsample_ptr upsample;
upsample = (my_upsample_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_upsampler));
- cinfo->upsample = (struct jpeg_upsampler *) upsample;
+ cinfo->upsample = (struct jpeg_upsampler *)upsample;
upsample->pub.start_pass = start_pass_merged_upsample;
upsample->pub.need_context_rows = FALSE;
@@ -602,8 +594,8 @@ jinit_merged_upsampler (j_decompress_ptr cinfo)
}
/* Allocate a spare row buffer */
upsample->spare_row = (JSAMPROW)
- (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (size_t) (upsample->out_row_width * sizeof(JSAMPLE)));
+ (*cinfo->mem->alloc_large) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (size_t)(upsample->out_row_width * sizeof(JSAMPLE)));
} else {
upsample->pub.upsample = merged_1v_upsample;
if (jsimd_can_h2v1_merged_upsample())
diff --git a/src/3rdparty/libjpeg/src/jdmrg565.c b/src/3rdparty/libjpeg/src/jdmrg565.c
index 18287b3735..1b87e3718d 100644
--- a/src/3rdparty/libjpeg/src/jdmrg565.c
+++ b/src/3rdparty/libjpeg/src/jdmrg565.c
@@ -5,7 +5,7 @@
* Copyright (C) 1994-1996, Thomas G. Lane.
* libjpeg-turbo Modifications:
* Copyright (C) 2013, Linaro Limited.
- * Copyright (C) 2014-2015, D. R. Commander.
+ * Copyright (C) 2014-2015, 2018, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -15,23 +15,22 @@
INLINE
LOCAL(void)
-h2v1_merged_upsample_565_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf,
- JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+h2v1_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf)
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
register int y, cred, cgreen, cblue;
int cb, cr;
register JSAMPROW outptr;
JSAMPROW inptr0, inptr1, inptr2;
JDIMENSION col;
/* copy these pointers into registers if possible */
- register JSAMPLE * range_limit = cinfo->sample_range_limit;
- int * Crrtab = upsample->Cr_r_tab;
- int * Cbbtab = upsample->Cb_b_tab;
- JLONG * Crgtab = upsample->Cr_g_tab;
- JLONG * Cbgtab = upsample->Cb_g_tab;
+ register JSAMPLE *range_limit = cinfo->sample_range_limit;
+ int *Crrtab = upsample->Cr_r_tab;
+ int *Cbbtab = upsample->Cb_b_tab;
+ JLONG *Crgtab = upsample->Cr_g_tab;
+ JLONG *Cbgtab = upsample->Cb_g_tab;
unsigned int r, g, b;
JLONG rgb;
SHIFT_TEMPS
@@ -47,7 +46,7 @@ h2v1_merged_upsample_565_internal (j_decompress_ptr cinfo,
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
cred = Crrtab[cr];
- cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
/* Fetch 2 Y values and emit 2 pixels */
@@ -72,37 +71,37 @@ h2v1_merged_upsample_565_internal (j_decompress_ptr cinfo,
cb = GETJSAMPLE(*inptr1);
cr = GETJSAMPLE(*inptr2);
cred = Crrtab[cr];
- cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
y = GETJSAMPLE(*inptr0);
r = range_limit[y + cred];
g = range_limit[y + cgreen];
b = range_limit[y + cblue];
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr = (INT16)rgb;
- }
- }
+ *(INT16 *)outptr = (INT16)rgb;
+ }
+}
INLINE
LOCAL(void)
-h2v1_merged_upsample_565D_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf,
- JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+h2v1_merged_upsample_565D_internal(j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf)
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
register int y, cred, cgreen, cblue;
int cb, cr;
register JSAMPROW outptr;
JSAMPROW inptr0, inptr1, inptr2;
JDIMENSION col;
/* copy these pointers into registers if possible */
- register JSAMPLE * range_limit = cinfo->sample_range_limit;
- int * Crrtab = upsample->Cr_r_tab;
- int * Cbbtab = upsample->Cb_b_tab;
- JLONG * Crgtab = upsample->Cr_g_tab;
- JLONG * Cbgtab = upsample->Cb_g_tab;
+ register JSAMPLE *range_limit = cinfo->sample_range_limit;
+ int *Crrtab = upsample->Cr_r_tab;
+ int *Cbbtab = upsample->Cb_b_tab;
+ JLONG *Crgtab = upsample->Cr_g_tab;
+ JLONG *Cbgtab = upsample->Cb_g_tab;
JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
unsigned int r, g, b;
JLONG rgb;
@@ -119,7 +118,7 @@ h2v1_merged_upsample_565D_internal (j_decompress_ptr cinfo,
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
cred = Crrtab[cr];
- cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
/* Fetch 2 Y values and emit 2 pixels */
@@ -146,37 +145,36 @@ h2v1_merged_upsample_565D_internal (j_decompress_ptr cinfo,
cb = GETJSAMPLE(*inptr1);
cr = GETJSAMPLE(*inptr2);
cred = Crrtab[cr];
- cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
y = GETJSAMPLE(*inptr0);
r = range_limit[DITHER_565_R(y + cred, d0)];
g = range_limit[DITHER_565_G(y + cgreen, d0)];
b = range_limit[DITHER_565_B(y + cblue, d0)];
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr = (INT16)rgb;
+ *(INT16 *)outptr = (INT16)rgb;
}
}
INLINE
LOCAL(void)
-h2v2_merged_upsample_565_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf,
- JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+h2v2_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf)
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
register int y, cred, cgreen, cblue;
int cb, cr;
register JSAMPROW outptr0, outptr1;
JSAMPROW inptr00, inptr01, inptr1, inptr2;
JDIMENSION col;
/* copy these pointers into registers if possible */
- register JSAMPLE * range_limit = cinfo->sample_range_limit;
- int * Crrtab = upsample->Cr_r_tab;
- int * Cbbtab = upsample->Cb_b_tab;
- JLONG * Crgtab = upsample->Cr_g_tab;
- JLONG * Cbgtab = upsample->Cb_g_tab;
+ register JSAMPLE *range_limit = cinfo->sample_range_limit;
+ int *Crrtab = upsample->Cr_r_tab;
+ int *Cbbtab = upsample->Cb_b_tab;
+ JLONG *Crgtab = upsample->Cr_g_tab;
+ JLONG *Cbgtab = upsample->Cb_g_tab;
unsigned int r, g, b;
JLONG rgb;
SHIFT_TEMPS
@@ -194,7 +192,7 @@ h2v2_merged_upsample_565_internal (j_decompress_ptr cinfo,
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
cred = Crrtab[cr];
- cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
/* Fetch 4 Y values and emit 4 pixels */
@@ -234,7 +232,7 @@ h2v2_merged_upsample_565_internal (j_decompress_ptr cinfo,
cb = GETJSAMPLE(*inptr1);
cr = GETJSAMPLE(*inptr2);
cred = Crrtab[cr];
- cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
y = GETJSAMPLE(*inptr00);
@@ -242,45 +240,45 @@ h2v2_merged_upsample_565_internal (j_decompress_ptr cinfo,
g = range_limit[y + cgreen];
b = range_limit[y + cblue];
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr0 = (INT16)rgb;
+ *(INT16 *)outptr0 = (INT16)rgb;
y = GETJSAMPLE(*inptr01);
r = range_limit[y + cred];
g = range_limit[y + cgreen];
b = range_limit[y + cblue];
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr1 = (INT16)rgb;
+ *(INT16 *)outptr1 = (INT16)rgb;
}
}
INLINE
LOCAL(void)
-h2v2_merged_upsample_565D_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf,
- JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+h2v2_merged_upsample_565D_internal(j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf)
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
register int y, cred, cgreen, cblue;
int cb, cr;
register JSAMPROW outptr0, outptr1;
JSAMPROW inptr00, inptr01, inptr1, inptr2;
JDIMENSION col;
/* copy these pointers into registers if possible */
- register JSAMPLE * range_limit = cinfo->sample_range_limit;
- int * Crrtab = upsample->Cr_r_tab;
- int * Cbbtab = upsample->Cb_b_tab;
- JLONG * Crgtab = upsample->Cr_g_tab;
- JLONG * Cbgtab = upsample->Cb_g_tab;
+ register JSAMPLE *range_limit = cinfo->sample_range_limit;
+ int *Crrtab = upsample->Cr_r_tab;
+ int *Cbbtab = upsample->Cb_b_tab;
+ JLONG *Crgtab = upsample->Cr_g_tab;
+ JLONG *Cbgtab = upsample->Cb_g_tab;
JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
- JLONG d1 = dither_matrix[(cinfo->output_scanline+1) & DITHER_MASK];
+ JLONG d1 = dither_matrix[(cinfo->output_scanline + 1) & DITHER_MASK];
unsigned int r, g, b;
JLONG rgb;
SHIFT_TEMPS
- inptr00 = input_buf[0][in_row_group_ctr*2];
- inptr01 = input_buf[0][in_row_group_ctr*2 + 1];
+ inptr00 = input_buf[0][in_row_group_ctr * 2];
+ inptr01 = input_buf[0][in_row_group_ctr * 2 + 1];
inptr1 = input_buf[1][in_row_group_ctr];
inptr2 = input_buf[2][in_row_group_ctr];
outptr0 = output_buf[0];
@@ -292,7 +290,7 @@ h2v2_merged_upsample_565D_internal (j_decompress_ptr cinfo,
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
cred = Crrtab[cr];
- cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
/* Fetch 4 Y values and emit 4 pixels */
@@ -304,20 +302,20 @@ h2v2_merged_upsample_565D_internal (j_decompress_ptr cinfo,
rgb = PACK_SHORT_565(r, g, b);
y = GETJSAMPLE(*inptr00++);
- r = range_limit[DITHER_565_R(y + cred, d1)];
- g = range_limit[DITHER_565_G(y + cgreen, d1)];
- b = range_limit[DITHER_565_B(y + cblue, d1)];
- d1 = DITHER_ROTATE(d1);
+ r = range_limit[DITHER_565_R(y + cred, d0)];
+ g = range_limit[DITHER_565_G(y + cgreen, d0)];
+ b = range_limit[DITHER_565_B(y + cblue, d0)];
+ d0 = DITHER_ROTATE(d0);
rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r, g, b));
WRITE_TWO_PIXELS(outptr0, rgb);
outptr0 += 4;
y = GETJSAMPLE(*inptr01++);
- r = range_limit[DITHER_565_R(y + cred, d0)];
- g = range_limit[DITHER_565_G(y + cgreen, d0)];
- b = range_limit[DITHER_565_B(y + cblue, d0)];
- d0 = DITHER_ROTATE(d0);
+ r = range_limit[DITHER_565_R(y + cred, d1)];
+ g = range_limit[DITHER_565_G(y + cgreen, d1)];
+ b = range_limit[DITHER_565_B(y + cblue, d1)];
+ d1 = DITHER_ROTATE(d1);
rgb = PACK_SHORT_565(r, g, b);
y = GETJSAMPLE(*inptr01++);
@@ -336,7 +334,7 @@ h2v2_merged_upsample_565D_internal (j_decompress_ptr cinfo,
cb = GETJSAMPLE(*inptr1);
cr = GETJSAMPLE(*inptr2);
cred = Crrtab[cr];
- cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
y = GETJSAMPLE(*inptr00);
@@ -344,13 +342,13 @@ h2v2_merged_upsample_565D_internal (j_decompress_ptr cinfo,
g = range_limit[DITHER_565_G(y + cgreen, d0)];
b = range_limit[DITHER_565_B(y + cblue, d0)];
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr0 = (INT16)rgb;
+ *(INT16 *)outptr0 = (INT16)rgb;
y = GETJSAMPLE(*inptr01);
r = range_limit[DITHER_565_R(y + cred, d1)];
g = range_limit[DITHER_565_G(y + cgreen, d1)];
b = range_limit[DITHER_565_B(y + cblue, d1)];
rgb = PACK_SHORT_565(r, g, b);
- *(INT16*)outptr1 = (INT16)rgb;
+ *(INT16 *)outptr1 = (INT16)rgb;
}
}
diff --git a/src/3rdparty/libjpeg/src/jdmrgext.c b/src/3rdparty/libjpeg/src/jdmrgext.c
index 9d7d2af2e9..b1c27df56a 100644
--- a/src/3rdparty/libjpeg/src/jdmrgext.c
+++ b/src/3rdparty/libjpeg/src/jdmrgext.c
@@ -21,23 +21,22 @@
INLINE
LOCAL(void)
-h2v1_merged_upsample_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf,
- JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+h2v1_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf)
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
register int y, cred, cgreen, cblue;
int cb, cr;
register JSAMPROW outptr;
JSAMPROW inptr0, inptr1, inptr2;
JDIMENSION col;
/* copy these pointers into registers if possible */
- register JSAMPLE * range_limit = cinfo->sample_range_limit;
- int * Crrtab = upsample->Cr_r_tab;
- int * Cbbtab = upsample->Cb_b_tab;
- JLONG * Crgtab = upsample->Cr_g_tab;
- JLONG * Cbgtab = upsample->Cb_g_tab;
+ register JSAMPLE *range_limit = cinfo->sample_range_limit;
+ int *Crrtab = upsample->Cr_r_tab;
+ int *Cbbtab = upsample->Cb_b_tab;
+ JLONG *Crgtab = upsample->Cr_g_tab;
+ JLONG *Cbgtab = upsample->Cb_g_tab;
SHIFT_TEMPS
inptr0 = input_buf[0][in_row_group_ctr];
@@ -50,7 +49,7 @@ h2v1_merged_upsample_internal (j_decompress_ptr cinfo,
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
cred = Crrtab[cr];
- cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
/* Fetch 2 Y values and emit 2 pixels */
y = GETJSAMPLE(*inptr0++);
@@ -75,7 +74,7 @@ h2v1_merged_upsample_internal (j_decompress_ptr cinfo,
cb = GETJSAMPLE(*inptr1);
cr = GETJSAMPLE(*inptr2);
cred = Crrtab[cr];
- cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
y = GETJSAMPLE(*inptr0);
outptr[RGB_RED] = range_limit[y + cred];
@@ -94,27 +93,26 @@ h2v1_merged_upsample_internal (j_decompress_ptr cinfo,
INLINE
LOCAL(void)
-h2v2_merged_upsample_internal (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf,
- JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf)
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
register int y, cred, cgreen, cblue;
int cb, cr;
register JSAMPROW outptr0, outptr1;
JSAMPROW inptr00, inptr01, inptr1, inptr2;
JDIMENSION col;
/* copy these pointers into registers if possible */
- register JSAMPLE * range_limit = cinfo->sample_range_limit;
- int * Crrtab = upsample->Cr_r_tab;
- int * Cbbtab = upsample->Cb_b_tab;
- JLONG * Crgtab = upsample->Cr_g_tab;
- JLONG * Cbgtab = upsample->Cb_g_tab;
+ register JSAMPLE *range_limit = cinfo->sample_range_limit;
+ int *Crrtab = upsample->Cr_r_tab;
+ int *Cbbtab = upsample->Cb_b_tab;
+ JLONG *Crgtab = upsample->Cr_g_tab;
+ JLONG *Cbgtab = upsample->Cb_g_tab;
SHIFT_TEMPS
- inptr00 = input_buf[0][in_row_group_ctr*2];
- inptr01 = input_buf[0][in_row_group_ctr*2 + 1];
+ inptr00 = input_buf[0][in_row_group_ctr * 2];
+ inptr01 = input_buf[0][in_row_group_ctr * 2 + 1];
inptr1 = input_buf[1][in_row_group_ctr];
inptr2 = input_buf[2][in_row_group_ctr];
outptr0 = output_buf[0];
@@ -125,7 +123,7 @@ h2v2_merged_upsample_internal (j_decompress_ptr cinfo,
cb = GETJSAMPLE(*inptr1++);
cr = GETJSAMPLE(*inptr2++);
cred = Crrtab[cr];
- cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
/* Fetch 4 Y values and emit 4 pixels */
y = GETJSAMPLE(*inptr00++);
@@ -166,7 +164,7 @@ h2v2_merged_upsample_internal (j_decompress_ptr cinfo,
cb = GETJSAMPLE(*inptr1);
cr = GETJSAMPLE(*inptr2);
cred = Crrtab[cr];
- cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
cblue = Cbbtab[cb];
y = GETJSAMPLE(*inptr00);
outptr0[RGB_RED] = range_limit[y + cred];
diff --git a/src/3rdparty/libjpeg/src/jdphuff.c b/src/3rdparty/libjpeg/src/jdphuff.c
index c927ffa071..9e82636bbd 100644
--- a/src/3rdparty/libjpeg/src/jdphuff.c
+++ b/src/3rdparty/libjpeg/src/jdphuff.c
@@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1995-1997, Thomas G. Lane.
* libjpeg-turbo Modifications:
- * Copyright (C) 2015-2016, D. R. Commander.
+ * Copyright (C) 2015-2016, 2018, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -15,12 +15,16 @@
* up to the start of the current MCU. To do this, we copy state variables
* into local working storage, and update them back to the permanent
* storage only upon successful completion of an MCU.
+ *
+ * NOTE: All referenced figures are from
+ * Recommendation ITU-T T.81 (1992) | ISO/IEC 10918-1:1994.
*/
#define JPEG_INTERNALS
#include "jinclude.h"
#include "jpeglib.h"
#include "jdhuff.h" /* Declarations shared with jdhuff.c */
+#include <limits.h>
#ifdef D_PROGRESSIVE_SUPPORTED
@@ -43,15 +47,15 @@ typedef struct {
*/
#ifndef NO_STRUCT_ASSIGN
-#define ASSIGN_STATE(dest,src) ((dest) = (src))
+#define ASSIGN_STATE(dest, src) ((dest) = (src))
#else
#if MAX_COMPS_IN_SCAN == 4
-#define ASSIGN_STATE(dest,src) \
- ((dest).EOBRUN = (src).EOBRUN, \
- (dest).last_dc_val[0] = (src).last_dc_val[0], \
- (dest).last_dc_val[1] = (src).last_dc_val[1], \
- (dest).last_dc_val[2] = (src).last_dc_val[2], \
- (dest).last_dc_val[3] = (src).last_dc_val[3])
+#define ASSIGN_STATE(dest, src) \
+ ((dest).EOBRUN = (src).EOBRUN, \
+ (dest).last_dc_val[0] = (src).last_dc_val[0], \
+ (dest).last_dc_val[1] = (src).last_dc_val[1], \
+ (dest).last_dc_val[2] = (src).last_dc_val[2], \
+ (dest).last_dc_val[3] = (src).last_dc_val[3])
#endif
#endif
@@ -77,14 +81,14 @@ typedef struct {
typedef phuff_entropy_decoder *phuff_entropy_ptr;
/* Forward declarations */
-METHODDEF(boolean) decode_mcu_DC_first (j_decompress_ptr cinfo,
+METHODDEF(boolean) decode_mcu_DC_first(j_decompress_ptr cinfo,
+ JBLOCKROW *MCU_data);
+METHODDEF(boolean) decode_mcu_AC_first(j_decompress_ptr cinfo,
+ JBLOCKROW *MCU_data);
+METHODDEF(boolean) decode_mcu_DC_refine(j_decompress_ptr cinfo,
JBLOCKROW *MCU_data);
-METHODDEF(boolean) decode_mcu_AC_first (j_decompress_ptr cinfo,
+METHODDEF(boolean) decode_mcu_AC_refine(j_decompress_ptr cinfo,
JBLOCKROW *MCU_data);
-METHODDEF(boolean) decode_mcu_DC_refine (j_decompress_ptr cinfo,
- JBLOCKROW *MCU_data);
-METHODDEF(boolean) decode_mcu_AC_refine (j_decompress_ptr cinfo,
- JBLOCKROW *MCU_data);
/*
@@ -92,9 +96,9 @@ METHODDEF(boolean) decode_mcu_AC_refine (j_decompress_ptr cinfo,
*/
METHODDEF(void)
-start_pass_phuff_decoder (j_decompress_ptr cinfo)
+start_pass_phuff_decoder(j_decompress_ptr cinfo)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
boolean is_DC_band, bad;
int ci, coefi, tbl;
d_derived_tbl **pdtbl;
@@ -118,7 +122,7 @@ start_pass_phuff_decoder (j_decompress_ptr cinfo)
}
if (cinfo->Ah != 0) {
/* Successive approximation refinement scan: must have Al = Ah-1. */
- if (cinfo->Al != cinfo->Ah-1)
+ if (cinfo->Al != cinfo->Ah - 1)
bad = TRUE;
}
if (cinfo->Al > 13) /* need not check for < 0 */
@@ -138,7 +142,7 @@ start_pass_phuff_decoder (j_decompress_ptr cinfo)
*/
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
int cindex = cinfo->cur_comp_info[ci]->component_index;
- coef_bit_ptr = & cinfo->coef_bits[cindex][0];
+ coef_bit_ptr = &cinfo->coef_bits[cindex][0];
if (!is_DC_band && coef_bit_ptr[0] < 0) /* AC without prior DC scan */
WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0);
for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) {
@@ -205,22 +209,26 @@ start_pass_phuff_decoder (j_decompress_ptr cinfo)
#define AVOID_TABLES
#ifdef AVOID_TABLES
-#define NEG_1 ((unsigned)-1)
-#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((NEG_1)<<(s)) + 1) : (x))
+#define NEG_1 ((unsigned)-1)
+#define HUFF_EXTEND(x, s) \
+ ((x) < (1 << ((s) - 1)) ? (x) + (((NEG_1) << (s)) + 1) : (x))
#else
-#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
+#define HUFF_EXTEND(x, s) \
+ ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
-static const int extend_test[16] = /* entry n is 2**(n-1) */
- { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
- 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
+static const int extend_test[16] = { /* entry n is 2**(n-1) */
+ 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
+ 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000
+};
-static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
- { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
- ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
- ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
- ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
+static const int extend_offset[16] = { /* entry n is (-1 << n) + 1 */
+ 0, ((-1) << 1) + 1, ((-1) << 2) + 1, ((-1) << 3) + 1, ((-1) << 4) + 1,
+ ((-1) << 5) + 1, ((-1) << 6) + 1, ((-1) << 7) + 1, ((-1) << 8) + 1,
+ ((-1) << 9) + 1, ((-1) << 10) + 1, ((-1) << 11) + 1, ((-1) << 12) + 1,
+ ((-1) << 13) + 1, ((-1) << 14) + 1, ((-1) << 15) + 1
+};
#endif /* AVOID_TABLES */
@@ -231,9 +239,9 @@ static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
*/
LOCAL(boolean)
-process_restart (j_decompress_ptr cinfo)
+process_restart(j_decompress_ptr cinfo)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
int ci;
/* Throw away any unused bits remaining in bit buffer; */
@@ -242,7 +250,7 @@ process_restart (j_decompress_ptr cinfo)
entropy->bitstate.bits_left = 0;
/* Advance past the RSTn marker */
- if (! (*cinfo->marker->read_restart_marker) (cinfo))
+ if (!(*cinfo->marker->read_restart_marker) (cinfo))
return FALSE;
/* Re-initialize DC predictions to 0 */
@@ -289,9 +297,9 @@ process_restart (j_decompress_ptr cinfo)
*/
METHODDEF(boolean)
-decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+decode_mcu_DC_first(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
int Al = cinfo->Al;
register int s, r;
int blkn, ci;
@@ -304,17 +312,17 @@ decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
/* Process restart marker if needed; may have to suspend */
if (cinfo->restart_interval) {
if (entropy->restarts_to_go == 0)
- if (! process_restart(cinfo))
+ if (!process_restart(cinfo))
return FALSE;
}
/* If we've run out of data, just leave the MCU set to zeroes.
* This way, we return uniform gray for the remainder of the segment.
*/
- if (! entropy->pub.insufficient_data) {
+ if (!entropy->pub.insufficient_data) {
/* Load up working state */
- BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+ BITREAD_LOAD_STATE(cinfo, entropy->bitstate);
ASSIGN_STATE(state, entropy->saved);
/* Outer loop handles each block in the MCU */
@@ -336,14 +344,18 @@ decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
}
/* Convert DC difference to actual value, update last_dc_val */
+ if ((state.last_dc_val[ci] >= 0 &&
+ s > INT_MAX - state.last_dc_val[ci]) ||
+ (state.last_dc_val[ci] < 0 && s < INT_MIN - state.last_dc_val[ci]))
+ ERREXIT(cinfo, JERR_BAD_DCT_COEF);
s += state.last_dc_val[ci];
state.last_dc_val[ci] = s;
/* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */
- (*block)[0] = (JCOEF) LEFT_SHIFT(s, Al);
+ (*block)[0] = (JCOEF)LEFT_SHIFT(s, Al);
}
/* Completed MCU, so update state */
- BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ BITREAD_SAVE_STATE(cinfo, entropy->bitstate);
ASSIGN_STATE(entropy->saved, state);
}
@@ -360,9 +372,9 @@ decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
*/
METHODDEF(boolean)
-decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+decode_mcu_AC_first(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
int Se = cinfo->Se;
int Al = cinfo->Al;
register int s, k, r;
@@ -374,14 +386,14 @@ decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
/* Process restart marker if needed; may have to suspend */
if (cinfo->restart_interval) {
if (entropy->restarts_to_go == 0)
- if (! process_restart(cinfo))
+ if (!process_restart(cinfo))
return FALSE;
}
/* If we've run out of data, just leave the MCU set to zeroes.
* This way, we return uniform gray for the remainder of the segment.
*/
- if (! entropy->pub.insufficient_data) {
+ if (!entropy->pub.insufficient_data) {
/* Load up working state.
* We can avoid loading/saving bitread state if in an EOB run.
@@ -393,7 +405,7 @@ decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
if (EOBRUN > 0) /* if it's a band of zeroes... */
EOBRUN--; /* ...process it now (we do nothing) */
else {
- BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+ BITREAD_LOAD_STATE(cinfo, entropy->bitstate);
block = MCU_data[0];
tbl = entropy->ac_derived_tbl;
@@ -407,7 +419,7 @@ decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
r = GET_BITS(s);
s = HUFF_EXTEND(r, s);
/* Scale and output coefficient in natural (dezigzagged) order */
- (*block)[jpeg_natural_order[k]] = (JCOEF) LEFT_SHIFT(s, Al);
+ (*block)[jpeg_natural_order[k]] = (JCOEF)LEFT_SHIFT(s, Al);
} else {
if (r == 15) { /* ZRL */
k += 15; /* skip 15 zeroes in band */
@@ -424,7 +436,7 @@ decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
}
}
- BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ BITREAD_SAVE_STATE(cinfo, entropy->bitstate);
}
/* Completed MCU, so update state */
@@ -445,9 +457,9 @@ decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
*/
METHODDEF(boolean)
-decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+decode_mcu_DC_refine(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */
int blkn;
JBLOCKROW block;
@@ -456,7 +468,7 @@ decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
/* Process restart marker if needed; may have to suspend */
if (cinfo->restart_interval) {
if (entropy->restarts_to_go == 0)
- if (! process_restart(cinfo))
+ if (!process_restart(cinfo))
return FALSE;
}
@@ -465,7 +477,7 @@ decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
*/
/* Load up working state */
- BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+ BITREAD_LOAD_STATE(cinfo, entropy->bitstate);
/* Outer loop handles each block in the MCU */
@@ -480,7 +492,7 @@ decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
}
/* Completed MCU, so update state */
- BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ BITREAD_SAVE_STATE(cinfo, entropy->bitstate);
/* Account for restart interval (no-op if not using restarts) */
entropy->restarts_to_go--;
@@ -494,9 +506,9 @@ decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
*/
METHODDEF(boolean)
-decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+decode_mcu_AC_refine(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
{
- phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr)cinfo->entropy;
int Se = cinfo->Se;
int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */
int m1 = (NEG_1) << cinfo->Al; /* -1 in the bit position being coded */
@@ -512,16 +524,16 @@ decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
/* Process restart marker if needed; may have to suspend */
if (cinfo->restart_interval) {
if (entropy->restarts_to_go == 0)
- if (! process_restart(cinfo))
+ if (!process_restart(cinfo))
return FALSE;
}
/* If we've run out of data, don't modify the MCU.
*/
- if (! entropy->pub.insufficient_data) {
+ if (!entropy->pub.insufficient_data) {
/* Load up working state */
- BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+ BITREAD_LOAD_STATE(cinfo, entropy->bitstate);
EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */
/* There is always only one block per MCU */
@@ -589,7 +601,7 @@ decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
if (s) {
int pos = jpeg_natural_order[k];
/* Output newly nonzero coefficient */
- (*block)[pos] = (JCOEF) s;
+ (*block)[pos] = (JCOEF)s;
/* Remember its position in case we have to suspend */
newnz_pos[num_newnz++] = pos;
}
@@ -621,7 +633,7 @@ decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
}
/* Completed MCU, so update state */
- BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ BITREAD_SAVE_STATE(cinfo, entropy->bitstate);
entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */
}
@@ -644,16 +656,16 @@ undoit:
*/
GLOBAL(void)
-jinit_phuff_decoder (j_decompress_ptr cinfo)
+jinit_phuff_decoder(j_decompress_ptr cinfo)
{
phuff_entropy_ptr entropy;
int *coef_bit_ptr;
int ci, i;
entropy = (phuff_entropy_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(phuff_entropy_decoder));
- cinfo->entropy = (struct jpeg_entropy_decoder *) entropy;
+ cinfo->entropy = (struct jpeg_entropy_decoder *)entropy;
entropy->pub.start_pass = start_pass_phuff_decoder;
/* Mark derived tables unallocated */
@@ -663,9 +675,10 @@ jinit_phuff_decoder (j_decompress_ptr cinfo)
/* Create progression status table */
cinfo->coef_bits = (int (*)[DCTSIZE2])
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- cinfo->num_components*DCTSIZE2*sizeof(int));
- coef_bit_ptr = & cinfo->coef_bits[0][0];
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ cinfo->num_components * DCTSIZE2 *
+ sizeof(int));
+ coef_bit_ptr = &cinfo->coef_bits[0][0];
for (ci = 0; ci < cinfo->num_components; ci++)
for (i = 0; i < DCTSIZE2; i++)
*coef_bit_ptr++ = -1;
diff --git a/src/3rdparty/libjpeg/src/jdpostct.c b/src/3rdparty/libjpeg/src/jdpostct.c
index 601fc2a792..6a2cf5c1b3 100644
--- a/src/3rdparty/libjpeg/src/jdpostct.c
+++ b/src/3rdparty/libjpeg/src/jdpostct.c
@@ -46,22 +46,28 @@ typedef my_post_controller *my_post_ptr;
/* Forward declarations */
-METHODDEF(void) post_process_1pass
- (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
- JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail,
- JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
- JDIMENSION out_rows_avail);
+METHODDEF(void) post_process_1pass(j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail);
#ifdef QUANT_2PASS_SUPPORTED
-METHODDEF(void) post_process_prepass
- (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
- JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail,
- JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
- JDIMENSION out_rows_avail);
-METHODDEF(void) post_process_2pass
- (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
- JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail,
- JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
- JDIMENSION out_rows_avail);
+METHODDEF(void) post_process_prepass(j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail);
+METHODDEF(void) post_process_2pass(j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail);
#endif
@@ -70,9 +76,9 @@ METHODDEF(void) post_process_2pass
*/
METHODDEF(void)
-start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
+start_pass_dpost(j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
{
- my_post_ptr post = (my_post_ptr) cinfo->post;
+ my_post_ptr post = (my_post_ptr)cinfo->post;
switch (pass_mode) {
case JBUF_PASS_THRU:
@@ -85,8 +91,8 @@ start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
*/
if (post->buffer == NULL) {
post->buffer = (*cinfo->mem->access_virt_sarray)
- ((j_common_ptr) cinfo, post->whole_image,
- (JDIMENSION) 0, post->strip_height, TRUE);
+ ((j_common_ptr)cinfo, post->whole_image,
+ (JDIMENSION)0, post->strip_height, TRUE);
}
} else {
/* For single-pass processing without color quantization,
@@ -123,13 +129,12 @@ start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
*/
METHODDEF(void)
-post_process_1pass (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
- JDIMENSION in_row_groups_avail,
- JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
- JDIMENSION out_rows_avail)
+post_process_1pass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)
{
- my_post_ptr post = (my_post_ptr) cinfo->post;
+ my_post_ptr post = (my_post_ptr)cinfo->post;
JDIMENSION num_rows, max_rows;
/* Fill the buffer, but not more than what we can dump out in one go. */
@@ -138,12 +143,13 @@ post_process_1pass (j_decompress_ptr cinfo,
if (max_rows > post->strip_height)
max_rows = post->strip_height;
num_rows = 0;
- (*cinfo->upsample->upsample) (cinfo,
- input_buf, in_row_group_ctr, in_row_groups_avail,
- post->buffer, &num_rows, max_rows);
+ (*cinfo->upsample->upsample) (cinfo, input_buf, in_row_group_ctr,
+ in_row_groups_avail, post->buffer, &num_rows,
+ max_rows);
/* Quantize and emit data. */
- (*cinfo->cquantize->color_quantize) (cinfo,
- post->buffer, output_buf + *out_row_ctr, (int) num_rows);
+ (*cinfo->cquantize->color_quantize) (cinfo, post->buffer,
+ output_buf + *out_row_ctr,
+ (int)num_rows);
*out_row_ctr += num_rows;
}
@@ -155,34 +161,33 @@ post_process_1pass (j_decompress_ptr cinfo,
*/
METHODDEF(void)
-post_process_prepass (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
- JDIMENSION in_row_groups_avail,
- JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
- JDIMENSION out_rows_avail)
+post_process_prepass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)
{
- my_post_ptr post = (my_post_ptr) cinfo->post;
+ my_post_ptr post = (my_post_ptr)cinfo->post;
JDIMENSION old_next_row, num_rows;
/* Reposition virtual buffer if at start of strip. */
if (post->next_row == 0) {
post->buffer = (*cinfo->mem->access_virt_sarray)
- ((j_common_ptr) cinfo, post->whole_image,
+ ((j_common_ptr)cinfo, post->whole_image,
post->starting_row, post->strip_height, TRUE);
}
/* Upsample some data (up to a strip height's worth). */
old_next_row = post->next_row;
- (*cinfo->upsample->upsample) (cinfo,
- input_buf, in_row_group_ctr, in_row_groups_avail,
- post->buffer, &post->next_row, post->strip_height);
+ (*cinfo->upsample->upsample) (cinfo, input_buf, in_row_group_ctr,
+ in_row_groups_avail, post->buffer,
+ &post->next_row, post->strip_height);
/* Allow quantizer to scan new data. No data is emitted, */
/* but we advance out_row_ctr so outer loop can tell when we're done. */
if (post->next_row > old_next_row) {
num_rows = post->next_row - old_next_row;
(*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row,
- (JSAMPARRAY) NULL, (int) num_rows);
+ (JSAMPARRAY)NULL, (int)num_rows);
*out_row_ctr += num_rows;
}
@@ -199,19 +204,18 @@ post_process_prepass (j_decompress_ptr cinfo,
*/
METHODDEF(void)
-post_process_2pass (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
- JDIMENSION in_row_groups_avail,
- JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
- JDIMENSION out_rows_avail)
+post_process_2pass(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)
{
- my_post_ptr post = (my_post_ptr) cinfo->post;
+ my_post_ptr post = (my_post_ptr)cinfo->post;
JDIMENSION num_rows, max_rows;
/* Reposition virtual buffer if at start of strip. */
if (post->next_row == 0) {
post->buffer = (*cinfo->mem->access_virt_sarray)
- ((j_common_ptr) cinfo, post->whole_image,
+ ((j_common_ptr)cinfo, post->whole_image,
post->starting_row, post->strip_height, FALSE);
}
@@ -226,9 +230,9 @@ post_process_2pass (j_decompress_ptr cinfo,
num_rows = max_rows;
/* Quantize and emit data. */
- (*cinfo->cquantize->color_quantize) (cinfo,
- post->buffer + post->next_row, output_buf + *out_row_ctr,
- (int) num_rows);
+ (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + post->next_row,
+ output_buf + *out_row_ctr,
+ (int)num_rows);
*out_row_ctr += num_rows;
/* Advance if we filled the strip. */
@@ -247,14 +251,14 @@ post_process_2pass (j_decompress_ptr cinfo,
*/
GLOBAL(void)
-jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
+jinit_d_post_controller(j_decompress_ptr cinfo, boolean need_full_buffer)
{
my_post_ptr post;
post = (my_post_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_post_controller));
- cinfo->post = (struct jpeg_d_post_controller *) post;
+ cinfo->post = (struct jpeg_d_post_controller *)post;
post->pub.start_pass = start_pass_dpost;
post->whole_image = NULL; /* flag for no virtual arrays */
post->buffer = NULL; /* flag for no strip buffer */
@@ -265,16 +269,16 @@ jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
* an efficient number of rows for upsampling to return.
* (In the presence of output rescaling, we might want to be smarter?)
*/
- post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor;
+ post->strip_height = (JDIMENSION)cinfo->max_v_samp_factor;
if (need_full_buffer) {
/* Two-pass color quantization: need full-image storage. */
/* We round up the number of rows to a multiple of the strip height. */
#ifdef QUANT_2PASS_SUPPORTED
post->whole_image = (*cinfo->mem->request_virt_sarray)
- ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+ ((j_common_ptr)cinfo, JPOOL_IMAGE, FALSE,
cinfo->output_width * cinfo->out_color_components,
- (JDIMENSION) jround_up((long) cinfo->output_height,
- (long) post->strip_height),
+ (JDIMENSION)jround_up((long)cinfo->output_height,
+ (long)post->strip_height),
post->strip_height);
#else
ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
@@ -282,7 +286,7 @@ jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
} else {
/* One-pass color quantization: just make a strip buffer. */
post->buffer = (*cinfo->mem->alloc_sarray)
- ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ ((j_common_ptr)cinfo, JPOOL_IMAGE,
cinfo->output_width * cinfo->out_color_components,
post->strip_height);
}
diff --git a/src/3rdparty/libjpeg/src/jdsample.c b/src/3rdparty/libjpeg/src/jdsample.c
index b1378e1512..52ee9af49b 100644
--- a/src/3rdparty/libjpeg/src/jdsample.c
+++ b/src/3rdparty/libjpeg/src/jdsample.c
@@ -36,9 +36,9 @@
*/
METHODDEF(void)
-start_pass_upsample (j_decompress_ptr cinfo)
+start_pass_upsample(j_decompress_ptr cinfo)
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
/* Mark the conversion buffer empty */
upsample->next_row_out = cinfo->max_v_samp_factor;
@@ -56,13 +56,12 @@ start_pass_upsample (j_decompress_ptr cinfo)
*/
METHODDEF(void)
-sep_upsample (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
- JDIMENSION in_row_groups_avail,
- JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
- JDIMENSION out_rows_avail)
+sep_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
int ci;
jpeg_component_info *compptr;
JDIMENSION num_rows;
@@ -84,7 +83,7 @@ sep_upsample (j_decompress_ptr cinfo,
/* Color-convert and emit rows */
/* How many we have in the buffer: */
- num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out);
+ num_rows = (JDIMENSION)(cinfo->max_v_samp_factor - upsample->next_row_out);
/* Not more than the distance to the end of the image. Need this test
* in case the image height is not a multiple of max_v_samp_factor:
*/
@@ -96,9 +95,8 @@ sep_upsample (j_decompress_ptr cinfo,
num_rows = out_rows_avail;
(*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf,
- (JDIMENSION) upsample->next_row_out,
- output_buf + *out_row_ctr,
- (int) num_rows);
+ (JDIMENSION)upsample->next_row_out,
+ output_buf + *out_row_ctr, (int)num_rows);
/* Adjust counts */
*out_row_ctr += num_rows;
@@ -124,8 +122,8 @@ sep_upsample (j_decompress_ptr cinfo,
*/
METHODDEF(void)
-fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
+fullsize_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
*output_data_ptr = input_data;
}
@@ -137,8 +135,8 @@ fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
*/
METHODDEF(void)
-noop_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
+noop_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
*output_data_ptr = NULL; /* safety check */
}
@@ -156,10 +154,10 @@ noop_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
*/
METHODDEF(void)
-int_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
+int_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
- my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
JSAMPARRAY output_data = *output_data_ptr;
register JSAMPROW inptr, outptr;
register JSAMPLE invalue;
@@ -185,8 +183,8 @@ int_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
}
/* Generate any additional output rows by duplicating the first one */
if (v_expand > 1) {
- jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
- v_expand-1, cinfo->output_width);
+ jcopy_sample_rows(output_data, outrow, output_data, outrow + 1,
+ v_expand - 1, cinfo->output_width);
}
inrow++;
outrow += v_expand;
@@ -200,8 +198,8 @@ int_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
*/
METHODDEF(void)
-h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
+h2v1_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
JSAMPARRAY output_data = *output_data_ptr;
register JSAMPROW inptr, outptr;
@@ -228,8 +226,8 @@ h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
*/
METHODDEF(void)
-h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
+h2v2_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
JSAMPARRAY output_data = *output_data_ptr;
register JSAMPROW inptr, outptr;
@@ -247,8 +245,8 @@ h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
*outptr++ = invalue;
*outptr++ = invalue;
}
- jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
- 1, cinfo->output_width);
+ jcopy_sample_rows(output_data, outrow, output_data, outrow + 1, 1,
+ cinfo->output_width);
inrow++;
outrow += 2;
}
@@ -271,8 +269,8 @@ h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
*/
METHODDEF(void)
-h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
+h2v1_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
JSAMPARRAY output_data = *output_data_ptr;
register JSAMPROW inptr, outptr;
@@ -285,20 +283,20 @@ h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
outptr = output_data[inrow];
/* Special case for first column */
invalue = GETJSAMPLE(*inptr++);
- *outptr++ = (JSAMPLE) invalue;
- *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2);
+ *outptr++ = (JSAMPLE)invalue;
+ *outptr++ = (JSAMPLE)((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2);
for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) {
/* General case: 3/4 * nearer pixel + 1/4 * further pixel */
invalue = GETJSAMPLE(*inptr++) * 3;
- *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2);
- *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2);
+ *outptr++ = (JSAMPLE)((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2);
+ *outptr++ = (JSAMPLE)((invalue + GETJSAMPLE(*inptr) + 2) >> 2);
}
/* Special case for last column */
invalue = GETJSAMPLE(*inptr);
- *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2);
- *outptr++ = (JSAMPLE) invalue;
+ *outptr++ = (JSAMPLE)((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2);
+ *outptr++ = (JSAMPLE)invalue;
}
}
@@ -311,8 +309,8 @@ h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
*/
METHODDEF(void)
-h1v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
+h1v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
JSAMPARRAY output_data = *output_data_ptr;
JSAMPROW inptr0, inptr1, outptr;
@@ -330,14 +328,14 @@ h1v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* inptr0 points to nearest input row, inptr1 points to next nearest */
inptr0 = input_data[inrow];
if (v == 0) /* next nearest is row above */
- inptr1 = input_data[inrow-1];
+ inptr1 = input_data[inrow - 1];
else /* next nearest is row below */
- inptr1 = input_data[inrow+1];
+ inptr1 = input_data[inrow + 1];
outptr = output_data[outrow++];
- for(colctr = 0; colctr < compptr->downsampled_width; colctr++) {
+ for (colctr = 0; colctr < compptr->downsampled_width; colctr++) {
thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
- *outptr++ = (JSAMPLE) ((thiscolsum + 1) >> 2);
+ *outptr++ = (JSAMPLE)((thiscolsum + 1) >> 2);
}
}
inrow++;
@@ -354,8 +352,8 @@ h1v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
*/
METHODDEF(void)
-h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
+h2v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
JSAMPARRAY output_data = *output_data_ptr;
register JSAMPROW inptr0, inptr1, outptr;
@@ -373,30 +371,30 @@ h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* inptr0 points to nearest input row, inptr1 points to next nearest */
inptr0 = input_data[inrow];
if (v == 0) /* next nearest is row above */
- inptr1 = input_data[inrow-1];
+ inptr1 = input_data[inrow - 1];
else /* next nearest is row below */
- inptr1 = input_data[inrow+1];
+ inptr1 = input_data[inrow + 1];
outptr = output_data[outrow++];
/* Special case for first column */
thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
- *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4);
- *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4);
- lastcolsum = thiscolsum; thiscolsum = nextcolsum;
+ *outptr++ = (JSAMPLE)((thiscolsum * 4 + 8) >> 4);
+ *outptr++ = (JSAMPLE)((thiscolsum * 3 + nextcolsum + 7) >> 4);
+ lastcolsum = thiscolsum; thiscolsum = nextcolsum;
for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) {
/* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */
/* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */
nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
- *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
- *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4);
- lastcolsum = thiscolsum; thiscolsum = nextcolsum;
+ *outptr++ = (JSAMPLE)((thiscolsum * 3 + lastcolsum + 8) >> 4);
+ *outptr++ = (JSAMPLE)((thiscolsum * 3 + nextcolsum + 7) >> 4);
+ lastcolsum = thiscolsum; thiscolsum = nextcolsum;
}
/* Special case for last column */
- *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
- *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4);
+ *outptr++ = (JSAMPLE)((thiscolsum * 3 + lastcolsum + 8) >> 4);
+ *outptr++ = (JSAMPLE)((thiscolsum * 4 + 7) >> 4);
}
inrow++;
}
@@ -408,7 +406,7 @@ h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
*/
GLOBAL(void)
-jinit_upsampler (j_decompress_ptr cinfo)
+jinit_upsampler(j_decompress_ptr cinfo)
{
my_upsample_ptr upsample;
int ci;
@@ -418,14 +416,14 @@ jinit_upsampler (j_decompress_ptr cinfo)
if (!cinfo->master->jinit_upsampler_no_alloc) {
upsample = (my_upsample_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_upsampler));
- cinfo->upsample = (struct jpeg_upsampler *) upsample;
+ cinfo->upsample = (struct jpeg_upsampler *)upsample;
upsample->pub.start_pass = start_pass_upsample;
upsample->pub.upsample = sep_upsample;
upsample->pub.need_context_rows = FALSE; /* until we find out differently */
} else
- upsample = (my_upsample_ptr) cinfo->upsample;
+ upsample = (my_upsample_ptr)cinfo->upsample;
if (cinfo->CCIR601_sampling) /* this isn't supported */
ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
@@ -451,7 +449,7 @@ jinit_upsampler (j_decompress_ptr cinfo)
v_out_group = cinfo->max_v_samp_factor;
upsample->rowgroup_height[ci] = v_in_group; /* save for use later */
need_buffer = TRUE;
- if (! compptr->component_needed) {
+ if (!compptr->component_needed) {
/* Don't bother to upsample an uninteresting component. */
upsample->methods[ci] = noop_upsample;
need_buffer = FALSE;
@@ -459,8 +457,7 @@ jinit_upsampler (j_decompress_ptr cinfo)
/* Fullsize components can be processed without any work. */
upsample->methods[ci] = fullsize_upsample;
need_buffer = FALSE;
- } else if (h_in_group * 2 == h_out_group &&
- v_in_group == v_out_group) {
+ } else if (h_in_group * 2 == h_out_group && v_in_group == v_out_group) {
/* Special cases for 2h1v upsampling */
if (do_fancy && compptr->downsampled_width > 2) {
if (jsimd_can_h2v1_fancy_upsample())
@@ -502,16 +499,16 @@ jinit_upsampler (j_decompress_ptr cinfo)
else
#endif
upsample->methods[ci] = int_upsample;
- upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group);
- upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group);
+ upsample->h_expand[ci] = (UINT8)(h_out_group / h_in_group);
+ upsample->v_expand[ci] = (UINT8)(v_out_group / v_in_group);
} else
ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
if (need_buffer && !cinfo->master->jinit_upsampler_no_alloc) {
upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray)
- ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (JDIMENSION) jround_up((long) cinfo->output_width,
- (long) cinfo->max_h_samp_factor),
- (JDIMENSION) cinfo->max_v_samp_factor);
+ ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (JDIMENSION)jround_up((long)cinfo->output_width,
+ (long)cinfo->max_h_samp_factor),
+ (JDIMENSION)cinfo->max_v_samp_factor);
}
}
}
diff --git a/src/3rdparty/libjpeg/src/jdtrans.c b/src/3rdparty/libjpeg/src/jdtrans.c
index cfc85dd24c..56713efe64 100644
--- a/src/3rdparty/libjpeg/src/jdtrans.c
+++ b/src/3rdparty/libjpeg/src/jdtrans.c
@@ -19,7 +19,7 @@
/* Forward declarations */
-LOCAL(void) transdecode_master_selection (j_decompress_ptr cinfo);
+LOCAL(void) transdecode_master_selection(j_decompress_ptr cinfo);
/*
@@ -45,7 +45,7 @@ LOCAL(void) transdecode_master_selection (j_decompress_ptr cinfo);
*/
GLOBAL(jvirt_barray_ptr *)
-jpeg_read_coefficients (j_decompress_ptr cinfo)
+jpeg_read_coefficients(j_decompress_ptr cinfo)
{
if (cinfo->global_state == DSTATE_READY) {
/* First call: initialize active modules */
@@ -58,7 +58,7 @@ jpeg_read_coefficients (j_decompress_ptr cinfo)
int retcode;
/* Call progress monitor hook if present */
if (cinfo->progress != NULL)
- (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ (*cinfo->progress->progress_monitor) ((j_common_ptr)cinfo);
/* Absorb some more input */
retcode = (*cinfo->inputctl->consume_input) (cinfo);
if (retcode == JPEG_SUSPENDED)
@@ -70,7 +70,7 @@ jpeg_read_coefficients (j_decompress_ptr cinfo)
(retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) {
if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) {
/* startup underestimated number of scans; ratchet up one scan */
- cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows;
+ cinfo->progress->pass_limit += (long)cinfo->total_iMCU_rows;
}
}
}
@@ -97,7 +97,7 @@ jpeg_read_coefficients (j_decompress_ptr cinfo)
*/
LOCAL(void)
-transdecode_master_selection (j_decompress_ptr cinfo)
+transdecode_master_selection(j_decompress_ptr cinfo)
{
/* This is effectively a buffered-image operation. */
cinfo->buffered_image = TRUE;
@@ -129,7 +129,7 @@ transdecode_master_selection (j_decompress_ptr cinfo)
jinit_d_coef_controller(cinfo, TRUE);
/* We can now tell the memory manager to allocate virtual arrays. */
- (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
+ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr)cinfo);
/* Initialize input side of decompressor to consume first scan. */
(*cinfo->inputctl->start_input_pass) (cinfo);
@@ -148,7 +148,7 @@ transdecode_master_selection (j_decompress_ptr cinfo)
nscans = 1;
}
cinfo->progress->pass_counter = 0L;
- cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans;
+ cinfo->progress->pass_limit = (long)cinfo->total_iMCU_rows * nscans;
cinfo->progress->completed_passes = 0;
cinfo->progress->total_passes = 1;
}
diff --git a/src/3rdparty/libjpeg/src/jerror.c b/src/3rdparty/libjpeg/src/jerror.c
index c31acd9ef0..936c4f5d80 100644
--- a/src/3rdparty/libjpeg/src/jerror.c
+++ b/src/3rdparty/libjpeg/src/jerror.c
@@ -44,7 +44,7 @@
* want to refer to it directly.
*/
-#define JMESSAGE(code,string) string ,
+#define JMESSAGE(code, string) string,
const char * const jpeg_std_message_table[] = {
#include "jerror.h"
@@ -66,7 +66,7 @@ const char * const jpeg_std_message_table[] = {
*/
METHODDEF(void)
-error_exit (j_common_ptr cinfo)
+error_exit(j_common_ptr cinfo)
{
/* Always display the message */
(*cinfo->err->output_message) (cinfo);
@@ -94,7 +94,7 @@ error_exit (j_common_ptr cinfo)
*/
METHODDEF(void)
-output_message (j_common_ptr cinfo)
+output_message(j_common_ptr cinfo)
{
char buffer[JMSG_LENGTH_MAX];
@@ -124,7 +124,7 @@ output_message (j_common_ptr cinfo)
*/
METHODDEF(void)
-emit_message (j_common_ptr cinfo, int msg_level)
+emit_message(j_common_ptr cinfo, int msg_level)
{
struct jpeg_error_mgr *err = cinfo->err;
@@ -153,7 +153,7 @@ emit_message (j_common_ptr cinfo, int msg_level)
*/
METHODDEF(void)
-format_message (j_common_ptr cinfo, char *buffer)
+format_message(j_common_ptr cinfo, char *buffer)
{
struct jpeg_error_mgr *err = cinfo->err;
int msg_code = err->msg_code;
@@ -208,7 +208,7 @@ format_message (j_common_ptr cinfo, char *buffer)
*/
METHODDEF(void)
-reset_error_mgr (j_common_ptr cinfo)
+reset_error_mgr(j_common_ptr cinfo)
{
cinfo->err->num_warnings = 0;
/* trace_level is not reset since it is an application-supplied parameter */
@@ -227,7 +227,7 @@ reset_error_mgr (j_common_ptr cinfo)
*/
GLOBAL(struct jpeg_error_mgr *)
-jpeg_std_error (struct jpeg_error_mgr *err)
+jpeg_std_error(struct jpeg_error_mgr *err)
{
err->error_exit = error_exit;
err->emit_message = emit_message;
@@ -241,7 +241,7 @@ jpeg_std_error (struct jpeg_error_mgr *err)
/* Initialize message table pointers */
err->jpeg_message_table = jpeg_std_message_table;
- err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1;
+ err->last_jpeg_message = (int)JMSG_LASTMSGCODE - 1;
err->addon_message_table = NULL;
err->first_addon_message = 0; /* for safety */
diff --git a/src/3rdparty/libjpeg/src/jerror.h b/src/3rdparty/libjpeg/src/jerror.h
index 11a07cb5d0..933a3690fd 100644
--- a/src/3rdparty/libjpeg/src/jerror.h
+++ b/src/3rdparty/libjpeg/src/jerror.h
@@ -5,7 +5,7 @@
* Copyright (C) 1994-1997, Thomas G. Lane.
* Modified 1997-2009 by Guido Vollbeding.
* libjpeg-turbo Modifications:
- * Copyright (C) 2014, D. R. Commander.
+ * Copyright (C) 2014, 2017, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -28,7 +28,7 @@
#define JMAKE_ENUM_LIST
#else
/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */
-#define JMESSAGE(code,string)
+#define JMESSAGE(code, string)
#endif /* JERROR_H */
#endif /* JMESSAGE */
@@ -36,7 +36,7 @@
typedef enum {
-#define JMESSAGE(code,string) code ,
+#define JMESSAGE(code, string) code,
#endif /* JMAKE_ENUM_LIST */
@@ -44,8 +44,7 @@ JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */
/* For maintenance convenience, list is alphabetical by message code name */
#if JPEG_LIB_VERSION < 70
-JMESSAGE(JERR_ARITH_NOTIMPL,
- "Sorry, arithmetic coding is not implemented")
+JMESSAGE(JERR_ARITH_NOTIMPL, "Sorry, arithmetic coding is not implemented")
#endif
JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix")
JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix")
@@ -154,8 +153,7 @@ JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d")
JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d")
JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE,
"Warning: thumbnail image size does not match data length %u")
-JMESSAGE(JTRC_JFIF_EXTENSION,
- "JFIF extension marker: type 0x%02x, length %u")
+JMESSAGE(JTRC_JFIF_EXTENSION, "JFIF extension marker: type 0x%02x, length %u")
JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image")
JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u")
JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x")
@@ -208,6 +206,7 @@ JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined")
JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code")
#endif
#endif
+JMESSAGE(JWRN_BOGUS_ICC, "Corrupt JPEG data: bad ICC marker")
#ifdef JMAKE_ENUM_LIST
@@ -228,90 +227,90 @@ JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code")
/* The first parameter is either type of cinfo pointer */
/* Fatal errors (print message and exit) */
-#define ERREXIT(cinfo,code) \
+#define ERREXIT(cinfo, code) \
((cinfo)->err->msg_code = (code), \
- (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
-#define ERREXIT1(cinfo,code,p1) \
+ (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
+#define ERREXIT1(cinfo, code, p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
- (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
-#define ERREXIT2(cinfo,code,p1,p2) \
+ (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
+#define ERREXIT2(cinfo, code, p1, p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
- (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
-#define ERREXIT3(cinfo,code,p1,p2,p3) \
+ (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
+#define ERREXIT3(cinfo, code, p1, p2, p3) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(cinfo)->err->msg_parm.i[2] = (p3), \
- (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
-#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \
+ (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
+#define ERREXIT4(cinfo, code, p1, p2, p3, p4) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(cinfo)->err->msg_parm.i[2] = (p3), \
(cinfo)->err->msg_parm.i[3] = (p4), \
- (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
-#define ERREXITS(cinfo,code,str) \
+ (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
+#define ERREXITS(cinfo, code, str) \
((cinfo)->err->msg_code = (code), \
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
- (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+ (*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
#define MAKESTMT(stuff) do { stuff } while (0)
/* Nonfatal errors (we can keep going, but the data is probably corrupt) */
-#define WARNMS(cinfo,code) \
+#define WARNMS(cinfo, code) \
((cinfo)->err->msg_code = (code), \
- (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
-#define WARNMS1(cinfo,code,p1) \
+ (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1))
+#define WARNMS1(cinfo, code, p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
- (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
-#define WARNMS2(cinfo,code,p1,p2) \
+ (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1))
+#define WARNMS2(cinfo, code, p1, p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
- (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
+ (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1))
/* Informational/debugging messages */
-#define TRACEMS(cinfo,lvl,code) \
+#define TRACEMS(cinfo, lvl, code) \
((cinfo)->err->msg_code = (code), \
- (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
-#define TRACEMS1(cinfo,lvl,code,p1) \
+ (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)))
+#define TRACEMS1(cinfo, lvl, code, p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
- (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
-#define TRACEMS2(cinfo,lvl,code,p1,p2) \
+ (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)))
+#define TRACEMS2(cinfo, lvl, code, p1, p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
- (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
-#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \
- MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
- _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \
+ (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)))
+#define TRACEMS3(cinfo, lvl, code, p1, p2, p3) \
+ MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \
+ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \
(cinfo)->err->msg_code = (code); \
- (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
-#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \
- MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
- _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
+ (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); )
+#define TRACEMS4(cinfo, lvl, code, p1, p2, p3, p4) \
+ MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \
+ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
(cinfo)->err->msg_code = (code); \
- (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
-#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \
- MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
- _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
+ (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); )
+#define TRACEMS5(cinfo, lvl, code, p1, p2, p3, p4, p5) \
+ MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \
+ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
_mp[4] = (p5); \
(cinfo)->err->msg_code = (code); \
- (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
-#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \
- MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
- _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
- _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \
+ (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); )
+#define TRACEMS8(cinfo, lvl, code, p1, p2, p3, p4, p5, p6, p7, p8) \
+ MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \
+ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
+ _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \
(cinfo)->err->msg_code = (code); \
- (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
-#define TRACEMSS(cinfo,lvl,code,str) \
+ (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); )
+#define TRACEMSS(cinfo, lvl, code, str) \
((cinfo)->err->msg_code = (code), \
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
- (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
+ (*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)))
#endif /* JERROR_H */
diff --git a/src/3rdparty/libjpeg/src/jfdctflt.c b/src/3rdparty/libjpeg/src/jfdctflt.c
index b3da3ebda8..ab6f6d0825 100644
--- a/src/3rdparty/libjpeg/src/jfdctflt.c
+++ b/src/3rdparty/libjpeg/src/jfdctflt.c
@@ -57,7 +57,7 @@
*/
GLOBAL(void)
-jpeg_fdct_float (FAST_FLOAT *data)
+jpeg_fdct_float(FAST_FLOAT *data)
{
FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
FAST_FLOAT tmp10, tmp11, tmp12, tmp13;
@@ -68,7 +68,7 @@ jpeg_fdct_float (FAST_FLOAT *data)
/* Pass 1: process rows. */
dataptr = data;
- for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ for (ctr = DCTSIZE - 1; ctr >= 0; ctr--) {
tmp0 = dataptr[0] + dataptr[7];
tmp7 = dataptr[0] - dataptr[7];
tmp1 = dataptr[1] + dataptr[6];
@@ -88,7 +88,7 @@ jpeg_fdct_float (FAST_FLOAT *data)
dataptr[0] = tmp10 + tmp11; /* phase 3 */
dataptr[4] = tmp10 - tmp11;
- z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */
+ z1 = (tmp12 + tmp13) * ((FAST_FLOAT)0.707106781); /* c4 */
dataptr[2] = tmp13 + z1; /* phase 5 */
dataptr[6] = tmp13 - z1;
@@ -99,10 +99,10 @@ jpeg_fdct_float (FAST_FLOAT *data)
tmp12 = tmp6 + tmp7;
/* The rotator is modified from fig 4-8 to avoid extra negations. */
- z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */
- z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */
- z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */
- z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */
+ z5 = (tmp10 - tmp12) * ((FAST_FLOAT)0.382683433); /* c6 */
+ z2 = ((FAST_FLOAT)0.541196100) * tmp10 + z5; /* c2-c6 */
+ z4 = ((FAST_FLOAT)1.306562965) * tmp12 + z5; /* c2+c6 */
+ z3 = tmp11 * ((FAST_FLOAT)0.707106781); /* c4 */
z11 = tmp7 + z3; /* phase 5 */
z13 = tmp7 - z3;
@@ -118,15 +118,15 @@ jpeg_fdct_float (FAST_FLOAT *data)
/* Pass 2: process columns. */
dataptr = data;
- for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
- tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
- tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
- tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
- tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
- tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
- tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
- tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
- tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
+ for (ctr = DCTSIZE - 1; ctr >= 0; ctr--) {
+ tmp0 = dataptr[DCTSIZE * 0] + dataptr[DCTSIZE * 7];
+ tmp7 = dataptr[DCTSIZE * 0] - dataptr[DCTSIZE * 7];
+ tmp1 = dataptr[DCTSIZE * 1] + dataptr[DCTSIZE * 6];
+ tmp6 = dataptr[DCTSIZE * 1] - dataptr[DCTSIZE * 6];
+ tmp2 = dataptr[DCTSIZE * 2] + dataptr[DCTSIZE * 5];
+ tmp5 = dataptr[DCTSIZE * 2] - dataptr[DCTSIZE * 5];
+ tmp3 = dataptr[DCTSIZE * 3] + dataptr[DCTSIZE * 4];
+ tmp4 = dataptr[DCTSIZE * 3] - dataptr[DCTSIZE * 4];
/* Even part */
@@ -135,12 +135,12 @@ jpeg_fdct_float (FAST_FLOAT *data)
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
- dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */
- dataptr[DCTSIZE*4] = tmp10 - tmp11;
+ dataptr[DCTSIZE * 0] = tmp10 + tmp11; /* phase 3 */
+ dataptr[DCTSIZE * 4] = tmp10 - tmp11;
- z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */
- dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */
- dataptr[DCTSIZE*6] = tmp13 - z1;
+ z1 = (tmp12 + tmp13) * ((FAST_FLOAT)0.707106781); /* c4 */
+ dataptr[DCTSIZE * 2] = tmp13 + z1; /* phase 5 */
+ dataptr[DCTSIZE * 6] = tmp13 - z1;
/* Odd part */
@@ -149,18 +149,18 @@ jpeg_fdct_float (FAST_FLOAT *data)
tmp12 = tmp6 + tmp7;
/* The rotator is modified from fig 4-8 to avoid extra negations. */
- z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */
- z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */
- z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */
- z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */
+ z5 = (tmp10 - tmp12) * ((FAST_FLOAT)0.382683433); /* c6 */
+ z2 = ((FAST_FLOAT)0.541196100) * tmp10 + z5; /* c2-c6 */
+ z4 = ((FAST_FLOAT)1.306562965) * tmp12 + z5; /* c2+c6 */
+ z3 = tmp11 * ((FAST_FLOAT)0.707106781); /* c4 */
z11 = tmp7 + z3; /* phase 5 */
z13 = tmp7 - z3;
- dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */
- dataptr[DCTSIZE*3] = z13 - z2;
- dataptr[DCTSIZE*1] = z11 + z4;
- dataptr[DCTSIZE*7] = z11 - z4;
+ dataptr[DCTSIZE * 5] = z13 + z2; /* phase 6 */
+ dataptr[DCTSIZE * 3] = z13 - z2;
+ dataptr[DCTSIZE * 1] = z11 + z4;
+ dataptr[DCTSIZE * 7] = z11 - z4;
dataptr++; /* advance pointer to next column */
}
diff --git a/src/3rdparty/libjpeg/src/jfdctfst.c b/src/3rdparty/libjpeg/src/jfdctfst.c
index 5cd83a7b8e..4c9ce0de8f 100644
--- a/src/3rdparty/libjpeg/src/jfdctfst.c
+++ b/src/3rdparty/libjpeg/src/jfdctfst.c
@@ -79,10 +79,10 @@
*/
#if CONST_BITS == 8
-#define FIX_0_382683433 ((JLONG) 98) /* FIX(0.382683433) */
-#define FIX_0_541196100 ((JLONG) 139) /* FIX(0.541196100) */
-#define FIX_0_707106781 ((JLONG) 181) /* FIX(0.707106781) */
-#define FIX_1_306562965 ((JLONG) 334) /* FIX(1.306562965) */
+#define FIX_0_382683433 ((JLONG)98) /* FIX(0.382683433) */
+#define FIX_0_541196100 ((JLONG)139) /* FIX(0.541196100) */
+#define FIX_0_707106781 ((JLONG)181) /* FIX(0.707106781) */
+#define FIX_1_306562965 ((JLONG)334) /* FIX(1.306562965) */
#else
#define FIX_0_382683433 FIX(0.382683433)
#define FIX_0_541196100 FIX(0.541196100)
@@ -98,7 +98,7 @@
#ifndef USE_ACCURATE_ROUNDING
#undef DESCALE
-#define DESCALE(x,n) RIGHT_SHIFT(x, n)
+#define DESCALE(x, n) RIGHT_SHIFT(x, n)
#endif
@@ -106,7 +106,7 @@
* descale to yield a DCTELEM result.
*/
-#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS))
+#define MULTIPLY(var, const) ((DCTELEM)DESCALE((var) * (const), CONST_BITS))
/*
@@ -114,7 +114,7 @@
*/
GLOBAL(void)
-jpeg_fdct_ifast (DCTELEM *data)
+jpeg_fdct_ifast(DCTELEM *data)
{
DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
DCTELEM tmp10, tmp11, tmp12, tmp13;
@@ -126,7 +126,7 @@ jpeg_fdct_ifast (DCTELEM *data)
/* Pass 1: process rows. */
dataptr = data;
- for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ for (ctr = DCTSIZE - 1; ctr >= 0; ctr--) {
tmp0 = dataptr[0] + dataptr[7];
tmp7 = dataptr[0] - dataptr[7];
tmp1 = dataptr[1] + dataptr[6];
@@ -176,15 +176,15 @@ jpeg_fdct_ifast (DCTELEM *data)
/* Pass 2: process columns. */
dataptr = data;
- for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
- tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
- tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
- tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
- tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
- tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
- tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
- tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
- tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
+ for (ctr = DCTSIZE - 1; ctr >= 0; ctr--) {
+ tmp0 = dataptr[DCTSIZE * 0] + dataptr[DCTSIZE * 7];
+ tmp7 = dataptr[DCTSIZE * 0] - dataptr[DCTSIZE * 7];
+ tmp1 = dataptr[DCTSIZE * 1] + dataptr[DCTSIZE * 6];
+ tmp6 = dataptr[DCTSIZE * 1] - dataptr[DCTSIZE * 6];
+ tmp2 = dataptr[DCTSIZE * 2] + dataptr[DCTSIZE * 5];
+ tmp5 = dataptr[DCTSIZE * 2] - dataptr[DCTSIZE * 5];
+ tmp3 = dataptr[DCTSIZE * 3] + dataptr[DCTSIZE * 4];
+ tmp4 = dataptr[DCTSIZE * 3] - dataptr[DCTSIZE * 4];
/* Even part */
@@ -193,12 +193,12 @@ jpeg_fdct_ifast (DCTELEM *data)
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
- dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */
- dataptr[DCTSIZE*4] = tmp10 - tmp11;
+ dataptr[DCTSIZE * 0] = tmp10 + tmp11; /* phase 3 */
+ dataptr[DCTSIZE * 4] = tmp10 - tmp11;
z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */
- dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */
- dataptr[DCTSIZE*6] = tmp13 - z1;
+ dataptr[DCTSIZE * 2] = tmp13 + z1; /* phase 5 */
+ dataptr[DCTSIZE * 6] = tmp13 - z1;
/* Odd part */
@@ -215,10 +215,10 @@ jpeg_fdct_ifast (DCTELEM *data)
z11 = tmp7 + z3; /* phase 5 */
z13 = tmp7 - z3;
- dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */
- dataptr[DCTSIZE*3] = z13 - z2;
- dataptr[DCTSIZE*1] = z11 + z4;
- dataptr[DCTSIZE*7] = z11 - z4;
+ dataptr[DCTSIZE * 5] = z13 + z2; /* phase 6 */
+ dataptr[DCTSIZE * 3] = z13 - z2;
+ dataptr[DCTSIZE * 1] = z11 + z4;
+ dataptr[DCTSIZE * 7] = z11 - z4;
dataptr++; /* advance pointer to next column */
}
diff --git a/src/3rdparty/libjpeg/src/jfdctint.c b/src/3rdparty/libjpeg/src/jfdctint.c
index 169bb942ce..c0391a92be 100644
--- a/src/3rdparty/libjpeg/src/jfdctint.c
+++ b/src/3rdparty/libjpeg/src/jfdctint.c
@@ -93,18 +93,18 @@
*/
#if CONST_BITS == 13
-#define FIX_0_298631336 ((JLONG) 2446) /* FIX(0.298631336) */
-#define FIX_0_390180644 ((JLONG) 3196) /* FIX(0.390180644) */
-#define FIX_0_541196100 ((JLONG) 4433) /* FIX(0.541196100) */
-#define FIX_0_765366865 ((JLONG) 6270) /* FIX(0.765366865) */
-#define FIX_0_899976223 ((JLONG) 7373) /* FIX(0.899976223) */
-#define FIX_1_175875602 ((JLONG) 9633) /* FIX(1.175875602) */
-#define FIX_1_501321110 ((JLONG) 12299) /* FIX(1.501321110) */
-#define FIX_1_847759065 ((JLONG) 15137) /* FIX(1.847759065) */
-#define FIX_1_961570560 ((JLONG) 16069) /* FIX(1.961570560) */
-#define FIX_2_053119869 ((JLONG) 16819) /* FIX(2.053119869) */
-#define FIX_2_562915447 ((JLONG) 20995) /* FIX(2.562915447) */
-#define FIX_3_072711026 ((JLONG) 25172) /* FIX(3.072711026) */
+#define FIX_0_298631336 ((JLONG)2446) /* FIX(0.298631336) */
+#define FIX_0_390180644 ((JLONG)3196) /* FIX(0.390180644) */
+#define FIX_0_541196100 ((JLONG)4433) /* FIX(0.541196100) */
+#define FIX_0_765366865 ((JLONG)6270) /* FIX(0.765366865) */
+#define FIX_0_899976223 ((JLONG)7373) /* FIX(0.899976223) */
+#define FIX_1_175875602 ((JLONG)9633) /* FIX(1.175875602) */
+#define FIX_1_501321110 ((JLONG)12299) /* FIX(1.501321110) */
+#define FIX_1_847759065 ((JLONG)15137) /* FIX(1.847759065) */
+#define FIX_1_961570560 ((JLONG)16069) /* FIX(1.961570560) */
+#define FIX_2_053119869 ((JLONG)16819) /* FIX(2.053119869) */
+#define FIX_2_562915447 ((JLONG)20995) /* FIX(2.562915447) */
+#define FIX_3_072711026 ((JLONG)25172) /* FIX(3.072711026) */
#else
#define FIX_0_298631336 FIX(0.298631336)
#define FIX_0_390180644 FIX(0.390180644)
@@ -129,9 +129,9 @@
*/
#if BITS_IN_JSAMPLE == 8
-#define MULTIPLY(var,const) MULTIPLY16C16(var,const)
+#define MULTIPLY(var, const) MULTIPLY16C16(var, const)
#else
-#define MULTIPLY(var,const) ((var) * (const))
+#define MULTIPLY(var, const) ((var) * (const))
#endif
@@ -140,7 +140,7 @@
*/
GLOBAL(void)
-jpeg_fdct_islow (DCTELEM *data)
+jpeg_fdct_islow(DCTELEM *data)
{
JLONG tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
JLONG tmp10, tmp11, tmp12, tmp13;
@@ -154,7 +154,7 @@ jpeg_fdct_islow (DCTELEM *data)
/* furthermore, we scale the results by 2**PASS1_BITS. */
dataptr = data;
- for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ for (ctr = DCTSIZE - 1; ctr >= 0; ctr--) {
tmp0 = dataptr[0] + dataptr[7];
tmp7 = dataptr[0] - dataptr[7];
tmp1 = dataptr[1] + dataptr[6];
@@ -173,14 +173,14 @@ jpeg_fdct_islow (DCTELEM *data)
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
- dataptr[0] = (DCTELEM) LEFT_SHIFT(tmp10 + tmp11, PASS1_BITS);
- dataptr[4] = (DCTELEM) LEFT_SHIFT(tmp10 - tmp11, PASS1_BITS);
+ dataptr[0] = (DCTELEM)LEFT_SHIFT(tmp10 + tmp11, PASS1_BITS);
+ dataptr[4] = (DCTELEM)LEFT_SHIFT(tmp10 - tmp11, PASS1_BITS);
z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
- dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865),
- CONST_BITS-PASS1_BITS);
- dataptr[6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065),
- CONST_BITS-PASS1_BITS);
+ dataptr[2] = (DCTELEM)DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865),
+ CONST_BITS - PASS1_BITS);
+ dataptr[6] = (DCTELEM)DESCALE(z1 + MULTIPLY(tmp12, -FIX_1_847759065),
+ CONST_BITS - PASS1_BITS);
/* Odd part per figure 8 --- note paper omits factor of sqrt(2).
* cK represents cos(K*pi/16).
@@ -197,18 +197,18 @@ jpeg_fdct_islow (DCTELEM *data)
tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
- z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
- z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
- z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
- z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+ z1 = MULTIPLY(z1, -FIX_0_899976223); /* sqrt(2) * ( c7-c3) */
+ z2 = MULTIPLY(z2, -FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ z3 = MULTIPLY(z3, -FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z4 = MULTIPLY(z4, -FIX_0_390180644); /* sqrt(2) * ( c5-c3) */
z3 += z5;
z4 += z5;
- dataptr[7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS);
- dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS);
- dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS);
- dataptr[1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS);
+ dataptr[7] = (DCTELEM)DESCALE(tmp4 + z1 + z3, CONST_BITS - PASS1_BITS);
+ dataptr[5] = (DCTELEM)DESCALE(tmp5 + z2 + z4, CONST_BITS - PASS1_BITS);
+ dataptr[3] = (DCTELEM)DESCALE(tmp6 + z2 + z3, CONST_BITS - PASS1_BITS);
+ dataptr[1] = (DCTELEM)DESCALE(tmp7 + z1 + z4, CONST_BITS - PASS1_BITS);
dataptr += DCTSIZE; /* advance pointer to next row */
}
@@ -219,15 +219,15 @@ jpeg_fdct_islow (DCTELEM *data)
*/
dataptr = data;
- for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
- tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
- tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
- tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
- tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
- tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
- tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
- tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
- tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
+ for (ctr = DCTSIZE - 1; ctr >= 0; ctr--) {
+ tmp0 = dataptr[DCTSIZE * 0] + dataptr[DCTSIZE * 7];
+ tmp7 = dataptr[DCTSIZE * 0] - dataptr[DCTSIZE * 7];
+ tmp1 = dataptr[DCTSIZE * 1] + dataptr[DCTSIZE * 6];
+ tmp6 = dataptr[DCTSIZE * 1] - dataptr[DCTSIZE * 6];
+ tmp2 = dataptr[DCTSIZE * 2] + dataptr[DCTSIZE * 5];
+ tmp5 = dataptr[DCTSIZE * 2] - dataptr[DCTSIZE * 5];
+ tmp3 = dataptr[DCTSIZE * 3] + dataptr[DCTSIZE * 4];
+ tmp4 = dataptr[DCTSIZE * 3] - dataptr[DCTSIZE * 4];
/* Even part per LL&M figure 1 --- note that published figure is faulty;
* rotator "sqrt(2)*c1" should be "sqrt(2)*c6".
@@ -238,14 +238,16 @@ jpeg_fdct_islow (DCTELEM *data)
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
- dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS);
- dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS);
+ dataptr[DCTSIZE * 0] = (DCTELEM)DESCALE(tmp10 + tmp11, PASS1_BITS);
+ dataptr[DCTSIZE * 4] = (DCTELEM)DESCALE(tmp10 - tmp11, PASS1_BITS);
z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
- dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865),
- CONST_BITS+PASS1_BITS);
- dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065),
- CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE * 2] =
+ (DCTELEM)DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865),
+ CONST_BITS + PASS1_BITS);
+ dataptr[DCTSIZE * 6] =
+ (DCTELEM)DESCALE(z1 + MULTIPLY(tmp12, -FIX_1_847759065),
+ CONST_BITS + PASS1_BITS);
/* Odd part per figure 8 --- note paper omits factor of sqrt(2).
* cK represents cos(K*pi/16).
@@ -262,22 +264,22 @@ jpeg_fdct_islow (DCTELEM *data)
tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
- z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
- z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
- z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
- z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+ z1 = MULTIPLY(z1, -FIX_0_899976223); /* sqrt(2) * ( c7-c3) */
+ z2 = MULTIPLY(z2, -FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ z3 = MULTIPLY(z3, -FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z4 = MULTIPLY(z4, -FIX_0_390180644); /* sqrt(2) * ( c5-c3) */
z3 += z5;
z4 += z5;
- dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3,
- CONST_BITS+PASS1_BITS);
- dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4,
- CONST_BITS+PASS1_BITS);
- dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3,
- CONST_BITS+PASS1_BITS);
- dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4,
- CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE * 7] = (DCTELEM)DESCALE(tmp4 + z1 + z3,
+ CONST_BITS + PASS1_BITS);
+ dataptr[DCTSIZE * 5] = (DCTELEM)DESCALE(tmp5 + z2 + z4,
+ CONST_BITS + PASS1_BITS);
+ dataptr[DCTSIZE * 3] = (DCTELEM)DESCALE(tmp6 + z2 + z3,
+ CONST_BITS + PASS1_BITS);
+ dataptr[DCTSIZE * 1] = (DCTELEM)DESCALE(tmp7 + z1 + z4,
+ CONST_BITS + PASS1_BITS);
dataptr++; /* advance pointer to next column */
}
diff --git a/src/3rdparty/libjpeg/src/jidctflt.c b/src/3rdparty/libjpeg/src/jidctflt.c
index 68c521ed7e..5aee74e232 100644
--- a/src/3rdparty/libjpeg/src/jidctflt.c
+++ b/src/3rdparty/libjpeg/src/jidctflt.c
@@ -61,7 +61,7 @@
* entry; produce a float result.
*/
-#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval))
+#define DEQUANTIZE(coef, quantval) (((FAST_FLOAT)(coef)) * (quantval))
/*
@@ -69,9 +69,9 @@
*/
GLOBAL(void)
-jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_float(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
FAST_FLOAT tmp10, tmp11, tmp12, tmp13;
@@ -83,12 +83,12 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info *compptr,
JSAMPLE *range_limit = cinfo->sample_range_limit;
int ctr;
FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */
- #define _0_125 ((FLOAT_MULT_TYPE)0.125)
+#define _0_125 ((FLOAT_MULT_TYPE)0.125)
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (FLOAT_MULT_TYPE *) compptr->dct_table;
+ quantptr = (FLOAT_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = DCTSIZE; ctr > 0; ctr--) {
/* Due to quantization, we will usually find that many of the input
@@ -100,22 +100,22 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info *compptr,
* column DCT calculations can be simplified this way.
*/
- if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
- inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
- inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
- inptr[DCTSIZE*7] == 0) {
+ if (inptr[DCTSIZE * 1] == 0 && inptr[DCTSIZE * 2] == 0 &&
+ inptr[DCTSIZE * 3] == 0 && inptr[DCTSIZE * 4] == 0 &&
+ inptr[DCTSIZE * 5] == 0 && inptr[DCTSIZE * 6] == 0 &&
+ inptr[DCTSIZE * 7] == 0) {
/* AC terms all zero */
- FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0],
- quantptr[DCTSIZE*0] * _0_125);
-
- wsptr[DCTSIZE*0] = dcval;
- wsptr[DCTSIZE*1] = dcval;
- wsptr[DCTSIZE*2] = dcval;
- wsptr[DCTSIZE*3] = dcval;
- wsptr[DCTSIZE*4] = dcval;
- wsptr[DCTSIZE*5] = dcval;
- wsptr[DCTSIZE*6] = dcval;
- wsptr[DCTSIZE*7] = dcval;
+ FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE * 0],
+ quantptr[DCTSIZE * 0] * _0_125);
+
+ wsptr[DCTSIZE * 0] = dcval;
+ wsptr[DCTSIZE * 1] = dcval;
+ wsptr[DCTSIZE * 2] = dcval;
+ wsptr[DCTSIZE * 3] = dcval;
+ wsptr[DCTSIZE * 4] = dcval;
+ wsptr[DCTSIZE * 5] = dcval;
+ wsptr[DCTSIZE * 6] = dcval;
+ wsptr[DCTSIZE * 7] = dcval;
inptr++; /* advance pointers to next column */
quantptr++;
@@ -125,16 +125,16 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Even part */
- tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0] * _0_125);
- tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2] * _0_125);
- tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4] * _0_125);
- tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6] * _0_125);
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0] * _0_125);
+ tmp1 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2] * _0_125);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4] * _0_125);
+ tmp3 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6] * _0_125);
tmp10 = tmp0 + tmp2; /* phase 3 */
tmp11 = tmp0 - tmp2;
tmp13 = tmp1 + tmp3; /* phases 5-3 */
- tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */
+ tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT)1.414213562) - tmp13; /* 2*c4 */
tmp0 = tmp10 + tmp13; /* phase 2 */
tmp3 = tmp10 - tmp13;
@@ -143,10 +143,10 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Odd part */
- tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1] * _0_125);
- tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3] * _0_125);
- tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5] * _0_125);
- tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7] * _0_125);
+ tmp4 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1] * _0_125);
+ tmp5 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3] * _0_125);
+ tmp6 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5] * _0_125);
+ tmp7 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7] * _0_125);
z13 = tmp6 + tmp5; /* phase 6 */
z10 = tmp6 - tmp5;
@@ -154,24 +154,24 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info *compptr,
z12 = tmp4 - tmp7;
tmp7 = z11 + z13; /* phase 5 */
- tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */
+ tmp11 = (z11 - z13) * ((FAST_FLOAT)1.414213562); /* 2*c4 */
- z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
- tmp10 = z5 - z12 * ((FAST_FLOAT) 1.082392200); /* 2*(c2-c6) */
- tmp12 = z5 - z10 * ((FAST_FLOAT) 2.613125930); /* 2*(c2+c6) */
+ z5 = (z10 + z12) * ((FAST_FLOAT)1.847759065); /* 2*c2 */
+ tmp10 = z5 - z12 * ((FAST_FLOAT)1.082392200); /* 2*(c2-c6) */
+ tmp12 = z5 - z10 * ((FAST_FLOAT)2.613125930); /* 2*(c2+c6) */
tmp6 = tmp12 - tmp7; /* phase 2 */
tmp5 = tmp11 - tmp6;
tmp4 = tmp10 - tmp5;
- wsptr[DCTSIZE*0] = tmp0 + tmp7;
- wsptr[DCTSIZE*7] = tmp0 - tmp7;
- wsptr[DCTSIZE*1] = tmp1 + tmp6;
- wsptr[DCTSIZE*6] = tmp1 - tmp6;
- wsptr[DCTSIZE*2] = tmp2 + tmp5;
- wsptr[DCTSIZE*5] = tmp2 - tmp5;
- wsptr[DCTSIZE*3] = tmp3 + tmp4;
- wsptr[DCTSIZE*4] = tmp3 - tmp4;
+ wsptr[DCTSIZE * 0] = tmp0 + tmp7;
+ wsptr[DCTSIZE * 7] = tmp0 - tmp7;
+ wsptr[DCTSIZE * 1] = tmp1 + tmp6;
+ wsptr[DCTSIZE * 6] = tmp1 - tmp6;
+ wsptr[DCTSIZE * 2] = tmp2 + tmp5;
+ wsptr[DCTSIZE * 5] = tmp2 - tmp5;
+ wsptr[DCTSIZE * 3] = tmp3 + tmp4;
+ wsptr[DCTSIZE * 4] = tmp3 - tmp4;
inptr++; /* advance pointers to next column */
quantptr++;
@@ -192,12 +192,12 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Even part */
/* Apply signed->unsigned and prepare float->int conversion */
- z5 = wsptr[0] + ((FAST_FLOAT) CENTERJSAMPLE + (FAST_FLOAT) 0.5);
+ z5 = wsptr[0] + ((FAST_FLOAT)CENTERJSAMPLE + (FAST_FLOAT)0.5);
tmp10 = z5 + wsptr[4];
tmp11 = z5 - wsptr[4];
tmp13 = wsptr[2] + wsptr[6];
- tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13;
+ tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT)1.414213562) - tmp13;
tmp0 = tmp10 + tmp13;
tmp3 = tmp10 - tmp13;
@@ -212,11 +212,11 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info *compptr,
z12 = wsptr[1] - wsptr[7];
tmp7 = z11 + z13;
- tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562);
+ tmp11 = (z11 - z13) * ((FAST_FLOAT)1.414213562);
- z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
- tmp10 = z5 - z12 * ((FAST_FLOAT) 1.082392200); /* 2*(c2-c6) */
- tmp12 = z5 - z10 * ((FAST_FLOAT) 2.613125930); /* 2*(c2+c6) */
+ z5 = (z10 + z12) * ((FAST_FLOAT)1.847759065); /* 2*c2 */
+ tmp10 = z5 - z12 * ((FAST_FLOAT)1.082392200); /* 2*(c2-c6) */
+ tmp12 = z5 - z10 * ((FAST_FLOAT)2.613125930); /* 2*(c2+c6) */
tmp6 = tmp12 - tmp7;
tmp5 = tmp11 - tmp6;
@@ -224,14 +224,14 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Final output stage: float->int conversion and range-limit */
- outptr[0] = range_limit[((int) (tmp0 + tmp7)) & RANGE_MASK];
- outptr[7] = range_limit[((int) (tmp0 - tmp7)) & RANGE_MASK];
- outptr[1] = range_limit[((int) (tmp1 + tmp6)) & RANGE_MASK];
- outptr[6] = range_limit[((int) (tmp1 - tmp6)) & RANGE_MASK];
- outptr[2] = range_limit[((int) (tmp2 + tmp5)) & RANGE_MASK];
- outptr[5] = range_limit[((int) (tmp2 - tmp5)) & RANGE_MASK];
- outptr[3] = range_limit[((int) (tmp3 + tmp4)) & RANGE_MASK];
- outptr[4] = range_limit[((int) (tmp3 - tmp4)) & RANGE_MASK];
+ outptr[0] = range_limit[((int)(tmp0 + tmp7)) & RANGE_MASK];
+ outptr[7] = range_limit[((int)(tmp0 - tmp7)) & RANGE_MASK];
+ outptr[1] = range_limit[((int)(tmp1 + tmp6)) & RANGE_MASK];
+ outptr[6] = range_limit[((int)(tmp1 - tmp6)) & RANGE_MASK];
+ outptr[2] = range_limit[((int)(tmp2 + tmp5)) & RANGE_MASK];
+ outptr[5] = range_limit[((int)(tmp2 - tmp5)) & RANGE_MASK];
+ outptr[3] = range_limit[((int)(tmp3 + tmp4)) & RANGE_MASK];
+ outptr[4] = range_limit[((int)(tmp3 - tmp4)) & RANGE_MASK];
wsptr += DCTSIZE; /* advance pointer to next row */
}
diff --git a/src/3rdparty/libjpeg/src/jidctfst.c b/src/3rdparty/libjpeg/src/jidctfst.c
index 10db739b86..89a20c937b 100644
--- a/src/3rdparty/libjpeg/src/jidctfst.c
+++ b/src/3rdparty/libjpeg/src/jidctfst.c
@@ -92,10 +92,10 @@
*/
#if CONST_BITS == 8
-#define FIX_1_082392200 ((JLONG) 277) /* FIX(1.082392200) */
-#define FIX_1_414213562 ((JLONG) 362) /* FIX(1.414213562) */
-#define FIX_1_847759065 ((JLONG) 473) /* FIX(1.847759065) */
-#define FIX_2_613125930 ((JLONG) 669) /* FIX(2.613125930) */
+#define FIX_1_082392200 ((JLONG)277) /* FIX(1.082392200) */
+#define FIX_1_414213562 ((JLONG)362) /* FIX(1.414213562) */
+#define FIX_1_847759065 ((JLONG)473) /* FIX(1.847759065) */
+#define FIX_2_613125930 ((JLONG)669) /* FIX(2.613125930) */
#else
#define FIX_1_082392200 FIX(1.082392200)
#define FIX_1_414213562 FIX(1.414213562)
@@ -111,7 +111,7 @@
#ifndef USE_ACCURATE_ROUNDING
#undef DESCALE
-#define DESCALE(x,n) RIGHT_SHIFT(x, n)
+#define DESCALE(x, n) RIGHT_SHIFT(x, n)
#endif
@@ -119,7 +119,7 @@
* descale to yield a DCTELEM result.
*/
-#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS))
+#define MULTIPLY(var, const) ((DCTELEM)DESCALE((var) * (const), CONST_BITS))
/* Dequantize a coefficient by multiplying it by the multiplier-table
@@ -129,10 +129,10 @@
*/
#if BITS_IN_JSAMPLE == 8
-#define DEQUANTIZE(coef,quantval) (((IFAST_MULT_TYPE) (coef)) * (quantval))
+#define DEQUANTIZE(coef, quantval) (((IFAST_MULT_TYPE)(coef)) * (quantval))
#else
-#define DEQUANTIZE(coef,quantval) \
- DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS)
+#define DEQUANTIZE(coef, quantval) \
+ DESCALE((coef) * (quantval), IFAST_SCALE_BITS - PASS1_BITS)
#endif
@@ -147,19 +147,19 @@
#else
#define DCTELEMBITS 32 /* DCTELEM must be 32 bits */
#endif
-#define IRIGHT_SHIFT(x,shft) \
- ((ishift_temp = (x)) < 0 ? \
- (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \
- (ishift_temp >> (shft)))
+#define IRIGHT_SHIFT(x, shft) \
+ ((ishift_temp = (x)) < 0 ? \
+ (ishift_temp >> (shft)) | ((~((DCTELEM)0)) << (DCTELEMBITS - (shft))) : \
+ (ishift_temp >> (shft)))
#else
#define ISHIFT_TEMPS
-#define IRIGHT_SHIFT(x,shft) ((x) >> (shft))
+#define IRIGHT_SHIFT(x, shft) ((x) >> (shft))
#endif
#ifdef USE_ACCURATE_ROUNDING
-#define IDESCALE(x,n) ((int) IRIGHT_SHIFT((x) + (1 << ((n)-1)), n))
+#define IDESCALE(x, n) ((int)IRIGHT_SHIFT((x) + (1 << ((n) - 1)), n))
#else
-#define IDESCALE(x,n) ((int) IRIGHT_SHIFT(x, n))
+#define IDESCALE(x, n) ((int)IRIGHT_SHIFT(x, n))
#endif
@@ -168,9 +168,9 @@
*/
GLOBAL(void)
-jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_ifast(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
DCTELEM tmp10, tmp11, tmp12, tmp13;
@@ -188,7 +188,7 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (IFAST_MULT_TYPE *) compptr->dct_table;
+ quantptr = (IFAST_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = DCTSIZE; ctr > 0; ctr--) {
/* Due to quantization, we will usually find that many of the input
@@ -200,21 +200,21 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info *compptr,
* column DCT calculations can be simplified this way.
*/
- if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
- inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
- inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
- inptr[DCTSIZE*7] == 0) {
+ if (inptr[DCTSIZE * 1] == 0 && inptr[DCTSIZE * 2] == 0 &&
+ inptr[DCTSIZE * 3] == 0 && inptr[DCTSIZE * 4] == 0 &&
+ inptr[DCTSIZE * 5] == 0 && inptr[DCTSIZE * 6] == 0 &&
+ inptr[DCTSIZE * 7] == 0) {
/* AC terms all zero */
- int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ int dcval = (int)DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
- wsptr[DCTSIZE*0] = dcval;
- wsptr[DCTSIZE*1] = dcval;
- wsptr[DCTSIZE*2] = dcval;
- wsptr[DCTSIZE*3] = dcval;
- wsptr[DCTSIZE*4] = dcval;
- wsptr[DCTSIZE*5] = dcval;
- wsptr[DCTSIZE*6] = dcval;
- wsptr[DCTSIZE*7] = dcval;
+ wsptr[DCTSIZE * 0] = dcval;
+ wsptr[DCTSIZE * 1] = dcval;
+ wsptr[DCTSIZE * 2] = dcval;
+ wsptr[DCTSIZE * 3] = dcval;
+ wsptr[DCTSIZE * 4] = dcval;
+ wsptr[DCTSIZE * 5] = dcval;
+ wsptr[DCTSIZE * 6] = dcval;
+ wsptr[DCTSIZE * 7] = dcval;
inptr++; /* advance pointers to next column */
quantptr++;
@@ -224,10 +224,10 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Even part */
- tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
- tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
- tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
+ tmp1 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
+ tmp3 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]);
tmp10 = tmp0 + tmp2; /* phase 3 */
tmp11 = tmp0 - tmp2;
@@ -242,10 +242,10 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Odd part */
- tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
- tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ tmp4 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ tmp5 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ tmp6 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
+ tmp7 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]);
z13 = tmp6 + tmp5; /* phase 6 */
z10 = tmp6 - tmp5;
@@ -257,20 +257,20 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info *compptr,
z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */
tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */
- tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */
+ tmp12 = MULTIPLY(z10, -FIX_2_613125930) + z5; /* -2*(c2+c6) */
tmp6 = tmp12 - tmp7; /* phase 2 */
tmp5 = tmp11 - tmp6;
tmp4 = tmp10 + tmp5;
- wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7);
- wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7);
- wsptr[DCTSIZE*1] = (int) (tmp1 + tmp6);
- wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6);
- wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5);
- wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5);
- wsptr[DCTSIZE*4] = (int) (tmp3 + tmp4);
- wsptr[DCTSIZE*3] = (int) (tmp3 - tmp4);
+ wsptr[DCTSIZE * 0] = (int)(tmp0 + tmp7);
+ wsptr[DCTSIZE * 7] = (int)(tmp0 - tmp7);
+ wsptr[DCTSIZE * 1] = (int)(tmp1 + tmp6);
+ wsptr[DCTSIZE * 6] = (int)(tmp1 - tmp6);
+ wsptr[DCTSIZE * 2] = (int)(tmp2 + tmp5);
+ wsptr[DCTSIZE * 5] = (int)(tmp2 - tmp5);
+ wsptr[DCTSIZE * 4] = (int)(tmp3 + tmp4);
+ wsptr[DCTSIZE * 3] = (int)(tmp3 - tmp4);
inptr++; /* advance pointers to next column */
quantptr++;
@@ -296,8 +296,8 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info *compptr,
if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 &&
wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) {
/* AC terms all zero */
- JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS+3)
- & RANGE_MASK];
+ JSAMPLE dcval =
+ range_limit[IDESCALE(wsptr[0], PASS1_BITS + 3) & RANGE_MASK];
outptr[0] = dcval;
outptr[1] = dcval;
@@ -315,12 +315,12 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Even part */
- tmp10 = ((DCTELEM) wsptr[0] + (DCTELEM) wsptr[4]);
- tmp11 = ((DCTELEM) wsptr[0] - (DCTELEM) wsptr[4]);
+ tmp10 = ((DCTELEM)wsptr[0] + (DCTELEM)wsptr[4]);
+ tmp11 = ((DCTELEM)wsptr[0] - (DCTELEM)wsptr[4]);
- tmp13 = ((DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]);
- tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562)
- - tmp13;
+ tmp13 = ((DCTELEM)wsptr[2] + (DCTELEM)wsptr[6]);
+ tmp12 =
+ MULTIPLY((DCTELEM)wsptr[2] - (DCTELEM)wsptr[6], FIX_1_414213562) - tmp13;
tmp0 = tmp10 + tmp13;
tmp3 = tmp10 - tmp13;
@@ -329,17 +329,17 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Odd part */
- z13 = (DCTELEM) wsptr[5] + (DCTELEM) wsptr[3];
- z10 = (DCTELEM) wsptr[5] - (DCTELEM) wsptr[3];
- z11 = (DCTELEM) wsptr[1] + (DCTELEM) wsptr[7];
- z12 = (DCTELEM) wsptr[1] - (DCTELEM) wsptr[7];
+ z13 = (DCTELEM)wsptr[5] + (DCTELEM)wsptr[3];
+ z10 = (DCTELEM)wsptr[5] - (DCTELEM)wsptr[3];
+ z11 = (DCTELEM)wsptr[1] + (DCTELEM)wsptr[7];
+ z12 = (DCTELEM)wsptr[1] - (DCTELEM)wsptr[7];
tmp7 = z11 + z13; /* phase 5 */
tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */
z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */
tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */
- tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */
+ tmp12 = MULTIPLY(z10, -FIX_2_613125930) + z5; /* -2*(c2+c6) */
tmp6 = tmp12 - tmp7; /* phase 2 */
tmp5 = tmp11 - tmp6;
@@ -347,22 +347,22 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Final output stage: scale down by a factor of 8 and range-limit */
- outptr[0] = range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS+3)
- & RANGE_MASK];
- outptr[7] = range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS+3)
- & RANGE_MASK];
- outptr[6] = range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS+3)
- & RANGE_MASK];
- outptr[5] = range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] =
+ range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS + 3) & RANGE_MASK];
+ outptr[7] =
+ range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS + 3) & RANGE_MASK];
+ outptr[1] =
+ range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS + 3) & RANGE_MASK];
+ outptr[6] =
+ range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS + 3) & RANGE_MASK];
+ outptr[2] =
+ range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS + 3) & RANGE_MASK];
+ outptr[5] =
+ range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS + 3) & RANGE_MASK];
+ outptr[4] =
+ range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS + 3) & RANGE_MASK];
+ outptr[3] =
+ range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS + 3) & RANGE_MASK];
wsptr += DCTSIZE; /* advance pointer to next row */
}
diff --git a/src/3rdparty/libjpeg/src/jidctint.c b/src/3rdparty/libjpeg/src/jidctint.c
index 3ac6caf692..55573429f1 100644
--- a/src/3rdparty/libjpeg/src/jidctint.c
+++ b/src/3rdparty/libjpeg/src/jidctint.c
@@ -115,18 +115,18 @@
*/
#if CONST_BITS == 13
-#define FIX_0_298631336 ((JLONG) 2446) /* FIX(0.298631336) */
-#define FIX_0_390180644 ((JLONG) 3196) /* FIX(0.390180644) */
-#define FIX_0_541196100 ((JLONG) 4433) /* FIX(0.541196100) */
-#define FIX_0_765366865 ((JLONG) 6270) /* FIX(0.765366865) */
-#define FIX_0_899976223 ((JLONG) 7373) /* FIX(0.899976223) */
-#define FIX_1_175875602 ((JLONG) 9633) /* FIX(1.175875602) */
-#define FIX_1_501321110 ((JLONG) 12299) /* FIX(1.501321110) */
-#define FIX_1_847759065 ((JLONG) 15137) /* FIX(1.847759065) */
-#define FIX_1_961570560 ((JLONG) 16069) /* FIX(1.961570560) */
-#define FIX_2_053119869 ((JLONG) 16819) /* FIX(2.053119869) */
-#define FIX_2_562915447 ((JLONG) 20995) /* FIX(2.562915447) */
-#define FIX_3_072711026 ((JLONG) 25172) /* FIX(3.072711026) */
+#define FIX_0_298631336 ((JLONG)2446) /* FIX(0.298631336) */
+#define FIX_0_390180644 ((JLONG)3196) /* FIX(0.390180644) */
+#define FIX_0_541196100 ((JLONG)4433) /* FIX(0.541196100) */
+#define FIX_0_765366865 ((JLONG)6270) /* FIX(0.765366865) */
+#define FIX_0_899976223 ((JLONG)7373) /* FIX(0.899976223) */
+#define FIX_1_175875602 ((JLONG)9633) /* FIX(1.175875602) */
+#define FIX_1_501321110 ((JLONG)12299) /* FIX(1.501321110) */
+#define FIX_1_847759065 ((JLONG)15137) /* FIX(1.847759065) */
+#define FIX_1_961570560 ((JLONG)16069) /* FIX(1.961570560) */
+#define FIX_2_053119869 ((JLONG)16819) /* FIX(2.053119869) */
+#define FIX_2_562915447 ((JLONG)20995) /* FIX(2.562915447) */
+#define FIX_3_072711026 ((JLONG)25172) /* FIX(3.072711026) */
#else
#define FIX_0_298631336 FIX(0.298631336)
#define FIX_0_390180644 FIX(0.390180644)
@@ -151,9 +151,9 @@
*/
#if BITS_IN_JSAMPLE == 8
-#define MULTIPLY(var,const) MULTIPLY16C16(var,const)
+#define MULTIPLY(var, const) MULTIPLY16C16(var, const)
#else
-#define MULTIPLY(var,const) ((var) * (const))
+#define MULTIPLY(var, const) ((var) * (const))
#endif
@@ -162,7 +162,7 @@
* are 16 bits or less, so either int or short multiply will work.
*/
-#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval))
+#define DEQUANTIZE(coef, quantval) (((ISLOW_MULT_TYPE)(coef)) * (quantval))
/*
@@ -170,9 +170,9 @@
*/
GLOBAL(void)
-jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_islow(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp0, tmp1, tmp2, tmp3;
JLONG tmp10, tmp11, tmp12, tmp13;
@@ -191,7 +191,7 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* furthermore, we scale the results by 2**PASS1_BITS. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = DCTSIZE; ctr > 0; ctr--) {
/* Due to quantization, we will usually find that many of the input
@@ -203,22 +203,22 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info *compptr,
* column DCT calculations can be simplified this way.
*/
- if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
- inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
- inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
- inptr[DCTSIZE*7] == 0) {
+ if (inptr[DCTSIZE * 1] == 0 && inptr[DCTSIZE * 2] == 0 &&
+ inptr[DCTSIZE * 3] == 0 && inptr[DCTSIZE * 4] == 0 &&
+ inptr[DCTSIZE * 5] == 0 && inptr[DCTSIZE * 6] == 0 &&
+ inptr[DCTSIZE * 7] == 0) {
/* AC terms all zero */
- int dcval = LEFT_SHIFT(DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]),
- PASS1_BITS);
-
- wsptr[DCTSIZE*0] = dcval;
- wsptr[DCTSIZE*1] = dcval;
- wsptr[DCTSIZE*2] = dcval;
- wsptr[DCTSIZE*3] = dcval;
- wsptr[DCTSIZE*4] = dcval;
- wsptr[DCTSIZE*5] = dcval;
- wsptr[DCTSIZE*6] = dcval;
- wsptr[DCTSIZE*7] = dcval;
+ int dcval = LEFT_SHIFT(DEQUANTIZE(inptr[DCTSIZE * 0],
+ quantptr[DCTSIZE * 0]), PASS1_BITS);
+
+ wsptr[DCTSIZE * 0] = dcval;
+ wsptr[DCTSIZE * 1] = dcval;
+ wsptr[DCTSIZE * 2] = dcval;
+ wsptr[DCTSIZE * 3] = dcval;
+ wsptr[DCTSIZE * 4] = dcval;
+ wsptr[DCTSIZE * 5] = dcval;
+ wsptr[DCTSIZE * 6] = dcval;
+ wsptr[DCTSIZE * 7] = dcval;
inptr++; /* advance pointers to next column */
quantptr++;
@@ -229,15 +229,15 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Even part: reverse the even part of the forward DCT. */
/* The rotator is sqrt(2)*c(-6). */
- z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]);
z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
- tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
+ tmp2 = z1 + MULTIPLY(z3, -FIX_1_847759065);
tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
- z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
tmp0 = LEFT_SHIFT(z2 + z3, CONST_BITS);
tmp1 = LEFT_SHIFT(z2 - z3, CONST_BITS);
@@ -251,10 +251,10 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info *compptr,
* transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
*/
- tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
- tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
- tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]);
+ tmp1 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ tmp3 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
z1 = tmp0 + tmp3;
z2 = tmp1 + tmp2;
@@ -266,10 +266,10 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info *compptr,
tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
- z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
- z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
- z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
- z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+ z1 = MULTIPLY(z1, -FIX_0_899976223); /* sqrt(2) * ( c7-c3) */
+ z2 = MULTIPLY(z2, -FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ z3 = MULTIPLY(z3, -FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z4 = MULTIPLY(z4, -FIX_0_390180644); /* sqrt(2) * ( c5-c3) */
z3 += z5;
z4 += z5;
@@ -281,14 +281,14 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
- wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
- wsptr[DCTSIZE*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
- wsptr[DCTSIZE*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
- wsptr[DCTSIZE*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
- wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
- wsptr[DCTSIZE*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
- wsptr[DCTSIZE*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
- wsptr[DCTSIZE*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE * 0] = (int)DESCALE(tmp10 + tmp3, CONST_BITS - PASS1_BITS);
+ wsptr[DCTSIZE * 7] = (int)DESCALE(tmp10 - tmp3, CONST_BITS - PASS1_BITS);
+ wsptr[DCTSIZE * 1] = (int)DESCALE(tmp11 + tmp2, CONST_BITS - PASS1_BITS);
+ wsptr[DCTSIZE * 6] = (int)DESCALE(tmp11 - tmp2, CONST_BITS - PASS1_BITS);
+ wsptr[DCTSIZE * 2] = (int)DESCALE(tmp12 + tmp1, CONST_BITS - PASS1_BITS);
+ wsptr[DCTSIZE * 5] = (int)DESCALE(tmp12 - tmp1, CONST_BITS - PASS1_BITS);
+ wsptr[DCTSIZE * 3] = (int)DESCALE(tmp13 + tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[DCTSIZE * 4] = (int)DESCALE(tmp13 - tmp0, CONST_BITS - PASS1_BITS);
inptr++; /* advance pointers to next column */
quantptr++;
@@ -314,8 +314,8 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info *compptr,
if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 &&
wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) {
/* AC terms all zero */
- JSAMPLE dcval = range_limit[(int) DESCALE((JLONG) wsptr[0], PASS1_BITS+3)
- & RANGE_MASK];
+ JSAMPLE dcval = range_limit[(int)DESCALE((JLONG)wsptr[0],
+ PASS1_BITS + 3) & RANGE_MASK];
outptr[0] = dcval;
outptr[1] = dcval;
@@ -334,15 +334,15 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Even part: reverse the even part of the forward DCT. */
/* The rotator is sqrt(2)*c(-6). */
- z2 = (JLONG) wsptr[2];
- z3 = (JLONG) wsptr[6];
+ z2 = (JLONG)wsptr[2];
+ z3 = (JLONG)wsptr[6];
z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
- tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
+ tmp2 = z1 + MULTIPLY(z3, -FIX_1_847759065);
tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
- tmp0 = LEFT_SHIFT((JLONG) wsptr[0] + (JLONG) wsptr[4], CONST_BITS);
- tmp1 = LEFT_SHIFT((JLONG) wsptr[0] - (JLONG) wsptr[4], CONST_BITS);
+ tmp0 = LEFT_SHIFT((JLONG)wsptr[0] + (JLONG)wsptr[4], CONST_BITS);
+ tmp1 = LEFT_SHIFT((JLONG)wsptr[0] - (JLONG)wsptr[4], CONST_BITS);
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
@@ -353,10 +353,10 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info *compptr,
* transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
*/
- tmp0 = (JLONG) wsptr[7];
- tmp1 = (JLONG) wsptr[5];
- tmp2 = (JLONG) wsptr[3];
- tmp3 = (JLONG) wsptr[1];
+ tmp0 = (JLONG)wsptr[7];
+ tmp1 = (JLONG)wsptr[5];
+ tmp2 = (JLONG)wsptr[3];
+ tmp3 = (JLONG)wsptr[1];
z1 = tmp0 + tmp3;
z2 = tmp1 + tmp2;
@@ -368,10 +368,10 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info *compptr,
tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
- z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
- z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
- z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
- z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+ z1 = MULTIPLY(z1, -FIX_0_899976223); /* sqrt(2) * ( c7-c3) */
+ z2 = MULTIPLY(z2, -FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ z3 = MULTIPLY(z3, -FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z4 = MULTIPLY(z4, -FIX_0_390180644); /* sqrt(2) * ( c5-c3) */
z3 += z5;
z4 += z5;
@@ -383,30 +383,30 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
- outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)DESCALE(tmp10 + tmp3,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[7] = range_limit[(int)DESCALE(tmp10 - tmp3,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)DESCALE(tmp11 + tmp2,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[6] = range_limit[(int)DESCALE(tmp11 - tmp2,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)DESCALE(tmp12 + tmp1,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[5] = range_limit[(int)DESCALE(tmp12 - tmp1,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)DESCALE(tmp13 + tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[4] = range_limit[(int)DESCALE(tmp13 - tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += DCTSIZE; /* advance pointer to next row */
}
@@ -424,9 +424,9 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info *compptr,
*/
GLOBAL(void)
-jpeg_idct_7x7 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_7x7(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp0, tmp1, tmp2, tmp10, tmp11, tmp12, tmp13;
JLONG z1, z2, z3;
@@ -436,25 +436,25 @@ jpeg_idct_7x7 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[7*7]; /* buffers data between passes */
+ int workspace[7 * 7]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = 0; ctr < 7; ctr++, inptr++, quantptr++, wsptr++) {
/* Even part */
- tmp13 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp13 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
tmp13 = LEFT_SHIFT(tmp13, CONST_BITS);
/* Add fudge factor here for final descale. */
- tmp13 += ONE << (CONST_BITS-PASS1_BITS-1);
+ tmp13 += ONE << (CONST_BITS - PASS1_BITS - 1);
- z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]);
tmp10 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */
tmp12 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */
@@ -468,15 +468,15 @@ jpeg_idct_7x7 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Odd part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
tmp1 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */
tmp2 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */
tmp0 = tmp1 - tmp2;
tmp1 += tmp2;
- tmp2 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */
+ tmp2 = MULTIPLY(z2 + z3, -FIX(1.378756276)); /* -c1 */
tmp1 += tmp2;
z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */
tmp0 += z2;
@@ -484,13 +484,13 @@ jpeg_idct_7x7 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Final output stage */
- wsptr[7*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS);
- wsptr[7*6] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS);
- wsptr[7*1] = (int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS-PASS1_BITS);
- wsptr[7*5] = (int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS-PASS1_BITS);
- wsptr[7*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS);
- wsptr[7*4] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS);
- wsptr[7*3] = (int) RIGHT_SHIFT(tmp13, CONST_BITS-PASS1_BITS);
+ wsptr[7 * 0] = (int)RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[7 * 6] = (int)RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[7 * 1] = (int)RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS - PASS1_BITS);
+ wsptr[7 * 5] = (int)RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS - PASS1_BITS);
+ wsptr[7 * 2] = (int)RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS - PASS1_BITS);
+ wsptr[7 * 4] = (int)RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS - PASS1_BITS);
+ wsptr[7 * 3] = (int)RIGHT_SHIFT(tmp13, CONST_BITS - PASS1_BITS);
}
/* Pass 2: process 7 rows from work array, store into output array. */
@@ -502,12 +502,12 @@ jpeg_idct_7x7 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Even part */
/* Add fudge factor here for final descale. */
- tmp13 = (JLONG) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp13 = (JLONG)wsptr[0] + (ONE << (PASS1_BITS + 2));
tmp13 = LEFT_SHIFT(tmp13, CONST_BITS);
- z1 = (JLONG) wsptr[2];
- z2 = (JLONG) wsptr[4];
- z3 = (JLONG) wsptr[6];
+ z1 = (JLONG)wsptr[2];
+ z2 = (JLONG)wsptr[4];
+ z3 = (JLONG)wsptr[6];
tmp10 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */
tmp12 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */
@@ -521,15 +521,15 @@ jpeg_idct_7x7 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Odd part */
- z1 = (JLONG) wsptr[1];
- z2 = (JLONG) wsptr[3];
- z3 = (JLONG) wsptr[5];
+ z1 = (JLONG)wsptr[1];
+ z2 = (JLONG)wsptr[3];
+ z3 = (JLONG)wsptr[5];
tmp1 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */
tmp2 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */
tmp0 = tmp1 - tmp2;
tmp1 += tmp2;
- tmp2 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */
+ tmp2 = MULTIPLY(z2 + z3, -FIX(1.378756276)); /* -c1 */
tmp1 += tmp2;
z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */
tmp0 += z2;
@@ -537,27 +537,27 @@ jpeg_idct_7x7 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Final output stage */
- outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)RIGHT_SHIFT(tmp10 + tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[6] = range_limit[(int)RIGHT_SHIFT(tmp10 - tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)RIGHT_SHIFT(tmp11 + tmp1,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[5] = range_limit[(int)RIGHT_SHIFT(tmp11 - tmp1,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)RIGHT_SHIFT(tmp12 + tmp2,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[4] = range_limit[(int)RIGHT_SHIFT(tmp12 - tmp2,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)RIGHT_SHIFT(tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += 7; /* advance pointer to next row */
}
@@ -573,9 +573,9 @@ jpeg_idct_7x7 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
*/
GLOBAL(void)
-jpeg_idct_6x6 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_6x6(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp0, tmp1, tmp2, tmp10, tmp11, tmp12;
JLONG z1, z2, z3;
@@ -585,35 +585,35 @@ jpeg_idct_6x6 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[6*6]; /* buffers data between passes */
+ int workspace[6 * 6]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = 0; ctr < 6; ctr++, inptr++, quantptr++, wsptr++) {
/* Even part */
- tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
tmp0 = LEFT_SHIFT(tmp0, CONST_BITS);
/* Add fudge factor here for final descale. */
- tmp0 += ONE << (CONST_BITS-PASS1_BITS-1);
- tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ tmp0 += ONE << (CONST_BITS - PASS1_BITS - 1);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */
tmp1 = tmp0 + tmp10;
- tmp11 = RIGHT_SHIFT(tmp0 - tmp10 - tmp10, CONST_BITS-PASS1_BITS);
- tmp10 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ tmp11 = RIGHT_SHIFT(tmp0 - tmp10 - tmp10, CONST_BITS - PASS1_BITS);
+ tmp10 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */
tmp10 = tmp1 + tmp0;
tmp12 = tmp1 - tmp0;
/* Odd part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */
tmp0 = tmp1 + LEFT_SHIFT(z1 + z2, CONST_BITS);
tmp2 = tmp1 + LEFT_SHIFT(z3 - z2, CONST_BITS);
@@ -621,12 +621,12 @@ jpeg_idct_6x6 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Final output stage */
- wsptr[6*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS);
- wsptr[6*5] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS);
- wsptr[6*1] = (int) (tmp11 + tmp1);
- wsptr[6*4] = (int) (tmp11 - tmp1);
- wsptr[6*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS);
- wsptr[6*3] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS);
+ wsptr[6 * 0] = (int)RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[6 * 5] = (int)RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[6 * 1] = (int)(tmp11 + tmp1);
+ wsptr[6 * 4] = (int)(tmp11 - tmp1);
+ wsptr[6 * 2] = (int)RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS - PASS1_BITS);
+ wsptr[6 * 3] = (int)RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS - PASS1_BITS);
}
/* Pass 2: process 6 rows from work array, store into output array. */
@@ -638,22 +638,22 @@ jpeg_idct_6x6 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Even part */
/* Add fudge factor here for final descale. */
- tmp0 = (JLONG) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp0 = (JLONG)wsptr[0] + (ONE << (PASS1_BITS + 2));
tmp0 = LEFT_SHIFT(tmp0, CONST_BITS);
- tmp2 = (JLONG) wsptr[4];
+ tmp2 = (JLONG)wsptr[4];
tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */
tmp1 = tmp0 + tmp10;
tmp11 = tmp0 - tmp10 - tmp10;
- tmp10 = (JLONG) wsptr[2];
+ tmp10 = (JLONG)wsptr[2];
tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */
tmp10 = tmp1 + tmp0;
tmp12 = tmp1 - tmp0;
/* Odd part */
- z1 = (JLONG) wsptr[1];
- z2 = (JLONG) wsptr[3];
- z3 = (JLONG) wsptr[5];
+ z1 = (JLONG)wsptr[1];
+ z2 = (JLONG)wsptr[3];
+ z3 = (JLONG)wsptr[5];
tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */
tmp0 = tmp1 + LEFT_SHIFT(z1 + z2, CONST_BITS);
tmp2 = tmp1 + LEFT_SHIFT(z3 - z2, CONST_BITS);
@@ -661,24 +661,24 @@ jpeg_idct_6x6 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Final output stage */
- outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)RIGHT_SHIFT(tmp10 + tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[5] = range_limit[(int)RIGHT_SHIFT(tmp10 - tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)RIGHT_SHIFT(tmp11 + tmp1,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[4] = range_limit[(int)RIGHT_SHIFT(tmp11 - tmp1,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)RIGHT_SHIFT(tmp12 + tmp2,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)RIGHT_SHIFT(tmp12 - tmp2,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += 6; /* advance pointer to next row */
}
@@ -694,9 +694,9 @@ jpeg_idct_6x6 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
*/
GLOBAL(void)
-jpeg_idct_5x5 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_5x5(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp0, tmp1, tmp10, tmp11, tmp12;
JLONG z1, z2, z3;
@@ -706,23 +706,23 @@ jpeg_idct_5x5 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[5*5]; /* buffers data between passes */
+ int workspace[5 * 5]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = 0; ctr < 5; ctr++, inptr++, quantptr++, wsptr++) {
/* Even part */
- tmp12 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp12 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
tmp12 = LEFT_SHIFT(tmp12, CONST_BITS);
/* Add fudge factor here for final descale. */
- tmp12 += ONE << (CONST_BITS-PASS1_BITS-1);
- tmp0 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- tmp1 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ tmp12 += ONE << (CONST_BITS - PASS1_BITS - 1);
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
+ tmp1 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
z1 = MULTIPLY(tmp0 + tmp1, FIX(0.790569415)); /* (c2+c4)/2 */
z2 = MULTIPLY(tmp0 - tmp1, FIX(0.353553391)); /* (c2-c4)/2 */
z3 = tmp12 + z2;
@@ -732,8 +732,8 @@ jpeg_idct_5x5 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Odd part */
- z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */
tmp0 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */
@@ -741,11 +741,11 @@ jpeg_idct_5x5 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Final output stage */
- wsptr[5*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS);
- wsptr[5*4] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS);
- wsptr[5*1] = (int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS-PASS1_BITS);
- wsptr[5*3] = (int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS-PASS1_BITS);
- wsptr[5*2] = (int) RIGHT_SHIFT(tmp12, CONST_BITS-PASS1_BITS);
+ wsptr[5 * 0] = (int)RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[5 * 4] = (int)RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[5 * 1] = (int)RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS - PASS1_BITS);
+ wsptr[5 * 3] = (int)RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS - PASS1_BITS);
+ wsptr[5 * 2] = (int)RIGHT_SHIFT(tmp12, CONST_BITS - PASS1_BITS);
}
/* Pass 2: process 5 rows from work array, store into output array. */
@@ -757,10 +757,10 @@ jpeg_idct_5x5 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Even part */
/* Add fudge factor here for final descale. */
- tmp12 = (JLONG) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp12 = (JLONG)wsptr[0] + (ONE << (PASS1_BITS + 2));
tmp12 = LEFT_SHIFT(tmp12, CONST_BITS);
- tmp0 = (JLONG) wsptr[2];
- tmp1 = (JLONG) wsptr[4];
+ tmp0 = (JLONG)wsptr[2];
+ tmp1 = (JLONG)wsptr[4];
z1 = MULTIPLY(tmp0 + tmp1, FIX(0.790569415)); /* (c2+c4)/2 */
z2 = MULTIPLY(tmp0 - tmp1, FIX(0.353553391)); /* (c2-c4)/2 */
z3 = tmp12 + z2;
@@ -770,8 +770,8 @@ jpeg_idct_5x5 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Odd part */
- z2 = (JLONG) wsptr[1];
- z3 = (JLONG) wsptr[3];
+ z2 = (JLONG)wsptr[1];
+ z3 = (JLONG)wsptr[3];
z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */
tmp0 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */
@@ -779,21 +779,21 @@ jpeg_idct_5x5 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Final output stage */
- outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)RIGHT_SHIFT(tmp10 + tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[4] = range_limit[(int)RIGHT_SHIFT(tmp10 - tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)RIGHT_SHIFT(tmp11 + tmp1,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)RIGHT_SHIFT(tmp11 - tmp1,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)RIGHT_SHIFT(tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += 5; /* advance pointer to next row */
}
@@ -809,9 +809,9 @@ jpeg_idct_5x5 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
*/
GLOBAL(void)
-jpeg_idct_3x3 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_3x3(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp0, tmp2, tmp10, tmp12;
JCOEFPTR inptr;
@@ -820,36 +820,36 @@ jpeg_idct_3x3 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[3*3]; /* buffers data between passes */
+ int workspace[3 * 3]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = 0; ctr < 3; ctr++, inptr++, quantptr++, wsptr++) {
/* Even part */
- tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
tmp0 = LEFT_SHIFT(tmp0, CONST_BITS);
/* Add fudge factor here for final descale. */
- tmp0 += ONE << (CONST_BITS-PASS1_BITS-1);
- tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ tmp0 += ONE << (CONST_BITS - PASS1_BITS - 1);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */
tmp10 = tmp0 + tmp12;
tmp2 = tmp0 - tmp12 - tmp12;
/* Odd part */
- tmp12 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ tmp12 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */
/* Final output stage */
- wsptr[3*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS);
- wsptr[3*2] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS);
- wsptr[3*1] = (int) RIGHT_SHIFT(tmp2, CONST_BITS-PASS1_BITS);
+ wsptr[3 * 0] = (int)RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[3 * 2] = (int)RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[3 * 1] = (int)RIGHT_SHIFT(tmp2, CONST_BITS - PASS1_BITS);
}
/* Pass 2: process 3 rows from work array, store into output array. */
@@ -861,29 +861,29 @@ jpeg_idct_3x3 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Even part */
/* Add fudge factor here for final descale. */
- tmp0 = (JLONG) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp0 = (JLONG)wsptr[0] + (ONE << (PASS1_BITS + 2));
tmp0 = LEFT_SHIFT(tmp0, CONST_BITS);
- tmp2 = (JLONG) wsptr[2];
+ tmp2 = (JLONG)wsptr[2];
tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */
tmp10 = tmp0 + tmp12;
tmp2 = tmp0 - tmp12 - tmp12;
/* Odd part */
- tmp12 = (JLONG) wsptr[1];
+ tmp12 = (JLONG)wsptr[1];
tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */
/* Final output stage */
- outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp2,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)RIGHT_SHIFT(tmp10 + tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)RIGHT_SHIFT(tmp10 - tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)RIGHT_SHIFT(tmp2,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += 3; /* advance pointer to next row */
}
@@ -899,9 +899,9 @@ jpeg_idct_3x3 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
*/
GLOBAL(void)
-jpeg_idct_9x9 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_9x9(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13, tmp14;
JLONG z1, z2, z3, z4;
@@ -911,25 +911,25 @@ jpeg_idct_9x9 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[8*9]; /* buffers data between passes */
+ int workspace[8 * 9]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
/* Even part */
- tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
tmp0 = LEFT_SHIFT(tmp0, CONST_BITS);
/* Add fudge factor here for final descale. */
- tmp0 += ONE << (CONST_BITS-PASS1_BITS-1);
+ tmp0 += ONE << (CONST_BITS - PASS1_BITS - 1);
- z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]);
tmp3 = MULTIPLY(z3, FIX(0.707106781)); /* c6 */
tmp1 = tmp0 + tmp3;
@@ -949,12 +949,12 @@ jpeg_idct_9x9 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Odd part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
- z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]);
- z2 = MULTIPLY(z2, - FIX(1.224744871)); /* -c3 */
+ z2 = MULTIPLY(z2, -FIX(1.224744871)); /* -c3 */
tmp2 = MULTIPLY(z1 + z3, FIX(0.909038955)); /* c5 */
tmp3 = MULTIPLY(z1 + z4, FIX(0.483689525)); /* c7 */
@@ -966,15 +966,15 @@ jpeg_idct_9x9 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Final output stage */
- wsptr[8*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS);
- wsptr[8*8] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS);
- wsptr[8*1] = (int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS-PASS1_BITS);
- wsptr[8*7] = (int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS-PASS1_BITS);
- wsptr[8*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS);
- wsptr[8*6] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS);
- wsptr[8*3] = (int) RIGHT_SHIFT(tmp13 + tmp3, CONST_BITS-PASS1_BITS);
- wsptr[8*5] = (int) RIGHT_SHIFT(tmp13 - tmp3, CONST_BITS-PASS1_BITS);
- wsptr[8*4] = (int) RIGHT_SHIFT(tmp14, CONST_BITS-PASS1_BITS);
+ wsptr[8 * 0] = (int)RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 8] = (int)RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 1] = (int)RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 7] = (int)RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 2] = (int)RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 6] = (int)RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 3] = (int)RIGHT_SHIFT(tmp13 + tmp3, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 5] = (int)RIGHT_SHIFT(tmp13 - tmp3, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 4] = (int)RIGHT_SHIFT(tmp14, CONST_BITS - PASS1_BITS);
}
/* Pass 2: process 9 rows from work array, store into output array. */
@@ -986,12 +986,12 @@ jpeg_idct_9x9 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Even part */
/* Add fudge factor here for final descale. */
- tmp0 = (JLONG) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp0 = (JLONG)wsptr[0] + (ONE << (PASS1_BITS + 2));
tmp0 = LEFT_SHIFT(tmp0, CONST_BITS);
- z1 = (JLONG) wsptr[2];
- z2 = (JLONG) wsptr[4];
- z3 = (JLONG) wsptr[6];
+ z1 = (JLONG)wsptr[2];
+ z2 = (JLONG)wsptr[4];
+ z3 = (JLONG)wsptr[6];
tmp3 = MULTIPLY(z3, FIX(0.707106781)); /* c6 */
tmp1 = tmp0 + tmp3;
@@ -1011,12 +1011,12 @@ jpeg_idct_9x9 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Odd part */
- z1 = (JLONG) wsptr[1];
- z2 = (JLONG) wsptr[3];
- z3 = (JLONG) wsptr[5];
- z4 = (JLONG) wsptr[7];
+ z1 = (JLONG)wsptr[1];
+ z2 = (JLONG)wsptr[3];
+ z3 = (JLONG)wsptr[5];
+ z4 = (JLONG)wsptr[7];
- z2 = MULTIPLY(z2, - FIX(1.224744871)); /* -c3 */
+ z2 = MULTIPLY(z2, -FIX(1.224744871)); /* -c3 */
tmp2 = MULTIPLY(z1 + z3, FIX(0.909038955)); /* c5 */
tmp3 = MULTIPLY(z1 + z4, FIX(0.483689525)); /* c7 */
@@ -1028,33 +1028,33 @@ jpeg_idct_9x9 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Final output stage */
- outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp3,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp3,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)RIGHT_SHIFT(tmp10 + tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[8] = range_limit[(int)RIGHT_SHIFT(tmp10 - tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)RIGHT_SHIFT(tmp11 + tmp1,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[7] = range_limit[(int)RIGHT_SHIFT(tmp11 - tmp1,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)RIGHT_SHIFT(tmp12 + tmp2,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[6] = range_limit[(int)RIGHT_SHIFT(tmp12 - tmp2,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)RIGHT_SHIFT(tmp13 + tmp3,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[5] = range_limit[(int)RIGHT_SHIFT(tmp13 - tmp3,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[4] = range_limit[(int)RIGHT_SHIFT(tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += 8; /* advance pointer to next row */
}
@@ -1070,9 +1070,9 @@ jpeg_idct_9x9 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
*/
GLOBAL(void)
-jpeg_idct_10x10 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_10x10(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp10, tmp11, tmp12, tmp13, tmp14;
JLONG tmp20, tmp21, tmp22, tmp23, tmp24;
@@ -1083,32 +1083,32 @@ jpeg_idct_10x10 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[8*10]; /* buffers data between passes */
+ int workspace[8 * 10]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
/* Even part */
- z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
z3 = LEFT_SHIFT(z3, CONST_BITS);
/* Add fudge factor here for final descale. */
- z3 += ONE << (CONST_BITS-PASS1_BITS-1);
- z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z3 += ONE << (CONST_BITS - PASS1_BITS - 1);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */
z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */
tmp10 = z3 + z1;
tmp11 = z3 - z2;
tmp22 = RIGHT_SHIFT(z3 - LEFT_SHIFT(z1 - z2, 1),
- CONST_BITS-PASS1_BITS); /* c0 = (c4-c8)*2 */
+ CONST_BITS - PASS1_BITS); /* c0 = (c4-c8)*2 */
- z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]);
z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */
tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */
@@ -1121,10 +1121,10 @@ jpeg_idct_10x10 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Odd part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
- z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]);
tmp11 = z2 + z4;
tmp13 = z2 - z4;
@@ -1148,16 +1148,16 @@ jpeg_idct_10x10 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Final output stage */
- wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*9] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*8] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*2] = (int) (tmp22 + tmp12);
- wsptr[8*7] = (int) (tmp22 - tmp12);
- wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS);
- wsptr[8*6] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS);
- wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS);
- wsptr[8*5] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS);
+ wsptr[8 * 0] = (int)RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 9] = (int)RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 1] = (int)RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 8] = (int)RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 2] = (int)(tmp22 + tmp12);
+ wsptr[8 * 7] = (int)(tmp22 - tmp12);
+ wsptr[8 * 3] = (int)RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 6] = (int)RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 4] = (int)RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 5] = (int)RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS - PASS1_BITS);
}
/* Pass 2: process 10 rows from work array, store into output array. */
@@ -1169,9 +1169,9 @@ jpeg_idct_10x10 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Even part */
/* Add fudge factor here for final descale. */
- z3 = (JLONG) wsptr[0] + (ONE << (PASS1_BITS+2));
+ z3 = (JLONG)wsptr[0] + (ONE << (PASS1_BITS + 2));
z3 = LEFT_SHIFT(z3, CONST_BITS);
- z4 = (JLONG) wsptr[4];
+ z4 = (JLONG)wsptr[4];
z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */
z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */
tmp10 = z3 + z1;
@@ -1179,8 +1179,8 @@ jpeg_idct_10x10 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
tmp22 = z3 - LEFT_SHIFT(z1 - z2, 1); /* c0 = (c4-c8)*2 */
- z2 = (JLONG) wsptr[2];
- z3 = (JLONG) wsptr[6];
+ z2 = (JLONG)wsptr[2];
+ z3 = (JLONG)wsptr[6];
z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */
tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */
@@ -1193,11 +1193,11 @@ jpeg_idct_10x10 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Odd part */
- z1 = (JLONG) wsptr[1];
- z2 = (JLONG) wsptr[3];
- z3 = (JLONG) wsptr[5];
+ z1 = (JLONG)wsptr[1];
+ z2 = (JLONG)wsptr[3];
+ z3 = (JLONG)wsptr[5];
z3 = LEFT_SHIFT(z3, CONST_BITS);
- z4 = (JLONG) wsptr[7];
+ z4 = (JLONG)wsptr[7];
tmp11 = z2 + z4;
tmp13 = z2 - z4;
@@ -1220,36 +1220,36 @@ jpeg_idct_10x10 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Final output stage */
- outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)RIGHT_SHIFT(tmp20 + tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[9] = range_limit[(int)RIGHT_SHIFT(tmp20 - tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)RIGHT_SHIFT(tmp21 + tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[8] = range_limit[(int)RIGHT_SHIFT(tmp21 - tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)RIGHT_SHIFT(tmp22 + tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[7] = range_limit[(int)RIGHT_SHIFT(tmp22 - tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)RIGHT_SHIFT(tmp23 + tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[6] = range_limit[(int)RIGHT_SHIFT(tmp23 - tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[4] = range_limit[(int)RIGHT_SHIFT(tmp24 + tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[5] = range_limit[(int)RIGHT_SHIFT(tmp24 - tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += 8; /* advance pointer to next row */
}
@@ -1265,9 +1265,9 @@ jpeg_idct_10x10 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
*/
GLOBAL(void)
-jpeg_idct_11x11 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_11x11(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp10, tmp11, tmp12, tmp13, tmp14;
JLONG tmp20, tmp21, tmp22, tmp23, tmp24, tmp25;
@@ -1278,30 +1278,30 @@ jpeg_idct_11x11 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[8*11]; /* buffers data between passes */
+ int workspace[8 * 11]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
/* Even part */
- tmp10 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp10 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
tmp10 = LEFT_SHIFT(tmp10, CONST_BITS);
/* Add fudge factor here for final descale. */
- tmp10 += ONE << (CONST_BITS-PASS1_BITS-1);
+ tmp10 += ONE << (CONST_BITS - PASS1_BITS - 1);
- z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]);
tmp20 = MULTIPLY(z2 - z3, FIX(2.546640132)); /* c2+c4 */
tmp23 = MULTIPLY(z2 - z1, FIX(0.430815045)); /* c2-c6 */
z4 = z1 + z3;
- tmp24 = MULTIPLY(z4, - FIX(1.155664402)); /* -(c2-c10) */
+ tmp24 = MULTIPLY(z4, -FIX(1.155664402)); /* -(c2-c10) */
z4 -= z2;
tmp25 = tmp10 + MULTIPLY(z4, FIX(1.356927976)); /* c2 */
tmp21 = tmp20 + tmp23 + tmp25 -
@@ -1316,10 +1316,10 @@ jpeg_idct_11x11 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Odd part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
- z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]);
tmp11 = z1 + z2;
tmp14 = MULTIPLY(tmp11 + z3 + z4, FIX(0.398430003)); /* c9 */
@@ -1331,26 +1331,26 @@ jpeg_idct_11x11 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
z1 = tmp14 - MULTIPLY(z2 + z3, FIX(1.163011579)); /* c7+c9 */
tmp11 += z1 + MULTIPLY(z2, FIX(2.073276588)); /* c1+c7+3*c9-c3 */
tmp12 += z1 - MULTIPLY(z3, FIX(1.192193623)); /* c3+c5-c7-c9 */
- z1 = MULTIPLY(z2 + z4, - FIX(1.798248910)); /* -(c1+c9) */
+ z1 = MULTIPLY(z2 + z4, -FIX(1.798248910)); /* -(c1+c9) */
tmp11 += z1;
tmp13 += z1 + MULTIPLY(z4, FIX(2.102458632)); /* c1+c5+c9-c7 */
- tmp14 += MULTIPLY(z2, - FIX(1.467221301)) + /* -(c5+c9) */
+ tmp14 += MULTIPLY(z2, -FIX(1.467221301)) + /* -(c5+c9) */
MULTIPLY(z3, FIX(1.001388905)) - /* c1-c9 */
MULTIPLY(z4, FIX(1.684843907)); /* c3+c9 */
/* Final output stage */
- wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*10] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*9] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS);
- wsptr[8*8] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS);
- wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS);
- wsptr[8*7] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS);
- wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS);
- wsptr[8*6] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS);
- wsptr[8*5] = (int) RIGHT_SHIFT(tmp25, CONST_BITS-PASS1_BITS);
+ wsptr[8 * 0] = (int)RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 10] = (int)RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 1] = (int)RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 9] = (int)RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 2] = (int)RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 8] = (int)RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 3] = (int)RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 7] = (int)RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 4] = (int)RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 6] = (int)RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 5] = (int)RIGHT_SHIFT(tmp25, CONST_BITS - PASS1_BITS);
}
/* Pass 2: process 11 rows from work array, store into output array. */
@@ -1362,17 +1362,17 @@ jpeg_idct_11x11 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Even part */
/* Add fudge factor here for final descale. */
- tmp10 = (JLONG) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp10 = (JLONG)wsptr[0] + (ONE << (PASS1_BITS + 2));
tmp10 = LEFT_SHIFT(tmp10, CONST_BITS);
- z1 = (JLONG) wsptr[2];
- z2 = (JLONG) wsptr[4];
- z3 = (JLONG) wsptr[6];
+ z1 = (JLONG)wsptr[2];
+ z2 = (JLONG)wsptr[4];
+ z3 = (JLONG)wsptr[6];
tmp20 = MULTIPLY(z2 - z3, FIX(2.546640132)); /* c2+c4 */
tmp23 = MULTIPLY(z2 - z1, FIX(0.430815045)); /* c2-c6 */
z4 = z1 + z3;
- tmp24 = MULTIPLY(z4, - FIX(1.155664402)); /* -(c2-c10) */
+ tmp24 = MULTIPLY(z4, -FIX(1.155664402)); /* -(c2-c10) */
z4 -= z2;
tmp25 = tmp10 + MULTIPLY(z4, FIX(1.356927976)); /* c2 */
tmp21 = tmp20 + tmp23 + tmp25 -
@@ -1387,10 +1387,10 @@ jpeg_idct_11x11 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Odd part */
- z1 = (JLONG) wsptr[1];
- z2 = (JLONG) wsptr[3];
- z3 = (JLONG) wsptr[5];
- z4 = (JLONG) wsptr[7];
+ z1 = (JLONG)wsptr[1];
+ z2 = (JLONG)wsptr[3];
+ z3 = (JLONG)wsptr[5];
+ z4 = (JLONG)wsptr[7];
tmp11 = z1 + z2;
tmp14 = MULTIPLY(tmp11 + z3 + z4, FIX(0.398430003)); /* c9 */
@@ -1402,48 +1402,48 @@ jpeg_idct_11x11 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
z1 = tmp14 - MULTIPLY(z2 + z3, FIX(1.163011579)); /* c7+c9 */
tmp11 += z1 + MULTIPLY(z2, FIX(2.073276588)); /* c1+c7+3*c9-c3 */
tmp12 += z1 - MULTIPLY(z3, FIX(1.192193623)); /* c3+c5-c7-c9 */
- z1 = MULTIPLY(z2 + z4, - FIX(1.798248910)); /* -(c1+c9) */
+ z1 = MULTIPLY(z2 + z4, -FIX(1.798248910)); /* -(c1+c9) */
tmp11 += z1;
tmp13 += z1 + MULTIPLY(z4, FIX(2.102458632)); /* c1+c5+c9-c7 */
- tmp14 += MULTIPLY(z2, - FIX(1.467221301)) + /* -(c5+c9) */
+ tmp14 += MULTIPLY(z2, -FIX(1.467221301)) + /* -(c5+c9) */
MULTIPLY(z3, FIX(1.001388905)) - /* c1-c9 */
MULTIPLY(z4, FIX(1.684843907)); /* c3+c9 */
/* Final output stage */
- outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)RIGHT_SHIFT(tmp20 + tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[10] = range_limit[(int)RIGHT_SHIFT(tmp20 - tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)RIGHT_SHIFT(tmp21 + tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[9] = range_limit[(int)RIGHT_SHIFT(tmp21 - tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)RIGHT_SHIFT(tmp22 + tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[8] = range_limit[(int)RIGHT_SHIFT(tmp22 - tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)RIGHT_SHIFT(tmp23 + tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[7] = range_limit[(int)RIGHT_SHIFT(tmp23 - tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[4] = range_limit[(int)RIGHT_SHIFT(tmp24 + tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[6] = range_limit[(int)RIGHT_SHIFT(tmp24 - tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[5] = range_limit[(int)RIGHT_SHIFT(tmp25,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += 8; /* advance pointer to next row */
}
@@ -1459,9 +1459,9 @@ jpeg_idct_11x11 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
*/
GLOBAL(void)
-jpeg_idct_12x12 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_12x12(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp10, tmp11, tmp12, tmp13, tmp14, tmp15;
JLONG tmp20, tmp21, tmp22, tmp23, tmp24, tmp25;
@@ -1472,32 +1472,32 @@ jpeg_idct_12x12 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[8*12]; /* buffers data between passes */
+ int workspace[8 * 12]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
/* Even part */
- z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
z3 = LEFT_SHIFT(z3, CONST_BITS);
/* Add fudge factor here for final descale. */
- z3 += ONE << (CONST_BITS-PASS1_BITS-1);
+ z3 += ONE << (CONST_BITS - PASS1_BITS - 1);
- z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */
tmp10 = z3 + z4;
tmp11 = z3 - z4;
- z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */
z1 = LEFT_SHIFT(z1, CONST_BITS);
- z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]);
z2 = LEFT_SHIFT(z2, CONST_BITS);
tmp12 = z1 - z2;
@@ -1517,19 +1517,19 @@ jpeg_idct_12x12 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Odd part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
- z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]);
tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */
- tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */
+ tmp14 = MULTIPLY(z2, -FIX_0_541196100); /* -c9 */
tmp10 = z1 + z3;
tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */
tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */
tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */
- tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */
+ tmp13 = MULTIPLY(z3 + z4, -FIX(1.045510580)); /* -(c7+c11) */
tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */
tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */
tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */
@@ -1543,18 +1543,18 @@ jpeg_idct_12x12 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Final output stage */
- wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*11] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*10] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS);
- wsptr[8*9] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS);
- wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS);
- wsptr[8*8] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS);
- wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS);
- wsptr[8*7] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS);
- wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS);
- wsptr[8*6] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS);
+ wsptr[8 * 0] = (int)RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 11] = (int)RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 1] = (int)RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 10] = (int)RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 2] = (int)RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 9] = (int)RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 3] = (int)RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 8] = (int)RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 4] = (int)RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 7] = (int)RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 5] = (int)RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 6] = (int)RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS - PASS1_BITS);
}
/* Pass 2: process 12 rows from work array, store into output array. */
@@ -1566,19 +1566,19 @@ jpeg_idct_12x12 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Even part */
/* Add fudge factor here for final descale. */
- z3 = (JLONG) wsptr[0] + (ONE << (PASS1_BITS+2));
+ z3 = (JLONG)wsptr[0] + (ONE << (PASS1_BITS + 2));
z3 = LEFT_SHIFT(z3, CONST_BITS);
- z4 = (JLONG) wsptr[4];
+ z4 = (JLONG)wsptr[4];
z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */
tmp10 = z3 + z4;
tmp11 = z3 - z4;
- z1 = (JLONG) wsptr[2];
+ z1 = (JLONG)wsptr[2];
z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */
z1 = LEFT_SHIFT(z1, CONST_BITS);
- z2 = (JLONG) wsptr[6];
+ z2 = (JLONG)wsptr[6];
z2 = LEFT_SHIFT(z2, CONST_BITS);
tmp12 = z1 - z2;
@@ -1598,19 +1598,19 @@ jpeg_idct_12x12 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Odd part */
- z1 = (JLONG) wsptr[1];
- z2 = (JLONG) wsptr[3];
- z3 = (JLONG) wsptr[5];
- z4 = (JLONG) wsptr[7];
+ z1 = (JLONG)wsptr[1];
+ z2 = (JLONG)wsptr[3];
+ z3 = (JLONG)wsptr[5];
+ z4 = (JLONG)wsptr[7];
tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */
- tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */
+ tmp14 = MULTIPLY(z2, -FIX_0_541196100); /* -c9 */
tmp10 = z1 + z3;
tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */
tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */
tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */
- tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */
+ tmp13 = MULTIPLY(z3 + z4, -FIX(1.045510580)); /* -(c7+c11) */
tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */
tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */
tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */
@@ -1624,42 +1624,42 @@ jpeg_idct_12x12 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Final output stage */
- outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)RIGHT_SHIFT(tmp20 + tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[11] = range_limit[(int)RIGHT_SHIFT(tmp20 - tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)RIGHT_SHIFT(tmp21 + tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[10] = range_limit[(int)RIGHT_SHIFT(tmp21 - tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)RIGHT_SHIFT(tmp22 + tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[9] = range_limit[(int)RIGHT_SHIFT(tmp22 - tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)RIGHT_SHIFT(tmp23 + tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[8] = range_limit[(int)RIGHT_SHIFT(tmp23 - tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[4] = range_limit[(int)RIGHT_SHIFT(tmp24 + tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[7] = range_limit[(int)RIGHT_SHIFT(tmp24 - tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[5] = range_limit[(int)RIGHT_SHIFT(tmp25 + tmp15,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[6] = range_limit[(int)RIGHT_SHIFT(tmp25 - tmp15,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += 8; /* advance pointer to next row */
}
@@ -1675,9 +1675,9 @@ jpeg_idct_12x12 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
*/
GLOBAL(void)
-jpeg_idct_13x13 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_13x13(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp10, tmp11, tmp12, tmp13, tmp14, tmp15;
JLONG tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26;
@@ -1688,25 +1688,25 @@ jpeg_idct_13x13 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[8*13]; /* buffers data between passes */
+ int workspace[8 * 13]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
/* Even part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
z1 = LEFT_SHIFT(z1, CONST_BITS);
/* Add fudge factor here for final descale. */
- z1 += ONE << (CONST_BITS-PASS1_BITS-1);
+ z1 += ONE << (CONST_BITS - PASS1_BITS - 1);
- z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
- z4 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]);
tmp10 = z3 + z4;
tmp11 = z3 - z4;
@@ -1721,22 +1721,22 @@ jpeg_idct_13x13 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
tmp13 = MULTIPLY(tmp11, FIX(0.486914739)) + z1; /* (c8+c12)/2 */
tmp21 = MULTIPLY(z2, FIX(1.058554052)) - tmp12 + tmp13; /* c6 */
- tmp25 = MULTIPLY(z2, - FIX(1.252223920)) + tmp12 + tmp13; /* c4 */
+ tmp25 = MULTIPLY(z2, -FIX(1.252223920)) + tmp12 + tmp13; /* c4 */
tmp12 = MULTIPLY(tmp10, FIX(0.435816023)); /* (c2-c10)/2 */
tmp13 = MULTIPLY(tmp11, FIX(0.937303064)) - z1; /* (c2+c10)/2 */
- tmp23 = MULTIPLY(z2, - FIX(0.170464608)) - tmp12 - tmp13; /* c12 */
- tmp24 = MULTIPLY(z2, - FIX(0.803364869)) + tmp12 - tmp13; /* c8 */
+ tmp23 = MULTIPLY(z2, -FIX(0.170464608)) - tmp12 - tmp13; /* c12 */
+ tmp24 = MULTIPLY(z2, -FIX(0.803364869)) + tmp12 - tmp13; /* c8 */
tmp26 = MULTIPLY(tmp11 - z2, FIX(1.414213562)) + z1; /* c0 */
/* Odd part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
- z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]);
tmp11 = MULTIPLY(z1 + z2, FIX(1.322312651)); /* c3 */
tmp12 = MULTIPLY(z1 + z3, FIX(1.163874945)); /* c5 */
@@ -1744,13 +1744,13 @@ jpeg_idct_13x13 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
tmp13 = MULTIPLY(tmp15, FIX(0.937797057)); /* c7 */
tmp10 = tmp11 + tmp12 + tmp13 -
MULTIPLY(z1, FIX(2.020082300)); /* c7+c5+c3-c1 */
- tmp14 = MULTIPLY(z2 + z3, - FIX(0.338443458)); /* -c11 */
+ tmp14 = MULTIPLY(z2 + z3, -FIX(0.338443458)); /* -c11 */
tmp11 += tmp14 + MULTIPLY(z2, FIX(0.837223564)); /* c5+c9+c11-c3 */
tmp12 += tmp14 - MULTIPLY(z3, FIX(1.572116027)); /* c1+c5-c9-c11 */
- tmp14 = MULTIPLY(z2 + z4, - FIX(1.163874945)); /* -c5 */
+ tmp14 = MULTIPLY(z2 + z4, -FIX(1.163874945)); /* -c5 */
tmp11 += tmp14;
tmp13 += tmp14 + MULTIPLY(z4, FIX(2.205608352)); /* c3+c5+c9-c7 */
- tmp14 = MULTIPLY(z3 + z4, - FIX(0.657217813)); /* -c9 */
+ tmp14 = MULTIPLY(z3 + z4, -FIX(0.657217813)); /* -c9 */
tmp12 += tmp14;
tmp13 += tmp14;
tmp15 = MULTIPLY(tmp15, FIX(0.338443458)); /* c11 */
@@ -1763,19 +1763,19 @@ jpeg_idct_13x13 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Final output stage */
- wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*12] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*11] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS);
- wsptr[8*10] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS);
- wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS);
- wsptr[8*9] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS);
- wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS);
- wsptr[8*8] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS);
- wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS);
- wsptr[8*7] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS);
- wsptr[8*6] = (int) RIGHT_SHIFT(tmp26, CONST_BITS-PASS1_BITS);
+ wsptr[8 * 0] = (int)RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 12] = (int)RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 1] = (int)RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 11] = (int)RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 2] = (int)RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 10] = (int)RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 3] = (int)RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 9] = (int)RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 4] = (int)RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 8] = (int)RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 5] = (int)RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 7] = (int)RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 6] = (int)RIGHT_SHIFT(tmp26, CONST_BITS - PASS1_BITS);
}
/* Pass 2: process 13 rows from work array, store into output array. */
@@ -1787,12 +1787,12 @@ jpeg_idct_13x13 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Even part */
/* Add fudge factor here for final descale. */
- z1 = (JLONG) wsptr[0] + (ONE << (PASS1_BITS+2));
+ z1 = (JLONG)wsptr[0] + (ONE << (PASS1_BITS + 2));
z1 = LEFT_SHIFT(z1, CONST_BITS);
- z2 = (JLONG) wsptr[2];
- z3 = (JLONG) wsptr[4];
- z4 = (JLONG) wsptr[6];
+ z2 = (JLONG)wsptr[2];
+ z3 = (JLONG)wsptr[4];
+ z4 = (JLONG)wsptr[6];
tmp10 = z3 + z4;
tmp11 = z3 - z4;
@@ -1807,22 +1807,22 @@ jpeg_idct_13x13 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
tmp13 = MULTIPLY(tmp11, FIX(0.486914739)) + z1; /* (c8+c12)/2 */
tmp21 = MULTIPLY(z2, FIX(1.058554052)) - tmp12 + tmp13; /* c6 */
- tmp25 = MULTIPLY(z2, - FIX(1.252223920)) + tmp12 + tmp13; /* c4 */
+ tmp25 = MULTIPLY(z2, -FIX(1.252223920)) + tmp12 + tmp13; /* c4 */
tmp12 = MULTIPLY(tmp10, FIX(0.435816023)); /* (c2-c10)/2 */
tmp13 = MULTIPLY(tmp11, FIX(0.937303064)) - z1; /* (c2+c10)/2 */
- tmp23 = MULTIPLY(z2, - FIX(0.170464608)) - tmp12 - tmp13; /* c12 */
- tmp24 = MULTIPLY(z2, - FIX(0.803364869)) + tmp12 - tmp13; /* c8 */
+ tmp23 = MULTIPLY(z2, -FIX(0.170464608)) - tmp12 - tmp13; /* c12 */
+ tmp24 = MULTIPLY(z2, -FIX(0.803364869)) + tmp12 - tmp13; /* c8 */
tmp26 = MULTIPLY(tmp11 - z2, FIX(1.414213562)) + z1; /* c0 */
/* Odd part */
- z1 = (JLONG) wsptr[1];
- z2 = (JLONG) wsptr[3];
- z3 = (JLONG) wsptr[5];
- z4 = (JLONG) wsptr[7];
+ z1 = (JLONG)wsptr[1];
+ z2 = (JLONG)wsptr[3];
+ z3 = (JLONG)wsptr[5];
+ z4 = (JLONG)wsptr[7];
tmp11 = MULTIPLY(z1 + z2, FIX(1.322312651)); /* c3 */
tmp12 = MULTIPLY(z1 + z3, FIX(1.163874945)); /* c5 */
@@ -1830,13 +1830,13 @@ jpeg_idct_13x13 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
tmp13 = MULTIPLY(tmp15, FIX(0.937797057)); /* c7 */
tmp10 = tmp11 + tmp12 + tmp13 -
MULTIPLY(z1, FIX(2.020082300)); /* c7+c5+c3-c1 */
- tmp14 = MULTIPLY(z2 + z3, - FIX(0.338443458)); /* -c11 */
+ tmp14 = MULTIPLY(z2 + z3, -FIX(0.338443458)); /* -c11 */
tmp11 += tmp14 + MULTIPLY(z2, FIX(0.837223564)); /* c5+c9+c11-c3 */
tmp12 += tmp14 - MULTIPLY(z3, FIX(1.572116027)); /* c1+c5-c9-c11 */
- tmp14 = MULTIPLY(z2 + z4, - FIX(1.163874945)); /* -c5 */
+ tmp14 = MULTIPLY(z2 + z4, -FIX(1.163874945)); /* -c5 */
tmp11 += tmp14;
tmp13 += tmp14 + MULTIPLY(z4, FIX(2.205608352)); /* c3+c5+c9-c7 */
- tmp14 = MULTIPLY(z3 + z4, - FIX(0.657217813)); /* -c9 */
+ tmp14 = MULTIPLY(z3 + z4, -FIX(0.657217813)); /* -c9 */
tmp12 += tmp14;
tmp13 += tmp14;
tmp15 = MULTIPLY(tmp15, FIX(0.338443458)); /* c11 */
@@ -1849,45 +1849,45 @@ jpeg_idct_13x13 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Final output stage */
- outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)RIGHT_SHIFT(tmp20 + tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[12] = range_limit[(int)RIGHT_SHIFT(tmp20 - tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)RIGHT_SHIFT(tmp21 + tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[11] = range_limit[(int)RIGHT_SHIFT(tmp21 - tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)RIGHT_SHIFT(tmp22 + tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[10] = range_limit[(int)RIGHT_SHIFT(tmp22 - tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)RIGHT_SHIFT(tmp23 + tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[9] = range_limit[(int)RIGHT_SHIFT(tmp23 - tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[4] = range_limit[(int)RIGHT_SHIFT(tmp24 + tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[8] = range_limit[(int)RIGHT_SHIFT(tmp24 - tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[5] = range_limit[(int)RIGHT_SHIFT(tmp25 + tmp15,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[7] = range_limit[(int)RIGHT_SHIFT(tmp25 - tmp15,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[6] = range_limit[(int)RIGHT_SHIFT(tmp26,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += 8; /* advance pointer to next row */
}
@@ -1903,9 +1903,9 @@ jpeg_idct_13x13 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
*/
GLOBAL(void)
-jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_14x14(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16;
JLONG tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26;
@@ -1916,22 +1916,22 @@ jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[8*14]; /* buffers data between passes */
+ int workspace[8 * 14]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
/* Even part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
z1 = LEFT_SHIFT(z1, CONST_BITS);
/* Add fudge factor here for final descale. */
- z1 += ONE << (CONST_BITS-PASS1_BITS-1);
- z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z1 += ONE << (CONST_BITS - PASS1_BITS - 1);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */
z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */
z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */
@@ -1941,10 +1941,10 @@ jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
tmp12 = z1 - z4;
tmp23 = RIGHT_SHIFT(z1 - LEFT_SHIFT(z2 + z3 - z4, 1),
- CONST_BITS-PASS1_BITS); /* c0 = (c4+c12-c8)*2 */
+ CONST_BITS - PASS1_BITS); /* c0 = (c4+c12-c8)*2 */
- z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]);
z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */
@@ -1962,10 +1962,10 @@ jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Odd part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
- z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]);
tmp13 = LEFT_SHIFT(z4, CONST_BITS);
tmp14 = z1 + z3;
@@ -1978,7 +1978,7 @@ jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
tmp15 = MULTIPLY(z1, FIX(0.467085129)) - tmp13; /* c11 */
tmp16 += tmp15;
z1 += z4;
- z4 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - tmp13; /* -c13 */
+ z4 = MULTIPLY(z2 + z3, -FIX(0.158341681)) - tmp13; /* -c13 */
tmp11 += z4 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */
tmp12 += z4 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */
z4 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */
@@ -1989,20 +1989,20 @@ jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Final output stage */
- wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*13] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*12] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS);
- wsptr[8*11] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS);
- wsptr[8*3] = (int) (tmp23 + tmp13);
- wsptr[8*10] = (int) (tmp23 - tmp13);
- wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS);
- wsptr[8*9] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS);
- wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS);
- wsptr[8*8] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS);
- wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS-PASS1_BITS);
- wsptr[8*7] = (int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS-PASS1_BITS);
+ wsptr[8 * 0] = (int)RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 13] = (int)RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 1] = (int)RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 12] = (int)RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 2] = (int)RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 11] = (int)RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 3] = (int)(tmp23 + tmp13);
+ wsptr[8 * 10] = (int)(tmp23 - tmp13);
+ wsptr[8 * 4] = (int)RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 9] = (int)RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 5] = (int)RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 8] = (int)RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 6] = (int)RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 7] = (int)RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS - PASS1_BITS);
}
/* Pass 2: process 14 rows from work array, store into output array. */
@@ -2014,9 +2014,9 @@ jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Even part */
/* Add fudge factor here for final descale. */
- z1 = (JLONG) wsptr[0] + (ONE << (PASS1_BITS+2));
+ z1 = (JLONG)wsptr[0] + (ONE << (PASS1_BITS + 2));
z1 = LEFT_SHIFT(z1, CONST_BITS);
- z4 = (JLONG) wsptr[4];
+ z4 = (JLONG)wsptr[4];
z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */
z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */
z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */
@@ -2027,8 +2027,8 @@ jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
tmp23 = z1 - LEFT_SHIFT(z2 + z3 - z4, 1); /* c0 = (c4+c12-c8)*2 */
- z1 = (JLONG) wsptr[2];
- z2 = (JLONG) wsptr[6];
+ z1 = (JLONG)wsptr[2];
+ z2 = (JLONG)wsptr[6];
z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */
@@ -2046,10 +2046,10 @@ jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Odd part */
- z1 = (JLONG) wsptr[1];
- z2 = (JLONG) wsptr[3];
- z3 = (JLONG) wsptr[5];
- z4 = (JLONG) wsptr[7];
+ z1 = (JLONG)wsptr[1];
+ z2 = (JLONG)wsptr[3];
+ z3 = (JLONG)wsptr[5];
+ z4 = (JLONG)wsptr[7];
z4 = LEFT_SHIFT(z4, CONST_BITS);
tmp14 = z1 + z3;
@@ -2061,7 +2061,7 @@ jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
z1 -= z2;
tmp15 = MULTIPLY(z1, FIX(0.467085129)) - z4; /* c11 */
tmp16 += tmp15;
- tmp13 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - z4; /* -c13 */
+ tmp13 = MULTIPLY(z2 + z3, -FIX(0.158341681)) - z4; /* -c13 */
tmp11 += tmp13 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */
tmp12 += tmp13 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */
tmp13 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */
@@ -2072,48 +2072,48 @@ jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Final output stage */
- outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)RIGHT_SHIFT(tmp20 + tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[13] = range_limit[(int)RIGHT_SHIFT(tmp20 - tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)RIGHT_SHIFT(tmp21 + tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[12] = range_limit[(int)RIGHT_SHIFT(tmp21 - tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)RIGHT_SHIFT(tmp22 + tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[11] = range_limit[(int)RIGHT_SHIFT(tmp22 - tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)RIGHT_SHIFT(tmp23 + tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[10] = range_limit[(int)RIGHT_SHIFT(tmp23 - tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[4] = range_limit[(int)RIGHT_SHIFT(tmp24 + tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[9] = range_limit[(int)RIGHT_SHIFT(tmp24 - tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[5] = range_limit[(int)RIGHT_SHIFT(tmp25 + tmp15,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[8] = range_limit[(int)RIGHT_SHIFT(tmp25 - tmp15,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[6] = range_limit[(int)RIGHT_SHIFT(tmp26 + tmp16,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[7] = range_limit[(int)RIGHT_SHIFT(tmp26 - tmp16,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += 8; /* advance pointer to next row */
}
@@ -2129,9 +2129,9 @@ jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
*/
GLOBAL(void)
-jpeg_idct_15x15 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_15x15(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16;
JLONG tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27;
@@ -2142,25 +2142,25 @@ jpeg_idct_15x15 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[8*15]; /* buffers data between passes */
+ int workspace[8 * 15]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
/* Even part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
z1 = LEFT_SHIFT(z1, CONST_BITS);
/* Add fudge factor here for final descale. */
- z1 += ONE << (CONST_BITS-PASS1_BITS-1);
+ z1 += ONE << (CONST_BITS - PASS1_BITS - 1);
- z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
- z4 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]);
tmp10 = MULTIPLY(z4, FIX(0.437016024)); /* c12 */
tmp11 = MULTIPLY(z4, FIX(1.144122806)); /* c6 */
@@ -2195,19 +2195,19 @@ jpeg_idct_15x15 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Odd part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- z4 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
z3 = MULTIPLY(z4, FIX(1.224744871)); /* c5 */
- z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]);
tmp13 = z2 - z4;
tmp15 = MULTIPLY(z1 + tmp13, FIX(0.831253876)); /* c9 */
tmp11 = tmp15 + MULTIPLY(z1, FIX(0.513743148)); /* c3-c9 */
tmp14 = tmp15 - MULTIPLY(tmp13, FIX(2.176250899)); /* c3+c9 */
- tmp13 = MULTIPLY(z2, - FIX(0.831253876)); /* -c9 */
- tmp15 = MULTIPLY(z2, - FIX(1.344997024)); /* -c3 */
+ tmp13 = MULTIPLY(z2, -FIX(0.831253876)); /* -c9 */
+ tmp15 = MULTIPLY(z2, -FIX(1.344997024)); /* -c3 */
z2 = z1 - z4;
tmp12 = z3 + MULTIPLY(z2, FIX(1.406466353)); /* c1 */
@@ -2220,21 +2220,21 @@ jpeg_idct_15x15 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Final output stage */
- wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*14] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*13] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS);
- wsptr[8*12] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS);
- wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS);
- wsptr[8*11] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS);
- wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS);
- wsptr[8*10] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS);
- wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS);
- wsptr[8*9] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS);
- wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS-PASS1_BITS);
- wsptr[8*8] = (int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS-PASS1_BITS);
- wsptr[8*7] = (int) RIGHT_SHIFT(tmp27, CONST_BITS-PASS1_BITS);
+ wsptr[8 * 0] = (int)RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 14] = (int)RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 1] = (int)RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 13] = (int)RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 2] = (int)RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 12] = (int)RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 3] = (int)RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 11] = (int)RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 4] = (int)RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 10] = (int)RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 5] = (int)RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 9] = (int)RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 6] = (int)RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 8] = (int)RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 7] = (int)RIGHT_SHIFT(tmp27, CONST_BITS - PASS1_BITS);
}
/* Pass 2: process 15 rows from work array, store into output array. */
@@ -2246,12 +2246,12 @@ jpeg_idct_15x15 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Even part */
/* Add fudge factor here for final descale. */
- z1 = (JLONG) wsptr[0] + (ONE << (PASS1_BITS+2));
+ z1 = (JLONG)wsptr[0] + (ONE << (PASS1_BITS + 2));
z1 = LEFT_SHIFT(z1, CONST_BITS);
- z2 = (JLONG) wsptr[2];
- z3 = (JLONG) wsptr[4];
- z4 = (JLONG) wsptr[6];
+ z2 = (JLONG)wsptr[2];
+ z3 = (JLONG)wsptr[4];
+ z4 = (JLONG)wsptr[6];
tmp10 = MULTIPLY(z4, FIX(0.437016024)); /* c12 */
tmp11 = MULTIPLY(z4, FIX(1.144122806)); /* c6 */
@@ -2286,19 +2286,19 @@ jpeg_idct_15x15 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Odd part */
- z1 = (JLONG) wsptr[1];
- z2 = (JLONG) wsptr[3];
- z4 = (JLONG) wsptr[5];
+ z1 = (JLONG)wsptr[1];
+ z2 = (JLONG)wsptr[3];
+ z4 = (JLONG)wsptr[5];
z3 = MULTIPLY(z4, FIX(1.224744871)); /* c5 */
- z4 = (JLONG) wsptr[7];
+ z4 = (JLONG)wsptr[7];
tmp13 = z2 - z4;
tmp15 = MULTIPLY(z1 + tmp13, FIX(0.831253876)); /* c9 */
tmp11 = tmp15 + MULTIPLY(z1, FIX(0.513743148)); /* c3-c9 */
tmp14 = tmp15 - MULTIPLY(tmp13, FIX(2.176250899)); /* c3+c9 */
- tmp13 = MULTIPLY(z2, - FIX(0.831253876)); /* -c9 */
- tmp15 = MULTIPLY(z2, - FIX(1.344997024)); /* -c3 */
+ tmp13 = MULTIPLY(z2, -FIX(0.831253876)); /* -c9 */
+ tmp15 = MULTIPLY(z2, -FIX(1.344997024)); /* -c3 */
z2 = z1 - z4;
tmp12 = z3 + MULTIPLY(z2, FIX(1.406466353)); /* c1 */
@@ -2311,51 +2311,51 @@ jpeg_idct_15x15 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Final output stage */
- outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)RIGHT_SHIFT(tmp20 + tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[14] = range_limit[(int)RIGHT_SHIFT(tmp20 - tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)RIGHT_SHIFT(tmp21 + tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[13] = range_limit[(int)RIGHT_SHIFT(tmp21 - tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)RIGHT_SHIFT(tmp22 + tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[12] = range_limit[(int)RIGHT_SHIFT(tmp22 - tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)RIGHT_SHIFT(tmp23 + tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[11] = range_limit[(int)RIGHT_SHIFT(tmp23 - tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[4] = range_limit[(int)RIGHT_SHIFT(tmp24 + tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[10] = range_limit[(int)RIGHT_SHIFT(tmp24 - tmp14,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[5] = range_limit[(int)RIGHT_SHIFT(tmp25 + tmp15,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[9] = range_limit[(int)RIGHT_SHIFT(tmp25 - tmp15,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[6] = range_limit[(int)RIGHT_SHIFT(tmp26 + tmp16,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[8] = range_limit[(int)RIGHT_SHIFT(tmp26 - tmp16,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[7] = range_limit[(int)RIGHT_SHIFT(tmp27,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += 8; /* advance pointer to next row */
}
@@ -2371,9 +2371,9 @@ jpeg_idct_15x15 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
*/
GLOBAL(void)
-jpeg_idct_16x16 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_16x16(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13;
JLONG tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27;
@@ -2384,23 +2384,23 @@ jpeg_idct_16x16 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[8*16]; /* buffers data between passes */
+ int workspace[8 * 16]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
/* Even part */
- tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
tmp0 = LEFT_SHIFT(tmp0, CONST_BITS);
/* Add fudge factor here for final descale. */
- tmp0 += 1 << (CONST_BITS-PASS1_BITS-1);
+ tmp0 += 1 << (CONST_BITS - PASS1_BITS - 1);
- z1 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]);
tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */
tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */
@@ -2409,8 +2409,8 @@ jpeg_idct_16x16 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
tmp12 = tmp0 + tmp2;
tmp13 = tmp0 - tmp2;
- z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]);
z3 = z1 - z2;
z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */
z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */
@@ -2431,10 +2431,10 @@ jpeg_idct_16x16 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Odd part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
- z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]);
tmp11 = z1 + z3;
@@ -2455,13 +2455,13 @@ jpeg_idct_16x16 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */
tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */
z2 += z4;
- z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */
+ z1 = MULTIPLY(z2, -FIX(0.666655658)); /* -c11 */
tmp1 += z1;
tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */
- z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */
+ z2 = MULTIPLY(z2, -FIX(1.247225013)); /* -c5 */
tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */
tmp12 += z2;
- z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */
+ z2 = MULTIPLY(z3 + z4, -FIX(1.353318001)); /* -c3 */
tmp2 += z2;
tmp3 += z2;
z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */
@@ -2470,22 +2470,22 @@ jpeg_idct_16x16 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Final output stage */
- wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp0, CONST_BITS-PASS1_BITS);
- wsptr[8*15] = (int) RIGHT_SHIFT(tmp20 - tmp0, CONST_BITS-PASS1_BITS);
- wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp1, CONST_BITS-PASS1_BITS);
- wsptr[8*14] = (int) RIGHT_SHIFT(tmp21 - tmp1, CONST_BITS-PASS1_BITS);
- wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp2, CONST_BITS-PASS1_BITS);
- wsptr[8*13] = (int) RIGHT_SHIFT(tmp22 - tmp2, CONST_BITS-PASS1_BITS);
- wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp3, CONST_BITS-PASS1_BITS);
- wsptr[8*12] = (int) RIGHT_SHIFT(tmp23 - tmp3, CONST_BITS-PASS1_BITS);
- wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*11] = (int) RIGHT_SHIFT(tmp24 - tmp10, CONST_BITS-PASS1_BITS);
- wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*10] = (int) RIGHT_SHIFT(tmp25 - tmp11, CONST_BITS-PASS1_BITS);
- wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp12, CONST_BITS-PASS1_BITS);
- wsptr[8*9] = (int) RIGHT_SHIFT(tmp26 - tmp12, CONST_BITS-PASS1_BITS);
- wsptr[8*7] = (int) RIGHT_SHIFT(tmp27 + tmp13, CONST_BITS-PASS1_BITS);
- wsptr[8*8] = (int) RIGHT_SHIFT(tmp27 - tmp13, CONST_BITS-PASS1_BITS);
+ wsptr[8 * 0] = (int)RIGHT_SHIFT(tmp20 + tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 15] = (int)RIGHT_SHIFT(tmp20 - tmp0, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 1] = (int)RIGHT_SHIFT(tmp21 + tmp1, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 14] = (int)RIGHT_SHIFT(tmp21 - tmp1, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 2] = (int)RIGHT_SHIFT(tmp22 + tmp2, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 13] = (int)RIGHT_SHIFT(tmp22 - tmp2, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 3] = (int)RIGHT_SHIFT(tmp23 + tmp3, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 12] = (int)RIGHT_SHIFT(tmp23 - tmp3, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 4] = (int)RIGHT_SHIFT(tmp24 + tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 11] = (int)RIGHT_SHIFT(tmp24 - tmp10, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 5] = (int)RIGHT_SHIFT(tmp25 + tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 10] = (int)RIGHT_SHIFT(tmp25 - tmp11, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 6] = (int)RIGHT_SHIFT(tmp26 + tmp12, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 9] = (int)RIGHT_SHIFT(tmp26 - tmp12, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 7] = (int)RIGHT_SHIFT(tmp27 + tmp13, CONST_BITS - PASS1_BITS);
+ wsptr[8 * 8] = (int)RIGHT_SHIFT(tmp27 - tmp13, CONST_BITS - PASS1_BITS);
}
/* Pass 2: process 16 rows from work array, store into output array. */
@@ -2497,10 +2497,10 @@ jpeg_idct_16x16 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Even part */
/* Add fudge factor here for final descale. */
- tmp0 = (JLONG) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp0 = (JLONG)wsptr[0] + (ONE << (PASS1_BITS + 2));
tmp0 = LEFT_SHIFT(tmp0, CONST_BITS);
- z1 = (JLONG) wsptr[4];
+ z1 = (JLONG)wsptr[4];
tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */
tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */
@@ -2509,8 +2509,8 @@ jpeg_idct_16x16 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
tmp12 = tmp0 + tmp2;
tmp13 = tmp0 - tmp2;
- z1 = (JLONG) wsptr[2];
- z2 = (JLONG) wsptr[6];
+ z1 = (JLONG)wsptr[2];
+ z2 = (JLONG)wsptr[6];
z3 = z1 - z2;
z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */
z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */
@@ -2531,10 +2531,10 @@ jpeg_idct_16x16 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Odd part */
- z1 = (JLONG) wsptr[1];
- z2 = (JLONG) wsptr[3];
- z3 = (JLONG) wsptr[5];
- z4 = (JLONG) wsptr[7];
+ z1 = (JLONG)wsptr[1];
+ z2 = (JLONG)wsptr[3];
+ z3 = (JLONG)wsptr[5];
+ z4 = (JLONG)wsptr[7];
tmp11 = z1 + z3;
@@ -2555,13 +2555,13 @@ jpeg_idct_16x16 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */
tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */
z2 += z4;
- z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */
+ z1 = MULTIPLY(z2, -FIX(0.666655658)); /* -c11 */
tmp1 += z1;
tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */
- z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */
+ z2 = MULTIPLY(z2, -FIX(1.247225013)); /* -c5 */
tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */
tmp12 += z2;
- z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */
+ z2 = MULTIPLY(z3 + z4, -FIX(1.353318001)); /* -c3 */
tmp2 += z2;
tmp3 += z2;
z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */
@@ -2570,54 +2570,54 @@ jpeg_idct_16x16 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Final output stage */
- outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[15] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp0,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp1,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp1,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp2,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp2,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp3,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp3,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp10,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp11,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp12,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27 + tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
- outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp27 - tmp13,
- CONST_BITS+PASS1_BITS+3)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)RIGHT_SHIFT(tmp20 + tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[15] = range_limit[(int)RIGHT_SHIFT(tmp20 - tmp0,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)RIGHT_SHIFT(tmp21 + tmp1,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[14] = range_limit[(int)RIGHT_SHIFT(tmp21 - tmp1,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)RIGHT_SHIFT(tmp22 + tmp2,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[13] = range_limit[(int)RIGHT_SHIFT(tmp22 - tmp2,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)RIGHT_SHIFT(tmp23 + tmp3,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[12] = range_limit[(int)RIGHT_SHIFT(tmp23 - tmp3,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[4] = range_limit[(int)RIGHT_SHIFT(tmp24 + tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[11] = range_limit[(int)RIGHT_SHIFT(tmp24 - tmp10,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[5] = range_limit[(int)RIGHT_SHIFT(tmp25 + tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[10] = range_limit[(int)RIGHT_SHIFT(tmp25 - tmp11,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[6] = range_limit[(int)RIGHT_SHIFT(tmp26 + tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[9] = range_limit[(int)RIGHT_SHIFT(tmp26 - tmp12,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[7] = range_limit[(int)RIGHT_SHIFT(tmp27 + tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
+ outptr[8] = range_limit[(int)RIGHT_SHIFT(tmp27 - tmp13,
+ CONST_BITS + PASS1_BITS + 3) &
+ RANGE_MASK];
wsptr += 8; /* advance pointer to next row */
}
diff --git a/src/3rdparty/libjpeg/src/jidctred.c b/src/3rdparty/libjpeg/src/jidctred.c
index 7a81803b8d..1ff352f875 100644
--- a/src/3rdparty/libjpeg/src/jidctred.c
+++ b/src/3rdparty/libjpeg/src/jidctred.c
@@ -58,20 +58,20 @@
*/
#if CONST_BITS == 13
-#define FIX_0_211164243 ((JLONG) 1730) /* FIX(0.211164243) */
-#define FIX_0_509795579 ((JLONG) 4176) /* FIX(0.509795579) */
-#define FIX_0_601344887 ((JLONG) 4926) /* FIX(0.601344887) */
-#define FIX_0_720959822 ((JLONG) 5906) /* FIX(0.720959822) */
-#define FIX_0_765366865 ((JLONG) 6270) /* FIX(0.765366865) */
-#define FIX_0_850430095 ((JLONG) 6967) /* FIX(0.850430095) */
-#define FIX_0_899976223 ((JLONG) 7373) /* FIX(0.899976223) */
-#define FIX_1_061594337 ((JLONG) 8697) /* FIX(1.061594337) */
-#define FIX_1_272758580 ((JLONG) 10426) /* FIX(1.272758580) */
-#define FIX_1_451774981 ((JLONG) 11893) /* FIX(1.451774981) */
-#define FIX_1_847759065 ((JLONG) 15137) /* FIX(1.847759065) */
-#define FIX_2_172734803 ((JLONG) 17799) /* FIX(2.172734803) */
-#define FIX_2_562915447 ((JLONG) 20995) /* FIX(2.562915447) */
-#define FIX_3_624509785 ((JLONG) 29692) /* FIX(3.624509785) */
+#define FIX_0_211164243 ((JLONG)1730) /* FIX(0.211164243) */
+#define FIX_0_509795579 ((JLONG)4176) /* FIX(0.509795579) */
+#define FIX_0_601344887 ((JLONG)4926) /* FIX(0.601344887) */
+#define FIX_0_720959822 ((JLONG)5906) /* FIX(0.720959822) */
+#define FIX_0_765366865 ((JLONG)6270) /* FIX(0.765366865) */
+#define FIX_0_850430095 ((JLONG)6967) /* FIX(0.850430095) */
+#define FIX_0_899976223 ((JLONG)7373) /* FIX(0.899976223) */
+#define FIX_1_061594337 ((JLONG)8697) /* FIX(1.061594337) */
+#define FIX_1_272758580 ((JLONG)10426) /* FIX(1.272758580) */
+#define FIX_1_451774981 ((JLONG)11893) /* FIX(1.451774981) */
+#define FIX_1_847759065 ((JLONG)15137) /* FIX(1.847759065) */
+#define FIX_2_172734803 ((JLONG)17799) /* FIX(2.172734803) */
+#define FIX_2_562915447 ((JLONG)20995) /* FIX(2.562915447) */
+#define FIX_3_624509785 ((JLONG)29692) /* FIX(3.624509785) */
#else
#define FIX_0_211164243 FIX(0.211164243)
#define FIX_0_509795579 FIX(0.509795579)
@@ -98,9 +98,9 @@
*/
#if BITS_IN_JSAMPLE == 8
-#define MULTIPLY(var,const) MULTIPLY16C16(var,const)
+#define MULTIPLY(var, const) MULTIPLY16C16(var, const)
#else
-#define MULTIPLY(var,const) ((var) * (const))
+#define MULTIPLY(var, const) ((var) * (const))
#endif
@@ -109,7 +109,7 @@
* are 16 bits or less, so either int or short multiply will work.
*/
-#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval))
+#define DEQUANTIZE(coef, quantval) (((ISLOW_MULT_TYPE)(coef)) * (quantval))
/*
@@ -118,9 +118,9 @@
*/
GLOBAL(void)
-jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_4x4(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp0, tmp2, tmp10, tmp12;
JLONG z1, z2, z3, z4;
@@ -130,69 +130,73 @@ jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[DCTSIZE*4]; /* buffers data between passes */
+ int workspace[DCTSIZE * 4]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) {
/* Don't bother to process column 4, because second pass won't use it */
- if (ctr == DCTSIZE-4)
+ if (ctr == DCTSIZE - 4)
continue;
- if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
- inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*5] == 0 &&
- inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) {
+ if (inptr[DCTSIZE * 1] == 0 && inptr[DCTSIZE * 2] == 0 &&
+ inptr[DCTSIZE * 3] == 0 && inptr[DCTSIZE * 5] == 0 &&
+ inptr[DCTSIZE * 6] == 0 && inptr[DCTSIZE * 7] == 0) {
/* AC terms all zero; we need not examine term 4 for 4x4 output */
- int dcval = LEFT_SHIFT(DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]),
- PASS1_BITS);
+ int dcval = LEFT_SHIFT(DEQUANTIZE(inptr[DCTSIZE * 0],
+ quantptr[DCTSIZE * 0]), PASS1_BITS);
- wsptr[DCTSIZE*0] = dcval;
- wsptr[DCTSIZE*1] = dcval;
- wsptr[DCTSIZE*2] = dcval;
- wsptr[DCTSIZE*3] = dcval;
+ wsptr[DCTSIZE * 0] = dcval;
+ wsptr[DCTSIZE * 1] = dcval;
+ wsptr[DCTSIZE * 2] = dcval;
+ wsptr[DCTSIZE * 3] = dcval;
continue;
}
/* Even part */
- tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
- tmp0 = LEFT_SHIFT(tmp0, CONST_BITS+1);
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
+ tmp0 = LEFT_SHIFT(tmp0, CONST_BITS + 1);
- z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]);
- tmp2 = MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, - FIX_0_765366865);
+ tmp2 = MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, -FIX_0_765366865);
tmp10 = tmp0 + tmp2;
tmp12 = tmp0 - tmp2;
/* Odd part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
- z2 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
- z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- z4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
- tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */
- + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */
- + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */
- + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */
+ tmp0 = MULTIPLY(z1, -FIX_0_211164243) + /* sqrt(2) * ( c3-c1) */
+ MULTIPLY(z2, FIX_1_451774981) + /* sqrt(2) * ( c3+c7) */
+ MULTIPLY(z3, -FIX_2_172734803) + /* sqrt(2) * (-c1-c5) */
+ MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * ( c5+c7) */
- tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */
- + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */
- + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */
- + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */
+ tmp2 = MULTIPLY(z1, -FIX_0_509795579) + /* sqrt(2) * (c7-c5) */
+ MULTIPLY(z2, -FIX_0_601344887) + /* sqrt(2) * (c5-c1) */
+ MULTIPLY(z3, FIX_0_899976223) + /* sqrt(2) * (c3-c7) */
+ MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */
/* Final output stage */
- wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp2, CONST_BITS-PASS1_BITS+1);
- wsptr[DCTSIZE*3] = (int) DESCALE(tmp10 - tmp2, CONST_BITS-PASS1_BITS+1);
- wsptr[DCTSIZE*1] = (int) DESCALE(tmp12 + tmp0, CONST_BITS-PASS1_BITS+1);
- wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 - tmp0, CONST_BITS-PASS1_BITS+1);
+ wsptr[DCTSIZE * 0] =
+ (int)DESCALE(tmp10 + tmp2, CONST_BITS - PASS1_BITS + 1);
+ wsptr[DCTSIZE * 3] =
+ (int)DESCALE(tmp10 - tmp2, CONST_BITS - PASS1_BITS + 1);
+ wsptr[DCTSIZE * 1] =
+ (int)DESCALE(tmp12 + tmp0, CONST_BITS - PASS1_BITS + 1);
+ wsptr[DCTSIZE * 2] =
+ (int)DESCALE(tmp12 - tmp0, CONST_BITS - PASS1_BITS + 1);
}
/* Pass 2: process 4 rows from work array, store into output array. */
@@ -206,8 +210,8 @@ jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 &&
wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) {
/* AC terms all zero */
- JSAMPLE dcval = range_limit[(int) DESCALE((JLONG) wsptr[0], PASS1_BITS+3)
- & RANGE_MASK];
+ JSAMPLE dcval = range_limit[(int)DESCALE((JLONG)wsptr[0],
+ PASS1_BITS + 3) & RANGE_MASK];
outptr[0] = dcval;
outptr[1] = dcval;
@@ -221,45 +225,45 @@ jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Even part */
- tmp0 = LEFT_SHIFT((JLONG) wsptr[0], CONST_BITS+1);
+ tmp0 = LEFT_SHIFT((JLONG)wsptr[0], CONST_BITS + 1);
- tmp2 = MULTIPLY((JLONG) wsptr[2], FIX_1_847759065)
- + MULTIPLY((JLONG) wsptr[6], - FIX_0_765366865);
+ tmp2 = MULTIPLY((JLONG)wsptr[2], FIX_1_847759065) +
+ MULTIPLY((JLONG)wsptr[6], -FIX_0_765366865);
tmp10 = tmp0 + tmp2;
tmp12 = tmp0 - tmp2;
/* Odd part */
- z1 = (JLONG) wsptr[7];
- z2 = (JLONG) wsptr[5];
- z3 = (JLONG) wsptr[3];
- z4 = (JLONG) wsptr[1];
+ z1 = (JLONG)wsptr[7];
+ z2 = (JLONG)wsptr[5];
+ z3 = (JLONG)wsptr[3];
+ z4 = (JLONG)wsptr[1];
- tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */
- + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */
- + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */
- + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */
+ tmp0 = MULTIPLY(z1, -FIX_0_211164243) + /* sqrt(2) * ( c3-c1) */
+ MULTIPLY(z2, FIX_1_451774981) + /* sqrt(2) * ( c3+c7) */
+ MULTIPLY(z3, -FIX_2_172734803) + /* sqrt(2) * (-c1-c5) */
+ MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * ( c5+c7) */
- tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */
- + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */
- + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */
- + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */
+ tmp2 = MULTIPLY(z1, -FIX_0_509795579) + /* sqrt(2) * (c7-c5) */
+ MULTIPLY(z2, -FIX_0_601344887) + /* sqrt(2) * (c5-c1) */
+ MULTIPLY(z3, FIX_0_899976223) + /* sqrt(2) * (c3-c7) */
+ MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */
/* Final output stage */
- outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp2,
- CONST_BITS+PASS1_BITS+3+1)
- & RANGE_MASK];
- outptr[3] = range_limit[(int) DESCALE(tmp10 - tmp2,
- CONST_BITS+PASS1_BITS+3+1)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) DESCALE(tmp12 + tmp0,
- CONST_BITS+PASS1_BITS+3+1)
- & RANGE_MASK];
- outptr[2] = range_limit[(int) DESCALE(tmp12 - tmp0,
- CONST_BITS+PASS1_BITS+3+1)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)DESCALE(tmp10 + tmp2,
+ CONST_BITS + PASS1_BITS + 3 + 1) &
+ RANGE_MASK];
+ outptr[3] = range_limit[(int)DESCALE(tmp10 - tmp2,
+ CONST_BITS + PASS1_BITS + 3 + 1) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)DESCALE(tmp12 + tmp0,
+ CONST_BITS + PASS1_BITS + 3 + 1) &
+ RANGE_MASK];
+ outptr[2] = range_limit[(int)DESCALE(tmp12 - tmp0,
+ CONST_BITS + PASS1_BITS + 3 + 1) &
+ RANGE_MASK];
wsptr += DCTSIZE; /* advance pointer to next row */
}
@@ -272,9 +276,9 @@ jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
*/
GLOBAL(void)
-jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_2x2(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
JLONG tmp0, tmp10, z1;
JCOEFPTR inptr;
@@ -283,50 +287,52 @@ jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
int ctr;
- int workspace[DCTSIZE*2]; /* buffers data between passes */
+ int workspace[DCTSIZE * 2]; /* buffers data between passes */
SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array. */
inptr = coef_block;
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
wsptr = workspace;
for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) {
/* Don't bother to process columns 2,4,6 */
- if (ctr == DCTSIZE-2 || ctr == DCTSIZE-4 || ctr == DCTSIZE-6)
+ if (ctr == DCTSIZE - 2 || ctr == DCTSIZE - 4 || ctr == DCTSIZE - 6)
continue;
- if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*3] == 0 &&
- inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*7] == 0) {
+ if (inptr[DCTSIZE * 1] == 0 && inptr[DCTSIZE * 3] == 0 &&
+ inptr[DCTSIZE * 5] == 0 && inptr[DCTSIZE * 7] == 0) {
/* AC terms all zero; we need not examine terms 2,4,6 for 2x2 output */
- int dcval = LEFT_SHIFT(DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]),
- PASS1_BITS);
+ int dcval = LEFT_SHIFT(DEQUANTIZE(inptr[DCTSIZE * 0],
+ quantptr[DCTSIZE * 0]), PASS1_BITS);
- wsptr[DCTSIZE*0] = dcval;
- wsptr[DCTSIZE*1] = dcval;
+ wsptr[DCTSIZE * 0] = dcval;
+ wsptr[DCTSIZE * 1] = dcval;
continue;
}
/* Even part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
- tmp10 = LEFT_SHIFT(z1, CONST_BITS+2);
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]);
+ tmp10 = LEFT_SHIFT(z1, CONST_BITS + 2);
/* Odd part */
- z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
- tmp0 = MULTIPLY(z1, - FIX_0_720959822); /* sqrt(2) * (c7-c5+c3-c1) */
- z1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
- tmp0 += MULTIPLY(z1, FIX_0_850430095); /* sqrt(2) * (-c1+c3+c5+c7) */
- z1 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
- tmp0 += MULTIPLY(z1, - FIX_1_272758580); /* sqrt(2) * (-c1+c3-c5-c7) */
- z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
- tmp0 += MULTIPLY(z1, FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]);
+ tmp0 = MULTIPLY(z1, -FIX_0_720959822); /* sqrt(2) * ( c7-c5+c3-c1) */
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]);
+ tmp0 += MULTIPLY(z1, FIX_0_850430095); /* sqrt(2) * (-c1+c3+c5+c7) */
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]);
+ tmp0 += MULTIPLY(z1, -FIX_1_272758580); /* sqrt(2) * (-c1+c3-c5-c7) */
+ z1 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]);
+ tmp0 += MULTIPLY(z1, FIX_3_624509785); /* sqrt(2) * ( c1+c3+c5+c7) */
/* Final output stage */
- wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp0, CONST_BITS-PASS1_BITS+2);
- wsptr[DCTSIZE*1] = (int) DESCALE(tmp10 - tmp0, CONST_BITS-PASS1_BITS+2);
+ wsptr[DCTSIZE * 0] =
+ (int)DESCALE(tmp10 + tmp0, CONST_BITS - PASS1_BITS + 2);
+ wsptr[DCTSIZE * 1] =
+ (int)DESCALE(tmp10 - tmp0, CONST_BITS - PASS1_BITS + 2);
}
/* Pass 2: process 2 rows from work array, store into output array. */
@@ -339,8 +345,8 @@ jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
#ifndef NO_ZERO_ROW_TEST
if (wsptr[1] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[7] == 0) {
/* AC terms all zero */
- JSAMPLE dcval = range_limit[(int) DESCALE((JLONG) wsptr[0], PASS1_BITS+3)
- & RANGE_MASK];
+ JSAMPLE dcval = range_limit[(int)DESCALE((JLONG)wsptr[0],
+ PASS1_BITS + 3) & RANGE_MASK];
outptr[0] = dcval;
outptr[1] = dcval;
@@ -352,23 +358,23 @@ jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* Even part */
- tmp10 = LEFT_SHIFT((JLONG) wsptr[0], CONST_BITS+2);
+ tmp10 = LEFT_SHIFT((JLONG)wsptr[0], CONST_BITS + 2);
/* Odd part */
- tmp0 = MULTIPLY((JLONG) wsptr[7], - FIX_0_720959822) /* sqrt(2) * (c7-c5+c3-c1) */
- + MULTIPLY((JLONG) wsptr[5], FIX_0_850430095) /* sqrt(2) * (-c1+c3+c5+c7) */
- + MULTIPLY((JLONG) wsptr[3], - FIX_1_272758580) /* sqrt(2) * (-c1+c3-c5-c7) */
- + MULTIPLY((JLONG) wsptr[1], FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */
+ tmp0 = MULTIPLY((JLONG)wsptr[7], -FIX_0_720959822) + /* sqrt(2) * ( c7-c5+c3-c1) */
+ MULTIPLY((JLONG)wsptr[5], FIX_0_850430095) + /* sqrt(2) * (-c1+c3+c5+c7) */
+ MULTIPLY((JLONG)wsptr[3], -FIX_1_272758580) + /* sqrt(2) * (-c1+c3-c5-c7) */
+ MULTIPLY((JLONG)wsptr[1], FIX_3_624509785); /* sqrt(2) * ( c1+c3+c5+c7) */
/* Final output stage */
- outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp0,
- CONST_BITS+PASS1_BITS+3+2)
- & RANGE_MASK];
- outptr[1] = range_limit[(int) DESCALE(tmp10 - tmp0,
- CONST_BITS+PASS1_BITS+3+2)
- & RANGE_MASK];
+ outptr[0] = range_limit[(int)DESCALE(tmp10 + tmp0,
+ CONST_BITS + PASS1_BITS + 3 + 2) &
+ RANGE_MASK];
+ outptr[1] = range_limit[(int)DESCALE(tmp10 - tmp0,
+ CONST_BITS + PASS1_BITS + 3 + 2) &
+ RANGE_MASK];
wsptr += DCTSIZE; /* advance pointer to next row */
}
@@ -381,9 +387,9 @@ jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
*/
GLOBAL(void)
-jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block,
- JSAMPARRAY output_buf, JDIMENSION output_col)
+jpeg_idct_1x1(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
int dcval;
ISLOW_MULT_TYPE *quantptr;
@@ -393,9 +399,9 @@ jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
/* We hardly need an inverse DCT routine for this: just take the
* average pixel value, which is one-eighth of the DC coefficient.
*/
- quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ quantptr = (ISLOW_MULT_TYPE *)compptr->dct_table;
dcval = DEQUANTIZE(coef_block[0], quantptr[0]);
- dcval = (int) DESCALE((JLONG) dcval, 3);
+ dcval = (int)DESCALE((JLONG)dcval, 3);
output_buf[0][output_col] = range_limit[dcval & RANGE_MASK];
}
diff --git a/src/3rdparty/libjpeg/src/jinclude.h b/src/3rdparty/libjpeg/src/jinclude.h
index d461a1aa16..c1bcf7d9da 100644
--- a/src/3rdparty/libjpeg/src/jinclude.h
+++ b/src/3rdparty/libjpeg/src/jinclude.h
@@ -61,14 +61,18 @@
#ifdef NEED_BSD_STRINGS
#include <strings.h>
-#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size))
-#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size))
+#define MEMZERO(target, size) \
+ bzero((void *)(target), (size_t)(size))
+#define MEMCOPY(dest, src, size) \
+ bcopy((const void *)(src), (void *)(dest), (size_t)(size))
#else /* not BSD, assume ANSI/SysV string lib */
#include <string.h>
-#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size))
-#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size))
+#define MEMZERO(target, size) \
+ memset((void *)(target), 0, (size_t)(size))
+#define MEMCOPY(dest, src, size) \
+ memcpy((void *)(dest), (const void *)(src), (size_t)(size))
#endif
@@ -78,7 +82,7 @@
* CAUTION: argument order is different from underlying functions!
*/
-#define JFREAD(file,buf,sizeofbuf) \
- ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
-#define JFWRITE(file,buf,sizeofbuf) \
- ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
+#define JFREAD(file, buf, sizeofbuf) \
+ ((size_t)fread((void *)(buf), (size_t)1, (size_t)(sizeofbuf), (file)))
+#define JFWRITE(file, buf, sizeofbuf) \
+ ((size_t)fwrite((const void *)(buf), (size_t)1, (size_t)(sizeofbuf), (file)))
diff --git a/src/3rdparty/libjpeg/src/jmemmgr.c b/src/3rdparty/libjpeg/src/jmemmgr.c
index 8dfb633dae..508ca7429c 100644
--- a/src/3rdparty/libjpeg/src/jmemmgr.c
+++ b/src/3rdparty/libjpeg/src/jmemmgr.c
@@ -32,20 +32,20 @@
#include "jinclude.h"
#include "jpeglib.h"
#include "jmemsys.h" /* import the system-dependent declarations */
-#ifndef _WIN32
+#if !defined(_MSC_VER) || _MSC_VER > 1600
#include <stdint.h>
#endif
#include <limits.h>
#ifndef NO_GETENV
#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare getenv() */
-extern char *getenv (const char *name);
+extern char *getenv(const char *name);
#endif
#endif
LOCAL(size_t)
-round_up_pow2 (size_t a, size_t b)
+round_up_pow2(size_t a, size_t b)
/* a rounded up to the next multiple of b, i.e. ceil(a/b)*b */
/* Assumes a >= 0, b > 0, and b is a power of 2 */
{
@@ -89,7 +89,9 @@ round_up_pow2 (size_t a, size_t b)
#ifndef WITH_SIMD
#define ALIGN_SIZE sizeof(double)
#else
-#define ALIGN_SIZE 16 /* Most SIMD implementations require this */
+#define ALIGN_SIZE 32 /* Most of the SIMD instructions we support require
+ 16-byte (128-bit) alignment, but AVX2 requires
+ 32-byte alignment. */
#endif
#endif
@@ -104,7 +106,7 @@ round_up_pow2 (size_t a, size_t b)
typedef struct small_pool_struct *small_pool_ptr;
typedef struct small_pool_struct {
- small_pool_ptr next; /* next in list of pools */
+ small_pool_ptr next; /* next in list of pools */
size_t bytes_used; /* how many bytes already used within pool */
size_t bytes_left; /* bytes still available in this pool */
} small_pool_hdr;
@@ -112,7 +114,7 @@ typedef struct small_pool_struct {
typedef struct large_pool_struct *large_pool_ptr;
typedef struct large_pool_struct {
- large_pool_ptr next; /* next in list of pools */
+ large_pool_ptr next; /* next in list of pools */
size_t bytes_used; /* how many bytes already used within pool */
size_t bytes_left; /* bytes still available in this pool */
} large_pool_hdr;
@@ -191,9 +193,9 @@ struct jvirt_barray_control {
#ifdef MEM_STATS /* optional extra stuff for statistics */
LOCAL(void)
-print_mem_stats (j_common_ptr cinfo, int pool_id)
+print_mem_stats(j_common_ptr cinfo, int pool_id)
{
- my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ my_mem_ptr mem = (my_mem_ptr)cinfo->mem;
small_pool_ptr shdr_ptr;
large_pool_ptr lhdr_ptr;
@@ -206,15 +208,13 @@ print_mem_stats (j_common_ptr cinfo, int pool_id)
for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL;
lhdr_ptr = lhdr_ptr->next) {
- fprintf(stderr, " Large chunk used %ld\n",
- (long) lhdr_ptr->bytes_used);
+ fprintf(stderr, " Large chunk used %ld\n", (long)lhdr_ptr->bytes_used);
}
for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL;
shdr_ptr = shdr_ptr->next) {
fprintf(stderr, " Small chunk used %ld free %ld\n",
- (long) shdr_ptr->bytes_used,
- (long) shdr_ptr->bytes_left);
+ (long)shdr_ptr->bytes_used, (long)shdr_ptr->bytes_left);
}
}
@@ -222,7 +222,7 @@ print_mem_stats (j_common_ptr cinfo, int pool_id)
LOCAL(void)
-out_of_memory (j_common_ptr cinfo, int which)
+out_of_memory(j_common_ptr cinfo, int which)
/* Report an out-of-memory error and stop execution */
/* If we compiled MEM_STATS support, report alloc requests before dying */
{
@@ -250,26 +250,24 @@ out_of_memory (j_common_ptr cinfo, int which)
* adjustment.
*/
-static const size_t first_pool_slop[JPOOL_NUMPOOLS] =
-{
- 1600, /* first PERMANENT pool */
- 16000 /* first IMAGE pool */
+static const size_t first_pool_slop[JPOOL_NUMPOOLS] = {
+ 1600, /* first PERMANENT pool */
+ 16000 /* first IMAGE pool */
};
-static const size_t extra_pool_slop[JPOOL_NUMPOOLS] =
-{
- 0, /* additional PERMANENT pools */
- 5000 /* additional IMAGE pools */
+static const size_t extra_pool_slop[JPOOL_NUMPOOLS] = {
+ 0, /* additional PERMANENT pools */
+ 5000 /* additional IMAGE pools */
};
#define MIN_SLOP 50 /* greater than 0 to avoid futile looping */
METHODDEF(void *)
-alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
+alloc_small(j_common_ptr cinfo, int pool_id, size_t sizeofobject)
/* Allocate a "small" object */
{
- my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ my_mem_ptr mem = (my_mem_ptr)cinfo->mem;
small_pool_ptr hdr_ptr, prev_hdr_ptr;
char *data_ptr;
size_t min_request, slop;
@@ -313,11 +311,11 @@ alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
else
slop = extra_pool_slop[pool_id];
/* Don't ask for more than MAX_ALLOC_CHUNK */
- if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request))
- slop = (size_t) (MAX_ALLOC_CHUNK-min_request);
+ if (slop > (size_t)(MAX_ALLOC_CHUNK - min_request))
+ slop = (size_t)(MAX_ALLOC_CHUNK - min_request);
/* Try to get space, if fail reduce slop and try again */
for (;;) {
- hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop);
+ hdr_ptr = (small_pool_ptr)jpeg_get_small(cinfo, min_request + slop);
if (hdr_ptr != NULL)
break;
slop /= 2;
@@ -336,7 +334,7 @@ alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
}
/* OK, allocate the object from the current pool */
- data_ptr = (char *) hdr_ptr; /* point to first data byte in pool... */
+ data_ptr = (char *)hdr_ptr; /* point to first data byte in pool... */
data_ptr += sizeof(small_pool_hdr); /* ...by skipping the header... */
if ((size_t)data_ptr % ALIGN_SIZE) /* ...and adjust for alignment */
data_ptr += ALIGN_SIZE - (size_t)data_ptr % ALIGN_SIZE;
@@ -344,7 +342,7 @@ alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
hdr_ptr->bytes_used += sizeofobject;
hdr_ptr->bytes_left -= sizeofobject;
- return (void *) data_ptr;
+ return (void *)data_ptr;
}
@@ -362,10 +360,10 @@ alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
*/
METHODDEF(void *)
-alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
+alloc_large(j_common_ptr cinfo, int pool_id, size_t sizeofobject)
/* Allocate a "large" object */
{
- my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ my_mem_ptr mem = (my_mem_ptr)cinfo->mem;
large_pool_ptr hdr_ptr;
char *data_ptr;
@@ -390,9 +388,9 @@ alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
- hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject +
- sizeof(large_pool_hdr) +
- ALIGN_SIZE - 1);
+ hdr_ptr = (large_pool_ptr)jpeg_get_large(cinfo, sizeofobject +
+ sizeof(large_pool_hdr) +
+ ALIGN_SIZE - 1);
if (hdr_ptr == NULL)
out_of_memory(cinfo, 4); /* jpeg_get_large failed */
mem->total_space_allocated += sizeofobject + sizeof(large_pool_hdr) +
@@ -407,12 +405,12 @@ alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
hdr_ptr->bytes_left = 0;
mem->large_list[pool_id] = hdr_ptr;
- data_ptr = (char *) hdr_ptr; /* point to first data byte in pool... */
+ data_ptr = (char *)hdr_ptr; /* point to first data byte in pool... */
data_ptr += sizeof(small_pool_hdr); /* ...by skipping the header... */
if ((size_t)data_ptr % ALIGN_SIZE) /* ...and adjust for alignment */
data_ptr += ALIGN_SIZE - (size_t)data_ptr % ALIGN_SIZE;
- return (void *) data_ptr;
+ return (void *)data_ptr;
}
@@ -433,11 +431,11 @@ alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
*/
METHODDEF(JSAMPARRAY)
-alloc_sarray (j_common_ptr cinfo, int pool_id,
- JDIMENSION samplesperrow, JDIMENSION numrows)
+alloc_sarray(j_common_ptr cinfo, int pool_id, JDIMENSION samplesperrow,
+ JDIMENSION numrows)
/* Allocate a 2-D sample array */
{
- my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ my_mem_ptr mem = (my_mem_ptr)cinfo->mem;
JSAMPARRAY result;
JSAMPROW workspace;
JDIMENSION rowsperchunk, currow, i;
@@ -456,27 +454,27 @@ alloc_sarray (j_common_ptr cinfo, int pool_id,
sizeof(JSAMPLE));
/* Calculate max # of rows allowed in one allocation chunk */
- ltemp = (MAX_ALLOC_CHUNK-sizeof(large_pool_hdr)) /
- ((long) samplesperrow * sizeof(JSAMPLE));
+ ltemp = (MAX_ALLOC_CHUNK - sizeof(large_pool_hdr)) /
+ ((long)samplesperrow * sizeof(JSAMPLE));
if (ltemp <= 0)
ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
- if (ltemp < (long) numrows)
- rowsperchunk = (JDIMENSION) ltemp;
+ if (ltemp < (long)numrows)
+ rowsperchunk = (JDIMENSION)ltemp;
else
rowsperchunk = numrows;
mem->last_rowsperchunk = rowsperchunk;
/* Get space for row pointers (small object) */
- result = (JSAMPARRAY) alloc_small(cinfo, pool_id,
- (size_t) (numrows * sizeof(JSAMPROW)));
+ result = (JSAMPARRAY)alloc_small(cinfo, pool_id,
+ (size_t)(numrows * sizeof(JSAMPROW)));
/* Get the rows themselves (large objects) */
currow = 0;
while (currow < numrows) {
rowsperchunk = MIN(rowsperchunk, numrows - currow);
- workspace = (JSAMPROW) alloc_large(cinfo, pool_id,
- (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow
- * sizeof(JSAMPLE)));
+ workspace = (JSAMPROW)alloc_large(cinfo, pool_id,
+ (size_t)((size_t)rowsperchunk * (size_t)samplesperrow *
+ sizeof(JSAMPLE)));
for (i = rowsperchunk; i > 0; i--) {
result[currow++] = workspace;
workspace += samplesperrow;
@@ -493,11 +491,11 @@ alloc_sarray (j_common_ptr cinfo, int pool_id,
*/
METHODDEF(JBLOCKARRAY)
-alloc_barray (j_common_ptr cinfo, int pool_id,
- JDIMENSION blocksperrow, JDIMENSION numrows)
+alloc_barray(j_common_ptr cinfo, int pool_id, JDIMENSION blocksperrow,
+ JDIMENSION numrows)
/* Allocate a 2-D coefficient-block array */
{
- my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ my_mem_ptr mem = (my_mem_ptr)cinfo->mem;
JBLOCKARRAY result;
JBLOCKROW workspace;
JDIMENSION rowsperchunk, currow, i;
@@ -508,27 +506,27 @@ alloc_barray (j_common_ptr cinfo, int pool_id,
out_of_memory(cinfo, 6); /* safety check */
/* Calculate max # of rows allowed in one allocation chunk */
- ltemp = (MAX_ALLOC_CHUNK-sizeof(large_pool_hdr)) /
- ((long) blocksperrow * sizeof(JBLOCK));
+ ltemp = (MAX_ALLOC_CHUNK - sizeof(large_pool_hdr)) /
+ ((long)blocksperrow * sizeof(JBLOCK));
if (ltemp <= 0)
ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
- if (ltemp < (long) numrows)
- rowsperchunk = (JDIMENSION) ltemp;
+ if (ltemp < (long)numrows)
+ rowsperchunk = (JDIMENSION)ltemp;
else
rowsperchunk = numrows;
mem->last_rowsperchunk = rowsperchunk;
/* Get space for row pointers (small object) */
- result = (JBLOCKARRAY) alloc_small(cinfo, pool_id,
- (size_t) (numrows * sizeof(JBLOCKROW)));
+ result = (JBLOCKARRAY)alloc_small(cinfo, pool_id,
+ (size_t)(numrows * sizeof(JBLOCKROW)));
/* Get the rows themselves (large objects) */
currow = 0;
while (currow < numrows) {
rowsperchunk = MIN(rowsperchunk, numrows - currow);
- workspace = (JBLOCKROW) alloc_large(cinfo, pool_id,
- (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow
- * sizeof(JBLOCK)));
+ workspace = (JBLOCKROW)alloc_large(cinfo, pool_id,
+ (size_t)((size_t)rowsperchunk * (size_t)blocksperrow *
+ sizeof(JBLOCK)));
for (i = rowsperchunk; i > 0; i--) {
result[currow++] = workspace;
workspace += blocksperrow;
@@ -577,12 +575,12 @@ alloc_barray (j_common_ptr cinfo, int pool_id,
METHODDEF(jvirt_sarray_ptr)
-request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
- JDIMENSION samplesperrow, JDIMENSION numrows,
- JDIMENSION maxaccess)
+request_virt_sarray(j_common_ptr cinfo, int pool_id, boolean pre_zero,
+ JDIMENSION samplesperrow, JDIMENSION numrows,
+ JDIMENSION maxaccess)
/* Request a virtual 2-D sample array */
{
- my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ my_mem_ptr mem = (my_mem_ptr)cinfo->mem;
jvirt_sarray_ptr result;
/* Only IMAGE-lifetime virtual arrays are currently supported */
@@ -590,8 +588,8 @@ request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
/* get control block */
- result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id,
- sizeof(struct jvirt_sarray_control));
+ result = (jvirt_sarray_ptr)alloc_small(cinfo, pool_id,
+ sizeof(struct jvirt_sarray_control));
result->mem_buffer = NULL; /* marks array not yet realized */
result->rows_in_array = numrows;
@@ -607,12 +605,12 @@ request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
METHODDEF(jvirt_barray_ptr)
-request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
- JDIMENSION blocksperrow, JDIMENSION numrows,
- JDIMENSION maxaccess)
+request_virt_barray(j_common_ptr cinfo, int pool_id, boolean pre_zero,
+ JDIMENSION blocksperrow, JDIMENSION numrows,
+ JDIMENSION maxaccess)
/* Request a virtual 2-D coefficient-block array */
{
- my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ my_mem_ptr mem = (my_mem_ptr)cinfo->mem;
jvirt_barray_ptr result;
/* Only IMAGE-lifetime virtual arrays are currently supported */
@@ -620,8 +618,8 @@ request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
/* get control block */
- result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id,
- sizeof(struct jvirt_barray_control));
+ result = (jvirt_barray_ptr)alloc_small(cinfo, pool_id,
+ sizeof(struct jvirt_barray_control));
result->mem_buffer = NULL; /* marks array not yet realized */
result->rows_in_array = numrows;
@@ -637,10 +635,10 @@ request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
METHODDEF(void)
-realize_virt_arrays (j_common_ptr cinfo)
+realize_virt_arrays(j_common_ptr cinfo)
/* Allocate the in-memory buffers for any unrealized virtual arrays */
{
- my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ my_mem_ptr mem = (my_mem_ptr)cinfo->mem;
size_t space_per_minheight, maximum_space, avail_mem;
size_t minheights, max_minheights;
jvirt_sarray_ptr sptr;
@@ -654,11 +652,11 @@ realize_virt_arrays (j_common_ptr cinfo)
maximum_space = 0;
for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
if (sptr->mem_buffer == NULL) { /* if not realized yet */
- size_t new_space = (long) sptr->rows_in_array *
- (long) sptr->samplesperrow * sizeof(JSAMPLE);
+ size_t new_space = (long)sptr->rows_in_array *
+ (long)sptr->samplesperrow * sizeof(JSAMPLE);
- space_per_minheight += (long) sptr->maxaccess *
- (long) sptr->samplesperrow * sizeof(JSAMPLE);
+ space_per_minheight += (long)sptr->maxaccess *
+ (long)sptr->samplesperrow * sizeof(JSAMPLE);
if (SIZE_MAX - maximum_space < new_space)
out_of_memory(cinfo, 10);
maximum_space += new_space;
@@ -666,11 +664,11 @@ realize_virt_arrays (j_common_ptr cinfo)
}
for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
if (bptr->mem_buffer == NULL) { /* if not realized yet */
- size_t new_space = (long) bptr->rows_in_array *
- (long) bptr->blocksperrow * sizeof(JBLOCK);
+ size_t new_space = (long)bptr->rows_in_array *
+ (long)bptr->blocksperrow * sizeof(JBLOCK);
- space_per_minheight += (long) bptr->maxaccess *
- (long) bptr->blocksperrow * sizeof(JBLOCK);
+ space_per_minheight += (long)bptr->maxaccess *
+ (long)bptr->blocksperrow * sizeof(JBLOCK);
if (SIZE_MAX - maximum_space < new_space)
out_of_memory(cinfo, 11);
maximum_space += new_space;
@@ -703,17 +701,17 @@ realize_virt_arrays (j_common_ptr cinfo)
for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
if (sptr->mem_buffer == NULL) { /* if not realized yet */
- minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L;
+ minheights = ((long)sptr->rows_in_array - 1L) / sptr->maxaccess + 1L;
if (minheights <= max_minheights) {
/* This buffer fits in memory */
sptr->rows_in_mem = sptr->rows_in_array;
} else {
/* It doesn't fit in memory, create backing store. */
- sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess);
- jpeg_open_backing_store(cinfo, & sptr->b_s_info,
- (long) sptr->rows_in_array *
- (long) sptr->samplesperrow *
- (long) sizeof(JSAMPLE));
+ sptr->rows_in_mem = (JDIMENSION)(max_minheights * sptr->maxaccess);
+ jpeg_open_backing_store(cinfo, &sptr->b_s_info,
+ (long)sptr->rows_in_array *
+ (long)sptr->samplesperrow *
+ (long)sizeof(JSAMPLE));
sptr->b_s_open = TRUE;
}
sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE,
@@ -727,17 +725,17 @@ realize_virt_arrays (j_common_ptr cinfo)
for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
if (bptr->mem_buffer == NULL) { /* if not realized yet */
- minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L;
+ minheights = ((long)bptr->rows_in_array - 1L) / bptr->maxaccess + 1L;
if (minheights <= max_minheights) {
/* This buffer fits in memory */
bptr->rows_in_mem = bptr->rows_in_array;
} else {
/* It doesn't fit in memory, create backing store. */
- bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess);
- jpeg_open_backing_store(cinfo, & bptr->b_s_info,
- (long) bptr->rows_in_array *
- (long) bptr->blocksperrow *
- (long) sizeof(JBLOCK));
+ bptr->rows_in_mem = (JDIMENSION)(max_minheights * bptr->maxaccess);
+ jpeg_open_backing_store(cinfo, &bptr->b_s_info,
+ (long)bptr->rows_in_array *
+ (long)bptr->blocksperrow *
+ (long)sizeof(JBLOCK));
bptr->b_s_open = TRUE;
}
bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE,
@@ -752,32 +750,32 @@ realize_virt_arrays (j_common_ptr cinfo)
LOCAL(void)
-do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing)
+do_sarray_io(j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing)
/* Do backing store read or write of a virtual sample array */
{
long bytesperrow, file_offset, byte_count, rows, thisrow, i;
- bytesperrow = (long) ptr->samplesperrow * sizeof(JSAMPLE);
+ bytesperrow = (long)ptr->samplesperrow * sizeof(JSAMPLE);
file_offset = ptr->cur_start_row * bytesperrow;
/* Loop to read or write each allocation chunk in mem_buffer */
- for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) {
+ for (i = 0; i < (long)ptr->rows_in_mem; i += ptr->rowsperchunk) {
/* One chunk, but check for short chunk at end of buffer */
- rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i);
+ rows = MIN((long)ptr->rowsperchunk, (long)ptr->rows_in_mem - i);
/* Transfer no more than is currently defined */
- thisrow = (long) ptr->cur_start_row + i;
- rows = MIN(rows, (long) ptr->first_undef_row - thisrow);
+ thisrow = (long)ptr->cur_start_row + i;
+ rows = MIN(rows, (long)ptr->first_undef_row - thisrow);
/* Transfer no more than fits in file */
- rows = MIN(rows, (long) ptr->rows_in_array - thisrow);
+ rows = MIN(rows, (long)ptr->rows_in_array - thisrow);
if (rows <= 0) /* this chunk might be past end of file! */
break;
byte_count = rows * bytesperrow;
if (writing)
- (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info,
- (void *) ptr->mem_buffer[i],
+ (*ptr->b_s_info.write_backing_store) (cinfo, &ptr->b_s_info,
+ (void *)ptr->mem_buffer[i],
file_offset, byte_count);
else
- (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info,
- (void *) ptr->mem_buffer[i],
+ (*ptr->b_s_info.read_backing_store) (cinfo, &ptr->b_s_info,
+ (void *)ptr->mem_buffer[i],
file_offset, byte_count);
file_offset += byte_count;
}
@@ -785,32 +783,32 @@ do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing)
LOCAL(void)
-do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing)
+do_barray_io(j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing)
/* Do backing store read or write of a virtual coefficient-block array */
{
long bytesperrow, file_offset, byte_count, rows, thisrow, i;
- bytesperrow = (long) ptr->blocksperrow * sizeof(JBLOCK);
+ bytesperrow = (long)ptr->blocksperrow * sizeof(JBLOCK);
file_offset = ptr->cur_start_row * bytesperrow;
/* Loop to read or write each allocation chunk in mem_buffer */
- for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) {
+ for (i = 0; i < (long)ptr->rows_in_mem; i += ptr->rowsperchunk) {
/* One chunk, but check for short chunk at end of buffer */
- rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i);
+ rows = MIN((long)ptr->rowsperchunk, (long)ptr->rows_in_mem - i);
/* Transfer no more than is currently defined */
- thisrow = (long) ptr->cur_start_row + i;
- rows = MIN(rows, (long) ptr->first_undef_row - thisrow);
+ thisrow = (long)ptr->cur_start_row + i;
+ rows = MIN(rows, (long)ptr->first_undef_row - thisrow);
/* Transfer no more than fits in file */
- rows = MIN(rows, (long) ptr->rows_in_array - thisrow);
+ rows = MIN(rows, (long)ptr->rows_in_array - thisrow);
if (rows <= 0) /* this chunk might be past end of file! */
break;
byte_count = rows * bytesperrow;
if (writing)
- (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info,
- (void *) ptr->mem_buffer[i],
+ (*ptr->b_s_info.write_backing_store) (cinfo, &ptr->b_s_info,
+ (void *)ptr->mem_buffer[i],
file_offset, byte_count);
else
- (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info,
- (void *) ptr->mem_buffer[i],
+ (*ptr->b_s_info.read_backing_store) (cinfo, &ptr->b_s_info,
+ (void *)ptr->mem_buffer[i],
file_offset, byte_count);
file_offset += byte_count;
}
@@ -818,9 +816,8 @@ do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing)
METHODDEF(JSAMPARRAY)
-access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr,
- JDIMENSION start_row, JDIMENSION num_rows,
- boolean writable)
+access_virt_sarray(j_common_ptr cinfo, jvirt_sarray_ptr ptr,
+ JDIMENSION start_row, JDIMENSION num_rows, boolean writable)
/* Access the part of a virtual sample array starting at start_row */
/* and extending for num_rows rows. writable is true if */
/* caller intends to modify the accessed area. */
@@ -835,8 +832,8 @@ access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr,
/* Make the desired part of the virtual array accessible */
if (start_row < ptr->cur_start_row ||
- end_row > ptr->cur_start_row+ptr->rows_in_mem) {
- if (! ptr->b_s_open)
+ end_row > ptr->cur_start_row + ptr->rows_in_mem) {
+ if (!ptr->b_s_open)
ERREXIT(cinfo, JERR_VIRTUAL_BUG);
/* Flush old buffer contents if necessary */
if (ptr->dirty) {
@@ -856,10 +853,10 @@ access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr,
/* use long arithmetic here to avoid overflow & unsigned problems */
long ltemp;
- ltemp = (long) end_row - (long) ptr->rows_in_mem;
+ ltemp = (long)end_row - (long)ptr->rows_in_mem;
if (ltemp < 0)
ltemp = 0; /* don't fall off front end of file */
- ptr->cur_start_row = (JDIMENSION) ltemp;
+ ptr->cur_start_row = (JDIMENSION)ltemp;
}
/* Read in the selected part of the array.
* During the initial write pass, we will do no actual read
@@ -882,15 +879,15 @@ access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr,
if (writable)
ptr->first_undef_row = end_row;
if (ptr->pre_zero) {
- size_t bytesperrow = (size_t) ptr->samplesperrow * sizeof(JSAMPLE);
+ size_t bytesperrow = (size_t)ptr->samplesperrow * sizeof(JSAMPLE);
undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */
end_row -= ptr->cur_start_row;
while (undef_row < end_row) {
- jzero_far((void *) ptr->mem_buffer[undef_row], bytesperrow);
+ jzero_far((void *)ptr->mem_buffer[undef_row], bytesperrow);
undef_row++;
}
} else {
- if (! writable) /* reader looking at undefined data */
+ if (!writable) /* reader looking at undefined data */
ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
}
}
@@ -903,9 +900,8 @@ access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr,
METHODDEF(JBLOCKARRAY)
-access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr,
- JDIMENSION start_row, JDIMENSION num_rows,
- boolean writable)
+access_virt_barray(j_common_ptr cinfo, jvirt_barray_ptr ptr,
+ JDIMENSION start_row, JDIMENSION num_rows, boolean writable)
/* Access the part of a virtual block array starting at start_row */
/* and extending for num_rows rows. writable is true if */
/* caller intends to modify the accessed area. */
@@ -920,8 +916,8 @@ access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr,
/* Make the desired part of the virtual array accessible */
if (start_row < ptr->cur_start_row ||
- end_row > ptr->cur_start_row+ptr->rows_in_mem) {
- if (! ptr->b_s_open)
+ end_row > ptr->cur_start_row + ptr->rows_in_mem) {
+ if (!ptr->b_s_open)
ERREXIT(cinfo, JERR_VIRTUAL_BUG);
/* Flush old buffer contents if necessary */
if (ptr->dirty) {
@@ -941,10 +937,10 @@ access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr,
/* use long arithmetic here to avoid overflow & unsigned problems */
long ltemp;
- ltemp = (long) end_row - (long) ptr->rows_in_mem;
+ ltemp = (long)end_row - (long)ptr->rows_in_mem;
if (ltemp < 0)
ltemp = 0; /* don't fall off front end of file */
- ptr->cur_start_row = (JDIMENSION) ltemp;
+ ptr->cur_start_row = (JDIMENSION)ltemp;
}
/* Read in the selected part of the array.
* During the initial write pass, we will do no actual read
@@ -967,15 +963,15 @@ access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr,
if (writable)
ptr->first_undef_row = end_row;
if (ptr->pre_zero) {
- size_t bytesperrow = (size_t) ptr->blocksperrow * sizeof(JBLOCK);
+ size_t bytesperrow = (size_t)ptr->blocksperrow * sizeof(JBLOCK);
undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */
end_row -= ptr->cur_start_row;
while (undef_row < end_row) {
- jzero_far((void *) ptr->mem_buffer[undef_row], bytesperrow);
+ jzero_far((void *)ptr->mem_buffer[undef_row], bytesperrow);
undef_row++;
}
} else {
- if (! writable) /* reader looking at undefined data */
+ if (!writable) /* reader looking at undefined data */
ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
}
}
@@ -992,9 +988,9 @@ access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr,
*/
METHODDEF(void)
-free_pool (j_common_ptr cinfo, int pool_id)
+free_pool(j_common_ptr cinfo, int pool_id)
{
- my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ my_mem_ptr mem = (my_mem_ptr)cinfo->mem;
small_pool_ptr shdr_ptr;
large_pool_ptr lhdr_ptr;
size_t space_freed;
@@ -1015,14 +1011,14 @@ free_pool (j_common_ptr cinfo, int pool_id)
for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
if (sptr->b_s_open) { /* there may be no backing store */
sptr->b_s_open = FALSE; /* prevent recursive close if error */
- (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info);
+ (*sptr->b_s_info.close_backing_store) (cinfo, &sptr->b_s_info);
}
}
mem->virt_sarray_list = NULL;
for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
if (bptr->b_s_open) { /* there may be no backing store */
bptr->b_s_open = FALSE; /* prevent recursive close if error */
- (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info);
+ (*bptr->b_s_info.close_backing_store) (cinfo, &bptr->b_s_info);
}
}
mem->virt_barray_list = NULL;
@@ -1037,7 +1033,7 @@ free_pool (j_common_ptr cinfo, int pool_id)
space_freed = lhdr_ptr->bytes_used +
lhdr_ptr->bytes_left +
sizeof(large_pool_hdr);
- jpeg_free_large(cinfo, (void *) lhdr_ptr, space_freed);
+ jpeg_free_large(cinfo, (void *)lhdr_ptr, space_freed);
mem->total_space_allocated -= space_freed;
lhdr_ptr = next_lhdr_ptr;
}
@@ -1048,10 +1044,9 @@ free_pool (j_common_ptr cinfo, int pool_id)
while (shdr_ptr != NULL) {
small_pool_ptr next_shdr_ptr = shdr_ptr->next;
- space_freed = shdr_ptr->bytes_used +
- shdr_ptr->bytes_left +
+ space_freed = shdr_ptr->bytes_used + shdr_ptr->bytes_left +
sizeof(small_pool_hdr);
- jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed);
+ jpeg_free_small(cinfo, (void *)shdr_ptr, space_freed);
mem->total_space_allocated -= space_freed;
shdr_ptr = next_shdr_ptr;
}
@@ -1064,7 +1059,7 @@ free_pool (j_common_ptr cinfo, int pool_id)
*/
METHODDEF(void)
-self_destruct (j_common_ptr cinfo)
+self_destruct(j_common_ptr cinfo)
{
int pool;
@@ -1072,12 +1067,12 @@ self_destruct (j_common_ptr cinfo)
* Releasing pools in reverse order might help avoid fragmentation
* with some (brain-damaged) malloc libraries.
*/
- for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
+ for (pool = JPOOL_NUMPOOLS - 1; pool >= JPOOL_PERMANENT; pool--) {
free_pool(cinfo, pool);
}
/* Release the memory manager control block too. */
- jpeg_free_small(cinfo, (void *) cinfo->mem, sizeof(my_memory_mgr));
+ jpeg_free_small(cinfo, (void *)cinfo->mem, sizeof(my_memory_mgr));
cinfo->mem = NULL; /* ensures I will be called only once */
jpeg_mem_term(cinfo); /* system-dependent cleanup */
@@ -1090,7 +1085,7 @@ self_destruct (j_common_ptr cinfo)
*/
GLOBAL(void)
-jinit_memory_mgr (j_common_ptr cinfo)
+jinit_memory_mgr(j_common_ptr cinfo)
{
my_mem_ptr mem;
long max_to_use;
@@ -1106,22 +1101,22 @@ jinit_memory_mgr (j_common_ptr cinfo)
* in common if and only if X is a power of 2, ie has only one one-bit.
* Some compilers may give an "unreachable code" warning here; ignore it.
*/
- if ((ALIGN_SIZE & (ALIGN_SIZE-1)) != 0)
+ if ((ALIGN_SIZE & (ALIGN_SIZE - 1)) != 0)
ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE);
/* MAX_ALLOC_CHUNK must be representable as type size_t, and must be
* a multiple of ALIGN_SIZE.
* Again, an "unreachable code" warning may be ignored here.
* But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK.
*/
- test_mac = (size_t) MAX_ALLOC_CHUNK;
- if ((long) test_mac != MAX_ALLOC_CHUNK ||
+ test_mac = (size_t)MAX_ALLOC_CHUNK;
+ if ((long)test_mac != MAX_ALLOC_CHUNK ||
(MAX_ALLOC_CHUNK % ALIGN_SIZE) != 0)
ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */
/* Attempt to allocate memory manager's control block */
- mem = (my_mem_ptr) jpeg_get_small(cinfo, sizeof(my_memory_mgr));
+ mem = (my_mem_ptr)jpeg_get_small(cinfo, sizeof(my_memory_mgr));
if (mem == NULL) {
jpeg_mem_term(cinfo); /* system-dependent cleanup */
@@ -1147,7 +1142,7 @@ jinit_memory_mgr (j_common_ptr cinfo)
/* Initialize working state */
mem->pub.max_memory_to_use = max_to_use;
- for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
+ for (pool = JPOOL_NUMPOOLS - 1; pool >= JPOOL_PERMANENT; pool--) {
mem->small_list[pool] = NULL;
mem->large_list[pool] = NULL;
}
@@ -1157,7 +1152,7 @@ jinit_memory_mgr (j_common_ptr cinfo)
mem->total_space_allocated = sizeof(my_memory_mgr);
/* Declare ourselves open for business */
- cinfo->mem = & mem->pub;
+ cinfo->mem = &mem->pub;
/* Check for an environment variable JPEGMEM; if found, override the
* default max_memory setting from jpeg_mem_init. Note that the
@@ -1166,7 +1161,8 @@ jinit_memory_mgr (j_common_ptr cinfo)
* this feature.
*/
#ifndef NO_GETENV
- { char *memenv;
+ {
+ char *memenv;
if ((memenv = getenv("JPEGMEM")) != NULL) {
char ch = 'x';
diff --git a/src/3rdparty/libjpeg/src/jmemnobs.c b/src/3rdparty/libjpeg/src/jmemnobs.c
index ac12afa51b..089be8f500 100644
--- a/src/3rdparty/libjpeg/src/jmemnobs.c
+++ b/src/3rdparty/libjpeg/src/jmemnobs.c
@@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1992-1996, Thomas G. Lane.
* libjpeg-turbo Modifications:
- * Copyright (C) 2017, D. R. Commander.
+ * Copyright (C) 2017-2018, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -23,8 +23,8 @@
#include "jmemsys.h" /* import the system-dependent declarations */
#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc(),free() */
-extern void *malloc (size_t size);
-extern void free (void *ptr);
+extern void *malloc(size_t size);
+extern void free(void *ptr);
#endif
@@ -34,13 +34,13 @@ extern void free (void *ptr);
*/
GLOBAL(void *)
-jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
+jpeg_get_small(j_common_ptr cinfo, size_t sizeofobject)
{
- return (void *) malloc(sizeofobject);
+ return (void *)malloc(sizeofobject);
}
GLOBAL(void)
-jpeg_free_small (j_common_ptr cinfo, void *object, size_t sizeofobject)
+jpeg_free_small(j_common_ptr cinfo, void *object, size_t sizeofobject)
{
free(object);
}
@@ -51,13 +51,13 @@ jpeg_free_small (j_common_ptr cinfo, void *object, size_t sizeofobject)
*/
GLOBAL(void *)
-jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
+jpeg_get_large(j_common_ptr cinfo, size_t sizeofobject)
{
- return (void *) malloc(sizeofobject);
+ return (void *)malloc(sizeofobject);
}
GLOBAL(void)
-jpeg_free_large (j_common_ptr cinfo, void *object, size_t sizeofobject)
+jpeg_free_large(j_common_ptr cinfo, void *object, size_t sizeofobject)
{
free(object);
}
@@ -68,11 +68,11 @@ jpeg_free_large (j_common_ptr cinfo, void *object, size_t sizeofobject)
*/
GLOBAL(size_t)
-jpeg_mem_available (j_common_ptr cinfo, size_t min_bytes_needed,
- size_t max_bytes_needed, size_t already_allocated)
+jpeg_mem_available(j_common_ptr cinfo, size_t min_bytes_needed,
+ size_t max_bytes_needed, size_t already_allocated)
{
if (cinfo->mem->max_memory_to_use) {
- if (cinfo->mem->max_memory_to_use > already_allocated)
+ if ((size_t)cinfo->mem->max_memory_to_use > already_allocated)
return cinfo->mem->max_memory_to_use - already_allocated;
else
return 0;
@@ -90,8 +90,8 @@ jpeg_mem_available (j_common_ptr cinfo, size_t min_bytes_needed,
*/
GLOBAL(void)
-jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
- long total_bytes_needed)
+jpeg_open_backing_store(j_common_ptr cinfo, backing_store_ptr info,
+ long total_bytes_needed)
{
ERREXIT(cinfo, JERR_NO_BACKING_STORE);
}
@@ -103,13 +103,13 @@ jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
*/
GLOBAL(long)
-jpeg_mem_init (j_common_ptr cinfo)
+jpeg_mem_init(j_common_ptr cinfo)
{
return 0; /* just set max_memory_to_use to 0 */
}
GLOBAL(void)
-jpeg_mem_term (j_common_ptr cinfo)
+jpeg_mem_term(j_common_ptr cinfo)
{
/* no work */
}
diff --git a/src/3rdparty/libjpeg/src/jmemsys.h b/src/3rdparty/libjpeg/src/jmemsys.h
index f7dfe87a83..9229550afd 100644
--- a/src/3rdparty/libjpeg/src/jmemsys.h
+++ b/src/3rdparty/libjpeg/src/jmemsys.h
@@ -31,9 +31,9 @@
* size of the object being freed, just in case it's needed.
*/
-EXTERN(void *) jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject);
-EXTERN(void) jpeg_free_small (j_common_ptr cinfo, void *object,
- size_t sizeofobject);
+EXTERN(void *) jpeg_get_small(j_common_ptr cinfo, size_t sizeofobject);
+EXTERN(void) jpeg_free_small(j_common_ptr cinfo, void *object,
+ size_t sizeofobject);
/*
* These two functions are used to allocate and release large chunks of
@@ -43,9 +43,9 @@ EXTERN(void) jpeg_free_small (j_common_ptr cinfo, void *object,
* large chunks.
*/
-EXTERN(void *) jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject);
-EXTERN(void) jpeg_free_large (j_common_ptr cinfo, void *object,
- size_t sizeofobject);
+EXTERN(void *) jpeg_get_large(j_common_ptr cinfo, size_t sizeofobject);
+EXTERN(void) jpeg_free_large(j_common_ptr cinfo, void *object,
+ size_t sizeofobject);
/*
* The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may
@@ -84,9 +84,9 @@ EXTERN(void) jpeg_free_large (j_common_ptr cinfo, void *object,
* Conversely, zero may be returned to always use the minimum amount of memory.
*/
-EXTERN(size_t) jpeg_mem_available (j_common_ptr cinfo, size_t min_bytes_needed,
- size_t max_bytes_needed,
- size_t already_allocated);
+EXTERN(size_t) jpeg_mem_available(j_common_ptr cinfo, size_t min_bytes_needed,
+ size_t max_bytes_needed,
+ size_t already_allocated);
/*
@@ -157,9 +157,9 @@ typedef struct backing_store_struct {
* just take an error exit.)
*/
-EXTERN(void) jpeg_open_backing_store (j_common_ptr cinfo,
- backing_store_ptr info,
- long total_bytes_needed);
+EXTERN(void) jpeg_open_backing_store(j_common_ptr cinfo,
+ backing_store_ptr info,
+ long total_bytes_needed);
/*
@@ -174,5 +174,5 @@ EXTERN(void) jpeg_open_backing_store (j_common_ptr cinfo,
* all opened backing-store objects have been closed.
*/
-EXTERN(long) jpeg_mem_init (j_common_ptr cinfo);
-EXTERN(void) jpeg_mem_term (j_common_ptr cinfo);
+EXTERN(long) jpeg_mem_init(j_common_ptr cinfo);
+EXTERN(void) jpeg_mem_term(j_common_ptr cinfo);
diff --git a/src/3rdparty/libjpeg/src/jmorecfg.h b/src/3rdparty/libjpeg/src/jmorecfg.h
index 1d967863cd..d0b930079a 100644
--- a/src/3rdparty/libjpeg/src/jmorecfg.h
+++ b/src/3rdparty/libjpeg/src/jmorecfg.h
@@ -5,7 +5,7 @@
* Copyright (C) 1991-1997, Thomas G. Lane.
* Modified 1997-2009 by Guido Vollbeding.
* libjpeg-turbo Modifications:
- * Copyright (C) 2009, 2011, 2014-2015, D. R. Commander.
+ * Copyright (C) 2009, 2011, 2014-2015, 2018, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -17,9 +17,9 @@
/*
* Maximum number of components (color channels) allowed in JPEG image.
- * To meet the letter of the JPEG spec, set this to 255. However, darn
- * few applications need more than 4 channels (maybe 5 for CMYK + alpha
- * mask). We recommend 10 as a reasonable compromise; use 4 if you are
+ * To meet the letter of Rec. ITU-T T.81 | ISO/IEC 10918-1, set this to 255.
+ * However, darn few applications need more than 4 channels (maybe 5 for CMYK +
+ * alpha mask). We recommend 10 as a reasonable compromise; use 4 if you are
* really short on memory. (Each allowed component costs a hundred or so
* bytes of storage, whether actually used in an image or not.)
*/
@@ -49,15 +49,15 @@
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char JSAMPLE;
-#define GETJSAMPLE(value) ((int) (value))
+#define GETJSAMPLE(value) ((int)(value))
#else /* not HAVE_UNSIGNED_CHAR */
typedef char JSAMPLE;
#ifdef __CHAR_UNSIGNED__
-#define GETJSAMPLE(value) ((int) (value))
+#define GETJSAMPLE(value) ((int)(value))
#else
-#define GETJSAMPLE(value) ((int) (value) & 0xFF)
+#define GETJSAMPLE(value) ((int)(value) & 0xFF)
#endif /* __CHAR_UNSIGNED__ */
#endif /* HAVE_UNSIGNED_CHAR */
@@ -74,7 +74,7 @@ typedef char JSAMPLE;
*/
typedef short JSAMPLE;
-#define GETJSAMPLE(value) ((int) (value))
+#define GETJSAMPLE(value) ((int)(value))
#define MAXJSAMPLE 4095
#define CENTERJSAMPLE 2048
@@ -173,9 +173,9 @@ typedef short INT16;
*/
#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */
-#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */
-#ifndef _BASETSD_H /* MinGW is slightly different */
-#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */
+#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */
+#ifndef _BASETSD_H /* MinGW is slightly different */
+#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */
typedef long INT32;
#endif
#endif
@@ -220,7 +220,7 @@ typedef unsigned int JDIMENSION;
* software out there that uses it.
*/
-#define JMETHOD(type,methodname,arglist) type (*methodname) arglist
+#define JMETHOD(type, methodname, arglist) type (*methodname) arglist
/* libjpeg-turbo no longer supports platforms that have far symbols (MS-DOS),
@@ -315,10 +315,10 @@ typedef int boolean;
* with it. In reality, few people ever did this, because there were some
* severe restrictions involved (cjpeg and djpeg no longer worked properly,
* compressing/decompressing RGB JPEGs no longer worked properly, and the color
- * quantizer wouldn't work with pixel sizes other than 3.) Further, since all
- * of the O/S-supplied versions of libjpeg were built with the default values
- * of RGB_RED, RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE, many applications have
- * come to regard these values as immutable.
+ * quantizer wouldn't work with pixel sizes other than 3.) Furthermore, since
+ * all of the O/S-supplied versions of libjpeg were built with the default
+ * values of RGB_RED, RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE, many applications
+ * have come to regard these values as immutable.
*
* The libjpeg-turbo colorspace extensions provide a much cleaner way of
* compressing from/decompressing to buffers with arbitrary component orders
@@ -333,37 +333,37 @@ typedef int boolean;
#define RGB_BLUE 2 /* Offset of Blue */
#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */
-#define JPEG_NUMCS 17
+#define JPEG_NUMCS 17
-#define EXT_RGB_RED 0
-#define EXT_RGB_GREEN 1
-#define EXT_RGB_BLUE 2
-#define EXT_RGB_PIXELSIZE 3
+#define EXT_RGB_RED 0
+#define EXT_RGB_GREEN 1
+#define EXT_RGB_BLUE 2
+#define EXT_RGB_PIXELSIZE 3
-#define EXT_RGBX_RED 0
-#define EXT_RGBX_GREEN 1
-#define EXT_RGBX_BLUE 2
-#define EXT_RGBX_PIXELSIZE 4
+#define EXT_RGBX_RED 0
+#define EXT_RGBX_GREEN 1
+#define EXT_RGBX_BLUE 2
+#define EXT_RGBX_PIXELSIZE 4
-#define EXT_BGR_RED 2
-#define EXT_BGR_GREEN 1
-#define EXT_BGR_BLUE 0
-#define EXT_BGR_PIXELSIZE 3
+#define EXT_BGR_RED 2
+#define EXT_BGR_GREEN 1
+#define EXT_BGR_BLUE 0
+#define EXT_BGR_PIXELSIZE 3
-#define EXT_BGRX_RED 2
-#define EXT_BGRX_GREEN 1
-#define EXT_BGRX_BLUE 0
-#define EXT_BGRX_PIXELSIZE 4
+#define EXT_BGRX_RED 2
+#define EXT_BGRX_GREEN 1
+#define EXT_BGRX_BLUE 0
+#define EXT_BGRX_PIXELSIZE 4
-#define EXT_XBGR_RED 3
-#define EXT_XBGR_GREEN 2
-#define EXT_XBGR_BLUE 1
-#define EXT_XBGR_PIXELSIZE 4
+#define EXT_XBGR_RED 3
+#define EXT_XBGR_GREEN 2
+#define EXT_XBGR_BLUE 1
+#define EXT_XBGR_PIXELSIZE 4
-#define EXT_XRGB_RED 1
-#define EXT_XRGB_GREEN 2
-#define EXT_XRGB_BLUE 3
-#define EXT_XRGB_PIXELSIZE 4
+#define EXT_XRGB_RED 1
+#define EXT_XRGB_GREEN 2
+#define EXT_XRGB_BLUE 3
+#define EXT_XRGB_PIXELSIZE 4
static const int rgb_red[JPEG_NUMCS] = {
-1, -1, RGB_RED, -1, -1, -1, EXT_RGB_RED, EXT_RGBX_RED,
@@ -404,7 +404,7 @@ static const int rgb_pixelsize[JPEG_NUMCS] = {
#ifndef WITH_SIMD
#define MULTIPLIER int /* type for fastest integer multiply */
#else
-#define MULTIPLIER short /* prefer 16-bit with SIMD for parellelism */
+#define MULTIPLIER short /* prefer 16-bit with SIMD for parellelism */
#endif
#endif
diff --git a/src/3rdparty/libjpeg/src/jpegcomp.h b/src/3rdparty/libjpeg/src/jpegcomp.h
index ade0d1edcd..b32d544bf1 100644
--- a/src/3rdparty/libjpeg/src/jpegcomp.h
+++ b/src/3rdparty/libjpeg/src/jpegcomp.h
@@ -11,21 +11,21 @@
*/
#if JPEG_LIB_VERSION >= 70
-#define _DCT_scaled_size DCT_h_scaled_size
-#define _DCT_h_scaled_size DCT_h_scaled_size
-#define _DCT_v_scaled_size DCT_v_scaled_size
-#define _min_DCT_scaled_size min_DCT_h_scaled_size
-#define _min_DCT_h_scaled_size min_DCT_h_scaled_size
-#define _min_DCT_v_scaled_size min_DCT_v_scaled_size
-#define _jpeg_width jpeg_width
-#define _jpeg_height jpeg_height
+#define _DCT_scaled_size DCT_h_scaled_size
+#define _DCT_h_scaled_size DCT_h_scaled_size
+#define _DCT_v_scaled_size DCT_v_scaled_size
+#define _min_DCT_scaled_size min_DCT_h_scaled_size
+#define _min_DCT_h_scaled_size min_DCT_h_scaled_size
+#define _min_DCT_v_scaled_size min_DCT_v_scaled_size
+#define _jpeg_width jpeg_width
+#define _jpeg_height jpeg_height
#else
-#define _DCT_scaled_size DCT_scaled_size
-#define _DCT_h_scaled_size DCT_scaled_size
-#define _DCT_v_scaled_size DCT_scaled_size
-#define _min_DCT_scaled_size min_DCT_scaled_size
-#define _min_DCT_h_scaled_size min_DCT_scaled_size
-#define _min_DCT_v_scaled_size min_DCT_scaled_size
-#define _jpeg_width image_width
-#define _jpeg_height image_height
+#define _DCT_scaled_size DCT_scaled_size
+#define _DCT_h_scaled_size DCT_scaled_size
+#define _DCT_v_scaled_size DCT_scaled_size
+#define _min_DCT_scaled_size min_DCT_scaled_size
+#define _min_DCT_h_scaled_size min_DCT_scaled_size
+#define _min_DCT_v_scaled_size min_DCT_scaled_size
+#define _jpeg_width image_width
+#define _jpeg_height image_height
#endif
diff --git a/src/3rdparty/libjpeg/src/jpegint.h b/src/3rdparty/libjpeg/src/jpegint.h
index 9979a912d9..ad36ca8b56 100644
--- a/src/3rdparty/libjpeg/src/jpegint.h
+++ b/src/3rdparty/libjpeg/src/jpegint.h
@@ -27,21 +27,21 @@ typedef enum { /* Operating modes for buffer controllers */
} J_BUF_MODE;
/* Values of global_state field (jdapi.c has some dependencies on ordering!) */
-#define CSTATE_START 100 /* after create_compress */
-#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */
-#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */
-#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */
-#define DSTATE_START 200 /* after create_decompress */
-#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */
-#define DSTATE_READY 202 /* found SOS, ready for start_decompress */
-#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/
-#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */
-#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */
-#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */
-#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */
-#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */
-#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */
-#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */
+#define CSTATE_START 100 /* after create_compress */
+#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */
+#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */
+#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */
+#define DSTATE_START 200 /* after create_decompress */
+#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */
+#define DSTATE_READY 202 /* found SOS, ready for start_decompress */
+#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/
+#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */
+#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */
+#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */
+#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */
+#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */
+#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */
+#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */
/* JLONG must hold at least signed 32-bit values. */
@@ -53,7 +53,7 @@ typedef long JLONG;
* sanitizer warnings
*/
-#define LEFT_SHIFT(a, b) ((JLONG)((unsigned long)(a) << (b)))
+#define LEFT_SHIFT(a, b) ((JLONG)((unsigned long)(a) << (b)))
/* Declarations for compression modules */
@@ -274,9 +274,9 @@ struct jpeg_color_quantizer {
/* Miscellaneous useful macros */
#undef MAX
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
#undef MIN
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
/* We assume that right shift corresponds to signed division by 2 with
@@ -291,64 +291,64 @@ struct jpeg_color_quantizer {
#ifdef RIGHT_SHIFT_IS_UNSIGNED
#define SHIFT_TEMPS JLONG shift_temp;
-#define RIGHT_SHIFT(x,shft) \
- ((shift_temp = (x)) < 0 ? \
- (shift_temp >> (shft)) | ((~((JLONG) 0)) << (32-(shft))) : \
- (shift_temp >> (shft)))
+#define RIGHT_SHIFT(x, shft) \
+ ((shift_temp = (x)) < 0 ? \
+ (shift_temp >> (shft)) | ((~((JLONG)0)) << (32 - (shft))) : \
+ (shift_temp >> (shft)))
#else
#define SHIFT_TEMPS
-#define RIGHT_SHIFT(x,shft) ((x) >> (shft))
+#define RIGHT_SHIFT(x, shft) ((x) >> (shft))
#endif
/* Compression module initialization routines */
-EXTERN(void) jinit_compress_master (j_compress_ptr cinfo);
-EXTERN(void) jinit_c_master_control (j_compress_ptr cinfo,
- boolean transcode_only);
-EXTERN(void) jinit_c_main_controller (j_compress_ptr cinfo,
- boolean need_full_buffer);
-EXTERN(void) jinit_c_prep_controller (j_compress_ptr cinfo,
- boolean need_full_buffer);
-EXTERN(void) jinit_c_coef_controller (j_compress_ptr cinfo,
- boolean need_full_buffer);
-EXTERN(void) jinit_color_converter (j_compress_ptr cinfo);
-EXTERN(void) jinit_downsampler (j_compress_ptr cinfo);
-EXTERN(void) jinit_forward_dct (j_compress_ptr cinfo);
-EXTERN(void) jinit_huff_encoder (j_compress_ptr cinfo);
-EXTERN(void) jinit_phuff_encoder (j_compress_ptr cinfo);
-EXTERN(void) jinit_arith_encoder (j_compress_ptr cinfo);
-EXTERN(void) jinit_marker_writer (j_compress_ptr cinfo);
+EXTERN(void) jinit_compress_master(j_compress_ptr cinfo);
+EXTERN(void) jinit_c_master_control(j_compress_ptr cinfo,
+ boolean transcode_only);
+EXTERN(void) jinit_c_main_controller(j_compress_ptr cinfo,
+ boolean need_full_buffer);
+EXTERN(void) jinit_c_prep_controller(j_compress_ptr cinfo,
+ boolean need_full_buffer);
+EXTERN(void) jinit_c_coef_controller(j_compress_ptr cinfo,
+ boolean need_full_buffer);
+EXTERN(void) jinit_color_converter(j_compress_ptr cinfo);
+EXTERN(void) jinit_downsampler(j_compress_ptr cinfo);
+EXTERN(void) jinit_forward_dct(j_compress_ptr cinfo);
+EXTERN(void) jinit_huff_encoder(j_compress_ptr cinfo);
+EXTERN(void) jinit_phuff_encoder(j_compress_ptr cinfo);
+EXTERN(void) jinit_arith_encoder(j_compress_ptr cinfo);
+EXTERN(void) jinit_marker_writer(j_compress_ptr cinfo);
/* Decompression module initialization routines */
-EXTERN(void) jinit_master_decompress (j_decompress_ptr cinfo);
-EXTERN(void) jinit_d_main_controller (j_decompress_ptr cinfo,
- boolean need_full_buffer);
-EXTERN(void) jinit_d_coef_controller (j_decompress_ptr cinfo,
- boolean need_full_buffer);
-EXTERN(void) jinit_d_post_controller (j_decompress_ptr cinfo,
- boolean need_full_buffer);
-EXTERN(void) jinit_input_controller (j_decompress_ptr cinfo);
-EXTERN(void) jinit_marker_reader (j_decompress_ptr cinfo);
-EXTERN(void) jinit_huff_decoder (j_decompress_ptr cinfo);
-EXTERN(void) jinit_phuff_decoder (j_decompress_ptr cinfo);
-EXTERN(void) jinit_arith_decoder (j_decompress_ptr cinfo);
-EXTERN(void) jinit_inverse_dct (j_decompress_ptr cinfo);
-EXTERN(void) jinit_upsampler (j_decompress_ptr cinfo);
-EXTERN(void) jinit_color_deconverter (j_decompress_ptr cinfo);
-EXTERN(void) jinit_1pass_quantizer (j_decompress_ptr cinfo);
-EXTERN(void) jinit_2pass_quantizer (j_decompress_ptr cinfo);
-EXTERN(void) jinit_merged_upsampler (j_decompress_ptr cinfo);
+EXTERN(void) jinit_master_decompress(j_decompress_ptr cinfo);
+EXTERN(void) jinit_d_main_controller(j_decompress_ptr cinfo,
+ boolean need_full_buffer);
+EXTERN(void) jinit_d_coef_controller(j_decompress_ptr cinfo,
+ boolean need_full_buffer);
+EXTERN(void) jinit_d_post_controller(j_decompress_ptr cinfo,
+ boolean need_full_buffer);
+EXTERN(void) jinit_input_controller(j_decompress_ptr cinfo);
+EXTERN(void) jinit_marker_reader(j_decompress_ptr cinfo);
+EXTERN(void) jinit_huff_decoder(j_decompress_ptr cinfo);
+EXTERN(void) jinit_phuff_decoder(j_decompress_ptr cinfo);
+EXTERN(void) jinit_arith_decoder(j_decompress_ptr cinfo);
+EXTERN(void) jinit_inverse_dct(j_decompress_ptr cinfo);
+EXTERN(void) jinit_upsampler(j_decompress_ptr cinfo);
+EXTERN(void) jinit_color_deconverter(j_decompress_ptr cinfo);
+EXTERN(void) jinit_1pass_quantizer(j_decompress_ptr cinfo);
+EXTERN(void) jinit_2pass_quantizer(j_decompress_ptr cinfo);
+EXTERN(void) jinit_merged_upsampler(j_decompress_ptr cinfo);
/* Memory manager initialization */
-EXTERN(void) jinit_memory_mgr (j_common_ptr cinfo);
+EXTERN(void) jinit_memory_mgr(j_common_ptr cinfo);
/* Utility routines in jutils.c */
-EXTERN(long) jdiv_round_up (long a, long b);
-EXTERN(long) jround_up (long a, long b);
-EXTERN(void) jcopy_sample_rows (JSAMPARRAY input_array, int source_row,
- JSAMPARRAY output_array, int dest_row,
- int num_rows, JDIMENSION num_cols);
-EXTERN(void) jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row,
- JDIMENSION num_blocks);
-EXTERN(void) jzero_far (void *target, size_t bytestozero);
+EXTERN(long) jdiv_round_up(long a, long b);
+EXTERN(long) jround_up(long a, long b);
+EXTERN(void) jcopy_sample_rows(JSAMPARRAY input_array, int source_row,
+ JSAMPARRAY output_array, int dest_row,
+ int num_rows, JDIMENSION num_cols);
+EXTERN(void) jcopy_block_row(JBLOCKROW input_row, JBLOCKROW output_row,
+ JDIMENSION num_blocks);
+EXTERN(void) jzero_far(void *target, size_t bytestozero);
/* Constant tables in jutils.c */
#if 0 /* This table is not actually needed in v6a */
extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */
diff --git a/src/3rdparty/libjpeg/src/jpeglib.h b/src/3rdparty/libjpeg/src/jpeglib.h
index 6c63f58222..33f8ad2791 100644
--- a/src/3rdparty/libjpeg/src/jpeglib.h
+++ b/src/3rdparty/libjpeg/src/jpeglib.h
@@ -5,7 +5,7 @@
* Copyright (C) 1991-1998, Thomas G. Lane.
* Modified 2002-2009 by Guido Vollbeding.
* libjpeg-turbo Modifications:
- * Copyright (C) 2009-2011, 2013-2014, 2016, D. R. Commander.
+ * Copyright (C) 2009-2011, 2013-2014, 2016-2017, D. R. Commander.
* Copyright (C) 2015, Google, Inc.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
@@ -211,8 +211,8 @@ struct jpeg_marker_struct {
/* Known color spaces. */
-#define JCS_EXTENSIONS 1
-#define JCS_ALPHA_EXTENSIONS 1
+#define JCS_EXTENSIONS 1
+#define JCS_ALPHA_EXTENSIONS 1
typedef enum {
JCS_UNKNOWN, /* error/unspecified */
@@ -268,11 +268,11 @@ typedef enum {
/* Common fields between JPEG compression and decompression master structs. */
#define jpeg_common_fields \
- struct jpeg_error_mgr *err; /* Error handler module */\
- struct jpeg_memory_mgr *mem; /* Memory manager module */\
- struct jpeg_progress_mgr *progress; /* Progress monitor, or NULL if none */\
- void *client_data; /* Available for use by application */\
- boolean is_decompressor; /* So common code can tell which is which */\
+ struct jpeg_error_mgr *err; /* Error handler module */ \
+ struct jpeg_memory_mgr *mem; /* Memory manager module */ \
+ struct jpeg_progress_mgr *progress; /* Progress monitor, or NULL if none */ \
+ void *client_data; /* Available for use by application */ \
+ boolean is_decompressor; /* So common code can tell which is which */ \
int global_state /* For checking call sequence validity */
/* Routines that are to be used by both halves of the library are declared
@@ -822,9 +822,9 @@ struct jpeg_source_mgr {
* successful.
*/
-#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */
-#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */
-#define JPOOL_NUMPOOLS 2
+#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */
+#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */
+#define JPOOL_NUMPOOLS 2
typedef struct jvirt_sarray_control *jvirt_sarray_ptr;
typedef struct jvirt_barray_control *jvirt_barray_ptr;
@@ -888,7 +888,7 @@ typedef boolean (*jpeg_marker_parser_method) (j_decompress_ptr cinfo);
/* Default error-management setup */
-EXTERN(struct jpeg_error_mgr *) jpeg_std_error (struct jpeg_error_mgr *err);
+EXTERN(struct jpeg_error_mgr *) jpeg_std_error(struct jpeg_error_mgr *err);
/* Initialization of JPEG compression objects.
* jpeg_create_compress() and jpeg_create_decompress() are the exported
@@ -898,90 +898,95 @@ EXTERN(struct jpeg_error_mgr *) jpeg_std_error (struct jpeg_error_mgr *err);
* NB: you must set up the error-manager BEFORE calling jpeg_create_xxx.
*/
#define jpeg_create_compress(cinfo) \
- jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \
- (size_t) sizeof(struct jpeg_compress_struct))
+ jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \
+ (size_t)sizeof(struct jpeg_compress_struct))
#define jpeg_create_decompress(cinfo) \
- jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \
- (size_t) sizeof(struct jpeg_decompress_struct))
-EXTERN(void) jpeg_CreateCompress (j_compress_ptr cinfo, int version,
- size_t structsize);
-EXTERN(void) jpeg_CreateDecompress (j_decompress_ptr cinfo, int version,
- size_t structsize);
+ jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \
+ (size_t)sizeof(struct jpeg_decompress_struct))
+EXTERN(void) jpeg_CreateCompress(j_compress_ptr cinfo, int version,
+ size_t structsize);
+EXTERN(void) jpeg_CreateDecompress(j_decompress_ptr cinfo, int version,
+ size_t structsize);
/* Destruction of JPEG compression objects */
-EXTERN(void) jpeg_destroy_compress (j_compress_ptr cinfo);
-EXTERN(void) jpeg_destroy_decompress (j_decompress_ptr cinfo);
+EXTERN(void) jpeg_destroy_compress(j_compress_ptr cinfo);
+EXTERN(void) jpeg_destroy_decompress(j_decompress_ptr cinfo);
/* Standard data source and destination managers: stdio streams. */
/* Caller is responsible for opening the file before and closing after. */
-EXTERN(void) jpeg_stdio_dest (j_compress_ptr cinfo, FILE *outfile);
-EXTERN(void) jpeg_stdio_src (j_decompress_ptr cinfo, FILE *infile);
+EXTERN(void) jpeg_stdio_dest(j_compress_ptr cinfo, FILE *outfile);
+EXTERN(void) jpeg_stdio_src(j_decompress_ptr cinfo, FILE *infile);
#if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED)
/* Data source and destination managers: memory buffers. */
-EXTERN(void) jpeg_mem_dest (j_compress_ptr cinfo, unsigned char **outbuffer,
- unsigned long *outsize);
-EXTERN(void) jpeg_mem_src (j_decompress_ptr cinfo,
- const unsigned char *inbuffer,
- unsigned long insize);
+EXTERN(void) jpeg_mem_dest(j_compress_ptr cinfo, unsigned char **outbuffer,
+ unsigned long *outsize);
+EXTERN(void) jpeg_mem_src(j_decompress_ptr cinfo,
+ const unsigned char *inbuffer, unsigned long insize);
#endif
/* Default parameter setup for compression */
-EXTERN(void) jpeg_set_defaults (j_compress_ptr cinfo);
+EXTERN(void) jpeg_set_defaults(j_compress_ptr cinfo);
/* Compression parameter setup aids */
-EXTERN(void) jpeg_set_colorspace (j_compress_ptr cinfo,
- J_COLOR_SPACE colorspace);
-EXTERN(void) jpeg_default_colorspace (j_compress_ptr cinfo);
-EXTERN(void) jpeg_set_quality (j_compress_ptr cinfo, int quality,
- boolean force_baseline);
-EXTERN(void) jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor,
- boolean force_baseline);
+EXTERN(void) jpeg_set_colorspace(j_compress_ptr cinfo,
+ J_COLOR_SPACE colorspace);
+EXTERN(void) jpeg_default_colorspace(j_compress_ptr cinfo);
+EXTERN(void) jpeg_set_quality(j_compress_ptr cinfo, int quality,
+ boolean force_baseline);
+EXTERN(void) jpeg_set_linear_quality(j_compress_ptr cinfo, int scale_factor,
+ boolean force_baseline);
#if JPEG_LIB_VERSION >= 70
-EXTERN(void) jpeg_default_qtables (j_compress_ptr cinfo,
- boolean force_baseline);
+EXTERN(void) jpeg_default_qtables(j_compress_ptr cinfo,
+ boolean force_baseline);
#endif
-EXTERN(void) jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl,
- const unsigned int *basic_table,
- int scale_factor, boolean force_baseline);
-EXTERN(int) jpeg_quality_scaling (int quality);
-EXTERN(void) jpeg_simple_progression (j_compress_ptr cinfo);
-EXTERN(void) jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress);
-EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table (j_common_ptr cinfo);
-EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table (j_common_ptr cinfo);
+EXTERN(void) jpeg_add_quant_table(j_compress_ptr cinfo, int which_tbl,
+ const unsigned int *basic_table,
+ int scale_factor, boolean force_baseline);
+EXTERN(int) jpeg_quality_scaling(int quality);
+EXTERN(void) jpeg_simple_progression(j_compress_ptr cinfo);
+EXTERN(void) jpeg_suppress_tables(j_compress_ptr cinfo, boolean suppress);
+EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table(j_common_ptr cinfo);
+EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table(j_common_ptr cinfo);
/* Main entry points for compression */
-EXTERN(void) jpeg_start_compress (j_compress_ptr cinfo,
- boolean write_all_tables);
-EXTERN(JDIMENSION) jpeg_write_scanlines (j_compress_ptr cinfo,
- JSAMPARRAY scanlines,
- JDIMENSION num_lines);
-EXTERN(void) jpeg_finish_compress (j_compress_ptr cinfo);
+EXTERN(void) jpeg_start_compress(j_compress_ptr cinfo,
+ boolean write_all_tables);
+EXTERN(JDIMENSION) jpeg_write_scanlines(j_compress_ptr cinfo,
+ JSAMPARRAY scanlines,
+ JDIMENSION num_lines);
+EXTERN(void) jpeg_finish_compress(j_compress_ptr cinfo);
#if JPEG_LIB_VERSION >= 70
/* Precalculate JPEG dimensions for current compression parameters. */
-EXTERN(void) jpeg_calc_jpeg_dimensions (j_compress_ptr cinfo);
+EXTERN(void) jpeg_calc_jpeg_dimensions(j_compress_ptr cinfo);
#endif
/* Replaces jpeg_write_scanlines when writing raw downsampled data. */
-EXTERN(JDIMENSION) jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data,
- JDIMENSION num_lines);
+EXTERN(JDIMENSION) jpeg_write_raw_data(j_compress_ptr cinfo, JSAMPIMAGE data,
+ JDIMENSION num_lines);
/* Write a special marker. See libjpeg.txt concerning safe usage. */
-EXTERN(void) jpeg_write_marker (j_compress_ptr cinfo, int marker,
- const JOCTET *dataptr, unsigned int datalen);
+EXTERN(void) jpeg_write_marker(j_compress_ptr cinfo, int marker,
+ const JOCTET *dataptr, unsigned int datalen);
/* Same, but piecemeal. */
-EXTERN(void) jpeg_write_m_header (j_compress_ptr cinfo, int marker,
- unsigned int datalen);
-EXTERN(void) jpeg_write_m_byte (j_compress_ptr cinfo, int val);
+EXTERN(void) jpeg_write_m_header(j_compress_ptr cinfo, int marker,
+ unsigned int datalen);
+EXTERN(void) jpeg_write_m_byte(j_compress_ptr cinfo, int val);
/* Alternate compression function: just write an abbreviated table file */
-EXTERN(void) jpeg_write_tables (j_compress_ptr cinfo);
+EXTERN(void) jpeg_write_tables(j_compress_ptr cinfo);
+
+/* Write ICC profile. See libjpeg.txt for usage information. */
+EXTERN(void) jpeg_write_icc_profile(j_compress_ptr cinfo,
+ const JOCTET *icc_data_ptr,
+ unsigned int icc_data_len);
+
/* Decompression startup: read start of JPEG datastream to see what's there */
-EXTERN(int) jpeg_read_header (j_decompress_ptr cinfo, boolean require_image);
+EXTERN(int) jpeg_read_header(j_decompress_ptr cinfo, boolean require_image);
/* Return value is one of: */
-#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */
-#define JPEG_HEADER_OK 1 /* Found valid image datastream */
-#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */
+#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */
+#define JPEG_HEADER_OK 1 /* Found valid image datastream */
+#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */
/* If you pass require_image = TRUE (normal case), you need not check for
* a TABLES_ONLY return code; an abbreviated file will cause an error exit.
* JPEG_SUSPENDED is only possible if you use a data source module that can
@@ -989,27 +994,27 @@ EXTERN(int) jpeg_read_header (j_decompress_ptr cinfo, boolean require_image);
*/
/* Main entry points for decompression */
-EXTERN(boolean) jpeg_start_decompress (j_decompress_ptr cinfo);
-EXTERN(JDIMENSION) jpeg_read_scanlines (j_decompress_ptr cinfo,
- JSAMPARRAY scanlines,
- JDIMENSION max_lines);
-EXTERN(JDIMENSION) jpeg_skip_scanlines (j_decompress_ptr cinfo,
- JDIMENSION num_lines);
-EXTERN(void) jpeg_crop_scanline (j_decompress_ptr cinfo, JDIMENSION *xoffset,
- JDIMENSION *width);
-EXTERN(boolean) jpeg_finish_decompress (j_decompress_ptr cinfo);
+EXTERN(boolean) jpeg_start_decompress(j_decompress_ptr cinfo);
+EXTERN(JDIMENSION) jpeg_read_scanlines(j_decompress_ptr cinfo,
+ JSAMPARRAY scanlines,
+ JDIMENSION max_lines);
+EXTERN(JDIMENSION) jpeg_skip_scanlines(j_decompress_ptr cinfo,
+ JDIMENSION num_lines);
+EXTERN(void) jpeg_crop_scanline(j_decompress_ptr cinfo, JDIMENSION *xoffset,
+ JDIMENSION *width);
+EXTERN(boolean) jpeg_finish_decompress(j_decompress_ptr cinfo);
/* Replaces jpeg_read_scanlines when reading raw downsampled data. */
-EXTERN(JDIMENSION) jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data,
- JDIMENSION max_lines);
+EXTERN(JDIMENSION) jpeg_read_raw_data(j_decompress_ptr cinfo, JSAMPIMAGE data,
+ JDIMENSION max_lines);
/* Additional entry points for buffered-image mode. */
-EXTERN(boolean) jpeg_has_multiple_scans (j_decompress_ptr cinfo);
-EXTERN(boolean) jpeg_start_output (j_decompress_ptr cinfo, int scan_number);
-EXTERN(boolean) jpeg_finish_output (j_decompress_ptr cinfo);
-EXTERN(boolean) jpeg_input_complete (j_decompress_ptr cinfo);
-EXTERN(void) jpeg_new_colormap (j_decompress_ptr cinfo);
-EXTERN(int) jpeg_consume_input (j_decompress_ptr cinfo);
+EXTERN(boolean) jpeg_has_multiple_scans(j_decompress_ptr cinfo);
+EXTERN(boolean) jpeg_start_output(j_decompress_ptr cinfo, int scan_number);
+EXTERN(boolean) jpeg_finish_output(j_decompress_ptr cinfo);
+EXTERN(boolean) jpeg_input_complete(j_decompress_ptr cinfo);
+EXTERN(void) jpeg_new_colormap(j_decompress_ptr cinfo);
+EXTERN(int) jpeg_consume_input(j_decompress_ptr cinfo);
/* Return value is one of: */
/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */
#define JPEG_REACHED_SOS 1 /* Reached start of new scan */
@@ -1019,25 +1024,25 @@ EXTERN(int) jpeg_consume_input (j_decompress_ptr cinfo);
/* Precalculate output dimensions for current decompression parameters. */
#if JPEG_LIB_VERSION >= 80
-EXTERN(void) jpeg_core_output_dimensions (j_decompress_ptr cinfo);
+EXTERN(void) jpeg_core_output_dimensions(j_decompress_ptr cinfo);
#endif
-EXTERN(void) jpeg_calc_output_dimensions (j_decompress_ptr cinfo);
+EXTERN(void) jpeg_calc_output_dimensions(j_decompress_ptr cinfo);
/* Control saving of COM and APPn markers into marker_list. */
-EXTERN(void) jpeg_save_markers (j_decompress_ptr cinfo, int marker_code,
- unsigned int length_limit);
+EXTERN(void) jpeg_save_markers(j_decompress_ptr cinfo, int marker_code,
+ unsigned int length_limit);
/* Install a special processing method for COM or APPn markers. */
-EXTERN(void) jpeg_set_marker_processor (j_decompress_ptr cinfo,
- int marker_code,
- jpeg_marker_parser_method routine);
+EXTERN(void) jpeg_set_marker_processor(j_decompress_ptr cinfo,
+ int marker_code,
+ jpeg_marker_parser_method routine);
/* Read or write raw DCT coefficients --- useful for lossless transcoding. */
-EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients (j_decompress_ptr cinfo);
-EXTERN(void) jpeg_write_coefficients (j_compress_ptr cinfo,
- jvirt_barray_ptr *coef_arrays);
-EXTERN(void) jpeg_copy_critical_parameters (j_decompress_ptr srcinfo,
- j_compress_ptr dstinfo);
+EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients(j_decompress_ptr cinfo);
+EXTERN(void) jpeg_write_coefficients(j_compress_ptr cinfo,
+ jvirt_barray_ptr *coef_arrays);
+EXTERN(void) jpeg_copy_critical_parameters(j_decompress_ptr srcinfo,
+ j_compress_ptr dstinfo);
/* If you choose to abort compression or decompression before completing
* jpeg_finish_(de)compress, then you need to clean up to release memory,
@@ -1045,17 +1050,22 @@ EXTERN(void) jpeg_copy_critical_parameters (j_decompress_ptr srcinfo,
* if you're done with the JPEG object, but if you want to clean it up and
* reuse it, call this:
*/
-EXTERN(void) jpeg_abort_compress (j_compress_ptr cinfo);
-EXTERN(void) jpeg_abort_decompress (j_decompress_ptr cinfo);
+EXTERN(void) jpeg_abort_compress(j_compress_ptr cinfo);
+EXTERN(void) jpeg_abort_decompress(j_decompress_ptr cinfo);
/* Generic versions of jpeg_abort and jpeg_destroy that work on either
* flavor of JPEG object. These may be more convenient in some places.
*/
-EXTERN(void) jpeg_abort (j_common_ptr cinfo);
-EXTERN(void) jpeg_destroy (j_common_ptr cinfo);
+EXTERN(void) jpeg_abort(j_common_ptr cinfo);
+EXTERN(void) jpeg_destroy(j_common_ptr cinfo);
/* Default restart-marker-resync procedure for use by data source modules */
-EXTERN(boolean) jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired);
+EXTERN(boolean) jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired);
+
+/* Read ICC profile. See libjpeg.txt for usage information. */
+EXTERN(boolean) jpeg_read_icc_profile(j_decompress_ptr cinfo,
+ JOCTET **icc_data_ptr,
+ unsigned int *icc_data_len);
/* These marker codes are exported since applications and data source modules
diff --git a/src/3rdparty/libjpeg/src/jquant1.c b/src/3rdparty/libjpeg/src/jquant1.c
index e7814815ef..a336abdbbb 100644
--- a/src/3rdparty/libjpeg/src/jquant1.c
+++ b/src/3rdparty/libjpeg/src/jquant1.c
@@ -73,8 +73,9 @@
#define ODITHER_SIZE 16 /* dimension of dither matrix */
/* NB: if ODITHER_SIZE is not a power of 2, ODITHER_MASK uses will break */
-#define ODITHER_CELLS (ODITHER_SIZE*ODITHER_SIZE) /* # cells in matrix */
-#define ODITHER_MASK (ODITHER_SIZE-1) /* mask for wrapping around counters */
+#define ODITHER_CELLS (ODITHER_SIZE * ODITHER_SIZE) /* # cells in matrix */
+#define ODITHER_MASK (ODITHER_SIZE - 1) /* mask for wrapping around
+ counters */
typedef int ODITHER_MATRIX[ODITHER_SIZE][ODITHER_SIZE];
typedef int (*ODITHER_MATRIX_PTR)[ODITHER_SIZE];
@@ -132,12 +133,12 @@ typedef JLONG FSERROR; /* may need more than 16 bits */
typedef JLONG LOCFSERROR; /* be sure calculation temps are big enough */
#endif
-typedef FSERROR *FSERRPTR; /* pointer to error array */
+typedef FSERROR *FSERRPTR; /* pointer to error array */
/* Private subobject */
-#define MAX_Q_COMPS 4 /* max components I can handle */
+#define MAX_Q_COMPS 4 /* max components I can handle */
typedef struct {
struct jpeg_color_quantizer pub; /* public fields */
@@ -183,7 +184,7 @@ typedef my_cquantizer *my_cquantize_ptr;
LOCAL(int)
-select_ncolors (j_decompress_ptr cinfo, int Ncolors[])
+select_ncolors(j_decompress_ptr cinfo, int Ncolors[])
/* Determine allocation of desired colors to components, */
/* and fill in Ncolors[] array to indicate choice. */
/* Return value is total number of colors (product of Ncolors[] values). */
@@ -206,12 +207,12 @@ select_ncolors (j_decompress_ptr cinfo, int Ncolors[])
temp = iroot; /* set temp = iroot ** nc */
for (i = 1; i < nc; i++)
temp *= iroot;
- } while (temp <= (long) max_colors); /* repeat till iroot exceeds root */
+ } while (temp <= (long)max_colors); /* repeat till iroot exceeds root */
iroot--; /* now iroot = floor(root) */
/* Must have at least 2 color values per component */
if (iroot < 2)
- ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int) temp);
+ ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int)temp);
/* Initialize to iroot color values for each component */
total_colors = 1;
@@ -231,11 +232,11 @@ select_ncolors (j_decompress_ptr cinfo, int Ncolors[])
j = (cinfo->out_color_space == JCS_RGB ? RGB_order[i] : i);
/* calculate new total_colors if Ncolors[j] is incremented */
temp = total_colors / Ncolors[j];
- temp *= Ncolors[j]+1; /* done in long arith to avoid oflo */
- if (temp > (long) max_colors)
+ temp *= Ncolors[j] + 1; /* done in long arith to avoid oflo */
+ if (temp > (long)max_colors)
break; /* won't fit, done with this pass */
Ncolors[j]++; /* OK, apply the increment */
- total_colors = (int) temp;
+ total_colors = (int)temp;
changed = TRUE;
}
} while (changed);
@@ -245,7 +246,7 @@ select_ncolors (j_decompress_ptr cinfo, int Ncolors[])
LOCAL(int)
-output_value (j_decompress_ptr cinfo, int ci, int j, int maxj)
+output_value(j_decompress_ptr cinfo, int ci, int j, int maxj)
/* Return j'th output value, where j will range from 0 to maxj */
/* The output values must fall in 0..MAXJSAMPLE in increasing order */
{
@@ -254,17 +255,17 @@ output_value (j_decompress_ptr cinfo, int ci, int j, int maxj)
* (Forcing the upper and lower values to the limits ensures that
* dithering can't produce a color outside the selected gamut.)
*/
- return (int) (((JLONG) j * MAXJSAMPLE + maxj/2) / maxj);
+ return (int)(((JLONG)j * MAXJSAMPLE + maxj / 2) / maxj);
}
LOCAL(int)
-largest_input_value (j_decompress_ptr cinfo, int ci, int j, int maxj)
+largest_input_value(j_decompress_ptr cinfo, int ci, int j, int maxj)
/* Return largest input value that should map to j'th output value */
/* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */
{
/* Breakpoints are halfway between values returned by output_value */
- return (int) (((JLONG) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj));
+ return (int)(((JLONG)(2 * j + 1) * MAXJSAMPLE + maxj) / (2 * maxj));
}
@@ -273,21 +274,21 @@ largest_input_value (j_decompress_ptr cinfo, int ci, int j, int maxj)
*/
LOCAL(void)
-create_colormap (j_decompress_ptr cinfo)
+create_colormap(j_decompress_ptr cinfo)
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
JSAMPARRAY colormap; /* Created colormap */
int total_colors; /* Number of distinct output colors */
- int i,j,k, nci, blksize, blkdist, ptr, val;
+ int i, j, k, nci, blksize, blkdist, ptr, val;
/* Select number of colors for each component */
total_colors = select_ncolors(cinfo, cquantize->Ncolors);
/* Report selected color counts */
if (cinfo->out_color_components == 3)
- TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS,
- total_colors, cquantize->Ncolors[0],
- cquantize->Ncolors[1], cquantize->Ncolors[2]);
+ TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS, total_colors,
+ cquantize->Ncolors[0], cquantize->Ncolors[1],
+ cquantize->Ncolors[2]);
else
TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors);
@@ -296,8 +297,8 @@ create_colormap (j_decompress_ptr cinfo)
/* i.e. rightmost (highest-indexed) color changes most rapidly. */
colormap = (*cinfo->mem->alloc_sarray)
- ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (JDIMENSION) total_colors, (JDIMENSION) cinfo->out_color_components);
+ ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (JDIMENSION)total_colors, (JDIMENSION)cinfo->out_color_components);
/* blksize is number of adjacent repeated entries for a component */
/* blkdist is distance between groups of identical entries for a component */
@@ -309,12 +310,12 @@ create_colormap (j_decompress_ptr cinfo)
blksize = blkdist / nci;
for (j = 0; j < nci; j++) {
/* Compute j'th output value (out of nci) for component */
- val = output_value(cinfo, i, j, nci-1);
+ val = output_value(cinfo, i, j, nci - 1);
/* Fill in all colormap entries that have this value of this component */
for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) {
/* fill in blksize entries beginning at ptr */
for (k = 0; k < blksize; k++)
- colormap[i][ptr+k] = (JSAMPLE) val;
+ colormap[i][ptr + k] = (JSAMPLE)val;
}
}
blkdist = blksize; /* blksize of this color is blkdist of next */
@@ -333,11 +334,11 @@ create_colormap (j_decompress_ptr cinfo)
*/
LOCAL(void)
-create_colorindex (j_decompress_ptr cinfo)
+create_colorindex(j_decompress_ptr cinfo)
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
JSAMPROW indexptr;
- int i,j,k, nci, blksize, val, pad;
+ int i, j, k, nci, blksize, val, pad;
/* For ordered dither, we pad the color index tables by MAXJSAMPLE in
* each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE).
@@ -345,7 +346,7 @@ create_colorindex (j_decompress_ptr cinfo)
* flag whether it was done in case user changes dithering mode.
*/
if (cinfo->dither_mode == JDITHER_ORDERED) {
- pad = MAXJSAMPLE*2;
+ pad = MAXJSAMPLE * 2;
cquantize->is_padded = TRUE;
} else {
pad = 0;
@@ -353,9 +354,9 @@ create_colorindex (j_decompress_ptr cinfo)
}
cquantize->colorindex = (*cinfo->mem->alloc_sarray)
- ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (JDIMENSION) (MAXJSAMPLE+1 + pad),
- (JDIMENSION) cinfo->out_color_components);
+ ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (JDIMENSION)(MAXJSAMPLE + 1 + pad),
+ (JDIMENSION)cinfo->out_color_components);
/* blksize is number of adjacent repeated entries for a component */
blksize = cquantize->sv_actual;
@@ -373,18 +374,18 @@ create_colorindex (j_decompress_ptr cinfo)
/* and k = largest j that maps to current val */
indexptr = cquantize->colorindex[i];
val = 0;
- k = largest_input_value(cinfo, i, 0, nci-1);
+ k = largest_input_value(cinfo, i, 0, nci - 1);
for (j = 0; j <= MAXJSAMPLE; j++) {
while (j > k) /* advance val if past boundary */
- k = largest_input_value(cinfo, i, ++val, nci-1);
+ k = largest_input_value(cinfo, i, ++val, nci - 1);
/* premultiply so that no multiplication needed in main processing */
- indexptr[j] = (JSAMPLE) (val * blksize);
+ indexptr[j] = (JSAMPLE)(val * blksize);
}
/* Pad at both ends if necessary */
if (pad)
for (j = 1; j <= MAXJSAMPLE; j++) {
indexptr[-j] = indexptr[0];
- indexptr[MAXJSAMPLE+j] = indexptr[MAXJSAMPLE];
+ indexptr[MAXJSAMPLE + j] = indexptr[MAXJSAMPLE];
}
}
}
@@ -396,29 +397,29 @@ create_colorindex (j_decompress_ptr cinfo)
*/
LOCAL(ODITHER_MATRIX_PTR)
-make_odither_array (j_decompress_ptr cinfo, int ncolors)
+make_odither_array(j_decompress_ptr cinfo, int ncolors)
{
ODITHER_MATRIX_PTR odither;
- int j,k;
- JLONG num,den;
+ int j, k;
+ JLONG num, den;
odither = (ODITHER_MATRIX_PTR)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(ODITHER_MATRIX));
/* The inter-value distance for this color is MAXJSAMPLE/(ncolors-1).
* Hence the dither value for the matrix cell with fill order f
* (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1).
* On 16-bit-int machine, be careful to avoid overflow.
*/
- den = 2 * ODITHER_CELLS * ((JLONG) (ncolors - 1));
+ den = 2 * ODITHER_CELLS * ((JLONG)(ncolors - 1));
for (j = 0; j < ODITHER_SIZE; j++) {
for (k = 0; k < ODITHER_SIZE; k++) {
- num = ((JLONG) (ODITHER_CELLS-1 - 2*((int)base_dither_matrix[j][k])))
- * MAXJSAMPLE;
+ num = ((JLONG)(ODITHER_CELLS - 1 -
+ 2 * ((int)base_dither_matrix[j][k]))) * MAXJSAMPLE;
/* Ensure round towards zero despite C's lack of consistency
* about rounding negative values in integer division...
*/
- odither[j][k] = (int) (num<0 ? -((-num)/den) : num/den);
+ odither[j][k] = (int)(num < 0 ? -((-num) / den) : num / den);
}
}
return odither;
@@ -432,9 +433,9 @@ make_odither_array (j_decompress_ptr cinfo, int ncolors)
*/
LOCAL(void)
-create_odither_tables (j_decompress_ptr cinfo)
+create_odither_tables(j_decompress_ptr cinfo)
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
ODITHER_MATRIX_PTR odither;
int i, j, nci;
@@ -459,11 +460,11 @@ create_odither_tables (j_decompress_ptr cinfo)
*/
METHODDEF(void)
-color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
- JSAMPARRAY output_buf, int num_rows)
+color_quantize(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
/* General case, no dithering */
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
JSAMPARRAY colorindex = cquantize->colorindex;
register int pixcode, ci;
register JSAMPROW ptrin, ptrout;
@@ -480,18 +481,18 @@ color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
for (ci = 0; ci < nc; ci++) {
pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]);
}
- *ptrout++ = (JSAMPLE) pixcode;
+ *ptrout++ = (JSAMPLE)pixcode;
}
}
}
METHODDEF(void)
-color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
- JSAMPARRAY output_buf, int num_rows)
+color_quantize3(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
/* Fast path for out_color_components==3, no dithering */
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
register int pixcode;
register JSAMPROW ptrin, ptrout;
JSAMPROW colorindex0 = cquantize->colorindex[0];
@@ -508,18 +509,18 @@ color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]);
pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]);
pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]);
- *ptrout++ = (JSAMPLE) pixcode;
+ *ptrout++ = (JSAMPLE)pixcode;
}
}
}
METHODDEF(void)
-quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
- JSAMPARRAY output_buf, int num_rows)
+quantize_ord_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
/* General case, with ordered dithering */
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
register JSAMPROW input_ptr;
register JSAMPROW output_ptr;
JSAMPROW colorindex_ci;
@@ -533,7 +534,7 @@ quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
for (row = 0; row < num_rows; row++) {
/* Initialize output values to 0 so can process components separately */
- jzero_far((void *) output_buf[row], (size_t) (width * sizeof(JSAMPLE)));
+ jzero_far((void *)output_buf[row], (size_t)(width * sizeof(JSAMPLE)));
row_index = cquantize->row_index;
for (ci = 0; ci < nc; ci++) {
input_ptr = input_buf[row] + ci;
@@ -550,7 +551,8 @@ quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
* inputs. The maximum dither is +- MAXJSAMPLE; this sets the
* required amount of padding.
*/
- *output_ptr += colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]];
+ *output_ptr +=
+ colorindex_ci[GETJSAMPLE(*input_ptr) + dither[col_index]];
input_ptr += nc;
output_ptr++;
col_index = (col_index + 1) & ODITHER_MASK;
@@ -564,11 +566,11 @@ quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
METHODDEF(void)
-quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
- JSAMPARRAY output_buf, int num_rows)
+quantize3_ord_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
/* Fast path for out_color_components==3, with ordered dithering */
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
register int pixcode;
register JSAMPROW input_ptr;
register JSAMPROW output_ptr;
@@ -593,13 +595,13 @@ quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
col_index = 0;
for (col = width; col > 0; col--) {
- pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) +
- dither0[col_index]]);
- pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) +
- dither1[col_index]]);
- pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) +
- dither2[col_index]]);
- *output_ptr++ = (JSAMPLE) pixcode;
+ pixcode =
+ GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) + dither0[col_index]]);
+ pixcode +=
+ GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) + dither1[col_index]]);
+ pixcode +=
+ GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) + dither2[col_index]]);
+ *output_ptr++ = (JSAMPLE)pixcode;
col_index = (col_index + 1) & ODITHER_MASK;
}
row_index = (row_index + 1) & ODITHER_MASK;
@@ -609,11 +611,11 @@ quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
METHODDEF(void)
-quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
- JSAMPARRAY output_buf, int num_rows)
+quantize_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
/* General case, with Floyd-Steinberg dithering */
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
register LOCFSERROR cur; /* current error or pixel value */
LOCFSERROR belowerr; /* error for pixel below cur */
LOCFSERROR bpreverr; /* error for below/prev col */
@@ -637,17 +639,17 @@ quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
for (row = 0; row < num_rows; row++) {
/* Initialize output values to 0 so can process components separately */
- jzero_far((void *) output_buf[row], (size_t) (width * sizeof(JSAMPLE)));
+ jzero_far((void *)output_buf[row], (size_t)(width * sizeof(JSAMPLE)));
for (ci = 0; ci < nc; ci++) {
input_ptr = input_buf[row] + ci;
output_ptr = output_buf[row];
if (cquantize->on_odd_row) {
/* work right to left in this row */
- input_ptr += (width-1) * nc; /* so point to rightmost pixel */
- output_ptr += width-1;
+ input_ptr += (width - 1) * nc; /* so point to rightmost pixel */
+ output_ptr += width - 1;
dir = -1;
dirnc = -nc;
- errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */
+ errorptr = cquantize->fserrors[ci] + (width + 1); /* => entry after last column */
} else {
/* work left to right in this row */
dir = 1;
@@ -679,7 +681,7 @@ quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
cur = GETJSAMPLE(range_limit[cur]);
/* Select output value, accumulate into output code for this pixel */
pixcode = GETJSAMPLE(colorindex_ci[cur]);
- *output_ptr += (JSAMPLE) pixcode;
+ *output_ptr += (JSAMPLE)pixcode;
/* Compute actual representation error at this pixel */
/* Note: we can do this even though we don't have the final */
/* pixel code, because the colormap is orthogonal. */
@@ -691,7 +693,7 @@ quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
bnexterr = cur;
delta = cur * 2;
cur += delta; /* form error * 3 */
- errorptr[0] = (FSERROR) (bpreverr + cur);
+ errorptr[0] = (FSERROR)(bpreverr + cur);
cur += delta; /* form error * 5 */
bpreverr = belowerr + cur;
belowerr = bnexterr;
@@ -708,7 +710,7 @@ quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
* final fserrors[] entry. Note we need not unload belowerr because
* it is for the dummy column before or after the actual array.
*/
- errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */
+ errorptr[0] = (FSERROR)bpreverr; /* unload prev err into array */
}
cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE);
}
@@ -720,16 +722,16 @@ quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
*/
LOCAL(void)
-alloc_fs_workspace (j_decompress_ptr cinfo)
+alloc_fs_workspace(j_decompress_ptr cinfo)
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
size_t arraysize;
int i;
- arraysize = (size_t) ((cinfo->output_width + 2) * sizeof(FSERROR));
+ arraysize = (size_t)((cinfo->output_width + 2) * sizeof(FSERROR));
for (i = 0; i < cinfo->out_color_components; i++) {
cquantize->fserrors[i] = (FSERRPTR)
- (*cinfo->mem->alloc_large)((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize);
+ (*cinfo->mem->alloc_large) ((j_common_ptr)cinfo, JPOOL_IMAGE, arraysize);
}
}
@@ -739,9 +741,9 @@ alloc_fs_workspace (j_decompress_ptr cinfo)
*/
METHODDEF(void)
-start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
+start_pass_1_quant(j_decompress_ptr cinfo, boolean is_pre_scan)
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
size_t arraysize;
int i;
@@ -767,7 +769,7 @@ start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
* we must recreate the color index table with padding.
* This will cost extra space, but probably isn't very likely.
*/
- if (! cquantize->is_padded)
+ if (!cquantize->is_padded)
create_colorindex(cinfo);
/* Create ordered-dither tables if we didn't already. */
if (cquantize->odither[0] == NULL)
@@ -780,9 +782,9 @@ start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
if (cquantize->fserrors[0] == NULL)
alloc_fs_workspace(cinfo);
/* Initialize the propagated errors to zero. */
- arraysize = (size_t) ((cinfo->output_width + 2) * sizeof(FSERROR));
+ arraysize = (size_t)((cinfo->output_width + 2) * sizeof(FSERROR));
for (i = 0; i < cinfo->out_color_components; i++)
- jzero_far((void *) cquantize->fserrors[i], arraysize);
+ jzero_far((void *)cquantize->fserrors[i], arraysize);
break;
default:
ERREXIT(cinfo, JERR_NOT_COMPILED);
@@ -796,7 +798,7 @@ start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
*/
METHODDEF(void)
-finish_pass_1_quant (j_decompress_ptr cinfo)
+finish_pass_1_quant(j_decompress_ptr cinfo)
{
/* no work in 1-pass case */
}
@@ -808,7 +810,7 @@ finish_pass_1_quant (j_decompress_ptr cinfo)
*/
METHODDEF(void)
-new_color_map_1_quant (j_decompress_ptr cinfo)
+new_color_map_1_quant(j_decompress_ptr cinfo)
{
ERREXIT(cinfo, JERR_MODE_CHANGE);
}
@@ -819,14 +821,14 @@ new_color_map_1_quant (j_decompress_ptr cinfo)
*/
GLOBAL(void)
-jinit_1pass_quantizer (j_decompress_ptr cinfo)
+jinit_1pass_quantizer(j_decompress_ptr cinfo)
{
my_cquantize_ptr cquantize;
cquantize = (my_cquantize_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_cquantizer));
- cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize;
+ cinfo->cquantize = (struct jpeg_color_quantizer *)cquantize;
cquantize->pub.start_pass = start_pass_1_quant;
cquantize->pub.finish_pass = finish_pass_1_quant;
cquantize->pub.new_color_map = new_color_map_1_quant;
@@ -837,8 +839,8 @@ jinit_1pass_quantizer (j_decompress_ptr cinfo)
if (cinfo->out_color_components > MAX_Q_COMPS)
ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS);
/* Make sure colormap indexes can be represented by JSAMPLEs */
- if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1))
- ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1);
+ if (cinfo->desired_number_of_colors > (MAXJSAMPLE + 1))
+ ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE + 1);
/* Create the colormap and color index table. */
create_colormap(cinfo);
diff --git a/src/3rdparty/libjpeg/src/jquant2.c b/src/3rdparty/libjpeg/src/jquant2.c
index cfbd0f1526..0ce0ca5472 100644
--- a/src/3rdparty/libjpeg/src/jquant2.c
+++ b/src/3rdparty/libjpeg/src/jquant2.c
@@ -73,14 +73,14 @@
* probably need to change these scale factors.
*/
-#define R_SCALE 2 /* scale R distances by this much */
-#define G_SCALE 3 /* scale G distances by this much */
-#define B_SCALE 1 /* and B by this much */
+#define R_SCALE 2 /* scale R distances by this much */
+#define G_SCALE 3 /* scale G distances by this much */
+#define B_SCALE 1 /* and B by this much */
-static const int c_scales[3]={R_SCALE, G_SCALE, B_SCALE};
-#define C0_SCALE c_scales[rgb_red[cinfo->out_color_space]]
-#define C1_SCALE c_scales[rgb_green[cinfo->out_color_space]]
-#define C2_SCALE c_scales[rgb_blue[cinfo->out_color_space]]
+static const int c_scales[3] = { R_SCALE, G_SCALE, B_SCALE };
+#define C0_SCALE c_scales[rgb_red[cinfo->out_color_space]]
+#define C1_SCALE c_scales[rgb_green[cinfo->out_color_space]]
+#define C2_SCALE c_scales[rgb_blue[cinfo->out_color_space]]
/*
* First we have the histogram data structure and routines for creating it.
@@ -106,7 +106,7 @@ static const int c_scales[3]={R_SCALE, G_SCALE, B_SCALE};
* each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries.
*/
-#define MAXNUMCOLORS (MAXJSAMPLE+1) /* maximum size of colormap */
+#define MAXNUMCOLORS (MAXJSAMPLE + 1) /* maximum size of colormap */
/* These will do the right thing for either R,G,B or B,G,R color order,
* but you may not like the results for other color orders.
@@ -116,19 +116,19 @@ static const int c_scales[3]={R_SCALE, G_SCALE, B_SCALE};
#define HIST_C2_BITS 5 /* bits of precision in B/R histogram */
/* Number of elements along histogram axes. */
-#define HIST_C0_ELEMS (1<<HIST_C0_BITS)
-#define HIST_C1_ELEMS (1<<HIST_C1_BITS)
-#define HIST_C2_ELEMS (1<<HIST_C2_BITS)
+#define HIST_C0_ELEMS (1 << HIST_C0_BITS)
+#define HIST_C1_ELEMS (1 << HIST_C1_BITS)
+#define HIST_C2_ELEMS (1 << HIST_C2_BITS)
/* These are the amounts to shift an input value to get a histogram index. */
-#define C0_SHIFT (BITS_IN_JSAMPLE-HIST_C0_BITS)
-#define C1_SHIFT (BITS_IN_JSAMPLE-HIST_C1_BITS)
-#define C2_SHIFT (BITS_IN_JSAMPLE-HIST_C2_BITS)
+#define C0_SHIFT (BITS_IN_JSAMPLE - HIST_C0_BITS)
+#define C1_SHIFT (BITS_IN_JSAMPLE - HIST_C1_BITS)
+#define C2_SHIFT (BITS_IN_JSAMPLE - HIST_C2_BITS)
typedef UINT16 histcell; /* histogram cell; prefer an unsigned type */
-typedef histcell *histptr; /* for pointers to histogram cells */
+typedef histcell *histptr; /* for pointers to histogram cells */
typedef histcell hist1d[HIST_C2_ELEMS]; /* typedefs for the array */
typedef hist1d *hist2d; /* type for the 2nd-level pointers */
@@ -200,10 +200,10 @@ typedef my_cquantizer *my_cquantize_ptr;
*/
METHODDEF(void)
-prescan_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
- JSAMPARRAY output_buf, int num_rows)
+prescan_quantize(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
register JSAMPROW ptr;
register histptr histp;
register hist3d histogram = cquantize->histogram;
@@ -215,9 +215,9 @@ prescan_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
ptr = input_buf[row];
for (col = width; col > 0; col--) {
/* get pixel value and index into the histogram */
- histp = & histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT]
- [GETJSAMPLE(ptr[1]) >> C1_SHIFT]
- [GETJSAMPLE(ptr[2]) >> C2_SHIFT];
+ histp = &histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT]
+ [GETJSAMPLE(ptr[1]) >> C1_SHIFT]
+ [GETJSAMPLE(ptr[2]) >> C2_SHIFT];
/* increment, check for overflow and undo increment if so. */
if (++(*histp) <= 0)
(*histp)--;
@@ -249,7 +249,7 @@ typedef box *boxptr;
LOCAL(boxptr)
-find_biggest_color_pop (boxptr boxlist, int numboxes)
+find_biggest_color_pop(boxptr boxlist, int numboxes)
/* Find the splittable box with the largest color population */
/* Returns NULL if no splittable boxes remain */
{
@@ -269,7 +269,7 @@ find_biggest_color_pop (boxptr boxlist, int numboxes)
LOCAL(boxptr)
-find_biggest_volume (boxptr boxlist, int numboxes)
+find_biggest_volume(boxptr boxlist, int numboxes)
/* Find the splittable box with the largest (scaled) volume */
/* Returns NULL if no splittable boxes remain */
{
@@ -289,16 +289,16 @@ find_biggest_volume (boxptr boxlist, int numboxes)
LOCAL(void)
-update_box (j_decompress_ptr cinfo, boxptr boxp)
+update_box(j_decompress_ptr cinfo, boxptr boxp)
/* Shrink the min/max bounds of a box to enclose only nonzero elements, */
/* and recompute its volume and population */
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
hist3d histogram = cquantize->histogram;
histptr histp;
- int c0,c1,c2;
- int c0min,c0max,c1min,c1max,c2min,c2max;
- JLONG dist0,dist1,dist2;
+ int c0, c1, c2;
+ int c0min, c0max, c1min, c1max, c2min, c2max;
+ JLONG dist0, dist1, dist2;
long ccount;
c0min = boxp->c0min; c0max = boxp->c0max;
@@ -308,69 +308,69 @@ update_box (j_decompress_ptr cinfo, boxptr boxp)
if (c0max > c0min)
for (c0 = c0min; c0 <= c0max; c0++)
for (c1 = c1min; c1 <= c1max; c1++) {
- histp = & histogram[c0][c1][c2min];
+ histp = &histogram[c0][c1][c2min];
for (c2 = c2min; c2 <= c2max; c2++)
if (*histp++ != 0) {
boxp->c0min = c0min = c0;
goto have_c0min;
}
}
- have_c0min:
+have_c0min:
if (c0max > c0min)
for (c0 = c0max; c0 >= c0min; c0--)
for (c1 = c1min; c1 <= c1max; c1++) {
- histp = & histogram[c0][c1][c2min];
+ histp = &histogram[c0][c1][c2min];
for (c2 = c2min; c2 <= c2max; c2++)
if (*histp++ != 0) {
boxp->c0max = c0max = c0;
goto have_c0max;
}
}
- have_c0max:
+have_c0max:
if (c1max > c1min)
for (c1 = c1min; c1 <= c1max; c1++)
for (c0 = c0min; c0 <= c0max; c0++) {
- histp = & histogram[c0][c1][c2min];
+ histp = &histogram[c0][c1][c2min];
for (c2 = c2min; c2 <= c2max; c2++)
if (*histp++ != 0) {
boxp->c1min = c1min = c1;
goto have_c1min;
}
}
- have_c1min:
+have_c1min:
if (c1max > c1min)
for (c1 = c1max; c1 >= c1min; c1--)
for (c0 = c0min; c0 <= c0max; c0++) {
- histp = & histogram[c0][c1][c2min];
+ histp = &histogram[c0][c1][c2min];
for (c2 = c2min; c2 <= c2max; c2++)
if (*histp++ != 0) {
boxp->c1max = c1max = c1;
goto have_c1max;
}
}
- have_c1max:
+have_c1max:
if (c2max > c2min)
for (c2 = c2min; c2 <= c2max; c2++)
for (c0 = c0min; c0 <= c0max; c0++) {
- histp = & histogram[c0][c1min][c2];
+ histp = &histogram[c0][c1min][c2];
for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS)
if (*histp != 0) {
boxp->c2min = c2min = c2;
goto have_c2min;
}
}
- have_c2min:
+have_c2min:
if (c2max > c2min)
for (c2 = c2max; c2 >= c2min; c2--)
for (c0 = c0min; c0 <= c0max; c0++) {
- histp = & histogram[c0][c1min][c2];
+ histp = &histogram[c0][c1min][c2];
for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS)
if (*histp != 0) {
boxp->c2max = c2max = c2;
goto have_c2max;
}
}
- have_c2max:
+have_c2max:
/* Update box volume.
* We use 2-norm rather than real volume here; this biases the method
@@ -383,13 +383,13 @@ update_box (j_decompress_ptr cinfo, boxptr boxp)
dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE;
dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE;
dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE;
- boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2;
+ boxp->volume = dist0 * dist0 + dist1 * dist1 + dist2 * dist2;
/* Now scan remaining volume of box and compute population */
ccount = 0;
for (c0 = c0min; c0 <= c0max; c0++)
for (c1 = c1min; c1 <= c1max; c1++) {
- histp = & histogram[c0][c1][c2min];
+ histp = &histogram[c0][c1][c2min];
for (c2 = c2min; c2 <= c2max; c2++, histp++)
if (*histp != 0) {
ccount++;
@@ -400,19 +400,19 @@ update_box (j_decompress_ptr cinfo, boxptr boxp)
LOCAL(int)
-median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes,
- int desired_colors)
+median_cut(j_decompress_ptr cinfo, boxptr boxlist, int numboxes,
+ int desired_colors)
/* Repeatedly select and split the largest box until we have enough boxes */
{
- int n,lb;
- int c0,c1,c2,cmax;
- register boxptr b1,b2;
+ int n, lb;
+ int c0, c1, c2, cmax;
+ register boxptr b1, b2;
while (numboxes < desired_colors) {
/* Select box to split.
* Current algorithm: by population for first half, then by volume.
*/
- if (numboxes*2 <= desired_colors) {
+ if (numboxes * 2 <= desired_colors) {
b1 = find_biggest_color_pop(boxlist, numboxes);
} else {
b1 = find_biggest_volume(boxlist, numboxes);
@@ -421,8 +421,8 @@ median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes,
break;
b2 = &boxlist[numboxes]; /* where new box will go */
/* Copy the color bounds to the new box. */
- b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max;
- b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min;
+ b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max;
+ b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min;
/* Choose which axis to split the box on.
* Current algorithm: longest scaled axis.
* See notes in update_box about scaling distances.
@@ -434,13 +434,12 @@ median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes,
* This code does the right thing for R,G,B or B,G,R color orders only.
*/
if (rgb_red[cinfo->out_color_space] == 0) {
- cmax = c1; n = 1;
- if (c0 > cmax) { cmax = c0; n = 0; }
+ cmax = c1; n = 1;
+ if (c0 > cmax) { cmax = c0; n = 0; }
if (c2 > cmax) { n = 2; }
- }
- else {
- cmax = c1; n = 1;
- if (c2 > cmax) { cmax = c2; n = 2; }
+ } else {
+ cmax = c1; n = 1;
+ if (c2 > cmax) { cmax = c2; n = 2; }
if (c0 > cmax) { n = 0; }
}
/* Choose split point along selected axis, and update box bounds.
@@ -453,17 +452,17 @@ median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes,
case 0:
lb = (b1->c0max + b1->c0min) / 2;
b1->c0max = lb;
- b2->c0min = lb+1;
+ b2->c0min = lb + 1;
break;
case 1:
lb = (b1->c1max + b1->c1min) / 2;
b1->c1max = lb;
- b2->c1min = lb+1;
+ b2->c1min = lb + 1;
break;
case 2:
lb = (b1->c2max + b1->c2min) / 2;
b1->c2max = lb;
- b2->c2min = lb+1;
+ b2->c2min = lb + 1;
break;
}
/* Update stats for boxes */
@@ -476,16 +475,16 @@ median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes,
LOCAL(void)
-compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor)
+compute_color(j_decompress_ptr cinfo, boxptr boxp, int icolor)
/* Compute representative color for a box, put it in colormap[icolor] */
{
/* Current algorithm: mean weighted by pixels (not colors) */
/* Note it is important to get the rounding correct! */
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
hist3d histogram = cquantize->histogram;
histptr histp;
- int c0,c1,c2;
- int c0min,c0max,c1min,c1max,c2min,c2max;
+ int c0, c1, c2;
+ int c0min, c0max, c1min, c1max, c2min, c2max;
long count;
long total = 0;
long c0total = 0;
@@ -498,25 +497,25 @@ compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor)
for (c0 = c0min; c0 <= c0max; c0++)
for (c1 = c1min; c1 <= c1max; c1++) {
- histp = & histogram[c0][c1][c2min];
+ histp = &histogram[c0][c1][c2min];
for (c2 = c2min; c2 <= c2max; c2++) {
if ((count = *histp++) != 0) {
total += count;
- c0total += ((c0 << C0_SHIFT) + ((1<<C0_SHIFT)>>1)) * count;
- c1total += ((c1 << C1_SHIFT) + ((1<<C1_SHIFT)>>1)) * count;
- c2total += ((c2 << C2_SHIFT) + ((1<<C2_SHIFT)>>1)) * count;
+ c0total += ((c0 << C0_SHIFT) + ((1 << C0_SHIFT) >> 1)) * count;
+ c1total += ((c1 << C1_SHIFT) + ((1 << C1_SHIFT) >> 1)) * count;
+ c2total += ((c2 << C2_SHIFT) + ((1 << C2_SHIFT) >> 1)) * count;
}
}
}
- cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total);
- cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total);
- cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total);
+ cinfo->colormap[0][icolor] = (JSAMPLE)((c0total + (total >> 1)) / total);
+ cinfo->colormap[1][icolor] = (JSAMPLE)((c1total + (total >> 1)) / total);
+ cinfo->colormap[2][icolor] = (JSAMPLE)((c2total + (total >> 1)) / total);
}
LOCAL(void)
-select_colors (j_decompress_ptr cinfo, int desired_colors)
+select_colors(j_decompress_ptr cinfo, int desired_colors)
/* Master routine for color selection */
{
boxptr boxlist;
@@ -524,8 +523,8 @@ select_colors (j_decompress_ptr cinfo, int desired_colors)
int i;
/* Allocate workspace for box list */
- boxlist = (boxptr) (*cinfo->mem->alloc_small)
- ((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * sizeof(box));
+ boxlist = (boxptr)(*cinfo->mem->alloc_small)
+ ((j_common_ptr)cinfo, JPOOL_IMAGE, desired_colors * sizeof(box));
/* Initialize one box containing whole space */
numboxes = 1;
boxlist[0].c0min = 0;
@@ -535,12 +534,12 @@ select_colors (j_decompress_ptr cinfo, int desired_colors)
boxlist[0].c2min = 0;
boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT;
/* Shrink it to actually-used volume and set its statistics */
- update_box(cinfo, & boxlist[0]);
+ update_box(cinfo, &boxlist[0]);
/* Perform median-cut to produce final box list */
numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors);
/* Compute the representative color for each box, fill colormap */
for (i = 0; i < numboxes; i++)
- compute_color(cinfo, & boxlist[i], i);
+ compute_color(cinfo, &boxlist[i], i);
cinfo->actual_number_of_colors = numboxes;
TRACEMS1(cinfo, 1, JTRC_QUANT_SELECTED, numboxes);
}
@@ -601,13 +600,13 @@ select_colors (j_decompress_ptr cinfo, int desired_colors)
/* log2(histogram cells in update box) for each axis; this can be adjusted */
-#define BOX_C0_LOG (HIST_C0_BITS-3)
-#define BOX_C1_LOG (HIST_C1_BITS-3)
-#define BOX_C2_LOG (HIST_C2_BITS-3)
+#define BOX_C0_LOG (HIST_C0_BITS - 3)
+#define BOX_C1_LOG (HIST_C1_BITS - 3)
+#define BOX_C2_LOG (HIST_C2_BITS - 3)
-#define BOX_C0_ELEMS (1<<BOX_C0_LOG) /* # of hist cells in update box */
-#define BOX_C1_ELEMS (1<<BOX_C1_LOG)
-#define BOX_C2_ELEMS (1<<BOX_C2_LOG)
+#define BOX_C0_ELEMS (1 << BOX_C0_LOG) /* # of hist cells in update box */
+#define BOX_C1_ELEMS (1 << BOX_C1_LOG)
+#define BOX_C2_ELEMS (1 << BOX_C2_LOG)
#define BOX_C0_SHIFT (C0_SHIFT + BOX_C0_LOG)
#define BOX_C1_SHIFT (C1_SHIFT + BOX_C1_LOG)
@@ -623,8 +622,8 @@ select_colors (j_decompress_ptr cinfo, int desired_colors)
*/
LOCAL(int)
-find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
- JSAMPLE colorlist[])
+find_nearby_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
+ JSAMPLE colorlist[])
/* Locate the colormap entries close enough to an update box to be candidates
* for the nearest entry to some cell(s) in the update box. The update box
* is specified by the center coordinates of its first cell. The number of
@@ -669,67 +668,67 @@ find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
x = GETJSAMPLE(cinfo->colormap[0][i]);
if (x < minc0) {
tdist = (x - minc0) * C0_SCALE;
- min_dist = tdist*tdist;
+ min_dist = tdist * tdist;
tdist = (x - maxc0) * C0_SCALE;
- max_dist = tdist*tdist;
+ max_dist = tdist * tdist;
} else if (x > maxc0) {
tdist = (x - maxc0) * C0_SCALE;
- min_dist = tdist*tdist;
+ min_dist = tdist * tdist;
tdist = (x - minc0) * C0_SCALE;
- max_dist = tdist*tdist;
+ max_dist = tdist * tdist;
} else {
/* within cell range so no contribution to min_dist */
min_dist = 0;
if (x <= centerc0) {
tdist = (x - maxc0) * C0_SCALE;
- max_dist = tdist*tdist;
+ max_dist = tdist * tdist;
} else {
tdist = (x - minc0) * C0_SCALE;
- max_dist = tdist*tdist;
+ max_dist = tdist * tdist;
}
}
x = GETJSAMPLE(cinfo->colormap[1][i]);
if (x < minc1) {
tdist = (x - minc1) * C1_SCALE;
- min_dist += tdist*tdist;
+ min_dist += tdist * tdist;
tdist = (x - maxc1) * C1_SCALE;
- max_dist += tdist*tdist;
+ max_dist += tdist * tdist;
} else if (x > maxc1) {
tdist = (x - maxc1) * C1_SCALE;
- min_dist += tdist*tdist;
+ min_dist += tdist * tdist;
tdist = (x - minc1) * C1_SCALE;
- max_dist += tdist*tdist;
+ max_dist += tdist * tdist;
} else {
/* within cell range so no contribution to min_dist */
if (x <= centerc1) {
tdist = (x - maxc1) * C1_SCALE;
- max_dist += tdist*tdist;
+ max_dist += tdist * tdist;
} else {
tdist = (x - minc1) * C1_SCALE;
- max_dist += tdist*tdist;
+ max_dist += tdist * tdist;
}
}
x = GETJSAMPLE(cinfo->colormap[2][i]);
if (x < minc2) {
tdist = (x - minc2) * C2_SCALE;
- min_dist += tdist*tdist;
+ min_dist += tdist * tdist;
tdist = (x - maxc2) * C2_SCALE;
- max_dist += tdist*tdist;
+ max_dist += tdist * tdist;
} else if (x > maxc2) {
tdist = (x - maxc2) * C2_SCALE;
- min_dist += tdist*tdist;
+ min_dist += tdist * tdist;
tdist = (x - minc2) * C2_SCALE;
- max_dist += tdist*tdist;
+ max_dist += tdist * tdist;
} else {
/* within cell range so no contribution to min_dist */
if (x <= centerc2) {
tdist = (x - maxc2) * C2_SCALE;
- max_dist += tdist*tdist;
+ max_dist += tdist * tdist;
} else {
tdist = (x - minc2) * C2_SCALE;
- max_dist += tdist*tdist;
+ max_dist += tdist * tdist;
}
}
@@ -745,15 +744,15 @@ find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
ncolors = 0;
for (i = 0; i < numcolors; i++) {
if (mindist[i] <= minmaxdist)
- colorlist[ncolors++] = (JSAMPLE) i;
+ colorlist[ncolors++] = (JSAMPLE)i;
}
return ncolors;
}
LOCAL(void)
-find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
- int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[])
+find_best_colors(j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
+ int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[])
/* Find the closest colormap entry for each cell in the update box,
* given the list of candidate colors prepared by find_nearby_colors.
* Return the indexes of the closest entries in the bestcolor[] array.
@@ -775,7 +774,7 @@ find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
/* Initialize best-distance for each cell of the update box */
bptr = bestdist;
- for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--)
+ for (i = BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS - 1; i >= 0; i--)
*bptr++ = 0x7FFFFFFFL;
/* For each color selected by find_nearby_colors,
@@ -792,11 +791,11 @@ find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
icolor = GETJSAMPLE(colorlist[i]);
/* Compute (square of) distance from minc0/c1/c2 to this color */
inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE;
- dist0 = inc0*inc0;
+ dist0 = inc0 * inc0;
inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE;
- dist0 += inc1*inc1;
+ dist0 += inc1 * inc1;
inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE;
- dist0 += inc2*inc2;
+ dist0 += inc2 * inc2;
/* Form the initial difference increments */
inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0;
inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1;
@@ -805,16 +804,16 @@ find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
bptr = bestdist;
cptr = bestcolor;
xx0 = inc0;
- for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) {
+ for (ic0 = BOX_C0_ELEMS - 1; ic0 >= 0; ic0--) {
dist1 = dist0;
xx1 = inc1;
- for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) {
+ for (ic1 = BOX_C1_ELEMS - 1; ic1 >= 0; ic1--) {
dist2 = dist1;
xx2 = inc2;
- for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) {
+ for (ic2 = BOX_C2_ELEMS - 1; ic2 >= 0; ic2--) {
if (dist2 < *bptr) {
*bptr = dist2;
- *cptr = (JSAMPLE) icolor;
+ *cptr = (JSAMPLE)icolor;
}
dist2 += xx2;
xx2 += 2 * STEP_C2 * STEP_C2;
@@ -832,12 +831,12 @@ find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
LOCAL(void)
-fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2)
+fill_inverse_cmap(j_decompress_ptr cinfo, int c0, int c1, int c2)
/* Fill the inverse-colormap entries in the update box that contains */
/* histogram cell c0/c1/c2. (Only that one cell MUST be filled, but */
/* we can fill as many others as we wish.) */
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
hist3d histogram = cquantize->histogram;
int minc0, minc1, minc2; /* lower left corner of update box */
int ic0, ic1, ic2;
@@ -878,9 +877,9 @@ fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2)
cptr = bestcolor;
for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) {
for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) {
- cachep = & histogram[c0+ic0][c1+ic1][c2];
+ cachep = &histogram[c0 + ic0][c1 + ic1][c2];
for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) {
- *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1);
+ *cachep++ = (histcell)(GETJSAMPLE(*cptr++) + 1);
}
}
}
@@ -892,11 +891,11 @@ fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2)
*/
METHODDEF(void)
-pass2_no_dither (j_decompress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows)
+pass2_no_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
/* This version performs no dithering */
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
hist3d histogram = cquantize->histogram;
register JSAMPROW inptr, outptr;
register histptr cachep;
@@ -913,24 +912,24 @@ pass2_no_dither (j_decompress_ptr cinfo,
c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT;
c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT;
c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT;
- cachep = & histogram[c0][c1][c2];
+ cachep = &histogram[c0][c1][c2];
/* If we have not seen this color before, find nearest colormap entry */
/* and update the cache */
if (*cachep == 0)
- fill_inverse_cmap(cinfo, c0,c1,c2);
+ fill_inverse_cmap(cinfo, c0, c1, c2);
/* Now emit the colormap index for this cell */
- *outptr++ = (JSAMPLE) (*cachep - 1);
+ *outptr++ = (JSAMPLE)(*cachep - 1);
}
}
}
METHODDEF(void)
-pass2_fs_dither (j_decompress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows)
+pass2_fs_dither(j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
/* This version performs Floyd-Steinberg dithering */
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
hist3d histogram = cquantize->histogram;
register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */
LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */
@@ -956,11 +955,11 @@ pass2_fs_dither (j_decompress_ptr cinfo,
outptr = output_buf[row];
if (cquantize->on_odd_row) {
/* work right to left in this row */
- inptr += (width-1) * 3; /* so point to rightmost pixel */
- outptr += width-1;
+ inptr += (width - 1) * 3; /* so point to rightmost pixel */
+ outptr += width - 1;
dir = -1;
dir3 = -3;
- errorptr = cquantize->fserrors + (width+1)*3; /* => entry after last column */
+ errorptr = cquantize->fserrors + (width + 1) * 3; /* => entry after last column */
cquantize->on_odd_row = FALSE; /* flip for next time */
} else {
/* work left to right in this row */
@@ -984,9 +983,9 @@ pass2_fs_dither (j_decompress_ptr cinfo,
* for either sign of the error value.
* Note: errorptr points to *previous* column's array entry.
*/
- cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4);
- cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4);
- cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4);
+ cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3 + 0] + 8, 4);
+ cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3 + 1] + 8, 4);
+ cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3 + 2] + 8, 4);
/* Limit the error using transfer function set by init_error_limit.
* See comments with init_error_limit for rationale.
*/
@@ -1004,14 +1003,17 @@ pass2_fs_dither (j_decompress_ptr cinfo,
cur1 = GETJSAMPLE(range_limit[cur1]);
cur2 = GETJSAMPLE(range_limit[cur2]);
/* Index into the cache with adjusted pixel value */
- cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT];
+ cachep =
+ &histogram[cur0 >> C0_SHIFT][cur1 >> C1_SHIFT][cur2 >> C2_SHIFT];
/* If we have not seen this color before, find nearest colormap */
/* entry and update the cache */
if (*cachep == 0)
- fill_inverse_cmap(cinfo, cur0>>C0_SHIFT,cur1>>C1_SHIFT,cur2>>C2_SHIFT);
+ fill_inverse_cmap(cinfo, cur0 >> C0_SHIFT, cur1 >> C1_SHIFT,
+ cur2 >> C2_SHIFT);
/* Now emit the colormap index for this cell */
- { register int pixcode = *cachep - 1;
- *outptr = (JSAMPLE) pixcode;
+ {
+ register int pixcode = *cachep - 1;
+ *outptr = (JSAMPLE)pixcode;
/* Compute representation error for this pixel */
cur0 -= GETJSAMPLE(colormap0[pixcode]);
cur1 -= GETJSAMPLE(colormap1[pixcode]);
@@ -1021,20 +1023,21 @@ pass2_fs_dither (j_decompress_ptr cinfo,
* Add these into the running sums, and simultaneously shift the
* next-line error sums left by 1 column.
*/
- { register LOCFSERROR bnexterr;
+ {
+ register LOCFSERROR bnexterr;
bnexterr = cur0; /* Process component 0 */
- errorptr[0] = (FSERROR) (bpreverr0 + cur0 * 3);
+ errorptr[0] = (FSERROR)(bpreverr0 + cur0 * 3);
bpreverr0 = belowerr0 + cur0 * 5;
belowerr0 = bnexterr;
cur0 *= 7;
bnexterr = cur1; /* Process component 1 */
- errorptr[1] = (FSERROR) (bpreverr1 + cur1 * 3);
+ errorptr[1] = (FSERROR)(bpreverr1 + cur1 * 3);
bpreverr1 = belowerr1 + cur1 * 5;
belowerr1 = bnexterr;
cur1 *= 7;
bnexterr = cur2; /* Process component 2 */
- errorptr[2] = (FSERROR) (bpreverr2 + cur2 * 3);
+ errorptr[2] = (FSERROR)(bpreverr2 + cur2 * 3);
bpreverr2 = belowerr2 + cur2 * 5;
belowerr2 = bnexterr;
cur2 *= 7;
@@ -1051,9 +1054,9 @@ pass2_fs_dither (j_decompress_ptr cinfo,
* final fserrors[] entry. Note we need not unload belowerrN because
* it is for the dummy column before or after the actual array.
*/
- errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */
- errorptr[1] = (FSERROR) bpreverr1;
- errorptr[2] = (FSERROR) bpreverr2;
+ errorptr[0] = (FSERROR)bpreverr0; /* unload prev errs into array */
+ errorptr[1] = (FSERROR)bpreverr1;
+ errorptr[2] = (FSERROR)bpreverr2;
}
}
@@ -1076,31 +1079,31 @@ pass2_fs_dither (j_decompress_ptr cinfo,
*/
LOCAL(void)
-init_error_limit (j_decompress_ptr cinfo)
+init_error_limit(j_decompress_ptr cinfo)
/* Allocate and fill in the error_limiter table */
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
int *table;
int in, out;
- table = (int *) (*cinfo->mem->alloc_small)
- ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE*2+1) * sizeof(int));
+ table = (int *)(*cinfo->mem->alloc_small)
+ ((j_common_ptr)cinfo, JPOOL_IMAGE, (MAXJSAMPLE * 2 + 1) * sizeof(int));
table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */
cquantize->error_limiter = table;
-#define STEPSIZE ((MAXJSAMPLE+1)/16)
+#define STEPSIZE ((MAXJSAMPLE + 1) / 16)
/* Map errors 1:1 up to +- MAXJSAMPLE/16 */
out = 0;
for (in = 0; in < STEPSIZE; in++, out++) {
- table[in] = out; table[-in] = -out;
+ table[in] = out; table[-in] = -out;
}
/* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */
- for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) {
- table[in] = out; table[-in] = -out;
+ for (; in < STEPSIZE * 3; in++, out += (in & 1) ? 0 : 1) {
+ table[in] = out; table[-in] = -out;
}
/* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */
for (; in <= MAXJSAMPLE; in++) {
- table[in] = out; table[-in] = -out;
+ table[in] = out; table[-in] = -out;
}
#undef STEPSIZE
}
@@ -1111,9 +1114,9 @@ init_error_limit (j_decompress_ptr cinfo)
*/
METHODDEF(void)
-finish_pass1 (j_decompress_ptr cinfo)
+finish_pass1(j_decompress_ptr cinfo)
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
/* Select the representative colors and fill in cinfo->colormap */
cinfo->colormap = cquantize->sv_colormap;
@@ -1124,7 +1127,7 @@ finish_pass1 (j_decompress_ptr cinfo)
METHODDEF(void)
-finish_pass2 (j_decompress_ptr cinfo)
+finish_pass2(j_decompress_ptr cinfo)
{
/* no work */
}
@@ -1135,9 +1138,9 @@ finish_pass2 (j_decompress_ptr cinfo)
*/
METHODDEF(void)
-start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
+start_pass_2_quant(j_decompress_ptr cinfo, boolean is_pre_scan)
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
hist3d histogram = cquantize->histogram;
int i;
@@ -1167,14 +1170,14 @@ start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);
if (cinfo->dither_mode == JDITHER_FS) {
- size_t arraysize = (size_t) ((cinfo->output_width + 2) *
- (3 * sizeof(FSERROR)));
+ size_t arraysize =
+ (size_t)((cinfo->output_width + 2) * (3 * sizeof(FSERROR)));
/* Allocate Floyd-Steinberg workspace if we didn't already. */
if (cquantize->fserrors == NULL)
- cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large)
- ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize);
+ cquantize->fserrors = (FSERRPTR)(*cinfo->mem->alloc_large)
+ ((j_common_ptr)cinfo, JPOOL_IMAGE, arraysize);
/* Initialize the propagated errors to zero. */
- jzero_far((void *) cquantize->fserrors, arraysize);
+ jzero_far((void *)cquantize->fserrors, arraysize);
/* Make the error-limit table if we didn't already. */
if (cquantize->error_limiter == NULL)
init_error_limit(cinfo);
@@ -1185,8 +1188,8 @@ start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
/* Zero the histogram or inverse color map, if necessary */
if (cquantize->needs_zeroed) {
for (i = 0; i < HIST_C0_ELEMS; i++) {
- jzero_far((void *) histogram[i],
- HIST_C1_ELEMS*HIST_C2_ELEMS * sizeof(histcell));
+ jzero_far((void *)histogram[i],
+ HIST_C1_ELEMS * HIST_C2_ELEMS * sizeof(histcell));
}
cquantize->needs_zeroed = FALSE;
}
@@ -1198,9 +1201,9 @@ start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
*/
METHODDEF(void)
-new_color_map_2_quant (j_decompress_ptr cinfo)
+new_color_map_2_quant(j_decompress_ptr cinfo)
{
- my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ my_cquantize_ptr cquantize = (my_cquantize_ptr)cinfo->cquantize;
/* Reset the inverse color map */
cquantize->needs_zeroed = TRUE;
@@ -1212,15 +1215,15 @@ new_color_map_2_quant (j_decompress_ptr cinfo)
*/
GLOBAL(void)
-jinit_2pass_quantizer (j_decompress_ptr cinfo)
+jinit_2pass_quantizer(j_decompress_ptr cinfo)
{
my_cquantize_ptr cquantize;
int i;
cquantize = (my_cquantize_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
sizeof(my_cquantizer));
- cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize;
+ cinfo->cquantize = (struct jpeg_color_quantizer *)cquantize;
cquantize->pub.start_pass = start_pass_2_quant;
cquantize->pub.new_color_map = new_color_map_2_quant;
cquantize->fserrors = NULL; /* flag optional arrays not allocated */
@@ -1231,12 +1234,12 @@ jinit_2pass_quantizer (j_decompress_ptr cinfo)
ERREXIT(cinfo, JERR_NOTIMPL);
/* Allocate the histogram/inverse colormap storage */
- cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small)
- ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * sizeof(hist2d));
+ cquantize->histogram = (hist3d)(*cinfo->mem->alloc_small)
+ ((j_common_ptr)cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * sizeof(hist2d));
for (i = 0; i < HIST_C0_ELEMS; i++) {
- cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large)
- ((j_common_ptr) cinfo, JPOOL_IMAGE,
- HIST_C1_ELEMS*HIST_C2_ELEMS * sizeof(histcell));
+ cquantize->histogram[i] = (hist2d)(*cinfo->mem->alloc_large)
+ ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ HIST_C1_ELEMS * HIST_C2_ELEMS * sizeof(histcell));
}
cquantize->needs_zeroed = TRUE; /* histogram is garbage now */
@@ -1254,7 +1257,7 @@ jinit_2pass_quantizer (j_decompress_ptr cinfo)
if (desired > MAXNUMCOLORS)
ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);
cquantize->sv_colormap = (*cinfo->mem->alloc_sarray)
- ((j_common_ptr) cinfo,JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3);
+ ((j_common_ptr)cinfo, JPOOL_IMAGE, (JDIMENSION)desired, (JDIMENSION)3);
cquantize->desired = desired;
} else
cquantize->sv_colormap = NULL;
@@ -1271,9 +1274,9 @@ jinit_2pass_quantizer (j_decompress_ptr cinfo)
* dither_mode changes.
*/
if (cinfo->dither_mode == JDITHER_FS) {
- cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large)
- ((j_common_ptr) cinfo, JPOOL_IMAGE,
- (size_t) ((cinfo->output_width + 2) * (3 * sizeof(FSERROR))));
+ cquantize->fserrors = (FSERRPTR)(*cinfo->mem->alloc_large)
+ ((j_common_ptr)cinfo, JPOOL_IMAGE,
+ (size_t)((cinfo->output_width + 2) * (3 * sizeof(FSERROR))));
/* Might as well create the error-limiting table too. */
init_error_limit(cinfo);
}
diff --git a/src/3rdparty/libjpeg/src/jsimd.h b/src/3rdparty/libjpeg/src/jsimd.h
index 3aa0779b8a..51e2b8c89d 100644
--- a/src/3rdparty/libjpeg/src/jsimd.h
+++ b/src/3rdparty/libjpeg/src/jsimd.h
@@ -3,7 +3,7 @@
*
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* Copyright (C) 2011, 2014, D. R. Commander.
- * Copyright (C) 2015, Matthieu Darbois.
+ * Copyright (C) 2015-2016, 2018, Matthieu Darbois.
*
* Based on the x86 SIMD extension for IJG JPEG library,
* Copyright (C) 1999-2006, MIYASAKA Masaru.
@@ -13,81 +13,105 @@
#include "jchuff.h" /* Declarations shared with jcphuff.c */
-EXTERN(int) jsimd_can_rgb_ycc (void);
-EXTERN(int) jsimd_can_rgb_gray (void);
-EXTERN(int) jsimd_can_ycc_rgb (void);
-EXTERN(int) jsimd_can_ycc_rgb565 (void);
-EXTERN(int) jsimd_c_can_null_convert (void);
-
-EXTERN(void) jsimd_rgb_ycc_convert
- (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows);
-EXTERN(void) jsimd_rgb_gray_convert
- (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows);
-EXTERN(void) jsimd_ycc_rgb_convert
- (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows);
-EXTERN(void) jsimd_ycc_rgb565_convert
- (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows);
-EXTERN(void) jsimd_c_null_convert
- (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows);
-
-EXTERN(int) jsimd_can_h2v2_downsample (void);
-EXTERN(int) jsimd_can_h2v1_downsample (void);
-
-EXTERN(void) jsimd_h2v2_downsample
- (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data);
-
-EXTERN(int) jsimd_can_h2v2_smooth_downsample (void);
-
-EXTERN(void) jsimd_h2v2_smooth_downsample
- (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data);
-
-EXTERN(void) jsimd_h2v1_downsample
- (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data);
-
-EXTERN(int) jsimd_can_h2v2_upsample (void);
-EXTERN(int) jsimd_can_h2v1_upsample (void);
-EXTERN(int) jsimd_can_int_upsample (void);
-
-EXTERN(void) jsimd_h2v2_upsample
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr);
-EXTERN(void) jsimd_h2v1_upsample
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr);
-EXTERN(void) jsimd_int_upsample
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr);
-
-EXTERN(int) jsimd_can_h2v2_fancy_upsample (void);
-EXTERN(int) jsimd_can_h2v1_fancy_upsample (void);
-
-EXTERN(void) jsimd_h2v2_fancy_upsample
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr);
-EXTERN(void) jsimd_h2v1_fancy_upsample
- (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr);
-
-EXTERN(int) jsimd_can_h2v2_merged_upsample (void);
-EXTERN(int) jsimd_can_h2v1_merged_upsample (void);
-
-EXTERN(void) jsimd_h2v2_merged_upsample
- (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
- JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf);
-EXTERN(void) jsimd_h2v1_merged_upsample
- (j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
- JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf);
-
-EXTERN(int) jsimd_can_huff_encode_one_block (void);
-
-EXTERN(JOCTET*) jsimd_huff_encode_one_block
- (void *state, JOCTET *buffer, JCOEFPTR block, int last_dc_val,
- c_derived_tbl *dctbl, c_derived_tbl *actbl);
+EXTERN(int) jsimd_can_rgb_ycc(void);
+EXTERN(int) jsimd_can_rgb_gray(void);
+EXTERN(int) jsimd_can_ycc_rgb(void);
+EXTERN(int) jsimd_can_ycc_rgb565(void);
+EXTERN(int) jsimd_c_can_null_convert(void);
+
+EXTERN(void) jsimd_rgb_ycc_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows);
+EXTERN(void) jsimd_rgb_gray_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows);
+EXTERN(void) jsimd_ycc_rgb_convert(j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION input_row,
+ JSAMPARRAY output_buf, int num_rows);
+EXTERN(void) jsimd_ycc_rgb565_convert(j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf,
+ JDIMENSION input_row,
+ JSAMPARRAY output_buf, int num_rows);
+EXTERN(void) jsimd_c_null_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf, JDIMENSION output_row,
+ int num_rows);
+
+EXTERN(int) jsimd_can_h2v2_downsample(void);
+EXTERN(int) jsimd_can_h2v1_downsample(void);
+
+EXTERN(void) jsimd_h2v2_downsample(j_compress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JSAMPARRAY input_data,
+ JSAMPARRAY output_data);
+
+EXTERN(int) jsimd_can_h2v2_smooth_downsample(void);
+
+EXTERN(void) jsimd_h2v2_smooth_downsample(j_compress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JSAMPARRAY input_data,
+ JSAMPARRAY output_data);
+
+EXTERN(void) jsimd_h2v1_downsample(j_compress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JSAMPARRAY input_data,
+ JSAMPARRAY output_data);
+
+EXTERN(int) jsimd_can_h2v2_upsample(void);
+EXTERN(int) jsimd_can_h2v1_upsample(void);
+EXTERN(int) jsimd_can_int_upsample(void);
+
+EXTERN(void) jsimd_h2v2_upsample(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JSAMPARRAY input_data,
+ JSAMPARRAY *output_data_ptr);
+EXTERN(void) jsimd_h2v1_upsample(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JSAMPARRAY input_data,
+ JSAMPARRAY *output_data_ptr);
+EXTERN(void) jsimd_int_upsample(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JSAMPARRAY input_data,
+ JSAMPARRAY *output_data_ptr);
+
+EXTERN(int) jsimd_can_h2v2_fancy_upsample(void);
+EXTERN(int) jsimd_can_h2v1_fancy_upsample(void);
+
+EXTERN(void) jsimd_h2v2_fancy_upsample(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JSAMPARRAY input_data,
+ JSAMPARRAY *output_data_ptr);
+EXTERN(void) jsimd_h2v1_fancy_upsample(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JSAMPARRAY input_data,
+ JSAMPARRAY *output_data_ptr);
+
+EXTERN(int) jsimd_can_h2v2_merged_upsample(void);
+EXTERN(int) jsimd_can_h2v1_merged_upsample(void);
+
+EXTERN(void) jsimd_h2v2_merged_upsample(j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf);
+EXTERN(void) jsimd_h2v1_merged_upsample(j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf);
+
+EXTERN(int) jsimd_can_huff_encode_one_block(void);
+
+EXTERN(JOCTET *) jsimd_huff_encode_one_block(void *state, JOCTET *buffer,
+ JCOEFPTR block, int last_dc_val,
+ c_derived_tbl *dctbl,
+ c_derived_tbl *actbl);
+
+EXTERN(int) jsimd_can_encode_mcu_AC_first_prepare(void);
+
+EXTERN(void) jsimd_encode_mcu_AC_first_prepare
+ (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al,
+ JCOEF *values, size_t *zerobits);
+
+EXTERN(int) jsimd_can_encode_mcu_AC_refine_prepare(void);
+
+EXTERN(int) jsimd_encode_mcu_AC_refine_prepare
+ (const JCOEF *block, const int *jpeg_natural_order_start, int Sl, int Al,
+ JCOEF *absvalues, size_t *bits);
diff --git a/src/3rdparty/libjpeg/src/jsimd_none.c b/src/3rdparty/libjpeg/src/jsimd_none.c
index f29030cfa7..3cb6c80f8a 100644
--- a/src/3rdparty/libjpeg/src/jsimd_none.c
+++ b/src/3rdparty/libjpeg/src/jsimd_none.c
@@ -3,7 +3,7 @@
*
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
* Copyright (C) 2009-2011, 2014, D. R. Commander.
- * Copyright (C) 2015, Matthieu Darbois.
+ * Copyright (C) 2015-2016, 2018, Matthieu Darbois.
*
* Based on the x86 SIMD extension for IJG JPEG library,
* Copyright (C) 1999-2006, MIYASAKA Masaru.
@@ -20,385 +20,399 @@
#include "jsimddct.h"
GLOBAL(int)
-jsimd_can_rgb_ycc (void)
+jsimd_can_rgb_ycc(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_rgb_gray (void)
+jsimd_can_rgb_gray(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_ycc_rgb (void)
+jsimd_can_ycc_rgb(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_ycc_rgb565 (void)
+jsimd_can_ycc_rgb565(void)
{
return 0;
}
GLOBAL(int)
-jsimd_c_can_null_convert (void)
+jsimd_c_can_null_convert(void)
{
return 0;
}
GLOBAL(void)
-jsimd_rgb_ycc_convert (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows)
+jsimd_rgb_ycc_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf, JDIMENSION output_row,
+ int num_rows)
{
}
GLOBAL(void)
-jsimd_rgb_gray_convert (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows)
+jsimd_rgb_gray_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf, JDIMENSION output_row,
+ int num_rows)
{
}
GLOBAL(void)
-jsimd_ycc_rgb_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+jsimd_ycc_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf,
+ int num_rows)
{
}
GLOBAL(void)
-jsimd_ycc_rgb565_convert (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf, JDIMENSION input_row,
- JSAMPARRAY output_buf, int num_rows)
+jsimd_ycc_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION input_row, JSAMPARRAY output_buf,
+ int num_rows)
{
}
GLOBAL(void)
-jsimd_c_null_convert (j_compress_ptr cinfo,
- JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
- JDIMENSION output_row, int num_rows)
+jsimd_c_null_convert(j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPIMAGE output_buf, JDIMENSION output_row,
+ int num_rows)
{
}
GLOBAL(int)
-jsimd_can_h2v2_downsample (void)
+jsimd_can_h2v2_downsample(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_h2v1_downsample (void)
+jsimd_can_h2v1_downsample(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_h2v2_smooth_downsample (void)
+jsimd_can_h2v2_smooth_downsample(void)
{
return 0;
}
GLOBAL(void)
-jsimd_h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data)
+jsimd_h2v2_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
{
}
GLOBAL(void)
-jsimd_h2v2_smooth_downsample (j_compress_ptr cinfo,
- jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data)
+jsimd_h2v2_smooth_downsample(j_compress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
{
}
GLOBAL(void)
-jsimd_h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data)
+jsimd_h2v1_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
{
}
GLOBAL(int)
-jsimd_can_h2v2_upsample (void)
+jsimd_can_h2v2_upsample(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_h2v1_upsample (void)
+jsimd_can_h2v1_upsample(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_int_upsample (void)
+jsimd_can_int_upsample(void)
{
return 0;
}
GLOBAL(void)
-jsimd_int_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
+jsimd_int_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
}
GLOBAL(void)
-jsimd_h2v2_upsample (j_decompress_ptr cinfo,
- jpeg_component_info *compptr,
- JSAMPARRAY input_data,
- JSAMPARRAY *output_data_ptr)
+jsimd_h2v2_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
}
GLOBAL(void)
-jsimd_h2v1_upsample (j_decompress_ptr cinfo,
- jpeg_component_info *compptr,
- JSAMPARRAY input_data,
- JSAMPARRAY *output_data_ptr)
+jsimd_h2v1_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
}
GLOBAL(int)
-jsimd_can_h2v2_fancy_upsample (void)
+jsimd_can_h2v2_fancy_upsample(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_h2v1_fancy_upsample (void)
+jsimd_can_h2v1_fancy_upsample(void)
{
return 0;
}
GLOBAL(void)
-jsimd_h2v2_fancy_upsample (j_decompress_ptr cinfo,
- jpeg_component_info *compptr,
- JSAMPARRAY input_data,
- JSAMPARRAY *output_data_ptr)
+jsimd_h2v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
}
GLOBAL(void)
-jsimd_h2v1_fancy_upsample (j_decompress_ptr cinfo,
- jpeg_component_info *compptr,
- JSAMPARRAY input_data,
- JSAMPARRAY *output_data_ptr)
+jsimd_h2v1_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
}
GLOBAL(int)
-jsimd_can_h2v2_merged_upsample (void)
+jsimd_can_h2v2_merged_upsample(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_h2v1_merged_upsample (void)
+jsimd_can_h2v1_merged_upsample(void)
{
return 0;
}
GLOBAL(void)
-jsimd_h2v2_merged_upsample (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf,
- JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+jsimd_h2v2_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf)
{
}
GLOBAL(void)
-jsimd_h2v1_merged_upsample (j_decompress_ptr cinfo,
- JSAMPIMAGE input_buf,
- JDIMENSION in_row_group_ctr,
- JSAMPARRAY output_buf)
+jsimd_h2v1_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
+ JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf)
{
}
GLOBAL(int)
-jsimd_can_convsamp (void)
+jsimd_can_convsamp(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_convsamp_float (void)
+jsimd_can_convsamp_float(void)
{
return 0;
}
GLOBAL(void)
-jsimd_convsamp (JSAMPARRAY sample_data, JDIMENSION start_col,
- DCTELEM *workspace)
+jsimd_convsamp(JSAMPARRAY sample_data, JDIMENSION start_col,
+ DCTELEM *workspace)
{
}
GLOBAL(void)
-jsimd_convsamp_float (JSAMPARRAY sample_data, JDIMENSION start_col,
- FAST_FLOAT *workspace)
+jsimd_convsamp_float(JSAMPARRAY sample_data, JDIMENSION start_col,
+ FAST_FLOAT *workspace)
{
}
GLOBAL(int)
-jsimd_can_fdct_islow (void)
+jsimd_can_fdct_islow(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_fdct_ifast (void)
+jsimd_can_fdct_ifast(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_fdct_float (void)
+jsimd_can_fdct_float(void)
{
return 0;
}
GLOBAL(void)
-jsimd_fdct_islow (DCTELEM *data)
+jsimd_fdct_islow(DCTELEM *data)
{
}
GLOBAL(void)
-jsimd_fdct_ifast (DCTELEM *data)
+jsimd_fdct_ifast(DCTELEM *data)
{
}
GLOBAL(void)
-jsimd_fdct_float (FAST_FLOAT *data)
+jsimd_fdct_float(FAST_FLOAT *data)
{
}
GLOBAL(int)
-jsimd_can_quantize (void)
+jsimd_can_quantize(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_quantize_float (void)
+jsimd_can_quantize_float(void)
{
return 0;
}
GLOBAL(void)
-jsimd_quantize (JCOEFPTR coef_block, DCTELEM *divisors,
- DCTELEM *workspace)
+jsimd_quantize(JCOEFPTR coef_block, DCTELEM *divisors, DCTELEM *workspace)
{
}
GLOBAL(void)
-jsimd_quantize_float (JCOEFPTR coef_block, FAST_FLOAT *divisors,
- FAST_FLOAT *workspace)
+jsimd_quantize_float(JCOEFPTR coef_block, FAST_FLOAT *divisors,
+ FAST_FLOAT *workspace)
{
}
GLOBAL(int)
-jsimd_can_idct_2x2 (void)
+jsimd_can_idct_2x2(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_idct_4x4 (void)
+jsimd_can_idct_4x4(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_idct_6x6 (void)
+jsimd_can_idct_6x6(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_idct_12x12 (void)
+jsimd_can_idct_12x12(void)
{
return 0;
}
GLOBAL(void)
-jsimd_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col)
+jsimd_idct_2x2(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
}
GLOBAL(void)
-jsimd_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col)
+jsimd_idct_4x4(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
}
GLOBAL(void)
-jsimd_idct_6x6 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col)
+jsimd_idct_6x6(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
}
GLOBAL(void)
-jsimd_idct_12x12 (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col)
+jsimd_idct_12x12(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
}
GLOBAL(int)
-jsimd_can_idct_islow (void)
+jsimd_can_idct_islow(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_idct_ifast (void)
+jsimd_can_idct_ifast(void)
{
return 0;
}
GLOBAL(int)
-jsimd_can_idct_float (void)
+jsimd_can_idct_float(void)
{
return 0;
}
GLOBAL(void)
-jsimd_idct_islow (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col)
+jsimd_idct_islow(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
}
GLOBAL(void)
-jsimd_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col)
+jsimd_idct_ifast(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
}
GLOBAL(void)
-jsimd_idct_float (j_decompress_ptr cinfo, jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col)
+jsimd_idct_float(j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col)
{
}
GLOBAL(int)
-jsimd_can_huff_encode_one_block (void)
+jsimd_can_huff_encode_one_block(void)
{
return 0;
}
-GLOBAL(JOCTET*)
-jsimd_huff_encode_one_block (void *state, JOCTET *buffer, JCOEFPTR block,
- int last_dc_val, c_derived_tbl *dctbl,
- c_derived_tbl *actbl)
+GLOBAL(JOCTET *)
+jsimd_huff_encode_one_block(void *state, JOCTET *buffer, JCOEFPTR block,
+ int last_dc_val, c_derived_tbl *dctbl,
+ c_derived_tbl *actbl)
{
return NULL;
}
+
+GLOBAL(int)
+jsimd_can_encode_mcu_AC_first_prepare(void)
+{
+ return 0;
+}
+
+GLOBAL(void)
+jsimd_encode_mcu_AC_first_prepare(const JCOEF *block,
+ const int *jpeg_natural_order_start, int Sl,
+ int Al, JCOEF *values, size_t *zerobits)
+{
+}
+
+GLOBAL(int)
+jsimd_can_encode_mcu_AC_refine_prepare(void)
+{
+ return 0;
+}
+
+GLOBAL(int)
+jsimd_encode_mcu_AC_refine_prepare(const JCOEF *block,
+ const int *jpeg_natural_order_start, int Sl,
+ int Al, JCOEF *absvalues, size_t *bits)
+{
+ return 0;
+}
diff --git a/src/3rdparty/libjpeg/src/jsimddct.h b/src/3rdparty/libjpeg/src/jsimddct.h
index b19ab48d40..55ee8cf67f 100644
--- a/src/3rdparty/libjpeg/src/jsimddct.h
+++ b/src/3rdparty/libjpeg/src/jsimddct.h
@@ -9,66 +9,62 @@
*
*/
-EXTERN(int) jsimd_can_convsamp (void);
-EXTERN(int) jsimd_can_convsamp_float (void);
+EXTERN(int) jsimd_can_convsamp(void);
+EXTERN(int) jsimd_can_convsamp_float(void);
-EXTERN(void) jsimd_convsamp (JSAMPARRAY sample_data, JDIMENSION start_col,
- DCTELEM *workspace);
-EXTERN(void) jsimd_convsamp_float (JSAMPARRAY sample_data,
- JDIMENSION start_col,
- FAST_FLOAT *workspace);
+EXTERN(void) jsimd_convsamp(JSAMPARRAY sample_data, JDIMENSION start_col,
+ DCTELEM *workspace);
+EXTERN(void) jsimd_convsamp_float(JSAMPARRAY sample_data, JDIMENSION start_col,
+ FAST_FLOAT *workspace);
-EXTERN(int) jsimd_can_fdct_islow (void);
-EXTERN(int) jsimd_can_fdct_ifast (void);
-EXTERN(int) jsimd_can_fdct_float (void);
+EXTERN(int) jsimd_can_fdct_islow(void);
+EXTERN(int) jsimd_can_fdct_ifast(void);
+EXTERN(int) jsimd_can_fdct_float(void);
-EXTERN(void) jsimd_fdct_islow (DCTELEM *data);
-EXTERN(void) jsimd_fdct_ifast (DCTELEM *data);
-EXTERN(void) jsimd_fdct_float (FAST_FLOAT *data);
+EXTERN(void) jsimd_fdct_islow(DCTELEM *data);
+EXTERN(void) jsimd_fdct_ifast(DCTELEM *data);
+EXTERN(void) jsimd_fdct_float(FAST_FLOAT *data);
-EXTERN(int) jsimd_can_quantize (void);
-EXTERN(int) jsimd_can_quantize_float (void);
+EXTERN(int) jsimd_can_quantize(void);
+EXTERN(int) jsimd_can_quantize_float(void);
-EXTERN(void) jsimd_quantize (JCOEFPTR coef_block, DCTELEM *divisors,
- DCTELEM *workspace);
-EXTERN(void) jsimd_quantize_float (JCOEFPTR coef_block, FAST_FLOAT *divisors,
- FAST_FLOAT *workspace);
+EXTERN(void) jsimd_quantize(JCOEFPTR coef_block, DCTELEM *divisors,
+ DCTELEM *workspace);
+EXTERN(void) jsimd_quantize_float(JCOEFPTR coef_block, FAST_FLOAT *divisors,
+ FAST_FLOAT *workspace);
-EXTERN(int) jsimd_can_idct_2x2 (void);
-EXTERN(int) jsimd_can_idct_4x4 (void);
-EXTERN(int) jsimd_can_idct_6x6 (void);
-EXTERN(int) jsimd_can_idct_12x12 (void);
+EXTERN(int) jsimd_can_idct_2x2(void);
+EXTERN(int) jsimd_can_idct_4x4(void);
+EXTERN(int) jsimd_can_idct_6x6(void);
+EXTERN(int) jsimd_can_idct_12x12(void);
-EXTERN(void) jsimd_idct_2x2 (j_decompress_ptr cinfo,
- jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col);
-EXTERN(void) jsimd_idct_4x4 (j_decompress_ptr cinfo,
- jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col);
-EXTERN(void) jsimd_idct_6x6 (j_decompress_ptr cinfo,
- jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col);
-EXTERN(void) jsimd_idct_12x12 (j_decompress_ptr cinfo,
- jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col);
+EXTERN(void) jsimd_idct_2x2(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jsimd_idct_4x4(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jsimd_idct_6x6(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr, JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col);
+EXTERN(void) jsimd_idct_12x12(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col);
-EXTERN(int) jsimd_can_idct_islow (void);
-EXTERN(int) jsimd_can_idct_ifast (void);
-EXTERN(int) jsimd_can_idct_float (void);
+EXTERN(int) jsimd_can_idct_islow(void);
+EXTERN(int) jsimd_can_idct_ifast(void);
+EXTERN(int) jsimd_can_idct_float(void);
-EXTERN(void) jsimd_idct_islow (j_decompress_ptr cinfo,
- jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col);
-EXTERN(void) jsimd_idct_ifast (j_decompress_ptr cinfo,
- jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col);
-EXTERN(void) jsimd_idct_float (j_decompress_ptr cinfo,
- jpeg_component_info *compptr,
- JCOEFPTR coef_block, JSAMPARRAY output_buf,
- JDIMENSION output_col);
+EXTERN(void) jsimd_idct_islow(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col);
+EXTERN(void) jsimd_idct_ifast(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col);
+EXTERN(void) jsimd_idct_float(j_decompress_ptr cinfo,
+ jpeg_component_info *compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf,
+ JDIMENSION output_col);
diff --git a/src/3rdparty/libjpeg/src/jstdhuff.c b/src/3rdparty/libjpeg/src/jstdhuff.c
index e202e8e7ec..036d6495a5 100644
--- a/src/3rdparty/libjpeg/src/jstdhuff.c
+++ b/src/3rdparty/libjpeg/src/jstdhuff.c
@@ -17,8 +17,8 @@
*/
LOCAL(void)
-add_huff_table (j_common_ptr cinfo,
- JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val)
+add_huff_table(j_common_ptr cinfo, JHUFF_TBL **htblptr, const UINT8 *bits,
+ const UINT8 *val)
/* Define a Huffman table */
{
int nsymbols, len;
@@ -50,71 +50,79 @@ add_huff_table (j_common_ptr cinfo,
LOCAL(void)
-std_huff_tables (j_common_ptr cinfo)
+std_huff_tables(j_common_ptr cinfo)
/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
/* IMPORTANT: these are only valid for 8-bit data precision! */
{
JHUFF_TBL **dc_huff_tbl_ptrs, **ac_huff_tbl_ptrs;
- static const UINT8 bits_dc_luminance[17] =
- { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
- static const UINT8 val_dc_luminance[] =
- { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+ static const UINT8 bits_dc_luminance[17] = {
+ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
+ };
+ static const UINT8 val_dc_luminance[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
+ };
- static const UINT8 bits_dc_chrominance[17] =
- { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
- static const UINT8 val_dc_chrominance[] =
- { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+ static const UINT8 bits_dc_chrominance[17] = {
+ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
+ };
+ static const UINT8 val_dc_chrominance[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
+ };
- static const UINT8 bits_ac_luminance[17] =
- { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
- static const UINT8 val_ac_luminance[] =
- { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
- 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
- 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
- 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
- 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
- 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
- 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
- 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
- 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
- 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
- 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
- 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
- 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
- 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
- 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
- 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
- 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
- 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
- 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
- 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
- 0xf9, 0xfa };
+ static const UINT8 bits_ac_luminance[17] = {
+ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
+ };
+ static const UINT8 val_ac_luminance[] = {
+ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+ 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+ 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+ 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+ 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+ 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+ 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+ 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+ 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+ 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+ 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+ 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+ 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+ 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+ 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa
+ };
- static const UINT8 bits_ac_chrominance[17] =
- { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
- static const UINT8 val_ac_chrominance[] =
- { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
- 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
- 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
- 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
- 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
- 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
- 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
- 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
- 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
- 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
- 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
- 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
- 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
- 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
- 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
- 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
- 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
- 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
- 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
- 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
- 0xf9, 0xfa };
+ static const UINT8 bits_ac_chrominance[17] = {
+ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77
+ };
+ static const UINT8 val_ac_chrominance[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
+ 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+ 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+ 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
+ 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
+ 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
+ 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
+ 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+ 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
+ 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
+ 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+ 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
+ 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+ 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa
+ };
if (cinfo->is_decompressor) {
dc_huff_tbl_ptrs = ((j_decompress_ptr)cinfo)->dc_huff_tbl_ptrs;
diff --git a/src/3rdparty/libjpeg/src/jutils.c b/src/3rdparty/libjpeg/src/jutils.c
index f9d35023e5..5c5bb17dc5 100644
--- a/src/3rdparty/libjpeg/src/jutils.c
+++ b/src/3rdparty/libjpeg/src/jutils.c
@@ -53,7 +53,7 @@ const int jpeg_zigzag_order[DCTSIZE2] = {
* fake entries.
*/
-const int jpeg_natural_order[DCTSIZE2+16] = {
+const int jpeg_natural_order[DCTSIZE2 + 16] = {
0, 1, 8, 16, 9, 2, 3, 10,
17, 24, 32, 25, 18, 11, 4, 5,
12, 19, 26, 33, 40, 48, 41, 34,
@@ -72,7 +72,7 @@ const int jpeg_natural_order[DCTSIZE2+16] = {
*/
GLOBAL(long)
-jdiv_round_up (long a, long b)
+jdiv_round_up(long a, long b)
/* Compute a/b rounded up to next integer, ie, ceil(a/b) */
/* Assumes a >= 0, b > 0 */
{
@@ -81,7 +81,7 @@ jdiv_round_up (long a, long b)
GLOBAL(long)
-jround_up (long a, long b)
+jround_up(long a, long b)
/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */
/* Assumes a >= 0, b > 0 */
{
@@ -91,9 +91,9 @@ jround_up (long a, long b)
GLOBAL(void)
-jcopy_sample_rows (JSAMPARRAY input_array, int source_row,
- JSAMPARRAY output_array, int dest_row,
- int num_rows, JDIMENSION num_cols)
+jcopy_sample_rows(JSAMPARRAY input_array, int source_row,
+ JSAMPARRAY output_array, int dest_row, int num_rows,
+ JDIMENSION num_cols)
/* Copy some rows of samples from one place to another.
* num_rows rows are copied from input_array[source_row++]
* to output_array[dest_row++]; these areas may overlap for duplication.
@@ -101,7 +101,7 @@ jcopy_sample_rows (JSAMPARRAY input_array, int source_row,
*/
{
register JSAMPROW inptr, outptr;
- register size_t count = (size_t) (num_cols * sizeof(JSAMPLE));
+ register size_t count = (size_t)(num_cols * sizeof(JSAMPLE));
register int row;
input_array += source_row;
@@ -116,8 +116,8 @@ jcopy_sample_rows (JSAMPARRAY input_array, int source_row,
GLOBAL(void)
-jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row,
- JDIMENSION num_blocks)
+jcopy_block_row(JBLOCKROW input_row, JBLOCKROW output_row,
+ JDIMENSION num_blocks)
/* Copy a row of coefficient blocks from one place to another. */
{
MEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * sizeof(JCOEF)));
@@ -125,7 +125,7 @@ jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row,
GLOBAL(void)
-jzero_far (void *target, size_t bytestozero)
+jzero_far(void *target, size_t bytestozero)
/* Zero out a chunk of memory. */
/* This might be sample-array data, block-array data, or alloc_large data. */
{
diff --git a/src/3rdparty/libjpeg/src/jversion.h b/src/3rdparty/libjpeg/src/jversion.h
index 7e44eaa3c5..2039f44c3a 100644
--- a/src/3rdparty/libjpeg/src/jversion.h
+++ b/src/3rdparty/libjpeg/src/jversion.h
@@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-2012, Thomas G. Lane, Guido Vollbeding.
* libjpeg-turbo Modifications:
- * Copyright (C) 2010, 2012-2017, D. R. Commander.
+ * Copyright (C) 2010, 2012-2018, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
@@ -35,15 +35,18 @@
* their code
*/
-#define JCOPYRIGHT "Copyright (C) 2009-2017 D. R. Commander\n" \
- "Copyright (C) 2011-2016 Siarhei Siamashka\n" \
- "Copyright (C) 2015-2016 Matthieu Darbois\n" \
- "Copyright (C) 2015 Google, Inc.\n" \
- "Copyright (C) 2013-2014 MIPS Technologies, Inc.\n" \
- "Copyright (C) 2013 Linaro Limited\n" \
- "Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies)\n" \
- "Copyright (C) 2009 Pierre Ossman for Cendio AB\n" \
- "Copyright (C) 1999-2006 MIYASAKA Masaru\n" \
- "Copyright (C) 1991-2016 Thomas G. Lane, Guido Vollbeding" \
-
-#define JCOPYRIGHT_SHORT "Copyright (C) 1991-2017 The libjpeg-turbo Project and many others"
+#define JCOPYRIGHT \
+ "Copyright (C) 2009-2018 D. R. Commander\n" \
+ "Copyright (C) 2011-2016 Siarhei Siamashka\n" \
+ "Copyright (C) 2015-2016, 2018 Matthieu Darbois\n" \
+ "Copyright (C) 2015 Intel Corporation\n" \
+ "Copyright (C) 2015 Google, Inc.\n" \
+ "Copyright (C) 2013-2014 MIPS Technologies, Inc.\n" \
+ "Copyright (C) 2013 Linaro Limited\n" \
+ "Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies)\n" \
+ "Copyright (C) 2009 Pierre Ossman for Cendio AB\n" \
+ "Copyright (C) 1999-2006 MIYASAKA Masaru\n" \
+ "Copyright (C) 1991-2016 Thomas G. Lane, Guido Vollbeding"
+
+#define JCOPYRIGHT_SHORT \
+ "Copyright (C) 1991-2018 The libjpeg-turbo Project and many others"
diff --git a/src/3rdparty/sqlite.pri b/src/3rdparty/sqlite.pri
index 4f3326a817..cb8b888a6a 100644
--- a/src/3rdparty/sqlite.pri
+++ b/src/3rdparty/sqlite.pri
@@ -2,7 +2,10 @@ CONFIG(release, debug|release):DEFINES *= NDEBUG
DEFINES += SQLITE_ENABLE_COLUMN_METADATA SQLITE_OMIT_LOAD_EXTENSION SQLITE_OMIT_COMPLETE SQLITE_ENABLE_FTS3 SQLITE_ENABLE_FTS3_PARENTHESIS SQLITE_ENABLE_FTS5 SQLITE_ENABLE_RTREE
!contains(CONFIG, largefile):DEFINES += SQLITE_DISABLE_LFS
qtConfig(posix_fallocate): DEFINES += HAVE_POSIX_FALLOCATE=1
-winrt: DEFINES += SQLITE_OS_WINRT
+winrt {
+ DEFINES += SQLITE_OS_WINRT
+ QMAKE_CFLAGS += -Gy
+}
qnx: DEFINES += _QNX_SOURCE
!win32:!winrt:!winphone: DEFINES += HAVE_USLEEP=1
integrity: QMAKE_CFLAGS += -include qplatformdefs.h
diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c
index ce4f343fdc..7b525c36bb 100644
--- a/src/3rdparty/sqlite/sqlite3.c
+++ b/src/3rdparty/sqlite/sqlite3.c
@@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.24.0. By combining all the individual C code files into this
+** version 3.25.2. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
@@ -55,6 +55,12 @@
#define CTIMEOPT_VAL_(opt) #opt
#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
+/* Like CTIMEOPT_VAL, but especially for SQLITE_DEFAULT_LOOKASIDE. This
+** option requires a separate macro because legal values contain a single
+** comma. e.g. (-DSQLITE_DEFAULT_LOOKASIDE="100,100") */
+#define CTIMEOPT_VAL2_(opt1,opt2) #opt1 "," #opt2
+#define CTIMEOPT_VAL2(opt) CTIMEOPT_VAL2_(opt)
+
/*
** An array of names of all compile-time options. This array should
** be sorted A-Z.
@@ -138,7 +144,7 @@ static const char * const sqlite3azCompileOpt[] = {
"DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
#endif
#ifdef SQLITE_DEFAULT_LOOKASIDE
- "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOOKASIDE),
+ "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL2(SQLITE_DEFAULT_LOOKASIDE),
#endif
#if SQLITE_DEFAULT_MEMSTATUS
"DEFAULT_MEMSTATUS",
@@ -1150,9 +1156,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.24.0"
-#define SQLITE_VERSION_NUMBER 3024000
-#define SQLITE_SOURCE_ID "2018-06-04 19:24:41 c7ee0833225bfd8c5ec2f9bf62b97c4e04d03bd9566366d5221ac8fb199a87ca"
+#define SQLITE_VERSION "3.25.2"
+#define SQLITE_VERSION_NUMBER 3025002
+#define SQLITE_SOURCE_ID "2018-09-25 19:08:10 fb90e7189ae6d62e77ba3a308ca5d683f90bbe633cf681865365b8e92792d1c7"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -1499,6 +1505,7 @@ SQLITE_API int sqlite3_exec(
*/
#define SQLITE_ERROR_MISSING_COLLSEQ (SQLITE_ERROR | (1<<8))
#define SQLITE_ERROR_RETRY (SQLITE_ERROR | (2<<8))
+#define SQLITE_ERROR_SNAPSHOT (SQLITE_ERROR | (3<<8))
#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8))
@@ -1538,6 +1545,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
+#define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
@@ -1913,7 +1921,8 @@ struct sqlite3_io_methods {
** <li>[[SQLITE_FCNTL_PERSIST_WAL]]
** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
** persistent [WAL | Write Ahead Log] setting. By default, the auxiliary
-** write ahead log and shared memory files used for transaction control
+** write ahead log ([WAL file]) and shared memory
+** files used for transaction control
** are automatically deleted when the latest connection to the database
** closes. Setting persistent WAL mode causes those files to persist after
** close. Persisting the files is useful when other processes that do not
@@ -2099,6 +2108,26 @@ struct sqlite3_io_methods {
** a file lock using the xLock or xShmLock methods of the VFS to wait
** for up to M milliseconds before failing, where M is the single
** unsigned integer parameter.
+**
+** <li>[[SQLITE_FCNTL_DATA_VERSION]]
+** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to
+** a database file. The argument is a pointer to a 32-bit unsigned integer.
+** The "data version" for the pager is written into the pointer. The
+** "data version" changes whenever any change occurs to the corresponding
+** database file, either through SQL statements on the same database
+** connection or through transactions committed by separate database
+** connections possibly in other processes. The [sqlite3_total_changes()]
+** interface can be used to find if any database on the connection has changed,
+** but that interface responds to changes on TEMP as well as MAIN and does
+** not provide a mechanism to detect changes to MAIN only. Also, the
+** [sqlite3_total_changes()] interface responds to internal changes only and
+** omits changes made by other database connections. The
+** [PRAGMA data_version] command provide a mechanism to detect changes to
+** a single attached database that occur due to other database connections,
+** but omits changes implemented by the database connection on which it is
+** called. This file control is the only mechanism to detect changes that
+** happen either internally or externally and that are associated with
+** a particular attached database.
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE 1
@@ -2134,6 +2163,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32
#define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33
#define SQLITE_FCNTL_LOCK_TIMEOUT 34
+#define SQLITE_FCNTL_DATA_VERSION 35
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -3148,6 +3178,12 @@ struct sqlite3_mem_methods {
** with no schema and no content. The following process works even for
** a badly corrupted database file:
** <ol>
+** <li> If the database connection is newly opened, make sure it has read the
+** database schema by preparing then discarding some query against the
+** database, or calling sqlite3_table_column_metadata(), ignoring any
+** errors. This step is only necessary if the application desires to keep
+** the database in WAL mode after the reset if it was in WAL mode before
+** the reset.
** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
** <li> [sqlite3_exec](db, "[VACUUM]", 0, 0, 0);
** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0);
@@ -3296,12 +3332,17 @@ SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64);
** program, the value returned reflects the number of rows modified by the
** previous INSERT, UPDATE or DELETE statement within the same trigger.
**
-** See also the [sqlite3_total_changes()] interface, the
-** [count_changes pragma], and the [changes() SQL function].
-**
** If a separate thread makes changes on the same database connection
** while [sqlite3_changes()] is running then the value returned
** is unpredictable and not meaningful.
+**
+** See also:
+** <ul>
+** <li> the [sqlite3_total_changes()] interface
+** <li> the [count_changes pragma]
+** <li> the [changes() SQL function]
+** <li> the [data_version pragma]
+** </ul>
*/
SQLITE_API int sqlite3_changes(sqlite3*);
@@ -3319,13 +3360,26 @@ SQLITE_API int sqlite3_changes(sqlite3*);
** count, but those made as part of REPLACE constraint resolution are
** not. ^Changes to a view that are intercepted by INSTEAD OF triggers
** are not counted.
-**
-** See also the [sqlite3_changes()] interface, the
-** [count_changes pragma], and the [total_changes() SQL function].
**
+** This the [sqlite3_total_changes(D)] interface only reports the number
+** of rows that changed due to SQL statement run against database
+** connection D. Any changes by other database connections are ignored.
+** To detect changes against a database file from other database
+** connections use the [PRAGMA data_version] command or the
+** [SQLITE_FCNTL_DATA_VERSION] [file control].
+**
** If a separate thread makes changes on the same database connection
** while [sqlite3_total_changes()] is running then the value
** returned is unpredictable and not meaningful.
+**
+** See also:
+** <ul>
+** <li> the [sqlite3_changes()] interface
+** <li> the [count_changes pragma]
+** <li> the [changes() SQL function]
+** <li> the [data_version pragma]
+** <li> the [SQLITE_FCNTL_DATA_VERSION] [file control]
+** </ul>
*/
SQLITE_API int sqlite3_total_changes(sqlite3*);
@@ -4381,13 +4435,24 @@ SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int
** [database connection] D failed, then the sqlite3_errcode(D) interface
** returns the numeric [result code] or [extended result code] for that
** API call.
-** If the most recent API call was successful,
-** then the return value from sqlite3_errcode() is undefined.
** ^The sqlite3_extended_errcode()
** interface is the same except that it always returns the
** [extended result code] even when extended result codes are
** disabled.
**
+** The values returned by sqlite3_errcode() and/or
+** sqlite3_extended_errcode() might change with each API call.
+** Except, there are some interfaces that are guaranteed to never
+** change the value of the error code. The error-code preserving
+** interfaces are:
+**
+** <ul>
+** <li> sqlite3_errcode()
+** <li> sqlite3_extended_errcode()
+** <li> sqlite3_errmsg()
+** <li> sqlite3_errmsg16()
+** </ul>
+**
** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language
** text that describes the error, as either UTF-8 or UTF-16 respectively.
** ^(Memory to hold the error message string is managed internally.
@@ -5541,11 +5606,25 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
** [sqlite3_free()].
**
-** ^(If a memory allocation error occurs during the evaluation of any
-** of these routines, a default value is returned. The default value
-** is either the integer 0, the floating point number 0.0, or a NULL
-** pointer. Subsequent calls to [sqlite3_errcode()] will return
-** [SQLITE_NOMEM].)^
+** As long as the input parameters are correct, these routines will only
+** fail if an out-of-memory error occurs during a format conversion.
+** Only the following subset of interfaces are subject to out-of-memory
+** errors:
+**
+** <ul>
+** <li> sqlite3_column_blob()
+** <li> sqlite3_column_text()
+** <li> sqlite3_column_text16()
+** <li> sqlite3_column_bytes()
+** <li> sqlite3_column_bytes16()
+** </ul>
+**
+** If an out-of-memory error occurs, then the return value from these
+** routines is the same as if the column had contained an SQL NULL value.
+** Valid SQL NULL returns can be distinguished from out-of-memory errors
+** by invoking the [sqlite3_errcode()] immediately after the suspect
+** return value is obtained and before any
+** other SQLite interface is called on the same [database connection].
*/
SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol);
@@ -5622,11 +5701,13 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
**
** ^These functions (collectively known as "function creation routines")
** are used to add SQL functions or aggregates or to redefine the behavior
-** of existing SQL functions or aggregates. The only differences between
-** these routines are the text encoding expected for
-** the second parameter (the name of the function being created)
-** and the presence or absence of a destructor callback for
-** the application data pointer.
+** of existing SQL functions or aggregates. The only differences between
+** the three "sqlite3_create_function*" routines are the text encoding
+** expected for the second parameter (the name of the function being
+** created) and the presence or absence of a destructor callback for
+** the application data pointer. Function sqlite3_create_window_function()
+** is similar, but allows the user to supply the extra callback functions
+** needed by [aggregate window functions].
**
** ^The first parameter is the [database connection] to which the SQL
** function is to be added. ^If an application uses more than one database
@@ -5672,7 +5753,8 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
** ^(The fifth parameter is an arbitrary pointer. The implementation of the
** function can gain access to this pointer using [sqlite3_user_data()].)^
**
-** ^The sixth, seventh and eighth parameters, xFunc, xStep and xFinal, are
+** ^The sixth, seventh and eighth parameters passed to the three
+** "sqlite3_create_function*" functions, xFunc, xStep and xFinal, are
** pointers to C-language functions that implement the SQL function or
** aggregate. ^A scalar SQL function requires an implementation of the xFunc
** callback only; NULL pointers must be passed as the xStep and xFinal
@@ -5681,15 +5763,24 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
** SQL function or aggregate, pass NULL pointers for all three function
** callbacks.
**
-** ^(If the ninth parameter to sqlite3_create_function_v2() is not NULL,
-** then it is destructor for the application data pointer.
-** The destructor is invoked when the function is deleted, either by being
-** overloaded or when the database connection closes.)^
-** ^The destructor is also invoked if the call to
-** sqlite3_create_function_v2() fails.
-** ^When the destructor callback of the tenth parameter is invoked, it
-** is passed a single argument which is a copy of the application data
-** pointer which was the fifth parameter to sqlite3_create_function_v2().
+** ^The sixth, seventh, eighth and ninth parameters (xStep, xFinal, xValue
+** and xInverse) passed to sqlite3_create_window_function are pointers to
+** C-language callbacks that implement the new function. xStep and xFinal
+** must both be non-NULL. xValue and xInverse may either both be NULL, in
+** which case a regular aggregate function is created, or must both be
+** non-NULL, in which case the new function may be used as either an aggregate
+** or aggregate window function. More details regarding the implementation
+** of aggregate window functions are
+** [user-defined window functions|available here].
+**
+** ^(If the final parameter to sqlite3_create_function_v2() or
+** sqlite3_create_window_function() is not NULL, then it is destructor for
+** the application data pointer. The destructor is invoked when the function
+** is deleted, either by being overloaded or when the database connection
+** closes.)^ ^The destructor is also invoked if the call to
+** sqlite3_create_function_v2() fails. ^When the destructor callback is
+** invoked, it is passed a single argument which is a copy of the application
+** data pointer which was the fifth parameter to sqlite3_create_function_v2().
**
** ^It is permitted to register multiple implementations of the same
** functions with the same name but with either differing numbers of
@@ -5742,6 +5833,18 @@ SQLITE_API int sqlite3_create_function_v2(
void (*xFinal)(sqlite3_context*),
void(*xDestroy)(void*)
);
+SQLITE_API int sqlite3_create_window_function(
+ sqlite3 *db,
+ const char *zFunctionName,
+ int nArg,
+ int eTextRep,
+ void *pApp,
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+ void (*xFinal)(sqlite3_context*),
+ void (*xValue)(sqlite3_context*),
+ void (*xInverse)(sqlite3_context*,int,sqlite3_value**),
+ void(*xDestroy)(void*)
+);
/*
** CAPI3REF: Text Encodings
@@ -5884,6 +5987,28 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
**
** These routines must be called from the same thread as
** the SQL function that supplied the [sqlite3_value*] parameters.
+**
+** As long as the input parameter is correct, these routines can only
+** fail if an out-of-memory error occurs during a format conversion.
+** Only the following subset of interfaces are subject to out-of-memory
+** errors:
+**
+** <ul>
+** <li> sqlite3_value_blob()
+** <li> sqlite3_value_text()
+** <li> sqlite3_value_text16()
+** <li> sqlite3_value_text16le()
+** <li> sqlite3_value_text16be()
+** <li> sqlite3_value_bytes()
+** <li> sqlite3_value_bytes16()
+** </ul>
+**
+** If an out-of-memory error occurs, then the return value from these
+** routines is the same as if the column had contained an SQL NULL value.
+** Valid SQL NULL returns can be distinguished from out-of-memory errors
+** by invoking the [sqlite3_errcode()] immediately after the suspect
+** return value is obtained and before any
+** other SQLite interface is called on the same [database connection].
*/
SQLITE_API const void *sqlite3_value_blob(sqlite3_value*);
SQLITE_API double sqlite3_value_double(sqlite3_value*);
@@ -7350,6 +7475,7 @@ struct sqlite3_index_info {
#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70
#define SQLITE_INDEX_CONSTRAINT_ISNULL 71
#define SQLITE_INDEX_CONSTRAINT_IS 72
+#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150
/*
** CAPI3REF: Register A Virtual Table Implementation
@@ -8026,6 +8152,7 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
/*
** CAPI3REF: Low-Level Control Of Database Files
** METHOD: sqlite3
+** KEYWORDS: {file control}
**
** ^The [sqlite3_file_control()] interface makes a direct call to the
** xFileControl method for the [sqlite3_io_methods] object associated
@@ -8040,11 +8167,18 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
** the xFileControl method. ^The return value of the xFileControl
** method becomes the return value of this routine.
**
+** A few opcodes for [sqlite3_file_control()] are handled directly
+** by the SQLite core and never invoke the
+** sqlite3_io_methods.xFileControl method.
** ^The [SQLITE_FCNTL_FILE_POINTER] value for the op parameter causes
** a pointer to the underlying [sqlite3_file] object to be written into
-** the space pointed to by the 4th parameter. ^The [SQLITE_FCNTL_FILE_POINTER]
-** case is a short-circuit path which does not actually invoke the
-** underlying sqlite3_io_methods.xFileControl method.
+** the space pointed to by the 4th parameter. The
+** [SQLITE_FCNTL_JOURNAL_POINTER] works similarly except that it returns
+** the [sqlite3_file] object associated with the journal file instead of
+** the main database. The [SQLITE_FCNTL_VFS_POINTER] opcode returns
+** a pointer to the underlying [sqlite3_vfs] object for the file.
+** The [SQLITE_FCNTL_DATA_VERSION] returns the data version counter
+** from the pager.
**
** ^If the second parameter (zDbName) does not match the name of any
** open database file, then SQLITE_ERROR is returned. ^This error
@@ -9863,7 +9997,6 @@ SQLITE_API int sqlite3_system_errno(sqlite3*);
/*
** CAPI3REF: Database Snapshot
** KEYWORDS: {snapshot} {sqlite3_snapshot}
-** EXPERIMENTAL
**
** An instance of the snapshot object records the state of a [WAL mode]
** database for some specific point in history.
@@ -9880,11 +10013,6 @@ SQLITE_API int sqlite3_system_errno(sqlite3*);
** version of the database file so that it is possible to later open a new read
** transaction that sees that historical version of the database rather than
** the most recent version.
-**
-** The constructor for this object is [sqlite3_snapshot_get()]. The
-** [sqlite3_snapshot_open()] method causes a fresh read transaction to refer
-** to an historical snapshot (if possible). The destructor for
-** sqlite3_snapshot objects is [sqlite3_snapshot_free()].
*/
typedef struct sqlite3_snapshot {
unsigned char hidden[48];
@@ -9892,7 +10020,7 @@ typedef struct sqlite3_snapshot {
/*
** CAPI3REF: Record A Database Snapshot
-** EXPERIMENTAL
+** CONSTRUCTOR: sqlite3_snapshot
**
** ^The [sqlite3_snapshot_get(D,S,P)] interface attempts to make a
** new [sqlite3_snapshot] object that records the current state of
@@ -9908,7 +10036,7 @@ typedef struct sqlite3_snapshot {
** in this case.
**
** <ul>
-** <li> The database handle must be in [autocommit mode].
+** <li> The database handle must not be in [autocommit mode].
**
** <li> Schema S of [database connection] D must be a [WAL mode] database.
**
@@ -9931,7 +10059,7 @@ typedef struct sqlite3_snapshot {
** to avoid a memory leak.
**
** The [sqlite3_snapshot_get()] interface is only available when the
-** SQLITE_ENABLE_SNAPSHOT compile-time option is used.
+** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
*/
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get(
sqlite3 *db,
@@ -9941,24 +10069,35 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get(
/*
** CAPI3REF: Start a read transaction on an historical snapshot
-** EXPERIMENTAL
+** METHOD: sqlite3_snapshot
+**
+** ^The [sqlite3_snapshot_open(D,S,P)] interface either starts a new read
+** transaction or upgrades an existing one for schema S of
+** [database connection] D such that the read transaction refers to
+** historical [snapshot] P, rather than the most recent change to the
+** database. ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK
+** on success or an appropriate [error code] if it fails.
+**
+** ^In order to succeed, the database connection must not be in
+** [autocommit mode] when [sqlite3_snapshot_open(D,S,P)] is called. If there
+** is already a read transaction open on schema S, then the database handle
+** must have no active statements (SELECT statements that have been passed
+** to sqlite3_step() but not sqlite3_reset() or sqlite3_finalize()).
+** SQLITE_ERROR is returned if either of these conditions is violated, or
+** if schema S does not exist, or if the snapshot object is invalid.
+**
+** ^A call to sqlite3_snapshot_open() will fail to open if the specified
+** snapshot has been overwritten by a [checkpoint]. In this case
+** SQLITE_ERROR_SNAPSHOT is returned.
+**
+** If there is already a read transaction open when this function is
+** invoked, then the same read transaction remains open (on the same
+** database snapshot) if SQLITE_ERROR, SQLITE_BUSY or SQLITE_ERROR_SNAPSHOT
+** is returned. If another error code - for example SQLITE_PROTOCOL or an
+** SQLITE_IOERR error code - is returned, then the final state of the
+** read transaction is undefined. If SQLITE_OK is returned, then the
+** read transaction is now open on database snapshot P.
**
-** ^The [sqlite3_snapshot_open(D,S,P)] interface starts a
-** read transaction for schema S of
-** [database connection] D such that the read transaction
-** refers to historical [snapshot] P, rather than the most
-** recent change to the database.
-** ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK on success
-** or an appropriate [error code] if it fails.
-**
-** ^In order to succeed, a call to [sqlite3_snapshot_open(D,S,P)] must be
-** the first operation following the [BEGIN] that takes the schema S
-** out of [autocommit mode].
-** ^In other words, schema S must not currently be in
-** a transaction for [sqlite3_snapshot_open(D,S,P)] to work, but the
-** database connection D must be out of [autocommit mode].
-** ^A [snapshot] will fail to open if it has been overwritten by a
-** [checkpoint].
** ^(A call to [sqlite3_snapshot_open(D,S,P)] will fail if the
** database connection D does not know that the database file for
** schema S is in [WAL mode]. A database connection might not know
@@ -9969,7 +10108,7 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get(
** database connection in order to make it ready to use snapshots.)
**
** The [sqlite3_snapshot_open()] interface is only available when the
-** SQLITE_ENABLE_SNAPSHOT compile-time option is used.
+** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
*/
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open(
sqlite3 *db,
@@ -9979,20 +10118,20 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open(
/*
** CAPI3REF: Destroy a snapshot
-** EXPERIMENTAL
+** DESTRUCTOR: sqlite3_snapshot
**
** ^The [sqlite3_snapshot_free(P)] interface destroys [sqlite3_snapshot] P.
** The application must eventually free every [sqlite3_snapshot] object
** using this routine to avoid a memory leak.
**
** The [sqlite3_snapshot_free()] interface is only available when the
-** SQLITE_ENABLE_SNAPSHOT compile-time option is used.
+** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
*/
SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*);
/*
** CAPI3REF: Compare the ages of two snapshot handles.
-** EXPERIMENTAL
+** METHOD: sqlite3_snapshot
**
** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages
** of two valid snapshot handles.
@@ -10011,6 +10150,9 @@ SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*);
** Otherwise, this API returns a negative value if P1 refers to an older
** snapshot than P2, zero if the two handles refer to the same database
** snapshot, and a positive value if P1 is a newer snapshot than P2.
+**
+** This interface is only available if SQLite is compiled with the
+** [SQLITE_ENABLE_SNAPSHOT] option.
*/
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
sqlite3_snapshot *p1,
@@ -10019,23 +10161,26 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
/*
** CAPI3REF: Recover snapshots from a wal file
-** EXPERIMENTAL
+** METHOD: sqlite3_snapshot
**
-** If all connections disconnect from a database file but do not perform
-** a checkpoint, the existing wal file is opened along with the database
-** file the next time the database is opened. At this point it is only
-** possible to successfully call sqlite3_snapshot_open() to open the most
-** recent snapshot of the database (the one at the head of the wal file),
-** even though the wal file may contain other valid snapshots for which
-** clients have sqlite3_snapshot handles.
+** If a [WAL file] remains on disk after all database connections close
+** (either through the use of the [SQLITE_FCNTL_PERSIST_WAL] [file control]
+** or because the last process to have the database opened exited without
+** calling [sqlite3_close()]) and a new connection is subsequently opened
+** on that database and [WAL file], the [sqlite3_snapshot_open()] interface
+** will only be able to open the last transaction added to the WAL file
+** even though the WAL file contains other valid transactions.
**
-** This function attempts to scan the wal file associated with database zDb
+** This function attempts to scan the WAL file associated with database zDb
** of database handle db and make all valid snapshots available to
** sqlite3_snapshot_open(). It is an error if there is already a read
-** transaction open on the database, or if the database is not a wal mode
+** transaction open on the database, or if the database is not a WAL mode
** database.
**
** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
+**
+** This interface is only available if SQLite is compiled with the
+** [SQLITE_ENABLE_SNAPSHOT] option.
*/
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
@@ -10146,7 +10291,7 @@ SQLITE_API int sqlite3_deserialize(
** in the P argument is held in memory obtained from [sqlite3_malloc64()]
** and that SQLite should take ownership of this memory and automatically
** free it when it has finished using it. Without this flag, the caller
-** is resposible for freeing any dynamically allocated memory.
+** is responsible for freeing any dynamically allocated memory.
**
** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to
** grow the size of the database using calls to [sqlite3_realloc64()]. This
@@ -12324,7 +12469,7 @@ struct Fts5ExtensionApi {
** This way, even if the tokenizer does not provide synonyms
** when tokenizing query text (it should not - to do would be
** inefficient), it doesn't matter if the user queries for
-** 'first + place' or '1st + place', as there are entires in the
+** 'first + place' or '1st + place', as there are entries in the
** FTS index corresponding to both forms of the first token.
** </ol>
**
@@ -12352,7 +12497,7 @@ struct Fts5ExtensionApi {
** extra data to the FTS index or require FTS5 to query for multiple terms,
** so it is efficient in terms of disk space and query speed. However, it
** does not support prefix queries very well. If, as suggested above, the
-** token "first" is subsituted for "1st" by the tokenizer, then the query:
+** token "first" is substituted for "1st" by the tokenizer, then the query:
**
** <codeblock>
** ... MATCH '1s*'</codeblock>
@@ -13216,94 +13361,104 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#define TK_REPLACE 73
#define TK_RESTRICT 74
#define TK_ROW 75
-#define TK_TRIGGER 76
-#define TK_VACUUM 77
-#define TK_VIEW 78
-#define TK_VIRTUAL 79
-#define TK_WITH 80
-#define TK_REINDEX 81
-#define TK_RENAME 82
-#define TK_CTIME_KW 83
-#define TK_ANY 84
-#define TK_BITAND 85
-#define TK_BITOR 86
-#define TK_LSHIFT 87
-#define TK_RSHIFT 88
-#define TK_PLUS 89
-#define TK_MINUS 90
-#define TK_STAR 91
-#define TK_SLASH 92
-#define TK_REM 93
-#define TK_CONCAT 94
-#define TK_COLLATE 95
-#define TK_BITNOT 96
-#define TK_ON 97
-#define TK_INDEXED 98
-#define TK_STRING 99
-#define TK_JOIN_KW 100
-#define TK_CONSTRAINT 101
-#define TK_DEFAULT 102
-#define TK_NULL 103
-#define TK_PRIMARY 104
-#define TK_UNIQUE 105
-#define TK_CHECK 106
-#define TK_REFERENCES 107
-#define TK_AUTOINCR 108
-#define TK_INSERT 109
-#define TK_DELETE 110
-#define TK_UPDATE 111
-#define TK_SET 112
-#define TK_DEFERRABLE 113
-#define TK_FOREIGN 114
-#define TK_DROP 115
-#define TK_UNION 116
-#define TK_ALL 117
-#define TK_EXCEPT 118
-#define TK_INTERSECT 119
-#define TK_SELECT 120
-#define TK_VALUES 121
-#define TK_DISTINCT 122
-#define TK_DOT 123
-#define TK_FROM 124
-#define TK_JOIN 125
-#define TK_USING 126
-#define TK_ORDER 127
-#define TK_GROUP 128
-#define TK_HAVING 129
-#define TK_LIMIT 130
-#define TK_WHERE 131
-#define TK_INTO 132
-#define TK_NOTHING 133
-#define TK_FLOAT 134
-#define TK_BLOB 135
-#define TK_INTEGER 136
-#define TK_VARIABLE 137
-#define TK_CASE 138
-#define TK_WHEN 139
-#define TK_THEN 140
-#define TK_ELSE 141
-#define TK_INDEX 142
-#define TK_ALTER 143
-#define TK_ADD 144
-#define TK_TRUEFALSE 145
-#define TK_ISNOT 146
-#define TK_FUNCTION 147
-#define TK_COLUMN 148
-#define TK_AGG_FUNCTION 149
-#define TK_AGG_COLUMN 150
-#define TK_UMINUS 151
-#define TK_UPLUS 152
-#define TK_TRUTH 153
-#define TK_REGISTER 154
-#define TK_VECTOR 155
-#define TK_SELECT_COLUMN 156
-#define TK_IF_NULL_ROW 157
-#define TK_ASTERISK 158
-#define TK_SPAN 159
-#define TK_END_OF_FILE 160
-#define TK_UNCLOSED_STRING 161
-#define TK_SPACE 162
-#define TK_ILLEGAL 163
+#define TK_ROWS 76
+#define TK_TRIGGER 77
+#define TK_VACUUM 78
+#define TK_VIEW 79
+#define TK_VIRTUAL 80
+#define TK_WITH 81
+#define TK_CURRENT 82
+#define TK_FOLLOWING 83
+#define TK_PARTITION 84
+#define TK_PRECEDING 85
+#define TK_RANGE 86
+#define TK_UNBOUNDED 87
+#define TK_REINDEX 88
+#define TK_RENAME 89
+#define TK_CTIME_KW 90
+#define TK_ANY 91
+#define TK_BITAND 92
+#define TK_BITOR 93
+#define TK_LSHIFT 94
+#define TK_RSHIFT 95
+#define TK_PLUS 96
+#define TK_MINUS 97
+#define TK_STAR 98
+#define TK_SLASH 99
+#define TK_REM 100
+#define TK_CONCAT 101
+#define TK_COLLATE 102
+#define TK_BITNOT 103
+#define TK_ON 104
+#define TK_INDEXED 105
+#define TK_STRING 106
+#define TK_JOIN_KW 107
+#define TK_CONSTRAINT 108
+#define TK_DEFAULT 109
+#define TK_NULL 110
+#define TK_PRIMARY 111
+#define TK_UNIQUE 112
+#define TK_CHECK 113
+#define TK_REFERENCES 114
+#define TK_AUTOINCR 115
+#define TK_INSERT 116
+#define TK_DELETE 117
+#define TK_UPDATE 118
+#define TK_SET 119
+#define TK_DEFERRABLE 120
+#define TK_FOREIGN 121
+#define TK_DROP 122
+#define TK_UNION 123
+#define TK_ALL 124
+#define TK_EXCEPT 125
+#define TK_INTERSECT 126
+#define TK_SELECT 127
+#define TK_VALUES 128
+#define TK_DISTINCT 129
+#define TK_DOT 130
+#define TK_FROM 131
+#define TK_JOIN 132
+#define TK_USING 133
+#define TK_ORDER 134
+#define TK_GROUP 135
+#define TK_HAVING 136
+#define TK_LIMIT 137
+#define TK_WHERE 138
+#define TK_INTO 139
+#define TK_NOTHING 140
+#define TK_FLOAT 141
+#define TK_BLOB 142
+#define TK_INTEGER 143
+#define TK_VARIABLE 144
+#define TK_CASE 145
+#define TK_WHEN 146
+#define TK_THEN 147
+#define TK_ELSE 148
+#define TK_INDEX 149
+#define TK_ALTER 150
+#define TK_ADD 151
+#define TK_WINDOW 152
+#define TK_OVER 153
+#define TK_FILTER 154
+#define TK_TRUEFALSE 155
+#define TK_ISNOT 156
+#define TK_FUNCTION 157
+#define TK_COLUMN 158
+#define TK_AGG_FUNCTION 159
+#define TK_AGG_COLUMN 160
+#define TK_UMINUS 161
+#define TK_UPLUS 162
+#define TK_TRUTH 163
+#define TK_REGISTER 164
+#define TK_VECTOR 165
+#define TK_SELECT_COLUMN 166
+#define TK_IF_NULL_ROW 167
+#define TK_ASTERISK 168
+#define TK_SPAN 169
+#define TK_END_OF_FILE 170
+#define TK_UNCLOSED_STRING 171
+#define TK_SPACE 172
+#define TK_ILLEGAL 173
/* The token codes above must all fit in 8 bits */
#define TKFLG_MASK 0xff
@@ -13577,7 +13732,8 @@ typedef INT16_TYPE LogEst;
# if defined(__SIZEOF_POINTER__)
# define SQLITE_PTRSIZE __SIZEOF_POINTER__
# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \
- defined(_M_ARM) || defined(__arm__) || defined(__x86)
+ defined(_M_ARM) || defined(__arm__) || defined(__x86) || \
+ (defined(__TOS_AIX__) && !defined(__64BIT__))
# define SQLITE_PTRSIZE 4
# else
# define SQLITE_PTRSIZE 8
@@ -13618,7 +13774,7 @@ typedef INT16_TYPE LogEst;
# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
- defined(__arm__)
+ defined(__arm__) || defined(_M_ARM64)
# define SQLITE_BYTEORDER 1234
# elif defined(sparc) || defined(__ppc__)
# define SQLITE_BYTEORDER 4321
@@ -13873,6 +14029,7 @@ typedef struct NameContext NameContext;
typedef struct Parse Parse;
typedef struct PreUpdate PreUpdate;
typedef struct PrintfArguments PrintfArguments;
+typedef struct RenameToken RenameToken;
typedef struct RowSet RowSet;
typedef struct Savepoint Savepoint;
typedef struct Select Select;
@@ -13893,8 +14050,35 @@ typedef struct VTable VTable;
typedef struct VtabCtx VtabCtx;
typedef struct Walker Walker;
typedef struct WhereInfo WhereInfo;
+typedef struct Window Window;
typedef struct With With;
+
+/*
+** The bitmask datatype defined below is used for various optimizations.
+**
+** Changing this from a 64-bit to a 32-bit type limits the number of
+** tables in a join to 32 instead of 64. But it also reduces the size
+** of the library by 738 bytes on ix86.
+*/
+#ifdef SQLITE_BITMASK_TYPE
+ typedef SQLITE_BITMASK_TYPE Bitmask;
+#else
+ typedef u64 Bitmask;
+#endif
+
+/*
+** The number of bits in a Bitmask. "BMS" means "BitMask Size".
+*/
+#define BMS ((int)(sizeof(Bitmask)*8))
+
+/*
+** A bit in a Bitmask
+*/
+#define MASKBIT(n) (((Bitmask)1)<<(n))
+#define MASKBIT32(n) (((unsigned int)1)<<(n))
+#define ALLBITS ((Bitmask)-1)
+
/* A VList object records a mapping between parameters/variables/wildcards
** in the SQL statement (such as $abc, @pqr, or :xyz) and the integer
** variable number associated with that parameter. See the format description
@@ -13990,7 +14174,7 @@ SQLITE_PRIVATE int sqlite3BtreeGetOptimalReserve(Btree*);
SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p);
SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int);
SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *);
-SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int);
+SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int,int*);
SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster);
SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*, int);
SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*);
@@ -14213,6 +14397,9 @@ struct BtreePayload {
SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload,
int flags, int seekResult);
SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes);
+#ifndef SQLITE_OMIT_WINDOWFUNC
+SQLITE_PRIVATE void sqlite3BtreeSkipNext(BtCursor*);
+#endif
SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes);
SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int flags);
SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*);
@@ -14380,7 +14567,8 @@ struct VdbeOp {
u64 cycles; /* Total time spent executing this instruction */
#endif
#ifdef SQLITE_VDBE_COVERAGE
- int iSrcLine; /* Source-code line that generated this opcode */
+ u32 iSrcLine; /* Source-code line that generated this opcode
+ ** with flags in the upper 8 bits */
#endif
};
typedef struct VdbeOp VdbeOp;
@@ -14481,52 +14669,52 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_AutoCommit 1
#define OP_Transaction 2
#define OP_SorterNext 3 /* jump */
-#define OP_PrevIfOpen 4 /* jump */
-#define OP_NextIfOpen 5 /* jump */
-#define OP_Prev 6 /* jump */
-#define OP_Next 7 /* jump */
-#define OP_Checkpoint 8
-#define OP_JournalMode 9
-#define OP_Vacuum 10
-#define OP_VFilter 11 /* jump, synopsis: iplan=r[P3] zplan='P4' */
-#define OP_VUpdate 12 /* synopsis: data=r[P3@P2] */
-#define OP_Goto 13 /* jump */
-#define OP_Gosub 14 /* jump */
-#define OP_InitCoroutine 15 /* jump */
-#define OP_Yield 16 /* jump */
-#define OP_MustBeInt 17 /* jump */
-#define OP_Jump 18 /* jump */
+#define OP_Prev 4 /* jump */
+#define OP_Next 5 /* jump */
+#define OP_Checkpoint 6
+#define OP_JournalMode 7
+#define OP_Vacuum 8
+#define OP_VFilter 9 /* jump, synopsis: iplan=r[P3] zplan='P4' */
+#define OP_VUpdate 10 /* synopsis: data=r[P3@P2] */
+#define OP_Goto 11 /* jump */
+#define OP_Gosub 12 /* jump */
+#define OP_InitCoroutine 13 /* jump */
+#define OP_Yield 14 /* jump */
+#define OP_MustBeInt 15 /* jump */
+#define OP_Jump 16 /* jump */
+#define OP_Once 17 /* jump */
+#define OP_If 18 /* jump */
#define OP_Not 19 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */
-#define OP_Once 20 /* jump */
-#define OP_If 21 /* jump */
-#define OP_IfNot 22 /* jump */
-#define OP_IfNullRow 23 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */
-#define OP_SeekLT 24 /* jump, synopsis: key=r[P3@P4] */
-#define OP_SeekLE 25 /* jump, synopsis: key=r[P3@P4] */
-#define OP_SeekGE 26 /* jump, synopsis: key=r[P3@P4] */
-#define OP_SeekGT 27 /* jump, synopsis: key=r[P3@P4] */
-#define OP_NoConflict 28 /* jump, synopsis: key=r[P3@P4] */
-#define OP_NotFound 29 /* jump, synopsis: key=r[P3@P4] */
-#define OP_Found 30 /* jump, synopsis: key=r[P3@P4] */
-#define OP_SeekRowid 31 /* jump, synopsis: intkey=r[P3] */
-#define OP_NotExists 32 /* jump, synopsis: intkey=r[P3] */
-#define OP_Last 33 /* jump */
-#define OP_IfSmaller 34 /* jump */
-#define OP_SorterSort 35 /* jump */
-#define OP_Sort 36 /* jump */
-#define OP_Rewind 37 /* jump */
-#define OP_IdxLE 38 /* jump, synopsis: key=r[P3@P4] */
-#define OP_IdxGT 39 /* jump, synopsis: key=r[P3@P4] */
-#define OP_IdxLT 40 /* jump, synopsis: key=r[P3@P4] */
-#define OP_IdxGE 41 /* jump, synopsis: key=r[P3@P4] */
-#define OP_RowSetRead 42 /* jump, synopsis: r[P3]=rowset(P1) */
+#define OP_IfNot 20 /* jump */
+#define OP_IfNullRow 21 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */
+#define OP_SeekLT 22 /* jump, synopsis: key=r[P3@P4] */
+#define OP_SeekLE 23 /* jump, synopsis: key=r[P3@P4] */
+#define OP_SeekGE 24 /* jump, synopsis: key=r[P3@P4] */
+#define OP_SeekGT 25 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IfNoHope 26 /* jump, synopsis: key=r[P3@P4] */
+#define OP_NoConflict 27 /* jump, synopsis: key=r[P3@P4] */
+#define OP_NotFound 28 /* jump, synopsis: key=r[P3@P4] */
+#define OP_Found 29 /* jump, synopsis: key=r[P3@P4] */
+#define OP_SeekRowid 30 /* jump, synopsis: intkey=r[P3] */
+#define OP_NotExists 31 /* jump, synopsis: intkey=r[P3] */
+#define OP_Last 32 /* jump */
+#define OP_IfSmaller 33 /* jump */
+#define OP_SorterSort 34 /* jump */
+#define OP_Sort 35 /* jump */
+#define OP_Rewind 36 /* jump */
+#define OP_IdxLE 37 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IdxGT 38 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IdxLT 39 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IdxGE 40 /* jump, synopsis: key=r[P3@P4] */
+#define OP_RowSetRead 41 /* jump, synopsis: r[P3]=rowset(P1) */
+#define OP_RowSetTest 42 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
#define OP_Or 43 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
#define OP_And 44 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
-#define OP_RowSetTest 45 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
-#define OP_Program 46 /* jump */
-#define OP_FkIfZero 47 /* jump, synopsis: if fkctr[P1]==0 goto P2 */
-#define OP_IfPos 48 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
-#define OP_IfNotZero 49 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
+#define OP_Program 45 /* jump */
+#define OP_FkIfZero 46 /* jump, synopsis: if fkctr[P1]==0 goto P2 */
+#define OP_IfPos 47 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
+#define OP_IfNotZero 48 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
+#define OP_DecrJumpZero 49 /* jump, synopsis: if (--r[P1])==0 goto P2 */
#define OP_IsNull 50 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
#define OP_NotNull 51 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
#define OP_Ne 52 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
@@ -14536,119 +14724,121 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_Lt 56 /* jump, same as TK_LT, synopsis: IF r[P3]<r[P1] */
#define OP_Ge 57 /* jump, same as TK_GE, synopsis: IF r[P3]>=r[P1] */
#define OP_ElseNotEq 58 /* jump, same as TK_ESCAPE */
-#define OP_DecrJumpZero 59 /* jump, synopsis: if (--r[P1])==0 goto P2 */
-#define OP_IncrVacuum 60 /* jump */
-#define OP_VNext 61 /* jump */
-#define OP_Init 62 /* jump, synopsis: Start at P2 */
-#define OP_Return 63
-#define OP_EndCoroutine 64
-#define OP_HaltIfNull 65 /* synopsis: if r[P3]=null halt */
-#define OP_Halt 66
-#define OP_Integer 67 /* synopsis: r[P2]=P1 */
-#define OP_Int64 68 /* synopsis: r[P2]=P4 */
-#define OP_String 69 /* synopsis: r[P2]='P4' (len=P1) */
-#define OP_Null 70 /* synopsis: r[P2..P3]=NULL */
-#define OP_SoftNull 71 /* synopsis: r[P1]=NULL */
-#define OP_Blob 72 /* synopsis: r[P2]=P4 (len=P1) */
-#define OP_Variable 73 /* synopsis: r[P2]=parameter(P1,P4) */
-#define OP_Move 74 /* synopsis: r[P2@P3]=r[P1@P3] */
-#define OP_Copy 75 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
-#define OP_SCopy 76 /* synopsis: r[P2]=r[P1] */
-#define OP_IntCopy 77 /* synopsis: r[P2]=r[P1] */
-#define OP_ResultRow 78 /* synopsis: output=r[P1@P2] */
-#define OP_CollSeq 79
-#define OP_AddImm 80 /* synopsis: r[P1]=r[P1]+P2 */
-#define OP_RealAffinity 81
-#define OP_Cast 82 /* synopsis: affinity(r[P1]) */
-#define OP_Permutation 83
-#define OP_Compare 84 /* synopsis: r[P1@P3] <-> r[P2@P3] */
-#define OP_BitAnd 85 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
-#define OP_BitOr 86 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
-#define OP_ShiftLeft 87 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
-#define OP_ShiftRight 88 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
-#define OP_Add 89 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
-#define OP_Subtract 90 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
-#define OP_Multiply 91 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
-#define OP_Divide 92 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
-#define OP_Remainder 93 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
-#define OP_Concat 94 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
-#define OP_IsTrue 95 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */
-#define OP_BitNot 96 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */
-#define OP_Offset 97 /* synopsis: r[P3] = sqlite_offset(P1) */
-#define OP_Column 98 /* synopsis: r[P3]=PX */
-#define OP_String8 99 /* same as TK_STRING, synopsis: r[P2]='P4' */
-#define OP_Affinity 100 /* synopsis: affinity(r[P1@P2]) */
-#define OP_MakeRecord 101 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
-#define OP_Count 102 /* synopsis: r[P2]=count() */
-#define OP_ReadCookie 103
-#define OP_SetCookie 104
-#define OP_ReopenIdx 105 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenRead 106 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenWrite 107 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenDup 108
-#define OP_OpenAutoindex 109 /* synopsis: nColumn=P2 */
-#define OP_OpenEphemeral 110 /* synopsis: nColumn=P2 */
-#define OP_SorterOpen 111
-#define OP_SequenceTest 112 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
-#define OP_OpenPseudo 113 /* synopsis: P3 columns in r[P2] */
-#define OP_Close 114
-#define OP_ColumnsUsed 115
-#define OP_Sequence 116 /* synopsis: r[P2]=cursor[P1].ctr++ */
-#define OP_NewRowid 117 /* synopsis: r[P2]=rowid */
-#define OP_Insert 118 /* synopsis: intkey=r[P3] data=r[P2] */
-#define OP_InsertInt 119 /* synopsis: intkey=P3 data=r[P2] */
-#define OP_Delete 120
-#define OP_ResetCount 121
-#define OP_SorterCompare 122 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
-#define OP_SorterData 123 /* synopsis: r[P2]=data */
-#define OP_RowData 124 /* synopsis: r[P2]=data */
-#define OP_Rowid 125 /* synopsis: r[P2]=rowid */
-#define OP_NullRow 126
-#define OP_SeekEnd 127
-#define OP_SorterInsert 128 /* synopsis: key=r[P2] */
-#define OP_IdxInsert 129 /* synopsis: key=r[P2] */
-#define OP_IdxDelete 130 /* synopsis: key=r[P2@P3] */
-#define OP_DeferredSeek 131 /* synopsis: Move P3 to P1.rowid if needed */
-#define OP_IdxRowid 132 /* synopsis: r[P2]=rowid */
-#define OP_Destroy 133
-#define OP_Real 134 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
-#define OP_Clear 135
-#define OP_ResetSorter 136
-#define OP_CreateBtree 137 /* synopsis: r[P2]=root iDb=P1 flags=P3 */
-#define OP_SqlExec 138
-#define OP_ParseSchema 139
-#define OP_LoadAnalysis 140
-#define OP_DropTable 141
-#define OP_DropIndex 142
-#define OP_DropTrigger 143
-#define OP_IntegrityCk 144
-#define OP_RowSetAdd 145 /* synopsis: rowset(P1)=r[P2] */
-#define OP_Param 146
-#define OP_FkCounter 147 /* synopsis: fkctr[P1]+=P2 */
-#define OP_MemMax 148 /* synopsis: r[P1]=max(r[P1],r[P2]) */
-#define OP_OffsetLimit 149 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
-#define OP_AggStep0 150 /* synopsis: accum=r[P3] step(r[P2@P5]) */
-#define OP_AggStep 151 /* synopsis: accum=r[P3] step(r[P2@P5]) */
-#define OP_AggFinal 152 /* synopsis: accum=r[P1] N=P2 */
-#define OP_Expire 153
-#define OP_TableLock 154 /* synopsis: iDb=P1 root=P2 write=P3 */
-#define OP_VBegin 155
-#define OP_VCreate 156
-#define OP_VDestroy 157
-#define OP_VOpen 158
-#define OP_VColumn 159 /* synopsis: r[P3]=vcolumn(P2) */
-#define OP_VRename 160
-#define OP_Pagecount 161
-#define OP_MaxPgcnt 162
-#define OP_PureFunc0 163
-#define OP_Function0 164 /* synopsis: r[P3]=func(r[P2@P5]) */
-#define OP_PureFunc 165
-#define OP_Function 166 /* synopsis: r[P3]=func(r[P2@P5]) */
-#define OP_Trace 167
-#define OP_CursorHint 168
-#define OP_Noop 169
-#define OP_Explain 170
-#define OP_Abortable 171
+#define OP_IncrVacuum 59 /* jump */
+#define OP_VNext 60 /* jump */
+#define OP_Init 61 /* jump, synopsis: Start at P2 */
+#define OP_PureFunc0 62
+#define OP_Function0 63 /* synopsis: r[P3]=func(r[P2@P5]) */
+#define OP_PureFunc 64
+#define OP_Function 65 /* synopsis: r[P3]=func(r[P2@P5]) */
+#define OP_Return 66
+#define OP_EndCoroutine 67
+#define OP_HaltIfNull 68 /* synopsis: if r[P3]=null halt */
+#define OP_Halt 69
+#define OP_Integer 70 /* synopsis: r[P2]=P1 */
+#define OP_Int64 71 /* synopsis: r[P2]=P4 */
+#define OP_String 72 /* synopsis: r[P2]='P4' (len=P1) */
+#define OP_Null 73 /* synopsis: r[P2..P3]=NULL */
+#define OP_SoftNull 74 /* synopsis: r[P1]=NULL */
+#define OP_Blob 75 /* synopsis: r[P2]=P4 (len=P1) */
+#define OP_Variable 76 /* synopsis: r[P2]=parameter(P1,P4) */
+#define OP_Move 77 /* synopsis: r[P2@P3]=r[P1@P3] */
+#define OP_Copy 78 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
+#define OP_SCopy 79 /* synopsis: r[P2]=r[P1] */
+#define OP_IntCopy 80 /* synopsis: r[P2]=r[P1] */
+#define OP_ResultRow 81 /* synopsis: output=r[P1@P2] */
+#define OP_CollSeq 82
+#define OP_AddImm 83 /* synopsis: r[P1]=r[P1]+P2 */
+#define OP_RealAffinity 84
+#define OP_Cast 85 /* synopsis: affinity(r[P1]) */
+#define OP_Permutation 86
+#define OP_Compare 87 /* synopsis: r[P1@P3] <-> r[P2@P3] */
+#define OP_IsTrue 88 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */
+#define OP_Offset 89 /* synopsis: r[P3] = sqlite_offset(P1) */
+#define OP_Column 90 /* synopsis: r[P3]=PX */
+#define OP_Affinity 91 /* synopsis: affinity(r[P1@P2]) */
+#define OP_BitAnd 92 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
+#define OP_BitOr 93 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
+#define OP_ShiftLeft 94 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
+#define OP_ShiftRight 95 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
+#define OP_Add 96 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
+#define OP_Subtract 97 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
+#define OP_Multiply 98 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
+#define OP_Divide 99 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
+#define OP_Remainder 100 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
+#define OP_Concat 101 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
+#define OP_MakeRecord 102 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
+#define OP_BitNot 103 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
+#define OP_Count 104 /* synopsis: r[P2]=count() */
+#define OP_ReadCookie 105
+#define OP_String8 106 /* same as TK_STRING, synopsis: r[P2]='P4' */
+#define OP_SetCookie 107
+#define OP_ReopenIdx 108 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenRead 109 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenWrite 110 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenDup 111
+#define OP_OpenAutoindex 112 /* synopsis: nColumn=P2 */
+#define OP_OpenEphemeral 113 /* synopsis: nColumn=P2 */
+#define OP_SorterOpen 114
+#define OP_SequenceTest 115 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
+#define OP_OpenPseudo 116 /* synopsis: P3 columns in r[P2] */
+#define OP_Close 117
+#define OP_ColumnsUsed 118
+#define OP_SeekHit 119 /* synopsis: seekHit=P2 */
+#define OP_Sequence 120 /* synopsis: r[P2]=cursor[P1].ctr++ */
+#define OP_NewRowid 121 /* synopsis: r[P2]=rowid */
+#define OP_Insert 122 /* synopsis: intkey=r[P3] data=r[P2] */
+#define OP_InsertInt 123 /* synopsis: intkey=P3 data=r[P2] */
+#define OP_Delete 124
+#define OP_ResetCount 125
+#define OP_SorterCompare 126 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
+#define OP_SorterData 127 /* synopsis: r[P2]=data */
+#define OP_RowData 128 /* synopsis: r[P2]=data */
+#define OP_Rowid 129 /* synopsis: r[P2]=rowid */
+#define OP_NullRow 130
+#define OP_SeekEnd 131
+#define OP_SorterInsert 132 /* synopsis: key=r[P2] */
+#define OP_IdxInsert 133 /* synopsis: key=r[P2] */
+#define OP_IdxDelete 134 /* synopsis: key=r[P2@P3] */
+#define OP_DeferredSeek 135 /* synopsis: Move P3 to P1.rowid if needed */
+#define OP_IdxRowid 136 /* synopsis: r[P2]=rowid */
+#define OP_Destroy 137
+#define OP_Clear 138
+#define OP_ResetSorter 139
+#define OP_CreateBtree 140 /* synopsis: r[P2]=root iDb=P1 flags=P3 */
+#define OP_Real 141 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
+#define OP_SqlExec 142
+#define OP_ParseSchema 143
+#define OP_LoadAnalysis 144
+#define OP_DropTable 145
+#define OP_DropIndex 146
+#define OP_DropTrigger 147
+#define OP_IntegrityCk 148
+#define OP_RowSetAdd 149 /* synopsis: rowset(P1)=r[P2] */
+#define OP_Param 150
+#define OP_FkCounter 151 /* synopsis: fkctr[P1]+=P2 */
+#define OP_MemMax 152 /* synopsis: r[P1]=max(r[P1],r[P2]) */
+#define OP_OffsetLimit 153 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
+#define OP_AggInverse 154 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */
+#define OP_AggStep 155 /* synopsis: accum=r[P3] step(r[P2@P5]) */
+#define OP_AggStep1 156 /* synopsis: accum=r[P3] step(r[P2@P5]) */
+#define OP_AggValue 157 /* synopsis: r[P3]=value N=P2 */
+#define OP_AggFinal 158 /* synopsis: accum=r[P1] N=P2 */
+#define OP_Expire 159
+#define OP_TableLock 160 /* synopsis: iDb=P1 root=P2 write=P3 */
+#define OP_VBegin 161
+#define OP_VCreate 162
+#define OP_VDestroy 163
+#define OP_VOpen 164
+#define OP_VColumn 165 /* synopsis: r[P3]=vcolumn(P2) */
+#define OP_VRename 166
+#define OP_Pagecount 167
+#define OP_MaxPgcnt 168
+#define OP_Trace 169
+#define OP_CursorHint 170
+#define OP_Noop 171
+#define OP_Explain 172
+#define OP_Abortable 173
/* Properties such as "out2" or "jump" that are specified in
** comments following the "case" for each opcode in the vdbe.c
@@ -14661,28 +14851,28 @@ typedef struct VdbeOpList VdbeOpList;
#define OPFLG_OUT2 0x10 /* out2: P2 is an output */
#define OPFLG_OUT3 0x20 /* out3: P3 is an output */
#define OPFLG_INITIALIZER {\
-/* 0 */ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,\
-/* 8 */ 0x00, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01,\
-/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0x03, 0x03, 0x01,\
+/* 0 */ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x10,\
+/* 8 */ 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x03, 0x03,\
+/* 16 */ 0x01, 0x01, 0x03, 0x12, 0x03, 0x01, 0x09, 0x09,\
/* 24 */ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,\
-/* 32 */ 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\
-/* 40 */ 0x01, 0x01, 0x23, 0x26, 0x26, 0x0b, 0x01, 0x01,\
+/* 32 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\
+/* 40 */ 0x01, 0x23, 0x0b, 0x26, 0x26, 0x01, 0x01, 0x03,\
/* 48 */ 0x03, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
-/* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x01, 0x01, 0x01, 0x02,\
-/* 64 */ 0x02, 0x08, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00,\
-/* 72 */ 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\
-/* 80 */ 0x02, 0x02, 0x02, 0x00, 0x00, 0x26, 0x26, 0x26,\
-/* 88 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x12,\
-/* 96 */ 0x12, 0x20, 0x00, 0x10, 0x00, 0x00, 0x10, 0x10,\
-/* 104 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\
-/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,\
-/* 128 */ 0x04, 0x04, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00,\
-/* 136 */ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 144 */ 0x00, 0x06, 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00,\
-/* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 160 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 168 */ 0x00, 0x00, 0x00, 0x00,}
+/* 56 */ 0x0b, 0x0b, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,\
+/* 64 */ 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10, 0x10,\
+/* 72 */ 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,\
+/* 80 */ 0x10, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,\
+/* 88 */ 0x12, 0x20, 0x00, 0x00, 0x26, 0x26, 0x26, 0x26,\
+/* 96 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00, 0x12,\
+/* 104 */ 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 120 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 128 */ 0x00, 0x10, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00,\
+/* 136 */ 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\
+/* 144 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00,\
+/* 152 */ 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\
+/* 168 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,}
/* The sqlite3P2Values() routine is able to run faster if it knows
** the value of the largest JUMP opcode. The smaller the maximum
@@ -14690,7 +14880,7 @@ typedef struct VdbeOpList VdbeOpList;
** generated this include file strives to group all JUMP opcodes
** together near the beginning of the list.
*/
-#define SQLITE_MX_JUMP_OPCODE 62 /* Maximum JUMP opcode */
+#define SQLITE_MX_JUMP_OPCODE 61 /* Maximum JUMP opcode */
/************** End of opcodes.h *********************************************/
/************** Continuing where we left off in vdbe.h ***********************/
@@ -14764,9 +14954,6 @@ SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3*,Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,Parse*);
SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int);
-#ifdef SQLITE_COVERAGE_TEST
-SQLITE_PRIVATE int sqlite3VdbeLabelHasBeenResolved(Vdbe*,int);
-#endif
SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*);
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *, int);
@@ -14788,6 +14975,7 @@ SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe*, int);
SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*);
#endif
SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
+SQLITE_PRIVATE int sqlite3BlobCompare(const Mem*, const Mem*);
SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
@@ -14843,23 +15031,52 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...);
**
** VdbeCoverageNeverTaken(v) // Previous branch is never taken
**
+** VdbeCoverageNeverNull(v) // Previous three-way branch is only
+** // taken on the first two ways. The
+** // NULL option is not possible
+**
+** VdbeCoverageEqNe(v) // Previous OP_Jump is only interested
+** // in distingishing equal and not-equal.
+**
** Every VDBE branch operation must be tagged with one of the macros above.
** If not, then when "make test" is run with -DSQLITE_VDBE_COVERAGE and
** -DSQLITE_DEBUG then an ALWAYS() will fail in the vdbeTakeBranch()
** routine in vdbe.c, alerting the developer to the missed tag.
+**
+** During testing, the test application will invoke
+** sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE,...) to set a callback
+** routine that is invoked as each bytecode branch is taken. The callback
+** contains the sqlite3.c source line number ov the VdbeCoverage macro and
+** flags to indicate whether or not the branch was taken. The test application
+** is responsible for keeping track of this and reporting byte-code branches
+** that are never taken.
+**
+** See the VdbeBranchTaken() macro and vdbeTakeBranch() function in the
+** vdbe.c source file for additional information.
*/
#ifdef SQLITE_VDBE_COVERAGE
SQLITE_PRIVATE void sqlite3VdbeSetLineNumber(Vdbe*,int);
# define VdbeCoverage(v) sqlite3VdbeSetLineNumber(v,__LINE__)
# define VdbeCoverageIf(v,x) if(x)sqlite3VdbeSetLineNumber(v,__LINE__)
-# define VdbeCoverageAlwaysTaken(v) sqlite3VdbeSetLineNumber(v,2);
-# define VdbeCoverageNeverTaken(v) sqlite3VdbeSetLineNumber(v,1);
+# define VdbeCoverageAlwaysTaken(v) \
+ sqlite3VdbeSetLineNumber(v,__LINE__|0x5000000);
+# define VdbeCoverageNeverTaken(v) \
+ sqlite3VdbeSetLineNumber(v,__LINE__|0x6000000);
+# define VdbeCoverageNeverNull(v) \
+ sqlite3VdbeSetLineNumber(v,__LINE__|0x4000000);
+# define VdbeCoverageNeverNullIf(v,x) \
+ if(x)sqlite3VdbeSetLineNumber(v,__LINE__|0x4000000);
+# define VdbeCoverageEqNe(v) \
+ sqlite3VdbeSetLineNumber(v,__LINE__|0x8000000);
# define VDBE_OFFSET_LINENO(x) (__LINE__+x)
#else
# define VdbeCoverage(v)
# define VdbeCoverageIf(v,x)
# define VdbeCoverageAlwaysTaken(v)
# define VdbeCoverageNeverTaken(v)
+# define VdbeCoverageNeverNull(v)
+# define VdbeCoverageNeverNullIf(v,x)
+# define VdbeCoverageEqNe(v)
# define VDBE_OFFSET_LINENO(x) 0
#endif
@@ -14869,6 +15086,10 @@ SQLITE_PRIVATE void sqlite3VdbeScanStatus(Vdbe*, int, int, int, LogEst, const ch
# define sqlite3VdbeScanStatus(a,b,c,d,e)
#endif
+#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
+SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, VdbeOp*);
+#endif
+
#endif /* SQLITE_VDBE_H */
/************** End of vdbe.h ************************************************/
@@ -15063,6 +15284,8 @@ SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager, Pgno);
SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot);
SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot);
SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager);
+SQLITE_PRIVATE int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot);
+SQLITE_PRIVATE void sqlite3PagerSnapshotUnlock(Pager *pPager);
# endif
#else
# define sqlite3PagerUseWal(x,y) 0
@@ -16046,6 +16269,7 @@ struct sqlite3 {
#define SQLITE_EnableQPSG 0x00800000 /* Query Planner Stability Guarantee*/
#define SQLITE_TriggerEQP 0x01000000 /* Show trigger EXPLAIN QUERY PLAN */
#define SQLITE_ResetDatabase 0x02000000 /* Reset the database */
+#define SQLITE_LegacyAlter 0x04000000 /* Legacy ALTER TABLE behaviour */
/* Flags used only if debugging */
#ifdef SQLITE_DEBUG
@@ -16070,7 +16294,7 @@ struct sqlite3 {
** selectively disable various optimizations.
*/
#define SQLITE_QueryFlattener 0x0001 /* Query flattening */
-#define SQLITE_ColumnCache 0x0002 /* Column cache */
+ /* 0x0002 available for reuse */
#define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */
#define SQLITE_FactorOutConst 0x0008 /* Constant factoring */
#define SQLITE_DistinctOpt 0x0010 /* DISTINCT using indexes */
@@ -16084,6 +16308,8 @@ struct sqlite3 {
/* TH3 expects the Stat34 ^^^^^^ value to be 0x0800. Don't change it */
#define SQLITE_PushDown 0x1000 /* The push-down optimization */
#define SQLITE_SimplifyJoin 0x2000 /* Convert LEFT JOIN to JOIN */
+#define SQLITE_SkipScan 0x4000 /* Skip-scans */
+#define SQLITE_PropagateConst 0x8000 /* The constant propagation opt */
#define SQLITE_AllOpts 0xffff /* All optimizations */
/*
@@ -16122,11 +16348,13 @@ struct sqlite3 {
*/
struct FuncDef {
i8 nArg; /* Number of arguments. -1 means unlimited */
- u16 funcFlags; /* Some combination of SQLITE_FUNC_* */
+ u32 funcFlags; /* Some combination of SQLITE_FUNC_* */
void *pUserData; /* User data parameter */
FuncDef *pNext; /* Next function with same name */
void (*xSFunc)(sqlite3_context*,int,sqlite3_value**); /* func or agg-step */
void (*xFinalize)(sqlite3_context*); /* Agg finalizer */
+ void (*xValue)(sqlite3_context*); /* Current agg value */
+ void (*xInverse)(sqlite3_context*,int,sqlite3_value**); /* inverse agg-step */
const char *zName; /* SQL name of the function. */
union {
FuncDef *pHash; /* Next with a different name but the same hash */
@@ -16183,6 +16411,8 @@ struct FuncDestructor {
** single query - might change over time */
#define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */
#define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */
+#define SQLITE_FUNC_WINDOW 0x10000 /* Built-in window-only function */
+#define SQLITE_FUNC_WINDOW_SIZE 0x20000 /* Requires partition size as arg. */
/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
@@ -16217,6 +16447,12 @@ struct FuncDestructor {
** are interpreted in the same way as the first 4 parameters to
** FUNCTION().
**
+** WFUNCTION(zName, nArg, iArg, xStep, xFinal, xValue, xInverse)
+** Used to create an aggregate function definition implemented by
+** the C functions xStep and xFinal. The first four parameters
+** are interpreted in the same way as the first 4 parameters to
+** FUNCTION().
+**
** LIKEFUNC(zName, nArg, pArg, flags)
** Used to create a scalar function definition of a function zName
** that accepts nArg arguments and is implemented by a call to C
@@ -16227,31 +16463,35 @@ struct FuncDestructor {
*/
#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
- SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} }
+ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
- SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} }
+ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8, \
- 0, 0, xFunc, 0, #zName, {0} }
+ 0, 0, xFunc, 0, 0, 0, #zName, {0} }
#define PURE_DATE(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
- (void*)&sqlite3Config, 0, xFunc, 0, #zName, {0} }
+ (void*)&sqlite3Config, 0, xFunc, 0, 0, 0, #zName, {0} }
#define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \
{nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\
- SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, #zName, {0} }
+ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \
{nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
- pArg, 0, xFunc, 0, #zName, }
+ pArg, 0, xFunc, 0, 0, 0, #zName, }
#define LIKEFUNC(zName, nArg, arg, flags) \
{nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \
- (void *)arg, 0, likeFunc, 0, #zName, {0} }
-#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \
+ (void *)arg, 0, likeFunc, 0, 0, 0, #zName, {0} }
+#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue) \
{nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \
- SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,#zName, {0}}
+ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,0,#zName, {0}}
#define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \
{nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \
- SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,#zName, {0}}
+ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xFinal,0,#zName, {0}}
+
+#define WAGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue, xInverse, f) \
+ {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|f, \
+ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,xInverse,#zName, {0}}
/*
** All current savepoints are stored in a linked list starting at
@@ -16737,6 +16977,7 @@ struct Index {
tRowcnt *aiRowEst; /* Non-logarithmic stat1 data for this index */
tRowcnt nRowEst0; /* Non-logarithmic number of rows in the index */
#endif
+ Bitmask colNotIdxed; /* 0 for unindexed columns in pTab */
};
/*
@@ -16775,9 +17016,11 @@ struct IndexSample {
** Each token coming out of the lexer is an instance of
** this structure. Tokens are also used as part of an expression.
**
-** Note if Token.z==0 then Token.dyn and Token.n are undefined and
-** may contain random values. Do not make any assumptions about Token.dyn
-** and Token.n when Token.z==0.
+** The memory that "z" points to is owned by other objects. Take care
+** that the owner of the "z" string does not deallocate the string before
+** the Token goes out of scope! Very often, the "z" points to some place
+** in the middle of the Parse.zSql text. But it might also point to a
+** static string.
*/
struct Token {
const char *z; /* Text of the token. Not NULL-terminated! */
@@ -16952,6 +17195,9 @@ struct Expr {
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
Table *pTab; /* Table for TK_COLUMN expressions. Can be NULL
** for a column of an index on an expression */
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ Window *pWin; /* Window definition for window functions */
+#endif
};
/*
@@ -16960,7 +17206,7 @@ struct Expr {
#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */
#define EP_Agg 0x000002 /* Contains one or more aggregate functions */
#define EP_HasFunc 0x000004 /* Contains one or more functions of any kind */
- /* 0x000008 // available for use */
+#define EP_FixedCol 0x000008 /* TK_Column with a known fixed value */
#define EP_Distinct 0x000010 /* Aggregate function with DISTINCT keyword */
#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */
#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
@@ -17083,31 +17329,6 @@ struct IdList {
};
/*
-** The bitmask datatype defined below is used for various optimizations.
-**
-** Changing this from a 64-bit to a 32-bit type limits the number of
-** tables in a join to 32 instead of 64. But it also reduces the size
-** of the library by 738 bytes on ix86.
-*/
-#ifdef SQLITE_BITMASK_TYPE
- typedef SQLITE_BITMASK_TYPE Bitmask;
-#else
- typedef u64 Bitmask;
-#endif
-
-/*
-** The number of bits in a Bitmask. "BMS" means "BitMask Size".
-*/
-#define BMS ((int)(sizeof(Bitmask)*8))
-
-/*
-** A bit in a Bitmask
-*/
-#define MASKBIT(n) (((Bitmask)1)<<(n))
-#define MASKBIT32(n) (((unsigned int)1)<<(n))
-#define ALLBITS ((Bitmask)-1)
-
-/*
** The following structure describes the FROM clause of a SELECT statement.
** Each table or subquery in the FROM clause is a separate element of
** the SrcList.a[] array.
@@ -17238,6 +17459,7 @@ struct NameContext {
int nRef; /* Number of names resolved by this context */
int nErr; /* Number of errors encountered while resolving names */
u16 ncFlags; /* Zero or more NC_* flags defined below */
+ Select *pWinSelect; /* SELECT statement for any window functions */
};
/*
@@ -17260,6 +17482,7 @@ struct NameContext {
#define NC_UUpsert 0x0200 /* True if uNC.pUpsert is used */
#define NC_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */
#define NC_Complex 0x2000 /* True if a function or subquery seen */
+#define NC_AllowWin 0x4000 /* Window functions are allowed here */
/*
** An instance of the following object describes a single ON CONFLICT
@@ -17314,9 +17537,7 @@ struct Select {
LogEst nSelectRow; /* Estimated number of result rows */
u32 selFlags; /* Various SF_* values */
int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
-#if SELECTTRACE_ENABLED
- char zSelName[12]; /* Symbolic name of this SELECT use for debugging */
-#endif
+ u32 selId; /* Unique identifier number for this SELECT */
int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */
SrcList *pSrc; /* The FROM clause */
Expr *pWhere; /* The WHERE clause */
@@ -17327,6 +17548,10 @@ struct Select {
Select *pNext; /* Next select to the left in a compound */
Expr *pLimit; /* LIMIT expression. NULL means not used. */
With *pWith; /* WITH clause attached to this select. Or NULL. */
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ Window *pWin; /* List of window functions */
+ Window *pWinDefn; /* List of named window definitions */
+#endif
};
/*
@@ -17471,13 +17696,6 @@ struct AutoincInfo {
};
/*
-** Size of the column cache
-*/
-#ifndef SQLITE_N_COLCACHE
-# define SQLITE_N_COLCACHE 10
-#endif
-
-/*
** At least one instance of the following structure is created for each
** trigger that may be fired while parsing an INSERT, UPDATE or DELETE
** statement. All such objects are stored in the linked list headed at
@@ -17552,7 +17770,6 @@ struct Parse {
u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */
u8 okConstFactor; /* OK to factor out constants */
u8 disableLookaside; /* Number of times lookaside has been disabled */
- u8 nColCache; /* Number of entries in aColCache[] */
int nRangeReg; /* Size of the temporary register block */
int iRangeReg; /* First register in temporary register block */
int nErr; /* Number of errors seen */
@@ -17562,8 +17779,6 @@ struct Parse {
int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */
int iSelfTab; /* Table associated with an index on expr, or negative
** of the base register during check-constraint eval */
- int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
- int iCacheCnt; /* Counter used to generate aColCache[].lru values */
int nLabel; /* Number of labels used */
int *aLabel; /* Space to hold the labels */
ExprList *pConstExpr;/* Constant expressions */
@@ -17573,9 +17788,7 @@ struct Parse {
int regRowid; /* Register holding rowid of CREATE TABLE entry */
int regRoot; /* Register holding root page number for new objects */
int nMaxArg; /* Max args passed to user function by sub-program */
-#if SELECTTRACE_ENABLED
- int nSelect; /* Number of SELECT statements seen */
-#endif
+ int nSelect; /* Number of SELECT stmts. Counter for Select.selId */
#ifndef SQLITE_OMIT_SHARED_CACHE
int nTableLock; /* Number of locks in aTableLock */
TableLock *aTableLock; /* Required table locks for shared-cache mode */
@@ -17595,17 +17808,9 @@ struct Parse {
** Fields above must be initialized to zero. The fields that follow,
** down to the beginning of the recursive section, do not need to be
** initialized as they will be set before being used. The boundary is
- ** determined by offsetof(Parse,aColCache).
+ ** determined by offsetof(Parse,aTempReg).
**************************************************************************/
- struct yColCache {
- int iTable; /* Table cursor number */
- i16 iColumn; /* Table column number */
- u8 tempReg; /* iReg is a temp register that needs to be freed */
- int iLevel; /* Nesting level */
- int iReg; /* Reg with value of this column. 0 means none. */
- int lru; /* Least recently used entry has the smallest value */
- } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */
int aTempReg[8]; /* Holding area for temporary registers */
Token sNameToken; /* Token with unqualified schema object name */
@@ -17620,8 +17825,10 @@ struct Parse {
ynVar nVar; /* Number of '?' variables seen in the SQL so far */
u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */
u8 explain; /* True if the EXPLAIN flag is found on the query */
+#if !(defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_OMIT_ALTERTABLE))
+ u8 eParseMode; /* PARSE_MODE_XXX constant */
+#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
- u8 declareVtab; /* True if inside sqlite3_declare_vtab() */
int nVtabLock; /* Number of virtual tables to lock */
#endif
int nHeight; /* Expression tree height of current sub-select */
@@ -17632,6 +17839,7 @@ struct Parse {
Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */
const char *zTail; /* All SQL text past the last semicolon parsed */
Table *pNewTable; /* A table being constructed by CREATE TABLE */
+ Index *pNewIndex; /* An index being constructed by CREATE INDEX */
Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */
const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -17642,12 +17850,20 @@ struct Parse {
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
With *pWith; /* Current WITH clause, or NULL */
With *pWithToFree; /* Free this WITH object at the end of the parse */
+#ifndef SQLITE_OMIT_ALTERTABLE
+ RenameToken *pRename; /* Tokens subject to renaming by ALTER TABLE */
+#endif
};
+#define PARSE_MODE_NORMAL 0
+#define PARSE_MODE_DECLARE_VTAB 1
+#define PARSE_MODE_RENAME_COLUMN 2
+#define PARSE_MODE_RENAME_TABLE 3
+
/*
** Sizes and pointers of various parts of the Parse object.
*/
-#define PARSE_HDR_SZ offsetof(Parse,aColCache) /* Recursive part w/o aColCache*/
+#define PARSE_HDR_SZ offsetof(Parse,aTempReg) /* Recursive part w/o aColCache*/
#define PARSE_RECURSE_SZ offsetof(Parse,sLastToken) /* Recursive part */
#define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */
#define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */
@@ -17658,7 +17874,19 @@ struct Parse {
#ifdef SQLITE_OMIT_VIRTUALTABLE
#define IN_DECLARE_VTAB 0
#else
- #define IN_DECLARE_VTAB (pParse->declareVtab)
+ #define IN_DECLARE_VTAB (pParse->eParseMode==PARSE_MODE_DECLARE_VTAB)
+#endif
+
+#if defined(SQLITE_OMIT_ALTERTABLE)
+ #define IN_RENAME_OBJECT 0
+#else
+ #define IN_RENAME_OBJECT (pParse->eParseMode>=PARSE_MODE_RENAME_COLUMN)
+#endif
+
+#if defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_OMIT_ALTERTABLE)
+ #define IN_SPECIAL_PARSE 0
+#else
+ #define IN_SPECIAL_PARSE (pParse->eParseMode!=PARSE_MODE_NORMAL)
#endif
/*
@@ -17837,9 +18065,15 @@ typedef struct {
char **pzErrMsg; /* Error message stored here */
int iDb; /* 0 for main database. 1 for TEMP, 2.. for ATTACHed */
int rc; /* Result code stored here */
+ u32 mInitFlags; /* Flags controlling error messages */
} InitData;
/*
+** Allowed values for mInitFlags
+*/
+#define INITFLAG_AlterTable 0x0001 /* This is a reparse after ALTER TABLE */
+
+/*
** Structure containing global configuration data for the SQLite library.
**
** This structure also contains some state information.
@@ -17889,7 +18123,7 @@ struct Sqlite3Config {
/* The following callback (if not NULL) is invoked on every VDBE branch
** operation. Set the callback using SQLITE_TESTCTRL_VDBE_COVERAGE.
*/
- void (*xVdbeBranch)(void*,int iSrcLine,u8 eThis,u8 eMx); /* Callback */
+ void (*xVdbeBranch)(void*,unsigned iSrcLine,u8 eThis,u8 eMx); /* Callback */
void *pVdbeBranchArg; /* 1st argument */
#endif
#ifndef SQLITE_UNTESTABLE
@@ -17940,6 +18174,9 @@ struct Walker {
struct IdxExprTrans *pIdxTrans; /* Convert idxed expr to column */
ExprList *pGroupBy; /* GROUP BY clause */
Select *pSelect; /* HAVING to WHERE clause ctx */
+ struct WindowRewrite *pRewrite; /* Window rewrite context */
+ struct WhereConst *pConst; /* WHERE clause constants */
+ struct RenameCtx *pRename; /* RENAME COLUMN context */
} u;
};
@@ -17991,6 +18228,68 @@ struct TreeView {
#endif /* SQLITE_DEBUG */
/*
+** This object is used in varioius ways, all related to window functions
+**
+** (1) A single instance of this structure is attached to the
+** the Expr.pWin field for each window function in an expression tree.
+** This object holds the information contained in the OVER clause,
+** plus additional fields used during code generation.
+**
+** (2) All window functions in a single SELECT form a linked-list
+** attached to Select.pWin. The Window.pFunc and Window.pExpr
+** fields point back to the expression that is the window function.
+**
+** (3) The terms of the WINDOW clause of a SELECT are instances of this
+** object on a linked list attached to Select.pWinDefn.
+**
+** The uses (1) and (2) are really the same Window object that just happens
+** to be accessible in two different ways. Use (3) is are separate objects.
+*/
+struct Window {
+ char *zName; /* Name of window (may be NULL) */
+ ExprList *pPartition; /* PARTITION BY clause */
+ ExprList *pOrderBy; /* ORDER BY clause */
+ u8 eType; /* TK_RANGE or TK_ROWS */
+ u8 eStart; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */
+ u8 eEnd; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */
+ Expr *pStart; /* Expression for "<expr> PRECEDING" */
+ Expr *pEnd; /* Expression for "<expr> FOLLOWING" */
+ Window *pNextWin; /* Next window function belonging to this SELECT */
+ Expr *pFilter; /* The FILTER expression */
+ FuncDef *pFunc; /* The function */
+ int iEphCsr; /* Partition buffer or Peer buffer */
+ int regAccum;
+ int regResult;
+ int csrApp; /* Function cursor (used by min/max) */
+ int regApp; /* Function register (also used by min/max) */
+ int regPart; /* First in a set of registers holding PARTITION BY
+ ** and ORDER BY values for the window */
+ Expr *pOwner; /* Expression object this window is attached to */
+ int nBufferCol; /* Number of columns in buffer table */
+ int iArgCol; /* Offset of first argument for this function */
+};
+
+#ifndef SQLITE_OMIT_WINDOWFUNC
+SQLITE_PRIVATE void sqlite3WindowDelete(sqlite3*, Window*);
+SQLITE_PRIVATE void sqlite3WindowListDelete(sqlite3 *db, Window *p);
+SQLITE_PRIVATE Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*);
+SQLITE_PRIVATE void sqlite3WindowAttach(Parse*, Expr*, Window*);
+SQLITE_PRIVATE int sqlite3WindowCompare(Parse*, Window*, Window*);
+SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse*, Window*);
+SQLITE_PRIVATE void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int);
+SQLITE_PRIVATE int sqlite3WindowRewrite(Parse*, Select*);
+SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse*, struct SrcList_item*);
+SQLITE_PRIVATE void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*);
+SQLITE_PRIVATE Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p);
+SQLITE_PRIVATE Window *sqlite3WindowListDup(sqlite3 *db, Window *p);
+SQLITE_PRIVATE void sqlite3WindowFunctions(void);
+#else
+# define sqlite3WindowDelete(a,b)
+# define sqlite3WindowFunctions()
+# define sqlite3WindowAttach(a,b,c)
+#endif
+
+/*
** Assuming zIn points to the first byte of a UTF-8 character,
** advance zIn to point to the first byte of the next UTF-8 character.
*/
@@ -18077,9 +18376,7 @@ SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno);
# define sqlite3Tolower(x) tolower((unsigned char)(x))
# define sqlite3Isquote(x) ((x)=='"'||(x)=='\''||(x)=='['||(x)=='`')
#endif
-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
SQLITE_PRIVATE int sqlite3IsIdChar(u8);
-#endif
/*
** Internal function prototypes
@@ -18204,6 +18501,10 @@ SQLITE_PRIVATE void sqlite3TreeViewBareExprList(TreeView*, const ExprList*, co
SQLITE_PRIVATE void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*);
SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView*, const Select*, u8);
SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView*, const With*, u8);
+#ifndef SQLITE_OMIT_WINDOWFUNC
+SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView*, const Window*, u8);
+SQLITE_PRIVATE void sqlite3TreeViewWinFunc(TreeView*, const Window*, u8);
+#endif
#endif
@@ -18228,7 +18529,7 @@ SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*);
SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*);
SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*);
SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*);
-SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*);
+SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int);
SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*);
SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
@@ -18240,6 +18541,7 @@ SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*);
SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*);
SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**);
SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**);
+SQLITE_PRIVATE int sqlite3InitOne(sqlite3*, int, char**, u32);
SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
#ifndef SQLITE_OMIT_VIRTUALTABLE
SQLITE_PRIVATE Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName);
@@ -18289,8 +18591,9 @@ SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec*);
SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int,int*);
#endif
-SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int);
-SQLITE_PRIVATE void sqlite3RowSetClear(RowSet*);
+SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3*);
+SQLITE_PRIVATE void sqlite3RowSetDelete(void*);
+SQLITE_PRIVATE void sqlite3RowSetClear(void*);
SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet*, i64);
SQLITE_PRIVATE int sqlite3RowSetTest(RowSet*, int iBatch, i64);
SQLITE_PRIVATE int sqlite3RowSetNext(RowSet*, i64*);
@@ -18309,6 +18612,7 @@ SQLITE_PRIVATE int sqlite3DbMaskAllZero(yDbMask);
SQLITE_PRIVATE void sqlite3DropTable(Parse*, SrcList*, int, int);
SQLITE_PRIVATE void sqlite3CodeDropTable(Parse*, Table*, int, int);
SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3*, Table*);
+SQLITE_PRIVATE void sqlite3FreeIndex(sqlite3*, Index*);
#ifndef SQLITE_OMIT_AUTOINCREMENT
SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse);
SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse);
@@ -18318,7 +18622,7 @@ SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse);
#endif
SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int, Upsert*);
SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
-SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*);
+SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse*, IdList*, Token*);
SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*);
SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(sqlite3*, SrcList*, int, int);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*);
@@ -18353,7 +18657,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
SQLITE_PRIVATE LogEst sqlite3WhereOutputRowCount(WhereInfo*);
SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo*);
SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo*);
-SQLITE_PRIVATE int sqlite3WhereOrderedInnerLoop(WhereInfo*);
+SQLITE_PRIVATE int sqlite3WhereOrderByLimitOptLabel(WhereInfo*);
SQLITE_PRIVATE int sqlite3WhereIsSorted(WhereInfo*);
SQLITE_PRIVATE int sqlite3WhereContinueLabel(WhereInfo*);
SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo*);
@@ -18363,15 +18667,8 @@ SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo*, int*);
#define ONEPASS_MULTI 2 /* ONEPASS is valid for multiple rows */
SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int);
SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
-SQLITE_PRIVATE void sqlite3ExprCodeGetColumnToReg(Parse*, Table*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
-SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse*, int, int, int);
-SQLITE_PRIVATE void sqlite3ExprCachePush(Parse*);
-SQLITE_PRIVATE void sqlite3ExprCachePop(Parse*);
-SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse*, int, int);
-SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse*);
-SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse*, int, int);
SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int);
SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, Expr*, int);
SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
@@ -18459,11 +18756,6 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*);
SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*,int);
-#if SELECTTRACE_ENABLED
-SQLITE_PRIVATE void sqlite3SelectSetName(Select*,const char*);
-#else
-# define sqlite3SelectSetName(A,B)
-#endif
SQLITE_PRIVATE void sqlite3InsertBuiltinFuncs(FuncDef*,int);
SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8);
SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void);
@@ -18492,12 +18784,12 @@ SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, i
SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*);
SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*,
const char*,const char*);
-SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*,
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(Parse*,Token*, IdList*,
Select*,u8,Upsert*,
const char*,const char*);
-SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8,
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(Parse*,Token*,ExprList*, Expr*, u8,
const char*,const char*);
-SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*,
+SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(Parse*,Token*, Expr*,
const char*,const char*);
SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*);
SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
@@ -18612,6 +18904,7 @@ SQLITE_PRIVATE int sqlite3MemdbInit(void);
SQLITE_PRIVATE const char *sqlite3ErrStr(int);
SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
+SQLITE_PRIVATE int sqlite3IsBinary(const CollSeq*);
SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr);
@@ -18664,9 +18957,10 @@ SQLITE_PRIVATE void sqlite3RootPageMoved(sqlite3*, int, int, int);
SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*);
SQLITE_PRIVATE void sqlite3AlterFunctions(void);
SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
+SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *);
SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
-SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*);
+SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, int);
SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr *, int, int);
SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
@@ -18679,6 +18973,10 @@ SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
+SQLITE_PRIVATE void *sqlite3RenameTokenMap(Parse*, void*, Token*);
+SQLITE_PRIVATE void sqlite3RenameTokenRemap(Parse*, void *pTo, void *pFrom);
+SQLITE_PRIVATE void sqlite3RenameExprUnmap(Parse*, Expr*);
+SQLITE_PRIVATE void sqlite3RenameExprlistUnmap(Parse*, ExprList*);
SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
SQLITE_PRIVATE char sqlite3AffinityType(const char*, Column*);
SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*);
@@ -18697,12 +18995,17 @@ SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int,int);
SQLITE_PRIVATE void sqlite3KeyInfoUnref(KeyInfo*);
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoRef(KeyInfo*);
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*);
+SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoFromExprList(Parse*, ExprList*, int, int);
+
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE int sqlite3KeyInfoIsWriteable(KeyInfo*);
#endif
SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
void (*)(sqlite3_context*,int,sqlite3_value **),
- void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*),
+ void (*)(sqlite3_context*,int,sqlite3_value **),
+ void (*)(sqlite3_context*),
+ void (*)(sqlite3_context*),
+ void (*)(sqlite3_context*,int,sqlite3_value **),
FuncDestructor *pDestructor
);
SQLITE_PRIVATE void sqlite3NoopDestructor(void*);
@@ -18743,6 +19046,7 @@ SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(u64), Parse*);
SQLITE_PRIVATE void sqlite3ParserFree(void*, void(*)(void*));
#endif
SQLITE_PRIVATE void sqlite3Parser(void*, int, Token);
+SQLITE_PRIVATE int sqlite3ParserFallback(int);
#ifdef YYTRACKMAXSTACKDEPTH
SQLITE_PRIVATE int sqlite3ParserStackPeak(void*);
#endif
@@ -19443,6 +19747,7 @@ struct VdbeCursor {
Bool isEphemeral:1; /* True for an ephemeral table */
Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */
Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */
+ Bool seekHit:1; /* See the OP_SeekHit and OP_IfNoHope opcodes */
Btree *pBtx; /* Separate file holding temporary table */
i64 seqCount; /* Sequence counter */
int *aAltMap; /* Mapping from table to index column numbers */
@@ -19526,6 +19831,9 @@ struct VdbeFrame {
void *token; /* Copy of SubProgram.token */
i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */
AuxData *pAuxData; /* Linked list of auxdata allocations */
+#if SQLITE_DEBUG
+ u32 iFrameMagic; /* magic number for sanity checking */
+#endif
int nCursor; /* Number of entries in apCsr */
int pc; /* Program Counter in parent (calling) frame */
int nOp; /* Size of aOp array */
@@ -19536,6 +19844,13 @@ struct VdbeFrame {
int nDbChange; /* Value of db->nChange */
};
+/* Magic number for sanity checking on VdbeFrame objects */
+#define SQLITE_FRAME_MAGIC 0x879fb71e
+
+/*
+** Return a pointer to the array of registers allocated for use
+** by a VdbeFrame.
+*/
#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])
/*
@@ -19550,8 +19865,6 @@ struct sqlite3_value {
int nZero; /* Extra zero bytes when MEM_Zero and MEM_Blob set */
const char *zPType; /* Pointer type when MEM_Term|MEM_Subtype|MEM_Null */
FuncDef *pDef; /* Used only when flags==MEM_Agg */
- RowSet *pRowSet; /* Used only when flags==MEM_RowSet */
- VdbeFrame *pFrame; /* Used when flags==MEM_Frame */
} u;
u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
@@ -19566,7 +19879,7 @@ struct sqlite3_value {
void (*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */
#ifdef SQLITE_DEBUG
Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */
- void *pFiller; /* So that sizeof(Mem) is a multiple of 8 */
+ u16 mScopyFlags; /* flags value immediately after the shallow copy */
#endif
};
@@ -19595,8 +19908,8 @@ struct sqlite3_value {
#define MEM_Real 0x0008 /* Value is a real number */
#define MEM_Blob 0x0010 /* Value is a BLOB */
#define MEM_AffMask 0x001f /* Mask of affinity bits */
-#define MEM_RowSet 0x0020 /* Value is a RowSet object */
-#define MEM_Frame 0x0040 /* Value is a VdbeFrame object */
+/* Available 0x0020 */
+/* Available 0x0040 */
#define MEM_Undefined 0x0080 /* Value is undefined */
#define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */
#define MEM_TypeMask 0xc1ff /* Mask of type bits */
@@ -19623,7 +19936,7 @@ struct sqlite3_value {
** that needs to be deallocated to avoid a leak.
*/
#define VdbeMemDynamic(X) \
- (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0)
+ (((X)->flags&(MEM_Agg|MEM_Dyn))!=0)
/*
** Clear any existing type flags from a Mem and replace them with f
@@ -19743,9 +20056,9 @@ struct Vdbe {
u8 errorAction; /* Recovery action to do in case of an error */
u8 minWriteFileFormat; /* Minimum file format for writable database files */
u8 prepFlags; /* SQLITE_PREPARE_* flags */
- bft expired:1; /* True if the VM needs to be recompiled */
- bft doingRerun:1; /* True if rerunning after an auto-reprepare */
+ bft expired:2; /* 1: recompile VM immediately 2: when convenient */
bft explain:2; /* True if EXPLAIN present on SQL command */
+ bft doingRerun:1; /* True if rerunning after an auto-reprepare */
bft changeCntOn:1; /* True to update the change-counter */
bft runOnlyOnce:1; /* Automatically expire on reset */
bft usesStmtJournal:1; /* True if uses a statement journal */
@@ -19806,9 +20119,6 @@ SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*);
void sqliteVdbePopStack(Vdbe*,int);
SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor**, int*);
SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor*);
-#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
-SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, Op*);
-#endif
SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32);
SQLITE_PRIVATE u8 sqlite3VdbeOneByteSerialTypeLen(u8);
SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int, u32*);
@@ -19839,7 +20149,10 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetPointer(Mem*, void*, const char*, void(*)(v
SQLITE_PRIVATE void sqlite3VdbeMemInit(Mem*,sqlite3*,u16);
SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*);
SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int);
-SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem*);
+#ifdef SQLITE_DEBUG
+SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem*);
+#endif
+SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8);
SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*);
@@ -19853,11 +20166,18 @@ SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem*,u8,u8);
SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*);
SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
+#ifndef SQLITE_OMIT_WINDOWFUNC
+SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*);
+#endif
SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int n);
SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
-SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*);
+#ifdef SQLITE_DEBUG
+SQLITE_PRIVATE int sqlite3VdbeFrameIsValid(VdbeFrame*);
+#endif
+SQLITE_PRIVATE void sqlite3VdbeFrameMemDel(void*); /* Destructor on Mem */
+SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*); /* Actually deletes the Frame */
SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int);
@@ -21955,9 +22275,12 @@ SQLITE_API int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){
** Unregister a VFS so that it is no longer accessible.
*/
SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
-#if SQLITE_THREADSAFE
- sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+ MUTEX_LOGIC(sqlite3_mutex *mutex;)
+#ifndef SQLITE_OMIT_AUTOINIT
+ int rc = sqlite3_initialize();
+ if( rc ) return rc;
#endif
+ MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
sqlite3_mutex_enter(mutex);
vfsUnlink(pVfs);
sqlite3_mutex_leave(mutex);
@@ -27288,7 +27611,12 @@ SQLITE_API void sqlite3_str_vappendf(
if( bufpt==0 ){
bufpt = "";
}else if( xtype==etDYNSTRING ){
- if( pAccum->nChar==0 && pAccum->mxAlloc && width==0 && precision<0 ){
+ if( pAccum->nChar==0
+ && pAccum->mxAlloc
+ && width==0
+ && precision<0
+ && pAccum->accError==0
+ ){
/* Special optimization for sqlite3_mprintf("%z..."):
** Extend an existing memory allocation rather than creating
** a new one. */
@@ -27986,21 +28314,13 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
sqlite3TreeViewPush(pView, 1);
}
do{
-#if SELECTTRACE_ENABLED
sqlite3TreeViewLine(pView,
- "SELECT%s%s (%s/%p) selFlags=0x%x nSelectRow=%d",
+ "SELECT%s%s (%u/%p) selFlags=0x%x nSelectRow=%d",
((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
((p->selFlags & SF_Aggregate) ? " agg_flag" : ""),
- p->zSelName, p, p->selFlags,
+ p->selId, p, p->selFlags,
(int)p->nSelectRow
);
-#else
- sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x nSelectRow=%d",
- ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
- ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p, p->selFlags,
- (int)p->nSelectRow
- );
-#endif
if( cnt++ ) sqlite3TreeViewPop(pView);
if( p->pPrior ){
n = 1000;
@@ -28012,8 +28332,23 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
if( p->pHaving ) n++;
if( p->pOrderBy ) n++;
if( p->pLimit ) n++;
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( p->pWin ) n++;
+ if( p->pWinDefn ) n++;
+#endif
}
sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set");
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( p->pWin ){
+ Window *pX;
+ pView = sqlite3TreeViewPush(pView, (n--)>0);
+ sqlite3TreeViewLine(pView, "window-functions");
+ for(pX=p->pWin; pX; pX=pX->pNextWin){
+ sqlite3TreeViewWinFunc(pView, pX, pX->pNextWin!=0);
+ }
+ sqlite3TreeViewPop(pView);
+ }
+#endif
if( p->pSrc && p->pSrc->nSrc ){
int i;
pView = sqlite3TreeViewPush(pView, (n--)>0);
@@ -28063,6 +28398,16 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
sqlite3TreeViewExpr(pView, p->pHaving, 0);
sqlite3TreeViewPop(pView);
}
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( p->pWinDefn ){
+ Window *pX;
+ sqlite3TreeViewItem(pView, "WINDOW", (n--)>0);
+ for(pX=p->pWinDefn; pX; pX=pX->pNextWin){
+ sqlite3TreeViewWindow(pView, pX, pX->pNextWin!=0);
+ }
+ sqlite3TreeViewPop(pView);
+ }
+#endif
if( p->pOrderBy ){
sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY");
}
@@ -28090,6 +28435,83 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
sqlite3TreeViewPop(pView);
}
+#ifndef SQLITE_OMIT_WINDOWFUNC
+/*
+** Generate a description of starting or stopping bounds
+*/
+SQLITE_PRIVATE void sqlite3TreeViewBound(
+ TreeView *pView, /* View context */
+ u8 eBound, /* UNBOUNDED, CURRENT, PRECEDING, FOLLOWING */
+ Expr *pExpr, /* Value for PRECEDING or FOLLOWING */
+ u8 moreToFollow /* True if more to follow */
+){
+ switch( eBound ){
+ case TK_UNBOUNDED: {
+ sqlite3TreeViewItem(pView, "UNBOUNDED", moreToFollow);
+ sqlite3TreeViewPop(pView);
+ break;
+ }
+ case TK_CURRENT: {
+ sqlite3TreeViewItem(pView, "CURRENT", moreToFollow);
+ sqlite3TreeViewPop(pView);
+ break;
+ }
+ case TK_PRECEDING: {
+ sqlite3TreeViewItem(pView, "PRECEDING", moreToFollow);
+ sqlite3TreeViewExpr(pView, pExpr, 0);
+ sqlite3TreeViewPop(pView);
+ break;
+ }
+ case TK_FOLLOWING: {
+ sqlite3TreeViewItem(pView, "FOLLOWING", moreToFollow);
+ sqlite3TreeViewExpr(pView, pExpr, 0);
+ sqlite3TreeViewPop(pView);
+ break;
+ }
+ }
+}
+#endif /* SQLITE_OMIT_WINDOWFUNC */
+
+#ifndef SQLITE_OMIT_WINDOWFUNC
+/*
+** Generate a human-readable explanation for a Window object
+*/
+SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u8 more){
+ pView = sqlite3TreeViewPush(pView, more);
+ if( pWin->zName ){
+ sqlite3TreeViewLine(pView, "OVER %s", pWin->zName);
+ }else{
+ sqlite3TreeViewLine(pView, "OVER");
+ }
+ if( pWin->pPartition ){
+ sqlite3TreeViewExprList(pView, pWin->pPartition, 1, "PARTITION-BY");
+ }
+ if( pWin->pOrderBy ){
+ sqlite3TreeViewExprList(pView, pWin->pOrderBy, 1, "ORDER-BY");
+ }
+ if( pWin->eType ){
+ sqlite3TreeViewItem(pView, pWin->eType==TK_RANGE ? "RANGE" : "ROWS", 0);
+ sqlite3TreeViewBound(pView, pWin->eStart, pWin->pStart, 1);
+ sqlite3TreeViewBound(pView, pWin->eEnd, pWin->pEnd, 0);
+ sqlite3TreeViewPop(pView);
+ }
+ sqlite3TreeViewPop(pView);
+}
+#endif /* SQLITE_OMIT_WINDOWFUNC */
+
+#ifndef SQLITE_OMIT_WINDOWFUNC
+/*
+** Generate a human-readable explanation for a Window Function object
+*/
+SQLITE_PRIVATE void sqlite3TreeViewWinFunc(TreeView *pView, const Window *pWin, u8 more){
+ pView = sqlite3TreeViewPush(pView, more);
+ sqlite3TreeViewLine(pView, "WINFUNC %s(%d)",
+ pWin->pFunc->zName, pWin->pFunc->nArg);
+ sqlite3TreeViewWindow(pView, pWin, 0);
+ sqlite3TreeViewPop(pView);
+}
+#endif /* SQLITE_OMIT_WINDOWFUNC */
+
/*
** Generate a human-readable explanation of an expression tree.
*/
@@ -28127,6 +28549,9 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
sqlite3TreeViewLine(pView, "{%d:%d}%s",
pExpr->iTable, pExpr->iColumn, zFlgs);
}
+ if( ExprHasProperty(pExpr, EP_FixedCol) ){
+ sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
+ }
break;
}
case TK_INTEGER: {
@@ -28240,10 +28665,17 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
case TK_AGG_FUNCTION:
case TK_FUNCTION: {
ExprList *pFarg; /* List of function arguments */
+ Window *pWin;
if( ExprHasProperty(pExpr, EP_TokenOnly) ){
pFarg = 0;
+ pWin = 0;
}else{
pFarg = pExpr->x.pList;
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ pWin = pExpr->pWin;
+#else
+ pWin = 0;
+#endif
}
if( pExpr->op==TK_AGG_FUNCTION ){
sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q",
@@ -28252,8 +28684,13 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken);
}
if( pFarg ){
- sqlite3TreeViewExprList(pView, pFarg, 0, 0);
+ sqlite3TreeViewExprList(pView, pFarg, pWin!=0, 0);
}
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( pWin ){
+ sqlite3TreeViewWindow(pView, pWin, 0);
+ }
+#endif
break;
}
#ifndef SQLITE_OMIT_SUBQUERY
@@ -31285,52 +31722,52 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 1 */ "AutoCommit" OpHelp(""),
/* 2 */ "Transaction" OpHelp(""),
/* 3 */ "SorterNext" OpHelp(""),
- /* 4 */ "PrevIfOpen" OpHelp(""),
- /* 5 */ "NextIfOpen" OpHelp(""),
- /* 6 */ "Prev" OpHelp(""),
- /* 7 */ "Next" OpHelp(""),
- /* 8 */ "Checkpoint" OpHelp(""),
- /* 9 */ "JournalMode" OpHelp(""),
- /* 10 */ "Vacuum" OpHelp(""),
- /* 11 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"),
- /* 12 */ "VUpdate" OpHelp("data=r[P3@P2]"),
- /* 13 */ "Goto" OpHelp(""),
- /* 14 */ "Gosub" OpHelp(""),
- /* 15 */ "InitCoroutine" OpHelp(""),
- /* 16 */ "Yield" OpHelp(""),
- /* 17 */ "MustBeInt" OpHelp(""),
- /* 18 */ "Jump" OpHelp(""),
+ /* 4 */ "Prev" OpHelp(""),
+ /* 5 */ "Next" OpHelp(""),
+ /* 6 */ "Checkpoint" OpHelp(""),
+ /* 7 */ "JournalMode" OpHelp(""),
+ /* 8 */ "Vacuum" OpHelp(""),
+ /* 9 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"),
+ /* 10 */ "VUpdate" OpHelp("data=r[P3@P2]"),
+ /* 11 */ "Goto" OpHelp(""),
+ /* 12 */ "Gosub" OpHelp(""),
+ /* 13 */ "InitCoroutine" OpHelp(""),
+ /* 14 */ "Yield" OpHelp(""),
+ /* 15 */ "MustBeInt" OpHelp(""),
+ /* 16 */ "Jump" OpHelp(""),
+ /* 17 */ "Once" OpHelp(""),
+ /* 18 */ "If" OpHelp(""),
/* 19 */ "Not" OpHelp("r[P2]= !r[P1]"),
- /* 20 */ "Once" OpHelp(""),
- /* 21 */ "If" OpHelp(""),
- /* 22 */ "IfNot" OpHelp(""),
- /* 23 */ "IfNullRow" OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"),
- /* 24 */ "SeekLT" OpHelp("key=r[P3@P4]"),
- /* 25 */ "SeekLE" OpHelp("key=r[P3@P4]"),
- /* 26 */ "SeekGE" OpHelp("key=r[P3@P4]"),
- /* 27 */ "SeekGT" OpHelp("key=r[P3@P4]"),
- /* 28 */ "NoConflict" OpHelp("key=r[P3@P4]"),
- /* 29 */ "NotFound" OpHelp("key=r[P3@P4]"),
- /* 30 */ "Found" OpHelp("key=r[P3@P4]"),
- /* 31 */ "SeekRowid" OpHelp("intkey=r[P3]"),
- /* 32 */ "NotExists" OpHelp("intkey=r[P3]"),
- /* 33 */ "Last" OpHelp(""),
- /* 34 */ "IfSmaller" OpHelp(""),
- /* 35 */ "SorterSort" OpHelp(""),
- /* 36 */ "Sort" OpHelp(""),
- /* 37 */ "Rewind" OpHelp(""),
- /* 38 */ "IdxLE" OpHelp("key=r[P3@P4]"),
- /* 39 */ "IdxGT" OpHelp("key=r[P3@P4]"),
- /* 40 */ "IdxLT" OpHelp("key=r[P3@P4]"),
- /* 41 */ "IdxGE" OpHelp("key=r[P3@P4]"),
- /* 42 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
+ /* 20 */ "IfNot" OpHelp(""),
+ /* 21 */ "IfNullRow" OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"),
+ /* 22 */ "SeekLT" OpHelp("key=r[P3@P4]"),
+ /* 23 */ "SeekLE" OpHelp("key=r[P3@P4]"),
+ /* 24 */ "SeekGE" OpHelp("key=r[P3@P4]"),
+ /* 25 */ "SeekGT" OpHelp("key=r[P3@P4]"),
+ /* 26 */ "IfNoHope" OpHelp("key=r[P3@P4]"),
+ /* 27 */ "NoConflict" OpHelp("key=r[P3@P4]"),
+ /* 28 */ "NotFound" OpHelp("key=r[P3@P4]"),
+ /* 29 */ "Found" OpHelp("key=r[P3@P4]"),
+ /* 30 */ "SeekRowid" OpHelp("intkey=r[P3]"),
+ /* 31 */ "NotExists" OpHelp("intkey=r[P3]"),
+ /* 32 */ "Last" OpHelp(""),
+ /* 33 */ "IfSmaller" OpHelp(""),
+ /* 34 */ "SorterSort" OpHelp(""),
+ /* 35 */ "Sort" OpHelp(""),
+ /* 36 */ "Rewind" OpHelp(""),
+ /* 37 */ "IdxLE" OpHelp("key=r[P3@P4]"),
+ /* 38 */ "IdxGT" OpHelp("key=r[P3@P4]"),
+ /* 39 */ "IdxLT" OpHelp("key=r[P3@P4]"),
+ /* 40 */ "IdxGE" OpHelp("key=r[P3@P4]"),
+ /* 41 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
+ /* 42 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
/* 43 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"),
/* 44 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"),
- /* 45 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
- /* 46 */ "Program" OpHelp(""),
- /* 47 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
- /* 48 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
- /* 49 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
+ /* 45 */ "Program" OpHelp(""),
+ /* 46 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
+ /* 47 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
+ /* 48 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
+ /* 49 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
/* 50 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
/* 51 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
/* 52 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
@@ -31340,119 +31777,121 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 56 */ "Lt" OpHelp("IF r[P3]<r[P1]"),
/* 57 */ "Ge" OpHelp("IF r[P3]>=r[P1]"),
/* 58 */ "ElseNotEq" OpHelp(""),
- /* 59 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
- /* 60 */ "IncrVacuum" OpHelp(""),
- /* 61 */ "VNext" OpHelp(""),
- /* 62 */ "Init" OpHelp("Start at P2"),
- /* 63 */ "Return" OpHelp(""),
- /* 64 */ "EndCoroutine" OpHelp(""),
- /* 65 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
- /* 66 */ "Halt" OpHelp(""),
- /* 67 */ "Integer" OpHelp("r[P2]=P1"),
- /* 68 */ "Int64" OpHelp("r[P2]=P4"),
- /* 69 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
- /* 70 */ "Null" OpHelp("r[P2..P3]=NULL"),
- /* 71 */ "SoftNull" OpHelp("r[P1]=NULL"),
- /* 72 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
- /* 73 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"),
- /* 74 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
- /* 75 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
- /* 76 */ "SCopy" OpHelp("r[P2]=r[P1]"),
- /* 77 */ "IntCopy" OpHelp("r[P2]=r[P1]"),
- /* 78 */ "ResultRow" OpHelp("output=r[P1@P2]"),
- /* 79 */ "CollSeq" OpHelp(""),
- /* 80 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
- /* 81 */ "RealAffinity" OpHelp(""),
- /* 82 */ "Cast" OpHelp("affinity(r[P1])"),
- /* 83 */ "Permutation" OpHelp(""),
- /* 84 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
- /* 85 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
- /* 86 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
- /* 87 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
- /* 88 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
- /* 89 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
- /* 90 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
- /* 91 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
- /* 92 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
- /* 93 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
- /* 94 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
- /* 95 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"),
- /* 96 */ "BitNot" OpHelp("r[P1]= ~r[P1]"),
- /* 97 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
- /* 98 */ "Column" OpHelp("r[P3]=PX"),
- /* 99 */ "String8" OpHelp("r[P2]='P4'"),
- /* 100 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
- /* 101 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
- /* 102 */ "Count" OpHelp("r[P2]=count()"),
- /* 103 */ "ReadCookie" OpHelp(""),
- /* 104 */ "SetCookie" OpHelp(""),
- /* 105 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
- /* 106 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
- /* 107 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
- /* 108 */ "OpenDup" OpHelp(""),
- /* 109 */ "OpenAutoindex" OpHelp("nColumn=P2"),
- /* 110 */ "OpenEphemeral" OpHelp("nColumn=P2"),
- /* 111 */ "SorterOpen" OpHelp(""),
- /* 112 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
- /* 113 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
- /* 114 */ "Close" OpHelp(""),
- /* 115 */ "ColumnsUsed" OpHelp(""),
- /* 116 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
- /* 117 */ "NewRowid" OpHelp("r[P2]=rowid"),
- /* 118 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
- /* 119 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"),
- /* 120 */ "Delete" OpHelp(""),
- /* 121 */ "ResetCount" OpHelp(""),
- /* 122 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
- /* 123 */ "SorterData" OpHelp("r[P2]=data"),
- /* 124 */ "RowData" OpHelp("r[P2]=data"),
- /* 125 */ "Rowid" OpHelp("r[P2]=rowid"),
- /* 126 */ "NullRow" OpHelp(""),
- /* 127 */ "SeekEnd" OpHelp(""),
- /* 128 */ "SorterInsert" OpHelp("key=r[P2]"),
- /* 129 */ "IdxInsert" OpHelp("key=r[P2]"),
- /* 130 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
- /* 131 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
- /* 132 */ "IdxRowid" OpHelp("r[P2]=rowid"),
- /* 133 */ "Destroy" OpHelp(""),
- /* 134 */ "Real" OpHelp("r[P2]=P4"),
- /* 135 */ "Clear" OpHelp(""),
- /* 136 */ "ResetSorter" OpHelp(""),
- /* 137 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
- /* 138 */ "SqlExec" OpHelp(""),
- /* 139 */ "ParseSchema" OpHelp(""),
- /* 140 */ "LoadAnalysis" OpHelp(""),
- /* 141 */ "DropTable" OpHelp(""),
- /* 142 */ "DropIndex" OpHelp(""),
- /* 143 */ "DropTrigger" OpHelp(""),
- /* 144 */ "IntegrityCk" OpHelp(""),
- /* 145 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
- /* 146 */ "Param" OpHelp(""),
- /* 147 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
- /* 148 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
- /* 149 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
- /* 150 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"),
- /* 151 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
- /* 152 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
- /* 153 */ "Expire" OpHelp(""),
- /* 154 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
- /* 155 */ "VBegin" OpHelp(""),
- /* 156 */ "VCreate" OpHelp(""),
- /* 157 */ "VDestroy" OpHelp(""),
- /* 158 */ "VOpen" OpHelp(""),
- /* 159 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
- /* 160 */ "VRename" OpHelp(""),
- /* 161 */ "Pagecount" OpHelp(""),
- /* 162 */ "MaxPgcnt" OpHelp(""),
- /* 163 */ "PureFunc0" OpHelp(""),
- /* 164 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"),
- /* 165 */ "PureFunc" OpHelp(""),
- /* 166 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"),
- /* 167 */ "Trace" OpHelp(""),
- /* 168 */ "CursorHint" OpHelp(""),
- /* 169 */ "Noop" OpHelp(""),
- /* 170 */ "Explain" OpHelp(""),
- /* 171 */ "Abortable" OpHelp(""),
+ /* 59 */ "IncrVacuum" OpHelp(""),
+ /* 60 */ "VNext" OpHelp(""),
+ /* 61 */ "Init" OpHelp("Start at P2"),
+ /* 62 */ "PureFunc0" OpHelp(""),
+ /* 63 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"),
+ /* 64 */ "PureFunc" OpHelp(""),
+ /* 65 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"),
+ /* 66 */ "Return" OpHelp(""),
+ /* 67 */ "EndCoroutine" OpHelp(""),
+ /* 68 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
+ /* 69 */ "Halt" OpHelp(""),
+ /* 70 */ "Integer" OpHelp("r[P2]=P1"),
+ /* 71 */ "Int64" OpHelp("r[P2]=P4"),
+ /* 72 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
+ /* 73 */ "Null" OpHelp("r[P2..P3]=NULL"),
+ /* 74 */ "SoftNull" OpHelp("r[P1]=NULL"),
+ /* 75 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
+ /* 76 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"),
+ /* 77 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
+ /* 78 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
+ /* 79 */ "SCopy" OpHelp("r[P2]=r[P1]"),
+ /* 80 */ "IntCopy" OpHelp("r[P2]=r[P1]"),
+ /* 81 */ "ResultRow" OpHelp("output=r[P1@P2]"),
+ /* 82 */ "CollSeq" OpHelp(""),
+ /* 83 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
+ /* 84 */ "RealAffinity" OpHelp(""),
+ /* 85 */ "Cast" OpHelp("affinity(r[P1])"),
+ /* 86 */ "Permutation" OpHelp(""),
+ /* 87 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
+ /* 88 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"),
+ /* 89 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
+ /* 90 */ "Column" OpHelp("r[P3]=PX"),
+ /* 91 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
+ /* 92 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
+ /* 93 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
+ /* 94 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
+ /* 95 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
+ /* 96 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
+ /* 97 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
+ /* 98 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
+ /* 99 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
+ /* 100 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
+ /* 101 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
+ /* 102 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
+ /* 103 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
+ /* 104 */ "Count" OpHelp("r[P2]=count()"),
+ /* 105 */ "ReadCookie" OpHelp(""),
+ /* 106 */ "String8" OpHelp("r[P2]='P4'"),
+ /* 107 */ "SetCookie" OpHelp(""),
+ /* 108 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
+ /* 109 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
+ /* 110 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
+ /* 111 */ "OpenDup" OpHelp(""),
+ /* 112 */ "OpenAutoindex" OpHelp("nColumn=P2"),
+ /* 113 */ "OpenEphemeral" OpHelp("nColumn=P2"),
+ /* 114 */ "SorterOpen" OpHelp(""),
+ /* 115 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
+ /* 116 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
+ /* 117 */ "Close" OpHelp(""),
+ /* 118 */ "ColumnsUsed" OpHelp(""),
+ /* 119 */ "SeekHit" OpHelp("seekHit=P2"),
+ /* 120 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
+ /* 121 */ "NewRowid" OpHelp("r[P2]=rowid"),
+ /* 122 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
+ /* 123 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"),
+ /* 124 */ "Delete" OpHelp(""),
+ /* 125 */ "ResetCount" OpHelp(""),
+ /* 126 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
+ /* 127 */ "SorterData" OpHelp("r[P2]=data"),
+ /* 128 */ "RowData" OpHelp("r[P2]=data"),
+ /* 129 */ "Rowid" OpHelp("r[P2]=rowid"),
+ /* 130 */ "NullRow" OpHelp(""),
+ /* 131 */ "SeekEnd" OpHelp(""),
+ /* 132 */ "SorterInsert" OpHelp("key=r[P2]"),
+ /* 133 */ "IdxInsert" OpHelp("key=r[P2]"),
+ /* 134 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
+ /* 135 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
+ /* 136 */ "IdxRowid" OpHelp("r[P2]=rowid"),
+ /* 137 */ "Destroy" OpHelp(""),
+ /* 138 */ "Clear" OpHelp(""),
+ /* 139 */ "ResetSorter" OpHelp(""),
+ /* 140 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
+ /* 141 */ "Real" OpHelp("r[P2]=P4"),
+ /* 142 */ "SqlExec" OpHelp(""),
+ /* 143 */ "ParseSchema" OpHelp(""),
+ /* 144 */ "LoadAnalysis" OpHelp(""),
+ /* 145 */ "DropTable" OpHelp(""),
+ /* 146 */ "DropIndex" OpHelp(""),
+ /* 147 */ "DropTrigger" OpHelp(""),
+ /* 148 */ "IntegrityCk" OpHelp(""),
+ /* 149 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
+ /* 150 */ "Param" OpHelp(""),
+ /* 151 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
+ /* 152 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
+ /* 153 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
+ /* 154 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"),
+ /* 155 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
+ /* 156 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"),
+ /* 157 */ "AggValue" OpHelp("r[P3]=value N=P2"),
+ /* 158 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
+ /* 159 */ "Expire" OpHelp(""),
+ /* 160 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
+ /* 161 */ "VBegin" OpHelp(""),
+ /* 162 */ "VCreate" OpHelp(""),
+ /* 163 */ "VDestroy" OpHelp(""),
+ /* 164 */ "VOpen" OpHelp(""),
+ /* 165 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
+ /* 166 */ "VRename" OpHelp(""),
+ /* 167 */ "Pagecount" OpHelp(""),
+ /* 168 */ "MaxPgcnt" OpHelp(""),
+ /* 169 */ "Trace" OpHelp(""),
+ /* 170 */ "CursorHint" OpHelp(""),
+ /* 171 */ "Noop" OpHelp(""),
+ /* 172 */ "Explain" OpHelp(""),
+ /* 173 */ "Abortable" OpHelp(""),
};
return azName[i];
}
@@ -32181,7 +32620,11 @@ static struct unix_syscall {
#define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent)
#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
+# ifdef __ANDROID__
+ { "ioctl", (sqlite3_syscall_ptr)(int(*)(int, int, ...))ioctl, 0 },
+# else
{ "ioctl", (sqlite3_syscall_ptr)ioctl, 0 },
+# endif
#else
{ "ioctl", (sqlite3_syscall_ptr)0, 0 },
#endif
@@ -32362,12 +32805,25 @@ static int robust_open(const char *z, int f, mode_t m){
** unixEnterMutex()
** assert( unixMutexHeld() );
** unixEnterLeave()
+**
+** To prevent deadlock, the global unixBigLock must must be acquired
+** before the unixInodeInfo.pLockMutex mutex, if both are held. It is
+** OK to get the pLockMutex without holding unixBigLock first, but if
+** that happens, the unixBigLock mutex must not be acquired until after
+** pLockMutex is released.
+**
+** OK: enter(unixBigLock), enter(pLockInfo)
+** OK: enter(unixBigLock)
+** OK: enter(pLockInfo)
+** ERROR: enter(pLockInfo), enter(unixBigLock)
*/
static sqlite3_mutex *unixBigLock = 0;
static void unixEnterMutex(void){
+ assert( sqlite3_mutex_notheld(unixBigLock) ); /* Not a recursive mutex */
sqlite3_mutex_enter(unixBigLock);
}
static void unixLeaveMutex(void){
+ assert( sqlite3_mutex_held(unixBigLock) );
sqlite3_mutex_leave(unixBigLock);
}
#ifdef SQLITE_DEBUG
@@ -32768,16 +33224,34 @@ struct unixFileId {
** A single inode can have multiple file descriptors, so each unixFile
** structure contains a pointer to an instance of this object and this
** object keeps a count of the number of unixFile pointing to it.
+**
+** Mutex rules:
+**
+** (1) Only the pLockMutex mutex must be held in order to read or write
+** any of the locking fields:
+** nShared, nLock, eFileLock, bProcessLock, pUnused
+**
+** (2) When nRef>0, then the following fields are unchanging and can
+** be read (but not written) without holding any mutex:
+** fileId, pLockMutex
+**
+** (3) With the exceptions above, all the fields may only be read
+** or written while holding the global unixBigLock mutex.
+**
+** Deadlock prevention: The global unixBigLock mutex may not
+** be acquired while holding the pLockMutex mutex. If both unixBigLock
+** and pLockMutex are needed, then unixBigLock must be acquired first.
*/
struct unixInodeInfo {
struct unixFileId fileId; /* The lookup key */
- int nShared; /* Number of SHARED locks held */
- unsigned char eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */
- unsigned char bProcessLock; /* An exclusive process lock is held */
+ sqlite3_mutex *pLockMutex; /* Hold this mutex for... */
+ int nShared; /* Number of SHARED locks held */
+ int nLock; /* Number of outstanding file locks */
+ unsigned char eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */
+ unsigned char bProcessLock; /* An exclusive process lock is held */
+ UnixUnusedFd *pUnused; /* Unused file descriptors to close */
int nRef; /* Number of pointers to this structure */
unixShmNode *pShmNode; /* Shared memory associated with this inode */
- int nLock; /* Number of outstanding file locks */
- UnixUnusedFd *pUnused; /* Unused file descriptors to close */
unixInodeInfo *pNext; /* List of all unixInodeInfo objects */
unixInodeInfo *pPrev; /* .... doubly linked */
#if SQLITE_ENABLE_LOCKING_STYLE
@@ -32793,7 +33267,21 @@ struct unixInodeInfo {
** A lists of all unixInodeInfo objects.
*/
static unixInodeInfo *inodeList = 0; /* All unixInodeInfo objects */
-static unsigned int nUnusedFd = 0; /* Total unused file descriptors */
+
+#ifdef SQLITE_DEBUG
+/*
+** True if the inode mutex is held, or not. Used only within assert()
+** to help verify correct mutex usage.
+*/
+int unixFileMutexHeld(unixFile *pFile){
+ assert( pFile->pInode );
+ return sqlite3_mutex_held(pFile->pInode->pLockMutex);
+}
+int unixFileMutexNotheld(unixFile *pFile){
+ assert( pFile->pInode );
+ return sqlite3_mutex_notheld(pFile->pInode->pLockMutex);
+}
+#endif
/*
**
@@ -32899,11 +33387,11 @@ static void closePendingFds(unixFile *pFile){
unixInodeInfo *pInode = pFile->pInode;
UnixUnusedFd *p;
UnixUnusedFd *pNext;
+ assert( unixFileMutexHeld(pFile) );
for(p=pInode->pUnused; p; p=pNext){
pNext = p->pNext;
robust_close(pFile, p->fd, __LINE__);
sqlite3_free(p);
- nUnusedFd--;
}
pInode->pUnused = 0;
}
@@ -32917,11 +33405,14 @@ static void closePendingFds(unixFile *pFile){
static void releaseInodeInfo(unixFile *pFile){
unixInodeInfo *pInode = pFile->pInode;
assert( unixMutexHeld() );
+ assert( unixFileMutexNotheld(pFile) );
if( ALWAYS(pInode) ){
pInode->nRef--;
if( pInode->nRef==0 ){
assert( pInode->pShmNode==0 );
+ sqlite3_mutex_enter(pInode->pLockMutex);
closePendingFds(pFile);
+ sqlite3_mutex_leave(pInode->pLockMutex);
if( pInode->pPrev ){
assert( pInode->pPrev->pNext==pInode );
pInode->pPrev->pNext = pInode->pNext;
@@ -32933,10 +33424,10 @@ static void releaseInodeInfo(unixFile *pFile){
assert( pInode->pNext->pPrev==pInode );
pInode->pNext->pPrev = pInode->pPrev;
}
+ sqlite3_mutex_free(pInode->pLockMutex);
sqlite3_free(pInode);
}
}
- assert( inodeList!=0 || nUnusedFd==0 );
}
/*
@@ -33006,7 +33497,6 @@ static int findInodeInfo(
#else
fileId.ino = (u64)statbuf.st_ino;
#endif
- assert( inodeList!=0 || nUnusedFd==0 );
pInode = inodeList;
while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){
pInode = pInode->pNext;
@@ -33018,6 +33508,13 @@ static int findInodeInfo(
}
memset(pInode, 0, sizeof(*pInode));
memcpy(&pInode->fileId, &fileId, sizeof(fileId));
+ if( sqlite3GlobalConfig.bCoreMutex ){
+ pInode->pLockMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
+ if( pInode->pLockMutex==0 ){
+ sqlite3_free(pInode);
+ return SQLITE_NOMEM_BKPT;
+ }
+ }
pInode->nRef = 1;
pInode->pNext = inodeList;
pInode->pPrev = 0;
@@ -33096,7 +33593,7 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
assert( pFile );
assert( pFile->eFileLock<=SHARED_LOCK );
- unixEnterMutex(); /* Because pFile->pInode is shared across threads */
+ sqlite3_mutex_enter(pFile->pInode->pLockMutex);
/* Check if a thread in this process holds such a lock */
if( pFile->pInode->eFileLock>SHARED_LOCK ){
@@ -33121,7 +33618,7 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
}
#endif
- unixLeaveMutex();
+ sqlite3_mutex_leave(pFile->pInode->pLockMutex);
OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved));
*pResOut = reserved;
@@ -33187,8 +33684,8 @@ static int osSetPosixAdvisoryLock(
static int unixFileLock(unixFile *pFile, struct flock *pLock){
int rc;
unixInodeInfo *pInode = pFile->pInode;
- assert( unixMutexHeld() );
assert( pInode!=0 );
+ assert( sqlite3_mutex_held(pInode->pLockMutex) );
if( (pFile->ctrlFlags & (UNIXFILE_EXCL|UNIXFILE_RDONLY))==UNIXFILE_EXCL ){
if( pInode->bProcessLock==0 ){
struct flock lock;
@@ -33307,8 +33804,8 @@ static int unixLock(sqlite3_file *id, int eFileLock){
/* This mutex is needed because pFile->pInode is shared across threads
*/
- unixEnterMutex();
pInode = pFile->pInode;
+ sqlite3_mutex_enter(pInode->pLockMutex);
/* If some thread using this PID has a lock via a different unixFile*
** handle that precludes the requested lock, return BUSY.
@@ -33451,7 +33948,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
}
end_lock:
- unixLeaveMutex();
+ sqlite3_mutex_leave(pInode->pLockMutex);
OSTRACE(("LOCK %d %s %s (unix)\n", pFile->h, azFileLock(eFileLock),
rc==SQLITE_OK ? "ok" : "failed"));
return rc;
@@ -33464,11 +33961,11 @@ end_lock:
static void setPendingFd(unixFile *pFile){
unixInodeInfo *pInode = pFile->pInode;
UnixUnusedFd *p = pFile->pPreallocatedUnused;
+ assert( unixFileMutexHeld(pFile) );
p->pNext = pInode->pUnused;
pInode->pUnused = p;
pFile->h = -1;
pFile->pPreallocatedUnused = 0;
- nUnusedFd++;
}
/*
@@ -33499,8 +33996,8 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
if( pFile->eFileLock<=eFileLock ){
return SQLITE_OK;
}
- unixEnterMutex();
pInode = pFile->pInode;
+ sqlite3_mutex_enter(pInode->pLockMutex);
assert( pInode->nShared!=0 );
if( pFile->eFileLock>SHARED_LOCK ){
assert( pInode->eFileLock==pFile->eFileLock );
@@ -33626,14 +34123,14 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
*/
pInode->nLock--;
assert( pInode->nLock>=0 );
- if( pInode->nLock==0 ){
- closePendingFds(pFile);
- }
+ if( pInode->nLock==0 ) closePendingFds(pFile);
}
end_unlock:
- unixLeaveMutex();
- if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
+ sqlite3_mutex_leave(pInode->pLockMutex);
+ if( rc==SQLITE_OK ){
+ pFile->eFileLock = eFileLock;
+ }
return rc;
}
@@ -33704,15 +34201,20 @@ static int closeUnixFile(sqlite3_file *id){
static int unixClose(sqlite3_file *id){
int rc = SQLITE_OK;
unixFile *pFile = (unixFile *)id;
+ unixInodeInfo *pInode = pFile->pInode;
+
+ assert( pInode!=0 );
verifyDbFile(pFile);
unixUnlock(id, NO_LOCK);
+ assert( unixFileMutexNotheld(pFile) );
unixEnterMutex();
/* unixFile.pInode is always valid here. Otherwise, a different close
** routine (e.g. nolockClose()) would be called instead.
*/
assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 );
- if( ALWAYS(pFile->pInode) && pFile->pInode->nLock ){
+ sqlite3_mutex_enter(pInode->pLockMutex);
+ if( pInode->nLock ){
/* If there are outstanding locks, do not actually close the file just
** yet because that would clear those locks. Instead, add the file
** descriptor to pInode->pUnused list. It will be automatically closed
@@ -33720,6 +34222,7 @@ static int unixClose(sqlite3_file *id){
*/
setPendingFd(pFile);
}
+ sqlite3_mutex_leave(pInode->pLockMutex);
releaseInodeInfo(pFile);
rc = closeUnixFile(id);
unixLeaveMutex();
@@ -34317,6 +34820,7 @@ static int semXClose(sqlite3_file *id) {
unixFile *pFile = (unixFile*)id;
semXUnlock(id, NO_LOCK);
assert( pFile );
+ assert( unixFileMutexNotheld(pFile) );
unixEnterMutex();
releaseInodeInfo(pFile);
unixLeaveMutex();
@@ -34431,8 +34935,7 @@ static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
*pResOut = 1;
return SQLITE_OK;
}
- unixEnterMutex(); /* Because pFile->pInode is shared across threads */
-
+ sqlite3_mutex_enter(pFile->pInode->pLockMutex);
/* Check if a thread in this process holds such a lock */
if( pFile->pInode->eFileLock>SHARED_LOCK ){
reserved = 1;
@@ -34456,7 +34959,7 @@ static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
}
}
- unixLeaveMutex();
+ sqlite3_mutex_leave(pFile->pInode->pLockMutex);
OSTRACE(("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved));
*pResOut = reserved;
@@ -34519,8 +35022,8 @@ static int afpLock(sqlite3_file *id, int eFileLock){
/* This mutex is needed because pFile->pInode is shared across threads
*/
- unixEnterMutex();
pInode = pFile->pInode;
+ sqlite3_mutex_enter(pInode->pLockMutex);
/* If some thread using this PID has a lock via a different unixFile*
** handle that precludes the requested lock, return BUSY.
@@ -34656,7 +35159,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){
}
afp_end_lock:
- unixLeaveMutex();
+ sqlite3_mutex_leave(pInode->pLockMutex);
OSTRACE(("LOCK %d %s %s (afp)\n", pFile->h, azFileLock(eFileLock),
rc==SQLITE_OK ? "ok" : "failed"));
return rc;
@@ -34688,8 +35191,8 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) {
if( pFile->eFileLock<=eFileLock ){
return SQLITE_OK;
}
- unixEnterMutex();
pInode = pFile->pInode;
+ sqlite3_mutex_enter(pInode->pLockMutex);
assert( pInode->nShared!=0 );
if( pFile->eFileLock>SHARED_LOCK ){
assert( pInode->eFileLock==pFile->eFileLock );
@@ -34758,14 +35261,14 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) {
if( rc==SQLITE_OK ){
pInode->nLock--;
assert( pInode->nLock>=0 );
- if( pInode->nLock==0 ){
- closePendingFds(pFile);
- }
+ if( pInode->nLock==0 ) closePendingFds(pFile);
}
}
- unixLeaveMutex();
- if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
+ sqlite3_mutex_leave(pInode->pLockMutex);
+ if( rc==SQLITE_OK ){
+ pFile->eFileLock = eFileLock;
+ }
return rc;
}
@@ -34777,14 +35280,20 @@ static int afpClose(sqlite3_file *id) {
unixFile *pFile = (unixFile*)id;
assert( id!=0 );
afpUnlock(id, NO_LOCK);
+ assert( unixFileMutexNotheld(pFile) );
unixEnterMutex();
- if( pFile->pInode && pFile->pInode->nLock ){
- /* If there are outstanding locks, do not actually close the file just
- ** yet because that would clear those locks. Instead, add the file
- ** descriptor to pInode->aPending. It will be automatically closed when
- ** the last lock is cleared.
- */
- setPendingFd(pFile);
+ if( pFile->pInode ){
+ unixInodeInfo *pInode = pFile->pInode;
+ sqlite3_mutex_enter(pInode->pLockMutex);
+ if( pInode->nLock ){
+ /* If there are outstanding locks, do not actually close the file just
+ ** yet because that would clear those locks. Instead, add the file
+ ** descriptor to pInode->aPending. It will be automatically closed when
+ ** the last lock is cleared.
+ */
+ setPendingFd(pFile);
+ }
+ sqlite3_mutex_leave(pInode->pLockMutex);
}
releaseInodeInfo(pFile);
sqlite3_free(pFile->lockingContext);
@@ -36090,6 +36599,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
/* Check to see if a unixShmNode object already exists. Reuse an existing
** one if present. Create a new one if necessary.
*/
+ assert( unixFileMutexNotheld(pDbFd) );
unixEnterMutex();
pInode = pDbFd->pInode;
pShmNode = pInode->pShmNode;
@@ -36472,6 +36982,9 @@ static void unixShmBarrier(
){
UNUSED_PARAMETER(fd);
sqlite3MemoryBarrier(); /* compiler-defined memory barrier */
+ assert( fd->pMethods->xLock==nolockLock
+ || unixFileMutexNotheld((unixFile*)fd)
+ );
unixEnterMutex(); /* Also mutex, for redundancy */
unixLeaveMutex();
}
@@ -36513,6 +37026,7 @@ static int unixShmUnmap(
/* If pShmNode->nRef has reached 0, then close the underlying
** shared-memory file, too */
+ assert( unixFileMutexNotheld(pDbFd) );
unixEnterMutex();
assert( pShmNode->nRef>0 );
pShmNode->nRef--;
@@ -36839,7 +37353,7 @@ IOMETHODS(
IOMETHODS(
nolockIoFinder, /* Finder function name */
nolockIoMethods, /* sqlite3_io_methods object name */
- 3, /* shared memory is disabled */
+ 3, /* shared memory and mmap are enabled */
nolockClose, /* xClose method */
nolockLock, /* xLock method */
nolockUnlock, /* xUnlock method */
@@ -37335,7 +37849,7 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
**
** Even if a subsequent open() call does succeed, the consequences of
** not searching for a reusable file descriptor are not dire. */
- if( nUnusedFd>0 && 0==osStat(zPath, &sStat) ){
+ if( inodeList!=0 && 0==osStat(zPath, &sStat) ){
unixInodeInfo *pInode;
pInode = inodeList;
@@ -37345,12 +37859,14 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
}
if( pInode ){
UnixUnusedFd **pp;
+ assert( sqlite3_mutex_notheld(pInode->pLockMutex) );
+ sqlite3_mutex_enter(pInode->pLockMutex);
for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
pUnused = *pp;
if( pUnused ){
- nUnusedFd--;
*pp = pUnused->pNext;
}
+ sqlite3_mutex_leave(pInode->pLockMutex);
}
}
unixLeaveMutex();
@@ -42553,6 +43069,9 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
winFile *pFile = (winFile*)id; /* File handle object */
int rc = SQLITE_OK; /* Return code for this function */
DWORD lastErrno;
+#if SQLITE_MAX_MMAP_SIZE>0
+ sqlite3_int64 oldMmapSize;
+#endif
assert( pFile );
SimulateIOError(return SQLITE_IOERR_TRUNCATE);
@@ -42568,6 +43087,15 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
}
+#if SQLITE_MAX_MMAP_SIZE>0
+ if( pFile->pMapRegion ){
+ oldMmapSize = pFile->mmapSize;
+ }else{
+ oldMmapSize = 0;
+ }
+ winUnmapfile(pFile);
+#endif
+
/* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
if( winSeekFile(pFile, nByte) ){
rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
@@ -42580,12 +43108,12 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
}
#if SQLITE_MAX_MMAP_SIZE>0
- /* If the file was truncated to a size smaller than the currently
- ** mapped region, reduce the effective mapping size as well. SQLite will
- ** use read() and write() to access data beyond this point from now on.
- */
- if( pFile->pMapRegion && nByte<pFile->mmapSize ){
- pFile->mmapSize = nByte;
+ if( rc==SQLITE_OK && oldMmapSize>0 ){
+ if( oldMmapSize>nByte ){
+ winMapfile(pFile, -1);
+ }else{
+ winMapfile(pFile, oldMmapSize);
+ }
}
#endif
@@ -45773,8 +46301,8 @@ SQLITE_API int sqlite3_os_end(void){
** This file also implements interface sqlite3_serialize() and
** sqlite3_deserialize().
*/
-#ifdef SQLITE_ENABLE_DESERIALIZE
/* #include "sqliteInt.h" */
+#ifdef SQLITE_ENABLE_DESERIALIZE
/*
** Forward declaration of objects used by this utility
@@ -49022,30 +49550,23 @@ struct RowSet {
#define ROWSET_NEXT 0x02 /* True if sqlite3RowSetNext() has been called */
/*
-** Turn bulk memory into a RowSet object. N bytes of memory
-** are available at pSpace. The db pointer is used as a memory context
-** for any subsequent allocations that need to occur.
-** Return a pointer to the new RowSet object.
-**
-** It must be the case that N is sufficient to make a Rowset. If not
-** an assertion fault occurs.
-**
-** If N is larger than the minimum, use the surplus as an initial
-** allocation of entries available to be filled.
+** Allocate a RowSet object. Return NULL if a memory allocation
+** error occurs.
*/
-SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3 *db, void *pSpace, unsigned int N){
- RowSet *p;
- assert( N >= ROUND8(sizeof(*p)) );
- p = pSpace;
- p->pChunk = 0;
- p->db = db;
- p->pEntry = 0;
- p->pLast = 0;
- p->pForest = 0;
- p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p);
- p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry));
- p->rsFlags = ROWSET_SORTED;
- p->iBatch = 0;
+SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3 *db){
+ RowSet *p = sqlite3DbMallocRawNN(db, sizeof(*p));
+ if( p ){
+ int N = sqlite3DbMallocSize(db, p);
+ p->pChunk = 0;
+ p->db = db;
+ p->pEntry = 0;
+ p->pLast = 0;
+ p->pForest = 0;
+ p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p);
+ p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry));
+ p->rsFlags = ROWSET_SORTED;
+ p->iBatch = 0;
+ }
return p;
}
@@ -49054,7 +49575,8 @@ SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3 *db, void *pSpace, unsigned int
** the RowSet has allocated over its lifetime. This routine is
** the destructor for the RowSet.
*/
-SQLITE_PRIVATE void sqlite3RowSetClear(RowSet *p){
+SQLITE_PRIVATE void sqlite3RowSetClear(void *pArg){
+ RowSet *p = (RowSet*)pArg;
struct RowSetChunk *pChunk, *pNextChunk;
for(pChunk=p->pChunk; pChunk; pChunk = pNextChunk){
pNextChunk = pChunk->pNextChunk;
@@ -49069,6 +49591,16 @@ SQLITE_PRIVATE void sqlite3RowSetClear(RowSet *p){
}
/*
+** Deallocate all chunks from a RowSet. This frees all memory that
+** the RowSet has allocated over its lifetime. This routine is
+** the destructor for the RowSet.
+*/
+SQLITE_PRIVATE void sqlite3RowSetDelete(void *pArg){
+ sqlite3RowSetClear(pArg);
+ sqlite3DbFree(((RowSet*)pArg)->db, pArg);
+}
+
+/*
** Allocate a new RowSetEntry object that is associated with the
** given RowSet. Return a pointer to the new and completely uninitialized
** objected.
@@ -49555,6 +50087,8 @@ SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal);
SQLITE_PRIVATE int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot);
SQLITE_PRIVATE void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot);
SQLITE_PRIVATE int sqlite3WalSnapshotRecover(Wal *pWal);
+SQLITE_PRIVATE int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot);
+SQLITE_PRIVATE void sqlite3WalSnapshotUnlock(Wal *pWal);
#endif
#ifdef SQLITE_ENABLE_ZIPVFS
@@ -50548,8 +51082,12 @@ static int assert_pager_state(Pager *p){
** to "print *pPager" in gdb:
**
** (gdb) printf "%s", print_pager_state(pPager)
+**
+** This routine has external linkage in order to suppress compiler warnings
+** about an unused function. It is enclosed within SQLITE_DEBUG and so does
+** not appear in normal builds.
*/
-static char *print_pager_state(Pager *p){
+char *print_pager_state(Pager *p){
static char zRet[1024];
sqlite3_snprintf(1024, zRet,
@@ -51315,7 +51853,6 @@ static void pager_reset(Pager *pPager){
** Return the pPager->iDataVersion value
*/
SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager *pPager){
- assert( pPager->eState>PAGER_OPEN );
return pPager->iDataVersion;
}
@@ -55933,9 +56470,10 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
** backup in progress needs to be restarted. */
sqlite3BackupRestart(pPager->pBackup);
}else{
+ PgHdr *pList;
if( pagerUseWal(pPager) ){
- PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache);
PgHdr *pPageOne = 0;
+ pList = sqlite3PcacheDirtyList(pPager->pPCache);
if( pList==0 ){
/* Must have at least one page for the WAL commit flag.
** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */
@@ -55956,14 +56494,14 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
** should be used. No rollback journal is created if batch-atomic-write
** is enabled.
*/
- sqlite3_file *fd = pPager->fd;
#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
- const int bBatch = zMaster==0 /* An SQLITE_IOCAP_BATCH_ATOMIC commit */
+ sqlite3_file *fd = pPager->fd;
+ int bBatch = zMaster==0 /* An SQLITE_IOCAP_BATCH_ATOMIC commit */
&& (sqlite3OsDeviceCharacteristics(fd) & SQLITE_IOCAP_BATCH_ATOMIC)
&& !pPager->noSync
&& sqlite3JournalIsInMemory(pPager->jfd);
#else
-# define bBatch 0
+# define bBatch 0
#endif
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
@@ -56015,15 +56553,16 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
}
}
}
-#else
+#else /* SQLITE_ENABLE_ATOMIC_WRITE */
#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
if( zMaster ){
rc = sqlite3JournalCreate(pPager->jfd);
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
+ assert( bBatch==0 );
}
#endif
rc = pager_incr_changecounter(pPager, 0);
-#endif
+#endif /* !SQLITE_ENABLE_ATOMIC_WRITE */
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
/* Write the master journal name into the journal file. If a master
@@ -56047,24 +56586,36 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
rc = syncJournal(pPager, 0);
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
+ pList = sqlite3PcacheDirtyList(pPager->pPCache);
+#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
if( bBatch ){
- /* The pager is now in DBMOD state. But regardless of what happens
- ** next, attempting to play the journal back into the database would
- ** be unsafe. Close it now to make sure that does not happen. */
- sqlite3OsClose(pPager->jfd);
rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_BEGIN_ATOMIC_WRITE, 0);
- if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
- }
- rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache));
- if( bBatch ){
if( rc==SQLITE_OK ){
- rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_COMMIT_ATOMIC_WRITE, 0);
+ rc = pager_write_pagelist(pPager, pList);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_COMMIT_ATOMIC_WRITE, 0);
+ }
+ if( rc!=SQLITE_OK ){
+ sqlite3OsFileControlHint(fd, SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE, 0);
+ }
}
- if( rc!=SQLITE_OK ){
- sqlite3OsFileControlHint(fd, SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE, 0);
+
+ if( (rc&0xFF)==SQLITE_IOERR && rc!=SQLITE_IOERR_NOMEM ){
+ rc = sqlite3JournalCreate(pPager->jfd);
+ if( rc!=SQLITE_OK ){
+ sqlite3OsClose(pPager->jfd);
+ goto commit_phase_one_exit;
+ }
+ bBatch = 0;
+ }else{
+ sqlite3OsClose(pPager->jfd);
}
}
+#endif /* SQLITE_ENABLE_BATCH_ATOMIC_WRITE */
+ if( bBatch==0 ){
+ rc = pager_write_pagelist(pPager, pList);
+ }
if( rc!=SQLITE_OK ){
assert( rc!=SQLITE_IOERR_BLOCKED );
goto commit_phase_one_exit;
@@ -56816,13 +57367,6 @@ SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *pPager, int eMode){
SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
u8 eOld = pPager->journalMode; /* Prior journalmode */
-#ifdef SQLITE_DEBUG
- /* The print_pager_state() routine is intended to be used by the debugger
- ** only. We invoke it once here to suppress a compiler warning. */
- print_pager_state(pPager);
-#endif
-
-
/* The eMode parameter is always valid */
assert( eMode==PAGER_JOURNALMODE_DELETE
|| eMode==PAGER_JOURNALMODE_TRUNCATE
@@ -57191,6 +57735,38 @@ SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager){
}
return rc;
}
+
+/*
+** The caller currently has a read transaction open on the database.
+** If this is not a WAL database, SQLITE_ERROR is returned. Otherwise,
+** this function takes a SHARED lock on the CHECKPOINTER slot and then
+** checks if the snapshot passed as the second argument is still
+** available. If so, SQLITE_OK is returned.
+**
+** If the snapshot is not available, SQLITE_ERROR is returned. Or, if
+** the CHECKPOINTER lock cannot be obtained, SQLITE_BUSY. If any error
+** occurs (any value other than SQLITE_OK is returned), the CHECKPOINTER
+** lock is released before returning.
+*/
+SQLITE_PRIVATE int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot){
+ int rc;
+ if( pPager->pWal ){
+ rc = sqlite3WalSnapshotCheck(pPager->pWal, pSnapshot);
+ }else{
+ rc = SQLITE_ERROR;
+ }
+ return rc;
+}
+
+/*
+** Release a lock obtained by an earlier successful call to
+** sqlite3PagerSnapshotCheck().
+*/
+SQLITE_PRIVATE void sqlite3PagerSnapshotUnlock(Pager *pPager){
+ assert( pPager->pWal );
+ return sqlite3WalSnapshotUnlock(pPager->pWal);
+}
+
#endif /* SQLITE_ENABLE_SNAPSHOT */
#endif /* !SQLITE_OMIT_WAL */
@@ -57473,6 +58049,18 @@ SQLITE_PRIVATE int sqlite3WalTrace = 0;
#endif
/*
+** WAL mode depends on atomic aligned 32-bit loads and stores in a few
+** places. The following macros try to make this explicit.
+*/
+#if GCC_VESRION>=5004000
+# define AtomicLoad(PTR) __atomic_load_n((PTR),__ATOMIC_RELAXED)
+# define AtomicStore(PTR,VAL) __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED)
+#else
+# define AtomicLoad(PTR) (*(PTR))
+# define AtomicStore(PTR,VAL) (*(PTR) = (VAL))
+#endif
+
+/*
** The maximum (and only) versions of the wal and wal-index formats
** that may be interpreted by this version of SQLite.
**
@@ -58094,48 +58682,51 @@ static int walNextHash(int iPriorHash){
return (iPriorHash+1)&(HASHTABLE_NSLOT-1);
}
+/*
+** An instance of the WalHashLoc object is used to describe the location
+** of a page hash table in the wal-index. This becomes the return value
+** from walHashGet().
+*/
+typedef struct WalHashLoc WalHashLoc;
+struct WalHashLoc {
+ volatile ht_slot *aHash; /* Start of the wal-index hash table */
+ volatile u32 *aPgno; /* aPgno[1] is the page of first frame indexed */
+ u32 iZero; /* One less than the frame number of first indexed*/
+};
+
/*
** Return pointers to the hash table and page number array stored on
** page iHash of the wal-index. The wal-index is broken into 32KB pages
** numbered starting from 0.
**
-** Set output variable *paHash to point to the start of the hash table
-** in the wal-index file. Set *piZero to one less than the frame
+** Set output variable pLoc->aHash to point to the start of the hash table
+** in the wal-index file. Set pLoc->iZero to one less than the frame
** number of the first frame indexed by this hash table. If a
** slot in the hash table is set to N, it refers to frame number
-** (*piZero+N) in the log.
+** (pLoc->iZero+N) in the log.
**
-** Finally, set *paPgno so that *paPgno[1] is the page number of the
-** first frame indexed by the hash table, frame (*piZero+1).
+** Finally, set pLoc->aPgno so that pLoc->aPgno[1] is the page number of the
+** first frame indexed by the hash table, frame (pLoc->iZero+1).
*/
static int walHashGet(
Wal *pWal, /* WAL handle */
int iHash, /* Find the iHash'th table */
- volatile ht_slot **paHash, /* OUT: Pointer to hash index */
- volatile u32 **paPgno, /* OUT: Pointer to page number array */
- u32 *piZero /* OUT: Frame associated with *paPgno[0] */
+ WalHashLoc *pLoc /* OUT: Hash table location */
){
int rc; /* Return code */
- volatile u32 *aPgno;
- rc = walIndexPage(pWal, iHash, &aPgno);
+ rc = walIndexPage(pWal, iHash, &pLoc->aPgno);
assert( rc==SQLITE_OK || iHash>0 );
if( rc==SQLITE_OK ){
- u32 iZero;
- volatile ht_slot *aHash;
-
- aHash = (volatile ht_slot *)&aPgno[HASHTABLE_NPAGE];
+ pLoc->aHash = (volatile ht_slot *)&pLoc->aPgno[HASHTABLE_NPAGE];
if( iHash==0 ){
- aPgno = &aPgno[WALINDEX_HDR_SIZE/sizeof(u32)];
- iZero = 0;
+ pLoc->aPgno = &pLoc->aPgno[WALINDEX_HDR_SIZE/sizeof(u32)];
+ pLoc->iZero = 0;
}else{
- iZero = HASHTABLE_NPAGE_ONE + (iHash-1)*HASHTABLE_NPAGE;
+ pLoc->iZero = HASHTABLE_NPAGE_ONE + (iHash-1)*HASHTABLE_NPAGE;
}
-
- *paPgno = &aPgno[-1];
- *paHash = aHash;
- *piZero = iZero;
+ pLoc->aPgno = &pLoc->aPgno[-1];
}
return rc;
}
@@ -58181,9 +58772,7 @@ static u32 walFramePgno(Wal *pWal, u32 iFrame){
** actually needed.
*/
static void walCleanupHash(Wal *pWal){
- volatile ht_slot *aHash = 0; /* Pointer to hash table to clear */
- volatile u32 *aPgno = 0; /* Page number array for hash table */
- u32 iZero = 0; /* frame == (aHash[x]+iZero) */
+ WalHashLoc sLoc; /* Hash table location */
int iLimit = 0; /* Zero values greater than this */
int nByte; /* Number of bytes to zero in aPgno[] */
int i; /* Used to iterate through aHash[] */
@@ -58201,24 +58790,24 @@ static void walCleanupHash(Wal *pWal){
*/
assert( pWal->nWiData>walFramePage(pWal->hdr.mxFrame) );
assert( pWal->apWiData[walFramePage(pWal->hdr.mxFrame)] );
- walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &aHash, &aPgno, &iZero);
+ walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &sLoc);
/* Zero all hash-table entries that correspond to frame numbers greater
** than pWal->hdr.mxFrame.
*/
- iLimit = pWal->hdr.mxFrame - iZero;
+ iLimit = pWal->hdr.mxFrame - sLoc.iZero;
assert( iLimit>0 );
for(i=0; i<HASHTABLE_NSLOT; i++){
- if( aHash[i]>iLimit ){
- aHash[i] = 0;
+ if( sLoc.aHash[i]>iLimit ){
+ sLoc.aHash[i] = 0;
}
}
/* Zero the entries in the aPgno array that correspond to frames with
** frame numbers greater than pWal->hdr.mxFrame.
*/
- nByte = (int)((char *)aHash - (char *)&aPgno[iLimit+1]);
- memset((void *)&aPgno[iLimit+1], 0, nByte);
+ nByte = (int)((char *)sLoc.aHash - (char *)&sLoc.aPgno[iLimit+1]);
+ memset((void *)&sLoc.aPgno[iLimit+1], 0, nByte);
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
/* Verify that the every entry in the mapping region is still reachable
@@ -58228,10 +58817,10 @@ static void walCleanupHash(Wal *pWal){
int j; /* Loop counter */
int iKey; /* Hash key */
for(j=1; j<=iLimit; j++){
- for(iKey=walHash(aPgno[j]); aHash[iKey]; iKey=walNextHash(iKey)){
- if( aHash[iKey]==j ) break;
+ for(iKey=walHash(sLoc.aPgno[j]);sLoc.aHash[iKey];iKey=walNextHash(iKey)){
+ if( sLoc.aHash[iKey]==j ) break;
}
- assert( aHash[iKey]==j );
+ assert( sLoc.aHash[iKey]==j );
}
}
#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */
@@ -58244,11 +58833,9 @@ static void walCleanupHash(Wal *pWal){
*/
static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
int rc; /* Return code */
- u32 iZero = 0; /* One less than frame number of aPgno[1] */
- volatile u32 *aPgno = 0; /* Page number array */
- volatile ht_slot *aHash = 0; /* Hash table */
+ WalHashLoc sLoc; /* Wal-index hash table location */
- rc = walHashGet(pWal, walFramePage(iFrame), &aHash, &aPgno, &iZero);
+ rc = walHashGet(pWal, walFramePage(iFrame), &sLoc);
/* Assuming the wal-index file was successfully mapped, populate the
** page number array and hash table entry.
@@ -58258,15 +58845,16 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
int idx; /* Value to write to hash-table slot */
int nCollide; /* Number of hash collisions */
- idx = iFrame - iZero;
+ idx = iFrame - sLoc.iZero;
assert( idx <= HASHTABLE_NSLOT/2 + 1 );
/* If this is the first entry to be added to this hash-table, zero the
** entire hash table and aPgno[] array before proceeding.
*/
if( idx==1 ){
- int nByte = (int)((u8 *)&aHash[HASHTABLE_NSLOT] - (u8 *)&aPgno[1]);
- memset((void*)&aPgno[1], 0, nByte);
+ int nByte = (int)((u8 *)&sLoc.aHash[HASHTABLE_NSLOT]
+ - (u8 *)&sLoc.aPgno[1]);
+ memset((void*)&sLoc.aPgno[1], 0, nByte);
}
/* If the entry in aPgno[] is already set, then the previous writer
@@ -58275,18 +58863,18 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
** Remove the remnants of that writers uncommitted transaction from
** the hash-table before writing any new entries.
*/
- if( aPgno[idx] ){
+ if( sLoc.aPgno[idx] ){
walCleanupHash(pWal);
- assert( !aPgno[idx] );
+ assert( !sLoc.aPgno[idx] );
}
/* Write the aPgno[] array entry and the hash-table slot. */
nCollide = idx;
- for(iKey=walHash(iPage); aHash[iKey]; iKey=walNextHash(iKey)){
+ for(iKey=walHash(iPage); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){
if( (nCollide--)==0 ) return SQLITE_CORRUPT_BKPT;
}
- aPgno[idx] = iPage;
- aHash[iKey] = (ht_slot)idx;
+ sLoc.aPgno[idx] = iPage;
+ sLoc.aHash[iKey] = (ht_slot)idx;
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
/* Verify that the number of entries in the hash table exactly equals
@@ -58295,7 +58883,7 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
{
int i; /* Loop counter */
int nEntry = 0; /* Number of entries in the hash table */
- for(i=0; i<HASHTABLE_NSLOT; i++){ if( aHash[i] ) nEntry++; }
+ for(i=0; i<HASHTABLE_NSLOT; i++){ if( sLoc.aHash[i] ) nEntry++; }
assert( nEntry==idx );
}
@@ -58307,10 +58895,12 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
if( (idx&0x3ff)==0 ){
int i; /* Loop counter */
for(i=1; i<=idx; i++){
- for(iKey=walHash(aPgno[i]); aHash[iKey]; iKey=walNextHash(iKey)){
- if( aHash[iKey]==i ) break;
+ for(iKey=walHash(sLoc.aPgno[i]);
+ sLoc.aHash[iKey];
+ iKey=walNextHash(iKey)){
+ if( sLoc.aHash[iKey]==i ) break;
}
- assert( aHash[iKey]==i );
+ assert( sLoc.aHash[iKey]==i );
}
}
#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */
@@ -58848,33 +59438,31 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
}
for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && i<nSegment; i++){
- volatile ht_slot *aHash;
- u32 iZero;
- volatile u32 *aPgno;
+ WalHashLoc sLoc;
- rc = walHashGet(pWal, i, &aHash, &aPgno, &iZero);
+ rc = walHashGet(pWal, i, &sLoc);
if( rc==SQLITE_OK ){
int j; /* Counter variable */
int nEntry; /* Number of entries in this segment */
ht_slot *aIndex; /* Sorted index for this segment */
- aPgno++;
+ sLoc.aPgno++;
if( (i+1)==nSegment ){
- nEntry = (int)(iLast - iZero);
+ nEntry = (int)(iLast - sLoc.iZero);
}else{
- nEntry = (int)((u32*)aHash - (u32*)aPgno);
+ nEntry = (int)((u32*)sLoc.aHash - (u32*)sLoc.aPgno);
}
- aIndex = &((ht_slot *)&p->aSegment[p->nSegment])[iZero];
- iZero++;
+ aIndex = &((ht_slot *)&p->aSegment[p->nSegment])[sLoc.iZero];
+ sLoc.iZero++;
for(j=0; j<nEntry; j++){
aIndex[j] = (ht_slot)j;
}
- walMergesort((u32 *)aPgno, aTmp, aIndex, &nEntry);
- p->aSegment[i].iZero = iZero;
+ walMergesort((u32 *)sLoc.aPgno, aTmp, aIndex, &nEntry);
+ p->aSegment[i].iZero = sLoc.iZero;
p->aSegment[i].nEntry = nEntry;
p->aSegment[i].aIndex = aIndex;
- p->aSegment[i].aPgno = (u32 *)aPgno;
+ p->aSegment[i].aPgno = (u32 *)sLoc.aPgno;
}
}
sqlite3_free(aTmp);
@@ -59049,7 +59637,6 @@ static int walCheckpoint(
if( pIter
&& (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0),1))==SQLITE_OK
){
- i64 nSize; /* Current size of database file */
u32 nBackfill = pInfo->nBackfill;
pInfo->nBackfillAttempted = mxSafeFrame;
@@ -59062,6 +59649,7 @@ static int walCheckpoint(
*/
if( rc==SQLITE_OK ){
i64 nReq = ((i64)mxPage * szPage);
+ i64 nSize; /* Current size of database file */
rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
if( rc==SQLITE_OK && nSize<nReq ){
sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq);
@@ -59769,7 +60357,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
}
#endif
for(i=1; i<WAL_NREADER; i++){
- u32 thisMark = pInfo->aReadMark[i];
+ u32 thisMark = AtomicLoad(pInfo->aReadMark+i);
if( mxReadMark<=thisMark && thisMark<=mxFrame ){
assert( thisMark!=READMARK_NOT_USED );
mxReadMark = thisMark;
@@ -59782,7 +60370,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
for(i=1; i<WAL_NREADER; i++){
rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
if( rc==SQLITE_OK ){
- mxReadMark = pInfo->aReadMark[i] = mxFrame;
+ mxReadMark = AtomicStore(pInfo->aReadMark+i,mxFrame);
mxI = i;
walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
break;
@@ -59834,9 +60422,9 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
** we can guarantee that the checkpointer that set nBackfill could not
** see any pages past pWal->hdr.mxFrame, this problem does not come up.
*/
- pWal->minFrame = pInfo->nBackfill+1;
+ pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1;
walShmBarrier(pWal);
- if( pInfo->aReadMark[mxI]!=mxReadMark
+ if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark
|| memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr))
){
walUnlockShared(pWal, WAL_READ_LOCK(mxI));
@@ -59887,16 +60475,14 @@ SQLITE_PRIVATE int sqlite3WalSnapshotRecover(Wal *pWal){
}else{
u32 i = pInfo->nBackfillAttempted;
for(i=pInfo->nBackfillAttempted; i>pInfo->nBackfill; i--){
- volatile ht_slot *dummy;
- volatile u32 *aPgno; /* Array of page numbers */
- u32 iZero; /* Frame corresponding to aPgno[0] */
+ WalHashLoc sLoc; /* Hash table location */
u32 pgno; /* Page number in db file */
i64 iDbOff; /* Offset of db file entry */
i64 iWalOff; /* Offset of wal file entry */
- rc = walHashGet(pWal, walFramePage(i), &dummy, &aPgno, &iZero);
+ rc = walHashGet(pWal, walFramePage(i), &sLoc);
if( rc!=SQLITE_OK ) break;
- pgno = aPgno[i-iZero];
+ pgno = sLoc.aPgno[i-sLoc.iZero];
iDbOff = (i64)(pgno-1) * szPage;
if( iDbOff+szPage<=szDb ){
@@ -59937,7 +60523,7 @@ SQLITE_PRIVATE int sqlite3WalSnapshotRecover(Wal *pWal){
**
** If the database contents have changes since the previous read
** transaction, then *pChanged is set to 1 before returning. The
-** Pager layer will use this to know that is cache is stale and
+** Pager layer will use this to know that its cache is stale and
** needs to be flushed.
*/
SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
@@ -59999,7 +60585,7 @@ SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
/* Check that the wal file has not been wrapped. Assuming that it has
** not, also check that no checkpointer has attempted to checkpoint any
** frames beyond pSnapshot->mxFrame. If either of these conditions are
- ** true, return SQLITE_BUSY_SNAPSHOT. Otherwise, overwrite pWal->hdr
+ ** true, return SQLITE_ERROR_SNAPSHOT. Otherwise, overwrite pWal->hdr
** with *pSnapshot and set *pChanged as appropriate for opening the
** snapshot. */
if( !memcmp(pSnapshot->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt))
@@ -60009,11 +60595,12 @@ SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
memcpy(&pWal->hdr, pSnapshot, sizeof(WalIndexHdr));
*pChanged = bChanged;
}else{
- rc = SQLITE_BUSY_SNAPSHOT;
+ rc = SQLITE_ERROR_SNAPSHOT;
}
/* Release the shared CKPT lock obtained above. */
walUnlockShared(pWal, WAL_CKPT_LOCK);
+ pWal->minFrame = 1;
}
@@ -60097,21 +60684,20 @@ SQLITE_PRIVATE int sqlite3WalFindFrame(
*/
iMinHash = walFramePage(pWal->minFrame);
for(iHash=walFramePage(iLast); iHash>=iMinHash; iHash--){
- volatile ht_slot *aHash; /* Pointer to hash table */
- volatile u32 *aPgno; /* Pointer to array of page numbers */
- u32 iZero; /* Frame number corresponding to aPgno[0] */
+ WalHashLoc sLoc; /* Hash table location */
int iKey; /* Hash slot index */
int nCollide; /* Number of hash collisions remaining */
int rc; /* Error code */
- rc = walHashGet(pWal, iHash, &aHash, &aPgno, &iZero);
+ rc = walHashGet(pWal, iHash, &sLoc);
if( rc!=SQLITE_OK ){
return rc;
}
nCollide = HASHTABLE_NSLOT;
- for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){
- u32 iFrame = aHash[iKey] + iZero;
- if( iFrame<=iLast && iFrame>=pWal->minFrame && aPgno[aHash[iKey]]==pgno ){
+ for(iKey=walHash(pgno); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){
+ u32 iFrame = sLoc.aHash[iKey] + sLoc.iZero;
+ if( iFrame<=iLast && iFrame>=pWal->minFrame
+ && sLoc.aPgno[sLoc.aHash[iKey]]==pgno ){
assert( iFrame>iRead || CORRUPT_DB );
iRead = iFrame;
}
@@ -60986,6 +61572,43 @@ SQLITE_API int sqlite3_snapshot_cmp(sqlite3_snapshot *p1, sqlite3_snapshot *p2){
if( pHdr1->mxFrame>pHdr2->mxFrame ) return +1;
return 0;
}
+
+/*
+** The caller currently has a read transaction open on the database.
+** This function takes a SHARED lock on the CHECKPOINTER slot and then
+** checks if the snapshot passed as the second argument is still
+** available. If so, SQLITE_OK is returned.
+**
+** If the snapshot is not available, SQLITE_ERROR is returned. Or, if
+** the CHECKPOINTER lock cannot be obtained, SQLITE_BUSY. If any error
+** occurs (any value other than SQLITE_OK is returned), the CHECKPOINTER
+** lock is released before returning.
+*/
+SQLITE_PRIVATE int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot){
+ int rc;
+ rc = walLockShared(pWal, WAL_CKPT_LOCK);
+ if( rc==SQLITE_OK ){
+ WalIndexHdr *pNew = (WalIndexHdr*)pSnapshot;
+ if( memcmp(pNew->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt))
+ || pNew->mxFrame<walCkptInfo(pWal)->nBackfillAttempted
+ ){
+ rc = SQLITE_ERROR_SNAPSHOT;
+ walUnlockShared(pWal, WAL_CKPT_LOCK);
+ }
+ }
+ return rc;
+}
+
+/*
+** Release a lock obtained by an earlier successful call to
+** sqlite3WalSnapshotCheck().
+*/
+SQLITE_PRIVATE void sqlite3WalSnapshotUnlock(Wal *pWal){
+ assert( pWal );
+ walUnlockShared(pWal, WAL_CKPT_LOCK);
+}
+
+
#endif /* SQLITE_ENABLE_SNAPSHOT */
#ifdef SQLITE_ENABLE_ZIPVFS
@@ -65331,7 +65954,7 @@ SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p){
** when A already has a read lock, we encourage A to give up and let B
** proceed.
*/
-SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
+SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){
BtShared *pBt = p->pBt;
int rc = SQLITE_OK;
@@ -65347,6 +65970,12 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
}
assert( pBt->inTransaction==TRANS_WRITE || IfNotOmitAV(pBt->bDoTruncate)==0 );
+ if( (p->db->flags & SQLITE_ResetDatabase)
+ && sqlite3PagerIsreadonly(pBt->pPager)==0
+ ){
+ pBt->btsFlags &= ~BTS_READ_ONLY;
+ }
+
/* Write transactions are not possible on a read-only database */
if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){
rc = SQLITE_READONLY;
@@ -65406,6 +66035,11 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db));
if( rc==SQLITE_OK ){
rc = newDatabase(pBt);
+ }else if( rc==SQLITE_BUSY_SNAPSHOT && pBt->inTransaction==TRANS_NONE ){
+ /* if there was no transaction opened when this function was
+ ** called and SQLITE_BUSY_SNAPSHOT is returned, change the error
+ ** code to SQLITE_BUSY. */
+ rc = SQLITE_BUSY;
}
}
}
@@ -65457,14 +66091,18 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
}
}
-
trans_begun:
- if( rc==SQLITE_OK && wrflag ){
- /* This call makes sure that the pager has the correct number of
- ** open savepoints. If the second parameter is greater than 0 and
- ** the sub-journal is not already open, then it will be opened here.
- */
- rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint);
+ if( rc==SQLITE_OK ){
+ if( pSchemaVersion ){
+ *pSchemaVersion = get4byte(&pBt->pPage1->aData[40]);
+ }
+ if( wrflag ){
+ /* This call makes sure that the pager has the correct number of
+ ** open savepoints. If the second parameter is greater than 0 and
+ ** the sub-journal is not already open, then it will be opened here.
+ */
+ rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint);
+ }
}
btreeIntegrity(p);
@@ -67211,6 +67849,23 @@ SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
return rc;
}
+/*
+** This function is a no-op if cursor pCur does not point to a valid row.
+** Otherwise, if pCur is valid, configure it so that the next call to
+** sqlite3BtreeNext() is a no-op.
+*/
+#ifndef SQLITE_OMIT_WINDOWFUNC
+SQLITE_PRIVATE void sqlite3BtreeSkipNext(BtCursor *pCur){
+ /* We believe that the cursor must always be in the valid state when
+ ** this routine is called, but the proof is difficult, so we add an
+ ** ALWaYS() test just in case we are wrong. */
+ if( ALWAYS(pCur->eState==CURSOR_VALID) ){
+ pCur->eState = CURSOR_SKIPNEXT;
+ pCur->skipNext = 1;
+ }
+}
+#endif /* SQLITE_OMIT_WINDOWFUNC */
+
/* Move the cursor to the last entry in the table. Return SQLITE_OK
** on success. Set *pRes to 0 if the cursor actually points to something
** or set *pRes to 1 if the table is empty.
@@ -67615,7 +68270,16 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
pPage = pCur->pPage;
idx = ++pCur->ix;
- assert( pPage->isInit );
+ if( !pPage->isInit ){
+ /* The only known way for this to happen is for there to be a
+ ** recursive SQL function that does a DELETE operation as part of a
+ ** SELECT which deletes content out from under an active cursor
+ ** in a corrupt database file where the table being DELETE-ed from
+ ** has pages in common with the table being queried. See TH3
+ ** module cov1/btree78.test testcase 220 (2018-06-08) for an
+ ** example. */
+ return SQLITE_CORRUPT_BKPT;
+ }
/* If the database file is corrupt, it is possible for the value of idx
** to be invalid here. This can only occur if a second cursor modifies
@@ -71327,8 +71991,7 @@ static void setPageReferenced(IntegrityCk *pCheck, Pgno iPg){
** Also check that the page number is in bounds.
*/
static int checkRef(IntegrityCk *pCheck, Pgno iPage){
- if( iPage==0 ) return 1;
- if( iPage>pCheck->nPage ){
+ if( iPage>pCheck->nPage || iPage==0 ){
checkAppendMsg(pCheck, "invalid page number %d", iPage);
return 1;
}
@@ -71383,17 +72046,12 @@ static void checkList(
){
int i;
int expected = N;
- int iFirst = iPage;
- while( N-- > 0 && pCheck->mxErr ){
+ int nErrAtStart = pCheck->nErr;
+ while( iPage!=0 && pCheck->mxErr ){
DbPage *pOvflPage;
unsigned char *pOvflData;
- if( iPage<1 ){
- checkAppendMsg(pCheck,
- "%d of %d pages missing from overflow list starting at %d",
- N+1, expected, iFirst);
- break;
- }
if( checkRef(pCheck, iPage) ) break;
+ N--;
if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage, 0) ){
checkAppendMsg(pCheck, "failed to get page %d", iPage);
break;
@@ -71437,10 +72095,12 @@ static void checkList(
#endif
iPage = get4byte(pOvflData);
sqlite3PagerUnref(pOvflPage);
-
- if( isFreeList && N<(iPage!=0) ){
- checkAppendMsg(pCheck, "free-page count in header is too small");
- }
+ }
+ if( N && nErrAtStart==pCheck->nErr ){
+ checkAppendMsg(pCheck,
+ "%s is %d but should be %d",
+ isFreeList ? "size" : "overflow list length",
+ expected-N, expected);
}
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
@@ -71834,6 +72494,24 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
/* Check all the tables.
*/
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ if( pBt->autoVacuum ){
+ int mx = 0;
+ int mxInHdr;
+ for(i=0; (int)i<nRoot; i++) if( mx<aRoot[i] ) mx = aRoot[i];
+ mxInHdr = get4byte(&pBt->pPage1->aData[52]);
+ if( mx!=mxInHdr ){
+ checkAppendMsg(&sCheck,
+ "max rootpage (%d) disagrees with header (%d)",
+ mx, mxInHdr
+ );
+ }
+ }else if( get4byte(&pBt->pPage1->aData[64])!=0 ){
+ checkAppendMsg(&sCheck,
+ "incremental_vacuum enabled with a max rootpage of zero"
+ );
+ }
+#endif
testcase( pBt->db->flags & SQLITE_CellSizeCk );
pBt->db->flags &= ~SQLITE_CellSizeCk;
for(i=0; (int)i<nRoot && sCheck.mxErr; i++){
@@ -72115,11 +72793,11 @@ SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
pBt->btsFlags &= ~BTS_NO_WAL;
if( iVersion==1 ) pBt->btsFlags |= BTS_NO_WAL;
- rc = sqlite3BtreeBeginTrans(pBtree, 0);
+ rc = sqlite3BtreeBeginTrans(pBtree, 0, 0);
if( rc==SQLITE_OK ){
u8 *aData = pBt->pPage1->aData;
if( aData[18]!=(u8)iVersion || aData[19]!=(u8)iVersion ){
- rc = sqlite3BtreeBeginTrans(pBtree, 2);
+ rc = sqlite3BtreeBeginTrans(pBtree, 2, 0);
if( rc==SQLITE_OK ){
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
if( rc==SQLITE_OK ){
@@ -72559,7 +73237,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
** before this function exits.
*/
if( rc==SQLITE_OK && 0==sqlite3BtreeIsInReadTrans(p->pSrc) ){
- rc = sqlite3BtreeBeginTrans(p->pSrc, 0);
+ rc = sqlite3BtreeBeginTrans(p->pSrc, 0, 0);
bCloseTrans = 1;
}
@@ -72575,10 +73253,10 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
/* Lock the destination database, if it is not locked already. */
if( SQLITE_OK==rc && p->bDestLocked==0
- && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2))
+ && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2,
+ (int*)&p->iDestSchema))
){
p->bDestLocked = 1;
- sqlite3BtreeGetMeta(p->pDest, BTREE_SCHEMA_VERSION, &p->iDestSchema);
}
/* Do not allow backup if the destination database is in WAL mode
@@ -73022,8 +73700,7 @@ SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){
if( p->flags & MEM_Null ){
/* Cannot be both MEM_Null and some other type */
- assert( (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob
- |MEM_RowSet|MEM_Frame|MEM_Agg))==0 );
+ assert( (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob|MEM_Agg))==0 );
/* If MEM_Null is set, then either the value is a pure NULL (the usual
** case) or it is a pointer set using sqlite3_bind_pointer() or
@@ -73136,7 +73813,7 @@ SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
#ifndef SQLITE_OMIT_UTF16
int rc;
#endif
- assert( (pMem->flags&MEM_RowSet)==0 );
+ assert( !sqlite3VdbeMemIsRowSet(pMem) );
assert( desiredEnc==SQLITE_UTF8 || desiredEnc==SQLITE_UTF16LE
|| desiredEnc==SQLITE_UTF16BE );
if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){
@@ -73169,7 +73846,7 @@ SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
*/
SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
assert( sqlite3VdbeCheckMemInvariants(pMem) );
- assert( (pMem->flags&MEM_RowSet)==0 );
+ assert( !sqlite3VdbeMemIsRowSet(pMem) );
testcase( pMem->db==0 );
/* If the bPreserve flag is set to true, then the memory cell must already
@@ -73257,7 +73934,7 @@ static SQLITE_NOINLINE int vdbeMemAddTerminator(Mem *pMem){
*/
SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- assert( (pMem->flags&MEM_RowSet)==0 );
+ assert( !sqlite3VdbeMemIsRowSet(pMem) );
if( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ){
if( ExpandBlob(pMem) ) return SQLITE_NOMEM;
if( pMem->szMalloc==0 || pMem->z!=pMem->zMalloc ){
@@ -73282,7 +73959,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *pMem){
int nByte;
assert( pMem->flags & MEM_Zero );
assert( pMem->flags&MEM_Blob );
- assert( (pMem->flags&MEM_RowSet)==0 );
+ assert( !sqlite3VdbeMemIsRowSet(pMem) );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
/* Set nByte to the number of bytes required to store the expanded blob. */
@@ -73337,7 +74014,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){
assert( !(fg&MEM_Zero) );
assert( !(fg&(MEM_Str|MEM_Blob)) );
assert( fg&(MEM_Int|MEM_Real) );
- assert( (pMem->flags&MEM_RowSet)==0 );
+ assert( !sqlite3VdbeMemIsRowSet(pMem) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
@@ -73396,6 +74073,35 @@ SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
}
/*
+** Memory cell pAccum contains the context of an aggregate function.
+** This routine calls the xValue method for that function and stores
+** the results in memory cell pMem.
+**
+** SQLITE_ERROR is returned if xValue() reports an error. SQLITE_OK
+** otherwise.
+*/
+#ifndef SQLITE_OMIT_WINDOWFUNC
+SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem *pAccum, Mem *pOut, FuncDef *pFunc){
+ sqlite3_context ctx;
+ Mem t;
+ assert( pFunc!=0 );
+ assert( pFunc->xValue!=0 );
+ assert( (pAccum->flags & MEM_Null)!=0 || pFunc==pAccum->u.pDef );
+ assert( pAccum->db==0 || sqlite3_mutex_held(pAccum->db->mutex) );
+ memset(&ctx, 0, sizeof(ctx));
+ memset(&t, 0, sizeof(t));
+ t.flags = MEM_Null;
+ t.db = pAccum->db;
+ sqlite3VdbeMemSetNull(pOut);
+ ctx.pOut = pOut;
+ ctx.pMem = pAccum;
+ ctx.pFunc = pFunc;
+ pFunc->xValue(&ctx);
+ return ctx.isError;
+}
+#endif /* SQLITE_OMIT_WINDOWFUNC */
+
+/*
** If the memory cell contains a value that must be freed by
** invoking the external callback in Mem.xDel, then this routine
** will free that value. It also sets Mem.flags to MEM_Null.
@@ -73413,15 +74119,8 @@ static SQLITE_NOINLINE void vdbeMemClearExternAndSetNull(Mem *p){
testcase( p->flags & MEM_Dyn );
}
if( p->flags&MEM_Dyn ){
- assert( (p->flags&MEM_RowSet)==0 );
assert( p->xDel!=SQLITE_DYNAMIC && p->xDel!=0 );
p->xDel((void *)p->z);
- }else if( p->flags&MEM_RowSet ){
- sqlite3RowSetClear(p->u.pRowSet);
- }else if( p->flags&MEM_Frame ){
- VdbeFrame *pFrame = p->u.pFrame;
- pFrame->pParent = pFrame->v->pDelFrame;
- pFrame->v->pDelFrame = pFrame;
}
p->flags = MEM_Null;
}
@@ -73569,7 +74268,7 @@ SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem *pMem, int ifNull){
SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem *pMem){
i64 ix;
assert( pMem->flags & MEM_Real );
- assert( (pMem->flags & MEM_RowSet)==0 );
+ assert( !sqlite3VdbeMemIsRowSet(pMem) );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
@@ -73596,7 +74295,7 @@ SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem *pMem){
*/
SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- assert( (pMem->flags & MEM_RowSet)==0 );
+ assert( !sqlite3VdbeMemIsRowSet(pMem) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
pMem->u.i = sqlite3VdbeIntValue(pMem);
@@ -73814,26 +74513,36 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem *pMem, double val){
}
#endif
+#ifdef SQLITE_DEBUG
+/*
+** Return true if the Mem holds a RowSet object. This routine is intended
+** for use inside of assert() statements.
+*/
+SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem *pMem){
+ return (pMem->flags&(MEM_Blob|MEM_Dyn))==(MEM_Blob|MEM_Dyn)
+ && pMem->xDel==sqlite3RowSetDelete;
+}
+#endif
+
/*
** Delete any previous value and set the value of pMem to be an
** empty boolean index.
+**
+** Return SQLITE_OK on success and SQLITE_NOMEM if a memory allocation
+** error occurs.
*/
-SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem *pMem){
+SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem *pMem){
sqlite3 *db = pMem->db;
+ RowSet *p;
assert( db!=0 );
- assert( (pMem->flags & MEM_RowSet)==0 );
+ assert( !sqlite3VdbeMemIsRowSet(pMem) );
sqlite3VdbeMemRelease(pMem);
- pMem->zMalloc = sqlite3DbMallocRawNN(db, 64);
- if( db->mallocFailed ){
- pMem->flags = MEM_Null;
- pMem->szMalloc = 0;
- }else{
- assert( pMem->zMalloc );
- pMem->szMalloc = sqlite3DbMallocSize(db, pMem->zMalloc);
- pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc, pMem->szMalloc);
- assert( pMem->u.pRowSet!=0 );
- pMem->flags = MEM_RowSet;
- }
+ p = sqlite3RowSetInit(db);
+ if( p==0 ) return SQLITE_NOMEM;
+ pMem->z = (char*)p;
+ pMem->flags = MEM_Blob|MEM_Dyn;
+ pMem->xDel = sqlite3RowSetDelete;
+ return SQLITE_OK;
}
/*
@@ -73866,7 +74575,21 @@ SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
Mem *pX;
for(i=0, pX=pVdbe->aMem; i<pVdbe->nMem; i++, pX++){
if( pX->pScopyFrom==pMem ){
- pX->flags |= MEM_Undefined;
+ /* If pX is marked as a shallow copy of pMem, then verify that
+ ** no significant changes have been made to pX since the OP_SCopy.
+ ** A significant change would indicated a missed call to this
+ ** function for pX. Minor changes, such as adding or removing a
+ ** dual type, are allowed, as long as the underlying value is the
+ ** same. */
+ u16 mFlags = pMem->flags & pX->flags & pX->mScopyFlags;
+ assert( (mFlags&MEM_Int)==0 || pMem->u.i==pX->u.i );
+ assert( (mFlags&MEM_Real)==0 || pMem->u.r==pX->u.r );
+ assert( (mFlags&MEM_Str)==0 || (pMem->n==pX->n && pMem->z==pX->z) );
+ assert( (mFlags&MEM_Blob)==0 || sqlite3BlobCompare(pMem,pX)==0 );
+
+ /* pMem is the register that is changing. But also mark pX as
+ ** undefined so that we can quickly detect the shallow-copy error */
+ pX->flags = MEM_Undefined;
pX->pScopyFrom = 0;
}
}
@@ -73887,7 +74610,7 @@ static SQLITE_NOINLINE void vdbeClrCopy(Mem *pTo, const Mem *pFrom, int eType){
sqlite3VdbeMemShallowCopy(pTo, pFrom, eType);
}
SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
- assert( (pFrom->flags & MEM_RowSet)==0 );
+ assert( !sqlite3VdbeMemIsRowSet(pFrom) );
assert( pTo->db==pFrom->db );
if( VdbeMemDynamic(pTo) ){ vdbeClrCopy(pTo,pFrom,srcType); return; }
memcpy(pTo, pFrom, MEMCELLSIZE);
@@ -73905,7 +74628,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int sr
SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
int rc = SQLITE_OK;
- assert( (pFrom->flags & MEM_RowSet)==0 );
+ assert( !sqlite3VdbeMemIsRowSet(pFrom) );
if( VdbeMemDynamic(pTo) ) vdbeMemClearExternAndSetNull(pTo);
memcpy(pTo, pFrom, MEMCELLSIZE);
pTo->flags &= ~MEM_Dyn;
@@ -73963,7 +74686,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr(
u16 flags = 0; /* New value for pMem->flags */
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- assert( (pMem->flags & MEM_RowSet)==0 );
+ assert( !sqlite3VdbeMemIsRowSet(pMem) );
/* If z is a NULL pointer, set pMem to contain an SQL NULL. */
if( !z ){
@@ -74085,7 +74808,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(
/* Note: the calls to BtreeKeyFetch() and DataFetch() below assert()
** that both the BtShared and database handle mutexes are held. */
- assert( (pMem->flags & MEM_RowSet)==0 );
+ assert( !sqlite3VdbeMemIsRowSet(pMem) );
zData = (char *)sqlite3BtreePayloadFetch(pCur, &available);
assert( zData!=0 );
@@ -74109,7 +74832,7 @@ static SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){
assert( pVal!=0 );
assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) );
assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) );
- assert( (pVal->flags & MEM_RowSet)==0 );
+ assert( !sqlite3VdbeMemIsRowSet(pVal) );
assert( (pVal->flags & (MEM_Null))==0 );
if( pVal->flags & (MEM_Blob|MEM_Str) ){
if( ExpandBlob(pVal) ) return 0;
@@ -74152,7 +74875,7 @@ SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){
if( !pVal ) return 0;
assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) );
assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) );
- assert( (pVal->flags & MEM_RowSet)==0 );
+ assert( !sqlite3VdbeMemIsRowSet(pVal) );
if( (pVal->flags&(MEM_Str|MEM_Term))==(MEM_Str|MEM_Term) && pVal->enc==enc ){
assert( sqlite3VdbeMemConsistentDualRep(pVal) );
return pVal->z;
@@ -74719,11 +75442,11 @@ SQLITE_PRIVATE int sqlite3Stat4Column(
int iCol, /* Column to extract */
sqlite3_value **ppVal /* OUT: Extracted value */
){
- u32 t; /* a column type code */
+ u32 t = 0; /* a column type code */
int nHdr; /* Size of the header in the record */
int iHdr; /* Next unread header byte */
int iField; /* Next unread data byte */
- int szField; /* Size of the current data field */
+ int szField = 0; /* Size of the current data field */
int i; /* Column index */
u8 *a = (u8*)pRec; /* Typecast byte array */
Mem *pMem = *ppVal; /* Write result into this Mem object */
@@ -75016,14 +75739,6 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
#endif
#ifdef SQLITE_DEBUG
if( p->db->flags & SQLITE_VdbeAddopTrace ){
- int jj, kk;
- Parse *pParse = p->pParse;
- for(jj=kk=0; jj<pParse->nColCache; jj++){
- struct yColCache *x = pParse->aColCache + jj;
- printf(" r[%d]={%d:%d}", x->iReg, x->iTable, x->iColumn);
- kk++;
- }
- if( kk ) printf("\n");
sqlite3VdbePrintOp(0, i, &p->aOp[i]);
test_addop_breakpoint();
}
@@ -75147,7 +75862,7 @@ SQLITE_PRIVATE int sqlite3VdbeExplainParent(Parse *pParse){
SQLITE_PRIVATE void sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){
if( pParse->explain==2 ){
char *zMsg;
- Vdbe *v = pParse->pVdbe;
+ Vdbe *v;
va_list ap;
int iThis;
va_start(ap, zFmt);
@@ -75268,19 +75983,6 @@ SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *v, int x){
}
}
-#ifdef SQLITE_COVERAGE_TEST
-/*
-** Return TRUE if and only if the label x has already been resolved.
-** Return FALSE (zero) if label x is still unresolved.
-**
-** This routine is only used inside of testcase() macros, and so it
-** only exists when measuring test coverage.
-*/
-SQLITE_PRIVATE int sqlite3VdbeLabelHasBeenResolved(Vdbe *v, int x){
- return v->pParse->aLabel && v->pParse->aLabel[ADDR(x)]>=0;
-}
-#endif /* SQLITE_COVERAGE_TEST */
-
/*
** Mark the VDBE as one that can only be run one time.
*/
@@ -75512,7 +76214,6 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
break;
}
case OP_Next:
- case OP_NextIfOpen:
case OP_SorterNext: {
pOp->p4.xAdvance = sqlite3BtreeNext;
pOp->p4type = P4_ADVANCE;
@@ -75522,8 +76223,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
assert( pOp->p2>=0 );
break;
}
- case OP_Prev:
- case OP_PrevIfOpen: {
+ case OP_Prev: {
pOp->p4.xAdvance = sqlite3BtreePrevious;
pOp->p4type = P4_ADVANCE;
/* The code generator never codes any of these opcodes as a jump
@@ -76438,7 +77138,7 @@ SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe *p){
/*
** Print a single opcode. This routine is used for debugging only.
*/
-SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){
+SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, VdbeOp *pOp){
char *zP4;
char zPtr[50];
char zCom[100];
@@ -76507,9 +77207,8 @@ static void releaseMemArray(Mem *p, int N){
*/
testcase( p->flags & MEM_Agg );
testcase( p->flags & MEM_Dyn );
- testcase( p->flags & MEM_Frame );
- testcase( p->flags & MEM_RowSet );
- if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){
+ testcase( p->xDel==sqlite3VdbeFrameMemDel );
+ if( p->flags&(MEM_Agg|MEM_Dyn) ){
sqlite3VdbeMemRelease(p);
}else if( p->szMalloc ){
sqlite3DbFreeNN(db, p->zMalloc);
@@ -76521,6 +77220,35 @@ static void releaseMemArray(Mem *p, int N){
}
}
+#ifdef SQLITE_DEBUG
+/*
+** Verify that pFrame is a valid VdbeFrame pointer. Return true if it is
+** and false if something is wrong.
+**
+** This routine is intended for use inside of assert() statements only.
+*/
+SQLITE_PRIVATE int sqlite3VdbeFrameIsValid(VdbeFrame *pFrame){
+ if( pFrame->iFrameMagic!=SQLITE_FRAME_MAGIC ) return 0;
+ return 1;
+}
+#endif
+
+
+/*
+** This is a destructor on a Mem object (which is really an sqlite3_value)
+** that deletes the Frame object that is attached to it as a blob.
+**
+** This routine does not delete the Frame right away. It merely adds the
+** frame to a list of frames to be deleted when the Vdbe halts.
+*/
+SQLITE_PRIVATE void sqlite3VdbeFrameMemDel(void *pArg){
+ VdbeFrame *pFrame = (VdbeFrame*)pArg;
+ assert( sqlite3VdbeFrameIsValid(pFrame) );
+ pFrame->pParent = pFrame->v->pDelFrame;
+ pFrame->v->pDelFrame = pFrame;
+}
+
+
/*
** Delete a VdbeFrame object and its contents. VdbeFrame objects are
** allocated by the OP_Program opcode in sqlite3VdbeExec().
@@ -76529,6 +77257,7 @@ SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame *p){
int i;
Mem *aMem = VdbeFrameMem(p);
VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem];
+ assert( sqlite3VdbeFrameIsValid(p) );
for(i=0; i<p->nChildCsr; i++){
sqlite3VdbeFreeCursor(p->v, apCsr[i]);
}
@@ -77825,7 +78554,7 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
*/
sqlite3VdbeHalt(p);
- /* If the VDBE has be run even partially, then transfer the error code
+ /* If the VDBE has been run even partially, then transfer the error code
** and error message from the VDBE into the main database structure. But
** if the VDBE has just been set to run but has not actually executed any
** instructions yet, leave the main database error information unchanged.
@@ -78737,7 +79466,7 @@ static int isAllZero(const char *z, int n){
** is less than, equal to, or greater than the second, respectively.
** If one blob is a prefix of the other, then the shorter is the lessor.
*/
-static SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem *pB2){
+SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem *pB2){
int c;
int n1 = pB1->n;
int n2 = pB2->n;
@@ -78807,7 +79536,7 @@ SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const C
f1 = pMem1->flags;
f2 = pMem2->flags;
combined_flags = f1|f2;
- assert( (combined_flags & MEM_RowSet)==0 );
+ assert( !sqlite3VdbeMemIsRowSet(pMem1) && !sqlite3VdbeMemIsRowSet(pMem2) );
/* If one value is NULL, it is less than the other. If both values
** are NULL, return 0.
@@ -78952,7 +79681,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
u32 idx1; /* Offset of first type in header */
int rc = 0; /* Return value */
Mem *pRhs = pPKey2->aMem; /* Next field of pPKey2 to compare */
- KeyInfo *pKeyInfo = pPKey2->pKeyInfo;
+ KeyInfo *pKeyInfo;
const unsigned char *aKey1 = (const unsigned char *)pKey1;
Mem mem1;
@@ -79047,7 +79776,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
if( (d1+mem1.n) > (unsigned)nKey1 ){
pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
return 0; /* Corruption */
- }else if( pKeyInfo->aColl[i] ){
+ }else if( (pKeyInfo = pPKey2->pKeyInfo)->aColl[i] ){
mem1.enc = pKeyInfo->enc;
mem1.db = pKeyInfo->db;
mem1.flags = MEM_Str;
@@ -79098,7 +79827,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
}
if( rc!=0 ){
- if( pKeyInfo->aSortOrder[i] ){
+ if( pPKey2->pKeyInfo->aSortOrder[i] ){
rc = -rc;
}
assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, rc) );
@@ -79107,10 +79836,11 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
}
i++;
+ if( i==pPKey2->nField ) break;
pRhs++;
d1 += sqlite3VdbeSerialTypeLen(serial_type);
idx1 += sqlite3VarintLen(serial_type);
- }while( idx1<(unsigned)szHdr1 && i<pPKey2->nField && d1<=(unsigned)nKey1 );
+ }while( idx1<(unsigned)szHdr1 && d1<=(unsigned)nKey1 );
/* No memory allocation is ever used on mem1. Prove this using
** the following assert(). If the assert() fails, it indicates a
@@ -79122,7 +79852,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
** value. */
assert( CORRUPT_DB
|| vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, pPKey2->default_rc)
- || pKeyInfo->db->mallocFailed
+ || pPKey2->pKeyInfo->db->mallocFailed
);
pPKey2->eqSeen = 1;
return pPKey2->default_rc;
@@ -79448,7 +80178,7 @@ SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
if( rc ){
return rc;
}
- *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked);
+ *res = sqlite3VdbeRecordCompareWithSkip(m.n, m.z, pUnpacked, 0);
sqlite3VdbeMemRelease(&m);
return SQLITE_OK;
}
@@ -79480,11 +80210,19 @@ SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe *v){
** programs obsolete. Removing user-defined functions or collating
** sequences, or changing an authorization function are the types of
** things that make prepared statements obsolete.
+**
+** If iCode is 1, then expiration is advisory. The statement should
+** be reprepared before being restarted, but if it is already running
+** it is allowed to run to completion.
+**
+** Internally, this function just sets the Vdbe.expired flag on all
+** prepared statements. The flag is set to 1 for an immediate expiration
+** and set to 2 for an advisory expiration.
*/
-SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3 *db){
+SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3 *db, int iCode){
Vdbe *p;
for(p = db->pVdbe; p; p=p->pNext){
- p->expired = 1;
+ p->expired = iCode+1;
}
}
@@ -80644,7 +81382,7 @@ static const Mem *columnNullValue(void){
/* .xDel = */ (void(*)(void*))0,
#ifdef SQLITE_DEBUG
/* .pScopyFrom = */ (Mem*)0,
- /* .pFiller = */ (void*)0,
+ /* .mScopyFlags= */ 0,
#endif
};
return &nullMem;
@@ -81954,32 +82692,56 @@ SQLITE_API int sqlite3_found_count = 0;
** feature is used for test suite validation only and does not appear an
** production builds.
**
-** M is an integer, 2 or 3, that indices how many different ways the
-** branch can go. It is usually 2. "I" is the direction the branch
-** goes. 0 means falls through. 1 means branch is taken. 2 means the
-** second alternative branch is taken.
+** M is an integer between 2 and 4. 2 indicates a ordinary two-way
+** branch (I=0 means fall through and I=1 means taken). 3 indicates
+** a 3-way branch where the third way is when one of the operands is
+** NULL. 4 indicates the OP_Jump instruction which has three destinations
+** depending on whether the first operand is less than, equal to, or greater
+** than the second.
**
** iSrcLine is the source code line (from the __LINE__ macro) that
-** generated the VDBE instruction. This instrumentation assumes that all
-** source code is in a single file (the amalgamation). Special values 1
-** and 2 for the iSrcLine parameter mean that this particular branch is
-** always taken or never taken, respectively.
+** generated the VDBE instruction combined with flag bits. The source
+** code line number is in the lower 24 bits of iSrcLine and the upper
+** 8 bytes are flags. The lower three bits of the flags indicate
+** values for I that should never occur. For example, if the branch is
+** always taken, the flags should be 0x05 since the fall-through and
+** alternate branch are never taken. If a branch is never taken then
+** flags should be 0x06 since only the fall-through approach is allowed.
+**
+** Bit 0x04 of the flags indicates an OP_Jump opcode that is only
+** interested in equal or not-equal. In other words, I==0 and I==2
+** should be treated the same.
+**
+** Since only a line number is retained, not the filename, this macro
+** only works for amalgamation builds. But that is ok, since these macros
+** should be no-ops except for special builds used to measure test coverage.
*/
#if !defined(SQLITE_VDBE_COVERAGE)
# define VdbeBranchTaken(I,M)
#else
# define VdbeBranchTaken(I,M) vdbeTakeBranch(pOp->iSrcLine,I,M)
- static void vdbeTakeBranch(int iSrcLine, u8 I, u8 M){
- if( iSrcLine<=2 && ALWAYS(iSrcLine>0) ){
- M = iSrcLine;
- /* Assert the truth of VdbeCoverageAlwaysTaken() and
- ** VdbeCoverageNeverTaken() */
- assert( (M & I)==I );
- }else{
- if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/
- sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg,
- iSrcLine,I,M);
- }
+ static void vdbeTakeBranch(u32 iSrcLine, u8 I, u8 M){
+ u8 mNever;
+ assert( I<=2 ); /* 0: fall through, 1: taken, 2: alternate taken */
+ assert( M<=4 ); /* 2: two-way branch, 3: three-way branch, 4: OP_Jump */
+ assert( I<M ); /* I can only be 2 if M is 3 or 4 */
+ /* Transform I from a integer [0,1,2] into a bitmask of [1,2,4] */
+ I = 1<<I;
+ /* The upper 8 bits of iSrcLine are flags. The lower three bits of
+ ** the flags indicate directions that the branch can never go. If
+ ** a branch really does go in one of those directions, assert right
+ ** away. */
+ mNever = iSrcLine >> 24;
+ assert( (I & mNever)==0 );
+ if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/
+ I |= mNever;
+ if( M==2 ) I |= 0x04;
+ if( M==4 ){
+ I |= 0x08;
+ if( (mNever&0x08)!=0 && (I&0x05)!=0) I |= 0x05; /*NO_TEST*/
+ }
+ sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg,
+ iSrcLine&0xffffff, I, M);
}
#endif
@@ -82310,7 +83072,7 @@ static void memTracePrint(Mem *p){
}else if( p->flags & MEM_Real ){
printf(" r:%g", p->u.r);
#endif
- }else if( p->flags & MEM_RowSet ){
+ }else if( sqlite3VdbeMemIsRowSet(p) ){
printf(" (rowset)");
}else{
char zBuf[200];
@@ -83064,6 +83826,9 @@ case OP_Null: { /* out2 */
assert( pOp->p3<=(p->nMem+1 - p->nCursor) );
pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null;
pOut->n = 0;
+#ifdef SQLITE_DEBUG
+ pOut->uTemp = 0;
+#endif
while( cnt>0 ){
pOut++;
memAboutToChange(p, pOut);
@@ -83185,6 +83950,7 @@ case OP_Copy: {
pOut = &aMem[pOp->p2];
assert( pOut!=pIn1 );
while( 1 ){
+ memAboutToChange(p, pOut);
sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
Deephemeralize(pOut);
#ifdef SQLITE_DEBUG
@@ -83217,7 +83983,8 @@ case OP_SCopy: { /* out2 */
assert( pOut!=pIn1 );
sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
#ifdef SQLITE_DEBUG
- if( pOut->pScopyFrom==0 ) pOut->pScopyFrom = pIn1;
+ pOut->pScopyFrom = pIn1;
+ pOut->mScopyFlags = pIn1->flags;
#endif
break;
}
@@ -83851,7 +84618,12 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
if( (flags1 | flags3)&MEM_Str ){
if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
applyNumericAffinity(pIn1,0);
- testcase( flags3!=pIn3->flags ); /* Possible if pIn1==pIn3 */
+ assert( flags3==pIn3->flags );
+ /* testcase( flags3!=pIn3->flags );
+ ** this used to be possible with pIn1==pIn3, but not since
+ ** the column cache was removed. The following assignment
+ ** is essentially a no-op. But, it provides defense-in-depth
+ ** in case our analysis is incorrect, so it is left in. */
flags3 = pIn3->flags;
}
if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
@@ -84065,11 +84837,11 @@ case OP_Compare: {
*/
case OP_Jump: { /* jump */
if( iCompare<0 ){
- VdbeBranchTaken(0,3); pOp = &aOp[pOp->p1 - 1];
+ VdbeBranchTaken(0,4); pOp = &aOp[pOp->p1 - 1];
}else if( iCompare==0 ){
- VdbeBranchTaken(1,3); pOp = &aOp[pOp->p2 - 1];
+ VdbeBranchTaken(1,4); pOp = &aOp[pOp->p2 - 1];
}else{
- VdbeBranchTaken(2,3); pOp = &aOp[pOp->p3 - 1];
+ VdbeBranchTaken(2,4); pOp = &aOp[pOp->p3 - 1];
}
break;
}
@@ -84166,7 +84938,7 @@ case OP_Not: { /* same as TK_NOT, in1, out2 */
}
/* Opcode: BitNot P1 P2 * * *
-** Synopsis: r[P1]= ~r[P1]
+** Synopsis: r[P2]= ~r[P1]
**
** Interpret the content of register P1 as an integer. Store the
** ones-complement of the P1 value into register P2. If P1 holds
@@ -84981,7 +85753,7 @@ case OP_Savepoint: {
}
}
if( isSchemaChange ){
- sqlite3ExpirePreparedStatements(db);
+ sqlite3ExpirePreparedStatements(db, 0);
sqlite3ResetAllSchemasOfConnection(db);
db->mDbFlags |= DBFLAG_SchemaChange;
}
@@ -85123,8 +85895,7 @@ case OP_AutoCommit: {
*/
case OP_Transaction: {
Btree *pBt;
- int iMeta;
- int iGen;
+ int iMeta = 0;
assert( p->bIsReader );
assert( p->readOnly==0 || pOp->p2==0 );
@@ -85137,7 +85908,7 @@ case OP_Transaction: {
pBt = db->aDb[pOp->p1].pBt;
if( pBt ){
- rc = sqlite3BtreeBeginTrans(pBt, pOp->p2);
+ rc = sqlite3BtreeBeginTrans(pBt, pOp->p2, &iMeta);
testcase( rc==SQLITE_BUSY_SNAPSHOT );
testcase( rc==SQLITE_BUSY_RECOVERY );
if( rc!=SQLITE_OK ){
@@ -85170,19 +85941,17 @@ case OP_Transaction: {
p->nStmtDefCons = db->nDeferredCons;
p->nStmtDefImmCons = db->nDeferredImmCons;
}
-
- /* Gather the schema version number for checking:
+ }
+ assert( pOp->p5==0 || pOp->p4type==P4_INT32 );
+ if( pOp->p5
+ && (iMeta!=pOp->p3
+ || db->aDb[pOp->p1].pSchema->iGeneration!=pOp->p4.i)
+ ){
+ /*
** IMPLEMENTATION-OF: R-03189-51135 As each SQL statement runs, the schema
** version is checked to ensure that the schema has not changed since the
** SQL statement was prepared.
*/
- sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta);
- iGen = db->aDb[pOp->p1].pSchema->iGeneration;
- }else{
- iGen = iMeta = 0;
- }
- assert( pOp->p5==0 || pOp->p4type==P4_INT32 );
- if( pOp->p5 && (iMeta!=pOp->p3 || iGen!=pOp->p4.i) ){
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
/* If the schema-cookie from the database file matches the cookie
@@ -85273,7 +86042,7 @@ case OP_SetCookie: {
if( pOp->p1==1 ){
/* Invalidate all prepared statements whenever the TEMP database
** schema is changed. Ticket #1644 */
- sqlite3ExpirePreparedStatements(db);
+ sqlite3ExpirePreparedStatements(db, 0);
p->expired = 0;
}
if( rc ) goto abort_due_to_error;
@@ -85291,59 +86060,78 @@ case OP_SetCookie: {
** values need not be contiguous but all P1 values should be small integers.
** It is an error for P1 to be negative.
**
-** If P5!=0 then use the content of register P2 as the root page, not
-** the value of P2 itself.
-**
-** There will be a read lock on the database whenever there is an
-** open cursor. If the database was unlocked prior to this instruction
-** then a read lock is acquired as part of this instruction. A read
-** lock allows other processes to read the database but prohibits
-** any other process from modifying the database. The read lock is
-** released when all cursors are closed. If this instruction attempts
-** to get a read lock but fails, the script terminates with an
-** SQLITE_BUSY error code.
+** Allowed P5 bits:
+** <ul>
+** <li> <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for
+** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT
+** of OP_SeekLE/OP_IdxGT)
+** </ul>
**
** The P4 value may be either an integer (P4_INT32) or a pointer to
** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
-** structure, then said structure defines the content and collating
-** sequence of the index being opened. Otherwise, if P4 is an integer
-** value, it is set to the number of columns in the table.
+** object, then table being opened must be an [index b-tree] where the
+** KeyInfo object defines the content and collating
+** sequence of that index b-tree. Otherwise, if P4 is an integer
+** value, then the table being opened must be a [table b-tree] with a
+** number of columns no less than the value of P4.
**
** See also: OpenWrite, ReopenIdx
*/
/* Opcode: ReopenIdx P1 P2 P3 P4 P5
** Synopsis: root=P2 iDb=P3
**
-** The ReopenIdx opcode works exactly like ReadOpen except that it first
-** checks to see if the cursor on P1 is already open with a root page
-** number of P2 and if it is this opcode becomes a no-op. In other words,
+** The ReopenIdx opcode works like OP_OpenRead except that it first
+** checks to see if the cursor on P1 is already open on the same
+** b-tree and if it is this opcode becomes a no-op. In other words,
** if the cursor is already open, do not reopen it.
**
-** The ReopenIdx opcode may only be used with P5==0 and with P4 being
-** a P4_KEYINFO object. Furthermore, the P3 value must be the same as
-** every other ReopenIdx or OpenRead for the same cursor number.
+** The ReopenIdx opcode may only be used with P5==0 or P5==OPFLAG_SEEKEQ
+** and with P4 being a P4_KEYINFO object. Furthermore, the P3 value must
+** be the same as every other ReopenIdx or OpenRead for the same cursor
+** number.
+**
+** Allowed P5 bits:
+** <ul>
+** <li> <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for
+** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT
+** of OP_SeekLE/OP_IdxGT)
+** </ul>
**
-** See the OpenRead opcode documentation for additional information.
+** See also: OP_OpenRead, OP_OpenWrite
*/
/* Opcode: OpenWrite P1 P2 P3 P4 P5
** Synopsis: root=P2 iDb=P3
**
** Open a read/write cursor named P1 on the table or index whose root
-** page is P2. Or if P5!=0 use the content of register P2 to find the
-** root page.
+** page is P2 (or whose root page is held in register P2 if the
+** OPFLAG_P2ISREG bit is set in P5 - see below).
**
** The P4 value may be either an integer (P4_INT32) or a pointer to
** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo
-** structure, then said structure defines the content and collating
-** sequence of the index being opened. Otherwise, if P4 is an integer
-** value, it is set to the number of columns in the table, or to the
-** largest index of any column of the table that is actually used.
+** object, then table being opened must be an [index b-tree] where the
+** KeyInfo object defines the content and collating
+** sequence of that index b-tree. Otherwise, if P4 is an integer
+** value, then the table being opened must be a [table b-tree] with a
+** number of columns no less than the value of P4.
+**
+** Allowed P5 bits:
+** <ul>
+** <li> <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for
+** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT
+** of OP_SeekLE/OP_IdxGT)
+** <li> <b>0x08 OPFLAG_FORDELETE</b>: This cursor is used only to seek
+** and subsequently delete entries in an index btree. This is a
+** hint to the storage engine that the storage engine is allowed to
+** ignore. The hint is not used by the official SQLite b*tree storage
+** engine, but is used by COMDB2.
+** <li> <b>0x10 OPFLAG_P2ISREG</b>: Use the content of register P2
+** as the root page, not the value of P2 itself.
+** </ul>
**
-** This instruction works just like OpenRead except that it opens the cursor
-** in read/write mode. For a given table, there can be one or more read-only
-** cursors or a single read/write cursor but not both.
+** This instruction works like OpenRead except that it opens the cursor
+** in read/write mode.
**
-** See also OpenRead.
+** See also: OP_OpenRead, OP_ReopenIdx
*/
case OP_ReopenIdx: {
int nField;
@@ -85372,7 +86160,7 @@ case OP_OpenWrite:
assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx
|| p->readOnly==0 );
- if( p->expired ){
+ if( p->expired==1 ){
rc = SQLITE_ABORT_ROLLBACK;
goto abort_due_to_error;
}
@@ -85399,6 +86187,7 @@ case OP_OpenWrite:
if( pOp->p5 & OPFLAG_P2ISREG ){
assert( p2>0 );
assert( p2<=(p->nMem+1 - p->nCursor) );
+ assert( pOp->opcode==OP_OpenWrite );
pIn2 = &aMem[p2];
assert( memIsValid(pIn2) );
assert( (pIn2->flags & MEM_Int)!=0 );
@@ -85527,7 +86316,7 @@ case OP_OpenEphemeral: {
rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBtx,
BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
if( rc==SQLITE_OK ){
- rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1);
+ rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1, 0);
}
if( rc==SQLITE_OK ){
/* If a transient index is required, create it by calling
@@ -85754,10 +86543,10 @@ case OP_ColumnsUsed: {
**
** See also: Found, NotFound, SeekGt, SeekGe, SeekLt
*/
-case OP_SeekLT: /* jump, in3 */
-case OP_SeekLE: /* jump, in3 */
-case OP_SeekGE: /* jump, in3 */
-case OP_SeekGT: { /* jump, in3 */
+case OP_SeekLT: /* jump, in3, group */
+case OP_SeekLE: /* jump, in3, group */
+case OP_SeekGE: /* jump, in3, group */
+case OP_SeekGT: { /* jump, in3, group */
int res; /* Comparison result */
int oc; /* Opcode */
VdbeCursor *pC; /* The cursor to seek */
@@ -85935,6 +86724,25 @@ seek_not_found:
break;
}
+/* Opcode: SeekHit P1 P2 * * *
+** Synopsis: seekHit=P2
+**
+** Set the seekHit flag on cursor P1 to the value in P2.
+** The seekHit flag is used by the IfNoHope opcode.
+**
+** P1 must be a valid b-tree cursor. P2 must be a boolean value,
+** either 0 or 1.
+*/
+case OP_SeekHit: {
+ VdbeCursor *pC;
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ assert( pOp->p2==0 || pOp->p2==1 );
+ pC->seekHit = pOp->p2 & 1;
+ break;
+}
+
/* Opcode: Found P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
@@ -85969,7 +86777,34 @@ seek_not_found:
** advanced in either direction. In other words, the Next and Prev
** opcodes do not work after this operation.
**
-** See also: Found, NotExists, NoConflict
+** See also: Found, NotExists, NoConflict, IfNoHope
+*/
+/* Opcode: IfNoHope P1 P2 P3 P4 *
+** Synopsis: key=r[P3@P4]
+**
+** Register P3 is the first of P4 registers that form an unpacked
+** record.
+**
+** Cursor P1 is on an index btree. If the seekHit flag is set on P1, then
+** this opcode is a no-op. But if the seekHit flag of P1 is clear, then
+** check to see if there is any entry in P1 that matches the
+** prefix identified by P3 and P4. If no entry matches the prefix,
+** jump to P2. Otherwise fall through.
+**
+** This opcode behaves like OP_NotFound if the seekHit
+** flag is clear and it behaves like OP_Noop if the seekHit flag is set.
+**
+** This opcode is used in IN clause processing for a multi-column key.
+** If an IN clause is attached to an element of the key other than the
+** left-most element, and if there are no matches on the most recent
+** seek over the whole key, then it might be that one of the key element
+** to the left is prohibiting a match, and hence there is "no hope" of
+** any match regardless of how many IN clause elements are checked.
+** In such a case, we abandon the IN clause search early, using this
+** opcode. The opcode name comes from the fact that the
+** jump is taken if there is "no hope" of achieving a match.
+**
+** See also: NotFound, SeekHit
*/
/* Opcode: NoConflict P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
@@ -85994,6 +86829,14 @@ seek_not_found:
**
** See also: NotFound, Found, NotExists
*/
+case OP_IfNoHope: { /* jump, in3 */
+ VdbeCursor *pC;
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ if( pC->seekHit ) break;
+ /* Fall through into OP_NotFound */
+}
case OP_NoConflict: /* jump, in3 */
case OP_NotFound: /* jump, in3 */
case OP_Found: { /* jump, in3 */
@@ -86131,18 +86974,26 @@ case OP_SeekRowid: { /* jump, in3 */
pIn3 = &aMem[pOp->p3];
if( (pIn3->flags & MEM_Int)==0 ){
+ /* Make sure pIn3->u.i contains a valid integer representation of
+ ** the key value, but do not change the datatype of the register, as
+ ** other parts of the perpared statement might be depending on the
+ ** current datatype. */
+ u16 origFlags = pIn3->flags;
+ int isNotInt;
applyAffinity(pIn3, SQLITE_AFF_NUMERIC, encoding);
- if( (pIn3->flags & MEM_Int)==0 ) goto jump_to_p2;
+ isNotInt = (pIn3->flags & MEM_Int)==0;
+ pIn3->flags = origFlags;
+ if( isNotInt ) goto jump_to_p2;
}
/* Fall through into OP_NotExists */
case OP_NotExists: /* jump, in3 */
pIn3 = &aMem[pOp->p3];
- assert( pIn3->flags & MEM_Int );
+ assert( (pIn3->flags & MEM_Int)!=0 || pOp->opcode==OP_SeekRowid );
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
#ifdef SQLITE_DEBUG
- pC->seekOp = 0;
+ pC->seekOp = OP_SeekRowid;
#endif
assert( pC->isTable );
assert( pC->eCurType==CURTYPE_BTREE );
@@ -86796,6 +87647,9 @@ case OP_NullRow: {
assert( pC->uc.pCursor!=0 );
sqlite3BtreeClearCursor(pC->uc.pCursor);
}
+#ifdef SQLITE_DEBUG
+ if( pC->seekOp==0 ) pC->seekOp = OP_NullRow;
+#endif
break;
}
@@ -86914,7 +87768,7 @@ case OP_Sort: { /* jump */
p->aCounter[SQLITE_STMTSTATUS_SORT]++;
/* Fall through into OP_Rewind */
}
-/* Opcode: Rewind P1 P2 * * *
+/* Opcode: Rewind P1 P2 * * P5
**
** The next use of the Rowid or Column or Next instruction for P1
** will refer to the first entry in the database table or index.
@@ -86922,6 +87776,10 @@ case OP_Sort: { /* jump */
** If the table or index is not empty, fall through to the following
** instruction.
**
+** If P5 is non-zero and the table is not empty, then the "skip-next"
+** flag is set on the cursor so that the next OP_Next instruction
+** executed on it is a no-op.
+**
** This opcode leaves the cursor configured to move in forward order,
** from the beginning toward the end. In other words, the cursor is
** configured to use Next, not Prev.
@@ -86946,6 +87804,9 @@ case OP_Rewind: { /* jump */
pCrsr = pC->uc.pCursor;
assert( pCrsr );
rc = sqlite3BtreeFirst(pCrsr, &res);
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( pOp->p5 ) sqlite3BtreeSkipNext(pCrsr);
+#endif
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
}
@@ -86982,12 +87843,7 @@ case OP_Rewind: { /* jump */
** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented.
**
-** See also: Prev, NextIfOpen
-*/
-/* Opcode: NextIfOpen P1 P2 P3 P4 P5
-**
-** This opcode works just like Next except that if cursor P1 is not
-** open it behaves a no-op.
+** See also: Prev
*/
/* Opcode: Prev P1 P2 P3 P4 P5
**
@@ -87015,11 +87871,6 @@ case OP_Rewind: { /* jump */
** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented.
*/
-/* Opcode: PrevIfOpen P1 P2 P3 P4 P5
-**
-** This opcode works just like Prev except that if cursor P1 is not
-** open it behaves a no-op.
-*/
/* Opcode: SorterNext P1 P2 * * P5
**
** This opcode works just like OP_Next except that P1 must be a
@@ -87034,10 +87885,6 @@ case OP_SorterNext: { /* jump */
assert( isSorter(pC) );
rc = sqlite3VdbeSorterNext(db, pC);
goto next_tail;
-case OP_PrevIfOpen: /* jump */
-case OP_NextIfOpen: /* jump */
- if( p->apCsr[pOp->p1]==0 ) break;
- /* Fall through */
case OP_Prev: /* jump */
case OP_Next: /* jump */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
@@ -87048,17 +87895,17 @@ case OP_Next: /* jump */
assert( pC->eCurType==CURTYPE_BTREE );
assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
- assert( pOp->opcode!=OP_NextIfOpen || pOp->p4.xAdvance==sqlite3BtreeNext );
- assert( pOp->opcode!=OP_PrevIfOpen || pOp->p4.xAdvance==sqlite3BtreePrevious);
- /* The Next opcode is only used after SeekGT, SeekGE, and Rewind.
+ /* The Next opcode is only used after SeekGT, SeekGE, Rewind, and Found.
** The Prev opcode is only used after SeekLT, SeekLE, and Last. */
- assert( pOp->opcode!=OP_Next || pOp->opcode!=OP_NextIfOpen
+ assert( pOp->opcode!=OP_Next
|| pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE
- || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found);
- assert( pOp->opcode!=OP_Prev || pOp->opcode!=OP_PrevIfOpen
+ || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found
+ || pC->seekOp==OP_NullRow);
+ assert( pOp->opcode!=OP_Prev
|| pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE
- || pC->seekOp==OP_Last );
+ || pC->seekOp==OP_Last
+ || pC->seekOp==OP_NullRow);
rc = pOp->p4.xAdvance(pC->uc.pCursor, pOp->p3);
next_tail:
@@ -87341,7 +88188,13 @@ case OP_IdxGE: { /* jump */
}
r.aMem = &aMem[pOp->p3];
#ifdef SQLITE_DEBUG
- { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
+ {
+ int i;
+ for(i=0; i<r.nField; i++){
+ assert( memIsValid(&r.aMem[i]) );
+ REGISTER_TRACE(pOp->p3+i, &aMem[pOp->p3+i]);
+ }
+ }
#endif
res = 0; /* Not needed. Only used to silence a warning. */
rc = sqlite3VdbeIdxKeyCompare(db, pC, &r, &res);
@@ -87528,7 +88381,8 @@ case OP_SqlExec: {
/* Opcode: ParseSchema P1 * * P4 *
**
** Read and parse all entries from the SQLITE_MASTER table of database P1
-** that match the WHERE clause P4.
+** that match the WHERE clause P4. If P4 is a NULL pointer, then the
+** entire schema for P1 is reparsed.
**
** This opcode invokes the parser to create a new virtual machine,
** then runs the new virtual machine. It is thus a re-entrant opcode.
@@ -87552,11 +88406,22 @@ case OP_ParseSchema: {
iDb = pOp->p1;
assert( iDb>=0 && iDb<db->nDb );
assert( DbHasProperty(db, iDb, DB_SchemaLoaded) );
- /* Used to be a conditional */ {
+
+#ifndef SQLITE_OMIT_ALTERTABLE
+ if( pOp->p4.z==0 ){
+ sqlite3SchemaClear(db->aDb[iDb].pSchema);
+ db->mDbFlags &= ~DBFLAG_SchemaKnownOk;
+ rc = sqlite3InitOne(db, iDb, &p->zErrMsg, INITFLAG_AlterTable);
+ db->mDbFlags |= DBFLAG_SchemaChange;
+ p->expired = 0;
+ }else
+#endif
+ {
zMaster = MASTER_NAME;
initData.db = db;
initData.iDb = pOp->p1;
initData.pzErrMsg = &p->zErrMsg;
+ initData.mInitFlags = 0;
zSql = sqlite3MPrintf(db,
"SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
db->aDb[iDb].zDbSName, zMaster, pOp->p4.z);
@@ -87709,11 +88574,11 @@ case OP_RowSetAdd: { /* in1, in2 */
pIn1 = &aMem[pOp->p1];
pIn2 = &aMem[pOp->p2];
assert( (pIn2->flags & MEM_Int)!=0 );
- if( (pIn1->flags & MEM_RowSet)==0 ){
- sqlite3VdbeMemSetRowSet(pIn1);
- if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem;
+ if( (pIn1->flags & MEM_Blob)==0 ){
+ if( sqlite3VdbeMemSetRowSet(pIn1) ) goto no_mem;
}
- sqlite3RowSetInsert(pIn1->u.pRowSet, pIn2->u.i);
+ assert( sqlite3VdbeMemIsRowSet(pIn1) );
+ sqlite3RowSetInsert((RowSet*)pIn1->z, pIn2->u.i);
break;
}
@@ -87729,8 +88594,9 @@ case OP_RowSetRead: { /* jump, in1, out3 */
i64 val;
pIn1 = &aMem[pOp->p1];
- if( (pIn1->flags & MEM_RowSet)==0
- || sqlite3RowSetNext(pIn1->u.pRowSet, &val)==0
+ assert( (pIn1->flags & MEM_Blob)==0 || sqlite3VdbeMemIsRowSet(pIn1) );
+ if( (pIn1->flags & MEM_Blob)==0
+ || sqlite3RowSetNext((RowSet*)pIn1->z, &val)==0
){
/* The boolean index is empty */
sqlite3VdbeMemSetNull(pIn1);
@@ -87779,20 +88645,19 @@ case OP_RowSetTest: { /* jump, in1, in3 */
/* If there is anything other than a rowset object in memory cell P1,
** delete it now and initialize P1 with an empty rowset
*/
- if( (pIn1->flags & MEM_RowSet)==0 ){
- sqlite3VdbeMemSetRowSet(pIn1);
- if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem;
+ if( (pIn1->flags & MEM_Blob)==0 ){
+ if( sqlite3VdbeMemSetRowSet(pIn1) ) goto no_mem;
}
-
+ assert( sqlite3VdbeMemIsRowSet(pIn1) );
assert( pOp->p4type==P4_INT32 );
assert( iSet==-1 || iSet>=0 );
if( iSet ){
- exists = sqlite3RowSetTest(pIn1->u.pRowSet, iSet, pIn3->u.i);
+ exists = sqlite3RowSetTest((RowSet*)pIn1->z, iSet, pIn3->u.i);
VdbeBranchTaken(exists!=0,2);
if( exists ) goto jump_to_p2;
}
if( iSet>=0 ){
- sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i);
+ sqlite3RowSetInsert((RowSet*)pIn1->z, pIn3->u.i);
}
break;
}
@@ -87856,7 +88721,7 @@ case OP_Program: { /* jump */
** of the current program, and the memory required at runtime to execute
** the trigger program. If this trigger has been fired before, then pRt
** is already allocated. Otherwise, it must be initialized. */
- if( (pRt->flags&MEM_Frame)==0 ){
+ if( (pRt->flags&MEM_Blob)==0 ){
/* SubProgram.nMem is set to the number of memory cells used by the
** program stored in SubProgram.aOp. As well as these, one memory
** cell is required for each cursor used by the program. Set local
@@ -87874,8 +88739,10 @@ case OP_Program: { /* jump */
goto no_mem;
}
sqlite3VdbeMemRelease(pRt);
- pRt->flags = MEM_Frame;
- pRt->u.pFrame = pFrame;
+ pRt->flags = MEM_Blob|MEM_Dyn;
+ pRt->z = (char*)pFrame;
+ pRt->n = nByte;
+ pRt->xDel = sqlite3VdbeFrameMemDel;
pFrame->v = p;
pFrame->nChildMem = nMem;
@@ -87891,6 +88758,9 @@ case OP_Program: { /* jump */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
pFrame->anExec = p->anExec;
#endif
+#ifdef SQLITE_DEBUG
+ pFrame->iFrameMagic = SQLITE_FRAME_MAGIC;
+#endif
pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem];
for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){
@@ -87898,7 +88768,8 @@ case OP_Program: { /* jump */
pMem->db = db;
}
}else{
- pFrame = pRt->u.pFrame;
+ pFrame = (VdbeFrame*)pRt->z;
+ assert( pRt->xDel==sqlite3VdbeFrameMemDel );
assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem
|| (pProgram->nCsr==0 && pProgram->nMem+1==pFrame->nChildMem) );
assert( pProgram->nCsr==pFrame->nChildCsr );
@@ -88127,24 +88998,35 @@ case OP_DecrJumpZero: { /* jump, in1 */
}
-/* Opcode: AggStep0 * P2 P3 P4 P5
+/* Opcode: AggStep * P2 P3 P4 P5
** Synopsis: accum=r[P3] step(r[P2@P5])
**
-** Execute the step function for an aggregate. The
-** function has P5 arguments. P4 is a pointer to the FuncDef
-** structure that specifies the function. Register P3 is the
+** Execute the xStep function for an aggregate.
+** The function has P5 arguments. P4 is a pointer to the
+** FuncDef structure that specifies the function. Register P3 is the
** accumulator.
**
** The P5 arguments are taken from register P2 and its
** successors.
*/
-/* Opcode: AggStep * P2 P3 P4 P5
+/* Opcode: AggInverse * P2 P3 P4 P5
+** Synopsis: accum=r[P3] inverse(r[P2@P5])
+**
+** Execute the xInverse function for an aggregate.
+** The function has P5 arguments. P4 is a pointer to the
+** FuncDef structure that specifies the function. Register P3 is the
+** accumulator.
+**
+** The P5 arguments are taken from register P2 and its
+** successors.
+*/
+/* Opcode: AggStep1 P1 P2 P3 P4 P5
** Synopsis: accum=r[P3] step(r[P2@P5])
**
-** Execute the step function for an aggregate. The
-** function has P5 arguments. P4 is a pointer to an sqlite3_context
-** object that is used to run the function. Register P3 is
-** as the accumulator.
+** Execute the xStep (if P1==0) or xInverse (if P1!=0) function for an
+** aggregate. The function has P5 arguments. P4 is a pointer to the
+** FuncDef structure that specifies the function. Register P3 is the
+** accumulator.
**
** The P5 arguments are taken from register P2 and its
** successors.
@@ -88155,7 +89037,8 @@ case OP_DecrJumpZero: { /* jump, in1 */
** sqlite3_context only happens once, instead of on each call to the
** step function.
*/
-case OP_AggStep0: {
+case OP_AggInverse:
+case OP_AggStep: {
int n;
sqlite3_context *pCtx;
@@ -88178,10 +89061,14 @@ case OP_AggStep0: {
pCtx->argc = n;
pOp->p4type = P4_FUNCCTX;
pOp->p4.pCtx = pCtx;
- pOp->opcode = OP_AggStep;
+
+ /* OP_AggInverse must have P1==1 and OP_AggStep must have P1==0 */
+ assert( pOp->p1==(pOp->opcode==OP_AggInverse) );
+
+ pOp->opcode = OP_AggStep1;
/* Fall through into OP_AggStep */
}
-case OP_AggStep: {
+case OP_AggStep1: {
int i;
sqlite3_context *pCtx;
Mem *pMem;
@@ -88190,6 +89077,17 @@ case OP_AggStep: {
pCtx = pOp->p4.pCtx;
pMem = &aMem[pOp->p3];
+#ifdef SQLITE_DEBUG
+ if( pOp->p1 ){
+ /* This is an OP_AggInverse call. Verify that xStep has always
+ ** been called at least once prior to any xInverse call. */
+ assert( pMem->uTemp==0x1122e0e3 );
+ }else{
+ /* This is an OP_AggStep call. Mark it as such. */
+ pMem->uTemp = 0x1122e0e3;
+ }
+#endif
+
/* If this function is inside of a trigger, the register array in aMem[]
** might change from one evaluation to the next. The next block of code
** checks to see if the register array has changed, and if so it
@@ -88210,7 +89108,13 @@ case OP_AggStep: {
assert( pCtx->pOut->flags==MEM_Null );
assert( pCtx->isError==0 );
assert( pCtx->skipFlag==0 );
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( pOp->p1 ){
+ (pCtx->pFunc->xInverse)(pCtx,pCtx->argc,pCtx->argv);
+ }else
+#endif
(pCtx->pFunc->xSFunc)(pCtx,pCtx->argc,pCtx->argv); /* IMP: R-24505-23230 */
+
if( pCtx->isError ){
if( pCtx->isError>0 ){
sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut));
@@ -88235,22 +89139,46 @@ case OP_AggStep: {
/* Opcode: AggFinal P1 P2 * P4 *
** Synopsis: accum=r[P1] N=P2
**
-** Execute the finalizer function for an aggregate. P1 is
-** the memory location that is the accumulator for the aggregate.
+** P1 is the memory location that is the accumulator for an aggregate
+** or window function. Execute the finalizer function
+** for an aggregate and store the result in P1.
**
** P2 is the number of arguments that the step function takes and
** P4 is a pointer to the FuncDef for this function. The P2
** argument is not used by this opcode. It is only there to disambiguate
** functions that can take varying numbers of arguments. The
-** P4 argument is only needed for the degenerate case where
+** P4 argument is only needed for the case where
** the step function was not previously called.
*/
+/* Opcode: AggValue * P2 P3 P4 *
+** Synopsis: r[P3]=value N=P2
+**
+** Invoke the xValue() function and store the result in register P3.
+**
+** P2 is the number of arguments that the step function takes and
+** P4 is a pointer to the FuncDef for this function. The P2
+** argument is not used by this opcode. It is only there to disambiguate
+** functions that can take varying numbers of arguments. The
+** P4 argument is only needed for the case where
+** the step function was not previously called.
+*/
+case OP_AggValue:
case OP_AggFinal: {
Mem *pMem;
assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) );
+ assert( pOp->p3==0 || pOp->opcode==OP_AggValue );
pMem = &aMem[pOp->p1];
assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
- rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc);
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( pOp->p3 ){
+ rc = sqlite3VdbeMemAggValue(pMem, &aMem[pOp->p3], pOp->p4.pFunc);
+ pMem = &aMem[pOp->p3];
+ }else
+#endif
+ {
+ rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc);
+ }
+
if( rc ){
sqlite3VdbeError(p, "%s", sqlite3_value_text(pMem));
goto abort_due_to_error;
@@ -88445,7 +89373,7 @@ case OP_IncrVacuum: { /* jump */
}
#endif
-/* Opcode: Expire P1 * * * *
+/* Opcode: Expire P1 P2 * * *
**
** Cause precompiled statements to expire. When an expired statement
** is executed using sqlite3_step() it will either automatically
@@ -88454,12 +89382,19 @@ case OP_IncrVacuum: { /* jump */
**
** If P1 is 0, then all SQL statements become expired. If P1 is non-zero,
** then only the currently executing statement is expired.
+**
+** If P2 is 0, then SQL statements are expired immediately. If P2 is 1,
+** then running SQL statements are allowed to continue to run to completion.
+** The P2==1 case occurs when a CREATE INDEX or similar schema change happens
+** that might help the statement run faster but which does not affect the
+** correctness of operation.
*/
case OP_Expire: {
+ assert( pOp->p2==0 || pOp->p2==1 );
if( !pOp->p1 ){
- sqlite3ExpirePreparedStatements(db);
+ sqlite3ExpirePreparedStatements(db, pOp->p2);
}else{
- p->expired = 1;
+ p->expired = pOp->p2+1;
}
break;
}
@@ -88783,7 +89718,10 @@ case OP_VNext: { /* jump */
case OP_VRename: {
sqlite3_vtab *pVtab;
Mem *pName;
-
+ int isLegacy;
+
+ isLegacy = (db->flags & SQLITE_LegacyAlter);
+ db->flags |= SQLITE_LegacyAlter;
pVtab = pOp->p4.pVtab->pVtab;
pName = &aMem[pOp->p1];
assert( pVtab->pModule->xRename );
@@ -88797,6 +89735,7 @@ case OP_VRename: {
rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8);
if( rc ) goto abort_due_to_error;
rc = pVtab->pModule->xRename(pVtab, pName->z);
+ if( isLegacy==0 ) db->flags &= ~SQLITE_LegacyAlter;
sqlite3VtabImportErrmsg(p, pVtab);
p->expired = 0;
if( rc ) goto abort_due_to_error;
@@ -88845,6 +89784,7 @@ case OP_VUpdate: {
|| pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace
);
assert( p->readOnly==0 );
+ if( db->mallocFailed ) goto no_mem;
sqlite3VdbeIncrWriteCounter(p, 0);
pVtab = pOp->p4.pVtab->pVtab;
if( pVtab==0 || NEVER(pVtab->pModule==0) ){
@@ -88966,8 +89906,8 @@ case OP_MaxPgcnt: { /* out2 */
**
** See also: Function0, AggStep, AggFinal
*/
-case OP_PureFunc0:
-case OP_Function0: {
+case OP_PureFunc0: /* group */
+case OP_Function0: { /* group */
int n;
sqlite3_context *pCtx;
@@ -88991,8 +89931,8 @@ case OP_Function0: {
pOp->opcode += 2;
/* Fall through into OP_Function */
}
-case OP_PureFunc:
-case OP_Function: {
+case OP_PureFunc: /* group */
+case OP_Function: { /* group */
int i;
sqlite3_context *pCtx;
@@ -91917,7 +92857,11 @@ static int vdbeMergeEngineInit(
){
int rc = SQLITE_OK; /* Return code */
int i; /* For looping over PmaReader objects */
- int nTree = pMerger->nTree;
+ int nTree; /* Number of subtrees to merge */
+
+ /* Failure to allocate the merge would have been detected prior to
+ ** invoking this routine */
+ assert( pMerger!=0 );
/* eMode is always INCRINIT_NORMAL in single-threaded mode */
assert( SQLITE_MAX_WORKER_THREADS>0 || eMode==INCRINIT_NORMAL );
@@ -91926,6 +92870,7 @@ static int vdbeMergeEngineInit(
assert( pMerger->pTask==0 );
pMerger->pTask = pTask;
+ nTree = pMerger->nTree;
for(i=0; i<nTree; i++){
if( SQLITE_MAX_WORKER_THREADS>0 && eMode==INCRINIT_ROOT ){
/* PmaReaders should be normally initialized in order, as if they are
@@ -93054,6 +93999,14 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
}else if( pExpr->x.pList ){
if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
}
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( !ExprHasProperty(pExpr, EP_Reduced) && pExpr->pWin ){
+ Window *pWin = pExpr->pWin;
+ if( sqlite3WalkExprList(pWalker, pWin->pPartition) ) return WRC_Abort;
+ if( sqlite3WalkExprList(pWalker, pWin->pOrderBy) ) return WRC_Abort;
+ if( sqlite3WalkExpr(pWalker, pWin->pFilter) ) return WRC_Abort;
+ }
+#endif
}
break;
}
@@ -93426,6 +94379,9 @@ static int lookupName(
if( sqlite3StrICmp(zTabName, zTab)!=0 ){
continue;
}
+ if( IN_RENAME_OBJECT && pItem->zAlias ){
+ sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->pTab);
+ }
}
if( 0==(cntTab++) ){
pMatch = pItem;
@@ -93511,9 +94467,15 @@ static int lookupName(
#ifndef SQLITE_OMIT_UPSERT
if( pExpr->iTable==2 ){
testcase( iCol==(-1) );
- pExpr->iTable = pNC->uNC.pUpsert->regData + iCol;
- eNewExprOp = TK_REGISTER;
- ExprSetProperty(pExpr, EP_Alias);
+ if( IN_RENAME_OBJECT ){
+ pExpr->iColumn = iCol;
+ pExpr->pTab = pTab;
+ eNewExprOp = TK_COLUMN;
+ }else{
+ pExpr->iTable = pNC->uNC.pUpsert->regData + iCol;
+ eNewExprOp = TK_REGISTER;
+ ExprSetProperty(pExpr, EP_Alias);
+ }
}else
#endif /* SQLITE_OMIT_UPSERT */
{
@@ -93598,6 +94560,9 @@ static int lookupName(
cnt = 1;
pMatch = 0;
assert( zTab==0 && zDb==0 );
+ if( IN_RENAME_OBJECT ){
+ sqlite3RenameTokenRemap(pParse, 0, (void*)pExpr);
+ }
goto lookupname_end;
}
}
@@ -93825,17 +94790,24 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
zTable = 0;
zColumn = pExpr->u.zToken;
}else{
+ Expr *pLeft = pExpr->pLeft;
notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr);
pRight = pExpr->pRight;
if( pRight->op==TK_ID ){
zDb = 0;
- zTable = pExpr->pLeft->u.zToken;
- zColumn = pRight->u.zToken;
}else{
assert( pRight->op==TK_DOT );
- zDb = pExpr->pLeft->u.zToken;
- zTable = pRight->pLeft->u.zToken;
- zColumn = pRight->pRight->u.zToken;
+ zDb = pLeft->u.zToken;
+ pLeft = pRight->pLeft;
+ pRight = pRight->pRight;
+ }
+ zTable = pLeft->u.zToken;
+ zColumn = pRight->u.zToken;
+ if( IN_RENAME_OBJECT ){
+ sqlite3RenameTokenRemap(pParse, (void*)pExpr, (void*)pRight);
+ }
+ if( IN_RENAME_OBJECT ){
+ sqlite3RenameTokenRemap(pParse, (void*)&pExpr->pTab, (void*)pLeft);
}
}
return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);
@@ -93918,40 +94890,95 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
NC_IdxExpr|NC_PartIdx);
}
}
- if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){
- sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
- pNC->nErr++;
- is_agg = 0;
- }else if( no_such_func && pParse->db->init.busy==0
+
+ if( 0==IN_RENAME_OBJECT ){
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ assert( is_agg==0 || (pDef->funcFlags & SQLITE_FUNC_MINMAX)
+ || (pDef->xValue==0 && pDef->xInverse==0)
+ || (pDef->xValue && pDef->xInverse && pDef->xSFunc && pDef->xFinalize)
+ );
+ if( pDef && pDef->xValue==0 && pExpr->pWin ){
+ sqlite3ErrorMsg(pParse,
+ "%.*s() may not be used as a window function", nId, zId
+ );
+ pNC->nErr++;
+ }else if(
+ (is_agg && (pNC->ncFlags & NC_AllowAgg)==0)
+ || (is_agg && (pDef->funcFlags & SQLITE_FUNC_WINDOW) && !pExpr->pWin)
+ || (is_agg && pExpr->pWin && (pNC->ncFlags & NC_AllowWin)==0)
+ ){
+ const char *zType;
+ if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->pWin ){
+ zType = "window";
+ }else{
+ zType = "aggregate";
+ }
+ sqlite3ErrorMsg(pParse, "misuse of %s function %.*s()",zType,nId,zId);
+ pNC->nErr++;
+ is_agg = 0;
+ }
+#else
+ if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) ){
+ sqlite3ErrorMsg(pParse,"misuse of aggregate function %.*s()",nId,zId);
+ pNC->nErr++;
+ is_agg = 0;
+ }
+#endif
+ else if( no_such_func && pParse->db->init.busy==0
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
- && pParse->explain==0
+ && pParse->explain==0
#endif
- ){
- sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
- pNC->nErr++;
- }else if( wrong_num_args ){
- sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
- nId, zId);
- pNC->nErr++;
- }
- if( is_agg ) pNC->ncFlags &= ~NC_AllowAgg;
+ ){
+ sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
+ pNC->nErr++;
+ }else if( wrong_num_args ){
+ sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
+ nId, zId);
+ pNC->nErr++;
+ }
+ if( is_agg ){
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ pNC->ncFlags &= ~(pExpr->pWin ? NC_AllowWin : NC_AllowAgg);
+#else
+ pNC->ncFlags &= ~NC_AllowAgg;
+#endif
+ }
+ }
sqlite3WalkExprList(pWalker, pList);
if( is_agg ){
- NameContext *pNC2 = pNC;
- pExpr->op = TK_AGG_FUNCTION;
- pExpr->op2 = 0;
- while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){
- pExpr->op2++;
- pNC2 = pNC2->pNext;
- }
- assert( pDef!=0 );
- if( pNC2 ){
- assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg );
- testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 );
- pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX);
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( pExpr->pWin ){
+ Select *pSel = pNC->pWinSelect;
+ sqlite3WalkExprList(pWalker, pExpr->pWin->pPartition);
+ sqlite3WalkExprList(pWalker, pExpr->pWin->pOrderBy);
+ sqlite3WalkExpr(pWalker, pExpr->pWin->pFilter);
+ sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->pWin, pDef);
+ if( 0==pSel->pWin
+ || 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->pWin)
+ ){
+ pExpr->pWin->pNextWin = pSel->pWin;
+ pSel->pWin = pExpr->pWin;
+ }
+ pNC->ncFlags |= NC_AllowWin;
+ }else
+#endif /* SQLITE_OMIT_WINDOWFUNC */
+ {
+ NameContext *pNC2 = pNC;
+ pExpr->op = TK_AGG_FUNCTION;
+ pExpr->op2 = 0;
+ while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){
+ pExpr->op2++;
+ pNC2 = pNC2->pNext;
+ }
+ assert( pDef!=0 );
+ if( pNC2 ){
+ assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg );
+ testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 );
+ pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX);
+ }
+ pNC->ncFlags |= NC_AllowAgg;
}
- pNC->ncFlags |= NC_AllowAgg;
}
/* FIX ME: Compute pExpr->affinity based on the expected return
** type of the function
@@ -94352,6 +95379,19 @@ static int resolveOrderGroupBy(
}
for(j=0; j<pSelect->pEList->nExpr; j++){
if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( pE->pWin ){
+ /* Since this window function is being changed into a reference
+ ** to the same window function the result set, remove the instance
+ ** of this window function from the Select.pWin list. */
+ Window **pp;
+ for(pp=&pSelect->pWin; *pp; pp=&(*pp)->pNextWin){
+ if( *pp==pE->pWin ){
+ *pp = (*pp)->pNextWin;
+ }
+ }
+ }
+#endif
pItem->u.x.iOrderByCol = j+1;
}
}
@@ -94408,6 +95448,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
*/
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
+ sNC.pWinSelect = p;
if( sqlite3ResolveExprNames(&sNC, p->pLimit) ){
return WRC_Abort;
}
@@ -94456,12 +95497,13 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
/* Set up the local name-context to pass to sqlite3ResolveExprNames() to
** resolve the result-set expression list.
*/
- sNC.ncFlags = NC_AllowAgg;
+ sNC.ncFlags = NC_AllowAgg|NC_AllowWin;
sNC.pSrcList = p->pSrc;
sNC.pNext = pOuterNC;
/* Resolve names in the result set. */
if( sqlite3ResolveExprListNames(&sNC, p->pEList) ) return WRC_Abort;
+ sNC.ncFlags &= ~NC_AllowWin;
/* If there are no aggregate functions in the result-set, and no GROUP BY
** expression, do not allow aggregates in any of the other expressions.
@@ -94510,7 +95552,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
** outer queries
*/
sNC.pNext = 0;
- sNC.ncFlags |= NC_AllowAgg;
+ sNC.ncFlags |= NC_AllowAgg|NC_AllowWin;
/* If this is a converted compound query, move the ORDER BY clause from
** the sub-query back to the parent query. At this point each term
@@ -94541,6 +95583,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
if( db->mallocFailed ){
return WRC_Abort;
}
+ sNC.ncFlags &= ~NC_AllowWin;
/* Resolve the GROUP BY clause. At the same time, make sure
** the GROUP BY clause does not contain aggregate functions.
@@ -94889,14 +95932,6 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
while( p ){
int op = p->op;
if( p->flags & EP_Generic ) break;
- if( op==TK_CAST || op==TK_UPLUS ){
- p = p->pLeft;
- continue;
- }
- if( op==TK_COLLATE || (op==TK_REGISTER && p->op2==TK_COLLATE) ){
- pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
- break;
- }
if( (op==TK_AGG_COLUMN || op==TK_COLUMN
|| op==TK_REGISTER || op==TK_TRIGGER)
&& p->pTab!=0
@@ -94910,6 +95945,14 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
}
break;
}
+ if( op==TK_CAST || op==TK_UPLUS ){
+ p = p->pLeft;
+ continue;
+ }
+ if( op==TK_COLLATE || (op==TK_REGISTER && p->op2==TK_COLLATE) ){
+ pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
+ break;
+ }
if( p->flags & EP_Collate ){
if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){
p = p->pLeft;
@@ -95329,7 +96372,6 @@ static void codeVectorCompare(
Expr *pL, *pR;
int r1, r2;
assert( i>=0 && i<nLeft );
- if( i>0 ) sqlite3ExprCachePush(pParse);
r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, &regFree1);
r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, &regFree2);
codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5);
@@ -95341,7 +96383,6 @@ static void codeVectorCompare(
testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
sqlite3ReleaseTempReg(pParse, regFree1);
sqlite3ReleaseTempReg(pParse, regFree2);
- if( i>0 ) sqlite3ExprCachePop(pParse);
if( i==nLeft-1 ){
break;
}
@@ -95689,7 +96730,12 @@ SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3 *db, Expr *pLeft, Expr *pRight){
** Construct a new expression node for a function with multiple
** arguments.
*/
-SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){
+SQLITE_PRIVATE Expr *sqlite3ExprFunction(
+ Parse *pParse, /* Parsing context */
+ ExprList *pList, /* Argument list */
+ Token *pToken, /* Name of the function */
+ int eDistinct /* SF_Distinct or SF_ALL or 0 */
+){
Expr *pNew;
sqlite3 *db = pParse->db;
assert( pToken );
@@ -95698,10 +96744,14 @@ SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *
sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */
return 0;
}
+ if( pList && pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
+ sqlite3ErrorMsg(pParse, "too many arguments on function %T", pToken);
+ }
pNew->x.pList = pList;
ExprSetProperty(pNew, EP_HasFunc);
assert( !ExprHasProperty(pNew, EP_xIsSelect) );
sqlite3ExprSetHeightAndFlags(pParse, pNew);
+ if( eDistinct==SF_Distinct ) ExprSetProperty(pNew, EP_Distinct);
return pNew;
}
@@ -95811,6 +96861,9 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
}else{
sqlite3ExprListDelete(db, p->x.pList);
}
+ if( !ExprHasProperty(p, EP_Reduced) ){
+ sqlite3WindowDelete(db, p->pWin);
+ }
}
if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken);
if( !ExprHasProperty(p, EP_Static) ){
@@ -95859,7 +96912,7 @@ static int exprStructSize(Expr *p){
** Note that with flags==EXPRDUP_REDUCE, this routines works on full-size
** (unreduced) Expr objects as they or originally constructed by the parser.
** During expression analysis, extra information is computed and moved into
-** later parts of teh Expr object and that extra information might get chopped
+** later parts of the Expr object and that extra information might get chopped
** off if the expression is reduced. Note also that it does not work to
** make an EXPRDUP_REDUCE copy of a reduced expression. It is only legal
** to reduce a pristine expression tree from the parser. The implementation
@@ -95871,7 +96924,11 @@ static int dupedExprStructSize(Expr *p, int flags){
assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */
assert( EXPR_FULLSIZE<=0xfff );
assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 );
- if( 0==flags || p->op==TK_SELECT_COLUMN ){
+ if( 0==flags || p->op==TK_SELECT_COLUMN
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ || p->pWin
+#endif
+ ){
nSize = EXPR_FULLSIZE;
}else{
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
@@ -95999,18 +97056,22 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
}
/* Fill in pNew->pLeft and pNew->pRight. */
+ zAlloc += dupedExprNodeSize(p, dupFlags);
if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){
- zAlloc += dupedExprNodeSize(p, dupFlags);
if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){
pNew->pLeft = p->pLeft ?
exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0;
pNew->pRight = p->pRight ?
exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0;
}
- if( pzBuffer ){
- *pzBuffer = zAlloc;
- }
}else{
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( ExprHasProperty(p, EP_Reduced|EP_TokenOnly) ){
+ pNew->pWin = 0;
+ }else{
+ pNew->pWin = sqlite3WindowDup(db, pNew, p->pWin);
+ }
+#endif /* SQLITE_OMIT_WINDOWFUNC */
if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
if( pNew->op==TK_SELECT_COLUMN ){
pNew->pLeft = p->pLeft;
@@ -96022,6 +97083,9 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
}
}
+ if( pzBuffer ){
+ *pzBuffer = zAlloc;
+ }
}
return pNew;
}
@@ -96217,7 +97281,11 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *pDup, int flags){
pNew->addrOpenEphm[1] = -1;
pNew->nSelectRow = p->nSelectRow;
pNew->pWith = withDup(db, p->pWith);
- sqlite3SelectSetName(pNew, p->zSelName);
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ pNew->pWin = 0;
+ pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn);
+#endif
+ pNew->selId = p->selId;
*pp = pNew;
pp = &pNew->pPrior;
pNext = pNew;
@@ -96389,6 +97457,9 @@ SQLITE_PRIVATE void sqlite3ExprListSetName(
assert( pItem->zName==0 );
pItem->zName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n);
if( dequote ) sqlite3Dequote(pItem->zName);
+ if( IN_RENAME_OBJECT ){
+ sqlite3RenameTokenMap(pParse, (void*)pItem->zName, pName);
+ }
}
}
@@ -96569,6 +97640,9 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_COLUMN );
testcase( pExpr->op==TK_AGG_FUNCTION );
testcase( pExpr->op==TK_AGG_COLUMN );
+ if( ExprHasProperty(pExpr, EP_FixedCol) && pWalker->eCode!=2 ){
+ return WRC_Continue;
+ }
if( pWalker->eCode==3 && pExpr->iTable==pWalker->u.iCur ){
return WRC_Continue;
}
@@ -96624,10 +97698,17 @@ SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr *p){
}
/*
-** Walk an expression tree. Return non-zero if the expression is constant
-** that does no originate from the ON or USING clauses of a join.
-** Return 0 if it involves variables or function calls or terms from
-** an ON or USING clause.
+** Walk an expression tree. Return non-zero if
+**
+** (1) the expression is constant, and
+** (2) the expression does originate in the ON or USING clause
+** of a LEFT JOIN, and
+** (3) the expression does not contain any EP_FixedCol TK_COLUMN
+** operands created by the constant propagation optimization.
+**
+** When this routine returns true, it indicates that the expression
+** can be added to the pParse->pConstExpr list and evaluated once when
+** the prepared statement starts up. See sqlite3ExprCodeAtInit().
*/
SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr *p){
return exprIsConst(p, 2, 0);
@@ -96657,7 +97738,7 @@ static int exprNodeIsConstantOrGroupBy(Walker *pWalker, Expr *pExpr){
Expr *p = pGroupBy->a[i].pExpr;
if( sqlite3ExprCompare(0, pExpr, p, -1)<2 ){
CollSeq *pColl = sqlite3ExprNNCollSeq(pWalker->pParse, p);
- if( sqlite3_stricmp("BINARY", pColl->zName)==0 ){
+ if( sqlite3IsBinary(pColl) ){
return WRC_Prune;
}
}
@@ -97079,7 +98160,8 @@ SQLITE_PRIVATE int sqlite3FindInIndex(
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
eType = IN_INDEX_ROWID;
-
+ ExplainQueryPlan((pParse, 0,
+ "USING ROWID SEARCH ON TABLE %s FOR IN-OPERATOR",pTab->zName));
sqlite3VdbeJumpHere(v, iAddr);
}else{
Index *pIdx; /* Iterator variable */
@@ -97338,7 +98420,6 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
int rReg = 0; /* Register storing resulting */
Vdbe *v = sqlite3GetVdbe(pParse);
if( NEVER(v==0) ) return 0;
- sqlite3ExprCachePush(pParse);
/* The evaluation of the IN/EXISTS/SELECT must be repeated every time it
** is encountered if any of the following is true:
@@ -97474,7 +98555,6 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3);
}else{
sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
- sqlite3ExprCacheAffinityChange(pParse, r3, 1);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pExpr->iTable, r2, r3, 1);
}
}
@@ -97555,7 +98635,6 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
if( jmpIfDynamic>=0 ){
sqlite3VdbeJumpHere(v, jmpIfDynamic);
}
- sqlite3ExprCachePop(pParse);
return rReg;
}
@@ -97674,7 +98753,6 @@ static void sqlite3ExprCodeIN(
** aiMap[] array contains a mapping from the original LHS field order to
** the field order that matches the RHS index.
*/
- sqlite3ExprCachePush(pParse);
rLhsOrig = exprCodeVector(pParse, pLeft, &iDummy);
for(i=0; i<nVector && aiMap[i]==i; i++){} /* Are LHS fields reordered? */
if( i==nVector ){
@@ -97833,7 +98911,6 @@ static void sqlite3ExprCodeIN(
sqlite3ExprCodeIN_finished:
if( rLhs!=rLhsOrig ) sqlite3ReleaseTempReg(pParse, rLhs);
- sqlite3ExprCachePop(pParse);
VdbeComment((v, "end IN expr"));
sqlite3ExprCodeIN_oom_error:
sqlite3DbFree(pParse->db, aiMap);
@@ -97901,145 +98978,6 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
}
}
-/*
-** Erase column-cache entry number i
-*/
-static void cacheEntryClear(Parse *pParse, int i){
- if( pParse->aColCache[i].tempReg ){
- if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){
- pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg;
- }
- }
- pParse->nColCache--;
- if( i<pParse->nColCache ){
- pParse->aColCache[i] = pParse->aColCache[pParse->nColCache];
- }
-}
-
-
-/*
-** Record in the column cache that a particular column from a
-** particular table is stored in a particular register.
-*/
-SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
- int i;
- int minLru;
- int idxLru;
- struct yColCache *p;
-
- /* Unless an error has occurred, register numbers are always positive. */
- assert( iReg>0 || pParse->nErr || pParse->db->mallocFailed );
- assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */
-
- /* The SQLITE_ColumnCache flag disables the column cache. This is used
- ** for testing only - to verify that SQLite always gets the same answer
- ** with and without the column cache.
- */
- if( OptimizationDisabled(pParse->db, SQLITE_ColumnCache) ) return;
-
- /* First replace any existing entry.
- **
- ** Actually, the way the column cache is currently used, we are guaranteed
- ** that the object will never already be in cache. Verify this guarantee.
- */
-#ifndef NDEBUG
- for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
- assert( p->iTable!=iTab || p->iColumn!=iCol );
- }
-#endif
-
- /* If the cache is already full, delete the least recently used entry */
- if( pParse->nColCache>=SQLITE_N_COLCACHE ){
- minLru = 0x7fffffff;
- idxLru = -1;
- for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
- if( p->lru<minLru ){
- idxLru = i;
- minLru = p->lru;
- }
- }
- p = &pParse->aColCache[idxLru];
- }else{
- p = &pParse->aColCache[pParse->nColCache++];
- }
-
- /* Add the new entry to the end of the cache */
- p->iLevel = pParse->iCacheLevel;
- p->iTable = iTab;
- p->iColumn = iCol;
- p->iReg = iReg;
- p->tempReg = 0;
- p->lru = pParse->iCacheCnt++;
-}
-
-/*
-** Indicate that registers between iReg..iReg+nReg-1 are being overwritten.
-** Purge the range of registers from the column cache.
-*/
-SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){
- int i = 0;
- while( i<pParse->nColCache ){
- struct yColCache *p = &pParse->aColCache[i];
- if( p->iReg >= iReg && p->iReg < iReg+nReg ){
- cacheEntryClear(pParse, i);
- }else{
- i++;
- }
- }
-}
-
-/*
-** Remember the current column cache context. Any new entries added
-** added to the column cache after this call are removed when the
-** corresponding pop occurs.
-*/
-SQLITE_PRIVATE void sqlite3ExprCachePush(Parse *pParse){
- pParse->iCacheLevel++;
-#ifdef SQLITE_DEBUG
- if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
- printf("PUSH to %d\n", pParse->iCacheLevel);
- }
-#endif
-}
-
-/*
-** Remove from the column cache any entries that were added since the
-** the previous sqlite3ExprCachePush operation. In other words, restore
-** the cache to the state it was in prior the most recent Push.
-*/
-SQLITE_PRIVATE void sqlite3ExprCachePop(Parse *pParse){
- int i = 0;
- assert( pParse->iCacheLevel>=1 );
- pParse->iCacheLevel--;
-#ifdef SQLITE_DEBUG
- if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
- printf("POP to %d\n", pParse->iCacheLevel);
- }
-#endif
- while( i<pParse->nColCache ){
- if( pParse->aColCache[i].iLevel>pParse->iCacheLevel ){
- cacheEntryClear(pParse, i);
- }else{
- i++;
- }
- }
-}
-
-/*
-** When a cached column is reused, make sure that its register is
-** no longer available as a temp register. ticket #3879: that same
-** register might be in the cache in multiple places, so be sure to
-** get them all.
-*/
-static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){
- int i;
- struct yColCache *p;
- for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
- if( p->iReg==iReg ){
- p->tempReg = 0;
- }
- }
-}
/* Generate code that will load into register regOut a value that is
** appropriate for the iIdxCol-th column of index pIdx.
@@ -98095,12 +99033,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(
/*
** Generate code that will extract the iColumn-th column from
-** table pTab and store the column value in a register.
-**
-** An effort is made to store the column value in register iReg. This
-** is not garanteeed for GetColumn() - the result can be stored in
-** any register. But the result is guaranteed to land in register iReg
-** for GetColumnToReg().
+** table pTab and store the column value in register iReg.
**
** There must be an open cursor to pTab in iTable when this routine
** is called. If iColumn<0 then code is generated that extracts the rowid.
@@ -98114,96 +99047,23 @@ SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(
u8 p5 /* P5 value for OP_Column + FLAGS */
){
Vdbe *v = pParse->pVdbe;
- int i;
- struct yColCache *p;
-
- for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
- if( p->iTable==iTable && p->iColumn==iColumn ){
- p->lru = pParse->iCacheCnt++;
- sqlite3ExprCachePinRegister(pParse, p->iReg);
- return p->iReg;
- }
- }
assert( v!=0 );
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg);
if( p5 ){
sqlite3VdbeChangeP5(v, p5);
- }else{
- sqlite3ExprCacheStore(pParse, iTable, iColumn, iReg);
}
return iReg;
}
-SQLITE_PRIVATE void sqlite3ExprCodeGetColumnToReg(
- Parse *pParse, /* Parsing and code generating context */
- Table *pTab, /* Description of the table we are reading from */
- int iColumn, /* Index of the table column */
- int iTable, /* The cursor pointing to the table */
- int iReg /* Store results here */
-){
- int r1 = sqlite3ExprCodeGetColumn(pParse, pTab, iColumn, iTable, iReg, 0);
- if( r1!=iReg ) sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, r1, iReg);
-}
-
-
-/*
-** Clear all column cache entries.
-*/
-SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse *pParse){
- int i;
-
-#ifdef SQLITE_DEBUG
- if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
- printf("CLEAR\n");
- }
-#endif
- for(i=0; i<pParse->nColCache; i++){
- if( pParse->aColCache[i].tempReg
- && pParse->nTempReg<ArraySize(pParse->aTempReg)
- ){
- pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg;
- }
- }
- pParse->nColCache = 0;
-}
-
-/*
-** Record the fact that an affinity change has occurred on iCount
-** registers starting with iStart.
-*/
-SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){
- sqlite3ExprCacheRemove(pParse, iStart, iCount);
-}
/*
** Generate code to move content from registers iFrom...iFrom+nReg-1
-** over to iTo..iTo+nReg-1. Keep the column cache up-to-date.
+** over to iTo..iTo+nReg-1.
*/
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo );
sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg);
- sqlite3ExprCacheRemove(pParse, iFrom, nReg);
}
-#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
-/*
-** Return true if any register in the range iFrom..iTo (inclusive)
-** is used as part of the column cache.
-**
-** This routine is used within assert() and testcase() macros only
-** and does not appear in a normal build.
-*/
-static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
- int i;
- struct yColCache *p;
- for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
- int r = p->iReg;
- if( r>=iFrom && r<=iTo ) return 1; /*NO_TEST*/
- }
- return 0;
-}
-#endif /* SQLITE_DEBUG || SQLITE_COVERAGE_TEST */
-
-
/*
** Convert a scalar expression node to a TK_REGISTER referencing
** register iReg. The caller must ensure that iReg already contains
@@ -98301,6 +99161,28 @@ expr_code_doover:
}
case TK_COLUMN: {
int iTab = pExpr->iTable;
+ if( ExprHasProperty(pExpr, EP_FixedCol) ){
+ /* This COLUMN expression is really a constant due to WHERE clause
+ ** constraints, and that constant is coded by the pExpr->pLeft
+ ** expresssion. However, make sure the constant has the correct
+ ** datatype by applying the Affinity of the table column to the
+ ** constant.
+ */
+ int iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target);
+ int aff = sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn);
+ if( aff!=SQLITE_AFF_BLOB ){
+ static const char zAff[] = "B\000C\000D\000E";
+ assert( SQLITE_AFF_BLOB=='A' );
+ assert( SQLITE_AFF_TEXT=='B' );
+ if( iReg!=target ){
+ sqlite3VdbeAddOp2(v, OP_SCopy, iReg, target);
+ iReg = target;
+ }
+ sqlite3VdbeAddOp4(v, OP_Affinity, iReg, 1, 0,
+ &zAff[(aff-'B')*2], P4_STATIC);
+ }
+ return iReg;
+ }
if( iTab<0 ){
if( pParse->iSelfTab<0 ){
/* Generating CHECK constraints or inserting into partial index */
@@ -98381,8 +99263,6 @@ expr_code_doover:
}
sqlite3VdbeAddOp2(v, OP_Cast, target,
sqlite3AffinityType(pExpr->u.zToken, 0));
- testcase( usedAsColumnCache(pParse, inReg, inReg) );
- sqlite3ExprCacheAffinityChange(pParse, inReg, 1);
return inReg;
}
#endif /* SQLITE_OMIT_CAST */
@@ -98526,6 +99406,12 @@ expr_code_doover:
u8 enc = ENC(db); /* The text encoding used by this database */
CollSeq *pColl = 0; /* A collating sequence */
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) && pExpr->pWin ){
+ return pExpr->pWin->regResult;
+ }
+#endif
+
if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){
/* SQL functions can be expensive. So try to move constant functions
** out of the inner loop, even if that means an extra OP_Copy. */
@@ -98562,10 +99448,7 @@ expr_code_doover:
for(i=1; i<nFarg; i++){
sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce);
VdbeCoverage(v);
- sqlite3ExprCacheRemove(pParse, target, 1);
- sqlite3ExprCachePush(pParse);
sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target);
- sqlite3ExprCachePop(pParse);
}
sqlite3VdbeResolveLabel(v, endCoalesce);
break;
@@ -98631,10 +99514,8 @@ expr_code_doover:
}
}
- sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */
sqlite3ExprCodeExprList(pParse, pFarg, r1, 0,
SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR);
- sqlite3ExprCachePop(pParse); /* Ticket 2ea2425d34be */
}else{
r1 = 0;
}
@@ -98651,7 +99532,7 @@ expr_code_doover:
** "glob(B,A). We want to use the A in "A glob B" to test
** for function overloading. But we use the B term in "glob(B,A)".
*/
- if( nFarg>=2 && (pExpr->flags & EP_InfixFunc) ){
+ if( nFarg>=2 && ExprHasProperty(pExpr, EP_InfixFunc) ){
pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[1].pExpr);
}else if( nFarg>0 ){
pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr);
@@ -98807,9 +99688,7 @@ expr_code_doover:
case TK_IF_NULL_ROW: {
int addrINR;
addrINR = sqlite3VdbeAddOp1(v, OP_IfNullRow, pExpr->iTable);
- sqlite3ExprCachePush(pParse);
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
- sqlite3ExprCachePop(pParse);
sqlite3VdbeJumpHere(v, addrINR);
sqlite3VdbeChangeP3(v, addrINR, inReg);
break;
@@ -98846,7 +99725,6 @@ expr_code_doover:
Expr opCompare; /* The X==Ei expression */
Expr *pX; /* The X expression */
Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */
- VVA_ONLY( int iCacheLevel = pParse->iCacheLevel; )
assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList );
assert(pExpr->x.pList->nExpr > 0);
@@ -98870,7 +99748,6 @@ expr_code_doover:
regFree1 = 0;
}
for(i=0; i<nExpr-1; i=i+2){
- sqlite3ExprCachePush(pParse);
if( pX ){
assert( pTest!=0 );
opCompare.pRight = aListelem[i].pExpr;
@@ -98883,18 +99760,13 @@ expr_code_doover:
testcase( aListelem[i+1].pExpr->op==TK_COLUMN );
sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target);
sqlite3VdbeGoto(v, endLabel);
- sqlite3ExprCachePop(pParse);
sqlite3VdbeResolveLabel(v, nextCase);
}
if( (nExpr&1)!=0 ){
- sqlite3ExprCachePush(pParse);
sqlite3ExprCode(pParse, pEList->a[nExpr-1].pExpr, target);
- sqlite3ExprCachePop(pParse);
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
}
- assert( pParse->db->mallocFailed || pParse->nErr>0
- || pParse->iCacheLevel==iCacheLevel );
sqlite3VdbeResolveLabel(v, endLabel);
break;
}
@@ -99044,7 +99916,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse *pParse, Expr *pExpr, int target){
** might choose to code the expression at initialization time.
*/
SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){
- if( pParse->okConstFactor && sqlite3ExprIsConstant(pExpr) ){
+ if( pParse->okConstFactor && sqlite3ExprIsConstantNotJoin(pExpr) ){
sqlite3ExprCodeAtInit(pParse, pExpr, target);
}else{
sqlite3ExprCode(pParse, pExpr, target);
@@ -99126,7 +99998,9 @@ SQLITE_PRIVATE int sqlite3ExprCodeExprList(
}else{
sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i);
}
- }else if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){
+ }else if( (flags & SQLITE_ECEL_FACTOR)!=0
+ && sqlite3ExprIsConstantNotJoin(pExpr)
+ ){
sqlite3ExprCodeAtInit(pParse, pExpr, target+i);
}else{
int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i);
@@ -99252,18 +100126,14 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int
int d2 = sqlite3VdbeMakeLabel(v);
testcase( jumpIfNull==0 );
sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL);
- sqlite3ExprCachePush(pParse);
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
sqlite3VdbeResolveLabel(v, d2);
- sqlite3ExprCachePop(pParse);
break;
}
case TK_OR: {
testcase( jumpIfNull==0 );
sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
- sqlite3ExprCachePush(pParse);
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
- sqlite3ExprCachePop(pParse);
break;
}
case TK_NOT: {
@@ -99422,19 +100292,15 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
case TK_AND: {
testcase( jumpIfNull==0 );
sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
- sqlite3ExprCachePush(pParse);
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
- sqlite3ExprCachePop(pParse);
break;
}
case TK_OR: {
int d2 = sqlite3VdbeMakeLabel(v);
testcase( jumpIfNull==0 );
sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL);
- sqlite3ExprCachePush(pParse);
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
sqlite3VdbeResolveLabel(v, d2);
- sqlite3ExprCachePop(pParse);
break;
}
case TK_NOT: {
@@ -99656,7 +100522,8 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTa
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){
if( combinedFlags & EP_xIsSelect ) return 2;
- if( sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2;
+ if( (combinedFlags & EP_FixedCol)==0
+ && sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2;
if( sqlite3ExprCompare(pParse, pA->pRight, pB->pRight, iTab) ) return 2;
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
assert( (combinedFlags & EP_Reduced)==0 );
@@ -99665,6 +100532,21 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTa
if( pA->iTable!=pB->iTable
&& (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
}
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ /* Justification for the assert():
+ ** window functions have p->op==TK_FUNCTION but aggregate functions
+ ** have p->op==TK_AGG_FUNCTION. So any comparison between an aggregate
+ ** function and a window function should have failed before reaching
+ ** this point. And, it is not possible to have a window function and
+ ** a scalar function with the same name and number of arguments. So
+ ** if we reach this point, either A and B both window functions or
+ ** neither are a window functions. */
+ assert( (pA->pWin==0)==(pB->pWin==0) );
+
+ if( pA->pWin!=0 ){
+ if( sqlite3WindowCompare(pParse,pA->pWin,pB->pWin)!=0 ) return 2;
+ }
+#endif
}
return 0;
}
@@ -99755,18 +100637,15 @@ SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Parse *pParse, Expr *pE1, Expr *pE2, i
/*
** This is the Expr node callback for sqlite3ExprImpliesNotNullRow().
** If the expression node requires that the table at pWalker->iCur
-** have a non-NULL column, then set pWalker->eCode to 1 and abort.
+** have one or more non-NULL column, then set pWalker->eCode to 1 and abort.
+**
+** This routine controls an optimization. False positives (setting
+** pWalker->eCode to 1 when it should not be) are deadly, but false-negatives
+** (never setting pWalker->eCode) is a harmless missed optimization.
*/
static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
- /* This routine is only called for WHERE clause expressions and so it
- ** cannot have any TK_AGG_COLUMN entries because those are only found
- ** in HAVING clauses. We can get a TK_AGG_FUNCTION in a WHERE clause,
- ** but that is an illegal construct and the query will be rejected at
- ** a later stage of processing, so the TK_AGG_FUNCTION case does not
- ** need to be considered here. */
- assert( pExpr->op!=TK_AGG_COLUMN );
+ testcase( pExpr->op==TK_AGG_COLUMN );
testcase( pExpr->op==TK_AGG_FUNCTION );
-
if( ExprHasProperty(pExpr, EP_FromJoin) ) return WRC_Prune;
switch( pExpr->op ){
case TK_ISNOT:
@@ -100186,21 +101065,9 @@ SQLITE_PRIVATE int sqlite3GetTempReg(Parse *pParse){
/*
** Deallocate a register, making available for reuse for some other
** purpose.
-**
-** If a register is currently being used by the column cache, then
-** the deallocation is deferred until the column cache line that uses
-** the register becomes stale.
*/
SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){
if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){
- int i;
- struct yColCache *p;
- for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
- if( p->iReg==iReg ){
- p->tempReg = 1;
- return;
- }
- }
pParse->aTempReg[pParse->nTempReg++] = iReg;
}
}
@@ -100214,7 +101081,6 @@ SQLITE_PRIVATE int sqlite3GetTempRange(Parse *pParse, int nReg){
i = pParse->iRangeReg;
n = pParse->nRangeReg;
if( nReg<=n ){
- assert( !usedAsColumnCache(pParse, i, i+n-1) );
pParse->iRangeReg += nReg;
pParse->nRangeReg -= nReg;
}else{
@@ -100228,7 +101094,6 @@ SQLITE_PRIVATE void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){
sqlite3ReleaseTempReg(pParse, iReg);
return;
}
- sqlite3ExprCacheRemove(pParse, iReg, nReg);
if( nReg>pParse->nRangeReg ){
pParse->nRangeReg = nReg;
pParse->iRangeReg = iReg;
@@ -100290,366 +101155,63 @@ SQLITE_PRIVATE int sqlite3NoTempsInRange(Parse *pParse, int iFirst, int iLast){
*/
#ifndef SQLITE_OMIT_ALTERTABLE
-
-/*
-** This function is used by SQL generated to implement the
-** ALTER TABLE command. The first argument is the text of a CREATE TABLE or
-** CREATE INDEX command. The second is a table name. The table name in
-** the CREATE TABLE or CREATE INDEX statement is replaced with the third
-** argument and the result returned. Examples:
-**
-** sqlite_rename_table('CREATE TABLE abc(a, b, c)', 'def')
-** -> 'CREATE TABLE def(a, b, c)'
-**
-** sqlite_rename_table('CREATE INDEX i ON abc(a)', 'def')
-** -> 'CREATE INDEX i ON def(a, b, c)'
-*/
-static void renameTableFunc(
- sqlite3_context *context,
- int NotUsed,
- sqlite3_value **argv
-){
- unsigned char const *zSql = sqlite3_value_text(argv[0]);
- unsigned char const *zTableName = sqlite3_value_text(argv[1]);
-
- int token;
- Token tname;
- unsigned char const *zCsr = zSql;
- int len = 0;
- char *zRet;
-
- sqlite3 *db = sqlite3_context_db_handle(context);
-
- UNUSED_PARAMETER(NotUsed);
-
- /* The principle used to locate the table name in the CREATE TABLE
- ** statement is that the table name is the first non-space token that
- ** is immediately followed by a TK_LP or TK_USING token.
- */
- if( zSql ){
- do {
- if( !*zCsr ){
- /* Ran out of input before finding an opening bracket. Return NULL. */
- return;
- }
-
- /* Store the token that zCsr points to in tname. */
- tname.z = (char*)zCsr;
- tname.n = len;
-
- /* Advance zCsr to the next token. Store that token type in 'token',
- ** and its length in 'len' (to be used next iteration of this loop).
- */
- do {
- zCsr += len;
- len = sqlite3GetToken(zCsr, &token);
- } while( token==TK_SPACE );
- assert( len>0 );
- } while( token!=TK_LP && token!=TK_USING );
-
- zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql),
- zSql, zTableName, tname.z+tname.n);
- sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
- }
-}
-
-/*
-** This C function implements an SQL user function that is used by SQL code
-** generated by the ALTER TABLE ... RENAME command to modify the definition
-** of any foreign key constraints that use the table being renamed as the
-** parent table. It is passed three arguments:
-**
-** 1) The complete text of the CREATE TABLE statement being modified,
-** 2) The old name of the table being renamed, and
-** 3) The new name of the table being renamed.
-**
-** It returns the new CREATE TABLE statement. For example:
-**
-** sqlite_rename_parent('CREATE TABLE t1(a REFERENCES t2)', 't2', 't3')
-** -> 'CREATE TABLE t1(a REFERENCES t3)'
-*/
-#ifndef SQLITE_OMIT_FOREIGN_KEY
-static void renameParentFunc(
- sqlite3_context *context,
- int NotUsed,
- sqlite3_value **argv
-){
- sqlite3 *db = sqlite3_context_db_handle(context);
- char *zOutput = 0;
- char *zResult;
- unsigned char const *zInput = sqlite3_value_text(argv[0]);
- unsigned char const *zOld = sqlite3_value_text(argv[1]);
- unsigned char const *zNew = sqlite3_value_text(argv[2]);
-
- unsigned const char *z; /* Pointer to token */
- int n; /* Length of token z */
- int token; /* Type of token */
-
- UNUSED_PARAMETER(NotUsed);
- if( zInput==0 || zOld==0 ) return;
- for(z=zInput; *z; z=z+n){
- n = sqlite3GetToken(z, &token);
- if( token==TK_REFERENCES ){
- char *zParent;
- do {
- z += n;
- n = sqlite3GetToken(z, &token);
- }while( token==TK_SPACE );
-
- if( token==TK_ILLEGAL ) break;
- zParent = sqlite3DbStrNDup(db, (const char *)z, n);
- if( zParent==0 ) break;
- sqlite3Dequote(zParent);
- if( 0==sqlite3StrICmp((const char *)zOld, zParent) ){
- char *zOut = sqlite3MPrintf(db, "%s%.*s\"%w\"",
- (zOutput?zOutput:""), (int)(z-zInput), zInput, (const char *)zNew
- );
- sqlite3DbFree(db, zOutput);
- zOutput = zOut;
- zInput = &z[n];
- }
- sqlite3DbFree(db, zParent);
- }
- }
-
- zResult = sqlite3MPrintf(db, "%s%s", (zOutput?zOutput:""), zInput),
- sqlite3_result_text(context, zResult, -1, SQLITE_DYNAMIC);
- sqlite3DbFree(db, zOutput);
-}
-#endif
-
-#ifndef SQLITE_OMIT_TRIGGER
-/* This function is used by SQL generated to implement the
-** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER
-** statement. The second is a table name. The table name in the CREATE
-** TRIGGER statement is replaced with the third argument and the result
-** returned. This is analagous to renameTableFunc() above, except for CREATE
-** TRIGGER, not CREATE INDEX and CREATE TABLE.
-*/
-static void renameTriggerFunc(
- sqlite3_context *context,
- int NotUsed,
- sqlite3_value **argv
-){
- unsigned char const *zSql = sqlite3_value_text(argv[0]);
- unsigned char const *zTableName = sqlite3_value_text(argv[1]);
-
- int token;
- Token tname;
- int dist = 3;
- unsigned char const *zCsr = zSql;
- int len = 0;
- char *zRet;
- sqlite3 *db = sqlite3_context_db_handle(context);
-
- UNUSED_PARAMETER(NotUsed);
-
- /* The principle used to locate the table name in the CREATE TRIGGER
- ** statement is that the table name is the first token that is immediately
- ** preceded by either TK_ON or TK_DOT and immediately followed by one
- ** of TK_WHEN, TK_BEGIN or TK_FOR.
- */
- if( zSql ){
- do {
-
- if( !*zCsr ){
- /* Ran out of input before finding the table name. Return NULL. */
- return;
- }
-
- /* Store the token that zCsr points to in tname. */
- tname.z = (char*)zCsr;
- tname.n = len;
-
- /* Advance zCsr to the next token. Store that token type in 'token',
- ** and its length in 'len' (to be used next iteration of this loop).
- */
- do {
- zCsr += len;
- len = sqlite3GetToken(zCsr, &token);
- }while( token==TK_SPACE );
- assert( len>0 );
-
- /* Variable 'dist' stores the number of tokens read since the most
- ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN
- ** token is read and 'dist' equals 2, the condition stated above
- ** to be met.
- **
- ** Note that ON cannot be a database, table or column name, so
- ** there is no need to worry about syntax like
- ** "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc.
- */
- dist++;
- if( token==TK_DOT || token==TK_ON ){
- dist = 0;
- }
- } while( dist!=2 || (token!=TK_WHEN && token!=TK_FOR && token!=TK_BEGIN) );
-
- /* Variable tname now contains the token that is the old table-name
- ** in the CREATE TRIGGER statement.
- */
- zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", (int)(((u8*)tname.z) - zSql),
- zSql, zTableName, tname.z+tname.n);
- sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
- }
-}
-#endif /* !SQLITE_OMIT_TRIGGER */
-
/*
-** Register built-in functions used to help implement ALTER TABLE
-*/
-SQLITE_PRIVATE void sqlite3AlterFunctions(void){
- static FuncDef aAlterTableFuncs[] = {
- FUNCTION(sqlite_rename_table, 2, 0, 0, renameTableFunc),
-#ifndef SQLITE_OMIT_TRIGGER
- FUNCTION(sqlite_rename_trigger, 2, 0, 0, renameTriggerFunc),
-#endif
-#ifndef SQLITE_OMIT_FOREIGN_KEY
- FUNCTION(sqlite_rename_parent, 3, 0, 0, renameParentFunc),
-#endif
- };
- sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
-}
-
-/*
-** This function is used to create the text of expressions of the form:
-**
-** name=<constant1> OR name=<constant2> OR ...
-**
-** If argument zWhere is NULL, then a pointer string containing the text
-** "name=<constant>" is returned, where <constant> is the quoted version
-** of the string passed as argument zConstant. The returned buffer is
-** allocated using sqlite3DbMalloc(). It is the responsibility of the
-** caller to ensure that it is eventually freed.
+** Parameter zName is the name of a table that is about to be altered
+** (either with ALTER TABLE ... RENAME TO or ALTER TABLE ... ADD COLUMN).
+** If the table is a system table, this function leaves an error message
+** in pParse->zErr (system tables may not be altered) and returns non-zero.
**
-** If argument zWhere is not NULL, then the string returned is
-** "<where> OR name=<constant>", where <where> is the contents of zWhere.
-** In this case zWhere is passed to sqlite3DbFree() before returning.
-**
-*/
-static char *whereOrName(sqlite3 *db, char *zWhere, char *zConstant){
- char *zNew;
- if( !zWhere ){
- zNew = sqlite3MPrintf(db, "name=%Q", zConstant);
- }else{
- zNew = sqlite3MPrintf(db, "%s OR name=%Q", zWhere, zConstant);
- sqlite3DbFree(db, zWhere);
- }
- return zNew;
-}
-
-#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
-/*
-** Generate the text of a WHERE expression which can be used to select all
-** tables that have foreign key constraints that refer to table pTab (i.e.
-** constraints for which pTab is the parent table) from the sqlite_master
-** table.
-*/
-static char *whereForeignKeys(Parse *pParse, Table *pTab){
- FKey *p;
- char *zWhere = 0;
- for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
- zWhere = whereOrName(pParse->db, zWhere, p->pFrom->zName);
- }
- return zWhere;
-}
-#endif
-
-/*
-** Generate the text of a WHERE expression which can be used to select all
-** temporary triggers on table pTab from the sqlite_temp_master table. If
-** table pTab has no temporary triggers, or is itself stored in the
-** temporary database, NULL is returned.
+** Or, if zName is not a system table, zero is returned.
*/
-static char *whereTempTriggers(Parse *pParse, Table *pTab){
- Trigger *pTrig;
- char *zWhere = 0;
- const Schema *pTempSchema = pParse->db->aDb[1].pSchema; /* Temp db schema */
-
- /* If the table is not located in the temp-db (in which case NULL is
- ** returned, loop through the tables list of triggers. For each trigger
- ** that is not part of the temp-db schema, add a clause to the WHERE
- ** expression being built up in zWhere.
- */
- if( pTab->pSchema!=pTempSchema ){
- sqlite3 *db = pParse->db;
- for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){
- if( pTrig->pSchema==pTempSchema ){
- zWhere = whereOrName(db, zWhere, pTrig->zName);
- }
- }
- }
- if( zWhere ){
- char *zNew = sqlite3MPrintf(pParse->db, "type='trigger' AND (%s)", zWhere);
- sqlite3DbFree(pParse->db, zWhere);
- zWhere = zNew;
+static int isSystemTable(Parse *pParse, const char *zName){
+ if( 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
+ sqlite3ErrorMsg(pParse, "table %s may not be altered", zName);
+ return 1;
}
- return zWhere;
+ return 0;
}
/*
-** Generate code to drop and reload the internal representation of table
-** pTab from the database, including triggers and temporary triggers.
-** Argument zName is the name of the table in the database schema at
-** the time the generated code is executed. This can be different from
-** pTab->zName if this function is being called to code part of an
-** "ALTER TABLE RENAME TO" statement.
+** Generate code to verify that the schemas of database zDb and, if
+** bTemp is not true, database "temp", can still be parsed. This is
+** called at the end of the generation of an ALTER TABLE ... RENAME ...
+** statement to ensure that the operation has not rendered any schema
+** objects unusable.
*/
-static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){
- Vdbe *v;
- char *zWhere;
- int iDb; /* Index of database containing pTab */
-#ifndef SQLITE_OMIT_TRIGGER
- Trigger *pTrig;
-#endif
-
- v = sqlite3GetVdbe(pParse);
- if( NEVER(v==0) ) return;
- assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
- iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- assert( iDb>=0 );
-
-#ifndef SQLITE_OMIT_TRIGGER
- /* Drop any table triggers from the internal schema. */
- for(pTrig=sqlite3TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){
- int iTrigDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
- assert( iTrigDb==iDb || iTrigDb==1 );
- sqlite3VdbeAddOp4(v, OP_DropTrigger, iTrigDb, 0, 0, pTrig->zName, 0);
- }
-#endif
-
- /* Drop the table and index from the internal schema. */
- sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0);
-
- /* Reload the table, index and permanent trigger schemas. */
- zWhere = sqlite3MPrintf(pParse->db, "tbl_name=%Q", zName);
- if( !zWhere ) return;
- sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere);
+static void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){
+ sqlite3NestedParse(pParse,
+ "SELECT 1 "
+ "FROM \"%w\".%s "
+ "WHERE name NOT LIKE 'sqlite_%%'"
+ " AND sql NOT LIKE 'create virtual%%'"
+ " AND sqlite_rename_test(%Q, sql, type, name, %d)=NULL ",
+ zDb, MASTER_NAME,
+ zDb, bTemp
+ );
-#ifndef SQLITE_OMIT_TRIGGER
- /* Now, if the table is not stored in the temp database, reload any temp
- ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined.
- */
- if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
- sqlite3VdbeAddParseSchemaOp(v, 1, zWhere);
+ if( bTemp==0 ){
+ sqlite3NestedParse(pParse,
+ "SELECT 1 "
+ "FROM temp.%s "
+ "WHERE name NOT LIKE 'sqlite_%%'"
+ " AND sql NOT LIKE 'create virtual%%'"
+ " AND sqlite_rename_test(%Q, sql, type, name, 1)=NULL ",
+ MASTER_NAME, zDb
+ );
}
-#endif
}
/*
-** Parameter zName is the name of a table that is about to be altered
-** (either with ALTER TABLE ... RENAME TO or ALTER TABLE ... ADD COLUMN).
-** If the table is a system table, this function leaves an error message
-** in pParse->zErr (system tables may not be altered) and returns non-zero.
-**
-** Or, if zName is not a system table, zero is returned.
+** Generate code to reload the schema for database iDb. And, if iDb!=1, for
+** the temp database as well.
*/
-static int isSystemTable(Parse *pParse, const char *zName){
- if( 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
- sqlite3ErrorMsg(pParse, "table %s may not be altered", zName);
- return 1;
+static void renameReloadSchema(Parse *pParse, int iDb){
+ Vdbe *v = pParse->pVdbe;
+ if( v ){
+ sqlite3ChangeCookie(pParse, iDb);
+ sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iDb, 0);
+ if( iDb!=1 ) sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, 1, 0);
}
- return 0;
}
/*
@@ -100669,9 +101231,6 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
int nTabName; /* Number of UTF-8 characters in zTabName */
const char *zTabName; /* Original name of the table */
Vdbe *v;
-#ifndef SQLITE_OMIT_TRIGGER
- char *zWhere = 0; /* Where clause to locate temp triggers */
-#endif
VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */
u32 savedDbFlags; /* Saved value of db->mDbFlags */
@@ -100744,52 +101303,25 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
if( v==0 ){
goto exit_rename_table;
}
- sqlite3BeginWriteOperation(pParse, pVTab!=0, iDb);
- sqlite3ChangeCookie(pParse, iDb);
-
- /* If this is a virtual table, invoke the xRename() function if
- ** one is defined. The xRename() callback will modify the names
- ** of any resources used by the v-table implementation (including other
- ** SQLite tables) that are identified by the name of the virtual table.
- */
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( pVTab ){
- int i = ++pParse->nMem;
- sqlite3VdbeLoadString(v, i, zName);
- sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB);
- sqlite3MayAbort(pParse);
- }
-#endif
/* figure out how many UTF-8 characters are in zName */
zTabName = pTab->zName;
nTabName = sqlite3Utf8CharLen(zTabName, -1);
-#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
- if( db->flags&SQLITE_ForeignKeys ){
- /* If foreign-key support is enabled, rewrite the CREATE TABLE
- ** statements corresponding to all child tables of foreign key constraints
- ** for which the renamed table is the parent table. */
- if( (zWhere=whereForeignKeys(pParse, pTab))!=0 ){
- sqlite3NestedParse(pParse,
- "UPDATE \"%w\".%s SET "
- "sql = sqlite_rename_parent(sql, %Q, %Q) "
- "WHERE %s;", zDb, MASTER_NAME, zTabName, zName, zWhere);
- sqlite3DbFree(db, zWhere);
- }
- }
-#endif
+ /* Rewrite all CREATE TABLE, INDEX, TRIGGER or VIEW statements in
+ ** the schema to use the new table name. */
+ sqlite3NestedParse(pParse,
+ "UPDATE \"%w\".%s SET "
+ "sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, %d) "
+ "WHERE (type!='index' OR tbl_name=%Q COLLATE nocase)"
+ "AND name NOT LIKE 'sqlite_%%'"
+ , zDb, MASTER_NAME, zDb, zTabName, zName, (iDb==1), zTabName
+ );
- /* Modify the sqlite_master table to use the new table name. */
+ /* Update the tbl_name and name columns of the sqlite_master table
+ ** as required. */
sqlite3NestedParse(pParse,
"UPDATE %Q.%s SET "
-#ifdef SQLITE_OMIT_TRIGGER
- "sql = sqlite_rename_table(sql, %Q), "
-#else
- "sql = CASE "
- "WHEN type = 'trigger' THEN sqlite_rename_trigger(sql, %Q)"
- "ELSE sqlite_rename_table(sql, %Q) END, "
-#endif
"tbl_name = %Q, "
"name = CASE "
"WHEN type='table' THEN %Q "
@@ -100798,11 +101330,9 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
"ELSE name END "
"WHERE tbl_name=%Q COLLATE nocase AND "
"(type='table' OR type='index' OR type='trigger');",
- zDb, MASTER_NAME, zName, zName, zName,
-#ifndef SQLITE_OMIT_TRIGGER
- zName,
-#endif
- zName, nTabName, zTabName
+ zDb, MASTER_NAME,
+ zName, zName, zName,
+ nTabName, zTabName
);
#ifndef SQLITE_OMIT_AUTOINCREMENT
@@ -100816,35 +101346,37 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
}
#endif
-#ifndef SQLITE_OMIT_TRIGGER
- /* If there are TEMP triggers on this table, modify the sqlite_temp_master
- ** table. Don't do this if the table being ALTERed is itself located in
- ** the temp database.
- */
- if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
+ /* If the table being renamed is not itself part of the temp database,
+ ** edit view and trigger definitions within the temp database
+ ** as required. */
+ if( iDb!=1 ){
sqlite3NestedParse(pParse,
"UPDATE sqlite_temp_master SET "
- "sql = sqlite_rename_trigger(sql, %Q), "
- "tbl_name = %Q "
- "WHERE %s;", zName, zName, zWhere);
- sqlite3DbFree(db, zWhere);
+ "sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, 1), "
+ "tbl_name = "
+ "CASE WHEN tbl_name=%Q COLLATE nocase AND "
+ " sqlite_rename_test(%Q, sql, type, name, 1) "
+ "THEN %Q ELSE tbl_name END "
+ "WHERE type IN ('view', 'trigger')"
+ , zDb, zTabName, zName, zTabName, zDb, zName);
}
-#endif
-#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
- if( db->flags&SQLITE_ForeignKeys ){
- FKey *p;
- for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
- Table *pFrom = p->pFrom;
- if( pFrom!=pTab ){
- reloadTableSchema(pParse, p->pFrom, pFrom->zName);
- }
- }
+ /* If this is a virtual table, invoke the xRename() function if
+ ** one is defined. The xRename() callback will modify the names
+ ** of any resources used by the v-table implementation (including other
+ ** SQLite tables) that are identified by the name of the virtual table.
+ */
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( pVTab ){
+ int i = ++pParse->nMem;
+ sqlite3VdbeLoadString(v, i, zName);
+ sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB);
+ sqlite3MayAbort(pParse);
}
#endif
- /* Drop and reload the internal table schema. */
- reloadTableSchema(pParse, pTab, zName);
+ renameReloadSchema(pParse, iDb);
+ renameTestSchema(pParse, zDb, iDb==1);
exit_rename_table:
sqlite3SrcListDelete(db, pSrc);
@@ -100870,12 +101402,11 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
Column *pCol; /* The new column */
Expr *pDflt; /* Default value for the new column */
sqlite3 *db; /* The database connection; */
- Vdbe *v = pParse->pVdbe; /* The prepared statement under construction */
+ Vdbe *v; /* The prepared statement under construction */
int r1; /* Temporary registers */
db = pParse->db;
if( pParse->nErr || db->mallocFailed ) return;
- assert( v!=0 );
pNew = pParse->pNewTable;
assert( pNew );
@@ -100970,17 +101501,20 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
** from less than 3 to 4, as that will corrupt any preexisting DESC
** index.
*/
- r1 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT);
- sqlite3VdbeUsesBtree(v, iDb);
- sqlite3VdbeAddOp2(v, OP_AddImm, r1, -2);
- sqlite3VdbeAddOp2(v, OP_IfPos, r1, sqlite3VdbeCurrentAddr(v)+2);
- VdbeCoverage(v);
- sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, 3);
- sqlite3ReleaseTempReg(pParse, r1);
+ v = sqlite3GetVdbe(pParse);
+ if( v ){
+ r1 = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT);
+ sqlite3VdbeUsesBtree(v, iDb);
+ sqlite3VdbeAddOp2(v, OP_AddImm, r1, -2);
+ sqlite3VdbeAddOp2(v, OP_IfPos, r1, sqlite3VdbeCurrentAddr(v)+2);
+ VdbeCoverage(v);
+ sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, 3);
+ sqlite3ReleaseTempReg(pParse, r1);
+ }
- /* Reload the schema of the modified table. */
- reloadTableSchema(pParse, pTab, pTab->zName);
+ /* Reload the table definition */
+ renameReloadSchema(pParse, iDb);
}
/*
@@ -101001,7 +101535,6 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
Table *pNew;
Table *pTab;
- Vdbe *v;
int iDb;
int i;
int nAlloc;
@@ -101065,16 +101598,1142 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
pNew->addColOffset = pTab->addColOffset;
pNew->nTabRef = 1;
- /* Begin a transaction and increment the schema cookie. */
- sqlite3BeginWriteOperation(pParse, 0, iDb);
- v = sqlite3GetVdbe(pParse);
- if( !v ) goto exit_begin_add_column;
- sqlite3ChangeCookie(pParse, iDb);
-
exit_begin_add_column:
sqlite3SrcListDelete(db, pSrc);
return;
}
+
+/*
+** Parameter pTab is the subject of an ALTER TABLE ... RENAME COLUMN
+** command. This function checks if the table is a view or virtual
+** table (columns of views or virtual tables may not be renamed). If so,
+** it loads an error message into pParse and returns non-zero.
+**
+** Or, if pTab is not a view or virtual table, zero is returned.
+*/
+#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
+static int isRealTable(Parse *pParse, Table *pTab){
+ const char *zType = 0;
+#ifndef SQLITE_OMIT_VIEW
+ if( pTab->pSelect ){
+ zType = "view";
+ }
+#endif
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( IsVirtual(pTab) ){
+ zType = "virtual table";
+ }
+#endif
+ if( zType ){
+ sqlite3ErrorMsg(
+ pParse, "cannot rename columns of %s \"%s\"", zType, pTab->zName
+ );
+ return 1;
+ }
+ return 0;
+}
+#else /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */
+# define isRealTable(x,y) (0)
+#endif
+
+/*
+** Handles the following parser reduction:
+**
+** cmd ::= ALTER TABLE pSrc RENAME COLUMN pOld TO pNew
+*/
+SQLITE_PRIVATE void sqlite3AlterRenameColumn(
+ Parse *pParse, /* Parsing context */
+ SrcList *pSrc, /* Table being altered. pSrc->nSrc==1 */
+ Token *pOld, /* Name of column being changed */
+ Token *pNew /* New column name */
+){
+ sqlite3 *db = pParse->db; /* Database connection */
+ Table *pTab; /* Table being updated */
+ int iCol; /* Index of column being renamed */
+ char *zOld = 0; /* Old column name */
+ char *zNew = 0; /* New column name */
+ const char *zDb; /* Name of schema containing the table */
+ int iSchema; /* Index of the schema */
+ int bQuote; /* True to quote the new name */
+
+ /* Locate the table to be altered */
+ pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
+ if( !pTab ) goto exit_rename_column;
+
+ /* Cannot alter a system table */
+ if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ) goto exit_rename_column;
+ if( SQLITE_OK!=isRealTable(pParse, pTab) ) goto exit_rename_column;
+
+ /* Which schema holds the table to be altered */
+ iSchema = sqlite3SchemaToIndex(db, pTab->pSchema);
+ assert( iSchema>=0 );
+ zDb = db->aDb[iSchema].zDbSName;
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ /* Invoke the authorization callback. */
+ if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){
+ goto exit_rename_column;
+ }
+#endif
+
+ /* Make sure the old name really is a column name in the table to be
+ ** altered. Set iCol to be the index of the column being renamed */
+ zOld = sqlite3NameFromToken(db, pOld);
+ if( !zOld ) goto exit_rename_column;
+ for(iCol=0; iCol<pTab->nCol; iCol++){
+ if( 0==sqlite3StrICmp(pTab->aCol[iCol].zName, zOld) ) break;
+ }
+ if( iCol==pTab->nCol ){
+ sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zOld);
+ goto exit_rename_column;
+ }
+
+ /* Do the rename operation using a recursive UPDATE statement that
+ ** uses the sqlite_rename_column() SQL function to compute the new
+ ** CREATE statement text for the sqlite_master table.
+ */
+ zNew = sqlite3NameFromToken(db, pNew);
+ if( !zNew ) goto exit_rename_column;
+ assert( pNew->n>0 );
+ bQuote = sqlite3Isquote(pNew->z[0]);
+ sqlite3NestedParse(pParse,
+ "UPDATE \"%w\".%s SET "
+ "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, %d) "
+ "WHERE name NOT LIKE 'sqlite_%%' AND (type != 'index' OR tbl_name = %Q)"
+ " AND sql NOT LIKE 'create virtual%%'",
+ zDb, MASTER_NAME,
+ zDb, pTab->zName, iCol, zNew, bQuote, iSchema==1,
+ pTab->zName
+ );
+
+ sqlite3NestedParse(pParse,
+ "UPDATE temp.%s SET "
+ "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, 1) "
+ "WHERE type IN ('trigger', 'view')",
+ MASTER_NAME,
+ zDb, pTab->zName, iCol, zNew, bQuote
+ );
+
+ /* Drop and reload the database schema. */
+ renameReloadSchema(pParse, iSchema);
+ renameTestSchema(pParse, zDb, iSchema==1);
+
+ exit_rename_column:
+ sqlite3SrcListDelete(db, pSrc);
+ sqlite3DbFree(db, zOld);
+ sqlite3DbFree(db, zNew);
+ return;
+}
+
+/*
+** Each RenameToken object maps an element of the parse tree into
+** the token that generated that element. The parse tree element
+** might be one of:
+**
+** * A pointer to an Expr that represents an ID
+** * The name of a table column in Column.zName
+**
+** A list of RenameToken objects can be constructed during parsing.
+** Each new object is created by sqlite3RenameTokenMap().
+** As the parse tree is transformed, the sqlite3RenameTokenRemap()
+** routine is used to keep the mapping current.
+**
+** After the parse finishes, renameTokenFind() routine can be used
+** to look up the actual token value that created some element in
+** the parse tree.
+*/
+struct RenameToken {
+ void *p; /* Parse tree element created by token t */
+ Token t; /* The token that created parse tree element p */
+ RenameToken *pNext; /* Next is a list of all RenameToken objects */
+};
+
+/*
+** The context of an ALTER TABLE RENAME COLUMN operation that gets passed
+** down into the Walker.
+*/
+typedef struct RenameCtx RenameCtx;
+struct RenameCtx {
+ RenameToken *pList; /* List of tokens to overwrite */
+ int nList; /* Number of tokens in pList */
+ int iCol; /* Index of column being renamed */
+ Table *pTab; /* Table being ALTERed */
+ const char *zOld; /* Old column name */
+};
+
+#ifdef SQLITE_DEBUG
+/*
+** This function is only for debugging. It performs two tasks:
+**
+** 1. Checks that pointer pPtr does not already appear in the
+** rename-token list.
+**
+** 2. Dereferences each pointer in the rename-token list.
+**
+** The second is most effective when debugging under valgrind or
+** address-sanitizer or similar. If any of these pointers no longer
+** point to valid objects, an exception is raised by the memory-checking
+** tool.
+**
+** The point of this is to prevent comparisons of invalid pointer values.
+** Even though this always seems to work, it is undefined according to the
+** C standard. Example of undefined comparison:
+**
+** sqlite3_free(x);
+** if( x==y ) ...
+**
+** Technically, as x no longer points into a valid object or to the byte
+** following a valid object, it may not be used in comparison operations.
+*/
+static void renameTokenCheckAll(Parse *pParse, void *pPtr){
+ if( pParse->nErr==0 && pParse->db->mallocFailed==0 ){
+ RenameToken *p;
+ u8 i = 0;
+ for(p=pParse->pRename; p; p=p->pNext){
+ if( p->p ){
+ assert( p->p!=pPtr );
+ i += *(u8*)(p->p);
+ }
+ }
+ }
+}
+#else
+# define renameTokenCheckAll(x,y)
+#endif
+
+/*
+** Add a new RenameToken object mapping parse tree element pPtr into
+** token *pToken to the Parse object currently under construction.
+**
+** Return a copy of pPtr.
+*/
+SQLITE_PRIVATE void *sqlite3RenameTokenMap(Parse *pParse, void *pPtr, Token *pToken){
+ RenameToken *pNew;
+ assert( pPtr || pParse->db->mallocFailed );
+ renameTokenCheckAll(pParse, pPtr);
+ pNew = sqlite3DbMallocZero(pParse->db, sizeof(RenameToken));
+ if( pNew ){
+ pNew->p = pPtr;
+ pNew->t = *pToken;
+ pNew->pNext = pParse->pRename;
+ pParse->pRename = pNew;
+ }
+
+ return pPtr;
+}
+
+/*
+** It is assumed that there is already a RenameToken object associated
+** with parse tree element pFrom. This function remaps the associated token
+** to parse tree element pTo.
+*/
+SQLITE_PRIVATE void sqlite3RenameTokenRemap(Parse *pParse, void *pTo, void *pFrom){
+ RenameToken *p;
+ renameTokenCheckAll(pParse, pTo);
+ for(p=pParse->pRename; p; p=p->pNext){
+ if( p->p==pFrom ){
+ p->p = pTo;
+ break;
+ }
+ }
+}
+
+/*
+** Walker callback used by sqlite3RenameExprUnmap().
+*/
+static int renameUnmapExprCb(Walker *pWalker, Expr *pExpr){
+ Parse *pParse = pWalker->pParse;
+ sqlite3RenameTokenRemap(pParse, 0, (void*)pExpr);
+ return WRC_Continue;
+}
+
+/*
+** Remove all nodes that are part of expression pExpr from the rename list.
+*/
+SQLITE_PRIVATE void sqlite3RenameExprUnmap(Parse *pParse, Expr *pExpr){
+ Walker sWalker;
+ memset(&sWalker, 0, sizeof(Walker));
+ sWalker.pParse = pParse;
+ sWalker.xExprCallback = renameUnmapExprCb;
+ sqlite3WalkExpr(&sWalker, pExpr);
+}
+
+/*
+** Remove all nodes that are part of expression-list pEList from the
+** rename list.
+*/
+SQLITE_PRIVATE void sqlite3RenameExprlistUnmap(Parse *pParse, ExprList *pEList){
+ if( pEList ){
+ int i;
+ Walker sWalker;
+ memset(&sWalker, 0, sizeof(Walker));
+ sWalker.pParse = pParse;
+ sWalker.xExprCallback = renameUnmapExprCb;
+ sqlite3WalkExprList(&sWalker, pEList);
+ for(i=0; i<pEList->nExpr; i++){
+ sqlite3RenameTokenRemap(pParse, 0, (void*)pEList->a[i].zName);
+ }
+ }
+}
+
+/*
+** Free the list of RenameToken objects given in the second argument
+*/
+static void renameTokenFree(sqlite3 *db, RenameToken *pToken){
+ RenameToken *pNext;
+ RenameToken *p;
+ for(p=pToken; p; p=pNext){
+ pNext = p->pNext;
+ sqlite3DbFree(db, p);
+ }
+}
+
+/*
+** Search the Parse object passed as the first argument for a RenameToken
+** object associated with parse tree element pPtr. If found, remove it
+** from the Parse object and add it to the list maintained by the
+** RenameCtx object passed as the second argument.
+*/
+static void renameTokenFind(Parse *pParse, struct RenameCtx *pCtx, void *pPtr){
+ RenameToken **pp;
+ assert( pPtr!=0 );
+ for(pp=&pParse->pRename; (*pp); pp=&(*pp)->pNext){
+ if( (*pp)->p==pPtr ){
+ RenameToken *pToken = *pp;
+ *pp = pToken->pNext;
+ pToken->pNext = pCtx->pList;
+ pCtx->pList = pToken;
+ pCtx->nList++;
+ break;
+ }
+ }
+}
+
+/*
+** This is a Walker select callback. It does nothing. It is only required
+** because without a dummy callback, sqlite3WalkExpr() and similar do not
+** descend into sub-select statements.
+*/
+static int renameColumnSelectCb(Walker *pWalker, Select *p){
+ UNUSED_PARAMETER(pWalker);
+ UNUSED_PARAMETER(p);
+ return WRC_Continue;
+}
+
+/*
+** This is a Walker expression callback.
+**
+** For every TK_COLUMN node in the expression tree, search to see
+** if the column being references is the column being renamed by an
+** ALTER TABLE statement. If it is, then attach its associated
+** RenameToken object to the list of RenameToken objects being
+** constructed in RenameCtx object at pWalker->u.pRename.
+*/
+static int renameColumnExprCb(Walker *pWalker, Expr *pExpr){
+ RenameCtx *p = pWalker->u.pRename;
+ if( pExpr->op==TK_TRIGGER
+ && pExpr->iColumn==p->iCol
+ && pWalker->pParse->pTriggerTab==p->pTab
+ ){
+ renameTokenFind(pWalker->pParse, p, (void*)pExpr);
+ }else if( pExpr->op==TK_COLUMN
+ && pExpr->iColumn==p->iCol
+ && p->pTab==pExpr->pTab
+ ){
+ renameTokenFind(pWalker->pParse, p, (void*)pExpr);
+ }
+ return WRC_Continue;
+}
+
+/*
+** The RenameCtx contains a list of tokens that reference a column that
+** is being renamed by an ALTER TABLE statement. Return the "last"
+** RenameToken in the RenameCtx and remove that RenameToken from the
+** RenameContext. "Last" means the last RenameToken encountered when
+** the input SQL is parsed from left to right. Repeated calls to this routine
+** return all column name tokens in the order that they are encountered
+** in the SQL statement.
+*/
+static RenameToken *renameColumnTokenNext(RenameCtx *pCtx){
+ RenameToken *pBest = pCtx->pList;
+ RenameToken *pToken;
+ RenameToken **pp;
+
+ for(pToken=pBest->pNext; pToken; pToken=pToken->pNext){
+ if( pToken->t.z>pBest->t.z ) pBest = pToken;
+ }
+ for(pp=&pCtx->pList; *pp!=pBest; pp=&(*pp)->pNext);
+ *pp = pBest->pNext;
+
+ return pBest;
+}
+
+/*
+** An error occured while parsing or otherwise processing a database
+** object (either pParse->pNewTable, pNewIndex or pNewTrigger) as part of an
+** ALTER TABLE RENAME COLUMN program. The error message emitted by the
+** sub-routine is currently stored in pParse->zErrMsg. This function
+** adds context to the error message and then stores it in pCtx.
+*/
+static void renameColumnParseError(
+ sqlite3_context *pCtx,
+ int bPost,
+ sqlite3_value *pType,
+ sqlite3_value *pObject,
+ Parse *pParse
+){
+ const char *zT = (const char*)sqlite3_value_text(pType);
+ const char *zN = (const char*)sqlite3_value_text(pObject);
+ char *zErr;
+
+ zErr = sqlite3_mprintf("error in %s %s%s: %s",
+ zT, zN, (bPost ? " after rename" : ""),
+ pParse->zErrMsg
+ );
+ sqlite3_result_error(pCtx, zErr, -1);
+ sqlite3_free(zErr);
+}
+
+/*
+** For each name in the the expression-list pEList (i.e. each
+** pEList->a[i].zName) that matches the string in zOld, extract the
+** corresponding rename-token from Parse object pParse and add it
+** to the RenameCtx pCtx.
+*/
+static void renameColumnElistNames(
+ Parse *pParse,
+ RenameCtx *pCtx,
+ ExprList *pEList,
+ const char *zOld
+){
+ if( pEList ){
+ int i;
+ for(i=0; i<pEList->nExpr; i++){
+ char *zName = pEList->a[i].zName;
+ if( 0==sqlite3_stricmp(zName, zOld) ){
+ renameTokenFind(pParse, pCtx, (void*)zName);
+ }
+ }
+ }
+}
+
+/*
+** For each name in the the id-list pIdList (i.e. each pIdList->a[i].zName)
+** that matches the string in zOld, extract the corresponding rename-token
+** from Parse object pParse and add it to the RenameCtx pCtx.
+*/
+static void renameColumnIdlistNames(
+ Parse *pParse,
+ RenameCtx *pCtx,
+ IdList *pIdList,
+ const char *zOld
+){
+ if( pIdList ){
+ int i;
+ for(i=0; i<pIdList->nId; i++){
+ char *zName = pIdList->a[i].zName;
+ if( 0==sqlite3_stricmp(zName, zOld) ){
+ renameTokenFind(pParse, pCtx, (void*)zName);
+ }
+ }
+ }
+}
+
+/*
+** Parse the SQL statement zSql using Parse object (*p). The Parse object
+** is initialized by this function before it is used.
+*/
+static int renameParseSql(
+ Parse *p, /* Memory to use for Parse object */
+ const char *zDb, /* Name of schema SQL belongs to */
+ int bTable, /* 1 -> RENAME TABLE, 0 -> RENAME COLUMN */
+ sqlite3 *db, /* Database handle */
+ const char *zSql, /* SQL to parse */
+ int bTemp /* True if SQL is from temp schema */
+){
+ int rc;
+ char *zErr = 0;
+
+ db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb);
+
+ /* Parse the SQL statement passed as the first argument. If no error
+ ** occurs and the parse does not result in a new table, index or
+ ** trigger object, the database must be corrupt. */
+ memset(p, 0, sizeof(Parse));
+ p->eParseMode = (bTable ? PARSE_MODE_RENAME_TABLE : PARSE_MODE_RENAME_COLUMN);
+ p->db = db;
+ p->nQueryLoop = 1;
+ rc = sqlite3RunParser(p, zSql, &zErr);
+ assert( p->zErrMsg==0 );
+ assert( rc!=SQLITE_OK || zErr==0 );
+ assert( (0!=p->pNewTable) + (0!=p->pNewIndex) + (0!=p->pNewTrigger)<2 );
+ p->zErrMsg = zErr;
+ if( db->mallocFailed ) rc = SQLITE_NOMEM;
+ if( rc==SQLITE_OK
+ && p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0
+ ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }
+
+#ifdef SQLITE_DEBUG
+ /* Ensure that all mappings in the Parse.pRename list really do map to
+ ** a part of the input string. */
+ if( rc==SQLITE_OK ){
+ int nSql = sqlite3Strlen30(zSql);
+ RenameToken *pToken;
+ for(pToken=p->pRename; pToken; pToken=pToken->pNext){
+ assert( pToken->t.z>=zSql && &pToken->t.z[pToken->t.n]<=&zSql[nSql] );
+ }
+ }
+#endif
+
+ db->init.iDb = 0;
+ return rc;
+}
+
+/*
+** This function edits SQL statement zSql, replacing each token identified
+** by the linked list pRename with the text of zNew. If argument bQuote is
+** true, then zNew is always quoted first. If no error occurs, the result
+** is loaded into context object pCtx as the result.
+**
+** Or, if an error occurs (i.e. an OOM condition), an error is left in
+** pCtx and an SQLite error code returned.
+*/
+static int renameEditSql(
+ sqlite3_context *pCtx, /* Return result here */
+ RenameCtx *pRename, /* Rename context */
+ const char *zSql, /* SQL statement to edit */
+ const char *zNew, /* New token text */
+ int bQuote /* True to always quote token */
+){
+ int nNew = sqlite3Strlen30(zNew);
+ int nSql = sqlite3Strlen30(zSql);
+ sqlite3 *db = sqlite3_context_db_handle(pCtx);
+ int rc = SQLITE_OK;
+ char *zQuot;
+ char *zOut;
+ int nQuot;
+
+ /* Set zQuot to point to a buffer containing a quoted copy of the
+ ** identifier zNew. If the corresponding identifier in the original
+ ** ALTER TABLE statement was quoted (bQuote==1), then set zNew to
+ ** point to zQuot so that all substitutions are made using the
+ ** quoted version of the new column name. */
+ zQuot = sqlite3MPrintf(db, "\"%w\"", zNew);
+ if( zQuot==0 ){
+ return SQLITE_NOMEM;
+ }else{
+ nQuot = sqlite3Strlen30(zQuot);
+ }
+ if( bQuote ){
+ zNew = zQuot;
+ nNew = nQuot;
+ }
+
+ /* At this point pRename->pList contains a list of RenameToken objects
+ ** corresponding to all tokens in the input SQL that must be replaced
+ ** with the new column name. All that remains is to construct and
+ ** return the edited SQL string. */
+ assert( nQuot>=nNew );
+ zOut = sqlite3DbMallocZero(db, nSql + pRename->nList*nQuot + 1);
+ if( zOut ){
+ int nOut = nSql;
+ memcpy(zOut, zSql, nSql);
+ while( pRename->pList ){
+ int iOff; /* Offset of token to replace in zOut */
+ RenameToken *pBest = renameColumnTokenNext(pRename);
+
+ u32 nReplace;
+ const char *zReplace;
+ if( sqlite3IsIdChar(*pBest->t.z) ){
+ nReplace = nNew;
+ zReplace = zNew;
+ }else{
+ nReplace = nQuot;
+ zReplace = zQuot;
+ }
+
+ iOff = pBest->t.z - zSql;
+ if( pBest->t.n!=nReplace ){
+ memmove(&zOut[iOff + nReplace], &zOut[iOff + pBest->t.n],
+ nOut - (iOff + pBest->t.n)
+ );
+ nOut += nReplace - pBest->t.n;
+ zOut[nOut] = '\0';
+ }
+ memcpy(&zOut[iOff], zReplace, nReplace);
+ sqlite3DbFree(db, pBest);
+ }
+
+ sqlite3_result_text(pCtx, zOut, -1, SQLITE_TRANSIENT);
+ sqlite3DbFree(db, zOut);
+ }else{
+ rc = SQLITE_NOMEM;
+ }
+
+ sqlite3_free(zQuot);
+ return rc;
+}
+
+/*
+** Resolve all symbols in the trigger at pParse->pNewTrigger, assuming
+** it was read from the schema of database zDb. Return SQLITE_OK if
+** successful. Otherwise, return an SQLite error code and leave an error
+** message in the Parse object.
+*/
+static int renameResolveTrigger(Parse *pParse, const char *zDb){
+ sqlite3 *db = pParse->db;
+ Trigger *pNew = pParse->pNewTrigger;
+ TriggerStep *pStep;
+ NameContext sNC;
+ int rc = SQLITE_OK;
+
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pParse = pParse;
+ assert( pNew->pTabSchema );
+ pParse->pTriggerTab = sqlite3FindTable(db, pNew->table,
+ db->aDb[sqlite3SchemaToIndex(db, pNew->pTabSchema)].zDbSName
+ );
+ pParse->eTriggerOp = pNew->op;
+
+ /* Resolve symbols in WHEN clause */
+ if( pNew->pWhen ){
+ rc = sqlite3ResolveExprNames(&sNC, pNew->pWhen);
+ }
+
+ for(pStep=pNew->step_list; rc==SQLITE_OK && pStep; pStep=pStep->pNext){
+ if( pStep->pSelect ){
+ sqlite3SelectPrep(pParse, pStep->pSelect, &sNC);
+ if( pParse->nErr ) rc = pParse->rc;
+ }
+ if( rc==SQLITE_OK && pStep->zTarget ){
+ Table *pTarget = sqlite3LocateTable(pParse, 0, pStep->zTarget, zDb);
+ if( pTarget==0 ){
+ rc = SQLITE_ERROR;
+ }else if( SQLITE_OK==(rc = sqlite3ViewGetColumnNames(pParse, pTarget)) ){
+ SrcList sSrc;
+ memset(&sSrc, 0, sizeof(sSrc));
+ sSrc.nSrc = 1;
+ sSrc.a[0].zName = pStep->zTarget;
+ sSrc.a[0].pTab = pTarget;
+ sNC.pSrcList = &sSrc;
+ if( pStep->pWhere ){
+ rc = sqlite3ResolveExprNames(&sNC, pStep->pWhere);
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3ResolveExprListNames(&sNC, pStep->pExprList);
+ }
+ assert( !pStep->pUpsert || (!pStep->pWhere && !pStep->pExprList) );
+ if( pStep->pUpsert ){
+ Upsert *pUpsert = pStep->pUpsert;
+ assert( rc==SQLITE_OK );
+ pUpsert->pUpsertSrc = &sSrc;
+ sNC.uNC.pUpsert = pUpsert;
+ sNC.ncFlags = NC_UUpsert;
+ rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget);
+ if( rc==SQLITE_OK ){
+ ExprList *pUpsertSet = pUpsert->pUpsertSet;
+ rc = sqlite3ResolveExprListNames(&sNC, pUpsertSet);
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertWhere);
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere);
+ }
+ sNC.ncFlags = 0;
+ }
+ }
+ }
+ }
+ return rc;
+}
+
+/*
+** Invoke sqlite3WalkExpr() or sqlite3WalkSelect() on all Select or Expr
+** objects that are part of the trigger passed as the second argument.
+*/
+static void renameWalkTrigger(Walker *pWalker, Trigger *pTrigger){
+ TriggerStep *pStep;
+
+ /* Find tokens to edit in WHEN clause */
+ sqlite3WalkExpr(pWalker, pTrigger->pWhen);
+
+ /* Find tokens to edit in trigger steps */
+ for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){
+ sqlite3WalkSelect(pWalker, pStep->pSelect);
+ sqlite3WalkExpr(pWalker, pStep->pWhere);
+ sqlite3WalkExprList(pWalker, pStep->pExprList);
+ if( pStep->pUpsert ){
+ Upsert *pUpsert = pStep->pUpsert;
+ sqlite3WalkExprList(pWalker, pUpsert->pUpsertTarget);
+ sqlite3WalkExprList(pWalker, pUpsert->pUpsertSet);
+ sqlite3WalkExpr(pWalker, pUpsert->pUpsertWhere);
+ sqlite3WalkExpr(pWalker, pUpsert->pUpsertTargetWhere);
+ }
+ }
+}
+
+/*
+** Free the contents of Parse object (*pParse). Do not free the memory
+** occupied by the Parse object itself.
+*/
+static void renameParseCleanup(Parse *pParse){
+ sqlite3 *db = pParse->db;
+ if( pParse->pVdbe ){
+ sqlite3VdbeFinalize(pParse->pVdbe);
+ }
+ sqlite3DeleteTable(db, pParse->pNewTable);
+ if( pParse->pNewIndex ) sqlite3FreeIndex(db, pParse->pNewIndex);
+ sqlite3DeleteTrigger(db, pParse->pNewTrigger);
+ sqlite3DbFree(db, pParse->zErrMsg);
+ renameTokenFree(db, pParse->pRename);
+ sqlite3ParserReset(pParse);
+}
+
+/*
+** SQL function:
+**
+** sqlite_rename_column(zSql, iCol, bQuote, zNew, zTable, zOld)
+**
+** 0. zSql: SQL statement to rewrite
+** 1. type: Type of object ("table", "view" etc.)
+** 2. object: Name of object
+** 3. Database: Database name (e.g. "main")
+** 4. Table: Table name
+** 5. iCol: Index of column to rename
+** 6. zNew: New column name
+** 7. bQuote: Non-zero if the new column name should be quoted.
+** 8. bTemp: True if zSql comes from temp schema
+**
+** Do a column rename operation on the CREATE statement given in zSql.
+** The iCol-th column (left-most is 0) of table zTable is renamed from zCol
+** into zNew. The name should be quoted if bQuote is true.
+**
+** This function is used internally by the ALTER TABLE RENAME COLUMN command.
+** Though accessible to application code, it is not intended for use by
+** applications. The existance of this function, and the way it works,
+** is subject to change without notice.
+**
+** If any of the parameters are out-of-bounds, then simply return NULL.
+** An out-of-bounds parameter can only occur when the application calls
+** this function directly. The parameters will always be well-formed when
+** this routine is invoked by the bytecode for a legitimate ALTER TABLE
+** statement.
+*/
+static void renameColumnFunc(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **argv
+){
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ RenameCtx sCtx;
+ const char *zSql = (const char*)sqlite3_value_text(argv[0]);
+ const char *zDb = (const char*)sqlite3_value_text(argv[3]);
+ const char *zTable = (const char*)sqlite3_value_text(argv[4]);
+ int iCol = sqlite3_value_int(argv[5]);
+ const char *zNew = (const char*)sqlite3_value_text(argv[6]);
+ int bQuote = sqlite3_value_int(argv[7]);
+ int bTemp = sqlite3_value_int(argv[8]);
+ const char *zOld;
+ int rc;
+ Parse sParse;
+ Walker sWalker;
+ Index *pIdx;
+ int i;
+ Table *pTab;
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ sqlite3_xauth xAuth = db->xAuth;
+#endif
+
+ UNUSED_PARAMETER(NotUsed);
+ if( zSql==0 ) return;
+ if( zTable==0 ) return;
+ if( zNew==0 ) return;
+ if( iCol<0 ) return;
+ sqlite3BtreeEnterAll(db);
+ pTab = sqlite3FindTable(db, zTable, zDb);
+ if( pTab==0 || iCol>=pTab->nCol ){
+ sqlite3BtreeLeaveAll(db);
+ return;
+ }
+ zOld = pTab->aCol[iCol].zName;
+ memset(&sCtx, 0, sizeof(sCtx));
+ sCtx.iCol = ((iCol==pTab->iPKey) ? -1 : iCol);
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ db->xAuth = 0;
+#endif
+ rc = renameParseSql(&sParse, zDb, 0, db, zSql, bTemp);
+
+ /* Find tokens that need to be replaced. */
+ memset(&sWalker, 0, sizeof(Walker));
+ sWalker.pParse = &sParse;
+ sWalker.xExprCallback = renameColumnExprCb;
+ sWalker.xSelectCallback = renameColumnSelectCb;
+ sWalker.u.pRename = &sCtx;
+
+ sCtx.pTab = pTab;
+ if( rc!=SQLITE_OK ) goto renameColumnFunc_done;
+ if( sParse.pNewTable ){
+ Select *pSelect = sParse.pNewTable->pSelect;
+ if( pSelect ){
+ sParse.rc = SQLITE_OK;
+ sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, 0);
+ rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
+ if( rc==SQLITE_OK ){
+ sqlite3WalkSelect(&sWalker, pSelect);
+ }
+ if( rc!=SQLITE_OK ) goto renameColumnFunc_done;
+ }else{
+ /* A regular table */
+ int bFKOnly = sqlite3_stricmp(zTable, sParse.pNewTable->zName);
+ FKey *pFKey;
+ assert( sParse.pNewTable->pSelect==0 );
+ sCtx.pTab = sParse.pNewTable;
+ if( bFKOnly==0 ){
+ renameTokenFind(
+ &sParse, &sCtx, (void*)sParse.pNewTable->aCol[iCol].zName
+ );
+ if( sCtx.iCol<0 ){
+ renameTokenFind(&sParse, &sCtx, (void*)&sParse.pNewTable->iPKey);
+ }
+ sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck);
+ for(pIdx=sParse.pNewTable->pIndex; pIdx; pIdx=pIdx->pNext){
+ sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
+ }
+ }
+
+ for(pFKey=sParse.pNewTable->pFKey; pFKey; pFKey=pFKey->pNextFrom){
+ for(i=0; i<pFKey->nCol; i++){
+ if( bFKOnly==0 && pFKey->aCol[i].iFrom==iCol ){
+ renameTokenFind(&sParse, &sCtx, (void*)&pFKey->aCol[i]);
+ }
+ if( 0==sqlite3_stricmp(pFKey->zTo, zTable)
+ && 0==sqlite3_stricmp(pFKey->aCol[i].zCol, zOld)
+ ){
+ renameTokenFind(&sParse, &sCtx, (void*)pFKey->aCol[i].zCol);
+ }
+ }
+ }
+ }
+ }else if( sParse.pNewIndex ){
+ sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr);
+ sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere);
+ }else{
+ /* A trigger */
+ TriggerStep *pStep;
+ rc = renameResolveTrigger(&sParse, (bTemp ? 0 : zDb));
+ if( rc!=SQLITE_OK ) goto renameColumnFunc_done;
+
+ for(pStep=sParse.pNewTrigger->step_list; pStep; pStep=pStep->pNext){
+ if( pStep->zTarget ){
+ Table *pTarget = sqlite3LocateTable(&sParse, 0, pStep->zTarget, zDb);
+ if( pTarget==pTab ){
+ if( pStep->pUpsert ){
+ ExprList *pUpsertSet = pStep->pUpsert->pUpsertSet;
+ renameColumnElistNames(&sParse, &sCtx, pUpsertSet, zOld);
+ }
+ renameColumnIdlistNames(&sParse, &sCtx, pStep->pIdList, zOld);
+ renameColumnElistNames(&sParse, &sCtx, pStep->pExprList, zOld);
+ }
+ }
+ }
+
+
+ /* Find tokens to edit in UPDATE OF clause */
+ if( sParse.pTriggerTab==pTab ){
+ renameColumnIdlistNames(&sParse, &sCtx,sParse.pNewTrigger->pColumns,zOld);
+ }
+
+ /* Find tokens to edit in various expressions and selects */
+ renameWalkTrigger(&sWalker, sParse.pNewTrigger);
+ }
+
+ assert( rc==SQLITE_OK );
+ rc = renameEditSql(context, &sCtx, zSql, zNew, bQuote);
+
+renameColumnFunc_done:
+ if( rc!=SQLITE_OK ){
+ if( sParse.zErrMsg ){
+ renameColumnParseError(context, 0, argv[1], argv[2], &sParse);
+ }else{
+ sqlite3_result_error_code(context, rc);
+ }
+ }
+
+ renameParseCleanup(&sParse);
+ renameTokenFree(db, sCtx.pList);
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ db->xAuth = xAuth;
+#endif
+ sqlite3BtreeLeaveAll(db);
+}
+
+/*
+** Walker expression callback used by "RENAME TABLE".
+*/
+static int renameTableExprCb(Walker *pWalker, Expr *pExpr){
+ RenameCtx *p = pWalker->u.pRename;
+ if( pExpr->op==TK_COLUMN && p->pTab==pExpr->pTab ){
+ renameTokenFind(pWalker->pParse, p, (void*)&pExpr->pTab);
+ }
+ return WRC_Continue;
+}
+
+/*
+** Walker select callback used by "RENAME TABLE".
+*/
+static int renameTableSelectCb(Walker *pWalker, Select *pSelect){
+ int i;
+ RenameCtx *p = pWalker->u.pRename;
+ SrcList *pSrc = pSelect->pSrc;
+ for(i=0; i<pSrc->nSrc; i++){
+ struct SrcList_item *pItem = &pSrc->a[i];
+ if( pItem->pTab==p->pTab ){
+ renameTokenFind(pWalker->pParse, p, pItem->zName);
+ }
+ }
+
+ return WRC_Continue;
+}
+
+
+/*
+** This C function implements an SQL user function that is used by SQL code
+** generated by the ALTER TABLE ... RENAME command to modify the definition
+** of any foreign key constraints that use the table being renamed as the
+** parent table. It is passed three arguments:
+**
+** 0: The database containing the table being renamed.
+** 1. type: Type of object ("table", "view" etc.)
+** 2. object: Name of object
+** 3: The complete text of the schema statement being modified,
+** 4: The old name of the table being renamed, and
+** 5: The new name of the table being renamed.
+** 6: True if the schema statement comes from the temp db.
+**
+** It returns the new schema statement. For example:
+**
+** sqlite_rename_table('main', 'CREATE TABLE t1(a REFERENCES t2)','t2','t3',0)
+** -> 'CREATE TABLE t1(a REFERENCES t3)'
+*/
+static void renameTableFunc(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **argv
+){
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ const char *zDb = (const char*)sqlite3_value_text(argv[0]);
+ const char *zInput = (const char*)sqlite3_value_text(argv[3]);
+ const char *zOld = (const char*)sqlite3_value_text(argv[4]);
+ const char *zNew = (const char*)sqlite3_value_text(argv[5]);
+ int bTemp = sqlite3_value_int(argv[6]);
+ UNUSED_PARAMETER(NotUsed);
+
+ if( zInput && zOld && zNew ){
+ Parse sParse;
+ int rc;
+ int bQuote = 1;
+ RenameCtx sCtx;
+ Walker sWalker;
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ sqlite3_xauth xAuth = db->xAuth;
+ db->xAuth = 0;
+#endif
+
+ sqlite3BtreeEnterAll(db);
+
+ memset(&sCtx, 0, sizeof(RenameCtx));
+ sCtx.pTab = sqlite3FindTable(db, zOld, zDb);
+ memset(&sWalker, 0, sizeof(Walker));
+ sWalker.pParse = &sParse;
+ sWalker.xExprCallback = renameTableExprCb;
+ sWalker.xSelectCallback = renameTableSelectCb;
+ sWalker.u.pRename = &sCtx;
+
+ rc = renameParseSql(&sParse, zDb, 1, db, zInput, bTemp);
+
+ if( rc==SQLITE_OK ){
+ int isLegacy = (db->flags & SQLITE_LegacyAlter);
+ if( sParse.pNewTable ){
+ Table *pTab = sParse.pNewTable;
+
+ if( pTab->pSelect ){
+ if( isLegacy==0 ){
+ NameContext sNC;
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pParse = &sParse;
+
+ sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC);
+ if( sParse.nErr ) rc = sParse.rc;
+ sqlite3WalkSelect(&sWalker, pTab->pSelect);
+ }
+ }else{
+ /* Modify any FK definitions to point to the new table. */
+#ifndef SQLITE_OMIT_FOREIGN_KEY
+ if( db->flags & SQLITE_ForeignKeys ){
+ FKey *pFKey;
+ for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
+ if( sqlite3_stricmp(pFKey->zTo, zOld)==0 ){
+ renameTokenFind(&sParse, &sCtx, (void*)pFKey->zTo);
+ }
+ }
+ }
+#endif
+
+ /* If this is the table being altered, fix any table refs in CHECK
+ ** expressions. Also update the name that appears right after the
+ ** "CREATE [VIRTUAL] TABLE" bit. */
+ if( sqlite3_stricmp(zOld, pTab->zName)==0 ){
+ sCtx.pTab = pTab;
+ if( isLegacy==0 ){
+ sqlite3WalkExprList(&sWalker, pTab->pCheck);
+ }
+ renameTokenFind(&sParse, &sCtx, pTab->zName);
+ }
+ }
+ }
+
+ else if( sParse.pNewIndex ){
+ renameTokenFind(&sParse, &sCtx, sParse.pNewIndex->zName);
+ if( isLegacy==0 ){
+ sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere);
+ }
+ }
+
+#ifndef SQLITE_OMIT_TRIGGER
+ else{
+ Trigger *pTrigger = sParse.pNewTrigger;
+ TriggerStep *pStep;
+ if( 0==sqlite3_stricmp(sParse.pNewTrigger->table, zOld)
+ && sCtx.pTab->pSchema==pTrigger->pTabSchema
+ ){
+ renameTokenFind(&sParse, &sCtx, sParse.pNewTrigger->table);
+ }
+
+ if( isLegacy==0 ){
+ rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb);
+ if( rc==SQLITE_OK ){
+ renameWalkTrigger(&sWalker, pTrigger);
+ for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){
+ if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){
+ renameTokenFind(&sParse, &sCtx, pStep->zTarget);
+ }
+ }
+ }
+ }
+ }
+#endif
+ }
+
+ if( rc==SQLITE_OK ){
+ rc = renameEditSql(context, &sCtx, zInput, zNew, bQuote);
+ }
+ if( rc!=SQLITE_OK ){
+ if( sParse.zErrMsg ){
+ renameColumnParseError(context, 0, argv[1], argv[2], &sParse);
+ }else{
+ sqlite3_result_error_code(context, rc);
+ }
+ }
+
+ renameParseCleanup(&sParse);
+ renameTokenFree(db, sCtx.pList);
+ sqlite3BtreeLeaveAll(db);
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ db->xAuth = xAuth;
+#endif
+ }
+
+ return;
+}
+
+/*
+** An SQL user function that checks that there are no parse or symbol
+** resolution problems in a CREATE TRIGGER|TABLE|VIEW|INDEX statement.
+** After an ALTER TABLE .. RENAME operation is performed and the schema
+** reloaded, this function is called on each SQL statement in the schema
+** to ensure that it is still usable.
+**
+** 0: Database name ("main", "temp" etc.).
+** 1: SQL statement.
+** 2: Object type ("view", "table", "trigger" or "index").
+** 3: Object name.
+** 4: True if object is from temp schema.
+**
+** Unless it finds an error, this function normally returns NULL. However, it
+** returns integer value 1 if:
+**
+** * the SQL argument creates a trigger, and
+** * the table that the trigger is attached to is in database zDb.
+*/
+static void renameTableTest(
+ sqlite3_context *context,
+ int NotUsed,
+ sqlite3_value **argv
+){
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ char const *zDb = (const char*)sqlite3_value_text(argv[0]);
+ char const *zInput = (const char*)sqlite3_value_text(argv[1]);
+ int bTemp = sqlite3_value_int(argv[4]);
+ int isLegacy = (db->flags & SQLITE_LegacyAlter);
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ sqlite3_xauth xAuth = db->xAuth;
+ db->xAuth = 0;
+#endif
+
+ UNUSED_PARAMETER(NotUsed);
+ if( zDb && zInput ){
+ int rc;
+ Parse sParse;
+ rc = renameParseSql(&sParse, zDb, 1, db, zInput, bTemp);
+ if( rc==SQLITE_OK ){
+ if( isLegacy==0 && sParse.pNewTable && sParse.pNewTable->pSelect ){
+ NameContext sNC;
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pParse = &sParse;
+ sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, &sNC);
+ if( sParse.nErr ) rc = sParse.rc;
+ }
+
+ else if( sParse.pNewTrigger ){
+ if( isLegacy==0 ){
+ rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb);
+ }
+ if( rc==SQLITE_OK ){
+ int i1 = sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema);
+ int i2 = sqlite3FindDbName(db, zDb);
+ if( i1==i2 ) sqlite3_result_int(context, 1);
+ }
+ }
+ }
+
+ if( rc!=SQLITE_OK ){
+ renameColumnParseError(context, 1, argv[2], argv[3], &sParse);
+ }
+ renameParseCleanup(&sParse);
+ }
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ db->xAuth = xAuth;
+#endif
+}
+
+/*
+** Register built-in functions used to help implement ALTER TABLE
+*/
+SQLITE_PRIVATE void sqlite3AlterFunctions(void){
+ static FuncDef aAlterTableFuncs[] = {
+ FUNCTION(sqlite_rename_column, 9, 0, 0, renameColumnFunc),
+ FUNCTION(sqlite_rename_table, 7, 0, 0, renameTableFunc),
+ FUNCTION(sqlite_rename_test, 5, 0, 0, renameTableTest),
+ };
+ sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
+}
#endif /* SQLITE_ALTER_TABLE */
/************** End of alter.c ***********************************************/
@@ -101566,6 +103225,7 @@ static const FuncDef statInitFuncdef = {
0, /* pNext */
statInit, /* xSFunc */
0, /* xFinalize */
+ 0, 0, /* xValue, xInverse */
"stat_init", /* zName */
{0}
};
@@ -101882,6 +103542,7 @@ static const FuncDef statPushFuncdef = {
0, /* pNext */
statPush, /* xSFunc */
0, /* xFinalize */
+ 0, 0, /* xValue, xInverse */
"stat_push", /* zName */
{0}
};
@@ -102033,6 +103694,7 @@ static const FuncDef statGetFuncdef = {
0, /* pNext */
statGet, /* xSFunc */
0, /* xFinalize */
+ 0, 0, /* xValue, xInverse */
"stat_get", /* zName */
{0}
};
@@ -102352,10 +104014,7 @@ static void analyzeOneTable(
callStatGet(v, regStat4, STAT_GET_NLT, regLt);
callStatGet(v, regStat4, STAT_GET_NDLT, regDLt);
sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0);
- /* We know that the regSampleRowid row exists because it was read by
- ** the previous loop. Thus the not-found jump of seekOp will never
- ** be taken */
- VdbeCoverageNeverTaken(v);
+ VdbeCoverage(v);
#ifdef SQLITE_ENABLE_STAT3
sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iTabCur, 0, regSample);
#else
@@ -102995,7 +104654,7 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
/* Load the statistics from the sqlite_stat4 table. */
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- if( rc==SQLITE_OK && OptimizationEnabled(db, SQLITE_Stat34) ){
+ if( rc==SQLITE_OK ){
db->lookaside.bDisable++;
rc = loadStat4(db, sInfo.zDatabase);
db->lookaside.bDisable--;
@@ -103434,6 +105093,7 @@ SQLITE_PRIVATE void sqlite3Detach(Parse *pParse, Expr *pDbname){
0, /* pNext */
detachFunc, /* xSFunc */
0, /* xFinalize */
+ 0, 0, /* xValue, xInverse */
"sqlite_detach", /* zName */
{0}
};
@@ -103453,6 +105113,7 @@ SQLITE_PRIVATE void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *p
0, /* pNext */
attachFunc, /* xSFunc */
0, /* xFinalize */
+ 0, 0, /* xValue, xInverse */
"sqlite_attach", /* zName */
{0}
};
@@ -103725,7 +105386,7 @@ SQLITE_API int sqlite3_set_authorizer(
sqlite3_mutex_enter(db->mutex);
db->xAuth = (sqlite3_xauth)xAuth;
db->pAuthArg = pArg;
- sqlite3ExpirePreparedStatements(db);
+ sqlite3ExpirePreparedStatements(db, 0);
sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
}
@@ -103854,7 +105515,7 @@ SQLITE_PRIVATE int sqlite3AuthCheck(
/* Don't do any authorization checks if the database is initialising
** or if the parser is being invoked from within sqlite3_declare_vtab.
*/
- if( db->init.busy || IN_DECLARE_VTAB ){
+ if( db->init.busy || IN_SPECIAL_PARSE ){
return SQLITE_OK;
}
@@ -104146,7 +105807,6 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
/* Get the VDBE program ready for execution
*/
if( v && pParse->nErr==0 && !db->mallocFailed ){
- assert( pParse->iCacheLevel==0 ); /* Disables and re-enables match */
/* A minimum of one cursor is required if autoincrement is used
* See ticket [a696379c1f08866] */
if( pParse->pAinc!=0 && pParse->nTab==0 ) pParse->nTab = 1;
@@ -104361,7 +106021,7 @@ SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const cha
/*
** Reclaim the memory used by an index
*/
-static void freeIndex(sqlite3 *db, Index *p){
+SQLITE_PRIVATE void sqlite3FreeIndex(sqlite3 *db, Index *p){
#ifndef SQLITE_OMIT_ANALYZE
sqlite3DeleteIndexSamples(db, p);
#endif
@@ -104401,7 +106061,7 @@ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char
p->pNext = pIndex->pNext;
}
}
- freeIndex(db, pIndex);
+ sqlite3FreeIndex(db, pIndex);
}
db->mDbFlags |= DBFLAG_SchemaChange;
}
@@ -104547,7 +106207,7 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
assert( pOld==pIndex || pOld==0 );
}
- freeIndex(db, pIndex);
+ sqlite3FreeIndex(db, pIndex);
}
/* Delete any foreign keys attached to this table. */
@@ -104705,7 +106365,7 @@ SQLITE_PRIVATE int sqlite3TwoPartName(
return -1;
}
}else{
- assert( db->init.iDb==0 || db->init.busy
+ assert( db->init.iDb==0 || db->init.busy || IN_RENAME_OBJECT
|| (db->mDbFlags & DBFLAG_Vacuum)!=0);
iDb = db->init.iDb;
*pUnqual = pName1;
@@ -104800,6 +106460,9 @@ SQLITE_PRIVATE void sqlite3StartTable(
}
if( !OMIT_TEMPDB && isTemp ) iDb = 1;
zName = sqlite3NameFromToken(db, pName);
+ if( IN_RENAME_OBJECT ){
+ sqlite3RenameTokenMap(pParse, (void*)zName, pName);
+ }
}
pParse->sNameToken = *pName;
if( zName==0 ) return;
@@ -104835,7 +106498,7 @@ SQLITE_PRIVATE void sqlite3StartTable(
** and types will be used, so there is no need to test for namespace
** collisions.
*/
- if( !IN_DECLARE_VTAB ){
+ if( !IN_SPECIAL_PARSE ){
char *zDb = db->aDb[iDb].zDbSName;
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
goto begin_table_error;
@@ -104994,6 +106657,7 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
}
z = sqlite3DbMallocRaw(db, pName->n + pType->n + 2);
if( z==0 ) return;
+ if( IN_RENAME_OBJECT ) sqlite3RenameTokenMap(pParse, (void*)z, pName);
memcpy(z, pName->z, pName->n);
z[pName->n] = 0;
sqlite3Dequote(z);
@@ -105200,6 +106864,9 @@ SQLITE_PRIVATE void sqlite3AddDefaultValue(
sqlite3DbFree(db, x.u.zToken);
}
}
+ if( IN_RENAME_OBJECT ){
+ sqlite3RenameExprUnmap(pParse, pExpr);
+ }
sqlite3ExprDelete(db, pExpr);
}
@@ -105291,6 +106958,9 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey(
&& sqlite3StrICmp(sqlite3ColumnType(pCol,""), "INTEGER")==0
&& sortOrder!=SQLITE_SO_DESC
){
+ if( IN_RENAME_OBJECT && pList ){
+ sqlite3RenameTokenRemap(pParse, &pTab->iPKey, pList->a[0].pExpr);
+ }
pTab->iPKey = iCol;
pTab->keyConf = (u8)onError;
assert( autoInc==0 || autoInc==1 );
@@ -105616,6 +107286,31 @@ static int hasColumn(const i16 *aiCol, int nCol, int x){
return 0;
}
+/* Recompute the colNotIdxed field of the Index.
+**
+** colNotIdxed is a bitmask that has a 0 bit representing each indexed
+** columns that are within the first 63 columns of the table. The
+** high-order bit of colNotIdxed is always 1. All unindexed columns
+** of the table have a 1.
+**
+** The colNotIdxed mask is AND-ed with the SrcList.a[].colUsed mask
+** to determine if the index is covering index.
+*/
+static void recomputeColumnsNotIndexed(Index *pIdx){
+ Bitmask m = 0;
+ int j;
+ for(j=pIdx->nColumn-1; j>=0; j--){
+ int x = pIdx->aiColumn[j];
+ if( x>=0 ){
+ testcase( x==BMS-1 );
+ testcase( x==BMS-2 );
+ if( x<BMS-1 ) m |= MASKBIT(x);
+ }
+ }
+ pIdx->colNotIdxed = ~m;
+ assert( (pIdx->colNotIdxed>>63)==1 );
+}
+
/*
** This routine runs at the end of parsing a CREATE TABLE statement that
** has a WITHOUT ROWID clause. The job of this routine is to convert both
@@ -105658,10 +107353,6 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
}
}
- /* The remaining transformations only apply to b-tree tables, not to
- ** virtual tables */
- if( IN_DECLARE_VTAB ) return;
-
/* Convert the P3 operand of the OP_CreateBtree opcode from BTREE_INTKEY
** into BTREE_BLOBKEY.
*/
@@ -105684,7 +107375,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
assert( pParse->pNewTable==pTab );
sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0,
SQLITE_IDXTYPE_PRIMARYKEY);
- if( db->mallocFailed ) return;
+ if( db->mallocFailed || pParse->nErr ) return;
pPk = sqlite3PrimaryKeyIndex(pTab);
pTab->iPKey = -1;
}else{
@@ -105764,6 +107455,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
}else{
pPk->nColumn = pTab->nCol;
}
+ recomputeColumnsNotIndexed(pPk);
}
/*
@@ -106067,7 +107759,12 @@ SQLITE_PRIVATE void sqlite3CreateView(
** allocated rather than point to the input string - which means that
** they will persist after the current sqlite3_exec() call returns.
*/
- p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
+ if( IN_RENAME_OBJECT ){
+ p->pSelect = pSelect;
+ pSelect = 0;
+ }else{
+ p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
+ }
p->pCheck = sqlite3ExprListDup(db, pCNames, EXPRDUP_REDUCE);
if( db->mallocFailed ) goto create_view_fail;
@@ -106092,6 +107789,9 @@ SQLITE_PRIVATE void sqlite3CreateView(
create_view_fail:
sqlite3SelectDelete(db, pSelect);
+ if( IN_RENAME_OBJECT ){
+ sqlite3RenameExprlistUnmap(pParse, pCNames);
+ }
sqlite3ExprListDelete(db, pCNames);
return;
}
@@ -106165,6 +107865,10 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
assert( pTable->pSelect );
pSel = sqlite3SelectDup(db, pTable->pSelect, 0);
if( pSel ){
+#ifndef SQLITE_OMIT_ALTERTABLE
+ u8 eParseMode = pParse->eParseMode;
+ pParse->eParseMode = PARSE_MODE_NORMAL;
+#endif
n = pParse->nTab;
sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
pTable->nCol = -1;
@@ -106210,10 +107914,18 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
sqlite3DeleteTable(db, pSelTab);
sqlite3SelectDelete(db, pSel);
db->lookaside.bDisable--;
+#ifndef SQLITE_OMIT_ALTERTABLE
+ pParse->eParseMode = eParseMode;
+#endif
} else {
nErr++;
}
pTable->pSchema->schemaFlags |= DB_UnresetViews;
+ if( db->mallocFailed ){
+ sqlite3DeleteColumnNames(db, pTable);
+ pTable->aCol = 0;
+ pTable->nCol = 0;
+ }
#endif /* SQLITE_OMIT_VIEW */
return nErr;
}
@@ -106552,8 +108264,10 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView,
v = sqlite3GetVdbe(pParse);
if( v ){
sqlite3BeginWriteOperation(pParse, 1, iDb);
- sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName);
- sqlite3FkDropTable(pParse, pName, pTab);
+ if( !isView ){
+ sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName);
+ sqlite3FkDropTable(pParse, pName, pTab);
+ }
sqlite3CodeDropTable(pParse, pTab, iDb, isView);
}
@@ -106628,6 +108342,9 @@ SQLITE_PRIVATE void sqlite3CreateForeignKey(
pFKey->pNextFrom = p->pFKey;
z = (char*)&pFKey->aCol[nCol];
pFKey->zTo = z;
+ if( IN_RENAME_OBJECT ){
+ sqlite3RenameTokenMap(pParse, (void*)z, pTo);
+ }
memcpy(z, pTo->z, pTo->n);
z[pTo->n] = 0;
sqlite3Dequote(z);
@@ -106650,12 +108367,18 @@ SQLITE_PRIVATE void sqlite3CreateForeignKey(
pFromCol->a[i].zName);
goto fk_end;
}
+ if( IN_RENAME_OBJECT ){
+ sqlite3RenameTokenRemap(pParse, &pFKey->aCol[i], pFromCol->a[i].zName);
+ }
}
}
if( pToCol ){
for(i=0; i<nCol; i++){
int n = sqlite3Strlen30(pToCol->a[i].zName);
pFKey->aCol[i].zCol = z;
+ if( IN_RENAME_OBJECT ){
+ sqlite3RenameTokenRemap(pParse, z, pToCol->a[i].zName);
+ }
memcpy(z, pToCol->a[i].zName, n);
z[n] = 0;
z += n+1;
@@ -106988,20 +108711,22 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
goto exit_create_index;
}
- if( !db->init.busy ){
- if( sqlite3FindTable(db, zName, 0)!=0 ){
- sqlite3ErrorMsg(pParse, "there is already a table named %s", zName);
- goto exit_create_index;
+ if( !IN_RENAME_OBJECT ){
+ if( !db->init.busy ){
+ if( sqlite3FindTable(db, zName, 0)!=0 ){
+ sqlite3ErrorMsg(pParse, "there is already a table named %s", zName);
+ goto exit_create_index;
+ }
}
- }
- if( sqlite3FindIndex(db, zName, pDb->zDbSName)!=0 ){
- if( !ifNotExist ){
- sqlite3ErrorMsg(pParse, "index %s already exists", zName);
- }else{
- assert( !db->init.busy );
- sqlite3CodeVerifySchema(pParse, iDb);
+ if( sqlite3FindIndex(db, zName, pDb->zDbSName)!=0 ){
+ if( !ifNotExist ){
+ sqlite3ErrorMsg(pParse, "index %s already exists", zName);
+ }else{
+ assert( !db->init.busy );
+ sqlite3CodeVerifySchema(pParse, iDb);
+ }
+ goto exit_create_index;
}
- goto exit_create_index;
}
}else{
int n;
@@ -107017,13 +108742,13 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
** The following statement converts "sqlite3_autoindex..." into
** "sqlite3_butoindex..." in order to make the names distinct.
** The "vtab_err.test" test demonstrates the need of this statement. */
- if( IN_DECLARE_VTAB ) zName[7]++;
+ if( IN_SPECIAL_PARSE ) zName[7]++;
}
/* Check for authorization to create an index.
*/
#ifndef SQLITE_OMIT_AUTHORIZATION
- {
+ if( !IN_RENAME_OBJECT ){
const char *zDb = pDb->zDbSName;
if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iDb), 0, zDb) ){
goto exit_create_index;
@@ -107110,7 +108835,12 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
** TODO: Issue a warning if the table primary key is used as part of the
** index key.
*/
- for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
+ pListItem = pList->a;
+ if( IN_RENAME_OBJECT ){
+ pIndex->aColExpr = pList;
+ pList = 0;
+ }
+ for(i=0; i<pIndex->nKeyCol; i++, pListItem++){
Expr *pCExpr; /* The i-th index expression */
int requestedSortOrder; /* ASC or DESC on the i-th expression */
const char *zColl; /* Collation sequence name */
@@ -107126,12 +108856,8 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
goto exit_create_index;
}
if( pIndex->aColExpr==0 ){
- ExprList *pCopy = sqlite3ExprListDup(db, pList, 0);
- pIndex->aColExpr = pCopy;
- if( !db->mallocFailed ){
- assert( pCopy!=0 );
- pListItem = &pCopy->a[i];
- }
+ pIndex->aColExpr = pList;
+ pList = 0;
}
j = XN_EXPR;
pIndex->aiColumn[i] = XN_EXPR;
@@ -107197,6 +108923,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
** it as a covering index */
assert( HasRowid(pTab)
|| pTab->iPKey<0 || sqlite3ColumnOfIndex(pIndex, pTab->iPKey)>=0 );
+ recomputeColumnsNotIndexed(pIndex);
if( pTblName!=0 && pIndex->nColumn>=pTab->nCol ){
pIndex->isCovering = 1;
for(j=0; j<pTab->nCol; j++){
@@ -107269,98 +108996,101 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
}
}
- /* Link the new Index structure to its table and to the other
- ** in-memory database structures.
- */
- assert( pParse->nErr==0 );
- if( db->init.busy ){
- Index *p;
- assert( !IN_DECLARE_VTAB );
- assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
- p = sqlite3HashInsert(&pIndex->pSchema->idxHash,
- pIndex->zName, pIndex);
- if( p ){
- assert( p==pIndex ); /* Malloc must have failed */
- sqlite3OomFault(db);
- goto exit_create_index;
- }
- db->mDbFlags |= DBFLAG_SchemaChange;
- if( pTblName!=0 ){
- pIndex->tnum = db->init.newTnum;
- }
- }
-
- /* If this is the initial CREATE INDEX statement (or CREATE TABLE if the
- ** index is an implied index for a UNIQUE or PRIMARY KEY constraint) then
- ** emit code to allocate the index rootpage on disk and make an entry for
- ** the index in the sqlite_master table and populate the index with
- ** content. But, do not do this if we are simply reading the sqlite_master
- ** table to parse the schema, or if this index is the PRIMARY KEY index
- ** of a WITHOUT ROWID table.
- **
- ** If pTblName==0 it means this index is generated as an implied PRIMARY KEY
- ** or UNIQUE index in a CREATE TABLE statement. Since the table
- ** has just been created, it contains no data and the index initialization
- ** step can be skipped.
- */
- else if( HasRowid(pTab) || pTblName!=0 ){
- Vdbe *v;
- char *zStmt;
- int iMem = ++pParse->nMem;
-
- v = sqlite3GetVdbe(pParse);
- if( v==0 ) goto exit_create_index;
-
- sqlite3BeginWriteOperation(pParse, 1, iDb);
+ if( !IN_RENAME_OBJECT ){
- /* Create the rootpage for the index using CreateIndex. But before
- ** doing so, code a Noop instruction and store its address in
- ** Index.tnum. This is required in case this index is actually a
- ** PRIMARY KEY and the table is actually a WITHOUT ROWID table. In
- ** that case the convertToWithoutRowidTable() routine will replace
- ** the Noop with a Goto to jump over the VDBE code generated below. */
- pIndex->tnum = sqlite3VdbeAddOp0(v, OP_Noop);
- sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, iMem, BTREE_BLOBKEY);
-
- /* Gather the complete text of the CREATE INDEX statement into
- ** the zStmt variable
+ /* Link the new Index structure to its table and to the other
+ ** in-memory database structures.
*/
- if( pStart ){
- int n = (int)(pParse->sLastToken.z - pName->z) + pParse->sLastToken.n;
- if( pName->z[n-1]==';' ) n--;
- /* A named index with an explicit CREATE INDEX statement */
- zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",
- onError==OE_None ? "" : " UNIQUE", n, pName->z);
- }else{
- /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
- /* zStmt = sqlite3MPrintf(""); */
- zStmt = 0;
+ assert( pParse->nErr==0 );
+ if( db->init.busy ){
+ Index *p;
+ assert( !IN_SPECIAL_PARSE );
+ assert( sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
+ p = sqlite3HashInsert(&pIndex->pSchema->idxHash,
+ pIndex->zName, pIndex);
+ if( p ){
+ assert( p==pIndex ); /* Malloc must have failed */
+ sqlite3OomFault(db);
+ goto exit_create_index;
+ }
+ db->mDbFlags |= DBFLAG_SchemaChange;
+ if( pTblName!=0 ){
+ pIndex->tnum = db->init.newTnum;
+ }
}
- /* Add an entry in sqlite_master for this index
+ /* If this is the initial CREATE INDEX statement (or CREATE TABLE if the
+ ** index is an implied index for a UNIQUE or PRIMARY KEY constraint) then
+ ** emit code to allocate the index rootpage on disk and make an entry for
+ ** the index in the sqlite_master table and populate the index with
+ ** content. But, do not do this if we are simply reading the sqlite_master
+ ** table to parse the schema, or if this index is the PRIMARY KEY index
+ ** of a WITHOUT ROWID table.
+ **
+ ** If pTblName==0 it means this index is generated as an implied PRIMARY KEY
+ ** or UNIQUE index in a CREATE TABLE statement. Since the table
+ ** has just been created, it contains no data and the index initialization
+ ** step can be skipped.
*/
- sqlite3NestedParse(pParse,
- "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);",
- db->aDb[iDb].zDbSName, MASTER_NAME,
- pIndex->zName,
- pTab->zName,
- iMem,
- zStmt
- );
- sqlite3DbFree(db, zStmt);
+ else if( HasRowid(pTab) || pTblName!=0 ){
+ Vdbe *v;
+ char *zStmt;
+ int iMem = ++pParse->nMem;
+
+ v = sqlite3GetVdbe(pParse);
+ if( v==0 ) goto exit_create_index;
+
+ sqlite3BeginWriteOperation(pParse, 1, iDb);
+
+ /* Create the rootpage for the index using CreateIndex. But before
+ ** doing so, code a Noop instruction and store its address in
+ ** Index.tnum. This is required in case this index is actually a
+ ** PRIMARY KEY and the table is actually a WITHOUT ROWID table. In
+ ** that case the convertToWithoutRowidTable() routine will replace
+ ** the Noop with a Goto to jump over the VDBE code generated below. */
+ pIndex->tnum = sqlite3VdbeAddOp0(v, OP_Noop);
+ sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, iMem, BTREE_BLOBKEY);
+
+ /* Gather the complete text of the CREATE INDEX statement into
+ ** the zStmt variable
+ */
+ if( pStart ){
+ int n = (int)(pParse->sLastToken.z - pName->z) + pParse->sLastToken.n;
+ if( pName->z[n-1]==';' ) n--;
+ /* A named index with an explicit CREATE INDEX statement */
+ zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",
+ onError==OE_None ? "" : " UNIQUE", n, pName->z);
+ }else{
+ /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
+ /* zStmt = sqlite3MPrintf(""); */
+ zStmt = 0;
+ }
- /* Fill the index with data and reparse the schema. Code an OP_Expire
- ** to invalidate all pre-compiled statements.
- */
- if( pTblName ){
- sqlite3RefillIndex(pParse, pIndex, iMem);
- sqlite3ChangeCookie(pParse, iDb);
- sqlite3VdbeAddParseSchemaOp(v, iDb,
- sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName));
- sqlite3VdbeAddOp0(v, OP_Expire);
- }
+ /* Add an entry in sqlite_master for this index
+ */
+ sqlite3NestedParse(pParse,
+ "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);",
+ db->aDb[iDb].zDbSName, MASTER_NAME,
+ pIndex->zName,
+ pTab->zName,
+ iMem,
+ zStmt
+ );
+ sqlite3DbFree(db, zStmt);
- sqlite3VdbeJumpHere(v, pIndex->tnum);
+ /* Fill the index with data and reparse the schema. Code an OP_Expire
+ ** to invalidate all pre-compiled statements.
+ */
+ if( pTblName ){
+ sqlite3RefillIndex(pParse, pIndex, iMem);
+ sqlite3ChangeCookie(pParse, iDb);
+ sqlite3VdbeAddParseSchemaOp(v, iDb,
+ sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName));
+ sqlite3VdbeAddOp2(v, OP_Expire, 0, 1);
+ }
+
+ sqlite3VdbeJumpHere(v, pIndex->tnum);
+ }
}
/* When adding an index to the list of indices for a table, make
@@ -107384,10 +109114,15 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
}
pIndex = 0;
}
+ else if( IN_RENAME_OBJECT ){
+ assert( pParse->pNewIndex==0 );
+ pParse->pNewIndex = pIndex;
+ pIndex = 0;
+ }
/* Clean up before exiting */
exit_create_index:
- if( pIndex ) freeIndex(db, pIndex);
+ if( pIndex ) sqlite3FreeIndex(db, pIndex);
sqlite3ExprDelete(db, pPIWhere);
sqlite3ExprListDelete(db, pList);
sqlite3SrcListDelete(db, pTblName);
@@ -107556,7 +109291,8 @@ SQLITE_PRIVATE void *sqlite3ArrayAllocate(
**
** A new IdList is returned, or NULL if malloc() fails.
*/
-SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3 *db, IdList *pList, Token *pToken){
+SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token *pToken){
+ sqlite3 *db = pParse->db;
int i;
if( pList==0 ){
pList = sqlite3DbMallocZero(db, sizeof(IdList) );
@@ -107574,6 +109310,9 @@ SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3 *db, IdList *pList, Token *pT
return 0;
}
pList->a[i].zName = sqlite3NameFromToken(db, pToken);
+ if( IN_RENAME_OBJECT && pList->a[i].zName ){
+ sqlite3RenameTokenMap(pParse, (void*)pList->a[i].zName, pToken);
+ }
return pList;
}
@@ -107820,6 +109559,12 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(
}
assert( p->nSrc>0 );
pItem = &p->a[p->nSrc-1];
+ assert( (pTable==0)==(pDatabase==0) );
+ assert( pItem->zName==0 || pDatabase!=0 );
+ if( IN_RENAME_OBJECT && pItem->zName ){
+ Token *pToken = (ALWAYS(pDatabase) && pDatabase->z) ? pDatabase : pTable;
+ sqlite3RenameTokenMap(pParse, pItem->zName, pToken);
+ }
assert( pAlias!=0 );
if( pAlias->n ){
pItem->zAlias = sqlite3NameFromToken(db, pAlias);
@@ -109373,9 +111118,8 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
}
iKey = iPk;
}else{
- iKey = pParse->nMem + 1;
- iKey = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iTabCur, iKey, 0);
- if( iKey>pParse->nMem ) pParse->nMem = iKey;
+ iKey = ++pParse->nMem;
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, -1, iKey);
}
if( eOnePass!=ONEPASS_OFF ){
@@ -109808,7 +111552,6 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey(
if( pIdx->pPartIdxWhere ){
*piPartIdxLabel = sqlite3VdbeMakeLabel(v);
pParse->iSelfTab = iDataCur + 1;
- sqlite3ExprCachePush(pParse);
sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel,
SQLITE_JUMPIFNULL);
pParse->iSelfTab = 0;
@@ -109855,7 +111598,6 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey(
SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse *pParse, int iLabel){
if( iLabel ){
sqlite3VdbeResolveLabel(pParse->pVdbe, iLabel);
- sqlite3ExprCachePop(pParse);
}
}
@@ -111368,7 +113110,7 @@ static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){
i64 v = sqlite3_value_int64(argv[0]);
p->rSum += v;
if( (p->approx|p->overflow)==0 && sqlite3AddInt64(&p->iSum, v) ){
- p->overflow = 1;
+ p->approx = p->overflow = 1;
}
}else{
p->rSum += sqlite3_value_double(argv[0]);
@@ -111376,6 +113118,32 @@ static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){
}
}
}
+#ifndef SQLITE_OMIT_WINDOWFUNC
+static void sumInverse(sqlite3_context *context, int argc, sqlite3_value**argv){
+ SumCtx *p;
+ int type;
+ assert( argc==1 );
+ UNUSED_PARAMETER(argc);
+ p = sqlite3_aggregate_context(context, sizeof(*p));
+ type = sqlite3_value_numeric_type(argv[0]);
+ /* p is always non-NULL because sumStep() will have been called first
+ ** to initialize it */
+ if( ALWAYS(p) && type!=SQLITE_NULL ){
+ assert( p->cnt>0 );
+ p->cnt--;
+ assert( type==SQLITE_INTEGER || p->approx );
+ if( type==SQLITE_INTEGER && p->approx==0 ){
+ i64 v = sqlite3_value_int64(argv[0]);
+ p->rSum -= v;
+ p->iSum -= v;
+ }else{
+ p->rSum -= sqlite3_value_double(argv[0]);
+ }
+ }
+}
+#else
+# define sumInverse 0
+#endif /* SQLITE_OMIT_WINDOWFUNC */
static void sumFinalize(sqlite3_context *context){
SumCtx *p;
p = sqlite3_aggregate_context(context, 0);
@@ -111410,6 +113178,9 @@ static void totalFinalize(sqlite3_context *context){
typedef struct CountCtx CountCtx;
struct CountCtx {
i64 n;
+#ifdef SQLITE_DEBUG
+ int bInverse; /* True if xInverse() ever called */
+#endif
};
/*
@@ -111427,7 +113198,7 @@ static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){
** sure it still operates correctly, verify that its count agrees with our
** internal count when using count(*) and when the total count can be
** expressed as a 32-bit integer. */
- assert( argc==1 || p==0 || p->n>0x7fffffff
+ assert( argc==1 || p==0 || p->n>0x7fffffff || p->bInverse
|| p->n==sqlite3_aggregate_count(context) );
#endif
}
@@ -111436,6 +113207,21 @@ static void countFinalize(sqlite3_context *context){
p = sqlite3_aggregate_context(context, 0);
sqlite3_result_int64(context, p ? p->n : 0);
}
+#ifndef SQLITE_OMIT_WINDOWFUNC
+static void countInverse(sqlite3_context *ctx, int argc, sqlite3_value **argv){
+ CountCtx *p;
+ p = sqlite3_aggregate_context(ctx, sizeof(*p));
+ /* p is always non-NULL since countStep() will have been called first */
+ if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0])) && ALWAYS(p) ){
+ p->n--;
+#ifdef SQLITE_DEBUG
+ p->bInverse = 1;
+#endif
+ }
+}
+#else
+# define countInverse 0
+#endif /* SQLITE_OMIT_WINDOWFUNC */
/*
** Routines to implement min() and max() aggregate functions.
@@ -111452,7 +113238,7 @@ static void minmaxStep(
pBest = (Mem *)sqlite3_aggregate_context(context, sizeof(*pBest));
if( !pBest ) return;
- if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
+ if( sqlite3_value_type(pArg)==SQLITE_NULL ){
if( pBest->flags ) sqlite3SkipAccumulatorLoad(context);
}else if( pBest->flags ){
int max;
@@ -111478,16 +113264,26 @@ static void minmaxStep(
sqlite3VdbeMemCopy(pBest, pArg);
}
}
-static void minMaxFinalize(sqlite3_context *context){
+static void minMaxValueFinalize(sqlite3_context *context, int bValue){
sqlite3_value *pRes;
pRes = (sqlite3_value *)sqlite3_aggregate_context(context, 0);
if( pRes ){
if( pRes->flags ){
sqlite3_result_value(context, pRes);
}
- sqlite3VdbeMemRelease(pRes);
+ if( bValue==0 ) sqlite3VdbeMemRelease(pRes);
}
}
+#ifndef SQLITE_OMIT_WINDOWFUNC
+static void minMaxValue(sqlite3_context *context){
+ minMaxValueFinalize(context, 1);
+}
+#else
+# define minMaxValue 0
+#endif /* SQLITE_OMIT_WINDOWFUNC */
+static void minMaxFinalize(sqlite3_context *context){
+ minMaxValueFinalize(context, 0);
+}
/*
** group_concat(EXPR, ?SEPARATOR?)
@@ -111524,6 +113320,38 @@ static void groupConcatStep(
if( zVal ) sqlite3_str_append(pAccum, zVal, nVal);
}
}
+#ifndef SQLITE_OMIT_WINDOWFUNC
+static void groupConcatInverse(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ int n;
+ StrAccum *pAccum;
+ assert( argc==1 || argc==2 );
+ if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
+ pAccum = (StrAccum*)sqlite3_aggregate_context(context, sizeof(*pAccum));
+ /* pAccum is always non-NULL since groupConcatStep() will have always
+ ** run frist to initialize it */
+ if( ALWAYS(pAccum) ){
+ n = sqlite3_value_bytes(argv[0]);
+ if( argc==2 ){
+ n += sqlite3_value_bytes(argv[1]);
+ }else{
+ n++;
+ }
+ if( n>=(int)pAccum->nChar ){
+ pAccum->nChar = 0;
+ }else{
+ pAccum->nChar -= n;
+ memmove(pAccum->zText, &pAccum->zText[n], pAccum->nChar);
+ }
+ if( pAccum->nChar==0 ) pAccum->mxAlloc = 0;
+ }
+}
+#else
+# define groupConcatInverse 0
+#endif /* SQLITE_OMIT_WINDOWFUNC */
static void groupConcatFinalize(sqlite3_context *context){
StrAccum *pAccum;
pAccum = sqlite3_aggregate_context(context, 0);
@@ -111538,6 +113366,24 @@ static void groupConcatFinalize(sqlite3_context *context){
}
}
}
+#ifndef SQLITE_OMIT_WINDOWFUNC
+static void groupConcatValue(sqlite3_context *context){
+ sqlite3_str *pAccum;
+ pAccum = (sqlite3_str*)sqlite3_aggregate_context(context, 0);
+ if( pAccum ){
+ if( pAccum->accError==SQLITE_TOOBIG ){
+ sqlite3_result_error_toobig(context);
+ }else if( pAccum->accError==SQLITE_NOMEM ){
+ sqlite3_result_error_nomem(context);
+ }else{
+ const char *zText = sqlite3_str_value(pAccum);
+ sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT);
+ }
+ }
+}
+#else
+# define groupConcatValue 0
+#endif /* SQLITE_OMIT_WINDOWFUNC */
/*
** This routine does per-connection function registration. Most
@@ -111575,10 +113421,10 @@ SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive)
}else{
pInfo = (struct compareInfo*)&likeInfoNorm;
}
- sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0);
- sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0);
+ sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0, 0, 0);
+ sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0, 0, 0, 0);
sqlite3CreateFunc(db, "glob", 2, SQLITE_UTF8,
- (struct compareInfo*)&globInfo, likeFunc, 0, 0, 0);
+ (struct compareInfo*)&globInfo, likeFunc, 0, 0, 0, 0, 0);
setLikeOptFlag(db, "glob", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE);
setLikeOptFlag(db, "like",
caseSensitive ? (SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE) : SQLITE_FUNC_LIKE);
@@ -111687,11 +113533,11 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
FUNCTION(trim, 2, 3, 0, trimFunc ),
FUNCTION(min, -1, 0, 1, minmaxFunc ),
FUNCTION(min, 0, 0, 1, 0 ),
- AGGREGATE2(min, 1, 0, 1, minmaxStep, minMaxFinalize,
+ WAGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize, minMaxValue, 0,
SQLITE_FUNC_MINMAX ),
FUNCTION(max, -1, 1, 1, minmaxFunc ),
FUNCTION(max, 0, 1, 1, 0 ),
- AGGREGATE2(max, 1, 1, 1, minmaxStep, minMaxFinalize,
+ WAGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize, minMaxValue, 0,
SQLITE_FUNC_MINMAX ),
FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
@@ -111722,14 +113568,17 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ),
FUNCTION(substr, 2, 0, 0, substrFunc ),
FUNCTION(substr, 3, 0, 0, substrFunc ),
- AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ),
- AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ),
- AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ),
- AGGREGATE2(count, 0, 0, 0, countStep, countFinalize,
- SQLITE_FUNC_COUNT ),
- AGGREGATE(count, 1, 0, 0, countStep, countFinalize ),
- AGGREGATE(group_concat, 1, 0, 0, groupConcatStep, groupConcatFinalize),
- AGGREGATE(group_concat, 2, 0, 0, groupConcatStep, groupConcatFinalize),
+ WAGGREGATE(sum, 1,0,0, sumStep, sumFinalize, sumFinalize, sumInverse, 0),
+ WAGGREGATE(total, 1,0,0, sumStep,totalFinalize,totalFinalize,sumInverse, 0),
+ WAGGREGATE(avg, 1,0,0, sumStep, avgFinalize, avgFinalize, sumInverse, 0),
+ WAGGREGATE(count, 0,0,0, countStep,
+ countFinalize, countFinalize, countInverse, SQLITE_FUNC_COUNT ),
+ WAGGREGATE(count, 1,0,0, countStep,
+ countFinalize, countFinalize, countInverse, 0 ),
+ WAGGREGATE(group_concat, 1, 0, 0, groupConcatStep,
+ groupConcatFinalize, groupConcatValue, groupConcatInverse, 0),
+ WAGGREGATE(group_concat, 2, 0, 0, groupConcatStep,
+ groupConcatFinalize, groupConcatValue, groupConcatInverse, 0),
LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
#ifdef SQLITE_CASE_SENSITIVE_LIKE
@@ -111749,6 +113598,7 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
#ifndef SQLITE_OMIT_ALTERTABLE
sqlite3AlterFunctions();
#endif
+ sqlite3WindowFunctions();
#if defined(SQLITE_ENABLE_STAT3) || defined(SQLITE_ENABLE_STAT4)
sqlite3AnalyzeFunctions();
#endif
@@ -112486,11 +114336,12 @@ static void fkTriggerDelete(sqlite3 *dbMem, Trigger *p){
*/
SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
sqlite3 *db = pParse->db;
- if( (db->flags&SQLITE_ForeignKeys) && !IsVirtual(pTab) && !pTab->pSelect ){
+ if( (db->flags&SQLITE_ForeignKeys) && !IsVirtual(pTab) ){
int iSkip = 0;
Vdbe *v = sqlite3GetVdbe(pParse);
assert( v ); /* VDBE has already been allocated */
+ assert( pTab->pSelect==0 ); /* Not a view */
if( sqlite3FkReferences(pTab)==0 ){
/* Search for a deferred foreign key constraint for which this table
** is the child table. If one cannot be found, return without
@@ -114386,44 +116237,6 @@ static int checkConstraintUnchanged(Expr *pExpr, int *aiChng, int chngRowid){
}
/*
-** An instance of the ConstraintAddr object remembers the byte-code addresses
-** for sections of the constraint checks that deal with uniqueness constraints
-** on the rowid and on the upsert constraint.
-**
-** This information is passed into checkReorderConstraintChecks() to insert
-** some OP_Goto operations so that the rowid and upsert constraints occur
-** in the correct order relative to other constraints.
-*/
-typedef struct ConstraintAddr ConstraintAddr;
-struct ConstraintAddr {
- int ipkTop; /* Subroutine for rowid constraint check */
- int upsertTop; /* Label for upsert constraint check subroutine */
- int upsertTop2; /* Copy of upsertTop not cleared by the call */
- int upsertBtm; /* upsert constraint returns to this label */
- int ipkBtm; /* Return opcode rowid constraint check */
-};
-
-/*
-** Generate any OP_Goto operations needed to cause constraints to be
-** run that haven't already been run.
-*/
-static void reorderConstraintChecks(Vdbe *v, ConstraintAddr *p){
- if( p->upsertTop ){
- testcase( sqlite3VdbeLabelHasBeenResolved(v, p->upsertTop) );
- sqlite3VdbeGoto(v, p->upsertTop);
- VdbeComment((v, "call upsert subroutine"));
- sqlite3VdbeResolveLabel(v, p->upsertBtm);
- p->upsertTop = 0;
- }
- if( p->ipkTop ){
- sqlite3VdbeGoto(v, p->ipkTop);
- VdbeComment((v, "call rowid unique-check subroutine"));
- sqlite3VdbeJumpHere(v, p->ipkBtm);
- p->ipkTop = 0;
- }
-}
-
-/*
** Generate code to do constraint checks prior to an INSERT or an UPDATE
** on table pTab.
**
@@ -114532,11 +116345,13 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
int addr1; /* Address of jump instruction */
int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
int nPkField; /* Number of fields in PRIMARY KEY. 1 for ROWID tables */
- ConstraintAddr sAddr;/* Address information for constraint reordering */
Index *pUpIdx = 0; /* Index to which to apply the upsert */
u8 isUpdate; /* True if this is an UPDATE operation */
u8 bAffinityDone = 0; /* True if the OP_Affinity operation has been run */
int upsertBypass = 0; /* Address of Goto to bypass upsert subroutine */
+ int upsertJump = 0; /* Address of Goto that jumps into upsert subroutine */
+ int ipkTop = 0; /* Top of the IPK uniqueness check */
+ int ipkBottom = 0; /* OP_Goto at the end of the IPK uniqueness check */
isUpdate = regOldData!=0;
db = pParse->db;
@@ -114544,7 +116359,6 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
assert( v!=0 );
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
nCol = pTab->nCol;
- memset(&sAddr, 0, sizeof(sAddr));
/* pPk is the PRIMARY KEY index for WITHOUT ROWID tables and NULL for
** normal rowid tables. nPkField is the number of key fields in the
@@ -114648,8 +116462,8 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
/* UNIQUE and PRIMARY KEY constraints should be handled in the following
** order:
**
- ** (1) OE_Abort, OE_Fail, OE_Rollback, OE_Ignore
- ** (2) OE_Update
+ ** (1) OE_Update
+ ** (2) OE_Abort, OE_Fail, OE_Rollback, OE_Ignore
** (3) OE_Replace
**
** OE_Fail and OE_Ignore must happen before any changes are made.
@@ -114658,6 +116472,11 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
** could happen in any order, but they are grouped up front for
** convenience.
**
+ ** 2018-08-14: Ticket https://www.sqlite.org/src/info/908f001483982c43
+ ** The order of constraints used to have OE_Update as (2) and OE_Abort
+ ** and so forth as (1). But apparently PostgreSQL checks the OE_Update
+ ** constraint before any others, so it had to be moved.
+ **
** Constraint checking code is generated in this order:
** (A) The rowid constraint
** (B) Unique index constraints that do not have OE_Replace as their
@@ -114677,11 +116496,10 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
overrideError = OE_Ignore;
pUpsert = 0;
}else if( (pUpIdx = pUpsert->pUpsertIdx)!=0 ){
- /* If the constraint-target is on some column other than
- ** then ROWID, then we might need to move the UPSERT around
- ** so that it occurs in the correct order. */
- sAddr.upsertTop = sAddr.upsertTop2 = sqlite3VdbeMakeLabel(v);
- sAddr.upsertBtm = sqlite3VdbeMakeLabel(v);
+ /* If the constraint-target uniqueness check must be run first.
+ ** Jump to that uniqueness check now */
+ upsertJump = sqlite3VdbeAddOp0(v, OP_Goto);
+ VdbeComment((v, "UPSERT constraint goes first"));
}
}
@@ -114713,16 +116531,12 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
** to defer the running of the rowid conflict checking until after
** the UNIQUE constraints have run.
*/
- assert( OE_Update>OE_Replace );
- assert( OE_Ignore<OE_Replace );
- assert( OE_Fail<OE_Replace );
- assert( OE_Abort<OE_Replace );
- assert( OE_Rollback<OE_Replace );
- if( onError>=OE_Replace
- && (pUpsert || onError!=overrideError)
- && pTab->pIndex
+ if( onError==OE_Replace /* IPK rule is REPLACE */
+ && onError!=overrideError /* Rules for other contraints are different */
+ && pTab->pIndex /* There exist other constraints */
){
- sAddr.ipkTop = sqlite3VdbeAddOp0(v, OP_Goto)+1;
+ ipkTop = sqlite3VdbeAddOp0(v, OP_Goto)+1;
+ VdbeComment((v, "defer IPK REPLACE until last"));
}
if( isUpdate ){
@@ -114817,9 +116631,9 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}
}
sqlite3VdbeResolveLabel(v, addrRowidOk);
- if( sAddr.ipkTop ){
- sAddr.ipkBtm = sqlite3VdbeAddOp0(v, OP_Goto);
- sqlite3VdbeJumpHere(v, sAddr.ipkTop-1);
+ if( ipkTop ){
+ ipkBottom = sqlite3VdbeAddOp0(v, OP_Goto);
+ sqlite3VdbeJumpHere(v, ipkTop-1);
}
}
@@ -114838,18 +116652,18 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
if( aRegIdx[ix]==0 ) continue; /* Skip indices that do not change */
if( pUpIdx==pIdx ){
- addrUniqueOk = sAddr.upsertBtm;
+ addrUniqueOk = upsertJump+1;
upsertBypass = sqlite3VdbeGoto(v, 0);
VdbeComment((v, "Skip upsert subroutine"));
- sqlite3VdbeResolveLabel(v, sAddr.upsertTop2);
+ sqlite3VdbeJumpHere(v, upsertJump);
}else{
addrUniqueOk = sqlite3VdbeMakeLabel(v);
}
- VdbeNoopComment((v, "uniqueness check for %s", pIdx->zName));
- if( bAffinityDone==0 ){
+ if( bAffinityDone==0 && (pUpIdx==0 || pUpIdx==pIdx) ){
sqlite3TableAffinity(v, pTab, regNewData+1);
bAffinityDone = 1;
}
+ VdbeNoopComment((v, "uniqueness check for %s", pIdx->zName));
iThisCur = iIdxCur+ix;
@@ -114920,15 +116734,6 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}
}
- /* Invoke subroutines to handle IPK replace and upsert prior to running
- ** the first REPLACE constraint check. */
- if( onError==OE_Replace ){
- testcase( sAddr.ipkTop );
- testcase( sAddr.upsertTop
- && sqlite3VdbeLabelHasBeenResolved(v,sAddr.upsertTop) );
- reorderConstraintChecks(v, &sAddr);
- }
-
/* Collision detection may be omitted if all of the following are true:
** (1) The conflict resolution algorithm is REPLACE
** (2) The table is a WITHOUT ROWID table
@@ -114949,7 +116754,6 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}
/* Check to see if the new index entry will be unique */
- sqlite3ExprCachePush(pParse);
sqlite3VdbeVerifyAbortable(v, onError);
sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
regIdx, pIdx->nKeyCol); VdbeCoverage(v);
@@ -115051,19 +116855,21 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}
}
if( pUpIdx==pIdx ){
+ sqlite3VdbeGoto(v, upsertJump+1);
sqlite3VdbeJumpHere(v, upsertBypass);
}else{
sqlite3VdbeResolveLabel(v, addrUniqueOk);
}
- sqlite3ExprCachePop(pParse);
if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField);
+ }
+ /* If the IPK constraint is a REPLACE, run it last */
+ if( ipkTop ){
+ sqlite3VdbeGoto(v, ipkTop+1);
+ VdbeComment((v, "Do IPK REPLACE"));
+ sqlite3VdbeJumpHere(v, ipkBottom);
}
- testcase( sAddr.ipkTop!=0 );
- testcase( sAddr.upsertTop
- && sqlite3VdbeLabelHasBeenResolved(v,sAddr.upsertTop) );
- reorderConstraintChecks(v, &sAddr);
-
+
*pbMayReplace = seenReplace;
VdbeModuleComment((v, "END: GenCnstCks(%d)", seenReplace));
}
@@ -115159,7 +116965,6 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
sqlite3SetMakeRecordP5(v, pTab);
if( !bAffinityDone ){
sqlite3TableAffinity(v, pTab, 0);
- sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol);
}
if( pParse->nested ){
pik_flags = 0;
@@ -116135,6 +117940,12 @@ struct sqlite3_api_routines {
int (*str_errcode)(sqlite3_str*);
int (*str_length)(sqlite3_str*);
char *(*str_value)(sqlite3_str*);
+ int (*create_window_function)(sqlite3*,const char*,int,int,void*,
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+ void (*xFinal)(sqlite3_context*),
+ void (*xValue)(sqlite3_context*),
+ void (*xInv)(sqlite3_context*,int,sqlite3_value**),
+ void(*xDestroy)(void*));
};
/*
@@ -116420,6 +118231,8 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_str_errcode sqlite3_api->str_errcode
#define sqlite3_str_length sqlite3_api->str_length
#define sqlite3_str_value sqlite3_api->str_value
+/* Version 3.25.0 and later */
+#define sqlite3_create_window_function sqlite3_api->create_window_function
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
@@ -116873,7 +118686,9 @@ static const sqlite3_api_routines sqlite3Apis = {
sqlite3_str_reset,
sqlite3_str_errcode,
sqlite3_str_length,
- sqlite3_str_value
+ sqlite3_str_value,
+ /* Version 3.25.0 and later */
+ sqlite3_create_window_function
};
/*
@@ -117668,6 +119483,11 @@ static const PragmaName aPragmaName[] = {
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+ {/* zName: */ "legacy_alter_table",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_LegacyAlter },
{/* zName: */ "legacy_file_format",
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
@@ -117921,7 +119741,7 @@ static const PragmaName aPragmaName[] = {
/* iArg: */ SQLITE_WriteSchema },
#endif
};
-/* Number of pragmas: 60 on by default, 77 total. */
+/* Number of pragmas: 61 on by default, 78 total. */
/************** End of pragma.h **********************************************/
/************** Continuing where we left off in pragma.c *********************/
@@ -119446,7 +121266,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
- sqlite3ExprCacheClear(pParse);
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
1, 0, &iDataCur, &iIdxCur);
/* reg[7] counts the number of entries in the table.
@@ -119460,6 +121279,11 @@ SQLITE_PRIVATE void sqlite3Pragma(
assert( sqlite3NoTempsInRange(pParse,1,7+j) );
sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v);
loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1);
+ if( !isQuick ){
+ /* Sanity check on record header decoding */
+ sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nCol-1, 3);
+ sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
+ }
/* Verify that all NOT NULL columns really are NOT NULL */
for(j=0; j<pTab->nCol; j++){
char *zErr;
@@ -119484,7 +121308,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
char *zErr;
int k;
pParse->iSelfTab = iDataCur + 1;
- sqlite3ExprCachePush(pParse);
for(k=pCheck->nExpr-1; k>0; k--){
sqlite3ExprIfFalse(pParse, pCheck->a[k].pExpr, addrCkFault, 0);
}
@@ -119497,14 +121320,10 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
integrityCheckResultRow(v);
sqlite3VdbeResolveLabel(v, addrCkOk);
- sqlite3ExprCachePop(pParse);
}
sqlite3ExprListDelete(db, pCheck);
}
if( !isQuick ){ /* Omit the remaining tests for quick_check */
- /* Sanity check on record header decoding */
- sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nCol-1, 3);
- sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
/* Validate index entries for the current row */
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
int jmp2, jmp3, jmp4, jmp5;
@@ -120119,7 +121938,6 @@ static int pragmaVtabConnect(
}
if( i==0 ){
sqlite3_str_appendf(&acc, "(\"%s\"", pPragma->zName);
- cSep = ',';
i++;
}
j = 0;
@@ -120412,15 +122230,23 @@ static void corruptSchema(
const char *zExtra /* Error information */
){
sqlite3 *db = pData->db;
- if( !db->mallocFailed && (db->flags & SQLITE_WriteSchema)==0 ){
+ if( db->mallocFailed ){
+ pData->rc = SQLITE_NOMEM_BKPT;
+ }else if( pData->pzErrMsg[0]!=0 ){
+ /* A error message has already been generated. Do not overwrite it */
+ }else if( pData->mInitFlags & INITFLAG_AlterTable ){
+ *pData->pzErrMsg = sqlite3DbStrDup(db, zExtra);
+ pData->rc = SQLITE_ERROR;
+ }else if( db->flags & SQLITE_WriteSchema ){
+ pData->rc = SQLITE_CORRUPT_BKPT;
+ }else{
char *z;
if( zObj==0 ) zObj = "?";
z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj);
if( zExtra && zExtra[0] ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra);
- sqlite3DbFree(db, *pData->pzErrMsg);
*pData->pzErrMsg = z;
+ pData->rc = SQLITE_CORRUPT_BKPT;
}
- pData->rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_CORRUPT_BKPT;
}
/*
@@ -120472,7 +122298,7 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
rc = db->errCode;
assert( (rc&0xFF)==(rcp&0xFF) );
db->init.iDb = saved_iDb;
- assert( saved_iDb==0 || (db->mDbFlags & DBFLAG_Vacuum)!=0 );
+ /* assert( saved_iDb==0 || (db->mDbFlags & DBFLAG_Vacuum)!=0 ); */
if( SQLITE_OK!=rc ){
if( db->init.orphanTrigger ){
assert( iDb==1 );
@@ -120519,7 +122345,7 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
** auxiliary databases. Return one of the SQLITE_ error codes to
** indicate success or failure.
*/
-static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
+SQLITE_PRIVATE int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
int rc;
int i;
#ifndef SQLITE_OMIT_DEPRECATED
@@ -120554,6 +122380,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
initData.iDb = iDb;
initData.rc = SQLITE_OK;
initData.pzErrMsg = pzErrMsg;
+ initData.mInitFlags = mFlags;
sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
if( initData.rc ){
rc = initData.rc;
@@ -120575,7 +122402,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
** will be closed before this function returns. */
sqlite3BtreeEnter(pDb->pBt);
if( !sqlite3BtreeIsInReadTrans(pDb->pBt) ){
- rc = sqlite3BtreeBeginTrans(pDb->pBt, 0);
+ rc = sqlite3BtreeBeginTrans(pDb->pBt, 0, 0);
if( rc!=SQLITE_OK ){
sqlite3SetString(pzErrMsg, db, sqlite3ErrStr(rc));
goto initone_error_out;
@@ -120760,14 +122587,14 @@ SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){
assert( db->nDb>0 );
/* Do the main schema first */
if( !DbHasProperty(db, 0, DB_SchemaLoaded) ){
- rc = sqlite3InitOne(db, 0, pzErrMsg);
+ rc = sqlite3InitOne(db, 0, pzErrMsg, 0);
if( rc ) return rc;
}
/* All other schemas after the main schema. The "temp" schema must be last */
for(i=db->nDb-1; i>0; i--){
assert( i==1 || sqlite3BtreeHoldsMutex(db->aDb[i].pBt) );
if( !DbHasProperty(db, i, DB_SchemaLoaded) ){
- rc = sqlite3InitOne(db, i, pzErrMsg);
+ rc = sqlite3InitOne(db, i, pzErrMsg, 0);
if( rc ) return rc;
}
}
@@ -120820,7 +122647,7 @@ static void schemaIsValid(Parse *pParse){
** on the b-tree database, open one now. If a transaction is opened, it
** will be closed immediately after reading the meta-value. */
if( !sqlite3BtreeIsInReadTrans(pBt) ){
- rc = sqlite3BtreeBeginTrans(pBt, 0);
+ rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
sqlite3OomFault(db);
}
@@ -121317,7 +123144,7 @@ SQLITE_API int sqlite3_prepare16_v3(
/***/ int sqlite3SelectTrace = 0;
# define SELECTTRACE(K,P,S,X) \
if(sqlite3SelectTrace&(K)) \
- sqlite3DebugPrintf("%s/%d/%p: ",(S)->zSelName,(P)->addrExplain,(S)),\
+ sqlite3DebugPrintf("%u/%d/%p: ",(S)->selId,(P)->addrExplain,(S)),\
sqlite3DebugPrintf X
#else
# define SELECTTRACE(K,P,S,X)
@@ -121364,8 +123191,8 @@ struct SortCtx {
int labelBkOut; /* Start label for the block-output subroutine */
int addrSortIndex; /* Address of the OP_SorterOpen or OP_OpenEphemeral */
int labelDone; /* Jump here when done, ex: LIMIT reached */
+ int labelOBLopt; /* Jump here when sorter is full */
u8 sortFlags; /* Zero or more SORTFLAG_* bits */
- u8 bOrderedInnerLoop; /* ORDER BY correctly sorts the inner loop */
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
u8 nDefer; /* Number of valid entries in aDefer[] */
struct DeferredCsr {
@@ -121392,6 +123219,11 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){
sqlite3ExprDelete(db, p->pHaving);
sqlite3ExprListDelete(db, p->pOrderBy);
sqlite3ExprDelete(db, p->pLimit);
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( OK_IF_ALWAYS_TRUE(p->pWinDefn) ){
+ sqlite3WindowListDelete(db, p->pWinDefn);
+ }
+#endif
if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith);
if( bFree ) sqlite3DbFreeNN(db, p);
p = pPrior;
@@ -121442,9 +123274,7 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
pNew->selFlags = selFlags;
pNew->iLimit = 0;
pNew->iOffset = 0;
-#if SELECTTRACE_ENABLED
- pNew->zSelName[0] = 0;
-#endif
+ pNew->selId = ++pParse->nSelect;
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->nSelectRow = 0;
@@ -121458,6 +123288,10 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
pNew->pNext = 0;
pNew->pLimit = pLimit;
pNew->pWith = 0;
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ pNew->pWin = 0;
+ pNew->pWinDefn = 0;
+#endif
if( pParse->db->mallocFailed ) {
clearSelect(pParse->db, pNew, pNew!=&standin);
pNew = 0;
@@ -121468,17 +123302,6 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
return pNew;
}
-#if SELECTTRACE_ENABLED
-/*
-** Set the name of a Select object
-*/
-SQLITE_PRIVATE void sqlite3SelectSetName(Select *p, const char *zName){
- if( p && zName ){
- sqlite3_snprintf(sizeof(p->zSelName), p->zSelName, "%s", zName);
- }
-}
-#endif
-
/*
** Delete the given Select structure and all of its substructures.
@@ -121825,14 +123648,6 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
return 0;
}
-/* Forward reference */
-static KeyInfo *keyInfoFromExprList(
- Parse *pParse, /* Parsing context */
- ExprList *pList, /* Form the KeyInfo object from this ExprList */
- int iStart, /* Begin with this column of pList */
- int nExtra /* Add this many extra columns to the end */
-);
-
/*
** An instance of this object holds information (beyond pParse and pSelect)
** needed to load the next result row that is to be added to the sorter.
@@ -121974,7 +123789,7 @@ static void pushOntoSorter(
memset(pKI->aSortOrder, 0, pKI->nKeyField); /* Makes OP_Jump testable */
sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO);
testcase( pKI->nAllField > pKI->nKeyField+2 );
- pOp->p4.pKeyInfo = keyInfoFromExprList(pParse, pSort->pOrderBy, nOBSat,
+ pOp->p4.pKeyInfo = sqlite3KeyInfoFromExprList(pParse,pSort->pOrderBy,nOBSat,
pKI->nAllField-pKI->nKeyField-1);
addrJmp = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v);
@@ -122001,10 +123816,10 @@ static void pushOntoSorter(
** than LIMIT+OFFSET items in the sorter.
**
** If the new record does not need to be inserted into the sorter,
- ** jump to the next iteration of the loop. Or, if the
- ** pSort->bOrderedInnerLoop flag is set to indicate that the inner
- ** loop delivers items in sorted order, jump to the next iteration
- ** of the outer loop.
+ ** jump to the next iteration of the loop. If the pSort->labelOBLopt
+ ** value is not zero, then it is a label of where to jump. Otherwise,
+ ** just bypass the row insert logic. See the header comment on the
+ ** sqlite3WhereOrderByLimitOptLabel() function for additional info.
*/
int iCsr = pSort->iECursor;
sqlite3VdbeAddOp2(v, OP_IfNotZero, iLimit, sqlite3VdbeCurrentAddr(v)+4);
@@ -122026,9 +123841,8 @@ static void pushOntoSorter(
sqlite3VdbeAddOp4Int(v, op, pSort->iECursor, regRecord,
regBase+nOBSat, nBase-nOBSat);
if( iSkip ){
- assert( pSort->bOrderedInnerLoop==0 || pSort->bOrderedInnerLoop==1 );
sqlite3VdbeChangeP2(v, iSkip,
- sqlite3VdbeCurrentAddr(v) + pSort->bOrderedInnerLoop);
+ pSort->labelOBLopt ? pSort->labelOBLopt : sqlite3VdbeCurrentAddr(v));
}
}
@@ -122457,7 +124271,6 @@ static void selectInnerLoop(
assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol );
sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol,
r1, pDest->zAffSdst, nResultCol);
- sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
sqlite3ReleaseTempReg(pParse, r1);
}
@@ -122501,7 +124314,6 @@ static void selectInnerLoop(
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
}else{
sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nResultCol);
- sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol);
}
break;
}
@@ -122644,7 +124456,7 @@ SQLITE_PRIVATE int sqlite3KeyInfoIsWriteable(KeyInfo *p){ return p->nRef==1; }
** function is responsible for seeing that this structure is eventually
** freed.
*/
-static KeyInfo *keyInfoFromExprList(
+SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoFromExprList(
Parse *pParse, /* Parsing context */
ExprList *pList, /* Form the KeyInfo object from this ExprList */
int iStart, /* Begin with this column of pList */
@@ -122858,7 +124670,6 @@ static void generateSortTail(
assert( nColumn==sqlite3Strlen30(pDest->zAffSdst) );
sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, nColumn, regRowid,
pDest->zAffSdst, nColumn);
- sqlite3ExprCacheAffinityChange(pParse, regRow, nColumn);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, regRowid, regRow, nColumn);
break;
}
@@ -122873,7 +124684,6 @@ static void generateSortTail(
testcase( eDest==SRT_Coroutine );
if( eDest==SRT_Output ){
sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iSdst, nColumn);
- sqlite3ExprCacheAffinityChange(pParse, pDest->iSdst, nColumn);
}else{
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
}
@@ -123474,7 +125284,6 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
** The current implementation interprets "LIMIT 0" to mean
** no rows.
*/
- sqlite3ExprCacheClear(pParse);
if( pLimit ){
assert( pLimit->op==TK_LIMIT );
assert( pLimit->pLeft!=0 );
@@ -124260,7 +126069,6 @@ static int generateOutputSubroutine(
r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst,
r1, pDest->zAffSdst, pIn->nSdst);
- sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1,
pIn->iSdst, pIn->nSdst);
sqlite3ReleaseTempReg(pParse, r1);
@@ -124303,7 +126111,6 @@ static int generateOutputSubroutine(
default: {
assert( pDest->eDest==SRT_Output );
sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iSdst, pIn->nSdst);
- sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst);
break;
}
}
@@ -124758,7 +126565,7 @@ static Expr *substExpr(
Expr *pCopy = pSubst->pEList->a[pExpr->iColumn].pExpr;
Expr ifNullRow;
assert( pSubst->pEList!=0 && pExpr->iColumn<pSubst->pEList->nExpr );
- assert( pExpr->pLeft==0 && pExpr->pRight==0 );
+ assert( pExpr->pRight==0 );
if( sqlite3ExprIsVector(pCopy) ){
sqlite3VectorErrorMsg(pSubst->pParse, pCopy);
}else{
@@ -124972,6 +126779,10 @@ static void substSelect(
** "SELECT x FROM (SELECT max(y), x FROM t1)" would not necessarily
** return the value X for which Y was maximal.)
**
+** (25) If either the subquery or the parent query contains a window
+** function in the select list or ORDER BY clause, flattening
+** is not attempted.
+**
**
** In this routine, the "p" parameter is a pointer to the outer query.
** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query
@@ -125015,6 +126826,10 @@ static int flattenSubquery(
pSub = pSubitem->pSelect;
assert( pSub!=0 );
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( p->pWin || pSub->pWin ) return 0; /* Restriction (25) */
+#endif
+
pSubSrc = pSub->pSrc;
assert( pSubSrc );
/* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants,
@@ -125125,8 +126940,8 @@ static int flattenSubquery(
assert( (p->selFlags & SF_Recursive)==0 || pSub->pPrior==0 );
/***** If we reach this point, flattening is permitted. *****/
- SELECTTRACE(1,pParse,p,("flatten %s.%p from term %d\n",
- pSub->zSelName, pSub, iFrom));
+ SELECTTRACE(1,pParse,p,("flatten %u.%p from term %d\n",
+ pSub->selId, pSub, iFrom));
/* Authorize the subquery */
pParse->zAuthContext = pSubitem->zName;
@@ -125177,7 +126992,6 @@ static int flattenSubquery(
p->pPrior = 0;
p->pLimit = 0;
pNew = sqlite3SelectDup(db, p, 0);
- sqlite3SelectSetName(pNew, pSub->zSelName);
p->pLimit = pLimit;
p->pOrderBy = pOrderBy;
p->pSrc = pSrc;
@@ -125190,7 +127004,7 @@ static int flattenSubquery(
pNew->pNext = p;
p->pPrior = pNew;
SELECTTRACE(2,pParse,p,("compound-subquery flattener"
- " creates %s.%p as peer\n",pNew->zSelName, pNew));
+ " creates %u as peer\n",pNew->selId));
}
if( db->mallocFailed ) return 1;
}
@@ -125375,7 +127189,168 @@ static int flattenSubquery(
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
+/*
+** A structure to keep track of all of the column values that fixed to
+** a known value due to WHERE clause constraints of the form COLUMN=VALUE.
+*/
+typedef struct WhereConst WhereConst;
+struct WhereConst {
+ Parse *pParse; /* Parsing context */
+ int nConst; /* Number for COLUMN=CONSTANT terms */
+ int nChng; /* Number of times a constant is propagated */
+ Expr **apExpr; /* [i*2] is COLUMN and [i*2+1] is VALUE */
+};
+
+/*
+** Add a new entry to the pConst object
+*/
+static void constInsert(
+ WhereConst *pConst,
+ Expr *pColumn,
+ Expr *pValue
+){
+
+ pConst->nConst++;
+ pConst->apExpr = sqlite3DbReallocOrFree(pConst->pParse->db, pConst->apExpr,
+ pConst->nConst*2*sizeof(Expr*));
+ if( pConst->apExpr==0 ){
+ pConst->nConst = 0;
+ }else{
+ if( ExprHasProperty(pValue, EP_FixedCol) ) pValue = pValue->pLeft;
+ pConst->apExpr[pConst->nConst*2-2] = pColumn;
+ pConst->apExpr[pConst->nConst*2-1] = pValue;
+ }
+}
+/*
+** Find all terms of COLUMN=VALUE or VALUE=COLUMN in pExpr where VALUE
+** is a constant expression and where the term must be true because it
+** is part of the AND-connected terms of the expression. For each term
+** found, add it to the pConst structure.
+*/
+static void findConstInWhere(WhereConst *pConst, Expr *pExpr){
+ Expr *pRight, *pLeft;
+ if( pExpr==0 ) return;
+ if( ExprHasProperty(pExpr, EP_FromJoin) ) return;
+ if( pExpr->op==TK_AND ){
+ findConstInWhere(pConst, pExpr->pRight);
+ findConstInWhere(pConst, pExpr->pLeft);
+ return;
+ }
+ if( pExpr->op!=TK_EQ ) return;
+ pRight = pExpr->pRight;
+ pLeft = pExpr->pLeft;
+ assert( pRight!=0 );
+ assert( pLeft!=0 );
+ if( pRight->op==TK_COLUMN
+ && !ExprHasProperty(pRight, EP_FixedCol)
+ && sqlite3ExprIsConstant(pLeft)
+ && sqlite3IsBinary(sqlite3BinaryCompareCollSeq(pConst->pParse,pLeft,pRight))
+ ){
+ constInsert(pConst, pRight, pLeft);
+ }else
+ if( pLeft->op==TK_COLUMN
+ && !ExprHasProperty(pLeft, EP_FixedCol)
+ && sqlite3ExprIsConstant(pRight)
+ && sqlite3IsBinary(sqlite3BinaryCompareCollSeq(pConst->pParse,pLeft,pRight))
+ ){
+ constInsert(pConst, pLeft, pRight);
+ }
+}
+
+/*
+** This is a Walker expression callback. pExpr is a candidate expression
+** to be replaced by a value. If pExpr is equivalent to one of the
+** columns named in pWalker->u.pConst, then overwrite it with its
+** corresponding value.
+*/
+static int propagateConstantExprRewrite(Walker *pWalker, Expr *pExpr){
+ int i;
+ WhereConst *pConst;
+ if( pExpr->op!=TK_COLUMN ) return WRC_Continue;
+ if( ExprHasProperty(pExpr, EP_FixedCol) ) return WRC_Continue;
+ pConst = pWalker->u.pConst;
+ for(i=0; i<pConst->nConst; i++){
+ Expr *pColumn = pConst->apExpr[i*2];
+ if( pColumn==pExpr ) continue;
+ if( pColumn->iTable!=pExpr->iTable ) continue;
+ if( pColumn->iColumn!=pExpr->iColumn ) continue;
+ /* A match is found. Add the EP_FixedCol property */
+ pConst->nChng++;
+ ExprClearProperty(pExpr, EP_Leaf);
+ ExprSetProperty(pExpr, EP_FixedCol);
+ assert( pExpr->pLeft==0 );
+ pExpr->pLeft = sqlite3ExprDup(pConst->pParse->db, pConst->apExpr[i*2+1], 0);
+ break;
+ }
+ return WRC_Prune;
+}
+
+/*
+** The WHERE-clause constant propagation optimization.
+**
+** If the WHERE clause contains terms of the form COLUMN=CONSTANT or
+** CONSTANT=COLUMN that must be tree (in other words, if the terms top-level
+** AND-connected terms that are not part of a ON clause from a LEFT JOIN)
+** then throughout the query replace all other occurrences of COLUMN
+** with CONSTANT within the WHERE clause.
+**
+** For example, the query:
+**
+** SELECT * FROM t1, t2, t3 WHERE t1.a=39 AND t2.b=t1.a AND t3.c=t2.b
+**
+** Is transformed into
+**
+** SELECT * FROM t1, t2, t3 WHERE t1.a=39 AND t2.b=39 AND t3.c=39
+**
+** Return true if any transformations where made and false if not.
+**
+** Implementation note: Constant propagation is tricky due to affinity
+** and collating sequence interactions. Consider this example:
+**
+** CREATE TABLE t1(a INT,b TEXT);
+** INSERT INTO t1 VALUES(123,'0123');
+** SELECT * FROM t1 WHERE a=123 AND b=a;
+** SELECT * FROM t1 WHERE a=123 AND b=123;
+**
+** The two SELECT statements above should return different answers. b=a
+** is alway true because the comparison uses numeric affinity, but b=123
+** is false because it uses text affinity and '0123' is not the same as '123'.
+** To work around this, the expression tree is not actually changed from
+** "b=a" to "b=123" but rather the "a" in "b=a" is tagged with EP_FixedCol
+** and the "123" value is hung off of the pLeft pointer. Code generator
+** routines know to generate the constant "123" instead of looking up the
+** column value. Also, to avoid collation problems, this optimization is
+** only attempted if the "a=123" term uses the default BINARY collation.
+*/
+static int propagateConstants(
+ Parse *pParse, /* The parsing context */
+ Select *p /* The query in which to propagate constants */
+){
+ WhereConst x;
+ Walker w;
+ int nChng = 0;
+ x.pParse = pParse;
+ do{
+ x.nConst = 0;
+ x.nChng = 0;
+ x.apExpr = 0;
+ findConstInWhere(&x, p->pWhere);
+ if( x.nConst ){
+ memset(&w, 0, sizeof(w));
+ w.pParse = pParse;
+ w.xExprCallback = propagateConstantExprRewrite;
+ w.xSelectCallback = sqlite3SelectWalkNoop;
+ w.xSelectCallback2 = 0;
+ w.walkerDepth = 0;
+ w.u.pConst = &x;
+ sqlite3WalkExpr(&w, p->pWhere);
+ sqlite3DbFree(x.pParse->db, x.apExpr);
+ nChng += x.nChng;
+ }
+ }while( x.nChng );
+ return nChng;
+}
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
@@ -125405,7 +127380,7 @@ static int flattenSubquery(
** (2) The inner query is the recursive part of a common table expression.
**
** (3) The inner query has a LIMIT clause (since the changes to the WHERE
-** close would change the meaning of the LIMIT).
+** clause would change the meaning of the LIMIT).
**
** (4) The inner query is the right operand of a LEFT JOIN and the
** expression to be pushed down does not come from the ON clause
@@ -125424,6 +127399,10 @@ static int flattenSubquery(
** But if the (b2=2) term were to be pushed down into the bb subquery,
** then the (1,1,NULL) row would be suppressed.
**
+** (6) The inner query features one or more window-functions (since
+** changes to the WHERE clause of the inner query could change the
+** window over which window functions are calculated).
+**
** Return 0 if no changes are made and non-zero if one or more WHERE clause
** terms are duplicated into the subquery.
*/
@@ -125439,6 +127418,10 @@ static int pushDownWhereTerms(
if( pWhere==0 ) return 0;
if( pSubq->selFlags & SF_Recursive ) return 0; /* restriction (2) */
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( pSubq->pWin ) return 0; /* restriction (6) */
+#endif
+
#ifdef SQLITE_DEBUG
/* Only the first term of a compound can have a WITH clause. But make
** sure no other terms are marked SF_Recursive in case something changes
@@ -125885,6 +127868,35 @@ static void selectPopWith(Walker *pWalker, Select *p){
#endif
/*
+** The SrcList_item structure passed as the second argument represents a
+** sub-query in the FROM clause of a SELECT statement. This function
+** allocates and populates the SrcList_item.pTab object. If successful,
+** SQLITE_OK is returned. Otherwise, if an OOM error is encountered,
+** SQLITE_NOMEM.
+*/
+SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse *pParse, struct SrcList_item *pFrom){
+ Select *pSel = pFrom->pSelect;
+ Table *pTab;
+
+ assert( pSel );
+ pFrom->pTab = pTab = sqlite3DbMallocZero(pParse->db, sizeof(Table));
+ if( pTab==0 ) return SQLITE_NOMEM;
+ pTab->nTabRef = 1;
+ if( pFrom->zAlias ){
+ pTab->zName = sqlite3DbStrDup(pParse->db, pFrom->zAlias);
+ }else{
+ pTab->zName = sqlite3MPrintf(pParse->db, "subquery_%u", pSel->selId);
+ }
+ while( pSel->pPrior ){ pSel = pSel->pPrior; }
+ sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
+ pTab->iPKey = -1;
+ pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
+ pTab->tabFlags |= TF_Ephemeral;
+
+ return SQLITE_OK;
+}
+
+/*
** This routine is a Walker callback for "expanding" a SELECT statement.
** "Expanding" means to do the following:
**
@@ -125956,19 +127968,7 @@ static int selectExpander(Walker *pWalker, Select *p){
assert( pSel!=0 );
assert( pFrom->pTab==0 );
if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort;
- pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
- if( pTab==0 ) return WRC_Abort;
- pTab->nTabRef = 1;
- if( pFrom->zAlias ){
- pTab->zName = sqlite3DbStrDup(db, pFrom->zAlias);
- }else{
- pTab->zName = sqlite3MPrintf(db, "subquery_%p", (void*)pTab);
- }
- while( pSel->pPrior ){ pSel = pSel->pPrior; }
- sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
- pTab->iPKey = -1;
- pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
- pTab->tabFlags |= TF_Ephemeral;
+ if( sqlite3ExpandSubquery(pParse, pFrom) ) return WRC_Abort;
#endif
}else{
/* An ordinary table or view name in the FROM clause */
@@ -125991,7 +127991,6 @@ static int selectExpander(Walker *pWalker, Select *p){
if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
assert( pFrom->pSelect==0 );
pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0);
- sqlite3SelectSetName(pFrom->pSelect, pTab->zName);
nCol = pTab->nCol;
pTab->nCol = -1;
sqlite3WalkSelect(pWalker, pFrom->pSelect);
@@ -126269,7 +128268,7 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
struct SrcList_item *pFrom;
assert( p->selFlags & SF_Resolved );
- assert( (p->selFlags & SF_HasTypeInfo)==0 );
+ if( p->selFlags & SF_HasTypeInfo ) return;
p->selFlags |= SF_HasTypeInfo;
pParse = pWalker->pParse;
pTabList = p->pSrc;
@@ -126372,7 +128371,7 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
"argument");
pFunc->iDistinct = -1;
}else{
- KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->x.pList, 0, 0);
+ KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pE->x.pList,0,0);
sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0,
(char*)pKeyInfo, P4_KEYINFO);
}
@@ -126396,11 +128395,17 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
}
}
+
/*
** Update the accumulator memory cells for an aggregate based on
** the current cursor position.
+**
+** If regAcc is non-zero and there are no min() or max() aggregates
+** in pAggInfo, then only populate the pAggInfo->nAccumulator accumulator
+** registers i register regAcc contains 0. The caller will take care
+** of setting and clearing regAcc.
*/
-static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
+static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
Vdbe *v = pParse->pVdbe;
int i;
int regHit = 0;
@@ -126443,36 +128448,24 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
if( regHit==0 && pAggInfo->nAccumulator ) regHit = ++pParse->nMem;
sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0, (char *)pColl, P4_COLLSEQ);
}
- sqlite3VdbeAddOp3(v, OP_AggStep0, 0, regAgg, pF->iMem);
+ sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, pF->iMem);
sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, (u8)nArg);
- sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg);
sqlite3ReleaseTempRange(pParse, regAgg, nArg);
if( addrNext ){
sqlite3VdbeResolveLabel(v, addrNext);
- sqlite3ExprCacheClear(pParse);
}
}
-
- /* Before populating the accumulator registers, clear the column cache.
- ** Otherwise, if any of the required column values are already present
- ** in registers, sqlite3ExprCode() may use OP_SCopy to copy the value
- ** to pC->iMem. But by the time the value is used, the original register
- ** may have been used, invalidating the underlying buffer holding the
- ** text or blob value. See ticket [883034dcb5].
- **
- ** Another solution would be to change the OP_SCopy used to copy cached
- ** values to an OP_Copy.
- */
+ if( regHit==0 && pAggInfo->nAccumulator ){
+ regHit = regAcc;
+ }
if( regHit ){
addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); VdbeCoverage(v);
}
- sqlite3ExprCacheClear(pParse);
for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
sqlite3ExprCode(pParse, pC->pExpr, pC->iMem);
}
pAggInfo->directMode = 0;
- sqlite3ExprCacheClear(pParse);
if( addrHitTest ){
sqlite3VdbeJumpHere(v, addrHitTest);
}
@@ -126602,6 +128595,7 @@ static struct SrcList_item *isSelfJoinView(
** The transformation only works if all of the following are true:
**
** * The subquery is a UNION ALL of two or more terms
+** * The subquery does not have a LIMIT clause
** * There is no WHERE or GROUP BY or HAVING clauses on the subqueries
** * The outer query is a simple count(*)
**
@@ -126625,6 +128619,7 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
do{
if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */
if( pSub->pWhere ) return 0; /* No WHERE clause */
+ if( pSub->pLimit ) return 0; /* No LIMIT clause */
if( pSub->selFlags & SF_Aggregate ) return 0; /* Not an aggregate */
pSub = pSub->pPrior; /* Repeat over compound */
}while( pSub );
@@ -126737,14 +128732,10 @@ SQLITE_PRIVATE int sqlite3Select(
p->selFlags &= ~SF_Distinct;
}
sqlite3SelectPrep(pParse, p, 0);
- memset(&sSort, 0, sizeof(sSort));
- sSort.pOrderBy = p->pOrderBy;
- pTabList = p->pSrc;
if( pParse->nErr || db->mallocFailed ){
goto select_end;
}
assert( p->pEList!=0 );
- isAgg = (p->selFlags & SF_Aggregate)!=0;
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x104 ){
SELECTTRACE(0x104,pParse,p, ("after name resolution:\n"));
@@ -126756,6 +128747,22 @@ SQLITE_PRIVATE int sqlite3Select(
generateColumnNames(pParse, p);
}
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( sqlite3WindowRewrite(pParse, p) ){
+ goto select_end;
+ }
+#if SELECTTRACE_ENABLED
+ if( sqlite3SelectTrace & 0x108 ){
+ SELECTTRACE(0x104,pParse,p, ("after window rewrite:\n"));
+ sqlite3TreeViewSelect(0, p, 0);
+ }
+#endif
+#endif /* SQLITE_OMIT_WINDOWFUNC */
+ pTabList = p->pSrc;
+ isAgg = (p->selFlags & SF_Aggregate)!=0;
+ memset(&sSort, 0, sizeof(sSort));
+ sSort.pOrderBy = p->pOrderBy;
+
/* Try to various optimizations (flattening subqueries, and strength
** reduction of join operators) in the FROM clause up into the main query
*/
@@ -126855,6 +128862,35 @@ SQLITE_PRIVATE int sqlite3Select(
}
#endif
+ /* Do the WHERE-clause constant propagation optimization if this is
+ ** a join. No need to speed time on this operation for non-join queries
+ ** as the equivalent optimization will be handled by query planner in
+ ** sqlite3WhereBegin().
+ */
+ if( pTabList->nSrc>1
+ && OptimizationEnabled(db, SQLITE_PropagateConst)
+ && propagateConstants(pParse, p)
+ ){
+#if SELECTTRACE_ENABLED
+ if( sqlite3SelectTrace & 0x100 ){
+ SELECTTRACE(0x100,pParse,p,("After constant propagation:\n"));
+ sqlite3TreeViewSelect(0, p, 0);
+ }
+#endif
+ }else{
+ SELECTTRACE(0x100,pParse,p,("Constant propagation not helpful\n"));
+ }
+
+#ifdef SQLITE_COUNTOFVIEW_OPTIMIZATION
+ if( OptimizationEnabled(db, SQLITE_QueryFlattener|SQLITE_CountOfView)
+ && countOfViewOptimization(pParse, p)
+ ){
+ if( db->mallocFailed ) goto select_end;
+ pEList = p->pEList;
+ pTabList = p->pSrc;
+ }
+#endif
+
/* For each term in the FROM clause, do two things:
** (1) Authorized unreferenced tables
** (2) Generate code for all sub-queries
@@ -126928,7 +128964,8 @@ SQLITE_PRIVATE int sqlite3Select(
){
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x100 ){
- SELECTTRACE(0x100,pParse,p,("After WHERE-clause push-down:\n"));
+ SELECTTRACE(0x100,pParse,p,
+ ("After WHERE-clause push-down into subquery %d:\n", pSub->selId));
sqlite3TreeViewSelect(0, p, 0);
}
#endif
@@ -126962,7 +128999,7 @@ SQLITE_PRIVATE int sqlite3Select(
VdbeComment((v, "%s", pItem->pTab->zName));
pItem->addrFillSub = addrTop;
sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
- ExplainQueryPlan((pParse, 1, "CO-ROUTINE 0x%p", pSub));
+ ExplainQueryPlan((pParse, 1, "CO-ROUTINE %u", pSub->selId));
sqlite3Select(pParse, pSub, &dest);
pItem->pTab->nRowLogEst = pSub->nSelectRow;
pItem->fg.viaCoroutine = 1;
@@ -127001,7 +129038,7 @@ SQLITE_PRIVATE int sqlite3Select(
pSub->nSelectRow = pPrior->pSelect->nSelectRow;
}else{
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
- ExplainQueryPlan((pParse, 1, "MATERIALIZE 0x%p", pSub));
+ ExplainQueryPlan((pParse, 1, "MATERIALIZE %u", pSub->selId));
sqlite3Select(pParse, pSub, &dest);
}
pItem->pTab->nRowLogEst = pSub->nSelectRow;
@@ -127032,16 +129069,6 @@ SQLITE_PRIVATE int sqlite3Select(
}
#endif
-#ifdef SQLITE_COUNTOFVIEW_OPTIMIZATION
- if( OptimizationEnabled(db, SQLITE_QueryFlattener|SQLITE_CountOfView)
- && countOfViewOptimization(pParse, p)
- ){
- if( db->mallocFailed ) goto select_end;
- pEList = p->pEList;
- pTabList = p->pSrc;
- }
-#endif
-
/* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
** if the select-list is the same as the ORDER BY list, then this query
** can be rewritten as a GROUP BY. In other words, this:
@@ -127085,7 +129112,8 @@ SQLITE_PRIVATE int sqlite3Select(
*/
if( sSort.pOrderBy ){
KeyInfo *pKeyInfo;
- pKeyInfo = keyInfoFromExprList(pParse, sSort.pOrderBy, 0, pEList->nExpr);
+ pKeyInfo = sqlite3KeyInfoFromExprList(
+ pParse, sSort.pOrderBy, 0, pEList->nExpr);
sSort.iECursor = pParse->nTab++;
sSort.addrSortIndex =
sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
@@ -127119,9 +129147,9 @@ SQLITE_PRIVATE int sqlite3Select(
if( p->selFlags & SF_Distinct ){
sDistinct.tabTnct = pParse->nTab++;
sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
- sDistinct.tabTnct, 0, 0,
- (char*)keyInfoFromExprList(pParse, p->pEList,0,0),
- P4_KEYINFO);
+ sDistinct.tabTnct, 0, 0,
+ (char*)sqlite3KeyInfoFromExprList(pParse, p->pEList,0,0),
+ P4_KEYINFO);
sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED;
}else{
@@ -127130,9 +129158,16 @@ SQLITE_PRIVATE int sqlite3Select(
if( !isAgg && pGroupBy==0 ){
/* No aggregate functions and no GROUP BY clause */
- u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0);
+ u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0)
+ | (p->selFlags & SF_FixedLimit);
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ Window *pWin = p->pWin; /* Master window object (or NULL) */
+ if( pWin ){
+ sqlite3WindowCodeInit(pParse, pWin);
+ }
+#endif
assert( WHERE_USE_LIMIT==SF_FixedLimit );
- wctrlFlags |= p->selFlags & SF_FixedLimit;
+
/* Begin the database scan. */
SELECTTRACE(1,pParse,p,("WhereBegin\n"));
@@ -127147,7 +129182,7 @@ SQLITE_PRIVATE int sqlite3Select(
}
if( sSort.pOrderBy ){
sSort.nOBSat = sqlite3WhereIsOrdered(pWInfo);
- sSort.bOrderedInnerLoop = sqlite3WhereOrderedInnerLoop(pWInfo);
+ sSort.labelOBLopt = sqlite3WhereOrderByLimitOptLabel(pWInfo);
if( sSort.nOBSat==sSort.pOrderBy->nExpr ){
sSort.pOrderBy = 0;
}
@@ -127161,15 +129196,37 @@ SQLITE_PRIVATE int sqlite3Select(
sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex);
}
- /* Use the standard inner loop. */
assert( p->pEList==pEList );
- selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest,
- sqlite3WhereContinueLabel(pWInfo),
- sqlite3WhereBreakLabel(pWInfo));
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( pWin ){
+ int addrGosub = sqlite3VdbeMakeLabel(v);
+ int iCont = sqlite3VdbeMakeLabel(v);
+ int iBreak = sqlite3VdbeMakeLabel(v);
+ int regGosub = ++pParse->nMem;
+
+ sqlite3WindowCodeStep(pParse, p, pWInfo, regGosub, addrGosub);
+
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak);
+ sqlite3VdbeResolveLabel(v, addrGosub);
+ VdbeNoopComment((v, "inner-loop subroutine"));
+ sSort.labelOBLopt = 0;
+ selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, iCont, iBreak);
+ sqlite3VdbeResolveLabel(v, iCont);
+ sqlite3VdbeAddOp1(v, OP_Return, regGosub);
+ VdbeComment((v, "end inner-loop subroutine"));
+ sqlite3VdbeResolveLabel(v, iBreak);
+ }else
+#endif /* SQLITE_OMIT_WINDOWFUNC */
+ {
+ /* Use the standard inner loop. */
+ selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest,
+ sqlite3WhereContinueLabel(pWInfo),
+ sqlite3WhereBreakLabel(pWInfo));
- /* End the database scan loop.
- */
- sqlite3WhereEnd(pWInfo);
+ /* End the database scan loop.
+ */
+ sqlite3WhereEnd(pWInfo);
+ }
}else{
/* This case when there exist aggregate functions or a GROUP BY clause
** or both */
@@ -127298,7 +129355,7 @@ SQLITE_PRIVATE int sqlite3Select(
** will be converted into a Noop.
*/
sAggInfo.sortingIdx = pParse->nTab++;
- pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0, sAggInfo.nColumn);
+ pKeyInfo = sqlite3KeyInfoFromExprList(pParse,pGroupBy,0,sAggInfo.nColumn);
addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen,
sAggInfo.sortingIdx, sAggInfo.nSortingColumn,
0, (char*)pKeyInfo, P4_KEYINFO);
@@ -127317,8 +129374,6 @@ SQLITE_PRIVATE int sqlite3Select(
pParse->nMem += pGroupBy->nExpr;
sqlite3VdbeAddOp2(v, OP_Integer, 0, iAbortFlag);
VdbeComment((v, "clear abort flag"));
- sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
- VdbeComment((v, "indicate accumulator empty"));
sqlite3VdbeAddOp3(v, OP_Null, 0, iAMem, iAMem+pGroupBy->nExpr-1);
/* Begin a loop that will extract all source rows in GROUP BY order.
@@ -127364,15 +129419,14 @@ SQLITE_PRIVATE int sqlite3Select(
}
}
regBase = sqlite3GetTempRange(pParse, nCol);
- sqlite3ExprCacheClear(pParse);
sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0, 0);
j = nGroupBy;
for(i=0; i<sAggInfo.nColumn; i++){
struct AggInfo_col *pCol = &sAggInfo.aCol[i];
if( pCol->iSorterColumn>=j ){
int r1 = j + regBase;
- sqlite3ExprCodeGetColumnToReg(pParse,
- pCol->pTab, pCol->iColumn, pCol->iTable, r1);
+ sqlite3ExprCodeGetColumnOfTable(v,
+ pCol->pTab, pCol->iTable, pCol->iColumn, r1);
j++;
}
}
@@ -127388,8 +129442,6 @@ SQLITE_PRIVATE int sqlite3Select(
sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd);
VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v);
sAggInfo.useSortingIdx = 1;
- sqlite3ExprCacheClear(pParse);
-
}
/* If the index or temporary table used by the GROUP BY sort
@@ -127412,7 +129464,6 @@ SQLITE_PRIVATE int sqlite3Select(
** from the previous row currently stored in a0, a1, a2...
*/
addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
- sqlite3ExprCacheClear(pParse);
if( groupBySort ){
sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx,
sortOut, sortPTab);
@@ -127451,7 +129502,7 @@ SQLITE_PRIVATE int sqlite3Select(
** the current row
*/
sqlite3VdbeJumpHere(v, addr1);
- updateAccumulator(pParse, &sAggInfo);
+ updateAccumulator(pParse, iUseFlag, &sAggInfo);
sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag);
VdbeComment((v, "indicate data in accumulator"));
@@ -127503,6 +129554,8 @@ SQLITE_PRIVATE int sqlite3Select(
*/
sqlite3VdbeResolveLabel(v, addrReset);
resetAccumulator(pParse, &sAggInfo);
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
+ VdbeComment((v, "indicate accumulator empty"));
sqlite3VdbeAddOp1(v, OP_Return, regReset);
} /* endif pGroupBy. Begin aggregate queries without GROUP BY: */
@@ -127568,6 +129621,23 @@ SQLITE_PRIVATE int sqlite3Select(
}else
#endif /* SQLITE_OMIT_BTREECOUNT */
{
+ int regAcc = 0; /* "populate accumulators" flag */
+
+ /* If there are accumulator registers but no min() or max() functions,
+ ** allocate register regAcc. Register regAcc will contain 0 the first
+ ** time the inner loop runs, and 1 thereafter. The code generated
+ ** by updateAccumulator() only updates the accumulator registers if
+ ** regAcc contains 0. */
+ if( sAggInfo.nAccumulator ){
+ for(i=0; i<sAggInfo.nFunc; i++){
+ if( sAggInfo.aFunc[i].pFunc->funcFlags&SQLITE_FUNC_NEEDCOLL ) break;
+ }
+ if( i==sAggInfo.nFunc ){
+ regAcc = ++pParse->nMem;
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, regAcc);
+ }
+ }
+
/* This case runs if the aggregate has no GROUP BY clause. The
** processing is much simpler since there is only a single row
** of output.
@@ -127589,7 +129659,8 @@ SQLITE_PRIVATE int sqlite3Select(
if( pWInfo==0 ){
goto select_end;
}
- updateAccumulator(pParse, &sAggInfo);
+ updateAccumulator(pParse, regAcc, &sAggInfo);
+ if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc);
if( sqlite3WhereIsOrdered(pWInfo)>0 ){
sqlite3VdbeGoto(v, sqlite3WhereBreakLabel(pWInfo));
VdbeComment((v, "%s() by index",
@@ -128033,14 +130104,16 @@ SQLITE_PRIVATE void sqlite3BeginTrigger(
goto trigger_cleanup;
}
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),zName) ){
- if( !noErr ){
- sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);
- }else{
- assert( !db->init.busy );
- sqlite3CodeVerifySchema(pParse, iDb);
+ if( !IN_RENAME_OBJECT ){
+ if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),zName) ){
+ if( !noErr ){
+ sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);
+ }else{
+ assert( !db->init.busy );
+ sqlite3CodeVerifySchema(pParse, iDb);
+ }
+ goto trigger_cleanup;
}
- goto trigger_cleanup;
}
/* Do not create a trigger on a system table */
@@ -128064,7 +130137,7 @@ SQLITE_PRIVATE void sqlite3BeginTrigger(
}
#ifndef SQLITE_OMIT_AUTHORIZATION
- {
+ if( !IN_RENAME_OBJECT ){
int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
int code = SQLITE_CREATE_TRIGGER;
const char *zDb = db->aDb[iTabDb].zDbSName;
@@ -128098,8 +130171,15 @@ SQLITE_PRIVATE void sqlite3BeginTrigger(
pTrigger->pTabSchema = pTab->pSchema;
pTrigger->op = (u8)op;
pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER;
- pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE);
- pTrigger->pColumns = sqlite3IdListDup(db, pColumns);
+ if( IN_RENAME_OBJECT ){
+ sqlite3RenameTokenRemap(pParse, pTrigger->table, pTableName->a[0].zName);
+ pTrigger->pWhen = pWhen;
+ pWhen = 0;
+ }else{
+ pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE);
+ }
+ pTrigger->pColumns = pColumns;
+ pColumns = 0;
assert( pParse->pNewTrigger==0 );
pParse->pNewTrigger = pTrigger;
@@ -128148,6 +130228,14 @@ SQLITE_PRIVATE void sqlite3FinishTrigger(
goto triggerfinish_cleanup;
}
+#ifndef SQLITE_OMIT_ALTERTABLE
+ if( IN_RENAME_OBJECT ){
+ assert( !db->init.busy );
+ pParse->pNewTrigger = pTrig;
+ pTrig = 0;
+ }else
+#endif
+
/* if we are not initializing,
** build the sqlite_master entry
*/
@@ -128189,7 +130277,7 @@ SQLITE_PRIVATE void sqlite3FinishTrigger(
triggerfinish_cleanup:
sqlite3DeleteTrigger(db, pTrig);
- assert( !pParse->pNewTrigger );
+ assert( IN_RENAME_OBJECT || !pParse->pNewTrigger );
sqlite3DeleteTriggerStep(db, pStepList);
}
@@ -128236,12 +130324,13 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(
** If an OOM error occurs, NULL is returned and db->mallocFailed is set.
*/
static TriggerStep *triggerStepAllocate(
- sqlite3 *db, /* Database connection */
+ Parse *pParse, /* Parser context */
u8 op, /* Trigger opcode */
Token *pName, /* The target name */
const char *zStart, /* Start of SQL text */
const char *zEnd /* End of SQL text */
){
+ sqlite3 *db = pParse->db;
TriggerStep *pTriggerStep;
pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n + 1);
@@ -128252,6 +130341,9 @@ static TriggerStep *triggerStepAllocate(
pTriggerStep->zTarget = z;
pTriggerStep->op = op;
pTriggerStep->zSpan = triggerSpanDup(db, zStart, zEnd);
+ if( IN_RENAME_OBJECT ){
+ sqlite3RenameTokenMap(pParse, pTriggerStep->zTarget, pName);
+ }
}
return pTriggerStep;
}
@@ -128264,7 +130356,7 @@ static TriggerStep *triggerStepAllocate(
** body of a trigger.
*/
SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(
- sqlite3 *db, /* The database connection */
+ Parse *pParse, /* Parser */
Token *pTableName, /* Name of the table into which we insert */
IdList *pColumn, /* List of columns in pTableName to insert into */
Select *pSelect, /* A SELECT statement that supplies values */
@@ -128273,13 +130365,19 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(
const char *zStart, /* Start of SQL text */
const char *zEnd /* End of SQL text */
){
+ sqlite3 *db = pParse->db;
TriggerStep *pTriggerStep;
assert(pSelect != 0 || db->mallocFailed);
- pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName, zStart, zEnd);
+ pTriggerStep = triggerStepAllocate(pParse, TK_INSERT, pTableName,zStart,zEnd);
if( pTriggerStep ){
- pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
+ if( IN_RENAME_OBJECT ){
+ pTriggerStep->pSelect = pSelect;
+ pSelect = 0;
+ }else{
+ pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
+ }
pTriggerStep->pIdList = pColumn;
pTriggerStep->pUpsert = pUpsert;
pTriggerStep->orconf = orconf;
@@ -128300,7 +130398,7 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(
** sees an UPDATE statement inside the body of a CREATE TRIGGER.
*/
SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(
- sqlite3 *db, /* The database connection */
+ Parse *pParse, /* Parser */
Token *pTableName, /* Name of the table to be updated */
ExprList *pEList, /* The SET clause: list of column and new values */
Expr *pWhere, /* The WHERE clause */
@@ -128308,12 +130406,20 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(
const char *zStart, /* Start of SQL text */
const char *zEnd /* End of SQL text */
){
+ sqlite3 *db = pParse->db;
TriggerStep *pTriggerStep;
- pTriggerStep = triggerStepAllocate(db, TK_UPDATE, pTableName, zStart, zEnd);
+ pTriggerStep = triggerStepAllocate(pParse, TK_UPDATE, pTableName,zStart,zEnd);
if( pTriggerStep ){
- pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE);
- pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
+ if( IN_RENAME_OBJECT ){
+ pTriggerStep->pExprList = pEList;
+ pTriggerStep->pWhere = pWhere;
+ pEList = 0;
+ pWhere = 0;
+ }else{
+ pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE);
+ pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
+ }
pTriggerStep->orconf = orconf;
}
sqlite3ExprListDelete(db, pEList);
@@ -128327,17 +130433,23 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(
** sees a DELETE statement inside the body of a CREATE TRIGGER.
*/
SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(
- sqlite3 *db, /* Database connection */
+ Parse *pParse, /* Parser */
Token *pTableName, /* The table from which rows are deleted */
Expr *pWhere, /* The WHERE clause */
const char *zStart, /* Start of SQL text */
const char *zEnd /* End of SQL text */
){
+ sqlite3 *db = pParse->db;
TriggerStep *pTriggerStep;
- pTriggerStep = triggerStepAllocate(db, TK_DELETE, pTableName, zStart, zEnd);
+ pTriggerStep = triggerStepAllocate(pParse, TK_DELETE, pTableName,zStart,zEnd);
if( pTriggerStep ){
- pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
+ if( IN_RENAME_OBJECT ){
+ pTriggerStep->pWhere = pWhere;
+ pWhere = 0;
+ }else{
+ pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
+ }
pTriggerStep->orconf = OE_Default;
}
sqlite3ExprDelete(db, pWhere);
@@ -129522,7 +131634,7 @@ SQLITE_PRIVATE void sqlite3Update(
if( !isView && aiCurOnePass[0]!=iDataCur && aiCurOnePass[1]!=iDataCur ){
assert( pPk );
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey,nKey);
- VdbeCoverageNeverTaken(v);
+ VdbeCoverage(v);
}
if( eOnePass!=ONEPASS_SINGLE ){
labelContinue = sqlite3VdbeMakeLabel(v);
@@ -129609,13 +131721,7 @@ SQLITE_PRIVATE void sqlite3Update(
*/
testcase( i==31 );
testcase( i==32 );
- sqlite3ExprCodeGetColumnToReg(pParse, pTab, i, iDataCur, regNew+i);
- if( tmask & TRIGGER_BEFORE ){
- /* This value will be recomputed in After-BEFORE-trigger-reload-loop
- ** below, so make sure that it is not cached and reused.
- ** Ticket d85fffd6ffe856092ed8daefa811b1e399706b28. */
- sqlite3ExprCacheRemove(pParse, regNew+i, 1);
- }
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
}
@@ -130152,10 +132258,12 @@ SQLITE_PRIVATE void sqlite3UpsertDoUpdate(
Vdbe *v = pParse->pVdbe;
sqlite3 *db = pParse->db;
SrcList *pSrc; /* FROM clause for the UPDATE */
- int iDataCur = pUpsert->iDataCur;
+ int iDataCur;
assert( v!=0 );
+ assert( pUpsert!=0 );
VdbeNoopComment((v, "Begin DO UPDATE of UPSERT"));
+ iDataCur = pUpsert->iDataCur;
if( pIdx && iCur!=iDataCur ){
if( HasRowid(pTab) ){
int regRowid = sqlite3GetTempReg(pParse);
@@ -130425,7 +132533,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
*/
rc = execSql(db, pzErrMsg, "BEGIN");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
- rc = sqlite3BtreeBeginTrans(pMain, 2);
+ rc = sqlite3BtreeBeginTrans(pMain, 2, 0);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Do not attempt to change the page size for a WAL database */
@@ -130843,7 +132951,7 @@ SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3 *db){
assert( sqlite3_mutex_held(db->mutex) );
if( p ){
- sqlite3ExpirePreparedStatements(db);
+ sqlite3ExpirePreparedStatements(db, 0);
do {
VTable *pNext = p->pNext;
sqlite3VtabUnlock(p);
@@ -131339,7 +133447,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
assert( IsVirtual(pTab) );
memset(&sParse, 0, sizeof(sParse));
- sParse.declareVtab = 1;
+ sParse.eParseMode = PARSE_MODE_DECLARE_VTAB;
sParse.db = db;
sParse.nQueryLoop = 1;
if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable, &zErr)
@@ -131380,7 +133488,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
sqlite3DbFree(db, zErr);
rc = SQLITE_ERROR;
}
- sParse.declareVtab = 0;
+ sParse.eParseMode = PARSE_MODE_NORMAL;
if( sParse.pVdbe ){
sqlite3VdbeFinalize(sParse.pVdbe);
@@ -131934,6 +134042,8 @@ struct WhereLevel {
struct InLoop {
int iCur; /* The VDBE cursor used by this IN operator */
int addrInTop; /* Top of the IN loop */
+ int iBase; /* Base register of multi-key index record */
+ int nPrefix; /* Number of prior entires in the key */
u8 eEndLoopOp; /* IN Loop terminator. OP_Next or OP_Prev */
} *aInLoop; /* Information about each nested IN operator */
} in; /* Used when pWLoop->wsFlags&WHERE_IN_ABLE */
@@ -132172,6 +134282,7 @@ struct WhereClause {
WhereInfo *pWInfo; /* WHERE clause processing context */
WhereClause *pOuter; /* Outer conjunction */
u8 op; /* Split operator. TK_AND or TK_OR */
+ u8 hasOr; /* True if any a[].eOperator is WO_OR */
int nTerm; /* Number of terms */
int nSlot; /* Number of entries in a[] */
WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */
@@ -132345,6 +134456,7 @@ SQLITE_PRIVATE void sqlite3WhereClauseInit(WhereClause*,WhereInfo*);
SQLITE_PRIVATE void sqlite3WhereClauseClear(WhereClause*);
SQLITE_PRIVATE void sqlite3WhereSplit(WhereClause*,Expr*,u8);
SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet*, Expr*);
+SQLITE_PRIVATE Bitmask sqlite3WhereExprUsageNN(WhereMaskSet*, Expr*);
SQLITE_PRIVATE Bitmask sqlite3WhereExprListUsage(WhereMaskSet*, ExprList*);
SQLITE_PRIVATE void sqlite3WhereExprAnalyze(SrcList*, WhereClause*);
SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*);
@@ -132407,6 +134519,7 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereC
#define WHERE_SKIPSCAN 0x00008000 /* Uses the skip-scan algorithm */
#define WHERE_UNQ_WANTED 0x00010000 /* WHERE_ONEROW would have been helpful*/
#define WHERE_PARTIALIDX 0x00020000 /* The automatic index is partial */
+#define WHERE_IN_EARLYOUT 0x00040000 /* Perhaps quit IN loops early */
/************** End of whereInt.h ********************************************/
/************** Continuing where we left off in wherecode.c ******************/
@@ -132541,7 +134654,7 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan(
sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
sqlite3_str_appendall(&str, isSearch ? "SEARCH" : "SCAN");
if( pItem->pSelect ){
- sqlite3_str_appendf(&str, " SUBQUERY 0x%p", pItem->pSelect);
+ sqlite3_str_appendf(&str, " SUBQUERY %u", pItem->pSelect->selId);
}else{
sqlite3_str_appendf(&str, " TABLE %s", pItem->zName);
}
@@ -132738,7 +134851,6 @@ static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){
/* Code the OP_Affinity opcode if there is anything left to do. */
if( n>0 ){
sqlite3VdbeAddOp4(v, OP_Affinity, base, n, 0, zAff, n);
- sqlite3ExprCacheAffinityChange(pParse, base, n);
}
}
@@ -132982,7 +135094,14 @@ static int codeEqualityTerm(
sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v);
if( i==iEq ){
pIn->iCur = iTab;
- pIn->eEndLoopOp = bRev ? OP_PrevIfOpen : OP_NextIfOpen;
+ pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
+ if( iEq>0 && (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ){
+ pIn->iBase = iReg - i;
+ pIn->nPrefix = i;
+ pLoop->wsFlags |= WHERE_IN_EARLYOUT;
+ }else{
+ pIn->nPrefix = 0;
+ }
}else{
pIn->eEndLoopOp = OP_Noop;
}
@@ -133269,11 +135388,8 @@ static int codeCursorHintFixExpr(Walker *pWalker, Expr *pExpr){
struct CCurHint *pHint = pWalker->u.pCCurHint;
if( pExpr->op==TK_COLUMN ){
if( pExpr->iTable!=pHint->iTabCur ){
- Vdbe *v = pWalker->pParse->pVdbe;
int reg = ++pWalker->pParse->nMem; /* Register for column value */
- sqlite3ExprCodeGetColumnOfTable(
- v, pExpr->pTab, pExpr->iTable, pExpr->iColumn, reg
- );
+ sqlite3ExprCode(pWalker->pParse, pExpr, reg);
pExpr->op = TK_REGISTER;
pExpr->iTable = reg;
}else if( pHint->pIdx!=0 ){
@@ -133626,7 +135742,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub);
pLevel->p2 = sqlite3VdbeAddOp2(v, OP_Yield, regYield, addrBrk);
VdbeCoverage(v);
- VdbeComment((v, "next row of \"%s\"", pTabItem->pTab->zName));
+ VdbeComment((v, "next row of %s", pTabItem->pTab->zName));
pLevel->op = OP_Goto;
}else
@@ -133640,7 +135756,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
int nConstraint = pLoop->nLTerm;
int iIn; /* Counter for IN constraints */
- sqlite3ExprCachePush(pParse);
iReg = sqlite3GetTempRange(pParse, nConstraint+2);
addrNotFound = pLevel->addrBrk;
for(j=0; j<nConstraint; j++){
@@ -133713,7 +135828,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
**
** sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2);
*/
- sqlite3ExprCachePop(pParse);
}else
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -133737,9 +135851,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
addrNxt = pLevel->addrNxt;
sqlite3VdbeAddOp3(v, OP_SeekRowid, iCur, addrNxt, iRowidReg);
VdbeCoverage(v);
- sqlite3ExprCacheAffinityChange(pParse, iRowidReg, 1);
- sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
- VdbeComment((v, "pk"));
pLevel->op = OP_Noop;
}else if( (pLoop->wsFlags & WHERE_IPK)!=0
&& (pLoop->wsFlags & WHERE_COLUMN_RANGE)!=0
@@ -133809,7 +135920,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
VdbeCoverageIf(v, pX->op==TK_LE);
VdbeCoverageIf(v, pX->op==TK_LT);
VdbeCoverageIf(v, pX->op==TK_GE);
- sqlite3ExprCacheAffinityChange(pParse, r1, 1);
sqlite3ReleaseTempReg(pParse, rTemp);
}else{
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrHalt);
@@ -133844,7 +135954,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
if( testOp!=OP_Noop ){
iRowidReg = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg);
- sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg);
VdbeCoverageIf(v, testOp==OP_Le);
VdbeCoverageIf(v, testOp==OP_Lt);
@@ -134049,6 +136158,9 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
** above has already left the cursor sitting on the correct row,
** so no further seeking is needed */
}else{
+ if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){
+ sqlite3VdbeAddOp1(v, OP_SeekHit, iIdxCur);
+ }
op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
assert( op!=0 );
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
@@ -134067,7 +136179,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
nConstraint = nEq;
if( pRangeEnd ){
Expr *pRight = pRangeEnd->pExpr->pRight;
- sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
codeExprOrVector(pParse, pRight, regBase+nEq, nTop);
whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd);
if( (pRangeEnd->wtFlags & TERM_VNULL)==0
@@ -134092,7 +136203,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
}
}else if( bStopAtNull ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
- sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
endEq = 0;
nConstraint++;
}
@@ -134112,6 +136222,10 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE );
}
+ if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){
+ sqlite3VdbeAddOp2(v, OP_SeekHit, iIdxCur, 1);
+ }
+
/* Seek the table cursor, if required */
if( omitTable ){
/* pIdx is a covering index. No need to access the main table. */
@@ -134122,7 +136236,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
)){
iRowidReg = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
- sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg);
VdbeCoverage(v);
}else{
@@ -134357,23 +136470,23 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
** row will be skipped in subsequent sub-WHERE clauses.
*/
if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
- int r;
int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
if( HasRowid(pTab) ){
- r = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, regRowid, 0);
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, -1, regRowid);
jmp1 = sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, 0,
- r,iSet);
+ regRowid, iSet);
VdbeCoverage(v);
}else{
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
int nPk = pPk->nKeyCol;
int iPk;
+ int r;
/* Read the PK into an array of temp registers. */
r = sqlite3GetTempRange(pParse, nPk);
for(iPk=0; iPk<nPk; iPk++){
int iCol = pPk->aiColumn[iPk];
- sqlite3ExprCodeGetColumnToReg(pParse, pTab, iCol, iCur, r+iPk);
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol, r+iPk);
}
/* Check if the temp table already contains this key. If so,
@@ -134606,7 +136719,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
pLevel->addrFirst = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin);
VdbeComment((v, "record LEFT JOIN hit"));
- sqlite3ExprCacheClear(pParse);
for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){
testcase( pTerm->wtFlags & TERM_VIRTUAL );
testcase( pTerm->wtFlags & TERM_CODED );
@@ -134822,18 +136934,18 @@ static int isLikeOrGlob(
int *pisComplete, /* True if the only wildcard is % in the last character */
int *pnoCase /* True if uppercase is equivalent to lowercase */
){
- const u8 *z = 0; /* String on RHS of LIKE operator */
+ const u8 *z = 0; /* String on RHS of LIKE operator */
Expr *pRight, *pLeft; /* Right and left size of LIKE operator */
ExprList *pList; /* List of operands to the LIKE operator */
- int c; /* One character in z[] */
+ u8 c; /* One character in z[] */
int cnt; /* Number of non-wildcard prefix characters */
- char wc[4]; /* Wildcard characters */
+ u8 wc[4]; /* Wildcard characters */
sqlite3 *db = pParse->db; /* Database connection */
sqlite3_value *pVal = 0;
int op; /* Opcode of pRight */
int rc; /* Result code to return */
- if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, wc) ){
+ if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, (char*)wc) ){
return 0;
}
#ifdef SQLITE_EBCDIC
@@ -134858,23 +136970,6 @@ static int isLikeOrGlob(
}
if( z ){
- /* If the RHS begins with a digit or a minus sign, then the LHS must
- ** be an ordinary column (not a virtual table column) with TEXT affinity.
- ** Otherwise the LHS might be numeric and "lhs >= rhs" would be false
- ** even though "lhs LIKE rhs" is true. But if the RHS does not start
- ** with a digit or '-', then "lhs LIKE rhs" will always be false if
- ** the LHS is numeric and so the optimization still works.
- */
- if( sqlite3Isdigit(z[0]) || z[0]=='-' ){
- if( pLeft->op!=TK_COLUMN
- || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
- || IsVirtual(pLeft->pTab) /* Value might be numeric */
- ){
- sqlite3ValueFree(pVal);
- return 0;
- }
- }
-
/* Count the number of prefix characters prior to the first wildcard */
cnt = 0;
while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){
@@ -134884,11 +136979,13 @@ static int isLikeOrGlob(
/* The optimization is possible only if (1) the pattern does not begin
** with a wildcard and if (2) the non-wildcard prefix does not end with
- ** an (illegal 0xff) character. The second condition is necessary so
+ ** an (illegal 0xff) character, or (3) the pattern does not consist of
+ ** a single escape character. The second condition is necessary so
** that we can increment the prefix key to find an upper bound for the
- ** range search.
- */
- if( cnt!=0 && 255!=(u8)z[cnt-1] ){
+ ** range search. The third is because the caller assumes that the pattern
+ ** consists of at least one character after all escapes have been
+ ** removed. */
+ if( cnt!=0 && 255!=(u8)z[cnt-1] && (cnt>1 || z[0]!=wc[3]) ){
Expr *pPrefix;
/* A "complete" match if the pattern ends with "*" or "%" */
@@ -134905,6 +137002,32 @@ static int isLikeOrGlob(
zNew[iTo++] = zNew[iFrom];
}
zNew[iTo] = 0;
+
+ /* If the RHS begins with a digit or a minus sign, then the LHS must be
+ ** an ordinary column (not a virtual table column) with TEXT affinity.
+ ** Otherwise the LHS might be numeric and "lhs >= rhs" would be false
+ ** even though "lhs LIKE rhs" is true. But if the RHS does not start
+ ** with a digit or '-', then "lhs LIKE rhs" will always be false if
+ ** the LHS is numeric and so the optimization still works.
+ **
+ ** 2018-09-10 ticket c94369cae9b561b1f996d0054bfab11389f9d033
+ ** The RHS pattern must not be '/%' because the termination condition
+ ** will then become "x<'0'" and if the affinity is numeric, will then
+ ** be converted into "x<0", which is incorrect.
+ */
+ if( sqlite3Isdigit(zNew[0])
+ || zNew[0]=='-'
+ || (zNew[0]+1=='0' && iTo==1)
+ ){
+ if( pLeft->op!=TK_COLUMN
+ || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
+ || IsVirtual(pLeft->pTab) /* Value might be numeric */
+ ){
+ sqlite3ExprDelete(db, pPrefix);
+ sqlite3ValueFree(pVal);
+ return 0;
+ }
+ }
}
*ppPrefix = pPrefix;
@@ -134966,6 +137089,7 @@ static int isLikeOrGlob(
** If the expression matches none of the patterns above, return 0.
*/
static int isAuxiliaryVtabOperator(
+ sqlite3 *db, /* Parsing context */
Expr *pExpr, /* Test this expression */
unsigned char *peOp2, /* OUT: 0 for MATCH, or else an op2 value */
Expr **ppLeft, /* Column expression to left of MATCH/op2 */
@@ -134989,16 +137113,54 @@ static int isAuxiliaryVtabOperator(
if( pList==0 || pList->nExpr!=2 ){
return 0;
}
+
+ /* Built-in operators MATCH, GLOB, LIKE, and REGEXP attach to a
+ ** virtual table on their second argument, which is the same as
+ ** the left-hand side operand in their in-fix form.
+ **
+ ** vtab_column MATCH expression
+ ** MATCH(expression,vtab_column)
+ */
pCol = pList->a[1].pExpr;
- if( pCol->op!=TK_COLUMN || !IsVirtual(pCol->pTab) ){
- return 0;
+ if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){
+ for(i=0; i<ArraySize(aOp); i++){
+ if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
+ *peOp2 = aOp[i].eOp2;
+ *ppRight = pList->a[0].pExpr;
+ *ppLeft = pCol;
+ return 1;
+ }
+ }
}
- for(i=0; i<ArraySize(aOp); i++){
- if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
- *peOp2 = aOp[i].eOp2;
- *ppRight = pList->a[0].pExpr;
- *ppLeft = pCol;
- return 1;
+
+ /* We can also match against the first column of overloaded
+ ** functions where xFindFunction returns a value of at least
+ ** SQLITE_INDEX_CONSTRAINT_FUNCTION.
+ **
+ ** OVERLOADED(vtab_column,expression)
+ **
+ ** Historically, xFindFunction expected to see lower-case function
+ ** names. But for this use case, xFindFunction is expected to deal
+ ** with function names in an arbitrary case.
+ */
+ pCol = pList->a[0].pExpr;
+ if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){
+ sqlite3_vtab *pVtab;
+ sqlite3_module *pMod;
+ void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**);
+ void *pNotUsed;
+ pVtab = sqlite3GetVTable(db, pCol->pTab)->pVtab;
+ assert( pVtab!=0 );
+ assert( pVtab->pModule!=0 );
+ pMod = (sqlite3_module *)pVtab->pModule;
+ if( pMod->xFindFunction!=0 ){
+ i = pMod->xFindFunction(pVtab,2, pExpr->u.zToken, &xNotUsed, &pNotUsed);
+ if( i>=SQLITE_INDEX_CONSTRAINT_FUNCTION ){
+ *peOp2 = i;
+ *ppRight = pList->a[1].pExpr;
+ *ppLeft = pCol;
+ return 1;
+ }
}
}
}else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){
@@ -135300,7 +137462,12 @@ static void exprAnalyzeOrTerm(
** empty.
*/
pOrInfo->indexable = indexable;
- pTerm->eOperator = indexable==0 ? 0 : WO_OR;
+ if( indexable ){
+ pTerm->eOperator = WO_OR;
+ pWC->hasOr = 1;
+ }else{
+ pTerm->eOperator = WO_OR;
+ }
/* For a two-way OR, attempt to implementation case 2.
*/
@@ -135441,7 +137608,7 @@ static void exprAnalyzeOrTerm(
idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew==0 );
exprAnalyze(pSrc, pWC, idxNew);
- pTerm = &pWC->a[idxTerm];
+ /* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm where used again */
markTermAsChild(pWC, idxNew, idxTerm);
}else{
sqlite3ExprListDelete(db, pList);
@@ -135480,7 +137647,7 @@ static int termIsEquivalence(Parse *pParse, Expr *pExpr){
return 0;
}
pColl = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight);
- if( pColl==0 || sqlite3StrICmp(pColl->zName, "BINARY")==0 ) return 1;
+ if( sqlite3IsBinary(pColl) ) return 1;
return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight);
}
@@ -135639,7 +137806,7 @@ static void exprAnalyze(
pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->pRight);
}
pMaskSet->bVarSelect = 0;
- prereqAll = sqlite3WhereExprUsage(pMaskSet, pExpr);
+ prereqAll = sqlite3WhereExprUsageNN(pMaskSet, pExpr);
if( pMaskSet->bVarSelect ) pTerm->wtFlags |= TERM_VARSELECT;
if( ExprHasProperty(pExpr, EP_FromJoin) ){
Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->iRightJoinTable);
@@ -135821,7 +137988,7 @@ static void exprAnalyze(
}
*pC = c + 1;
}
- zCollSeqName = noCase ? "NOCASE" : "BINARY";
+ zCollSeqName = noCase ? "NOCASE" : sqlite3StrBINARY;
pNewExpr1 = sqlite3ExprDup(db, pLeft, 0);
pNewExpr1 = sqlite3PExpr(pParse, TK_GE,
sqlite3ExprAddCollateString(pParse,pNewExpr1,zCollSeqName),
@@ -135858,7 +138025,7 @@ static void exprAnalyze(
*/
if( pWC->op==TK_AND ){
Expr *pRight = 0, *pLeft = 0;
- int res = isAuxiliaryVtabOperator(pExpr, &eOp2, &pLeft, &pRight);
+ int res = isAuxiliaryVtabOperator(db, pExpr, &eOp2, &pLeft, &pRight);
while( res-- > 0 ){
int idxNew;
WhereTerm *pNewTerm;
@@ -136032,6 +138199,7 @@ SQLITE_PRIVATE void sqlite3WhereClauseInit(
WhereInfo *pWInfo /* The WHERE processing context */
){
pWC->pWInfo = pWInfo;
+ pWC->hasOr = 0;
pWC->pOuter = 0;
pWC->nTerm = 0;
pWC->nSlot = ArraySize(pWC->aStatic);
@@ -136068,17 +138236,18 @@ SQLITE_PRIVATE void sqlite3WhereClauseClear(WhereClause *pWC){
** a bitmask indicating which tables are used in that expression
** tree.
*/
-SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){
+SQLITE_PRIVATE Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){
Bitmask mask;
- if( p==0 ) return 0;
- if( p->op==TK_COLUMN ){
+ if( p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){
return sqlite3WhereGetMask(pMaskSet, p->iTable);
+ }else if( ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
+ assert( p->op!=TK_IF_NULL_ROW );
+ return 0;
}
mask = (p->op==TK_IF_NULL_ROW) ? sqlite3WhereGetMask(pMaskSet, p->iTable) : 0;
- assert( !ExprHasProperty(p, EP_TokenOnly) );
- if( p->pLeft ) mask |= sqlite3WhereExprUsage(pMaskSet, p->pLeft);
+ if( p->pLeft ) mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pLeft);
if( p->pRight ){
- mask |= sqlite3WhereExprUsage(pMaskSet, p->pRight);
+ mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pRight);
assert( p->x.pList==0 );
}else if( ExprHasProperty(p, EP_xIsSelect) ){
if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1;
@@ -136088,6 +138257,9 @@ SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){
}
return mask;
}
+SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){
+ return p ? sqlite3WhereExprUsageNN(pMaskSet,p) : 0;
+}
SQLITE_PRIVATE Bitmask sqlite3WhereExprListUsage(WhereMaskSet *pMaskSet, ExprList *pList){
int i;
Bitmask mask = 0;
@@ -136229,15 +138401,38 @@ SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo *pWInfo){
}
/*
-** Return TRUE if the innermost loop of the WHERE clause implementation
-** returns rows in ORDER BY order for complete run of the inner loop.
+** In the ORDER BY LIMIT optimization, if the inner-most loop is known
+** to emit rows in increasing order, and if the last row emitted by the
+** inner-most loop did not fit within the sorter, then we can skip all
+** subsequent rows for the current iteration of the inner loop (because they
+** will not fit in the sorter either) and continue with the second inner
+** loop - the loop immediately outside the inner-most.
+**
+** When a row does not fit in the sorter (because the sorter already
+** holds LIMIT+OFFSET rows that are smaller), then a jump is made to the
+** label returned by this function.
+**
+** If the ORDER BY LIMIT optimization applies, the jump destination should
+** be the continuation for the second-inner-most loop. If the ORDER BY
+** LIMIT optimization does not apply, then the jump destination should
+** be the continuation for the inner-most loop.
**
-** Across multiple iterations of outer loops, the output rows need not be
-** sorted. As long as rows are sorted for just the innermost loop, this
-** routine can return TRUE.
+** It is always safe for this routine to return the continuation of the
+** inner-most loop, in the sense that a correct answer will result.
+** Returning the continuation the second inner loop is an optimization
+** that might make the code run a little faster, but should not change
+** the final answer.
*/
-SQLITE_PRIVATE int sqlite3WhereOrderedInnerLoop(WhereInfo *pWInfo){
- return pWInfo->bOrderedInnerLoop;
+SQLITE_PRIVATE int sqlite3WhereOrderByLimitOptLabel(WhereInfo *pWInfo){
+ WhereLevel *pInner;
+ if( !pWInfo->bOrderedInnerLoop ){
+ /* The ORDER BY LIMIT optimization does not apply. Jump to the
+ ** continuation of the inner-most loop. */
+ return pWInfo->iContinue;
+ }
+ pInner = &pWInfo->a[pWInfo->nLevel-1];
+ assert( pInner->addrNxt!=0 );
+ return pInner->addrNxt;
}
/*
@@ -136964,7 +139159,6 @@ static void constructAutomaticIndex(
VdbeComment((v, "for %s", pTable->zName));
/* Fill the automatic index with content */
- sqlite3ExprCachePush(pParse);
pTabItem = &pWC->pWInfo->pTabList->a[pLevel->iFrom];
if( pTabItem->fg.viaCoroutine ){
int regYield = pTabItem->regReturn;
@@ -136972,7 +139166,7 @@ static void constructAutomaticIndex(
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub);
addrTop = sqlite3VdbeAddOp1(v, OP_Yield, regYield);
VdbeCoverage(v);
- VdbeComment((v, "next row of \"%s\"", pTabItem->pTab->zName));
+ VdbeComment((v, "next row of %s", pTabItem->pTab->zName));
}else{
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v);
}
@@ -137001,7 +139195,6 @@ static void constructAutomaticIndex(
sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX);
sqlite3VdbeJumpHere(v, addrTop);
sqlite3ReleaseTempReg(pParse, regRecord);
- sqlite3ExprCachePop(pParse);
/* Jump here when skipping the initialization */
sqlite3VdbeJumpHere(v, addrInit);
@@ -137107,6 +139300,20 @@ static sqlite3_index_info *allocateIndexInfo(
testcase( pTerm->eOperator & WO_ALL );
if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
if( pTerm->wtFlags & TERM_VNULL ) continue;
+ if( (pSrc->fg.jointype & JT_LEFT)!=0
+ && !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
+ && (pTerm->eOperator & (WO_IS|WO_ISNULL))
+ ){
+ /* An "IS" term in the WHERE clause where the virtual table is the rhs
+ ** of a LEFT JOIN. Do not pass this term to the virtual table
+ ** implementation, as this can lead to incorrect results from SQL such
+ ** as:
+ **
+ ** "LEFT JOIN vtab WHERE vtab.col IS NULL" */
+ testcase( pTerm->eOperator & WO_ISNULL );
+ testcase( pTerm->eOperator & WO_IS );
+ continue;
+ }
assert( pTerm->u.leftColumn>=(-1) );
pIdxCons[j].iColumn = pTerm->u.leftColumn;
pIdxCons[j].iTermOffset = i;
@@ -137598,7 +139805,9 @@ static int whereRangeScanEst(
Index *p = pLoop->u.btree.pIndex;
int nEq = pLoop->u.btree.nEq;
- if( p->nSample>0 && nEq<p->nSampleCol ){
+ if( p->nSample>0 && nEq<p->nSampleCol
+ && OptimizationEnabled(pParse->db, SQLITE_Stat34)
+ ){
if( nEq==pBuilder->nRecValid ){
UnpackedRecord *pRec = pBuilder->pRec;
tRowcnt a[2];
@@ -138613,7 +140822,6 @@ static int whereLoopAddBtreeIndex(
if( eOp & WO_IN ){
Expr *pExpr = pTerm->pExpr;
- pNew->wsFlags |= WHERE_COLUMN_IN;
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
/* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */
int i;
@@ -138633,6 +140841,42 @@ static int whereLoopAddBtreeIndex(
assert( nIn>0 ); /* RHS always has 2 or more terms... The parser
** changes "x IN (?)" into "x=?". */
}
+ if( pProbe->hasStat1 ){
+ LogEst M, logK, safetyMargin;
+ /* Let:
+ ** N = the total number of rows in the table
+ ** K = the number of entries on the RHS of the IN operator
+ ** M = the number of rows in the table that match terms to the
+ ** to the left in the same index. If the IN operator is on
+ ** the left-most index column, M==N.
+ **
+ ** Given the definitions above, it is better to omit the IN operator
+ ** from the index lookup and instead do a scan of the M elements,
+ ** testing each scanned row against the IN operator separately, if:
+ **
+ ** M*log(K) < K*log(N)
+ **
+ ** Our estimates for M, K, and N might be inaccurate, so we build in
+ ** a safety margin of 2 (LogEst: 10) that favors using the IN operator
+ ** with the index, as using an index has better worst-case behavior.
+ ** If we do not have real sqlite_stat1 data, always prefer to use
+ ** the index.
+ */
+ M = pProbe->aiRowLogEst[saved_nEq];
+ logK = estLog(nIn);
+ safetyMargin = 10; /* TUNING: extra weight for indexed IN */
+ if( M + logK + safetyMargin < nIn + rLogSize ){
+ WHERETRACE(0x40,
+ ("Scan preferred over IN operator on column %d of \"%s\" (%d<%d)\n",
+ saved_nEq, pProbe->zName, M+logK+10, nIn+rLogSize));
+ continue;
+ }else{
+ WHERETRACE(0x40,
+ ("IN operator preferred on column %d of \"%s\" (%d>=%d)\n",
+ saved_nEq, pProbe->zName, M+logK+10, nIn+rLogSize));
+ }
+ }
+ pNew->wsFlags |= WHERE_COLUMN_IN;
}else if( eOp & (WO_EQ|WO_IS) ){
int iCol = pProbe->aiColumn[saved_nEq];
pNew->wsFlags |= WHERE_COLUMN_EQ;
@@ -138711,6 +140955,7 @@ static int whereLoopAddBtreeIndex(
&& pProbe->nSample
&& pNew->u.btree.nEq<=pProbe->nSampleCol
&& ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect))
+ && OptimizationEnabled(db, SQLITE_Stat34)
){
Expr *pExpr = pTerm->pExpr;
if( (eOp & (WO_EQ|WO_ISNULL|WO_IS))!=0 ){
@@ -138799,6 +141044,7 @@ static int whereLoopAddBtreeIndex(
if( saved_nEq==saved_nSkip
&& saved_nEq+1<pProbe->nKeyCol
&& pProbe->noSkipScan==0
+ && OptimizationEnabled(db, SQLITE_SkipScan)
&& pProbe->aiRowLogEst[saved_nEq+1]>=42 /* TUNING: Minimum for skip-scan */
&& (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK
){
@@ -138862,24 +141108,6 @@ static int indexMightHelpWithOrderBy(
return 0;
}
-/*
-** Return a bitmask where 1s indicate that the corresponding column of
-** the table is used by an index. Only the first 63 columns are considered.
-*/
-static Bitmask columnsInIndex(Index *pIdx){
- Bitmask m = 0;
- int j;
- for(j=pIdx->nColumn-1; j>=0; j--){
- int x = pIdx->aiColumn[j];
- if( x>=0 ){
- testcase( x==BMS-1 );
- testcase( x==BMS-2 );
- if( x<BMS-1 ) m |= MASKBIT(x);
- }
- }
- return m;
-}
-
/* Check to see if a partial index with pPartIndexWhere can be used
** in the current query. Return true if it can be and false if not.
*/
@@ -139095,7 +141323,7 @@ static int whereLoopAddBtree(
pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED;
m = 0;
}else{
- m = pSrc->colUsed & ~columnsInIndex(pProbe);
+ m = pSrc->colUsed & pProbe->colNotIdxed;
pNew->wsFlags = (m==0) ? (WHERE_IDX_ONLY|WHERE_INDEXED) : WHERE_INDEXED;
}
@@ -139346,7 +141574,7 @@ SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info *pIdxInfo, int
if( pX->pLeft ){
pC = sqlite3BinaryCompareCollSeq(pHidden->pParse, pX->pLeft, pX->pRight);
}
- zRet = (pC ? pC->zName : "BINARY");
+ zRet = (pC ? pC->zName : sqlite3StrBINARY);
}
return zRet;
}
@@ -139662,7 +141890,7 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
{
rc = whereLoopAddBtree(pBuilder, mPrereq);
}
- if( rc==SQLITE_OK ){
+ if( rc==SQLITE_OK && pBuilder->pWC->hasOr ){
rc = whereLoopAddOr(pBuilder, mPrereq, mUnusable);
}
mPrior |= pNew->maskSelf;
@@ -140197,7 +142425,11 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
pWInfo, nRowEst, nOrderBy, isOrdered
);
}
- rCost = sqlite3LogEstAdd(rUnsorted, aSortCost[isOrdered]);
+ /* TUNING: Add a small extra penalty (5) to sorting as an
+ ** extra encouragment to the query planner to select a plan
+ ** where the rows emerge in the correct order without any sorting
+ ** required. */
+ rCost = sqlite3LogEstAdd(rUnsorted, aSortCost[isOrdered]) + 5;
WHERETRACE(0x002,
("---- sort cost=%-3d (%d/%d) increases cost %3d to %-3d\n",
@@ -140387,6 +142619,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
}
}
+ pWInfo->bOrderedInnerLoop = 0;
if( pWInfo->pOrderBy ){
if( pWInfo->wctrlFlags & WHERE_DISTINCTBY ){
if( pFrom->isOrdered==pWInfo->pOrderBy->nExpr ){
@@ -140498,7 +142731,7 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
}
if( j!=pIdx->nKeyCol ) continue;
pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_ONEROW|WHERE_INDEXED;
- if( pIdx->isCovering || (pItem->colUsed & ~columnsInIndex(pIdx))==0 ){
+ if( pIdx->isCovering || (pItem->colUsed & pIdx->colNotIdxed)==0 ){
pLoop->wsFlags |= WHERE_IDX_ONLY;
}
pLoop->nLTerm = j;
@@ -141179,6 +143412,26 @@ whereBeginError:
}
/*
+** Part of sqlite3WhereEnd() will rewrite opcodes to reference the
+** index rather than the main table. In SQLITE_DEBUG mode, we want
+** to trace those changes if PRAGMA vdbe_addoptrace=on. This routine
+** does that.
+*/
+#ifndef SQLITE_DEBUG
+# define OpcodeRewriteTrace(D,K,P) /* no-op */
+#else
+# define OpcodeRewriteTrace(D,K,P) sqlite3WhereOpcodeRewriteTrace(D,K,P)
+ static void sqlite3WhereOpcodeRewriteTrace(
+ sqlite3 *db,
+ int pc,
+ VdbeOp *pOp
+ ){
+ if( (db->flags & SQLITE_VdbeAddopTrace)==0 ) return;
+ sqlite3VdbePrintOp(0, pc, pOp);
+ }
+#endif
+
+/*
** Generate the end of the WHERE loop. See comments on
** sqlite3WhereBegin() for additional information.
*/
@@ -141194,7 +143447,6 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
/* Generate loop termination code.
*/
VdbeModuleComment((v, "End WHERE-core"));
- sqlite3ExprCacheClear(pParse);
for(i=pWInfo->nLevel-1; i>=0; i--){
int addr;
pLevel = &pWInfo->a[i];
@@ -141245,10 +143497,17 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
if( pIn->eEndLoopOp!=OP_Noop ){
+ if( pIn->nPrefix ){
+ assert( pLoop->wsFlags & WHERE_IN_EARLYOUT );
+ sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur,
+ sqlite3VdbeCurrentAddr(v)+2,
+ pIn->iBase, pIn->nPrefix);
+ VdbeCoverage(v);
+ }
sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
VdbeCoverage(v);
- VdbeCoverageIf(v, pIn->eEndLoopOp==OP_PrevIfOpen);
- VdbeCoverageIf(v, pIn->eEndLoopOp==OP_NextIfOpen);
+ VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Prev);
+ VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Next);
}
sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
}
@@ -141339,6 +143598,11 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
){
last = sqlite3VdbeCurrentAddr(v);
k = pLevel->addrBody;
+#ifdef SQLITE_DEBUG
+ if( db->flags & SQLITE_VdbeAddopTrace ){
+ printf("TRANSLATE opcodes in range %d..%d\n", k, last-1);
+ }
+#endif
pOp = sqlite3VdbeGetOp(v, k);
for(; k<last; k++, pOp++){
if( pOp->p1!=pLevel->iTabCur ) continue;
@@ -141358,16 +143622,22 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
if( x>=0 ){
pOp->p2 = x;
pOp->p1 = pLevel->iIdxCur;
+ OpcodeRewriteTrace(db, k, pOp);
}
assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || x>=0
|| pWInfo->eOnePass );
}else if( pOp->opcode==OP_Rowid ){
pOp->p1 = pLevel->iIdxCur;
pOp->opcode = OP_IdxRowid;
+ OpcodeRewriteTrace(db, k, pOp);
}else if( pOp->opcode==OP_IfNullRow ){
pOp->p1 = pLevel->iIdxCur;
+ OpcodeRewriteTrace(db, k, pOp);
}
}
+#ifdef SQLITE_DEBUG
+ if( db->flags & SQLITE_VdbeAddopTrace ) printf("TRANSLATE complete\n");
+#endif
}
}
@@ -141379,6 +143649,2261 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
}
/************** End of where.c ***********************************************/
+/************** Begin file window.c ******************************************/
+/*
+** 2018 May 08
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+*/
+/* #include "sqliteInt.h" */
+
+#ifndef SQLITE_OMIT_WINDOWFUNC
+
+/*
+** SELECT REWRITING
+**
+** Any SELECT statement that contains one or more window functions in
+** either the select list or ORDER BY clause (the only two places window
+** functions may be used) is transformed by function sqlite3WindowRewrite()
+** in order to support window function processing. For example, with the
+** schema:
+**
+** CREATE TABLE t1(a, b, c, d, e, f, g);
+**
+** the statement:
+**
+** SELECT a+1, max(b) OVER (PARTITION BY c ORDER BY d) FROM t1 ORDER BY e;
+**
+** is transformed to:
+**
+** SELECT a+1, max(b) OVER (PARTITION BY c ORDER BY d) FROM (
+** SELECT a, e, c, d, b FROM t1 ORDER BY c, d
+** ) ORDER BY e;
+**
+** The flattening optimization is disabled when processing this transformed
+** SELECT statement. This allows the implementation of the window function
+** (in this case max()) to process rows sorted in order of (c, d), which
+** makes things easier for obvious reasons. More generally:
+**
+** * FROM, WHERE, GROUP BY and HAVING clauses are all moved to
+** the sub-query.
+**
+** * ORDER BY, LIMIT and OFFSET remain part of the parent query.
+**
+** * Terminals from each of the expression trees that make up the
+** select-list and ORDER BY expressions in the parent query are
+** selected by the sub-query. For the purposes of the transformation,
+** terminals are column references and aggregate functions.
+**
+** If there is more than one window function in the SELECT that uses
+** the same window declaration (the OVER bit), then a single scan may
+** be used to process more than one window function. For example:
+**
+** SELECT max(b) OVER (PARTITION BY c ORDER BY d),
+** min(e) OVER (PARTITION BY c ORDER BY d)
+** FROM t1;
+**
+** is transformed in the same way as the example above. However:
+**
+** SELECT max(b) OVER (PARTITION BY c ORDER BY d),
+** min(e) OVER (PARTITION BY a ORDER BY b)
+** FROM t1;
+**
+** Must be transformed to:
+**
+** SELECT max(b) OVER (PARTITION BY c ORDER BY d) FROM (
+** SELECT e, min(e) OVER (PARTITION BY a ORDER BY b), c, d, b FROM
+** SELECT a, e, c, d, b FROM t1 ORDER BY a, b
+** ) ORDER BY c, d
+** ) ORDER BY e;
+**
+** so that both min() and max() may process rows in the order defined by
+** their respective window declarations.
+**
+** INTERFACE WITH SELECT.C
+**
+** When processing the rewritten SELECT statement, code in select.c calls
+** sqlite3WhereBegin() to begin iterating through the results of the
+** sub-query, which is always implemented as a co-routine. It then calls
+** sqlite3WindowCodeStep() to process rows and finish the scan by calling
+** sqlite3WhereEnd().
+**
+** sqlite3WindowCodeStep() generates VM code so that, for each row returned
+** by the sub-query a sub-routine (OP_Gosub) coded by select.c is invoked.
+** When the sub-routine is invoked:
+**
+** * The results of all window-functions for the row are stored
+** in the associated Window.regResult registers.
+**
+** * The required terminal values are stored in the current row of
+** temp table Window.iEphCsr.
+**
+** In some cases, depending on the window frame and the specific window
+** functions invoked, sqlite3WindowCodeStep() caches each entire partition
+** in a temp table before returning any rows. In other cases it does not.
+** This detail is encapsulated within this file, the code generated by
+** select.c is the same in either case.
+**
+** BUILT-IN WINDOW FUNCTIONS
+**
+** This implementation features the following built-in window functions:
+**
+** row_number()
+** rank()
+** dense_rank()
+** percent_rank()
+** cume_dist()
+** ntile(N)
+** lead(expr [, offset [, default]])
+** lag(expr [, offset [, default]])
+** first_value(expr)
+** last_value(expr)
+** nth_value(expr, N)
+**
+** These are the same built-in window functions supported by Postgres.
+** Although the behaviour of aggregate window functions (functions that
+** can be used as either aggregates or window funtions) allows them to
+** be implemented using an API, built-in window functions are much more
+** esoteric. Additionally, some window functions (e.g. nth_value())
+** may only be implemented by caching the entire partition in memory.
+** As such, some built-in window functions use the same API as aggregate
+** window functions and some are implemented directly using VDBE
+** instructions. Additionally, for those functions that use the API, the
+** window frame is sometimes modified before the SELECT statement is
+** rewritten. For example, regardless of the specified window frame, the
+** row_number() function always uses:
+**
+** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+**
+** See sqlite3WindowUpdate() for details.
+**
+** As well as some of the built-in window functions, aggregate window
+** functions min() and max() are implemented using VDBE instructions if
+** the start of the window frame is declared as anything other than
+** UNBOUNDED PRECEDING.
+*/
+
+/*
+** Implementation of built-in window function row_number(). Assumes that the
+** window frame has been coerced to:
+**
+** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+*/
+static void row_numberStepFunc(
+ sqlite3_context *pCtx,
+ int nArg,
+ sqlite3_value **apArg
+){
+ i64 *p = (i64*)sqlite3_aggregate_context(pCtx, sizeof(*p));
+ if( p ) (*p)++;
+ UNUSED_PARAMETER(nArg);
+ UNUSED_PARAMETER(apArg);
+}
+static void row_numberValueFunc(sqlite3_context *pCtx){
+ i64 *p = (i64*)sqlite3_aggregate_context(pCtx, sizeof(*p));
+ sqlite3_result_int64(pCtx, (p ? *p : 0));
+}
+
+/*
+** Context object type used by rank(), dense_rank(), percent_rank() and
+** cume_dist().
+*/
+struct CallCount {
+ i64 nValue;
+ i64 nStep;
+ i64 nTotal;
+};
+
+/*
+** Implementation of built-in window function dense_rank(). Assumes that
+** the window frame has been set to:
+**
+** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+*/
+static void dense_rankStepFunc(
+ sqlite3_context *pCtx,
+ int nArg,
+ sqlite3_value **apArg
+){
+ struct CallCount *p;
+ p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
+ if( p ) p->nStep = 1;
+ UNUSED_PARAMETER(nArg);
+ UNUSED_PARAMETER(apArg);
+}
+static void dense_rankValueFunc(sqlite3_context *pCtx){
+ struct CallCount *p;
+ p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
+ if( p ){
+ if( p->nStep ){
+ p->nValue++;
+ p->nStep = 0;
+ }
+ sqlite3_result_int64(pCtx, p->nValue);
+ }
+}
+
+/*
+** Implementation of built-in window function rank(). Assumes that
+** the window frame has been set to:
+**
+** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+*/
+static void rankStepFunc(
+ sqlite3_context *pCtx,
+ int nArg,
+ sqlite3_value **apArg
+){
+ struct CallCount *p;
+ p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
+ if( p ){
+ p->nStep++;
+ if( p->nValue==0 ){
+ p->nValue = p->nStep;
+ }
+ }
+ UNUSED_PARAMETER(nArg);
+ UNUSED_PARAMETER(apArg);
+}
+static void rankValueFunc(sqlite3_context *pCtx){
+ struct CallCount *p;
+ p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
+ if( p ){
+ sqlite3_result_int64(pCtx, p->nValue);
+ p->nValue = 0;
+ }
+}
+
+/*
+** Implementation of built-in window function percent_rank(). Assumes that
+** the window frame has been set to:
+**
+** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+*/
+static void percent_rankStepFunc(
+ sqlite3_context *pCtx,
+ int nArg,
+ sqlite3_value **apArg
+){
+ struct CallCount *p;
+ UNUSED_PARAMETER(nArg); assert( nArg==1 );
+
+ p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
+ if( p ){
+ if( p->nTotal==0 ){
+ p->nTotal = sqlite3_value_int64(apArg[0]);
+ }
+ p->nStep++;
+ if( p->nValue==0 ){
+ p->nValue = p->nStep;
+ }
+ }
+}
+static void percent_rankValueFunc(sqlite3_context *pCtx){
+ struct CallCount *p;
+ p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
+ if( p ){
+ if( p->nTotal>1 ){
+ double r = (double)(p->nValue-1) / (double)(p->nTotal-1);
+ sqlite3_result_double(pCtx, r);
+ }else{
+ sqlite3_result_double(pCtx, 0.0);
+ }
+ p->nValue = 0;
+ }
+}
+
+/*
+** Implementation of built-in window function cume_dist(). Assumes that
+** the window frame has been set to:
+**
+** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+*/
+static void cume_distStepFunc(
+ sqlite3_context *pCtx,
+ int nArg,
+ sqlite3_value **apArg
+){
+ struct CallCount *p;
+ assert( nArg==1 ); UNUSED_PARAMETER(nArg);
+
+ p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
+ if( p ){
+ if( p->nTotal==0 ){
+ p->nTotal = sqlite3_value_int64(apArg[0]);
+ }
+ p->nStep++;
+ }
+}
+static void cume_distValueFunc(sqlite3_context *pCtx){
+ struct CallCount *p;
+ p = (struct CallCount*)sqlite3_aggregate_context(pCtx, sizeof(*p));
+ if( p && p->nTotal ){
+ double r = (double)(p->nStep) / (double)(p->nTotal);
+ sqlite3_result_double(pCtx, r);
+ }
+}
+
+/*
+** Context object for ntile() window function.
+*/
+struct NtileCtx {
+ i64 nTotal; /* Total rows in partition */
+ i64 nParam; /* Parameter passed to ntile(N) */
+ i64 iRow; /* Current row */
+};
+
+/*
+** Implementation of ntile(). This assumes that the window frame has
+** been coerced to:
+**
+** ROWS UNBOUNDED PRECEDING AND CURRENT ROW
+*/
+static void ntileStepFunc(
+ sqlite3_context *pCtx,
+ int nArg,
+ sqlite3_value **apArg
+){
+ struct NtileCtx *p;
+ assert( nArg==2 ); UNUSED_PARAMETER(nArg);
+ p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p));
+ if( p ){
+ if( p->nTotal==0 ){
+ p->nParam = sqlite3_value_int64(apArg[0]);
+ p->nTotal = sqlite3_value_int64(apArg[1]);
+ if( p->nParam<=0 ){
+ sqlite3_result_error(
+ pCtx, "argument of ntile must be a positive integer", -1
+ );
+ }
+ }
+ p->iRow++;
+ }
+}
+static void ntileValueFunc(sqlite3_context *pCtx){
+ struct NtileCtx *p;
+ p = (struct NtileCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p));
+ if( p && p->nParam>0 ){
+ int nSize = (p->nTotal / p->nParam);
+ if( nSize==0 ){
+ sqlite3_result_int64(pCtx, p->iRow);
+ }else{
+ i64 nLarge = p->nTotal - p->nParam*nSize;
+ i64 iSmall = nLarge*(nSize+1);
+ i64 iRow = p->iRow-1;
+
+ assert( (nLarge*(nSize+1) + (p->nParam-nLarge)*nSize)==p->nTotal );
+
+ if( iRow<iSmall ){
+ sqlite3_result_int64(pCtx, 1 + iRow/(nSize+1));
+ }else{
+ sqlite3_result_int64(pCtx, 1 + nLarge + (iRow-iSmall)/nSize);
+ }
+ }
+ }
+}
+
+/*
+** Context object for last_value() window function.
+*/
+struct LastValueCtx {
+ sqlite3_value *pVal;
+ int nVal;
+};
+
+/*
+** Implementation of last_value().
+*/
+static void last_valueStepFunc(
+ sqlite3_context *pCtx,
+ int nArg,
+ sqlite3_value **apArg
+){
+ struct LastValueCtx *p;
+ UNUSED_PARAMETER(nArg);
+ p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p));
+ if( p ){
+ sqlite3_value_free(p->pVal);
+ p->pVal = sqlite3_value_dup(apArg[0]);
+ if( p->pVal==0 ){
+ sqlite3_result_error_nomem(pCtx);
+ }else{
+ p->nVal++;
+ }
+ }
+}
+static void last_valueInvFunc(
+ sqlite3_context *pCtx,
+ int nArg,
+ sqlite3_value **apArg
+){
+ struct LastValueCtx *p;
+ UNUSED_PARAMETER(nArg);
+ UNUSED_PARAMETER(apArg);
+ p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p));
+ if( ALWAYS(p) ){
+ p->nVal--;
+ if( p->nVal==0 ){
+ sqlite3_value_free(p->pVal);
+ p->pVal = 0;
+ }
+ }
+}
+static void last_valueValueFunc(sqlite3_context *pCtx){
+ struct LastValueCtx *p;
+ p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p));
+ if( p && p->pVal ){
+ sqlite3_result_value(pCtx, p->pVal);
+ }
+}
+static void last_valueFinalizeFunc(sqlite3_context *pCtx){
+ struct LastValueCtx *p;
+ p = (struct LastValueCtx*)sqlite3_aggregate_context(pCtx, sizeof(*p));
+ if( p && p->pVal ){
+ sqlite3_result_value(pCtx, p->pVal);
+ sqlite3_value_free(p->pVal);
+ p->pVal = 0;
+ }
+}
+
+/*
+** Static names for the built-in window function names. These static
+** names are used, rather than string literals, so that FuncDef objects
+** can be associated with a particular window function by direct
+** comparison of the zName pointer. Example:
+**
+** if( pFuncDef->zName==row_valueName ){ ... }
+*/
+static const char row_numberName[] = "row_number";
+static const char dense_rankName[] = "dense_rank";
+static const char rankName[] = "rank";
+static const char percent_rankName[] = "percent_rank";
+static const char cume_distName[] = "cume_dist";
+static const char ntileName[] = "ntile";
+static const char last_valueName[] = "last_value";
+static const char nth_valueName[] = "nth_value";
+static const char first_valueName[] = "first_value";
+static const char leadName[] = "lead";
+static const char lagName[] = "lag";
+
+/*
+** No-op implementations of xStep() and xFinalize(). Used as place-holders
+** for built-in window functions that never call those interfaces.
+**
+** The noopValueFunc() is called but is expected to do nothing. The
+** noopStepFunc() is never called, and so it is marked with NO_TEST to
+** let the test coverage routine know not to expect this function to be
+** invoked.
+*/
+static void noopStepFunc( /*NO_TEST*/
+ sqlite3_context *p, /*NO_TEST*/
+ int n, /*NO_TEST*/
+ sqlite3_value **a /*NO_TEST*/
+){ /*NO_TEST*/
+ UNUSED_PARAMETER(p); /*NO_TEST*/
+ UNUSED_PARAMETER(n); /*NO_TEST*/
+ UNUSED_PARAMETER(a); /*NO_TEST*/
+ assert(0); /*NO_TEST*/
+} /*NO_TEST*/
+static void noopValueFunc(sqlite3_context *p){ UNUSED_PARAMETER(p); /*no-op*/ }
+
+/* Window functions that use all window interfaces: xStep, xFinal,
+** xValue, and xInverse */
+#define WINDOWFUNCALL(name,nArg,extra) { \
+ nArg, (SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \
+ name ## StepFunc, name ## FinalizeFunc, name ## ValueFunc, \
+ name ## InvFunc, name ## Name, {0} \
+}
+
+/* Window functions that are implemented using bytecode and thus have
+** no-op routines for their methods */
+#define WINDOWFUNCNOOP(name,nArg,extra) { \
+ nArg, (SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \
+ noopStepFunc, noopValueFunc, noopValueFunc, \
+ noopStepFunc, name ## Name, {0} \
+}
+
+/* Window functions that use all window interfaces: xStep, the
+** same routine for xFinalize and xValue and which never call
+** xInverse. */
+#define WINDOWFUNCX(name,nArg,extra) { \
+ nArg, (SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \
+ name ## StepFunc, name ## ValueFunc, name ## ValueFunc, \
+ noopStepFunc, name ## Name, {0} \
+}
+
+
+/*
+** Register those built-in window functions that are not also aggregates.
+*/
+SQLITE_PRIVATE void sqlite3WindowFunctions(void){
+ static FuncDef aWindowFuncs[] = {
+ WINDOWFUNCX(row_number, 0, 0),
+ WINDOWFUNCX(dense_rank, 0, 0),
+ WINDOWFUNCX(rank, 0, 0),
+ WINDOWFUNCX(percent_rank, 0, SQLITE_FUNC_WINDOW_SIZE),
+ WINDOWFUNCX(cume_dist, 0, SQLITE_FUNC_WINDOW_SIZE),
+ WINDOWFUNCX(ntile, 1, SQLITE_FUNC_WINDOW_SIZE),
+ WINDOWFUNCALL(last_value, 1, 0),
+ WINDOWFUNCNOOP(nth_value, 2, 0),
+ WINDOWFUNCNOOP(first_value, 1, 0),
+ WINDOWFUNCNOOP(lead, 1, 0),
+ WINDOWFUNCNOOP(lead, 2, 0),
+ WINDOWFUNCNOOP(lead, 3, 0),
+ WINDOWFUNCNOOP(lag, 1, 0),
+ WINDOWFUNCNOOP(lag, 2, 0),
+ WINDOWFUNCNOOP(lag, 3, 0),
+ };
+ sqlite3InsertBuiltinFuncs(aWindowFuncs, ArraySize(aWindowFuncs));
+}
+
+/*
+** This function is called immediately after resolving the function name
+** for a window function within a SELECT statement. Argument pList is a
+** linked list of WINDOW definitions for the current SELECT statement.
+** Argument pFunc is the function definition just resolved and pWin
+** is the Window object representing the associated OVER clause. This
+** function updates the contents of pWin as follows:
+**
+** * If the OVER clause refered to a named window (as in "max(x) OVER win"),
+** search list pList for a matching WINDOW definition, and update pWin
+** accordingly. If no such WINDOW clause can be found, leave an error
+** in pParse.
+**
+** * If the function is a built-in window function that requires the
+** window to be coerced (see "BUILT-IN WINDOW FUNCTIONS" at the top
+** of this file), pWin is updated here.
+*/
+SQLITE_PRIVATE void sqlite3WindowUpdate(
+ Parse *pParse,
+ Window *pList, /* List of named windows for this SELECT */
+ Window *pWin, /* Window frame to update */
+ FuncDef *pFunc /* Window function definition */
+){
+ if( pWin->zName && pWin->eType==0 ){
+ Window *p;
+ for(p=pList; p; p=p->pNextWin){
+ if( sqlite3StrICmp(p->zName, pWin->zName)==0 ) break;
+ }
+ if( p==0 ){
+ sqlite3ErrorMsg(pParse, "no such window: %s", pWin->zName);
+ return;
+ }
+ pWin->pPartition = sqlite3ExprListDup(pParse->db, p->pPartition, 0);
+ pWin->pOrderBy = sqlite3ExprListDup(pParse->db, p->pOrderBy, 0);
+ pWin->pStart = sqlite3ExprDup(pParse->db, p->pStart, 0);
+ pWin->pEnd = sqlite3ExprDup(pParse->db, p->pEnd, 0);
+ pWin->eStart = p->eStart;
+ pWin->eEnd = p->eEnd;
+ pWin->eType = p->eType;
+ }
+ if( pFunc->funcFlags & SQLITE_FUNC_WINDOW ){
+ sqlite3 *db = pParse->db;
+ if( pWin->pFilter ){
+ sqlite3ErrorMsg(pParse,
+ "FILTER clause may only be used with aggregate window functions"
+ );
+ }else
+ if( pFunc->zName==row_numberName || pFunc->zName==ntileName ){
+ sqlite3ExprDelete(db, pWin->pStart);
+ sqlite3ExprDelete(db, pWin->pEnd);
+ pWin->pStart = pWin->pEnd = 0;
+ pWin->eType = TK_ROWS;
+ pWin->eStart = TK_UNBOUNDED;
+ pWin->eEnd = TK_CURRENT;
+ }else
+
+ if( pFunc->zName==dense_rankName || pFunc->zName==rankName
+ || pFunc->zName==percent_rankName || pFunc->zName==cume_distName
+ ){
+ sqlite3ExprDelete(db, pWin->pStart);
+ sqlite3ExprDelete(db, pWin->pEnd);
+ pWin->pStart = pWin->pEnd = 0;
+ pWin->eType = TK_RANGE;
+ pWin->eStart = TK_UNBOUNDED;
+ pWin->eEnd = TK_CURRENT;
+ }
+ }
+ pWin->pFunc = pFunc;
+}
+
+/*
+** Context object passed through sqlite3WalkExprList() to
+** selectWindowRewriteExprCb() by selectWindowRewriteEList().
+*/
+typedef struct WindowRewrite WindowRewrite;
+struct WindowRewrite {
+ Window *pWin;
+ SrcList *pSrc;
+ ExprList *pSub;
+ Select *pSubSelect; /* Current sub-select, if any */
+};
+
+/*
+** Callback function used by selectWindowRewriteEList(). If necessary,
+** this function appends to the output expression-list and updates
+** expression (*ppExpr) in place.
+*/
+static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){
+ struct WindowRewrite *p = pWalker->u.pRewrite;
+ Parse *pParse = pWalker->pParse;
+
+ /* If this function is being called from within a scalar sub-select
+ ** that used by the SELECT statement being processed, only process
+ ** TK_COLUMN expressions that refer to it (the outer SELECT). Do
+ ** not process aggregates or window functions at all, as they belong
+ ** to the scalar sub-select. */
+ if( p->pSubSelect ){
+ if( pExpr->op!=TK_COLUMN ){
+ return WRC_Continue;
+ }else{
+ int nSrc = p->pSrc->nSrc;
+ int i;
+ for(i=0; i<nSrc; i++){
+ if( pExpr->iTable==p->pSrc->a[i].iCursor ) break;
+ }
+ if( i==nSrc ) return WRC_Continue;
+ }
+ }
+
+ switch( pExpr->op ){
+
+ case TK_FUNCTION:
+ if( pExpr->pWin==0 ){
+ break;
+ }else{
+ Window *pWin;
+ for(pWin=p->pWin; pWin; pWin=pWin->pNextWin){
+ if( pExpr->pWin==pWin ){
+ assert( pWin->pOwner==pExpr );
+ return WRC_Prune;
+ }
+ }
+ }
+ /* Fall through. */
+
+ case TK_AGG_FUNCTION:
+ case TK_COLUMN: {
+ Expr *pDup = sqlite3ExprDup(pParse->db, pExpr, 0);
+ p->pSub = sqlite3ExprListAppend(pParse, p->pSub, pDup);
+ if( p->pSub ){
+ assert( ExprHasProperty(pExpr, EP_Static)==0 );
+ ExprSetProperty(pExpr, EP_Static);
+ sqlite3ExprDelete(pParse->db, pExpr);
+ ExprClearProperty(pExpr, EP_Static);
+ memset(pExpr, 0, sizeof(Expr));
+
+ pExpr->op = TK_COLUMN;
+ pExpr->iColumn = p->pSub->nExpr-1;
+ pExpr->iTable = p->pWin->iEphCsr;
+ }
+
+ break;
+ }
+
+ default: /* no-op */
+ break;
+ }
+
+ return WRC_Continue;
+}
+static int selectWindowRewriteSelectCb(Walker *pWalker, Select *pSelect){
+ struct WindowRewrite *p = pWalker->u.pRewrite;
+ Select *pSave = p->pSubSelect;
+ if( pSave==pSelect ){
+ return WRC_Continue;
+ }else{
+ p->pSubSelect = pSelect;
+ sqlite3WalkSelect(pWalker, pSelect);
+ p->pSubSelect = pSave;
+ }
+ return WRC_Prune;
+}
+
+
+/*
+** Iterate through each expression in expression-list pEList. For each:
+**
+** * TK_COLUMN,
+** * aggregate function, or
+** * window function with a Window object that is not a member of the
+** Window list passed as the second argument (pWin).
+**
+** Append the node to output expression-list (*ppSub). And replace it
+** with a TK_COLUMN that reads the (N-1)th element of table
+** pWin->iEphCsr, where N is the number of elements in (*ppSub) after
+** appending the new one.
+*/
+static void selectWindowRewriteEList(
+ Parse *pParse,
+ Window *pWin,
+ SrcList *pSrc,
+ ExprList *pEList, /* Rewrite expressions in this list */
+ ExprList **ppSub /* IN/OUT: Sub-select expression-list */
+){
+ Walker sWalker;
+ WindowRewrite sRewrite;
+
+ memset(&sWalker, 0, sizeof(Walker));
+ memset(&sRewrite, 0, sizeof(WindowRewrite));
+
+ sRewrite.pSub = *ppSub;
+ sRewrite.pWin = pWin;
+ sRewrite.pSrc = pSrc;
+
+ sWalker.pParse = pParse;
+ sWalker.xExprCallback = selectWindowRewriteExprCb;
+ sWalker.xSelectCallback = selectWindowRewriteSelectCb;
+ sWalker.u.pRewrite = &sRewrite;
+
+ (void)sqlite3WalkExprList(&sWalker, pEList);
+
+ *ppSub = sRewrite.pSub;
+}
+
+/*
+** Append a copy of each expression in expression-list pAppend to
+** expression list pList. Return a pointer to the result list.
+*/
+static ExprList *exprListAppendList(
+ Parse *pParse, /* Parsing context */
+ ExprList *pList, /* List to which to append. Might be NULL */
+ ExprList *pAppend /* List of values to append. Might be NULL */
+){
+ if( pAppend ){
+ int i;
+ int nInit = pList ? pList->nExpr : 0;
+ for(i=0; i<pAppend->nExpr; i++){
+ Expr *pDup = sqlite3ExprDup(pParse->db, pAppend->a[i].pExpr, 0);
+ pList = sqlite3ExprListAppend(pParse, pList, pDup);
+ if( pList ) pList->a[nInit+i].sortOrder = pAppend->a[i].sortOrder;
+ }
+ }
+ return pList;
+}
+
+/*
+** If the SELECT statement passed as the second argument does not invoke
+** any SQL window functions, this function is a no-op. Otherwise, it
+** rewrites the SELECT statement so that window function xStep functions
+** are invoked in the correct order as described under "SELECT REWRITING"
+** at the top of this file.
+*/
+SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){
+ int rc = SQLITE_OK;
+ if( p->pWin ){
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ sqlite3 *db = pParse->db;
+ Select *pSub = 0; /* The subquery */
+ SrcList *pSrc = p->pSrc;
+ Expr *pWhere = p->pWhere;
+ ExprList *pGroupBy = p->pGroupBy;
+ Expr *pHaving = p->pHaving;
+ ExprList *pSort = 0;
+
+ ExprList *pSublist = 0; /* Expression list for sub-query */
+ Window *pMWin = p->pWin; /* Master window object */
+ Window *pWin; /* Window object iterator */
+
+ p->pSrc = 0;
+ p->pWhere = 0;
+ p->pGroupBy = 0;
+ p->pHaving = 0;
+
+ /* Create the ORDER BY clause for the sub-select. This is the concatenation
+ ** of the window PARTITION and ORDER BY clauses. Then, if this makes it
+ ** redundant, remove the ORDER BY from the parent SELECT. */
+ pSort = sqlite3ExprListDup(db, pMWin->pPartition, 0);
+ pSort = exprListAppendList(pParse, pSort, pMWin->pOrderBy);
+ if( pSort && p->pOrderBy ){
+ if( sqlite3ExprListCompare(pSort, p->pOrderBy, -1)==0 ){
+ sqlite3ExprListDelete(db, p->pOrderBy);
+ p->pOrderBy = 0;
+ }
+ }
+
+ /* Assign a cursor number for the ephemeral table used to buffer rows.
+ ** The OpenEphemeral instruction is coded later, after it is known how
+ ** many columns the table will have. */
+ pMWin->iEphCsr = pParse->nTab++;
+
+ selectWindowRewriteEList(pParse, pMWin, pSrc, p->pEList, &pSublist);
+ selectWindowRewriteEList(pParse, pMWin, pSrc, p->pOrderBy, &pSublist);
+ pMWin->nBufferCol = (pSublist ? pSublist->nExpr : 0);
+
+ /* Append the PARTITION BY and ORDER BY expressions to the to the
+ ** sub-select expression list. They are required to figure out where
+ ** boundaries for partitions and sets of peer rows lie. */
+ pSublist = exprListAppendList(pParse, pSublist, pMWin->pPartition);
+ pSublist = exprListAppendList(pParse, pSublist, pMWin->pOrderBy);
+
+ /* Append the arguments passed to each window function to the
+ ** sub-select expression list. Also allocate two registers for each
+ ** window function - one for the accumulator, another for interim
+ ** results. */
+ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
+ pWin->iArgCol = (pSublist ? pSublist->nExpr : 0);
+ pSublist = exprListAppendList(pParse, pSublist, pWin->pOwner->x.pList);
+ if( pWin->pFilter ){
+ Expr *pFilter = sqlite3ExprDup(db, pWin->pFilter, 0);
+ pSublist = sqlite3ExprListAppend(pParse, pSublist, pFilter);
+ }
+ pWin->regAccum = ++pParse->nMem;
+ pWin->regResult = ++pParse->nMem;
+ sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum);
+ }
+
+ /* If there is no ORDER BY or PARTITION BY clause, and the window
+ ** function accepts zero arguments, and there are no other columns
+ ** selected (e.g. "SELECT row_number() OVER () FROM t1"), it is possible
+ ** that pSublist is still NULL here. Add a constant expression here to
+ ** keep everything legal in this case.
+ */
+ if( pSublist==0 ){
+ pSublist = sqlite3ExprListAppend(pParse, 0,
+ sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0)
+ );
+ }
+
+ pSub = sqlite3SelectNew(
+ pParse, pSublist, pSrc, pWhere, pGroupBy, pHaving, pSort, 0, 0
+ );
+ p->pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
+ assert( p->pSrc || db->mallocFailed );
+ if( p->pSrc ){
+ p->pSrc->a[0].pSelect = pSub;
+ sqlite3SrcListAssignCursors(pParse, p->pSrc);
+ if( sqlite3ExpandSubquery(pParse, &p->pSrc->a[0]) ){
+ rc = SQLITE_NOMEM;
+ }else{
+ pSub->selFlags |= SF_Expanded;
+ p->selFlags &= ~SF_Aggregate;
+ sqlite3SelectPrep(pParse, pSub, 0);
+ }
+
+ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pMWin->iEphCsr, pSublist->nExpr);
+ }else{
+ sqlite3SelectDelete(db, pSub);
+ }
+ if( db->mallocFailed ) rc = SQLITE_NOMEM;
+ }
+
+ return rc;
+}
+
+/*
+** Free the Window object passed as the second argument.
+*/
+SQLITE_PRIVATE void sqlite3WindowDelete(sqlite3 *db, Window *p){
+ if( p ){
+ sqlite3ExprDelete(db, p->pFilter);
+ sqlite3ExprListDelete(db, p->pPartition);
+ sqlite3ExprListDelete(db, p->pOrderBy);
+ sqlite3ExprDelete(db, p->pEnd);
+ sqlite3ExprDelete(db, p->pStart);
+ sqlite3DbFree(db, p->zName);
+ sqlite3DbFree(db, p);
+ }
+}
+
+/*
+** Free the linked list of Window objects starting at the second argument.
+*/
+SQLITE_PRIVATE void sqlite3WindowListDelete(sqlite3 *db, Window *p){
+ while( p ){
+ Window *pNext = p->pNextWin;
+ sqlite3WindowDelete(db, p);
+ p = pNext;
+ }
+}
+
+/*
+** The argument expression is an PRECEDING or FOLLOWING offset. The
+** value should be a non-negative integer. If the value is not a
+** constant, change it to NULL. The fact that it is then a non-negative
+** integer will be caught later. But it is important not to leave
+** variable values in the expression tree.
+*/
+static Expr *sqlite3WindowOffsetExpr(Parse *pParse, Expr *pExpr){
+ if( 0==sqlite3ExprIsConstant(pExpr) ){
+ sqlite3ExprDelete(pParse->db, pExpr);
+ pExpr = sqlite3ExprAlloc(pParse->db, TK_NULL, 0, 0);
+ }
+ return pExpr;
+}
+
+/*
+** Allocate and return a new Window object describing a Window Definition.
+*/
+SQLITE_PRIVATE Window *sqlite3WindowAlloc(
+ Parse *pParse, /* Parsing context */
+ int eType, /* Frame type. TK_RANGE or TK_ROWS */
+ int eStart, /* Start type: CURRENT, PRECEDING, FOLLOWING, UNBOUNDED */
+ Expr *pStart, /* Start window size if TK_PRECEDING or FOLLOWING */
+ int eEnd, /* End type: CURRENT, FOLLOWING, TK_UNBOUNDED, PRECEDING */
+ Expr *pEnd /* End window size if TK_FOLLOWING or PRECEDING */
+){
+ Window *pWin = 0;
+
+ /* Parser assures the following: */
+ assert( eType==TK_RANGE || eType==TK_ROWS );
+ assert( eStart==TK_CURRENT || eStart==TK_PRECEDING
+ || eStart==TK_UNBOUNDED || eStart==TK_FOLLOWING );
+ assert( eEnd==TK_CURRENT || eEnd==TK_FOLLOWING
+ || eEnd==TK_UNBOUNDED || eEnd==TK_PRECEDING );
+ assert( (eStart==TK_PRECEDING || eStart==TK_FOLLOWING)==(pStart!=0) );
+ assert( (eEnd==TK_FOLLOWING || eEnd==TK_PRECEDING)==(pEnd!=0) );
+
+
+ /* If a frame is declared "RANGE" (not "ROWS"), then it may not use
+ ** either "<expr> PRECEDING" or "<expr> FOLLOWING".
+ */
+ if( eType==TK_RANGE && (pStart!=0 || pEnd!=0) ){
+ sqlite3ErrorMsg(pParse, "RANGE must use only UNBOUNDED or CURRENT ROW");
+ goto windowAllocErr;
+ }
+
+ /* Additionally, the
+ ** starting boundary type may not occur earlier in the following list than
+ ** the ending boundary type:
+ **
+ ** UNBOUNDED PRECEDING
+ ** <expr> PRECEDING
+ ** CURRENT ROW
+ ** <expr> FOLLOWING
+ ** UNBOUNDED FOLLOWING
+ **
+ ** The parser ensures that "UNBOUNDED PRECEDING" cannot be used as an ending
+ ** boundary, and than "UNBOUNDED FOLLOWING" cannot be used as a starting
+ ** frame boundary.
+ */
+ if( (eStart==TK_CURRENT && eEnd==TK_PRECEDING)
+ || (eStart==TK_FOLLOWING && (eEnd==TK_PRECEDING || eEnd==TK_CURRENT))
+ ){
+ sqlite3ErrorMsg(pParse, "unsupported frame delimiter for ROWS");
+ goto windowAllocErr;
+ }
+
+ pWin = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
+ if( pWin==0 ) goto windowAllocErr;
+ pWin->eType = eType;
+ pWin->eStart = eStart;
+ pWin->eEnd = eEnd;
+ pWin->pEnd = sqlite3WindowOffsetExpr(pParse, pEnd);
+ pWin->pStart = sqlite3WindowOffsetExpr(pParse, pStart);
+ return pWin;
+
+windowAllocErr:
+ sqlite3ExprDelete(pParse->db, pEnd);
+ sqlite3ExprDelete(pParse->db, pStart);
+ return 0;
+}
+
+/*
+** Attach window object pWin to expression p.
+*/
+SQLITE_PRIVATE void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){
+ if( p ){
+ /* This routine is only called for the parser. If pWin was not
+ ** allocated due to an OOM, then the parser would fail before ever
+ ** invoking this routine */
+ if( ALWAYS(pWin) ){
+ p->pWin = pWin;
+ pWin->pOwner = p;
+ if( p->flags & EP_Distinct ){
+ sqlite3ErrorMsg(pParse,
+ "DISTINCT is not supported for window functions");
+ }
+ }
+ }else{
+ sqlite3WindowDelete(pParse->db, pWin);
+ }
+}
+
+/*
+** Return 0 if the two window objects are identical, or non-zero otherwise.
+** Identical window objects can be processed in a single scan.
+*/
+SQLITE_PRIVATE int sqlite3WindowCompare(Parse *pParse, Window *p1, Window *p2){
+ if( p1->eType!=p2->eType ) return 1;
+ if( p1->eStart!=p2->eStart ) return 1;
+ if( p1->eEnd!=p2->eEnd ) return 1;
+ if( sqlite3ExprCompare(pParse, p1->pStart, p2->pStart, -1) ) return 1;
+ if( sqlite3ExprCompare(pParse, p1->pEnd, p2->pEnd, -1) ) return 1;
+ if( sqlite3ExprListCompare(p1->pPartition, p2->pPartition, -1) ) return 1;
+ if( sqlite3ExprListCompare(p1->pOrderBy, p2->pOrderBy, -1) ) return 1;
+ return 0;
+}
+
+
+/*
+** This is called by code in select.c before it calls sqlite3WhereBegin()
+** to begin iterating through the sub-query results. It is used to allocate
+** and initialize registers and cursors used by sqlite3WindowCodeStep().
+*/
+SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse *pParse, Window *pMWin){
+ Window *pWin;
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ int nPart = (pMWin->pPartition ? pMWin->pPartition->nExpr : 0);
+ nPart += (pMWin->pOrderBy ? pMWin->pOrderBy->nExpr : 0);
+ if( nPart ){
+ pMWin->regPart = pParse->nMem+1;
+ pParse->nMem += nPart;
+ sqlite3VdbeAddOp3(v, OP_Null, 0, pMWin->regPart, pMWin->regPart+nPart-1);
+ }
+
+ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
+ FuncDef *p = pWin->pFunc;
+ if( (p->funcFlags & SQLITE_FUNC_MINMAX) && pWin->eStart!=TK_UNBOUNDED ){
+ /* The inline versions of min() and max() require a single ephemeral
+ ** table and 3 registers. The registers are used as follows:
+ **
+ ** regApp+0: slot to copy min()/max() argument to for MakeRecord
+ ** regApp+1: integer value used to ensure keys are unique
+ ** regApp+2: output of MakeRecord
+ */
+ ExprList *pList = pWin->pOwner->x.pList;
+ KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pList, 0, 0);
+ pWin->csrApp = pParse->nTab++;
+ pWin->regApp = pParse->nMem+1;
+ pParse->nMem += 3;
+ if( pKeyInfo && pWin->pFunc->zName[1]=='i' ){
+ assert( pKeyInfo->aSortOrder[0]==0 );
+ pKeyInfo->aSortOrder[0] = 1;
+ }
+ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pWin->csrApp, 2);
+ sqlite3VdbeAppendP4(v, pKeyInfo, P4_KEYINFO);
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1);
+ }
+ else if( p->zName==nth_valueName || p->zName==first_valueName ){
+ /* Allocate two registers at pWin->regApp. These will be used to
+ ** store the start and end index of the current frame. */
+ assert( pMWin->iEphCsr );
+ pWin->regApp = pParse->nMem+1;
+ pWin->csrApp = pParse->nTab++;
+ pParse->nMem += 2;
+ sqlite3VdbeAddOp2(v, OP_OpenDup, pWin->csrApp, pMWin->iEphCsr);
+ }
+ else if( p->zName==leadName || p->zName==lagName ){
+ assert( pMWin->iEphCsr );
+ pWin->csrApp = pParse->nTab++;
+ sqlite3VdbeAddOp2(v, OP_OpenDup, pWin->csrApp, pMWin->iEphCsr);
+ }
+ }
+}
+
+/*
+** A "PRECEDING <expr>" (eCond==0) or "FOLLOWING <expr>" (eCond==1) or the
+** value of the second argument to nth_value() (eCond==2) has just been
+** evaluated and the result left in register reg. This function generates VM
+** code to check that the value is a non-negative integer and throws an
+** exception if it is not.
+*/
+static void windowCheckIntValue(Parse *pParse, int reg, int eCond){
+ static const char *azErr[] = {
+ "frame starting offset must be a non-negative integer",
+ "frame ending offset must be a non-negative integer",
+ "second argument to nth_value must be a positive integer"
+ };
+ static int aOp[] = { OP_Ge, OP_Ge, OP_Gt };
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ int regZero = sqlite3GetTempReg(pParse);
+ assert( eCond==0 || eCond==1 || eCond==2 );
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, regZero);
+ sqlite3VdbeAddOp2(v, OP_MustBeInt, reg, sqlite3VdbeCurrentAddr(v)+2);
+ VdbeCoverageIf(v, eCond==0);
+ VdbeCoverageIf(v, eCond==1);
+ VdbeCoverageIf(v, eCond==2);
+ sqlite3VdbeAddOp3(v, aOp[eCond], regZero, sqlite3VdbeCurrentAddr(v)+2, reg);
+ VdbeCoverageNeverNullIf(v, eCond==0);
+ VdbeCoverageNeverNullIf(v, eCond==1);
+ VdbeCoverageNeverNullIf(v, eCond==2);
+ sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_ERROR, OE_Abort);
+ sqlite3VdbeAppendP4(v, (void*)azErr[eCond], P4_STATIC);
+ sqlite3ReleaseTempReg(pParse, regZero);
+}
+
+/*
+** Return the number of arguments passed to the window-function associated
+** with the object passed as the only argument to this function.
+*/
+static int windowArgCount(Window *pWin){
+ ExprList *pList = pWin->pOwner->x.pList;
+ return (pList ? pList->nExpr : 0);
+}
+
+/*
+** Generate VM code to invoke either xStep() (if bInverse is 0) or
+** xInverse (if bInverse is non-zero) for each window function in the
+** linked list starting at pMWin. Or, for built-in window functions
+** that do not use the standard function API, generate the required
+** inline VM code.
+**
+** If argument csr is greater than or equal to 0, then argument reg is
+** the first register in an array of registers guaranteed to be large
+** enough to hold the array of arguments for each function. In this case
+** the arguments are extracted from the current row of csr into the
+** array of registers before invoking OP_AggStep or OP_AggInverse
+**
+** Or, if csr is less than zero, then the array of registers at reg is
+** already populated with all columns from the current row of the sub-query.
+**
+** If argument regPartSize is non-zero, then it is a register containing the
+** number of rows in the current partition.
+*/
+static void windowAggStep(
+ Parse *pParse,
+ Window *pMWin, /* Linked list of window functions */
+ int csr, /* Read arguments from this cursor */
+ int bInverse, /* True to invoke xInverse instead of xStep */
+ int reg, /* Array of registers */
+ int regPartSize /* Register containing size of partition */
+){
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ Window *pWin;
+ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
+ int flags = pWin->pFunc->funcFlags;
+ int regArg;
+ int nArg = windowArgCount(pWin);
+
+ if( csr>=0 ){
+ int i;
+ for(i=0; i<nArg; i++){
+ sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+i, reg+i);
+ }
+ regArg = reg;
+ if( flags & SQLITE_FUNC_WINDOW_SIZE ){
+ if( nArg==0 ){
+ regArg = regPartSize;
+ }else{
+ sqlite3VdbeAddOp2(v, OP_SCopy, regPartSize, reg+nArg);
+ }
+ nArg++;
+ }
+ }else{
+ assert( !(flags & SQLITE_FUNC_WINDOW_SIZE) );
+ regArg = reg + pWin->iArgCol;
+ }
+
+ if( (pWin->pFunc->funcFlags & SQLITE_FUNC_MINMAX)
+ && pWin->eStart!=TK_UNBOUNDED
+ ){
+ int addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regArg);
+ VdbeCoverage(v);
+ if( bInverse==0 ){
+ sqlite3VdbeAddOp2(v, OP_AddImm, pWin->regApp+1, 1);
+ sqlite3VdbeAddOp2(v, OP_SCopy, regArg, pWin->regApp);
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, pWin->regApp, 2, pWin->regApp+2);
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, pWin->csrApp, pWin->regApp+2);
+ }else{
+ sqlite3VdbeAddOp4Int(v, OP_SeekGE, pWin->csrApp, 0, regArg, 1);
+ VdbeCoverageNeverTaken(v);
+ sqlite3VdbeAddOp1(v, OP_Delete, pWin->csrApp);
+ sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
+ }
+ sqlite3VdbeJumpHere(v, addrIsNull);
+ }else if( pWin->regApp ){
+ assert( pWin->pFunc->zName==nth_valueName
+ || pWin->pFunc->zName==first_valueName
+ );
+ assert( bInverse==0 || bInverse==1 );
+ sqlite3VdbeAddOp2(v, OP_AddImm, pWin->regApp+1-bInverse, 1);
+ }else if( pWin->pFunc->zName==leadName
+ || pWin->pFunc->zName==lagName
+ ){
+ /* no-op */
+ }else{
+ int addrIf = 0;
+ if( pWin->pFilter ){
+ int regTmp;
+ assert( nArg==0 || nArg==pWin->pOwner->x.pList->nExpr );
+ assert( nArg || pWin->pOwner->x.pList==0 );
+ if( csr>0 ){
+ regTmp = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp);
+ }else{
+ regTmp = regArg + nArg;
+ }
+ addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1);
+ VdbeCoverage(v);
+ if( csr>0 ){
+ sqlite3ReleaseTempReg(pParse, regTmp);
+ }
+ }
+ if( pWin->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
+ CollSeq *pColl;
+ assert( nArg>0 );
+ pColl = sqlite3ExprNNCollSeq(pParse, pWin->pOwner->x.pList->a[0].pExpr);
+ sqlite3VdbeAddOp4(v, OP_CollSeq, 0,0,0, (const char*)pColl, P4_COLLSEQ);
+ }
+ sqlite3VdbeAddOp3(v, bInverse? OP_AggInverse : OP_AggStep,
+ bInverse, regArg, pWin->regAccum);
+ sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
+ sqlite3VdbeChangeP5(v, (u8)nArg);
+ if( addrIf ) sqlite3VdbeJumpHere(v, addrIf);
+ }
+ }
+}
+
+/*
+** Generate VM code to invoke either xValue() (bFinal==0) or xFinalize()
+** (bFinal==1) for each window function in the linked list starting at
+** pMWin. Or, for built-in window-functions that do not use the standard
+** API, generate the equivalent VM code.
+*/
+static void windowAggFinal(Parse *pParse, Window *pMWin, int bFinal){
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ Window *pWin;
+
+ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
+ if( (pWin->pFunc->funcFlags & SQLITE_FUNC_MINMAX)
+ && pWin->eStart!=TK_UNBOUNDED
+ ){
+ sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult);
+ sqlite3VdbeAddOp1(v, OP_Last, pWin->csrApp);
+ VdbeCoverage(v);
+ sqlite3VdbeAddOp3(v, OP_Column, pWin->csrApp, 0, pWin->regResult);
+ sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
+ if( bFinal ){
+ sqlite3VdbeAddOp1(v, OP_ResetSorter, pWin->csrApp);
+ }
+ }else if( pWin->regApp ){
+ }else{
+ if( bFinal ){
+ sqlite3VdbeAddOp2(v, OP_AggFinal, pWin->regAccum, windowArgCount(pWin));
+ sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
+ sqlite3VdbeAddOp2(v, OP_Copy, pWin->regAccum, pWin->regResult);
+ sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum);
+ }else{
+ sqlite3VdbeAddOp3(v, OP_AggValue, pWin->regAccum, windowArgCount(pWin),
+ pWin->regResult);
+ sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
+ }
+ }
+ }
+}
+
+/*
+** This function generates VM code to invoke the sub-routine at address
+** lblFlushPart once for each partition with the entire partition cached in
+** the Window.iEphCsr temp table.
+*/
+static void windowPartitionCache(
+ Parse *pParse,
+ Select *p, /* The rewritten SELECT statement */
+ WhereInfo *pWInfo, /* WhereInfo to call WhereEnd() on */
+ int regFlushPart, /* Register to use with Gosub lblFlushPart */
+ int lblFlushPart, /* Subroutine to Gosub to */
+ int *pRegSize /* OUT: Register containing partition size */
+){
+ Window *pMWin = p->pWin;
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ int iSubCsr = p->pSrc->a[0].iCursor;
+ int nSub = p->pSrc->a[0].pTab->nCol;
+ int k;
+
+ int reg = pParse->nMem+1;
+ int regRecord = reg+nSub;
+ int regRowid = regRecord+1;
+
+ *pRegSize = regRowid;
+ pParse->nMem += nSub + 2;
+
+ /* Load the column values for the row returned by the sub-select
+ ** into an array of registers starting at reg. */
+ for(k=0; k<nSub; k++){
+ sqlite3VdbeAddOp3(v, OP_Column, iSubCsr, k, reg+k);
+ }
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, nSub, regRecord);
+
+ /* Check if this is the start of a new partition. If so, call the
+ ** flush_partition sub-routine. */
+ if( pMWin->pPartition ){
+ int addr;
+ ExprList *pPart = pMWin->pPartition;
+ int nPart = pPart->nExpr;
+ int regNewPart = reg + pMWin->nBufferCol;
+ KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pPart, 0, 0);
+
+ addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPart, pMWin->regPart,nPart);
+ sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO);
+ sqlite3VdbeAddOp3(v, OP_Jump, addr+2, addr+4, addr+2);
+ VdbeCoverageEqNe(v);
+ sqlite3VdbeAddOp3(v, OP_Copy, regNewPart, pMWin->regPart, nPart-1);
+ sqlite3VdbeAddOp2(v, OP_Gosub, regFlushPart, lblFlushPart);
+ VdbeComment((v, "call flush_partition"));
+ }
+
+ /* Buffer the current row in the ephemeral table. */
+ sqlite3VdbeAddOp2(v, OP_NewRowid, pMWin->iEphCsr, regRowid);
+ sqlite3VdbeAddOp3(v, OP_Insert, pMWin->iEphCsr, regRecord, regRowid);
+
+ /* End of the input loop */
+ sqlite3WhereEnd(pWInfo);
+
+ /* Invoke "flush_partition" to deal with the final (or only) partition */
+ sqlite3VdbeAddOp2(v, OP_Gosub, regFlushPart, lblFlushPart);
+ VdbeComment((v, "call flush_partition"));
+}
+
+/*
+** Invoke the sub-routine at regGosub (generated by code in select.c) to
+** return the current row of Window.iEphCsr. If all window functions are
+** aggregate window functions that use the standard API, a single
+** OP_Gosub instruction is all that this routine generates. Extra VM code
+** for per-row processing is only generated for the following built-in window
+** functions:
+**
+** nth_value()
+** first_value()
+** lag()
+** lead()
+*/
+static void windowReturnOneRow(
+ Parse *pParse,
+ Window *pMWin,
+ int regGosub,
+ int addrGosub
+){
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ Window *pWin;
+ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
+ FuncDef *pFunc = pWin->pFunc;
+ if( pFunc->zName==nth_valueName
+ || pFunc->zName==first_valueName
+ ){
+ int csr = pWin->csrApp;
+ int lbl = sqlite3VdbeMakeLabel(v);
+ int tmpReg = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult);
+
+ if( pFunc->zName==nth_valueName ){
+ sqlite3VdbeAddOp3(v, OP_Column, pMWin->iEphCsr, pWin->iArgCol+1,tmpReg);
+ windowCheckIntValue(pParse, tmpReg, 2);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, tmpReg);
+ }
+ sqlite3VdbeAddOp3(v, OP_Add, tmpReg, pWin->regApp, tmpReg);
+ sqlite3VdbeAddOp3(v, OP_Gt, pWin->regApp+1, lbl, tmpReg);
+ VdbeCoverageNeverNull(v);
+ sqlite3VdbeAddOp3(v, OP_SeekRowid, csr, 0, tmpReg);
+ VdbeCoverageNeverTaken(v);
+ sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol, pWin->regResult);
+ sqlite3VdbeResolveLabel(v, lbl);
+ sqlite3ReleaseTempReg(pParse, tmpReg);
+ }
+ else if( pFunc->zName==leadName || pFunc->zName==lagName ){
+ int nArg = pWin->pOwner->x.pList->nExpr;
+ int iEph = pMWin->iEphCsr;
+ int csr = pWin->csrApp;
+ int lbl = sqlite3VdbeMakeLabel(v);
+ int tmpReg = sqlite3GetTempReg(pParse);
+
+ if( nArg<3 ){
+ sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult);
+ }else{
+ sqlite3VdbeAddOp3(v, OP_Column, iEph, pWin->iArgCol+2, pWin->regResult);
+ }
+ sqlite3VdbeAddOp2(v, OP_Rowid, iEph, tmpReg);
+ if( nArg<2 ){
+ int val = (pFunc->zName==leadName ? 1 : -1);
+ sqlite3VdbeAddOp2(v, OP_AddImm, tmpReg, val);
+ }else{
+ int op = (pFunc->zName==leadName ? OP_Add : OP_Subtract);
+ int tmpReg2 = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp3(v, OP_Column, iEph, pWin->iArgCol+1, tmpReg2);
+ sqlite3VdbeAddOp3(v, op, tmpReg2, tmpReg, tmpReg);
+ sqlite3ReleaseTempReg(pParse, tmpReg2);
+ }
+
+ sqlite3VdbeAddOp3(v, OP_SeekRowid, csr, lbl, tmpReg);
+ VdbeCoverage(v);
+ sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol, pWin->regResult);
+ sqlite3VdbeResolveLabel(v, lbl);
+ sqlite3ReleaseTempReg(pParse, tmpReg);
+ }
+ }
+ sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub);
+}
+
+/*
+** Invoke the code generated by windowReturnOneRow() and, optionally, the
+** xInverse() function for each window function, for one or more rows
+** from the Window.iEphCsr temp table. This routine generates VM code
+** similar to:
+**
+** while( regCtr>0 ){
+** regCtr--;
+** windowReturnOneRow()
+** if( bInverse ){
+** AggInverse
+** }
+** Next (Window.iEphCsr)
+** }
+*/
+static void windowReturnRows(
+ Parse *pParse,
+ Window *pMWin, /* List of window functions */
+ int regCtr, /* Register containing number of rows */
+ int regGosub, /* Register for Gosub addrGosub */
+ int addrGosub, /* Address of sub-routine for ReturnOneRow */
+ int regInvArg, /* Array of registers for xInverse args */
+ int regInvSize /* Register containing size of partition */
+){
+ int addr;
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ windowAggFinal(pParse, pMWin, 0);
+ addr = sqlite3VdbeAddOp3(v, OP_IfPos, regCtr, sqlite3VdbeCurrentAddr(v)+2 ,1);
+ VdbeCoverage(v);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
+ windowReturnOneRow(pParse, pMWin, regGosub, addrGosub);
+ if( regInvArg ){
+ windowAggStep(pParse, pMWin, pMWin->iEphCsr, 1, regInvArg, regInvSize);
+ }
+ sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, addr);
+ VdbeCoverage(v);
+ sqlite3VdbeJumpHere(v, addr+1); /* The OP_Goto */
+}
+
+/*
+** Generate code to set the accumulator register for each window function
+** in the linked list passed as the second argument to NULL. And perform
+** any equivalent initialization required by any built-in window functions
+** in the list.
+*/
+static int windowInitAccum(Parse *pParse, Window *pMWin){
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ int regArg;
+ int nArg = 0;
+ Window *pWin;
+ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
+ FuncDef *pFunc = pWin->pFunc;
+ sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum);
+ nArg = MAX(nArg, windowArgCount(pWin));
+ if( pFunc->zName==nth_valueName
+ || pFunc->zName==first_valueName
+ ){
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp);
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1);
+ }
+
+ if( (pFunc->funcFlags & SQLITE_FUNC_MINMAX) && pWin->csrApp ){
+ assert( pWin->eStart!=TK_UNBOUNDED );
+ sqlite3VdbeAddOp1(v, OP_ResetSorter, pWin->csrApp);
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, pWin->regApp+1);
+ }
+ }
+ regArg = pParse->nMem+1;
+ pParse->nMem += nArg;
+ return regArg;
+}
+
+
+/*
+** This function does the work of sqlite3WindowCodeStep() for all "ROWS"
+** window frame types except for "BETWEEN UNBOUNDED PRECEDING AND CURRENT
+** ROW". Pseudo-code for each follows.
+**
+** ROWS BETWEEN <expr1> PRECEDING AND <expr2> FOLLOWING
+**
+** ...
+** if( new partition ){
+** Gosub flush_partition
+** }
+** Insert (record in eph-table)
+** sqlite3WhereEnd()
+** Gosub flush_partition
+**
+** flush_partition:
+** Once {
+** OpenDup (iEphCsr -> csrStart)
+** OpenDup (iEphCsr -> csrEnd)
+** }
+** regStart = <expr1> // PRECEDING expression
+** regEnd = <expr2> // FOLLOWING expression
+** if( regStart<0 || regEnd<0 ){ error! }
+** Rewind (csr,csrStart,csrEnd) // if EOF goto flush_partition_done
+** Next(csrEnd) // if EOF skip Aggstep
+** Aggstep (csrEnd)
+** if( (regEnd--)<=0 ){
+** AggFinal (xValue)
+** Gosub addrGosub
+** Next(csr) // if EOF goto flush_partition_done
+** if( (regStart--)<=0 ){
+** AggInverse (csrStart)
+** Next(csrStart)
+** }
+** }
+** flush_partition_done:
+** ResetSorter (csr)
+** Return
+**
+** ROWS BETWEEN <expr> PRECEDING AND CURRENT ROW
+** ROWS BETWEEN CURRENT ROW AND <expr> FOLLOWING
+** ROWS BETWEEN UNBOUNDED PRECEDING AND <expr> FOLLOWING
+**
+** These are similar to the above. For "CURRENT ROW", intialize the
+** register to 0. For "UNBOUNDED PRECEDING" to infinity.
+**
+** ROWS BETWEEN <expr> PRECEDING AND UNBOUNDED FOLLOWING
+** ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
+**
+** Rewind (csr,csrStart,csrEnd) // if EOF goto flush_partition_done
+** while( 1 ){
+** Next(csrEnd) // Exit while(1) at EOF
+** Aggstep (csrEnd)
+** }
+** while( 1 ){
+** AggFinal (xValue)
+** Gosub addrGosub
+** Next(csr) // if EOF goto flush_partition_done
+** if( (regStart--)<=0 ){
+** AggInverse (csrStart)
+** Next(csrStart)
+** }
+** }
+**
+** For the "CURRENT ROW AND UNBOUNDED FOLLOWING" case, the final if()
+** condition is always true (as if regStart were initialized to 0).
+**
+** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
+**
+** This is the only RANGE case handled by this routine. It modifies the
+** second while( 1 ) loop in "ROWS BETWEEN CURRENT ... UNBOUNDED..." to
+** be:
+**
+** while( 1 ){
+** AggFinal (xValue)
+** while( 1 ){
+** regPeer++
+** Gosub addrGosub
+** Next(csr) // if EOF goto flush_partition_done
+** if( new peer ) break;
+** }
+** while( (regPeer--)>0 ){
+** AggInverse (csrStart)
+** Next(csrStart)
+** }
+** }
+**
+** ROWS BETWEEN <expr> FOLLOWING AND <expr> FOLLOWING
+**
+** regEnd = regEnd - regStart
+** Rewind (csr,csrStart,csrEnd) // if EOF goto flush_partition_done
+** Aggstep (csrEnd)
+** Next(csrEnd) // if EOF fall-through
+** if( (regEnd--)<=0 ){
+** if( (regStart--)<=0 ){
+** AggFinal (xValue)
+** Gosub addrGosub
+** Next(csr) // if EOF goto flush_partition_done
+** }
+** AggInverse (csrStart)
+** Next (csrStart)
+** }
+**
+** ROWS BETWEEN <expr> PRECEDING AND <expr> PRECEDING
+**
+** Replace the bit after "Rewind" in the above with:
+**
+** if( (regEnd--)<=0 ){
+** AggStep (csrEnd)
+** Next (csrEnd)
+** }
+** AggFinal (xValue)
+** Gosub addrGosub
+** Next(csr) // if EOF goto flush_partition_done
+** if( (regStart--)<=0 ){
+** AggInverse (csr2)
+** Next (csr2)
+** }
+**
+*/
+static void windowCodeRowExprStep(
+ Parse *pParse,
+ Select *p,
+ WhereInfo *pWInfo,
+ int regGosub,
+ int addrGosub
+){
+ Window *pMWin = p->pWin;
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ int regFlushPart; /* Register for "Gosub flush_partition" */
+ int lblFlushPart; /* Label for "Gosub flush_partition" */
+ int lblFlushDone; /* Label for "Gosub flush_partition_done" */
+
+ int regArg;
+ int addr;
+ int csrStart = pParse->nTab++;
+ int csrEnd = pParse->nTab++;
+ int regStart; /* Value of <expr> PRECEDING */
+ int regEnd; /* Value of <expr> FOLLOWING */
+ int addrGoto;
+ int addrTop;
+ int addrIfPos1 = 0;
+ int addrIfPos2 = 0;
+ int regSize = 0;
+
+ assert( pMWin->eStart==TK_PRECEDING
+ || pMWin->eStart==TK_CURRENT
+ || pMWin->eStart==TK_FOLLOWING
+ || pMWin->eStart==TK_UNBOUNDED
+ );
+ assert( pMWin->eEnd==TK_FOLLOWING
+ || pMWin->eEnd==TK_CURRENT
+ || pMWin->eEnd==TK_UNBOUNDED
+ || pMWin->eEnd==TK_PRECEDING
+ );
+
+ /* Allocate register and label for the "flush_partition" sub-routine. */
+ regFlushPart = ++pParse->nMem;
+ lblFlushPart = sqlite3VdbeMakeLabel(v);
+ lblFlushDone = sqlite3VdbeMakeLabel(v);
+
+ regStart = ++pParse->nMem;
+ regEnd = ++pParse->nMem;
+
+ windowPartitionCache(pParse, p, pWInfo, regFlushPart, lblFlushPart, &regSize);
+
+ addrGoto = sqlite3VdbeAddOp0(v, OP_Goto);
+
+ /* Start of "flush_partition" */
+ sqlite3VdbeResolveLabel(v, lblFlushPart);
+ sqlite3VdbeAddOp2(v, OP_Once, 0, sqlite3VdbeCurrentAddr(v)+3);
+ VdbeCoverage(v);
+ VdbeComment((v, "Flush_partition subroutine"));
+ sqlite3VdbeAddOp2(v, OP_OpenDup, csrStart, pMWin->iEphCsr);
+ sqlite3VdbeAddOp2(v, OP_OpenDup, csrEnd, pMWin->iEphCsr);
+
+ /* If either regStart or regEnd are not non-negative integers, throw
+ ** an exception. */
+ if( pMWin->pStart ){
+ sqlite3ExprCode(pParse, pMWin->pStart, regStart);
+ windowCheckIntValue(pParse, regStart, 0);
+ }
+ if( pMWin->pEnd ){
+ sqlite3ExprCode(pParse, pMWin->pEnd, regEnd);
+ windowCheckIntValue(pParse, regEnd, 1);
+ }
+
+ /* If this is "ROWS <expr1> FOLLOWING AND ROWS <expr2> FOLLOWING", do:
+ **
+ ** if( regEnd<regStart ){
+ ** // The frame always consists of 0 rows
+ ** regStart = regSize;
+ ** }
+ ** regEnd = regEnd - regStart;
+ */
+ if( pMWin->pEnd && pMWin->eStart==TK_FOLLOWING ){
+ assert( pMWin->pStart!=0 );
+ assert( pMWin->eEnd==TK_FOLLOWING );
+ sqlite3VdbeAddOp3(v, OP_Ge, regStart, sqlite3VdbeCurrentAddr(v)+2, regEnd);
+ VdbeCoverageNeverNull(v);
+ sqlite3VdbeAddOp2(v, OP_Copy, regSize, regStart);
+ sqlite3VdbeAddOp3(v, OP_Subtract, regStart, regEnd, regEnd);
+ }
+
+ if( pMWin->pStart && pMWin->eEnd==TK_PRECEDING ){
+ assert( pMWin->pEnd!=0 );
+ assert( pMWin->eStart==TK_PRECEDING );
+ sqlite3VdbeAddOp3(v, OP_Le, regStart, sqlite3VdbeCurrentAddr(v)+3, regEnd);
+ VdbeCoverageNeverNull(v);
+ sqlite3VdbeAddOp2(v, OP_Copy, regSize, regStart);
+ sqlite3VdbeAddOp2(v, OP_Copy, regSize, regEnd);
+ }
+
+ /* Initialize the accumulator register for each window function to NULL */
+ regArg = windowInitAccum(pParse, pMWin);
+
+ sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr, lblFlushDone);
+ VdbeCoverage(v);
+ sqlite3VdbeAddOp2(v, OP_Rewind, csrStart, lblFlushDone);
+ VdbeCoverageNeverTaken(v);
+ sqlite3VdbeChangeP5(v, 1);
+ sqlite3VdbeAddOp2(v, OP_Rewind, csrEnd, lblFlushDone);
+ VdbeCoverageNeverTaken(v);
+ sqlite3VdbeChangeP5(v, 1);
+
+ /* Invoke AggStep function for each window function using the row that
+ ** csrEnd currently points to. Or, if csrEnd is already at EOF,
+ ** do nothing. */
+ addrTop = sqlite3VdbeCurrentAddr(v);
+ if( pMWin->eEnd==TK_PRECEDING ){
+ addrIfPos1 = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0 , 1);
+ VdbeCoverage(v);
+ }
+ sqlite3VdbeAddOp2(v, OP_Next, csrEnd, sqlite3VdbeCurrentAddr(v)+2);
+ VdbeCoverage(v);
+ addr = sqlite3VdbeAddOp0(v, OP_Goto);
+ windowAggStep(pParse, pMWin, csrEnd, 0, regArg, regSize);
+ if( pMWin->eEnd==TK_UNBOUNDED ){
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop);
+ sqlite3VdbeJumpHere(v, addr);
+ addrTop = sqlite3VdbeCurrentAddr(v);
+ }else{
+ sqlite3VdbeJumpHere(v, addr);
+ if( pMWin->eEnd==TK_PRECEDING ){
+ sqlite3VdbeJumpHere(v, addrIfPos1);
+ }
+ }
+
+ if( pMWin->eEnd==TK_FOLLOWING ){
+ addrIfPos1 = sqlite3VdbeAddOp3(v, OP_IfPos, regEnd, 0 , 1);
+ VdbeCoverage(v);
+ }
+ if( pMWin->eStart==TK_FOLLOWING ){
+ addrIfPos2 = sqlite3VdbeAddOp3(v, OP_IfPos, regStart, 0 , 1);
+ VdbeCoverage(v);
+ }
+ windowAggFinal(pParse, pMWin, 0);
+ windowReturnOneRow(pParse, pMWin, regGosub, addrGosub);
+ sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)+2);
+ VdbeCoverage(v);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, lblFlushDone);
+ if( pMWin->eStart==TK_FOLLOWING ){
+ sqlite3VdbeJumpHere(v, addrIfPos2);
+ }
+
+ if( pMWin->eStart==TK_CURRENT
+ || pMWin->eStart==TK_PRECEDING
+ || pMWin->eStart==TK_FOLLOWING
+ ){
+ int lblSkipInverse = sqlite3VdbeMakeLabel(v);;
+ if( pMWin->eStart==TK_PRECEDING ){
+ sqlite3VdbeAddOp3(v, OP_IfPos, regStart, lblSkipInverse, 1);
+ VdbeCoverage(v);
+ }
+ if( pMWin->eStart==TK_FOLLOWING ){
+ sqlite3VdbeAddOp2(v, OP_Next, csrStart, sqlite3VdbeCurrentAddr(v)+2);
+ VdbeCoverage(v);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, lblSkipInverse);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_Next, csrStart, sqlite3VdbeCurrentAddr(v)+1);
+ VdbeCoverageAlwaysTaken(v);
+ }
+ windowAggStep(pParse, pMWin, csrStart, 1, regArg, regSize);
+ sqlite3VdbeResolveLabel(v, lblSkipInverse);
+ }
+ if( pMWin->eEnd==TK_FOLLOWING ){
+ sqlite3VdbeJumpHere(v, addrIfPos1);
+ }
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop);
+
+ /* flush_partition_done: */
+ sqlite3VdbeResolveLabel(v, lblFlushDone);
+ sqlite3VdbeAddOp1(v, OP_ResetSorter, pMWin->iEphCsr);
+ sqlite3VdbeAddOp1(v, OP_Return, regFlushPart);
+ VdbeComment((v, "end flush_partition subroutine"));
+
+ /* Jump to here to skip over flush_partition */
+ sqlite3VdbeJumpHere(v, addrGoto);
+}
+
+/*
+** This function does the work of sqlite3WindowCodeStep() for cases that
+** would normally be handled by windowCodeDefaultStep() when there are
+** one or more built-in window-functions that require the entire partition
+** to be cached in a temp table before any rows can be returned. Additionally.
+** "RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING" is always handled by
+** this function.
+**
+** Pseudo-code corresponding to the VM code generated by this function
+** for each type of window follows.
+**
+** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+**
+** flush_partition:
+** Once {
+** OpenDup (iEphCsr -> csrLead)
+** }
+** Integer ctr 0
+** foreach row (csrLead){
+** if( new peer ){
+** AggFinal (xValue)
+** for(i=0; i<ctr; i++){
+** Gosub addrGosub
+** Next iEphCsr
+** }
+** Integer ctr 0
+** }
+** AggStep (csrLead)
+** Incr ctr
+** }
+**
+** AggFinal (xFinalize)
+** for(i=0; i<ctr; i++){
+** Gosub addrGosub
+** Next iEphCsr
+** }
+**
+** ResetSorter (csr)
+** Return
+**
+** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+**
+** As above, except that the "if( new peer )" branch is always taken.
+**
+** RANGE BETWEEN CURRENT ROW AND CURRENT ROW
+**
+** As above, except that each of the for() loops becomes:
+**
+** for(i=0; i<ctr; i++){
+** Gosub addrGosub
+** AggInverse (iEphCsr)
+** Next iEphCsr
+** }
+**
+** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
+**
+** flush_partition:
+** Once {
+** OpenDup (iEphCsr -> csrLead)
+** }
+** foreach row (csrLead) {
+** AggStep (csrLead)
+** }
+** foreach row (iEphCsr) {
+** Gosub addrGosub
+** }
+**
+** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
+**
+** flush_partition:
+** Once {
+** OpenDup (iEphCsr -> csrLead)
+** }
+** foreach row (csrLead){
+** AggStep (csrLead)
+** }
+** Rewind (csrLead)
+** Integer ctr 0
+** foreach row (csrLead){
+** if( new peer ){
+** AggFinal (xValue)
+** for(i=0; i<ctr; i++){
+** Gosub addrGosub
+** AggInverse (iEphCsr)
+** Next iEphCsr
+** }
+** Integer ctr 0
+** }
+** Incr ctr
+** }
+**
+** AggFinal (xFinalize)
+** for(i=0; i<ctr; i++){
+** Gosub addrGosub
+** Next iEphCsr
+** }
+**
+** ResetSorter (csr)
+** Return
+*/
+static void windowCodeCacheStep(
+ Parse *pParse,
+ Select *p,
+ WhereInfo *pWInfo,
+ int regGosub,
+ int addrGosub
+){
+ Window *pMWin = p->pWin;
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ int k;
+ int addr;
+ ExprList *pPart = pMWin->pPartition;
+ ExprList *pOrderBy = pMWin->pOrderBy;
+ int nPeer = pOrderBy ? pOrderBy->nExpr : 0;
+ int regNewPeer;
+
+ int addrGoto; /* Address of Goto used to jump flush_par.. */
+ int addrNext; /* Jump here for next iteration of loop */
+ int regFlushPart;
+ int lblFlushPart;
+ int csrLead;
+ int regCtr;
+ int regArg; /* Register array to martial function args */
+ int regSize;
+ int lblEmpty;
+ int bReverse = pMWin->pOrderBy && pMWin->eStart==TK_CURRENT
+ && pMWin->eEnd==TK_UNBOUNDED;
+
+ assert( (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_CURRENT)
+ || (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_UNBOUNDED)
+ || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_CURRENT)
+ || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED)
+ );
+
+ lblEmpty = sqlite3VdbeMakeLabel(v);
+ regNewPeer = pParse->nMem+1;
+ pParse->nMem += nPeer;
+
+ /* Allocate register and label for the "flush_partition" sub-routine. */
+ regFlushPart = ++pParse->nMem;
+ lblFlushPart = sqlite3VdbeMakeLabel(v);
+
+ csrLead = pParse->nTab++;
+ regCtr = ++pParse->nMem;
+
+ windowPartitionCache(pParse, p, pWInfo, regFlushPart, lblFlushPart, &regSize);
+ addrGoto = sqlite3VdbeAddOp0(v, OP_Goto);
+
+ /* Start of "flush_partition" */
+ sqlite3VdbeResolveLabel(v, lblFlushPart);
+ sqlite3VdbeAddOp2(v, OP_Once, 0, sqlite3VdbeCurrentAddr(v)+2);
+ VdbeCoverage(v);
+ sqlite3VdbeAddOp2(v, OP_OpenDup, csrLead, pMWin->iEphCsr);
+
+ /* Initialize the accumulator register for each window function to NULL */
+ regArg = windowInitAccum(pParse, pMWin);
+
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, regCtr);
+ sqlite3VdbeAddOp2(v, OP_Rewind, csrLead, lblEmpty);
+ VdbeCoverage(v);
+ sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr, lblEmpty);
+ VdbeCoverageNeverTaken(v);
+
+ if( bReverse ){
+ int addr2 = sqlite3VdbeCurrentAddr(v);
+ windowAggStep(pParse, pMWin, csrLead, 0, regArg, regSize);
+ sqlite3VdbeAddOp2(v, OP_Next, csrLead, addr2);
+ VdbeCoverage(v);
+ sqlite3VdbeAddOp2(v, OP_Rewind, csrLead, lblEmpty);
+ VdbeCoverageNeverTaken(v);
+ }
+ addrNext = sqlite3VdbeCurrentAddr(v);
+
+ if( pOrderBy && (pMWin->eEnd==TK_CURRENT || pMWin->eStart==TK_CURRENT) ){
+ int bCurrent = (pMWin->eStart==TK_CURRENT);
+ int addrJump = 0; /* Address of OP_Jump below */
+ if( pMWin->eType==TK_RANGE ){
+ int iOff = pMWin->nBufferCol + (pPart ? pPart->nExpr : 0);
+ int regPeer = pMWin->regPart + (pPart ? pPart->nExpr : 0);
+ KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pOrderBy, 0, 0);
+ for(k=0; k<nPeer; k++){
+ sqlite3VdbeAddOp3(v, OP_Column, csrLead, iOff+k, regNewPeer+k);
+ }
+ addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPeer, regPeer, nPeer);
+ sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO);
+ addrJump = sqlite3VdbeAddOp3(v, OP_Jump, addr+2, 0, addr+2);
+ VdbeCoverage(v);
+ sqlite3VdbeAddOp3(v, OP_Copy, regNewPeer, regPeer, nPeer-1);
+ }
+
+ windowReturnRows(pParse, pMWin, regCtr, regGosub, addrGosub,
+ (bCurrent ? regArg : 0), (bCurrent ? regSize : 0)
+ );
+ if( addrJump ) sqlite3VdbeJumpHere(v, addrJump);
+ }
+
+ if( bReverse==0 ){
+ windowAggStep(pParse, pMWin, csrLead, 0, regArg, regSize);
+ }
+ sqlite3VdbeAddOp2(v, OP_AddImm, regCtr, 1);
+ sqlite3VdbeAddOp2(v, OP_Next, csrLead, addrNext);
+ VdbeCoverage(v);
+
+ windowReturnRows(pParse, pMWin, regCtr, regGosub, addrGosub, 0, 0);
+
+ sqlite3VdbeResolveLabel(v, lblEmpty);
+ sqlite3VdbeAddOp1(v, OP_ResetSorter, pMWin->iEphCsr);
+ sqlite3VdbeAddOp1(v, OP_Return, regFlushPart);
+
+ /* Jump to here to skip over flush_partition */
+ sqlite3VdbeJumpHere(v, addrGoto);
+}
+
+
+/*
+** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+**
+** ...
+** if( new partition ){
+** AggFinal (xFinalize)
+** Gosub addrGosub
+** ResetSorter eph-table
+** }
+** else if( new peer ){
+** AggFinal (xValue)
+** Gosub addrGosub
+** ResetSorter eph-table
+** }
+** AggStep
+** Insert (record into eph-table)
+** sqlite3WhereEnd()
+** AggFinal (xFinalize)
+** Gosub addrGosub
+**
+** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
+**
+** As above, except take no action for a "new peer". Invoke
+** the sub-routine once only for each partition.
+**
+** RANGE BETWEEN CURRENT ROW AND CURRENT ROW
+**
+** As above, except that the "new peer" condition is handled in the
+** same way as "new partition" (so there is no "else if" block).
+**
+** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+**
+** As above, except assume every row is a "new peer".
+*/
+static void windowCodeDefaultStep(
+ Parse *pParse,
+ Select *p,
+ WhereInfo *pWInfo,
+ int regGosub,
+ int addrGosub
+){
+ Window *pMWin = p->pWin;
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ int k;
+ int iSubCsr = p->pSrc->a[0].iCursor;
+ int nSub = p->pSrc->a[0].pTab->nCol;
+ int reg = pParse->nMem+1;
+ int regRecord = reg+nSub;
+ int regRowid = regRecord+1;
+ int addr;
+ ExprList *pPart = pMWin->pPartition;
+ ExprList *pOrderBy = pMWin->pOrderBy;
+
+ assert( pMWin->eType==TK_RANGE
+ || (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_CURRENT)
+ );
+
+ assert( (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_CURRENT)
+ || (pMWin->eStart==TK_UNBOUNDED && pMWin->eEnd==TK_UNBOUNDED)
+ || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_CURRENT)
+ || (pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED && !pOrderBy)
+ );
+
+ if( pMWin->eEnd==TK_UNBOUNDED ){
+ pOrderBy = 0;
+ }
+
+ pParse->nMem += nSub + 2;
+
+ /* Load the individual column values of the row returned by
+ ** the sub-select into an array of registers. */
+ for(k=0; k<nSub; k++){
+ sqlite3VdbeAddOp3(v, OP_Column, iSubCsr, k, reg+k);
+ }
+
+ /* Check if this is the start of a new partition or peer group. */
+ if( pPart || pOrderBy ){
+ int nPart = (pPart ? pPart->nExpr : 0);
+ int addrGoto = 0;
+ int addrJump = 0;
+ int nPeer = (pOrderBy ? pOrderBy->nExpr : 0);
+
+ if( pPart ){
+ int regNewPart = reg + pMWin->nBufferCol;
+ KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pPart, 0, 0);
+ addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPart, pMWin->regPart,nPart);
+ sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO);
+ addrJump = sqlite3VdbeAddOp3(v, OP_Jump, addr+2, 0, addr+2);
+ VdbeCoverageEqNe(v);
+ windowAggFinal(pParse, pMWin, 1);
+ if( pOrderBy ){
+ addrGoto = sqlite3VdbeAddOp0(v, OP_Goto);
+ }
+ }
+
+ if( pOrderBy ){
+ int regNewPeer = reg + pMWin->nBufferCol + nPart;
+ int regPeer = pMWin->regPart + nPart;
+
+ if( addrJump ) sqlite3VdbeJumpHere(v, addrJump);
+ if( pMWin->eType==TK_RANGE ){
+ KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pOrderBy, 0, 0);
+ addr = sqlite3VdbeAddOp3(v, OP_Compare, regNewPeer, regPeer, nPeer);
+ sqlite3VdbeAppendP4(v, (void*)pKeyInfo, P4_KEYINFO);
+ addrJump = sqlite3VdbeAddOp3(v, OP_Jump, addr+2, 0, addr+2);
+ VdbeCoverage(v);
+ }else{
+ addrJump = 0;
+ }
+ windowAggFinal(pParse, pMWin, pMWin->eStart==TK_CURRENT);
+ if( addrGoto ) sqlite3VdbeJumpHere(v, addrGoto);
+ }
+
+ sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr,sqlite3VdbeCurrentAddr(v)+3);
+ VdbeCoverage(v);
+ sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub);
+ sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)-1);
+ VdbeCoverage(v);
+
+ sqlite3VdbeAddOp1(v, OP_ResetSorter, pMWin->iEphCsr);
+ sqlite3VdbeAddOp3(
+ v, OP_Copy, reg+pMWin->nBufferCol, pMWin->regPart, nPart+nPeer-1
+ );
+
+ if( addrJump ) sqlite3VdbeJumpHere(v, addrJump);
+ }
+
+ /* Invoke step function for window functions */
+ windowAggStep(pParse, pMWin, -1, 0, reg, 0);
+
+ /* Buffer the current row in the ephemeral table. */
+ if( pMWin->nBufferCol>0 ){
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, pMWin->nBufferCol, regRecord);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_Blob, 0, regRecord);
+ sqlite3VdbeAppendP4(v, (void*)"", 0);
+ }
+ sqlite3VdbeAddOp2(v, OP_NewRowid, pMWin->iEphCsr, regRowid);
+ sqlite3VdbeAddOp3(v, OP_Insert, pMWin->iEphCsr, regRecord, regRowid);
+
+ /* End the database scan loop. */
+ sqlite3WhereEnd(pWInfo);
+
+ windowAggFinal(pParse, pMWin, 1);
+ sqlite3VdbeAddOp2(v, OP_Rewind, pMWin->iEphCsr,sqlite3VdbeCurrentAddr(v)+3);
+ VdbeCoverage(v);
+ sqlite3VdbeAddOp2(v, OP_Gosub, regGosub, addrGosub);
+ sqlite3VdbeAddOp2(v, OP_Next, pMWin->iEphCsr, sqlite3VdbeCurrentAddr(v)-1);
+ VdbeCoverage(v);
+}
+
+/*
+** Allocate and return a duplicate of the Window object indicated by the
+** third argument. Set the Window.pOwner field of the new object to
+** pOwner.
+*/
+SQLITE_PRIVATE Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){
+ Window *pNew = 0;
+ if( p ){
+ pNew = sqlite3DbMallocZero(db, sizeof(Window));
+ if( pNew ){
+ pNew->zName = sqlite3DbStrDup(db, p->zName);
+ pNew->pFilter = sqlite3ExprDup(db, p->pFilter, 0);
+ pNew->pPartition = sqlite3ExprListDup(db, p->pPartition, 0);
+ pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, 0);
+ pNew->eType = p->eType;
+ pNew->eEnd = p->eEnd;
+ pNew->eStart = p->eStart;
+ pNew->pStart = sqlite3ExprDup(db, p->pStart, 0);
+ pNew->pEnd = sqlite3ExprDup(db, p->pEnd, 0);
+ pNew->pOwner = pOwner;
+ }
+ }
+ return pNew;
+}
+
+/*
+** Return a copy of the linked list of Window objects passed as the
+** second argument.
+*/
+SQLITE_PRIVATE Window *sqlite3WindowListDup(sqlite3 *db, Window *p){
+ Window *pWin;
+ Window *pRet = 0;
+ Window **pp = &pRet;
+
+ for(pWin=p; pWin; pWin=pWin->pNextWin){
+ *pp = sqlite3WindowDup(db, 0, pWin);
+ if( *pp==0 ) break;
+ pp = &((*pp)->pNextWin);
+ }
+
+ return pRet;
+}
+
+/*
+** sqlite3WhereBegin() has already been called for the SELECT statement
+** passed as the second argument when this function is invoked. It generates
+** code to populate the Window.regResult register for each window function and
+** invoke the sub-routine at instruction addrGosub once for each row.
+** This function calls sqlite3WhereEnd() before returning.
+*/
+SQLITE_PRIVATE void sqlite3WindowCodeStep(
+ Parse *pParse, /* Parse context */
+ Select *p, /* Rewritten SELECT statement */
+ WhereInfo *pWInfo, /* Context returned by sqlite3WhereBegin() */
+ int regGosub, /* Register for OP_Gosub */
+ int addrGosub /* OP_Gosub here to return each row */
+){
+ Window *pMWin = p->pWin;
+
+ /* There are three different functions that may be used to do the work
+ ** of this one, depending on the window frame and the specific built-in
+ ** window functions used (if any).
+ **
+ ** windowCodeRowExprStep() handles all "ROWS" window frames, except for:
+ **
+ ** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+ **
+ ** The exception is because windowCodeRowExprStep() implements all window
+ ** frame types by caching the entire partition in a temp table, and
+ ** "ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW" is easy enough to
+ ** implement without such a cache.
+ **
+ ** windowCodeCacheStep() is used for:
+ **
+ ** RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
+ **
+ ** It is also used for anything not handled by windowCodeRowExprStep()
+ ** that invokes a built-in window function that requires the entire
+ ** partition to be cached in a temp table before any rows are returned
+ ** (e.g. nth_value() or percent_rank()).
+ **
+ ** Finally, assuming there is no built-in window function that requires
+ ** the partition to be cached, windowCodeDefaultStep() is used for:
+ **
+ ** RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+ ** RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
+ ** RANGE BETWEEN CURRENT ROW AND CURRENT ROW
+ ** ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
+ **
+ ** windowCodeDefaultStep() is the only one of the three functions that
+ ** does not cache each partition in a temp table before beginning to
+ ** return rows.
+ */
+ if( pMWin->eType==TK_ROWS
+ && (pMWin->eStart!=TK_UNBOUNDED||pMWin->eEnd!=TK_CURRENT||!pMWin->pOrderBy)
+ ){
+ VdbeModuleComment((pParse->pVdbe, "Begin RowExprStep()"));
+ windowCodeRowExprStep(pParse, p, pWInfo, regGosub, addrGosub);
+ }else{
+ Window *pWin;
+ int bCache = 0; /* True to use CacheStep() */
+
+ if( pMWin->eStart==TK_CURRENT && pMWin->eEnd==TK_UNBOUNDED ){
+ bCache = 1;
+ }else{
+ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
+ FuncDef *pFunc = pWin->pFunc;
+ if( (pFunc->funcFlags & SQLITE_FUNC_WINDOW_SIZE)
+ || (pFunc->zName==nth_valueName)
+ || (pFunc->zName==first_valueName)
+ || (pFunc->zName==leadName)
+ || (pFunc->zName==lagName)
+ ){
+ bCache = 1;
+ break;
+ }
+ }
+ }
+
+ /* Otherwise, call windowCodeDefaultStep(). */
+ if( bCache ){
+ VdbeModuleComment((pParse->pVdbe, "Begin CacheStep()"));
+ windowCodeCacheStep(pParse, p, pWInfo, regGosub, addrGosub);
+ }else{
+ VdbeModuleComment((pParse->pVdbe, "Begin DefaultStep()"));
+ windowCodeDefaultStep(pParse, p, pWInfo, regGosub, addrGosub);
+ }
+ }
+}
+
+#endif /* SQLITE_OMIT_WINDOWFUNC */
+
+/************** End of window.c **********************************************/
/************** Begin file parse.c *******************************************/
/*
** 2000-05-29
@@ -141456,6 +145981,8 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
*/
struct TrigEvent { int a; IdList * b; };
+struct FrameBound { int eType; Expr *pExpr; };
+
/*
** Disable lookaside memory allocation for objects that might be
** shared across database connections.
@@ -141496,10 +146023,21 @@ static void disableLookaside(Parse *pParse){
static Expr *tokenExpr(Parse *pParse, int op, Token t){
Expr *p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)+t.n+1);
if( p ){
- memset(p, 0, sizeof(Expr));
+ /* memset(p, 0, sizeof(Expr)); */
p->op = (u8)op;
+ p->affinity = 0;
p->flags = EP_Leaf;
p->iAgg = -1;
+ p->pLeft = p->pRight = 0;
+ p->x.pList = 0;
+ p->pAggInfo = 0;
+ p->pTab = 0;
+ p->op2 = 0;
+ p->iTable = 0;
+ p->iColumn = 0;
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ p->pWin = 0;
+#endif
p->u.zToken = (char*)&p[1];
memcpy(p->u.zToken, t.z, t.n);
p->u.zToken[t.n] = 0;
@@ -141510,15 +146048,19 @@ static void disableLookaside(Parse *pParse){
#if SQLITE_MAX_EXPR_DEPTH>0
p->nHeight = 1;
#endif
+ if( IN_RENAME_OBJECT ){
+ return (Expr*)sqlite3RenameTokenMap(pParse, (void*)p, &t);
+ }
}
return p;
}
+
/* A routine to convert a binary TK_IS or TK_ISNOT expression into a
** unary TK_ISNULL or TK_NOTNULL expression. */
static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){
sqlite3 *db = pParse->db;
- if( pA && pY && pY->op==TK_NULL ){
+ if( pA && pY && pY->op==TK_NULL && !IN_RENAME_OBJECT ){
pA->op = (u8)op;
sqlite3ExprDelete(db, pA->pRight);
pA->pRight = 0;
@@ -141609,26 +146151,28 @@ static void disableLookaside(Parse *pParse){
# define INTERFACE 1
#endif
/************* Begin control #defines *****************************************/
-#define YYCODETYPE unsigned char
-#define YYNOCODE 255
+#define YYCODETYPE unsigned short int
+#define YYNOCODE 277
#define YYACTIONTYPE unsigned short int
-#define YYWILDCARD 84
+#define YYWILDCARD 91
#define sqlite3ParserTOKENTYPE Token
typedef union {
int yyinit;
sqlite3ParserTOKENTYPE yy0;
- const char* yy36;
- TriggerStep* yy47;
- With* yy91;
- struct {int value; int mask;} yy107;
- Expr* yy182;
- Upsert* yy198;
- ExprList* yy232;
- struct TrigEvent yy300;
- Select* yy399;
- SrcList* yy427;
- int yy502;
- IdList* yy510;
+ Expr* yy18;
+ struct TrigEvent yy34;
+ IdList* yy48;
+ int yy70;
+ struct {int value; int mask;} yy111;
+ struct FrameBound yy119;
+ SrcList* yy135;
+ TriggerStep* yy207;
+ Window* yy327;
+ Upsert* yy340;
+ const char* yy392;
+ ExprList* yy420;
+ With* yy449;
+ Select* yy489;
} YYMINORTYPE;
#ifndef YYSTACKDEPTH
#define YYSTACKDEPTH 100
@@ -141644,18 +146188,19 @@ typedef union {
#define sqlite3ParserCTX_FETCH Parse *pParse=yypParser->pParse;
#define sqlite3ParserCTX_STORE yypParser->pParse=pParse;
#define YYFALLBACK 1
-#define YYNSTATE 490
-#define YYNRULE 341
-#define YYNTOKEN 145
-#define YY_MAX_SHIFT 489
-#define YY_MIN_SHIFTREDUCE 705
-#define YY_MAX_SHIFTREDUCE 1045
-#define YY_ERROR_ACTION 1046
-#define YY_ACCEPT_ACTION 1047
-#define YY_NO_ACTION 1048
-#define YY_MIN_REDUCE 1049
-#define YY_MAX_REDUCE 1389
+#define YYNSTATE 521
+#define YYNRULE 367
+#define YYNTOKEN 155
+#define YY_MAX_SHIFT 520
+#define YY_MIN_SHIFTREDUCE 756
+#define YY_MAX_SHIFTREDUCE 1122
+#define YY_ERROR_ACTION 1123
+#define YY_ACCEPT_ACTION 1124
+#define YY_NO_ACTION 1125
+#define YY_MIN_REDUCE 1126
+#define YY_MAX_REDUCE 1492
/************* End control #defines *******************************************/
+#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])))
/* Define the yytestcase() macro to be a no-op if is not already defined
** otherwise.
@@ -141720,503 +146265,568 @@ typedef union {
** yy_default[] Default action for each state.
**
*********** Begin parsing tables **********************************************/
-#define YY_ACTTAB_COUNT (1657)
+#define YY_ACTTAB_COUNT (2009)
static const YYACTIONTYPE yy_action[] = {
- /* 0 */ 349, 99, 96, 185, 99, 96, 185, 233, 1047, 1,
- /* 10 */ 1, 489, 2, 1051, 484, 477, 477, 477, 260, 351,
- /* 20 */ 121, 1310, 1120, 1120, 1178, 1115, 1094, 1128, 380, 380,
- /* 30 */ 380, 835, 454, 410, 1115, 59, 59, 1357, 425, 836,
- /* 40 */ 710, 711, 712, 106, 107, 97, 1023, 1023, 900, 903,
- /* 50 */ 892, 892, 104, 104, 105, 105, 105, 105, 346, 238,
- /* 60 */ 238, 99, 96, 185, 238, 238, 889, 889, 901, 904,
- /* 70 */ 460, 481, 351, 99, 96, 185, 481, 347, 1177, 82,
- /* 80 */ 388, 214, 182, 23, 194, 103, 103, 103, 103, 102,
- /* 90 */ 102, 101, 101, 101, 100, 381, 106, 107, 97, 1023,
- /* 100 */ 1023, 900, 903, 892, 892, 104, 104, 105, 105, 105,
- /* 110 */ 105, 10, 385, 484, 24, 484, 1333, 489, 2, 1051,
- /* 120 */ 335, 1043, 108, 893, 260, 351, 121, 99, 96, 185,
- /* 130 */ 100, 381, 386, 1128, 59, 59, 59, 59, 103, 103,
- /* 140 */ 103, 103, 102, 102, 101, 101, 101, 100, 381, 106,
- /* 150 */ 107, 97, 1023, 1023, 900, 903, 892, 892, 104, 104,
- /* 160 */ 105, 105, 105, 105, 360, 238, 238, 170, 170, 467,
- /* 170 */ 455, 467, 464, 67, 381, 329, 169, 481, 351, 343,
- /* 180 */ 338, 400, 1044, 68, 101, 101, 101, 100, 381, 393,
- /* 190 */ 194, 103, 103, 103, 103, 102, 102, 101, 101, 101,
- /* 200 */ 100, 381, 106, 107, 97, 1023, 1023, 900, 903, 892,
- /* 210 */ 892, 104, 104, 105, 105, 105, 105, 483, 385, 103,
- /* 220 */ 103, 103, 103, 102, 102, 101, 101, 101, 100, 381,
- /* 230 */ 268, 351, 946, 946, 422, 296, 102, 102, 101, 101,
- /* 240 */ 101, 100, 381, 861, 103, 103, 103, 103, 102, 102,
- /* 250 */ 101, 101, 101, 100, 381, 106, 107, 97, 1023, 1023,
- /* 260 */ 900, 903, 892, 892, 104, 104, 105, 105, 105, 105,
- /* 270 */ 484, 983, 1383, 206, 1353, 1383, 438, 435, 434, 281,
- /* 280 */ 396, 269, 1089, 941, 351, 1002, 433, 861, 743, 401,
- /* 290 */ 282, 57, 57, 482, 145, 791, 791, 103, 103, 103,
- /* 300 */ 103, 102, 102, 101, 101, 101, 100, 381, 106, 107,
- /* 310 */ 97, 1023, 1023, 900, 903, 892, 892, 104, 104, 105,
- /* 320 */ 105, 105, 105, 281, 1002, 1003, 1004, 206, 879, 319,
- /* 330 */ 438, 435, 434, 981, 259, 474, 360, 351, 1118, 1118,
- /* 340 */ 433, 736, 379, 378, 872, 1002, 1356, 322, 871, 766,
- /* 350 */ 103, 103, 103, 103, 102, 102, 101, 101, 101, 100,
- /* 360 */ 381, 106, 107, 97, 1023, 1023, 900, 903, 892, 892,
- /* 370 */ 104, 104, 105, 105, 105, 105, 484, 801, 484, 871,
- /* 380 */ 871, 873, 401, 282, 1002, 1003, 1004, 1030, 360, 1030,
- /* 390 */ 351, 983, 1384, 213, 880, 1384, 145, 59, 59, 59,
- /* 400 */ 59, 1002, 244, 103, 103, 103, 103, 102, 102, 101,
- /* 410 */ 101, 101, 100, 381, 106, 107, 97, 1023, 1023, 900,
- /* 420 */ 903, 892, 892, 104, 104, 105, 105, 105, 105, 274,
- /* 430 */ 484, 110, 467, 479, 467, 444, 259, 474, 232, 232,
- /* 440 */ 1002, 1003, 1004, 351, 210, 335, 982, 866, 1385, 336,
- /* 450 */ 481, 59, 59, 981, 245, 307, 103, 103, 103, 103,
- /* 460 */ 102, 102, 101, 101, 101, 100, 381, 106, 107, 97,
- /* 470 */ 1023, 1023, 900, 903, 892, 892, 104, 104, 105, 105,
- /* 480 */ 105, 105, 453, 459, 484, 408, 377, 259, 474, 271,
- /* 490 */ 183, 273, 209, 208, 207, 356, 351, 307, 178, 177,
- /* 500 */ 127, 1006, 1098, 14, 14, 43, 43, 1044, 425, 103,
- /* 510 */ 103, 103, 103, 102, 102, 101, 101, 101, 100, 381,
- /* 520 */ 106, 107, 97, 1023, 1023, 900, 903, 892, 892, 104,
- /* 530 */ 104, 105, 105, 105, 105, 294, 1132, 408, 160, 484,
- /* 540 */ 408, 1006, 129, 962, 1209, 239, 239, 481, 307, 425,
- /* 550 */ 1309, 1097, 351, 235, 243, 272, 820, 481, 963, 425,
- /* 560 */ 11, 11, 103, 103, 103, 103, 102, 102, 101, 101,
- /* 570 */ 101, 100, 381, 964, 362, 1002, 106, 107, 97, 1023,
- /* 580 */ 1023, 900, 903, 892, 892, 104, 104, 105, 105, 105,
- /* 590 */ 105, 1275, 161, 126, 777, 289, 1209, 292, 1072, 357,
- /* 600 */ 1209, 1127, 476, 357, 778, 425, 247, 425, 351, 248,
- /* 610 */ 414, 364, 414, 171, 1002, 1003, 1004, 84, 103, 103,
- /* 620 */ 103, 103, 102, 102, 101, 101, 101, 100, 381, 1002,
- /* 630 */ 184, 484, 106, 107, 97, 1023, 1023, 900, 903, 892,
- /* 640 */ 892, 104, 104, 105, 105, 105, 105, 1123, 1209, 287,
- /* 650 */ 484, 1209, 11, 11, 179, 820, 259, 474, 307, 237,
- /* 660 */ 182, 351, 321, 365, 414, 308, 367, 366, 1002, 1003,
- /* 670 */ 1004, 44, 44, 87, 103, 103, 103, 103, 102, 102,
- /* 680 */ 101, 101, 101, 100, 381, 106, 107, 97, 1023, 1023,
- /* 690 */ 900, 903, 892, 892, 104, 104, 105, 105, 105, 105,
- /* 700 */ 246, 368, 280, 128, 10, 358, 146, 796, 835, 258,
- /* 710 */ 1020, 88, 795, 86, 351, 421, 836, 943, 376, 348,
- /* 720 */ 191, 943, 1318, 267, 308, 279, 456, 103, 103, 103,
- /* 730 */ 103, 102, 102, 101, 101, 101, 100, 381, 106, 95,
- /* 740 */ 97, 1023, 1023, 900, 903, 892, 892, 104, 104, 105,
- /* 750 */ 105, 105, 105, 420, 249, 238, 238, 238, 238, 79,
- /* 760 */ 375, 125, 305, 29, 262, 978, 351, 481, 337, 481,
- /* 770 */ 756, 755, 304, 278, 415, 15, 81, 940, 1126, 940,
- /* 780 */ 103, 103, 103, 103, 102, 102, 101, 101, 101, 100,
- /* 790 */ 381, 107, 97, 1023, 1023, 900, 903, 892, 892, 104,
- /* 800 */ 104, 105, 105, 105, 105, 457, 263, 484, 174, 484,
- /* 810 */ 238, 238, 863, 407, 402, 216, 216, 351, 409, 193,
- /* 820 */ 283, 216, 481, 81, 763, 764, 266, 5, 13, 13,
- /* 830 */ 34, 34, 103, 103, 103, 103, 102, 102, 101, 101,
- /* 840 */ 101, 100, 381, 97, 1023, 1023, 900, 903, 892, 892,
- /* 850 */ 104, 104, 105, 105, 105, 105, 93, 475, 1002, 4,
- /* 860 */ 403, 1002, 340, 431, 1002, 297, 212, 1277, 81, 746,
- /* 870 */ 1163, 152, 926, 478, 166, 212, 757, 829, 930, 939,
- /* 880 */ 216, 939, 858, 103, 103, 103, 103, 102, 102, 101,
- /* 890 */ 101, 101, 100, 381, 238, 238, 382, 1002, 1003, 1004,
- /* 900 */ 1002, 1003, 1004, 1002, 1003, 1004, 481, 439, 472, 746,
- /* 910 */ 105, 105, 105, 105, 98, 758, 1162, 145, 930, 412,
- /* 920 */ 879, 406, 793, 81, 395, 89, 90, 91, 105, 105,
- /* 930 */ 105, 105, 1323, 92, 484, 382, 486, 485, 240, 275,
- /* 940 */ 871, 103, 103, 103, 103, 102, 102, 101, 101, 101,
- /* 950 */ 100, 381, 1096, 371, 355, 45, 45, 259, 474, 103,
- /* 960 */ 103, 103, 103, 102, 102, 101, 101, 101, 100, 381,
- /* 970 */ 1150, 871, 871, 873, 874, 21, 1332, 991, 384, 730,
- /* 980 */ 722, 242, 123, 1298, 124, 875, 333, 333, 332, 227,
- /* 990 */ 330, 991, 384, 719, 256, 242, 484, 391, 413, 1297,
- /* 1000 */ 333, 333, 332, 227, 330, 748, 187, 719, 265, 470,
- /* 1010 */ 1279, 1002, 484, 417, 391, 390, 264, 11, 11, 284,
- /* 1020 */ 187, 732, 265, 93, 475, 875, 4, 1279, 1281, 419,
- /* 1030 */ 264, 369, 416, 11, 11, 1159, 288, 484, 399, 1346,
- /* 1040 */ 478, 379, 378, 291, 484, 293, 189, 250, 295, 1027,
- /* 1050 */ 1002, 1003, 1004, 190, 1029, 1111, 140, 188, 11, 11,
- /* 1060 */ 189, 732, 1028, 382, 923, 46, 46, 190, 1095, 230,
- /* 1070 */ 140, 188, 462, 93, 475, 472, 4, 300, 309, 391,
- /* 1080 */ 373, 6, 1069, 217, 739, 310, 1030, 879, 1030, 1171,
- /* 1090 */ 478, 352, 1279, 90, 91, 800, 259, 474, 1208, 484,
- /* 1100 */ 92, 1268, 382, 486, 485, 352, 1002, 871, 879, 426,
- /* 1110 */ 259, 474, 172, 382, 238, 238, 1146, 170, 1021, 389,
- /* 1120 */ 47, 47, 1157, 739, 872, 472, 481, 469, 871, 350,
- /* 1130 */ 1214, 83, 475, 389, 4, 1078, 1071, 879, 871, 871,
- /* 1140 */ 873, 874, 21, 90, 91, 1002, 1003, 1004, 478, 251,
- /* 1150 */ 92, 251, 382, 486, 485, 443, 370, 871, 1021, 871,
- /* 1160 */ 871, 873, 224, 241, 306, 441, 301, 440, 211, 1060,
- /* 1170 */ 820, 382, 822, 447, 299, 1059, 484, 1061, 1143, 962,
- /* 1180 */ 430, 796, 484, 472, 1340, 312, 795, 465, 871, 871,
- /* 1190 */ 873, 874, 21, 314, 963, 879, 316, 59, 59, 1002,
- /* 1200 */ 9, 90, 91, 48, 48, 238, 238, 210, 92, 964,
- /* 1210 */ 382, 486, 485, 176, 334, 871, 242, 481, 1193, 238,
- /* 1220 */ 238, 333, 333, 332, 227, 330, 394, 270, 719, 277,
- /* 1230 */ 471, 481, 467, 466, 484, 145, 217, 1201, 1002, 1003,
- /* 1240 */ 1004, 187, 3, 265, 184, 445, 871, 871, 873, 874,
- /* 1250 */ 21, 264, 1337, 450, 1051, 39, 39, 392, 356, 260,
- /* 1260 */ 342, 121, 468, 411, 436, 821, 180, 1094, 1128, 820,
- /* 1270 */ 303, 1021, 1272, 1271, 299, 259, 474, 238, 238, 1002,
- /* 1280 */ 473, 189, 484, 318, 327, 238, 238, 484, 190, 481,
- /* 1290 */ 446, 140, 188, 1343, 238, 238, 1038, 481, 148, 175,
- /* 1300 */ 238, 238, 484, 49, 49, 219, 481, 484, 35, 35,
- /* 1310 */ 1317, 1021, 481, 484, 1035, 484, 1315, 484, 1002, 1003,
- /* 1320 */ 1004, 484, 66, 36, 36, 194, 352, 484, 38, 38,
- /* 1330 */ 484, 259, 474, 69, 50, 50, 51, 51, 52, 52,
- /* 1340 */ 359, 484, 12, 12, 484, 1198, 484, 158, 53, 53,
- /* 1350 */ 405, 112, 112, 385, 389, 484, 26, 484, 143, 484,
- /* 1360 */ 150, 484, 54, 54, 397, 40, 40, 55, 55, 484,
- /* 1370 */ 79, 484, 153, 1190, 484, 154, 56, 56, 41, 41,
- /* 1380 */ 58, 58, 133, 133, 484, 398, 484, 429, 484, 155,
- /* 1390 */ 134, 134, 135, 135, 484, 63, 63, 484, 341, 484,
- /* 1400 */ 339, 484, 196, 484, 156, 42, 42, 113, 113, 60,
- /* 1410 */ 60, 484, 404, 484, 27, 114, 114, 1204, 115, 115,
- /* 1420 */ 111, 111, 132, 132, 131, 131, 1266, 418, 484, 162,
- /* 1430 */ 484, 200, 119, 119, 118, 118, 484, 74, 424, 484,
- /* 1440 */ 1286, 484, 231, 484, 202, 484, 167, 286, 427, 116,
- /* 1450 */ 116, 117, 117, 290, 203, 442, 1062, 62, 62, 204,
- /* 1460 */ 64, 64, 61, 61, 33, 33, 37, 37, 344, 372,
- /* 1470 */ 1114, 1105, 748, 1113, 374, 1112, 254, 458, 1086, 255,
- /* 1480 */ 345, 1085, 302, 1084, 1355, 78, 1154, 311, 1104, 449,
- /* 1490 */ 452, 1155, 1153, 218, 7, 313, 315, 320, 1152, 85,
- /* 1500 */ 1252, 317, 109, 80, 463, 225, 461, 1068, 25, 487,
- /* 1510 */ 997, 323, 257, 226, 229, 228, 1136, 324, 325, 326,
- /* 1520 */ 488, 136, 1057, 1052, 1302, 1303, 1301, 706, 1300, 137,
- /* 1530 */ 122, 138, 383, 173, 1082, 261, 186, 252, 1081, 65,
- /* 1540 */ 387, 120, 938, 936, 855, 353, 149, 1079, 139, 151,
- /* 1550 */ 192, 780, 195, 276, 952, 157, 141, 361, 70, 363,
- /* 1560 */ 859, 159, 71, 72, 142, 73, 955, 354, 147, 197,
- /* 1570 */ 198, 951, 130, 16, 199, 285, 216, 1032, 201, 423,
- /* 1580 */ 164, 944, 163, 28, 721, 428, 304, 165, 205, 759,
- /* 1590 */ 75, 432, 298, 17, 18, 437, 76, 253, 878, 144,
- /* 1600 */ 877, 906, 77, 986, 30, 448, 987, 31, 451, 181,
- /* 1610 */ 234, 236, 168, 828, 823, 89, 910, 921, 81, 907,
- /* 1620 */ 215, 905, 909, 961, 960, 19, 221, 20, 220, 22,
- /* 1630 */ 32, 331, 876, 731, 94, 790, 794, 8, 992, 222,
- /* 1640 */ 480, 328, 1048, 1048, 1048, 1048, 1048, 1048, 1048, 1048,
- /* 1650 */ 223, 1048, 1048, 1048, 1048, 1348, 1347,
+ /* 0 */ 368, 105, 102, 197, 105, 102, 197, 515, 1124, 1,
+ /* 10 */ 1, 520, 2, 1128, 515, 1192, 1171, 1456, 275, 370,
+ /* 20 */ 127, 1389, 1197, 1197, 1192, 1166, 178, 1205, 64, 64,
+ /* 30 */ 477, 887, 322, 428, 348, 37, 37, 808, 362, 888,
+ /* 40 */ 509, 509, 509, 112, 113, 103, 1100, 1100, 953, 956,
+ /* 50 */ 946, 946, 110, 110, 111, 111, 111, 111, 365, 252,
+ /* 60 */ 252, 515, 252, 252, 497, 515, 309, 515, 459, 515,
+ /* 70 */ 1079, 491, 512, 478, 6, 512, 809, 134, 498, 228,
+ /* 80 */ 194, 428, 37, 37, 515, 208, 64, 64, 64, 64,
+ /* 90 */ 13, 13, 109, 109, 109, 109, 108, 108, 107, 107,
+ /* 100 */ 107, 106, 401, 258, 381, 13, 13, 398, 397, 428,
+ /* 110 */ 252, 252, 370, 476, 405, 1104, 1079, 1080, 1081, 386,
+ /* 120 */ 1106, 390, 497, 512, 497, 1423, 1419, 304, 1105, 307,
+ /* 130 */ 1256, 496, 370, 499, 16, 16, 112, 113, 103, 1100,
+ /* 140 */ 1100, 953, 956, 946, 946, 110, 110, 111, 111, 111,
+ /* 150 */ 111, 262, 1107, 495, 1107, 401, 112, 113, 103, 1100,
+ /* 160 */ 1100, 953, 956, 946, 946, 110, 110, 111, 111, 111,
+ /* 170 */ 111, 129, 1425, 343, 1420, 339, 1059, 492, 1057, 263,
+ /* 180 */ 73, 105, 102, 197, 994, 109, 109, 109, 109, 108,
+ /* 190 */ 108, 107, 107, 107, 106, 401, 370, 111, 111, 111,
+ /* 200 */ 111, 104, 492, 89, 1432, 109, 109, 109, 109, 108,
+ /* 210 */ 108, 107, 107, 107, 106, 401, 111, 111, 111, 111,
+ /* 220 */ 112, 113, 103, 1100, 1100, 953, 956, 946, 946, 110,
+ /* 230 */ 110, 111, 111, 111, 111, 109, 109, 109, 109, 108,
+ /* 240 */ 108, 107, 107, 107, 106, 401, 114, 108, 108, 107,
+ /* 250 */ 107, 107, 106, 401, 109, 109, 109, 109, 108, 108,
+ /* 260 */ 107, 107, 107, 106, 401, 152, 399, 399, 399, 109,
+ /* 270 */ 109, 109, 109, 108, 108, 107, 107, 107, 106, 401,
+ /* 280 */ 178, 493, 1412, 434, 1037, 1486, 1079, 515, 1486, 370,
+ /* 290 */ 421, 297, 357, 412, 74, 1079, 109, 109, 109, 109,
+ /* 300 */ 108, 108, 107, 107, 107, 106, 401, 1413, 37, 37,
+ /* 310 */ 1431, 274, 506, 112, 113, 103, 1100, 1100, 953, 956,
+ /* 320 */ 946, 946, 110, 110, 111, 111, 111, 111, 1436, 520,
+ /* 330 */ 2, 1128, 1079, 1080, 1081, 430, 275, 1079, 127, 366,
+ /* 340 */ 933, 1079, 1080, 1081, 220, 1205, 913, 458, 455, 454,
+ /* 350 */ 392, 167, 515, 1035, 152, 445, 924, 453, 152, 874,
+ /* 360 */ 923, 289, 109, 109, 109, 109, 108, 108, 107, 107,
+ /* 370 */ 107, 106, 401, 13, 13, 261, 853, 252, 252, 227,
+ /* 380 */ 106, 401, 370, 1079, 1080, 1081, 311, 388, 1079, 296,
+ /* 390 */ 512, 923, 923, 925, 231, 323, 1255, 1388, 1423, 490,
+ /* 400 */ 274, 506, 12, 208, 274, 506, 112, 113, 103, 1100,
+ /* 410 */ 1100, 953, 956, 946, 946, 110, 110, 111, 111, 111,
+ /* 420 */ 111, 1440, 286, 1128, 288, 1079, 1097, 247, 275, 1098,
+ /* 430 */ 127, 387, 405, 389, 1079, 1080, 1081, 1205, 159, 238,
+ /* 440 */ 255, 321, 461, 316, 460, 225, 790, 105, 102, 197,
+ /* 450 */ 513, 314, 842, 842, 445, 109, 109, 109, 109, 108,
+ /* 460 */ 108, 107, 107, 107, 106, 401, 515, 514, 515, 252,
+ /* 470 */ 252, 1079, 1080, 1081, 435, 370, 1098, 933, 1460, 794,
+ /* 480 */ 274, 506, 512, 105, 102, 197, 336, 63, 63, 64,
+ /* 490 */ 64, 27, 790, 924, 287, 208, 1354, 923, 515, 112,
+ /* 500 */ 113, 103, 1100, 1100, 953, 956, 946, 946, 110, 110,
+ /* 510 */ 111, 111, 111, 111, 107, 107, 107, 106, 401, 49,
+ /* 520 */ 49, 515, 28, 1079, 405, 497, 421, 297, 923, 923,
+ /* 530 */ 925, 186, 468, 1079, 467, 999, 999, 442, 515, 1079,
+ /* 540 */ 334, 515, 45, 45, 1083, 342, 173, 168, 109, 109,
+ /* 550 */ 109, 109, 108, 108, 107, 107, 107, 106, 401, 13,
+ /* 560 */ 13, 205, 13, 13, 252, 252, 1195, 1195, 370, 1079,
+ /* 570 */ 1080, 1081, 787, 265, 5, 359, 494, 512, 469, 1079,
+ /* 580 */ 1080, 1081, 398, 397, 1079, 1079, 1080, 1081, 3, 282,
+ /* 590 */ 1079, 1083, 112, 113, 103, 1100, 1100, 953, 956, 946,
+ /* 600 */ 946, 110, 110, 111, 111, 111, 111, 252, 252, 1015,
+ /* 610 */ 220, 1079, 873, 458, 455, 454, 943, 943, 954, 957,
+ /* 620 */ 512, 252, 252, 453, 1016, 1079, 445, 1107, 1209, 1107,
+ /* 630 */ 1079, 1080, 1081, 515, 512, 426, 1079, 1080, 1081, 1017,
+ /* 640 */ 512, 109, 109, 109, 109, 108, 108, 107, 107, 107,
+ /* 650 */ 106, 401, 1052, 515, 50, 50, 515, 1079, 1080, 1081,
+ /* 660 */ 828, 370, 1051, 379, 411, 1064, 1358, 207, 408, 773,
+ /* 670 */ 829, 1079, 1080, 1081, 64, 64, 322, 64, 64, 1302,
+ /* 680 */ 947, 411, 410, 1358, 1360, 112, 113, 103, 1100, 1100,
+ /* 690 */ 953, 956, 946, 946, 110, 110, 111, 111, 111, 111,
+ /* 700 */ 294, 482, 515, 1037, 1487, 515, 434, 1487, 354, 1120,
+ /* 710 */ 483, 996, 913, 485, 466, 996, 132, 178, 33, 450,
+ /* 720 */ 1203, 136, 406, 64, 64, 479, 64, 64, 419, 369,
+ /* 730 */ 283, 1146, 252, 252, 109, 109, 109, 109, 108, 108,
+ /* 740 */ 107, 107, 107, 106, 401, 512, 224, 440, 411, 266,
+ /* 750 */ 1358, 266, 252, 252, 370, 296, 416, 284, 934, 396,
+ /* 760 */ 976, 470, 400, 252, 252, 512, 9, 473, 231, 500,
+ /* 770 */ 354, 1036, 1035, 1488, 355, 374, 512, 1121, 112, 113,
+ /* 780 */ 103, 1100, 1100, 953, 956, 946, 946, 110, 110, 111,
+ /* 790 */ 111, 111, 111, 252, 252, 1015, 515, 1347, 295, 252,
+ /* 800 */ 252, 252, 252, 1098, 375, 249, 512, 445, 872, 322,
+ /* 810 */ 1016, 480, 512, 195, 512, 434, 273, 15, 15, 515,
+ /* 820 */ 314, 515, 95, 515, 93, 1017, 367, 109, 109, 109,
+ /* 830 */ 109, 108, 108, 107, 107, 107, 106, 401, 515, 1121,
+ /* 840 */ 39, 39, 51, 51, 52, 52, 503, 370, 515, 1204,
+ /* 850 */ 1098, 918, 439, 341, 133, 436, 223, 222, 221, 53,
+ /* 860 */ 53, 322, 1400, 761, 762, 763, 515, 370, 88, 54,
+ /* 870 */ 54, 112, 113, 103, 1100, 1100, 953, 956, 946, 946,
+ /* 880 */ 110, 110, 111, 111, 111, 111, 407, 55, 55, 196,
+ /* 890 */ 515, 112, 113, 103, 1100, 1100, 953, 956, 946, 946,
+ /* 900 */ 110, 110, 111, 111, 111, 111, 135, 264, 1149, 376,
+ /* 910 */ 515, 40, 40, 515, 872, 515, 993, 515, 993, 116,
+ /* 920 */ 109, 109, 109, 109, 108, 108, 107, 107, 107, 106,
+ /* 930 */ 401, 41, 41, 515, 43, 43, 44, 44, 56, 56,
+ /* 940 */ 109, 109, 109, 109, 108, 108, 107, 107, 107, 106,
+ /* 950 */ 401, 515, 379, 515, 57, 57, 515, 799, 515, 379,
+ /* 960 */ 515, 445, 200, 515, 323, 515, 1397, 515, 1459, 515,
+ /* 970 */ 1287, 817, 58, 58, 14, 14, 515, 59, 59, 118,
+ /* 980 */ 118, 60, 60, 515, 46, 46, 61, 61, 62, 62,
+ /* 990 */ 47, 47, 515, 190, 189, 91, 515, 140, 140, 515,
+ /* 1000 */ 394, 515, 277, 1200, 141, 141, 515, 1115, 515, 992,
+ /* 1010 */ 515, 992, 515, 69, 69, 370, 278, 48, 48, 259,
+ /* 1020 */ 65, 65, 119, 119, 246, 246, 260, 66, 66, 120,
+ /* 1030 */ 120, 121, 121, 117, 117, 370, 515, 512, 383, 112,
+ /* 1040 */ 113, 103, 1100, 1100, 953, 956, 946, 946, 110, 110,
+ /* 1050 */ 111, 111, 111, 111, 515, 872, 515, 139, 139, 112,
+ /* 1060 */ 113, 103, 1100, 1100, 953, 956, 946, 946, 110, 110,
+ /* 1070 */ 111, 111, 111, 111, 1287, 138, 138, 125, 125, 515,
+ /* 1080 */ 12, 515, 281, 1287, 515, 445, 131, 1287, 109, 109,
+ /* 1090 */ 109, 109, 108, 108, 107, 107, 107, 106, 401, 515,
+ /* 1100 */ 124, 124, 122, 122, 515, 123, 123, 515, 109, 109,
+ /* 1110 */ 109, 109, 108, 108, 107, 107, 107, 106, 401, 515,
+ /* 1120 */ 68, 68, 463, 783, 515, 70, 70, 302, 67, 67,
+ /* 1130 */ 1032, 253, 253, 356, 1287, 191, 196, 1433, 465, 1301,
+ /* 1140 */ 38, 38, 384, 94, 512, 42, 42, 177, 848, 274,
+ /* 1150 */ 506, 385, 420, 847, 1356, 441, 508, 376, 377, 153,
+ /* 1160 */ 423, 872, 432, 370, 224, 251, 194, 887, 182, 293,
+ /* 1170 */ 783, 848, 88, 254, 466, 888, 847, 915, 807, 806,
+ /* 1180 */ 230, 1241, 910, 370, 17, 413, 797, 112, 113, 103,
+ /* 1190 */ 1100, 1100, 953, 956, 946, 946, 110, 110, 111, 111,
+ /* 1200 */ 111, 111, 395, 814, 815, 1175, 983, 112, 101, 103,
+ /* 1210 */ 1100, 1100, 953, 956, 946, 946, 110, 110, 111, 111,
+ /* 1220 */ 111, 111, 375, 422, 427, 429, 298, 230, 230, 88,
+ /* 1230 */ 1240, 451, 312, 797, 226, 88, 109, 109, 109, 109,
+ /* 1240 */ 108, 108, 107, 107, 107, 106, 401, 86, 433, 979,
+ /* 1250 */ 927, 881, 226, 983, 230, 415, 109, 109, 109, 109,
+ /* 1260 */ 108, 108, 107, 107, 107, 106, 401, 320, 845, 781,
+ /* 1270 */ 846, 100, 130, 100, 1403, 290, 370, 319, 1377, 1376,
+ /* 1280 */ 437, 1449, 299, 1237, 303, 306, 308, 310, 1188, 1174,
+ /* 1290 */ 1173, 1172, 315, 324, 325, 1228, 370, 927, 1249, 271,
+ /* 1300 */ 1286, 113, 103, 1100, 1100, 953, 956, 946, 946, 110,
+ /* 1310 */ 110, 111, 111, 111, 111, 1224, 1235, 502, 501, 1292,
+ /* 1320 */ 1221, 1155, 103, 1100, 1100, 953, 956, 946, 946, 110,
+ /* 1330 */ 110, 111, 111, 111, 111, 1148, 1137, 1136, 1138, 1443,
+ /* 1340 */ 446, 244, 184, 98, 507, 188, 4, 353, 327, 109,
+ /* 1350 */ 109, 109, 109, 108, 108, 107, 107, 107, 106, 401,
+ /* 1360 */ 510, 329, 331, 199, 414, 456, 292, 285, 318, 109,
+ /* 1370 */ 109, 109, 109, 108, 108, 107, 107, 107, 106, 401,
+ /* 1380 */ 11, 1271, 1279, 402, 361, 192, 1171, 1351, 431, 505,
+ /* 1390 */ 346, 1350, 333, 98, 507, 504, 4, 187, 1446, 1115,
+ /* 1400 */ 233, 1396, 155, 1394, 1112, 152, 72, 75, 378, 425,
+ /* 1410 */ 510, 165, 149, 157, 933, 1276, 86, 30, 1268, 417,
+ /* 1420 */ 96, 96, 8, 160, 161, 162, 163, 97, 418, 402,
+ /* 1430 */ 517, 516, 449, 402, 923, 210, 358, 424, 1282, 438,
+ /* 1440 */ 169, 214, 360, 1345, 80, 504, 31, 444, 1365, 301,
+ /* 1450 */ 245, 274, 506, 216, 174, 305, 488, 447, 217, 462,
+ /* 1460 */ 1139, 487, 218, 363, 933, 923, 923, 925, 926, 24,
+ /* 1470 */ 96, 96, 1191, 1190, 1189, 391, 1182, 97, 1163, 402,
+ /* 1480 */ 517, 516, 799, 364, 923, 1162, 317, 1161, 98, 507,
+ /* 1490 */ 1181, 4, 1458, 472, 393, 269, 270, 475, 481, 1232,
+ /* 1500 */ 85, 1233, 326, 328, 232, 510, 495, 1231, 330, 98,
+ /* 1510 */ 507, 1230, 4, 486, 335, 923, 923, 925, 926, 24,
+ /* 1520 */ 1435, 1068, 404, 181, 336, 256, 510, 115, 402, 332,
+ /* 1530 */ 352, 352, 351, 241, 349, 1214, 1414, 770, 338, 10,
+ /* 1540 */ 504, 340, 272, 92, 1331, 1213, 87, 183, 484, 402,
+ /* 1550 */ 201, 488, 280, 239, 344, 345, 489, 1145, 29, 933,
+ /* 1560 */ 279, 504, 1074, 518, 240, 96, 96, 242, 243, 519,
+ /* 1570 */ 1134, 1129, 97, 154, 402, 517, 516, 372, 373, 923,
+ /* 1580 */ 933, 142, 143, 128, 1381, 267, 96, 96, 852, 757,
+ /* 1590 */ 203, 144, 403, 97, 1382, 402, 517, 516, 204, 1380,
+ /* 1600 */ 923, 146, 1379, 1159, 1158, 71, 1156, 276, 202, 185,
+ /* 1610 */ 923, 923, 925, 926, 24, 198, 257, 126, 991, 989,
+ /* 1620 */ 907, 98, 507, 156, 4, 145, 158, 206, 831, 209,
+ /* 1630 */ 291, 923, 923, 925, 926, 24, 1005, 911, 510, 164,
+ /* 1640 */ 147, 380, 371, 382, 166, 76, 77, 274, 506, 148,
+ /* 1650 */ 78, 79, 1008, 211, 212, 1004, 137, 213, 18, 300,
+ /* 1660 */ 230, 402, 997, 1109, 443, 215, 32, 170, 171, 772,
+ /* 1670 */ 409, 448, 319, 504, 219, 172, 452, 81, 19, 457,
+ /* 1680 */ 313, 20, 82, 268, 488, 150, 810, 179, 83, 487,
+ /* 1690 */ 464, 151, 933, 180, 959, 84, 1040, 34, 96, 96,
+ /* 1700 */ 471, 1041, 35, 474, 193, 97, 248, 402, 517, 516,
+ /* 1710 */ 1068, 404, 923, 250, 256, 880, 229, 175, 875, 352,
+ /* 1720 */ 352, 351, 241, 349, 100, 21, 770, 22, 1054, 1056,
+ /* 1730 */ 7, 98, 507, 1045, 4, 337, 1058, 23, 974, 201,
+ /* 1740 */ 176, 280, 88, 923, 923, 925, 926, 24, 510, 279,
+ /* 1750 */ 960, 958, 962, 1014, 963, 1013, 235, 234, 25, 36,
+ /* 1760 */ 99, 90, 507, 928, 4, 511, 350, 782, 26, 841,
+ /* 1770 */ 236, 402, 347, 1069, 237, 1125, 1125, 1451, 510, 203,
+ /* 1780 */ 1450, 1125, 1125, 504, 1125, 1125, 1125, 204, 1125, 1125,
+ /* 1790 */ 146, 1125, 1125, 1125, 1125, 1125, 1125, 202, 1125, 1125,
+ /* 1800 */ 1125, 402, 933, 1125, 1125, 1125, 1125, 1125, 96, 96,
+ /* 1810 */ 1125, 1125, 1125, 504, 1125, 97, 1125, 402, 517, 516,
+ /* 1820 */ 1125, 1125, 923, 1125, 1125, 1125, 1125, 1125, 1125, 1125,
+ /* 1830 */ 1125, 371, 933, 1125, 1125, 1125, 274, 506, 96, 96,
+ /* 1840 */ 1125, 1125, 1125, 1125, 1125, 97, 1125, 402, 517, 516,
+ /* 1850 */ 1125, 1125, 923, 923, 923, 925, 926, 24, 1125, 409,
+ /* 1860 */ 1125, 1125, 1125, 256, 1125, 1125, 1125, 1125, 352, 352,
+ /* 1870 */ 351, 241, 349, 1125, 1125, 770, 1125, 1125, 1125, 1125,
+ /* 1880 */ 1125, 1125, 1125, 923, 923, 925, 926, 24, 201, 1125,
+ /* 1890 */ 280, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 279, 1125,
+ /* 1900 */ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125,
+ /* 1910 */ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125,
+ /* 1920 */ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 203, 1125,
+ /* 1930 */ 1125, 1125, 1125, 1125, 1125, 1125, 204, 1125, 1125, 146,
+ /* 1940 */ 1125, 1125, 1125, 1125, 1125, 1125, 202, 1125, 1125, 1125,
+ /* 1950 */ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125,
+ /* 1960 */ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125,
+ /* 1970 */ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125,
+ /* 1980 */ 371, 1125, 1125, 1125, 1125, 274, 506, 1125, 1125, 1125,
+ /* 1990 */ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125,
+ /* 2000 */ 1125, 1125, 1125, 1125, 1125, 1125, 1125, 1125, 409,
};
static const YYCODETYPE yy_lookahead[] = {
- /* 0 */ 174, 226, 227, 228, 226, 227, 228, 172, 145, 146,
- /* 10 */ 147, 148, 149, 150, 153, 169, 170, 171, 155, 19,
- /* 20 */ 157, 246, 192, 193, 177, 181, 182, 164, 169, 170,
- /* 30 */ 171, 31, 164, 153, 190, 174, 175, 187, 153, 39,
- /* 40 */ 7, 8, 9, 43, 44, 45, 46, 47, 48, 49,
- /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 174, 196,
- /* 60 */ 197, 226, 227, 228, 196, 197, 46, 47, 48, 49,
- /* 70 */ 209, 208, 19, 226, 227, 228, 208, 174, 177, 26,
- /* 80 */ 195, 213, 214, 22, 221, 85, 86, 87, 88, 89,
- /* 90 */ 90, 91, 92, 93, 94, 95, 43, 44, 45, 46,
- /* 100 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
- /* 110 */ 57, 172, 249, 153, 53, 153, 147, 148, 149, 150,
- /* 120 */ 22, 23, 69, 103, 155, 19, 157, 226, 227, 228,
- /* 130 */ 94, 95, 247, 164, 174, 175, 174, 175, 85, 86,
- /* 140 */ 87, 88, 89, 90, 91, 92, 93, 94, 95, 43,
- /* 150 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- /* 160 */ 54, 55, 56, 57, 153, 196, 197, 153, 153, 209,
- /* 170 */ 210, 209, 210, 67, 95, 161, 237, 208, 19, 165,
- /* 180 */ 165, 242, 84, 24, 91, 92, 93, 94, 95, 223,
- /* 190 */ 221, 85, 86, 87, 88, 89, 90, 91, 92, 93,
- /* 200 */ 94, 95, 43, 44, 45, 46, 47, 48, 49, 50,
- /* 210 */ 51, 52, 53, 54, 55, 56, 57, 153, 249, 85,
- /* 220 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
- /* 230 */ 219, 19, 109, 110, 111, 23, 89, 90, 91, 92,
- /* 240 */ 93, 94, 95, 73, 85, 86, 87, 88, 89, 90,
- /* 250 */ 91, 92, 93, 94, 95, 43, 44, 45, 46, 47,
- /* 260 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- /* 270 */ 153, 22, 23, 101, 173, 26, 104, 105, 106, 109,
- /* 280 */ 110, 111, 181, 11, 19, 59, 114, 73, 23, 110,
- /* 290 */ 111, 174, 175, 116, 80, 118, 119, 85, 86, 87,
- /* 300 */ 88, 89, 90, 91, 92, 93, 94, 95, 43, 44,
- /* 310 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
- /* 320 */ 55, 56, 57, 109, 98, 99, 100, 101, 83, 153,
- /* 330 */ 104, 105, 106, 84, 120, 121, 153, 19, 192, 193,
- /* 340 */ 114, 23, 89, 90, 99, 59, 23, 230, 103, 26,
- /* 350 */ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
- /* 360 */ 95, 43, 44, 45, 46, 47, 48, 49, 50, 51,
- /* 370 */ 52, 53, 54, 55, 56, 57, 153, 91, 153, 134,
- /* 380 */ 135, 136, 110, 111, 98, 99, 100, 134, 153, 136,
- /* 390 */ 19, 22, 23, 26, 23, 26, 80, 174, 175, 174,
- /* 400 */ 175, 59, 219, 85, 86, 87, 88, 89, 90, 91,
- /* 410 */ 92, 93, 94, 95, 43, 44, 45, 46, 47, 48,
- /* 420 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 16,
- /* 430 */ 153, 22, 209, 210, 209, 210, 120, 121, 196, 197,
- /* 440 */ 98, 99, 100, 19, 46, 22, 23, 23, 252, 253,
- /* 450 */ 208, 174, 175, 84, 219, 153, 85, 86, 87, 88,
- /* 460 */ 89, 90, 91, 92, 93, 94, 95, 43, 44, 45,
- /* 470 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
- /* 480 */ 56, 57, 153, 153, 153, 153, 209, 120, 121, 76,
- /* 490 */ 153, 78, 109, 110, 111, 97, 19, 153, 89, 90,
- /* 500 */ 198, 59, 183, 174, 175, 174, 175, 84, 153, 85,
- /* 510 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
- /* 520 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- /* 530 */ 53, 54, 55, 56, 57, 16, 197, 153, 22, 153,
- /* 540 */ 153, 99, 198, 12, 153, 196, 197, 208, 153, 153,
- /* 550 */ 195, 183, 19, 23, 222, 142, 26, 208, 27, 153,
- /* 560 */ 174, 175, 85, 86, 87, 88, 89, 90, 91, 92,
- /* 570 */ 93, 94, 95, 42, 188, 59, 43, 44, 45, 46,
- /* 580 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
- /* 590 */ 57, 195, 22, 198, 63, 76, 153, 78, 167, 168,
- /* 600 */ 153, 195, 167, 168, 73, 153, 222, 153, 19, 222,
- /* 610 */ 153, 220, 153, 24, 98, 99, 100, 140, 85, 86,
- /* 620 */ 87, 88, 89, 90, 91, 92, 93, 94, 95, 59,
- /* 630 */ 100, 153, 43, 44, 45, 46, 47, 48, 49, 50,
- /* 640 */ 51, 52, 53, 54, 55, 56, 57, 195, 153, 195,
- /* 650 */ 153, 153, 174, 175, 26, 125, 120, 121, 153, 213,
- /* 660 */ 214, 19, 153, 220, 153, 153, 188, 220, 98, 99,
- /* 670 */ 100, 174, 175, 140, 85, 86, 87, 88, 89, 90,
- /* 680 */ 91, 92, 93, 94, 95, 43, 44, 45, 46, 47,
+ /* 0 */ 184, 238, 239, 240, 238, 239, 240, 163, 155, 156,
+ /* 10 */ 157, 158, 159, 160, 163, 191, 192, 183, 165, 19,
+ /* 20 */ 167, 258, 202, 203, 200, 191, 163, 174, 184, 185,
+ /* 30 */ 174, 31, 163, 163, 171, 184, 185, 35, 175, 39,
+ /* 40 */ 179, 180, 181, 43, 44, 45, 46, 47, 48, 49,
+ /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 184, 206,
+ /* 60 */ 207, 163, 206, 207, 220, 163, 16, 163, 66, 163,
+ /* 70 */ 59, 270, 219, 229, 273, 219, 74, 208, 174, 223,
+ /* 80 */ 224, 163, 184, 185, 163, 232, 184, 185, 184, 185,
+ /* 90 */ 184, 185, 92, 93, 94, 95, 96, 97, 98, 99,
+ /* 100 */ 100, 101, 102, 233, 198, 184, 185, 96, 97, 163,
+ /* 110 */ 206, 207, 19, 163, 261, 104, 105, 106, 107, 198,
+ /* 120 */ 109, 119, 220, 219, 220, 274, 275, 77, 117, 79,
+ /* 130 */ 187, 229, 19, 229, 184, 185, 43, 44, 45, 46,
+ /* 140 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ /* 150 */ 57, 233, 141, 134, 143, 102, 43, 44, 45, 46,
+ /* 160 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ /* 170 */ 57, 152, 274, 216, 276, 218, 83, 163, 85, 233,
+ /* 180 */ 67, 238, 239, 240, 11, 92, 93, 94, 95, 96,
+ /* 190 */ 97, 98, 99, 100, 101, 102, 19, 54, 55, 56,
+ /* 200 */ 57, 58, 163, 26, 163, 92, 93, 94, 95, 96,
+ /* 210 */ 97, 98, 99, 100, 101, 102, 54, 55, 56, 57,
+ /* 220 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ /* 230 */ 53, 54, 55, 56, 57, 92, 93, 94, 95, 96,
+ /* 240 */ 97, 98, 99, 100, 101, 102, 69, 96, 97, 98,
+ /* 250 */ 99, 100, 101, 102, 92, 93, 94, 95, 96, 97,
+ /* 260 */ 98, 99, 100, 101, 102, 81, 179, 180, 181, 92,
+ /* 270 */ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
+ /* 280 */ 163, 267, 268, 163, 22, 23, 59, 163, 26, 19,
+ /* 290 */ 117, 118, 175, 109, 24, 59, 92, 93, 94, 95,
+ /* 300 */ 96, 97, 98, 99, 100, 101, 102, 268, 184, 185,
+ /* 310 */ 269, 127, 128, 43, 44, 45, 46, 47, 48, 49,
+ /* 320 */ 50, 51, 52, 53, 54, 55, 56, 57, 157, 158,
+ /* 330 */ 159, 160, 105, 106, 107, 163, 165, 59, 167, 184,
+ /* 340 */ 90, 105, 106, 107, 108, 174, 73, 111, 112, 113,
+ /* 350 */ 19, 22, 163, 91, 81, 163, 106, 121, 81, 132,
+ /* 360 */ 110, 16, 92, 93, 94, 95, 96, 97, 98, 99,
+ /* 370 */ 100, 101, 102, 184, 185, 255, 98, 206, 207, 26,
+ /* 380 */ 101, 102, 19, 105, 106, 107, 23, 198, 59, 116,
+ /* 390 */ 219, 141, 142, 143, 24, 163, 187, 205, 274, 275,
+ /* 400 */ 127, 128, 182, 232, 127, 128, 43, 44, 45, 46,
+ /* 410 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ /* 420 */ 57, 158, 77, 160, 79, 59, 26, 182, 165, 59,
+ /* 430 */ 167, 199, 261, 102, 105, 106, 107, 174, 72, 108,
+ /* 440 */ 109, 110, 111, 112, 113, 114, 59, 238, 239, 240,
+ /* 450 */ 123, 120, 125, 126, 163, 92, 93, 94, 95, 96,
+ /* 460 */ 97, 98, 99, 100, 101, 102, 163, 163, 163, 206,
+ /* 470 */ 207, 105, 106, 107, 254, 19, 106, 90, 197, 23,
+ /* 480 */ 127, 128, 219, 238, 239, 240, 22, 184, 185, 184,
+ /* 490 */ 185, 22, 105, 106, 149, 232, 205, 110, 163, 43,
+ /* 500 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ /* 510 */ 54, 55, 56, 57, 98, 99, 100, 101, 102, 184,
+ /* 520 */ 185, 163, 53, 59, 261, 220, 117, 118, 141, 142,
+ /* 530 */ 143, 131, 174, 59, 229, 116, 117, 118, 163, 59,
+ /* 540 */ 163, 163, 184, 185, 59, 242, 72, 22, 92, 93,
+ /* 550 */ 94, 95, 96, 97, 98, 99, 100, 101, 102, 184,
+ /* 560 */ 185, 24, 184, 185, 206, 207, 202, 203, 19, 105,
+ /* 570 */ 106, 107, 23, 198, 22, 174, 198, 219, 220, 105,
+ /* 580 */ 106, 107, 96, 97, 59, 105, 106, 107, 22, 174,
+ /* 590 */ 59, 106, 43, 44, 45, 46, 47, 48, 49, 50,
+ /* 600 */ 51, 52, 53, 54, 55, 56, 57, 206, 207, 12,
+ /* 610 */ 108, 59, 132, 111, 112, 113, 46, 47, 48, 49,
+ /* 620 */ 219, 206, 207, 121, 27, 59, 163, 141, 207, 143,
+ /* 630 */ 105, 106, 107, 163, 219, 234, 105, 106, 107, 42,
+ /* 640 */ 219, 92, 93, 94, 95, 96, 97, 98, 99, 100,
+ /* 650 */ 101, 102, 76, 163, 184, 185, 163, 105, 106, 107,
+ /* 660 */ 63, 19, 86, 163, 163, 23, 163, 130, 205, 21,
+ /* 670 */ 73, 105, 106, 107, 184, 185, 163, 184, 185, 237,
+ /* 680 */ 110, 180, 181, 180, 181, 43, 44, 45, 46, 47,
/* 690 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- /* 700 */ 243, 189, 243, 198, 172, 250, 251, 117, 31, 201,
- /* 710 */ 26, 139, 122, 141, 19, 220, 39, 29, 220, 211,
- /* 720 */ 24, 33, 153, 164, 153, 164, 19, 85, 86, 87,
- /* 730 */ 88, 89, 90, 91, 92, 93, 94, 95, 43, 44,
- /* 740 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
- /* 750 */ 55, 56, 57, 65, 243, 196, 197, 196, 197, 131,
- /* 760 */ 189, 22, 103, 24, 153, 23, 19, 208, 26, 208,
- /* 770 */ 102, 103, 113, 23, 242, 22, 26, 134, 164, 136,
- /* 780 */ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
- /* 790 */ 95, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- /* 800 */ 53, 54, 55, 56, 57, 98, 153, 153, 124, 153,
- /* 810 */ 196, 197, 23, 23, 61, 26, 26, 19, 23, 123,
- /* 820 */ 23, 26, 208, 26, 7, 8, 153, 22, 174, 175,
- /* 830 */ 174, 175, 85, 86, 87, 88, 89, 90, 91, 92,
- /* 840 */ 93, 94, 95, 45, 46, 47, 48, 49, 50, 51,
- /* 850 */ 52, 53, 54, 55, 56, 57, 19, 20, 59, 22,
- /* 860 */ 111, 59, 164, 23, 59, 23, 26, 153, 26, 59,
- /* 870 */ 153, 72, 23, 36, 72, 26, 35, 23, 59, 134,
- /* 880 */ 26, 136, 133, 85, 86, 87, 88, 89, 90, 91,
- /* 890 */ 92, 93, 94, 95, 196, 197, 59, 98, 99, 100,
- /* 900 */ 98, 99, 100, 98, 99, 100, 208, 66, 71, 99,
- /* 910 */ 54, 55, 56, 57, 58, 74, 153, 80, 99, 19,
- /* 920 */ 83, 223, 23, 26, 153, 26, 89, 90, 54, 55,
- /* 930 */ 56, 57, 153, 96, 153, 98, 99, 100, 22, 153,
- /* 940 */ 103, 85, 86, 87, 88, 89, 90, 91, 92, 93,
- /* 950 */ 94, 95, 183, 112, 158, 174, 175, 120, 121, 85,
- /* 960 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
- /* 970 */ 215, 134, 135, 136, 137, 138, 0, 1, 2, 23,
- /* 980 */ 21, 5, 26, 153, 22, 59, 10, 11, 12, 13,
- /* 990 */ 14, 1, 2, 17, 212, 5, 153, 153, 98, 153,
- /* 1000 */ 10, 11, 12, 13, 14, 108, 30, 17, 32, 193,
- /* 1010 */ 153, 59, 153, 153, 170, 171, 40, 174, 175, 153,
- /* 1020 */ 30, 59, 32, 19, 20, 99, 22, 170, 171, 233,
- /* 1030 */ 40, 188, 236, 174, 175, 153, 153, 153, 79, 123,
- /* 1040 */ 36, 89, 90, 153, 153, 153, 70, 188, 153, 97,
- /* 1050 */ 98, 99, 100, 77, 102, 153, 80, 81, 174, 175,
- /* 1060 */ 70, 99, 110, 59, 105, 174, 175, 77, 153, 238,
- /* 1070 */ 80, 81, 188, 19, 20, 71, 22, 153, 153, 235,
- /* 1080 */ 19, 22, 164, 24, 59, 153, 134, 83, 136, 153,
- /* 1090 */ 36, 115, 235, 89, 90, 91, 120, 121, 153, 153,
- /* 1100 */ 96, 142, 98, 99, 100, 115, 59, 103, 83, 239,
- /* 1110 */ 120, 121, 199, 59, 196, 197, 153, 153, 59, 143,
- /* 1120 */ 174, 175, 153, 98, 99, 71, 208, 153, 103, 165,
- /* 1130 */ 153, 19, 20, 143, 22, 153, 153, 83, 134, 135,
- /* 1140 */ 136, 137, 138, 89, 90, 98, 99, 100, 36, 185,
- /* 1150 */ 96, 187, 98, 99, 100, 91, 95, 103, 99, 134,
- /* 1160 */ 135, 136, 101, 102, 103, 104, 105, 106, 107, 153,
- /* 1170 */ 26, 59, 125, 164, 113, 153, 153, 153, 212, 12,
- /* 1180 */ 19, 117, 153, 71, 153, 212, 122, 164, 134, 135,
- /* 1190 */ 136, 137, 138, 212, 27, 83, 212, 174, 175, 59,
- /* 1200 */ 200, 89, 90, 174, 175, 196, 197, 46, 96, 42,
- /* 1210 */ 98, 99, 100, 172, 151, 103, 5, 208, 203, 196,
- /* 1220 */ 197, 10, 11, 12, 13, 14, 216, 216, 17, 244,
- /* 1230 */ 63, 208, 209, 210, 153, 80, 24, 203, 98, 99,
- /* 1240 */ 100, 30, 22, 32, 100, 164, 134, 135, 136, 137,
- /* 1250 */ 138, 40, 148, 164, 150, 174, 175, 102, 97, 155,
- /* 1260 */ 203, 157, 164, 244, 178, 125, 186, 182, 164, 125,
- /* 1270 */ 177, 59, 177, 177, 113, 120, 121, 196, 197, 59,
- /* 1280 */ 232, 70, 153, 216, 202, 196, 197, 153, 77, 208,
- /* 1290 */ 209, 80, 81, 156, 196, 197, 60, 208, 248, 200,
- /* 1300 */ 196, 197, 153, 174, 175, 123, 208, 153, 174, 175,
- /* 1310 */ 160, 99, 208, 153, 38, 153, 160, 153, 98, 99,
- /* 1320 */ 100, 153, 245, 174, 175, 221, 115, 153, 174, 175,
- /* 1330 */ 153, 120, 121, 245, 174, 175, 174, 175, 174, 175,
- /* 1340 */ 160, 153, 174, 175, 153, 225, 153, 22, 174, 175,
- /* 1350 */ 97, 174, 175, 249, 143, 153, 224, 153, 43, 153,
- /* 1360 */ 191, 153, 174, 175, 18, 174, 175, 174, 175, 153,
- /* 1370 */ 131, 153, 194, 203, 153, 194, 174, 175, 174, 175,
- /* 1380 */ 174, 175, 174, 175, 153, 160, 153, 18, 153, 194,
- /* 1390 */ 174, 175, 174, 175, 153, 174, 175, 153, 225, 153,
- /* 1400 */ 203, 153, 159, 153, 194, 174, 175, 174, 175, 174,
- /* 1410 */ 175, 153, 203, 153, 224, 174, 175, 191, 174, 175,
- /* 1420 */ 174, 175, 174, 175, 174, 175, 203, 160, 153, 191,
- /* 1430 */ 153, 159, 174, 175, 174, 175, 153, 139, 62, 153,
- /* 1440 */ 241, 153, 160, 153, 159, 153, 22, 240, 179, 174,
- /* 1450 */ 175, 174, 175, 160, 159, 97, 160, 174, 175, 159,
- /* 1460 */ 174, 175, 174, 175, 174, 175, 174, 175, 179, 64,
- /* 1470 */ 176, 184, 108, 176, 95, 176, 234, 126, 176, 234,
- /* 1480 */ 179, 178, 176, 176, 176, 97, 218, 217, 184, 179,
- /* 1490 */ 179, 218, 218, 160, 22, 217, 217, 160, 218, 139,
- /* 1500 */ 229, 217, 130, 129, 127, 25, 128, 163, 26, 162,
- /* 1510 */ 13, 206, 231, 154, 6, 154, 207, 205, 204, 203,
- /* 1520 */ 152, 166, 152, 152, 172, 172, 172, 4, 172, 166,
- /* 1530 */ 180, 166, 3, 22, 172, 144, 15, 180, 172, 172,
- /* 1540 */ 82, 16, 23, 23, 121, 254, 132, 172, 112, 124,
- /* 1550 */ 24, 20, 126, 16, 1, 124, 112, 61, 53, 37,
- /* 1560 */ 133, 132, 53, 53, 112, 53, 98, 254, 251, 34,
- /* 1570 */ 123, 1, 5, 22, 97, 142, 26, 75, 123, 41,
- /* 1580 */ 97, 68, 68, 24, 20, 19, 113, 22, 107, 28,
- /* 1590 */ 22, 67, 23, 22, 22, 67, 22, 67, 23, 37,
- /* 1600 */ 23, 23, 26, 23, 22, 24, 23, 22, 24, 123,
- /* 1610 */ 23, 23, 22, 98, 125, 26, 11, 23, 26, 23,
- /* 1620 */ 34, 23, 23, 23, 23, 34, 22, 34, 26, 22,
- /* 1630 */ 22, 15, 23, 23, 22, 117, 23, 22, 1, 123,
- /* 1640 */ 26, 23, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1650 */ 123, 255, 255, 255, 255, 123, 123, 255, 255, 255,
- /* 1660 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1670 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1680 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1690 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1700 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1710 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1720 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1730 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1740 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1750 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1760 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1770 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1780 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1790 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- /* 1800 */ 255, 255,
+ /* 700 */ 174, 163, 163, 22, 23, 163, 163, 26, 22, 23,
+ /* 710 */ 220, 29, 73, 220, 272, 33, 22, 163, 24, 19,
+ /* 720 */ 174, 208, 259, 184, 185, 19, 184, 185, 80, 175,
+ /* 730 */ 230, 174, 206, 207, 92, 93, 94, 95, 96, 97,
+ /* 740 */ 98, 99, 100, 101, 102, 219, 46, 65, 247, 195,
+ /* 750 */ 247, 197, 206, 207, 19, 116, 117, 118, 23, 220,
+ /* 760 */ 112, 174, 220, 206, 207, 219, 22, 174, 24, 174,
+ /* 770 */ 22, 23, 91, 264, 265, 168, 219, 91, 43, 44,
+ /* 780 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ /* 790 */ 55, 56, 57, 206, 207, 12, 163, 149, 255, 206,
+ /* 800 */ 207, 206, 207, 59, 104, 23, 219, 163, 26, 163,
+ /* 810 */ 27, 105, 219, 163, 219, 163, 211, 184, 185, 163,
+ /* 820 */ 120, 163, 146, 163, 148, 42, 221, 92, 93, 94,
+ /* 830 */ 95, 96, 97, 98, 99, 100, 101, 102, 163, 91,
+ /* 840 */ 184, 185, 184, 185, 184, 185, 63, 19, 163, 205,
+ /* 850 */ 106, 23, 245, 163, 208, 248, 116, 117, 118, 184,
+ /* 860 */ 185, 163, 163, 7, 8, 9, 163, 19, 26, 184,
+ /* 870 */ 185, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ /* 880 */ 52, 53, 54, 55, 56, 57, 163, 184, 185, 107,
+ /* 890 */ 163, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ /* 900 */ 52, 53, 54, 55, 56, 57, 208, 255, 177, 178,
+ /* 910 */ 163, 184, 185, 163, 132, 163, 141, 163, 143, 22,
+ /* 920 */ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
+ /* 930 */ 102, 184, 185, 163, 184, 185, 184, 185, 184, 185,
+ /* 940 */ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
+ /* 950 */ 102, 163, 163, 163, 184, 185, 163, 115, 163, 163,
+ /* 960 */ 163, 163, 15, 163, 163, 163, 163, 163, 23, 163,
+ /* 970 */ 163, 26, 184, 185, 184, 185, 163, 184, 185, 184,
+ /* 980 */ 185, 184, 185, 163, 184, 185, 184, 185, 184, 185,
+ /* 990 */ 184, 185, 163, 96, 97, 147, 163, 184, 185, 163,
+ /* 1000 */ 199, 163, 163, 205, 184, 185, 163, 60, 163, 141,
+ /* 1010 */ 163, 143, 163, 184, 185, 19, 163, 184, 185, 230,
+ /* 1020 */ 184, 185, 184, 185, 206, 207, 230, 184, 185, 184,
+ /* 1030 */ 185, 184, 185, 184, 185, 19, 163, 219, 231, 43,
+ /* 1040 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ /* 1050 */ 54, 55, 56, 57, 163, 26, 163, 184, 185, 43,
+ /* 1060 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ /* 1070 */ 54, 55, 56, 57, 163, 184, 185, 184, 185, 163,
+ /* 1080 */ 182, 163, 163, 163, 163, 163, 22, 163, 92, 93,
+ /* 1090 */ 94, 95, 96, 97, 98, 99, 100, 101, 102, 163,
+ /* 1100 */ 184, 185, 184, 185, 163, 184, 185, 163, 92, 93,
+ /* 1110 */ 94, 95, 96, 97, 98, 99, 100, 101, 102, 163,
+ /* 1120 */ 184, 185, 98, 59, 163, 184, 185, 205, 184, 185,
+ /* 1130 */ 23, 206, 207, 26, 163, 26, 107, 153, 154, 237,
+ /* 1140 */ 184, 185, 231, 147, 219, 184, 185, 249, 124, 127,
+ /* 1150 */ 128, 231, 254, 129, 163, 231, 177, 178, 262, 263,
+ /* 1160 */ 118, 132, 19, 19, 46, 223, 224, 31, 24, 23,
+ /* 1170 */ 106, 124, 26, 22, 272, 39, 129, 23, 109, 110,
+ /* 1180 */ 26, 163, 140, 19, 22, 234, 59, 43, 44, 45,
+ /* 1190 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+ /* 1200 */ 56, 57, 231, 7, 8, 193, 59, 43, 44, 45,
+ /* 1210 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+ /* 1220 */ 56, 57, 104, 61, 23, 23, 23, 26, 26, 26,
+ /* 1230 */ 163, 23, 23, 106, 26, 26, 92, 93, 94, 95,
+ /* 1240 */ 96, 97, 98, 99, 100, 101, 102, 138, 105, 23,
+ /* 1250 */ 59, 23, 26, 106, 26, 163, 92, 93, 94, 95,
+ /* 1260 */ 96, 97, 98, 99, 100, 101, 102, 110, 23, 23,
+ /* 1270 */ 23, 26, 26, 26, 163, 163, 19, 120, 163, 163,
+ /* 1280 */ 163, 130, 163, 163, 163, 163, 163, 163, 163, 193,
+ /* 1290 */ 193, 163, 163, 163, 163, 225, 19, 106, 163, 222,
+ /* 1300 */ 163, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ /* 1310 */ 53, 54, 55, 56, 57, 163, 163, 203, 163, 163,
+ /* 1320 */ 222, 163, 45, 46, 47, 48, 49, 50, 51, 52,
+ /* 1330 */ 53, 54, 55, 56, 57, 163, 163, 163, 163, 163,
+ /* 1340 */ 251, 250, 209, 19, 20, 182, 22, 161, 222, 92,
+ /* 1350 */ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
+ /* 1360 */ 36, 222, 222, 260, 226, 188, 256, 226, 187, 92,
+ /* 1370 */ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
+ /* 1380 */ 210, 213, 213, 59, 213, 196, 192, 187, 256, 244,
+ /* 1390 */ 212, 187, 226, 19, 20, 71, 22, 210, 166, 60,
+ /* 1400 */ 130, 170, 260, 170, 38, 81, 257, 257, 170, 104,
+ /* 1410 */ 36, 22, 43, 201, 90, 236, 138, 235, 213, 18,
+ /* 1420 */ 96, 97, 48, 204, 204, 204, 204, 103, 170, 105,
+ /* 1430 */ 106, 107, 18, 59, 110, 169, 213, 213, 201, 170,
+ /* 1440 */ 201, 169, 236, 213, 146, 71, 235, 62, 253, 252,
+ /* 1450 */ 170, 127, 128, 169, 22, 170, 82, 189, 169, 104,
+ /* 1460 */ 170, 87, 169, 189, 90, 141, 142, 143, 144, 145,
+ /* 1470 */ 96, 97, 186, 186, 186, 64, 194, 103, 186, 105,
+ /* 1480 */ 106, 107, 115, 189, 110, 188, 186, 186, 19, 20,
+ /* 1490 */ 194, 22, 186, 189, 102, 246, 246, 189, 133, 228,
+ /* 1500 */ 104, 228, 227, 227, 170, 36, 134, 228, 227, 19,
+ /* 1510 */ 20, 228, 22, 84, 271, 141, 142, 143, 144, 145,
+ /* 1520 */ 0, 1, 2, 216, 22, 5, 36, 137, 59, 227,
+ /* 1530 */ 10, 11, 12, 13, 14, 217, 269, 17, 216, 22,
+ /* 1540 */ 71, 170, 243, 146, 241, 217, 136, 215, 135, 59,
+ /* 1550 */ 30, 82, 32, 25, 214, 213, 87, 173, 26, 90,
+ /* 1560 */ 40, 71, 13, 172, 164, 96, 97, 164, 6, 162,
+ /* 1570 */ 162, 162, 103, 263, 105, 106, 107, 266, 266, 110,
+ /* 1580 */ 90, 176, 176, 190, 182, 190, 96, 97, 98, 4,
+ /* 1590 */ 70, 176, 3, 103, 182, 105, 106, 107, 78, 182,
+ /* 1600 */ 110, 81, 182, 182, 182, 182, 182, 151, 88, 22,
+ /* 1610 */ 141, 142, 143, 144, 145, 15, 89, 16, 23, 23,
+ /* 1620 */ 128, 19, 20, 139, 22, 119, 131, 24, 20, 133,
+ /* 1630 */ 16, 141, 142, 143, 144, 145, 1, 140, 36, 131,
+ /* 1640 */ 119, 61, 122, 37, 139, 53, 53, 127, 128, 119,
+ /* 1650 */ 53, 53, 105, 34, 130, 1, 5, 104, 22, 149,
+ /* 1660 */ 26, 59, 68, 75, 41, 130, 24, 68, 104, 20,
+ /* 1670 */ 150, 19, 120, 71, 114, 22, 67, 22, 22, 67,
+ /* 1680 */ 23, 22, 22, 67, 82, 37, 28, 23, 138, 87,
+ /* 1690 */ 22, 153, 90, 23, 23, 26, 23, 22, 96, 97,
+ /* 1700 */ 24, 23, 22, 24, 130, 103, 23, 105, 106, 107,
+ /* 1710 */ 1, 2, 110, 23, 5, 105, 34, 22, 132, 10,
+ /* 1720 */ 11, 12, 13, 14, 26, 34, 17, 34, 85, 83,
+ /* 1730 */ 44, 19, 20, 23, 22, 24, 75, 34, 23, 30,
+ /* 1740 */ 26, 32, 26, 141, 142, 143, 144, 145, 36, 40,
+ /* 1750 */ 23, 23, 23, 23, 11, 23, 22, 26, 22, 22,
+ /* 1760 */ 22, 19, 20, 23, 22, 26, 15, 23, 22, 124,
+ /* 1770 */ 130, 59, 23, 1, 130, 277, 277, 130, 36, 70,
+ /* 1780 */ 130, 277, 277, 71, 277, 277, 277, 78, 277, 277,
+ /* 1790 */ 81, 277, 277, 277, 277, 277, 277, 88, 277, 277,
+ /* 1800 */ 277, 59, 90, 277, 277, 277, 277, 277, 96, 97,
+ /* 1810 */ 277, 277, 277, 71, 277, 103, 277, 105, 106, 107,
+ /* 1820 */ 277, 277, 110, 277, 277, 277, 277, 277, 277, 277,
+ /* 1830 */ 277, 122, 90, 277, 277, 277, 127, 128, 96, 97,
+ /* 1840 */ 277, 277, 277, 277, 277, 103, 277, 105, 106, 107,
+ /* 1850 */ 277, 277, 110, 141, 142, 143, 144, 145, 277, 150,
+ /* 1860 */ 277, 277, 277, 5, 277, 277, 277, 277, 10, 11,
+ /* 1870 */ 12, 13, 14, 277, 277, 17, 277, 277, 277, 277,
+ /* 1880 */ 277, 277, 277, 141, 142, 143, 144, 145, 30, 277,
+ /* 1890 */ 32, 277, 277, 277, 277, 277, 277, 277, 40, 277,
+ /* 1900 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ /* 1910 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ /* 1920 */ 277, 277, 277, 277, 277, 277, 277, 277, 70, 277,
+ /* 1930 */ 277, 277, 277, 277, 277, 277, 78, 277, 277, 81,
+ /* 1940 */ 277, 277, 277, 277, 277, 277, 88, 277, 277, 277,
+ /* 1950 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ /* 1960 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ /* 1970 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ /* 1980 */ 122, 277, 277, 277, 277, 127, 128, 277, 277, 277,
+ /* 1990 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ /* 2000 */ 277, 277, 277, 277, 277, 277, 277, 277, 150, 277,
+ /* 2010 */ 277, 277, 277, 277, 277, 277, 277, 277, 277,
};
-#define YY_SHIFT_COUNT (489)
+#define YY_SHIFT_COUNT (520)
#define YY_SHIFT_MIN (0)
-#define YY_SHIFT_MAX (1637)
+#define YY_SHIFT_MAX (1858)
static const unsigned short int yy_shift_ofst[] = {
- /* 0 */ 990, 976, 1211, 837, 837, 316, 1054, 1054, 1054, 1054,
- /* 10 */ 214, 0, 0, 106, 642, 1054, 1054, 1054, 1054, 1054,
- /* 20 */ 1054, 1054, 1054, 952, 952, 226, 1155, 316, 316, 316,
- /* 30 */ 316, 316, 316, 53, 159, 212, 265, 318, 371, 424,
- /* 40 */ 477, 533, 589, 642, 642, 642, 642, 642, 642, 642,
- /* 50 */ 642, 642, 642, 642, 642, 642, 642, 642, 642, 642,
- /* 60 */ 695, 642, 747, 798, 798, 1004, 1054, 1054, 1054, 1054,
- /* 70 */ 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054,
- /* 80 */ 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054,
- /* 90 */ 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1112, 1054, 1054,
- /* 100 */ 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054,
- /* 110 */ 1054, 856, 874, 874, 874, 874, 874, 134, 147, 93,
- /* 120 */ 342, 959, 1161, 253, 253, 342, 367, 367, 367, 367,
- /* 130 */ 179, 36, 79, 1657, 1657, 1657, 1061, 1061, 1061, 516,
- /* 140 */ 799, 516, 516, 531, 531, 802, 249, 369, 342, 342,
- /* 150 */ 342, 342, 342, 342, 342, 342, 342, 342, 342, 342,
- /* 160 */ 342, 342, 342, 342, 342, 342, 342, 342, 342, 272,
- /* 170 */ 442, 442, 536, 1657, 1657, 1657, 1025, 245, 245, 570,
- /* 180 */ 172, 286, 805, 1047, 1140, 1220, 342, 342, 342, 342,
- /* 190 */ 342, 342, 342, 342, 170, 342, 342, 342, 342, 342,
- /* 200 */ 342, 342, 342, 342, 342, 342, 342, 841, 841, 841,
- /* 210 */ 342, 342, 342, 342, 530, 342, 342, 342, 1059, 342,
- /* 220 */ 342, 1167, 342, 342, 342, 342, 342, 342, 342, 342,
- /* 230 */ 123, 688, 177, 1212, 1212, 1212, 1212, 1144, 177, 177,
- /* 240 */ 1064, 409, 33, 628, 707, 707, 900, 628, 628, 900,
- /* 250 */ 897, 323, 398, 677, 677, 677, 707, 572, 684, 590,
- /* 260 */ 739, 1236, 1182, 1182, 1276, 1276, 1182, 1253, 1325, 1315,
- /* 270 */ 1239, 1346, 1346, 1346, 1346, 1182, 1369, 1239, 1239, 1253,
- /* 280 */ 1325, 1315, 1315, 1239, 1182, 1369, 1298, 1376, 1182, 1369,
- /* 290 */ 1424, 1182, 1369, 1182, 1369, 1424, 1358, 1358, 1358, 1405,
- /* 300 */ 1424, 1358, 1364, 1358, 1405, 1358, 1358, 1424, 1379, 1379,
- /* 310 */ 1424, 1351, 1388, 1351, 1388, 1351, 1388, 1351, 1388, 1182,
- /* 320 */ 1472, 1182, 1360, 1372, 1377, 1374, 1378, 1239, 1480, 1482,
- /* 330 */ 1497, 1497, 1508, 1508, 1508, 1657, 1657, 1657, 1657, 1657,
- /* 340 */ 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657, 1657,
- /* 350 */ 1657, 20, 413, 98, 423, 519, 383, 962, 742, 61,
- /* 360 */ 696, 749, 750, 753, 789, 790, 795, 797, 840, 842,
- /* 370 */ 810, 668, 817, 659, 819, 849, 854, 899, 643, 745,
- /* 380 */ 956, 926, 916, 1523, 1529, 1511, 1391, 1521, 1458, 1525,
- /* 390 */ 1519, 1520, 1423, 1414, 1436, 1526, 1425, 1531, 1426, 1537,
- /* 400 */ 1553, 1431, 1427, 1444, 1496, 1522, 1429, 1505, 1509, 1510,
- /* 410 */ 1512, 1452, 1468, 1535, 1447, 1570, 1567, 1551, 1477, 1433,
- /* 420 */ 1513, 1550, 1514, 1502, 1538, 1455, 1483, 1559, 1564, 1566,
- /* 430 */ 1473, 1481, 1565, 1524, 1568, 1571, 1569, 1572, 1528, 1561,
- /* 440 */ 1574, 1530, 1562, 1575, 1577, 1578, 1576, 1580, 1582, 1581,
- /* 450 */ 1583, 1585, 1584, 1486, 1587, 1588, 1515, 1586, 1590, 1489,
- /* 460 */ 1589, 1591, 1592, 1593, 1594, 1596, 1598, 1589, 1599, 1600,
- /* 470 */ 1602, 1601, 1604, 1605, 1607, 1608, 1609, 1610, 1612, 1613,
- /* 480 */ 1615, 1614, 1518, 1516, 1527, 1532, 1533, 1618, 1616, 1637,
+ /* 0 */ 1709, 1520, 1858, 1324, 1324, 277, 1374, 1469, 1602, 1712,
+ /* 10 */ 1712, 1712, 273, 0, 0, 113, 1016, 1712, 1712, 1712,
+ /* 20 */ 1712, 1712, 1712, 1712, 1712, 1712, 1712, 11, 11, 236,
+ /* 30 */ 184, 277, 277, 277, 277, 277, 277, 93, 177, 270,
+ /* 40 */ 363, 456, 549, 642, 735, 828, 848, 996, 1144, 1016,
+ /* 50 */ 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016, 1016,
+ /* 60 */ 1016, 1016, 1016, 1016, 1016, 1016, 1164, 1016, 1257, 1277,
+ /* 70 */ 1277, 1490, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712,
+ /* 80 */ 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712,
+ /* 90 */ 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712, 1712,
+ /* 100 */ 1712, 1712, 1712, 1742, 1712, 1712, 1712, 1712, 1712, 1712,
+ /* 110 */ 1712, 1712, 1712, 1712, 1712, 1712, 1712, 143, 162, 162,
+ /* 120 */ 162, 162, 162, 204, 151, 416, 531, 648, 700, 531,
+ /* 130 */ 486, 486, 531, 353, 353, 353, 353, 409, 279, 53,
+ /* 140 */ 2009, 2009, 331, 331, 331, 329, 366, 329, 329, 597,
+ /* 150 */ 597, 464, 474, 262, 681, 531, 531, 531, 531, 531,
+ /* 160 */ 531, 531, 531, 531, 531, 531, 531, 531, 531, 531,
+ /* 170 */ 531, 531, 531, 531, 531, 531, 531, 173, 485, 984,
+ /* 180 */ 984, 576, 485, 19, 1022, 2009, 2009, 2009, 387, 250,
+ /* 190 */ 250, 525, 502, 278, 552, 227, 480, 566, 531, 531,
+ /* 200 */ 531, 531, 531, 531, 531, 531, 531, 531, 639, 531,
+ /* 210 */ 531, 531, 531, 531, 531, 531, 531, 531, 531, 531,
+ /* 220 */ 531, 2, 2, 2, 531, 531, 531, 531, 782, 531,
+ /* 230 */ 531, 531, 744, 531, 531, 783, 531, 531, 531, 531,
+ /* 240 */ 531, 531, 531, 531, 419, 682, 327, 370, 370, 370,
+ /* 250 */ 370, 1029, 327, 327, 1024, 897, 856, 947, 1109, 706,
+ /* 260 */ 706, 1143, 1109, 1109, 1143, 842, 945, 1118, 1136, 1136,
+ /* 270 */ 1136, 706, 676, 400, 1047, 694, 1339, 1270, 1270, 1366,
+ /* 280 */ 1366, 1270, 1305, 1389, 1369, 1278, 1401, 1401, 1401, 1401,
+ /* 290 */ 1270, 1414, 1278, 1278, 1305, 1389, 1369, 1369, 1278, 1270,
+ /* 300 */ 1414, 1298, 1385, 1270, 1414, 1432, 1270, 1414, 1270, 1414,
+ /* 310 */ 1432, 1355, 1355, 1355, 1411, 1432, 1355, 1367, 1355, 1411,
+ /* 320 */ 1355, 1355, 1432, 1392, 1392, 1432, 1365, 1396, 1365, 1396,
+ /* 330 */ 1365, 1396, 1365, 1396, 1270, 1372, 1429, 1502, 1390, 1372,
+ /* 340 */ 1517, 1270, 1397, 1390, 1410, 1413, 1278, 1528, 1532, 1549,
+ /* 350 */ 1549, 1562, 1562, 1562, 2009, 2009, 2009, 2009, 2009, 2009,
+ /* 360 */ 2009, 2009, 2009, 2009, 2009, 2009, 2009, 2009, 2009, 2009,
+ /* 370 */ 570, 345, 686, 748, 50, 740, 1064, 1107, 469, 537,
+ /* 380 */ 1042, 1146, 1162, 1154, 1201, 1202, 1203, 1208, 1209, 1127,
+ /* 390 */ 1069, 1196, 1157, 1147, 1226, 1228, 1245, 775, 868, 1246,
+ /* 400 */ 1247, 1191, 1151, 1585, 1589, 1587, 1456, 1600, 1527, 1601,
+ /* 410 */ 1595, 1596, 1492, 1484, 1506, 1603, 1495, 1608, 1496, 1614,
+ /* 420 */ 1635, 1508, 1497, 1521, 1580, 1606, 1505, 1592, 1593, 1597,
+ /* 430 */ 1598, 1530, 1547, 1619, 1524, 1654, 1651, 1636, 1553, 1510,
+ /* 440 */ 1594, 1634, 1599, 1588, 1623, 1535, 1564, 1642, 1649, 1652,
+ /* 450 */ 1552, 1560, 1653, 1609, 1655, 1656, 1657, 1659, 1612, 1658,
+ /* 460 */ 1660, 1616, 1648, 1664, 1550, 1668, 1538, 1670, 1671, 1669,
+ /* 470 */ 1673, 1675, 1676, 1678, 1680, 1679, 1574, 1683, 1690, 1610,
+ /* 480 */ 1682, 1695, 1586, 1698, 1691, 1698, 1693, 1643, 1661, 1646,
+ /* 490 */ 1686, 1710, 1711, 1714, 1716, 1703, 1715, 1698, 1727, 1728,
+ /* 500 */ 1729, 1730, 1731, 1732, 1734, 1743, 1736, 1737, 1740, 1744,
+ /* 510 */ 1738, 1746, 1739, 1645, 1640, 1644, 1647, 1650, 1749, 1751,
+ /* 520 */ 1772,
};
-#define YY_REDUCE_COUNT (350)
-#define YY_REDUCE_MIN (-225)
-#define YY_REDUCE_MAX (1375)
+#define YY_REDUCE_COUNT (369)
+#define YY_REDUCE_MIN (-237)
+#define YY_REDUCE_MAX (1424)
static const short yy_reduce_ofst[] = {
- /* 0 */ -137, -31, 1104, 1023, 1081, -132, -40, -38, 223, 225,
- /* 10 */ 698, -153, -99, -225, -165, 386, 478, 843, 859, -139,
- /* 20 */ 884, 117, 277, 844, 857, 964, 559, 561, 614, 918,
- /* 30 */ 1009, 1089, 1098, -222, -222, -222, -222, -222, -222, -222,
- /* 40 */ -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
- /* 50 */ -222, -222, -222, -222, -222, -222, -222, -222, -222, -222,
- /* 60 */ -222, -222, -222, -222, -222, 329, 331, 497, 654, 656,
- /* 70 */ 781, 891, 946, 1029, 1129, 1134, 1149, 1154, 1160, 1162,
- /* 80 */ 1164, 1168, 1174, 1177, 1188, 1191, 1193, 1202, 1204, 1206,
- /* 90 */ 1208, 1216, 1218, 1221, 1231, 1233, 1235, 1241, 1244, 1246,
- /* 100 */ 1248, 1250, 1258, 1260, 1275, 1277, 1283, 1286, 1288, 1290,
- /* 110 */ 1292, -222, -222, -222, -222, -222, -222, -222, -222, -222,
- /* 120 */ -115, 796, -156, -154, -141, 14, 242, 349, 242, 349,
- /* 130 */ -61, -222, -222, -222, -222, -222, 101, 101, 101, 332,
- /* 140 */ 302, 384, 387, -170, 146, 344, 196, 196, 15, 11,
- /* 150 */ 183, 235, 395, 355, 396, 406, 452, 457, 391, 459,
- /* 160 */ 443, 447, 511, 495, 454, 512, 505, 571, 498, 532,
- /* 170 */ 431, 435, 339, 455, 446, 508, -174, -116, -97, -120,
- /* 180 */ -150, 64, 176, 330, 337, 509, 569, 611, 653, 673,
- /* 190 */ 714, 717, 763, 771, -34, 779, 786, 830, 846, 860,
- /* 200 */ 866, 882, 883, 890, 892, 895, 902, 319, 368, 769,
- /* 210 */ 915, 924, 925, 932, 755, 936, 945, 963, 782, 969,
- /* 220 */ 974, 816, 977, 64, 982, 983, 1016, 1022, 1024, 1031,
- /* 230 */ 870, 831, 913, 966, 973, 981, 984, 755, 913, 913,
- /* 240 */ 1000, 1041, 1063, 1015, 1010, 1011, 985, 1034, 1057, 1019,
- /* 250 */ 1086, 1080, 1085, 1093, 1095, 1096, 1067, 1048, 1082, 1099,
- /* 260 */ 1137, 1050, 1150, 1156, 1077, 1088, 1180, 1120, 1132, 1169,
- /* 270 */ 1170, 1178, 1181, 1195, 1210, 1225, 1243, 1197, 1209, 1173,
- /* 280 */ 1190, 1226, 1238, 1223, 1267, 1272, 1199, 1207, 1282, 1285,
- /* 290 */ 1269, 1293, 1295, 1296, 1300, 1289, 1294, 1297, 1299, 1287,
- /* 300 */ 1301, 1302, 1303, 1306, 1304, 1307, 1308, 1310, 1242, 1245,
- /* 310 */ 1311, 1268, 1270, 1273, 1278, 1274, 1279, 1280, 1284, 1333,
- /* 320 */ 1271, 1337, 1281, 1309, 1305, 1312, 1314, 1316, 1344, 1347,
- /* 330 */ 1359, 1361, 1368, 1370, 1371, 1291, 1313, 1317, 1355, 1352,
- /* 340 */ 1353, 1354, 1356, 1363, 1350, 1357, 1362, 1366, 1367, 1375,
- /* 350 */ 1365,
+ /* 0 */ -147, 171, 263, -96, 358, -144, -149, -102, 124, -156,
+ /* 10 */ -98, 305, 401, -57, 209, -237, 245, -94, -79, 189,
+ /* 20 */ 375, 490, 493, 378, 303, 539, 542, 501, 503, 554,
+ /* 30 */ 415, 526, 546, 557, 587, 593, 595, -234, -234, -234,
+ /* 40 */ -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+ /* 50 */ -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+ /* 60 */ -234, -234, -234, -234, -234, -234, -234, -234, -234, -234,
+ /* 70 */ -234, -50, 335, 470, 633, 656, 658, 660, 675, 685,
+ /* 80 */ 703, 727, 747, 750, 752, 754, 770, 788, 790, 793,
+ /* 90 */ 795, 797, 800, 802, 804, 806, 813, 820, 829, 833,
+ /* 100 */ 836, 838, 843, 845, 847, 849, 873, 891, 893, 916,
+ /* 110 */ 918, 921, 936, 941, 944, 956, 961, -234, -234, -234,
+ /* 120 */ -234, -234, -234, -234, -234, -234, 463, 607, -176, 14,
+ /* 130 */ -139, 87, -137, 818, 925, 818, 925, 898, -234, -234,
+ /* 140 */ -234, -234, -166, -166, -166, -130, -131, -82, -54, -180,
+ /* 150 */ 364, 41, 513, 509, 509, 117, 500, 789, 796, 646,
+ /* 160 */ 192, 291, 644, 798, 120, 807, 543, 911, 920, 652,
+ /* 170 */ 924, 922, 232, 698, 801, 971, 39, 220, 731, 442,
+ /* 180 */ 902, -199, 979, -43, 421, 896, 942, 605, -184, -126,
+ /* 190 */ 155, 172, 281, 304, 377, 538, 650, 690, 699, 723,
+ /* 200 */ 803, 839, 853, 919, 991, 1018, 1067, 1092, 951, 1111,
+ /* 210 */ 1112, 1115, 1116, 1117, 1119, 1120, 1121, 1122, 1123, 1124,
+ /* 220 */ 1125, 1012, 1096, 1097, 1128, 1129, 1130, 1131, 1070, 1135,
+ /* 230 */ 1137, 1152, 1077, 1153, 1155, 1114, 1156, 304, 1158, 1172,
+ /* 240 */ 1173, 1174, 1175, 1176, 1089, 1091, 1133, 1098, 1126, 1139,
+ /* 250 */ 1140, 1070, 1133, 1133, 1170, 1163, 1186, 1103, 1168, 1138,
+ /* 260 */ 1141, 1110, 1169, 1171, 1132, 1177, 1189, 1194, 1181, 1200,
+ /* 270 */ 1204, 1166, 1145, 1178, 1187, 1232, 1142, 1231, 1233, 1149,
+ /* 280 */ 1150, 1238, 1179, 1182, 1212, 1205, 1219, 1220, 1221, 1222,
+ /* 290 */ 1258, 1266, 1223, 1224, 1206, 1211, 1237, 1239, 1230, 1269,
+ /* 300 */ 1272, 1195, 1197, 1280, 1284, 1268, 1285, 1289, 1290, 1293,
+ /* 310 */ 1274, 1286, 1287, 1288, 1282, 1294, 1292, 1297, 1300, 1296,
+ /* 320 */ 1301, 1306, 1304, 1249, 1250, 1308, 1271, 1275, 1273, 1276,
+ /* 330 */ 1279, 1281, 1283, 1302, 1334, 1307, 1243, 1267, 1318, 1322,
+ /* 340 */ 1303, 1371, 1299, 1328, 1332, 1340, 1342, 1384, 1391, 1400,
+ /* 350 */ 1403, 1407, 1408, 1409, 1311, 1312, 1310, 1405, 1402, 1412,
+ /* 360 */ 1417, 1420, 1406, 1393, 1395, 1421, 1422, 1423, 1424, 1415,
};
static const YYACTIONTYPE yy_default[] = {
- /* 0 */ 1389, 1389, 1389, 1261, 1046, 1151, 1261, 1261, 1261, 1261,
- /* 10 */ 1046, 1181, 1181, 1312, 1077, 1046, 1046, 1046, 1046, 1046,
- /* 20 */ 1046, 1260, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
- /* 30 */ 1046, 1046, 1046, 1187, 1046, 1046, 1046, 1046, 1262, 1263,
- /* 40 */ 1046, 1046, 1046, 1311, 1313, 1197, 1196, 1195, 1194, 1294,
- /* 50 */ 1168, 1192, 1185, 1189, 1256, 1257, 1255, 1259, 1262, 1263,
- /* 60 */ 1046, 1188, 1226, 1240, 1225, 1046, 1046, 1046, 1046, 1046,
- /* 70 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
- /* 80 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
- /* 90 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
- /* 100 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
- /* 110 */ 1046, 1234, 1239, 1246, 1238, 1235, 1228, 1227, 1229, 1230,
- /* 120 */ 1046, 1067, 1116, 1046, 1046, 1046, 1329, 1328, 1046, 1046,
- /* 130 */ 1077, 1231, 1232, 1243, 1242, 1241, 1319, 1345, 1344, 1046,
- /* 140 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
- /* 150 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
- /* 160 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1077,
- /* 170 */ 1073, 1073, 1046, 1324, 1151, 1142, 1046, 1046, 1046, 1046,
- /* 180 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1316, 1314, 1046,
- /* 190 */ 1276, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
- /* 200 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
- /* 210 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1147, 1046,
- /* 220 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1339,
- /* 230 */ 1046, 1289, 1130, 1147, 1147, 1147, 1147, 1149, 1131, 1129,
- /* 240 */ 1141, 1077, 1053, 1191, 1170, 1170, 1378, 1191, 1191, 1378,
- /* 250 */ 1091, 1359, 1088, 1181, 1181, 1181, 1170, 1258, 1148, 1141,
- /* 260 */ 1046, 1381, 1156, 1156, 1380, 1380, 1156, 1200, 1206, 1119,
- /* 270 */ 1191, 1125, 1125, 1125, 1125, 1156, 1064, 1191, 1191, 1200,
- /* 280 */ 1206, 1119, 1119, 1191, 1156, 1064, 1293, 1375, 1156, 1064,
- /* 290 */ 1269, 1156, 1064, 1156, 1064, 1269, 1117, 1117, 1117, 1106,
- /* 300 */ 1269, 1117, 1091, 1117, 1106, 1117, 1117, 1269, 1273, 1273,
- /* 310 */ 1269, 1174, 1169, 1174, 1169, 1174, 1169, 1174, 1169, 1156,
- /* 320 */ 1264, 1156, 1046, 1186, 1175, 1184, 1182, 1191, 1070, 1109,
- /* 330 */ 1342, 1342, 1338, 1338, 1338, 1386, 1386, 1324, 1354, 1077,
- /* 340 */ 1077, 1077, 1077, 1354, 1093, 1093, 1077, 1077, 1077, 1077,
- /* 350 */ 1354, 1046, 1046, 1046, 1046, 1046, 1046, 1349, 1046, 1278,
- /* 360 */ 1160, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
- /* 370 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
- /* 380 */ 1046, 1046, 1211, 1046, 1049, 1321, 1046, 1046, 1320, 1046,
- /* 390 */ 1046, 1046, 1046, 1046, 1046, 1161, 1046, 1046, 1046, 1046,
- /* 400 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
- /* 410 */ 1046, 1046, 1046, 1046, 1377, 1046, 1046, 1046, 1046, 1046,
- /* 420 */ 1046, 1292, 1291, 1046, 1046, 1158, 1046, 1046, 1046, 1046,
- /* 430 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
- /* 440 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
- /* 450 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
- /* 460 */ 1183, 1046, 1176, 1046, 1046, 1046, 1046, 1368, 1046, 1046,
- /* 470 */ 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046, 1046,
- /* 480 */ 1046, 1363, 1133, 1213, 1046, 1212, 1216, 1046, 1058, 1046,
+ /* 0 */ 1492, 1492, 1492, 1340, 1123, 1229, 1123, 1123, 1123, 1340,
+ /* 10 */ 1340, 1340, 1123, 1259, 1259, 1391, 1154, 1123, 1123, 1123,
+ /* 20 */ 1123, 1123, 1123, 1123, 1339, 1123, 1123, 1123, 1123, 1123,
+ /* 30 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1265, 1123,
+ /* 40 */ 1123, 1123, 1123, 1123, 1341, 1342, 1123, 1123, 1123, 1390,
+ /* 50 */ 1392, 1275, 1274, 1273, 1272, 1373, 1246, 1270, 1263, 1267,
+ /* 60 */ 1335, 1336, 1334, 1338, 1342, 1341, 1123, 1266, 1306, 1320,
+ /* 70 */ 1305, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123,
+ /* 80 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123,
+ /* 90 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123,
+ /* 100 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123,
+ /* 110 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1314, 1319, 1325,
+ /* 120 */ 1318, 1315, 1308, 1307, 1309, 1310, 1123, 1144, 1193, 1123,
+ /* 130 */ 1123, 1123, 1123, 1409, 1408, 1123, 1123, 1154, 1311, 1312,
+ /* 140 */ 1322, 1321, 1398, 1448, 1447, 1123, 1123, 1123, 1123, 1123,
+ /* 150 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123,
+ /* 160 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123,
+ /* 170 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1154, 1150, 1300,
+ /* 180 */ 1299, 1418, 1150, 1253, 1123, 1404, 1229, 1220, 1123, 1123,
+ /* 190 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123,
+ /* 200 */ 1123, 1395, 1393, 1123, 1355, 1123, 1123, 1123, 1123, 1123,
+ /* 210 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123,
+ /* 220 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123,
+ /* 230 */ 1123, 1123, 1225, 1123, 1123, 1123, 1123, 1123, 1123, 1123,
+ /* 240 */ 1123, 1123, 1123, 1442, 1123, 1368, 1207, 1225, 1225, 1225,
+ /* 250 */ 1225, 1227, 1208, 1206, 1219, 1154, 1130, 1484, 1269, 1248,
+ /* 260 */ 1248, 1481, 1269, 1269, 1481, 1168, 1462, 1165, 1259, 1259,
+ /* 270 */ 1259, 1248, 1337, 1226, 1219, 1123, 1484, 1234, 1234, 1483,
+ /* 280 */ 1483, 1234, 1278, 1284, 1196, 1269, 1202, 1202, 1202, 1202,
+ /* 290 */ 1234, 1141, 1269, 1269, 1278, 1284, 1196, 1196, 1269, 1234,
+ /* 300 */ 1141, 1372, 1478, 1234, 1141, 1348, 1234, 1141, 1234, 1141,
+ /* 310 */ 1348, 1194, 1194, 1194, 1183, 1348, 1194, 1168, 1194, 1183,
+ /* 320 */ 1194, 1194, 1348, 1352, 1352, 1348, 1252, 1247, 1252, 1247,
+ /* 330 */ 1252, 1247, 1252, 1247, 1234, 1253, 1417, 1123, 1264, 1253,
+ /* 340 */ 1343, 1234, 1123, 1264, 1262, 1260, 1269, 1147, 1186, 1445,
+ /* 350 */ 1445, 1441, 1441, 1441, 1489, 1489, 1404, 1457, 1154, 1154,
+ /* 360 */ 1154, 1154, 1457, 1170, 1170, 1154, 1154, 1154, 1154, 1457,
+ /* 370 */ 1123, 1123, 1123, 1123, 1123, 1123, 1452, 1123, 1357, 1238,
+ /* 380 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123,
+ /* 390 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123,
+ /* 400 */ 1123, 1123, 1289, 1123, 1126, 1401, 1123, 1123, 1399, 1123,
+ /* 410 */ 1123, 1123, 1123, 1123, 1123, 1239, 1123, 1123, 1123, 1123,
+ /* 420 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123,
+ /* 430 */ 1123, 1123, 1123, 1123, 1480, 1123, 1123, 1123, 1123, 1123,
+ /* 440 */ 1123, 1371, 1370, 1123, 1123, 1236, 1123, 1123, 1123, 1123,
+ /* 450 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123,
+ /* 460 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123,
+ /* 470 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123,
+ /* 480 */ 1123, 1123, 1123, 1261, 1123, 1416, 1123, 1123, 1123, 1123,
+ /* 490 */ 1123, 1123, 1123, 1430, 1254, 1123, 1123, 1471, 1123, 1123,
+ /* 500 */ 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123,
+ /* 510 */ 1123, 1123, 1466, 1210, 1291, 1123, 1290, 1294, 1123, 1135,
+ /* 520 */ 1123,
};
/********** End of lemon-generated parsing tables *****************************/
@@ -142312,11 +146922,18 @@ static const YYCODETYPE yyFallback[] = {
59, /* REPLACE => ID */
59, /* RESTRICT => ID */
59, /* ROW => ID */
+ 59, /* ROWS => ID */
59, /* TRIGGER => ID */
59, /* VACUUM => ID */
59, /* VIEW => ID */
59, /* VIRTUAL => ID */
59, /* WITH => ID */
+ 59, /* CURRENT => ID */
+ 59, /* FOLLOWING => ID */
+ 59, /* PARTITION => ID */
+ 59, /* PRECEDING => ID */
+ 59, /* RANGE => ID */
+ 59, /* UNBOUNDED => ID */
59, /* REINDEX => ID */
59, /* RENAME => ID */
59, /* CTIME_KW => ID */
@@ -142483,185 +147100,207 @@ static const char *const yyTokenName[] = {
/* 73 */ "REPLACE",
/* 74 */ "RESTRICT",
/* 75 */ "ROW",
- /* 76 */ "TRIGGER",
- /* 77 */ "VACUUM",
- /* 78 */ "VIEW",
- /* 79 */ "VIRTUAL",
- /* 80 */ "WITH",
- /* 81 */ "REINDEX",
- /* 82 */ "RENAME",
- /* 83 */ "CTIME_KW",
- /* 84 */ "ANY",
- /* 85 */ "BITAND",
- /* 86 */ "BITOR",
- /* 87 */ "LSHIFT",
- /* 88 */ "RSHIFT",
- /* 89 */ "PLUS",
- /* 90 */ "MINUS",
- /* 91 */ "STAR",
- /* 92 */ "SLASH",
- /* 93 */ "REM",
- /* 94 */ "CONCAT",
- /* 95 */ "COLLATE",
- /* 96 */ "BITNOT",
- /* 97 */ "ON",
- /* 98 */ "INDEXED",
- /* 99 */ "STRING",
- /* 100 */ "JOIN_KW",
- /* 101 */ "CONSTRAINT",
- /* 102 */ "DEFAULT",
- /* 103 */ "NULL",
- /* 104 */ "PRIMARY",
- /* 105 */ "UNIQUE",
- /* 106 */ "CHECK",
- /* 107 */ "REFERENCES",
- /* 108 */ "AUTOINCR",
- /* 109 */ "INSERT",
- /* 110 */ "DELETE",
- /* 111 */ "UPDATE",
- /* 112 */ "SET",
- /* 113 */ "DEFERRABLE",
- /* 114 */ "FOREIGN",
- /* 115 */ "DROP",
- /* 116 */ "UNION",
- /* 117 */ "ALL",
- /* 118 */ "EXCEPT",
- /* 119 */ "INTERSECT",
- /* 120 */ "SELECT",
- /* 121 */ "VALUES",
- /* 122 */ "DISTINCT",
- /* 123 */ "DOT",
- /* 124 */ "FROM",
- /* 125 */ "JOIN",
- /* 126 */ "USING",
- /* 127 */ "ORDER",
- /* 128 */ "GROUP",
- /* 129 */ "HAVING",
- /* 130 */ "LIMIT",
- /* 131 */ "WHERE",
- /* 132 */ "INTO",
- /* 133 */ "NOTHING",
- /* 134 */ "FLOAT",
- /* 135 */ "BLOB",
- /* 136 */ "INTEGER",
- /* 137 */ "VARIABLE",
- /* 138 */ "CASE",
- /* 139 */ "WHEN",
- /* 140 */ "THEN",
- /* 141 */ "ELSE",
- /* 142 */ "INDEX",
- /* 143 */ "ALTER",
- /* 144 */ "ADD",
- /* 145 */ "input",
- /* 146 */ "cmdlist",
- /* 147 */ "ecmd",
- /* 148 */ "cmdx",
- /* 149 */ "explain",
- /* 150 */ "cmd",
- /* 151 */ "transtype",
- /* 152 */ "trans_opt",
- /* 153 */ "nm",
- /* 154 */ "savepoint_opt",
- /* 155 */ "create_table",
- /* 156 */ "create_table_args",
- /* 157 */ "createkw",
- /* 158 */ "temp",
- /* 159 */ "ifnotexists",
- /* 160 */ "dbnm",
- /* 161 */ "columnlist",
- /* 162 */ "conslist_opt",
- /* 163 */ "table_options",
- /* 164 */ "select",
- /* 165 */ "columnname",
- /* 166 */ "carglist",
- /* 167 */ "typetoken",
- /* 168 */ "typename",
- /* 169 */ "signed",
- /* 170 */ "plus_num",
- /* 171 */ "minus_num",
- /* 172 */ "scanpt",
- /* 173 */ "ccons",
- /* 174 */ "term",
- /* 175 */ "expr",
- /* 176 */ "onconf",
- /* 177 */ "sortorder",
- /* 178 */ "autoinc",
- /* 179 */ "eidlist_opt",
- /* 180 */ "refargs",
- /* 181 */ "defer_subclause",
- /* 182 */ "refarg",
- /* 183 */ "refact",
- /* 184 */ "init_deferred_pred_opt",
- /* 185 */ "conslist",
- /* 186 */ "tconscomma",
- /* 187 */ "tcons",
- /* 188 */ "sortlist",
- /* 189 */ "eidlist",
- /* 190 */ "defer_subclause_opt",
- /* 191 */ "orconf",
- /* 192 */ "resolvetype",
- /* 193 */ "raisetype",
- /* 194 */ "ifexists",
- /* 195 */ "fullname",
- /* 196 */ "selectnowith",
- /* 197 */ "oneselect",
- /* 198 */ "wqlist",
- /* 199 */ "multiselect_op",
- /* 200 */ "distinct",
- /* 201 */ "selcollist",
- /* 202 */ "from",
- /* 203 */ "where_opt",
- /* 204 */ "groupby_opt",
- /* 205 */ "having_opt",
- /* 206 */ "orderby_opt",
- /* 207 */ "limit_opt",
- /* 208 */ "values",
- /* 209 */ "nexprlist",
- /* 210 */ "exprlist",
- /* 211 */ "sclp",
- /* 212 */ "as",
- /* 213 */ "seltablist",
- /* 214 */ "stl_prefix",
- /* 215 */ "joinop",
- /* 216 */ "indexed_opt",
- /* 217 */ "on_opt",
- /* 218 */ "using_opt",
- /* 219 */ "xfullname",
- /* 220 */ "idlist",
- /* 221 */ "with",
- /* 222 */ "setlist",
- /* 223 */ "insert_cmd",
- /* 224 */ "idlist_opt",
- /* 225 */ "upsert",
- /* 226 */ "likeop",
- /* 227 */ "between_op",
- /* 228 */ "in_op",
- /* 229 */ "paren_exprlist",
- /* 230 */ "case_operand",
- /* 231 */ "case_exprlist",
- /* 232 */ "case_else",
- /* 233 */ "uniqueflag",
- /* 234 */ "collate",
- /* 235 */ "nmnum",
- /* 236 */ "trigger_decl",
- /* 237 */ "trigger_cmd_list",
- /* 238 */ "trigger_time",
- /* 239 */ "trigger_event",
- /* 240 */ "foreach_clause",
- /* 241 */ "when_clause",
- /* 242 */ "trigger_cmd",
- /* 243 */ "trnm",
- /* 244 */ "tridxby",
- /* 245 */ "database_kw_opt",
- /* 246 */ "key_opt",
- /* 247 */ "add_column_fullname",
- /* 248 */ "kwcolumn_opt",
- /* 249 */ "create_vtab",
- /* 250 */ "vtabarglist",
- /* 251 */ "vtabarg",
- /* 252 */ "vtabargtoken",
- /* 253 */ "lp",
- /* 254 */ "anylist",
+ /* 76 */ "ROWS",
+ /* 77 */ "TRIGGER",
+ /* 78 */ "VACUUM",
+ /* 79 */ "VIEW",
+ /* 80 */ "VIRTUAL",
+ /* 81 */ "WITH",
+ /* 82 */ "CURRENT",
+ /* 83 */ "FOLLOWING",
+ /* 84 */ "PARTITION",
+ /* 85 */ "PRECEDING",
+ /* 86 */ "RANGE",
+ /* 87 */ "UNBOUNDED",
+ /* 88 */ "REINDEX",
+ /* 89 */ "RENAME",
+ /* 90 */ "CTIME_KW",
+ /* 91 */ "ANY",
+ /* 92 */ "BITAND",
+ /* 93 */ "BITOR",
+ /* 94 */ "LSHIFT",
+ /* 95 */ "RSHIFT",
+ /* 96 */ "PLUS",
+ /* 97 */ "MINUS",
+ /* 98 */ "STAR",
+ /* 99 */ "SLASH",
+ /* 100 */ "REM",
+ /* 101 */ "CONCAT",
+ /* 102 */ "COLLATE",
+ /* 103 */ "BITNOT",
+ /* 104 */ "ON",
+ /* 105 */ "INDEXED",
+ /* 106 */ "STRING",
+ /* 107 */ "JOIN_KW",
+ /* 108 */ "CONSTRAINT",
+ /* 109 */ "DEFAULT",
+ /* 110 */ "NULL",
+ /* 111 */ "PRIMARY",
+ /* 112 */ "UNIQUE",
+ /* 113 */ "CHECK",
+ /* 114 */ "REFERENCES",
+ /* 115 */ "AUTOINCR",
+ /* 116 */ "INSERT",
+ /* 117 */ "DELETE",
+ /* 118 */ "UPDATE",
+ /* 119 */ "SET",
+ /* 120 */ "DEFERRABLE",
+ /* 121 */ "FOREIGN",
+ /* 122 */ "DROP",
+ /* 123 */ "UNION",
+ /* 124 */ "ALL",
+ /* 125 */ "EXCEPT",
+ /* 126 */ "INTERSECT",
+ /* 127 */ "SELECT",
+ /* 128 */ "VALUES",
+ /* 129 */ "DISTINCT",
+ /* 130 */ "DOT",
+ /* 131 */ "FROM",
+ /* 132 */ "JOIN",
+ /* 133 */ "USING",
+ /* 134 */ "ORDER",
+ /* 135 */ "GROUP",
+ /* 136 */ "HAVING",
+ /* 137 */ "LIMIT",
+ /* 138 */ "WHERE",
+ /* 139 */ "INTO",
+ /* 140 */ "NOTHING",
+ /* 141 */ "FLOAT",
+ /* 142 */ "BLOB",
+ /* 143 */ "INTEGER",
+ /* 144 */ "VARIABLE",
+ /* 145 */ "CASE",
+ /* 146 */ "WHEN",
+ /* 147 */ "THEN",
+ /* 148 */ "ELSE",
+ /* 149 */ "INDEX",
+ /* 150 */ "ALTER",
+ /* 151 */ "ADD",
+ /* 152 */ "WINDOW",
+ /* 153 */ "OVER",
+ /* 154 */ "FILTER",
+ /* 155 */ "input",
+ /* 156 */ "cmdlist",
+ /* 157 */ "ecmd",
+ /* 158 */ "cmdx",
+ /* 159 */ "explain",
+ /* 160 */ "cmd",
+ /* 161 */ "transtype",
+ /* 162 */ "trans_opt",
+ /* 163 */ "nm",
+ /* 164 */ "savepoint_opt",
+ /* 165 */ "create_table",
+ /* 166 */ "create_table_args",
+ /* 167 */ "createkw",
+ /* 168 */ "temp",
+ /* 169 */ "ifnotexists",
+ /* 170 */ "dbnm",
+ /* 171 */ "columnlist",
+ /* 172 */ "conslist_opt",
+ /* 173 */ "table_options",
+ /* 174 */ "select",
+ /* 175 */ "columnname",
+ /* 176 */ "carglist",
+ /* 177 */ "typetoken",
+ /* 178 */ "typename",
+ /* 179 */ "signed",
+ /* 180 */ "plus_num",
+ /* 181 */ "minus_num",
+ /* 182 */ "scanpt",
+ /* 183 */ "ccons",
+ /* 184 */ "term",
+ /* 185 */ "expr",
+ /* 186 */ "onconf",
+ /* 187 */ "sortorder",
+ /* 188 */ "autoinc",
+ /* 189 */ "eidlist_opt",
+ /* 190 */ "refargs",
+ /* 191 */ "defer_subclause",
+ /* 192 */ "refarg",
+ /* 193 */ "refact",
+ /* 194 */ "init_deferred_pred_opt",
+ /* 195 */ "conslist",
+ /* 196 */ "tconscomma",
+ /* 197 */ "tcons",
+ /* 198 */ "sortlist",
+ /* 199 */ "eidlist",
+ /* 200 */ "defer_subclause_opt",
+ /* 201 */ "orconf",
+ /* 202 */ "resolvetype",
+ /* 203 */ "raisetype",
+ /* 204 */ "ifexists",
+ /* 205 */ "fullname",
+ /* 206 */ "selectnowith",
+ /* 207 */ "oneselect",
+ /* 208 */ "wqlist",
+ /* 209 */ "multiselect_op",
+ /* 210 */ "distinct",
+ /* 211 */ "selcollist",
+ /* 212 */ "from",
+ /* 213 */ "where_opt",
+ /* 214 */ "groupby_opt",
+ /* 215 */ "having_opt",
+ /* 216 */ "orderby_opt",
+ /* 217 */ "limit_opt",
+ /* 218 */ "window_clause",
+ /* 219 */ "values",
+ /* 220 */ "nexprlist",
+ /* 221 */ "sclp",
+ /* 222 */ "as",
+ /* 223 */ "seltablist",
+ /* 224 */ "stl_prefix",
+ /* 225 */ "joinop",
+ /* 226 */ "indexed_opt",
+ /* 227 */ "on_opt",
+ /* 228 */ "using_opt",
+ /* 229 */ "exprlist",
+ /* 230 */ "xfullname",
+ /* 231 */ "idlist",
+ /* 232 */ "with",
+ /* 233 */ "setlist",
+ /* 234 */ "insert_cmd",
+ /* 235 */ "idlist_opt",
+ /* 236 */ "upsert",
+ /* 237 */ "over_clause",
+ /* 238 */ "likeop",
+ /* 239 */ "between_op",
+ /* 240 */ "in_op",
+ /* 241 */ "paren_exprlist",
+ /* 242 */ "case_operand",
+ /* 243 */ "case_exprlist",
+ /* 244 */ "case_else",
+ /* 245 */ "uniqueflag",
+ /* 246 */ "collate",
+ /* 247 */ "nmnum",
+ /* 248 */ "trigger_decl",
+ /* 249 */ "trigger_cmd_list",
+ /* 250 */ "trigger_time",
+ /* 251 */ "trigger_event",
+ /* 252 */ "foreach_clause",
+ /* 253 */ "when_clause",
+ /* 254 */ "trigger_cmd",
+ /* 255 */ "trnm",
+ /* 256 */ "tridxby",
+ /* 257 */ "database_kw_opt",
+ /* 258 */ "key_opt",
+ /* 259 */ "add_column_fullname",
+ /* 260 */ "kwcolumn_opt",
+ /* 261 */ "create_vtab",
+ /* 262 */ "vtabarglist",
+ /* 263 */ "vtabarg",
+ /* 264 */ "vtabargtoken",
+ /* 265 */ "lp",
+ /* 266 */ "anylist",
+ /* 267 */ "windowdefn_list",
+ /* 268 */ "windowdefn",
+ /* 269 */ "window",
+ /* 270 */ "frame_opt",
+ /* 271 */ "part_opt",
+ /* 272 */ "filter_opt",
+ /* 273 */ "range_or_rows",
+ /* 274 */ "frame_bound",
+ /* 275 */ "frame_bound_s",
+ /* 276 */ "frame_bound_e",
};
#endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */
@@ -142757,259 +147396,285 @@ static const char *const yyRuleName[] = {
/* 85 */ "multiselect_op ::= UNION ALL",
/* 86 */ "multiselect_op ::= EXCEPT|INTERSECT",
/* 87 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
- /* 88 */ "values ::= VALUES LP nexprlist RP",
- /* 89 */ "values ::= values COMMA LP exprlist RP",
- /* 90 */ "distinct ::= DISTINCT",
- /* 91 */ "distinct ::= ALL",
- /* 92 */ "distinct ::=",
- /* 93 */ "sclp ::=",
- /* 94 */ "selcollist ::= sclp scanpt expr scanpt as",
- /* 95 */ "selcollist ::= sclp scanpt STAR",
- /* 96 */ "selcollist ::= sclp scanpt nm DOT STAR",
- /* 97 */ "as ::= AS nm",
- /* 98 */ "as ::=",
- /* 99 */ "from ::=",
- /* 100 */ "from ::= FROM seltablist",
- /* 101 */ "stl_prefix ::= seltablist joinop",
- /* 102 */ "stl_prefix ::=",
- /* 103 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt",
- /* 104 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt",
- /* 105 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt",
- /* 106 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt",
- /* 107 */ "dbnm ::=",
- /* 108 */ "dbnm ::= DOT nm",
- /* 109 */ "fullname ::= nm",
- /* 110 */ "fullname ::= nm DOT nm",
- /* 111 */ "xfullname ::= nm",
- /* 112 */ "xfullname ::= nm DOT nm",
- /* 113 */ "xfullname ::= nm DOT nm AS nm",
- /* 114 */ "xfullname ::= nm AS nm",
- /* 115 */ "joinop ::= COMMA|JOIN",
- /* 116 */ "joinop ::= JOIN_KW JOIN",
- /* 117 */ "joinop ::= JOIN_KW nm JOIN",
- /* 118 */ "joinop ::= JOIN_KW nm nm JOIN",
- /* 119 */ "on_opt ::= ON expr",
- /* 120 */ "on_opt ::=",
- /* 121 */ "indexed_opt ::=",
- /* 122 */ "indexed_opt ::= INDEXED BY nm",
- /* 123 */ "indexed_opt ::= NOT INDEXED",
- /* 124 */ "using_opt ::= USING LP idlist RP",
- /* 125 */ "using_opt ::=",
- /* 126 */ "orderby_opt ::=",
- /* 127 */ "orderby_opt ::= ORDER BY sortlist",
- /* 128 */ "sortlist ::= sortlist COMMA expr sortorder",
- /* 129 */ "sortlist ::= expr sortorder",
- /* 130 */ "sortorder ::= ASC",
- /* 131 */ "sortorder ::= DESC",
- /* 132 */ "sortorder ::=",
- /* 133 */ "groupby_opt ::=",
- /* 134 */ "groupby_opt ::= GROUP BY nexprlist",
- /* 135 */ "having_opt ::=",
- /* 136 */ "having_opt ::= HAVING expr",
- /* 137 */ "limit_opt ::=",
- /* 138 */ "limit_opt ::= LIMIT expr",
- /* 139 */ "limit_opt ::= LIMIT expr OFFSET expr",
- /* 140 */ "limit_opt ::= LIMIT expr COMMA expr",
- /* 141 */ "cmd ::= with DELETE FROM xfullname indexed_opt where_opt",
- /* 142 */ "where_opt ::=",
- /* 143 */ "where_opt ::= WHERE expr",
- /* 144 */ "cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt",
- /* 145 */ "setlist ::= setlist COMMA nm EQ expr",
- /* 146 */ "setlist ::= setlist COMMA LP idlist RP EQ expr",
- /* 147 */ "setlist ::= nm EQ expr",
- /* 148 */ "setlist ::= LP idlist RP EQ expr",
- /* 149 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert",
- /* 150 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES",
- /* 151 */ "upsert ::=",
- /* 152 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt",
- /* 153 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING",
- /* 154 */ "upsert ::= ON CONFLICT DO NOTHING",
- /* 155 */ "insert_cmd ::= INSERT orconf",
- /* 156 */ "insert_cmd ::= REPLACE",
- /* 157 */ "idlist_opt ::=",
- /* 158 */ "idlist_opt ::= LP idlist RP",
- /* 159 */ "idlist ::= idlist COMMA nm",
- /* 160 */ "idlist ::= nm",
- /* 161 */ "expr ::= LP expr RP",
- /* 162 */ "expr ::= ID|INDEXED",
- /* 163 */ "expr ::= JOIN_KW",
- /* 164 */ "expr ::= nm DOT nm",
- /* 165 */ "expr ::= nm DOT nm DOT nm",
- /* 166 */ "term ::= NULL|FLOAT|BLOB",
- /* 167 */ "term ::= STRING",
- /* 168 */ "term ::= INTEGER",
- /* 169 */ "expr ::= VARIABLE",
- /* 170 */ "expr ::= expr COLLATE ID|STRING",
- /* 171 */ "expr ::= CAST LP expr AS typetoken RP",
- /* 172 */ "expr ::= ID|INDEXED LP distinct exprlist RP",
- /* 173 */ "expr ::= ID|INDEXED LP STAR RP",
- /* 174 */ "term ::= CTIME_KW",
- /* 175 */ "expr ::= LP nexprlist COMMA expr RP",
- /* 176 */ "expr ::= expr AND expr",
- /* 177 */ "expr ::= expr OR expr",
- /* 178 */ "expr ::= expr LT|GT|GE|LE expr",
- /* 179 */ "expr ::= expr EQ|NE expr",
- /* 180 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
- /* 181 */ "expr ::= expr PLUS|MINUS expr",
- /* 182 */ "expr ::= expr STAR|SLASH|REM expr",
- /* 183 */ "expr ::= expr CONCAT expr",
- /* 184 */ "likeop ::= NOT LIKE_KW|MATCH",
- /* 185 */ "expr ::= expr likeop expr",
- /* 186 */ "expr ::= expr likeop expr ESCAPE expr",
- /* 187 */ "expr ::= expr ISNULL|NOTNULL",
- /* 188 */ "expr ::= expr NOT NULL",
- /* 189 */ "expr ::= expr IS expr",
- /* 190 */ "expr ::= expr IS NOT expr",
- /* 191 */ "expr ::= NOT expr",
- /* 192 */ "expr ::= BITNOT expr",
- /* 193 */ "expr ::= MINUS expr",
- /* 194 */ "expr ::= PLUS expr",
- /* 195 */ "between_op ::= BETWEEN",
- /* 196 */ "between_op ::= NOT BETWEEN",
- /* 197 */ "expr ::= expr between_op expr AND expr",
- /* 198 */ "in_op ::= IN",
- /* 199 */ "in_op ::= NOT IN",
- /* 200 */ "expr ::= expr in_op LP exprlist RP",
- /* 201 */ "expr ::= LP select RP",
- /* 202 */ "expr ::= expr in_op LP select RP",
- /* 203 */ "expr ::= expr in_op nm dbnm paren_exprlist",
- /* 204 */ "expr ::= EXISTS LP select RP",
- /* 205 */ "expr ::= CASE case_operand case_exprlist case_else END",
- /* 206 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
- /* 207 */ "case_exprlist ::= WHEN expr THEN expr",
- /* 208 */ "case_else ::= ELSE expr",
- /* 209 */ "case_else ::=",
- /* 210 */ "case_operand ::= expr",
- /* 211 */ "case_operand ::=",
- /* 212 */ "exprlist ::=",
- /* 213 */ "nexprlist ::= nexprlist COMMA expr",
- /* 214 */ "nexprlist ::= expr",
- /* 215 */ "paren_exprlist ::=",
- /* 216 */ "paren_exprlist ::= LP exprlist RP",
- /* 217 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt",
- /* 218 */ "uniqueflag ::= UNIQUE",
- /* 219 */ "uniqueflag ::=",
- /* 220 */ "eidlist_opt ::=",
- /* 221 */ "eidlist_opt ::= LP eidlist RP",
- /* 222 */ "eidlist ::= eidlist COMMA nm collate sortorder",
- /* 223 */ "eidlist ::= nm collate sortorder",
- /* 224 */ "collate ::=",
- /* 225 */ "collate ::= COLLATE ID|STRING",
- /* 226 */ "cmd ::= DROP INDEX ifexists fullname",
- /* 227 */ "cmd ::= VACUUM",
- /* 228 */ "cmd ::= VACUUM nm",
- /* 229 */ "cmd ::= PRAGMA nm dbnm",
- /* 230 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
- /* 231 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
- /* 232 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
- /* 233 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
- /* 234 */ "plus_num ::= PLUS INTEGER|FLOAT",
- /* 235 */ "minus_num ::= MINUS INTEGER|FLOAT",
- /* 236 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
- /* 237 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
- /* 238 */ "trigger_time ::= BEFORE|AFTER",
- /* 239 */ "trigger_time ::= INSTEAD OF",
- /* 240 */ "trigger_time ::=",
- /* 241 */ "trigger_event ::= DELETE|INSERT",
- /* 242 */ "trigger_event ::= UPDATE",
- /* 243 */ "trigger_event ::= UPDATE OF idlist",
- /* 244 */ "when_clause ::=",
- /* 245 */ "when_clause ::= WHEN expr",
- /* 246 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
- /* 247 */ "trigger_cmd_list ::= trigger_cmd SEMI",
- /* 248 */ "trnm ::= nm DOT nm",
- /* 249 */ "tridxby ::= INDEXED BY nm",
- /* 250 */ "tridxby ::= NOT INDEXED",
- /* 251 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt",
- /* 252 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt",
- /* 253 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt",
- /* 254 */ "trigger_cmd ::= scanpt select scanpt",
- /* 255 */ "expr ::= RAISE LP IGNORE RP",
- /* 256 */ "expr ::= RAISE LP raisetype COMMA nm RP",
- /* 257 */ "raisetype ::= ROLLBACK",
- /* 258 */ "raisetype ::= ABORT",
- /* 259 */ "raisetype ::= FAIL",
- /* 260 */ "cmd ::= DROP TRIGGER ifexists fullname",
- /* 261 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
- /* 262 */ "cmd ::= DETACH database_kw_opt expr",
- /* 263 */ "key_opt ::=",
- /* 264 */ "key_opt ::= KEY expr",
- /* 265 */ "cmd ::= REINDEX",
- /* 266 */ "cmd ::= REINDEX nm dbnm",
- /* 267 */ "cmd ::= ANALYZE",
- /* 268 */ "cmd ::= ANALYZE nm dbnm",
- /* 269 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
- /* 270 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist",
- /* 271 */ "add_column_fullname ::= fullname",
- /* 272 */ "cmd ::= create_vtab",
- /* 273 */ "cmd ::= create_vtab LP vtabarglist RP",
- /* 274 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
- /* 275 */ "vtabarg ::=",
- /* 276 */ "vtabargtoken ::= ANY",
- /* 277 */ "vtabargtoken ::= lp anylist RP",
- /* 278 */ "lp ::= LP",
- /* 279 */ "with ::= WITH wqlist",
- /* 280 */ "with ::= WITH RECURSIVE wqlist",
- /* 281 */ "wqlist ::= nm eidlist_opt AS LP select RP",
- /* 282 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP",
- /* 283 */ "input ::= cmdlist",
- /* 284 */ "cmdlist ::= cmdlist ecmd",
- /* 285 */ "cmdlist ::= ecmd",
- /* 286 */ "ecmd ::= SEMI",
- /* 287 */ "ecmd ::= cmdx SEMI",
- /* 288 */ "ecmd ::= explain cmdx",
- /* 289 */ "trans_opt ::=",
- /* 290 */ "trans_opt ::= TRANSACTION",
- /* 291 */ "trans_opt ::= TRANSACTION nm",
- /* 292 */ "savepoint_opt ::= SAVEPOINT",
- /* 293 */ "savepoint_opt ::=",
- /* 294 */ "cmd ::= create_table create_table_args",
- /* 295 */ "columnlist ::= columnlist COMMA columnname carglist",
- /* 296 */ "columnlist ::= columnname carglist",
- /* 297 */ "nm ::= ID|INDEXED",
- /* 298 */ "nm ::= STRING",
- /* 299 */ "nm ::= JOIN_KW",
- /* 300 */ "typetoken ::= typename",
- /* 301 */ "typename ::= ID|STRING",
- /* 302 */ "signed ::= plus_num",
- /* 303 */ "signed ::= minus_num",
- /* 304 */ "carglist ::= carglist ccons",
- /* 305 */ "carglist ::=",
- /* 306 */ "ccons ::= NULL onconf",
- /* 307 */ "conslist_opt ::= COMMA conslist",
- /* 308 */ "conslist ::= conslist tconscomma tcons",
- /* 309 */ "conslist ::= tcons",
- /* 310 */ "tconscomma ::=",
- /* 311 */ "defer_subclause_opt ::= defer_subclause",
- /* 312 */ "resolvetype ::= raisetype",
- /* 313 */ "selectnowith ::= oneselect",
- /* 314 */ "oneselect ::= values",
- /* 315 */ "sclp ::= selcollist COMMA",
- /* 316 */ "as ::= ID|STRING",
- /* 317 */ "expr ::= term",
- /* 318 */ "likeop ::= LIKE_KW|MATCH",
- /* 319 */ "exprlist ::= nexprlist",
- /* 320 */ "nmnum ::= plus_num",
- /* 321 */ "nmnum ::= nm",
- /* 322 */ "nmnum ::= ON",
- /* 323 */ "nmnum ::= DELETE",
- /* 324 */ "nmnum ::= DEFAULT",
- /* 325 */ "plus_num ::= INTEGER|FLOAT",
- /* 326 */ "foreach_clause ::=",
- /* 327 */ "foreach_clause ::= FOR EACH ROW",
- /* 328 */ "trnm ::= nm",
- /* 329 */ "tridxby ::=",
- /* 330 */ "database_kw_opt ::= DATABASE",
- /* 331 */ "database_kw_opt ::=",
- /* 332 */ "kwcolumn_opt ::=",
- /* 333 */ "kwcolumn_opt ::= COLUMNKW",
- /* 334 */ "vtabarglist ::= vtabarg",
- /* 335 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
- /* 336 */ "vtabarg ::= vtabarg vtabargtoken",
- /* 337 */ "anylist ::=",
- /* 338 */ "anylist ::= anylist LP anylist RP",
- /* 339 */ "anylist ::= anylist ANY",
- /* 340 */ "with ::=",
+ /* 88 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt",
+ /* 89 */ "values ::= VALUES LP nexprlist RP",
+ /* 90 */ "values ::= values COMMA LP nexprlist RP",
+ /* 91 */ "distinct ::= DISTINCT",
+ /* 92 */ "distinct ::= ALL",
+ /* 93 */ "distinct ::=",
+ /* 94 */ "sclp ::=",
+ /* 95 */ "selcollist ::= sclp scanpt expr scanpt as",
+ /* 96 */ "selcollist ::= sclp scanpt STAR",
+ /* 97 */ "selcollist ::= sclp scanpt nm DOT STAR",
+ /* 98 */ "as ::= AS nm",
+ /* 99 */ "as ::=",
+ /* 100 */ "from ::=",
+ /* 101 */ "from ::= FROM seltablist",
+ /* 102 */ "stl_prefix ::= seltablist joinop",
+ /* 103 */ "stl_prefix ::=",
+ /* 104 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt",
+ /* 105 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt",
+ /* 106 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt",
+ /* 107 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt",
+ /* 108 */ "dbnm ::=",
+ /* 109 */ "dbnm ::= DOT nm",
+ /* 110 */ "fullname ::= nm",
+ /* 111 */ "fullname ::= nm DOT nm",
+ /* 112 */ "xfullname ::= nm",
+ /* 113 */ "xfullname ::= nm DOT nm",
+ /* 114 */ "xfullname ::= nm DOT nm AS nm",
+ /* 115 */ "xfullname ::= nm AS nm",
+ /* 116 */ "joinop ::= COMMA|JOIN",
+ /* 117 */ "joinop ::= JOIN_KW JOIN",
+ /* 118 */ "joinop ::= JOIN_KW nm JOIN",
+ /* 119 */ "joinop ::= JOIN_KW nm nm JOIN",
+ /* 120 */ "on_opt ::= ON expr",
+ /* 121 */ "on_opt ::=",
+ /* 122 */ "indexed_opt ::=",
+ /* 123 */ "indexed_opt ::= INDEXED BY nm",
+ /* 124 */ "indexed_opt ::= NOT INDEXED",
+ /* 125 */ "using_opt ::= USING LP idlist RP",
+ /* 126 */ "using_opt ::=",
+ /* 127 */ "orderby_opt ::=",
+ /* 128 */ "orderby_opt ::= ORDER BY sortlist",
+ /* 129 */ "sortlist ::= sortlist COMMA expr sortorder",
+ /* 130 */ "sortlist ::= expr sortorder",
+ /* 131 */ "sortorder ::= ASC",
+ /* 132 */ "sortorder ::= DESC",
+ /* 133 */ "sortorder ::=",
+ /* 134 */ "groupby_opt ::=",
+ /* 135 */ "groupby_opt ::= GROUP BY nexprlist",
+ /* 136 */ "having_opt ::=",
+ /* 137 */ "having_opt ::= HAVING expr",
+ /* 138 */ "limit_opt ::=",
+ /* 139 */ "limit_opt ::= LIMIT expr",
+ /* 140 */ "limit_opt ::= LIMIT expr OFFSET expr",
+ /* 141 */ "limit_opt ::= LIMIT expr COMMA expr",
+ /* 142 */ "cmd ::= with DELETE FROM xfullname indexed_opt where_opt",
+ /* 143 */ "where_opt ::=",
+ /* 144 */ "where_opt ::= WHERE expr",
+ /* 145 */ "cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt",
+ /* 146 */ "setlist ::= setlist COMMA nm EQ expr",
+ /* 147 */ "setlist ::= setlist COMMA LP idlist RP EQ expr",
+ /* 148 */ "setlist ::= nm EQ expr",
+ /* 149 */ "setlist ::= LP idlist RP EQ expr",
+ /* 150 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert",
+ /* 151 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES",
+ /* 152 */ "upsert ::=",
+ /* 153 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt",
+ /* 154 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING",
+ /* 155 */ "upsert ::= ON CONFLICT DO NOTHING",
+ /* 156 */ "insert_cmd ::= INSERT orconf",
+ /* 157 */ "insert_cmd ::= REPLACE",
+ /* 158 */ "idlist_opt ::=",
+ /* 159 */ "idlist_opt ::= LP idlist RP",
+ /* 160 */ "idlist ::= idlist COMMA nm",
+ /* 161 */ "idlist ::= nm",
+ /* 162 */ "expr ::= LP expr RP",
+ /* 163 */ "expr ::= ID|INDEXED",
+ /* 164 */ "expr ::= JOIN_KW",
+ /* 165 */ "expr ::= nm DOT nm",
+ /* 166 */ "expr ::= nm DOT nm DOT nm",
+ /* 167 */ "term ::= NULL|FLOAT|BLOB",
+ /* 168 */ "term ::= STRING",
+ /* 169 */ "term ::= INTEGER",
+ /* 170 */ "expr ::= VARIABLE",
+ /* 171 */ "expr ::= expr COLLATE ID|STRING",
+ /* 172 */ "expr ::= CAST LP expr AS typetoken RP",
+ /* 173 */ "expr ::= ID|INDEXED LP distinct exprlist RP",
+ /* 174 */ "expr ::= ID|INDEXED LP STAR RP",
+ /* 175 */ "expr ::= ID|INDEXED LP distinct exprlist RP over_clause",
+ /* 176 */ "expr ::= ID|INDEXED LP STAR RP over_clause",
+ /* 177 */ "term ::= CTIME_KW",
+ /* 178 */ "expr ::= LP nexprlist COMMA expr RP",
+ /* 179 */ "expr ::= expr AND expr",
+ /* 180 */ "expr ::= expr OR expr",
+ /* 181 */ "expr ::= expr LT|GT|GE|LE expr",
+ /* 182 */ "expr ::= expr EQ|NE expr",
+ /* 183 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
+ /* 184 */ "expr ::= expr PLUS|MINUS expr",
+ /* 185 */ "expr ::= expr STAR|SLASH|REM expr",
+ /* 186 */ "expr ::= expr CONCAT expr",
+ /* 187 */ "likeop ::= NOT LIKE_KW|MATCH",
+ /* 188 */ "expr ::= expr likeop expr",
+ /* 189 */ "expr ::= expr likeop expr ESCAPE expr",
+ /* 190 */ "expr ::= expr ISNULL|NOTNULL",
+ /* 191 */ "expr ::= expr NOT NULL",
+ /* 192 */ "expr ::= expr IS expr",
+ /* 193 */ "expr ::= expr IS NOT expr",
+ /* 194 */ "expr ::= NOT expr",
+ /* 195 */ "expr ::= BITNOT expr",
+ /* 196 */ "expr ::= PLUS|MINUS expr",
+ /* 197 */ "between_op ::= BETWEEN",
+ /* 198 */ "between_op ::= NOT BETWEEN",
+ /* 199 */ "expr ::= expr between_op expr AND expr",
+ /* 200 */ "in_op ::= IN",
+ /* 201 */ "in_op ::= NOT IN",
+ /* 202 */ "expr ::= expr in_op LP exprlist RP",
+ /* 203 */ "expr ::= LP select RP",
+ /* 204 */ "expr ::= expr in_op LP select RP",
+ /* 205 */ "expr ::= expr in_op nm dbnm paren_exprlist",
+ /* 206 */ "expr ::= EXISTS LP select RP",
+ /* 207 */ "expr ::= CASE case_operand case_exprlist case_else END",
+ /* 208 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
+ /* 209 */ "case_exprlist ::= WHEN expr THEN expr",
+ /* 210 */ "case_else ::= ELSE expr",
+ /* 211 */ "case_else ::=",
+ /* 212 */ "case_operand ::= expr",
+ /* 213 */ "case_operand ::=",
+ /* 214 */ "exprlist ::=",
+ /* 215 */ "nexprlist ::= nexprlist COMMA expr",
+ /* 216 */ "nexprlist ::= expr",
+ /* 217 */ "paren_exprlist ::=",
+ /* 218 */ "paren_exprlist ::= LP exprlist RP",
+ /* 219 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt",
+ /* 220 */ "uniqueflag ::= UNIQUE",
+ /* 221 */ "uniqueflag ::=",
+ /* 222 */ "eidlist_opt ::=",
+ /* 223 */ "eidlist_opt ::= LP eidlist RP",
+ /* 224 */ "eidlist ::= eidlist COMMA nm collate sortorder",
+ /* 225 */ "eidlist ::= nm collate sortorder",
+ /* 226 */ "collate ::=",
+ /* 227 */ "collate ::= COLLATE ID|STRING",
+ /* 228 */ "cmd ::= DROP INDEX ifexists fullname",
+ /* 229 */ "cmd ::= VACUUM",
+ /* 230 */ "cmd ::= VACUUM nm",
+ /* 231 */ "cmd ::= PRAGMA nm dbnm",
+ /* 232 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
+ /* 233 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
+ /* 234 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
+ /* 235 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
+ /* 236 */ "plus_num ::= PLUS INTEGER|FLOAT",
+ /* 237 */ "minus_num ::= MINUS INTEGER|FLOAT",
+ /* 238 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
+ /* 239 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
+ /* 240 */ "trigger_time ::= BEFORE|AFTER",
+ /* 241 */ "trigger_time ::= INSTEAD OF",
+ /* 242 */ "trigger_time ::=",
+ /* 243 */ "trigger_event ::= DELETE|INSERT",
+ /* 244 */ "trigger_event ::= UPDATE",
+ /* 245 */ "trigger_event ::= UPDATE OF idlist",
+ /* 246 */ "when_clause ::=",
+ /* 247 */ "when_clause ::= WHEN expr",
+ /* 248 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
+ /* 249 */ "trigger_cmd_list ::= trigger_cmd SEMI",
+ /* 250 */ "trnm ::= nm DOT nm",
+ /* 251 */ "tridxby ::= INDEXED BY nm",
+ /* 252 */ "tridxby ::= NOT INDEXED",
+ /* 253 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt",
+ /* 254 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt",
+ /* 255 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt",
+ /* 256 */ "trigger_cmd ::= scanpt select scanpt",
+ /* 257 */ "expr ::= RAISE LP IGNORE RP",
+ /* 258 */ "expr ::= RAISE LP raisetype COMMA nm RP",
+ /* 259 */ "raisetype ::= ROLLBACK",
+ /* 260 */ "raisetype ::= ABORT",
+ /* 261 */ "raisetype ::= FAIL",
+ /* 262 */ "cmd ::= DROP TRIGGER ifexists fullname",
+ /* 263 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
+ /* 264 */ "cmd ::= DETACH database_kw_opt expr",
+ /* 265 */ "key_opt ::=",
+ /* 266 */ "key_opt ::= KEY expr",
+ /* 267 */ "cmd ::= REINDEX",
+ /* 268 */ "cmd ::= REINDEX nm dbnm",
+ /* 269 */ "cmd ::= ANALYZE",
+ /* 270 */ "cmd ::= ANALYZE nm dbnm",
+ /* 271 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
+ /* 272 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist",
+ /* 273 */ "add_column_fullname ::= fullname",
+ /* 274 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm",
+ /* 275 */ "cmd ::= create_vtab",
+ /* 276 */ "cmd ::= create_vtab LP vtabarglist RP",
+ /* 277 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
+ /* 278 */ "vtabarg ::=",
+ /* 279 */ "vtabargtoken ::= ANY",
+ /* 280 */ "vtabargtoken ::= lp anylist RP",
+ /* 281 */ "lp ::= LP",
+ /* 282 */ "with ::= WITH wqlist",
+ /* 283 */ "with ::= WITH RECURSIVE wqlist",
+ /* 284 */ "wqlist ::= nm eidlist_opt AS LP select RP",
+ /* 285 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP",
+ /* 286 */ "windowdefn_list ::= windowdefn",
+ /* 287 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn",
+ /* 288 */ "windowdefn ::= nm AS window",
+ /* 289 */ "window ::= LP part_opt orderby_opt frame_opt RP",
+ /* 290 */ "part_opt ::= PARTITION BY nexprlist",
+ /* 291 */ "part_opt ::=",
+ /* 292 */ "frame_opt ::=",
+ /* 293 */ "frame_opt ::= range_or_rows frame_bound_s",
+ /* 294 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e",
+ /* 295 */ "range_or_rows ::= RANGE",
+ /* 296 */ "range_or_rows ::= ROWS",
+ /* 297 */ "frame_bound_s ::= frame_bound",
+ /* 298 */ "frame_bound_s ::= UNBOUNDED PRECEDING",
+ /* 299 */ "frame_bound_e ::= frame_bound",
+ /* 300 */ "frame_bound_e ::= UNBOUNDED FOLLOWING",
+ /* 301 */ "frame_bound ::= expr PRECEDING",
+ /* 302 */ "frame_bound ::= CURRENT ROW",
+ /* 303 */ "frame_bound ::= expr FOLLOWING",
+ /* 304 */ "window_clause ::= WINDOW windowdefn_list",
+ /* 305 */ "over_clause ::= filter_opt OVER window",
+ /* 306 */ "over_clause ::= filter_opt OVER nm",
+ /* 307 */ "filter_opt ::=",
+ /* 308 */ "filter_opt ::= FILTER LP WHERE expr RP",
+ /* 309 */ "input ::= cmdlist",
+ /* 310 */ "cmdlist ::= cmdlist ecmd",
+ /* 311 */ "cmdlist ::= ecmd",
+ /* 312 */ "ecmd ::= SEMI",
+ /* 313 */ "ecmd ::= cmdx SEMI",
+ /* 314 */ "ecmd ::= explain cmdx",
+ /* 315 */ "trans_opt ::=",
+ /* 316 */ "trans_opt ::= TRANSACTION",
+ /* 317 */ "trans_opt ::= TRANSACTION nm",
+ /* 318 */ "savepoint_opt ::= SAVEPOINT",
+ /* 319 */ "savepoint_opt ::=",
+ /* 320 */ "cmd ::= create_table create_table_args",
+ /* 321 */ "columnlist ::= columnlist COMMA columnname carglist",
+ /* 322 */ "columnlist ::= columnname carglist",
+ /* 323 */ "nm ::= ID|INDEXED",
+ /* 324 */ "nm ::= STRING",
+ /* 325 */ "nm ::= JOIN_KW",
+ /* 326 */ "typetoken ::= typename",
+ /* 327 */ "typename ::= ID|STRING",
+ /* 328 */ "signed ::= plus_num",
+ /* 329 */ "signed ::= minus_num",
+ /* 330 */ "carglist ::= carglist ccons",
+ /* 331 */ "carglist ::=",
+ /* 332 */ "ccons ::= NULL onconf",
+ /* 333 */ "conslist_opt ::= COMMA conslist",
+ /* 334 */ "conslist ::= conslist tconscomma tcons",
+ /* 335 */ "conslist ::= tcons",
+ /* 336 */ "tconscomma ::=",
+ /* 337 */ "defer_subclause_opt ::= defer_subclause",
+ /* 338 */ "resolvetype ::= raisetype",
+ /* 339 */ "selectnowith ::= oneselect",
+ /* 340 */ "oneselect ::= values",
+ /* 341 */ "sclp ::= selcollist COMMA",
+ /* 342 */ "as ::= ID|STRING",
+ /* 343 */ "expr ::= term",
+ /* 344 */ "likeop ::= LIKE_KW|MATCH",
+ /* 345 */ "exprlist ::= nexprlist",
+ /* 346 */ "nmnum ::= plus_num",
+ /* 347 */ "nmnum ::= nm",
+ /* 348 */ "nmnum ::= ON",
+ /* 349 */ "nmnum ::= DELETE",
+ /* 350 */ "nmnum ::= DEFAULT",
+ /* 351 */ "plus_num ::= INTEGER|FLOAT",
+ /* 352 */ "foreach_clause ::=",
+ /* 353 */ "foreach_clause ::= FOR EACH ROW",
+ /* 354 */ "trnm ::= nm",
+ /* 355 */ "tridxby ::=",
+ /* 356 */ "database_kw_opt ::= DATABASE",
+ /* 357 */ "database_kw_opt ::=",
+ /* 358 */ "kwcolumn_opt ::=",
+ /* 359 */ "kwcolumn_opt ::= COLUMNKW",
+ /* 360 */ "vtabarglist ::= vtabarg",
+ /* 361 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
+ /* 362 */ "vtabarg ::= vtabarg vtabargtoken",
+ /* 363 */ "anylist ::=",
+ /* 364 */ "anylist ::= anylist LP anylist RP",
+ /* 365 */ "anylist ::= anylist ANY",
+ /* 366 */ "with ::=",
};
#endif /* NDEBUG */
@@ -143135,73 +147800,96 @@ static void yy_destructor(
** inside the C code.
*/
/********* Begin destructor definitions ***************************************/
- case 164: /* select */
- case 196: /* selectnowith */
- case 197: /* oneselect */
- case 208: /* values */
+ case 174: /* select */
+ case 206: /* selectnowith */
+ case 207: /* oneselect */
+ case 219: /* values */
+{
+sqlite3SelectDelete(pParse->db, (yypminor->yy489));
+}
+ break;
+ case 184: /* term */
+ case 185: /* expr */
+ case 213: /* where_opt */
+ case 215: /* having_opt */
+ case 227: /* on_opt */
+ case 242: /* case_operand */
+ case 244: /* case_else */
+ case 253: /* when_clause */
+ case 258: /* key_opt */
+ case 272: /* filter_opt */
+{
+sqlite3ExprDelete(pParse->db, (yypminor->yy18));
+}
+ break;
+ case 189: /* eidlist_opt */
+ case 198: /* sortlist */
+ case 199: /* eidlist */
+ case 211: /* selcollist */
+ case 214: /* groupby_opt */
+ case 216: /* orderby_opt */
+ case 220: /* nexprlist */
+ case 221: /* sclp */
+ case 229: /* exprlist */
+ case 233: /* setlist */
+ case 241: /* paren_exprlist */
+ case 243: /* case_exprlist */
+ case 271: /* part_opt */
+{
+sqlite3ExprListDelete(pParse->db, (yypminor->yy420));
+}
+ break;
+ case 205: /* fullname */
+ case 212: /* from */
+ case 223: /* seltablist */
+ case 224: /* stl_prefix */
+ case 230: /* xfullname */
{
-sqlite3SelectDelete(pParse->db, (yypminor->yy399));
+sqlite3SrcListDelete(pParse->db, (yypminor->yy135));
}
break;
- case 174: /* term */
- case 175: /* expr */
- case 203: /* where_opt */
- case 205: /* having_opt */
- case 217: /* on_opt */
- case 230: /* case_operand */
- case 232: /* case_else */
- case 241: /* when_clause */
- case 246: /* key_opt */
+ case 208: /* wqlist */
{
-sqlite3ExprDelete(pParse->db, (yypminor->yy182));
+sqlite3WithDelete(pParse->db, (yypminor->yy449));
}
break;
- case 179: /* eidlist_opt */
- case 188: /* sortlist */
- case 189: /* eidlist */
- case 201: /* selcollist */
- case 204: /* groupby_opt */
- case 206: /* orderby_opt */
- case 209: /* nexprlist */
- case 210: /* exprlist */
- case 211: /* sclp */
- case 222: /* setlist */
- case 229: /* paren_exprlist */
- case 231: /* case_exprlist */
+ case 218: /* window_clause */
+ case 267: /* windowdefn_list */
{
-sqlite3ExprListDelete(pParse->db, (yypminor->yy232));
+sqlite3WindowListDelete(pParse->db, (yypminor->yy327));
}
break;
- case 195: /* fullname */
- case 202: /* from */
- case 213: /* seltablist */
- case 214: /* stl_prefix */
- case 219: /* xfullname */
+ case 228: /* using_opt */
+ case 231: /* idlist */
+ case 235: /* idlist_opt */
{
-sqlite3SrcListDelete(pParse->db, (yypminor->yy427));
+sqlite3IdListDelete(pParse->db, (yypminor->yy48));
}
break;
- case 198: /* wqlist */
+ case 237: /* over_clause */
+ case 268: /* windowdefn */
+ case 269: /* window */
+ case 270: /* frame_opt */
{
-sqlite3WithDelete(pParse->db, (yypminor->yy91));
+sqlite3WindowDelete(pParse->db, (yypminor->yy327));
}
break;
- case 218: /* using_opt */
- case 220: /* idlist */
- case 224: /* idlist_opt */
+ case 249: /* trigger_cmd_list */
+ case 254: /* trigger_cmd */
{
-sqlite3IdListDelete(pParse->db, (yypminor->yy510));
+sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy207));
}
break;
- case 237: /* trigger_cmd_list */
- case 242: /* trigger_cmd */
+ case 251: /* trigger_event */
{
-sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy47));
+sqlite3IdListDelete(pParse->db, (yypminor->yy34).b);
}
break;
- case 239: /* trigger_event */
+ case 274: /* frame_bound */
+ case 275: /* frame_bound_s */
+ case 276: /* frame_bound_e */
{
-sqlite3IdListDelete(pParse->db, (yypminor->yy300).b);
+sqlite3ExprDelete(pParse->db, (yypminor->yy119).pExpr);
}
break;
/********* End destructor definitions *****************************************/
@@ -143327,11 +148015,11 @@ static YYACTIONTYPE yy_find_shift_action(
do{
i = yy_shift_ofst[stateno];
assert( i>=0 );
- assert( i+YYNTOKEN<=(int)sizeof(yy_lookahead)/sizeof(yy_lookahead[0]) );
+ /* assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD ); */
assert( iLookAhead!=YYNOCODE );
assert( iLookAhead < YYNTOKEN );
i += iLookAhead;
- if( yy_lookahead[i]!=iLookAhead ){
+ if( i>=YY_NLOOKAHEAD || yy_lookahead[i]!=iLookAhead ){
#ifdef YYFALLBACK
YYCODETYPE iFallback; /* Fallback token */
if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
@@ -143357,6 +148045,7 @@ static YYACTIONTYPE yy_find_shift_action(
#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT
j<YY_ACTTAB_COUNT &&
#endif
+ j<(int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])) &&
yy_lookahead[j]==YYWILDCARD && iLookAhead>0
){
#ifndef NDEBUG
@@ -143381,7 +148070,7 @@ static YYACTIONTYPE yy_find_shift_action(
** Find the appropriate action for a parser given the non-terminal
** look-ahead token iLookAhead.
*/
-static int yy_find_reduce_action(
+static YYACTIONTYPE yy_find_reduce_action(
YYACTIONTYPE stateno, /* Current state number */
YYCODETYPE iLookAhead /* The look-ahead token */
){
@@ -143499,347 +148188,373 @@ static const struct {
YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
signed char nrhs; /* Negative of the number of RHS symbols in the rule */
} yyRuleInfo[] = {
- { 149, -1 }, /* (0) explain ::= EXPLAIN */
- { 149, -3 }, /* (1) explain ::= EXPLAIN QUERY PLAN */
- { 148, -1 }, /* (2) cmdx ::= cmd */
- { 150, -3 }, /* (3) cmd ::= BEGIN transtype trans_opt */
- { 151, 0 }, /* (4) transtype ::= */
- { 151, -1 }, /* (5) transtype ::= DEFERRED */
- { 151, -1 }, /* (6) transtype ::= IMMEDIATE */
- { 151, -1 }, /* (7) transtype ::= EXCLUSIVE */
- { 150, -2 }, /* (8) cmd ::= COMMIT|END trans_opt */
- { 150, -2 }, /* (9) cmd ::= ROLLBACK trans_opt */
- { 150, -2 }, /* (10) cmd ::= SAVEPOINT nm */
- { 150, -3 }, /* (11) cmd ::= RELEASE savepoint_opt nm */
- { 150, -5 }, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
- { 155, -6 }, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */
- { 157, -1 }, /* (14) createkw ::= CREATE */
- { 159, 0 }, /* (15) ifnotexists ::= */
- { 159, -3 }, /* (16) ifnotexists ::= IF NOT EXISTS */
- { 158, -1 }, /* (17) temp ::= TEMP */
- { 158, 0 }, /* (18) temp ::= */
- { 156, -5 }, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_options */
- { 156, -2 }, /* (20) create_table_args ::= AS select */
- { 163, 0 }, /* (21) table_options ::= */
- { 163, -2 }, /* (22) table_options ::= WITHOUT nm */
- { 165, -2 }, /* (23) columnname ::= nm typetoken */
- { 167, 0 }, /* (24) typetoken ::= */
- { 167, -4 }, /* (25) typetoken ::= typename LP signed RP */
- { 167, -6 }, /* (26) typetoken ::= typename LP signed COMMA signed RP */
- { 168, -2 }, /* (27) typename ::= typename ID|STRING */
- { 172, 0 }, /* (28) scanpt ::= */
- { 173, -2 }, /* (29) ccons ::= CONSTRAINT nm */
- { 173, -4 }, /* (30) ccons ::= DEFAULT scanpt term scanpt */
- { 173, -4 }, /* (31) ccons ::= DEFAULT LP expr RP */
- { 173, -4 }, /* (32) ccons ::= DEFAULT PLUS term scanpt */
- { 173, -4 }, /* (33) ccons ::= DEFAULT MINUS term scanpt */
- { 173, -3 }, /* (34) ccons ::= DEFAULT scanpt ID|INDEXED */
- { 173, -3 }, /* (35) ccons ::= NOT NULL onconf */
- { 173, -5 }, /* (36) ccons ::= PRIMARY KEY sortorder onconf autoinc */
- { 173, -2 }, /* (37) ccons ::= UNIQUE onconf */
- { 173, -4 }, /* (38) ccons ::= CHECK LP expr RP */
- { 173, -4 }, /* (39) ccons ::= REFERENCES nm eidlist_opt refargs */
- { 173, -1 }, /* (40) ccons ::= defer_subclause */
- { 173, -2 }, /* (41) ccons ::= COLLATE ID|STRING */
- { 178, 0 }, /* (42) autoinc ::= */
- { 178, -1 }, /* (43) autoinc ::= AUTOINCR */
- { 180, 0 }, /* (44) refargs ::= */
- { 180, -2 }, /* (45) refargs ::= refargs refarg */
- { 182, -2 }, /* (46) refarg ::= MATCH nm */
- { 182, -3 }, /* (47) refarg ::= ON INSERT refact */
- { 182, -3 }, /* (48) refarg ::= ON DELETE refact */
- { 182, -3 }, /* (49) refarg ::= ON UPDATE refact */
- { 183, -2 }, /* (50) refact ::= SET NULL */
- { 183, -2 }, /* (51) refact ::= SET DEFAULT */
- { 183, -1 }, /* (52) refact ::= CASCADE */
- { 183, -1 }, /* (53) refact ::= RESTRICT */
- { 183, -2 }, /* (54) refact ::= NO ACTION */
- { 181, -3 }, /* (55) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
- { 181, -2 }, /* (56) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
- { 184, 0 }, /* (57) init_deferred_pred_opt ::= */
- { 184, -2 }, /* (58) init_deferred_pred_opt ::= INITIALLY DEFERRED */
- { 184, -2 }, /* (59) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
- { 162, 0 }, /* (60) conslist_opt ::= */
- { 186, -1 }, /* (61) tconscomma ::= COMMA */
- { 187, -2 }, /* (62) tcons ::= CONSTRAINT nm */
- { 187, -7 }, /* (63) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
- { 187, -5 }, /* (64) tcons ::= UNIQUE LP sortlist RP onconf */
- { 187, -5 }, /* (65) tcons ::= CHECK LP expr RP onconf */
- { 187, -10 }, /* (66) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
- { 190, 0 }, /* (67) defer_subclause_opt ::= */
- { 176, 0 }, /* (68) onconf ::= */
- { 176, -3 }, /* (69) onconf ::= ON CONFLICT resolvetype */
- { 191, 0 }, /* (70) orconf ::= */
- { 191, -2 }, /* (71) orconf ::= OR resolvetype */
- { 192, -1 }, /* (72) resolvetype ::= IGNORE */
- { 192, -1 }, /* (73) resolvetype ::= REPLACE */
- { 150, -4 }, /* (74) cmd ::= DROP TABLE ifexists fullname */
- { 194, -2 }, /* (75) ifexists ::= IF EXISTS */
- { 194, 0 }, /* (76) ifexists ::= */
- { 150, -9 }, /* (77) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
- { 150, -4 }, /* (78) cmd ::= DROP VIEW ifexists fullname */
- { 150, -1 }, /* (79) cmd ::= select */
- { 164, -3 }, /* (80) select ::= WITH wqlist selectnowith */
- { 164, -4 }, /* (81) select ::= WITH RECURSIVE wqlist selectnowith */
- { 164, -1 }, /* (82) select ::= selectnowith */
- { 196, -3 }, /* (83) selectnowith ::= selectnowith multiselect_op oneselect */
- { 199, -1 }, /* (84) multiselect_op ::= UNION */
- { 199, -2 }, /* (85) multiselect_op ::= UNION ALL */
- { 199, -1 }, /* (86) multiselect_op ::= EXCEPT|INTERSECT */
- { 197, -9 }, /* (87) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
- { 208, -4 }, /* (88) values ::= VALUES LP nexprlist RP */
- { 208, -5 }, /* (89) values ::= values COMMA LP exprlist RP */
- { 200, -1 }, /* (90) distinct ::= DISTINCT */
- { 200, -1 }, /* (91) distinct ::= ALL */
- { 200, 0 }, /* (92) distinct ::= */
- { 211, 0 }, /* (93) sclp ::= */
- { 201, -5 }, /* (94) selcollist ::= sclp scanpt expr scanpt as */
- { 201, -3 }, /* (95) selcollist ::= sclp scanpt STAR */
- { 201, -5 }, /* (96) selcollist ::= sclp scanpt nm DOT STAR */
- { 212, -2 }, /* (97) as ::= AS nm */
- { 212, 0 }, /* (98) as ::= */
- { 202, 0 }, /* (99) from ::= */
- { 202, -2 }, /* (100) from ::= FROM seltablist */
- { 214, -2 }, /* (101) stl_prefix ::= seltablist joinop */
- { 214, 0 }, /* (102) stl_prefix ::= */
- { 213, -7 }, /* (103) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
- { 213, -9 }, /* (104) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
- { 213, -7 }, /* (105) seltablist ::= stl_prefix LP select RP as on_opt using_opt */
- { 213, -7 }, /* (106) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
- { 160, 0 }, /* (107) dbnm ::= */
- { 160, -2 }, /* (108) dbnm ::= DOT nm */
- { 195, -1 }, /* (109) fullname ::= nm */
- { 195, -3 }, /* (110) fullname ::= nm DOT nm */
- { 219, -1 }, /* (111) xfullname ::= nm */
- { 219, -3 }, /* (112) xfullname ::= nm DOT nm */
- { 219, -5 }, /* (113) xfullname ::= nm DOT nm AS nm */
- { 219, -3 }, /* (114) xfullname ::= nm AS nm */
- { 215, -1 }, /* (115) joinop ::= COMMA|JOIN */
- { 215, -2 }, /* (116) joinop ::= JOIN_KW JOIN */
- { 215, -3 }, /* (117) joinop ::= JOIN_KW nm JOIN */
- { 215, -4 }, /* (118) joinop ::= JOIN_KW nm nm JOIN */
- { 217, -2 }, /* (119) on_opt ::= ON expr */
- { 217, 0 }, /* (120) on_opt ::= */
- { 216, 0 }, /* (121) indexed_opt ::= */
- { 216, -3 }, /* (122) indexed_opt ::= INDEXED BY nm */
- { 216, -2 }, /* (123) indexed_opt ::= NOT INDEXED */
- { 218, -4 }, /* (124) using_opt ::= USING LP idlist RP */
- { 218, 0 }, /* (125) using_opt ::= */
- { 206, 0 }, /* (126) orderby_opt ::= */
- { 206, -3 }, /* (127) orderby_opt ::= ORDER BY sortlist */
- { 188, -4 }, /* (128) sortlist ::= sortlist COMMA expr sortorder */
- { 188, -2 }, /* (129) sortlist ::= expr sortorder */
- { 177, -1 }, /* (130) sortorder ::= ASC */
- { 177, -1 }, /* (131) sortorder ::= DESC */
- { 177, 0 }, /* (132) sortorder ::= */
- { 204, 0 }, /* (133) groupby_opt ::= */
- { 204, -3 }, /* (134) groupby_opt ::= GROUP BY nexprlist */
- { 205, 0 }, /* (135) having_opt ::= */
- { 205, -2 }, /* (136) having_opt ::= HAVING expr */
- { 207, 0 }, /* (137) limit_opt ::= */
- { 207, -2 }, /* (138) limit_opt ::= LIMIT expr */
- { 207, -4 }, /* (139) limit_opt ::= LIMIT expr OFFSET expr */
- { 207, -4 }, /* (140) limit_opt ::= LIMIT expr COMMA expr */
- { 150, -6 }, /* (141) cmd ::= with DELETE FROM xfullname indexed_opt where_opt */
- { 203, 0 }, /* (142) where_opt ::= */
- { 203, -2 }, /* (143) where_opt ::= WHERE expr */
- { 150, -8 }, /* (144) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */
- { 222, -5 }, /* (145) setlist ::= setlist COMMA nm EQ expr */
- { 222, -7 }, /* (146) setlist ::= setlist COMMA LP idlist RP EQ expr */
- { 222, -3 }, /* (147) setlist ::= nm EQ expr */
- { 222, -5 }, /* (148) setlist ::= LP idlist RP EQ expr */
- { 150, -7 }, /* (149) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
- { 150, -7 }, /* (150) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
- { 225, 0 }, /* (151) upsert ::= */
- { 225, -11 }, /* (152) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
- { 225, -8 }, /* (153) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
- { 225, -4 }, /* (154) upsert ::= ON CONFLICT DO NOTHING */
- { 223, -2 }, /* (155) insert_cmd ::= INSERT orconf */
- { 223, -1 }, /* (156) insert_cmd ::= REPLACE */
- { 224, 0 }, /* (157) idlist_opt ::= */
- { 224, -3 }, /* (158) idlist_opt ::= LP idlist RP */
- { 220, -3 }, /* (159) idlist ::= idlist COMMA nm */
- { 220, -1 }, /* (160) idlist ::= nm */
- { 175, -3 }, /* (161) expr ::= LP expr RP */
- { 175, -1 }, /* (162) expr ::= ID|INDEXED */
- { 175, -1 }, /* (163) expr ::= JOIN_KW */
- { 175, -3 }, /* (164) expr ::= nm DOT nm */
- { 175, -5 }, /* (165) expr ::= nm DOT nm DOT nm */
- { 174, -1 }, /* (166) term ::= NULL|FLOAT|BLOB */
- { 174, -1 }, /* (167) term ::= STRING */
- { 174, -1 }, /* (168) term ::= INTEGER */
- { 175, -1 }, /* (169) expr ::= VARIABLE */
- { 175, -3 }, /* (170) expr ::= expr COLLATE ID|STRING */
- { 175, -6 }, /* (171) expr ::= CAST LP expr AS typetoken RP */
- { 175, -5 }, /* (172) expr ::= ID|INDEXED LP distinct exprlist RP */
- { 175, -4 }, /* (173) expr ::= ID|INDEXED LP STAR RP */
- { 174, -1 }, /* (174) term ::= CTIME_KW */
- { 175, -5 }, /* (175) expr ::= LP nexprlist COMMA expr RP */
- { 175, -3 }, /* (176) expr ::= expr AND expr */
- { 175, -3 }, /* (177) expr ::= expr OR expr */
- { 175, -3 }, /* (178) expr ::= expr LT|GT|GE|LE expr */
- { 175, -3 }, /* (179) expr ::= expr EQ|NE expr */
- { 175, -3 }, /* (180) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
- { 175, -3 }, /* (181) expr ::= expr PLUS|MINUS expr */
- { 175, -3 }, /* (182) expr ::= expr STAR|SLASH|REM expr */
- { 175, -3 }, /* (183) expr ::= expr CONCAT expr */
- { 226, -2 }, /* (184) likeop ::= NOT LIKE_KW|MATCH */
- { 175, -3 }, /* (185) expr ::= expr likeop expr */
- { 175, -5 }, /* (186) expr ::= expr likeop expr ESCAPE expr */
- { 175, -2 }, /* (187) expr ::= expr ISNULL|NOTNULL */
- { 175, -3 }, /* (188) expr ::= expr NOT NULL */
- { 175, -3 }, /* (189) expr ::= expr IS expr */
- { 175, -4 }, /* (190) expr ::= expr IS NOT expr */
- { 175, -2 }, /* (191) expr ::= NOT expr */
- { 175, -2 }, /* (192) expr ::= BITNOT expr */
- { 175, -2 }, /* (193) expr ::= MINUS expr */
- { 175, -2 }, /* (194) expr ::= PLUS expr */
- { 227, -1 }, /* (195) between_op ::= BETWEEN */
- { 227, -2 }, /* (196) between_op ::= NOT BETWEEN */
- { 175, -5 }, /* (197) expr ::= expr between_op expr AND expr */
- { 228, -1 }, /* (198) in_op ::= IN */
- { 228, -2 }, /* (199) in_op ::= NOT IN */
- { 175, -5 }, /* (200) expr ::= expr in_op LP exprlist RP */
- { 175, -3 }, /* (201) expr ::= LP select RP */
- { 175, -5 }, /* (202) expr ::= expr in_op LP select RP */
- { 175, -5 }, /* (203) expr ::= expr in_op nm dbnm paren_exprlist */
- { 175, -4 }, /* (204) expr ::= EXISTS LP select RP */
- { 175, -5 }, /* (205) expr ::= CASE case_operand case_exprlist case_else END */
- { 231, -5 }, /* (206) case_exprlist ::= case_exprlist WHEN expr THEN expr */
- { 231, -4 }, /* (207) case_exprlist ::= WHEN expr THEN expr */
- { 232, -2 }, /* (208) case_else ::= ELSE expr */
- { 232, 0 }, /* (209) case_else ::= */
- { 230, -1 }, /* (210) case_operand ::= expr */
- { 230, 0 }, /* (211) case_operand ::= */
- { 210, 0 }, /* (212) exprlist ::= */
- { 209, -3 }, /* (213) nexprlist ::= nexprlist COMMA expr */
- { 209, -1 }, /* (214) nexprlist ::= expr */
- { 229, 0 }, /* (215) paren_exprlist ::= */
- { 229, -3 }, /* (216) paren_exprlist ::= LP exprlist RP */
- { 150, -12 }, /* (217) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
- { 233, -1 }, /* (218) uniqueflag ::= UNIQUE */
- { 233, 0 }, /* (219) uniqueflag ::= */
- { 179, 0 }, /* (220) eidlist_opt ::= */
- { 179, -3 }, /* (221) eidlist_opt ::= LP eidlist RP */
- { 189, -5 }, /* (222) eidlist ::= eidlist COMMA nm collate sortorder */
- { 189, -3 }, /* (223) eidlist ::= nm collate sortorder */
- { 234, 0 }, /* (224) collate ::= */
- { 234, -2 }, /* (225) collate ::= COLLATE ID|STRING */
- { 150, -4 }, /* (226) cmd ::= DROP INDEX ifexists fullname */
- { 150, -1 }, /* (227) cmd ::= VACUUM */
- { 150, -2 }, /* (228) cmd ::= VACUUM nm */
- { 150, -3 }, /* (229) cmd ::= PRAGMA nm dbnm */
- { 150, -5 }, /* (230) cmd ::= PRAGMA nm dbnm EQ nmnum */
- { 150, -6 }, /* (231) cmd ::= PRAGMA nm dbnm LP nmnum RP */
- { 150, -5 }, /* (232) cmd ::= PRAGMA nm dbnm EQ minus_num */
- { 150, -6 }, /* (233) cmd ::= PRAGMA nm dbnm LP minus_num RP */
- { 170, -2 }, /* (234) plus_num ::= PLUS INTEGER|FLOAT */
- { 171, -2 }, /* (235) minus_num ::= MINUS INTEGER|FLOAT */
- { 150, -5 }, /* (236) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
- { 236, -11 }, /* (237) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
- { 238, -1 }, /* (238) trigger_time ::= BEFORE|AFTER */
- { 238, -2 }, /* (239) trigger_time ::= INSTEAD OF */
- { 238, 0 }, /* (240) trigger_time ::= */
- { 239, -1 }, /* (241) trigger_event ::= DELETE|INSERT */
- { 239, -1 }, /* (242) trigger_event ::= UPDATE */
- { 239, -3 }, /* (243) trigger_event ::= UPDATE OF idlist */
- { 241, 0 }, /* (244) when_clause ::= */
- { 241, -2 }, /* (245) when_clause ::= WHEN expr */
- { 237, -3 }, /* (246) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
- { 237, -2 }, /* (247) trigger_cmd_list ::= trigger_cmd SEMI */
- { 243, -3 }, /* (248) trnm ::= nm DOT nm */
- { 244, -3 }, /* (249) tridxby ::= INDEXED BY nm */
- { 244, -2 }, /* (250) tridxby ::= NOT INDEXED */
- { 242, -8 }, /* (251) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
- { 242, -8 }, /* (252) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
- { 242, -6 }, /* (253) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
- { 242, -3 }, /* (254) trigger_cmd ::= scanpt select scanpt */
- { 175, -4 }, /* (255) expr ::= RAISE LP IGNORE RP */
- { 175, -6 }, /* (256) expr ::= RAISE LP raisetype COMMA nm RP */
- { 193, -1 }, /* (257) raisetype ::= ROLLBACK */
- { 193, -1 }, /* (258) raisetype ::= ABORT */
- { 193, -1 }, /* (259) raisetype ::= FAIL */
- { 150, -4 }, /* (260) cmd ::= DROP TRIGGER ifexists fullname */
- { 150, -6 }, /* (261) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
- { 150, -3 }, /* (262) cmd ::= DETACH database_kw_opt expr */
- { 246, 0 }, /* (263) key_opt ::= */
- { 246, -2 }, /* (264) key_opt ::= KEY expr */
- { 150, -1 }, /* (265) cmd ::= REINDEX */
- { 150, -3 }, /* (266) cmd ::= REINDEX nm dbnm */
- { 150, -1 }, /* (267) cmd ::= ANALYZE */
- { 150, -3 }, /* (268) cmd ::= ANALYZE nm dbnm */
- { 150, -6 }, /* (269) cmd ::= ALTER TABLE fullname RENAME TO nm */
- { 150, -7 }, /* (270) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
- { 247, -1 }, /* (271) add_column_fullname ::= fullname */
- { 150, -1 }, /* (272) cmd ::= create_vtab */
- { 150, -4 }, /* (273) cmd ::= create_vtab LP vtabarglist RP */
- { 249, -8 }, /* (274) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
- { 251, 0 }, /* (275) vtabarg ::= */
- { 252, -1 }, /* (276) vtabargtoken ::= ANY */
- { 252, -3 }, /* (277) vtabargtoken ::= lp anylist RP */
- { 253, -1 }, /* (278) lp ::= LP */
- { 221, -2 }, /* (279) with ::= WITH wqlist */
- { 221, -3 }, /* (280) with ::= WITH RECURSIVE wqlist */
- { 198, -6 }, /* (281) wqlist ::= nm eidlist_opt AS LP select RP */
- { 198, -8 }, /* (282) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
- { 145, -1 }, /* (283) input ::= cmdlist */
- { 146, -2 }, /* (284) cmdlist ::= cmdlist ecmd */
- { 146, -1 }, /* (285) cmdlist ::= ecmd */
- { 147, -1 }, /* (286) ecmd ::= SEMI */
- { 147, -2 }, /* (287) ecmd ::= cmdx SEMI */
- { 147, -2 }, /* (288) ecmd ::= explain cmdx */
- { 152, 0 }, /* (289) trans_opt ::= */
- { 152, -1 }, /* (290) trans_opt ::= TRANSACTION */
- { 152, -2 }, /* (291) trans_opt ::= TRANSACTION nm */
- { 154, -1 }, /* (292) savepoint_opt ::= SAVEPOINT */
- { 154, 0 }, /* (293) savepoint_opt ::= */
- { 150, -2 }, /* (294) cmd ::= create_table create_table_args */
- { 161, -4 }, /* (295) columnlist ::= columnlist COMMA columnname carglist */
- { 161, -2 }, /* (296) columnlist ::= columnname carglist */
- { 153, -1 }, /* (297) nm ::= ID|INDEXED */
- { 153, -1 }, /* (298) nm ::= STRING */
- { 153, -1 }, /* (299) nm ::= JOIN_KW */
- { 167, -1 }, /* (300) typetoken ::= typename */
- { 168, -1 }, /* (301) typename ::= ID|STRING */
- { 169, -1 }, /* (302) signed ::= plus_num */
- { 169, -1 }, /* (303) signed ::= minus_num */
- { 166, -2 }, /* (304) carglist ::= carglist ccons */
- { 166, 0 }, /* (305) carglist ::= */
- { 173, -2 }, /* (306) ccons ::= NULL onconf */
- { 162, -2 }, /* (307) conslist_opt ::= COMMA conslist */
- { 185, -3 }, /* (308) conslist ::= conslist tconscomma tcons */
- { 185, -1 }, /* (309) conslist ::= tcons */
- { 186, 0 }, /* (310) tconscomma ::= */
- { 190, -1 }, /* (311) defer_subclause_opt ::= defer_subclause */
- { 192, -1 }, /* (312) resolvetype ::= raisetype */
- { 196, -1 }, /* (313) selectnowith ::= oneselect */
- { 197, -1 }, /* (314) oneselect ::= values */
- { 211, -2 }, /* (315) sclp ::= selcollist COMMA */
- { 212, -1 }, /* (316) as ::= ID|STRING */
- { 175, -1 }, /* (317) expr ::= term */
- { 226, -1 }, /* (318) likeop ::= LIKE_KW|MATCH */
- { 210, -1 }, /* (319) exprlist ::= nexprlist */
- { 235, -1 }, /* (320) nmnum ::= plus_num */
- { 235, -1 }, /* (321) nmnum ::= nm */
- { 235, -1 }, /* (322) nmnum ::= ON */
- { 235, -1 }, /* (323) nmnum ::= DELETE */
- { 235, -1 }, /* (324) nmnum ::= DEFAULT */
- { 170, -1 }, /* (325) plus_num ::= INTEGER|FLOAT */
- { 240, 0 }, /* (326) foreach_clause ::= */
- { 240, -3 }, /* (327) foreach_clause ::= FOR EACH ROW */
- { 243, -1 }, /* (328) trnm ::= nm */
- { 244, 0 }, /* (329) tridxby ::= */
- { 245, -1 }, /* (330) database_kw_opt ::= DATABASE */
- { 245, 0 }, /* (331) database_kw_opt ::= */
- { 248, 0 }, /* (332) kwcolumn_opt ::= */
- { 248, -1 }, /* (333) kwcolumn_opt ::= COLUMNKW */
- { 250, -1 }, /* (334) vtabarglist ::= vtabarg */
- { 250, -3 }, /* (335) vtabarglist ::= vtabarglist COMMA vtabarg */
- { 251, -2 }, /* (336) vtabarg ::= vtabarg vtabargtoken */
- { 254, 0 }, /* (337) anylist ::= */
- { 254, -4 }, /* (338) anylist ::= anylist LP anylist RP */
- { 254, -2 }, /* (339) anylist ::= anylist ANY */
- { 221, 0 }, /* (340) with ::= */
+ { 159, -1 }, /* (0) explain ::= EXPLAIN */
+ { 159, -3 }, /* (1) explain ::= EXPLAIN QUERY PLAN */
+ { 158, -1 }, /* (2) cmdx ::= cmd */
+ { 160, -3 }, /* (3) cmd ::= BEGIN transtype trans_opt */
+ { 161, 0 }, /* (4) transtype ::= */
+ { 161, -1 }, /* (5) transtype ::= DEFERRED */
+ { 161, -1 }, /* (6) transtype ::= IMMEDIATE */
+ { 161, -1 }, /* (7) transtype ::= EXCLUSIVE */
+ { 160, -2 }, /* (8) cmd ::= COMMIT|END trans_opt */
+ { 160, -2 }, /* (9) cmd ::= ROLLBACK trans_opt */
+ { 160, -2 }, /* (10) cmd ::= SAVEPOINT nm */
+ { 160, -3 }, /* (11) cmd ::= RELEASE savepoint_opt nm */
+ { 160, -5 }, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
+ { 165, -6 }, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */
+ { 167, -1 }, /* (14) createkw ::= CREATE */
+ { 169, 0 }, /* (15) ifnotexists ::= */
+ { 169, -3 }, /* (16) ifnotexists ::= IF NOT EXISTS */
+ { 168, -1 }, /* (17) temp ::= TEMP */
+ { 168, 0 }, /* (18) temp ::= */
+ { 166, -5 }, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_options */
+ { 166, -2 }, /* (20) create_table_args ::= AS select */
+ { 173, 0 }, /* (21) table_options ::= */
+ { 173, -2 }, /* (22) table_options ::= WITHOUT nm */
+ { 175, -2 }, /* (23) columnname ::= nm typetoken */
+ { 177, 0 }, /* (24) typetoken ::= */
+ { 177, -4 }, /* (25) typetoken ::= typename LP signed RP */
+ { 177, -6 }, /* (26) typetoken ::= typename LP signed COMMA signed RP */
+ { 178, -2 }, /* (27) typename ::= typename ID|STRING */
+ { 182, 0 }, /* (28) scanpt ::= */
+ { 183, -2 }, /* (29) ccons ::= CONSTRAINT nm */
+ { 183, -4 }, /* (30) ccons ::= DEFAULT scanpt term scanpt */
+ { 183, -4 }, /* (31) ccons ::= DEFAULT LP expr RP */
+ { 183, -4 }, /* (32) ccons ::= DEFAULT PLUS term scanpt */
+ { 183, -4 }, /* (33) ccons ::= DEFAULT MINUS term scanpt */
+ { 183, -3 }, /* (34) ccons ::= DEFAULT scanpt ID|INDEXED */
+ { 183, -3 }, /* (35) ccons ::= NOT NULL onconf */
+ { 183, -5 }, /* (36) ccons ::= PRIMARY KEY sortorder onconf autoinc */
+ { 183, -2 }, /* (37) ccons ::= UNIQUE onconf */
+ { 183, -4 }, /* (38) ccons ::= CHECK LP expr RP */
+ { 183, -4 }, /* (39) ccons ::= REFERENCES nm eidlist_opt refargs */
+ { 183, -1 }, /* (40) ccons ::= defer_subclause */
+ { 183, -2 }, /* (41) ccons ::= COLLATE ID|STRING */
+ { 188, 0 }, /* (42) autoinc ::= */
+ { 188, -1 }, /* (43) autoinc ::= AUTOINCR */
+ { 190, 0 }, /* (44) refargs ::= */
+ { 190, -2 }, /* (45) refargs ::= refargs refarg */
+ { 192, -2 }, /* (46) refarg ::= MATCH nm */
+ { 192, -3 }, /* (47) refarg ::= ON INSERT refact */
+ { 192, -3 }, /* (48) refarg ::= ON DELETE refact */
+ { 192, -3 }, /* (49) refarg ::= ON UPDATE refact */
+ { 193, -2 }, /* (50) refact ::= SET NULL */
+ { 193, -2 }, /* (51) refact ::= SET DEFAULT */
+ { 193, -1 }, /* (52) refact ::= CASCADE */
+ { 193, -1 }, /* (53) refact ::= RESTRICT */
+ { 193, -2 }, /* (54) refact ::= NO ACTION */
+ { 191, -3 }, /* (55) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
+ { 191, -2 }, /* (56) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
+ { 194, 0 }, /* (57) init_deferred_pred_opt ::= */
+ { 194, -2 }, /* (58) init_deferred_pred_opt ::= INITIALLY DEFERRED */
+ { 194, -2 }, /* (59) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
+ { 172, 0 }, /* (60) conslist_opt ::= */
+ { 196, -1 }, /* (61) tconscomma ::= COMMA */
+ { 197, -2 }, /* (62) tcons ::= CONSTRAINT nm */
+ { 197, -7 }, /* (63) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
+ { 197, -5 }, /* (64) tcons ::= UNIQUE LP sortlist RP onconf */
+ { 197, -5 }, /* (65) tcons ::= CHECK LP expr RP onconf */
+ { 197, -10 }, /* (66) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
+ { 200, 0 }, /* (67) defer_subclause_opt ::= */
+ { 186, 0 }, /* (68) onconf ::= */
+ { 186, -3 }, /* (69) onconf ::= ON CONFLICT resolvetype */
+ { 201, 0 }, /* (70) orconf ::= */
+ { 201, -2 }, /* (71) orconf ::= OR resolvetype */
+ { 202, -1 }, /* (72) resolvetype ::= IGNORE */
+ { 202, -1 }, /* (73) resolvetype ::= REPLACE */
+ { 160, -4 }, /* (74) cmd ::= DROP TABLE ifexists fullname */
+ { 204, -2 }, /* (75) ifexists ::= IF EXISTS */
+ { 204, 0 }, /* (76) ifexists ::= */
+ { 160, -9 }, /* (77) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
+ { 160, -4 }, /* (78) cmd ::= DROP VIEW ifexists fullname */
+ { 160, -1 }, /* (79) cmd ::= select */
+ { 174, -3 }, /* (80) select ::= WITH wqlist selectnowith */
+ { 174, -4 }, /* (81) select ::= WITH RECURSIVE wqlist selectnowith */
+ { 174, -1 }, /* (82) select ::= selectnowith */
+ { 206, -3 }, /* (83) selectnowith ::= selectnowith multiselect_op oneselect */
+ { 209, -1 }, /* (84) multiselect_op ::= UNION */
+ { 209, -2 }, /* (85) multiselect_op ::= UNION ALL */
+ { 209, -1 }, /* (86) multiselect_op ::= EXCEPT|INTERSECT */
+ { 207, -9 }, /* (87) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
+ { 207, -10 }, /* (88) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
+ { 219, -4 }, /* (89) values ::= VALUES LP nexprlist RP */
+ { 219, -5 }, /* (90) values ::= values COMMA LP nexprlist RP */
+ { 210, -1 }, /* (91) distinct ::= DISTINCT */
+ { 210, -1 }, /* (92) distinct ::= ALL */
+ { 210, 0 }, /* (93) distinct ::= */
+ { 221, 0 }, /* (94) sclp ::= */
+ { 211, -5 }, /* (95) selcollist ::= sclp scanpt expr scanpt as */
+ { 211, -3 }, /* (96) selcollist ::= sclp scanpt STAR */
+ { 211, -5 }, /* (97) selcollist ::= sclp scanpt nm DOT STAR */
+ { 222, -2 }, /* (98) as ::= AS nm */
+ { 222, 0 }, /* (99) as ::= */
+ { 212, 0 }, /* (100) from ::= */
+ { 212, -2 }, /* (101) from ::= FROM seltablist */
+ { 224, -2 }, /* (102) stl_prefix ::= seltablist joinop */
+ { 224, 0 }, /* (103) stl_prefix ::= */
+ { 223, -7 }, /* (104) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
+ { 223, -9 }, /* (105) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
+ { 223, -7 }, /* (106) seltablist ::= stl_prefix LP select RP as on_opt using_opt */
+ { 223, -7 }, /* (107) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
+ { 170, 0 }, /* (108) dbnm ::= */
+ { 170, -2 }, /* (109) dbnm ::= DOT nm */
+ { 205, -1 }, /* (110) fullname ::= nm */
+ { 205, -3 }, /* (111) fullname ::= nm DOT nm */
+ { 230, -1 }, /* (112) xfullname ::= nm */
+ { 230, -3 }, /* (113) xfullname ::= nm DOT nm */
+ { 230, -5 }, /* (114) xfullname ::= nm DOT nm AS nm */
+ { 230, -3 }, /* (115) xfullname ::= nm AS nm */
+ { 225, -1 }, /* (116) joinop ::= COMMA|JOIN */
+ { 225, -2 }, /* (117) joinop ::= JOIN_KW JOIN */
+ { 225, -3 }, /* (118) joinop ::= JOIN_KW nm JOIN */
+ { 225, -4 }, /* (119) joinop ::= JOIN_KW nm nm JOIN */
+ { 227, -2 }, /* (120) on_opt ::= ON expr */
+ { 227, 0 }, /* (121) on_opt ::= */
+ { 226, 0 }, /* (122) indexed_opt ::= */
+ { 226, -3 }, /* (123) indexed_opt ::= INDEXED BY nm */
+ { 226, -2 }, /* (124) indexed_opt ::= NOT INDEXED */
+ { 228, -4 }, /* (125) using_opt ::= USING LP idlist RP */
+ { 228, 0 }, /* (126) using_opt ::= */
+ { 216, 0 }, /* (127) orderby_opt ::= */
+ { 216, -3 }, /* (128) orderby_opt ::= ORDER BY sortlist */
+ { 198, -4 }, /* (129) sortlist ::= sortlist COMMA expr sortorder */
+ { 198, -2 }, /* (130) sortlist ::= expr sortorder */
+ { 187, -1 }, /* (131) sortorder ::= ASC */
+ { 187, -1 }, /* (132) sortorder ::= DESC */
+ { 187, 0 }, /* (133) sortorder ::= */
+ { 214, 0 }, /* (134) groupby_opt ::= */
+ { 214, -3 }, /* (135) groupby_opt ::= GROUP BY nexprlist */
+ { 215, 0 }, /* (136) having_opt ::= */
+ { 215, -2 }, /* (137) having_opt ::= HAVING expr */
+ { 217, 0 }, /* (138) limit_opt ::= */
+ { 217, -2 }, /* (139) limit_opt ::= LIMIT expr */
+ { 217, -4 }, /* (140) limit_opt ::= LIMIT expr OFFSET expr */
+ { 217, -4 }, /* (141) limit_opt ::= LIMIT expr COMMA expr */
+ { 160, -6 }, /* (142) cmd ::= with DELETE FROM xfullname indexed_opt where_opt */
+ { 213, 0 }, /* (143) where_opt ::= */
+ { 213, -2 }, /* (144) where_opt ::= WHERE expr */
+ { 160, -8 }, /* (145) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */
+ { 233, -5 }, /* (146) setlist ::= setlist COMMA nm EQ expr */
+ { 233, -7 }, /* (147) setlist ::= setlist COMMA LP idlist RP EQ expr */
+ { 233, -3 }, /* (148) setlist ::= nm EQ expr */
+ { 233, -5 }, /* (149) setlist ::= LP idlist RP EQ expr */
+ { 160, -7 }, /* (150) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
+ { 160, -7 }, /* (151) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
+ { 236, 0 }, /* (152) upsert ::= */
+ { 236, -11 }, /* (153) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
+ { 236, -8 }, /* (154) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
+ { 236, -4 }, /* (155) upsert ::= ON CONFLICT DO NOTHING */
+ { 234, -2 }, /* (156) insert_cmd ::= INSERT orconf */
+ { 234, -1 }, /* (157) insert_cmd ::= REPLACE */
+ { 235, 0 }, /* (158) idlist_opt ::= */
+ { 235, -3 }, /* (159) idlist_opt ::= LP idlist RP */
+ { 231, -3 }, /* (160) idlist ::= idlist COMMA nm */
+ { 231, -1 }, /* (161) idlist ::= nm */
+ { 185, -3 }, /* (162) expr ::= LP expr RP */
+ { 185, -1 }, /* (163) expr ::= ID|INDEXED */
+ { 185, -1 }, /* (164) expr ::= JOIN_KW */
+ { 185, -3 }, /* (165) expr ::= nm DOT nm */
+ { 185, -5 }, /* (166) expr ::= nm DOT nm DOT nm */
+ { 184, -1 }, /* (167) term ::= NULL|FLOAT|BLOB */
+ { 184, -1 }, /* (168) term ::= STRING */
+ { 184, -1 }, /* (169) term ::= INTEGER */
+ { 185, -1 }, /* (170) expr ::= VARIABLE */
+ { 185, -3 }, /* (171) expr ::= expr COLLATE ID|STRING */
+ { 185, -6 }, /* (172) expr ::= CAST LP expr AS typetoken RP */
+ { 185, -5 }, /* (173) expr ::= ID|INDEXED LP distinct exprlist RP */
+ { 185, -4 }, /* (174) expr ::= ID|INDEXED LP STAR RP */
+ { 185, -6 }, /* (175) expr ::= ID|INDEXED LP distinct exprlist RP over_clause */
+ { 185, -5 }, /* (176) expr ::= ID|INDEXED LP STAR RP over_clause */
+ { 184, -1 }, /* (177) term ::= CTIME_KW */
+ { 185, -5 }, /* (178) expr ::= LP nexprlist COMMA expr RP */
+ { 185, -3 }, /* (179) expr ::= expr AND expr */
+ { 185, -3 }, /* (180) expr ::= expr OR expr */
+ { 185, -3 }, /* (181) expr ::= expr LT|GT|GE|LE expr */
+ { 185, -3 }, /* (182) expr ::= expr EQ|NE expr */
+ { 185, -3 }, /* (183) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
+ { 185, -3 }, /* (184) expr ::= expr PLUS|MINUS expr */
+ { 185, -3 }, /* (185) expr ::= expr STAR|SLASH|REM expr */
+ { 185, -3 }, /* (186) expr ::= expr CONCAT expr */
+ { 238, -2 }, /* (187) likeop ::= NOT LIKE_KW|MATCH */
+ { 185, -3 }, /* (188) expr ::= expr likeop expr */
+ { 185, -5 }, /* (189) expr ::= expr likeop expr ESCAPE expr */
+ { 185, -2 }, /* (190) expr ::= expr ISNULL|NOTNULL */
+ { 185, -3 }, /* (191) expr ::= expr NOT NULL */
+ { 185, -3 }, /* (192) expr ::= expr IS expr */
+ { 185, -4 }, /* (193) expr ::= expr IS NOT expr */
+ { 185, -2 }, /* (194) expr ::= NOT expr */
+ { 185, -2 }, /* (195) expr ::= BITNOT expr */
+ { 185, -2 }, /* (196) expr ::= PLUS|MINUS expr */
+ { 239, -1 }, /* (197) between_op ::= BETWEEN */
+ { 239, -2 }, /* (198) between_op ::= NOT BETWEEN */
+ { 185, -5 }, /* (199) expr ::= expr between_op expr AND expr */
+ { 240, -1 }, /* (200) in_op ::= IN */
+ { 240, -2 }, /* (201) in_op ::= NOT IN */
+ { 185, -5 }, /* (202) expr ::= expr in_op LP exprlist RP */
+ { 185, -3 }, /* (203) expr ::= LP select RP */
+ { 185, -5 }, /* (204) expr ::= expr in_op LP select RP */
+ { 185, -5 }, /* (205) expr ::= expr in_op nm dbnm paren_exprlist */
+ { 185, -4 }, /* (206) expr ::= EXISTS LP select RP */
+ { 185, -5 }, /* (207) expr ::= CASE case_operand case_exprlist case_else END */
+ { 243, -5 }, /* (208) case_exprlist ::= case_exprlist WHEN expr THEN expr */
+ { 243, -4 }, /* (209) case_exprlist ::= WHEN expr THEN expr */
+ { 244, -2 }, /* (210) case_else ::= ELSE expr */
+ { 244, 0 }, /* (211) case_else ::= */
+ { 242, -1 }, /* (212) case_operand ::= expr */
+ { 242, 0 }, /* (213) case_operand ::= */
+ { 229, 0 }, /* (214) exprlist ::= */
+ { 220, -3 }, /* (215) nexprlist ::= nexprlist COMMA expr */
+ { 220, -1 }, /* (216) nexprlist ::= expr */
+ { 241, 0 }, /* (217) paren_exprlist ::= */
+ { 241, -3 }, /* (218) paren_exprlist ::= LP exprlist RP */
+ { 160, -12 }, /* (219) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
+ { 245, -1 }, /* (220) uniqueflag ::= UNIQUE */
+ { 245, 0 }, /* (221) uniqueflag ::= */
+ { 189, 0 }, /* (222) eidlist_opt ::= */
+ { 189, -3 }, /* (223) eidlist_opt ::= LP eidlist RP */
+ { 199, -5 }, /* (224) eidlist ::= eidlist COMMA nm collate sortorder */
+ { 199, -3 }, /* (225) eidlist ::= nm collate sortorder */
+ { 246, 0 }, /* (226) collate ::= */
+ { 246, -2 }, /* (227) collate ::= COLLATE ID|STRING */
+ { 160, -4 }, /* (228) cmd ::= DROP INDEX ifexists fullname */
+ { 160, -1 }, /* (229) cmd ::= VACUUM */
+ { 160, -2 }, /* (230) cmd ::= VACUUM nm */
+ { 160, -3 }, /* (231) cmd ::= PRAGMA nm dbnm */
+ { 160, -5 }, /* (232) cmd ::= PRAGMA nm dbnm EQ nmnum */
+ { 160, -6 }, /* (233) cmd ::= PRAGMA nm dbnm LP nmnum RP */
+ { 160, -5 }, /* (234) cmd ::= PRAGMA nm dbnm EQ minus_num */
+ { 160, -6 }, /* (235) cmd ::= PRAGMA nm dbnm LP minus_num RP */
+ { 180, -2 }, /* (236) plus_num ::= PLUS INTEGER|FLOAT */
+ { 181, -2 }, /* (237) minus_num ::= MINUS INTEGER|FLOAT */
+ { 160, -5 }, /* (238) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
+ { 248, -11 }, /* (239) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+ { 250, -1 }, /* (240) trigger_time ::= BEFORE|AFTER */
+ { 250, -2 }, /* (241) trigger_time ::= INSTEAD OF */
+ { 250, 0 }, /* (242) trigger_time ::= */
+ { 251, -1 }, /* (243) trigger_event ::= DELETE|INSERT */
+ { 251, -1 }, /* (244) trigger_event ::= UPDATE */
+ { 251, -3 }, /* (245) trigger_event ::= UPDATE OF idlist */
+ { 253, 0 }, /* (246) when_clause ::= */
+ { 253, -2 }, /* (247) when_clause ::= WHEN expr */
+ { 249, -3 }, /* (248) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+ { 249, -2 }, /* (249) trigger_cmd_list ::= trigger_cmd SEMI */
+ { 255, -3 }, /* (250) trnm ::= nm DOT nm */
+ { 256, -3 }, /* (251) tridxby ::= INDEXED BY nm */
+ { 256, -2 }, /* (252) tridxby ::= NOT INDEXED */
+ { 254, -8 }, /* (253) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
+ { 254, -8 }, /* (254) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
+ { 254, -6 }, /* (255) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
+ { 254, -3 }, /* (256) trigger_cmd ::= scanpt select scanpt */
+ { 185, -4 }, /* (257) expr ::= RAISE LP IGNORE RP */
+ { 185, -6 }, /* (258) expr ::= RAISE LP raisetype COMMA nm RP */
+ { 203, -1 }, /* (259) raisetype ::= ROLLBACK */
+ { 203, -1 }, /* (260) raisetype ::= ABORT */
+ { 203, -1 }, /* (261) raisetype ::= FAIL */
+ { 160, -4 }, /* (262) cmd ::= DROP TRIGGER ifexists fullname */
+ { 160, -6 }, /* (263) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+ { 160, -3 }, /* (264) cmd ::= DETACH database_kw_opt expr */
+ { 258, 0 }, /* (265) key_opt ::= */
+ { 258, -2 }, /* (266) key_opt ::= KEY expr */
+ { 160, -1 }, /* (267) cmd ::= REINDEX */
+ { 160, -3 }, /* (268) cmd ::= REINDEX nm dbnm */
+ { 160, -1 }, /* (269) cmd ::= ANALYZE */
+ { 160, -3 }, /* (270) cmd ::= ANALYZE nm dbnm */
+ { 160, -6 }, /* (271) cmd ::= ALTER TABLE fullname RENAME TO nm */
+ { 160, -7 }, /* (272) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
+ { 259, -1 }, /* (273) add_column_fullname ::= fullname */
+ { 160, -8 }, /* (274) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
+ { 160, -1 }, /* (275) cmd ::= create_vtab */
+ { 160, -4 }, /* (276) cmd ::= create_vtab LP vtabarglist RP */
+ { 261, -8 }, /* (277) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+ { 263, 0 }, /* (278) vtabarg ::= */
+ { 264, -1 }, /* (279) vtabargtoken ::= ANY */
+ { 264, -3 }, /* (280) vtabargtoken ::= lp anylist RP */
+ { 265, -1 }, /* (281) lp ::= LP */
+ { 232, -2 }, /* (282) with ::= WITH wqlist */
+ { 232, -3 }, /* (283) with ::= WITH RECURSIVE wqlist */
+ { 208, -6 }, /* (284) wqlist ::= nm eidlist_opt AS LP select RP */
+ { 208, -8 }, /* (285) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
+ { 267, -1 }, /* (286) windowdefn_list ::= windowdefn */
+ { 267, -3 }, /* (287) windowdefn_list ::= windowdefn_list COMMA windowdefn */
+ { 268, -3 }, /* (288) windowdefn ::= nm AS window */
+ { 269, -5 }, /* (289) window ::= LP part_opt orderby_opt frame_opt RP */
+ { 271, -3 }, /* (290) part_opt ::= PARTITION BY nexprlist */
+ { 271, 0 }, /* (291) part_opt ::= */
+ { 270, 0 }, /* (292) frame_opt ::= */
+ { 270, -2 }, /* (293) frame_opt ::= range_or_rows frame_bound_s */
+ { 270, -5 }, /* (294) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e */
+ { 273, -1 }, /* (295) range_or_rows ::= RANGE */
+ { 273, -1 }, /* (296) range_or_rows ::= ROWS */
+ { 275, -1 }, /* (297) frame_bound_s ::= frame_bound */
+ { 275, -2 }, /* (298) frame_bound_s ::= UNBOUNDED PRECEDING */
+ { 276, -1 }, /* (299) frame_bound_e ::= frame_bound */
+ { 276, -2 }, /* (300) frame_bound_e ::= UNBOUNDED FOLLOWING */
+ { 274, -2 }, /* (301) frame_bound ::= expr PRECEDING */
+ { 274, -2 }, /* (302) frame_bound ::= CURRENT ROW */
+ { 274, -2 }, /* (303) frame_bound ::= expr FOLLOWING */
+ { 218, -2 }, /* (304) window_clause ::= WINDOW windowdefn_list */
+ { 237, -3 }, /* (305) over_clause ::= filter_opt OVER window */
+ { 237, -3 }, /* (306) over_clause ::= filter_opt OVER nm */
+ { 272, 0 }, /* (307) filter_opt ::= */
+ { 272, -5 }, /* (308) filter_opt ::= FILTER LP WHERE expr RP */
+ { 155, -1 }, /* (309) input ::= cmdlist */
+ { 156, -2 }, /* (310) cmdlist ::= cmdlist ecmd */
+ { 156, -1 }, /* (311) cmdlist ::= ecmd */
+ { 157, -1 }, /* (312) ecmd ::= SEMI */
+ { 157, -2 }, /* (313) ecmd ::= cmdx SEMI */
+ { 157, -2 }, /* (314) ecmd ::= explain cmdx */
+ { 162, 0 }, /* (315) trans_opt ::= */
+ { 162, -1 }, /* (316) trans_opt ::= TRANSACTION */
+ { 162, -2 }, /* (317) trans_opt ::= TRANSACTION nm */
+ { 164, -1 }, /* (318) savepoint_opt ::= SAVEPOINT */
+ { 164, 0 }, /* (319) savepoint_opt ::= */
+ { 160, -2 }, /* (320) cmd ::= create_table create_table_args */
+ { 171, -4 }, /* (321) columnlist ::= columnlist COMMA columnname carglist */
+ { 171, -2 }, /* (322) columnlist ::= columnname carglist */
+ { 163, -1 }, /* (323) nm ::= ID|INDEXED */
+ { 163, -1 }, /* (324) nm ::= STRING */
+ { 163, -1 }, /* (325) nm ::= JOIN_KW */
+ { 177, -1 }, /* (326) typetoken ::= typename */
+ { 178, -1 }, /* (327) typename ::= ID|STRING */
+ { 179, -1 }, /* (328) signed ::= plus_num */
+ { 179, -1 }, /* (329) signed ::= minus_num */
+ { 176, -2 }, /* (330) carglist ::= carglist ccons */
+ { 176, 0 }, /* (331) carglist ::= */
+ { 183, -2 }, /* (332) ccons ::= NULL onconf */
+ { 172, -2 }, /* (333) conslist_opt ::= COMMA conslist */
+ { 195, -3 }, /* (334) conslist ::= conslist tconscomma tcons */
+ { 195, -1 }, /* (335) conslist ::= tcons */
+ { 196, 0 }, /* (336) tconscomma ::= */
+ { 200, -1 }, /* (337) defer_subclause_opt ::= defer_subclause */
+ { 202, -1 }, /* (338) resolvetype ::= raisetype */
+ { 206, -1 }, /* (339) selectnowith ::= oneselect */
+ { 207, -1 }, /* (340) oneselect ::= values */
+ { 221, -2 }, /* (341) sclp ::= selcollist COMMA */
+ { 222, -1 }, /* (342) as ::= ID|STRING */
+ { 185, -1 }, /* (343) expr ::= term */
+ { 238, -1 }, /* (344) likeop ::= LIKE_KW|MATCH */
+ { 229, -1 }, /* (345) exprlist ::= nexprlist */
+ { 247, -1 }, /* (346) nmnum ::= plus_num */
+ { 247, -1 }, /* (347) nmnum ::= nm */
+ { 247, -1 }, /* (348) nmnum ::= ON */
+ { 247, -1 }, /* (349) nmnum ::= DELETE */
+ { 247, -1 }, /* (350) nmnum ::= DEFAULT */
+ { 180, -1 }, /* (351) plus_num ::= INTEGER|FLOAT */
+ { 252, 0 }, /* (352) foreach_clause ::= */
+ { 252, -3 }, /* (353) foreach_clause ::= FOR EACH ROW */
+ { 255, -1 }, /* (354) trnm ::= nm */
+ { 256, 0 }, /* (355) tridxby ::= */
+ { 257, -1 }, /* (356) database_kw_opt ::= DATABASE */
+ { 257, 0 }, /* (357) database_kw_opt ::= */
+ { 260, 0 }, /* (358) kwcolumn_opt ::= */
+ { 260, -1 }, /* (359) kwcolumn_opt ::= COLUMNKW */
+ { 262, -1 }, /* (360) vtabarglist ::= vtabarg */
+ { 262, -3 }, /* (361) vtabarglist ::= vtabarglist COMMA vtabarg */
+ { 263, -2 }, /* (362) vtabarg ::= vtabarg vtabargtoken */
+ { 266, 0 }, /* (363) anylist ::= */
+ { 266, -4 }, /* (364) anylist ::= anylist LP anylist RP */
+ { 266, -2 }, /* (365) anylist ::= anylist ANY */
+ { 232, 0 }, /* (366) with ::= */
};
static void yy_accept(yyParser*); /* Forward Declaration */
@@ -143862,7 +148577,7 @@ static YYACTIONTYPE yy_reduce(
sqlite3ParserCTX_PDECL /* %extra_context */
){
int yygoto; /* The next state */
- int yyact; /* The next action */
+ YYACTIONTYPE yyact; /* The next action */
yyStackEntry *yymsp; /* The top of the parser's stack */
int yysize; /* Amount to pop the stack */
sqlite3ParserARG_FETCH
@@ -143936,15 +148651,15 @@ static YYACTIONTYPE yy_reduce(
{ sqlite3FinishCoding(pParse); }
break;
case 3: /* cmd ::= BEGIN transtype trans_opt */
-{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy502);}
+{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy70);}
break;
case 4: /* transtype ::= */
-{yymsp[1].minor.yy502 = TK_DEFERRED;}
+{yymsp[1].minor.yy70 = TK_DEFERRED;}
break;
case 5: /* transtype ::= DEFERRED */
case 6: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==6);
case 7: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7);
-{yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-X*/}
+{yymsp[0].minor.yy70 = yymsp[0].major; /*A-overwrites-X*/}
break;
case 8: /* cmd ::= COMMIT|END trans_opt */
case 9: /* cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==9);
@@ -143967,7 +148682,7 @@ static YYACTIONTYPE yy_reduce(
break;
case 13: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */
{
- sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy502,0,0,yymsp[-2].minor.yy502);
+ sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy70,0,0,yymsp[-2].minor.yy70);
}
break;
case 14: /* createkw ::= CREATE */
@@ -143980,34 +148695,34 @@ static YYACTIONTYPE yy_reduce(
case 57: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==57);
case 67: /* defer_subclause_opt ::= */ yytestcase(yyruleno==67);
case 76: /* ifexists ::= */ yytestcase(yyruleno==76);
- case 92: /* distinct ::= */ yytestcase(yyruleno==92);
- case 224: /* collate ::= */ yytestcase(yyruleno==224);
-{yymsp[1].minor.yy502 = 0;}
+ case 93: /* distinct ::= */ yytestcase(yyruleno==93);
+ case 226: /* collate ::= */ yytestcase(yyruleno==226);
+{yymsp[1].minor.yy70 = 0;}
break;
case 16: /* ifnotexists ::= IF NOT EXISTS */
-{yymsp[-2].minor.yy502 = 1;}
+{yymsp[-2].minor.yy70 = 1;}
break;
case 17: /* temp ::= TEMP */
case 43: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==43);
-{yymsp[0].minor.yy502 = 1;}
+{yymsp[0].minor.yy70 = 1;}
break;
case 19: /* create_table_args ::= LP columnlist conslist_opt RP table_options */
{
- sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy502,0);
+ sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy70,0);
}
break;
case 20: /* create_table_args ::= AS select */
{
- sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy399);
- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy399);
+ sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy489);
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy489);
}
break;
case 22: /* table_options ::= WITHOUT nm */
{
if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){
- yymsp[-1].minor.yy502 = TF_WithoutRowid | TF_NoVisibleRowid;
+ yymsp[-1].minor.yy70 = TF_WithoutRowid | TF_NoVisibleRowid;
}else{
- yymsp[-1].minor.yy502 = 0;
+ yymsp[-1].minor.yy70 = 0;
sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z);
}
}
@@ -144017,7 +148732,7 @@ static YYACTIONTYPE yy_reduce(
break;
case 24: /* typetoken ::= */
case 60: /* conslist_opt ::= */ yytestcase(yyruleno==60);
- case 98: /* as ::= */ yytestcase(yyruleno==98);
+ case 99: /* as ::= */ yytestcase(yyruleno==99);
{yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = 0;}
break;
case 25: /* typetoken ::= typename LP signed RP */
@@ -144036,7 +148751,7 @@ static YYACTIONTYPE yy_reduce(
case 28: /* scanpt ::= */
{
assert( yyLookahead!=YYNOCODE );
- yymsp[1].minor.yy36 = yyLookaheadToken.z;
+ yymsp[1].minor.yy392 = yyLookaheadToken.z;
}
break;
case 29: /* ccons ::= CONSTRAINT nm */
@@ -144044,18 +148759,18 @@ static YYACTIONTYPE yy_reduce(
{pParse->constraintName = yymsp[0].minor.yy0;}
break;
case 30: /* ccons ::= DEFAULT scanpt term scanpt */
-{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy182,yymsp[-2].minor.yy36,yymsp[0].minor.yy36);}
+{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy18,yymsp[-2].minor.yy392,yymsp[0].minor.yy392);}
break;
case 31: /* ccons ::= DEFAULT LP expr RP */
-{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy182,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);}
+{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy18,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);}
break;
case 32: /* ccons ::= DEFAULT PLUS term scanpt */
-{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy182,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy36);}
+{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy18,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy392);}
break;
case 33: /* ccons ::= DEFAULT MINUS term scanpt */
{
- Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[-1].minor.yy182, 0);
- sqlite3AddDefaultValue(pParse,p,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy36);
+ Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[-1].minor.yy18, 0);
+ sqlite3AddDefaultValue(pParse,p,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy392);
}
break;
case 34: /* ccons ::= DEFAULT scanpt ID|INDEXED */
@@ -144065,174 +148780,174 @@ static YYACTIONTYPE yy_reduce(
sqlite3ExprIdToTrueFalse(p);
testcase( p->op==TK_TRUEFALSE && sqlite3ExprTruthValue(p) );
}
- sqlite3AddDefaultValue(pParse,p,yymsp[0].minor.yy0.z,yymsp[0].minor.yy0.z+yymsp[0].minor.yy0.n);
+ sqlite3AddDefaultValue(pParse,p,yymsp[0].minor.yy0.z,yymsp[0].minor.yy0.z+yymsp[0].minor.yy0.n);
}
break;
case 35: /* ccons ::= NOT NULL onconf */
-{sqlite3AddNotNull(pParse, yymsp[0].minor.yy502);}
+{sqlite3AddNotNull(pParse, yymsp[0].minor.yy70);}
break;
case 36: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
-{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy502,yymsp[0].minor.yy502,yymsp[-2].minor.yy502);}
+{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy70,yymsp[0].minor.yy70,yymsp[-2].minor.yy70);}
break;
case 37: /* ccons ::= UNIQUE onconf */
-{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy502,0,0,0,0,
+{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy70,0,0,0,0,
SQLITE_IDXTYPE_UNIQUE);}
break;
case 38: /* ccons ::= CHECK LP expr RP */
-{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy182);}
+{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy18);}
break;
case 39: /* ccons ::= REFERENCES nm eidlist_opt refargs */
-{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy232,yymsp[0].minor.yy502);}
+{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy420,yymsp[0].minor.yy70);}
break;
case 40: /* ccons ::= defer_subclause */
-{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy502);}
+{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy70);}
break;
case 41: /* ccons ::= COLLATE ID|STRING */
{sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);}
break;
case 44: /* refargs ::= */
-{ yymsp[1].minor.yy502 = OE_None*0x0101; /* EV: R-19803-45884 */}
+{ yymsp[1].minor.yy70 = OE_None*0x0101; /* EV: R-19803-45884 */}
break;
case 45: /* refargs ::= refargs refarg */
-{ yymsp[-1].minor.yy502 = (yymsp[-1].minor.yy502 & ~yymsp[0].minor.yy107.mask) | yymsp[0].minor.yy107.value; }
+{ yymsp[-1].minor.yy70 = (yymsp[-1].minor.yy70 & ~yymsp[0].minor.yy111.mask) | yymsp[0].minor.yy111.value; }
break;
case 46: /* refarg ::= MATCH nm */
-{ yymsp[-1].minor.yy107.value = 0; yymsp[-1].minor.yy107.mask = 0x000000; }
+{ yymsp[-1].minor.yy111.value = 0; yymsp[-1].minor.yy111.mask = 0x000000; }
break;
case 47: /* refarg ::= ON INSERT refact */
-{ yymsp[-2].minor.yy107.value = 0; yymsp[-2].minor.yy107.mask = 0x000000; }
+{ yymsp[-2].minor.yy111.value = 0; yymsp[-2].minor.yy111.mask = 0x000000; }
break;
case 48: /* refarg ::= ON DELETE refact */
-{ yymsp[-2].minor.yy107.value = yymsp[0].minor.yy502; yymsp[-2].minor.yy107.mask = 0x0000ff; }
+{ yymsp[-2].minor.yy111.value = yymsp[0].minor.yy70; yymsp[-2].minor.yy111.mask = 0x0000ff; }
break;
case 49: /* refarg ::= ON UPDATE refact */
-{ yymsp[-2].minor.yy107.value = yymsp[0].minor.yy502<<8; yymsp[-2].minor.yy107.mask = 0x00ff00; }
+{ yymsp[-2].minor.yy111.value = yymsp[0].minor.yy70<<8; yymsp[-2].minor.yy111.mask = 0x00ff00; }
break;
case 50: /* refact ::= SET NULL */
-{ yymsp[-1].minor.yy502 = OE_SetNull; /* EV: R-33326-45252 */}
+{ yymsp[-1].minor.yy70 = OE_SetNull; /* EV: R-33326-45252 */}
break;
case 51: /* refact ::= SET DEFAULT */
-{ yymsp[-1].minor.yy502 = OE_SetDflt; /* EV: R-33326-45252 */}
+{ yymsp[-1].minor.yy70 = OE_SetDflt; /* EV: R-33326-45252 */}
break;
case 52: /* refact ::= CASCADE */
-{ yymsp[0].minor.yy502 = OE_Cascade; /* EV: R-33326-45252 */}
+{ yymsp[0].minor.yy70 = OE_Cascade; /* EV: R-33326-45252 */}
break;
case 53: /* refact ::= RESTRICT */
-{ yymsp[0].minor.yy502 = OE_Restrict; /* EV: R-33326-45252 */}
+{ yymsp[0].minor.yy70 = OE_Restrict; /* EV: R-33326-45252 */}
break;
case 54: /* refact ::= NO ACTION */
-{ yymsp[-1].minor.yy502 = OE_None; /* EV: R-33326-45252 */}
+{ yymsp[-1].minor.yy70 = OE_None; /* EV: R-33326-45252 */}
break;
case 55: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
-{yymsp[-2].minor.yy502 = 0;}
+{yymsp[-2].minor.yy70 = 0;}
break;
case 56: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
case 71: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==71);
- case 155: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==155);
-{yymsp[-1].minor.yy502 = yymsp[0].minor.yy502;}
+ case 156: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==156);
+{yymsp[-1].minor.yy70 = yymsp[0].minor.yy70;}
break;
case 58: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */
case 75: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==75);
- case 196: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==196);
- case 199: /* in_op ::= NOT IN */ yytestcase(yyruleno==199);
- case 225: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==225);
-{yymsp[-1].minor.yy502 = 1;}
+ case 198: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==198);
+ case 201: /* in_op ::= NOT IN */ yytestcase(yyruleno==201);
+ case 227: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==227);
+{yymsp[-1].minor.yy70 = 1;}
break;
case 59: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
-{yymsp[-1].minor.yy502 = 0;}
+{yymsp[-1].minor.yy70 = 0;}
break;
case 61: /* tconscomma ::= COMMA */
{pParse->constraintName.n = 0;}
break;
case 63: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
-{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy232,yymsp[0].minor.yy502,yymsp[-2].minor.yy502,0);}
+{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy420,yymsp[0].minor.yy70,yymsp[-2].minor.yy70,0);}
break;
case 64: /* tcons ::= UNIQUE LP sortlist RP onconf */
-{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy232,yymsp[0].minor.yy502,0,0,0,0,
+{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy420,yymsp[0].minor.yy70,0,0,0,0,
SQLITE_IDXTYPE_UNIQUE);}
break;
case 65: /* tcons ::= CHECK LP expr RP onconf */
-{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy182);}
+{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy18);}
break;
case 66: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
{
- sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy232, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy232, yymsp[-1].minor.yy502);
- sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy502);
+ sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy420, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy420, yymsp[-1].minor.yy70);
+ sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy70);
}
break;
case 68: /* onconf ::= */
case 70: /* orconf ::= */ yytestcase(yyruleno==70);
-{yymsp[1].minor.yy502 = OE_Default;}
+{yymsp[1].minor.yy70 = OE_Default;}
break;
case 69: /* onconf ::= ON CONFLICT resolvetype */
-{yymsp[-2].minor.yy502 = yymsp[0].minor.yy502;}
+{yymsp[-2].minor.yy70 = yymsp[0].minor.yy70;}
break;
case 72: /* resolvetype ::= IGNORE */
-{yymsp[0].minor.yy502 = OE_Ignore;}
+{yymsp[0].minor.yy70 = OE_Ignore;}
break;
case 73: /* resolvetype ::= REPLACE */
- case 156: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==156);
-{yymsp[0].minor.yy502 = OE_Replace;}
+ case 157: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==157);
+{yymsp[0].minor.yy70 = OE_Replace;}
break;
case 74: /* cmd ::= DROP TABLE ifexists fullname */
{
- sqlite3DropTable(pParse, yymsp[0].minor.yy427, 0, yymsp[-1].minor.yy502);
+ sqlite3DropTable(pParse, yymsp[0].minor.yy135, 0, yymsp[-1].minor.yy70);
}
break;
case 77: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
{
- sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy232, yymsp[0].minor.yy399, yymsp[-7].minor.yy502, yymsp[-5].minor.yy502);
+ sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy420, yymsp[0].minor.yy489, yymsp[-7].minor.yy70, yymsp[-5].minor.yy70);
}
break;
case 78: /* cmd ::= DROP VIEW ifexists fullname */
{
- sqlite3DropTable(pParse, yymsp[0].minor.yy427, 1, yymsp[-1].minor.yy502);
+ sqlite3DropTable(pParse, yymsp[0].minor.yy135, 1, yymsp[-1].minor.yy70);
}
break;
case 79: /* cmd ::= select */
{
SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0};
- sqlite3Select(pParse, yymsp[0].minor.yy399, &dest);
- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy399);
+ sqlite3Select(pParse, yymsp[0].minor.yy489, &dest);
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy489);
}
break;
case 80: /* select ::= WITH wqlist selectnowith */
{
- Select *p = yymsp[0].minor.yy399;
+ Select *p = yymsp[0].minor.yy489;
if( p ){
- p->pWith = yymsp[-1].minor.yy91;
+ p->pWith = yymsp[-1].minor.yy449;
parserDoubleLinkSelect(pParse, p);
}else{
- sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy91);
+ sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy449);
}
- yymsp[-2].minor.yy399 = p;
+ yymsp[-2].minor.yy489 = p;
}
break;
case 81: /* select ::= WITH RECURSIVE wqlist selectnowith */
{
- Select *p = yymsp[0].minor.yy399;
+ Select *p = yymsp[0].minor.yy489;
if( p ){
- p->pWith = yymsp[-1].minor.yy91;
+ p->pWith = yymsp[-1].minor.yy449;
parserDoubleLinkSelect(pParse, p);
}else{
- sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy91);
+ sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy449);
}
- yymsp[-3].minor.yy399 = p;
+ yymsp[-3].minor.yy489 = p;
}
break;
case 82: /* select ::= selectnowith */
{
- Select *p = yymsp[0].minor.yy399;
+ Select *p = yymsp[0].minor.yy489;
if( p ){
parserDoubleLinkSelect(pParse, p);
}
- yymsp[0].minor.yy399 = p; /*A-overwrites-X*/
+ yymsp[0].minor.yy489 = p; /*A-overwrites-X*/
}
break;
case 83: /* selectnowith ::= selectnowith multiselect_op oneselect */
{
- Select *pRhs = yymsp[0].minor.yy399;
- Select *pLhs = yymsp[-2].minor.yy399;
+ Select *pRhs = yymsp[0].minor.yy489;
+ Select *pLhs = yymsp[-2].minor.yy489;
if( pRhs && pRhs->pPrior ){
SrcList *pFrom;
Token x;
@@ -144242,378 +148957,382 @@ static YYACTIONTYPE yy_reduce(
pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0);
}
if( pRhs ){
- pRhs->op = (u8)yymsp[-1].minor.yy502;
+ pRhs->op = (u8)yymsp[-1].minor.yy70;
pRhs->pPrior = pLhs;
if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue;
pRhs->selFlags &= ~SF_MultiValue;
- if( yymsp[-1].minor.yy502!=TK_ALL ) pParse->hasCompound = 1;
+ if( yymsp[-1].minor.yy70!=TK_ALL ) pParse->hasCompound = 1;
}else{
sqlite3SelectDelete(pParse->db, pLhs);
}
- yymsp[-2].minor.yy399 = pRhs;
+ yymsp[-2].minor.yy489 = pRhs;
}
break;
case 84: /* multiselect_op ::= UNION */
case 86: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==86);
-{yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-OP*/}
+{yymsp[0].minor.yy70 = yymsp[0].major; /*A-overwrites-OP*/}
break;
case 85: /* multiselect_op ::= UNION ALL */
-{yymsp[-1].minor.yy502 = TK_ALL;}
+{yymsp[-1].minor.yy70 = TK_ALL;}
break;
case 87: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
{
-#if SELECTTRACE_ENABLED
- Token s = yymsp[-8].minor.yy0; /*A-overwrites-S*/
-#endif
- yymsp[-8].minor.yy399 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy232,yymsp[-5].minor.yy427,yymsp[-4].minor.yy182,yymsp[-3].minor.yy232,yymsp[-2].minor.yy182,yymsp[-1].minor.yy232,yymsp[-7].minor.yy502,yymsp[0].minor.yy182);
-#if SELECTTRACE_ENABLED
- /* Populate the Select.zSelName[] string that is used to help with
- ** query planner debugging, to differentiate between multiple Select
- ** objects in a complex query.
- **
- ** If the SELECT keyword is immediately followed by a C-style comment
- ** then extract the first few alphanumeric characters from within that
- ** comment to be the zSelName value. Otherwise, the label is #N where
- ** is an integer that is incremented with each SELECT statement seen.
- */
- if( yymsp[-8].minor.yy399!=0 ){
- const char *z = s.z+6;
- int i;
- sqlite3_snprintf(sizeof(yymsp[-8].minor.yy399->zSelName), yymsp[-8].minor.yy399->zSelName,"#%d",++pParse->nSelect);
- while( z[0]==' ' ) z++;
- if( z[0]=='/' && z[1]=='*' ){
- z += 2;
- while( z[0]==' ' ) z++;
- for(i=0; sqlite3Isalnum(z[i]); i++){}
- sqlite3_snprintf(sizeof(yymsp[-8].minor.yy399->zSelName), yymsp[-8].minor.yy399->zSelName, "%.*s", i, z);
- }
+ yymsp[-8].minor.yy489 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy420,yymsp[-5].minor.yy135,yymsp[-4].minor.yy18,yymsp[-3].minor.yy420,yymsp[-2].minor.yy18,yymsp[-1].minor.yy420,yymsp[-7].minor.yy70,yymsp[0].minor.yy18);
+}
+ break;
+ case 88: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
+{
+ yymsp[-9].minor.yy489 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy420,yymsp[-6].minor.yy135,yymsp[-5].minor.yy18,yymsp[-4].minor.yy420,yymsp[-3].minor.yy18,yymsp[-1].minor.yy420,yymsp[-8].minor.yy70,yymsp[0].minor.yy18);
+ if( yymsp[-9].minor.yy489 ){
+ yymsp[-9].minor.yy489->pWinDefn = yymsp[-2].minor.yy327;
+ }else{
+ sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy327);
}
-#endif /* SELECTRACE_ENABLED */
}
break;
- case 88: /* values ::= VALUES LP nexprlist RP */
+ case 89: /* values ::= VALUES LP nexprlist RP */
{
- yymsp[-3].minor.yy399 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy232,0,0,0,0,0,SF_Values,0);
+ yymsp[-3].minor.yy489 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy420,0,0,0,0,0,SF_Values,0);
}
break;
- case 89: /* values ::= values COMMA LP exprlist RP */
+ case 90: /* values ::= values COMMA LP nexprlist RP */
{
- Select *pRight, *pLeft = yymsp[-4].minor.yy399;
- pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy232,0,0,0,0,0,SF_Values|SF_MultiValue,0);
+ Select *pRight, *pLeft = yymsp[-4].minor.yy489;
+ pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy420,0,0,0,0,0,SF_Values|SF_MultiValue,0);
if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue;
if( pRight ){
pRight->op = TK_ALL;
pRight->pPrior = pLeft;
- yymsp[-4].minor.yy399 = pRight;
+ yymsp[-4].minor.yy489 = pRight;
}else{
- yymsp[-4].minor.yy399 = pLeft;
+ yymsp[-4].minor.yy489 = pLeft;
}
}
break;
- case 90: /* distinct ::= DISTINCT */
-{yymsp[0].minor.yy502 = SF_Distinct;}
+ case 91: /* distinct ::= DISTINCT */
+{yymsp[0].minor.yy70 = SF_Distinct;}
break;
- case 91: /* distinct ::= ALL */
-{yymsp[0].minor.yy502 = SF_All;}
+ case 92: /* distinct ::= ALL */
+{yymsp[0].minor.yy70 = SF_All;}
break;
- case 93: /* sclp ::= */
- case 126: /* orderby_opt ::= */ yytestcase(yyruleno==126);
- case 133: /* groupby_opt ::= */ yytestcase(yyruleno==133);
- case 212: /* exprlist ::= */ yytestcase(yyruleno==212);
- case 215: /* paren_exprlist ::= */ yytestcase(yyruleno==215);
- case 220: /* eidlist_opt ::= */ yytestcase(yyruleno==220);
-{yymsp[1].minor.yy232 = 0;}
+ case 94: /* sclp ::= */
+ case 127: /* orderby_opt ::= */ yytestcase(yyruleno==127);
+ case 134: /* groupby_opt ::= */ yytestcase(yyruleno==134);
+ case 214: /* exprlist ::= */ yytestcase(yyruleno==214);
+ case 217: /* paren_exprlist ::= */ yytestcase(yyruleno==217);
+ case 222: /* eidlist_opt ::= */ yytestcase(yyruleno==222);
+{yymsp[1].minor.yy420 = 0;}
break;
- case 94: /* selcollist ::= sclp scanpt expr scanpt as */
+ case 95: /* selcollist ::= sclp scanpt expr scanpt as */
{
- yymsp[-4].minor.yy232 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy232, yymsp[-2].minor.yy182);
- if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy232, &yymsp[0].minor.yy0, 1);
- sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy232,yymsp[-3].minor.yy36,yymsp[-1].minor.yy36);
+ yymsp[-4].minor.yy420 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy420, yymsp[-2].minor.yy18);
+ if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy420, &yymsp[0].minor.yy0, 1);
+ sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy420,yymsp[-3].minor.yy392,yymsp[-1].minor.yy392);
}
break;
- case 95: /* selcollist ::= sclp scanpt STAR */
+ case 96: /* selcollist ::= sclp scanpt STAR */
{
Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0);
- yymsp[-2].minor.yy232 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy232, p);
+ yymsp[-2].minor.yy420 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy420, p);
}
break;
- case 96: /* selcollist ::= sclp scanpt nm DOT STAR */
+ case 97: /* selcollist ::= sclp scanpt nm DOT STAR */
{
Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0);
Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight);
- yymsp[-4].minor.yy232 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy232, pDot);
+ yymsp[-4].minor.yy420 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy420, pDot);
}
break;
- case 97: /* as ::= AS nm */
- case 108: /* dbnm ::= DOT nm */ yytestcase(yyruleno==108);
- case 234: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==234);
- case 235: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==235);
+ case 98: /* as ::= AS nm */
+ case 109: /* dbnm ::= DOT nm */ yytestcase(yyruleno==109);
+ case 236: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==236);
+ case 237: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==237);
{yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;}
break;
- case 99: /* from ::= */
-{yymsp[1].minor.yy427 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy427));}
+ case 100: /* from ::= */
+{yymsp[1].minor.yy135 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy135));}
break;
- case 100: /* from ::= FROM seltablist */
+ case 101: /* from ::= FROM seltablist */
{
- yymsp[-1].minor.yy427 = yymsp[0].minor.yy427;
- sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy427);
+ yymsp[-1].minor.yy135 = yymsp[0].minor.yy135;
+ sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy135);
}
break;
- case 101: /* stl_prefix ::= seltablist joinop */
+ case 102: /* stl_prefix ::= seltablist joinop */
{
- if( ALWAYS(yymsp[-1].minor.yy427 && yymsp[-1].minor.yy427->nSrc>0) ) yymsp[-1].minor.yy427->a[yymsp[-1].minor.yy427->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy502;
+ if( ALWAYS(yymsp[-1].minor.yy135 && yymsp[-1].minor.yy135->nSrc>0) ) yymsp[-1].minor.yy135->a[yymsp[-1].minor.yy135->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy70;
}
break;
- case 102: /* stl_prefix ::= */
-{yymsp[1].minor.yy427 = 0;}
+ case 103: /* stl_prefix ::= */
+{yymsp[1].minor.yy135 = 0;}
break;
- case 103: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
+ case 104: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
{
- yymsp[-6].minor.yy427 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy427,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy182,yymsp[0].minor.yy510);
- sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy427, &yymsp[-2].minor.yy0);
+ yymsp[-6].minor.yy135 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy135,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy18,yymsp[0].minor.yy48);
+ sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy135, &yymsp[-2].minor.yy0);
}
break;
- case 104: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
+ case 105: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
{
- yymsp[-8].minor.yy427 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy427,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy182,yymsp[0].minor.yy510);
- sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy427, yymsp[-4].minor.yy232);
+ yymsp[-8].minor.yy135 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy135,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy18,yymsp[0].minor.yy48);
+ sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy135, yymsp[-4].minor.yy420);
}
break;
- case 105: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
+ case 106: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
{
- yymsp[-6].minor.yy427 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy427,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy399,yymsp[-1].minor.yy182,yymsp[0].minor.yy510);
+ yymsp[-6].minor.yy135 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy135,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy489,yymsp[-1].minor.yy18,yymsp[0].minor.yy48);
}
break;
- case 106: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
+ case 107: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
{
- if( yymsp[-6].minor.yy427==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy182==0 && yymsp[0].minor.yy510==0 ){
- yymsp[-6].minor.yy427 = yymsp[-4].minor.yy427;
- }else if( yymsp[-4].minor.yy427->nSrc==1 ){
- yymsp[-6].minor.yy427 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy427,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy182,yymsp[0].minor.yy510);
- if( yymsp[-6].minor.yy427 ){
- struct SrcList_item *pNew = &yymsp[-6].minor.yy427->a[yymsp[-6].minor.yy427->nSrc-1];
- struct SrcList_item *pOld = yymsp[-4].minor.yy427->a;
+ if( yymsp[-6].minor.yy135==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy18==0 && yymsp[0].minor.yy48==0 ){
+ yymsp[-6].minor.yy135 = yymsp[-4].minor.yy135;
+ }else if( yymsp[-4].minor.yy135->nSrc==1 ){
+ yymsp[-6].minor.yy135 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy135,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy18,yymsp[0].minor.yy48);
+ if( yymsp[-6].minor.yy135 ){
+ struct SrcList_item *pNew = &yymsp[-6].minor.yy135->a[yymsp[-6].minor.yy135->nSrc-1];
+ struct SrcList_item *pOld = yymsp[-4].minor.yy135->a;
pNew->zName = pOld->zName;
pNew->zDatabase = pOld->zDatabase;
pNew->pSelect = pOld->pSelect;
pOld->zName = pOld->zDatabase = 0;
pOld->pSelect = 0;
}
- sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy427);
+ sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy135);
}else{
Select *pSubquery;
- sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy427);
- pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy427,0,0,0,0,SF_NestedFrom,0);
- yymsp[-6].minor.yy427 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy427,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy182,yymsp[0].minor.yy510);
+ sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy135);
+ pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy135,0,0,0,0,SF_NestedFrom,0);
+ yymsp[-6].minor.yy135 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy135,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy18,yymsp[0].minor.yy48);
}
}
break;
- case 107: /* dbnm ::= */
- case 121: /* indexed_opt ::= */ yytestcase(yyruleno==121);
+ case 108: /* dbnm ::= */
+ case 122: /* indexed_opt ::= */ yytestcase(yyruleno==122);
{yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;}
break;
- case 109: /* fullname ::= nm */
- case 111: /* xfullname ::= nm */ yytestcase(yyruleno==111);
-{yymsp[0].minor.yy427 = sqlite3SrcListAppend(pParse->db,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/}
+ case 110: /* fullname ::= nm */
+{
+ yylhsminor.yy135 = sqlite3SrcListAppend(pParse->db,0,&yymsp[0].minor.yy0,0);
+ if( IN_RENAME_OBJECT && yylhsminor.yy135 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy135->a[0].zName, &yymsp[0].minor.yy0);
+}
+ yymsp[0].minor.yy135 = yylhsminor.yy135;
+ break;
+ case 111: /* fullname ::= nm DOT nm */
+{
+ yylhsminor.yy135 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
+ if( IN_RENAME_OBJECT && yylhsminor.yy135 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy135->a[0].zName, &yymsp[0].minor.yy0);
+}
+ yymsp[-2].minor.yy135 = yylhsminor.yy135;
+ break;
+ case 112: /* xfullname ::= nm */
+{yymsp[0].minor.yy135 = sqlite3SrcListAppend(pParse->db,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/}
break;
- case 110: /* fullname ::= nm DOT nm */
- case 112: /* xfullname ::= nm DOT nm */ yytestcase(yyruleno==112);
-{yymsp[-2].minor.yy427 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/}
+ case 113: /* xfullname ::= nm DOT nm */
+{yymsp[-2].minor.yy135 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
- case 113: /* xfullname ::= nm DOT nm AS nm */
+ case 114: /* xfullname ::= nm DOT nm AS nm */
{
- yymsp[-4].minor.yy427 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/
- if( yymsp[-4].minor.yy427 ) yymsp[-4].minor.yy427->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
+ yymsp[-4].minor.yy135 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/
+ if( yymsp[-4].minor.yy135 ) yymsp[-4].minor.yy135->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
}
break;
- case 114: /* xfullname ::= nm AS nm */
+ case 115: /* xfullname ::= nm AS nm */
{
- yymsp[-2].minor.yy427 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/
- if( yymsp[-2].minor.yy427 ) yymsp[-2].minor.yy427->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
+ yymsp[-2].minor.yy135 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/
+ if( yymsp[-2].minor.yy135 ) yymsp[-2].minor.yy135->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
}
break;
- case 115: /* joinop ::= COMMA|JOIN */
-{ yymsp[0].minor.yy502 = JT_INNER; }
+ case 116: /* joinop ::= COMMA|JOIN */
+{ yymsp[0].minor.yy70 = JT_INNER; }
break;
- case 116: /* joinop ::= JOIN_KW JOIN */
-{yymsp[-1].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/}
+ case 117: /* joinop ::= JOIN_KW JOIN */
+{yymsp[-1].minor.yy70 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/}
break;
- case 117: /* joinop ::= JOIN_KW nm JOIN */
-{yymsp[-2].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/}
+ case 118: /* joinop ::= JOIN_KW nm JOIN */
+{yymsp[-2].minor.yy70 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/}
break;
- case 118: /* joinop ::= JOIN_KW nm nm JOIN */
-{yymsp[-3].minor.yy502 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/}
+ case 119: /* joinop ::= JOIN_KW nm nm JOIN */
+{yymsp[-3].minor.yy70 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/}
break;
- case 119: /* on_opt ::= ON expr */
- case 136: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==136);
- case 143: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==143);
- case 208: /* case_else ::= ELSE expr */ yytestcase(yyruleno==208);
-{yymsp[-1].minor.yy182 = yymsp[0].minor.yy182;}
+ case 120: /* on_opt ::= ON expr */
+ case 137: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==137);
+ case 144: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==144);
+ case 210: /* case_else ::= ELSE expr */ yytestcase(yyruleno==210);
+{yymsp[-1].minor.yy18 = yymsp[0].minor.yy18;}
break;
- case 120: /* on_opt ::= */
- case 135: /* having_opt ::= */ yytestcase(yyruleno==135);
- case 137: /* limit_opt ::= */ yytestcase(yyruleno==137);
- case 142: /* where_opt ::= */ yytestcase(yyruleno==142);
- case 209: /* case_else ::= */ yytestcase(yyruleno==209);
- case 211: /* case_operand ::= */ yytestcase(yyruleno==211);
-{yymsp[1].minor.yy182 = 0;}
+ case 121: /* on_opt ::= */
+ case 136: /* having_opt ::= */ yytestcase(yyruleno==136);
+ case 138: /* limit_opt ::= */ yytestcase(yyruleno==138);
+ case 143: /* where_opt ::= */ yytestcase(yyruleno==143);
+ case 211: /* case_else ::= */ yytestcase(yyruleno==211);
+ case 213: /* case_operand ::= */ yytestcase(yyruleno==213);
+{yymsp[1].minor.yy18 = 0;}
break;
- case 122: /* indexed_opt ::= INDEXED BY nm */
+ case 123: /* indexed_opt ::= INDEXED BY nm */
{yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;}
break;
- case 123: /* indexed_opt ::= NOT INDEXED */
+ case 124: /* indexed_opt ::= NOT INDEXED */
{yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;}
break;
- case 124: /* using_opt ::= USING LP idlist RP */
-{yymsp[-3].minor.yy510 = yymsp[-1].minor.yy510;}
+ case 125: /* using_opt ::= USING LP idlist RP */
+{yymsp[-3].minor.yy48 = yymsp[-1].minor.yy48;}
break;
- case 125: /* using_opt ::= */
- case 157: /* idlist_opt ::= */ yytestcase(yyruleno==157);
-{yymsp[1].minor.yy510 = 0;}
+ case 126: /* using_opt ::= */
+ case 158: /* idlist_opt ::= */ yytestcase(yyruleno==158);
+{yymsp[1].minor.yy48 = 0;}
break;
- case 127: /* orderby_opt ::= ORDER BY sortlist */
- case 134: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==134);
-{yymsp[-2].minor.yy232 = yymsp[0].minor.yy232;}
+ case 128: /* orderby_opt ::= ORDER BY sortlist */
+ case 135: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==135);
+{yymsp[-2].minor.yy420 = yymsp[0].minor.yy420;}
break;
- case 128: /* sortlist ::= sortlist COMMA expr sortorder */
+ case 129: /* sortlist ::= sortlist COMMA expr sortorder */
{
- yymsp[-3].minor.yy232 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy232,yymsp[-1].minor.yy182);
- sqlite3ExprListSetSortOrder(yymsp[-3].minor.yy232,yymsp[0].minor.yy502);
+ yymsp[-3].minor.yy420 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy420,yymsp[-1].minor.yy18);
+ sqlite3ExprListSetSortOrder(yymsp[-3].minor.yy420,yymsp[0].minor.yy70);
}
break;
- case 129: /* sortlist ::= expr sortorder */
+ case 130: /* sortlist ::= expr sortorder */
{
- yymsp[-1].minor.yy232 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy182); /*A-overwrites-Y*/
- sqlite3ExprListSetSortOrder(yymsp[-1].minor.yy232,yymsp[0].minor.yy502);
+ yymsp[-1].minor.yy420 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy18); /*A-overwrites-Y*/
+ sqlite3ExprListSetSortOrder(yymsp[-1].minor.yy420,yymsp[0].minor.yy70);
}
break;
- case 130: /* sortorder ::= ASC */
-{yymsp[0].minor.yy502 = SQLITE_SO_ASC;}
+ case 131: /* sortorder ::= ASC */
+{yymsp[0].minor.yy70 = SQLITE_SO_ASC;}
break;
- case 131: /* sortorder ::= DESC */
-{yymsp[0].minor.yy502 = SQLITE_SO_DESC;}
+ case 132: /* sortorder ::= DESC */
+{yymsp[0].minor.yy70 = SQLITE_SO_DESC;}
break;
- case 132: /* sortorder ::= */
-{yymsp[1].minor.yy502 = SQLITE_SO_UNDEFINED;}
+ case 133: /* sortorder ::= */
+{yymsp[1].minor.yy70 = SQLITE_SO_UNDEFINED;}
break;
- case 138: /* limit_opt ::= LIMIT expr */
-{yymsp[-1].minor.yy182 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy182,0);}
+ case 139: /* limit_opt ::= LIMIT expr */
+{yymsp[-1].minor.yy18 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy18,0);}
break;
- case 139: /* limit_opt ::= LIMIT expr OFFSET expr */
-{yymsp[-3].minor.yy182 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy182,yymsp[0].minor.yy182);}
+ case 140: /* limit_opt ::= LIMIT expr OFFSET expr */
+{yymsp[-3].minor.yy18 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy18,yymsp[0].minor.yy18);}
break;
- case 140: /* limit_opt ::= LIMIT expr COMMA expr */
-{yymsp[-3].minor.yy182 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy182,yymsp[-2].minor.yy182);}
+ case 141: /* limit_opt ::= LIMIT expr COMMA expr */
+{yymsp[-3].minor.yy18 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy18,yymsp[-2].minor.yy18);}
break;
- case 141: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt */
+ case 142: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt */
{
- sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy427, &yymsp[-1].minor.yy0);
- sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy427,yymsp[0].minor.yy182,0,0);
+ sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy135, &yymsp[-1].minor.yy0);
+ sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy135,yymsp[0].minor.yy18,0,0);
}
break;
- case 144: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */
+ case 145: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */
{
- sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy427, &yymsp[-3].minor.yy0);
- sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy232,"set list");
- sqlite3Update(pParse,yymsp[-4].minor.yy427,yymsp[-1].minor.yy232,yymsp[0].minor.yy182,yymsp[-5].minor.yy502,0,0,0);
+ sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy135, &yymsp[-3].minor.yy0);
+ sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy420,"set list");
+ sqlite3Update(pParse,yymsp[-4].minor.yy135,yymsp[-1].minor.yy420,yymsp[0].minor.yy18,yymsp[-5].minor.yy70,0,0,0);
}
break;
- case 145: /* setlist ::= setlist COMMA nm EQ expr */
+ case 146: /* setlist ::= setlist COMMA nm EQ expr */
{
- yymsp[-4].minor.yy232 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy232, yymsp[0].minor.yy182);
- sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy232, &yymsp[-2].minor.yy0, 1);
+ yymsp[-4].minor.yy420 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy420, yymsp[0].minor.yy18);
+ sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy420, &yymsp[-2].minor.yy0, 1);
}
break;
- case 146: /* setlist ::= setlist COMMA LP idlist RP EQ expr */
+ case 147: /* setlist ::= setlist COMMA LP idlist RP EQ expr */
{
- yymsp[-6].minor.yy232 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy232, yymsp[-3].minor.yy510, yymsp[0].minor.yy182);
+ yymsp[-6].minor.yy420 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy420, yymsp[-3].minor.yy48, yymsp[0].minor.yy18);
}
break;
- case 147: /* setlist ::= nm EQ expr */
+ case 148: /* setlist ::= nm EQ expr */
{
- yylhsminor.yy232 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy182);
- sqlite3ExprListSetName(pParse, yylhsminor.yy232, &yymsp[-2].minor.yy0, 1);
+ yylhsminor.yy420 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy18);
+ sqlite3ExprListSetName(pParse, yylhsminor.yy420, &yymsp[-2].minor.yy0, 1);
}
- yymsp[-2].minor.yy232 = yylhsminor.yy232;
+ yymsp[-2].minor.yy420 = yylhsminor.yy420;
break;
- case 148: /* setlist ::= LP idlist RP EQ expr */
+ case 149: /* setlist ::= LP idlist RP EQ expr */
{
- yymsp[-4].minor.yy232 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy510, yymsp[0].minor.yy182);
+ yymsp[-4].minor.yy420 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy48, yymsp[0].minor.yy18);
}
break;
- case 149: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
+ case 150: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
{
- sqlite3Insert(pParse, yymsp[-3].minor.yy427, yymsp[-1].minor.yy399, yymsp[-2].minor.yy510, yymsp[-5].minor.yy502, yymsp[0].minor.yy198);
+ sqlite3Insert(pParse, yymsp[-3].minor.yy135, yymsp[-1].minor.yy489, yymsp[-2].minor.yy48, yymsp[-5].minor.yy70, yymsp[0].minor.yy340);
}
break;
- case 150: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
+ case 151: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
{
- sqlite3Insert(pParse, yymsp[-3].minor.yy427, 0, yymsp[-2].minor.yy510, yymsp[-5].minor.yy502, 0);
+ sqlite3Insert(pParse, yymsp[-3].minor.yy135, 0, yymsp[-2].minor.yy48, yymsp[-5].minor.yy70, 0);
}
break;
- case 151: /* upsert ::= */
-{ yymsp[1].minor.yy198 = 0; }
+ case 152: /* upsert ::= */
+{ yymsp[1].minor.yy340 = 0; }
break;
- case 152: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
-{ yymsp[-10].minor.yy198 = sqlite3UpsertNew(pParse->db,yymsp[-7].minor.yy232,yymsp[-5].minor.yy182,yymsp[-1].minor.yy232,yymsp[0].minor.yy182);}
+ case 153: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
+{ yymsp[-10].minor.yy340 = sqlite3UpsertNew(pParse->db,yymsp[-7].minor.yy420,yymsp[-5].minor.yy18,yymsp[-1].minor.yy420,yymsp[0].minor.yy18);}
break;
- case 153: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
-{ yymsp[-7].minor.yy198 = sqlite3UpsertNew(pParse->db,yymsp[-4].minor.yy232,yymsp[-2].minor.yy182,0,0); }
+ case 154: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
+{ yymsp[-7].minor.yy340 = sqlite3UpsertNew(pParse->db,yymsp[-4].minor.yy420,yymsp[-2].minor.yy18,0,0); }
break;
- case 154: /* upsert ::= ON CONFLICT DO NOTHING */
-{ yymsp[-3].minor.yy198 = sqlite3UpsertNew(pParse->db,0,0,0,0); }
+ case 155: /* upsert ::= ON CONFLICT DO NOTHING */
+{ yymsp[-3].minor.yy340 = sqlite3UpsertNew(pParse->db,0,0,0,0); }
break;
- case 158: /* idlist_opt ::= LP idlist RP */
-{yymsp[-2].minor.yy510 = yymsp[-1].minor.yy510;}
+ case 159: /* idlist_opt ::= LP idlist RP */
+{yymsp[-2].minor.yy48 = yymsp[-1].minor.yy48;}
break;
- case 159: /* idlist ::= idlist COMMA nm */
-{yymsp[-2].minor.yy510 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy510,&yymsp[0].minor.yy0);}
+ case 160: /* idlist ::= idlist COMMA nm */
+{yymsp[-2].minor.yy48 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy48,&yymsp[0].minor.yy0);}
break;
- case 160: /* idlist ::= nm */
-{yymsp[0].minor.yy510 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/}
+ case 161: /* idlist ::= nm */
+{yymsp[0].minor.yy48 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/}
break;
- case 161: /* expr ::= LP expr RP */
-{yymsp[-2].minor.yy182 = yymsp[-1].minor.yy182;}
+ case 162: /* expr ::= LP expr RP */
+{yymsp[-2].minor.yy18 = yymsp[-1].minor.yy18;}
break;
- case 162: /* expr ::= ID|INDEXED */
- case 163: /* expr ::= JOIN_KW */ yytestcase(yyruleno==163);
-{yymsp[0].minor.yy182=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/}
+ case 163: /* expr ::= ID|INDEXED */
+ case 164: /* expr ::= JOIN_KW */ yytestcase(yyruleno==164);
+{yymsp[0].minor.yy18=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
- case 164: /* expr ::= nm DOT nm */
+ case 165: /* expr ::= nm DOT nm */
{
Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1);
- yylhsminor.yy182 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
+ if( IN_RENAME_OBJECT ){
+ sqlite3RenameTokenMap(pParse, (void*)temp2, &yymsp[0].minor.yy0);
+ sqlite3RenameTokenMap(pParse, (void*)temp1, &yymsp[-2].minor.yy0);
+ }
+ yylhsminor.yy18 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
}
- yymsp[-2].minor.yy182 = yylhsminor.yy182;
+ yymsp[-2].minor.yy18 = yylhsminor.yy18;
break;
- case 165: /* expr ::= nm DOT nm DOT nm */
+ case 166: /* expr ::= nm DOT nm DOT nm */
{
Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-4].minor.yy0, 1);
Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
Expr *temp3 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1);
Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3);
- yylhsminor.yy182 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4);
+ if( IN_RENAME_OBJECT ){
+ sqlite3RenameTokenMap(pParse, (void*)temp3, &yymsp[0].minor.yy0);
+ sqlite3RenameTokenMap(pParse, (void*)temp2, &yymsp[-2].minor.yy0);
+ }
+ yylhsminor.yy18 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4);
}
- yymsp[-4].minor.yy182 = yylhsminor.yy182;
+ yymsp[-4].minor.yy18 = yylhsminor.yy18;
break;
- case 166: /* term ::= NULL|FLOAT|BLOB */
- case 167: /* term ::= STRING */ yytestcase(yyruleno==167);
-{yymsp[0].minor.yy182=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/}
+ case 167: /* term ::= NULL|FLOAT|BLOB */
+ case 168: /* term ::= STRING */ yytestcase(yyruleno==168);
+{yymsp[0].minor.yy18=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
- case 168: /* term ::= INTEGER */
+ case 169: /* term ::= INTEGER */
{
- yylhsminor.yy182 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1);
+ yylhsminor.yy18 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1);
}
- yymsp[0].minor.yy182 = yylhsminor.yy182;
+ yymsp[0].minor.yy18 = yylhsminor.yy18;
break;
- case 169: /* expr ::= VARIABLE */
+ case 170: /* expr ::= VARIABLE */
{
if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){
u32 n = yymsp[0].minor.yy0.n;
- yymsp[0].minor.yy182 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0);
- sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy182, n);
+ yymsp[0].minor.yy18 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0);
+ sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy18, n);
}else{
/* When doing a nested parse, one can include terms in an expression
** that look like this: #1 #2 ... These terms refer to registers
@@ -144622,146 +149341,154 @@ static YYACTIONTYPE yy_reduce(
assert( t.n>=2 );
if( pParse->nested==0 ){
sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t);
- yymsp[0].minor.yy182 = 0;
+ yymsp[0].minor.yy18 = 0;
}else{
- yymsp[0].minor.yy182 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0);
- if( yymsp[0].minor.yy182 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy182->iTable);
+ yymsp[0].minor.yy18 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0);
+ if( yymsp[0].minor.yy18 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy18->iTable);
}
}
}
break;
- case 170: /* expr ::= expr COLLATE ID|STRING */
+ case 171: /* expr ::= expr COLLATE ID|STRING */
{
- yymsp[-2].minor.yy182 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy182, &yymsp[0].minor.yy0, 1);
+ yymsp[-2].minor.yy18 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy18, &yymsp[0].minor.yy0, 1);
}
break;
- case 171: /* expr ::= CAST LP expr AS typetoken RP */
+ case 172: /* expr ::= CAST LP expr AS typetoken RP */
{
- yymsp[-5].minor.yy182 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1);
- sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy182, yymsp[-3].minor.yy182, 0);
+ yymsp[-5].minor.yy18 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1);
+ sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy18, yymsp[-3].minor.yy18, 0);
}
break;
- case 172: /* expr ::= ID|INDEXED LP distinct exprlist RP */
+ case 173: /* expr ::= ID|INDEXED LP distinct exprlist RP */
{
- if( yymsp[-1].minor.yy232 && yymsp[-1].minor.yy232->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
- sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
- }
- yylhsminor.yy182 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy232, &yymsp[-4].minor.yy0);
- if( yymsp[-2].minor.yy502==SF_Distinct && yylhsminor.yy182 ){
- yylhsminor.yy182->flags |= EP_Distinct;
- }
+ yylhsminor.yy18 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy420, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy70);
+}
+ yymsp[-4].minor.yy18 = yylhsminor.yy18;
+ break;
+ case 174: /* expr ::= ID|INDEXED LP STAR RP */
+{
+ yylhsminor.yy18 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0);
+}
+ yymsp[-3].minor.yy18 = yylhsminor.yy18;
+ break;
+ case 175: /* expr ::= ID|INDEXED LP distinct exprlist RP over_clause */
+{
+ yylhsminor.yy18 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy420, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy70);
+ sqlite3WindowAttach(pParse, yylhsminor.yy18, yymsp[0].minor.yy327);
}
- yymsp[-4].minor.yy182 = yylhsminor.yy182;
+ yymsp[-5].minor.yy18 = yylhsminor.yy18;
break;
- case 173: /* expr ::= ID|INDEXED LP STAR RP */
+ case 176: /* expr ::= ID|INDEXED LP STAR RP over_clause */
{
- yylhsminor.yy182 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
+ yylhsminor.yy18 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0);
+ sqlite3WindowAttach(pParse, yylhsminor.yy18, yymsp[0].minor.yy327);
}
- yymsp[-3].minor.yy182 = yylhsminor.yy182;
+ yymsp[-4].minor.yy18 = yylhsminor.yy18;
break;
- case 174: /* term ::= CTIME_KW */
+ case 177: /* term ::= CTIME_KW */
{
- yylhsminor.yy182 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0);
+ yylhsminor.yy18 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0);
}
- yymsp[0].minor.yy182 = yylhsminor.yy182;
+ yymsp[0].minor.yy18 = yylhsminor.yy18;
break;
- case 175: /* expr ::= LP nexprlist COMMA expr RP */
+ case 178: /* expr ::= LP nexprlist COMMA expr RP */
{
- ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy232, yymsp[-1].minor.yy182);
- yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
- if( yymsp[-4].minor.yy182 ){
- yymsp[-4].minor.yy182->x.pList = pList;
+ ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy420, yymsp[-1].minor.yy18);
+ yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
+ if( yymsp[-4].minor.yy18 ){
+ yymsp[-4].minor.yy18->x.pList = pList;
}else{
sqlite3ExprListDelete(pParse->db, pList);
}
}
break;
- case 176: /* expr ::= expr AND expr */
- case 177: /* expr ::= expr OR expr */ yytestcase(yyruleno==177);
- case 178: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==178);
- case 179: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==179);
- case 180: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==180);
- case 181: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==181);
- case 182: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==182);
- case 183: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==183);
-{yymsp[-2].minor.yy182=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy182,yymsp[0].minor.yy182);}
+ case 179: /* expr ::= expr AND expr */
+ case 180: /* expr ::= expr OR expr */ yytestcase(yyruleno==180);
+ case 181: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==181);
+ case 182: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==182);
+ case 183: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==183);
+ case 184: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==184);
+ case 185: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==185);
+ case 186: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==186);
+{yymsp[-2].minor.yy18=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy18,yymsp[0].minor.yy18);}
break;
- case 184: /* likeop ::= NOT LIKE_KW|MATCH */
+ case 187: /* likeop ::= NOT LIKE_KW|MATCH */
{yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/}
break;
- case 185: /* expr ::= expr likeop expr */
+ case 188: /* expr ::= expr likeop expr */
{
ExprList *pList;
int bNot = yymsp[-1].minor.yy0.n & 0x80000000;
yymsp[-1].minor.yy0.n &= 0x7fffffff;
- pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy182);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy182);
- yymsp[-2].minor.yy182 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0);
- if( bNot ) yymsp[-2].minor.yy182 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy182, 0);
- if( yymsp[-2].minor.yy182 ) yymsp[-2].minor.yy182->flags |= EP_InfixFunc;
+ pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy18);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy18);
+ yymsp[-2].minor.yy18 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0);
+ if( bNot ) yymsp[-2].minor.yy18 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy18, 0);
+ if( yymsp[-2].minor.yy18 ) yymsp[-2].minor.yy18->flags |= EP_InfixFunc;
}
break;
- case 186: /* expr ::= expr likeop expr ESCAPE expr */
+ case 189: /* expr ::= expr likeop expr ESCAPE expr */
{
ExprList *pList;
int bNot = yymsp[-3].minor.yy0.n & 0x80000000;
yymsp[-3].minor.yy0.n &= 0x7fffffff;
- pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy182);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy182);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy182);
- yymsp[-4].minor.yy182 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0);
- if( bNot ) yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy182, 0);
- if( yymsp[-4].minor.yy182 ) yymsp[-4].minor.yy182->flags |= EP_InfixFunc;
+ pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy18);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy18);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy18);
+ yymsp[-4].minor.yy18 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0);
+ if( bNot ) yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy18, 0);
+ if( yymsp[-4].minor.yy18 ) yymsp[-4].minor.yy18->flags |= EP_InfixFunc;
}
break;
- case 187: /* expr ::= expr ISNULL|NOTNULL */
-{yymsp[-1].minor.yy182 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy182,0);}
+ case 190: /* expr ::= expr ISNULL|NOTNULL */
+{yymsp[-1].minor.yy18 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy18,0);}
break;
- case 188: /* expr ::= expr NOT NULL */
-{yymsp[-2].minor.yy182 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy182,0);}
+ case 191: /* expr ::= expr NOT NULL */
+{yymsp[-2].minor.yy18 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy18,0);}
break;
- case 189: /* expr ::= expr IS expr */
+ case 192: /* expr ::= expr IS expr */
{
- yymsp[-2].minor.yy182 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy182,yymsp[0].minor.yy182);
- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy182, yymsp[-2].minor.yy182, TK_ISNULL);
+ yymsp[-2].minor.yy18 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy18,yymsp[0].minor.yy18);
+ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy18, yymsp[-2].minor.yy18, TK_ISNULL);
}
break;
- case 190: /* expr ::= expr IS NOT expr */
+ case 193: /* expr ::= expr IS NOT expr */
{
- yymsp[-3].minor.yy182 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy182,yymsp[0].minor.yy182);
- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy182, yymsp[-3].minor.yy182, TK_NOTNULL);
+ yymsp[-3].minor.yy18 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy18,yymsp[0].minor.yy18);
+ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy18, yymsp[-3].minor.yy18, TK_NOTNULL);
}
break;
- case 191: /* expr ::= NOT expr */
- case 192: /* expr ::= BITNOT expr */ yytestcase(yyruleno==192);
-{yymsp[-1].minor.yy182 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy182, 0);/*A-overwrites-B*/}
- break;
- case 193: /* expr ::= MINUS expr */
-{yymsp[-1].minor.yy182 = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy182, 0);}
+ case 194: /* expr ::= NOT expr */
+ case 195: /* expr ::= BITNOT expr */ yytestcase(yyruleno==195);
+{yymsp[-1].minor.yy18 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy18, 0);/*A-overwrites-B*/}
break;
- case 194: /* expr ::= PLUS expr */
-{yymsp[-1].minor.yy182 = sqlite3PExpr(pParse, TK_UPLUS, yymsp[0].minor.yy182, 0);}
+ case 196: /* expr ::= PLUS|MINUS expr */
+{
+ yymsp[-1].minor.yy18 = sqlite3PExpr(pParse, yymsp[-1].major==TK_PLUS ? TK_UPLUS : TK_UMINUS, yymsp[0].minor.yy18, 0);
+ /*A-overwrites-B*/
+}
break;
- case 195: /* between_op ::= BETWEEN */
- case 198: /* in_op ::= IN */ yytestcase(yyruleno==198);
-{yymsp[0].minor.yy502 = 0;}
+ case 197: /* between_op ::= BETWEEN */
+ case 200: /* in_op ::= IN */ yytestcase(yyruleno==200);
+{yymsp[0].minor.yy70 = 0;}
break;
- case 197: /* expr ::= expr between_op expr AND expr */
+ case 199: /* expr ::= expr between_op expr AND expr */
{
- ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy182);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy182);
- yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy182, 0);
- if( yymsp[-4].minor.yy182 ){
- yymsp[-4].minor.yy182->x.pList = pList;
+ ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy18);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy18);
+ yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy18, 0);
+ if( yymsp[-4].minor.yy18 ){
+ yymsp[-4].minor.yy18->x.pList = pList;
}else{
sqlite3ExprListDelete(pParse->db, pList);
}
- if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy182, 0);
+ if( yymsp[-3].minor.yy70 ) yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy18, 0);
}
break;
- case 200: /* expr ::= expr in_op LP exprlist RP */
+ case 202: /* expr ::= expr in_op LP exprlist RP */
{
- if( yymsp[-1].minor.yy232==0 ){
+ if( yymsp[-1].minor.yy420==0 ){
/* Expressions of the form
**
** expr1 IN ()
@@ -144770,9 +149497,9 @@ static YYACTIONTYPE yy_reduce(
** simplify to constants 0 (false) and 1 (true), respectively,
** regardless of the value of expr1.
*/
- sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy182);
- yymsp[-4].minor.yy182 = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[yymsp[-3].minor.yy502],1);
- }else if( yymsp[-1].minor.yy232->nExpr==1 ){
+ sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy18);
+ yymsp[-4].minor.yy18 = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[yymsp[-3].minor.yy70],1);
+ }else if( yymsp[-1].minor.yy420->nExpr==1 ){
/* Expressions of the form:
**
** expr1 IN (?1)
@@ -144789,195 +149516,199 @@ static YYACTIONTYPE yy_reduce(
** affinity or the collating sequence to use for comparison. Otherwise,
** the semantics would be subtly different from IN or NOT IN.
*/
- Expr *pRHS = yymsp[-1].minor.yy232->a[0].pExpr;
- yymsp[-1].minor.yy232->a[0].pExpr = 0;
- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy232);
+ Expr *pRHS = yymsp[-1].minor.yy420->a[0].pExpr;
+ yymsp[-1].minor.yy420->a[0].pExpr = 0;
+ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy420);
/* pRHS cannot be NULL because a malloc error would have been detected
** before now and control would have never reached this point */
if( ALWAYS(pRHS) ){
pRHS->flags &= ~EP_Collate;
pRHS->flags |= EP_Generic;
}
- yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, yymsp[-3].minor.yy502 ? TK_NE : TK_EQ, yymsp[-4].minor.yy182, pRHS);
+ yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, yymsp[-3].minor.yy70 ? TK_NE : TK_EQ, yymsp[-4].minor.yy18, pRHS);
}else{
- yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy182, 0);
- if( yymsp[-4].minor.yy182 ){
- yymsp[-4].minor.yy182->x.pList = yymsp[-1].minor.yy232;
- sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy182);
+ yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy18, 0);
+ if( yymsp[-4].minor.yy18 ){
+ yymsp[-4].minor.yy18->x.pList = yymsp[-1].minor.yy420;
+ sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy18);
}else{
- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy232);
+ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy420);
}
- if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy182, 0);
+ if( yymsp[-3].minor.yy70 ) yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy18, 0);
}
}
break;
- case 201: /* expr ::= LP select RP */
+ case 203: /* expr ::= LP select RP */
{
- yymsp[-2].minor.yy182 = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
- sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy182, yymsp[-1].minor.yy399);
+ yymsp[-2].minor.yy18 = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
+ sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy18, yymsp[-1].minor.yy489);
}
break;
- case 202: /* expr ::= expr in_op LP select RP */
+ case 204: /* expr ::= expr in_op LP select RP */
{
- yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy182, 0);
- sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy182, yymsp[-1].minor.yy399);
- if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy182, 0);
+ yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy18, 0);
+ sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy18, yymsp[-1].minor.yy489);
+ if( yymsp[-3].minor.yy70 ) yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy18, 0);
}
break;
- case 203: /* expr ::= expr in_op nm dbnm paren_exprlist */
+ case 205: /* expr ::= expr in_op nm dbnm paren_exprlist */
{
SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);
Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0);
- if( yymsp[0].minor.yy232 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy232);
- yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy182, 0);
- sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy182, pSelect);
- if( yymsp[-3].minor.yy502 ) yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy182, 0);
+ if( yymsp[0].minor.yy420 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy420);
+ yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy18, 0);
+ sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy18, pSelect);
+ if( yymsp[-3].minor.yy70 ) yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy18, 0);
}
break;
- case 204: /* expr ::= EXISTS LP select RP */
+ case 206: /* expr ::= EXISTS LP select RP */
{
Expr *p;
- p = yymsp[-3].minor.yy182 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0);
- sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy399);
+ p = yymsp[-3].minor.yy18 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0);
+ sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy489);
}
break;
- case 205: /* expr ::= CASE case_operand case_exprlist case_else END */
+ case 207: /* expr ::= CASE case_operand case_exprlist case_else END */
{
- yymsp[-4].minor.yy182 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy182, 0);
- if( yymsp[-4].minor.yy182 ){
- yymsp[-4].minor.yy182->x.pList = yymsp[-1].minor.yy182 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy232,yymsp[-1].minor.yy182) : yymsp[-2].minor.yy232;
- sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy182);
+ yymsp[-4].minor.yy18 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy18, 0);
+ if( yymsp[-4].minor.yy18 ){
+ yymsp[-4].minor.yy18->x.pList = yymsp[-1].minor.yy18 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy420,yymsp[-1].minor.yy18) : yymsp[-2].minor.yy420;
+ sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy18);
}else{
- sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy232);
- sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy182);
+ sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy420);
+ sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy18);
}
}
break;
- case 206: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
+ case 208: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
{
- yymsp[-4].minor.yy232 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy232, yymsp[-2].minor.yy182);
- yymsp[-4].minor.yy232 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy232, yymsp[0].minor.yy182);
+ yymsp[-4].minor.yy420 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy420, yymsp[-2].minor.yy18);
+ yymsp[-4].minor.yy420 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy420, yymsp[0].minor.yy18);
}
break;
- case 207: /* case_exprlist ::= WHEN expr THEN expr */
+ case 209: /* case_exprlist ::= WHEN expr THEN expr */
{
- yymsp[-3].minor.yy232 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy182);
- yymsp[-3].minor.yy232 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy232, yymsp[0].minor.yy182);
+ yymsp[-3].minor.yy420 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy18);
+ yymsp[-3].minor.yy420 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy420, yymsp[0].minor.yy18);
}
break;
- case 210: /* case_operand ::= expr */
-{yymsp[0].minor.yy182 = yymsp[0].minor.yy182; /*A-overwrites-X*/}
+ case 212: /* case_operand ::= expr */
+{yymsp[0].minor.yy18 = yymsp[0].minor.yy18; /*A-overwrites-X*/}
break;
- case 213: /* nexprlist ::= nexprlist COMMA expr */
-{yymsp[-2].minor.yy232 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy232,yymsp[0].minor.yy182);}
+ case 215: /* nexprlist ::= nexprlist COMMA expr */
+{yymsp[-2].minor.yy420 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy420,yymsp[0].minor.yy18);}
break;
- case 214: /* nexprlist ::= expr */
-{yymsp[0].minor.yy232 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy182); /*A-overwrites-Y*/}
+ case 216: /* nexprlist ::= expr */
+{yymsp[0].minor.yy420 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy18); /*A-overwrites-Y*/}
break;
- case 216: /* paren_exprlist ::= LP exprlist RP */
- case 221: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==221);
-{yymsp[-2].minor.yy232 = yymsp[-1].minor.yy232;}
+ case 218: /* paren_exprlist ::= LP exprlist RP */
+ case 223: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==223);
+{yymsp[-2].minor.yy420 = yymsp[-1].minor.yy420;}
break;
- case 217: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
+ case 219: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
{
sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0,
- sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy232, yymsp[-10].minor.yy502,
- &yymsp[-11].minor.yy0, yymsp[0].minor.yy182, SQLITE_SO_ASC, yymsp[-8].minor.yy502, SQLITE_IDXTYPE_APPDEF);
+ sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy420, yymsp[-10].minor.yy70,
+ &yymsp[-11].minor.yy0, yymsp[0].minor.yy18, SQLITE_SO_ASC, yymsp[-8].minor.yy70, SQLITE_IDXTYPE_APPDEF);
+ if( IN_RENAME_OBJECT && pParse->pNewIndex ){
+ sqlite3RenameTokenMap(pParse, pParse->pNewIndex->zName, &yymsp[-4].minor.yy0);
+ }
}
break;
- case 218: /* uniqueflag ::= UNIQUE */
- case 258: /* raisetype ::= ABORT */ yytestcase(yyruleno==258);
-{yymsp[0].minor.yy502 = OE_Abort;}
+ case 220: /* uniqueflag ::= UNIQUE */
+ case 260: /* raisetype ::= ABORT */ yytestcase(yyruleno==260);
+{yymsp[0].minor.yy70 = OE_Abort;}
break;
- case 219: /* uniqueflag ::= */
-{yymsp[1].minor.yy502 = OE_None;}
+ case 221: /* uniqueflag ::= */
+{yymsp[1].minor.yy70 = OE_None;}
break;
- case 222: /* eidlist ::= eidlist COMMA nm collate sortorder */
+ case 224: /* eidlist ::= eidlist COMMA nm collate sortorder */
{
- yymsp[-4].minor.yy232 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy232, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy502, yymsp[0].minor.yy502);
+ yymsp[-4].minor.yy420 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy420, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy70, yymsp[0].minor.yy70);
}
break;
- case 223: /* eidlist ::= nm collate sortorder */
+ case 225: /* eidlist ::= nm collate sortorder */
{
- yymsp[-2].minor.yy232 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy502, yymsp[0].minor.yy502); /*A-overwrites-Y*/
+ yymsp[-2].minor.yy420 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy70, yymsp[0].minor.yy70); /*A-overwrites-Y*/
}
break;
- case 226: /* cmd ::= DROP INDEX ifexists fullname */
-{sqlite3DropIndex(pParse, yymsp[0].minor.yy427, yymsp[-1].minor.yy502);}
+ case 228: /* cmd ::= DROP INDEX ifexists fullname */
+{sqlite3DropIndex(pParse, yymsp[0].minor.yy135, yymsp[-1].minor.yy70);}
break;
- case 227: /* cmd ::= VACUUM */
+ case 229: /* cmd ::= VACUUM */
{sqlite3Vacuum(pParse,0);}
break;
- case 228: /* cmd ::= VACUUM nm */
+ case 230: /* cmd ::= VACUUM nm */
{sqlite3Vacuum(pParse,&yymsp[0].minor.yy0);}
break;
- case 229: /* cmd ::= PRAGMA nm dbnm */
+ case 231: /* cmd ::= PRAGMA nm dbnm */
{sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
break;
- case 230: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
+ case 232: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);}
break;
- case 231: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
+ case 233: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);}
break;
- case 232: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
+ case 234: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);}
break;
- case 233: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
+ case 235: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);}
break;
- case 236: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
+ case 238: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
{
Token all;
all.z = yymsp[-3].minor.yy0.z;
all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n;
- sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy47, &all);
+ sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy207, &all);
}
break;
- case 237: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+ case 239: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
{
- sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy502, yymsp[-4].minor.yy300.a, yymsp[-4].minor.yy300.b, yymsp[-2].minor.yy427, yymsp[0].minor.yy182, yymsp[-10].minor.yy502, yymsp[-8].minor.yy502);
+ sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy70, yymsp[-4].minor.yy34.a, yymsp[-4].minor.yy34.b, yymsp[-2].minor.yy135, yymsp[0].minor.yy18, yymsp[-10].minor.yy70, yymsp[-8].minor.yy70);
yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/
}
break;
- case 238: /* trigger_time ::= BEFORE|AFTER */
-{ yymsp[0].minor.yy502 = yymsp[0].major; /*A-overwrites-X*/ }
+ case 240: /* trigger_time ::= BEFORE|AFTER */
+{ yymsp[0].minor.yy70 = yymsp[0].major; /*A-overwrites-X*/ }
break;
- case 239: /* trigger_time ::= INSTEAD OF */
-{ yymsp[-1].minor.yy502 = TK_INSTEAD;}
+ case 241: /* trigger_time ::= INSTEAD OF */
+{ yymsp[-1].minor.yy70 = TK_INSTEAD;}
break;
- case 240: /* trigger_time ::= */
-{ yymsp[1].minor.yy502 = TK_BEFORE; }
+ case 242: /* trigger_time ::= */
+{ yymsp[1].minor.yy70 = TK_BEFORE; }
break;
- case 241: /* trigger_event ::= DELETE|INSERT */
- case 242: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==242);
-{yymsp[0].minor.yy300.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy300.b = 0;}
+ case 243: /* trigger_event ::= DELETE|INSERT */
+ case 244: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==244);
+{yymsp[0].minor.yy34.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy34.b = 0;}
break;
- case 243: /* trigger_event ::= UPDATE OF idlist */
-{yymsp[-2].minor.yy300.a = TK_UPDATE; yymsp[-2].minor.yy300.b = yymsp[0].minor.yy510;}
+ case 245: /* trigger_event ::= UPDATE OF idlist */
+{yymsp[-2].minor.yy34.a = TK_UPDATE; yymsp[-2].minor.yy34.b = yymsp[0].minor.yy48;}
break;
- case 244: /* when_clause ::= */
- case 263: /* key_opt ::= */ yytestcase(yyruleno==263);
-{ yymsp[1].minor.yy182 = 0; }
+ case 246: /* when_clause ::= */
+ case 265: /* key_opt ::= */ yytestcase(yyruleno==265);
+ case 307: /* filter_opt ::= */ yytestcase(yyruleno==307);
+{ yymsp[1].minor.yy18 = 0; }
break;
- case 245: /* when_clause ::= WHEN expr */
- case 264: /* key_opt ::= KEY expr */ yytestcase(yyruleno==264);
-{ yymsp[-1].minor.yy182 = yymsp[0].minor.yy182; }
+ case 247: /* when_clause ::= WHEN expr */
+ case 266: /* key_opt ::= KEY expr */ yytestcase(yyruleno==266);
+{ yymsp[-1].minor.yy18 = yymsp[0].minor.yy18; }
break;
- case 246: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+ case 248: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
{
- assert( yymsp[-2].minor.yy47!=0 );
- yymsp[-2].minor.yy47->pLast->pNext = yymsp[-1].minor.yy47;
- yymsp[-2].minor.yy47->pLast = yymsp[-1].minor.yy47;
+ assert( yymsp[-2].minor.yy207!=0 );
+ yymsp[-2].minor.yy207->pLast->pNext = yymsp[-1].minor.yy207;
+ yymsp[-2].minor.yy207->pLast = yymsp[-1].minor.yy207;
}
break;
- case 247: /* trigger_cmd_list ::= trigger_cmd SEMI */
+ case 249: /* trigger_cmd_list ::= trigger_cmd SEMI */
{
- assert( yymsp[-1].minor.yy47!=0 );
- yymsp[-1].minor.yy47->pLast = yymsp[-1].minor.yy47;
+ assert( yymsp[-1].minor.yy207!=0 );
+ yymsp[-1].minor.yy207->pLast = yymsp[-1].minor.yy207;
}
break;
- case 248: /* trnm ::= nm DOT nm */
+ case 250: /* trnm ::= nm DOT nm */
{
yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;
sqlite3ErrorMsg(pParse,
@@ -144985,196 +149716,306 @@ static YYACTIONTYPE yy_reduce(
"statements within triggers");
}
break;
- case 249: /* tridxby ::= INDEXED BY nm */
+ case 251: /* tridxby ::= INDEXED BY nm */
{
sqlite3ErrorMsg(pParse,
"the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
"within triggers");
}
break;
- case 250: /* tridxby ::= NOT INDEXED */
+ case 252: /* tridxby ::= NOT INDEXED */
{
sqlite3ErrorMsg(pParse,
"the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
"within triggers");
}
break;
- case 251: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
-{yylhsminor.yy47 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-5].minor.yy0, yymsp[-2].minor.yy232, yymsp[-1].minor.yy182, yymsp[-6].minor.yy502, yymsp[-7].minor.yy0.z, yymsp[0].minor.yy36);}
- yymsp[-7].minor.yy47 = yylhsminor.yy47;
+ case 253: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
+{yylhsminor.yy207 = sqlite3TriggerUpdateStep(pParse, &yymsp[-5].minor.yy0, yymsp[-2].minor.yy420, yymsp[-1].minor.yy18, yymsp[-6].minor.yy70, yymsp[-7].minor.yy0.z, yymsp[0].minor.yy392);}
+ yymsp[-7].minor.yy207 = yylhsminor.yy207;
break;
- case 252: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
+ case 254: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
{
- yylhsminor.yy47 = sqlite3TriggerInsertStep(pParse->db,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy510,yymsp[-2].minor.yy399,yymsp[-6].minor.yy502,yymsp[-1].minor.yy198,yymsp[-7].minor.yy36,yymsp[0].minor.yy36);/*yylhsminor.yy47-overwrites-yymsp[-6].minor.yy502*/
+ yylhsminor.yy207 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy48,yymsp[-2].minor.yy489,yymsp[-6].minor.yy70,yymsp[-1].minor.yy340,yymsp[-7].minor.yy392,yymsp[0].minor.yy392);/*yylhsminor.yy207-overwrites-yymsp[-6].minor.yy70*/
}
- yymsp[-7].minor.yy47 = yylhsminor.yy47;
+ yymsp[-7].minor.yy207 = yylhsminor.yy207;
break;
- case 253: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
-{yylhsminor.yy47 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy182, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy36);}
- yymsp[-5].minor.yy47 = yylhsminor.yy47;
+ case 255: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
+{yylhsminor.yy207 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy18, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy392);}
+ yymsp[-5].minor.yy207 = yylhsminor.yy207;
break;
- case 254: /* trigger_cmd ::= scanpt select scanpt */
-{yylhsminor.yy47 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy399, yymsp[-2].minor.yy36, yymsp[0].minor.yy36); /*yylhsminor.yy47-overwrites-yymsp[-1].minor.yy399*/}
- yymsp[-2].minor.yy47 = yylhsminor.yy47;
+ case 256: /* trigger_cmd ::= scanpt select scanpt */
+{yylhsminor.yy207 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy489, yymsp[-2].minor.yy392, yymsp[0].minor.yy392); /*yylhsminor.yy207-overwrites-yymsp[-1].minor.yy489*/}
+ yymsp[-2].minor.yy207 = yylhsminor.yy207;
break;
- case 255: /* expr ::= RAISE LP IGNORE RP */
+ case 257: /* expr ::= RAISE LP IGNORE RP */
{
- yymsp[-3].minor.yy182 = sqlite3PExpr(pParse, TK_RAISE, 0, 0);
- if( yymsp[-3].minor.yy182 ){
- yymsp[-3].minor.yy182->affinity = OE_Ignore;
+ yymsp[-3].minor.yy18 = sqlite3PExpr(pParse, TK_RAISE, 0, 0);
+ if( yymsp[-3].minor.yy18 ){
+ yymsp[-3].minor.yy18->affinity = OE_Ignore;
}
}
break;
- case 256: /* expr ::= RAISE LP raisetype COMMA nm RP */
+ case 258: /* expr ::= RAISE LP raisetype COMMA nm RP */
{
- yymsp[-5].minor.yy182 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1);
- if( yymsp[-5].minor.yy182 ) {
- yymsp[-5].minor.yy182->affinity = (char)yymsp[-3].minor.yy502;
+ yymsp[-5].minor.yy18 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1);
+ if( yymsp[-5].minor.yy18 ) {
+ yymsp[-5].minor.yy18->affinity = (char)yymsp[-3].minor.yy70;
}
}
break;
- case 257: /* raisetype ::= ROLLBACK */
-{yymsp[0].minor.yy502 = OE_Rollback;}
+ case 259: /* raisetype ::= ROLLBACK */
+{yymsp[0].minor.yy70 = OE_Rollback;}
break;
- case 259: /* raisetype ::= FAIL */
-{yymsp[0].minor.yy502 = OE_Fail;}
+ case 261: /* raisetype ::= FAIL */
+{yymsp[0].minor.yy70 = OE_Fail;}
break;
- case 260: /* cmd ::= DROP TRIGGER ifexists fullname */
+ case 262: /* cmd ::= DROP TRIGGER ifexists fullname */
{
- sqlite3DropTrigger(pParse,yymsp[0].minor.yy427,yymsp[-1].minor.yy502);
+ sqlite3DropTrigger(pParse,yymsp[0].minor.yy135,yymsp[-1].minor.yy70);
}
break;
- case 261: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+ case 263: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
{
- sqlite3Attach(pParse, yymsp[-3].minor.yy182, yymsp[-1].minor.yy182, yymsp[0].minor.yy182);
+ sqlite3Attach(pParse, yymsp[-3].minor.yy18, yymsp[-1].minor.yy18, yymsp[0].minor.yy18);
}
break;
- case 262: /* cmd ::= DETACH database_kw_opt expr */
+ case 264: /* cmd ::= DETACH database_kw_opt expr */
{
- sqlite3Detach(pParse, yymsp[0].minor.yy182);
+ sqlite3Detach(pParse, yymsp[0].minor.yy18);
}
break;
- case 265: /* cmd ::= REINDEX */
+ case 267: /* cmd ::= REINDEX */
{sqlite3Reindex(pParse, 0, 0);}
break;
- case 266: /* cmd ::= REINDEX nm dbnm */
+ case 268: /* cmd ::= REINDEX nm dbnm */
{sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
- case 267: /* cmd ::= ANALYZE */
+ case 269: /* cmd ::= ANALYZE */
{sqlite3Analyze(pParse, 0, 0);}
break;
- case 268: /* cmd ::= ANALYZE nm dbnm */
+ case 270: /* cmd ::= ANALYZE nm dbnm */
{sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
- case 269: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
+ case 271: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
{
- sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy427,&yymsp[0].minor.yy0);
+ sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy135,&yymsp[0].minor.yy0);
}
break;
- case 270: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
+ case 272: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
{
yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n;
sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0);
}
break;
- case 271: /* add_column_fullname ::= fullname */
+ case 273: /* add_column_fullname ::= fullname */
{
disableLookaside(pParse);
- sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy427);
+ sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy135);
+}
+ break;
+ case 274: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
+{
+ sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy135, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);
}
break;
- case 272: /* cmd ::= create_vtab */
+ case 275: /* cmd ::= create_vtab */
{sqlite3VtabFinishParse(pParse,0);}
break;
- case 273: /* cmd ::= create_vtab LP vtabarglist RP */
+ case 276: /* cmd ::= create_vtab LP vtabarglist RP */
{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
break;
- case 274: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+ case 277: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
{
- sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy502);
+ sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy70);
}
break;
- case 275: /* vtabarg ::= */
+ case 278: /* vtabarg ::= */
{sqlite3VtabArgInit(pParse);}
break;
- case 276: /* vtabargtoken ::= ANY */
- case 277: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==277);
- case 278: /* lp ::= LP */ yytestcase(yyruleno==278);
+ case 279: /* vtabargtoken ::= ANY */
+ case 280: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==280);
+ case 281: /* lp ::= LP */ yytestcase(yyruleno==281);
{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
break;
- case 279: /* with ::= WITH wqlist */
- case 280: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==280);
-{ sqlite3WithPush(pParse, yymsp[0].minor.yy91, 1); }
+ case 282: /* with ::= WITH wqlist */
+ case 283: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==283);
+{ sqlite3WithPush(pParse, yymsp[0].minor.yy449, 1); }
break;
- case 281: /* wqlist ::= nm eidlist_opt AS LP select RP */
+ case 284: /* wqlist ::= nm eidlist_opt AS LP select RP */
{
- yymsp[-5].minor.yy91 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy232, yymsp[-1].minor.yy399); /*A-overwrites-X*/
+ yymsp[-5].minor.yy449 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy420, yymsp[-1].minor.yy489); /*A-overwrites-X*/
}
break;
- case 282: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
+ case 285: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
{
- yymsp[-7].minor.yy91 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy91, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy232, yymsp[-1].minor.yy399);
+ yymsp[-7].minor.yy449 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy449, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy420, yymsp[-1].minor.yy489);
+}
+ break;
+ case 286: /* windowdefn_list ::= windowdefn */
+{ yylhsminor.yy327 = yymsp[0].minor.yy327; }
+ yymsp[0].minor.yy327 = yylhsminor.yy327;
+ break;
+ case 287: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */
+{
+ assert( yymsp[0].minor.yy327!=0 );
+ yymsp[0].minor.yy327->pNextWin = yymsp[-2].minor.yy327;
+ yylhsminor.yy327 = yymsp[0].minor.yy327;
+}
+ yymsp[-2].minor.yy327 = yylhsminor.yy327;
+ break;
+ case 288: /* windowdefn ::= nm AS window */
+{
+ if( ALWAYS(yymsp[0].minor.yy327) ){
+ yymsp[0].minor.yy327->zName = sqlite3DbStrNDup(pParse->db, yymsp[-2].minor.yy0.z, yymsp[-2].minor.yy0.n);
+ }
+ yylhsminor.yy327 = yymsp[0].minor.yy327;
+}
+ yymsp[-2].minor.yy327 = yylhsminor.yy327;
+ break;
+ case 289: /* window ::= LP part_opt orderby_opt frame_opt RP */
+{
+ yymsp[-4].minor.yy327 = yymsp[-1].minor.yy327;
+ if( ALWAYS(yymsp[-4].minor.yy327) ){
+ yymsp[-4].minor.yy327->pPartition = yymsp[-3].minor.yy420;
+ yymsp[-4].minor.yy327->pOrderBy = yymsp[-2].minor.yy420;
+ }
+}
+ break;
+ case 290: /* part_opt ::= PARTITION BY nexprlist */
+{ yymsp[-2].minor.yy420 = yymsp[0].minor.yy420; }
+ break;
+ case 291: /* part_opt ::= */
+{ yymsp[1].minor.yy420 = 0; }
+ break;
+ case 292: /* frame_opt ::= */
+{
+ yymsp[1].minor.yy327 = sqlite3WindowAlloc(pParse, TK_RANGE, TK_UNBOUNDED, 0, TK_CURRENT, 0);
}
break;
+ case 293: /* frame_opt ::= range_or_rows frame_bound_s */
+{
+ yylhsminor.yy327 = sqlite3WindowAlloc(pParse, yymsp[-1].minor.yy70, yymsp[0].minor.yy119.eType, yymsp[0].minor.yy119.pExpr, TK_CURRENT, 0);
+}
+ yymsp[-1].minor.yy327 = yylhsminor.yy327;
+ break;
+ case 294: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e */
+{
+ yylhsminor.yy327 = sqlite3WindowAlloc(pParse, yymsp[-4].minor.yy70, yymsp[-2].minor.yy119.eType, yymsp[-2].minor.yy119.pExpr, yymsp[0].minor.yy119.eType, yymsp[0].minor.yy119.pExpr);
+}
+ yymsp[-4].minor.yy327 = yylhsminor.yy327;
+ break;
+ case 295: /* range_or_rows ::= RANGE */
+{ yymsp[0].minor.yy70 = TK_RANGE; }
+ break;
+ case 296: /* range_or_rows ::= ROWS */
+{ yymsp[0].minor.yy70 = TK_ROWS; }
+ break;
+ case 297: /* frame_bound_s ::= frame_bound */
+ case 299: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==299);
+{ yylhsminor.yy119 = yymsp[0].minor.yy119; }
+ yymsp[0].minor.yy119 = yylhsminor.yy119;
+ break;
+ case 298: /* frame_bound_s ::= UNBOUNDED PRECEDING */
+ case 300: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==300);
+{yymsp[-1].minor.yy119.eType = TK_UNBOUNDED; yymsp[-1].minor.yy119.pExpr = 0;}
+ break;
+ case 301: /* frame_bound ::= expr PRECEDING */
+{ yylhsminor.yy119.eType = TK_PRECEDING; yylhsminor.yy119.pExpr = yymsp[-1].minor.yy18; }
+ yymsp[-1].minor.yy119 = yylhsminor.yy119;
+ break;
+ case 302: /* frame_bound ::= CURRENT ROW */
+{ yymsp[-1].minor.yy119.eType = TK_CURRENT ; yymsp[-1].minor.yy119.pExpr = 0; }
+ break;
+ case 303: /* frame_bound ::= expr FOLLOWING */
+{ yylhsminor.yy119.eType = TK_FOLLOWING; yylhsminor.yy119.pExpr = yymsp[-1].minor.yy18; }
+ yymsp[-1].minor.yy119 = yylhsminor.yy119;
+ break;
+ case 304: /* window_clause ::= WINDOW windowdefn_list */
+{ yymsp[-1].minor.yy327 = yymsp[0].minor.yy327; }
+ break;
+ case 305: /* over_clause ::= filter_opt OVER window */
+{
+ yylhsminor.yy327 = yymsp[0].minor.yy327;
+ assert( yylhsminor.yy327!=0 );
+ yylhsminor.yy327->pFilter = yymsp[-2].minor.yy18;
+}
+ yymsp[-2].minor.yy327 = yylhsminor.yy327;
+ break;
+ case 306: /* over_clause ::= filter_opt OVER nm */
+{
+ yylhsminor.yy327 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
+ if( yylhsminor.yy327 ){
+ yylhsminor.yy327->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n);
+ yylhsminor.yy327->pFilter = yymsp[-2].minor.yy18;
+ }else{
+ sqlite3ExprDelete(pParse->db, yymsp[-2].minor.yy18);
+ }
+}
+ yymsp[-2].minor.yy327 = yylhsminor.yy327;
+ break;
+ case 308: /* filter_opt ::= FILTER LP WHERE expr RP */
+{ yymsp[-4].minor.yy18 = yymsp[-1].minor.yy18; }
+ break;
default:
- /* (283) input ::= cmdlist */ yytestcase(yyruleno==283);
- /* (284) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==284);
- /* (285) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=285);
- /* (286) ecmd ::= SEMI */ yytestcase(yyruleno==286);
- /* (287) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==287);
- /* (288) ecmd ::= explain cmdx */ yytestcase(yyruleno==288);
- /* (289) trans_opt ::= */ yytestcase(yyruleno==289);
- /* (290) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==290);
- /* (291) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==291);
- /* (292) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==292);
- /* (293) savepoint_opt ::= */ yytestcase(yyruleno==293);
- /* (294) cmd ::= create_table create_table_args */ yytestcase(yyruleno==294);
- /* (295) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==295);
- /* (296) columnlist ::= columnname carglist */ yytestcase(yyruleno==296);
- /* (297) nm ::= ID|INDEXED */ yytestcase(yyruleno==297);
- /* (298) nm ::= STRING */ yytestcase(yyruleno==298);
- /* (299) nm ::= JOIN_KW */ yytestcase(yyruleno==299);
- /* (300) typetoken ::= typename */ yytestcase(yyruleno==300);
- /* (301) typename ::= ID|STRING */ yytestcase(yyruleno==301);
- /* (302) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=302);
- /* (303) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=303);
- /* (304) carglist ::= carglist ccons */ yytestcase(yyruleno==304);
- /* (305) carglist ::= */ yytestcase(yyruleno==305);
- /* (306) ccons ::= NULL onconf */ yytestcase(yyruleno==306);
- /* (307) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==307);
- /* (308) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==308);
- /* (309) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=309);
- /* (310) tconscomma ::= */ yytestcase(yyruleno==310);
- /* (311) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=311);
- /* (312) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=312);
- /* (313) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=313);
- /* (314) oneselect ::= values */ yytestcase(yyruleno==314);
- /* (315) sclp ::= selcollist COMMA */ yytestcase(yyruleno==315);
- /* (316) as ::= ID|STRING */ yytestcase(yyruleno==316);
- /* (317) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=317);
- /* (318) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==318);
- /* (319) exprlist ::= nexprlist */ yytestcase(yyruleno==319);
- /* (320) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=320);
- /* (321) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=321);
- /* (322) nmnum ::= ON */ yytestcase(yyruleno==322);
- /* (323) nmnum ::= DELETE */ yytestcase(yyruleno==323);
- /* (324) nmnum ::= DEFAULT */ yytestcase(yyruleno==324);
- /* (325) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==325);
- /* (326) foreach_clause ::= */ yytestcase(yyruleno==326);
- /* (327) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==327);
- /* (328) trnm ::= nm */ yytestcase(yyruleno==328);
- /* (329) tridxby ::= */ yytestcase(yyruleno==329);
- /* (330) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==330);
- /* (331) database_kw_opt ::= */ yytestcase(yyruleno==331);
- /* (332) kwcolumn_opt ::= */ yytestcase(yyruleno==332);
- /* (333) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==333);
- /* (334) vtabarglist ::= vtabarg */ yytestcase(yyruleno==334);
- /* (335) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==335);
- /* (336) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==336);
- /* (337) anylist ::= */ yytestcase(yyruleno==337);
- /* (338) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==338);
- /* (339) anylist ::= anylist ANY */ yytestcase(yyruleno==339);
- /* (340) with ::= */ yytestcase(yyruleno==340);
+ /* (309) input ::= cmdlist */ yytestcase(yyruleno==309);
+ /* (310) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==310);
+ /* (311) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=311);
+ /* (312) ecmd ::= SEMI */ yytestcase(yyruleno==312);
+ /* (313) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==313);
+ /* (314) ecmd ::= explain cmdx */ yytestcase(yyruleno==314);
+ /* (315) trans_opt ::= */ yytestcase(yyruleno==315);
+ /* (316) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==316);
+ /* (317) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==317);
+ /* (318) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==318);
+ /* (319) savepoint_opt ::= */ yytestcase(yyruleno==319);
+ /* (320) cmd ::= create_table create_table_args */ yytestcase(yyruleno==320);
+ /* (321) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==321);
+ /* (322) columnlist ::= columnname carglist */ yytestcase(yyruleno==322);
+ /* (323) nm ::= ID|INDEXED */ yytestcase(yyruleno==323);
+ /* (324) nm ::= STRING */ yytestcase(yyruleno==324);
+ /* (325) nm ::= JOIN_KW */ yytestcase(yyruleno==325);
+ /* (326) typetoken ::= typename */ yytestcase(yyruleno==326);
+ /* (327) typename ::= ID|STRING */ yytestcase(yyruleno==327);
+ /* (328) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=328);
+ /* (329) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=329);
+ /* (330) carglist ::= carglist ccons */ yytestcase(yyruleno==330);
+ /* (331) carglist ::= */ yytestcase(yyruleno==331);
+ /* (332) ccons ::= NULL onconf */ yytestcase(yyruleno==332);
+ /* (333) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==333);
+ /* (334) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==334);
+ /* (335) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=335);
+ /* (336) tconscomma ::= */ yytestcase(yyruleno==336);
+ /* (337) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=337);
+ /* (338) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=338);
+ /* (339) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=339);
+ /* (340) oneselect ::= values */ yytestcase(yyruleno==340);
+ /* (341) sclp ::= selcollist COMMA */ yytestcase(yyruleno==341);
+ /* (342) as ::= ID|STRING */ yytestcase(yyruleno==342);
+ /* (343) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=343);
+ /* (344) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==344);
+ /* (345) exprlist ::= nexprlist */ yytestcase(yyruleno==345);
+ /* (346) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=346);
+ /* (347) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=347);
+ /* (348) nmnum ::= ON */ yytestcase(yyruleno==348);
+ /* (349) nmnum ::= DELETE */ yytestcase(yyruleno==349);
+ /* (350) nmnum ::= DEFAULT */ yytestcase(yyruleno==350);
+ /* (351) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==351);
+ /* (352) foreach_clause ::= */ yytestcase(yyruleno==352);
+ /* (353) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==353);
+ /* (354) trnm ::= nm */ yytestcase(yyruleno==354);
+ /* (355) tridxby ::= */ yytestcase(yyruleno==355);
+ /* (356) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==356);
+ /* (357) database_kw_opt ::= */ yytestcase(yyruleno==357);
+ /* (358) kwcolumn_opt ::= */ yytestcase(yyruleno==358);
+ /* (359) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==359);
+ /* (360) vtabarglist ::= vtabarg */ yytestcase(yyruleno==360);
+ /* (361) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==361);
+ /* (362) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==362);
+ /* (363) anylist ::= */ yytestcase(yyruleno==363);
+ /* (364) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==364);
+ /* (365) anylist ::= anylist ANY */ yytestcase(yyruleno==365);
+ /* (366) with ::= */ yytestcase(yyruleno==366);
break;
/********** End reduce actions ************************************************/
};
@@ -145328,12 +150169,12 @@ SQLITE_PRIVATE void sqlite3Parser(
do{
assert( yyact==yypParser->yytos->stateno );
- yyact = yy_find_shift_action(yymajor,yyact);
+ yyact = yy_find_shift_action((YYCODETYPE)yymajor,yyact);
if( yyact >= YY_MIN_REDUCE ){
yyact = yy_reduce(yypParser,yyact-YY_MIN_REDUCE,yymajor,
yyminor sqlite3ParserCTX_PARAM);
}else if( yyact <= YY_MAX_SHIFTREDUCE ){
- yy_shift(yypParser,yyact,yymajor,yyminor);
+ yy_shift(yypParser,yyact,(YYCODETYPE)yymajor,yyminor);
#ifndef YYNOERRORRECOVERY
yypParser->yyerrcnt--;
#endif
@@ -145461,6 +150302,21 @@ SQLITE_PRIVATE void sqlite3Parser(
return;
}
+/*
+** Return the fallback token corresponding to canonical token iToken, or
+** 0 if iToken has no fallback.
+*/
+SQLITE_PRIVATE int sqlite3ParserFallback(int iToken){
+#ifdef YYFALLBACK
+ if( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ){
+ return yyFallback[iToken];
+ }
+#else
+ (void)iToken;
+#endif
+ return 0;
+}
+
/************** End of parse.c ***********************************************/
/************** Begin file tokenize.c ****************************************/
/*
@@ -145519,11 +150375,12 @@ SQLITE_PRIVATE void sqlite3Parser(
#define CC_TILDA 25 /* '~' */
#define CC_DOT 26 /* '.' */
#define CC_ILLEGAL 27 /* Illegal character */
+#define CC_NUL 28 /* 0x00 */
static const unsigned char aiClass[] = {
#ifdef SQLITE_ASCII
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
-/* 0x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 27, 7, 7, 27, 27,
+/* 0x */ 28, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 27, 7, 7, 27, 27,
/* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* 2x */ 7, 15, 8, 5, 4, 22, 24, 8, 17, 18, 21, 20, 23, 11, 26, 16,
/* 3x */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 19, 12, 14, 13, 6,
@@ -145622,19 +150479,20 @@ const unsigned char ebcdicToAscii[] = {
** is substantially reduced. This is important for embedded applications
** on platforms with limited memory.
*/
-/* Hash score: 185 */
-/* zKWText[] encodes 845 bytes of keyword text in 561 bytes */
+/* Hash score: 208 */
+/* zKWText[] encodes 923 bytes of keyword text in 614 bytes */
/* REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT */
/* ABLEFTHENDEFERRABLELSEXCEPTRANSACTIONATURALTERAISEXCLUSIVE */
/* XISTSAVEPOINTERSECTRIGGEREFERENCESCONSTRAINTOFFSETEMPORARY */
-/* UNIQUERYWITHOUTERELEASEATTACHAVINGROUPDATEBEGINNERECURSIVE */
-/* BETWEENOTHINGLOBYCASCADELETECASECOLLATECREATECURRENT_DATE */
-/* DETACHIMMEDIATEJOINSERTLIKEMATCHPLANALYZEPRAGMABORTVALUES */
-/* VIRTUALIMITWHENOTNULLWHERENAMEAFTEREPLACEANDEFAULT */
-/* AUTOINCREMENTCASTCOLUMNCOMMITCONFLICTCROSSCURRENT_TIMESTAMP */
-/* RIMARYDEFERREDISTINCTDORDERESTRICTDROPFAILFROMFULLIFISNULL */
-/* RIGHTROLLBACKROWUNIONUSINGVACUUMVIEWINITIALLY */
-static const char zKWText[560] = {
+/* UNIQUERYWITHOUTERELEASEATTACHAVINGROUPDATEBEGINNERANGEBETWEEN */
+/* OTHINGLOBYCASCADELETECASECOLLATECREATECURRENT_DATEDETACH */
+/* IMMEDIATEJOINSERTLIKEMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMIT */
+/* WHENOTNULLWHERECURSIVEAFTERENAMEANDEFAULTAUTOINCREMENTCAST */
+/* COLUMNCOMMITCONFLICTCROSSCURRENT_TIMESTAMPARTITIONDEFERRED */
+/* ISTINCTDROPRECEDINGFAILFILTEREPLACEFOLLOWINGFROMFULLIFISNULL */
+/* ORDERESTRICTOVERIGHTROLLBACKROWSUNBOUNDEDUNIONUSINGVACUUMVIEW */
+/* INDOWINITIALLYPRIMARY */
+static const char zKWText[613] = {
'R','E','I','N','D','E','X','E','D','E','S','C','A','P','E','A','C','H',
'E','C','K','E','Y','B','E','F','O','R','E','I','G','N','O','R','E','G',
'E','X','P','L','A','I','N','S','T','E','A','D','D','A','T','A','B','A',
@@ -145647,84 +150505,90 @@ static const char zKWText[560] = {
'O','F','F','S','E','T','E','M','P','O','R','A','R','Y','U','N','I','Q',
'U','E','R','Y','W','I','T','H','O','U','T','E','R','E','L','E','A','S',
'E','A','T','T','A','C','H','A','V','I','N','G','R','O','U','P','D','A',
- 'T','E','B','E','G','I','N','N','E','R','E','C','U','R','S','I','V','E',
- 'B','E','T','W','E','E','N','O','T','H','I','N','G','L','O','B','Y','C',
- 'A','S','C','A','D','E','L','E','T','E','C','A','S','E','C','O','L','L',
- 'A','T','E','C','R','E','A','T','E','C','U','R','R','E','N','T','_','D',
- 'A','T','E','D','E','T','A','C','H','I','M','M','E','D','I','A','T','E',
- 'J','O','I','N','S','E','R','T','L','I','K','E','M','A','T','C','H','P',
- 'L','A','N','A','L','Y','Z','E','P','R','A','G','M','A','B','O','R','T',
- 'V','A','L','U','E','S','V','I','R','T','U','A','L','I','M','I','T','W',
- 'H','E','N','O','T','N','U','L','L','W','H','E','R','E','N','A','M','E',
- 'A','F','T','E','R','E','P','L','A','C','E','A','N','D','E','F','A','U',
- 'L','T','A','U','T','O','I','N','C','R','E','M','E','N','T','C','A','S',
- 'T','C','O','L','U','M','N','C','O','M','M','I','T','C','O','N','F','L',
- 'I','C','T','C','R','O','S','S','C','U','R','R','E','N','T','_','T','I',
- 'M','E','S','T','A','M','P','R','I','M','A','R','Y','D','E','F','E','R',
- 'R','E','D','I','S','T','I','N','C','T','D','O','R','D','E','R','E','S',
- 'T','R','I','C','T','D','R','O','P','F','A','I','L','F','R','O','M','F',
- 'U','L','L','I','F','I','S','N','U','L','L','R','I','G','H','T','R','O',
- 'L','L','B','A','C','K','R','O','W','U','N','I','O','N','U','S','I','N',
- 'G','V','A','C','U','U','M','V','I','E','W','I','N','I','T','I','A','L',
- 'L','Y',
+ 'T','E','B','E','G','I','N','N','E','R','A','N','G','E','B','E','T','W',
+ 'E','E','N','O','T','H','I','N','G','L','O','B','Y','C','A','S','C','A',
+ 'D','E','L','E','T','E','C','A','S','E','C','O','L','L','A','T','E','C',
+ 'R','E','A','T','E','C','U','R','R','E','N','T','_','D','A','T','E','D',
+ 'E','T','A','C','H','I','M','M','E','D','I','A','T','E','J','O','I','N',
+ 'S','E','R','T','L','I','K','E','M','A','T','C','H','P','L','A','N','A',
+ 'L','Y','Z','E','P','R','A','G','M','A','B','O','R','T','V','A','L','U',
+ 'E','S','V','I','R','T','U','A','L','I','M','I','T','W','H','E','N','O',
+ 'T','N','U','L','L','W','H','E','R','E','C','U','R','S','I','V','E','A',
+ 'F','T','E','R','E','N','A','M','E','A','N','D','E','F','A','U','L','T',
+ 'A','U','T','O','I','N','C','R','E','M','E','N','T','C','A','S','T','C',
+ 'O','L','U','M','N','C','O','M','M','I','T','C','O','N','F','L','I','C',
+ 'T','C','R','O','S','S','C','U','R','R','E','N','T','_','T','I','M','E',
+ 'S','T','A','M','P','A','R','T','I','T','I','O','N','D','E','F','E','R',
+ 'R','E','D','I','S','T','I','N','C','T','D','R','O','P','R','E','C','E',
+ 'D','I','N','G','F','A','I','L','F','I','L','T','E','R','E','P','L','A',
+ 'C','E','F','O','L','L','O','W','I','N','G','F','R','O','M','F','U','L',
+ 'L','I','F','I','S','N','U','L','L','O','R','D','E','R','E','S','T','R',
+ 'I','C','T','O','V','E','R','I','G','H','T','R','O','L','L','B','A','C',
+ 'K','R','O','W','S','U','N','B','O','U','N','D','E','D','U','N','I','O',
+ 'N','U','S','I','N','G','V','A','C','U','U','M','V','I','E','W','I','N',
+ 'D','O','W','I','N','I','T','I','A','L','L','Y','P','R','I','M','A','R',
+ 'Y',
};
/* aKWHash[i] is the hash value for the i-th keyword */
static const unsigned char aKWHash[127] = {
- 74, 108, 119, 72, 0, 45, 0, 0, 81, 0, 76, 61, 0,
- 42, 12, 77, 15, 0, 118, 84, 54, 116, 0, 19, 0, 0,
- 123, 0, 121, 111, 0, 22, 96, 0, 9, 0, 0, 68, 69,
- 0, 67, 6, 0, 48, 93, 105, 0, 120, 104, 0, 0, 44,
- 0, 106, 24, 0, 17, 0, 124, 53, 23, 0, 5, 62, 25,
- 99, 0, 0, 126, 112, 60, 125, 57, 28, 55, 0, 94, 0,
- 103, 26, 0, 102, 0, 0, 0, 98, 95, 100, 91, 115, 14,
- 39, 114, 0, 80, 0, 109, 92, 90, 32, 0, 122, 79, 117,
- 86, 46, 83, 0, 0, 97, 40, 59, 110, 0, 36, 0, 0,
- 29, 0, 89, 87, 88, 0, 20, 85, 0, 56,
+ 74, 109, 124, 72, 106, 45, 0, 0, 81, 0, 76, 61, 0,
+ 42, 12, 77, 15, 0, 123, 84, 54, 118, 125, 19, 0, 0,
+ 130, 0, 128, 121, 0, 22, 96, 0, 9, 0, 0, 115, 69,
+ 0, 67, 6, 0, 48, 93, 136, 0, 126, 104, 0, 0, 44,
+ 0, 107, 24, 0, 17, 0, 131, 53, 23, 0, 5, 62, 132,
+ 99, 0, 0, 135, 110, 60, 134, 57, 113, 55, 0, 94, 0,
+ 103, 26, 0, 102, 0, 0, 0, 98, 95, 100, 105, 117, 14,
+ 39, 116, 0, 80, 0, 133, 114, 92, 59, 0, 129, 79, 119,
+ 86, 46, 83, 0, 0, 97, 40, 122, 120, 0, 127, 0, 0,
+ 29, 0, 89, 87, 88, 0, 20, 85, 111, 56,
};
/* aKWNext[] forms the hash collision chain. If aKWHash[i]==0
** then the i-th keyword has no more hash collisions. Otherwise,
** the next keyword with the same hash is aKWHash[i]-1. */
-static const unsigned char aKWNext[126] = {
+static const unsigned char aKWNext[136] = {
0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0,
0, 2, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 33, 0, 21, 0, 0, 0, 0, 0, 50,
- 0, 43, 3, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 43, 3, 47, 0, 0, 32, 0, 0, 0, 0, 0, 0,
0, 1, 64, 0, 0, 65, 0, 41, 0, 38, 0, 0, 0,
- 0, 0, 49, 75, 0, 0, 30, 0, 58, 0, 0, 63, 31,
- 52, 16, 34, 10, 0, 0, 0, 0, 0, 0, 0, 11, 70,
- 78, 0, 8, 0, 18, 51, 0, 107, 101, 0, 113, 0, 73,
- 27, 37, 71, 82, 0, 35, 66, 0, 0,
+ 0, 0, 49, 75, 0, 0, 30, 0, 58, 0, 0, 0, 31,
+ 63, 16, 34, 10, 0, 0, 0, 0, 0, 0, 0, 11, 70,
+ 91, 0, 0, 8, 0, 108, 0, 101, 28, 52, 68, 0, 112,
+ 0, 73, 51, 0, 90, 27, 37, 0, 71, 36, 82, 0, 35,
+ 66, 25, 18, 0, 0, 78,
};
/* aKWLen[i] is the length (in bytes) of the i-th keyword */
-static const unsigned char aKWLen[126] = {
+static const unsigned char aKWLen[136] = {
7, 7, 5, 4, 6, 4, 5, 3, 6, 7, 3, 6, 6,
7, 7, 3, 8, 2, 6, 5, 4, 4, 3, 10, 4, 6,
11, 6, 2, 7, 5, 5, 9, 6, 9, 9, 7, 10, 10,
4, 6, 2, 3, 9, 4, 2, 6, 5, 7, 4, 5, 7,
- 6, 6, 5, 6, 5, 5, 9, 7, 7, 4, 2, 7, 3,
+ 6, 6, 5, 6, 5, 5, 5, 7, 7, 4, 2, 7, 3,
6, 4, 7, 6, 12, 6, 9, 4, 6, 4, 5, 4, 7,
- 6, 5, 6, 7, 5, 4, 7, 3, 2, 4, 5, 6, 5,
- 7, 3, 7, 13, 2, 2, 4, 6, 6, 8, 5, 17, 12,
- 7, 8, 8, 2, 2, 5, 8, 4, 4, 4, 4, 2, 6,
- 5, 8, 3, 5, 5, 6, 4, 9, 3,
+ 6, 5, 6, 7, 5, 4, 7, 3, 2, 4, 5, 9, 5,
+ 6, 3, 7, 13, 2, 2, 4, 6, 6, 8, 5, 17, 12,
+ 7, 9, 8, 8, 2, 4, 9, 4, 6, 7, 9, 4, 4,
+ 2, 6, 5, 8, 4, 5, 8, 4, 3, 9, 5, 5, 6,
+ 4, 6, 2, 9, 3, 7,
};
/* aKWOffset[i] is the index into zKWText[] of the start of
** the text for the i-th keyword. */
-static const unsigned short int aKWOffset[126] = {
+static const unsigned short int aKWOffset[136] = {
0, 2, 2, 8, 9, 14, 16, 20, 23, 25, 25, 29, 33,
36, 41, 46, 48, 53, 54, 59, 62, 65, 67, 69, 78, 81,
86, 91, 95, 96, 101, 105, 109, 117, 122, 128, 136, 142, 152,
159, 162, 162, 165, 167, 167, 171, 176, 179, 184, 184, 188, 192,
- 199, 204, 209, 212, 218, 221, 225, 234, 240, 246, 249, 251, 252,
- 256, 262, 266, 273, 279, 291, 297, 306, 308, 314, 318, 323, 325,
- 332, 337, 342, 348, 354, 359, 362, 362, 362, 365, 369, 372, 378,
- 382, 389, 391, 398, 400, 402, 411, 415, 421, 427, 435, 440, 440,
- 456, 463, 470, 471, 478, 479, 483, 491, 495, 499, 503, 507, 509,
- 515, 520, 528, 531, 536, 541, 547, 551, 556,
+ 199, 204, 209, 212, 218, 221, 225, 230, 236, 242, 245, 247, 248,
+ 252, 258, 262, 269, 275, 287, 293, 302, 304, 310, 314, 319, 321,
+ 328, 333, 338, 344, 350, 355, 358, 358, 358, 361, 365, 368, 377,
+ 381, 387, 389, 396, 398, 400, 409, 413, 419, 425, 433, 438, 438,
+ 438, 454, 463, 470, 471, 478, 481, 490, 494, 499, 506, 515, 519,
+ 523, 525, 531, 535, 543, 546, 551, 559, 559, 563, 572, 577, 582,
+ 588, 591, 594, 597, 602, 606,
};
/* aKWCode[i] is the parser symbol code for the i-th keyword */
-static const unsigned char aKWCode[126] = {
+static const unsigned char aKWCode[136] = {
TK_REINDEX, TK_INDEXED, TK_INDEX, TK_DESC, TK_ESCAPE,
TK_EACH, TK_CHECK, TK_KEY, TK_BEFORE, TK_FOREIGN,
TK_FOR, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD,
@@ -145736,21 +150600,23 @@ static const unsigned char aKWCode[126] = {
TK_OFFSET, TK_OF, TK_SET, TK_TEMP, TK_TEMP,
TK_OR, TK_UNIQUE, TK_QUERY, TK_WITHOUT, TK_WITH,
TK_JOIN_KW, TK_RELEASE, TK_ATTACH, TK_HAVING, TK_GROUP,
- TK_UPDATE, TK_BEGIN, TK_JOIN_KW, TK_RECURSIVE, TK_BETWEEN,
+ TK_UPDATE, TK_BEGIN, TK_JOIN_KW, TK_RANGE, TK_BETWEEN,
TK_NOTHING, TK_LIKE_KW, TK_BY, TK_CASCADE, TK_ASC,
TK_DELETE, TK_CASE, TK_COLLATE, TK_CREATE, TK_CTIME_KW,
TK_DETACH, TK_IMMEDIATE, TK_JOIN, TK_INSERT, TK_LIKE_KW,
TK_MATCH, TK_PLAN, TK_ANALYZE, TK_PRAGMA, TK_ABORT,
TK_VALUES, TK_VIRTUAL, TK_LIMIT, TK_WHEN, TK_NOTNULL,
- TK_NOT, TK_NO, TK_NULL, TK_WHERE, TK_RENAME,
- TK_AFTER, TK_REPLACE, TK_AND, TK_DEFAULT, TK_AUTOINCR,
+ TK_NOT, TK_NO, TK_NULL, TK_WHERE, TK_RECURSIVE,
+ TK_AFTER, TK_RENAME, TK_AND, TK_DEFAULT, TK_AUTOINCR,
TK_TO, TK_IN, TK_CAST, TK_COLUMNKW, TK_COMMIT,
- TK_CONFLICT, TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW, TK_PRIMARY,
- TK_DEFERRED, TK_DISTINCT, TK_IS, TK_DO, TK_ORDER,
- TK_RESTRICT, TK_DROP, TK_FAIL, TK_FROM, TK_JOIN_KW,
- TK_IF, TK_ISNULL, TK_JOIN_KW, TK_ROLLBACK, TK_ROW,
- TK_UNION, TK_USING, TK_VACUUM, TK_VIEW, TK_INITIALLY,
- TK_ALL,
+ TK_CONFLICT, TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW, TK_CURRENT,
+ TK_PARTITION, TK_DEFERRED, TK_DISTINCT, TK_IS, TK_DROP,
+ TK_PRECEDING, TK_FAIL, TK_FILTER, TK_REPLACE, TK_FOLLOWING,
+ TK_FROM, TK_JOIN_KW, TK_IF, TK_ISNULL, TK_ORDER,
+ TK_RESTRICT, TK_OVER, TK_JOIN_KW, TK_ROLLBACK, TK_ROWS,
+ TK_ROW, TK_UNBOUNDED, TK_UNION, TK_USING, TK_VACUUM,
+ TK_VIEW, TK_WINDOW, TK_DO, TK_INITIALLY, TK_ALL,
+ TK_PRIMARY,
};
/* Check to see if z[0..n-1] is a keyword. If it is, write the
** parser symbol code for that keyword into *pType. Always
@@ -145829,7 +150695,7 @@ static int keywordCode(const char *z, int n, int *pType){
testcase( i==55 ); /* UPDATE */
testcase( i==56 ); /* BEGIN */
testcase( i==57 ); /* INNER */
- testcase( i==58 ); /* RECURSIVE */
+ testcase( i==58 ); /* RANGE */
testcase( i==59 ); /* BETWEEN */
testcase( i==60 ); /* NOTHING */
testcase( i==61 ); /* GLOB */
@@ -145860,9 +150726,9 @@ static int keywordCode(const char *z, int n, int *pType){
testcase( i==86 ); /* NO */
testcase( i==87 ); /* NULL */
testcase( i==88 ); /* WHERE */
- testcase( i==89 ); /* RENAME */
+ testcase( i==89 ); /* RECURSIVE */
testcase( i==90 ); /* AFTER */
- testcase( i==91 ); /* REPLACE */
+ testcase( i==91 ); /* RENAME */
testcase( i==92 ); /* AND */
testcase( i==93 ); /* DEFAULT */
testcase( i==94 ); /* AUTOINCREMENT */
@@ -145875,28 +150741,38 @@ static int keywordCode(const char *z, int n, int *pType){
testcase( i==101 ); /* CROSS */
testcase( i==102 ); /* CURRENT_TIMESTAMP */
testcase( i==103 ); /* CURRENT_TIME */
- testcase( i==104 ); /* PRIMARY */
- testcase( i==105 ); /* DEFERRED */
- testcase( i==106 ); /* DISTINCT */
- testcase( i==107 ); /* IS */
- testcase( i==108 ); /* DO */
- testcase( i==109 ); /* ORDER */
- testcase( i==110 ); /* RESTRICT */
- testcase( i==111 ); /* DROP */
- testcase( i==112 ); /* FAIL */
- testcase( i==113 ); /* FROM */
- testcase( i==114 ); /* FULL */
- testcase( i==115 ); /* IF */
- testcase( i==116 ); /* ISNULL */
- testcase( i==117 ); /* RIGHT */
- testcase( i==118 ); /* ROLLBACK */
- testcase( i==119 ); /* ROW */
- testcase( i==120 ); /* UNION */
- testcase( i==121 ); /* USING */
- testcase( i==122 ); /* VACUUM */
- testcase( i==123 ); /* VIEW */
- testcase( i==124 ); /* INITIALLY */
- testcase( i==125 ); /* ALL */
+ testcase( i==104 ); /* CURRENT */
+ testcase( i==105 ); /* PARTITION */
+ testcase( i==106 ); /* DEFERRED */
+ testcase( i==107 ); /* DISTINCT */
+ testcase( i==108 ); /* IS */
+ testcase( i==109 ); /* DROP */
+ testcase( i==110 ); /* PRECEDING */
+ testcase( i==111 ); /* FAIL */
+ testcase( i==112 ); /* FILTER */
+ testcase( i==113 ); /* REPLACE */
+ testcase( i==114 ); /* FOLLOWING */
+ testcase( i==115 ); /* FROM */
+ testcase( i==116 ); /* FULL */
+ testcase( i==117 ); /* IF */
+ testcase( i==118 ); /* ISNULL */
+ testcase( i==119 ); /* ORDER */
+ testcase( i==120 ); /* RESTRICT */
+ testcase( i==121 ); /* OVER */
+ testcase( i==122 ); /* RIGHT */
+ testcase( i==123 ); /* ROLLBACK */
+ testcase( i==124 ); /* ROWS */
+ testcase( i==125 ); /* ROW */
+ testcase( i==126 ); /* UNBOUNDED */
+ testcase( i==127 ); /* UNION */
+ testcase( i==128 ); /* USING */
+ testcase( i==129 ); /* VACUUM */
+ testcase( i==130 ); /* VIEW */
+ testcase( i==131 ); /* WINDOW */
+ testcase( i==132 ); /* DO */
+ testcase( i==133 ); /* INITIALLY */
+ testcase( i==134 ); /* ALL */
+ testcase( i==135 ); /* PRIMARY */
*pType = aKWCode[i];
break;
}
@@ -145908,7 +150784,7 @@ SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char *z, int n){
keywordCode((char*)z, n, &id);
return id;
}
-#define SQLITE_N_KEYWORD 126
+#define SQLITE_N_KEYWORD 136
SQLITE_API int sqlite3_keyword_name(int i,const char **pzName,int *pnName){
if( i<0 || i>=SQLITE_N_KEYWORD ) return SQLITE_ERROR;
*pzName = zKWText + aKWOffset[i];
@@ -145962,11 +150838,85 @@ SQLITE_PRIVATE const char sqlite3IsEbcdicIdChar[] = {
#define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40]))
#endif
-/* Make the IdChar function accessible from ctime.c */
-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
+/* Make the IdChar function accessible from ctime.c and alter.c */
SQLITE_PRIVATE int sqlite3IsIdChar(u8 c){ return IdChar(c); }
-#endif
+#ifndef SQLITE_OMIT_WINDOWFUNC
+/*
+** Return the id of the next token in string (*pz). Before returning, set
+** (*pz) to point to the byte following the parsed token.
+*/
+static int getToken(const unsigned char **pz){
+ const unsigned char *z = *pz;
+ int t; /* Token type to return */
+ do {
+ z += sqlite3GetToken(z, &t);
+ }while( t==TK_SPACE );
+ if( t==TK_ID
+ || t==TK_STRING
+ || t==TK_JOIN_KW
+ || t==TK_WINDOW
+ || t==TK_OVER
+ || sqlite3ParserFallback(t)==TK_ID
+ ){
+ t = TK_ID;
+ }
+ *pz = z;
+ return t;
+}
+
+/*
+** The following three functions are called immediately after the tokenizer
+** reads the keywords WINDOW, OVER and FILTER, respectively, to determine
+** whether the token should be treated as a keyword or an SQL identifier.
+** This cannot be handled by the usual lemon %fallback method, due to
+** the ambiguity in some constructions. e.g.
+**
+** SELECT sum(x) OVER ...
+**
+** In the above, "OVER" might be a keyword, or it might be an alias for the
+** sum(x) expression. If a "%fallback ID OVER" directive were added to
+** grammar, then SQLite would always treat "OVER" as an alias, making it
+** impossible to call a window-function without a FILTER clause.
+**
+** WINDOW is treated as a keyword if:
+**
+** * the following token is an identifier, or a keyword that can fallback
+** to being an identifier, and
+** * the token after than one is TK_AS.
+**
+** OVER is a keyword if:
+**
+** * the previous token was TK_RP, and
+** * the next token is either TK_LP or an identifier.
+**
+** FILTER is a keyword if:
+**
+** * the previous token was TK_RP, and
+** * the next token is TK_LP.
+*/
+static int analyzeWindowKeyword(const unsigned char *z){
+ int t;
+ t = getToken(&z);
+ if( t!=TK_ID ) return TK_ID;
+ t = getToken(&z);
+ if( t!=TK_AS ) return TK_ID;
+ return TK_WINDOW;
+}
+static int analyzeOverKeyword(const unsigned char *z, int lastToken){
+ if( lastToken==TK_RP ){
+ int t = getToken(&z);
+ if( t==TK_LP || t==TK_ID ) return TK_OVER;
+ }
+ return TK_ID;
+}
+static int analyzeFilterKeyword(const unsigned char *z, int lastToken){
+ if( lastToken==TK_RP && getToken(&z)==TK_LP ){
+ return TK_FILTER;
+ }
+ return TK_ID;
+}
+#endif /* SQLITE_OMIT_WINDOWFUNC */
/*
** Return the length (in bytes) of the token that begins at z[0].
@@ -146235,6 +151185,10 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
i = 1;
break;
}
+ case CC_NUL: {
+ *tokenType = TK_ILLEGAL;
+ return 0;
+ }
default: {
*tokenType = TK_ILLEGAL;
return 1;
@@ -146288,47 +151242,64 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr
assert( pParse->nVar==0 );
assert( pParse->pVList==0 );
while( 1 ){
- if( zSql[0]!=0 ){
- n = sqlite3GetToken((u8*)zSql, &tokenType);
- mxSqlLen -= n;
- if( mxSqlLen<0 ){
- pParse->rc = SQLITE_TOOBIG;
- break;
- }
- }else{
- /* Upon reaching the end of input, call the parser two more times
- ** with tokens TK_SEMI and 0, in that order. */
- if( lastTokenParsed==TK_SEMI ){
- tokenType = 0;
- }else if( lastTokenParsed==0 ){
- break;
- }else{
- tokenType = TK_SEMI;
- }
- n = 0;
+ n = sqlite3GetToken((u8*)zSql, &tokenType);
+ mxSqlLen -= n;
+ if( mxSqlLen<0 ){
+ pParse->rc = SQLITE_TOOBIG;
+ break;
}
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( tokenType>=TK_WINDOW ){
+ assert( tokenType==TK_SPACE || tokenType==TK_OVER || tokenType==TK_FILTER
+ || tokenType==TK_ILLEGAL || tokenType==TK_WINDOW
+ );
+#else
if( tokenType>=TK_SPACE ){
assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL );
+#endif /* SQLITE_OMIT_WINDOWFUNC */
if( db->u1.isInterrupted ){
pParse->rc = SQLITE_INTERRUPT;
break;
}
- if( tokenType==TK_ILLEGAL ){
+ if( tokenType==TK_SPACE ){
+ zSql += n;
+ continue;
+ }
+ if( zSql[0]==0 ){
+ /* Upon reaching the end of input, call the parser two more times
+ ** with tokens TK_SEMI and 0, in that order. */
+ if( lastTokenParsed==TK_SEMI ){
+ tokenType = 0;
+ }else if( lastTokenParsed==0 ){
+ break;
+ }else{
+ tokenType = TK_SEMI;
+ }
+ n = 0;
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ }else if( tokenType==TK_WINDOW ){
+ assert( n==6 );
+ tokenType = analyzeWindowKeyword((const u8*)&zSql[6]);
+ }else if( tokenType==TK_OVER ){
+ assert( n==4 );
+ tokenType = analyzeOverKeyword((const u8*)&zSql[4], lastTokenParsed);
+ }else if( tokenType==TK_FILTER ){
+ assert( n==6 );
+ tokenType = analyzeFilterKeyword((const u8*)&zSql[6], lastTokenParsed);
+#endif /* SQLITE_OMIT_WINDOWFUNC */
+ }else{
sqlite3ErrorMsg(pParse, "unrecognized token: \"%.*s\"", n, zSql);
break;
}
- zSql += n;
- }else{
- pParse->sLastToken.z = zSql;
- pParse->sLastToken.n = n;
- sqlite3Parser(pEngine, tokenType, pParse->sLastToken);
- lastTokenParsed = tokenType;
- zSql += n;
- if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break;
}
+ pParse->sLastToken.z = zSql;
+ pParse->sLastToken.n = n;
+ sqlite3Parser(pEngine, tokenType, pParse->sLastToken);
+ lastTokenParsed = tokenType;
+ zSql += n;
+ if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break;
}
assert( nErr==0 );
- pParse->zTail = zSql;
#ifdef YYTRACKMAXSTACKDEPTH
sqlite3_mutex_enter(sqlite3MallocMutex());
sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK,
@@ -146350,10 +151321,12 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr
assert( pzErrMsg!=0 );
if( pParse->zErrMsg ){
*pzErrMsg = pParse->zErrMsg;
- sqlite3_log(pParse->rc, "%s", *pzErrMsg);
+ sqlite3_log(pParse->rc, "%s in \"%s\"",
+ *pzErrMsg, pParse->zTail);
pParse->zErrMsg = 0;
nErr++;
}
+ pParse->zTail = zSql;
if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){
sqlite3VdbeDelete(pParse->pVdbe);
pParse->pVdbe = 0;
@@ -146369,16 +151342,18 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr
sqlite3_free(pParse->apVtabLock);
#endif
- if( !IN_DECLARE_VTAB ){
+ if( !IN_SPECIAL_PARSE ){
/* If the pParse->declareVtab flag is set, do not delete any table
** structure built up in pParse->pNewTable. The calling code (see vtab.c)
** will take responsibility for freeing the Table structure.
*/
sqlite3DeleteTable(db, pParse->pNewTable);
}
+ if( !IN_RENAME_OBJECT ){
+ sqlite3DeleteTrigger(db, pParse->pNewTrigger);
+ }
if( pParse->pWithToFree ) sqlite3WithDelete(db, pParse->pWithToFree);
- sqlite3DeleteTrigger(db, pParse->pNewTrigger);
sqlite3DbFree(db, pParse->pVList);
while( pParse->pAinc ){
AutoincInfo *p = pParse->pAinc;
@@ -147635,7 +152610,7 @@ SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){
db->flags &= ~aFlagOp[i].mask;
}
if( oldFlags!=db->flags ){
- sqlite3ExpirePreparedStatements(db);
+ sqlite3ExpirePreparedStatements(db, 0);
}
if( pRes ){
*pRes = (db->flags & aFlagOp[i].mask)!=0;
@@ -147697,6 +152672,15 @@ static int binCollFunc(
}
/*
+** Return true if CollSeq is the default built-in BINARY.
+*/
+SQLITE_PRIVATE int sqlite3IsBinary(const CollSeq *p){
+ assert( p==0 || p->xCmp!=binCollFunc || p->pUser!=0
+ || strcmp(p->zName,"BINARY")==0 );
+ return p==0 || (p->xCmp==binCollFunc && p->pUser==0);
+}
+
+/*
** Another built-in collating sequence: NOCASE.
**
** This collating sequence is intended to be used for "case independent
@@ -147817,7 +152801,7 @@ static void disconnectAllVtab(sqlite3 *db){
sqlite3BtreeEnterAll(db);
for(i=0; i<db->nDb; i++){
Schema *pSchema = db->aDb[i].pSchema;
- if( db->aDb[i].pSchema ){
+ if( pSchema ){
for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
Table *pTab = (Table *)sqliteHashData(p);
if( IsVirtual(pTab) ) sqlite3VtabDisconnect(db, pTab);
@@ -148077,8 +153061,8 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
sqlite3VtabRollback(db);
sqlite3EndBenignMalloc();
- if( (db->mDbFlags&DBFLAG_SchemaChange)!=0 && db->init.busy==0 ){
- sqlite3ExpirePreparedStatements(db);
+ if( schemaChange ){
+ sqlite3ExpirePreparedStatements(db, 0);
sqlite3ResetAllSchemasOfConnection(db);
}
sqlite3BtreeLeaveAll(db);
@@ -148106,6 +153090,7 @@ SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
switch( rc ){
case SQLITE_OK: zName = "SQLITE_OK"; break;
case SQLITE_ERROR: zName = "SQLITE_ERROR"; break;
+ case SQLITE_ERROR_SNAPSHOT: zName = "SQLITE_ERROR_SNAPSHOT"; break;
case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break;
case SQLITE_PERM: zName = "SQLITE_PERM"; break;
case SQLITE_ABORT: zName = "SQLITE_ABORT"; break;
@@ -148469,6 +153454,8 @@ SQLITE_PRIVATE int sqlite3CreateFunc(
void (*xSFunc)(sqlite3_context*,int,sqlite3_value **),
void (*xStep)(sqlite3_context*,int,sqlite3_value **),
void (*xFinal)(sqlite3_context*),
+ void (*xValue)(sqlite3_context*),
+ void (*xInverse)(sqlite3_context*,int,sqlite3_value **),
FuncDestructor *pDestructor
){
FuncDef *p;
@@ -148476,12 +153463,14 @@ SQLITE_PRIVATE int sqlite3CreateFunc(
int extraFlags;
assert( sqlite3_mutex_held(db->mutex) );
- if( zFunctionName==0 ||
- (xSFunc && (xFinal || xStep)) ||
- (!xSFunc && (xFinal && !xStep)) ||
- (!xSFunc && (!xFinal && xStep)) ||
- (nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG) ||
- (255<(nName = sqlite3Strlen30( zFunctionName))) ){
+ assert( xValue==0 || xSFunc==0 );
+ if( zFunctionName==0 /* Must have a valid name */
+ || (xSFunc!=0 && xFinal!=0) /* Not both xSFunc and xFinal */
+ || ((xFinal==0)!=(xStep==0)) /* Both or neither of xFinal and xStep */
+ || ((xValue==0)!=(xInverse==0)) /* Both or neither of xValue, xInverse */
+ || (nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG)
+ || (255<(nName = sqlite3Strlen30( zFunctionName)))
+ ){
return SQLITE_MISUSE_BKPT;
}
@@ -148502,10 +153491,10 @@ SQLITE_PRIVATE int sqlite3CreateFunc(
}else if( enc==SQLITE_ANY ){
int rc;
rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8|extraFlags,
- pUserData, xSFunc, xStep, xFinal, pDestructor);
+ pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
if( rc==SQLITE_OK ){
rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE|extraFlags,
- pUserData, xSFunc, xStep, xFinal, pDestructor);
+ pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
}
if( rc!=SQLITE_OK ){
return rc;
@@ -148522,14 +153511,14 @@ SQLITE_PRIVATE int sqlite3CreateFunc(
** operation to continue but invalidate all precompiled statements.
*/
p = sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 0);
- if( p && (p->funcFlags & SQLITE_FUNC_ENCMASK)==enc && p->nArg==nArg ){
+ if( p && (p->funcFlags & SQLITE_FUNC_ENCMASK)==(u32)enc && p->nArg==nArg ){
if( db->nVdbeActive ){
sqlite3ErrorWithMsg(db, SQLITE_BUSY,
"unable to delete/modify user-function due to active statements");
assert( !db->mallocFailed );
return SQLITE_BUSY;
}else{
- sqlite3ExpirePreparedStatements(db);
+ sqlite3ExpirePreparedStatements(db, 0);
}
}
@@ -148551,38 +153540,32 @@ SQLITE_PRIVATE int sqlite3CreateFunc(
testcase( p->funcFlags & SQLITE_DETERMINISTIC );
p->xSFunc = xSFunc ? xSFunc : xStep;
p->xFinalize = xFinal;
+ p->xValue = xValue;
+ p->xInverse = xInverse;
p->pUserData = pUserData;
p->nArg = (u16)nArg;
return SQLITE_OK;
}
/*
-** Create new user functions.
+** Worker function used by utf-8 APIs that create new functions:
+**
+** sqlite3_create_function()
+** sqlite3_create_function_v2()
+** sqlite3_create_window_function()
*/
-SQLITE_API int sqlite3_create_function(
+static int createFunctionApi(
sqlite3 *db,
const char *zFunc,
int nArg,
int enc,
void *p,
- void (*xSFunc)(sqlite3_context*,int,sqlite3_value **),
- void (*xStep)(sqlite3_context*,int,sqlite3_value **),
- void (*xFinal)(sqlite3_context*)
-){
- return sqlite3_create_function_v2(db, zFunc, nArg, enc, p, xSFunc, xStep,
- xFinal, 0);
-}
-
-SQLITE_API int sqlite3_create_function_v2(
- sqlite3 *db,
- const char *zFunc,
- int nArg,
- int enc,
- void *p,
- void (*xSFunc)(sqlite3_context*,int,sqlite3_value **),
- void (*xStep)(sqlite3_context*,int,sqlite3_value **),
+ void (*xSFunc)(sqlite3_context*,int,sqlite3_value**),
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*),
- void (*xDestroy)(void *)
+ void (*xValue)(sqlite3_context*),
+ void (*xInverse)(sqlite3_context*,int,sqlite3_value**),
+ void(*xDestroy)(void*)
){
int rc = SQLITE_ERROR;
FuncDestructor *pArg = 0;
@@ -148604,7 +153587,9 @@ SQLITE_API int sqlite3_create_function_v2(
pArg->xDestroy = xDestroy;
pArg->pUserData = p;
}
- rc = sqlite3CreateFunc(db, zFunc, nArg, enc, p, xSFunc, xStep, xFinal, pArg);
+ rc = sqlite3CreateFunc(db, zFunc, nArg, enc, p,
+ xSFunc, xStep, xFinal, xValue, xInverse, pArg
+ );
if( pArg && pArg->nRef==0 ){
assert( rc!=SQLITE_OK );
xDestroy(p);
@@ -148617,6 +153602,52 @@ SQLITE_API int sqlite3_create_function_v2(
return rc;
}
+/*
+** Create new user functions.
+*/
+SQLITE_API int sqlite3_create_function(
+ sqlite3 *db,
+ const char *zFunc,
+ int nArg,
+ int enc,
+ void *p,
+ void (*xSFunc)(sqlite3_context*,int,sqlite3_value **),
+ void (*xStep)(sqlite3_context*,int,sqlite3_value **),
+ void (*xFinal)(sqlite3_context*)
+){
+ return createFunctionApi(db, zFunc, nArg, enc, p, xSFunc, xStep,
+ xFinal, 0, 0, 0);
+}
+SQLITE_API int sqlite3_create_function_v2(
+ sqlite3 *db,
+ const char *zFunc,
+ int nArg,
+ int enc,
+ void *p,
+ void (*xSFunc)(sqlite3_context*,int,sqlite3_value **),
+ void (*xStep)(sqlite3_context*,int,sqlite3_value **),
+ void (*xFinal)(sqlite3_context*),
+ void (*xDestroy)(void *)
+){
+ return createFunctionApi(db, zFunc, nArg, enc, p, xSFunc, xStep,
+ xFinal, 0, 0, xDestroy);
+}
+SQLITE_API int sqlite3_create_window_function(
+ sqlite3 *db,
+ const char *zFunc,
+ int nArg,
+ int enc,
+ void *p,
+ void (*xStep)(sqlite3_context*,int,sqlite3_value **),
+ void (*xFinal)(sqlite3_context*),
+ void (*xValue)(sqlite3_context*),
+ void (*xInverse)(sqlite3_context*,int,sqlite3_value **),
+ void (*xDestroy)(void *)
+){
+ return createFunctionApi(db, zFunc, nArg, enc, p, 0, xStep,
+ xFinal, xValue, xInverse, xDestroy);
+}
+
#ifndef SQLITE_OMIT_UTF16
SQLITE_API int sqlite3_create_function16(
sqlite3 *db,
@@ -148637,7 +153668,7 @@ SQLITE_API int sqlite3_create_function16(
sqlite3_mutex_enter(db->mutex);
assert( !db->mallocFailed );
zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1, SQLITE_UTF16NATIVE);
- rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xSFunc,xStep,xFinal,0);
+ rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xSFunc,xStep,xFinal,0,0,0);
sqlite3DbFree(db, zFunc8);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
@@ -149262,7 +154293,7 @@ static int createCollation(
"unable to delete/modify collation sequence due to active statements");
return SQLITE_BUSY;
}
- sqlite3ExpirePreparedStatements(db);
+ sqlite3ExpirePreparedStatements(db, 0);
/* If collation sequence pColl was created directly by a call to
** sqlite3_create_collation, and not generated by synthCollSeq(),
@@ -149751,6 +154782,7 @@ static int openDatabase(
db->nDb = 2;
db->magic = SQLITE_MAGIC_BUSY;
db->aDb = db->aDbStatic;
+ db->lookaside.bDisable = 1;
assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
@@ -150451,6 +155483,9 @@ SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, vo
}else if( op==SQLITE_FCNTL_JOURNAL_POINTER ){
*(sqlite3_file**)pArg = sqlite3PagerJrnlFile(pPager);
rc = SQLITE_OK;
+ }else if( op==SQLITE_FCNTL_DATA_VERSION ){
+ *(unsigned int*)pArg = sqlite3PagerDataVersion(pPager);
+ rc = SQLITE_OK;
}else{
rc = sqlite3OsFileControl(fd, op, pArg);
}
@@ -150714,7 +155749,8 @@ SQLITE_API int sqlite3_test_control(int op, ...){
*/
case SQLITE_TESTCTRL_VDBE_COVERAGE: {
#ifdef SQLITE_VDBE_COVERAGE
- typedef void (*branch_callback)(void*,int,u8,u8);
+ typedef void (*branch_callback)(void*,unsigned int,
+ unsigned char,unsigned char);
sqlite3GlobalConfig.xVdbeBranch = va_arg(ap,branch_callback);
sqlite3GlobalConfig.pVdbeBranchArg = va_arg(ap,void*);
#endif
@@ -150901,7 +155937,7 @@ SQLITE_API int sqlite3_snapshot_get(
if( iDb==0 || iDb>1 ){
Btree *pBt = db->aDb[iDb].pBt;
if( 0==sqlite3BtreeIsInTrans(pBt) ){
- rc = sqlite3BtreeBeginTrans(pBt, 0);
+ rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot);
}
@@ -150936,11 +155972,29 @@ SQLITE_API int sqlite3_snapshot_open(
iDb = sqlite3FindDbName(db, zDb);
if( iDb==0 || iDb>1 ){
Btree *pBt = db->aDb[iDb].pBt;
- if( 0==sqlite3BtreeIsInReadTrans(pBt) ){
- rc = sqlite3PagerSnapshotOpen(sqlite3BtreePager(pBt), pSnapshot);
+ if( sqlite3BtreeIsInTrans(pBt)==0 ){
+ Pager *pPager = sqlite3BtreePager(pBt);
+ int bUnlock = 0;
+ if( sqlite3BtreeIsInReadTrans(pBt) ){
+ if( db->nVdbeActive==0 ){
+ rc = sqlite3PagerSnapshotCheck(pPager, pSnapshot);
+ if( rc==SQLITE_OK ){
+ bUnlock = 1;
+ rc = sqlite3BtreeCommit(pBt);
+ }
+ }
+ }else{
+ rc = SQLITE_OK;
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PagerSnapshotOpen(pPager, pSnapshot);
+ }
if( rc==SQLITE_OK ){
- rc = sqlite3BtreeBeginTrans(pBt, 0);
- sqlite3PagerSnapshotOpen(sqlite3BtreePager(pBt), 0);
+ rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
+ sqlite3PagerSnapshotOpen(pPager, 0);
+ }
+ if( bUnlock ){
+ sqlite3PagerSnapshotUnlock(pPager);
}
}
}
@@ -150971,7 +156025,7 @@ SQLITE_API int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb){
if( iDb==0 || iDb>1 ){
Btree *pBt = db->aDb[iDb].pBt;
if( 0==sqlite3BtreeIsInReadTrans(pBt) ){
- rc = sqlite3BtreeBeginTrans(pBt, 0);
+ rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3PagerSnapshotRecover(sqlite3BtreePager(pBt));
sqlite3BtreeCommit(pBt);
@@ -156094,7 +161148,7 @@ static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){
int rc = SQLITE_OK;
UNUSED_PARAMETER(iSavepoint);
assert( ((Fts3Table *)pVtab)->inTransaction );
- assert( ((Fts3Table *)pVtab)->mxSavepoint < iSavepoint );
+ assert( ((Fts3Table *)pVtab)->mxSavepoint <= iSavepoint );
TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint );
if( ((Fts3Table *)pVtab)->bIgnoreSavepoint==0 ){
rc = fts3SyncMethod(pVtab);
@@ -170517,6 +175571,2526 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
#endif /* !defined(SQLITE_DISABLE_FTS3_UNICODE) */
/************** End of fts3_unicode2.c ***************************************/
+/************** Begin file json1.c *******************************************/
+/*
+** 2015-08-12
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This SQLite extension implements JSON functions. The interface is
+** modeled after MySQL JSON functions:
+**
+** https://dev.mysql.com/doc/refman/5.7/en/json.html
+**
+** For the time being, all JSON is stored as pure text. (We might add
+** a JSONB type in the future which stores a binary encoding of JSON in
+** a BLOB, but there is no support for JSONB in the current implementation.
+** This implementation parses JSON text at 250 MB/s, so it is hard to see
+** how JSONB might improve on that.)
+*/
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1)
+#if !defined(SQLITEINT_H)
+/* #include "sqlite3ext.h" */
+#endif
+SQLITE_EXTENSION_INIT1
+/* #include <assert.h> */
+/* #include <string.h> */
+/* #include <stdlib.h> */
+/* #include <stdarg.h> */
+
+/* Mark a function parameter as unused, to suppress nuisance compiler
+** warnings. */
+#ifndef UNUSED_PARAM
+# define UNUSED_PARAM(X) (void)(X)
+#endif
+
+#ifndef LARGEST_INT64
+# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
+# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
+#endif
+
+/*
+** Versions of isspace(), isalnum() and isdigit() to which it is safe
+** to pass signed char values.
+*/
+#ifdef sqlite3Isdigit
+ /* Use the SQLite core versions if this routine is part of the
+ ** SQLite amalgamation */
+# define safe_isdigit(x) sqlite3Isdigit(x)
+# define safe_isalnum(x) sqlite3Isalnum(x)
+# define safe_isxdigit(x) sqlite3Isxdigit(x)
+#else
+ /* Use the standard library for separate compilation */
+#include <ctype.h> /* amalgamator: keep */
+# define safe_isdigit(x) isdigit((unsigned char)(x))
+# define safe_isalnum(x) isalnum((unsigned char)(x))
+# define safe_isxdigit(x) isxdigit((unsigned char)(x))
+#endif
+
+/*
+** Growing our own isspace() routine this way is twice as fast as
+** the library isspace() function, resulting in a 7% overall performance
+** increase for the parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os).
+*/
+static const char jsonIsSpace[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+#define safe_isspace(x) (jsonIsSpace[(unsigned char)x])
+
+#ifndef SQLITE_AMALGAMATION
+ /* Unsigned integer types. These are already defined in the sqliteInt.h,
+ ** but the definitions need to be repeated for separate compilation. */
+ typedef sqlite3_uint64 u64;
+ typedef unsigned int u32;
+ typedef unsigned short int u16;
+ typedef unsigned char u8;
+#endif
+
+/* Objects */
+typedef struct JsonString JsonString;
+typedef struct JsonNode JsonNode;
+typedef struct JsonParse JsonParse;
+
+/* An instance of this object represents a JSON string
+** under construction. Really, this is a generic string accumulator
+** that can be and is used to create strings other than JSON.
+*/
+struct JsonString {
+ sqlite3_context *pCtx; /* Function context - put error messages here */
+ char *zBuf; /* Append JSON content here */
+ u64 nAlloc; /* Bytes of storage available in zBuf[] */
+ u64 nUsed; /* Bytes of zBuf[] currently used */
+ u8 bStatic; /* True if zBuf is static space */
+ u8 bErr; /* True if an error has been encountered */
+ char zSpace[100]; /* Initial static space */
+};
+
+/* JSON type values
+*/
+#define JSON_NULL 0
+#define JSON_TRUE 1
+#define JSON_FALSE 2
+#define JSON_INT 3
+#define JSON_REAL 4
+#define JSON_STRING 5
+#define JSON_ARRAY 6
+#define JSON_OBJECT 7
+
+/* The "subtype" set for JSON values */
+#define JSON_SUBTYPE 74 /* Ascii for "J" */
+
+/*
+** Names of the various JSON types:
+*/
+static const char * const jsonType[] = {
+ "null", "true", "false", "integer", "real", "text", "array", "object"
+};
+
+/* Bit values for the JsonNode.jnFlag field
+*/
+#define JNODE_RAW 0x01 /* Content is raw, not JSON encoded */
+#define JNODE_ESCAPE 0x02 /* Content is text with \ escapes */
+#define JNODE_REMOVE 0x04 /* Do not output */
+#define JNODE_REPLACE 0x08 /* Replace with JsonNode.u.iReplace */
+#define JNODE_PATCH 0x10 /* Patch with JsonNode.u.pPatch */
+#define JNODE_APPEND 0x20 /* More ARRAY/OBJECT entries at u.iAppend */
+#define JNODE_LABEL 0x40 /* Is a label of an object */
+
+
+/* A single node of parsed JSON
+*/
+struct JsonNode {
+ u8 eType; /* One of the JSON_ type values */
+ u8 jnFlags; /* JNODE flags */
+ u32 n; /* Bytes of content, or number of sub-nodes */
+ union {
+ const char *zJContent; /* Content for INT, REAL, and STRING */
+ u32 iAppend; /* More terms for ARRAY and OBJECT */
+ u32 iKey; /* Key for ARRAY objects in json_tree() */
+ u32 iReplace; /* Replacement content for JNODE_REPLACE */
+ JsonNode *pPatch; /* Node chain of patch for JNODE_PATCH */
+ } u;
+};
+
+/* A completely parsed JSON string
+*/
+struct JsonParse {
+ u32 nNode; /* Number of slots of aNode[] used */
+ u32 nAlloc; /* Number of slots of aNode[] allocated */
+ JsonNode *aNode; /* Array of nodes containing the parse */
+ const char *zJson; /* Original JSON string */
+ u32 *aUp; /* Index of parent of each node */
+ u8 oom; /* Set to true if out of memory */
+ u8 nErr; /* Number of errors seen */
+ u16 iDepth; /* Nesting depth */
+ int nJson; /* Length of the zJson string in bytes */
+ u32 iHold; /* Replace cache line with the lowest iHold value */
+};
+
+/*
+** Maximum nesting depth of JSON for this implementation.
+**
+** This limit is needed to avoid a stack overflow in the recursive
+** descent parser. A depth of 2000 is far deeper than any sane JSON
+** should go.
+*/
+#define JSON_MAX_DEPTH 2000
+
+/**************************************************************************
+** Utility routines for dealing with JsonString objects
+**************************************************************************/
+
+/* Set the JsonString object to an empty string
+*/
+static void jsonZero(JsonString *p){
+ p->zBuf = p->zSpace;
+ p->nAlloc = sizeof(p->zSpace);
+ p->nUsed = 0;
+ p->bStatic = 1;
+}
+
+/* Initialize the JsonString object
+*/
+static void jsonInit(JsonString *p, sqlite3_context *pCtx){
+ p->pCtx = pCtx;
+ p->bErr = 0;
+ jsonZero(p);
+}
+
+
+/* Free all allocated memory and reset the JsonString object back to its
+** initial state.
+*/
+static void jsonReset(JsonString *p){
+ if( !p->bStatic ) sqlite3_free(p->zBuf);
+ jsonZero(p);
+}
+
+
+/* Report an out-of-memory (OOM) condition
+*/
+static void jsonOom(JsonString *p){
+ p->bErr = 1;
+ sqlite3_result_error_nomem(p->pCtx);
+ jsonReset(p);
+}
+
+/* Enlarge pJson->zBuf so that it can hold at least N more bytes.
+** Return zero on success. Return non-zero on an OOM error
+*/
+static int jsonGrow(JsonString *p, u32 N){
+ u64 nTotal = N<p->nAlloc ? p->nAlloc*2 : p->nAlloc+N+10;
+ char *zNew;
+ if( p->bStatic ){
+ if( p->bErr ) return 1;
+ zNew = sqlite3_malloc64(nTotal);
+ if( zNew==0 ){
+ jsonOom(p);
+ return SQLITE_NOMEM;
+ }
+ memcpy(zNew, p->zBuf, (size_t)p->nUsed);
+ p->zBuf = zNew;
+ p->bStatic = 0;
+ }else{
+ zNew = sqlite3_realloc64(p->zBuf, nTotal);
+ if( zNew==0 ){
+ jsonOom(p);
+ return SQLITE_NOMEM;
+ }
+ p->zBuf = zNew;
+ }
+ p->nAlloc = nTotal;
+ return SQLITE_OK;
+}
+
+/* Append N bytes from zIn onto the end of the JsonString string.
+*/
+static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){
+ if( (N+p->nUsed >= p->nAlloc) && jsonGrow(p,N)!=0 ) return;
+ memcpy(p->zBuf+p->nUsed, zIn, N);
+ p->nUsed += N;
+}
+
+/* Append formatted text (not to exceed N bytes) to the JsonString.
+*/
+static void jsonPrintf(int N, JsonString *p, const char *zFormat, ...){
+ va_list ap;
+ if( (p->nUsed + N >= p->nAlloc) && jsonGrow(p, N) ) return;
+ va_start(ap, zFormat);
+ sqlite3_vsnprintf(N, p->zBuf+p->nUsed, zFormat, ap);
+ va_end(ap);
+ p->nUsed += (int)strlen(p->zBuf+p->nUsed);
+}
+
+/* Append a single character
+*/
+static void jsonAppendChar(JsonString *p, char c){
+ if( p->nUsed>=p->nAlloc && jsonGrow(p,1)!=0 ) return;
+ p->zBuf[p->nUsed++] = c;
+}
+
+/* Append a comma separator to the output buffer, if the previous
+** character is not '[' or '{'.
+*/
+static void jsonAppendSeparator(JsonString *p){
+ char c;
+ if( p->nUsed==0 ) return;
+ c = p->zBuf[p->nUsed-1];
+ if( c!='[' && c!='{' ) jsonAppendChar(p, ',');
+}
+
+/* Append the N-byte string in zIn to the end of the JsonString string
+** under construction. Enclose the string in "..." and escape
+** any double-quotes or backslash characters contained within the
+** string.
+*/
+static void jsonAppendString(JsonString *p, const char *zIn, u32 N){
+ u32 i;
+ if( (N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0 ) return;
+ p->zBuf[p->nUsed++] = '"';
+ for(i=0; i<N; i++){
+ unsigned char c = ((unsigned const char*)zIn)[i];
+ if( c=='"' || c=='\\' ){
+ json_simple_escape:
+ if( (p->nUsed+N+3-i > p->nAlloc) && jsonGrow(p,N+3-i)!=0 ) return;
+ p->zBuf[p->nUsed++] = '\\';
+ }else if( c<=0x1f ){
+ static const char aSpecial[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ assert( sizeof(aSpecial)==32 );
+ assert( aSpecial['\b']=='b' );
+ assert( aSpecial['\f']=='f' );
+ assert( aSpecial['\n']=='n' );
+ assert( aSpecial['\r']=='r' );
+ assert( aSpecial['\t']=='t' );
+ if( aSpecial[c] ){
+ c = aSpecial[c];
+ goto json_simple_escape;
+ }
+ if( (p->nUsed+N+7+i > p->nAlloc) && jsonGrow(p,N+7-i)!=0 ) return;
+ p->zBuf[p->nUsed++] = '\\';
+ p->zBuf[p->nUsed++] = 'u';
+ p->zBuf[p->nUsed++] = '0';
+ p->zBuf[p->nUsed++] = '0';
+ p->zBuf[p->nUsed++] = '0' + (c>>4);
+ c = "0123456789abcdef"[c&0xf];
+ }
+ p->zBuf[p->nUsed++] = c;
+ }
+ p->zBuf[p->nUsed++] = '"';
+ assert( p->nUsed<p->nAlloc );
+}
+
+/*
+** Append a function parameter value to the JSON string under
+** construction.
+*/
+static void jsonAppendValue(
+ JsonString *p, /* Append to this JSON string */
+ sqlite3_value *pValue /* Value to append */
+){
+ switch( sqlite3_value_type(pValue) ){
+ case SQLITE_NULL: {
+ jsonAppendRaw(p, "null", 4);
+ break;
+ }
+ case SQLITE_INTEGER:
+ case SQLITE_FLOAT: {
+ const char *z = (const char*)sqlite3_value_text(pValue);
+ u32 n = (u32)sqlite3_value_bytes(pValue);
+ jsonAppendRaw(p, z, n);
+ break;
+ }
+ case SQLITE_TEXT: {
+ const char *z = (const char*)sqlite3_value_text(pValue);
+ u32 n = (u32)sqlite3_value_bytes(pValue);
+ if( sqlite3_value_subtype(pValue)==JSON_SUBTYPE ){
+ jsonAppendRaw(p, z, n);
+ }else{
+ jsonAppendString(p, z, n);
+ }
+ break;
+ }
+ default: {
+ if( p->bErr==0 ){
+ sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1);
+ p->bErr = 2;
+ jsonReset(p);
+ }
+ break;
+ }
+ }
+}
+
+
+/* Make the JSON in p the result of the SQL function.
+*/
+static void jsonResult(JsonString *p){
+ if( p->bErr==0 ){
+ sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed,
+ p->bStatic ? SQLITE_TRANSIENT : sqlite3_free,
+ SQLITE_UTF8);
+ jsonZero(p);
+ }
+ assert( p->bStatic );
+}
+
+/**************************************************************************
+** Utility routines for dealing with JsonNode and JsonParse objects
+**************************************************************************/
+
+/*
+** Return the number of consecutive JsonNode slots need to represent
+** the parsed JSON at pNode. The minimum answer is 1. For ARRAY and
+** OBJECT types, the number might be larger.
+**
+** Appended elements are not counted. The value returned is the number
+** by which the JsonNode counter should increment in order to go to the
+** next peer value.
+*/
+static u32 jsonNodeSize(JsonNode *pNode){
+ return pNode->eType>=JSON_ARRAY ? pNode->n+1 : 1;
+}
+
+/*
+** Reclaim all memory allocated by a JsonParse object. But do not
+** delete the JsonParse object itself.
+*/
+static void jsonParseReset(JsonParse *pParse){
+ sqlite3_free(pParse->aNode);
+ pParse->aNode = 0;
+ pParse->nNode = 0;
+ pParse->nAlloc = 0;
+ sqlite3_free(pParse->aUp);
+ pParse->aUp = 0;
+}
+
+/*
+** Free a JsonParse object that was obtained from sqlite3_malloc().
+*/
+static void jsonParseFree(JsonParse *pParse){
+ jsonParseReset(pParse);
+ sqlite3_free(pParse);
+}
+
+/*
+** Convert the JsonNode pNode into a pure JSON string and
+** append to pOut. Subsubstructure is also included. Return
+** the number of JsonNode objects that are encoded.
+*/
+static void jsonRenderNode(
+ JsonNode *pNode, /* The node to render */
+ JsonString *pOut, /* Write JSON here */
+ sqlite3_value **aReplace /* Replacement values */
+){
+ if( pNode->jnFlags & (JNODE_REPLACE|JNODE_PATCH) ){
+ if( pNode->jnFlags & JNODE_REPLACE ){
+ jsonAppendValue(pOut, aReplace[pNode->u.iReplace]);
+ return;
+ }
+ pNode = pNode->u.pPatch;
+ }
+ switch( pNode->eType ){
+ default: {
+ assert( pNode->eType==JSON_NULL );
+ jsonAppendRaw(pOut, "null", 4);
+ break;
+ }
+ case JSON_TRUE: {
+ jsonAppendRaw(pOut, "true", 4);
+ break;
+ }
+ case JSON_FALSE: {
+ jsonAppendRaw(pOut, "false", 5);
+ break;
+ }
+ case JSON_STRING: {
+ if( pNode->jnFlags & JNODE_RAW ){
+ jsonAppendString(pOut, pNode->u.zJContent, pNode->n);
+ break;
+ }
+ /* Fall through into the next case */
+ }
+ case JSON_REAL:
+ case JSON_INT: {
+ jsonAppendRaw(pOut, pNode->u.zJContent, pNode->n);
+ break;
+ }
+ case JSON_ARRAY: {
+ u32 j = 1;
+ jsonAppendChar(pOut, '[');
+ for(;;){
+ while( j<=pNode->n ){
+ if( (pNode[j].jnFlags & JNODE_REMOVE)==0 ){
+ jsonAppendSeparator(pOut);
+ jsonRenderNode(&pNode[j], pOut, aReplace);
+ }
+ j += jsonNodeSize(&pNode[j]);
+ }
+ if( (pNode->jnFlags & JNODE_APPEND)==0 ) break;
+ pNode = &pNode[pNode->u.iAppend];
+ j = 1;
+ }
+ jsonAppendChar(pOut, ']');
+ break;
+ }
+ case JSON_OBJECT: {
+ u32 j = 1;
+ jsonAppendChar(pOut, '{');
+ for(;;){
+ while( j<=pNode->n ){
+ if( (pNode[j+1].jnFlags & JNODE_REMOVE)==0 ){
+ jsonAppendSeparator(pOut);
+ jsonRenderNode(&pNode[j], pOut, aReplace);
+ jsonAppendChar(pOut, ':');
+ jsonRenderNode(&pNode[j+1], pOut, aReplace);
+ }
+ j += 1 + jsonNodeSize(&pNode[j+1]);
+ }
+ if( (pNode->jnFlags & JNODE_APPEND)==0 ) break;
+ pNode = &pNode[pNode->u.iAppend];
+ j = 1;
+ }
+ jsonAppendChar(pOut, '}');
+ break;
+ }
+ }
+}
+
+/*
+** Return a JsonNode and all its descendents as a JSON string.
+*/
+static void jsonReturnJson(
+ JsonNode *pNode, /* Node to return */
+ sqlite3_context *pCtx, /* Return value for this function */
+ sqlite3_value **aReplace /* Array of replacement values */
+){
+ JsonString s;
+ jsonInit(&s, pCtx);
+ jsonRenderNode(pNode, &s, aReplace);
+ jsonResult(&s);
+ sqlite3_result_subtype(pCtx, JSON_SUBTYPE);
+}
+
+/*
+** Make the JsonNode the return value of the function.
+*/
+static void jsonReturn(
+ JsonNode *pNode, /* Node to return */
+ sqlite3_context *pCtx, /* Return value for this function */
+ sqlite3_value **aReplace /* Array of replacement values */
+){
+ switch( pNode->eType ){
+ default: {
+ assert( pNode->eType==JSON_NULL );
+ sqlite3_result_null(pCtx);
+ break;
+ }
+ case JSON_TRUE: {
+ sqlite3_result_int(pCtx, 1);
+ break;
+ }
+ case JSON_FALSE: {
+ sqlite3_result_int(pCtx, 0);
+ break;
+ }
+ case JSON_INT: {
+ sqlite3_int64 i = 0;
+ const char *z = pNode->u.zJContent;
+ if( z[0]=='-' ){ z++; }
+ while( z[0]>='0' && z[0]<='9' ){
+ unsigned v = *(z++) - '0';
+ if( i>=LARGEST_INT64/10 ){
+ if( i>LARGEST_INT64/10 ) goto int_as_real;
+ if( z[0]>='0' && z[0]<='9' ) goto int_as_real;
+ if( v==9 ) goto int_as_real;
+ if( v==8 ){
+ if( pNode->u.zJContent[0]=='-' ){
+ sqlite3_result_int64(pCtx, SMALLEST_INT64);
+ goto int_done;
+ }else{
+ goto int_as_real;
+ }
+ }
+ }
+ i = i*10 + v;
+ }
+ if( pNode->u.zJContent[0]=='-' ){ i = -i; }
+ sqlite3_result_int64(pCtx, i);
+ int_done:
+ break;
+ int_as_real: /* fall through to real */;
+ }
+ case JSON_REAL: {
+ double r;
+#ifdef SQLITE_AMALGAMATION
+ const char *z = pNode->u.zJContent;
+ sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8);
+#else
+ r = strtod(pNode->u.zJContent, 0);
+#endif
+ sqlite3_result_double(pCtx, r);
+ break;
+ }
+ case JSON_STRING: {
+#if 0 /* Never happens because JNODE_RAW is only set by json_set(),
+ ** json_insert() and json_replace() and those routines do not
+ ** call jsonReturn() */
+ if( pNode->jnFlags & JNODE_RAW ){
+ sqlite3_result_text(pCtx, pNode->u.zJContent, pNode->n,
+ SQLITE_TRANSIENT);
+ }else
+#endif
+ assert( (pNode->jnFlags & JNODE_RAW)==0 );
+ if( (pNode->jnFlags & JNODE_ESCAPE)==0 ){
+ /* JSON formatted without any backslash-escapes */
+ sqlite3_result_text(pCtx, pNode->u.zJContent+1, pNode->n-2,
+ SQLITE_TRANSIENT);
+ }else{
+ /* Translate JSON formatted string into raw text */
+ u32 i;
+ u32 n = pNode->n;
+ const char *z = pNode->u.zJContent;
+ char *zOut;
+ u32 j;
+ zOut = sqlite3_malloc( n+1 );
+ if( zOut==0 ){
+ sqlite3_result_error_nomem(pCtx);
+ break;
+ }
+ for(i=1, j=0; i<n-1; i++){
+ char c = z[i];
+ if( c!='\\' ){
+ zOut[j++] = c;
+ }else{
+ c = z[++i];
+ if( c=='u' ){
+ u32 v = 0, k;
+ for(k=0; k<4; i++, k++){
+ assert( i<n-2 );
+ c = z[i+1];
+ assert( safe_isxdigit(c) );
+ if( c<='9' ) v = v*16 + c - '0';
+ else if( c<='F' ) v = v*16 + c - 'A' + 10;
+ else v = v*16 + c - 'a' + 10;
+ }
+ if( v==0 ) break;
+ if( v<=0x7f ){
+ zOut[j++] = (char)v;
+ }else if( v<=0x7ff ){
+ zOut[j++] = (char)(0xc0 | (v>>6));
+ zOut[j++] = 0x80 | (v&0x3f);
+ }else{
+ zOut[j++] = (char)(0xe0 | (v>>12));
+ zOut[j++] = 0x80 | ((v>>6)&0x3f);
+ zOut[j++] = 0x80 | (v&0x3f);
+ }
+ }else{
+ if( c=='b' ){
+ c = '\b';
+ }else if( c=='f' ){
+ c = '\f';
+ }else if( c=='n' ){
+ c = '\n';
+ }else if( c=='r' ){
+ c = '\r';
+ }else if( c=='t' ){
+ c = '\t';
+ }
+ zOut[j++] = c;
+ }
+ }
+ }
+ zOut[j] = 0;
+ sqlite3_result_text(pCtx, zOut, j, sqlite3_free);
+ }
+ break;
+ }
+ case JSON_ARRAY:
+ case JSON_OBJECT: {
+ jsonReturnJson(pNode, pCtx, aReplace);
+ break;
+ }
+ }
+}
+
+/* Forward reference */
+static int jsonParseAddNode(JsonParse*,u32,u32,const char*);
+
+/*
+** A macro to hint to the compiler that a function should not be
+** inlined.
+*/
+#if defined(__GNUC__)
+# define JSON_NOINLINE __attribute__((noinline))
+#elif defined(_MSC_VER) && _MSC_VER>=1310
+# define JSON_NOINLINE __declspec(noinline)
+#else
+# define JSON_NOINLINE
+#endif
+
+
+static JSON_NOINLINE int jsonParseAddNodeExpand(
+ JsonParse *pParse, /* Append the node to this object */
+ u32 eType, /* Node type */
+ u32 n, /* Content size or sub-node count */
+ const char *zContent /* Content */
+){
+ u32 nNew;
+ JsonNode *pNew;
+ assert( pParse->nNode>=pParse->nAlloc );
+ if( pParse->oom ) return -1;
+ nNew = pParse->nAlloc*2 + 10;
+ pNew = sqlite3_realloc(pParse->aNode, sizeof(JsonNode)*nNew);
+ if( pNew==0 ){
+ pParse->oom = 1;
+ return -1;
+ }
+ pParse->nAlloc = nNew;
+ pParse->aNode = pNew;
+ assert( pParse->nNode<pParse->nAlloc );
+ return jsonParseAddNode(pParse, eType, n, zContent);
+}
+
+/*
+** Create a new JsonNode instance based on the arguments and append that
+** instance to the JsonParse. Return the index in pParse->aNode[] of the
+** new node, or -1 if a memory allocation fails.
+*/
+static int jsonParseAddNode(
+ JsonParse *pParse, /* Append the node to this object */
+ u32 eType, /* Node type */
+ u32 n, /* Content size or sub-node count */
+ const char *zContent /* Content */
+){
+ JsonNode *p;
+ if( pParse->nNode>=pParse->nAlloc ){
+ return jsonParseAddNodeExpand(pParse, eType, n, zContent);
+ }
+ p = &pParse->aNode[pParse->nNode];
+ p->eType = (u8)eType;
+ p->jnFlags = 0;
+ p->n = n;
+ p->u.zJContent = zContent;
+ return pParse->nNode++;
+}
+
+/*
+** Return true if z[] begins with 4 (or more) hexadecimal digits
+*/
+static int jsonIs4Hex(const char *z){
+ int i;
+ for(i=0; i<4; i++) if( !safe_isxdigit(z[i]) ) return 0;
+ return 1;
+}
+
+/*
+** Parse a single JSON value which begins at pParse->zJson[i]. Return the
+** index of the first character past the end of the value parsed.
+**
+** Return negative for a syntax error. Special cases: return -2 if the
+** first non-whitespace character is '}' and return -3 if the first
+** non-whitespace character is ']'.
+*/
+static int jsonParseValue(JsonParse *pParse, u32 i){
+ char c;
+ u32 j;
+ int iThis;
+ int x;
+ JsonNode *pNode;
+ const char *z = pParse->zJson;
+ while( safe_isspace(z[i]) ){ i++; }
+ if( (c = z[i])=='{' ){
+ /* Parse object */
+ iThis = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0);
+ if( iThis<0 ) return -1;
+ for(j=i+1;;j++){
+ while( safe_isspace(z[j]) ){ j++; }
+ if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1;
+ x = jsonParseValue(pParse, j);
+ if( x<0 ){
+ pParse->iDepth--;
+ if( x==(-2) && pParse->nNode==(u32)iThis+1 ) return j+1;
+ return -1;
+ }
+ if( pParse->oom ) return -1;
+ pNode = &pParse->aNode[pParse->nNode-1];
+ if( pNode->eType!=JSON_STRING ) return -1;
+ pNode->jnFlags |= JNODE_LABEL;
+ j = x;
+ while( safe_isspace(z[j]) ){ j++; }
+ if( z[j]!=':' ) return -1;
+ j++;
+ x = jsonParseValue(pParse, j);
+ pParse->iDepth--;
+ if( x<0 ) return -1;
+ j = x;
+ while( safe_isspace(z[j]) ){ j++; }
+ c = z[j];
+ if( c==',' ) continue;
+ if( c!='}' ) return -1;
+ break;
+ }
+ pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1;
+ return j+1;
+ }else if( c=='[' ){
+ /* Parse array */
+ iThis = jsonParseAddNode(pParse, JSON_ARRAY, 0, 0);
+ if( iThis<0 ) return -1;
+ for(j=i+1;;j++){
+ while( safe_isspace(z[j]) ){ j++; }
+ if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1;
+ x = jsonParseValue(pParse, j);
+ pParse->iDepth--;
+ if( x<0 ){
+ if( x==(-3) && pParse->nNode==(u32)iThis+1 ) return j+1;
+ return -1;
+ }
+ j = x;
+ while( safe_isspace(z[j]) ){ j++; }
+ c = z[j];
+ if( c==',' ) continue;
+ if( c!=']' ) return -1;
+ break;
+ }
+ pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1;
+ return j+1;
+ }else if( c=='"' ){
+ /* Parse string */
+ u8 jnFlags = 0;
+ j = i+1;
+ for(;;){
+ c = z[j];
+ if( (c & ~0x1f)==0 ){
+ /* Control characters are not allowed in strings */
+ return -1;
+ }
+ if( c=='\\' ){
+ c = z[++j];
+ if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f'
+ || c=='n' || c=='r' || c=='t'
+ || (c=='u' && jsonIs4Hex(z+j+1)) ){
+ jnFlags = JNODE_ESCAPE;
+ }else{
+ return -1;
+ }
+ }else if( c=='"' ){
+ break;
+ }
+ j++;
+ }
+ jsonParseAddNode(pParse, JSON_STRING, j+1-i, &z[i]);
+ if( !pParse->oom ) pParse->aNode[pParse->nNode-1].jnFlags = jnFlags;
+ return j+1;
+ }else if( c=='n'
+ && strncmp(z+i,"null",4)==0
+ && !safe_isalnum(z[i+4]) ){
+ jsonParseAddNode(pParse, JSON_NULL, 0, 0);
+ return i+4;
+ }else if( c=='t'
+ && strncmp(z+i,"true",4)==0
+ && !safe_isalnum(z[i+4]) ){
+ jsonParseAddNode(pParse, JSON_TRUE, 0, 0);
+ return i+4;
+ }else if( c=='f'
+ && strncmp(z+i,"false",5)==0
+ && !safe_isalnum(z[i+5]) ){
+ jsonParseAddNode(pParse, JSON_FALSE, 0, 0);
+ return i+5;
+ }else if( c=='-' || (c>='0' && c<='9') ){
+ /* Parse number */
+ u8 seenDP = 0;
+ u8 seenE = 0;
+ assert( '-' < '0' );
+ if( c<='0' ){
+ j = c=='-' ? i+1 : i;
+ if( z[j]=='0' && z[j+1]>='0' && z[j+1]<='9' ) return -1;
+ }
+ j = i+1;
+ for(;; j++){
+ c = z[j];
+ if( c>='0' && c<='9' ) continue;
+ if( c=='.' ){
+ if( z[j-1]=='-' ) return -1;
+ if( seenDP ) return -1;
+ seenDP = 1;
+ continue;
+ }
+ if( c=='e' || c=='E' ){
+ if( z[j-1]<'0' ) return -1;
+ if( seenE ) return -1;
+ seenDP = seenE = 1;
+ c = z[j+1];
+ if( c=='+' || c=='-' ){
+ j++;
+ c = z[j+1];
+ }
+ if( c<'0' || c>'9' ) return -1;
+ continue;
+ }
+ break;
+ }
+ if( z[j-1]<'0' ) return -1;
+ jsonParseAddNode(pParse, seenDP ? JSON_REAL : JSON_INT,
+ j - i, &z[i]);
+ return j;
+ }else if( c=='}' ){
+ return -2; /* End of {...} */
+ }else if( c==']' ){
+ return -3; /* End of [...] */
+ }else if( c==0 ){
+ return 0; /* End of file */
+ }else{
+ return -1; /* Syntax error */
+ }
+}
+
+/*
+** Parse a complete JSON string. Return 0 on success or non-zero if there
+** are any errors. If an error occurs, free all memory associated with
+** pParse.
+**
+** pParse is uninitialized when this routine is called.
+*/
+static int jsonParse(
+ JsonParse *pParse, /* Initialize and fill this JsonParse object */
+ sqlite3_context *pCtx, /* Report errors here */
+ const char *zJson /* Input JSON text to be parsed */
+){
+ int i;
+ memset(pParse, 0, sizeof(*pParse));
+ if( zJson==0 ) return 1;
+ pParse->zJson = zJson;
+ i = jsonParseValue(pParse, 0);
+ if( pParse->oom ) i = -1;
+ if( i>0 ){
+ assert( pParse->iDepth==0 );
+ while( safe_isspace(zJson[i]) ) i++;
+ if( zJson[i] ) i = -1;
+ }
+ if( i<=0 ){
+ if( pCtx!=0 ){
+ if( pParse->oom ){
+ sqlite3_result_error_nomem(pCtx);
+ }else{
+ sqlite3_result_error(pCtx, "malformed JSON", -1);
+ }
+ }
+ jsonParseReset(pParse);
+ return 1;
+ }
+ return 0;
+}
+
+/* Mark node i of pParse as being a child of iParent. Call recursively
+** to fill in all the descendants of node i.
+*/
+static void jsonParseFillInParentage(JsonParse *pParse, u32 i, u32 iParent){
+ JsonNode *pNode = &pParse->aNode[i];
+ u32 j;
+ pParse->aUp[i] = iParent;
+ switch( pNode->eType ){
+ case JSON_ARRAY: {
+ for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j)){
+ jsonParseFillInParentage(pParse, i+j, i);
+ }
+ break;
+ }
+ case JSON_OBJECT: {
+ for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j+1)+1){
+ pParse->aUp[i+j] = i;
+ jsonParseFillInParentage(pParse, i+j+1, i);
+ }
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+}
+
+/*
+** Compute the parentage of all nodes in a completed parse.
+*/
+static int jsonParseFindParents(JsonParse *pParse){
+ u32 *aUp;
+ assert( pParse->aUp==0 );
+ aUp = pParse->aUp = sqlite3_malloc( sizeof(u32)*pParse->nNode );
+ if( aUp==0 ){
+ pParse->oom = 1;
+ return SQLITE_NOMEM;
+ }
+ jsonParseFillInParentage(pParse, 0, 0);
+ return SQLITE_OK;
+}
+
+/*
+** Magic number used for the JSON parse cache in sqlite3_get_auxdata()
+*/
+#define JSON_CACHE_ID (-429938) /* First cache entry */
+#define JSON_CACHE_SZ 4 /* Max number of cache entries */
+
+/*
+** Obtain a complete parse of the JSON found in the first argument
+** of the argv array. Use the sqlite3_get_auxdata() cache for this
+** parse if it is available. If the cache is not available or if it
+** is no longer valid, parse the JSON again and return the new parse,
+** and also register the new parse so that it will be available for
+** future sqlite3_get_auxdata() calls.
+*/
+static JsonParse *jsonParseCached(
+ sqlite3_context *pCtx,
+ sqlite3_value **argv,
+ sqlite3_context *pErrCtx
+){
+ const char *zJson = (const char*)sqlite3_value_text(argv[0]);
+ int nJson = sqlite3_value_bytes(argv[0]);
+ JsonParse *p;
+ JsonParse *pMatch = 0;
+ int iKey;
+ int iMinKey = 0;
+ u32 iMinHold = 0xffffffff;
+ u32 iMaxHold = 0;
+ if( zJson==0 ) return 0;
+ for(iKey=0; iKey<JSON_CACHE_SZ; iKey++){
+ p = (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID+iKey);
+ if( p==0 ){
+ iMinKey = iKey;
+ break;
+ }
+ if( pMatch==0
+ && p->nJson==nJson
+ && memcmp(p->zJson,zJson,nJson)==0
+ ){
+ p->nErr = 0;
+ pMatch = p;
+ }else if( p->iHold<iMinHold ){
+ iMinHold = p->iHold;
+ iMinKey = iKey;
+ }
+ if( p->iHold>iMaxHold ){
+ iMaxHold = p->iHold;
+ }
+ }
+ if( pMatch ){
+ pMatch->nErr = 0;
+ pMatch->iHold = iMaxHold+1;
+ return pMatch;
+ }
+ p = sqlite3_malloc( sizeof(*p) + nJson + 1 );
+ if( p==0 ){
+ sqlite3_result_error_nomem(pCtx);
+ return 0;
+ }
+ memset(p, 0, sizeof(*p));
+ p->zJson = (char*)&p[1];
+ memcpy((char*)p->zJson, zJson, nJson+1);
+ if( jsonParse(p, pErrCtx, p->zJson) ){
+ sqlite3_free(p);
+ return 0;
+ }
+ p->nJson = nJson;
+ p->iHold = iMaxHold+1;
+ sqlite3_set_auxdata(pCtx, JSON_CACHE_ID+iMinKey, p,
+ (void(*)(void*))jsonParseFree);
+ return (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID+iMinKey);
+}
+
+/*
+** Compare the OBJECT label at pNode against zKey,nKey. Return true on
+** a match.
+*/
+static int jsonLabelCompare(JsonNode *pNode, const char *zKey, u32 nKey){
+ if( pNode->jnFlags & JNODE_RAW ){
+ if( pNode->n!=nKey ) return 0;
+ return strncmp(pNode->u.zJContent, zKey, nKey)==0;
+ }else{
+ if( pNode->n!=nKey+2 ) return 0;
+ return strncmp(pNode->u.zJContent+1, zKey, nKey)==0;
+ }
+}
+
+/* forward declaration */
+static JsonNode *jsonLookupAppend(JsonParse*,const char*,int*,const char**);
+
+/*
+** Search along zPath to find the node specified. Return a pointer
+** to that node, or NULL if zPath is malformed or if there is no such
+** node.
+**
+** If pApnd!=0, then try to append new nodes to complete zPath if it is
+** possible to do so and if no existing node corresponds to zPath. If
+** new nodes are appended *pApnd is set to 1.
+*/
+static JsonNode *jsonLookupStep(
+ JsonParse *pParse, /* The JSON to search */
+ u32 iRoot, /* Begin the search at this node */
+ const char *zPath, /* The path to search */
+ int *pApnd, /* Append nodes to complete path if not NULL */
+ const char **pzErr /* Make *pzErr point to any syntax error in zPath */
+){
+ u32 i, j, nKey;
+ const char *zKey;
+ JsonNode *pRoot = &pParse->aNode[iRoot];
+ if( zPath[0]==0 ) return pRoot;
+ if( zPath[0]=='.' ){
+ if( pRoot->eType!=JSON_OBJECT ) return 0;
+ zPath++;
+ if( zPath[0]=='"' ){
+ zKey = zPath + 1;
+ for(i=1; zPath[i] && zPath[i]!='"'; i++){}
+ nKey = i-1;
+ if( zPath[i] ){
+ i++;
+ }else{
+ *pzErr = zPath;
+ return 0;
+ }
+ }else{
+ zKey = zPath;
+ for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){}
+ nKey = i;
+ }
+ if( nKey==0 ){
+ *pzErr = zPath;
+ return 0;
+ }
+ j = 1;
+ for(;;){
+ while( j<=pRoot->n ){
+ if( jsonLabelCompare(pRoot+j, zKey, nKey) ){
+ return jsonLookupStep(pParse, iRoot+j+1, &zPath[i], pApnd, pzErr);
+ }
+ j++;
+ j += jsonNodeSize(&pRoot[j]);
+ }
+ if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break;
+ iRoot += pRoot->u.iAppend;
+ pRoot = &pParse->aNode[iRoot];
+ j = 1;
+ }
+ if( pApnd ){
+ u32 iStart, iLabel;
+ JsonNode *pNode;
+ iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0);
+ iLabel = jsonParseAddNode(pParse, JSON_STRING, i, zPath);
+ zPath += i;
+ pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr);
+ if( pParse->oom ) return 0;
+ if( pNode ){
+ pRoot = &pParse->aNode[iRoot];
+ pRoot->u.iAppend = iStart - iRoot;
+ pRoot->jnFlags |= JNODE_APPEND;
+ pParse->aNode[iLabel].jnFlags |= JNODE_RAW;
+ }
+ return pNode;
+ }
+ }else if( zPath[0]=='[' && safe_isdigit(zPath[1]) ){
+ if( pRoot->eType!=JSON_ARRAY ) return 0;
+ i = 0;
+ j = 1;
+ while( safe_isdigit(zPath[j]) ){
+ i = i*10 + zPath[j] - '0';
+ j++;
+ }
+ if( zPath[j]!=']' ){
+ *pzErr = zPath;
+ return 0;
+ }
+ zPath += j + 1;
+ j = 1;
+ for(;;){
+ while( j<=pRoot->n && (i>0 || (pRoot[j].jnFlags & JNODE_REMOVE)!=0) ){
+ if( (pRoot[j].jnFlags & JNODE_REMOVE)==0 ) i--;
+ j += jsonNodeSize(&pRoot[j]);
+ }
+ if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break;
+ iRoot += pRoot->u.iAppend;
+ pRoot = &pParse->aNode[iRoot];
+ j = 1;
+ }
+ if( j<=pRoot->n ){
+ return jsonLookupStep(pParse, iRoot+j, zPath, pApnd, pzErr);
+ }
+ if( i==0 && pApnd ){
+ u32 iStart;
+ JsonNode *pNode;
+ iStart = jsonParseAddNode(pParse, JSON_ARRAY, 1, 0);
+ pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr);
+ if( pParse->oom ) return 0;
+ if( pNode ){
+ pRoot = &pParse->aNode[iRoot];
+ pRoot->u.iAppend = iStart - iRoot;
+ pRoot->jnFlags |= JNODE_APPEND;
+ }
+ return pNode;
+ }
+ }else{
+ *pzErr = zPath;
+ }
+ return 0;
+}
+
+/*
+** Append content to pParse that will complete zPath. Return a pointer
+** to the inserted node, or return NULL if the append fails.
+*/
+static JsonNode *jsonLookupAppend(
+ JsonParse *pParse, /* Append content to the JSON parse */
+ const char *zPath, /* Description of content to append */
+ int *pApnd, /* Set this flag to 1 */
+ const char **pzErr /* Make this point to any syntax error */
+){
+ *pApnd = 1;
+ if( zPath[0]==0 ){
+ jsonParseAddNode(pParse, JSON_NULL, 0, 0);
+ return pParse->oom ? 0 : &pParse->aNode[pParse->nNode-1];
+ }
+ if( zPath[0]=='.' ){
+ jsonParseAddNode(pParse, JSON_OBJECT, 0, 0);
+ }else if( strncmp(zPath,"[0]",3)==0 ){
+ jsonParseAddNode(pParse, JSON_ARRAY, 0, 0);
+ }else{
+ return 0;
+ }
+ if( pParse->oom ) return 0;
+ return jsonLookupStep(pParse, pParse->nNode-1, zPath, pApnd, pzErr);
+}
+
+/*
+** Return the text of a syntax error message on a JSON path. Space is
+** obtained from sqlite3_malloc().
+*/
+static char *jsonPathSyntaxError(const char *zErr){
+ return sqlite3_mprintf("JSON path error near '%q'", zErr);
+}
+
+/*
+** Do a node lookup using zPath. Return a pointer to the node on success.
+** Return NULL if not found or if there is an error.
+**
+** On an error, write an error message into pCtx and increment the
+** pParse->nErr counter.
+**
+** If pApnd!=NULL then try to append missing nodes and set *pApnd = 1 if
+** nodes are appended.
+*/
+static JsonNode *jsonLookup(
+ JsonParse *pParse, /* The JSON to search */
+ const char *zPath, /* The path to search */
+ int *pApnd, /* Append nodes to complete path if not NULL */
+ sqlite3_context *pCtx /* Report errors here, if not NULL */
+){
+ const char *zErr = 0;
+ JsonNode *pNode = 0;
+ char *zMsg;
+
+ if( zPath==0 ) return 0;
+ if( zPath[0]!='$' ){
+ zErr = zPath;
+ goto lookup_err;
+ }
+ zPath++;
+ pNode = jsonLookupStep(pParse, 0, zPath, pApnd, &zErr);
+ if( zErr==0 ) return pNode;
+
+lookup_err:
+ pParse->nErr++;
+ assert( zErr!=0 && pCtx!=0 );
+ zMsg = jsonPathSyntaxError(zErr);
+ if( zMsg ){
+ sqlite3_result_error(pCtx, zMsg, -1);
+ sqlite3_free(zMsg);
+ }else{
+ sqlite3_result_error_nomem(pCtx);
+ }
+ return 0;
+}
+
+
+/*
+** Report the wrong number of arguments for json_insert(), json_replace()
+** or json_set().
+*/
+static void jsonWrongNumArgs(
+ sqlite3_context *pCtx,
+ const char *zFuncName
+){
+ char *zMsg = sqlite3_mprintf("json_%s() needs an odd number of arguments",
+ zFuncName);
+ sqlite3_result_error(pCtx, zMsg, -1);
+ sqlite3_free(zMsg);
+}
+
+/*
+** Mark all NULL entries in the Object passed in as JNODE_REMOVE.
+*/
+static void jsonRemoveAllNulls(JsonNode *pNode){
+ int i, n;
+ assert( pNode->eType==JSON_OBJECT );
+ n = pNode->n;
+ for(i=2; i<=n; i += jsonNodeSize(&pNode[i])+1){
+ switch( pNode[i].eType ){
+ case JSON_NULL:
+ pNode[i].jnFlags |= JNODE_REMOVE;
+ break;
+ case JSON_OBJECT:
+ jsonRemoveAllNulls(&pNode[i]);
+ break;
+ }
+ }
+}
+
+
+/****************************************************************************
+** SQL functions used for testing and debugging
+****************************************************************************/
+
+#ifdef SQLITE_DEBUG
+/*
+** The json_parse(JSON) function returns a string which describes
+** a parse of the JSON provided. Or it returns NULL if JSON is not
+** well-formed.
+*/
+static void jsonParseFunc(
+ sqlite3_context *ctx,
+ int argc,
+ sqlite3_value **argv
+){
+ JsonString s; /* Output string - not real JSON */
+ JsonParse x; /* The parse */
+ u32 i;
+
+ assert( argc==1 );
+ if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
+ jsonParseFindParents(&x);
+ jsonInit(&s, ctx);
+ for(i=0; i<x.nNode; i++){
+ const char *zType;
+ if( x.aNode[i].jnFlags & JNODE_LABEL ){
+ assert( x.aNode[i].eType==JSON_STRING );
+ zType = "label";
+ }else{
+ zType = jsonType[x.aNode[i].eType];
+ }
+ jsonPrintf(100, &s,"node %3u: %7s n=%-4d up=%-4d",
+ i, zType, x.aNode[i].n, x.aUp[i]);
+ if( x.aNode[i].u.zJContent!=0 ){
+ jsonAppendRaw(&s, " ", 1);
+ jsonAppendRaw(&s, x.aNode[i].u.zJContent, x.aNode[i].n);
+ }
+ jsonAppendRaw(&s, "\n", 1);
+ }
+ jsonParseReset(&x);
+ jsonResult(&s);
+}
+
+/*
+** The json_test1(JSON) function return true (1) if the input is JSON
+** text generated by another json function. It returns (0) if the input
+** is not known to be JSON.
+*/
+static void jsonTest1Func(
+ sqlite3_context *ctx,
+ int argc,
+ sqlite3_value **argv
+){
+ UNUSED_PARAM(argc);
+ sqlite3_result_int(ctx, sqlite3_value_subtype(argv[0])==JSON_SUBTYPE);
+}
+#endif /* SQLITE_DEBUG */
+
+/****************************************************************************
+** Scalar SQL function implementations
+****************************************************************************/
+
+/*
+** Implementation of the json_QUOTE(VALUE) function. Return a JSON value
+** corresponding to the SQL value input. Mostly this means putting
+** double-quotes around strings and returning the unquoted string "null"
+** when given a NULL input.
+*/
+static void jsonQuoteFunc(
+ sqlite3_context *ctx,
+ int argc,
+ sqlite3_value **argv
+){
+ JsonString jx;
+ UNUSED_PARAM(argc);
+
+ jsonInit(&jx, ctx);
+ jsonAppendValue(&jx, argv[0]);
+ jsonResult(&jx);
+ sqlite3_result_subtype(ctx, JSON_SUBTYPE);
+}
+
+/*
+** Implementation of the json_array(VALUE,...) function. Return a JSON
+** array that contains all values given in arguments. Or if any argument
+** is a BLOB, throw an error.
+*/
+static void jsonArrayFunc(
+ sqlite3_context *ctx,
+ int argc,
+ sqlite3_value **argv
+){
+ int i;
+ JsonString jx;
+
+ jsonInit(&jx, ctx);
+ jsonAppendChar(&jx, '[');
+ for(i=0; i<argc; i++){
+ jsonAppendSeparator(&jx);
+ jsonAppendValue(&jx, argv[i]);
+ }
+ jsonAppendChar(&jx, ']');
+ jsonResult(&jx);
+ sqlite3_result_subtype(ctx, JSON_SUBTYPE);
+}
+
+
+/*
+** json_array_length(JSON)
+** json_array_length(JSON, PATH)
+**
+** Return the number of elements in the top-level JSON array.
+** Return 0 if the input is not a well-formed JSON array.
+*/
+static void jsonArrayLengthFunc(
+ sqlite3_context *ctx,
+ int argc,
+ sqlite3_value **argv
+){
+ JsonParse *p; /* The parse */
+ sqlite3_int64 n = 0;
+ u32 i;
+ JsonNode *pNode;
+
+ p = jsonParseCached(ctx, argv, ctx);
+ if( p==0 ) return;
+ assert( p->nNode );
+ if( argc==2 ){
+ const char *zPath = (const char*)sqlite3_value_text(argv[1]);
+ pNode = jsonLookup(p, zPath, 0, ctx);
+ }else{
+ pNode = p->aNode;
+ }
+ if( pNode==0 ){
+ return;
+ }
+ if( pNode->eType==JSON_ARRAY ){
+ assert( (pNode->jnFlags & JNODE_APPEND)==0 );
+ for(i=1; i<=pNode->n; n++){
+ i += jsonNodeSize(&pNode[i]);
+ }
+ }
+ sqlite3_result_int64(ctx, n);
+}
+
+/*
+** json_extract(JSON, PATH, ...)
+**
+** Return the element described by PATH. Return NULL if there is no
+** PATH element. If there are multiple PATHs, then return a JSON array
+** with the result from each path. Throw an error if the JSON or any PATH
+** is malformed.
+*/
+static void jsonExtractFunc(
+ sqlite3_context *ctx,
+ int argc,
+ sqlite3_value **argv
+){
+ JsonParse *p; /* The parse */
+ JsonNode *pNode;
+ const char *zPath;
+ JsonString jx;
+ int i;
+
+ if( argc<2 ) return;
+ p = jsonParseCached(ctx, argv, ctx);
+ if( p==0 ) return;
+ jsonInit(&jx, ctx);
+ jsonAppendChar(&jx, '[');
+ for(i=1; i<argc; i++){
+ zPath = (const char*)sqlite3_value_text(argv[i]);
+ pNode = jsonLookup(p, zPath, 0, ctx);
+ if( p->nErr ) break;
+ if( argc>2 ){
+ jsonAppendSeparator(&jx);
+ if( pNode ){
+ jsonRenderNode(pNode, &jx, 0);
+ }else{
+ jsonAppendRaw(&jx, "null", 4);
+ }
+ }else if( pNode ){
+ jsonReturn(pNode, ctx, 0);
+ }
+ }
+ if( argc>2 && i==argc ){
+ jsonAppendChar(&jx, ']');
+ jsonResult(&jx);
+ sqlite3_result_subtype(ctx, JSON_SUBTYPE);
+ }
+ jsonReset(&jx);
+}
+
+/* This is the RFC 7396 MergePatch algorithm.
+*/
+static JsonNode *jsonMergePatch(
+ JsonParse *pParse, /* The JSON parser that contains the TARGET */
+ u32 iTarget, /* Node of the TARGET in pParse */
+ JsonNode *pPatch /* The PATCH */
+){
+ u32 i, j;
+ u32 iRoot;
+ JsonNode *pTarget;
+ if( pPatch->eType!=JSON_OBJECT ){
+ return pPatch;
+ }
+ assert( iTarget>=0 && iTarget<pParse->nNode );
+ pTarget = &pParse->aNode[iTarget];
+ assert( (pPatch->jnFlags & JNODE_APPEND)==0 );
+ if( pTarget->eType!=JSON_OBJECT ){
+ jsonRemoveAllNulls(pPatch);
+ return pPatch;
+ }
+ iRoot = iTarget;
+ for(i=1; i<pPatch->n; i += jsonNodeSize(&pPatch[i+1])+1){
+ u32 nKey;
+ const char *zKey;
+ assert( pPatch[i].eType==JSON_STRING );
+ assert( pPatch[i].jnFlags & JNODE_LABEL );
+ nKey = pPatch[i].n;
+ zKey = pPatch[i].u.zJContent;
+ assert( (pPatch[i].jnFlags & JNODE_RAW)==0 );
+ for(j=1; j<pTarget->n; j += jsonNodeSize(&pTarget[j+1])+1 ){
+ assert( pTarget[j].eType==JSON_STRING );
+ assert( pTarget[j].jnFlags & JNODE_LABEL );
+ assert( (pPatch[i].jnFlags & JNODE_RAW)==0 );
+ if( pTarget[j].n==nKey && strncmp(pTarget[j].u.zJContent,zKey,nKey)==0 ){
+ if( pTarget[j+1].jnFlags & (JNODE_REMOVE|JNODE_PATCH) ) break;
+ if( pPatch[i+1].eType==JSON_NULL ){
+ pTarget[j+1].jnFlags |= JNODE_REMOVE;
+ }else{
+ JsonNode *pNew = jsonMergePatch(pParse, iTarget+j+1, &pPatch[i+1]);
+ if( pNew==0 ) return 0;
+ pTarget = &pParse->aNode[iTarget];
+ if( pNew!=&pTarget[j+1] ){
+ pTarget[j+1].u.pPatch = pNew;
+ pTarget[j+1].jnFlags |= JNODE_PATCH;
+ }
+ }
+ break;
+ }
+ }
+ if( j>=pTarget->n && pPatch[i+1].eType!=JSON_NULL ){
+ int iStart, iPatch;
+ iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0);
+ jsonParseAddNode(pParse, JSON_STRING, nKey, zKey);
+ iPatch = jsonParseAddNode(pParse, JSON_TRUE, 0, 0);
+ if( pParse->oom ) return 0;
+ jsonRemoveAllNulls(pPatch);
+ pTarget = &pParse->aNode[iTarget];
+ pParse->aNode[iRoot].jnFlags |= JNODE_APPEND;
+ pParse->aNode[iRoot].u.iAppend = iStart - iRoot;
+ iRoot = iStart;
+ pParse->aNode[iPatch].jnFlags |= JNODE_PATCH;
+ pParse->aNode[iPatch].u.pPatch = &pPatch[i+1];
+ }
+ }
+ return pTarget;
+}
+
+/*
+** Implementation of the json_mergepatch(JSON1,JSON2) function. Return a JSON
+** object that is the result of running the RFC 7396 MergePatch() algorithm
+** on the two arguments.
+*/
+static void jsonPatchFunc(
+ sqlite3_context *ctx,
+ int argc,
+ sqlite3_value **argv
+){
+ JsonParse x; /* The JSON that is being patched */
+ JsonParse y; /* The patch */
+ JsonNode *pResult; /* The result of the merge */
+
+ UNUSED_PARAM(argc);
+ if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
+ if( jsonParse(&y, ctx, (const char*)sqlite3_value_text(argv[1])) ){
+ jsonParseReset(&x);
+ return;
+ }
+ pResult = jsonMergePatch(&x, 0, y.aNode);
+ assert( pResult!=0 || x.oom );
+ if( pResult ){
+ jsonReturnJson(pResult, ctx, 0);
+ }else{
+ sqlite3_result_error_nomem(ctx);
+ }
+ jsonParseReset(&x);
+ jsonParseReset(&y);
+}
+
+
+/*
+** Implementation of the json_object(NAME,VALUE,...) function. Return a JSON
+** object that contains all name/value given in arguments. Or if any name
+** is not a string or if any value is a BLOB, throw an error.
+*/
+static void jsonObjectFunc(
+ sqlite3_context *ctx,
+ int argc,
+ sqlite3_value **argv
+){
+ int i;
+ JsonString jx;
+ const char *z;
+ u32 n;
+
+ if( argc&1 ){
+ sqlite3_result_error(ctx, "json_object() requires an even number "
+ "of arguments", -1);
+ return;
+ }
+ jsonInit(&jx, ctx);
+ jsonAppendChar(&jx, '{');
+ for(i=0; i<argc; i+=2){
+ if( sqlite3_value_type(argv[i])!=SQLITE_TEXT ){
+ sqlite3_result_error(ctx, "json_object() labels must be TEXT", -1);
+ jsonReset(&jx);
+ return;
+ }
+ jsonAppendSeparator(&jx);
+ z = (const char*)sqlite3_value_text(argv[i]);
+ n = (u32)sqlite3_value_bytes(argv[i]);
+ jsonAppendString(&jx, z, n);
+ jsonAppendChar(&jx, ':');
+ jsonAppendValue(&jx, argv[i+1]);
+ }
+ jsonAppendChar(&jx, '}');
+ jsonResult(&jx);
+ sqlite3_result_subtype(ctx, JSON_SUBTYPE);
+}
+
+
+/*
+** json_remove(JSON, PATH, ...)
+**
+** Remove the named elements from JSON and return the result. malformed
+** JSON or PATH arguments result in an error.
+*/
+static void jsonRemoveFunc(
+ sqlite3_context *ctx,
+ int argc,
+ sqlite3_value **argv
+){
+ JsonParse x; /* The parse */
+ JsonNode *pNode;
+ const char *zPath;
+ u32 i;
+
+ if( argc<1 ) return;
+ if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
+ assert( x.nNode );
+ for(i=1; i<(u32)argc; i++){
+ zPath = (const char*)sqlite3_value_text(argv[i]);
+ if( zPath==0 ) goto remove_done;
+ pNode = jsonLookup(&x, zPath, 0, ctx);
+ if( x.nErr ) goto remove_done;
+ if( pNode ) pNode->jnFlags |= JNODE_REMOVE;
+ }
+ if( (x.aNode[0].jnFlags & JNODE_REMOVE)==0 ){
+ jsonReturnJson(x.aNode, ctx, 0);
+ }
+remove_done:
+ jsonParseReset(&x);
+}
+
+/*
+** json_replace(JSON, PATH, VALUE, ...)
+**
+** Replace the value at PATH with VALUE. If PATH does not already exist,
+** this routine is a no-op. If JSON or PATH is malformed, throw an error.
+*/
+static void jsonReplaceFunc(
+ sqlite3_context *ctx,
+ int argc,
+ sqlite3_value **argv
+){
+ JsonParse x; /* The parse */
+ JsonNode *pNode;
+ const char *zPath;
+ u32 i;
+
+ if( argc<1 ) return;
+ if( (argc&1)==0 ) {
+ jsonWrongNumArgs(ctx, "replace");
+ return;
+ }
+ if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
+ assert( x.nNode );
+ for(i=1; i<(u32)argc; i+=2){
+ zPath = (const char*)sqlite3_value_text(argv[i]);
+ pNode = jsonLookup(&x, zPath, 0, ctx);
+ if( x.nErr ) goto replace_err;
+ if( pNode ){
+ pNode->jnFlags |= (u8)JNODE_REPLACE;
+ pNode->u.iReplace = i + 1;
+ }
+ }
+ if( x.aNode[0].jnFlags & JNODE_REPLACE ){
+ sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]);
+ }else{
+ jsonReturnJson(x.aNode, ctx, argv);
+ }
+replace_err:
+ jsonParseReset(&x);
+}
+
+/*
+** json_set(JSON, PATH, VALUE, ...)
+**
+** Set the value at PATH to VALUE. Create the PATH if it does not already
+** exist. Overwrite existing values that do exist.
+** If JSON or PATH is malformed, throw an error.
+**
+** json_insert(JSON, PATH, VALUE, ...)
+**
+** Create PATH and initialize it to VALUE. If PATH already exists, this
+** routine is a no-op. If JSON or PATH is malformed, throw an error.
+*/
+static void jsonSetFunc(
+ sqlite3_context *ctx,
+ int argc,
+ sqlite3_value **argv
+){
+ JsonParse x; /* The parse */
+ JsonNode *pNode;
+ const char *zPath;
+ u32 i;
+ int bApnd;
+ int bIsSet = *(int*)sqlite3_user_data(ctx);
+
+ if( argc<1 ) return;
+ if( (argc&1)==0 ) {
+ jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert");
+ return;
+ }
+ if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
+ assert( x.nNode );
+ for(i=1; i<(u32)argc; i+=2){
+ zPath = (const char*)sqlite3_value_text(argv[i]);
+ bApnd = 0;
+ pNode = jsonLookup(&x, zPath, &bApnd, ctx);
+ if( x.oom ){
+ sqlite3_result_error_nomem(ctx);
+ goto jsonSetDone;
+ }else if( x.nErr ){
+ goto jsonSetDone;
+ }else if( pNode && (bApnd || bIsSet) ){
+ pNode->jnFlags |= (u8)JNODE_REPLACE;
+ pNode->u.iReplace = i + 1;
+ }
+ }
+ if( x.aNode[0].jnFlags & JNODE_REPLACE ){
+ sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]);
+ }else{
+ jsonReturnJson(x.aNode, ctx, argv);
+ }
+jsonSetDone:
+ jsonParseReset(&x);
+}
+
+/*
+** json_type(JSON)
+** json_type(JSON, PATH)
+**
+** Return the top-level "type" of a JSON string. Throw an error if
+** either the JSON or PATH inputs are not well-formed.
+*/
+static void jsonTypeFunc(
+ sqlite3_context *ctx,
+ int argc,
+ sqlite3_value **argv
+){
+ JsonParse *p; /* The parse */
+ const char *zPath;
+ JsonNode *pNode;
+
+ p = jsonParseCached(ctx, argv, ctx);
+ if( p==0 ) return;
+ if( argc==2 ){
+ zPath = (const char*)sqlite3_value_text(argv[1]);
+ pNode = jsonLookup(p, zPath, 0, ctx);
+ }else{
+ pNode = p->aNode;
+ }
+ if( pNode ){
+ sqlite3_result_text(ctx, jsonType[pNode->eType], -1, SQLITE_STATIC);
+ }
+}
+
+/*
+** json_valid(JSON)
+**
+** Return 1 if JSON is a well-formed JSON string according to RFC-7159.
+** Return 0 otherwise.
+*/
+static void jsonValidFunc(
+ sqlite3_context *ctx,
+ int argc,
+ sqlite3_value **argv
+){
+ JsonParse *p; /* The parse */
+ UNUSED_PARAM(argc);
+ p = jsonParseCached(ctx, argv, 0);
+ sqlite3_result_int(ctx, p!=0);
+}
+
+
+/****************************************************************************
+** Aggregate SQL function implementations
+****************************************************************************/
+/*
+** json_group_array(VALUE)
+**
+** Return a JSON array composed of all values in the aggregate.
+*/
+static void jsonArrayStep(
+ sqlite3_context *ctx,
+ int argc,
+ sqlite3_value **argv
+){
+ JsonString *pStr;
+ UNUSED_PARAM(argc);
+ pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
+ if( pStr ){
+ if( pStr->zBuf==0 ){
+ jsonInit(pStr, ctx);
+ jsonAppendChar(pStr, '[');
+ }else{
+ jsonAppendChar(pStr, ',');
+ pStr->pCtx = ctx;
+ }
+ jsonAppendValue(pStr, argv[0]);
+ }
+}
+static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){
+ JsonString *pStr;
+ pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
+ if( pStr ){
+ pStr->pCtx = ctx;
+ jsonAppendChar(pStr, ']');
+ if( pStr->bErr ){
+ if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx);
+ assert( pStr->bStatic );
+ }else if( isFinal ){
+ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed,
+ pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free);
+ pStr->bStatic = 1;
+ }else{
+ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
+ pStr->nUsed--;
+ }
+ }else{
+ sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC);
+ }
+ sqlite3_result_subtype(ctx, JSON_SUBTYPE);
+}
+static void jsonArrayValue(sqlite3_context *ctx){
+ jsonArrayCompute(ctx, 0);
+}
+static void jsonArrayFinal(sqlite3_context *ctx){
+ jsonArrayCompute(ctx, 1);
+}
+
+#ifndef SQLITE_OMIT_WINDOWFUNC
+/*
+** This method works for both json_group_array() and json_group_object().
+** It works by removing the first element of the group by searching forward
+** to the first comma (",") that is not within a string and deleting all
+** text through that comma.
+*/
+static void jsonGroupInverse(
+ sqlite3_context *ctx,
+ int argc,
+ sqlite3_value **argv
+){
+ int i;
+ int inStr = 0;
+ char *z;
+ JsonString *pStr;
+ UNUSED_PARAM(argc);
+ UNUSED_PARAM(argv);
+ pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
+#ifdef NEVER
+ /* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will
+ ** always have been called to initalize it */
+ if( NEVER(!pStr) ) return;
+#endif
+ z = pStr->zBuf;
+ for(i=1; z[i]!=',' || inStr; i++){
+ assert( i<pStr->nUsed );
+ if( z[i]=='"' ){
+ inStr = !inStr;
+ }else if( z[i]=='\\' ){
+ i++;
+ }
+ }
+ pStr->nUsed -= i;
+ memmove(&z[1], &z[i+1], (size_t)pStr->nUsed-1);
+}
+#else
+# define jsonGroupInverse 0
+#endif
+
+
+/*
+** json_group_obj(NAME,VALUE)
+**
+** Return a JSON object composed of all names and values in the aggregate.
+*/
+static void jsonObjectStep(
+ sqlite3_context *ctx,
+ int argc,
+ sqlite3_value **argv
+){
+ JsonString *pStr;
+ const char *z;
+ u32 n;
+ UNUSED_PARAM(argc);
+ pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
+ if( pStr ){
+ if( pStr->zBuf==0 ){
+ jsonInit(pStr, ctx);
+ jsonAppendChar(pStr, '{');
+ }else{
+ jsonAppendChar(pStr, ',');
+ pStr->pCtx = ctx;
+ }
+ z = (const char*)sqlite3_value_text(argv[0]);
+ n = (u32)sqlite3_value_bytes(argv[0]);
+ jsonAppendString(pStr, z, n);
+ jsonAppendChar(pStr, ':');
+ jsonAppendValue(pStr, argv[1]);
+ }
+}
+static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
+ JsonString *pStr;
+ pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
+ if( pStr ){
+ jsonAppendChar(pStr, '}');
+ if( pStr->bErr ){
+ if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx);
+ assert( pStr->bStatic );
+ }else if( isFinal ){
+ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed,
+ pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free);
+ pStr->bStatic = 1;
+ }else{
+ sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
+ pStr->nUsed--;
+ }
+ }else{
+ sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC);
+ }
+ sqlite3_result_subtype(ctx, JSON_SUBTYPE);
+}
+static void jsonObjectValue(sqlite3_context *ctx){
+ jsonObjectCompute(ctx, 0);
+}
+static void jsonObjectFinal(sqlite3_context *ctx){
+ jsonObjectCompute(ctx, 1);
+}
+
+
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/****************************************************************************
+** The json_each virtual table
+****************************************************************************/
+typedef struct JsonEachCursor JsonEachCursor;
+struct JsonEachCursor {
+ sqlite3_vtab_cursor base; /* Base class - must be first */
+ u32 iRowid; /* The rowid */
+ u32 iBegin; /* The first node of the scan */
+ u32 i; /* Index in sParse.aNode[] of current row */
+ u32 iEnd; /* EOF when i equals or exceeds this value */
+ u8 eType; /* Type of top-level element */
+ u8 bRecursive; /* True for json_tree(). False for json_each() */
+ char *zJson; /* Input JSON */
+ char *zRoot; /* Path by which to filter zJson */
+ JsonParse sParse; /* Parse of the input JSON */
+};
+
+/* Constructor for the json_each virtual table */
+static int jsonEachConnect(
+ sqlite3 *db,
+ void *pAux,
+ int argc, const char *const*argv,
+ sqlite3_vtab **ppVtab,
+ char **pzErr
+){
+ sqlite3_vtab *pNew;
+ int rc;
+
+/* Column numbers */
+#define JEACH_KEY 0
+#define JEACH_VALUE 1
+#define JEACH_TYPE 2
+#define JEACH_ATOM 3
+#define JEACH_ID 4
+#define JEACH_PARENT 5
+#define JEACH_FULLKEY 6
+#define JEACH_PATH 7
+#define JEACH_JSON 8
+#define JEACH_ROOT 9
+
+ UNUSED_PARAM(pzErr);
+ UNUSED_PARAM(argv);
+ UNUSED_PARAM(argc);
+ UNUSED_PARAM(pAux);
+ rc = sqlite3_declare_vtab(db,
+ "CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path,"
+ "json HIDDEN,root HIDDEN)");
+ if( rc==SQLITE_OK ){
+ pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
+ if( pNew==0 ) return SQLITE_NOMEM;
+ memset(pNew, 0, sizeof(*pNew));
+ }
+ return rc;
+}
+
+/* destructor for json_each virtual table */
+static int jsonEachDisconnect(sqlite3_vtab *pVtab){
+ sqlite3_free(pVtab);
+ return SQLITE_OK;
+}
+
+/* constructor for a JsonEachCursor object for json_each(). */
+static int jsonEachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
+ JsonEachCursor *pCur;
+
+ UNUSED_PARAM(p);
+ pCur = sqlite3_malloc( sizeof(*pCur) );
+ if( pCur==0 ) return SQLITE_NOMEM;
+ memset(pCur, 0, sizeof(*pCur));
+ *ppCursor = &pCur->base;
+ return SQLITE_OK;
+}
+
+/* constructor for a JsonEachCursor object for json_tree(). */
+static int jsonEachOpenTree(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
+ int rc = jsonEachOpenEach(p, ppCursor);
+ if( rc==SQLITE_OK ){
+ JsonEachCursor *pCur = (JsonEachCursor*)*ppCursor;
+ pCur->bRecursive = 1;
+ }
+ return rc;
+}
+
+/* Reset a JsonEachCursor back to its original state. Free any memory
+** held. */
+static void jsonEachCursorReset(JsonEachCursor *p){
+ sqlite3_free(p->zJson);
+ sqlite3_free(p->zRoot);
+ jsonParseReset(&p->sParse);
+ p->iRowid = 0;
+ p->i = 0;
+ p->iEnd = 0;
+ p->eType = 0;
+ p->zJson = 0;
+ p->zRoot = 0;
+}
+
+/* Destructor for a jsonEachCursor object */
+static int jsonEachClose(sqlite3_vtab_cursor *cur){
+ JsonEachCursor *p = (JsonEachCursor*)cur;
+ jsonEachCursorReset(p);
+ sqlite3_free(cur);
+ return SQLITE_OK;
+}
+
+/* Return TRUE if the jsonEachCursor object has been advanced off the end
+** of the JSON object */
+static int jsonEachEof(sqlite3_vtab_cursor *cur){
+ JsonEachCursor *p = (JsonEachCursor*)cur;
+ return p->i >= p->iEnd;
+}
+
+/* Advance the cursor to the next element for json_tree() */
+static int jsonEachNext(sqlite3_vtab_cursor *cur){
+ JsonEachCursor *p = (JsonEachCursor*)cur;
+ if( p->bRecursive ){
+ if( p->sParse.aNode[p->i].jnFlags & JNODE_LABEL ) p->i++;
+ p->i++;
+ p->iRowid++;
+ if( p->i<p->iEnd ){
+ u32 iUp = p->sParse.aUp[p->i];
+ JsonNode *pUp = &p->sParse.aNode[iUp];
+ p->eType = pUp->eType;
+ if( pUp->eType==JSON_ARRAY ){
+ if( iUp==p->i-1 ){
+ pUp->u.iKey = 0;
+ }else{
+ pUp->u.iKey++;
+ }
+ }
+ }
+ }else{
+ switch( p->eType ){
+ case JSON_ARRAY: {
+ p->i += jsonNodeSize(&p->sParse.aNode[p->i]);
+ p->iRowid++;
+ break;
+ }
+ case JSON_OBJECT: {
+ p->i += 1 + jsonNodeSize(&p->sParse.aNode[p->i+1]);
+ p->iRowid++;
+ break;
+ }
+ default: {
+ p->i = p->iEnd;
+ break;
+ }
+ }
+ }
+ return SQLITE_OK;
+}
+
+/* Append the name of the path for element i to pStr
+*/
+static void jsonEachComputePath(
+ JsonEachCursor *p, /* The cursor */
+ JsonString *pStr, /* Write the path here */
+ u32 i /* Path to this element */
+){
+ JsonNode *pNode, *pUp;
+ u32 iUp;
+ if( i==0 ){
+ jsonAppendChar(pStr, '$');
+ return;
+ }
+ iUp = p->sParse.aUp[i];
+ jsonEachComputePath(p, pStr, iUp);
+ pNode = &p->sParse.aNode[i];
+ pUp = &p->sParse.aNode[iUp];
+ if( pUp->eType==JSON_ARRAY ){
+ jsonPrintf(30, pStr, "[%d]", pUp->u.iKey);
+ }else{
+ assert( pUp->eType==JSON_OBJECT );
+ if( (pNode->jnFlags & JNODE_LABEL)==0 ) pNode--;
+ assert( pNode->eType==JSON_STRING );
+ assert( pNode->jnFlags & JNODE_LABEL );
+ jsonPrintf(pNode->n+1, pStr, ".%.*s", pNode->n-2, pNode->u.zJContent+1);
+ }
+}
+
+/* Return the value of a column */
+static int jsonEachColumn(
+ sqlite3_vtab_cursor *cur, /* The cursor */
+ sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
+ int i /* Which column to return */
+){
+ JsonEachCursor *p = (JsonEachCursor*)cur;
+ JsonNode *pThis = &p->sParse.aNode[p->i];
+ switch( i ){
+ case JEACH_KEY: {
+ if( p->i==0 ) break;
+ if( p->eType==JSON_OBJECT ){
+ jsonReturn(pThis, ctx, 0);
+ }else if( p->eType==JSON_ARRAY ){
+ u32 iKey;
+ if( p->bRecursive ){
+ if( p->iRowid==0 ) break;
+ iKey = p->sParse.aNode[p->sParse.aUp[p->i]].u.iKey;
+ }else{
+ iKey = p->iRowid;
+ }
+ sqlite3_result_int64(ctx, (sqlite3_int64)iKey);
+ }
+ break;
+ }
+ case JEACH_VALUE: {
+ if( pThis->jnFlags & JNODE_LABEL ) pThis++;
+ jsonReturn(pThis, ctx, 0);
+ break;
+ }
+ case JEACH_TYPE: {
+ if( pThis->jnFlags & JNODE_LABEL ) pThis++;
+ sqlite3_result_text(ctx, jsonType[pThis->eType], -1, SQLITE_STATIC);
+ break;
+ }
+ case JEACH_ATOM: {
+ if( pThis->jnFlags & JNODE_LABEL ) pThis++;
+ if( pThis->eType>=JSON_ARRAY ) break;
+ jsonReturn(pThis, ctx, 0);
+ break;
+ }
+ case JEACH_ID: {
+ sqlite3_result_int64(ctx,
+ (sqlite3_int64)p->i + ((pThis->jnFlags & JNODE_LABEL)!=0));
+ break;
+ }
+ case JEACH_PARENT: {
+ if( p->i>p->iBegin && p->bRecursive ){
+ sqlite3_result_int64(ctx, (sqlite3_int64)p->sParse.aUp[p->i]);
+ }
+ break;
+ }
+ case JEACH_FULLKEY: {
+ JsonString x;
+ jsonInit(&x, ctx);
+ if( p->bRecursive ){
+ jsonEachComputePath(p, &x, p->i);
+ }else{
+ if( p->zRoot ){
+ jsonAppendRaw(&x, p->zRoot, (int)strlen(p->zRoot));
+ }else{
+ jsonAppendChar(&x, '$');
+ }
+ if( p->eType==JSON_ARRAY ){
+ jsonPrintf(30, &x, "[%d]", p->iRowid);
+ }else if( p->eType==JSON_OBJECT ){
+ jsonPrintf(pThis->n, &x, ".%.*s", pThis->n-2, pThis->u.zJContent+1);
+ }
+ }
+ jsonResult(&x);
+ break;
+ }
+ case JEACH_PATH: {
+ if( p->bRecursive ){
+ JsonString x;
+ jsonInit(&x, ctx);
+ jsonEachComputePath(p, &x, p->sParse.aUp[p->i]);
+ jsonResult(&x);
+ break;
+ }
+ /* For json_each() path and root are the same so fall through
+ ** into the root case */
+ }
+ default: {
+ const char *zRoot = p->zRoot;
+ if( zRoot==0 ) zRoot = "$";
+ sqlite3_result_text(ctx, zRoot, -1, SQLITE_STATIC);
+ break;
+ }
+ case JEACH_JSON: {
+ assert( i==JEACH_JSON );
+ sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_STATIC);
+ break;
+ }
+ }
+ return SQLITE_OK;
+}
+
+/* Return the current rowid value */
+static int jsonEachRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
+ JsonEachCursor *p = (JsonEachCursor*)cur;
+ *pRowid = p->iRowid;
+ return SQLITE_OK;
+}
+
+/* The query strategy is to look for an equality constraint on the json
+** column. Without such a constraint, the table cannot operate. idxNum is
+** 1 if the constraint is found, 3 if the constraint and zRoot are found,
+** and 0 otherwise.
+*/
+static int jsonEachBestIndex(
+ sqlite3_vtab *tab,
+ sqlite3_index_info *pIdxInfo
+){
+ int i;
+ int jsonIdx = -1;
+ int rootIdx = -1;
+ const struct sqlite3_index_constraint *pConstraint;
+
+ UNUSED_PARAM(tab);
+ pConstraint = pIdxInfo->aConstraint;
+ for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
+ if( pConstraint->usable==0 ) continue;
+ if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
+ switch( pConstraint->iColumn ){
+ case JEACH_JSON: jsonIdx = i; break;
+ case JEACH_ROOT: rootIdx = i; break;
+ default: /* no-op */ break;
+ }
+ }
+ if( jsonIdx<0 ){
+ pIdxInfo->idxNum = 0;
+ pIdxInfo->estimatedCost = 1e99;
+ }else{
+ pIdxInfo->estimatedCost = 1.0;
+ pIdxInfo->aConstraintUsage[jsonIdx].argvIndex = 1;
+ pIdxInfo->aConstraintUsage[jsonIdx].omit = 1;
+ if( rootIdx<0 ){
+ pIdxInfo->idxNum = 1;
+ }else{
+ pIdxInfo->aConstraintUsage[rootIdx].argvIndex = 2;
+ pIdxInfo->aConstraintUsage[rootIdx].omit = 1;
+ pIdxInfo->idxNum = 3;
+ }
+ }
+ return SQLITE_OK;
+}
+
+/* Start a search on a new JSON string */
+static int jsonEachFilter(
+ sqlite3_vtab_cursor *cur,
+ int idxNum, const char *idxStr,
+ int argc, sqlite3_value **argv
+){
+ JsonEachCursor *p = (JsonEachCursor*)cur;
+ const char *z;
+ const char *zRoot = 0;
+ sqlite3_int64 n;
+
+ UNUSED_PARAM(idxStr);
+ UNUSED_PARAM(argc);
+ jsonEachCursorReset(p);
+ if( idxNum==0 ) return SQLITE_OK;
+ z = (const char*)sqlite3_value_text(argv[0]);
+ if( z==0 ) return SQLITE_OK;
+ n = sqlite3_value_bytes(argv[0]);
+ p->zJson = sqlite3_malloc64( n+1 );
+ if( p->zJson==0 ) return SQLITE_NOMEM;
+ memcpy(p->zJson, z, (size_t)n+1);
+ if( jsonParse(&p->sParse, 0, p->zJson) ){
+ int rc = SQLITE_NOMEM;
+ if( p->sParse.oom==0 ){
+ sqlite3_free(cur->pVtab->zErrMsg);
+ cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON");
+ if( cur->pVtab->zErrMsg ) rc = SQLITE_ERROR;
+ }
+ jsonEachCursorReset(p);
+ return rc;
+ }else if( p->bRecursive && jsonParseFindParents(&p->sParse) ){
+ jsonEachCursorReset(p);
+ return SQLITE_NOMEM;
+ }else{
+ JsonNode *pNode = 0;
+ if( idxNum==3 ){
+ const char *zErr = 0;
+ zRoot = (const char*)sqlite3_value_text(argv[1]);
+ if( zRoot==0 ) return SQLITE_OK;
+ n = sqlite3_value_bytes(argv[1]);
+ p->zRoot = sqlite3_malloc64( n+1 );
+ if( p->zRoot==0 ) return SQLITE_NOMEM;
+ memcpy(p->zRoot, zRoot, (size_t)n+1);
+ if( zRoot[0]!='$' ){
+ zErr = zRoot;
+ }else{
+ pNode = jsonLookupStep(&p->sParse, 0, p->zRoot+1, 0, &zErr);
+ }
+ if( zErr ){
+ sqlite3_free(cur->pVtab->zErrMsg);
+ cur->pVtab->zErrMsg = jsonPathSyntaxError(zErr);
+ jsonEachCursorReset(p);
+ return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
+ }else if( pNode==0 ){
+ return SQLITE_OK;
+ }
+ }else{
+ pNode = p->sParse.aNode;
+ }
+ p->iBegin = p->i = (int)(pNode - p->sParse.aNode);
+ p->eType = pNode->eType;
+ if( p->eType>=JSON_ARRAY ){
+ pNode->u.iKey = 0;
+ p->iEnd = p->i + pNode->n + 1;
+ if( p->bRecursive ){
+ p->eType = p->sParse.aNode[p->sParse.aUp[p->i]].eType;
+ if( p->i>0 && (p->sParse.aNode[p->i-1].jnFlags & JNODE_LABEL)!=0 ){
+ p->i--;
+ }
+ }else{
+ p->i++;
+ }
+ }else{
+ p->iEnd = p->i+1;
+ }
+ }
+ return SQLITE_OK;
+}
+
+/* The methods of the json_each virtual table */
+static sqlite3_module jsonEachModule = {
+ 0, /* iVersion */
+ 0, /* xCreate */
+ jsonEachConnect, /* xConnect */
+ jsonEachBestIndex, /* xBestIndex */
+ jsonEachDisconnect, /* xDisconnect */
+ 0, /* xDestroy */
+ jsonEachOpenEach, /* xOpen - open a cursor */
+ jsonEachClose, /* xClose - close a cursor */
+ jsonEachFilter, /* xFilter - configure scan constraints */
+ jsonEachNext, /* xNext - advance a cursor */
+ jsonEachEof, /* xEof - check for end of scan */
+ jsonEachColumn, /* xColumn - read data */
+ jsonEachRowid, /* xRowid - read data */
+ 0, /* xUpdate */
+ 0, /* xBegin */
+ 0, /* xSync */
+ 0, /* xCommit */
+ 0, /* xRollback */
+ 0, /* xFindMethod */
+ 0, /* xRename */
+ 0, /* xSavepoint */
+ 0, /* xRelease */
+ 0 /* xRollbackTo */
+};
+
+/* The methods of the json_tree virtual table. */
+static sqlite3_module jsonTreeModule = {
+ 0, /* iVersion */
+ 0, /* xCreate */
+ jsonEachConnect, /* xConnect */
+ jsonEachBestIndex, /* xBestIndex */
+ jsonEachDisconnect, /* xDisconnect */
+ 0, /* xDestroy */
+ jsonEachOpenTree, /* xOpen - open a cursor */
+ jsonEachClose, /* xClose - close a cursor */
+ jsonEachFilter, /* xFilter - configure scan constraints */
+ jsonEachNext, /* xNext - advance a cursor */
+ jsonEachEof, /* xEof - check for end of scan */
+ jsonEachColumn, /* xColumn - read data */
+ jsonEachRowid, /* xRowid - read data */
+ 0, /* xUpdate */
+ 0, /* xBegin */
+ 0, /* xSync */
+ 0, /* xCommit */
+ 0, /* xRollback */
+ 0, /* xFindMethod */
+ 0, /* xRename */
+ 0, /* xSavepoint */
+ 0, /* xRelease */
+ 0 /* xRollbackTo */
+};
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+/****************************************************************************
+** The following routines are the only publically visible identifiers in this
+** file. Call the following routines in order to register the various SQL
+** functions and the virtual table implemented by this file.
+****************************************************************************/
+
+SQLITE_PRIVATE int sqlite3Json1Init(sqlite3 *db){
+ int rc = SQLITE_OK;
+ unsigned int i;
+ static const struct {
+ const char *zName;
+ int nArg;
+ int flag;
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
+ } aFunc[] = {
+ { "json", 1, 0, jsonRemoveFunc },
+ { "json_array", -1, 0, jsonArrayFunc },
+ { "json_array_length", 1, 0, jsonArrayLengthFunc },
+ { "json_array_length", 2, 0, jsonArrayLengthFunc },
+ { "json_extract", -1, 0, jsonExtractFunc },
+ { "json_insert", -1, 0, jsonSetFunc },
+ { "json_object", -1, 0, jsonObjectFunc },
+ { "json_patch", 2, 0, jsonPatchFunc },
+ { "json_quote", 1, 0, jsonQuoteFunc },
+ { "json_remove", -1, 0, jsonRemoveFunc },
+ { "json_replace", -1, 0, jsonReplaceFunc },
+ { "json_set", -1, 1, jsonSetFunc },
+ { "json_type", 1, 0, jsonTypeFunc },
+ { "json_type", 2, 0, jsonTypeFunc },
+ { "json_valid", 1, 0, jsonValidFunc },
+
+#if SQLITE_DEBUG
+ /* DEBUG and TESTING functions */
+ { "json_parse", 1, 0, jsonParseFunc },
+ { "json_test1", 1, 0, jsonTest1Func },
+#endif
+ };
+ static const struct {
+ const char *zName;
+ int nArg;
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**);
+ void (*xFinal)(sqlite3_context*);
+ void (*xValue)(sqlite3_context*);
+ } aAgg[] = {
+ { "json_group_array", 1,
+ jsonArrayStep, jsonArrayFinal, jsonArrayValue },
+ { "json_group_object", 2,
+ jsonObjectStep, jsonObjectFinal, jsonObjectValue },
+ };
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ static const struct {
+ const char *zName;
+ sqlite3_module *pModule;
+ } aMod[] = {
+ { "json_each", &jsonEachModule },
+ { "json_tree", &jsonTreeModule },
+ };
+#endif
+ for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
+ rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg,
+ SQLITE_UTF8 | SQLITE_DETERMINISTIC,
+ (void*)&aFunc[i].flag,
+ aFunc[i].xFunc, 0, 0);
+ }
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){
+ rc = sqlite3_create_window_function(db, aAgg[i].zName, aAgg[i].nArg,
+ SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
+ aAgg[i].xStep, aAgg[i].xFinal,
+ aAgg[i].xValue, jsonGroupInverse, 0);
+ }
+#endif
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ for(i=0; i<sizeof(aMod)/sizeof(aMod[0]) && rc==SQLITE_OK; i++){
+ rc = sqlite3_create_module(db, aMod[i].zName, aMod[i].pModule, 0);
+ }
+#endif
+ return rc;
+}
+
+
+#ifndef SQLITE_CORE
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+SQLITE_API int sqlite3_json_init(
+ sqlite3 *db,
+ char **pzErrMsg,
+ const sqlite3_api_routines *pApi
+){
+ SQLITE_EXTENSION_INIT2(pApi);
+ (void)pzErrMsg; /* Unused parameter */
+ return sqlite3Json1Init(db);
+}
+#endif
+#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1) */
+
+/************** End of json1.c ***********************************************/
/************** Begin file rtree.c *******************************************/
/*
** 2001 September 15
@@ -170647,6 +178221,7 @@ struct Rtree {
u8 nBytesPerCell; /* Bytes consumed per cell */
u8 inWrTrans; /* True if inside write transaction */
u8 nAux; /* # of auxiliary columns in %_rowid */
+ u8 nAuxNotNull; /* Number of initial not-null aux columns */
int iDepth; /* Current depth of the r-tree structure */
char *zDb; /* Name of database containing r-tree table */
char *zName; /* Name of r-tree table */
@@ -173413,7 +180988,7 @@ static int reinsertNodeContent(Rtree *pRtree, RtreeNode *pNode){
/*
** Select a currently unused rowid for a new r-tree record.
*/
-static int newRowid(Rtree *pRtree, i64 *piRowid){
+static int rtreeNewRowid(Rtree *pRtree, i64 *piRowid){
int rc;
sqlite3_bind_null(pRtree->pWriteRowid, 1);
sqlite3_bind_null(pRtree->pWriteRowid, 2);
@@ -173700,7 +181275,7 @@ static int rtreeUpdate(
/* Figure out the rowid of the new row. */
if( bHaveRowid==0 ){
- rc = newRowid(pRtree, &cell.iRowid);
+ rc = rtreeNewRowid(pRtree, &cell.iRowid);
}
*pRowid = cell.iRowid;
@@ -173792,7 +181367,7 @@ static int rtreeRename(sqlite3_vtab *pVtab, const char *zNewName){
*/
static int rtreeSavepoint(sqlite3_vtab *pVtab, int iSavepoint){
Rtree *pRtree = (Rtree *)pVtab;
- int iwt = pRtree->inWrTrans;
+ u8 iwt = pRtree->inWrTrans;
UNUSED_PARAMETER(iSavepoint);
pRtree->inWrTrans = 0;
nodeBlobReset(pRtree);
@@ -173973,7 +181548,11 @@ static int rtreeSqlInit(
sqlite3_str_appendf(p, "UPDATE \"%w\".\"%w_rowid\"SET ", zDb, zPrefix);
for(ii=0; ii<pRtree->nAux; ii++){
if( ii ) sqlite3_str_append(p, ",", 1);
- sqlite3_str_appendf(p,"a%d=?%d",ii,ii+2);
+ if( ii<pRtree->nAuxNotNull ){
+ sqlite3_str_appendf(p,"a%d=coalesce(?%d,a%d)",ii,ii+2,ii);
+ }else{
+ sqlite3_str_appendf(p,"a%d=?%d",ii,ii+2);
+ }
}
sqlite3_str_appendf(p, " WHERE rowid=?1");
zSql = sqlite3_str_finish(p);
@@ -174742,6 +182321,1673 @@ static void rtreecheck(
}
}
+/* Conditionally include the geopoly code */
+#ifdef SQLITE_ENABLE_GEOPOLY
+/************** Include geopoly.c in the middle of rtree.c *******************/
+/************** Begin file geopoly.c *****************************************/
+/*
+** 2018-05-25
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This file implements an alternative R-Tree virtual table that
+** uses polygons to express the boundaries of 2-dimensional objects.
+**
+** This file is #include-ed onto the end of "rtree.c" so that it has
+** access to all of the R-Tree internals.
+*/
+/* #include <stdlib.h> */
+
+/* Enable -DGEOPOLY_ENABLE_DEBUG for debugging facilities */
+#ifdef GEOPOLY_ENABLE_DEBUG
+ static int geo_debug = 0;
+# define GEODEBUG(X) if(geo_debug)printf X
+#else
+# define GEODEBUG(X)
+#endif
+
+#ifndef JSON_NULL /* The following stuff repeats things found in json1 */
+/*
+** Versions of isspace(), isalnum() and isdigit() to which it is safe
+** to pass signed char values.
+*/
+#ifdef sqlite3Isdigit
+ /* Use the SQLite core versions if this routine is part of the
+ ** SQLite amalgamation */
+# define safe_isdigit(x) sqlite3Isdigit(x)
+# define safe_isalnum(x) sqlite3Isalnum(x)
+# define safe_isxdigit(x) sqlite3Isxdigit(x)
+#else
+ /* Use the standard library for separate compilation */
+#include <ctype.h> /* amalgamator: keep */
+# define safe_isdigit(x) isdigit((unsigned char)(x))
+# define safe_isalnum(x) isalnum((unsigned char)(x))
+# define safe_isxdigit(x) isxdigit((unsigned char)(x))
+#endif
+
+/*
+** Growing our own isspace() routine this way is twice as fast as
+** the library isspace() function.
+*/
+static const char geopolyIsSpace[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+#define safe_isspace(x) (geopolyIsSpace[(unsigned char)x])
+#endif /* JSON NULL - back to original code */
+
+/* Compiler and version */
+#ifndef GCC_VERSION
+#if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC)
+# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__)
+#else
+# define GCC_VERSION 0
+#endif
+#endif
+#ifndef MSVC_VERSION
+#if defined(_MSC_VER) && !defined(SQLITE_DISABLE_INTRINSIC)
+# define MSVC_VERSION _MSC_VER
+#else
+# define MSVC_VERSION 0
+#endif
+#endif
+
+/* Datatype for coordinates
+*/
+typedef float GeoCoord;
+
+/*
+** Internal representation of a polygon.
+**
+** The polygon consists of a sequence of vertexes. There is a line
+** segment between each pair of vertexes, and one final segment from
+** the last vertex back to the first. (This differs from the GeoJSON
+** standard in which the final vertex is a repeat of the first.)
+**
+** The polygon follows the right-hand rule. The area to the right of
+** each segment is "outside" and the area to the left is "inside".
+**
+** The on-disk representation consists of a 4-byte header followed by
+** the values. The 4-byte header is:
+**
+** encoding (1 byte) 0=big-endian, 1=little-endian
+** nvertex (3 bytes) Number of vertexes as a big-endian integer
+*/
+typedef struct GeoPoly GeoPoly;
+struct GeoPoly {
+ int nVertex; /* Number of vertexes */
+ unsigned char hdr[4]; /* Header for on-disk representation */
+ GeoCoord a[2]; /* 2*nVertex values. X (longitude) first, then Y */
+};
+
+/*
+** State of a parse of a GeoJSON input.
+*/
+typedef struct GeoParse GeoParse;
+struct GeoParse {
+ const unsigned char *z; /* Unparsed input */
+ int nVertex; /* Number of vertexes in a[] */
+ int nAlloc; /* Space allocated to a[] */
+ int nErr; /* Number of errors encountered */
+ GeoCoord *a; /* Array of vertexes. From sqlite3_malloc64() */
+};
+
+/* Do a 4-byte byte swap */
+static void geopolySwab32(unsigned char *a){
+ unsigned char t = a[0];
+ a[0] = a[3];
+ a[3] = t;
+ t = a[1];
+ a[1] = a[2];
+ a[2] = t;
+}
+
+/* Skip whitespace. Return the next non-whitespace character. */
+static char geopolySkipSpace(GeoParse *p){
+ while( p->z[0] && safe_isspace(p->z[0]) ) p->z++;
+ return p->z[0];
+}
+
+/* Parse out a number. Write the value into *pVal if pVal!=0.
+** return non-zero on success and zero if the next token is not a number.
+*/
+static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){
+ char c = geopolySkipSpace(p);
+ const unsigned char *z = p->z;
+ int j = 0;
+ int seenDP = 0;
+ int seenE = 0;
+ if( c=='-' ){
+ j = 1;
+ c = z[j];
+ }
+ if( c=='0' && z[j+1]>='0' && z[j+1]<='9' ) return 0;
+ for(;; j++){
+ c = z[j];
+ if( c>='0' && c<='9' ) continue;
+ if( c=='.' ){
+ if( z[j-1]=='-' ) return 0;
+ if( seenDP ) return 0;
+ seenDP = 1;
+ continue;
+ }
+ if( c=='e' || c=='E' ){
+ if( z[j-1]<'0' ) return 0;
+ if( seenE ) return -1;
+ seenDP = seenE = 1;
+ c = z[j+1];
+ if( c=='+' || c=='-' ){
+ j++;
+ c = z[j+1];
+ }
+ if( c<'0' || c>'9' ) return 0;
+ continue;
+ }
+ break;
+ }
+ if( z[j-1]<'0' ) return 0;
+ if( pVal ) *pVal = (GeoCoord)atof((const char*)p->z);
+ p->z += j;
+ return 1;
+}
+
+/*
+** If the input is a well-formed JSON array of coordinates with at least
+** four coordinates and where each coordinate is itself a two-value array,
+** then convert the JSON into a GeoPoly object and return a pointer to
+** that object.
+**
+** If any error occurs, return NULL.
+*/
+static GeoPoly *geopolyParseJson(const unsigned char *z, int *pRc){
+ GeoParse s;
+ int rc = SQLITE_OK;
+ memset(&s, 0, sizeof(s));
+ s.z = z;
+ if( geopolySkipSpace(&s)=='[' ){
+ s.z++;
+ while( geopolySkipSpace(&s)=='[' ){
+ int ii = 0;
+ char c;
+ s.z++;
+ if( s.nVertex>=s.nAlloc ){
+ GeoCoord *aNew;
+ s.nAlloc = s.nAlloc*2 + 16;
+ aNew = sqlite3_realloc64(s.a, s.nAlloc*sizeof(GeoCoord)*2 );
+ if( aNew==0 ){
+ rc = SQLITE_NOMEM;
+ s.nErr++;
+ break;
+ }
+ s.a = aNew;
+ }
+ while( geopolyParseNumber(&s, ii<=1 ? &s.a[s.nVertex*2+ii] : 0) ){
+ ii++;
+ if( ii==2 ) s.nVertex++;
+ c = geopolySkipSpace(&s);
+ s.z++;
+ if( c==',' ) continue;
+ if( c==']' && ii>=2 ) break;
+ s.nErr++;
+ rc = SQLITE_ERROR;
+ goto parse_json_err;
+ }
+ if( geopolySkipSpace(&s)==',' ){
+ s.z++;
+ continue;
+ }
+ break;
+ }
+ if( geopolySkipSpace(&s)==']'
+ && s.nVertex>=4
+ && s.a[0]==s.a[s.nVertex*2-2]
+ && s.a[1]==s.a[s.nVertex*2-1]
+ && (s.z++, geopolySkipSpace(&s)==0)
+ ){
+ int nByte;
+ GeoPoly *pOut;
+ int x = 1;
+ s.nVertex--; /* Remove the redundant vertex at the end */
+ nByte = sizeof(GeoPoly) * s.nVertex*2*sizeof(GeoCoord);
+ pOut = sqlite3_malloc64( nByte );
+ x = 1;
+ if( pOut==0 ) goto parse_json_err;
+ pOut->nVertex = s.nVertex;
+ memcpy(pOut->a, s.a, s.nVertex*2*sizeof(GeoCoord));
+ pOut->hdr[0] = *(unsigned char*)&x;
+ pOut->hdr[1] = (s.nVertex>>16)&0xff;
+ pOut->hdr[2] = (s.nVertex>>8)&0xff;
+ pOut->hdr[3] = s.nVertex&0xff;
+ sqlite3_free(s.a);
+ if( pRc ) *pRc = SQLITE_OK;
+ return pOut;
+ }else{
+ s.nErr++;
+ rc = SQLITE_ERROR;
+ }
+ }
+parse_json_err:
+ if( pRc ) *pRc = rc;
+ sqlite3_free(s.a);
+ return 0;
+}
+
+/*
+** Given a function parameter, try to interpret it as a polygon, either
+** in the binary format or JSON text. Compute a GeoPoly object and
+** return a pointer to that object. Or if the input is not a well-formed
+** polygon, put an error message in sqlite3_context and return NULL.
+*/
+static GeoPoly *geopolyFuncParam(
+ sqlite3_context *pCtx, /* Context for error messages */
+ sqlite3_value *pVal, /* The value to decode */
+ int *pRc /* Write error here */
+){
+ GeoPoly *p = 0;
+ int nByte;
+ if( sqlite3_value_type(pVal)==SQLITE_BLOB
+ && (nByte = sqlite3_value_bytes(pVal))>=(4+6*sizeof(GeoCoord))
+ ){
+ const unsigned char *a = sqlite3_value_blob(pVal);
+ int nVertex;
+ nVertex = (a[1]<<16) + (a[2]<<8) + a[3];
+ if( (a[0]==0 || a[0]==1)
+ && (nVertex*2*sizeof(GeoCoord) + 4)==(unsigned int)nByte
+ ){
+ p = sqlite3_malloc64( sizeof(*p) + (nVertex-1)*2*sizeof(GeoCoord) );
+ if( p==0 ){
+ if( pRc ) *pRc = SQLITE_NOMEM;
+ if( pCtx ) sqlite3_result_error_nomem(pCtx);
+ }else{
+ int x = 1;
+ p->nVertex = nVertex;
+ memcpy(p->hdr, a, nByte);
+ if( a[0] != *(unsigned char*)&x ){
+ int ii;
+ for(ii=0; ii<nVertex*2; ii++){
+ geopolySwab32((unsigned char*)&p->a[ii]);
+ }
+ p->hdr[0] ^= 1;
+ }
+ }
+ }
+ if( pRc ) *pRc = SQLITE_OK;
+ return p;
+ }else if( sqlite3_value_type(pVal)==SQLITE_TEXT ){
+ const unsigned char *zJson = sqlite3_value_text(pVal);
+ if( zJson==0 ){
+ if( pRc ) *pRc = SQLITE_NOMEM;
+ return 0;
+ }
+ return geopolyParseJson(zJson, pRc);
+ }else{
+ if( pRc ) *pRc = SQLITE_ERROR;
+ return 0;
+ }
+}
+
+/*
+** Implementation of the geopoly_blob(X) function.
+**
+** If the input is a well-formed Geopoly BLOB or JSON string
+** then return the BLOB representation of the polygon. Otherwise
+** return NULL.
+*/
+static void geopolyBlobFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ GeoPoly *p = geopolyFuncParam(context, argv[0], 0);
+ if( p ){
+ sqlite3_result_blob(context, p->hdr,
+ 4+8*p->nVertex, SQLITE_TRANSIENT);
+ sqlite3_free(p);
+ }
+}
+
+/*
+** SQL function: geopoly_json(X)
+**
+** Interpret X as a polygon and render it as a JSON array
+** of coordinates. Or, if X is not a valid polygon, return NULL.
+*/
+static void geopolyJsonFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ GeoPoly *p = geopolyFuncParam(context, argv[0], 0);
+ if( p ){
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ sqlite3_str *x = sqlite3_str_new(db);
+ int i;
+ sqlite3_str_append(x, "[", 1);
+ for(i=0; i<p->nVertex; i++){
+ sqlite3_str_appendf(x, "[%!g,%!g],", p->a[i*2], p->a[i*2+1]);
+ }
+ sqlite3_str_appendf(x, "[%!g,%!g]]", p->a[0], p->a[1]);
+ sqlite3_result_text(context, sqlite3_str_finish(x), -1, sqlite3_free);
+ sqlite3_free(p);
+ }
+}
+
+/*
+** SQL function: geopoly_svg(X, ....)
+**
+** Interpret X as a polygon and render it as a SVG <polyline>.
+** Additional arguments are added as attributes to the <polyline>.
+*/
+static void geopolySvgFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ GeoPoly *p = geopolyFuncParam(context, argv[0], 0);
+ if( p ){
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ sqlite3_str *x = sqlite3_str_new(db);
+ int i;
+ char cSep = '\'';
+ sqlite3_str_appendf(x, "<polyline points=");
+ for(i=0; i<p->nVertex; i++){
+ sqlite3_str_appendf(x, "%c%g,%g", cSep, p->a[i*2], p->a[i*2+1]);
+ cSep = ' ';
+ }
+ sqlite3_str_appendf(x, " %g,%g'", p->a[0], p->a[1]);
+ for(i=1; i<argc; i++){
+ const char *z = (const char*)sqlite3_value_text(argv[i]);
+ if( z && z[0] ){
+ sqlite3_str_appendf(x, " %s", z);
+ }
+ }
+ sqlite3_str_appendf(x, "></polyline>");
+ sqlite3_result_text(context, sqlite3_str_finish(x), -1, sqlite3_free);
+ sqlite3_free(p);
+ }
+}
+
+/*
+** SQL Function: geopoly_xform(poly, A, B, C, D, E, F)
+**
+** Transform and/or translate a polygon as follows:
+**
+** x1 = A*x0 + B*y0 + E
+** y1 = C*x0 + D*y0 + F
+**
+** For a translation:
+**
+** geopoly_xform(poly, 1, 0, 0, 1, x-offset, y-offset)
+**
+** Rotate by R around the point (0,0):
+**
+** geopoly_xform(poly, cos(R), sin(R), -sin(R), cos(R), 0, 0)
+*/
+static void geopolyXformFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ GeoPoly *p = geopolyFuncParam(context, argv[0], 0);
+ double A = sqlite3_value_double(argv[1]);
+ double B = sqlite3_value_double(argv[2]);
+ double C = sqlite3_value_double(argv[3]);
+ double D = sqlite3_value_double(argv[4]);
+ double E = sqlite3_value_double(argv[5]);
+ double F = sqlite3_value_double(argv[6]);
+ GeoCoord x1, y1, x0, y0;
+ int ii;
+ if( p ){
+ for(ii=0; ii<p->nVertex; ii++){
+ x0 = p->a[ii*2];
+ y0 = p->a[ii*2+1];
+ x1 = (GeoCoord)(A*x0 + B*y0 + E);
+ y1 = (GeoCoord)(C*x0 + D*y0 + F);
+ p->a[ii*2] = x1;
+ p->a[ii*2+1] = y1;
+ }
+ sqlite3_result_blob(context, p->hdr,
+ 4+8*p->nVertex, SQLITE_TRANSIENT);
+ sqlite3_free(p);
+ }
+}
+
+/*
+** Implementation of the geopoly_area(X) function.
+**
+** If the input is a well-formed Geopoly BLOB then return the area
+** enclosed by the polygon. If the polygon circulates clockwise instead
+** of counterclockwise (as it should) then return the negative of the
+** enclosed area. Otherwise return NULL.
+*/
+static void geopolyAreaFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ GeoPoly *p = geopolyFuncParam(context, argv[0], 0);
+ if( p ){
+ double rArea = 0.0;
+ int ii;
+ for(ii=0; ii<p->nVertex-1; ii++){
+ rArea += (p->a[ii*2] - p->a[ii*2+2]) /* (x0 - x1) */
+ * (p->a[ii*2+1] + p->a[ii*2+3]) /* (y0 + y1) */
+ * 0.5;
+ }
+ rArea += (p->a[ii*2] - p->a[0]) /* (xN - x0) */
+ * (p->a[ii*2+1] + p->a[1]) /* (yN + y0) */
+ * 0.5;
+ sqlite3_result_double(context, rArea);
+ sqlite3_free(p);
+ }
+}
+
+/*
+** If pPoly is a polygon, compute its bounding box. Then:
+**
+** (1) if aCoord!=0 store the bounding box in aCoord, returning NULL
+** (2) otherwise, compute a GeoPoly for the bounding box and return the
+** new GeoPoly
+**
+** If pPoly is NULL but aCoord is not NULL, then compute a new GeoPoly from
+** the bounding box in aCoord and return a pointer to that GeoPoly.
+*/
+static GeoPoly *geopolyBBox(
+ sqlite3_context *context, /* For recording the error */
+ sqlite3_value *pPoly, /* The polygon */
+ RtreeCoord *aCoord, /* Results here */
+ int *pRc /* Error code here */
+){
+ GeoPoly *pOut = 0;
+ GeoPoly *p;
+ float mnX, mxX, mnY, mxY;
+ if( pPoly==0 && aCoord!=0 ){
+ p = 0;
+ mnX = aCoord[0].f;
+ mxX = aCoord[1].f;
+ mnY = aCoord[2].f;
+ mxY = aCoord[3].f;
+ goto geopolyBboxFill;
+ }else{
+ p = geopolyFuncParam(context, pPoly, pRc);
+ }
+ if( p ){
+ int ii;
+ mnX = mxX = p->a[0];
+ mnY = mxY = p->a[1];
+ for(ii=1; ii<p->nVertex; ii++){
+ double r = p->a[ii*2];
+ if( r<mnX ) mnX = (float)r;
+ else if( r>mxX ) mxX = (float)r;
+ r = p->a[ii*2+1];
+ if( r<mnY ) mnY = (float)r;
+ else if( r>mxY ) mxY = (float)r;
+ }
+ if( pRc ) *pRc = SQLITE_OK;
+ if( aCoord==0 ){
+ geopolyBboxFill:
+ pOut = sqlite3_realloc(p, sizeof(GeoPoly)+sizeof(GeoCoord)*6);
+ if( pOut==0 ){
+ sqlite3_free(p);
+ if( context ) sqlite3_result_error_nomem(context);
+ if( pRc ) *pRc = SQLITE_NOMEM;
+ return 0;
+ }
+ pOut->nVertex = 4;
+ ii = 1;
+ pOut->hdr[0] = *(unsigned char*)&ii;
+ pOut->hdr[1] = 0;
+ pOut->hdr[2] = 0;
+ pOut->hdr[3] = 4;
+ pOut->a[0] = mnX;
+ pOut->a[1] = mnY;
+ pOut->a[2] = mxX;
+ pOut->a[3] = mnY;
+ pOut->a[4] = mxX;
+ pOut->a[5] = mxY;
+ pOut->a[6] = mnX;
+ pOut->a[7] = mxY;
+ }else{
+ sqlite3_free(p);
+ aCoord[0].f = mnX;
+ aCoord[1].f = mxX;
+ aCoord[2].f = mnY;
+ aCoord[3].f = mxY;
+ }
+ }
+ return pOut;
+}
+
+/*
+** Implementation of the geopoly_bbox(X) SQL function.
+*/
+static void geopolyBBoxFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ GeoPoly *p = geopolyBBox(context, argv[0], 0, 0);
+ if( p ){
+ sqlite3_result_blob(context, p->hdr,
+ 4+8*p->nVertex, SQLITE_TRANSIENT);
+ sqlite3_free(p);
+ }
+}
+
+/*
+** State vector for the geopoly_group_bbox() aggregate function.
+*/
+typedef struct GeoBBox GeoBBox;
+struct GeoBBox {
+ int isInit;
+ RtreeCoord a[4];
+};
+
+
+/*
+** Implementation of the geopoly_group_bbox(X) aggregate SQL function.
+*/
+static void geopolyBBoxStep(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ RtreeCoord a[4];
+ int rc = SQLITE_OK;
+ (void)geopolyBBox(context, argv[0], a, &rc);
+ if( rc==SQLITE_OK ){
+ GeoBBox *pBBox;
+ pBBox = (GeoBBox*)sqlite3_aggregate_context(context, sizeof(*pBBox));
+ if( pBBox==0 ) return;
+ if( pBBox->isInit==0 ){
+ pBBox->isInit = 1;
+ memcpy(pBBox->a, a, sizeof(RtreeCoord)*4);
+ }else{
+ if( a[0].f < pBBox->a[0].f ) pBBox->a[0] = a[0];
+ if( a[1].f > pBBox->a[1].f ) pBBox->a[1] = a[1];
+ if( a[2].f < pBBox->a[2].f ) pBBox->a[2] = a[2];
+ if( a[3].f > pBBox->a[3].f ) pBBox->a[3] = a[3];
+ }
+ }
+}
+static void geopolyBBoxFinal(
+ sqlite3_context *context
+){
+ GeoPoly *p;
+ GeoBBox *pBBox;
+ pBBox = (GeoBBox*)sqlite3_aggregate_context(context, 0);
+ if( pBBox==0 ) return;
+ p = geopolyBBox(context, 0, pBBox->a, 0);
+ if( p ){
+ sqlite3_result_blob(context, p->hdr,
+ 4+8*p->nVertex, SQLITE_TRANSIENT);
+ sqlite3_free(p);
+ }
+}
+
+
+/*
+** Determine if point (x0,y0) is beneath line segment (x1,y1)->(x2,y2).
+** Returns:
+**
+** +2 x0,y0 is on the line segement
+**
+** +1 x0,y0 is beneath line segment
+**
+** 0 x0,y0 is not on or beneath the line segment or the line segment
+** is vertical and x0,y0 is not on the line segment
+**
+** The left-most coordinate min(x1,x2) is not considered to be part of
+** the line segment for the purposes of this analysis.
+*/
+static int pointBeneathLine(
+ double x0, double y0,
+ double x1, double y1,
+ double x2, double y2
+){
+ double y;
+ if( x0==x1 && y0==y1 ) return 2;
+ if( x1<x2 ){
+ if( x0<=x1 || x0>x2 ) return 0;
+ }else if( x1>x2 ){
+ if( x0<=x2 || x0>x1 ) return 0;
+ }else{
+ /* Vertical line segment */
+ if( x0!=x1 ) return 0;
+ if( y0<y1 && y0<y2 ) return 0;
+ if( y0>y1 && y0>y2 ) return 0;
+ return 2;
+ }
+ y = y1 + (y2-y1)*(x0-x1)/(x2-x1);
+ if( y0==y ) return 2;
+ if( y0<y ) return 1;
+ return 0;
+}
+
+/*
+** SQL function: geopoly_contains_point(P,X,Y)
+**
+** Return +2 if point X,Y is within polygon P.
+** Return +1 if point X,Y is on the polygon boundary.
+** Return 0 if point X,Y is outside the polygon
+*/
+static void geopolyContainsPointFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0);
+ double x0 = sqlite3_value_double(argv[1]);
+ double y0 = sqlite3_value_double(argv[2]);
+ int v = 0;
+ int cnt = 0;
+ int ii;
+ if( p1==0 ) return;
+ for(ii=0; ii<p1->nVertex-1; ii++){
+ v = pointBeneathLine(x0,y0,p1->a[ii*2],p1->a[ii*2+1],
+ p1->a[ii*2+2],p1->a[ii*2+3]);
+ if( v==2 ) break;
+ cnt += v;
+ }
+ if( v!=2 ){
+ v = pointBeneathLine(x0,y0,p1->a[ii*2],p1->a[ii*2+1],
+ p1->a[0],p1->a[1]);
+ }
+ if( v==2 ){
+ sqlite3_result_int(context, 1);
+ }else if( ((v+cnt)&1)==0 ){
+ sqlite3_result_int(context, 0);
+ }else{
+ sqlite3_result_int(context, 2);
+ }
+ sqlite3_free(p1);
+}
+
+/* Forward declaration */
+static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2);
+
+/*
+** SQL function: geopoly_within(P1,P2)
+**
+** Return +2 if P1 and P2 are the same polygon
+** Return +1 if P2 is contained within P1
+** Return 0 if any part of P2 is on the outside of P1
+**
+*/
+static void geopolyWithinFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0);
+ GeoPoly *p2 = geopolyFuncParam(context, argv[1], 0);
+ if( p1 && p2 ){
+ int x = geopolyOverlap(p1, p2);
+ if( x<0 ){
+ sqlite3_result_error_nomem(context);
+ }else{
+ sqlite3_result_int(context, x==2 ? 1 : x==4 ? 2 : 0);
+ }
+ }
+ sqlite3_free(p1);
+ sqlite3_free(p2);
+}
+
+/* Objects used by the overlap algorihm. */
+typedef struct GeoEvent GeoEvent;
+typedef struct GeoSegment GeoSegment;
+typedef struct GeoOverlap GeoOverlap;
+struct GeoEvent {
+ double x; /* X coordinate at which event occurs */
+ int eType; /* 0 for ADD, 1 for REMOVE */
+ GeoSegment *pSeg; /* The segment to be added or removed */
+ GeoEvent *pNext; /* Next event in the sorted list */
+};
+struct GeoSegment {
+ double C, B; /* y = C*x + B */
+ double y; /* Current y value */
+ float y0; /* Initial y value */
+ unsigned char side; /* 1 for p1, 2 for p2 */
+ unsigned int idx; /* Which segment within the side */
+ GeoSegment *pNext; /* Next segment in a list sorted by y */
+};
+struct GeoOverlap {
+ GeoEvent *aEvent; /* Array of all events */
+ GeoSegment *aSegment; /* Array of all segments */
+ int nEvent; /* Number of events */
+ int nSegment; /* Number of segments */
+};
+
+/*
+** Add a single segment and its associated events.
+*/
+static void geopolyAddOneSegment(
+ GeoOverlap *p,
+ GeoCoord x0,
+ GeoCoord y0,
+ GeoCoord x1,
+ GeoCoord y1,
+ unsigned char side,
+ unsigned int idx
+){
+ GeoSegment *pSeg;
+ GeoEvent *pEvent;
+ if( x0==x1 ) return; /* Ignore vertical segments */
+ if( x0>x1 ){
+ GeoCoord t = x0;
+ x0 = x1;
+ x1 = t;
+ t = y0;
+ y0 = y1;
+ y1 = t;
+ }
+ pSeg = p->aSegment + p->nSegment;
+ p->nSegment++;
+ pSeg->C = (y1-y0)/(x1-x0);
+ pSeg->B = y1 - x1*pSeg->C;
+ pSeg->y0 = y0;
+ pSeg->side = side;
+ pSeg->idx = idx;
+ pEvent = p->aEvent + p->nEvent;
+ p->nEvent++;
+ pEvent->x = x0;
+ pEvent->eType = 0;
+ pEvent->pSeg = pSeg;
+ pEvent = p->aEvent + p->nEvent;
+ p->nEvent++;
+ pEvent->x = x1;
+ pEvent->eType = 1;
+ pEvent->pSeg = pSeg;
+}
+
+
+
+/*
+** Insert all segments and events for polygon pPoly.
+*/
+static void geopolyAddSegments(
+ GeoOverlap *p, /* Add segments to this Overlap object */
+ GeoPoly *pPoly, /* Take all segments from this polygon */
+ unsigned char side /* The side of pPoly */
+){
+ unsigned int i;
+ GeoCoord *x;
+ for(i=0; i<(unsigned)pPoly->nVertex-1; i++){
+ x = pPoly->a + (i*2);
+ geopolyAddOneSegment(p, x[0], x[1], x[2], x[3], side, i);
+ }
+ x = pPoly->a + (i*2);
+ geopolyAddOneSegment(p, x[0], x[1], pPoly->a[0], pPoly->a[1], side, i);
+}
+
+/*
+** Merge two lists of sorted events by X coordinate
+*/
+static GeoEvent *geopolyEventMerge(GeoEvent *pLeft, GeoEvent *pRight){
+ GeoEvent head, *pLast;
+ head.pNext = 0;
+ pLast = &head;
+ while( pRight && pLeft ){
+ if( pRight->x <= pLeft->x ){
+ pLast->pNext = pRight;
+ pLast = pRight;
+ pRight = pRight->pNext;
+ }else{
+ pLast->pNext = pLeft;
+ pLast = pLeft;
+ pLeft = pLeft->pNext;
+ }
+ }
+ pLast->pNext = pRight ? pRight : pLeft;
+ return head.pNext;
+}
+
+/*
+** Sort an array of nEvent event objects into a list.
+*/
+static GeoEvent *geopolySortEventsByX(GeoEvent *aEvent, int nEvent){
+ int mx = 0;
+ int i, j;
+ GeoEvent *p;
+ GeoEvent *a[50];
+ for(i=0; i<nEvent; i++){
+ p = &aEvent[i];
+ p->pNext = 0;
+ for(j=0; j<mx && a[j]; j++){
+ p = geopolyEventMerge(a[j], p);
+ a[j] = 0;
+ }
+ a[j] = p;
+ if( j>=mx ) mx = j+1;
+ }
+ p = 0;
+ for(i=0; i<mx; i++){
+ p = geopolyEventMerge(a[i], p);
+ }
+ return p;
+}
+
+/*
+** Merge two lists of sorted segments by Y, and then by C.
+*/
+static GeoSegment *geopolySegmentMerge(GeoSegment *pLeft, GeoSegment *pRight){
+ GeoSegment head, *pLast;
+ head.pNext = 0;
+ pLast = &head;
+ while( pRight && pLeft ){
+ double r = pRight->y - pLeft->y;
+ if( r==0.0 ) r = pRight->C - pLeft->C;
+ if( r<0.0 ){
+ pLast->pNext = pRight;
+ pLast = pRight;
+ pRight = pRight->pNext;
+ }else{
+ pLast->pNext = pLeft;
+ pLast = pLeft;
+ pLeft = pLeft->pNext;
+ }
+ }
+ pLast->pNext = pRight ? pRight : pLeft;
+ return head.pNext;
+}
+
+/*
+** Sort a list of GeoSegments in order of increasing Y and in the event of
+** a tie, increasing C (slope).
+*/
+static GeoSegment *geopolySortSegmentsByYAndC(GeoSegment *pList){
+ int mx = 0;
+ int i;
+ GeoSegment *p;
+ GeoSegment *a[50];
+ while( pList ){
+ p = pList;
+ pList = pList->pNext;
+ p->pNext = 0;
+ for(i=0; i<mx && a[i]; i++){
+ p = geopolySegmentMerge(a[i], p);
+ a[i] = 0;
+ }
+ a[i] = p;
+ if( i>=mx ) mx = i+1;
+ }
+ p = 0;
+ for(i=0; i<mx; i++){
+ p = geopolySegmentMerge(a[i], p);
+ }
+ return p;
+}
+
+/*
+** Determine the overlap between two polygons
+*/
+static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2){
+ int nVertex = p1->nVertex + p2->nVertex + 2;
+ GeoOverlap *p;
+ int nByte;
+ GeoEvent *pThisEvent;
+ double rX;
+ int rc = 0;
+ int needSort = 0;
+ GeoSegment *pActive = 0;
+ GeoSegment *pSeg;
+ unsigned char aOverlap[4];
+
+ nByte = sizeof(GeoEvent)*nVertex*2
+ + sizeof(GeoSegment)*nVertex
+ + sizeof(GeoOverlap);
+ p = sqlite3_malloc( nByte );
+ if( p==0 ) return -1;
+ p->aEvent = (GeoEvent*)&p[1];
+ p->aSegment = (GeoSegment*)&p->aEvent[nVertex*2];
+ p->nEvent = p->nSegment = 0;
+ geopolyAddSegments(p, p1, 1);
+ geopolyAddSegments(p, p2, 2);
+ pThisEvent = geopolySortEventsByX(p->aEvent, p->nEvent);
+ rX = pThisEvent->x==0.0 ? -1.0 : 0.0;
+ memset(aOverlap, 0, sizeof(aOverlap));
+ while( pThisEvent ){
+ if( pThisEvent->x!=rX ){
+ GeoSegment *pPrev = 0;
+ int iMask = 0;
+ GEODEBUG(("Distinct X: %g\n", pThisEvent->x));
+ rX = pThisEvent->x;
+ if( needSort ){
+ GEODEBUG(("SORT\n"));
+ pActive = geopolySortSegmentsByYAndC(pActive);
+ needSort = 0;
+ }
+ for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){
+ if( pPrev ){
+ if( pPrev->y!=pSeg->y ){
+ GEODEBUG(("MASK: %d\n", iMask));
+ aOverlap[iMask] = 1;
+ }
+ }
+ iMask ^= pSeg->side;
+ pPrev = pSeg;
+ }
+ pPrev = 0;
+ for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){
+ double y = pSeg->C*rX + pSeg->B;
+ GEODEBUG(("Segment %d.%d %g->%g\n", pSeg->side, pSeg->idx, pSeg->y, y));
+ pSeg->y = y;
+ if( pPrev ){
+ if( pPrev->y>pSeg->y && pPrev->side!=pSeg->side ){
+ rc = 1;
+ GEODEBUG(("Crossing: %d.%d and %d.%d\n",
+ pPrev->side, pPrev->idx,
+ pSeg->side, pSeg->idx));
+ goto geopolyOverlapDone;
+ }else if( pPrev->y!=pSeg->y ){
+ GEODEBUG(("MASK: %d\n", iMask));
+ aOverlap[iMask] = 1;
+ }
+ }
+ iMask ^= pSeg->side;
+ pPrev = pSeg;
+ }
+ }
+ GEODEBUG(("%s %d.%d C=%g B=%g\n",
+ pThisEvent->eType ? "RM " : "ADD",
+ pThisEvent->pSeg->side, pThisEvent->pSeg->idx,
+ pThisEvent->pSeg->C,
+ pThisEvent->pSeg->B));
+ if( pThisEvent->eType==0 ){
+ /* Add a segment */
+ pSeg = pThisEvent->pSeg;
+ pSeg->y = pSeg->y0;
+ pSeg->pNext = pActive;
+ pActive = pSeg;
+ needSort = 1;
+ }else{
+ /* Remove a segment */
+ if( pActive==pThisEvent->pSeg ){
+ pActive = pActive->pNext;
+ }else{
+ for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){
+ if( pSeg->pNext==pThisEvent->pSeg ){
+ pSeg->pNext = pSeg->pNext->pNext;
+ break;
+ }
+ }
+ }
+ }
+ pThisEvent = pThisEvent->pNext;
+ }
+ if( aOverlap[3]==0 ){
+ rc = 0;
+ }else if( aOverlap[1]!=0 && aOverlap[2]==0 ){
+ rc = 3;
+ }else if( aOverlap[1]==0 && aOverlap[2]!=0 ){
+ rc = 2;
+ }else if( aOverlap[1]==0 && aOverlap[2]==0 ){
+ rc = 4;
+ }else{
+ rc = 1;
+ }
+
+geopolyOverlapDone:
+ sqlite3_free(p);
+ return rc;
+}
+
+/*
+** SQL function: geopoly_overlap(P1,P2)
+**
+** Determine whether or not P1 and P2 overlap. Return value:
+**
+** 0 The two polygons are disjoint
+** 1 They overlap
+** 2 P1 is completely contained within P2
+** 3 P2 is completely contained within P1
+** 4 P1 and P2 are the same polygon
+** NULL Either P1 or P2 or both are not valid polygons
+*/
+static void geopolyOverlapFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ GeoPoly *p1 = geopolyFuncParam(context, argv[0], 0);
+ GeoPoly *p2 = geopolyFuncParam(context, argv[1], 0);
+ if( p1 && p2 ){
+ int x = geopolyOverlap(p1, p2);
+ if( x<0 ){
+ sqlite3_result_error_nomem(context);
+ }else{
+ sqlite3_result_int(context, x);
+ }
+ }
+ sqlite3_free(p1);
+ sqlite3_free(p2);
+}
+
+/*
+** Enable or disable debugging output
+*/
+static void geopolyDebugFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+#ifdef GEOPOLY_ENABLE_DEBUG
+ geo_debug = sqlite3_value_int(argv[0]);
+#endif
+}
+
+/*
+** This function is the implementation of both the xConnect and xCreate
+** methods of the geopoly virtual table.
+**
+** argv[0] -> module name
+** argv[1] -> database name
+** argv[2] -> table name
+** argv[...] -> column names...
+*/
+static int geopolyInit(
+ sqlite3 *db, /* Database connection */
+ void *pAux, /* One of the RTREE_COORD_* constants */
+ int argc, const char *const*argv, /* Parameters to CREATE TABLE statement */
+ sqlite3_vtab **ppVtab, /* OUT: New virtual table */
+ char **pzErr, /* OUT: Error message, if any */
+ int isCreate /* True for xCreate, false for xConnect */
+){
+ int rc = SQLITE_OK;
+ Rtree *pRtree;
+ int nDb; /* Length of string argv[1] */
+ int nName; /* Length of string argv[2] */
+ sqlite3_str *pSql;
+ char *zSql;
+ int ii;
+
+ sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1);
+
+ /* Allocate the sqlite3_vtab structure */
+ nDb = (int)strlen(argv[1]);
+ nName = (int)strlen(argv[2]);
+ pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2);
+ if( !pRtree ){
+ return SQLITE_NOMEM;
+ }
+ memset(pRtree, 0, sizeof(Rtree)+nDb+nName+2);
+ pRtree->nBusy = 1;
+ pRtree->base.pModule = &rtreeModule;
+ pRtree->zDb = (char *)&pRtree[1];
+ pRtree->zName = &pRtree->zDb[nDb+1];
+ pRtree->eCoordType = RTREE_COORD_REAL32;
+ pRtree->nDim = 2;
+ pRtree->nDim2 = 4;
+ memcpy(pRtree->zDb, argv[1], nDb);
+ memcpy(pRtree->zName, argv[2], nName);
+
+
+ /* Create/Connect to the underlying relational database schema. If
+ ** that is successful, call sqlite3_declare_vtab() to configure
+ ** the r-tree table schema.
+ */
+ pSql = sqlite3_str_new(db);
+ sqlite3_str_appendf(pSql, "CREATE TABLE x(_shape");
+ pRtree->nAux = 1; /* Add one for _shape */
+ pRtree->nAuxNotNull = 1; /* The _shape column is always not-null */
+ for(ii=3; ii<argc; ii++){
+ pRtree->nAux++;
+ sqlite3_str_appendf(pSql, ",%s", argv[ii]);
+ }
+ sqlite3_str_appendf(pSql, ");");
+ zSql = sqlite3_str_finish(pSql);
+ if( !zSql ){
+ rc = SQLITE_NOMEM;
+ }else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){
+ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
+ }
+ sqlite3_free(zSql);
+ if( rc ) goto geopolyInit_fail;
+ pRtree->nBytesPerCell = 8 + pRtree->nDim2*4;
+
+ /* Figure out the node size to use. */
+ rc = getNodeSize(db, pRtree, isCreate, pzErr);
+ if( rc ) goto geopolyInit_fail;
+ rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate);
+ if( rc ){
+ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
+ goto geopolyInit_fail;
+ }
+
+ *ppVtab = (sqlite3_vtab *)pRtree;
+ return SQLITE_OK;
+
+geopolyInit_fail:
+ if( rc==SQLITE_OK ) rc = SQLITE_ERROR;
+ assert( *ppVtab==0 );
+ assert( pRtree->nBusy==1 );
+ rtreeRelease(pRtree);
+ return rc;
+}
+
+
+/*
+** GEOPOLY virtual table module xCreate method.
+*/
+static int geopolyCreate(
+ sqlite3 *db,
+ void *pAux,
+ int argc, const char *const*argv,
+ sqlite3_vtab **ppVtab,
+ char **pzErr
+){
+ return geopolyInit(db, pAux, argc, argv, ppVtab, pzErr, 1);
+}
+
+/*
+** GEOPOLY virtual table module xConnect method.
+*/
+static int geopolyConnect(
+ sqlite3 *db,
+ void *pAux,
+ int argc, const char *const*argv,
+ sqlite3_vtab **ppVtab,
+ char **pzErr
+){
+ return geopolyInit(db, pAux, argc, argv, ppVtab, pzErr, 0);
+}
+
+
+/*
+** GEOPOLY virtual table module xFilter method.
+**
+** Query plans:
+**
+** 1 rowid lookup
+** 2 search for objects overlapping the same bounding box
+** that contains polygon argv[0]
+** 3 search for objects overlapping the same bounding box
+** that contains polygon argv[0]
+** 4 full table scan
+*/
+static int geopolyFilter(
+ sqlite3_vtab_cursor *pVtabCursor, /* The cursor to initialize */
+ int idxNum, /* Query plan */
+ const char *idxStr, /* Not Used */
+ int argc, sqlite3_value **argv /* Parameters to the query plan */
+){
+ Rtree *pRtree = (Rtree *)pVtabCursor->pVtab;
+ RtreeCursor *pCsr = (RtreeCursor *)pVtabCursor;
+ RtreeNode *pRoot = 0;
+ int rc = SQLITE_OK;
+ int iCell = 0;
+ sqlite3_stmt *pStmt;
+
+ rtreeReference(pRtree);
+
+ /* Reset the cursor to the same state as rtreeOpen() leaves it in. */
+ freeCursorConstraints(pCsr);
+ sqlite3_free(pCsr->aPoint);
+ pStmt = pCsr->pReadAux;
+ memset(pCsr, 0, sizeof(RtreeCursor));
+ pCsr->base.pVtab = (sqlite3_vtab*)pRtree;
+ pCsr->pReadAux = pStmt;
+
+ pCsr->iStrategy = idxNum;
+ if( idxNum==1 ){
+ /* Special case - lookup by rowid. */
+ RtreeNode *pLeaf; /* Leaf on which the required cell resides */
+ RtreeSearchPoint *p; /* Search point for the leaf */
+ i64 iRowid = sqlite3_value_int64(argv[0]);
+ i64 iNode = 0;
+ rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode);
+ if( rc==SQLITE_OK && pLeaf!=0 ){
+ p = rtreeSearchPointNew(pCsr, RTREE_ZERO, 0);
+ assert( p!=0 ); /* Always returns pCsr->sPoint */
+ pCsr->aNode[0] = pLeaf;
+ p->id = iNode;
+ p->eWithin = PARTLY_WITHIN;
+ rc = nodeRowidIndex(pRtree, pLeaf, iRowid, &iCell);
+ p->iCell = (u8)iCell;
+ RTREE_QUEUE_TRACE(pCsr, "PUSH-F1:");
+ }else{
+ pCsr->atEOF = 1;
+ }
+ }else{
+ /* Normal case - r-tree scan. Set up the RtreeCursor.aConstraint array
+ ** with the configured constraints.
+ */
+ rc = nodeAcquire(pRtree, 1, 0, &pRoot);
+ if( rc==SQLITE_OK && idxNum<=3 ){
+ RtreeCoord bbox[4];
+ RtreeConstraint *p;
+ assert( argc==1 );
+ geopolyBBox(0, argv[0], bbox, &rc);
+ if( rc ){
+ goto geopoly_filter_end;
+ }
+ pCsr->aConstraint = p = sqlite3_malloc(sizeof(RtreeConstraint)*4);
+ pCsr->nConstraint = 4;
+ if( p==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ memset(pCsr->aConstraint, 0, sizeof(RtreeConstraint)*4);
+ memset(pCsr->anQueue, 0, sizeof(u32)*(pRtree->iDepth + 1));
+ if( idxNum==2 ){
+ /* Overlap query */
+ p->op = 'B';
+ p->iCoord = 0;
+ p->u.rValue = bbox[1].f;
+ p++;
+ p->op = 'D';
+ p->iCoord = 1;
+ p->u.rValue = bbox[0].f;
+ p++;
+ p->op = 'B';
+ p->iCoord = 2;
+ p->u.rValue = bbox[3].f;
+ p++;
+ p->op = 'D';
+ p->iCoord = 3;
+ p->u.rValue = bbox[2].f;
+ }else{
+ /* Within query */
+ p->op = 'D';
+ p->iCoord = 0;
+ p->u.rValue = bbox[0].f;
+ p++;
+ p->op = 'B';
+ p->iCoord = 1;
+ p->u.rValue = bbox[1].f;
+ p++;
+ p->op = 'D';
+ p->iCoord = 2;
+ p->u.rValue = bbox[2].f;
+ p++;
+ p->op = 'B';
+ p->iCoord = 3;
+ p->u.rValue = bbox[3].f;
+ }
+ }
+ }
+ if( rc==SQLITE_OK ){
+ RtreeSearchPoint *pNew;
+ pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, (u8)(pRtree->iDepth+1));
+ if( pNew==0 ){
+ rc = SQLITE_NOMEM;
+ goto geopoly_filter_end;
+ }
+ pNew->id = 1;
+ pNew->iCell = 0;
+ pNew->eWithin = PARTLY_WITHIN;
+ assert( pCsr->bPoint==1 );
+ pCsr->aNode[0] = pRoot;
+ pRoot = 0;
+ RTREE_QUEUE_TRACE(pCsr, "PUSH-Fm:");
+ rc = rtreeStepToLeaf(pCsr);
+ }
+ }
+
+geopoly_filter_end:
+ nodeRelease(pRtree, pRoot);
+ rtreeRelease(pRtree);
+ return rc;
+}
+
+/*
+** Rtree virtual table module xBestIndex method. There are three
+** table scan strategies to choose from (in order from most to
+** least desirable):
+**
+** idxNum idxStr Strategy
+** ------------------------------------------------
+** 1 "rowid" Direct lookup by rowid.
+** 2 "rtree" R-tree overlap query using geopoly_overlap()
+** 3 "rtree" R-tree within query using geopoly_within()
+** 4 "fullscan" full-table scan.
+** ------------------------------------------------
+*/
+static int geopolyBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
+ int ii;
+ int iRowidTerm = -1;
+ int iFuncTerm = -1;
+ int idxNum = 0;
+
+ for(ii=0; ii<pIdxInfo->nConstraint; ii++){
+ struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii];
+ if( !p->usable ) continue;
+ if( p->iColumn<0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
+ iRowidTerm = ii;
+ break;
+ }
+ if( p->iColumn==0 && p->op>=SQLITE_INDEX_CONSTRAINT_FUNCTION ){
+ /* p->op==SQLITE_INDEX_CONSTRAINT_FUNCTION for geopoly_overlap()
+ ** p->op==(SQLITE_INDEX_CONTRAINT_FUNCTION+1) for geopoly_within().
+ ** See geopolyFindFunction() */
+ iFuncTerm = ii;
+ idxNum = p->op - SQLITE_INDEX_CONSTRAINT_FUNCTION + 2;
+ }
+ }
+
+ if( iRowidTerm>=0 ){
+ pIdxInfo->idxNum = 1;
+ pIdxInfo->idxStr = "rowid";
+ pIdxInfo->aConstraintUsage[iRowidTerm].argvIndex = 1;
+ pIdxInfo->aConstraintUsage[iRowidTerm].omit = 1;
+ pIdxInfo->estimatedCost = 30.0;
+ pIdxInfo->estimatedRows = 1;
+ pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE;
+ return SQLITE_OK;
+ }
+ if( iFuncTerm>=0 ){
+ pIdxInfo->idxNum = idxNum;
+ pIdxInfo->idxStr = "rtree";
+ pIdxInfo->aConstraintUsage[iFuncTerm].argvIndex = 1;
+ pIdxInfo->aConstraintUsage[iFuncTerm].omit = 0;
+ pIdxInfo->estimatedCost = 300.0;
+ pIdxInfo->estimatedRows = 10;
+ return SQLITE_OK;
+ }
+ pIdxInfo->idxNum = 4;
+ pIdxInfo->idxStr = "fullscan";
+ pIdxInfo->estimatedCost = 3000000.0;
+ pIdxInfo->estimatedRows = 100000;
+ return SQLITE_OK;
+}
+
+
+/*
+** GEOPOLY virtual table module xColumn method.
+*/
+static int geopolyColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
+ Rtree *pRtree = (Rtree *)cur->pVtab;
+ RtreeCursor *pCsr = (RtreeCursor *)cur;
+ RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr);
+ int rc = SQLITE_OK;
+ RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc);
+
+ if( rc ) return rc;
+ if( p==0 ) return SQLITE_OK;
+ if( i==0 && sqlite3_vtab_nochange(ctx) ) return SQLITE_OK;
+ if( i<=pRtree->nAux ){
+ if( !pCsr->bAuxValid ){
+ if( pCsr->pReadAux==0 ){
+ rc = sqlite3_prepare_v3(pRtree->db, pRtree->zReadAuxSql, -1, 0,
+ &pCsr->pReadAux, 0);
+ if( rc ) return rc;
+ }
+ sqlite3_bind_int64(pCsr->pReadAux, 1,
+ nodeGetRowid(pRtree, pNode, p->iCell));
+ rc = sqlite3_step(pCsr->pReadAux);
+ if( rc==SQLITE_ROW ){
+ pCsr->bAuxValid = 1;
+ }else{
+ sqlite3_reset(pCsr->pReadAux);
+ if( rc==SQLITE_DONE ) rc = SQLITE_OK;
+ return rc;
+ }
+ }
+ sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pReadAux, i+2));
+ }
+ return SQLITE_OK;
+}
+
+
+/*
+** The xUpdate method for GEOPOLY module virtual tables.
+**
+** For DELETE:
+**
+** argv[0] = the rowid to be deleted
+**
+** For INSERT:
+**
+** argv[0] = SQL NULL
+** argv[1] = rowid to insert, or an SQL NULL to select automatically
+** argv[2] = _shape column
+** argv[3] = first application-defined column....
+**
+** For UPDATE:
+**
+** argv[0] = rowid to modify. Never NULL
+** argv[1] = rowid after the change. Never NULL
+** argv[2] = new value for _shape
+** argv[3] = new value for first application-defined column....
+*/
+static int geopolyUpdate(
+ sqlite3_vtab *pVtab,
+ int nData,
+ sqlite3_value **aData,
+ sqlite_int64 *pRowid
+){
+ Rtree *pRtree = (Rtree *)pVtab;
+ int rc = SQLITE_OK;
+ RtreeCell cell; /* New cell to insert if nData>1 */
+ i64 oldRowid; /* The old rowid */
+ int oldRowidValid; /* True if oldRowid is valid */
+ i64 newRowid; /* The new rowid */
+ int newRowidValid; /* True if newRowid is valid */
+ int coordChange = 0; /* Change in coordinates */
+
+ if( pRtree->nNodeRef ){
+ /* Unable to write to the btree while another cursor is reading from it,
+ ** since the write might do a rebalance which would disrupt the read
+ ** cursor. */
+ return SQLITE_LOCKED_VTAB;
+ }
+ rtreeReference(pRtree);
+ assert(nData>=1);
+
+ oldRowidValid = sqlite3_value_type(aData[0])!=SQLITE_NULL;;
+ oldRowid = oldRowidValid ? sqlite3_value_int64(aData[0]) : 0;
+ newRowidValid = nData>1 && sqlite3_value_type(aData[1])!=SQLITE_NULL;
+ newRowid = newRowidValid ? sqlite3_value_int64(aData[1]) : 0;
+ cell.iRowid = newRowid;
+
+ if( nData>1 /* not a DELETE */
+ && (!oldRowidValid /* INSERT */
+ || !sqlite3_value_nochange(aData[2]) /* UPDATE _shape */
+ || oldRowid!=newRowid) /* Rowid change */
+ ){
+ geopolyBBox(0, aData[2], cell.aCoord, &rc);
+ if( rc ){
+ if( rc==SQLITE_ERROR ){
+ pVtab->zErrMsg =
+ sqlite3_mprintf("_shape does not contain a valid polygon");
+ }
+ goto geopoly_update_end;
+ }
+ coordChange = 1;
+
+ /* If a rowid value was supplied, check if it is already present in
+ ** the table. If so, the constraint has failed. */
+ if( newRowidValid && (!oldRowidValid || oldRowid!=newRowid) ){
+ int steprc;
+ sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid);
+ steprc = sqlite3_step(pRtree->pReadRowid);
+ rc = sqlite3_reset(pRtree->pReadRowid);
+ if( SQLITE_ROW==steprc ){
+ if( sqlite3_vtab_on_conflict(pRtree->db)==SQLITE_REPLACE ){
+ rc = rtreeDeleteRowid(pRtree, cell.iRowid);
+ }else{
+ rc = rtreeConstraintError(pRtree, 0);
+ }
+ }
+ }
+ }
+
+ /* If aData[0] is not an SQL NULL value, it is the rowid of a
+ ** record to delete from the r-tree table. The following block does
+ ** just that.
+ */
+ if( rc==SQLITE_OK && (nData==1 || (coordChange && oldRowidValid)) ){
+ rc = rtreeDeleteRowid(pRtree, oldRowid);
+ }
+
+ /* If the aData[] array contains more than one element, elements
+ ** (aData[2]..aData[argc-1]) contain a new record to insert into
+ ** the r-tree structure.
+ */
+ if( rc==SQLITE_OK && nData>1 && coordChange ){
+ /* Insert the new record into the r-tree */
+ RtreeNode *pLeaf = 0;
+ if( !newRowidValid ){
+ rc = rtreeNewRowid(pRtree, &cell.iRowid);
+ }
+ *pRowid = cell.iRowid;
+ if( rc==SQLITE_OK ){
+ rc = ChooseLeaf(pRtree, &cell, 0, &pLeaf);
+ }
+ if( rc==SQLITE_OK ){
+ int rc2;
+ pRtree->iReinsertHeight = -1;
+ rc = rtreeInsertCell(pRtree, pLeaf, &cell, 0);
+ rc2 = nodeRelease(pRtree, pLeaf);
+ if( rc==SQLITE_OK ){
+ rc = rc2;
+ }
+ }
+ }
+
+ /* Change the data */
+ if( rc==SQLITE_OK && nData>1 ){
+ sqlite3_stmt *pUp = pRtree->pWriteAux;
+ int jj;
+ int nChange = 0;
+ sqlite3_bind_int64(pUp, 1, cell.iRowid);
+ assert( pRtree->nAux>=1 );
+ if( sqlite3_value_nochange(aData[2]) ){
+ sqlite3_bind_null(pUp, 2);
+ }else{
+ sqlite3_bind_value(pUp, 2, aData[2]);
+ nChange = 1;
+ }
+ for(jj=1; jj<pRtree->nAux; jj++){
+ nChange++;
+ sqlite3_bind_value(pUp, jj+2, aData[jj+2]);
+ }
+ if( nChange ){
+ sqlite3_step(pUp);
+ rc = sqlite3_reset(pUp);
+ }
+ }
+
+geopoly_update_end:
+ rtreeRelease(pRtree);
+ return rc;
+}
+
+/*
+** Report that geopoly_overlap() is an overloaded function suitable
+** for use in xBestIndex.
+*/
+static int geopolyFindFunction(
+ sqlite3_vtab *pVtab,
+ int nArg,
+ const char *zName,
+ void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
+ void **ppArg
+){
+ if( sqlite3_stricmp(zName, "geopoly_overlap")==0 ){
+ *pxFunc = geopolyOverlapFunc;
+ *ppArg = 0;
+ return SQLITE_INDEX_CONSTRAINT_FUNCTION;
+ }
+ if( sqlite3_stricmp(zName, "geopoly_within")==0 ){
+ *pxFunc = geopolyWithinFunc;
+ *ppArg = 0;
+ return SQLITE_INDEX_CONSTRAINT_FUNCTION+1;
+ }
+ return 0;
+}
+
+
+static sqlite3_module geopolyModule = {
+ 2, /* iVersion */
+ geopolyCreate, /* xCreate - create a table */
+ geopolyConnect, /* xConnect - connect to an existing table */
+ geopolyBestIndex, /* xBestIndex - Determine search strategy */
+ rtreeDisconnect, /* xDisconnect - Disconnect from a table */
+ rtreeDestroy, /* xDestroy - Drop a table */
+ rtreeOpen, /* xOpen - open a cursor */
+ rtreeClose, /* xClose - close a cursor */
+ geopolyFilter, /* xFilter - configure scan constraints */
+ rtreeNext, /* xNext - advance a cursor */
+ rtreeEof, /* xEof */
+ geopolyColumn, /* xColumn - read data */
+ rtreeRowid, /* xRowid - read data */
+ geopolyUpdate, /* xUpdate - write data */
+ rtreeBeginTransaction, /* xBegin - begin transaction */
+ rtreeEndTransaction, /* xSync - sync transaction */
+ rtreeEndTransaction, /* xCommit - commit transaction */
+ rtreeEndTransaction, /* xRollback - rollback transaction */
+ geopolyFindFunction, /* xFindFunction - function overloading */
+ rtreeRename, /* xRename - rename the table */
+ rtreeSavepoint, /* xSavepoint */
+ 0, /* xRelease */
+ 0, /* xRollbackTo */
+};
+
+static int sqlite3_geopoly_init(sqlite3 *db){
+ int rc = SQLITE_OK;
+ static const struct {
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
+ int nArg;
+ const char *zName;
+ } aFunc[] = {
+ { geopolyAreaFunc, 1, "geopoly_area" },
+ { geopolyBlobFunc, 1, "geopoly_blob" },
+ { geopolyJsonFunc, 1, "geopoly_json" },
+ { geopolySvgFunc, -1, "geopoly_svg" },
+ { geopolyWithinFunc, 2, "geopoly_within" },
+ { geopolyContainsPointFunc, 3, "geopoly_contains_point" },
+ { geopolyOverlapFunc, 2, "geopoly_overlap" },
+ { geopolyDebugFunc, 1, "geopoly_debug" },
+ { geopolyBBoxFunc, 1, "geopoly_bbox" },
+ { geopolyXformFunc, 7, "geopoly_xform" },
+ };
+ static const struct {
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**);
+ void (*xFinal)(sqlite3_context*);
+ const char *zName;
+ } aAgg[] = {
+ { geopolyBBoxStep, geopolyBBoxFinal, "geopoly_group_bbox" },
+ };
+ int i;
+ for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
+ rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg,
+ SQLITE_UTF8, 0,
+ aFunc[i].xFunc, 0, 0);
+ }
+ for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){
+ rc = sqlite3_create_function(db, aAgg[i].zName, 1, SQLITE_UTF8, 0,
+ 0, aAgg[i].xStep, aAgg[i].xFinal);
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_create_module_v2(db, "geopoly", &geopolyModule, 0, 0);
+ }
+ return rc;
+}
+
+/************** End of geopoly.c *********************************************/
+/************** Continuing where we left off in rtree.c **********************/
+#endif
/*
** Register the r-tree module with database handle db. This creates the
@@ -174771,6 +184017,11 @@ SQLITE_PRIVATE int sqlite3RtreeInit(sqlite3 *db){
void *c = (void *)RTREE_COORD_INT32;
rc = sqlite3_create_module_v2(db, "rtree_i32", &rtreeModule, c, 0);
}
+#ifdef SQLITE_ENABLE_GEOPOLY
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_geopoly_init(db);
+ }
+#endif
return rc;
}
@@ -182311,7 +191562,7 @@ static int dbpageBegin(sqlite3_vtab *pVtab){
int i;
for(i=0; i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
- if( pBt ) sqlite3BtreeBeginTrans(pBt, 1);
+ if( pBt ) sqlite3BtreeBeginTrans(pBt, 1, 0);
}
return SQLITE_OK;
}
@@ -187733,2436 +196984,6 @@ SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p){
#endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */
/************** End of sqlite3session.c **************************************/
-/************** Begin file json1.c *******************************************/
-/*
-** 2015-08-12
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-******************************************************************************
-**
-** This SQLite extension implements JSON functions. The interface is
-** modeled after MySQL JSON functions:
-**
-** https://dev.mysql.com/doc/refman/5.7/en/json.html
-**
-** For the time being, all JSON is stored as pure text. (We might add
-** a JSONB type in the future which stores a binary encoding of JSON in
-** a BLOB, but there is no support for JSONB in the current implementation.
-** This implementation parses JSON text at 250 MB/s, so it is hard to see
-** how JSONB might improve on that.)
-*/
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1)
-#if !defined(SQLITEINT_H)
-/* #include "sqlite3ext.h" */
-#endif
-SQLITE_EXTENSION_INIT1
-/* #include <assert.h> */
-/* #include <string.h> */
-/* #include <stdlib.h> */
-/* #include <stdarg.h> */
-
-/* Mark a function parameter as unused, to suppress nuisance compiler
-** warnings. */
-#ifndef UNUSED_PARAM
-# define UNUSED_PARAM(X) (void)(X)
-#endif
-
-#ifndef LARGEST_INT64
-# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
-# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
-#endif
-
-/*
-** Versions of isspace(), isalnum() and isdigit() to which it is safe
-** to pass signed char values.
-*/
-#ifdef sqlite3Isdigit
- /* Use the SQLite core versions if this routine is part of the
- ** SQLite amalgamation */
-# define safe_isdigit(x) sqlite3Isdigit(x)
-# define safe_isalnum(x) sqlite3Isalnum(x)
-# define safe_isxdigit(x) sqlite3Isxdigit(x)
-#else
- /* Use the standard library for separate compilation */
-#include <ctype.h> /* amalgamator: keep */
-# define safe_isdigit(x) isdigit((unsigned char)(x))
-# define safe_isalnum(x) isalnum((unsigned char)(x))
-# define safe_isxdigit(x) isxdigit((unsigned char)(x))
-#endif
-
-/*
-** Growing our own isspace() routine this way is twice as fast as
-** the library isspace() function, resulting in a 7% overall performance
-** increase for the parser. (Ubuntu14.10 gcc 4.8.4 x64 with -Os).
-*/
-static const char jsonIsSpace[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-#define safe_isspace(x) (jsonIsSpace[(unsigned char)x])
-
-#ifndef SQLITE_AMALGAMATION
- /* Unsigned integer types. These are already defined in the sqliteInt.h,
- ** but the definitions need to be repeated for separate compilation. */
- typedef sqlite3_uint64 u64;
- typedef unsigned int u32;
- typedef unsigned short int u16;
- typedef unsigned char u8;
-#endif
-
-/* Objects */
-typedef struct JsonString JsonString;
-typedef struct JsonNode JsonNode;
-typedef struct JsonParse JsonParse;
-
-/* An instance of this object represents a JSON string
-** under construction. Really, this is a generic string accumulator
-** that can be and is used to create strings other than JSON.
-*/
-struct JsonString {
- sqlite3_context *pCtx; /* Function context - put error messages here */
- char *zBuf; /* Append JSON content here */
- u64 nAlloc; /* Bytes of storage available in zBuf[] */
- u64 nUsed; /* Bytes of zBuf[] currently used */
- u8 bStatic; /* True if zBuf is static space */
- u8 bErr; /* True if an error has been encountered */
- char zSpace[100]; /* Initial static space */
-};
-
-/* JSON type values
-*/
-#define JSON_NULL 0
-#define JSON_TRUE 1
-#define JSON_FALSE 2
-#define JSON_INT 3
-#define JSON_REAL 4
-#define JSON_STRING 5
-#define JSON_ARRAY 6
-#define JSON_OBJECT 7
-
-/* The "subtype" set for JSON values */
-#define JSON_SUBTYPE 74 /* Ascii for "J" */
-
-/*
-** Names of the various JSON types:
-*/
-static const char * const jsonType[] = {
- "null", "true", "false", "integer", "real", "text", "array", "object"
-};
-
-/* Bit values for the JsonNode.jnFlag field
-*/
-#define JNODE_RAW 0x01 /* Content is raw, not JSON encoded */
-#define JNODE_ESCAPE 0x02 /* Content is text with \ escapes */
-#define JNODE_REMOVE 0x04 /* Do not output */
-#define JNODE_REPLACE 0x08 /* Replace with JsonNode.u.iReplace */
-#define JNODE_PATCH 0x10 /* Patch with JsonNode.u.pPatch */
-#define JNODE_APPEND 0x20 /* More ARRAY/OBJECT entries at u.iAppend */
-#define JNODE_LABEL 0x40 /* Is a label of an object */
-
-
-/* A single node of parsed JSON
-*/
-struct JsonNode {
- u8 eType; /* One of the JSON_ type values */
- u8 jnFlags; /* JNODE flags */
- u32 n; /* Bytes of content, or number of sub-nodes */
- union {
- const char *zJContent; /* Content for INT, REAL, and STRING */
- u32 iAppend; /* More terms for ARRAY and OBJECT */
- u32 iKey; /* Key for ARRAY objects in json_tree() */
- u32 iReplace; /* Replacement content for JNODE_REPLACE */
- JsonNode *pPatch; /* Node chain of patch for JNODE_PATCH */
- } u;
-};
-
-/* A completely parsed JSON string
-*/
-struct JsonParse {
- u32 nNode; /* Number of slots of aNode[] used */
- u32 nAlloc; /* Number of slots of aNode[] allocated */
- JsonNode *aNode; /* Array of nodes containing the parse */
- const char *zJson; /* Original JSON string */
- u32 *aUp; /* Index of parent of each node */
- u8 oom; /* Set to true if out of memory */
- u8 nErr; /* Number of errors seen */
- u16 iDepth; /* Nesting depth */
- int nJson; /* Length of the zJson string in bytes */
-};
-
-/*
-** Maximum nesting depth of JSON for this implementation.
-**
-** This limit is needed to avoid a stack overflow in the recursive
-** descent parser. A depth of 2000 is far deeper than any sane JSON
-** should go.
-*/
-#define JSON_MAX_DEPTH 2000
-
-/**************************************************************************
-** Utility routines for dealing with JsonString objects
-**************************************************************************/
-
-/* Set the JsonString object to an empty string
-*/
-static void jsonZero(JsonString *p){
- p->zBuf = p->zSpace;
- p->nAlloc = sizeof(p->zSpace);
- p->nUsed = 0;
- p->bStatic = 1;
-}
-
-/* Initialize the JsonString object
-*/
-static void jsonInit(JsonString *p, sqlite3_context *pCtx){
- p->pCtx = pCtx;
- p->bErr = 0;
- jsonZero(p);
-}
-
-
-/* Free all allocated memory and reset the JsonString object back to its
-** initial state.
-*/
-static void jsonReset(JsonString *p){
- if( !p->bStatic ) sqlite3_free(p->zBuf);
- jsonZero(p);
-}
-
-
-/* Report an out-of-memory (OOM) condition
-*/
-static void jsonOom(JsonString *p){
- p->bErr = 1;
- sqlite3_result_error_nomem(p->pCtx);
- jsonReset(p);
-}
-
-/* Enlarge pJson->zBuf so that it can hold at least N more bytes.
-** Return zero on success. Return non-zero on an OOM error
-*/
-static int jsonGrow(JsonString *p, u32 N){
- u64 nTotal = N<p->nAlloc ? p->nAlloc*2 : p->nAlloc+N+10;
- char *zNew;
- if( p->bStatic ){
- if( p->bErr ) return 1;
- zNew = sqlite3_malloc64(nTotal);
- if( zNew==0 ){
- jsonOom(p);
- return SQLITE_NOMEM;
- }
- memcpy(zNew, p->zBuf, (size_t)p->nUsed);
- p->zBuf = zNew;
- p->bStatic = 0;
- }else{
- zNew = sqlite3_realloc64(p->zBuf, nTotal);
- if( zNew==0 ){
- jsonOom(p);
- return SQLITE_NOMEM;
- }
- p->zBuf = zNew;
- }
- p->nAlloc = nTotal;
- return SQLITE_OK;
-}
-
-/* Append N bytes from zIn onto the end of the JsonString string.
-*/
-static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){
- if( (N+p->nUsed >= p->nAlloc) && jsonGrow(p,N)!=0 ) return;
- memcpy(p->zBuf+p->nUsed, zIn, N);
- p->nUsed += N;
-}
-
-/* Append formatted text (not to exceed N bytes) to the JsonString.
-*/
-static void jsonPrintf(int N, JsonString *p, const char *zFormat, ...){
- va_list ap;
- if( (p->nUsed + N >= p->nAlloc) && jsonGrow(p, N) ) return;
- va_start(ap, zFormat);
- sqlite3_vsnprintf(N, p->zBuf+p->nUsed, zFormat, ap);
- va_end(ap);
- p->nUsed += (int)strlen(p->zBuf+p->nUsed);
-}
-
-/* Append a single character
-*/
-static void jsonAppendChar(JsonString *p, char c){
- if( p->nUsed>=p->nAlloc && jsonGrow(p,1)!=0 ) return;
- p->zBuf[p->nUsed++] = c;
-}
-
-/* Append a comma separator to the output buffer, if the previous
-** character is not '[' or '{'.
-*/
-static void jsonAppendSeparator(JsonString *p){
- char c;
- if( p->nUsed==0 ) return;
- c = p->zBuf[p->nUsed-1];
- if( c!='[' && c!='{' ) jsonAppendChar(p, ',');
-}
-
-/* Append the N-byte string in zIn to the end of the JsonString string
-** under construction. Enclose the string in "..." and escape
-** any double-quotes or backslash characters contained within the
-** string.
-*/
-static void jsonAppendString(JsonString *p, const char *zIn, u32 N){
- u32 i;
- if( (N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0 ) return;
- p->zBuf[p->nUsed++] = '"';
- for(i=0; i<N; i++){
- unsigned char c = ((unsigned const char*)zIn)[i];
- if( c=='"' || c=='\\' ){
- json_simple_escape:
- if( (p->nUsed+N+3-i > p->nAlloc) && jsonGrow(p,N+3-i)!=0 ) return;
- p->zBuf[p->nUsed++] = '\\';
- }else if( c<=0x1f ){
- static const char aSpecial[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
- assert( sizeof(aSpecial)==32 );
- assert( aSpecial['\b']=='b' );
- assert( aSpecial['\f']=='f' );
- assert( aSpecial['\n']=='n' );
- assert( aSpecial['\r']=='r' );
- assert( aSpecial['\t']=='t' );
- if( aSpecial[c] ){
- c = aSpecial[c];
- goto json_simple_escape;
- }
- if( (p->nUsed+N+7+i > p->nAlloc) && jsonGrow(p,N+7-i)!=0 ) return;
- p->zBuf[p->nUsed++] = '\\';
- p->zBuf[p->nUsed++] = 'u';
- p->zBuf[p->nUsed++] = '0';
- p->zBuf[p->nUsed++] = '0';
- p->zBuf[p->nUsed++] = '0' + (c>>4);
- c = "0123456789abcdef"[c&0xf];
- }
- p->zBuf[p->nUsed++] = c;
- }
- p->zBuf[p->nUsed++] = '"';
- assert( p->nUsed<p->nAlloc );
-}
-
-/*
-** Append a function parameter value to the JSON string under
-** construction.
-*/
-static void jsonAppendValue(
- JsonString *p, /* Append to this JSON string */
- sqlite3_value *pValue /* Value to append */
-){
- switch( sqlite3_value_type(pValue) ){
- case SQLITE_NULL: {
- jsonAppendRaw(p, "null", 4);
- break;
- }
- case SQLITE_INTEGER:
- case SQLITE_FLOAT: {
- const char *z = (const char*)sqlite3_value_text(pValue);
- u32 n = (u32)sqlite3_value_bytes(pValue);
- jsonAppendRaw(p, z, n);
- break;
- }
- case SQLITE_TEXT: {
- const char *z = (const char*)sqlite3_value_text(pValue);
- u32 n = (u32)sqlite3_value_bytes(pValue);
- if( sqlite3_value_subtype(pValue)==JSON_SUBTYPE ){
- jsonAppendRaw(p, z, n);
- }else{
- jsonAppendString(p, z, n);
- }
- break;
- }
- default: {
- if( p->bErr==0 ){
- sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1);
- p->bErr = 2;
- jsonReset(p);
- }
- break;
- }
- }
-}
-
-
-/* Make the JSON in p the result of the SQL function.
-*/
-static void jsonResult(JsonString *p){
- if( p->bErr==0 ){
- sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed,
- p->bStatic ? SQLITE_TRANSIENT : sqlite3_free,
- SQLITE_UTF8);
- jsonZero(p);
- }
- assert( p->bStatic );
-}
-
-/**************************************************************************
-** Utility routines for dealing with JsonNode and JsonParse objects
-**************************************************************************/
-
-/*
-** Return the number of consecutive JsonNode slots need to represent
-** the parsed JSON at pNode. The minimum answer is 1. For ARRAY and
-** OBJECT types, the number might be larger.
-**
-** Appended elements are not counted. The value returned is the number
-** by which the JsonNode counter should increment in order to go to the
-** next peer value.
-*/
-static u32 jsonNodeSize(JsonNode *pNode){
- return pNode->eType>=JSON_ARRAY ? pNode->n+1 : 1;
-}
-
-/*
-** Reclaim all memory allocated by a JsonParse object. But do not
-** delete the JsonParse object itself.
-*/
-static void jsonParseReset(JsonParse *pParse){
- sqlite3_free(pParse->aNode);
- pParse->aNode = 0;
- pParse->nNode = 0;
- pParse->nAlloc = 0;
- sqlite3_free(pParse->aUp);
- pParse->aUp = 0;
-}
-
-/*
-** Free a JsonParse object that was obtained from sqlite3_malloc().
-*/
-static void jsonParseFree(JsonParse *pParse){
- jsonParseReset(pParse);
- sqlite3_free(pParse);
-}
-
-/*
-** Convert the JsonNode pNode into a pure JSON string and
-** append to pOut. Subsubstructure is also included. Return
-** the number of JsonNode objects that are encoded.
-*/
-static void jsonRenderNode(
- JsonNode *pNode, /* The node to render */
- JsonString *pOut, /* Write JSON here */
- sqlite3_value **aReplace /* Replacement values */
-){
- if( pNode->jnFlags & (JNODE_REPLACE|JNODE_PATCH) ){
- if( pNode->jnFlags & JNODE_REPLACE ){
- jsonAppendValue(pOut, aReplace[pNode->u.iReplace]);
- return;
- }
- pNode = pNode->u.pPatch;
- }
- switch( pNode->eType ){
- default: {
- assert( pNode->eType==JSON_NULL );
- jsonAppendRaw(pOut, "null", 4);
- break;
- }
- case JSON_TRUE: {
- jsonAppendRaw(pOut, "true", 4);
- break;
- }
- case JSON_FALSE: {
- jsonAppendRaw(pOut, "false", 5);
- break;
- }
- case JSON_STRING: {
- if( pNode->jnFlags & JNODE_RAW ){
- jsonAppendString(pOut, pNode->u.zJContent, pNode->n);
- break;
- }
- /* Fall through into the next case */
- }
- case JSON_REAL:
- case JSON_INT: {
- jsonAppendRaw(pOut, pNode->u.zJContent, pNode->n);
- break;
- }
- case JSON_ARRAY: {
- u32 j = 1;
- jsonAppendChar(pOut, '[');
- for(;;){
- while( j<=pNode->n ){
- if( (pNode[j].jnFlags & JNODE_REMOVE)==0 ){
- jsonAppendSeparator(pOut);
- jsonRenderNode(&pNode[j], pOut, aReplace);
- }
- j += jsonNodeSize(&pNode[j]);
- }
- if( (pNode->jnFlags & JNODE_APPEND)==0 ) break;
- pNode = &pNode[pNode->u.iAppend];
- j = 1;
- }
- jsonAppendChar(pOut, ']');
- break;
- }
- case JSON_OBJECT: {
- u32 j = 1;
- jsonAppendChar(pOut, '{');
- for(;;){
- while( j<=pNode->n ){
- if( (pNode[j+1].jnFlags & JNODE_REMOVE)==0 ){
- jsonAppendSeparator(pOut);
- jsonRenderNode(&pNode[j], pOut, aReplace);
- jsonAppendChar(pOut, ':');
- jsonRenderNode(&pNode[j+1], pOut, aReplace);
- }
- j += 1 + jsonNodeSize(&pNode[j+1]);
- }
- if( (pNode->jnFlags & JNODE_APPEND)==0 ) break;
- pNode = &pNode[pNode->u.iAppend];
- j = 1;
- }
- jsonAppendChar(pOut, '}');
- break;
- }
- }
-}
-
-/*
-** Return a JsonNode and all its descendents as a JSON string.
-*/
-static void jsonReturnJson(
- JsonNode *pNode, /* Node to return */
- sqlite3_context *pCtx, /* Return value for this function */
- sqlite3_value **aReplace /* Array of replacement values */
-){
- JsonString s;
- jsonInit(&s, pCtx);
- jsonRenderNode(pNode, &s, aReplace);
- jsonResult(&s);
- sqlite3_result_subtype(pCtx, JSON_SUBTYPE);
-}
-
-/*
-** Make the JsonNode the return value of the function.
-*/
-static void jsonReturn(
- JsonNode *pNode, /* Node to return */
- sqlite3_context *pCtx, /* Return value for this function */
- sqlite3_value **aReplace /* Array of replacement values */
-){
- switch( pNode->eType ){
- default: {
- assert( pNode->eType==JSON_NULL );
- sqlite3_result_null(pCtx);
- break;
- }
- case JSON_TRUE: {
- sqlite3_result_int(pCtx, 1);
- break;
- }
- case JSON_FALSE: {
- sqlite3_result_int(pCtx, 0);
- break;
- }
- case JSON_INT: {
- sqlite3_int64 i = 0;
- const char *z = pNode->u.zJContent;
- if( z[0]=='-' ){ z++; }
- while( z[0]>='0' && z[0]<='9' ){
- unsigned v = *(z++) - '0';
- if( i>=LARGEST_INT64/10 ){
- if( i>LARGEST_INT64/10 ) goto int_as_real;
- if( z[0]>='0' && z[0]<='9' ) goto int_as_real;
- if( v==9 ) goto int_as_real;
- if( v==8 ){
- if( pNode->u.zJContent[0]=='-' ){
- sqlite3_result_int64(pCtx, SMALLEST_INT64);
- goto int_done;
- }else{
- goto int_as_real;
- }
- }
- }
- i = i*10 + v;
- }
- if( pNode->u.zJContent[0]=='-' ){ i = -i; }
- sqlite3_result_int64(pCtx, i);
- int_done:
- break;
- int_as_real: /* fall through to real */;
- }
- case JSON_REAL: {
- double r;
-#ifdef SQLITE_AMALGAMATION
- const char *z = pNode->u.zJContent;
- sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8);
-#else
- r = strtod(pNode->u.zJContent, 0);
-#endif
- sqlite3_result_double(pCtx, r);
- break;
- }
- case JSON_STRING: {
-#if 0 /* Never happens because JNODE_RAW is only set by json_set(),
- ** json_insert() and json_replace() and those routines do not
- ** call jsonReturn() */
- if( pNode->jnFlags & JNODE_RAW ){
- sqlite3_result_text(pCtx, pNode->u.zJContent, pNode->n,
- SQLITE_TRANSIENT);
- }else
-#endif
- assert( (pNode->jnFlags & JNODE_RAW)==0 );
- if( (pNode->jnFlags & JNODE_ESCAPE)==0 ){
- /* JSON formatted without any backslash-escapes */
- sqlite3_result_text(pCtx, pNode->u.zJContent+1, pNode->n-2,
- SQLITE_TRANSIENT);
- }else{
- /* Translate JSON formatted string into raw text */
- u32 i;
- u32 n = pNode->n;
- const char *z = pNode->u.zJContent;
- char *zOut;
- u32 j;
- zOut = sqlite3_malloc( n+1 );
- if( zOut==0 ){
- sqlite3_result_error_nomem(pCtx);
- break;
- }
- for(i=1, j=0; i<n-1; i++){
- char c = z[i];
- if( c!='\\' ){
- zOut[j++] = c;
- }else{
- c = z[++i];
- if( c=='u' ){
- u32 v = 0, k;
- for(k=0; k<4; i++, k++){
- assert( i<n-2 );
- c = z[i+1];
- assert( safe_isxdigit(c) );
- if( c<='9' ) v = v*16 + c - '0';
- else if( c<='F' ) v = v*16 + c - 'A' + 10;
- else v = v*16 + c - 'a' + 10;
- }
- if( v==0 ) break;
- if( v<=0x7f ){
- zOut[j++] = (char)v;
- }else if( v<=0x7ff ){
- zOut[j++] = (char)(0xc0 | (v>>6));
- zOut[j++] = 0x80 | (v&0x3f);
- }else{
- zOut[j++] = (char)(0xe0 | (v>>12));
- zOut[j++] = 0x80 | ((v>>6)&0x3f);
- zOut[j++] = 0x80 | (v&0x3f);
- }
- }else{
- if( c=='b' ){
- c = '\b';
- }else if( c=='f' ){
- c = '\f';
- }else if( c=='n' ){
- c = '\n';
- }else if( c=='r' ){
- c = '\r';
- }else if( c=='t' ){
- c = '\t';
- }
- zOut[j++] = c;
- }
- }
- }
- zOut[j] = 0;
- sqlite3_result_text(pCtx, zOut, j, sqlite3_free);
- }
- break;
- }
- case JSON_ARRAY:
- case JSON_OBJECT: {
- jsonReturnJson(pNode, pCtx, aReplace);
- break;
- }
- }
-}
-
-/* Forward reference */
-static int jsonParseAddNode(JsonParse*,u32,u32,const char*);
-
-/*
-** A macro to hint to the compiler that a function should not be
-** inlined.
-*/
-#if defined(__GNUC__)
-# define JSON_NOINLINE __attribute__((noinline))
-#elif defined(_MSC_VER) && _MSC_VER>=1310
-# define JSON_NOINLINE __declspec(noinline)
-#else
-# define JSON_NOINLINE
-#endif
-
-
-static JSON_NOINLINE int jsonParseAddNodeExpand(
- JsonParse *pParse, /* Append the node to this object */
- u32 eType, /* Node type */
- u32 n, /* Content size or sub-node count */
- const char *zContent /* Content */
-){
- u32 nNew;
- JsonNode *pNew;
- assert( pParse->nNode>=pParse->nAlloc );
- if( pParse->oom ) return -1;
- nNew = pParse->nAlloc*2 + 10;
- pNew = sqlite3_realloc(pParse->aNode, sizeof(JsonNode)*nNew);
- if( pNew==0 ){
- pParse->oom = 1;
- return -1;
- }
- pParse->nAlloc = nNew;
- pParse->aNode = pNew;
- assert( pParse->nNode<pParse->nAlloc );
- return jsonParseAddNode(pParse, eType, n, zContent);
-}
-
-/*
-** Create a new JsonNode instance based on the arguments and append that
-** instance to the JsonParse. Return the index in pParse->aNode[] of the
-** new node, or -1 if a memory allocation fails.
-*/
-static int jsonParseAddNode(
- JsonParse *pParse, /* Append the node to this object */
- u32 eType, /* Node type */
- u32 n, /* Content size or sub-node count */
- const char *zContent /* Content */
-){
- JsonNode *p;
- if( pParse->nNode>=pParse->nAlloc ){
- return jsonParseAddNodeExpand(pParse, eType, n, zContent);
- }
- p = &pParse->aNode[pParse->nNode];
- p->eType = (u8)eType;
- p->jnFlags = 0;
- p->n = n;
- p->u.zJContent = zContent;
- return pParse->nNode++;
-}
-
-/*
-** Return true if z[] begins with 4 (or more) hexadecimal digits
-*/
-static int jsonIs4Hex(const char *z){
- int i;
- for(i=0; i<4; i++) if( !safe_isxdigit(z[i]) ) return 0;
- return 1;
-}
-
-/*
-** Parse a single JSON value which begins at pParse->zJson[i]. Return the
-** index of the first character past the end of the value parsed.
-**
-** Return negative for a syntax error. Special cases: return -2 if the
-** first non-whitespace character is '}' and return -3 if the first
-** non-whitespace character is ']'.
-*/
-static int jsonParseValue(JsonParse *pParse, u32 i){
- char c;
- u32 j;
- int iThis;
- int x;
- JsonNode *pNode;
- const char *z = pParse->zJson;
- while( safe_isspace(z[i]) ){ i++; }
- if( (c = z[i])=='{' ){
- /* Parse object */
- iThis = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0);
- if( iThis<0 ) return -1;
- for(j=i+1;;j++){
- while( safe_isspace(z[j]) ){ j++; }
- if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1;
- x = jsonParseValue(pParse, j);
- if( x<0 ){
- pParse->iDepth--;
- if( x==(-2) && pParse->nNode==(u32)iThis+1 ) return j+1;
- return -1;
- }
- if( pParse->oom ) return -1;
- pNode = &pParse->aNode[pParse->nNode-1];
- if( pNode->eType!=JSON_STRING ) return -1;
- pNode->jnFlags |= JNODE_LABEL;
- j = x;
- while( safe_isspace(z[j]) ){ j++; }
- if( z[j]!=':' ) return -1;
- j++;
- x = jsonParseValue(pParse, j);
- pParse->iDepth--;
- if( x<0 ) return -1;
- j = x;
- while( safe_isspace(z[j]) ){ j++; }
- c = z[j];
- if( c==',' ) continue;
- if( c!='}' ) return -1;
- break;
- }
- pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1;
- return j+1;
- }else if( c=='[' ){
- /* Parse array */
- iThis = jsonParseAddNode(pParse, JSON_ARRAY, 0, 0);
- if( iThis<0 ) return -1;
- for(j=i+1;;j++){
- while( safe_isspace(z[j]) ){ j++; }
- if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1;
- x = jsonParseValue(pParse, j);
- pParse->iDepth--;
- if( x<0 ){
- if( x==(-3) && pParse->nNode==(u32)iThis+1 ) return j+1;
- return -1;
- }
- j = x;
- while( safe_isspace(z[j]) ){ j++; }
- c = z[j];
- if( c==',' ) continue;
- if( c!=']' ) return -1;
- break;
- }
- pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1;
- return j+1;
- }else if( c=='"' ){
- /* Parse string */
- u8 jnFlags = 0;
- j = i+1;
- for(;;){
- c = z[j];
- if( (c & ~0x1f)==0 ){
- /* Control characters are not allowed in strings */
- return -1;
- }
- if( c=='\\' ){
- c = z[++j];
- if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f'
- || c=='n' || c=='r' || c=='t'
- || (c=='u' && jsonIs4Hex(z+j+1)) ){
- jnFlags = JNODE_ESCAPE;
- }else{
- return -1;
- }
- }else if( c=='"' ){
- break;
- }
- j++;
- }
- jsonParseAddNode(pParse, JSON_STRING, j+1-i, &z[i]);
- if( !pParse->oom ) pParse->aNode[pParse->nNode-1].jnFlags = jnFlags;
- return j+1;
- }else if( c=='n'
- && strncmp(z+i,"null",4)==0
- && !safe_isalnum(z[i+4]) ){
- jsonParseAddNode(pParse, JSON_NULL, 0, 0);
- return i+4;
- }else if( c=='t'
- && strncmp(z+i,"true",4)==0
- && !safe_isalnum(z[i+4]) ){
- jsonParseAddNode(pParse, JSON_TRUE, 0, 0);
- return i+4;
- }else if( c=='f'
- && strncmp(z+i,"false",5)==0
- && !safe_isalnum(z[i+5]) ){
- jsonParseAddNode(pParse, JSON_FALSE, 0, 0);
- return i+5;
- }else if( c=='-' || (c>='0' && c<='9') ){
- /* Parse number */
- u8 seenDP = 0;
- u8 seenE = 0;
- assert( '-' < '0' );
- if( c<='0' ){
- j = c=='-' ? i+1 : i;
- if( z[j]=='0' && z[j+1]>='0' && z[j+1]<='9' ) return -1;
- }
- j = i+1;
- for(;; j++){
- c = z[j];
- if( c>='0' && c<='9' ) continue;
- if( c=='.' ){
- if( z[j-1]=='-' ) return -1;
- if( seenDP ) return -1;
- seenDP = 1;
- continue;
- }
- if( c=='e' || c=='E' ){
- if( z[j-1]<'0' ) return -1;
- if( seenE ) return -1;
- seenDP = seenE = 1;
- c = z[j+1];
- if( c=='+' || c=='-' ){
- j++;
- c = z[j+1];
- }
- if( c<'0' || c>'9' ) return -1;
- continue;
- }
- break;
- }
- if( z[j-1]<'0' ) return -1;
- jsonParseAddNode(pParse, seenDP ? JSON_REAL : JSON_INT,
- j - i, &z[i]);
- return j;
- }else if( c=='}' ){
- return -2; /* End of {...} */
- }else if( c==']' ){
- return -3; /* End of [...] */
- }else if( c==0 ){
- return 0; /* End of file */
- }else{
- return -1; /* Syntax error */
- }
-}
-
-/*
-** Parse a complete JSON string. Return 0 on success or non-zero if there
-** are any errors. If an error occurs, free all memory associated with
-** pParse.
-**
-** pParse is uninitialized when this routine is called.
-*/
-static int jsonParse(
- JsonParse *pParse, /* Initialize and fill this JsonParse object */
- sqlite3_context *pCtx, /* Report errors here */
- const char *zJson /* Input JSON text to be parsed */
-){
- int i;
- memset(pParse, 0, sizeof(*pParse));
- if( zJson==0 ) return 1;
- pParse->zJson = zJson;
- i = jsonParseValue(pParse, 0);
- if( pParse->oom ) i = -1;
- if( i>0 ){
- assert( pParse->iDepth==0 );
- while( safe_isspace(zJson[i]) ) i++;
- if( zJson[i] ) i = -1;
- }
- if( i<=0 ){
- if( pCtx!=0 ){
- if( pParse->oom ){
- sqlite3_result_error_nomem(pCtx);
- }else{
- sqlite3_result_error(pCtx, "malformed JSON", -1);
- }
- }
- jsonParseReset(pParse);
- return 1;
- }
- return 0;
-}
-
-/* Mark node i of pParse as being a child of iParent. Call recursively
-** to fill in all the descendants of node i.
-*/
-static void jsonParseFillInParentage(JsonParse *pParse, u32 i, u32 iParent){
- JsonNode *pNode = &pParse->aNode[i];
- u32 j;
- pParse->aUp[i] = iParent;
- switch( pNode->eType ){
- case JSON_ARRAY: {
- for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j)){
- jsonParseFillInParentage(pParse, i+j, i);
- }
- break;
- }
- case JSON_OBJECT: {
- for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j+1)+1){
- pParse->aUp[i+j] = i;
- jsonParseFillInParentage(pParse, i+j+1, i);
- }
- break;
- }
- default: {
- break;
- }
- }
-}
-
-/*
-** Compute the parentage of all nodes in a completed parse.
-*/
-static int jsonParseFindParents(JsonParse *pParse){
- u32 *aUp;
- assert( pParse->aUp==0 );
- aUp = pParse->aUp = sqlite3_malloc( sizeof(u32)*pParse->nNode );
- if( aUp==0 ){
- pParse->oom = 1;
- return SQLITE_NOMEM;
- }
- jsonParseFillInParentage(pParse, 0, 0);
- return SQLITE_OK;
-}
-
-/*
-** Magic number used for the JSON parse cache in sqlite3_get_auxdata()
-*/
-#define JSON_CACHE_ID (-429938)
-
-/*
-** Obtain a complete parse of the JSON found in the first argument
-** of the argv array. Use the sqlite3_get_auxdata() cache for this
-** parse if it is available. If the cache is not available or if it
-** is no longer valid, parse the JSON again and return the new parse,
-** and also register the new parse so that it will be available for
-** future sqlite3_get_auxdata() calls.
-*/
-static JsonParse *jsonParseCached(
- sqlite3_context *pCtx,
- sqlite3_value **argv
-){
- const char *zJson = (const char*)sqlite3_value_text(argv[0]);
- int nJson = sqlite3_value_bytes(argv[0]);
- JsonParse *p;
- if( zJson==0 ) return 0;
- p = (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID);
- if( p && p->nJson==nJson && memcmp(p->zJson,zJson,nJson)==0 ){
- p->nErr = 0;
- return p; /* The cached entry matches, so return it */
- }
- p = sqlite3_malloc( sizeof(*p) + nJson + 1 );
- if( p==0 ){
- sqlite3_result_error_nomem(pCtx);
- return 0;
- }
- memset(p, 0, sizeof(*p));
- p->zJson = (char*)&p[1];
- memcpy((char*)p->zJson, zJson, nJson+1);
- if( jsonParse(p, pCtx, p->zJson) ){
- sqlite3_free(p);
- return 0;
- }
- p->nJson = nJson;
- sqlite3_set_auxdata(pCtx, JSON_CACHE_ID, p, (void(*)(void*))jsonParseFree);
- return (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID);
-}
-
-/*
-** Compare the OBJECT label at pNode against zKey,nKey. Return true on
-** a match.
-*/
-static int jsonLabelCompare(JsonNode *pNode, const char *zKey, u32 nKey){
- if( pNode->jnFlags & JNODE_RAW ){
- if( pNode->n!=nKey ) return 0;
- return strncmp(pNode->u.zJContent, zKey, nKey)==0;
- }else{
- if( pNode->n!=nKey+2 ) return 0;
- return strncmp(pNode->u.zJContent+1, zKey, nKey)==0;
- }
-}
-
-/* forward declaration */
-static JsonNode *jsonLookupAppend(JsonParse*,const char*,int*,const char**);
-
-/*
-** Search along zPath to find the node specified. Return a pointer
-** to that node, or NULL if zPath is malformed or if there is no such
-** node.
-**
-** If pApnd!=0, then try to append new nodes to complete zPath if it is
-** possible to do so and if no existing node corresponds to zPath. If
-** new nodes are appended *pApnd is set to 1.
-*/
-static JsonNode *jsonLookupStep(
- JsonParse *pParse, /* The JSON to search */
- u32 iRoot, /* Begin the search at this node */
- const char *zPath, /* The path to search */
- int *pApnd, /* Append nodes to complete path if not NULL */
- const char **pzErr /* Make *pzErr point to any syntax error in zPath */
-){
- u32 i, j, nKey;
- const char *zKey;
- JsonNode *pRoot = &pParse->aNode[iRoot];
- if( zPath[0]==0 ) return pRoot;
- if( zPath[0]=='.' ){
- if( pRoot->eType!=JSON_OBJECT ) return 0;
- zPath++;
- if( zPath[0]=='"' ){
- zKey = zPath + 1;
- for(i=1; zPath[i] && zPath[i]!='"'; i++){}
- nKey = i-1;
- if( zPath[i] ){
- i++;
- }else{
- *pzErr = zPath;
- return 0;
- }
- }else{
- zKey = zPath;
- for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){}
- nKey = i;
- }
- if( nKey==0 ){
- *pzErr = zPath;
- return 0;
- }
- j = 1;
- for(;;){
- while( j<=pRoot->n ){
- if( jsonLabelCompare(pRoot+j, zKey, nKey) ){
- return jsonLookupStep(pParse, iRoot+j+1, &zPath[i], pApnd, pzErr);
- }
- j++;
- j += jsonNodeSize(&pRoot[j]);
- }
- if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break;
- iRoot += pRoot->u.iAppend;
- pRoot = &pParse->aNode[iRoot];
- j = 1;
- }
- if( pApnd ){
- u32 iStart, iLabel;
- JsonNode *pNode;
- iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0);
- iLabel = jsonParseAddNode(pParse, JSON_STRING, i, zPath);
- zPath += i;
- pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr);
- if( pParse->oom ) return 0;
- if( pNode ){
- pRoot = &pParse->aNode[iRoot];
- pRoot->u.iAppend = iStart - iRoot;
- pRoot->jnFlags |= JNODE_APPEND;
- pParse->aNode[iLabel].jnFlags |= JNODE_RAW;
- }
- return pNode;
- }
- }else if( zPath[0]=='[' && safe_isdigit(zPath[1]) ){
- if( pRoot->eType!=JSON_ARRAY ) return 0;
- i = 0;
- j = 1;
- while( safe_isdigit(zPath[j]) ){
- i = i*10 + zPath[j] - '0';
- j++;
- }
- if( zPath[j]!=']' ){
- *pzErr = zPath;
- return 0;
- }
- zPath += j + 1;
- j = 1;
- for(;;){
- while( j<=pRoot->n && (i>0 || (pRoot[j].jnFlags & JNODE_REMOVE)!=0) ){
- if( (pRoot[j].jnFlags & JNODE_REMOVE)==0 ) i--;
- j += jsonNodeSize(&pRoot[j]);
- }
- if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break;
- iRoot += pRoot->u.iAppend;
- pRoot = &pParse->aNode[iRoot];
- j = 1;
- }
- if( j<=pRoot->n ){
- return jsonLookupStep(pParse, iRoot+j, zPath, pApnd, pzErr);
- }
- if( i==0 && pApnd ){
- u32 iStart;
- JsonNode *pNode;
- iStart = jsonParseAddNode(pParse, JSON_ARRAY, 1, 0);
- pNode = jsonLookupAppend(pParse, zPath, pApnd, pzErr);
- if( pParse->oom ) return 0;
- if( pNode ){
- pRoot = &pParse->aNode[iRoot];
- pRoot->u.iAppend = iStart - iRoot;
- pRoot->jnFlags |= JNODE_APPEND;
- }
- return pNode;
- }
- }else{
- *pzErr = zPath;
- }
- return 0;
-}
-
-/*
-** Append content to pParse that will complete zPath. Return a pointer
-** to the inserted node, or return NULL if the append fails.
-*/
-static JsonNode *jsonLookupAppend(
- JsonParse *pParse, /* Append content to the JSON parse */
- const char *zPath, /* Description of content to append */
- int *pApnd, /* Set this flag to 1 */
- const char **pzErr /* Make this point to any syntax error */
-){
- *pApnd = 1;
- if( zPath[0]==0 ){
- jsonParseAddNode(pParse, JSON_NULL, 0, 0);
- return pParse->oom ? 0 : &pParse->aNode[pParse->nNode-1];
- }
- if( zPath[0]=='.' ){
- jsonParseAddNode(pParse, JSON_OBJECT, 0, 0);
- }else if( strncmp(zPath,"[0]",3)==0 ){
- jsonParseAddNode(pParse, JSON_ARRAY, 0, 0);
- }else{
- return 0;
- }
- if( pParse->oom ) return 0;
- return jsonLookupStep(pParse, pParse->nNode-1, zPath, pApnd, pzErr);
-}
-
-/*
-** Return the text of a syntax error message on a JSON path. Space is
-** obtained from sqlite3_malloc().
-*/
-static char *jsonPathSyntaxError(const char *zErr){
- return sqlite3_mprintf("JSON path error near '%q'", zErr);
-}
-
-/*
-** Do a node lookup using zPath. Return a pointer to the node on success.
-** Return NULL if not found or if there is an error.
-**
-** On an error, write an error message into pCtx and increment the
-** pParse->nErr counter.
-**
-** If pApnd!=NULL then try to append missing nodes and set *pApnd = 1 if
-** nodes are appended.
-*/
-static JsonNode *jsonLookup(
- JsonParse *pParse, /* The JSON to search */
- const char *zPath, /* The path to search */
- int *pApnd, /* Append nodes to complete path if not NULL */
- sqlite3_context *pCtx /* Report errors here, if not NULL */
-){
- const char *zErr = 0;
- JsonNode *pNode = 0;
- char *zMsg;
-
- if( zPath==0 ) return 0;
- if( zPath[0]!='$' ){
- zErr = zPath;
- goto lookup_err;
- }
- zPath++;
- pNode = jsonLookupStep(pParse, 0, zPath, pApnd, &zErr);
- if( zErr==0 ) return pNode;
-
-lookup_err:
- pParse->nErr++;
- assert( zErr!=0 && pCtx!=0 );
- zMsg = jsonPathSyntaxError(zErr);
- if( zMsg ){
- sqlite3_result_error(pCtx, zMsg, -1);
- sqlite3_free(zMsg);
- }else{
- sqlite3_result_error_nomem(pCtx);
- }
- return 0;
-}
-
-
-/*
-** Report the wrong number of arguments for json_insert(), json_replace()
-** or json_set().
-*/
-static void jsonWrongNumArgs(
- sqlite3_context *pCtx,
- const char *zFuncName
-){
- char *zMsg = sqlite3_mprintf("json_%s() needs an odd number of arguments",
- zFuncName);
- sqlite3_result_error(pCtx, zMsg, -1);
- sqlite3_free(zMsg);
-}
-
-/*
-** Mark all NULL entries in the Object passed in as JNODE_REMOVE.
-*/
-static void jsonRemoveAllNulls(JsonNode *pNode){
- int i, n;
- assert( pNode->eType==JSON_OBJECT );
- n = pNode->n;
- for(i=2; i<=n; i += jsonNodeSize(&pNode[i])+1){
- switch( pNode[i].eType ){
- case JSON_NULL:
- pNode[i].jnFlags |= JNODE_REMOVE;
- break;
- case JSON_OBJECT:
- jsonRemoveAllNulls(&pNode[i]);
- break;
- }
- }
-}
-
-
-/****************************************************************************
-** SQL functions used for testing and debugging
-****************************************************************************/
-
-#ifdef SQLITE_DEBUG
-/*
-** The json_parse(JSON) function returns a string which describes
-** a parse of the JSON provided. Or it returns NULL if JSON is not
-** well-formed.
-*/
-static void jsonParseFunc(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- JsonString s; /* Output string - not real JSON */
- JsonParse x; /* The parse */
- u32 i;
-
- assert( argc==1 );
- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
- jsonParseFindParents(&x);
- jsonInit(&s, ctx);
- for(i=0; i<x.nNode; i++){
- const char *zType;
- if( x.aNode[i].jnFlags & JNODE_LABEL ){
- assert( x.aNode[i].eType==JSON_STRING );
- zType = "label";
- }else{
- zType = jsonType[x.aNode[i].eType];
- }
- jsonPrintf(100, &s,"node %3u: %7s n=%-4d up=%-4d",
- i, zType, x.aNode[i].n, x.aUp[i]);
- if( x.aNode[i].u.zJContent!=0 ){
- jsonAppendRaw(&s, " ", 1);
- jsonAppendRaw(&s, x.aNode[i].u.zJContent, x.aNode[i].n);
- }
- jsonAppendRaw(&s, "\n", 1);
- }
- jsonParseReset(&x);
- jsonResult(&s);
-}
-
-/*
-** The json_test1(JSON) function return true (1) if the input is JSON
-** text generated by another json function. It returns (0) if the input
-** is not known to be JSON.
-*/
-static void jsonTest1Func(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- UNUSED_PARAM(argc);
- sqlite3_result_int(ctx, sqlite3_value_subtype(argv[0])==JSON_SUBTYPE);
-}
-#endif /* SQLITE_DEBUG */
-
-/****************************************************************************
-** Scalar SQL function implementations
-****************************************************************************/
-
-/*
-** Implementation of the json_QUOTE(VALUE) function. Return a JSON value
-** corresponding to the SQL value input. Mostly this means putting
-** double-quotes around strings and returning the unquoted string "null"
-** when given a NULL input.
-*/
-static void jsonQuoteFunc(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- JsonString jx;
- UNUSED_PARAM(argc);
-
- jsonInit(&jx, ctx);
- jsonAppendValue(&jx, argv[0]);
- jsonResult(&jx);
- sqlite3_result_subtype(ctx, JSON_SUBTYPE);
-}
-
-/*
-** Implementation of the json_array(VALUE,...) function. Return a JSON
-** array that contains all values given in arguments. Or if any argument
-** is a BLOB, throw an error.
-*/
-static void jsonArrayFunc(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- int i;
- JsonString jx;
-
- jsonInit(&jx, ctx);
- jsonAppendChar(&jx, '[');
- for(i=0; i<argc; i++){
- jsonAppendSeparator(&jx);
- jsonAppendValue(&jx, argv[i]);
- }
- jsonAppendChar(&jx, ']');
- jsonResult(&jx);
- sqlite3_result_subtype(ctx, JSON_SUBTYPE);
-}
-
-
-/*
-** json_array_length(JSON)
-** json_array_length(JSON, PATH)
-**
-** Return the number of elements in the top-level JSON array.
-** Return 0 if the input is not a well-formed JSON array.
-*/
-static void jsonArrayLengthFunc(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- JsonParse *p; /* The parse */
- sqlite3_int64 n = 0;
- u32 i;
- JsonNode *pNode;
-
- p = jsonParseCached(ctx, argv);
- if( p==0 ) return;
- assert( p->nNode );
- if( argc==2 ){
- const char *zPath = (const char*)sqlite3_value_text(argv[1]);
- pNode = jsonLookup(p, zPath, 0, ctx);
- }else{
- pNode = p->aNode;
- }
- if( pNode==0 ){
- return;
- }
- if( pNode->eType==JSON_ARRAY ){
- assert( (pNode->jnFlags & JNODE_APPEND)==0 );
- for(i=1; i<=pNode->n; n++){
- i += jsonNodeSize(&pNode[i]);
- }
- }
- sqlite3_result_int64(ctx, n);
-}
-
-/*
-** json_extract(JSON, PATH, ...)
-**
-** Return the element described by PATH. Return NULL if there is no
-** PATH element. If there are multiple PATHs, then return a JSON array
-** with the result from each path. Throw an error if the JSON or any PATH
-** is malformed.
-*/
-static void jsonExtractFunc(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- JsonParse *p; /* The parse */
- JsonNode *pNode;
- const char *zPath;
- JsonString jx;
- int i;
-
- if( argc<2 ) return;
- p = jsonParseCached(ctx, argv);
- if( p==0 ) return;
- jsonInit(&jx, ctx);
- jsonAppendChar(&jx, '[');
- for(i=1; i<argc; i++){
- zPath = (const char*)sqlite3_value_text(argv[i]);
- pNode = jsonLookup(p, zPath, 0, ctx);
- if( p->nErr ) break;
- if( argc>2 ){
- jsonAppendSeparator(&jx);
- if( pNode ){
- jsonRenderNode(pNode, &jx, 0);
- }else{
- jsonAppendRaw(&jx, "null", 4);
- }
- }else if( pNode ){
- jsonReturn(pNode, ctx, 0);
- }
- }
- if( argc>2 && i==argc ){
- jsonAppendChar(&jx, ']');
- jsonResult(&jx);
- sqlite3_result_subtype(ctx, JSON_SUBTYPE);
- }
- jsonReset(&jx);
-}
-
-/* This is the RFC 7396 MergePatch algorithm.
-*/
-static JsonNode *jsonMergePatch(
- JsonParse *pParse, /* The JSON parser that contains the TARGET */
- u32 iTarget, /* Node of the TARGET in pParse */
- JsonNode *pPatch /* The PATCH */
-){
- u32 i, j;
- u32 iRoot;
- JsonNode *pTarget;
- if( pPatch->eType!=JSON_OBJECT ){
- return pPatch;
- }
- assert( iTarget>=0 && iTarget<pParse->nNode );
- pTarget = &pParse->aNode[iTarget];
- assert( (pPatch->jnFlags & JNODE_APPEND)==0 );
- if( pTarget->eType!=JSON_OBJECT ){
- jsonRemoveAllNulls(pPatch);
- return pPatch;
- }
- iRoot = iTarget;
- for(i=1; i<pPatch->n; i += jsonNodeSize(&pPatch[i+1])+1){
- u32 nKey;
- const char *zKey;
- assert( pPatch[i].eType==JSON_STRING );
- assert( pPatch[i].jnFlags & JNODE_LABEL );
- nKey = pPatch[i].n;
- zKey = pPatch[i].u.zJContent;
- assert( (pPatch[i].jnFlags & JNODE_RAW)==0 );
- for(j=1; j<pTarget->n; j += jsonNodeSize(&pTarget[j+1])+1 ){
- assert( pTarget[j].eType==JSON_STRING );
- assert( pTarget[j].jnFlags & JNODE_LABEL );
- assert( (pPatch[i].jnFlags & JNODE_RAW)==0 );
- if( pTarget[j].n==nKey && strncmp(pTarget[j].u.zJContent,zKey,nKey)==0 ){
- if( pTarget[j+1].jnFlags & (JNODE_REMOVE|JNODE_PATCH) ) break;
- if( pPatch[i+1].eType==JSON_NULL ){
- pTarget[j+1].jnFlags |= JNODE_REMOVE;
- }else{
- JsonNode *pNew = jsonMergePatch(pParse, iTarget+j+1, &pPatch[i+1]);
- if( pNew==0 ) return 0;
- pTarget = &pParse->aNode[iTarget];
- if( pNew!=&pTarget[j+1] ){
- pTarget[j+1].u.pPatch = pNew;
- pTarget[j+1].jnFlags |= JNODE_PATCH;
- }
- }
- break;
- }
- }
- if( j>=pTarget->n && pPatch[i+1].eType!=JSON_NULL ){
- int iStart, iPatch;
- iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0);
- jsonParseAddNode(pParse, JSON_STRING, nKey, zKey);
- iPatch = jsonParseAddNode(pParse, JSON_TRUE, 0, 0);
- if( pParse->oom ) return 0;
- jsonRemoveAllNulls(pPatch);
- pTarget = &pParse->aNode[iTarget];
- pParse->aNode[iRoot].jnFlags |= JNODE_APPEND;
- pParse->aNode[iRoot].u.iAppend = iStart - iRoot;
- iRoot = iStart;
- pParse->aNode[iPatch].jnFlags |= JNODE_PATCH;
- pParse->aNode[iPatch].u.pPatch = &pPatch[i+1];
- }
- }
- return pTarget;
-}
-
-/*
-** Implementation of the json_mergepatch(JSON1,JSON2) function. Return a JSON
-** object that is the result of running the RFC 7396 MergePatch() algorithm
-** on the two arguments.
-*/
-static void jsonPatchFunc(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- JsonParse x; /* The JSON that is being patched */
- JsonParse y; /* The patch */
- JsonNode *pResult; /* The result of the merge */
-
- UNUSED_PARAM(argc);
- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
- if( jsonParse(&y, ctx, (const char*)sqlite3_value_text(argv[1])) ){
- jsonParseReset(&x);
- return;
- }
- pResult = jsonMergePatch(&x, 0, y.aNode);
- assert( pResult!=0 || x.oom );
- if( pResult ){
- jsonReturnJson(pResult, ctx, 0);
- }else{
- sqlite3_result_error_nomem(ctx);
- }
- jsonParseReset(&x);
- jsonParseReset(&y);
-}
-
-
-/*
-** Implementation of the json_object(NAME,VALUE,...) function. Return a JSON
-** object that contains all name/value given in arguments. Or if any name
-** is not a string or if any value is a BLOB, throw an error.
-*/
-static void jsonObjectFunc(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- int i;
- JsonString jx;
- const char *z;
- u32 n;
-
- if( argc&1 ){
- sqlite3_result_error(ctx, "json_object() requires an even number "
- "of arguments", -1);
- return;
- }
- jsonInit(&jx, ctx);
- jsonAppendChar(&jx, '{');
- for(i=0; i<argc; i+=2){
- if( sqlite3_value_type(argv[i])!=SQLITE_TEXT ){
- sqlite3_result_error(ctx, "json_object() labels must be TEXT", -1);
- jsonReset(&jx);
- return;
- }
- jsonAppendSeparator(&jx);
- z = (const char*)sqlite3_value_text(argv[i]);
- n = (u32)sqlite3_value_bytes(argv[i]);
- jsonAppendString(&jx, z, n);
- jsonAppendChar(&jx, ':');
- jsonAppendValue(&jx, argv[i+1]);
- }
- jsonAppendChar(&jx, '}');
- jsonResult(&jx);
- sqlite3_result_subtype(ctx, JSON_SUBTYPE);
-}
-
-
-/*
-** json_remove(JSON, PATH, ...)
-**
-** Remove the named elements from JSON and return the result. malformed
-** JSON or PATH arguments result in an error.
-*/
-static void jsonRemoveFunc(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- JsonParse x; /* The parse */
- JsonNode *pNode;
- const char *zPath;
- u32 i;
-
- if( argc<1 ) return;
- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
- assert( x.nNode );
- for(i=1; i<(u32)argc; i++){
- zPath = (const char*)sqlite3_value_text(argv[i]);
- if( zPath==0 ) goto remove_done;
- pNode = jsonLookup(&x, zPath, 0, ctx);
- if( x.nErr ) goto remove_done;
- if( pNode ) pNode->jnFlags |= JNODE_REMOVE;
- }
- if( (x.aNode[0].jnFlags & JNODE_REMOVE)==0 ){
- jsonReturnJson(x.aNode, ctx, 0);
- }
-remove_done:
- jsonParseReset(&x);
-}
-
-/*
-** json_replace(JSON, PATH, VALUE, ...)
-**
-** Replace the value at PATH with VALUE. If PATH does not already exist,
-** this routine is a no-op. If JSON or PATH is malformed, throw an error.
-*/
-static void jsonReplaceFunc(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- JsonParse x; /* The parse */
- JsonNode *pNode;
- const char *zPath;
- u32 i;
-
- if( argc<1 ) return;
- if( (argc&1)==0 ) {
- jsonWrongNumArgs(ctx, "replace");
- return;
- }
- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
- assert( x.nNode );
- for(i=1; i<(u32)argc; i+=2){
- zPath = (const char*)sqlite3_value_text(argv[i]);
- pNode = jsonLookup(&x, zPath, 0, ctx);
- if( x.nErr ) goto replace_err;
- if( pNode ){
- pNode->jnFlags |= (u8)JNODE_REPLACE;
- pNode->u.iReplace = i + 1;
- }
- }
- if( x.aNode[0].jnFlags & JNODE_REPLACE ){
- sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]);
- }else{
- jsonReturnJson(x.aNode, ctx, argv);
- }
-replace_err:
- jsonParseReset(&x);
-}
-
-/*
-** json_set(JSON, PATH, VALUE, ...)
-**
-** Set the value at PATH to VALUE. Create the PATH if it does not already
-** exist. Overwrite existing values that do exist.
-** If JSON or PATH is malformed, throw an error.
-**
-** json_insert(JSON, PATH, VALUE, ...)
-**
-** Create PATH and initialize it to VALUE. If PATH already exists, this
-** routine is a no-op. If JSON or PATH is malformed, throw an error.
-*/
-static void jsonSetFunc(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- JsonParse x; /* The parse */
- JsonNode *pNode;
- const char *zPath;
- u32 i;
- int bApnd;
- int bIsSet = *(int*)sqlite3_user_data(ctx);
-
- if( argc<1 ) return;
- if( (argc&1)==0 ) {
- jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert");
- return;
- }
- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
- assert( x.nNode );
- for(i=1; i<(u32)argc; i+=2){
- zPath = (const char*)sqlite3_value_text(argv[i]);
- bApnd = 0;
- pNode = jsonLookup(&x, zPath, &bApnd, ctx);
- if( x.oom ){
- sqlite3_result_error_nomem(ctx);
- goto jsonSetDone;
- }else if( x.nErr ){
- goto jsonSetDone;
- }else if( pNode && (bApnd || bIsSet) ){
- pNode->jnFlags |= (u8)JNODE_REPLACE;
- pNode->u.iReplace = i + 1;
- }
- }
- if( x.aNode[0].jnFlags & JNODE_REPLACE ){
- sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]);
- }else{
- jsonReturnJson(x.aNode, ctx, argv);
- }
-jsonSetDone:
- jsonParseReset(&x);
-}
-
-/*
-** json_type(JSON)
-** json_type(JSON, PATH)
-**
-** Return the top-level "type" of a JSON string. Throw an error if
-** either the JSON or PATH inputs are not well-formed.
-*/
-static void jsonTypeFunc(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- JsonParse x; /* The parse */
- const char *zPath;
- JsonNode *pNode;
-
- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
- assert( x.nNode );
- if( argc==2 ){
- zPath = (const char*)sqlite3_value_text(argv[1]);
- pNode = jsonLookup(&x, zPath, 0, ctx);
- }else{
- pNode = x.aNode;
- }
- if( pNode ){
- sqlite3_result_text(ctx, jsonType[pNode->eType], -1, SQLITE_STATIC);
- }
- jsonParseReset(&x);
-}
-
-/*
-** json_valid(JSON)
-**
-** Return 1 if JSON is a well-formed JSON string according to RFC-7159.
-** Return 0 otherwise.
-*/
-static void jsonValidFunc(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- JsonParse x; /* The parse */
- int rc = 0;
-
- UNUSED_PARAM(argc);
- if( jsonParse(&x, 0, (const char*)sqlite3_value_text(argv[0]))==0 ){
- rc = 1;
- }
- jsonParseReset(&x);
- sqlite3_result_int(ctx, rc);
-}
-
-
-/****************************************************************************
-** Aggregate SQL function implementations
-****************************************************************************/
-/*
-** json_group_array(VALUE)
-**
-** Return a JSON array composed of all values in the aggregate.
-*/
-static void jsonArrayStep(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- JsonString *pStr;
- UNUSED_PARAM(argc);
- pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
- if( pStr ){
- if( pStr->zBuf==0 ){
- jsonInit(pStr, ctx);
- jsonAppendChar(pStr, '[');
- }else{
- jsonAppendChar(pStr, ',');
- pStr->pCtx = ctx;
- }
- jsonAppendValue(pStr, argv[0]);
- }
-}
-static void jsonArrayFinal(sqlite3_context *ctx){
- JsonString *pStr;
- pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
- if( pStr ){
- pStr->pCtx = ctx;
- jsonAppendChar(pStr, ']');
- if( pStr->bErr ){
- if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx);
- assert( pStr->bStatic );
- }else{
- sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed,
- pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free);
- pStr->bStatic = 1;
- }
- }else{
- sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC);
- }
- sqlite3_result_subtype(ctx, JSON_SUBTYPE);
-}
-
-/*
-** json_group_obj(NAME,VALUE)
-**
-** Return a JSON object composed of all names and values in the aggregate.
-*/
-static void jsonObjectStep(
- sqlite3_context *ctx,
- int argc,
- sqlite3_value **argv
-){
- JsonString *pStr;
- const char *z;
- u32 n;
- UNUSED_PARAM(argc);
- pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
- if( pStr ){
- if( pStr->zBuf==0 ){
- jsonInit(pStr, ctx);
- jsonAppendChar(pStr, '{');
- }else{
- jsonAppendChar(pStr, ',');
- pStr->pCtx = ctx;
- }
- z = (const char*)sqlite3_value_text(argv[0]);
- n = (u32)sqlite3_value_bytes(argv[0]);
- jsonAppendString(pStr, z, n);
- jsonAppendChar(pStr, ':');
- jsonAppendValue(pStr, argv[1]);
- }
-}
-static void jsonObjectFinal(sqlite3_context *ctx){
- JsonString *pStr;
- pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
- if( pStr ){
- jsonAppendChar(pStr, '}');
- if( pStr->bErr ){
- if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx);
- assert( pStr->bStatic );
- }else{
- sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed,
- pStr->bStatic ? SQLITE_TRANSIENT : sqlite3_free);
- pStr->bStatic = 1;
- }
- }else{
- sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC);
- }
- sqlite3_result_subtype(ctx, JSON_SUBTYPE);
-}
-
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-/****************************************************************************
-** The json_each virtual table
-****************************************************************************/
-typedef struct JsonEachCursor JsonEachCursor;
-struct JsonEachCursor {
- sqlite3_vtab_cursor base; /* Base class - must be first */
- u32 iRowid; /* The rowid */
- u32 iBegin; /* The first node of the scan */
- u32 i; /* Index in sParse.aNode[] of current row */
- u32 iEnd; /* EOF when i equals or exceeds this value */
- u8 eType; /* Type of top-level element */
- u8 bRecursive; /* True for json_tree(). False for json_each() */
- char *zJson; /* Input JSON */
- char *zRoot; /* Path by which to filter zJson */
- JsonParse sParse; /* Parse of the input JSON */
-};
-
-/* Constructor for the json_each virtual table */
-static int jsonEachConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- sqlite3_vtab *pNew;
- int rc;
-
-/* Column numbers */
-#define JEACH_KEY 0
-#define JEACH_VALUE 1
-#define JEACH_TYPE 2
-#define JEACH_ATOM 3
-#define JEACH_ID 4
-#define JEACH_PARENT 5
-#define JEACH_FULLKEY 6
-#define JEACH_PATH 7
-#define JEACH_JSON 8
-#define JEACH_ROOT 9
-
- UNUSED_PARAM(pzErr);
- UNUSED_PARAM(argv);
- UNUSED_PARAM(argc);
- UNUSED_PARAM(pAux);
- rc = sqlite3_declare_vtab(db,
- "CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path,"
- "json HIDDEN,root HIDDEN)");
- if( rc==SQLITE_OK ){
- pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
- if( pNew==0 ) return SQLITE_NOMEM;
- memset(pNew, 0, sizeof(*pNew));
- }
- return rc;
-}
-
-/* destructor for json_each virtual table */
-static int jsonEachDisconnect(sqlite3_vtab *pVtab){
- sqlite3_free(pVtab);
- return SQLITE_OK;
-}
-
-/* constructor for a JsonEachCursor object for json_each(). */
-static int jsonEachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
- JsonEachCursor *pCur;
-
- UNUSED_PARAM(p);
- pCur = sqlite3_malloc( sizeof(*pCur) );
- if( pCur==0 ) return SQLITE_NOMEM;
- memset(pCur, 0, sizeof(*pCur));
- *ppCursor = &pCur->base;
- return SQLITE_OK;
-}
-
-/* constructor for a JsonEachCursor object for json_tree(). */
-static int jsonEachOpenTree(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
- int rc = jsonEachOpenEach(p, ppCursor);
- if( rc==SQLITE_OK ){
- JsonEachCursor *pCur = (JsonEachCursor*)*ppCursor;
- pCur->bRecursive = 1;
- }
- return rc;
-}
-
-/* Reset a JsonEachCursor back to its original state. Free any memory
-** held. */
-static void jsonEachCursorReset(JsonEachCursor *p){
- sqlite3_free(p->zJson);
- sqlite3_free(p->zRoot);
- jsonParseReset(&p->sParse);
- p->iRowid = 0;
- p->i = 0;
- p->iEnd = 0;
- p->eType = 0;
- p->zJson = 0;
- p->zRoot = 0;
-}
-
-/* Destructor for a jsonEachCursor object */
-static int jsonEachClose(sqlite3_vtab_cursor *cur){
- JsonEachCursor *p = (JsonEachCursor*)cur;
- jsonEachCursorReset(p);
- sqlite3_free(cur);
- return SQLITE_OK;
-}
-
-/* Return TRUE if the jsonEachCursor object has been advanced off the end
-** of the JSON object */
-static int jsonEachEof(sqlite3_vtab_cursor *cur){
- JsonEachCursor *p = (JsonEachCursor*)cur;
- return p->i >= p->iEnd;
-}
-
-/* Advance the cursor to the next element for json_tree() */
-static int jsonEachNext(sqlite3_vtab_cursor *cur){
- JsonEachCursor *p = (JsonEachCursor*)cur;
- if( p->bRecursive ){
- if( p->sParse.aNode[p->i].jnFlags & JNODE_LABEL ) p->i++;
- p->i++;
- p->iRowid++;
- if( p->i<p->iEnd ){
- u32 iUp = p->sParse.aUp[p->i];
- JsonNode *pUp = &p->sParse.aNode[iUp];
- p->eType = pUp->eType;
- if( pUp->eType==JSON_ARRAY ){
- if( iUp==p->i-1 ){
- pUp->u.iKey = 0;
- }else{
- pUp->u.iKey++;
- }
- }
- }
- }else{
- switch( p->eType ){
- case JSON_ARRAY: {
- p->i += jsonNodeSize(&p->sParse.aNode[p->i]);
- p->iRowid++;
- break;
- }
- case JSON_OBJECT: {
- p->i += 1 + jsonNodeSize(&p->sParse.aNode[p->i+1]);
- p->iRowid++;
- break;
- }
- default: {
- p->i = p->iEnd;
- break;
- }
- }
- }
- return SQLITE_OK;
-}
-
-/* Append the name of the path for element i to pStr
-*/
-static void jsonEachComputePath(
- JsonEachCursor *p, /* The cursor */
- JsonString *pStr, /* Write the path here */
- u32 i /* Path to this element */
-){
- JsonNode *pNode, *pUp;
- u32 iUp;
- if( i==0 ){
- jsonAppendChar(pStr, '$');
- return;
- }
- iUp = p->sParse.aUp[i];
- jsonEachComputePath(p, pStr, iUp);
- pNode = &p->sParse.aNode[i];
- pUp = &p->sParse.aNode[iUp];
- if( pUp->eType==JSON_ARRAY ){
- jsonPrintf(30, pStr, "[%d]", pUp->u.iKey);
- }else{
- assert( pUp->eType==JSON_OBJECT );
- if( (pNode->jnFlags & JNODE_LABEL)==0 ) pNode--;
- assert( pNode->eType==JSON_STRING );
- assert( pNode->jnFlags & JNODE_LABEL );
- jsonPrintf(pNode->n+1, pStr, ".%.*s", pNode->n-2, pNode->u.zJContent+1);
- }
-}
-
-/* Return the value of a column */
-static int jsonEachColumn(
- sqlite3_vtab_cursor *cur, /* The cursor */
- sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
- int i /* Which column to return */
-){
- JsonEachCursor *p = (JsonEachCursor*)cur;
- JsonNode *pThis = &p->sParse.aNode[p->i];
- switch( i ){
- case JEACH_KEY: {
- if( p->i==0 ) break;
- if( p->eType==JSON_OBJECT ){
- jsonReturn(pThis, ctx, 0);
- }else if( p->eType==JSON_ARRAY ){
- u32 iKey;
- if( p->bRecursive ){
- if( p->iRowid==0 ) break;
- iKey = p->sParse.aNode[p->sParse.aUp[p->i]].u.iKey;
- }else{
- iKey = p->iRowid;
- }
- sqlite3_result_int64(ctx, (sqlite3_int64)iKey);
- }
- break;
- }
- case JEACH_VALUE: {
- if( pThis->jnFlags & JNODE_LABEL ) pThis++;
- jsonReturn(pThis, ctx, 0);
- break;
- }
- case JEACH_TYPE: {
- if( pThis->jnFlags & JNODE_LABEL ) pThis++;
- sqlite3_result_text(ctx, jsonType[pThis->eType], -1, SQLITE_STATIC);
- break;
- }
- case JEACH_ATOM: {
- if( pThis->jnFlags & JNODE_LABEL ) pThis++;
- if( pThis->eType>=JSON_ARRAY ) break;
- jsonReturn(pThis, ctx, 0);
- break;
- }
- case JEACH_ID: {
- sqlite3_result_int64(ctx,
- (sqlite3_int64)p->i + ((pThis->jnFlags & JNODE_LABEL)!=0));
- break;
- }
- case JEACH_PARENT: {
- if( p->i>p->iBegin && p->bRecursive ){
- sqlite3_result_int64(ctx, (sqlite3_int64)p->sParse.aUp[p->i]);
- }
- break;
- }
- case JEACH_FULLKEY: {
- JsonString x;
- jsonInit(&x, ctx);
- if( p->bRecursive ){
- jsonEachComputePath(p, &x, p->i);
- }else{
- if( p->zRoot ){
- jsonAppendRaw(&x, p->zRoot, (int)strlen(p->zRoot));
- }else{
- jsonAppendChar(&x, '$');
- }
- if( p->eType==JSON_ARRAY ){
- jsonPrintf(30, &x, "[%d]", p->iRowid);
- }else if( p->eType==JSON_OBJECT ){
- jsonPrintf(pThis->n, &x, ".%.*s", pThis->n-2, pThis->u.zJContent+1);
- }
- }
- jsonResult(&x);
- break;
- }
- case JEACH_PATH: {
- if( p->bRecursive ){
- JsonString x;
- jsonInit(&x, ctx);
- jsonEachComputePath(p, &x, p->sParse.aUp[p->i]);
- jsonResult(&x);
- break;
- }
- /* For json_each() path and root are the same so fall through
- ** into the root case */
- }
- default: {
- const char *zRoot = p->zRoot;
- if( zRoot==0 ) zRoot = "$";
- sqlite3_result_text(ctx, zRoot, -1, SQLITE_STATIC);
- break;
- }
- case JEACH_JSON: {
- assert( i==JEACH_JSON );
- sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_STATIC);
- break;
- }
- }
- return SQLITE_OK;
-}
-
-/* Return the current rowid value */
-static int jsonEachRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- JsonEachCursor *p = (JsonEachCursor*)cur;
- *pRowid = p->iRowid;
- return SQLITE_OK;
-}
-
-/* The query strategy is to look for an equality constraint on the json
-** column. Without such a constraint, the table cannot operate. idxNum is
-** 1 if the constraint is found, 3 if the constraint and zRoot are found,
-** and 0 otherwise.
-*/
-static int jsonEachBestIndex(
- sqlite3_vtab *tab,
- sqlite3_index_info *pIdxInfo
-){
- int i;
- int jsonIdx = -1;
- int rootIdx = -1;
- const struct sqlite3_index_constraint *pConstraint;
-
- UNUSED_PARAM(tab);
- pConstraint = pIdxInfo->aConstraint;
- for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
- if( pConstraint->usable==0 ) continue;
- if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
- switch( pConstraint->iColumn ){
- case JEACH_JSON: jsonIdx = i; break;
- case JEACH_ROOT: rootIdx = i; break;
- default: /* no-op */ break;
- }
- }
- if( jsonIdx<0 ){
- pIdxInfo->idxNum = 0;
- pIdxInfo->estimatedCost = 1e99;
- }else{
- pIdxInfo->estimatedCost = 1.0;
- pIdxInfo->aConstraintUsage[jsonIdx].argvIndex = 1;
- pIdxInfo->aConstraintUsage[jsonIdx].omit = 1;
- if( rootIdx<0 ){
- pIdxInfo->idxNum = 1;
- }else{
- pIdxInfo->aConstraintUsage[rootIdx].argvIndex = 2;
- pIdxInfo->aConstraintUsage[rootIdx].omit = 1;
- pIdxInfo->idxNum = 3;
- }
- }
- return SQLITE_OK;
-}
-
-/* Start a search on a new JSON string */
-static int jsonEachFilter(
- sqlite3_vtab_cursor *cur,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- JsonEachCursor *p = (JsonEachCursor*)cur;
- const char *z;
- const char *zRoot = 0;
- sqlite3_int64 n;
-
- UNUSED_PARAM(idxStr);
- UNUSED_PARAM(argc);
- jsonEachCursorReset(p);
- if( idxNum==0 ) return SQLITE_OK;
- z = (const char*)sqlite3_value_text(argv[0]);
- if( z==0 ) return SQLITE_OK;
- n = sqlite3_value_bytes(argv[0]);
- p->zJson = sqlite3_malloc64( n+1 );
- if( p->zJson==0 ) return SQLITE_NOMEM;
- memcpy(p->zJson, z, (size_t)n+1);
- if( jsonParse(&p->sParse, 0, p->zJson) ){
- int rc = SQLITE_NOMEM;
- if( p->sParse.oom==0 ){
- sqlite3_free(cur->pVtab->zErrMsg);
- cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON");
- if( cur->pVtab->zErrMsg ) rc = SQLITE_ERROR;
- }
- jsonEachCursorReset(p);
- return rc;
- }else if( p->bRecursive && jsonParseFindParents(&p->sParse) ){
- jsonEachCursorReset(p);
- return SQLITE_NOMEM;
- }else{
- JsonNode *pNode = 0;
- if( idxNum==3 ){
- const char *zErr = 0;
- zRoot = (const char*)sqlite3_value_text(argv[1]);
- if( zRoot==0 ) return SQLITE_OK;
- n = sqlite3_value_bytes(argv[1]);
- p->zRoot = sqlite3_malloc64( n+1 );
- if( p->zRoot==0 ) return SQLITE_NOMEM;
- memcpy(p->zRoot, zRoot, (size_t)n+1);
- if( zRoot[0]!='$' ){
- zErr = zRoot;
- }else{
- pNode = jsonLookupStep(&p->sParse, 0, p->zRoot+1, 0, &zErr);
- }
- if( zErr ){
- sqlite3_free(cur->pVtab->zErrMsg);
- cur->pVtab->zErrMsg = jsonPathSyntaxError(zErr);
- jsonEachCursorReset(p);
- return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
- }else if( pNode==0 ){
- return SQLITE_OK;
- }
- }else{
- pNode = p->sParse.aNode;
- }
- p->iBegin = p->i = (int)(pNode - p->sParse.aNode);
- p->eType = pNode->eType;
- if( p->eType>=JSON_ARRAY ){
- pNode->u.iKey = 0;
- p->iEnd = p->i + pNode->n + 1;
- if( p->bRecursive ){
- p->eType = p->sParse.aNode[p->sParse.aUp[p->i]].eType;
- if( p->i>0 && (p->sParse.aNode[p->i-1].jnFlags & JNODE_LABEL)!=0 ){
- p->i--;
- }
- }else{
- p->i++;
- }
- }else{
- p->iEnd = p->i+1;
- }
- }
- return SQLITE_OK;
-}
-
-/* The methods of the json_each virtual table */
-static sqlite3_module jsonEachModule = {
- 0, /* iVersion */
- 0, /* xCreate */
- jsonEachConnect, /* xConnect */
- jsonEachBestIndex, /* xBestIndex */
- jsonEachDisconnect, /* xDisconnect */
- 0, /* xDestroy */
- jsonEachOpenEach, /* xOpen - open a cursor */
- jsonEachClose, /* xClose - close a cursor */
- jsonEachFilter, /* xFilter - configure scan constraints */
- jsonEachNext, /* xNext - advance a cursor */
- jsonEachEof, /* xEof - check for end of scan */
- jsonEachColumn, /* xColumn - read data */
- jsonEachRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
- 0, /* xSavepoint */
- 0, /* xRelease */
- 0 /* xRollbackTo */
-};
-
-/* The methods of the json_tree virtual table. */
-static sqlite3_module jsonTreeModule = {
- 0, /* iVersion */
- 0, /* xCreate */
- jsonEachConnect, /* xConnect */
- jsonEachBestIndex, /* xBestIndex */
- jsonEachDisconnect, /* xDisconnect */
- 0, /* xDestroy */
- jsonEachOpenTree, /* xOpen - open a cursor */
- jsonEachClose, /* xClose - close a cursor */
- jsonEachFilter, /* xFilter - configure scan constraints */
- jsonEachNext, /* xNext - advance a cursor */
- jsonEachEof, /* xEof - check for end of scan */
- jsonEachColumn, /* xColumn - read data */
- jsonEachRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
- 0, /* xSavepoint */
- 0, /* xRelease */
- 0 /* xRollbackTo */
-};
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-/****************************************************************************
-** The following routines are the only publically visible identifiers in this
-** file. Call the following routines in order to register the various SQL
-** functions and the virtual table implemented by this file.
-****************************************************************************/
-
-SQLITE_PRIVATE int sqlite3Json1Init(sqlite3 *db){
- int rc = SQLITE_OK;
- unsigned int i;
- static const struct {
- const char *zName;
- int nArg;
- int flag;
- void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
- } aFunc[] = {
- { "json", 1, 0, jsonRemoveFunc },
- { "json_array", -1, 0, jsonArrayFunc },
- { "json_array_length", 1, 0, jsonArrayLengthFunc },
- { "json_array_length", 2, 0, jsonArrayLengthFunc },
- { "json_extract", -1, 0, jsonExtractFunc },
- { "json_insert", -1, 0, jsonSetFunc },
- { "json_object", -1, 0, jsonObjectFunc },
- { "json_patch", 2, 0, jsonPatchFunc },
- { "json_quote", 1, 0, jsonQuoteFunc },
- { "json_remove", -1, 0, jsonRemoveFunc },
- { "json_replace", -1, 0, jsonReplaceFunc },
- { "json_set", -1, 1, jsonSetFunc },
- { "json_type", 1, 0, jsonTypeFunc },
- { "json_type", 2, 0, jsonTypeFunc },
- { "json_valid", 1, 0, jsonValidFunc },
-
-#if SQLITE_DEBUG
- /* DEBUG and TESTING functions */
- { "json_parse", 1, 0, jsonParseFunc },
- { "json_test1", 1, 0, jsonTest1Func },
-#endif
- };
- static const struct {
- const char *zName;
- int nArg;
- void (*xStep)(sqlite3_context*,int,sqlite3_value**);
- void (*xFinal)(sqlite3_context*);
- } aAgg[] = {
- { "json_group_array", 1, jsonArrayStep, jsonArrayFinal },
- { "json_group_object", 2, jsonObjectStep, jsonObjectFinal },
- };
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- static const struct {
- const char *zName;
- sqlite3_module *pModule;
- } aMod[] = {
- { "json_each", &jsonEachModule },
- { "json_tree", &jsonTreeModule },
- };
-#endif
- for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
- rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg,
- SQLITE_UTF8 | SQLITE_DETERMINISTIC,
- (void*)&aFunc[i].flag,
- aFunc[i].xFunc, 0, 0);
- }
- for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){
- rc = sqlite3_create_function(db, aAgg[i].zName, aAgg[i].nArg,
- SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
- 0, aAgg[i].xStep, aAgg[i].xFinal);
- }
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- for(i=0; i<sizeof(aMod)/sizeof(aMod[0]) && rc==SQLITE_OK; i++){
- rc = sqlite3_create_module(db, aMod[i].zName, aMod[i].pModule, 0);
- }
-#endif
- return rc;
-}
-
-
-#ifndef SQLITE_CORE
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-SQLITE_API int sqlite3_json_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg; /* Unused parameter */
- return sqlite3Json1Init(db);
-}
-#endif
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1) */
-
-/************** End of json1.c ***********************************************/
/************** Begin file fts5.c ********************************************/
@@ -190621,7 +197442,7 @@ struct Fts5ExtensionApi {
** This way, even if the tokenizer does not provide synonyms
** when tokenizing query text (it should not - to do would be
** inefficient), it doesn't matter if the user queries for
-** 'first + place' or '1st + place', as there are entires in the
+** 'first + place' or '1st + place', as there are entries in the
** FTS index corresponding to both forms of the first token.
** </ol>
**
@@ -190649,7 +197470,7 @@ struct Fts5ExtensionApi {
** extra data to the FTS index or require FTS5 to query for multiple terms,
** so it is efficient in terms of disk space and query speed. However, it
** does not support prefix queries very well. If, as suggested above, the
-** token "first" is subsituted for "1st" by the tokenizer, then the query:
+** token "first" is substituted for "1st" by the tokenizer, then the query:
**
** <codeblock>
** ... MATCH '1s*'</codeblock>
@@ -191541,9 +198362,12 @@ static int sqlite3Fts5VocabInit(Fts5Global*, sqlite3*);
/**************************************************************************
** Interface to automatically generated code in fts5_unicode2.c.
*/
-static int sqlite3Fts5UnicodeIsalnum(int c);
static int sqlite3Fts5UnicodeIsdiacritic(int c);
static int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic);
+
+static int sqlite3Fts5UnicodeCatParse(const char*, u8*);
+static int sqlite3Fts5UnicodeCategory(int iCode);
+static void sqlite3Fts5UnicodeAscii(u8*, u8*);
/*
** End of interface to code in fts5_unicode2.c.
**************************************************************************/
@@ -191719,6 +198543,7 @@ typedef union {
#define fts5YY_MIN_REDUCE 83
#define fts5YY_MAX_REDUCE 110
/************* End control #defines *******************************************/
+#define fts5YY_NLOOKAHEAD ((int)(sizeof(fts5yy_lookahead)/sizeof(fts5yy_lookahead[0])))
/* Define the fts5yytestcase() macro to be a no-op if is not already defined
** otherwise.
@@ -192278,11 +199103,11 @@ static fts5YYACTIONTYPE fts5yy_find_shift_action(
do{
i = fts5yy_shift_ofst[stateno];
assert( i>=0 );
- assert( i+fts5YYNFTS5TOKEN<=(int)sizeof(fts5yy_lookahead)/sizeof(fts5yy_lookahead[0]) );
+ /* assert( i+fts5YYNFTS5TOKEN<=(int)fts5YY_NLOOKAHEAD ); */
assert( iLookAhead!=fts5YYNOCODE );
assert( iLookAhead < fts5YYNFTS5TOKEN );
i += iLookAhead;
- if( fts5yy_lookahead[i]!=iLookAhead ){
+ if( i>=fts5YY_NLOOKAHEAD || fts5yy_lookahead[i]!=iLookAhead ){
#ifdef fts5YYFALLBACK
fts5YYCODETYPE iFallback; /* Fallback token */
if( iLookAhead<sizeof(fts5yyFallback)/sizeof(fts5yyFallback[0])
@@ -192308,6 +199133,7 @@ static fts5YYACTIONTYPE fts5yy_find_shift_action(
#if fts5YY_SHIFT_MAX+fts5YYWILDCARD>=fts5YY_ACTTAB_COUNT
j<fts5YY_ACTTAB_COUNT &&
#endif
+ j<(int)(sizeof(fts5yy_lookahead)/sizeof(fts5yy_lookahead[0])) &&
fts5yy_lookahead[j]==fts5YYWILDCARD && iLookAhead>0
){
#ifndef NDEBUG
@@ -192332,7 +199158,7 @@ static fts5YYACTIONTYPE fts5yy_find_shift_action(
** Find the appropriate action for a parser given the non-terminal
** look-ahead token iLookAhead.
*/
-static int fts5yy_find_reduce_action(
+static fts5YYACTIONTYPE fts5yy_find_reduce_action(
fts5YYACTIONTYPE stateno, /* Current state number */
fts5YYCODETYPE iLookAhead /* The look-ahead token */
){
@@ -192500,7 +199326,7 @@ static fts5YYACTIONTYPE fts5yy_reduce(
sqlite3Fts5ParserCTX_PDECL /* %extra_context */
){
int fts5yygoto; /* The next state */
- int fts5yyact; /* The next action */
+ fts5YYACTIONTYPE fts5yyact; /* The next action */
fts5yyStackEntry *fts5yymsp; /* The top of the parser's stack */
int fts5yysize; /* Amount to pop the stack */
sqlite3Fts5ParserARG_FETCH
@@ -192856,12 +199682,12 @@ static void sqlite3Fts5Parser(
do{
assert( fts5yyact==fts5yypParser->fts5yytos->stateno );
- fts5yyact = fts5yy_find_shift_action(fts5yymajor,fts5yyact);
+ fts5yyact = fts5yy_find_shift_action((fts5YYCODETYPE)fts5yymajor,fts5yyact);
if( fts5yyact >= fts5YY_MIN_REDUCE ){
fts5yyact = fts5yy_reduce(fts5yypParser,fts5yyact-fts5YY_MIN_REDUCE,fts5yymajor,
fts5yyminor sqlite3Fts5ParserCTX_PARAM);
}else if( fts5yyact <= fts5YY_MAX_SHIFTREDUCE ){
- fts5yy_shift(fts5yypParser,fts5yyact,fts5yymajor,fts5yyminor);
+ fts5yy_shift(fts5yypParser,fts5yyact,(fts5YYCODETYPE)fts5yymajor,fts5yyminor);
#ifndef fts5YYNOERRORRECOVERY
fts5yypParser->fts5yyerrcnt--;
#endif
@@ -192990,6 +199816,21 @@ static void sqlite3Fts5Parser(
}
/*
+** Return the fallback token corresponding to canonical token iToken, or
+** 0 if iToken has no fallback.
+*/
+static int sqlite3Fts5ParserFallback(int iToken){
+#ifdef fts5YYFALLBACK
+ if( iToken<(int)(sizeof(fts5yyFallback)/sizeof(fts5yyFallback[0])) ){
+ return fts5yyFallback[iToken];
+ }
+#else
+ (void)iToken;
+#endif
+ return 0;
+}
+
+/*
** 2014 May 31
**
** The author disclaims copyright to this source code. In place of
@@ -195099,6 +201940,7 @@ static void sqlite3Fts5Parser(void*, int, Fts5Token, Fts5Parse*);
/* #include <stdio.h> */
static void sqlite3Fts5ParserTrace(FILE*, char*);
#endif
+static int sqlite3Fts5ParserFallback(int);
struct Fts5Expr {
@@ -197603,14 +204445,19 @@ static void fts5ExprIsAlnum(
sqlite3_value **apVal /* Function arguments */
){
int iCode;
+ u8 aArr[32];
if( nArg!=1 ){
sqlite3_result_error(pCtx,
"wrong number of arguments to function fts5_isalnum", -1
);
return;
}
+ memset(aArr, 0, sizeof(aArr));
+ sqlite3Fts5UnicodeCatParse("L*", aArr);
+ sqlite3Fts5UnicodeCatParse("N*", aArr);
+ sqlite3Fts5UnicodeCatParse("Co", aArr);
iCode = sqlite3_value_int(apVal[0]);
- sqlite3_result_int(pCtx, sqlite3Fts5UnicodeIsalnum(iCode));
+ sqlite3_result_int(pCtx, aArr[sqlite3Fts5UnicodeCategory(iCode)]);
}
static void fts5ExprFold(
@@ -197654,10 +204501,12 @@ static int sqlite3Fts5ExprInit(Fts5Global *pGlobal, sqlite3 *db){
rc = sqlite3_create_function(db, p->z, -1, SQLITE_UTF8, pCtx, p->x, 0, 0);
}
- /* Avoid a warning indicating that sqlite3Fts5ParserTrace() is unused */
+ /* Avoid warnings indicating that sqlite3Fts5ParserTrace() and
+ ** sqlite3Fts5ParserFallback() are unused */
#ifndef NDEBUG
(void)sqlite3Fts5ParserTrace;
#endif
+ (void)sqlite3Fts5ParserFallback;
return rc;
}
@@ -203705,7 +210554,10 @@ static int sqlite3Fts5IndexCharlenToBytelen(
for(i=0; i<nChar; i++){
if( n>=nByte ) return 0; /* Input contains fewer than nChar chars */
if( (unsigned char)p[n++]>=0xc0 ){
- while( (p[n] & 0xc0)==0x80 ) n++;
+ while( (p[n] & 0xc0)==0x80 ){
+ n++;
+ if( n>=nByte ) break;
+ }
}
}
return n;
@@ -205230,7 +212082,7 @@ static void fts5CheckTransactionState(Fts5Table *p, int op, int iSavepoint){
case FTS5_SAVEPOINT:
assert( p->ts.eState==1 );
assert( iSavepoint>=0 );
- assert( iSavepoint>p->ts.iSavepoint );
+ assert( iSavepoint>=p->ts.iSavepoint );
p->ts.iSavepoint = iSavepoint;
break;
@@ -206155,6 +213007,13 @@ static int fts5FilterMethod(
assert( nVal==0 && pMatch==0 && bOrderByRank==0 && bDesc==0 );
assert( pCsr->iLastRowid==LARGEST_INT64 );
assert( pCsr->iFirstRowid==SMALLEST_INT64 );
+ if( pTab->pSortCsr->bDesc ){
+ pCsr->iLastRowid = pTab->pSortCsr->iFirstRowid;
+ pCsr->iFirstRowid = pTab->pSortCsr->iLastRowid;
+ }else{
+ pCsr->iLastRowid = pTab->pSortCsr->iLastRowid;
+ pCsr->iFirstRowid = pTab->pSortCsr->iFirstRowid;
+ }
pCsr->ePlan = FTS5_PLAN_SOURCE;
pCsr->pExpr = pTab->pSortCsr->pExpr;
rc = fts5CursorFirst(pTab, pCsr, bDesc);
@@ -207585,7 +214444,7 @@ static void fts5SourceIdFunc(
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
- sqlite3_result_text(pCtx, "fts5: 2018-06-04 19:24:41 c7ee0833225bfd8c5ec2f9bf62b97c4e04d03bd9566366d5221ac8fb199a87ca", -1, SQLITE_TRANSIENT);
+ sqlite3_result_text(pCtx, "fts5: 2018-09-25 19:08:10 fb90e7189ae6d62e77ba3a308ca5d683f90bbe633cf681865365b8e92792d1c7", -1, SQLITE_TRANSIENT);
}
static int fts5Init(sqlite3 *db){
@@ -209073,6 +215932,8 @@ struct Unicode61Tokenizer {
int bRemoveDiacritic; /* True if remove_diacritics=1 is set */
int nException;
int *aiException;
+
+ unsigned char aCategory[32]; /* True for token char categories */
};
static int fts5UnicodeAddExceptions(
@@ -209097,7 +215958,7 @@ static int fts5UnicodeAddExceptions(
if( iCode<128 ){
p->aTokenChar[iCode] = (unsigned char)bTokenChars;
}else{
- bToken = sqlite3Fts5UnicodeIsalnum(iCode);
+ bToken = p->aCategory[sqlite3Fts5UnicodeCategory(iCode)];
assert( (bToken==0 || bToken==1) );
assert( (bTokenChars==0 || bTokenChars==1) );
if( bToken!=bTokenChars && sqlite3Fts5UnicodeIsdiacritic(iCode)==0 ){
@@ -209158,6 +216019,21 @@ static void fts5UnicodeDelete(Fts5Tokenizer *pTok){
return;
}
+static int unicodeSetCategories(Unicode61Tokenizer *p, const char *zCat){
+ const char *z = zCat;
+
+ while( *z ){
+ while( *z==' ' || *z=='\t' ) z++;
+ if( *z && sqlite3Fts5UnicodeCatParse(z, p->aCategory) ){
+ return SQLITE_ERROR;
+ }
+ while( *z!=' ' && *z!='\t' && *z!='\0' ) z++;
+ }
+
+ sqlite3Fts5UnicodeAscii(p->aCategory, p->aTokenChar);
+ return SQLITE_OK;
+}
+
/*
** Create a "unicode61" tokenizer.
*/
@@ -209176,15 +216052,28 @@ static int fts5UnicodeCreate(
}else{
p = (Unicode61Tokenizer*)sqlite3_malloc(sizeof(Unicode61Tokenizer));
if( p ){
+ const char *zCat = "L* N* Co";
int i;
memset(p, 0, sizeof(Unicode61Tokenizer));
- memcpy(p->aTokenChar, aAsciiTokenChar, sizeof(aAsciiTokenChar));
+
p->bRemoveDiacritic = 1;
p->nFold = 64;
p->aFold = sqlite3_malloc(p->nFold * sizeof(char));
if( p->aFold==0 ){
rc = SQLITE_NOMEM;
}
+
+ /* Search for a "categories" argument */
+ for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
+ if( 0==sqlite3_stricmp(azArg[i], "categories") ){
+ zCat = azArg[i+1];
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ rc = unicodeSetCategories(p, zCat);
+ }
+
for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
const char *zArg = azArg[i+1];
if( 0==sqlite3_stricmp(azArg[i], "remove_diacritics") ){
@@ -209198,10 +216087,14 @@ static int fts5UnicodeCreate(
}else
if( 0==sqlite3_stricmp(azArg[i], "separators") ){
rc = fts5UnicodeAddExceptions(p, zArg, 0);
+ }else
+ if( 0==sqlite3_stricmp(azArg[i], "categories") ){
+ /* no-op */
}else{
rc = SQLITE_ERROR;
}
}
+
}else{
rc = SQLITE_NOMEM;
}
@@ -209220,8 +216113,10 @@ static int fts5UnicodeCreate(
** character (not a separator).
*/
static int fts5UnicodeIsAlnum(Unicode61Tokenizer *p, int iCode){
- assert( (sqlite3Fts5UnicodeIsalnum(iCode) & 0xFFFFFFFE)==0 );
- return sqlite3Fts5UnicodeIsalnum(iCode) ^ fts5UnicodeIsException(p, iCode);
+ return (
+ p->aCategory[sqlite3Fts5UnicodeCategory(iCode)]
+ ^ fts5UnicodeIsException(p, iCode)
+ );
}
static int fts5UnicodeTokenize(
@@ -210097,135 +216992,6 @@ static int sqlite3Fts5TokenizerInit(fts5_api *pApi){
/* #include <assert.h> */
-/*
-** Return true if the argument corresponds to a unicode codepoint
-** classified as either a letter or a number. Otherwise false.
-**
-** The results are undefined if the value passed to this function
-** is less than zero.
-*/
-static int sqlite3Fts5UnicodeIsalnum(int c){
- /* Each unsigned integer in the following array corresponds to a contiguous
- ** range of unicode codepoints that are not either letters or numbers (i.e.
- ** codepoints for which this function should return 0).
- **
- ** The most significant 22 bits in each 32-bit value contain the first
- ** codepoint in the range. The least significant 10 bits are used to store
- ** the size of the range (always at least 1). In other words, the value
- ** ((C<<22) + N) represents a range of N codepoints starting with codepoint
- ** C. It is not possible to represent a range larger than 1023 codepoints
- ** using this format.
- */
- static const unsigned int aEntry[] = {
- 0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07,
- 0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01,
- 0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401,
- 0x000BBC81, 0x000DD401, 0x000DF801, 0x000E1002, 0x000E1C01,
- 0x000FD801, 0x00120808, 0x00156806, 0x00162402, 0x00163C01,
- 0x00164437, 0x0017CC02, 0x00180005, 0x00181816, 0x00187802,
- 0x00192C15, 0x0019A804, 0x0019C001, 0x001B5001, 0x001B580F,
- 0x001B9C07, 0x001BF402, 0x001C000E, 0x001C3C01, 0x001C4401,
- 0x001CC01B, 0x001E980B, 0x001FAC09, 0x001FD804, 0x00205804,
- 0x00206C09, 0x00209403, 0x0020A405, 0x0020C00F, 0x00216403,
- 0x00217801, 0x0023901B, 0x00240004, 0x0024E803, 0x0024F812,
- 0x00254407, 0x00258804, 0x0025C001, 0x00260403, 0x0026F001,
- 0x0026F807, 0x00271C02, 0x00272C03, 0x00275C01, 0x00278802,
- 0x0027C802, 0x0027E802, 0x00280403, 0x0028F001, 0x0028F805,
- 0x00291C02, 0x00292C03, 0x00294401, 0x0029C002, 0x0029D401,
- 0x002A0403, 0x002AF001, 0x002AF808, 0x002B1C03, 0x002B2C03,
- 0x002B8802, 0x002BC002, 0x002C0403, 0x002CF001, 0x002CF807,
- 0x002D1C02, 0x002D2C03, 0x002D5802, 0x002D8802, 0x002DC001,
- 0x002E0801, 0x002EF805, 0x002F1803, 0x002F2804, 0x002F5C01,
- 0x002FCC08, 0x00300403, 0x0030F807, 0x00311803, 0x00312804,
- 0x00315402, 0x00318802, 0x0031FC01, 0x00320802, 0x0032F001,
- 0x0032F807, 0x00331803, 0x00332804, 0x00335402, 0x00338802,
- 0x00340802, 0x0034F807, 0x00351803, 0x00352804, 0x00355C01,
- 0x00358802, 0x0035E401, 0x00360802, 0x00372801, 0x00373C06,
- 0x00375801, 0x00376008, 0x0037C803, 0x0038C401, 0x0038D007,
- 0x0038FC01, 0x00391C09, 0x00396802, 0x003AC401, 0x003AD006,
- 0x003AEC02, 0x003B2006, 0x003C041F, 0x003CD00C, 0x003DC417,
- 0x003E340B, 0x003E6424, 0x003EF80F, 0x003F380D, 0x0040AC14,
- 0x00412806, 0x00415804, 0x00417803, 0x00418803, 0x00419C07,
- 0x0041C404, 0x0042080C, 0x00423C01, 0x00426806, 0x0043EC01,
- 0x004D740C, 0x004E400A, 0x00500001, 0x0059B402, 0x005A0001,
- 0x005A6C02, 0x005BAC03, 0x005C4803, 0x005CC805, 0x005D4802,
- 0x005DC802, 0x005ED023, 0x005F6004, 0x005F7401, 0x0060000F,
- 0x0062A401, 0x0064800C, 0x0064C00C, 0x00650001, 0x00651002,
- 0x0066C011, 0x00672002, 0x00677822, 0x00685C05, 0x00687802,
- 0x0069540A, 0x0069801D, 0x0069FC01, 0x006A8007, 0x006AA006,
- 0x006C0005, 0x006CD011, 0x006D6823, 0x006E0003, 0x006E840D,
- 0x006F980E, 0x006FF004, 0x00709014, 0x0070EC05, 0x0071F802,
- 0x00730008, 0x00734019, 0x0073B401, 0x0073C803, 0x00770027,
- 0x0077F004, 0x007EF401, 0x007EFC03, 0x007F3403, 0x007F7403,
- 0x007FB403, 0x007FF402, 0x00800065, 0x0081A806, 0x0081E805,
- 0x00822805, 0x0082801A, 0x00834021, 0x00840002, 0x00840C04,
- 0x00842002, 0x00845001, 0x00845803, 0x00847806, 0x00849401,
- 0x00849C01, 0x0084A401, 0x0084B801, 0x0084E802, 0x00850005,
- 0x00852804, 0x00853C01, 0x00864264, 0x00900027, 0x0091000B,
- 0x0092704E, 0x00940200, 0x009C0475, 0x009E53B9, 0x00AD400A,
- 0x00B39406, 0x00B3BC03, 0x00B3E404, 0x00B3F802, 0x00B5C001,
- 0x00B5FC01, 0x00B7804F, 0x00B8C00C, 0x00BA001A, 0x00BA6C59,
- 0x00BC00D6, 0x00BFC00C, 0x00C00005, 0x00C02019, 0x00C0A807,
- 0x00C0D802, 0x00C0F403, 0x00C26404, 0x00C28001, 0x00C3EC01,
- 0x00C64002, 0x00C6580A, 0x00C70024, 0x00C8001F, 0x00C8A81E,
- 0x00C94001, 0x00C98020, 0x00CA2827, 0x00CB003F, 0x00CC0100,
- 0x01370040, 0x02924037, 0x0293F802, 0x02983403, 0x0299BC10,
- 0x029A7C01, 0x029BC008, 0x029C0017, 0x029C8002, 0x029E2402,
- 0x02A00801, 0x02A01801, 0x02A02C01, 0x02A08C09, 0x02A0D804,
- 0x02A1D004, 0x02A20002, 0x02A2D011, 0x02A33802, 0x02A38012,
- 0x02A3E003, 0x02A4980A, 0x02A51C0D, 0x02A57C01, 0x02A60004,
- 0x02A6CC1B, 0x02A77802, 0x02A8A40E, 0x02A90C01, 0x02A93002,
- 0x02A97004, 0x02A9DC03, 0x02A9EC01, 0x02AAC001, 0x02AAC803,
- 0x02AADC02, 0x02AAF802, 0x02AB0401, 0x02AB7802, 0x02ABAC07,
- 0x02ABD402, 0x02AF8C0B, 0x03600001, 0x036DFC02, 0x036FFC02,
- 0x037FFC01, 0x03EC7801, 0x03ECA401, 0x03EEC810, 0x03F4F802,
- 0x03F7F002, 0x03F8001A, 0x03F88007, 0x03F8C023, 0x03F95013,
- 0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807, 0x03FCEC06,
- 0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405, 0x04040003,
- 0x0404DC09, 0x0405E411, 0x0406400C, 0x0407402E, 0x040E7C01,
- 0x040F4001, 0x04215C01, 0x04247C01, 0x0424FC01, 0x04280403,
- 0x04281402, 0x04283004, 0x0428E003, 0x0428FC01, 0x04294009,
- 0x0429FC01, 0x042CE407, 0x04400003, 0x0440E016, 0x04420003,
- 0x0442C012, 0x04440003, 0x04449C0E, 0x04450004, 0x04460003,
- 0x0446CC0E, 0x04471404, 0x045AAC0D, 0x0491C004, 0x05BD442E,
- 0x05BE3C04, 0x074000F6, 0x07440027, 0x0744A4B5, 0x07480046,
- 0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01, 0x075C5401,
- 0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401, 0x075EA401,
- 0x075F0C01, 0x07BBC002, 0x07C0002C, 0x07C0C064, 0x07C2800F,
- 0x07C2C40E, 0x07C3040F, 0x07C3440F, 0x07C4401F, 0x07C4C03C,
- 0x07C5C02B, 0x07C7981D, 0x07C8402B, 0x07C90009, 0x07C94002,
- 0x07CC0021, 0x07CCC006, 0x07CCDC46, 0x07CE0014, 0x07CE8025,
- 0x07CF1805, 0x07CF8011, 0x07D0003F, 0x07D10001, 0x07D108B6,
- 0x07D3E404, 0x07D4003E, 0x07D50004, 0x07D54018, 0x07D7EC46,
- 0x07D9140B, 0x07DA0046, 0x07DC0074, 0x38000401, 0x38008060,
- 0x380400F0,
- };
- static const unsigned int aAscii[4] = {
- 0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001,
- };
-
- if( (unsigned int)c<128 ){
- return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
- }else if( (unsigned int)c<(1<<22) ){
- unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
- int iRes = 0;
- int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
- int iLo = 0;
- while( iHi>=iLo ){
- int iTest = (iHi + iLo) / 2;
- if( key >= aEntry[iTest] ){
- iRes = iTest;
- iLo = iTest+1;
- }else{
- iHi = iTest-1;
- }
- }
- assert( aEntry[0]<key );
- assert( key>=aEntry[iRes] );
- return (((unsigned int)c) >= ((aEntry[iRes]>>10) + (aEntry[iRes]&0x3FF)));
- }
- return 1;
-}
/*
@@ -210438,6 +217204,539 @@ static int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic){
return ret;
}
+
+#if 0
+static int sqlite3Fts5UnicodeNCat(void) {
+ return 32;
+}
+#endif
+
+static int sqlite3Fts5UnicodeCatParse(const char *zCat, u8 *aArray){
+ aArray[0] = 1;
+ switch( zCat[0] ){
+ case 'C':
+ switch( zCat[1] ){
+ case 'c': aArray[1] = 1; break;
+ case 'f': aArray[2] = 1; break;
+ case 'n': aArray[3] = 1; break;
+ case 's': aArray[4] = 1; break;
+ case 'o': aArray[31] = 1; break;
+ case '*':
+ aArray[1] = 1;
+ aArray[2] = 1;
+ aArray[3] = 1;
+ aArray[4] = 1;
+ aArray[31] = 1;
+ break;
+ default: return 1; }
+ break;
+
+ case 'L':
+ switch( zCat[1] ){
+ case 'l': aArray[5] = 1; break;
+ case 'm': aArray[6] = 1; break;
+ case 'o': aArray[7] = 1; break;
+ case 't': aArray[8] = 1; break;
+ case 'u': aArray[9] = 1; break;
+ case 'C': aArray[30] = 1; break;
+ case '*':
+ aArray[5] = 1;
+ aArray[6] = 1;
+ aArray[7] = 1;
+ aArray[8] = 1;
+ aArray[9] = 1;
+ aArray[30] = 1;
+ break;
+ default: return 1; }
+ break;
+
+ case 'M':
+ switch( zCat[1] ){
+ case 'c': aArray[10] = 1; break;
+ case 'e': aArray[11] = 1; break;
+ case 'n': aArray[12] = 1; break;
+ case '*':
+ aArray[10] = 1;
+ aArray[11] = 1;
+ aArray[12] = 1;
+ break;
+ default: return 1; }
+ break;
+
+ case 'N':
+ switch( zCat[1] ){
+ case 'd': aArray[13] = 1; break;
+ case 'l': aArray[14] = 1; break;
+ case 'o': aArray[15] = 1; break;
+ case '*':
+ aArray[13] = 1;
+ aArray[14] = 1;
+ aArray[15] = 1;
+ break;
+ default: return 1; }
+ break;
+
+ case 'P':
+ switch( zCat[1] ){
+ case 'c': aArray[16] = 1; break;
+ case 'd': aArray[17] = 1; break;
+ case 'e': aArray[18] = 1; break;
+ case 'f': aArray[19] = 1; break;
+ case 'i': aArray[20] = 1; break;
+ case 'o': aArray[21] = 1; break;
+ case 's': aArray[22] = 1; break;
+ case '*':
+ aArray[16] = 1;
+ aArray[17] = 1;
+ aArray[18] = 1;
+ aArray[19] = 1;
+ aArray[20] = 1;
+ aArray[21] = 1;
+ aArray[22] = 1;
+ break;
+ default: return 1; }
+ break;
+
+ case 'S':
+ switch( zCat[1] ){
+ case 'c': aArray[23] = 1; break;
+ case 'k': aArray[24] = 1; break;
+ case 'm': aArray[25] = 1; break;
+ case 'o': aArray[26] = 1; break;
+ case '*':
+ aArray[23] = 1;
+ aArray[24] = 1;
+ aArray[25] = 1;
+ aArray[26] = 1;
+ break;
+ default: return 1; }
+ break;
+
+ case 'Z':
+ switch( zCat[1] ){
+ case 'l': aArray[27] = 1; break;
+ case 'p': aArray[28] = 1; break;
+ case 's': aArray[29] = 1; break;
+ case '*':
+ aArray[27] = 1;
+ aArray[28] = 1;
+ aArray[29] = 1;
+ break;
+ default: return 1; }
+ break;
+
+ }
+ return 0;
+}
+
+static u16 aFts5UnicodeBlock[] = {
+ 0, 1471, 1753, 1760, 1760, 1760, 1760, 1760, 1760, 1760,
+ 1760, 1760, 1760, 1760, 1760, 1763, 1765,
+ };
+static u16 aFts5UnicodeMap[] = {
+ 0, 32, 33, 36, 37, 40, 41, 42, 43, 44,
+ 45, 46, 48, 58, 60, 63, 65, 91, 92, 93,
+ 94, 95, 96, 97, 123, 124, 125, 126, 127, 160,
+ 161, 162, 166, 167, 168, 169, 170, 171, 172, 173,
+ 174, 175, 176, 177, 178, 180, 181, 182, 184, 185,
+ 186, 187, 188, 191, 192, 215, 216, 223, 247, 248,
+ 256, 312, 313, 329, 330, 377, 383, 385, 387, 388,
+ 391, 394, 396, 398, 402, 403, 405, 406, 409, 412,
+ 414, 415, 417, 418, 423, 427, 428, 431, 434, 436,
+ 437, 440, 442, 443, 444, 446, 448, 452, 453, 454,
+ 455, 456, 457, 458, 459, 460, 461, 477, 478, 496,
+ 497, 498, 499, 500, 503, 505, 506, 564, 570, 572,
+ 573, 575, 577, 580, 583, 584, 592, 660, 661, 688,
+ 706, 710, 722, 736, 741, 748, 749, 750, 751, 768,
+ 880, 884, 885, 886, 890, 891, 894, 900, 902, 903,
+ 904, 908, 910, 912, 913, 931, 940, 975, 977, 978,
+ 981, 984, 1008, 1012, 1014, 1015, 1018, 1020, 1021, 1072,
+ 1120, 1154, 1155, 1160, 1162, 1217, 1231, 1232, 1329, 1369,
+ 1370, 1377, 1417, 1418, 1423, 1425, 1470, 1471, 1472, 1473,
+ 1475, 1476, 1478, 1479, 1488, 1520, 1523, 1536, 1542, 1545,
+ 1547, 1548, 1550, 1552, 1563, 1566, 1568, 1600, 1601, 1611,
+ 1632, 1642, 1646, 1648, 1649, 1748, 1749, 1750, 1757, 1758,
+ 1759, 1765, 1767, 1769, 1770, 1774, 1776, 1786, 1789, 1791,
+ 1792, 1807, 1808, 1809, 1810, 1840, 1869, 1958, 1969, 1984,
+ 1994, 2027, 2036, 2038, 2039, 2042, 2048, 2070, 2074, 2075,
+ 2084, 2085, 2088, 2089, 2096, 2112, 2137, 2142, 2208, 2210,
+ 2276, 2304, 2307, 2308, 2362, 2363, 2364, 2365, 2366, 2369,
+ 2377, 2381, 2382, 2384, 2385, 2392, 2402, 2404, 2406, 2416,
+ 2417, 2418, 2425, 2433, 2434, 2437, 2447, 2451, 2474, 2482,
+ 2486, 2492, 2493, 2494, 2497, 2503, 2507, 2509, 2510, 2519,
+ 2524, 2527, 2530, 2534, 2544, 2546, 2548, 2554, 2555, 2561,
+ 2563, 2565, 2575, 2579, 2602, 2610, 2613, 2616, 2620, 2622,
+ 2625, 2631, 2635, 2641, 2649, 2654, 2662, 2672, 2674, 2677,
+ 2689, 2691, 2693, 2703, 2707, 2730, 2738, 2741, 2748, 2749,
+ 2750, 2753, 2759, 2761, 2763, 2765, 2768, 2784, 2786, 2790,
+ 2800, 2801, 2817, 2818, 2821, 2831, 2835, 2858, 2866, 2869,
+ 2876, 2877, 2878, 2879, 2880, 2881, 2887, 2891, 2893, 2902,
+ 2903, 2908, 2911, 2914, 2918, 2928, 2929, 2930, 2946, 2947,
+ 2949, 2958, 2962, 2969, 2972, 2974, 2979, 2984, 2990, 3006,
+ 3008, 3009, 3014, 3018, 3021, 3024, 3031, 3046, 3056, 3059,
+ 3065, 3066, 3073, 3077, 3086, 3090, 3114, 3125, 3133, 3134,
+ 3137, 3142, 3146, 3157, 3160, 3168, 3170, 3174, 3192, 3199,
+ 3202, 3205, 3214, 3218, 3242, 3253, 3260, 3261, 3262, 3263,
+ 3264, 3270, 3271, 3274, 3276, 3285, 3294, 3296, 3298, 3302,
+ 3313, 3330, 3333, 3342, 3346, 3389, 3390, 3393, 3398, 3402,
+ 3405, 3406, 3415, 3424, 3426, 3430, 3440, 3449, 3450, 3458,
+ 3461, 3482, 3507, 3517, 3520, 3530, 3535, 3538, 3542, 3544,
+ 3570, 3572, 3585, 3633, 3634, 3636, 3647, 3648, 3654, 3655,
+ 3663, 3664, 3674, 3713, 3716, 3719, 3722, 3725, 3732, 3737,
+ 3745, 3749, 3751, 3754, 3757, 3761, 3762, 3764, 3771, 3773,
+ 3776, 3782, 3784, 3792, 3804, 3840, 3841, 3844, 3859, 3860,
+ 3861, 3864, 3866, 3872, 3882, 3892, 3893, 3894, 3895, 3896,
+ 3897, 3898, 3899, 3900, 3901, 3902, 3904, 3913, 3953, 3967,
+ 3968, 3973, 3974, 3976, 3981, 3993, 4030, 4038, 4039, 4046,
+ 4048, 4053, 4057, 4096, 4139, 4141, 4145, 4146, 4152, 4153,
+ 4155, 4157, 4159, 4160, 4170, 4176, 4182, 4184, 4186, 4190,
+ 4193, 4194, 4197, 4199, 4206, 4209, 4213, 4226, 4227, 4229,
+ 4231, 4237, 4238, 4239, 4240, 4250, 4253, 4254, 4256, 4295,
+ 4301, 4304, 4347, 4348, 4349, 4682, 4688, 4696, 4698, 4704,
+ 4746, 4752, 4786, 4792, 4800, 4802, 4808, 4824, 4882, 4888,
+ 4957, 4960, 4969, 4992, 5008, 5024, 5120, 5121, 5741, 5743,
+ 5760, 5761, 5787, 5788, 5792, 5867, 5870, 5888, 5902, 5906,
+ 5920, 5938, 5941, 5952, 5970, 5984, 5998, 6002, 6016, 6068,
+ 6070, 6071, 6078, 6086, 6087, 6089, 6100, 6103, 6104, 6107,
+ 6108, 6109, 6112, 6128, 6144, 6150, 6151, 6155, 6158, 6160,
+ 6176, 6211, 6212, 6272, 6313, 6314, 6320, 6400, 6432, 6435,
+ 6439, 6441, 6448, 6450, 6451, 6457, 6464, 6468, 6470, 6480,
+ 6512, 6528, 6576, 6593, 6600, 6608, 6618, 6622, 6656, 6679,
+ 6681, 6686, 6688, 6741, 6742, 6743, 6744, 6752, 6753, 6754,
+ 6755, 6757, 6765, 6771, 6783, 6784, 6800, 6816, 6823, 6824,
+ 6912, 6916, 6917, 6964, 6965, 6966, 6971, 6972, 6973, 6978,
+ 6979, 6981, 6992, 7002, 7009, 7019, 7028, 7040, 7042, 7043,
+ 7073, 7074, 7078, 7080, 7082, 7083, 7084, 7086, 7088, 7098,
+ 7142, 7143, 7144, 7146, 7149, 7150, 7151, 7154, 7164, 7168,
+ 7204, 7212, 7220, 7222, 7227, 7232, 7245, 7248, 7258, 7288,
+ 7294, 7360, 7376, 7379, 7380, 7393, 7394, 7401, 7405, 7406,
+ 7410, 7412, 7413, 7424, 7468, 7531, 7544, 7545, 7579, 7616,
+ 7676, 7680, 7830, 7838, 7936, 7944, 7952, 7960, 7968, 7976,
+ 7984, 7992, 8000, 8008, 8016, 8025, 8027, 8029, 8031, 8033,
+ 8040, 8048, 8064, 8072, 8080, 8088, 8096, 8104, 8112, 8118,
+ 8120, 8124, 8125, 8126, 8127, 8130, 8134, 8136, 8140, 8141,
+ 8144, 8150, 8152, 8157, 8160, 8168, 8173, 8178, 8182, 8184,
+ 8188, 8189, 8192, 8203, 8208, 8214, 8216, 8217, 8218, 8219,
+ 8221, 8222, 8223, 8224, 8232, 8233, 8234, 8239, 8240, 8249,
+ 8250, 8251, 8255, 8257, 8260, 8261, 8262, 8263, 8274, 8275,
+ 8276, 8277, 8287, 8288, 8298, 8304, 8305, 8308, 8314, 8317,
+ 8318, 8319, 8320, 8330, 8333, 8334, 8336, 8352, 8400, 8413,
+ 8417, 8418, 8421, 8448, 8450, 8451, 8455, 8456, 8458, 8459,
+ 8462, 8464, 8467, 8468, 8469, 8470, 8472, 8473, 8478, 8484,
+ 8485, 8486, 8487, 8488, 8489, 8490, 8494, 8495, 8496, 8500,
+ 8501, 8505, 8506, 8508, 8510, 8512, 8517, 8519, 8522, 8523,
+ 8524, 8526, 8527, 8528, 8544, 8579, 8581, 8585, 8592, 8597,
+ 8602, 8604, 8608, 8609, 8611, 8612, 8614, 8615, 8622, 8623,
+ 8654, 8656, 8658, 8659, 8660, 8661, 8692, 8960, 8968, 8972,
+ 8992, 8994, 9001, 9002, 9003, 9084, 9085, 9115, 9140, 9180,
+ 9186, 9216, 9280, 9312, 9372, 9450, 9472, 9655, 9656, 9665,
+ 9666, 9720, 9728, 9839, 9840, 9985, 10088, 10089, 10090, 10091,
+ 10092, 10093, 10094, 10095, 10096, 10097, 10098, 10099, 10100, 10101,
+ 10102, 10132, 10176, 10181, 10182, 10183, 10214, 10215, 10216, 10217,
+ 10218, 10219, 10220, 10221, 10222, 10223, 10224, 10240, 10496, 10627,
+ 10628, 10629, 10630, 10631, 10632, 10633, 10634, 10635, 10636, 10637,
+ 10638, 10639, 10640, 10641, 10642, 10643, 10644, 10645, 10646, 10647,
+ 10648, 10649, 10712, 10713, 10714, 10715, 10716, 10748, 10749, 10750,
+ 11008, 11056, 11077, 11079, 11088, 11264, 11312, 11360, 11363, 11365,
+ 11367, 11374, 11377, 11378, 11380, 11381, 11383, 11388, 11390, 11393,
+ 11394, 11492, 11493, 11499, 11503, 11506, 11513, 11517, 11518, 11520,
+ 11559, 11565, 11568, 11631, 11632, 11647, 11648, 11680, 11688, 11696,
+ 11704, 11712, 11720, 11728, 11736, 11744, 11776, 11778, 11779, 11780,
+ 11781, 11782, 11785, 11786, 11787, 11788, 11789, 11790, 11799, 11800,
+ 11802, 11803, 11804, 11805, 11806, 11808, 11809, 11810, 11811, 11812,
+ 11813, 11814, 11815, 11816, 11817, 11818, 11823, 11824, 11834, 11904,
+ 11931, 12032, 12272, 12288, 12289, 12292, 12293, 12294, 12295, 12296,
+ 12297, 12298, 12299, 12300, 12301, 12302, 12303, 12304, 12305, 12306,
+ 12308, 12309, 12310, 12311, 12312, 12313, 12314, 12315, 12316, 12317,
+ 12318, 12320, 12321, 12330, 12334, 12336, 12337, 12342, 12344, 12347,
+ 12348, 12349, 12350, 12353, 12441, 12443, 12445, 12447, 12448, 12449,
+ 12539, 12540, 12543, 12549, 12593, 12688, 12690, 12694, 12704, 12736,
+ 12784, 12800, 12832, 12842, 12872, 12880, 12881, 12896, 12928, 12938,
+ 12977, 12992, 13056, 13312, 19893, 19904, 19968, 40908, 40960, 40981,
+ 40982, 42128, 42192, 42232, 42238, 42240, 42508, 42509, 42512, 42528,
+ 42538, 42560, 42606, 42607, 42608, 42611, 42612, 42622, 42623, 42624,
+ 42655, 42656, 42726, 42736, 42738, 42752, 42775, 42784, 42786, 42800,
+ 42802, 42864, 42865, 42873, 42878, 42888, 42889, 42891, 42896, 42912,
+ 43000, 43002, 43003, 43010, 43011, 43014, 43015, 43019, 43020, 43043,
+ 43045, 43047, 43048, 43056, 43062, 43064, 43065, 43072, 43124, 43136,
+ 43138, 43188, 43204, 43214, 43216, 43232, 43250, 43256, 43259, 43264,
+ 43274, 43302, 43310, 43312, 43335, 43346, 43359, 43360, 43392, 43395,
+ 43396, 43443, 43444, 43446, 43450, 43452, 43453, 43457, 43471, 43472,
+ 43486, 43520, 43561, 43567, 43569, 43571, 43573, 43584, 43587, 43588,
+ 43596, 43597, 43600, 43612, 43616, 43632, 43633, 43639, 43642, 43643,
+ 43648, 43696, 43697, 43698, 43701, 43703, 43705, 43710, 43712, 43713,
+ 43714, 43739, 43741, 43742, 43744, 43755, 43756, 43758, 43760, 43762,
+ 43763, 43765, 43766, 43777, 43785, 43793, 43808, 43816, 43968, 44003,
+ 44005, 44006, 44008, 44009, 44011, 44012, 44013, 44016, 44032, 55203,
+ 55216, 55243, 55296, 56191, 56319, 57343, 57344, 63743, 63744, 64112,
+ 64256, 64275, 64285, 64286, 64287, 64297, 64298, 64312, 64318, 64320,
+ 64323, 64326, 64434, 64467, 64830, 64831, 64848, 64914, 65008, 65020,
+ 65021, 65024, 65040, 65047, 65048, 65049, 65056, 65072, 65073, 65075,
+ 65077, 65078, 65079, 65080, 65081, 65082, 65083, 65084, 65085, 65086,
+ 65087, 65088, 65089, 65090, 65091, 65092, 65093, 65095, 65096, 65097,
+ 65101, 65104, 65108, 65112, 65113, 65114, 65115, 65116, 65117, 65118,
+ 65119, 65122, 65123, 65124, 65128, 65129, 65130, 65136, 65142, 65279,
+ 65281, 65284, 65285, 65288, 65289, 65290, 65291, 65292, 65293, 65294,
+ 65296, 65306, 65308, 65311, 65313, 65339, 65340, 65341, 65342, 65343,
+ 65344, 65345, 65371, 65372, 65373, 65374, 65375, 65376, 65377, 65378,
+ 65379, 65380, 65382, 65392, 65393, 65438, 65440, 65474, 65482, 65490,
+ 65498, 65504, 65506, 65507, 65508, 65509, 65512, 65513, 65517, 65529,
+ 65532, 0, 13, 40, 60, 63, 80, 128, 256, 263,
+ 311, 320, 373, 377, 394, 400, 464, 509, 640, 672,
+ 768, 800, 816, 833, 834, 842, 896, 927, 928, 968,
+ 976, 977, 1024, 1064, 1104, 1184, 2048, 2056, 2058, 2103,
+ 2108, 2111, 2135, 2136, 2304, 2326, 2335, 2336, 2367, 2432,
+ 2494, 2560, 2561, 2565, 2572, 2576, 2581, 2585, 2616, 2623,
+ 2624, 2640, 2656, 2685, 2687, 2816, 2873, 2880, 2904, 2912,
+ 2936, 3072, 3680, 4096, 4097, 4098, 4099, 4152, 4167, 4178,
+ 4198, 4224, 4226, 4227, 4272, 4275, 4279, 4281, 4283, 4285,
+ 4286, 4304, 4336, 4352, 4355, 4391, 4396, 4397, 4406, 4416,
+ 4480, 4482, 4483, 4531, 4534, 4543, 4545, 4549, 4560, 5760,
+ 5803, 5804, 5805, 5806, 5808, 5814, 5815, 5824, 8192, 9216,
+ 9328, 12288, 26624, 28416, 28496, 28497, 28559, 28563, 45056, 53248,
+ 53504, 53545, 53605, 53607, 53610, 53613, 53619, 53627, 53635, 53637,
+ 53644, 53674, 53678, 53760, 53826, 53829, 54016, 54112, 54272, 54298,
+ 54324, 54350, 54358, 54376, 54402, 54428, 54430, 54434, 54437, 54441,
+ 54446, 54454, 54459, 54461, 54469, 54480, 54506, 54532, 54535, 54541,
+ 54550, 54558, 54584, 54587, 54592, 54598, 54602, 54610, 54636, 54662,
+ 54688, 54714, 54740, 54766, 54792, 54818, 54844, 54870, 54896, 54922,
+ 54952, 54977, 54978, 55003, 55004, 55010, 55035, 55036, 55061, 55062,
+ 55068, 55093, 55094, 55119, 55120, 55126, 55151, 55152, 55177, 55178,
+ 55184, 55209, 55210, 55235, 55236, 55242, 55246, 60928, 60933, 60961,
+ 60964, 60967, 60969, 60980, 60985, 60987, 60994, 60999, 61001, 61003,
+ 61005, 61009, 61012, 61015, 61017, 61019, 61021, 61023, 61025, 61028,
+ 61031, 61036, 61044, 61049, 61054, 61056, 61067, 61089, 61093, 61099,
+ 61168, 61440, 61488, 61600, 61617, 61633, 61649, 61696, 61712, 61744,
+ 61808, 61926, 61968, 62016, 62032, 62208, 62256, 62263, 62336, 62368,
+ 62406, 62432, 62464, 62528, 62530, 62713, 62720, 62784, 62800, 62971,
+ 63045, 63104, 63232, 0, 42710, 42752, 46900, 46912, 47133, 63488,
+ 1, 32, 256, 0, 65533,
+ };
+static u16 aFts5UnicodeData[] = {
+ 1025, 61, 117, 55, 117, 54, 50, 53, 57, 53,
+ 49, 85, 333, 85, 121, 85, 841, 54, 53, 50,
+ 56, 48, 56, 837, 54, 57, 50, 57, 1057, 61,
+ 53, 151, 58, 53, 56, 58, 39, 52, 57, 34,
+ 58, 56, 58, 57, 79, 56, 37, 85, 56, 47,
+ 39, 51, 111, 53, 745, 57, 233, 773, 57, 261,
+ 1822, 37, 542, 37, 1534, 222, 69, 73, 37, 126,
+ 126, 73, 69, 137, 37, 73, 37, 105, 101, 73,
+ 37, 73, 37, 190, 158, 37, 126, 126, 73, 37,
+ 126, 94, 37, 39, 94, 69, 135, 41, 40, 37,
+ 41, 40, 37, 41, 40, 37, 542, 37, 606, 37,
+ 41, 40, 37, 126, 73, 37, 1886, 197, 73, 37,
+ 73, 69, 126, 105, 37, 286, 2181, 39, 869, 582,
+ 152, 390, 472, 166, 248, 38, 56, 38, 568, 3596,
+ 158, 38, 56, 94, 38, 101, 53, 88, 41, 53,
+ 105, 41, 73, 37, 553, 297, 1125, 94, 37, 105,
+ 101, 798, 133, 94, 57, 126, 94, 37, 1641, 1541,
+ 1118, 58, 172, 75, 1790, 478, 37, 2846, 1225, 38,
+ 213, 1253, 53, 49, 55, 1452, 49, 44, 53, 76,
+ 53, 76, 53, 44, 871, 103, 85, 162, 121, 85,
+ 55, 85, 90, 364, 53, 85, 1031, 38, 327, 684,
+ 333, 149, 71, 44, 3175, 53, 39, 236, 34, 58,
+ 204, 70, 76, 58, 140, 71, 333, 103, 90, 39,
+ 469, 34, 39, 44, 967, 876, 2855, 364, 39, 333,
+ 1063, 300, 70, 58, 117, 38, 711, 140, 38, 300,
+ 38, 108, 38, 172, 501, 807, 108, 53, 39, 359,
+ 876, 108, 42, 1735, 44, 42, 44, 39, 106, 268,
+ 138, 44, 74, 39, 236, 327, 76, 85, 333, 53,
+ 38, 199, 231, 44, 74, 263, 71, 711, 231, 39,
+ 135, 44, 39, 106, 140, 74, 74, 44, 39, 42,
+ 71, 103, 76, 333, 71, 87, 207, 58, 55, 76,
+ 42, 199, 71, 711, 231, 71, 71, 71, 44, 106,
+ 76, 76, 108, 44, 135, 39, 333, 76, 103, 44,
+ 76, 42, 295, 103, 711, 231, 71, 167, 44, 39,
+ 106, 172, 76, 42, 74, 44, 39, 71, 76, 333,
+ 53, 55, 44, 74, 263, 71, 711, 231, 71, 167,
+ 44, 39, 42, 44, 42, 140, 74, 74, 44, 44,
+ 42, 71, 103, 76, 333, 58, 39, 207, 44, 39,
+ 199, 103, 135, 71, 39, 71, 71, 103, 391, 74,
+ 44, 74, 106, 106, 44, 39, 42, 333, 111, 218,
+ 55, 58, 106, 263, 103, 743, 327, 167, 39, 108,
+ 138, 108, 140, 76, 71, 71, 76, 333, 239, 58,
+ 74, 263, 103, 743, 327, 167, 44, 39, 42, 44,
+ 170, 44, 74, 74, 76, 74, 39, 71, 76, 333,
+ 71, 74, 263, 103, 1319, 39, 106, 140, 106, 106,
+ 44, 39, 42, 71, 76, 333, 207, 58, 199, 74,
+ 583, 775, 295, 39, 231, 44, 106, 108, 44, 266,
+ 74, 53, 1543, 44, 71, 236, 55, 199, 38, 268,
+ 53, 333, 85, 71, 39, 71, 39, 39, 135, 231,
+ 103, 39, 39, 71, 135, 44, 71, 204, 76, 39,
+ 167, 38, 204, 333, 135, 39, 122, 501, 58, 53,
+ 122, 76, 218, 333, 335, 58, 44, 58, 44, 58,
+ 44, 54, 50, 54, 50, 74, 263, 1159, 460, 42,
+ 172, 53, 76, 167, 364, 1164, 282, 44, 218, 90,
+ 181, 154, 85, 1383, 74, 140, 42, 204, 42, 76,
+ 74, 76, 39, 333, 213, 199, 74, 76, 135, 108,
+ 39, 106, 71, 234, 103, 140, 423, 44, 74, 76,
+ 202, 44, 39, 42, 333, 106, 44, 90, 1225, 41,
+ 41, 1383, 53, 38, 10631, 135, 231, 39, 135, 1319,
+ 135, 1063, 135, 231, 39, 135, 487, 1831, 135, 2151,
+ 108, 309, 655, 519, 346, 2727, 49, 19847, 85, 551,
+ 61, 839, 54, 50, 2407, 117, 110, 423, 135, 108,
+ 583, 108, 85, 583, 76, 423, 103, 76, 1671, 76,
+ 42, 236, 266, 44, 74, 364, 117, 38, 117, 55,
+ 39, 44, 333, 335, 213, 49, 149, 108, 61, 333,
+ 1127, 38, 1671, 1319, 44, 39, 2247, 935, 108, 138,
+ 76, 106, 74, 44, 202, 108, 58, 85, 333, 967,
+ 167, 1415, 554, 231, 74, 333, 47, 1114, 743, 76,
+ 106, 85, 1703, 42, 44, 42, 236, 44, 42, 44,
+ 74, 268, 202, 332, 44, 333, 333, 245, 38, 213,
+ 140, 42, 1511, 44, 42, 172, 42, 44, 170, 44,
+ 74, 231, 333, 245, 346, 300, 314, 76, 42, 967,
+ 42, 140, 74, 76, 42, 44, 74, 71, 333, 1415,
+ 44, 42, 76, 106, 44, 42, 108, 74, 149, 1159,
+ 266, 268, 74, 76, 181, 333, 103, 333, 967, 198,
+ 85, 277, 108, 53, 428, 42, 236, 135, 44, 135,
+ 74, 44, 71, 1413, 2022, 421, 38, 1093, 1190, 1260,
+ 140, 4830, 261, 3166, 261, 265, 197, 201, 261, 265,
+ 261, 265, 197, 201, 261, 41, 41, 41, 94, 229,
+ 265, 453, 261, 264, 261, 264, 261, 264, 165, 69,
+ 137, 40, 56, 37, 120, 101, 69, 137, 40, 120,
+ 133, 69, 137, 120, 261, 169, 120, 101, 69, 137,
+ 40, 88, 381, 162, 209, 85, 52, 51, 54, 84,
+ 51, 54, 52, 277, 59, 60, 162, 61, 309, 52,
+ 51, 149, 80, 117, 57, 54, 50, 373, 57, 53,
+ 48, 341, 61, 162, 194, 47, 38, 207, 121, 54,
+ 50, 38, 335, 121, 54, 50, 422, 855, 428, 139,
+ 44, 107, 396, 90, 41, 154, 41, 90, 37, 105,
+ 69, 105, 37, 58, 41, 90, 57, 169, 218, 41,
+ 58, 41, 58, 41, 58, 137, 58, 37, 137, 37,
+ 135, 37, 90, 69, 73, 185, 94, 101, 58, 57,
+ 90, 37, 58, 527, 1134, 94, 142, 47, 185, 186,
+ 89, 154, 57, 90, 57, 90, 57, 250, 57, 1018,
+ 89, 90, 57, 58, 57, 1018, 8601, 282, 153, 666,
+ 89, 250, 54, 50, 2618, 57, 986, 825, 1306, 217,
+ 602, 1274, 378, 1935, 2522, 719, 5882, 57, 314, 57,
+ 1754, 281, 3578, 57, 4634, 3322, 54, 50, 54, 50,
+ 54, 50, 54, 50, 54, 50, 54, 50, 54, 50,
+ 975, 1434, 185, 54, 50, 1017, 54, 50, 54, 50,
+ 54, 50, 54, 50, 54, 50, 537, 8218, 4217, 54,
+ 50, 54, 50, 54, 50, 54, 50, 54, 50, 54,
+ 50, 54, 50, 54, 50, 54, 50, 54, 50, 54,
+ 50, 2041, 54, 50, 54, 50, 1049, 54, 50, 8281,
+ 1562, 697, 90, 217, 346, 1513, 1509, 126, 73, 69,
+ 254, 105, 37, 94, 37, 94, 165, 70, 105, 37,
+ 3166, 37, 218, 158, 108, 94, 149, 47, 85, 1221,
+ 37, 37, 1799, 38, 53, 44, 743, 231, 231, 231,
+ 231, 231, 231, 231, 231, 1036, 85, 52, 51, 52,
+ 51, 117, 52, 51, 53, 52, 51, 309, 49, 85,
+ 49, 53, 52, 51, 85, 52, 51, 54, 50, 54,
+ 50, 54, 50, 54, 50, 181, 38, 341, 81, 858,
+ 2874, 6874, 410, 61, 117, 58, 38, 39, 46, 54,
+ 50, 54, 50, 54, 50, 54, 50, 54, 50, 90,
+ 54, 50, 54, 50, 54, 50, 54, 50, 49, 54,
+ 82, 58, 302, 140, 74, 49, 166, 90, 110, 38,
+ 39, 53, 90, 2759, 76, 88, 70, 39, 49, 2887,
+ 53, 102, 39, 1319, 3015, 90, 143, 346, 871, 1178,
+ 519, 1018, 335, 986, 271, 58, 495, 1050, 335, 1274,
+ 495, 2042, 8218, 39, 39, 2074, 39, 39, 679, 38,
+ 36583, 1786, 1287, 198, 85, 8583, 38, 117, 519, 333,
+ 71, 1502, 39, 44, 107, 53, 332, 53, 38, 798,
+ 44, 2247, 334, 76, 213, 760, 294, 88, 478, 69,
+ 2014, 38, 261, 190, 350, 38, 88, 158, 158, 382,
+ 70, 37, 231, 44, 103, 44, 135, 44, 743, 74,
+ 76, 42, 154, 207, 90, 55, 58, 1671, 149, 74,
+ 1607, 522, 44, 85, 333, 588, 199, 117, 39, 333,
+ 903, 268, 85, 743, 364, 74, 53, 935, 108, 42,
+ 1511, 44, 74, 140, 74, 44, 138, 437, 38, 333,
+ 85, 1319, 204, 74, 76, 74, 76, 103, 44, 263,
+ 44, 42, 333, 149, 519, 38, 199, 122, 39, 42,
+ 1543, 44, 39, 108, 71, 76, 167, 76, 39, 44,
+ 39, 71, 38, 85, 359, 42, 76, 74, 85, 39,
+ 70, 42, 44, 199, 199, 199, 231, 231, 1127, 74,
+ 44, 74, 44, 74, 53, 42, 44, 333, 39, 39,
+ 743, 1575, 36, 68, 68, 36, 63, 63, 11719, 3399,
+ 229, 165, 39, 44, 327, 57, 423, 167, 39, 71,
+ 71, 3463, 536, 11623, 54, 50, 2055, 1735, 391, 55,
+ 58, 524, 245, 54, 50, 53, 236, 53, 81, 80,
+ 54, 50, 54, 50, 54, 50, 54, 50, 54, 50,
+ 54, 50, 54, 50, 54, 50, 85, 54, 50, 149,
+ 112, 117, 149, 49, 54, 50, 54, 50, 54, 50,
+ 117, 57, 49, 121, 53, 55, 85, 167, 4327, 34,
+ 117, 55, 117, 54, 50, 53, 57, 53, 49, 85,
+ 333, 85, 121, 85, 841, 54, 53, 50, 56, 48,
+ 56, 837, 54, 57, 50, 57, 54, 50, 53, 54,
+ 50, 85, 327, 38, 1447, 70, 999, 199, 199, 199,
+ 103, 87, 57, 56, 58, 87, 58, 153, 90, 98,
+ 90, 391, 839, 615, 71, 487, 455, 3943, 117, 1455,
+ 314, 1710, 143, 570, 47, 410, 1466, 44, 935, 1575,
+ 999, 143, 551, 46, 263, 46, 967, 53, 1159, 263,
+ 53, 174, 1289, 1285, 2503, 333, 199, 39, 1415, 71,
+ 39, 743, 53, 271, 711, 207, 53, 839, 53, 1799,
+ 71, 39, 108, 76, 140, 135, 103, 871, 108, 44,
+ 271, 309, 935, 79, 53, 1735, 245, 711, 271, 615,
+ 271, 2343, 1007, 42, 44, 42, 1703, 492, 245, 655,
+ 333, 76, 42, 1447, 106, 140, 74, 76, 85, 34,
+ 149, 807, 333, 108, 1159, 172, 42, 268, 333, 149,
+ 76, 42, 1543, 106, 300, 74, 135, 149, 333, 1383,
+ 44, 42, 44, 74, 204, 42, 44, 333, 28135, 3182,
+ 149, 34279, 18215, 2215, 39, 1482, 140, 422, 71, 7898,
+ 1274, 1946, 74, 108, 122, 202, 258, 268, 90, 236,
+ 986, 140, 1562, 2138, 108, 58, 2810, 591, 841, 837,
+ 841, 229, 581, 841, 837, 41, 73, 41, 73, 137,
+ 265, 133, 37, 229, 357, 841, 837, 73, 137, 265,
+ 233, 837, 73, 137, 169, 41, 233, 837, 841, 837,
+ 841, 837, 841, 837, 841, 837, 841, 837, 841, 901,
+ 809, 57, 805, 57, 197, 809, 57, 805, 57, 197,
+ 809, 57, 805, 57, 197, 809, 57, 805, 57, 197,
+ 809, 57, 805, 57, 197, 94, 1613, 135, 871, 71,
+ 39, 39, 327, 135, 39, 39, 39, 39, 39, 39,
+ 103, 71, 39, 39, 39, 39, 39, 39, 71, 39,
+ 135, 231, 135, 135, 39, 327, 551, 103, 167, 551,
+ 89, 1434, 3226, 506, 474, 506, 506, 367, 1018, 1946,
+ 1402, 954, 1402, 314, 90, 1082, 218, 2266, 666, 1210,
+ 186, 570, 2042, 58, 5850, 154, 2010, 154, 794, 2266,
+ 378, 2266, 3738, 39, 39, 39, 39, 39, 39, 17351,
+ 34, 3074, 7692, 63, 63,
+ };
+
+static int sqlite3Fts5UnicodeCategory(int iCode) {
+ int iRes = -1;
+ int iHi;
+ int iLo;
+ int ret;
+ u16 iKey;
+
+ if( iCode>=(1<<20) ){
+ return 0;
+ }
+ iLo = aFts5UnicodeBlock[(iCode>>16)];
+ iHi = aFts5UnicodeBlock[1+(iCode>>16)];
+ iKey = (iCode & 0xFFFF);
+ while( iHi>iLo ){
+ int iTest = (iHi + iLo) / 2;
+ assert( iTest>=iLo && iTest<iHi );
+ if( iKey>=aFts5UnicodeMap[iTest] ){
+ iRes = iTest;
+ iLo = iTest+1;
+ }else{
+ iHi = iTest;
+ }
+ }
+
+ if( iRes<0 ) return 0;
+ if( iKey>=(aFts5UnicodeMap[iRes]+(aFts5UnicodeData[iRes]>>5)) ) return 0;
+ ret = aFts5UnicodeData[iRes] & 0x1F;
+ if( ret!=30 ) return ret;
+ return ((iKey - aFts5UnicodeMap[iRes]) & 0x01) ? 5 : 9;
+}
+
+static void sqlite3Fts5UnicodeAscii(u8 *aArray, u8 *aAscii){
+ int i = 0;
+ int iTbl = 0;
+ while( i<128 ){
+ int bToken = aArray[ aFts5UnicodeData[iTbl] & 0x1F ];
+ int n = (aFts5UnicodeData[iTbl] >> 5) + i;
+ for(; i<128 && i<n; i++){
+ aAscii[i] = (u8)bToken;
+ }
+ iTbl++;
+ }
+}
+
+
/*
** 2015 May 30
**
@@ -211855,9 +219154,9 @@ SQLITE_API int sqlite3_stmt_init(
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
/************** End of stmt.c ************************************************/
-#if __LINE__!=211858
+#if __LINE__!=219157
#undef SQLITE_SOURCE_ID
-#define SQLITE_SOURCE_ID "2018-06-04 19:24:41 c7ee0833225bfd8c5ec2f9bf62b97c4e04d03bd9566366d5221ac8fb199aalt2"
+#define SQLITE_SOURCE_ID "2018-09-25 19:08:10 fb90e7189ae6d62e77ba3a308ca5d683f90bbe633cf681865365b8e92792alt2"
#endif
/* Return the source-id for this library */
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
diff --git a/src/3rdparty/sqlite/sqlite3.h b/src/3rdparty/sqlite/sqlite3.h
index 4427d2fa27..4612ecda7f 100644
--- a/src/3rdparty/sqlite/sqlite3.h
+++ b/src/3rdparty/sqlite/sqlite3.h
@@ -123,9 +123,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.24.0"
-#define SQLITE_VERSION_NUMBER 3024000
-#define SQLITE_SOURCE_ID "2018-06-04 19:24:41 c7ee0833225bfd8c5ec2f9bf62b97c4e04d03bd9566366d5221ac8fb199a87ca"
+#define SQLITE_VERSION "3.25.2"
+#define SQLITE_VERSION_NUMBER 3025002
+#define SQLITE_SOURCE_ID "2018-09-25 19:08:10 fb90e7189ae6d62e77ba3a308ca5d683f90bbe633cf681865365b8e92792d1c7"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -472,6 +472,7 @@ SQLITE_API int sqlite3_exec(
*/
#define SQLITE_ERROR_MISSING_COLLSEQ (SQLITE_ERROR | (1<<8))
#define SQLITE_ERROR_RETRY (SQLITE_ERROR | (2<<8))
+#define SQLITE_ERROR_SNAPSHOT (SQLITE_ERROR | (3<<8))
#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8))
@@ -511,6 +512,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
+#define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
@@ -886,7 +888,8 @@ struct sqlite3_io_methods {
** <li>[[SQLITE_FCNTL_PERSIST_WAL]]
** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
** persistent [WAL | Write Ahead Log] setting. By default, the auxiliary
-** write ahead log and shared memory files used for transaction control
+** write ahead log ([WAL file]) and shared memory
+** files used for transaction control
** are automatically deleted when the latest connection to the database
** closes. Setting persistent WAL mode causes those files to persist after
** close. Persisting the files is useful when other processes that do not
@@ -1072,6 +1075,26 @@ struct sqlite3_io_methods {
** a file lock using the xLock or xShmLock methods of the VFS to wait
** for up to M milliseconds before failing, where M is the single
** unsigned integer parameter.
+**
+** <li>[[SQLITE_FCNTL_DATA_VERSION]]
+** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to
+** a database file. The argument is a pointer to a 32-bit unsigned integer.
+** The "data version" for the pager is written into the pointer. The
+** "data version" changes whenever any change occurs to the corresponding
+** database file, either through SQL statements on the same database
+** connection or through transactions committed by separate database
+** connections possibly in other processes. The [sqlite3_total_changes()]
+** interface can be used to find if any database on the connection has changed,
+** but that interface responds to changes on TEMP as well as MAIN and does
+** not provide a mechanism to detect changes to MAIN only. Also, the
+** [sqlite3_total_changes()] interface responds to internal changes only and
+** omits changes made by other database connections. The
+** [PRAGMA data_version] command provide a mechanism to detect changes to
+** a single attached database that occur due to other database connections,
+** but omits changes implemented by the database connection on which it is
+** called. This file control is the only mechanism to detect changes that
+** happen either internally or externally and that are associated with
+** a particular attached database.
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE 1
@@ -1107,6 +1130,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32
#define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33
#define SQLITE_FCNTL_LOCK_TIMEOUT 34
+#define SQLITE_FCNTL_DATA_VERSION 35
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -2121,6 +2145,12 @@ struct sqlite3_mem_methods {
** with no schema and no content. The following process works even for
** a badly corrupted database file:
** <ol>
+** <li> If the database connection is newly opened, make sure it has read the
+** database schema by preparing then discarding some query against the
+** database, or calling sqlite3_table_column_metadata(), ignoring any
+** errors. This step is only necessary if the application desires to keep
+** the database in WAL mode after the reset if it was in WAL mode before
+** the reset.
** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
** <li> [sqlite3_exec](db, "[VACUUM]", 0, 0, 0);
** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0);
@@ -2269,12 +2299,17 @@ SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64);
** program, the value returned reflects the number of rows modified by the
** previous INSERT, UPDATE or DELETE statement within the same trigger.
**
-** See also the [sqlite3_total_changes()] interface, the
-** [count_changes pragma], and the [changes() SQL function].
-**
** If a separate thread makes changes on the same database connection
** while [sqlite3_changes()] is running then the value returned
** is unpredictable and not meaningful.
+**
+** See also:
+** <ul>
+** <li> the [sqlite3_total_changes()] interface
+** <li> the [count_changes pragma]
+** <li> the [changes() SQL function]
+** <li> the [data_version pragma]
+** </ul>
*/
SQLITE_API int sqlite3_changes(sqlite3*);
@@ -2292,13 +2327,26 @@ SQLITE_API int sqlite3_changes(sqlite3*);
** count, but those made as part of REPLACE constraint resolution are
** not. ^Changes to a view that are intercepted by INSTEAD OF triggers
** are not counted.
-**
-** See also the [sqlite3_changes()] interface, the
-** [count_changes pragma], and the [total_changes() SQL function].
**
+** This the [sqlite3_total_changes(D)] interface only reports the number
+** of rows that changed due to SQL statement run against database
+** connection D. Any changes by other database connections are ignored.
+** To detect changes against a database file from other database
+** connections use the [PRAGMA data_version] command or the
+** [SQLITE_FCNTL_DATA_VERSION] [file control].
+**
** If a separate thread makes changes on the same database connection
** while [sqlite3_total_changes()] is running then the value
** returned is unpredictable and not meaningful.
+**
+** See also:
+** <ul>
+** <li> the [sqlite3_changes()] interface
+** <li> the [count_changes pragma]
+** <li> the [changes() SQL function]
+** <li> the [data_version pragma]
+** <li> the [SQLITE_FCNTL_DATA_VERSION] [file control]
+** </ul>
*/
SQLITE_API int sqlite3_total_changes(sqlite3*);
@@ -3354,13 +3402,24 @@ SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int
** [database connection] D failed, then the sqlite3_errcode(D) interface
** returns the numeric [result code] or [extended result code] for that
** API call.
-** If the most recent API call was successful,
-** then the return value from sqlite3_errcode() is undefined.
** ^The sqlite3_extended_errcode()
** interface is the same except that it always returns the
** [extended result code] even when extended result codes are
** disabled.
**
+** The values returned by sqlite3_errcode() and/or
+** sqlite3_extended_errcode() might change with each API call.
+** Except, there are some interfaces that are guaranteed to never
+** change the value of the error code. The error-code preserving
+** interfaces are:
+**
+** <ul>
+** <li> sqlite3_errcode()
+** <li> sqlite3_extended_errcode()
+** <li> sqlite3_errmsg()
+** <li> sqlite3_errmsg16()
+** </ul>
+**
** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language
** text that describes the error, as either UTF-8 or UTF-16 respectively.
** ^(Memory to hold the error message string is managed internally.
@@ -4514,11 +4573,25 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
** [sqlite3_free()].
**
-** ^(If a memory allocation error occurs during the evaluation of any
-** of these routines, a default value is returned. The default value
-** is either the integer 0, the floating point number 0.0, or a NULL
-** pointer. Subsequent calls to [sqlite3_errcode()] will return
-** [SQLITE_NOMEM].)^
+** As long as the input parameters are correct, these routines will only
+** fail if an out-of-memory error occurs during a format conversion.
+** Only the following subset of interfaces are subject to out-of-memory
+** errors:
+**
+** <ul>
+** <li> sqlite3_column_blob()
+** <li> sqlite3_column_text()
+** <li> sqlite3_column_text16()
+** <li> sqlite3_column_bytes()
+** <li> sqlite3_column_bytes16()
+** </ul>
+**
+** If an out-of-memory error occurs, then the return value from these
+** routines is the same as if the column had contained an SQL NULL value.
+** Valid SQL NULL returns can be distinguished from out-of-memory errors
+** by invoking the [sqlite3_errcode()] immediately after the suspect
+** return value is obtained and before any
+** other SQLite interface is called on the same [database connection].
*/
SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol);
@@ -4595,11 +4668,13 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
**
** ^These functions (collectively known as "function creation routines")
** are used to add SQL functions or aggregates or to redefine the behavior
-** of existing SQL functions or aggregates. The only differences between
-** these routines are the text encoding expected for
-** the second parameter (the name of the function being created)
-** and the presence or absence of a destructor callback for
-** the application data pointer.
+** of existing SQL functions or aggregates. The only differences between
+** the three "sqlite3_create_function*" routines are the text encoding
+** expected for the second parameter (the name of the function being
+** created) and the presence or absence of a destructor callback for
+** the application data pointer. Function sqlite3_create_window_function()
+** is similar, but allows the user to supply the extra callback functions
+** needed by [aggregate window functions].
**
** ^The first parameter is the [database connection] to which the SQL
** function is to be added. ^If an application uses more than one database
@@ -4645,7 +4720,8 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
** ^(The fifth parameter is an arbitrary pointer. The implementation of the
** function can gain access to this pointer using [sqlite3_user_data()].)^
**
-** ^The sixth, seventh and eighth parameters, xFunc, xStep and xFinal, are
+** ^The sixth, seventh and eighth parameters passed to the three
+** "sqlite3_create_function*" functions, xFunc, xStep and xFinal, are
** pointers to C-language functions that implement the SQL function or
** aggregate. ^A scalar SQL function requires an implementation of the xFunc
** callback only; NULL pointers must be passed as the xStep and xFinal
@@ -4654,15 +4730,24 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
** SQL function or aggregate, pass NULL pointers for all three function
** callbacks.
**
-** ^(If the ninth parameter to sqlite3_create_function_v2() is not NULL,
-** then it is destructor for the application data pointer.
-** The destructor is invoked when the function is deleted, either by being
-** overloaded or when the database connection closes.)^
-** ^The destructor is also invoked if the call to
-** sqlite3_create_function_v2() fails.
-** ^When the destructor callback of the tenth parameter is invoked, it
-** is passed a single argument which is a copy of the application data
-** pointer which was the fifth parameter to sqlite3_create_function_v2().
+** ^The sixth, seventh, eighth and ninth parameters (xStep, xFinal, xValue
+** and xInverse) passed to sqlite3_create_window_function are pointers to
+** C-language callbacks that implement the new function. xStep and xFinal
+** must both be non-NULL. xValue and xInverse may either both be NULL, in
+** which case a regular aggregate function is created, or must both be
+** non-NULL, in which case the new function may be used as either an aggregate
+** or aggregate window function. More details regarding the implementation
+** of aggregate window functions are
+** [user-defined window functions|available here].
+**
+** ^(If the final parameter to sqlite3_create_function_v2() or
+** sqlite3_create_window_function() is not NULL, then it is destructor for
+** the application data pointer. The destructor is invoked when the function
+** is deleted, either by being overloaded or when the database connection
+** closes.)^ ^The destructor is also invoked if the call to
+** sqlite3_create_function_v2() fails. ^When the destructor callback is
+** invoked, it is passed a single argument which is a copy of the application
+** data pointer which was the fifth parameter to sqlite3_create_function_v2().
**
** ^It is permitted to register multiple implementations of the same
** functions with the same name but with either differing numbers of
@@ -4715,6 +4800,18 @@ SQLITE_API int sqlite3_create_function_v2(
void (*xFinal)(sqlite3_context*),
void(*xDestroy)(void*)
);
+SQLITE_API int sqlite3_create_window_function(
+ sqlite3 *db,
+ const char *zFunctionName,
+ int nArg,
+ int eTextRep,
+ void *pApp,
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**),
+ void (*xFinal)(sqlite3_context*),
+ void (*xValue)(sqlite3_context*),
+ void (*xInverse)(sqlite3_context*,int,sqlite3_value**),
+ void(*xDestroy)(void*)
+);
/*
** CAPI3REF: Text Encodings
@@ -4857,6 +4954,28 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
**
** These routines must be called from the same thread as
** the SQL function that supplied the [sqlite3_value*] parameters.
+**
+** As long as the input parameter is correct, these routines can only
+** fail if an out-of-memory error occurs during a format conversion.
+** Only the following subset of interfaces are subject to out-of-memory
+** errors:
+**
+** <ul>
+** <li> sqlite3_value_blob()
+** <li> sqlite3_value_text()
+** <li> sqlite3_value_text16()
+** <li> sqlite3_value_text16le()
+** <li> sqlite3_value_text16be()
+** <li> sqlite3_value_bytes()
+** <li> sqlite3_value_bytes16()
+** </ul>
+**
+** If an out-of-memory error occurs, then the return value from these
+** routines is the same as if the column had contained an SQL NULL value.
+** Valid SQL NULL returns can be distinguished from out-of-memory errors
+** by invoking the [sqlite3_errcode()] immediately after the suspect
+** return value is obtained and before any
+** other SQLite interface is called on the same [database connection].
*/
SQLITE_API const void *sqlite3_value_blob(sqlite3_value*);
SQLITE_API double sqlite3_value_double(sqlite3_value*);
@@ -6323,6 +6442,7 @@ struct sqlite3_index_info {
#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70
#define SQLITE_INDEX_CONSTRAINT_ISNULL 71
#define SQLITE_INDEX_CONSTRAINT_IS 72
+#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150
/*
** CAPI3REF: Register A Virtual Table Implementation
@@ -6999,6 +7119,7 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
/*
** CAPI3REF: Low-Level Control Of Database Files
** METHOD: sqlite3
+** KEYWORDS: {file control}
**
** ^The [sqlite3_file_control()] interface makes a direct call to the
** xFileControl method for the [sqlite3_io_methods] object associated
@@ -7013,11 +7134,18 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
** the xFileControl method. ^The return value of the xFileControl
** method becomes the return value of this routine.
**
+** A few opcodes for [sqlite3_file_control()] are handled directly
+** by the SQLite core and never invoke the
+** sqlite3_io_methods.xFileControl method.
** ^The [SQLITE_FCNTL_FILE_POINTER] value for the op parameter causes
** a pointer to the underlying [sqlite3_file] object to be written into
-** the space pointed to by the 4th parameter. ^The [SQLITE_FCNTL_FILE_POINTER]
-** case is a short-circuit path which does not actually invoke the
-** underlying sqlite3_io_methods.xFileControl method.
+** the space pointed to by the 4th parameter. The
+** [SQLITE_FCNTL_JOURNAL_POINTER] works similarly except that it returns
+** the [sqlite3_file] object associated with the journal file instead of
+** the main database. The [SQLITE_FCNTL_VFS_POINTER] opcode returns
+** a pointer to the underlying [sqlite3_vfs] object for the file.
+** The [SQLITE_FCNTL_DATA_VERSION] returns the data version counter
+** from the pager.
**
** ^If the second parameter (zDbName) does not match the name of any
** open database file, then SQLITE_ERROR is returned. ^This error
@@ -8836,7 +8964,6 @@ SQLITE_API int sqlite3_system_errno(sqlite3*);
/*
** CAPI3REF: Database Snapshot
** KEYWORDS: {snapshot} {sqlite3_snapshot}
-** EXPERIMENTAL
**
** An instance of the snapshot object records the state of a [WAL mode]
** database for some specific point in history.
@@ -8853,11 +8980,6 @@ SQLITE_API int sqlite3_system_errno(sqlite3*);
** version of the database file so that it is possible to later open a new read
** transaction that sees that historical version of the database rather than
** the most recent version.
-**
-** The constructor for this object is [sqlite3_snapshot_get()]. The
-** [sqlite3_snapshot_open()] method causes a fresh read transaction to refer
-** to an historical snapshot (if possible). The destructor for
-** sqlite3_snapshot objects is [sqlite3_snapshot_free()].
*/
typedef struct sqlite3_snapshot {
unsigned char hidden[48];
@@ -8865,7 +8987,7 @@ typedef struct sqlite3_snapshot {
/*
** CAPI3REF: Record A Database Snapshot
-** EXPERIMENTAL
+** CONSTRUCTOR: sqlite3_snapshot
**
** ^The [sqlite3_snapshot_get(D,S,P)] interface attempts to make a
** new [sqlite3_snapshot] object that records the current state of
@@ -8881,7 +9003,7 @@ typedef struct sqlite3_snapshot {
** in this case.
**
** <ul>
-** <li> The database handle must be in [autocommit mode].
+** <li> The database handle must not be in [autocommit mode].
**
** <li> Schema S of [database connection] D must be a [WAL mode] database.
**
@@ -8904,7 +9026,7 @@ typedef struct sqlite3_snapshot {
** to avoid a memory leak.
**
** The [sqlite3_snapshot_get()] interface is only available when the
-** SQLITE_ENABLE_SNAPSHOT compile-time option is used.
+** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
*/
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get(
sqlite3 *db,
@@ -8914,24 +9036,35 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get(
/*
** CAPI3REF: Start a read transaction on an historical snapshot
-** EXPERIMENTAL
+** METHOD: sqlite3_snapshot
+**
+** ^The [sqlite3_snapshot_open(D,S,P)] interface either starts a new read
+** transaction or upgrades an existing one for schema S of
+** [database connection] D such that the read transaction refers to
+** historical [snapshot] P, rather than the most recent change to the
+** database. ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK
+** on success or an appropriate [error code] if it fails.
+**
+** ^In order to succeed, the database connection must not be in
+** [autocommit mode] when [sqlite3_snapshot_open(D,S,P)] is called. If there
+** is already a read transaction open on schema S, then the database handle
+** must have no active statements (SELECT statements that have been passed
+** to sqlite3_step() but not sqlite3_reset() or sqlite3_finalize()).
+** SQLITE_ERROR is returned if either of these conditions is violated, or
+** if schema S does not exist, or if the snapshot object is invalid.
+**
+** ^A call to sqlite3_snapshot_open() will fail to open if the specified
+** snapshot has been overwritten by a [checkpoint]. In this case
+** SQLITE_ERROR_SNAPSHOT is returned.
+**
+** If there is already a read transaction open when this function is
+** invoked, then the same read transaction remains open (on the same
+** database snapshot) if SQLITE_ERROR, SQLITE_BUSY or SQLITE_ERROR_SNAPSHOT
+** is returned. If another error code - for example SQLITE_PROTOCOL or an
+** SQLITE_IOERR error code - is returned, then the final state of the
+** read transaction is undefined. If SQLITE_OK is returned, then the
+** read transaction is now open on database snapshot P.
**
-** ^The [sqlite3_snapshot_open(D,S,P)] interface starts a
-** read transaction for schema S of
-** [database connection] D such that the read transaction
-** refers to historical [snapshot] P, rather than the most
-** recent change to the database.
-** ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK on success
-** or an appropriate [error code] if it fails.
-**
-** ^In order to succeed, a call to [sqlite3_snapshot_open(D,S,P)] must be
-** the first operation following the [BEGIN] that takes the schema S
-** out of [autocommit mode].
-** ^In other words, schema S must not currently be in
-** a transaction for [sqlite3_snapshot_open(D,S,P)] to work, but the
-** database connection D must be out of [autocommit mode].
-** ^A [snapshot] will fail to open if it has been overwritten by a
-** [checkpoint].
** ^(A call to [sqlite3_snapshot_open(D,S,P)] will fail if the
** database connection D does not know that the database file for
** schema S is in [WAL mode]. A database connection might not know
@@ -8942,7 +9075,7 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get(
** database connection in order to make it ready to use snapshots.)
**
** The [sqlite3_snapshot_open()] interface is only available when the
-** SQLITE_ENABLE_SNAPSHOT compile-time option is used.
+** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
*/
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open(
sqlite3 *db,
@@ -8952,20 +9085,20 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open(
/*
** CAPI3REF: Destroy a snapshot
-** EXPERIMENTAL
+** DESTRUCTOR: sqlite3_snapshot
**
** ^The [sqlite3_snapshot_free(P)] interface destroys [sqlite3_snapshot] P.
** The application must eventually free every [sqlite3_snapshot] object
** using this routine to avoid a memory leak.
**
** The [sqlite3_snapshot_free()] interface is only available when the
-** SQLITE_ENABLE_SNAPSHOT compile-time option is used.
+** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
*/
SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*);
/*
** CAPI3REF: Compare the ages of two snapshot handles.
-** EXPERIMENTAL
+** METHOD: sqlite3_snapshot
**
** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages
** of two valid snapshot handles.
@@ -8984,6 +9117,9 @@ SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*);
** Otherwise, this API returns a negative value if P1 refers to an older
** snapshot than P2, zero if the two handles refer to the same database
** snapshot, and a positive value if P1 is a newer snapshot than P2.
+**
+** This interface is only available if SQLite is compiled with the
+** [SQLITE_ENABLE_SNAPSHOT] option.
*/
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
sqlite3_snapshot *p1,
@@ -8992,23 +9128,26 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
/*
** CAPI3REF: Recover snapshots from a wal file
-** EXPERIMENTAL
+** METHOD: sqlite3_snapshot
**
-** If all connections disconnect from a database file but do not perform
-** a checkpoint, the existing wal file is opened along with the database
-** file the next time the database is opened. At this point it is only
-** possible to successfully call sqlite3_snapshot_open() to open the most
-** recent snapshot of the database (the one at the head of the wal file),
-** even though the wal file may contain other valid snapshots for which
-** clients have sqlite3_snapshot handles.
+** If a [WAL file] remains on disk after all database connections close
+** (either through the use of the [SQLITE_FCNTL_PERSIST_WAL] [file control]
+** or because the last process to have the database opened exited without
+** calling [sqlite3_close()]) and a new connection is subsequently opened
+** on that database and [WAL file], the [sqlite3_snapshot_open()] interface
+** will only be able to open the last transaction added to the WAL file
+** even though the WAL file contains other valid transactions.
**
-** This function attempts to scan the wal file associated with database zDb
+** This function attempts to scan the WAL file associated with database zDb
** of database handle db and make all valid snapshots available to
** sqlite3_snapshot_open(). It is an error if there is already a read
-** transaction open on the database, or if the database is not a wal mode
+** transaction open on the database, or if the database is not a WAL mode
** database.
**
** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
+**
+** This interface is only available if SQLite is compiled with the
+** [SQLITE_ENABLE_SNAPSHOT] option.
*/
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
@@ -9119,7 +9258,7 @@ SQLITE_API int sqlite3_deserialize(
** in the P argument is held in memory obtained from [sqlite3_malloc64()]
** and that SQLite should take ownership of this memory and automatically
** free it when it has finished using it. Without this flag, the caller
-** is resposible for freeing any dynamically allocated memory.
+** is responsible for freeing any dynamically allocated memory.
**
** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to
** grow the size of the database using calls to [sqlite3_realloc64()]. This
@@ -11297,7 +11436,7 @@ struct Fts5ExtensionApi {
** This way, even if the tokenizer does not provide synonyms
** when tokenizing query text (it should not - to do would be
** inefficient), it doesn't matter if the user queries for
-** 'first + place' or '1st + place', as there are entires in the
+** 'first + place' or '1st + place', as there are entries in the
** FTS index corresponding to both forms of the first token.
** </ol>
**
@@ -11325,7 +11464,7 @@ struct Fts5ExtensionApi {
** extra data to the FTS index or require FTS5 to query for multiple terms,
** so it is efficient in terms of disk space and query speed. However, it
** does not support prefix queries very well. If, as suggested above, the
-** token "first" is subsituted for "1st" by the tokenizer, then the query:
+** token "first" is substituted for "1st" by the tokenizer, then the query:
**
** <codeblock>
** ... MATCH '1s*'</codeblock>
diff --git a/src/3rdparty/tinycbor/.gitignore b/src/3rdparty/tinycbor/.gitignore
new file mode 100644
index 0000000000..3272de3326
--- /dev/null
+++ b/src/3rdparty/tinycbor/.gitignore
@@ -0,0 +1,81 @@
+# Frequent generated files
+callgrind.out.*
+pcviewer.cfg
+*~
+*.a
+*.la
+*.core
+*.d
+*.dylib
+*.moc
+*.o
+*.obj
+*.orig
+*.swp
+*.rej
+*.so
+*.so.*
+*.pbxuser
+*.mode1
+*.mode1v3
+*_pch.h.cpp
+*_resource.rc
+.#*
+*.*#
+core
+.qmake.cache
+.qmake.stash
+.qmake.vars
+.device.vars
+tags
+.DS_Store
+*.debug
+Makefile*
+*.prl
+*.app
+*.pro.user*
+*.qmlproject.user*
+*.gcov
+*.gcda
+*.gcno
+*.flc
+.*.swp
+tinycbor.pc
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.vcxproj
+*.vcxproj.filters
+*.vcxproj.user
+*.exe.embed.manifest
+*.exe_manifest.rc
+*.exe_manifest.res
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# INTEGRITY generated files
+*.gpj
+*.int
+*.ael
+*.dla
+*.dnm
+*.dep
+*.map
+
+bin
+doc
+lib
+src/cjson
+src/doxygen.log
+!/Makefile
+.config
diff --git a/src/3rdparty/tinycbor/LICENSE b/src/3rdparty/tinycbor/LICENSE
new file mode 100644
index 0000000000..4aad977ceb
--- /dev/null
+++ b/src/3rdparty/tinycbor/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 Intel Corporation
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/3rdparty/tinycbor/README b/src/3rdparty/tinycbor/README
new file mode 100644
index 0000000000..167efa06e2
--- /dev/null
+++ b/src/3rdparty/tinycbor/README
@@ -0,0 +1,13 @@
+Concise Binary Object Representation (CBOR) Library
+---------------------------------------------------
+
+To build TinyCBOR:
+
+ make
+
+If you want to change the compiler or pass extra compiler flags:
+
+ make CC=clang CFLAGS="-m32 -Oz" LDFLAGS="-m32"
+
+Documentation: https://intel.github.io/tinycbor/current/
+
diff --git a/src/3rdparty/tinycbor/VERSION b/src/3rdparty/tinycbor/VERSION
new file mode 100644
index 0000000000..a918a2aa18
--- /dev/null
+++ b/src/3rdparty/tinycbor/VERSION
@@ -0,0 +1 @@
+0.6.0
diff --git a/src/3rdparty/tinycbor/qt_attribution.json b/src/3rdparty/tinycbor/qt_attribution.json
new file mode 100644
index 0000000000..1d61534861
--- /dev/null
+++ b/src/3rdparty/tinycbor/qt_attribution.json
@@ -0,0 +1,14 @@
+{
+ "Id": "tinycbor",
+ "Name": "TinyCBOR",
+ "QDocModule": "qtcore",
+ "QtUsage": "Used for QCborStreamReader and QCborStreamWriter.",
+
+ "Description": "Concise Binary Object Representation (CBOR) Library",
+ "Homepage": "https://github.com/intel/tinycbor",
+ "License": "MIT License",
+ "LicenseId": "MIT",
+ "LicenseFile": "LICENSE",
+ "Version": "0.6+patches",
+ "Copyright": "Copyright (C) 2018 Intel Corporation"
+}
diff --git a/src/3rdparty/tinycbor/src/cbor.h b/src/3rdparty/tinycbor/src/cbor.h
new file mode 100644
index 0000000000..5c7ba74e39
--- /dev/null
+++ b/src/3rdparty/tinycbor/src/cbor.h
@@ -0,0 +1,722 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and associated documentation files (the "Software"), to deal
+** in the Software without restriction, including without limitation the rights
+** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+** copies of the Software, and to permit persons to whom the Software is
+** furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+** THE SOFTWARE.
+**
+****************************************************************************/
+
+#ifndef CBOR_H
+#define CBOR_H
+
+#ifndef assert
+#include <assert.h>
+#endif
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "tinycbor-version.h"
+
+#define TINYCBOR_VERSION ((TINYCBOR_VERSION_MAJOR << 16) | (TINYCBOR_VERSION_MINOR << 8) | TINYCBOR_VERSION_PATCH)
+
+#ifdef __cplusplus
+extern "C" {
+#else
+#include <stdbool.h>
+#endif
+
+#ifndef SIZE_MAX
+/* Some systems fail to define SIZE_MAX in <stdint.h>, even though C99 requires it...
+ * Conversion from signed to unsigned is defined in 6.3.1.3 (Signed and unsigned integers) p2,
+ * which says: "the value is converted by repeatedly adding or subtracting one more than the
+ * maximum value that can be represented in the new type until the value is in the range of the
+ * new type."
+ * So -1 gets converted to size_t by adding SIZE_MAX + 1, which results in SIZE_MAX.
+ */
+# define SIZE_MAX ((size_t)-1)
+#endif
+
+#ifndef CBOR_API
+# define CBOR_API
+#endif
+#ifndef CBOR_PRIVATE_API
+# define CBOR_PRIVATE_API
+#endif
+#ifndef CBOR_INLINE_API
+# if defined(__cplusplus)
+# define CBOR_INLINE inline
+# define CBOR_INLINE_API inline
+# else
+# define CBOR_INLINE_API static CBOR_INLINE
+# if defined(_MSC_VER)
+# define CBOR_INLINE __inline
+# elif defined(__GNUC__)
+# define CBOR_INLINE __inline__
+# elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+# define CBOR_INLINE inline
+# else
+# define CBOR_INLINE
+# endif
+# endif
+#endif
+
+typedef enum CborType {
+ CborIntegerType = 0x00,
+ CborByteStringType = 0x40,
+ CborTextStringType = 0x60,
+ CborArrayType = 0x80,
+ CborMapType = 0xa0,
+ CborTagType = 0xc0,
+ CborSimpleType = 0xe0,
+ CborBooleanType = 0xf5,
+ CborNullType = 0xf6,
+ CborUndefinedType = 0xf7,
+ CborHalfFloatType = 0xf9,
+ CborFloatType = 0xfa,
+ CborDoubleType = 0xfb,
+
+ CborInvalidType = 0xff /* equivalent to the break byte, so it will never be used */
+} CborType;
+
+typedef uint64_t CborTag;
+typedef enum CborKnownTags {
+ CborDateTimeStringTag = 0,
+ CborUnixTime_tTag = 1,
+ CborPositiveBignumTag = 2,
+ CborNegativeBignumTag = 3,
+ CborDecimalTag = 4,
+ CborBigfloatTag = 5,
+ CborCOSE_Encrypt0Tag = 16,
+ CborCOSE_Mac0Tag = 17,
+ CborCOSE_Sign1Tag = 18,
+ CborExpectedBase64urlTag = 21,
+ CborExpectedBase64Tag = 22,
+ CborExpectedBase16Tag = 23,
+ CborEncodedCborTag = 24,
+ CborUrlTag = 32,
+ CborBase64urlTag = 33,
+ CborBase64Tag = 34,
+ CborRegularExpressionTag = 35,
+ CborMimeMessageTag = 36,
+ CborCOSE_EncryptTag = 96,
+ CborCOSE_MacTag = 97,
+ CborCOSE_SignTag = 98,
+ CborSignatureTag = 55799
+} CborKnownTags;
+
+/* #define the constants so we can check with #ifdef */
+#define CborDateTimeStringTag CborDateTimeStringTag
+#define CborUnixTime_tTag CborUnixTime_tTag
+#define CborPositiveBignumTag CborPositiveBignumTag
+#define CborNegativeBignumTag CborNegativeBignumTag
+#define CborDecimalTag CborDecimalTag
+#define CborBigfloatTag CborBigfloatTag
+#define CborCOSE_Encrypt0Tag CborCOSE_Encrypt0Tag
+#define CborCOSE_Mac0Tag CborCOSE_Mac0Tag
+#define CborCOSE_Sign1Tag CborCOSE_Sign1Tag
+#define CborExpectedBase64urlTag CborExpectedBase64urlTag
+#define CborExpectedBase64Tag CborExpectedBase64Tag
+#define CborExpectedBase16Tag CborExpectedBase16Tag
+#define CborEncodedCborTag CborEncodedCborTag
+#define CborUrlTag CborUrlTag
+#define CborBase64urlTag CborBase64urlTag
+#define CborBase64Tag CborBase64Tag
+#define CborRegularExpressionTag CborRegularExpressionTag
+#define CborMimeMessageTag CborMimeMessageTag
+#define CborCOSE_EncryptTag CborCOSE_EncryptTag
+#define CborCOSE_MacTag CborCOSE_MacTag
+#define CborCOSE_SignTag CborCOSE_SignTag
+#define CborSignatureTag CborSignatureTag
+
+/* Error API */
+
+typedef enum CborError {
+ CborNoError = 0,
+
+ /* errors in all modes */
+ CborUnknownError,
+ CborErrorUnknownLength, /* request for length in array, map, or string with indeterminate length */
+ CborErrorAdvancePastEOF,
+ CborErrorIO,
+
+ /* parser errors streaming errors */
+ CborErrorGarbageAtEnd = 256,
+ CborErrorUnexpectedEOF,
+ CborErrorUnexpectedBreak,
+ CborErrorUnknownType, /* can only happen in major type 7 */
+ CborErrorIllegalType, /* type not allowed here */
+ CborErrorIllegalNumber,
+ CborErrorIllegalSimpleType, /* types of value less than 32 encoded in two bytes */
+ CborErrorNoMoreStringChunks,
+
+ /* parser errors in strict mode parsing only */
+ CborErrorUnknownSimpleType = 512,
+ CborErrorUnknownTag,
+ CborErrorInappropriateTagForType,
+ CborErrorDuplicateObjectKeys,
+ CborErrorInvalidUtf8TextString,
+ CborErrorExcludedType,
+ CborErrorExcludedValue,
+ CborErrorImproperValue,
+ CborErrorOverlongEncoding,
+ CborErrorMapKeyNotString,
+ CborErrorMapNotSorted,
+ CborErrorMapKeysNotUnique,
+
+ /* encoder errors */
+ CborErrorTooManyItems = 768,
+ CborErrorTooFewItems,
+
+ /* internal implementation errors */
+ CborErrorDataTooLarge = 1024,
+ CborErrorNestingTooDeep,
+ CborErrorUnsupportedType,
+ CborErrorUnimplementedValidation,
+
+ /* errors in converting to JSON */
+ CborErrorJsonObjectKeyIsAggregate = 1280,
+ CborErrorJsonObjectKeyNotString,
+ CborErrorJsonNotImplemented,
+
+ CborErrorOutOfMemory = (int) (~0U / 2 + 1),
+ CborErrorInternalError = (int) (~0U / 2) /* INT_MAX on two's complement machines */
+} CborError;
+
+CBOR_API const char *cbor_error_string(CborError error);
+
+/* Encoder API */
+
+typedef enum CborEncoderAppendType
+{
+ CborEncoderAppendCborData = 0,
+ CborEncoderAppendStringData = 1
+} CborEncoderAppendType;
+
+typedef CborError (*CborEncoderWriteFunction)(void *, const void *, size_t, CborEncoderAppendType);
+
+enum CborEncoderFlags
+{
+ CborIteratorFlag_WriterFunction = 0x01,
+ CborIteratorFlag_ContainerIsMap_ = 0x20
+};
+
+struct CborEncoder
+{
+ union {
+ uint8_t *ptr;
+ ptrdiff_t bytes_needed;
+ CborEncoderWriteFunction writer;
+ } data;
+ uint8_t *end;
+ size_t remaining;
+ int flags;
+};
+typedef struct CborEncoder CborEncoder;
+
+static const size_t CborIndefiniteLength = SIZE_MAX;
+
+#ifndef CBOR_NO_ENCODER_API
+CBOR_API void cbor_encoder_init(CborEncoder *encoder, uint8_t *buffer, size_t size, int flags);
+CBOR_API void cbor_encoder_init_writer(CborEncoder *encoder, CborEncoderWriteFunction writer, void *);
+CBOR_API CborError cbor_encode_uint(CborEncoder *encoder, uint64_t value);
+CBOR_API CborError cbor_encode_int(CborEncoder *encoder, int64_t value);
+CBOR_API CborError cbor_encode_negative_int(CborEncoder *encoder, uint64_t absolute_value);
+CBOR_API CborError cbor_encode_simple_value(CborEncoder *encoder, uint8_t value);
+CBOR_API CborError cbor_encode_tag(CborEncoder *encoder, CborTag tag);
+CBOR_API CborError cbor_encode_text_string(CborEncoder *encoder, const char *string, size_t length);
+CBOR_INLINE_API CborError cbor_encode_text_stringz(CborEncoder *encoder, const char *string)
+{ return cbor_encode_text_string(encoder, string, strlen(string)); }
+CBOR_API CborError cbor_encode_byte_string(CborEncoder *encoder, const uint8_t *string, size_t length);
+CBOR_API CborError cbor_encode_floating_point(CborEncoder *encoder, CborType fpType, const void *value);
+
+CBOR_INLINE_API CborError cbor_encode_boolean(CborEncoder *encoder, bool value)
+{ return cbor_encode_simple_value(encoder, (int)value - 1 + (CborBooleanType & 0x1f)); }
+CBOR_INLINE_API CborError cbor_encode_null(CborEncoder *encoder)
+{ return cbor_encode_simple_value(encoder, CborNullType & 0x1f); }
+CBOR_INLINE_API CborError cbor_encode_undefined(CborEncoder *encoder)
+{ return cbor_encode_simple_value(encoder, CborUndefinedType & 0x1f); }
+
+CBOR_INLINE_API CborError cbor_encode_half_float(CborEncoder *encoder, const void *value)
+{ return cbor_encode_floating_point(encoder, CborHalfFloatType, value); }
+CBOR_INLINE_API CborError cbor_encode_float(CborEncoder *encoder, float value)
+{ return cbor_encode_floating_point(encoder, CborFloatType, &value); }
+CBOR_INLINE_API CborError cbor_encode_double(CborEncoder *encoder, double value)
+{ return cbor_encode_floating_point(encoder, CborDoubleType, &value); }
+
+CBOR_API CborError cbor_encoder_create_array(CborEncoder *encoder, CborEncoder *arrayEncoder, size_t length);
+CBOR_API CborError cbor_encoder_create_map(CborEncoder *encoder, CborEncoder *mapEncoder, size_t length);
+CBOR_API CborError cbor_encoder_close_container(CborEncoder *encoder, const CborEncoder *containerEncoder);
+CBOR_API CborError cbor_encoder_close_container_checked(CborEncoder *encoder, const CborEncoder *containerEncoder);
+
+CBOR_INLINE_API uint8_t *_cbor_encoder_get_buffer_pointer(const CborEncoder *encoder)
+{
+ return encoder->data.ptr;
+}
+
+CBOR_INLINE_API size_t cbor_encoder_get_buffer_size(const CborEncoder *encoder, const uint8_t *buffer)
+{
+ return (size_t)(encoder->data.ptr - buffer);
+}
+
+CBOR_INLINE_API size_t cbor_encoder_get_extra_bytes_needed(const CborEncoder *encoder)
+{
+ return encoder->end ? 0 : (size_t)encoder->data.bytes_needed;
+}
+#endif /* CBOR_NO_ENCODER_API */
+
+/* Parser API */
+
+enum CborParserGlobalFlags
+{
+ CborParserFlag_ExternalSource = 0x01
+};
+
+enum CborParserIteratorFlags
+{
+ /* used for all types, but not during string chunk iteration
+ * (values are static-asserted, don't change) */
+ CborIteratorFlag_IntegerValueIs64Bit = 0x01,
+ CborIteratorFlag_IntegerValueTooLarge = 0x02,
+
+ /* used only for CborIntegerType */
+ CborIteratorFlag_NegativeInteger = 0x04,
+
+ /* used only during string iteration */
+ CborIteratorFlag_BeforeFirstStringChunk = 0x04,
+ CborIteratorFlag_IteratingStringChunks = 0x08,
+
+ /* used for arrays, maps and strings, including during chunk iteration */
+ CborIteratorFlag_UnknownLength = 0x10,
+
+ /* used for maps, but must be kept for all types
+ * (ContainerIsMap value must be CborMapType - CborArrayType) */
+ CborIteratorFlag_ContainerIsMap = 0x20,
+ CborIteratorFlag_NextIsMapKey = 0x40
+};
+
+struct CborValue;
+struct CborParserOperations
+{
+ bool (*can_read_bytes)(void *token, size_t len);
+ void *(*read_bytes)(void *token, void *dst, size_t offset, size_t len);
+ void (*advance_bytes)(void *token, size_t len);
+ CborError (*transfer_string)(void *token, const void **userptr, size_t offset, size_t len);
+};
+
+struct CborParser
+{
+ union {
+ const uint8_t *end;
+ const struct CborParserOperations *ops;
+ } source;
+ enum CborParserGlobalFlags flags;
+};
+typedef struct CborParser CborParser;
+
+struct CborValue
+{
+ const CborParser *parser;
+ union {
+ const uint8_t *ptr;
+ void *token;
+ } source;
+ uint32_t remaining;
+ uint16_t extra;
+ uint8_t type;
+ uint8_t flags;
+};
+typedef struct CborValue CborValue;
+
+#ifndef CBOR_NO_PARSER_API
+CBOR_API CborError cbor_parser_init(const uint8_t *buffer, size_t size, uint32_t flags, CborParser *parser, CborValue *it);
+CBOR_API CborError cbor_parser_init_reader(const struct CborParserOperations *ops, CborParser *parser, CborValue *it, void *token);
+
+CBOR_API CborError cbor_value_validate_basic(const CborValue *it);
+
+CBOR_INLINE_API bool cbor_value_at_end(const CborValue *it)
+{ return it->remaining == 0; }
+CBOR_INLINE_API const uint8_t *cbor_value_get_next_byte(const CborValue *it)
+{ return it->source.ptr; }
+CBOR_API CborError cbor_value_reparse(CborValue *it);
+CBOR_API CborError cbor_value_advance_fixed(CborValue *it);
+CBOR_API CborError cbor_value_advance(CborValue *it);
+CBOR_INLINE_API bool cbor_value_is_container(const CborValue *it)
+{ return it->type == CborArrayType || it->type == CborMapType; }
+CBOR_API CborError cbor_value_enter_container(const CborValue *it, CborValue *recursed);
+CBOR_API CborError cbor_value_leave_container(CborValue *it, const CborValue *recursed);
+
+CBOR_PRIVATE_API uint64_t _cbor_value_decode_int64_internal(const CborValue *value);
+CBOR_INLINE_API uint64_t _cbor_value_extract_int64_helper(const CborValue *value)
+{
+ return value->flags & CborIteratorFlag_IntegerValueTooLarge ?
+ _cbor_value_decode_int64_internal(value) : value->extra;
+}
+
+CBOR_INLINE_API bool cbor_value_is_valid(const CborValue *value)
+{ return value && value->type != CborInvalidType; }
+CBOR_INLINE_API CborType cbor_value_get_type(const CborValue *value)
+{ return (CborType)value->type; }
+
+/* Null & undefined type */
+CBOR_INLINE_API bool cbor_value_is_null(const CborValue *value)
+{ return value->type == CborNullType; }
+CBOR_INLINE_API bool cbor_value_is_undefined(const CborValue *value)
+{ return value->type == CborUndefinedType; }
+
+/* Booleans */
+CBOR_INLINE_API bool cbor_value_is_boolean(const CborValue *value)
+{ return value->type == CborBooleanType; }
+CBOR_INLINE_API CborError cbor_value_get_boolean(const CborValue *value, bool *result)
+{
+ assert(cbor_value_is_boolean(value));
+ *result = !!value->extra;
+ return CborNoError;
+}
+
+/* Simple types */
+CBOR_INLINE_API bool cbor_value_is_simple_type(const CborValue *value)
+{ return value->type == CborSimpleType; }
+CBOR_INLINE_API CborError cbor_value_get_simple_type(const CborValue *value, uint8_t *result)
+{
+ assert(cbor_value_is_simple_type(value));
+ *result = (uint8_t)value->extra;
+ return CborNoError;
+}
+
+/* Integers */
+CBOR_INLINE_API bool cbor_value_is_integer(const CborValue *value)
+{ return value->type == CborIntegerType; }
+CBOR_INLINE_API bool cbor_value_is_unsigned_integer(const CborValue *value)
+{ return cbor_value_is_integer(value) && (value->flags & CborIteratorFlag_NegativeInteger) == 0; }
+CBOR_INLINE_API bool cbor_value_is_negative_integer(const CborValue *value)
+{ return cbor_value_is_integer(value) && (value->flags & CborIteratorFlag_NegativeInteger); }
+
+CBOR_INLINE_API CborError cbor_value_get_raw_integer(const CborValue *value, uint64_t *result)
+{
+ assert(cbor_value_is_integer(value));
+ *result = _cbor_value_extract_int64_helper(value);
+ return CborNoError;
+}
+
+CBOR_INLINE_API CborError cbor_value_get_uint64(const CborValue *value, uint64_t *result)
+{
+ assert(cbor_value_is_unsigned_integer(value));
+ *result = _cbor_value_extract_int64_helper(value);
+ return CborNoError;
+}
+
+CBOR_INLINE_API CborError cbor_value_get_int64(const CborValue *value, int64_t *result)
+{
+ assert(cbor_value_is_integer(value));
+ *result = (int64_t) _cbor_value_extract_int64_helper(value);
+ if (value->flags & CborIteratorFlag_NegativeInteger)
+ *result = -*result - 1;
+ return CborNoError;
+}
+
+CBOR_INLINE_API CborError cbor_value_get_int(const CborValue *value, int *result)
+{
+ assert(cbor_value_is_integer(value));
+ *result = (int) _cbor_value_extract_int64_helper(value);
+ if (value->flags & CborIteratorFlag_NegativeInteger)
+ *result = -*result - 1;
+ return CborNoError;
+}
+
+CBOR_API CborError cbor_value_get_int64_checked(const CborValue *value, int64_t *result);
+CBOR_API CborError cbor_value_get_int_checked(const CborValue *value, int *result);
+
+CBOR_INLINE_API bool cbor_value_is_length_known(const CborValue *value)
+{ return (value->flags & CborIteratorFlag_UnknownLength) == 0; }
+
+/* Tags */
+CBOR_INLINE_API bool cbor_value_is_tag(const CborValue *value)
+{ return value->type == CborTagType; }
+CBOR_INLINE_API CborError cbor_value_get_tag(const CborValue *value, CborTag *result)
+{
+ assert(cbor_value_is_tag(value));
+ *result = _cbor_value_extract_int64_helper(value);
+ return CborNoError;
+}
+CBOR_API CborError cbor_value_skip_tag(CborValue *it);
+
+/* Strings */
+CBOR_INLINE_API bool cbor_value_is_byte_string(const CborValue *value)
+{ return value->type == CborByteStringType; }
+CBOR_INLINE_API bool cbor_value_is_text_string(const CborValue *value)
+{ return value->type == CborTextStringType; }
+
+CBOR_INLINE_API CborError cbor_value_get_string_length(const CborValue *value, size_t *length)
+{
+ uint64_t v;
+ assert(cbor_value_is_byte_string(value) || cbor_value_is_text_string(value));
+ if (!cbor_value_is_length_known(value))
+ return CborErrorUnknownLength;
+ v = _cbor_value_extract_int64_helper(value);
+ *length = (size_t)v;
+ if (*length != v)
+ return CborErrorDataTooLarge;
+ return CborNoError;
+}
+
+CBOR_PRIVATE_API CborError _cbor_value_copy_string(const CborValue *value, void *buffer,
+ size_t *buflen, CborValue *next);
+CBOR_PRIVATE_API CborError _cbor_value_dup_string(const CborValue *value, void **buffer,
+ size_t *buflen, CborValue *next);
+
+CBOR_API CborError cbor_value_calculate_string_length(const CborValue *value, size_t *length);
+
+CBOR_INLINE_API CborError cbor_value_copy_text_string(const CborValue *value, char *buffer,
+ size_t *buflen, CborValue *next)
+{
+ assert(cbor_value_is_text_string(value));
+ return _cbor_value_copy_string(value, buffer, buflen, next);
+}
+CBOR_INLINE_API CborError cbor_value_copy_byte_string(const CborValue *value, uint8_t *buffer,
+ size_t *buflen, CborValue *next)
+{
+ assert(cbor_value_is_byte_string(value));
+ return _cbor_value_copy_string(value, buffer, buflen, next);
+}
+
+CBOR_INLINE_API CborError cbor_value_dup_text_string(const CborValue *value, char **buffer,
+ size_t *buflen, CborValue *next)
+{
+ assert(cbor_value_is_text_string(value));
+ return _cbor_value_dup_string(value, (void **)buffer, buflen, next);
+}
+CBOR_INLINE_API CborError cbor_value_dup_byte_string(const CborValue *value, uint8_t **buffer,
+ size_t *buflen, CborValue *next)
+{
+ assert(cbor_value_is_byte_string(value));
+ return _cbor_value_dup_string(value, (void **)buffer, buflen, next);
+}
+
+CBOR_PRIVATE_API CborError _cbor_value_get_string_chunk_size(const CborValue *value, size_t *len);
+CBOR_INLINE_API CborError cbor_value_get_string_chunk_size(const CborValue *value, size_t *len)
+{
+ assert(value->flags & CborIteratorFlag_IteratingStringChunks);
+ return _cbor_value_get_string_chunk_size(value, len);
+}
+
+CBOR_INLINE_API bool cbor_value_string_iteration_at_end(const CborValue *value)
+{
+ size_t dummy;
+ return cbor_value_get_string_chunk_size(value, &dummy) == CborErrorNoMoreStringChunks;
+}
+
+CBOR_PRIVATE_API CborError _cbor_value_begin_string_iteration(CborValue *value);
+CBOR_INLINE_API CborError cbor_value_begin_string_iteration(CborValue *value)
+{
+ assert(cbor_value_is_text_string(value) || cbor_value_is_byte_string(value));
+ assert(!(value->flags & CborIteratorFlag_IteratingStringChunks));
+ return _cbor_value_begin_string_iteration(value);
+}
+
+CBOR_PRIVATE_API CborError _cbor_value_finish_string_iteration(CborValue *value);
+CBOR_INLINE_API CborError cbor_value_finish_string_iteration(CborValue *value)
+{
+ assert(cbor_value_string_iteration_at_end(value));
+ return _cbor_value_finish_string_iteration(value);
+}
+
+CBOR_PRIVATE_API CborError _cbor_value_get_string_chunk(const CborValue *value, const void **bufferptr,
+ size_t *len, CborValue *next);
+CBOR_INLINE_API CborError cbor_value_get_text_string_chunk(const CborValue *value, const char **bufferptr,
+ size_t *len, CborValue *next)
+{
+ assert(cbor_value_is_text_string(value));
+ return _cbor_value_get_string_chunk(value, (const void **)bufferptr, len, next);
+}
+CBOR_INLINE_API CborError cbor_value_get_byte_string_chunk(const CborValue *value, const uint8_t **bufferptr,
+ size_t *len, CborValue *next)
+{
+ assert(cbor_value_is_byte_string(value));
+ return _cbor_value_get_string_chunk(value, (const void **)bufferptr, len, next);
+}
+
+CBOR_API CborError cbor_value_text_string_equals(const CborValue *value, const char *string, bool *result);
+
+/* Maps and arrays */
+CBOR_INLINE_API bool cbor_value_is_array(const CborValue *value)
+{ return value->type == CborArrayType; }
+CBOR_INLINE_API bool cbor_value_is_map(const CborValue *value)
+{ return value->type == CborMapType; }
+
+CBOR_INLINE_API CborError cbor_value_get_array_length(const CborValue *value, size_t *length)
+{
+ uint64_t v;
+ assert(cbor_value_is_array(value));
+ if (!cbor_value_is_length_known(value))
+ return CborErrorUnknownLength;
+ v = _cbor_value_extract_int64_helper(value);
+ *length = (size_t)v;
+ if (*length != v)
+ return CborErrorDataTooLarge;
+ return CborNoError;
+}
+
+CBOR_INLINE_API CborError cbor_value_get_map_length(const CborValue *value, size_t *length)
+{
+ uint64_t v;
+ assert(cbor_value_is_map(value));
+ if (!cbor_value_is_length_known(value))
+ return CborErrorUnknownLength;
+ v = _cbor_value_extract_int64_helper(value);
+ *length = (size_t)v;
+ if (*length != v)
+ return CborErrorDataTooLarge;
+ return CborNoError;
+}
+
+CBOR_API CborError cbor_value_map_find_value(const CborValue *map, const char *string, CborValue *element);
+
+/* Floating point */
+CBOR_INLINE_API bool cbor_value_is_half_float(const CborValue *value)
+{ return value->type == CborHalfFloatType; }
+CBOR_INLINE_API CborError cbor_value_get_half_float(const CborValue *value, void *result)
+{
+ assert(cbor_value_is_half_float(value));
+ assert((value->flags & CborIteratorFlag_IntegerValueTooLarge) == 0);
+
+ /* size has been computed already */
+ memcpy(result, &value->extra, sizeof(value->extra));
+ return CborNoError;
+}
+
+CBOR_INLINE_API bool cbor_value_is_float(const CborValue *value)
+{ return value->type == CborFloatType; }
+CBOR_INLINE_API CborError cbor_value_get_float(const CborValue *value, float *result)
+{
+ uint32_t data;
+ assert(cbor_value_is_float(value));
+ assert(value->flags & CborIteratorFlag_IntegerValueTooLarge);
+ data = (uint32_t)_cbor_value_decode_int64_internal(value);
+ memcpy(result, &data, sizeof(*result));
+ return CborNoError;
+}
+
+CBOR_INLINE_API bool cbor_value_is_double(const CborValue *value)
+{ return value->type == CborDoubleType; }
+CBOR_INLINE_API CborError cbor_value_get_double(const CborValue *value, double *result)
+{
+ uint64_t data;
+ assert(cbor_value_is_double(value));
+ assert(value->flags & CborIteratorFlag_IntegerValueTooLarge);
+ data = _cbor_value_decode_int64_internal(value);
+ memcpy(result, &data, sizeof(*result));
+ return CborNoError;
+}
+
+/* Validation API */
+#ifndef CBOR_NO_VALIDATION_API
+
+enum CborValidationFlags {
+ /* Bit mapping:
+ * bits 0-7 (8 bits): canonical format
+ * bits 8-11 (4 bits): canonical format & strict mode
+ * bits 12-20 (8 bits): strict mode
+ * bits 21-31 (10 bits): other
+ */
+
+ CborValidateShortestIntegrals = 0x0001,
+ CborValidateShortestFloatingPoint = 0x0002,
+ CborValidateShortestNumbers = CborValidateShortestIntegrals | CborValidateShortestFloatingPoint,
+ CborValidateNoIndeterminateLength = 0x0100,
+ CborValidateMapIsSorted = 0x0200 | CborValidateNoIndeterminateLength,
+
+ CborValidateCanonicalFormat = 0x0fff,
+
+ CborValidateMapKeysAreUnique = 0x1000 | CborValidateMapIsSorted,
+ CborValidateTagUse = 0x2000,
+ CborValidateUtf8 = 0x4000,
+
+ CborValidateStrictMode = 0xfff00,
+
+ CborValidateMapKeysAreString = 0x100000,
+ CborValidateNoUndefined = 0x200000,
+ CborValidateNoTags = 0x400000,
+ CborValidateFiniteFloatingPoint = 0x800000,
+ /* unused = 0x1000000, */
+ /* unused = 0x2000000, */
+
+ CborValidateNoUnknownSimpleTypesSA = 0x4000000,
+ CborValidateNoUnknownSimpleTypes = 0x8000000 | CborValidateNoUnknownSimpleTypesSA,
+ CborValidateNoUnknownTagsSA = 0x10000000,
+ CborValidateNoUnknownTagsSR = 0x20000000 | CborValidateNoUnknownTagsSA,
+ CborValidateNoUnknownTags = 0x40000000 | CborValidateNoUnknownTagsSR,
+
+ CborValidateCompleteData = (int)0x80000000,
+
+ CborValidateStrictest = (int)~0U,
+ CborValidateBasic = 0
+};
+
+CBOR_API CborError cbor_value_validate(const CborValue *it, uint32_t flags);
+#endif /* CBOR_NO_VALIDATION_API */
+
+/* Human-readable (dump) API */
+#ifndef CBOR_NO_PRETTY_API
+
+enum CborPrettyFlags {
+ CborPrettyNumericEncodingIndicators = 0x01,
+ CborPrettyTextualEncodingIndicators = 0,
+
+ CborPrettyIndicateIndeterminateLength = 0x02,
+ CborPrettyIndicateIndetermineLength = CborPrettyIndicateIndeterminateLength, /* deprecated */
+ CborPrettyIndicateOverlongNumbers = 0x04,
+
+ CborPrettyShowStringFragments = 0x100,
+ CborPrettyMergeStringFragments = 0,
+
+ CborPrettyDefaultFlags = CborPrettyIndicateIndeterminateLength
+};
+
+typedef CborError (*CborStreamFunction)(void *token, const char *fmt, ...)
+#ifdef __GNUC__
+ __attribute__((__format__(printf, 2, 3)))
+#endif
+;
+
+CBOR_API CborError cbor_value_to_pretty_stream(CborStreamFunction streamFunction, void *token, CborValue *value, int flags);
+
+/* The following API requires a hosted C implementation (uses FILE*) */
+#if !defined(__STDC_HOSTED__) || __STDC_HOSTED__-0 == 1
+CBOR_API CborError cbor_value_to_pretty_advance_flags(FILE *out, CborValue *value, int flags);
+CBOR_API CborError cbor_value_to_pretty_advance(FILE *out, CborValue *value);
+CBOR_INLINE_API CborError cbor_value_to_pretty(FILE *out, const CborValue *value)
+{
+ CborValue copy = *value;
+ return cbor_value_to_pretty_advance_flags(out, &copy, CborPrettyDefaultFlags);
+}
+#endif /* __STDC_HOSTED__ check */
+
+#endif /* CBOR_NO_PRETTY_API */
+
+#endif /* CBOR_NO_PARSER_API */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CBOR_H */
+
diff --git a/src/3rdparty/tinycbor/src/cborencoder.c b/src/3rdparty/tinycbor/src/cborencoder.c
new file mode 100644
index 0000000000..52a4025be1
--- /dev/null
+++ b/src/3rdparty/tinycbor/src/cborencoder.c
@@ -0,0 +1,677 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and associated documentation files (the "Software"), to deal
+** in the Software without restriction, including without limitation the rights
+** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+** copies of the Software, and to permit persons to whom the Software is
+** furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+** THE SOFTWARE.
+**
+****************************************************************************/
+
+#ifndef _BSD_SOURCE
+#define _BSD_SOURCE 1
+#endif
+#ifndef _DEFAULT_SOURCE
+#define _DEFAULT_SOURCE 1
+#endif
+#ifndef __STDC_LIMIT_MACROS
+# define __STDC_LIMIT_MACROS 1
+#endif
+
+#include "cbor.h"
+#include "cborinternal_p.h"
+#include "compilersupport_p.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * \defgroup CborEncoding Encoding to CBOR
+ * \brief Group of functions used to encode data to CBOR.
+ *
+ * CborEncoder is used to encode data into a CBOR stream. The outermost
+ * CborEncoder is initialized by calling cbor_encoder_init(), with the buffer
+ * where the CBOR stream will be stored. The outermost CborEncoder is usually
+ * used to encode exactly one item, most often an array or map. It is possible
+ * to encode more than one item, but care must then be taken on the decoder
+ * side to ensure the state is reset after each item was decoded.
+ *
+ * Nested CborEncoder objects are created using cbor_encoder_create_array() and
+ * cbor_encoder_create_map(), later closed with cbor_encoder_close_container()
+ * or cbor_encoder_close_container_checked(). The pairs of creation and closing
+ * must be exactly matched and their parameters are always the same.
+ *
+ * CborEncoder writes directly to the user-supplied buffer, without extra
+ * buffering. CborEncoder does not allocate memory and CborEncoder objects are
+ * usually created on the stack of the encoding functions.
+ *
+ * The example below initializes a CborEncoder object with a buffer and encodes
+ * a single integer.
+ *
+ * \code
+ * uint8_t buf[16];
+ * CborEncoder encoder;
+ * cbor_encoder_init(&encoder, &buf, sizeof(buf), 0);
+ * cbor_encode_int(&encoder, some_value);
+ * \endcode
+ *
+ * As explained before, usually the outermost CborEncoder object is used to add
+ * one array or map, which in turn contains multiple elements. The example
+ * below creates a CBOR map with one element: a key "foo" and a boolean value.
+ *
+ * \code
+ * uint8_t buf[16];
+ * CborEncoder encoder, mapEncoder;
+ * cbor_encoder_init(&encoder, &buf, sizeof(buf), 0);
+ * cbor_encoder_create_map(&encoder, &mapEncoder, 1);
+ * cbor_encode_text_stringz(&mapEncoder, "foo");
+ * cbor_encode_boolean(&mapEncoder, some_value);
+ * cbor_encoder_close_container(&encoder, &mapEncoder);
+ * \endcode
+ *
+ * <h3 class="groupheader">Error checking and buffer size</h3>
+ *
+ * All functions operating on CborEncoder return a condition of type CborError.
+ * If the encoding was successful, they return CborNoError. Some functions do
+ * extra checking on the input provided and may return some other error
+ * conditions (for example, cbor_encode_simple_value() checks that the type is
+ * of the correct type).
+ *
+ * In addition, all functions check whether the buffer has enough bytes to
+ * encode the item being appended. If that is not possible, they return
+ * CborErrorOutOfMemory.
+ *
+ * It is possible to continue with the encoding of data past the first function
+ * that returns CborErrorOutOfMemory. CborEncoder functions will not overrun
+ * the buffer, but will instead count how many more bytes are needed to
+ * complete the encoding. At the end, you can obtain that count by calling
+ * cbor_encoder_get_extra_bytes_needed().
+ *
+ * \section1 Finalizing the encoding
+ *
+ * Once all items have been appended and the containers have all been properly
+ * closed, the user-supplied buffer will contain the CBOR stream and may be
+ * immediately used. To obtain the size of the buffer, call
+ * cbor_encoder_get_buffer_size() with the original buffer pointer.
+ *
+ * The example below illustrates how one can encode an item with error checking
+ * and then pass on the buffer for network sending.
+ *
+ * \code
+ * uint8_t buf[16];
+ * CborError err;
+ * CborEncoder encoder, mapEncoder;
+ * cbor_encoder_init(&encoder, &buf, sizeof(buf), 0);
+ * err = cbor_encoder_create_map(&encoder, &mapEncoder, 1);
+ * if (!err)
+ * return err;
+ * err = cbor_encode_text_stringz(&mapEncoder, "foo");
+ * if (!err)
+ * return err;
+ * err = cbor_encode_boolean(&mapEncoder, some_value);
+ * if (!err)
+ * return err;
+ * err = cbor_encoder_close_container_checked(&encoder, &mapEncoder);
+ * if (!err)
+ * return err;
+ *
+ * size_t len = cbor_encoder_get_buffer_size(&encoder, buf);
+ * send_payload(buf, len);
+ * return CborNoError;
+ * \endcode
+ *
+ * Finally, the example below expands on the one above and also
+ * deals with dynamically growing the buffer if the initial allocation wasn't
+ * big enough. Note the two places where the error checking was replaced with
+ * an cbor_assertion, showing where the author assumes no error can occur.
+ *
+ * \code
+ * uint8_t *encode_string_array(const char **strings, int n, size_t *bufsize)
+ * {
+ * CborError err;
+ * CborEncoder encoder, arrayEncoder;
+ * size_t size = 256;
+ * uint8_t *buf = NULL;
+ *
+ * while (1) {
+ * int i;
+ * size_t more_bytes;
+ * uint8_t *nbuf = realloc(buf, size);
+ * if (nbuf == NULL)
+ * goto error;
+ * buf = nbuf;
+ *
+ * cbor_encoder_init(&encoder, &buf, size, 0);
+ * err = cbor_encoder_create_array(&encoder, &arrayEncoder, n);
+ * cbor_assert(err); // can't fail, the buffer is always big enough
+ *
+ * for (i = 0; i < n; ++i) {
+ * err = cbor_encode_text_stringz(&arrayEncoder, strings[i]);
+ * if (err && err != CborErrorOutOfMemory)
+ * goto error;
+ * }
+ *
+ * err = cbor_encoder_close_container_checked(&encoder, &arrayEncoder);
+ * cbor_assert(err); // shouldn't fail!
+ *
+ * more_bytes = cbor_encoder_get_extra_bytes_needed(encoder);
+ * if (more_size) {
+ * // buffer wasn't big enough, try again
+ * size += more_bytes;
+ * continue;
+ * }
+ *
+ * *bufsize = cbor_encoder_get_buffer_size(encoder, buf);
+ * return buf;
+ * }
+ * error:
+ * free(buf);
+ * return NULL;
+ * }
+ * \endcode
+ */
+
+/**
+ * \addtogroup CborEncoding
+ * @{
+ */
+
+/**
+ * \struct CborEncoder
+ * Structure used to encode to CBOR.
+ */
+
+/**
+ * Initializes a CborEncoder structure \a encoder by pointing it to buffer \a
+ * buffer of size \a size. The \a flags field is currently unused and must be
+ * zero.
+ */
+void cbor_encoder_init(CborEncoder *encoder, uint8_t *buffer, size_t size, int flags)
+{
+ encoder->data.ptr = buffer;
+ encoder->end = buffer + size;
+ encoder->remaining = 2;
+ encoder->flags = flags;
+}
+
+void cbor_encoder_init_writer(CborEncoder *encoder, CborEncoderWriteFunction writer, void *token)
+{
+#ifdef CBOR_ENCODER_WRITE_FUNCTION
+ (void) writer;
+#else
+ encoder->data.writer = writer;
+#endif
+ encoder->end = (uint8_t *)token;
+ encoder->remaining = 2;
+ encoder->flags = CborIteratorFlag_WriterFunction;
+}
+
+static inline void put16(void *where, uint16_t v)
+{
+ v = cbor_htons(v);
+ memcpy(where, &v, sizeof(v));
+}
+
+/* Note: Since this is currently only used in situations where OOM is the only
+ * valid error, we KNOW this to be true. Thus, this function now returns just 'true',
+ * but if in the future, any function starts returning a non-OOM error, this will need
+ * to be changed to the test. At the moment, this is done to prevent more branches
+ * being created in the tinycbor output */
+static inline bool isOomError(CborError err)
+{
+ if (CBOR_ENCODER_WRITER_CONTROL < 0)
+ return true;
+
+ /* CborErrorOutOfMemory is the only negative error code, intentionally
+ * so we can write the test like this */
+ return (int)err < 0;
+}
+
+static inline void put32(void *where, uint32_t v)
+{
+ v = cbor_htonl(v);
+ memcpy(where, &v, sizeof(v));
+}
+
+static inline void put64(void *where, uint64_t v)
+{
+ v = cbor_htonll(v);
+ memcpy(where, &v, sizeof(v));
+}
+
+static inline bool would_overflow(CborEncoder *encoder, size_t len)
+{
+ ptrdiff_t remaining = (ptrdiff_t)encoder->end;
+ remaining -= remaining ? (ptrdiff_t)encoder->data.ptr : encoder->data.bytes_needed;
+ remaining -= (ptrdiff_t)len;
+ return unlikely(remaining < 0);
+}
+
+static inline void advance_ptr(CborEncoder *encoder, size_t n)
+{
+ if (encoder->end)
+ encoder->data.ptr += n;
+ else
+ encoder->data.bytes_needed += n;
+}
+
+static inline CborError append_to_buffer(CborEncoder *encoder, const void *data, size_t len,
+ CborEncoderAppendType appendType)
+{
+ if (CBOR_ENCODER_WRITER_CONTROL >= 0) {
+ if (encoder->flags & CborIteratorFlag_WriterFunction || CBOR_ENCODER_WRITER_CONTROL != 0) {
+# ifdef CBOR_ENCODER_WRITE_FUNCTION
+ return CBOR_ENCODER_WRITE_FUNCTION(encoder->end, data, len, appendType);
+# else
+ return encoder->data.writer(encoder->end, data, len, appendType);
+# endif
+ }
+ }
+
+#if CBOR_ENCODER_WRITER_CONTROL <= 0
+ if (would_overflow(encoder, len)) {
+ if (encoder->end != NULL) {
+ len -= encoder->end - encoder->data.ptr;
+ encoder->end = NULL;
+ encoder->data.bytes_needed = 0;
+ }
+
+ advance_ptr(encoder, len);
+ return CborErrorOutOfMemory;
+ }
+
+ memcpy(encoder->data.ptr, data, len);
+ encoder->data.ptr += len;
+#endif
+ return CborNoError;
+}
+
+static inline CborError append_byte_to_buffer(CborEncoder *encoder, uint8_t byte)
+{
+ return append_to_buffer(encoder, &byte, 1, CborEncoderAppendCborData);
+}
+
+static inline CborError encode_number_no_update(CborEncoder *encoder, uint64_t ui, uint8_t shiftedMajorType)
+{
+ /* Little-endian would have been so much more convenient here:
+ * We could just write at the beginning of buf but append_to_buffer
+ * only the necessary bytes.
+ * Since it has to be big endian, do it the other way around:
+ * write from the end. */
+ uint64_t buf[2];
+ uint8_t *const bufend = (uint8_t *)buf + sizeof(buf);
+ uint8_t *bufstart = bufend - 1;
+ put64(buf + 1, ui); /* we probably have a bunch of zeros in the beginning */
+
+ if (ui < Value8Bit) {
+ *bufstart += shiftedMajorType;
+ } else {
+ uint8_t more = 0;
+ if (ui > 0xffU)
+ ++more;
+ if (ui > 0xffffU)
+ ++more;
+ if (ui > 0xffffffffU)
+ ++more;
+ bufstart -= (size_t)1 << more;
+ *bufstart = shiftedMajorType + Value8Bit + more;
+ }
+
+ return append_to_buffer(encoder, bufstart, bufend - bufstart, CborEncoderAppendCborData);
+}
+
+static inline void saturated_decrement(CborEncoder *encoder)
+{
+ if (encoder->remaining)
+ --encoder->remaining;
+}
+
+static inline CborError encode_number(CborEncoder *encoder, uint64_t ui, uint8_t shiftedMajorType)
+{
+ saturated_decrement(encoder);
+ return encode_number_no_update(encoder, ui, shiftedMajorType);
+}
+
+/**
+ * Appends the unsigned 64-bit integer \a value to the CBOR stream provided by
+ * \a encoder.
+ *
+ * \sa cbor_encode_negative_int, cbor_encode_int
+ */
+CborError cbor_encode_uint(CborEncoder *encoder, uint64_t value)
+{
+ return encode_number(encoder, value, UnsignedIntegerType << MajorTypeShift);
+}
+
+/**
+ * Appends the negative 64-bit integer whose absolute value is \a
+ * absolute_value to the CBOR stream provided by \a encoder.
+ *
+ * If the value \a absolute_value is zero, this function encodes -2^64.
+ *
+ * \sa cbor_encode_uint, cbor_encode_int
+ */
+CborError cbor_encode_negative_int(CborEncoder *encoder, uint64_t absolute_value)
+{
+ return encode_number(encoder, absolute_value - 1, NegativeIntegerType << MajorTypeShift);
+}
+
+/**
+ * Appends the signed 64-bit integer \a value to the CBOR stream provided by
+ * \a encoder.
+ *
+ * \sa cbor_encode_negative_int, cbor_encode_uint
+ */
+CborError cbor_encode_int(CborEncoder *encoder, int64_t value)
+{
+ /* adapted from code in RFC 7049 appendix C (pseudocode) */
+ uint64_t ui = value >> 63; /* extend sign to whole length */
+ uint8_t majorType = ui & 0x20; /* extract major type */
+ ui ^= value; /* complement negatives */
+ return encode_number(encoder, ui, majorType);
+}
+
+/**
+ * Appends the CBOR Simple Type of value \a value to the CBOR stream provided by
+ * \a encoder.
+ *
+ * This function may return error CborErrorIllegalSimpleType if the \a value
+ * variable contains a number that is not a valid simple type.
+ */
+CborError cbor_encode_simple_value(CborEncoder *encoder, uint8_t value)
+{
+#ifndef CBOR_ENCODER_NO_CHECK_USER
+ /* check if this is a valid simple type */
+ if (value >= HalfPrecisionFloat && value <= Break)
+ return CborErrorIllegalSimpleType;
+#endif
+ return encode_number(encoder, value, SimpleTypesType << MajorTypeShift);
+}
+
+/**
+ * Appends the floating-point value of type \a fpType and pointed to by \a
+ * value to the CBOR stream provided by \a encoder. The value of \a fpType must
+ * be one of CborHalfFloatType, CborFloatType or CborDoubleType, otherwise the
+ * behavior of this function is undefined.
+ *
+ * This function is useful for code that needs to pass through floating point
+ * values but does not wish to have the actual floating-point code.
+ *
+ * \sa cbor_encode_half_float, cbor_encode_float, cbor_encode_double
+ */
+CborError cbor_encode_floating_point(CborEncoder *encoder, CborType fpType, const void *value)
+{
+ unsigned size;
+ uint8_t buf[1 + sizeof(uint64_t)];
+ cbor_assert(fpType == CborHalfFloatType || fpType == CborFloatType || fpType == CborDoubleType);
+ buf[0] = fpType;
+
+ size = 2U << (fpType - CborHalfFloatType);
+ if (size == 8)
+ put64(buf + 1, *(const uint64_t*)value);
+ else if (size == 4)
+ put32(buf + 1, *(const uint32_t*)value);
+ else
+ put16(buf + 1, *(const uint16_t*)value);
+ saturated_decrement(encoder);
+ return append_to_buffer(encoder, buf, size + 1, CborEncoderAppendCborData);
+}
+
+/**
+ * Appends the CBOR tag \a tag to the CBOR stream provided by \a encoder.
+ *
+ * \sa CborTag
+ */
+CborError cbor_encode_tag(CborEncoder *encoder, CborTag tag)
+{
+ /* tags don't count towards the number of elements in an array or map */
+ return encode_number_no_update(encoder, tag, TagType << MajorTypeShift);
+}
+
+static CborError encode_string(CborEncoder *encoder, size_t length, uint8_t shiftedMajorType, const void *string)
+{
+ CborError err = encode_number(encoder, length, shiftedMajorType);
+ if (err && !isOomError(err))
+ return err;
+ return append_to_buffer(encoder, string, length, CborEncoderAppendStringData);
+}
+
+/**
+ * \fn CborError cbor_encode_text_stringz(CborEncoder *encoder, const char *string)
+ *
+ * Appends the null-terminated text string \a string to the CBOR stream
+ * provided by \a encoder. CBOR requires that \a string be valid UTF-8, but
+ * TinyCBOR makes no verification of correctness. The terminating null is not
+ * included in the stream.
+ *
+ * \sa cbor_encode_text_string, cbor_encode_byte_string
+ */
+
+/**
+ * Appends the text string \a string of length \a length to the CBOR stream
+ * provided by \a encoder. CBOR requires that \a string be valid UTF-8, but
+ * TinyCBOR makes no verification of correctness.
+ *
+ * \sa CborError cbor_encode_text_stringz, cbor_encode_byte_string
+ */
+CborError cbor_encode_byte_string(CborEncoder *encoder, const uint8_t *string, size_t length)
+{
+ return encode_string(encoder, length, ByteStringType << MajorTypeShift, string);
+}
+
+/**
+ * Appends the byte string \a string of length \a length to the CBOR stream
+ * provided by \a encoder. CBOR byte strings are arbitrary raw data.
+ *
+ * \sa cbor_encode_text_stringz, cbor_encode_text_string
+ */
+CborError cbor_encode_text_string(CborEncoder *encoder, const char *string, size_t length)
+{
+ return encode_string(encoder, length, TextStringType << MajorTypeShift, string);
+}
+
+#ifdef __GNUC__
+__attribute__((noinline))
+#endif
+static CborError create_container(CborEncoder *encoder, CborEncoder *container, size_t length, uint8_t shiftedMajorType)
+{
+ CborError err;
+ container->data.ptr = encoder->data.ptr;
+ container->end = encoder->end;
+ saturated_decrement(encoder);
+ container->remaining = length + 1; /* overflow ok on CborIndefiniteLength */
+
+ cbor_static_assert((int)CborIteratorFlag_ContainerIsMap_ == (int)CborIteratorFlag_ContainerIsMap);
+ cbor_static_assert(((MapType << MajorTypeShift) & CborIteratorFlag_ContainerIsMap) == CborIteratorFlag_ContainerIsMap);
+ cbor_static_assert(((ArrayType << MajorTypeShift) & CborIteratorFlag_ContainerIsMap) == 0);
+ container->flags = shiftedMajorType & CborIteratorFlag_ContainerIsMap;
+ if (CBOR_ENCODER_WRITER_CONTROL == 0)
+ container->flags |= encoder->flags & CborIteratorFlag_WriterFunction;
+
+ if (length == CborIndefiniteLength) {
+ container->flags |= CborIteratorFlag_UnknownLength;
+ err = append_byte_to_buffer(container, shiftedMajorType + IndefiniteLength);
+ } else {
+ if (shiftedMajorType & CborIteratorFlag_ContainerIsMap)
+ container->remaining += length;
+ err = encode_number_no_update(container, length, shiftedMajorType);
+ }
+ return err;
+}
+
+/**
+ * Creates a CBOR array in the CBOR stream provided by \a encoder and
+ * initializes \a arrayEncoder so that items can be added to the array using
+ * the CborEncoder functions. The array must be terminated by calling either
+ * cbor_encoder_close_container() or cbor_encoder_close_container_checked()
+ * with the same \a encoder and \a arrayEncoder parameters.
+ *
+ * The number of items inserted into the array must be exactly \a length items,
+ * otherwise the stream is invalid. If the number of items is not known when
+ * creating the array, the constant \ref CborIndefiniteLength may be passed as
+ * length instead.
+ *
+ * \sa cbor_encoder_create_map
+ */
+CborError cbor_encoder_create_array(CborEncoder *encoder, CborEncoder *arrayEncoder, size_t length)
+{
+ return create_container(encoder, arrayEncoder, length, ArrayType << MajorTypeShift);
+}
+
+/**
+ * Creates a CBOR map in the CBOR stream provided by \a encoder and
+ * initializes \a mapEncoder so that items can be added to the map using
+ * the CborEncoder functions. The map must be terminated by calling either
+ * cbor_encoder_close_container() or cbor_encoder_close_container_checked()
+ * with the same \a encoder and \a mapEncoder parameters.
+ *
+ * The number of pair of items inserted into the map must be exactly \a length
+ * items, otherwise the stream is invalid. If the number is not known
+ * when creating the map, the constant \ref CborIndefiniteLength may be passed as
+ * length instead.
+ *
+ * \b{Implementation limitation:} TinyCBOR cannot encode more than SIZE_MAX/2
+ * key-value pairs in the stream. If the length \a length is larger than this
+ * value (and is not \ref CborIndefiniteLength), this function returns error
+ * CborErrorDataTooLarge.
+ *
+ * \sa cbor_encoder_create_array
+ */
+CborError cbor_encoder_create_map(CborEncoder *encoder, CborEncoder *mapEncoder, size_t length)
+{
+ if (length != CborIndefiniteLength && length > SIZE_MAX / 2)
+ return CborErrorDataTooLarge;
+ return create_container(encoder, mapEncoder, length, MapType << MajorTypeShift);
+}
+
+/**
+ * Closes the CBOR container (array or map) provided by \a containerEncoder and
+ * updates the CBOR stream provided by \a encoder. Both parameters must be the
+ * same as were passed to cbor_encoder_create_array() or
+ * cbor_encoder_create_map().
+ *
+ * Since version 0.5, this function verifies that the number of items (or pairs
+ * of items, in the case of a map) was correct. It is no longer necessary to call
+ * cbor_encoder_close_container_checked() instead.
+ *
+ * \sa cbor_encoder_create_array(), cbor_encoder_create_map()
+ */
+CborError cbor_encoder_close_container(CborEncoder *encoder, const CborEncoder *containerEncoder)
+{
+ if (encoder->end && !(encoder->flags & CborIteratorFlag_WriterFunction))
+ encoder->data.ptr = containerEncoder->data.ptr;
+ else
+ encoder->data.bytes_needed = containerEncoder->data.bytes_needed;
+ encoder->end = containerEncoder->end;
+ if (containerEncoder->flags & CborIteratorFlag_UnknownLength)
+ return append_byte_to_buffer(encoder, BreakByte);
+
+ if (containerEncoder->remaining != 1)
+ return containerEncoder->remaining == 0 ? CborErrorTooManyItems : CborErrorTooFewItems;
+
+ if (!encoder->end)
+ return CborErrorOutOfMemory; /* keep the state */
+ return CborNoError;
+}
+
+/**
+ * \fn CborError cbor_encode_boolean(CborEncoder *encoder, bool value)
+ *
+ * Appends the boolean value \a value to the CBOR stream provided by \a encoder.
+ */
+
+/**
+ * \fn CborError cbor_encode_null(CborEncoder *encoder)
+ *
+ * Appends the CBOR type representing a null value to the CBOR stream provided
+ * by \a encoder.
+ *
+ * \sa cbor_encode_undefined()
+ */
+
+/**
+ * \fn CborError cbor_encode_undefined(CborEncoder *encoder)
+ *
+ * Appends the CBOR type representing an undefined value to the CBOR stream
+ * provided by \a encoder.
+ *
+ * \sa cbor_encode_null()
+ */
+
+/**
+ * \fn CborError cbor_encode_half_float(CborEncoder *encoder, const void *value)
+ *
+ * Appends the IEEE 754 half-precision (16-bit) floating point value pointed to
+ * by \a value to the CBOR stream provided by \a encoder.
+ *
+ * \sa cbor_encode_floating_point(), cbor_encode_float(), cbor_encode_double()
+ */
+
+/**
+ * \fn CborError cbor_encode_float(CborEncoder *encoder, float value)
+ *
+ * Appends the IEEE 754 single-precision (32-bit) floating point value \a value
+ * to the CBOR stream provided by \a encoder.
+ *
+ * \sa cbor_encode_floating_point(), cbor_encode_half_float(), cbor_encode_double()
+ */
+
+/**
+ * \fn CborError cbor_encode_double(CborEncoder *encoder, double value)
+ *
+ * Appends the IEEE 754 double-precision (64-bit) floating point value \a value
+ * to the CBOR stream provided by \a encoder.
+ *
+ * \sa cbor_encode_floating_point(), cbor_encode_half_float(), cbor_encode_float()
+ */
+
+/**
+ * \fn size_t cbor_encoder_get_buffer_size(const CborEncoder *encoder, const uint8_t *buffer)
+ *
+ * Returns the total size of the buffer starting at \a buffer after the
+ * encoding finished without errors. The \a encoder and \a buffer arguments
+ * must be the same as supplied to cbor_encoder_init().
+ *
+ * If the encoding process had errors, the return value of this function is
+ * meaningless. If the only errors were CborErrorOutOfMemory, instead use
+ * cbor_encoder_get_extra_bytes_needed() to find out by how much to grow the
+ * buffer before encoding again.
+ *
+ * See \ref CborEncoding for an example of using this function.
+ *
+ * \sa cbor_encoder_init(), cbor_encoder_get_extra_bytes_needed(), CborEncoding
+ */
+
+/**
+ * \fn size_t cbor_encoder_get_extra_bytes_needed(const CborEncoder *encoder)
+ *
+ * Returns how many more bytes the original buffer supplied to
+ * cbor_encoder_init() needs to be extended by so that no CborErrorOutOfMemory
+ * condition will happen for the encoding. If the buffer was big enough, this
+ * function returns 0. The \a encoder must be the original argument as passed
+ * to cbor_encoder_init().
+ *
+ * This function is usually called after an encoding sequence ended with one or
+ * more CborErrorOutOfMemory errors, but no other error. If any other error
+ * happened, the return value of this function is meaningless.
+ *
+ * See \ref CborEncoding for an example of using this function.
+ *
+ * \sa cbor_encoder_init(), cbor_encoder_get_buffer_size(), CborEncoding
+ */
+
+/** @} */
diff --git a/src/3rdparty/tinycbor/src/cborerrorstrings.c b/src/3rdparty/tinycbor/src/cborerrorstrings.c
new file mode 100644
index 0000000000..1dd8ae25bd
--- /dev/null
+++ b/src/3rdparty/tinycbor/src/cborerrorstrings.c
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and associated documentation files (the "Software"), to deal
+** in the Software without restriction, including without limitation the rights
+** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+** copies of the Software, and to permit persons to whom the Software is
+** furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+** THE SOFTWARE.
+**
+****************************************************************************/
+
+#include "cbor.h"
+
+#ifndef _
+# define _(msg) msg
+#endif
+
+/**
+ * \enum CborError
+ * \ingroup CborGlobals
+ * The CborError enum contains the possible error values used by the CBOR encoder and decoder.
+ *
+ * TinyCBOR functions report success by returning CborNoError, or one error
+ * condition by returning one of the values below. One exception is the
+ * out-of-memory condition (CborErrorOutOfMemory), which the functions for \ref
+ * CborEncoding may report in bit-wise OR with other conditions.
+ *
+ * This technique allows code to determine whether the only error condition was
+ * a lack of buffer space, which may not be a fatal condition if the buffer can
+ * be resized. Additionally, the functions for \ref CborEncoding may continue
+ * to be used even after CborErrorOutOfMemory is returned, and instead they
+ * will simply calculate the extra space needed.
+ *
+ * \value CborNoError No error occurred
+ * \omitvalue CborUnknownError
+ * \value CborErrorUnknownLength Request for the length of an array, map or string whose length is not provided in the CBOR stream
+ * \value CborErrorAdvancePastEOF Not enough data in the stream to decode item (decoding would advance past end of stream)
+ * \value CborErrorIO An I/O error occurred, probably due to an out-of-memory situation
+ * \value CborErrorGarbageAtEnd Bytes exist past the end of the CBOR stream
+ * \value CborErrorUnexpectedEOF End of stream reached unexpectedly
+ * \value CborErrorUnexpectedBreak A CBOR break byte was found where not expected
+ * \value CborErrorUnknownType An unknown type (future extension to CBOR) was found in the stream
+ * \value CborErrorIllegalType An invalid type was found while parsing a chunked CBOR string
+ * \value CborErrorIllegalNumber An illegal initial byte (encoding unspecified additional information) was found
+ * \value CborErrorIllegalSimpleType An illegal encoding of a CBOR Simple Type of value less than 32 was found
+ * \omitvalue CborErrorUnknownSimpleType
+ * \omitvalue CborErrorUnknownTag
+ * \omitvalue CborErrorInappropriateTagForType
+ * \omitvalue CborErrorDuplicateObjectKeys
+ * \value CborErrorInvalidUtf8TextString Illegal UTF-8 encoding found while parsing CBOR Text String
+ * \value CborErrorTooManyItems Too many items were added to CBOR map or array of pre-determined length
+ * \value CborErrorTooFewItems Too few items were added to CBOR map or array of pre-determined length
+ * \value CborErrorDataTooLarge Data item size exceeds TinyCBOR's implementation limits
+ * \value CborErrorNestingTooDeep Data item nesting exceeds TinyCBOR's implementation limits
+ * \omitvalue CborErrorUnsupportedType
+ * \value CborErrorJsonObjectKeyIsAggregate Conversion to JSON failed because the key in a map is a CBOR map or array
+ * \value CborErrorJsonObjectKeyNotString Conversion to JSON failed because the key in a map is not a text string
+ * \value CborErrorOutOfMemory During CBOR encoding, the buffer provided is insufficient for encoding the data item;
+ * in other situations, TinyCBOR failed to allocate memory
+ * \value CborErrorInternalError An internal error occurred in TinyCBOR
+ */
+
+/**
+ * \ingroup CborGlobals
+ * Returns the error string corresponding to the CBOR error condition \a error.
+ */
+const char *cbor_error_string(CborError error)
+{
+ switch (error) {
+ case CborNoError:
+ return "";
+
+ case CborUnknownError:
+ return _("unknown error");
+
+ case CborErrorOutOfMemory:
+ return _("out of memory/need more memory");
+
+ case CborErrorUnknownLength:
+ return _("unknown length (attempted to get the length of a map/array/string of indeterminate length");
+
+ case CborErrorAdvancePastEOF:
+ return _("attempted to advance past EOF");
+
+ case CborErrorIO:
+ return _("I/O error");
+
+ case CborErrorGarbageAtEnd:
+ return _("garbage after the end of the content");
+
+ case CborErrorUnexpectedEOF:
+ return _("unexpected end of data");
+
+ case CborErrorUnexpectedBreak:
+ return _("unexpected 'break' byte");
+
+ case CborErrorUnknownType:
+ return _("illegal byte (encodes future extension type)");
+
+ case CborErrorIllegalType:
+ return _("mismatched string type in chunked string");
+
+ case CborErrorIllegalNumber:
+ return _("illegal initial byte (encodes unspecified additional information)");
+
+ case CborErrorIllegalSimpleType:
+ return _("illegal encoding of simple type smaller than 32");
+
+ case CborErrorNoMoreStringChunks:
+ return _("no more byte or text strings available");
+
+ case CborErrorUnknownSimpleType:
+ return _("unknown simple type");
+
+ case CborErrorUnknownTag:
+ return _("unknown tag");
+
+ case CborErrorInappropriateTagForType:
+ return _("inappropriate tag for type");
+
+ case CborErrorDuplicateObjectKeys:
+ return _("duplicate keys in object");
+
+ case CborErrorInvalidUtf8TextString:
+ return _("invalid UTF-8 content in string");
+
+ case CborErrorExcludedType:
+ return _("excluded type found");
+
+ case CborErrorExcludedValue:
+ return _("excluded value found");
+
+ case CborErrorImproperValue:
+ case CborErrorOverlongEncoding:
+ return _("value encoded in non-canonical form");
+
+ case CborErrorMapKeyNotString:
+ case CborErrorJsonObjectKeyNotString:
+ return _("key in map is not a string");
+
+ case CborErrorMapNotSorted:
+ return _("map is not sorted");
+
+ case CborErrorMapKeysNotUnique:
+ return _("map keys are not unique");
+
+ case CborErrorTooManyItems:
+ return _("too many items added to encoder");
+
+ case CborErrorTooFewItems:
+ return _("too few items added to encoder");
+
+ case CborErrorDataTooLarge:
+ return _("internal error: data too large");
+
+ case CborErrorNestingTooDeep:
+ return _("internal error: too many nested containers found in recursive function");
+
+ case CborErrorUnsupportedType:
+ return _("unsupported type");
+
+ case CborErrorUnimplementedValidation:
+ return _("validation not implemented for the current parser state");
+
+ case CborErrorJsonObjectKeyIsAggregate:
+ return _("conversion to JSON failed: key in object is an array or map");
+
+ case CborErrorJsonNotImplemented:
+ return _("conversion to JSON failed: open_memstream unavailable");
+
+ case CborErrorInternalError:
+ return _("internal error");
+ }
+ return cbor_error_string(CborUnknownError);
+}
diff --git a/src/3rdparty/tinycbor/src/cborinternal_p.h b/src/3rdparty/tinycbor/src/cborinternal_p.h
new file mode 100644
index 0000000000..c5fe63003f
--- /dev/null
+++ b/src/3rdparty/tinycbor/src/cborinternal_p.h
@@ -0,0 +1,314 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and associated documentation files (the "Software"), to deal
+** in the Software without restriction, including without limitation the rights
+** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+** copies of the Software, and to permit persons to whom the Software is
+** furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+** THE SOFTWARE.
+**
+****************************************************************************/
+
+#ifndef CBORINTERNAL_P_H
+#define CBORINTERNAL_P_H
+
+#include "compilersupport_p.h"
+
+#ifndef CBOR_NO_FLOATING_POINT
+# include <float.h>
+# include <math.h>
+#else
+# ifndef CBOR_NO_HALF_FLOAT_TYPE
+# define CBOR_NO_HALF_FLOAT_TYPE 1
+# endif
+#endif
+
+#ifndef CBOR_NO_HALF_FLOAT_TYPE
+# ifdef __F16C__
+# include <immintrin.h>
+static inline unsigned short encode_half(double val)
+{
+ return _cvtss_sh((float)val, 3);
+}
+static inline double decode_half(unsigned short half)
+{
+ return _cvtsh_ss(half);
+}
+# else
+/* software implementation of float-to-fp16 conversions */
+static inline unsigned short encode_half(double val)
+{
+ uint64_t v;
+ int sign, exp, mant;
+ memcpy(&v, &val, sizeof(v));
+ sign = v >> 63 << 15;
+ exp = (v >> 52) & 0x7ff;
+ mant = v << 12 >> 12 >> (53-11); /* keep only the 11 most significant bits of the mantissa */
+ exp -= 1023;
+ if (exp == 1024) {
+ /* infinity or NaN */
+ exp = 16;
+ mant >>= 1;
+ } else if (exp >= 16) {
+ /* overflow, as largest number */
+ exp = 15;
+ mant = 1023;
+ } else if (exp >= -14) {
+ /* regular normal */
+ } else if (exp >= -24) {
+ /* subnormal */
+ mant |= 1024;
+ mant >>= -(exp + 14);
+ exp = -15;
+ } else {
+ /* underflow, make zero */
+ return 0;
+ }
+
+ /* safe cast here as bit operations above guarantee not to overflow */
+ return (unsigned short)(sign | ((exp + 15) << 10) | mant);
+}
+
+/* this function was copied & adapted from RFC 7049 Appendix D */
+static inline double decode_half(unsigned short half)
+{
+ int exp = (half >> 10) & 0x1f;
+ int mant = half & 0x3ff;
+ double val;
+ if (exp == 0) val = ldexp(mant, -24);
+ else if (exp != 31) val = ldexp(mant + 1024, exp - 25);
+ else val = mant == 0 ? INFINITY : NAN;
+ return half & 0x8000 ? -val : val;
+}
+# endif
+#endif /* CBOR_NO_HALF_FLOAT_TYPE */
+
+#ifndef CBOR_INTERNAL_API
+# define CBOR_INTERNAL_API
+#endif
+
+#ifndef CBOR_PARSER_MAX_RECURSIONS
+# define CBOR_PARSER_MAX_RECURSIONS 1024
+#endif
+
+#ifndef CBOR_ENCODER_WRITER_CONTROL
+# define CBOR_ENCODER_WRITER_CONTROL 0
+#endif
+#ifndef CBOR_PARSER_READER_CONTROL
+# define CBOR_PARSER_READER_CONTROL 0
+#endif
+
+/*
+ * CBOR Major types
+ * Encoded in the high 3 bits of the descriptor byte
+ * See http://tools.ietf.org/html/rfc7049#section-2.1
+ */
+typedef enum CborMajorTypes {
+ UnsignedIntegerType = 0U,
+ NegativeIntegerType = 1U,
+ ByteStringType = 2U,
+ TextStringType = 3U,
+ ArrayType = 4U,
+ MapType = 5U, /* a.k.a. object */
+ TagType = 6U,
+ SimpleTypesType = 7U
+} CborMajorTypes;
+
+/*
+ * CBOR simple and floating point types
+ * Encoded in the low 8 bits of the descriptor byte when the
+ * Major Type is 7.
+ */
+typedef enum CborSimpleTypes {
+ FalseValue = 20,
+ TrueValue = 21,
+ NullValue = 22,
+ UndefinedValue = 23,
+ SimpleTypeInNextByte = 24, /* not really a simple type */
+ HalfPrecisionFloat = 25, /* ditto */
+ SinglePrecisionFloat = 26, /* ditto */
+ DoublePrecisionFloat = 27, /* ditto */
+ Break = 31
+} CborSimpleTypes;
+
+enum {
+ SmallValueBitLength = 5U,
+ SmallValueMask = (1U << SmallValueBitLength) - 1, /* 31 */
+ Value8Bit = 24U,
+ Value16Bit = 25U,
+ Value32Bit = 26U,
+ Value64Bit = 27U,
+ IndefiniteLength = 31U,
+
+ MajorTypeShift = SmallValueBitLength,
+ MajorTypeMask = (int) (~0U << MajorTypeShift),
+
+ BreakByte = (unsigned)Break | (SimpleTypesType << MajorTypeShift)
+};
+
+static inline void copy_current_position(CborValue *dst, const CborValue *src)
+{
+ /* This "if" is here for pedantry only: the two branches should perform
+ * the same memory operation. */
+ if (src->parser->flags & CborParserFlag_ExternalSource)
+ dst->source.token = src->source.token;
+ else
+ dst->source.ptr = src->source.ptr;
+}
+
+static inline bool can_read_bytes(const CborValue *it, size_t n)
+{
+ if (CBOR_PARSER_READER_CONTROL >= 0) {
+ if (it->parser->flags & CborParserFlag_ExternalSource || CBOR_PARSER_READER_CONTROL != 0) {
+#ifdef CBOR_PARSER_CAN_READ_BYTES_FUNCTION
+ return CBOR_PARSER_CAN_READ_BYTES_FUNCTION(it->source.token, n);
+#else
+ return it->parser->source.ops->can_read_bytes(it->source.token, n);
+#endif
+ }
+ }
+
+ /* Convert the pointer subtraction to size_t since end >= ptr
+ * (this prevents issues with (ptrdiff_t)n becoming negative).
+ */
+ return (size_t)(it->parser->source.end - it->source.ptr) >= n;
+}
+
+static inline void advance_bytes(CborValue *it, size_t n)
+{
+ if (CBOR_PARSER_READER_CONTROL >= 0) {
+ if (it->parser->flags & CborParserFlag_ExternalSource || CBOR_PARSER_READER_CONTROL != 0) {
+#ifdef CBOR_PARSER_ADVANCE_BYTES_FUNCTION
+ CBOR_PARSER_ADVANCE_BYTES_FUNCTION(it->source.token, n);
+#else
+ it->parser->source.ops->advance_bytes(it->source.token, n);
+#endif
+ return;
+ }
+ }
+
+ it->source.ptr += n;
+}
+
+static inline CborError transfer_string(CborValue *it, const void **ptr, size_t offset, size_t len)
+{
+ if (CBOR_PARSER_READER_CONTROL >= 0) {
+ if (it->parser->flags & CborParserFlag_ExternalSource || CBOR_PARSER_READER_CONTROL != 0) {
+#ifdef CBOR_PARSER_TRANSFER_STRING_FUNCTION
+ return CBOR_PARSER_TRANSFER_STRING_FUNCTION(it->source.token, ptr, offset, len);
+#else
+ return it->parser->source.ops->transfer_string(it->source.token, ptr, offset, len);
+#endif
+ }
+ }
+
+ it->source.ptr += offset;
+ if (can_read_bytes(it, len)) {
+ *CONST_CAST(const void **, ptr) = it->source.ptr;
+ it->source.ptr += len;
+ return CborNoError;
+ }
+ return CborErrorUnexpectedEOF;
+}
+
+static inline void *read_bytes_unchecked(const CborValue *it, void *dst, size_t offset, size_t n)
+{
+ if (CBOR_PARSER_READER_CONTROL >= 0) {
+ if (it->parser->flags & CborParserFlag_ExternalSource || CBOR_PARSER_READER_CONTROL != 0) {
+#ifdef CBOR_PARSER_READ_BYTES_FUNCTION
+ return CBOR_PARSER_READ_BYTES_FUNCTION(it->source.token, dst, offset, n);
+#else
+ return it->parser->source.ops->read_bytes(it->source.token, dst, offset, n);
+#endif
+ }
+ }
+
+ return memcpy(dst, it->source.ptr + offset, n);
+}
+
+#ifdef __GNUC__
+__attribute__((warn_unused_result))
+#endif
+static inline void *read_bytes(const CborValue *it, void *dst, size_t offset, size_t n)
+{
+ if (can_read_bytes(it, offset + n))
+ return read_bytes_unchecked(it, dst, offset, n);
+ return NULL;
+}
+
+static inline uint16_t read_uint8(const CborValue *it, size_t offset)
+{
+ uint8_t result;
+ read_bytes_unchecked(it, &result, offset, sizeof(result));
+ return result;
+}
+
+static inline uint16_t read_uint16(const CborValue *it, size_t offset)
+{
+ uint16_t result;
+ read_bytes_unchecked(it, &result, offset, sizeof(result));
+ return cbor_ntohs(result);
+}
+
+static inline uint32_t read_uint32(const CborValue *it, size_t offset)
+{
+ uint32_t result;
+ read_bytes_unchecked(it, &result, offset, sizeof(result));
+ return cbor_ntohl(result);
+}
+
+static inline uint64_t read_uint64(const CborValue *it, size_t offset)
+{
+ uint64_t result;
+ read_bytes_unchecked(it, &result, offset, sizeof(result));
+ return cbor_ntohll(result);
+}
+
+static inline CborError extract_number_checked(const CborValue *it, uint64_t *value, size_t *bytesUsed)
+{
+ uint8_t descriptor;
+ size_t bytesNeeded = 0;
+
+ /* We've already verified that there's at least one byte to be read */
+ read_bytes_unchecked(it, &descriptor, 0, 1);
+ descriptor &= SmallValueMask;
+ if (descriptor < Value8Bit) {
+ *value = descriptor;
+ } else if (unlikely(descriptor > Value64Bit)) {
+ return CborErrorIllegalNumber;
+ } else {
+ bytesNeeded = (size_t)(1 << (descriptor - Value8Bit));
+ if (!can_read_bytes(it, 1 + bytesNeeded))
+ return CborErrorUnexpectedEOF;
+ if (descriptor <= Value16Bit) {
+ if (descriptor == Value16Bit)
+ *value = read_uint16(it, 1);
+ else
+ *value = read_uint8(it, 1);
+ } else {
+ if (descriptor == Value32Bit)
+ *value = read_uint32(it, 1);
+ else
+ *value = read_uint64(it, 1);
+ }
+ }
+
+ if (bytesUsed)
+ *bytesUsed = bytesNeeded;
+ return CborNoError;
+}
+
+#endif /* CBORINTERNAL_P_H */
diff --git a/src/3rdparty/tinycbor/src/cborjson.h b/src/3rdparty/tinycbor/src/cborjson.h
new file mode 100644
index 0000000000..8ff27b9202
--- /dev/null
+++ b/src/3rdparty/tinycbor/src/cborjson.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Intel Corporation
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and associated documentation files (the "Software"), to deal
+** in the Software without restriction, including without limitation the rights
+** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+** copies of the Software, and to permit persons to whom the Software is
+** furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+** THE SOFTWARE.
+**
+****************************************************************************/
+
+#ifndef CBORJSON_H
+#define CBORJSON_H
+
+#include "cbor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Conversion to JSON */
+enum CborToJsonFlags
+{
+ CborConvertAddMetadata = 1,
+ CborConvertTagsToObjects = 2,
+ CborConvertIgnoreTags = 0,
+
+ CborConvertObeyByteStringTags = 0,
+ CborConvertByteStringsToBase64Url = 4,
+
+ CborConvertRequireMapStringKeys = 0,
+ CborConvertStringifyMapKeys = 8,
+
+ CborConvertDefaultFlags = 0
+};
+
+CBOR_API CborError cbor_value_to_json_advance(FILE *out, CborValue *value, int flags);
+CBOR_INLINE_API CborError cbor_value_to_json(FILE *out, const CborValue *value, int flags)
+{
+ CborValue copy = *value;
+ return cbor_value_to_json_advance(out, &copy, flags);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CBORJSON_H */
+
diff --git a/src/3rdparty/tinycbor/src/cborparser.c b/src/3rdparty/tinycbor/src/cborparser.c
new file mode 100644
index 0000000000..971230ea61
--- /dev/null
+++ b/src/3rdparty/tinycbor/src/cborparser.c
@@ -0,0 +1,1526 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and associated documentation files (the "Software"), to deal
+** in the Software without restriction, including without limitation the rights
+** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+** copies of the Software, and to permit persons to whom the Software is
+** furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+** THE SOFTWARE.
+**
+****************************************************************************/
+
+#ifndef _BSD_SOURCE
+#define _BSD_SOURCE 1
+#endif
+#ifndef _DEFAULT_SOURCE
+#define _DEFAULT_SOURCE 1
+#endif
+#ifndef __STDC_LIMIT_MACROS
+# define __STDC_LIMIT_MACROS 1
+#endif
+
+#include "cbor.h"
+#include "cborinternal_p.h"
+#include "compilersupport_p.h"
+
+#include <string.h>
+
+/**
+ * \defgroup CborParsing Parsing CBOR streams
+ * \brief Group of functions used to parse CBOR streams.
+ *
+ * TinyCBOR provides functions for pull-based stream parsing of a CBOR-encoded
+ * payload. The main data type for the parsing is a CborValue, which behaves
+ * like an iterator and can be used to extract the encoded data. It is first
+ * initialized with a call to cbor_parser_init() and is usually used to extract
+ * exactly one item, most often an array or map.
+ *
+ * Nested CborValue objects can be parsed using cbor_value_enter_container().
+ * Each call to cbor_value_enter_container() must be matched by a call to
+ * cbor_value_leave_container(), with the exact same parameters.
+ *
+ * The example below initializes a CborParser object, begins the parsing with a
+ * CborValue and decodes a single integer:
+ *
+ * \code
+ * int extract_int(const uint8_t *buffer, size_t len)
+ * {
+ * CborParser parser;
+ * CborValue value;
+ * int result;
+ * cbor_parser_init(buffer, len, 0, &parser, &value);
+ * cbor_value_get_int(&value, &result);
+ * return result;
+ * }
+ * \endcode
+ *
+ * The code above does no error checking, which means it assumes the data comes
+ * from a source trusted to send one properly-encoded integer. The following
+ * example does the exact same operation, but includes error checking and
+ * returns 0 on parsing failure:
+ *
+ * \code
+ * int extract_int(const uint8_t *buffer, size_t len)
+ * {
+ * CborParser parser;
+ * CborValue value;
+ * int result;
+ * if (cbor_parser_init(buffer, len, 0, &parser, &value) != CborNoError)
+ * return 0;
+ * if (!cbor_value_is_integer(&value) ||
+ * cbor_value_get_int(&value, &result) != CborNoError)
+ * return 0;
+ * return result;
+ * }
+ * \endcode
+ *
+ * Note, in the example above, that one can't distinguish a parsing failure
+ * from an encoded value of zero. Reporting a parsing error is left as an
+ * exercise to the reader.
+ *
+ * The code above does not execute a range-check either: it is possible that
+ * the value decoded from the CBOR stream encodes a number larger than what can
+ * be represented in a variable of type \c{int}. If detecting that case is
+ * important, the code should call cbor_value_get_int_checked() instead.
+ *
+ * <h3 class="groupheader">Memory and parsing constraints</h3>
+ *
+ * TinyCBOR is designed to run with little memory and with minimal overhead.
+ * Except where otherwise noted, the parser functions always run on constant
+ * time (O(1)), do not recurse and never allocate memory (thus, stack usage is
+ * bounded and is O(1)).
+ *
+ * <h3 class="groupheader">Error handling and preconditions</h3>
+ *
+ * All functions operating on a CborValue return a CborError condition, with
+ * CborNoError standing for the normal situation in which no parsing error
+ * occurred. All functions may return parsing errors in case the stream cannot
+ * be decoded properly, be it due to corrupted data or due to reaching the end
+ * of the input buffer.
+ *
+ * Error conditions must not be ignored. All decoder functions have undefined
+ * behavior if called after an error has been reported, and may crash.
+ *
+ * Some functions are also documented to have preconditions, like
+ * cbor_value_get_int() requiring that the input be an integral value.
+ * Violation of preconditions also results in undefined behavior and the
+ * program may crash.
+ */
+
+/**
+ * \addtogroup CborParsing
+ * @{
+ */
+
+/**
+ * \struct CborValue
+ *
+ * This type contains one value parsed from the CBOR stream. Each CborValue
+ * behaves as an iterator in a StAX-style parser.
+ *
+ * \if privatedocs
+ * Implementation details: the CborValue contains these fields:
+ * \list
+ * \li ptr: pointer to the actual data
+ * \li flags: flags from the decoder
+ * \li extra: partially decoded integer value (0, 1 or 2 bytes)
+ * \li remaining: remaining items in this collection after this item or UINT32_MAX if length is unknown
+ * \endlist
+ * \endif
+ */
+
+static uint64_t extract_number_and_advance(CborValue *it)
+{
+ /* This function is only called after we've verified that the number
+ * here is valid, so we can just use _cbor_value_extract_int64_helper. */
+ uint8_t descriptor;
+ uint64_t v = _cbor_value_extract_int64_helper(it);
+
+ read_bytes_unchecked(it, &descriptor, 0, 1);
+ descriptor &= SmallValueMask;
+
+ size_t bytesNeeded = descriptor < Value8Bit ? 0 : (1 << (descriptor - Value8Bit));
+ advance_bytes(it, bytesNeeded + 1);
+
+ return v;
+}
+
+static bool is_fixed_type(uint8_t type)
+{
+ return type != CborTextStringType && type != CborByteStringType && type != CborArrayType &&
+ type != CborMapType;
+}
+
+static CborError preparse_value(CborValue *it)
+{
+ enum {
+ /* flags to keep */
+ FlagsToKeep = CborIteratorFlag_ContainerIsMap | CborIteratorFlag_NextIsMapKey
+ };
+ uint8_t descriptor;
+
+ /* are we at the end? */
+ it->type = CborInvalidType;
+ it->flags &= FlagsToKeep;
+ if (!read_bytes(it, &descriptor, 0, 1))
+ return CborErrorUnexpectedEOF;
+
+ uint8_t type = descriptor & MajorTypeMask;
+ it->type = type;
+ it->extra = (descriptor &= SmallValueMask);
+
+ if (descriptor > Value64Bit) {
+ if (unlikely(descriptor != IndefiniteLength))
+ return type == CborSimpleType ? CborErrorUnknownType : CborErrorIllegalNumber;
+ if (likely(!is_fixed_type(type))) {
+ /* special case */
+ it->flags |= CborIteratorFlag_UnknownLength;
+ it->type = type;
+ return CborNoError;
+ }
+ return type == CborSimpleType ? CborErrorUnexpectedBreak : CborErrorIllegalNumber;
+ }
+
+ size_t bytesNeeded = descriptor < Value8Bit ? 0 : (1 << (descriptor - Value8Bit));
+
+ if (bytesNeeded) {
+ if (!can_read_bytes(it, bytesNeeded + 1))
+ return CborErrorUnexpectedEOF;
+
+ it->extra = 0;
+
+ /* read up to 16 bits into it->extra */
+ if (bytesNeeded <= 2) {
+ read_bytes_unchecked(it, &it->extra, 1, bytesNeeded);
+ if (bytesNeeded == 2)
+ it->extra = cbor_ntohs(it->extra);
+ } else {
+ cbor_static_assert(CborIteratorFlag_IntegerValueTooLarge == (Value32Bit & 3));
+ cbor_static_assert((CborIteratorFlag_IntegerValueIs64Bit |
+ CborIteratorFlag_IntegerValueTooLarge) == (Value64Bit & 3));
+ it->flags |= (descriptor & 3);
+ }
+ }
+
+ uint8_t majortype = type >> MajorTypeShift;
+ if (majortype == NegativeIntegerType) {
+ it->flags |= CborIteratorFlag_NegativeInteger;
+ it->type = CborIntegerType;
+ } else if (majortype == SimpleTypesType) {
+ switch (descriptor) {
+ case FalseValue:
+ it->extra = false;
+ it->type = CborBooleanType;
+ break;
+
+ case SinglePrecisionFloat:
+ case DoublePrecisionFloat:
+ it->flags |= CborIteratorFlag_IntegerValueTooLarge;
+ /* fall through */
+ case TrueValue:
+ case NullValue:
+ case UndefinedValue:
+ case HalfPrecisionFloat:
+ read_bytes_unchecked(it, &it->type, 0, 1);
+ break;
+
+ case SimpleTypeInNextByte:
+#ifndef CBOR_PARSER_NO_STRICT_CHECKS
+ if (unlikely(it->extra < 32)) {
+ it->type = CborInvalidType;
+ return CborErrorIllegalSimpleType;
+ }
+#endif
+ break;
+
+ case 28:
+ case 29:
+ case 30:
+ case Break:
+ cbor_assert(false); /* these conditions can't be reached */
+ return CborErrorUnexpectedBreak;
+ }
+ }
+
+ return CborNoError;
+}
+
+static CborError preparse_next_value_nodecrement(CborValue *it)
+{
+ uint8_t byte;
+ if (it->remaining == UINT32_MAX && read_bytes(it, &byte, 0, 1) && byte == (uint8_t)BreakByte) {
+ /* end of map or array */
+ if ((it->flags & CborIteratorFlag_ContainerIsMap && it->flags & CborIteratorFlag_NextIsMapKey)
+ || it->type == CborTagType) {
+ /* but we weren't expecting it! */
+ return CborErrorUnexpectedBreak;
+ }
+ it->type = CborInvalidType;
+ it->remaining = 0;
+ it->flags |= CborIteratorFlag_UnknownLength; /* leave_container must consume the Break */
+ return CborNoError;
+ }
+
+ return preparse_value(it);
+}
+
+static CborError preparse_next_value(CborValue *it)
+{
+ /* tags don't count towards item totals or whether we've successfully
+ * read a map's key or value */
+ bool itemCounts = it->type != CborTagType;
+
+ if (it->remaining != UINT32_MAX) {
+ if (itemCounts && --it->remaining == 0) {
+ it->type = CborInvalidType;
+ it->flags &= ~CborIteratorFlag_UnknownLength; /* no Break to consume */
+ return CborNoError;
+ }
+ }
+ if (itemCounts) {
+ /* toggle the flag indicating whether this was a map key */
+ it->flags ^= CborIteratorFlag_NextIsMapKey;
+ }
+ return preparse_next_value_nodecrement(it);
+}
+
+static CborError advance_internal(CborValue *it)
+{
+ uint64_t length = extract_number_and_advance(it);
+
+ if (it->type == CborByteStringType || it->type == CborTextStringType) {
+ cbor_assert(length == (size_t)length);
+ cbor_assert((it->flags & CborIteratorFlag_UnknownLength) == 0);
+ advance_bytes(it, length);
+ }
+
+ return preparse_next_value(it);
+}
+
+/** \internal
+ *
+ * Decodes the CBOR integer value when it is larger than the 16 bits available
+ * in value->extra. This function requires that value->flags have the
+ * CborIteratorFlag_IntegerValueTooLarge flag set.
+ *
+ * This function is also used to extract single- and double-precision floating
+ * point values (SinglePrecisionFloat == Value32Bit and DoublePrecisionFloat ==
+ * Value64Bit).
+ */
+uint64_t _cbor_value_decode_int64_internal(const CborValue *value)
+{
+ cbor_assert(value->flags & CborIteratorFlag_IntegerValueTooLarge ||
+ value->type == CborFloatType || value->type == CborDoubleType);
+ if (value->flags & CborIteratorFlag_IntegerValueIs64Bit)
+ return read_uint64(value, 1);
+
+ return read_uint32(value, 1);
+}
+
+/**
+ * Initializes the CBOR parser for parsing \a size bytes beginning at \a
+ * buffer. Parsing will use flags set in \a flags. The iterator to the first
+ * element is returned in \a it.
+ *
+ * The \a parser structure needs to remain valid throughout the decoding
+ * process. It is not thread-safe to share one CborParser among multiple
+ * threads iterating at the same time, but the object can be copied so multiple
+ * threads can iterate.
+ */
+CborError cbor_parser_init(const uint8_t *buffer, size_t size, uint32_t flags, CborParser *parser, CborValue *it)
+{
+ memset(parser, 0, sizeof(*parser));
+ parser->source.end = buffer + size;
+ parser->flags = (enum CborParserGlobalFlags)flags;
+ it->parser = parser;
+ it->source.ptr = buffer;
+ it->remaining = 1; /* there's one type altogether, usually an array or map */
+ it->flags = 0;
+ return preparse_value(it);
+}
+
+CborError cbor_parser_init_reader(const struct CborParserOperations *ops, CborParser *parser, CborValue *it, void *token)
+{
+ memset(parser, 0, sizeof(*parser));
+ parser->source.ops = ops;
+ parser->flags = CborParserFlag_ExternalSource;
+ it->parser = parser;
+ it->source.token = token;
+ it->remaining = 1;
+ return preparse_value(it);
+}
+
+/**
+ * \fn bool cbor_value_at_end(const CborValue *it)
+ *
+ * Returns true if \a it has reached the end of the iteration, usually when
+ * advancing after the last item in an array or map.
+ *
+ * In the case of the outermost CborValue object, this function returns true
+ * after decoding a single element. A pointer to the first byte of the
+ * remaining data (if any) can be obtained with cbor_value_get_next_byte().
+ *
+ * \sa cbor_value_advance(), cbor_value_is_valid(), cbor_value_get_next_byte()
+ */
+
+/**
+ * \fn const uint8_t *cbor_value_get_next_byte(const CborValue *it)
+ *
+ * Returns a pointer to the next byte that would be decoded if this CborValue
+ * object were advanced.
+ *
+ * This function is useful if cbor_value_at_end() returns true for the
+ * outermost CborValue: the pointer returned is the first byte of the data
+ * remaining in the buffer, if any. Code can decide whether to begin decoding a
+ * new CBOR data stream from this point, or parse some other data appended to
+ * the same buffer.
+ *
+ * This function may be used even after a parsing error. If that occurred,
+ * then this function returns a pointer to where the parsing error occurred.
+ * Note that the error recovery is not precise and the pointer may not indicate
+ * the exact byte containing bad data.
+ *
+ * This function makes sense only when using a linear buffer (that is, when the
+ * parser is initialize by cbor_parser_init()). If using an external source,
+ * this function may return garbage; instead, consult the external source itself
+ * to find out more details about the presence of more data.
+ *
+ * \sa cbor_value_at_end()
+ */
+
+CborError cbor_value_reparse(CborValue *it)
+{
+ if (it->flags & CborIteratorFlag_IteratingStringChunks)
+ return CborNoError;
+ return preparse_next_value_nodecrement(it);
+}
+
+/**
+ * \fn bool cbor_value_is_valid(const CborValue *it)
+ *
+ * Returns true if the iterator \a it contains a valid value. Invalid iterators
+ * happen when iteration reaches the end of a container (see \ref
+ * cbor_value_at_end()) or when a search function resulted in no matches.
+ *
+ * \sa cbor_value_advance(), cbor_value_at_end(), cbor_value_get_type()
+ */
+
+/**
+ * Performs a basic validation of the CBOR stream pointed by \a it and returns
+ * the error it found. If no error was found, it returns CborNoError and the
+ * application can iterate over the items with certainty that no other errors
+ * will appear during parsing.
+ *
+ * A basic validation checks for:
+ * \list
+ * \li absence of undefined additional information bytes;
+ * \li well-formedness of all numbers, lengths, and simple values;
+ * \li string contents match reported sizes;
+ * \li arrays and maps contain the number of elements they are reported to have;
+ * \endlist
+ *
+ * For further checks, see cbor_value_validate().
+ *
+ * This function has the same timing and memory requirements as
+ * cbor_value_advance().
+ *
+ * \sa cbor_value_validate(), cbor_value_advance()
+ */
+CborError cbor_value_validate_basic(const CborValue *it)
+{
+ CborValue value = *it;
+ return cbor_value_advance(&value);
+}
+
+/**
+ * Advances the CBOR value \a it by one fixed-size position. Fixed-size types
+ * are: integers, tags, simple types (including boolean, null and undefined
+ * values) and floating point types.
+ *
+ * If the type is not of fixed size, this function has undefined behavior. Code
+ * must be sure that the current type is one of the fixed-size types before
+ * calling this function. This function is provided because it can guarantee
+ * that it runs in constant time (O(1)).
+ *
+ * If the caller is not able to determine whether the type is fixed or not, code
+ * can use the cbor_value_advance() function instead.
+ *
+ * \sa cbor_value_at_end(), cbor_value_advance(), cbor_value_enter_container(), cbor_value_leave_container()
+ */
+CborError cbor_value_advance_fixed(CborValue *it)
+{
+ cbor_assert(it->type != CborInvalidType);
+ cbor_assert(is_fixed_type(it->type));
+ if (!it->remaining)
+ return CborErrorAdvancePastEOF;
+ return advance_internal(it);
+}
+
+static CborError advance_recursive(CborValue *it, int nestingLevel)
+{
+ CborError err;
+ CborValue recursed;
+
+ if (is_fixed_type(it->type))
+ return advance_internal(it);
+
+ if (!cbor_value_is_container(it)) {
+ size_t len = SIZE_MAX;
+ return _cbor_value_copy_string(it, NULL, &len, it);
+ }
+
+ /* map or array */
+ if (nestingLevel == 0)
+ return CborErrorNestingTooDeep;
+
+ err = cbor_value_enter_container(it, &recursed);
+ if (err)
+ return err;
+ while (!cbor_value_at_end(&recursed)) {
+ err = advance_recursive(&recursed, nestingLevel - 1);
+ if (err)
+ return err;
+ }
+ return cbor_value_leave_container(it, &recursed);
+}
+
+
+/**
+ * Advances the CBOR value \a it by one element, skipping over containers.
+ * Unlike cbor_value_advance_fixed(), this function can be called on a CBOR
+ * value of any type. However, if the type is a container (map or array) or a
+ * string with a chunked payload, this function will not run in constant time
+ * and will recurse into itself (it will run on O(n) time for the number of
+ * elements or chunks and will use O(n) memory for the number of nested
+ * containers).
+ *
+ * The number of recursions can be limited at compile time to avoid stack
+ * exhaustion in constrained systems.
+ *
+ * \sa cbor_value_at_end(), cbor_value_advance_fixed(), cbor_value_enter_container(), cbor_value_leave_container()
+ */
+CborError cbor_value_advance(CborValue *it)
+{
+ cbor_assert(it->type != CborInvalidType);
+ if (!it->remaining)
+ return CborErrorAdvancePastEOF;
+ return advance_recursive(it, CBOR_PARSER_MAX_RECURSIONS);
+}
+
+/**
+ * \fn bool cbor_value_is_tag(const CborValue *value)
+ *
+ * Returns true if the iterator \a value is valid and points to a CBOR tag.
+ *
+ * \sa cbor_value_get_tag(), cbor_value_skip_tag()
+ */
+
+/**
+ * \fn CborError cbor_value_get_tag(const CborValue *value, CborTag *result)
+ *
+ * Retrieves the CBOR tag value that \a value points to and stores it in \a
+ * result. If the iterator \a value does not point to a CBOR tag value, the
+ * behavior is undefined, so checking with \ref cbor_value_get_type or with
+ * \ref cbor_value_is_tag is recommended.
+ *
+ * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_tag()
+ */
+
+/**
+ * Advances the CBOR value \a it until it no longer points to a tag. If \a it is
+ * already not pointing to a tag, then this function returns it unchanged.
+ *
+ * This function does not run in constant time: it will run on O(n) for n being
+ * the number of tags. It does use constant memory (O(1) memory requirements).
+ *
+ * \sa cbor_value_advance_fixed(), cbor_value_advance()
+ */
+CborError cbor_value_skip_tag(CborValue *it)
+{
+ while (cbor_value_is_tag(it)) {
+ CborError err = cbor_value_advance_fixed(it);
+ if (err)
+ return err;
+ }
+ return CborNoError;
+}
+
+/**
+ * \fn bool cbor_value_is_container(const CborValue *it)
+ *
+ * Returns true if the \a it value is a container and requires recursion in
+ * order to decode (maps and arrays), false otherwise.
+ */
+
+/**
+ * Creates a CborValue iterator pointing to the first element of the container
+ * represented by \a it and saves it in \a recursed. The \a it container object
+ * needs to be kept and passed again to cbor_value_leave_container() in order
+ * to continue iterating past this container.
+ *
+ * The \a it CborValue iterator must point to a container.
+ *
+ * \sa cbor_value_is_container(), cbor_value_leave_container(), cbor_value_advance()
+ */
+CborError cbor_value_enter_container(const CborValue *it, CborValue *recursed)
+{
+ cbor_static_assert(CborIteratorFlag_ContainerIsMap == (CborMapType & ~CborArrayType));
+ cbor_assert(cbor_value_is_container(it));
+ *recursed = *it;
+
+ if (it->flags & CborIteratorFlag_UnknownLength) {
+ recursed->remaining = UINT32_MAX;
+ advance_bytes(recursed, 1);
+ } else {
+ uint64_t len = extract_number_and_advance(recursed);
+
+ recursed->remaining = (uint32_t)len;
+ if (recursed->remaining != len || len == UINT32_MAX) {
+ /* back track the pointer to indicate where the error occurred */
+ copy_current_position(recursed, it);
+ return CborErrorDataTooLarge;
+ }
+ if (recursed->type == CborMapType) {
+ /* maps have keys and values, so we need to multiply by 2 */
+ if (recursed->remaining > UINT32_MAX / 2) {
+ /* back track the pointer to indicate where the error occurred */
+ copy_current_position(recursed, it);
+ return CborErrorDataTooLarge;
+ }
+ recursed->remaining *= 2;
+ }
+ if (len == 0) {
+ /* the case of the empty container */
+ recursed->type = CborInvalidType;
+ return CborNoError;
+ }
+ }
+ recursed->flags = (recursed->type & CborIteratorFlag_ContainerIsMap);
+ return preparse_next_value_nodecrement(recursed);
+}
+
+/**
+ * Updates \a it to point to the next element after the container. The \a
+ * recursed object needs to point to the element obtained either by advancing
+ * the last element of the container (via cbor_value_advance(),
+ * cbor_value_advance_fixed(), a nested cbor_value_leave_container(), or the \c
+ * next pointer from cbor_value_copy_string() or cbor_value_dup_string()).
+ *
+ * The \a it and \a recursed parameters must be the exact same as passed to
+ * cbor_value_enter_container().
+ *
+ * \sa cbor_value_enter_container(), cbor_value_at_end()
+ */
+CborError cbor_value_leave_container(CborValue *it, const CborValue *recursed)
+{
+ cbor_assert(cbor_value_is_container(it));
+ cbor_assert(recursed->type == CborInvalidType);
+
+ copy_current_position(it, recursed);
+ if (recursed->flags & CborIteratorFlag_UnknownLength)
+ advance_bytes(it, 1);
+ return preparse_next_value(it);
+}
+
+
+/**
+ * \fn CborType cbor_value_get_type(const CborValue *value)
+ *
+ * Returns the type of the CBOR value that the iterator \a value points to. If
+ * \a value does not point to a valid value, this function returns \ref
+ * CborInvalidType.
+ *
+ * TinyCBOR also provides functions to test directly if a given CborValue object
+ * is of a given type, like cbor_value_is_text_string() and cbor_value_is_null().
+ *
+ * \sa cbor_value_is_valid()
+ */
+
+/**
+ * \fn bool cbor_value_is_null(const CborValue *value)
+ *
+ * Returns true if the iterator \a value is valid and points to a CBOR null type.
+ *
+ * \sa cbor_value_is_valid(), cbor_value_is_undefined()
+ */
+
+/**
+ * \fn bool cbor_value_is_undefined(const CborValue *value)
+ *
+ * Returns true if the iterator \a value is valid and points to a CBOR undefined type.
+ *
+ * \sa cbor_value_is_valid(), cbor_value_is_null()
+ */
+
+/**
+ * \fn bool cbor_value_is_boolean(const CborValue *value)
+ *
+ * Returns true if the iterator \a value is valid and points to a CBOR boolean
+ * type (true or false).
+ *
+ * \sa cbor_value_is_valid(), cbor_value_get_boolean()
+ */
+
+/**
+ * \fn CborError cbor_value_get_boolean(const CborValue *value, bool *result)
+ *
+ * Retrieves the boolean value that \a value points to and stores it in \a
+ * result. If the iterator \a value does not point to a boolean value, the
+ * behavior is undefined, so checking with \ref cbor_value_get_type or with
+ * \ref cbor_value_is_boolean is recommended.
+ *
+ * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_boolean()
+ */
+
+/**
+ * \fn bool cbor_value_is_simple_type(const CborValue *value)
+ *
+ * Returns true if the iterator \a value is valid and points to a CBOR Simple Type
+ * type (other than true, false, null and undefined).
+ *
+ * \sa cbor_value_is_valid(), cbor_value_get_simple_type()
+ */
+
+/**
+ * \fn CborError cbor_value_get_simple_type(const CborValue *value, uint8_t *result)
+ *
+ * Retrieves the CBOR Simple Type value that \a value points to and stores it
+ * in \a result. If the iterator \a value does not point to a simple_type
+ * value, the behavior is undefined, so checking with \ref cbor_value_get_type
+ * or with \ref cbor_value_is_simple_type is recommended.
+ *
+ * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_simple_type()
+ */
+
+/**
+ * \fn bool cbor_value_is_integer(const CborValue *value)
+ *
+ * Returns true if the iterator \a value is valid and points to a CBOR integer
+ * type.
+ *
+ * \sa cbor_value_is_valid(), cbor_value_get_int, cbor_value_get_int64, cbor_value_get_uint64, cbor_value_get_raw_integer
+ */
+
+/**
+ * \fn bool cbor_value_is_unsigned_integer(const CborValue *value)
+ *
+ * Returns true if the iterator \a value is valid and points to a CBOR unsigned
+ * integer type (positive values or zero).
+ *
+ * \sa cbor_value_is_valid(), cbor_value_get_uint64()
+ */
+
+/**
+ * \fn bool cbor_value_is_negative_integer(const CborValue *value)
+ *
+ * Returns true if the iterator \a value is valid and points to a CBOR negative
+ * integer type.
+ *
+ * \sa cbor_value_is_valid(), cbor_value_get_int, cbor_value_get_int64, cbor_value_get_raw_integer
+ */
+
+/**
+ * \fn CborError cbor_value_get_int(const CborValue *value, int *result)
+ *
+ * Retrieves the CBOR integer value that \a value points to and stores it in \a
+ * result. If the iterator \a value does not point to an integer value, the
+ * behavior is undefined, so checking with \ref cbor_value_get_type or with
+ * \ref cbor_value_is_integer is recommended.
+ *
+ * Note that this function does not do range-checking: integral values that do
+ * not fit in a variable of type \c{int} are silently truncated to fit. Use
+ * cbor_value_get_int_checked() if that is not acceptable.
+ *
+ * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer()
+ */
+
+/**
+ * \fn CborError cbor_value_get_int64(const CborValue *value, int64_t *result)
+ *
+ * Retrieves the CBOR integer value that \a value points to and stores it in \a
+ * result. If the iterator \a value does not point to an integer value, the
+ * behavior is undefined, so checking with \ref cbor_value_get_type or with
+ * \ref cbor_value_is_integer is recommended.
+ *
+ * Note that this function does not do range-checking: integral values that do
+ * not fit in a variable of type \c{int64_t} are silently truncated to fit. Use
+ * cbor_value_get_int64_checked() that is not acceptable.
+ *
+ * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer()
+ */
+
+/**
+ * \fn CborError cbor_value_get_uint64(const CborValue *value, uint64_t *result)
+ *
+ * Retrieves the CBOR integer value that \a value points to and stores it in \a
+ * result. If the iterator \a value does not point to an unsigned integer
+ * value, the behavior is undefined, so checking with \ref cbor_value_get_type
+ * or with \ref cbor_value_is_unsigned_integer is recommended.
+ *
+ * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_unsigned_integer()
+ */
+
+/**
+ * \fn CborError cbor_value_get_raw_integer(const CborValue *value, uint64_t *result)
+ *
+ * Retrieves the CBOR integer value that \a value points to and stores it in \a
+ * result. If the iterator \a value does not point to an integer value, the
+ * behavior is undefined, so checking with \ref cbor_value_get_type or with
+ * \ref cbor_value_is_integer is recommended.
+ *
+ * This function is provided because CBOR negative integers can assume values
+ * that cannot be represented with normal 64-bit integer variables.
+ *
+ * If the integer is unsigned (that is, if cbor_value_is_unsigned_integer()
+ * returns true), then \a result will contain the actual value. If the integer
+ * is negative, then \a result will contain the absolute value of that integer,
+ * minus one. That is, \c {actual = -result - 1}. On architectures using two's
+ * complement for representation of negative integers, it is equivalent to say
+ * that \a result will contain the bitwise negation of the actual value.
+ *
+ * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer()
+ */
+
+/**
+ * Retrieves the CBOR integer value that \a value points to and stores it in \a
+ * result. If the iterator \a value does not point to an integer value, the
+ * behavior is undefined, so checking with \ref cbor_value_get_type or with
+ * \ref cbor_value_is_integer is recommended.
+ *
+ * Unlike \ref cbor_value_get_int64(), this function performs a check to see if the
+ * stored integer fits in \a result without data loss. If the number is outside
+ * the valid range for the data type, this function returns the recoverable
+ * error CborErrorDataTooLarge. In that case, use either
+ * cbor_value_get_uint64() (if the number is positive) or
+ * cbor_value_get_raw_integer().
+ *
+ * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer(), cbor_value_get_int64()
+ */
+CborError cbor_value_get_int64_checked(const CborValue *value, int64_t *result)
+{
+ uint64_t v;
+ cbor_assert(cbor_value_is_integer(value));
+ v = _cbor_value_extract_int64_helper(value);
+
+ /* Check before converting, as the standard says (C11 6.3.1.3 paragraph 3):
+ * "[if] the new type is signed and the value cannot be represented in it; either the
+ * result is implementation-defined or an implementation-defined signal is raised."
+ *
+ * The range for int64_t is -2^63 to 2^63-1 (int64_t is required to be
+ * two's complement, C11 7.20.1.1 paragraph 3), which in CBOR is
+ * represented the same way, differing only on the "sign bit" (the major
+ * type).
+ */
+
+ if (unlikely(v > (uint64_t)INT64_MAX))
+ return CborErrorDataTooLarge;
+
+ *result = v;
+ if (value->flags & CborIteratorFlag_NegativeInteger)
+ *result = -*result - 1;
+ return CborNoError;
+}
+
+/**
+ * Retrieves the CBOR integer value that \a value points to and stores it in \a
+ * result. If the iterator \a value does not point to an integer value, the
+ * behavior is undefined, so checking with \ref cbor_value_get_type or with
+ * \ref cbor_value_is_integer is recommended.
+ *
+ * Unlike \ref cbor_value_get_int(), this function performs a check to see if the
+ * stored integer fits in \a result without data loss. If the number is outside
+ * the valid range for the data type, this function returns the recoverable
+ * error CborErrorDataTooLarge. In that case, use one of the other integer
+ * functions to obtain the value.
+ *
+ * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer(), cbor_value_get_int64(),
+ * cbor_value_get_uint64(), cbor_value_get_int64_checked(), cbor_value_get_raw_integer()
+ */
+CborError cbor_value_get_int_checked(const CborValue *value, int *result)
+{
+ uint64_t v;
+ cbor_assert(cbor_value_is_integer(value));
+ v = _cbor_value_extract_int64_helper(value);
+
+ /* Check before converting, as the standard says (C11 6.3.1.3 paragraph 3):
+ * "[if] the new type is signed and the value cannot be represented in it; either the
+ * result is implementation-defined or an implementation-defined signal is raised."
+ *
+ * But we can convert from signed to unsigned without fault (paragraph 2).
+ *
+ * The range for int is implementation-defined and int is not guaranteed to use
+ * two's complement representation (although int32_t is).
+ */
+
+ if (value->flags & CborIteratorFlag_NegativeInteger) {
+ if (unlikely(v > (unsigned) -(INT_MIN + 1)))
+ return CborErrorDataTooLarge;
+
+ *result = (int)v;
+ *result = -*result - 1;
+ } else {
+ if (unlikely(v > (uint64_t)INT_MAX))
+ return CborErrorDataTooLarge;
+
+ *result = (int)v;
+ }
+ return CborNoError;
+
+}
+
+/**
+ * \fn bool cbor_value_is_length_known(const CborValue *value)
+ *
+ * Returns true if the length of this type is known without calculation. That
+ * is, if the length of this CBOR string, map or array is encoded in the data
+ * stream, this function returns true. If the length is not encoded, it returns
+ * false.
+ *
+ * If the length is known, code can call cbor_value_get_string_length(),
+ * cbor_value_get_array_length() or cbor_value_get_map_length() to obtain the
+ * length. If the length is not known but is necessary, code can use the
+ * cbor_value_calculate_string_length() function (no equivalent function is
+ * provided for maps and arrays).
+ */
+
+/**
+ * \fn bool cbor_value_is_text_string(const CborValue *value)
+ *
+ * Returns true if the iterator \a value is valid and points to a CBOR text
+ * string. CBOR text strings are UTF-8 encoded and usually contain
+ * human-readable text.
+ *
+ * \sa cbor_value_is_valid(), cbor_value_get_string_length(), cbor_value_calculate_string_length(),
+ * cbor_value_copy_text_string(), cbor_value_dup_text_string()
+ */
+
+/**
+ * \fn bool cbor_value_is_byte_string(const CborValue *value)
+ *
+ * Returns true if the iterator \a value is valid and points to a CBOR text
+ * string. CBOR byte strings are binary data with no specified encoding or
+ * format.
+ *
+ * \sa cbor_value_is_valid(), cbor_value_get_string_length(), cbor_value_calculate_string_length(),
+ * cbor_value_copy_byte_string(), cbor_value_dup_byte_string()
+ */
+
+/**
+ * \fn CborError cbor_value_get_string_length(const CborValue *value, size_t *length)
+ *
+ * Extracts the length of the byte or text string that \a value points to and
+ * stores it in \a result. If the iterator \a value does not point to a text
+ * string or a byte string, the behaviour is undefined, so checking with \ref
+ * cbor_value_get_type, with \ref cbor_value_is_text_string or \ref
+ * cbor_value_is_byte_string is recommended.
+ *
+ * If the length of this string is not encoded in the CBOR data stream, this
+ * function will return the recoverable error CborErrorUnknownLength. You may
+ * also check whether that is the case by using cbor_value_is_length_known().
+ *
+ * If the length of the string is required but the length was not encoded, use
+ * cbor_value_calculate_string_length(), but note that that function does not
+ * run in constant time.
+ *
+ * \note On 32-bit platforms, this function will return error condition of \ref
+ * CborErrorDataTooLarge if the stream indicates a length that is too big to
+ * fit in 32-bit.
+ *
+ * \sa cbor_value_is_valid(), cbor_value_is_length_known(), cbor_value_calculate_string_length()
+ */
+
+/**
+ * Calculates the length of the byte or text string that \a value points to and
+ * stores it in \a len. If the iterator \a value does not point to a text
+ * string or a byte string, the behaviour is undefined, so checking with \ref
+ * cbor_value_get_type, with \ref cbor_value_is_text_string or \ref
+ * cbor_value_is_byte_string is recommended.
+ *
+ * This function is different from cbor_value_get_string_length() in that it
+ * calculates the length even for strings sent in chunks. For that reason, this
+ * function may not run in constant time (it will run in O(n) time on the
+ * number of chunks). It does use constant memory (O(1)).
+ *
+ * \note On 32-bit platforms, this function will return error condition of \ref
+ * CborErrorDataTooLarge if the stream indicates a length that is too big to
+ * fit in 32-bit.
+ *
+ * \sa cbor_value_get_string_length(), cbor_value_copy_text_string(), cbor_value_copy_byte_string(), cbor_value_is_length_known()
+ */
+CborError cbor_value_calculate_string_length(const CborValue *value, size_t *len)
+{
+ *len = SIZE_MAX;
+ return _cbor_value_copy_string(value, NULL, len, NULL);
+}
+
+CborError _cbor_value_begin_string_iteration(CborValue *it)
+{
+ it->flags |= CborIteratorFlag_IteratingStringChunks |
+ CborIteratorFlag_BeforeFirstStringChunk;
+ if (!cbor_value_is_length_known(it)) {
+ /* chunked string: we're before the first chunk;
+ * advance to the first chunk */
+ advance_bytes(it, 1);
+ }
+
+ return CborNoError;
+}
+
+CborError _cbor_value_finish_string_iteration(CborValue *it)
+{
+ if (!cbor_value_is_length_known(it))
+ advance_bytes(it, 1); /* skip the Break */
+
+ return preparse_next_value(it);
+}
+
+static CborError get_string_chunk_size(const CborValue *it, size_t *offset, size_t *len)
+{
+ uint8_t descriptor;
+ size_t bytesNeeded = 1;
+
+ if (cbor_value_is_length_known(it) && (it->flags & CborIteratorFlag_BeforeFirstStringChunk) == 0)
+ return CborErrorNoMoreStringChunks;
+
+ /* are we at the end? */
+ if (!read_bytes(it, &descriptor, 0, 1))
+ return CborErrorUnexpectedEOF;
+
+ if (descriptor == BreakByte)
+ return CborErrorNoMoreStringChunks;
+ if ((descriptor & MajorTypeMask) != it->type)
+ return CborErrorIllegalType;
+
+ /* find the string length */
+ descriptor &= SmallValueMask;
+ if (descriptor < Value8Bit) {
+ *len = descriptor;
+ } else if (unlikely(descriptor > Value64Bit)) {
+ return CborErrorIllegalNumber;
+ } else {
+ uint64_t val;
+ bytesNeeded = (size_t)(1 << (descriptor - Value8Bit));
+ if (!can_read_bytes(it, 1 + bytesNeeded))
+ return CborErrorUnexpectedEOF;
+
+ if (descriptor <= Value16Bit) {
+ if (descriptor == Value16Bit)
+ val = read_uint16(it, 1);
+ else
+ val = read_uint8(it, 1);
+ } else {
+ if (descriptor == Value32Bit)
+ val = read_uint32(it, 1);
+ else
+ val = read_uint64(it, 1);
+ }
+
+ *len = val;
+ if (*len != val)
+ return CborErrorDataTooLarge;
+
+ ++bytesNeeded;
+ }
+
+ *offset = bytesNeeded;
+ return CborNoError;
+}
+
+CborError _cbor_value_get_string_chunk_size(const CborValue *value, size_t *len)
+{
+ size_t offset;
+ return get_string_chunk_size(value, &offset, len);
+}
+
+static CborError get_string_chunk(CborValue *it, const void **bufferptr, size_t *len)
+{
+ size_t offset;
+ CborError err = get_string_chunk_size(it, &offset, len);
+ if (err)
+ return err;
+
+ /* we're good, transfer the string now */
+ err = transfer_string(it, bufferptr, offset, *len);
+ if (err)
+ return err;
+
+ /* we've iterated at least once */
+ it->flags &= ~CborIteratorFlag_BeforeFirstStringChunk;
+ return CborNoError;
+}
+
+/**
+ * \fn CborError cbor_value_get_text_string_chunk(const CborValue *value, const char **bufferptr, size_t *len, CborValue *next)
+ *
+ * Extracts one text string chunk pointed to by \a value and stores a pointer
+ * to the data in \a buffer and the size in \a len, which must not be null. If
+ * no more chunks are available, then \a bufferptr will be set to null. This
+ * function may be used to iterate over any string without causing its contents
+ * to be copied to a separate buffer, like the convenience function
+ * cbor_value_copy_text_string() does.
+ *
+ * It is designed to be used in code like:
+ *
+ * \code
+ * if (cbor_value_is_text_string(value)) {
+ * char *ptr;
+ * size_t len;
+ * while (1) {
+ * err = cbor_value_get_text_string_chunk(value, &ptr, &len, &value));
+ * if (err) return err;
+ * if (ptr == NULL) return CborNoError;
+ * consume(ptr, len);
+ * }
+ * }
+ * \endcode
+ *
+ * If the iterator \a value does not point to a text string, the behaviour is
+ * undefined, so checking with \ref cbor_value_get_type or \ref
+ * cbor_value_is_text_string is recommended.
+ *
+ * The \a next pointer, if not null, will be updated to point to the next item
+ * after this string. During iteration, the pointer must only be passed back
+ * again to this function; passing it to any other function in this library
+ * results in undefined behavior. If there are no more chunks to be read from
+ * \a value, then \a next will be set to the next item after this string; if \a
+ * value points to the last item, then \a next will be invalid.
+ *
+ * \note This function does not perform UTF-8 validation on the incoming text
+ * string.
+ *
+ * \sa cbor_value_dup_text_string(), cbor_value_copy_text_string(), cbor_value_caculate_string_length(), cbor_value_get_byte_string_chunk()
+ */
+
+/**
+ * \fn CborError cbor_value_get_byte_string_chunk(const CborValue *value, const char **bufferptr, size_t *len, CborValue *next)
+ *
+ * Extracts one byte string chunk pointed to by \a value and stores a pointer
+ * to the data in \a buffer and the size in \a len, which must not be null. If
+ * no more chunks are available, then \a bufferptr will be set to null. This
+ * function may be used to iterate over any string without causing its contents
+ * to be copied to a separate buffer, like the convenience function
+ * cbor_value_copy_byte_string() does.
+ *
+ * It is designed to be used in code like:
+ *
+ * \code
+ * if (cbor_value_is_byte_string(value)) {
+ * char *ptr;
+ * size_t len;
+ * while (1) {
+ * err = cbor_value_get_byte_string_chunk(value, &ptr, &len, &value));
+ * if (err) return err;
+ * if (ptr == NULL) return CborNoError;
+ * consume(ptr, len);
+ * }
+ * }
+ * \endcode
+ *
+ * If the iterator \a value does not point to a byte string, the behaviour is
+ * undefined, so checking with \ref cbor_value_get_type or \ref
+ * cbor_value_is_byte_string is recommended.
+ *
+ * The \a next pointer, if not null, will be updated to point to the next item
+ * after this string. During iteration, the pointer must only be passed back
+ * again to this function; passing it to any other function in this library
+ * results in undefined behavior. If there are no more chunks to be read from
+ * \a value, then \a next will be set to the next item after this string; if \a
+ * value points to the last item, then \a next will be invalid.
+ *
+ * \sa cbor_value_dup_byte_string(), cbor_value_copy_byte_string(), cbor_value_caculate_string_length(), cbor_value_get_text_string_chunk()
+ */
+
+CborError _cbor_value_get_string_chunk(const CborValue *value, const void **bufferptr,
+ size_t *len, CborValue *next)
+{
+ CborValue tmp;
+ if (!next)
+ next = &tmp;
+ *next = *value;
+ return get_string_chunk(next, bufferptr, len);
+}
+
+/* We return uintptr_t so that we can pass memcpy directly as the iteration
+ * function. The choice is to optimize for memcpy, which is used in the base
+ * parser API (cbor_value_copy_string), while memcmp is used in convenience API
+ * only. */
+typedef uintptr_t (*IterateFunction)(char *, const uint8_t *, size_t);
+
+static uintptr_t iterate_noop(char *dest, const uint8_t *src, size_t len)
+{
+ (void)dest;
+ (void)src;
+ (void)len;
+ return true;
+}
+
+static uintptr_t iterate_memcmp(char *s1, const uint8_t *s2, size_t len)
+{
+ return memcmp(s1, (const char *)s2, len) == 0;
+}
+
+static uintptr_t iterate_memcpy(char *dest, const uint8_t *src, size_t len)
+{
+ return (uintptr_t)memcpy(dest, src, len);
+}
+
+static CborError iterate_string_chunks(const CborValue *value, char *buffer, size_t *buflen,
+ bool *result, CborValue *next, IterateFunction func)
+{
+ CborError err;
+ CborValue tmp;
+ size_t total = 0;
+ const void *ptr;
+
+ cbor_assert(cbor_value_is_byte_string(value) || cbor_value_is_text_string(value));
+ if (!next)
+ next = &tmp;
+ *next = *value;
+ *result = true;
+
+ err = _cbor_value_begin_string_iteration(next);
+ if (err)
+ return err;
+
+ while (1) {
+ size_t newTotal;
+ size_t chunkLen;
+ err = get_string_chunk(next, &ptr, &chunkLen);
+ if (err == CborErrorNoMoreStringChunks)
+ break;
+ if (err)
+ return err;
+
+ if (unlikely(add_check_overflow(total, chunkLen, &newTotal)))
+ return CborErrorDataTooLarge;
+
+ if (*result && *buflen >= newTotal)
+ *result = !!func(buffer + total, (const uint8_t *)ptr, chunkLen);
+ else
+ *result = false;
+
+ total = newTotal;
+ }
+
+ /* is there enough room for the ending NUL byte? */
+ if (*result && *buflen > total) {
+ uint8_t nul[] = { 0 };
+ *result = !!func(buffer + total, nul, 1);
+ }
+ *buflen = total;
+ return _cbor_value_finish_string_iteration(next);
+}
+
+/**
+ * \fn CborError cbor_value_copy_text_string(const CborValue *value, char *buffer, size_t *buflen, CborValue *next)
+ *
+ * Copies the string pointed to by \a value into the buffer provided at \a buffer
+ * of \a buflen bytes. If \a buffer is a NULL pointer, this function will not
+ * copy anything and will only update the \a next value.
+ *
+ * If the iterator \a value does not point to a text string, the behaviour is
+ * undefined, so checking with \ref cbor_value_get_type or \ref
+ * cbor_value_is_text_string is recommended.
+ *
+ * If the provided buffer length was too small, this function returns an error
+ * condition of \ref CborErrorOutOfMemory. If you need to calculate the length
+ * of the string in order to preallocate a buffer, use
+ * cbor_value_calculate_string_length().
+ *
+ * On success, this function sets the number of bytes copied to \c{*buflen}. If
+ * the buffer is large enough, this function will insert a null byte after the
+ * last copied byte, to facilitate manipulation of text strings. That byte is
+ * not included in the returned value of \c{*buflen}. If there was no space for
+ * the terminating null, no error is returned, so callers must check the value
+ * of *buflen after the call, before relying on the '\0'; if it has not been
+ * changed by the call, there is no '\0'-termination on the buffer's contents.
+ *
+ * The \a next pointer, if not null, will be updated to point to the next item
+ * after this string. If \a value points to the last item, then \a next will be
+ * invalid.
+ *
+ * This function may not run in constant time (it will run in O(n) time on the
+ * number of chunks). It requires constant memory (O(1)).
+ *
+ * \note This function does not perform UTF-8 validation on the incoming text
+ * string.
+ *
+ * \sa cbor_value_get_text_string_chunk() cbor_value_dup_text_string(), cbor_value_copy_byte_string(), cbor_value_get_string_length(), cbor_value_calculate_string_length()
+ */
+
+/**
+ * \fn CborError cbor_value_copy_byte_string(const CborValue *value, uint8_t *buffer, size_t *buflen, CborValue *next)
+ *
+ * Copies the string pointed by \a value into the buffer provided at \a buffer
+ * of \a buflen bytes. If \a buffer is a NULL pointer, this function will not
+ * copy anything and will only update the \a next value.
+ *
+ * If the iterator \a value does not point to a byte string, the behaviour is
+ * undefined, so checking with \ref cbor_value_get_type or \ref
+ * cbor_value_is_byte_string is recommended.
+ *
+ * If the provided buffer length was too small, this function returns an error
+ * condition of \ref CborErrorOutOfMemory. If you need to calculate the length
+ * of the string in order to preallocate a buffer, use
+ * cbor_value_calculate_string_length().
+ *
+ * On success, this function sets the number of bytes copied to \c{*buflen}. If
+ * the buffer is large enough, this function will insert a null byte after the
+ * last copied byte, to facilitate manipulation of null-terminated strings.
+ * That byte is not included in the returned value of \c{*buflen}.
+ *
+ * The \a next pointer, if not null, will be updated to point to the next item
+ * after this string. If \a value points to the last item, then \a next will be
+ * invalid.
+ *
+ * This function may not run in constant time (it will run in O(n) time on the
+ * number of chunks). It requires constant memory (O(1)).
+ *
+ * \sa cbor_value_get_byte_string_chunk(), cbor_value_dup_text_string(), cbor_value_copy_text_string(), cbor_value_get_string_length(), cbor_value_calculate_string_length()
+ */
+
+CborError _cbor_value_copy_string(const CborValue *value, void *buffer,
+ size_t *buflen, CborValue *next)
+{
+ bool copied_all;
+ CborError err = iterate_string_chunks(value, (char*)buffer, buflen, &copied_all, next,
+ buffer ? iterate_memcpy : iterate_noop);
+ return err ? err :
+ copied_all ? CborNoError : CborErrorOutOfMemory;
+}
+
+/**
+ * Compares the entry \a value with the string \a string and stores the result
+ * in \a result. If the value is different from \a string \a result will
+ * contain \c false.
+ *
+ * The entry at \a value may be a tagged string. If \a value is not a string or
+ * a tagged string, the comparison result will be false.
+ *
+ * CBOR requires text strings to be encoded in UTF-8, but this function does
+ * not validate either the strings in the stream or the string \a string to be
+ * matched. Moreover, comparison is done on strict codepoint comparison,
+ * without any Unicode normalization.
+ *
+ * This function may not run in constant time (it will run in O(n) time on the
+ * number of chunks). It requires constant memory (O(1)).
+ *
+ * \sa cbor_value_skip_tag(), cbor_value_copy_text_string()
+ */
+CborError cbor_value_text_string_equals(const CborValue *value, const char *string, bool *result)
+{
+ size_t len;
+ CborValue copy = *value;
+ CborError err = cbor_value_skip_tag(&copy);
+ if (err)
+ return err;
+ if (!cbor_value_is_text_string(&copy)) {
+ *result = false;
+ return CborNoError;
+ }
+
+ len = strlen(string);
+ return iterate_string_chunks(&copy, CONST_CAST(char *, string), &len, result, NULL, iterate_memcmp);
+}
+
+/**
+ * \fn bool cbor_value_is_array(const CborValue *value)
+ *
+ * Returns true if the iterator \a value is valid and points to a CBOR array.
+ *
+ * \sa cbor_value_is_valid(), cbor_value_is_map()
+ */
+
+/**
+ * \fn CborError cbor_value_get_array_length(const CborValue *value, size_t *length)
+ *
+ * Extracts the length of the CBOR array that \a value points to and stores it
+ * in \a result. If the iterator \a value does not point to a CBOR array, the
+ * behaviour is undefined, so checking with \ref cbor_value_get_type or \ref
+ * cbor_value_is_array is recommended.
+ *
+ * If the length of this array is not encoded in the CBOR data stream, this
+ * function will return the recoverable error CborErrorUnknownLength. You may
+ * also check whether that is the case by using cbor_value_is_length_known().
+ *
+ * \note On 32-bit platforms, this function will return error condition of \ref
+ * CborErrorDataTooLarge if the stream indicates a length that is too big to
+ * fit in 32-bit.
+ *
+ * \sa cbor_value_is_valid(), cbor_value_is_length_known()
+ */
+
+/**
+ * \fn bool cbor_value_is_map(const CborValue *value)
+ *
+ * Returns true if the iterator \a value is valid and points to a CBOR map.
+ *
+ * \sa cbor_value_is_valid(), cbor_value_is_array()
+ */
+
+/**
+ * \fn CborError cbor_value_get_map_length(const CborValue *value, size_t *length)
+ *
+ * Extracts the length of the CBOR map that \a value points to and stores it in
+ * \a result. If the iterator \a value does not point to a CBOR map, the
+ * behaviour is undefined, so checking with \ref cbor_value_get_type or \ref
+ * cbor_value_is_map is recommended.
+ *
+ * If the length of this map is not encoded in the CBOR data stream, this
+ * function will return the recoverable error CborErrorUnknownLength. You may
+ * also check whether that is the case by using cbor_value_is_length_known().
+ *
+ * \note On 32-bit platforms, this function will return error condition of \ref
+ * CborErrorDataTooLarge if the stream indicates a length that is too big to
+ * fit in 32-bit.
+ *
+ * \sa cbor_value_is_valid(), cbor_value_is_length_known()
+ */
+
+/**
+ * Attempts to find the value in map \a map that corresponds to the text string
+ * entry \a string. If the iterator \a value does not point to a CBOR map, the
+ * behaviour is undefined, so checking with \ref cbor_value_get_type or \ref
+ * cbor_value_is_map is recommended.
+ *
+ * If the item is found, it is stored in \a result. If no item is found
+ * matching the key, then \a result will contain an element of type \ref
+ * CborInvalidType. Matching is performed using
+ * cbor_value_text_string_equals(), so tagged strings will also match.
+ *
+ * This function has a time complexity of O(n) where n is the number of
+ * elements in the map to be searched. In addition, this function is has O(n)
+ * memory requirement based on the number of nested containers (maps or arrays)
+ * found as elements of this map.
+ *
+ * \sa cbor_value_is_valid(), cbor_value_text_string_equals(), cbor_value_advance()
+ */
+CborError cbor_value_map_find_value(const CborValue *map, const char *string, CborValue *element)
+{
+ CborError err;
+ size_t len = strlen(string);
+ cbor_assert(cbor_value_is_map(map));
+ err = cbor_value_enter_container(map, element);
+ if (err)
+ goto error;
+
+ while (!cbor_value_at_end(element)) {
+ /* find the non-tag so we can compare */
+ err = cbor_value_skip_tag(element);
+ if (err)
+ goto error;
+ if (cbor_value_is_text_string(element)) {
+ bool equals;
+ size_t dummyLen = len;
+ err = iterate_string_chunks(element, CONST_CAST(char *, string), &dummyLen,
+ &equals, element, iterate_memcmp);
+ if (err)
+ goto error;
+ if (equals)
+ return preparse_value(element);
+ } else {
+ /* skip this key */
+ err = cbor_value_advance(element);
+ if (err)
+ goto error;
+ }
+
+ /* skip this value */
+ err = cbor_value_skip_tag(element);
+ if (err)
+ goto error;
+ err = cbor_value_advance(element);
+ if (err)
+ goto error;
+ }
+
+ /* not found */
+ element->type = CborInvalidType;
+ return CborNoError;
+
+error:
+ element->type = CborInvalidType;
+ return err;
+}
+
+/**
+ * \fn bool cbor_value_is_float(const CborValue *value)
+ *
+ * Returns true if the iterator \a value is valid and points to a CBOR
+ * single-precision floating point (32-bit).
+ *
+ * \sa cbor_value_is_valid(), cbor_value_is_double(), cbor_value_is_half_float()
+ */
+
+/**
+ * \fn CborError cbor_value_get_float(const CborValue *value, float *result)
+ *
+ * Retrieves the CBOR single-precision floating point (32-bit) value that \a
+ * value points to and stores it in \a result. If the iterator \a value does
+ * not point to a single-precision floating point value, the behavior is
+ * undefined, so checking with \ref cbor_value_get_type or with \ref
+ * cbor_value_is_float is recommended.
+ *
+ * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_float(), cbor_value_get_double()
+ */
+
+/**
+ * \fn bool cbor_value_is_double(const CborValue *value)
+ *
+ * Returns true if the iterator \a value is valid and points to a CBOR
+ * double-precision floating point (64-bit).
+ *
+ * \sa cbor_value_is_valid(), cbor_value_is_float(), cbor_value_is_half_float()
+ */
+
+/**
+ * \fn CborError cbor_value_get_double(const CborValue *value, float *result)
+ *
+ * Retrieves the CBOR double-precision floating point (64-bit) value that \a
+ * value points to and stores it in \a result. If the iterator \a value does
+ * not point to a double-precision floating point value, the behavior is
+ * undefined, so checking with \ref cbor_value_get_type or with \ref
+ * cbor_value_is_double is recommended.
+ *
+ * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_double(), cbor_value_get_float()
+ */
+
+/**
+ * \fn bool cbor_value_is_half_float(const CborValue *value)
+ *
+ * Returns true if the iterator \a value is valid and points to a CBOR
+ * single-precision floating point (16-bit).
+ *
+ * \sa cbor_value_is_valid(), cbor_value_is_double(), cbor_value_is_float()
+ */
+
+/**
+ * \fn CborError cbor_value_get_half_float(const CborValue *value, void *result)
+ *
+ * Retrieves the CBOR half-precision floating point (16-bit) value that \a
+ * value points to and stores it in \a result. If the iterator \a value does
+ * not point to a half-precision floating point value, the behavior is
+ * undefined, so checking with \ref cbor_value_get_type or with \ref
+ * cbor_value_is_half_float is recommended.
+ *
+ * Note: since the C language does not have a standard type for half-precision
+ * floating point, this function takes a \c{void *} as a parameter for the
+ * storage area, which must be at least 16 bits wide.
+ *
+ * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_half_float(), cbor_value_get_float()
+ */
+
+/** @} */
diff --git a/src/3rdparty/tinycbor/src/compilersupport_p.h b/src/3rdparty/tinycbor/src/compilersupport_p.h
new file mode 100644
index 0000000000..2b9491d34d
--- /dev/null
+++ b/src/3rdparty/tinycbor/src/compilersupport_p.h
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Intel Corporation
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and associated documentation files (the "Software"), to deal
+** in the Software without restriction, including without limitation the rights
+** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+** copies of the Software, and to permit persons to whom the Software is
+** furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+** THE SOFTWARE.
+**
+****************************************************************************/
+
+#ifndef COMPILERSUPPORT_H
+#define COMPILERSUPPORT_H
+
+#include "cbor.h"
+
+#ifndef _BSD_SOURCE
+# define _BSD_SOURCE
+#endif
+#ifndef _DEFAULT_SOURCE
+# define _DEFAULT_SOURCE
+#endif
+#ifndef assert
+# include <assert.h>
+#endif
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#ifndef __cplusplus
+# include <stdbool.h>
+#endif
+
+#if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L || __cpp_static_assert >= 200410
+# define cbor_static_assert(x) static_assert(x, #x)
+#elif !defined(__cplusplus) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406) && (__STDC_VERSION__ > 199901L)
+# define cbor_static_assert(x) _Static_assert(x, #x)
+#else
+# define cbor_static_assert(x) ((void)sizeof(char[2*!!(x) - 1]))
+#endif
+#if __STDC_VERSION__ >= 199901L || defined(__cplusplus)
+/* inline is a keyword */
+#else
+/* use the definition from cbor.h */
+# define inline CBOR_INLINE
+#endif
+
+#ifdef NDEBUG
+# define cbor_assert(cond) do { if (!(cond)) unreachable(); } while (0)
+#else
+# define cbor_assert(cond) assert(cond)
+#endif
+
+#ifndef STRINGIFY
+#define STRINGIFY(x) STRINGIFY2(x)
+#endif
+#define STRINGIFY2(x) #x
+
+#if !defined(UINT32_MAX) || !defined(INT64_MAX)
+/* C89? We can define UINT32_MAX portably, but not INT64_MAX */
+# error "Your system has stdint.h but that doesn't define UINT32_MAX or INT64_MAX"
+#endif
+
+#ifndef DBL_DECIMAL_DIG
+/* DBL_DECIMAL_DIG is C11 */
+# define DBL_DECIMAL_DIG 17
+#endif
+#define DBL_DECIMAL_DIG_STR STRINGIFY(DBL_DECIMAL_DIG)
+
+#if defined(__GNUC__) && defined(__i386__) && !defined(__iamcu__)
+# define CBOR_INTERNAL_API_CC __attribute__((regparm(3)))
+#elif defined(_MSC_VER) && defined(_M_IX86)
+# define CBOR_INTERNAL_API_CC __fastcall
+#else
+# define CBOR_INTERNAL_API_CC
+#endif
+
+#ifndef __has_builtin
+# define __has_builtin(x) 0
+#endif
+
+#if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) || \
+ (__has_builtin(__builtin_bswap64) && __has_builtin(__builtin_bswap32))
+# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+# define cbor_ntohll __builtin_bswap64
+# define cbor_htonll __builtin_bswap64
+# define cbor_ntohl __builtin_bswap32
+# define cbor_htonl __builtin_bswap32
+# ifdef __INTEL_COMPILER
+# define cbor_ntohs _bswap16
+# define cbor_htons _bswap16
+# elif (__GNUC__ * 100 + __GNUC_MINOR__ >= 608) || __has_builtin(__builtin_bswap16)
+# define cbor_ntohs __builtin_bswap16
+# define cbor_htons __builtin_bswap16
+# else
+# define cbor_ntohs(x) (((uint16_t)x >> 8) | ((uint16_t)x << 8))
+# define cbor_htons cbor_ntohs
+# endif
+# else
+# define cbor_ntohll
+# define cbor_htonll
+# define cbor_ntohl
+# define cbor_htonl
+# define cbor_ntohs
+# define cbor_htons
+# endif
+#elif defined(__sun)
+# include <sys/byteorder.h>
+#elif defined(_MSC_VER)
+/* MSVC, which implies Windows, which implies little-endian and sizeof(long) == 4 */
+# include <stdlib.h>
+# define cbor_ntohll _byteswap_uint64
+# define cbor_htonll _byteswap_uint64
+# define cbor_ntohl _byteswap_ulong
+# define cbor_htonl _byteswap_ulong
+# define cbor_ntohs _byteswap_ushort
+# define cbor_htons _byteswap_ushort
+#endif
+#ifndef cbor_ntohs
+# include <arpa/inet.h>
+# define cbor_ntohs ntohs
+# define cbor_htons htons
+#endif
+#ifndef cbor_ntohl
+# include <arpa/inet.h>
+# define cbor_ntohl ntohl
+# define cbor_htonl htonl
+#endif
+#ifndef cbor_ntohll
+# define cbor_ntohll ntohll
+# define cbor_htonll htonll
+/* ntohll isn't usually defined */
+# ifndef ntohll
+# if (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \
+ (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER == __BIG_ENDIAN) || \
+ (defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN) || \
+ (defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)) || (defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)) || \
+ defined(__ARMEB__) || defined(__MIPSEB__) || defined(__s390__) || defined(__sparc__)
+# define ntohll
+# define htonll
+# elif (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
+ (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN) || \
+ (defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && BYTE_ORDER == LITTLE_ENDIAN) || \
+ defined(_LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || defined(__MIPSEL__) || \
+ defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__) || defined(__amd64)
+# define ntohll(x) ((ntohl((uint32_t)(x)) * UINT64_C(0x100000000)) + (ntohl((x) >> 32)))
+# define htonll ntohll
+# else
+# error "Unable to determine byte order!"
+# endif
+# endif
+#endif
+
+
+#ifdef __cplusplus
+# define CONST_CAST(t, v) const_cast<t>(v)
+#else
+/* C-style const_cast without triggering a warning with -Wcast-qual */
+# define CONST_CAST(t, v) (t)(uintptr_t)(v)
+#endif
+
+#ifdef __GNUC__
+#ifndef likely
+# define likely(x) __builtin_expect(!!(x), 1)
+#endif
+#ifndef unlikely
+# define unlikely(x) __builtin_expect(!!(x), 0)
+#endif
+# define unreachable() __builtin_unreachable()
+#elif defined(_MSC_VER)
+# define likely(x) (x)
+# define unlikely(x) (x)
+# define unreachable() __assume(0)
+#else
+# define likely(x) (x)
+# define unlikely(x) (x)
+# define unreachable() do {} while (0)
+#endif
+
+static inline bool add_check_overflow(size_t v1, size_t v2, size_t *r)
+{
+#if ((defined(__GNUC__) && (__GNUC__ >= 5)) && !defined(__INTEL_COMPILER)) || __has_builtin(__builtin_add_overflow)
+ return __builtin_add_overflow(v1, v2, r);
+#else
+ /* unsigned additions are well-defined */
+ *r = v1 + v2;
+ return v1 > v1 + v2;
+#endif
+}
+
+#endif /* COMPILERSUPPORT_H */
+
diff --git a/src/3rdparty/tinycbor/src/tinycbor-version.h b/src/3rdparty/tinycbor/src/tinycbor-version.h
new file mode 100644
index 0000000000..c26560cce8
--- /dev/null
+++ b/src/3rdparty/tinycbor/src/tinycbor-version.h
@@ -0,0 +1,3 @@
+#define TINYCBOR_VERSION_MAJOR 0
+#define TINYCBOR_VERSION_MINOR 6
+#define TINYCBOR_VERSION_PATCH 0
diff --git a/src/3rdparty/tinycbor/tests/.gitignore b/src/3rdparty/tinycbor/tests/.gitignore
new file mode 100644
index 0000000000..e65577d287
--- /dev/null
+++ b/src/3rdparty/tinycbor/tests/.gitignore
@@ -0,0 +1,15 @@
+Makefile
+debug
+moc_predefs.h
+release
+target_wrapper.*
+
+# The executables
+cpp/cpp
+cpp/cpp.exe
+encoder/encoder
+encoder/encoder.exe
+parser/parser
+parser/parser.exe
+tojson/tojson
+tojson/tojson.exe
diff --git a/src/3rdparty/tinycbor/tests/encoder/data.cpp b/src/3rdparty/tinycbor/tests/encoder/data.cpp
new file mode 100644
index 0000000000..c33fb605aa
--- /dev/null
+++ b/src/3rdparty/tinycbor/tests/encoder/data.cpp
@@ -0,0 +1,310 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and associated documentation files (the "Software"), to deal
+** in the Software without restriction, including without limitation the rights
+** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+** copies of the Software, and to permit persons to whom the Software is
+** furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+** THE SOFTWARE.
+**
+****************************************************************************/
+
+#include <QtTest>
+
+static float myNaNf()
+{
+ uint32_t v = 0x7fc00000;
+ float f;
+ memcpy(&f, &v, sizeof(f));
+ Q_ASSERT(qIsNaN(f));
+ return f;
+}
+
+static float myInff()
+{
+ uint32_t v = 0x7f800000;
+ float f;
+ memcpy(&f, &v, sizeof(f));
+ Q_ASSERT(qIsInf(f));
+ return f;
+}
+
+static float myNInff()
+{
+ uint32_t v = 0xff800000;
+ float f;
+ memcpy(&f, &v, sizeof(f));
+ Q_ASSERT(qIsInf(f));
+ return f;
+}
+
+static double myNaN()
+{
+ uint64_t v = UINT64_C(0x7ff8000000000000);
+ double f;
+ memcpy(&f, &v, sizeof(f));
+ Q_ASSERT(qIsNaN(f));
+ return f;
+}
+
+static double myInf()
+{
+ uint64_t v = UINT64_C(0x7ff0000000000000);
+ double f;
+ memcpy(&f, &v, sizeof(f));
+ Q_ASSERT(qIsInf(f));
+ return f;
+}
+
+static double myNInf()
+{
+ uint64_t v = UINT64_C(0xfff0000000000000);
+ double f;
+ memcpy(&f, &v, sizeof(f));
+ Q_ASSERT(qIsInf(f));
+ return f;
+}
+
+template <size_t N> QByteArray raw(const char (&data)[N])
+{
+ return QByteArray::fromRawData(data, N - 1);
+}
+
+struct NegativeInteger { quint64 abs; };
+Q_DECLARE_METATYPE(NegativeInteger)
+
+struct SimpleType { uint8_t type; };
+Q_DECLARE_METATYPE(SimpleType)
+
+struct Float16Standin { uint16_t val; };
+Q_DECLARE_METATYPE(Float16Standin)
+
+struct Tag { CborTag tag; QVariant tagged; };
+Q_DECLARE_METATYPE(Tag)
+
+template <typename... Args>
+QVariant make_list(const Args &... args)
+{
+ return QVariantList{args...};
+}
+
+typedef QVector<QPair<QVariant, QVariant>> Map;
+Q_DECLARE_METATYPE(Map)
+QVariant make_map(const std::initializer_list<QPair<QVariant, QVariant>> &list)
+{
+ return QVariant::fromValue(Map(list));
+}
+
+struct IndeterminateLengthArray : QVariantList { using QVariantList::QVariantList; };
+struct IndeterminateLengthMap : Map { using Map::Map; };
+Q_DECLARE_METATYPE(IndeterminateLengthArray)
+Q_DECLARE_METATYPE(IndeterminateLengthMap)
+
+QVariant make_ilarray(const std::initializer_list<QVariant> &list)
+{
+ return QVariant::fromValue(IndeterminateLengthArray(list));
+}
+
+QVariant make_ilmap(const std::initializer_list<QPair<QVariant, QVariant>> &list)
+{
+ return QVariant::fromValue(IndeterminateLengthMap(list));
+}
+
+void addColumns()
+{
+ QTest::addColumn<QByteArray>("output");
+ QTest::addColumn<QVariant>("input");
+}
+
+void addFixedData()
+{
+ // unsigned integers
+ QTest::newRow("0U") << raw("\x00") << QVariant(0U);
+ QTest::newRow("1U") << raw("\x01") << QVariant(1U);
+ QTest::newRow("10U") << raw("\x0a") << QVariant(10U);
+ QTest::newRow("23U") << raw("\x17") << QVariant(23U);
+ QTest::newRow("24U") << raw("\x18\x18") << QVariant(24U);
+ QTest::newRow("255U") << raw("\x18\xff") << QVariant(255U);
+ QTest::newRow("256U") << raw("\x19\x01\x00") << QVariant(256U);
+ QTest::newRow("65535U") << raw("\x19\xff\xff") << QVariant(65535U);
+ QTest::newRow("65536U") << raw("\x1a\0\1\x00\x00") << QVariant(65536U);
+ QTest::newRow("4294967295U") << raw("\x1a\xff\xff\xff\xff") << QVariant(4294967295U);
+ QTest::newRow("4294967296U") << raw("\x1b\0\0\0\1\0\0\0\0") << QVariant(Q_UINT64_C(4294967296));
+ QTest::newRow("UINT64_MAX") << raw("\x1b" "\xff\xff\xff\xff" "\xff\xff\xff\xff")
+ << QVariant(std::numeric_limits<quint64>::max());
+
+ // signed integers containing non-negative numbers
+ QTest::newRow("0") << raw("\x00") << QVariant(0);
+ QTest::newRow("1") << raw("\x01") << QVariant(1);
+ QTest::newRow("10") << raw("\x0a") << QVariant(10);
+ QTest::newRow("23") << raw("\x17") << QVariant(23);
+ QTest::newRow("24") << raw("\x18\x18") << QVariant(24);
+ QTest::newRow("255") << raw("\x18\xff") << QVariant(255);
+ QTest::newRow("256") << raw("\x19\x01\x00") << QVariant(256);
+ QTest::newRow("65535") << raw("\x19\xff\xff") << QVariant(65535);
+ QTest::newRow("65536") << raw("\x1a\0\1\x00\x00") << QVariant(65536);
+ QTest::newRow("4294967295") << raw("\x1a\xff\xff\xff\xff") << QVariant(Q_INT64_C(4294967295));
+ QTest::newRow("4294967296") << raw("\x1b\0\0\0\1\0\0\0\0") << QVariant(Q_INT64_C(4294967296));
+
+ // signed integers containing negative numbers
+ QTest::newRow("-1") << raw("\x20") << QVariant(-1);
+ QTest::newRow("-2") << raw("\x21") << QVariant(-2);
+ QTest::newRow("-24") << raw("\x37") << QVariant(-24);
+ QTest::newRow("-25") << raw("\x38\x18") << QVariant(-25);
+ QTest::newRow("-UINT8_MAX") << raw("\x38\xff") << QVariant(-256);
+ QTest::newRow("-UINT8_MAX-1") << raw("\x39\x01\x00") << QVariant(-257);
+ QTest::newRow("-UINT16_MAX") << raw("\x39\xff\xff") << QVariant(-65536);
+ QTest::newRow("-UINT16_MAX-1") << raw("\x3a\0\1\x00\x00") << QVariant(-65537);
+ QTest::newRow("-UINT32_MAX") << raw("\x3a\xff\xff\xff\xff") << QVariant(Q_INT64_C(-4294967296));
+ QTest::newRow("-UINT32_MAX-1") << raw("\x3b\0\0\0\1\0\0\0\0") << QVariant(Q_INT64_C(-4294967297));
+
+ // negative integers
+ auto neg = [](quint64 v) { return QVariant::fromValue<NegativeInteger>({v}); };
+ QTest::newRow("negative1") << raw("\x20") << neg(1);
+ QTest::newRow("negative2") << raw("\x21") << neg(2);
+ QTest::newRow("negative24") << raw("\x37") << neg(24);
+ QTest::newRow("negative25") << raw("\x38\x18") << neg(25);
+ QTest::newRow("negativeUINT8_MAX") << raw("\x38\xff") << neg(256);
+ QTest::newRow("negativeUINT8_MAX-1") << raw("\x39\x01\x00") << neg(257);
+ QTest::newRow("negativeUINT16_MAX") << raw("\x39\xff\xff") << neg(65536);
+ QTest::newRow("negativeUINT16_MAX-1") << raw("\x3a\0\1\x00\x00") << neg(65537);
+ QTest::newRow("negativeUINT32_MAX") << raw("\x3a\xff\xff\xff\xff") << neg(Q_UINT64_C(4294967296));
+ QTest::newRow("negativeUINT32_MAX-1") << raw("\x3b\0\0\0\1\0\0\0\0") << neg(Q_UINT64_C(4294967297));
+ QTest::newRow("negativeUINT64_MAX") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xfe")
+ << neg(std::numeric_limits<quint64>::max());
+ QTest::newRow("negativeUINT64_MAX+1") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xff") << neg(0);
+
+ QTest::newRow("simple0") << raw("\xe0") << QVariant::fromValue(SimpleType{0});
+ QTest::newRow("simple19") << raw("\xf3") << QVariant::fromValue(SimpleType{19});
+ QTest::newRow("false") << raw("\xf4") << QVariant(false);
+ QTest::newRow("true") << raw("\xf5") << QVariant(true);
+ QTest::newRow("null") << raw("\xf6") << QVariant::fromValue<void *>(nullptr);
+ QTest::newRow("undefined") << raw("\xf7") << QVariant();
+ QTest::newRow("simple32") << raw("\xf8\x20") << QVariant::fromValue(SimpleType{32});
+ QTest::newRow("simple255") << raw("\xf8\xff") << QVariant::fromValue(SimpleType{255});
+
+ // floating point
+#if QT_VERSION < QT_VERSION_CHECK(5, 9, 0)
+ QTest::newRow("0.f16") << raw("\xf9\0\0") << QVariant::fromValue(Float16Standin{0x0000});
+#else
+ QTest::newRow("0.f16") << raw("\xf9\0\0") << QVariant::fromValue(qfloat16(0));
+ QTest::newRow("-1.f16") << raw("\xf9\xbc\0") << QVariant::fromValue(qfloat16(-1));
+ QTest::newRow("1.5f16") << raw("\xf9\x3e\0") << QVariant::fromValue(qfloat16(1.5));
+ QTest::newRow("nan_f16") << raw("\xf9\x7e\0") << QVariant::fromValue<qfloat16>(myNaNf());
+ QTest::newRow("-inf_f16") << raw("\xf9\xfc\0") << QVariant::fromValue<qfloat16>(myNInff());
+ QTest::newRow("+inf_f16") << raw("\xf9\x7c\0") << QVariant::fromValue<qfloat16>(myInff());
+#endif
+
+ QTest::newRow("0.f") << raw("\xfa\0\0\0\0") << QVariant::fromValue(0.f);
+ QTest::newRow("0.") << raw("\xfb\0\0\0\0\0\0\0\0") << QVariant(0.);
+ QTest::newRow("-1.f") << raw("\xfa\xbf\x80\0\0") << QVariant::fromValue(-1.f);
+ QTest::newRow("-1.") << raw("\xfb\xbf\xf0\0\0\0\0\0\0") << QVariant(-1.);
+ QTest::newRow("16777215.f") << raw("\xfa\x4b\x7f\xff\xff") << QVariant::fromValue(16777215.f);
+ QTest::newRow("16777215.") << raw("\xfb\x41\x6f\xff\xff\xe0\0\0\0") << QVariant::fromValue(16777215.);
+ QTest::newRow("-16777215.f") << raw("\xfa\xcb\x7f\xff\xff") << QVariant(-16777215.f);
+ QTest::newRow("-16777215.") << raw("\xfb\xc1\x6f\xff\xff\xe0\0\0\0") << QVariant::fromValue(-16777215.);
+
+ QTest::newRow("nan_f") << raw("\xfa\x7f\xc0\0\0") << QVariant::fromValue<float>(myNaNf());
+ QTest::newRow("nan") << raw("\xfb\x7f\xf8\0\0\0\0\0\0") << QVariant(myNaN());
+ QTest::newRow("-inf_f") << raw("\xfa\xff\x80\0\0") << QVariant::fromValue<float>(myNInff());
+ QTest::newRow("-inf") << raw("\xfb\xff\xf0\0\0\0\0\0\0") << QVariant(myNInf());
+ QTest::newRow("+inf_f") << raw("\xfa\x7f\x80\0\0") << QVariant::fromValue<float>(myInff());
+ QTest::newRow("+inf") << raw("\xfb\x7f\xf0\0\0\0\0\0\0") << QVariant(myInf());
+}
+
+void addStringsData()
+{
+ // byte strings
+ QTest::newRow("emptybytestring") << raw("\x40") << QVariant(QByteArray(""));
+ QTest::newRow("bytestring1") << raw("\x41 ") << QVariant(QByteArray(" "));
+ QTest::newRow("bytestring1-nul") << raw("\x41\0") << QVariant(QByteArray("", 1));
+ QTest::newRow("bytestring5") << raw("\x45Hello") << QVariant(QByteArray("Hello"));
+ QTest::newRow("bytestring24") << raw("\x58\x18""123456789012345678901234")
+ << QVariant(QByteArray("123456789012345678901234"));
+ QTest::newRow("bytestring256") << raw("\x59\1\0") + QByteArray(256, '3')
+ << QVariant(QByteArray(256, '3'));
+
+ // text strings
+ QTest::newRow("emptytextstring") << raw("\x60") << QVariant("");
+ QTest::newRow("textstring1") << raw("\x61 ") << QVariant(" ");
+ QTest::newRow("textstring1-nul") << raw("\x61\0") << QVariant(QString::fromLatin1("", 1));
+ QTest::newRow("textstring5") << raw("\x65Hello") << QVariant("Hello");
+ QTest::newRow("textstring24") << raw("\x78\x18""123456789012345678901234")
+ << QVariant("123456789012345678901234");
+ QTest::newRow("textstring256") << raw("\x79\1\0") + QByteArray(256, '3')
+ << QVariant(QString(256, '3'));
+}
+
+void addArraysAndMaps()
+{
+ QTest::newRow("emptyarray") << raw("\x80") << make_list();
+ QTest::newRow("emptymap") << raw("\xa0") << make_map({});
+
+ QTest::newRow("array-0") << raw("\x81\0") << make_list(0);
+ QTest::newRow("array-{0-0}") << raw("\x82\0\0") << make_list(0, 0);
+ QTest::newRow("array-Hello") << raw("\x81\x65Hello") << make_list("Hello");
+ QTest::newRow("array-array-0") << raw("\x81\x81\0") << make_list(make_list(0));
+ QTest::newRow("array-array-{0-0}") << raw("\x81\x82\0\0") << make_list(make_list(0, 0));
+ QTest::newRow("array-array-0-0") << raw("\x82\x81\0\0") << make_list(make_list(0),0);
+ QTest::newRow("array-array-Hello") << raw("\x81\x81\x65Hello") << make_list(make_list("Hello"));
+
+ QTest::newRow("map-0:0") << raw("\xa1\0\0") << make_map({{0,0}});
+ QTest::newRow("map-0:0-1:1") << raw("\xa2\0\0\1\1") << make_map({{0,0}, {1,1}});
+ QTest::newRow("map-0:{map-0:0-1:1}") << raw("\xa1\0\xa2\0\0\1\1") << make_map({{0, make_map({{0,0}, {1,1}})}});
+
+ QTest::newRow("array-map1") << raw("\x81\xa1\0\0") << make_list(make_map({{0,0}}));
+ QTest::newRow("array-map2") << raw("\x82\xa1\0\0\xa1\1\1") << make_list(make_map({{0,0}}), make_map({{1,1}}));
+
+ QTest::newRow("map-array1") << raw("\xa1\x62oc\x81\0") << make_map({{"oc", make_list(0)}});
+ QTest::newRow("map-array2") << raw("\xa1\x62oc\x84\0\1\2\3") << make_map({{"oc", make_list(0, 1, 2, 3)}});
+ QTest::newRow("map-array3") << raw("\xa2\x62oc\x82\0\1\2\3") << make_map({{"oc", make_list(0, 1)}, {2, 3}});
+
+ // indeterminate length
+ QTest::newRow("_emptyarray") << raw("\x9f\xff") << QVariant::fromValue(IndeterminateLengthArray{});
+ QTest::newRow("_emptymap") << raw("\xbf\xff") << make_ilmap({});
+
+ QTest::newRow("_array-0") << raw("\x9f\0\xff") << make_ilarray({0});
+ QTest::newRow("_array-{0-0}") << raw("\x9f\0\0\xff") << make_ilarray({0, 0});
+ QTest::newRow("_array-Hello") << raw("\x9f\x65Hello\xff") << make_ilarray({"Hello"});
+ QTest::newRow("_array-array-0") << raw("\x9f\x81\0\xff") << make_ilarray({make_list(0)});
+ QTest::newRow("_array-_array-0") << raw("\x9f\x9f\0\xff\xff") << make_ilarray({make_ilarray({0})});
+ QTest::newRow("_array-_array-{0-0}") << raw("\x9f\x9f\0\0\xff\xff") << make_ilarray({make_ilarray({0, 0})});
+ QTest::newRow("_array-_array-0-0") << raw("\x9f\x9f\0\xff\0\xff") << make_ilarray({make_ilarray({0}),0});
+ QTest::newRow("_array-_array-Hello") << raw("\x9f\x9f\x65Hello\xff\xff") << make_ilarray({make_ilarray({"Hello"})});
+
+ QTest::newRow("_map-0:0") << raw("\xbf\0\0\xff") << make_ilmap({{0,0}});
+ QTest::newRow("_map-0:0-1:1") << raw("\xbf\0\0\1\1\xff") << make_ilmap({{0,0}, {1,1}});
+ QTest::newRow("_map-0:{map-0:0-1:1}") << raw("\xbf\0\xa2\0\0\1\1\xff") << make_ilmap({{0, make_map({{0,0}, {1,1}})}});
+ QTest::newRow("_map-0:{_map-0:0-1:1}") << raw("\xbf\0\xbf\0\0\1\1\xff\xff") << make_ilmap({{0, make_ilmap({{0,0}, {1,1}})}});
+
+ QTest::newRow("_array-map1") << raw("\x9f\xa1\0\0\xff") << make_ilarray({make_map({{0,0}})});
+ QTest::newRow("_array-_map1") << raw("\x9f\xbf\0\0\xff\xff") << make_ilarray({make_ilmap({{0,0}})});
+ QTest::newRow("_array-map2") << raw("\x9f\xa1\0\0\xa1\1\1\xff") << make_ilarray({make_map({{0,0}}), make_map({{1,1}})});
+ QTest::newRow("_array-_map2") << raw("\x9f\xbf\0\0\xff\xbf\1\1\xff\xff") << make_ilarray({make_ilmap({{0,0}}), make_ilmap({{1,1}})});
+
+ QTest::newRow("_map-array1") << raw("\xbf\x62oc\x81\0\xff") << make_ilmap({{"oc", make_list(0)}});
+ QTest::newRow("_map-_array1") << raw("\xbf\x62oc\x9f\0\xff\xff") << make_ilmap({{"oc", make_ilarray({0})}});
+ QTest::newRow("_map-array2") << raw("\xbf\x62oc\x84\0\1\2\3\xff") << make_ilmap({{"oc", make_list(0, 1, 2, 3)}});
+ QTest::newRow("_map-_array2") << raw("\xbf\x62oc\x9f\0\1\2\3\xff\xff") << make_ilmap({{"oc", make_ilarray({0, 1, 2, 3})}});
+ QTest::newRow("_map-array3") << raw("\xbf\x62oc\x82\0\1\2\3\xff") << make_ilmap({{"oc", make_list(0, 1)}, {2, 3}});
+ QTest::newRow("_map-_array3") << raw("\xbf\x62oc\x9f\0\1\xff\2\3\xff") << make_ilmap({{"oc", make_ilarray({0, 1})}, {2, 3}});
+
+ // tagged
+ QTest::newRow("array-1(0)") << raw("\x81\xc1\0") << make_list(QVariant::fromValue(Tag{1, 0}));
+ QTest::newRow("array-1(map)") << raw("\x81\xc1\xa0") << make_list(QVariant::fromValue(Tag{1, make_map({})}));
+ QTest::newRow("map-1(2):3(4)") << raw("\xa1\xc1\2\xc3\4") << make_map({{QVariant::fromValue(Tag{1, 2}), QVariant::fromValue(Tag{3, 4})}});
+}
+
diff --git a/src/3rdparty/tinycbor/tests/encoder/encoder.pro b/src/3rdparty/tinycbor/tests/encoder/encoder.pro
new file mode 100644
index 0000000000..62d9b7e409
--- /dev/null
+++ b/src/3rdparty/tinycbor/tests/encoder/encoder.pro
@@ -0,0 +1,9 @@
+SOURCES += tst_encoder.cpp
+
+CONFIG += testcase parallel_test c++11
+QT = core testlib
+
+INCLUDEPATH += ../../src
+msvc: POST_TARGETDEPS = ../../lib/tinycbor.lib
+else: POST_TARGETDEPS += ../../lib/libtinycbor.a
+LIBS += $$POST_TARGETDEPS
diff --git a/src/3rdparty/tinycbor/tests/encoder/tst_encoder.cpp b/src/3rdparty/tinycbor/tests/encoder/tst_encoder.cpp
new file mode 100644
index 0000000000..f30c522601
--- /dev/null
+++ b/src/3rdparty/tinycbor/tests/encoder/tst_encoder.cpp
@@ -0,0 +1,496 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Intel Corporation
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and associated documentation files (the "Software"), to deal
+** in the Software without restriction, including without limitation the rights
+** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+** copies of the Software, and to permit persons to whom the Software is
+** furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+** THE SOFTWARE.
+**
+****************************************************************************/
+
+#include <QtTest>
+#include "cbor.h"
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
+#include <qfloat16.h>
+#endif
+
+Q_DECLARE_METATYPE(CborError)
+namespace QTest {
+template<> char *toString<CborError>(const CborError &err)
+{
+ return qstrdup(cbor_error_string(err));
+}
+}
+
+class tst_Encoder : public QObject
+{
+ Q_OBJECT
+private slots:
+ void fixed_data();
+ void fixed();
+ void strings_data();
+ void strings() { fixed(); }
+ void arraysAndMaps_data();
+ void arraysAndMaps() { fixed(); }
+ void tags_data();
+ void tags();
+ void arrays_data() { tags_data(); }
+ void arrays();
+ void maps_data() { tags_data(); }
+ void maps();
+
+ void writerApi_data() { tags_data(); }
+ void writerApi();
+ void writerApiFail_data() { tags_data(); }
+ void writerApiFail();
+ void shortBuffer_data() { tags_data(); }
+ void shortBuffer();
+ void tooShortArrays_data() { tags_data(); }
+ void tooShortArrays();
+ void tooShortMaps_data() { tags_data(); }
+ void tooShortMaps();
+ void tooBigArrays_data() { tags_data(); }
+ void tooBigArrays();
+ void tooBigMaps_data() { tags_data(); }
+ void tooBigMaps();
+ void illegalSimpleType_data();
+ void illegalSimpleType();
+};
+
+#include "tst_encoder.moc"
+#include "data.cpp"
+
+static inline bool isOomError(CborError err)
+{
+ return err == CborErrorOutOfMemory;
+}
+
+CborError encodeVariant(CborEncoder *encoder, const QVariant &v)
+{
+ int type = v.userType();
+ switch (type) {
+ case QVariant::Int:
+ case QVariant::LongLong:
+ return cbor_encode_int(encoder, v.toLongLong());
+
+ case QVariant::UInt:
+ case QVariant::ULongLong:
+ return cbor_encode_uint(encoder, v.toULongLong());
+
+ case QVariant::Bool:
+ return cbor_encode_boolean(encoder, v.toBool());
+
+ case QVariant::Invalid:
+ return cbor_encode_undefined(encoder);
+
+ case QMetaType::VoidStar:
+ return cbor_encode_null(encoder);
+
+ case QVariant::Double:
+ return cbor_encode_double(encoder, v.toDouble());
+
+ case QMetaType::Float:
+ return cbor_encode_float(encoder, v.toFloat());
+
+ case QVariant::String: {
+ QByteArray string = v.toString().toUtf8();
+ return cbor_encode_text_string(encoder, string.constData(), string.length());
+ }
+
+ case QVariant::ByteArray: {
+ QByteArray string = v.toByteArray();
+ return cbor_encode_byte_string(encoder, reinterpret_cast<const quint8 *>(string.constData()), string.length());
+ }
+
+ default:
+ if (type == qMetaTypeId<NegativeInteger>())
+ return cbor_encode_negative_int(encoder, v.value<NegativeInteger>().abs);
+ if (type == qMetaTypeId<SimpleType>())
+ return cbor_encode_simple_value(encoder, v.value<SimpleType>().type);
+#if QT_VERSION < QT_VERSION_CHECK(5, 9, 0)
+ if (type == qMetaTypeId<Float16Standin>())
+ return cbor_encode_half_float(encoder, v.constData());
+#else
+ if (type == qMetaTypeId<qfloat16>())
+ return cbor_encode_half_float(encoder, v.constData());
+#endif
+ if (type == qMetaTypeId<Tag>()) {
+ CborError err = cbor_encode_tag(encoder, v.value<Tag>().tag);
+ if (err && !isOomError(err))
+ return err;
+ return static_cast<CborError>(err | encodeVariant(encoder, v.value<Tag>().tagged));
+ }
+ if (type == QVariant::List || type == qMetaTypeId<IndeterminateLengthArray>()) {
+ CborEncoder sub;
+ QVariantList list = v.toList();
+ size_t len = list.length();
+ if (type == qMetaTypeId<IndeterminateLengthArray>()) {
+ len = CborIndefiniteLength;
+ list = v.value<IndeterminateLengthArray>();
+ }
+ CborError err = cbor_encoder_create_array(encoder, &sub, len);
+ if (err && !isOomError(err))
+ return err;
+ foreach (const QVariant &v2, list) {
+ err = static_cast<CborError>(err | encodeVariant(&sub, v2));
+ if (err && !isOomError(err))
+ return err;
+ }
+ return cbor_encoder_close_container_checked(encoder, &sub);
+ }
+ if (type == qMetaTypeId<Map>() || type == qMetaTypeId<IndeterminateLengthMap>()) {
+ CborEncoder sub;
+ Map map = v.value<Map>();
+ size_t len = map.length();
+ if (type == qMetaTypeId<IndeterminateLengthMap>()) {
+ len = CborIndefiniteLength;
+ map = v.value<IndeterminateLengthMap>();
+ }
+ CborError err = cbor_encoder_create_map(encoder, &sub, len);
+ if (err && !isOomError(err))
+ return err;
+ for (auto pair : map) {
+ err = static_cast<CborError>(err | encodeVariant(&sub, pair.first));
+ if (err && !isOomError(err))
+ return err;
+ err = static_cast<CborError>(err | encodeVariant(&sub, pair.second));
+ if (err && !isOomError(err))
+ return err;
+ }
+ return cbor_encoder_close_container_checked(encoder, &sub);
+ }
+ }
+ return CborErrorUnknownType;
+}
+
+void compare(const QVariant &input, const QByteArray &output)
+{
+ QByteArray buffer(output.length(), Qt::Uninitialized);
+ uint8_t *bufptr = reinterpret_cast<quint8 *>(buffer.data());
+ CborEncoder encoder;
+ cbor_encoder_init(&encoder, bufptr, buffer.length(), 0);
+
+ QCOMPARE(encodeVariant(&encoder, input), CborNoError);
+ QCOMPARE(encoder.remaining, size_t(1));
+ QCOMPARE(cbor_encoder_get_extra_bytes_needed(&encoder), size_t(0));
+
+ buffer.resize(int(cbor_encoder_get_buffer_size(&encoder, bufptr)));
+ QCOMPARE(buffer, output);
+}
+
+void tst_Encoder::fixed_data()
+{
+ addColumns();
+ addFixedData();
+}
+
+void tst_Encoder::fixed()
+{
+ QFETCH(QVariant, input);
+ QFETCH(QByteArray, output);
+ compare(input, output);
+}
+
+void tst_Encoder::strings_data()
+{
+ addColumns();
+ addStringsData();
+}
+
+void tst_Encoder::arraysAndMaps_data()
+{
+ addColumns();
+ addArraysAndMaps();
+}
+
+void tst_Encoder::tags_data()
+{
+ addColumns();
+ addFixedData();
+ addStringsData();
+ addArraysAndMaps();
+}
+
+void tst_Encoder::tags()
+{
+ QFETCH(QVariant, input);
+ QFETCH(QByteArray, output);
+
+ compare(QVariant::fromValue(Tag{1, input}), "\xc1" + output);
+ if (QTest::currentTestFailed()) return;
+
+ compare(QVariant::fromValue(Tag{24, input}), "\xd8\x18" + output);
+ if (QTest::currentTestFailed()) return;
+
+ compare(QVariant::fromValue(Tag{255, input}), "\xd8\xff" + output);
+ if (QTest::currentTestFailed()) return;
+
+ compare(QVariant::fromValue(Tag{256, input}), raw("\xd9\1\0") + output);
+ if (QTest::currentTestFailed()) return;
+
+ compare(QVariant::fromValue(Tag{CborSignatureTag, input}), raw("\xd9\xd9\xf7") + output);
+ if (QTest::currentTestFailed()) return;
+
+ compare(QVariant::fromValue(Tag{65535, input}), raw("\xd9\xff\xff") + output);
+ if (QTest::currentTestFailed()) return;
+
+ compare(QVariant::fromValue(Tag{65536, input}), raw("\xda\0\1\0\0") + output);
+ if (QTest::currentTestFailed()) return;
+
+ compare(QVariant::fromValue(Tag{UINT32_MAX, input}), raw("\xda\xff\xff\xff\xff") + output);
+ if (QTest::currentTestFailed()) return;
+
+ compare(QVariant::fromValue(Tag{UINT32_MAX + Q_UINT64_C(1), input}), raw("\xdb\0\0\0\1\0\0\0\0") + output);
+ if (QTest::currentTestFailed()) return;
+
+ compare(QVariant::fromValue(Tag{UINT64_MAX, input}), raw("\xdb\xff\xff\xff\xff\xff\xff\xff\xff") + output);
+ if (QTest::currentTestFailed()) return;
+
+ // nested tags
+ compare(QVariant::fromValue(Tag{1, QVariant::fromValue(Tag{1, input})}), "\xc1\xc1" + output);
+}
+
+void tst_Encoder::arrays()
+{
+ QFETCH(QVariant, input);
+ QFETCH(QByteArray, output);
+
+ compare(make_list(input), "\x81" + output);
+ if (QTest::currentTestFailed()) return;
+
+ compare(make_list(input, input), "\x82" + output + output);
+ if (QTest::currentTestFailed()) return;
+
+ {
+ QVariantList list{input};
+ QByteArray longoutput = output;
+
+ // make a list with 32 elements (1 << 5)
+ for (int i = 0; i < 5; ++i) {
+ list += list;
+ longoutput += longoutput;
+ }
+ compare(list, "\x98\x20" + longoutput);
+ if (QTest::currentTestFailed()) return;
+
+ // now 256 elements (32 << 3)
+ for (int i = 0; i < 3; ++i) {
+ list += list;
+ longoutput += longoutput;
+ }
+ compare(list, raw("\x99\1\0") + longoutput);
+ if (QTest::currentTestFailed()) return;
+ }
+
+ // nested lists
+ compare(make_list(make_list(input)), "\x81\x81" + output);
+ if (QTest::currentTestFailed()) return;
+
+ compare(make_list(make_list(input, input)), "\x81\x82" + output + output);
+ if (QTest::currentTestFailed()) return;
+
+ compare(make_list(make_list(input), input), "\x82\x81" + output + output);
+ if (QTest::currentTestFailed()) return;
+
+ compare(make_list(make_list(input), make_list(input)), "\x82\x81" + output + "\x81" + output);
+}
+
+void tst_Encoder::maps()
+{
+ QFETCH(QVariant, input);
+ QFETCH(QByteArray, output);
+
+ compare(make_map({{1, input}}), "\xa1\1" + output);
+ if (QTest::currentTestFailed()) return;
+
+ compare(make_map({{1, input}, {input, 24}}), "\xa2\1" + output + output + "\x18\x18");
+ if (QTest::currentTestFailed()) return;
+
+ compare(make_map({{input, input}}), "\xa1" + output + output);
+ if (QTest::currentTestFailed()) return;
+
+ {
+ Map map{{1, input}};
+ QByteArray longoutput = "\1" + output;
+
+ // make a map with 32 elements (1 << 5)
+ for (int i = 0; i < 5; ++i) {
+ map += map;
+ longoutput += longoutput;
+ }
+ compare(QVariant::fromValue(map), "\xb8\x20" + longoutput);
+ if (QTest::currentTestFailed()) return;
+
+ // now 256 elements (32 << 3)
+ for (int i = 0; i < 3; ++i) {
+ map += map;
+ longoutput += longoutput;
+ }
+ compare(QVariant::fromValue(map), raw("\xb9\1\0") + longoutput);
+ if (QTest::currentTestFailed()) return;
+ }
+
+ // nested maps
+ compare(make_map({{1, make_map({{2, input}})}}), "\xa1\1\xa1\2" + output);
+ if (QTest::currentTestFailed()) return;
+
+ compare(make_map({{1, make_map({{2, input}, {input, false}})}}), "\xa1\1\xa2\2" + output + output + "\xf4");
+ if (QTest::currentTestFailed()) return;
+
+ compare(make_map({{1, make_map({{2, input}})}, {input, false}}), "\xa2\1\xa1\2" + output + output + "\xf4");
+ if (QTest::currentTestFailed()) return;
+}
+
+void tst_Encoder::writerApi()
+{
+ QFETCH(QVariant, input);
+ QFETCH(QByteArray, output);
+
+ // instead of writing to a QByteArray like all other tests, write to a QBuffer
+ QBuffer buffer;
+ buffer.open(QIODevice::ReadWrite);
+ auto callback = [](void *token, const void *data, size_t len, CborEncoderAppendType) {
+ auto buffer = static_cast<QBuffer *>(token);
+ buffer->write(static_cast<const char *>(data), len);
+ return CborNoError;
+ };
+
+ CborEncoder encoder;
+ cbor_encoder_init_writer(&encoder, callback, &buffer);
+ QCOMPARE(encodeVariant(&encoder, input), CborNoError);
+
+ buffer.reset();
+ QCOMPARE(buffer.readAll(), output);
+}
+
+void tst_Encoder::writerApiFail()
+{
+ QFETCH(QVariant, input);
+ QFETCH(QByteArray, output);
+
+ // same as above, but we'll produce an error during writing and we expect
+ // it to be returned
+ int callCount = 0;
+ auto callback = [](void *token, const void *, size_t, CborEncoderAppendType) {
+ ++*static_cast<int *>(token);
+ return CborErrorIO;
+ };
+
+ CborEncoder encoder;
+ cbor_encoder_init_writer(&encoder, callback, &callCount);
+ QCOMPARE(encodeVariant(&encoder, input), CborErrorIO);
+ QCOMPARE(callCount, 1);
+}
+
+void tst_Encoder::shortBuffer()
+{
+ QFETCH(QVariant, input);
+ QFETCH(QByteArray, output);
+ QByteArray buffer(output.length(), Qt::Uninitialized);
+
+ for (int len = 0; len < output.length(); ++len) {
+ CborEncoder encoder;
+ cbor_encoder_init(&encoder, reinterpret_cast<quint8 *>(buffer.data()), len, 0);
+ QCOMPARE(encodeVariant(&encoder, input), CborErrorOutOfMemory);
+ QVERIFY(cbor_encoder_get_extra_bytes_needed(&encoder) != 0);
+ QCOMPARE(len + cbor_encoder_get_extra_bytes_needed(&encoder), size_t(output.length()));
+ }
+}
+
+void tst_Encoder::tooShortArrays()
+{
+ QFETCH(QVariant, input);
+ QFETCH(QByteArray, output);
+ QByteArray buffer(output.length() + 1, Qt::Uninitialized);
+
+ CborEncoder encoder, container;
+ cbor_encoder_init(&encoder, reinterpret_cast<quint8 *>(buffer.data()), buffer.length(), 0);
+ QCOMPARE(cbor_encoder_create_array(&encoder, &container, 2), CborNoError);
+ QCOMPARE(encodeVariant(&container, input), CborNoError);
+ QCOMPARE(container.remaining, size_t(2));
+ QCOMPARE(cbor_encoder_close_container_checked(&encoder, &container), CborErrorTooFewItems);
+}
+
+void tst_Encoder::tooShortMaps()
+{
+ QFETCH(QVariant, input);
+ QFETCH(QByteArray, output);
+ QByteArray buffer(output.length() + 1, Qt::Uninitialized);
+
+ CborEncoder encoder, container;
+ cbor_encoder_init(&encoder, reinterpret_cast<quint8 *>(buffer.data()), buffer.length(), 0);
+ QCOMPARE(cbor_encoder_create_map(&encoder, &container, 2), CborNoError);
+ QCOMPARE(encodeVariant(&container, input), CborNoError);
+ QCOMPARE(container.remaining, size_t(4));
+ QCOMPARE(cbor_encoder_close_container_checked(&encoder, &container), CborErrorTooFewItems);
+}
+
+void tst_Encoder::tooBigArrays()
+{
+ QFETCH(QVariant, input);
+ QFETCH(QByteArray, output);
+ QByteArray buffer(output.length() * 2 + 1, Qt::Uninitialized);
+
+ CborEncoder encoder, container;
+ cbor_encoder_init(&encoder, reinterpret_cast<quint8 *>(buffer.data()), buffer.length(), 0);
+ QCOMPARE(cbor_encoder_create_array(&encoder, &container, 1), CborNoError);
+ QCOMPARE(encodeVariant(&container, input), CborNoError);
+ QCOMPARE(encodeVariant(&container, input), CborNoError);
+ QCOMPARE(container.remaining, size_t(0));
+ QCOMPARE(cbor_encoder_close_container_checked(&encoder, &container), CborErrorTooManyItems);
+}
+
+void tst_Encoder::tooBigMaps()
+{
+ QFETCH(QVariant, input);
+ QFETCH(QByteArray, output);
+ QByteArray buffer(output.length() * 3 + 1, Qt::Uninitialized);
+
+ CborEncoder encoder, container;
+ cbor_encoder_init(&encoder, reinterpret_cast<quint8 *>(buffer.data()), buffer.length(), 0);
+ QCOMPARE(cbor_encoder_create_map(&encoder, &container, 1), CborNoError);
+ QCOMPARE(encodeVariant(&container, input), CborNoError);
+ QCOMPARE(encodeVariant(&container, input), CborNoError);
+ QCOMPARE(encodeVariant(&container, input), CborNoError);
+ QCOMPARE(container.remaining, size_t(0));
+ QCOMPARE(cbor_encoder_close_container_checked(&encoder, &container), CborErrorTooManyItems);
+}
+
+void tst_Encoder::illegalSimpleType_data()
+{
+ QTest::addColumn<int>("type");
+ QTest::newRow("half-float") << 25;
+ QTest::newRow("float") << 26;
+ QTest::newRow("double") << 27;
+ QTest::newRow("28") << 28;
+ QTest::newRow("29") << 29;
+ QTest::newRow("30") << 30;
+ QTest::newRow("31") << 31;
+}
+
+void tst_Encoder::illegalSimpleType()
+{
+ QFETCH(int, type);
+
+ quint8 buf[2];
+ CborEncoder encoder;
+ cbor_encoder_init(&encoder, buf, sizeof(buf), 0);
+ QCOMPARE(cbor_encode_simple_value(&encoder, type), CborErrorIllegalSimpleType);
+}
+
+QTEST_MAIN(tst_Encoder)
diff --git a/src/3rdparty/tinycbor/tests/parser/data.cpp b/src/3rdparty/tinycbor/tests/parser/data.cpp
new file mode 100644
index 0000000000..0ab0e47be4
--- /dev/null
+++ b/src/3rdparty/tinycbor/tests/parser/data.cpp
@@ -0,0 +1,573 @@
+#include <QtTest>
+#include <limits>
+#include <cbor.h>
+
+Q_DECLARE_METATYPE(CborError)
+
+template <size_t N> QByteArray raw(const char (&data)[N])
+{
+ return QByteArray::fromRawData(data, N - 1);
+}
+
+void addIntegers()
+{
+ QTest::addColumn<QByteArray>("data");
+ QTest::addColumn<quint64>("expectedRaw");
+ QTest::addColumn<qint64>("expectedValue");
+ QTest::addColumn<bool>("isNegative");
+ QTest::addColumn<bool>("inInt64Range");
+
+ // unsigned integers
+ QTest::newRow("0") << raw("\x00") << Q_UINT64_C(0) << Q_INT64_C(0) << false << true;
+ QTest::newRow("1") << raw("\x01") << Q_UINT64_C(1) << Q_INT64_C(1) << false << true;
+ QTest::newRow("10") << raw("\x0a") << Q_UINT64_C(10) << Q_INT64_C(10) << false << true;
+ QTest::newRow("23") << raw("\x17") << Q_UINT64_C(23) << Q_INT64_C(23) << false << true;
+ QTest::newRow("24") << raw("\x18\x18") << Q_UINT64_C(24) << Q_INT64_C(24) << false << true;
+ QTest::newRow("UINT8_MAX") << raw("\x18\xff") << Q_UINT64_C(255) << Q_INT64_C(255) << false << true;
+ QTest::newRow("UINT8_MAX+1") << raw("\x19\x01\x00") << Q_UINT64_C(256) << Q_INT64_C(256) << false << true;
+ QTest::newRow("UINT16_MAX") << raw("\x19\xff\xff") << Q_UINT64_C(65535) << Q_INT64_C(65535) << false << true;
+ QTest::newRow("UINT16_MAX+1") << raw("\x1a\0\1\x00\x00") << Q_UINT64_C(65536) << Q_INT64_C(65536) << false << true;
+ QTest::newRow("UINT32_MAX") << raw("\x1a\xff\xff\xff\xff") << Q_UINT64_C(4294967295) << Q_INT64_C(4294967295) << false << true;
+ QTest::newRow("UINT32_MAX+1") << raw("\x1b\0\0\0\1\0\0\0\0") << Q_UINT64_C(4294967296) << Q_INT64_C(4294967296) << false << true;
+ QTest::newRow("INT64_MAX") << raw("\x1b" "\x7f\xff\xff\xff" "\xff\xff\xff\xff")
+ << quint64(std::numeric_limits<qint64>::max())
+ << std::numeric_limits<qint64>::max() << false << true;
+ QTest::newRow("UINT64_MAX") << raw("\x1b" "\xff\xff\xff\xff" "\xff\xff\xff\xff")
+ << std::numeric_limits<quint64>::max() << qint64(-123456) << false << false;
+
+ // negative integers
+ QTest::newRow("-1") << raw("\x20") << Q_UINT64_C(0) << Q_INT64_C(-1) << true << true;
+ QTest::newRow("-2") << raw("\x21") << Q_UINT64_C(1) << Q_INT64_C(-2) << true << true;
+ QTest::newRow("-24") << raw("\x37") << Q_UINT64_C(23) << Q_INT64_C(-24) << true << true;
+ QTest::newRow("-25") << raw("\x38\x18") << Q_UINT64_C(24) << Q_INT64_C(-25) << true << true;
+ QTest::newRow("-UINT8_MAX") << raw("\x38\xff") << Q_UINT64_C(255) << Q_INT64_C(-256) << true << true;
+ QTest::newRow("-UINT8_MAX-1") << raw("\x39\x01\x00") << Q_UINT64_C(256) << Q_INT64_C(-257) << true << true;
+ QTest::newRow("-UINT16_MAX") << raw("\x39\xff\xff") << Q_UINT64_C(65535) << Q_INT64_C(-65536) << true << true;
+ QTest::newRow("-UINT16_MAX-1") << raw("\x3a\0\1\x00\x00") << Q_UINT64_C(65536) << Q_INT64_C(-65537) << true << true;
+ QTest::newRow("-UINT32_MAX") << raw("\x3a\xff\xff\xff\xff") << Q_UINT64_C(4294967295) << Q_INT64_C(-4294967296) << true << true;
+ QTest::newRow("-UINT32_MAX-1") << raw("\x3b\0\0\0\1\0\0\0\0") << Q_UINT64_C(4294967296) << Q_INT64_C(-4294967297) << true << true;
+ QTest::newRow("INT64_MIN+1") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xfe")
+ << quint64(std::numeric_limits<qint64>::max() - 1)
+ << (std::numeric_limits<qint64>::min() + 1)
+ << true << true;
+ QTest::newRow("INT64_MIN") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xff")
+ << quint64(std::numeric_limits<qint64>::max())
+ << std::numeric_limits<qint64>::min()
+ << true << true;
+ QTest::newRow("INT64_MIN-1") << raw("\x3b\x80\0\0\0""\0\0\0\0") << Q_UINT64_C(9223372036854775808) << qint64(-123456) << true << false;
+ QTest::newRow("-UINT64_MAX") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xfe")
+ << (std::numeric_limits<quint64>::max() - 1) << qint64(-123456) << true << false;
+ QTest::newRow("-UINT64_MAX+1") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xff")
+ << std::numeric_limits<quint64>::max() << qint64(-123456) << true << false;
+}
+
+void addColumns()
+{
+ QTest::addColumn<QByteArray>("data");
+ QTest::addColumn<QString>("expected");
+ QTest::addColumn<int>("n"); // some aux integer, not added in all columns
+}
+
+void addFixedData()
+{
+ // unsigned integers
+ QTest::newRow("0") << raw("\x00") << "0";
+ QTest::newRow("1") << raw("\x01") << "1";
+ QTest::newRow("10") << raw("\x0a") << "10";
+ QTest::newRow("23") << raw("\x17") << "23";
+ QTest::newRow("24") << raw("\x18\x18") << "24";
+ QTest::newRow("UINT8_MAX") << raw("\x18\xff") << "255";
+ QTest::newRow("UINT8_MAX+1") << raw("\x19\x01\x00") << "256";
+ QTest::newRow("UINT16_MAX") << raw("\x19\xff\xff") << "65535";
+ QTest::newRow("UINT16_MAX+1") << raw("\x1a\0\1\x00\x00") << "65536";
+ QTest::newRow("UINT32_MAX") << raw("\x1a\xff\xff\xff\xff") << "4294967295";
+ QTest::newRow("UINT32_MAX+1") << raw("\x1b\0\0\0\1\0\0\0\0") << "4294967296";
+ QTest::newRow("UINT64_MAX") << raw("\x1b" "\xff\xff\xff\xff" "\xff\xff\xff\xff")
+ << QString::number(std::numeric_limits<uint64_t>::max());
+
+ // negative integers
+ QTest::newRow("-1") << raw("\x20") << "-1";
+ QTest::newRow("-2") << raw("\x21") << "-2";
+ QTest::newRow("-24") << raw("\x37") << "-24";
+ QTest::newRow("-25") << raw("\x38\x18") << "-25";
+ QTest::newRow("-UINT8_MAX") << raw("\x38\xff") << "-256";
+ QTest::newRow("-UINT8_MAX-1") << raw("\x39\x01\x00") << "-257";
+ QTest::newRow("-UINT16_MAX") << raw("\x39\xff\xff") << "-65536";
+ QTest::newRow("-UINT16_MAX-1") << raw("\x3a\0\1\x00\x00") << "-65537";
+ QTest::newRow("-UINT32_MAX") << raw("\x3a\xff\xff\xff\xff") << "-4294967296";
+ QTest::newRow("-UINT32_MAX-1") << raw("\x3b\0\0\0\1\0\0\0\0") << "-4294967297";
+ QTest::newRow("INT64_MIN+1") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xfe")
+ << QString::number(std::numeric_limits<int64_t>::min() + 1);
+ QTest::newRow("INT64_MIN") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xff")
+ << QString::number(std::numeric_limits<int64_t>::min());
+ QTest::newRow("INT64_MIN-1") << raw("\x3b\x80\0\0\0""\0\0\0\0") << "-9223372036854775809";
+ QTest::newRow("-UINT64_MAX") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xfe")
+ << '-' + QString::number(std::numeric_limits<uint64_t>::max());
+ QTest::newRow("-UINT64_MAX+1") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xff")
+ << "-18446744073709551616";
+
+ // overlongs
+ QTest::newRow("0*1") << raw("\x18\x00") << "0_0";
+ QTest::newRow("0*2") << raw("\x19\x00\x00") << "0_1";
+ QTest::newRow("0*4") << raw("\x1a\0\0\0\0") << "0_2";
+ QTest::newRow("0*8") << raw("\x1b\0\0\0\0\0\0\0\0") << "0_3";
+ QTest::newRow("-1*1") << raw("\x38\x00") << "-1_0";
+ QTest::newRow("-1*2") << raw("\x39\x00\x00") << "-1_1";
+ QTest::newRow("-1*4") << raw("\x3a\0\0\0\0") << "-1_2";
+ QTest::newRow("-1*8") << raw("\x3b\0\0\0\0\0\0\0\0") << "-1_3";
+
+ QTest::newRow("simple0") << raw("\xe0") << "simple(0)";
+ QTest::newRow("simple19") << raw("\xf3") << "simple(19)";
+ QTest::newRow("false") << raw("\xf4") << "false";
+ QTest::newRow("true") << raw("\xf5") << "true";
+ QTest::newRow("null") << raw("\xf6") << "null";
+ QTest::newRow("undefined") << raw("\xf7") << "undefined";
+ QTest::newRow("simple32") << raw("\xf8\x20") << "simple(32)";
+ QTest::newRow("simple255") << raw("\xf8\xff") << "simple(255)";
+
+ // floating point
+
+ QTest::newRow("0.f16") << raw("\xf9\0\0") << "0.f16";
+ QTest::newRow("0.f") << raw("\xfa\0\0\0\0") << "0.f";
+ QTest::newRow("0.") << raw("\xfb\0\0\0\0\0\0\0\0") << "0.";
+ QTest::newRow("-1.f16") << raw("\xf9\xbc\x00") << "-1.f16";
+ QTest::newRow("-1.f") << raw("\xfa\xbf\x80\0\0") << "-1.f";
+ QTest::newRow("-1.") << raw("\xfb\xbf\xf0\0\0\0\0\0\0") << "-1.";
+ QTest::newRow("65504.f16") << raw("\xf9\x7b\xff") << "65504.f16";
+ QTest::newRow("16777215.f") << raw("\xfa\x4b\x7f\xff\xff") << "16777215.f";
+ QTest::newRow("16777215.") << raw("\xfb\x41\x6f\xff\xff\xe0\0\0\0") << "16777215.";
+ QTest::newRow("-16777215.f") << raw("\xfa\xcb\x7f\xff\xff") << "-16777215.f";
+ QTest::newRow("-16777215.") << raw("\xfb\xc1\x6f\xff\xff\xe0\0\0\0") << "-16777215.";
+
+ QTest::newRow("0.5f16") << raw("\xf9\x38\0") << "0.5f16";
+ QTest::newRow("0.5f") << raw("\xfa\x3f\0\0\0") << "0.5f";
+ QTest::newRow("0.5") << raw("\xfb\x3f\xe0\0\0\0\0\0\0") << "0.5";
+ QTest::newRow("2.f16^11-1") << raw("\xf9\x67\xff") << "2047.f16";
+ QTest::newRow("2.f^24-1") << raw("\xfa\x4b\x7f\xff\xff") << "16777215.f";
+ QTest::newRow("2.^53-1") << raw("\xfb\x43\x3f\xff\xff""\xff\xff\xff\xff") << "9007199254740991.";
+ QTest::newRow("2.f^64-epsilon") << raw("\xfa\x5f\x7f\xff\xff") << "18446742974197923840.f";
+ QTest::newRow("2.^64-epsilon") << raw("\xfb\x43\xef\xff\xff""\xff\xff\xff\xff") << "18446744073709549568.";
+ QTest::newRow("2.f^64") << raw("\xfa\x5f\x80\0\0") << "1.8446744073709552e+19f";
+ QTest::newRow("2.^64") << raw("\xfb\x43\xf0\0\0\0\0\0\0") << "1.8446744073709552e+19";
+
+ QTest::newRow("nan_f16") << raw("\xf9\x7e\x00") << "nan";
+ QTest::newRow("nan_f") << raw("\xfa\x7f\xc0\0\0") << "nan";
+ QTest::newRow("nan") << raw("\xfb\x7f\xf8\0\0\0\0\0\0") << "nan";
+ QTest::newRow("-inf_f16") << raw("\xf9\xfc\x00") << "-inf";
+ QTest::newRow("-inf_f") << raw("\xfa\xff\x80\0\0") << "-inf";
+ QTest::newRow("-inf") << raw("\xfb\xff\xf0\0\0\0\0\0\0") << "-inf";
+ QTest::newRow("+inf_f16") << raw("\xf9\x7c\x00") << "inf";
+ QTest::newRow("+inf_f") << raw("\xfa\x7f\x80\0\0") << "inf";
+ QTest::newRow("+inf") << raw("\xfb\x7f\xf0\0\0\0\0\0\0") << "inf";
+
+}
+
+void addNonChunkedStringsData()
+{
+ // byte strings
+ QTest::newRow("emptybytestring") << raw("\x40") << "h''";
+ QTest::newRow("bytestring1") << raw("\x41 ") << "h'20'";
+ QTest::newRow("bytestring1-nul") << raw("\x41\0") << "h'00'";
+ QTest::newRow("bytestring5") << raw("\x45Hello") << "h'48656c6c6f'";
+ QTest::newRow("bytestring24") << raw("\x58\x18""123456789012345678901234")
+ << "h'313233343536373839303132333435363738393031323334'";
+ QTest::newRow("bytestring256") << raw("\x59\1\0") + QByteArray(256, '3')
+ << "h'" + QString(256 * 2, '3') + '\'';
+
+ // text strings
+ QTest::newRow("emptytextstring") << raw("\x60") << "\"\"";
+ QTest::newRow("textstring1") << raw("\x61 ") << "\" \"";
+ QTest::newRow("textstring1-nul") << raw("\x61\0") << "\"\\u0000\"";
+ QTest::newRow("textstring5") << raw("\x65Hello") << "\"Hello\"";
+ QTest::newRow("textstring24") << raw("\x78\x18""123456789012345678901234")
+ << "\"123456789012345678901234\"";
+ QTest::newRow("textstring256") << raw("\x79\1\0") + QByteArray(256, '3')
+ << '"' + QString(256, '3') + '"';
+
+ // some strings with UTF-8 content
+ // we had a bug in the pretty dumper - see issue #54
+ QTest::newRow("textstringutf8-2char") << raw("\x62\xc2\xa0") << "\"\\u00A0\"";
+ QTest::newRow("textstringutf8-2char2") << raw("\x64\xc2\xa0\xc2\xa9") << "\"\\u00A0\\u00A9\"";
+ QTest::newRow("textstringutf8-3char") << raw("\x63\xe2\x88\x80") << "\"\\u2200\"";
+ QTest::newRow("textstringutf8-4char") << raw("\x64\xf0\x90\x88\x83") << "\"\\uD800\\uDE03\"";
+
+ // strings with overlong length
+ QTest::newRow("emptybytestring*1") << raw("\x58\x00") << "h''_0";
+ QTest::newRow("emptytextstring*1") << raw("\x78\x00") << "\"\"_0";
+ QTest::newRow("emptybytestring*2") << raw("\x59\x00\x00") << "h''_1";
+ QTest::newRow("emptytextstring*2") << raw("\x79\x00\x00") << "\"\"_1";
+ QTest::newRow("emptybytestring*4") << raw("\x5a\0\0\0\0") << "h''_2";
+ QTest::newRow("emptytextstring*4") << raw("\x7a\0\0\0\0") << "\"\"_2";
+ QTest::newRow("emptybytestring*8") << raw("\x5b\0\0\0\0\0\0\0\0") << "h''_3";
+ QTest::newRow("emptytextstring*8") << raw("\x7b\0\0\0\0\0\0\0\0") << "\"\"_3";
+ QTest::newRow("bytestring5*1") << raw("\x58\x05Hello") << "h'48656c6c6f'_0";
+ QTest::newRow("textstring5*1") << raw("\x78\x05Hello") << "\"Hello\"_0";
+ QTest::newRow("bytestring5*2") << raw("\x59\0\5Hello") << "h'48656c6c6f'_1";
+ QTest::newRow("textstring5*2") << raw("\x79\0\x05Hello") << "\"Hello\"_1";
+ QTest::newRow("bytestring5*4") << raw("\x5a\0\0\0\5Hello") << "h'48656c6c6f'_2";
+ QTest::newRow("textstring5*4") << raw("\x7a\0\0\0\x05Hello") << "\"Hello\"_2";
+ QTest::newRow("bytestring5*8") << raw("\x5b\0\0\0\0\0\0\0\5Hello") << "h'48656c6c6f'_3";
+ QTest::newRow("textstring5*8") << raw("\x7b\0\0\0\0\0\0\0\x05Hello") << "\"Hello\"_3";
+
+}
+
+void addStringsData()
+{
+ addNonChunkedStringsData();
+
+ // strings with undefined length
+ QTest::newRow("_emptybytestring") << raw("\x5f\xff") << "(_ )";
+ QTest::newRow("_emptytextstring") << raw("\x7f\xff") << "(_ )";
+ QTest::newRow("_emptybytestring2") << raw("\x5f\x40\xff") << "(_ h'')";
+ QTest::newRow("_emptytextstring2") << raw("\x7f\x60\xff") << "(_ \"\")";
+ QTest::newRow("_emptybytestring2*1") << raw("\x5f\x58\x00\xff") << "(_ h''_0)";
+ QTest::newRow("_emptytextstring2*1") << raw("\x7f\x78\x00\xff") << "(_ \"\"_0)";
+ QTest::newRow("_emptybytestring3") << raw("\x5f\x40\x40\xff") << "(_ h'', h'')";
+ QTest::newRow("_emptytextstring3") << raw("\x7f\x60\x60\xff") << "(_ \"\", \"\")";
+ QTest::newRow("_emptybytestring3*2") << raw("\x5f\x59\x00\x00\x40\xff") << "(_ h''_1, h'')";
+ QTest::newRow("_emptytextstring3*2") << raw("\x7f\x79\x00\x00\x60\xff") << "(_ \"\"_1, \"\")";
+ QTest::newRow("_bytestring5x2") << raw("\x5f\x43Hel\x42lo\xff") << "(_ h'48656c', h'6c6f')";
+ QTest::newRow("_textstring5x2") << raw("\x7f\x63Hel\x62lo\xff") << "(_ \"Hel\", \"lo\")";
+ QTest::newRow("_bytestring5x2*8*4") << raw("\x5f\x5b\0\0\0\0\0\0\0\3Hel\x5a\0\0\0\2lo\xff") << "(_ h'48656c'_3, h'6c6f'_2)";
+ QTest::newRow("_textstring5x2*8*4") << raw("\x7f\x7b\0\0\0\0\0\0\0\3Hel\x7a\0\0\0\2lo\xff") << "(_ \"Hel\"_3, \"lo\"_2)";
+ QTest::newRow("_bytestring5x5") << raw("\x5f\x41H\x41""e\x41l\x41l\x41o\xff") << "(_ h'48', h'65', h'6c', h'6c', h'6f')";
+ QTest::newRow("_textstring5x5") << raw("\x7f\x61H\x61""e\x61l\x61l\x61o\xff") << "(_ \"H\", \"e\", \"l\", \"l\", \"o\")";
+ QTest::newRow("_bytestring5x6") << raw("\x5f\x41H\x41""e\x40\x41l\x41l\x41o\xff") << "(_ h'48', h'65', h'', h'6c', h'6c', h'6f')";
+ QTest::newRow("_textstring5x6") << raw("\x7f\x61H\x61""e\x61l\x60\x61l\x61o\xff") << "(_ \"H\", \"e\", \"l\", \"\", \"l\", \"o\")";
+}
+
+void addTagsData()
+{
+ // since parseOne() works recursively for tags, we can't test lone tags
+ QTest::newRow("tag0") << raw("\xc0\x00") << "0(0)";
+ QTest::newRow("tag1") << raw("\xc1\x00") << "1(0)";
+ QTest::newRow("tag24") << raw("\xd8\x18\x00") << "24(0)";
+ QTest::newRow("tag255") << raw("\xd8\xff\x00") << "255(0)";
+ QTest::newRow("tag256") << raw("\xd9\1\0\x00") << "256(0)";
+ QTest::newRow("tag65535") << raw("\xd9\xff\xff\x00") << "65535(0)";
+ QTest::newRow("tag65536") << raw("\xda\0\1\0\0\x00") << "65536(0)";
+ QTest::newRow("tagUINT32_MAX-1") << raw("\xda\xff\xff\xff\xff\x00") << "4294967295(0)";
+ QTest::newRow("tagUINT32_MAX") << raw("\xdb\0\0\0\1\0\0\0\0\x00") << "4294967296(0)";
+ QTest::newRow("tagUINT64_MAX") << raw("\xdb" "\xff\xff\xff\xff" "\xff\xff\xff\xff" "\x00")
+ << QString::number(std::numeric_limits<uint64_t>::max()) + "(0)";
+
+ // overlong tags
+ QTest::newRow("tag0*1") << raw("\xd8\0\x00") << "0_0(0)";
+ QTest::newRow("tag0*2") << raw("\xd9\0\0\x00") << "0_1(0)";
+ QTest::newRow("tag0*4") << raw("\xda\0\0\0\0\x00") << "0_2(0)";
+ QTest::newRow("tag0*8") << raw("\xdb\0\0\0\0\0\0\0\0\x00") << "0_3(0)";
+
+ // tag other things
+ QTest::newRow("unixtime") << raw("\xc1\x1a\x55\x4b\xbf\xd3") << "1(1431027667)";
+ QTest::newRow("rfc3339date") << raw("\xc0\x78\x19" "2015-05-07 12:41:07-07:00")
+ << "0(\"2015-05-07 12:41:07-07:00\")";
+ QTest::newRow("tag6+false") << raw("\xc6\xf4") << "6(false)";
+ QTest::newRow("tag25+true") << raw("\xd8\x19\xf5") << "25(true)";
+ QTest::newRow("tag256+null") << raw("\xd9\1\0\xf6") << "256(null)";
+ QTest::newRow("tag65536+simple32") << raw("\xda\0\1\0\0\xf8\x20") << "65536(simple(32))";
+ QTest::newRow("float+unixtime") << raw("\xc1\xfa\x4e\xaa\x97\x80") << "1(1431027712.f)";
+ QTest::newRow("double+unixtime") << raw("\xc1\xfb" "\x41\xd5\x52\xef" "\xf4\xc7\xce\xfe")
+ << "1(1431027667.1220088)";
+}
+
+void addEmptyContainersData()
+{
+ QTest::newRow("emptyarray") << raw("\x80") << "[]" << 0;
+ QTest::newRow("emptymap") << raw("\xa0") << "{}" << 0;
+ QTest::newRow("_emptyarray") << raw("\x9f\xff") << "[_ ]" << -1;
+ QTest::newRow("_emptymap") << raw("\xbf\xff") << "{_ }" << -1;
+}
+
+void addMapMixedData()
+{
+ QTest::newRow("map-0-24") << raw("\xa1\0\x18\x18") << "{0: 24}" << 1;
+ QTest::newRow("map-0*1-24") << raw("\xa1\x18\0\x18\x18") << "{0_0: 24}" << 1;
+ QTest::newRow("map-0*1-24*2") << raw("\xa1\x18\0\x19\0\x18") << "{0_0: 24_1}" << 1;
+ QTest::newRow("map-0*4-24*2") << raw("\xa1\x1a\0\0\0\0\x19\0\x18") << "{0_2: 24_1}" << 1;
+ QTest::newRow("map-24-0") << raw("\xa1\x18\x18\0") << "{24: 0}" << 1;
+ QTest::newRow("map-24-0*1") << raw("\xa1\x18\x18\x18\0") << "{24: 0_0}" << 1;
+ QTest::newRow("map-255-65535") << raw("\xa1\x18\xff\x19\xff\xff") << "{255: 65535}" << 1;
+
+ QTest::newRow("_map-0-24") << raw("\xbf\0\x18\x18\xff") << "{_ 0: 24}" << 1;
+ QTest::newRow("_map-0*1-24") << raw("\xbf\x18\0\x18\x18\xff") << "{_ 0_0: 24}" << 1;
+ QTest::newRow("_map-0*1-24*2") << raw("\xbf\x18\0\x19\0\x18\xff") << "{_ 0_0: 24_1}" << 1;
+ QTest::newRow("_map-0*4-24*2") << raw("\xbf\x1a\0\0\0\0\x19\0\x18\xff") << "{_ 0_2: 24_1}" << 1;
+ QTest::newRow("_map-24-0") << raw("\xbf\x18\x18\0\xff") << "{_ 24: 0}" << 1;
+ QTest::newRow("_map-24-0*1") << raw("\xbf\x18\x18\x18\0\xff") << "{_ 24: 0_0}" << 1;
+ QTest::newRow("_map-255-65535") << raw("\xbf\x18\xff\x19\xff\xff\xff") << "{_ 255: 65535}" << 1;
+}
+
+void addChunkedStringData()
+{
+ QTest::addColumn<QByteArray>("data");
+ QTest::addColumn<QString>("concatenated");
+ QTest::addColumn<QStringList>("chunks");
+
+ // non-chunked:
+ QTest::newRow("emptybytestring") << raw("\x40") << "h''" << QStringList{"h''"};
+ QTest::newRow("bytestring1") << raw("\x41 ") << "h'20'" << QStringList{"h'20'"};
+ QTest::newRow("emptytextstring") << raw("\x60") << "\"\"" << QStringList{"\"\""};
+ QTest::newRow("textstring1") << raw("\x61 ") << "\" \"" << QStringList{"\" \""};
+
+ // empty chunked:
+ QTest::newRow("_emptybytestring") << raw("\x5f\xff") << "h''" << QStringList{};
+ QTest::newRow("_emptytextstring") << raw("\x7f\xff") << "\"\"" << QStringList{};
+ QTest::newRow("_emptybytestring2") << raw("\x5f\x40\xff") << "h''" << QStringList{"h''"};
+ QTest::newRow("_emptytextstring2") << raw("\x7f\x60\xff") << "\"\"" << QStringList{"\"\""};
+ QTest::newRow("_emptybytestring3") << raw("\x5f\x40\x40\xff") << "h''" << QStringList{"h''", "h''"};
+ QTest::newRow("_emptytextstring3") << raw("\x7f\x60\x60\xff") << "\"\"" << QStringList{"\"\"", "\"\""};
+
+ // regular chunks
+ QTest::newRow("_bytestring1") << raw("\x5f\x41 \xff") << "h'20'" << QStringList{"h'20'"};
+ QTest::newRow("_bytestring2") << raw("\x5f\x41 \x41z\xff") << "h'207a'" << QStringList{"h'20'", "h'7a'"};
+ QTest::newRow("_bytestring3") << raw("\x5f\x41 \x58\x18""123456789012345678901234\x41z\xff")
+ << "h'203132333435363738393031323334353637383930313233347a'"
+ << QStringList{"h'20'", "h'313233343536373839303132333435363738393031323334'", "h'7a'"};
+
+ QTest::newRow("_textstring1") << raw("\x7f\x61 \xff") << "\" \"" << QStringList{"\" \""};
+ QTest::newRow("_textstring2") << raw("\x7f\x61 \x61z\xff") << "\" z\"" << QStringList{"\" \"", "\"z\""};
+ QTest::newRow("_textstring3") << raw("\x7f\x61 \x78\x18""123456789012345678901234\x61z\xff")
+ << "\" 123456789012345678901234z\""
+ << QStringList{"\" \"", "\"123456789012345678901234\"", "\"z\""};
+}
+
+void addValidationColumns()
+{
+ QTest::addColumn<QByteArray>("data");
+ QTest::addColumn<int>("flags"); // future
+ QTest::addColumn<CborError>("expectedError");
+}
+
+void addValidationData()
+{
+ // illegal numbers are future extension points
+ QTest::newRow("illegal-number-in-unsigned-1") << raw("\x81\x1c") << 0 << CborErrorIllegalNumber;
+ QTest::newRow("illegal-number-in-unsigned-2") << raw("\x81\x1d") << 0 << CborErrorIllegalNumber;
+ QTest::newRow("illegal-number-in-unsigned-3") << raw("\x81\x1e") << 0 << CborErrorIllegalNumber;
+ QTest::newRow("illegal-number-in-unsigned-4") << raw("\x81\x1f") << 0 << CborErrorIllegalNumber;
+ QTest::newRow("illegal-number-in-negative-1") << raw("\x81\x3c") << 0 << CborErrorIllegalNumber;
+ QTest::newRow("illegal-number-in-negative-2") << raw("\x81\x3d") << 0 << CborErrorIllegalNumber;
+ QTest::newRow("illegal-number-in-negative-3") << raw("\x81\x3e") << 0 << CborErrorIllegalNumber;
+ QTest::newRow("illegal-number-in-negative-4") << raw("\x81\x3f") << 0 << CborErrorIllegalNumber;
+ QTest::newRow("illegal-number-in-bytearray-length-1") << raw("\x81\x5c") << 0 << CborErrorIllegalNumber;
+ QTest::newRow("illegal-number-in-bytearray-length-2") << raw("\x81\x5d") << 0 << CborErrorIllegalNumber;
+ QTest::newRow("illegal-number-in-bytearray-length-3") << raw("\x81\x5e") << 0 << CborErrorIllegalNumber;
+ QTest::newRow("illegal-number-in-string-length-1") << raw("\x81\x7c") << 0 << CborErrorIllegalNumber;
+ QTest::newRow("illegal-number-in-string-length-2") << raw("\x81\x7d") << 0 << CborErrorIllegalNumber;
+ QTest::newRow("illegal-number-in-string-length-3") << raw("\x81\x7e") << 0 << CborErrorIllegalNumber;
+ QTest::newRow("illegal-number-in-array-length-1") << raw("\x81\x9c") << 0 << CborErrorIllegalNumber;
+ QTest::newRow("illegal-number-in-array-length-2") << raw("\x81\x9d") << 0 << CborErrorIllegalNumber;
+ QTest::newRow("illegal-number-in-array-length-3") << raw("\x81\x9e") << 0 << CborErrorIllegalNumber;
+ QTest::newRow("illegal-number-in-map-length-1") << raw("\x81\xbc") << 0 << CborErrorIllegalNumber;
+ QTest::newRow("illegal-number-in-map-length-2") << raw("\x81\xbd") << 0 << CborErrorIllegalNumber;
+ QTest::newRow("illegal-number-in-map-length-3") << raw("\x81\xbe") << 0 << CborErrorIllegalNumber;
+ QTest::newRow("illegal-number-in-tag-1") << raw("\x81\xdc") << 0 << CborErrorIllegalNumber;
+ QTest::newRow("illegal-number-in-tag-2") << raw("\x81\xdd") << 0 << CborErrorIllegalNumber;
+ QTest::newRow("illegal-number-in-tag-3") << raw("\x81\xde") << 0 << CborErrorIllegalNumber;
+ QTest::newRow("illegal-number-in-tag-4") << raw("\x81\xdf") << 0 << CborErrorIllegalNumber;
+
+ QTest::newRow("unsigned-too-short-1-0") << raw("\x81\x18") << 0 << CborErrorUnexpectedEOF; // requires 1 byte, 0 given
+ QTest::newRow("unsigned-too-short-2-0") << raw("\x81\x19") << 0 << CborErrorUnexpectedEOF; // requires 2 bytes, 0 given
+ QTest::newRow("unsigned-too-short-2-1") << raw("\x81\x19\x01") << 0 << CborErrorUnexpectedEOF; // etc
+ QTest::newRow("unsigned-too-short-4-0") << raw("\x81\x1a") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("unsigned-too-short-4-3") << raw("\x81\x1a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("unsigned-too-short-8-0") << raw("\x81\x1b") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("unsigned-too-short-8-7") << raw("\x81\x1b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("negative-length-too-short-1-0") << raw("\x81\x38") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("negative-length-too-short-2-0") << raw("\x81\x39") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("negative-length-too-short-2-1") << raw("\x81\x39\x01") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("negative-length-too-short-4-0") << raw("\x81\x3a") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("negative-length-too-short-4-3") << raw("\x81\x3a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("negative-length-too-short-8-0") << raw("\x81\x3b") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("negative-length-too-short-8-7") << raw("\x81\x3b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-length-too-short-1-0") << raw("\x81\x58") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-length-too-short-2-0") << raw("\x81\x59") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-length-too-short-2-1") << raw("\x81\x59\x01") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-length-too-short-4-0") << raw("\x81\x5a") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-length-too-short-4-3") << raw("\x81\x5a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-length-too-short-8-0") << raw("\x81\x5b") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-length-too-short-8-7") << raw("\x81\x5b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-length-too-short-1-0") << raw("\x81\x78") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-length-too-short-2-0") << raw("\x81\x79") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-length-too-short-2-1") << raw("\x81\x79\x01") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-length-too-short-4-0") << raw("\x81\x7a") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-length-too-short-4-3") << raw("\x81\x7a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-length-too-short-8-0") << raw("\x81\x7b") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-length-too-short-8-7") << raw("\x81\x7b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-chunked-length-too-short-1-0") << raw("\x81\x5f\x58") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-chunked-length-too-short-2-0") << raw("\x81\x5f\x59") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-chunked-length-too-short-2-1") << raw("\x81\x5f\x59\x01") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-chunked-length-too-short-4-0") << raw("\x81\x5f\x5a") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-chunked-length-too-short-4-3") << raw("\x81\x5f\x5a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-chunked-length-too-short-8-0") << raw("\x81\x5f\x5b") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-chunked-length-too-short-8-7") << raw("\x81\x5f\x5b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-chunked-length-too-short-1-0") << raw("\x81\x7f\x78") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-chunked-length-too-short-2-0") << raw("\x81\x7f\x79") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-chunked-length-too-short-2-1") << raw("\x81\x7f\x79\x01") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-chunked-length-too-short-4-0") << raw("\x81\x7f\x7a") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-chunked-length-too-short-4-3") << raw("\x81\x7f\x7a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-chunked-length-too-short-8-0") << raw("\x81\x7f\x7b") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-chunked-length-too-short-8-7") << raw("\x81\x7f\x7b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-chunked-2-length-too-short-1-0") << raw("\x81\x5f\x40\x58") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-chunked-2-length-too-short-2-0") << raw("\x81\x5f\x40\x59") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-chunked-2-length-too-short-2-1") << raw("\x81\x5f\x40\x59\x01") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-chunked-2-length-too-short-4-0") << raw("\x81\x5f\x40\x5a") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-chunked-2-length-too-short-4-3") << raw("\x81\x5f\x40\x5a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-chunked-2-length-too-short-8-0") << raw("\x81\x5f\x40\x5b") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-chunked-2-length-too-short-8-7") << raw("\x81\x5f\x40\x5b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-chunked-2-length-too-short-1-0") << raw("\x81\x7f\x60\x78") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-chunked-2-length-too-short-2-0") << raw("\x81\x7f\x60\x79") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-chunked-2-length-too-short-2-1") << raw("\x81\x7f\x60\x79\x01") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-chunked-2-length-too-short-4-0") << raw("\x81\x7f\x60\x7a") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-chunked-2-length-too-short-4-3") << raw("\x81\x7f\x60\x7a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-chunked-2-length-too-short-8-0") << raw("\x81\x7f\x60\x7b") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-chunked-2-length-too-short-8-7") << raw("\x81\x7f\x60\x7b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("array-length-too-short-1-0") << raw("\x81\x98") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("array-length-too-short-2-0") << raw("\x81\x99") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("array-length-too-short-2-1") << raw("\x81\x99\x01") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("array-length-too-short-4-0") << raw("\x81\x9a") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("array-length-too-short-4-3") << raw("\x81\x9a\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("array-length-too-short-8-0") << raw("\x81\x9b") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("array-length-too-short-8-7") << raw("\x81\x9b\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("map-length-too-short-1-0") << raw("\x81\xb8") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("map-length-too-short-2-0") << raw("\x81\xb9") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("map-length-too-short-2-1") << raw("\x81\xb9\x01") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("map-length-too-short-4-0") << raw("\x81\xba") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("map-length-too-short-4-3") << raw("\x81\xba\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("map-length-too-short-8-0") << raw("\x81\xbb") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("map-length-too-short-8-7") << raw("\x81\xbb\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("tag-too-short-1-0") << raw("\x81\xd8") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("tag-too-short-2-0") << raw("\x81\xd9") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("tag-too-short-2-1") << raw("\x81\xd9\x01") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("tag-too-short-4-0") << raw("\x81\xda") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("tag-too-short-4-3") << raw("\x81\xda\x01\x02\x03") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("tag-too-short-8-0") << raw("\x81\xdb") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("tag-too-short-8-7") << raw("\x81\xdb\1\2\3\4\5\6\7") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("fp16-too-short1") << raw("\x81\xf9") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("fp16-too-short2") << raw("\x81\xf9\x00") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("float-too-short1") << raw("\x81\xfa") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("float-too-short2") << raw("\x81\xfa\0\0\0") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("double-too-short1") << raw("\x81\xfb") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("double-too-short2") << raw("\x81\xfb\0\0\0\0\0\0\0") << 0 << CborErrorUnexpectedEOF;
+
+ QTest::newRow("bytearray-too-short1") << raw("\x81\x42z") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-too-short2") << raw("\x81\x58\x02z") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-too-short3") << raw("\x81\x5a\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-too-short4") << raw("\x81\x5b\0\0\0\0\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-too-short1") << raw("\x81\x62z") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-too-short2") << raw("\x81\x78\x02z") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-too-short3") << raw("\x81\x7a\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-too-short4") << raw("\x81\x7b\0\0\0\0\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-chunked-too-short1") << raw("\x81\x5f\x42z") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-chunked-too-short2") << raw("\x81\x5f\x58\x02z") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-chunked-too-short3") << raw("\x81\x5f\x5a\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-chunked-too-short4") << raw("\x81\x5f\x5b\0\0\0\0\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-chunked-too-short1") << raw("\x81\x7f\x62z") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-chunked-too-short2") << raw("\x81\x7f\x78\x02z") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-chunked-too-short3") << raw("\x81\x7f\x7a\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-chunked-too-short4") << raw("\x81\x7f\x7b\0\0\0\0\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-chunked-too-short1x2") << raw("\x81\x5f\x40\x42z") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-chunked-too-short2x2") << raw("\x81\x5f\x40\x58\x02z") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-chunked-too-short3x2") << raw("\x81\x5f\x40\x5a\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-chunked-too-short4x2") << raw("\x81\x5f\x40\x5b\0\0\0\0\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-chunked-too-short1x2") << raw("\x81\x7f\x60\x62z") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-chunked-too-short2x2") << raw("\x81\x7f\x60\x78\x02z") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-chunked-too-short3x2") << raw("\x81\x7f\x60\x7a\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-chunked-too-short4x2") << raw("\x81\x7f\x60\x7b\0\0\0\0\0\0\0\2z") << 0 << CborErrorUnexpectedEOF;
+
+ QTest::newRow("bytearray-no-break1") << raw("\x81\x5f") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("bytearray-no-break2") << raw("\x81\x5f\x40") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-no-break1") << raw("\x81\x7f") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-no-break2") << raw("\x81\x7f\x60") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("array-no-break1") << raw("\x81\x9f") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("array-no-break2") << raw("\x81\x9f\0") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("map-no-break1") << raw("\x81\xbf") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("map-no-break2") << raw("\x81\xbf\0\0") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("map-break-after-key") << raw("\x81\xbf\0\xff") << 0 << CborErrorUnexpectedBreak;
+ QTest::newRow("map-break-after-value-tag") << raw("\x81\xbf\0\xc0\xff") << 0 << CborErrorUnexpectedBreak;
+ QTest::newRow("map-break-after-value-tag2") << raw("\x81\xbf\0\xd8\x20\xff") << 0 << CborErrorUnexpectedBreak;
+
+ // check for pointer additions wrapping over the limit of the address space
+ CborError tooLargeOn32bit = (sizeof(void *) == 4) ? CborErrorDataTooLarge : CborErrorUnexpectedEOF;
+ // on 32-bit systems, this is a -1
+ QTest::newRow("bytearray-wraparound1") << raw("\x81\x5a\xff\xff\xff\xff") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-wraparound1") << raw("\x81\x7a\xff\xff\xff\xff") << 0 << CborErrorUnexpectedEOF;
+ // on 32-bit systems, a 4GB addition could be dropped
+ QTest::newRow("bytearray-wraparound2") << raw("\x81\x5b\0\0\0\1\0\0\0\0") << 0 << tooLargeOn32bit;
+ QTest::newRow("string-wraparound2") << raw("\x81\x7b\0\0\0\1\0\0\0\0") << 0 << tooLargeOn32bit;
+ // on 64-bit systems, this could be a -1
+ QTest::newRow("bytearray-wraparound3") << raw("\x81\x5b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 << tooLargeOn32bit;
+ QTest::newRow("string-wraparound3") << raw("\x81\x7b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 << tooLargeOn32bit;
+
+ // ditto on chunks
+ QTest::newRow("bytearray-chunk-wraparound1") << raw("\x81\x5f\x5a\xff\xff\xff\xff") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("string-chunk-wraparound1") << raw("\x81\x7f\x7a\xff\xff\xff\xff") << 0 << CborErrorUnexpectedEOF;
+ // on 32-bit systems, a 4GB addition could be dropped
+ QTest::newRow("bytearray-chunk-wraparound2") << raw("\x81\x5f\x5b\0\0\0\1\0\0\0\0") << 0 << tooLargeOn32bit;
+ QTest::newRow("string-chunk-wraparound2") << raw("\x81\x7f\x7b\0\0\0\1\0\0\0\0") << 0 << tooLargeOn32bit;
+ // on 64-bit systems, this could be a -1
+ QTest::newRow("bytearray-chunk-wraparound3") << raw("\x81\x5f\x5b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 << tooLargeOn32bit;
+ QTest::newRow("string-chunk-wraparound3") << raw("\x81\x7f\x7b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 << tooLargeOn32bit;
+
+ QTest::newRow("eof-after-array") << raw("\x81") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("eof-after-array2") << raw("\x81\x78\x20") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("eof-after-array-element") << raw("\x81\x82\x01") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("eof-after-object") << raw("\x81\xa1") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("eof-after-object2") << raw("\x81\xb8\x20") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("eof-after-object-key") << raw("\x81\xa1\x01") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("eof-after-object-value") << raw("\x81\xa2\x01\x01") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("eof-after-tag") << raw("\x81\xc0") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("eof-after-tag2") << raw("\x81\xd8\x20") << 0 << CborErrorUnexpectedEOF;
+
+ // major type 7 has future types
+ QTest::newRow("future-type-28") << raw("\x81\xfc") << 0 << CborErrorUnknownType;
+ QTest::newRow("future-type-29") << raw("\x81\xfd") << 0 << CborErrorUnknownType;
+ QTest::newRow("future-type-30") << raw("\x81\xfe") << 0 << CborErrorUnknownType;
+ QTest::newRow("unexpected-break") << raw("\x81\xff") << 0 << CborErrorUnexpectedBreak;
+ QTest::newRow("illegal-simple-0") << raw("\x81\xf8\0") << 0 << CborErrorIllegalSimpleType;
+ QTest::newRow("illegal-simple-31") << raw("\x81\xf8\x1f") << 0 << CborErrorIllegalSimpleType;
+
+ // not only too big (UINT_MAX or UINT_MAX+1 in size), but also incomplete
+ if (sizeof(size_t) < sizeof(uint64_t)) {
+ QTest::newRow("bytearray-too-big1") << raw("\x81\x5b\0\0\0\1\0\0\0\0") << 0 << CborErrorDataTooLarge;
+ QTest::newRow("string-too-big1") << raw("\x81\x7b\0\0\0\1\0\0\0\0") << 0 << CborErrorDataTooLarge;
+ }
+ QTest::newRow("array-too-big1") << raw("\x81\x9a\xff\xff\xff\xff\0\0\0\0") << 0 << CborErrorDataTooLarge;
+ QTest::newRow("array-too-big2") << raw("\x81\x9b\0\0\0\1\0\0\0\0") << 0 << CborErrorDataTooLarge;
+ QTest::newRow("object-too-big1") << raw("\x81\xba\xff\xff\xff\xff\0\0\0\0") << 0 << CborErrorDataTooLarge;
+ QTest::newRow("object-too-big2") << raw("\x81\xbb\0\0\0\1\0\0\0\0") << 0 << CborErrorDataTooLarge;
+
+ QTest::newRow("no-break-for-array0") << raw("\x81\x9f") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("no-break-for-array1") << raw("\x81\x9f\x01") << 0 << CborErrorUnexpectedEOF;
+
+ QTest::newRow("no-break-string0") << raw("\x81\x7f") << 0 << CborErrorUnexpectedEOF;
+ QTest::newRow("no-break-string1") << raw("\x81\x7f\x61Z") << 0 << CborErrorUnexpectedEOF;
+
+ QTest::newRow("nested-indefinite-length-bytearrays") << raw("\x81\x5f\x5f\xff\xff") << 0 << CborErrorIllegalNumber;
+ QTest::newRow("nested-indefinite-length-strings") << raw("\x81\x7f\x7f\xff\xff") << 0 << CborErrorIllegalNumber;
+
+ QTest::newRow("string-chunk-unsigned") << raw("\x81\x7f\0\xff") << 0 << CborErrorIllegalType;
+ QTest::newRow("string-chunk-negative") << raw("\x81\x7f\x20\xff") << 0 << CborErrorIllegalType;
+ QTest::newRow("string-chunk-bytearray") << raw("\x81\x7f\x40\xff") << 0 << CborErrorIllegalType;
+ QTest::newRow("string-chunk-array") << raw("\x81\x7f\x80\xff") << 0 << CborErrorIllegalType;
+ QTest::newRow("string-chunk-map") << raw("\x81\x7f\xa0\xff") << 0 << CborErrorIllegalType;
+ QTest::newRow("string-chunk-tag") << raw("\x81\x7f\xc0\xff") << 0 << CborErrorIllegalType;
+ QTest::newRow("string-chunk-tagged-string") << raw("\x81\x7f\xc0\x60\xff") << 0 << CborErrorIllegalType;
+ QTest::newRow("string-chunk-simple0") << raw("\x81\x7f\xe0\xff") << 0 << CborErrorIllegalType;
+ QTest::newRow("string-chunk-false") << raw("\x81\x7f\xf4\xff") << 0 << CborErrorIllegalType;
+ QTest::newRow("string-chunk-true") << raw("\x81\x7f\xf5\xff") << 0 << CborErrorIllegalType;
+ QTest::newRow("string-chunk-null") << raw("\x81\x7f\xf6\xff") << 0 << CborErrorIllegalType;
+ QTest::newRow("string-chunk-undefined") << raw("\x81\x7f\xf7\xff") << 0 << CborErrorIllegalType;
+
+ QTest::newRow("bytearray-chunk-string") << raw("\x81\x5f\x60\xff") << 0 << CborErrorIllegalType;
+ QTest::newRow("bytearray-chunk-tagged-bytearray") << raw("\x81\x7f\xc0\x40\xff") << 0 << CborErrorIllegalType;
+
+ // RFC 7049 Section 2.2.2 "Indefinite-Length Byte Strings and Text Strings" says
+ // Text strings with indefinite lengths act the same as byte strings
+ // with indefinite lengths, except that all their chunks MUST be
+ // definite-length text strings. Note that this implies that the bytes
+ // of a single UTF-8 character cannot be spread between chunks: a new
+ // chunk can only be started at a character boundary.
+ // This test technically tests the dumper, not the parser.
+ QTest::newRow("string-utf8-chunk-split") << raw("\x81\x7f\x61\xc2\x61\xa0\xff") << 0 << CborErrorInvalidUtf8TextString;
+}
diff --git a/src/3rdparty/tinycbor/tests/parser/parser.pro b/src/3rdparty/tinycbor/tests/parser/parser.pro
new file mode 100644
index 0000000000..a61291a9e4
--- /dev/null
+++ b/src/3rdparty/tinycbor/tests/parser/parser.pro
@@ -0,0 +1,10 @@
+SOURCES += tst_parser.cpp ../../src/cborparser.c
+
+CONFIG += testcase parallel_test c++11
+QT = core testlib
+DEFINES += CBOR_PARSER_MAX_RECURSIONS=16
+
+INCLUDEPATH += ../../src
+msvc: POST_TARGETDEPS = ../../lib/tinycbor.lib
+else: POST_TARGETDEPS += ../../lib/libtinycbor.a
+LIBS += $$POST_TARGETDEPS
diff --git a/src/3rdparty/tinycbor/tests/parser/tst_parser.cpp b/src/3rdparty/tinycbor/tests/parser/tst_parser.cpp
new file mode 100644
index 0000000000..74c480bc51
--- /dev/null
+++ b/src/3rdparty/tinycbor/tests/parser/tst_parser.cpp
@@ -0,0 +1,1667 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Intel Corporation
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and associated documentation files (the "Software"), to deal
+** in the Software without restriction, including without limitation the rights
+** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+** copies of the Software, and to permit persons to whom the Software is
+** furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+** THE SOFTWARE.
+**
+****************************************************************************/
+
+#define _XOPEN_SOURCE 700
+#include <QtTest>
+#include "cbor.h"
+#include <stdio.h>
+#include <stdarg.h>
+
+namespace QTest {
+template<> char *toString<CborError>(const CborError &err)
+{
+ return qstrdup(cbor_error_string(err));
+}
+}
+
+class tst_Parser : public QObject
+{
+ Q_OBJECT
+private slots:
+ void initParserEmpty();
+
+ // parsing API
+ void integers_data();
+ void integers();
+ void fixed_data();
+ void fixed();
+ void strings_data();
+ void strings() { fixed(); }
+ void tags_data();
+ void tags() { fixed(); }
+ void tagTags_data() { tags_data(); }
+ void tagTags();
+ void emptyContainers_data();
+ void emptyContainers();
+ void arrays_data();
+ void arrays();
+ void undefLengthArrays_data() { arrays_data(); }
+ void undefLengthArrays();
+ void nestedArrays_data() { arrays_data(); }
+ void nestedArrays();
+ void maps_data();
+ void maps();
+ void undefLengthMaps_data() { maps_data(); }
+ void undefLengthMaps();
+ void nestedMaps_data() { maps_data(); }
+ void nestedMaps();
+ void mapMixed_data();
+ void mapMixed() { arrays(); }
+ void mapsAndArrays_data() { arrays_data(); }
+ void mapsAndArrays();
+
+ void readerApi_data() { arrays_data(); }
+ void readerApi();
+ void reparse_data();
+ void reparse();
+
+ // chunked string API
+ void chunkedString_data();
+ void chunkedString();
+ void chunkedStringInUndefArray_data() { chunkedString_data(); }
+ void chunkedStringInUndefArray();
+
+ // convenience API
+ void stringLength_data();
+ void stringLength();
+ void stringCompare_data();
+ void stringCompare();
+ void mapFind_data();
+ void mapFind();
+
+ // validation & errors
+ void checkedIntegers_data();
+ void checkedIntegers();
+ void validation_data();
+ void validation();
+ void strictValidation_data();
+ void strictValidation();
+ void incompleteData_data();
+ void incompleteData();
+ void endPointer_data();
+ void endPointer();
+ void recursionLimit_data();
+ void recursionLimit();
+};
+
+static CborError qstring_printf(void *out, const char *fmt, ...)
+{
+ auto str = static_cast<QString *>(out);
+ va_list va;
+ va_start(va, fmt);
+ *str += QString::vasprintf(fmt, va);
+ va_end(va);
+ return CborNoError;
+};
+
+CborError parseOne(CborValue *it, QString *parsed)
+{
+ int flags = CborPrettyShowStringFragments | CborPrettyIndicateIndeterminateLength |
+ CborPrettyIndicateOverlongNumbers;
+
+ parsed->clear();
+ return cbor_value_to_pretty_stream(qstring_printf, parsed, it, flags);
+}
+
+CborError parseOneChunk(CborValue *it, QString *parsed)
+{
+ CborError err;
+ CborType ourType = cbor_value_get_type(it);
+ if (ourType == CborByteStringType) {
+ const uint8_t *bytes;
+ size_t len;
+ err = cbor_value_get_byte_string_chunk(it, &bytes, &len, it);
+ if (err)
+ return err;
+
+ if (bytes)
+ *parsed = QString::fromLatin1("h'" +
+ QByteArray::fromRawData(reinterpret_cast<const char *>(bytes), len).toHex() +
+ '\'');
+ } else if (ourType == CborTextStringType) {
+ const char *text;
+ size_t len;
+ err = cbor_value_get_text_string_chunk(it, &text, &len, it);
+ if (err)
+ return err;
+
+ if (text)
+ *parsed = '"' + QString::fromUtf8(text, len) + '"';
+ } else {
+ Q_ASSERT(false);
+ }
+ return err;
+}
+
+void tst_Parser::initParserEmpty()
+{
+ CborParser parser;
+ CborValue first;
+ CborError err = cbor_parser_init((const quint8 *)"", 0, 0, &parser, &first);
+ QCOMPARE(err, CborErrorUnexpectedEOF);
+}
+
+bool compareFailed = true;
+void compareOne_real(const QByteArray &data, const QString &expected, int line, int n = -1)
+{
+ compareFailed = true;
+ CborParser parser;
+ CborValue first;
+ CborError err = cbor_parser_init(reinterpret_cast<const quint8 *>(data.constData()), data.length(), 0, &parser, &first);
+ QVERIFY2(!err, QByteArray::number(line) + ": Got error \"" + cbor_error_string(err) + "\"");
+
+ if (cbor_value_get_type(&first) == CborArrayType) {
+ size_t len;
+ if (n >= 0) {
+ QVERIFY(cbor_value_is_length_known(&first));
+ QCOMPARE(cbor_value_get_array_length(&first, &len), CborNoError);
+ QCOMPARE(len, size_t(len));
+ } else {
+ QVERIFY(!cbor_value_is_length_known(&first));
+ QCOMPARE(cbor_value_get_array_length(&first, &len), CborErrorUnknownLength);
+ }
+ } else if (cbor_value_get_type(&first) == CborMapType) {
+ size_t len;
+ if (n >= 0) {
+ QVERIFY(cbor_value_is_length_known(&first));
+ QCOMPARE(cbor_value_get_map_length(&first, &len), CborNoError);
+ QCOMPARE(len, size_t(len));
+ } else {
+ QVERIFY(!cbor_value_is_length_known(&first));
+ QCOMPARE(cbor_value_get_map_length(&first, &len), CborErrorUnknownLength);
+ }
+ } else if (cbor_value_is_text_string(&first) || cbor_value_is_byte_string(&first)) {
+ size_t len;
+ QCOMPARE(cbor_value_calculate_string_length(&first, &len), CborNoError);
+ if (cbor_value_is_length_known(&first)) {
+ size_t len2;
+ QCOMPARE(cbor_value_get_string_length(&first, &len2), CborNoError);
+ QCOMPARE(len2, len);
+ } else {
+ QCOMPARE(cbor_value_get_string_length(&first, &len), CborErrorUnknownLength);
+ }
+ }
+
+ CborError err2 = cbor_value_validate_basic(&first);
+
+ QString decoded;
+ err = parseOne(&first, &decoded);
+ QVERIFY2(!err, QByteArray::number(line) + ": Got error \"" + cbor_error_string(err) +
+ "\"; decoded stream:\n" + decoded.toLatin1());
+ QCOMPARE(decoded, expected);
+
+ // check that the errors are the same
+ QCOMPARE(err2, err);
+
+ // check that we consumed everything
+ QCOMPARE((void*)cbor_value_get_next_byte(&first), (void*)data.constEnd());
+
+ compareFailed = false;
+}
+#define compareOne(data, expected) compareOne_real(data, expected, __LINE__)
+#define compareOneSize(n, data, expected) compareOne_real(data, expected, __LINE__, n)
+
+#include "data.cpp"
+
+void tst_Parser::integers_data()
+{
+ addIntegers();
+}
+
+void tst_Parser::integers()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(bool, isNegative);
+ QFETCH(quint64, expectedRaw);
+ QFETCH(qint64, expectedValue);
+ QFETCH(bool, inInt64Range);
+
+ CborParser parser;
+ CborValue first;
+ CborError err = cbor_parser_init(reinterpret_cast<const quint8 *>(data.constData()), data.length(), 0, &parser, &first);
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+ QVERIFY(cbor_value_is_integer(&first));
+
+ uint64_t raw;
+ cbor_value_get_raw_integer(&first, &raw);
+ QCOMPARE(quint64(raw), expectedRaw);
+
+ if (isNegative) {
+ QVERIFY(cbor_value_is_negative_integer(&first));
+ QVERIFY(!cbor_value_is_unsigned_integer(&first));
+ } else {
+ QVERIFY(!cbor_value_is_negative_integer(&first));
+ QVERIFY(cbor_value_is_unsigned_integer(&first));
+ }
+
+ int64_t value;
+ if (inInt64Range) {
+ cbor_value_get_int64(&first, &value);
+ QCOMPARE(qint64(value), expectedValue);
+ }
+
+ err = cbor_value_get_int64_checked(&first, &value);
+ QCOMPARE(err, inInt64Range ? CborNoError : CborErrorDataTooLarge);
+
+ int ivalue;
+ bool inIntRange = inInt64Range && (expectedValue == int(expectedValue));
+ err = cbor_value_get_int_checked(&first, &ivalue);
+ QCOMPARE(err, inIntRange ? CborNoError : CborErrorDataTooLarge);
+}
+
+void tst_Parser::fixed_data()
+{
+ addColumns();
+ addFixedData();
+}
+
+void tst_Parser::fixed()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+
+ compareOne(data, expected);
+}
+
+void tst_Parser::strings_data()
+{
+ addColumns();
+ addStringsData();
+}
+
+void tst_Parser::tags_data()
+{
+ addColumns();
+ addTagsData();
+}
+
+void tst_Parser::tagTags()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+
+ compareOne("\xd9\xd9\xf7" + data, "55799(" + expected + ')');
+ if (!compareFailed)
+ compareOne("\xd9\xd9\xf7" "\xd9\xd9\xf7" + data, "55799(55799(" + expected + "))");
+}
+
+void tst_Parser::emptyContainers_data()
+{
+ addColumns();
+ addEmptyContainersData();
+}
+
+void tst_Parser::emptyContainers()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+ QFETCH(int, n);
+
+ compareOneSize(n, data, expected);
+}
+
+void tst_Parser::arrays_data()
+{
+ addColumns();
+ addFixedData();
+ addStringsData();
+ addTagsData();
+}
+
+void tst_Parser::arrays()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+
+ compareOneSize(1, "\x81" + data, '[' + expected + ']');
+ if (compareFailed) return;
+
+ compareOneSize(2, "\x82" + data + data, '[' + expected + ", " + expected + ']');
+ if (compareFailed) return;
+
+ // overlong length
+ compareOneSize(1, "\x98\1" + data, "[_0 " + expected + ']');
+ if (compareFailed) return;
+ compareOneSize(1, raw("\x99\0\1") + data, "[_1 " + expected + ']');
+ if (compareFailed) return;
+ compareOneSize(1, raw("\x9a\0\0\0\1") + data, "[_2 " + expected + ']');
+ if (compareFailed) return;
+ compareOneSize(1, raw("\x9b\0\0\0\0\0\0\0\1") + data, "[_3 " + expected + ']');
+ if (compareFailed) return;
+
+ // medium-sized array: 32 elements (1 << 5)
+ expected += ", ";
+ for (int i = 0; i < 5; ++i) {
+ data += data;
+ expected += expected;
+ }
+ expected.chop(2); // remove the last ", "
+ compareOneSize(32, "\x98\x20" + data, '[' + expected + ']');
+ if (compareFailed) return;
+
+ // large array: 256 elements (32 << 3)
+ expected += ", ";
+ for (int i = 0; i < 3; ++i) {
+ data += data;
+ expected += expected;
+ }
+ expected.chop(2); // remove the last ", "
+ compareOneSize(256, raw("\x99\1\0") + data, '[' + expected + ']');
+ if (compareFailed) return;
+}
+
+void tst_Parser::undefLengthArrays()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+
+ compareOne("\x9f" + data + "\xff", "[_ " + expected + ']');
+ if (compareFailed) return;
+
+ compareOne("\x9f" + data + data + "\xff", "[_ " + expected + ", " + expected + ']');
+}
+
+void tst_Parser::nestedArrays()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+
+ compareOneSize(1, "\x81\x81" + data, "[[" + expected + "]]");
+ if (compareFailed) return;
+
+ compareOneSize(1, "\x81\x81\x81" + data, "[[[" + expected + "]]]");
+ if (compareFailed) return;
+
+ compareOneSize(1, "\x81\x82" + data + data, "[[" + expected + ", " + expected + "]]");
+ if (compareFailed) return;
+
+ compareOneSize(2, "\x82\x81" + data + data, "[[" + expected + "], " + expected + "]");
+ if (compareFailed) return;
+
+ compareOneSize(2, "\x82\x81" + data + '\x81' + data, "[[" + expected + "], [" + expected + "]]");
+ if (compareFailed) return;
+
+ // undefined length
+ compareOneSize(-1, "\x9f\x9f" + data + data + "\xff\xff", "[_ [_ " + expected + ", " + expected + "]]");
+ if (compareFailed) return;
+
+ compareOneSize(-1, "\x9f\x9f" + data + "\xff\x9f" + data + "\xff\xff", "[_ [_ " + expected + "], [_ " + expected + "]]");
+ if (compareFailed) return;
+
+ compareOneSize(-1, "\x9f\x9f" + data + data + "\xff\x9f" + data + "\xff\xff",
+ "[_ [_ " + expected + ", " + expected + "], [_ " + expected + "]]");
+ if (compareFailed) return;
+
+ // mix them
+ compareOneSize(1, "\x81\x9f" + data + "\xff", "[[_ " + expected + "]]");
+ if (compareFailed) return;
+
+ compareOneSize(-1, "\x9f\x81" + data + "\xff", "[_ [" + expected + "]]");
+}
+
+void tst_Parser::maps_data()
+{
+ arrays_data();
+}
+
+void tst_Parser::maps()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+
+ // integer key
+ compareOneSize(1, "\xa1\1" + data, "{1: " + expected + '}');
+ if (compareFailed) return;
+
+ // string key
+ compareOneSize(1, "\xa1\x65" "Hello" + data, "{\"Hello\": " + expected + '}');
+ if (compareFailed) return;
+
+ // map to self
+ compareOneSize(1, "\xa1" + data + data, '{' + expected + ": " + expected + '}');
+ if (compareFailed) return;
+
+ // two integer keys
+ compareOneSize(2, "\xa2\1" + data + "\2" + data, "{1: " + expected + ", 2: " + expected + '}');
+ if (compareFailed) return;
+
+ // OneSize integer and OneSize string key
+ compareOneSize(2, "\xa2\1" + data + "\x65" "Hello" + data, "{1: " + expected + ", \"Hello\": " + expected + '}');
+ if (compareFailed) return;
+}
+
+void tst_Parser::undefLengthMaps()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+
+ // integer key
+ compareOne("\xbf\1" + data + '\xff', "{_ 1: " + expected + '}');
+ if (compareFailed) return;
+
+ compareOne("\xbf\1" + data + '\2' + data + '\xff', "{_ 1: " + expected + ", 2: " + expected + '}');
+ if (compareFailed) return;
+
+ compareOne("\xbf\1" + data + "\x65Hello" + data + '\xff', "{_ 1: " + expected + ", \"Hello\": " + expected + '}');
+ if (compareFailed) return;
+
+ compareOne("\xbf\x65Hello" + data + '\1' + data + '\xff', "{_ \"Hello\": " + expected + ", 1: " + expected + '}');
+}
+
+void tst_Parser::nestedMaps()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+
+ // nested maps as values
+ compareOneSize(1, "\xa1\1\xa1\2" + data, "{1: {2: " + expected + "}}");
+ if (compareFailed) return;
+
+ compareOneSize(1, "\xa1\x65Hello\xa1\2" + data, "{\"Hello\": {2: " + expected + "}}");
+ if (compareFailed) return;
+
+ compareOneSize(1, "\xa1\1\xa2\2" + data + '\x20' + data, "{1: {2: " + expected + ", -1: " + expected + "}}");
+ if (compareFailed) return;
+
+ compareOneSize(2, "\xa2\1\xa1\2" + data + "\2\xa1\x20" + data, "{1: {2: " + expected + "}, 2: {-1: " + expected + "}}");
+ if (compareFailed) return;
+
+ // nested maps as keys
+ compareOneSize(1, "\xa1\xa1\xf4" + data + "\xf5", "{{false: " + expected + "}: true}");
+ if (compareFailed) return;
+
+ compareOneSize(1, "\xa1\xa1" + data + data + "\xa1" + data + data,
+ "{{" + expected + ": " + expected + "}: {" + expected + ": " + expected + "}}");
+ if (compareFailed) return;
+
+ // undefined length
+ compareOneSize(-1, "\xbf\1\xbf\2" + data + "\xff\xff", "{_ 1: {_ 2: " + expected + "}}");
+ if (compareFailed) return;
+
+ compareOneSize(-1, "\xbf\1\xbf\2" + data + '\x20' + data + "\xff\xff", "{_ 1: {_ 2: " + expected + ", -1: " + expected + "}}");
+ if (compareFailed) return;
+
+ compareOneSize(-1, "\xbf\1\xbf\2" + data + "\xff\2\xbf\x20" + data + "\xff\xff",
+ "{_ 1: {_ 2: " + expected + "}, 2: {_ -1: " + expected + "}}");
+ if (compareFailed) return;
+
+ compareOneSize(-1, "\xbf\xbf" + data + data + "\xff\xbf" + data + data + "\xff\xff",
+ "{_ {_ " + expected + ": " + expected + "}: {_ " + expected + ": " + expected + "}}");
+ if (compareFailed) return;
+
+ // mix them
+ compareOneSize(1, "\xa1\1\xbf\2" + data + "\xff", "{1: {_ 2: " + expected + "}}");
+ if (compareFailed) return;
+
+ compareOneSize(-1, "\xbf\1\xa1\2" + data + "\xff", "{_ 1: {2: " + expected + "}}");
+ if (compareFailed) return;
+}
+
+void tst_Parser::mapMixed_data()
+{
+ addColumns();
+ addMapMixedData();
+}
+
+void tst_Parser::mapsAndArrays()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+
+ // arrays of maps
+ compareOneSize(1, "\x81\xa1\1" + data, "[{1: " + expected + "}]");
+ if (compareFailed) return;
+
+ compareOneSize(2, "\x82\xa1\1" + data + "\xa1\2" + data, "[{1: " + expected + "}, {2: " + expected + "}]");
+ if (compareFailed) return;
+
+ compareOneSize(1, "\x81\xa2\1" + data + "\2" + data, "[{1: " + expected + ", 2: " + expected + "}]");
+ if (compareFailed) return;
+
+ compareOneSize(-1, "\x9f\xa1\1" + data + "\xff", "[_ {1: " + expected + "}]");
+ if (compareFailed) return;
+
+ compareOneSize(1, "\x81\xbf\1" + data + "\xff", "[{_ 1: " + expected + "}]");
+ if (compareFailed) return;
+
+ compareOneSize(-1, "\x9f\xbf\1" + data + "\xff\xff", "[_ {_ 1: " + expected + "}]");
+ if (compareFailed) return;
+
+ // maps of arrays
+ compareOneSize(1, "\xa1\1\x81" + data, "{1: [" + expected + "]}");
+ if (compareFailed) return;
+
+ compareOneSize(1, "\xa1\1\x82" + data + data, "{1: [" + expected + ", " + expected + "]}");
+ if (compareFailed) return;
+
+ compareOneSize(2, "\xa2\1\x81" + data + "\x65Hello\x81" + data, "{1: [" + expected + "], \"Hello\": [" + expected + "]}");
+ if (compareFailed) return;
+
+ compareOneSize(1, "\xa1\1\x9f" + data + "\xff", "{1: [_ " + expected + "]}");
+ if (compareFailed) return;
+
+ compareOneSize(1, "\xa1\1\x9f" + data + data + "\xff", "{1: [_ " + expected + ", " + expected + "]}");
+ if (compareFailed) return;
+
+ compareOneSize(-1, "\xbf\1\x81" + data + "\xff", "{_ 1: [" + expected + "]}");
+ if (compareFailed) return;
+
+ compareOneSize(-1, "\xbf\1\x9f" + data + "\xff\xff", "{_ 1: [_ " + expected + "]}");
+ if (compareFailed) return;
+
+ compareOneSize(-1, "\xbf\1\x9f" + data + data + "\xff\xff", "{_ 1: [_ " + expected + ", " + expected + "]}");
+ if (compareFailed) return;
+
+ // mixed with indeterminate length strings
+ compareOneSize(-1, "\xbf\1\x9f" + data + "\xff\x65Hello\xbf" + data + "\x7f\xff\xff\xff",
+ "{_ 1: [_ " + expected + "], \"Hello\": {_ " + expected + ": (_ )}}");
+}
+
+struct Input {
+ QByteArray data;
+ int consumed;
+};
+
+static const CborParserOperations byteArrayOps = {
+ /* can_read_bytes = */ [](void *token, size_t len) {
+ auto input = static_cast<Input *>(token);
+ return input->data.size() - input->consumed >= int(len);
+ },
+ /* read_bytes = */ [](void *token, void *dst, size_t offset, size_t len) {
+ auto input = static_cast<Input *>(token);
+ return memcpy(dst, input->data.constData() + input->consumed + offset, len);
+ },
+ /* advance_bytes = */ [](void *token, size_t len) {
+ auto input = static_cast<Input *>(token);
+ input->consumed += int(len);
+ },
+ /* transfer_string = */ [](void *token, const void **userptr, size_t offset, size_t len) {
+ // ###
+ auto input = static_cast<Input *>(token);
+ if (input->data.size() - input->consumed < int(len + offset))
+ return CborErrorUnexpectedEOF;
+ input->consumed += int(offset);
+ *userptr = input->data.constData() + input->consumed;
+ input->consumed += int(len);
+ return CborNoError;
+ }
+};
+
+void tst_Parser::readerApi()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+
+ Input input = { data, 0 };
+
+ CborParser parser;
+ CborValue first;
+ CborError err = cbor_parser_init_reader(&byteArrayOps, &parser, &first, &input);
+ QCOMPARE(err, CborNoError);
+
+ QString decoded;
+ err = parseOne(&first, &decoded);
+ QCOMPARE(err, CborNoError);
+ QCOMPARE(decoded, expected);
+
+ // check we consumed everything
+ QCOMPARE(input.consumed, data.size());
+}
+
+void tst_Parser::reparse_data()
+{
+ // only one-item rows
+ addColumns();
+ addFixedData();
+}
+
+void tst_Parser::reparse()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+
+ Input input = { QByteArray(), 0 };
+ CborParser parser;
+ CborValue first;
+ CborError err = cbor_parser_init_reader(&byteArrayOps, &parser, &first, &input);
+ QCOMPARE(err, CborErrorUnexpectedEOF);
+
+ for (int i = 0; i < data.size(); ++i) {
+ input.data = data.left(i);
+ err = cbor_value_reparse(&first);
+ if (err != CborErrorUnexpectedEOF)
+ qDebug() << "At" << i;
+ QCOMPARE(err, CborErrorUnexpectedEOF);
+ QCOMPARE(input.consumed, 0);
+ }
+
+ // now it should work
+ input.data = data;
+ err = cbor_value_reparse(&first);
+ QCOMPARE(err, CborNoError);
+
+ QString decoded;
+ err = parseOne(&first, &decoded);
+ QCOMPARE(err, CborNoError);
+ QCOMPARE(decoded, expected);
+
+ // check we consumed everything
+ QCOMPARE(input.consumed, data.size());
+}
+
+void tst_Parser::chunkedString_data()
+{
+ addChunkedStringData();
+}
+
+static void chunkedStringTest(const QByteArray &data, const QString &concatenated,
+ QStringList &chunks, CborType ourType)
+{
+ CborParser parser;
+ CborValue first;
+ CborError err = cbor_parser_init(reinterpret_cast<const quint8 *>(data.constData()), data.length(), 0, &parser, &first);
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+
+ CborValue value;
+ QVERIFY(cbor_value_is_array(&first));
+ err = cbor_value_enter_container(&first, &value);
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+ QVERIFY(cbor_value_is_byte_string(&value) || cbor_value_is_text_string(&value));
+
+ CborValue copy = value;
+
+ err = cbor_value_begin_string_iteration(&value);
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+ forever {
+ QString decoded;
+ err = parseOneChunk(&value, &decoded);
+ if (err == CborErrorNoMoreStringChunks)
+ break; // last chunk
+
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+
+ QVERIFY2(!chunks.isEmpty(), "Too many chunks");
+ QString expected = chunks.takeFirst();
+ QCOMPARE(decoded, expected);
+ }
+
+ err = cbor_value_finish_string_iteration(&value);
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+ QVERIFY2(chunks.isEmpty(), "Too few chunks");
+
+ // compare to the concatenated data
+ {
+ size_t n;
+ err = cbor_value_calculate_string_length(&copy, &n);
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+
+ QByteArray buffer(n, Qt::Uninitialized);
+ QString formatted;
+ if (cbor_value_is_byte_string(&copy)) {
+ err = cbor_value_copy_byte_string(&copy, (uint8_t *)buffer.data(), &n, nullptr);
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+ QCOMPARE(int(n), buffer.size());
+
+ formatted = QString::fromLatin1("h'" + buffer.toHex() + '\'');
+ } else {
+ err = cbor_value_copy_text_string(&copy, buffer.data(), &n, nullptr);
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+ QCOMPARE(int(n), buffer.size());
+
+ formatted = '"' + QString::fromUtf8(buffer.data(), n) + '"';
+ }
+ QCOMPARE(formatted, concatenated);
+ }
+
+ // confirm that the extra string we appended is still here
+ QVERIFY(!cbor_value_at_end(&value));
+ QCOMPARE(cbor_value_get_type(&value), ourType);
+ size_t len;
+ err = cbor_value_get_string_length(&value, &len);
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+ QCOMPARE(len, size_t(0));
+
+ err = cbor_value_advance(&value);
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+
+ // confirm EOF
+ QVERIFY(cbor_value_at_end(&value));
+
+ err = cbor_value_leave_container(&first, &value);
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+ QCOMPARE((void*)cbor_value_get_next_byte(&first), (void*)data.constEnd());
+}
+
+void tst_Parser::chunkedString()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, concatenated);
+ QFETCH(QStringList, chunks);
+
+ // Make this an array of two entries, with the second an empty byte or text string
+ CborType ourType = CborType(data.at(0) & 0xe0);
+ data.prepend(char(0x82));
+ data.append(ourType);
+
+ chunkedStringTest(data, concatenated, chunks, ourType);
+}
+
+void tst_Parser::chunkedStringInUndefArray()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, concatenated);
+ QFETCH(QStringList, chunks);
+
+ // Make this an array of undefined length entries, with the second entry an empty byte or text string
+ CborType ourType = CborType(data.at(0) & 0xe0);
+ data.prepend(char(0x9f));
+ data.append(ourType);
+ data.append(char(0xff));
+
+ chunkedStringTest(data, concatenated, chunks, ourType);
+}
+
+void tst_Parser::stringLength_data()
+{
+ QTest::addColumn<QByteArray>("data");
+ QTest::addColumn<int>("expected");
+
+ QTest::newRow("emptybytestring") << raw("\x40") << 0;
+ QTest::newRow("bytestring1") << raw("\x41 ") << 1;
+ QTest::newRow("bytestring1-nul") << raw("\x41\0") << 1;
+ QTest::newRow("bytestring5") << raw("\x45Hello") << 5;
+ QTest::newRow("bytestring24") << raw("\x58\x18""123456789012345678901234") << 24;
+ QTest::newRow("bytestring256") << raw("\x59\1\0") + QByteArray(256, '3') << 256;
+
+ // text strings
+ QTest::newRow("emptytextstring") << raw("\x60") << 0;
+ QTest::newRow("textstring1") << raw("\x61 ") << 1;
+ QTest::newRow("textstring1-nul") << raw("\x61\0") << 1;
+ QTest::newRow("textstring5") << raw("\x65Hello") << 5;
+ QTest::newRow("textstring24") << raw("\x78\x18""123456789012345678901234") << 24;
+ QTest::newRow("textstring256") << raw("\x79\1\0") + QByteArray(256, '3') << 256;
+
+ // strings with overlong length
+ QTest::newRow("emptybytestring*1") << raw("\x58\x00") << 0;
+ QTest::newRow("emptytextstring*1") << raw("\x78\x00") << 0;
+ QTest::newRow("emptybytestring*2") << raw("\x59\x00\x00") << 0;
+ QTest::newRow("emptytextstring*2") << raw("\x79\x00\x00") << 0;
+ QTest::newRow("emptybytestring*4") << raw("\x5a\0\0\0\0") << 0;
+ QTest::newRow("emptytextstring*4") << raw("\x7a\0\0\0\0") << 0;
+ QTest::newRow("emptybytestring*8") << raw("\x5b\0\0\0\0\0\0\0\0") << 0;
+ QTest::newRow("emptytextstring*8") << raw("\x7b\0\0\0\0\0\0\0\0") << 0;
+ QTest::newRow("bytestring5*1") << raw("\x58\x05Hello") << 5;
+ QTest::newRow("textstring5*1") << raw("\x78\x05Hello") << 5;
+ QTest::newRow("bytestring5*2") << raw("\x59\0\5Hello") << 5;
+ QTest::newRow("textstring5*2") << raw("\x79\0\x05Hello") << 5;
+ QTest::newRow("bytestring5*4") << raw("\x5a\0\0\0\5Hello") << 5;
+ QTest::newRow("textstring5*4") << raw("\x7a\0\0\0\x05Hello") << 5;
+ QTest::newRow("bytestring5*8") << raw("\x5b\0\0\0\0\0\0\0\5Hello") << 5;
+ QTest::newRow("textstring5*8") << raw("\x7b\0\0\0\0\0\0\0\x05Hello") << 5;
+
+ // strings with undefined length
+ QTest::newRow("_emptybytestring") << raw("\x5f\xff") << 0;
+ QTest::newRow("_emptytextstring") << raw("\x7f\xff") << 0;
+ QTest::newRow("_emptybytestring2") << raw("\x5f\x40\xff") << 0;
+ QTest::newRow("_emptytextstring2") << raw("\x7f\x60\xff") << 0;
+ QTest::newRow("_emptybytestring3") << raw("\x5f\x40\x40\xff") << 0;
+ QTest::newRow("_emptytextstring3") << raw("\x7f\x60\x60\xff") << 0;
+ QTest::newRow("_bytestring5*2") << raw("\x5f\x43Hel\x42lo\xff") << 5;
+ QTest::newRow("_textstring5*2") << raw("\x7f\x63Hel\x62lo\xff") << 5;
+ QTest::newRow("_bytestring5*5") << raw("\x5f\x41H\x41""e\x41l\x41l\x41o\xff") << 5;
+ QTest::newRow("_textstring5*5") << raw("\x7f\x61H\x61""e\x61l\x61l\x61o\xff") << 5;
+ QTest::newRow("_bytestring5*6") << raw("\x5f\x41H\x41""e\x40\x41l\x41l\x41o\xff") << 5;
+ QTest::newRow("_textstring5*6") << raw("\x7f\x61H\x61""e\x61l\x60\x61l\x61o\xff") << 5;
+}
+
+void tst_Parser::stringLength()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(int, expected);
+
+ CborParser parser;
+ CborValue value;
+ CborError err = cbor_parser_init(reinterpret_cast<const quint8 *>(data.constData()), data.length(), 0, &parser, &value);
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+
+ size_t result;
+ err = cbor_value_calculate_string_length(&value, &result);
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+ QCOMPARE(result, size_t(expected));
+
+ if (cbor_value_is_length_known(&value)) {
+ QCOMPARE(cbor_value_get_string_length(&value, &result), CborNoError);
+ QCOMPARE(result, size_t(expected));
+ }
+
+}
+
+void tst_Parser::stringCompare_data()
+{
+ QTest::addColumn<QByteArray>("data");
+ QTest::addColumn<QString>("string");
+ QTest::addColumn<bool>("expected");
+
+ // compare empty to empty
+ QTest::newRow("empty-empty") << raw("\x60") << QString() << true;
+ QTest::newRow("_empty-empty") << raw("\x7f\xff") << QString() << true;
+ QTest::newRow("_empty*1-empty") << raw("\x7f\x60\xff") << QString() << true;
+ QTest::newRow("_empty*2-empty") << raw("\x7f\x60\x60\xff") << QString() << true;
+
+ // compare empty to non-empty
+ QTest::newRow("empty-nonempty") << raw("\x60") << "Hello" << false;
+ QTest::newRow("_empty-nonempty") << raw("\x7f\xff") << "Hello" << false;
+ QTest::newRow("_empty*1-nonempty") << raw("\x7f\x60\xff") << "Hello" << false;
+ QTest::newRow("_empty*2-nonempty") << raw("\x7f\x60\x60\xff") << "Hello" << false;
+
+ // compare same strings
+ QTest::newRow("same-short-short") << raw("\x65Hello") << "Hello" << true;
+ QTest::newRow("same-_short*1-short") << raw("\x7f\x65Hello\xff") << "Hello" << true;
+ QTest::newRow("same-_short*2-short") << raw("\x7f\x63Hel\x62lo\xff") << "Hello" << true;
+ QTest::newRow("same-_short*5-short") << raw("\x7f\x61H\x61""e\x61l\x61l\x61o\xff") << "Hello" << true;
+ QTest::newRow("same-_short*8-short") << raw("\x7f\x61H\x60\x61""e\x60\x61l\x61l\x60\x61o\xff") << "Hello" << true;
+ QTest::newRow("same-long-long") << raw("\x78\x2aGood morning, good afternoon and goodnight")
+ << "Good morning, good afternoon and goodnight" << true;
+ QTest::newRow("same-_long*1-long") << raw("\x7f\x78\x2aGood morning, good afternoon and goodnight\xff")
+ << "Good morning, good afternoon and goodnight" << true;
+ QTest::newRow("same-_long*2-long") << raw("\x7f\x78\x1cGood morning, good afternoon\x6e and goodnight\xff")
+ << "Good morning, good afternoon and goodnight" << true;
+
+ // compare different strings (same length)
+ QTest::newRow("diff-same-length-short-short") << raw("\x65Hello") << "World" << false;
+ QTest::newRow("diff-same-length-_short*1-short") << raw("\x7f\x65Hello\xff") << "World" << false;
+ QTest::newRow("diff-same-length-_short*2-short") << raw("\x7f\x63Hel\x62lo\xff") << "World" << false;
+ QTest::newRow("diff-same-length-_short*5-short") << raw("\x7f\x61H\x61""e\x61l\x61l\x61o\xff") << "World" << false;
+ QTest::newRow("diff-same-length-_short*8-short") << raw("\x7f\x61H\x60\x61""e\x60\x61l\x61l\x60\x61o\xff") << "World" << false;
+ QTest::newRow("diff-same-length-long-long") << raw("\x78\x2aGood morning, good afternoon and goodnight")
+ << "Good morning, good afternoon and goodnight, world" << false;
+ QTest::newRow("diff-same-length-_long*1-long") << raw("\x7f\x78\x2aGood morning, good afternoon and goodnight\xff")
+ << "Good morning, good afternoon and goodnight, world" << false;
+ QTest::newRow("diff-same-length-_long*2-long") << raw("\x7f\x78\x1cGood morning, good afternoon\x6e and goodnight\xff")
+ << "Good morning, good afternoon and goodnight, world" << false;
+
+ // compare different strings (different length)
+ QTest::newRow("diff-diff-length-short-short") << raw("\x65Hello") << "Hello World" << false;
+ QTest::newRow("diff-diff-length-_short*1-short") << raw("\x7f\x65Hello\xff") << "Hello World" << false;
+ QTest::newRow("diff-diff-length-_short*2-short") << raw("\x7f\x63Hel\x62lo\xff") << "Hello World" << false;
+ QTest::newRow("diff-diff-length-_short*5-short") << raw("\x7f\x61H\x61""e\x61l\x61l\x61o\xff") << "Hello World" << false;
+ QTest::newRow("diff-diff-length-_short*8-short") << raw("\x7f\x61H\x60\x61""e\x60\x61l\x61l\x60\x61o\xff") << "Hello World" << false;
+ QTest::newRow("diff-diff-length-long-long") << raw("\x78\x2aGood morning, good afternoon and goodnight")
+ << "Good morning, good afternoon and goodnight World" << false;
+ QTest::newRow("diff-diff-length-_long*1-long") << raw("\x7f\x78\x2aGood morning, good afternoon and goodnight\xff")
+ << "Good morning, good afternoon and goodnight World" << false;
+ QTest::newRow("diff-diff-length-_long*2-long") << raw("\x7f\x78\x1cGood morning, good afternoon\x6e and goodnight\xff")
+ << "Good morning, good afternoon and goodnight World" << false;
+
+ // compare against non-strings
+ QTest::newRow("unsigned") << raw("\0") << "0" << false;
+ QTest::newRow("negative") << raw("\x20") << "-1" << false;
+ QTest::newRow("emptybytestring") << raw("\x40") << "" << false;
+ QTest::newRow("_emptybytestring") << raw("\x5f\xff") << "" << false;
+ QTest::newRow("shortbytestring") << raw("\x45Hello") << "Hello" << false;
+ QTest::newRow("longbytestring") << raw("\x58\x2aGood morning, good afternoon and goodnight")
+ << "Good morning, good afternoon and goodnight" << false;
+ QTest::newRow("emptyarray") << raw("\x80") << "" << false;
+ QTest::newRow("emptymap") << raw("\xa0") << "" << false;
+ QTest::newRow("array") << raw("\x81\x65Hello") << "Hello" << false;
+ QTest::newRow("map") << raw("\xa1\x65Hello\x65World") << "Hello World" << false;
+ QTest::newRow("false") << raw("\xf4") << "false" << false;
+ QTest::newRow("true") << raw("\xf5") << "true" << false;
+ QTest::newRow("null") << raw("\xf6") << "null" << false;
+}
+
+void compareOneString(const QByteArray &data, const QString &string, bool expected, int line)
+{
+ compareFailed = true;
+
+ CborParser parser;
+ CborValue value;
+ CborError err = cbor_parser_init(reinterpret_cast<const quint8 *>(data.constData()), data.length(), 0, &parser, &value);
+ QVERIFY2(!err, QByteArray::number(line) + ": Got error \"" + cbor_error_string(err) + "\"");
+
+ bool result;
+ QByteArray bastring = string.toUtf8();
+ err = cbor_value_text_string_equals(&value, bastring.constData(), &result);
+ QVERIFY2(!err, QByteArray::number(line) + ": Got error \"" + cbor_error_string(err) + "\"");
+ QCOMPARE(result, expected);
+
+ if (expected) {
+ size_t len;
+ cbor_value_skip_tag(&value);
+ if (cbor_value_is_length_known(&value)) {
+ QCOMPARE(cbor_value_get_string_length(&value, &len), CborNoError);
+ QCOMPARE(int(len), bastring.size());
+ }
+ QCOMPARE(cbor_value_calculate_string_length(&value, &len), CborNoError);
+ QCOMPARE(int(len), bastring.size());
+ }
+
+ compareFailed = false;
+}
+#define compareOneString(data, string, expected) compareOneString(data, string, expected, __LINE__)
+
+void tst_Parser::stringCompare()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, string);
+ QFETCH(bool, expected);
+
+ compareOneString(data, string, expected);
+ if (compareFailed) return;
+
+ // tag it
+ compareOneString("\xc1" + data, string, expected);
+ if (compareFailed) return;
+
+ compareOneString("\xc1\xc2" + data, string, expected);
+}
+
+void tst_Parser::mapFind_data()
+{
+ // Rules:
+ // we are searching for string "needle"
+ // if present, the value should be the string "haystack" (with tag 42)
+
+ QTest::addColumn<QByteArray>("data");
+ QTest::addColumn<bool>("expected");
+
+ QTest::newRow("emptymap") << raw("\xa0") << false;
+ QTest::newRow("_emptymap") << raw("\xbf\xff") << false;
+
+ // maps not containing our items
+ QTest::newRow("absent-unsigned-unsigned") << raw("\xa1\0\0") << false;
+ QTest::newRow("absent-taggedunsigned-unsigned") << raw("\xa1\xc0\0\0") << false;
+ QTest::newRow("absent-unsigned-taggedunsigned") << raw("\xa1\0\xc0\0") << false;
+ QTest::newRow("absent-taggedunsigned-taggedunsigned") << raw("\xa1\xc0\0\xc0\0") << false;
+ QTest::newRow("absent-string-unsigned") << raw("\xa1\x68haystack\0") << false;
+ QTest::newRow("absent-taggedstring-unsigned") << raw("\xa1\xc0\x68haystack\0") << false;
+ QTest::newRow("absent-string-taggedunsigned") << raw("\xa1\x68haystack\xc0\0") << false;
+ QTest::newRow("absent-taggedstring-taggedunsigned") << raw("\xa1\xc0\x68haystack\xc0\0") << false;
+ QTest::newRow("absent-string-string") << raw("\xa1\x68haystack\x66needle") << false;
+ QTest::newRow("absent-string-taggedstring") << raw("\xa1\x68haystack\xc0\x66needle") << false;
+ QTest::newRow("absent-taggedstring-string") << raw("\xa1\xc0\x68haystack\x66needle") << false;
+ QTest::newRow("absent-string-taggedstring") << raw("\xa1\xc0\x68haystack\xc0\x66needle") << false;
+
+ QTest::newRow("absent-string-emptyarray") << raw("\xa1\x68haystack\x80") << false;
+ QTest::newRow("absent-string-_emptyarray") << raw("\xa1\x68haystack\x9f\xff") << false;
+ QTest::newRow("absent-string-array1") << raw("\xa1\x68haystack\x81\0") << false;
+ QTest::newRow("absent-string-array2") << raw("\xa1\x68haystack\x85\0\1\2\3\4") << false;
+ QTest::newRow("absent-string-array3") << raw("\xa1\x68haystack\x85\x63one\x63two\x65three\x64""four\x64""five") << false;
+
+ QTest::newRow("absent-string-emptymap") << raw("\xa1\x68haystack\xa0") << false;
+ QTest::newRow("absent-string-_emptymap") << raw("\xa1\x68haystack\xbf\xff") << false;
+ QTest::newRow("absent-string-map") << raw("\xa1\x68haystack\xa1\x68haystack\x66needle") << false;
+ QTest::newRow("absent-string-map2") << raw("\xa1\x68haystack\xa1\x68haystack\x66needle\61z\62yx") << false;
+
+ // maps containing our items
+ QTest::newRow("alone") << raw("\xa1\x66needle\xd8\x2a\x68haystack") << true;
+ QTest::newRow("tagged") << raw("\xa1\xc1\x66needle\xd8\x2a\x68haystack") << true;
+ QTest::newRow("doubletagged") << raw("\xa1\xc1\xc2\x66needle\xd8\x2a\x68haystack") << true;
+ QTest::newRow("chunked") << raw("\xa1\x7f\x66needle\xff\xd8\x2a\x68haystack") << true;
+ QTest::newRow("chunked*2") << raw("\xa1\x7f\x60\x66needle\xff\xd8\x2a\x68haystack") << true;
+ QTest::newRow("chunked*2bis") << raw("\xa1\x7f\x66needle\x60\xff\xd8\x2a\x68haystack") << true;
+ QTest::newRow("chunked*3") << raw("\xa1\x7f\x62ne\x62""ed\x62le\xff\xd8\x2a\x68haystack") << true;
+ QTest::newRow("chunked*8") << raw("\xa1\x7f\x61n\x61""e\x60\x61""e\x61""d\x60\x62le\x60\xff\xd8\x2a\x68haystack") << true;
+
+ QTest::newRow("1before") << raw("\xa2\x68haystack\x66needle\x66needle\xd8\x2a\x68haystack") << true;
+ QTest::newRow("tagged-1before") << raw("\xa2\xc1\x68haystack\x66needle\xc1\x66needle\xd8\x2a\x68haystack") << true;
+ QTest::newRow("doubletagged-1before2") << raw("\xa2\xc1\xc2\x68haystack\x66needle\xc1\xc2\x66needle\xd8\x2a\x68haystack") << true;
+
+ QTest::newRow("arraybefore") << raw("\xa2\x61z\x80\x66needle\xd8\x2a\x68haystack") << true;
+ QTest::newRow("nestedarraybefore") << raw("\xa2\x61z\x81\x81\0\x66needle\xd8\x2a\x68haystack") << true;
+ QTest::newRow("arrayarraybefore") << raw("\xa2\x82\1\2\x80\x66needle\xd8\x2a\x68haystack") << true;
+
+ QTest::newRow("mapbefore") << raw("\xa2\x61z\xa0\x66needle\xd8\x2a\x68haystack") << true;
+ QTest::newRow("nestedmapbefore") << raw("\xa2\x61z\xa1\0\x81\0\x66needle\xd8\x2a\x68haystack") << true;
+ QTest::newRow("mapmapbefore") << raw("\xa2\xa1\1\2\xa0\x66needle\xd8\x2a\x68haystack") << true;
+}
+
+void tst_Parser::mapFind()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(bool, expected);
+
+ CborParser parser;
+ CborValue value;
+ CborError err = cbor_parser_init(reinterpret_cast<const quint8 *>(data.constData()), data.length(), 0, &parser, &value);
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+
+ CborValue element;
+ err = cbor_value_map_find_value(&value, "needle", &element);
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+
+ if (expected) {
+ QCOMPARE(int(element.type), int(CborTagType));
+
+ CborTag tag;
+ err = cbor_value_get_tag(&element, &tag);
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+ QCOMPARE(int(tag), 42);
+
+ bool equals;
+ err = cbor_value_text_string_equals(&element, "haystack", &equals);
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+ QVERIFY(equals);
+ } else {
+ QCOMPARE(int(element.type), int(CborInvalidType));
+ }
+}
+
+void tst_Parser::checkedIntegers_data()
+{
+ QTest::addColumn<QByteArray>("data");
+ QTest::addColumn<QVariant>("result"); // QVariant so we can note numbers out of int64_t range
+
+ QTest::newRow("0") << raw("\x00") << QVariant(Q_INT64_C(0));
+ QTest::newRow("1") << raw("\x01") << QVariant(Q_INT64_C(1));
+ QTest::newRow("10") << raw("\x0a") << QVariant(Q_INT64_C(10));
+ QTest::newRow("23") << raw("\x17") << QVariant(Q_INT64_C(23));
+ QTest::newRow("24") << raw("\x18\x18") << QVariant(Q_INT64_C(24));
+ QTest::newRow("UINT8_MAX") << raw("\x18\xff") << QVariant(Q_INT64_C(255));
+ QTest::newRow("UINT8_MAX+1") << raw("\x19\x01\x00") << QVariant(Q_INT64_C(256));
+ QTest::newRow("UINT16_MAX") << raw("\x19\xff\xff") << QVariant(Q_INT64_C(65535));
+ QTest::newRow("UINT16_MAX+1") << raw("\x1a\0\1\x00\x00") << QVariant(Q_INT64_C(65536));
+ QTest::newRow("INT32_MAX") << raw("\x1a\x7f\xff\xff\xff") << QVariant(Q_INT64_C(2147483647));
+ QTest::newRow("INT32_MAX+1") << raw("\x1a\x80\x00\x00\x00") << QVariant(Q_INT64_C(2147483648));
+ QTest::newRow("UINT32_MAX") << raw("\x1a\xff\xff\xff\xff") << QVariant(Q_INT64_C(4294967295));
+ QTest::newRow("UINT32_MAX+1") << raw("\x1b\0\0\0\1\0\0\0\0") << QVariant(Q_INT64_C(4294967296));
+ QTest::newRow("UINT64_MAX") << raw("\x1b" "\xff\xff\xff\xff" "\xff\xff\xff\xff")
+ << QVariant(); // out of range
+
+ // negative integers
+ QTest::newRow("-1") << raw("\x20") << QVariant(Q_INT64_C(-1));
+ QTest::newRow("-2") << raw("\x21") << QVariant(Q_INT64_C(-2));
+ QTest::newRow("-24") << raw("\x37") << QVariant(Q_INT64_C(-24));
+ QTest::newRow("-25") << raw("\x38\x18") << QVariant(Q_INT64_C(-25));
+ QTest::newRow("-UINT8_MAX") << raw("\x38\xff") << QVariant(Q_INT64_C(-256));
+ QTest::newRow("-UINT8_MAX-1") << raw("\x39\x01\x00") << QVariant(Q_INT64_C(-257));
+ QTest::newRow("-UINT16_MAX") << raw("\x39\xff\xff") << QVariant(Q_INT64_C(-65536));
+ QTest::newRow("-UINT16_MAX-1") << raw("\x3a\0\1\x00\x00") << QVariant(Q_INT64_C(-65537));
+ QTest::newRow("INT32_MIN") << raw("\x3a\x7f\xff\xff\xff") << QVariant(Q_INT64_C(-2147483648));
+ QTest::newRow("INT32_MIN-1") << raw("\x3a\x80\x00\x00\x00") << QVariant(Q_INT64_C(-2147483649));
+ QTest::newRow("-UINT32_MAX") << raw("\x3a\xff\xff\xff\xff") << QVariant(Q_INT64_C(-4294967296));
+ QTest::newRow("-UINT32_MAX-1") << raw("\x3b\0\0\0\1\0\0\0\0") << QVariant(Q_INT64_C(-4294967297));
+ QTest::newRow("INT64_MIN+1") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xfe")
+ << QVariant(std::numeric_limits<qint64>::min() + 1);
+ QTest::newRow("INT64_MIN") << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xff")
+ << QVariant(std::numeric_limits<qint64>::min());
+ QTest::newRow("INT64_MIN-1") << raw("\x3b\x80\0\0\0""\0\0\0\0") << QVariant(); // out of range
+ QTest::newRow("-UINT64_MAX") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xfe")
+ << QVariant(); // out of range
+ QTest::newRow("-UINT64_MAX+1") << raw("\x3b" "\xff\xff\xff\xff" "\xff\xff\xff\xff")
+ << QVariant(); // out of range
+}
+
+void tst_Parser::checkedIntegers()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QVariant, result);
+ int64_t expected = result.toLongLong();
+
+ CborParser parser;
+ CborValue value;
+ CborError err = cbor_parser_init(reinterpret_cast<const quint8 *>(data.constData()), data.length(), 0, &parser, &value);
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+
+ int64_t v;
+ err = cbor_value_get_int64_checked(&value, &v);
+ if (result.isNull()) {
+ QCOMPARE(err, CborErrorDataTooLarge);
+ } else {
+ QCOMPARE(v, expected);
+ }
+
+ int v2;
+ err = cbor_value_get_int_checked(&value, &v2);
+ if (result.isNull() || expected < std::numeric_limits<int>::min() || expected > std::numeric_limits<int>::max()) {
+ QCOMPARE(err, CborErrorDataTooLarge);
+ } else {
+ QCOMPARE(int64_t(v2), expected);
+ }
+}
+
+void tst_Parser::validation_data()
+{
+ addValidationColumns();
+ addValidationData();
+}
+
+void tst_Parser::validation()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(int, flags);
+ QFETCH(CborError, expectedError);
+
+ QString decoded;
+ CborParser parser;
+ CborValue first;
+ CborError err = cbor_parser_init(reinterpret_cast<const quint8 *>(data.constData()), data.length(), flags, &parser, &first);
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+
+ CborError err2 = cbor_value_validate_basic(&first);
+ CborError err3 = cbor_value_validate(&first, CborValidateBasic);
+ err = parseOne(&first, &decoded);
+ QCOMPARE(err, expectedError);
+ if (!QByteArray(QTest::currentDataTag()).contains("utf8")) {
+ QCOMPARE(err2, expectedError);
+ QCOMPARE(err3, expectedError);
+ }
+}
+
+void tst_Parser::strictValidation_data()
+{
+ addValidationColumns();
+
+ // Canonical validation - fixed types
+ QTest::newRow("unsigned-0") << raw("\x00") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("unsigned-24") << raw("\x18\x18") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("unsigned-256") << raw("\x19\1\0") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("unsigned-65536") << raw("\x1a\0\1\0\0") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("unsigned-4294967296") << raw("\x1b\0\0\0\1\0\0\0\0") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("overlong-unsigned-0*1") << raw("\x18\x00") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-unsigned-0*2") << raw("\x19\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-unsigned-0*4") << raw("\x1a\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-unsigned-0*8") << raw("\x1b\0\0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-unsigned-24*2") << raw("\x19\0\x18") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-unsigned-24*4") << raw("\x1a\0\0\0\x18") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-unsigned-24*8") << raw("\x1b\0\0\0\0\0\0\0\x18") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-unsigned-256*4") << raw("\x1a\0\0\1\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-unsigned-256*8") << raw("\x1b\0\0\0\0\0\0\1\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-unsigned-65536*8") << raw("\x1b\0\0\0\0\0\1\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("negative-1") << raw("\x20") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("negative-25") << raw("\x38\x38") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("negative-257") << raw("\x39\1\0") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("negative-65537") << raw("\x3a\0\1\0\0") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("negative-4294967297") << raw("\x3b\0\0\0\1\0\0\0\0") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("overlong-negative-1*1") << raw("\x38\x00") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-negative-1*2") << raw("\x39\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-negative-1*4") << raw("\x3a\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-negative-1*8") << raw("\x3b\0\0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-negative-25*2") << raw("\x39\0\x18") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-negative-25*4") << raw("\x3a\0\0\0\x18") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-negative-25*8") << raw("\x3b\0\0\0\0\0\0\0\x18") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-negative-257*4") << raw("\x3a\0\0\1\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-negative-257*8") << raw("\x3b\0\0\0\0\0\0\1\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-negative-65537*8") << raw("\x3b\0\0\0\0\0\1\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("simple-0") << raw("\xe0") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("false") << raw("\xf4") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("true") << raw("\xf5") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("null") << raw("\xf6") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("undefined") << raw("\xf7") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("simple-32") << raw("\xf8\x20") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("fp-nan") << raw("\xf9\x7e\00") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("fp--inf") << raw("\xf9\xfc\00") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("fp-+inf") << raw("\xf9\x7c\00") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("overlong-fp-nan_f") << raw("\xfa\x7f\xc0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-fp--inf_f") << raw("\xfa\xff\x80\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-fp-+inf_f") << raw("\xfa\x7f\x80\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-fp-nan") << raw("\xfb\x7f\xf8\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-fp--inf") << raw("\xfb\xff\xf0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-fp-+inf") << raw("\xfb\x7f\xf0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+
+ // canonical - lengths
+ QByteArray data24(24, 0x20); // also decodes as -1
+ QByteArray data256(256, 0x40); // also decodes as h''
+ QByteArray data65536(65536, 0x60);// also decodes as ""
+ QTest::newRow("bytearray-0") << raw("\x40") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("bytearray-24") << (raw("\x58\x18") + data24) << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("bytearray-256") << (raw("\x59\1\0") + data256) << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("bytearray-65536") << (raw("\x5a\0\1\0\0") + data65536) << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("_bytearray-0") << raw("\x5f\xff") << int(CborValidateCanonicalFormat) << CborErrorUnknownLength;
+ QTest::newRow("overlong-bytearray-0*1") << raw("\x58\x00") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-bytearray-0*2") << raw("\x59\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-bytearray-0*4") << raw("\x5a\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-bytearray-0*8") << raw("\x5b\0\0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-bytearray-24*2") << (raw("\x59\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-bytearray-24*4") << (raw("\x5a\0\0\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-bytearray-24*8") << (raw("\x5b\0\0\0\0\0\0\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-bytearray-256*4") << (raw("\x5a\0\0\1\0") + data256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-bytearray-256*8") << (raw("\x5b\0\0\0\0\0\0\1\0") + data256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-bytearray-65536*8") << (raw("\x5b\0\0\0\0\0\1\0\0") + data65536) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("string-0") << raw("\x60") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("string-24") << (raw("\x78\x18") + data24) << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("string-256") << (raw("\x79\1\0") + data256) << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("string-65536") << (raw("\x7a\0\1\0\0") + data65536) << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("_string-0") << raw("\x7f\xff") << int(CborValidateCanonicalFormat) << CborErrorUnknownLength;
+ QTest::newRow("overlong-string-0*1") << raw("\x78\x00") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-string-0*2") << raw("\x79\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-string-0*4") << raw("\x7a\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-string-0*8") << raw("\x7b\0\0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-string-24*2") << (raw("\x79\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-string-24*4") << (raw("\x7a\0\0\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-string-24*8") << (raw("\x7b\0\0\0\0\0\0\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-string-256*4") << (raw("\x7a\0\0\1\0") + data256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-string-256*8") << (raw("\x7b\0\0\0\0\0\0\1\0") + data256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-string-65536*8") << (raw("\x7b\0\0\0\0\0\1\0\0") + data65536) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("array-0") << raw("\x80") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("array-24") << (raw("\x98\x18") + data24) << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("array-256") << (raw("\x99\1\0") + data256) << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("array-65536") << (raw("\x9a\0\1\0\0") + data65536) << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("_array-0") << raw("\x9f\xff") << int(CborValidateCanonicalFormat) << CborErrorUnknownLength;
+ QTest::newRow("overlong-array-0*1") << raw("\x98\x00") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-array-0*2") << raw("\x99\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-array-0*4") << raw("\x9a\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-array-0*8") << raw("\x9b\0\0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-array-24*2") << (raw("\x99\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-array-24*4") << (raw("\x9a\0\0\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-array-24*8") << (raw("\x9b\0\0\0\0\0\0\0\x18") + data24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-array-256*4") << (raw("\x9a\0\0\1\0") + data256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-array-256*8") << (raw("\x9b\0\0\0\0\0\0\1\0") + data256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-array-65536*8") << (raw("\x9b\0\0\0\0\0\1\0\0") + data65536) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+
+ // we need unique, sorted, string keys for map
+ // we'll make all key-value pairs a total of 4 bytes
+ char mapentry[] = { 0x62, 0, 0, 0x20 };
+ QByteArray mapdata24(24 * sizeof(mapentry), Qt::Uninitialized);
+ QByteArray mapdata256(256 * sizeof(mapentry), Qt::Uninitialized);
+ char *mapdata24ptr = mapdata24.data();
+ char *mapdata256ptr = mapdata256.data();
+ for (int i = 0; i < 256; ++i) {
+ mapentry[1] = 'A' + (i >> 4);
+ mapentry[2] = 'a' + (i & 0xf);
+ memcpy(mapdata256ptr + i * sizeof(mapentry), mapentry, sizeof(mapentry));
+ if (i < 24)
+ memcpy(mapdata24ptr + i * sizeof(mapentry), mapentry, sizeof(mapentry));
+ }
+ QTest::newRow("map-0") << raw("\xa0") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("map-24") << (raw("\xb8\x18") + mapdata24) << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("map-256") << (raw("\xb9\1\0") + mapdata256) << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("_map-0") << raw("\xbf\xff") << int(CborValidateCanonicalFormat) << CborErrorUnknownLength;
+ QTest::newRow("overlong-map-0*1") << raw("\xb8\x00") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-map-0*2") << raw("\xb9\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-map-0*4") << raw("\xba\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-map-0*8") << raw("\xbb\0\0\0\0\0\0\0\0") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-map-24*2") << (raw("\xb9\0\x18") + mapdata24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-map-24*4") << (raw("\xba\0\0\0\x18") + mapdata24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-map-24*8") << (raw("\xbb\0\0\0\0\0\0\0\x18") + mapdata24) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-map-256*4") << (raw("\xba\0\0\1\0") + mapdata256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-map-256*8") << (raw("\xbb\0\0\0\0\0\0\1\0") + mapdata256) << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("unsorted-length-map-UU") << raw("\xa2\1\1\0\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted;
+ QTest::newRow("unsorted-length-map-UUU") << raw("\xa3\1\1\1\1\0\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted;
+ QTest::newRow("unsorted-length-map-SS") << raw("\xa2\x61z\1\x60\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted;
+ QTest::newRow("unsorted-length-map-SSS") << raw("\xa3\x61z\1\x61z\2\x60\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted;
+ QTest::newRow("unsorted-length-map-SB") << raw("\xa2\x61z\1\x40\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted;
+ QTest::newRow("unsorted-length-map-AS") << raw("\xa2\x83\0\x20\x45Hello\1\x60\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted;
+ QTest::newRow("unsorted-content-map-SS") << raw("\xa2\x61z\1\x61y\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted;
+ QTest::newRow("unsorted-content-map-AS") << raw("\xa2\x81\x21\1\x61\x21\0") << int(CborValidateCanonicalFormat) << CborErrorMapNotSorted;
+
+ QTest::newRow("tag-0") << raw("\xc0\x60") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("tag-24") << raw("\xd8\x18\x40") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("tag-65536") << raw("\xda\0\1\0\0\x60") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("tag-4294967296") << raw("\xdb\0\0\0\1\0\0\0\0\x60") << int(CborValidateCanonicalFormat) << CborNoError;
+ QTest::newRow("overlong-tag-0*1") << raw("\xd8\x00\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-tag-0*2") << raw("\xd9\0\0\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-tag-0*4") << raw("\xda\0\0\0\0\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-tag-0*8") << raw("\xdb\0\0\0\0\0\0\0\0\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-tag-24*2") << raw("\xd9\0\x18\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-tag-24*4") << raw("\xda\0\0\0\x18\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-tag-24*8") << raw("\xdb\0\0\0\0\0\0\0\x18\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-tag-256*4") << raw("\xda\0\0\1\0\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-tag-256*8") << raw("\xdb\0\0\0\0\0\0\1\0\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-tag-65536*8") << raw("\xdb\0\0\0\0\0\1\0\0\x60") << int(CborValidateCanonicalFormat) << CborErrorOverlongEncoding;
+
+ // non-canonical: string length in chunked transfer
+ QTest::newRow("overlong-_bytearray-0*1") << raw("\x5f\x58\x00\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_bytearray-0*2") << raw("\x5f\x59\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_bytearray-0*4") << raw("\x5f\x5a\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_bytearray-0*8") << raw("\x5f\x5b\0\0\0\0\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_bytearray-24*2") << (raw("\x5f\x59\0\x18") + data24 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_bytearray-24*4") << (raw("\x5f\x5a\0\0\0\x18") + data24 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_bytearray-24*8") << (raw("\x5f\x5b\0\0\0\0\0\0\0\x18") + data24 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_bytearray-256*4") << (raw("\x5f\x5a\0\0\1\0") + data256 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_bytearray-256*8") << (raw("\x5f\x5b\0\0\0\0\0\0\1\0") + data256 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_bytearray-65536*8") << (raw("\x5f\x5b\0\0\0\0\0\1\0\0") + data65536 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_bytearrayx2-0*1") << raw("\x5f\x40\x58\x00\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_bytearrayx2-0*2") << raw("\x5f\x40\x59\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_bytearrayx2-0*4") << raw("\x5f\x40\x5a\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_bytearrayx2-0*8") << raw("\x5f\x40\x5b\0\0\0\0\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_string-0*1") << raw("\x7f\x78\x00\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_string-0*2") << raw("\x7f\x79\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_string-0*4") << raw("\x7f\x7a\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_string-0*8") << raw("\x7f\x7b\0\0\0\0\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_string-24*2") << (raw("\x7f\x79\0\x18") + data24 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_string-24*4") << (raw("\x7f\x7a\0\0\0\x18") + data24 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_string-24*8") << (raw("\x7f\x7b\0\0\0\0\0\0\0\x18") + data24 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_string-256*4") << (raw("\x7f\x7a\0\0\1\0") + data256 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_string-256*8") << (raw("\x7f\x7b\0\0\0\0\0\0\1\0") + data256 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_string-65536*8") << (raw("\x7f\x7b\0\0\0\0\0\1\0\0") + data65536 + '\xff') << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_stringx2-0*1") << raw("\x7f\x60\x78\x00\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_stringx2-0*2") << raw("\x7f\x60\x79\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_stringx2-0*4") << raw("\x7f\x60\x7a\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+ QTest::newRow("overlong-_stringx2-0*8") << raw("\x7f\x60\x7b\0\0\0\0\0\0\0\0\xff") << int(CborValidateShortestNumbers) << CborErrorOverlongEncoding;
+
+ // strict mode
+ QTest::newRow("invalid-utf8-1char") << raw("\x61\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-2chars-1") << raw("\x62\xc2\xc0") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-2chars-2") << raw("\x62\xc3\xdf") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-2chars-3") << raw("\x62\xc7\xf0") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-3chars-1") << raw("\x63\xe0\xa0\xc0") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-3chars-2") << raw("\x63\xe0\xc0\xa0") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-4chars-1") << raw("\x64\xf0\x90\x80\xc0") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-4chars-2") << raw("\x64\xf0\x90\xc0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-4chars-3") << raw("\x64\xf0\xc0\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-hi-surrogate") << raw("\x63\xed\xa0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-lo-surrogate") << raw("\x63\xed\xb0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-surrogate-pair") << raw("\x66\xed\xa0\x80\xed\xb0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-non-unicode-1") << raw("\x64\xf4\x90\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-non-unicode-2") << raw("\x65\xf8\x88\x80\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-non-unicode-3") << raw("\x66\xfc\x84\x80\x80\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-non-unicode-4") << raw("\x66\xfd\xbf\xbf\xbf\xbf\xbf") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-fe") << raw("\x61\xfe") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-ff") << raw("\x61\xff") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-overlong-1-2") << raw("\x62\xc1\x81") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-overlong-1-3") << raw("\x63\xe0\x81\x81") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-overlong-1-4") << raw("\x64\xf0\x80\x81\x81") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-overlong-1-5") << raw("\x65\xf8\x80\x80\x81\x81") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-overlong-1-6") << raw("\x66\xfc\x80\x80\x80\x81\x81") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-overlong-2-3") << raw("\x63\xe0\x82\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-overlong-2-4") << raw("\x64\xf0\x80\x82\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-overlong-2-5") << raw("\x65\xf8\x80\x80\x82\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-overlong-2-6") << raw("\x66\xfc\x80\x80\x80\x82\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-overlong-3-4") << raw("\x64\xf0\x80\xa0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-overlong-3-5") << raw("\x65\xf8\x80\x80\xa0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-overlong-3-6") << raw("\x66\xfc\x80\x80\x80\xa0\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-overlong-4-5") << raw("\x65\xf8\x80\x84\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+ QTest::newRow("invalid-utf8-overlong-4-6") << raw("\x66\xfc\x80\x80\x84\x80\x80") << int(CborValidateStrictMode) << CborErrorInvalidUtf8TextString;
+
+ QTest::newRow("nonunique-content-map-UU") << raw("\xa2\0\1\0\2") << int(CborValidateStrictMode) << CborErrorMapKeysNotUnique;
+ QTest::newRow("nonunique-content-map-SS") << raw("\xa2\x61z\1\x61z\2") << int(CborValidateStrictMode) << CborErrorMapKeysNotUnique;
+ QTest::newRow("nonunique-content-map-AA") << raw("\xa2\x81\x65Hello\1\x81\x65Hello\2") << int(CborValidateStrictMode) << CborErrorMapKeysNotUnique;
+
+ QTest::newRow("tag-0-unsigned") << raw("\xc0\x00") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
+ QTest::newRow("tag-0-bytearray") << raw("\xc0\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
+ QTest::newRow("tag-0-string") << raw("\xc0\x60") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-0-tag-0-string") << raw("\xc0\xc0\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
+ QTest::newRow("tag-1-unsigned") << raw("\xc1\x00") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-1-negative") << raw("\xc1\x20") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-1-bytearray") << raw("\xc1\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
+ QTest::newRow("tag-2-bytearray") << raw("\xc2\x40") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-2-string") << raw("\xc2\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
+ QTest::newRow("tag-3-bytearray") << raw("\xc3\x40") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-3-string") << raw("\xc3\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
+ QTest::newRow("tag-4-string") << raw("\xc4\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
+ QTest::newRow("tag-4-array") << raw("\xc4\x82\0\1") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-5-string") << raw("\xc5\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
+ QTest::newRow("tag-5-array") << raw("\xc5\x82\0\1") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-21-bytearray") << raw("\xd5\x40") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-21-string") << raw("\xd5\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
+ QTest::newRow("tag-21-array") << raw("\xd5\x80") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-21-map") << raw("\xd5\xa0") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-22-bytearray") << raw("\xd6\x40") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-22-string") << raw("\xd6\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
+ QTest::newRow("tag-22-array") << raw("\xd6\x80") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-22-map") << raw("\xd6\xa0") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-23-bytearray") << raw("\xd7\x40") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-23-string") << raw("\xd7\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
+ QTest::newRow("tag-23-array") << raw("\xd7\x80") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-23-map") << raw("\xd7\xa0") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-24-bytearray") << raw("\xd8\x18\x40") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-24-string") << raw("\xd8\x18\x60") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
+ QTest::newRow("tag-32-bytearray") << raw("\xd8\x20\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
+ QTest::newRow("tag-32-string") << raw("\xd8\x20\x60") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-33-bytearray") << raw("\xd8\x21\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
+ QTest::newRow("tag-33-string") << raw("\xd8\x21\x60") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-34-bytearray") << raw("\xd8\x22\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
+ QTest::newRow("tag-34-string") << raw("\xd8\x22\x60") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-35-bytearray") << raw("\xd8\x23\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
+ QTest::newRow("tag-35-string") << raw("\xd8\x23\x60") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-36-bytearray") << raw("\xd8\x24\x40") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
+ QTest::newRow("tag-36-string") << raw("\xd8\x24\x60") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-55799-unsigned") << raw("\xd9\xd9\xf7\x00") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-55799-negative") << raw("\xd9\xd9\xf7\x20") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-55799-bytearray") << raw("\xd9\xd9\xf7\x40") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-55799-string") << raw("\xd9\xd9\xf7\x60") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-55799-array") << raw("\xd9\xd9\xf7\x80") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-55799-map") << raw("\xd9\xd9\xf7\xa0") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-55799-tag-0-unsigned") << raw("\xd9\xd9\xf7\xc0\x00") << int(CborValidateStrictMode) << CborErrorInappropriateTagForType;
+ QTest::newRow("tag-55799-tag-0-string") << raw("\xd9\xd9\xf7\xc0\x60") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-55799-simple0") << raw("\xd9\xd9\xf7\xe0") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-55799-false") << raw("\xd9\xd9\xf7\xf4") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-55799-true") << raw("\xd9\xd9\xf7\xf5") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-55799-null") << raw("\xd9\xd9\xf7\xf6") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-55799-undefined") << raw("\xd9\xd9\xf7\xf7") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-55799-simple32") << raw("\xd9\xd9\xf7\xf8\x20") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-55799-half") << raw("\xd9\xd9\xf7\xf9\0\0") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-55799-float") << raw("\xd9\xd9\xf7\xfa\0\0\0\0") << int(CborValidateStrictMode) << CborNoError;
+ QTest::newRow("tag-55799-double") << raw("\xd9\xd9\xf7\xfb\0\0\0\0\0\0\0\0") << int(CborValidateStrictMode) << CborNoError;
+
+ // excluded non-finite
+ QTest::newRow("excluded-fp-nan") << raw("\xfb\x7f\xf8\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
+ QTest::newRow("excluded-fp-nan_f") << raw("\xfa\x7f\xc0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
+ QTest::newRow("excluded-fp--inf_f") << raw("\xfa\xff\x80\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
+ QTest::newRow("excluded-fp--inf") << raw("\xfb\xff\xf0\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
+ QTest::newRow("excluded-fp-+inf_f") << raw("\xfa\x7f\x80\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
+ QTest::newRow("excluded-fp-+inf") << raw("\xfb\x7f\xf0\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
+
+ // excluded undefined
+ QTest::newRow("no-undefined") << raw("\xf7") << int(CborValidateNoUndefined) << CborErrorExcludedType;
+
+ // exclude non-finite
+ QTest::newRow("excluded-fp-nan_f16") << raw("\xf9\x7e\00") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
+ QTest::newRow("excluded-fp--inf_f16") << raw("\xf9\xfc\00") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
+ QTest::newRow("excluded-fp-+inf_f16") << raw("\xf9\x7c\00") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
+ QTest::newRow("excluded-fp-nan_f") << raw("\xfa\x7f\xc0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
+ QTest::newRow("excluded-fp--inf_f") << raw("\xfa\xff\x80\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
+ QTest::newRow("excluded-fp-+inf_f") << raw("\xfa\x7f\x80\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
+ QTest::newRow("excluded-fp-nan") << raw("\xfb\x7f\xf8\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
+ QTest::newRow("excluded-fp--inf") << raw("\xfb\xff\xf0\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
+ QTest::newRow("excluded-fp-+inf") << raw("\xfb\x7f\xf0\0\0\0\0\0\0") << int(CborValidateFiniteFloatingPoint) << CborErrorExcludedValue;
+
+ // exclude non-string keys in maps
+ QTest::newRow("excluded-map-unsigned") << raw("\xa1\x00\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
+ QTest::newRow("excluded-map-negative") << raw("\xa1\x20\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
+ QTest::newRow("excluded-map-bytearray") << raw("\xa1\x40\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
+ QTest::newRow("map-string") << raw("\xa1\x60\1") << int(CborValidateMapKeysAreString) << CborNoError;
+ QTest::newRow("map-tag-0-string") << raw("\xa1\xc0\x60\1") << int(CborValidateMapKeysAreString) << CborNoError;
+ QTest::newRow("excluded-map-array") << raw("\xa1\x80\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
+ QTest::newRow("excluded-map-map") << raw("\xa1\xa0\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
+ QTest::newRow("excluded-map-simple-0") << raw("\xa1\xe0\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
+ QTest::newRow("excluded-map-false") << raw("\xa1\xf4\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
+ QTest::newRow("excluded-map-true") << raw("\xa1\xf5\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
+ QTest::newRow("excluded-map-null") << raw("\xa1\xf6\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
+ QTest::newRow("excluded-map-undefined") << raw("\xa1\xf7\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
+ QTest::newRow("excluded-map-half") << raw("\xa1\xf9\0\0\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
+ QTest::newRow("excluded-map-float") << raw("\xa1\xfa\0\0\0\0\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
+ QTest::newRow("excluded-map-double") << raw("\xa1\xfb\0\0\0\0\0\0\0\0\1") << int(CborValidateMapKeysAreString) << CborErrorMapKeyNotString;
+
+ // unknown simple types
+ QTest::newRow("unknown-simple-type-0") << raw("\xe0") << int(CborValidateNoUnknownSimpleTypes) << CborErrorUnknownSimpleType;
+ QTest::newRow("unknown-simple-type-32") << raw("\xf8\x20") << int(CborValidateNoUnknownSimpleTypes) << CborErrorUnknownSimpleType;
+ QTest::newRow("allowed-simple-type-32") << raw("\xf8\x20") << int(CborValidateNoUnknownSimpleTypesSA) << CborNoError;
+
+ // unknown tags
+ QTest::newRow("unknown-tag-6") << raw("\xc6\x60") << int(CborValidateNoUnknownTags) << CborErrorUnknownTag;
+ QTest::newRow("unknown-tag-31") << raw("\xd8\x1f\x60") << int(CborValidateNoUnknownTags) << CborErrorUnknownTag;
+ QTest::newRow("unknown-tag-256") << raw("\xd9\1\0\x60") << int(CborValidateNoUnknownTags) << CborErrorUnknownTag;
+ QTest::newRow("unknown-tag-65536") << raw("\xda\0\1\0\0\x60") << int(CborValidateNoUnknownTags) << CborErrorUnknownTag;
+ QTest::newRow("unknown-tag-4294967296") << raw("\xdb\0\0\0\1\0\0\0\0\x60") << int(CborValidateNoUnknownTags) << CborErrorUnknownTag;
+ QTest::newRow("allowed-tag-31") << raw("\xd8\x1f\x60") << int(CborValidateNoUnknownTagsSA) << CborNoError;
+ QTest::newRow("allowed-tag-256") << raw("\xd9\1\0\x60") << int(CborValidateNoUnknownTagsSR) << CborNoError;
+
+ // excluded tags
+ QTest::newRow("excluded-tag-0") << raw("\xc0\x60") << int(CborValidateNoTags) << CborErrorExcludedType;
+ QTest::newRow("excluded-tag-24") << raw("\xd8\x18\x40") << int(CborValidateNoTags) << CborErrorExcludedType;
+ QTest::newRow("excluded-tag-55799") << raw("\xd9\xd9\xf7\x60") << int(CborValidateNoTags) << CborErrorExcludedType;
+
+ // complete data
+ QTest::newRow("garbage-data-0") << raw("\0\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
+ QTest::newRow("garbage-data-1") << raw("\x20\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
+ QTest::newRow("garbage-data-2") << raw("\x40\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
+ QTest::newRow("garbage-data-3") << raw("\x60\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
+ QTest::newRow("garbage-data-4") << raw("\x80\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
+ QTest::newRow("garbage-data-5") << raw("\xa0\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
+ QTest::newRow("garbage-data-6") << raw("\xc0\x60\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
+ QTest::newRow("garbage-data-7") << raw("\xf4\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
+ QTest::newRow("garbage-data-f16") << raw("\xf9\0\0\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
+ QTest::newRow("garbage-data-f32") << raw("\xfa\0\0\0\0\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
+ QTest::newRow("garbage-data-f64") << raw("\xfb\0\0\0\0\0\0\0\0\1") << int(CborValidateCompleteData) << CborErrorGarbageAtEnd;
+}
+
+void tst_Parser::strictValidation()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(int, flags);
+ QFETCH(CborError, expectedError);
+
+ QString decoded;
+ CborParser parser;
+ CborValue first;
+ CborError err = cbor_parser_init(reinterpret_cast<const quint8 *>(data.constData()), data.length(), 0, &parser, &first);
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+
+ err = cbor_value_validate(&first, flags);
+ QCOMPARE(err, expectedError);
+}
+
+void tst_Parser::incompleteData_data()
+{
+ addColumns();
+ addFixedData();
+ addStringsData();
+ addTagsData();
+ addMapMixedData();
+}
+
+void tst_Parser::incompleteData()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+
+ for (int len = 0; len < data.length() - 1; ++len) {
+ CborParser parser;
+ CborValue first;
+ CborError err = cbor_parser_init(reinterpret_cast<const quint8 *>(data.constData()), len, 0, &parser, &first);
+ if (!err) {
+ QString decoded;
+ err = parseOne(&first, &decoded);
+ }
+ if (err != CborErrorUnexpectedEOF)
+ qDebug() << "Length is" << len;
+ QCOMPARE(err, CborErrorUnexpectedEOF);
+ }
+}
+
+void tst_Parser::endPointer_data()
+{
+ QTest::addColumn<QByteArray>("data");
+ QTest::addColumn<int>("offset");
+
+ QTest::newRow("number1") << raw("\x81\x01\x01") << 2;
+ QTest::newRow("number24") << raw("\x81\x18\x18\x01") << 3;
+ QTest::newRow("string") << raw("\x81\x61Z\x01") << 3;
+ QTest::newRow("indefinite-string") << raw("\x81\x7f\x61Z\xff\x01") << 5;
+ QTest::newRow("array") << raw("\x81\x02\x01") << 2;
+ QTest::newRow("indefinite-array") << raw("\x81\x9f\x02\xff\x01") << 4;
+ QTest::newRow("object") << raw("\x81\xa1\x03\x02\x01") << 4;
+ QTest::newRow("indefinite-object") << raw("\x81\xbf\x03\x02\xff\x01") << 5;
+}
+
+void tst_Parser::endPointer()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(int, offset);
+
+ QString decoded;
+ CborParser parser;
+ CborValue first;
+ CborError err = cbor_parser_init(reinterpret_cast<const quint8 *>(data.constData()), data.length(), 0, &parser, &first);
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+
+ err = parseOne(&first, &decoded);
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+ QCOMPARE(int(cbor_value_get_next_byte(&first) - reinterpret_cast<const quint8 *>(data.constBegin())), offset);
+}
+
+void tst_Parser::recursionLimit_data()
+{
+ static const int recursions = CBOR_PARSER_MAX_RECURSIONS + 2;
+ QTest::addColumn<QByteArray>("data");
+
+ QTest::newRow("array") << QByteArray(recursions, '\x81') + '\x20';
+ QTest::newRow("_array") << QByteArray(recursions, '\x9f') + '\x20' + QByteArray(recursions, '\xff');
+
+ QByteArray data;
+ for (int i = 0; i < recursions; ++i)
+ data += "\xa1\x65Hello";
+ data += '\2';
+ QTest::newRow("map-recursive-values") << data;
+
+ data.clear();
+ for (int i = 0; i < recursions; ++i)
+ data += "\xbf\x65World";
+ data += '\2';
+ for (int i = 0; i < recursions; ++i)
+ data += "\xff";
+ QTest::newRow("_map-recursive-values") << data;
+
+ data = QByteArray(recursions, '\xa1');
+ data += '\2';
+ for (int i = 0; i < recursions; ++i)
+ data += "\x7f\x64quux\xff";
+ QTest::newRow("map-recursive-keys") << data;
+
+ data = QByteArray(recursions, '\xbf');
+ data += '\2';
+ for (int i = 0; i < recursions; ++i)
+ data += "\1\xff";
+ QTest::newRow("_map-recursive-keys") << data;
+
+ data.clear();
+ for (int i = 0; i < recursions / 2; ++i)
+ data += "\x81\xa1\1";
+ data += '\2';
+ QTest::newRow("mixed") << data;
+}
+
+void tst_Parser::recursionLimit()
+{
+ QFETCH(QByteArray, data);
+
+ CborParser parser;
+ CborValue first;
+ CborError err = cbor_parser_init(reinterpret_cast<const quint8 *>(data.constData()), data.length(), 0, &parser, &first);
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+
+ // check that it is valid:
+ CborValue it = first;
+ {
+ QString dummy;
+ err = parseOne(&it, &dummy);
+ QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
+ }
+
+ it = first;
+ err = cbor_value_advance(&it);
+ QCOMPARE(err, CborErrorNestingTooDeep);
+
+ it = first;
+ if (cbor_value_is_map(&it)) {
+ CborValue dummy;
+ err = cbor_value_map_find_value(&it, "foo", &dummy);
+ QCOMPARE(err, CborErrorNestingTooDeep);
+ }
+}
+
+QTEST_MAIN(tst_Parser)
+#include "tst_parser.moc"
diff --git a/src/3rdparty/wasm/DEJAVU-LICENSE b/src/3rdparty/wasm/DEJAVU-LICENSE
new file mode 100644
index 0000000000..df52c1709b
--- /dev/null
+++ b/src/3rdparty/wasm/DEJAVU-LICENSE
@@ -0,0 +1,187 @@
+Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
+Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below)
+
+
+Bitstream Vera Fonts Copyright
+------------------------------
+
+Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
+a trademark of Bitstream, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of the fonts accompanying this license ("Fonts") and associated
+documentation files (the "Font Software"), to reproduce and distribute the
+Font Software, including without limitation the rights to use, copy, merge,
+publish, distribute, and/or sell copies of the Font Software, and to permit
+persons to whom the Font Software is furnished to do so, subject to the
+following conditions:
+
+The above copyright and trademark notices and this permission notice shall
+be included in all copies of one or more of the Font Software typefaces.
+
+The Font Software may be modified, altered, or added to, and in particular
+the designs of glyphs or characters in the Fonts may be modified and
+additional glyphs or characters may be added to the Fonts, only if the fonts
+are renamed to names not containing either the words "Bitstream" or the word
+"Vera".
+
+This License becomes null and void to the extent applicable to Fonts or Font
+Software that has been modified and is distributed under the "Bitstream
+Vera" names.
+
+The Font Software may be sold as part of a larger software package but no
+copy of one or more of the Font Software typefaces may be sold by itself.
+
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
+TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
+FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
+ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
+FONT SOFTWARE.
+
+Except as contained in this notice, the names of Gnome, the Gnome
+Foundation, and Bitstream Inc., shall not be used in advertising or
+otherwise to promote the sale, use or other dealings in this Font Software
+without prior written authorization from the Gnome Foundation or Bitstream
+Inc., respectively. For further information, contact: fonts at gnome dot
+org.
+
+Arev Fonts Copyright
+------------------------------
+
+Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the fonts accompanying this license ("Fonts") and
+associated documentation files (the "Font Software"), to reproduce
+and distribute the modifications to the Bitstream Vera Font Software,
+including without limitation the rights to use, copy, merge, publish,
+distribute, and/or sell copies of the Font Software, and to permit
+persons to whom the Font Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright and trademark notices and this permission notice
+shall be included in all copies of one or more of the Font Software
+typefaces.
+
+The Font Software may be modified, altered, or added to, and in
+particular the designs of glyphs or characters in the Fonts may be
+modified and additional glyphs or characters may be added to the
+Fonts, only if the fonts are renamed to names not containing either
+the words "Tavmjong Bah" or the word "Arev".
+
+This License becomes null and void to the extent applicable to Fonts
+or Font Software that has been modified and is distributed under the
+"Tavmjong Bah Arev" names.
+
+The Font Software may be sold as part of a larger software package but
+no copy of one or more of the Font Software typefaces may be sold by
+itself.
+
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
+TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
+
+Except as contained in this notice, the name of Tavmjong Bah shall not
+be used in advertising or otherwise to promote the sale, use or other
+dealings in this Font Software without prior written authorization
+from Tavmjong Bah. For further information, contact: tavmjong @ free
+. fr.
+
+TeX Gyre DJV Math
+-----------------
+Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
+
+Math extensions done by B. Jackowski, P. Strzelczyk and P. Pianowski
+(on behalf of TeX users groups) are in public domain.
+
+Letters imported from Euler Fraktur from AMSfonts are (c) American
+Mathematical Society (see below).
+Bitstream Vera Fonts Copyright
+Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera
+is a trademark of Bitstream, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of the fonts accompanying this license (“Fontsâ€) and associated
+documentation
+files (the “Font Softwareâ€), to reproduce and distribute the Font Software,
+including without limitation the rights to use, copy, merge, publish,
+distribute,
+and/or sell copies of the Font Software, and to permit persons to whom
+the Font Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright and trademark notices and this permission notice
+shall be
+included in all copies of one or more of the Font Software typefaces.
+
+The Font Software may be modified, altered, or added to, and in particular
+the designs of glyphs or characters in the Fonts may be modified and
+additional
+glyphs or characters may be added to the Fonts, only if the fonts are
+renamed
+to names not containing either the words “Bitstream†or the word “Veraâ€.
+
+This License becomes null and void to the extent applicable to Fonts or
+Font Software
+that has been modified and is distributed under the “Bitstream Veraâ€
+names.
+
+The Font Software may be sold as part of a larger software package but
+no copy
+of one or more of the Font Software typefaces may be sold by itself.
+
+THE FONT SOFTWARE IS PROVIDED “AS ISâ€, WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
+TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
+FOUNDATION
+BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL,
+SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN
+ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR
+INABILITY TO USE
+THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
+Except as contained in this notice, the names of GNOME, the GNOME
+Foundation,
+and Bitstream Inc., shall not be used in advertising or otherwise to promote
+the sale, use or other dealings in this Font Software without prior written
+authorization from the GNOME Foundation or Bitstream Inc., respectively.
+For further information, contact: fonts at gnome dot org.
+
+AMSFonts (v. 2.2) copyright
+
+The PostScript Type 1 implementation of the AMSFonts produced by and
+previously distributed by Blue Sky Research and Y&Y, Inc. are now freely
+available for general use. This has been accomplished through the
+cooperation
+of a consortium of scientific publishers with Blue Sky Research and Y&Y.
+Members of this consortium include:
+
+Elsevier Science IBM Corporation Society for Industrial and Applied
+Mathematics (SIAM) Springer-Verlag American Mathematical Society (AMS)
+
+In order to assure the authenticity of these fonts, copyright will be
+held by
+the American Mathematical Society. This is not meant to restrict in any way
+the legitimate use of the fonts, such as (but not limited to) electronic
+distribution of documents containing these fonts, inclusion of these fonts
+into other public domain or commercial font collections or computer
+applications, use of the outline data to create derivative fonts and/or
+faces, etc. However, the AMS does require that the AMS copyright notice be
+removed from any derivative versions of the fonts which have been altered in
+any way. In addition, to ensure the fidelity of TeX documents using Computer
+Modern fonts, Professor Donald Knuth, creator of the Computer Modern faces,
+has requested that any alterations which yield different font metrics be
+given a different name.
+
+$Id$
diff --git a/src/3rdparty/wasm/DejaVuSans.ttf b/src/3rdparty/wasm/DejaVuSans.ttf
new file mode 100644
index 0000000000..7e411a71be
--- /dev/null
+++ b/src/3rdparty/wasm/DejaVuSans.ttf
Binary files differ
diff --git a/src/3rdparty/wasm/VERA-LICENSE b/src/3rdparty/wasm/VERA-LICENSE
new file mode 100644
index 0000000000..4f9e8544b7
--- /dev/null
+++ b/src/3rdparty/wasm/VERA-LICENSE
@@ -0,0 +1,15 @@
+Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license (“Fontsâ€) and associated documentation files (the “Font Softwareâ€), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions:
+
+The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces.
+
+The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words “Bitstream†or the word “Veraâ€.
+
+This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the “Bitstream Vera†names.
+
+The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself.
+
+THE FONT SOFTWARE IS PROVIDED “AS ISâ€, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
+
+Except as contained in this notice, the names of GNOME, the GNOME Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the GNOME Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org.
diff --git a/src/3rdparty/wasm/Vera.ttf b/src/3rdparty/wasm/Vera.ttf
new file mode 100644
index 0000000000..58cd6b5e61
--- /dev/null
+++ b/src/3rdparty/wasm/Vera.ttf
Binary files differ
diff --git a/src/3rdparty/wasm/qt_attribution.json b/src/3rdparty/wasm/qt_attribution.json
new file mode 100644
index 0000000000..5d89e4adfa
--- /dev/null
+++ b/src/3rdparty/wasm/qt_attribution.json
@@ -0,0 +1,33 @@
+[
+{
+ "Id": "vera_font",
+ "Name": "Bitstream Vera Font",
+ "QDocModule": "qtgui",
+ "QtUsage": "Used for WebAssembly platform.",
+ "Files": "Vera.ttf",
+ "Description": "Vera is a group typeface (font) with a liberal license.",
+
+ "Homepage": "https://www.gnome.org/fonts/",
+ "Version": "1.10",
+ "DownloadLocation": "http://ftp.gnome.org/pub/GNOME/sources/ttf-bitstream-vera/1.10/ttf-bitstream-vera-1.10.tar.bz2",
+ "License": "Bitstream Vera Font License",
+ "LicenseId": "bitstream-vera",
+ "LicenseFile": "VERA-LICENSE",
+ "Copyright": "Copyright (C) 2003 Bitstream,Inc"
+},
+{
+ "Id": "dejayvu",
+ "Name": "DejaVu Fonts",
+ "QDocModule": "qtgui",
+ "QtUsage": "Used for WebAssembly platform.",
+ "Files": "DejaVuSans.ttf",
+ "Description": "The DejaVu fonts are a font family based on the Vera Fonts.",
+
+ "Homepage": "https://dejavu-fonts.github.io/",
+ "License": "Bitstream Vera Font License",
+ "LicenseFile": "DEJAVU-LICENSE",
+ "Copyright": "Copyright (C) 2003 Bitstream,Inc
+Copyright (c) 2006 by Tavmjong Bah
+(c) American Mathematical Society"
+}
+] \ No newline at end of file
diff --git a/src/3rdparty/xcb/README b/src/3rdparty/xcb/README
index d7c8eba294..9e8ea30b51 100644
--- a/src/3rdparty/xcb/README
+++ b/src/3rdparty/xcb/README
@@ -1,15 +1,19 @@
Contains the header and sources files from selected xcb libraries:
- libxcb-1.5 together with xcb-proto-1.6 (sync, xfixes, randr, xinerama sources)
+ libxcb-1.9.1 together with xcb-proto-1.8 (randr, render, shape, shm, sync,
+ xfixes, xinerama sources)
# libxkbcommon-x11 requires libxcb-xkb >= 1.10
libxcb-1.10 together with xcb-proto-1.10 (xkb sources)
+ libxcb-1.13 together with xcb-proto-1.13 (xinput sources with removed
+ Pointer Barriers API and SendExtensionEvent API)
libxcb-util-image-0.3.9
libxcb-util-keysyms-0.3.9
libxcb-util-renderutil-0.3.8
libxcb-util-wm-0.3.9
The 'include' directory was obtained by compiling and installing all of the modules.
-They have been tested to run also with libxcb 1.5 (the oldest version we support).
+When upgrading the bundled xcb headers, they must be tested to run also with the
+minimal supported libxcb version, which currently is 1.9.1.
Use the -qt-xcb configure option to use the files instead of system xcb libraries.
See src/plugins/platforms/xcb/README for details.
diff --git a/src/3rdparty/xcb/include/xcb/randr.h b/src/3rdparty/xcb/include/xcb/randr.h
index 1035c4043c..4f4f2104cf 100644
--- a/src/3rdparty/xcb/include/xcb/randr.h
+++ b/src/3rdparty/xcb/include/xcb/randr.h
@@ -1379,6 +1379,9 @@ xcb_randr_screen_size_next (xcb_randr_screen_size_iterator_t *i /**< */);
xcb_generic_iterator_t
xcb_randr_screen_size_end (xcb_randr_screen_size_iterator_t i /**< */);
+int
+xcb_randr_refresh_rates_sizeof (const void *_buffer /**< */);
+
/*****************************************************************************
**
@@ -1462,7 +1465,7 @@ xcb_generic_iterator_t
xcb_randr_refresh_rates_end (xcb_randr_refresh_rates_iterator_t i /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1487,7 +1490,7 @@ xcb_randr_query_version (xcb_connection_t *c /**< */,
uint32_t minor_version /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1546,7 +1549,7 @@ xcb_randr_query_version_reply (xcb_connection_t *c /**< */,
xcb_generic_error_t **e /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1579,7 +1582,7 @@ xcb_randr_set_screen_config (xcb_connection_t *c /**< */,
uint16_t rate /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1646,7 +1649,7 @@ xcb_randr_set_screen_config_reply (xcb_connection_t *c /**
xcb_generic_error_t **e /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1674,7 +1677,7 @@ xcb_randr_select_input_checked (xcb_connection_t *c /**< */,
uint16_t enable /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1698,8 +1701,11 @@ xcb_randr_select_input (xcb_connection_t *c /**< */,
xcb_window_t window /**< */,
uint16_t enable /**< */);
+int
+xcb_randr_get_screen_info_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1722,7 +1728,7 @@ xcb_randr_get_screen_info (xcb_connection_t *c /**< */,
xcb_window_t window /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1844,7 +1850,7 @@ xcb_randr_get_screen_info_reply (xcb_connection_t *c /**< */
xcb_generic_error_t **e /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1867,7 +1873,7 @@ xcb_randr_get_screen_size_range (xcb_connection_t *c /**< */,
xcb_window_t window /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1924,7 +1930,7 @@ xcb_randr_get_screen_size_range_reply (xcb_connection_t
xcb_generic_error_t **e /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1958,7 +1964,7 @@ xcb_randr_set_screen_size_checked (xcb_connection_t *c /**< */,
uint32_t mm_height /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2031,8 +2037,11 @@ xcb_randr_mode_info_next (xcb_randr_mode_info_iterator_t *i /**< */);
xcb_generic_iterator_t
xcb_randr_mode_info_end (xcb_randr_mode_info_iterator_t i /**< */);
+int
+xcb_randr_get_screen_resources_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2055,7 +2064,7 @@ xcb_randr_get_screen_resources (xcb_connection_t *c /**< */,
xcb_window_t window /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2267,8 +2276,11 @@ xcb_randr_get_screen_resources_reply (xcb_connection_t *
xcb_randr_get_screen_resources_cookie_t cookie /**< */,
xcb_generic_error_t **e /**< */);
+int
+xcb_randr_get_output_info_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2293,7 +2305,7 @@ xcb_randr_get_output_info (xcb_connection_t *c /**< */,
xcb_timestamp_t config_timestamp /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2507,8 +2519,11 @@ xcb_randr_get_output_info_reply (xcb_connection_t *c /**< */
xcb_randr_get_output_info_cookie_t cookie /**< */,
xcb_generic_error_t **e /**< */);
+int
+xcb_randr_list_output_properties_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2531,7 +2546,7 @@ xcb_randr_list_output_properties (xcb_connection_t *c /**< */,
xcb_randr_output_t output /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2626,8 +2641,11 @@ xcb_randr_list_output_properties_reply (xcb_connection_t
xcb_randr_list_output_properties_cookie_t cookie /**< */,
xcb_generic_error_t **e /**< */);
+int
+xcb_randr_query_output_property_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2652,7 +2670,7 @@ xcb_randr_query_output_property (xcb_connection_t *c /**< */,
xcb_atom_t property /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2749,8 +2767,12 @@ xcb_randr_query_output_property_reply (xcb_connection_t
xcb_randr_query_output_property_cookie_t cookie /**< */,
xcb_generic_error_t **e /**< */);
+int
+xcb_randr_configure_output_property_sizeof (const void *_buffer /**< */,
+ uint32_t values_len /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2786,7 +2808,7 @@ xcb_randr_configure_output_property_checked (xcb_connection_t *c /**< */,
const int32_t *values /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2818,8 +2840,11 @@ xcb_randr_configure_output_property (xcb_connection_t *c /**< */,
uint32_t values_len /**< */,
const int32_t *values /**< */);
+int
+xcb_randr_change_output_property_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2857,7 +2882,7 @@ xcb_randr_change_output_property_checked (xcb_connection_t *c /**< */,
const void *data /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2892,7 +2917,7 @@ xcb_randr_change_output_property (xcb_connection_t *c /**< */,
const void *data /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2920,7 +2945,7 @@ xcb_randr_delete_output_property_checked (xcb_connection_t *c /**< */,
xcb_atom_t property /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2944,8 +2969,11 @@ xcb_randr_delete_output_property (xcb_connection_t *c /**< */,
xcb_randr_output_t output /**< */,
xcb_atom_t property /**< */);
+int
+xcb_randr_get_output_property_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2980,7 +3008,7 @@ xcb_randr_get_output_property (xcb_connection_t *c /**< */,
uint8_t pending /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3087,8 +3115,12 @@ xcb_randr_get_output_property_reply (xcb_connection_t *c
xcb_randr_get_output_property_cookie_t cookie /**< */,
xcb_generic_error_t **e /**< */);
+int
+xcb_randr_create_mode_sizeof (const void *_buffer /**< */,
+ uint32_t name_len /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3117,7 +3149,7 @@ xcb_randr_create_mode (xcb_connection_t *c /**< */,
const char *name /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3180,7 +3212,7 @@ xcb_randr_create_mode_reply (xcb_connection_t *c /**< */,
xcb_generic_error_t **e /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3206,7 +3238,7 @@ xcb_randr_destroy_mode_checked (xcb_connection_t *c /**< */,
xcb_randr_mode_t mode /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3229,7 +3261,7 @@ xcb_randr_destroy_mode (xcb_connection_t *c /**< */,
xcb_randr_mode_t mode /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3257,7 +3289,7 @@ xcb_randr_add_output_mode_checked (xcb_connection_t *c /**< */,
xcb_randr_mode_t mode /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3282,7 +3314,7 @@ xcb_randr_add_output_mode (xcb_connection_t *c /**< */,
xcb_randr_mode_t mode /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3310,7 +3342,7 @@ xcb_randr_delete_output_mode_checked (xcb_connection_t *c /**< */,
xcb_randr_mode_t mode /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3334,8 +3366,11 @@ xcb_randr_delete_output_mode (xcb_connection_t *c /**< */,
xcb_randr_output_t output /**< */,
xcb_randr_mode_t mode /**< */);
+int
+xcb_randr_get_crtc_info_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3360,7 +3395,7 @@ xcb_randr_get_crtc_info (xcb_connection_t *c /**< */,
xcb_timestamp_t config_timestamp /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3496,8 +3531,12 @@ xcb_randr_get_crtc_info_reply (xcb_connection_t *c /**< */,
xcb_randr_get_crtc_info_cookie_t cookie /**< */,
xcb_generic_error_t **e /**< */);
+int
+xcb_randr_set_crtc_config_sizeof (const void *_buffer /**< */,
+ uint32_t outputs_len /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3536,7 +3575,7 @@ xcb_randr_set_crtc_config (xcb_connection_t *c /**< */,
const xcb_randr_output_t *outputs /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3609,7 +3648,7 @@ xcb_randr_set_crtc_config_reply (xcb_connection_t *c /**< */
xcb_generic_error_t **e /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3632,7 +3671,7 @@ xcb_randr_get_crtc_gamma_size (xcb_connection_t *c /**< */,
xcb_randr_crtc_t crtc /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3688,8 +3727,11 @@ xcb_randr_get_crtc_gamma_size_reply (xcb_connection_t *c
xcb_randr_get_crtc_gamma_size_cookie_t cookie /**< */,
xcb_generic_error_t **e /**< */);
+int
+xcb_randr_get_crtc_gamma_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3712,7 +3754,7 @@ xcb_randr_get_crtc_gamma (xcb_connection_t *c /**< */,
xcb_randr_crtc_t crtc /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3885,8 +3927,11 @@ xcb_randr_get_crtc_gamma_reply (xcb_connection_t *c /**< */,
xcb_randr_get_crtc_gamma_cookie_t cookie /**< */,
xcb_generic_error_t **e /**< */);
+int
+xcb_randr_set_crtc_gamma_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3920,7 +3965,7 @@ xcb_randr_set_crtc_gamma_checked (xcb_connection_t *c /**< */,
const uint16_t *blue /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3950,8 +3995,11 @@ xcb_randr_set_crtc_gamma (xcb_connection_t *c /**< */,
const uint16_t *green /**< */,
const uint16_t *blue /**< */);
+int
+xcb_randr_get_screen_resources_current_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3974,7 +4022,7 @@ xcb_randr_get_screen_resources_current (xcb_connection_t *c /**< */,
xcb_window_t window /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -4186,8 +4234,12 @@ xcb_randr_get_screen_resources_current_reply (xcb_connection_t
xcb_randr_get_screen_resources_current_cookie_t cookie /**< */,
xcb_generic_error_t **e /**< */);
+int
+xcb_randr_set_crtc_transform_sizeof (const void *_buffer /**< */,
+ uint32_t filter_params_len /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -4223,7 +4275,7 @@ xcb_randr_set_crtc_transform_checked (xcb_connection_t *c /**< */,
const xcb_render_fixed_t *filter_params /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -4255,8 +4307,11 @@ xcb_randr_set_crtc_transform (xcb_connection_t *c /**< */,
uint32_t filter_params_len /**< */,
const xcb_render_fixed_t *filter_params /**< */);
+int
+xcb_randr_get_crtc_transform_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -4279,7 +4334,7 @@ xcb_randr_get_crtc_transform (xcb_connection_t *c /**< */,
xcb_randr_crtc_t crtc /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -4492,7 +4547,7 @@ xcb_randr_get_crtc_transform_reply (xcb_connection_t *c /
xcb_generic_error_t **e /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -4515,7 +4570,7 @@ xcb_randr_get_panning (xcb_connection_t *c /**< */,
xcb_randr_crtc_t crtc /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -4572,7 +4627,7 @@ xcb_randr_get_panning_reply (xcb_connection_t *c /**< */,
xcb_generic_error_t **e /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -4621,7 +4676,7 @@ xcb_randr_set_panning (xcb_connection_t *c /**< */,
int16_t border_bottom /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -4704,7 +4759,7 @@ xcb_randr_set_panning_reply (xcb_connection_t *c /**< */,
xcb_generic_error_t **e /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -4732,7 +4787,7 @@ xcb_randr_set_output_primary_checked (xcb_connection_t *c /**< */,
xcb_randr_output_t output /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -4757,7 +4812,7 @@ xcb_randr_set_output_primary (xcb_connection_t *c /**< */,
xcb_randr_output_t output /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -4780,7 +4835,7 @@ xcb_randr_get_output_primary (xcb_connection_t *c /**< */,
xcb_window_t window /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
diff --git a/src/3rdparty/xcb/include/xcb/render.h b/src/3rdparty/xcb/include/xcb/render.h
index 0f96ca1fbc..eb7f0424d5 100644
--- a/src/3rdparty/xcb/include/xcb/render.h
+++ b/src/3rdparty/xcb/include/xcb/render.h
@@ -20,7 +20,7 @@ extern "C" {
#endif
#define XCB_RENDER_MAJOR_VERSION 0
-#define XCB_RENDER_MINOR_VERSION 10
+#define XCB_RENDER_MINOR_VERSION 11
extern xcb_extension_t xcb_render_id;
@@ -71,7 +71,22 @@ typedef enum xcb_render_pict_op_t {
XCB_RENDER_PICT_OP_CONJOINT_OUT_REVERSE,
XCB_RENDER_PICT_OP_CONJOINT_ATOP,
XCB_RENDER_PICT_OP_CONJOINT_ATOP_REVERSE,
- XCB_RENDER_PICT_OP_CONJOINT_XOR
+ XCB_RENDER_PICT_OP_CONJOINT_XOR,
+ XCB_RENDER_PICT_OP_MULTIPLY = 48,
+ XCB_RENDER_PICT_OP_SCREEN,
+ XCB_RENDER_PICT_OP_OVERLAY,
+ XCB_RENDER_PICT_OP_DARKEN,
+ XCB_RENDER_PICT_OP_LIGHTEN,
+ XCB_RENDER_PICT_OP_COLOR_DODGE,
+ XCB_RENDER_PICT_OP_COLOR_BURN,
+ XCB_RENDER_PICT_OP_HARD_LIGHT,
+ XCB_RENDER_PICT_OP_SOFT_LIGHT,
+ XCB_RENDER_PICT_OP_DIFFERENCE,
+ XCB_RENDER_PICT_OP_EXCLUSION,
+ XCB_RENDER_PICT_OP_HSL_HUE,
+ XCB_RENDER_PICT_OP_HSL_SATURATION,
+ XCB_RENDER_PICT_OP_HSL_COLOR,
+ XCB_RENDER_PICT_OP_HSL_LUMINOSITY
} xcb_render_pict_op_t;
typedef enum xcb_render_poly_edge_t {
@@ -1453,6 +1468,9 @@ xcb_render_pictvisual_next (xcb_render_pictvisual_iterator_t *i /**< */);
xcb_generic_iterator_t
xcb_render_pictvisual_end (xcb_render_pictvisual_iterator_t i /**< */);
+int
+xcb_render_pictdepth_sizeof (const void *_buffer /**< */);
+
/*****************************************************************************
**
@@ -1535,6 +1553,9 @@ xcb_render_pictdepth_next (xcb_render_pictdepth_iterator_t *i /**< */);
xcb_generic_iterator_t
xcb_render_pictdepth_end (xcb_render_pictdepth_iterator_t i /**< */);
+int
+xcb_render_pictscreen_sizeof (const void *_buffer /**< */);
+
/*****************************************************************************
**
@@ -1906,7 +1927,7 @@ xcb_generic_iterator_t
xcb_render_glyphinfo_end (xcb_render_glyphinfo_iterator_t i /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1931,7 +1952,7 @@ xcb_render_query_version (xcb_connection_t *c /**< */,
uint32_t client_minor_version /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1989,8 +2010,11 @@ xcb_render_query_version_reply (xcb_connection_t *c /**< */,
xcb_render_query_version_cookie_t cookie /**< */,
xcb_generic_error_t **e /**< */);
+int
+xcb_render_query_pict_formats_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2011,7 +2035,7 @@ xcb_render_query_pict_formats_cookie_t
xcb_render_query_pict_formats (xcb_connection_t *c /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2169,8 +2193,11 @@ xcb_render_query_pict_formats_reply (xcb_connection_t *c
xcb_render_query_pict_formats_cookie_t cookie /**< */,
xcb_generic_error_t **e /**< */);
+int
+xcb_render_query_pict_index_values_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2193,7 +2220,7 @@ xcb_render_query_pict_index_values (xcb_connection_t *c /**< */,
xcb_render_pictformat_t format /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2288,8 +2315,11 @@ xcb_render_query_pict_index_values_reply (xcb_connection_t
xcb_render_query_pict_index_values_cookie_t cookie /**< */,
xcb_generic_error_t **e /**< */);
+int
+xcb_render_create_picture_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2323,7 +2353,7 @@ xcb_render_create_picture_checked (xcb_connection_t *c /**< */,
const uint32_t *value_list /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2353,8 +2383,11 @@ xcb_render_create_picture (xcb_connection_t *c /**< */,
uint32_t value_mask /**< */,
const uint32_t *value_list /**< */);
+int
+xcb_render_change_picture_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2384,7 +2417,7 @@ xcb_render_change_picture_checked (xcb_connection_t *c /**< */,
const uint32_t *value_list /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2410,8 +2443,12 @@ xcb_render_change_picture (xcb_connection_t *c /**< */,
uint32_t value_mask /**< */,
const uint32_t *value_list /**< */);
+int
+xcb_render_set_picture_clip_rectangles_sizeof (const void *_buffer /**< */,
+ uint32_t rectangles_len /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2445,7 +2482,7 @@ xcb_render_set_picture_clip_rectangles_checked (xcb_connection_t *c /**< *
const xcb_rectangle_t *rectangles /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2476,7 +2513,7 @@ xcb_render_set_picture_clip_rectangles (xcb_connection_t *c /**< */,
const xcb_rectangle_t *rectangles /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2502,7 +2539,7 @@ xcb_render_free_picture_checked (xcb_connection_t *c /**< */,
xcb_render_picture_t picture /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2525,7 +2562,7 @@ xcb_render_free_picture (xcb_connection_t *c /**< */,
xcb_render_picture_t picture /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2573,7 +2610,7 @@ xcb_render_composite_checked (xcb_connection_t *c /**< */,
uint16_t height /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2617,8 +2654,12 @@ xcb_render_composite (xcb_connection_t *c /**< */,
uint16_t width /**< */,
uint16_t height /**< */);
+int
+xcb_render_trapezoids_sizeof (const void *_buffer /**< */,
+ uint32_t traps_len /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2658,7 +2699,7 @@ xcb_render_trapezoids_checked (xcb_connection_t *c /**< */,
const xcb_render_trapezoid_t *traps /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2694,8 +2735,12 @@ xcb_render_trapezoids (xcb_connection_t *c /**< */,
uint32_t traps_len /**< */,
const xcb_render_trapezoid_t *traps /**< */);
+int
+xcb_render_triangles_sizeof (const void *_buffer /**< */,
+ uint32_t triangles_len /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2735,7 +2780,7 @@ xcb_render_triangles_checked (xcb_connection_t *c /**< */,
const xcb_render_triangle_t *triangles /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2771,8 +2816,12 @@ xcb_render_triangles (xcb_connection_t *c /**< */,
uint32_t triangles_len /**< */,
const xcb_render_triangle_t *triangles /**< */);
+int
+xcb_render_tri_strip_sizeof (const void *_buffer /**< */,
+ uint32_t points_len /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2812,7 +2861,7 @@ xcb_render_tri_strip_checked (xcb_connection_t *c /**< */,
const xcb_render_pointfix_t *points /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2848,8 +2897,12 @@ xcb_render_tri_strip (xcb_connection_t *c /**< */,
uint32_t points_len /**< */,
const xcb_render_pointfix_t *points /**< */);
+int
+xcb_render_tri_fan_sizeof (const void *_buffer /**< */,
+ uint32_t points_len /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2889,7 +2942,7 @@ xcb_render_tri_fan_checked (xcb_connection_t *c /**< */,
const xcb_render_pointfix_t *points /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2926,7 +2979,7 @@ xcb_render_tri_fan (xcb_connection_t *c /**< */,
const xcb_render_pointfix_t *points /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2954,7 +3007,7 @@ xcb_render_create_glyph_set_checked (xcb_connection_t *c /**< */,
xcb_render_pictformat_t format /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2979,7 +3032,7 @@ xcb_render_create_glyph_set (xcb_connection_t *c /**< */,
xcb_render_pictformat_t format /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3007,7 +3060,7 @@ xcb_render_reference_glyph_set_checked (xcb_connection_t *c /**< */,
xcb_render_glyphset_t existing /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3032,7 +3085,7 @@ xcb_render_reference_glyph_set (xcb_connection_t *c /**< */,
xcb_render_glyphset_t existing /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3058,7 +3111,7 @@ xcb_render_free_glyph_set_checked (xcb_connection_t *c /**< */,
xcb_render_glyphset_t glyphset /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3080,8 +3133,12 @@ xcb_void_cookie_t
xcb_render_free_glyph_set (xcb_connection_t *c /**< */,
xcb_render_glyphset_t glyphset /**< */);
+int
+xcb_render_add_glyphs_sizeof (const void *_buffer /**< */,
+ uint32_t data_len /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3117,7 +3174,7 @@ xcb_render_add_glyphs_checked (xcb_connection_t *c /**< */,
const uint8_t *data /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3149,8 +3206,12 @@ xcb_render_add_glyphs (xcb_connection_t *c /**< */,
uint32_t data_len /**< */,
const uint8_t *data /**< */);
+int
+xcb_render_free_glyphs_sizeof (const void *_buffer /**< */,
+ uint32_t glyphs_len /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3180,7 +3241,7 @@ xcb_render_free_glyphs_checked (xcb_connection_t *c /**< */,
const xcb_render_glyph_t *glyphs /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3206,8 +3267,12 @@ xcb_render_free_glyphs (xcb_connection_t *c /**< */,
uint32_t glyphs_len /**< */,
const xcb_render_glyph_t *glyphs /**< */);
+int
+xcb_render_composite_glyphs_8_sizeof (const void *_buffer /**< */,
+ uint32_t glyphcmds_len /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3249,7 +3314,7 @@ xcb_render_composite_glyphs_8_checked (xcb_connection_t *c /**< */,
const uint8_t *glyphcmds /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3287,8 +3352,12 @@ xcb_render_composite_glyphs_8 (xcb_connection_t *c /**< */,
uint32_t glyphcmds_len /**< */,
const uint8_t *glyphcmds /**< */);
+int
+xcb_render_composite_glyphs_16_sizeof (const void *_buffer /**< */,
+ uint32_t glyphcmds_len /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3330,7 +3399,7 @@ xcb_render_composite_glyphs_16_checked (xcb_connection_t *c /**< */,
const uint8_t *glyphcmds /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3368,8 +3437,12 @@ xcb_render_composite_glyphs_16 (xcb_connection_t *c /**< */,
uint32_t glyphcmds_len /**< */,
const uint8_t *glyphcmds /**< */);
+int
+xcb_render_composite_glyphs_32_sizeof (const void *_buffer /**< */,
+ uint32_t glyphcmds_len /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3411,7 +3484,7 @@ xcb_render_composite_glyphs_32_checked (xcb_connection_t *c /**< */,
const uint8_t *glyphcmds /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3449,8 +3522,12 @@ xcb_render_composite_glyphs_32 (xcb_connection_t *c /**< */,
uint32_t glyphcmds_len /**< */,
const uint8_t *glyphcmds /**< */);
+int
+xcb_render_fill_rectangles_sizeof (const void *_buffer /**< */,
+ uint32_t rects_len /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3484,7 +3561,7 @@ xcb_render_fill_rectangles_checked (xcb_connection_t *c /**< */,
const xcb_rectangle_t *rects /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3515,7 +3592,7 @@ xcb_render_fill_rectangles (xcb_connection_t *c /**< */,
const xcb_rectangle_t *rects /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3547,7 +3624,7 @@ xcb_render_create_cursor_checked (xcb_connection_t *c /**< */,
uint16_t y /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3619,7 +3696,7 @@ xcb_generic_iterator_t
xcb_render_transform_end (xcb_render_transform_iterator_t i /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3647,7 +3724,7 @@ xcb_render_set_picture_transform_checked (xcb_connection_t *c /**< */,
xcb_render_transform_t transform /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3671,8 +3748,11 @@ xcb_render_set_picture_transform (xcb_connection_t *c /**< */,
xcb_render_picture_t picture /**< */,
xcb_render_transform_t transform /**< */);
+int
+xcb_render_query_filters_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3695,7 +3775,7 @@ xcb_render_query_filters (xcb_connection_t *c /**< */,
xcb_drawable_t drawable /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3816,8 +3896,12 @@ xcb_render_query_filters_reply (xcb_connection_t *c /**< */,
xcb_render_query_filters_cookie_t cookie /**< */,
xcb_generic_error_t **e /**< */);
+int
+xcb_render_set_picture_filter_sizeof (const void *_buffer /**< */,
+ uint32_t values_len /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3851,7 +3935,7 @@ xcb_render_set_picture_filter_checked (xcb_connection_t *c /**< */,
const xcb_render_fixed_t *values /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3924,8 +4008,12 @@ xcb_render_animcursorelt_next (xcb_render_animcursorelt_iterator_t *i /**< */);
xcb_generic_iterator_t
xcb_render_animcursorelt_end (xcb_render_animcursorelt_iterator_t i /**< */);
+int
+xcb_render_create_anim_cursor_sizeof (const void *_buffer /**< */,
+ uint32_t cursors_len /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -3955,7 +4043,7 @@ xcb_render_create_anim_cursor_checked (xcb_connection_t *c /**<
const xcb_render_animcursorelt_t *cursors /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -4067,8 +4155,12 @@ xcb_render_trap_next (xcb_render_trap_iterator_t *i /**< */);
xcb_generic_iterator_t
xcb_render_trap_end (xcb_render_trap_iterator_t i /**< */);
+int
+xcb_render_add_traps_sizeof (const void *_buffer /**< */,
+ uint32_t traps_len /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -4102,7 +4194,7 @@ xcb_render_add_traps_checked (xcb_connection_t *c /**< */,
const xcb_render_trap_t *traps /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -4133,7 +4225,7 @@ xcb_render_add_traps (xcb_connection_t *c /**< */,
const xcb_render_trap_t *traps /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -4161,7 +4253,7 @@ xcb_render_create_solid_fill_checked (xcb_connection_t *c /**< */,
xcb_render_color_t color /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -4185,8 +4277,11 @@ xcb_render_create_solid_fill (xcb_connection_t *c /**< */,
xcb_render_picture_t picture /**< */,
xcb_render_color_t color /**< */);
+int
+xcb_render_create_linear_gradient_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -4222,7 +4317,7 @@ xcb_render_create_linear_gradient_checked (xcb_connection_t *c /**< */,
const xcb_render_color_t *colors /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -4254,8 +4349,11 @@ xcb_render_create_linear_gradient (xcb_connection_t *c /**< */,
const xcb_render_fixed_t *stops /**< */,
const xcb_render_color_t *colors /**< */);
+int
+xcb_render_create_radial_gradient_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -4295,7 +4393,7 @@ xcb_render_create_radial_gradient_checked (xcb_connection_t *c /**< */,
const xcb_render_color_t *colors /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -4331,8 +4429,11 @@ xcb_render_create_radial_gradient (xcb_connection_t *c /**< */,
const xcb_render_fixed_t *stops /**< */,
const xcb_render_color_t *colors /**< */);
+int
+xcb_render_create_conical_gradient_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -4368,7 +4469,7 @@ xcb_render_create_conical_gradient_checked (xcb_connection_t *c /**< */
const xcb_render_color_t *colors /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
diff --git a/src/3rdparty/xcb/include/xcb/shape.h b/src/3rdparty/xcb/include/xcb/shape.h
index 107d2ff748..63919b42c7 100644
--- a/src/3rdparty/xcb/include/xcb/shape.h
+++ b/src/3rdparty/xcb/include/xcb/shape.h
@@ -393,7 +393,7 @@ xcb_generic_iterator_t
xcb_shape_kind_end (xcb_shape_kind_iterator_t i /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -414,7 +414,7 @@ xcb_shape_query_version_cookie_t
xcb_shape_query_version (xcb_connection_t *c /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -468,8 +468,12 @@ xcb_shape_query_version_reply (xcb_connection_t *c /**< */,
xcb_shape_query_version_cookie_t cookie /**< */,
xcb_generic_error_t **e /**< */);
+int
+xcb_shape_rectangles_sizeof (const void *_buffer /**< */,
+ uint32_t rectangles_len /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -509,7 +513,7 @@ xcb_shape_rectangles_checked (xcb_connection_t *c /**< */,
const xcb_rectangle_t *rectangles /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -546,7 +550,7 @@ xcb_shape_rectangles (xcb_connection_t *c /**< */,
const xcb_rectangle_t *rectangles /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -582,7 +586,7 @@ xcb_shape_mask_checked (xcb_connection_t *c /**< */,
xcb_pixmap_t source_bitmap /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -615,7 +619,7 @@ xcb_shape_mask (xcb_connection_t *c /**< */,
xcb_pixmap_t source_bitmap /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -653,7 +657,7 @@ xcb_shape_combine_checked (xcb_connection_t *c /**< */,
xcb_window_t source_window /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -688,7 +692,7 @@ xcb_shape_combine (xcb_connection_t *c /**< */,
xcb_window_t source_window /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -720,7 +724,7 @@ xcb_shape_offset_checked (xcb_connection_t *c /**< */,
int16_t y_offset /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -749,7 +753,7 @@ xcb_shape_offset (xcb_connection_t *c /**< */,
int16_t y_offset /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -772,7 +776,7 @@ xcb_shape_query_extents (xcb_connection_t *c /**< */,
xcb_window_t destination_window /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -829,7 +833,7 @@ xcb_shape_query_extents_reply (xcb_connection_t *c /**< */,
xcb_generic_error_t **e /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -857,7 +861,7 @@ xcb_shape_select_input_checked (xcb_connection_t *c /**< */,
uint8_t enable /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -882,7 +886,7 @@ xcb_shape_select_input (xcb_connection_t *c /**< */,
uint8_t enable /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -905,7 +909,7 @@ xcb_shape_input_selected (xcb_connection_t *c /**< */,
xcb_window_t destination_window /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -961,8 +965,11 @@ xcb_shape_input_selected_reply (xcb_connection_t *c /**< */,
xcb_shape_input_selected_cookie_t cookie /**< */,
xcb_generic_error_t **e /**< */);
+int
+xcb_shape_get_rectangles_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -987,7 +994,7 @@ xcb_shape_get_rectangles (xcb_connection_t *c /**< */,
xcb_shape_kind_t source_kind /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
diff --git a/src/3rdparty/xcb/include/xcb/shm.h b/src/3rdparty/xcb/include/xcb/shm.h
index bcb60d81f1..315f37e9b9 100644
--- a/src/3rdparty/xcb/include/xcb/shm.h
+++ b/src/3rdparty/xcb/include/xcb/shm.h
@@ -255,7 +255,7 @@ xcb_generic_iterator_t
xcb_shm_seg_end (xcb_shm_seg_iterator_t i /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -276,7 +276,7 @@ xcb_shm_query_version_cookie_t
xcb_shm_query_version (xcb_connection_t *c /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -331,7 +331,7 @@ xcb_shm_query_version_reply (xcb_connection_t *c /**< */,
xcb_generic_error_t **e /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -361,7 +361,7 @@ xcb_shm_attach_checked (xcb_connection_t *c /**< */,
uint8_t read_only /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -388,7 +388,7 @@ xcb_shm_attach (xcb_connection_t *c /**< */,
uint8_t read_only /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -414,7 +414,7 @@ xcb_shm_detach_checked (xcb_connection_t *c /**< */,
xcb_shm_seg_t shmseg /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -437,7 +437,7 @@ xcb_shm_detach (xcb_connection_t *c /**< */,
xcb_shm_seg_t shmseg /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -491,7 +491,7 @@ xcb_shm_put_image_checked (xcb_connection_t *c /**< */,
uint32_t offset /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -542,7 +542,7 @@ xcb_shm_put_image (xcb_connection_t *c /**< */,
uint32_t offset /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -581,7 +581,7 @@ xcb_shm_get_image (xcb_connection_t *c /**< */,
uint32_t offset /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -654,7 +654,7 @@ xcb_shm_get_image_reply (xcb_connection_t *c /**< */,
xcb_generic_error_t **e /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -692,7 +692,7 @@ xcb_shm_create_pixmap_checked (xcb_connection_t *c /**< */,
uint32_t offset /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
diff --git a/src/3rdparty/xcb/include/xcb/sync.h b/src/3rdparty/xcb/include/xcb/sync.h
index 50665c2865..3d0069d7ef 100644
--- a/src/3rdparty/xcb/include/xcb/sync.h
+++ b/src/3rdparty/xcb/include/xcb/sync.h
@@ -20,7 +20,7 @@ extern "C" {
#endif
#define XCB_SYNC_MAJOR_VERSION 3
-#define XCB_SYNC_MINOR_VERSION 0
+#define XCB_SYNC_MINOR_VERSION 1
extern xcb_extension_t xcb_sync_id;
@@ -52,6 +52,17 @@ typedef struct xcb_sync_counter_iterator_t {
int index; /**< */
} xcb_sync_counter_iterator_t;
+typedef uint32_t xcb_sync_fence_t;
+
+/**
+ * @brief xcb_sync_fence_iterator_t
+ **/
+typedef struct xcb_sync_fence_iterator_t {
+ xcb_sync_fence_t *data; /**< */
+ int rem; /**< */
+ int index; /**< */
+} xcb_sync_fence_iterator_t;
+
typedef enum xcb_sync_testtype_t {
XCB_SYNC_TESTTYPE_POSITIVE_TRANSITION,
XCB_SYNC_TESTTYPE_NEGATIVE_TRANSITION,
@@ -458,6 +469,104 @@ typedef struct xcb_sync_get_priority_reply_t {
int32_t priority; /**< */
} xcb_sync_get_priority_reply_t;
+/** Opcode for xcb_sync_create_fence. */
+#define XCB_SYNC_CREATE_FENCE 14
+
+/**
+ * @brief xcb_sync_create_fence_request_t
+ **/
+typedef struct xcb_sync_create_fence_request_t {
+ uint8_t major_opcode; /**< */
+ uint8_t minor_opcode; /**< */
+ uint16_t length; /**< */
+ xcb_drawable_t drawable; /**< */
+ xcb_sync_fence_t fence; /**< */
+ uint8_t initially_triggered; /**< */
+} xcb_sync_create_fence_request_t;
+
+/** Opcode for xcb_sync_trigger_fence. */
+#define XCB_SYNC_TRIGGER_FENCE 15
+
+/**
+ * @brief xcb_sync_trigger_fence_request_t
+ **/
+typedef struct xcb_sync_trigger_fence_request_t {
+ uint8_t major_opcode; /**< */
+ uint8_t minor_opcode; /**< */
+ uint16_t length; /**< */
+ xcb_sync_fence_t fence; /**< */
+} xcb_sync_trigger_fence_request_t;
+
+/** Opcode for xcb_sync_reset_fence. */
+#define XCB_SYNC_RESET_FENCE 16
+
+/**
+ * @brief xcb_sync_reset_fence_request_t
+ **/
+typedef struct xcb_sync_reset_fence_request_t {
+ uint8_t major_opcode; /**< */
+ uint8_t minor_opcode; /**< */
+ uint16_t length; /**< */
+ xcb_sync_fence_t fence; /**< */
+} xcb_sync_reset_fence_request_t;
+
+/** Opcode for xcb_sync_destroy_fence. */
+#define XCB_SYNC_DESTROY_FENCE 17
+
+/**
+ * @brief xcb_sync_destroy_fence_request_t
+ **/
+typedef struct xcb_sync_destroy_fence_request_t {
+ uint8_t major_opcode; /**< */
+ uint8_t minor_opcode; /**< */
+ uint16_t length; /**< */
+ xcb_sync_fence_t fence; /**< */
+} xcb_sync_destroy_fence_request_t;
+
+/**
+ * @brief xcb_sync_query_fence_cookie_t
+ **/
+typedef struct xcb_sync_query_fence_cookie_t {
+ unsigned int sequence; /**< */
+} xcb_sync_query_fence_cookie_t;
+
+/** Opcode for xcb_sync_query_fence. */
+#define XCB_SYNC_QUERY_FENCE 18
+
+/**
+ * @brief xcb_sync_query_fence_request_t
+ **/
+typedef struct xcb_sync_query_fence_request_t {
+ uint8_t major_opcode; /**< */
+ uint8_t minor_opcode; /**< */
+ uint16_t length; /**< */
+ xcb_sync_fence_t fence; /**< */
+} xcb_sync_query_fence_request_t;
+
+/**
+ * @brief xcb_sync_query_fence_reply_t
+ **/
+typedef struct xcb_sync_query_fence_reply_t {
+ uint8_t response_type; /**< */
+ uint8_t pad0; /**< */
+ uint16_t sequence; /**< */
+ uint32_t length; /**< */
+ uint8_t triggered; /**< */
+ uint8_t pad1[23]; /**< */
+} xcb_sync_query_fence_reply_t;
+
+/** Opcode for xcb_sync_await_fence. */
+#define XCB_SYNC_AWAIT_FENCE 19
+
+/**
+ * @brief xcb_sync_await_fence_request_t
+ **/
+typedef struct xcb_sync_await_fence_request_t {
+ uint8_t major_opcode; /**< */
+ uint8_t minor_opcode; /**< */
+ uint16_t length; /**< */
+} xcb_sync_await_fence_request_t;
+
/** Opcode for xcb_sync_counter_notify. */
#define XCB_SYNC_COUNTER_NOTIFY 0
@@ -583,6 +692,49 @@ xcb_sync_counter_end (xcb_sync_counter_iterator_t i /**< */);
/**
* Get the next element of the iterator
+ * @param i Pointer to a xcb_sync_fence_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_sync_fence_t)
+ */
+
+/*****************************************************************************
+ **
+ ** void xcb_sync_fence_next
+ **
+ ** @param xcb_sync_fence_iterator_t *i
+ ** @returns void
+ **
+ *****************************************************************************/
+
+void
+xcb_sync_fence_next (xcb_sync_fence_iterator_t *i /**< */);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_sync_fence_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+
+/*****************************************************************************
+ **
+ ** xcb_generic_iterator_t xcb_sync_fence_end
+ **
+ ** @param xcb_sync_fence_iterator_t i
+ ** @returns xcb_generic_iterator_t
+ **
+ *****************************************************************************/
+
+xcb_generic_iterator_t
+xcb_sync_fence_end (xcb_sync_fence_iterator_t i /**< */);
+
+/**
+ * Get the next element of the iterator
* @param i Pointer to a xcb_sync_int64_iterator_t
*
* Get the next element in the iterator. The member rem is
@@ -624,6 +776,9 @@ xcb_sync_int64_next (xcb_sync_int64_iterator_t *i /**< */);
xcb_generic_iterator_t
xcb_sync_int64_end (xcb_sync_int64_iterator_t i /**< */);
+int
+xcb_sync_systemcounter_sizeof (const void *_buffer /**< */);
+
/*****************************************************************************
**
@@ -793,7 +948,7 @@ xcb_generic_iterator_t
xcb_sync_waitcondition_end (xcb_sync_waitcondition_iterator_t i /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -818,7 +973,7 @@ xcb_sync_initialize (xcb_connection_t *c /**< */,
uint8_t desired_minor_version /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -876,8 +1031,11 @@ xcb_sync_initialize_reply (xcb_connection_t *c /**< */,
xcb_sync_initialize_cookie_t cookie /**< */,
xcb_generic_error_t **e /**< */);
+int
+xcb_sync_list_system_counters_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -898,7 +1056,7 @@ xcb_sync_list_system_counters_cookie_t
xcb_sync_list_system_counters (xcb_connection_t *c /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -979,7 +1137,7 @@ xcb_sync_list_system_counters_reply (xcb_connection_t *c
xcb_generic_error_t **e /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1007,7 +1165,7 @@ xcb_sync_create_counter_checked (xcb_connection_t *c /**< */,
xcb_sync_int64_t initial_value /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1032,7 +1190,7 @@ xcb_sync_create_counter (xcb_connection_t *c /**< */,
xcb_sync_int64_t initial_value /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1058,7 +1216,7 @@ xcb_sync_destroy_counter_checked (xcb_connection_t *c /**< */,
xcb_sync_counter_t counter /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1081,7 +1239,7 @@ xcb_sync_destroy_counter (xcb_connection_t *c /**< */,
xcb_sync_counter_t counter /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1104,7 +1262,7 @@ xcb_sync_query_counter (xcb_connection_t *c /**< */,
xcb_sync_counter_t counter /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1160,8 +1318,12 @@ xcb_sync_query_counter_reply (xcb_connection_t *c /**< */,
xcb_sync_query_counter_cookie_t cookie /**< */,
xcb_generic_error_t **e /**< */);
+int
+xcb_sync_await_sizeof (const void *_buffer /**< */,
+ uint32_t wait_list_len /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1189,7 +1351,7 @@ xcb_sync_await_checked (xcb_connection_t *c /**< */,
const xcb_sync_waitcondition_t *wait_list /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1214,7 +1376,7 @@ xcb_sync_await (xcb_connection_t *c /**< */,
const xcb_sync_waitcondition_t *wait_list /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1242,7 +1404,7 @@ xcb_sync_change_counter_checked (xcb_connection_t *c /**< */,
xcb_sync_int64_t amount /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1267,7 +1429,7 @@ xcb_sync_change_counter (xcb_connection_t *c /**< */,
xcb_sync_int64_t amount /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1295,7 +1457,7 @@ xcb_sync_set_counter_checked (xcb_connection_t *c /**< */,
xcb_sync_int64_t value /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1319,8 +1481,11 @@ xcb_sync_set_counter (xcb_connection_t *c /**< */,
xcb_sync_counter_t counter /**< */,
xcb_sync_int64_t value /**< */);
+int
+xcb_sync_create_alarm_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1350,7 +1515,7 @@ xcb_sync_create_alarm_checked (xcb_connection_t *c /**< */,
const uint32_t *value_list /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1376,8 +1541,11 @@ xcb_sync_create_alarm (xcb_connection_t *c /**< */,
uint32_t value_mask /**< */,
const uint32_t *value_list /**< */);
+int
+xcb_sync_change_alarm_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1407,7 +1575,7 @@ xcb_sync_change_alarm_checked (xcb_connection_t *c /**< */,
const uint32_t *value_list /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1434,7 +1602,7 @@ xcb_sync_change_alarm (xcb_connection_t *c /**< */,
const uint32_t *value_list /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1460,7 +1628,7 @@ xcb_sync_destroy_alarm_checked (xcb_connection_t *c /**< */,
xcb_sync_alarm_t alarm /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1483,7 +1651,7 @@ xcb_sync_destroy_alarm (xcb_connection_t *c /**< */,
xcb_sync_alarm_t alarm /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1506,7 +1674,7 @@ xcb_sync_query_alarm (xcb_connection_t *c /**< */,
xcb_sync_alarm_t alarm /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1563,7 +1731,7 @@ xcb_sync_query_alarm_reply (xcb_connection_t *c /**< */,
xcb_generic_error_t **e /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1591,7 +1759,7 @@ xcb_sync_set_priority_checked (xcb_connection_t *c /**< */,
int32_t priority /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1616,7 +1784,7 @@ xcb_sync_set_priority (xcb_connection_t *c /**< */,
int32_t priority /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1639,7 +1807,7 @@ xcb_sync_get_priority (xcb_connection_t *c /**< */,
uint32_t id /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1695,6 +1863,347 @@ xcb_sync_get_priority_reply (xcb_connection_t *c /**< */,
xcb_sync_get_priority_cookie_t cookie /**< */,
xcb_generic_error_t **e /**< */);
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+
+/*****************************************************************************
+ **
+ ** xcb_void_cookie_t xcb_sync_create_fence_checked
+ **
+ ** @param xcb_connection_t *c
+ ** @param xcb_drawable_t drawable
+ ** @param xcb_sync_fence_t fence
+ ** @param uint8_t initially_triggered
+ ** @returns xcb_void_cookie_t
+ **
+ *****************************************************************************/
+
+xcb_void_cookie_t
+xcb_sync_create_fence_checked (xcb_connection_t *c /**< */,
+ xcb_drawable_t drawable /**< */,
+ xcb_sync_fence_t fence /**< */,
+ uint8_t initially_triggered /**< */);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+
+/*****************************************************************************
+ **
+ ** xcb_void_cookie_t xcb_sync_create_fence
+ **
+ ** @param xcb_connection_t *c
+ ** @param xcb_drawable_t drawable
+ ** @param xcb_sync_fence_t fence
+ ** @param uint8_t initially_triggered
+ ** @returns xcb_void_cookie_t
+ **
+ *****************************************************************************/
+
+xcb_void_cookie_t
+xcb_sync_create_fence (xcb_connection_t *c /**< */,
+ xcb_drawable_t drawable /**< */,
+ xcb_sync_fence_t fence /**< */,
+ uint8_t initially_triggered /**< */);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+
+/*****************************************************************************
+ **
+ ** xcb_void_cookie_t xcb_sync_trigger_fence_checked
+ **
+ ** @param xcb_connection_t *c
+ ** @param xcb_sync_fence_t fence
+ ** @returns xcb_void_cookie_t
+ **
+ *****************************************************************************/
+
+xcb_void_cookie_t
+xcb_sync_trigger_fence_checked (xcb_connection_t *c /**< */,
+ xcb_sync_fence_t fence /**< */);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+
+/*****************************************************************************
+ **
+ ** xcb_void_cookie_t xcb_sync_trigger_fence
+ **
+ ** @param xcb_connection_t *c
+ ** @param xcb_sync_fence_t fence
+ ** @returns xcb_void_cookie_t
+ **
+ *****************************************************************************/
+
+xcb_void_cookie_t
+xcb_sync_trigger_fence (xcb_connection_t *c /**< */,
+ xcb_sync_fence_t fence /**< */);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+
+/*****************************************************************************
+ **
+ ** xcb_void_cookie_t xcb_sync_reset_fence_checked
+ **
+ ** @param xcb_connection_t *c
+ ** @param xcb_sync_fence_t fence
+ ** @returns xcb_void_cookie_t
+ **
+ *****************************************************************************/
+
+xcb_void_cookie_t
+xcb_sync_reset_fence_checked (xcb_connection_t *c /**< */,
+ xcb_sync_fence_t fence /**< */);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+
+/*****************************************************************************
+ **
+ ** xcb_void_cookie_t xcb_sync_reset_fence
+ **
+ ** @param xcb_connection_t *c
+ ** @param xcb_sync_fence_t fence
+ ** @returns xcb_void_cookie_t
+ **
+ *****************************************************************************/
+
+xcb_void_cookie_t
+xcb_sync_reset_fence (xcb_connection_t *c /**< */,
+ xcb_sync_fence_t fence /**< */);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+
+/*****************************************************************************
+ **
+ ** xcb_void_cookie_t xcb_sync_destroy_fence_checked
+ **
+ ** @param xcb_connection_t *c
+ ** @param xcb_sync_fence_t fence
+ ** @returns xcb_void_cookie_t
+ **
+ *****************************************************************************/
+
+xcb_void_cookie_t
+xcb_sync_destroy_fence_checked (xcb_connection_t *c /**< */,
+ xcb_sync_fence_t fence /**< */);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+
+/*****************************************************************************
+ **
+ ** xcb_void_cookie_t xcb_sync_destroy_fence
+ **
+ ** @param xcb_connection_t *c
+ ** @param xcb_sync_fence_t fence
+ ** @returns xcb_void_cookie_t
+ **
+ *****************************************************************************/
+
+xcb_void_cookie_t
+xcb_sync_destroy_fence (xcb_connection_t *c /**< */,
+ xcb_sync_fence_t fence /**< */);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+
+/*****************************************************************************
+ **
+ ** xcb_sync_query_fence_cookie_t xcb_sync_query_fence
+ **
+ ** @param xcb_connection_t *c
+ ** @param xcb_sync_fence_t fence
+ ** @returns xcb_sync_query_fence_cookie_t
+ **
+ *****************************************************************************/
+
+xcb_sync_query_fence_cookie_t
+xcb_sync_query_fence (xcb_connection_t *c /**< */,
+ xcb_sync_fence_t fence /**< */);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+
+/*****************************************************************************
+ **
+ ** xcb_sync_query_fence_cookie_t xcb_sync_query_fence_unchecked
+ **
+ ** @param xcb_connection_t *c
+ ** @param xcb_sync_fence_t fence
+ ** @returns xcb_sync_query_fence_cookie_t
+ **
+ *****************************************************************************/
+
+xcb_sync_query_fence_cookie_t
+xcb_sync_query_fence_unchecked (xcb_connection_t *c /**< */,
+ xcb_sync_fence_t fence /**< */);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_sync_query_fence_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+
+/*****************************************************************************
+ **
+ ** xcb_sync_query_fence_reply_t * xcb_sync_query_fence_reply
+ **
+ ** @param xcb_connection_t *c
+ ** @param xcb_sync_query_fence_cookie_t cookie
+ ** @param xcb_generic_error_t **e
+ ** @returns xcb_sync_query_fence_reply_t *
+ **
+ *****************************************************************************/
+
+xcb_sync_query_fence_reply_t *
+xcb_sync_query_fence_reply (xcb_connection_t *c /**< */,
+ xcb_sync_query_fence_cookie_t cookie /**< */,
+ xcb_generic_error_t **e /**< */);
+
+int
+xcb_sync_await_fence_sizeof (const void *_buffer /**< */,
+ uint32_t fence_list_len /**< */);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+
+/*****************************************************************************
+ **
+ ** xcb_void_cookie_t xcb_sync_await_fence_checked
+ **
+ ** @param xcb_connection_t *c
+ ** @param uint32_t fence_list_len
+ ** @param const xcb_sync_fence_t *fence_list
+ ** @returns xcb_void_cookie_t
+ **
+ *****************************************************************************/
+
+xcb_void_cookie_t
+xcb_sync_await_fence_checked (xcb_connection_t *c /**< */,
+ uint32_t fence_list_len /**< */,
+ const xcb_sync_fence_t *fence_list /**< */);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+
+/*****************************************************************************
+ **
+ ** xcb_void_cookie_t xcb_sync_await_fence
+ **
+ ** @param xcb_connection_t *c
+ ** @param uint32_t fence_list_len
+ ** @param const xcb_sync_fence_t *fence_list
+ ** @returns xcb_void_cookie_t
+ **
+ *****************************************************************************/
+
+xcb_void_cookie_t
+xcb_sync_await_fence (xcb_connection_t *c /**< */,
+ uint32_t fence_list_len /**< */,
+ const xcb_sync_fence_t *fence_list /**< */);
+
#ifdef __cplusplus
}
diff --git a/src/3rdparty/xcb/include/xcb/xfixes.h b/src/3rdparty/xcb/include/xcb/xfixes.h
index 4d7eb0900a..b67aa85135 100644
--- a/src/3rdparty/xcb/include/xcb/xfixes.h
+++ b/src/3rdparty/xcb/include/xcb/xfixes.h
@@ -683,7 +683,7 @@ typedef struct xcb_xfixes_show_cursor_request_t {
} xcb_xfixes_show_cursor_request_t;
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -708,7 +708,7 @@ xcb_xfixes_query_version (xcb_connection_t *c /**< */,
uint32_t client_minor_version /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -767,7 +767,7 @@ xcb_xfixes_query_version_reply (xcb_connection_t *c /**< */,
xcb_generic_error_t **e /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -799,7 +799,7 @@ xcb_xfixes_change_save_set_checked (xcb_connection_t *c /**< */,
xcb_window_t window /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -828,7 +828,7 @@ xcb_xfixes_change_save_set (xcb_connection_t *c /**< */,
xcb_window_t window /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -858,7 +858,7 @@ xcb_xfixes_select_selection_input_checked (xcb_connection_t *c /**< */,
uint32_t event_mask /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -885,7 +885,7 @@ xcb_xfixes_select_selection_input (xcb_connection_t *c /**< */,
uint32_t event_mask /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -913,7 +913,7 @@ xcb_xfixes_select_cursor_input_checked (xcb_connection_t *c /**< */,
uint32_t event_mask /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -937,8 +937,11 @@ xcb_xfixes_select_cursor_input (xcb_connection_t *c /**< */,
xcb_window_t window /**< */,
uint32_t event_mask /**< */);
+int
+xcb_xfixes_get_cursor_image_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -959,7 +962,7 @@ xcb_xfixes_get_cursor_image_cookie_t
xcb_xfixes_get_cursor_image (xcb_connection_t *c /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1095,8 +1098,12 @@ xcb_xfixes_region_next (xcb_xfixes_region_iterator_t *i /**< */);
xcb_generic_iterator_t
xcb_xfixes_region_end (xcb_xfixes_region_iterator_t i /**< */);
+int
+xcb_xfixes_create_region_sizeof (const void *_buffer /**< */,
+ uint32_t rectangles_len /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1126,7 +1133,7 @@ xcb_xfixes_create_region_checked (xcb_connection_t *c /**< */,
const xcb_rectangle_t *rectangles /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1153,7 +1160,7 @@ xcb_xfixes_create_region (xcb_connection_t *c /**< */,
const xcb_rectangle_t *rectangles /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1181,7 +1188,7 @@ xcb_xfixes_create_region_from_bitmap_checked (xcb_connection_t *c /**< */,
xcb_pixmap_t bitmap /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1206,7 +1213,7 @@ xcb_xfixes_create_region_from_bitmap (xcb_connection_t *c /**< */,
xcb_pixmap_t bitmap /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1236,7 +1243,7 @@ xcb_xfixes_create_region_from_window_checked (xcb_connection_t *c /**< */,
xcb_shape_kind_t kind /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1263,7 +1270,7 @@ xcb_xfixes_create_region_from_window (xcb_connection_t *c /**< */,
xcb_shape_kind_t kind /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1291,7 +1298,7 @@ xcb_xfixes_create_region_from_gc_checked (xcb_connection_t *c /**< */,
xcb_gcontext_t gc /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1316,7 +1323,7 @@ xcb_xfixes_create_region_from_gc (xcb_connection_t *c /**< */,
xcb_gcontext_t gc /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1344,7 +1351,7 @@ xcb_xfixes_create_region_from_picture_checked (xcb_connection_t *c /**< */,
xcb_render_picture_t picture /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1369,7 +1376,7 @@ xcb_xfixes_create_region_from_picture (xcb_connection_t *c /**< */,
xcb_render_picture_t picture /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1395,7 +1402,7 @@ xcb_xfixes_destroy_region_checked (xcb_connection_t *c /**< */,
xcb_xfixes_region_t region /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1417,8 +1424,12 @@ xcb_void_cookie_t
xcb_xfixes_destroy_region (xcb_connection_t *c /**< */,
xcb_xfixes_region_t region /**< */);
+int
+xcb_xfixes_set_region_sizeof (const void *_buffer /**< */,
+ uint32_t rectangles_len /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1448,7 +1459,7 @@ xcb_xfixes_set_region_checked (xcb_connection_t *c /**< */,
const xcb_rectangle_t *rectangles /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1475,7 +1486,7 @@ xcb_xfixes_set_region (xcb_connection_t *c /**< */,
const xcb_rectangle_t *rectangles /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1503,7 +1514,7 @@ xcb_xfixes_copy_region_checked (xcb_connection_t *c /**< */,
xcb_xfixes_region_t destination /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1528,7 +1539,7 @@ xcb_xfixes_copy_region (xcb_connection_t *c /**< */,
xcb_xfixes_region_t destination /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1558,7 +1569,7 @@ xcb_xfixes_union_region_checked (xcb_connection_t *c /**< */,
xcb_xfixes_region_t destination /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1585,7 +1596,7 @@ xcb_xfixes_union_region (xcb_connection_t *c /**< */,
xcb_xfixes_region_t destination /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1615,7 +1626,7 @@ xcb_xfixes_intersect_region_checked (xcb_connection_t *c /**< */,
xcb_xfixes_region_t destination /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1642,7 +1653,7 @@ xcb_xfixes_intersect_region (xcb_connection_t *c /**< */,
xcb_xfixes_region_t destination /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1672,7 +1683,7 @@ xcb_xfixes_subtract_region_checked (xcb_connection_t *c /**< */,
xcb_xfixes_region_t destination /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1699,7 +1710,7 @@ xcb_xfixes_subtract_region (xcb_connection_t *c /**< */,
xcb_xfixes_region_t destination /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1729,7 +1740,7 @@ xcb_xfixes_invert_region_checked (xcb_connection_t *c /**< */,
xcb_xfixes_region_t destination /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1756,7 +1767,7 @@ xcb_xfixes_invert_region (xcb_connection_t *c /**< */,
xcb_xfixes_region_t destination /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1786,7 +1797,7 @@ xcb_xfixes_translate_region_checked (xcb_connection_t *c /**< */,
int16_t dy /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1813,7 +1824,7 @@ xcb_xfixes_translate_region (xcb_connection_t *c /**< */,
int16_t dy /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1841,7 +1852,7 @@ xcb_xfixes_region_extents_checked (xcb_connection_t *c /**< */,
xcb_xfixes_region_t destination /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1865,8 +1876,11 @@ xcb_xfixes_region_extents (xcb_connection_t *c /**< */,
xcb_xfixes_region_t source /**< */,
xcb_xfixes_region_t destination /**< */);
+int
+xcb_xfixes_fetch_region_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1889,7 +1903,7 @@ xcb_xfixes_fetch_region (xcb_connection_t *c /**< */,
xcb_xfixes_region_t region /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -1985,7 +1999,7 @@ xcb_xfixes_fetch_region_reply (xcb_connection_t *c /**< */,
xcb_generic_error_t **e /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2017,7 +2031,7 @@ xcb_xfixes_set_gc_clip_region_checked (xcb_connection_t *c /**< */,
int16_t y_origin /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2046,7 +2060,7 @@ xcb_xfixes_set_gc_clip_region (xcb_connection_t *c /**< */,
int16_t y_origin /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2080,7 +2094,7 @@ xcb_xfixes_set_window_shape_region_checked (xcb_connection_t *c /**< */,
xcb_xfixes_region_t region /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2111,7 +2125,7 @@ xcb_xfixes_set_window_shape_region (xcb_connection_t *c /**< */,
xcb_xfixes_region_t region /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2143,7 +2157,7 @@ xcb_xfixes_set_picture_clip_region_checked (xcb_connection_t *c /**< */,
int16_t y_origin /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2171,8 +2185,11 @@ xcb_xfixes_set_picture_clip_region (xcb_connection_t *c /**< */,
int16_t x_origin /**< */,
int16_t y_origin /**< */);
+int
+xcb_xfixes_set_cursor_name_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2202,7 +2219,7 @@ xcb_xfixes_set_cursor_name_checked (xcb_connection_t *c /**< */,
const char *name /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2228,8 +2245,11 @@ xcb_xfixes_set_cursor_name (xcb_connection_t *c /**< */,
uint16_t nbytes /**< */,
const char *name /**< */);
+int
+xcb_xfixes_get_cursor_name_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2252,7 +2272,7 @@ xcb_xfixes_get_cursor_name (xcb_connection_t *c /**< */,
xcb_cursor_t cursor /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2347,8 +2367,11 @@ xcb_xfixes_get_cursor_name_reply (xcb_connection_t *c /**<
xcb_xfixes_get_cursor_name_cookie_t cookie /**< */,
xcb_generic_error_t **e /**< */);
+int
+xcb_xfixes_get_cursor_image_and_name_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2369,7 +2392,7 @@ xcb_xfixes_get_cursor_image_and_name_cookie_t
xcb_xfixes_get_cursor_image_and_name (xcb_connection_t *c /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2502,7 +2525,7 @@ xcb_xfixes_get_cursor_image_and_name_reply (xcb_connection_t
xcb_generic_error_t **e /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2530,7 +2553,7 @@ xcb_xfixes_change_cursor_checked (xcb_connection_t *c /**< */,
xcb_cursor_t destination /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2554,8 +2577,11 @@ xcb_xfixes_change_cursor (xcb_connection_t *c /**< */,
xcb_cursor_t source /**< */,
xcb_cursor_t destination /**< */);
+int
+xcb_xfixes_change_cursor_by_name_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2585,7 +2611,7 @@ xcb_xfixes_change_cursor_by_name_checked (xcb_connection_t *c /**< */,
const char *name /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2612,7 +2638,7 @@ xcb_xfixes_change_cursor_by_name (xcb_connection_t *c /**< */,
const char *name /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2648,7 +2674,7 @@ xcb_xfixes_expand_region_checked (xcb_connection_t *c /**< */,
uint16_t bottom /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2681,7 +2707,7 @@ xcb_xfixes_expand_region (xcb_connection_t *c /**< */,
uint16_t bottom /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2707,7 +2733,7 @@ xcb_xfixes_hide_cursor_checked (xcb_connection_t *c /**< */,
xcb_window_t window /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2730,7 +2756,7 @@ xcb_xfixes_hide_cursor (xcb_connection_t *c /**< */,
xcb_window_t window /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
@@ -2756,7 +2782,7 @@ xcb_xfixes_show_cursor_checked (xcb_connection_t *c /**< */,
xcb_window_t window /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
diff --git a/src/3rdparty/xcb/include/xcb/xinerama.h b/src/3rdparty/xcb/include/xcb/xinerama.h
index 74da5458d2..f18a96c791 100644
--- a/src/3rdparty/xcb/include/xcb/xinerama.h
+++ b/src/3rdparty/xcb/include/xcb/xinerama.h
@@ -21,7 +21,7 @@ extern "C" {
#define XCB_XINERAMA_MAJOR_VERSION 1
#define XCB_XINERAMA_MINOR_VERSION 1
-
+
extern xcb_extension_t xcb_xinerama_id;
/**
@@ -246,12 +246,12 @@ typedef struct xcb_xinerama_query_screens_reply_t {
/*****************************************************************************
**
** void xcb_xinerama_screen_info_next
- **
+ **
** @param xcb_xinerama_screen_info_iterator_t *i
** @returns void
**
*****************************************************************************/
-
+
void
xcb_xinerama_screen_info_next (xcb_xinerama_screen_info_iterator_t *i /**< */);
@@ -268,47 +268,47 @@ xcb_xinerama_screen_info_next (xcb_xinerama_screen_info_iterator_t *i /**< */);
/*****************************************************************************
**
** xcb_generic_iterator_t xcb_xinerama_screen_info_end
- **
+ **
** @param xcb_xinerama_screen_info_iterator_t i
** @returns xcb_generic_iterator_t
**
*****************************************************************************/
-
+
xcb_generic_iterator_t
xcb_xinerama_screen_info_end (xcb_xinerama_screen_info_iterator_t i /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
* Delivers a request to the X server.
- *
+ *
*/
/*****************************************************************************
**
** xcb_xinerama_query_version_cookie_t xcb_xinerama_query_version
- **
+ **
** @param xcb_connection_t *c
** @param uint8_t major
** @param uint8_t minor
** @returns xcb_xinerama_query_version_cookie_t
**
*****************************************************************************/
-
+
xcb_xinerama_query_version_cookie_t
xcb_xinerama_query_version (xcb_connection_t *c /**< */,
uint8_t major /**< */,
uint8_t minor /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
* Delivers a request to the X server.
- *
+ *
* This form can be used only if the request will cause
* a reply to be generated. Any returned error will be
* placed in the event queue.
@@ -317,14 +317,14 @@ xcb_xinerama_query_version (xcb_connection_t *c /**< */,
/*****************************************************************************
**
** xcb_xinerama_query_version_cookie_t xcb_xinerama_query_version_unchecked
- **
+ **
** @param xcb_connection_t *c
** @param uint8_t major
** @param uint8_t minor
** @returns xcb_xinerama_query_version_cookie_t
**
*****************************************************************************/
-
+
xcb_xinerama_query_version_cookie_t
xcb_xinerama_query_version_unchecked (xcb_connection_t *c /**< */,
uint8_t major /**< */,
@@ -337,7 +337,7 @@ xcb_xinerama_query_version_unchecked (xcb_connection_t *c /**< */,
* @param e The xcb_generic_error_t supplied
*
* Returns the reply of the request asked by
- *
+ *
* The parameter @p e supplied to this function must be NULL if
* xcb_xinerama_query_version_unchecked(). is used.
* Otherwise, it stores the error if any.
@@ -348,49 +348,49 @@ xcb_xinerama_query_version_unchecked (xcb_connection_t *c /**< */,
/*****************************************************************************
**
** xcb_xinerama_query_version_reply_t * xcb_xinerama_query_version_reply
- **
+ **
** @param xcb_connection_t *c
** @param xcb_xinerama_query_version_cookie_t cookie
** @param xcb_generic_error_t **e
** @returns xcb_xinerama_query_version_reply_t *
**
*****************************************************************************/
-
+
xcb_xinerama_query_version_reply_t *
xcb_xinerama_query_version_reply (xcb_connection_t *c /**< */,
xcb_xinerama_query_version_cookie_t cookie /**< */,
xcb_generic_error_t **e /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
* Delivers a request to the X server.
- *
+ *
*/
/*****************************************************************************
**
** xcb_xinerama_get_state_cookie_t xcb_xinerama_get_state
- **
+ **
** @param xcb_connection_t *c
** @param xcb_window_t window
** @returns xcb_xinerama_get_state_cookie_t
**
*****************************************************************************/
-
+
xcb_xinerama_get_state_cookie_t
xcb_xinerama_get_state (xcb_connection_t *c /**< */,
xcb_window_t window /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
* Delivers a request to the X server.
- *
+ *
* This form can be used only if the request will cause
* a reply to be generated. Any returned error will be
* placed in the event queue.
@@ -399,13 +399,13 @@ xcb_xinerama_get_state (xcb_connection_t *c /**< */,
/*****************************************************************************
**
** xcb_xinerama_get_state_cookie_t xcb_xinerama_get_state_unchecked
- **
+ **
** @param xcb_connection_t *c
** @param xcb_window_t window
** @returns xcb_xinerama_get_state_cookie_t
**
*****************************************************************************/
-
+
xcb_xinerama_get_state_cookie_t
xcb_xinerama_get_state_unchecked (xcb_connection_t *c /**< */,
xcb_window_t window /**< */);
@@ -417,7 +417,7 @@ xcb_xinerama_get_state_unchecked (xcb_connection_t *c /**< */,
* @param e The xcb_generic_error_t supplied
*
* Returns the reply of the request asked by
- *
+ *
* The parameter @p e supplied to this function must be NULL if
* xcb_xinerama_get_state_unchecked(). is used.
* Otherwise, it stores the error if any.
@@ -428,49 +428,49 @@ xcb_xinerama_get_state_unchecked (xcb_connection_t *c /**< */,
/*****************************************************************************
**
** xcb_xinerama_get_state_reply_t * xcb_xinerama_get_state_reply
- **
+ **
** @param xcb_connection_t *c
** @param xcb_xinerama_get_state_cookie_t cookie
** @param xcb_generic_error_t **e
** @returns xcb_xinerama_get_state_reply_t *
**
*****************************************************************************/
-
+
xcb_xinerama_get_state_reply_t *
xcb_xinerama_get_state_reply (xcb_connection_t *c /**< */,
xcb_xinerama_get_state_cookie_t cookie /**< */,
xcb_generic_error_t **e /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
* Delivers a request to the X server.
- *
+ *
*/
/*****************************************************************************
**
** xcb_xinerama_get_screen_count_cookie_t xcb_xinerama_get_screen_count
- **
+ **
** @param xcb_connection_t *c
** @param xcb_window_t window
** @returns xcb_xinerama_get_screen_count_cookie_t
**
*****************************************************************************/
-
+
xcb_xinerama_get_screen_count_cookie_t
xcb_xinerama_get_screen_count (xcb_connection_t *c /**< */,
xcb_window_t window /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
* Delivers a request to the X server.
- *
+ *
* This form can be used only if the request will cause
* a reply to be generated. Any returned error will be
* placed in the event queue.
@@ -479,13 +479,13 @@ xcb_xinerama_get_screen_count (xcb_connection_t *c /**< */,
/*****************************************************************************
**
** xcb_xinerama_get_screen_count_cookie_t xcb_xinerama_get_screen_count_unchecked
- **
+ **
** @param xcb_connection_t *c
** @param xcb_window_t window
** @returns xcb_xinerama_get_screen_count_cookie_t
**
*****************************************************************************/
-
+
xcb_xinerama_get_screen_count_cookie_t
xcb_xinerama_get_screen_count_unchecked (xcb_connection_t *c /**< */,
xcb_window_t window /**< */);
@@ -497,7 +497,7 @@ xcb_xinerama_get_screen_count_unchecked (xcb_connection_t *c /**< */,
* @param e The xcb_generic_error_t supplied
*
* Returns the reply of the request asked by
- *
+ *
* The parameter @p e supplied to this function must be NULL if
* xcb_xinerama_get_screen_count_unchecked(). is used.
* Otherwise, it stores the error if any.
@@ -508,51 +508,51 @@ xcb_xinerama_get_screen_count_unchecked (xcb_connection_t *c /**< */,
/*****************************************************************************
**
** xcb_xinerama_get_screen_count_reply_t * xcb_xinerama_get_screen_count_reply
- **
+ **
** @param xcb_connection_t *c
** @param xcb_xinerama_get_screen_count_cookie_t cookie
** @param xcb_generic_error_t **e
** @returns xcb_xinerama_get_screen_count_reply_t *
**
*****************************************************************************/
-
+
xcb_xinerama_get_screen_count_reply_t *
xcb_xinerama_get_screen_count_reply (xcb_connection_t *c /**< */,
xcb_xinerama_get_screen_count_cookie_t cookie /**< */,
xcb_generic_error_t **e /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
* Delivers a request to the X server.
- *
+ *
*/
/*****************************************************************************
**
** xcb_xinerama_get_screen_size_cookie_t xcb_xinerama_get_screen_size
- **
+ **
** @param xcb_connection_t *c
** @param xcb_window_t window
** @param uint32_t screen
** @returns xcb_xinerama_get_screen_size_cookie_t
**
*****************************************************************************/
-
+
xcb_xinerama_get_screen_size_cookie_t
xcb_xinerama_get_screen_size (xcb_connection_t *c /**< */,
xcb_window_t window /**< */,
uint32_t screen /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
* Delivers a request to the X server.
- *
+ *
* This form can be used only if the request will cause
* a reply to be generated. Any returned error will be
* placed in the event queue.
@@ -561,14 +561,14 @@ xcb_xinerama_get_screen_size (xcb_connection_t *c /**< */,
/*****************************************************************************
**
** xcb_xinerama_get_screen_size_cookie_t xcb_xinerama_get_screen_size_unchecked
- **
+ **
** @param xcb_connection_t *c
** @param xcb_window_t window
** @param uint32_t screen
** @returns xcb_xinerama_get_screen_size_cookie_t
**
*****************************************************************************/
-
+
xcb_xinerama_get_screen_size_cookie_t
xcb_xinerama_get_screen_size_unchecked (xcb_connection_t *c /**< */,
xcb_window_t window /**< */,
@@ -581,7 +581,7 @@ xcb_xinerama_get_screen_size_unchecked (xcb_connection_t *c /**< */,
* @param e The xcb_generic_error_t supplied
*
* Returns the reply of the request asked by
- *
+ *
* The parameter @p e supplied to this function must be NULL if
* xcb_xinerama_get_screen_size_unchecked(). is used.
* Otherwise, it stores the error if any.
@@ -592,47 +592,47 @@ xcb_xinerama_get_screen_size_unchecked (xcb_connection_t *c /**< */,
/*****************************************************************************
**
** xcb_xinerama_get_screen_size_reply_t * xcb_xinerama_get_screen_size_reply
- **
+ **
** @param xcb_connection_t *c
** @param xcb_xinerama_get_screen_size_cookie_t cookie
** @param xcb_generic_error_t **e
** @returns xcb_xinerama_get_screen_size_reply_t *
**
*****************************************************************************/
-
+
xcb_xinerama_get_screen_size_reply_t *
xcb_xinerama_get_screen_size_reply (xcb_connection_t *c /**< */,
xcb_xinerama_get_screen_size_cookie_t cookie /**< */,
xcb_generic_error_t **e /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
* Delivers a request to the X server.
- *
+ *
*/
/*****************************************************************************
**
** xcb_xinerama_is_active_cookie_t xcb_xinerama_is_active
- **
+ **
** @param xcb_connection_t *c
** @returns xcb_xinerama_is_active_cookie_t
**
*****************************************************************************/
-
+
xcb_xinerama_is_active_cookie_t
xcb_xinerama_is_active (xcb_connection_t *c /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
* Delivers a request to the X server.
- *
+ *
* This form can be used only if the request will cause
* a reply to be generated. Any returned error will be
* placed in the event queue.
@@ -641,12 +641,12 @@ xcb_xinerama_is_active (xcb_connection_t *c /**< */);
/*****************************************************************************
**
** xcb_xinerama_is_active_cookie_t xcb_xinerama_is_active_unchecked
- **
+ **
** @param xcb_connection_t *c
** @returns xcb_xinerama_is_active_cookie_t
**
*****************************************************************************/
-
+
xcb_xinerama_is_active_cookie_t
xcb_xinerama_is_active_unchecked (xcb_connection_t *c /**< */);
@@ -657,7 +657,7 @@ xcb_xinerama_is_active_unchecked (xcb_connection_t *c /**< */);
* @param e The xcb_generic_error_t supplied
*
* Returns the reply of the request asked by
- *
+ *
* The parameter @p e supplied to this function must be NULL if
* xcb_xinerama_is_active_unchecked(). is used.
* Otherwise, it stores the error if any.
@@ -668,47 +668,50 @@ xcb_xinerama_is_active_unchecked (xcb_connection_t *c /**< */);
/*****************************************************************************
**
** xcb_xinerama_is_active_reply_t * xcb_xinerama_is_active_reply
- **
+ **
** @param xcb_connection_t *c
** @param xcb_xinerama_is_active_cookie_t cookie
** @param xcb_generic_error_t **e
** @returns xcb_xinerama_is_active_reply_t *
**
*****************************************************************************/
-
+
xcb_xinerama_is_active_reply_t *
xcb_xinerama_is_active_reply (xcb_connection_t *c /**< */,
xcb_xinerama_is_active_cookie_t cookie /**< */,
xcb_generic_error_t **e /**< */);
+int
+xcb_xinerama_query_screens_sizeof (const void *_buffer /**< */);
+
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
* Delivers a request to the X server.
- *
+ *
*/
/*****************************************************************************
**
** xcb_xinerama_query_screens_cookie_t xcb_xinerama_query_screens
- **
+ **
** @param xcb_connection_t *c
** @returns xcb_xinerama_query_screens_cookie_t
**
*****************************************************************************/
-
+
xcb_xinerama_query_screens_cookie_t
xcb_xinerama_query_screens (xcb_connection_t *c /**< */);
/**
- * Delivers a request to the X server
+ *
* @param c The connection
* @return A cookie
*
* Delivers a request to the X server.
- *
+ *
* This form can be used only if the request will cause
* a reply to be generated. Any returned error will be
* placed in the event queue.
@@ -717,12 +720,12 @@ xcb_xinerama_query_screens (xcb_connection_t *c /**< */);
/*****************************************************************************
**
** xcb_xinerama_query_screens_cookie_t xcb_xinerama_query_screens_unchecked
- **
+ **
** @param xcb_connection_t *c
** @returns xcb_xinerama_query_screens_cookie_t
**
*****************************************************************************/
-
+
xcb_xinerama_query_screens_cookie_t
xcb_xinerama_query_screens_unchecked (xcb_connection_t *c /**< */);
@@ -730,12 +733,12 @@ xcb_xinerama_query_screens_unchecked (xcb_connection_t *c /**< */);
/*****************************************************************************
**
** xcb_xinerama_screen_info_t * xcb_xinerama_query_screens_screen_info
- **
+ **
** @param const xcb_xinerama_query_screens_reply_t *R
** @returns xcb_xinerama_screen_info_t *
**
*****************************************************************************/
-
+
xcb_xinerama_screen_info_t *
xcb_xinerama_query_screens_screen_info (const xcb_xinerama_query_screens_reply_t *R /**< */);
@@ -743,12 +746,12 @@ xcb_xinerama_query_screens_screen_info (const xcb_xinerama_query_screens_reply_t
/*****************************************************************************
**
** int xcb_xinerama_query_screens_screen_info_length
- **
+ **
** @param const xcb_xinerama_query_screens_reply_t *R
** @returns int
**
*****************************************************************************/
-
+
int
xcb_xinerama_query_screens_screen_info_length (const xcb_xinerama_query_screens_reply_t *R /**< */);
@@ -756,12 +759,12 @@ xcb_xinerama_query_screens_screen_info_length (const xcb_xinerama_query_screens_
/*****************************************************************************
**
** xcb_xinerama_screen_info_iterator_t xcb_xinerama_query_screens_screen_info_iterator
- **
+ **
** @param const xcb_xinerama_query_screens_reply_t *R
** @returns xcb_xinerama_screen_info_iterator_t
**
*****************************************************************************/
-
+
xcb_xinerama_screen_info_iterator_t
xcb_xinerama_query_screens_screen_info_iterator (const xcb_xinerama_query_screens_reply_t *R /**< */);
@@ -772,7 +775,7 @@ xcb_xinerama_query_screens_screen_info_iterator (const xcb_xinerama_query_screen
* @param e The xcb_generic_error_t supplied
*
* Returns the reply of the request asked by
- *
+ *
* The parameter @p e supplied to this function must be NULL if
* xcb_xinerama_query_screens_unchecked(). is used.
* Otherwise, it stores the error if any.
@@ -783,14 +786,14 @@ xcb_xinerama_query_screens_screen_info_iterator (const xcb_xinerama_query_screen
/*****************************************************************************
**
** xcb_xinerama_query_screens_reply_t * xcb_xinerama_query_screens_reply
- **
+ **
** @param xcb_connection_t *c
** @param xcb_xinerama_query_screens_cookie_t cookie
** @param xcb_generic_error_t **e
** @returns xcb_xinerama_query_screens_reply_t *
**
*****************************************************************************/
-
+
xcb_xinerama_query_screens_reply_t *
xcb_xinerama_query_screens_reply (xcb_connection_t *c /**< */,
xcb_xinerama_query_screens_cookie_t cookie /**< */,
diff --git a/src/3rdparty/xcb/include/xcb/xinput.h b/src/3rdparty/xcb/include/xcb/xinput.h
new file mode 100644
index 0000000000..9420047c71
--- /dev/null
+++ b/src/3rdparty/xcb/include/xcb/xinput.h
@@ -0,0 +1,9306 @@
+/*
+ * This file generated automatically from xinput.xml by c_client.py.
+ * Edit at your peril.
+ */
+
+/**
+ * @defgroup XCB_Input_API XCB Input API
+ * @brief Input XCB Protocol Implementation.
+ * @{
+ **/
+
+#ifndef __XINPUT_H
+#define __XINPUT_H
+
+#include "xcb.h"
+#include "xfixes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define XCB_INPUT_MAJOR_VERSION 2
+#define XCB_INPUT_MINOR_VERSION 3
+
+extern xcb_extension_t xcb_input_id;
+
+typedef uint32_t xcb_input_event_class_t;
+
+/**
+ * @brief xcb_input_event_class_iterator_t
+ **/
+typedef struct xcb_input_event_class_iterator_t {
+ xcb_input_event_class_t *data;
+ int rem;
+ int index;
+} xcb_input_event_class_iterator_t;
+
+typedef uint8_t xcb_input_key_code_t;
+
+/**
+ * @brief xcb_input_key_code_iterator_t
+ **/
+typedef struct xcb_input_key_code_iterator_t {
+ xcb_input_key_code_t *data;
+ int rem;
+ int index;
+} xcb_input_key_code_iterator_t;
+
+typedef uint16_t xcb_input_device_id_t;
+
+/**
+ * @brief xcb_input_device_id_iterator_t
+ **/
+typedef struct xcb_input_device_id_iterator_t {
+ xcb_input_device_id_t *data;
+ int rem;
+ int index;
+} xcb_input_device_id_iterator_t;
+
+typedef int32_t xcb_input_fp1616_t;
+
+/**
+ * @brief xcb_input_fp1616_iterator_t
+ **/
+typedef struct xcb_input_fp1616_iterator_t {
+ xcb_input_fp1616_t *data;
+ int rem;
+ int index;
+} xcb_input_fp1616_iterator_t;
+
+/**
+ * @brief xcb_input_fp3232_t
+ **/
+typedef struct xcb_input_fp3232_t {
+ int32_t integral;
+ uint32_t frac;
+} xcb_input_fp3232_t;
+
+/**
+ * @brief xcb_input_fp3232_iterator_t
+ **/
+typedef struct xcb_input_fp3232_iterator_t {
+ xcb_input_fp3232_t *data;
+ int rem;
+ int index;
+} xcb_input_fp3232_iterator_t;
+
+/**
+ * @brief xcb_input_get_extension_version_cookie_t
+ **/
+typedef struct xcb_input_get_extension_version_cookie_t {
+ unsigned int sequence;
+} xcb_input_get_extension_version_cookie_t;
+
+/** Opcode for xcb_input_get_extension_version. */
+#define XCB_INPUT_GET_EXTENSION_VERSION 1
+
+/**
+ * @brief xcb_input_get_extension_version_request_t
+ **/
+typedef struct xcb_input_get_extension_version_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ uint16_t name_len;
+ uint8_t pad0[2];
+} xcb_input_get_extension_version_request_t;
+
+/**
+ * @brief xcb_input_get_extension_version_reply_t
+ **/
+typedef struct xcb_input_get_extension_version_reply_t {
+ uint8_t response_type;
+ uint8_t xi_reply_type;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t server_major;
+ uint16_t server_minor;
+ uint8_t present;
+ uint8_t pad0[19];
+} xcb_input_get_extension_version_reply_t;
+
+typedef enum xcb_input_device_use_t {
+ XCB_INPUT_DEVICE_USE_IS_X_POINTER = 0,
+ XCB_INPUT_DEVICE_USE_IS_X_KEYBOARD = 1,
+ XCB_INPUT_DEVICE_USE_IS_X_EXTENSION_DEVICE = 2,
+ XCB_INPUT_DEVICE_USE_IS_X_EXTENSION_KEYBOARD = 3,
+ XCB_INPUT_DEVICE_USE_IS_X_EXTENSION_POINTER = 4
+} xcb_input_device_use_t;
+
+typedef enum xcb_input_input_class_t {
+ XCB_INPUT_INPUT_CLASS_KEY = 0,
+ XCB_INPUT_INPUT_CLASS_BUTTON = 1,
+ XCB_INPUT_INPUT_CLASS_VALUATOR = 2,
+ XCB_INPUT_INPUT_CLASS_FEEDBACK = 3,
+ XCB_INPUT_INPUT_CLASS_PROXIMITY = 4,
+ XCB_INPUT_INPUT_CLASS_FOCUS = 5,
+ XCB_INPUT_INPUT_CLASS_OTHER = 6
+} xcb_input_input_class_t;
+
+typedef enum xcb_input_valuator_mode_t {
+ XCB_INPUT_VALUATOR_MODE_RELATIVE = 0,
+ XCB_INPUT_VALUATOR_MODE_ABSOLUTE = 1
+} xcb_input_valuator_mode_t;
+
+/**
+ * @brief xcb_input_device_info_t
+ **/
+typedef struct xcb_input_device_info_t {
+ xcb_atom_t device_type;
+ uint8_t device_id;
+ uint8_t num_class_info;
+ uint8_t device_use;
+ uint8_t pad0;
+} xcb_input_device_info_t;
+
+/**
+ * @brief xcb_input_device_info_iterator_t
+ **/
+typedef struct xcb_input_device_info_iterator_t {
+ xcb_input_device_info_t *data;
+ int rem;
+ int index;
+} xcb_input_device_info_iterator_t;
+
+/**
+ * @brief xcb_input_key_info_t
+ **/
+typedef struct xcb_input_key_info_t {
+ uint8_t class_id;
+ uint8_t len;
+ xcb_input_key_code_t min_keycode;
+ xcb_input_key_code_t max_keycode;
+ uint16_t num_keys;
+ uint8_t pad0[2];
+} xcb_input_key_info_t;
+
+/**
+ * @brief xcb_input_key_info_iterator_t
+ **/
+typedef struct xcb_input_key_info_iterator_t {
+ xcb_input_key_info_t *data;
+ int rem;
+ int index;
+} xcb_input_key_info_iterator_t;
+
+/**
+ * @brief xcb_input_button_info_t
+ **/
+typedef struct xcb_input_button_info_t {
+ uint8_t class_id;
+ uint8_t len;
+ uint16_t num_buttons;
+} xcb_input_button_info_t;
+
+/**
+ * @brief xcb_input_button_info_iterator_t
+ **/
+typedef struct xcb_input_button_info_iterator_t {
+ xcb_input_button_info_t *data;
+ int rem;
+ int index;
+} xcb_input_button_info_iterator_t;
+
+/**
+ * @brief xcb_input_axis_info_t
+ **/
+typedef struct xcb_input_axis_info_t {
+ uint32_t resolution;
+ int32_t minimum;
+ int32_t maximum;
+} xcb_input_axis_info_t;
+
+/**
+ * @brief xcb_input_axis_info_iterator_t
+ **/
+typedef struct xcb_input_axis_info_iterator_t {
+ xcb_input_axis_info_t *data;
+ int rem;
+ int index;
+} xcb_input_axis_info_iterator_t;
+
+/**
+ * @brief xcb_input_valuator_info_t
+ **/
+typedef struct xcb_input_valuator_info_t {
+ uint8_t class_id;
+ uint8_t len;
+ uint8_t axes_len;
+ uint8_t mode;
+ uint32_t motion_size;
+} xcb_input_valuator_info_t;
+
+/**
+ * @brief xcb_input_valuator_info_iterator_t
+ **/
+typedef struct xcb_input_valuator_info_iterator_t {
+ xcb_input_valuator_info_t *data;
+ int rem;
+ int index;
+} xcb_input_valuator_info_iterator_t;
+
+/**
+ * @brief xcb_input_input_info_info_t
+ **/
+typedef struct xcb_input_input_info_info_t {
+ struct {
+ xcb_input_key_code_t min_keycode;
+ xcb_input_key_code_t max_keycode;
+ uint16_t num_keys;
+ uint8_t pad0[2];
+ } key;
+ struct {
+ uint16_t num_buttons;
+ } button;
+ struct {
+ uint8_t axes_len;
+ uint8_t mode;
+ uint32_t motion_size;
+ xcb_input_axis_info_t *axes;
+ } valuator;
+} xcb_input_input_info_info_t;
+
+/**
+ * @brief xcb_input_input_info_t
+ **/
+typedef struct xcb_input_input_info_t {
+ uint8_t class_id;
+ uint8_t len;
+} xcb_input_input_info_t;
+
+void *
+xcb_input_input_info_info (const xcb_input_input_info_t *R);
+
+/**
+ * @brief xcb_input_input_info_iterator_t
+ **/
+typedef struct xcb_input_input_info_iterator_t {
+ xcb_input_input_info_t *data;
+ int rem;
+ int index;
+} xcb_input_input_info_iterator_t;
+
+/**
+ * @brief xcb_input_device_name_t
+ **/
+typedef struct xcb_input_device_name_t {
+ uint8_t len;
+} xcb_input_device_name_t;
+
+/**
+ * @brief xcb_input_device_name_iterator_t
+ **/
+typedef struct xcb_input_device_name_iterator_t {
+ xcb_input_device_name_t *data;
+ int rem;
+ int index;
+} xcb_input_device_name_iterator_t;
+
+/**
+ * @brief xcb_input_list_input_devices_cookie_t
+ **/
+typedef struct xcb_input_list_input_devices_cookie_t {
+ unsigned int sequence;
+} xcb_input_list_input_devices_cookie_t;
+
+/** Opcode for xcb_input_list_input_devices. */
+#define XCB_INPUT_LIST_INPUT_DEVICES 2
+
+/**
+ * @brief xcb_input_list_input_devices_request_t
+ **/
+typedef struct xcb_input_list_input_devices_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+} xcb_input_list_input_devices_request_t;
+
+/**
+ * @brief xcb_input_list_input_devices_reply_t
+ **/
+typedef struct xcb_input_list_input_devices_reply_t {
+ uint8_t response_type;
+ uint8_t xi_reply_type;
+ uint16_t sequence;
+ uint32_t length;
+ uint8_t devices_len;
+ uint8_t pad0[23];
+} xcb_input_list_input_devices_reply_t;
+
+typedef uint8_t xcb_input_event_type_base_t;
+
+/**
+ * @brief xcb_input_event_type_base_iterator_t
+ **/
+typedef struct xcb_input_event_type_base_iterator_t {
+ xcb_input_event_type_base_t *data;
+ int rem;
+ int index;
+} xcb_input_event_type_base_iterator_t;
+
+/**
+ * @brief xcb_input_input_class_info_t
+ **/
+typedef struct xcb_input_input_class_info_t {
+ uint8_t class_id;
+ xcb_input_event_type_base_t event_type_base;
+} xcb_input_input_class_info_t;
+
+/**
+ * @brief xcb_input_input_class_info_iterator_t
+ **/
+typedef struct xcb_input_input_class_info_iterator_t {
+ xcb_input_input_class_info_t *data;
+ int rem;
+ int index;
+} xcb_input_input_class_info_iterator_t;
+
+/**
+ * @brief xcb_input_open_device_cookie_t
+ **/
+typedef struct xcb_input_open_device_cookie_t {
+ unsigned int sequence;
+} xcb_input_open_device_cookie_t;
+
+/** Opcode for xcb_input_open_device. */
+#define XCB_INPUT_OPEN_DEVICE 3
+
+/**
+ * @brief xcb_input_open_device_request_t
+ **/
+typedef struct xcb_input_open_device_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ uint8_t device_id;
+ uint8_t pad0[3];
+} xcb_input_open_device_request_t;
+
+/**
+ * @brief xcb_input_open_device_reply_t
+ **/
+typedef struct xcb_input_open_device_reply_t {
+ uint8_t response_type;
+ uint8_t xi_reply_type;
+ uint16_t sequence;
+ uint32_t length;
+ uint8_t num_classes;
+ uint8_t pad0[23];
+} xcb_input_open_device_reply_t;
+
+/** Opcode for xcb_input_close_device. */
+#define XCB_INPUT_CLOSE_DEVICE 4
+
+/**
+ * @brief xcb_input_close_device_request_t
+ **/
+typedef struct xcb_input_close_device_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ uint8_t device_id;
+ uint8_t pad0[3];
+} xcb_input_close_device_request_t;
+
+/**
+ * @brief xcb_input_set_device_mode_cookie_t
+ **/
+typedef struct xcb_input_set_device_mode_cookie_t {
+ unsigned int sequence;
+} xcb_input_set_device_mode_cookie_t;
+
+/** Opcode for xcb_input_set_device_mode. */
+#define XCB_INPUT_SET_DEVICE_MODE 5
+
+/**
+ * @brief xcb_input_set_device_mode_request_t
+ **/
+typedef struct xcb_input_set_device_mode_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ uint8_t device_id;
+ uint8_t mode;
+ uint8_t pad0[2];
+} xcb_input_set_device_mode_request_t;
+
+/**
+ * @brief xcb_input_set_device_mode_reply_t
+ **/
+typedef struct xcb_input_set_device_mode_reply_t {
+ uint8_t response_type;
+ uint8_t xi_reply_type;
+ uint16_t sequence;
+ uint32_t length;
+ uint8_t status;
+ uint8_t pad0[23];
+} xcb_input_set_device_mode_reply_t;
+
+/** Opcode for xcb_input_select_extension_event. */
+#define XCB_INPUT_SELECT_EXTENSION_EVENT 6
+
+/**
+ * @brief xcb_input_select_extension_event_request_t
+ **/
+typedef struct xcb_input_select_extension_event_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_window_t window;
+ uint16_t num_classes;
+ uint8_t pad0[2];
+} xcb_input_select_extension_event_request_t;
+
+/**
+ * @brief xcb_input_get_selected_extension_events_cookie_t
+ **/
+typedef struct xcb_input_get_selected_extension_events_cookie_t {
+ unsigned int sequence;
+} xcb_input_get_selected_extension_events_cookie_t;
+
+/** Opcode for xcb_input_get_selected_extension_events. */
+#define XCB_INPUT_GET_SELECTED_EXTENSION_EVENTS 7
+
+/**
+ * @brief xcb_input_get_selected_extension_events_request_t
+ **/
+typedef struct xcb_input_get_selected_extension_events_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_window_t window;
+} xcb_input_get_selected_extension_events_request_t;
+
+/**
+ * @brief xcb_input_get_selected_extension_events_reply_t
+ **/
+typedef struct xcb_input_get_selected_extension_events_reply_t {
+ uint8_t response_type;
+ uint8_t xi_reply_type;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t num_this_classes;
+ uint16_t num_all_classes;
+ uint8_t pad0[20];
+} xcb_input_get_selected_extension_events_reply_t;
+
+typedef enum xcb_input_propagate_mode_t {
+ XCB_INPUT_PROPAGATE_MODE_ADD_TO_LIST = 0,
+ XCB_INPUT_PROPAGATE_MODE_DELETE_FROM_LIST = 1
+} xcb_input_propagate_mode_t;
+
+/** Opcode for xcb_input_change_device_dont_propagate_list. */
+#define XCB_INPUT_CHANGE_DEVICE_DONT_PROPAGATE_LIST 8
+
+/**
+ * @brief xcb_input_change_device_dont_propagate_list_request_t
+ **/
+typedef struct xcb_input_change_device_dont_propagate_list_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_window_t window;
+ uint16_t num_classes;
+ uint8_t mode;
+ uint8_t pad0;
+} xcb_input_change_device_dont_propagate_list_request_t;
+
+/**
+ * @brief xcb_input_get_device_dont_propagate_list_cookie_t
+ **/
+typedef struct xcb_input_get_device_dont_propagate_list_cookie_t {
+ unsigned int sequence;
+} xcb_input_get_device_dont_propagate_list_cookie_t;
+
+/** Opcode for xcb_input_get_device_dont_propagate_list. */
+#define XCB_INPUT_GET_DEVICE_DONT_PROPAGATE_LIST 9
+
+/**
+ * @brief xcb_input_get_device_dont_propagate_list_request_t
+ **/
+typedef struct xcb_input_get_device_dont_propagate_list_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_window_t window;
+} xcb_input_get_device_dont_propagate_list_request_t;
+
+/**
+ * @brief xcb_input_get_device_dont_propagate_list_reply_t
+ **/
+typedef struct xcb_input_get_device_dont_propagate_list_reply_t {
+ uint8_t response_type;
+ uint8_t xi_reply_type;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t num_classes;
+ uint8_t pad0[22];
+} xcb_input_get_device_dont_propagate_list_reply_t;
+
+/**
+ * @brief xcb_input_device_time_coord_t
+ **/
+typedef struct xcb_input_device_time_coord_t {
+ xcb_timestamp_t time;
+} xcb_input_device_time_coord_t;
+
+/**
+ * @brief xcb_input_device_time_coord_iterator_t
+ **/
+typedef struct xcb_input_device_time_coord_iterator_t {
+ xcb_input_device_time_coord_t *data;
+ int rem;
+ int index;
+ uint8_t num_axes; /**< */
+} xcb_input_device_time_coord_iterator_t;
+
+/**
+ * @brief xcb_input_get_device_motion_events_cookie_t
+ **/
+typedef struct xcb_input_get_device_motion_events_cookie_t {
+ unsigned int sequence;
+} xcb_input_get_device_motion_events_cookie_t;
+
+/** Opcode for xcb_input_get_device_motion_events. */
+#define XCB_INPUT_GET_DEVICE_MOTION_EVENTS 10
+
+/**
+ * @brief xcb_input_get_device_motion_events_request_t
+ **/
+typedef struct xcb_input_get_device_motion_events_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_timestamp_t start;
+ xcb_timestamp_t stop;
+ uint8_t device_id;
+ uint8_t pad0[3];
+} xcb_input_get_device_motion_events_request_t;
+
+/**
+ * @brief xcb_input_get_device_motion_events_reply_t
+ **/
+typedef struct xcb_input_get_device_motion_events_reply_t {
+ uint8_t response_type;
+ uint8_t xi_reply_type;
+ uint16_t sequence;
+ uint32_t length;
+ uint32_t num_events;
+ uint8_t num_axes;
+ uint8_t device_mode;
+ uint8_t pad0[18];
+} xcb_input_get_device_motion_events_reply_t;
+
+/**
+ * @brief xcb_input_change_keyboard_device_cookie_t
+ **/
+typedef struct xcb_input_change_keyboard_device_cookie_t {
+ unsigned int sequence;
+} xcb_input_change_keyboard_device_cookie_t;
+
+/** Opcode for xcb_input_change_keyboard_device. */
+#define XCB_INPUT_CHANGE_KEYBOARD_DEVICE 11
+
+/**
+ * @brief xcb_input_change_keyboard_device_request_t
+ **/
+typedef struct xcb_input_change_keyboard_device_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ uint8_t device_id;
+ uint8_t pad0[3];
+} xcb_input_change_keyboard_device_request_t;
+
+/**
+ * @brief xcb_input_change_keyboard_device_reply_t
+ **/
+typedef struct xcb_input_change_keyboard_device_reply_t {
+ uint8_t response_type;
+ uint8_t xi_reply_type;
+ uint16_t sequence;
+ uint32_t length;
+ uint8_t status;
+ uint8_t pad0[23];
+} xcb_input_change_keyboard_device_reply_t;
+
+/**
+ * @brief xcb_input_change_pointer_device_cookie_t
+ **/
+typedef struct xcb_input_change_pointer_device_cookie_t {
+ unsigned int sequence;
+} xcb_input_change_pointer_device_cookie_t;
+
+/** Opcode for xcb_input_change_pointer_device. */
+#define XCB_INPUT_CHANGE_POINTER_DEVICE 12
+
+/**
+ * @brief xcb_input_change_pointer_device_request_t
+ **/
+typedef struct xcb_input_change_pointer_device_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ uint8_t x_axis;
+ uint8_t y_axis;
+ uint8_t device_id;
+ uint8_t pad0;
+} xcb_input_change_pointer_device_request_t;
+
+/**
+ * @brief xcb_input_change_pointer_device_reply_t
+ **/
+typedef struct xcb_input_change_pointer_device_reply_t {
+ uint8_t response_type;
+ uint8_t xi_reply_type;
+ uint16_t sequence;
+ uint32_t length;
+ uint8_t status;
+ uint8_t pad0[23];
+} xcb_input_change_pointer_device_reply_t;
+
+/**
+ * @brief xcb_input_grab_device_cookie_t
+ **/
+typedef struct xcb_input_grab_device_cookie_t {
+ unsigned int sequence;
+} xcb_input_grab_device_cookie_t;
+
+/** Opcode for xcb_input_grab_device. */
+#define XCB_INPUT_GRAB_DEVICE 13
+
+/**
+ * @brief xcb_input_grab_device_request_t
+ **/
+typedef struct xcb_input_grab_device_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_window_t grab_window;
+ xcb_timestamp_t time;
+ uint16_t num_classes;
+ uint8_t this_device_mode;
+ uint8_t other_device_mode;
+ uint8_t owner_events;
+ uint8_t device_id;
+ uint8_t pad0[2];
+} xcb_input_grab_device_request_t;
+
+/**
+ * @brief xcb_input_grab_device_reply_t
+ **/
+typedef struct xcb_input_grab_device_reply_t {
+ uint8_t response_type;
+ uint8_t xi_reply_type;
+ uint16_t sequence;
+ uint32_t length;
+ uint8_t status;
+ uint8_t pad0[23];
+} xcb_input_grab_device_reply_t;
+
+/** Opcode for xcb_input_ungrab_device. */
+#define XCB_INPUT_UNGRAB_DEVICE 14
+
+/**
+ * @brief xcb_input_ungrab_device_request_t
+ **/
+typedef struct xcb_input_ungrab_device_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_timestamp_t time;
+ uint8_t device_id;
+ uint8_t pad0[3];
+} xcb_input_ungrab_device_request_t;
+
+typedef enum xcb_input_modifier_device_t {
+ XCB_INPUT_MODIFIER_DEVICE_USE_X_KEYBOARD = 255
+} xcb_input_modifier_device_t;
+
+/** Opcode for xcb_input_grab_device_key. */
+#define XCB_INPUT_GRAB_DEVICE_KEY 15
+
+/**
+ * @brief xcb_input_grab_device_key_request_t
+ **/
+typedef struct xcb_input_grab_device_key_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_window_t grab_window;
+ uint16_t num_classes;
+ uint16_t modifiers;
+ uint8_t modifier_device;
+ uint8_t grabbed_device;
+ uint8_t key;
+ uint8_t this_device_mode;
+ uint8_t other_device_mode;
+ uint8_t owner_events;
+ uint8_t pad0[2];
+} xcb_input_grab_device_key_request_t;
+
+/** Opcode for xcb_input_ungrab_device_key. */
+#define XCB_INPUT_UNGRAB_DEVICE_KEY 16
+
+/**
+ * @brief xcb_input_ungrab_device_key_request_t
+ **/
+typedef struct xcb_input_ungrab_device_key_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_window_t grabWindow;
+ uint16_t modifiers;
+ uint8_t modifier_device;
+ uint8_t key;
+ uint8_t grabbed_device;
+} xcb_input_ungrab_device_key_request_t;
+
+/** Opcode for xcb_input_grab_device_button. */
+#define XCB_INPUT_GRAB_DEVICE_BUTTON 17
+
+/**
+ * @brief xcb_input_grab_device_button_request_t
+ **/
+typedef struct xcb_input_grab_device_button_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_window_t grab_window;
+ uint8_t grabbed_device;
+ uint8_t modifier_device;
+ uint16_t num_classes;
+ uint16_t modifiers;
+ uint8_t this_device_mode;
+ uint8_t other_device_mode;
+ uint8_t button;
+ uint8_t owner_events;
+ uint8_t pad0[2];
+} xcb_input_grab_device_button_request_t;
+
+/** Opcode for xcb_input_ungrab_device_button. */
+#define XCB_INPUT_UNGRAB_DEVICE_BUTTON 18
+
+/**
+ * @brief xcb_input_ungrab_device_button_request_t
+ **/
+typedef struct xcb_input_ungrab_device_button_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_window_t grab_window;
+ uint16_t modifiers;
+ uint8_t modifier_device;
+ uint8_t button;
+ uint8_t grabbed_device;
+ uint8_t pad0[3];
+} xcb_input_ungrab_device_button_request_t;
+
+typedef enum xcb_input_device_input_mode_t {
+ XCB_INPUT_DEVICE_INPUT_MODE_ASYNC_THIS_DEVICE = 0,
+ XCB_INPUT_DEVICE_INPUT_MODE_SYNC_THIS_DEVICE = 1,
+ XCB_INPUT_DEVICE_INPUT_MODE_REPLAY_THIS_DEVICE = 2,
+ XCB_INPUT_DEVICE_INPUT_MODE_ASYNC_OTHER_DEVICES = 3,
+ XCB_INPUT_DEVICE_INPUT_MODE_ASYNC_ALL = 4,
+ XCB_INPUT_DEVICE_INPUT_MODE_SYNC_ALL = 5
+} xcb_input_device_input_mode_t;
+
+/** Opcode for xcb_input_allow_device_events. */
+#define XCB_INPUT_ALLOW_DEVICE_EVENTS 19
+
+/**
+ * @brief xcb_input_allow_device_events_request_t
+ **/
+typedef struct xcb_input_allow_device_events_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_timestamp_t time;
+ uint8_t mode;
+ uint8_t device_id;
+ uint8_t pad0[2];
+} xcb_input_allow_device_events_request_t;
+
+/**
+ * @brief xcb_input_get_device_focus_cookie_t
+ **/
+typedef struct xcb_input_get_device_focus_cookie_t {
+ unsigned int sequence;
+} xcb_input_get_device_focus_cookie_t;
+
+/** Opcode for xcb_input_get_device_focus. */
+#define XCB_INPUT_GET_DEVICE_FOCUS 20
+
+/**
+ * @brief xcb_input_get_device_focus_request_t
+ **/
+typedef struct xcb_input_get_device_focus_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ uint8_t device_id;
+ uint8_t pad0[3];
+} xcb_input_get_device_focus_request_t;
+
+/**
+ * @brief xcb_input_get_device_focus_reply_t
+ **/
+typedef struct xcb_input_get_device_focus_reply_t {
+ uint8_t response_type;
+ uint8_t xi_reply_type;
+ uint16_t sequence;
+ uint32_t length;
+ xcb_window_t focus;
+ xcb_timestamp_t time;
+ uint8_t revert_to;
+ uint8_t pad0[15];
+} xcb_input_get_device_focus_reply_t;
+
+/** Opcode for xcb_input_set_device_focus. */
+#define XCB_INPUT_SET_DEVICE_FOCUS 21
+
+/**
+ * @brief xcb_input_set_device_focus_request_t
+ **/
+typedef struct xcb_input_set_device_focus_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_window_t focus;
+ xcb_timestamp_t time;
+ uint8_t revert_to;
+ uint8_t device_id;
+ uint8_t pad0[2];
+} xcb_input_set_device_focus_request_t;
+
+typedef enum xcb_input_feedback_class_t {
+ XCB_INPUT_FEEDBACK_CLASS_KEYBOARD = 0,
+ XCB_INPUT_FEEDBACK_CLASS_POINTER = 1,
+ XCB_INPUT_FEEDBACK_CLASS_STRING = 2,
+ XCB_INPUT_FEEDBACK_CLASS_INTEGER = 3,
+ XCB_INPUT_FEEDBACK_CLASS_LED = 4,
+ XCB_INPUT_FEEDBACK_CLASS_BELL = 5
+} xcb_input_feedback_class_t;
+
+/**
+ * @brief xcb_input_kbd_feedback_state_t
+ **/
+typedef struct xcb_input_kbd_feedback_state_t {
+ uint8_t class_id;
+ uint8_t feedback_id;
+ uint16_t len;
+ uint16_t pitch;
+ uint16_t duration;
+ uint32_t led_mask;
+ uint32_t led_values;
+ uint8_t global_auto_repeat;
+ uint8_t click;
+ uint8_t percent;
+ uint8_t pad0;
+ uint8_t auto_repeats[32];
+} xcb_input_kbd_feedback_state_t;
+
+/**
+ * @brief xcb_input_kbd_feedback_state_iterator_t
+ **/
+typedef struct xcb_input_kbd_feedback_state_iterator_t {
+ xcb_input_kbd_feedback_state_t *data;
+ int rem;
+ int index;
+} xcb_input_kbd_feedback_state_iterator_t;
+
+/**
+ * @brief xcb_input_ptr_feedback_state_t
+ **/
+typedef struct xcb_input_ptr_feedback_state_t {
+ uint8_t class_id;
+ uint8_t feedback_id;
+ uint16_t len;
+ uint8_t pad0[2];
+ uint16_t accel_num;
+ uint16_t accel_denom;
+ uint16_t threshold;
+} xcb_input_ptr_feedback_state_t;
+
+/**
+ * @brief xcb_input_ptr_feedback_state_iterator_t
+ **/
+typedef struct xcb_input_ptr_feedback_state_iterator_t {
+ xcb_input_ptr_feedback_state_t *data;
+ int rem;
+ int index;
+} xcb_input_ptr_feedback_state_iterator_t;
+
+/**
+ * @brief xcb_input_integer_feedback_state_t
+ **/
+typedef struct xcb_input_integer_feedback_state_t {
+ uint8_t class_id;
+ uint8_t feedback_id;
+ uint16_t len;
+ uint32_t resolution;
+ int32_t min_value;
+ int32_t max_value;
+} xcb_input_integer_feedback_state_t;
+
+/**
+ * @brief xcb_input_integer_feedback_state_iterator_t
+ **/
+typedef struct xcb_input_integer_feedback_state_iterator_t {
+ xcb_input_integer_feedback_state_t *data;
+ int rem;
+ int index;
+} xcb_input_integer_feedback_state_iterator_t;
+
+/**
+ * @brief xcb_input_string_feedback_state_t
+ **/
+typedef struct xcb_input_string_feedback_state_t {
+ uint8_t class_id;
+ uint8_t feedback_id;
+ uint16_t len;
+ uint16_t max_symbols;
+ uint16_t num_keysyms;
+} xcb_input_string_feedback_state_t;
+
+/**
+ * @brief xcb_input_string_feedback_state_iterator_t
+ **/
+typedef struct xcb_input_string_feedback_state_iterator_t {
+ xcb_input_string_feedback_state_t *data;
+ int rem;
+ int index;
+} xcb_input_string_feedback_state_iterator_t;
+
+/**
+ * @brief xcb_input_bell_feedback_state_t
+ **/
+typedef struct xcb_input_bell_feedback_state_t {
+ uint8_t class_id;
+ uint8_t feedback_id;
+ uint16_t len;
+ uint8_t percent;
+ uint8_t pad0[3];
+ uint16_t pitch;
+ uint16_t duration;
+} xcb_input_bell_feedback_state_t;
+
+/**
+ * @brief xcb_input_bell_feedback_state_iterator_t
+ **/
+typedef struct xcb_input_bell_feedback_state_iterator_t {
+ xcb_input_bell_feedback_state_t *data;
+ int rem;
+ int index;
+} xcb_input_bell_feedback_state_iterator_t;
+
+/**
+ * @brief xcb_input_led_feedback_state_t
+ **/
+typedef struct xcb_input_led_feedback_state_t {
+ uint8_t class_id;
+ uint8_t feedback_id;
+ uint16_t len;
+ uint32_t led_mask;
+ uint32_t led_values;
+} xcb_input_led_feedback_state_t;
+
+/**
+ * @brief xcb_input_led_feedback_state_iterator_t
+ **/
+typedef struct xcb_input_led_feedback_state_iterator_t {
+ xcb_input_led_feedback_state_t *data;
+ int rem;
+ int index;
+} xcb_input_led_feedback_state_iterator_t;
+
+/**
+ * @brief xcb_input_feedback_state_data_t
+ **/
+typedef struct xcb_input_feedback_state_data_t {
+ struct {
+ uint16_t pitch;
+ uint16_t duration;
+ uint32_t led_mask;
+ uint32_t led_values;
+ uint8_t global_auto_repeat;
+ uint8_t click;
+ uint8_t percent;
+ uint8_t pad0;
+ uint8_t auto_repeats[32];
+ } keyboard;
+ struct {
+ uint8_t pad1[2];
+ uint16_t accel_num;
+ uint16_t accel_denom;
+ uint16_t threshold;
+ } pointer;
+ struct {
+ uint16_t max_symbols;
+ uint16_t num_keysyms;
+ xcb_keysym_t *keysyms;
+ } string;
+ struct {
+ uint32_t resolution;
+ int32_t min_value;
+ int32_t max_value;
+ } integer;
+ struct {
+ uint32_t led_mask;
+ uint32_t led_values;
+ } led;
+ struct {
+ uint8_t percent;
+ uint8_t pad2[3];
+ uint16_t pitch;
+ uint16_t duration;
+ } bell;
+} xcb_input_feedback_state_data_t;
+
+/**
+ * @brief xcb_input_feedback_state_t
+ **/
+typedef struct xcb_input_feedback_state_t {
+ uint8_t class_id;
+ uint8_t feedback_id;
+ uint16_t len;
+} xcb_input_feedback_state_t;
+
+void *
+xcb_input_feedback_state_data (const xcb_input_feedback_state_t *R);
+
+/**
+ * @brief xcb_input_feedback_state_iterator_t
+ **/
+typedef struct xcb_input_feedback_state_iterator_t {
+ xcb_input_feedback_state_t *data;
+ int rem;
+ int index;
+} xcb_input_feedback_state_iterator_t;
+
+/**
+ * @brief xcb_input_get_feedback_control_cookie_t
+ **/
+typedef struct xcb_input_get_feedback_control_cookie_t {
+ unsigned int sequence;
+} xcb_input_get_feedback_control_cookie_t;
+
+/** Opcode for xcb_input_get_feedback_control. */
+#define XCB_INPUT_GET_FEEDBACK_CONTROL 22
+
+/**
+ * @brief xcb_input_get_feedback_control_request_t
+ **/
+typedef struct xcb_input_get_feedback_control_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ uint8_t device_id;
+ uint8_t pad0[3];
+} xcb_input_get_feedback_control_request_t;
+
+/**
+ * @brief xcb_input_get_feedback_control_reply_t
+ **/
+typedef struct xcb_input_get_feedback_control_reply_t {
+ uint8_t response_type;
+ uint8_t xi_reply_type;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t num_feedbacks;
+ uint8_t pad0[22];
+} xcb_input_get_feedback_control_reply_t;
+
+/**
+ * @brief xcb_input_kbd_feedback_ctl_t
+ **/
+typedef struct xcb_input_kbd_feedback_ctl_t {
+ uint8_t class_id;
+ uint8_t feedback_id;
+ uint16_t len;
+ xcb_input_key_code_t key;
+ uint8_t auto_repeat_mode;
+ int8_t key_click_percent;
+ int8_t bell_percent;
+ int16_t bell_pitch;
+ int16_t bell_duration;
+ uint32_t led_mask;
+ uint32_t led_values;
+} xcb_input_kbd_feedback_ctl_t;
+
+/**
+ * @brief xcb_input_kbd_feedback_ctl_iterator_t
+ **/
+typedef struct xcb_input_kbd_feedback_ctl_iterator_t {
+ xcb_input_kbd_feedback_ctl_t *data;
+ int rem;
+ int index;
+} xcb_input_kbd_feedback_ctl_iterator_t;
+
+/**
+ * @brief xcb_input_ptr_feedback_ctl_t
+ **/
+typedef struct xcb_input_ptr_feedback_ctl_t {
+ uint8_t class_id;
+ uint8_t feedback_id;
+ uint16_t len;
+ uint8_t pad0[2];
+ int16_t num;
+ int16_t denom;
+ int16_t threshold;
+} xcb_input_ptr_feedback_ctl_t;
+
+/**
+ * @brief xcb_input_ptr_feedback_ctl_iterator_t
+ **/
+typedef struct xcb_input_ptr_feedback_ctl_iterator_t {
+ xcb_input_ptr_feedback_ctl_t *data;
+ int rem;
+ int index;
+} xcb_input_ptr_feedback_ctl_iterator_t;
+
+/**
+ * @brief xcb_input_integer_feedback_ctl_t
+ **/
+typedef struct xcb_input_integer_feedback_ctl_t {
+ uint8_t class_id;
+ uint8_t feedback_id;
+ uint16_t len;
+ int32_t int_to_display;
+} xcb_input_integer_feedback_ctl_t;
+
+/**
+ * @brief xcb_input_integer_feedback_ctl_iterator_t
+ **/
+typedef struct xcb_input_integer_feedback_ctl_iterator_t {
+ xcb_input_integer_feedback_ctl_t *data;
+ int rem;
+ int index;
+} xcb_input_integer_feedback_ctl_iterator_t;
+
+/**
+ * @brief xcb_input_string_feedback_ctl_t
+ **/
+typedef struct xcb_input_string_feedback_ctl_t {
+ uint8_t class_id;
+ uint8_t feedback_id;
+ uint16_t len;
+ uint8_t pad0[2];
+ uint16_t num_keysyms;
+} xcb_input_string_feedback_ctl_t;
+
+/**
+ * @brief xcb_input_string_feedback_ctl_iterator_t
+ **/
+typedef struct xcb_input_string_feedback_ctl_iterator_t {
+ xcb_input_string_feedback_ctl_t *data;
+ int rem;
+ int index;
+} xcb_input_string_feedback_ctl_iterator_t;
+
+/**
+ * @brief xcb_input_bell_feedback_ctl_t
+ **/
+typedef struct xcb_input_bell_feedback_ctl_t {
+ uint8_t class_id;
+ uint8_t feedback_id;
+ uint16_t len;
+ int8_t percent;
+ uint8_t pad0[3];
+ int16_t pitch;
+ int16_t duration;
+} xcb_input_bell_feedback_ctl_t;
+
+/**
+ * @brief xcb_input_bell_feedback_ctl_iterator_t
+ **/
+typedef struct xcb_input_bell_feedback_ctl_iterator_t {
+ xcb_input_bell_feedback_ctl_t *data;
+ int rem;
+ int index;
+} xcb_input_bell_feedback_ctl_iterator_t;
+
+/**
+ * @brief xcb_input_led_feedback_ctl_t
+ **/
+typedef struct xcb_input_led_feedback_ctl_t {
+ uint8_t class_id;
+ uint8_t feedback_id;
+ uint16_t len;
+ uint32_t led_mask;
+ uint32_t led_values;
+} xcb_input_led_feedback_ctl_t;
+
+/**
+ * @brief xcb_input_led_feedback_ctl_iterator_t
+ **/
+typedef struct xcb_input_led_feedback_ctl_iterator_t {
+ xcb_input_led_feedback_ctl_t *data;
+ int rem;
+ int index;
+} xcb_input_led_feedback_ctl_iterator_t;
+
+/**
+ * @brief xcb_input_feedback_ctl_data_t
+ **/
+typedef struct xcb_input_feedback_ctl_data_t {
+ struct {
+ xcb_input_key_code_t key;
+ uint8_t auto_repeat_mode;
+ int8_t key_click_percent;
+ int8_t bell_percent;
+ int16_t bell_pitch;
+ int16_t bell_duration;
+ uint32_t led_mask;
+ uint32_t led_values;
+ } keyboard;
+ struct {
+ uint8_t pad0[2];
+ int16_t num;
+ int16_t denom;
+ int16_t threshold;
+ } pointer;
+ struct {
+ uint8_t pad1[2];
+ uint16_t num_keysyms;
+ xcb_keysym_t *keysyms;
+ } string;
+ struct {
+ int32_t int_to_display;
+ } integer;
+ struct {
+ uint32_t led_mask;
+ uint32_t led_values;
+ } led;
+ struct {
+ int8_t percent;
+ uint8_t pad2[3];
+ int16_t pitch;
+ int16_t duration;
+ } bell;
+} xcb_input_feedback_ctl_data_t;
+
+/**
+ * @brief xcb_input_feedback_ctl_t
+ **/
+typedef struct xcb_input_feedback_ctl_t {
+ uint8_t class_id;
+ uint8_t feedback_id;
+ uint16_t len;
+} xcb_input_feedback_ctl_t;
+
+void *
+xcb_input_feedback_ctl_data (const xcb_input_feedback_ctl_t *R);
+
+/**
+ * @brief xcb_input_feedback_ctl_iterator_t
+ **/
+typedef struct xcb_input_feedback_ctl_iterator_t {
+ xcb_input_feedback_ctl_t *data;
+ int rem;
+ int index;
+} xcb_input_feedback_ctl_iterator_t;
+
+typedef enum xcb_input_change_feedback_control_mask_t {
+ XCB_INPUT_CHANGE_FEEDBACK_CONTROL_MASK_KEY_CLICK_PERCENT = 1,
+ XCB_INPUT_CHANGE_FEEDBACK_CONTROL_MASK_PERCENT = 2,
+ XCB_INPUT_CHANGE_FEEDBACK_CONTROL_MASK_PITCH = 4,
+ XCB_INPUT_CHANGE_FEEDBACK_CONTROL_MASK_DURATION = 8,
+ XCB_INPUT_CHANGE_FEEDBACK_CONTROL_MASK_LED = 16,
+ XCB_INPUT_CHANGE_FEEDBACK_CONTROL_MASK_LED_MODE = 32,
+ XCB_INPUT_CHANGE_FEEDBACK_CONTROL_MASK_KEY = 64,
+ XCB_INPUT_CHANGE_FEEDBACK_CONTROL_MASK_AUTO_REPEAT_MODE = 128,
+ XCB_INPUT_CHANGE_FEEDBACK_CONTROL_MASK_STRING = 1,
+ XCB_INPUT_CHANGE_FEEDBACK_CONTROL_MASK_INTEGER = 1,
+ XCB_INPUT_CHANGE_FEEDBACK_CONTROL_MASK_ACCEL_NUM = 1,
+ XCB_INPUT_CHANGE_FEEDBACK_CONTROL_MASK_ACCEL_DENOM = 2,
+ XCB_INPUT_CHANGE_FEEDBACK_CONTROL_MASK_THRESHOLD = 4
+} xcb_input_change_feedback_control_mask_t;
+
+/** Opcode for xcb_input_change_feedback_control. */
+#define XCB_INPUT_CHANGE_FEEDBACK_CONTROL 23
+
+/**
+ * @brief xcb_input_change_feedback_control_request_t
+ **/
+typedef struct xcb_input_change_feedback_control_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ uint32_t mask;
+ uint8_t device_id;
+ uint8_t feedback_id;
+ uint8_t pad0[2];
+} xcb_input_change_feedback_control_request_t;
+
+/**
+ * @brief xcb_input_get_device_key_mapping_cookie_t
+ **/
+typedef struct xcb_input_get_device_key_mapping_cookie_t {
+ unsigned int sequence;
+} xcb_input_get_device_key_mapping_cookie_t;
+
+/** Opcode for xcb_input_get_device_key_mapping. */
+#define XCB_INPUT_GET_DEVICE_KEY_MAPPING 24
+
+/**
+ * @brief xcb_input_get_device_key_mapping_request_t
+ **/
+typedef struct xcb_input_get_device_key_mapping_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ uint8_t device_id;
+ xcb_input_key_code_t first_keycode;
+ uint8_t count;
+ uint8_t pad0;
+} xcb_input_get_device_key_mapping_request_t;
+
+/**
+ * @brief xcb_input_get_device_key_mapping_reply_t
+ **/
+typedef struct xcb_input_get_device_key_mapping_reply_t {
+ uint8_t response_type;
+ uint8_t xi_reply_type;
+ uint16_t sequence;
+ uint32_t length;
+ uint8_t keysyms_per_keycode;
+ uint8_t pad0[23];
+} xcb_input_get_device_key_mapping_reply_t;
+
+/** Opcode for xcb_input_change_device_key_mapping. */
+#define XCB_INPUT_CHANGE_DEVICE_KEY_MAPPING 25
+
+/**
+ * @brief xcb_input_change_device_key_mapping_request_t
+ **/
+typedef struct xcb_input_change_device_key_mapping_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ uint8_t device_id;
+ xcb_input_key_code_t first_keycode;
+ uint8_t keysyms_per_keycode;
+ uint8_t keycode_count;
+} xcb_input_change_device_key_mapping_request_t;
+
+/**
+ * @brief xcb_input_get_device_modifier_mapping_cookie_t
+ **/
+typedef struct xcb_input_get_device_modifier_mapping_cookie_t {
+ unsigned int sequence;
+} xcb_input_get_device_modifier_mapping_cookie_t;
+
+/** Opcode for xcb_input_get_device_modifier_mapping. */
+#define XCB_INPUT_GET_DEVICE_MODIFIER_MAPPING 26
+
+/**
+ * @brief xcb_input_get_device_modifier_mapping_request_t
+ **/
+typedef struct xcb_input_get_device_modifier_mapping_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ uint8_t device_id;
+ uint8_t pad0[3];
+} xcb_input_get_device_modifier_mapping_request_t;
+
+/**
+ * @brief xcb_input_get_device_modifier_mapping_reply_t
+ **/
+typedef struct xcb_input_get_device_modifier_mapping_reply_t {
+ uint8_t response_type;
+ uint8_t xi_reply_type;
+ uint16_t sequence;
+ uint32_t length;
+ uint8_t keycodes_per_modifier;
+ uint8_t pad0[23];
+} xcb_input_get_device_modifier_mapping_reply_t;
+
+/**
+ * @brief xcb_input_set_device_modifier_mapping_cookie_t
+ **/
+typedef struct xcb_input_set_device_modifier_mapping_cookie_t {
+ unsigned int sequence;
+} xcb_input_set_device_modifier_mapping_cookie_t;
+
+/** Opcode for xcb_input_set_device_modifier_mapping. */
+#define XCB_INPUT_SET_DEVICE_MODIFIER_MAPPING 27
+
+/**
+ * @brief xcb_input_set_device_modifier_mapping_request_t
+ **/
+typedef struct xcb_input_set_device_modifier_mapping_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ uint8_t device_id;
+ uint8_t keycodes_per_modifier;
+ uint8_t pad0[2];
+} xcb_input_set_device_modifier_mapping_request_t;
+
+/**
+ * @brief xcb_input_set_device_modifier_mapping_reply_t
+ **/
+typedef struct xcb_input_set_device_modifier_mapping_reply_t {
+ uint8_t response_type;
+ uint8_t xi_reply_type;
+ uint16_t sequence;
+ uint32_t length;
+ uint8_t status;
+ uint8_t pad0[23];
+} xcb_input_set_device_modifier_mapping_reply_t;
+
+/**
+ * @brief xcb_input_get_device_button_mapping_cookie_t
+ **/
+typedef struct xcb_input_get_device_button_mapping_cookie_t {
+ unsigned int sequence;
+} xcb_input_get_device_button_mapping_cookie_t;
+
+/** Opcode for xcb_input_get_device_button_mapping. */
+#define XCB_INPUT_GET_DEVICE_BUTTON_MAPPING 28
+
+/**
+ * @brief xcb_input_get_device_button_mapping_request_t
+ **/
+typedef struct xcb_input_get_device_button_mapping_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ uint8_t device_id;
+ uint8_t pad0[3];
+} xcb_input_get_device_button_mapping_request_t;
+
+/**
+ * @brief xcb_input_get_device_button_mapping_reply_t
+ **/
+typedef struct xcb_input_get_device_button_mapping_reply_t {
+ uint8_t response_type;
+ uint8_t xi_reply_type;
+ uint16_t sequence;
+ uint32_t length;
+ uint8_t map_size;
+ uint8_t pad0[23];
+} xcb_input_get_device_button_mapping_reply_t;
+
+/**
+ * @brief xcb_input_set_device_button_mapping_cookie_t
+ **/
+typedef struct xcb_input_set_device_button_mapping_cookie_t {
+ unsigned int sequence;
+} xcb_input_set_device_button_mapping_cookie_t;
+
+/** Opcode for xcb_input_set_device_button_mapping. */
+#define XCB_INPUT_SET_DEVICE_BUTTON_MAPPING 29
+
+/**
+ * @brief xcb_input_set_device_button_mapping_request_t
+ **/
+typedef struct xcb_input_set_device_button_mapping_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ uint8_t device_id;
+ uint8_t map_size;
+ uint8_t pad0[2];
+} xcb_input_set_device_button_mapping_request_t;
+
+/**
+ * @brief xcb_input_set_device_button_mapping_reply_t
+ **/
+typedef struct xcb_input_set_device_button_mapping_reply_t {
+ uint8_t response_type;
+ uint8_t xi_reply_type;
+ uint16_t sequence;
+ uint32_t length;
+ uint8_t status;
+ uint8_t pad0[23];
+} xcb_input_set_device_button_mapping_reply_t;
+
+/**
+ * @brief xcb_input_key_state_t
+ **/
+typedef struct xcb_input_key_state_t {
+ uint8_t class_id;
+ uint8_t len;
+ uint8_t num_keys;
+ uint8_t pad0;
+ uint8_t keys[32];
+} xcb_input_key_state_t;
+
+/**
+ * @brief xcb_input_key_state_iterator_t
+ **/
+typedef struct xcb_input_key_state_iterator_t {
+ xcb_input_key_state_t *data;
+ int rem;
+ int index;
+} xcb_input_key_state_iterator_t;
+
+/**
+ * @brief xcb_input_button_state_t
+ **/
+typedef struct xcb_input_button_state_t {
+ uint8_t class_id;
+ uint8_t len;
+ uint8_t num_buttons;
+ uint8_t pad0;
+ uint8_t buttons[32];
+} xcb_input_button_state_t;
+
+/**
+ * @brief xcb_input_button_state_iterator_t
+ **/
+typedef struct xcb_input_button_state_iterator_t {
+ xcb_input_button_state_t *data;
+ int rem;
+ int index;
+} xcb_input_button_state_iterator_t;
+
+typedef enum xcb_input_valuator_state_mode_mask_t {
+ XCB_INPUT_VALUATOR_STATE_MODE_MASK_DEVICE_MODE_ABSOLUTE = 1,
+ XCB_INPUT_VALUATOR_STATE_MODE_MASK_OUT_OF_PROXIMITY = 2
+} xcb_input_valuator_state_mode_mask_t;
+
+/**
+ * @brief xcb_input_valuator_state_t
+ **/
+typedef struct xcb_input_valuator_state_t {
+ uint8_t class_id;
+ uint8_t len;
+ uint8_t num_valuators;
+ uint8_t mode;
+} xcb_input_valuator_state_t;
+
+/**
+ * @brief xcb_input_valuator_state_iterator_t
+ **/
+typedef struct xcb_input_valuator_state_iterator_t {
+ xcb_input_valuator_state_t *data;
+ int rem;
+ int index;
+} xcb_input_valuator_state_iterator_t;
+
+/**
+ * @brief xcb_input_input_state_data_t
+ **/
+typedef struct xcb_input_input_state_data_t {
+ struct {
+ uint8_t num_keys;
+ uint8_t pad0;
+ uint8_t keys[32];
+ } key;
+ struct {
+ uint8_t num_buttons;
+ uint8_t pad1;
+ uint8_t buttons[32];
+ } button;
+ struct {
+ uint8_t num_valuators;
+ uint8_t mode;
+ int32_t *valuators;
+ } valuator;
+} xcb_input_input_state_data_t;
+
+/**
+ * @brief xcb_input_input_state_t
+ **/
+typedef struct xcb_input_input_state_t {
+ uint8_t class_id;
+ uint8_t len;
+} xcb_input_input_state_t;
+
+void *
+xcb_input_input_state_data (const xcb_input_input_state_t *R);
+
+/**
+ * @brief xcb_input_input_state_iterator_t
+ **/
+typedef struct xcb_input_input_state_iterator_t {
+ xcb_input_input_state_t *data;
+ int rem;
+ int index;
+} xcb_input_input_state_iterator_t;
+
+/**
+ * @brief xcb_input_query_device_state_cookie_t
+ **/
+typedef struct xcb_input_query_device_state_cookie_t {
+ unsigned int sequence;
+} xcb_input_query_device_state_cookie_t;
+
+/** Opcode for xcb_input_query_device_state. */
+#define XCB_INPUT_QUERY_DEVICE_STATE 30
+
+/**
+ * @brief xcb_input_query_device_state_request_t
+ **/
+typedef struct xcb_input_query_device_state_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ uint8_t device_id;
+ uint8_t pad0[3];
+} xcb_input_query_device_state_request_t;
+
+/**
+ * @brief xcb_input_query_device_state_reply_t
+ **/
+typedef struct xcb_input_query_device_state_reply_t {
+ uint8_t response_type;
+ uint8_t xi_reply_type;
+ uint16_t sequence;
+ uint32_t length;
+ uint8_t num_classes;
+ uint8_t pad0[23];
+} xcb_input_query_device_state_reply_t;
+
+/** Opcode for xcb_input_device_bell. */
+#define XCB_INPUT_DEVICE_BELL 32
+
+/**
+ * @brief xcb_input_device_bell_request_t
+ **/
+typedef struct xcb_input_device_bell_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ uint8_t device_id;
+ uint8_t feedback_id;
+ uint8_t feedback_class;
+ int8_t percent;
+} xcb_input_device_bell_request_t;
+
+/**
+ * @brief xcb_input_set_device_valuators_cookie_t
+ **/
+typedef struct xcb_input_set_device_valuators_cookie_t {
+ unsigned int sequence;
+} xcb_input_set_device_valuators_cookie_t;
+
+/** Opcode for xcb_input_set_device_valuators. */
+#define XCB_INPUT_SET_DEVICE_VALUATORS 33
+
+/**
+ * @brief xcb_input_set_device_valuators_request_t
+ **/
+typedef struct xcb_input_set_device_valuators_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ uint8_t device_id;
+ uint8_t first_valuator;
+ uint8_t num_valuators;
+ uint8_t pad0;
+} xcb_input_set_device_valuators_request_t;
+
+/**
+ * @brief xcb_input_set_device_valuators_reply_t
+ **/
+typedef struct xcb_input_set_device_valuators_reply_t {
+ uint8_t response_type;
+ uint8_t xi_reply_type;
+ uint16_t sequence;
+ uint32_t length;
+ uint8_t status;
+ uint8_t pad0[23];
+} xcb_input_set_device_valuators_reply_t;
+
+typedef enum xcb_input_device_control_t {
+ XCB_INPUT_DEVICE_CONTROL_RESOLUTION = 1,
+ XCB_INPUT_DEVICE_CONTROL_ABS_CALIB = 2,
+ XCB_INPUT_DEVICE_CONTROL_CORE = 3,
+ XCB_INPUT_DEVICE_CONTROL_ENABLE = 4,
+ XCB_INPUT_DEVICE_CONTROL_ABS_AREA = 5
+} xcb_input_device_control_t;
+
+/**
+ * @brief xcb_input_device_resolution_state_t
+ **/
+typedef struct xcb_input_device_resolution_state_t {
+ uint16_t control_id;
+ uint16_t len;
+ uint32_t num_valuators;
+} xcb_input_device_resolution_state_t;
+
+/**
+ * @brief xcb_input_device_resolution_state_iterator_t
+ **/
+typedef struct xcb_input_device_resolution_state_iterator_t {
+ xcb_input_device_resolution_state_t *data;
+ int rem;
+ int index;
+} xcb_input_device_resolution_state_iterator_t;
+
+/**
+ * @brief xcb_input_device_abs_calib_state_t
+ **/
+typedef struct xcb_input_device_abs_calib_state_t {
+ uint16_t control_id;
+ uint16_t len;
+ int32_t min_x;
+ int32_t max_x;
+ int32_t min_y;
+ int32_t max_y;
+ uint32_t flip_x;
+ uint32_t flip_y;
+ uint32_t rotation;
+ uint32_t button_threshold;
+} xcb_input_device_abs_calib_state_t;
+
+/**
+ * @brief xcb_input_device_abs_calib_state_iterator_t
+ **/
+typedef struct xcb_input_device_abs_calib_state_iterator_t {
+ xcb_input_device_abs_calib_state_t *data;
+ int rem;
+ int index;
+} xcb_input_device_abs_calib_state_iterator_t;
+
+/**
+ * @brief xcb_input_device_abs_area_state_t
+ **/
+typedef struct xcb_input_device_abs_area_state_t {
+ uint16_t control_id;
+ uint16_t len;
+ uint32_t offset_x;
+ uint32_t offset_y;
+ uint32_t width;
+ uint32_t height;
+ uint32_t screen;
+ uint32_t following;
+} xcb_input_device_abs_area_state_t;
+
+/**
+ * @brief xcb_input_device_abs_area_state_iterator_t
+ **/
+typedef struct xcb_input_device_abs_area_state_iterator_t {
+ xcb_input_device_abs_area_state_t *data;
+ int rem;
+ int index;
+} xcb_input_device_abs_area_state_iterator_t;
+
+/**
+ * @brief xcb_input_device_core_state_t
+ **/
+typedef struct xcb_input_device_core_state_t {
+ uint16_t control_id;
+ uint16_t len;
+ uint8_t status;
+ uint8_t iscore;
+ uint8_t pad0[2];
+} xcb_input_device_core_state_t;
+
+/**
+ * @brief xcb_input_device_core_state_iterator_t
+ **/
+typedef struct xcb_input_device_core_state_iterator_t {
+ xcb_input_device_core_state_t *data;
+ int rem;
+ int index;
+} xcb_input_device_core_state_iterator_t;
+
+/**
+ * @brief xcb_input_device_enable_state_t
+ **/
+typedef struct xcb_input_device_enable_state_t {
+ uint16_t control_id;
+ uint16_t len;
+ uint8_t enable;
+ uint8_t pad0[3];
+} xcb_input_device_enable_state_t;
+
+/**
+ * @brief xcb_input_device_enable_state_iterator_t
+ **/
+typedef struct xcb_input_device_enable_state_iterator_t {
+ xcb_input_device_enable_state_t *data;
+ int rem;
+ int index;
+} xcb_input_device_enable_state_iterator_t;
+
+/**
+ * @brief xcb_input_device_state_data_t
+ **/
+typedef struct xcb_input_device_state_data_t {
+ struct {
+ uint32_t num_valuators;
+ uint32_t *resolution_values;
+ uint32_t *resolution_min;
+ uint32_t *resolution_max;
+ } resolution;
+ struct {
+ int32_t min_x;
+ int32_t max_x;
+ int32_t min_y;
+ int32_t max_y;
+ uint32_t flip_x;
+ uint32_t flip_y;
+ uint32_t rotation;
+ uint32_t button_threshold;
+ } abs_calib;
+ struct {
+ uint8_t status;
+ uint8_t iscore;
+ uint8_t pad0[2];
+ } core;
+ struct {
+ uint8_t enable;
+ uint8_t pad1[3];
+ } enable;
+ struct {
+ uint32_t offset_x;
+ uint32_t offset_y;
+ uint32_t width;
+ uint32_t height;
+ uint32_t screen;
+ uint32_t following;
+ } abs_area;
+} xcb_input_device_state_data_t;
+
+/**
+ * @brief xcb_input_device_state_t
+ **/
+typedef struct xcb_input_device_state_t {
+ uint16_t control_id;
+ uint16_t len;
+} xcb_input_device_state_t;
+
+void *
+xcb_input_device_state_data (const xcb_input_device_state_t *R);
+
+/**
+ * @brief xcb_input_device_state_iterator_t
+ **/
+typedef struct xcb_input_device_state_iterator_t {
+ xcb_input_device_state_t *data;
+ int rem;
+ int index;
+} xcb_input_device_state_iterator_t;
+
+/**
+ * @brief xcb_input_get_device_control_cookie_t
+ **/
+typedef struct xcb_input_get_device_control_cookie_t {
+ unsigned int sequence;
+} xcb_input_get_device_control_cookie_t;
+
+/** Opcode for xcb_input_get_device_control. */
+#define XCB_INPUT_GET_DEVICE_CONTROL 34
+
+/**
+ * @brief xcb_input_get_device_control_request_t
+ **/
+typedef struct xcb_input_get_device_control_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ uint16_t control_id;
+ uint8_t device_id;
+ uint8_t pad0;
+} xcb_input_get_device_control_request_t;
+
+/**
+ * @brief xcb_input_get_device_control_reply_t
+ **/
+typedef struct xcb_input_get_device_control_reply_t {
+ uint8_t response_type;
+ uint8_t xi_reply_type;
+ uint16_t sequence;
+ uint32_t length;
+ uint8_t status;
+ uint8_t pad0[23];
+} xcb_input_get_device_control_reply_t;
+
+/**
+ * @brief xcb_input_device_resolution_ctl_t
+ **/
+typedef struct xcb_input_device_resolution_ctl_t {
+ uint16_t control_id;
+ uint16_t len;
+ uint8_t first_valuator;
+ uint8_t num_valuators;
+ uint8_t pad0[2];
+} xcb_input_device_resolution_ctl_t;
+
+/**
+ * @brief xcb_input_device_resolution_ctl_iterator_t
+ **/
+typedef struct xcb_input_device_resolution_ctl_iterator_t {
+ xcb_input_device_resolution_ctl_t *data;
+ int rem;
+ int index;
+} xcb_input_device_resolution_ctl_iterator_t;
+
+/**
+ * @brief xcb_input_device_abs_calib_ctl_t
+ **/
+typedef struct xcb_input_device_abs_calib_ctl_t {
+ uint16_t control_id;
+ uint16_t len;
+ int32_t min_x;
+ int32_t max_x;
+ int32_t min_y;
+ int32_t max_y;
+ uint32_t flip_x;
+ uint32_t flip_y;
+ uint32_t rotation;
+ uint32_t button_threshold;
+} xcb_input_device_abs_calib_ctl_t;
+
+/**
+ * @brief xcb_input_device_abs_calib_ctl_iterator_t
+ **/
+typedef struct xcb_input_device_abs_calib_ctl_iterator_t {
+ xcb_input_device_abs_calib_ctl_t *data;
+ int rem;
+ int index;
+} xcb_input_device_abs_calib_ctl_iterator_t;
+
+/**
+ * @brief xcb_input_device_abs_area_ctrl_t
+ **/
+typedef struct xcb_input_device_abs_area_ctrl_t {
+ uint16_t control_id;
+ uint16_t len;
+ uint32_t offset_x;
+ uint32_t offset_y;
+ int32_t width;
+ int32_t height;
+ int32_t screen;
+ uint32_t following;
+} xcb_input_device_abs_area_ctrl_t;
+
+/**
+ * @brief xcb_input_device_abs_area_ctrl_iterator_t
+ **/
+typedef struct xcb_input_device_abs_area_ctrl_iterator_t {
+ xcb_input_device_abs_area_ctrl_t *data;
+ int rem;
+ int index;
+} xcb_input_device_abs_area_ctrl_iterator_t;
+
+/**
+ * @brief xcb_input_device_core_ctrl_t
+ **/
+typedef struct xcb_input_device_core_ctrl_t {
+ uint16_t control_id;
+ uint16_t len;
+ uint8_t status;
+ uint8_t pad0[3];
+} xcb_input_device_core_ctrl_t;
+
+/**
+ * @brief xcb_input_device_core_ctrl_iterator_t
+ **/
+typedef struct xcb_input_device_core_ctrl_iterator_t {
+ xcb_input_device_core_ctrl_t *data;
+ int rem;
+ int index;
+} xcb_input_device_core_ctrl_iterator_t;
+
+/**
+ * @brief xcb_input_device_enable_ctrl_t
+ **/
+typedef struct xcb_input_device_enable_ctrl_t {
+ uint16_t control_id;
+ uint16_t len;
+ uint8_t enable;
+ uint8_t pad0[3];
+} xcb_input_device_enable_ctrl_t;
+
+/**
+ * @brief xcb_input_device_enable_ctrl_iterator_t
+ **/
+typedef struct xcb_input_device_enable_ctrl_iterator_t {
+ xcb_input_device_enable_ctrl_t *data;
+ int rem;
+ int index;
+} xcb_input_device_enable_ctrl_iterator_t;
+
+/**
+ * @brief xcb_input_device_ctl_data_t
+ **/
+typedef struct xcb_input_device_ctl_data_t {
+ struct {
+ uint8_t first_valuator;
+ uint8_t num_valuators;
+ uint8_t pad0[2];
+ uint32_t *resolution_values;
+ } resolution;
+ struct {
+ int32_t min_x;
+ int32_t max_x;
+ int32_t min_y;
+ int32_t max_y;
+ uint32_t flip_x;
+ uint32_t flip_y;
+ uint32_t rotation;
+ uint32_t button_threshold;
+ } abs_calib;
+ struct {
+ uint8_t status;
+ uint8_t pad1[3];
+ } core;
+ struct {
+ uint8_t enable;
+ uint8_t pad2[3];
+ } enable;
+ struct {
+ uint32_t offset_x;
+ uint32_t offset_y;
+ int32_t width;
+ int32_t height;
+ int32_t screen;
+ uint32_t following;
+ } abs_area;
+} xcb_input_device_ctl_data_t;
+
+/**
+ * @brief xcb_input_device_ctl_t
+ **/
+typedef struct xcb_input_device_ctl_t {
+ uint16_t control_id;
+ uint16_t len;
+} xcb_input_device_ctl_t;
+
+void *
+xcb_input_device_ctl_data (const xcb_input_device_ctl_t *R);
+
+/**
+ * @brief xcb_input_device_ctl_iterator_t
+ **/
+typedef struct xcb_input_device_ctl_iterator_t {
+ xcb_input_device_ctl_t *data;
+ int rem;
+ int index;
+} xcb_input_device_ctl_iterator_t;
+
+/**
+ * @brief xcb_input_change_device_control_cookie_t
+ **/
+typedef struct xcb_input_change_device_control_cookie_t {
+ unsigned int sequence;
+} xcb_input_change_device_control_cookie_t;
+
+/** Opcode for xcb_input_change_device_control. */
+#define XCB_INPUT_CHANGE_DEVICE_CONTROL 35
+
+/**
+ * @brief xcb_input_change_device_control_request_t
+ **/
+typedef struct xcb_input_change_device_control_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ uint16_t control_id;
+ uint8_t device_id;
+ uint8_t pad0;
+} xcb_input_change_device_control_request_t;
+
+/**
+ * @brief xcb_input_change_device_control_reply_t
+ **/
+typedef struct xcb_input_change_device_control_reply_t {
+ uint8_t response_type;
+ uint8_t xi_reply_type;
+ uint16_t sequence;
+ uint32_t length;
+ uint8_t status;
+ uint8_t pad0[23];
+} xcb_input_change_device_control_reply_t;
+
+/**
+ * @brief xcb_input_list_device_properties_cookie_t
+ **/
+typedef struct xcb_input_list_device_properties_cookie_t {
+ unsigned int sequence;
+} xcb_input_list_device_properties_cookie_t;
+
+/** Opcode for xcb_input_list_device_properties. */
+#define XCB_INPUT_LIST_DEVICE_PROPERTIES 36
+
+/**
+ * @brief xcb_input_list_device_properties_request_t
+ **/
+typedef struct xcb_input_list_device_properties_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ uint8_t device_id;
+ uint8_t pad0[3];
+} xcb_input_list_device_properties_request_t;
+
+/**
+ * @brief xcb_input_list_device_properties_reply_t
+ **/
+typedef struct xcb_input_list_device_properties_reply_t {
+ uint8_t response_type;
+ uint8_t xi_reply_type;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t num_atoms;
+ uint8_t pad0[22];
+} xcb_input_list_device_properties_reply_t;
+
+typedef enum xcb_input_property_format_t {
+ XCB_INPUT_PROPERTY_FORMAT_8_BITS = 8,
+ XCB_INPUT_PROPERTY_FORMAT_16_BITS = 16,
+ XCB_INPUT_PROPERTY_FORMAT_32_BITS = 32
+} xcb_input_property_format_t;
+
+/**
+ * @brief xcb_input_change_device_property_items_t
+ **/
+typedef struct xcb_input_change_device_property_items_t {
+ uint8_t *data8;
+ uint16_t *data16;
+ uint32_t *data32;
+} xcb_input_change_device_property_items_t;
+
+/** Opcode for xcb_input_change_device_property. */
+#define XCB_INPUT_CHANGE_DEVICE_PROPERTY 37
+
+/**
+ * @brief xcb_input_change_device_property_request_t
+ **/
+typedef struct xcb_input_change_device_property_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_atom_t property;
+ xcb_atom_t type;
+ uint8_t device_id;
+ uint8_t format;
+ uint8_t mode;
+ uint8_t pad0;
+ uint32_t num_items;
+} xcb_input_change_device_property_request_t;
+
+/** Opcode for xcb_input_delete_device_property. */
+#define XCB_INPUT_DELETE_DEVICE_PROPERTY 38
+
+/**
+ * @brief xcb_input_delete_device_property_request_t
+ **/
+typedef struct xcb_input_delete_device_property_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_atom_t property;
+ uint8_t device_id;
+ uint8_t pad0[3];
+} xcb_input_delete_device_property_request_t;
+
+/**
+ * @brief xcb_input_get_device_property_cookie_t
+ **/
+typedef struct xcb_input_get_device_property_cookie_t {
+ unsigned int sequence;
+} xcb_input_get_device_property_cookie_t;
+
+/** Opcode for xcb_input_get_device_property. */
+#define XCB_INPUT_GET_DEVICE_PROPERTY 39
+
+/**
+ * @brief xcb_input_get_device_property_request_t
+ **/
+typedef struct xcb_input_get_device_property_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_atom_t property;
+ xcb_atom_t type;
+ uint32_t offset;
+ uint32_t len;
+ uint8_t device_id;
+ uint8_t _delete;
+ uint8_t pad0[2];
+} xcb_input_get_device_property_request_t;
+
+/**
+ * @brief xcb_input_get_device_property_items_t
+ **/
+typedef struct xcb_input_get_device_property_items_t {
+ uint8_t *data8;
+ uint16_t *data16;
+ uint32_t *data32;
+} xcb_input_get_device_property_items_t;
+
+/**
+ * @brief xcb_input_get_device_property_reply_t
+ **/
+typedef struct xcb_input_get_device_property_reply_t {
+ uint8_t response_type;
+ uint8_t xi_reply_type;
+ uint16_t sequence;
+ uint32_t length;
+ xcb_atom_t type;
+ uint32_t bytes_after;
+ uint32_t num_items;
+ uint8_t format;
+ uint8_t device_id;
+ uint8_t pad0[10];
+} xcb_input_get_device_property_reply_t;
+
+typedef enum xcb_input_device_t {
+ XCB_INPUT_DEVICE_ALL = 0,
+ XCB_INPUT_DEVICE_ALL_MASTER = 1
+} xcb_input_device_t;
+
+/**
+ * @brief xcb_input_group_info_t
+ **/
+typedef struct xcb_input_group_info_t {
+ uint8_t base;
+ uint8_t latched;
+ uint8_t locked;
+ uint8_t effective;
+} xcb_input_group_info_t;
+
+/**
+ * @brief xcb_input_group_info_iterator_t
+ **/
+typedef struct xcb_input_group_info_iterator_t {
+ xcb_input_group_info_t *data;
+ int rem;
+ int index;
+} xcb_input_group_info_iterator_t;
+
+/**
+ * @brief xcb_input_modifier_info_t
+ **/
+typedef struct xcb_input_modifier_info_t {
+ uint32_t base;
+ uint32_t latched;
+ uint32_t locked;
+ uint32_t effective;
+} xcb_input_modifier_info_t;
+
+/**
+ * @brief xcb_input_modifier_info_iterator_t
+ **/
+typedef struct xcb_input_modifier_info_iterator_t {
+ xcb_input_modifier_info_t *data;
+ int rem;
+ int index;
+} xcb_input_modifier_info_iterator_t;
+
+/**
+ * @brief xcb_input_xi_query_pointer_cookie_t
+ **/
+typedef struct xcb_input_xi_query_pointer_cookie_t {
+ unsigned int sequence;
+} xcb_input_xi_query_pointer_cookie_t;
+
+/** Opcode for xcb_input_xi_query_pointer. */
+#define XCB_INPUT_XI_QUERY_POINTER 40
+
+/**
+ * @brief xcb_input_xi_query_pointer_request_t
+ **/
+typedef struct xcb_input_xi_query_pointer_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_window_t window;
+ xcb_input_device_id_t deviceid;
+ uint8_t pad0[2];
+} xcb_input_xi_query_pointer_request_t;
+
+/**
+ * @brief xcb_input_xi_query_pointer_reply_t
+ **/
+typedef struct xcb_input_xi_query_pointer_reply_t {
+ uint8_t response_type;
+ uint8_t pad0;
+ uint16_t sequence;
+ uint32_t length;
+ xcb_window_t root;
+ xcb_window_t child;
+ xcb_input_fp1616_t root_x;
+ xcb_input_fp1616_t root_y;
+ xcb_input_fp1616_t win_x;
+ xcb_input_fp1616_t win_y;
+ uint8_t same_screen;
+ uint8_t pad1;
+ uint16_t buttons_len;
+ xcb_input_modifier_info_t mods;
+ xcb_input_group_info_t group;
+} xcb_input_xi_query_pointer_reply_t;
+
+/** Opcode for xcb_input_xi_warp_pointer. */
+#define XCB_INPUT_XI_WARP_POINTER 41
+
+/**
+ * @brief xcb_input_xi_warp_pointer_request_t
+ **/
+typedef struct xcb_input_xi_warp_pointer_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_window_t src_win;
+ xcb_window_t dst_win;
+ xcb_input_fp1616_t src_x;
+ xcb_input_fp1616_t src_y;
+ uint16_t src_width;
+ uint16_t src_height;
+ xcb_input_fp1616_t dst_x;
+ xcb_input_fp1616_t dst_y;
+ xcb_input_device_id_t deviceid;
+ uint8_t pad0[2];
+} xcb_input_xi_warp_pointer_request_t;
+
+/** Opcode for xcb_input_xi_change_cursor. */
+#define XCB_INPUT_XI_CHANGE_CURSOR 42
+
+/**
+ * @brief xcb_input_xi_change_cursor_request_t
+ **/
+typedef struct xcb_input_xi_change_cursor_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_window_t window;
+ xcb_cursor_t cursor;
+ xcb_input_device_id_t deviceid;
+ uint8_t pad0[2];
+} xcb_input_xi_change_cursor_request_t;
+
+typedef enum xcb_input_hierarchy_change_type_t {
+ XCB_INPUT_HIERARCHY_CHANGE_TYPE_ADD_MASTER = 1,
+ XCB_INPUT_HIERARCHY_CHANGE_TYPE_REMOVE_MASTER = 2,
+ XCB_INPUT_HIERARCHY_CHANGE_TYPE_ATTACH_SLAVE = 3,
+ XCB_INPUT_HIERARCHY_CHANGE_TYPE_DETACH_SLAVE = 4
+} xcb_input_hierarchy_change_type_t;
+
+typedef enum xcb_input_change_mode_t {
+ XCB_INPUT_CHANGE_MODE_ATTACH = 1,
+ XCB_INPUT_CHANGE_MODE_FLOAT = 2
+} xcb_input_change_mode_t;
+
+/**
+ * @brief xcb_input_add_master_t
+ **/
+typedef struct xcb_input_add_master_t {
+ uint16_t type;
+ uint16_t len;
+ uint16_t name_len;
+ uint8_t send_core;
+ uint8_t enable;
+} xcb_input_add_master_t;
+
+/**
+ * @brief xcb_input_add_master_iterator_t
+ **/
+typedef struct xcb_input_add_master_iterator_t {
+ xcb_input_add_master_t *data;
+ int rem;
+ int index;
+} xcb_input_add_master_iterator_t;
+
+/**
+ * @brief xcb_input_remove_master_t
+ **/
+typedef struct xcb_input_remove_master_t {
+ uint16_t type;
+ uint16_t len;
+ xcb_input_device_id_t deviceid;
+ uint8_t return_mode;
+ uint8_t pad0;
+ xcb_input_device_id_t return_pointer;
+ xcb_input_device_id_t return_keyboard;
+} xcb_input_remove_master_t;
+
+/**
+ * @brief xcb_input_remove_master_iterator_t
+ **/
+typedef struct xcb_input_remove_master_iterator_t {
+ xcb_input_remove_master_t *data;
+ int rem;
+ int index;
+} xcb_input_remove_master_iterator_t;
+
+/**
+ * @brief xcb_input_attach_slave_t
+ **/
+typedef struct xcb_input_attach_slave_t {
+ uint16_t type;
+ uint16_t len;
+ xcb_input_device_id_t deviceid;
+ xcb_input_device_id_t master;
+} xcb_input_attach_slave_t;
+
+/**
+ * @brief xcb_input_attach_slave_iterator_t
+ **/
+typedef struct xcb_input_attach_slave_iterator_t {
+ xcb_input_attach_slave_t *data;
+ int rem;
+ int index;
+} xcb_input_attach_slave_iterator_t;
+
+/**
+ * @brief xcb_input_detach_slave_t
+ **/
+typedef struct xcb_input_detach_slave_t {
+ uint16_t type;
+ uint16_t len;
+ xcb_input_device_id_t deviceid;
+ uint8_t pad0[2];
+} xcb_input_detach_slave_t;
+
+/**
+ * @brief xcb_input_detach_slave_iterator_t
+ **/
+typedef struct xcb_input_detach_slave_iterator_t {
+ xcb_input_detach_slave_t *data;
+ int rem;
+ int index;
+} xcb_input_detach_slave_iterator_t;
+
+/**
+ * @brief xcb_input_hierarchy_change_data_t
+ **/
+typedef struct xcb_input_hierarchy_change_data_t {
+ struct {
+ uint16_t name_len;
+ uint8_t send_core;
+ uint8_t enable;
+ char *name;
+ } add_master;
+ struct {
+ xcb_input_device_id_t deviceid;
+ uint8_t return_mode;
+ uint8_t pad1;
+ xcb_input_device_id_t return_pointer;
+ xcb_input_device_id_t return_keyboard;
+ } remove_master;
+ struct {
+ xcb_input_device_id_t deviceid;
+ xcb_input_device_id_t master;
+ } attach_slave;
+ struct {
+ xcb_input_device_id_t deviceid;
+ uint8_t pad2[2];
+ } detach_slave;
+} xcb_input_hierarchy_change_data_t;
+
+/**
+ * @brief xcb_input_hierarchy_change_t
+ **/
+typedef struct xcb_input_hierarchy_change_t {
+ uint16_t type;
+ uint16_t len;
+} xcb_input_hierarchy_change_t;
+
+void *
+xcb_input_hierarchy_change_data (const xcb_input_hierarchy_change_t *R);
+
+/**
+ * @brief xcb_input_hierarchy_change_iterator_t
+ **/
+typedef struct xcb_input_hierarchy_change_iterator_t {
+ xcb_input_hierarchy_change_t *data;
+ int rem;
+ int index;
+} xcb_input_hierarchy_change_iterator_t;
+
+/** Opcode for xcb_input_xi_change_hierarchy. */
+#define XCB_INPUT_XI_CHANGE_HIERARCHY 43
+
+/**
+ * @brief xcb_input_xi_change_hierarchy_request_t
+ **/
+typedef struct xcb_input_xi_change_hierarchy_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ uint8_t num_changes;
+ uint8_t pad0[3];
+} xcb_input_xi_change_hierarchy_request_t;
+
+/** Opcode for xcb_input_xi_set_client_pointer. */
+#define XCB_INPUT_XI_SET_CLIENT_POINTER 44
+
+/**
+ * @brief xcb_input_xi_set_client_pointer_request_t
+ **/
+typedef struct xcb_input_xi_set_client_pointer_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_window_t window;
+ xcb_input_device_id_t deviceid;
+ uint8_t pad0[2];
+} xcb_input_xi_set_client_pointer_request_t;
+
+/**
+ * @brief xcb_input_xi_get_client_pointer_cookie_t
+ **/
+typedef struct xcb_input_xi_get_client_pointer_cookie_t {
+ unsigned int sequence;
+} xcb_input_xi_get_client_pointer_cookie_t;
+
+/** Opcode for xcb_input_xi_get_client_pointer. */
+#define XCB_INPUT_XI_GET_CLIENT_POINTER 45
+
+/**
+ * @brief xcb_input_xi_get_client_pointer_request_t
+ **/
+typedef struct xcb_input_xi_get_client_pointer_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_window_t window;
+} xcb_input_xi_get_client_pointer_request_t;
+
+/**
+ * @brief xcb_input_xi_get_client_pointer_reply_t
+ **/
+typedef struct xcb_input_xi_get_client_pointer_reply_t {
+ uint8_t response_type;
+ uint8_t pad0;
+ uint16_t sequence;
+ uint32_t length;
+ uint8_t set;
+ uint8_t pad1;
+ xcb_input_device_id_t deviceid;
+ uint8_t pad2[20];
+} xcb_input_xi_get_client_pointer_reply_t;
+
+typedef enum xcb_input_xi_event_mask_t {
+ XCB_INPUT_XI_EVENT_MASK_DEVICE_CHANGED = 2,
+ XCB_INPUT_XI_EVENT_MASK_KEY_PRESS = 4,
+ XCB_INPUT_XI_EVENT_MASK_KEY_RELEASE = 8,
+ XCB_INPUT_XI_EVENT_MASK_BUTTON_PRESS = 16,
+ XCB_INPUT_XI_EVENT_MASK_BUTTON_RELEASE = 32,
+ XCB_INPUT_XI_EVENT_MASK_MOTION = 64,
+ XCB_INPUT_XI_EVENT_MASK_ENTER = 128,
+ XCB_INPUT_XI_EVENT_MASK_LEAVE = 256,
+ XCB_INPUT_XI_EVENT_MASK_FOCUS_IN = 512,
+ XCB_INPUT_XI_EVENT_MASK_FOCUS_OUT = 1024,
+ XCB_INPUT_XI_EVENT_MASK_HIERARCHY = 2048,
+ XCB_INPUT_XI_EVENT_MASK_PROPERTY = 4096,
+ XCB_INPUT_XI_EVENT_MASK_RAW_KEY_PRESS = 8192,
+ XCB_INPUT_XI_EVENT_MASK_RAW_KEY_RELEASE = 16384,
+ XCB_INPUT_XI_EVENT_MASK_RAW_BUTTON_PRESS = 32768,
+ XCB_INPUT_XI_EVENT_MASK_RAW_BUTTON_RELEASE = 65536,
+ XCB_INPUT_XI_EVENT_MASK_RAW_MOTION = 131072,
+ XCB_INPUT_XI_EVENT_MASK_TOUCH_BEGIN = 262144,
+ XCB_INPUT_XI_EVENT_MASK_TOUCH_UPDATE = 524288,
+ XCB_INPUT_XI_EVENT_MASK_TOUCH_END = 1048576,
+ XCB_INPUT_XI_EVENT_MASK_TOUCH_OWNERSHIP = 2097152,
+ XCB_INPUT_XI_EVENT_MASK_RAW_TOUCH_BEGIN = 4194304,
+ XCB_INPUT_XI_EVENT_MASK_RAW_TOUCH_UPDATE = 8388608,
+ XCB_INPUT_XI_EVENT_MASK_RAW_TOUCH_END = 16777216,
+ XCB_INPUT_XI_EVENT_MASK_BARRIER_HIT = 33554432,
+ XCB_INPUT_XI_EVENT_MASK_BARRIER_LEAVE = 67108864
+} xcb_input_xi_event_mask_t;
+
+/**
+ * @brief xcb_input_event_mask_t
+ **/
+typedef struct xcb_input_event_mask_t {
+ xcb_input_device_id_t deviceid;
+ uint16_t mask_len;
+} xcb_input_event_mask_t;
+
+/**
+ * @brief xcb_input_event_mask_iterator_t
+ **/
+typedef struct xcb_input_event_mask_iterator_t {
+ xcb_input_event_mask_t *data;
+ int rem;
+ int index;
+} xcb_input_event_mask_iterator_t;
+
+/** Opcode for xcb_input_xi_select_events. */
+#define XCB_INPUT_XI_SELECT_EVENTS 46
+
+/**
+ * @brief xcb_input_xi_select_events_request_t
+ **/
+typedef struct xcb_input_xi_select_events_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_window_t window;
+ uint16_t num_mask;
+ uint8_t pad0[2];
+} xcb_input_xi_select_events_request_t;
+
+/**
+ * @brief xcb_input_xi_query_version_cookie_t
+ **/
+typedef struct xcb_input_xi_query_version_cookie_t {
+ unsigned int sequence;
+} xcb_input_xi_query_version_cookie_t;
+
+/** Opcode for xcb_input_xi_query_version. */
+#define XCB_INPUT_XI_QUERY_VERSION 47
+
+/**
+ * @brief xcb_input_xi_query_version_request_t
+ **/
+typedef struct xcb_input_xi_query_version_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ uint16_t major_version;
+ uint16_t minor_version;
+} xcb_input_xi_query_version_request_t;
+
+/**
+ * @brief xcb_input_xi_query_version_reply_t
+ **/
+typedef struct xcb_input_xi_query_version_reply_t {
+ uint8_t response_type;
+ uint8_t pad0;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t major_version;
+ uint16_t minor_version;
+ uint8_t pad1[20];
+} xcb_input_xi_query_version_reply_t;
+
+typedef enum xcb_input_device_class_type_t {
+ XCB_INPUT_DEVICE_CLASS_TYPE_KEY = 0,
+ XCB_INPUT_DEVICE_CLASS_TYPE_BUTTON = 1,
+ XCB_INPUT_DEVICE_CLASS_TYPE_VALUATOR = 2,
+ XCB_INPUT_DEVICE_CLASS_TYPE_SCROLL = 3,
+ XCB_INPUT_DEVICE_CLASS_TYPE_TOUCH = 8
+} xcb_input_device_class_type_t;
+
+typedef enum xcb_input_device_type_t {
+ XCB_INPUT_DEVICE_TYPE_MASTER_POINTER = 1,
+ XCB_INPUT_DEVICE_TYPE_MASTER_KEYBOARD = 2,
+ XCB_INPUT_DEVICE_TYPE_SLAVE_POINTER = 3,
+ XCB_INPUT_DEVICE_TYPE_SLAVE_KEYBOARD = 4,
+ XCB_INPUT_DEVICE_TYPE_FLOATING_SLAVE = 5
+} xcb_input_device_type_t;
+
+typedef enum xcb_input_scroll_flags_t {
+ XCB_INPUT_SCROLL_FLAGS_NO_EMULATION = 1,
+ XCB_INPUT_SCROLL_FLAGS_PREFERRED = 2
+} xcb_input_scroll_flags_t;
+
+typedef enum xcb_input_scroll_type_t {
+ XCB_INPUT_SCROLL_TYPE_VERTICAL = 1,
+ XCB_INPUT_SCROLL_TYPE_HORIZONTAL = 2
+} xcb_input_scroll_type_t;
+
+typedef enum xcb_input_touch_mode_t {
+ XCB_INPUT_TOUCH_MODE_DIRECT = 1,
+ XCB_INPUT_TOUCH_MODE_DEPENDENT = 2
+} xcb_input_touch_mode_t;
+
+/**
+ * @brief xcb_input_button_class_t
+ **/
+typedef struct xcb_input_button_class_t {
+ uint16_t type;
+ uint16_t len;
+ xcb_input_device_id_t sourceid;
+ uint16_t num_buttons;
+} xcb_input_button_class_t;
+
+/**
+ * @brief xcb_input_button_class_iterator_t
+ **/
+typedef struct xcb_input_button_class_iterator_t {
+ xcb_input_button_class_t *data;
+ int rem;
+ int index;
+} xcb_input_button_class_iterator_t;
+
+/**
+ * @brief xcb_input_key_class_t
+ **/
+typedef struct xcb_input_key_class_t {
+ uint16_t type;
+ uint16_t len;
+ xcb_input_device_id_t sourceid;
+ uint16_t num_keys;
+} xcb_input_key_class_t;
+
+/**
+ * @brief xcb_input_key_class_iterator_t
+ **/
+typedef struct xcb_input_key_class_iterator_t {
+ xcb_input_key_class_t *data;
+ int rem;
+ int index;
+} xcb_input_key_class_iterator_t;
+
+/**
+ * @brief xcb_input_scroll_class_t
+ **/
+typedef struct xcb_input_scroll_class_t {
+ uint16_t type;
+ uint16_t len;
+ xcb_input_device_id_t sourceid;
+ uint16_t number;
+ uint16_t scroll_type;
+ uint8_t pad0[2];
+ uint32_t flags;
+ xcb_input_fp3232_t increment;
+} xcb_input_scroll_class_t;
+
+/**
+ * @brief xcb_input_scroll_class_iterator_t
+ **/
+typedef struct xcb_input_scroll_class_iterator_t {
+ xcb_input_scroll_class_t *data;
+ int rem;
+ int index;
+} xcb_input_scroll_class_iterator_t;
+
+/**
+ * @brief xcb_input_touch_class_t
+ **/
+typedef struct xcb_input_touch_class_t {
+ uint16_t type;
+ uint16_t len;
+ xcb_input_device_id_t sourceid;
+ uint8_t mode;
+ uint8_t num_touches;
+} xcb_input_touch_class_t;
+
+/**
+ * @brief xcb_input_touch_class_iterator_t
+ **/
+typedef struct xcb_input_touch_class_iterator_t {
+ xcb_input_touch_class_t *data;
+ int rem;
+ int index;
+} xcb_input_touch_class_iterator_t;
+
+/**
+ * @brief xcb_input_valuator_class_t
+ **/
+typedef struct xcb_input_valuator_class_t {
+ uint16_t type;
+ uint16_t len;
+ xcb_input_device_id_t sourceid;
+ uint16_t number;
+ xcb_atom_t label;
+ xcb_input_fp3232_t min;
+ xcb_input_fp3232_t max;
+ xcb_input_fp3232_t value;
+ uint32_t resolution;
+ uint8_t mode;
+ uint8_t pad0[3];
+} xcb_input_valuator_class_t;
+
+/**
+ * @brief xcb_input_valuator_class_iterator_t
+ **/
+typedef struct xcb_input_valuator_class_iterator_t {
+ xcb_input_valuator_class_t *data;
+ int rem;
+ int index;
+} xcb_input_valuator_class_iterator_t;
+
+/**
+ * @brief xcb_input_device_class_data_t
+ **/
+typedef struct xcb_input_device_class_data_t {
+ struct {
+ uint16_t num_keys;
+ uint32_t *keys;
+ } key;
+ struct {
+ uint16_t num_buttons;
+ uint32_t *state;
+ xcb_atom_t *labels;
+ } button;
+ struct {
+ uint16_t number;
+ xcb_atom_t label;
+ xcb_input_fp3232_t min;
+ xcb_input_fp3232_t max;
+ xcb_input_fp3232_t value;
+ uint32_t resolution;
+ uint8_t mode;
+ uint8_t pad0[3];
+ } valuator;
+ struct {
+ uint16_t number;
+ uint16_t scroll_type;
+ uint8_t pad1[2];
+ uint32_t flags;
+ xcb_input_fp3232_t increment;
+ } scroll;
+ struct {
+ uint8_t mode;
+ uint8_t num_touches;
+ } touch;
+} xcb_input_device_class_data_t;
+
+/**
+ * @brief xcb_input_device_class_t
+ **/
+typedef struct xcb_input_device_class_t {
+ uint16_t type;
+ uint16_t len;
+ xcb_input_device_id_t sourceid;
+} xcb_input_device_class_t;
+
+void *
+xcb_input_device_class_data (const xcb_input_device_class_t *R);
+
+/**
+ * @brief xcb_input_device_class_iterator_t
+ **/
+typedef struct xcb_input_device_class_iterator_t {
+ xcb_input_device_class_t *data;
+ int rem;
+ int index;
+} xcb_input_device_class_iterator_t;
+
+/**
+ * @brief xcb_input_xi_device_info_t
+ **/
+typedef struct xcb_input_xi_device_info_t {
+ xcb_input_device_id_t deviceid;
+ uint16_t type;
+ xcb_input_device_id_t attachment;
+ uint16_t num_classes;
+ uint16_t name_len;
+ uint8_t enabled;
+ uint8_t pad0;
+} xcb_input_xi_device_info_t;
+
+/**
+ * @brief xcb_input_xi_device_info_iterator_t
+ **/
+typedef struct xcb_input_xi_device_info_iterator_t {
+ xcb_input_xi_device_info_t *data;
+ int rem;
+ int index;
+} xcb_input_xi_device_info_iterator_t;
+
+/**
+ * @brief xcb_input_xi_query_device_cookie_t
+ **/
+typedef struct xcb_input_xi_query_device_cookie_t {
+ unsigned int sequence;
+} xcb_input_xi_query_device_cookie_t;
+
+/** Opcode for xcb_input_xi_query_device. */
+#define XCB_INPUT_XI_QUERY_DEVICE 48
+
+/**
+ * @brief xcb_input_xi_query_device_request_t
+ **/
+typedef struct xcb_input_xi_query_device_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_input_device_id_t deviceid;
+ uint8_t pad0[2];
+} xcb_input_xi_query_device_request_t;
+
+/**
+ * @brief xcb_input_xi_query_device_reply_t
+ **/
+typedef struct xcb_input_xi_query_device_reply_t {
+ uint8_t response_type;
+ uint8_t pad0;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t num_infos;
+ uint8_t pad1[22];
+} xcb_input_xi_query_device_reply_t;
+
+/** Opcode for xcb_input_xi_set_focus. */
+#define XCB_INPUT_XI_SET_FOCUS 49
+
+/**
+ * @brief xcb_input_xi_set_focus_request_t
+ **/
+typedef struct xcb_input_xi_set_focus_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_window_t window;
+ xcb_timestamp_t time;
+ xcb_input_device_id_t deviceid;
+ uint8_t pad0[2];
+} xcb_input_xi_set_focus_request_t;
+
+/**
+ * @brief xcb_input_xi_get_focus_cookie_t
+ **/
+typedef struct xcb_input_xi_get_focus_cookie_t {
+ unsigned int sequence;
+} xcb_input_xi_get_focus_cookie_t;
+
+/** Opcode for xcb_input_xi_get_focus. */
+#define XCB_INPUT_XI_GET_FOCUS 50
+
+/**
+ * @brief xcb_input_xi_get_focus_request_t
+ **/
+typedef struct xcb_input_xi_get_focus_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_input_device_id_t deviceid;
+ uint8_t pad0[2];
+} xcb_input_xi_get_focus_request_t;
+
+/**
+ * @brief xcb_input_xi_get_focus_reply_t
+ **/
+typedef struct xcb_input_xi_get_focus_reply_t {
+ uint8_t response_type;
+ uint8_t pad0;
+ uint16_t sequence;
+ uint32_t length;
+ xcb_window_t focus;
+ uint8_t pad1[20];
+} xcb_input_xi_get_focus_reply_t;
+
+typedef enum xcb_input_grab_owner_t {
+ XCB_INPUT_GRAB_OWNER_NO_OWNER = 0,
+ XCB_INPUT_GRAB_OWNER_OWNER = 1
+} xcb_input_grab_owner_t;
+
+/**
+ * @brief xcb_input_xi_grab_device_cookie_t
+ **/
+typedef struct xcb_input_xi_grab_device_cookie_t {
+ unsigned int sequence;
+} xcb_input_xi_grab_device_cookie_t;
+
+/** Opcode for xcb_input_xi_grab_device. */
+#define XCB_INPUT_XI_GRAB_DEVICE 51
+
+/**
+ * @brief xcb_input_xi_grab_device_request_t
+ **/
+typedef struct xcb_input_xi_grab_device_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_window_t window;
+ xcb_timestamp_t time;
+ xcb_cursor_t cursor;
+ xcb_input_device_id_t deviceid;
+ uint8_t mode;
+ uint8_t paired_device_mode;
+ uint8_t owner_events;
+ uint8_t pad0;
+ uint16_t mask_len;
+} xcb_input_xi_grab_device_request_t;
+
+/**
+ * @brief xcb_input_xi_grab_device_reply_t
+ **/
+typedef struct xcb_input_xi_grab_device_reply_t {
+ uint8_t response_type;
+ uint8_t pad0;
+ uint16_t sequence;
+ uint32_t length;
+ uint8_t status;
+ uint8_t pad1[23];
+} xcb_input_xi_grab_device_reply_t;
+
+/** Opcode for xcb_input_xi_ungrab_device. */
+#define XCB_INPUT_XI_UNGRAB_DEVICE 52
+
+/**
+ * @brief xcb_input_xi_ungrab_device_request_t
+ **/
+typedef struct xcb_input_xi_ungrab_device_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_timestamp_t time;
+ xcb_input_device_id_t deviceid;
+ uint8_t pad0[2];
+} xcb_input_xi_ungrab_device_request_t;
+
+typedef enum xcb_input_event_mode_t {
+ XCB_INPUT_EVENT_MODE_ASYNC_DEVICE = 0,
+ XCB_INPUT_EVENT_MODE_SYNC_DEVICE = 1,
+ XCB_INPUT_EVENT_MODE_REPLAY_DEVICE = 2,
+ XCB_INPUT_EVENT_MODE_ASYNC_PAIRED_DEVICE = 3,
+ XCB_INPUT_EVENT_MODE_ASYNC_PAIR = 4,
+ XCB_INPUT_EVENT_MODE_SYNC_PAIR = 5,
+ XCB_INPUT_EVENT_MODE_ACCEPT_TOUCH = 6,
+ XCB_INPUT_EVENT_MODE_REJECT_TOUCH = 7
+} xcb_input_event_mode_t;
+
+/** Opcode for xcb_input_xi_allow_events. */
+#define XCB_INPUT_XI_ALLOW_EVENTS 53
+
+/**
+ * @brief xcb_input_xi_allow_events_request_t
+ **/
+typedef struct xcb_input_xi_allow_events_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_timestamp_t time;
+ xcb_input_device_id_t deviceid;
+ uint8_t event_mode;
+ uint8_t pad0;
+ uint32_t touchid;
+ xcb_window_t grab_window;
+} xcb_input_xi_allow_events_request_t;
+
+typedef enum xcb_input_grab_mode_22_t {
+ XCB_INPUT_GRAB_MODE_22_SYNC = 0,
+ XCB_INPUT_GRAB_MODE_22_ASYNC = 1,
+ XCB_INPUT_GRAB_MODE_22_TOUCH = 2
+} xcb_input_grab_mode_22_t;
+
+typedef enum xcb_input_grab_type_t {
+ XCB_INPUT_GRAB_TYPE_BUTTON = 0,
+ XCB_INPUT_GRAB_TYPE_KEYCODE = 1,
+ XCB_INPUT_GRAB_TYPE_ENTER = 2,
+ XCB_INPUT_GRAB_TYPE_FOCUS_IN = 3,
+ XCB_INPUT_GRAB_TYPE_TOUCH_BEGIN = 4
+} xcb_input_grab_type_t;
+
+typedef enum xcb_input_modifier_mask_t {
+ XCB_INPUT_MODIFIER_MASK_ANY = 2147483648
+} xcb_input_modifier_mask_t;
+
+/**
+ * @brief xcb_input_grab_modifier_info_t
+ **/
+typedef struct xcb_input_grab_modifier_info_t {
+ uint32_t modifiers;
+ uint8_t status;
+ uint8_t pad0[3];
+} xcb_input_grab_modifier_info_t;
+
+/**
+ * @brief xcb_input_grab_modifier_info_iterator_t
+ **/
+typedef struct xcb_input_grab_modifier_info_iterator_t {
+ xcb_input_grab_modifier_info_t *data;
+ int rem;
+ int index;
+} xcb_input_grab_modifier_info_iterator_t;
+
+/**
+ * @brief xcb_input_xi_passive_grab_device_cookie_t
+ **/
+typedef struct xcb_input_xi_passive_grab_device_cookie_t {
+ unsigned int sequence;
+} xcb_input_xi_passive_grab_device_cookie_t;
+
+/** Opcode for xcb_input_xi_passive_grab_device. */
+#define XCB_INPUT_XI_PASSIVE_GRAB_DEVICE 54
+
+/**
+ * @brief xcb_input_xi_passive_grab_device_request_t
+ **/
+typedef struct xcb_input_xi_passive_grab_device_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_timestamp_t time;
+ xcb_window_t grab_window;
+ xcb_cursor_t cursor;
+ uint32_t detail;
+ xcb_input_device_id_t deviceid;
+ uint16_t num_modifiers;
+ uint16_t mask_len;
+ uint8_t grab_type;
+ uint8_t grab_mode;
+ uint8_t paired_device_mode;
+ uint8_t owner_events;
+ uint8_t pad0[2];
+} xcb_input_xi_passive_grab_device_request_t;
+
+/**
+ * @brief xcb_input_xi_passive_grab_device_reply_t
+ **/
+typedef struct xcb_input_xi_passive_grab_device_reply_t {
+ uint8_t response_type;
+ uint8_t pad0;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t num_modifiers;
+ uint8_t pad1[22];
+} xcb_input_xi_passive_grab_device_reply_t;
+
+/** Opcode for xcb_input_xi_passive_ungrab_device. */
+#define XCB_INPUT_XI_PASSIVE_UNGRAB_DEVICE 55
+
+/**
+ * @brief xcb_input_xi_passive_ungrab_device_request_t
+ **/
+typedef struct xcb_input_xi_passive_ungrab_device_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_window_t grab_window;
+ uint32_t detail;
+ xcb_input_device_id_t deviceid;
+ uint16_t num_modifiers;
+ uint8_t grab_type;
+ uint8_t pad0[3];
+} xcb_input_xi_passive_ungrab_device_request_t;
+
+/**
+ * @brief xcb_input_xi_list_properties_cookie_t
+ **/
+typedef struct xcb_input_xi_list_properties_cookie_t {
+ unsigned int sequence;
+} xcb_input_xi_list_properties_cookie_t;
+
+/** Opcode for xcb_input_xi_list_properties. */
+#define XCB_INPUT_XI_LIST_PROPERTIES 56
+
+/**
+ * @brief xcb_input_xi_list_properties_request_t
+ **/
+typedef struct xcb_input_xi_list_properties_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_input_device_id_t deviceid;
+ uint8_t pad0[2];
+} xcb_input_xi_list_properties_request_t;
+
+/**
+ * @brief xcb_input_xi_list_properties_reply_t
+ **/
+typedef struct xcb_input_xi_list_properties_reply_t {
+ uint8_t response_type;
+ uint8_t pad0;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t num_properties;
+ uint8_t pad1[22];
+} xcb_input_xi_list_properties_reply_t;
+
+/**
+ * @brief xcb_input_xi_change_property_items_t
+ **/
+typedef struct xcb_input_xi_change_property_items_t {
+ uint8_t *data8;
+ uint16_t *data16;
+ uint32_t *data32;
+} xcb_input_xi_change_property_items_t;
+
+/** Opcode for xcb_input_xi_change_property. */
+#define XCB_INPUT_XI_CHANGE_PROPERTY 57
+
+/**
+ * @brief xcb_input_xi_change_property_request_t
+ **/
+typedef struct xcb_input_xi_change_property_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_input_device_id_t deviceid;
+ uint8_t mode;
+ uint8_t format;
+ xcb_atom_t property;
+ xcb_atom_t type;
+ uint32_t num_items;
+} xcb_input_xi_change_property_request_t;
+
+/** Opcode for xcb_input_xi_delete_property. */
+#define XCB_INPUT_XI_DELETE_PROPERTY 58
+
+/**
+ * @brief xcb_input_xi_delete_property_request_t
+ **/
+typedef struct xcb_input_xi_delete_property_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_input_device_id_t deviceid;
+ uint8_t pad0[2];
+ xcb_atom_t property;
+} xcb_input_xi_delete_property_request_t;
+
+/**
+ * @brief xcb_input_xi_get_property_cookie_t
+ **/
+typedef struct xcb_input_xi_get_property_cookie_t {
+ unsigned int sequence;
+} xcb_input_xi_get_property_cookie_t;
+
+/** Opcode for xcb_input_xi_get_property. */
+#define XCB_INPUT_XI_GET_PROPERTY 59
+
+/**
+ * @brief xcb_input_xi_get_property_request_t
+ **/
+typedef struct xcb_input_xi_get_property_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_input_device_id_t deviceid;
+ uint8_t _delete;
+ uint8_t pad0;
+ xcb_atom_t property;
+ xcb_atom_t type;
+ uint32_t offset;
+ uint32_t len;
+} xcb_input_xi_get_property_request_t;
+
+/**
+ * @brief xcb_input_xi_get_property_items_t
+ **/
+typedef struct xcb_input_xi_get_property_items_t {
+ uint8_t *data8;
+ uint16_t *data16;
+ uint32_t *data32;
+} xcb_input_xi_get_property_items_t;
+
+/**
+ * @brief xcb_input_xi_get_property_reply_t
+ **/
+typedef struct xcb_input_xi_get_property_reply_t {
+ uint8_t response_type;
+ uint8_t pad0;
+ uint16_t sequence;
+ uint32_t length;
+ xcb_atom_t type;
+ uint32_t bytes_after;
+ uint32_t num_items;
+ uint8_t format;
+ uint8_t pad1[11];
+} xcb_input_xi_get_property_reply_t;
+
+/**
+ * @brief xcb_input_xi_get_selected_events_cookie_t
+ **/
+typedef struct xcb_input_xi_get_selected_events_cookie_t {
+ unsigned int sequence;
+} xcb_input_xi_get_selected_events_cookie_t;
+
+/** Opcode for xcb_input_xi_get_selected_events. */
+#define XCB_INPUT_XI_GET_SELECTED_EVENTS 60
+
+/**
+ * @brief xcb_input_xi_get_selected_events_request_t
+ **/
+typedef struct xcb_input_xi_get_selected_events_request_t {
+ uint8_t major_opcode;
+ uint8_t minor_opcode;
+ uint16_t length;
+ xcb_window_t window;
+} xcb_input_xi_get_selected_events_request_t;
+
+/**
+ * @brief xcb_input_xi_get_selected_events_reply_t
+ **/
+typedef struct xcb_input_xi_get_selected_events_reply_t {
+ uint8_t response_type;
+ uint8_t pad0;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t num_masks;
+ uint8_t pad1[22];
+} xcb_input_xi_get_selected_events_reply_t;
+
+/** Opcode for xcb_input_device_valuator. */
+#define XCB_INPUT_DEVICE_VALUATOR 0
+
+/**
+ * @brief xcb_input_device_valuator_event_t
+ **/
+typedef struct xcb_input_device_valuator_event_t {
+ uint8_t response_type;
+ uint8_t device_id;
+ uint16_t sequence;
+ uint16_t device_state;
+ uint8_t num_valuators;
+ uint8_t first_valuator;
+ int32_t valuators[6];
+} xcb_input_device_valuator_event_t;
+
+typedef enum xcb_input_more_events_mask_t {
+ XCB_INPUT_MORE_EVENTS_MASK_MORE_EVENTS = 128
+} xcb_input_more_events_mask_t;
+
+/** Opcode for xcb_input_device_key_press. */
+#define XCB_INPUT_DEVICE_KEY_PRESS 1
+
+/**
+ * @brief xcb_input_device_key_press_event_t
+ **/
+typedef struct xcb_input_device_key_press_event_t {
+ uint8_t response_type;
+ uint8_t detail;
+ uint16_t sequence;
+ xcb_timestamp_t time;
+ xcb_window_t root;
+ xcb_window_t event;
+ xcb_window_t child;
+ int16_t root_x;
+ int16_t root_y;
+ int16_t event_x;
+ int16_t event_y;
+ uint16_t state;
+ uint8_t same_screen;
+ uint8_t device_id;
+} xcb_input_device_key_press_event_t;
+
+/** Opcode for xcb_input_device_key_release. */
+#define XCB_INPUT_DEVICE_KEY_RELEASE 2
+
+typedef xcb_input_device_key_press_event_t xcb_input_device_key_release_event_t;
+
+/** Opcode for xcb_input_device_button_press. */
+#define XCB_INPUT_DEVICE_BUTTON_PRESS 3
+
+typedef xcb_input_device_key_press_event_t xcb_input_device_button_press_event_t;
+
+/** Opcode for xcb_input_device_button_release. */
+#define XCB_INPUT_DEVICE_BUTTON_RELEASE 4
+
+typedef xcb_input_device_key_press_event_t xcb_input_device_button_release_event_t;
+
+/** Opcode for xcb_input_device_motion_notify. */
+#define XCB_INPUT_DEVICE_MOTION_NOTIFY 5
+
+typedef xcb_input_device_key_press_event_t xcb_input_device_motion_notify_event_t;
+
+/** Opcode for xcb_input_device_focus_in. */
+#define XCB_INPUT_DEVICE_FOCUS_IN 6
+
+/**
+ * @brief xcb_input_device_focus_in_event_t
+ **/
+typedef struct xcb_input_device_focus_in_event_t {
+ uint8_t response_type;
+ uint8_t detail;
+ uint16_t sequence;
+ xcb_timestamp_t time;
+ xcb_window_t window;
+ uint8_t mode;
+ uint8_t device_id;
+ uint8_t pad0[18];
+} xcb_input_device_focus_in_event_t;
+
+/** Opcode for xcb_input_device_focus_out. */
+#define XCB_INPUT_DEVICE_FOCUS_OUT 7
+
+typedef xcb_input_device_focus_in_event_t xcb_input_device_focus_out_event_t;
+
+/** Opcode for xcb_input_proximity_in. */
+#define XCB_INPUT_PROXIMITY_IN 8
+
+typedef xcb_input_device_key_press_event_t xcb_input_proximity_in_event_t;
+
+/** Opcode for xcb_input_proximity_out. */
+#define XCB_INPUT_PROXIMITY_OUT 9
+
+typedef xcb_input_device_key_press_event_t xcb_input_proximity_out_event_t;
+
+typedef enum xcb_input_classes_reported_mask_t {
+ XCB_INPUT_CLASSES_REPORTED_MASK_OUT_OF_PROXIMITY = 128,
+ XCB_INPUT_CLASSES_REPORTED_MASK_DEVICE_MODE_ABSOLUTE = 64,
+ XCB_INPUT_CLASSES_REPORTED_MASK_REPORTING_VALUATORS = 4,
+ XCB_INPUT_CLASSES_REPORTED_MASK_REPORTING_BUTTONS = 2,
+ XCB_INPUT_CLASSES_REPORTED_MASK_REPORTING_KEYS = 1
+} xcb_input_classes_reported_mask_t;
+
+/** Opcode for xcb_input_device_state_notify. */
+#define XCB_INPUT_DEVICE_STATE_NOTIFY 10
+
+/**
+ * @brief xcb_input_device_state_notify_event_t
+ **/
+typedef struct xcb_input_device_state_notify_event_t {
+ uint8_t response_type;
+ uint8_t device_id;
+ uint16_t sequence;
+ xcb_timestamp_t time;
+ uint8_t num_keys;
+ uint8_t num_buttons;
+ uint8_t num_valuators;
+ uint8_t classes_reported;
+ uint8_t buttons[4];
+ uint8_t keys[4];
+ uint32_t valuators[3];
+} xcb_input_device_state_notify_event_t;
+
+/** Opcode for xcb_input_device_mapping_notify. */
+#define XCB_INPUT_DEVICE_MAPPING_NOTIFY 11
+
+/**
+ * @brief xcb_input_device_mapping_notify_event_t
+ **/
+typedef struct xcb_input_device_mapping_notify_event_t {
+ uint8_t response_type;
+ uint8_t device_id;
+ uint16_t sequence;
+ uint8_t request;
+ xcb_input_key_code_t first_keycode;
+ uint8_t count;
+ uint8_t pad0;
+ xcb_timestamp_t time;
+ uint8_t pad1[20];
+} xcb_input_device_mapping_notify_event_t;
+
+typedef enum xcb_input_change_device_t {
+ XCB_INPUT_CHANGE_DEVICE_NEW_POINTER = 0,
+ XCB_INPUT_CHANGE_DEVICE_NEW_KEYBOARD = 1
+} xcb_input_change_device_t;
+
+/** Opcode for xcb_input_change_device_notify. */
+#define XCB_INPUT_CHANGE_DEVICE_NOTIFY 12
+
+/**
+ * @brief xcb_input_change_device_notify_event_t
+ **/
+typedef struct xcb_input_change_device_notify_event_t {
+ uint8_t response_type;
+ uint8_t device_id;
+ uint16_t sequence;
+ xcb_timestamp_t time;
+ uint8_t request;
+ uint8_t pad0[23];
+} xcb_input_change_device_notify_event_t;
+
+/** Opcode for xcb_input_device_key_state_notify. */
+#define XCB_INPUT_DEVICE_KEY_STATE_NOTIFY 13
+
+/**
+ * @brief xcb_input_device_key_state_notify_event_t
+ **/
+typedef struct xcb_input_device_key_state_notify_event_t {
+ uint8_t response_type;
+ uint8_t device_id;
+ uint16_t sequence;
+ uint8_t keys[28];
+} xcb_input_device_key_state_notify_event_t;
+
+/** Opcode for xcb_input_device_button_state_notify. */
+#define XCB_INPUT_DEVICE_BUTTON_STATE_NOTIFY 14
+
+/**
+ * @brief xcb_input_device_button_state_notify_event_t
+ **/
+typedef struct xcb_input_device_button_state_notify_event_t {
+ uint8_t response_type;
+ uint8_t device_id;
+ uint16_t sequence;
+ uint8_t buttons[28];
+} xcb_input_device_button_state_notify_event_t;
+
+typedef enum xcb_input_device_change_t {
+ XCB_INPUT_DEVICE_CHANGE_ADDED = 0,
+ XCB_INPUT_DEVICE_CHANGE_REMOVED = 1,
+ XCB_INPUT_DEVICE_CHANGE_ENABLED = 2,
+ XCB_INPUT_DEVICE_CHANGE_DISABLED = 3,
+ XCB_INPUT_DEVICE_CHANGE_UNRECOVERABLE = 4,
+ XCB_INPUT_DEVICE_CHANGE_CONTROL_CHANGED = 5
+} xcb_input_device_change_t;
+
+/** Opcode for xcb_input_device_presence_notify. */
+#define XCB_INPUT_DEVICE_PRESENCE_NOTIFY 15
+
+/**
+ * @brief xcb_input_device_presence_notify_event_t
+ **/
+typedef struct xcb_input_device_presence_notify_event_t {
+ uint8_t response_type;
+ uint8_t pad0;
+ uint16_t sequence;
+ xcb_timestamp_t time;
+ uint8_t devchange;
+ uint8_t device_id;
+ uint16_t control;
+ uint8_t pad1[20];
+} xcb_input_device_presence_notify_event_t;
+
+/** Opcode for xcb_input_device_property_notify. */
+#define XCB_INPUT_DEVICE_PROPERTY_NOTIFY 16
+
+/**
+ * @brief xcb_input_device_property_notify_event_t
+ **/
+typedef struct xcb_input_device_property_notify_event_t {
+ uint8_t response_type;
+ uint8_t state;
+ uint16_t sequence;
+ xcb_timestamp_t time;
+ xcb_atom_t property;
+ uint8_t pad0[19];
+ uint8_t device_id;
+} xcb_input_device_property_notify_event_t;
+
+typedef enum xcb_input_change_reason_t {
+ XCB_INPUT_CHANGE_REASON_SLAVE_SWITCH = 1,
+ XCB_INPUT_CHANGE_REASON_DEVICE_CHANGE = 2
+} xcb_input_change_reason_t;
+
+/** Opcode for xcb_input_device_changed. */
+#define XCB_INPUT_DEVICE_CHANGED 1
+
+/**
+ * @brief xcb_input_device_changed_event_t
+ **/
+typedef struct xcb_input_device_changed_event_t {
+ uint8_t response_type;
+ uint8_t extension;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t event_type;
+ xcb_input_device_id_t deviceid;
+ xcb_timestamp_t time;
+ uint16_t num_classes;
+ xcb_input_device_id_t sourceid;
+ uint8_t reason;
+ uint8_t pad0[11];
+ uint32_t full_sequence;
+} xcb_input_device_changed_event_t;
+
+typedef enum xcb_input_key_event_flags_t {
+ XCB_INPUT_KEY_EVENT_FLAGS_KEY_REPEAT = 65536
+} xcb_input_key_event_flags_t;
+
+/** Opcode for xcb_input_key_press. */
+#define XCB_INPUT_KEY_PRESS 2
+
+/**
+ * @brief xcb_input_key_press_event_t
+ **/
+typedef struct xcb_input_key_press_event_t {
+ uint8_t response_type;
+ uint8_t extension;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t event_type;
+ xcb_input_device_id_t deviceid;
+ xcb_timestamp_t time;
+ uint32_t detail;
+ xcb_window_t root;
+ xcb_window_t event;
+ xcb_window_t child;
+ uint32_t full_sequence;
+ xcb_input_fp1616_t root_x;
+ xcb_input_fp1616_t root_y;
+ xcb_input_fp1616_t event_x;
+ xcb_input_fp1616_t event_y;
+ uint16_t buttons_len;
+ uint16_t valuators_len;
+ xcb_input_device_id_t sourceid;
+ uint8_t pad0[2];
+ uint32_t flags;
+ xcb_input_modifier_info_t mods;
+ xcb_input_group_info_t group;
+} xcb_input_key_press_event_t;
+
+/** Opcode for xcb_input_key_release. */
+#define XCB_INPUT_KEY_RELEASE 3
+
+typedef xcb_input_key_press_event_t xcb_input_key_release_event_t;
+
+typedef enum xcb_input_pointer_event_flags_t {
+ XCB_INPUT_POINTER_EVENT_FLAGS_POINTER_EMULATED = 65536
+} xcb_input_pointer_event_flags_t;
+
+/** Opcode for xcb_input_button_press. */
+#define XCB_INPUT_BUTTON_PRESS 4
+
+/**
+ * @brief xcb_input_button_press_event_t
+ **/
+typedef struct xcb_input_button_press_event_t {
+ uint8_t response_type;
+ uint8_t extension;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t event_type;
+ xcb_input_device_id_t deviceid;
+ xcb_timestamp_t time;
+ uint32_t detail;
+ xcb_window_t root;
+ xcb_window_t event;
+ xcb_window_t child;
+ uint32_t full_sequence;
+ xcb_input_fp1616_t root_x;
+ xcb_input_fp1616_t root_y;
+ xcb_input_fp1616_t event_x;
+ xcb_input_fp1616_t event_y;
+ uint16_t buttons_len;
+ uint16_t valuators_len;
+ xcb_input_device_id_t sourceid;
+ uint8_t pad0[2];
+ uint32_t flags;
+ xcb_input_modifier_info_t mods;
+ xcb_input_group_info_t group;
+} xcb_input_button_press_event_t;
+
+/** Opcode for xcb_input_button_release. */
+#define XCB_INPUT_BUTTON_RELEASE 5
+
+typedef xcb_input_button_press_event_t xcb_input_button_release_event_t;
+
+/** Opcode for xcb_input_motion. */
+#define XCB_INPUT_MOTION 6
+
+typedef xcb_input_button_press_event_t xcb_input_motion_event_t;
+
+typedef enum xcb_input_notify_mode_t {
+ XCB_INPUT_NOTIFY_MODE_NORMAL = 0,
+ XCB_INPUT_NOTIFY_MODE_GRAB = 1,
+ XCB_INPUT_NOTIFY_MODE_UNGRAB = 2,
+ XCB_INPUT_NOTIFY_MODE_WHILE_GRABBED = 3,
+ XCB_INPUT_NOTIFY_MODE_PASSIVE_GRAB = 4,
+ XCB_INPUT_NOTIFY_MODE_PASSIVE_UNGRAB = 5
+} xcb_input_notify_mode_t;
+
+typedef enum xcb_input_notify_detail_t {
+ XCB_INPUT_NOTIFY_DETAIL_ANCESTOR = 0,
+ XCB_INPUT_NOTIFY_DETAIL_VIRTUAL = 1,
+ XCB_INPUT_NOTIFY_DETAIL_INFERIOR = 2,
+ XCB_INPUT_NOTIFY_DETAIL_NONLINEAR = 3,
+ XCB_INPUT_NOTIFY_DETAIL_NONLINEAR_VIRTUAL = 4,
+ XCB_INPUT_NOTIFY_DETAIL_POINTER = 5,
+ XCB_INPUT_NOTIFY_DETAIL_POINTER_ROOT = 6,
+ XCB_INPUT_NOTIFY_DETAIL_NONE = 7
+} xcb_input_notify_detail_t;
+
+/** Opcode for xcb_input_enter. */
+#define XCB_INPUT_ENTER 7
+
+/**
+ * @brief xcb_input_enter_event_t
+ **/
+typedef struct xcb_input_enter_event_t {
+ uint8_t response_type;
+ uint8_t extension;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t event_type;
+ xcb_input_device_id_t deviceid;
+ xcb_timestamp_t time;
+ xcb_input_device_id_t sourceid;
+ uint8_t mode;
+ uint8_t detail;
+ xcb_window_t root;
+ xcb_window_t event;
+ xcb_window_t child;
+ uint32_t full_sequence;
+ xcb_input_fp1616_t root_x;
+ xcb_input_fp1616_t root_y;
+ xcb_input_fp1616_t event_x;
+ xcb_input_fp1616_t event_y;
+ uint8_t same_screen;
+ uint8_t focus;
+ uint16_t buttons_len;
+ xcb_input_modifier_info_t mods;
+ xcb_input_group_info_t group;
+} xcb_input_enter_event_t;
+
+/** Opcode for xcb_input_leave. */
+#define XCB_INPUT_LEAVE 8
+
+typedef xcb_input_enter_event_t xcb_input_leave_event_t;
+
+/** Opcode for xcb_input_focus_in. */
+#define XCB_INPUT_FOCUS_IN 9
+
+typedef xcb_input_enter_event_t xcb_input_focus_in_event_t;
+
+/** Opcode for xcb_input_focus_out. */
+#define XCB_INPUT_FOCUS_OUT 10
+
+typedef xcb_input_enter_event_t xcb_input_focus_out_event_t;
+
+typedef enum xcb_input_hierarchy_mask_t {
+ XCB_INPUT_HIERARCHY_MASK_MASTER_ADDED = 1,
+ XCB_INPUT_HIERARCHY_MASK_MASTER_REMOVED = 2,
+ XCB_INPUT_HIERARCHY_MASK_SLAVE_ADDED = 4,
+ XCB_INPUT_HIERARCHY_MASK_SLAVE_REMOVED = 8,
+ XCB_INPUT_HIERARCHY_MASK_SLAVE_ATTACHED = 16,
+ XCB_INPUT_HIERARCHY_MASK_SLAVE_DETACHED = 32,
+ XCB_INPUT_HIERARCHY_MASK_DEVICE_ENABLED = 64,
+ XCB_INPUT_HIERARCHY_MASK_DEVICE_DISABLED = 128
+} xcb_input_hierarchy_mask_t;
+
+/**
+ * @brief xcb_input_hierarchy_info_t
+ **/
+typedef struct xcb_input_hierarchy_info_t {
+ xcb_input_device_id_t deviceid;
+ xcb_input_device_id_t attachment;
+ uint8_t type;
+ uint8_t enabled;
+ uint8_t pad0[2];
+ uint32_t flags;
+} xcb_input_hierarchy_info_t;
+
+/**
+ * @brief xcb_input_hierarchy_info_iterator_t
+ **/
+typedef struct xcb_input_hierarchy_info_iterator_t {
+ xcb_input_hierarchy_info_t *data;
+ int rem;
+ int index;
+} xcb_input_hierarchy_info_iterator_t;
+
+/** Opcode for xcb_input_hierarchy. */
+#define XCB_INPUT_HIERARCHY 11
+
+/**
+ * @brief xcb_input_hierarchy_event_t
+ **/
+typedef struct xcb_input_hierarchy_event_t {
+ uint8_t response_type;
+ uint8_t extension;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t event_type;
+ xcb_input_device_id_t deviceid;
+ xcb_timestamp_t time;
+ uint32_t flags;
+ uint16_t num_infos;
+ uint8_t pad0[10];
+ uint32_t full_sequence;
+} xcb_input_hierarchy_event_t;
+
+typedef enum xcb_input_property_flag_t {
+ XCB_INPUT_PROPERTY_FLAG_DELETED = 0,
+ XCB_INPUT_PROPERTY_FLAG_CREATED = 1,
+ XCB_INPUT_PROPERTY_FLAG_MODIFIED = 2
+} xcb_input_property_flag_t;
+
+/** Opcode for xcb_input_property. */
+#define XCB_INPUT_PROPERTY 12
+
+/**
+ * @brief xcb_input_property_event_t
+ **/
+typedef struct xcb_input_property_event_t {
+ uint8_t response_type;
+ uint8_t extension;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t event_type;
+ xcb_input_device_id_t deviceid;
+ xcb_timestamp_t time;
+ xcb_atom_t property;
+ uint8_t what;
+ uint8_t pad0[11];
+ uint32_t full_sequence;
+} xcb_input_property_event_t;
+
+/** Opcode for xcb_input_raw_key_press. */
+#define XCB_INPUT_RAW_KEY_PRESS 13
+
+/**
+ * @brief xcb_input_raw_key_press_event_t
+ **/
+typedef struct xcb_input_raw_key_press_event_t {
+ uint8_t response_type;
+ uint8_t extension;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t event_type;
+ xcb_input_device_id_t deviceid;
+ xcb_timestamp_t time;
+ uint32_t detail;
+ xcb_input_device_id_t sourceid;
+ uint16_t valuators_len;
+ uint32_t flags;
+ uint8_t pad0[4];
+ uint32_t full_sequence;
+} xcb_input_raw_key_press_event_t;
+
+/** Opcode for xcb_input_raw_key_release. */
+#define XCB_INPUT_RAW_KEY_RELEASE 14
+
+typedef xcb_input_raw_key_press_event_t xcb_input_raw_key_release_event_t;
+
+/** Opcode for xcb_input_raw_button_press. */
+#define XCB_INPUT_RAW_BUTTON_PRESS 15
+
+/**
+ * @brief xcb_input_raw_button_press_event_t
+ **/
+typedef struct xcb_input_raw_button_press_event_t {
+ uint8_t response_type;
+ uint8_t extension;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t event_type;
+ xcb_input_device_id_t deviceid;
+ xcb_timestamp_t time;
+ uint32_t detail;
+ xcb_input_device_id_t sourceid;
+ uint16_t valuators_len;
+ uint32_t flags;
+ uint8_t pad0[4];
+ uint32_t full_sequence;
+} xcb_input_raw_button_press_event_t;
+
+/** Opcode for xcb_input_raw_button_release. */
+#define XCB_INPUT_RAW_BUTTON_RELEASE 16
+
+typedef xcb_input_raw_button_press_event_t xcb_input_raw_button_release_event_t;
+
+/** Opcode for xcb_input_raw_motion. */
+#define XCB_INPUT_RAW_MOTION 17
+
+typedef xcb_input_raw_button_press_event_t xcb_input_raw_motion_event_t;
+
+typedef enum xcb_input_touch_event_flags_t {
+ XCB_INPUT_TOUCH_EVENT_FLAGS_TOUCH_PENDING_END = 65536,
+ XCB_INPUT_TOUCH_EVENT_FLAGS_TOUCH_EMULATING_POINTER = 131072
+} xcb_input_touch_event_flags_t;
+
+/** Opcode for xcb_input_touch_begin. */
+#define XCB_INPUT_TOUCH_BEGIN 18
+
+/**
+ * @brief xcb_input_touch_begin_event_t
+ **/
+typedef struct xcb_input_touch_begin_event_t {
+ uint8_t response_type;
+ uint8_t extension;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t event_type;
+ xcb_input_device_id_t deviceid;
+ xcb_timestamp_t time;
+ uint32_t detail;
+ xcb_window_t root;
+ xcb_window_t event;
+ xcb_window_t child;
+ uint32_t full_sequence;
+ xcb_input_fp1616_t root_x;
+ xcb_input_fp1616_t root_y;
+ xcb_input_fp1616_t event_x;
+ xcb_input_fp1616_t event_y;
+ uint16_t buttons_len;
+ uint16_t valuators_len;
+ xcb_input_device_id_t sourceid;
+ uint8_t pad0[2];
+ uint32_t flags;
+ xcb_input_modifier_info_t mods;
+ xcb_input_group_info_t group;
+} xcb_input_touch_begin_event_t;
+
+/** Opcode for xcb_input_touch_update. */
+#define XCB_INPUT_TOUCH_UPDATE 19
+
+typedef xcb_input_touch_begin_event_t xcb_input_touch_update_event_t;
+
+/** Opcode for xcb_input_touch_end. */
+#define XCB_INPUT_TOUCH_END 20
+
+typedef xcb_input_touch_begin_event_t xcb_input_touch_end_event_t;
+
+typedef enum xcb_input_touch_ownership_flags_t {
+ XCB_INPUT_TOUCH_OWNERSHIP_FLAGS_NONE = 0
+} xcb_input_touch_ownership_flags_t;
+
+/** Opcode for xcb_input_touch_ownership. */
+#define XCB_INPUT_TOUCH_OWNERSHIP 21
+
+/**
+ * @brief xcb_input_touch_ownership_event_t
+ **/
+typedef struct xcb_input_touch_ownership_event_t {
+ uint8_t response_type;
+ uint8_t extension;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t event_type;
+ xcb_input_device_id_t deviceid;
+ xcb_timestamp_t time;
+ uint32_t touchid;
+ xcb_window_t root;
+ xcb_window_t event;
+ xcb_window_t child;
+ uint32_t full_sequence;
+ xcb_input_device_id_t sourceid;
+ uint8_t pad0[2];
+ uint32_t flags;
+ uint8_t pad1[8];
+} xcb_input_touch_ownership_event_t;
+
+/** Opcode for xcb_input_raw_touch_begin. */
+#define XCB_INPUT_RAW_TOUCH_BEGIN 22
+
+/**
+ * @brief xcb_input_raw_touch_begin_event_t
+ **/
+typedef struct xcb_input_raw_touch_begin_event_t {
+ uint8_t response_type;
+ uint8_t extension;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t event_type;
+ xcb_input_device_id_t deviceid;
+ xcb_timestamp_t time;
+ uint32_t detail;
+ xcb_input_device_id_t sourceid;
+ uint16_t valuators_len;
+ uint32_t flags;
+ uint8_t pad0[4];
+ uint32_t full_sequence;
+} xcb_input_raw_touch_begin_event_t;
+
+/** Opcode for xcb_input_raw_touch_update. */
+#define XCB_INPUT_RAW_TOUCH_UPDATE 23
+
+typedef xcb_input_raw_touch_begin_event_t xcb_input_raw_touch_update_event_t;
+
+/** Opcode for xcb_input_raw_touch_end. */
+#define XCB_INPUT_RAW_TOUCH_END 24
+
+typedef xcb_input_raw_touch_begin_event_t xcb_input_raw_touch_end_event_t;
+
+/** Opcode for xcb_input_barrier_hit. */
+#define XCB_INPUT_BARRIER_HIT 25
+
+/** Opcode for xcb_input_barrier_leave. */
+#define XCB_INPUT_BARRIER_LEAVE 26
+
+/** Opcode for xcb_input_device. */
+#define XCB_INPUT_DEVICE 0
+
+/**
+ * @brief xcb_input_device_error_t
+ **/
+typedef struct xcb_input_device_error_t {
+ uint8_t response_type;
+ uint8_t error_code;
+ uint16_t sequence;
+} xcb_input_device_error_t;
+
+/** Opcode for xcb_input_event. */
+#define XCB_INPUT_EVENT 1
+
+/**
+ * @brief xcb_input_event_error_t
+ **/
+typedef struct xcb_input_event_error_t {
+ uint8_t response_type;
+ uint8_t error_code;
+ uint16_t sequence;
+} xcb_input_event_error_t;
+
+/** Opcode for xcb_input_mode. */
+#define XCB_INPUT_MODE 2
+
+/**
+ * @brief xcb_input_mode_error_t
+ **/
+typedef struct xcb_input_mode_error_t {
+ uint8_t response_type;
+ uint8_t error_code;
+ uint16_t sequence;
+} xcb_input_mode_error_t;
+
+/** Opcode for xcb_input_device_busy. */
+#define XCB_INPUT_DEVICE_BUSY 3
+
+/**
+ * @brief xcb_input_device_busy_error_t
+ **/
+typedef struct xcb_input_device_busy_error_t {
+ uint8_t response_type;
+ uint8_t error_code;
+ uint16_t sequence;
+} xcb_input_device_busy_error_t;
+
+/** Opcode for xcb_input_class. */
+#define XCB_INPUT_CLASS 4
+
+/**
+ * @brief xcb_input_class_error_t
+ **/
+typedef struct xcb_input_class_error_t {
+ uint8_t response_type;
+ uint8_t error_code;
+ uint16_t sequence;
+} xcb_input_class_error_t;
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_event_class_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_event_class_t)
+ */
+void
+xcb_input_event_class_next (xcb_input_event_class_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_event_class_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_event_class_end (xcb_input_event_class_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_key_code_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_key_code_t)
+ */
+void
+xcb_input_key_code_next (xcb_input_key_code_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_key_code_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_key_code_end (xcb_input_key_code_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_device_id_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_device_id_t)
+ */
+void
+xcb_input_device_id_next (xcb_input_device_id_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_device_id_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_device_id_end (xcb_input_device_id_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_fp1616_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_fp1616_t)
+ */
+void
+xcb_input_fp1616_next (xcb_input_fp1616_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_fp1616_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_fp1616_end (xcb_input_fp1616_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_fp3232_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_fp3232_t)
+ */
+void
+xcb_input_fp3232_next (xcb_input_fp3232_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_fp3232_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_fp3232_end (xcb_input_fp3232_iterator_t i);
+
+int
+xcb_input_get_extension_version_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_get_extension_version_cookie_t
+xcb_input_get_extension_version (xcb_connection_t *c,
+ uint16_t name_len,
+ const char *name);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_get_extension_version_cookie_t
+xcb_input_get_extension_version_unchecked (xcb_connection_t *c,
+ uint16_t name_len,
+ const char *name);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_get_extension_version_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_get_extension_version_reply_t *
+xcb_input_get_extension_version_reply (xcb_connection_t *c,
+ xcb_input_get_extension_version_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_device_info_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_device_info_t)
+ */
+void
+xcb_input_device_info_next (xcb_input_device_info_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_device_info_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_device_info_end (xcb_input_device_info_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_key_info_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_key_info_t)
+ */
+void
+xcb_input_key_info_next (xcb_input_key_info_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_key_info_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_key_info_end (xcb_input_key_info_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_button_info_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_button_info_t)
+ */
+void
+xcb_input_button_info_next (xcb_input_button_info_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_button_info_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_button_info_end (xcb_input_button_info_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_axis_info_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_axis_info_t)
+ */
+void
+xcb_input_axis_info_next (xcb_input_axis_info_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_axis_info_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_axis_info_end (xcb_input_axis_info_iterator_t i);
+
+int
+xcb_input_valuator_info_sizeof (const void *_buffer);
+
+xcb_input_axis_info_t *
+xcb_input_valuator_info_axes (const xcb_input_valuator_info_t *R);
+
+int
+xcb_input_valuator_info_axes_length (const xcb_input_valuator_info_t *R);
+
+xcb_input_axis_info_iterator_t
+xcb_input_valuator_info_axes_iterator (const xcb_input_valuator_info_t *R);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_valuator_info_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_valuator_info_t)
+ */
+void
+xcb_input_valuator_info_next (xcb_input_valuator_info_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_valuator_info_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_valuator_info_end (xcb_input_valuator_info_iterator_t i);
+
+xcb_input_axis_info_t *
+xcb_input_input_info_info_valuator_axes (const xcb_input_input_info_info_t *S);
+
+int
+xcb_input_input_info_info_valuator_axes_length (const xcb_input_input_info_t *R,
+ const xcb_input_input_info_info_t *S);
+
+xcb_input_axis_info_iterator_t
+xcb_input_input_info_info_valuator_axes_iterator (const xcb_input_input_info_t *R,
+ const xcb_input_input_info_info_t *S);
+
+int
+xcb_input_input_info_info_serialize (void **_buffer,
+ uint8_t class_id,
+ const xcb_input_input_info_info_t *_aux);
+
+int
+xcb_input_input_info_info_unpack (const void *_buffer,
+ uint8_t class_id,
+ xcb_input_input_info_info_t *_aux);
+
+int
+xcb_input_input_info_info_sizeof (const void *_buffer,
+ uint8_t class_id);
+
+int
+xcb_input_input_info_sizeof (const void *_buffer);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_input_info_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_input_info_t)
+ */
+void
+xcb_input_input_info_next (xcb_input_input_info_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_input_info_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_input_info_end (xcb_input_input_info_iterator_t i);
+
+int
+xcb_input_device_name_sizeof (const void *_buffer);
+
+char *
+xcb_input_device_name_string (const xcb_input_device_name_t *R);
+
+int
+xcb_input_device_name_string_length (const xcb_input_device_name_t *R);
+
+xcb_generic_iterator_t
+xcb_input_device_name_string_end (const xcb_input_device_name_t *R);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_device_name_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_device_name_t)
+ */
+void
+xcb_input_device_name_next (xcb_input_device_name_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_device_name_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_device_name_end (xcb_input_device_name_iterator_t i);
+
+int
+xcb_input_list_input_devices_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_list_input_devices_cookie_t
+xcb_input_list_input_devices (xcb_connection_t *c);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_list_input_devices_cookie_t
+xcb_input_list_input_devices_unchecked (xcb_connection_t *c);
+
+xcb_input_device_info_t *
+xcb_input_list_input_devices_devices (const xcb_input_list_input_devices_reply_t *R);
+
+int
+xcb_input_list_input_devices_devices_length (const xcb_input_list_input_devices_reply_t *R);
+
+xcb_input_device_info_iterator_t
+xcb_input_list_input_devices_devices_iterator (const xcb_input_list_input_devices_reply_t *R);
+
+int
+xcb_input_list_input_devices_infos_length (const xcb_input_list_input_devices_reply_t *R);
+
+xcb_input_input_info_iterator_t
+xcb_input_list_input_devices_infos_iterator (const xcb_input_list_input_devices_reply_t *R);
+
+int
+xcb_input_list_input_devices_names_length (const xcb_input_list_input_devices_reply_t *R);
+
+xcb_str_iterator_t
+xcb_input_list_input_devices_names_iterator (const xcb_input_list_input_devices_reply_t *R);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_list_input_devices_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_list_input_devices_reply_t *
+xcb_input_list_input_devices_reply (xcb_connection_t *c,
+ xcb_input_list_input_devices_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_event_type_base_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_event_type_base_t)
+ */
+void
+xcb_input_event_type_base_next (xcb_input_event_type_base_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_event_type_base_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_event_type_base_end (xcb_input_event_type_base_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_input_class_info_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_input_class_info_t)
+ */
+void
+xcb_input_input_class_info_next (xcb_input_input_class_info_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_input_class_info_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_input_class_info_end (xcb_input_input_class_info_iterator_t i);
+
+int
+xcb_input_open_device_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_open_device_cookie_t
+xcb_input_open_device (xcb_connection_t *c,
+ uint8_t device_id);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_open_device_cookie_t
+xcb_input_open_device_unchecked (xcb_connection_t *c,
+ uint8_t device_id);
+
+xcb_input_input_class_info_t *
+xcb_input_open_device_class_info (const xcb_input_open_device_reply_t *R);
+
+int
+xcb_input_open_device_class_info_length (const xcb_input_open_device_reply_t *R);
+
+xcb_input_input_class_info_iterator_t
+xcb_input_open_device_class_info_iterator (const xcb_input_open_device_reply_t *R);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_open_device_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_open_device_reply_t *
+xcb_input_open_device_reply (xcb_connection_t *c,
+ xcb_input_open_device_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_close_device_checked (xcb_connection_t *c,
+ uint8_t device_id);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_close_device (xcb_connection_t *c,
+ uint8_t device_id);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_set_device_mode_cookie_t
+xcb_input_set_device_mode (xcb_connection_t *c,
+ uint8_t device_id,
+ uint8_t mode);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_set_device_mode_cookie_t
+xcb_input_set_device_mode_unchecked (xcb_connection_t *c,
+ uint8_t device_id,
+ uint8_t mode);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_set_device_mode_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_set_device_mode_reply_t *
+xcb_input_set_device_mode_reply (xcb_connection_t *c,
+ xcb_input_set_device_mode_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+int
+xcb_input_select_extension_event_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_select_extension_event_checked (xcb_connection_t *c,
+ xcb_window_t window,
+ uint16_t num_classes,
+ const xcb_input_event_class_t *classes);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_select_extension_event (xcb_connection_t *c,
+ xcb_window_t window,
+ uint16_t num_classes,
+ const xcb_input_event_class_t *classes);
+
+xcb_input_event_class_t *
+xcb_input_select_extension_event_classes (const xcb_input_select_extension_event_request_t *R);
+
+int
+xcb_input_select_extension_event_classes_length (const xcb_input_select_extension_event_request_t *R);
+
+xcb_generic_iterator_t
+xcb_input_select_extension_event_classes_end (const xcb_input_select_extension_event_request_t *R);
+
+int
+xcb_input_get_selected_extension_events_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_get_selected_extension_events_cookie_t
+xcb_input_get_selected_extension_events (xcb_connection_t *c,
+ xcb_window_t window);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_get_selected_extension_events_cookie_t
+xcb_input_get_selected_extension_events_unchecked (xcb_connection_t *c,
+ xcb_window_t window);
+
+xcb_input_event_class_t *
+xcb_input_get_selected_extension_events_this_classes (const xcb_input_get_selected_extension_events_reply_t *R);
+
+int
+xcb_input_get_selected_extension_events_this_classes_length (const xcb_input_get_selected_extension_events_reply_t *R);
+
+xcb_generic_iterator_t
+xcb_input_get_selected_extension_events_this_classes_end (const xcb_input_get_selected_extension_events_reply_t *R);
+
+xcb_input_event_class_t *
+xcb_input_get_selected_extension_events_all_classes (const xcb_input_get_selected_extension_events_reply_t *R);
+
+int
+xcb_input_get_selected_extension_events_all_classes_length (const xcb_input_get_selected_extension_events_reply_t *R);
+
+xcb_generic_iterator_t
+xcb_input_get_selected_extension_events_all_classes_end (const xcb_input_get_selected_extension_events_reply_t *R);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_get_selected_extension_events_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_get_selected_extension_events_reply_t *
+xcb_input_get_selected_extension_events_reply (xcb_connection_t *c,
+ xcb_input_get_selected_extension_events_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+int
+xcb_input_change_device_dont_propagate_list_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_change_device_dont_propagate_list_checked (xcb_connection_t *c,
+ xcb_window_t window,
+ uint16_t num_classes,
+ uint8_t mode,
+ const xcb_input_event_class_t *classes);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_change_device_dont_propagate_list (xcb_connection_t *c,
+ xcb_window_t window,
+ uint16_t num_classes,
+ uint8_t mode,
+ const xcb_input_event_class_t *classes);
+
+xcb_input_event_class_t *
+xcb_input_change_device_dont_propagate_list_classes (const xcb_input_change_device_dont_propagate_list_request_t *R);
+
+int
+xcb_input_change_device_dont_propagate_list_classes_length (const xcb_input_change_device_dont_propagate_list_request_t *R);
+
+xcb_generic_iterator_t
+xcb_input_change_device_dont_propagate_list_classes_end (const xcb_input_change_device_dont_propagate_list_request_t *R);
+
+int
+xcb_input_get_device_dont_propagate_list_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_get_device_dont_propagate_list_cookie_t
+xcb_input_get_device_dont_propagate_list (xcb_connection_t *c,
+ xcb_window_t window);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_get_device_dont_propagate_list_cookie_t
+xcb_input_get_device_dont_propagate_list_unchecked (xcb_connection_t *c,
+ xcb_window_t window);
+
+xcb_input_event_class_t *
+xcb_input_get_device_dont_propagate_list_classes (const xcb_input_get_device_dont_propagate_list_reply_t *R);
+
+int
+xcb_input_get_device_dont_propagate_list_classes_length (const xcb_input_get_device_dont_propagate_list_reply_t *R);
+
+xcb_generic_iterator_t
+xcb_input_get_device_dont_propagate_list_classes_end (const xcb_input_get_device_dont_propagate_list_reply_t *R);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_get_device_dont_propagate_list_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_get_device_dont_propagate_list_reply_t *
+xcb_input_get_device_dont_propagate_list_reply (xcb_connection_t *c,
+ xcb_input_get_device_dont_propagate_list_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+int
+xcb_input_device_time_coord_sizeof (const void *_buffer,
+ uint8_t num_axes);
+
+int32_t *
+xcb_input_device_time_coord_axisvalues (const xcb_input_device_time_coord_t *R);
+
+int
+xcb_input_device_time_coord_axisvalues_length (const xcb_input_device_time_coord_t *R,
+ uint8_t num_axes);
+
+xcb_generic_iterator_t
+xcb_input_device_time_coord_axisvalues_end (const xcb_input_device_time_coord_t *R,
+ uint8_t num_axes);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_device_time_coord_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_device_time_coord_t)
+ */
+void
+xcb_input_device_time_coord_next (xcb_input_device_time_coord_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_device_time_coord_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_device_time_coord_end (xcb_input_device_time_coord_iterator_t i);
+
+int
+xcb_input_get_device_motion_events_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_get_device_motion_events_cookie_t
+xcb_input_get_device_motion_events (xcb_connection_t *c,
+ xcb_timestamp_t start,
+ xcb_timestamp_t stop,
+ uint8_t device_id);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_get_device_motion_events_cookie_t
+xcb_input_get_device_motion_events_unchecked (xcb_connection_t *c,
+ xcb_timestamp_t start,
+ xcb_timestamp_t stop,
+ uint8_t device_id);
+
+int
+xcb_input_get_device_motion_events_events_length (const xcb_input_get_device_motion_events_reply_t *R);
+
+xcb_input_device_time_coord_iterator_t
+xcb_input_get_device_motion_events_events_iterator (const xcb_input_get_device_motion_events_reply_t *R);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_get_device_motion_events_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_get_device_motion_events_reply_t *
+xcb_input_get_device_motion_events_reply (xcb_connection_t *c,
+ xcb_input_get_device_motion_events_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_change_keyboard_device_cookie_t
+xcb_input_change_keyboard_device (xcb_connection_t *c,
+ uint8_t device_id);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_change_keyboard_device_cookie_t
+xcb_input_change_keyboard_device_unchecked (xcb_connection_t *c,
+ uint8_t device_id);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_change_keyboard_device_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_change_keyboard_device_reply_t *
+xcb_input_change_keyboard_device_reply (xcb_connection_t *c,
+ xcb_input_change_keyboard_device_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_change_pointer_device_cookie_t
+xcb_input_change_pointer_device (xcb_connection_t *c,
+ uint8_t x_axis,
+ uint8_t y_axis,
+ uint8_t device_id);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_change_pointer_device_cookie_t
+xcb_input_change_pointer_device_unchecked (xcb_connection_t *c,
+ uint8_t x_axis,
+ uint8_t y_axis,
+ uint8_t device_id);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_change_pointer_device_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_change_pointer_device_reply_t *
+xcb_input_change_pointer_device_reply (xcb_connection_t *c,
+ xcb_input_change_pointer_device_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+int
+xcb_input_grab_device_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_grab_device_cookie_t
+xcb_input_grab_device (xcb_connection_t *c,
+ xcb_window_t grab_window,
+ xcb_timestamp_t time,
+ uint16_t num_classes,
+ uint8_t this_device_mode,
+ uint8_t other_device_mode,
+ uint8_t owner_events,
+ uint8_t device_id,
+ const xcb_input_event_class_t *classes);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_grab_device_cookie_t
+xcb_input_grab_device_unchecked (xcb_connection_t *c,
+ xcb_window_t grab_window,
+ xcb_timestamp_t time,
+ uint16_t num_classes,
+ uint8_t this_device_mode,
+ uint8_t other_device_mode,
+ uint8_t owner_events,
+ uint8_t device_id,
+ const xcb_input_event_class_t *classes);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_grab_device_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_grab_device_reply_t *
+xcb_input_grab_device_reply (xcb_connection_t *c,
+ xcb_input_grab_device_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_ungrab_device_checked (xcb_connection_t *c,
+ xcb_timestamp_t time,
+ uint8_t device_id);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_ungrab_device (xcb_connection_t *c,
+ xcb_timestamp_t time,
+ uint8_t device_id);
+
+int
+xcb_input_grab_device_key_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_grab_device_key_checked (xcb_connection_t *c,
+ xcb_window_t grab_window,
+ uint16_t num_classes,
+ uint16_t modifiers,
+ uint8_t modifier_device,
+ uint8_t grabbed_device,
+ uint8_t key,
+ uint8_t this_device_mode,
+ uint8_t other_device_mode,
+ uint8_t owner_events,
+ const xcb_input_event_class_t *classes);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_grab_device_key (xcb_connection_t *c,
+ xcb_window_t grab_window,
+ uint16_t num_classes,
+ uint16_t modifiers,
+ uint8_t modifier_device,
+ uint8_t grabbed_device,
+ uint8_t key,
+ uint8_t this_device_mode,
+ uint8_t other_device_mode,
+ uint8_t owner_events,
+ const xcb_input_event_class_t *classes);
+
+xcb_input_event_class_t *
+xcb_input_grab_device_key_classes (const xcb_input_grab_device_key_request_t *R);
+
+int
+xcb_input_grab_device_key_classes_length (const xcb_input_grab_device_key_request_t *R);
+
+xcb_generic_iterator_t
+xcb_input_grab_device_key_classes_end (const xcb_input_grab_device_key_request_t *R);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_ungrab_device_key_checked (xcb_connection_t *c,
+ xcb_window_t grabWindow,
+ uint16_t modifiers,
+ uint8_t modifier_device,
+ uint8_t key,
+ uint8_t grabbed_device);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_ungrab_device_key (xcb_connection_t *c,
+ xcb_window_t grabWindow,
+ uint16_t modifiers,
+ uint8_t modifier_device,
+ uint8_t key,
+ uint8_t grabbed_device);
+
+int
+xcb_input_grab_device_button_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_grab_device_button_checked (xcb_connection_t *c,
+ xcb_window_t grab_window,
+ uint8_t grabbed_device,
+ uint8_t modifier_device,
+ uint16_t num_classes,
+ uint16_t modifiers,
+ uint8_t this_device_mode,
+ uint8_t other_device_mode,
+ uint8_t button,
+ uint8_t owner_events,
+ const xcb_input_event_class_t *classes);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_grab_device_button (xcb_connection_t *c,
+ xcb_window_t grab_window,
+ uint8_t grabbed_device,
+ uint8_t modifier_device,
+ uint16_t num_classes,
+ uint16_t modifiers,
+ uint8_t this_device_mode,
+ uint8_t other_device_mode,
+ uint8_t button,
+ uint8_t owner_events,
+ const xcb_input_event_class_t *classes);
+
+xcb_input_event_class_t *
+xcb_input_grab_device_button_classes (const xcb_input_grab_device_button_request_t *R);
+
+int
+xcb_input_grab_device_button_classes_length (const xcb_input_grab_device_button_request_t *R);
+
+xcb_generic_iterator_t
+xcb_input_grab_device_button_classes_end (const xcb_input_grab_device_button_request_t *R);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_ungrab_device_button_checked (xcb_connection_t *c,
+ xcb_window_t grab_window,
+ uint16_t modifiers,
+ uint8_t modifier_device,
+ uint8_t button,
+ uint8_t grabbed_device);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_ungrab_device_button (xcb_connection_t *c,
+ xcb_window_t grab_window,
+ uint16_t modifiers,
+ uint8_t modifier_device,
+ uint8_t button,
+ uint8_t grabbed_device);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_allow_device_events_checked (xcb_connection_t *c,
+ xcb_timestamp_t time,
+ uint8_t mode,
+ uint8_t device_id);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_allow_device_events (xcb_connection_t *c,
+ xcb_timestamp_t time,
+ uint8_t mode,
+ uint8_t device_id);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_get_device_focus_cookie_t
+xcb_input_get_device_focus (xcb_connection_t *c,
+ uint8_t device_id);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_get_device_focus_cookie_t
+xcb_input_get_device_focus_unchecked (xcb_connection_t *c,
+ uint8_t device_id);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_get_device_focus_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_get_device_focus_reply_t *
+xcb_input_get_device_focus_reply (xcb_connection_t *c,
+ xcb_input_get_device_focus_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_set_device_focus_checked (xcb_connection_t *c,
+ xcb_window_t focus,
+ xcb_timestamp_t time,
+ uint8_t revert_to,
+ uint8_t device_id);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_set_device_focus (xcb_connection_t *c,
+ xcb_window_t focus,
+ xcb_timestamp_t time,
+ uint8_t revert_to,
+ uint8_t device_id);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_kbd_feedback_state_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_kbd_feedback_state_t)
+ */
+void
+xcb_input_kbd_feedback_state_next (xcb_input_kbd_feedback_state_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_kbd_feedback_state_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_kbd_feedback_state_end (xcb_input_kbd_feedback_state_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_ptr_feedback_state_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_ptr_feedback_state_t)
+ */
+void
+xcb_input_ptr_feedback_state_next (xcb_input_ptr_feedback_state_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_ptr_feedback_state_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_ptr_feedback_state_end (xcb_input_ptr_feedback_state_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_integer_feedback_state_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_integer_feedback_state_t)
+ */
+void
+xcb_input_integer_feedback_state_next (xcb_input_integer_feedback_state_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_integer_feedback_state_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_integer_feedback_state_end (xcb_input_integer_feedback_state_iterator_t i);
+
+int
+xcb_input_string_feedback_state_sizeof (const void *_buffer);
+
+xcb_keysym_t *
+xcb_input_string_feedback_state_keysyms (const xcb_input_string_feedback_state_t *R);
+
+int
+xcb_input_string_feedback_state_keysyms_length (const xcb_input_string_feedback_state_t *R);
+
+xcb_generic_iterator_t
+xcb_input_string_feedback_state_keysyms_end (const xcb_input_string_feedback_state_t *R);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_string_feedback_state_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_string_feedback_state_t)
+ */
+void
+xcb_input_string_feedback_state_next (xcb_input_string_feedback_state_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_string_feedback_state_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_string_feedback_state_end (xcb_input_string_feedback_state_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_bell_feedback_state_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_bell_feedback_state_t)
+ */
+void
+xcb_input_bell_feedback_state_next (xcb_input_bell_feedback_state_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_bell_feedback_state_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_bell_feedback_state_end (xcb_input_bell_feedback_state_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_led_feedback_state_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_led_feedback_state_t)
+ */
+void
+xcb_input_led_feedback_state_next (xcb_input_led_feedback_state_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_led_feedback_state_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_led_feedback_state_end (xcb_input_led_feedback_state_iterator_t i);
+
+xcb_keysym_t *
+xcb_input_feedback_state_data_string_keysyms (const xcb_input_feedback_state_data_t *S);
+
+int
+xcb_input_feedback_state_data_string_keysyms_length (const xcb_input_feedback_state_t *R,
+ const xcb_input_feedback_state_data_t *S);
+
+xcb_generic_iterator_t
+xcb_input_feedback_state_data_string_keysyms_end (const xcb_input_feedback_state_t *R,
+ const xcb_input_feedback_state_data_t *S);
+
+int
+xcb_input_feedback_state_data_serialize (void **_buffer,
+ uint8_t class_id,
+ const xcb_input_feedback_state_data_t *_aux);
+
+int
+xcb_input_feedback_state_data_unpack (const void *_buffer,
+ uint8_t class_id,
+ xcb_input_feedback_state_data_t *_aux);
+
+int
+xcb_input_feedback_state_data_sizeof (const void *_buffer,
+ uint8_t class_id);
+
+int
+xcb_input_feedback_state_sizeof (const void *_buffer);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_feedback_state_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_feedback_state_t)
+ */
+void
+xcb_input_feedback_state_next (xcb_input_feedback_state_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_feedback_state_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_feedback_state_end (xcb_input_feedback_state_iterator_t i);
+
+int
+xcb_input_get_feedback_control_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_get_feedback_control_cookie_t
+xcb_input_get_feedback_control (xcb_connection_t *c,
+ uint8_t device_id);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_get_feedback_control_cookie_t
+xcb_input_get_feedback_control_unchecked (xcb_connection_t *c,
+ uint8_t device_id);
+
+int
+xcb_input_get_feedback_control_feedbacks_length (const xcb_input_get_feedback_control_reply_t *R);
+
+xcb_input_feedback_state_iterator_t
+xcb_input_get_feedback_control_feedbacks_iterator (const xcb_input_get_feedback_control_reply_t *R);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_get_feedback_control_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_get_feedback_control_reply_t *
+xcb_input_get_feedback_control_reply (xcb_connection_t *c,
+ xcb_input_get_feedback_control_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_kbd_feedback_ctl_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_kbd_feedback_ctl_t)
+ */
+void
+xcb_input_kbd_feedback_ctl_next (xcb_input_kbd_feedback_ctl_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_kbd_feedback_ctl_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_kbd_feedback_ctl_end (xcb_input_kbd_feedback_ctl_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_ptr_feedback_ctl_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_ptr_feedback_ctl_t)
+ */
+void
+xcb_input_ptr_feedback_ctl_next (xcb_input_ptr_feedback_ctl_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_ptr_feedback_ctl_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_ptr_feedback_ctl_end (xcb_input_ptr_feedback_ctl_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_integer_feedback_ctl_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_integer_feedback_ctl_t)
+ */
+void
+xcb_input_integer_feedback_ctl_next (xcb_input_integer_feedback_ctl_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_integer_feedback_ctl_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_integer_feedback_ctl_end (xcb_input_integer_feedback_ctl_iterator_t i);
+
+int
+xcb_input_string_feedback_ctl_sizeof (const void *_buffer);
+
+xcb_keysym_t *
+xcb_input_string_feedback_ctl_keysyms (const xcb_input_string_feedback_ctl_t *R);
+
+int
+xcb_input_string_feedback_ctl_keysyms_length (const xcb_input_string_feedback_ctl_t *R);
+
+xcb_generic_iterator_t
+xcb_input_string_feedback_ctl_keysyms_end (const xcb_input_string_feedback_ctl_t *R);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_string_feedback_ctl_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_string_feedback_ctl_t)
+ */
+void
+xcb_input_string_feedback_ctl_next (xcb_input_string_feedback_ctl_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_string_feedback_ctl_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_string_feedback_ctl_end (xcb_input_string_feedback_ctl_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_bell_feedback_ctl_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_bell_feedback_ctl_t)
+ */
+void
+xcb_input_bell_feedback_ctl_next (xcb_input_bell_feedback_ctl_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_bell_feedback_ctl_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_bell_feedback_ctl_end (xcb_input_bell_feedback_ctl_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_led_feedback_ctl_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_led_feedback_ctl_t)
+ */
+void
+xcb_input_led_feedback_ctl_next (xcb_input_led_feedback_ctl_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_led_feedback_ctl_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_led_feedback_ctl_end (xcb_input_led_feedback_ctl_iterator_t i);
+
+xcb_keysym_t *
+xcb_input_feedback_ctl_data_string_keysyms (const xcb_input_feedback_ctl_data_t *S);
+
+int
+xcb_input_feedback_ctl_data_string_keysyms_length (const xcb_input_feedback_ctl_t *R,
+ const xcb_input_feedback_ctl_data_t *S);
+
+xcb_generic_iterator_t
+xcb_input_feedback_ctl_data_string_keysyms_end (const xcb_input_feedback_ctl_t *R,
+ const xcb_input_feedback_ctl_data_t *S);
+
+int
+xcb_input_feedback_ctl_data_serialize (void **_buffer,
+ uint8_t class_id,
+ const xcb_input_feedback_ctl_data_t *_aux);
+
+int
+xcb_input_feedback_ctl_data_unpack (const void *_buffer,
+ uint8_t class_id,
+ xcb_input_feedback_ctl_data_t *_aux);
+
+int
+xcb_input_feedback_ctl_data_sizeof (const void *_buffer,
+ uint8_t class_id);
+
+int
+xcb_input_feedback_ctl_sizeof (const void *_buffer);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_feedback_ctl_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_feedback_ctl_t)
+ */
+void
+xcb_input_feedback_ctl_next (xcb_input_feedback_ctl_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_feedback_ctl_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_feedback_ctl_end (xcb_input_feedback_ctl_iterator_t i);
+
+int
+xcb_input_change_feedback_control_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_change_feedback_control_checked (xcb_connection_t *c,
+ uint32_t mask,
+ uint8_t device_id,
+ uint8_t feedback_id,
+ xcb_input_feedback_ctl_t *feedback);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_change_feedback_control (xcb_connection_t *c,
+ uint32_t mask,
+ uint8_t device_id,
+ uint8_t feedback_id,
+ xcb_input_feedback_ctl_t *feedback);
+
+xcb_input_feedback_ctl_t *
+xcb_input_change_feedback_control_feedback (const xcb_input_change_feedback_control_request_t *R);
+
+int
+xcb_input_get_device_key_mapping_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_get_device_key_mapping_cookie_t
+xcb_input_get_device_key_mapping (xcb_connection_t *c,
+ uint8_t device_id,
+ xcb_input_key_code_t first_keycode,
+ uint8_t count);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_get_device_key_mapping_cookie_t
+xcb_input_get_device_key_mapping_unchecked (xcb_connection_t *c,
+ uint8_t device_id,
+ xcb_input_key_code_t first_keycode,
+ uint8_t count);
+
+xcb_keysym_t *
+xcb_input_get_device_key_mapping_keysyms (const xcb_input_get_device_key_mapping_reply_t *R);
+
+int
+xcb_input_get_device_key_mapping_keysyms_length (const xcb_input_get_device_key_mapping_reply_t *R);
+
+xcb_generic_iterator_t
+xcb_input_get_device_key_mapping_keysyms_end (const xcb_input_get_device_key_mapping_reply_t *R);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_get_device_key_mapping_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_get_device_key_mapping_reply_t *
+xcb_input_get_device_key_mapping_reply (xcb_connection_t *c,
+ xcb_input_get_device_key_mapping_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+int
+xcb_input_change_device_key_mapping_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_change_device_key_mapping_checked (xcb_connection_t *c,
+ uint8_t device_id,
+ xcb_input_key_code_t first_keycode,
+ uint8_t keysyms_per_keycode,
+ uint8_t keycode_count,
+ const xcb_keysym_t *keysyms);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_change_device_key_mapping (xcb_connection_t *c,
+ uint8_t device_id,
+ xcb_input_key_code_t first_keycode,
+ uint8_t keysyms_per_keycode,
+ uint8_t keycode_count,
+ const xcb_keysym_t *keysyms);
+
+xcb_keysym_t *
+xcb_input_change_device_key_mapping_keysyms (const xcb_input_change_device_key_mapping_request_t *R);
+
+int
+xcb_input_change_device_key_mapping_keysyms_length (const xcb_input_change_device_key_mapping_request_t *R);
+
+xcb_generic_iterator_t
+xcb_input_change_device_key_mapping_keysyms_end (const xcb_input_change_device_key_mapping_request_t *R);
+
+int
+xcb_input_get_device_modifier_mapping_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_get_device_modifier_mapping_cookie_t
+xcb_input_get_device_modifier_mapping (xcb_connection_t *c,
+ uint8_t device_id);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_get_device_modifier_mapping_cookie_t
+xcb_input_get_device_modifier_mapping_unchecked (xcb_connection_t *c,
+ uint8_t device_id);
+
+uint8_t *
+xcb_input_get_device_modifier_mapping_keymaps (const xcb_input_get_device_modifier_mapping_reply_t *R);
+
+int
+xcb_input_get_device_modifier_mapping_keymaps_length (const xcb_input_get_device_modifier_mapping_reply_t *R);
+
+xcb_generic_iterator_t
+xcb_input_get_device_modifier_mapping_keymaps_end (const xcb_input_get_device_modifier_mapping_reply_t *R);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_get_device_modifier_mapping_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_get_device_modifier_mapping_reply_t *
+xcb_input_get_device_modifier_mapping_reply (xcb_connection_t *c,
+ xcb_input_get_device_modifier_mapping_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+int
+xcb_input_set_device_modifier_mapping_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_set_device_modifier_mapping_cookie_t
+xcb_input_set_device_modifier_mapping (xcb_connection_t *c,
+ uint8_t device_id,
+ uint8_t keycodes_per_modifier,
+ const uint8_t *keymaps);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_set_device_modifier_mapping_cookie_t
+xcb_input_set_device_modifier_mapping_unchecked (xcb_connection_t *c,
+ uint8_t device_id,
+ uint8_t keycodes_per_modifier,
+ const uint8_t *keymaps);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_set_device_modifier_mapping_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_set_device_modifier_mapping_reply_t *
+xcb_input_set_device_modifier_mapping_reply (xcb_connection_t *c,
+ xcb_input_set_device_modifier_mapping_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+int
+xcb_input_get_device_button_mapping_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_get_device_button_mapping_cookie_t
+xcb_input_get_device_button_mapping (xcb_connection_t *c,
+ uint8_t device_id);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_get_device_button_mapping_cookie_t
+xcb_input_get_device_button_mapping_unchecked (xcb_connection_t *c,
+ uint8_t device_id);
+
+uint8_t *
+xcb_input_get_device_button_mapping_map (const xcb_input_get_device_button_mapping_reply_t *R);
+
+int
+xcb_input_get_device_button_mapping_map_length (const xcb_input_get_device_button_mapping_reply_t *R);
+
+xcb_generic_iterator_t
+xcb_input_get_device_button_mapping_map_end (const xcb_input_get_device_button_mapping_reply_t *R);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_get_device_button_mapping_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_get_device_button_mapping_reply_t *
+xcb_input_get_device_button_mapping_reply (xcb_connection_t *c,
+ xcb_input_get_device_button_mapping_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+int
+xcb_input_set_device_button_mapping_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_set_device_button_mapping_cookie_t
+xcb_input_set_device_button_mapping (xcb_connection_t *c,
+ uint8_t device_id,
+ uint8_t map_size,
+ const uint8_t *map);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_set_device_button_mapping_cookie_t
+xcb_input_set_device_button_mapping_unchecked (xcb_connection_t *c,
+ uint8_t device_id,
+ uint8_t map_size,
+ const uint8_t *map);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_set_device_button_mapping_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_set_device_button_mapping_reply_t *
+xcb_input_set_device_button_mapping_reply (xcb_connection_t *c,
+ xcb_input_set_device_button_mapping_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_key_state_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_key_state_t)
+ */
+void
+xcb_input_key_state_next (xcb_input_key_state_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_key_state_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_key_state_end (xcb_input_key_state_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_button_state_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_button_state_t)
+ */
+void
+xcb_input_button_state_next (xcb_input_button_state_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_button_state_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_button_state_end (xcb_input_button_state_iterator_t i);
+
+int
+xcb_input_valuator_state_sizeof (const void *_buffer);
+
+int32_t *
+xcb_input_valuator_state_valuators (const xcb_input_valuator_state_t *R);
+
+int
+xcb_input_valuator_state_valuators_length (const xcb_input_valuator_state_t *R);
+
+xcb_generic_iterator_t
+xcb_input_valuator_state_valuators_end (const xcb_input_valuator_state_t *R);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_valuator_state_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_valuator_state_t)
+ */
+void
+xcb_input_valuator_state_next (xcb_input_valuator_state_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_valuator_state_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_valuator_state_end (xcb_input_valuator_state_iterator_t i);
+
+int32_t *
+xcb_input_input_state_data_valuator_valuators (const xcb_input_input_state_data_t *S);
+
+int
+xcb_input_input_state_data_valuator_valuators_length (const xcb_input_input_state_t *R,
+ const xcb_input_input_state_data_t *S);
+
+xcb_generic_iterator_t
+xcb_input_input_state_data_valuator_valuators_end (const xcb_input_input_state_t *R,
+ const xcb_input_input_state_data_t *S);
+
+int
+xcb_input_input_state_data_serialize (void **_buffer,
+ uint8_t class_id,
+ const xcb_input_input_state_data_t *_aux);
+
+int
+xcb_input_input_state_data_unpack (const void *_buffer,
+ uint8_t class_id,
+ xcb_input_input_state_data_t *_aux);
+
+int
+xcb_input_input_state_data_sizeof (const void *_buffer,
+ uint8_t class_id);
+
+int
+xcb_input_input_state_sizeof (const void *_buffer);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_input_state_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_input_state_t)
+ */
+void
+xcb_input_input_state_next (xcb_input_input_state_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_input_state_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_input_state_end (xcb_input_input_state_iterator_t i);
+
+int
+xcb_input_query_device_state_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_query_device_state_cookie_t
+xcb_input_query_device_state (xcb_connection_t *c,
+ uint8_t device_id);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_query_device_state_cookie_t
+xcb_input_query_device_state_unchecked (xcb_connection_t *c,
+ uint8_t device_id);
+
+int
+xcb_input_query_device_state_classes_length (const xcb_input_query_device_state_reply_t *R);
+
+xcb_input_input_state_iterator_t
+xcb_input_query_device_state_classes_iterator (const xcb_input_query_device_state_reply_t *R);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_query_device_state_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_query_device_state_reply_t *
+xcb_input_query_device_state_reply (xcb_connection_t *c,
+ xcb_input_query_device_state_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_device_bell_checked (xcb_connection_t *c,
+ uint8_t device_id,
+ uint8_t feedback_id,
+ uint8_t feedback_class,
+ int8_t percent);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_device_bell (xcb_connection_t *c,
+ uint8_t device_id,
+ uint8_t feedback_id,
+ uint8_t feedback_class,
+ int8_t percent);
+
+int
+xcb_input_set_device_valuators_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_set_device_valuators_cookie_t
+xcb_input_set_device_valuators (xcb_connection_t *c,
+ uint8_t device_id,
+ uint8_t first_valuator,
+ uint8_t num_valuators,
+ const int32_t *valuators);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_set_device_valuators_cookie_t
+xcb_input_set_device_valuators_unchecked (xcb_connection_t *c,
+ uint8_t device_id,
+ uint8_t first_valuator,
+ uint8_t num_valuators,
+ const int32_t *valuators);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_set_device_valuators_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_set_device_valuators_reply_t *
+xcb_input_set_device_valuators_reply (xcb_connection_t *c,
+ xcb_input_set_device_valuators_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+int
+xcb_input_device_resolution_state_sizeof (const void *_buffer);
+
+uint32_t *
+xcb_input_device_resolution_state_resolution_values (const xcb_input_device_resolution_state_t *R);
+
+int
+xcb_input_device_resolution_state_resolution_values_length (const xcb_input_device_resolution_state_t *R);
+
+xcb_generic_iterator_t
+xcb_input_device_resolution_state_resolution_values_end (const xcb_input_device_resolution_state_t *R);
+
+uint32_t *
+xcb_input_device_resolution_state_resolution_min (const xcb_input_device_resolution_state_t *R);
+
+int
+xcb_input_device_resolution_state_resolution_min_length (const xcb_input_device_resolution_state_t *R);
+
+xcb_generic_iterator_t
+xcb_input_device_resolution_state_resolution_min_end (const xcb_input_device_resolution_state_t *R);
+
+uint32_t *
+xcb_input_device_resolution_state_resolution_max (const xcb_input_device_resolution_state_t *R);
+
+int
+xcb_input_device_resolution_state_resolution_max_length (const xcb_input_device_resolution_state_t *R);
+
+xcb_generic_iterator_t
+xcb_input_device_resolution_state_resolution_max_end (const xcb_input_device_resolution_state_t *R);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_device_resolution_state_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_device_resolution_state_t)
+ */
+void
+xcb_input_device_resolution_state_next (xcb_input_device_resolution_state_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_device_resolution_state_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_device_resolution_state_end (xcb_input_device_resolution_state_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_device_abs_calib_state_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_device_abs_calib_state_t)
+ */
+void
+xcb_input_device_abs_calib_state_next (xcb_input_device_abs_calib_state_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_device_abs_calib_state_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_device_abs_calib_state_end (xcb_input_device_abs_calib_state_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_device_abs_area_state_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_device_abs_area_state_t)
+ */
+void
+xcb_input_device_abs_area_state_next (xcb_input_device_abs_area_state_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_device_abs_area_state_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_device_abs_area_state_end (xcb_input_device_abs_area_state_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_device_core_state_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_device_core_state_t)
+ */
+void
+xcb_input_device_core_state_next (xcb_input_device_core_state_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_device_core_state_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_device_core_state_end (xcb_input_device_core_state_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_device_enable_state_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_device_enable_state_t)
+ */
+void
+xcb_input_device_enable_state_next (xcb_input_device_enable_state_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_device_enable_state_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_device_enable_state_end (xcb_input_device_enable_state_iterator_t i);
+
+uint32_t *
+xcb_input_device_state_data_resolution_resolution_values (const xcb_input_device_state_data_t *S);
+
+int
+xcb_input_device_state_data_resolution_resolution_values_length (const xcb_input_device_state_t *R,
+ const xcb_input_device_state_data_t *S);
+
+xcb_generic_iterator_t
+xcb_input_device_state_data_resolution_resolution_values_end (const xcb_input_device_state_t *R,
+ const xcb_input_device_state_data_t *S);
+
+uint32_t *
+xcb_input_device_state_data_resolution_resolution_min (const xcb_input_device_state_data_t *S);
+
+int
+xcb_input_device_state_data_resolution_resolution_min_length (const xcb_input_device_state_t *R,
+ const xcb_input_device_state_data_t *S);
+
+xcb_generic_iterator_t
+xcb_input_device_state_data_resolution_resolution_min_end (const xcb_input_device_state_t *R,
+ const xcb_input_device_state_data_t *S);
+
+uint32_t *
+xcb_input_device_state_data_resolution_resolution_max (const xcb_input_device_state_data_t *S);
+
+int
+xcb_input_device_state_data_resolution_resolution_max_length (const xcb_input_device_state_t *R,
+ const xcb_input_device_state_data_t *S);
+
+xcb_generic_iterator_t
+xcb_input_device_state_data_resolution_resolution_max_end (const xcb_input_device_state_t *R,
+ const xcb_input_device_state_data_t *S);
+
+int
+xcb_input_device_state_data_serialize (void **_buffer,
+ uint16_t control_id,
+ const xcb_input_device_state_data_t *_aux);
+
+int
+xcb_input_device_state_data_unpack (const void *_buffer,
+ uint16_t control_id,
+ xcb_input_device_state_data_t *_aux);
+
+int
+xcb_input_device_state_data_sizeof (const void *_buffer,
+ uint16_t control_id);
+
+int
+xcb_input_device_state_sizeof (const void *_buffer);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_device_state_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_device_state_t)
+ */
+void
+xcb_input_device_state_next (xcb_input_device_state_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_device_state_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_device_state_end (xcb_input_device_state_iterator_t i);
+
+int
+xcb_input_get_device_control_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_get_device_control_cookie_t
+xcb_input_get_device_control (xcb_connection_t *c,
+ uint16_t control_id,
+ uint8_t device_id);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_get_device_control_cookie_t
+xcb_input_get_device_control_unchecked (xcb_connection_t *c,
+ uint16_t control_id,
+ uint8_t device_id);
+
+xcb_input_device_state_t *
+xcb_input_get_device_control_control (const xcb_input_get_device_control_reply_t *R);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_get_device_control_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_get_device_control_reply_t *
+xcb_input_get_device_control_reply (xcb_connection_t *c,
+ xcb_input_get_device_control_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+int
+xcb_input_device_resolution_ctl_sizeof (const void *_buffer);
+
+uint32_t *
+xcb_input_device_resolution_ctl_resolution_values (const xcb_input_device_resolution_ctl_t *R);
+
+int
+xcb_input_device_resolution_ctl_resolution_values_length (const xcb_input_device_resolution_ctl_t *R);
+
+xcb_generic_iterator_t
+xcb_input_device_resolution_ctl_resolution_values_end (const xcb_input_device_resolution_ctl_t *R);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_device_resolution_ctl_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_device_resolution_ctl_t)
+ */
+void
+xcb_input_device_resolution_ctl_next (xcb_input_device_resolution_ctl_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_device_resolution_ctl_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_device_resolution_ctl_end (xcb_input_device_resolution_ctl_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_device_abs_calib_ctl_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_device_abs_calib_ctl_t)
+ */
+void
+xcb_input_device_abs_calib_ctl_next (xcb_input_device_abs_calib_ctl_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_device_abs_calib_ctl_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_device_abs_calib_ctl_end (xcb_input_device_abs_calib_ctl_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_device_abs_area_ctrl_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_device_abs_area_ctrl_t)
+ */
+void
+xcb_input_device_abs_area_ctrl_next (xcb_input_device_abs_area_ctrl_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_device_abs_area_ctrl_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_device_abs_area_ctrl_end (xcb_input_device_abs_area_ctrl_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_device_core_ctrl_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_device_core_ctrl_t)
+ */
+void
+xcb_input_device_core_ctrl_next (xcb_input_device_core_ctrl_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_device_core_ctrl_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_device_core_ctrl_end (xcb_input_device_core_ctrl_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_device_enable_ctrl_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_device_enable_ctrl_t)
+ */
+void
+xcb_input_device_enable_ctrl_next (xcb_input_device_enable_ctrl_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_device_enable_ctrl_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_device_enable_ctrl_end (xcb_input_device_enable_ctrl_iterator_t i);
+
+uint32_t *
+xcb_input_device_ctl_data_resolution_resolution_values (const xcb_input_device_ctl_data_t *S);
+
+int
+xcb_input_device_ctl_data_resolution_resolution_values_length (const xcb_input_device_ctl_t *R,
+ const xcb_input_device_ctl_data_t *S);
+
+xcb_generic_iterator_t
+xcb_input_device_ctl_data_resolution_resolution_values_end (const xcb_input_device_ctl_t *R,
+ const xcb_input_device_ctl_data_t *S);
+
+int
+xcb_input_device_ctl_data_serialize (void **_buffer,
+ uint16_t control_id,
+ const xcb_input_device_ctl_data_t *_aux);
+
+int
+xcb_input_device_ctl_data_unpack (const void *_buffer,
+ uint16_t control_id,
+ xcb_input_device_ctl_data_t *_aux);
+
+int
+xcb_input_device_ctl_data_sizeof (const void *_buffer,
+ uint16_t control_id);
+
+int
+xcb_input_device_ctl_sizeof (const void *_buffer);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_device_ctl_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_device_ctl_t)
+ */
+void
+xcb_input_device_ctl_next (xcb_input_device_ctl_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_device_ctl_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_device_ctl_end (xcb_input_device_ctl_iterator_t i);
+
+int
+xcb_input_change_device_control_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_change_device_control_cookie_t
+xcb_input_change_device_control (xcb_connection_t *c,
+ uint16_t control_id,
+ uint8_t device_id,
+ xcb_input_device_ctl_t *control);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_change_device_control_cookie_t
+xcb_input_change_device_control_unchecked (xcb_connection_t *c,
+ uint16_t control_id,
+ uint8_t device_id,
+ xcb_input_device_ctl_t *control);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_change_device_control_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_change_device_control_reply_t *
+xcb_input_change_device_control_reply (xcb_connection_t *c,
+ xcb_input_change_device_control_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+int
+xcb_input_list_device_properties_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_list_device_properties_cookie_t
+xcb_input_list_device_properties (xcb_connection_t *c,
+ uint8_t device_id);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_list_device_properties_cookie_t
+xcb_input_list_device_properties_unchecked (xcb_connection_t *c,
+ uint8_t device_id);
+
+xcb_atom_t *
+xcb_input_list_device_properties_atoms (const xcb_input_list_device_properties_reply_t *R);
+
+int
+xcb_input_list_device_properties_atoms_length (const xcb_input_list_device_properties_reply_t *R);
+
+xcb_generic_iterator_t
+xcb_input_list_device_properties_atoms_end (const xcb_input_list_device_properties_reply_t *R);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_list_device_properties_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_list_device_properties_reply_t *
+xcb_input_list_device_properties_reply (xcb_connection_t *c,
+ xcb_input_list_device_properties_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+uint8_t *
+xcb_input_change_device_property_items_data_8 (const xcb_input_change_device_property_items_t *S);
+
+int
+xcb_input_change_device_property_items_data_8_length (const xcb_input_change_device_property_request_t *R,
+ const xcb_input_change_device_property_items_t *S);
+
+xcb_generic_iterator_t
+xcb_input_change_device_property_items_data_8_end (const xcb_input_change_device_property_request_t *R,
+ const xcb_input_change_device_property_items_t *S);
+
+uint16_t *
+xcb_input_change_device_property_items_data_16 (const xcb_input_change_device_property_items_t *S);
+
+int
+xcb_input_change_device_property_items_data_16_length (const xcb_input_change_device_property_request_t *R,
+ const xcb_input_change_device_property_items_t *S);
+
+xcb_generic_iterator_t
+xcb_input_change_device_property_items_data_16_end (const xcb_input_change_device_property_request_t *R,
+ const xcb_input_change_device_property_items_t *S);
+
+uint32_t *
+xcb_input_change_device_property_items_data_32 (const xcb_input_change_device_property_items_t *S);
+
+int
+xcb_input_change_device_property_items_data_32_length (const xcb_input_change_device_property_request_t *R,
+ const xcb_input_change_device_property_items_t *S);
+
+xcb_generic_iterator_t
+xcb_input_change_device_property_items_data_32_end (const xcb_input_change_device_property_request_t *R,
+ const xcb_input_change_device_property_items_t *S);
+
+int
+xcb_input_change_device_property_items_serialize (void **_buffer,
+ uint32_t num_items,
+ uint8_t format,
+ const xcb_input_change_device_property_items_t *_aux);
+
+int
+xcb_input_change_device_property_items_unpack (const void *_buffer,
+ uint32_t num_items,
+ uint8_t format,
+ xcb_input_change_device_property_items_t *_aux);
+
+int
+xcb_input_change_device_property_items_sizeof (const void *_buffer,
+ uint32_t num_items,
+ uint8_t format);
+
+int
+xcb_input_change_device_property_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_change_device_property_checked (xcb_connection_t *c,
+ xcb_atom_t property,
+ xcb_atom_t type,
+ uint8_t device_id,
+ uint8_t format,
+ uint8_t mode,
+ uint32_t num_items,
+ const void *items);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_change_device_property (xcb_connection_t *c,
+ xcb_atom_t property,
+ xcb_atom_t type,
+ uint8_t device_id,
+ uint8_t format,
+ uint8_t mode,
+ uint32_t num_items,
+ const void *items);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_change_device_property_aux_checked (xcb_connection_t *c,
+ xcb_atom_t property,
+ xcb_atom_t type,
+ uint8_t device_id,
+ uint8_t format,
+ uint8_t mode,
+ uint32_t num_items,
+ const xcb_input_change_device_property_items_t *items);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_change_device_property_aux (xcb_connection_t *c,
+ xcb_atom_t property,
+ xcb_atom_t type,
+ uint8_t device_id,
+ uint8_t format,
+ uint8_t mode,
+ uint32_t num_items,
+ const xcb_input_change_device_property_items_t *items);
+
+void *
+xcb_input_change_device_property_items (const xcb_input_change_device_property_request_t *R);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_delete_device_property_checked (xcb_connection_t *c,
+ xcb_atom_t property,
+ uint8_t device_id);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_delete_device_property (xcb_connection_t *c,
+ xcb_atom_t property,
+ uint8_t device_id);
+
+uint8_t *
+xcb_input_get_device_property_items_data_8 (const xcb_input_get_device_property_items_t *S);
+
+int
+xcb_input_get_device_property_items_data_8_length (const xcb_input_get_device_property_reply_t *R,
+ const xcb_input_get_device_property_items_t *S);
+
+xcb_generic_iterator_t
+xcb_input_get_device_property_items_data_8_end (const xcb_input_get_device_property_reply_t *R,
+ const xcb_input_get_device_property_items_t *S);
+
+uint16_t *
+xcb_input_get_device_property_items_data_16 (const xcb_input_get_device_property_items_t *S);
+
+int
+xcb_input_get_device_property_items_data_16_length (const xcb_input_get_device_property_reply_t *R,
+ const xcb_input_get_device_property_items_t *S);
+
+xcb_generic_iterator_t
+xcb_input_get_device_property_items_data_16_end (const xcb_input_get_device_property_reply_t *R,
+ const xcb_input_get_device_property_items_t *S);
+
+uint32_t *
+xcb_input_get_device_property_items_data_32 (const xcb_input_get_device_property_items_t *S);
+
+int
+xcb_input_get_device_property_items_data_32_length (const xcb_input_get_device_property_reply_t *R,
+ const xcb_input_get_device_property_items_t *S);
+
+xcb_generic_iterator_t
+xcb_input_get_device_property_items_data_32_end (const xcb_input_get_device_property_reply_t *R,
+ const xcb_input_get_device_property_items_t *S);
+
+int
+xcb_input_get_device_property_items_serialize (void **_buffer,
+ uint32_t num_items,
+ uint8_t format,
+ const xcb_input_get_device_property_items_t *_aux);
+
+int
+xcb_input_get_device_property_items_unpack (const void *_buffer,
+ uint32_t num_items,
+ uint8_t format,
+ xcb_input_get_device_property_items_t *_aux);
+
+int
+xcb_input_get_device_property_items_sizeof (const void *_buffer,
+ uint32_t num_items,
+ uint8_t format);
+
+int
+xcb_input_get_device_property_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_get_device_property_cookie_t
+xcb_input_get_device_property (xcb_connection_t *c,
+ xcb_atom_t property,
+ xcb_atom_t type,
+ uint32_t offset,
+ uint32_t len,
+ uint8_t device_id,
+ uint8_t _delete);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_get_device_property_cookie_t
+xcb_input_get_device_property_unchecked (xcb_connection_t *c,
+ xcb_atom_t property,
+ xcb_atom_t type,
+ uint32_t offset,
+ uint32_t len,
+ uint8_t device_id,
+ uint8_t _delete);
+
+void *
+xcb_input_get_device_property_items (const xcb_input_get_device_property_reply_t *R);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_get_device_property_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_get_device_property_reply_t *
+xcb_input_get_device_property_reply (xcb_connection_t *c,
+ xcb_input_get_device_property_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_group_info_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_group_info_t)
+ */
+void
+xcb_input_group_info_next (xcb_input_group_info_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_group_info_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_group_info_end (xcb_input_group_info_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_modifier_info_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_modifier_info_t)
+ */
+void
+xcb_input_modifier_info_next (xcb_input_modifier_info_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_modifier_info_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_modifier_info_end (xcb_input_modifier_info_iterator_t i);
+
+int
+xcb_input_xi_query_pointer_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_xi_query_pointer_cookie_t
+xcb_input_xi_query_pointer (xcb_connection_t *c,
+ xcb_window_t window,
+ xcb_input_device_id_t deviceid);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_xi_query_pointer_cookie_t
+xcb_input_xi_query_pointer_unchecked (xcb_connection_t *c,
+ xcb_window_t window,
+ xcb_input_device_id_t deviceid);
+
+uint32_t *
+xcb_input_xi_query_pointer_buttons (const xcb_input_xi_query_pointer_reply_t *R);
+
+int
+xcb_input_xi_query_pointer_buttons_length (const xcb_input_xi_query_pointer_reply_t *R);
+
+xcb_generic_iterator_t
+xcb_input_xi_query_pointer_buttons_end (const xcb_input_xi_query_pointer_reply_t *R);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_xi_query_pointer_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_xi_query_pointer_reply_t *
+xcb_input_xi_query_pointer_reply (xcb_connection_t *c,
+ xcb_input_xi_query_pointer_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_xi_warp_pointer_checked (xcb_connection_t *c,
+ xcb_window_t src_win,
+ xcb_window_t dst_win,
+ xcb_input_fp1616_t src_x,
+ xcb_input_fp1616_t src_y,
+ uint16_t src_width,
+ uint16_t src_height,
+ xcb_input_fp1616_t dst_x,
+ xcb_input_fp1616_t dst_y,
+ xcb_input_device_id_t deviceid);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_xi_warp_pointer (xcb_connection_t *c,
+ xcb_window_t src_win,
+ xcb_window_t dst_win,
+ xcb_input_fp1616_t src_x,
+ xcb_input_fp1616_t src_y,
+ uint16_t src_width,
+ uint16_t src_height,
+ xcb_input_fp1616_t dst_x,
+ xcb_input_fp1616_t dst_y,
+ xcb_input_device_id_t deviceid);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_xi_change_cursor_checked (xcb_connection_t *c,
+ xcb_window_t window,
+ xcb_cursor_t cursor,
+ xcb_input_device_id_t deviceid);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_xi_change_cursor (xcb_connection_t *c,
+ xcb_window_t window,
+ xcb_cursor_t cursor,
+ xcb_input_device_id_t deviceid);
+
+int
+xcb_input_add_master_sizeof (const void *_buffer);
+
+char *
+xcb_input_add_master_name (const xcb_input_add_master_t *R);
+
+int
+xcb_input_add_master_name_length (const xcb_input_add_master_t *R);
+
+xcb_generic_iterator_t
+xcb_input_add_master_name_end (const xcb_input_add_master_t *R);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_add_master_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_add_master_t)
+ */
+void
+xcb_input_add_master_next (xcb_input_add_master_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_add_master_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_add_master_end (xcb_input_add_master_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_remove_master_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_remove_master_t)
+ */
+void
+xcb_input_remove_master_next (xcb_input_remove_master_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_remove_master_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_remove_master_end (xcb_input_remove_master_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_attach_slave_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_attach_slave_t)
+ */
+void
+xcb_input_attach_slave_next (xcb_input_attach_slave_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_attach_slave_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_attach_slave_end (xcb_input_attach_slave_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_detach_slave_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_detach_slave_t)
+ */
+void
+xcb_input_detach_slave_next (xcb_input_detach_slave_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_detach_slave_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_detach_slave_end (xcb_input_detach_slave_iterator_t i);
+
+char *
+xcb_input_hierarchy_change_data_add_master_name (const xcb_input_hierarchy_change_data_t *S);
+
+int
+xcb_input_hierarchy_change_data_add_master_name_length (const xcb_input_hierarchy_change_t *R,
+ const xcb_input_hierarchy_change_data_t *S);
+
+xcb_generic_iterator_t
+xcb_input_hierarchy_change_data_add_master_name_end (const xcb_input_hierarchy_change_t *R,
+ const xcb_input_hierarchy_change_data_t *S);
+
+int
+xcb_input_hierarchy_change_data_serialize (void **_buffer,
+ uint16_t type,
+ const xcb_input_hierarchy_change_data_t *_aux);
+
+int
+xcb_input_hierarchy_change_data_unpack (const void *_buffer,
+ uint16_t type,
+ xcb_input_hierarchy_change_data_t *_aux);
+
+int
+xcb_input_hierarchy_change_data_sizeof (const void *_buffer,
+ uint16_t type);
+
+int
+xcb_input_hierarchy_change_sizeof (const void *_buffer);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_hierarchy_change_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_hierarchy_change_t)
+ */
+void
+xcb_input_hierarchy_change_next (xcb_input_hierarchy_change_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_hierarchy_change_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_hierarchy_change_end (xcb_input_hierarchy_change_iterator_t i);
+
+int
+xcb_input_xi_change_hierarchy_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_xi_change_hierarchy_checked (xcb_connection_t *c,
+ uint8_t num_changes,
+ const xcb_input_hierarchy_change_t *changes);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_xi_change_hierarchy (xcb_connection_t *c,
+ uint8_t num_changes,
+ const xcb_input_hierarchy_change_t *changes);
+
+int
+xcb_input_xi_change_hierarchy_changes_length (const xcb_input_xi_change_hierarchy_request_t *R);
+
+xcb_input_hierarchy_change_iterator_t
+xcb_input_xi_change_hierarchy_changes_iterator (const xcb_input_xi_change_hierarchy_request_t *R);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_xi_set_client_pointer_checked (xcb_connection_t *c,
+ xcb_window_t window,
+ xcb_input_device_id_t deviceid);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_xi_set_client_pointer (xcb_connection_t *c,
+ xcb_window_t window,
+ xcb_input_device_id_t deviceid);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_xi_get_client_pointer_cookie_t
+xcb_input_xi_get_client_pointer (xcb_connection_t *c,
+ xcb_window_t window);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_xi_get_client_pointer_cookie_t
+xcb_input_xi_get_client_pointer_unchecked (xcb_connection_t *c,
+ xcb_window_t window);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_xi_get_client_pointer_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_xi_get_client_pointer_reply_t *
+xcb_input_xi_get_client_pointer_reply (xcb_connection_t *c,
+ xcb_input_xi_get_client_pointer_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+int
+xcb_input_event_mask_sizeof (const void *_buffer);
+
+uint32_t *
+xcb_input_event_mask_mask (const xcb_input_event_mask_t *R);
+
+int
+xcb_input_event_mask_mask_length (const xcb_input_event_mask_t *R);
+
+xcb_generic_iterator_t
+xcb_input_event_mask_mask_end (const xcb_input_event_mask_t *R);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_event_mask_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_event_mask_t)
+ */
+void
+xcb_input_event_mask_next (xcb_input_event_mask_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_event_mask_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_event_mask_end (xcb_input_event_mask_iterator_t i);
+
+int
+xcb_input_xi_select_events_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_xi_select_events_checked (xcb_connection_t *c,
+ xcb_window_t window,
+ uint16_t num_mask,
+ const xcb_input_event_mask_t *masks);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_xi_select_events (xcb_connection_t *c,
+ xcb_window_t window,
+ uint16_t num_mask,
+ const xcb_input_event_mask_t *masks);
+
+int
+xcb_input_xi_select_events_masks_length (const xcb_input_xi_select_events_request_t *R);
+
+xcb_input_event_mask_iterator_t
+xcb_input_xi_select_events_masks_iterator (const xcb_input_xi_select_events_request_t *R);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_xi_query_version_cookie_t
+xcb_input_xi_query_version (xcb_connection_t *c,
+ uint16_t major_version,
+ uint16_t minor_version);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_xi_query_version_cookie_t
+xcb_input_xi_query_version_unchecked (xcb_connection_t *c,
+ uint16_t major_version,
+ uint16_t minor_version);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_xi_query_version_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_xi_query_version_reply_t *
+xcb_input_xi_query_version_reply (xcb_connection_t *c,
+ xcb_input_xi_query_version_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+int
+xcb_input_button_class_sizeof (const void *_buffer);
+
+uint32_t *
+xcb_input_button_class_state (const xcb_input_button_class_t *R);
+
+int
+xcb_input_button_class_state_length (const xcb_input_button_class_t *R);
+
+xcb_generic_iterator_t
+xcb_input_button_class_state_end (const xcb_input_button_class_t *R);
+
+xcb_atom_t *
+xcb_input_button_class_labels (const xcb_input_button_class_t *R);
+
+int
+xcb_input_button_class_labels_length (const xcb_input_button_class_t *R);
+
+xcb_generic_iterator_t
+xcb_input_button_class_labels_end (const xcb_input_button_class_t *R);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_button_class_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_button_class_t)
+ */
+void
+xcb_input_button_class_next (xcb_input_button_class_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_button_class_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_button_class_end (xcb_input_button_class_iterator_t i);
+
+int
+xcb_input_key_class_sizeof (const void *_buffer);
+
+uint32_t *
+xcb_input_key_class_keys (const xcb_input_key_class_t *R);
+
+int
+xcb_input_key_class_keys_length (const xcb_input_key_class_t *R);
+
+xcb_generic_iterator_t
+xcb_input_key_class_keys_end (const xcb_input_key_class_t *R);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_key_class_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_key_class_t)
+ */
+void
+xcb_input_key_class_next (xcb_input_key_class_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_key_class_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_key_class_end (xcb_input_key_class_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_scroll_class_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_scroll_class_t)
+ */
+void
+xcb_input_scroll_class_next (xcb_input_scroll_class_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_scroll_class_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_scroll_class_end (xcb_input_scroll_class_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_touch_class_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_touch_class_t)
+ */
+void
+xcb_input_touch_class_next (xcb_input_touch_class_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_touch_class_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_touch_class_end (xcb_input_touch_class_iterator_t i);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_valuator_class_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_valuator_class_t)
+ */
+void
+xcb_input_valuator_class_next (xcb_input_valuator_class_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_valuator_class_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_valuator_class_end (xcb_input_valuator_class_iterator_t i);
+
+uint32_t *
+xcb_input_device_class_data_key_keys (const xcb_input_device_class_data_t *S);
+
+int
+xcb_input_device_class_data_key_keys_length (const xcb_input_device_class_t *R,
+ const xcb_input_device_class_data_t *S);
+
+xcb_generic_iterator_t
+xcb_input_device_class_data_key_keys_end (const xcb_input_device_class_t *R,
+ const xcb_input_device_class_data_t *S);
+
+uint32_t *
+xcb_input_device_class_data_button_state (const xcb_input_device_class_data_t *S);
+
+int
+xcb_input_device_class_data_button_state_length (const xcb_input_device_class_t *R,
+ const xcb_input_device_class_data_t *S);
+
+xcb_generic_iterator_t
+xcb_input_device_class_data_button_state_end (const xcb_input_device_class_t *R,
+ const xcb_input_device_class_data_t *S);
+
+xcb_atom_t *
+xcb_input_device_class_data_button_labels (const xcb_input_device_class_data_t *S);
+
+int
+xcb_input_device_class_data_button_labels_length (const xcb_input_device_class_t *R,
+ const xcb_input_device_class_data_t *S);
+
+xcb_generic_iterator_t
+xcb_input_device_class_data_button_labels_end (const xcb_input_device_class_t *R,
+ const xcb_input_device_class_data_t *S);
+
+int
+xcb_input_device_class_data_serialize (void **_buffer,
+ uint16_t type,
+ const xcb_input_device_class_data_t *_aux);
+
+int
+xcb_input_device_class_data_unpack (const void *_buffer,
+ uint16_t type,
+ xcb_input_device_class_data_t *_aux);
+
+int
+xcb_input_device_class_data_sizeof (const void *_buffer,
+ uint16_t type);
+
+int
+xcb_input_device_class_sizeof (const void *_buffer);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_device_class_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_device_class_t)
+ */
+void
+xcb_input_device_class_next (xcb_input_device_class_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_device_class_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_device_class_end (xcb_input_device_class_iterator_t i);
+
+int
+xcb_input_xi_device_info_sizeof (const void *_buffer);
+
+char *
+xcb_input_xi_device_info_name (const xcb_input_xi_device_info_t *R);
+
+int
+xcb_input_xi_device_info_name_length (const xcb_input_xi_device_info_t *R);
+
+xcb_generic_iterator_t
+xcb_input_xi_device_info_name_end (const xcb_input_xi_device_info_t *R);
+
+int
+xcb_input_xi_device_info_classes_length (const xcb_input_xi_device_info_t *R);
+
+xcb_input_device_class_iterator_t
+xcb_input_xi_device_info_classes_iterator (const xcb_input_xi_device_info_t *R);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_xi_device_info_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_xi_device_info_t)
+ */
+void
+xcb_input_xi_device_info_next (xcb_input_xi_device_info_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_xi_device_info_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_xi_device_info_end (xcb_input_xi_device_info_iterator_t i);
+
+int
+xcb_input_xi_query_device_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_xi_query_device_cookie_t
+xcb_input_xi_query_device (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_xi_query_device_cookie_t
+xcb_input_xi_query_device_unchecked (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid);
+
+int
+xcb_input_xi_query_device_infos_length (const xcb_input_xi_query_device_reply_t *R);
+
+xcb_input_xi_device_info_iterator_t
+xcb_input_xi_query_device_infos_iterator (const xcb_input_xi_query_device_reply_t *R);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_xi_query_device_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_xi_query_device_reply_t *
+xcb_input_xi_query_device_reply (xcb_connection_t *c,
+ xcb_input_xi_query_device_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_xi_set_focus_checked (xcb_connection_t *c,
+ xcb_window_t window,
+ xcb_timestamp_t time,
+ xcb_input_device_id_t deviceid);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_xi_set_focus (xcb_connection_t *c,
+ xcb_window_t window,
+ xcb_timestamp_t time,
+ xcb_input_device_id_t deviceid);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_xi_get_focus_cookie_t
+xcb_input_xi_get_focus (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_xi_get_focus_cookie_t
+xcb_input_xi_get_focus_unchecked (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_xi_get_focus_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_xi_get_focus_reply_t *
+xcb_input_xi_get_focus_reply (xcb_connection_t *c,
+ xcb_input_xi_get_focus_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+int
+xcb_input_xi_grab_device_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_xi_grab_device_cookie_t
+xcb_input_xi_grab_device (xcb_connection_t *c,
+ xcb_window_t window,
+ xcb_timestamp_t time,
+ xcb_cursor_t cursor,
+ xcb_input_device_id_t deviceid,
+ uint8_t mode,
+ uint8_t paired_device_mode,
+ uint8_t owner_events,
+ uint16_t mask_len,
+ const uint32_t *mask);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_xi_grab_device_cookie_t
+xcb_input_xi_grab_device_unchecked (xcb_connection_t *c,
+ xcb_window_t window,
+ xcb_timestamp_t time,
+ xcb_cursor_t cursor,
+ xcb_input_device_id_t deviceid,
+ uint8_t mode,
+ uint8_t paired_device_mode,
+ uint8_t owner_events,
+ uint16_t mask_len,
+ const uint32_t *mask);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_xi_grab_device_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_xi_grab_device_reply_t *
+xcb_input_xi_grab_device_reply (xcb_connection_t *c,
+ xcb_input_xi_grab_device_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_xi_ungrab_device_checked (xcb_connection_t *c,
+ xcb_timestamp_t time,
+ xcb_input_device_id_t deviceid);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_xi_ungrab_device (xcb_connection_t *c,
+ xcb_timestamp_t time,
+ xcb_input_device_id_t deviceid);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_xi_allow_events_checked (xcb_connection_t *c,
+ xcb_timestamp_t time,
+ xcb_input_device_id_t deviceid,
+ uint8_t event_mode,
+ uint32_t touchid,
+ xcb_window_t grab_window);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_xi_allow_events (xcb_connection_t *c,
+ xcb_timestamp_t time,
+ xcb_input_device_id_t deviceid,
+ uint8_t event_mode,
+ uint32_t touchid,
+ xcb_window_t grab_window);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_grab_modifier_info_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_grab_modifier_info_t)
+ */
+void
+xcb_input_grab_modifier_info_next (xcb_input_grab_modifier_info_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_grab_modifier_info_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_grab_modifier_info_end (xcb_input_grab_modifier_info_iterator_t i);
+
+int
+xcb_input_xi_passive_grab_device_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_xi_passive_grab_device_cookie_t
+xcb_input_xi_passive_grab_device (xcb_connection_t *c,
+ xcb_timestamp_t time,
+ xcb_window_t grab_window,
+ xcb_cursor_t cursor,
+ uint32_t detail,
+ xcb_input_device_id_t deviceid,
+ uint16_t num_modifiers,
+ uint16_t mask_len,
+ uint8_t grab_type,
+ uint8_t grab_mode,
+ uint8_t paired_device_mode,
+ uint8_t owner_events,
+ const uint32_t *mask,
+ const uint32_t *modifiers);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_xi_passive_grab_device_cookie_t
+xcb_input_xi_passive_grab_device_unchecked (xcb_connection_t *c,
+ xcb_timestamp_t time,
+ xcb_window_t grab_window,
+ xcb_cursor_t cursor,
+ uint32_t detail,
+ xcb_input_device_id_t deviceid,
+ uint16_t num_modifiers,
+ uint16_t mask_len,
+ uint8_t grab_type,
+ uint8_t grab_mode,
+ uint8_t paired_device_mode,
+ uint8_t owner_events,
+ const uint32_t *mask,
+ const uint32_t *modifiers);
+
+xcb_input_grab_modifier_info_t *
+xcb_input_xi_passive_grab_device_modifiers (const xcb_input_xi_passive_grab_device_reply_t *R);
+
+int
+xcb_input_xi_passive_grab_device_modifiers_length (const xcb_input_xi_passive_grab_device_reply_t *R);
+
+xcb_input_grab_modifier_info_iterator_t
+xcb_input_xi_passive_grab_device_modifiers_iterator (const xcb_input_xi_passive_grab_device_reply_t *R);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_xi_passive_grab_device_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_xi_passive_grab_device_reply_t *
+xcb_input_xi_passive_grab_device_reply (xcb_connection_t *c,
+ xcb_input_xi_passive_grab_device_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+int
+xcb_input_xi_passive_ungrab_device_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_xi_passive_ungrab_device_checked (xcb_connection_t *c,
+ xcb_window_t grab_window,
+ uint32_t detail,
+ xcb_input_device_id_t deviceid,
+ uint16_t num_modifiers,
+ uint8_t grab_type,
+ const uint32_t *modifiers);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_xi_passive_ungrab_device (xcb_connection_t *c,
+ xcb_window_t grab_window,
+ uint32_t detail,
+ xcb_input_device_id_t deviceid,
+ uint16_t num_modifiers,
+ uint8_t grab_type,
+ const uint32_t *modifiers);
+
+uint32_t *
+xcb_input_xi_passive_ungrab_device_modifiers (const xcb_input_xi_passive_ungrab_device_request_t *R);
+
+int
+xcb_input_xi_passive_ungrab_device_modifiers_length (const xcb_input_xi_passive_ungrab_device_request_t *R);
+
+xcb_generic_iterator_t
+xcb_input_xi_passive_ungrab_device_modifiers_end (const xcb_input_xi_passive_ungrab_device_request_t *R);
+
+int
+xcb_input_xi_list_properties_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_xi_list_properties_cookie_t
+xcb_input_xi_list_properties (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_xi_list_properties_cookie_t
+xcb_input_xi_list_properties_unchecked (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid);
+
+xcb_atom_t *
+xcb_input_xi_list_properties_properties (const xcb_input_xi_list_properties_reply_t *R);
+
+int
+xcb_input_xi_list_properties_properties_length (const xcb_input_xi_list_properties_reply_t *R);
+
+xcb_generic_iterator_t
+xcb_input_xi_list_properties_properties_end (const xcb_input_xi_list_properties_reply_t *R);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_xi_list_properties_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_xi_list_properties_reply_t *
+xcb_input_xi_list_properties_reply (xcb_connection_t *c,
+ xcb_input_xi_list_properties_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+uint8_t *
+xcb_input_xi_change_property_items_data_8 (const xcb_input_xi_change_property_items_t *S);
+
+int
+xcb_input_xi_change_property_items_data_8_length (const xcb_input_xi_change_property_request_t *R,
+ const xcb_input_xi_change_property_items_t *S);
+
+xcb_generic_iterator_t
+xcb_input_xi_change_property_items_data_8_end (const xcb_input_xi_change_property_request_t *R,
+ const xcb_input_xi_change_property_items_t *S);
+
+uint16_t *
+xcb_input_xi_change_property_items_data_16 (const xcb_input_xi_change_property_items_t *S);
+
+int
+xcb_input_xi_change_property_items_data_16_length (const xcb_input_xi_change_property_request_t *R,
+ const xcb_input_xi_change_property_items_t *S);
+
+xcb_generic_iterator_t
+xcb_input_xi_change_property_items_data_16_end (const xcb_input_xi_change_property_request_t *R,
+ const xcb_input_xi_change_property_items_t *S);
+
+uint32_t *
+xcb_input_xi_change_property_items_data_32 (const xcb_input_xi_change_property_items_t *S);
+
+int
+xcb_input_xi_change_property_items_data_32_length (const xcb_input_xi_change_property_request_t *R,
+ const xcb_input_xi_change_property_items_t *S);
+
+xcb_generic_iterator_t
+xcb_input_xi_change_property_items_data_32_end (const xcb_input_xi_change_property_request_t *R,
+ const xcb_input_xi_change_property_items_t *S);
+
+int
+xcb_input_xi_change_property_items_serialize (void **_buffer,
+ uint32_t num_items,
+ uint8_t format,
+ const xcb_input_xi_change_property_items_t *_aux);
+
+int
+xcb_input_xi_change_property_items_unpack (const void *_buffer,
+ uint32_t num_items,
+ uint8_t format,
+ xcb_input_xi_change_property_items_t *_aux);
+
+int
+xcb_input_xi_change_property_items_sizeof (const void *_buffer,
+ uint32_t num_items,
+ uint8_t format);
+
+int
+xcb_input_xi_change_property_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_xi_change_property_checked (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid,
+ uint8_t mode,
+ uint8_t format,
+ xcb_atom_t property,
+ xcb_atom_t type,
+ uint32_t num_items,
+ const void *items);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_xi_change_property (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid,
+ uint8_t mode,
+ uint8_t format,
+ xcb_atom_t property,
+ xcb_atom_t type,
+ uint32_t num_items,
+ const void *items);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_xi_change_property_aux_checked (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid,
+ uint8_t mode,
+ uint8_t format,
+ xcb_atom_t property,
+ xcb_atom_t type,
+ uint32_t num_items,
+ const xcb_input_xi_change_property_items_t *items);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_xi_change_property_aux (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid,
+ uint8_t mode,
+ uint8_t format,
+ xcb_atom_t property,
+ xcb_atom_t type,
+ uint32_t num_items,
+ const xcb_input_xi_change_property_items_t *items);
+
+void *
+xcb_input_xi_change_property_items (const xcb_input_xi_change_property_request_t *R);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will not cause
+ * a reply to be generated. Any returned error will be
+ * saved for handling by xcb_request_check().
+ */
+xcb_void_cookie_t
+xcb_input_xi_delete_property_checked (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid,
+ xcb_atom_t property);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_void_cookie_t
+xcb_input_xi_delete_property (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid,
+ xcb_atom_t property);
+
+uint8_t *
+xcb_input_xi_get_property_items_data_8 (const xcb_input_xi_get_property_items_t *S);
+
+int
+xcb_input_xi_get_property_items_data_8_length (const xcb_input_xi_get_property_reply_t *R,
+ const xcb_input_xi_get_property_items_t *S);
+
+xcb_generic_iterator_t
+xcb_input_xi_get_property_items_data_8_end (const xcb_input_xi_get_property_reply_t *R,
+ const xcb_input_xi_get_property_items_t *S);
+
+uint16_t *
+xcb_input_xi_get_property_items_data_16 (const xcb_input_xi_get_property_items_t *S);
+
+int
+xcb_input_xi_get_property_items_data_16_length (const xcb_input_xi_get_property_reply_t *R,
+ const xcb_input_xi_get_property_items_t *S);
+
+xcb_generic_iterator_t
+xcb_input_xi_get_property_items_data_16_end (const xcb_input_xi_get_property_reply_t *R,
+ const xcb_input_xi_get_property_items_t *S);
+
+uint32_t *
+xcb_input_xi_get_property_items_data_32 (const xcb_input_xi_get_property_items_t *S);
+
+int
+xcb_input_xi_get_property_items_data_32_length (const xcb_input_xi_get_property_reply_t *R,
+ const xcb_input_xi_get_property_items_t *S);
+
+xcb_generic_iterator_t
+xcb_input_xi_get_property_items_data_32_end (const xcb_input_xi_get_property_reply_t *R,
+ const xcb_input_xi_get_property_items_t *S);
+
+int
+xcb_input_xi_get_property_items_serialize (void **_buffer,
+ uint32_t num_items,
+ uint8_t format,
+ const xcb_input_xi_get_property_items_t *_aux);
+
+int
+xcb_input_xi_get_property_items_unpack (const void *_buffer,
+ uint32_t num_items,
+ uint8_t format,
+ xcb_input_xi_get_property_items_t *_aux);
+
+int
+xcb_input_xi_get_property_items_sizeof (const void *_buffer,
+ uint32_t num_items,
+ uint8_t format);
+
+int
+xcb_input_xi_get_property_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_xi_get_property_cookie_t
+xcb_input_xi_get_property (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid,
+ uint8_t _delete,
+ xcb_atom_t property,
+ xcb_atom_t type,
+ uint32_t offset,
+ uint32_t len);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_xi_get_property_cookie_t
+xcb_input_xi_get_property_unchecked (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid,
+ uint8_t _delete,
+ xcb_atom_t property,
+ xcb_atom_t type,
+ uint32_t offset,
+ uint32_t len);
+
+void *
+xcb_input_xi_get_property_items (const xcb_input_xi_get_property_reply_t *R);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_xi_get_property_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_xi_get_property_reply_t *
+xcb_input_xi_get_property_reply (xcb_connection_t *c,
+ xcb_input_xi_get_property_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+int
+xcb_input_xi_get_selected_events_sizeof (const void *_buffer);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ */
+xcb_input_xi_get_selected_events_cookie_t
+xcb_input_xi_get_selected_events (xcb_connection_t *c,
+ xcb_window_t window);
+
+/**
+ *
+ * @param c The connection
+ * @return A cookie
+ *
+ * Delivers a request to the X server.
+ *
+ * This form can be used only if the request will cause
+ * a reply to be generated. Any returned error will be
+ * placed in the event queue.
+ */
+xcb_input_xi_get_selected_events_cookie_t
+xcb_input_xi_get_selected_events_unchecked (xcb_connection_t *c,
+ xcb_window_t window);
+
+int
+xcb_input_xi_get_selected_events_masks_length (const xcb_input_xi_get_selected_events_reply_t *R);
+
+xcb_input_event_mask_iterator_t
+xcb_input_xi_get_selected_events_masks_iterator (const xcb_input_xi_get_selected_events_reply_t *R);
+
+/**
+ * Return the reply
+ * @param c The connection
+ * @param cookie The cookie
+ * @param e The xcb_generic_error_t supplied
+ *
+ * Returns the reply of the request asked by
+ *
+ * The parameter @p e supplied to this function must be NULL if
+ * xcb_input_xi_get_selected_events_unchecked(). is used.
+ * Otherwise, it stores the error if any.
+ *
+ * The returned value must be freed by the caller using free().
+ */
+xcb_input_xi_get_selected_events_reply_t *
+xcb_input_xi_get_selected_events_reply (xcb_connection_t *c,
+ xcb_input_xi_get_selected_events_cookie_t cookie /**< */,
+ xcb_generic_error_t **e);
+
+int
+xcb_input_device_changed_sizeof (const void *_buffer);
+
+int
+xcb_input_device_changed_classes_length (const xcb_input_device_changed_event_t *R);
+
+xcb_input_device_class_iterator_t
+xcb_input_device_changed_classes_iterator (const xcb_input_device_changed_event_t *R);
+
+int
+xcb_input_key_press_sizeof (const void *_buffer);
+
+uint32_t *
+xcb_input_key_press_button_mask (const xcb_input_key_press_event_t *R);
+
+int
+xcb_input_key_press_button_mask_length (const xcb_input_key_press_event_t *R);
+
+xcb_generic_iterator_t
+xcb_input_key_press_button_mask_end (const xcb_input_key_press_event_t *R);
+
+uint32_t *
+xcb_input_key_press_valuator_mask (const xcb_input_key_press_event_t *R);
+
+int
+xcb_input_key_press_valuator_mask_length (const xcb_input_key_press_event_t *R);
+
+xcb_generic_iterator_t
+xcb_input_key_press_valuator_mask_end (const xcb_input_key_press_event_t *R);
+
+xcb_input_fp3232_t *
+xcb_input_key_press_axisvalues (const xcb_input_key_press_event_t *R);
+
+int
+xcb_input_key_press_axisvalues_length (const xcb_input_key_press_event_t *R);
+
+xcb_input_fp3232_iterator_t
+xcb_input_key_press_axisvalues_iterator (const xcb_input_key_press_event_t *R);
+
+int
+xcb_input_key_release_sizeof (const void *_buffer /**< */);
+
+int
+xcb_input_button_press_sizeof (const void *_buffer);
+
+uint32_t *
+xcb_input_button_press_button_mask (const xcb_input_button_press_event_t *R);
+
+int
+xcb_input_button_press_button_mask_length (const xcb_input_button_press_event_t *R);
+
+xcb_generic_iterator_t
+xcb_input_button_press_button_mask_end (const xcb_input_button_press_event_t *R);
+
+uint32_t *
+xcb_input_button_press_valuator_mask (const xcb_input_button_press_event_t *R);
+
+int
+xcb_input_button_press_valuator_mask_length (const xcb_input_button_press_event_t *R);
+
+xcb_generic_iterator_t
+xcb_input_button_press_valuator_mask_end (const xcb_input_button_press_event_t *R);
+
+xcb_input_fp3232_t *
+xcb_input_button_press_axisvalues (const xcb_input_button_press_event_t *R);
+
+int
+xcb_input_button_press_axisvalues_length (const xcb_input_button_press_event_t *R);
+
+xcb_input_fp3232_iterator_t
+xcb_input_button_press_axisvalues_iterator (const xcb_input_button_press_event_t *R);
+
+int
+xcb_input_button_release_sizeof (const void *_buffer /**< */);
+
+int
+xcb_input_motion_sizeof (const void *_buffer /**< */);
+
+int
+xcb_input_enter_sizeof (const void *_buffer);
+
+uint32_t *
+xcb_input_enter_buttons (const xcb_input_enter_event_t *R);
+
+int
+xcb_input_enter_buttons_length (const xcb_input_enter_event_t *R);
+
+xcb_generic_iterator_t
+xcb_input_enter_buttons_end (const xcb_input_enter_event_t *R);
+
+int
+xcb_input_leave_sizeof (const void *_buffer /**< */);
+
+int
+xcb_input_focus_in_sizeof (const void *_buffer /**< */);
+
+int
+xcb_input_focus_out_sizeof (const void *_buffer /**< */);
+
+/**
+ * Get the next element of the iterator
+ * @param i Pointer to a xcb_input_hierarchy_info_iterator_t
+ *
+ * Get the next element in the iterator. The member rem is
+ * decreased by one. The member data points to the next
+ * element. The member index is increased by sizeof(xcb_input_hierarchy_info_t)
+ */
+void
+xcb_input_hierarchy_info_next (xcb_input_hierarchy_info_iterator_t *i);
+
+/**
+ * Return the iterator pointing to the last element
+ * @param i An xcb_input_hierarchy_info_iterator_t
+ * @return The iterator pointing to the last element
+ *
+ * Set the current element in the iterator to the last element.
+ * The member rem is set to 0. The member data points to the
+ * last element.
+ */
+xcb_generic_iterator_t
+xcb_input_hierarchy_info_end (xcb_input_hierarchy_info_iterator_t i);
+
+int
+xcb_input_hierarchy_sizeof (const void *_buffer);
+
+xcb_input_hierarchy_info_t *
+xcb_input_hierarchy_infos (const xcb_input_hierarchy_event_t *R);
+
+int
+xcb_input_hierarchy_infos_length (const xcb_input_hierarchy_event_t *R);
+
+xcb_input_hierarchy_info_iterator_t
+xcb_input_hierarchy_infos_iterator (const xcb_input_hierarchy_event_t *R);
+
+int
+xcb_input_raw_key_press_sizeof (const void *_buffer);
+
+uint32_t *
+xcb_input_raw_key_press_valuator_mask (const xcb_input_raw_key_press_event_t *R);
+
+int
+xcb_input_raw_key_press_valuator_mask_length (const xcb_input_raw_key_press_event_t *R);
+
+xcb_generic_iterator_t
+xcb_input_raw_key_press_valuator_mask_end (const xcb_input_raw_key_press_event_t *R);
+
+xcb_input_fp3232_t *
+xcb_input_raw_key_press_axisvalues (const xcb_input_raw_key_press_event_t *R);
+
+int
+xcb_input_raw_key_press_axisvalues_length (const xcb_input_raw_key_press_event_t *R);
+
+xcb_input_fp3232_iterator_t
+xcb_input_raw_key_press_axisvalues_iterator (const xcb_input_raw_key_press_event_t *R);
+
+xcb_input_fp3232_t *
+xcb_input_raw_key_press_axisvalues_raw (const xcb_input_raw_key_press_event_t *R);
+
+int
+xcb_input_raw_key_press_axisvalues_raw_length (const xcb_input_raw_key_press_event_t *R);
+
+xcb_input_fp3232_iterator_t
+xcb_input_raw_key_press_axisvalues_raw_iterator (const xcb_input_raw_key_press_event_t *R);
+
+int
+xcb_input_raw_key_release_sizeof (const void *_buffer /**< */);
+
+int
+xcb_input_raw_button_press_sizeof (const void *_buffer);
+
+uint32_t *
+xcb_input_raw_button_press_valuator_mask (const xcb_input_raw_button_press_event_t *R);
+
+int
+xcb_input_raw_button_press_valuator_mask_length (const xcb_input_raw_button_press_event_t *R);
+
+xcb_generic_iterator_t
+xcb_input_raw_button_press_valuator_mask_end (const xcb_input_raw_button_press_event_t *R);
+
+xcb_input_fp3232_t *
+xcb_input_raw_button_press_axisvalues (const xcb_input_raw_button_press_event_t *R);
+
+int
+xcb_input_raw_button_press_axisvalues_length (const xcb_input_raw_button_press_event_t *R);
+
+xcb_input_fp3232_iterator_t
+xcb_input_raw_button_press_axisvalues_iterator (const xcb_input_raw_button_press_event_t *R);
+
+xcb_input_fp3232_t *
+xcb_input_raw_button_press_axisvalues_raw (const xcb_input_raw_button_press_event_t *R);
+
+int
+xcb_input_raw_button_press_axisvalues_raw_length (const xcb_input_raw_button_press_event_t *R);
+
+xcb_input_fp3232_iterator_t
+xcb_input_raw_button_press_axisvalues_raw_iterator (const xcb_input_raw_button_press_event_t *R);
+
+int
+xcb_input_raw_button_release_sizeof (const void *_buffer /**< */);
+
+int
+xcb_input_raw_motion_sizeof (const void *_buffer /**< */);
+
+int
+xcb_input_touch_begin_sizeof (const void *_buffer);
+
+uint32_t *
+xcb_input_touch_begin_button_mask (const xcb_input_touch_begin_event_t *R);
+
+int
+xcb_input_touch_begin_button_mask_length (const xcb_input_touch_begin_event_t *R);
+
+xcb_generic_iterator_t
+xcb_input_touch_begin_button_mask_end (const xcb_input_touch_begin_event_t *R);
+
+uint32_t *
+xcb_input_touch_begin_valuator_mask (const xcb_input_touch_begin_event_t *R);
+
+int
+xcb_input_touch_begin_valuator_mask_length (const xcb_input_touch_begin_event_t *R);
+
+xcb_generic_iterator_t
+xcb_input_touch_begin_valuator_mask_end (const xcb_input_touch_begin_event_t *R);
+
+xcb_input_fp3232_t *
+xcb_input_touch_begin_axisvalues (const xcb_input_touch_begin_event_t *R);
+
+int
+xcb_input_touch_begin_axisvalues_length (const xcb_input_touch_begin_event_t *R);
+
+xcb_input_fp3232_iterator_t
+xcb_input_touch_begin_axisvalues_iterator (const xcb_input_touch_begin_event_t *R);
+
+int
+xcb_input_touch_update_sizeof (const void *_buffer /**< */);
+
+int
+xcb_input_touch_end_sizeof (const void *_buffer /**< */);
+
+int
+xcb_input_raw_touch_begin_sizeof (const void *_buffer);
+
+uint32_t *
+xcb_input_raw_touch_begin_valuator_mask (const xcb_input_raw_touch_begin_event_t *R);
+
+int
+xcb_input_raw_touch_begin_valuator_mask_length (const xcb_input_raw_touch_begin_event_t *R);
+
+xcb_generic_iterator_t
+xcb_input_raw_touch_begin_valuator_mask_end (const xcb_input_raw_touch_begin_event_t *R);
+
+xcb_input_fp3232_t *
+xcb_input_raw_touch_begin_axisvalues (const xcb_input_raw_touch_begin_event_t *R);
+
+int
+xcb_input_raw_touch_begin_axisvalues_length (const xcb_input_raw_touch_begin_event_t *R);
+
+xcb_input_fp3232_iterator_t
+xcb_input_raw_touch_begin_axisvalues_iterator (const xcb_input_raw_touch_begin_event_t *R);
+
+xcb_input_fp3232_t *
+xcb_input_raw_touch_begin_axisvalues_raw (const xcb_input_raw_touch_begin_event_t *R);
+
+int
+xcb_input_raw_touch_begin_axisvalues_raw_length (const xcb_input_raw_touch_begin_event_t *R);
+
+xcb_input_fp3232_iterator_t
+xcb_input_raw_touch_begin_axisvalues_raw_iterator (const xcb_input_raw_touch_begin_event_t *R);
+
+int
+xcb_input_raw_touch_update_sizeof (const void *_buffer /**< */);
+
+int
+xcb_input_raw_touch_end_sizeof (const void *_buffer /**< */);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/**
+ * @}
+ */
diff --git a/src/3rdparty/xcb/libxcb/randr.c b/src/3rdparty/xcb/libxcb/randr.c
index 1956ee033e..0232af802f 100644
--- a/src/3rdparty/xcb/libxcb/randr.c
+++ b/src/3rdparty/xcb/libxcb/randr.c
@@ -3,10 +3,17 @@
* Edit at your peril.
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
+#include <stddef.h> /* for offsetof() */
#include "xcbext.h"
#include "randr.h"
+
+#define ALIGNOF(type) offsetof(struct { char dummy; type member; }, member)
#include "xproto.h"
#include "render.h"
@@ -164,6 +171,35 @@ xcb_randr_screen_size_end (xcb_randr_screen_size_iterator_t i /**< */)
return ret;
}
+int
+xcb_randr_refresh_rates_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_randr_refresh_rates_t *_aux = (xcb_randr_refresh_rates_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_randr_refresh_rates_t);
+ xcb_tmp += xcb_block_len;
+ /* rates */
+ xcb_block_len += _aux->nRates * sizeof(uint16_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -230,10 +266,11 @@ void
xcb_randr_refresh_rates_next (xcb_randr_refresh_rates_iterator_t *i /**< */)
{
xcb_randr_refresh_rates_t *R = i->data;
- xcb_generic_iterator_t child = xcb_randr_refresh_rates_rates_end(R);
+ xcb_generic_iterator_t child;
+ child.data = (xcb_randr_refresh_rates_t *)(((char *)R) + xcb_randr_refresh_rates_sizeof(R));
+ i->index = (char *) child.data - (char *) i->data;
--i->rem;
i->data = (xcb_randr_refresh_rates_t *) child.data;
- i->index = child.index;
}
@@ -293,6 +330,7 @@ xcb_randr_query_version (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -332,6 +370,7 @@ xcb_randr_query_version_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -404,6 +443,7 @@ xcb_randr_set_screen_config (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -456,6 +496,7 @@ xcb_randr_set_screen_config_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -516,6 +557,7 @@ xcb_randr_select_input_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -556,10 +598,57 @@ xcb_randr_select_input (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_randr_get_screen_info_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_randr_get_screen_info_reply_t *_aux = (xcb_randr_get_screen_info_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+ unsigned int i;
+ unsigned int xcb_tmp_len;
+
+ xcb_block_len += sizeof(xcb_randr_get_screen_info_reply_t);
+ xcb_tmp += xcb_block_len;
+ /* sizes */
+ xcb_block_len += _aux->nSizes * sizeof(xcb_randr_screen_size_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_randr_screen_size_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* rates */
+ for(i=0; i<(_aux->nInfo - _aux->nSizes); i++) {
+ xcb_tmp_len = xcb_randr_refresh_rates_sizeof(xcb_tmp);
+ xcb_block_len += xcb_tmp_len;
+ xcb_tmp += xcb_tmp_len;
+ }
+ xcb_align_to = ALIGNOF(xcb_randr_refresh_rates_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -592,6 +681,7 @@ xcb_randr_get_screen_info (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -628,6 +718,7 @@ xcb_randr_get_screen_info_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -773,6 +864,7 @@ xcb_randr_get_screen_size_range (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -809,6 +901,7 @@ xcb_randr_get_screen_size_range_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -877,6 +970,7 @@ xcb_randr_set_screen_size_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -925,6 +1019,7 @@ xcb_randr_set_screen_size (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -967,6 +1062,71 @@ xcb_randr_mode_info_end (xcb_randr_mode_info_iterator_t i /**< */)
return ret;
}
+int
+xcb_randr_get_screen_resources_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_randr_get_screen_resources_reply_t *_aux = (xcb_randr_get_screen_resources_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_randr_get_screen_resources_reply_t);
+ xcb_tmp += xcb_block_len;
+ /* crtcs */
+ xcb_block_len += _aux->num_crtcs * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_randr_crtc_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* outputs */
+ xcb_block_len += _aux->num_outputs * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_randr_output_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* modes */
+ xcb_block_len += _aux->num_modes * sizeof(xcb_randr_mode_info_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_randr_mode_info_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* names */
+ xcb_block_len += _aux->names_len * sizeof(uint8_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -999,6 +1159,7 @@ xcb_randr_get_screen_resources (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1035,6 +1196,7 @@ xcb_randr_get_screen_resources_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1273,6 +1435,71 @@ xcb_randr_get_screen_resources_reply (xcb_connection_t *
return (xcb_randr_get_screen_resources_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
}
+int
+xcb_randr_get_output_info_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_randr_get_output_info_reply_t *_aux = (xcb_randr_get_output_info_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_randr_get_output_info_reply_t);
+ xcb_tmp += xcb_block_len;
+ /* crtcs */
+ xcb_block_len += _aux->num_crtcs * sizeof(xcb_randr_output_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_randr_crtc_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* modes */
+ xcb_block_len += _aux->num_modes * sizeof(xcb_randr_output_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_randr_mode_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* clones */
+ xcb_block_len += _aux->num_clones * sizeof(xcb_randr_output_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_randr_output_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* name */
+ xcb_block_len += _aux->name_len * sizeof(uint8_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -1308,6 +1535,7 @@ xcb_randr_get_output_info (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1347,6 +1575,7 @@ xcb_randr_get_output_info_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1585,6 +1814,35 @@ xcb_randr_get_output_info_reply (xcb_connection_t *c /**< */
return (xcb_randr_get_output_info_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
}
+int
+xcb_randr_list_output_properties_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_randr_list_output_properties_reply_t *_aux = (xcb_randr_list_output_properties_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_randr_list_output_properties_reply_t);
+ xcb_tmp += xcb_block_len;
+ /* atoms */
+ xcb_block_len += _aux->num_atoms * sizeof(xcb_atom_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_atom_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -1617,6 +1875,7 @@ xcb_randr_list_output_properties (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1653,6 +1912,7 @@ xcb_randr_list_output_properties_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1729,6 +1989,35 @@ xcb_randr_list_output_properties_reply (xcb_connection_t
return (xcb_randr_list_output_properties_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
}
+int
+xcb_randr_query_output_property_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_randr_query_output_property_reply_t *_aux = (xcb_randr_query_output_property_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_randr_query_output_property_reply_t);
+ xcb_tmp += xcb_block_len;
+ /* validValues */
+ xcb_block_len += _aux->length * sizeof(int32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(int32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -1764,6 +2053,7 @@ xcb_randr_query_output_property (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1803,6 +2093,7 @@ xcb_randr_query_output_property_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1879,6 +2170,35 @@ xcb_randr_query_output_property_reply (xcb_connection_t
return (xcb_randr_query_output_property_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
}
+int
+xcb_randr_configure_output_property_sizeof (const void *_buffer /**< */,
+ uint32_t values_len /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_randr_configure_output_property_request_t);
+ xcb_tmp += xcb_block_len;
+ /* values */
+ xcb_block_len += values_len * sizeof(int32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(int32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -1925,10 +2245,12 @@ xcb_randr_configure_output_property_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* int32_t values */
xcb_parts[4].iov_base = (char *) values;
xcb_parts[4].iov_len = values_len * sizeof(int32_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1979,14 +2301,45 @@ xcb_randr_configure_output_property (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* int32_t values */
xcb_parts[4].iov_base = (char *) values;
xcb_parts[4].iov_len = values_len * sizeof(int32_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_randr_change_output_property_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_randr_change_output_property_request_t *_aux = (xcb_randr_change_output_property_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_randr_change_output_property_request_t);
+ xcb_tmp += xcb_block_len;
+ /* data */
+ xcb_block_len += ((_aux->num_units * _aux->format) / 8) * sizeof(char);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -2037,10 +2390,12 @@ xcb_randr_change_output_property_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* void data */
xcb_parts[4].iov_base = (char *) data;
xcb_parts[4].iov_len = ((num_units * format) / 8) * sizeof(char);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2095,10 +2450,12 @@ xcb_randr_change_output_property (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* void data */
xcb_parts[4].iov_base = (char *) data;
xcb_parts[4].iov_len = ((num_units * format) / 8) * sizeof(char);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2138,6 +2495,7 @@ xcb_randr_delete_output_property_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2177,10 +2535,40 @@ xcb_randr_delete_output_property (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_randr_get_output_property_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_randr_get_output_property_reply_t *_aux = (xcb_randr_get_output_property_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_randr_get_output_property_reply_t);
+ xcb_tmp += xcb_block_len;
+ /* data */
+ xcb_block_len += (_aux->num_items * (_aux->format / 8)) * sizeof(uint8_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -2232,6 +2620,7 @@ xcb_randr_get_output_property (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2287,6 +2676,7 @@ xcb_randr_get_output_property_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2363,6 +2753,35 @@ xcb_randr_get_output_property_reply (xcb_connection_t *c
return (xcb_randr_get_output_property_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
}
+int
+xcb_randr_create_mode_sizeof (const void *_buffer /**< */,
+ uint32_t name_len /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_randr_create_mode_request_t);
+ xcb_tmp += xcb_block_len;
+ /* name */
+ xcb_block_len += name_len * sizeof(char);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -2402,10 +2821,12 @@ xcb_randr_create_mode (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* char name */
xcb_parts[4].iov_base = (char *) name;
xcb_parts[4].iov_len = name_len * sizeof(char);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2449,10 +2870,12 @@ xcb_randr_create_mode_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* char name */
xcb_parts[4].iov_base = (char *) name;
xcb_parts[4].iov_len = name_len * sizeof(char);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2509,6 +2932,7 @@ xcb_randr_destroy_mode_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2545,6 +2969,7 @@ xcb_randr_destroy_mode (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2584,6 +3009,7 @@ xcb_randr_add_output_mode_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2623,6 +3049,7 @@ xcb_randr_add_output_mode (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2662,6 +3089,7 @@ xcb_randr_delete_output_mode_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2701,10 +3129,52 @@ xcb_randr_delete_output_mode (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_randr_get_crtc_info_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_randr_get_crtc_info_reply_t *_aux = (xcb_randr_get_crtc_info_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_randr_get_crtc_info_reply_t);
+ xcb_tmp += xcb_block_len;
+ /* outputs */
+ xcb_block_len += _aux->num_outputs * sizeof(xcb_randr_output_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_randr_output_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* possible */
+ xcb_block_len += _aux->num_possible_outputs * sizeof(xcb_randr_output_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_randr_output_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -2740,6 +3210,7 @@ xcb_randr_get_crtc_info (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2779,6 +3250,7 @@ xcb_randr_get_crtc_info_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2909,6 +3381,35 @@ xcb_randr_get_crtc_info_reply (xcb_connection_t *c /**< */,
return (xcb_randr_get_crtc_info_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
}
+int
+xcb_randr_set_crtc_config_sizeof (const void *_buffer /**< */,
+ uint32_t outputs_len /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_randr_set_crtc_config_request_t);
+ xcb_tmp += xcb_block_len;
+ /* outputs */
+ xcb_block_len += outputs_len * sizeof(xcb_randr_output_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_randr_output_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -2964,10 +3465,12 @@ xcb_randr_set_crtc_config (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_randr_output_t outputs */
xcb_parts[4].iov_base = (char *) outputs;
xcb_parts[4].iov_len = outputs_len * sizeof(xcb_timestamp_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3027,10 +3530,12 @@ xcb_randr_set_crtc_config_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_randr_output_t outputs */
xcb_parts[4].iov_base = (char *) outputs;
xcb_parts[4].iov_len = outputs_len * sizeof(xcb_timestamp_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3087,6 +3592,7 @@ xcb_randr_get_crtc_gamma_size (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3123,6 +3629,7 @@ xcb_randr_get_crtc_gamma_size_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3147,6 +3654,59 @@ xcb_randr_get_crtc_gamma_size_reply (xcb_connection_t *c
return (xcb_randr_get_crtc_gamma_size_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
}
+int
+xcb_randr_get_crtc_gamma_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_randr_get_crtc_gamma_reply_t *_aux = (xcb_randr_get_crtc_gamma_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_randr_get_crtc_gamma_reply_t);
+ xcb_tmp += xcb_block_len;
+ /* red */
+ xcb_block_len += _aux->size * sizeof(uint16_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* green */
+ xcb_block_len += _aux->size * sizeof(uint16_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* blue */
+ xcb_block_len += _aux->size * sizeof(uint16_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -3179,6 +3739,7 @@ xcb_randr_get_crtc_gamma (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3215,6 +3776,7 @@ xcb_randr_get_crtc_gamma_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3399,6 +3961,59 @@ xcb_randr_get_crtc_gamma_reply (xcb_connection_t *c /**< */,
return (xcb_randr_get_crtc_gamma_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
}
+int
+xcb_randr_set_crtc_gamma_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_randr_set_crtc_gamma_request_t *_aux = (xcb_randr_set_crtc_gamma_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_randr_set_crtc_gamma_request_t);
+ xcb_tmp += xcb_block_len;
+ /* red */
+ xcb_block_len += _aux->size * sizeof(uint16_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* green */
+ xcb_block_len += _aux->size * sizeof(uint16_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* blue */
+ xcb_block_len += _aux->size * sizeof(uint16_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -3441,18 +4056,22 @@ xcb_randr_set_crtc_gamma_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint16_t red */
xcb_parts[4].iov_base = (char *) red;
xcb_parts[4].iov_len = size * sizeof(uint16_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+ /* uint16_t green */
xcb_parts[6].iov_base = (char *) green;
xcb_parts[6].iov_len = size * sizeof(uint16_t);
xcb_parts[7].iov_base = 0;
xcb_parts[7].iov_len = -xcb_parts[6].iov_len & 3;
+ /* uint16_t blue */
xcb_parts[8].iov_base = (char *) blue;
xcb_parts[8].iov_len = size * sizeof(uint16_t);
xcb_parts[9].iov_base = 0;
xcb_parts[9].iov_len = -xcb_parts[8].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3499,22 +4118,91 @@ xcb_randr_set_crtc_gamma (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint16_t red */
xcb_parts[4].iov_base = (char *) red;
xcb_parts[4].iov_len = size * sizeof(uint16_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+ /* uint16_t green */
xcb_parts[6].iov_base = (char *) green;
xcb_parts[6].iov_len = size * sizeof(uint16_t);
xcb_parts[7].iov_base = 0;
xcb_parts[7].iov_len = -xcb_parts[6].iov_len & 3;
+ /* uint16_t blue */
xcb_parts[8].iov_base = (char *) blue;
xcb_parts[8].iov_len = size * sizeof(uint16_t);
xcb_parts[9].iov_base = 0;
xcb_parts[9].iov_len = -xcb_parts[8].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_randr_get_screen_resources_current_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_randr_get_screen_resources_current_reply_t *_aux = (xcb_randr_get_screen_resources_current_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_randr_get_screen_resources_current_reply_t);
+ xcb_tmp += xcb_block_len;
+ /* crtcs */
+ xcb_block_len += _aux->num_crtcs * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_randr_crtc_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* outputs */
+ xcb_block_len += _aux->num_outputs * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_randr_output_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* modes */
+ xcb_block_len += _aux->num_modes * sizeof(xcb_randr_mode_info_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_randr_mode_info_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* names */
+ xcb_block_len += _aux->names_len * sizeof(uint8_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -3547,6 +4235,7 @@ xcb_randr_get_screen_resources_current (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3583,6 +4272,7 @@ xcb_randr_get_screen_resources_current_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3821,6 +4511,48 @@ xcb_randr_get_screen_resources_current_reply (xcb_connection_t
return (xcb_randr_get_screen_resources_current_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
}
+int
+xcb_randr_set_crtc_transform_sizeof (const void *_buffer /**< */,
+ uint32_t filter_params_len /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_randr_set_crtc_transform_request_t *_aux = (xcb_randr_set_crtc_transform_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_randr_set_crtc_transform_request_t);
+ xcb_tmp += xcb_block_len;
+ /* filter_name */
+ xcb_block_len += _aux->filter_len * sizeof(char);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* filter_params */
+ xcb_block_len += filter_params_len * sizeof(xcb_render_fixed_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_render_fixed_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -3866,14 +4598,17 @@ xcb_randr_set_crtc_transform_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* char filter_name */
xcb_parts[4].iov_base = (char *) filter_name;
xcb_parts[4].iov_len = filter_len * sizeof(char);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+ /* xcb_render_fixed_t filter_params */
xcb_parts[6].iov_base = (char *) filter_params;
xcb_parts[6].iov_len = filter_params_len * sizeof(xcb_render_fixed_t);
xcb_parts[7].iov_base = 0;
xcb_parts[7].iov_len = -xcb_parts[6].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3923,18 +4658,86 @@ xcb_randr_set_crtc_transform (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* char filter_name */
xcb_parts[4].iov_base = (char *) filter_name;
xcb_parts[4].iov_len = filter_len * sizeof(char);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+ /* xcb_render_fixed_t filter_params */
xcb_parts[6].iov_base = (char *) filter_params;
xcb_parts[6].iov_len = filter_params_len * sizeof(xcb_render_fixed_t);
xcb_parts[7].iov_base = 0;
xcb_parts[7].iov_len = -xcb_parts[6].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_randr_get_crtc_transform_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_randr_get_crtc_transform_reply_t *_aux = (xcb_randr_get_crtc_transform_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_randr_get_crtc_transform_reply_t);
+ xcb_tmp += xcb_block_len;
+ /* pending_filter_name */
+ xcb_block_len += _aux->pending_len * sizeof(char);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* pending_params */
+ xcb_block_len += _aux->pending_nparams * sizeof(xcb_render_fixed_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_render_fixed_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* current_filter_name */
+ xcb_block_len += _aux->current_len * sizeof(char);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* current_params */
+ xcb_block_len += _aux->current_nparams * sizeof(xcb_render_fixed_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_render_fixed_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -3967,6 +4770,7 @@ xcb_randr_get_crtc_transform (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -4003,6 +4807,7 @@ xcb_randr_get_crtc_transform_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -4273,6 +5078,7 @@ xcb_randr_get_panning (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -4309,6 +5115,7 @@ xcb_randr_get_panning_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -4404,6 +5211,7 @@ xcb_randr_set_panning (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -4479,6 +5287,7 @@ xcb_randr_set_panning_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -4538,6 +5347,7 @@ xcb_randr_set_output_primary_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -4577,6 +5387,7 @@ xcb_randr_set_output_primary (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -4613,6 +5424,7 @@ xcb_randr_get_output_primary (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -4649,6 +5461,7 @@ xcb_randr_get_output_primary_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
diff --git a/src/3rdparty/xcb/libxcb/render.c b/src/3rdparty/xcb/libxcb/render.c
index b251f8814c..7e5379cfcf 100644
--- a/src/3rdparty/xcb/libxcb/render.c
+++ b/src/3rdparty/xcb/libxcb/render.c
@@ -3,10 +3,17 @@
* Edit at your peril.
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
+#include <stddef.h> /* for offsetof() */
#include "xcbext.h"
#include "render.h"
+
+#define ALIGNOF(type) offsetof(struct { char dummy; type member; }, member)
#include "xproto.h"
xcb_extension_t xcb_render_id = { "RENDER", 0 };
@@ -315,6 +322,35 @@ xcb_render_pictvisual_end (xcb_render_pictvisual_iterator_t i /**< */)
return ret;
}
+int
+xcb_render_pictdepth_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_render_pictdepth_t *_aux = (xcb_render_pictdepth_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_render_pictdepth_t);
+ xcb_tmp += xcb_block_len;
+ /* visuals */
+ xcb_block_len += _aux->num_visuals * sizeof(xcb_render_pictvisual_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_render_pictvisual_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -381,10 +417,11 @@ void
xcb_render_pictdepth_next (xcb_render_pictdepth_iterator_t *i /**< */)
{
xcb_render_pictdepth_t *R = i->data;
- xcb_generic_iterator_t child = xcb_render_pictvisual_end(xcb_render_pictdepth_visuals_iterator(R));
+ xcb_generic_iterator_t child;
+ child.data = (xcb_render_pictdepth_t *)(((char *)R) + xcb_render_pictdepth_sizeof(R));
+ i->index = (char *) child.data - (char *) i->data;
--i->rem;
i->data = (xcb_render_pictdepth_t *) child.data;
- i->index = child.index;
}
@@ -409,6 +446,40 @@ xcb_render_pictdepth_end (xcb_render_pictdepth_iterator_t i /**< */)
return ret;
}
+int
+xcb_render_pictscreen_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_render_pictscreen_t *_aux = (xcb_render_pictscreen_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+ unsigned int i;
+ unsigned int xcb_tmp_len;
+
+ xcb_block_len += sizeof(xcb_render_pictscreen_t);
+ xcb_tmp += xcb_block_len;
+ /* depths */
+ for(i=0; i<_aux->num_depths; i++) {
+ xcb_tmp_len = xcb_render_pictdepth_sizeof(xcb_tmp);
+ xcb_block_len += xcb_tmp_len;
+ xcb_tmp += xcb_tmp_len;
+ }
+ xcb_align_to = ALIGNOF(xcb_render_pictdepth_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -459,10 +530,11 @@ void
xcb_render_pictscreen_next (xcb_render_pictscreen_iterator_t *i /**< */)
{
xcb_render_pictscreen_t *R = i->data;
- xcb_generic_iterator_t child = xcb_render_pictdepth_end(xcb_render_pictscreen_depths_iterator(R));
+ xcb_generic_iterator_t child;
+ child.data = (xcb_render_pictscreen_t *)(((char *)R) + xcb_render_pictscreen_sizeof(R));
+ i->index = (char *) child.data - (char *) i->data;
--i->rem;
i->data = (xcb_render_pictscreen_t *) child.data;
- i->index = child.index;
}
@@ -788,6 +860,7 @@ xcb_render_query_version (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -827,6 +900,7 @@ xcb_render_query_version_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -851,6 +925,64 @@ xcb_render_query_version_reply (xcb_connection_t *c /**< */,
return (xcb_render_query_version_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
}
+int
+xcb_render_query_pict_formats_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_render_query_pict_formats_reply_t *_aux = (xcb_render_query_pict_formats_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+ unsigned int i;
+ unsigned int xcb_tmp_len;
+
+ xcb_block_len += sizeof(xcb_render_query_pict_formats_reply_t);
+ xcb_tmp += xcb_block_len;
+ /* formats */
+ xcb_block_len += _aux->num_formats * sizeof(xcb_render_pictforminfo_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_render_pictforminfo_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* screens */
+ for(i=0; i<_aux->num_screens; i++) {
+ xcb_tmp_len = xcb_render_pictscreen_sizeof(xcb_tmp);
+ xcb_block_len += xcb_tmp_len;
+ xcb_tmp += xcb_tmp_len;
+ }
+ xcb_align_to = ALIGNOF(xcb_render_pictscreen_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* subpixels */
+ xcb_block_len += _aux->num_subpixel * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -880,6 +1012,7 @@ xcb_render_query_pict_formats (xcb_connection_t *c /**< */)
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -913,6 +1046,7 @@ xcb_render_query_pict_formats_unchecked (xcb_connection_t *c /**< */)
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1080,6 +1214,35 @@ xcb_render_query_pict_formats_reply (xcb_connection_t *c
return (xcb_render_query_pict_formats_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
}
+int
+xcb_render_query_pict_index_values_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_render_query_pict_index_values_reply_t *_aux = (xcb_render_query_pict_index_values_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_render_query_pict_index_values_reply_t);
+ xcb_tmp += xcb_block_len;
+ /* values */
+ xcb_block_len += _aux->num_values * sizeof(xcb_render_indexvalue_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_render_indexvalue_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -1112,6 +1275,7 @@ xcb_render_query_pict_index_values (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1148,6 +1312,7 @@ xcb_render_query_pict_index_values_unchecked (xcb_connection_t *c /**< *
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1224,6 +1389,35 @@ xcb_render_query_pict_index_values_reply (xcb_connection_t
return (xcb_render_query_pict_index_values_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
}
+int
+xcb_render_create_picture_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_render_create_picture_request_t *_aux = (xcb_render_create_picture_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_render_create_picture_request_t);
+ xcb_tmp += xcb_block_len;
+ /* value_list */
+ xcb_block_len += xcb_popcount(_aux->value_mask) * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -1267,10 +1461,12 @@ xcb_render_create_picture_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint32_t value_list */
xcb_parts[4].iov_base = (char *) value_list;
xcb_parts[4].iov_len = xcb_popcount(value_mask) * sizeof(uint32_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1318,14 +1514,45 @@ xcb_render_create_picture (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint32_t value_list */
xcb_parts[4].iov_base = (char *) value_list;
xcb_parts[4].iov_len = xcb_popcount(value_mask) * sizeof(uint32_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_render_change_picture_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_render_change_picture_request_t *_aux = (xcb_render_change_picture_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_render_change_picture_request_t);
+ xcb_tmp += xcb_block_len;
+ /* value_list */
+ xcb_block_len += xcb_popcount(_aux->value_mask) * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -1363,10 +1590,12 @@ xcb_render_change_picture_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint32_t value_list */
xcb_parts[4].iov_base = (char *) value_list;
xcb_parts[4].iov_len = xcb_popcount(value_mask) * sizeof(uint32_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1408,14 +1637,45 @@ xcb_render_change_picture (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint32_t value_list */
xcb_parts[4].iov_base = (char *) value_list;
xcb_parts[4].iov_len = xcb_popcount(value_mask) * sizeof(uint32_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_render_set_picture_clip_rectangles_sizeof (const void *_buffer /**< */,
+ uint32_t rectangles_len /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_render_set_picture_clip_rectangles_request_t);
+ xcb_tmp += xcb_block_len;
+ /* rectangles */
+ xcb_block_len += rectangles_len * sizeof(xcb_rectangle_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_rectangle_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -1458,10 +1718,12 @@ xcb_render_set_picture_clip_rectangles_checked (xcb_connection_t *c /**< *
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_rectangle_t rectangles */
xcb_parts[4].iov_base = (char *) rectangles;
xcb_parts[4].iov_len = rectangles_len * sizeof(xcb_rectangle_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1508,10 +1770,12 @@ xcb_render_set_picture_clip_rectangles (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_rectangle_t rectangles */
xcb_parts[4].iov_base = (char *) rectangles;
xcb_parts[4].iov_len = rectangles_len * sizeof(xcb_rectangle_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1548,6 +1812,7 @@ xcb_render_free_picture_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1584,6 +1849,7 @@ xcb_render_free_picture (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1654,6 +1920,7 @@ xcb_render_composite_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1724,10 +1991,40 @@ xcb_render_composite (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_render_trapezoids_sizeof (const void *_buffer /**< */,
+ uint32_t traps_len /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_render_trapezoids_request_t);
+ xcb_tmp += xcb_block_len;
+ /* traps */
+ xcb_block_len += traps_len * sizeof(xcb_render_trapezoid_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_render_trapezoid_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -1780,10 +2077,12 @@ xcb_render_trapezoids_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_render_trapezoid_t traps */
xcb_parts[4].iov_base = (char *) traps;
xcb_parts[4].iov_len = traps_len * sizeof(xcb_render_trapezoid_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1840,14 +2139,45 @@ xcb_render_trapezoids (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_render_trapezoid_t traps */
xcb_parts[4].iov_base = (char *) traps;
xcb_parts[4].iov_len = traps_len * sizeof(xcb_render_trapezoid_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_render_triangles_sizeof (const void *_buffer /**< */,
+ uint32_t triangles_len /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_render_triangles_request_t);
+ xcb_tmp += xcb_block_len;
+ /* triangles */
+ xcb_block_len += triangles_len * sizeof(xcb_render_triangle_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_render_triangle_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -1900,10 +2230,12 @@ xcb_render_triangles_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_render_triangle_t triangles */
xcb_parts[4].iov_base = (char *) triangles;
xcb_parts[4].iov_len = triangles_len * sizeof(xcb_render_triangle_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1960,14 +2292,45 @@ xcb_render_triangles (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_render_triangle_t triangles */
xcb_parts[4].iov_base = (char *) triangles;
xcb_parts[4].iov_len = triangles_len * sizeof(xcb_render_triangle_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_render_tri_strip_sizeof (const void *_buffer /**< */,
+ uint32_t points_len /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_render_tri_strip_request_t);
+ xcb_tmp += xcb_block_len;
+ /* points */
+ xcb_block_len += points_len * sizeof(xcb_render_pointfix_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_render_pointfix_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -2020,10 +2383,12 @@ xcb_render_tri_strip_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_render_pointfix_t points */
xcb_parts[4].iov_base = (char *) points;
xcb_parts[4].iov_len = points_len * sizeof(xcb_render_pointfix_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2080,14 +2445,45 @@ xcb_render_tri_strip (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_render_pointfix_t points */
xcb_parts[4].iov_base = (char *) points;
xcb_parts[4].iov_len = points_len * sizeof(xcb_render_pointfix_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_render_tri_fan_sizeof (const void *_buffer /**< */,
+ uint32_t points_len /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_render_tri_fan_request_t);
+ xcb_tmp += xcb_block_len;
+ /* points */
+ xcb_block_len += points_len * sizeof(xcb_render_pointfix_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_render_pointfix_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -2140,10 +2536,12 @@ xcb_render_tri_fan_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_render_pointfix_t points */
xcb_parts[4].iov_base = (char *) points;
xcb_parts[4].iov_len = points_len * sizeof(xcb_render_pointfix_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2200,10 +2598,12 @@ xcb_render_tri_fan (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_render_pointfix_t points */
xcb_parts[4].iov_base = (char *) points;
xcb_parts[4].iov_len = points_len * sizeof(xcb_render_pointfix_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2243,6 +2643,7 @@ xcb_render_create_glyph_set_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2282,6 +2683,7 @@ xcb_render_create_glyph_set (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2321,6 +2723,7 @@ xcb_render_reference_glyph_set_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2360,6 +2763,7 @@ xcb_render_reference_glyph_set (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2396,6 +2800,7 @@ xcb_render_free_glyph_set_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2432,10 +2837,65 @@ xcb_render_free_glyph_set (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_render_add_glyphs_sizeof (const void *_buffer /**< */,
+ uint32_t data_len /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_render_add_glyphs_request_t *_aux = (xcb_render_add_glyphs_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_render_add_glyphs_request_t);
+ xcb_tmp += xcb_block_len;
+ /* glyphids */
+ xcb_block_len += _aux->glyphs_len * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* glyphs */
+ xcb_block_len += _aux->glyphs_len * sizeof(xcb_render_glyphinfo_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_render_glyphinfo_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* data */
+ xcb_block_len += data_len * sizeof(uint8_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -2479,18 +2939,22 @@ xcb_render_add_glyphs_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint32_t glyphids */
xcb_parts[4].iov_base = (char *) glyphids;
xcb_parts[4].iov_len = glyphs_len * sizeof(uint32_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+ /* xcb_render_glyphinfo_t glyphs */
xcb_parts[6].iov_base = (char *) glyphs;
xcb_parts[6].iov_len = glyphs_len * sizeof(xcb_render_glyphinfo_t);
xcb_parts[7].iov_base = 0;
xcb_parts[7].iov_len = -xcb_parts[6].iov_len & 3;
+ /* uint8_t data */
xcb_parts[8].iov_base = (char *) data;
xcb_parts[8].iov_len = data_len * sizeof(uint8_t);
xcb_parts[9].iov_base = 0;
xcb_parts[9].iov_len = -xcb_parts[8].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2538,22 +3002,55 @@ xcb_render_add_glyphs (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint32_t glyphids */
xcb_parts[4].iov_base = (char *) glyphids;
xcb_parts[4].iov_len = glyphs_len * sizeof(uint32_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+ /* xcb_render_glyphinfo_t glyphs */
xcb_parts[6].iov_base = (char *) glyphs;
xcb_parts[6].iov_len = glyphs_len * sizeof(xcb_render_glyphinfo_t);
xcb_parts[7].iov_base = 0;
xcb_parts[7].iov_len = -xcb_parts[6].iov_len & 3;
+ /* uint8_t data */
xcb_parts[8].iov_base = (char *) data;
xcb_parts[8].iov_len = data_len * sizeof(uint8_t);
xcb_parts[9].iov_base = 0;
xcb_parts[9].iov_len = -xcb_parts[8].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_render_free_glyphs_sizeof (const void *_buffer /**< */,
+ uint32_t glyphs_len /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_render_free_glyphs_request_t);
+ xcb_tmp += xcb_block_len;
+ /* glyphs */
+ xcb_block_len += glyphs_len * sizeof(xcb_render_glyph_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_render_glyph_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -2590,10 +3087,12 @@ xcb_render_free_glyphs_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_render_glyph_t glyphs */
xcb_parts[4].iov_base = (char *) glyphs;
xcb_parts[4].iov_len = glyphs_len * sizeof(xcb_render_glyph_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2634,14 +3133,45 @@ xcb_render_free_glyphs (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_render_glyph_t glyphs */
xcb_parts[4].iov_base = (char *) glyphs;
xcb_parts[4].iov_len = glyphs_len * sizeof(xcb_render_glyph_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_render_composite_glyphs_8_sizeof (const void *_buffer /**< */,
+ uint32_t glyphcmds_len /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_render_composite_glyphs_8_request_t);
+ xcb_tmp += xcb_block_len;
+ /* glyphcmds */
+ xcb_block_len += glyphcmds_len * sizeof(uint8_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -2697,10 +3227,12 @@ xcb_render_composite_glyphs_8_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint8_t glyphcmds */
xcb_parts[4].iov_base = (char *) glyphcmds;
xcb_parts[4].iov_len = glyphcmds_len * sizeof(uint8_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2760,14 +3292,45 @@ xcb_render_composite_glyphs_8 (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint8_t glyphcmds */
xcb_parts[4].iov_base = (char *) glyphcmds;
xcb_parts[4].iov_len = glyphcmds_len * sizeof(uint8_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_render_composite_glyphs_16_sizeof (const void *_buffer /**< */,
+ uint32_t glyphcmds_len /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_render_composite_glyphs_16_request_t);
+ xcb_tmp += xcb_block_len;
+ /* glyphcmds */
+ xcb_block_len += glyphcmds_len * sizeof(uint8_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -2823,10 +3386,12 @@ xcb_render_composite_glyphs_16_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint8_t glyphcmds */
xcb_parts[4].iov_base = (char *) glyphcmds;
xcb_parts[4].iov_len = glyphcmds_len * sizeof(uint8_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2886,14 +3451,45 @@ xcb_render_composite_glyphs_16 (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint8_t glyphcmds */
xcb_parts[4].iov_base = (char *) glyphcmds;
xcb_parts[4].iov_len = glyphcmds_len * sizeof(uint8_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_render_composite_glyphs_32_sizeof (const void *_buffer /**< */,
+ uint32_t glyphcmds_len /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_render_composite_glyphs_32_request_t);
+ xcb_tmp += xcb_block_len;
+ /* glyphcmds */
+ xcb_block_len += glyphcmds_len * sizeof(uint8_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -2949,10 +3545,12 @@ xcb_render_composite_glyphs_32_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint8_t glyphcmds */
xcb_parts[4].iov_base = (char *) glyphcmds;
xcb_parts[4].iov_len = glyphcmds_len * sizeof(uint8_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3012,14 +3610,45 @@ xcb_render_composite_glyphs_32 (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint8_t glyphcmds */
xcb_parts[4].iov_base = (char *) glyphcmds;
xcb_parts[4].iov_len = glyphcmds_len * sizeof(uint8_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_render_fill_rectangles_sizeof (const void *_buffer /**< */,
+ uint32_t rects_len /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_render_fill_rectangles_request_t);
+ xcb_tmp += xcb_block_len;
+ /* rects */
+ xcb_block_len += rects_len * sizeof(xcb_rectangle_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_rectangle_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -3063,10 +3692,12 @@ xcb_render_fill_rectangles_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_rectangle_t rects */
xcb_parts[4].iov_base = (char *) rects;
xcb_parts[4].iov_len = rects_len * sizeof(xcb_rectangle_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3114,10 +3745,12 @@ xcb_render_fill_rectangles (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_rectangle_t rects */
xcb_parts[4].iov_base = (char *) rects;
xcb_parts[4].iov_len = rects_len * sizeof(xcb_rectangle_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3163,6 +3796,7 @@ xcb_render_create_cursor_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3208,6 +3842,7 @@ xcb_render_create_cursor (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3285,6 +3920,7 @@ xcb_render_set_picture_transform_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3324,10 +3960,57 @@ xcb_render_set_picture_transform (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_render_query_filters_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_render_query_filters_reply_t *_aux = (xcb_render_query_filters_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+ unsigned int i;
+ unsigned int xcb_tmp_len;
+
+ xcb_block_len += sizeof(xcb_render_query_filters_reply_t);
+ xcb_tmp += xcb_block_len;
+ /* aliases */
+ xcb_block_len += _aux->num_aliases * sizeof(uint16_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* filters */
+ for(i=0; i<_aux->num_filters; i++) {
+ xcb_tmp_len = xcb_str_sizeof(xcb_tmp);
+ xcb_block_len += xcb_tmp_len;
+ xcb_tmp += xcb_tmp_len;
+ }
+ xcb_align_to = ALIGNOF(xcb_str_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -3360,6 +4043,7 @@ xcb_render_query_filters (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3396,6 +4080,7 @@ xcb_render_query_filters_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3509,6 +4194,48 @@ xcb_render_query_filters_reply (xcb_connection_t *c /**< */,
return (xcb_render_query_filters_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
}
+int
+xcb_render_set_picture_filter_sizeof (const void *_buffer /**< */,
+ uint32_t values_len /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_render_set_picture_filter_request_t *_aux = (xcb_render_set_picture_filter_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_render_set_picture_filter_request_t);
+ xcb_tmp += xcb_block_len;
+ /* filter */
+ xcb_block_len += _aux->filter_len * sizeof(char);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* values */
+ xcb_block_len += values_len * sizeof(xcb_render_fixed_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_render_fixed_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -3551,14 +4278,17 @@ xcb_render_set_picture_filter_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* char filter */
xcb_parts[4].iov_base = (char *) filter;
xcb_parts[4].iov_len = filter_len * sizeof(char);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+ /* xcb_render_fixed_t values */
xcb_parts[6].iov_base = (char *) values;
xcb_parts[6].iov_len = values_len * sizeof(xcb_render_fixed_t);
xcb_parts[7].iov_base = 0;
xcb_parts[7].iov_len = -xcb_parts[6].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3605,14 +4335,17 @@ xcb_render_set_picture_filter (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* char filter */
xcb_parts[4].iov_base = (char *) filter;
xcb_parts[4].iov_len = filter_len * sizeof(char);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+ /* xcb_render_fixed_t values */
xcb_parts[6].iov_base = (char *) values;
xcb_parts[6].iov_len = values_len * sizeof(xcb_render_fixed_t);
xcb_parts[7].iov_base = 0;
xcb_parts[7].iov_len = -xcb_parts[6].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3655,6 +4388,35 @@ xcb_render_animcursorelt_end (xcb_render_animcursorelt_iterator_t i /**< */)
return ret;
}
+int
+xcb_render_create_anim_cursor_sizeof (const void *_buffer /**< */,
+ uint32_t cursors_len /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_render_create_anim_cursor_request_t);
+ xcb_tmp += xcb_block_len;
+ /* cursors */
+ xcb_block_len += cursors_len * sizeof(xcb_render_animcursorelt_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_render_animcursorelt_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -3691,10 +4453,12 @@ xcb_render_create_anim_cursor_checked (xcb_connection_t *c /**<
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_render_animcursorelt_t cursors */
xcb_parts[4].iov_base = (char *) cursors;
xcb_parts[4].iov_len = cursors_len * sizeof(xcb_render_animcursorelt_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3735,10 +4499,12 @@ xcb_render_create_anim_cursor (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_render_animcursorelt_t cursors */
xcb_parts[4].iov_base = (char *) cursors;
xcb_parts[4].iov_len = cursors_len * sizeof(xcb_render_animcursorelt_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3819,6 +4585,35 @@ xcb_render_trap_end (xcb_render_trap_iterator_t i /**< */)
return ret;
}
+int
+xcb_render_add_traps_sizeof (const void *_buffer /**< */,
+ uint32_t traps_len /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_render_add_traps_request_t);
+ xcb_tmp += xcb_block_len;
+ /* traps */
+ xcb_block_len += traps_len * sizeof(xcb_render_trap_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_render_trap_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -3861,10 +4656,12 @@ xcb_render_add_traps_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_render_trap_t traps */
xcb_parts[4].iov_base = (char *) traps;
xcb_parts[4].iov_len = traps_len * sizeof(xcb_render_trap_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3911,10 +4708,12 @@ xcb_render_add_traps (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_render_trap_t traps */
xcb_parts[4].iov_base = (char *) traps;
xcb_parts[4].iov_len = traps_len * sizeof(xcb_render_trap_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3954,6 +4753,7 @@ xcb_render_create_solid_fill_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -3993,10 +4793,52 @@ xcb_render_create_solid_fill (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_render_create_linear_gradient_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_render_create_linear_gradient_request_t *_aux = (xcb_render_create_linear_gradient_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_render_create_linear_gradient_request_t);
+ xcb_tmp += xcb_block_len;
+ /* stops */
+ xcb_block_len += _aux->num_stops * sizeof(xcb_render_fixed_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_render_fixed_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* colors */
+ xcb_block_len += _aux->num_stops * sizeof(xcb_render_color_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_render_color_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -4042,14 +4884,17 @@ xcb_render_create_linear_gradient_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_render_fixed_t stops */
xcb_parts[4].iov_base = (char *) stops;
xcb_parts[4].iov_len = num_stops * sizeof(xcb_render_fixed_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+ /* xcb_render_color_t colors */
xcb_parts[6].iov_base = (char *) colors;
xcb_parts[6].iov_len = num_stops * sizeof(xcb_render_color_t);
xcb_parts[7].iov_base = 0;
xcb_parts[7].iov_len = -xcb_parts[6].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -4099,18 +4944,62 @@ xcb_render_create_linear_gradient (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_render_fixed_t stops */
xcb_parts[4].iov_base = (char *) stops;
xcb_parts[4].iov_len = num_stops * sizeof(xcb_render_fixed_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+ /* xcb_render_color_t colors */
xcb_parts[6].iov_base = (char *) colors;
xcb_parts[6].iov_len = num_stops * sizeof(xcb_render_color_t);
xcb_parts[7].iov_base = 0;
xcb_parts[7].iov_len = -xcb_parts[6].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_render_create_radial_gradient_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_render_create_radial_gradient_request_t *_aux = (xcb_render_create_radial_gradient_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_render_create_radial_gradient_request_t);
+ xcb_tmp += xcb_block_len;
+ /* stops */
+ xcb_block_len += _aux->num_stops * sizeof(xcb_render_fixed_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_render_fixed_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* colors */
+ xcb_block_len += _aux->num_stops * sizeof(xcb_render_color_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_render_color_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -4162,14 +5051,17 @@ xcb_render_create_radial_gradient_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_render_fixed_t stops */
xcb_parts[4].iov_base = (char *) stops;
xcb_parts[4].iov_len = num_stops * sizeof(xcb_render_fixed_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+ /* xcb_render_color_t colors */
xcb_parts[6].iov_base = (char *) colors;
xcb_parts[6].iov_len = num_stops * sizeof(xcb_render_color_t);
xcb_parts[7].iov_base = 0;
xcb_parts[7].iov_len = -xcb_parts[6].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -4225,18 +5117,62 @@ xcb_render_create_radial_gradient (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_render_fixed_t stops */
xcb_parts[4].iov_base = (char *) stops;
xcb_parts[4].iov_len = num_stops * sizeof(xcb_render_fixed_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+ /* xcb_render_color_t colors */
xcb_parts[6].iov_base = (char *) colors;
xcb_parts[6].iov_len = num_stops * sizeof(xcb_render_color_t);
xcb_parts[7].iov_base = 0;
xcb_parts[7].iov_len = -xcb_parts[6].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_render_create_conical_gradient_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_render_create_conical_gradient_request_t *_aux = (xcb_render_create_conical_gradient_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_render_create_conical_gradient_request_t);
+ xcb_tmp += xcb_block_len;
+ /* stops */
+ xcb_block_len += _aux->num_stops * sizeof(xcb_render_fixed_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_render_fixed_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* colors */
+ xcb_block_len += _aux->num_stops * sizeof(xcb_render_color_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_render_color_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -4282,14 +5218,17 @@ xcb_render_create_conical_gradient_checked (xcb_connection_t *c /**< */
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_render_fixed_t stops */
xcb_parts[4].iov_base = (char *) stops;
xcb_parts[4].iov_len = num_stops * sizeof(xcb_render_fixed_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+ /* xcb_render_color_t colors */
xcb_parts[6].iov_base = (char *) colors;
xcb_parts[6].iov_len = num_stops * sizeof(xcb_render_color_t);
xcb_parts[7].iov_base = 0;
xcb_parts[7].iov_len = -xcb_parts[6].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -4339,14 +5278,17 @@ xcb_render_create_conical_gradient (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_render_fixed_t stops */
xcb_parts[4].iov_base = (char *) stops;
xcb_parts[4].iov_len = num_stops * sizeof(xcb_render_fixed_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+ /* xcb_render_color_t colors */
xcb_parts[6].iov_base = (char *) colors;
xcb_parts[6].iov_len = num_stops * sizeof(xcb_render_color_t);
xcb_parts[7].iov_base = 0;
xcb_parts[7].iov_len = -xcb_parts[6].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
diff --git a/src/3rdparty/xcb/libxcb/shape.c b/src/3rdparty/xcb/libxcb/shape.c
index 948522581e..98621c4983 100644
--- a/src/3rdparty/xcb/libxcb/shape.c
+++ b/src/3rdparty/xcb/libxcb/shape.c
@@ -3,10 +3,17 @@
* Edit at your peril.
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
+#include <stddef.h> /* for offsetof() */
#include "xcbext.h"
#include "shape.h"
+
+#define ALIGNOF(type) offsetof(struct { char dummy; type member; }, member)
#include "xproto.h"
xcb_extension_t xcb_shape_id = { "SHAPE", 0 };
@@ -116,6 +123,7 @@ xcb_shape_query_version (xcb_connection_t *c /**< */)
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -149,6 +157,7 @@ xcb_shape_query_version_unchecked (xcb_connection_t *c /**< */)
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -173,6 +182,35 @@ xcb_shape_query_version_reply (xcb_connection_t *c /**< */,
return (xcb_shape_query_version_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
}
+int
+xcb_shape_rectangles_sizeof (const void *_buffer /**< */,
+ uint32_t rectangles_len /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_shape_rectangles_request_t);
+ xcb_tmp += xcb_block_len;
+ /* rectangles */
+ xcb_block_len += rectangles_len * sizeof(xcb_rectangle_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_rectangle_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -225,10 +263,12 @@ xcb_shape_rectangles_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_rectangle_t rectangles */
xcb_parts[4].iov_base = (char *) rectangles;
xcb_parts[4].iov_len = rectangles_len * sizeof(xcb_rectangle_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -285,10 +325,12 @@ xcb_shape_rectangles (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_rectangle_t rectangles */
xcb_parts[4].iov_base = (char *) rectangles;
xcb_parts[4].iov_len = rectangles_len * sizeof(xcb_rectangle_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -341,6 +383,7 @@ xcb_shape_mask_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -393,6 +436,7 @@ xcb_shape_mask (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -448,6 +492,7 @@ xcb_shape_combine_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -503,6 +548,7 @@ xcb_shape_combine (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -549,6 +595,7 @@ xcb_shape_offset_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -595,6 +642,7 @@ xcb_shape_offset (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -631,6 +679,7 @@ xcb_shape_query_extents (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -667,6 +716,7 @@ xcb_shape_query_extents_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -727,6 +777,7 @@ xcb_shape_select_input_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -767,6 +818,7 @@ xcb_shape_select_input (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -803,6 +855,7 @@ xcb_shape_input_selected (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -839,6 +892,7 @@ xcb_shape_input_selected_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -863,6 +917,35 @@ xcb_shape_input_selected_reply (xcb_connection_t *c /**< */,
return (xcb_shape_input_selected_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
}
+int
+xcb_shape_get_rectangles_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_shape_get_rectangles_reply_t *_aux = (xcb_shape_get_rectangles_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_shape_get_rectangles_reply_t);
+ xcb_tmp += xcb_block_len;
+ /* rectangles */
+ xcb_block_len += _aux->rectangles_len * sizeof(xcb_rectangle_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_rectangle_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -899,6 +982,7 @@ xcb_shape_get_rectangles (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -939,6 +1023,7 @@ xcb_shape_get_rectangles_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
diff --git a/src/3rdparty/xcb/libxcb/shm.c b/src/3rdparty/xcb/libxcb/shm.c
index c1637a8654..0a1c238732 100644
--- a/src/3rdparty/xcb/libxcb/shm.c
+++ b/src/3rdparty/xcb/libxcb/shm.c
@@ -3,10 +3,17 @@
* Edit at your peril.
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
+#include <stddef.h> /* for offsetof() */
#include "xcbext.h"
#include "shm.h"
+
+#define ALIGNOF(type) offsetof(struct { char dummy; type member; }, member)
#include "xproto.h"
xcb_extension_t xcb_shm_id = { "MIT-SHM", 0 };
@@ -78,6 +85,7 @@ xcb_shm_query_version (xcb_connection_t *c /**< */)
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -111,6 +119,7 @@ xcb_shm_query_version_unchecked (xcb_connection_t *c /**< */)
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -174,6 +183,7 @@ xcb_shm_attach_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -217,6 +227,7 @@ xcb_shm_attach (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -253,6 +264,7 @@ xcb_shm_detach_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -289,6 +301,7 @@ xcb_shm_detach (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -368,6 +381,7 @@ xcb_shm_put_image_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -447,6 +461,7 @@ xcb_shm_put_image (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -508,6 +523,7 @@ xcb_shm_get_image (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -569,6 +585,7 @@ xcb_shm_get_image_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -644,6 +661,7 @@ xcb_shm_create_pixmap_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -699,6 +717,7 @@ xcb_shm_create_pixmap (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
diff --git a/src/3rdparty/xcb/libxcb/support_libxcb_versions_where_xcb_sumof_not_available.patch b/src/3rdparty/xcb/libxcb/support_libxcb_versions_where_xcb_sumof_not_available.patch
deleted file mode 100644
index a73e633e73..0000000000
--- a/src/3rdparty/xcb/libxcb/support_libxcb_versions_where_xcb_sumof_not_available.patch
+++ /dev/null
@@ -1,273 +0,0 @@
-diff --git a/src/3rdparty/xcb/libxcb/support_libxcb_versions_where_xcb_sumof_not_available.patch b/src/3rdparty/xcb/libxcb/support_libxcb_versions_where_xcb_sumof_not_available.patch
-index f63719d..e69de29 100644
---- a/src/3rdparty/xcb/libxcb/support_libxcb_versions_where_xcb_sumof_not_available.patch
-+++ b/src/3rdparty/xcb/libxcb/support_libxcb_versions_where_xcb_sumof_not_available.patch
-@@ -1,134 +0,0 @@
--diff --git a/src/3rdparty/xcb/libxcb/xkb.c b/src/3rdparty/xcb/libxcb/xkb.c
--index d55bd76..2e3a24a 100644
----- a/src/3rdparty/xcb/libxcb/xkb.c
--+++ b/src/3rdparty/xcb/libxcb/xkb.c
--@@ -18,6 +18,15 @@
--
-- xcb_extension_t xcb_xkb_id = { "XKEYBOARD", 0 };
--
--+int qt_xcb_sumof(uint8_t *list, int len)
--+{
--+ int i, s = 0;
--+ for(i=0; i<len; i++) {
--+ s += *list;
--+ list++;
--+ }
--+ return s;
--+}
--
-- /*****************************************************************************
-- **
--@@ -9025,7 +9034,7 @@ int
-- xcb_xkb_get_names_value_list_kt_level_names_length (const xcb_xkb_get_names_reply_t *R /**< */,
-- const xcb_xkb_get_names_value_list_t *S /**< */)
-- {
--- return xcb_sumof(/* valueList */ S->nLevelsPerType, R->nTypes);
--+ return (/* valueList */ S->nLevelsPerType, R->nTypes);
-- }
--
--
--@@ -9043,7 +9052,7 @@ xcb_xkb_get_names_value_list_kt_level_names_end (const xcb_xkb_get_names_reply_t
-- const xcb_xkb_get_names_value_list_t *S /**< */)
-- {
-- xcb_generic_iterator_t i;
--- i.data = /* valueList */ S->ktLevelNames + xcb_sumof(/* valueList */ S->nLevelsPerType, R->nTypes);
--+ i.data = /* valueList */ S->ktLevelNames + qt_xcb_sumof(/* valueList */ S->nLevelsPerType, R->nTypes);
-- i.rem = 0;
-- i.index = (char *) i.data - (char *) S;
-- return i;
--@@ -9508,8 +9517,8 @@ xcb_xkb_get_names_value_list_serialize (void **_
-- xcb_block_len = 0;
-- /* ktLevelNames */
-- xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->ktLevelNames;
--- xcb_block_len += xcb_sumof(_aux->nLevelsPerType, nTypes) * sizeof(xcb_atom_t);
--- xcb_parts[xcb_parts_idx].iov_len = xcb_sumof(_aux->nLevelsPerType, nTypes) * sizeof(xcb_atom_t);
--+ xcb_block_len += qt_xcb_sumof(_aux->nLevelsPerType, nTypes) * sizeof(xcb_atom_t);
--+ xcb_parts[xcb_parts_idx].iov_len = qt_xcb_sumof(_aux->nLevelsPerType, nTypes) * sizeof(xcb_atom_t);
-- xcb_parts_idx++;
-- xcb_align_to = ALIGNOF(xcb_atom_t);
-- }
--@@ -9762,7 +9771,7 @@ xcb_xkb_get_names_value_list_unpack (const void *_buffer /
-- xcb_block_len = 0;
-- /* ktLevelNames */
-- _aux->ktLevelNames = (xcb_atom_t *)xcb_tmp;
--- xcb_block_len += xcb_sumof(_aux->nLevelsPerType, nTypes) * sizeof(xcb_atom_t);
--+ xcb_block_len += qt_xcb_sumof(_aux->nLevelsPerType, nTypes) * sizeof(xcb_atom_t);
-- xcb_tmp += xcb_block_len;
-- xcb_align_to = ALIGNOF(xcb_atom_t);
-- }
--@@ -10139,7 +10148,7 @@ int
-- xcb_xkb_set_names_values_kt_level_names_length (const xcb_xkb_set_names_request_t *R /**< */,
-- const xcb_xkb_set_names_values_t *S /**< */)
-- {
--- return xcb_sumof(/* values */ S->nLevelsPerType, R->nKTLevels);
--+ return qt_xcb_sumof(/* values */ S->nLevelsPerType, R->nKTLevels);
-- }
--
--
--@@ -10157,7 +10166,7 @@ xcb_xkb_set_names_values_kt_level_names_end (const xcb_xkb_set_names_request_t *
-- const xcb_xkb_set_names_values_t *S /**< */)
-- {
-- xcb_generic_iterator_t i;
--- i.data = /* values */ S->ktLevelNames + xcb_sumof(/* values */ S->nLevelsPerType, R->nKTLevels);
--+ i.data = /* values */ S->ktLevelNames + qt_xcb_sumof(/* values */ S->nLevelsPerType, R->nKTLevels);
-- i.rem = 0;
-- i.index = (char *) i.data - (char *) S;
-- return i;
--@@ -10607,8 +10616,8 @@ xcb_xkb_set_names_values_serialize (void **_buffer
-- xcb_block_len = 0;
-- /* ktLevelNames */
-- xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->ktLevelNames;
--- xcb_block_len += xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
--- xcb_parts[xcb_parts_idx].iov_len = xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
--+ xcb_block_len += qt_xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
--+ xcb_parts[xcb_parts_idx].iov_len = qt_xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
-- xcb_parts_idx++;
-- xcb_align_to = ALIGNOF(xcb_atom_t);
-- }
--@@ -10849,7 +10858,7 @@ xcb_xkb_set_names_values_unpack (const void *_buffer /**< */,
-- xcb_block_len = 0;
-- /* ktLevelNames */
-- _aux->ktLevelNames = (xcb_atom_t *)xcb_tmp;
--- xcb_block_len += xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
--+ xcb_block_len += qt_xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
-- xcb_tmp += xcb_block_len;
-- xcb_align_to = ALIGNOF(xcb_atom_t);
-- }
--@@ -12872,7 +12881,7 @@ int
-- xcb_xkb_get_kbd_by_name_replies_key_names_value_list_kt_level_names_length (const xcb_xkb_get_kbd_by_name_reply_t *R /**< */,
-- const xcb_xkb_get_kbd_by_name_replies_t *S /**< */)
-- {
--- return xcb_sumof(/* replies */ S->key_names.valueList.nLevelsPerType, /* replies */ S->key_names.nKTLevels);
--+ return qt_xcb_sumof(/* replies */ S->key_names.valueList.nLevelsPerType, /* replies */ S->key_names.nKTLevels);
-- }
--
--
--@@ -12890,7 +12899,7 @@ xcb_xkb_get_kbd_by_name_replies_key_names_value_list_kt_level_names_end (const x
-- const xcb_xkb_get_kbd_by_name_replies_t *S /**< */)
-- {
-- xcb_generic_iterator_t i;
--- i.data = /* replies */ S->key_names.valueList.ktLevelNames + xcb_sumof(/* replies */ S->key_names.valueList.nLevelsPerType, /* replies */ S->key_names.nKTLevels);
--+ i.data = /* replies */ S->key_names.valueList.ktLevelNames + qt_xcb_sumof(/* replies */ S->key_names.valueList.nLevelsPerType, /* replies */ S->key_names.nKTLevels);
-- i.rem = 0;
-- i.index = (char *) i.data - (char *) S;
-- return i;
--@@ -13340,8 +13349,8 @@ xcb_xkb_get_kbd_by_name_replies_key_names_value_list_serialize (void
-- xcb_block_len = 0;
-- /* ktLevelNames */
-- xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->ktLevelNames;
--- xcb_block_len += xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
--- xcb_parts[xcb_parts_idx].iov_len = xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
--+ xcb_block_len += qt_xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
--+ xcb_parts[xcb_parts_idx].iov_len = qt_xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
-- xcb_parts_idx++;
-- xcb_align_to = ALIGNOF(xcb_atom_t);
-- }
--@@ -13582,7 +13591,7 @@ xcb_xkb_get_kbd_by_name_replies_key_names_value_list_unpack (const void
-- xcb_block_len = 0;
-- /* ktLevelNames */
-- _aux->ktLevelNames = (xcb_atom_t *)xcb_tmp;
--- xcb_block_len += xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
--+ xcb_block_len += qt_xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
-- xcb_tmp += xcb_block_len;
-- xcb_align_to = ALIGNOF(xcb_atom_t);
-- }
-diff --git a/src/3rdparty/xcb/libxcb/xkb.c b/src/3rdparty/xcb/libxcb/xkb.c
-index d55bd76..ff025f6 100644
---- a/src/3rdparty/xcb/libxcb/xkb.c
-+++ b/src/3rdparty/xcb/libxcb/xkb.c
-@@ -18,6 +18,15 @@
-
- xcb_extension_t xcb_xkb_id = { "XKEYBOARD", 0 };
-
-+int qt_xcb_sumof(uint8_t *list, int len)
-+{
-+ int i, s = 0;
-+ for(i=0; i<len; i++) {
-+ s += *list;
-+ list++;
-+ }
-+ return s;
-+}
-
- /*****************************************************************************
- **
-@@ -9025,7 +9034,7 @@ int
- xcb_xkb_get_names_value_list_kt_level_names_length (const xcb_xkb_get_names_reply_t *R /**< */,
- const xcb_xkb_get_names_value_list_t *S /**< */)
- {
-- return xcb_sumof(/* valueList */ S->nLevelsPerType, R->nTypes);
-+ return qt_xcb_sumof(/* valueList */ S->nLevelsPerType, R->nTypes);
- }
-
-
-@@ -9043,7 +9052,7 @@ xcb_xkb_get_names_value_list_kt_level_names_end (const xcb_xkb_get_names_reply_t
- const xcb_xkb_get_names_value_list_t *S /**< */)
- {
- xcb_generic_iterator_t i;
-- i.data = /* valueList */ S->ktLevelNames + xcb_sumof(/* valueList */ S->nLevelsPerType, R->nTypes);
-+ i.data = /* valueList */ S->ktLevelNames + qt_xcb_sumof(/* valueList */ S->nLevelsPerType, R->nTypes);
- i.rem = 0;
- i.index = (char *) i.data - (char *) S;
- return i;
-@@ -9508,8 +9517,8 @@ xcb_xkb_get_names_value_list_serialize (void **_
- xcb_block_len = 0;
- /* ktLevelNames */
- xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->ktLevelNames;
-- xcb_block_len += xcb_sumof(_aux->nLevelsPerType, nTypes) * sizeof(xcb_atom_t);
-- xcb_parts[xcb_parts_idx].iov_len = xcb_sumof(_aux->nLevelsPerType, nTypes) * sizeof(xcb_atom_t);
-+ xcb_block_len += qt_xcb_sumof(_aux->nLevelsPerType, nTypes) * sizeof(xcb_atom_t);
-+ xcb_parts[xcb_parts_idx].iov_len = qt_xcb_sumof(_aux->nLevelsPerType, nTypes) * sizeof(xcb_atom_t);
- xcb_parts_idx++;
- xcb_align_to = ALIGNOF(xcb_atom_t);
- }
-@@ -9762,7 +9771,7 @@ xcb_xkb_get_names_value_list_unpack (const void *_buffer /
- xcb_block_len = 0;
- /* ktLevelNames */
- _aux->ktLevelNames = (xcb_atom_t *)xcb_tmp;
-- xcb_block_len += xcb_sumof(_aux->nLevelsPerType, nTypes) * sizeof(xcb_atom_t);
-+ xcb_block_len += qt_xcb_sumof(_aux->nLevelsPerType, nTypes) * sizeof(xcb_atom_t);
- xcb_tmp += xcb_block_len;
- xcb_align_to = ALIGNOF(xcb_atom_t);
- }
-@@ -10139,7 +10148,7 @@ int
- xcb_xkb_set_names_values_kt_level_names_length (const xcb_xkb_set_names_request_t *R /**< */,
- const xcb_xkb_set_names_values_t *S /**< */)
- {
-- return xcb_sumof(/* values */ S->nLevelsPerType, R->nKTLevels);
-+ return qt_xcb_sumof(/* values */ S->nLevelsPerType, R->nKTLevels);
- }
-
-
-@@ -10157,7 +10166,7 @@ xcb_xkb_set_names_values_kt_level_names_end (const xcb_xkb_set_names_request_t *
- const xcb_xkb_set_names_values_t *S /**< */)
- {
- xcb_generic_iterator_t i;
-- i.data = /* values */ S->ktLevelNames + xcb_sumof(/* values */ S->nLevelsPerType, R->nKTLevels);
-+ i.data = /* values */ S->ktLevelNames + qt_xcb_sumof(/* values */ S->nLevelsPerType, R->nKTLevels);
- i.rem = 0;
- i.index = (char *) i.data - (char *) S;
- return i;
-@@ -10607,8 +10616,8 @@ xcb_xkb_set_names_values_serialize (void **_buffer
- xcb_block_len = 0;
- /* ktLevelNames */
- xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->ktLevelNames;
-- xcb_block_len += xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
-- xcb_parts[xcb_parts_idx].iov_len = xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
-+ xcb_block_len += qt_xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
-+ xcb_parts[xcb_parts_idx].iov_len = qt_xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
- xcb_parts_idx++;
- xcb_align_to = ALIGNOF(xcb_atom_t);
- }
-@@ -10849,7 +10858,7 @@ xcb_xkb_set_names_values_unpack (const void *_buffer /**< */,
- xcb_block_len = 0;
- /* ktLevelNames */
- _aux->ktLevelNames = (xcb_atom_t *)xcb_tmp;
-- xcb_block_len += xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
-+ xcb_block_len += qt_xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
- xcb_tmp += xcb_block_len;
- xcb_align_to = ALIGNOF(xcb_atom_t);
- }
-@@ -12872,7 +12881,7 @@ int
- xcb_xkb_get_kbd_by_name_replies_key_names_value_list_kt_level_names_length (const xcb_xkb_get_kbd_by_name_reply_t *R /**< */,
- const xcb_xkb_get_kbd_by_name_replies_t *S /**< */)
- {
-- return xcb_sumof(/* replies */ S->key_names.valueList.nLevelsPerType, /* replies */ S->key_names.nKTLevels);
-+ return qt_xcb_sumof(/* replies */ S->key_names.valueList.nLevelsPerType, /* replies */ S->key_names.nKTLevels);
- }
-
-
-@@ -12890,7 +12899,7 @@ xcb_xkb_get_kbd_by_name_replies_key_names_value_list_kt_level_names_end (const x
- const xcb_xkb_get_kbd_by_name_replies_t *S /**< */)
- {
- xcb_generic_iterator_t i;
-- i.data = /* replies */ S->key_names.valueList.ktLevelNames + xcb_sumof(/* replies */ S->key_names.valueList.nLevelsPerType, /* replies */ S->key_names.nKTLevels);
-+ i.data = /* replies */ S->key_names.valueList.ktLevelNames + qt_xcb_sumof(/* replies */ S->key_names.valueList.nLevelsPerType, /* replies */ S->key_names.nKTLevels);
- i.rem = 0;
- i.index = (char *) i.data - (char *) S;
- return i;
-@@ -13340,8 +13349,8 @@ xcb_xkb_get_kbd_by_name_replies_key_names_value_list_serialize (void
- xcb_block_len = 0;
- /* ktLevelNames */
- xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->ktLevelNames;
-- xcb_block_len += xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
-- xcb_parts[xcb_parts_idx].iov_len = xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
-+ xcb_block_len += qt_xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
-+ xcb_parts[xcb_parts_idx].iov_len = qt_xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
- xcb_parts_idx++;
- xcb_align_to = ALIGNOF(xcb_atom_t);
- }
-@@ -13582,7 +13591,7 @@ xcb_xkb_get_kbd_by_name_replies_key_names_value_list_unpack (const void
- xcb_block_len = 0;
- /* ktLevelNames */
- _aux->ktLevelNames = (xcb_atom_t *)xcb_tmp;
-- xcb_block_len += xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
-+ xcb_block_len += qt_xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
- xcb_tmp += xcb_block_len;
- xcb_align_to = ALIGNOF(xcb_atom_t);
- }
diff --git a/src/3rdparty/xcb/libxcb/sync.c b/src/3rdparty/xcb/libxcb/sync.c
index 408a263d2b..1f352756d8 100644
--- a/src/3rdparty/xcb/libxcb/sync.c
+++ b/src/3rdparty/xcb/libxcb/sync.c
@@ -3,10 +3,17 @@
* Edit at your peril.
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
+#include <stddef.h> /* for offsetof() */
#include "xcbext.h"
#include "sync.h"
+
+#define ALIGNOF(type) offsetof(struct { char dummy; type member; }, member)
#include "xproto.h"
xcb_extension_t xcb_sync_id = { "SYNC", 0 };
@@ -90,6 +97,44 @@ xcb_sync_counter_end (xcb_sync_counter_iterator_t i /**< */)
/*****************************************************************************
**
+ ** void xcb_sync_fence_next
+ **
+ ** @param xcb_sync_fence_iterator_t *i
+ ** @returns void
+ **
+ *****************************************************************************/
+
+void
+xcb_sync_fence_next (xcb_sync_fence_iterator_t *i /**< */)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_sync_fence_t);
+}
+
+
+/*****************************************************************************
+ **
+ ** xcb_generic_iterator_t xcb_sync_fence_end
+ **
+ ** @param xcb_sync_fence_iterator_t i
+ ** @returns xcb_generic_iterator_t
+ **
+ *****************************************************************************/
+
+xcb_generic_iterator_t
+xcb_sync_fence_end (xcb_sync_fence_iterator_t i /**< */)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+
+/*****************************************************************************
+ **
** void xcb_sync_int64_next
**
** @param xcb_sync_int64_iterator_t *i
@@ -125,6 +170,35 @@ xcb_sync_int64_end (xcb_sync_int64_iterator_t i /**< */)
return ret;
}
+int
+xcb_sync_systemcounter_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_sync_systemcounter_t *_aux = (xcb_sync_systemcounter_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_sync_systemcounter_t);
+ xcb_tmp += xcb_block_len;
+ /* name */
+ xcb_block_len += _aux->name_len * sizeof(char);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -191,10 +265,11 @@ void
xcb_sync_systemcounter_next (xcb_sync_systemcounter_iterator_t *i /**< */)
{
xcb_sync_systemcounter_t *R = i->data;
- xcb_generic_iterator_t child = xcb_sync_systemcounter_name_end(R);
+ xcb_generic_iterator_t child;
+ child.data = (xcb_sync_systemcounter_t *)(((char *)R) + xcb_sync_systemcounter_sizeof(R));
+ i->index = (char *) child.data - (char *) i->data;
--i->rem;
i->data = (xcb_sync_systemcounter_t *) child.data;
- i->index = child.index;
}
@@ -330,6 +405,7 @@ xcb_sync_initialize (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -369,6 +445,7 @@ xcb_sync_initialize_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -393,6 +470,40 @@ xcb_sync_initialize_reply (xcb_connection_t *c /**< */,
return (xcb_sync_initialize_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
}
+int
+xcb_sync_list_system_counters_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_sync_list_system_counters_reply_t *_aux = (xcb_sync_list_system_counters_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+ unsigned int i;
+ unsigned int xcb_tmp_len;
+
+ xcb_block_len += sizeof(xcb_sync_list_system_counters_reply_t);
+ xcb_tmp += xcb_block_len;
+ /* counters */
+ for(i=0; i<_aux->counters_len; i++) {
+ xcb_tmp_len = xcb_sync_systemcounter_sizeof(xcb_tmp);
+ xcb_block_len += xcb_tmp_len;
+ xcb_tmp += xcb_tmp_len;
+ }
+ xcb_align_to = ALIGNOF(xcb_sync_systemcounter_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -422,6 +533,7 @@ xcb_sync_list_system_counters (xcb_connection_t *c /**< */)
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -455,6 +567,7 @@ xcb_sync_list_system_counters_unchecked (xcb_connection_t *c /**< */)
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -550,6 +663,7 @@ xcb_sync_create_counter_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -589,6 +703,7 @@ xcb_sync_create_counter (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -625,6 +740,7 @@ xcb_sync_destroy_counter_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -661,6 +777,7 @@ xcb_sync_destroy_counter (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -697,6 +814,7 @@ xcb_sync_query_counter (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -733,6 +851,7 @@ xcb_sync_query_counter_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -757,6 +876,35 @@ xcb_sync_query_counter_reply (xcb_connection_t *c /**< */,
return (xcb_sync_query_counter_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
}
+int
+xcb_sync_await_sizeof (const void *_buffer /**< */,
+ uint32_t wait_list_len /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_sync_await_request_t);
+ xcb_tmp += xcb_block_len;
+ /* wait_list */
+ xcb_block_len += wait_list_len * sizeof(xcb_sync_waitcondition_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_sync_waitcondition_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -790,10 +938,12 @@ xcb_sync_await_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_sync_waitcondition_t wait_list */
xcb_parts[4].iov_base = (char *) wait_list;
xcb_parts[4].iov_len = wait_list_len * sizeof(xcb_sync_waitcondition_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -831,10 +981,12 @@ xcb_sync_await (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_sync_waitcondition_t wait_list */
xcb_parts[4].iov_base = (char *) wait_list;
xcb_parts[4].iov_len = wait_list_len * sizeof(xcb_sync_waitcondition_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -874,6 +1026,7 @@ xcb_sync_change_counter_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -913,6 +1066,7 @@ xcb_sync_change_counter (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -952,6 +1106,7 @@ xcb_sync_set_counter_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -991,10 +1146,40 @@ xcb_sync_set_counter (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_sync_create_alarm_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_sync_create_alarm_request_t *_aux = (xcb_sync_create_alarm_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_sync_create_alarm_request_t);
+ xcb_tmp += xcb_block_len;
+ /* value_list */
+ xcb_block_len += xcb_popcount(_aux->value_mask) * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -1032,10 +1217,12 @@ xcb_sync_create_alarm_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint32_t value_list */
xcb_parts[4].iov_base = (char *) value_list;
xcb_parts[4].iov_len = xcb_popcount(value_mask) * sizeof(uint32_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1077,14 +1264,45 @@ xcb_sync_create_alarm (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint32_t value_list */
xcb_parts[4].iov_base = (char *) value_list;
xcb_parts[4].iov_len = xcb_popcount(value_mask) * sizeof(uint32_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_sync_change_alarm_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_sync_change_alarm_request_t *_aux = (xcb_sync_change_alarm_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_sync_change_alarm_request_t);
+ xcb_tmp += xcb_block_len;
+ /* value_list */
+ xcb_block_len += xcb_popcount(_aux->value_mask) * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -1122,10 +1340,12 @@ xcb_sync_change_alarm_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint32_t value_list */
xcb_parts[4].iov_base = (char *) value_list;
xcb_parts[4].iov_len = xcb_popcount(value_mask) * sizeof(uint32_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1167,10 +1387,12 @@ xcb_sync_change_alarm (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint32_t value_list */
xcb_parts[4].iov_base = (char *) value_list;
xcb_parts[4].iov_len = xcb_popcount(value_mask) * sizeof(uint32_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1207,6 +1429,7 @@ xcb_sync_destroy_alarm_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1243,6 +1466,7 @@ xcb_sync_destroy_alarm (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1279,6 +1503,7 @@ xcb_sync_query_alarm (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1315,6 +1540,7 @@ xcb_sync_query_alarm_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1374,6 +1600,7 @@ xcb_sync_set_priority_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1413,6 +1640,7 @@ xcb_sync_set_priority (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1449,6 +1677,7 @@ xcb_sync_get_priority (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1485,6 +1714,7 @@ xcb_sync_get_priority_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1509,3 +1739,520 @@ xcb_sync_get_priority_reply (xcb_connection_t *c /**< */,
return (xcb_sync_get_priority_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
}
+
+/*****************************************************************************
+ **
+ ** xcb_void_cookie_t xcb_sync_create_fence_checked
+ **
+ ** @param xcb_connection_t *c
+ ** @param xcb_drawable_t drawable
+ ** @param xcb_sync_fence_t fence
+ ** @param uint8_t initially_triggered
+ ** @returns xcb_void_cookie_t
+ **
+ *****************************************************************************/
+
+xcb_void_cookie_t
+xcb_sync_create_fence_checked (xcb_connection_t *c /**< */,
+ xcb_drawable_t drawable /**< */,
+ xcb_sync_fence_t fence /**< */,
+ uint8_t initially_triggered /**< */)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ /* count */ 2,
+ /* ext */ &xcb_sync_id,
+ /* opcode */ XCB_SYNC_CREATE_FENCE,
+ /* isvoid */ 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_sync_create_fence_request_t xcb_out;
+
+ xcb_out.drawable = drawable;
+ xcb_out.fence = fence;
+ xcb_out.initially_triggered = initially_triggered;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+
+/*****************************************************************************
+ **
+ ** xcb_void_cookie_t xcb_sync_create_fence
+ **
+ ** @param xcb_connection_t *c
+ ** @param xcb_drawable_t drawable
+ ** @param xcb_sync_fence_t fence
+ ** @param uint8_t initially_triggered
+ ** @returns xcb_void_cookie_t
+ **
+ *****************************************************************************/
+
+xcb_void_cookie_t
+xcb_sync_create_fence (xcb_connection_t *c /**< */,
+ xcb_drawable_t drawable /**< */,
+ xcb_sync_fence_t fence /**< */,
+ uint8_t initially_triggered /**< */)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ /* count */ 2,
+ /* ext */ &xcb_sync_id,
+ /* opcode */ XCB_SYNC_CREATE_FENCE,
+ /* isvoid */ 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_sync_create_fence_request_t xcb_out;
+
+ xcb_out.drawable = drawable;
+ xcb_out.fence = fence;
+ xcb_out.initially_triggered = initially_triggered;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+
+/*****************************************************************************
+ **
+ ** xcb_void_cookie_t xcb_sync_trigger_fence_checked
+ **
+ ** @param xcb_connection_t *c
+ ** @param xcb_sync_fence_t fence
+ ** @returns xcb_void_cookie_t
+ **
+ *****************************************************************************/
+
+xcb_void_cookie_t
+xcb_sync_trigger_fence_checked (xcb_connection_t *c /**< */,
+ xcb_sync_fence_t fence /**< */)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ /* count */ 2,
+ /* ext */ &xcb_sync_id,
+ /* opcode */ XCB_SYNC_TRIGGER_FENCE,
+ /* isvoid */ 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_sync_trigger_fence_request_t xcb_out;
+
+ xcb_out.fence = fence;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+
+/*****************************************************************************
+ **
+ ** xcb_void_cookie_t xcb_sync_trigger_fence
+ **
+ ** @param xcb_connection_t *c
+ ** @param xcb_sync_fence_t fence
+ ** @returns xcb_void_cookie_t
+ **
+ *****************************************************************************/
+
+xcb_void_cookie_t
+xcb_sync_trigger_fence (xcb_connection_t *c /**< */,
+ xcb_sync_fence_t fence /**< */)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ /* count */ 2,
+ /* ext */ &xcb_sync_id,
+ /* opcode */ XCB_SYNC_TRIGGER_FENCE,
+ /* isvoid */ 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_sync_trigger_fence_request_t xcb_out;
+
+ xcb_out.fence = fence;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+
+/*****************************************************************************
+ **
+ ** xcb_void_cookie_t xcb_sync_reset_fence_checked
+ **
+ ** @param xcb_connection_t *c
+ ** @param xcb_sync_fence_t fence
+ ** @returns xcb_void_cookie_t
+ **
+ *****************************************************************************/
+
+xcb_void_cookie_t
+xcb_sync_reset_fence_checked (xcb_connection_t *c /**< */,
+ xcb_sync_fence_t fence /**< */)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ /* count */ 2,
+ /* ext */ &xcb_sync_id,
+ /* opcode */ XCB_SYNC_RESET_FENCE,
+ /* isvoid */ 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_sync_reset_fence_request_t xcb_out;
+
+ xcb_out.fence = fence;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+
+/*****************************************************************************
+ **
+ ** xcb_void_cookie_t xcb_sync_reset_fence
+ **
+ ** @param xcb_connection_t *c
+ ** @param xcb_sync_fence_t fence
+ ** @returns xcb_void_cookie_t
+ **
+ *****************************************************************************/
+
+xcb_void_cookie_t
+xcb_sync_reset_fence (xcb_connection_t *c /**< */,
+ xcb_sync_fence_t fence /**< */)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ /* count */ 2,
+ /* ext */ &xcb_sync_id,
+ /* opcode */ XCB_SYNC_RESET_FENCE,
+ /* isvoid */ 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_sync_reset_fence_request_t xcb_out;
+
+ xcb_out.fence = fence;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+
+/*****************************************************************************
+ **
+ ** xcb_void_cookie_t xcb_sync_destroy_fence_checked
+ **
+ ** @param xcb_connection_t *c
+ ** @param xcb_sync_fence_t fence
+ ** @returns xcb_void_cookie_t
+ **
+ *****************************************************************************/
+
+xcb_void_cookie_t
+xcb_sync_destroy_fence_checked (xcb_connection_t *c /**< */,
+ xcb_sync_fence_t fence /**< */)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ /* count */ 2,
+ /* ext */ &xcb_sync_id,
+ /* opcode */ XCB_SYNC_DESTROY_FENCE,
+ /* isvoid */ 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_sync_destroy_fence_request_t xcb_out;
+
+ xcb_out.fence = fence;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+
+/*****************************************************************************
+ **
+ ** xcb_void_cookie_t xcb_sync_destroy_fence
+ **
+ ** @param xcb_connection_t *c
+ ** @param xcb_sync_fence_t fence
+ ** @returns xcb_void_cookie_t
+ **
+ *****************************************************************************/
+
+xcb_void_cookie_t
+xcb_sync_destroy_fence (xcb_connection_t *c /**< */,
+ xcb_sync_fence_t fence /**< */)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ /* count */ 2,
+ /* ext */ &xcb_sync_id,
+ /* opcode */ XCB_SYNC_DESTROY_FENCE,
+ /* isvoid */ 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_sync_destroy_fence_request_t xcb_out;
+
+ xcb_out.fence = fence;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+
+/*****************************************************************************
+ **
+ ** xcb_sync_query_fence_cookie_t xcb_sync_query_fence
+ **
+ ** @param xcb_connection_t *c
+ ** @param xcb_sync_fence_t fence
+ ** @returns xcb_sync_query_fence_cookie_t
+ **
+ *****************************************************************************/
+
+xcb_sync_query_fence_cookie_t
+xcb_sync_query_fence (xcb_connection_t *c /**< */,
+ xcb_sync_fence_t fence /**< */)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ /* count */ 2,
+ /* ext */ &xcb_sync_id,
+ /* opcode */ XCB_SYNC_QUERY_FENCE,
+ /* isvoid */ 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_sync_query_fence_cookie_t xcb_ret;
+ xcb_sync_query_fence_request_t xcb_out;
+
+ xcb_out.fence = fence;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+
+/*****************************************************************************
+ **
+ ** xcb_sync_query_fence_cookie_t xcb_sync_query_fence_unchecked
+ **
+ ** @param xcb_connection_t *c
+ ** @param xcb_sync_fence_t fence
+ ** @returns xcb_sync_query_fence_cookie_t
+ **
+ *****************************************************************************/
+
+xcb_sync_query_fence_cookie_t
+xcb_sync_query_fence_unchecked (xcb_connection_t *c /**< */,
+ xcb_sync_fence_t fence /**< */)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ /* count */ 2,
+ /* ext */ &xcb_sync_id,
+ /* opcode */ XCB_SYNC_QUERY_FENCE,
+ /* isvoid */ 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_sync_query_fence_cookie_t xcb_ret;
+ xcb_sync_query_fence_request_t xcb_out;
+
+ xcb_out.fence = fence;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+
+/*****************************************************************************
+ **
+ ** xcb_sync_query_fence_reply_t * xcb_sync_query_fence_reply
+ **
+ ** @param xcb_connection_t *c
+ ** @param xcb_sync_query_fence_cookie_t cookie
+ ** @param xcb_generic_error_t **e
+ ** @returns xcb_sync_query_fence_reply_t *
+ **
+ *****************************************************************************/
+
+xcb_sync_query_fence_reply_t *
+xcb_sync_query_fence_reply (xcb_connection_t *c /**< */,
+ xcb_sync_query_fence_cookie_t cookie /**< */,
+ xcb_generic_error_t **e /**< */)
+{
+ return (xcb_sync_query_fence_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+int
+xcb_sync_await_fence_sizeof (const void *_buffer /**< */,
+ uint32_t fence_list_len /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_sync_await_fence_request_t);
+ xcb_tmp += xcb_block_len;
+ /* fence_list */
+ xcb_block_len += fence_list_len * sizeof(xcb_sync_fence_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_sync_fence_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+
+/*****************************************************************************
+ **
+ ** xcb_void_cookie_t xcb_sync_await_fence_checked
+ **
+ ** @param xcb_connection_t *c
+ ** @param uint32_t fence_list_len
+ ** @param const xcb_sync_fence_t *fence_list
+ ** @returns xcb_void_cookie_t
+ **
+ *****************************************************************************/
+
+xcb_void_cookie_t
+xcb_sync_await_fence_checked (xcb_connection_t *c /**< */,
+ uint32_t fence_list_len /**< */,
+ const xcb_sync_fence_t *fence_list /**< */)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ /* count */ 4,
+ /* ext */ &xcb_sync_id,
+ /* opcode */ XCB_SYNC_AWAIT_FENCE,
+ /* isvoid */ 1
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_void_cookie_t xcb_ret;
+ xcb_sync_await_fence_request_t xcb_out;
+
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_sync_fence_t fence_list */
+ xcb_parts[4].iov_base = (char *) fence_list;
+ xcb_parts[4].iov_len = fence_list_len * sizeof(xcb_sync_fence_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+
+/*****************************************************************************
+ **
+ ** xcb_void_cookie_t xcb_sync_await_fence
+ **
+ ** @param xcb_connection_t *c
+ ** @param uint32_t fence_list_len
+ ** @param const xcb_sync_fence_t *fence_list
+ ** @returns xcb_void_cookie_t
+ **
+ *****************************************************************************/
+
+xcb_void_cookie_t
+xcb_sync_await_fence (xcb_connection_t *c /**< */,
+ uint32_t fence_list_len /**< */,
+ const xcb_sync_fence_t *fence_list /**< */)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ /* count */ 4,
+ /* ext */ &xcb_sync_id,
+ /* opcode */ XCB_SYNC_AWAIT_FENCE,
+ /* isvoid */ 1
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_void_cookie_t xcb_ret;
+ xcb_sync_await_fence_request_t xcb_out;
+
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_sync_fence_t fence_list */
+ xcb_parts[4].iov_base = (char *) fence_list;
+ xcb_parts[4].iov_len = fence_list_len * sizeof(xcb_sync_fence_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
diff --git a/src/3rdparty/xcb/libxcb/xfixes.c b/src/3rdparty/xcb/libxcb/xfixes.c
index 541918ce16..4c0dc84b64 100644
--- a/src/3rdparty/xcb/libxcb/xfixes.c
+++ b/src/3rdparty/xcb/libxcb/xfixes.c
@@ -3,10 +3,17 @@
* Edit at your peril.
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
+#include <stddef.h> /* for offsetof() */
#include "xcbext.h"
#include "xfixes.h"
+
+#define ALIGNOF(type) offsetof(struct { char dummy; type member; }, member)
#include "xproto.h"
#include "render.h"
#include "shape.h"
@@ -48,6 +55,7 @@ xcb_xfixes_query_version (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -87,6 +95,7 @@ xcb_xfixes_query_version_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -153,6 +162,7 @@ xcb_xfixes_change_save_set_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -199,6 +209,7 @@ xcb_xfixes_change_save_set (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -241,6 +252,7 @@ xcb_xfixes_select_selection_input_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -283,6 +295,7 @@ xcb_xfixes_select_selection_input (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -322,6 +335,7 @@ xcb_xfixes_select_cursor_input_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -361,10 +375,40 @@ xcb_xfixes_select_cursor_input (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_xfixes_get_cursor_image_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_xfixes_get_cursor_image_reply_t *_aux = (xcb_xfixes_get_cursor_image_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_xfixes_get_cursor_image_reply_t);
+ xcb_tmp += xcb_block_len;
+ /* cursor_image */
+ xcb_block_len += (_aux->width * _aux->height) * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -394,6 +438,7 @@ xcb_xfixes_get_cursor_image (xcb_connection_t *c /**< */)
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -427,6 +472,7 @@ xcb_xfixes_get_cursor_image_unchecked (xcb_connection_t *c /**< */)
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -541,6 +587,35 @@ xcb_xfixes_region_end (xcb_xfixes_region_iterator_t i /**< */)
return ret;
}
+int
+xcb_xfixes_create_region_sizeof (const void *_buffer /**< */,
+ uint32_t rectangles_len /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_xfixes_create_region_request_t);
+ xcb_tmp += xcb_block_len;
+ /* rectangles */
+ xcb_block_len += rectangles_len * sizeof(xcb_rectangle_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_rectangle_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -577,10 +652,12 @@ xcb_xfixes_create_region_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_rectangle_t rectangles */
xcb_parts[4].iov_base = (char *) rectangles;
xcb_parts[4].iov_len = rectangles_len * sizeof(xcb_rectangle_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -621,10 +698,12 @@ xcb_xfixes_create_region (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_rectangle_t rectangles */
xcb_parts[4].iov_base = (char *) rectangles;
xcb_parts[4].iov_len = rectangles_len * sizeof(xcb_rectangle_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -664,6 +743,7 @@ xcb_xfixes_create_region_from_bitmap_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -703,6 +783,7 @@ xcb_xfixes_create_region_from_bitmap (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -746,6 +827,7 @@ xcb_xfixes_create_region_from_window_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -789,6 +871,7 @@ xcb_xfixes_create_region_from_window (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -828,6 +911,7 @@ xcb_xfixes_create_region_from_gc_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -867,6 +951,7 @@ xcb_xfixes_create_region_from_gc (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -906,6 +991,7 @@ xcb_xfixes_create_region_from_picture_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -945,6 +1031,7 @@ xcb_xfixes_create_region_from_picture (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -981,6 +1068,7 @@ xcb_xfixes_destroy_region_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1017,10 +1105,40 @@ xcb_xfixes_destroy_region (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_xfixes_set_region_sizeof (const void *_buffer /**< */,
+ uint32_t rectangles_len /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_xfixes_set_region_request_t);
+ xcb_tmp += xcb_block_len;
+ /* rectangles */
+ xcb_block_len += rectangles_len * sizeof(xcb_rectangle_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_rectangle_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -1057,10 +1175,12 @@ xcb_xfixes_set_region_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_rectangle_t rectangles */
xcb_parts[4].iov_base = (char *) rectangles;
xcb_parts[4].iov_len = rectangles_len * sizeof(xcb_rectangle_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1101,10 +1221,12 @@ xcb_xfixes_set_region (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_rectangle_t rectangles */
xcb_parts[4].iov_base = (char *) rectangles;
xcb_parts[4].iov_len = rectangles_len * sizeof(xcb_rectangle_t);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1144,6 +1266,7 @@ xcb_xfixes_copy_region_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1183,6 +1306,7 @@ xcb_xfixes_copy_region (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1225,6 +1349,7 @@ xcb_xfixes_union_region_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1267,6 +1392,7 @@ xcb_xfixes_union_region (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1309,6 +1435,7 @@ xcb_xfixes_intersect_region_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1351,6 +1478,7 @@ xcb_xfixes_intersect_region (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1393,6 +1521,7 @@ xcb_xfixes_subtract_region_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1435,6 +1564,7 @@ xcb_xfixes_subtract_region (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1477,6 +1607,7 @@ xcb_xfixes_invert_region_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1519,6 +1650,7 @@ xcb_xfixes_invert_region (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1561,6 +1693,7 @@ xcb_xfixes_translate_region_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1603,6 +1736,7 @@ xcb_xfixes_translate_region (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1642,6 +1776,7 @@ xcb_xfixes_region_extents_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1681,10 +1816,40 @@ xcb_xfixes_region_extents (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_xfixes_fetch_region_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_xfixes_fetch_region_reply_t *_aux = (xcb_xfixes_fetch_region_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_xfixes_fetch_region_reply_t);
+ xcb_tmp += xcb_block_len;
+ /* rectangles */
+ xcb_block_len += (_aux->length / 2) * sizeof(xcb_rectangle_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_rectangle_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -1717,6 +1882,7 @@ xcb_xfixes_fetch_region (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1753,6 +1919,7 @@ xcb_xfixes_fetch_region_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1870,6 +2037,7 @@ xcb_xfixes_set_gc_clip_region_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1915,6 +2083,7 @@ xcb_xfixes_set_gc_clip_region (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -1964,6 +2133,7 @@ xcb_xfixes_set_window_shape_region_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2013,6 +2183,7 @@ xcb_xfixes_set_window_shape_region (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2058,6 +2229,7 @@ xcb_xfixes_set_picture_clip_region_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2103,10 +2275,40 @@ xcb_xfixes_set_picture_clip_region (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_xfixes_set_cursor_name_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_xfixes_set_cursor_name_request_t *_aux = (xcb_xfixes_set_cursor_name_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_xfixes_set_cursor_name_request_t);
+ xcb_tmp += xcb_block_len;
+ /* name */
+ xcb_block_len += _aux->nbytes * sizeof(char);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -2145,10 +2347,12 @@ xcb_xfixes_set_cursor_name_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* char name */
xcb_parts[4].iov_base = (char *) name;
xcb_parts[4].iov_len = nbytes * sizeof(char);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2191,14 +2395,45 @@ xcb_xfixes_set_cursor_name (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* char name */
xcb_parts[4].iov_base = (char *) name;
xcb_parts[4].iov_len = nbytes * sizeof(char);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_xfixes_get_cursor_name_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_xfixes_get_cursor_name_reply_t *_aux = (xcb_xfixes_get_cursor_name_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_xfixes_get_cursor_name_reply_t);
+ xcb_tmp += xcb_block_len;
+ /* name */
+ xcb_block_len += _aux->nbytes * sizeof(char);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -2231,6 +2466,7 @@ xcb_xfixes_get_cursor_name (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2267,6 +2503,7 @@ xcb_xfixes_get_cursor_name_unchecked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2343,6 +2580,47 @@ xcb_xfixes_get_cursor_name_reply (xcb_connection_t *c /**<
return (xcb_xfixes_get_cursor_name_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
}
+int
+xcb_xfixes_get_cursor_image_and_name_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_xfixes_get_cursor_image_and_name_reply_t *_aux = (xcb_xfixes_get_cursor_image_and_name_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_xfixes_get_cursor_image_and_name_reply_t);
+ xcb_tmp += xcb_block_len;
+ /* name */
+ xcb_block_len += _aux->nbytes * sizeof(char);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* cursor_image */
+ xcb_block_len += (_aux->width * _aux->height) * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -2372,6 +2650,7 @@ xcb_xfixes_get_cursor_image_and_name (xcb_connection_t *c /**< */)
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2405,6 +2684,7 @@ xcb_xfixes_get_cursor_image_and_name_unchecked (xcb_connection_t *c /**< */)
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2570,6 +2850,7 @@ xcb_xfixes_change_cursor_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2609,10 +2890,40 @@ xcb_xfixes_change_cursor (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
+int
+xcb_xfixes_change_cursor_by_name_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_xfixes_change_cursor_by_name_request_t *_aux = (xcb_xfixes_change_cursor_by_name_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_xfixes_change_cursor_by_name_request_t);
+ xcb_tmp += xcb_block_len;
+ /* name */
+ xcb_block_len += _aux->nbytes * sizeof(char);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
@@ -2651,10 +2962,12 @@ xcb_xfixes_change_cursor_by_name_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* char name */
xcb_parts[4].iov_base = (char *) name;
xcb_parts[4].iov_len = nbytes * sizeof(char);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2697,10 +3010,12 @@ xcb_xfixes_change_cursor_by_name (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* char name */
xcb_parts[4].iov_base = (char *) name;
xcb_parts[4].iov_len = nbytes * sizeof(char);
xcb_parts[5].iov_base = 0;
xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2752,6 +3067,7 @@ xcb_xfixes_expand_region_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2803,6 +3119,7 @@ xcb_xfixes_expand_region (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2839,6 +3156,7 @@ xcb_xfixes_hide_cursor_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2875,6 +3193,7 @@ xcb_xfixes_hide_cursor (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2911,6 +3230,7 @@ xcb_xfixes_show_cursor_checked (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -2947,6 +3267,7 @@ xcb_xfixes_show_cursor (xcb_connection_t *c /**< */,
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
diff --git a/src/3rdparty/xcb/libxcb/xinerama.c b/src/3rdparty/xcb/libxcb/xinerama.c
index 05b6b73707..e660be267b 100644
--- a/src/3rdparty/xcb/libxcb/xinerama.c
+++ b/src/3rdparty/xcb/libxcb/xinerama.c
@@ -3,10 +3,17 @@
* Edit at your peril.
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
+#include <stddef.h> /* for offsetof() */
#include "xcbext.h"
#include "xinerama.h"
+
+#define ALIGNOF(type) offsetof(struct { char dummy; type member; }, member)
#include "xproto.h"
xcb_extension_t xcb_xinerama_id = { "XINERAMA", 0 };
@@ -15,12 +22,12 @@ xcb_extension_t xcb_xinerama_id = { "XINERAMA", 0 };
/*****************************************************************************
**
** void xcb_xinerama_screen_info_next
- **
+ **
** @param xcb_xinerama_screen_info_iterator_t *i
** @returns void
**
*****************************************************************************/
-
+
void
xcb_xinerama_screen_info_next (xcb_xinerama_screen_info_iterator_t *i /**< */)
{
@@ -33,12 +40,12 @@ xcb_xinerama_screen_info_next (xcb_xinerama_screen_info_iterator_t *i /**< */)
/*****************************************************************************
**
** xcb_generic_iterator_t xcb_xinerama_screen_info_end
- **
+ **
** @param xcb_xinerama_screen_info_iterator_t i
** @returns xcb_generic_iterator_t
**
*****************************************************************************/
-
+
xcb_generic_iterator_t
xcb_xinerama_screen_info_end (xcb_xinerama_screen_info_iterator_t i /**< */)
{
@@ -53,14 +60,14 @@ xcb_xinerama_screen_info_end (xcb_xinerama_screen_info_iterator_t i /**< */)
/*****************************************************************************
**
** xcb_xinerama_query_version_cookie_t xcb_xinerama_query_version
- **
+ **
** @param xcb_connection_t *c
** @param uint8_t major
** @param uint8_t minor
** @returns xcb_xinerama_query_version_cookie_t
**
*****************************************************************************/
-
+
xcb_xinerama_query_version_cookie_t
xcb_xinerama_query_version (xcb_connection_t *c /**< */,
uint8_t major /**< */,
@@ -72,18 +79,19 @@ xcb_xinerama_query_version (xcb_connection_t *c /**< */,
/* opcode */ XCB_XINERAMA_QUERY_VERSION,
/* isvoid */ 0
};
-
+
struct iovec xcb_parts[4];
xcb_xinerama_query_version_cookie_t xcb_ret;
xcb_xinerama_query_version_request_t xcb_out;
-
+
xcb_out.major = major;
xcb_out.minor = minor;
-
+
xcb_parts[2].iov_base = (char *) &xcb_out;
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -92,14 +100,14 @@ xcb_xinerama_query_version (xcb_connection_t *c /**< */,
/*****************************************************************************
**
** xcb_xinerama_query_version_cookie_t xcb_xinerama_query_version_unchecked
- **
+ **
** @param xcb_connection_t *c
** @param uint8_t major
** @param uint8_t minor
** @returns xcb_xinerama_query_version_cookie_t
**
*****************************************************************************/
-
+
xcb_xinerama_query_version_cookie_t
xcb_xinerama_query_version_unchecked (xcb_connection_t *c /**< */,
uint8_t major /**< */,
@@ -111,18 +119,19 @@ xcb_xinerama_query_version_unchecked (xcb_connection_t *c /**< */,
/* opcode */ XCB_XINERAMA_QUERY_VERSION,
/* isvoid */ 0
};
-
+
struct iovec xcb_parts[4];
xcb_xinerama_query_version_cookie_t xcb_ret;
xcb_xinerama_query_version_request_t xcb_out;
-
+
xcb_out.major = major;
xcb_out.minor = minor;
-
+
xcb_parts[2].iov_base = (char *) &xcb_out;
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -131,14 +140,14 @@ xcb_xinerama_query_version_unchecked (xcb_connection_t *c /**< */,
/*****************************************************************************
**
** xcb_xinerama_query_version_reply_t * xcb_xinerama_query_version_reply
- **
+ **
** @param xcb_connection_t *c
** @param xcb_xinerama_query_version_cookie_t cookie
** @param xcb_generic_error_t **e
** @returns xcb_xinerama_query_version_reply_t *
**
*****************************************************************************/
-
+
xcb_xinerama_query_version_reply_t *
xcb_xinerama_query_version_reply (xcb_connection_t *c /**< */,
xcb_xinerama_query_version_cookie_t cookie /**< */,
@@ -151,13 +160,13 @@ xcb_xinerama_query_version_reply (xcb_connection_t *c /**<
/*****************************************************************************
**
** xcb_xinerama_get_state_cookie_t xcb_xinerama_get_state
- **
+ **
** @param xcb_connection_t *c
** @param xcb_window_t window
** @returns xcb_xinerama_get_state_cookie_t
**
*****************************************************************************/
-
+
xcb_xinerama_get_state_cookie_t
xcb_xinerama_get_state (xcb_connection_t *c /**< */,
xcb_window_t window /**< */)
@@ -168,17 +177,18 @@ xcb_xinerama_get_state (xcb_connection_t *c /**< */,
/* opcode */ XCB_XINERAMA_GET_STATE,
/* isvoid */ 0
};
-
+
struct iovec xcb_parts[4];
xcb_xinerama_get_state_cookie_t xcb_ret;
xcb_xinerama_get_state_request_t xcb_out;
-
+
xcb_out.window = window;
-
+
xcb_parts[2].iov_base = (char *) &xcb_out;
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -187,13 +197,13 @@ xcb_xinerama_get_state (xcb_connection_t *c /**< */,
/*****************************************************************************
**
** xcb_xinerama_get_state_cookie_t xcb_xinerama_get_state_unchecked
- **
+ **
** @param xcb_connection_t *c
** @param xcb_window_t window
** @returns xcb_xinerama_get_state_cookie_t
**
*****************************************************************************/
-
+
xcb_xinerama_get_state_cookie_t
xcb_xinerama_get_state_unchecked (xcb_connection_t *c /**< */,
xcb_window_t window /**< */)
@@ -204,17 +214,18 @@ xcb_xinerama_get_state_unchecked (xcb_connection_t *c /**< */,
/* opcode */ XCB_XINERAMA_GET_STATE,
/* isvoid */ 0
};
-
+
struct iovec xcb_parts[4];
xcb_xinerama_get_state_cookie_t xcb_ret;
xcb_xinerama_get_state_request_t xcb_out;
-
+
xcb_out.window = window;
-
+
xcb_parts[2].iov_base = (char *) &xcb_out;
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -223,14 +234,14 @@ xcb_xinerama_get_state_unchecked (xcb_connection_t *c /**< */,
/*****************************************************************************
**
** xcb_xinerama_get_state_reply_t * xcb_xinerama_get_state_reply
- **
+ **
** @param xcb_connection_t *c
** @param xcb_xinerama_get_state_cookie_t cookie
** @param xcb_generic_error_t **e
** @returns xcb_xinerama_get_state_reply_t *
**
*****************************************************************************/
-
+
xcb_xinerama_get_state_reply_t *
xcb_xinerama_get_state_reply (xcb_connection_t *c /**< */,
xcb_xinerama_get_state_cookie_t cookie /**< */,
@@ -243,13 +254,13 @@ xcb_xinerama_get_state_reply (xcb_connection_t *c /**< */,
/*****************************************************************************
**
** xcb_xinerama_get_screen_count_cookie_t xcb_xinerama_get_screen_count
- **
+ **
** @param xcb_connection_t *c
** @param xcb_window_t window
** @returns xcb_xinerama_get_screen_count_cookie_t
**
*****************************************************************************/
-
+
xcb_xinerama_get_screen_count_cookie_t
xcb_xinerama_get_screen_count (xcb_connection_t *c /**< */,
xcb_window_t window /**< */)
@@ -260,17 +271,18 @@ xcb_xinerama_get_screen_count (xcb_connection_t *c /**< */,
/* opcode */ XCB_XINERAMA_GET_SCREEN_COUNT,
/* isvoid */ 0
};
-
+
struct iovec xcb_parts[4];
xcb_xinerama_get_screen_count_cookie_t xcb_ret;
xcb_xinerama_get_screen_count_request_t xcb_out;
-
+
xcb_out.window = window;
-
+
xcb_parts[2].iov_base = (char *) &xcb_out;
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -279,13 +291,13 @@ xcb_xinerama_get_screen_count (xcb_connection_t *c /**< */,
/*****************************************************************************
**
** xcb_xinerama_get_screen_count_cookie_t xcb_xinerama_get_screen_count_unchecked
- **
+ **
** @param xcb_connection_t *c
** @param xcb_window_t window
** @returns xcb_xinerama_get_screen_count_cookie_t
**
*****************************************************************************/
-
+
xcb_xinerama_get_screen_count_cookie_t
xcb_xinerama_get_screen_count_unchecked (xcb_connection_t *c /**< */,
xcb_window_t window /**< */)
@@ -296,17 +308,18 @@ xcb_xinerama_get_screen_count_unchecked (xcb_connection_t *c /**< */,
/* opcode */ XCB_XINERAMA_GET_SCREEN_COUNT,
/* isvoid */ 0
};
-
+
struct iovec xcb_parts[4];
xcb_xinerama_get_screen_count_cookie_t xcb_ret;
xcb_xinerama_get_screen_count_request_t xcb_out;
-
+
xcb_out.window = window;
-
+
xcb_parts[2].iov_base = (char *) &xcb_out;
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -315,14 +328,14 @@ xcb_xinerama_get_screen_count_unchecked (xcb_connection_t *c /**< */,
/*****************************************************************************
**
** xcb_xinerama_get_screen_count_reply_t * xcb_xinerama_get_screen_count_reply
- **
+ **
** @param xcb_connection_t *c
** @param xcb_xinerama_get_screen_count_cookie_t cookie
** @param xcb_generic_error_t **e
** @returns xcb_xinerama_get_screen_count_reply_t *
**
*****************************************************************************/
-
+
xcb_xinerama_get_screen_count_reply_t *
xcb_xinerama_get_screen_count_reply (xcb_connection_t *c /**< */,
xcb_xinerama_get_screen_count_cookie_t cookie /**< */,
@@ -335,14 +348,14 @@ xcb_xinerama_get_screen_count_reply (xcb_connection_t *c
/*****************************************************************************
**
** xcb_xinerama_get_screen_size_cookie_t xcb_xinerama_get_screen_size
- **
+ **
** @param xcb_connection_t *c
** @param xcb_window_t window
** @param uint32_t screen
** @returns xcb_xinerama_get_screen_size_cookie_t
**
*****************************************************************************/
-
+
xcb_xinerama_get_screen_size_cookie_t
xcb_xinerama_get_screen_size (xcb_connection_t *c /**< */,
xcb_window_t window /**< */,
@@ -354,18 +367,19 @@ xcb_xinerama_get_screen_size (xcb_connection_t *c /**< */,
/* opcode */ XCB_XINERAMA_GET_SCREEN_SIZE,
/* isvoid */ 0
};
-
+
struct iovec xcb_parts[4];
xcb_xinerama_get_screen_size_cookie_t xcb_ret;
xcb_xinerama_get_screen_size_request_t xcb_out;
-
+
xcb_out.window = window;
xcb_out.screen = screen;
-
+
xcb_parts[2].iov_base = (char *) &xcb_out;
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -374,14 +388,14 @@ xcb_xinerama_get_screen_size (xcb_connection_t *c /**< */,
/*****************************************************************************
**
** xcb_xinerama_get_screen_size_cookie_t xcb_xinerama_get_screen_size_unchecked
- **
+ **
** @param xcb_connection_t *c
** @param xcb_window_t window
** @param uint32_t screen
** @returns xcb_xinerama_get_screen_size_cookie_t
**
*****************************************************************************/
-
+
xcb_xinerama_get_screen_size_cookie_t
xcb_xinerama_get_screen_size_unchecked (xcb_connection_t *c /**< */,
xcb_window_t window /**< */,
@@ -393,18 +407,19 @@ xcb_xinerama_get_screen_size_unchecked (xcb_connection_t *c /**< */,
/* opcode */ XCB_XINERAMA_GET_SCREEN_SIZE,
/* isvoid */ 0
};
-
+
struct iovec xcb_parts[4];
xcb_xinerama_get_screen_size_cookie_t xcb_ret;
xcb_xinerama_get_screen_size_request_t xcb_out;
-
+
xcb_out.window = window;
xcb_out.screen = screen;
-
+
xcb_parts[2].iov_base = (char *) &xcb_out;
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -413,14 +428,14 @@ xcb_xinerama_get_screen_size_unchecked (xcb_connection_t *c /**< */,
/*****************************************************************************
**
** xcb_xinerama_get_screen_size_reply_t * xcb_xinerama_get_screen_size_reply
- **
+ **
** @param xcb_connection_t *c
** @param xcb_xinerama_get_screen_size_cookie_t cookie
** @param xcb_generic_error_t **e
** @returns xcb_xinerama_get_screen_size_reply_t *
**
*****************************************************************************/
-
+
xcb_xinerama_get_screen_size_reply_t *
xcb_xinerama_get_screen_size_reply (xcb_connection_t *c /**< */,
xcb_xinerama_get_screen_size_cookie_t cookie /**< */,
@@ -433,12 +448,12 @@ xcb_xinerama_get_screen_size_reply (xcb_connection_t *c /
/*****************************************************************************
**
** xcb_xinerama_is_active_cookie_t xcb_xinerama_is_active
- **
+ **
** @param xcb_connection_t *c
** @returns xcb_xinerama_is_active_cookie_t
**
*****************************************************************************/
-
+
xcb_xinerama_is_active_cookie_t
xcb_xinerama_is_active (xcb_connection_t *c /**< */)
{
@@ -448,16 +463,17 @@ xcb_xinerama_is_active (xcb_connection_t *c /**< */)
/* opcode */ XCB_XINERAMA_IS_ACTIVE,
/* isvoid */ 0
};
-
+
struct iovec xcb_parts[4];
xcb_xinerama_is_active_cookie_t xcb_ret;
xcb_xinerama_is_active_request_t xcb_out;
-
-
+
+
xcb_parts[2].iov_base = (char *) &xcb_out;
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -466,12 +482,12 @@ xcb_xinerama_is_active (xcb_connection_t *c /**< */)
/*****************************************************************************
**
** xcb_xinerama_is_active_cookie_t xcb_xinerama_is_active_unchecked
- **
+ **
** @param xcb_connection_t *c
** @returns xcb_xinerama_is_active_cookie_t
**
*****************************************************************************/
-
+
xcb_xinerama_is_active_cookie_t
xcb_xinerama_is_active_unchecked (xcb_connection_t *c /**< */)
{
@@ -481,16 +497,17 @@ xcb_xinerama_is_active_unchecked (xcb_connection_t *c /**< */)
/* opcode */ XCB_XINERAMA_IS_ACTIVE,
/* isvoid */ 0
};
-
+
struct iovec xcb_parts[4];
xcb_xinerama_is_active_cookie_t xcb_ret;
xcb_xinerama_is_active_request_t xcb_out;
-
-
+
+
xcb_parts[2].iov_base = (char *) &xcb_out;
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -499,14 +516,14 @@ xcb_xinerama_is_active_unchecked (xcb_connection_t *c /**< */)
/*****************************************************************************
**
** xcb_xinerama_is_active_reply_t * xcb_xinerama_is_active_reply
- **
+ **
** @param xcb_connection_t *c
** @param xcb_xinerama_is_active_cookie_t cookie
** @param xcb_generic_error_t **e
** @returns xcb_xinerama_is_active_reply_t *
**
*****************************************************************************/
-
+
xcb_xinerama_is_active_reply_t *
xcb_xinerama_is_active_reply (xcb_connection_t *c /**< */,
xcb_xinerama_is_active_cookie_t cookie /**< */,
@@ -515,16 +532,45 @@ xcb_xinerama_is_active_reply (xcb_connection_t *c /**< */,
return (xcb_xinerama_is_active_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
}
+int
+xcb_xinerama_query_screens_sizeof (const void *_buffer /**< */)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_xinerama_query_screens_reply_t *_aux = (xcb_xinerama_query_screens_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to;
+
+
+ xcb_block_len += sizeof(xcb_xinerama_query_screens_reply_t);
+ xcb_tmp += xcb_block_len;
+ /* screen_info */
+ xcb_block_len += _aux->number * sizeof(xcb_xinerama_screen_info_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_xinerama_screen_info_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
/*****************************************************************************
**
** xcb_xinerama_query_screens_cookie_t xcb_xinerama_query_screens
- **
+ **
** @param xcb_connection_t *c
** @returns xcb_xinerama_query_screens_cookie_t
**
*****************************************************************************/
-
+
xcb_xinerama_query_screens_cookie_t
xcb_xinerama_query_screens (xcb_connection_t *c /**< */)
{
@@ -534,16 +580,17 @@ xcb_xinerama_query_screens (xcb_connection_t *c /**< */)
/* opcode */ XCB_XINERAMA_QUERY_SCREENS,
/* isvoid */ 0
};
-
+
struct iovec xcb_parts[4];
xcb_xinerama_query_screens_cookie_t xcb_ret;
xcb_xinerama_query_screens_request_t xcb_out;
-
-
+
+
xcb_parts[2].iov_base = (char *) &xcb_out;
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -552,12 +599,12 @@ xcb_xinerama_query_screens (xcb_connection_t *c /**< */)
/*****************************************************************************
**
** xcb_xinerama_query_screens_cookie_t xcb_xinerama_query_screens_unchecked
- **
+ **
** @param xcb_connection_t *c
** @returns xcb_xinerama_query_screens_cookie_t
**
*****************************************************************************/
-
+
xcb_xinerama_query_screens_cookie_t
xcb_xinerama_query_screens_unchecked (xcb_connection_t *c /**< */)
{
@@ -567,16 +614,17 @@ xcb_xinerama_query_screens_unchecked (xcb_connection_t *c /**< */)
/* opcode */ XCB_XINERAMA_QUERY_SCREENS,
/* isvoid */ 0
};
-
+
struct iovec xcb_parts[4];
xcb_xinerama_query_screens_cookie_t xcb_ret;
xcb_xinerama_query_screens_request_t xcb_out;
-
-
+
+
xcb_parts[2].iov_base = (char *) &xcb_out;
xcb_parts[2].iov_len = sizeof(xcb_out);
xcb_parts[3].iov_base = 0;
xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
return xcb_ret;
}
@@ -585,12 +633,12 @@ xcb_xinerama_query_screens_unchecked (xcb_connection_t *c /**< */)
/*****************************************************************************
**
** xcb_xinerama_screen_info_t * xcb_xinerama_query_screens_screen_info
- **
+ **
** @param const xcb_xinerama_query_screens_reply_t *R
** @returns xcb_xinerama_screen_info_t *
**
*****************************************************************************/
-
+
xcb_xinerama_screen_info_t *
xcb_xinerama_query_screens_screen_info (const xcb_xinerama_query_screens_reply_t *R /**< */)
{
@@ -601,12 +649,12 @@ xcb_xinerama_query_screens_screen_info (const xcb_xinerama_query_screens_reply_t
/*****************************************************************************
**
** int xcb_xinerama_query_screens_screen_info_length
- **
+ **
** @param const xcb_xinerama_query_screens_reply_t *R
** @returns int
**
*****************************************************************************/
-
+
int
xcb_xinerama_query_screens_screen_info_length (const xcb_xinerama_query_screens_reply_t *R /**< */)
{
@@ -617,12 +665,12 @@ xcb_xinerama_query_screens_screen_info_length (const xcb_xinerama_query_screens_
/*****************************************************************************
**
** xcb_xinerama_screen_info_iterator_t xcb_xinerama_query_screens_screen_info_iterator
- **
+ **
** @param const xcb_xinerama_query_screens_reply_t *R
** @returns xcb_xinerama_screen_info_iterator_t
**
*****************************************************************************/
-
+
xcb_xinerama_screen_info_iterator_t
xcb_xinerama_query_screens_screen_info_iterator (const xcb_xinerama_query_screens_reply_t *R /**< */)
{
@@ -637,14 +685,14 @@ xcb_xinerama_query_screens_screen_info_iterator (const xcb_xinerama_query_screen
/*****************************************************************************
**
** xcb_xinerama_query_screens_reply_t * xcb_xinerama_query_screens_reply
- **
+ **
** @param xcb_connection_t *c
** @param xcb_xinerama_query_screens_cookie_t cookie
** @param xcb_generic_error_t **e
** @returns xcb_xinerama_query_screens_reply_t *
**
*****************************************************************************/
-
+
xcb_xinerama_query_screens_reply_t *
xcb_xinerama_query_screens_reply (xcb_connection_t *c /**< */,
xcb_xinerama_query_screens_cookie_t cookie /**< */,
diff --git a/src/3rdparty/xcb/libxcb/xinput.c b/src/3rdparty/xcb/libxcb/xinput.c
new file mode 100644
index 0000000000..0edfde656c
--- /dev/null
+++ b/src/3rdparty/xcb/libxcb/xinput.c
@@ -0,0 +1,14156 @@
+/*
+ * This file generated automatically from xinput.xml by c_client.py.
+ * Edit at your peril.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stddef.h> /* for offsetof() */
+#include "xcbext.h"
+#include "xinput.h"
+
+#define ALIGNOF(type) offsetof(struct { char dummy; type member; }, member)
+#include "xfixes.h"
+
+xcb_extension_t xcb_input_id = { "XInputExtension", 0 };
+
+void
+xcb_input_event_class_next (xcb_input_event_class_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_event_class_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_event_class_end (xcb_input_event_class_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_key_code_next (xcb_input_key_code_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_key_code_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_key_code_end (xcb_input_key_code_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_device_id_next (xcb_input_device_id_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_device_id_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_device_id_end (xcb_input_device_id_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_fp1616_next (xcb_input_fp1616_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_fp1616_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_fp1616_end (xcb_input_fp1616_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_fp3232_next (xcb_input_fp3232_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_fp3232_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_fp3232_end (xcb_input_fp3232_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+int
+xcb_input_get_extension_version_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_get_extension_version_request_t *_aux = (xcb_input_get_extension_version_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_get_extension_version_request_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* name */
+ xcb_block_len += _aux->name_len * sizeof(char);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_get_extension_version_cookie_t
+xcb_input_get_extension_version (xcb_connection_t *c,
+ uint16_t name_len,
+ const char *name)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GET_EXTENSION_VERSION,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_input_get_extension_version_cookie_t xcb_ret;
+ xcb_input_get_extension_version_request_t xcb_out;
+
+ xcb_out.name_len = name_len;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* char name */
+ xcb_parts[4].iov_base = (char *) name;
+ xcb_parts[4].iov_len = name_len * sizeof(char);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_get_extension_version_cookie_t
+xcb_input_get_extension_version_unchecked (xcb_connection_t *c,
+ uint16_t name_len,
+ const char *name)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GET_EXTENSION_VERSION,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_input_get_extension_version_cookie_t xcb_ret;
+ xcb_input_get_extension_version_request_t xcb_out;
+
+ xcb_out.name_len = name_len;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* char name */
+ xcb_parts[4].iov_base = (char *) name;
+ xcb_parts[4].iov_len = name_len * sizeof(char);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_get_extension_version_reply_t *
+xcb_input_get_extension_version_reply (xcb_connection_t *c,
+ xcb_input_get_extension_version_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_get_extension_version_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+void
+xcb_input_device_info_next (xcb_input_device_info_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_device_info_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_device_info_end (xcb_input_device_info_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_key_info_next (xcb_input_key_info_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_key_info_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_key_info_end (xcb_input_key_info_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_button_info_next (xcb_input_button_info_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_button_info_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_button_info_end (xcb_input_button_info_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_axis_info_next (xcb_input_axis_info_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_axis_info_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_axis_info_end (xcb_input_axis_info_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+int
+xcb_input_valuator_info_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_valuator_info_t *_aux = (xcb_input_valuator_info_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_valuator_info_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* axes */
+ xcb_block_len += _aux->axes_len * sizeof(xcb_input_axis_info_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_axis_info_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_axis_info_t *
+xcb_input_valuator_info_axes (const xcb_input_valuator_info_t *R)
+{
+ return (xcb_input_axis_info_t *) (R + 1);
+}
+
+int
+xcb_input_valuator_info_axes_length (const xcb_input_valuator_info_t *R)
+{
+ return R->axes_len;
+}
+
+xcb_input_axis_info_iterator_t
+xcb_input_valuator_info_axes_iterator (const xcb_input_valuator_info_t *R)
+{
+ xcb_input_axis_info_iterator_t i;
+ i.data = (xcb_input_axis_info_t *) (R + 1);
+ i.rem = R->axes_len;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+void
+xcb_input_valuator_info_next (xcb_input_valuator_info_iterator_t *i)
+{
+ xcb_input_valuator_info_t *R = i->data;
+ xcb_generic_iterator_t child;
+ child.data = (xcb_input_valuator_info_t *)(((char *)R) + xcb_input_valuator_info_sizeof(R));
+ i->index = (char *) child.data - (char *) i->data;
+ --i->rem;
+ i->data = (xcb_input_valuator_info_t *) child.data;
+}
+
+xcb_generic_iterator_t
+xcb_input_valuator_info_end (xcb_input_valuator_info_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ while(i.rem > 0)
+ xcb_input_valuator_info_next(&i);
+ ret.data = i.data;
+ ret.rem = i.rem;
+ ret.index = i.index;
+ return ret;
+}
+
+xcb_input_axis_info_t *
+xcb_input_input_info_info_valuator_axes (const xcb_input_input_info_info_t *S)
+{
+ return S->valuator.axes;
+}
+
+int
+xcb_input_input_info_info_valuator_axes_length (const xcb_input_input_info_t *R,
+ const xcb_input_input_info_info_t *S)
+{
+ return S->valuator.axes_len;
+}
+
+xcb_input_axis_info_iterator_t
+xcb_input_input_info_info_valuator_axes_iterator (const xcb_input_input_info_t *R,
+ const xcb_input_input_info_info_t *S)
+{
+ xcb_input_axis_info_iterator_t i;
+ i.data = S->valuator.axes;
+ i.rem = S->valuator.axes_len;
+ i.index = (char *) i.data - (char *) S;
+ return i;
+}
+
+int
+xcb_input_input_info_info_serialize (void **_buffer,
+ uint8_t class_id,
+ const xcb_input_input_info_info_t *_aux)
+{
+ char *xcb_out = *_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_align_to = 0;
+ unsigned int xcb_padding_offset = 2;
+
+ unsigned int xcb_pad = 0;
+ char xcb_pad0[3] = {0, 0, 0};
+ struct iovec xcb_parts[11];
+ unsigned int xcb_parts_idx = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int i;
+ char *xcb_tmp;
+
+ if(class_id == XCB_INPUT_INPUT_CLASS_KEY) {
+ /* xcb_input_input_info_info_t.key.min_keycode */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->key.min_keycode;
+ xcb_block_len += sizeof(xcb_input_key_code_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(xcb_input_key_code_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(xcb_input_key_code_t);
+ /* xcb_input_input_info_info_t.key.max_keycode */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->key.max_keycode;
+ xcb_block_len += sizeof(xcb_input_key_code_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(xcb_input_key_code_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(xcb_input_key_code_t);
+ /* xcb_input_input_info_info_t.key.num_keys */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->key.num_keys;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* xcb_input_input_info_info_t.key.pad0 */
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_block_len += sizeof(uint8_t)*2;
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t)*2;
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ }
+ if(class_id == XCB_INPUT_INPUT_CLASS_BUTTON) {
+ /* xcb_input_input_info_info_t.button.num_buttons */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->button.num_buttons;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint16_t);
+ }
+ if(class_id == XCB_INPUT_INPUT_CLASS_VALUATOR) {
+ /* xcb_input_input_info_info_t.valuator.axes_len */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->valuator.axes_len;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_input_info_info_t.valuator.mode */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->valuator.mode;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_input_info_info_t.valuator.motion_size */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->valuator.motion_size;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* axes */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->valuator.axes;
+ xcb_block_len += _aux->valuator.axes_len * sizeof(xcb_input_axis_info_t);
+ xcb_parts[xcb_parts_idx].iov_len = _aux->valuator.axes_len * sizeof(xcb_input_axis_info_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(xcb_input_axis_info_t);
+ }
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+
+ if (NULL == xcb_out) {
+ /* allocate memory */
+ xcb_out = malloc(xcb_buffer_len);
+ *_buffer = xcb_out;
+ }
+
+ xcb_tmp = xcb_out;
+ for(i=0; i<xcb_parts_idx; i++) {
+ if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)
+ memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);
+ if (0 != xcb_parts[i].iov_len)
+ xcb_tmp += xcb_parts[i].iov_len;
+ }
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_input_info_info_unpack (const void *_buffer,
+ uint8_t class_id,
+ xcb_input_input_info_info_t *_aux)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+ unsigned int xcb_padding_offset = 2;
+
+
+ if(class_id == XCB_INPUT_INPUT_CLASS_KEY) {
+ /* xcb_input_input_info_info_t.key.min_keycode */
+ _aux->key.min_keycode = *(xcb_input_key_code_t *)xcb_tmp;
+ xcb_block_len += sizeof(xcb_input_key_code_t);
+ xcb_tmp += sizeof(xcb_input_key_code_t);
+ xcb_align_to = ALIGNOF(xcb_input_key_code_t);
+ /* xcb_input_input_info_info_t.key.max_keycode */
+ _aux->key.max_keycode = *(xcb_input_key_code_t *)xcb_tmp;
+ xcb_block_len += sizeof(xcb_input_key_code_t);
+ xcb_tmp += sizeof(xcb_input_key_code_t);
+ xcb_align_to = ALIGNOF(xcb_input_key_code_t);
+ /* xcb_input_input_info_info_t.key.num_keys */
+ _aux->key.num_keys = *(uint16_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_tmp += sizeof(uint16_t);
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* xcb_input_input_info_info_t.key.pad0 */
+ _aux->key.pad0[0] = *(uint8_t *)xcb_tmp;
+ _aux->key.pad0[1] = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t) * 2;
+ xcb_tmp += sizeof(uint8_t) * 2;
+ xcb_align_to = ALIGNOF(uint8_t);
+ }
+ if(class_id == XCB_INPUT_INPUT_CLASS_BUTTON) {
+ /* xcb_input_input_info_info_t.button.num_buttons */
+ _aux->button.num_buttons = *(uint16_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_tmp += sizeof(uint16_t);
+ xcb_align_to = ALIGNOF(uint16_t);
+ }
+ if(class_id == XCB_INPUT_INPUT_CLASS_VALUATOR) {
+ /* xcb_input_input_info_info_t.valuator.axes_len */
+ _aux->valuator.axes_len = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_input_info_info_t.valuator.mode */
+ _aux->valuator.mode = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_input_info_info_t.valuator.motion_size */
+ _aux->valuator.motion_size = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* axes */
+ _aux->valuator.axes = (xcb_input_axis_info_t *)xcb_tmp;
+ xcb_block_len += _aux->valuator.axes_len * sizeof(xcb_input_axis_info_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_axis_info_t);
+ }
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_input_info_info_sizeof (const void *_buffer,
+ uint8_t class_id)
+{
+ xcb_input_input_info_info_t _aux;
+ return xcb_input_input_info_info_unpack(_buffer, class_id, &_aux);
+}
+
+int
+xcb_input_input_info_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_input_info_t *_aux = (xcb_input_input_info_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_input_info_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* info */
+ xcb_block_len += xcb_input_input_info_info_sizeof(xcb_tmp, _aux->class_id);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+void *
+xcb_input_input_info_info (const xcb_input_input_info_t *R)
+{
+ return (void *) (R + 1);
+}
+
+void
+xcb_input_input_info_next (xcb_input_input_info_iterator_t *i)
+{
+ xcb_input_input_info_t *R = i->data;
+ xcb_generic_iterator_t child;
+ child.data = (xcb_input_input_info_t *)(((char *)R) + xcb_input_input_info_sizeof(R));
+ i->index = (char *) child.data - (char *) i->data;
+ --i->rem;
+ i->data = (xcb_input_input_info_t *) child.data;
+}
+
+xcb_generic_iterator_t
+xcb_input_input_info_end (xcb_input_input_info_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ while(i.rem > 0)
+ xcb_input_input_info_next(&i);
+ ret.data = i.data;
+ ret.rem = i.rem;
+ ret.index = i.index;
+ return ret;
+}
+
+int
+xcb_input_device_name_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_device_name_t *_aux = (xcb_input_device_name_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_device_name_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* string */
+ xcb_block_len += _aux->len * sizeof(char);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+char *
+xcb_input_device_name_string (const xcb_input_device_name_t *R)
+{
+ return (char *) (R + 1);
+}
+
+int
+xcb_input_device_name_string_length (const xcb_input_device_name_t *R)
+{
+ return R->len;
+}
+
+xcb_generic_iterator_t
+xcb_input_device_name_string_end (const xcb_input_device_name_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((char *) (R + 1)) + (R->len);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+void
+xcb_input_device_name_next (xcb_input_device_name_iterator_t *i)
+{
+ xcb_input_device_name_t *R = i->data;
+ xcb_generic_iterator_t child;
+ child.data = (xcb_input_device_name_t *)(((char *)R) + xcb_input_device_name_sizeof(R));
+ i->index = (char *) child.data - (char *) i->data;
+ --i->rem;
+ i->data = (xcb_input_device_name_t *) child.data;
+}
+
+xcb_generic_iterator_t
+xcb_input_device_name_end (xcb_input_device_name_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ while(i.rem > 0)
+ xcb_input_device_name_next(&i);
+ ret.data = i.data;
+ ret.rem = i.rem;
+ ret.index = i.index;
+ return ret;
+}
+
+int
+xcb_input_list_input_devices_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_list_input_devices_reply_t *_aux = (xcb_input_list_input_devices_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+ int xcb_pre_tmp_1; /* sumof length */
+ int xcb_pre_tmp_2; /* sumof loop counter */
+ int64_t xcb_pre_tmp_3; /* sumof sum */
+ const xcb_input_device_info_t* xcb_pre_tmp_4; /* sumof list ptr */
+ unsigned int i;
+ unsigned int xcb_tmp_len;
+
+ xcb_block_len += sizeof(xcb_input_list_input_devices_reply_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* devices */
+ xcb_block_len += _aux->devices_len * sizeof(xcb_input_device_info_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_device_info_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* infos */
+ /* sumof start */
+ xcb_pre_tmp_1 = _aux->devices_len;
+ xcb_pre_tmp_3 = 0;
+ xcb_pre_tmp_4 = xcb_input_list_input_devices_devices(_aux);
+ for (xcb_pre_tmp_2 = 0; xcb_pre_tmp_2 < xcb_pre_tmp_1; xcb_pre_tmp_2++) {
+ xcb_pre_tmp_3 += xcb_pre_tmp_4->num_class_info;
+ xcb_pre_tmp_4++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_3 */
+ for(i=0; i<xcb_pre_tmp_3; i++) {
+ xcb_tmp_len = xcb_input_input_info_sizeof(xcb_tmp);
+ xcb_block_len += xcb_tmp_len;
+ xcb_tmp += xcb_tmp_len;
+ }
+ xcb_align_to = ALIGNOF(xcb_input_input_info_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* names */
+ for(i=0; i<_aux->devices_len; i++) {
+ xcb_tmp_len = xcb_str_sizeof(xcb_tmp);
+ xcb_block_len += xcb_tmp_len;
+ xcb_tmp += xcb_tmp_len;
+ }
+ xcb_align_to = ALIGNOF(xcb_str_t);
+ xcb_align_to = 4;
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_list_input_devices_cookie_t
+xcb_input_list_input_devices (xcb_connection_t *c)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_LIST_INPUT_DEVICES,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_list_input_devices_cookie_t xcb_ret;
+ xcb_input_list_input_devices_request_t xcb_out;
+
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_list_input_devices_cookie_t
+xcb_input_list_input_devices_unchecked (xcb_connection_t *c)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_LIST_INPUT_DEVICES,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_list_input_devices_cookie_t xcb_ret;
+ xcb_input_list_input_devices_request_t xcb_out;
+
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_device_info_t *
+xcb_input_list_input_devices_devices (const xcb_input_list_input_devices_reply_t *R)
+{
+ return (xcb_input_device_info_t *) (R + 1);
+}
+
+int
+xcb_input_list_input_devices_devices_length (const xcb_input_list_input_devices_reply_t *R)
+{
+ return R->devices_len;
+}
+
+xcb_input_device_info_iterator_t
+xcb_input_list_input_devices_devices_iterator (const xcb_input_list_input_devices_reply_t *R)
+{
+ xcb_input_device_info_iterator_t i;
+ i.data = (xcb_input_device_info_t *) (R + 1);
+ i.rem = R->devices_len;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+int
+xcb_input_list_input_devices_infos_length (const xcb_input_list_input_devices_reply_t *R)
+{
+ int xcb_pre_tmp_5; /* sumof length */
+ int xcb_pre_tmp_6; /* sumof loop counter */
+ int64_t xcb_pre_tmp_7; /* sumof sum */
+ const xcb_input_device_info_t* xcb_pre_tmp_8; /* sumof list ptr */
+ /* sumof start */
+ xcb_pre_tmp_5 = R->devices_len;
+ xcb_pre_tmp_7 = 0;
+ xcb_pre_tmp_8 = xcb_input_list_input_devices_devices(R);
+ for (xcb_pre_tmp_6 = 0; xcb_pre_tmp_6 < xcb_pre_tmp_5; xcb_pre_tmp_6++) {
+ xcb_pre_tmp_7 += xcb_pre_tmp_8->num_class_info;
+ xcb_pre_tmp_8++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_7 */
+ return xcb_pre_tmp_7;
+}
+
+xcb_input_input_info_iterator_t
+xcb_input_list_input_devices_infos_iterator (const xcb_input_list_input_devices_reply_t *R)
+{
+ xcb_input_input_info_iterator_t i;
+ xcb_generic_iterator_t prev = xcb_input_device_info_end(xcb_input_list_input_devices_devices_iterator(R));
+ int xcb_pre_tmp_9; /* sumof length */
+ int xcb_pre_tmp_10; /* sumof loop counter */
+ int64_t xcb_pre_tmp_11; /* sumof sum */
+ const xcb_input_device_info_t* xcb_pre_tmp_12; /* sumof list ptr */
+ /* sumof start */
+ xcb_pre_tmp_9 = R->devices_len;
+ xcb_pre_tmp_11 = 0;
+ xcb_pre_tmp_12 = xcb_input_list_input_devices_devices(R);
+ for (xcb_pre_tmp_10 = 0; xcb_pre_tmp_10 < xcb_pre_tmp_9; xcb_pre_tmp_10++) {
+ xcb_pre_tmp_11 += xcb_pre_tmp_12->num_class_info;
+ xcb_pre_tmp_12++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_11 */
+ i.data = (xcb_input_input_info_t *) ((char *) prev.data + XCB_TYPE_PAD(xcb_input_input_info_t, prev.index));
+ i.rem = xcb_pre_tmp_11;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+int
+xcb_input_list_input_devices_names_length (const xcb_input_list_input_devices_reply_t *R)
+{
+ return R->devices_len;
+}
+
+xcb_str_iterator_t
+xcb_input_list_input_devices_names_iterator (const xcb_input_list_input_devices_reply_t *R)
+{
+ xcb_str_iterator_t i;
+ xcb_generic_iterator_t prev = xcb_input_input_info_end(xcb_input_list_input_devices_infos_iterator(R));
+ i.data = (xcb_str_t *) ((char *) prev.data + XCB_TYPE_PAD(xcb_str_t, prev.index));
+ i.rem = R->devices_len;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_list_input_devices_reply_t *
+xcb_input_list_input_devices_reply (xcb_connection_t *c,
+ xcb_input_list_input_devices_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_list_input_devices_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+void
+xcb_input_event_type_base_next (xcb_input_event_type_base_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_event_type_base_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_event_type_base_end (xcb_input_event_type_base_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_input_class_info_next (xcb_input_input_class_info_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_input_class_info_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_input_class_info_end (xcb_input_input_class_info_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+int
+xcb_input_open_device_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_open_device_reply_t *_aux = (xcb_input_open_device_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_open_device_reply_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* class_info */
+ xcb_block_len += _aux->num_classes * sizeof(xcb_input_input_class_info_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_input_class_info_t);
+ xcb_align_to = 4;
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_open_device_cookie_t
+xcb_input_open_device (xcb_connection_t *c,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_OPEN_DEVICE,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_open_device_cookie_t xcb_ret;
+ xcb_input_open_device_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_open_device_cookie_t
+xcb_input_open_device_unchecked (xcb_connection_t *c,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_OPEN_DEVICE,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_open_device_cookie_t xcb_ret;
+ xcb_input_open_device_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_input_class_info_t *
+xcb_input_open_device_class_info (const xcb_input_open_device_reply_t *R)
+{
+ return (xcb_input_input_class_info_t *) (R + 1);
+}
+
+int
+xcb_input_open_device_class_info_length (const xcb_input_open_device_reply_t *R)
+{
+ return R->num_classes;
+}
+
+xcb_input_input_class_info_iterator_t
+xcb_input_open_device_class_info_iterator (const xcb_input_open_device_reply_t *R)
+{
+ xcb_input_input_class_info_iterator_t i;
+ i.data = (xcb_input_input_class_info_t *) (R + 1);
+ i.rem = R->num_classes;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_open_device_reply_t *
+xcb_input_open_device_reply (xcb_connection_t *c,
+ xcb_input_open_device_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_open_device_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+xcb_void_cookie_t
+xcb_input_close_device_checked (xcb_connection_t *c,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_CLOSE_DEVICE,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_close_device_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_close_device (xcb_connection_t *c,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_CLOSE_DEVICE,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_close_device_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_set_device_mode_cookie_t
+xcb_input_set_device_mode (xcb_connection_t *c,
+ uint8_t device_id,
+ uint8_t mode)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_SET_DEVICE_MODE,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_set_device_mode_cookie_t xcb_ret;
+ xcb_input_set_device_mode_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ xcb_out.mode = mode;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_set_device_mode_cookie_t
+xcb_input_set_device_mode_unchecked (xcb_connection_t *c,
+ uint8_t device_id,
+ uint8_t mode)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_SET_DEVICE_MODE,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_set_device_mode_cookie_t xcb_ret;
+ xcb_input_set_device_mode_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ xcb_out.mode = mode;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_set_device_mode_reply_t *
+xcb_input_set_device_mode_reply (xcb_connection_t *c,
+ xcb_input_set_device_mode_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_set_device_mode_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+int
+xcb_input_select_extension_event_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_select_extension_event_request_t *_aux = (xcb_input_select_extension_event_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_select_extension_event_request_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* classes */
+ xcb_block_len += _aux->num_classes * sizeof(xcb_input_event_class_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_event_class_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_void_cookie_t
+xcb_input_select_extension_event_checked (xcb_connection_t *c,
+ xcb_window_t window,
+ uint16_t num_classes,
+ const xcb_input_event_class_t *classes)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_SELECT_EXTENSION_EVENT,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_select_extension_event_request_t xcb_out;
+
+ xcb_out.window = window;
+ xcb_out.num_classes = num_classes;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_event_class_t classes */
+ xcb_parts[4].iov_base = (char *) classes;
+ xcb_parts[4].iov_len = num_classes * sizeof(xcb_input_event_class_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_select_extension_event (xcb_connection_t *c,
+ xcb_window_t window,
+ uint16_t num_classes,
+ const xcb_input_event_class_t *classes)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_SELECT_EXTENSION_EVENT,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_select_extension_event_request_t xcb_out;
+
+ xcb_out.window = window;
+ xcb_out.num_classes = num_classes;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_event_class_t classes */
+ xcb_parts[4].iov_base = (char *) classes;
+ xcb_parts[4].iov_len = num_classes * sizeof(xcb_input_event_class_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_event_class_t *
+xcb_input_select_extension_event_classes (const xcb_input_select_extension_event_request_t *R)
+{
+ return (xcb_input_event_class_t *) (R + 1);
+}
+
+int
+xcb_input_select_extension_event_classes_length (const xcb_input_select_extension_event_request_t *R)
+{
+ return R->num_classes;
+}
+
+xcb_generic_iterator_t
+xcb_input_select_extension_event_classes_end (const xcb_input_select_extension_event_request_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((xcb_input_event_class_t *) (R + 1)) + (R->num_classes);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+int
+xcb_input_get_selected_extension_events_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_get_selected_extension_events_reply_t *_aux = (xcb_input_get_selected_extension_events_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_get_selected_extension_events_reply_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* this_classes */
+ xcb_block_len += _aux->num_this_classes * sizeof(xcb_input_event_class_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_event_class_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* all_classes */
+ xcb_block_len += _aux->num_all_classes * sizeof(xcb_input_event_class_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_event_class_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_get_selected_extension_events_cookie_t
+xcb_input_get_selected_extension_events (xcb_connection_t *c,
+ xcb_window_t window)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GET_SELECTED_EXTENSION_EVENTS,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_get_selected_extension_events_cookie_t xcb_ret;
+ xcb_input_get_selected_extension_events_request_t xcb_out;
+
+ xcb_out.window = window;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_get_selected_extension_events_cookie_t
+xcb_input_get_selected_extension_events_unchecked (xcb_connection_t *c,
+ xcb_window_t window)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GET_SELECTED_EXTENSION_EVENTS,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_get_selected_extension_events_cookie_t xcb_ret;
+ xcb_input_get_selected_extension_events_request_t xcb_out;
+
+ xcb_out.window = window;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_event_class_t *
+xcb_input_get_selected_extension_events_this_classes (const xcb_input_get_selected_extension_events_reply_t *R)
+{
+ return (xcb_input_event_class_t *) (R + 1);
+}
+
+int
+xcb_input_get_selected_extension_events_this_classes_length (const xcb_input_get_selected_extension_events_reply_t *R)
+{
+ return R->num_this_classes;
+}
+
+xcb_generic_iterator_t
+xcb_input_get_selected_extension_events_this_classes_end (const xcb_input_get_selected_extension_events_reply_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((xcb_input_event_class_t *) (R + 1)) + (R->num_this_classes);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_event_class_t *
+xcb_input_get_selected_extension_events_all_classes (const xcb_input_get_selected_extension_events_reply_t *R)
+{
+ xcb_generic_iterator_t prev = xcb_input_get_selected_extension_events_this_classes_end(R);
+ return (xcb_input_event_class_t *) ((char *) prev.data + XCB_TYPE_PAD(xcb_input_event_class_t, prev.index) + 0);
+}
+
+int
+xcb_input_get_selected_extension_events_all_classes_length (const xcb_input_get_selected_extension_events_reply_t *R)
+{
+ return R->num_all_classes;
+}
+
+xcb_generic_iterator_t
+xcb_input_get_selected_extension_events_all_classes_end (const xcb_input_get_selected_extension_events_reply_t *R)
+{
+ xcb_generic_iterator_t i;
+ xcb_generic_iterator_t prev = xcb_input_get_selected_extension_events_this_classes_end(R);
+ i.data = ((xcb_input_event_class_t *) ((char*) prev.data + XCB_TYPE_PAD(xcb_input_event_class_t, prev.index))) + (R->num_all_classes);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_get_selected_extension_events_reply_t *
+xcb_input_get_selected_extension_events_reply (xcb_connection_t *c,
+ xcb_input_get_selected_extension_events_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_get_selected_extension_events_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+int
+xcb_input_change_device_dont_propagate_list_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_change_device_dont_propagate_list_request_t *_aux = (xcb_input_change_device_dont_propagate_list_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_change_device_dont_propagate_list_request_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* classes */
+ xcb_block_len += _aux->num_classes * sizeof(xcb_input_event_class_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_event_class_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_void_cookie_t
+xcb_input_change_device_dont_propagate_list_checked (xcb_connection_t *c,
+ xcb_window_t window,
+ uint16_t num_classes,
+ uint8_t mode,
+ const xcb_input_event_class_t *classes)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_CHANGE_DEVICE_DONT_PROPAGATE_LIST,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_change_device_dont_propagate_list_request_t xcb_out;
+
+ xcb_out.window = window;
+ xcb_out.num_classes = num_classes;
+ xcb_out.mode = mode;
+ xcb_out.pad0 = 0;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_event_class_t classes */
+ xcb_parts[4].iov_base = (char *) classes;
+ xcb_parts[4].iov_len = num_classes * sizeof(xcb_input_event_class_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_change_device_dont_propagate_list (xcb_connection_t *c,
+ xcb_window_t window,
+ uint16_t num_classes,
+ uint8_t mode,
+ const xcb_input_event_class_t *classes)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_CHANGE_DEVICE_DONT_PROPAGATE_LIST,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_change_device_dont_propagate_list_request_t xcb_out;
+
+ xcb_out.window = window;
+ xcb_out.num_classes = num_classes;
+ xcb_out.mode = mode;
+ xcb_out.pad0 = 0;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_event_class_t classes */
+ xcb_parts[4].iov_base = (char *) classes;
+ xcb_parts[4].iov_len = num_classes * sizeof(xcb_input_event_class_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_event_class_t *
+xcb_input_change_device_dont_propagate_list_classes (const xcb_input_change_device_dont_propagate_list_request_t *R)
+{
+ return (xcb_input_event_class_t *) (R + 1);
+}
+
+int
+xcb_input_change_device_dont_propagate_list_classes_length (const xcb_input_change_device_dont_propagate_list_request_t *R)
+{
+ return R->num_classes;
+}
+
+xcb_generic_iterator_t
+xcb_input_change_device_dont_propagate_list_classes_end (const xcb_input_change_device_dont_propagate_list_request_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((xcb_input_event_class_t *) (R + 1)) + (R->num_classes);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+int
+xcb_input_get_device_dont_propagate_list_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_get_device_dont_propagate_list_reply_t *_aux = (xcb_input_get_device_dont_propagate_list_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_get_device_dont_propagate_list_reply_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* classes */
+ xcb_block_len += _aux->num_classes * sizeof(xcb_input_event_class_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_event_class_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_get_device_dont_propagate_list_cookie_t
+xcb_input_get_device_dont_propagate_list (xcb_connection_t *c,
+ xcb_window_t window)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GET_DEVICE_DONT_PROPAGATE_LIST,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_get_device_dont_propagate_list_cookie_t xcb_ret;
+ xcb_input_get_device_dont_propagate_list_request_t xcb_out;
+
+ xcb_out.window = window;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_get_device_dont_propagate_list_cookie_t
+xcb_input_get_device_dont_propagate_list_unchecked (xcb_connection_t *c,
+ xcb_window_t window)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GET_DEVICE_DONT_PROPAGATE_LIST,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_get_device_dont_propagate_list_cookie_t xcb_ret;
+ xcb_input_get_device_dont_propagate_list_request_t xcb_out;
+
+ xcb_out.window = window;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_event_class_t *
+xcb_input_get_device_dont_propagate_list_classes (const xcb_input_get_device_dont_propagate_list_reply_t *R)
+{
+ return (xcb_input_event_class_t *) (R + 1);
+}
+
+int
+xcb_input_get_device_dont_propagate_list_classes_length (const xcb_input_get_device_dont_propagate_list_reply_t *R)
+{
+ return R->num_classes;
+}
+
+xcb_generic_iterator_t
+xcb_input_get_device_dont_propagate_list_classes_end (const xcb_input_get_device_dont_propagate_list_reply_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((xcb_input_event_class_t *) (R + 1)) + (R->num_classes);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_get_device_dont_propagate_list_reply_t *
+xcb_input_get_device_dont_propagate_list_reply (xcb_connection_t *c,
+ xcb_input_get_device_dont_propagate_list_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_get_device_dont_propagate_list_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+int
+xcb_input_device_time_coord_sizeof (const void *_buffer,
+ uint8_t num_axes)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_device_time_coord_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* axisvalues */
+ xcb_block_len += num_axes * sizeof(int32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(int32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+int32_t *
+xcb_input_device_time_coord_axisvalues (const xcb_input_device_time_coord_t *R)
+{
+ return (int32_t *) (R + 1);
+}
+
+int
+xcb_input_device_time_coord_axisvalues_length (const xcb_input_device_time_coord_t *R,
+ uint8_t num_axes)
+{
+ return num_axes;
+}
+
+xcb_generic_iterator_t
+xcb_input_device_time_coord_axisvalues_end (const xcb_input_device_time_coord_t *R,
+ uint8_t num_axes)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((int32_t *) (R + 1)) + (num_axes);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+void
+xcb_input_device_time_coord_next (xcb_input_device_time_coord_iterator_t *i)
+{
+ xcb_input_device_time_coord_t *R = i->data;
+ xcb_generic_iterator_t child;
+ child.data = (xcb_input_device_time_coord_t *)(((char *)R) + xcb_input_device_time_coord_sizeof(R, i->num_axes));
+ i->index = (char *) child.data - (char *) i->data;
+ --i->rem;
+ i->data = (xcb_input_device_time_coord_t *) child.data;
+}
+
+xcb_generic_iterator_t
+xcb_input_device_time_coord_end (xcb_input_device_time_coord_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ while(i.rem > 0)
+ xcb_input_device_time_coord_next(&i);
+ ret.data = i.data;
+ ret.rem = i.rem;
+ ret.index = i.index;
+ return ret;
+}
+
+int
+xcb_input_get_device_motion_events_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_get_device_motion_events_reply_t *_aux = (xcb_input_get_device_motion_events_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+ unsigned int i;
+ unsigned int xcb_tmp_len;
+
+ xcb_block_len += sizeof(xcb_input_get_device_motion_events_reply_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* events */
+ for(i=0; i<_aux->num_events; i++) {
+ xcb_tmp_len = xcb_input_device_time_coord_sizeof(xcb_tmp, _aux->num_axes);
+ xcb_block_len += xcb_tmp_len;
+ xcb_tmp += xcb_tmp_len;
+ }
+ xcb_align_to = ALIGNOF(xcb_input_device_time_coord_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_get_device_motion_events_cookie_t
+xcb_input_get_device_motion_events (xcb_connection_t *c,
+ xcb_timestamp_t start,
+ xcb_timestamp_t stop,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GET_DEVICE_MOTION_EVENTS,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_get_device_motion_events_cookie_t xcb_ret;
+ xcb_input_get_device_motion_events_request_t xcb_out;
+
+ xcb_out.start = start;
+ xcb_out.stop = stop;
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_get_device_motion_events_cookie_t
+xcb_input_get_device_motion_events_unchecked (xcb_connection_t *c,
+ xcb_timestamp_t start,
+ xcb_timestamp_t stop,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GET_DEVICE_MOTION_EVENTS,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_get_device_motion_events_cookie_t xcb_ret;
+ xcb_input_get_device_motion_events_request_t xcb_out;
+
+ xcb_out.start = start;
+ xcb_out.stop = stop;
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+int
+xcb_input_get_device_motion_events_events_length (const xcb_input_get_device_motion_events_reply_t *R)
+{
+ return R->num_events;
+}
+
+xcb_input_device_time_coord_iterator_t
+xcb_input_get_device_motion_events_events_iterator (const xcb_input_get_device_motion_events_reply_t *R)
+{
+ xcb_input_device_time_coord_iterator_t i;
+ i.data = (xcb_input_device_time_coord_t *) (R + 1);
+ i.rem = R->num_events;
+ i.index = (char *) i.data - (char *) R;
+ i.num_axes = R->num_axes;
+ return i;
+}
+
+xcb_input_get_device_motion_events_reply_t *
+xcb_input_get_device_motion_events_reply (xcb_connection_t *c,
+ xcb_input_get_device_motion_events_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_get_device_motion_events_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+xcb_input_change_keyboard_device_cookie_t
+xcb_input_change_keyboard_device (xcb_connection_t *c,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_CHANGE_KEYBOARD_DEVICE,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_change_keyboard_device_cookie_t xcb_ret;
+ xcb_input_change_keyboard_device_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_change_keyboard_device_cookie_t
+xcb_input_change_keyboard_device_unchecked (xcb_connection_t *c,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_CHANGE_KEYBOARD_DEVICE,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_change_keyboard_device_cookie_t xcb_ret;
+ xcb_input_change_keyboard_device_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_change_keyboard_device_reply_t *
+xcb_input_change_keyboard_device_reply (xcb_connection_t *c,
+ xcb_input_change_keyboard_device_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_change_keyboard_device_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+xcb_input_change_pointer_device_cookie_t
+xcb_input_change_pointer_device (xcb_connection_t *c,
+ uint8_t x_axis,
+ uint8_t y_axis,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_CHANGE_POINTER_DEVICE,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_change_pointer_device_cookie_t xcb_ret;
+ xcb_input_change_pointer_device_request_t xcb_out;
+
+ xcb_out.x_axis = x_axis;
+ xcb_out.y_axis = y_axis;
+ xcb_out.device_id = device_id;
+ xcb_out.pad0 = 0;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_change_pointer_device_cookie_t
+xcb_input_change_pointer_device_unchecked (xcb_connection_t *c,
+ uint8_t x_axis,
+ uint8_t y_axis,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_CHANGE_POINTER_DEVICE,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_change_pointer_device_cookie_t xcb_ret;
+ xcb_input_change_pointer_device_request_t xcb_out;
+
+ xcb_out.x_axis = x_axis;
+ xcb_out.y_axis = y_axis;
+ xcb_out.device_id = device_id;
+ xcb_out.pad0 = 0;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_change_pointer_device_reply_t *
+xcb_input_change_pointer_device_reply (xcb_connection_t *c,
+ xcb_input_change_pointer_device_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_change_pointer_device_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+int
+xcb_input_grab_device_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_grab_device_request_t *_aux = (xcb_input_grab_device_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_grab_device_request_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* classes */
+ xcb_block_len += _aux->num_classes * sizeof(xcb_input_event_class_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_event_class_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_grab_device_cookie_t
+xcb_input_grab_device (xcb_connection_t *c,
+ xcb_window_t grab_window,
+ xcb_timestamp_t time,
+ uint16_t num_classes,
+ uint8_t this_device_mode,
+ uint8_t other_device_mode,
+ uint8_t owner_events,
+ uint8_t device_id,
+ const xcb_input_event_class_t *classes)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GRAB_DEVICE,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_input_grab_device_cookie_t xcb_ret;
+ xcb_input_grab_device_request_t xcb_out;
+
+ xcb_out.grab_window = grab_window;
+ xcb_out.time = time;
+ xcb_out.num_classes = num_classes;
+ xcb_out.this_device_mode = this_device_mode;
+ xcb_out.other_device_mode = other_device_mode;
+ xcb_out.owner_events = owner_events;
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_event_class_t classes */
+ xcb_parts[4].iov_base = (char *) classes;
+ xcb_parts[4].iov_len = num_classes * sizeof(uint32_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_grab_device_cookie_t
+xcb_input_grab_device_unchecked (xcb_connection_t *c,
+ xcb_window_t grab_window,
+ xcb_timestamp_t time,
+ uint16_t num_classes,
+ uint8_t this_device_mode,
+ uint8_t other_device_mode,
+ uint8_t owner_events,
+ uint8_t device_id,
+ const xcb_input_event_class_t *classes)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GRAB_DEVICE,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_input_grab_device_cookie_t xcb_ret;
+ xcb_input_grab_device_request_t xcb_out;
+
+ xcb_out.grab_window = grab_window;
+ xcb_out.time = time;
+ xcb_out.num_classes = num_classes;
+ xcb_out.this_device_mode = this_device_mode;
+ xcb_out.other_device_mode = other_device_mode;
+ xcb_out.owner_events = owner_events;
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_event_class_t classes */
+ xcb_parts[4].iov_base = (char *) classes;
+ xcb_parts[4].iov_len = num_classes * sizeof(uint32_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_grab_device_reply_t *
+xcb_input_grab_device_reply (xcb_connection_t *c,
+ xcb_input_grab_device_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_grab_device_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+xcb_void_cookie_t
+xcb_input_ungrab_device_checked (xcb_connection_t *c,
+ xcb_timestamp_t time,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_UNGRAB_DEVICE,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_ungrab_device_request_t xcb_out;
+
+ xcb_out.time = time;
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_ungrab_device (xcb_connection_t *c,
+ xcb_timestamp_t time,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_UNGRAB_DEVICE,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_ungrab_device_request_t xcb_out;
+
+ xcb_out.time = time;
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+int
+xcb_input_grab_device_key_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_grab_device_key_request_t *_aux = (xcb_input_grab_device_key_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_grab_device_key_request_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* classes */
+ xcb_block_len += _aux->num_classes * sizeof(xcb_input_event_class_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_event_class_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_void_cookie_t
+xcb_input_grab_device_key_checked (xcb_connection_t *c,
+ xcb_window_t grab_window,
+ uint16_t num_classes,
+ uint16_t modifiers,
+ uint8_t modifier_device,
+ uint8_t grabbed_device,
+ uint8_t key,
+ uint8_t this_device_mode,
+ uint8_t other_device_mode,
+ uint8_t owner_events,
+ const xcb_input_event_class_t *classes)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GRAB_DEVICE_KEY,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_grab_device_key_request_t xcb_out;
+
+ xcb_out.grab_window = grab_window;
+ xcb_out.num_classes = num_classes;
+ xcb_out.modifiers = modifiers;
+ xcb_out.modifier_device = modifier_device;
+ xcb_out.grabbed_device = grabbed_device;
+ xcb_out.key = key;
+ xcb_out.this_device_mode = this_device_mode;
+ xcb_out.other_device_mode = other_device_mode;
+ xcb_out.owner_events = owner_events;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_event_class_t classes */
+ xcb_parts[4].iov_base = (char *) classes;
+ xcb_parts[4].iov_len = num_classes * sizeof(xcb_input_event_class_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_grab_device_key (xcb_connection_t *c,
+ xcb_window_t grab_window,
+ uint16_t num_classes,
+ uint16_t modifiers,
+ uint8_t modifier_device,
+ uint8_t grabbed_device,
+ uint8_t key,
+ uint8_t this_device_mode,
+ uint8_t other_device_mode,
+ uint8_t owner_events,
+ const xcb_input_event_class_t *classes)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GRAB_DEVICE_KEY,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_grab_device_key_request_t xcb_out;
+
+ xcb_out.grab_window = grab_window;
+ xcb_out.num_classes = num_classes;
+ xcb_out.modifiers = modifiers;
+ xcb_out.modifier_device = modifier_device;
+ xcb_out.grabbed_device = grabbed_device;
+ xcb_out.key = key;
+ xcb_out.this_device_mode = this_device_mode;
+ xcb_out.other_device_mode = other_device_mode;
+ xcb_out.owner_events = owner_events;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_event_class_t classes */
+ xcb_parts[4].iov_base = (char *) classes;
+ xcb_parts[4].iov_len = num_classes * sizeof(xcb_input_event_class_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_event_class_t *
+xcb_input_grab_device_key_classes (const xcb_input_grab_device_key_request_t *R)
+{
+ return (xcb_input_event_class_t *) (R + 1);
+}
+
+int
+xcb_input_grab_device_key_classes_length (const xcb_input_grab_device_key_request_t *R)
+{
+ return R->num_classes;
+}
+
+xcb_generic_iterator_t
+xcb_input_grab_device_key_classes_end (const xcb_input_grab_device_key_request_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((xcb_input_event_class_t *) (R + 1)) + (R->num_classes);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_void_cookie_t
+xcb_input_ungrab_device_key_checked (xcb_connection_t *c,
+ xcb_window_t grabWindow,
+ uint16_t modifiers,
+ uint8_t modifier_device,
+ uint8_t key,
+ uint8_t grabbed_device)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_UNGRAB_DEVICE_KEY,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_ungrab_device_key_request_t xcb_out;
+
+ xcb_out.grabWindow = grabWindow;
+ xcb_out.modifiers = modifiers;
+ xcb_out.modifier_device = modifier_device;
+ xcb_out.key = key;
+ xcb_out.grabbed_device = grabbed_device;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_ungrab_device_key (xcb_connection_t *c,
+ xcb_window_t grabWindow,
+ uint16_t modifiers,
+ uint8_t modifier_device,
+ uint8_t key,
+ uint8_t grabbed_device)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_UNGRAB_DEVICE_KEY,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_ungrab_device_key_request_t xcb_out;
+
+ xcb_out.grabWindow = grabWindow;
+ xcb_out.modifiers = modifiers;
+ xcb_out.modifier_device = modifier_device;
+ xcb_out.key = key;
+ xcb_out.grabbed_device = grabbed_device;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+int
+xcb_input_grab_device_button_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_grab_device_button_request_t *_aux = (xcb_input_grab_device_button_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_grab_device_button_request_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* classes */
+ xcb_block_len += _aux->num_classes * sizeof(xcb_input_event_class_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_event_class_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_void_cookie_t
+xcb_input_grab_device_button_checked (xcb_connection_t *c,
+ xcb_window_t grab_window,
+ uint8_t grabbed_device,
+ uint8_t modifier_device,
+ uint16_t num_classes,
+ uint16_t modifiers,
+ uint8_t this_device_mode,
+ uint8_t other_device_mode,
+ uint8_t button,
+ uint8_t owner_events,
+ const xcb_input_event_class_t *classes)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GRAB_DEVICE_BUTTON,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_grab_device_button_request_t xcb_out;
+
+ xcb_out.grab_window = grab_window;
+ xcb_out.grabbed_device = grabbed_device;
+ xcb_out.modifier_device = modifier_device;
+ xcb_out.num_classes = num_classes;
+ xcb_out.modifiers = modifiers;
+ xcb_out.this_device_mode = this_device_mode;
+ xcb_out.other_device_mode = other_device_mode;
+ xcb_out.button = button;
+ xcb_out.owner_events = owner_events;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_event_class_t classes */
+ xcb_parts[4].iov_base = (char *) classes;
+ xcb_parts[4].iov_len = num_classes * sizeof(xcb_input_event_class_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_grab_device_button (xcb_connection_t *c,
+ xcb_window_t grab_window,
+ uint8_t grabbed_device,
+ uint8_t modifier_device,
+ uint16_t num_classes,
+ uint16_t modifiers,
+ uint8_t this_device_mode,
+ uint8_t other_device_mode,
+ uint8_t button,
+ uint8_t owner_events,
+ const xcb_input_event_class_t *classes)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GRAB_DEVICE_BUTTON,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_grab_device_button_request_t xcb_out;
+
+ xcb_out.grab_window = grab_window;
+ xcb_out.grabbed_device = grabbed_device;
+ xcb_out.modifier_device = modifier_device;
+ xcb_out.num_classes = num_classes;
+ xcb_out.modifiers = modifiers;
+ xcb_out.this_device_mode = this_device_mode;
+ xcb_out.other_device_mode = other_device_mode;
+ xcb_out.button = button;
+ xcb_out.owner_events = owner_events;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_event_class_t classes */
+ xcb_parts[4].iov_base = (char *) classes;
+ xcb_parts[4].iov_len = num_classes * sizeof(xcb_input_event_class_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_event_class_t *
+xcb_input_grab_device_button_classes (const xcb_input_grab_device_button_request_t *R)
+{
+ return (xcb_input_event_class_t *) (R + 1);
+}
+
+int
+xcb_input_grab_device_button_classes_length (const xcb_input_grab_device_button_request_t *R)
+{
+ return R->num_classes;
+}
+
+xcb_generic_iterator_t
+xcb_input_grab_device_button_classes_end (const xcb_input_grab_device_button_request_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((xcb_input_event_class_t *) (R + 1)) + (R->num_classes);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_void_cookie_t
+xcb_input_ungrab_device_button_checked (xcb_connection_t *c,
+ xcb_window_t grab_window,
+ uint16_t modifiers,
+ uint8_t modifier_device,
+ uint8_t button,
+ uint8_t grabbed_device)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_UNGRAB_DEVICE_BUTTON,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_ungrab_device_button_request_t xcb_out;
+
+ xcb_out.grab_window = grab_window;
+ xcb_out.modifiers = modifiers;
+ xcb_out.modifier_device = modifier_device;
+ xcb_out.button = button;
+ xcb_out.grabbed_device = grabbed_device;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_ungrab_device_button (xcb_connection_t *c,
+ xcb_window_t grab_window,
+ uint16_t modifiers,
+ uint8_t modifier_device,
+ uint8_t button,
+ uint8_t grabbed_device)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_UNGRAB_DEVICE_BUTTON,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_ungrab_device_button_request_t xcb_out;
+
+ xcb_out.grab_window = grab_window;
+ xcb_out.modifiers = modifiers;
+ xcb_out.modifier_device = modifier_device;
+ xcb_out.button = button;
+ xcb_out.grabbed_device = grabbed_device;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_allow_device_events_checked (xcb_connection_t *c,
+ xcb_timestamp_t time,
+ uint8_t mode,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_ALLOW_DEVICE_EVENTS,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_allow_device_events_request_t xcb_out;
+
+ xcb_out.time = time;
+ xcb_out.mode = mode;
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_allow_device_events (xcb_connection_t *c,
+ xcb_timestamp_t time,
+ uint8_t mode,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_ALLOW_DEVICE_EVENTS,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_allow_device_events_request_t xcb_out;
+
+ xcb_out.time = time;
+ xcb_out.mode = mode;
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_get_device_focus_cookie_t
+xcb_input_get_device_focus (xcb_connection_t *c,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GET_DEVICE_FOCUS,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_get_device_focus_cookie_t xcb_ret;
+ xcb_input_get_device_focus_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_get_device_focus_cookie_t
+xcb_input_get_device_focus_unchecked (xcb_connection_t *c,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GET_DEVICE_FOCUS,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_get_device_focus_cookie_t xcb_ret;
+ xcb_input_get_device_focus_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_get_device_focus_reply_t *
+xcb_input_get_device_focus_reply (xcb_connection_t *c,
+ xcb_input_get_device_focus_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_get_device_focus_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+xcb_void_cookie_t
+xcb_input_set_device_focus_checked (xcb_connection_t *c,
+ xcb_window_t focus,
+ xcb_timestamp_t time,
+ uint8_t revert_to,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_SET_DEVICE_FOCUS,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_set_device_focus_request_t xcb_out;
+
+ xcb_out.focus = focus;
+ xcb_out.time = time;
+ xcb_out.revert_to = revert_to;
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_set_device_focus (xcb_connection_t *c,
+ xcb_window_t focus,
+ xcb_timestamp_t time,
+ uint8_t revert_to,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_SET_DEVICE_FOCUS,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_set_device_focus_request_t xcb_out;
+
+ xcb_out.focus = focus;
+ xcb_out.time = time;
+ xcb_out.revert_to = revert_to;
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+void
+xcb_input_kbd_feedback_state_next (xcb_input_kbd_feedback_state_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_kbd_feedback_state_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_kbd_feedback_state_end (xcb_input_kbd_feedback_state_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_ptr_feedback_state_next (xcb_input_ptr_feedback_state_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_ptr_feedback_state_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_ptr_feedback_state_end (xcb_input_ptr_feedback_state_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_integer_feedback_state_next (xcb_input_integer_feedback_state_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_integer_feedback_state_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_integer_feedback_state_end (xcb_input_integer_feedback_state_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+int
+xcb_input_string_feedback_state_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_string_feedback_state_t *_aux = (xcb_input_string_feedback_state_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_string_feedback_state_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* keysyms */
+ xcb_block_len += _aux->num_keysyms * sizeof(xcb_keysym_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_keysym_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_keysym_t *
+xcb_input_string_feedback_state_keysyms (const xcb_input_string_feedback_state_t *R)
+{
+ return (xcb_keysym_t *) (R + 1);
+}
+
+int
+xcb_input_string_feedback_state_keysyms_length (const xcb_input_string_feedback_state_t *R)
+{
+ return R->num_keysyms;
+}
+
+xcb_generic_iterator_t
+xcb_input_string_feedback_state_keysyms_end (const xcb_input_string_feedback_state_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((xcb_keysym_t *) (R + 1)) + (R->num_keysyms);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+void
+xcb_input_string_feedback_state_next (xcb_input_string_feedback_state_iterator_t *i)
+{
+ xcb_input_string_feedback_state_t *R = i->data;
+ xcb_generic_iterator_t child;
+ child.data = (xcb_input_string_feedback_state_t *)(((char *)R) + xcb_input_string_feedback_state_sizeof(R));
+ i->index = (char *) child.data - (char *) i->data;
+ --i->rem;
+ i->data = (xcb_input_string_feedback_state_t *) child.data;
+}
+
+xcb_generic_iterator_t
+xcb_input_string_feedback_state_end (xcb_input_string_feedback_state_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ while(i.rem > 0)
+ xcb_input_string_feedback_state_next(&i);
+ ret.data = i.data;
+ ret.rem = i.rem;
+ ret.index = i.index;
+ return ret;
+}
+
+void
+xcb_input_bell_feedback_state_next (xcb_input_bell_feedback_state_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_bell_feedback_state_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_bell_feedback_state_end (xcb_input_bell_feedback_state_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_led_feedback_state_next (xcb_input_led_feedback_state_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_led_feedback_state_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_led_feedback_state_end (xcb_input_led_feedback_state_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+xcb_keysym_t *
+xcb_input_feedback_state_data_string_keysyms (const xcb_input_feedback_state_data_t *S)
+{
+ return S->string.keysyms;
+}
+
+int
+xcb_input_feedback_state_data_string_keysyms_length (const xcb_input_feedback_state_t *R,
+ const xcb_input_feedback_state_data_t *S)
+{
+ return S->string.num_keysyms;
+}
+
+xcb_generic_iterator_t
+xcb_input_feedback_state_data_string_keysyms_end (const xcb_input_feedback_state_t *R,
+ const xcb_input_feedback_state_data_t *S)
+{
+ xcb_generic_iterator_t i;
+ i.data = S->string.keysyms + S->string.num_keysyms;
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) S;
+ return i;
+}
+
+int
+xcb_input_feedback_state_data_serialize (void **_buffer,
+ uint8_t class_id,
+ const xcb_input_feedback_state_data_t *_aux)
+{
+ char *xcb_out = *_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_align_to = 0;
+ unsigned int xcb_padding_offset = 0;
+
+ unsigned int xcb_pad = 0;
+ char xcb_pad0[3] = {0, 0, 0};
+ struct iovec xcb_parts[27];
+ unsigned int xcb_parts_idx = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int i;
+ char *xcb_tmp;
+
+ if(class_id == XCB_INPUT_FEEDBACK_CLASS_KEYBOARD) {
+ /* xcb_input_feedback_state_data_t.keyboard.pitch */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->keyboard.pitch;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* xcb_input_feedback_state_data_t.keyboard.duration */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->keyboard.duration;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* xcb_input_feedback_state_data_t.keyboard.led_mask */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->keyboard.led_mask;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_feedback_state_data_t.keyboard.led_values */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->keyboard.led_values;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_feedback_state_data_t.keyboard.global_auto_repeat */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->keyboard.global_auto_repeat;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_feedback_state_data_t.keyboard.click */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->keyboard.click;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_feedback_state_data_t.keyboard.percent */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->keyboard.percent;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_feedback_state_data_t.keyboard.pad0 */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &xcb_pad;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_feedback_state_data_t.keyboard.auto_repeats */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->keyboard.auto_repeats;
+ xcb_block_len += 32;
+ xcb_parts[xcb_parts_idx].iov_len = 32;
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ }
+ if(class_id == XCB_INPUT_FEEDBACK_CLASS_POINTER) {
+ /* xcb_input_feedback_state_data_t.pointer.pad1 */
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_block_len += sizeof(uint8_t)*2;
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t)*2;
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_feedback_state_data_t.pointer.accel_num */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->pointer.accel_num;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* xcb_input_feedback_state_data_t.pointer.accel_denom */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->pointer.accel_denom;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* xcb_input_feedback_state_data_t.pointer.threshold */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->pointer.threshold;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint16_t);
+ }
+ if(class_id == XCB_INPUT_FEEDBACK_CLASS_STRING) {
+ /* xcb_input_feedback_state_data_t.string.max_symbols */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->string.max_symbols;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* xcb_input_feedback_state_data_t.string.num_keysyms */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->string.num_keysyms;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* keysyms */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->string.keysyms;
+ xcb_block_len += _aux->string.num_keysyms * sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = _aux->string.num_keysyms * sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(xcb_keysym_t);
+ }
+ if(class_id == XCB_INPUT_FEEDBACK_CLASS_INTEGER) {
+ /* xcb_input_feedback_state_data_t.integer.resolution */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->integer.resolution;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_feedback_state_data_t.integer.min_value */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->integer.min_value;
+ xcb_block_len += sizeof(int32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(int32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int32_t);
+ /* xcb_input_feedback_state_data_t.integer.max_value */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->integer.max_value;
+ xcb_block_len += sizeof(int32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(int32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int32_t);
+ }
+ if(class_id == XCB_INPUT_FEEDBACK_CLASS_LED) {
+ /* xcb_input_feedback_state_data_t.led.led_mask */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->led.led_mask;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_feedback_state_data_t.led.led_values */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->led.led_values;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ if(class_id == XCB_INPUT_FEEDBACK_CLASS_BELL) {
+ /* xcb_input_feedback_state_data_t.bell.percent */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->bell.percent;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_feedback_state_data_t.bell.pad2 */
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_block_len += sizeof(uint8_t)*3;
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t)*3;
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_feedback_state_data_t.bell.pitch */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->bell.pitch;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* xcb_input_feedback_state_data_t.bell.duration */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->bell.duration;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint16_t);
+ }
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+
+ if (NULL == xcb_out) {
+ /* allocate memory */
+ xcb_out = malloc(xcb_buffer_len);
+ *_buffer = xcb_out;
+ }
+
+ xcb_tmp = xcb_out;
+ for(i=0; i<xcb_parts_idx; i++) {
+ if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)
+ memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);
+ if (0 != xcb_parts[i].iov_len)
+ xcb_tmp += xcb_parts[i].iov_len;
+ }
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_feedback_state_data_unpack (const void *_buffer,
+ uint8_t class_id,
+ xcb_input_feedback_state_data_t *_aux)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+ unsigned int xcb_padding_offset = 0;
+
+
+ if(class_id == XCB_INPUT_FEEDBACK_CLASS_KEYBOARD) {
+ /* xcb_input_feedback_state_data_t.keyboard.pitch */
+ _aux->keyboard.pitch = *(uint16_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_tmp += sizeof(uint16_t);
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* xcb_input_feedback_state_data_t.keyboard.duration */
+ _aux->keyboard.duration = *(uint16_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_tmp += sizeof(uint16_t);
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* xcb_input_feedback_state_data_t.keyboard.led_mask */
+ _aux->keyboard.led_mask = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_feedback_state_data_t.keyboard.led_values */
+ _aux->keyboard.led_values = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_feedback_state_data_t.keyboard.global_auto_repeat */
+ _aux->keyboard.global_auto_repeat = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_feedback_state_data_t.keyboard.click */
+ _aux->keyboard.click = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_feedback_state_data_t.keyboard.percent */
+ _aux->keyboard.percent = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_feedback_state_data_t.keyboard.pad0 */
+ _aux->keyboard.pad0 = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_feedback_state_data_t.keyboard.auto_repeats */
+ memcpy(_aux->keyboard.auto_repeats, xcb_tmp, sizeof(uint8_t) * 32);
+ xcb_block_len += sizeof(uint8_t) * 32;
+ xcb_tmp += sizeof(uint8_t) * 32;
+ xcb_align_to = ALIGNOF(uint8_t);
+ }
+ if(class_id == XCB_INPUT_FEEDBACK_CLASS_POINTER) {
+ /* xcb_input_feedback_state_data_t.pointer.pad1 */
+ _aux->pointer.pad1[0] = *(uint8_t *)xcb_tmp;
+ _aux->pointer.pad1[1] = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t) * 2;
+ xcb_tmp += sizeof(uint8_t) * 2;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_feedback_state_data_t.pointer.accel_num */
+ _aux->pointer.accel_num = *(uint16_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_tmp += sizeof(uint16_t);
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* xcb_input_feedback_state_data_t.pointer.accel_denom */
+ _aux->pointer.accel_denom = *(uint16_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_tmp += sizeof(uint16_t);
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* xcb_input_feedback_state_data_t.pointer.threshold */
+ _aux->pointer.threshold = *(uint16_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_tmp += sizeof(uint16_t);
+ xcb_align_to = ALIGNOF(uint16_t);
+ }
+ if(class_id == XCB_INPUT_FEEDBACK_CLASS_STRING) {
+ /* xcb_input_feedback_state_data_t.string.max_symbols */
+ _aux->string.max_symbols = *(uint16_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_tmp += sizeof(uint16_t);
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* xcb_input_feedback_state_data_t.string.num_keysyms */
+ _aux->string.num_keysyms = *(uint16_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_tmp += sizeof(uint16_t);
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* keysyms */
+ _aux->string.keysyms = (xcb_keysym_t *)xcb_tmp;
+ xcb_block_len += _aux->string.num_keysyms * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_keysym_t);
+ }
+ if(class_id == XCB_INPUT_FEEDBACK_CLASS_INTEGER) {
+ /* xcb_input_feedback_state_data_t.integer.resolution */
+ _aux->integer.resolution = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_feedback_state_data_t.integer.min_value */
+ _aux->integer.min_value = *(int32_t *)xcb_tmp;
+ xcb_block_len += sizeof(int32_t);
+ xcb_tmp += sizeof(int32_t);
+ xcb_align_to = ALIGNOF(int32_t);
+ /* xcb_input_feedback_state_data_t.integer.max_value */
+ _aux->integer.max_value = *(int32_t *)xcb_tmp;
+ xcb_block_len += sizeof(int32_t);
+ xcb_tmp += sizeof(int32_t);
+ xcb_align_to = ALIGNOF(int32_t);
+ }
+ if(class_id == XCB_INPUT_FEEDBACK_CLASS_LED) {
+ /* xcb_input_feedback_state_data_t.led.led_mask */
+ _aux->led.led_mask = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_feedback_state_data_t.led.led_values */
+ _aux->led.led_values = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ if(class_id == XCB_INPUT_FEEDBACK_CLASS_BELL) {
+ /* xcb_input_feedback_state_data_t.bell.percent */
+ _aux->bell.percent = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_feedback_state_data_t.bell.pad2 */
+ _aux->bell.pad2[0] = *(uint8_t *)xcb_tmp;
+ _aux->bell.pad2[1] = *(uint8_t *)xcb_tmp;
+ _aux->bell.pad2[2] = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t) * 3;
+ xcb_tmp += sizeof(uint8_t) * 3;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_feedback_state_data_t.bell.pitch */
+ _aux->bell.pitch = *(uint16_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_tmp += sizeof(uint16_t);
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* xcb_input_feedback_state_data_t.bell.duration */
+ _aux->bell.duration = *(uint16_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_tmp += sizeof(uint16_t);
+ xcb_align_to = ALIGNOF(uint16_t);
+ }
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_feedback_state_data_sizeof (const void *_buffer,
+ uint8_t class_id)
+{
+ xcb_input_feedback_state_data_t _aux;
+ return xcb_input_feedback_state_data_unpack(_buffer, class_id, &_aux);
+}
+
+int
+xcb_input_feedback_state_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_feedback_state_t *_aux = (xcb_input_feedback_state_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_feedback_state_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* data */
+ xcb_block_len += xcb_input_feedback_state_data_sizeof(xcb_tmp, _aux->class_id);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+void *
+xcb_input_feedback_state_data (const xcb_input_feedback_state_t *R)
+{
+ return (void *) (R + 1);
+}
+
+void
+xcb_input_feedback_state_next (xcb_input_feedback_state_iterator_t *i)
+{
+ xcb_input_feedback_state_t *R = i->data;
+ xcb_generic_iterator_t child;
+ child.data = (xcb_input_feedback_state_t *)(((char *)R) + xcb_input_feedback_state_sizeof(R));
+ i->index = (char *) child.data - (char *) i->data;
+ --i->rem;
+ i->data = (xcb_input_feedback_state_t *) child.data;
+}
+
+xcb_generic_iterator_t
+xcb_input_feedback_state_end (xcb_input_feedback_state_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ while(i.rem > 0)
+ xcb_input_feedback_state_next(&i);
+ ret.data = i.data;
+ ret.rem = i.rem;
+ ret.index = i.index;
+ return ret;
+}
+
+int
+xcb_input_get_feedback_control_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_get_feedback_control_reply_t *_aux = (xcb_input_get_feedback_control_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+ unsigned int i;
+ unsigned int xcb_tmp_len;
+
+ xcb_block_len += sizeof(xcb_input_get_feedback_control_reply_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* feedbacks */
+ for(i=0; i<_aux->num_feedbacks; i++) {
+ xcb_tmp_len = xcb_input_feedback_state_sizeof(xcb_tmp);
+ xcb_block_len += xcb_tmp_len;
+ xcb_tmp += xcb_tmp_len;
+ }
+ xcb_align_to = ALIGNOF(xcb_input_feedback_state_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_get_feedback_control_cookie_t
+xcb_input_get_feedback_control (xcb_connection_t *c,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GET_FEEDBACK_CONTROL,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_get_feedback_control_cookie_t xcb_ret;
+ xcb_input_get_feedback_control_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_get_feedback_control_cookie_t
+xcb_input_get_feedback_control_unchecked (xcb_connection_t *c,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GET_FEEDBACK_CONTROL,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_get_feedback_control_cookie_t xcb_ret;
+ xcb_input_get_feedback_control_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+int
+xcb_input_get_feedback_control_feedbacks_length (const xcb_input_get_feedback_control_reply_t *R)
+{
+ return R->num_feedbacks;
+}
+
+xcb_input_feedback_state_iterator_t
+xcb_input_get_feedback_control_feedbacks_iterator (const xcb_input_get_feedback_control_reply_t *R)
+{
+ xcb_input_feedback_state_iterator_t i;
+ i.data = (xcb_input_feedback_state_t *) (R + 1);
+ i.rem = R->num_feedbacks;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_get_feedback_control_reply_t *
+xcb_input_get_feedback_control_reply (xcb_connection_t *c,
+ xcb_input_get_feedback_control_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_get_feedback_control_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+void
+xcb_input_kbd_feedback_ctl_next (xcb_input_kbd_feedback_ctl_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_kbd_feedback_ctl_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_kbd_feedback_ctl_end (xcb_input_kbd_feedback_ctl_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_ptr_feedback_ctl_next (xcb_input_ptr_feedback_ctl_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_ptr_feedback_ctl_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_ptr_feedback_ctl_end (xcb_input_ptr_feedback_ctl_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_integer_feedback_ctl_next (xcb_input_integer_feedback_ctl_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_integer_feedback_ctl_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_integer_feedback_ctl_end (xcb_input_integer_feedback_ctl_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+int
+xcb_input_string_feedback_ctl_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_string_feedback_ctl_t *_aux = (xcb_input_string_feedback_ctl_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_string_feedback_ctl_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* keysyms */
+ xcb_block_len += _aux->num_keysyms * sizeof(xcb_keysym_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_keysym_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_keysym_t *
+xcb_input_string_feedback_ctl_keysyms (const xcb_input_string_feedback_ctl_t *R)
+{
+ return (xcb_keysym_t *) (R + 1);
+}
+
+int
+xcb_input_string_feedback_ctl_keysyms_length (const xcb_input_string_feedback_ctl_t *R)
+{
+ return R->num_keysyms;
+}
+
+xcb_generic_iterator_t
+xcb_input_string_feedback_ctl_keysyms_end (const xcb_input_string_feedback_ctl_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((xcb_keysym_t *) (R + 1)) + (R->num_keysyms);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+void
+xcb_input_string_feedback_ctl_next (xcb_input_string_feedback_ctl_iterator_t *i)
+{
+ xcb_input_string_feedback_ctl_t *R = i->data;
+ xcb_generic_iterator_t child;
+ child.data = (xcb_input_string_feedback_ctl_t *)(((char *)R) + xcb_input_string_feedback_ctl_sizeof(R));
+ i->index = (char *) child.data - (char *) i->data;
+ --i->rem;
+ i->data = (xcb_input_string_feedback_ctl_t *) child.data;
+}
+
+xcb_generic_iterator_t
+xcb_input_string_feedback_ctl_end (xcb_input_string_feedback_ctl_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ while(i.rem > 0)
+ xcb_input_string_feedback_ctl_next(&i);
+ ret.data = i.data;
+ ret.rem = i.rem;
+ ret.index = i.index;
+ return ret;
+}
+
+void
+xcb_input_bell_feedback_ctl_next (xcb_input_bell_feedback_ctl_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_bell_feedback_ctl_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_bell_feedback_ctl_end (xcb_input_bell_feedback_ctl_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_led_feedback_ctl_next (xcb_input_led_feedback_ctl_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_led_feedback_ctl_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_led_feedback_ctl_end (xcb_input_led_feedback_ctl_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+xcb_keysym_t *
+xcb_input_feedback_ctl_data_string_keysyms (const xcb_input_feedback_ctl_data_t *S)
+{
+ return S->string.keysyms;
+}
+
+int
+xcb_input_feedback_ctl_data_string_keysyms_length (const xcb_input_feedback_ctl_t *R,
+ const xcb_input_feedback_ctl_data_t *S)
+{
+ return S->string.num_keysyms;
+}
+
+xcb_generic_iterator_t
+xcb_input_feedback_ctl_data_string_keysyms_end (const xcb_input_feedback_ctl_t *R,
+ const xcb_input_feedback_ctl_data_t *S)
+{
+ xcb_generic_iterator_t i;
+ i.data = S->string.keysyms + S->string.num_keysyms;
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) S;
+ return i;
+}
+
+int
+xcb_input_feedback_ctl_data_serialize (void **_buffer,
+ uint8_t class_id,
+ const xcb_input_feedback_ctl_data_t *_aux)
+{
+ char *xcb_out = *_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_align_to = 0;
+ unsigned int xcb_padding_offset = 0;
+
+ unsigned int xcb_pad = 0;
+ char xcb_pad0[3] = {0, 0, 0};
+ struct iovec xcb_parts[24];
+ unsigned int xcb_parts_idx = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int i;
+ char *xcb_tmp;
+
+ if(class_id == XCB_INPUT_FEEDBACK_CLASS_KEYBOARD) {
+ /* xcb_input_feedback_ctl_data_t.keyboard.key */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->keyboard.key;
+ xcb_block_len += sizeof(xcb_input_key_code_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(xcb_input_key_code_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(xcb_input_key_code_t);
+ /* xcb_input_feedback_ctl_data_t.keyboard.auto_repeat_mode */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->keyboard.auto_repeat_mode;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_feedback_ctl_data_t.keyboard.key_click_percent */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->keyboard.key_click_percent;
+ xcb_block_len += sizeof(int8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(int8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int8_t);
+ /* xcb_input_feedback_ctl_data_t.keyboard.bell_percent */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->keyboard.bell_percent;
+ xcb_block_len += sizeof(int8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(int8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int8_t);
+ /* xcb_input_feedback_ctl_data_t.keyboard.bell_pitch */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->keyboard.bell_pitch;
+ xcb_block_len += sizeof(int16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(int16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int16_t);
+ /* xcb_input_feedback_ctl_data_t.keyboard.bell_duration */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->keyboard.bell_duration;
+ xcb_block_len += sizeof(int16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(int16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int16_t);
+ /* xcb_input_feedback_ctl_data_t.keyboard.led_mask */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->keyboard.led_mask;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_feedback_ctl_data_t.keyboard.led_values */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->keyboard.led_values;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ if(class_id == XCB_INPUT_FEEDBACK_CLASS_POINTER) {
+ /* xcb_input_feedback_ctl_data_t.pointer.pad0 */
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_block_len += sizeof(uint8_t)*2;
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t)*2;
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_feedback_ctl_data_t.pointer.num */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->pointer.num;
+ xcb_block_len += sizeof(int16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(int16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int16_t);
+ /* xcb_input_feedback_ctl_data_t.pointer.denom */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->pointer.denom;
+ xcb_block_len += sizeof(int16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(int16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int16_t);
+ /* xcb_input_feedback_ctl_data_t.pointer.threshold */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->pointer.threshold;
+ xcb_block_len += sizeof(int16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(int16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int16_t);
+ }
+ if(class_id == XCB_INPUT_FEEDBACK_CLASS_STRING) {
+ /* xcb_input_feedback_ctl_data_t.string.pad1 */
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_block_len += sizeof(uint8_t)*2;
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t)*2;
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_feedback_ctl_data_t.string.num_keysyms */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->string.num_keysyms;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* keysyms */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->string.keysyms;
+ xcb_block_len += _aux->string.num_keysyms * sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = _aux->string.num_keysyms * sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(xcb_keysym_t);
+ }
+ if(class_id == XCB_INPUT_FEEDBACK_CLASS_INTEGER) {
+ /* xcb_input_feedback_ctl_data_t.integer.int_to_display */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->integer.int_to_display;
+ xcb_block_len += sizeof(int32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(int32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int32_t);
+ }
+ if(class_id == XCB_INPUT_FEEDBACK_CLASS_LED) {
+ /* xcb_input_feedback_ctl_data_t.led.led_mask */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->led.led_mask;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_feedback_ctl_data_t.led.led_values */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->led.led_values;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ if(class_id == XCB_INPUT_FEEDBACK_CLASS_BELL) {
+ /* xcb_input_feedback_ctl_data_t.bell.percent */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->bell.percent;
+ xcb_block_len += sizeof(int8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(int8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int8_t);
+ /* xcb_input_feedback_ctl_data_t.bell.pad2 */
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_block_len += sizeof(uint8_t)*3;
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t)*3;
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_feedback_ctl_data_t.bell.pitch */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->bell.pitch;
+ xcb_block_len += sizeof(int16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(int16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int16_t);
+ /* xcb_input_feedback_ctl_data_t.bell.duration */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->bell.duration;
+ xcb_block_len += sizeof(int16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(int16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int16_t);
+ }
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+
+ if (NULL == xcb_out) {
+ /* allocate memory */
+ xcb_out = malloc(xcb_buffer_len);
+ *_buffer = xcb_out;
+ }
+
+ xcb_tmp = xcb_out;
+ for(i=0; i<xcb_parts_idx; i++) {
+ if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)
+ memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);
+ if (0 != xcb_parts[i].iov_len)
+ xcb_tmp += xcb_parts[i].iov_len;
+ }
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_feedback_ctl_data_unpack (const void *_buffer,
+ uint8_t class_id,
+ xcb_input_feedback_ctl_data_t *_aux)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+ unsigned int xcb_padding_offset = 0;
+
+
+ if(class_id == XCB_INPUT_FEEDBACK_CLASS_KEYBOARD) {
+ /* xcb_input_feedback_ctl_data_t.keyboard.key */
+ _aux->keyboard.key = *(xcb_input_key_code_t *)xcb_tmp;
+ xcb_block_len += sizeof(xcb_input_key_code_t);
+ xcb_tmp += sizeof(xcb_input_key_code_t);
+ xcb_align_to = ALIGNOF(xcb_input_key_code_t);
+ /* xcb_input_feedback_ctl_data_t.keyboard.auto_repeat_mode */
+ _aux->keyboard.auto_repeat_mode = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_feedback_ctl_data_t.keyboard.key_click_percent */
+ _aux->keyboard.key_click_percent = *(int8_t *)xcb_tmp;
+ xcb_block_len += sizeof(int8_t);
+ xcb_tmp += sizeof(int8_t);
+ xcb_align_to = ALIGNOF(int8_t);
+ /* xcb_input_feedback_ctl_data_t.keyboard.bell_percent */
+ _aux->keyboard.bell_percent = *(int8_t *)xcb_tmp;
+ xcb_block_len += sizeof(int8_t);
+ xcb_tmp += sizeof(int8_t);
+ xcb_align_to = ALIGNOF(int8_t);
+ /* xcb_input_feedback_ctl_data_t.keyboard.bell_pitch */
+ _aux->keyboard.bell_pitch = *(int16_t *)xcb_tmp;
+ xcb_block_len += sizeof(int16_t);
+ xcb_tmp += sizeof(int16_t);
+ xcb_align_to = ALIGNOF(int16_t);
+ /* xcb_input_feedback_ctl_data_t.keyboard.bell_duration */
+ _aux->keyboard.bell_duration = *(int16_t *)xcb_tmp;
+ xcb_block_len += sizeof(int16_t);
+ xcb_tmp += sizeof(int16_t);
+ xcb_align_to = ALIGNOF(int16_t);
+ /* xcb_input_feedback_ctl_data_t.keyboard.led_mask */
+ _aux->keyboard.led_mask = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_feedback_ctl_data_t.keyboard.led_values */
+ _aux->keyboard.led_values = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ if(class_id == XCB_INPUT_FEEDBACK_CLASS_POINTER) {
+ /* xcb_input_feedback_ctl_data_t.pointer.pad0 */
+ _aux->pointer.pad0[0] = *(uint8_t *)xcb_tmp;
+ _aux->pointer.pad0[1] = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t) * 2;
+ xcb_tmp += sizeof(uint8_t) * 2;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_feedback_ctl_data_t.pointer.num */
+ _aux->pointer.num = *(int16_t *)xcb_tmp;
+ xcb_block_len += sizeof(int16_t);
+ xcb_tmp += sizeof(int16_t);
+ xcb_align_to = ALIGNOF(int16_t);
+ /* xcb_input_feedback_ctl_data_t.pointer.denom */
+ _aux->pointer.denom = *(int16_t *)xcb_tmp;
+ xcb_block_len += sizeof(int16_t);
+ xcb_tmp += sizeof(int16_t);
+ xcb_align_to = ALIGNOF(int16_t);
+ /* xcb_input_feedback_ctl_data_t.pointer.threshold */
+ _aux->pointer.threshold = *(int16_t *)xcb_tmp;
+ xcb_block_len += sizeof(int16_t);
+ xcb_tmp += sizeof(int16_t);
+ xcb_align_to = ALIGNOF(int16_t);
+ }
+ if(class_id == XCB_INPUT_FEEDBACK_CLASS_STRING) {
+ /* xcb_input_feedback_ctl_data_t.string.pad1 */
+ _aux->string.pad1[0] = *(uint8_t *)xcb_tmp;
+ _aux->string.pad1[1] = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t) * 2;
+ xcb_tmp += sizeof(uint8_t) * 2;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_feedback_ctl_data_t.string.num_keysyms */
+ _aux->string.num_keysyms = *(uint16_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_tmp += sizeof(uint16_t);
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* keysyms */
+ _aux->string.keysyms = (xcb_keysym_t *)xcb_tmp;
+ xcb_block_len += _aux->string.num_keysyms * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_keysym_t);
+ }
+ if(class_id == XCB_INPUT_FEEDBACK_CLASS_INTEGER) {
+ /* xcb_input_feedback_ctl_data_t.integer.int_to_display */
+ _aux->integer.int_to_display = *(int32_t *)xcb_tmp;
+ xcb_block_len += sizeof(int32_t);
+ xcb_tmp += sizeof(int32_t);
+ xcb_align_to = ALIGNOF(int32_t);
+ }
+ if(class_id == XCB_INPUT_FEEDBACK_CLASS_LED) {
+ /* xcb_input_feedback_ctl_data_t.led.led_mask */
+ _aux->led.led_mask = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_feedback_ctl_data_t.led.led_values */
+ _aux->led.led_values = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ if(class_id == XCB_INPUT_FEEDBACK_CLASS_BELL) {
+ /* xcb_input_feedback_ctl_data_t.bell.percent */
+ _aux->bell.percent = *(int8_t *)xcb_tmp;
+ xcb_block_len += sizeof(int8_t);
+ xcb_tmp += sizeof(int8_t);
+ xcb_align_to = ALIGNOF(int8_t);
+ /* xcb_input_feedback_ctl_data_t.bell.pad2 */
+ _aux->bell.pad2[0] = *(uint8_t *)xcb_tmp;
+ _aux->bell.pad2[1] = *(uint8_t *)xcb_tmp;
+ _aux->bell.pad2[2] = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t) * 3;
+ xcb_tmp += sizeof(uint8_t) * 3;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_feedback_ctl_data_t.bell.pitch */
+ _aux->bell.pitch = *(int16_t *)xcb_tmp;
+ xcb_block_len += sizeof(int16_t);
+ xcb_tmp += sizeof(int16_t);
+ xcb_align_to = ALIGNOF(int16_t);
+ /* xcb_input_feedback_ctl_data_t.bell.duration */
+ _aux->bell.duration = *(int16_t *)xcb_tmp;
+ xcb_block_len += sizeof(int16_t);
+ xcb_tmp += sizeof(int16_t);
+ xcb_align_to = ALIGNOF(int16_t);
+ }
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_feedback_ctl_data_sizeof (const void *_buffer,
+ uint8_t class_id)
+{
+ xcb_input_feedback_ctl_data_t _aux;
+ return xcb_input_feedback_ctl_data_unpack(_buffer, class_id, &_aux);
+}
+
+int
+xcb_input_feedback_ctl_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_feedback_ctl_t *_aux = (xcb_input_feedback_ctl_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_feedback_ctl_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* data */
+ xcb_block_len += xcb_input_feedback_ctl_data_sizeof(xcb_tmp, _aux->class_id);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+void *
+xcb_input_feedback_ctl_data (const xcb_input_feedback_ctl_t *R)
+{
+ return (void *) (R + 1);
+}
+
+void
+xcb_input_feedback_ctl_next (xcb_input_feedback_ctl_iterator_t *i)
+{
+ xcb_input_feedback_ctl_t *R = i->data;
+ xcb_generic_iterator_t child;
+ child.data = (xcb_input_feedback_ctl_t *)(((char *)R) + xcb_input_feedback_ctl_sizeof(R));
+ i->index = (char *) child.data - (char *) i->data;
+ --i->rem;
+ i->data = (xcb_input_feedback_ctl_t *) child.data;
+}
+
+xcb_generic_iterator_t
+xcb_input_feedback_ctl_end (xcb_input_feedback_ctl_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ while(i.rem > 0)
+ xcb_input_feedback_ctl_next(&i);
+ ret.data = i.data;
+ ret.rem = i.rem;
+ ret.index = i.index;
+ return ret;
+}
+
+int
+xcb_input_change_feedback_control_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_change_feedback_control_request_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* feedback */
+ xcb_block_len += xcb_input_feedback_ctl_sizeof(xcb_tmp);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_feedback_ctl_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_void_cookie_t
+xcb_input_change_feedback_control_checked (xcb_connection_t *c,
+ uint32_t mask,
+ uint8_t device_id,
+ uint8_t feedback_id,
+ xcb_input_feedback_ctl_t *feedback)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_CHANGE_FEEDBACK_CONTROL,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_change_feedback_control_request_t xcb_out;
+
+ xcb_out.mask = mask;
+ xcb_out.device_id = device_id;
+ xcb_out.feedback_id = feedback_id;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_feedback_ctl_t feedback */
+ xcb_parts[4].iov_base = (char *) feedback;
+ xcb_parts[4].iov_len =
+ xcb_input_feedback_ctl_sizeof (feedback);
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_change_feedback_control (xcb_connection_t *c,
+ uint32_t mask,
+ uint8_t device_id,
+ uint8_t feedback_id,
+ xcb_input_feedback_ctl_t *feedback)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_CHANGE_FEEDBACK_CONTROL,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_change_feedback_control_request_t xcb_out;
+
+ xcb_out.mask = mask;
+ xcb_out.device_id = device_id;
+ xcb_out.feedback_id = feedback_id;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_feedback_ctl_t feedback */
+ xcb_parts[4].iov_base = (char *) feedback;
+ xcb_parts[4].iov_len =
+ xcb_input_feedback_ctl_sizeof (feedback);
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_feedback_ctl_t *
+xcb_input_change_feedback_control_feedback (const xcb_input_change_feedback_control_request_t *R)
+{
+ return (xcb_input_feedback_ctl_t *) (R + 1);
+}
+
+int
+xcb_input_get_device_key_mapping_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_get_device_key_mapping_reply_t *_aux = (xcb_input_get_device_key_mapping_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_get_device_key_mapping_reply_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* keysyms */
+ xcb_block_len += _aux->length * sizeof(xcb_keysym_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_keysym_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_get_device_key_mapping_cookie_t
+xcb_input_get_device_key_mapping (xcb_connection_t *c,
+ uint8_t device_id,
+ xcb_input_key_code_t first_keycode,
+ uint8_t count)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GET_DEVICE_KEY_MAPPING,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_get_device_key_mapping_cookie_t xcb_ret;
+ xcb_input_get_device_key_mapping_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ xcb_out.first_keycode = first_keycode;
+ xcb_out.count = count;
+ xcb_out.pad0 = 0;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_get_device_key_mapping_cookie_t
+xcb_input_get_device_key_mapping_unchecked (xcb_connection_t *c,
+ uint8_t device_id,
+ xcb_input_key_code_t first_keycode,
+ uint8_t count)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GET_DEVICE_KEY_MAPPING,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_get_device_key_mapping_cookie_t xcb_ret;
+ xcb_input_get_device_key_mapping_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ xcb_out.first_keycode = first_keycode;
+ xcb_out.count = count;
+ xcb_out.pad0 = 0;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_keysym_t *
+xcb_input_get_device_key_mapping_keysyms (const xcb_input_get_device_key_mapping_reply_t *R)
+{
+ return (xcb_keysym_t *) (R + 1);
+}
+
+int
+xcb_input_get_device_key_mapping_keysyms_length (const xcb_input_get_device_key_mapping_reply_t *R)
+{
+ return R->length;
+}
+
+xcb_generic_iterator_t
+xcb_input_get_device_key_mapping_keysyms_end (const xcb_input_get_device_key_mapping_reply_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((xcb_keysym_t *) (R + 1)) + (R->length);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_get_device_key_mapping_reply_t *
+xcb_input_get_device_key_mapping_reply (xcb_connection_t *c,
+ xcb_input_get_device_key_mapping_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_get_device_key_mapping_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+int
+xcb_input_change_device_key_mapping_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_change_device_key_mapping_request_t *_aux = (xcb_input_change_device_key_mapping_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_change_device_key_mapping_request_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* keysyms */
+ xcb_block_len += (_aux->keycode_count * _aux->keysyms_per_keycode) * sizeof(xcb_keysym_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_keysym_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_void_cookie_t
+xcb_input_change_device_key_mapping_checked (xcb_connection_t *c,
+ uint8_t device_id,
+ xcb_input_key_code_t first_keycode,
+ uint8_t keysyms_per_keycode,
+ uint8_t keycode_count,
+ const xcb_keysym_t *keysyms)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_CHANGE_DEVICE_KEY_MAPPING,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_change_device_key_mapping_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ xcb_out.first_keycode = first_keycode;
+ xcb_out.keysyms_per_keycode = keysyms_per_keycode;
+ xcb_out.keycode_count = keycode_count;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_keysym_t keysyms */
+ xcb_parts[4].iov_base = (char *) keysyms;
+ xcb_parts[4].iov_len = (keycode_count * keysyms_per_keycode) * sizeof(xcb_keysym_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_change_device_key_mapping (xcb_connection_t *c,
+ uint8_t device_id,
+ xcb_input_key_code_t first_keycode,
+ uint8_t keysyms_per_keycode,
+ uint8_t keycode_count,
+ const xcb_keysym_t *keysyms)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_CHANGE_DEVICE_KEY_MAPPING,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_change_device_key_mapping_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ xcb_out.first_keycode = first_keycode;
+ xcb_out.keysyms_per_keycode = keysyms_per_keycode;
+ xcb_out.keycode_count = keycode_count;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_keysym_t keysyms */
+ xcb_parts[4].iov_base = (char *) keysyms;
+ xcb_parts[4].iov_len = (keycode_count * keysyms_per_keycode) * sizeof(xcb_keysym_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_keysym_t *
+xcb_input_change_device_key_mapping_keysyms (const xcb_input_change_device_key_mapping_request_t *R)
+{
+ return (xcb_keysym_t *) (R + 1);
+}
+
+int
+xcb_input_change_device_key_mapping_keysyms_length (const xcb_input_change_device_key_mapping_request_t *R)
+{
+ return (R->keycode_count * R->keysyms_per_keycode);
+}
+
+xcb_generic_iterator_t
+xcb_input_change_device_key_mapping_keysyms_end (const xcb_input_change_device_key_mapping_request_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((xcb_keysym_t *) (R + 1)) + ((R->keycode_count * R->keysyms_per_keycode));
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+int
+xcb_input_get_device_modifier_mapping_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_get_device_modifier_mapping_reply_t *_aux = (xcb_input_get_device_modifier_mapping_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_get_device_modifier_mapping_reply_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* keymaps */
+ xcb_block_len += (_aux->keycodes_per_modifier * 8) * sizeof(uint8_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_get_device_modifier_mapping_cookie_t
+xcb_input_get_device_modifier_mapping (xcb_connection_t *c,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GET_DEVICE_MODIFIER_MAPPING,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_get_device_modifier_mapping_cookie_t xcb_ret;
+ xcb_input_get_device_modifier_mapping_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_get_device_modifier_mapping_cookie_t
+xcb_input_get_device_modifier_mapping_unchecked (xcb_connection_t *c,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GET_DEVICE_MODIFIER_MAPPING,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_get_device_modifier_mapping_cookie_t xcb_ret;
+ xcb_input_get_device_modifier_mapping_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+uint8_t *
+xcb_input_get_device_modifier_mapping_keymaps (const xcb_input_get_device_modifier_mapping_reply_t *R)
+{
+ return (uint8_t *) (R + 1);
+}
+
+int
+xcb_input_get_device_modifier_mapping_keymaps_length (const xcb_input_get_device_modifier_mapping_reply_t *R)
+{
+ return (R->keycodes_per_modifier * 8);
+}
+
+xcb_generic_iterator_t
+xcb_input_get_device_modifier_mapping_keymaps_end (const xcb_input_get_device_modifier_mapping_reply_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((uint8_t *) (R + 1)) + ((R->keycodes_per_modifier * 8));
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_get_device_modifier_mapping_reply_t *
+xcb_input_get_device_modifier_mapping_reply (xcb_connection_t *c,
+ xcb_input_get_device_modifier_mapping_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_get_device_modifier_mapping_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+int
+xcb_input_set_device_modifier_mapping_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_set_device_modifier_mapping_request_t *_aux = (xcb_input_set_device_modifier_mapping_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_set_device_modifier_mapping_request_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* keymaps */
+ xcb_block_len += (_aux->keycodes_per_modifier * 8) * sizeof(uint8_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_set_device_modifier_mapping_cookie_t
+xcb_input_set_device_modifier_mapping (xcb_connection_t *c,
+ uint8_t device_id,
+ uint8_t keycodes_per_modifier,
+ const uint8_t *keymaps)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_SET_DEVICE_MODIFIER_MAPPING,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_input_set_device_modifier_mapping_cookie_t xcb_ret;
+ xcb_input_set_device_modifier_mapping_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ xcb_out.keycodes_per_modifier = keycodes_per_modifier;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint8_t keymaps */
+ xcb_parts[4].iov_base = (char *) keymaps;
+ xcb_parts[4].iov_len = (keycodes_per_modifier * 8) * sizeof(uint8_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_set_device_modifier_mapping_cookie_t
+xcb_input_set_device_modifier_mapping_unchecked (xcb_connection_t *c,
+ uint8_t device_id,
+ uint8_t keycodes_per_modifier,
+ const uint8_t *keymaps)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_SET_DEVICE_MODIFIER_MAPPING,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_input_set_device_modifier_mapping_cookie_t xcb_ret;
+ xcb_input_set_device_modifier_mapping_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ xcb_out.keycodes_per_modifier = keycodes_per_modifier;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint8_t keymaps */
+ xcb_parts[4].iov_base = (char *) keymaps;
+ xcb_parts[4].iov_len = (keycodes_per_modifier * 8) * sizeof(uint8_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_set_device_modifier_mapping_reply_t *
+xcb_input_set_device_modifier_mapping_reply (xcb_connection_t *c,
+ xcb_input_set_device_modifier_mapping_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_set_device_modifier_mapping_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+int
+xcb_input_get_device_button_mapping_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_get_device_button_mapping_reply_t *_aux = (xcb_input_get_device_button_mapping_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_get_device_button_mapping_reply_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* map */
+ xcb_block_len += _aux->map_size * sizeof(uint8_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint8_t);
+ xcb_align_to = 4;
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_get_device_button_mapping_cookie_t
+xcb_input_get_device_button_mapping (xcb_connection_t *c,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GET_DEVICE_BUTTON_MAPPING,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_get_device_button_mapping_cookie_t xcb_ret;
+ xcb_input_get_device_button_mapping_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_get_device_button_mapping_cookie_t
+xcb_input_get_device_button_mapping_unchecked (xcb_connection_t *c,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GET_DEVICE_BUTTON_MAPPING,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_get_device_button_mapping_cookie_t xcb_ret;
+ xcb_input_get_device_button_mapping_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+uint8_t *
+xcb_input_get_device_button_mapping_map (const xcb_input_get_device_button_mapping_reply_t *R)
+{
+ return (uint8_t *) (R + 1);
+}
+
+int
+xcb_input_get_device_button_mapping_map_length (const xcb_input_get_device_button_mapping_reply_t *R)
+{
+ return R->map_size;
+}
+
+xcb_generic_iterator_t
+xcb_input_get_device_button_mapping_map_end (const xcb_input_get_device_button_mapping_reply_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((uint8_t *) (R + 1)) + (R->map_size);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_get_device_button_mapping_reply_t *
+xcb_input_get_device_button_mapping_reply (xcb_connection_t *c,
+ xcb_input_get_device_button_mapping_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_get_device_button_mapping_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+int
+xcb_input_set_device_button_mapping_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_set_device_button_mapping_request_t *_aux = (xcb_input_set_device_button_mapping_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_set_device_button_mapping_request_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* map */
+ xcb_block_len += _aux->map_size * sizeof(uint8_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_set_device_button_mapping_cookie_t
+xcb_input_set_device_button_mapping (xcb_connection_t *c,
+ uint8_t device_id,
+ uint8_t map_size,
+ const uint8_t *map)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_SET_DEVICE_BUTTON_MAPPING,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_input_set_device_button_mapping_cookie_t xcb_ret;
+ xcb_input_set_device_button_mapping_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ xcb_out.map_size = map_size;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint8_t map */
+ xcb_parts[4].iov_base = (char *) map;
+ xcb_parts[4].iov_len = map_size * sizeof(uint8_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_set_device_button_mapping_cookie_t
+xcb_input_set_device_button_mapping_unchecked (xcb_connection_t *c,
+ uint8_t device_id,
+ uint8_t map_size,
+ const uint8_t *map)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_SET_DEVICE_BUTTON_MAPPING,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_input_set_device_button_mapping_cookie_t xcb_ret;
+ xcb_input_set_device_button_mapping_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ xcb_out.map_size = map_size;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint8_t map */
+ xcb_parts[4].iov_base = (char *) map;
+ xcb_parts[4].iov_len = map_size * sizeof(uint8_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_set_device_button_mapping_reply_t *
+xcb_input_set_device_button_mapping_reply (xcb_connection_t *c,
+ xcb_input_set_device_button_mapping_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_set_device_button_mapping_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+void
+xcb_input_key_state_next (xcb_input_key_state_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_key_state_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_key_state_end (xcb_input_key_state_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_button_state_next (xcb_input_button_state_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_button_state_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_button_state_end (xcb_input_button_state_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+int
+xcb_input_valuator_state_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_valuator_state_t *_aux = (xcb_input_valuator_state_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_valuator_state_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* valuators */
+ xcb_block_len += _aux->num_valuators * sizeof(int32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(int32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+int32_t *
+xcb_input_valuator_state_valuators (const xcb_input_valuator_state_t *R)
+{
+ return (int32_t *) (R + 1);
+}
+
+int
+xcb_input_valuator_state_valuators_length (const xcb_input_valuator_state_t *R)
+{
+ return R->num_valuators;
+}
+
+xcb_generic_iterator_t
+xcb_input_valuator_state_valuators_end (const xcb_input_valuator_state_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((int32_t *) (R + 1)) + (R->num_valuators);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+void
+xcb_input_valuator_state_next (xcb_input_valuator_state_iterator_t *i)
+{
+ xcb_input_valuator_state_t *R = i->data;
+ xcb_generic_iterator_t child;
+ child.data = (xcb_input_valuator_state_t *)(((char *)R) + xcb_input_valuator_state_sizeof(R));
+ i->index = (char *) child.data - (char *) i->data;
+ --i->rem;
+ i->data = (xcb_input_valuator_state_t *) child.data;
+}
+
+xcb_generic_iterator_t
+xcb_input_valuator_state_end (xcb_input_valuator_state_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ while(i.rem > 0)
+ xcb_input_valuator_state_next(&i);
+ ret.data = i.data;
+ ret.rem = i.rem;
+ ret.index = i.index;
+ return ret;
+}
+
+int32_t *
+xcb_input_input_state_data_valuator_valuators (const xcb_input_input_state_data_t *S)
+{
+ return S->valuator.valuators;
+}
+
+int
+xcb_input_input_state_data_valuator_valuators_length (const xcb_input_input_state_t *R,
+ const xcb_input_input_state_data_t *S)
+{
+ return S->valuator.num_valuators;
+}
+
+xcb_generic_iterator_t
+xcb_input_input_state_data_valuator_valuators_end (const xcb_input_input_state_t *R,
+ const xcb_input_input_state_data_t *S)
+{
+ xcb_generic_iterator_t i;
+ i.data = S->valuator.valuators + S->valuator.num_valuators;
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) S;
+ return i;
+}
+
+int
+xcb_input_input_state_data_serialize (void **_buffer,
+ uint8_t class_id,
+ const xcb_input_input_state_data_t *_aux)
+{
+ char *xcb_out = *_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_align_to = 0;
+ unsigned int xcb_padding_offset = 2;
+
+ unsigned int xcb_pad = 0;
+ char xcb_pad0[3] = {0, 0, 0};
+ struct iovec xcb_parts[11];
+ unsigned int xcb_parts_idx = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int i;
+ char *xcb_tmp;
+
+ if(class_id == XCB_INPUT_INPUT_CLASS_KEY) {
+ /* xcb_input_input_state_data_t.key.num_keys */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->key.num_keys;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_input_state_data_t.key.pad0 */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &xcb_pad;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_input_state_data_t.key.keys */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->key.keys;
+ xcb_block_len += 32;
+ xcb_parts[xcb_parts_idx].iov_len = 32;
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ }
+ if(class_id == XCB_INPUT_INPUT_CLASS_BUTTON) {
+ /* xcb_input_input_state_data_t.button.num_buttons */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->button.num_buttons;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_input_state_data_t.button.pad1 */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &xcb_pad;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_input_state_data_t.button.buttons */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->button.buttons;
+ xcb_block_len += 32;
+ xcb_parts[xcb_parts_idx].iov_len = 32;
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ }
+ if(class_id == XCB_INPUT_INPUT_CLASS_VALUATOR) {
+ /* xcb_input_input_state_data_t.valuator.num_valuators */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->valuator.num_valuators;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_input_state_data_t.valuator.mode */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->valuator.mode;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* valuators */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->valuator.valuators;
+ xcb_block_len += _aux->valuator.num_valuators * sizeof(int32_t);
+ xcb_parts[xcb_parts_idx].iov_len = _aux->valuator.num_valuators * sizeof(int32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int32_t);
+ }
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+
+ if (NULL == xcb_out) {
+ /* allocate memory */
+ xcb_out = malloc(xcb_buffer_len);
+ *_buffer = xcb_out;
+ }
+
+ xcb_tmp = xcb_out;
+ for(i=0; i<xcb_parts_idx; i++) {
+ if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)
+ memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);
+ if (0 != xcb_parts[i].iov_len)
+ xcb_tmp += xcb_parts[i].iov_len;
+ }
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_input_state_data_unpack (const void *_buffer,
+ uint8_t class_id,
+ xcb_input_input_state_data_t *_aux)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+ unsigned int xcb_padding_offset = 2;
+
+
+ if(class_id == XCB_INPUT_INPUT_CLASS_KEY) {
+ /* xcb_input_input_state_data_t.key.num_keys */
+ _aux->key.num_keys = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_input_state_data_t.key.pad0 */
+ _aux->key.pad0 = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_input_state_data_t.key.keys */
+ memcpy(_aux->key.keys, xcb_tmp, sizeof(uint8_t) * 32);
+ xcb_block_len += sizeof(uint8_t) * 32;
+ xcb_tmp += sizeof(uint8_t) * 32;
+ xcb_align_to = ALIGNOF(uint8_t);
+ }
+ if(class_id == XCB_INPUT_INPUT_CLASS_BUTTON) {
+ /* xcb_input_input_state_data_t.button.num_buttons */
+ _aux->button.num_buttons = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_input_state_data_t.button.pad1 */
+ _aux->button.pad1 = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_input_state_data_t.button.buttons */
+ memcpy(_aux->button.buttons, xcb_tmp, sizeof(uint8_t) * 32);
+ xcb_block_len += sizeof(uint8_t) * 32;
+ xcb_tmp += sizeof(uint8_t) * 32;
+ xcb_align_to = ALIGNOF(uint8_t);
+ }
+ if(class_id == XCB_INPUT_INPUT_CLASS_VALUATOR) {
+ /* xcb_input_input_state_data_t.valuator.num_valuators */
+ _aux->valuator.num_valuators = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_input_state_data_t.valuator.mode */
+ _aux->valuator.mode = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* valuators */
+ _aux->valuator.valuators = (int32_t *)xcb_tmp;
+ xcb_block_len += _aux->valuator.num_valuators * sizeof(int32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(int32_t);
+ }
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_input_state_data_sizeof (const void *_buffer,
+ uint8_t class_id)
+{
+ xcb_input_input_state_data_t _aux;
+ return xcb_input_input_state_data_unpack(_buffer, class_id, &_aux);
+}
+
+int
+xcb_input_input_state_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_input_state_t *_aux = (xcb_input_input_state_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_input_state_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* data */
+ xcb_block_len += xcb_input_input_state_data_sizeof(xcb_tmp, _aux->class_id);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+void *
+xcb_input_input_state_data (const xcb_input_input_state_t *R)
+{
+ return (void *) (R + 1);
+}
+
+void
+xcb_input_input_state_next (xcb_input_input_state_iterator_t *i)
+{
+ xcb_input_input_state_t *R = i->data;
+ xcb_generic_iterator_t child;
+ child.data = (xcb_input_input_state_t *)(((char *)R) + xcb_input_input_state_sizeof(R));
+ i->index = (char *) child.data - (char *) i->data;
+ --i->rem;
+ i->data = (xcb_input_input_state_t *) child.data;
+}
+
+xcb_generic_iterator_t
+xcb_input_input_state_end (xcb_input_input_state_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ while(i.rem > 0)
+ xcb_input_input_state_next(&i);
+ ret.data = i.data;
+ ret.rem = i.rem;
+ ret.index = i.index;
+ return ret;
+}
+
+int
+xcb_input_query_device_state_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_query_device_state_reply_t *_aux = (xcb_input_query_device_state_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+ unsigned int i;
+ unsigned int xcb_tmp_len;
+
+ xcb_block_len += sizeof(xcb_input_query_device_state_reply_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* classes */
+ for(i=0; i<_aux->num_classes; i++) {
+ xcb_tmp_len = xcb_input_input_state_sizeof(xcb_tmp);
+ xcb_block_len += xcb_tmp_len;
+ xcb_tmp += xcb_tmp_len;
+ }
+ xcb_align_to = ALIGNOF(xcb_input_input_state_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_query_device_state_cookie_t
+xcb_input_query_device_state (xcb_connection_t *c,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_QUERY_DEVICE_STATE,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_query_device_state_cookie_t xcb_ret;
+ xcb_input_query_device_state_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_query_device_state_cookie_t
+xcb_input_query_device_state_unchecked (xcb_connection_t *c,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_QUERY_DEVICE_STATE,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_query_device_state_cookie_t xcb_ret;
+ xcb_input_query_device_state_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+int
+xcb_input_query_device_state_classes_length (const xcb_input_query_device_state_reply_t *R)
+{
+ return R->num_classes;
+}
+
+xcb_input_input_state_iterator_t
+xcb_input_query_device_state_classes_iterator (const xcb_input_query_device_state_reply_t *R)
+{
+ xcb_input_input_state_iterator_t i;
+ i.data = (xcb_input_input_state_t *) (R + 1);
+ i.rem = R->num_classes;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_query_device_state_reply_t *
+xcb_input_query_device_state_reply (xcb_connection_t *c,
+ xcb_input_query_device_state_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_query_device_state_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+xcb_void_cookie_t
+xcb_input_device_bell_checked (xcb_connection_t *c,
+ uint8_t device_id,
+ uint8_t feedback_id,
+ uint8_t feedback_class,
+ int8_t percent)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_DEVICE_BELL,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_device_bell_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ xcb_out.feedback_id = feedback_id;
+ xcb_out.feedback_class = feedback_class;
+ xcb_out.percent = percent;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_device_bell (xcb_connection_t *c,
+ uint8_t device_id,
+ uint8_t feedback_id,
+ uint8_t feedback_class,
+ int8_t percent)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_DEVICE_BELL,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_device_bell_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ xcb_out.feedback_id = feedback_id;
+ xcb_out.feedback_class = feedback_class;
+ xcb_out.percent = percent;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+int
+xcb_input_set_device_valuators_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_set_device_valuators_request_t *_aux = (xcb_input_set_device_valuators_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_set_device_valuators_request_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* valuators */
+ xcb_block_len += _aux->num_valuators * sizeof(int32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(int32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_set_device_valuators_cookie_t
+xcb_input_set_device_valuators (xcb_connection_t *c,
+ uint8_t device_id,
+ uint8_t first_valuator,
+ uint8_t num_valuators,
+ const int32_t *valuators)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_SET_DEVICE_VALUATORS,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_input_set_device_valuators_cookie_t xcb_ret;
+ xcb_input_set_device_valuators_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ xcb_out.first_valuator = first_valuator;
+ xcb_out.num_valuators = num_valuators;
+ xcb_out.pad0 = 0;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* int32_t valuators */
+ xcb_parts[4].iov_base = (char *) valuators;
+ xcb_parts[4].iov_len = num_valuators * sizeof(int32_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_set_device_valuators_cookie_t
+xcb_input_set_device_valuators_unchecked (xcb_connection_t *c,
+ uint8_t device_id,
+ uint8_t first_valuator,
+ uint8_t num_valuators,
+ const int32_t *valuators)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_SET_DEVICE_VALUATORS,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_input_set_device_valuators_cookie_t xcb_ret;
+ xcb_input_set_device_valuators_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ xcb_out.first_valuator = first_valuator;
+ xcb_out.num_valuators = num_valuators;
+ xcb_out.pad0 = 0;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* int32_t valuators */
+ xcb_parts[4].iov_base = (char *) valuators;
+ xcb_parts[4].iov_len = num_valuators * sizeof(int32_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_set_device_valuators_reply_t *
+xcb_input_set_device_valuators_reply (xcb_connection_t *c,
+ xcb_input_set_device_valuators_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_set_device_valuators_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+int
+xcb_input_device_resolution_state_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_device_resolution_state_t *_aux = (xcb_input_device_resolution_state_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_device_resolution_state_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* resolution_values */
+ xcb_block_len += _aux->num_valuators * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* resolution_min */
+ xcb_block_len += _aux->num_valuators * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* resolution_max */
+ xcb_block_len += _aux->num_valuators * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+uint32_t *
+xcb_input_device_resolution_state_resolution_values (const xcb_input_device_resolution_state_t *R)
+{
+ return (uint32_t *) (R + 1);
+}
+
+int
+xcb_input_device_resolution_state_resolution_values_length (const xcb_input_device_resolution_state_t *R)
+{
+ return R->num_valuators;
+}
+
+xcb_generic_iterator_t
+xcb_input_device_resolution_state_resolution_values_end (const xcb_input_device_resolution_state_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((uint32_t *) (R + 1)) + (R->num_valuators);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+uint32_t *
+xcb_input_device_resolution_state_resolution_min (const xcb_input_device_resolution_state_t *R)
+{
+ xcb_generic_iterator_t prev = xcb_input_device_resolution_state_resolution_values_end(R);
+ return (uint32_t *) ((char *) prev.data + XCB_TYPE_PAD(uint32_t, prev.index) + 0);
+}
+
+int
+xcb_input_device_resolution_state_resolution_min_length (const xcb_input_device_resolution_state_t *R)
+{
+ return R->num_valuators;
+}
+
+xcb_generic_iterator_t
+xcb_input_device_resolution_state_resolution_min_end (const xcb_input_device_resolution_state_t *R)
+{
+ xcb_generic_iterator_t i;
+ xcb_generic_iterator_t prev = xcb_input_device_resolution_state_resolution_values_end(R);
+ i.data = ((uint32_t *) ((char*) prev.data + XCB_TYPE_PAD(uint32_t, prev.index))) + (R->num_valuators);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+uint32_t *
+xcb_input_device_resolution_state_resolution_max (const xcb_input_device_resolution_state_t *R)
+{
+ xcb_generic_iterator_t prev = xcb_input_device_resolution_state_resolution_min_end(R);
+ return (uint32_t *) ((char *) prev.data + XCB_TYPE_PAD(uint32_t, prev.index) + 0);
+}
+
+int
+xcb_input_device_resolution_state_resolution_max_length (const xcb_input_device_resolution_state_t *R)
+{
+ return R->num_valuators;
+}
+
+xcb_generic_iterator_t
+xcb_input_device_resolution_state_resolution_max_end (const xcb_input_device_resolution_state_t *R)
+{
+ xcb_generic_iterator_t i;
+ xcb_generic_iterator_t prev = xcb_input_device_resolution_state_resolution_min_end(R);
+ i.data = ((uint32_t *) ((char*) prev.data + XCB_TYPE_PAD(uint32_t, prev.index))) + (R->num_valuators);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+void
+xcb_input_device_resolution_state_next (xcb_input_device_resolution_state_iterator_t *i)
+{
+ xcb_input_device_resolution_state_t *R = i->data;
+ xcb_generic_iterator_t child;
+ child.data = (xcb_input_device_resolution_state_t *)(((char *)R) + xcb_input_device_resolution_state_sizeof(R));
+ i->index = (char *) child.data - (char *) i->data;
+ --i->rem;
+ i->data = (xcb_input_device_resolution_state_t *) child.data;
+}
+
+xcb_generic_iterator_t
+xcb_input_device_resolution_state_end (xcb_input_device_resolution_state_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ while(i.rem > 0)
+ xcb_input_device_resolution_state_next(&i);
+ ret.data = i.data;
+ ret.rem = i.rem;
+ ret.index = i.index;
+ return ret;
+}
+
+void
+xcb_input_device_abs_calib_state_next (xcb_input_device_abs_calib_state_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_device_abs_calib_state_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_device_abs_calib_state_end (xcb_input_device_abs_calib_state_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_device_abs_area_state_next (xcb_input_device_abs_area_state_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_device_abs_area_state_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_device_abs_area_state_end (xcb_input_device_abs_area_state_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_device_core_state_next (xcb_input_device_core_state_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_device_core_state_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_device_core_state_end (xcb_input_device_core_state_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_device_enable_state_next (xcb_input_device_enable_state_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_device_enable_state_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_device_enable_state_end (xcb_input_device_enable_state_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+uint32_t *
+xcb_input_device_state_data_resolution_resolution_values (const xcb_input_device_state_data_t *S)
+{
+ return S->resolution.resolution_values;
+}
+
+int
+xcb_input_device_state_data_resolution_resolution_values_length (const xcb_input_device_state_t *R,
+ const xcb_input_device_state_data_t *S)
+{
+ return S->resolution.num_valuators;
+}
+
+xcb_generic_iterator_t
+xcb_input_device_state_data_resolution_resolution_values_end (const xcb_input_device_state_t *R,
+ const xcb_input_device_state_data_t *S)
+{
+ xcb_generic_iterator_t i;
+ i.data = S->resolution.resolution_values + S->resolution.num_valuators;
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) S;
+ return i;
+}
+
+uint32_t *
+xcb_input_device_state_data_resolution_resolution_min (const xcb_input_device_state_data_t *S)
+{
+ return S->resolution.resolution_min;
+}
+
+int
+xcb_input_device_state_data_resolution_resolution_min_length (const xcb_input_device_state_t *R,
+ const xcb_input_device_state_data_t *S)
+{
+ return S->resolution.num_valuators;
+}
+
+xcb_generic_iterator_t
+xcb_input_device_state_data_resolution_resolution_min_end (const xcb_input_device_state_t *R,
+ const xcb_input_device_state_data_t *S)
+{
+ xcb_generic_iterator_t i;
+ i.data = S->resolution.resolution_min + S->resolution.num_valuators;
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) S;
+ return i;
+}
+
+uint32_t *
+xcb_input_device_state_data_resolution_resolution_max (const xcb_input_device_state_data_t *S)
+{
+ return S->resolution.resolution_max;
+}
+
+int
+xcb_input_device_state_data_resolution_resolution_max_length (const xcb_input_device_state_t *R,
+ const xcb_input_device_state_data_t *S)
+{
+ return S->resolution.num_valuators;
+}
+
+xcb_generic_iterator_t
+xcb_input_device_state_data_resolution_resolution_max_end (const xcb_input_device_state_t *R,
+ const xcb_input_device_state_data_t *S)
+{
+ xcb_generic_iterator_t i;
+ i.data = S->resolution.resolution_max + S->resolution.num_valuators;
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) S;
+ return i;
+}
+
+int
+xcb_input_device_state_data_serialize (void **_buffer,
+ uint16_t control_id,
+ const xcb_input_device_state_data_t *_aux)
+{
+ char *xcb_out = *_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_align_to = 0;
+ unsigned int xcb_padding_offset = 0;
+
+ unsigned int xcb_pad = 0;
+ char xcb_pad0[3] = {0, 0, 0};
+ struct iovec xcb_parts[27];
+ unsigned int xcb_parts_idx = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int i;
+ char *xcb_tmp;
+
+ if(control_id == XCB_INPUT_DEVICE_CONTROL_RESOLUTION) {
+ /* xcb_input_device_state_data_t.resolution.num_valuators */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->resolution.num_valuators;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* resolution_values */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->resolution.resolution_values;
+ xcb_block_len += _aux->resolution.num_valuators * sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = _aux->resolution.num_valuators * sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* resolution_min */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->resolution.resolution_min;
+ xcb_block_len += _aux->resolution.num_valuators * sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = _aux->resolution.num_valuators * sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* resolution_max */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->resolution.resolution_max;
+ xcb_block_len += _aux->resolution.num_valuators * sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = _aux->resolution.num_valuators * sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ if(control_id == XCB_INPUT_DEVICE_CONTROL_ABS_CALIB) {
+ /* xcb_input_device_state_data_t.abs_calib.min_x */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_calib.min_x;
+ xcb_block_len += sizeof(int32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(int32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int32_t);
+ /* xcb_input_device_state_data_t.abs_calib.max_x */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_calib.max_x;
+ xcb_block_len += sizeof(int32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(int32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int32_t);
+ /* xcb_input_device_state_data_t.abs_calib.min_y */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_calib.min_y;
+ xcb_block_len += sizeof(int32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(int32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int32_t);
+ /* xcb_input_device_state_data_t.abs_calib.max_y */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_calib.max_y;
+ xcb_block_len += sizeof(int32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(int32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int32_t);
+ /* xcb_input_device_state_data_t.abs_calib.flip_x */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_calib.flip_x;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_state_data_t.abs_calib.flip_y */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_calib.flip_y;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_state_data_t.abs_calib.rotation */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_calib.rotation;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_state_data_t.abs_calib.button_threshold */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_calib.button_threshold;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ if(control_id == XCB_INPUT_DEVICE_CONTROL_CORE) {
+ /* xcb_input_device_state_data_t.core.status */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->core.status;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_device_state_data_t.core.iscore */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->core.iscore;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_device_state_data_t.core.pad0 */
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_block_len += sizeof(uint8_t)*2;
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t)*2;
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ }
+ if(control_id == XCB_INPUT_DEVICE_CONTROL_ENABLE) {
+ /* xcb_input_device_state_data_t.enable.enable */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->enable.enable;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_device_state_data_t.enable.pad1 */
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_block_len += sizeof(uint8_t)*3;
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t)*3;
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ }
+ if(control_id == XCB_INPUT_DEVICE_CONTROL_ABS_AREA) {
+ /* xcb_input_device_state_data_t.abs_area.offset_x */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_area.offset_x;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_state_data_t.abs_area.offset_y */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_area.offset_y;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_state_data_t.abs_area.width */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_area.width;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_state_data_t.abs_area.height */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_area.height;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_state_data_t.abs_area.screen */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_area.screen;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_state_data_t.abs_area.following */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_area.following;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+
+ if (NULL == xcb_out) {
+ /* allocate memory */
+ xcb_out = malloc(xcb_buffer_len);
+ *_buffer = xcb_out;
+ }
+
+ xcb_tmp = xcb_out;
+ for(i=0; i<xcb_parts_idx; i++) {
+ if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)
+ memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);
+ if (0 != xcb_parts[i].iov_len)
+ xcb_tmp += xcb_parts[i].iov_len;
+ }
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_device_state_data_unpack (const void *_buffer,
+ uint16_t control_id,
+ xcb_input_device_state_data_t *_aux)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+ unsigned int xcb_padding_offset = 0;
+
+
+ if(control_id == XCB_INPUT_DEVICE_CONTROL_RESOLUTION) {
+ /* xcb_input_device_state_data_t.resolution.num_valuators */
+ _aux->resolution.num_valuators = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* resolution_values */
+ _aux->resolution.resolution_values = (uint32_t *)xcb_tmp;
+ xcb_block_len += _aux->resolution.num_valuators * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* resolution_min */
+ _aux->resolution.resolution_min = (uint32_t *)xcb_tmp;
+ xcb_block_len += _aux->resolution.num_valuators * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* resolution_max */
+ _aux->resolution.resolution_max = (uint32_t *)xcb_tmp;
+ xcb_block_len += _aux->resolution.num_valuators * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ if(control_id == XCB_INPUT_DEVICE_CONTROL_ABS_CALIB) {
+ /* xcb_input_device_state_data_t.abs_calib.min_x */
+ _aux->abs_calib.min_x = *(int32_t *)xcb_tmp;
+ xcb_block_len += sizeof(int32_t);
+ xcb_tmp += sizeof(int32_t);
+ xcb_align_to = ALIGNOF(int32_t);
+ /* xcb_input_device_state_data_t.abs_calib.max_x */
+ _aux->abs_calib.max_x = *(int32_t *)xcb_tmp;
+ xcb_block_len += sizeof(int32_t);
+ xcb_tmp += sizeof(int32_t);
+ xcb_align_to = ALIGNOF(int32_t);
+ /* xcb_input_device_state_data_t.abs_calib.min_y */
+ _aux->abs_calib.min_y = *(int32_t *)xcb_tmp;
+ xcb_block_len += sizeof(int32_t);
+ xcb_tmp += sizeof(int32_t);
+ xcb_align_to = ALIGNOF(int32_t);
+ /* xcb_input_device_state_data_t.abs_calib.max_y */
+ _aux->abs_calib.max_y = *(int32_t *)xcb_tmp;
+ xcb_block_len += sizeof(int32_t);
+ xcb_tmp += sizeof(int32_t);
+ xcb_align_to = ALIGNOF(int32_t);
+ /* xcb_input_device_state_data_t.abs_calib.flip_x */
+ _aux->abs_calib.flip_x = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_state_data_t.abs_calib.flip_y */
+ _aux->abs_calib.flip_y = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_state_data_t.abs_calib.rotation */
+ _aux->abs_calib.rotation = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_state_data_t.abs_calib.button_threshold */
+ _aux->abs_calib.button_threshold = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ if(control_id == XCB_INPUT_DEVICE_CONTROL_CORE) {
+ /* xcb_input_device_state_data_t.core.status */
+ _aux->core.status = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_device_state_data_t.core.iscore */
+ _aux->core.iscore = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_device_state_data_t.core.pad0 */
+ _aux->core.pad0[0] = *(uint8_t *)xcb_tmp;
+ _aux->core.pad0[1] = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t) * 2;
+ xcb_tmp += sizeof(uint8_t) * 2;
+ xcb_align_to = ALIGNOF(uint8_t);
+ }
+ if(control_id == XCB_INPUT_DEVICE_CONTROL_ENABLE) {
+ /* xcb_input_device_state_data_t.enable.enable */
+ _aux->enable.enable = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_device_state_data_t.enable.pad1 */
+ _aux->enable.pad1[0] = *(uint8_t *)xcb_tmp;
+ _aux->enable.pad1[1] = *(uint8_t *)xcb_tmp;
+ _aux->enable.pad1[2] = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t) * 3;
+ xcb_tmp += sizeof(uint8_t) * 3;
+ xcb_align_to = ALIGNOF(uint8_t);
+ }
+ if(control_id == XCB_INPUT_DEVICE_CONTROL_ABS_AREA) {
+ /* xcb_input_device_state_data_t.abs_area.offset_x */
+ _aux->abs_area.offset_x = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_state_data_t.abs_area.offset_y */
+ _aux->abs_area.offset_y = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_state_data_t.abs_area.width */
+ _aux->abs_area.width = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_state_data_t.abs_area.height */
+ _aux->abs_area.height = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_state_data_t.abs_area.screen */
+ _aux->abs_area.screen = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_state_data_t.abs_area.following */
+ _aux->abs_area.following = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_device_state_data_sizeof (const void *_buffer,
+ uint16_t control_id)
+{
+ xcb_input_device_state_data_t _aux;
+ return xcb_input_device_state_data_unpack(_buffer, control_id, &_aux);
+}
+
+int
+xcb_input_device_state_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_device_state_t *_aux = (xcb_input_device_state_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_device_state_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* data */
+ xcb_block_len += xcb_input_device_state_data_sizeof(xcb_tmp, _aux->control_id);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+void *
+xcb_input_device_state_data (const xcb_input_device_state_t *R)
+{
+ return (void *) (R + 1);
+}
+
+void
+xcb_input_device_state_next (xcb_input_device_state_iterator_t *i)
+{
+ xcb_input_device_state_t *R = i->data;
+ xcb_generic_iterator_t child;
+ child.data = (xcb_input_device_state_t *)(((char *)R) + xcb_input_device_state_sizeof(R));
+ i->index = (char *) child.data - (char *) i->data;
+ --i->rem;
+ i->data = (xcb_input_device_state_t *) child.data;
+}
+
+xcb_generic_iterator_t
+xcb_input_device_state_end (xcb_input_device_state_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ while(i.rem > 0)
+ xcb_input_device_state_next(&i);
+ ret.data = i.data;
+ ret.rem = i.rem;
+ ret.index = i.index;
+ return ret;
+}
+
+int
+xcb_input_get_device_control_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_get_device_control_reply_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* control */
+ xcb_block_len += xcb_input_device_state_sizeof(xcb_tmp);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_device_state_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_get_device_control_cookie_t
+xcb_input_get_device_control (xcb_connection_t *c,
+ uint16_t control_id,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GET_DEVICE_CONTROL,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_get_device_control_cookie_t xcb_ret;
+ xcb_input_get_device_control_request_t xcb_out;
+
+ xcb_out.control_id = control_id;
+ xcb_out.device_id = device_id;
+ xcb_out.pad0 = 0;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_get_device_control_cookie_t
+xcb_input_get_device_control_unchecked (xcb_connection_t *c,
+ uint16_t control_id,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GET_DEVICE_CONTROL,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_get_device_control_cookie_t xcb_ret;
+ xcb_input_get_device_control_request_t xcb_out;
+
+ xcb_out.control_id = control_id;
+ xcb_out.device_id = device_id;
+ xcb_out.pad0 = 0;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_device_state_t *
+xcb_input_get_device_control_control (const xcb_input_get_device_control_reply_t *R)
+{
+ return (xcb_input_device_state_t *) (R + 1);
+}
+
+xcb_input_get_device_control_reply_t *
+xcb_input_get_device_control_reply (xcb_connection_t *c,
+ xcb_input_get_device_control_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_get_device_control_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+int
+xcb_input_device_resolution_ctl_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_device_resolution_ctl_t *_aux = (xcb_input_device_resolution_ctl_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_device_resolution_ctl_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* resolution_values */
+ xcb_block_len += _aux->num_valuators * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+uint32_t *
+xcb_input_device_resolution_ctl_resolution_values (const xcb_input_device_resolution_ctl_t *R)
+{
+ return (uint32_t *) (R + 1);
+}
+
+int
+xcb_input_device_resolution_ctl_resolution_values_length (const xcb_input_device_resolution_ctl_t *R)
+{
+ return R->num_valuators;
+}
+
+xcb_generic_iterator_t
+xcb_input_device_resolution_ctl_resolution_values_end (const xcb_input_device_resolution_ctl_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((uint32_t *) (R + 1)) + (R->num_valuators);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+void
+xcb_input_device_resolution_ctl_next (xcb_input_device_resolution_ctl_iterator_t *i)
+{
+ xcb_input_device_resolution_ctl_t *R = i->data;
+ xcb_generic_iterator_t child;
+ child.data = (xcb_input_device_resolution_ctl_t *)(((char *)R) + xcb_input_device_resolution_ctl_sizeof(R));
+ i->index = (char *) child.data - (char *) i->data;
+ --i->rem;
+ i->data = (xcb_input_device_resolution_ctl_t *) child.data;
+}
+
+xcb_generic_iterator_t
+xcb_input_device_resolution_ctl_end (xcb_input_device_resolution_ctl_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ while(i.rem > 0)
+ xcb_input_device_resolution_ctl_next(&i);
+ ret.data = i.data;
+ ret.rem = i.rem;
+ ret.index = i.index;
+ return ret;
+}
+
+void
+xcb_input_device_abs_calib_ctl_next (xcb_input_device_abs_calib_ctl_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_device_abs_calib_ctl_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_device_abs_calib_ctl_end (xcb_input_device_abs_calib_ctl_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_device_abs_area_ctrl_next (xcb_input_device_abs_area_ctrl_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_device_abs_area_ctrl_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_device_abs_area_ctrl_end (xcb_input_device_abs_area_ctrl_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_device_core_ctrl_next (xcb_input_device_core_ctrl_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_device_core_ctrl_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_device_core_ctrl_end (xcb_input_device_core_ctrl_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_device_enable_ctrl_next (xcb_input_device_enable_ctrl_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_device_enable_ctrl_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_device_enable_ctrl_end (xcb_input_device_enable_ctrl_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+uint32_t *
+xcb_input_device_ctl_data_resolution_resolution_values (const xcb_input_device_ctl_data_t *S)
+{
+ return S->resolution.resolution_values;
+}
+
+int
+xcb_input_device_ctl_data_resolution_resolution_values_length (const xcb_input_device_ctl_t *R,
+ const xcb_input_device_ctl_data_t *S)
+{
+ return S->resolution.num_valuators;
+}
+
+xcb_generic_iterator_t
+xcb_input_device_ctl_data_resolution_resolution_values_end (const xcb_input_device_ctl_t *R,
+ const xcb_input_device_ctl_data_t *S)
+{
+ xcb_generic_iterator_t i;
+ i.data = S->resolution.resolution_values + S->resolution.num_valuators;
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) S;
+ return i;
+}
+
+int
+xcb_input_device_ctl_data_serialize (void **_buffer,
+ uint16_t control_id,
+ const xcb_input_device_ctl_data_t *_aux)
+{
+ char *xcb_out = *_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_align_to = 0;
+ unsigned int xcb_padding_offset = 0;
+
+ unsigned int xcb_pad = 0;
+ char xcb_pad0[3] = {0, 0, 0};
+ struct iovec xcb_parts[24];
+ unsigned int xcb_parts_idx = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int i;
+ char *xcb_tmp;
+
+ if(control_id == XCB_INPUT_DEVICE_CONTROL_RESOLUTION) {
+ /* xcb_input_device_ctl_data_t.resolution.first_valuator */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->resolution.first_valuator;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_device_ctl_data_t.resolution.num_valuators */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->resolution.num_valuators;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_device_ctl_data_t.resolution.pad0 */
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_block_len += sizeof(uint8_t)*2;
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t)*2;
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* resolution_values */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->resolution.resolution_values;
+ xcb_block_len += _aux->resolution.num_valuators * sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = _aux->resolution.num_valuators * sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ if(control_id == XCB_INPUT_DEVICE_CONTROL_ABS_CALIB) {
+ /* xcb_input_device_ctl_data_t.abs_calib.min_x */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_calib.min_x;
+ xcb_block_len += sizeof(int32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(int32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int32_t);
+ /* xcb_input_device_ctl_data_t.abs_calib.max_x */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_calib.max_x;
+ xcb_block_len += sizeof(int32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(int32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int32_t);
+ /* xcb_input_device_ctl_data_t.abs_calib.min_y */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_calib.min_y;
+ xcb_block_len += sizeof(int32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(int32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int32_t);
+ /* xcb_input_device_ctl_data_t.abs_calib.max_y */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_calib.max_y;
+ xcb_block_len += sizeof(int32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(int32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int32_t);
+ /* xcb_input_device_ctl_data_t.abs_calib.flip_x */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_calib.flip_x;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_ctl_data_t.abs_calib.flip_y */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_calib.flip_y;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_ctl_data_t.abs_calib.rotation */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_calib.rotation;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_ctl_data_t.abs_calib.button_threshold */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_calib.button_threshold;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ if(control_id == XCB_INPUT_DEVICE_CONTROL_CORE) {
+ /* xcb_input_device_ctl_data_t.core.status */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->core.status;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_device_ctl_data_t.core.pad1 */
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_block_len += sizeof(uint8_t)*3;
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t)*3;
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ }
+ if(control_id == XCB_INPUT_DEVICE_CONTROL_ENABLE) {
+ /* xcb_input_device_ctl_data_t.enable.enable */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->enable.enable;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_device_ctl_data_t.enable.pad2 */
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_block_len += sizeof(uint8_t)*3;
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t)*3;
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ }
+ if(control_id == XCB_INPUT_DEVICE_CONTROL_ABS_AREA) {
+ /* xcb_input_device_ctl_data_t.abs_area.offset_x */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_area.offset_x;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_ctl_data_t.abs_area.offset_y */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_area.offset_y;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_ctl_data_t.abs_area.width */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_area.width;
+ xcb_block_len += sizeof(int32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(int32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int32_t);
+ /* xcb_input_device_ctl_data_t.abs_area.height */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_area.height;
+ xcb_block_len += sizeof(int32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(int32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int32_t);
+ /* xcb_input_device_ctl_data_t.abs_area.screen */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_area.screen;
+ xcb_block_len += sizeof(int32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(int32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(int32_t);
+ /* xcb_input_device_ctl_data_t.abs_area.following */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->abs_area.following;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+
+ if (NULL == xcb_out) {
+ /* allocate memory */
+ xcb_out = malloc(xcb_buffer_len);
+ *_buffer = xcb_out;
+ }
+
+ xcb_tmp = xcb_out;
+ for(i=0; i<xcb_parts_idx; i++) {
+ if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)
+ memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);
+ if (0 != xcb_parts[i].iov_len)
+ xcb_tmp += xcb_parts[i].iov_len;
+ }
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_device_ctl_data_unpack (const void *_buffer,
+ uint16_t control_id,
+ xcb_input_device_ctl_data_t *_aux)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+ unsigned int xcb_padding_offset = 0;
+
+
+ if(control_id == XCB_INPUT_DEVICE_CONTROL_RESOLUTION) {
+ /* xcb_input_device_ctl_data_t.resolution.first_valuator */
+ _aux->resolution.first_valuator = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_device_ctl_data_t.resolution.num_valuators */
+ _aux->resolution.num_valuators = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_device_ctl_data_t.resolution.pad0 */
+ _aux->resolution.pad0[0] = *(uint8_t *)xcb_tmp;
+ _aux->resolution.pad0[1] = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t) * 2;
+ xcb_tmp += sizeof(uint8_t) * 2;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* resolution_values */
+ _aux->resolution.resolution_values = (uint32_t *)xcb_tmp;
+ xcb_block_len += _aux->resolution.num_valuators * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ if(control_id == XCB_INPUT_DEVICE_CONTROL_ABS_CALIB) {
+ /* xcb_input_device_ctl_data_t.abs_calib.min_x */
+ _aux->abs_calib.min_x = *(int32_t *)xcb_tmp;
+ xcb_block_len += sizeof(int32_t);
+ xcb_tmp += sizeof(int32_t);
+ xcb_align_to = ALIGNOF(int32_t);
+ /* xcb_input_device_ctl_data_t.abs_calib.max_x */
+ _aux->abs_calib.max_x = *(int32_t *)xcb_tmp;
+ xcb_block_len += sizeof(int32_t);
+ xcb_tmp += sizeof(int32_t);
+ xcb_align_to = ALIGNOF(int32_t);
+ /* xcb_input_device_ctl_data_t.abs_calib.min_y */
+ _aux->abs_calib.min_y = *(int32_t *)xcb_tmp;
+ xcb_block_len += sizeof(int32_t);
+ xcb_tmp += sizeof(int32_t);
+ xcb_align_to = ALIGNOF(int32_t);
+ /* xcb_input_device_ctl_data_t.abs_calib.max_y */
+ _aux->abs_calib.max_y = *(int32_t *)xcb_tmp;
+ xcb_block_len += sizeof(int32_t);
+ xcb_tmp += sizeof(int32_t);
+ xcb_align_to = ALIGNOF(int32_t);
+ /* xcb_input_device_ctl_data_t.abs_calib.flip_x */
+ _aux->abs_calib.flip_x = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_ctl_data_t.abs_calib.flip_y */
+ _aux->abs_calib.flip_y = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_ctl_data_t.abs_calib.rotation */
+ _aux->abs_calib.rotation = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_ctl_data_t.abs_calib.button_threshold */
+ _aux->abs_calib.button_threshold = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ if(control_id == XCB_INPUT_DEVICE_CONTROL_CORE) {
+ /* xcb_input_device_ctl_data_t.core.status */
+ _aux->core.status = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_device_ctl_data_t.core.pad1 */
+ _aux->core.pad1[0] = *(uint8_t *)xcb_tmp;
+ _aux->core.pad1[1] = *(uint8_t *)xcb_tmp;
+ _aux->core.pad1[2] = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t) * 3;
+ xcb_tmp += sizeof(uint8_t) * 3;
+ xcb_align_to = ALIGNOF(uint8_t);
+ }
+ if(control_id == XCB_INPUT_DEVICE_CONTROL_ENABLE) {
+ /* xcb_input_device_ctl_data_t.enable.enable */
+ _aux->enable.enable = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_device_ctl_data_t.enable.pad2 */
+ _aux->enable.pad2[0] = *(uint8_t *)xcb_tmp;
+ _aux->enable.pad2[1] = *(uint8_t *)xcb_tmp;
+ _aux->enable.pad2[2] = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t) * 3;
+ xcb_tmp += sizeof(uint8_t) * 3;
+ xcb_align_to = ALIGNOF(uint8_t);
+ }
+ if(control_id == XCB_INPUT_DEVICE_CONTROL_ABS_AREA) {
+ /* xcb_input_device_ctl_data_t.abs_area.offset_x */
+ _aux->abs_area.offset_x = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_ctl_data_t.abs_area.offset_y */
+ _aux->abs_area.offset_y = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_ctl_data_t.abs_area.width */
+ _aux->abs_area.width = *(int32_t *)xcb_tmp;
+ xcb_block_len += sizeof(int32_t);
+ xcb_tmp += sizeof(int32_t);
+ xcb_align_to = ALIGNOF(int32_t);
+ /* xcb_input_device_ctl_data_t.abs_area.height */
+ _aux->abs_area.height = *(int32_t *)xcb_tmp;
+ xcb_block_len += sizeof(int32_t);
+ xcb_tmp += sizeof(int32_t);
+ xcb_align_to = ALIGNOF(int32_t);
+ /* xcb_input_device_ctl_data_t.abs_area.screen */
+ _aux->abs_area.screen = *(int32_t *)xcb_tmp;
+ xcb_block_len += sizeof(int32_t);
+ xcb_tmp += sizeof(int32_t);
+ xcb_align_to = ALIGNOF(int32_t);
+ /* xcb_input_device_ctl_data_t.abs_area.following */
+ _aux->abs_area.following = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_device_ctl_data_sizeof (const void *_buffer,
+ uint16_t control_id)
+{
+ xcb_input_device_ctl_data_t _aux;
+ return xcb_input_device_ctl_data_unpack(_buffer, control_id, &_aux);
+}
+
+int
+xcb_input_device_ctl_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_device_ctl_t *_aux = (xcb_input_device_ctl_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_device_ctl_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* data */
+ xcb_block_len += xcb_input_device_ctl_data_sizeof(xcb_tmp, _aux->control_id);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+void *
+xcb_input_device_ctl_data (const xcb_input_device_ctl_t *R)
+{
+ return (void *) (R + 1);
+}
+
+void
+xcb_input_device_ctl_next (xcb_input_device_ctl_iterator_t *i)
+{
+ xcb_input_device_ctl_t *R = i->data;
+ xcb_generic_iterator_t child;
+ child.data = (xcb_input_device_ctl_t *)(((char *)R) + xcb_input_device_ctl_sizeof(R));
+ i->index = (char *) child.data - (char *) i->data;
+ --i->rem;
+ i->data = (xcb_input_device_ctl_t *) child.data;
+}
+
+xcb_generic_iterator_t
+xcb_input_device_ctl_end (xcb_input_device_ctl_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ while(i.rem > 0)
+ xcb_input_device_ctl_next(&i);
+ ret.data = i.data;
+ ret.rem = i.rem;
+ ret.index = i.index;
+ return ret;
+}
+
+int
+xcb_input_change_device_control_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_change_device_control_request_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* control */
+ xcb_block_len += xcb_input_device_ctl_sizeof(xcb_tmp);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_device_ctl_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_change_device_control_cookie_t
+xcb_input_change_device_control (xcb_connection_t *c,
+ uint16_t control_id,
+ uint8_t device_id,
+ xcb_input_device_ctl_t *control)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_CHANGE_DEVICE_CONTROL,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_input_change_device_control_cookie_t xcb_ret;
+ xcb_input_change_device_control_request_t xcb_out;
+
+ xcb_out.control_id = control_id;
+ xcb_out.device_id = device_id;
+ xcb_out.pad0 = 0;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_device_ctl_t control */
+ xcb_parts[4].iov_base = (char *) control;
+ xcb_parts[4].iov_len =
+ xcb_input_device_ctl_sizeof (control);
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_change_device_control_cookie_t
+xcb_input_change_device_control_unchecked (xcb_connection_t *c,
+ uint16_t control_id,
+ uint8_t device_id,
+ xcb_input_device_ctl_t *control)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_CHANGE_DEVICE_CONTROL,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_input_change_device_control_cookie_t xcb_ret;
+ xcb_input_change_device_control_request_t xcb_out;
+
+ xcb_out.control_id = control_id;
+ xcb_out.device_id = device_id;
+ xcb_out.pad0 = 0;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_device_ctl_t control */
+ xcb_parts[4].iov_base = (char *) control;
+ xcb_parts[4].iov_len =
+ xcb_input_device_ctl_sizeof (control);
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_change_device_control_reply_t *
+xcb_input_change_device_control_reply (xcb_connection_t *c,
+ xcb_input_change_device_control_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_change_device_control_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+int
+xcb_input_list_device_properties_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_list_device_properties_reply_t *_aux = (xcb_input_list_device_properties_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_list_device_properties_reply_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* atoms */
+ xcb_block_len += _aux->num_atoms * sizeof(xcb_atom_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_atom_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_list_device_properties_cookie_t
+xcb_input_list_device_properties (xcb_connection_t *c,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_LIST_DEVICE_PROPERTIES,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_list_device_properties_cookie_t xcb_ret;
+ xcb_input_list_device_properties_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_list_device_properties_cookie_t
+xcb_input_list_device_properties_unchecked (xcb_connection_t *c,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_LIST_DEVICE_PROPERTIES,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_list_device_properties_cookie_t xcb_ret;
+ xcb_input_list_device_properties_request_t xcb_out;
+
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_atom_t *
+xcb_input_list_device_properties_atoms (const xcb_input_list_device_properties_reply_t *R)
+{
+ return (xcb_atom_t *) (R + 1);
+}
+
+int
+xcb_input_list_device_properties_atoms_length (const xcb_input_list_device_properties_reply_t *R)
+{
+ return R->num_atoms;
+}
+
+xcb_generic_iterator_t
+xcb_input_list_device_properties_atoms_end (const xcb_input_list_device_properties_reply_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((xcb_atom_t *) (R + 1)) + (R->num_atoms);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_list_device_properties_reply_t *
+xcb_input_list_device_properties_reply (xcb_connection_t *c,
+ xcb_input_list_device_properties_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_list_device_properties_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+uint8_t *
+xcb_input_change_device_property_items_data_8 (const xcb_input_change_device_property_items_t *S)
+{
+ return S->data8;
+}
+
+int
+xcb_input_change_device_property_items_data_8_length (const xcb_input_change_device_property_request_t *R,
+ const xcb_input_change_device_property_items_t *S)
+{
+ return R->num_items;
+}
+
+xcb_generic_iterator_t
+xcb_input_change_device_property_items_data_8_end (const xcb_input_change_device_property_request_t *R,
+ const xcb_input_change_device_property_items_t *S)
+{
+ xcb_generic_iterator_t i;
+ i.data = S->data8 + R->num_items;
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) S;
+ return i;
+}
+
+uint16_t *
+xcb_input_change_device_property_items_data_16 (const xcb_input_change_device_property_items_t *S)
+{
+ return S->data16;
+}
+
+int
+xcb_input_change_device_property_items_data_16_length (const xcb_input_change_device_property_request_t *R,
+ const xcb_input_change_device_property_items_t *S)
+{
+ return R->num_items;
+}
+
+xcb_generic_iterator_t
+xcb_input_change_device_property_items_data_16_end (const xcb_input_change_device_property_request_t *R,
+ const xcb_input_change_device_property_items_t *S)
+{
+ xcb_generic_iterator_t i;
+ i.data = S->data16 + R->num_items;
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) S;
+ return i;
+}
+
+uint32_t *
+xcb_input_change_device_property_items_data_32 (const xcb_input_change_device_property_items_t *S)
+{
+ return S->data32;
+}
+
+int
+xcb_input_change_device_property_items_data_32_length (const xcb_input_change_device_property_request_t *R,
+ const xcb_input_change_device_property_items_t *S)
+{
+ return R->num_items;
+}
+
+xcb_generic_iterator_t
+xcb_input_change_device_property_items_data_32_end (const xcb_input_change_device_property_request_t *R,
+ const xcb_input_change_device_property_items_t *S)
+{
+ xcb_generic_iterator_t i;
+ i.data = S->data32 + R->num_items;
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) S;
+ return i;
+}
+
+int
+xcb_input_change_device_property_items_serialize (void **_buffer,
+ uint32_t num_items,
+ uint8_t format,
+ const xcb_input_change_device_property_items_t *_aux)
+{
+ char *xcb_out = *_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_align_to = 0;
+ unsigned int xcb_padding_offset = 0;
+
+ unsigned int xcb_pad = 0;
+ char xcb_pad0[3] = {0, 0, 0};
+ struct iovec xcb_parts[9];
+ unsigned int xcb_parts_idx = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int i;
+ char *xcb_tmp;
+
+ if(format == XCB_INPUT_PROPERTY_FORMAT_8_BITS) {
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* data8 */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->data8;
+ xcb_block_len += num_items * sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = num_items * sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ xcb_align_to = 4;
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ }
+ if(format == XCB_INPUT_PROPERTY_FORMAT_16_BITS) {
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* data16 */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->data16;
+ xcb_block_len += num_items * sizeof(uint16_t);
+ xcb_parts[xcb_parts_idx].iov_len = num_items * sizeof(uint16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint16_t);
+ xcb_align_to = 4;
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ }
+ if(format == XCB_INPUT_PROPERTY_FORMAT_32_BITS) {
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* data32 */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->data32;
+ xcb_block_len += num_items * sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = num_items * sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+
+ if (NULL == xcb_out) {
+ /* allocate memory */
+ xcb_out = malloc(xcb_buffer_len);
+ *_buffer = xcb_out;
+ }
+
+ xcb_tmp = xcb_out;
+ for(i=0; i<xcb_parts_idx; i++) {
+ if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)
+ memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);
+ if (0 != xcb_parts[i].iov_len)
+ xcb_tmp += xcb_parts[i].iov_len;
+ }
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_change_device_property_items_unpack (const void *_buffer,
+ uint32_t num_items,
+ uint8_t format,
+ xcb_input_change_device_property_items_t *_aux)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+ unsigned int xcb_padding_offset = 0;
+
+
+ if(format == XCB_INPUT_PROPERTY_FORMAT_8_BITS) {
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* data8 */
+ _aux->data8 = (uint8_t *)xcb_tmp;
+ xcb_block_len += num_items * sizeof(uint8_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint8_t);
+ xcb_align_to = 4;
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ }
+ if(format == XCB_INPUT_PROPERTY_FORMAT_16_BITS) {
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* data16 */
+ _aux->data16 = (uint16_t *)xcb_tmp;
+ xcb_block_len += num_items * sizeof(uint16_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint16_t);
+ xcb_align_to = 4;
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ }
+ if(format == XCB_INPUT_PROPERTY_FORMAT_32_BITS) {
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* data32 */
+ _aux->data32 = (uint32_t *)xcb_tmp;
+ xcb_block_len += num_items * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_change_device_property_items_sizeof (const void *_buffer,
+ uint32_t num_items,
+ uint8_t format)
+{
+ xcb_input_change_device_property_items_t _aux;
+ return xcb_input_change_device_property_items_unpack(_buffer, num_items, format, &_aux);
+}
+
+int
+xcb_input_change_device_property_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_change_device_property_request_t *_aux = (xcb_input_change_device_property_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_change_device_property_request_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* items */
+ xcb_block_len += xcb_input_change_device_property_items_sizeof(xcb_tmp, _aux->num_items, _aux->format);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_void_cookie_t
+xcb_input_change_device_property_checked (xcb_connection_t *c,
+ xcb_atom_t property,
+ xcb_atom_t type,
+ uint8_t device_id,
+ uint8_t format,
+ uint8_t mode,
+ uint32_t num_items,
+ const void *items)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 3,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_CHANGE_DEVICE_PROPERTY,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[5];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_change_device_property_request_t xcb_out;
+
+ xcb_out.property = property;
+ xcb_out.type = type;
+ xcb_out.device_id = device_id;
+ xcb_out.format = format;
+ xcb_out.mode = mode;
+ xcb_out.pad0 = 0;
+ xcb_out.num_items = num_items;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_change_device_property_items_t items */
+ xcb_parts[4].iov_base = (char *) items;
+ xcb_parts[4].iov_len =
+ xcb_input_change_device_property_items_sizeof (items, num_items, format);
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_change_device_property (xcb_connection_t *c,
+ xcb_atom_t property,
+ xcb_atom_t type,
+ uint8_t device_id,
+ uint8_t format,
+ uint8_t mode,
+ uint32_t num_items,
+ const void *items)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 3,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_CHANGE_DEVICE_PROPERTY,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[5];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_change_device_property_request_t xcb_out;
+
+ xcb_out.property = property;
+ xcb_out.type = type;
+ xcb_out.device_id = device_id;
+ xcb_out.format = format;
+ xcb_out.mode = mode;
+ xcb_out.pad0 = 0;
+ xcb_out.num_items = num_items;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_change_device_property_items_t items */
+ xcb_parts[4].iov_base = (char *) items;
+ xcb_parts[4].iov_len =
+ xcb_input_change_device_property_items_sizeof (items, num_items, format);
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_change_device_property_aux_checked (xcb_connection_t *c,
+ xcb_atom_t property,
+ xcb_atom_t type,
+ uint8_t device_id,
+ uint8_t format,
+ uint8_t mode,
+ uint32_t num_items,
+ const xcb_input_change_device_property_items_t *items)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 3,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_CHANGE_DEVICE_PROPERTY,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[5];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_change_device_property_request_t xcb_out;
+ void *xcb_aux0 = 0;
+
+ xcb_out.property = property;
+ xcb_out.type = type;
+ xcb_out.device_id = device_id;
+ xcb_out.format = format;
+ xcb_out.mode = mode;
+ xcb_out.pad0 = 0;
+ xcb_out.num_items = num_items;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_change_device_property_items_t items */
+ xcb_parts[4].iov_len =
+ xcb_input_change_device_property_items_serialize (&xcb_aux0, num_items, format, items);
+ xcb_parts[4].iov_base = xcb_aux0;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ free(xcb_aux0);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_change_device_property_aux (xcb_connection_t *c,
+ xcb_atom_t property,
+ xcb_atom_t type,
+ uint8_t device_id,
+ uint8_t format,
+ uint8_t mode,
+ uint32_t num_items,
+ const xcb_input_change_device_property_items_t *items)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 3,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_CHANGE_DEVICE_PROPERTY,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[5];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_change_device_property_request_t xcb_out;
+ void *xcb_aux0 = 0;
+
+ xcb_out.property = property;
+ xcb_out.type = type;
+ xcb_out.device_id = device_id;
+ xcb_out.format = format;
+ xcb_out.mode = mode;
+ xcb_out.pad0 = 0;
+ xcb_out.num_items = num_items;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_change_device_property_items_t items */
+ xcb_parts[4].iov_len =
+ xcb_input_change_device_property_items_serialize (&xcb_aux0, num_items, format, items);
+ xcb_parts[4].iov_base = xcb_aux0;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ free(xcb_aux0);
+ return xcb_ret;
+}
+
+void *
+xcb_input_change_device_property_items (const xcb_input_change_device_property_request_t *R)
+{
+ return (void *) (R + 1);
+}
+
+xcb_void_cookie_t
+xcb_input_delete_device_property_checked (xcb_connection_t *c,
+ xcb_atom_t property,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_DELETE_DEVICE_PROPERTY,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_delete_device_property_request_t xcb_out;
+
+ xcb_out.property = property;
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_delete_device_property (xcb_connection_t *c,
+ xcb_atom_t property,
+ uint8_t device_id)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_DELETE_DEVICE_PROPERTY,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_delete_device_property_request_t xcb_out;
+
+ xcb_out.property = property;
+ xcb_out.device_id = device_id;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+uint8_t *
+xcb_input_get_device_property_items_data_8 (const xcb_input_get_device_property_items_t *S)
+{
+ return S->data8;
+}
+
+int
+xcb_input_get_device_property_items_data_8_length (const xcb_input_get_device_property_reply_t *R,
+ const xcb_input_get_device_property_items_t *S)
+{
+ return R->num_items;
+}
+
+xcb_generic_iterator_t
+xcb_input_get_device_property_items_data_8_end (const xcb_input_get_device_property_reply_t *R,
+ const xcb_input_get_device_property_items_t *S)
+{
+ xcb_generic_iterator_t i;
+ i.data = S->data8 + R->num_items;
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) S;
+ return i;
+}
+
+uint16_t *
+xcb_input_get_device_property_items_data_16 (const xcb_input_get_device_property_items_t *S)
+{
+ return S->data16;
+}
+
+int
+xcb_input_get_device_property_items_data_16_length (const xcb_input_get_device_property_reply_t *R,
+ const xcb_input_get_device_property_items_t *S)
+{
+ return R->num_items;
+}
+
+xcb_generic_iterator_t
+xcb_input_get_device_property_items_data_16_end (const xcb_input_get_device_property_reply_t *R,
+ const xcb_input_get_device_property_items_t *S)
+{
+ xcb_generic_iterator_t i;
+ i.data = S->data16 + R->num_items;
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) S;
+ return i;
+}
+
+uint32_t *
+xcb_input_get_device_property_items_data_32 (const xcb_input_get_device_property_items_t *S)
+{
+ return S->data32;
+}
+
+int
+xcb_input_get_device_property_items_data_32_length (const xcb_input_get_device_property_reply_t *R,
+ const xcb_input_get_device_property_items_t *S)
+{
+ return R->num_items;
+}
+
+xcb_generic_iterator_t
+xcb_input_get_device_property_items_data_32_end (const xcb_input_get_device_property_reply_t *R,
+ const xcb_input_get_device_property_items_t *S)
+{
+ xcb_generic_iterator_t i;
+ i.data = S->data32 + R->num_items;
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) S;
+ return i;
+}
+
+int
+xcb_input_get_device_property_items_serialize (void **_buffer,
+ uint32_t num_items,
+ uint8_t format,
+ const xcb_input_get_device_property_items_t *_aux)
+{
+ char *xcb_out = *_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_align_to = 0;
+ unsigned int xcb_padding_offset = 0;
+
+ unsigned int xcb_pad = 0;
+ char xcb_pad0[3] = {0, 0, 0};
+ struct iovec xcb_parts[9];
+ unsigned int xcb_parts_idx = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int i;
+ char *xcb_tmp;
+
+ if(format == XCB_INPUT_PROPERTY_FORMAT_8_BITS) {
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* data8 */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->data8;
+ xcb_block_len += num_items * sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = num_items * sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ xcb_align_to = 4;
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ }
+ if(format == XCB_INPUT_PROPERTY_FORMAT_16_BITS) {
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* data16 */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->data16;
+ xcb_block_len += num_items * sizeof(uint16_t);
+ xcb_parts[xcb_parts_idx].iov_len = num_items * sizeof(uint16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint16_t);
+ xcb_align_to = 4;
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ }
+ if(format == XCB_INPUT_PROPERTY_FORMAT_32_BITS) {
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* data32 */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->data32;
+ xcb_block_len += num_items * sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = num_items * sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+
+ if (NULL == xcb_out) {
+ /* allocate memory */
+ xcb_out = malloc(xcb_buffer_len);
+ *_buffer = xcb_out;
+ }
+
+ xcb_tmp = xcb_out;
+ for(i=0; i<xcb_parts_idx; i++) {
+ if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)
+ memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);
+ if (0 != xcb_parts[i].iov_len)
+ xcb_tmp += xcb_parts[i].iov_len;
+ }
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_get_device_property_items_unpack (const void *_buffer,
+ uint32_t num_items,
+ uint8_t format,
+ xcb_input_get_device_property_items_t *_aux)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+ unsigned int xcb_padding_offset = 0;
+
+
+ if(format == XCB_INPUT_PROPERTY_FORMAT_8_BITS) {
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* data8 */
+ _aux->data8 = (uint8_t *)xcb_tmp;
+ xcb_block_len += num_items * sizeof(uint8_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint8_t);
+ xcb_align_to = 4;
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ }
+ if(format == XCB_INPUT_PROPERTY_FORMAT_16_BITS) {
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* data16 */
+ _aux->data16 = (uint16_t *)xcb_tmp;
+ xcb_block_len += num_items * sizeof(uint16_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint16_t);
+ xcb_align_to = 4;
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ }
+ if(format == XCB_INPUT_PROPERTY_FORMAT_32_BITS) {
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* data32 */
+ _aux->data32 = (uint32_t *)xcb_tmp;
+ xcb_block_len += num_items * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_get_device_property_items_sizeof (const void *_buffer,
+ uint32_t num_items,
+ uint8_t format)
+{
+ xcb_input_get_device_property_items_t _aux;
+ return xcb_input_get_device_property_items_unpack(_buffer, num_items, format, &_aux);
+}
+
+int
+xcb_input_get_device_property_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_get_device_property_reply_t *_aux = (xcb_input_get_device_property_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_get_device_property_reply_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* items */
+ xcb_block_len += xcb_input_get_device_property_items_sizeof(xcb_tmp, _aux->num_items, _aux->format);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_get_device_property_cookie_t
+xcb_input_get_device_property (xcb_connection_t *c,
+ xcb_atom_t property,
+ xcb_atom_t type,
+ uint32_t offset,
+ uint32_t len,
+ uint8_t device_id,
+ uint8_t _delete)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GET_DEVICE_PROPERTY,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_get_device_property_cookie_t xcb_ret;
+ xcb_input_get_device_property_request_t xcb_out;
+
+ xcb_out.property = property;
+ xcb_out.type = type;
+ xcb_out.offset = offset;
+ xcb_out.len = len;
+ xcb_out.device_id = device_id;
+ xcb_out._delete = _delete;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_get_device_property_cookie_t
+xcb_input_get_device_property_unchecked (xcb_connection_t *c,
+ xcb_atom_t property,
+ xcb_atom_t type,
+ uint32_t offset,
+ uint32_t len,
+ uint8_t device_id,
+ uint8_t _delete)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_GET_DEVICE_PROPERTY,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_get_device_property_cookie_t xcb_ret;
+ xcb_input_get_device_property_request_t xcb_out;
+
+ xcb_out.property = property;
+ xcb_out.type = type;
+ xcb_out.offset = offset;
+ xcb_out.len = len;
+ xcb_out.device_id = device_id;
+ xcb_out._delete = _delete;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+void *
+xcb_input_get_device_property_items (const xcb_input_get_device_property_reply_t *R)
+{
+ return (void *) (R + 1);
+}
+
+xcb_input_get_device_property_reply_t *
+xcb_input_get_device_property_reply (xcb_connection_t *c,
+ xcb_input_get_device_property_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_get_device_property_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+void
+xcb_input_group_info_next (xcb_input_group_info_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_group_info_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_group_info_end (xcb_input_group_info_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_modifier_info_next (xcb_input_modifier_info_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_modifier_info_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_modifier_info_end (xcb_input_modifier_info_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+int
+xcb_input_xi_query_pointer_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_xi_query_pointer_reply_t *_aux = (xcb_input_xi_query_pointer_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_xi_query_pointer_reply_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* buttons */
+ xcb_block_len += _aux->buttons_len * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_xi_query_pointer_cookie_t
+xcb_input_xi_query_pointer (xcb_connection_t *c,
+ xcb_window_t window,
+ xcb_input_device_id_t deviceid)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_QUERY_POINTER,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_xi_query_pointer_cookie_t xcb_ret;
+ xcb_input_xi_query_pointer_request_t xcb_out;
+
+ xcb_out.window = window;
+ xcb_out.deviceid = deviceid;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_xi_query_pointer_cookie_t
+xcb_input_xi_query_pointer_unchecked (xcb_connection_t *c,
+ xcb_window_t window,
+ xcb_input_device_id_t deviceid)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_QUERY_POINTER,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_xi_query_pointer_cookie_t xcb_ret;
+ xcb_input_xi_query_pointer_request_t xcb_out;
+
+ xcb_out.window = window;
+ xcb_out.deviceid = deviceid;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+uint32_t *
+xcb_input_xi_query_pointer_buttons (const xcb_input_xi_query_pointer_reply_t *R)
+{
+ return (uint32_t *) (R + 1);
+}
+
+int
+xcb_input_xi_query_pointer_buttons_length (const xcb_input_xi_query_pointer_reply_t *R)
+{
+ return R->buttons_len;
+}
+
+xcb_generic_iterator_t
+xcb_input_xi_query_pointer_buttons_end (const xcb_input_xi_query_pointer_reply_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((uint32_t *) (R + 1)) + (R->buttons_len);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_xi_query_pointer_reply_t *
+xcb_input_xi_query_pointer_reply (xcb_connection_t *c,
+ xcb_input_xi_query_pointer_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_xi_query_pointer_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+xcb_void_cookie_t
+xcb_input_xi_warp_pointer_checked (xcb_connection_t *c,
+ xcb_window_t src_win,
+ xcb_window_t dst_win,
+ xcb_input_fp1616_t src_x,
+ xcb_input_fp1616_t src_y,
+ uint16_t src_width,
+ uint16_t src_height,
+ xcb_input_fp1616_t dst_x,
+ xcb_input_fp1616_t dst_y,
+ xcb_input_device_id_t deviceid)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_WARP_POINTER,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_xi_warp_pointer_request_t xcb_out;
+
+ xcb_out.src_win = src_win;
+ xcb_out.dst_win = dst_win;
+ xcb_out.src_x = src_x;
+ xcb_out.src_y = src_y;
+ xcb_out.src_width = src_width;
+ xcb_out.src_height = src_height;
+ xcb_out.dst_x = dst_x;
+ xcb_out.dst_y = dst_y;
+ xcb_out.deviceid = deviceid;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_xi_warp_pointer (xcb_connection_t *c,
+ xcb_window_t src_win,
+ xcb_window_t dst_win,
+ xcb_input_fp1616_t src_x,
+ xcb_input_fp1616_t src_y,
+ uint16_t src_width,
+ uint16_t src_height,
+ xcb_input_fp1616_t dst_x,
+ xcb_input_fp1616_t dst_y,
+ xcb_input_device_id_t deviceid)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_WARP_POINTER,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_xi_warp_pointer_request_t xcb_out;
+
+ xcb_out.src_win = src_win;
+ xcb_out.dst_win = dst_win;
+ xcb_out.src_x = src_x;
+ xcb_out.src_y = src_y;
+ xcb_out.src_width = src_width;
+ xcb_out.src_height = src_height;
+ xcb_out.dst_x = dst_x;
+ xcb_out.dst_y = dst_y;
+ xcb_out.deviceid = deviceid;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_xi_change_cursor_checked (xcb_connection_t *c,
+ xcb_window_t window,
+ xcb_cursor_t cursor,
+ xcb_input_device_id_t deviceid)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_CHANGE_CURSOR,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_xi_change_cursor_request_t xcb_out;
+
+ xcb_out.window = window;
+ xcb_out.cursor = cursor;
+ xcb_out.deviceid = deviceid;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_xi_change_cursor (xcb_connection_t *c,
+ xcb_window_t window,
+ xcb_cursor_t cursor,
+ xcb_input_device_id_t deviceid)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_CHANGE_CURSOR,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_xi_change_cursor_request_t xcb_out;
+
+ xcb_out.window = window;
+ xcb_out.cursor = cursor;
+ xcb_out.deviceid = deviceid;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+int
+xcb_input_add_master_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_add_master_t *_aux = (xcb_input_add_master_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_add_master_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* name */
+ xcb_block_len += _aux->name_len * sizeof(char);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ xcb_align_to = 4;
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+char *
+xcb_input_add_master_name (const xcb_input_add_master_t *R)
+{
+ return (char *) (R + 1);
+}
+
+int
+xcb_input_add_master_name_length (const xcb_input_add_master_t *R)
+{
+ return R->name_len;
+}
+
+xcb_generic_iterator_t
+xcb_input_add_master_name_end (const xcb_input_add_master_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((char *) (R + 1)) + (R->name_len);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+void
+xcb_input_add_master_next (xcb_input_add_master_iterator_t *i)
+{
+ xcb_input_add_master_t *R = i->data;
+ xcb_generic_iterator_t child;
+ child.data = (xcb_input_add_master_t *)(((char *)R) + xcb_input_add_master_sizeof(R));
+ i->index = (char *) child.data - (char *) i->data;
+ --i->rem;
+ i->data = (xcb_input_add_master_t *) child.data;
+}
+
+xcb_generic_iterator_t
+xcb_input_add_master_end (xcb_input_add_master_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ while(i.rem > 0)
+ xcb_input_add_master_next(&i);
+ ret.data = i.data;
+ ret.rem = i.rem;
+ ret.index = i.index;
+ return ret;
+}
+
+void
+xcb_input_remove_master_next (xcb_input_remove_master_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_remove_master_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_remove_master_end (xcb_input_remove_master_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_attach_slave_next (xcb_input_attach_slave_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_attach_slave_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_attach_slave_end (xcb_input_attach_slave_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_detach_slave_next (xcb_input_detach_slave_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_detach_slave_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_detach_slave_end (xcb_input_detach_slave_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+char *
+xcb_input_hierarchy_change_data_add_master_name (const xcb_input_hierarchy_change_data_t *S)
+{
+ return S->add_master.name;
+}
+
+int
+xcb_input_hierarchy_change_data_add_master_name_length (const xcb_input_hierarchy_change_t *R,
+ const xcb_input_hierarchy_change_data_t *S)
+{
+ return S->add_master.name_len;
+}
+
+xcb_generic_iterator_t
+xcb_input_hierarchy_change_data_add_master_name_end (const xcb_input_hierarchy_change_t *R,
+ const xcb_input_hierarchy_change_data_t *S)
+{
+ xcb_generic_iterator_t i;
+ i.data = S->add_master.name + S->add_master.name_len;
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) S;
+ return i;
+}
+
+int
+xcb_input_hierarchy_change_data_serialize (void **_buffer,
+ uint16_t type,
+ const xcb_input_hierarchy_change_data_t *_aux)
+{
+ char *xcb_out = *_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_align_to = 0;
+ unsigned int xcb_padding_offset = 0;
+
+ unsigned int xcb_pad = 0;
+ char xcb_pad0[3] = {0, 0, 0};
+ struct iovec xcb_parts[16];
+ unsigned int xcb_parts_idx = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int i;
+ char *xcb_tmp;
+
+ if(type == XCB_INPUT_HIERARCHY_CHANGE_TYPE_ADD_MASTER) {
+ /* xcb_input_hierarchy_change_data_t.add_master.name_len */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->add_master.name_len;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* xcb_input_hierarchy_change_data_t.add_master.send_core */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->add_master.send_core;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_hierarchy_change_data_t.add_master.enable */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->add_master.enable;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* name */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->add_master.name;
+ xcb_block_len += _aux->add_master.name_len * sizeof(char);
+ xcb_parts[xcb_parts_idx].iov_len = _aux->add_master.name_len * sizeof(char);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(char);
+ xcb_align_to = 4;
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ }
+ if(type == XCB_INPUT_HIERARCHY_CHANGE_TYPE_REMOVE_MASTER) {
+ /* xcb_input_hierarchy_change_data_t.remove_master.deviceid */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->remove_master.deviceid;
+ xcb_block_len += sizeof(xcb_input_device_id_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(xcb_input_device_id_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(xcb_input_device_id_t);
+ /* xcb_input_hierarchy_change_data_t.remove_master.return_mode */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->remove_master.return_mode;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_hierarchy_change_data_t.remove_master.pad1 */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &xcb_pad;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_hierarchy_change_data_t.remove_master.return_pointer */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->remove_master.return_pointer;
+ xcb_block_len += sizeof(xcb_input_device_id_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(xcb_input_device_id_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(xcb_input_device_id_t);
+ /* xcb_input_hierarchy_change_data_t.remove_master.return_keyboard */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->remove_master.return_keyboard;
+ xcb_block_len += sizeof(xcb_input_device_id_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(xcb_input_device_id_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(xcb_input_device_id_t);
+ }
+ if(type == XCB_INPUT_HIERARCHY_CHANGE_TYPE_ATTACH_SLAVE) {
+ /* xcb_input_hierarchy_change_data_t.attach_slave.deviceid */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->attach_slave.deviceid;
+ xcb_block_len += sizeof(xcb_input_device_id_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(xcb_input_device_id_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(xcb_input_device_id_t);
+ /* xcb_input_hierarchy_change_data_t.attach_slave.master */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->attach_slave.master;
+ xcb_block_len += sizeof(xcb_input_device_id_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(xcb_input_device_id_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(xcb_input_device_id_t);
+ }
+ if(type == XCB_INPUT_HIERARCHY_CHANGE_TYPE_DETACH_SLAVE) {
+ /* xcb_input_hierarchy_change_data_t.detach_slave.deviceid */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->detach_slave.deviceid;
+ xcb_block_len += sizeof(xcb_input_device_id_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(xcb_input_device_id_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(xcb_input_device_id_t);
+ /* xcb_input_hierarchy_change_data_t.detach_slave.pad2 */
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_block_len += sizeof(uint8_t)*2;
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t)*2;
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ }
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+
+ if (NULL == xcb_out) {
+ /* allocate memory */
+ xcb_out = malloc(xcb_buffer_len);
+ *_buffer = xcb_out;
+ }
+
+ xcb_tmp = xcb_out;
+ for(i=0; i<xcb_parts_idx; i++) {
+ if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)
+ memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);
+ if (0 != xcb_parts[i].iov_len)
+ xcb_tmp += xcb_parts[i].iov_len;
+ }
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_hierarchy_change_data_unpack (const void *_buffer,
+ uint16_t type,
+ xcb_input_hierarchy_change_data_t *_aux)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+ unsigned int xcb_padding_offset = 0;
+
+
+ if(type == XCB_INPUT_HIERARCHY_CHANGE_TYPE_ADD_MASTER) {
+ /* xcb_input_hierarchy_change_data_t.add_master.name_len */
+ _aux->add_master.name_len = *(uint16_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_tmp += sizeof(uint16_t);
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* xcb_input_hierarchy_change_data_t.add_master.send_core */
+ _aux->add_master.send_core = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_hierarchy_change_data_t.add_master.enable */
+ _aux->add_master.enable = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* name */
+ _aux->add_master.name = (char *)xcb_tmp;
+ xcb_block_len += _aux->add_master.name_len * sizeof(char);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ xcb_align_to = 4;
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ }
+ if(type == XCB_INPUT_HIERARCHY_CHANGE_TYPE_REMOVE_MASTER) {
+ /* xcb_input_hierarchy_change_data_t.remove_master.deviceid */
+ _aux->remove_master.deviceid = *(xcb_input_device_id_t *)xcb_tmp;
+ xcb_block_len += sizeof(xcb_input_device_id_t);
+ xcb_tmp += sizeof(xcb_input_device_id_t);
+ xcb_align_to = ALIGNOF(xcb_input_device_id_t);
+ /* xcb_input_hierarchy_change_data_t.remove_master.return_mode */
+ _aux->remove_master.return_mode = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_hierarchy_change_data_t.remove_master.pad1 */
+ _aux->remove_master.pad1 = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_hierarchy_change_data_t.remove_master.return_pointer */
+ _aux->remove_master.return_pointer = *(xcb_input_device_id_t *)xcb_tmp;
+ xcb_block_len += sizeof(xcb_input_device_id_t);
+ xcb_tmp += sizeof(xcb_input_device_id_t);
+ xcb_align_to = ALIGNOF(xcb_input_device_id_t);
+ /* xcb_input_hierarchy_change_data_t.remove_master.return_keyboard */
+ _aux->remove_master.return_keyboard = *(xcb_input_device_id_t *)xcb_tmp;
+ xcb_block_len += sizeof(xcb_input_device_id_t);
+ xcb_tmp += sizeof(xcb_input_device_id_t);
+ xcb_align_to = ALIGNOF(xcb_input_device_id_t);
+ }
+ if(type == XCB_INPUT_HIERARCHY_CHANGE_TYPE_ATTACH_SLAVE) {
+ /* xcb_input_hierarchy_change_data_t.attach_slave.deviceid */
+ _aux->attach_slave.deviceid = *(xcb_input_device_id_t *)xcb_tmp;
+ xcb_block_len += sizeof(xcb_input_device_id_t);
+ xcb_tmp += sizeof(xcb_input_device_id_t);
+ xcb_align_to = ALIGNOF(xcb_input_device_id_t);
+ /* xcb_input_hierarchy_change_data_t.attach_slave.master */
+ _aux->attach_slave.master = *(xcb_input_device_id_t *)xcb_tmp;
+ xcb_block_len += sizeof(xcb_input_device_id_t);
+ xcb_tmp += sizeof(xcb_input_device_id_t);
+ xcb_align_to = ALIGNOF(xcb_input_device_id_t);
+ }
+ if(type == XCB_INPUT_HIERARCHY_CHANGE_TYPE_DETACH_SLAVE) {
+ /* xcb_input_hierarchy_change_data_t.detach_slave.deviceid */
+ _aux->detach_slave.deviceid = *(xcb_input_device_id_t *)xcb_tmp;
+ xcb_block_len += sizeof(xcb_input_device_id_t);
+ xcb_tmp += sizeof(xcb_input_device_id_t);
+ xcb_align_to = ALIGNOF(xcb_input_device_id_t);
+ /* xcb_input_hierarchy_change_data_t.detach_slave.pad2 */
+ _aux->detach_slave.pad2[0] = *(uint8_t *)xcb_tmp;
+ _aux->detach_slave.pad2[1] = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t) * 2;
+ xcb_tmp += sizeof(uint8_t) * 2;
+ xcb_align_to = ALIGNOF(uint8_t);
+ }
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_hierarchy_change_data_sizeof (const void *_buffer,
+ uint16_t type)
+{
+ xcb_input_hierarchy_change_data_t _aux;
+ return xcb_input_hierarchy_change_data_unpack(_buffer, type, &_aux);
+}
+
+int
+xcb_input_hierarchy_change_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_hierarchy_change_t *_aux = (xcb_input_hierarchy_change_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_hierarchy_change_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* data */
+ xcb_block_len += xcb_input_hierarchy_change_data_sizeof(xcb_tmp, _aux->type);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+void *
+xcb_input_hierarchy_change_data (const xcb_input_hierarchy_change_t *R)
+{
+ return (void *) (R + 1);
+}
+
+void
+xcb_input_hierarchy_change_next (xcb_input_hierarchy_change_iterator_t *i)
+{
+ xcb_input_hierarchy_change_t *R = i->data;
+ xcb_generic_iterator_t child;
+ child.data = (xcb_input_hierarchy_change_t *)(((char *)R) + xcb_input_hierarchy_change_sizeof(R));
+ i->index = (char *) child.data - (char *) i->data;
+ --i->rem;
+ i->data = (xcb_input_hierarchy_change_t *) child.data;
+}
+
+xcb_generic_iterator_t
+xcb_input_hierarchy_change_end (xcb_input_hierarchy_change_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ while(i.rem > 0)
+ xcb_input_hierarchy_change_next(&i);
+ ret.data = i.data;
+ ret.rem = i.rem;
+ ret.index = i.index;
+ return ret;
+}
+
+int
+xcb_input_xi_change_hierarchy_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_xi_change_hierarchy_request_t *_aux = (xcb_input_xi_change_hierarchy_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+ unsigned int i;
+ unsigned int xcb_tmp_len;
+
+ xcb_block_len += sizeof(xcb_input_xi_change_hierarchy_request_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* changes */
+ for(i=0; i<_aux->num_changes; i++) {
+ xcb_tmp_len = xcb_input_hierarchy_change_sizeof(xcb_tmp);
+ xcb_block_len += xcb_tmp_len;
+ xcb_tmp += xcb_tmp_len;
+ }
+ xcb_align_to = ALIGNOF(xcb_input_hierarchy_change_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_void_cookie_t
+xcb_input_xi_change_hierarchy_checked (xcb_connection_t *c,
+ uint8_t num_changes,
+ const xcb_input_hierarchy_change_t *changes)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_CHANGE_HIERARCHY,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_xi_change_hierarchy_request_t xcb_out;
+ unsigned int xcb_tmp_len;
+ char *xcb_tmp;
+ unsigned int i;
+
+ xcb_out.num_changes = num_changes;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_hierarchy_change_t changes */
+ xcb_parts[4].iov_base = (char *) changes;
+ xcb_parts[4].iov_len = 0;
+ xcb_tmp = (char *)changes;
+ for(i=0; i<num_changes; i++) {
+ xcb_tmp_len = xcb_input_hierarchy_change_sizeof(xcb_tmp);
+ xcb_parts[4].iov_len += xcb_tmp_len;
+ xcb_tmp += xcb_tmp_len;
+ }
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_xi_change_hierarchy (xcb_connection_t *c,
+ uint8_t num_changes,
+ const xcb_input_hierarchy_change_t *changes)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_CHANGE_HIERARCHY,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_xi_change_hierarchy_request_t xcb_out;
+ unsigned int xcb_tmp_len;
+ char *xcb_tmp;
+ unsigned int i;
+
+ xcb_out.num_changes = num_changes;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_hierarchy_change_t changes */
+ xcb_parts[4].iov_base = (char *) changes;
+ xcb_parts[4].iov_len = 0;
+ xcb_tmp = (char *)changes;
+ for(i=0; i<num_changes; i++) {
+ xcb_tmp_len = xcb_input_hierarchy_change_sizeof(xcb_tmp);
+ xcb_parts[4].iov_len += xcb_tmp_len;
+ xcb_tmp += xcb_tmp_len;
+ }
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+int
+xcb_input_xi_change_hierarchy_changes_length (const xcb_input_xi_change_hierarchy_request_t *R)
+{
+ return R->num_changes;
+}
+
+xcb_input_hierarchy_change_iterator_t
+xcb_input_xi_change_hierarchy_changes_iterator (const xcb_input_xi_change_hierarchy_request_t *R)
+{
+ xcb_input_hierarchy_change_iterator_t i;
+ i.data = (xcb_input_hierarchy_change_t *) (R + 1);
+ i.rem = R->num_changes;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_void_cookie_t
+xcb_input_xi_set_client_pointer_checked (xcb_connection_t *c,
+ xcb_window_t window,
+ xcb_input_device_id_t deviceid)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_SET_CLIENT_POINTER,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_xi_set_client_pointer_request_t xcb_out;
+
+ xcb_out.window = window;
+ xcb_out.deviceid = deviceid;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_xi_set_client_pointer (xcb_connection_t *c,
+ xcb_window_t window,
+ xcb_input_device_id_t deviceid)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_SET_CLIENT_POINTER,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_xi_set_client_pointer_request_t xcb_out;
+
+ xcb_out.window = window;
+ xcb_out.deviceid = deviceid;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_xi_get_client_pointer_cookie_t
+xcb_input_xi_get_client_pointer (xcb_connection_t *c,
+ xcb_window_t window)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_GET_CLIENT_POINTER,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_xi_get_client_pointer_cookie_t xcb_ret;
+ xcb_input_xi_get_client_pointer_request_t xcb_out;
+
+ xcb_out.window = window;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_xi_get_client_pointer_cookie_t
+xcb_input_xi_get_client_pointer_unchecked (xcb_connection_t *c,
+ xcb_window_t window)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_GET_CLIENT_POINTER,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_xi_get_client_pointer_cookie_t xcb_ret;
+ xcb_input_xi_get_client_pointer_request_t xcb_out;
+
+ xcb_out.window = window;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_xi_get_client_pointer_reply_t *
+xcb_input_xi_get_client_pointer_reply (xcb_connection_t *c,
+ xcb_input_xi_get_client_pointer_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_xi_get_client_pointer_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+int
+xcb_input_event_mask_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_event_mask_t *_aux = (xcb_input_event_mask_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_event_mask_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* mask */
+ xcb_block_len += _aux->mask_len * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+uint32_t *
+xcb_input_event_mask_mask (const xcb_input_event_mask_t *R)
+{
+ return (uint32_t *) (R + 1);
+}
+
+int
+xcb_input_event_mask_mask_length (const xcb_input_event_mask_t *R)
+{
+ return R->mask_len;
+}
+
+xcb_generic_iterator_t
+xcb_input_event_mask_mask_end (const xcb_input_event_mask_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((uint32_t *) (R + 1)) + (R->mask_len);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+void
+xcb_input_event_mask_next (xcb_input_event_mask_iterator_t *i)
+{
+ xcb_input_event_mask_t *R = i->data;
+ xcb_generic_iterator_t child;
+ child.data = (xcb_input_event_mask_t *)(((char *)R) + xcb_input_event_mask_sizeof(R));
+ i->index = (char *) child.data - (char *) i->data;
+ --i->rem;
+ i->data = (xcb_input_event_mask_t *) child.data;
+}
+
+xcb_generic_iterator_t
+xcb_input_event_mask_end (xcb_input_event_mask_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ while(i.rem > 0)
+ xcb_input_event_mask_next(&i);
+ ret.data = i.data;
+ ret.rem = i.rem;
+ ret.index = i.index;
+ return ret;
+}
+
+int
+xcb_input_xi_select_events_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_xi_select_events_request_t *_aux = (xcb_input_xi_select_events_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+ unsigned int i;
+ unsigned int xcb_tmp_len;
+
+ xcb_block_len += sizeof(xcb_input_xi_select_events_request_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* masks */
+ for(i=0; i<_aux->num_mask; i++) {
+ xcb_tmp_len = xcb_input_event_mask_sizeof(xcb_tmp);
+ xcb_block_len += xcb_tmp_len;
+ xcb_tmp += xcb_tmp_len;
+ }
+ xcb_align_to = ALIGNOF(xcb_input_event_mask_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_void_cookie_t
+xcb_input_xi_select_events_checked (xcb_connection_t *c,
+ xcb_window_t window,
+ uint16_t num_mask,
+ const xcb_input_event_mask_t *masks)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_SELECT_EVENTS,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_xi_select_events_request_t xcb_out;
+ unsigned int xcb_tmp_len;
+ char *xcb_tmp;
+ unsigned int i;
+
+ xcb_out.window = window;
+ xcb_out.num_mask = num_mask;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_event_mask_t masks */
+ xcb_parts[4].iov_base = (char *) masks;
+ xcb_parts[4].iov_len = 0;
+ xcb_tmp = (char *)masks;
+ for(i=0; i<num_mask; i++) {
+ xcb_tmp_len = xcb_input_event_mask_sizeof(xcb_tmp);
+ xcb_parts[4].iov_len += xcb_tmp_len;
+ xcb_tmp += xcb_tmp_len;
+ }
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_xi_select_events (xcb_connection_t *c,
+ xcb_window_t window,
+ uint16_t num_mask,
+ const xcb_input_event_mask_t *masks)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_SELECT_EVENTS,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_xi_select_events_request_t xcb_out;
+ unsigned int xcb_tmp_len;
+ char *xcb_tmp;
+ unsigned int i;
+
+ xcb_out.window = window;
+ xcb_out.num_mask = num_mask;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_event_mask_t masks */
+ xcb_parts[4].iov_base = (char *) masks;
+ xcb_parts[4].iov_len = 0;
+ xcb_tmp = (char *)masks;
+ for(i=0; i<num_mask; i++) {
+ xcb_tmp_len = xcb_input_event_mask_sizeof(xcb_tmp);
+ xcb_parts[4].iov_len += xcb_tmp_len;
+ xcb_tmp += xcb_tmp_len;
+ }
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+int
+xcb_input_xi_select_events_masks_length (const xcb_input_xi_select_events_request_t *R)
+{
+ return R->num_mask;
+}
+
+xcb_input_event_mask_iterator_t
+xcb_input_xi_select_events_masks_iterator (const xcb_input_xi_select_events_request_t *R)
+{
+ xcb_input_event_mask_iterator_t i;
+ i.data = (xcb_input_event_mask_t *) (R + 1);
+ i.rem = R->num_mask;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_xi_query_version_cookie_t
+xcb_input_xi_query_version (xcb_connection_t *c,
+ uint16_t major_version,
+ uint16_t minor_version)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_QUERY_VERSION,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_xi_query_version_cookie_t xcb_ret;
+ xcb_input_xi_query_version_request_t xcb_out;
+
+ xcb_out.major_version = major_version;
+ xcb_out.minor_version = minor_version;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_xi_query_version_cookie_t
+xcb_input_xi_query_version_unchecked (xcb_connection_t *c,
+ uint16_t major_version,
+ uint16_t minor_version)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_QUERY_VERSION,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_xi_query_version_cookie_t xcb_ret;
+ xcb_input_xi_query_version_request_t xcb_out;
+
+ xcb_out.major_version = major_version;
+ xcb_out.minor_version = minor_version;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_xi_query_version_reply_t *
+xcb_input_xi_query_version_reply (xcb_connection_t *c,
+ xcb_input_xi_query_version_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_xi_query_version_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+int
+xcb_input_button_class_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_button_class_t *_aux = (xcb_input_button_class_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_button_class_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* state */
+ xcb_block_len += ((_aux->num_buttons + 31) / 32) * sizeof(xcb_atom_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* labels */
+ xcb_block_len += _aux->num_buttons * sizeof(xcb_atom_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_atom_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+uint32_t *
+xcb_input_button_class_state (const xcb_input_button_class_t *R)
+{
+ return (uint32_t *) (R + 1);
+}
+
+int
+xcb_input_button_class_state_length (const xcb_input_button_class_t *R)
+{
+ return ((R->num_buttons + 31) / 32);
+}
+
+xcb_generic_iterator_t
+xcb_input_button_class_state_end (const xcb_input_button_class_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((uint32_t *) (R + 1)) + (((R->num_buttons + 31) / 32));
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_atom_t *
+xcb_input_button_class_labels (const xcb_input_button_class_t *R)
+{
+ xcb_generic_iterator_t prev = xcb_input_button_class_state_end(R);
+ return (xcb_atom_t *) ((char *) prev.data + XCB_TYPE_PAD(xcb_atom_t, prev.index) + 0);
+}
+
+int
+xcb_input_button_class_labels_length (const xcb_input_button_class_t *R)
+{
+ return R->num_buttons;
+}
+
+xcb_generic_iterator_t
+xcb_input_button_class_labels_end (const xcb_input_button_class_t *R)
+{
+ xcb_generic_iterator_t i;
+ xcb_generic_iterator_t prev = xcb_input_button_class_state_end(R);
+ i.data = ((xcb_atom_t *) ((char*) prev.data + XCB_TYPE_PAD(xcb_atom_t, prev.index))) + (R->num_buttons);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+void
+xcb_input_button_class_next (xcb_input_button_class_iterator_t *i)
+{
+ xcb_input_button_class_t *R = i->data;
+ xcb_generic_iterator_t child;
+ child.data = (xcb_input_button_class_t *)(((char *)R) + xcb_input_button_class_sizeof(R));
+ i->index = (char *) child.data - (char *) i->data;
+ --i->rem;
+ i->data = (xcb_input_button_class_t *) child.data;
+}
+
+xcb_generic_iterator_t
+xcb_input_button_class_end (xcb_input_button_class_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ while(i.rem > 0)
+ xcb_input_button_class_next(&i);
+ ret.data = i.data;
+ ret.rem = i.rem;
+ ret.index = i.index;
+ return ret;
+}
+
+int
+xcb_input_key_class_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_key_class_t *_aux = (xcb_input_key_class_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_key_class_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* keys */
+ xcb_block_len += _aux->num_keys * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+uint32_t *
+xcb_input_key_class_keys (const xcb_input_key_class_t *R)
+{
+ return (uint32_t *) (R + 1);
+}
+
+int
+xcb_input_key_class_keys_length (const xcb_input_key_class_t *R)
+{
+ return R->num_keys;
+}
+
+xcb_generic_iterator_t
+xcb_input_key_class_keys_end (const xcb_input_key_class_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((uint32_t *) (R + 1)) + (R->num_keys);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+void
+xcb_input_key_class_next (xcb_input_key_class_iterator_t *i)
+{
+ xcb_input_key_class_t *R = i->data;
+ xcb_generic_iterator_t child;
+ child.data = (xcb_input_key_class_t *)(((char *)R) + xcb_input_key_class_sizeof(R));
+ i->index = (char *) child.data - (char *) i->data;
+ --i->rem;
+ i->data = (xcb_input_key_class_t *) child.data;
+}
+
+xcb_generic_iterator_t
+xcb_input_key_class_end (xcb_input_key_class_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ while(i.rem > 0)
+ xcb_input_key_class_next(&i);
+ ret.data = i.data;
+ ret.rem = i.rem;
+ ret.index = i.index;
+ return ret;
+}
+
+void
+xcb_input_scroll_class_next (xcb_input_scroll_class_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_scroll_class_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_scroll_class_end (xcb_input_scroll_class_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_touch_class_next (xcb_input_touch_class_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_touch_class_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_touch_class_end (xcb_input_touch_class_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+void
+xcb_input_valuator_class_next (xcb_input_valuator_class_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_valuator_class_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_valuator_class_end (xcb_input_valuator_class_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+uint32_t *
+xcb_input_device_class_data_key_keys (const xcb_input_device_class_data_t *S)
+{
+ return S->key.keys;
+}
+
+int
+xcb_input_device_class_data_key_keys_length (const xcb_input_device_class_t *R,
+ const xcb_input_device_class_data_t *S)
+{
+ return S->key.num_keys;
+}
+
+xcb_generic_iterator_t
+xcb_input_device_class_data_key_keys_end (const xcb_input_device_class_t *R,
+ const xcb_input_device_class_data_t *S)
+{
+ xcb_generic_iterator_t i;
+ i.data = S->key.keys + S->key.num_keys;
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) S;
+ return i;
+}
+
+uint32_t *
+xcb_input_device_class_data_button_state (const xcb_input_device_class_data_t *S)
+{
+ return S->button.state;
+}
+
+int
+xcb_input_device_class_data_button_state_length (const xcb_input_device_class_t *R,
+ const xcb_input_device_class_data_t *S)
+{
+ return ((S->button.num_buttons + 31) / 32);
+}
+
+xcb_generic_iterator_t
+xcb_input_device_class_data_button_state_end (const xcb_input_device_class_t *R,
+ const xcb_input_device_class_data_t *S)
+{
+ xcb_generic_iterator_t i;
+ i.data = S->button.state + ((S->button.num_buttons + 31) / 32);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) S;
+ return i;
+}
+
+xcb_atom_t *
+xcb_input_device_class_data_button_labels (const xcb_input_device_class_data_t *S)
+{
+ return S->button.labels;
+}
+
+int
+xcb_input_device_class_data_button_labels_length (const xcb_input_device_class_t *R,
+ const xcb_input_device_class_data_t *S)
+{
+ return S->button.num_buttons;
+}
+
+xcb_generic_iterator_t
+xcb_input_device_class_data_button_labels_end (const xcb_input_device_class_t *R,
+ const xcb_input_device_class_data_t *S)
+{
+ xcb_generic_iterator_t i;
+ i.data = S->button.labels + S->button.num_buttons;
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) S;
+ return i;
+}
+
+int
+xcb_input_device_class_data_serialize (void **_buffer,
+ uint16_t type,
+ const xcb_input_device_class_data_t *_aux)
+{
+ char *xcb_out = *_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_align_to = 0;
+ unsigned int xcb_padding_offset = 2;
+
+ unsigned int xcb_pad = 0;
+ char xcb_pad0[3] = {0, 0, 0};
+ struct iovec xcb_parts[24];
+ unsigned int xcb_parts_idx = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int i;
+ char *xcb_tmp;
+
+ if(type == XCB_INPUT_DEVICE_CLASS_TYPE_KEY) {
+ /* xcb_input_device_class_data_t.key.num_keys */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->key.num_keys;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* keys */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->key.keys;
+ xcb_block_len += _aux->key.num_keys * sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = _aux->key.num_keys * sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ if(type == XCB_INPUT_DEVICE_CLASS_TYPE_BUTTON) {
+ /* xcb_input_device_class_data_t.button.num_buttons */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->button.num_buttons;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* state */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->button.state;
+ xcb_block_len += ((_aux->button.num_buttons + 31) / 32) * sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = ((_aux->button.num_buttons + 31) / 32) * sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* labels */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->button.labels;
+ xcb_block_len += _aux->button.num_buttons * sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = _aux->button.num_buttons * sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(xcb_atom_t);
+ }
+ if(type == XCB_INPUT_DEVICE_CLASS_TYPE_VALUATOR) {
+ /* xcb_input_device_class_data_t.valuator.number */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->valuator.number;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* xcb_input_device_class_data_t.valuator.label */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->valuator.label;
+ xcb_block_len += sizeof(xcb_atom_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(xcb_atom_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(xcb_atom_t);
+ /* xcb_input_device_class_data_t.valuator.min */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->valuator.min;
+ xcb_block_len += sizeof(xcb_input_fp3232_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(xcb_input_fp3232_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(xcb_input_fp3232_t);
+ /* xcb_input_device_class_data_t.valuator.max */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->valuator.max;
+ xcb_block_len += sizeof(xcb_input_fp3232_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(xcb_input_fp3232_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(xcb_input_fp3232_t);
+ /* xcb_input_device_class_data_t.valuator.value */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->valuator.value;
+ xcb_block_len += sizeof(xcb_input_fp3232_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(xcb_input_fp3232_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(xcb_input_fp3232_t);
+ /* xcb_input_device_class_data_t.valuator.resolution */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->valuator.resolution;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_class_data_t.valuator.mode */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->valuator.mode;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_device_class_data_t.valuator.pad0 */
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_block_len += sizeof(uint8_t)*3;
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t)*3;
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ }
+ if(type == XCB_INPUT_DEVICE_CLASS_TYPE_SCROLL) {
+ /* xcb_input_device_class_data_t.scroll.number */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->scroll.number;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* xcb_input_device_class_data_t.scroll.scroll_type */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->scroll.scroll_type;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* xcb_input_device_class_data_t.scroll.pad1 */
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_block_len += sizeof(uint8_t)*2;
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t)*2;
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_device_class_data_t.scroll.flags */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->scroll.flags;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_class_data_t.scroll.increment */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->scroll.increment;
+ xcb_block_len += sizeof(xcb_input_fp3232_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(xcb_input_fp3232_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(xcb_input_fp3232_t);
+ }
+ if(type == XCB_INPUT_DEVICE_CLASS_TYPE_TOUCH) {
+ /* xcb_input_device_class_data_t.touch.mode */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->touch.mode;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_device_class_data_t.touch.num_touches */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) &_aux->touch.num_touches;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ }
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+
+ if (NULL == xcb_out) {
+ /* allocate memory */
+ xcb_out = malloc(xcb_buffer_len);
+ *_buffer = xcb_out;
+ }
+
+ xcb_tmp = xcb_out;
+ for(i=0; i<xcb_parts_idx; i++) {
+ if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)
+ memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);
+ if (0 != xcb_parts[i].iov_len)
+ xcb_tmp += xcb_parts[i].iov_len;
+ }
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_device_class_data_unpack (const void *_buffer,
+ uint16_t type,
+ xcb_input_device_class_data_t *_aux)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+ unsigned int xcb_padding_offset = 2;
+
+
+ if(type == XCB_INPUT_DEVICE_CLASS_TYPE_KEY) {
+ /* xcb_input_device_class_data_t.key.num_keys */
+ _aux->key.num_keys = *(uint16_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_tmp += sizeof(uint16_t);
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* keys */
+ _aux->key.keys = (uint32_t *)xcb_tmp;
+ xcb_block_len += _aux->key.num_keys * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ if(type == XCB_INPUT_DEVICE_CLASS_TYPE_BUTTON) {
+ /* xcb_input_device_class_data_t.button.num_buttons */
+ _aux->button.num_buttons = *(uint16_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_tmp += sizeof(uint16_t);
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* state */
+ _aux->button.state = (uint32_t *)xcb_tmp;
+ xcb_block_len += ((_aux->button.num_buttons + 31) / 32) * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* labels */
+ _aux->button.labels = (xcb_atom_t *)xcb_tmp;
+ xcb_block_len += _aux->button.num_buttons * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_atom_t);
+ }
+ if(type == XCB_INPUT_DEVICE_CLASS_TYPE_VALUATOR) {
+ /* xcb_input_device_class_data_t.valuator.number */
+ _aux->valuator.number = *(uint16_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_tmp += sizeof(uint16_t);
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* xcb_input_device_class_data_t.valuator.label */
+ _aux->valuator.label = *(xcb_atom_t *)xcb_tmp;
+ xcb_block_len += sizeof(xcb_atom_t);
+ xcb_tmp += sizeof(xcb_atom_t);
+ xcb_align_to = ALIGNOF(xcb_atom_t);
+ /* xcb_input_device_class_data_t.valuator.min */
+ _aux->valuator.min = *(xcb_input_fp3232_t *)xcb_tmp;
+ xcb_block_len += sizeof(xcb_input_fp3232_t);
+ xcb_tmp += sizeof(xcb_input_fp3232_t);
+ xcb_align_to = ALIGNOF(xcb_input_fp3232_t);
+ /* xcb_input_device_class_data_t.valuator.max */
+ _aux->valuator.max = *(xcb_input_fp3232_t *)xcb_tmp;
+ xcb_block_len += sizeof(xcb_input_fp3232_t);
+ xcb_tmp += sizeof(xcb_input_fp3232_t);
+ xcb_align_to = ALIGNOF(xcb_input_fp3232_t);
+ /* xcb_input_device_class_data_t.valuator.value */
+ _aux->valuator.value = *(xcb_input_fp3232_t *)xcb_tmp;
+ xcb_block_len += sizeof(xcb_input_fp3232_t);
+ xcb_tmp += sizeof(xcb_input_fp3232_t);
+ xcb_align_to = ALIGNOF(xcb_input_fp3232_t);
+ /* xcb_input_device_class_data_t.valuator.resolution */
+ _aux->valuator.resolution = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_class_data_t.valuator.mode */
+ _aux->valuator.mode = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_device_class_data_t.valuator.pad0 */
+ _aux->valuator.pad0[0] = *(uint8_t *)xcb_tmp;
+ _aux->valuator.pad0[1] = *(uint8_t *)xcb_tmp;
+ _aux->valuator.pad0[2] = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t) * 3;
+ xcb_tmp += sizeof(uint8_t) * 3;
+ xcb_align_to = ALIGNOF(uint8_t);
+ }
+ if(type == XCB_INPUT_DEVICE_CLASS_TYPE_SCROLL) {
+ /* xcb_input_device_class_data_t.scroll.number */
+ _aux->scroll.number = *(uint16_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_tmp += sizeof(uint16_t);
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* xcb_input_device_class_data_t.scroll.scroll_type */
+ _aux->scroll.scroll_type = *(uint16_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint16_t);
+ xcb_tmp += sizeof(uint16_t);
+ xcb_align_to = ALIGNOF(uint16_t);
+ /* xcb_input_device_class_data_t.scroll.pad1 */
+ _aux->scroll.pad1[0] = *(uint8_t *)xcb_tmp;
+ _aux->scroll.pad1[1] = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t) * 2;
+ xcb_tmp += sizeof(uint8_t) * 2;
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_device_class_data_t.scroll.flags */
+ _aux->scroll.flags = *(uint32_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint32_t);
+ xcb_tmp += sizeof(uint32_t);
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* xcb_input_device_class_data_t.scroll.increment */
+ _aux->scroll.increment = *(xcb_input_fp3232_t *)xcb_tmp;
+ xcb_block_len += sizeof(xcb_input_fp3232_t);
+ xcb_tmp += sizeof(xcb_input_fp3232_t);
+ xcb_align_to = ALIGNOF(xcb_input_fp3232_t);
+ }
+ if(type == XCB_INPUT_DEVICE_CLASS_TYPE_TOUCH) {
+ /* xcb_input_device_class_data_t.touch.mode */
+ _aux->touch.mode = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ /* xcb_input_device_class_data_t.touch.num_touches */
+ _aux->touch.num_touches = *(uint8_t *)xcb_tmp;
+ xcb_block_len += sizeof(uint8_t);
+ xcb_tmp += sizeof(uint8_t);
+ xcb_align_to = ALIGNOF(uint8_t);
+ }
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_device_class_data_sizeof (const void *_buffer,
+ uint16_t type)
+{
+ xcb_input_device_class_data_t _aux;
+ return xcb_input_device_class_data_unpack(_buffer, type, &_aux);
+}
+
+int
+xcb_input_device_class_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_device_class_t *_aux = (xcb_input_device_class_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_device_class_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* data */
+ xcb_block_len += xcb_input_device_class_data_sizeof(xcb_tmp, _aux->type);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+void *
+xcb_input_device_class_data (const xcb_input_device_class_t *R)
+{
+ return (void *) (R + 1);
+}
+
+void
+xcb_input_device_class_next (xcb_input_device_class_iterator_t *i)
+{
+ xcb_input_device_class_t *R = i->data;
+ xcb_generic_iterator_t child;
+ child.data = (xcb_input_device_class_t *)(((char *)R) + xcb_input_device_class_sizeof(R));
+ i->index = (char *) child.data - (char *) i->data;
+ --i->rem;
+ i->data = (xcb_input_device_class_t *) child.data;
+}
+
+xcb_generic_iterator_t
+xcb_input_device_class_end (xcb_input_device_class_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ while(i.rem > 0)
+ xcb_input_device_class_next(&i);
+ ret.data = i.data;
+ ret.rem = i.rem;
+ ret.index = i.index;
+ return ret;
+}
+
+int
+xcb_input_xi_device_info_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_xi_device_info_t *_aux = (xcb_input_xi_device_info_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+ unsigned int i;
+ unsigned int xcb_tmp_len;
+
+ xcb_block_len += sizeof(xcb_input_xi_device_info_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* name */
+ xcb_block_len += _aux->name_len * sizeof(char);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ xcb_align_to = 4;
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* classes */
+ for(i=0; i<_aux->num_classes; i++) {
+ xcb_tmp_len = xcb_input_device_class_sizeof(xcb_tmp);
+ xcb_block_len += xcb_tmp_len;
+ xcb_tmp += xcb_tmp_len;
+ }
+ xcb_align_to = ALIGNOF(xcb_input_device_class_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+char *
+xcb_input_xi_device_info_name (const xcb_input_xi_device_info_t *R)
+{
+ return (char *) (R + 1);
+}
+
+int
+xcb_input_xi_device_info_name_length (const xcb_input_xi_device_info_t *R)
+{
+ return R->name_len;
+}
+
+xcb_generic_iterator_t
+xcb_input_xi_device_info_name_end (const xcb_input_xi_device_info_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((char *) (R + 1)) + (R->name_len);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+int
+xcb_input_xi_device_info_classes_length (const xcb_input_xi_device_info_t *R)
+{
+ return R->num_classes;
+}
+
+xcb_input_device_class_iterator_t
+xcb_input_xi_device_info_classes_iterator (const xcb_input_xi_device_info_t *R)
+{
+ xcb_input_device_class_iterator_t i;
+ xcb_generic_iterator_t prev = xcb_input_xi_device_info_name_end(R);
+ i.data = (xcb_input_device_class_t *) ((char *) prev.data + ((-prev.index) & (4 - 1)));
+ i.rem = R->num_classes;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+void
+xcb_input_xi_device_info_next (xcb_input_xi_device_info_iterator_t *i)
+{
+ xcb_input_xi_device_info_t *R = i->data;
+ xcb_generic_iterator_t child;
+ child.data = (xcb_input_xi_device_info_t *)(((char *)R) + xcb_input_xi_device_info_sizeof(R));
+ i->index = (char *) child.data - (char *) i->data;
+ --i->rem;
+ i->data = (xcb_input_xi_device_info_t *) child.data;
+}
+
+xcb_generic_iterator_t
+xcb_input_xi_device_info_end (xcb_input_xi_device_info_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ while(i.rem > 0)
+ xcb_input_xi_device_info_next(&i);
+ ret.data = i.data;
+ ret.rem = i.rem;
+ ret.index = i.index;
+ return ret;
+}
+
+int
+xcb_input_xi_query_device_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_xi_query_device_reply_t *_aux = (xcb_input_xi_query_device_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+ unsigned int i;
+ unsigned int xcb_tmp_len;
+
+ xcb_block_len += sizeof(xcb_input_xi_query_device_reply_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* infos */
+ for(i=0; i<_aux->num_infos; i++) {
+ xcb_tmp_len = xcb_input_xi_device_info_sizeof(xcb_tmp);
+ xcb_block_len += xcb_tmp_len;
+ xcb_tmp += xcb_tmp_len;
+ }
+ xcb_align_to = ALIGNOF(xcb_input_xi_device_info_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_xi_query_device_cookie_t
+xcb_input_xi_query_device (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_QUERY_DEVICE,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_xi_query_device_cookie_t xcb_ret;
+ xcb_input_xi_query_device_request_t xcb_out;
+
+ xcb_out.deviceid = deviceid;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_xi_query_device_cookie_t
+xcb_input_xi_query_device_unchecked (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_QUERY_DEVICE,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_xi_query_device_cookie_t xcb_ret;
+ xcb_input_xi_query_device_request_t xcb_out;
+
+ xcb_out.deviceid = deviceid;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+int
+xcb_input_xi_query_device_infos_length (const xcb_input_xi_query_device_reply_t *R)
+{
+ return R->num_infos;
+}
+
+xcb_input_xi_device_info_iterator_t
+xcb_input_xi_query_device_infos_iterator (const xcb_input_xi_query_device_reply_t *R)
+{
+ xcb_input_xi_device_info_iterator_t i;
+ i.data = (xcb_input_xi_device_info_t *) (R + 1);
+ i.rem = R->num_infos;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_xi_query_device_reply_t *
+xcb_input_xi_query_device_reply (xcb_connection_t *c,
+ xcb_input_xi_query_device_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_xi_query_device_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+xcb_void_cookie_t
+xcb_input_xi_set_focus_checked (xcb_connection_t *c,
+ xcb_window_t window,
+ xcb_timestamp_t time,
+ xcb_input_device_id_t deviceid)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_SET_FOCUS,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_xi_set_focus_request_t xcb_out;
+
+ xcb_out.window = window;
+ xcb_out.time = time;
+ xcb_out.deviceid = deviceid;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_xi_set_focus (xcb_connection_t *c,
+ xcb_window_t window,
+ xcb_timestamp_t time,
+ xcb_input_device_id_t deviceid)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_SET_FOCUS,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_xi_set_focus_request_t xcb_out;
+
+ xcb_out.window = window;
+ xcb_out.time = time;
+ xcb_out.deviceid = deviceid;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_xi_get_focus_cookie_t
+xcb_input_xi_get_focus (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_GET_FOCUS,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_xi_get_focus_cookie_t xcb_ret;
+ xcb_input_xi_get_focus_request_t xcb_out;
+
+ xcb_out.deviceid = deviceid;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_xi_get_focus_cookie_t
+xcb_input_xi_get_focus_unchecked (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_GET_FOCUS,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_xi_get_focus_cookie_t xcb_ret;
+ xcb_input_xi_get_focus_request_t xcb_out;
+
+ xcb_out.deviceid = deviceid;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_xi_get_focus_reply_t *
+xcb_input_xi_get_focus_reply (xcb_connection_t *c,
+ xcb_input_xi_get_focus_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_xi_get_focus_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+int
+xcb_input_xi_grab_device_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_xi_grab_device_request_t *_aux = (xcb_input_xi_grab_device_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_xi_grab_device_request_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* mask */
+ xcb_block_len += _aux->mask_len * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_xi_grab_device_cookie_t
+xcb_input_xi_grab_device (xcb_connection_t *c,
+ xcb_window_t window,
+ xcb_timestamp_t time,
+ xcb_cursor_t cursor,
+ xcb_input_device_id_t deviceid,
+ uint8_t mode,
+ uint8_t paired_device_mode,
+ uint8_t owner_events,
+ uint16_t mask_len,
+ const uint32_t *mask)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_GRAB_DEVICE,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_input_xi_grab_device_cookie_t xcb_ret;
+ xcb_input_xi_grab_device_request_t xcb_out;
+
+ xcb_out.window = window;
+ xcb_out.time = time;
+ xcb_out.cursor = cursor;
+ xcb_out.deviceid = deviceid;
+ xcb_out.mode = mode;
+ xcb_out.paired_device_mode = paired_device_mode;
+ xcb_out.owner_events = owner_events;
+ xcb_out.pad0 = 0;
+ xcb_out.mask_len = mask_len;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint32_t mask */
+ xcb_parts[4].iov_base = (char *) mask;
+ xcb_parts[4].iov_len = mask_len * sizeof(uint32_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_xi_grab_device_cookie_t
+xcb_input_xi_grab_device_unchecked (xcb_connection_t *c,
+ xcb_window_t window,
+ xcb_timestamp_t time,
+ xcb_cursor_t cursor,
+ xcb_input_device_id_t deviceid,
+ uint8_t mode,
+ uint8_t paired_device_mode,
+ uint8_t owner_events,
+ uint16_t mask_len,
+ const uint32_t *mask)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_GRAB_DEVICE,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_input_xi_grab_device_cookie_t xcb_ret;
+ xcb_input_xi_grab_device_request_t xcb_out;
+
+ xcb_out.window = window;
+ xcb_out.time = time;
+ xcb_out.cursor = cursor;
+ xcb_out.deviceid = deviceid;
+ xcb_out.mode = mode;
+ xcb_out.paired_device_mode = paired_device_mode;
+ xcb_out.owner_events = owner_events;
+ xcb_out.pad0 = 0;
+ xcb_out.mask_len = mask_len;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint32_t mask */
+ xcb_parts[4].iov_base = (char *) mask;
+ xcb_parts[4].iov_len = mask_len * sizeof(uint32_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_xi_grab_device_reply_t *
+xcb_input_xi_grab_device_reply (xcb_connection_t *c,
+ xcb_input_xi_grab_device_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_xi_grab_device_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+xcb_void_cookie_t
+xcb_input_xi_ungrab_device_checked (xcb_connection_t *c,
+ xcb_timestamp_t time,
+ xcb_input_device_id_t deviceid)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_UNGRAB_DEVICE,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_xi_ungrab_device_request_t xcb_out;
+
+ xcb_out.time = time;
+ xcb_out.deviceid = deviceid;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_xi_ungrab_device (xcb_connection_t *c,
+ xcb_timestamp_t time,
+ xcb_input_device_id_t deviceid)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_UNGRAB_DEVICE,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_xi_ungrab_device_request_t xcb_out;
+
+ xcb_out.time = time;
+ xcb_out.deviceid = deviceid;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_xi_allow_events_checked (xcb_connection_t *c,
+ xcb_timestamp_t time,
+ xcb_input_device_id_t deviceid,
+ uint8_t event_mode,
+ uint32_t touchid,
+ xcb_window_t grab_window)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_ALLOW_EVENTS,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_xi_allow_events_request_t xcb_out;
+
+ xcb_out.time = time;
+ xcb_out.deviceid = deviceid;
+ xcb_out.event_mode = event_mode;
+ xcb_out.pad0 = 0;
+ xcb_out.touchid = touchid;
+ xcb_out.grab_window = grab_window;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_xi_allow_events (xcb_connection_t *c,
+ xcb_timestamp_t time,
+ xcb_input_device_id_t deviceid,
+ uint8_t event_mode,
+ uint32_t touchid,
+ xcb_window_t grab_window)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_ALLOW_EVENTS,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_xi_allow_events_request_t xcb_out;
+
+ xcb_out.time = time;
+ xcb_out.deviceid = deviceid;
+ xcb_out.event_mode = event_mode;
+ xcb_out.pad0 = 0;
+ xcb_out.touchid = touchid;
+ xcb_out.grab_window = grab_window;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+void
+xcb_input_grab_modifier_info_next (xcb_input_grab_modifier_info_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_grab_modifier_info_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_grab_modifier_info_end (xcb_input_grab_modifier_info_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+int
+xcb_input_xi_passive_grab_device_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_xi_passive_grab_device_request_t *_aux = (xcb_input_xi_passive_grab_device_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_xi_passive_grab_device_request_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* mask */
+ xcb_block_len += _aux->mask_len * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* modifiers */
+ xcb_block_len += _aux->num_modifiers * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_xi_passive_grab_device_cookie_t
+xcb_input_xi_passive_grab_device (xcb_connection_t *c,
+ xcb_timestamp_t time,
+ xcb_window_t grab_window,
+ xcb_cursor_t cursor,
+ uint32_t detail,
+ xcb_input_device_id_t deviceid,
+ uint16_t num_modifiers,
+ uint16_t mask_len,
+ uint8_t grab_type,
+ uint8_t grab_mode,
+ uint8_t paired_device_mode,
+ uint8_t owner_events,
+ const uint32_t *mask,
+ const uint32_t *modifiers)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 6,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_PASSIVE_GRAB_DEVICE,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[8];
+ xcb_input_xi_passive_grab_device_cookie_t xcb_ret;
+ xcb_input_xi_passive_grab_device_request_t xcb_out;
+
+ xcb_out.time = time;
+ xcb_out.grab_window = grab_window;
+ xcb_out.cursor = cursor;
+ xcb_out.detail = detail;
+ xcb_out.deviceid = deviceid;
+ xcb_out.num_modifiers = num_modifiers;
+ xcb_out.mask_len = mask_len;
+ xcb_out.grab_type = grab_type;
+ xcb_out.grab_mode = grab_mode;
+ xcb_out.paired_device_mode = paired_device_mode;
+ xcb_out.owner_events = owner_events;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint32_t mask */
+ xcb_parts[4].iov_base = (char *) mask;
+ xcb_parts[4].iov_len = mask_len * sizeof(uint32_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+ /* uint32_t modifiers */
+ xcb_parts[6].iov_base = (char *) modifiers;
+ xcb_parts[6].iov_len = num_modifiers * sizeof(uint32_t);
+ xcb_parts[7].iov_base = 0;
+ xcb_parts[7].iov_len = -xcb_parts[6].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_xi_passive_grab_device_cookie_t
+xcb_input_xi_passive_grab_device_unchecked (xcb_connection_t *c,
+ xcb_timestamp_t time,
+ xcb_window_t grab_window,
+ xcb_cursor_t cursor,
+ uint32_t detail,
+ xcb_input_device_id_t deviceid,
+ uint16_t num_modifiers,
+ uint16_t mask_len,
+ uint8_t grab_type,
+ uint8_t grab_mode,
+ uint8_t paired_device_mode,
+ uint8_t owner_events,
+ const uint32_t *mask,
+ const uint32_t *modifiers)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 6,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_PASSIVE_GRAB_DEVICE,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[8];
+ xcb_input_xi_passive_grab_device_cookie_t xcb_ret;
+ xcb_input_xi_passive_grab_device_request_t xcb_out;
+
+ xcb_out.time = time;
+ xcb_out.grab_window = grab_window;
+ xcb_out.cursor = cursor;
+ xcb_out.detail = detail;
+ xcb_out.deviceid = deviceid;
+ xcb_out.num_modifiers = num_modifiers;
+ xcb_out.mask_len = mask_len;
+ xcb_out.grab_type = grab_type;
+ xcb_out.grab_mode = grab_mode;
+ xcb_out.paired_device_mode = paired_device_mode;
+ xcb_out.owner_events = owner_events;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint32_t mask */
+ xcb_parts[4].iov_base = (char *) mask;
+ xcb_parts[4].iov_len = mask_len * sizeof(uint32_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+ /* uint32_t modifiers */
+ xcb_parts[6].iov_base = (char *) modifiers;
+ xcb_parts[6].iov_len = num_modifiers * sizeof(uint32_t);
+ xcb_parts[7].iov_base = 0;
+ xcb_parts[7].iov_len = -xcb_parts[6].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_grab_modifier_info_t *
+xcb_input_xi_passive_grab_device_modifiers (const xcb_input_xi_passive_grab_device_reply_t *R)
+{
+ return (xcb_input_grab_modifier_info_t *) (R + 1);
+}
+
+int
+xcb_input_xi_passive_grab_device_modifiers_length (const xcb_input_xi_passive_grab_device_reply_t *R)
+{
+ return R->num_modifiers;
+}
+
+xcb_input_grab_modifier_info_iterator_t
+xcb_input_xi_passive_grab_device_modifiers_iterator (const xcb_input_xi_passive_grab_device_reply_t *R)
+{
+ xcb_input_grab_modifier_info_iterator_t i;
+ i.data = (xcb_input_grab_modifier_info_t *) (R + 1);
+ i.rem = R->num_modifiers;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_xi_passive_grab_device_reply_t *
+xcb_input_xi_passive_grab_device_reply (xcb_connection_t *c,
+ xcb_input_xi_passive_grab_device_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_xi_passive_grab_device_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+int
+xcb_input_xi_passive_ungrab_device_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_xi_passive_ungrab_device_request_t *_aux = (xcb_input_xi_passive_ungrab_device_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_xi_passive_ungrab_device_request_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* modifiers */
+ xcb_block_len += _aux->num_modifiers * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_void_cookie_t
+xcb_input_xi_passive_ungrab_device_checked (xcb_connection_t *c,
+ xcb_window_t grab_window,
+ uint32_t detail,
+ xcb_input_device_id_t deviceid,
+ uint16_t num_modifiers,
+ uint8_t grab_type,
+ const uint32_t *modifiers)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_PASSIVE_UNGRAB_DEVICE,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_xi_passive_ungrab_device_request_t xcb_out;
+
+ xcb_out.grab_window = grab_window;
+ xcb_out.detail = detail;
+ xcb_out.deviceid = deviceid;
+ xcb_out.num_modifiers = num_modifiers;
+ xcb_out.grab_type = grab_type;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint32_t modifiers */
+ xcb_parts[4].iov_base = (char *) modifiers;
+ xcb_parts[4].iov_len = num_modifiers * sizeof(uint32_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_xi_passive_ungrab_device (xcb_connection_t *c,
+ xcb_window_t grab_window,
+ uint32_t detail,
+ xcb_input_device_id_t deviceid,
+ uint16_t num_modifiers,
+ uint8_t grab_type,
+ const uint32_t *modifiers)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 4,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_PASSIVE_UNGRAB_DEVICE,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[6];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_xi_passive_ungrab_device_request_t xcb_out;
+
+ xcb_out.grab_window = grab_window;
+ xcb_out.detail = detail;
+ xcb_out.deviceid = deviceid;
+ xcb_out.num_modifiers = num_modifiers;
+ xcb_out.grab_type = grab_type;
+ memset(xcb_out.pad0, 0, 3);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* uint32_t modifiers */
+ xcb_parts[4].iov_base = (char *) modifiers;
+ xcb_parts[4].iov_len = num_modifiers * sizeof(uint32_t);
+ xcb_parts[5].iov_base = 0;
+ xcb_parts[5].iov_len = -xcb_parts[4].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+uint32_t *
+xcb_input_xi_passive_ungrab_device_modifiers (const xcb_input_xi_passive_ungrab_device_request_t *R)
+{
+ return (uint32_t *) (R + 1);
+}
+
+int
+xcb_input_xi_passive_ungrab_device_modifiers_length (const xcb_input_xi_passive_ungrab_device_request_t *R)
+{
+ return R->num_modifiers;
+}
+
+xcb_generic_iterator_t
+xcb_input_xi_passive_ungrab_device_modifiers_end (const xcb_input_xi_passive_ungrab_device_request_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((uint32_t *) (R + 1)) + (R->num_modifiers);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+int
+xcb_input_xi_list_properties_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_xi_list_properties_reply_t *_aux = (xcb_input_xi_list_properties_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_xi_list_properties_reply_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* properties */
+ xcb_block_len += _aux->num_properties * sizeof(xcb_atom_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_atom_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_xi_list_properties_cookie_t
+xcb_input_xi_list_properties (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_LIST_PROPERTIES,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_xi_list_properties_cookie_t xcb_ret;
+ xcb_input_xi_list_properties_request_t xcb_out;
+
+ xcb_out.deviceid = deviceid;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_xi_list_properties_cookie_t
+xcb_input_xi_list_properties_unchecked (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_LIST_PROPERTIES,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_xi_list_properties_cookie_t xcb_ret;
+ xcb_input_xi_list_properties_request_t xcb_out;
+
+ xcb_out.deviceid = deviceid;
+ memset(xcb_out.pad0, 0, 2);
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_atom_t *
+xcb_input_xi_list_properties_properties (const xcb_input_xi_list_properties_reply_t *R)
+{
+ return (xcb_atom_t *) (R + 1);
+}
+
+int
+xcb_input_xi_list_properties_properties_length (const xcb_input_xi_list_properties_reply_t *R)
+{
+ return R->num_properties;
+}
+
+xcb_generic_iterator_t
+xcb_input_xi_list_properties_properties_end (const xcb_input_xi_list_properties_reply_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((xcb_atom_t *) (R + 1)) + (R->num_properties);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_xi_list_properties_reply_t *
+xcb_input_xi_list_properties_reply (xcb_connection_t *c,
+ xcb_input_xi_list_properties_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_xi_list_properties_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+uint8_t *
+xcb_input_xi_change_property_items_data_8 (const xcb_input_xi_change_property_items_t *S)
+{
+ return S->data8;
+}
+
+int
+xcb_input_xi_change_property_items_data_8_length (const xcb_input_xi_change_property_request_t *R,
+ const xcb_input_xi_change_property_items_t *S)
+{
+ return R->num_items;
+}
+
+xcb_generic_iterator_t
+xcb_input_xi_change_property_items_data_8_end (const xcb_input_xi_change_property_request_t *R,
+ const xcb_input_xi_change_property_items_t *S)
+{
+ xcb_generic_iterator_t i;
+ i.data = S->data8 + R->num_items;
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) S;
+ return i;
+}
+
+uint16_t *
+xcb_input_xi_change_property_items_data_16 (const xcb_input_xi_change_property_items_t *S)
+{
+ return S->data16;
+}
+
+int
+xcb_input_xi_change_property_items_data_16_length (const xcb_input_xi_change_property_request_t *R,
+ const xcb_input_xi_change_property_items_t *S)
+{
+ return R->num_items;
+}
+
+xcb_generic_iterator_t
+xcb_input_xi_change_property_items_data_16_end (const xcb_input_xi_change_property_request_t *R,
+ const xcb_input_xi_change_property_items_t *S)
+{
+ xcb_generic_iterator_t i;
+ i.data = S->data16 + R->num_items;
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) S;
+ return i;
+}
+
+uint32_t *
+xcb_input_xi_change_property_items_data_32 (const xcb_input_xi_change_property_items_t *S)
+{
+ return S->data32;
+}
+
+int
+xcb_input_xi_change_property_items_data_32_length (const xcb_input_xi_change_property_request_t *R,
+ const xcb_input_xi_change_property_items_t *S)
+{
+ return R->num_items;
+}
+
+xcb_generic_iterator_t
+xcb_input_xi_change_property_items_data_32_end (const xcb_input_xi_change_property_request_t *R,
+ const xcb_input_xi_change_property_items_t *S)
+{
+ xcb_generic_iterator_t i;
+ i.data = S->data32 + R->num_items;
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) S;
+ return i;
+}
+
+int
+xcb_input_xi_change_property_items_serialize (void **_buffer,
+ uint32_t num_items,
+ uint8_t format,
+ const xcb_input_xi_change_property_items_t *_aux)
+{
+ char *xcb_out = *_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_align_to = 0;
+ unsigned int xcb_padding_offset = 0;
+
+ unsigned int xcb_pad = 0;
+ char xcb_pad0[3] = {0, 0, 0};
+ struct iovec xcb_parts[9];
+ unsigned int xcb_parts_idx = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int i;
+ char *xcb_tmp;
+
+ if(format == XCB_INPUT_PROPERTY_FORMAT_8_BITS) {
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* data8 */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->data8;
+ xcb_block_len += num_items * sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = num_items * sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ xcb_align_to = 4;
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ }
+ if(format == XCB_INPUT_PROPERTY_FORMAT_16_BITS) {
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* data16 */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->data16;
+ xcb_block_len += num_items * sizeof(uint16_t);
+ xcb_parts[xcb_parts_idx].iov_len = num_items * sizeof(uint16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint16_t);
+ xcb_align_to = 4;
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ }
+ if(format == XCB_INPUT_PROPERTY_FORMAT_32_BITS) {
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* data32 */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->data32;
+ xcb_block_len += num_items * sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = num_items * sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+
+ if (NULL == xcb_out) {
+ /* allocate memory */
+ xcb_out = malloc(xcb_buffer_len);
+ *_buffer = xcb_out;
+ }
+
+ xcb_tmp = xcb_out;
+ for(i=0; i<xcb_parts_idx; i++) {
+ if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)
+ memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);
+ if (0 != xcb_parts[i].iov_len)
+ xcb_tmp += xcb_parts[i].iov_len;
+ }
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_xi_change_property_items_unpack (const void *_buffer,
+ uint32_t num_items,
+ uint8_t format,
+ xcb_input_xi_change_property_items_t *_aux)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+ unsigned int xcb_padding_offset = 0;
+
+
+ if(format == XCB_INPUT_PROPERTY_FORMAT_8_BITS) {
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* data8 */
+ _aux->data8 = (uint8_t *)xcb_tmp;
+ xcb_block_len += num_items * sizeof(uint8_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint8_t);
+ xcb_align_to = 4;
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ }
+ if(format == XCB_INPUT_PROPERTY_FORMAT_16_BITS) {
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* data16 */
+ _aux->data16 = (uint16_t *)xcb_tmp;
+ xcb_block_len += num_items * sizeof(uint16_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint16_t);
+ xcb_align_to = 4;
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ }
+ if(format == XCB_INPUT_PROPERTY_FORMAT_32_BITS) {
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* data32 */
+ _aux->data32 = (uint32_t *)xcb_tmp;
+ xcb_block_len += num_items * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_xi_change_property_items_sizeof (const void *_buffer,
+ uint32_t num_items,
+ uint8_t format)
+{
+ xcb_input_xi_change_property_items_t _aux;
+ return xcb_input_xi_change_property_items_unpack(_buffer, num_items, format, &_aux);
+}
+
+int
+xcb_input_xi_change_property_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_xi_change_property_request_t *_aux = (xcb_input_xi_change_property_request_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_xi_change_property_request_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* items */
+ xcb_block_len += xcb_input_xi_change_property_items_sizeof(xcb_tmp, _aux->num_items, _aux->format);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_void_cookie_t
+xcb_input_xi_change_property_checked (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid,
+ uint8_t mode,
+ uint8_t format,
+ xcb_atom_t property,
+ xcb_atom_t type,
+ uint32_t num_items,
+ const void *items)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 3,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_CHANGE_PROPERTY,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[5];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_xi_change_property_request_t xcb_out;
+
+ xcb_out.deviceid = deviceid;
+ xcb_out.mode = mode;
+ xcb_out.format = format;
+ xcb_out.property = property;
+ xcb_out.type = type;
+ xcb_out.num_items = num_items;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_xi_change_property_items_t items */
+ xcb_parts[4].iov_base = (char *) items;
+ xcb_parts[4].iov_len =
+ xcb_input_xi_change_property_items_sizeof (items, num_items, format);
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_xi_change_property (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid,
+ uint8_t mode,
+ uint8_t format,
+ xcb_atom_t property,
+ xcb_atom_t type,
+ uint32_t num_items,
+ const void *items)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 3,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_CHANGE_PROPERTY,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[5];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_xi_change_property_request_t xcb_out;
+
+ xcb_out.deviceid = deviceid;
+ xcb_out.mode = mode;
+ xcb_out.format = format;
+ xcb_out.property = property;
+ xcb_out.type = type;
+ xcb_out.num_items = num_items;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_xi_change_property_items_t items */
+ xcb_parts[4].iov_base = (char *) items;
+ xcb_parts[4].iov_len =
+ xcb_input_xi_change_property_items_sizeof (items, num_items, format);
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_xi_change_property_aux_checked (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid,
+ uint8_t mode,
+ uint8_t format,
+ xcb_atom_t property,
+ xcb_atom_t type,
+ uint32_t num_items,
+ const xcb_input_xi_change_property_items_t *items)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 3,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_CHANGE_PROPERTY,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[5];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_xi_change_property_request_t xcb_out;
+ void *xcb_aux0 = 0;
+
+ xcb_out.deviceid = deviceid;
+ xcb_out.mode = mode;
+ xcb_out.format = format;
+ xcb_out.property = property;
+ xcb_out.type = type;
+ xcb_out.num_items = num_items;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_xi_change_property_items_t items */
+ xcb_parts[4].iov_len =
+ xcb_input_xi_change_property_items_serialize (&xcb_aux0, num_items, format, items);
+ xcb_parts[4].iov_base = xcb_aux0;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ free(xcb_aux0);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_xi_change_property_aux (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid,
+ uint8_t mode,
+ uint8_t format,
+ xcb_atom_t property,
+ xcb_atom_t type,
+ uint32_t num_items,
+ const xcb_input_xi_change_property_items_t *items)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 3,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_CHANGE_PROPERTY,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[5];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_xi_change_property_request_t xcb_out;
+ void *xcb_aux0 = 0;
+
+ xcb_out.deviceid = deviceid;
+ xcb_out.mode = mode;
+ xcb_out.format = format;
+ xcb_out.property = property;
+ xcb_out.type = type;
+ xcb_out.num_items = num_items;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+ /* xcb_input_xi_change_property_items_t items */
+ xcb_parts[4].iov_len =
+ xcb_input_xi_change_property_items_serialize (&xcb_aux0, num_items, format, items);
+ xcb_parts[4].iov_base = xcb_aux0;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ free(xcb_aux0);
+ return xcb_ret;
+}
+
+void *
+xcb_input_xi_change_property_items (const xcb_input_xi_change_property_request_t *R)
+{
+ return (void *) (R + 1);
+}
+
+xcb_void_cookie_t
+xcb_input_xi_delete_property_checked (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid,
+ xcb_atom_t property)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_DELETE_PROPERTY,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_xi_delete_property_request_t xcb_out;
+
+ xcb_out.deviceid = deviceid;
+ memset(xcb_out.pad0, 0, 2);
+ xcb_out.property = property;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_void_cookie_t
+xcb_input_xi_delete_property (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid,
+ xcb_atom_t property)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_DELETE_PROPERTY,
+ .isvoid = 1
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_void_cookie_t xcb_ret;
+ xcb_input_xi_delete_property_request_t xcb_out;
+
+ xcb_out.deviceid = deviceid;
+ memset(xcb_out.pad0, 0, 2);
+ xcb_out.property = property;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+uint8_t *
+xcb_input_xi_get_property_items_data_8 (const xcb_input_xi_get_property_items_t *S)
+{
+ return S->data8;
+}
+
+int
+xcb_input_xi_get_property_items_data_8_length (const xcb_input_xi_get_property_reply_t *R,
+ const xcb_input_xi_get_property_items_t *S)
+{
+ return R->num_items;
+}
+
+xcb_generic_iterator_t
+xcb_input_xi_get_property_items_data_8_end (const xcb_input_xi_get_property_reply_t *R,
+ const xcb_input_xi_get_property_items_t *S)
+{
+ xcb_generic_iterator_t i;
+ i.data = S->data8 + R->num_items;
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) S;
+ return i;
+}
+
+uint16_t *
+xcb_input_xi_get_property_items_data_16 (const xcb_input_xi_get_property_items_t *S)
+{
+ return S->data16;
+}
+
+int
+xcb_input_xi_get_property_items_data_16_length (const xcb_input_xi_get_property_reply_t *R,
+ const xcb_input_xi_get_property_items_t *S)
+{
+ return R->num_items;
+}
+
+xcb_generic_iterator_t
+xcb_input_xi_get_property_items_data_16_end (const xcb_input_xi_get_property_reply_t *R,
+ const xcb_input_xi_get_property_items_t *S)
+{
+ xcb_generic_iterator_t i;
+ i.data = S->data16 + R->num_items;
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) S;
+ return i;
+}
+
+uint32_t *
+xcb_input_xi_get_property_items_data_32 (const xcb_input_xi_get_property_items_t *S)
+{
+ return S->data32;
+}
+
+int
+xcb_input_xi_get_property_items_data_32_length (const xcb_input_xi_get_property_reply_t *R,
+ const xcb_input_xi_get_property_items_t *S)
+{
+ return R->num_items;
+}
+
+xcb_generic_iterator_t
+xcb_input_xi_get_property_items_data_32_end (const xcb_input_xi_get_property_reply_t *R,
+ const xcb_input_xi_get_property_items_t *S)
+{
+ xcb_generic_iterator_t i;
+ i.data = S->data32 + R->num_items;
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) S;
+ return i;
+}
+
+int
+xcb_input_xi_get_property_items_serialize (void **_buffer,
+ uint32_t num_items,
+ uint8_t format,
+ const xcb_input_xi_get_property_items_t *_aux)
+{
+ char *xcb_out = *_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_align_to = 0;
+ unsigned int xcb_padding_offset = 0;
+
+ unsigned int xcb_pad = 0;
+ char xcb_pad0[3] = {0, 0, 0};
+ struct iovec xcb_parts[9];
+ unsigned int xcb_parts_idx = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int i;
+ char *xcb_tmp;
+
+ if(format == XCB_INPUT_PROPERTY_FORMAT_8_BITS) {
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* data8 */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->data8;
+ xcb_block_len += num_items * sizeof(uint8_t);
+ xcb_parts[xcb_parts_idx].iov_len = num_items * sizeof(uint8_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint8_t);
+ xcb_align_to = 4;
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ }
+ if(format == XCB_INPUT_PROPERTY_FORMAT_16_BITS) {
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* data16 */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->data16;
+ xcb_block_len += num_items * sizeof(uint16_t);
+ xcb_parts[xcb_parts_idx].iov_len = num_items * sizeof(uint16_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint16_t);
+ xcb_align_to = 4;
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ }
+ if(format == XCB_INPUT_PROPERTY_FORMAT_32_BITS) {
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* data32 */
+ xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->data32;
+ xcb_block_len += num_items * sizeof(uint32_t);
+ xcb_parts[xcb_parts_idx].iov_len = num_items * sizeof(uint32_t);
+ xcb_parts_idx++;
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;
+ xcb_parts[xcb_parts_idx].iov_len = xcb_pad;
+ xcb_parts_idx++;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+
+ if (NULL == xcb_out) {
+ /* allocate memory */
+ xcb_out = malloc(xcb_buffer_len);
+ *_buffer = xcb_out;
+ }
+
+ xcb_tmp = xcb_out;
+ for(i=0; i<xcb_parts_idx; i++) {
+ if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)
+ memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);
+ if (0 != xcb_parts[i].iov_len)
+ xcb_tmp += xcb_parts[i].iov_len;
+ }
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_xi_get_property_items_unpack (const void *_buffer,
+ uint32_t num_items,
+ uint8_t format,
+ xcb_input_xi_get_property_items_t *_aux)
+{
+ char *xcb_tmp = (char *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+ unsigned int xcb_padding_offset = 0;
+
+
+ if(format == XCB_INPUT_PROPERTY_FORMAT_8_BITS) {
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* data8 */
+ _aux->data8 = (uint8_t *)xcb_tmp;
+ xcb_block_len += num_items * sizeof(uint8_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint8_t);
+ xcb_align_to = 4;
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ }
+ if(format == XCB_INPUT_PROPERTY_FORMAT_16_BITS) {
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* data16 */
+ _aux->data16 = (uint16_t *)xcb_tmp;
+ xcb_block_len += num_items * sizeof(uint16_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint16_t);
+ xcb_align_to = 4;
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ }
+ if(format == XCB_INPUT_PROPERTY_FORMAT_32_BITS) {
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+ /* data32 */
+ _aux->data32 = (uint32_t *)xcb_tmp;
+ xcb_block_len += num_items * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ }
+ /* insert padding */
+ xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ xcb_padding_offset = 0;
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_xi_get_property_items_sizeof (const void *_buffer,
+ uint32_t num_items,
+ uint8_t format)
+{
+ xcb_input_xi_get_property_items_t _aux;
+ return xcb_input_xi_get_property_items_unpack(_buffer, num_items, format, &_aux);
+}
+
+int
+xcb_input_xi_get_property_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_xi_get_property_reply_t *_aux = (xcb_input_xi_get_property_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_xi_get_property_reply_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* items */
+ xcb_block_len += xcb_input_xi_get_property_items_sizeof(xcb_tmp, _aux->num_items, _aux->format);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(char);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_xi_get_property_cookie_t
+xcb_input_xi_get_property (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid,
+ uint8_t _delete,
+ xcb_atom_t property,
+ xcb_atom_t type,
+ uint32_t offset,
+ uint32_t len)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_GET_PROPERTY,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_xi_get_property_cookie_t xcb_ret;
+ xcb_input_xi_get_property_request_t xcb_out;
+
+ xcb_out.deviceid = deviceid;
+ xcb_out._delete = _delete;
+ xcb_out.pad0 = 0;
+ xcb_out.property = property;
+ xcb_out.type = type;
+ xcb_out.offset = offset;
+ xcb_out.len = len;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_xi_get_property_cookie_t
+xcb_input_xi_get_property_unchecked (xcb_connection_t *c,
+ xcb_input_device_id_t deviceid,
+ uint8_t _delete,
+ xcb_atom_t property,
+ xcb_atom_t type,
+ uint32_t offset,
+ uint32_t len)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_GET_PROPERTY,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_xi_get_property_cookie_t xcb_ret;
+ xcb_input_xi_get_property_request_t xcb_out;
+
+ xcb_out.deviceid = deviceid;
+ xcb_out._delete = _delete;
+ xcb_out.pad0 = 0;
+ xcb_out.property = property;
+ xcb_out.type = type;
+ xcb_out.offset = offset;
+ xcb_out.len = len;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+void *
+xcb_input_xi_get_property_items (const xcb_input_xi_get_property_reply_t *R)
+{
+ return (void *) (R + 1);
+}
+
+xcb_input_xi_get_property_reply_t *
+xcb_input_xi_get_property_reply (xcb_connection_t *c,
+ xcb_input_xi_get_property_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_xi_get_property_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+int
+xcb_input_xi_get_selected_events_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_xi_get_selected_events_reply_t *_aux = (xcb_input_xi_get_selected_events_reply_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+ unsigned int i;
+ unsigned int xcb_tmp_len;
+
+ xcb_block_len += sizeof(xcb_input_xi_get_selected_events_reply_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* masks */
+ for(i=0; i<_aux->num_masks; i++) {
+ xcb_tmp_len = xcb_input_event_mask_sizeof(xcb_tmp);
+ xcb_block_len += xcb_tmp_len;
+ xcb_tmp += xcb_tmp_len;
+ }
+ xcb_align_to = ALIGNOF(xcb_input_event_mask_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_xi_get_selected_events_cookie_t
+xcb_input_xi_get_selected_events (xcb_connection_t *c,
+ xcb_window_t window)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_GET_SELECTED_EVENTS,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_xi_get_selected_events_cookie_t xcb_ret;
+ xcb_input_xi_get_selected_events_request_t xcb_out;
+
+ xcb_out.window = window;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, XCB_REQUEST_CHECKED, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+xcb_input_xi_get_selected_events_cookie_t
+xcb_input_xi_get_selected_events_unchecked (xcb_connection_t *c,
+ xcb_window_t window)
+{
+ static const xcb_protocol_request_t xcb_req = {
+ .count = 2,
+ .ext = &xcb_input_id,
+ .opcode = XCB_INPUT_XI_GET_SELECTED_EVENTS,
+ .isvoid = 0
+ };
+
+ struct iovec xcb_parts[4];
+ xcb_input_xi_get_selected_events_cookie_t xcb_ret;
+ xcb_input_xi_get_selected_events_request_t xcb_out;
+
+ xcb_out.window = window;
+
+ xcb_parts[2].iov_base = (char *) &xcb_out;
+ xcb_parts[2].iov_len = sizeof(xcb_out);
+ xcb_parts[3].iov_base = 0;
+ xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;
+
+ xcb_ret.sequence = xcb_send_request(c, 0, xcb_parts + 2, &xcb_req);
+ return xcb_ret;
+}
+
+int
+xcb_input_xi_get_selected_events_masks_length (const xcb_input_xi_get_selected_events_reply_t *R)
+{
+ return R->num_masks;
+}
+
+xcb_input_event_mask_iterator_t
+xcb_input_xi_get_selected_events_masks_iterator (const xcb_input_xi_get_selected_events_reply_t *R)
+{
+ xcb_input_event_mask_iterator_t i;
+ i.data = (xcb_input_event_mask_t *) (R + 1);
+ i.rem = R->num_masks;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_xi_get_selected_events_reply_t *
+xcb_input_xi_get_selected_events_reply (xcb_connection_t *c,
+ xcb_input_xi_get_selected_events_cookie_t cookie /**< */,
+ xcb_generic_error_t **e)
+{
+ return (xcb_input_xi_get_selected_events_reply_t *) xcb_wait_for_reply(c, cookie.sequence, e);
+}
+
+int
+xcb_input_device_changed_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_device_changed_event_t *_aux = (xcb_input_device_changed_event_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+ unsigned int i;
+ unsigned int xcb_tmp_len;
+
+ xcb_block_len += sizeof(xcb_input_device_changed_event_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* classes */
+ for(i=0; i<_aux->num_classes; i++) {
+ xcb_tmp_len = xcb_input_device_class_sizeof(xcb_tmp);
+ xcb_block_len += xcb_tmp_len;
+ xcb_tmp += xcb_tmp_len;
+ }
+ xcb_align_to = ALIGNOF(xcb_input_device_class_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+int
+xcb_input_device_changed_classes_length (const xcb_input_device_changed_event_t *R)
+{
+ return R->num_classes;
+}
+
+xcb_input_device_class_iterator_t
+xcb_input_device_changed_classes_iterator (const xcb_input_device_changed_event_t *R)
+{
+ xcb_input_device_class_iterator_t i;
+ i.data = (xcb_input_device_class_t *) (R + 1);
+ i.rem = R->num_classes;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+int
+xcb_input_key_press_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_key_press_event_t *_aux = (xcb_input_key_press_event_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+ int xcb_pre_tmp_1; /* sumof length */
+ int xcb_pre_tmp_2; /* sumof loop counter */
+ int64_t xcb_pre_tmp_3; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_4; /* sumof list ptr */
+
+ xcb_block_len += sizeof(xcb_input_key_press_event_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* button_mask */
+ xcb_block_len += _aux->buttons_len * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* valuator_mask */
+ xcb_block_len += _aux->valuators_len * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* axisvalues */
+ /* sumof start */
+ xcb_pre_tmp_1 = _aux->valuators_len;
+ xcb_pre_tmp_3 = 0;
+ xcb_pre_tmp_4 = xcb_input_key_press_valuator_mask(_aux);
+ for (xcb_pre_tmp_2 = 0; xcb_pre_tmp_2 < xcb_pre_tmp_1; xcb_pre_tmp_2++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_4;
+ xcb_pre_tmp_3 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_4++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_3 */
+ xcb_block_len += xcb_pre_tmp_3 * sizeof(xcb_input_fp3232_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_fp3232_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+uint32_t *
+xcb_input_key_press_button_mask (const xcb_input_key_press_event_t *R)
+{
+ return (uint32_t *) (R + 1);
+}
+
+int
+xcb_input_key_press_button_mask_length (const xcb_input_key_press_event_t *R)
+{
+ return R->buttons_len;
+}
+
+xcb_generic_iterator_t
+xcb_input_key_press_button_mask_end (const xcb_input_key_press_event_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((uint32_t *) (R + 1)) + (R->buttons_len);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+uint32_t *
+xcb_input_key_press_valuator_mask (const xcb_input_key_press_event_t *R)
+{
+ xcb_generic_iterator_t prev = xcb_input_key_press_button_mask_end(R);
+ return (uint32_t *) ((char *) prev.data + XCB_TYPE_PAD(uint32_t, prev.index) + 0);
+}
+
+int
+xcb_input_key_press_valuator_mask_length (const xcb_input_key_press_event_t *R)
+{
+ return R->valuators_len;
+}
+
+xcb_generic_iterator_t
+xcb_input_key_press_valuator_mask_end (const xcb_input_key_press_event_t *R)
+{
+ xcb_generic_iterator_t i;
+ xcb_generic_iterator_t prev = xcb_input_key_press_button_mask_end(R);
+ i.data = ((uint32_t *) ((char*) prev.data + XCB_TYPE_PAD(uint32_t, prev.index))) + (R->valuators_len);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_fp3232_t *
+xcb_input_key_press_axisvalues (const xcb_input_key_press_event_t *R)
+{
+ xcb_generic_iterator_t prev = xcb_input_key_press_valuator_mask_end(R);
+ return (xcb_input_fp3232_t *) ((char *) prev.data + XCB_TYPE_PAD(xcb_input_fp3232_t, prev.index) + 0);
+}
+
+int
+xcb_input_key_press_axisvalues_length (const xcb_input_key_press_event_t *R)
+{
+ int xcb_pre_tmp_5; /* sumof length */
+ int xcb_pre_tmp_6; /* sumof loop counter */
+ int64_t xcb_pre_tmp_7; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_8; /* sumof list ptr */
+ /* sumof start */
+ xcb_pre_tmp_5 = R->valuators_len;
+ xcb_pre_tmp_7 = 0;
+ xcb_pre_tmp_8 = xcb_input_key_press_valuator_mask(R);
+ for (xcb_pre_tmp_6 = 0; xcb_pre_tmp_6 < xcb_pre_tmp_5; xcb_pre_tmp_6++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_8;
+ xcb_pre_tmp_7 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_8++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_7 */
+ return xcb_pre_tmp_7;
+}
+
+xcb_input_fp3232_iterator_t
+xcb_input_key_press_axisvalues_iterator (const xcb_input_key_press_event_t *R)
+{
+ xcb_input_fp3232_iterator_t i;
+ xcb_generic_iterator_t prev = xcb_input_key_press_valuator_mask_end(R);
+ int xcb_pre_tmp_9; /* sumof length */
+ int xcb_pre_tmp_10; /* sumof loop counter */
+ int64_t xcb_pre_tmp_11; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_12; /* sumof list ptr */
+ /* sumof start */
+ xcb_pre_tmp_9 = R->valuators_len;
+ xcb_pre_tmp_11 = 0;
+ xcb_pre_tmp_12 = xcb_input_key_press_valuator_mask(R);
+ for (xcb_pre_tmp_10 = 0; xcb_pre_tmp_10 < xcb_pre_tmp_9; xcb_pre_tmp_10++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_12;
+ xcb_pre_tmp_11 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_12++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_11 */
+ i.data = (xcb_input_fp3232_t *) ((char *) prev.data + XCB_TYPE_PAD(xcb_input_fp3232_t, prev.index));
+ i.rem = xcb_pre_tmp_11;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+int
+xcb_input_key_release_sizeof (const void *_buffer /**< */)
+{
+ return xcb_input_key_press_sizeof(_buffer);
+}
+
+int
+xcb_input_button_press_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_button_press_event_t *_aux = (xcb_input_button_press_event_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+ int xcb_pre_tmp_1; /* sumof length */
+ int xcb_pre_tmp_2; /* sumof loop counter */
+ int64_t xcb_pre_tmp_3; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_4; /* sumof list ptr */
+
+ xcb_block_len += sizeof(xcb_input_button_press_event_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* button_mask */
+ xcb_block_len += _aux->buttons_len * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* valuator_mask */
+ xcb_block_len += _aux->valuators_len * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* axisvalues */
+ /* sumof start */
+ xcb_pre_tmp_1 = _aux->valuators_len;
+ xcb_pre_tmp_3 = 0;
+ xcb_pre_tmp_4 = xcb_input_button_press_valuator_mask(_aux);
+ for (xcb_pre_tmp_2 = 0; xcb_pre_tmp_2 < xcb_pre_tmp_1; xcb_pre_tmp_2++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_4;
+ xcb_pre_tmp_3 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_4++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_3 */
+ xcb_block_len += xcb_pre_tmp_3 * sizeof(xcb_input_fp3232_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_fp3232_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+uint32_t *
+xcb_input_button_press_button_mask (const xcb_input_button_press_event_t *R)
+{
+ return (uint32_t *) (R + 1);
+}
+
+int
+xcb_input_button_press_button_mask_length (const xcb_input_button_press_event_t *R)
+{
+ return R->buttons_len;
+}
+
+xcb_generic_iterator_t
+xcb_input_button_press_button_mask_end (const xcb_input_button_press_event_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((uint32_t *) (R + 1)) + (R->buttons_len);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+uint32_t *
+xcb_input_button_press_valuator_mask (const xcb_input_button_press_event_t *R)
+{
+ xcb_generic_iterator_t prev = xcb_input_button_press_button_mask_end(R);
+ return (uint32_t *) ((char *) prev.data + XCB_TYPE_PAD(uint32_t, prev.index) + 0);
+}
+
+int
+xcb_input_button_press_valuator_mask_length (const xcb_input_button_press_event_t *R)
+{
+ return R->valuators_len;
+}
+
+xcb_generic_iterator_t
+xcb_input_button_press_valuator_mask_end (const xcb_input_button_press_event_t *R)
+{
+ xcb_generic_iterator_t i;
+ xcb_generic_iterator_t prev = xcb_input_button_press_button_mask_end(R);
+ i.data = ((uint32_t *) ((char*) prev.data + XCB_TYPE_PAD(uint32_t, prev.index))) + (R->valuators_len);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_fp3232_t *
+xcb_input_button_press_axisvalues (const xcb_input_button_press_event_t *R)
+{
+ xcb_generic_iterator_t prev = xcb_input_button_press_valuator_mask_end(R);
+ return (xcb_input_fp3232_t *) ((char *) prev.data + XCB_TYPE_PAD(xcb_input_fp3232_t, prev.index) + 0);
+}
+
+int
+xcb_input_button_press_axisvalues_length (const xcb_input_button_press_event_t *R)
+{
+ int xcb_pre_tmp_5; /* sumof length */
+ int xcb_pre_tmp_6; /* sumof loop counter */
+ int64_t xcb_pre_tmp_7; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_8; /* sumof list ptr */
+ /* sumof start */
+ xcb_pre_tmp_5 = R->valuators_len;
+ xcb_pre_tmp_7 = 0;
+ xcb_pre_tmp_8 = xcb_input_button_press_valuator_mask(R);
+ for (xcb_pre_tmp_6 = 0; xcb_pre_tmp_6 < xcb_pre_tmp_5; xcb_pre_tmp_6++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_8;
+ xcb_pre_tmp_7 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_8++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_7 */
+ return xcb_pre_tmp_7;
+}
+
+xcb_input_fp3232_iterator_t
+xcb_input_button_press_axisvalues_iterator (const xcb_input_button_press_event_t *R)
+{
+ xcb_input_fp3232_iterator_t i;
+ xcb_generic_iterator_t prev = xcb_input_button_press_valuator_mask_end(R);
+ int xcb_pre_tmp_9; /* sumof length */
+ int xcb_pre_tmp_10; /* sumof loop counter */
+ int64_t xcb_pre_tmp_11; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_12; /* sumof list ptr */
+ /* sumof start */
+ xcb_pre_tmp_9 = R->valuators_len;
+ xcb_pre_tmp_11 = 0;
+ xcb_pre_tmp_12 = xcb_input_button_press_valuator_mask(R);
+ for (xcb_pre_tmp_10 = 0; xcb_pre_tmp_10 < xcb_pre_tmp_9; xcb_pre_tmp_10++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_12;
+ xcb_pre_tmp_11 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_12++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_11 */
+ i.data = (xcb_input_fp3232_t *) ((char *) prev.data + XCB_TYPE_PAD(xcb_input_fp3232_t, prev.index));
+ i.rem = xcb_pre_tmp_11;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+int
+xcb_input_button_release_sizeof (const void *_buffer /**< */)
+{
+ return xcb_input_button_press_sizeof(_buffer);
+}
+
+int
+xcb_input_motion_sizeof (const void *_buffer /**< */)
+{
+ return xcb_input_button_press_sizeof(_buffer);
+}
+
+int
+xcb_input_enter_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_enter_event_t *_aux = (xcb_input_enter_event_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_enter_event_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* buttons */
+ xcb_block_len += _aux->buttons_len * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+uint32_t *
+xcb_input_enter_buttons (const xcb_input_enter_event_t *R)
+{
+ return (uint32_t *) (R + 1);
+}
+
+int
+xcb_input_enter_buttons_length (const xcb_input_enter_event_t *R)
+{
+ return R->buttons_len;
+}
+
+xcb_generic_iterator_t
+xcb_input_enter_buttons_end (const xcb_input_enter_event_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((uint32_t *) (R + 1)) + (R->buttons_len);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+int
+xcb_input_leave_sizeof (const void *_buffer /**< */)
+{
+ return xcb_input_enter_sizeof(_buffer);
+}
+
+int
+xcb_input_focus_in_sizeof (const void *_buffer /**< */)
+{
+ return xcb_input_enter_sizeof(_buffer);
+}
+
+int
+xcb_input_focus_out_sizeof (const void *_buffer /**< */)
+{
+ return xcb_input_enter_sizeof(_buffer);
+}
+
+void
+xcb_input_hierarchy_info_next (xcb_input_hierarchy_info_iterator_t *i)
+{
+ --i->rem;
+ ++i->data;
+ i->index += sizeof(xcb_input_hierarchy_info_t);
+}
+
+xcb_generic_iterator_t
+xcb_input_hierarchy_info_end (xcb_input_hierarchy_info_iterator_t i)
+{
+ xcb_generic_iterator_t ret;
+ ret.data = i.data + i.rem;
+ ret.index = i.index + ((char *) ret.data - (char *) i.data);
+ ret.rem = 0;
+ return ret;
+}
+
+int
+xcb_input_hierarchy_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_hierarchy_event_t *_aux = (xcb_input_hierarchy_event_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+
+ xcb_block_len += sizeof(xcb_input_hierarchy_event_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* infos */
+ xcb_block_len += _aux->num_infos * sizeof(xcb_input_hierarchy_info_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_hierarchy_info_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+xcb_input_hierarchy_info_t *
+xcb_input_hierarchy_infos (const xcb_input_hierarchy_event_t *R)
+{
+ return (xcb_input_hierarchy_info_t *) (R + 1);
+}
+
+int
+xcb_input_hierarchy_infos_length (const xcb_input_hierarchy_event_t *R)
+{
+ return R->num_infos;
+}
+
+xcb_input_hierarchy_info_iterator_t
+xcb_input_hierarchy_infos_iterator (const xcb_input_hierarchy_event_t *R)
+{
+ xcb_input_hierarchy_info_iterator_t i;
+ i.data = (xcb_input_hierarchy_info_t *) (R + 1);
+ i.rem = R->num_infos;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+int
+xcb_input_raw_key_press_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_raw_key_press_event_t *_aux = (xcb_input_raw_key_press_event_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+ int xcb_pre_tmp_1; /* sumof length */
+ int xcb_pre_tmp_2; /* sumof loop counter */
+ int64_t xcb_pre_tmp_3; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_4; /* sumof list ptr */
+ int xcb_pre_tmp_5; /* sumof length */
+ int xcb_pre_tmp_6; /* sumof loop counter */
+ int64_t xcb_pre_tmp_7; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_8; /* sumof list ptr */
+
+ xcb_block_len += sizeof(xcb_input_raw_key_press_event_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* valuator_mask */
+ xcb_block_len += _aux->valuators_len * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* axisvalues */
+ /* sumof start */
+ xcb_pre_tmp_1 = _aux->valuators_len;
+ xcb_pre_tmp_3 = 0;
+ xcb_pre_tmp_4 = xcb_input_raw_key_press_valuator_mask(_aux);
+ for (xcb_pre_tmp_2 = 0; xcb_pre_tmp_2 < xcb_pre_tmp_1; xcb_pre_tmp_2++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_4;
+ xcb_pre_tmp_3 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_4++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_3 */
+ xcb_block_len += xcb_pre_tmp_3 * sizeof(xcb_input_fp3232_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_fp3232_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* axisvalues_raw */
+ /* sumof start */
+ xcb_pre_tmp_5 = _aux->valuators_len;
+ xcb_pre_tmp_7 = 0;
+ xcb_pre_tmp_8 = xcb_input_raw_key_press_valuator_mask(_aux);
+ for (xcb_pre_tmp_6 = 0; xcb_pre_tmp_6 < xcb_pre_tmp_5; xcb_pre_tmp_6++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_8;
+ xcb_pre_tmp_7 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_8++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_7 */
+ xcb_block_len += xcb_pre_tmp_7 * sizeof(xcb_input_fp3232_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_fp3232_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+uint32_t *
+xcb_input_raw_key_press_valuator_mask (const xcb_input_raw_key_press_event_t *R)
+{
+ return (uint32_t *) (R + 1);
+}
+
+int
+xcb_input_raw_key_press_valuator_mask_length (const xcb_input_raw_key_press_event_t *R)
+{
+ return R->valuators_len;
+}
+
+xcb_generic_iterator_t
+xcb_input_raw_key_press_valuator_mask_end (const xcb_input_raw_key_press_event_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((uint32_t *) (R + 1)) + (R->valuators_len);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_fp3232_t *
+xcb_input_raw_key_press_axisvalues (const xcb_input_raw_key_press_event_t *R)
+{
+ xcb_generic_iterator_t prev = xcb_input_raw_key_press_valuator_mask_end(R);
+ return (xcb_input_fp3232_t *) ((char *) prev.data + XCB_TYPE_PAD(xcb_input_fp3232_t, prev.index) + 0);
+}
+
+int
+xcb_input_raw_key_press_axisvalues_length (const xcb_input_raw_key_press_event_t *R)
+{
+ int xcb_pre_tmp_9; /* sumof length */
+ int xcb_pre_tmp_10; /* sumof loop counter */
+ int64_t xcb_pre_tmp_11; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_12; /* sumof list ptr */
+ /* sumof start */
+ xcb_pre_tmp_9 = R->valuators_len;
+ xcb_pre_tmp_11 = 0;
+ xcb_pre_tmp_12 = xcb_input_raw_key_press_valuator_mask(R);
+ for (xcb_pre_tmp_10 = 0; xcb_pre_tmp_10 < xcb_pre_tmp_9; xcb_pre_tmp_10++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_12;
+ xcb_pre_tmp_11 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_12++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_11 */
+ return xcb_pre_tmp_11;
+}
+
+xcb_input_fp3232_iterator_t
+xcb_input_raw_key_press_axisvalues_iterator (const xcb_input_raw_key_press_event_t *R)
+{
+ xcb_input_fp3232_iterator_t i;
+ xcb_generic_iterator_t prev = xcb_input_raw_key_press_valuator_mask_end(R);
+ int xcb_pre_tmp_13; /* sumof length */
+ int xcb_pre_tmp_14; /* sumof loop counter */
+ int64_t xcb_pre_tmp_15; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_16; /* sumof list ptr */
+ /* sumof start */
+ xcb_pre_tmp_13 = R->valuators_len;
+ xcb_pre_tmp_15 = 0;
+ xcb_pre_tmp_16 = xcb_input_raw_key_press_valuator_mask(R);
+ for (xcb_pre_tmp_14 = 0; xcb_pre_tmp_14 < xcb_pre_tmp_13; xcb_pre_tmp_14++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_16;
+ xcb_pre_tmp_15 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_16++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_15 */
+ i.data = (xcb_input_fp3232_t *) ((char *) prev.data + XCB_TYPE_PAD(xcb_input_fp3232_t, prev.index));
+ i.rem = xcb_pre_tmp_15;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_fp3232_t *
+xcb_input_raw_key_press_axisvalues_raw (const xcb_input_raw_key_press_event_t *R)
+{
+ xcb_generic_iterator_t prev = xcb_input_fp3232_end(xcb_input_raw_key_press_axisvalues_iterator(R));
+ return (xcb_input_fp3232_t *) ((char *) prev.data + XCB_TYPE_PAD(xcb_input_fp3232_t, prev.index) + 0);
+}
+
+int
+xcb_input_raw_key_press_axisvalues_raw_length (const xcb_input_raw_key_press_event_t *R)
+{
+ int xcb_pre_tmp_17; /* sumof length */
+ int xcb_pre_tmp_18; /* sumof loop counter */
+ int64_t xcb_pre_tmp_19; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_20; /* sumof list ptr */
+ /* sumof start */
+ xcb_pre_tmp_17 = R->valuators_len;
+ xcb_pre_tmp_19 = 0;
+ xcb_pre_tmp_20 = xcb_input_raw_key_press_valuator_mask(R);
+ for (xcb_pre_tmp_18 = 0; xcb_pre_tmp_18 < xcb_pre_tmp_17; xcb_pre_tmp_18++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_20;
+ xcb_pre_tmp_19 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_20++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_19 */
+ return xcb_pre_tmp_19;
+}
+
+xcb_input_fp3232_iterator_t
+xcb_input_raw_key_press_axisvalues_raw_iterator (const xcb_input_raw_key_press_event_t *R)
+{
+ xcb_input_fp3232_iterator_t i;
+ xcb_generic_iterator_t prev = xcb_input_fp3232_end(xcb_input_raw_key_press_axisvalues_iterator(R));
+ int xcb_pre_tmp_21; /* sumof length */
+ int xcb_pre_tmp_22; /* sumof loop counter */
+ int64_t xcb_pre_tmp_23; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_24; /* sumof list ptr */
+ /* sumof start */
+ xcb_pre_tmp_21 = R->valuators_len;
+ xcb_pre_tmp_23 = 0;
+ xcb_pre_tmp_24 = xcb_input_raw_key_press_valuator_mask(R);
+ for (xcb_pre_tmp_22 = 0; xcb_pre_tmp_22 < xcb_pre_tmp_21; xcb_pre_tmp_22++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_24;
+ xcb_pre_tmp_23 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_24++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_23 */
+ i.data = (xcb_input_fp3232_t *) ((char *) prev.data + XCB_TYPE_PAD(xcb_input_fp3232_t, prev.index));
+ i.rem = xcb_pre_tmp_23;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+int
+xcb_input_raw_key_release_sizeof (const void *_buffer /**< */)
+{
+ return xcb_input_raw_key_press_sizeof(_buffer);
+}
+
+int
+xcb_input_raw_button_press_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_raw_button_press_event_t *_aux = (xcb_input_raw_button_press_event_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+ int xcb_pre_tmp_1; /* sumof length */
+ int xcb_pre_tmp_2; /* sumof loop counter */
+ int64_t xcb_pre_tmp_3; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_4; /* sumof list ptr */
+ int xcb_pre_tmp_5; /* sumof length */
+ int xcb_pre_tmp_6; /* sumof loop counter */
+ int64_t xcb_pre_tmp_7; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_8; /* sumof list ptr */
+
+ xcb_block_len += sizeof(xcb_input_raw_button_press_event_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* valuator_mask */
+ xcb_block_len += _aux->valuators_len * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* axisvalues */
+ /* sumof start */
+ xcb_pre_tmp_1 = _aux->valuators_len;
+ xcb_pre_tmp_3 = 0;
+ xcb_pre_tmp_4 = xcb_input_raw_button_press_valuator_mask(_aux);
+ for (xcb_pre_tmp_2 = 0; xcb_pre_tmp_2 < xcb_pre_tmp_1; xcb_pre_tmp_2++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_4;
+ xcb_pre_tmp_3 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_4++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_3 */
+ xcb_block_len += xcb_pre_tmp_3 * sizeof(xcb_input_fp3232_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_fp3232_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* axisvalues_raw */
+ /* sumof start */
+ xcb_pre_tmp_5 = _aux->valuators_len;
+ xcb_pre_tmp_7 = 0;
+ xcb_pre_tmp_8 = xcb_input_raw_button_press_valuator_mask(_aux);
+ for (xcb_pre_tmp_6 = 0; xcb_pre_tmp_6 < xcb_pre_tmp_5; xcb_pre_tmp_6++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_8;
+ xcb_pre_tmp_7 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_8++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_7 */
+ xcb_block_len += xcb_pre_tmp_7 * sizeof(xcb_input_fp3232_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_fp3232_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+uint32_t *
+xcb_input_raw_button_press_valuator_mask (const xcb_input_raw_button_press_event_t *R)
+{
+ return (uint32_t *) (R + 1);
+}
+
+int
+xcb_input_raw_button_press_valuator_mask_length (const xcb_input_raw_button_press_event_t *R)
+{
+ return R->valuators_len;
+}
+
+xcb_generic_iterator_t
+xcb_input_raw_button_press_valuator_mask_end (const xcb_input_raw_button_press_event_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((uint32_t *) (R + 1)) + (R->valuators_len);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_fp3232_t *
+xcb_input_raw_button_press_axisvalues (const xcb_input_raw_button_press_event_t *R)
+{
+ xcb_generic_iterator_t prev = xcb_input_raw_button_press_valuator_mask_end(R);
+ return (xcb_input_fp3232_t *) ((char *) prev.data + XCB_TYPE_PAD(xcb_input_fp3232_t, prev.index) + 0);
+}
+
+int
+xcb_input_raw_button_press_axisvalues_length (const xcb_input_raw_button_press_event_t *R)
+{
+ int xcb_pre_tmp_9; /* sumof length */
+ int xcb_pre_tmp_10; /* sumof loop counter */
+ int64_t xcb_pre_tmp_11; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_12; /* sumof list ptr */
+ /* sumof start */
+ xcb_pre_tmp_9 = R->valuators_len;
+ xcb_pre_tmp_11 = 0;
+ xcb_pre_tmp_12 = xcb_input_raw_button_press_valuator_mask(R);
+ for (xcb_pre_tmp_10 = 0; xcb_pre_tmp_10 < xcb_pre_tmp_9; xcb_pre_tmp_10++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_12;
+ xcb_pre_tmp_11 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_12++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_11 */
+ return xcb_pre_tmp_11;
+}
+
+xcb_input_fp3232_iterator_t
+xcb_input_raw_button_press_axisvalues_iterator (const xcb_input_raw_button_press_event_t *R)
+{
+ xcb_input_fp3232_iterator_t i;
+ xcb_generic_iterator_t prev = xcb_input_raw_button_press_valuator_mask_end(R);
+ int xcb_pre_tmp_13; /* sumof length */
+ int xcb_pre_tmp_14; /* sumof loop counter */
+ int64_t xcb_pre_tmp_15; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_16; /* sumof list ptr */
+ /* sumof start */
+ xcb_pre_tmp_13 = R->valuators_len;
+ xcb_pre_tmp_15 = 0;
+ xcb_pre_tmp_16 = xcb_input_raw_button_press_valuator_mask(R);
+ for (xcb_pre_tmp_14 = 0; xcb_pre_tmp_14 < xcb_pre_tmp_13; xcb_pre_tmp_14++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_16;
+ xcb_pre_tmp_15 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_16++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_15 */
+ i.data = (xcb_input_fp3232_t *) ((char *) prev.data + XCB_TYPE_PAD(xcb_input_fp3232_t, prev.index));
+ i.rem = xcb_pre_tmp_15;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_fp3232_t *
+xcb_input_raw_button_press_axisvalues_raw (const xcb_input_raw_button_press_event_t *R)
+{
+ xcb_generic_iterator_t prev = xcb_input_fp3232_end(xcb_input_raw_button_press_axisvalues_iterator(R));
+ return (xcb_input_fp3232_t *) ((char *) prev.data + XCB_TYPE_PAD(xcb_input_fp3232_t, prev.index) + 0);
+}
+
+int
+xcb_input_raw_button_press_axisvalues_raw_length (const xcb_input_raw_button_press_event_t *R)
+{
+ int xcb_pre_tmp_17; /* sumof length */
+ int xcb_pre_tmp_18; /* sumof loop counter */
+ int64_t xcb_pre_tmp_19; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_20; /* sumof list ptr */
+ /* sumof start */
+ xcb_pre_tmp_17 = R->valuators_len;
+ xcb_pre_tmp_19 = 0;
+ xcb_pre_tmp_20 = xcb_input_raw_button_press_valuator_mask(R);
+ for (xcb_pre_tmp_18 = 0; xcb_pre_tmp_18 < xcb_pre_tmp_17; xcb_pre_tmp_18++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_20;
+ xcb_pre_tmp_19 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_20++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_19 */
+ return xcb_pre_tmp_19;
+}
+
+xcb_input_fp3232_iterator_t
+xcb_input_raw_button_press_axisvalues_raw_iterator (const xcb_input_raw_button_press_event_t *R)
+{
+ xcb_input_fp3232_iterator_t i;
+ xcb_generic_iterator_t prev = xcb_input_fp3232_end(xcb_input_raw_button_press_axisvalues_iterator(R));
+ int xcb_pre_tmp_21; /* sumof length */
+ int xcb_pre_tmp_22; /* sumof loop counter */
+ int64_t xcb_pre_tmp_23; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_24; /* sumof list ptr */
+ /* sumof start */
+ xcb_pre_tmp_21 = R->valuators_len;
+ xcb_pre_tmp_23 = 0;
+ xcb_pre_tmp_24 = xcb_input_raw_button_press_valuator_mask(R);
+ for (xcb_pre_tmp_22 = 0; xcb_pre_tmp_22 < xcb_pre_tmp_21; xcb_pre_tmp_22++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_24;
+ xcb_pre_tmp_23 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_24++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_23 */
+ i.data = (xcb_input_fp3232_t *) ((char *) prev.data + XCB_TYPE_PAD(xcb_input_fp3232_t, prev.index));
+ i.rem = xcb_pre_tmp_23;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+int
+xcb_input_raw_button_release_sizeof (const void *_buffer /**< */)
+{
+ return xcb_input_raw_button_press_sizeof(_buffer);
+}
+
+int
+xcb_input_raw_motion_sizeof (const void *_buffer /**< */)
+{
+ return xcb_input_raw_button_press_sizeof(_buffer);
+}
+
+int
+xcb_input_touch_begin_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_touch_begin_event_t *_aux = (xcb_input_touch_begin_event_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+ int xcb_pre_tmp_1; /* sumof length */
+ int xcb_pre_tmp_2; /* sumof loop counter */
+ int64_t xcb_pre_tmp_3; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_4; /* sumof list ptr */
+
+ xcb_block_len += sizeof(xcb_input_touch_begin_event_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* button_mask */
+ xcb_block_len += _aux->buttons_len * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* valuator_mask */
+ xcb_block_len += _aux->valuators_len * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* axisvalues */
+ /* sumof start */
+ xcb_pre_tmp_1 = _aux->valuators_len;
+ xcb_pre_tmp_3 = 0;
+ xcb_pre_tmp_4 = xcb_input_touch_begin_valuator_mask(_aux);
+ for (xcb_pre_tmp_2 = 0; xcb_pre_tmp_2 < xcb_pre_tmp_1; xcb_pre_tmp_2++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_4;
+ xcb_pre_tmp_3 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_4++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_3 */
+ xcb_block_len += xcb_pre_tmp_3 * sizeof(xcb_input_fp3232_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_fp3232_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+uint32_t *
+xcb_input_touch_begin_button_mask (const xcb_input_touch_begin_event_t *R)
+{
+ return (uint32_t *) (R + 1);
+}
+
+int
+xcb_input_touch_begin_button_mask_length (const xcb_input_touch_begin_event_t *R)
+{
+ return R->buttons_len;
+}
+
+xcb_generic_iterator_t
+xcb_input_touch_begin_button_mask_end (const xcb_input_touch_begin_event_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((uint32_t *) (R + 1)) + (R->buttons_len);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+uint32_t *
+xcb_input_touch_begin_valuator_mask (const xcb_input_touch_begin_event_t *R)
+{
+ xcb_generic_iterator_t prev = xcb_input_touch_begin_button_mask_end(R);
+ return (uint32_t *) ((char *) prev.data + XCB_TYPE_PAD(uint32_t, prev.index) + 0);
+}
+
+int
+xcb_input_touch_begin_valuator_mask_length (const xcb_input_touch_begin_event_t *R)
+{
+ return R->valuators_len;
+}
+
+xcb_generic_iterator_t
+xcb_input_touch_begin_valuator_mask_end (const xcb_input_touch_begin_event_t *R)
+{
+ xcb_generic_iterator_t i;
+ xcb_generic_iterator_t prev = xcb_input_touch_begin_button_mask_end(R);
+ i.data = ((uint32_t *) ((char*) prev.data + XCB_TYPE_PAD(uint32_t, prev.index))) + (R->valuators_len);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_fp3232_t *
+xcb_input_touch_begin_axisvalues (const xcb_input_touch_begin_event_t *R)
+{
+ xcb_generic_iterator_t prev = xcb_input_touch_begin_valuator_mask_end(R);
+ return (xcb_input_fp3232_t *) ((char *) prev.data + XCB_TYPE_PAD(xcb_input_fp3232_t, prev.index) + 0);
+}
+
+int
+xcb_input_touch_begin_axisvalues_length (const xcb_input_touch_begin_event_t *R)
+{
+ int xcb_pre_tmp_5; /* sumof length */
+ int xcb_pre_tmp_6; /* sumof loop counter */
+ int64_t xcb_pre_tmp_7; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_8; /* sumof list ptr */
+ /* sumof start */
+ xcb_pre_tmp_5 = R->valuators_len;
+ xcb_pre_tmp_7 = 0;
+ xcb_pre_tmp_8 = xcb_input_touch_begin_valuator_mask(R);
+ for (xcb_pre_tmp_6 = 0; xcb_pre_tmp_6 < xcb_pre_tmp_5; xcb_pre_tmp_6++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_8;
+ xcb_pre_tmp_7 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_8++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_7 */
+ return xcb_pre_tmp_7;
+}
+
+xcb_input_fp3232_iterator_t
+xcb_input_touch_begin_axisvalues_iterator (const xcb_input_touch_begin_event_t *R)
+{
+ xcb_input_fp3232_iterator_t i;
+ xcb_generic_iterator_t prev = xcb_input_touch_begin_valuator_mask_end(R);
+ int xcb_pre_tmp_9; /* sumof length */
+ int xcb_pre_tmp_10; /* sumof loop counter */
+ int64_t xcb_pre_tmp_11; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_12; /* sumof list ptr */
+ /* sumof start */
+ xcb_pre_tmp_9 = R->valuators_len;
+ xcb_pre_tmp_11 = 0;
+ xcb_pre_tmp_12 = xcb_input_touch_begin_valuator_mask(R);
+ for (xcb_pre_tmp_10 = 0; xcb_pre_tmp_10 < xcb_pre_tmp_9; xcb_pre_tmp_10++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_12;
+ xcb_pre_tmp_11 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_12++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_11 */
+ i.data = (xcb_input_fp3232_t *) ((char *) prev.data + XCB_TYPE_PAD(xcb_input_fp3232_t, prev.index));
+ i.rem = xcb_pre_tmp_11;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+int
+xcb_input_touch_update_sizeof (const void *_buffer /**< */)
+{
+ return xcb_input_touch_begin_sizeof(_buffer);
+}
+
+int
+xcb_input_touch_end_sizeof (const void *_buffer /**< */)
+{
+ return xcb_input_touch_begin_sizeof(_buffer);
+}
+
+int
+xcb_input_raw_touch_begin_sizeof (const void *_buffer)
+{
+ char *xcb_tmp = (char *)_buffer;
+ const xcb_input_raw_touch_begin_event_t *_aux = (xcb_input_raw_touch_begin_event_t *)_buffer;
+ unsigned int xcb_buffer_len = 0;
+ unsigned int xcb_block_len = 0;
+ unsigned int xcb_pad = 0;
+ unsigned int xcb_align_to = 0;
+
+ int xcb_pre_tmp_1; /* sumof length */
+ int xcb_pre_tmp_2; /* sumof loop counter */
+ int64_t xcb_pre_tmp_3; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_4; /* sumof list ptr */
+ int xcb_pre_tmp_5; /* sumof length */
+ int xcb_pre_tmp_6; /* sumof loop counter */
+ int64_t xcb_pre_tmp_7; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_8; /* sumof list ptr */
+
+ xcb_block_len += sizeof(xcb_input_raw_touch_begin_event_t);
+ xcb_tmp += xcb_block_len;
+ xcb_buffer_len += xcb_block_len;
+ xcb_block_len = 0;
+ /* valuator_mask */
+ xcb_block_len += _aux->valuators_len * sizeof(uint32_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(uint32_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* axisvalues */
+ /* sumof start */
+ xcb_pre_tmp_1 = _aux->valuators_len;
+ xcb_pre_tmp_3 = 0;
+ xcb_pre_tmp_4 = xcb_input_raw_touch_begin_valuator_mask(_aux);
+ for (xcb_pre_tmp_2 = 0; xcb_pre_tmp_2 < xcb_pre_tmp_1; xcb_pre_tmp_2++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_4;
+ xcb_pre_tmp_3 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_4++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_3 */
+ xcb_block_len += xcb_pre_tmp_3 * sizeof(xcb_input_fp3232_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_fp3232_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+ /* axisvalues_raw */
+ /* sumof start */
+ xcb_pre_tmp_5 = _aux->valuators_len;
+ xcb_pre_tmp_7 = 0;
+ xcb_pre_tmp_8 = xcb_input_raw_touch_begin_valuator_mask(_aux);
+ for (xcb_pre_tmp_6 = 0; xcb_pre_tmp_6 < xcb_pre_tmp_5; xcb_pre_tmp_6++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_8;
+ xcb_pre_tmp_7 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_8++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_7 */
+ xcb_block_len += xcb_pre_tmp_7 * sizeof(xcb_input_fp3232_t);
+ xcb_tmp += xcb_block_len;
+ xcb_align_to = ALIGNOF(xcb_input_fp3232_t);
+ /* insert padding */
+ xcb_pad = -xcb_block_len & (xcb_align_to - 1);
+ xcb_buffer_len += xcb_block_len + xcb_pad;
+ if (0 != xcb_pad) {
+ xcb_tmp += xcb_pad;
+ xcb_pad = 0;
+ }
+ xcb_block_len = 0;
+
+ return xcb_buffer_len;
+}
+
+uint32_t *
+xcb_input_raw_touch_begin_valuator_mask (const xcb_input_raw_touch_begin_event_t *R)
+{
+ return (uint32_t *) (R + 1);
+}
+
+int
+xcb_input_raw_touch_begin_valuator_mask_length (const xcb_input_raw_touch_begin_event_t *R)
+{
+ return R->valuators_len;
+}
+
+xcb_generic_iterator_t
+xcb_input_raw_touch_begin_valuator_mask_end (const xcb_input_raw_touch_begin_event_t *R)
+{
+ xcb_generic_iterator_t i;
+ i.data = ((uint32_t *) (R + 1)) + (R->valuators_len);
+ i.rem = 0;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_fp3232_t *
+xcb_input_raw_touch_begin_axisvalues (const xcb_input_raw_touch_begin_event_t *R)
+{
+ xcb_generic_iterator_t prev = xcb_input_raw_touch_begin_valuator_mask_end(R);
+ return (xcb_input_fp3232_t *) ((char *) prev.data + XCB_TYPE_PAD(xcb_input_fp3232_t, prev.index) + 0);
+}
+
+int
+xcb_input_raw_touch_begin_axisvalues_length (const xcb_input_raw_touch_begin_event_t *R)
+{
+ int xcb_pre_tmp_9; /* sumof length */
+ int xcb_pre_tmp_10; /* sumof loop counter */
+ int64_t xcb_pre_tmp_11; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_12; /* sumof list ptr */
+ /* sumof start */
+ xcb_pre_tmp_9 = R->valuators_len;
+ xcb_pre_tmp_11 = 0;
+ xcb_pre_tmp_12 = xcb_input_raw_touch_begin_valuator_mask(R);
+ for (xcb_pre_tmp_10 = 0; xcb_pre_tmp_10 < xcb_pre_tmp_9; xcb_pre_tmp_10++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_12;
+ xcb_pre_tmp_11 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_12++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_11 */
+ return xcb_pre_tmp_11;
+}
+
+xcb_input_fp3232_iterator_t
+xcb_input_raw_touch_begin_axisvalues_iterator (const xcb_input_raw_touch_begin_event_t *R)
+{
+ xcb_input_fp3232_iterator_t i;
+ xcb_generic_iterator_t prev = xcb_input_raw_touch_begin_valuator_mask_end(R);
+ int xcb_pre_tmp_13; /* sumof length */
+ int xcb_pre_tmp_14; /* sumof loop counter */
+ int64_t xcb_pre_tmp_15; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_16; /* sumof list ptr */
+ /* sumof start */
+ xcb_pre_tmp_13 = R->valuators_len;
+ xcb_pre_tmp_15 = 0;
+ xcb_pre_tmp_16 = xcb_input_raw_touch_begin_valuator_mask(R);
+ for (xcb_pre_tmp_14 = 0; xcb_pre_tmp_14 < xcb_pre_tmp_13; xcb_pre_tmp_14++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_16;
+ xcb_pre_tmp_15 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_16++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_15 */
+ i.data = (xcb_input_fp3232_t *) ((char *) prev.data + XCB_TYPE_PAD(xcb_input_fp3232_t, prev.index));
+ i.rem = xcb_pre_tmp_15;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+xcb_input_fp3232_t *
+xcb_input_raw_touch_begin_axisvalues_raw (const xcb_input_raw_touch_begin_event_t *R)
+{
+ xcb_generic_iterator_t prev = xcb_input_fp3232_end(xcb_input_raw_touch_begin_axisvalues_iterator(R));
+ return (xcb_input_fp3232_t *) ((char *) prev.data + XCB_TYPE_PAD(xcb_input_fp3232_t, prev.index) + 0);
+}
+
+int
+xcb_input_raw_touch_begin_axisvalues_raw_length (const xcb_input_raw_touch_begin_event_t *R)
+{
+ int xcb_pre_tmp_17; /* sumof length */
+ int xcb_pre_tmp_18; /* sumof loop counter */
+ int64_t xcb_pre_tmp_19; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_20; /* sumof list ptr */
+ /* sumof start */
+ xcb_pre_tmp_17 = R->valuators_len;
+ xcb_pre_tmp_19 = 0;
+ xcb_pre_tmp_20 = xcb_input_raw_touch_begin_valuator_mask(R);
+ for (xcb_pre_tmp_18 = 0; xcb_pre_tmp_18 < xcb_pre_tmp_17; xcb_pre_tmp_18++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_20;
+ xcb_pre_tmp_19 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_20++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_19 */
+ return xcb_pre_tmp_19;
+}
+
+xcb_input_fp3232_iterator_t
+xcb_input_raw_touch_begin_axisvalues_raw_iterator (const xcb_input_raw_touch_begin_event_t *R)
+{
+ xcb_input_fp3232_iterator_t i;
+ xcb_generic_iterator_t prev = xcb_input_fp3232_end(xcb_input_raw_touch_begin_axisvalues_iterator(R));
+ int xcb_pre_tmp_21; /* sumof length */
+ int xcb_pre_tmp_22; /* sumof loop counter */
+ int64_t xcb_pre_tmp_23; /* sumof sum */
+ const uint32_t* xcb_pre_tmp_24; /* sumof list ptr */
+ /* sumof start */
+ xcb_pre_tmp_21 = R->valuators_len;
+ xcb_pre_tmp_23 = 0;
+ xcb_pre_tmp_24 = xcb_input_raw_touch_begin_valuator_mask(R);
+ for (xcb_pre_tmp_22 = 0; xcb_pre_tmp_22 < xcb_pre_tmp_21; xcb_pre_tmp_22++) {
+ const uint32_t *xcb_listelement = xcb_pre_tmp_24;
+ xcb_pre_tmp_23 += xcb_popcount((*xcb_listelement));
+ xcb_pre_tmp_24++;
+ }
+ /* sumof end. Result is in xcb_pre_tmp_23 */
+ i.data = (xcb_input_fp3232_t *) ((char *) prev.data + XCB_TYPE_PAD(xcb_input_fp3232_t, prev.index));
+ i.rem = xcb_pre_tmp_23;
+ i.index = (char *) i.data - (char *) R;
+ return i;
+}
+
+int
+xcb_input_raw_touch_update_sizeof (const void *_buffer /**< */)
+{
+ return xcb_input_raw_touch_begin_sizeof(_buffer);
+}
+
+int
+xcb_input_raw_touch_end_sizeof (const void *_buffer /**< */)
+{
+ return xcb_input_raw_touch_begin_sizeof(_buffer);
+}
diff --git a/src/3rdparty/xcb/libxcb/xkb.c b/src/3rdparty/xcb/libxcb/xkb.c
index ff025f6b60..d55bd76f10 100644
--- a/src/3rdparty/xcb/libxcb/xkb.c
+++ b/src/3rdparty/xcb/libxcb/xkb.c
@@ -18,15 +18,6 @@
xcb_extension_t xcb_xkb_id = { "XKEYBOARD", 0 };
-int qt_xcb_sumof(uint8_t *list, int len)
-{
- int i, s = 0;
- for(i=0; i<len; i++) {
- s += *list;
- list++;
- }
- return s;
-}
/*****************************************************************************
**
@@ -9034,7 +9025,7 @@ int
xcb_xkb_get_names_value_list_kt_level_names_length (const xcb_xkb_get_names_reply_t *R /**< */,
const xcb_xkb_get_names_value_list_t *S /**< */)
{
- return qt_xcb_sumof(/* valueList */ S->nLevelsPerType, R->nTypes);
+ return xcb_sumof(/* valueList */ S->nLevelsPerType, R->nTypes);
}
@@ -9052,7 +9043,7 @@ xcb_xkb_get_names_value_list_kt_level_names_end (const xcb_xkb_get_names_reply_t
const xcb_xkb_get_names_value_list_t *S /**< */)
{
xcb_generic_iterator_t i;
- i.data = /* valueList */ S->ktLevelNames + qt_xcb_sumof(/* valueList */ S->nLevelsPerType, R->nTypes);
+ i.data = /* valueList */ S->ktLevelNames + xcb_sumof(/* valueList */ S->nLevelsPerType, R->nTypes);
i.rem = 0;
i.index = (char *) i.data - (char *) S;
return i;
@@ -9517,8 +9508,8 @@ xcb_xkb_get_names_value_list_serialize (void **_
xcb_block_len = 0;
/* ktLevelNames */
xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->ktLevelNames;
- xcb_block_len += qt_xcb_sumof(_aux->nLevelsPerType, nTypes) * sizeof(xcb_atom_t);
- xcb_parts[xcb_parts_idx].iov_len = qt_xcb_sumof(_aux->nLevelsPerType, nTypes) * sizeof(xcb_atom_t);
+ xcb_block_len += xcb_sumof(_aux->nLevelsPerType, nTypes) * sizeof(xcb_atom_t);
+ xcb_parts[xcb_parts_idx].iov_len = xcb_sumof(_aux->nLevelsPerType, nTypes) * sizeof(xcb_atom_t);
xcb_parts_idx++;
xcb_align_to = ALIGNOF(xcb_atom_t);
}
@@ -9771,7 +9762,7 @@ xcb_xkb_get_names_value_list_unpack (const void *_buffer /
xcb_block_len = 0;
/* ktLevelNames */
_aux->ktLevelNames = (xcb_atom_t *)xcb_tmp;
- xcb_block_len += qt_xcb_sumof(_aux->nLevelsPerType, nTypes) * sizeof(xcb_atom_t);
+ xcb_block_len += xcb_sumof(_aux->nLevelsPerType, nTypes) * sizeof(xcb_atom_t);
xcb_tmp += xcb_block_len;
xcb_align_to = ALIGNOF(xcb_atom_t);
}
@@ -10148,7 +10139,7 @@ int
xcb_xkb_set_names_values_kt_level_names_length (const xcb_xkb_set_names_request_t *R /**< */,
const xcb_xkb_set_names_values_t *S /**< */)
{
- return qt_xcb_sumof(/* values */ S->nLevelsPerType, R->nKTLevels);
+ return xcb_sumof(/* values */ S->nLevelsPerType, R->nKTLevels);
}
@@ -10166,7 +10157,7 @@ xcb_xkb_set_names_values_kt_level_names_end (const xcb_xkb_set_names_request_t *
const xcb_xkb_set_names_values_t *S /**< */)
{
xcb_generic_iterator_t i;
- i.data = /* values */ S->ktLevelNames + qt_xcb_sumof(/* values */ S->nLevelsPerType, R->nKTLevels);
+ i.data = /* values */ S->ktLevelNames + xcb_sumof(/* values */ S->nLevelsPerType, R->nKTLevels);
i.rem = 0;
i.index = (char *) i.data - (char *) S;
return i;
@@ -10616,8 +10607,8 @@ xcb_xkb_set_names_values_serialize (void **_buffer
xcb_block_len = 0;
/* ktLevelNames */
xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->ktLevelNames;
- xcb_block_len += qt_xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
- xcb_parts[xcb_parts_idx].iov_len = qt_xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
+ xcb_block_len += xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
+ xcb_parts[xcb_parts_idx].iov_len = xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
xcb_parts_idx++;
xcb_align_to = ALIGNOF(xcb_atom_t);
}
@@ -10858,7 +10849,7 @@ xcb_xkb_set_names_values_unpack (const void *_buffer /**< */,
xcb_block_len = 0;
/* ktLevelNames */
_aux->ktLevelNames = (xcb_atom_t *)xcb_tmp;
- xcb_block_len += qt_xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
+ xcb_block_len += xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
xcb_tmp += xcb_block_len;
xcb_align_to = ALIGNOF(xcb_atom_t);
}
@@ -12881,7 +12872,7 @@ int
xcb_xkb_get_kbd_by_name_replies_key_names_value_list_kt_level_names_length (const xcb_xkb_get_kbd_by_name_reply_t *R /**< */,
const xcb_xkb_get_kbd_by_name_replies_t *S /**< */)
{
- return qt_xcb_sumof(/* replies */ S->key_names.valueList.nLevelsPerType, /* replies */ S->key_names.nKTLevels);
+ return xcb_sumof(/* replies */ S->key_names.valueList.nLevelsPerType, /* replies */ S->key_names.nKTLevels);
}
@@ -12899,7 +12890,7 @@ xcb_xkb_get_kbd_by_name_replies_key_names_value_list_kt_level_names_end (const x
const xcb_xkb_get_kbd_by_name_replies_t *S /**< */)
{
xcb_generic_iterator_t i;
- i.data = /* replies */ S->key_names.valueList.ktLevelNames + qt_xcb_sumof(/* replies */ S->key_names.valueList.nLevelsPerType, /* replies */ S->key_names.nKTLevels);
+ i.data = /* replies */ S->key_names.valueList.ktLevelNames + xcb_sumof(/* replies */ S->key_names.valueList.nLevelsPerType, /* replies */ S->key_names.nKTLevels);
i.rem = 0;
i.index = (char *) i.data - (char *) S;
return i;
@@ -13349,8 +13340,8 @@ xcb_xkb_get_kbd_by_name_replies_key_names_value_list_serialize (void
xcb_block_len = 0;
/* ktLevelNames */
xcb_parts[xcb_parts_idx].iov_base = (char *) _aux->ktLevelNames;
- xcb_block_len += qt_xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
- xcb_parts[xcb_parts_idx].iov_len = qt_xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
+ xcb_block_len += xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
+ xcb_parts[xcb_parts_idx].iov_len = xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
xcb_parts_idx++;
xcb_align_to = ALIGNOF(xcb_atom_t);
}
@@ -13591,7 +13582,7 @@ xcb_xkb_get_kbd_by_name_replies_key_names_value_list_unpack (const void
xcb_block_len = 0;
/* ktLevelNames */
_aux->ktLevelNames = (xcb_atom_t *)xcb_tmp;
- xcb_block_len += qt_xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
+ xcb_block_len += xcb_sumof(_aux->nLevelsPerType, nKTLevels) * sizeof(xcb_atom_t);
xcb_tmp += xcb_block_len;
xcb_align_to = ALIGNOF(xcb_atom_t);
}
diff --git a/src/3rdparty/xkbcommon-x11.pri b/src/3rdparty/xkbcommon-x11.pri
index 36f22ce9cc..58e3a63b46 100644
--- a/src/3rdparty/xkbcommon-x11.pri
+++ b/src/3rdparty/xkbcommon-x11.pri
@@ -4,6 +4,10 @@ include(xkbcommon.pri)
# in xcb-plugin.pro (linked to system libraries or if Qt was configured with -qt-xcb then
# linked to -lxcb-static).
INCLUDEPATH += $$PWD/xkbcommon/src/x11
+
+# Need to rename several files, qmake has problems processing a project when
+# sub-directories contain files with an equal names.
+
SOURCES += \
$$PWD/xkbcommon/src/x11/util.c \
$$PWD/xkbcommon/src/x11/x11-keymap.c \ # renamed: keymap.c -> x11-keymap.c
diff --git a/src/3rdparty/xkbcommon.pri b/src/3rdparty/xkbcommon.pri
index 1d953d8372..63c8e687ec 100644
--- a/src/3rdparty/xkbcommon.pri
+++ b/src/3rdparty/xkbcommon.pri
@@ -1,4 +1,6 @@
-QMAKE_CFLAGS += -std=gnu99 -w
+# Requires GNU C extensions
+CONFIG -= strict_c
+
INCLUDEPATH += $$PWD/xkbcommon \
$$PWD/xkbcommon/xkbcommon \
$$PWD/xkbcommon/src \
@@ -6,47 +8,53 @@ INCLUDEPATH += $$PWD/xkbcommon \
include($$shadowed($$PWD/../gui/qtgui-config.pri))
-DEFINES += DFLT_XKB_CONFIG_ROOT='\\"/usr/share/X11/xkb\\"' # unused, but needs to be set to something
+# Unused (but needs to be set to something) - we don't use APIs that read xkb
+# config files from file system. We use APIs that fetch the necessary keymap
+# details directly from X server.
+DEFINES += DFLT_XKB_CONFIG_ROOT='\\"/usr/share/X11/xkb\\"'
+# Unused (but needs to be set to something) - After QTBUG-42181, this needs to
+# be become a configure switch.
+DEFINES += XLOCALEDIR='\\"/usr/share/X11/locale/\\"'
### RMLVO names can be overwritten with environmental variables (see libxkbcommon documentation)
DEFINES += DEFAULT_XKB_RULES='\\"evdev\\"'
DEFINES += DEFAULT_XKB_MODEL='\\"pc105\\"'
DEFINES += DEFAULT_XKB_LAYOUT='\\"us\\"'
+
# Need to rename several files, qmake has problems processing a project when
# sub-directories contain files with an equal names.
-# libxkbcommon generates some of these files while executing "./autogen.sh"
-# and some while executing "make" (actually YACC)
SOURCES += \
- $$PWD/xkbcommon/src/atom.c \
- $$PWD/xkbcommon/src/xkb-compat.c \ # renamed: compat.c -> xkb-compat.c
- $$PWD/xkbcommon/src/context.c \
- $$PWD/xkbcommon/src/xkb-keymap.c \ # renamed: keymap.c -> xkb-keymap.c
- $$PWD/xkbcommon/src/keysym.c \
$$PWD/xkbcommon/src/keysym-utf.c \
- $$PWD/xkbcommon/src/state.c \
- $$PWD/xkbcommon/src/text.c \
- $$PWD/xkbcommon/src/context-priv.c \
+ $$PWD/xkbcommon/src/keymap.c \
$$PWD/xkbcommon/src/keymap-priv.c \
$$PWD/xkbcommon/src/utils.c \
- $$PWD/xkbcommon/src/utf8.c
-
-SOURCES += \
- $$PWD/xkbcommon/src/xkbcomp/action.c \
- $$PWD/xkbcommon/src/xkbcomp/ast-build.c \
- $$PWD/xkbcommon/src/xkbcomp/compat.c \
- $$PWD/xkbcommon/src/xkbcomp/expr.c \
- $$PWD/xkbcommon/src/xkbcomp/include.c \
- $$PWD/xkbcommon/src/xkbcomp/keycodes.c \
+ $$PWD/xkbcommon/src/atom.c \
+ $$PWD/xkbcommon/src/compose/paths.c \
+ $$PWD/xkbcommon/src/compose/parser.c \
+ $$PWD/xkbcommon/src/compose/compose-state.c \ # renamed: keymap.c -> compose-state.c
+ $$PWD/xkbcommon/src/compose/table.c \
+ $$PWD/xkbcommon/src/xkbcomp/xkbcomp-keymap.c \ # renamed: keymap.c -> xkbcomp-keymap.c
+ $$PWD/xkbcommon/src/xkbcomp/xkbcomp.c \
$$PWD/xkbcommon/src/xkbcomp/keymap-dump.c \
- $$PWD/xkbcommon/src/xkbcomp/keymap.c \
- $$PWD/xkbcommon/src/xkbcomp/keywords.c \
$$PWD/xkbcommon/src/xkbcomp/rules.c \
- $$PWD/xkbcommon/src/xkbcomp/scanner.c \
- $$PWD/xkbcommon/src/xkbcomp/symbols.c \
+ $$PWD/xkbcommon/src/xkbcomp/expr.c \
+ $$PWD/xkbcommon/src/xkbcomp/action.c \
+ $$PWD/xkbcommon/src/xkbcomp/compat.c \
$$PWD/xkbcommon/src/xkbcomp/types.c \
+ $$PWD/xkbcommon/src/xkbcomp/scanner.c \
+ $$PWD/xkbcommon/src/xkbcomp/xkbcomp-parser.c \ # renamed: parser.c -> xkbcomp-parser.c
+ $$PWD/xkbcommon/src/xkbcomp/ast-build.c \
+ $$PWD/xkbcommon/src/xkbcomp/keywords.c \
+ $$PWD/xkbcommon/src/xkbcomp/keycodes.c \
$$PWD/xkbcommon/src/xkbcomp/vmod.c \
- $$PWD/xkbcommon/src/xkbcomp/xkbcomp.c \
- $$PWD/xkbcommon/src/xkbcomp/parser.c
+ $$PWD/xkbcommon/src/xkbcomp/include.c \
+ $$PWD/xkbcommon/src/xkbcomp/symbols.c \
+ $$PWD/xkbcommon/src/context-priv.c \
+ $$PWD/xkbcommon/src/text.c \
+ $$PWD/xkbcommon/src/context.c \
+ $$PWD/xkbcommon/src/keysym.c \
+ $$PWD/xkbcommon/src/utf8.c \
+ $$PWD/xkbcommon/src/state.c
TR_EXCLUDE += $$PWD/*
diff --git a/src/3rdparty/xkbcommon/COPYING b/src/3rdparty/xkbcommon/COPYING
deleted file mode 100644
index 2d3b55a962..0000000000
--- a/src/3rdparty/xkbcommon/COPYING
+++ /dev/null
@@ -1,188 +0,0 @@
-The following is a list of all copyright notices and license statements which
-appear in the xkbcommon source tree.
-
-If making new contributions, the first form (i.e. Daniel Stone, Ran Benita,
-etc) is vastly preferred.
-
-All licenses are derivative of the MIT/X11 license, mostly identical other
-than no-endorsement clauses (e.g. paragraph 4 of The Open Group's license).
-
-These statements are split into two sections: one for the code compiled and
-distributed as part of the libxkbcommon shared library and the code
-component of all tests (i.e. everything under src/ and xkbcommon/, plus the
-.c and .h files under test/), and another for the test data under test/data,
-which is distributed with the xkbcommon source tarball, but not installed to
-the system.
-
-
-BEGINNING OF SOFTWARE COPYRIGHT/LICENSE STATEMENTS:
-
-
--------------------------------------------------------------------------------
-
-Copyright © 2009-2012 Daniel Stone
-Copyright © 2012 Ran Benita <ran234@gmail.com>
-Copyright © 2010, 2012 Intel Corporation
-Copyright © 2008, 2009 Dan Nicholson
-Copyright © 2010 Francisco Jerez <currojerez@riseup.net>
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice (including the next
-paragraph) shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
-
-
--------------------------------------------------------------------------------
-
-
-Copyright 1985, 1987, 1988, 1990, 1998 The Open Group
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the names of the authors or their
-institutions shall not be used in advertising or otherwise to promote the
-sale, use or other dealings in this Software without prior written
-authorization from the authors.
-
-
--------------------------------------------------------------------------------
-
-
-Copyright (c) 1993, 1994, 1995, 1996 by Silicon Graphics Computer Systems, Inc.
-
-Permission to use, copy, modify, and distribute this
-software and its documentation for any purpose and without
-fee is hereby granted, provided that the above copyright
-notice appear in all copies and that both that copyright
-notice and this permission notice appear in supporting
-documentation, and that the name of Silicon Graphics not be
-used in advertising or publicity pertaining to distribution
-of the software without specific prior written permission.
-Silicon Graphics makes no representation about the suitability
-of this software for any purpose. It is provided "as is"
-without any express or implied warranty.
-
-SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
-GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
-DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
-THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-
--------------------------------------------------------------------------------
-
-
-Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-
--------------------------------------------------------------------------------
-
-
-Copyright (C) 2011 Joseph Adams <joeyadams3.14159@gmail.com>
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
-
--------------------------------------------------------------------------------
-
-
-
-END OF SOFTWARE COPYRIGHT/LICENSE STATEMENTS
-
-
-BEGINNING OF LICENSE STATEMENTS FOR UNDISTRIBUTED DATA FILES IN test/data,
-derived from xkeyboard-config:
-
-
-
--------------------------------------------------------------------------------
-
-Copyright 1996 by Joseph Moss
-Copyright (C) 2002-2007 Free Software Foundation, Inc.
-Copyright (C) Dmitry Golubev <lastguru@mail.ru>, 2003-2004
-Copyright (C) 2004, Gregory Mokhin <mokhin@bog.msu.ru>
-Copyright (C) 2006 Erdal Ronahî
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation, and that the name of the copyright holder(s) not be used in
-advertising or publicity pertaining to distribution of the software without
-specific, written prior permission. The copyright holder(s) makes no
-representations about the suitability of this software for any purpose. It
-is provided "as is" without express or implied warranty.
-
-THE COPYRIGHT HOLDER(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
-EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
-TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
diff --git a/src/3rdparty/xkbcommon/Fix-compilation-on-libxcb-1.5.patch b/src/3rdparty/xkbcommon/Fix-compilation-on-libxcb-1.5.patch
deleted file mode 100644
index 691f142e5e..0000000000
--- a/src/3rdparty/xkbcommon/Fix-compilation-on-libxcb-1.5.patch
+++ /dev/null
@@ -1,19 +0,0 @@
-diff --git a/src/3rdparty/xkbcommon/src/x11/util.c b/src/3rdparty/xkbcommon/src/x11/util.c
-index 92ff2e6..7659c71 100644
---- a/src/3rdparty/xkbcommon/src/x11/util.c
-+++ b/src/3rdparty/xkbcommon/src/x11/util.c
-@@ -198,8 +198,12 @@ adopt_atoms(struct xkb_context *ctx, xcb_connection_t *conn,
- * sit there waiting. Sad.
- */
- err_discard:
-- for (size_t j = i + 1; j < stop; j++)
-- xcb_discard_reply(conn, cookies[j].sequence);
-+ for (size_t j = i + 1; j < stop; j++) {
-+ if (from[j] != XCB_ATOM_NONE) {
-+ reply = xcb_get_atom_name_reply(conn, cookies[j % SIZE], NULL);
-+ free(reply);
-+ }
-+ }
- return false;
- }
- }
diff --git a/src/3rdparty/xkbcommon/LICENSE b/src/3rdparty/xkbcommon/LICENSE
new file mode 100644
index 0000000000..3dcd0391fc
--- /dev/null
+++ b/src/3rdparty/xkbcommon/LICENSE
@@ -0,0 +1,215 @@
+The following is a list of all copyright notices and license statements which
+appear in the xkbcommon source tree.
+
+If making new contributions, the first form (i.e. Daniel Stone, Ran Benita,
+etc) is vastly preferred.
+
+All licenses are derivative of the MIT/X11 license, mostly identical other
+than no-endorsement clauses (e.g. paragraph 4 of The Open Group's license).
+
+These statements are split into two sections: one for the code compiled and
+distributed as part of the libxkbcommon shared library and the code
+component of all tests (i.e. everything under src/ and xkbcommon/, plus the
+.c and .h files under test/), and another for the test data under test/data,
+which is distributed with the xkbcommon source tarball, but not installed to
+the system.
+
+
+BEGINNING OF SOFTWARE COPYRIGHT/LICENSE STATEMENTS:
+
+
+-------------------------------------------------------------------------------
+
+Copyright © 2009-2012, 2016 Daniel Stone
+Copyright © 2012 Ran Benita <ran234@gmail.com>
+Copyright © 2010, 2012 Intel Corporation
+Copyright © 2008, 2009 Dan Nicholson
+Copyright © 2010 Francisco Jerez <currojerez@riseup.net>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+
+-------------------------------------------------------------------------------
+
+
+Copyright 1985, 1987, 1988, 1990, 1998 The Open Group
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the names of the authors or their
+institutions shall not be used in advertising or otherwise to promote the
+sale, use or other dealings in this Software without prior written
+authorization from the authors.
+
+
+-------------------------------------------------------------------------------
+
+
+Copyright (c) 1993, 1994, 1995, 1996 by Silicon Graphics Computer Systems, Inc.
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of Silicon Graphics not be
+used in advertising or publicity pertaining to distribution
+of the software without specific prior written permission.
+Silicon Graphics makes no representation about the suitability
+of this software for any purpose. It is provided "as is"
+without any express or implied warranty.
+
+SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+
+-------------------------------------------------------------------------------
+
+
+Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+
+-------------------------------------------------------------------------------
+
+
+Copyright (C) 2011 Joseph Adams <joeyadams3.14159@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+
+-------------------------------------------------------------------------------
+
+
+
+END OF SOFTWARE COPYRIGHT/LICENSE STATEMENTS
+
+
+BEGINNING OF LICENSE STATEMENTS FOR UNDISTRIBUTED DATA FILES IN test/data,
+derived from xkeyboard-config:
+
+
+
+-------------------------------------------------------------------------------
+
+Copyright 1996 by Joseph Moss
+Copyright (C) 2002-2007 Free Software Foundation, Inc.
+Copyright (C) Dmitry Golubev <lastguru@mail.ru>, 2003-2004
+Copyright (C) 2004, Gregory Mokhin <mokhin@bog.msu.ru>
+Copyright (C) 2006 Erdal Ronahî
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of the copyright holder(s) not be used in
+advertising or publicity pertaining to distribution of the software without
+specific, written prior permission. The copyright holder(s) makes no
+representations about the suitability of this software for any purpose. It
+is provided "as is" without express or implied warranty.
+
+THE COPYRIGHT HOLDER(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+
+-------------------------------------------------------------------------------
+
+ Copyright 1992 by Oki Technosystems Laboratory, Inc.
+ Copyright 1992 by Fuji Xerox Co., Ltd.
+
+Permission to use, copy, modify, distribute, and sell this software
+and its documentation for any purpose is hereby granted without fee,
+provided that the above copyright notice appear in all copies and
+that both that copyright notice and this permission notice appear
+in supporting documentation, and that the name of Oki Technosystems
+Laboratory and Fuji Xerox not be used in advertising or publicity
+pertaining to distribution of the software without specific, written
+prior permission.
+Oki Technosystems Laboratory and Fuji Xerox make no representations
+about the suitability of this software for any purpose. It is provided
+"as is" without express or implied warranty.
+
+OKI TECHNOSYSTEMS LABORATORY AND FUJI XEROX DISCLAIM ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL OKI TECHNOSYSTEMS
+LABORATORY AND FUJI XEROX BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
+OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/src/3rdparty/xkbcommon/NEWS b/src/3rdparty/xkbcommon/NEWS
index 07ebdd97e3..50b01a3b5f 100644
--- a/src/3rdparty/xkbcommon/NEWS
+++ b/src/3rdparty/xkbcommon/NEWS
@@ -1,4 +1,278 @@
-libxkbcommon 0.4.1
+libxkbcommon 0.8.2 - 2018-08-05
+==================
+
+- Fix various problems found with fuzzing (see commit messages for
+ more details):
+
+ - Fix a few NULL-dereferences, out-of-bounds access and undefined behavior
+ in the XKB text format parser.
+
+
+libxkbcommon 0.8.1 - 2018-08-03
+==================
+
+- Fix various problems found in the meson build (see commit messages for more
+ details):
+
+ - Fix compilation on Darwin.
+
+ - Fix compilation of the x11 tests and demos when XCB is installed in a
+ non-standard location.
+
+ - Fix xkbcommon-x11.pc missing the Requires specification.
+
+- Fix various problems found with fuzzing and Coverity (see commit messages for
+ more details):
+
+ - Fix stack overflow in the XKB text format parser when evaluating boolean
+ negation.
+
+ - Fix NULL-dereferences in the XKB text format parser when some unsupported
+ tokens appear (the tokens are still parsed for backward compatibility).
+
+ - Fix NULL-dereference in the XKB text format parser when parsing an
+ xkb_geometry section.
+
+ - Fix an infinite loop in the Compose text format parser on some inputs.
+
+ - Fix an invalid free() when using multiple keysyms.
+
+- Replace the Unicode characters for the leftanglebracket and rightanglebracket
+ keysyms from the deprecated LEFT/RIGHT-POINTING ANGLE BRACKET to
+ MATHEMATICAL LEFT/RIGHT ANGLE BRACKET.
+
+- Reject out-of-range Unicode codepoints in xkb_keysym_to_utf8 and
+ xkb_keysym_to_utf32.
+
+
+libxkbcommon 0.8.0 - 2017-12-15
+==================
+
+- Added xkb_keysym_to_{upper,lower} to perform case-conversion directly on
+ keysyms. This is useful in some odd cases, but working with the Unicode
+ representations should be preferred when possible.
+
+- Added Unicode conversion rules for the signifblank and permille keysyms.
+
+- Fixed a bug in the parsing of XKB key type definitions where the number
+ of levels were determined by the number of level *names*. Keymaps which
+ omit level names were hence miscompiled.
+
+ This regressed in version 0.4.3. Keymaps from xkeyboard-config were not
+ affected since they don't omit level names.
+
+- New API:
+ xkb_keysym_to_upper()
+ xkb_keysym_to_lower()
+
+
+libxkbcommon 0.7.2 - 2017-08-04
+==================
+
+- Added a Meson build system as an alternative to existing autotools build
+ system.
+
+ The intent is to remove the autotools build in one of the next releases.
+ Please try to convert to it and report any problems.
+
+ See http://mesonbuild.com/Quick-guide.html for basic usage, the
+ meson_options.txt for the project-specific configuration options,
+ and the PACKAGING file for more details.
+
+ There are some noteworthy differences compared to the autotools build:
+
+ - Feature auto-detection is not performed. By default, all features are
+ enabled (currently: docs, x11, wayland). The build fails if any of
+ the required dependencies are not available. To disable a feature,
+ pass -Denable-<feature>=false to meson.
+
+ - The libraries are either installed as shared or static, as specified
+ by the -Ddefault_library=shared/static option. With autotools, both
+ versions are installed by default.
+
+ - xorg-util-macros is not used.
+
+ - A parser generator (bison/byacc) is always required - there is no
+ fallback to pre-generated output bundled in the tarball, as there is
+ in autotools.
+
+- Removed Android.mk support.
+
+- Removed the *-uninstalled.pc pkgconfig files.
+
+- Ported the interactive-wayland demo program to v6 of the xdg-shell
+ protocol.
+
+- Added new keysym definitions from xproto.
+
+- New API:
+ XKB_KEY_XF86Keyboard
+ XKB_KEY_XF86WWAN
+ XKB_KEY_XF86RFKill
+ XKB_KEY_XF86AudioPreset
+
+
+libxkbcommon 0.7.1 - 2017-01-18
+==================
+
+- Fixed various reported problems when the current locale is tr_TR.UTF-8.
+
+ The function xkb_keysym_from_name() used to perform case-insensitive
+ string comparisons in a locale-dependent way, but required it to to
+ work as in the C/ASCII locale (the so called "Turkish i problem").
+
+ The function is now no longer affected by the current locale.
+
+- Fixed compilation in NetBSD.
+
+
+libxkbcommon 0.7.0 - 2016-11-11
+==================
+
+- Added support for different "modes" of calculating consumed modifiers.
+ The existing mode, based on the XKB standard, has proven to be
+ unintuitive in various shortcut implementations.
+
+ A new mode, based on the calculation used by the GTK toolkit, is added.
+ This mode is less eager to declare a modifier as consumed.
+
+- Added a new interactive demo program using the Wayland protocol.
+ See the PACKAGING file for the new (optional) test dependencies.
+
+- Fixed a compilation error on GNU Hurd.
+
+- New API:
+ enum xkb_consumed_mode
+ XKB_CONSUMED_MODE_XKB
+ XKB_CONSUMED_MODE_GTK
+ xkb_state_key_get_consumed_mods2
+ xkb_state_mod_index_is_consumed2
+
+
+libxkbcommon 0.6.1 - 2016-04-08
+==================
+
+- Added LICENSE to distributed files in tarball releases.
+
+- Minor typo fix in xkb_keymap_get_as_string() documentation.
+
+
+libxkbcommon 0.6.0 - 2016-03-16
+==================
+
+- If the XKB_CONFIG_ROOT environment variable is set, it is used as the XKB
+ configuration root instead of the path determined at build time.
+
+- Tests and benchmarks now build correctly on OSX.
+
+- An XKB keymap provides a name for each key it defines. Traditionally,
+ these names are limited to at most 4 characters, and are thus somewhat
+ obscure, but might still be useful (xkbcommon lifts the 4 character limit).
+
+ The new functions xkb_keymap_key_get_name() and xkb_keymap_key_by_name()
+ can be used to get the name of a key or find a key by name. Note that
+ a key may have aliases.
+
+- Documentation improvements.
+
+- New API:
+ xkb_keymap_key_by_name()
+ xkb_keymap_key_get_name()
+
+
+libxkbcommon 0.5.0 - 2014-10-18
+==================
+
+- Added support for Compose/dead keys in a new module (included in
+ libxkbcommon). See the documentation or the
+ xkbcommon/xkbcommon-compose.h header file for more details.
+
+- Improved and reordered some sections of the documentation.
+
+- The doxygen HTML pages were made nicer to read.
+
+- Most tests now run also on non-linux platforms.
+
+- A warning is emitted by default about RMLVO values which are not used
+ during keymap compilation, which are most often a user misconfiguration.
+ For example, "terminate:ctrl_alt_backspace" instead of
+ "terminate:ctrl_alt_bksp".
+
+- Added symbol versioning for libxkbcommon and libxkbcommon-x11.
+ Note: binaries compiled against this and future versions will not be
+ able to link against the previous versions of the library.
+
+- Removed several compatablity symbols from the binary (the API isn't
+ affected). This affects binaries which
+
+ 1. Were compiled against a pre-stable (<0.2.0) version of libxkbcommon, and
+ 2. Are linked against the this or later version of libxkbcommon.
+
+ Such a scenario is likely to fail already.
+
+- If Xvfb is not available, the x11comp test is now correctly skipped
+ instead of hanging.
+
+- Benchmarks were moved to a separate bench/ directory.
+
+- Build fixes from OpenBSD.
+
+- Fixed a bug where key type entries such as "map[None] = Level2;" were
+ ignored.
+
+- New API:
+ XKB_COMPOSE_*
+ xkb_compose_*
+
+
+libxkbcommon 0.4.3 - 2014-08-19
+==================
+
+- Fixed a bug which caused xkb_x11_keymap_new_from_device() to misrepresent
+ modifiers for some keymaps.
+
+ https://github.com/xkbcommon/libxkbcommon/issues/9
+
+- Fixed a bug which caused xkb_x11_keymap_new_from_device() to ignore XKB
+ PrivateAction's.
+
+- Modifiers are now always fully resolved after xkb_state_update_mask().
+ Previously the given state components were used as-is, without
+ considering virtual modifier mappings.
+ Note: this only affects non-standard uses of xkb_state_update_mask().
+
+- Added a test for xkbcommon-x11, "x11comp". The test uses the system's
+ Xvfb server and xkbcomp. If they do not exist or fail, the test is
+ skipped.
+
+- Fixed memory leaks after parse errors in the XKB yacc parser.
+ The fix required changes which are currently incompatible with byacc.
+
+
+libxkbcommon 0.4.2 - 2014-05-15
+==================
+
+- Fixed a bug where explicitly passing "--enable-x11" to ./configure would
+ in fact disable it (regressed in 0.4.1).
+
+- Added @since version annotations to the API documentation for everything
+ introduced after the initial stable release (0.2.0).
+
+- Added a section to the documentation about keysym transformations, and
+ clarified which functions perform a given transformation.
+
+- XKB files which fail to compile during keymap construction can no longer
+ have any effect on the resulting keymap: changes are only applied when
+ the entire compilation succeeds.
+ Note: this was a minor correctness issue inherited from xkbcomp.
+
+- Fix an out-of-bounds array access in src/x11/util.c:adopt_atoms()
+ error-handling code.
+ Note: it seems impossible to trigger in the current code since the input
+ size cannot exceed the required size.
+
+
+libxkbcommon 0.4.1 - 2014-03-27
==================
- Converted README to markdown and added a Quick Guide to the
@@ -15,7 +289,7 @@ libxkbcommon 0.4.1
is converted to an appropriate control character.
This matches the behavior of libX11's XLookupString(3), and
required by the XKB specification:
- http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Control_Modifier
+ https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Control_Modifier
https://bugs.freedesktop.org/show_bug.cgi?id=75892
@@ -41,7 +315,8 @@ libxkbcommon 0.4.1
- Bug fixes.
-libxkbcommon 0.4.0
+
+libxkbcommon 0.4.0 - 2014-02-02
==================
- Add a new add-on library, xkbcommon-x11, to support creating keymaps
@@ -68,7 +343,7 @@ libxkbcommon 0.4.0
xkb_x11_* types and functions, XKB_X11_* constants.
-libxkbcommon 0.3.2
+libxkbcommon 0.3.2 - 2013-11-22
==================
- Log messages from the library now look like "xkbcommon: ERROR" by
@@ -77,7 +352,7 @@ libxkbcommon 0.3.2
- Apply capitalization transformation on keysyms in
xkb_keysym_get_one_sym(), to match the behavior specified in the XKB
specification:
- http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Lock_Modifier
+ https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Lock_Modifier
- Support byacc for generating the parser, in addition to Bison.
@@ -90,7 +365,7 @@ libxkbcommon 0.3.2
- Bug fixes.
-libxkbcommon 0.3.1
+libxkbcommon 0.3.1 - 2013-06-03
==================
- Replace the flex scanner with a hand-written one. flex is no longer
@@ -102,7 +377,7 @@ libxkbcommon 0.3.1
xkb_keymap_key_for_each()
-libxkbcommon 0.3.0
+libxkbcommon 0.3.0 - 2013-04-01
==================
- Allow passing NULL to *_unref() functions; do nothing instead of
diff --git a/src/3rdparty/xkbcommon/README.md b/src/3rdparty/xkbcommon/README.md
index 2627a324a6..b8ae50de77 100644
--- a/src/3rdparty/xkbcommon/README.md
+++ b/src/3rdparty/xkbcommon/README.md
@@ -1,100 +1,66 @@
# libxkbcommon
-xkbcommon is a keymap compiler and support library which processes a
-reduced subset of keymaps as defined by the XKB specification. Primarily,
-a keymap is created from a set of Rules/Model/Layout/Variant/Options names,
-processed through an XKB ruleset, and compiled into a struct xkb_keymap,
-which is the base type for all xkbcommon operations.
-
-From an xkb_keymap, an xkb_state object is created which holds the current
-state of all modifiers, groups, LEDs, etc, relating to that keymap. All
-key events must be fed into the xkb_state object using xkb_state_update_key().
-Once this is done, the xkb_state object will be properly updated, and the
-keysyms to use can be obtained with xkb_state_key_get_syms().
-
-libxkbcommon does not distribute a dataset itself, other than for testing
-purposes. The most common dataset is xkeyboard-config, as used by all
-current distributions for their X11 XKB data. More information on
-xkeyboard-config is available here:
- http://www.freedesktop.org/wiki/Software/XKeyboardConfig
+libxkbcommon is a keyboard keymap compiler and support library which
+processes a reduced subset of keymaps as defined by the XKB (X Keyboard
+Extension) specification. It also contains a module for handling Compose
+and dead keys.
## Quick Guide
See [Quick Guide](doc/quick-guide.md).
+## Building
+
+libxkbcommon is built with [Meson](http://mesonbuild.com/):
+
+ meson setup build
+ ninja -C build
+
+To build for use with Wayland, you can disable X11 support while still
+using the X11 keyboard configuration resource files thusly:
+
+ meson setup build \
+ -Denable-x11=false \
+ -Dxkb-config-root=/usr/share/X11/xkb \
+ -Dx-locale-root=/usr/share/X11/locale
+ ninja -C build
+
## API
-While xkbcommon's API is somewhat derived from the classic XKB API as found
+While libxkbcommon's API is somewhat derived from the classic XKB API as found
in X11/extensions/XKB.h and friends, it has been substantially reworked to
-expose fewer internal details to clients. The supported API is available
-in the xkbcommon/xkbcommon-*.h files. Additional support is provided for
-X11 (XCB) clients, in the xkbcommon-x11 library, xkbcommon/xkbcommon-x11.h.
-
-The xkbcommon API and ABI are stable. We will attempt to not break ABI during
-a minor release series, so applications written against 0.1.0 should be
-completely compatible with 0.5.3, but not necessarily with 1.0.0. However, new
-symbols may be introduced in any release. Thus, anyone packaging xkbcommon
-should make sure any package depending on it depends on a release greater than
-or equal to the version it was built against (or earlier, if it doesn't use
-any newly-introduced symbols), but less than the next major release.
+expose fewer internal details to clients.
+
+See the [API Documentation](https://xkbcommon.org/doc/current/modules.html).
+
+## Dataset
+
+libxkbcommon does not distribute a keymap dataset itself, other than for
+testing purposes. The most common dataset is xkeyboard-config, which is used
+by all current distributions for their X11 XKB data. More information on
+xkeyboard-config is available here:
+ https://www.freedesktop.org/wiki/Software/XKeyboardConfig
+
+The dataset for Compose is distributed in libX11, as part of the X locale
+data.
## Relation to X11
-Relative to the XKB 1.1 specification implemented in current X servers,
-xkbcommon has removed support for some parts of the specification which
-introduced unnecessary complications. Many of these removals were in fact
-not implemented, or half-implemented at best, as well as being totally
-unused in the standard dataset.
-
-Notable removals:
-- geometry support
- + there were very few geometry definitions available, and while
- xkbcommon was responsible for parsing this insanely complex format,
- it never actually did anything with it
- + hopefully someone will develop a companion library which supports
- keyboard geometries in a more useful format
-- KcCGST (keycodes/compat/geometry/symbols/types) API
- + use RMLVO instead; KcCGST is now an implementation detail
- + including pre-defined keymap files
-- XKM support
- + may come in an optional X11 support/compatibility library
-- around half of the interpret actions
- + pointer device, message and redirect actions in particular
-- non-virtual modifiers
- + core and virtual modifiers have been collapsed into the same
- namespace, with a 'significant' flag that largely parallels the
- core/virtual split
-- radio groups
- + completely unused in current keymaps, never fully implemented
-- overlays
- + almost completely unused in current keymaps
-- key behaviors
- + used to implement radio groups and overlays, and to deal with things
- like keys that physically lock; unused in current keymaps
-- indicator behaviours such as LED-controls-key
- + the only supported LED behaviour is key-controls-LED; again this
- was never really used in current keymaps
-
-Notable additions:
-- 32-bit keycodes
-- extended number of modifiers
-- extended number of groups
-- multiple keysyms per level
- + this requires incompatible dataset changes, such that X11 would
- not be able to parse these
+See [Compatibility](doc/compat.md) notes.
## Development
An extremely rudimentary homepage can be found at
- http://xkbcommon.org
+ https://xkbcommon.org
xkbcommon is maintained in git at
https://github.com/xkbcommon/libxkbcommon
Patches are always welcome, and may be sent to either
<xorg-devel@lists.x.org> or <wayland-devel@lists.freedesktop.org>
+or through github.
-Bugs are also welcome, and may be reported either at
+Bug reports are also welcome, and may be filed either at
Bugzilla https://bugs.freedesktop.org/describecomponents.cgi?product=libxkbcommon
or
Github https://github.com/xkbcommon/libxkbcommon/issues
diff --git a/src/3rdparty/xkbcommon/qt_attribution.json b/src/3rdparty/xkbcommon/qt_attribution.json
index 4be9b42917..215a4513f3 100644
--- a/src/3rdparty/xkbcommon/qt_attribution.json
+++ b/src/3rdparty/xkbcommon/qt_attribution.json
@@ -6,22 +6,24 @@
"Description": "xkbcommon is a keymap compiler and support library which processes a reduced subset of keymaps as defined by the XKB specification.",
"Homepage": "http://xkbcommon.org/",
- "Version": "0.4.1",
+ "Version": "0.8.2 + subsequent commits up to 31f1f355700870c6615399fbfa7934934b3a9a57",
"License": "MIT Licenses (with no-advertisement clause)",
"LicenseId": "MIT",
- "LicenseFile": "COPYING",
- "Copyright": "Copyright 1985, 1987, 1988, 1990, 1998 The Open Group
-Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
+ "LicenseFile": "LICENSE",
+ "Copyright": "Copyright 2009-2012, 2016 Daniel Stone
+Copyright 2012 Ran Benita <ran234@gmail.com>
+Copyright 2010, 2012 Intel Corporation
+Copyright 2008, 2009 Dan Nicholson
+Copyright 2010 Francisco Jerez <currojerez@riseup.net>
+Copyright 1985, 1987, 1988, 1990, 1998 The Open Group
Copyright 1993, 1994, 1995, 1996 by Silicon Graphics Computer Systems, Inc.
+Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
+Copyright 2011 Joseph Adams <joeyadams3.14159@gmail.com>
Copyright 1996 by Joseph Moss
Copyright 2002-2007 Free Software Foundation, Inc.
Copyright 2003-2004 Dmitry Golubev <lastguru@mail.ru>
Copyright 2004, Gregory Mokhin <mokhin@bog.msu.ru>
Copyright 2006 Erdal Ronahî
-Copyright 2008, 2009 Dan Nicholson
-Copyright 2009-2012 Daniel Stone
-Copyright 2010, 2012 Intel Corporation
-Copyright 2010 Francisco Jerez <currojerez@riseup.net>
-Copyright 2011 Joseph Adams <joeyadams3.14159@gmail.com>
-Copyright 2012 Ran Benita <ran234@gmail.com>"
+Copyright 1992 by Oki Technosystems Laboratory, Inc.
+Copyright 1992 by Fuji Xerox Co., Ltd."
}
diff --git a/src/3rdparty/xkbcommon/src/compose/compose-state.c b/src/3rdparty/xkbcommon/src/compose/compose-state.c
new file mode 100644
index 0000000000..8657ff7e17
--- /dev/null
+++ b/src/3rdparty/xkbcommon/src/compose/compose-state.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright © 2013 Ran Benita <ran234@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "table.h"
+#include "utils.h"
+#include "keysym.h"
+
+struct xkb_compose_state {
+ int refcnt;
+ enum xkb_compose_state_flags flags;
+ struct xkb_compose_table *table;
+
+ /*
+ * Offsets into xkb_compose_table::nodes.
+ *
+ * They maintain the current and previous position in the trie; see
+ * xkb_compose_state_feed().
+ *
+ * This is also sufficient for inferring the current status; see
+ * xkb_compose_state_get_status().
+ */
+ uint32_t prev_context;
+ uint32_t context;
+};
+
+XKB_EXPORT struct xkb_compose_state *
+xkb_compose_state_new(struct xkb_compose_table *table,
+ enum xkb_compose_state_flags flags)
+{
+ struct xkb_compose_state *state;
+
+ state = calloc(1, sizeof(*state));
+ if (!state)
+ return NULL;
+
+ state->refcnt = 1;
+ state->table = xkb_compose_table_ref(table);
+
+ state->flags = flags;
+ state->prev_context = 0;
+ state->context = 0;
+
+ return state;
+}
+
+XKB_EXPORT struct xkb_compose_state *
+xkb_compose_state_ref(struct xkb_compose_state *state)
+{
+ state->refcnt++;
+ return state;
+}
+
+XKB_EXPORT void
+xkb_compose_state_unref(struct xkb_compose_state *state)
+{
+ if (!state || --state->refcnt > 0)
+ return;
+
+ xkb_compose_table_unref(state->table);
+ free(state);
+}
+
+XKB_EXPORT struct xkb_compose_table *
+xkb_compose_state_get_compose_table(struct xkb_compose_state *state)
+{
+ return state->table;
+}
+
+XKB_EXPORT enum xkb_compose_feed_result
+xkb_compose_state_feed(struct xkb_compose_state *state, xkb_keysym_t keysym)
+{
+ uint32_t context;
+ const struct compose_node *node;
+
+ /*
+ * Modifiers do not affect the sequence directly. In particular,
+ * they do not cancel a sequence; otherwise it'd be impossible to
+ * have a sequence like <dead_acute><A> (needs Shift in the middle).
+ *
+ * The following test is not really accurate - in order to test if
+ * a key is "modifier key", we really need the keymap, but we don't
+ * have it here. However, this is (approximately) what libX11 does
+ * as well.
+ */
+ if (xkb_keysym_is_modifier(keysym))
+ return XKB_COMPOSE_FEED_IGNORED;
+
+ node = &darray_item(state->table->nodes, state->context);
+
+ context = (node->is_leaf ? 0 : node->u.successor);
+ node = &darray_item(state->table->nodes, context);
+
+ while (node->keysym != keysym && node->next != 0) {
+ context = node->next;
+ node = &darray_item(state->table->nodes, context);
+ }
+
+ if (node->keysym != keysym)
+ context = 0;
+
+ state->prev_context = state->context;
+ state->context = context;
+ return XKB_COMPOSE_FEED_ACCEPTED;
+}
+
+XKB_EXPORT void
+xkb_compose_state_reset(struct xkb_compose_state *state)
+{
+ state->prev_context = 0;
+ state->context = 0;
+}
+
+XKB_EXPORT enum xkb_compose_status
+xkb_compose_state_get_status(struct xkb_compose_state *state)
+{
+ const struct compose_node *prev_node, *node;
+
+ prev_node = &darray_item(state->table->nodes, state->prev_context);
+ node = &darray_item(state->table->nodes, state->context);
+
+ if (state->context == 0 && !prev_node->is_leaf)
+ return XKB_COMPOSE_CANCELLED;
+
+ if (state->context == 0)
+ return XKB_COMPOSE_NOTHING;
+
+ if (!node->is_leaf)
+ return XKB_COMPOSE_COMPOSING;
+
+ return XKB_COMPOSE_COMPOSED;
+}
+
+XKB_EXPORT int
+xkb_compose_state_get_utf8(struct xkb_compose_state *state,
+ char *buffer, size_t size)
+{
+ const struct compose_node *node =
+ &darray_item(state->table->nodes, state->context);
+
+ if (!node->is_leaf)
+ goto fail;
+
+ /* If there's no string specified, but only a keysym, try to do the
+ * most helpful thing. */
+ if (node->u.leaf.utf8 == 0 && node->u.leaf.keysym != XKB_KEY_NoSymbol) {
+ char name[64];
+ int ret;
+
+ ret = xkb_keysym_to_utf8(node->u.leaf.keysym, name, sizeof(name));
+ if (ret < 0 || ret == 0) {
+ /* ret < 0 is impossible.
+ * ret == 0 means the keysym has no string representation. */
+ goto fail;
+ }
+
+ return snprintf(buffer, size, "%s", name);
+ }
+
+ return snprintf(buffer, size, "%s",
+ &darray_item(state->table->utf8, node->u.leaf.utf8));
+
+fail:
+ if (size > 0)
+ buffer[0] = '\0';
+ return 0;
+}
+
+XKB_EXPORT xkb_keysym_t
+xkb_compose_state_get_one_sym(struct xkb_compose_state *state)
+{
+ const struct compose_node *node =
+ &darray_item(state->table->nodes, state->context);
+ if (!node->is_leaf)
+ return XKB_KEY_NoSymbol;
+ return node->u.leaf.keysym;
+}
diff --git a/src/3rdparty/xkbcommon/src/compose/parser.c b/src/3rdparty/xkbcommon/src/compose/parser.c
new file mode 100644
index 0000000000..439d404f06
--- /dev/null
+++ b/src/3rdparty/xkbcommon/src/compose/parser.c
@@ -0,0 +1,737 @@
+/*
+ * Copyright © 2013 Ran Benita <ran234@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/******************************************************************
+
+ Copyright 1992 by Oki Technosystems Laboratory, Inc.
+ Copyright 1992 by Fuji Xerox Co., Ltd.
+
+Permission to use, copy, modify, distribute, and sell this software
+and its documentation for any purpose is hereby granted without fee,
+provided that the above copyright notice appear in all copies and
+that both that copyright notice and this permission notice appear
+in supporting documentation, and that the name of Oki Technosystems
+Laboratory and Fuji Xerox not be used in advertising or publicity
+pertaining to distribution of the software without specific, written
+prior permission.
+Oki Technosystems Laboratory and Fuji Xerox make no representations
+about the suitability of this software for any purpose. It is provided
+"as is" without express or implied warranty.
+
+OKI TECHNOSYSTEMS LABORATORY AND FUJI XEROX DISCLAIM ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL OKI TECHNOSYSTEMS
+LABORATORY AND FUJI XEROX BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
+OR PERFORMANCE OF THIS SOFTWARE.
+
+ Author: Yasuhiro Kawai Oki Technosystems Laboratory
+ Author: Kazunori Nishihara Fuji Xerox
+
+******************************************************************/
+
+#include <errno.h>
+
+#include "utils.h"
+#include "scanner-utils.h"
+#include "table.h"
+#include "paths.h"
+#include "utf8.h"
+#include "parser.h"
+
+#define MAX_LHS_LEN 10
+#define MAX_INCLUDE_DEPTH 5
+
+/*
+ * Grammar adapted from libX11/modules/im/ximcp/imLcPrs.c.
+ * See also the XCompose(5) manpage.
+ *
+ * FILE ::= { [PRODUCTION] [COMMENT] "\n" | INCLUDE }
+ * INCLUDE ::= "include" '"' INCLUDE_STRING '"'
+ * PRODUCTION ::= LHS ":" RHS [ COMMENT ]
+ * COMMENT ::= "#" {<any character except null or newline>}
+ * LHS ::= EVENT { EVENT }
+ * EVENT ::= [MODIFIER_LIST] "<" keysym ">"
+ * MODIFIER_LIST ::= (["!"] {MODIFIER} ) | "None"
+ * MODIFIER ::= ["~"] MODIFIER_NAME
+ * MODIFIER_NAME ::= ("Ctrl"|"Lock"|"Caps"|"Shift"|"Alt"|"Meta")
+ * RHS ::= ( STRING | keysym | STRING keysym )
+ * STRING ::= '"' { CHAR } '"'
+ * CHAR ::= GRAPHIC_CHAR | ESCAPED_CHAR
+ * GRAPHIC_CHAR ::= locale (codeset) dependent code
+ * ESCAPED_CHAR ::= ('\\' | '\"' | OCTAL | HEX )
+ * OCTAL ::= '\' OCTAL_CHAR [OCTAL_CHAR [OCTAL_CHAR]]
+ * OCTAL_CHAR ::= (0|1|2|3|4|5|6|7)
+ * HEX ::= '\' (x|X) HEX_CHAR [HEX_CHAR]]
+ * HEX_CHAR ::= (0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|a|b|c|d|e|f)
+ *
+ * INCLUDE_STRING is a filesystem path, with the following %-expansions:
+ * %% - '%'.
+ * %H - The user's home directory (the $HOME environment variable).
+ * %L - The name of the locale specific Compose file (e.g.,
+ * "/usr/share/X11/locale/<localename>/Compose").
+ * %S - The name of the system directory for Compose files (e.g.,
+ * "/usr/share/X11/locale").
+ */
+
+enum rules_token {
+ TOK_END_OF_FILE = 0,
+ TOK_END_OF_LINE,
+ TOK_INCLUDE,
+ TOK_INCLUDE_STRING,
+ TOK_LHS_KEYSYM,
+ TOK_COLON,
+ TOK_BANG,
+ TOK_TILDE,
+ TOK_STRING,
+ TOK_IDENT,
+ TOK_ERROR
+};
+
+/* Values returned with some tokens, like yylval. */
+union lvalue {
+ struct {
+ /* Still \0-terminated. */
+ const char *str;
+ size_t len;
+ } string;
+};
+
+static enum rules_token
+lex(struct scanner *s, union lvalue *val)
+{
+skip_more_whitespace_and_comments:
+ /* Skip spaces. */
+ while (is_space(peek(s)))
+ if (next(s) == '\n')
+ return TOK_END_OF_LINE;
+
+ /* Skip comments. */
+ if (chr(s, '#')) {
+ skip_to_eol(s);
+ goto skip_more_whitespace_and_comments;
+ }
+
+ /* See if we're done. */
+ if (eof(s)) return TOK_END_OF_FILE;
+
+ /* New token. */
+ s->token_line = s->line;
+ s->token_column = s->column;
+ s->buf_pos = 0;
+
+ /* LHS Keysym. */
+ if (chr(s, '<')) {
+ while (peek(s) != '>' && !eol(s) && !eof(s))
+ buf_append(s, next(s));
+ if (!chr(s, '>')) {
+ scanner_err(s, "unterminated keysym literal");
+ return TOK_ERROR;
+ }
+ if (!buf_append(s, '\0')) {
+ scanner_err(s, "keysym literal is too long");
+ return TOK_ERROR;
+ }
+ val->string.str = s->buf;
+ val->string.len = s->buf_pos;
+ return TOK_LHS_KEYSYM;
+ }
+
+ /* Colon. */
+ if (chr(s, ':'))
+ return TOK_COLON;
+ if (chr(s, '!'))
+ return TOK_BANG;
+ if (chr(s, '~'))
+ return TOK_TILDE;
+
+ /* String literal. */
+ if (chr(s, '\"')) {
+ while (!eof(s) && !eol(s) && peek(s) != '\"') {
+ if (chr(s, '\\')) {
+ uint8_t o;
+ if (chr(s, '\\')) {
+ buf_append(s, '\\');
+ }
+ else if (chr(s, '"')) {
+ buf_append(s, '"');
+ }
+ else if (chr(s, 'x') || chr(s, 'X')) {
+ if (hex(s, &o))
+ buf_append(s, (char) o);
+ else
+ scanner_warn(s, "illegal hexadecimal escape sequence in string literal");
+ }
+ else if (oct(s, &o)) {
+ buf_append(s, (char) o);
+ }
+ else {
+ scanner_warn(s, "unknown escape sequence (%c) in string literal", peek(s));
+ /* Ignore. */
+ }
+ } else {
+ buf_append(s, next(s));
+ }
+ }
+ if (!chr(s, '\"')) {
+ scanner_err(s, "unterminated string literal");
+ return TOK_ERROR;
+ }
+ if (!buf_append(s, '\0')) {
+ scanner_err(s, "string literal is too long");
+ return TOK_ERROR;
+ }
+ if (!is_valid_utf8(s->buf, s->buf_pos - 1)) {
+ scanner_err(s, "string literal is not a valid UTF-8 string");
+ return TOK_ERROR;
+ }
+ val->string.str = s->buf;
+ val->string.len = s->buf_pos;
+ return TOK_STRING;
+ }
+
+ /* Identifier or include. */
+ if (is_alpha(peek(s)) || peek(s) == '_') {
+ s->buf_pos = 0;
+ while (is_alnum(peek(s)) || peek(s) == '_')
+ buf_append(s, next(s));
+ if (!buf_append(s, '\0')) {
+ scanner_err(s, "identifier is too long");
+ return TOK_ERROR;
+ }
+
+ if (streq(s->buf, "include"))
+ return TOK_INCLUDE;
+
+ val->string.str = s->buf;
+ val->string.len = s->buf_pos;
+ return TOK_IDENT;
+ }
+
+ /* Discard rest of line. */
+ skip_to_eol(s);
+
+ scanner_err(s, "unrecognized token");
+ return TOK_ERROR;
+}
+
+static enum rules_token
+lex_include_string(struct scanner *s, struct xkb_compose_table *table,
+ union lvalue *val_out)
+{
+ while (is_space(peek(s)))
+ if (next(s) == '\n')
+ return TOK_END_OF_LINE;
+
+ s->token_line = s->line;
+ s->token_column = s->column;
+ s->buf_pos = 0;
+
+ if (!chr(s, '\"')) {
+ scanner_err(s, "include statement must be followed by a path");
+ return TOK_ERROR;
+ }
+
+ while (!eof(s) && !eol(s) && peek(s) != '\"') {
+ if (chr(s, '%')) {
+ if (chr(s, '%')) {
+ buf_append(s, '%');
+ }
+ else if (chr(s, 'H')) {
+ const char *home = secure_getenv("HOME");
+ if (!home) {
+ scanner_err(s, "%%H was used in an include statement, but the HOME environment variable is not set");
+ return TOK_ERROR;
+ }
+ if (!buf_appends(s, home)) {
+ scanner_err(s, "include path after expanding %%H is too long");
+ return TOK_ERROR;
+ }
+ }
+ else if (chr(s, 'L')) {
+ char *path = get_locale_compose_file_path(table->locale);
+ if (!path) {
+ scanner_err(s, "failed to expand %%L to the locale Compose file");
+ return TOK_ERROR;
+ }
+ if (!buf_appends(s, path)) {
+ free(path);
+ scanner_err(s, "include path after expanding %%L is too long");
+ return TOK_ERROR;
+ }
+ free(path);
+ }
+ else if (chr(s, 'S')) {
+ const char *xlocaledir = get_xlocaledir_path();
+ if (!buf_appends(s, xlocaledir)) {
+ scanner_err(s, "include path after expanding %%S is too long");
+ return TOK_ERROR;
+ }
+ }
+ else {
+ scanner_err(s, "unknown %% format (%c) in include statement", peek(s));
+ return TOK_ERROR;
+ }
+ } else {
+ buf_append(s, next(s));
+ }
+ }
+ if (!chr(s, '\"')) {
+ scanner_err(s, "unterminated include statement");
+ return TOK_ERROR;
+ }
+ if (!buf_append(s, '\0')) {
+ scanner_err(s, "include path is too long");
+ return TOK_ERROR;
+ }
+ val_out->string.str = s->buf;
+ val_out->string.len = s->buf_pos;
+ return TOK_INCLUDE_STRING;
+}
+
+struct production {
+ xkb_keysym_t lhs[MAX_LHS_LEN];
+ unsigned int len;
+ xkb_keysym_t keysym;
+ char string[256];
+ /* At least one of these is true. */
+ bool has_keysym;
+ bool has_string;
+
+ /* The matching is as follows: (active_mods & modmask) == mods. */
+ xkb_mod_mask_t modmask;
+ xkb_mod_mask_t mods;
+};
+
+static uint32_t
+add_node(struct xkb_compose_table *table, xkb_keysym_t keysym)
+{
+ struct compose_node new = {
+ .keysym = keysym,
+ .next = 0,
+ .is_leaf = true,
+ };
+ darray_append(table->nodes, new);
+ return darray_size(table->nodes) - 1;
+}
+
+static void
+add_production(struct xkb_compose_table *table, struct scanner *s,
+ const struct production *production)
+{
+ unsigned lhs_pos;
+ uint32_t curr;
+ struct compose_node *node;
+
+ curr = 0;
+ node = &darray_item(table->nodes, curr);
+
+ /*
+ * Insert the sequence to the trie, creating new nodes as needed.
+ *
+ * TODO: This can be sped up a bit by first trying the path that the
+ * previous production took, and only then doing the linear search
+ * through the trie levels. This will work because sequences in the
+ * Compose files are often clustered by a common prefix; especially
+ * in the 1st and 2nd keysyms, which is where the largest variation
+ * (thus, longest search) is.
+ */
+ for (lhs_pos = 0; lhs_pos < production->len; lhs_pos++) {
+ while (production->lhs[lhs_pos] != node->keysym) {
+ if (node->next == 0) {
+ uint32_t next = add_node(table, production->lhs[lhs_pos]);
+ /* Refetch since add_node could have realloc()ed. */
+ node = &darray_item(table->nodes, curr);
+ node->next = next;
+ }
+
+ curr = node->next;
+ node = &darray_item(table->nodes, curr);
+ }
+
+ if (lhs_pos + 1 == production->len)
+ break;
+
+ if (node->is_leaf) {
+ if (node->u.leaf.utf8 != 0 ||
+ node->u.leaf.keysym != XKB_KEY_NoSymbol) {
+ scanner_warn(s, "a sequence already exists which is a prefix of this sequence; overriding");
+ node->u.leaf.utf8 = 0;
+ node->u.leaf.keysym = XKB_KEY_NoSymbol;
+ }
+
+ {
+ uint32_t successor = add_node(table, production->lhs[lhs_pos + 1]);
+ /* Refetch since add_node could have realloc()ed. */
+ node = &darray_item(table->nodes, curr);
+ node->is_leaf = false;
+ node->u.successor = successor;
+ }
+ }
+
+ curr = node->u.successor;
+ node = &darray_item(table->nodes, curr);
+ }
+
+ if (!node->is_leaf) {
+ scanner_warn(s, "this compose sequence is a prefix of another; skipping line");
+ return;
+ }
+
+ if (node->u.leaf.utf8 != 0 || node->u.leaf.keysym != XKB_KEY_NoSymbol) {
+ bool same_string =
+ (node->u.leaf.utf8 == 0 && !production->has_string) ||
+ (
+ node->u.leaf.utf8 != 0 && production->has_string &&
+ streq(&darray_item(table->utf8, node->u.leaf.utf8),
+ production->string)
+ );
+ bool same_keysym =
+ (node->u.leaf.keysym == XKB_KEY_NoSymbol && !production->has_keysym) ||
+ (
+ node->u.leaf.keysym != XKB_KEY_NoSymbol && production->has_keysym &&
+ node->u.leaf.keysym == production->keysym
+ );
+ if (same_string && same_keysym) {
+ scanner_warn(s, "this compose sequence is a duplicate of another; skipping line");
+ return;
+ }
+ scanner_warn(s, "this compose sequence already exists; overriding");
+ }
+
+ if (production->has_string) {
+ node->u.leaf.utf8 = darray_size(table->utf8);
+ darray_append_items(table->utf8, production->string,
+ strlen(production->string) + 1);
+ }
+ if (production->has_keysym) {
+ node->u.leaf.keysym = production->keysym;
+ }
+}
+
+/* Should match resolve_modifier(). */
+#define ALL_MODS_MASK ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3))
+
+static xkb_mod_index_t
+resolve_modifier(const char *name)
+{
+ static const struct {
+ const char *name;
+ xkb_mod_index_t mod;
+ } mods[] = {
+ { "Shift", 0 },
+ { "Ctrl", 2 },
+ { "Alt", 3 },
+ { "Meta", 3 },
+ { "Lock", 1 },
+ { "Caps", 1 },
+ };
+
+ for (unsigned i = 0; i < ARRAY_SIZE(mods); i++)
+ if (streq(name, mods[i].name))
+ return mods[i].mod;
+
+ return XKB_MOD_INVALID;
+}
+
+static bool
+parse(struct xkb_compose_table *table, struct scanner *s,
+ unsigned include_depth);
+
+static bool
+do_include(struct xkb_compose_table *table, struct scanner *s,
+ const char *path, unsigned include_depth)
+{
+ FILE *file;
+ bool ok;
+ char *string;
+ size_t size;
+ struct scanner new_s;
+
+ if (include_depth >= MAX_INCLUDE_DEPTH) {
+ scanner_err(s, "maximum include depth (%d) exceeded; maybe there is an include loop?",
+ MAX_INCLUDE_DEPTH);
+ return false;
+ }
+
+ file = fopen(path, "r");
+ if (!file) {
+ scanner_err(s, "failed to open included Compose file \"%s\": %s",
+ path, strerror(errno));
+ return false;
+ }
+
+ ok = map_file(file, &string, &size);
+ if (!ok) {
+ scanner_err(s, "failed to read included Compose file \"%s\": %s",
+ path, strerror(errno));
+ goto err_file;
+ }
+
+ scanner_init(&new_s, table->ctx, string, size, path, s->priv);
+
+ ok = parse(table, &new_s, include_depth + 1);
+ if (!ok)
+ goto err_unmap;
+
+err_unmap:
+ unmap_file(string, size);
+err_file:
+ fclose(file);
+ return ok;
+}
+
+static bool
+parse(struct xkb_compose_table *table, struct scanner *s,
+ unsigned include_depth)
+{
+ enum rules_token tok;
+ union lvalue val;
+ xkb_keysym_t keysym;
+ struct production production;
+ enum { MAX_ERRORS = 10 };
+ int num_errors = 0;
+
+initial:
+ production.len = 0;
+ production.has_keysym = false;
+ production.has_string = false;
+ production.mods = 0;
+ production.modmask = 0;
+
+ /* fallthrough */
+
+initial_eol:
+ switch (tok = lex(s, &val)) {
+ case TOK_END_OF_LINE:
+ goto initial_eol;
+ case TOK_END_OF_FILE:
+ goto finished;
+ case TOK_INCLUDE:
+ goto include;
+ default:
+ goto lhs_tok;
+ }
+
+include:
+ switch (tok = lex_include_string(s, table, &val)) {
+ case TOK_INCLUDE_STRING:
+ goto include_eol;
+ default:
+ goto unexpected;
+ }
+
+include_eol:
+ switch (tok = lex(s, &val)) {
+ case TOK_END_OF_LINE:
+ if (!do_include(table, s, val.string.str, include_depth))
+ goto fail;
+ goto initial;
+ default:
+ goto unexpected;
+ }
+
+lhs:
+ tok = lex(s, &val);
+lhs_tok:
+ switch (tok) {
+ case TOK_COLON:
+ if (production.len <= 0) {
+ scanner_warn(s, "expected at least one keysym on left-hand side; skipping line");
+ goto skip;
+ }
+ goto rhs;
+ case TOK_IDENT:
+ if (streq(val.string.str, "None")) {
+ production.mods = 0;
+ production.modmask = ALL_MODS_MASK;
+ goto lhs_keysym;
+ }
+ goto lhs_mod_list_tok;
+ case TOK_TILDE:
+ goto lhs_mod_list_tok;
+ case TOK_BANG:
+ production.modmask = ALL_MODS_MASK;
+ goto lhs_mod_list;
+ default:
+ goto lhs_keysym_tok;
+ }
+
+lhs_keysym:
+ tok = lex(s, &val);
+lhs_keysym_tok:
+ switch (tok) {
+ case TOK_LHS_KEYSYM:
+ keysym = xkb_keysym_from_name(val.string.str, XKB_KEYSYM_NO_FLAGS);
+ if (keysym == XKB_KEY_NoSymbol) {
+ scanner_err(s, "unrecognized keysym \"%s\" on left-hand side",
+ val.string.str);
+ goto error;
+ }
+ if (production.len + 1 > MAX_LHS_LEN) {
+ scanner_warn(s, "too many keysyms (%d) on left-hand side; skipping line",
+ MAX_LHS_LEN + 1);
+ goto skip;
+ }
+ production.lhs[production.len++] = keysym;
+ production.mods = 0;
+ production.modmask = 0;
+ goto lhs;
+ default:
+ goto unexpected;
+ }
+
+lhs_mod_list:
+ tok = lex(s, &val);
+lhs_mod_list_tok: {
+ bool tilde = false;
+ xkb_mod_index_t mod;
+
+ if (tok != TOK_TILDE && tok != TOK_IDENT)
+ goto lhs_keysym_tok;
+
+ if (tok == TOK_TILDE) {
+ tilde = true;
+ tok = lex(s, &val);
+ }
+
+ if (tok != TOK_IDENT)
+ goto unexpected;
+
+ mod = resolve_modifier(val.string.str);
+ if (mod == XKB_MOD_INVALID) {
+ scanner_err(s, "unrecognized modifier \"%s\"",
+ val.string.str);
+ goto error;
+ }
+
+ production.modmask |= 1 << mod;
+ if (tilde)
+ production.mods &= ~(1 << mod);
+ else
+ production.mods |= 1 << mod;
+
+ goto lhs_mod_list;
+ }
+
+rhs:
+ switch (tok = lex(s, &val)) {
+ case TOK_STRING:
+ if (production.has_string) {
+ scanner_warn(s, "right-hand side can have at most one string; skipping line");
+ goto skip;
+ }
+ if (val.string.len <= 0) {
+ scanner_warn(s, "right-hand side string must not be empty; skipping line");
+ goto skip;
+ }
+ if (val.string.len >= sizeof(production.string)) {
+ scanner_warn(s, "right-hand side string is too long; skipping line");
+ goto skip;
+ }
+ strcpy(production.string, val.string.str);
+ production.has_string = true;
+ goto rhs;
+ case TOK_IDENT:
+ keysym = xkb_keysym_from_name(val.string.str, XKB_KEYSYM_NO_FLAGS);
+ if (keysym == XKB_KEY_NoSymbol) {
+ scanner_err(s, "unrecognized keysym \"%s\" on right-hand side",
+ val.string.str);
+ goto error;
+ }
+ if (production.has_keysym) {
+ scanner_warn(s, "right-hand side can have at most one keysym; skipping line");
+ goto skip;
+ }
+ production.keysym = keysym;
+ production.has_keysym = true;
+ /* fallthrough */
+ case TOK_END_OF_LINE:
+ if (!production.has_string && !production.has_keysym) {
+ scanner_warn(s, "right-hand side must have at least one of string or keysym; skipping line");
+ goto skip;
+ }
+ add_production(table, s, &production);
+ goto initial;
+ default:
+ goto unexpected;
+ }
+
+unexpected:
+ if (tok != TOK_ERROR)
+ scanner_err(s, "unexpected token");
+error:
+ num_errors++;
+ if (num_errors <= MAX_ERRORS)
+ goto skip;
+
+ scanner_err(s, "too many errors");
+ goto fail;
+
+fail:
+ scanner_err(s, "failed to parse file");
+ return false;
+
+skip:
+ while (tok != TOK_END_OF_LINE && tok != TOK_END_OF_FILE)
+ tok = lex(s, &val);
+ goto initial;
+
+finished:
+ return true;
+}
+
+bool
+parse_string(struct xkb_compose_table *table, const char *string, size_t len,
+ const char *file_name)
+{
+ struct scanner s;
+ scanner_init(&s, table->ctx, string, len, file_name, NULL);
+ if (!parse(table, &s, 0))
+ return false;
+ /* Maybe the allocator can use the excess space. */
+ darray_shrink(table->nodes);
+ darray_shrink(table->utf8);
+ return true;
+}
+
+bool
+parse_file(struct xkb_compose_table *table, FILE *file, const char *file_name)
+{
+ bool ok;
+ char *string;
+ size_t size;
+
+ ok = map_file(file, &string, &size);
+ if (!ok) {
+ log_err(table->ctx, "Couldn't read Compose file %s: %s\n",
+ file_name, strerror(errno));
+ return false;
+ }
+
+ ok = parse_string(table, string, size, file_name);
+ unmap_file(string, size);
+ return ok;
+}
diff --git a/src/3rdparty/xkbcommon/src/compose/parser.h b/src/3rdparty/xkbcommon/src/compose/parser.h
new file mode 100644
index 0000000000..3f64a07402
--- /dev/null
+++ b/src/3rdparty/xkbcommon/src/compose/parser.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2013 Ran Benita <ran234@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef COMPOSE_PARSER_H
+#define COMPOSE_PARSER_H
+
+bool
+parse_string(struct xkb_compose_table *table,
+ const char *string, size_t len,
+ const char *file_name);
+
+bool
+parse_file(struct xkb_compose_table *table,
+ FILE *file, const char *file_name);
+
+#endif
diff --git a/src/3rdparty/xkbcommon/src/compose/paths.c b/src/3rdparty/xkbcommon/src/compose/paths.c
new file mode 100644
index 0000000000..e9d43d7e44
--- /dev/null
+++ b/src/3rdparty/xkbcommon/src/compose/paths.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright © 2014 Ran Benita <ran234@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "utils.h"
+#include "paths.h"
+
+enum resolve_name_direction {
+ LEFT_TO_RIGHT,
+ RIGHT_TO_LEFT,
+};
+
+const char *
+get_xlocaledir_path(void)
+{
+ const char *dir = secure_getenv("XLOCALEDIR");
+ if (!dir)
+ dir = XLOCALEDIR;
+ return dir;
+}
+
+/*
+ * Files like compose.dir have the format LEFT: RIGHT. Lookup @name in
+ * such a file and return its matching value, according to @direction.
+ * @filename is relative to the xlocaledir.
+ */
+static char *
+resolve_name(const char *filename, enum resolve_name_direction direction,
+ const char *name)
+{
+ int ret;
+ bool ok;
+ const char *xlocaledir;
+ char path[512];
+ FILE *file;
+ char *string;
+ size_t string_size;
+ const char *end;
+ const char *s, *left, *right;
+ char *match;
+ size_t left_len, right_len, name_len;
+
+ xlocaledir = get_xlocaledir_path();
+
+ ret = snprintf(path, sizeof(path), "%s/%s", xlocaledir, filename);
+ if (ret < 0 || (size_t) ret >= sizeof(path))
+ return false;
+
+ file = fopen(path, "r");
+ if (!file)
+ return false;
+
+ ok = map_file(file, &string, &string_size);
+ fclose(file);
+ if (!ok)
+ return false;
+
+ s = string;
+ end = string + string_size;
+ name_len = strlen(name);
+ match = NULL;
+
+ while (s < end) {
+ /* Skip spaces. */
+ while (s < end && is_space(*s))
+ s++;
+
+ /* Skip comments. */
+ if (s < end && *s == '#') {
+ while (s < end && *s != '\n')
+ s++;
+ continue;
+ }
+
+ /* Get the left value. */
+ left = s;
+ while (s < end && !is_space(*s) && *s != ':')
+ s++;
+ left_len = s - left;
+
+ /* There's an optional colon between left and right. */
+ if (s < end && *s == ':')
+ s++;
+
+ /* Skip spaces. */
+ while (s < end && is_space(*s))
+ s++;
+
+ /* Get the right value. */
+ right = s;
+ while (s < end && !is_space(*s))
+ s++;
+ right_len = s - right;
+
+ /* Discard rest of line. */
+ while (s < end && *s != '\n')
+ s++;
+
+ if (direction == LEFT_TO_RIGHT) {
+ if (left_len == name_len && memcmp(left, name, left_len) == 0) {
+ match = strndup(right, right_len);
+ break;
+ }
+ }
+ else if (direction == RIGHT_TO_LEFT) {
+ if (right_len == name_len && memcmp(right, name, right_len) == 0) {
+ match = strndup(left, left_len);
+ break;
+ }
+ }
+ }
+
+ unmap_file(string, string_size);
+ return match;
+}
+
+char *
+resolve_locale(const char *locale)
+{
+ char *alias = resolve_name("locale.alias", LEFT_TO_RIGHT, locale);
+ return alias ? alias : strdup(locale);
+}
+
+const char *
+get_xcomposefile_path(void)
+{
+ return secure_getenv("XCOMPOSEFILE");
+}
+
+char *
+get_home_xcompose_file_path(void)
+{
+ int ret;
+ const char *home;
+ char *path;
+
+ home = secure_getenv("HOME");
+ if (!home)
+ return NULL;
+
+ ret = asprintf(&path, "%s/.XCompose", home);
+ if (ret <0)
+ return NULL;
+
+ return path;
+}
+
+char *
+get_locale_compose_file_path(const char *locale)
+{
+ char *resolved;
+ char *path;
+
+ /*
+ * WARNING: Random workaround ahead.
+ *
+ * We currently do not support non-UTF-8 Compose files. The C/POSIX
+ * locale is specified to be the default fallback locale with an
+ * ASCII charset. But for some reason the compose.dir points the C
+ * locale to the iso8859-1/Compose file, which is not ASCII but
+ * ISO8859-1. Since this is bound to happen a lot, and since our API
+ * is UTF-8 based, and since 99% of the time a C locale is really just
+ * a misconfiguration for UTF-8, let's do the most helpful thing.
+ */
+ if (streq(locale, "C"))
+ locale = "en_US.UTF-8";
+
+ resolved = resolve_name("compose.dir", RIGHT_TO_LEFT, locale);
+ if (!resolved)
+ return NULL;
+
+ if (resolved[0] == '/') {
+ path = resolved;
+ }
+ else {
+ const char *xlocaledir = get_xlocaledir_path();
+ int ret = asprintf(&path, "%s/%s", xlocaledir, resolved);
+ free(resolved);
+ if (ret < 0)
+ return NULL;
+ }
+
+ return path;
+}
diff --git a/src/3rdparty/xkbcommon/src/compose/paths.h b/src/3rdparty/xkbcommon/src/compose/paths.h
new file mode 100644
index 0000000000..1d719af1b9
--- /dev/null
+++ b/src/3rdparty/xkbcommon/src/compose/paths.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2014 Ran Benita <ran234@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef COMPOSE_RESOLVE_H
+#define COMPOSE_RESOLVE_H
+
+char *
+resolve_locale(const char *locale);
+
+const char *
+get_xlocaledir_path(void);
+
+const char *
+get_xcomposefile_path(void);
+
+char *
+get_home_xcompose_file_path(void);
+
+char *
+get_locale_compose_file_path(const char *locale);
+
+#endif
diff --git a/src/3rdparty/xkbcommon/src/compose/table.c b/src/3rdparty/xkbcommon/src/compose/table.c
new file mode 100644
index 0000000000..5cd8415850
--- /dev/null
+++ b/src/3rdparty/xkbcommon/src/compose/table.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright © 2013 Ran Benita <ran234@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "utils.h"
+#include "table.h"
+#include "parser.h"
+#include "paths.h"
+
+static struct xkb_compose_table *
+xkb_compose_table_new(struct xkb_context *ctx,
+ const char *locale,
+ enum xkb_compose_format format,
+ enum xkb_compose_compile_flags flags)
+{
+ char *resolved_locale;
+ struct xkb_compose_table *table;
+ struct compose_node root;
+
+ resolved_locale = resolve_locale(locale);
+ if (!resolved_locale)
+ return NULL;
+
+ table = calloc(1, sizeof(*table));
+ if (!table) {
+ free(resolved_locale);
+ return NULL;
+ }
+
+ table->refcnt = 1;
+ table->ctx = xkb_context_ref(ctx);
+
+ table->locale = resolved_locale;
+ table->format = format;
+ table->flags = flags;
+
+ darray_init(table->nodes);
+ darray_init(table->utf8);
+
+ root.keysym = XKB_KEY_NoSymbol;
+ root.next = 0;
+ root.is_leaf = true;
+ root.u.leaf.utf8 = 0;
+ root.u.leaf.keysym = XKB_KEY_NoSymbol;
+ darray_append(table->nodes, root);
+
+ darray_append(table->utf8, '\0');
+
+ return table;
+}
+
+XKB_EXPORT struct xkb_compose_table *
+xkb_compose_table_ref(struct xkb_compose_table *table)
+{
+ table->refcnt++;
+ return table;
+}
+
+XKB_EXPORT void
+xkb_compose_table_unref(struct xkb_compose_table *table)
+{
+ if (!table || --table->refcnt > 0)
+ return;
+ free(table->locale);
+ darray_free(table->nodes);
+ darray_free(table->utf8);
+ xkb_context_unref(table->ctx);
+ free(table);
+}
+
+XKB_EXPORT struct xkb_compose_table *
+xkb_compose_table_new_from_file(struct xkb_context *ctx,
+ FILE *file,
+ const char *locale,
+ enum xkb_compose_format format,
+ enum xkb_compose_compile_flags flags)
+{
+ struct xkb_compose_table *table;
+ bool ok;
+
+ if (flags & ~(XKB_COMPOSE_COMPILE_NO_FLAGS)) {
+ log_err_func(ctx, "unrecognized flags: %#x\n", flags);
+ return NULL;
+ }
+
+ if (format != XKB_COMPOSE_FORMAT_TEXT_V1) {
+ log_err_func(ctx, "unsupported compose format: %d\n", format);
+ return NULL;
+ }
+
+ table = xkb_compose_table_new(ctx, locale, format, flags);
+ if (!table)
+ return NULL;
+
+ ok = parse_file(table, file, "(unknown file)");
+ if (!ok) {
+ xkb_compose_table_unref(table);
+ return NULL;
+ }
+
+ return table;
+}
+
+XKB_EXPORT struct xkb_compose_table *
+xkb_compose_table_new_from_buffer(struct xkb_context *ctx,
+ const char *buffer, size_t length,
+ const char *locale,
+ enum xkb_compose_format format,
+ enum xkb_compose_compile_flags flags)
+{
+ struct xkb_compose_table *table;
+ bool ok;
+
+ if (flags & ~(XKB_COMPOSE_COMPILE_NO_FLAGS)) {
+ log_err_func(ctx, "unrecognized flags: %#x\n", flags);
+ return NULL;
+ }
+
+ if (format != XKB_COMPOSE_FORMAT_TEXT_V1) {
+ log_err_func(ctx, "unsupported compose format: %d\n", format);
+ return NULL;
+ }
+
+ table = xkb_compose_table_new(ctx, locale, format, flags);
+ if (!table)
+ return NULL;
+
+ ok = parse_string(table, buffer, length, "(input string)");
+ if (!ok) {
+ xkb_compose_table_unref(table);
+ return NULL;
+ }
+
+ return table;
+}
+
+XKB_EXPORT struct xkb_compose_table *
+xkb_compose_table_new_from_locale(struct xkb_context *ctx,
+ const char *locale,
+ enum xkb_compose_compile_flags flags)
+{
+ struct xkb_compose_table *table;
+ char *path = NULL;
+ const char *cpath;
+ FILE *file;
+ bool ok;
+
+ if (flags & ~(XKB_COMPOSE_COMPILE_NO_FLAGS)) {
+ log_err_func(ctx, "unrecognized flags: %#x\n", flags);
+ return NULL;
+ }
+
+ table = xkb_compose_table_new(ctx, locale, XKB_COMPOSE_FORMAT_TEXT_V1,
+ flags);
+ if (!table)
+ return NULL;
+
+ cpath = get_xcomposefile_path();
+ if (cpath) {
+ file = fopen(cpath, "r");
+ if (file)
+ goto found_path;
+ }
+
+ cpath = path = get_home_xcompose_file_path();
+ if (path) {
+ file = fopen(path, "r");
+ if (file)
+ goto found_path;
+ }
+ free(path);
+ path = NULL;
+
+ cpath = path = get_locale_compose_file_path(table->locale);
+ if (path) {
+ file = fopen(path, "r");
+ if (file)
+ goto found_path;
+ }
+ free(path);
+ path = NULL;
+
+ log_err(ctx, "couldn't find a Compose file for locale \"%s\"\n", locale);
+ xkb_compose_table_unref(table);
+ return NULL;
+
+found_path:
+ ok = parse_file(table, file, cpath);
+ fclose(file);
+ if (!ok) {
+ xkb_compose_table_unref(table);
+ return NULL;
+ }
+
+ log_dbg(ctx, "created compose table from locale %s with path %s\n",
+ table->locale, path);
+
+ free(path);
+ return table;
+}
diff --git a/src/3rdparty/xkbcommon/src/compose/table.h b/src/3rdparty/xkbcommon/src/compose/table.h
new file mode 100644
index 0000000000..05a415ffa3
--- /dev/null
+++ b/src/3rdparty/xkbcommon/src/compose/table.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright © 2013 Ran Benita <ran234@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef COMPOSE_COMPOSE_H
+#define COMPOSE_COMPOSE_H
+
+#include "xkbcommon/xkbcommon-compose.h"
+#include "utils.h"
+#include "context.h"
+
+/*
+ * The compose table data structure is a simple trie. An example will
+ * help. Given these sequences:
+ *
+ * <A> <B> : "first" dead_a
+ * <A> <C> <D> : "second" dead_b
+ * <E> <F> : "third" dead_c
+ *
+ * the trie would look like:
+ *
+ * [root] ---> [<A>] -----------------> [<E>] -#
+ * | | |
+ * # v v
+ * [<B>] ---> [<C>] -# [<F>] -#
+ * | | -
+ * # v #
+ * [<D>] -#
+ * |
+ * #
+ * where:
+ * - [root] is a special empty root node.
+ * - [<X>] is a node for a sequence keysym <X>.
+ * - right arrows are `next` pointers.
+ * - down arrows are `successor` pointers.
+ * - # is a nil pointer.
+ *
+ * The nodes are all kept in a contiguous array. Pointers are represented
+ * as integer offsets into this array. A nil pointer is represented as 0
+ * (which, helpfully, is the offset of the empty root node).
+ *
+ * Nodes without a successor are leaf nodes. Since a sequence cannot be a
+ * prefix of another, these are exactly the nodes which terminate the
+ * sequences (in a bijective manner).
+ *
+ * A leaf contains the result data of its sequence. The result keysym is
+ * contained in the node struct itself; the result UTF-8 string is a byte
+ * offset into an array of the form "\0first\0second\0third" (the initial
+ * \0 is so offset 0 points to an empty string).
+ */
+
+struct compose_node {
+ xkb_keysym_t keysym;
+ /* Offset into xkb_compose_table::nodes. */
+ unsigned int next:31;
+ bool is_leaf:1;
+
+ union {
+ /* Offset into xkb_compose_table::nodes. */
+ uint32_t successor;
+ struct {
+ /* Offset into xkb_compose_table::utf8. */
+ uint32_t utf8;
+ xkb_keysym_t keysym;
+ } leaf;
+ } u;
+};
+
+struct xkb_compose_table {
+ int refcnt;
+ enum xkb_compose_format format;
+ enum xkb_compose_compile_flags flags;
+ struct xkb_context *ctx;
+
+ char *locale;
+
+ darray_char utf8;
+ darray(struct compose_node) nodes;
+};
+
+#endif
diff --git a/src/3rdparty/xkbcommon/src/context.c b/src/3rdparty/xkbcommon/src/context.c
index e9c52ebeee..50993e108a 100644
--- a/src/3rdparty/xkbcommon/src/context.c
+++ b/src/3rdparty/xkbcommon/src/context.c
@@ -75,12 +75,16 @@ err:
XKB_EXPORT int
xkb_context_include_path_append_default(struct xkb_context *ctx)
{
- const char *home;
+ const char *home, *root;
char *user_path;
int err;
int ret = 0;
- ret |= xkb_context_include_path_append(ctx, DFLT_XKB_CONFIG_ROOT);
+ root = secure_getenv("XKB_CONFIG_ROOT");
+ if (root != NULL)
+ ret |= xkb_context_include_path_append(ctx, root);
+ else
+ ret |= xkb_context_include_path_append(ctx, DFLT_XKB_CONFIG_ROOT);
home = secure_getenv("HOME");
if (!home)
diff --git a/src/3rdparty/xkbcommon/src/darray.h b/src/3rdparty/xkbcommon/src/darray.h
index d3fe37b089..8e87c942ee 100644
--- a/src/3rdparty/xkbcommon/src/darray.h
+++ b/src/3rdparty/xkbcommon/src/darray.h
@@ -23,7 +23,7 @@
#ifndef CCAN_DARRAY_H
#define CCAN_DARRAY_H
-/* Originally taken from: http://ccodearchive.net/info/darray.html
+/* Originally taken from: https://ccodearchive.net/info/darray.html
* But modified for libxkbcommon. */
#include <stdlib.h>
@@ -44,6 +44,13 @@
darray_init(arr); \
} while (0)
+#define darray_steal(arr, to, to_size) do { \
+ *(to) = (arr).item; \
+ if (to_size) \
+ *(unsigned int *) (to_size) = (arr).size; \
+ darray_init(arr); \
+} while (0)
+
/*
* Typedefs for darrays of common types. These are useful
* when you want to pass a pointer to an darray(T) around.
@@ -78,7 +85,6 @@ typedef darray (unsigned long) darray_ulong;
#define darray_item(arr, i) ((arr).item[i])
#define darray_size(arr) ((arr).size)
#define darray_empty(arr) ((arr).size == 0)
-#define darray_mem(arr, offset) ((arr).item + (offset))
/*** Insertion (single item) ***/
@@ -98,12 +104,16 @@ typedef darray (unsigned long) darray_ulong;
#define darray_from_items(arr, items, count) do { \
unsigned __count = (count); \
darray_resize(arr, __count); \
- memcpy((arr).item, items, __count * sizeof(*(arr).item)); \
+ if (__count != 0) \
+ memcpy((arr).item, items, __count * sizeof(*(arr).item)); \
} while (0)
#define darray_copy(arr_to, arr_from) \
darray_from_items((arr_to), (arr_from).item, (arr_from).size)
+#define darray_concat(arr_to, arr_from) \
+ darray_append_items((arr_to), (arr_from).item, (arr_from).size)
+
/*** String buffer ***/
#define darray_append_string(arr, str) do { \
@@ -160,6 +170,12 @@ typedef darray (unsigned long) darray_ulong;
sizeof(*(arr).item))); \
} while (0)
+#define darray_shrink(arr) do { \
+ if ((arr).size > 0) \
+ (arr).item = realloc((arr).item, \
+ ((arr).alloc = (arr).size) * sizeof(*(arr).item)); \
+} while (0)
+
static inline unsigned
darray_next_alloc(unsigned alloc, unsigned need, unsigned itemSize)
{
@@ -190,7 +206,4 @@ darray_next_alloc(unsigned alloc, unsigned need, unsigned itemSize)
(idx) < (arr).size; \
(idx)++, (val)++)
-#define darray_foreach_reverse(i, arr) \
- for ((i) = &(arr).item[(arr).size]; (i)-- > &(arr).item[0]; )
-
#endif /* CCAN_DARRAY_H */
diff --git a/src/3rdparty/xkbcommon/src/keymap-priv.c b/src/3rdparty/xkbcommon/src/keymap-priv.c
index 2b3f8cde0c..fffb2fd30d 100644
--- a/src/3rdparty/xkbcommon/src/keymap-priv.c
+++ b/src/3rdparty/xkbcommon/src/keymap-priv.c
@@ -29,23 +29,25 @@
static void
update_builtin_keymap_fields(struct xkb_keymap *keymap)
{
- struct xkb_context *ctx = keymap->ctx;
- const struct xkb_mod builtin_mods[] = {
- { .name = xkb_atom_intern_literal(ctx, "Shift"), .type = MOD_REAL },
- { .name = xkb_atom_intern_literal(ctx, "Lock"), .type = MOD_REAL },
- { .name = xkb_atom_intern_literal(ctx, "Control"), .type = MOD_REAL },
- { .name = xkb_atom_intern_literal(ctx, "Mod1"), .type = MOD_REAL },
- { .name = xkb_atom_intern_literal(ctx, "Mod2"), .type = MOD_REAL },
- { .name = xkb_atom_intern_literal(ctx, "Mod3"), .type = MOD_REAL },
- { .name = xkb_atom_intern_literal(ctx, "Mod4"), .type = MOD_REAL },
- { .name = xkb_atom_intern_literal(ctx, "Mod5"), .type = MOD_REAL },
+ /* Predefined (AKA real, core, X11) modifiers. The order is important! */
+ static const char *const builtin_mods[] = {
+ [0] = "Shift",
+ [1] = "Lock",
+ [2] = "Control",
+ [3] = "Mod1",
+ [4] = "Mod2",
+ [5] = "Mod3",
+ [6] = "Mod4",
+ [7] = "Mod5"
};
- /*
- * Add predefined (AKA real, core, X11) modifiers.
- * The order is important!
- */
- darray_append_items(keymap->mods, builtin_mods, ARRAY_SIZE(builtin_mods));
+ for (unsigned i = 0; i < ARRAY_SIZE(builtin_mods); i++) {
+ keymap->mods.mods[i].name = xkb_atom_intern(keymap->ctx,
+ builtin_mods[i],
+ strlen(builtin_mods[i]));
+ keymap->mods.mods[i].type = MOD_REAL;
+ }
+ keymap->mods.num_mods = ARRAY_SIZE(builtin_mods);
}
struct xkb_keymap *
@@ -75,7 +77,7 @@ XkbKeyByName(struct xkb_keymap *keymap, xkb_atom_t name, bool use_aliases)
{
struct xkb_key *key;
- xkb_foreach_key(key, keymap)
+ xkb_keys_foreach(key, keymap)
if (key->name == name)
return key;
@@ -89,7 +91,7 @@ XkbKeyByName(struct xkb_keymap *keymap, xkb_atom_t name, bool use_aliases)
}
xkb_atom_t
-XkbResolveKeyAlias(struct xkb_keymap *keymap, xkb_atom_t name)
+XkbResolveKeyAlias(const struct xkb_keymap *keymap, xkb_atom_t name)
{
for (unsigned i = 0; i < keymap->num_key_aliases; i++)
if (keymap->key_aliases[i].alias == name)
@@ -116,8 +118,33 @@ XkbEscapeMapName(char *name)
return;
while (*name) {
- if (!(legal[*name / 8] & (1 << (*name % 8))))
+ unsigned char c = *name;
+ if (!(legal[c / 8] & (1 << (c % 8))))
*name = '_';
name++;
}
}
+
+xkb_mod_index_t
+XkbModNameToIndex(const struct xkb_mod_set *mods, xkb_atom_t name,
+ enum mod_type type)
+{
+ xkb_mod_index_t i;
+ const struct xkb_mod *mod;
+
+ xkb_mods_enumerate(i, mod, mods)
+ if ((mod->type & type) && name == mod->name)
+ return i;
+
+ return XKB_MOD_INVALID;
+}
+
+bool
+XkbLevelsSameSyms(const struct xkb_level *a, const struct xkb_level *b)
+{
+ if (a->num_syms != b->num_syms)
+ return false;
+ if (a->num_syms <= 1)
+ return a->u.sym == b->u.sym;
+ return memcmp(a->u.syms, b->u.syms, sizeof(*a->u.syms) * a->num_syms) == 0;
+}
diff --git a/src/3rdparty/xkbcommon/src/keymap.c b/src/3rdparty/xkbcommon/src/keymap.c
new file mode 100644
index 0000000000..859c64a556
--- /dev/null
+++ b/src/3rdparty/xkbcommon/src/keymap.c
@@ -0,0 +1,519 @@
+/**
+ * Copyright © 2012 Intel Corporation
+ * Copyright © 2012 Ran Benita <ran234@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Daniel Stone <daniel@fooishbar.org>
+ */
+
+/************************************************************
+ * Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software and its documentation for any purpose and without
+ * fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting
+ * documentation, and that the name of Silicon Graphics not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific prior written permission.
+ * Silicon Graphics makes no representation about the suitability
+ * of this software for any purpose. It is provided "as is"
+ * without any express or implied warranty.
+ *
+ * SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+ * GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+ * THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * ********************************************************/
+
+#include "keymap.h"
+#include "text.h"
+
+XKB_EXPORT struct xkb_keymap *
+xkb_keymap_ref(struct xkb_keymap *keymap)
+{
+ keymap->refcnt++;
+ return keymap;
+}
+
+XKB_EXPORT void
+xkb_keymap_unref(struct xkb_keymap *keymap)
+{
+ if (!keymap || --keymap->refcnt > 0)
+ return;
+
+ if (keymap->keys) {
+ struct xkb_key *key;
+ xkb_keys_foreach(key, keymap) {
+ if (key->groups) {
+ for (unsigned i = 0; i < key->num_groups; i++) {
+ if (key->groups[i].levels) {
+ for (unsigned j = 0; j < XkbKeyNumLevels(key, i); j++)
+ if (key->groups[i].levels[j].num_syms > 1)
+ free(key->groups[i].levels[j].u.syms);
+ free(key->groups[i].levels);
+ }
+ }
+ free(key->groups);
+ }
+ }
+ free(keymap->keys);
+ }
+ if (keymap->types) {
+ for (unsigned i = 0; i < keymap->num_types; i++) {
+ free(keymap->types[i].entries);
+ free(keymap->types[i].level_names);
+ }
+ free(keymap->types);
+ }
+ free(keymap->sym_interprets);
+ free(keymap->key_aliases);
+ free(keymap->group_names);
+ free(keymap->keycodes_section_name);
+ free(keymap->symbols_section_name);
+ free(keymap->types_section_name);
+ free(keymap->compat_section_name);
+ xkb_context_unref(keymap->ctx);
+ free(keymap);
+}
+
+static const struct xkb_keymap_format_ops *
+get_keymap_format_ops(enum xkb_keymap_format format)
+{
+ static const struct xkb_keymap_format_ops *keymap_format_ops[] = {
+ [XKB_KEYMAP_FORMAT_TEXT_V1] = &text_v1_keymap_format_ops,
+ };
+
+ if ((int) format < 0 || (int) format >= (int) ARRAY_SIZE(keymap_format_ops))
+ return NULL;
+
+ return keymap_format_ops[(int) format];
+}
+
+XKB_EXPORT struct xkb_keymap *
+xkb_keymap_new_from_names(struct xkb_context *ctx,
+ const struct xkb_rule_names *rmlvo_in,
+ enum xkb_keymap_compile_flags flags)
+{
+ struct xkb_keymap *keymap;
+ struct xkb_rule_names rmlvo;
+ const enum xkb_keymap_format format = XKB_KEYMAP_FORMAT_TEXT_V1;
+ const struct xkb_keymap_format_ops *ops;
+
+ ops = get_keymap_format_ops(format);
+ if (!ops || !ops->keymap_new_from_names) {
+ log_err_func(ctx, "unsupported keymap format: %d\n", format);
+ return NULL;
+ }
+
+ if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) {
+ log_err_func(ctx, "unrecognized flags: %#x\n", flags);
+ return NULL;
+ }
+
+ keymap = xkb_keymap_new(ctx, format, flags);
+ if (!keymap)
+ return NULL;
+
+ if (rmlvo_in)
+ rmlvo = *rmlvo_in;
+ else
+ memset(&rmlvo, 0, sizeof(rmlvo));
+ xkb_context_sanitize_rule_names(ctx, &rmlvo);
+
+ if (!ops->keymap_new_from_names(keymap, &rmlvo)) {
+ xkb_keymap_unref(keymap);
+ return NULL;
+ }
+
+ return keymap;
+}
+
+XKB_EXPORT struct xkb_keymap *
+xkb_keymap_new_from_string(struct xkb_context *ctx,
+ const char *string,
+ enum xkb_keymap_format format,
+ enum xkb_keymap_compile_flags flags)
+{
+ return xkb_keymap_new_from_buffer(ctx, string, strlen(string),
+ format, flags);
+}
+
+XKB_EXPORT struct xkb_keymap *
+xkb_keymap_new_from_buffer(struct xkb_context *ctx,
+ const char *buffer, size_t length,
+ enum xkb_keymap_format format,
+ enum xkb_keymap_compile_flags flags)
+{
+ struct xkb_keymap *keymap;
+ const struct xkb_keymap_format_ops *ops;
+
+ ops = get_keymap_format_ops(format);
+ if (!ops || !ops->keymap_new_from_string) {
+ log_err_func(ctx, "unsupported keymap format: %d\n", format);
+ return NULL;
+ }
+
+ if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) {
+ log_err_func(ctx, "unrecognized flags: %#x\n", flags);
+ return NULL;
+ }
+
+ if (!buffer) {
+ log_err_func1(ctx, "no buffer specified\n");
+ return NULL;
+ }
+
+ keymap = xkb_keymap_new(ctx, format, flags);
+ if (!keymap)
+ return NULL;
+
+ if (!ops->keymap_new_from_string(keymap, buffer, length)) {
+ xkb_keymap_unref(keymap);
+ return NULL;
+ }
+
+ return keymap;
+}
+
+XKB_EXPORT struct xkb_keymap *
+xkb_keymap_new_from_file(struct xkb_context *ctx,
+ FILE *file,
+ enum xkb_keymap_format format,
+ enum xkb_keymap_compile_flags flags)
+{
+ struct xkb_keymap *keymap;
+ const struct xkb_keymap_format_ops *ops;
+
+ ops = get_keymap_format_ops(format);
+ if (!ops || !ops->keymap_new_from_file) {
+ log_err_func(ctx, "unsupported keymap format: %d\n", format);
+ return NULL;
+ }
+
+ if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) {
+ log_err_func(ctx, "unrecognized flags: %#x\n", flags);
+ return NULL;
+ }
+
+ if (!file) {
+ log_err_func1(ctx, "no file specified\n");
+ return NULL;
+ }
+
+ keymap = xkb_keymap_new(ctx, format, flags);
+ if (!keymap)
+ return NULL;
+
+ if (!ops->keymap_new_from_file(keymap, file)) {
+ xkb_keymap_unref(keymap);
+ return NULL;
+ }
+
+ return keymap;
+}
+
+XKB_EXPORT char *
+xkb_keymap_get_as_string(struct xkb_keymap *keymap,
+ enum xkb_keymap_format format)
+{
+ const struct xkb_keymap_format_ops *ops;
+
+ if (format == XKB_KEYMAP_USE_ORIGINAL_FORMAT)
+ format = keymap->format;
+
+ ops = get_keymap_format_ops(format);
+ if (!ops || !ops->keymap_get_as_string) {
+ log_err_func(keymap->ctx, "unsupported keymap format: %d\n", format);
+ return NULL;
+ }
+
+ return ops->keymap_get_as_string(keymap);
+}
+
+/**
+ * Returns the total number of modifiers active in the keymap.
+ */
+XKB_EXPORT xkb_mod_index_t
+xkb_keymap_num_mods(struct xkb_keymap *keymap)
+{
+ return keymap->mods.num_mods;
+}
+
+/**
+ * Return the name for a given modifier.
+ */
+XKB_EXPORT const char *
+xkb_keymap_mod_get_name(struct xkb_keymap *keymap, xkb_mod_index_t idx)
+{
+ if (idx >= keymap->mods.num_mods)
+ return NULL;
+
+ return xkb_atom_text(keymap->ctx, keymap->mods.mods[idx].name);
+}
+
+/**
+ * Returns the index for a named modifier.
+ */
+XKB_EXPORT xkb_mod_index_t
+xkb_keymap_mod_get_index(struct xkb_keymap *keymap, const char *name)
+{
+ xkb_atom_t atom;
+
+ atom = xkb_atom_lookup(keymap->ctx, name);
+ if (atom == XKB_ATOM_NONE)
+ return XKB_MOD_INVALID;
+
+ return XkbModNameToIndex(&keymap->mods, atom, MOD_BOTH);
+}
+
+/**
+ * Return the total number of active groups in the keymap.
+ */
+XKB_EXPORT xkb_layout_index_t
+xkb_keymap_num_layouts(struct xkb_keymap *keymap)
+{
+ return keymap->num_groups;
+}
+
+/**
+ * Returns the name for a given group.
+ */
+XKB_EXPORT const char *
+xkb_keymap_layout_get_name(struct xkb_keymap *keymap, xkb_layout_index_t idx)
+{
+ if (idx >= keymap->num_group_names)
+ return NULL;
+
+ return xkb_atom_text(keymap->ctx, keymap->group_names[idx]);
+}
+
+/**
+ * Returns the index for a named layout.
+ */
+XKB_EXPORT xkb_layout_index_t
+xkb_keymap_layout_get_index(struct xkb_keymap *keymap, const char *name)
+{
+ xkb_atom_t atom = xkb_atom_lookup(keymap->ctx, name);
+ xkb_layout_index_t i;
+
+ if (atom == XKB_ATOM_NONE)
+ return XKB_LAYOUT_INVALID;
+
+ for (i = 0; i < keymap->num_group_names; i++)
+ if (keymap->group_names[i] == atom)
+ return i;
+
+ return XKB_LAYOUT_INVALID;
+}
+
+/**
+ * Returns the number of layouts active for a particular key.
+ */
+XKB_EXPORT xkb_layout_index_t
+xkb_keymap_num_layouts_for_key(struct xkb_keymap *keymap, xkb_keycode_t kc)
+{
+ const struct xkb_key *key = XkbKey(keymap, kc);
+
+ if (!key)
+ return 0;
+
+ return key->num_groups;
+}
+
+/**
+ * Returns the number of levels active for a particular key and layout.
+ */
+XKB_EXPORT xkb_level_index_t
+xkb_keymap_num_levels_for_key(struct xkb_keymap *keymap, xkb_keycode_t kc,
+ xkb_layout_index_t layout)
+{
+ const struct xkb_key *key = XkbKey(keymap, kc);
+
+ if (!key)
+ return 0;
+
+ layout = XkbWrapGroupIntoRange(layout, key->num_groups,
+ key->out_of_range_group_action,
+ key->out_of_range_group_number);
+ if (layout == XKB_LAYOUT_INVALID)
+ return 0;
+
+ return XkbKeyNumLevels(key, layout);
+}
+
+/**
+ * Return the total number of LEDs in the keymap.
+ */
+XKB_EXPORT xkb_led_index_t
+xkb_keymap_num_leds(struct xkb_keymap *keymap)
+{
+ return keymap->num_leds;
+}
+
+/**
+ * Returns the name for a given LED.
+ */
+XKB_EXPORT const char *
+xkb_keymap_led_get_name(struct xkb_keymap *keymap, xkb_led_index_t idx)
+{
+ if (idx >= keymap->num_leds)
+ return NULL;
+
+ return xkb_atom_text(keymap->ctx, keymap->leds[idx].name);
+}
+
+/**
+ * Returns the index for a named LED.
+ */
+XKB_EXPORT xkb_led_index_t
+xkb_keymap_led_get_index(struct xkb_keymap *keymap, const char *name)
+{
+ xkb_atom_t atom = xkb_atom_lookup(keymap->ctx, name);
+ xkb_led_index_t i;
+ const struct xkb_led *led;
+
+ if (atom == XKB_ATOM_NONE)
+ return XKB_LED_INVALID;
+
+ xkb_leds_enumerate(i, led, keymap)
+ if (led->name == atom)
+ return i;
+
+ return XKB_LED_INVALID;
+}
+
+/**
+ * As below, but takes an explicit layout/level rather than state.
+ */
+XKB_EXPORT int
+xkb_keymap_key_get_syms_by_level(struct xkb_keymap *keymap,
+ xkb_keycode_t kc,
+ xkb_layout_index_t layout,
+ xkb_level_index_t level,
+ const xkb_keysym_t **syms_out)
+{
+ const struct xkb_key *key = XkbKey(keymap, kc);
+ int num_syms;
+
+ if (!key)
+ goto err;
+
+ layout = XkbWrapGroupIntoRange(layout, key->num_groups,
+ key->out_of_range_group_action,
+ key->out_of_range_group_number);
+ if (layout == XKB_LAYOUT_INVALID)
+ goto err;
+
+ if (level >= XkbKeyNumLevels(key, layout))
+ goto err;
+
+ num_syms = key->groups[layout].levels[level].num_syms;
+ if (num_syms == 0)
+ goto err;
+
+ if (num_syms == 1)
+ *syms_out = &key->groups[layout].levels[level].u.sym;
+ else
+ *syms_out = key->groups[layout].levels[level].u.syms;
+
+ return num_syms;
+
+err:
+ *syms_out = NULL;
+ return 0;
+}
+
+XKB_EXPORT xkb_keycode_t
+xkb_keymap_min_keycode(struct xkb_keymap *keymap)
+{
+ return keymap->min_key_code;
+}
+
+XKB_EXPORT xkb_keycode_t
+xkb_keymap_max_keycode(struct xkb_keymap *keymap)
+{
+ return keymap->max_key_code;
+}
+
+XKB_EXPORT void
+xkb_keymap_key_for_each(struct xkb_keymap *keymap, xkb_keymap_key_iter_t iter,
+ void *data)
+{
+ struct xkb_key *key;
+
+ xkb_keys_foreach(key, keymap)
+ iter(keymap, key->keycode, data);
+}
+
+XKB_EXPORT const char *
+xkb_keymap_key_get_name(struct xkb_keymap *keymap, xkb_keycode_t kc)
+{
+ const struct xkb_key *key = XkbKey(keymap, kc);
+
+ if (!key)
+ return NULL;
+
+ return xkb_atom_text(keymap->ctx, key->name);
+}
+
+XKB_EXPORT xkb_keycode_t
+xkb_keymap_key_by_name(struct xkb_keymap *keymap, const char *name)
+{
+ struct xkb_key *key;
+ xkb_atom_t atom;
+
+ atom = xkb_atom_lookup(keymap->ctx, name);
+ if (atom) {
+ xkb_atom_t ratom = XkbResolveKeyAlias(keymap, atom);
+ if (ratom)
+ atom = ratom;
+ }
+ if (!atom)
+ return XKB_KEYCODE_INVALID;
+
+ xkb_keys_foreach(key, keymap) {
+ if (key->name == atom)
+ return key->keycode;
+ }
+
+ return XKB_KEYCODE_INVALID;
+}
+
+/**
+ * Simple boolean specifying whether or not the key should repeat.
+ */
+XKB_EXPORT int
+xkb_keymap_key_repeats(struct xkb_keymap *keymap, xkb_keycode_t kc)
+{
+ const struct xkb_key *key = XkbKey(keymap, kc);
+
+ if (!key)
+ return 0;
+
+ return key->repeats;
+}
diff --git a/src/3rdparty/xkbcommon/src/keymap.h b/src/3rdparty/xkbcommon/src/keymap.h
index 39ac4209ae..c15052bc7f 100644
--- a/src/3rdparty/xkbcommon/src/keymap.h
+++ b/src/3rdparty/xkbcommon/src/keymap.h
@@ -228,7 +228,6 @@ struct xkb_pointer_button_action {
struct xkb_private_action {
enum xkb_action_type type;
- enum xkb_action_flags flags;
uint8_t data[7];
};
@@ -254,6 +253,7 @@ struct xkb_key_type {
xkb_atom_t name;
struct xkb_mods mods;
xkb_level_index_t num_levels;
+ unsigned int num_level_names;
xkb_atom_t *level_names;
unsigned int num_entries;
struct xkb_key_type_entry *entries;
@@ -325,7 +325,7 @@ struct xkb_group {
bool explicit_type;
/* Points to a type in keymap->types. */
const struct xkb_key_type *type;
- /* Use XkbKeyGroupWidth for the number of levels. */
+ /* Use XkbKeyNumLevels for the number of levels. */
struct xkb_level *levels;
};
@@ -353,6 +353,11 @@ struct xkb_mod {
xkb_mod_mask_t mapping; /* vmod -> real mod mapping */
};
+struct xkb_mod_set {
+ struct xkb_mod mods[XKB_MAX_MODS];
+ unsigned int num_mods;
+};
+
/* Common keyboard description structure */
struct xkb_keymap {
struct xkb_context *ctx;
@@ -377,7 +382,7 @@ struct xkb_keymap {
unsigned int num_sym_interprets;
struct xkb_sym_interpret *sym_interprets;
- darray(struct xkb_mod) mods;
+ struct xkb_mod_set mods;
/* Number of groups in the key with the most groups. */
xkb_layout_index_t num_groups;
@@ -385,7 +390,8 @@ struct xkb_keymap {
xkb_layout_index_t num_group_names;
xkb_atom_t *group_names;
- darray(struct xkb_led) leds;
+ struct xkb_led leds[XKB_MAX_LEDS];
+ unsigned int num_leds;
char *keycodes_section_name;
char *symbols_section_name;
@@ -393,10 +399,30 @@ struct xkb_keymap {
char *compat_section_name;
};
-#define xkb_foreach_key(iter, keymap) \
- for (iter = keymap->keys + keymap->min_key_code; \
- iter <= keymap->keys + keymap->max_key_code; \
- iter++)
+#define xkb_keys_foreach(iter, keymap) \
+ for ((iter) = (keymap)->keys + (keymap)->min_key_code; \
+ (iter) <= (keymap)->keys + (keymap)->max_key_code; \
+ (iter)++)
+
+#define xkb_mods_foreach(iter, mods_) \
+ for ((iter) = (mods_)->mods; \
+ (iter) < (mods_)->mods + (mods_)->num_mods; \
+ (iter)++)
+
+#define xkb_mods_enumerate(idx, iter, mods_) \
+ for ((idx) = 0, (iter) = (mods_)->mods; \
+ (idx) < (mods_)->num_mods; \
+ (idx)++, (iter)++)
+
+#define xkb_leds_foreach(iter, keymap) \
+ for ((iter) = (keymap)->leds; \
+ (iter) < (keymap)->leds + (keymap)->num_leds; \
+ (iter)++)
+
+#define xkb_leds_enumerate(idx, iter, keymap) \
+ for ((idx) = 0, (iter) = (keymap)->leds; \
+ (idx) < (keymap)->num_leds; \
+ (idx)++, (iter)++)
static inline const struct xkb_key *
XkbKey(struct xkb_keymap *keymap, xkb_keycode_t kc)
@@ -407,7 +433,7 @@ XkbKey(struct xkb_keymap *keymap, xkb_keycode_t kc)
}
static inline xkb_level_index_t
-XkbKeyGroupWidth(const struct xkb_key *key, xkb_layout_index_t layout)
+XkbKeyNumLevels(const struct xkb_key *key, xkb_layout_index_t layout)
{
return key->groups[layout].type->num_levels;
}
@@ -421,17 +447,27 @@ struct xkb_key *
XkbKeyByName(struct xkb_keymap *keymap, xkb_atom_t name, bool use_aliases);
xkb_atom_t
-XkbResolveKeyAlias(struct xkb_keymap *keymap, xkb_atom_t name);
+XkbResolveKeyAlias(const struct xkb_keymap *keymap, xkb_atom_t name);
void
XkbEscapeMapName(char *name);
+xkb_mod_index_t
+XkbModNameToIndex(const struct xkb_mod_set *mods, xkb_atom_t name,
+ enum mod_type type);
+
+bool
+XkbLevelsSameSyms(const struct xkb_level *a, const struct xkb_level *b);
+
xkb_layout_index_t
-wrap_group_into_range(int32_t group,
+XkbWrapGroupIntoRange(int32_t group,
xkb_layout_index_t num_groups,
enum xkb_range_exceed_type out_of_range_group_action,
xkb_layout_index_t out_of_range_group_number);
+xkb_mod_mask_t
+mod_mask_get_effective(struct xkb_keymap *keymap, xkb_mod_mask_t mods);
+
struct xkb_keymap_format_ops {
bool (*keymap_new_from_names)(struct xkb_keymap *keymap,
const struct xkb_rule_names *names);
diff --git a/src/3rdparty/xkbcommon/src/keysym-utf.c b/src/3rdparty/xkbcommon/src/keysym-utf.c
index ffe2cea48e..c0e76f54da 100644
--- a/src/3rdparty/xkbcommon/src/keysym-utf.c
+++ b/src/3rdparty/xkbcommon/src/keysym-utf.c
@@ -521,7 +521,7 @@ static const struct codepair keysymtab[] = {
{ 0x0aa8, 0x200a }, /* hairspace   HAIR SPACE */
{ 0x0aa9, 0x2014 }, /* emdash — EM DASH */
{ 0x0aaa, 0x2013 }, /* endash – EN DASH */
- /* 0x0aac signifblank ? ??? */
+ { 0x0aac, 0x2423 }, /* signifblank ⣠OPEN BOX */
{ 0x0aae, 0x2026 }, /* ellipsis … HORIZONTAL ELLIPSIS */
{ 0x0aaf, 0x2025 }, /* doubbaselinedot ‥ TWO DOT LEADER */
{ 0x0ab0, 0x2153 }, /* onethird â…“ VULGAR FRACTION ONE THIRD */
@@ -534,9 +534,9 @@ static const struct codepair keysymtab[] = {
{ 0x0ab7, 0x215a }, /* fivesixths â…š VULGAR FRACTION FIVE SIXTHS */
{ 0x0ab8, 0x2105 }, /* careof â„… CARE OF */
{ 0x0abb, 0x2012 }, /* figdash ‒ FIGURE DASH */
- { 0x0abc, 0x2329 }, /* leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET */
+ { 0x0abc, 0x27e8 }, /* leftanglebracket ⟨ MATHEMATICAL LEFT ANGLE BRACKET */
{ 0x0abd, 0x002e }, /* decimalpoint . FULL STOP */
- { 0x0abe, 0x232a }, /* rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET */
+ { 0x0abe, 0x27e9 }, /* rightanglebracket ⟩ MATHEMATICAL RIGHT ANGLE BRACKET */
/* 0x0abf marker ? ??? */
{ 0x0ac3, 0x215b }, /* oneeighth â…› VULGAR FRACTION ONE EIGHTH */
{ 0x0ac4, 0x215c }, /* threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS */
@@ -554,6 +554,7 @@ static const struct codepair keysymtab[] = {
{ 0x0ad2, 0x201c }, /* leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK */
{ 0x0ad3, 0x201d }, /* rightdoublequotemark †RIGHT DOUBLE QUOTATION MARK */
{ 0x0ad4, 0x211e }, /* prescription â„ž PRESCRIPTION TAKE */
+ { 0x0ad5, 0x2030 }, /* permille ‰ PER MILLE SIGN */
{ 0x0ad6, 0x2032 }, /* minutes ′ PRIME */
{ 0x0ad7, 0x2033 }, /* seconds ″ DOUBLE PRIME */
{ 0x0ad9, 0x271d }, /* latincross ✠LATIN CROSS */
@@ -880,9 +881,15 @@ xkb_keysym_to_utf32(xkb_keysym_t keysym)
keysym == XKB_KEY_KP_Enter || keysym == XKB_KEY_KP_Equal)
return keysym & 0x7f;
- /* also check for directly encoded 24-bit UCS characters */
- if ((keysym & 0xff000000) == 0x01000000)
- return keysym & 0x00ffffff;
+ /* also check for directly encoded Unicode codepoints */
+ /*
+ * In theory, this is supposed to start from 0x100100, such that the ASCII
+ * range, which is already covered by 0x00-0xff, can't be encoded in two
+ * ways. However, changing this after a couple of decades probably won't
+ * go well, so it stays as it is.
+ */
+ if (0x01000000 <= keysym && keysym <= 0x0110ffff)
+ return keysym - 0x01000000;
/* search main table */
return bin_search(keysymtab, ARRAY_SIZE(keysymtab) - 1, keysym);
diff --git a/src/3rdparty/xkbcommon/src/keysym.c b/src/3rdparty/xkbcommon/src/keysym.c
index e8fa5e12ba..6d06de0bf0 100644
--- a/src/3rdparty/xkbcommon/src/keysym.c
+++ b/src/3rdparty/xkbcommon/src/keysym.c
@@ -76,7 +76,7 @@ compare_by_name(const void *a, const void *b)
{
const char *key = a;
const struct name_keysym *entry = b;
- return strcasecmp(key, get_name(entry));
+ return istrcmp(key, get_name(entry));
}
XKB_EXPORT int
@@ -109,7 +109,7 @@ xkb_keysym_get_name(xkb_keysym_t ks, char *buffer, size_t size)
/*
* Find the correct keysym if one case-insensitive match is given.
*
- * The name_to_keysym table is sorted by strcasecmp(). So bsearch() may return
+ * The name_to_keysym table is sorted by istrcmp(). So bsearch() may return
* _any_ of all possible case-insensitive duplicates. This function searches the
* returned entry @entry, all previous and all next entries that match by
* case-insensitive comparison and returns the exact match to @name. If @icase
@@ -138,7 +138,7 @@ find_sym(const struct name_keysym *entry, const char *name, bool icase)
for (iter = entry - 1; iter >= name_to_keysym; --iter) {
if (!icase && strcmp(get_name(iter), name) == 0)
return iter;
- if (strcasecmp(get_name(iter), get_name(entry)) != 0)
+ if (istrcmp(get_name(iter), get_name(entry)) != 0)
break;
if (icase && xkb_keysym_is_lower(iter->keysym))
return iter;
@@ -148,7 +148,7 @@ find_sym(const struct name_keysym *entry, const char *name, bool icase)
for (iter = entry + 1; iter < last; ++iter) {
if (!icase && strcmp(get_name(iter), name) == 0)
return iter;
- if (strcasecmp(get_name(iter), get_name(entry)) != 0)
+ if (istrcmp(get_name(iter), get_name(entry)) != 0)
break;
if (icase && xkb_keysym_is_lower(iter->keysym))
return iter;
@@ -165,7 +165,7 @@ xkb_keysym_from_name(const char *s, enum xkb_keysym_flags flags)
const struct name_keysym *entry;
char *tmp;
xkb_keysym_t val;
- bool icase = !!(flags & XKB_KEYSYM_CASE_INSENSITIVE);
+ bool icase = (flags & XKB_KEYSYM_CASE_INSENSITIVE);
if (flags & ~XKB_KEYSYM_CASE_INSENSITIVE)
return XKB_KEY_NoSymbol;
@@ -223,6 +223,18 @@ xkb_keysym_is_keypad(xkb_keysym_t keysym)
return keysym >= XKB_KEY_KP_Space && keysym <= XKB_KEY_KP_Equal;
}
+
+bool
+xkb_keysym_is_modifier(xkb_keysym_t keysym)
+{
+ return
+ (keysym >= XKB_KEY_Shift_L && keysym <= XKB_KEY_Hyper_R) ||
+ /* libX11 only goes upto XKB_KEY_ISO_Level5_Lock. */
+ (keysym >= XKB_KEY_ISO_Lock && keysym <= XKB_KEY_ISO_Last_Group_Lock) ||
+ keysym == XKB_KEY_Mode_switch ||
+ keysym == XKB_KEY_Num_Lock;
+}
+
static void
XConvertCase(xkb_keysym_t sym, xkb_keysym_t *lower, xkb_keysym_t *upper);
@@ -252,7 +264,7 @@ xkb_keysym_is_upper(xkb_keysym_t ks)
return (ks == upper ? true : false);
}
-xkb_keysym_t
+XKB_EXPORT xkb_keysym_t
xkb_keysym_to_lower(xkb_keysym_t ks)
{
xkb_keysym_t lower, upper;
@@ -262,7 +274,7 @@ xkb_keysym_to_lower(xkb_keysym_t ks)
return lower;
}
-xkb_keysym_t
+XKB_EXPORT xkb_keysym_t
xkb_keysym_to_upper(xkb_keysym_t ks)
{
xkb_keysym_t lower, upper;
diff --git a/src/3rdparty/xkbcommon/src/keysym.h b/src/3rdparty/xkbcommon/src/keysym.h
index e9374dc492..26339632ee 100644
--- a/src/3rdparty/xkbcommon/src/keysym.h
+++ b/src/3rdparty/xkbcommon/src/keysym.h
@@ -59,10 +59,7 @@ xkb_keysym_is_upper(xkb_keysym_t keysym);
bool
xkb_keysym_is_keypad(xkb_keysym_t keysym);
-xkb_keysym_t
-xkb_keysym_to_upper(xkb_keysym_t ks);
-
-xkb_keysym_t
-xkb_keysym_to_lower(xkb_keysym_t ks);
+bool
+xkb_keysym_is_modifier(xkb_keysym_t keysym);
#endif
diff --git a/src/3rdparty/xkbcommon/src/ks_tables.h b/src/3rdparty/xkbcommon/src/ks_tables.h
index 1010b694e4..aa55fc1df0 100644
--- a/src/3rdparty/xkbcommon/src/ks_tables.h
+++ b/src/3rdparty/xkbcommon/src/ks_tables.h
@@ -2213,6 +2213,7 @@ static const char *keysym_names =
"XF86AudioNext\0"
"XF86AudioPause\0"
"XF86AudioPlay\0"
+ "XF86AudioPreset\0"
"XF86AudioPrev\0"
"XF86AudioRaiseVolume\0"
"XF86AudioRandomPlay\0"
@@ -2262,6 +2263,7 @@ static const char *keysym_names =
"XF86KbdBrightnessDown\0"
"XF86KbdBrightnessUp\0"
"XF86KbdLightOnOff\0"
+ "XF86Keyboard\0"
"XF86Launch0\0"
"XF86Launch1\0"
"XF86Launch2\0"
@@ -2314,6 +2316,7 @@ static const char *keysym_names =
"XF86Refresh\0"
"XF86Reload\0"
"XF86Reply\0"
+ "XF86RFKill\0"
"XF86RockerDown\0"
"XF86RockerEnter\0"
"XF86RockerUp\0"
@@ -2373,6 +2376,7 @@ static const char *keysym_names =
"XF86WheelButton\0"
"XF86WLAN\0"
"XF86Word\0"
+ "XF86WWAN\0"
"XF86WWW\0"
"XF86Xfer\0"
"XF86Yellow\0"
@@ -4624,203 +4628,207 @@ static const struct name_keysym name_to_keysym[] = {
{ 0x1008ff17, 26816 }, /* XF86AudioNext */
{ 0x1008ff31, 26830 }, /* XF86AudioPause */
{ 0x1008ff14, 26845 }, /* XF86AudioPlay */
- { 0x1008ff16, 26859 }, /* XF86AudioPrev */
- { 0x1008ff13, 26873 }, /* XF86AudioRaiseVolume */
- { 0x1008ff99, 26894 }, /* XF86AudioRandomPlay */
- { 0x1008ff1c, 26914 }, /* XF86AudioRecord */
- { 0x1008ff98, 26930 }, /* XF86AudioRepeat */
- { 0x1008ff3e, 26946 }, /* XF86AudioRewind */
- { 0x1008ff15, 26962 }, /* XF86AudioStop */
- { 0x1008ff8d, 26976 }, /* XF86Away */
- { 0x1008ff26, 26985 }, /* XF86Back */
- { 0x1008ff3f, 26994 }, /* XF86BackForward */
- { 0x1008ff93, 27010 }, /* XF86Battery */
- { 0x1008ffa6, 27022 }, /* XF86Blue */
- { 0x1008ff94, 27031 }, /* XF86Bluetooth */
- { 0x1008ff52, 27045 }, /* XF86Book */
- { 0x1008ff3b, 27054 }, /* XF86BrightnessAdjust */
- { 0x1008ff54, 27075 }, /* XF86Calculater */
- { 0x1008ff1d, 27090 }, /* XF86Calculator */
- { 0x1008ff20, 27105 }, /* XF86Calendar */
- { 0x1008ff53, 27118 }, /* XF86CD */
- { 0x1008ff55, 27125 }, /* XF86Clear */
- { 0x1008fe21, 27135 }, /* XF86ClearGrab */
- { 0x1008ff56, 27149 }, /* XF86Close */
- { 0x1008ff3d, 27159 }, /* XF86Community */
- { 0x1008ff22, 27173 }, /* XF86ContrastAdjust */
- { 0x1008ff57, 27192 }, /* XF86Copy */
- { 0x1008ff58, 27201 }, /* XF86Cut */
- { 0x1008ff9c, 27209 }, /* XF86CycleAngle */
- { 0x1008ff59, 27224 }, /* XF86Display */
- { 0x1008ff5b, 27236 }, /* XF86Documents */
- { 0x1008ff5a, 27250 }, /* XF86DOS */
- { 0x1008ff2c, 27258 }, /* XF86Eject */
- { 0x1008ff5c, 27268 }, /* XF86Excel */
- { 0x1008ff5d, 27278 }, /* XF86Explorer */
- { 0x1008ff30, 27291 }, /* XF86Favorites */
- { 0x1008ff3c, 27305 }, /* XF86Finance */
- { 0x1008ff27, 27317 }, /* XF86Forward */
- { 0x1008ff9d, 27329 }, /* XF86FrameBack */
- { 0x1008ff9e, 27343 }, /* XF86FrameForward */
- { 0x1008ff5e, 27360 }, /* XF86Game */
- { 0x1008ff5f, 27369 }, /* XF86Go */
- { 0x1008ffa4, 27376 }, /* XF86Green */
- { 0x1008ffa8, 27386 }, /* XF86Hibernate */
- { 0x1008ff37, 27400 }, /* XF86History */
- { 0x1008ff18, 27412 }, /* XF86HomePage */
- { 0x1008ff3a, 27425 }, /* XF86HotLinks */
- { 0x1008ff60, 27438 }, /* XF86iTouch */
- { 0x1008ff06, 27449 }, /* XF86KbdBrightnessDown */
- { 0x1008ff05, 27471 }, /* XF86KbdBrightnessUp */
- { 0x1008ff04, 27491 }, /* XF86KbdLightOnOff */
- { 0x1008ff40, 27509 }, /* XF86Launch0 */
- { 0x1008ff41, 27521 }, /* XF86Launch1 */
- { 0x1008ff42, 27533 }, /* XF86Launch2 */
- { 0x1008ff43, 27545 }, /* XF86Launch3 */
- { 0x1008ff44, 27557 }, /* XF86Launch4 */
- { 0x1008ff45, 27569 }, /* XF86Launch5 */
- { 0x1008ff46, 27581 }, /* XF86Launch6 */
- { 0x1008ff47, 27593 }, /* XF86Launch7 */
- { 0x1008ff48, 27605 }, /* XF86Launch8 */
- { 0x1008ff49, 27617 }, /* XF86Launch9 */
- { 0x1008ff4a, 27629 }, /* XF86LaunchA */
- { 0x1008ff4b, 27641 }, /* XF86LaunchB */
- { 0x1008ff4c, 27653 }, /* XF86LaunchC */
- { 0x1008ff4d, 27665 }, /* XF86LaunchD */
- { 0x1008ff4e, 27677 }, /* XF86LaunchE */
- { 0x1008ff4f, 27689 }, /* XF86LaunchF */
- { 0x1008ff35, 27701 }, /* XF86LightBulb */
- { 0x1008fe25, 27715 }, /* XF86LogGrabInfo */
- { 0x1008ff61, 27731 }, /* XF86LogOff */
- { 0x1008fe24, 27742 }, /* XF86LogWindowTree */
- { 0x1008ff19, 27760 }, /* XF86Mail */
- { 0x1008ff90, 27769 }, /* XF86MailForward */
- { 0x1008ff62, 27785 }, /* XF86Market */
- { 0x1008ff63, 27796 }, /* XF86Meeting */
- { 0x1008ff1e, 27808 }, /* XF86Memo */
- { 0x1008ff65, 27817 }, /* XF86MenuKB */
- { 0x1008ff66, 27828 }, /* XF86MenuPB */
- { 0x1008ff8e, 27839 }, /* XF86Messenger */
- { 0x1008ff01, 27853 }, /* XF86ModeLock */
- { 0x1008ff03, 27866 }, /* XF86MonBrightnessDown */
- { 0x1008ff02, 27888 }, /* XF86MonBrightnessUp */
- { 0x1008ff92, 27908 }, /* XF86Music */
- { 0x1008ff33, 27918 }, /* XF86MyComputer */
- { 0x1008ff67, 27933 }, /* XF86MySites */
- { 0x1008ff68, 27945 }, /* XF86New */
- { 0x1008ff69, 27953 }, /* XF86News */
- { 0x1008fe22, 27962 }, /* XF86Next_VMode */
- { 0x1008ff6a, 27977 }, /* XF86OfficeHome */
- { 0x1008ff6b, 27992 }, /* XF86Open */
- { 0x1008ff38, 28001 }, /* XF86OpenURL */
- { 0x1008ff6c, 28013 }, /* XF86Option */
- { 0x1008ff6d, 28024 }, /* XF86Paste */
- { 0x1008ff6e, 28034 }, /* XF86Phone */
- { 0x1008ff91, 28044 }, /* XF86Pictures */
- { 0x1008ff21, 28057 }, /* XF86PowerDown */
- { 0x1008ff2a, 28071 }, /* XF86PowerOff */
- { 0x1008fe23, 28084 }, /* XF86Prev_VMode */
- { 0x1008ff70, 28099 }, /* XF86Q */
- { 0x1008ffa3, 28105 }, /* XF86Red */
- { 0x1008ff29, 28113 }, /* XF86Refresh */
- { 0x1008ff73, 28125 }, /* XF86Reload */
- { 0x1008ff72, 28136 }, /* XF86Reply */
- { 0x1008ff24, 28146 }, /* XF86RockerDown */
- { 0x1008ff25, 28161 }, /* XF86RockerEnter */
- { 0x1008ff23, 28177 }, /* XF86RockerUp */
- { 0x1008ff74, 28190 }, /* XF86RotateWindows */
- { 0x1008ff76, 28208 }, /* XF86RotationKB */
- { 0x1008ff75, 28223 }, /* XF86RotationPB */
- { 0x1008ff77, 28238 }, /* XF86Save */
- { 0x1008ff2d, 28247 }, /* XF86ScreenSaver */
- { 0x1008ff7a, 28263 }, /* XF86ScrollClick */
- { 0x1008ff79, 28279 }, /* XF86ScrollDown */
- { 0x1008ff78, 28294 }, /* XF86ScrollUp */
- { 0x1008ff1b, 28307 }, /* XF86Search */
- { 0x1008ffa0, 28318 }, /* XF86Select */
- { 0x1008ff7b, 28329 }, /* XF86Send */
- { 0x1008ff36, 28338 }, /* XF86Shop */
- { 0x1008ff2f, 28347 }, /* XF86Sleep */
- { 0x1008ff7c, 28357 }, /* XF86Spell */
- { 0x1008ff7d, 28367 }, /* XF86SplitScreen */
- { 0x1008ff10, 28383 }, /* XF86Standby */
- { 0x1008ff1a, 28395 }, /* XF86Start */
- { 0x1008ff28, 28405 }, /* XF86Stop */
- { 0x1008ff9a, 28414 }, /* XF86Subtitle */
- { 0x1008ff7e, 28427 }, /* XF86Support */
- { 0x1008ffa7, 28439 }, /* XF86Suspend */
- { 0x1008fe01, 28451 }, /* XF86Switch_VT_1 */
- { 0x1008fe0a, 28467 }, /* XF86Switch_VT_10 */
- { 0x1008fe0b, 28484 }, /* XF86Switch_VT_11 */
- { 0x1008fe0c, 28501 }, /* XF86Switch_VT_12 */
- { 0x1008fe02, 28518 }, /* XF86Switch_VT_2 */
- { 0x1008fe03, 28534 }, /* XF86Switch_VT_3 */
- { 0x1008fe04, 28550 }, /* XF86Switch_VT_4 */
- { 0x1008fe05, 28566 }, /* XF86Switch_VT_5 */
- { 0x1008fe06, 28582 }, /* XF86Switch_VT_6 */
- { 0x1008fe07, 28598 }, /* XF86Switch_VT_7 */
- { 0x1008fe08, 28614 }, /* XF86Switch_VT_8 */
- { 0x1008fe09, 28630 }, /* XF86Switch_VT_9 */
- { 0x1008ff7f, 28646 }, /* XF86TaskPane */
- { 0x1008ff80, 28659 }, /* XF86Terminal */
- { 0x1008ff9f, 28672 }, /* XF86Time */
- { 0x1008ff1f, 28681 }, /* XF86ToDoList */
- { 0x1008ff81, 28694 }, /* XF86Tools */
- { 0x1008ffa2, 28704 }, /* XF86TopMenu */
- { 0x1008ffb1, 28716 }, /* XF86TouchpadOff */
- { 0x1008ffb0, 28732 }, /* XF86TouchpadOn */
- { 0x1008ffa9, 28747 }, /* XF86TouchpadToggle */
- { 0x1008ff82, 28766 }, /* XF86Travel */
- { 0x1008fe20, 28777 }, /* XF86Ungrab */
- { 0x1008ff85, 28788 }, /* XF86User1KB */
- { 0x1008ff86, 28800 }, /* XF86User2KB */
- { 0x1008ff84, 28812 }, /* XF86UserPB */
- { 0x1008ff96, 28823 }, /* XF86UWB */
- { 0x1008ff34, 28831 }, /* XF86VendorHome */
- { 0x1008ff87, 28846 }, /* XF86Video */
- { 0x1008ffa1, 28856 }, /* XF86View */
- { 0x1008ff2b, 28865 }, /* XF86WakeUp */
- { 0x1008ff8f, 28876 }, /* XF86WebCam */
- { 0x1008ff88, 28887 }, /* XF86WheelButton */
- { 0x1008ff95, 28903 }, /* XF86WLAN */
- { 0x1008ff89, 28912 }, /* XF86Word */
- { 0x1008ff2e, 28921 }, /* XF86WWW */
- { 0x1008ff8a, 28929 }, /* XF86Xfer */
- { 0x1008ffa5, 28938 }, /* XF86Yellow */
- { 0x1008ff8b, 28949 }, /* XF86ZoomIn */
- { 0x1008ff8c, 28960 }, /* XF86ZoomOut */
- { 0x00000059, 28972 }, /* Y */
- { 0x00000079, 28974 }, /* y */
- { 0x000000dd, 28976 }, /* Yacute */
- { 0x000000fd, 28983 }, /* yacute */
- { 0x01001ef4, 28990 }, /* Ybelowdot */
- { 0x01001ef5, 29000 }, /* ybelowdot */
- { 0x01000176, 29010 }, /* Ycircumflex */
- { 0x01000177, 29022 }, /* ycircumflex */
- { 0x000000ff, 29034 }, /* ydiaeresis */
- { 0x000013be, 29045 }, /* Ydiaeresis */
- { 0x000000a5, 29056 }, /* yen */
- { 0x01001ef2, 29060 }, /* Ygrave */
- { 0x01001ef3, 29067 }, /* ygrave */
- { 0x01001ef6, 29074 }, /* Yhook */
- { 0x01001ef7, 29080 }, /* yhook */
- { 0x01001ef8, 29086 }, /* Ytilde */
- { 0x01001ef9, 29093 }, /* ytilde */
- { 0x0000005a, 29100 }, /* Z */
- { 0x0000007a, 29102 }, /* z */
- { 0x000001af, 29104 }, /* Zabovedot */
- { 0x000001bf, 29114 }, /* zabovedot */
- { 0x000001ac, 29124 }, /* Zacute */
- { 0x000001bc, 29131 }, /* zacute */
- { 0x000001ae, 29138 }, /* Zcaron */
- { 0x000001be, 29145 }, /* zcaron */
- { 0x0000ff3d, 29152 }, /* Zen_Koho */
- { 0x0000ff28, 29161 }, /* Zenkaku */
- { 0x0000ff2a, 29169 }, /* Zenkaku_Hankaku */
- { 0x01002080, 29185 }, /* zerosubscript */
- { 0x01002070, 29199 }, /* zerosuperior */
- { 0x010001b5, 29212 }, /* Zstroke */
- { 0x010001b6, 29220 }, /* zstroke */
+ { 0x1008ffb6, 26859 }, /* XF86AudioPreset */
+ { 0x1008ff16, 26875 }, /* XF86AudioPrev */
+ { 0x1008ff13, 26889 }, /* XF86AudioRaiseVolume */
+ { 0x1008ff99, 26910 }, /* XF86AudioRandomPlay */
+ { 0x1008ff1c, 26930 }, /* XF86AudioRecord */
+ { 0x1008ff98, 26946 }, /* XF86AudioRepeat */
+ { 0x1008ff3e, 26962 }, /* XF86AudioRewind */
+ { 0x1008ff15, 26978 }, /* XF86AudioStop */
+ { 0x1008ff8d, 26992 }, /* XF86Away */
+ { 0x1008ff26, 27001 }, /* XF86Back */
+ { 0x1008ff3f, 27010 }, /* XF86BackForward */
+ { 0x1008ff93, 27026 }, /* XF86Battery */
+ { 0x1008ffa6, 27038 }, /* XF86Blue */
+ { 0x1008ff94, 27047 }, /* XF86Bluetooth */
+ { 0x1008ff52, 27061 }, /* XF86Book */
+ { 0x1008ff3b, 27070 }, /* XF86BrightnessAdjust */
+ { 0x1008ff54, 27091 }, /* XF86Calculater */
+ { 0x1008ff1d, 27106 }, /* XF86Calculator */
+ { 0x1008ff20, 27121 }, /* XF86Calendar */
+ { 0x1008ff53, 27134 }, /* XF86CD */
+ { 0x1008ff55, 27141 }, /* XF86Clear */
+ { 0x1008fe21, 27151 }, /* XF86ClearGrab */
+ { 0x1008ff56, 27165 }, /* XF86Close */
+ { 0x1008ff3d, 27175 }, /* XF86Community */
+ { 0x1008ff22, 27189 }, /* XF86ContrastAdjust */
+ { 0x1008ff57, 27208 }, /* XF86Copy */
+ { 0x1008ff58, 27217 }, /* XF86Cut */
+ { 0x1008ff9c, 27225 }, /* XF86CycleAngle */
+ { 0x1008ff59, 27240 }, /* XF86Display */
+ { 0x1008ff5b, 27252 }, /* XF86Documents */
+ { 0x1008ff5a, 27266 }, /* XF86DOS */
+ { 0x1008ff2c, 27274 }, /* XF86Eject */
+ { 0x1008ff5c, 27284 }, /* XF86Excel */
+ { 0x1008ff5d, 27294 }, /* XF86Explorer */
+ { 0x1008ff30, 27307 }, /* XF86Favorites */
+ { 0x1008ff3c, 27321 }, /* XF86Finance */
+ { 0x1008ff27, 27333 }, /* XF86Forward */
+ { 0x1008ff9d, 27345 }, /* XF86FrameBack */
+ { 0x1008ff9e, 27359 }, /* XF86FrameForward */
+ { 0x1008ff5e, 27376 }, /* XF86Game */
+ { 0x1008ff5f, 27385 }, /* XF86Go */
+ { 0x1008ffa4, 27392 }, /* XF86Green */
+ { 0x1008ffa8, 27402 }, /* XF86Hibernate */
+ { 0x1008ff37, 27416 }, /* XF86History */
+ { 0x1008ff18, 27428 }, /* XF86HomePage */
+ { 0x1008ff3a, 27441 }, /* XF86HotLinks */
+ { 0x1008ff60, 27454 }, /* XF86iTouch */
+ { 0x1008ff06, 27465 }, /* XF86KbdBrightnessDown */
+ { 0x1008ff05, 27487 }, /* XF86KbdBrightnessUp */
+ { 0x1008ff04, 27507 }, /* XF86KbdLightOnOff */
+ { 0x1008ffb3, 27525 }, /* XF86Keyboard */
+ { 0x1008ff40, 27538 }, /* XF86Launch0 */
+ { 0x1008ff41, 27550 }, /* XF86Launch1 */
+ { 0x1008ff42, 27562 }, /* XF86Launch2 */
+ { 0x1008ff43, 27574 }, /* XF86Launch3 */
+ { 0x1008ff44, 27586 }, /* XF86Launch4 */
+ { 0x1008ff45, 27598 }, /* XF86Launch5 */
+ { 0x1008ff46, 27610 }, /* XF86Launch6 */
+ { 0x1008ff47, 27622 }, /* XF86Launch7 */
+ { 0x1008ff48, 27634 }, /* XF86Launch8 */
+ { 0x1008ff49, 27646 }, /* XF86Launch9 */
+ { 0x1008ff4a, 27658 }, /* XF86LaunchA */
+ { 0x1008ff4b, 27670 }, /* XF86LaunchB */
+ { 0x1008ff4c, 27682 }, /* XF86LaunchC */
+ { 0x1008ff4d, 27694 }, /* XF86LaunchD */
+ { 0x1008ff4e, 27706 }, /* XF86LaunchE */
+ { 0x1008ff4f, 27718 }, /* XF86LaunchF */
+ { 0x1008ff35, 27730 }, /* XF86LightBulb */
+ { 0x1008fe25, 27744 }, /* XF86LogGrabInfo */
+ { 0x1008ff61, 27760 }, /* XF86LogOff */
+ { 0x1008fe24, 27771 }, /* XF86LogWindowTree */
+ { 0x1008ff19, 27789 }, /* XF86Mail */
+ { 0x1008ff90, 27798 }, /* XF86MailForward */
+ { 0x1008ff62, 27814 }, /* XF86Market */
+ { 0x1008ff63, 27825 }, /* XF86Meeting */
+ { 0x1008ff1e, 27837 }, /* XF86Memo */
+ { 0x1008ff65, 27846 }, /* XF86MenuKB */
+ { 0x1008ff66, 27857 }, /* XF86MenuPB */
+ { 0x1008ff8e, 27868 }, /* XF86Messenger */
+ { 0x1008ff01, 27882 }, /* XF86ModeLock */
+ { 0x1008ff03, 27895 }, /* XF86MonBrightnessDown */
+ { 0x1008ff02, 27917 }, /* XF86MonBrightnessUp */
+ { 0x1008ff92, 27937 }, /* XF86Music */
+ { 0x1008ff33, 27947 }, /* XF86MyComputer */
+ { 0x1008ff67, 27962 }, /* XF86MySites */
+ { 0x1008ff68, 27974 }, /* XF86New */
+ { 0x1008ff69, 27982 }, /* XF86News */
+ { 0x1008fe22, 27991 }, /* XF86Next_VMode */
+ { 0x1008ff6a, 28006 }, /* XF86OfficeHome */
+ { 0x1008ff6b, 28021 }, /* XF86Open */
+ { 0x1008ff38, 28030 }, /* XF86OpenURL */
+ { 0x1008ff6c, 28042 }, /* XF86Option */
+ { 0x1008ff6d, 28053 }, /* XF86Paste */
+ { 0x1008ff6e, 28063 }, /* XF86Phone */
+ { 0x1008ff91, 28073 }, /* XF86Pictures */
+ { 0x1008ff21, 28086 }, /* XF86PowerDown */
+ { 0x1008ff2a, 28100 }, /* XF86PowerOff */
+ { 0x1008fe23, 28113 }, /* XF86Prev_VMode */
+ { 0x1008ff70, 28128 }, /* XF86Q */
+ { 0x1008ffa3, 28134 }, /* XF86Red */
+ { 0x1008ff29, 28142 }, /* XF86Refresh */
+ { 0x1008ff73, 28154 }, /* XF86Reload */
+ { 0x1008ff72, 28165 }, /* XF86Reply */
+ { 0x1008ffb5, 28175 }, /* XF86RFKill */
+ { 0x1008ff24, 28186 }, /* XF86RockerDown */
+ { 0x1008ff25, 28201 }, /* XF86RockerEnter */
+ { 0x1008ff23, 28217 }, /* XF86RockerUp */
+ { 0x1008ff74, 28230 }, /* XF86RotateWindows */
+ { 0x1008ff76, 28248 }, /* XF86RotationKB */
+ { 0x1008ff75, 28263 }, /* XF86RotationPB */
+ { 0x1008ff77, 28278 }, /* XF86Save */
+ { 0x1008ff2d, 28287 }, /* XF86ScreenSaver */
+ { 0x1008ff7a, 28303 }, /* XF86ScrollClick */
+ { 0x1008ff79, 28319 }, /* XF86ScrollDown */
+ { 0x1008ff78, 28334 }, /* XF86ScrollUp */
+ { 0x1008ff1b, 28347 }, /* XF86Search */
+ { 0x1008ffa0, 28358 }, /* XF86Select */
+ { 0x1008ff7b, 28369 }, /* XF86Send */
+ { 0x1008ff36, 28378 }, /* XF86Shop */
+ { 0x1008ff2f, 28387 }, /* XF86Sleep */
+ { 0x1008ff7c, 28397 }, /* XF86Spell */
+ { 0x1008ff7d, 28407 }, /* XF86SplitScreen */
+ { 0x1008ff10, 28423 }, /* XF86Standby */
+ { 0x1008ff1a, 28435 }, /* XF86Start */
+ { 0x1008ff28, 28445 }, /* XF86Stop */
+ { 0x1008ff9a, 28454 }, /* XF86Subtitle */
+ { 0x1008ff7e, 28467 }, /* XF86Support */
+ { 0x1008ffa7, 28479 }, /* XF86Suspend */
+ { 0x1008fe01, 28491 }, /* XF86Switch_VT_1 */
+ { 0x1008fe0a, 28507 }, /* XF86Switch_VT_10 */
+ { 0x1008fe0b, 28524 }, /* XF86Switch_VT_11 */
+ { 0x1008fe0c, 28541 }, /* XF86Switch_VT_12 */
+ { 0x1008fe02, 28558 }, /* XF86Switch_VT_2 */
+ { 0x1008fe03, 28574 }, /* XF86Switch_VT_3 */
+ { 0x1008fe04, 28590 }, /* XF86Switch_VT_4 */
+ { 0x1008fe05, 28606 }, /* XF86Switch_VT_5 */
+ { 0x1008fe06, 28622 }, /* XF86Switch_VT_6 */
+ { 0x1008fe07, 28638 }, /* XF86Switch_VT_7 */
+ { 0x1008fe08, 28654 }, /* XF86Switch_VT_8 */
+ { 0x1008fe09, 28670 }, /* XF86Switch_VT_9 */
+ { 0x1008ff7f, 28686 }, /* XF86TaskPane */
+ { 0x1008ff80, 28699 }, /* XF86Terminal */
+ { 0x1008ff9f, 28712 }, /* XF86Time */
+ { 0x1008ff1f, 28721 }, /* XF86ToDoList */
+ { 0x1008ff81, 28734 }, /* XF86Tools */
+ { 0x1008ffa2, 28744 }, /* XF86TopMenu */
+ { 0x1008ffb1, 28756 }, /* XF86TouchpadOff */
+ { 0x1008ffb0, 28772 }, /* XF86TouchpadOn */
+ { 0x1008ffa9, 28787 }, /* XF86TouchpadToggle */
+ { 0x1008ff82, 28806 }, /* XF86Travel */
+ { 0x1008fe20, 28817 }, /* XF86Ungrab */
+ { 0x1008ff85, 28828 }, /* XF86User1KB */
+ { 0x1008ff86, 28840 }, /* XF86User2KB */
+ { 0x1008ff84, 28852 }, /* XF86UserPB */
+ { 0x1008ff96, 28863 }, /* XF86UWB */
+ { 0x1008ff34, 28871 }, /* XF86VendorHome */
+ { 0x1008ff87, 28886 }, /* XF86Video */
+ { 0x1008ffa1, 28896 }, /* XF86View */
+ { 0x1008ff2b, 28905 }, /* XF86WakeUp */
+ { 0x1008ff8f, 28916 }, /* XF86WebCam */
+ { 0x1008ff88, 28927 }, /* XF86WheelButton */
+ { 0x1008ff95, 28943 }, /* XF86WLAN */
+ { 0x1008ff89, 28952 }, /* XF86Word */
+ { 0x1008ffb4, 28961 }, /* XF86WWAN */
+ { 0x1008ff2e, 28970 }, /* XF86WWW */
+ { 0x1008ff8a, 28978 }, /* XF86Xfer */
+ { 0x1008ffa5, 28987 }, /* XF86Yellow */
+ { 0x1008ff8b, 28998 }, /* XF86ZoomIn */
+ { 0x1008ff8c, 29009 }, /* XF86ZoomOut */
+ { 0x00000059, 29021 }, /* Y */
+ { 0x00000079, 29023 }, /* y */
+ { 0x000000dd, 29025 }, /* Yacute */
+ { 0x000000fd, 29032 }, /* yacute */
+ { 0x01001ef4, 29039 }, /* Ybelowdot */
+ { 0x01001ef5, 29049 }, /* ybelowdot */
+ { 0x01000176, 29059 }, /* Ycircumflex */
+ { 0x01000177, 29071 }, /* ycircumflex */
+ { 0x000000ff, 29083 }, /* ydiaeresis */
+ { 0x000013be, 29094 }, /* Ydiaeresis */
+ { 0x000000a5, 29105 }, /* yen */
+ { 0x01001ef2, 29109 }, /* Ygrave */
+ { 0x01001ef3, 29116 }, /* ygrave */
+ { 0x01001ef6, 29123 }, /* Yhook */
+ { 0x01001ef7, 29129 }, /* yhook */
+ { 0x01001ef8, 29135 }, /* Ytilde */
+ { 0x01001ef9, 29142 }, /* ytilde */
+ { 0x0000005a, 29149 }, /* Z */
+ { 0x0000007a, 29151 }, /* z */
+ { 0x000001af, 29153 }, /* Zabovedot */
+ { 0x000001bf, 29163 }, /* zabovedot */
+ { 0x000001ac, 29173 }, /* Zacute */
+ { 0x000001bc, 29180 }, /* zacute */
+ { 0x000001ae, 29187 }, /* Zcaron */
+ { 0x000001be, 29194 }, /* zcaron */
+ { 0x0000ff3d, 29201 }, /* Zen_Koho */
+ { 0x0000ff28, 29210 }, /* Zenkaku */
+ { 0x0000ff2a, 29218 }, /* Zenkaku_Hankaku */
+ { 0x01002080, 29234 }, /* zerosubscript */
+ { 0x01002070, 29248 }, /* zerosuperior */
+ { 0x010001b5, 29261 }, /* Zstroke */
+ { 0x010001b6, 29269 }, /* zstroke */
};
static const struct name_keysym keysym_to_name[] = {
@@ -4882,8 +4890,8 @@ static const struct name_keysym keysym_to_name[] = {
{ 0x00000056, 26483 }, /* V */
{ 0x00000057, 26545 }, /* W */
{ 0x00000058, 26631 }, /* X */
- { 0x00000059, 28972 }, /* Y */
- { 0x0000005a, 29100 }, /* Z */
+ { 0x00000059, 29021 }, /* Y */
+ { 0x0000005a, 29149 }, /* Z */
{ 0x0000005b, 3603 }, /* bracketleft */
{ 0x0000005c, 3352 }, /* backslash */
{ 0x0000005d, 3615 }, /* bracketright */
@@ -4914,8 +4922,8 @@ static const struct name_keysym keysym_to_name[] = {
{ 0x00000076, 26485 }, /* v */
{ 0x00000077, 26547 }, /* w */
{ 0x00000078, 26633 }, /* x */
- { 0x00000079, 28974 }, /* y */
- { 0x0000007a, 29102 }, /* z */
+ { 0x00000079, 29023 }, /* y */
+ { 0x0000007a, 29151 }, /* z */
{ 0x0000007b, 3582 }, /* braceleft */
{ 0x0000007c, 3392 }, /* bar */
{ 0x0000007d, 3592 }, /* braceright */
@@ -4925,7 +4933,7 @@ static const struct name_keysym keysym_to_name[] = {
{ 0x000000a2, 8589 }, /* cent */
{ 0x000000a3, 23827 }, /* sterling */
{ 0x000000a4, 8766 }, /* currency */
- { 0x000000a5, 29056 }, /* yen */
+ { 0x000000a5, 29105 }, /* yen */
{ 0x000000a6, 8389 }, /* brokenbar */
{ 0x000000a7, 22719 }, /* section */
{ 0x000000a8, 11203 }, /* diaeresis */
@@ -4981,7 +4989,7 @@ static const struct name_keysym keysym_to_name[] = {
{ 0x000000da, 25851 }, /* Uacute */
{ 0x000000db, 25899 }, /* Ucircumflex */
{ 0x000000dc, 25923 }, /* Udiaeresis */
- { 0x000000dd, 28976 }, /* Yacute */
+ { 0x000000dd, 29025 }, /* Yacute */
{ 0x000000de, 25499 }, /* THORN */
{ 0x000000df, 23820 }, /* ssharp */
{ 0x000000e0, 861 }, /* agrave */
@@ -5013,9 +5021,9 @@ static const struct name_keysym keysym_to_name[] = {
{ 0x000000fa, 25858 }, /* uacute */
{ 0x000000fb, 25911 }, /* ucircumflex */
{ 0x000000fc, 25934 }, /* udiaeresis */
- { 0x000000fd, 28983 }, /* yacute */
+ { 0x000000fd, 29032 }, /* yacute */
{ 0x000000fe, 25511 }, /* thorn */
- { 0x000000ff, 29034 }, /* ydiaeresis */
+ { 0x000000ff, 29083 }, /* ydiaeresis */
{ 0x000001a1, 918 }, /* Aogonek */
{ 0x000001a2, 8383 }, /* breve */
{ 0x000001a3, 19517 }, /* Lstroke */
@@ -5024,9 +5032,9 @@ static const struct name_keysym keysym_to_name[] = {
{ 0x000001a9, 22617 }, /* Scaron */
{ 0x000001aa, 22631 }, /* Scedilla */
{ 0x000001ab, 24322 }, /* Tcaron */
- { 0x000001ac, 29124 }, /* Zacute */
- { 0x000001ae, 29138 }, /* Zcaron */
- { 0x000001af, 29104 }, /* Zabovedot */
+ { 0x000001ac, 29173 }, /* Zacute */
+ { 0x000001ae, 29187 }, /* Zcaron */
+ { 0x000001af, 29153 }, /* Zabovedot */
{ 0x000001b1, 926 }, /* aogonek */
{ 0x000001b2, 20520 }, /* ogonek */
{ 0x000001b3, 19525 }, /* lstroke */
@@ -5036,10 +5044,10 @@ static const struct name_keysym keysym_to_name[] = {
{ 0x000001b9, 22624 }, /* scaron */
{ 0x000001ba, 22640 }, /* scedilla */
{ 0x000001bb, 24329 }, /* tcaron */
- { 0x000001bc, 29131 }, /* zacute */
+ { 0x000001bc, 29180 }, /* zacute */
{ 0x000001bd, 11283 }, /* doubleacute */
- { 0x000001be, 29145 }, /* zcaron */
- { 0x000001bf, 29114 }, /* zabovedot */
+ { 0x000001be, 29194 }, /* zcaron */
+ { 0x000001bf, 29163 }, /* zabovedot */
{ 0x000001c0, 22272 }, /* Racute */
{ 0x000001c3, 445 }, /* Abreve */
{ 0x000001c5, 19147 }, /* Lacute */
@@ -5789,7 +5797,7 @@ static const struct name_keysym keysym_to_name[] = {
{ 0x00000eff, 18797 }, /* Korean_Won */
{ 0x000013bc, 20514 }, /* OE */
{ 0x000013bd, 20517 }, /* oe */
- { 0x000013be, 29045 }, /* Ydiaeresis */
+ { 0x000013be, 29094 }, /* Ydiaeresis */
{ 0x000020ac, 12090 }, /* EuroSign */
{ 0x0000fd01, 125 }, /* 3270_Duplicate */
{ 0x0000fd02, 195 }, /* 3270_FieldMark */
@@ -5978,9 +5986,9 @@ static const struct name_keysym keysym_to_name[] = {
{ 0x0000ff25, 16635 }, /* Hiragana */
{ 0x0000ff26, 18770 }, /* Katakana */
{ 0x0000ff27, 16644 }, /* Hiragana_Katakana */
- { 0x0000ff28, 29161 }, /* Zenkaku */
+ { 0x0000ff28, 29210 }, /* Zenkaku */
{ 0x0000ff29, 16048 }, /* Hankaku */
- { 0x0000ff2a, 29169 }, /* Zenkaku_Hankaku */
+ { 0x0000ff2a, 29218 }, /* Zenkaku_Hankaku */
{ 0x0000ff2b, 25752 }, /* Touroku */
{ 0x0000ff2c, 19698 }, /* Massyo */
{ 0x0000ff2d, 18351 }, /* Kana_Lock */
@@ -6124,16 +6132,16 @@ static const struct name_keysym keysym_to_name[] = {
{ 0x0100012d, 17124 }, /* ibreve */
{ 0x01000174, 26563 }, /* Wcircumflex */
{ 0x01000175, 26575 }, /* wcircumflex */
- { 0x01000176, 29010 }, /* Ycircumflex */
- { 0x01000177, 29022 }, /* ycircumflex */
+ { 0x01000176, 29059 }, /* Ycircumflex */
+ { 0x01000177, 29071 }, /* ycircumflex */
{ 0x0100018f, 22649 }, /* SCHWA */
{ 0x0100019f, 20218 }, /* Obarred */
{ 0x010001a0, 20553 }, /* Ohorn */
{ 0x010001a1, 20559 }, /* ohorn */
{ 0x010001af, 25997 }, /* Uhorn */
{ 0x010001b0, 26003 }, /* uhorn */
- { 0x010001b5, 29212 }, /* Zstroke */
- { 0x010001b6, 29220 }, /* zstroke */
+ { 0x010001b5, 29261 }, /* Zstroke */
+ { 0x010001b6, 29269 }, /* zstroke */
{ 0x010001b7, 12147 }, /* EZH */
{ 0x010001d1, 20254 }, /* Ocaron */
{ 0x010001d2, 20261 }, /* ocaron */
@@ -6521,22 +6529,22 @@ static const struct name_keysym keysym_to_name[] = {
{ 0x01001eef, 26112 }, /* uhorntilde */
{ 0x01001ef0, 26031 }, /* Uhornbelowdot */
{ 0x01001ef1, 26045 }, /* uhornbelowdot */
- { 0x01001ef2, 29060 }, /* Ygrave */
- { 0x01001ef3, 29067 }, /* ygrave */
- { 0x01001ef4, 28990 }, /* Ybelowdot */
- { 0x01001ef5, 29000 }, /* ybelowdot */
- { 0x01001ef6, 29074 }, /* Yhook */
- { 0x01001ef7, 29080 }, /* yhook */
- { 0x01001ef8, 29086 }, /* Ytilde */
- { 0x01001ef9, 29093 }, /* ytilde */
- { 0x01002070, 29199 }, /* zerosuperior */
+ { 0x01001ef2, 29109 }, /* Ygrave */
+ { 0x01001ef3, 29116 }, /* ygrave */
+ { 0x01001ef4, 29039 }, /* Ybelowdot */
+ { 0x01001ef5, 29049 }, /* ybelowdot */
+ { 0x01001ef6, 29123 }, /* Yhook */
+ { 0x01001ef7, 29129 }, /* yhook */
+ { 0x01001ef8, 29135 }, /* Ytilde */
+ { 0x01001ef9, 29142 }, /* ytilde */
+ { 0x01002070, 29248 }, /* zerosuperior */
{ 0x01002074, 12632 }, /* foursuperior */
{ 0x01002075, 12594 }, /* fivesuperior */
{ 0x01002076, 23756 }, /* sixsuperior */
{ 0x01002077, 22932 }, /* sevensuperior */
{ 0x01002078, 11765 }, /* eightsuperior */
{ 0x01002079, 20062 }, /* ninesuperior */
- { 0x01002080, 29185 }, /* zerosubscript */
+ { 0x01002080, 29234 }, /* zerosubscript */
{ 0x01002081, 20742 }, /* onesubscript */
{ 0x01002082, 25812 }, /* twosubscript */
{ 0x01002083, 25556 }, /* threesubscript */
@@ -6924,181 +6932,185 @@ static const struct name_keysym keysym_to_name[] = {
{ 0x1005ff7b, 24215 }, /* SunVideoLowerBrightness */
{ 0x1005ff7c, 24239 }, /* SunVideoRaiseBrightness */
{ 0x1005ff7d, 24127 }, /* SunPowerSwitchShift */
- { 0x1008fe01, 28451 }, /* XF86Switch_VT_1 */
- { 0x1008fe02, 28518 }, /* XF86Switch_VT_2 */
- { 0x1008fe03, 28534 }, /* XF86Switch_VT_3 */
- { 0x1008fe04, 28550 }, /* XF86Switch_VT_4 */
- { 0x1008fe05, 28566 }, /* XF86Switch_VT_5 */
- { 0x1008fe06, 28582 }, /* XF86Switch_VT_6 */
- { 0x1008fe07, 28598 }, /* XF86Switch_VT_7 */
- { 0x1008fe08, 28614 }, /* XF86Switch_VT_8 */
- { 0x1008fe09, 28630 }, /* XF86Switch_VT_9 */
- { 0x1008fe0a, 28467 }, /* XF86Switch_VT_10 */
- { 0x1008fe0b, 28484 }, /* XF86Switch_VT_11 */
- { 0x1008fe0c, 28501 }, /* XF86Switch_VT_12 */
- { 0x1008fe20, 28777 }, /* XF86Ungrab */
- { 0x1008fe21, 27135 }, /* XF86ClearGrab */
- { 0x1008fe22, 27962 }, /* XF86Next_VMode */
- { 0x1008fe23, 28084 }, /* XF86Prev_VMode */
- { 0x1008fe24, 27742 }, /* XF86LogWindowTree */
- { 0x1008fe25, 27715 }, /* XF86LogGrabInfo */
- { 0x1008ff01, 27853 }, /* XF86ModeLock */
- { 0x1008ff02, 27888 }, /* XF86MonBrightnessUp */
- { 0x1008ff03, 27866 }, /* XF86MonBrightnessDown */
- { 0x1008ff04, 27491 }, /* XF86KbdLightOnOff */
- { 0x1008ff05, 27471 }, /* XF86KbdBrightnessUp */
- { 0x1008ff06, 27449 }, /* XF86KbdBrightnessDown */
- { 0x1008ff10, 28383 }, /* XF86Standby */
+ { 0x1008fe01, 28491 }, /* XF86Switch_VT_1 */
+ { 0x1008fe02, 28558 }, /* XF86Switch_VT_2 */
+ { 0x1008fe03, 28574 }, /* XF86Switch_VT_3 */
+ { 0x1008fe04, 28590 }, /* XF86Switch_VT_4 */
+ { 0x1008fe05, 28606 }, /* XF86Switch_VT_5 */
+ { 0x1008fe06, 28622 }, /* XF86Switch_VT_6 */
+ { 0x1008fe07, 28638 }, /* XF86Switch_VT_7 */
+ { 0x1008fe08, 28654 }, /* XF86Switch_VT_8 */
+ { 0x1008fe09, 28670 }, /* XF86Switch_VT_9 */
+ { 0x1008fe0a, 28507 }, /* XF86Switch_VT_10 */
+ { 0x1008fe0b, 28524 }, /* XF86Switch_VT_11 */
+ { 0x1008fe0c, 28541 }, /* XF86Switch_VT_12 */
+ { 0x1008fe20, 28817 }, /* XF86Ungrab */
+ { 0x1008fe21, 27151 }, /* XF86ClearGrab */
+ { 0x1008fe22, 27991 }, /* XF86Next_VMode */
+ { 0x1008fe23, 28113 }, /* XF86Prev_VMode */
+ { 0x1008fe24, 27771 }, /* XF86LogWindowTree */
+ { 0x1008fe25, 27744 }, /* XF86LogGrabInfo */
+ { 0x1008ff01, 27882 }, /* XF86ModeLock */
+ { 0x1008ff02, 27917 }, /* XF86MonBrightnessUp */
+ { 0x1008ff03, 27895 }, /* XF86MonBrightnessDown */
+ { 0x1008ff04, 27507 }, /* XF86KbdLightOnOff */
+ { 0x1008ff05, 27487 }, /* XF86KbdBrightnessUp */
+ { 0x1008ff06, 27465 }, /* XF86KbdBrightnessDown */
+ { 0x1008ff10, 28423 }, /* XF86Standby */
{ 0x1008ff11, 26749 }, /* XF86AudioLowerVolume */
{ 0x1008ff12, 26802 }, /* XF86AudioMute */
- { 0x1008ff13, 26873 }, /* XF86AudioRaiseVolume */
+ { 0x1008ff13, 26889 }, /* XF86AudioRaiseVolume */
{ 0x1008ff14, 26845 }, /* XF86AudioPlay */
- { 0x1008ff15, 26962 }, /* XF86AudioStop */
- { 0x1008ff16, 26859 }, /* XF86AudioPrev */
+ { 0x1008ff15, 26978 }, /* XF86AudioStop */
+ { 0x1008ff16, 26875 }, /* XF86AudioPrev */
{ 0x1008ff17, 26816 }, /* XF86AudioNext */
- { 0x1008ff18, 27412 }, /* XF86HomePage */
- { 0x1008ff19, 27760 }, /* XF86Mail */
- { 0x1008ff1a, 28395 }, /* XF86Start */
- { 0x1008ff1b, 28307 }, /* XF86Search */
- { 0x1008ff1c, 26914 }, /* XF86AudioRecord */
- { 0x1008ff1d, 27090 }, /* XF86Calculator */
- { 0x1008ff1e, 27808 }, /* XF86Memo */
- { 0x1008ff1f, 28681 }, /* XF86ToDoList */
- { 0x1008ff20, 27105 }, /* XF86Calendar */
- { 0x1008ff21, 28057 }, /* XF86PowerDown */
- { 0x1008ff22, 27173 }, /* XF86ContrastAdjust */
- { 0x1008ff23, 28177 }, /* XF86RockerUp */
- { 0x1008ff24, 28146 }, /* XF86RockerDown */
- { 0x1008ff25, 28161 }, /* XF86RockerEnter */
- { 0x1008ff26, 26985 }, /* XF86Back */
- { 0x1008ff27, 27317 }, /* XF86Forward */
- { 0x1008ff28, 28405 }, /* XF86Stop */
- { 0x1008ff29, 28113 }, /* XF86Refresh */
- { 0x1008ff2a, 28071 }, /* XF86PowerOff */
- { 0x1008ff2b, 28865 }, /* XF86WakeUp */
- { 0x1008ff2c, 27258 }, /* XF86Eject */
- { 0x1008ff2d, 28247 }, /* XF86ScreenSaver */
- { 0x1008ff2e, 28921 }, /* XF86WWW */
- { 0x1008ff2f, 28347 }, /* XF86Sleep */
- { 0x1008ff30, 27291 }, /* XF86Favorites */
+ { 0x1008ff18, 27428 }, /* XF86HomePage */
+ { 0x1008ff19, 27789 }, /* XF86Mail */
+ { 0x1008ff1a, 28435 }, /* XF86Start */
+ { 0x1008ff1b, 28347 }, /* XF86Search */
+ { 0x1008ff1c, 26930 }, /* XF86AudioRecord */
+ { 0x1008ff1d, 27106 }, /* XF86Calculator */
+ { 0x1008ff1e, 27837 }, /* XF86Memo */
+ { 0x1008ff1f, 28721 }, /* XF86ToDoList */
+ { 0x1008ff20, 27121 }, /* XF86Calendar */
+ { 0x1008ff21, 28086 }, /* XF86PowerDown */
+ { 0x1008ff22, 27189 }, /* XF86ContrastAdjust */
+ { 0x1008ff23, 28217 }, /* XF86RockerUp */
+ { 0x1008ff24, 28186 }, /* XF86RockerDown */
+ { 0x1008ff25, 28201 }, /* XF86RockerEnter */
+ { 0x1008ff26, 27001 }, /* XF86Back */
+ { 0x1008ff27, 27333 }, /* XF86Forward */
+ { 0x1008ff28, 28445 }, /* XF86Stop */
+ { 0x1008ff29, 28142 }, /* XF86Refresh */
+ { 0x1008ff2a, 28100 }, /* XF86PowerOff */
+ { 0x1008ff2b, 28905 }, /* XF86WakeUp */
+ { 0x1008ff2c, 27274 }, /* XF86Eject */
+ { 0x1008ff2d, 28287 }, /* XF86ScreenSaver */
+ { 0x1008ff2e, 28970 }, /* XF86WWW */
+ { 0x1008ff2f, 28387 }, /* XF86Sleep */
+ { 0x1008ff30, 27307 }, /* XF86Favorites */
{ 0x1008ff31, 26830 }, /* XF86AudioPause */
{ 0x1008ff32, 26770 }, /* XF86AudioMedia */
- { 0x1008ff33, 27918 }, /* XF86MyComputer */
- { 0x1008ff34, 28831 }, /* XF86VendorHome */
- { 0x1008ff35, 27701 }, /* XF86LightBulb */
- { 0x1008ff36, 28338 }, /* XF86Shop */
- { 0x1008ff37, 27400 }, /* XF86History */
- { 0x1008ff38, 28001 }, /* XF86OpenURL */
+ { 0x1008ff33, 27947 }, /* XF86MyComputer */
+ { 0x1008ff34, 28871 }, /* XF86VendorHome */
+ { 0x1008ff35, 27730 }, /* XF86LightBulb */
+ { 0x1008ff36, 28378 }, /* XF86Shop */
+ { 0x1008ff37, 27416 }, /* XF86History */
+ { 0x1008ff38, 28030 }, /* XF86OpenURL */
{ 0x1008ff39, 26655 }, /* XF86AddFavorite */
- { 0x1008ff3a, 27425 }, /* XF86HotLinks */
- { 0x1008ff3b, 27054 }, /* XF86BrightnessAdjust */
- { 0x1008ff3c, 27305 }, /* XF86Finance */
- { 0x1008ff3d, 27159 }, /* XF86Community */
- { 0x1008ff3e, 26946 }, /* XF86AudioRewind */
- { 0x1008ff3f, 26994 }, /* XF86BackForward */
- { 0x1008ff40, 27509 }, /* XF86Launch0 */
- { 0x1008ff41, 27521 }, /* XF86Launch1 */
- { 0x1008ff42, 27533 }, /* XF86Launch2 */
- { 0x1008ff43, 27545 }, /* XF86Launch3 */
- { 0x1008ff44, 27557 }, /* XF86Launch4 */
- { 0x1008ff45, 27569 }, /* XF86Launch5 */
- { 0x1008ff46, 27581 }, /* XF86Launch6 */
- { 0x1008ff47, 27593 }, /* XF86Launch7 */
- { 0x1008ff48, 27605 }, /* XF86Launch8 */
- { 0x1008ff49, 27617 }, /* XF86Launch9 */
- { 0x1008ff4a, 27629 }, /* XF86LaunchA */
- { 0x1008ff4b, 27641 }, /* XF86LaunchB */
- { 0x1008ff4c, 27653 }, /* XF86LaunchC */
- { 0x1008ff4d, 27665 }, /* XF86LaunchD */
- { 0x1008ff4e, 27677 }, /* XF86LaunchE */
- { 0x1008ff4f, 27689 }, /* XF86LaunchF */
+ { 0x1008ff3a, 27441 }, /* XF86HotLinks */
+ { 0x1008ff3b, 27070 }, /* XF86BrightnessAdjust */
+ { 0x1008ff3c, 27321 }, /* XF86Finance */
+ { 0x1008ff3d, 27175 }, /* XF86Community */
+ { 0x1008ff3e, 26962 }, /* XF86AudioRewind */
+ { 0x1008ff3f, 27010 }, /* XF86BackForward */
+ { 0x1008ff40, 27538 }, /* XF86Launch0 */
+ { 0x1008ff41, 27550 }, /* XF86Launch1 */
+ { 0x1008ff42, 27562 }, /* XF86Launch2 */
+ { 0x1008ff43, 27574 }, /* XF86Launch3 */
+ { 0x1008ff44, 27586 }, /* XF86Launch4 */
+ { 0x1008ff45, 27598 }, /* XF86Launch5 */
+ { 0x1008ff46, 27610 }, /* XF86Launch6 */
+ { 0x1008ff47, 27622 }, /* XF86Launch7 */
+ { 0x1008ff48, 27634 }, /* XF86Launch8 */
+ { 0x1008ff49, 27646 }, /* XF86Launch9 */
+ { 0x1008ff4a, 27658 }, /* XF86LaunchA */
+ { 0x1008ff4b, 27670 }, /* XF86LaunchB */
+ { 0x1008ff4c, 27682 }, /* XF86LaunchC */
+ { 0x1008ff4d, 27694 }, /* XF86LaunchD */
+ { 0x1008ff4e, 27706 }, /* XF86LaunchE */
+ { 0x1008ff4f, 27718 }, /* XF86LaunchF */
{ 0x1008ff50, 26671 }, /* XF86ApplicationLeft */
{ 0x1008ff51, 26691 }, /* XF86ApplicationRight */
- { 0x1008ff52, 27045 }, /* XF86Book */
- { 0x1008ff53, 27118 }, /* XF86CD */
- { 0x1008ff54, 27075 }, /* XF86Calculater */
- { 0x1008ff55, 27125 }, /* XF86Clear */
- { 0x1008ff56, 27149 }, /* XF86Close */
- { 0x1008ff57, 27192 }, /* XF86Copy */
- { 0x1008ff58, 27201 }, /* XF86Cut */
- { 0x1008ff59, 27224 }, /* XF86Display */
- { 0x1008ff5a, 27250 }, /* XF86DOS */
- { 0x1008ff5b, 27236 }, /* XF86Documents */
- { 0x1008ff5c, 27268 }, /* XF86Excel */
- { 0x1008ff5d, 27278 }, /* XF86Explorer */
- { 0x1008ff5e, 27360 }, /* XF86Game */
- { 0x1008ff5f, 27369 }, /* XF86Go */
- { 0x1008ff60, 27438 }, /* XF86iTouch */
- { 0x1008ff61, 27731 }, /* XF86LogOff */
- { 0x1008ff62, 27785 }, /* XF86Market */
- { 0x1008ff63, 27796 }, /* XF86Meeting */
- { 0x1008ff65, 27817 }, /* XF86MenuKB */
- { 0x1008ff66, 27828 }, /* XF86MenuPB */
- { 0x1008ff67, 27933 }, /* XF86MySites */
- { 0x1008ff68, 27945 }, /* XF86New */
- { 0x1008ff69, 27953 }, /* XF86News */
- { 0x1008ff6a, 27977 }, /* XF86OfficeHome */
- { 0x1008ff6b, 27992 }, /* XF86Open */
- { 0x1008ff6c, 28013 }, /* XF86Option */
- { 0x1008ff6d, 28024 }, /* XF86Paste */
- { 0x1008ff6e, 28034 }, /* XF86Phone */
- { 0x1008ff70, 28099 }, /* XF86Q */
- { 0x1008ff72, 28136 }, /* XF86Reply */
- { 0x1008ff73, 28125 }, /* XF86Reload */
- { 0x1008ff74, 28190 }, /* XF86RotateWindows */
- { 0x1008ff75, 28223 }, /* XF86RotationPB */
- { 0x1008ff76, 28208 }, /* XF86RotationKB */
- { 0x1008ff77, 28238 }, /* XF86Save */
- { 0x1008ff78, 28294 }, /* XF86ScrollUp */
- { 0x1008ff79, 28279 }, /* XF86ScrollDown */
- { 0x1008ff7a, 28263 }, /* XF86ScrollClick */
- { 0x1008ff7b, 28329 }, /* XF86Send */
- { 0x1008ff7c, 28357 }, /* XF86Spell */
- { 0x1008ff7d, 28367 }, /* XF86SplitScreen */
- { 0x1008ff7e, 28427 }, /* XF86Support */
- { 0x1008ff7f, 28646 }, /* XF86TaskPane */
- { 0x1008ff80, 28659 }, /* XF86Terminal */
- { 0x1008ff81, 28694 }, /* XF86Tools */
- { 0x1008ff82, 28766 }, /* XF86Travel */
- { 0x1008ff84, 28812 }, /* XF86UserPB */
- { 0x1008ff85, 28788 }, /* XF86User1KB */
- { 0x1008ff86, 28800 }, /* XF86User2KB */
- { 0x1008ff87, 28846 }, /* XF86Video */
- { 0x1008ff88, 28887 }, /* XF86WheelButton */
- { 0x1008ff89, 28912 }, /* XF86Word */
- { 0x1008ff8a, 28929 }, /* XF86Xfer */
- { 0x1008ff8b, 28949 }, /* XF86ZoomIn */
- { 0x1008ff8c, 28960 }, /* XF86ZoomOut */
- { 0x1008ff8d, 26976 }, /* XF86Away */
- { 0x1008ff8e, 27839 }, /* XF86Messenger */
- { 0x1008ff8f, 28876 }, /* XF86WebCam */
- { 0x1008ff90, 27769 }, /* XF86MailForward */
- { 0x1008ff91, 28044 }, /* XF86Pictures */
- { 0x1008ff92, 27908 }, /* XF86Music */
- { 0x1008ff93, 27010 }, /* XF86Battery */
- { 0x1008ff94, 27031 }, /* XF86Bluetooth */
- { 0x1008ff95, 28903 }, /* XF86WLAN */
- { 0x1008ff96, 28823 }, /* XF86UWB */
+ { 0x1008ff52, 27061 }, /* XF86Book */
+ { 0x1008ff53, 27134 }, /* XF86CD */
+ { 0x1008ff54, 27091 }, /* XF86Calculater */
+ { 0x1008ff55, 27141 }, /* XF86Clear */
+ { 0x1008ff56, 27165 }, /* XF86Close */
+ { 0x1008ff57, 27208 }, /* XF86Copy */
+ { 0x1008ff58, 27217 }, /* XF86Cut */
+ { 0x1008ff59, 27240 }, /* XF86Display */
+ { 0x1008ff5a, 27266 }, /* XF86DOS */
+ { 0x1008ff5b, 27252 }, /* XF86Documents */
+ { 0x1008ff5c, 27284 }, /* XF86Excel */
+ { 0x1008ff5d, 27294 }, /* XF86Explorer */
+ { 0x1008ff5e, 27376 }, /* XF86Game */
+ { 0x1008ff5f, 27385 }, /* XF86Go */
+ { 0x1008ff60, 27454 }, /* XF86iTouch */
+ { 0x1008ff61, 27760 }, /* XF86LogOff */
+ { 0x1008ff62, 27814 }, /* XF86Market */
+ { 0x1008ff63, 27825 }, /* XF86Meeting */
+ { 0x1008ff65, 27846 }, /* XF86MenuKB */
+ { 0x1008ff66, 27857 }, /* XF86MenuPB */
+ { 0x1008ff67, 27962 }, /* XF86MySites */
+ { 0x1008ff68, 27974 }, /* XF86New */
+ { 0x1008ff69, 27982 }, /* XF86News */
+ { 0x1008ff6a, 28006 }, /* XF86OfficeHome */
+ { 0x1008ff6b, 28021 }, /* XF86Open */
+ { 0x1008ff6c, 28042 }, /* XF86Option */
+ { 0x1008ff6d, 28053 }, /* XF86Paste */
+ { 0x1008ff6e, 28063 }, /* XF86Phone */
+ { 0x1008ff70, 28128 }, /* XF86Q */
+ { 0x1008ff72, 28165 }, /* XF86Reply */
+ { 0x1008ff73, 28154 }, /* XF86Reload */
+ { 0x1008ff74, 28230 }, /* XF86RotateWindows */
+ { 0x1008ff75, 28263 }, /* XF86RotationPB */
+ { 0x1008ff76, 28248 }, /* XF86RotationKB */
+ { 0x1008ff77, 28278 }, /* XF86Save */
+ { 0x1008ff78, 28334 }, /* XF86ScrollUp */
+ { 0x1008ff79, 28319 }, /* XF86ScrollDown */
+ { 0x1008ff7a, 28303 }, /* XF86ScrollClick */
+ { 0x1008ff7b, 28369 }, /* XF86Send */
+ { 0x1008ff7c, 28397 }, /* XF86Spell */
+ { 0x1008ff7d, 28407 }, /* XF86SplitScreen */
+ { 0x1008ff7e, 28467 }, /* XF86Support */
+ { 0x1008ff7f, 28686 }, /* XF86TaskPane */
+ { 0x1008ff80, 28699 }, /* XF86Terminal */
+ { 0x1008ff81, 28734 }, /* XF86Tools */
+ { 0x1008ff82, 28806 }, /* XF86Travel */
+ { 0x1008ff84, 28852 }, /* XF86UserPB */
+ { 0x1008ff85, 28828 }, /* XF86User1KB */
+ { 0x1008ff86, 28840 }, /* XF86User2KB */
+ { 0x1008ff87, 28886 }, /* XF86Video */
+ { 0x1008ff88, 28927 }, /* XF86WheelButton */
+ { 0x1008ff89, 28952 }, /* XF86Word */
+ { 0x1008ff8a, 28978 }, /* XF86Xfer */
+ { 0x1008ff8b, 28998 }, /* XF86ZoomIn */
+ { 0x1008ff8c, 29009 }, /* XF86ZoomOut */
+ { 0x1008ff8d, 26992 }, /* XF86Away */
+ { 0x1008ff8e, 27868 }, /* XF86Messenger */
+ { 0x1008ff8f, 28916 }, /* XF86WebCam */
+ { 0x1008ff90, 27798 }, /* XF86MailForward */
+ { 0x1008ff91, 28073 }, /* XF86Pictures */
+ { 0x1008ff92, 27937 }, /* XF86Music */
+ { 0x1008ff93, 27026 }, /* XF86Battery */
+ { 0x1008ff94, 27047 }, /* XF86Bluetooth */
+ { 0x1008ff95, 28943 }, /* XF86WLAN */
+ { 0x1008ff96, 28863 }, /* XF86UWB */
{ 0x1008ff97, 26732 }, /* XF86AudioForward */
- { 0x1008ff98, 26930 }, /* XF86AudioRepeat */
- { 0x1008ff99, 26894 }, /* XF86AudioRandomPlay */
- { 0x1008ff9a, 28414 }, /* XF86Subtitle */
+ { 0x1008ff98, 26946 }, /* XF86AudioRepeat */
+ { 0x1008ff99, 26910 }, /* XF86AudioRandomPlay */
+ { 0x1008ff9a, 28454 }, /* XF86Subtitle */
{ 0x1008ff9b, 26712 }, /* XF86AudioCycleTrack */
- { 0x1008ff9c, 27209 }, /* XF86CycleAngle */
- { 0x1008ff9d, 27329 }, /* XF86FrameBack */
- { 0x1008ff9e, 27343 }, /* XF86FrameForward */
- { 0x1008ff9f, 28672 }, /* XF86Time */
- { 0x1008ffa0, 28318 }, /* XF86Select */
- { 0x1008ffa1, 28856 }, /* XF86View */
- { 0x1008ffa2, 28704 }, /* XF86TopMenu */
- { 0x1008ffa3, 28105 }, /* XF86Red */
- { 0x1008ffa4, 27376 }, /* XF86Green */
- { 0x1008ffa5, 28938 }, /* XF86Yellow */
- { 0x1008ffa6, 27022 }, /* XF86Blue */
- { 0x1008ffa7, 28439 }, /* XF86Suspend */
- { 0x1008ffa8, 27386 }, /* XF86Hibernate */
- { 0x1008ffa9, 28747 }, /* XF86TouchpadToggle */
- { 0x1008ffb0, 28732 }, /* XF86TouchpadOn */
- { 0x1008ffb1, 28716 }, /* XF86TouchpadOff */
+ { 0x1008ff9c, 27225 }, /* XF86CycleAngle */
+ { 0x1008ff9d, 27345 }, /* XF86FrameBack */
+ { 0x1008ff9e, 27359 }, /* XF86FrameForward */
+ { 0x1008ff9f, 28712 }, /* XF86Time */
+ { 0x1008ffa0, 28358 }, /* XF86Select */
+ { 0x1008ffa1, 28896 }, /* XF86View */
+ { 0x1008ffa2, 28744 }, /* XF86TopMenu */
+ { 0x1008ffa3, 28134 }, /* XF86Red */
+ { 0x1008ffa4, 27392 }, /* XF86Green */
+ { 0x1008ffa5, 28987 }, /* XF86Yellow */
+ { 0x1008ffa6, 27038 }, /* XF86Blue */
+ { 0x1008ffa7, 28479 }, /* XF86Suspend */
+ { 0x1008ffa8, 27402 }, /* XF86Hibernate */
+ { 0x1008ffa9, 28787 }, /* XF86TouchpadToggle */
+ { 0x1008ffb0, 28772 }, /* XF86TouchpadOn */
+ { 0x1008ffb1, 28756 }, /* XF86TouchpadOff */
{ 0x1008ffb2, 26785 }, /* XF86AudioMicMute */
+ { 0x1008ffb3, 27525 }, /* XF86Keyboard */
+ { 0x1008ffb4, 28961 }, /* XF86WWAN */
+ { 0x1008ffb5, 28175 }, /* XF86RFKill */
+ { 0x1008ffb6, 26859 }, /* XF86AudioPreset */
};
diff --git a/src/3rdparty/xkbcommon/src/scanner-utils.h b/src/3rdparty/xkbcommon/src/scanner-utils.h
index e4e90eb0b6..5fdb22ae9a 100644
--- a/src/3rdparty/xkbcommon/src/scanner-utils.h
+++ b/src/3rdparty/xkbcommon/src/scanner-utils.h
@@ -34,13 +34,13 @@ typedef darray(struct sval) darray_sval;
static inline bool
svaleq(struct sval s1, struct sval s2)
{
- return s1.len == s2.len && strncmp(s1.start, s2.start, s1.len) == 0;
+ return s1.len == s2.len && memcmp(s1.start, s2.start, s1.len) == 0;
}
static inline bool
svaleq_prefix(struct sval s1, struct sval s2)
{
- return s1.len <= s2.len && strncmp(s1.start, s2.start, s1.len) == 0;
+ return s1.len <= s2.len && memcmp(s1.start, s2.start, s1.len) == 0;
}
struct scanner {
@@ -54,6 +54,7 @@ struct scanner {
unsigned token_line, token_column;
const char *file_name;
struct xkb_context *ctx;
+ void *priv;
};
#define scanner_log(scanner, level, fmt, ...) \
@@ -70,7 +71,8 @@ struct scanner {
static inline void
scanner_init(struct scanner *s, struct xkb_context *ctx,
- const char *string, size_t len, const char *file_name)
+ const char *string, size_t len, const char *file_name,
+ void *priv)
{
s->s = string;
s->len = len;
@@ -79,6 +81,7 @@ scanner_init(struct scanner *s, struct xkb_context *ctx,
s->token_line = s->token_column = 1;
s->file_name = file_name;
s->ctx = ctx;
+ s->priv = priv;
}
static inline char
@@ -101,6 +104,15 @@ eol(struct scanner *s)
return peek(s) == '\n';
}
+static inline void
+skip_to_eol(struct scanner *s)
+{
+ const char *nl = memchr(s->s + s->pos, '\n', s->len - s->pos);
+ const size_t new_pos = nl ? (size_t) (nl - s->s) : s->len;
+ s->column += new_pos - s->pos;
+ s->pos = new_pos;
+}
+
static inline char
next(struct scanner *s)
{
@@ -130,7 +142,7 @@ str(struct scanner *s, const char *string, size_t len)
{
if (s->len - s->pos < len)
return false;
- if (strncasecmp(s->s + s->pos, string, len) != 0)
+ if (memcmp(s->s + s->pos, string, len) != 0)
return false;
s->pos += len; s->column += len;
return true;
@@ -148,6 +160,17 @@ buf_append(struct scanner *s, char ch)
}
static inline bool
+buf_appends(struct scanner *s, const char *str)
+{
+ int ret;
+ ret = snprintf(s->buf + s->buf_pos, sizeof(s->buf) - s->buf_pos, "%s", str);
+ if (ret < 0 || (size_t) ret >= sizeof(s->buf) - s->buf_pos)
+ return false;
+ s->buf_pos += ret;
+ return true;
+}
+
+static inline bool
oct(struct scanner *s, uint8_t *out)
{
int i;
@@ -156,4 +179,17 @@ oct(struct scanner *s, uint8_t *out)
return i > 0;
}
+static inline bool
+hex(struct scanner *s, uint8_t *out)
+{
+ int i;
+ for (i = 0, *out = 0; is_xdigit(peek(s)) && i < 2; i++) {
+ const char c = next(s);
+ const char offset = (c >= '0' && c <= '9' ? '0' :
+ c >= 'a' && c <= 'f' ? 'a' - 10 : 'A' - 10);
+ *out = *out * 16 + c - offset;
+ }
+ return i > 0;
+}
+
#endif
diff --git a/src/3rdparty/xkbcommon/src/state.c b/src/3rdparty/xkbcommon/src/state.c
index 0f9ea79264..16a4caa23d 100644
--- a/src/3rdparty/xkbcommon/src/state.c
+++ b/src/3rdparty/xkbcommon/src/state.c
@@ -116,27 +116,34 @@ struct xkb_state {
struct xkb_keymap *keymap;
};
+/*
+ * If the virtual modifiers are not bound to anything, the entry
+ * is not active and should be skipped. xserver does this with
+ * cached entry->active field.
+ */
+static bool
+entry_is_active(const struct xkb_key_type_entry *entry)
+{
+ return entry->mods.mods == 0 || entry->mods.mask != 0;
+}
+
+static const struct xkb_key_type_entry *
+get_entry_for_mods(const struct xkb_key_type *type, xkb_mod_mask_t mods)
+{
+ for (unsigned i = 0; i < type->num_entries; i++)
+ if (entry_is_active(&type->entries[i]) &&
+ type->entries[i].mods.mask == mods)
+ return &type->entries[i];
+ return NULL;
+}
+
static const struct xkb_key_type_entry *
get_entry_for_key_state(struct xkb_state *state, const struct xkb_key *key,
xkb_layout_index_t group)
{
const struct xkb_key_type *type = key->groups[group].type;
xkb_mod_mask_t active_mods = state->components.mods & type->mods.mask;
-
- for (unsigned i = 0; i < type->num_entries; i++) {
- /*
- * If the virtual modifiers are not bound to anything, we're
- * supposed to skip the entry (xserver does this with cached
- * entry->active field).
- */
- if (!type->entries[i].mods.mask)
- continue;
-
- if (type->entries[i].mods.mask == active_mods)
- return &type->entries[i];
- }
-
- return NULL;
+ return get_entry_for_mods(type, active_mods);
}
/**
@@ -162,7 +169,7 @@ xkb_state_key_get_level(struct xkb_state *state, xkb_keycode_t kc,
}
xkb_layout_index_t
-wrap_group_into_range(int32_t group,
+XkbWrapGroupIntoRange(int32_t group,
xkb_layout_index_t num_groups,
enum xkb_range_exceed_type out_of_range_group_action,
xkb_layout_index_t out_of_range_group_number)
@@ -210,26 +217,26 @@ xkb_state_key_get_layout(struct xkb_state *state, xkb_keycode_t kc)
if (!key)
return XKB_LAYOUT_INVALID;
- return wrap_group_into_range(state->components.group, key->num_groups,
+ return XkbWrapGroupIntoRange(state->components.group, key->num_groups,
key->out_of_range_group_action,
key->out_of_range_group_number);
}
-static const union xkb_action fake = { .type = ACTION_TYPE_NONE };
-
static const union xkb_action *
xkb_key_get_action(struct xkb_state *state, const struct xkb_key *key)
{
+ static const union xkb_action dummy = { .type = ACTION_TYPE_NONE };
+
xkb_layout_index_t layout;
xkb_level_index_t level;
layout = xkb_state_key_get_layout(state, key->keycode);
if (layout == XKB_LAYOUT_INVALID)
- return &fake;
+ return &dummy;
level = xkb_state_key_get_level(state, key->keycode, layout);
if (level == XKB_LEVEL_INVALID)
- return &fake;
+ return &dummy;
return &key->groups[layout].levels[level].action;
}
@@ -257,6 +264,31 @@ xkb_filter_new(struct xkb_state *state)
/***====================================================================***/
+enum xkb_filter_result {
+ /*
+ * The event is consumed by the filters.
+ *
+ * An event is always processed by all filters, but any filter can
+ * prevent it from being processed further by consuming it.
+ */
+ XKB_FILTER_CONSUME,
+ /*
+ * The event may continue to be processed as far as this filter is
+ * concerned.
+ */
+ XKB_FILTER_CONTINUE,
+};
+
+static void
+xkb_filter_group_set_new(struct xkb_state *state, struct xkb_filter *filter)
+{
+ filter->priv = state->components.base_group;
+ if (filter->action.group.flags & ACTION_ABSOLUTE_SWITCH)
+ state->components.base_group = filter->action.group.group;
+ else
+ state->components.base_group += filter->action.group.group;
+}
+
static bool
xkb_filter_group_set_func(struct xkb_state *state,
struct xkb_filter *filter,
@@ -265,15 +297,15 @@ xkb_filter_group_set_func(struct xkb_state *state,
{
if (key != filter->key) {
filter->action.group.flags &= ~ACTION_LOCK_CLEAR;
- return true;
+ return XKB_FILTER_CONTINUE;
}
if (direction == XKB_KEY_DOWN) {
filter->refcnt++;
- return false;
+ return XKB_FILTER_CONSUME;
}
else if (--filter->refcnt > 0) {
- return false;
+ return XKB_FILTER_CONSUME;
}
state->components.base_group = filter->priv;
@@ -282,17 +314,16 @@ xkb_filter_group_set_func(struct xkb_state *state,
state->components.locked_group = 0;
filter->func = NULL;
- return true;
+ return XKB_FILTER_CONTINUE;
}
static void
-xkb_filter_group_set_new(struct xkb_state *state, struct xkb_filter *filter)
+xkb_filter_group_lock_new(struct xkb_state *state, struct xkb_filter *filter)
{
- filter->priv = state->components.base_group;
if (filter->action.group.flags & ACTION_ABSOLUTE_SWITCH)
- state->components.base_group = filter->action.group.group;
+ state->components.locked_group = filter->action.group.group;
else
- state->components.base_group += filter->action.group.group;
+ state->components.locked_group += filter->action.group.group;
}
static bool
@@ -302,26 +333,23 @@ xkb_filter_group_lock_func(struct xkb_state *state,
enum xkb_key_direction direction)
{
if (key != filter->key)
- return true;
+ return XKB_FILTER_CONTINUE;
if (direction == XKB_KEY_DOWN) {
filter->refcnt++;
- return false;
+ return XKB_FILTER_CONSUME;
}
if (--filter->refcnt > 0)
- return false;
+ return XKB_FILTER_CONSUME;
filter->func = NULL;
- return true;
+ return XKB_FILTER_CONTINUE;
}
static void
-xkb_filter_group_lock_new(struct xkb_state *state, struct xkb_filter *filter)
+xkb_filter_mod_set_new(struct xkb_state *state, struct xkb_filter *filter)
{
- if (filter->action.group.flags & ACTION_ABSOLUTE_SWITCH)
- state->components.locked_group = filter->action.group.group;
- else
- state->components.locked_group += filter->action.group.group;
+ state->set_mods = filter->action.mods.mods.mask;
}
static bool
@@ -332,15 +360,15 @@ xkb_filter_mod_set_func(struct xkb_state *state,
{
if (key != filter->key) {
filter->action.mods.flags &= ~ACTION_LOCK_CLEAR;
- return true;
+ return XKB_FILTER_CONTINUE;
}
if (direction == XKB_KEY_DOWN) {
filter->refcnt++;
- return false;
+ return XKB_FILTER_CONSUME;
}
else if (--filter->refcnt > 0) {
- return false;
+ return XKB_FILTER_CONSUME;
}
state->clear_mods = filter->action.mods.mods.mask;
@@ -348,13 +376,17 @@ xkb_filter_mod_set_func(struct xkb_state *state,
state->components.locked_mods &= ~filter->action.mods.mods.mask;
filter->func = NULL;
- return true;
+ return XKB_FILTER_CONTINUE;
}
static void
-xkb_filter_mod_set_new(struct xkb_state *state, struct xkb_filter *filter)
+xkb_filter_mod_lock_new(struct xkb_state *state, struct xkb_filter *filter)
{
- state->set_mods = filter->action.mods.mods.mask;
+ filter->priv = (state->components.locked_mods &
+ filter->action.mods.mods.mask);
+ state->set_mods |= filter->action.mods.mods.mask;
+ if (!(filter->action.mods.flags & ACTION_LOCK_NO_LOCK))
+ state->components.locked_mods |= filter->action.mods.mods.mask;
}
static bool
@@ -364,31 +396,21 @@ xkb_filter_mod_lock_func(struct xkb_state *state,
enum xkb_key_direction direction)
{
if (key != filter->key)
- return true;
+ return XKB_FILTER_CONTINUE;
if (direction == XKB_KEY_DOWN) {
filter->refcnt++;
- return false;
+ return XKB_FILTER_CONSUME;
}
if (--filter->refcnt > 0)
- return false;
+ return XKB_FILTER_CONSUME;
state->clear_mods |= filter->action.mods.mods.mask;
if (!(filter->action.mods.flags & ACTION_LOCK_NO_UNLOCK))
state->components.locked_mods &= ~filter->priv;
filter->func = NULL;
- return true;
-}
-
-static void
-xkb_filter_mod_lock_new(struct xkb_state *state, struct xkb_filter *filter)
-{
- filter->priv = (state->components.locked_mods &
- filter->action.mods.mods.mask);
- state->set_mods |= filter->action.mods.mods.mask;
- if (!(filter->action.mods.flags & ACTION_LOCK_NO_LOCK))
- state->components.locked_mods |= filter->action.mods.mods.mask;
+ return XKB_FILTER_CONTINUE;
}
enum xkb_key_latch_state {
@@ -414,6 +436,13 @@ xkb_action_breaks_latch(const union xkb_action *action)
}
}
+static void
+xkb_filter_mod_latch_new(struct xkb_state *state, struct xkb_filter *filter)
+{
+ filter->priv = LATCH_KEY_DOWN;
+ state->set_mods = filter->action.mods.mods.mask;
+}
+
static bool
xkb_filter_mod_latch_func(struct xkb_state *state,
struct xkb_filter *filter,
@@ -445,14 +474,14 @@ xkb_filter_mod_latch_func(struct xkb_state *state,
filter->key = key;
state->components.latched_mods &= ~filter->action.mods.mods.mask;
/* XXX beep beep! */
- return false;
+ return XKB_FILTER_CONSUME;
}
else if (xkb_action_breaks_latch(action)) {
/* XXX: This may be totally broken, we might need to break the
* latch in the next run after this press? */
state->components.latched_mods &= ~filter->action.mods.mods.mask;
filter->func = NULL;
- return true;
+ return XKB_FILTER_CONTINUE;
}
}
else if (direction == XKB_KEY_UP && key == filter->key) {
@@ -492,14 +521,7 @@ xkb_filter_mod_latch_func(struct xkb_state *state,
filter->priv = latch;
- return true;
-}
-
-static void
-xkb_filter_mod_latch_new(struct xkb_state *state, struct xkb_filter *filter)
-{
- filter->priv = LATCH_KEY_DOWN;
- state->set_mods = filter->action.mods.mods.mask;
+ return XKB_FILTER_CONTINUE;
}
static const struct {
@@ -531,17 +553,19 @@ xkb_filter_apply_all(struct xkb_state *state,
{
struct xkb_filter *filter;
const union xkb_action *action;
- bool send = true;
+ bool consumed;
/* First run through all the currently active filters and see if any of
- * them have claimed this event. */
+ * them have consumed this event. */
+ consumed = false;
darray_foreach(filter, state->filters) {
if (!filter->func)
continue;
- send = filter->func(state, filter, key, direction) && send;
- }
- if (!send || direction == XKB_KEY_UP)
+ if (filter->func(state, filter, key, direction) == XKB_FILTER_CONSUME)
+ consumed = true;
+ }
+ if (consumed || direction == XKB_KEY_UP)
return;
action = xkb_key_get_action(state, key);
@@ -560,9 +584,6 @@ xkb_filter_apply_all(struct xkb_state *state,
return;
filter = xkb_filter_new(state);
- if (!filter)
- return; /* WSGO */
-
filter->key = key;
filter->func = filter_action_funcs[action->type].func;
filter->action = *action;
@@ -619,7 +640,7 @@ xkb_state_led_update_all(struct xkb_state *state)
state->components.leds = 0;
- darray_enumerate(idx, led, state->keymap->leds) {
+ xkb_leds_enumerate(idx, led, state->keymap) {
xkb_mod_mask_t mod_mask = 0;
xkb_layout_mask_t group_mask = 0;
@@ -677,13 +698,13 @@ xkb_state_update_derived(struct xkb_state *state)
/* TODO: Use groups_wrap control instead of always RANGE_WRAP. */
- wrapped = wrap_group_into_range(state->components.locked_group,
+ wrapped = XkbWrapGroupIntoRange(state->components.locked_group,
state->keymap->num_groups,
RANGE_WRAP, 0);
state->components.locked_group =
(wrapped == XKB_LAYOUT_INVALID ? 0 : wrapped);
- wrapped = wrap_group_into_range(state->components.base_group +
+ wrapped = XkbWrapGroupIntoRange(state->components.base_group +
state->components.latched_group +
state->components.locked_group,
state->keymap->num_groups,
@@ -786,25 +807,37 @@ xkb_state_update_mask(struct xkb_state *state,
xkb_layout_index_t locked_group)
{
struct state_components prev_components;
- xkb_mod_index_t num_mods;
- xkb_mod_index_t idx;
+ xkb_mod_mask_t mask;
prev_components = state->components;
- state->components.base_mods = 0;
- state->components.latched_mods = 0;
- state->components.locked_mods = 0;
- num_mods = xkb_keymap_num_mods(state->keymap);
-
- for (idx = 0; idx < num_mods; idx++) {
- xkb_mod_mask_t mod = (1u << idx);
- if (base_mods & mod)
- state->components.base_mods |= mod;
- if (latched_mods & mod)
- state->components.latched_mods |= mod;
- if (locked_mods & mod)
- state->components.locked_mods |= mod;
- }
+ /* Only include modifiers which exist in the keymap. */
+ mask = (xkb_mod_mask_t) ((1ull << xkb_keymap_num_mods(state->keymap)) - 1u);
+
+ state->components.base_mods = base_mods & mask;
+ state->components.latched_mods = latched_mods & mask;
+ state->components.locked_mods = locked_mods & mask;
+
+ /* Make sure the mods are fully resolved - since we get arbitrary
+ * input, they might not be.
+ *
+ * It might seem more reasonable to do this only for components.mods
+ * in xkb_state_update_derived(), rather than for each component
+ * seperately. That would allow to distinguish between "really"
+ * depressed mods (would be in MODS_DEPRESSED) and indirectly
+ * depressed to to a mapping (would only be in MODS_EFFECTIVE).
+ * However, the traditional behavior of xkb_state_update_key() is that
+ * if a vmod is depressed, its mappings are depressed with it; so we're
+ * expected to do the same here. Also, LEDs (usually) look if a real
+ * mod is locked, not just effective; otherwise it won't be lit.
+ *
+ * We OR here because mod_mask_get_effective() drops vmods. */
+ state->components.base_mods |=
+ mod_mask_get_effective(state->keymap, state->components.base_mods);
+ state->components.latched_mods |=
+ mod_mask_get_effective(state->keymap, state->components.latched_mods);
+ state->components.locked_mods |=
+ mod_mask_get_effective(state->keymap, state->components.locked_mods);
state->components.base_group = base_group;
state->components.latched_group = latched_group;
@@ -843,7 +876,7 @@ err:
}
/*
- * http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Lock_Modifier
+ * https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Lock_Modifier
*/
static bool
should_do_caps_transformation(struct xkb_state *state, xkb_keycode_t kc)
@@ -857,7 +890,7 @@ should_do_caps_transformation(struct xkb_state *state, xkb_keycode_t kc)
}
/*
- * http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Control_Modifier
+ * https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Control_Modifier
*/
static bool
should_do_ctrl_transformation(struct xkb_state *state, xkb_keycode_t kc)
@@ -1081,6 +1114,28 @@ xkb_state_serialize_layout(struct xkb_state *state,
}
/**
+ * Gets a modifier mask and returns the resolved effective mask; this
+ * is needed because some modifiers can also map to other modifiers, e.g.
+ * the "NumLock" modifier usually also sets the "Mod2" modifier.
+ */
+xkb_mod_mask_t
+mod_mask_get_effective(struct xkb_keymap *keymap, xkb_mod_mask_t mods)
+{
+ const struct xkb_mod *mod;
+ xkb_mod_index_t i;
+ xkb_mod_mask_t mask;
+
+ /* The effective mask is only real mods for now. */
+ mask = mods & MOD_REAL_MASK_ALL;
+
+ xkb_mods_enumerate(i, mod, &keymap->mods)
+ if (mods & (1u << i))
+ mask |= mod->mapping;
+
+ return mask;
+}
+
+/**
* Returns 1 if the given modifier is active with the specified type(s), 0 if
* not, or -1 if the modifier is invalid.
*/
@@ -1099,7 +1154,7 @@ xkb_state_mod_index_is_active(struct xkb_state *state,
* Helper function for xkb_state_mod_indices_are_active and
* xkb_state_mod_names_are_active.
*/
-static int
+static bool
match_mod_masks(struct xkb_state *state,
enum xkb_state_component type,
enum xkb_state_match match,
@@ -1108,14 +1163,12 @@ match_mod_masks(struct xkb_state *state,
xkb_mod_mask_t active = xkb_state_serialize_mods(state, type);
if (!(match & XKB_STATE_MATCH_NON_EXCLUSIVE) && (active & ~wanted))
- return 0;
+ return false;
if (match & XKB_STATE_MATCH_ANY)
- return !!(active & wanted);
- else
- return (active & wanted) == wanted;
+ return active & wanted;
- return 0;
+ return (active & wanted) == wanted;
}
/**
@@ -1129,14 +1182,13 @@ xkb_state_mod_indices_are_active(struct xkb_state *state,
...)
{
va_list ap;
- xkb_mod_index_t idx = 0;
xkb_mod_mask_t wanted = 0;
int ret = 0;
xkb_mod_index_t num_mods = xkb_keymap_num_mods(state->keymap);
va_start(ap, match);
while (1) {
- idx = va_arg(ap, xkb_mod_index_t);
+ xkb_mod_index_t idx = va_arg(ap, xkb_mod_index_t);
if (idx == XKB_MOD_INVALID)
break;
if (idx >= num_mods) {
@@ -1180,12 +1232,12 @@ xkb_state_mod_names_are_active(struct xkb_state *state,
...)
{
va_list ap;
- xkb_mod_index_t idx = 0;
xkb_mod_mask_t wanted = 0;
int ret = 0;
va_start(ap, match);
while (1) {
+ xkb_mod_index_t idx;
const char *str = va_arg(ap, const char *);
if (str == NULL)
break;
@@ -1252,8 +1304,8 @@ xkb_state_layout_name_is_active(struct xkb_state *state, const char *name,
XKB_EXPORT int
xkb_state_led_index_is_active(struct xkb_state *state, xkb_led_index_t idx)
{
- if (idx >= darray_size(state->keymap->leds) ||
- darray_item(state->keymap->leds, idx).name == XKB_ATOM_NONE)
+ if (idx >= state->keymap->num_leds ||
+ state->keymap->leds[idx].name == XKB_ATOM_NONE)
return -1;
return !!(state->components.leds & (1u << idx));
@@ -1273,13 +1325,20 @@ xkb_state_led_name_is_active(struct xkb_state *state, const char *name)
return xkb_state_led_index_is_active(state, idx);
}
+/**
+ * See:
+ * - XkbTranslateKeyCode(3), mod_rtrn return value, from libX11.
+ * - MyEnhancedXkbTranslateKeyCode(), a modification of the above, from GTK+.
+ */
static xkb_mod_mask_t
-key_get_consumed(struct xkb_state *state, const struct xkb_key *key)
+key_get_consumed(struct xkb_state *state, const struct xkb_key *key,
+ enum xkb_consumed_mode mode)
{
const struct xkb_key_type *type;
- const struct xkb_key_type_entry *entry;
- xkb_mod_mask_t preserve;
+ const struct xkb_key_type_entry *matching_entry;
+ xkb_mod_mask_t preserve = 0;
xkb_layout_index_t group;
+ xkb_mod_mask_t consumed = 0;
group = xkb_state_key_get_layout(state, key->keycode);
if (group == XKB_LAYOUT_INVALID)
@@ -1287,47 +1346,64 @@ key_get_consumed(struct xkb_state *state, const struct xkb_key *key)
type = key->groups[group].type;
- entry = get_entry_for_key_state(state, key, group);
- if (entry)
- preserve = entry->preserve.mask;
- else
- preserve = 0;
+ matching_entry = get_entry_for_key_state(state, key, group);
+ if (matching_entry)
+ preserve = matching_entry->preserve.mask;
- return type->mods.mask & ~preserve;
+ switch (mode) {
+ case XKB_CONSUMED_MODE_XKB:
+ consumed = type->mods.mask;
+ break;
+
+ case XKB_CONSUMED_MODE_GTK: {
+ const struct xkb_key_type_entry *no_mods_entry;
+ xkb_level_index_t no_mods_leveli;
+ const struct xkb_level *no_mods_level, *level;
+
+ no_mods_entry = get_entry_for_mods(type, 0);
+ no_mods_leveli = no_mods_entry ? no_mods_entry->level : 0;
+ no_mods_level = &key->groups[group].levels[no_mods_leveli];
+
+ for (unsigned i = 0; i < type->num_entries; i++) {
+ const struct xkb_key_type_entry *entry = &type->entries[i];
+ if (!entry_is_active(entry))
+ continue;
+
+ level = &key->groups[group].levels[entry->level];
+ if (XkbLevelsSameSyms(level, no_mods_level))
+ continue;
+
+ if (entry == matching_entry || my_popcount(entry->mods.mask) == 1)
+ consumed |= entry->mods.mask & ~entry->preserve.mask;
+ }
+ break;
+ }
+ }
+
+ return consumed & ~preserve;
}
-/**
- * Tests to see if a modifier is used up by our translation of a
- * keycode to keysyms, taking note of the current modifier state and
- * the appropriate key type's preserve information, if any. This allows
- * the user to mask out the modifier in later processing of the
- * modifiers, e.g. when implementing hot keys or accelerators.
- *
- * See also, for example:
- * - XkbTranslateKeyCode(3), mod_rtrn return value, from libX11.
- * - gdk_keymap_translate_keyboard_state, consumed_modifiers return value,
- * from gtk+.
- */
XKB_EXPORT int
-xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t kc,
- xkb_mod_index_t idx)
+xkb_state_mod_index_is_consumed2(struct xkb_state *state, xkb_keycode_t kc,
+ xkb_mod_index_t idx,
+ enum xkb_consumed_mode mode)
{
const struct xkb_key *key = XkbKey(state->keymap, kc);
if (!key || idx >= xkb_keymap_num_mods(state->keymap))
return -1;
- return !!((1u << idx) & key_get_consumed(state, key));
+ return !!((1u << idx) & key_get_consumed(state, key, mode));
+}
+
+XKB_EXPORT int
+xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t kc,
+ xkb_mod_index_t idx)
+{
+ return xkb_state_mod_index_is_consumed2(state, kc, idx,
+ XKB_CONSUMED_MODE_XKB);
}
-/**
- * Calculates which modifiers should be consumed during key processing,
- * and returns the mask with all these modifiers removed. e.g. if
- * given a state of Alt and Shift active for a two-level alphabetic
- * key containing plus and equal on the first and second level
- * respectively, will return a mask of only Alt, as Shift has been
- * consumed by the type handling.
- */
XKB_EXPORT xkb_mod_mask_t
xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t kc,
xkb_mod_mask_t mask)
@@ -1337,16 +1413,34 @@ xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t kc,
if (!key)
return 0;
- return mask & ~key_get_consumed(state, key);
+ return mask & ~key_get_consumed(state, key, XKB_CONSUMED_MODE_XKB);
}
XKB_EXPORT xkb_mod_mask_t
-xkb_state_key_get_consumed_mods(struct xkb_state *state, xkb_keycode_t kc)
+xkb_state_key_get_consumed_mods2(struct xkb_state *state, xkb_keycode_t kc,
+ enum xkb_consumed_mode mode)
{
- const struct xkb_key *key = XkbKey(state->keymap, kc);
+ const struct xkb_key *key;
+ switch (mode) {
+ case XKB_CONSUMED_MODE_XKB:
+ case XKB_CONSUMED_MODE_GTK:
+ break;
+ default:
+ log_err_func(state->keymap->ctx,
+ "unrecognized consumed modifiers mode: %d\n", mode);
+ return 0;
+ }
+
+ key = XkbKey(state->keymap, kc);
if (!key)
return 0;
- return key_get_consumed(state, key);
+ return key_get_consumed(state, key, mode);
+}
+
+XKB_EXPORT xkb_mod_mask_t
+xkb_state_key_get_consumed_mods(struct xkb_state *state, xkb_keycode_t kc)
+{
+ return xkb_state_key_get_consumed_mods2(state, kc, XKB_CONSUMED_MODE_XKB);
}
diff --git a/src/3rdparty/xkbcommon/src/text.c b/src/3rdparty/xkbcommon/src/text.c
index f3a09e843d..1a44de47b4 100644
--- a/src/3rdparty/xkbcommon/src/text.c
+++ b/src/3rdparty/xkbcommon/src/text.c
@@ -204,32 +204,20 @@ const LookupEntry symInterpretMatchMaskNames[] = {
{ "AnyOf", MATCH_ANY },
{ "AllOf", MATCH_ALL },
{ "Exactly", MATCH_EXACTLY },
+ { NULL, 0 },
};
const char *
-ModIndexText(const struct xkb_keymap *keymap, xkb_mod_index_t ndx)
+ModIndexText(struct xkb_context *ctx, const struct xkb_mod_set *mods,
+ xkb_mod_index_t ndx)
{
if (ndx == XKB_MOD_INVALID)
return "none";
- if (ndx >= darray_size(keymap->mods))
+ if (ndx >= mods->num_mods)
return NULL;
- return xkb_atom_text(keymap->ctx, darray_item(keymap->mods, ndx).name);
-}
-
-xkb_mod_index_t
-ModNameToIndex(const struct xkb_keymap *keymap, xkb_atom_t name,
- enum mod_type type)
-{
- xkb_mod_index_t i;
- const struct xkb_mod *mod;
-
- darray_enumerate(i, mod, keymap->mods)
- if ((mod->type & type) && name == mod->name)
- return i;
-
- return XKB_MOD_INVALID;
+ return xkb_atom_text(ctx, mods->mods[ndx].name);
}
const char *
@@ -264,9 +252,10 @@ SIMatchText(enum xkb_match_operation type)
}
const char *
-ModMaskText(const struct xkb_keymap *keymap, xkb_mod_mask_t mask)
+ModMaskText(struct xkb_context *ctx, const struct xkb_mod_set *mods,
+ xkb_mod_mask_t mask)
{
- char buf[1024];
+ char buf[1024] = {0};
size_t pos = 0;
xkb_mod_index_t i;
const struct xkb_mod *mod;
@@ -277,7 +266,7 @@ ModMaskText(const struct xkb_keymap *keymap, xkb_mod_mask_t mask)
if (mask == MOD_REAL_MASK_ALL)
return "all";
- darray_enumerate(i, mod, keymap->mods) {
+ xkb_mods_enumerate(i, mod, mods) {
int ret;
if (!(mask & (1u << i)))
@@ -285,14 +274,14 @@ ModMaskText(const struct xkb_keymap *keymap, xkb_mod_mask_t mask)
ret = snprintf(buf + pos, sizeof(buf) - pos, "%s%s",
pos == 0 ? "" : "+",
- xkb_atom_text(keymap->ctx, mod->name));
+ xkb_atom_text(ctx, mod->name));
if (ret <= 0 || pos + ret >= sizeof(buf))
break;
else
pos += ret;
}
- return strcpy(xkb_context_get_buffer(keymap->ctx, pos + 1), buf);
+ return strcpy(xkb_context_get_buffer(ctx, pos + 1), buf);
}
const char *
diff --git a/src/3rdparty/xkbcommon/src/text.h b/src/3rdparty/xkbcommon/src/text.h
index 29f73abc95..584dea62d7 100644
--- a/src/3rdparty/xkbcommon/src/text.h
+++ b/src/3rdparty/xkbcommon/src/text.h
@@ -48,14 +48,12 @@ extern const LookupEntry actionTypeNames[];
extern const LookupEntry symInterpretMatchMaskNames[];
const char *
-ModMaskText(const struct xkb_keymap *keymap, xkb_mod_mask_t mask);
+ModMaskText(struct xkb_context *ctx, const struct xkb_mod_set *mods,
+ xkb_mod_mask_t mask);
const char *
-ModIndexText(const struct xkb_keymap *keymap, xkb_mod_index_t ndx);
-
-xkb_mod_index_t
-ModNameToIndex(const struct xkb_keymap *keymap, xkb_atom_t name,
- enum mod_type type);
+ModIndexText(struct xkb_context *ctx, const struct xkb_mod_set *mods,
+ xkb_mod_index_t ndx);
const char *
ActionTypeText(enum xkb_action_type type);
diff --git a/src/3rdparty/xkbcommon/src/utf8.c b/src/3rdparty/xkbcommon/src/utf8.c
index 11382c809d..a76b001bab 100644
--- a/src/3rdparty/xkbcommon/src/utf8.c
+++ b/src/3rdparty/xkbcommon/src/utf8.c
@@ -49,17 +49,13 @@ utf32_to_utf8(uint32_t unichar, char *buffer)
length = 3;
head = 0xe0;
}
- else if (unichar <= 0x1fffff) {
+ else if (unichar <= 0x10ffff) {
length = 4;
head = 0xf0;
}
- else if (unichar <= 0x3ffffff) {
- length = 5;
- head = 0xf8;
- }
else {
- length = 6;
- head = 0xfc;
+ buffer[0] = '\0';
+ return 0;
}
for (count = length - 1, shift = 0; count > 0; count--, shift += 6)
@@ -80,7 +76,7 @@ is_valid_utf8(const char *ss, size_t len)
/* This beauty is from:
* The Unicode Standard Version 6.2 - Core Specification, Table 3.7
- * http://www.unicode.org/versions/Unicode6.2.0/ch03.pdf#G7404
+ * https://www.unicode.org/versions/Unicode6.2.0/ch03.pdf#G7404
* We can optimize if needed. */
while (i < len)
{
diff --git a/src/3rdparty/xkbcommon/src/utils.c b/src/3rdparty/xkbcommon/src/utils.c
index a00b04eeec..a71b570b34 100644
--- a/src/3rdparty/xkbcommon/src/utils.c
+++ b/src/3rdparty/xkbcommon/src/utils.c
@@ -32,13 +32,16 @@
#include <sys/types.h>
bool
-map_file(FILE *file, const char **string_out, size_t *size_out)
+map_file(FILE *file, char **string_out, size_t *size_out)
{
struct stat stat_buf;
- const int fd = fileno(file);
+ int fd;
char *string;
/* Make sure to keep the errno on failure! */
+ fd = fileno(file);
+ if (fd < 0)
+ return false;
if (fstat(fd, &stat_buf) != 0)
return false;
@@ -53,15 +56,15 @@ map_file(FILE *file, const char **string_out, size_t *size_out)
}
void
-unmap_file(const char *str, size_t size)
+unmap_file(char *str, size_t size)
{
- munmap(UNCONSTIFY(str), size);
+ munmap(str, size);
}
#else
bool
-map_file(FILE *file, const char **string_out, size_t *size_out)
+map_file(FILE *file, char **string_out, size_t *size_out)
{
long ret;
size_t ret_s;
@@ -99,9 +102,62 @@ map_file(FILE *file, const char **string_out, size_t *size_out)
}
void
-unmap_file(const char *str, size_t size)
+unmap_file(char *str, size_t size)
{
- free(UNCONSTIFY(str));
+ free(str);
}
#endif
+
+// ASCII lower-case map.
+static const unsigned char lower_map[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
+ 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122,
+ 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
+ 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122,
+ 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
+ 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152,
+ 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
+ 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182,
+ 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
+ 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212,
+ 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
+ 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242,
+ 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
+};
+
+// ASCII tolower (to avoid locale issues).
+char
+to_lower(char c)
+{
+ return (char) lower_map[(unsigned char) c];
+}
+
+// ASCII strcasecmp (to avoid locale issues).
+int
+istrcmp(const char *a, const char *b)
+{
+ for (size_t i = 0; ; i++) {
+ if (to_lower(a[i]) != to_lower(b[i]))
+ return (int) to_lower(a[i]) - (int) to_lower(b[i]);
+ if (!a[i])
+ break;
+ }
+ return 0;
+}
+
+// ASCII strncasecmp (to avoid locale issues).
+int
+istrncmp(const char *a, const char *b, size_t n)
+{
+ for (size_t i = 0; i < n; i++) {
+ if (to_lower(a[i]) != to_lower(b[i]))
+ return (int) to_lower(a[i]) - (int) to_lower(b[i]);
+ if (!a[i])
+ break;
+ }
+ return 0;
+}
diff --git a/src/3rdparty/xkbcommon/src/utils.h b/src/3rdparty/xkbcommon/src/utils.h
index 878c2ac1e3..cb98e8e11a 100644
--- a/src/3rdparty/xkbcommon/src/utils.h
+++ b/src/3rdparty/xkbcommon/src/utils.h
@@ -29,7 +29,6 @@
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
-#include <strings.h>
#include "darray.h"
@@ -40,6 +39,19 @@
*/
#define UNCONSTIFY(const_ptr) ((void *) (uintptr_t) (const_ptr))
+#define STATIC_ASSERT(expr, message) do { \
+ switch (0) { case 0: case (expr): ; } \
+} while (0)
+
+char
+to_lower(char c);
+
+int
+istrcmp(const char *a, const char *b);
+
+int
+istrncmp(const char *a, const char *b, size_t n);
+
static inline bool
streq(const char *s1, const char *s2)
{
@@ -57,13 +69,13 @@ streq_not_null(const char *s1, const char *s2)
static inline bool
istreq(const char *s1, const char *s2)
{
- return strcasecmp(s1, s2) == 0;
+ return istrcmp(s1, s2) == 0;
}
static inline bool
istreq_prefix(const char *s1, const char *s2)
{
- return strncasecmp(s1, s2, strlen(s1)) == 0;
+ return istrncmp(s1, s2, strlen(s1)) == 0;
}
static inline char *
@@ -99,7 +111,7 @@ strempty(const char *s)
static inline void *
memdup(const void *mem, size_t nmemb, size_t size)
{
- void *p = malloc(nmemb * size);
+ void *p = calloc(nmemb, size);
if (p)
memcpy(p, mem, nmemb * size);
return p;
@@ -174,11 +186,25 @@ msb_pos(uint32_t mask)
return pos;
}
+// Avoid conflict with other popcount()s.
+static inline int
+my_popcount(uint32_t x)
+{
+ int count;
+#if defined(HAVE___BUILTIN_POPCOUNT)
+ count = __builtin_popcount(x);
+#else
+ for (count = 0; x; count++)
+ x &= x - 1;
+#endif
+ return count;
+}
+
bool
-map_file(FILE *file, const char **string_out, size_t *size_out);
+map_file(FILE *file, char **string_out, size_t *size_out);
void
-unmap_file(const char *str, size_t size);
+unmap_file(char *string, size_t size);
#define ARRAY_SIZE(arr) ((sizeof(arr) / sizeof(*(arr))))
@@ -187,6 +213,9 @@ unmap_file(const char *str, size_t size);
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MAX3(a, b, c) MAX(MAX((a), (b)), (c))
+/* Round up @a so it's divisible by @b. */
+#define ROUNDUP(a, b) (((a) + (b) - 1) / (b) * (b))
+
#if defined(HAVE_SECURE_GETENV)
# define secure_getenv secure_getenv
#elif defined(HAVE___SECURE_GETENV)
diff --git a/src/3rdparty/xkbcommon/src/x11/util.c b/src/3rdparty/xkbcommon/src/x11/util.c
index 7659c711a2..c41f1d6cd9 100644
--- a/src/3rdparty/xkbcommon/src/x11/util.c
+++ b/src/3rdparty/xkbcommon/src/x11/util.c
@@ -159,9 +159,10 @@ adopt_atoms(struct xkb_context *ctx, xcb_connection_t *conn,
{
enum { SIZE = 128 };
xcb_get_atom_name_cookie_t cookies[SIZE];
+ const size_t num_batches = ROUNDUP(count, SIZE) / SIZE;
/* Send and collect the atoms in batches of reasonable SIZE. */
- for (size_t batch = 0; batch <= count / SIZE; batch++) {
+ for (size_t batch = 0; batch < num_batches; batch++) {
const size_t start = batch * SIZE;
const size_t stop = min((batch + 1) * SIZE, count);
@@ -195,15 +196,12 @@ adopt_atoms(struct xkb_context *ctx, xcb_connection_t *conn,
/*
* If we don't discard the uncollected replies, they just
- * sit there waiting. Sad.
+ * sit in the XCB queue waiting forever. Sad.
*/
err_discard:
- for (size_t j = i + 1; j < stop; j++) {
- if (from[j] != XCB_ATOM_NONE) {
- reply = xcb_get_atom_name_reply(conn, cookies[j % SIZE], NULL);
- free(reply);
- }
- }
+ for (size_t j = i + 1; j < stop; j++)
+ if (from[j] != XCB_ATOM_NONE)
+ xcb_discard_reply(conn, cookies[j % SIZE].sequence);
return false;
}
}
diff --git a/src/3rdparty/xkbcommon/src/x11/x11-keymap.c b/src/3rdparty/xkbcommon/src/x11/x11-keymap.c
index 76adf7428d..701b614b2f 100644
--- a/src/3rdparty/xkbcommon/src/x11/x11-keymap.c
+++ b/src/3rdparty/xkbcommon/src/x11/x11-keymap.c
@@ -26,7 +26,7 @@
/*
* References for the lonesome traveler:
* Xkb protocol specification:
- * http://www.x.org/releases/current/doc/kbproto/xkbproto.html
+ * https://www.x.org/releases/current/doc/kbproto/xkbproto.html
* The XCB xkb XML protocol file:
* /user/share/xcb/xkb.xml
* The XCB xkb header file:
@@ -218,8 +218,8 @@ translate_action(union xkb_action *action, const xcb_xkb_action_t *wire)
case XCB_XKB_SA_TYPE_MOVE_PTR:
action->type = ACTION_TYPE_PTR_MOVE;
- action->ptr.x = (wire->moveptr.xLow | (wire->moveptr.xHigh << 8));
- action->ptr.y = (wire->moveptr.yLow | (wire->moveptr.yHigh << 8));
+ action->ptr.x = (int16_t) (wire->moveptr.xLow | ((uint16_t) wire->moveptr.xHigh << 8));
+ action->ptr.y = (int16_t) (wire->moveptr.yLow | ((uint16_t) wire->moveptr.yHigh << 8));
if (!(wire->moveptr.flags & XCB_XKB_SA_MOVE_PTR_FLAG_NO_ACCELERATION))
action->ptr.flags |= ACTION_ACCEL;
@@ -299,6 +299,20 @@ translate_action(union xkb_action *action, const xcb_xkb_action_t *wire)
case XCB_XKB_SA_TYPE_DEVICE_VALUATOR:
action->type = ACTION_TYPE_NONE;
break;
+
+ default:
+ if (wire->type < ACTION_TYPE_PRIVATE) {
+ action->type = ACTION_TYPE_NONE;
+ break;
+ }
+
+ /* Treat high unknown actions as Private actions. */
+ action->priv.type = wire->noaction.type;
+ STATIC_ASSERT(sizeof(action->priv.data) == 7 &&
+ sizeof(wire->noaction.pad0) == 7,
+ "The private action data must be 7 bytes long!");
+ memcpy(action->priv.data, wire->noaction.pad0, 7);
+ break;
}
}
@@ -434,6 +448,7 @@ get_sym_maps(struct xkb_keymap *keymap, xcb_connection_t *conn,
const xkb_layout_index_t group = j / wire_sym_map->width;
const xkb_level_index_t level = j % wire_sym_map->width;
+ assert(key->groups[group].type != NULL);
if (level < key->groups[group].type->num_levels &&
wire_keysym != XKB_KEY_NoSymbol) {
key->groups[group].levels[level].num_syms = 1;
@@ -508,13 +523,13 @@ get_vmods(struct xkb_keymap *keymap, xcb_connection_t *conn,
{
uint8_t *iter = xcb_xkb_get_map_map_vmods_rtrn(map);
- darray_resize0(keymap->mods,
- NUM_REAL_MODS + msb_pos(reply->virtualMods));
+ keymap->mods.num_mods =
+ NUM_REAL_MODS + MIN(msb_pos(reply->virtualMods), NUM_VMODS);
for (unsigned i = 0; i < NUM_VMODS; i++) {
if (reply->virtualMods & (1u << i)) {
uint8_t wire = *iter;
- struct xkb_mod *mod = &darray_item(keymap->mods, NUM_REAL_MODS + i);
+ struct xkb_mod *mod = &keymap->mods.mods[NUM_REAL_MODS + i];
mod->type = MOD_VIRT;
mod->mapping = translate_mods(wire, 0, 0);
@@ -685,12 +700,12 @@ get_indicators(struct xkb_keymap *keymap, xcb_connection_t *conn,
xcb_xkb_indicator_map_iterator_t iter =
xcb_xkb_get_indicator_map_maps_iterator(reply);
- darray_resize0(keymap->leds, msb_pos(reply->which));
+ keymap->num_leds = msb_pos(reply->which);
for (unsigned i = 0; i < NUM_INDICATORS; i++) {
if (reply->which & (1u << i)) {
xcb_xkb_indicator_map_t *wire = iter.data;
- struct xkb_led *led = &darray_item(keymap->leds, i);
+ struct xkb_led *led = &keymap->leds[i];
if (wire->whichGroups & XCB_XKB_IM_GROUPS_WHICH_USE_BASE)
led->which_groups |= XKB_STATE_LAYOUT_DEPRESSED;
@@ -789,7 +804,7 @@ get_sym_interprets(struct xkb_keymap *keymap, xcb_connection_t *conn,
}
sym_interpret->level_one_only =
- !!(wire->match & XCB_XKB_SYM_INTERP_MATCH_LEVEL_ONE_ONLY);
+ (wire->match & XCB_XKB_SYM_INTERP_MATCH_LEVEL_ONE_ONLY);
sym_interpret->mods = wire->mods;
if (wire->virtualMod == NO_MODIFIER)
@@ -797,7 +812,7 @@ get_sym_interprets(struct xkb_keymap *keymap, xcb_connection_t *conn,
else
sym_interpret->virtual_mod = NUM_REAL_MODS + wire->virtualMod;
- sym_interpret->repeat = !!(wire->flags & 0x01);
+ sym_interpret->repeat = (wire->flags & 0x01);
translate_action(&sym_interpret->action,
(xcb_xkb_action_t *) &wire->action);
@@ -887,12 +902,12 @@ get_indicator_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
{
xcb_atom_t *iter = xcb_xkb_get_names_value_list_indicator_names(list);
- FAIL_UNLESS(msb_pos(reply->indicators) <= darray_size(keymap->leds));
+ FAIL_UNLESS(msb_pos(reply->indicators) <= keymap->num_leds);
for (unsigned i = 0; i < NUM_INDICATORS; i++) {
if (reply->indicators & (1u << i)) {
xcb_atom_t wire = *iter;
- struct xkb_led *led = &darray_item(keymap->leds, i);
+ struct xkb_led *led = &keymap->leds[i];
if (!adopt_atom(keymap->ctx, conn, wire, &led->name))
return false;
@@ -919,12 +934,13 @@ get_vmod_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
* tells us which vmods exist (a vmod must have a name), so we fix
* up the size here.
*/
- darray_resize0(keymap->mods, NUM_REAL_MODS + msb_pos(reply->virtualMods));
+ keymap->mods.num_mods =
+ NUM_REAL_MODS + MIN(msb_pos(reply->virtualMods), NUM_VMODS);
for (unsigned i = 0; i < NUM_VMODS; i++) {
if (reply->virtualMods & (1u << i)) {
xcb_atom_t wire = *iter;
- struct xkb_mod *mod = &darray_item(keymap->mods, NUM_REAL_MODS + i);
+ struct xkb_mod *mod = &keymap->mods.mods[NUM_REAL_MODS + i];
if (!adopt_atom(keymap->ctx, conn, wire, &mod->name))
return false;
@@ -1115,7 +1131,7 @@ get_controls(struct xkb_keymap *keymap, xcb_connection_t *conn,
FAIL_UNLESS(keymap->max_key_code < XCB_XKB_CONST_PER_KEY_BIT_ARRAY_SIZE * 8);
for (xkb_keycode_t i = keymap->min_key_code; i <= keymap->max_key_code; i++)
- keymap->keys[i].repeats = !!(reply->perKeyRepeat[i / 8] & (1 << (i % 8)));
+ keymap->keys[i].repeats = (reply->perKeyRepeat[i / 8] & (1 << (i % 8)));
free(reply);
return true;
@@ -1139,7 +1155,7 @@ xkb_x11_keymap_new_from_device(struct xkb_context *ctx,
return NULL;
}
- if (device_id < 0 || device_id > 255) {
+ if (device_id < 0 || device_id > 127) {
log_err_func(ctx, "illegal device ID: %d\n", device_id);
return NULL;
}
diff --git a/src/3rdparty/xkbcommon/src/xkb-compat.c b/src/3rdparty/xkbcommon/src/xkb-compat.c
deleted file mode 100644
index 3cc3ab3d6e..0000000000
--- a/src/3rdparty/xkbcommon/src/xkb-compat.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright © 2012 Daniel Stone
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Author: Daniel Stone <daniel@fooishbar.org>
- */
-
-#define _XKBCOMMON_COMPAT_H /* don't mangle our legacy names! */
-
-#include "xkbcommon/xkbcommon.h"
-#include "utils.h"
-
-/* We don't carry any prototypes for these functions, as we #define them
- * to their newer versions so people link against those. */
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
-XKB_EXPORT struct xkb_keymap *
-xkb_map_new_from_names(struct xkb_context *context,
- const struct xkb_rule_names *names,
- enum xkb_keymap_compile_flags flags)
-{
- return xkb_keymap_new_from_names(context, names, flags);
-}
-
-XKB_EXPORT struct xkb_keymap *
-xkb_map_new_from_file(struct xkb_context *context, FILE *file,
- enum xkb_keymap_format format,
- enum xkb_keymap_compile_flags flags)
-{
- return xkb_keymap_new_from_file(context, file, format, flags);
-}
-
-XKB_EXPORT struct xkb_keymap *
-xkb_map_new_from_string(struct xkb_context *context, const char *string,
- enum xkb_keymap_format format,
- enum xkb_keymap_compile_flags flags)
-{
- return xkb_keymap_new_from_string(context, string, format, flags);
-}
-
-XKB_EXPORT char *
-xkb_map_get_as_string(struct xkb_keymap *keymap)
-{
- return xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
-}
-
-XKB_EXPORT struct xkb_keymap *
-xkb_map_ref(struct xkb_keymap *keymap)
-{
- return xkb_keymap_ref(keymap);
-}
-
-XKB_EXPORT void
-xkb_map_unref(struct xkb_keymap *keymap)
-{
- xkb_keymap_unref(keymap);
-}
-
-XKB_EXPORT xkb_mod_index_t
-xkb_map_num_mods(struct xkb_keymap *keymap)
-{
- return xkb_keymap_num_mods(keymap);
-}
-
-XKB_EXPORT const char *
-xkb_map_mod_get_name(struct xkb_keymap *keymap, xkb_mod_index_t idx)
-{
- return xkb_keymap_mod_get_name(keymap, idx);
-}
-
-XKB_EXPORT xkb_mod_index_t
-xkb_map_mod_get_index(struct xkb_keymap *keymap, const char *name)
-{
- return xkb_keymap_mod_get_index(keymap, name);
-}
-
-XKB_EXPORT bool
-xkb_key_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t kc,
- xkb_mod_index_t idx)
-{
- return xkb_state_mod_index_is_consumed(state, kc, idx);
-}
-
-XKB_EXPORT xkb_mod_mask_t
-xkb_key_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t kc,
- xkb_mod_mask_t mask)
-{
- return xkb_state_mod_mask_remove_consumed(state, kc, mask);
-}
-
-XKB_EXPORT xkb_layout_index_t
-xkb_map_num_groups(struct xkb_keymap *keymap)
-{
- return xkb_keymap_num_layouts(keymap);
-}
-
-XKB_EXPORT xkb_layout_index_t
-xkb_key_num_groups(struct xkb_keymap *keymap, xkb_keycode_t kc)
-{
- return xkb_keymap_num_layouts_for_key(keymap, kc);
-}
-
-XKB_EXPORT const char *
-xkb_map_group_get_name(struct xkb_keymap *keymap, xkb_layout_index_t idx)
-{
- return xkb_keymap_layout_get_name(keymap, idx);
-}
-
-XKB_EXPORT xkb_layout_index_t
-xkb_map_group_get_index(struct xkb_keymap *keymap, const char *name)
-{
- return xkb_keymap_layout_get_index(keymap, name);
-}
-
-XKB_EXPORT xkb_led_index_t
-xkb_map_num_leds(struct xkb_keymap *keymap)
-{
- return xkb_keymap_num_leds(keymap);
-}
-
-XKB_EXPORT const char *
-xkb_map_led_get_name(struct xkb_keymap *keymap, xkb_led_index_t idx)
-{
- return xkb_keymap_led_get_name(keymap, idx);
-}
-
-XKB_EXPORT xkb_led_index_t
-xkb_map_led_get_index(struct xkb_keymap *keymap, const char *name)
-{
- return xkb_keymap_led_get_index(keymap, name);
-}
-
-XKB_EXPORT bool
-xkb_key_repeats(struct xkb_keymap *keymap, xkb_keycode_t kc)
-{
- return xkb_keymap_key_repeats(keymap, kc);
-}
-
-XKB_EXPORT int
-xkb_key_get_syms(struct xkb_state *state, xkb_keycode_t kc,
- const xkb_keysym_t **syms_out)
-{
- return xkb_state_key_get_syms(state, kc, syms_out);
-}
-
-XKB_EXPORT bool
-xkb_state_group_name_is_active(struct xkb_state *state, const char *name,
- enum xkb_state_component type)
-{
- return xkb_state_layout_name_is_active(state, name, type);
-}
-
-XKB_EXPORT bool
-xkb_state_group_index_is_active(struct xkb_state *state, xkb_layout_index_t idx,
- enum xkb_state_component type)
-{
- return xkb_state_layout_index_is_active(state, idx, type);
-}
-
-XKB_EXPORT xkb_layout_index_t
-xkb_state_serialize_group(struct xkb_state *state,
- enum xkb_state_component type)
-{
- return xkb_state_serialize_layout(state, type);
-}
-
-XKB_EXPORT struct xkb_keymap *
-xkb_state_get_map(struct xkb_state *state)
-{
- return xkb_state_get_keymap(state);
-}
diff --git a/src/3rdparty/xkbcommon/src/xkb-keymap.c b/src/3rdparty/xkbcommon/src/xkb-keymap.c
deleted file mode 100644
index 892b7cf198..0000000000
--- a/src/3rdparty/xkbcommon/src/xkb-keymap.c
+++ /dev/null
@@ -1,493 +0,0 @@
-/**
- * Copyright © 2012 Intel Corporation
- * Copyright © 2012 Ran Benita <ran234@gmail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Author: Daniel Stone <daniel@fooishbar.org>
- */
-
-/************************************************************
- * Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
- *
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright
- * notice and this permission notice appear in supporting
- * documentation, and that the name of Silicon Graphics not be
- * used in advertising or publicity pertaining to distribution
- * of the software without specific prior written permission.
- * Silicon Graphics makes no representation about the suitability
- * of this software for any purpose. It is provided "as is"
- * without any express or implied warranty.
- *
- * SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
- * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
- * GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
- * THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * ********************************************************/
-
-#include "keymap.h"
-#include "text.h"
-
-XKB_EXPORT struct xkb_keymap *
-xkb_keymap_ref(struct xkb_keymap *keymap)
-{
- keymap->refcnt++;
- return keymap;
-}
-
-XKB_EXPORT void
-xkb_keymap_unref(struct xkb_keymap *keymap)
-{
- if (!keymap || --keymap->refcnt > 0)
- return;
-
- if (keymap->keys) {
- struct xkb_key *key;
- xkb_foreach_key(key, keymap) {
- if (key->groups) {
- for (unsigned i = 0; i < key->num_groups; i++) {
- if (key->groups[i].levels) {
- for (unsigned j = 0; j < XkbKeyGroupWidth(key, i); j++)
- if (key->groups[i].levels[j].num_syms > 1)
- free(key->groups[i].levels[j].u.syms);
- free(key->groups[i].levels);
- }
- }
- free(key->groups);
- }
- }
- free(keymap->keys);
- }
- if (keymap->types) {
- for (unsigned i = 0; i < keymap->num_types; i++) {
- free(keymap->types[i].entries);
- free(keymap->types[i].level_names);
- }
- free(keymap->types);
- }
- free(keymap->sym_interprets);
- free(keymap->key_aliases);
- free(keymap->group_names);
- darray_free(keymap->mods);
- darray_free(keymap->leds);
- free(keymap->keycodes_section_name);
- free(keymap->symbols_section_name);
- free(keymap->types_section_name);
- free(keymap->compat_section_name);
- xkb_context_unref(keymap->ctx);
- free(keymap);
-}
-
-static const struct xkb_keymap_format_ops *
-get_keymap_format_ops(enum xkb_keymap_format format)
-{
- static const struct xkb_keymap_format_ops *keymap_format_ops[] = {
- [XKB_KEYMAP_FORMAT_TEXT_V1] = &text_v1_keymap_format_ops,
- };
-
- if ((int) format < 0 || (int) format >= (int) ARRAY_SIZE(keymap_format_ops))
- return NULL;
-
- return keymap_format_ops[(int) format];
-}
-
-XKB_EXPORT struct xkb_keymap *
-xkb_keymap_new_from_names(struct xkb_context *ctx,
- const struct xkb_rule_names *rmlvo_in,
- enum xkb_keymap_compile_flags flags)
-{
- struct xkb_keymap *keymap;
- struct xkb_rule_names rmlvo;
- const enum xkb_keymap_format format = XKB_KEYMAP_FORMAT_TEXT_V1;
- const struct xkb_keymap_format_ops *ops;
-
- ops = get_keymap_format_ops(format);
- if (!ops || !ops->keymap_new_from_names) {
- log_err_func(ctx, "unsupported keymap format: %d\n", format);
- return NULL;
- }
-
- if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) {
- log_err_func(ctx, "unrecognized flags: %#x\n", flags);
- return NULL;
- }
-
- keymap = xkb_keymap_new(ctx, format, flags);
- if (!keymap)
- return NULL;
-
- if (rmlvo_in)
- rmlvo = *rmlvo_in;
- else
- memset(&rmlvo, 0, sizeof(rmlvo));
- xkb_context_sanitize_rule_names(ctx, &rmlvo);
-
- if (!ops->keymap_new_from_names(keymap, &rmlvo)) {
- xkb_keymap_unref(keymap);
- return NULL;
- }
-
- return keymap;
-}
-
-XKB_EXPORT struct xkb_keymap *
-xkb_keymap_new_from_string(struct xkb_context *ctx,
- const char *string,
- enum xkb_keymap_format format,
- enum xkb_keymap_compile_flags flags)
-{
- return xkb_keymap_new_from_buffer(ctx, string, strlen(string),
- format, flags);
-}
-
-XKB_EXPORT struct xkb_keymap *
-xkb_keymap_new_from_buffer(struct xkb_context *ctx,
- const char *buffer, size_t length,
- enum xkb_keymap_format format,
- enum xkb_keymap_compile_flags flags)
-{
- struct xkb_keymap *keymap;
- const struct xkb_keymap_format_ops *ops;
-
- ops = get_keymap_format_ops(format);
- if (!ops || !ops->keymap_new_from_string) {
- log_err_func(ctx, "unsupported keymap format: %d\n", format);
- return NULL;
- }
-
- if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) {
- log_err_func(ctx, "unrecognized flags: %#x\n", flags);
- return NULL;
- }
-
- if (!buffer) {
- log_err_func1(ctx, "no buffer specified\n");
- return NULL;
- }
-
- keymap = xkb_keymap_new(ctx, format, flags);
- if (!keymap)
- return NULL;
-
- if (!ops->keymap_new_from_string(keymap, buffer, length)) {
- xkb_keymap_unref(keymap);
- return NULL;
- }
-
- return keymap;
-}
-
-XKB_EXPORT struct xkb_keymap *
-xkb_keymap_new_from_file(struct xkb_context *ctx,
- FILE *file,
- enum xkb_keymap_format format,
- enum xkb_keymap_compile_flags flags)
-{
- struct xkb_keymap *keymap;
- const struct xkb_keymap_format_ops *ops;
-
- ops = get_keymap_format_ops(format);
- if (!ops || !ops->keymap_new_from_file) {
- log_err_func(ctx, "unsupported keymap format: %d\n", format);
- return NULL;
- }
-
- if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) {
- log_err_func(ctx, "unrecognized flags: %#x\n", flags);
- return NULL;
- }
-
- if (!file) {
- log_err_func1(ctx, "no file specified\n");
- return NULL;
- }
-
- keymap = xkb_keymap_new(ctx, format, flags);
- if (!keymap)
- return NULL;
-
- if (!ops->keymap_new_from_file(keymap, file)) {
- xkb_keymap_unref(keymap);
- return NULL;
- }
-
- return keymap;
-}
-
-XKB_EXPORT char *
-xkb_keymap_get_as_string(struct xkb_keymap *keymap,
- enum xkb_keymap_format format)
-{
- const struct xkb_keymap_format_ops *ops;
-
- if (format == XKB_KEYMAP_USE_ORIGINAL_FORMAT)
- format = keymap->format;
-
- ops = get_keymap_format_ops(format);
- if (!ops || !ops->keymap_get_as_string) {
- log_err_func(keymap->ctx, "unsupported keymap format: %d\n", format);
- return NULL;
- }
-
- return ops->keymap_get_as_string(keymap);
-}
-
-/**
- * Returns the total number of modifiers active in the keymap.
- */
-XKB_EXPORT xkb_mod_index_t
-xkb_keymap_num_mods(struct xkb_keymap *keymap)
-{
- return darray_size(keymap->mods);
-}
-
-/**
- * Return the name for a given modifier.
- */
-XKB_EXPORT const char *
-xkb_keymap_mod_get_name(struct xkb_keymap *keymap, xkb_mod_index_t idx)
-{
- if (idx >= darray_size(keymap->mods))
- return NULL;
-
- return xkb_atom_text(keymap->ctx, darray_item(keymap->mods, idx).name);
-}
-
-/**
- * Returns the index for a named modifier.
- */
-XKB_EXPORT xkb_mod_index_t
-xkb_keymap_mod_get_index(struct xkb_keymap *keymap, const char *name)
-{
- xkb_mod_index_t i;
- xkb_atom_t atom;
- const struct xkb_mod *mod;
-
- atom = xkb_atom_lookup(keymap->ctx, name);
- if (atom == XKB_ATOM_NONE)
- return XKB_MOD_INVALID;
-
- darray_enumerate(i, mod, keymap->mods)
- if (mod->name == atom)
- return i;
-
- return XKB_MOD_INVALID;
-}
-
-/**
- * Return the total number of active groups in the keymap.
- */
-XKB_EXPORT xkb_layout_index_t
-xkb_keymap_num_layouts(struct xkb_keymap *keymap)
-{
- return keymap->num_groups;
-}
-
-/**
- * Returns the name for a given group.
- */
-XKB_EXPORT const char *
-xkb_keymap_layout_get_name(struct xkb_keymap *keymap, xkb_layout_index_t idx)
-{
- if (idx >= keymap->num_group_names)
- return NULL;
-
- return xkb_atom_text(keymap->ctx, keymap->group_names[idx]);
-}
-
-/**
- * Returns the index for a named layout.
- */
-XKB_EXPORT xkb_layout_index_t
-xkb_keymap_layout_get_index(struct xkb_keymap *keymap, const char *name)
-{
- xkb_atom_t atom = xkb_atom_lookup(keymap->ctx, name);
- xkb_layout_index_t i;
-
- if (atom == XKB_ATOM_NONE)
- return XKB_LAYOUT_INVALID;
-
- for (i = 0; i < keymap->num_group_names; i++)
- if (keymap->group_names[i] == atom)
- return i;
-
- return XKB_LAYOUT_INVALID;
-}
-
-/**
- * Returns the number of layouts active for a particular key.
- */
-XKB_EXPORT xkb_layout_index_t
-xkb_keymap_num_layouts_for_key(struct xkb_keymap *keymap, xkb_keycode_t kc)
-{
- const struct xkb_key *key = XkbKey(keymap, kc);
-
- if (!key)
- return 0;
-
- return key->num_groups;
-}
-
-/**
- * Returns the number of levels active for a particular key and layout.
- */
-XKB_EXPORT xkb_level_index_t
-xkb_keymap_num_levels_for_key(struct xkb_keymap *keymap, xkb_keycode_t kc,
- xkb_layout_index_t layout)
-{
- const struct xkb_key *key = XkbKey(keymap, kc);
-
- if (!key)
- return 0;
-
- layout = wrap_group_into_range(layout, key->num_groups,
- key->out_of_range_group_action,
- key->out_of_range_group_number);
- if (layout == XKB_LAYOUT_INVALID)
- return 0;
-
- return XkbKeyGroupWidth(key, layout);
-}
-
-/**
- * Return the total number of LEDs in the keymap.
- */
-XKB_EXPORT xkb_led_index_t
-xkb_keymap_num_leds(struct xkb_keymap *keymap)
-{
- return darray_size(keymap->leds);
-}
-
-/**
- * Returns the name for a given LED.
- */
-XKB_EXPORT const char *
-xkb_keymap_led_get_name(struct xkb_keymap *keymap, xkb_led_index_t idx)
-{
- if (idx >= darray_size(keymap->leds))
- return NULL;
-
- return xkb_atom_text(keymap->ctx, darray_item(keymap->leds, idx).name);
-}
-
-/**
- * Returns the index for a named LED.
- */
-XKB_EXPORT xkb_led_index_t
-xkb_keymap_led_get_index(struct xkb_keymap *keymap, const char *name)
-{
- xkb_atom_t atom = xkb_atom_lookup(keymap->ctx, name);
- xkb_led_index_t i;
- const struct xkb_led *led;
-
- if (atom == XKB_ATOM_NONE)
- return XKB_LED_INVALID;
-
- darray_enumerate(i, led, keymap->leds)
- if (led->name == atom)
- return i;
-
- return XKB_LED_INVALID;
-}
-
-/**
- * As below, but takes an explicit layout/level rather than state.
- */
-XKB_EXPORT int
-xkb_keymap_key_get_syms_by_level(struct xkb_keymap *keymap,
- xkb_keycode_t kc,
- xkb_layout_index_t layout,
- xkb_level_index_t level,
- const xkb_keysym_t **syms_out)
-{
- const struct xkb_key *key = XkbKey(keymap, kc);
- int num_syms;
-
- if (!key)
- goto err;
-
- layout = wrap_group_into_range(layout, key->num_groups,
- key->out_of_range_group_action,
- key->out_of_range_group_number);
- if (layout == XKB_LAYOUT_INVALID)
- goto err;
-
- if (level >= XkbKeyGroupWidth(key, layout))
- goto err;
-
- num_syms = key->groups[layout].levels[level].num_syms;
- if (num_syms == 0)
- goto err;
-
- if (num_syms == 1)
- *syms_out = &key->groups[layout].levels[level].u.sym;
- else
- *syms_out = key->groups[layout].levels[level].u.syms;
-
- return num_syms;
-
-err:
- *syms_out = NULL;
- return 0;
-}
-
-XKB_EXPORT xkb_keycode_t
-xkb_keymap_min_keycode(struct xkb_keymap *keymap)
-{
- return keymap->min_key_code;
-}
-
-XKB_EXPORT xkb_keycode_t
-xkb_keymap_max_keycode(struct xkb_keymap *keymap)
-{
- return keymap->max_key_code;
-}
-
-XKB_EXPORT void
-xkb_keymap_key_for_each(struct xkb_keymap *keymap, xkb_keymap_key_iter_t iter,
- void *data)
-{
- struct xkb_key *key;
-
- xkb_foreach_key(key, keymap)
- iter(keymap, key->keycode, data);
-}
-
-/**
- * Simple boolean specifying whether or not the key should repeat.
- */
-XKB_EXPORT int
-xkb_keymap_key_repeats(struct xkb_keymap *keymap, xkb_keycode_t kc)
-{
- const struct xkb_key *key = XkbKey(keymap, kc);
-
- if (!key)
- return 0;
-
- return key->repeats;
-}
diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/action.c b/src/3rdparty/xkbcommon/src/xkbcomp/action.c
index eb3d37fbbe..f99a850083 100644
--- a/src/3rdparty/xkbcommon/src/xkbcomp/action.c
+++ b/src/3rdparty/xkbcommon/src/xkbcomp/action.c
@@ -103,7 +103,7 @@ enum action_field {
ActionsInfo *
NewActionsInfo(void)
{
- unsigned type;
+ enum xkb_action_type type;
ActionsInfo *info;
info = calloc(1, sizeof(*info));
@@ -168,7 +168,7 @@ static const LookupEntry fieldStrings[] = {
};
static bool
-stringToAction(const char *str, unsigned *type_rtrn)
+stringToAction(const char *str, enum xkb_action_type *type_rtrn)
{
return LookupString(actionTypeNames, str, type_rtrn);
}
@@ -221,9 +221,9 @@ ReportActionNotArray(struct xkb_context *ctx, enum xkb_action_type action,
}
static bool
-HandleNoAction(struct xkb_keymap *keymap, union xkb_action *action,
- enum action_field field, const ExprDef *array_ndx,
- const ExprDef *value)
+HandleNoAction(struct xkb_context *ctx, const struct xkb_mod_set *mods,
+ union xkb_action *action, enum action_field field,
+ const ExprDef *array_ndx, const ExprDef *value)
{
return true;
@@ -252,16 +252,17 @@ CheckBooleanFlag(struct xkb_context *ctx, enum xkb_action_type action,
}
static bool
-CheckModifierField(struct xkb_keymap *keymap, enum xkb_action_type action,
- const ExprDef *array_ndx, const ExprDef *value,
- enum xkb_action_flags *flags_inout, xkb_mod_mask_t *mods_rtrn)
+CheckModifierField(struct xkb_context *ctx, const struct xkb_mod_set *mods,
+ enum xkb_action_type action, const ExprDef *array_ndx,
+ const ExprDef *value, enum xkb_action_flags *flags_inout,
+ xkb_mod_mask_t *mods_rtrn)
{
if (array_ndx)
- return ReportActionNotArray(keymap->ctx, action, ACTION_FIELD_MODIFIERS);
+ return ReportActionNotArray(ctx, action, ACTION_FIELD_MODIFIERS);
if (value->expr.op == EXPR_IDENT) {
const char *valStr;
- valStr = xkb_atom_text(keymap->ctx, value->ident.ident);
+ valStr = xkb_atom_text(ctx, value->ident.ident);
if (valStr && (istreq(valStr, "usemodmapmods") ||
istreq(valStr, "modmapmods"))) {
*mods_rtrn = 0;
@@ -270,8 +271,8 @@ CheckModifierField(struct xkb_keymap *keymap, enum xkb_action_type action,
}
}
- if (!ExprResolveModMask(keymap, value, MOD_BOTH, mods_rtrn))
- return ReportMismatch(keymap->ctx, action,
+ if (!ExprResolveModMask(ctx, value, MOD_BOTH, mods, mods_rtrn))
+ return ReportMismatch(ctx, action,
ACTION_FIELD_MODIFIERS, "modifier mask");
*flags_inout &= ~ACTION_MODS_LOOKUP_MODMAP;
@@ -306,36 +307,36 @@ CheckAffectField(struct xkb_context *ctx, enum xkb_action_type action,
}
static bool
-HandleSetLatchLockMods(struct xkb_keymap *keymap, union xkb_action *action,
- enum action_field field, const ExprDef *array_ndx,
- const ExprDef *value)
+HandleSetLatchLockMods(struct xkb_context *ctx, const struct xkb_mod_set *mods,
+ union xkb_action *action, enum action_field field,
+ const ExprDef *array_ndx, const ExprDef *value)
{
struct xkb_mod_action *act = &action->mods;
const enum xkb_action_type type = action->type;
if (field == ACTION_FIELD_MODIFIERS)
- return CheckModifierField(keymap, action->type, array_ndx, value,
+ return CheckModifierField(ctx, mods, action->type, array_ndx, value,
&act->flags, &act->mods.mods);
if ((type == ACTION_TYPE_MOD_SET || type == ACTION_TYPE_MOD_LATCH) &&
field == ACTION_FIELD_CLEAR_LOCKS)
- return CheckBooleanFlag(keymap->ctx, action->type, field,
+ return CheckBooleanFlag(ctx, action->type, field,
ACTION_LOCK_CLEAR, array_ndx, value,
&act->flags);
if (type == ACTION_TYPE_MOD_LATCH &&
field == ACTION_FIELD_LATCH_TO_LOCK)
- return CheckBooleanFlag(keymap->ctx, action->type, field,
+ return CheckBooleanFlag(ctx, action->type, field,
ACTION_LATCH_TO_LOCK, array_ndx, value,
&act->flags);
if (type == ACTION_TYPE_MOD_LOCK &&
field == ACTION_FIELD_AFFECT)
- return CheckAffectField(keymap->ctx, action->type, array_ndx, value,
+ return CheckAffectField(ctx, action->type, array_ndx, value,
&act->flags);
- return ReportIllegal(keymap->ctx, action->type, field);
+ return ReportIllegal(ctx, action->type, field);
}
static bool
-CheckGroupField(struct xkb_context *ctx, unsigned action,
+CheckGroupField(struct xkb_context *ctx, enum xkb_action_type action,
const ExprDef *array_ndx, const ExprDef *value,
enum xkb_action_flags *flags_inout, int32_t *group_rtrn)
{
@@ -373,34 +374,34 @@ CheckGroupField(struct xkb_context *ctx, unsigned action,
}
static bool
-HandleSetLatchLockGroup(struct xkb_keymap *keymap, union xkb_action *action,
- enum action_field field, const ExprDef *array_ndx,
- const ExprDef *value)
+HandleSetLatchLockGroup(struct xkb_context *ctx, const struct xkb_mod_set *mods,
+ union xkb_action *action, enum action_field field,
+ const ExprDef *array_ndx, const ExprDef *value)
{
struct xkb_group_action *act = &action->group;
const enum xkb_action_type type = action->type;
if (field == ACTION_FIELD_GROUP)
- return CheckGroupField(keymap->ctx, action->type, array_ndx, value,
+ return CheckGroupField(ctx, action->type, array_ndx, value,
&act->flags, &act->group);
if ((type == ACTION_TYPE_GROUP_SET || type == ACTION_TYPE_GROUP_LATCH) &&
field == ACTION_FIELD_CLEAR_LOCKS)
- return CheckBooleanFlag(keymap->ctx, action->type, field,
+ return CheckBooleanFlag(ctx, action->type, field,
ACTION_LOCK_CLEAR, array_ndx, value,
&act->flags);
if (type == ACTION_TYPE_GROUP_LATCH &&
field == ACTION_FIELD_LATCH_TO_LOCK)
- return CheckBooleanFlag(keymap->ctx, action->type, field,
+ return CheckBooleanFlag(ctx, action->type, field,
ACTION_LATCH_TO_LOCK, array_ndx, value,
&act->flags);
- return ReportIllegal(keymap->ctx, action->type, field);
+ return ReportIllegal(ctx, action->type, field);
}
static bool
-HandleMovePtr(struct xkb_keymap *keymap, union xkb_action *action,
- enum action_field field, const ExprDef *array_ndx,
- const ExprDef *value)
+HandleMovePtr(struct xkb_context *ctx, const struct xkb_mod_set *mods,
+ union xkb_action *action, enum action_field field,
+ const ExprDef *array_ndx, const ExprDef *value)
{
struct xkb_pointer_action *act = &action->ptr;
@@ -410,13 +411,13 @@ HandleMovePtr(struct xkb_keymap *keymap, union xkb_action *action,
value->expr.op != EXPR_UNARY_PLUS);
if (array_ndx)
- return ReportActionNotArray(keymap->ctx, action->type, field);
+ return ReportActionNotArray(ctx, action->type, field);
- if (!ExprResolveInteger(keymap->ctx, value, &val))
- return ReportMismatch(keymap->ctx, action->type, field, "integer");
+ if (!ExprResolveInteger(ctx, value, &val))
+ return ReportMismatch(ctx, action->type, field, "integer");
if (val < INT16_MIN || val > INT16_MAX) {
- log_err(keymap->ctx,
+ log_err(ctx,
"The %s field in the %s action must be in range %d..%d; "
"Action definition ignored\n",
fieldText(field), ActionTypeText(action->type),
@@ -438,17 +439,17 @@ HandleMovePtr(struct xkb_keymap *keymap, union xkb_action *action,
return true;
}
else if (field == ACTION_FIELD_ACCEL) {
- return CheckBooleanFlag(keymap->ctx, action->type, field,
+ return CheckBooleanFlag(ctx, action->type, field,
ACTION_ACCEL, array_ndx, value, &act->flags);
}
- return ReportIllegal(keymap->ctx, action->type, field);
+ return ReportIllegal(ctx, action->type, field);
}
static bool
-HandlePtrBtn(struct xkb_keymap *keymap, union xkb_action *action,
- enum action_field field, const ExprDef *array_ndx,
- const ExprDef *value)
+HandlePtrBtn(struct xkb_context *ctx, const struct xkb_mod_set *mods,
+ union xkb_action *action, enum action_field field,
+ const ExprDef *array_ndx, const ExprDef *value)
{
struct xkb_pointer_button_action *act = &action->btn;
@@ -456,14 +457,14 @@ HandlePtrBtn(struct xkb_keymap *keymap, union xkb_action *action,
int btn;
if (array_ndx)
- return ReportActionNotArray(keymap->ctx, action->type, field);
+ return ReportActionNotArray(ctx, action->type, field);
- if (!ExprResolveButton(keymap->ctx, value, &btn))
- return ReportMismatch(keymap->ctx, action->type, field,
+ if (!ExprResolveButton(ctx, value, &btn))
+ return ReportMismatch(ctx, action->type, field,
"integer (range 1..5)");
if (btn < 0 || btn > 5) {
- log_err(keymap->ctx,
+ log_err(ctx,
"Button must specify default or be in the range 1..5; "
"Illegal button value %d ignored\n", btn);
return false;
@@ -474,20 +475,20 @@ HandlePtrBtn(struct xkb_keymap *keymap, union xkb_action *action,
}
else if (action->type == ACTION_TYPE_PTR_LOCK &&
field == ACTION_FIELD_AFFECT) {
- return CheckAffectField(keymap->ctx, action->type, array_ndx, value,
+ return CheckAffectField(ctx, action->type, array_ndx, value,
&act->flags);
}
else if (field == ACTION_FIELD_COUNT) {
int val;
if (array_ndx)
- return ReportActionNotArray(keymap->ctx, action->type, field);
+ return ReportActionNotArray(ctx, action->type, field);
- if (!ExprResolveInteger(keymap->ctx, value, &val))
- return ReportMismatch(keymap->ctx, action->type, field, "integer");
+ if (!ExprResolveInteger(ctx, value, &val))
+ return ReportMismatch(ctx, action->type, field, "integer");
if (val < 0 || val > 255) {
- log_err(keymap->ctx,
+ log_err(ctx,
"The count field must have a value in the range 0..255; "
"Illegal count %d ignored\n", val);
return false;
@@ -497,7 +498,7 @@ HandlePtrBtn(struct xkb_keymap *keymap, union xkb_action *action,
return true;
}
- return ReportIllegal(keymap->ctx, action->type, field);
+ return ReportIllegal(ctx, action->type, field);
}
static const LookupEntry ptrDflts[] = {
@@ -508,9 +509,9 @@ static const LookupEntry ptrDflts[] = {
};
static bool
-HandleSetPtrDflt(struct xkb_keymap *keymap, union xkb_action *action,
- enum action_field field, const ExprDef *array_ndx,
- const ExprDef *value)
+HandleSetPtrDflt(struct xkb_context *ctx, const struct xkb_mod_set *mods,
+ union xkb_action *action, enum action_field field,
+ const ExprDef *array_ndx, const ExprDef *value)
{
struct xkb_pointer_default_action *act = &action->dflt;
@@ -518,10 +519,10 @@ HandleSetPtrDflt(struct xkb_keymap *keymap, union xkb_action *action,
unsigned int val;
if (array_ndx)
- return ReportActionNotArray(keymap->ctx, action->type, field);
+ return ReportActionNotArray(ctx, action->type, field);
- if (!ExprResolveEnum(keymap->ctx, value, &val, ptrDflts))
- return ReportMismatch(keymap->ctx, action->type, field,
+ if (!ExprResolveEnum(ctx, value, &val, ptrDflts))
+ return ReportMismatch(ctx, action->type, field,
"pointer component");
return true;
}
@@ -530,7 +531,7 @@ HandleSetPtrDflt(struct xkb_keymap *keymap, union xkb_action *action,
int btn;
if (array_ndx)
- return ReportActionNotArray(keymap->ctx, action->type, field);
+ return ReportActionNotArray(ctx, action->type, field);
if (value->expr.op == EXPR_NEGATE ||
value->expr.op == EXPR_UNARY_PLUS) {
@@ -542,18 +543,18 @@ HandleSetPtrDflt(struct xkb_keymap *keymap, union xkb_action *action,
button = value;
}
- if (!ExprResolveButton(keymap->ctx, button, &btn))
- return ReportMismatch(keymap->ctx, action->type, field,
+ if (!ExprResolveButton(ctx, button, &btn))
+ return ReportMismatch(ctx, action->type, field,
"integer (range 1..5)");
if (btn < 0 || btn > 5) {
- log_err(keymap->ctx,
+ log_err(ctx,
"New default button value must be in the range 1..5; "
"Illegal default button value %d ignored\n", btn);
return false;
}
if (btn == 0) {
- log_err(keymap->ctx,
+ log_err(ctx,
"Cannot set default pointer button to \"default\"; "
"Illegal default button setting ignored\n");
return false;
@@ -563,13 +564,13 @@ HandleSetPtrDflt(struct xkb_keymap *keymap, union xkb_action *action,
return true;
}
- return ReportIllegal(keymap->ctx, action->type, field);
+ return ReportIllegal(ctx, action->type, field);
}
static bool
-HandleSwitchScreen(struct xkb_keymap *keymap, union xkb_action *action,
- enum action_field field, const ExprDef *array_ndx,
- const ExprDef *value)
+HandleSwitchScreen(struct xkb_context *ctx, const struct xkb_mod_set *mods,
+ union xkb_action *action, enum action_field field,
+ const ExprDef *array_ndx, const ExprDef *value)
{
struct xkb_switch_screen_action *act = &action->screen;
@@ -578,7 +579,7 @@ HandleSwitchScreen(struct xkb_keymap *keymap, union xkb_action *action,
int val;
if (array_ndx)
- return ReportActionNotArray(keymap->ctx, action->type, field);
+ return ReportActionNotArray(ctx, action->type, field);
if (value->expr.op == EXPR_NEGATE ||
value->expr.op == EXPR_UNARY_PLUS) {
@@ -590,12 +591,12 @@ HandleSwitchScreen(struct xkb_keymap *keymap, union xkb_action *action,
scrn = value;
}
- if (!ExprResolveInteger(keymap->ctx, scrn, &val))
- return ReportMismatch(keymap->ctx, action->type, field,
+ if (!ExprResolveInteger(ctx, scrn, &val))
+ return ReportMismatch(ctx, action->type, field,
"integer (0..255)");
if (val < 0 || val > 255) {
- log_err(keymap->ctx,
+ log_err(ctx,
"Screen index must be in the range 1..255; "
"Illegal screen value %d ignored\n", val);
return false;
@@ -605,46 +606,46 @@ HandleSwitchScreen(struct xkb_keymap *keymap, union xkb_action *action,
return true;
}
else if (field == ACTION_FIELD_SAME) {
- return CheckBooleanFlag(keymap->ctx, action->type, field,
+ return CheckBooleanFlag(ctx, action->type, field,
ACTION_SAME_SCREEN, array_ndx, value,
&act->flags);
}
- return ReportIllegal(keymap->ctx, action->type, field);
+ return ReportIllegal(ctx, action->type, field);
}
static bool
-HandleSetLockControls(struct xkb_keymap *keymap, union xkb_action *action,
- enum action_field field, const ExprDef *array_ndx,
- const ExprDef *value)
+HandleSetLockControls(struct xkb_context *ctx, const struct xkb_mod_set *mods,
+ union xkb_action *action, enum action_field field,
+ const ExprDef *array_ndx, const ExprDef *value)
{
struct xkb_controls_action *act = &action->ctrls;
if (field == ACTION_FIELD_CONTROLS) {
- unsigned int mask;
+ enum xkb_action_controls mask;
if (array_ndx)
- return ReportActionNotArray(keymap->ctx, action->type, field);
+ return ReportActionNotArray(ctx, action->type, field);
- if (!ExprResolveMask(keymap->ctx, value, &mask, ctrlMaskNames))
- return ReportMismatch(keymap->ctx, action->type, field,
+ if (!ExprResolveMask(ctx, value, &mask, ctrlMaskNames))
+ return ReportMismatch(ctx, action->type, field,
"controls mask");
act->ctrls = mask;
return true;
}
else if (field == ACTION_FIELD_AFFECT) {
- return CheckAffectField(keymap->ctx, action->type, array_ndx, value,
+ return CheckAffectField(ctx, action->type, array_ndx, value,
&act->flags);
}
- return ReportIllegal(keymap->ctx, action->type, field);
+ return ReportIllegal(ctx, action->type, field);
}
static bool
-HandlePrivate(struct xkb_keymap *keymap, union xkb_action *action,
- enum action_field field, const ExprDef *array_ndx,
- const ExprDef *value)
+HandlePrivate(struct xkb_context *ctx, const struct xkb_mod_set *mods,
+ union xkb_action *action, enum action_field field,
+ const ExprDef *array_ndx, const ExprDef *value)
{
struct xkb_private_action *act = &action->priv;
@@ -652,13 +653,13 @@ HandlePrivate(struct xkb_keymap *keymap, union xkb_action *action,
int type;
if (array_ndx)
- return ReportActionNotArray(keymap->ctx, action->type, field);
+ return ReportActionNotArray(ctx, action->type, field);
- if (!ExprResolveInteger(keymap->ctx, value, &type))
- return ReportMismatch(keymap->ctx, ACTION_TYPE_PRIVATE, field, "integer");
+ if (!ExprResolveInteger(ctx, value, &type))
+ return ReportMismatch(ctx, ACTION_TYPE_PRIVATE, field, "integer");
if (type < 0 || type > 255) {
- log_err(keymap->ctx,
+ log_err(ctx,
"Private action type must be in the range 0..255; "
"Illegal type %d ignored\n", type);
return false;
@@ -675,7 +676,7 @@ HandlePrivate(struct xkb_keymap *keymap, union xkb_action *action,
* make actions like these no-ops for now.
*/
if (type < ACTION_TYPE_PRIVATE) {
- log_info(keymap->ctx,
+ log_info(ctx,
"Private actions of type %s are not supported; Ignored\n",
ActionTypeText(type));
act->type = ACTION_TYPE_NONE;
@@ -692,44 +693,45 @@ HandlePrivate(struct xkb_keymap *keymap, union xkb_action *action,
const char *str;
size_t len;
- if (!ExprResolveString(keymap->ctx, value, &val))
- return ReportMismatch(keymap->ctx, action->type, field, "string");
+ if (!ExprResolveString(ctx, value, &val))
+ return ReportMismatch(ctx, action->type, field, "string");
- str = xkb_atom_text(keymap->ctx, val);
+ str = xkb_atom_text(ctx, val);
len = strlen(str);
if (len < 1 || len > 7) {
- log_warn(keymap->ctx,
+ log_warn(ctx,
"A private action has 7 data bytes; "
"Illegal data ignored\n");
return false;
}
+ /* act->data may not be null-terminated, this is intentional */
strncpy((char *) act->data, str, sizeof(act->data));
return true;
}
else {
int ndx, datum;
- if (!ExprResolveInteger(keymap->ctx, array_ndx, &ndx)) {
- log_err(keymap->ctx,
+ if (!ExprResolveInteger(ctx, array_ndx, &ndx)) {
+ log_err(ctx,
"Array subscript must be integer; "
"Illegal subscript ignored\n");
return false;
}
if (ndx < 0 || (size_t) ndx >= sizeof(act->data)) {
- log_err(keymap->ctx,
+ log_err(ctx,
"The data for a private action is %lu bytes long; "
"Attempt to use data[%d] ignored\n",
(unsigned long) sizeof(act->data), ndx);
return false;
}
- if (!ExprResolveInteger(keymap->ctx, value, &datum))
- return ReportMismatch(keymap->ctx, act->type, field, "integer");
+ if (!ExprResolveInteger(ctx, value, &datum))
+ return ReportMismatch(ctx, act->type, field, "integer");
if (datum < 0 || datum > 255) {
- log_err(keymap->ctx,
+ log_err(ctx,
"All data for a private action must be 0..255; "
"Illegal datum %d ignored\n", datum);
return false;
@@ -740,10 +742,11 @@ HandlePrivate(struct xkb_keymap *keymap, union xkb_action *action,
}
}
- return ReportIllegal(keymap->ctx, ACTION_TYPE_NONE, field);
+ return ReportIllegal(ctx, ACTION_TYPE_NONE, field);
}
-typedef bool (*actionHandler)(struct xkb_keymap *keymap,
+typedef bool (*actionHandler)(struct xkb_context *ctx,
+ const struct xkb_mod_set *mods,
union xkb_action *action,
enum action_field field,
const ExprDef *array_ndx,
@@ -771,22 +774,23 @@ static const actionHandler handleAction[_ACTION_TYPE_NUM_ENTRIES] = {
/***====================================================================***/
bool
-HandleActionDef(ExprDef *def, struct xkb_keymap *keymap,
- union xkb_action *action, ActionsInfo *info)
+HandleActionDef(struct xkb_context *ctx, ActionsInfo *info,
+ const struct xkb_mod_set *mods, ExprDef *def,
+ union xkb_action *action)
{
ExprDef *arg;
const char *str;
- unsigned handler_type;
+ enum xkb_action_type handler_type;
if (def->expr.op != EXPR_ACTION_DECL) {
- log_err(keymap->ctx, "Expected an action definition, found %s\n",
+ log_err(ctx, "Expected an action definition, found %s\n",
expr_op_type_to_string(def->expr.op));
return false;
}
- str = xkb_atom_text(keymap->ctx, def->action.name);
+ str = xkb_atom_text(ctx, def->action.name);
if (!stringToAction(str, &handler_type)) {
- log_err(keymap->ctx, "Unknown action %s\n", str);
+ log_err(ctx, "Unknown action %s\n", str);
return false;
}
@@ -822,12 +826,11 @@ HandleActionDef(ExprDef *def, struct xkb_keymap *keymap,
value = (const ExprDef *) &constTrue;
}
- if (!ExprResolveLhs(keymap->ctx, field, &elemRtrn, &fieldRtrn,
- &arrayRtrn))
+ if (!ExprResolveLhs(ctx, field, &elemRtrn, &fieldRtrn, &arrayRtrn))
return false;
if (elemRtrn) {
- log_err(keymap->ctx,
+ log_err(ctx,
"Cannot change defaults in an action definition; "
"Ignoring attempt to change %s.%s\n",
elemRtrn, fieldRtrn);
@@ -835,12 +838,12 @@ HandleActionDef(ExprDef *def, struct xkb_keymap *keymap,
}
if (!stringToField(fieldRtrn, &fieldNdx)) {
- log_err(keymap->ctx, "Unknown field name %s\n", fieldRtrn);
+ log_err(ctx, "Unknown field name %s\n", fieldRtrn);
return false;
}
- if (!handleAction[handler_type](keymap, action, fieldNdx, arrayRtrn,
- value))
+ if (!handleAction[handler_type](ctx, mods, action, fieldNdx,
+ arrayRtrn, value))
return false;
}
@@ -848,20 +851,21 @@ HandleActionDef(ExprDef *def, struct xkb_keymap *keymap,
}
bool
-SetActionField(struct xkb_keymap *keymap, const char *elem, const char *field,
- ExprDef *array_ndx, ExprDef *value, ActionsInfo *info)
+SetActionField(struct xkb_context *ctx, ActionsInfo *info,
+ struct xkb_mod_set *mods, const char *elem,
+ const char *field, ExprDef *array_ndx, ExprDef *value)
{
- unsigned action;
+ enum xkb_action_type action;
enum action_field action_field;
if (!stringToAction(elem, &action))
return false;
if (!stringToField(field, &action_field)) {
- log_err(keymap->ctx, "\"%s\" is not a legal field name\n", field);
+ log_err(ctx, "\"%s\" is not a legal field name\n", field);
return false;
}
- return handleAction[action](keymap, &info->actions[action],
+ return handleAction[action](ctx, mods, &info->actions[action],
action_field, array_ndx, value);
}
diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/action.h b/src/3rdparty/xkbcommon/src/xkbcomp/action.h
index 82915ef57d..1f92e7b38e 100644
--- a/src/3rdparty/xkbcommon/src/xkbcomp/action.h
+++ b/src/3rdparty/xkbcommon/src/xkbcomp/action.h
@@ -43,11 +43,14 @@ void
FreeActionsInfo(ActionsInfo *info);
bool
-HandleActionDef(ExprDef *def, struct xkb_keymap *keymap,
- union xkb_action *action, ActionsInfo *info);
+HandleActionDef(struct xkb_context *ctx, ActionsInfo *info,
+ const struct xkb_mod_set *mods, ExprDef *def,
+ union xkb_action *action);
bool
-SetActionField(struct xkb_keymap *keymap, const char *elem, const char *field,
- ExprDef *array_ndx, ExprDef *value, ActionsInfo *info);
+SetActionField(struct xkb_context *ctx, ActionsInfo *info,
+ struct xkb_mod_set *mods, const char *elem,
+ const char *field, ExprDef *array_ndx, ExprDef *value);
+
#endif
diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/ast-build.c b/src/3rdparty/xkbcommon/src/xkbcomp/ast-build.c
index 11bc0912d1..365ff51c5f 100644
--- a/src/3rdparty/xkbcommon/src/xkbcomp/ast-build.c
+++ b/src/3rdparty/xkbcommon/src/xkbcomp/ast-build.c
@@ -106,6 +106,13 @@ ExprCreateInteger(int ival)
}
ExprDef *
+ExprCreateFloat(void)
+{
+ EXPR_CREATE(ExprFloat, expr, EXPR_VALUE, EXPR_TYPE_FLOAT);
+ return expr;
+}
+
+ExprDef *
ExprCreateBoolean(bool set)
{
EXPR_CREATE(ExprBoolean, expr, EXPR_VALUE, EXPR_TYPE_BOOLEAN);
@@ -231,11 +238,9 @@ ExprAppendMultiKeysymList(ExprDef *expr, ExprDef *append)
darray_append(expr->keysym_list.symsMapIndex, nSyms);
darray_append(expr->keysym_list.symsNumEntries, numEntries);
- darray_append_items(expr->keysym_list.syms,
- darray_mem(append->keysym_list.syms, 0), numEntries);
+ darray_concat(expr->keysym_list.syms, append->keysym_list.syms);
- darray_resize(append->keysym_list.syms, 0);
- FreeStmt(&append->common);
+ FreeStmt((ParseCommon *) append);
return expr;
}
@@ -303,8 +308,21 @@ VarCreate(ExprDef *name, ExprDef *value)
VarDef *
BoolVarCreate(xkb_atom_t ident, bool set)
{
- return VarCreate((ExprDef *) ExprCreateIdent(ident),
- (ExprDef *) ExprCreateBoolean(set));
+ ExprDef *name, *value;
+ VarDef *def;
+ if (!(name = ExprCreateIdent(ident))) {
+ return NULL;
+ }
+ if (!(value = ExprCreateBoolean(set))) {
+ FreeStmt((ParseCommon *) name);
+ return NULL;
+ }
+ if (!(def = VarCreate(name, value))) {
+ FreeStmt((ParseCommon *) name);
+ FreeStmt((ParseCommon *) value);
+ return NULL;
+ }
+ return def;
}
InterpDef *
@@ -318,6 +336,7 @@ InterpCreate(xkb_keysym_t sym, ExprDef *match)
def->common.next = NULL;
def->sym = sym;
def->match = match;
+ def->def = NULL;
return def;
}
@@ -458,12 +477,8 @@ IncludeCreate(struct xkb_context *ctx, char *str, enum merge_mode merge)
incl = incl->next_incl;
}
- if (!incl) {
- log_wsgo(ctx,
- "Allocation failure in IncludeCreate; "
- "Using only part of the include\n");
+ if (!incl)
break;
- }
incl->common.type = STMT_INCLUDE;
incl->common.next = NULL;
@@ -506,8 +521,7 @@ XkbFileCreate(enum xkb_file_type type, char *name, ParseCommon *defs,
XkbEscapeMapName(name);
file->file_type = type;
- file->topName = strdup_safe(name);
- file->name = name;
+ file->name = name ? name : strdup("(unnamed)");
file->defs = defs;
file->flags = flags;
@@ -697,7 +711,6 @@ FreeXkbFile(XkbFile *file)
}
free(file->name);
- free(file->topName);
free(file);
file = next;
}
@@ -716,7 +729,7 @@ static const char *xkb_file_type_strings[_FILE_TYPE_NUM_ENTRIES] = {
const char *
xkb_file_type_to_string(enum xkb_file_type type)
{
- if (type > _FILE_TYPE_NUM_ENTRIES)
+ if (type >= _FILE_TYPE_NUM_ENTRIES)
return "unknown";
return xkb_file_type_strings[type];
}
@@ -777,6 +790,7 @@ static const char *expr_value_type_strings[_EXPR_TYPE_NUM_VALUES] = {
[EXPR_TYPE_UNKNOWN] = "unknown",
[EXPR_TYPE_BOOLEAN] = "boolean",
[EXPR_TYPE_INT] = "int",
+ [EXPR_TYPE_FLOAT] = "float",
[EXPR_TYPE_STRING] = "string",
[EXPR_TYPE_ACTION] = "action",
[EXPR_TYPE_KEYNAME] = "keyname",
diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/ast-build.h b/src/3rdparty/xkbcommon/src/xkbcomp/ast-build.h
index b57e4cdce1..6c76f381ac 100644
--- a/src/3rdparty/xkbcommon/src/xkbcomp/ast-build.h
+++ b/src/3rdparty/xkbcommon/src/xkbcomp/ast-build.h
@@ -37,6 +37,9 @@ ExprDef *
ExprCreateInteger(int ival);
ExprDef *
+ExprCreateFloat(void);
+
+ExprDef *
ExprCreateBoolean(bool set);
ExprDef *
diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/ast.h b/src/3rdparty/xkbcommon/src/xkbcomp/ast.h
index 26cbb3a3e4..49c5ada457 100644
--- a/src/3rdparty/xkbcommon/src/xkbcomp/ast.h
+++ b/src/3rdparty/xkbcommon/src/xkbcomp/ast.h
@@ -95,6 +95,7 @@ enum expr_value_type {
EXPR_TYPE_UNKNOWN = 0,
EXPR_TYPE_BOOLEAN,
EXPR_TYPE_INT,
+ EXPR_TYPE_FLOAT,
EXPR_TYPE_STRING,
EXPR_TYPE_ACTION,
EXPR_TYPE_KEYNAME,
@@ -188,6 +189,12 @@ typedef struct {
typedef struct {
ExprCommon expr;
+ /* We don't support floats, but we still represnt them in the AST, in
+ * order to provide proper error messages. */
+} ExprFloat;
+
+typedef struct {
+ ExprCommon expr;
xkb_atom_t key_name;
} ExprKeyName;
@@ -338,7 +345,6 @@ enum xkb_map_flags {
typedef struct {
ParseCommon common;
enum xkb_file_type file_type;
- char *topName;
char *name;
ParseCommon *defs;
enum xkb_map_flags flags;
diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/compat.c b/src/3rdparty/xkbcommon/src/xkbcomp/compat.c
index 475895c6c1..bd587c8db9 100644
--- a/src/3rdparty/xkbcommon/src/xkbcomp/compat.c
+++ b/src/3rdparty/xkbcommon/src/xkbcomp/compat.c
@@ -55,9 +55,9 @@
#include "include.h"
enum si_field {
- SI_FIELD_VIRTUAL_MOD = (1 << 0),
- SI_FIELD_ACTION = (1 << 1),
- SI_FIELD_AUTO_REPEAT = (1 << 2),
+ SI_FIELD_VIRTUAL_MOD = (1 << 0),
+ SI_FIELD_ACTION = (1 << 1),
+ SI_FIELD_AUTO_REPEAT = (1 << 2),
SI_FIELD_LEVEL_ONE_ONLY = (1 << 3),
};
@@ -69,9 +69,9 @@ typedef struct {
} SymInterpInfo;
enum led_field {
- LED_FIELD_MODS = (1 << 0),
- LED_FIELD_GROUPS = (1 << 1),
- LED_FIELD_CTRLS = (1 << 2),
+ LED_FIELD_MODS = (1 << 0),
+ LED_FIELD_GROUPS = (1 << 1),
+ LED_FIELD_CTRLS = (1 << 2),
};
typedef struct {
@@ -87,23 +87,26 @@ typedef struct {
SymInterpInfo default_interp;
darray(SymInterpInfo) interps;
LedInfo default_led;
- darray(LedInfo) leds;
+ LedInfo leds[XKB_MAX_LEDS];
+ unsigned int num_leds;
ActionsInfo *actions;
- struct xkb_keymap *keymap;
+ struct xkb_mod_set mods;
+
+ struct xkb_context *ctx;
} CompatInfo;
static const char *
siText(SymInterpInfo *si, CompatInfo *info)
{
- char *buf = xkb_context_get_buffer(info->keymap->ctx, 128);
+ char *buf = xkb_context_get_buffer(info->ctx, 128);
if (si == &info->default_interp)
return "default";
snprintf(buf, 128, "%s+%s(%s)",
- KeysymText(info->keymap->ctx, si->interp.sym),
+ KeysymText(info->ctx, si->interp.sym),
SIMatchText(si->interp.match),
- ModMaskText(info->keymap, si->interp.mods));
+ ModMaskText(info->ctx, &info->mods, si->interp.mods));
return buf;
}
@@ -111,7 +114,7 @@ siText(SymInterpInfo *si, CompatInfo *info)
static inline bool
ReportSINotArray(CompatInfo *info, SymInterpInfo *si, const char *field)
{
- return ReportNotArray(info->keymap->ctx, "symbol interpretation", field,
+ return ReportNotArray(info->ctx, "symbol interpretation", field,
siText(si, info));
}
@@ -119,7 +122,7 @@ static inline bool
ReportSIBadType(CompatInfo *info, SymInterpInfo *si, const char *field,
const char *wanted)
{
- return ReportBadType(info->keymap->ctx, "symbol interpretation", field,
+ return ReportBadType(info->ctx, "symbol interpretation", field,
siText(si, info), wanted);
}
@@ -127,25 +130,26 @@ static inline bool
ReportLedBadType(CompatInfo *info, LedInfo *ledi, const char *field,
const char *wanted)
{
- return ReportBadType(info->keymap->ctx, "indicator map", field,
- xkb_atom_text(info->keymap->ctx, ledi->led.name),
+ return ReportBadType(info->ctx, "indicator map", field,
+ xkb_atom_text(info->ctx, ledi->led.name),
wanted);
}
static inline bool
ReportLedNotArray(CompatInfo *info, LedInfo *ledi, const char *field)
{
- return ReportNotArray(info->keymap->ctx, "indicator map", field,
- xkb_atom_text(info->keymap->ctx, ledi->led.name));
+ return ReportNotArray(info->ctx, "indicator map", field,
+ xkb_atom_text(info->ctx, ledi->led.name));
}
static void
-InitCompatInfo(CompatInfo *info, struct xkb_keymap *keymap,
- ActionsInfo *actions)
+InitCompatInfo(CompatInfo *info, struct xkb_context *ctx,
+ ActionsInfo *actions, const struct xkb_mod_set *mods)
{
memset(info, 0, sizeof(*info));
- info->keymap = keymap;
+ info->ctx = ctx;
info->actions = actions;
+ info->mods = *mods;
info->default_interp.merge = MERGE_OVERRIDE;
info->default_interp.interp.virtual_mod = XKB_MOD_INVALID;
info->default_led.merge = MERGE_OVERRIDE;
@@ -156,7 +160,6 @@ ClearCompatInfo(CompatInfo *info)
{
free(info->name);
darray_free(info->interps);
- darray_free(info->leds);
}
static SymInterpInfo *
@@ -196,13 +199,13 @@ AddInterp(CompatInfo *info, SymInterpInfo *new, bool same_file)
{
SymInterpInfo *old = FindMatchingInterp(info, new);
if (old) {
- const int verbosity = xkb_context_get_log_verbosity(info->keymap->ctx);
+ const int verbosity = xkb_context_get_log_verbosity(info->ctx);
const bool report = (same_file && verbosity > 0) || verbosity > 9;
enum si_field collide = 0;
if (new->merge == MERGE_REPLACE) {
if (report)
- log_warn(info->keymap->ctx,
+ log_warn(info->ctx,
"Multiple definitions for \"%s\"; "
"Earlier interpretation ignored\n",
siText(new, info));
@@ -232,7 +235,7 @@ AddInterp(CompatInfo *info, SymInterpInfo *new, bool same_file)
}
if (collide) {
- log_warn(info->keymap->ctx,
+ log_warn(info->ctx,
"Multiple interpretations of \"%s\"; "
"Using %s definition for duplicate fields\n",
siText(new, info),
@@ -260,18 +263,17 @@ ResolveStateAndPredicate(ExprDef *expr, enum xkb_match_operation *pred_rtrn,
*pred_rtrn = MATCH_EXACTLY;
if (expr->expr.op == EXPR_ACTION_DECL) {
- const char *pred_txt = xkb_atom_text(info->keymap->ctx,
- expr->action.name);
- if (!LookupString(symInterpretMatchMaskNames, pred_txt, pred_rtrn)) {
- log_err(info->keymap->ctx,
+ const char *pred_txt = xkb_atom_text(info->ctx, expr->action.name);
+ if (!LookupString(symInterpretMatchMaskNames, pred_txt, pred_rtrn) ||
+ !expr->action.args) {
+ log_err(info->ctx,
"Illegal modifier predicate \"%s\"; Ignored\n", pred_txt);
return false;
}
expr = expr->action.args;
}
else if (expr->expr.op == EXPR_IDENT) {
- const char *pred_txt = xkb_atom_text(info->keymap->ctx,
- expr->ident.ident);
+ const char *pred_txt = xkb_atom_text(info->ctx, expr->ident.ident);
if (pred_txt && istreq(pred_txt, "any")) {
*pred_rtrn = MATCH_ANY;
*mods_rtrn = MOD_REAL_MASK_ALL;
@@ -279,7 +281,8 @@ ResolveStateAndPredicate(ExprDef *expr, enum xkb_match_operation *pred_rtrn,
}
}
- return ExprResolveModMask(info->keymap, expr, MOD_REAL, mods_rtrn);
+ return ExprResolveModMask(info->ctx, expr, MOD_REAL, &info->mods,
+ mods_rtrn);
}
/***====================================================================***/
@@ -305,13 +308,13 @@ UseNewLEDField(enum led_field field, LedInfo *old, LedInfo *new,
static bool
AddLedMap(CompatInfo *info, LedInfo *new, bool same_file)
{
- LedInfo *old;
enum led_field collide;
- struct xkb_context *ctx = info->keymap->ctx;
- const int verbosity = xkb_context_get_log_verbosity(ctx);
+ const int verbosity = xkb_context_get_log_verbosity(info->ctx);
const bool report = (same_file && verbosity > 0) || verbosity > 9;
- darray_foreach(old, info->leds) {
+ for (xkb_led_index_t i = 0; i < info->num_leds; i++) {
+ LedInfo *old = &info->leds[i];
+
if (old->led.name != new->led.name)
continue;
@@ -326,10 +329,10 @@ AddLedMap(CompatInfo *info, LedInfo *new, bool same_file)
if (new->merge == MERGE_REPLACE) {
if (report)
- log_warn(info->keymap->ctx,
+ log_warn(info->ctx,
"Map for indicator %s redefined; "
"Earlier definition ignored\n",
- xkb_atom_text(ctx, old->led.name));
+ xkb_atom_text(info->ctx, old->led.name));
*old = *new;
return true;
}
@@ -351,17 +354,23 @@ AddLedMap(CompatInfo *info, LedInfo *new, bool same_file)
}
if (collide) {
- log_warn(info->keymap->ctx,
+ log_warn(info->ctx,
"Map for indicator %s redefined; "
"Using %s definition for duplicate fields\n",
- xkb_atom_text(ctx, old->led.name),
+ xkb_atom_text(info->ctx, old->led.name),
(new->merge == MERGE_AUGMENT ? "first" : "last"));
}
return true;
}
- darray_append(info->leds, *new);
+ if (info->num_leds >= XKB_MAX_LEDS) {
+ log_err(info->ctx,
+ "Too many LEDs defined (maximum %d)\n",
+ XKB_MAX_LEDS);
+ return false;
+ }
+ info->leds[info->num_leds++] = *new;
return true;
}
@@ -369,14 +378,13 @@ static void
MergeIncludedCompatMaps(CompatInfo *into, CompatInfo *from,
enum merge_mode merge)
{
- SymInterpInfo *si;
- LedInfo *ledi;
-
if (from->errorCount > 0) {
into->errorCount += from->errorCount;
return;
}
+ into->mods = from->mods;
+
if (into->name == NULL) {
into->name = from->name;
from->name = NULL;
@@ -387,6 +395,7 @@ MergeIncludedCompatMaps(CompatInfo *into, CompatInfo *from,
darray_init(from->interps);
}
else {
+ SymInterpInfo *si;
darray_foreach(si, from->interps) {
si->merge = (merge == MERGE_DEFAULT ? si->merge : merge);
if (!AddInterp(into, si, false))
@@ -394,12 +403,14 @@ MergeIncludedCompatMaps(CompatInfo *into, CompatInfo *from,
}
}
- if (darray_empty(into->leds)) {
- into->leds = from->leds;
- darray_init(from->leds);
+ if (into->num_leds == 0) {
+ memcpy(into->leds, from->leds, sizeof(*from->leds) * from->num_leds);
+ into->num_leds = from->num_leds;
+ from->num_leds = 0;
}
else {
- darray_foreach(ledi, from->leds) {
+ for (xkb_led_index_t i = 0; i < from->num_leds; i++) {
+ LedInfo *ledi = &from->leds[i];
ledi->merge = (merge == MERGE_DEFAULT ? ledi->merge : merge);
if (!AddLedMap(into, ledi, false))
into->errorCount++;
@@ -415,7 +426,7 @@ HandleIncludeCompatMap(CompatInfo *info, IncludeStmt *include)
{
CompatInfo included;
- InitCompatInfo(&included, info->keymap, info->actions);
+ InitCompatInfo(&included, info->ctx, info->actions, &info->mods);
included.name = include->stmt;
include->stmt = NULL;
@@ -423,14 +434,14 @@ HandleIncludeCompatMap(CompatInfo *info, IncludeStmt *include)
CompatInfo next_incl;
XkbFile *file;
- file = ProcessIncludeFile(info->keymap->ctx, stmt, FILE_TYPE_COMPAT);
+ file = ProcessIncludeFile(info->ctx, stmt, FILE_TYPE_COMPAT);
if (!file) {
info->errorCount += 10;
ClearCompatInfo(&included);
return false;
}
- InitCompatInfo(&next_incl, info->keymap, info->actions);
+ InitCompatInfo(&next_incl, info->ctx, info->actions, &included.mods);
next_incl.default_interp = info->default_interp;
next_incl.default_interp.merge = stmt->merge;
next_incl.default_led = info->default_led;
@@ -454,14 +465,14 @@ static bool
SetInterpField(CompatInfo *info, SymInterpInfo *si, const char *field,
ExprDef *arrayNdx, ExprDef *value)
{
- struct xkb_keymap *keymap = info->keymap;
xkb_mod_index_t ndx;
if (istreq(field, "action")) {
if (arrayNdx)
return ReportSINotArray(info, si, field);
- if (!HandleActionDef(value, keymap, &si->interp.action, info->actions))
+ if (!HandleActionDef(info->ctx, info->actions, &info->mods,
+ value, &si->interp.action))
return false;
si->defined |= SI_FIELD_ACTION;
@@ -471,7 +482,7 @@ SetInterpField(CompatInfo *info, SymInterpInfo *si, const char *field,
if (arrayNdx)
return ReportSINotArray(info, si, field);
- if (!ExprResolveMod(keymap, value, MOD_VIRT, &ndx))
+ if (!ExprResolveMod(info->ctx, value, MOD_VIRT, &info->mods, &ndx))
return ReportSIBadType(info, si, field, "virtual modifier");
si->interp.virtual_mod = ndx;
@@ -483,7 +494,7 @@ SetInterpField(CompatInfo *info, SymInterpInfo *si, const char *field,
if (arrayNdx)
return ReportSINotArray(info, si, field);
- if (!ExprResolveBoolean(keymap->ctx, value, &set))
+ if (!ExprResolveBoolean(info->ctx, value, &set))
return ReportSIBadType(info, si, field, "boolean");
si->interp.repeat = set;
@@ -491,7 +502,7 @@ SetInterpField(CompatInfo *info, SymInterpInfo *si, const char *field,
si->defined |= SI_FIELD_AUTO_REPEAT;
}
else if (istreq(field, "locking")) {
- log_dbg(info->keymap->ctx,
+ log_dbg(info->ctx,
"The \"locking\" field in symbol interpretation is unsupported; "
"Ignored\n");
}
@@ -502,14 +513,14 @@ SetInterpField(CompatInfo *info, SymInterpInfo *si, const char *field,
if (arrayNdx)
return ReportSINotArray(info, si, field);
- if (!ExprResolveEnum(keymap->ctx, value, &val, useModMapValueNames))
+ if (!ExprResolveEnum(info->ctx, value, &val, useModMapValueNames))
return ReportSIBadType(info, si, field, "level specification");
- si->interp.level_one_only = !!val;
+ si->interp.level_one_only = val;
si->defined |= SI_FIELD_LEVEL_ONE_ONLY;
}
else {
- return ReportBadField(keymap->ctx, "symbol interpretation", field,
+ return ReportBadField(info->ctx, "symbol interpretation", field,
siText(si, info));
}
@@ -521,13 +532,13 @@ SetLedMapField(CompatInfo *info, LedInfo *ledi, const char *field,
ExprDef *arrayNdx, ExprDef *value)
{
bool ok = true;
- struct xkb_keymap *keymap = info->keymap;
if (istreq(field, "modifiers") || istreq(field, "mods")) {
if (arrayNdx)
return ReportLedNotArray(info, ledi, field);
- if (!ExprResolveModMask(keymap, value, MOD_BOTH, &ledi->led.mods.mods))
+ if (!ExprResolveModMask(info->ctx, value, MOD_BOTH,
+ &info->mods, &ledi->led.mods.mods))
return ReportLedBadType(info, ledi, field, "modifier mask");
ledi->defined |= LED_FIELD_MODS;
@@ -538,7 +549,7 @@ SetLedMapField(CompatInfo *info, LedInfo *ledi, const char *field,
if (arrayNdx)
return ReportLedNotArray(info, ledi, field);
- if (!ExprResolveMask(keymap->ctx, value, &mask, groupMaskNames))
+ if (!ExprResolveMask(info->ctx, value, &mask, groupMaskNames))
return ReportLedBadType(info, ledi, field, "group mask");
ledi->led.groups = mask;
@@ -550,14 +561,14 @@ SetLedMapField(CompatInfo *info, LedInfo *ledi, const char *field,
if (arrayNdx)
return ReportLedNotArray(info, ledi, field);
- if (!ExprResolveMask(keymap->ctx, value, &mask, ctrlMaskNames))
+ if (!ExprResolveMask(info->ctx, value, &mask, ctrlMaskNames))
return ReportLedBadType(info, ledi, field, "controls mask");
ledi->led.ctrls = mask;
ledi->defined |= LED_FIELD_CTRLS;
}
else if (istreq(field, "allowexplicit")) {
- log_dbg(info->keymap->ctx,
+ log_dbg(info->ctx,
"The \"allowExplicit\" field in indicator statements is unsupported; "
"Ignored\n");
}
@@ -568,7 +579,7 @@ SetLedMapField(CompatInfo *info, LedInfo *ledi, const char *field,
if (arrayNdx)
return ReportLedNotArray(info, ledi, field);
- if (!ExprResolveMask(keymap->ctx, value, &mask,
+ if (!ExprResolveMask(info->ctx, value, &mask,
modComponentMaskNames))
return ReportLedBadType(info, ledi, field,
"mask of modifier state components");
@@ -581,7 +592,7 @@ SetLedMapField(CompatInfo *info, LedInfo *ledi, const char *field,
if (arrayNdx)
return ReportLedNotArray(info, ledi, field);
- if (!ExprResolveMask(keymap->ctx, value, &mask,
+ if (!ExprResolveMask(info->ctx, value, &mask,
groupComponentMaskNames))
return ReportLedBadType(info, ledi, field,
"mask of group state components");
@@ -594,21 +605,21 @@ SetLedMapField(CompatInfo *info, LedInfo *ledi, const char *field,
istreq(field, "leddriveskeyboard") ||
istreq(field, "indicatordriveskbd") ||
istreq(field, "indicatordriveskeyboard")) {
- log_dbg(info->keymap->ctx,
+ log_dbg(info->ctx,
"The \"%s\" field in indicator statements is unsupported; "
"Ignored\n", field);
}
else if (istreq(field, "index")) {
/* Users should see this, it might cause unexpected behavior. */
- log_err(info->keymap->ctx,
+ log_err(info->ctx,
"The \"index\" field in indicator statements is unsupported; "
"Ignored\n");
}
else {
- log_err(info->keymap->ctx,
+ log_err(info->ctx,
"Unknown field %s in map for %s indicator; "
"Definition ignored\n",
- field, xkb_atom_text(keymap->ctx, ledi->led.name));
+ field, xkb_atom_text(info->ctx, ledi->led.name));
ok = false;
}
@@ -622,7 +633,7 @@ HandleGlobalVar(CompatInfo *info, VarDef *stmt)
ExprDef *ndx;
bool ret;
- if (!ExprResolveLhs(info->keymap->ctx, stmt->name, &elem, &field, &ndx))
+ if (!ExprResolveLhs(info->ctx, stmt->name, &elem, &field, &ndx))
ret = false;
else if (elem && istreq(elem, "interpret"))
ret = SetInterpField(info, &info->default_interp, field, ndx,
@@ -631,8 +642,8 @@ HandleGlobalVar(CompatInfo *info, VarDef *stmt)
ret = SetLedMapField(info, &info->default_led, field, ndx,
stmt->value);
else
- ret = SetActionField(info->keymap, elem, field, ndx, stmt->value,
- info->actions);
+ ret = SetActionField(info->ctx, info->actions, &info->mods,
+ elem, field, ndx, stmt->value);
return ret;
}
@@ -645,15 +656,14 @@ HandleInterpBody(CompatInfo *info, VarDef *def, SymInterpInfo *si)
for (; def; def = (VarDef *) def->common.next) {
if (def->name && def->name->expr.op == EXPR_FIELD_REF) {
- log_err(info->keymap->ctx,
+ log_err(info->ctx,
"Cannot set a global default value from within an interpret statement; "
"Move statements to the global file scope\n");
ok = false;
continue;
}
- ok = ExprResolveLhs(info->keymap->ctx, def->name, &elem, &field,
- &arrayNdx);
+ ok = ExprResolveLhs(info->ctx, def->name, &elem, &field, &arrayNdx);
if (!ok)
continue;
@@ -671,7 +681,7 @@ HandleInterpDef(CompatInfo *info, InterpDef *def, enum merge_mode merge)
SymInterpInfo si;
if (!ResolveStateAndPredicate(def->match, &pred, &mods, info)) {
- log_err(info->keymap->ctx,
+ log_err(info->ctx,
"Couldn't determine matching modifiers; "
"Symbol interpretation ignored\n");
return false;
@@ -714,14 +724,13 @@ HandleLedMapDef(CompatInfo *info, LedMapDef *def, enum merge_mode merge)
for (var = def->body; var != NULL; var = (VarDef *) var->common.next) {
const char *elem, *field;
ExprDef *arrayNdx;
- if (!ExprResolveLhs(info->keymap->ctx, var->name, &elem, &field,
- &arrayNdx)) {
+ if (!ExprResolveLhs(info->ctx, var->name, &elem, &field, &arrayNdx)) {
ok = false;
continue;
}
if (elem) {
- log_err(info->keymap->ctx,
+ log_err(info->ctx,
"Cannot set defaults for \"%s\" element in indicator map; "
"Assignment to %s.%s ignored\n", elem, elem, field);
ok = false;
@@ -756,7 +765,7 @@ HandleCompatMapFile(CompatInfo *info, XkbFile *file, enum merge_mode merge)
ok = HandleInterpDef(info, (InterpDef *) stmt, merge);
break;
case STMT_GROUP_COMPAT:
- log_dbg(info->keymap->ctx,
+ log_dbg(info->ctx,
"The \"group\" statement in compat is unsupported; "
"Ignored\n");
ok = true;
@@ -768,10 +777,10 @@ HandleCompatMapFile(CompatInfo *info, XkbFile *file, enum merge_mode merge)
ok = HandleGlobalVar(info, (VarDef *) stmt);
break;
case STMT_VMOD:
- ok = HandleVModDef(info->keymap, (VModDef *) stmt, merge);
+ ok = HandleVModDef(info->ctx, &info->mods, (VModDef *) stmt, merge);
break;
default:
- log_err(info->keymap->ctx,
+ log_err(info->ctx,
"Compat files may not include other types; "
"Ignoring %s\n", stmt_type_to_string(stmt->type));
ok = false;
@@ -782,8 +791,8 @@ HandleCompatMapFile(CompatInfo *info, XkbFile *file, enum merge_mode merge)
info->errorCount++;
if (info->errorCount > 10) {
- log_err(info->keymap->ctx,
- "Abandoning compatibility map \"%s\"\n", file->topName);
+ log_err(info->ctx,
+ "Abandoning compatibility map \"%s\"\n", file->name);
break;
}
}
@@ -807,34 +816,33 @@ CopyInterps(CompatInfo *info, bool needSymbol, enum xkb_match_operation pred,
}
static void
-CopyLedMapDefs(CompatInfo *info)
+CopyLedMapDefsToKeymap(struct xkb_keymap *keymap, CompatInfo *info)
{
- LedInfo *ledi;
- xkb_led_index_t i;
- struct xkb_led *led;
- struct xkb_keymap *keymap = info->keymap;
+ for (xkb_led_index_t idx = 0; idx < info->num_leds; idx++) {
+ LedInfo *ledi = &info->leds[idx];
+ xkb_led_index_t i;
+ struct xkb_led *led;
- darray_foreach(ledi, info->leds) {
/*
* Find the LED with the given name, if it was already declared
* in keycodes.
*/
- darray_enumerate(i, led, keymap->leds)
+ xkb_leds_enumerate(i, led, keymap)
if (led->name == ledi->led.name)
break;
/* Not previously declared; create it with next free index. */
- if (i >= darray_size(keymap->leds)) {
+ if (i >= keymap->num_leds) {
log_dbg(keymap->ctx,
"Indicator name \"%s\" was not declared in the keycodes section; "
"Adding new indicator\n",
xkb_atom_text(keymap->ctx, ledi->led.name));
- darray_enumerate(i, led, keymap->leds)
+ xkb_leds_enumerate(i, led, keymap)
if (led->name == XKB_ATOM_NONE)
break;
- if (i >= darray_size(keymap->leds)) {
+ if (i >= keymap->num_leds) {
/* Not place to put it; ignore. */
if (i >= XKB_MAX_LEDS) {
log_err(keymap->ctx,
@@ -844,9 +852,9 @@ CopyLedMapDefs(CompatInfo *info)
xkb_atom_text(keymap->ctx, ledi->led.name));
continue;
}
+
/* Add a new LED. */
- darray_resize(keymap->leds, i + 1);
- led = &darray_item(keymap->leds, i);
+ led = &keymap->leds[keymap->num_leds++];
}
}
@@ -864,6 +872,8 @@ CopyCompatToKeymap(struct xkb_keymap *keymap, CompatInfo *info)
keymap->compat_section_name = strdup_safe(info->name);
XkbEscapeMapName(keymap->compat_section_name);
+ keymap->mods = info->mods;
+
if (!darray_empty(info->interps)) {
struct collect collect;
darray_init(collect.sym_interprets);
@@ -880,11 +890,11 @@ CopyCompatToKeymap(struct xkb_keymap *keymap, CompatInfo *info)
CopyInterps(info, false, MATCH_ANY, &collect);
CopyInterps(info, false, MATCH_ANY_OR_NONE, &collect);
- keymap->num_sym_interprets = darray_size(collect.sym_interprets);
- keymap->sym_interprets = darray_mem(collect.sym_interprets, 0);
+ darray_steal(collect.sym_interprets,
+ &keymap->sym_interprets, &keymap->num_sym_interprets);
}
- CopyLedMapDefs(info);
+ CopyLedMapDefsToKeymap(keymap, info);
return true;
}
@@ -900,7 +910,7 @@ CompileCompatMap(XkbFile *file, struct xkb_keymap *keymap,
if (!actions)
return false;
- InitCompatInfo(&info, keymap, actions);
+ InitCompatInfo(&info, keymap->ctx, actions, &keymap->mods);
info.default_interp.merge = merge;
info.default_led.merge = merge;
diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/expr.c b/src/3rdparty/xkbcommon/src/xkbcomp/expr.c
index c514f8d54c..b2567de3eb 100644
--- a/src/3rdparty/xkbcommon/src/xkbcomp/expr.c
+++ b/src/3rdparty/xkbcommon/src/xkbcomp/expr.c
@@ -42,16 +42,20 @@ ExprResolveLhs(struct xkb_context *ctx, const ExprDef *expr,
*elem_rtrn = NULL;
*field_rtrn = xkb_atom_text(ctx, expr->ident.ident);
*index_rtrn = NULL;
- return true;
+ return (*field_rtrn != NULL);
case EXPR_FIELD_REF:
*elem_rtrn = xkb_atom_text(ctx, expr->field_ref.element);
*field_rtrn = xkb_atom_text(ctx, expr->field_ref.field);
*index_rtrn = NULL;
- return true;
+ return (*elem_rtrn != NULL && *field_rtrn != NULL);
case EXPR_ARRAY_REF:
*elem_rtrn = xkb_atom_text(ctx, expr->array_ref.element);
*field_rtrn = xkb_atom_text(ctx, expr->array_ref.field);
*index_rtrn = expr->array_ref.entry;
+ if (expr->array_ref.element != XKB_ATOM_NONE && *elem_rtrn == NULL)
+ return false;
+ if (*field_rtrn == NULL)
+ return false;
return true;
default:
break;
@@ -83,7 +87,7 @@ SimpleLookup(struct xkb_context *ctx, const void *priv, xkb_atom_t field,
/* Data passed in the *priv argument for LookupModMask. */
typedef struct {
- const struct xkb_keymap *keymap;
+ const struct xkb_mod_set *mods;
enum mod_type mod_type;
} LookupModMaskPriv;
@@ -94,13 +98,15 @@ LookupModMask(struct xkb_context *ctx, const void *priv, xkb_atom_t field,
const char *str;
xkb_mod_index_t ndx;
const LookupModMaskPriv *arg = priv;
- const struct xkb_keymap *keymap = arg->keymap;
+ const struct xkb_mod_set *mods = arg->mods;
enum mod_type mod_type = arg->mod_type;
if (type != EXPR_TYPE_INT)
return false;
str = xkb_atom_text(ctx, field);
+ if (!str)
+ return false;
if (istreq(str, "all")) {
*val_rtrn = MOD_REAL_MASK_ALL;
@@ -112,7 +118,7 @@ LookupModMask(struct xkb_context *ctx, const void *priv, xkb_atom_t field,
return true;
}
- ndx = ModNameToIndex(keymap, field, mod_type);
+ ndx = XkbModNameToIndex(mods, field, mod_type);
if (ndx == XKB_MOD_INVALID)
return false;
@@ -165,7 +171,7 @@ ExprResolveBoolean(struct xkb_context *ctx, const ExprDef *expr,
case EXPR_INVERT:
case EXPR_NOT:
- ok = ExprResolveBoolean(ctx, expr, set_rtrn);
+ ok = ExprResolveBoolean(ctx, expr->unary.child, set_rtrn);
if (ok)
*set_rtrn = !*set_rtrn;
return ok;
@@ -337,7 +343,9 @@ ExprResolveIntegerLookup(struct xkb_context *ctx, const ExprDef *expr,
*val_rtrn = l / r;
break;
default:
- break;
+ log_err(ctx, "%s of integers not permitted\n",
+ expr_op_type_to_string(expr->expr.op));
+ return false;
}
return true;
@@ -508,8 +516,8 @@ ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr,
unsigned int *val_rtrn, IdentLookupFunc lookup,
const void *lookupPriv)
{
- bool ok = 0;
- unsigned int l, r;
+ bool ok = false;
+ unsigned int l = 0, r = 0;
int v;
ExprDef *left, *right;
const char *bogus = NULL;
@@ -541,7 +549,7 @@ ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr,
case EXPR_ARRAY_REF:
bogus = "array reference";
-
+ /* fallthrough */
case EXPR_ACTION_DECL:
if (bogus == NULL)
bogus = "function use";
@@ -616,12 +624,12 @@ ExprResolveMask(struct xkb_context *ctx, const ExprDef *expr,
}
bool
-ExprResolveModMask(struct xkb_keymap *keymap, const ExprDef *expr,
- enum mod_type mod_type, xkb_mod_mask_t *mask_rtrn)
+ExprResolveModMask(struct xkb_context *ctx, const ExprDef *expr,
+ enum mod_type mod_type, const struct xkb_mod_set *mods,
+ xkb_mod_mask_t *mask_rtrn)
{
- LookupModMaskPriv priv = { .keymap = keymap, .mod_type = mod_type };
- return ExprResolveMaskLookup(keymap->ctx, expr, mask_rtrn, LookupModMask,
- &priv);
+ LookupModMaskPriv priv = { .mods = mods, .mod_type = mod_type };
+ return ExprResolveMaskLookup(ctx, expr, mask_rtrn, LookupModMask, &priv);
}
bool
@@ -648,14 +656,15 @@ ExprResolveKeySym(struct xkb_context *ctx, const ExprDef *expr,
}
bool
-ExprResolveMod(struct xkb_keymap *keymap, const ExprDef *def,
- enum mod_type mod_type, xkb_mod_index_t *ndx_rtrn)
+ExprResolveMod(struct xkb_context *ctx, const ExprDef *def,
+ enum mod_type mod_type, const struct xkb_mod_set *mods,
+ xkb_mod_index_t *ndx_rtrn)
{
xkb_mod_index_t ndx;
xkb_atom_t name;
if (def->expr.op != EXPR_IDENT) {
- log_err(keymap->ctx,
+ log_err(ctx,
"Cannot resolve virtual modifier: "
"found %s where a virtual modifier name was expected\n",
expr_op_type_to_string(def->expr.op));
@@ -663,12 +672,12 @@ ExprResolveMod(struct xkb_keymap *keymap, const ExprDef *def,
}
name = def->ident.ident;
- ndx = ModNameToIndex(keymap, name, mod_type);
+ ndx = XkbModNameToIndex(mods, name, mod_type);
if (ndx == XKB_MOD_INVALID) {
- log_err(keymap->ctx,
+ log_err(ctx,
"Cannot resolve virtual modifier: "
"\"%s\" was not previously declared\n",
- xkb_atom_text(keymap->ctx, name));
+ xkb_atom_text(ctx, name));
return false;
}
diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/expr.h b/src/3rdparty/xkbcommon/src/xkbcomp/expr.h
index 5434ad199e..9882b8cce5 100644
--- a/src/3rdparty/xkbcommon/src/xkbcomp/expr.h
+++ b/src/3rdparty/xkbcommon/src/xkbcomp/expr.h
@@ -33,12 +33,14 @@ ExprResolveLhs(struct xkb_context *ctx, const ExprDef *expr,
ExprDef **index_rtrn);
bool
-ExprResolveModMask(struct xkb_keymap *keymap, const ExprDef *expr,
- enum mod_type mod_type, xkb_mod_mask_t *mask_rtrn);
+ExprResolveModMask(struct xkb_context *ctx, const ExprDef *expr,
+ enum mod_type mod_type, const struct xkb_mod_set *mods,
+ xkb_mod_mask_t *mask_rtrn);
bool
-ExprResolveMod(struct xkb_keymap *keymap, const ExprDef *def,
- enum mod_type mod_type, xkb_mod_index_t *ndx_rtrn);
+ExprResolveMod(struct xkb_context *ctx, const ExprDef *def,
+ enum mod_type mod_type, const struct xkb_mod_set *mods,
+ xkb_mod_index_t *ndx_rtrn);
bool
ExprResolveBoolean(struct xkb_context *ctx, const ExprDef *expr,
diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/keycodes.c b/src/3rdparty/xkbcommon/src/xkbcomp/keycodes.c
index d90f6a4465..491da51067 100644
--- a/src/3rdparty/xkbcommon/src/xkbcomp/keycodes.c
+++ b/src/3rdparty/xkbcommon/src/xkbcomp/keycodes.c
@@ -49,7 +49,8 @@ typedef struct {
xkb_keycode_t min_key_code;
xkb_keycode_t max_key_code;
darray(xkb_atom_t) key_names;
- darray(LedNameInfo) led_names;
+ LedNameInfo led_names[XKB_MAX_LEDS];
+ unsigned int num_led_names;
darray(AliasInfo) aliases;
struct xkb_context *ctx;
@@ -71,10 +72,8 @@ static LedNameInfo *
FindLedByName(KeyNamesInfo *info, xkb_atom_t name,
xkb_led_index_t *idx_out)
{
- LedNameInfo *ledi;
- xkb_led_index_t idx;
-
- darray_enumerate(idx, ledi, info->led_names) {
+ for (xkb_led_index_t idx = 0; idx < info->num_led_names; idx++) {
+ LedNameInfo *ledi = &info->led_names[idx];
if (ledi->name == name) {
*idx_out = idx;
return ledi;
@@ -119,11 +118,11 @@ AddLedName(KeyNamesInfo *info, enum merge_mode merge, bool same_file,
return true;
}
- if (new_idx >= darray_size(info->led_names))
- darray_resize0(info->led_names, new_idx + 1);
+ if (new_idx >= info->num_led_names)
+ info->num_led_names = new_idx + 1;
/* LED with the same index already exists. */
- old = &darray_item(info->led_names, new_idx);
+ old = &info->led_names[new_idx];
if (old->name != XKB_ATOM_NONE) {
if (report) {
const xkb_atom_t use = (replace ? new->name : old->name);
@@ -140,7 +139,7 @@ AddLedName(KeyNamesInfo *info, enum merge_mode merge, bool same_file,
return true;
}
- darray_item(info->led_names, new_idx) = *new;
+ *old = *new;
return true;
}
@@ -150,7 +149,6 @@ ClearKeyNamesInfo(KeyNamesInfo *info)
free(info->name);
darray_free(info->key_names);
darray_free(info->aliases);
- darray_free(info->led_names);
}
static void
@@ -308,15 +306,16 @@ MergeIncludedKeycodes(KeyNamesInfo *into, KeyNamesInfo *from,
}
/* Merge LED names. */
- if (darray_empty(into->led_names)) {
- into->led_names = from->led_names;
- darray_init(from->led_names);
+ if (into->num_led_names == 0) {
+ memcpy(into->led_names, from->led_names,
+ sizeof(*from->led_names) * from->num_led_names);
+ into->num_led_names = from->num_led_names;
+ from->num_led_names = 0;
}
else {
- xkb_led_index_t idx;
- LedNameInfo *ledi;
+ for (xkb_led_index_t idx = 0; idx < from->num_led_names; idx++) {
+ LedNameInfo *ledi = &from->led_names[idx];
- darray_enumerate(idx, ledi, from->led_names) {
if (ledi->name == XKB_ATOM_NONE)
continue;
@@ -468,7 +467,7 @@ HandleLedNameDef(KeyNamesInfo *info, LedNameDef *def,
if (!ExprResolveString(info->ctx, def->name, &name)) {
char buf[20];
- snprintf(buf, sizeof(buf), "%d", def->ndx);
+ snprintf(buf, sizeof(buf), "%u", def->ndx);
info->errorCount++;
return ReportBadType(info->ctx, "indicator", "name", buf, "string");
}
@@ -516,7 +515,7 @@ HandleKeycodesFile(KeyNamesInfo *info, XkbFile *file, enum merge_mode merge)
if (info->errorCount > 10) {
log_err(info->ctx, "Abandoning keycodes file \"%s\"\n",
- file->topName);
+ file->name);
break;
}
}
@@ -527,41 +526,45 @@ HandleKeycodesFile(KeyNamesInfo *info, XkbFile *file, enum merge_mode merge)
static bool
CopyKeyNamesToKeymap(struct xkb_keymap *keymap, KeyNamesInfo *info)
{
- xkb_keycode_t kc;
- xkb_led_index_t idx;
- LedNameInfo *ledi;
- AliasInfo *alias;
- unsigned i;
-
- keymap->keycodes_section_name = strdup_safe(info->name);
- XkbEscapeMapName(keymap->keycodes_section_name);
-
- if (info->min_key_code != XKB_KEYCODE_INVALID) {
- keymap->min_key_code = info->min_key_code;
- keymap->max_key_code = info->max_key_code;
- }
- else {
- /*
- * If the keymap has no keys, let's just use the safest pair
- * we know.
- */
- keymap->min_key_code = 8;
- keymap->max_key_code = 255;
+ struct xkb_key *keys;
+ xkb_keycode_t min_key_code, max_key_code, kc;
+
+ min_key_code = info->min_key_code;
+ max_key_code = info->max_key_code;
+ /* If the keymap has no keys, let's just use the safest pair we know. */
+ if (min_key_code == XKB_KEYCODE_INVALID) {
+ min_key_code = 8;
+ max_key_code = 255;
}
- keymap->keys = calloc(keymap->max_key_code + 1, sizeof(*keymap->keys));
- for (kc = keymap->min_key_code; kc <= keymap->max_key_code; kc++)
- keymap->keys[kc].keycode = kc;
+ keys = calloc(max_key_code + 1, sizeof(*keys));
+ if (!keys)
+ return false;
+
+ for (kc = min_key_code; kc <= max_key_code; kc++)
+ keys[kc].keycode = kc;
- /* Copy key names. */
for (kc = info->min_key_code; kc <= info->max_key_code; kc++)
- keymap->keys[kc].name = darray_item(info->key_names, kc);
+ keys[kc].name = darray_item(info->key_names, kc);
+
+ keymap->min_key_code = min_key_code;
+ keymap->max_key_code = max_key_code;
+ keymap->keys = keys;
+ return true;
+}
+
+static bool
+CopyKeyAliasesToKeymap(struct xkb_keymap *keymap, KeyNamesInfo *info)
+{
+ AliasInfo *alias;
+ unsigned i, num_key_aliases;
+ struct xkb_key_alias *key_aliases;
/*
* Do some sanity checking on the aliases. We can't do it before
* because keys and their aliases may be added out-of-order.
*/
- keymap->num_key_aliases = 0;
+ num_key_aliases = 0;
darray_foreach(alias, info->aliases) {
/* Check that ->real is a key. */
if (!XkbKeyByName(keymap, alias->real, false)) {
@@ -584,30 +587,61 @@ CopyKeyNamesToKeymap(struct xkb_keymap *keymap, KeyNamesInfo *info)
continue;
}
- keymap->num_key_aliases++;
+ num_key_aliases++;
}
/* Copy key aliases. */
- keymap->key_aliases = calloc(keymap->num_key_aliases,
- sizeof(*keymap->key_aliases));
- i = 0;
- darray_foreach(alias, info->aliases) {
- if (alias->real != XKB_ATOM_NONE) {
- keymap->key_aliases[i].alias = alias->alias;
- keymap->key_aliases[i].real = alias->real;
- i++;
+ key_aliases = NULL;
+ if (num_key_aliases > 0) {
+ key_aliases = calloc(num_key_aliases, sizeof(*key_aliases));
+ if (!key_aliases)
+ return false;
+
+ i = 0;
+ darray_foreach(alias, info->aliases) {
+ if (alias->real != XKB_ATOM_NONE) {
+ key_aliases[i].alias = alias->alias;
+ key_aliases[i].real = alias->real;
+ i++;
+ }
}
}
- /* Copy LED names. */
- darray_resize0(keymap->leds, darray_size(info->led_names));
- darray_enumerate(idx, ledi, info->led_names)
- if (ledi->name != XKB_ATOM_NONE)
- darray_item(keymap->leds, idx).name = ledi->name;
+ keymap->num_key_aliases = num_key_aliases;
+ keymap->key_aliases = key_aliases;
+ return true;
+}
+
+static bool
+CopyLedNamesToKeymap(struct xkb_keymap *keymap, KeyNamesInfo *info)
+{
+ keymap->num_leds = info->num_led_names;
+ for (xkb_led_index_t idx = 0; idx < info->num_led_names; idx++) {
+ LedNameInfo *ledi = &info->led_names[idx];
+
+ if (ledi->name == XKB_ATOM_NONE)
+ continue;
+
+ keymap->leds[idx].name = ledi->name;
+ }
return true;
}
+static bool
+CopyKeyNamesInfoToKeymap(struct xkb_keymap *keymap, KeyNamesInfo *info)
+{
+ /* This function trashes keymap on error, but that's OK. */
+ if (!CopyKeyNamesToKeymap(keymap, info) ||
+ !CopyKeyAliasesToKeymap(keymap, info) ||
+ !CopyLedNamesToKeymap(keymap, info))
+ return false;
+
+ keymap->keycodes_section_name = strdup_safe(info->name);
+ XkbEscapeMapName(keymap->keycodes_section_name);
+ return true;
+}
+
/***====================================================================***/
bool
@@ -622,7 +656,7 @@ CompileKeycodes(XkbFile *file, struct xkb_keymap *keymap,
if (info.errorCount != 0)
goto err_info;
- if (!CopyKeyNamesToKeymap(keymap, &info))
+ if (!CopyKeyNamesInfoToKeymap(keymap, &info))
goto err_info;
ClearKeyNamesInfo(&info);
diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/keymap-dump.c b/src/3rdparty/xkbcommon/src/xkbcomp/keymap-dump.c
index 7f70ca3481..2ed591c661 100644
--- a/src/3rdparty/xkbcommon/src/xkbcomp/keymap-dump.c
+++ b/src/3rdparty/xkbcommon/src/xkbcomp/keymap-dump.c
@@ -126,7 +126,7 @@ write_vmods(struct xkb_keymap *keymap, struct buf *buf)
const struct xkb_mod *mod;
xkb_mod_index_t num_vmods = 0;
- darray_foreach(mod, keymap->mods) {
+ xkb_mods_foreach(mod, &keymap->mods) {
if (mod->type != MOD_VIRT)
continue;
@@ -164,7 +164,7 @@ write_keycodes(struct xkb_keymap *keymap, struct buf *buf)
write_buf(buf, "\tminimum = %u;\n", min(keymap->min_key_code, 8));
write_buf(buf, "\tmaximum = %u;\n", max(keymap->max_key_code, 255));
- xkb_foreach_key(key, keymap) {
+ xkb_keys_foreach(key, keymap) {
if (key->name == XKB_ATOM_NONE)
continue;
@@ -172,7 +172,7 @@ write_keycodes(struct xkb_keymap *keymap, struct buf *buf)
KeyNameText(keymap->ctx, key->name), key->keycode);
}
- darray_enumerate(idx, led, keymap->leds)
+ xkb_leds_enumerate(idx, led, keymap)
if (led->name != XKB_ATOM_NONE)
write_buf(buf, "\tindicator %u = \"%s\";\n",
idx + 1, xkb_atom_text(keymap->ctx, led->name));
@@ -205,7 +205,7 @@ write_types(struct xkb_keymap *keymap, struct buf *buf)
xkb_atom_text(keymap->ctx, type->name));
write_buf(buf, "\t\tmodifiers= %s;\n",
- ModMaskText(keymap, type->mods.mods));
+ ModMaskText(keymap->ctx, &keymap->mods, type->mods.mods));
for (unsigned j = 0; j < type->num_entries; j++) {
const char *str;
@@ -218,16 +218,17 @@ write_types(struct xkb_keymap *keymap, struct buf *buf)
if (entry->level == 0 && entry->preserve.mods == 0)
continue;
- str = ModMaskText(keymap, entry->mods.mods);
+ str = ModMaskText(keymap->ctx, &keymap->mods, entry->mods.mods);
write_buf(buf, "\t\tmap[%s]= Level%u;\n",
str, entry->level + 1);
if (entry->preserve.mods)
write_buf(buf, "\t\tpreserve[%s]= %s;\n",
- str, ModMaskText(keymap, entry->preserve.mods));
+ str, ModMaskText(keymap->ctx, &keymap->mods,
+ entry->preserve.mods));
}
- for (xkb_level_index_t n = 0; n < type->num_levels; n++)
+ for (xkb_level_index_t n = 0; n < type->num_level_names; n++)
if (type->level_names[n])
write_buf(buf, "\t\tlevel_name[Level%u]= \"%s\";\n", n + 1,
xkb_atom_text(keymap->ctx, type->level_names[n]));
@@ -261,7 +262,7 @@ write_led_map(struct xkb_keymap *keymap, struct buf *buf,
LedStateMaskText(keymap->ctx, led->which_mods));
}
write_buf(buf, "\t\tmodifiers= %s;\n",
- ModMaskText(keymap, led->mods.mods));
+ ModMaskText(keymap->ctx, &keymap->mods, led->mods.mods));
}
if (led->ctrls) {
@@ -303,13 +304,14 @@ write_action(struct xkb_keymap *keymap, struct buf *buf,
type = ActionTypeText(action->type);
switch (action->type) {
- case ACTION_TYPE_MOD_LOCK:
case ACTION_TYPE_MOD_SET:
case ACTION_TYPE_MOD_LATCH:
+ case ACTION_TYPE_MOD_LOCK:
if (action->mods.flags & ACTION_MODS_LOOKUP_MODMAP)
args = "modMapMods";
else
- args = ModMaskText(keymap, action->mods.mods.mods);
+ args = ModMaskText(keymap->ctx, &keymap->mods,
+ action->mods.mods.mods);
write_buf(buf, "%s%s(modifiers=%s%s%s%s)%s", prefix, type, args,
(action->type != ACTION_TYPE_MOD_LOCK && (action->mods.flags & ACTION_LOCK_CLEAR)) ? ",clearLocks" : "",
(action->type != ACTION_TYPE_MOD_LOCK && (action->mods.flags & ACTION_LATCH_TO_LOCK)) ? ",latchToLock" : "",
@@ -422,11 +424,12 @@ write_compat(struct xkb_keymap *keymap, struct buf *buf)
write_buf(buf, "\tinterpret %s+%s(%s) {\n",
si->sym ? KeysymText(keymap->ctx, si->sym) : "Any",
SIMatchText(si->match),
- ModMaskText(keymap, si->mods));
+ ModMaskText(keymap->ctx, &keymap->mods, si->mods));
if (si->virtual_mod != XKB_MOD_INVALID)
write_buf(buf, "\t\tvirtualModifier= %s;\n",
- ModIndexText(keymap, si->virtual_mod));
+ ModIndexText(keymap->ctx, &keymap->mods,
+ si->virtual_mod));
if (si->level_one_only)
write_buf(buf, "\t\tuseModMapMods=level1;\n");
@@ -438,7 +441,7 @@ write_compat(struct xkb_keymap *keymap, struct buf *buf)
write_buf(buf, "\t};\n");
}
- darray_foreach(led, keymap->leds)
+ xkb_leds_foreach(led, keymap)
if (led->which_groups || led->groups || led->which_mods ||
led->mods.mods || led->ctrls)
write_led_map(keymap, buf, led);
@@ -452,7 +455,7 @@ static bool
write_keysyms(struct xkb_keymap *keymap, struct buf *buf,
const struct xkb_key *key, xkb_layout_index_t group)
{
- for (xkb_level_index_t level = 0; level < XkbKeyGroupWidth(key, group);
+ for (xkb_level_index_t level = 0; level < XkbKeyNumLevels(key, group);
level++) {
const xkb_keysym_t *syms;
int num_syms;
@@ -534,7 +537,7 @@ write_key(struct xkb_keymap *keymap, struct buf *buf,
if (key->vmodmap && (key->explicit & EXPLICIT_VMODMAP))
write_buf(buf, "\n\t\tvirtualMods= %s,",
- ModMaskText(keymap, key->vmodmap));
+ ModMaskText(keymap->ctx, &keymap->mods, key->vmodmap));
switch (key->out_of_range_group_action) {
case RANGE_SATURATE:
@@ -550,7 +553,7 @@ write_key(struct xkb_keymap *keymap, struct buf *buf,
break;
}
- show_actions = !!(key->explicit & EXPLICIT_INTERP);
+ show_actions = (key->explicit & EXPLICIT_INTERP);
if (key->num_groups > 1 || show_actions)
simple = false;
@@ -573,8 +576,7 @@ write_key(struct xkb_keymap *keymap, struct buf *buf,
write_buf(buf, " ]");
if (show_actions) {
write_buf(buf, ",\n\t\tactions[Group%u]= [ ", group + 1);
- for (level = 0;
- level < XkbKeyGroupWidth(key, group); level++) {
+ for (level = 0; level < XkbKeyNumLevels(key, group); level++) {
if (level != 0)
write_buf(buf, ", ");
write_action(keymap, buf,
@@ -595,6 +597,8 @@ write_symbols(struct xkb_keymap *keymap, struct buf *buf)
{
const struct xkb_key *key;
xkb_layout_index_t group;
+ xkb_mod_index_t i;
+ const struct xkb_mod *mod;
if (keymap->symbols_section_name)
write_buf(buf, "xkb_symbols \"%s\" {\n",
@@ -610,22 +614,25 @@ write_symbols(struct xkb_keymap *keymap, struct buf *buf)
if (group > 0)
write_buf(buf, "\n");
- xkb_foreach_key(key, keymap)
+ xkb_keys_foreach(key, keymap)
if (key->num_groups > 0)
write_key(keymap, buf, key);
- xkb_foreach_key(key, keymap) {
- xkb_mod_index_t i;
- const struct xkb_mod *mod;
-
- if (key->modmap == 0)
- continue;
-
- darray_enumerate(i, mod, keymap->mods)
- if (key->modmap & (1u << i))
- write_buf(buf, "\tmodifier_map %s { %s };\n",
- xkb_atom_text(keymap->ctx, mod->name),
+ xkb_mods_enumerate(i, mod, &keymap->mods) {
+ bool had_any = false;
+ xkb_keys_foreach(key, keymap) {
+ if (key->modmap & (1u << i)) {
+ if (!had_any)
+ write_buf(buf, "\tmodifier_map %s { ",
+ xkb_atom_text(keymap->ctx, mod->name));
+ write_buf(buf, "%s%s",
+ had_any ? ", " : "",
KeyNameText(keymap->ctx, key->name));
+ had_any = true;
+ }
+ }
+ if (had_any)
+ write_buf(buf, " };\n");
}
write_buf(buf, "};\n\n");
diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/keymap.c b/src/3rdparty/xkbcommon/src/xkbcomp/keymap.c
deleted file mode 100644
index 8a70577faf..0000000000
--- a/src/3rdparty/xkbcommon/src/xkbcomp/keymap.c
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * Copyright © 2009 Dan Nicholson
- * Copyright © 2012 Intel Corporation
- * Copyright © 2012 Ran Benita <ran234@gmail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Author: Dan Nicholson <dbn.lists@gmail.com>
- * Daniel Stone <daniel@fooishbar.org>
- * Ran Benita <ran234@gmail.com>
- */
-
-#include "xkbcomp-priv.h"
-
-static void
-ComputeEffectiveMask(struct xkb_keymap *keymap, struct xkb_mods *mods)
-{
- const struct xkb_mod *mod;
- xkb_mod_index_t i;
-
- /* The effective mask is only real mods for now. */
- mods->mask = mods->mods & MOD_REAL_MASK_ALL;
-
- darray_enumerate(i, mod, keymap->mods)
- if (mods->mods & (1u << i))
- mods->mask |= mod->mapping;
-}
-
-static void
-UpdateActionMods(struct xkb_keymap *keymap, union xkb_action *act,
- xkb_mod_mask_t modmap)
-{
- switch (act->type) {
- case ACTION_TYPE_MOD_SET:
- case ACTION_TYPE_MOD_LATCH:
- case ACTION_TYPE_MOD_LOCK:
- if (act->mods.flags & ACTION_MODS_LOOKUP_MODMAP)
- act->mods.mods.mods = modmap;
- ComputeEffectiveMask(keymap, &act->mods.mods);
- break;
- default:
- break;
- }
-}
-
-static const struct xkb_sym_interpret default_interpret = {
- .sym = XKB_KEY_NoSymbol,
- .repeat = true,
- .match = MATCH_ANY_OR_NONE,
- .mods = 0,
- .virtual_mod = XKB_MOD_INVALID,
- .action = { .type = ACTION_TYPE_NONE },
-};
-
-/**
- * Find an interpretation which applies to this particular level, either by
- * finding an exact match for the symbol and modifier combination, or a
- * generic XKB_KEY_NoSymbol match.
- */
-static const struct xkb_sym_interpret *
-FindInterpForKey(struct xkb_keymap *keymap, const struct xkb_key *key,
- xkb_layout_index_t group, xkb_level_index_t level)
-{
- const xkb_keysym_t *syms;
- int num_syms;
-
- num_syms = xkb_keymap_key_get_syms_by_level(keymap, key->keycode, group,
- level, &syms);
- if (num_syms == 0)
- return NULL;
-
- /*
- * There may be multiple matchings interprets; we should always return
- * the most specific. Here we rely on compat.c to set up the
- * sym_interprets array from the most specific to the least specific,
- * such that when we find a match we return immediately.
- */
- for (unsigned i = 0; i < keymap->num_sym_interprets; i++) {
- const struct xkb_sym_interpret *interp = &keymap->sym_interprets[i];
-
- xkb_mod_mask_t mods;
- bool found = false;
-
- if ((num_syms > 1 || interp->sym != syms[0]) &&
- interp->sym != XKB_KEY_NoSymbol)
- continue;
-
- if (interp->level_one_only && level != 0)
- mods = 0;
- else
- mods = key->modmap;
-
- switch (interp->match) {
- case MATCH_NONE:
- found = !(interp->mods & mods);
- break;
- case MATCH_ANY_OR_NONE:
- found = (!mods || (interp->mods & mods));
- break;
- case MATCH_ANY:
- found = !!(interp->mods & mods);
- break;
- case MATCH_ALL:
- found = ((interp->mods & mods) == interp->mods);
- break;
- case MATCH_EXACTLY:
- found = (interp->mods == mods);
- break;
- }
-
- if (found)
- return interp;
- }
-
- return &default_interpret;
-}
-
-static bool
-ApplyInterpsToKey(struct xkb_keymap *keymap, struct xkb_key *key)
-{
- xkb_mod_mask_t vmodmap = 0;
- xkb_layout_index_t group;
- xkb_level_index_t level;
-
- /* If we've been told not to bind interps to this key, then don't. */
- if (key->explicit & EXPLICIT_INTERP)
- return true;
-
- for (group = 0; group < key->num_groups; group++) {
- for (level = 0; level < XkbKeyGroupWidth(key, group); level++) {
- const struct xkb_sym_interpret *interp;
-
- interp = FindInterpForKey(keymap, key, group, level);
- if (!interp)
- continue;
-
- /* Infer default key behaviours from the base level. */
- if (group == 0 && level == 0)
- if (!(key->explicit & EXPLICIT_REPEAT) && interp->repeat)
- key->repeats = true;
-
- if ((group == 0 && level == 0) || !interp->level_one_only)
- if (interp->virtual_mod != XKB_MOD_INVALID)
- vmodmap |= (1u << interp->virtual_mod);
-
- if (interp->action.type != ACTION_TYPE_NONE)
- key->groups[group].levels[level].action = interp->action;
- }
- }
-
- if (!(key->explicit & EXPLICIT_VMODMAP))
- key->vmodmap = vmodmap;
-
- return true;
-}
-
-/**
- * This collects a bunch of disparate functions which was done in the server
- * at various points that really should've been done within xkbcomp. Turns out
- * your actions and types are a lot more useful when any of your modifiers
- * other than Shift actually do something ...
- */
-static bool
-UpdateDerivedKeymapFields(struct xkb_keymap *keymap)
-{
- struct xkb_mod *mod;
- struct xkb_led *led;
- unsigned int i, j;
- struct xkb_key *key;
-
- /* Find all the interprets for the key and bind them to actions,
- * which will also update the vmodmap. */
- xkb_foreach_key(key, keymap)
- if (!ApplyInterpsToKey(keymap, key))
- return false;
-
- /* Update keymap->mods, the virtual -> real mod mapping. */
- xkb_foreach_key(key, keymap)
- darray_enumerate(i, mod, keymap->mods)
- if (key->vmodmap & (1u << i))
- mod->mapping |= key->modmap;
-
- /* Now update the level masks for all the types to reflect the vmods. */
- for (i = 0; i < keymap->num_types; i++) {
- ComputeEffectiveMask(keymap, &keymap->types[i].mods);
-
- for (j = 0; j < keymap->types[i].num_entries; j++) {
- ComputeEffectiveMask(keymap, &keymap->types[i].entries[j].mods);
- ComputeEffectiveMask(keymap, &keymap->types[i].entries[j].preserve);
- }
- }
-
- /* Update action modifiers. */
- xkb_foreach_key(key, keymap)
- for (i = 0; i < key->num_groups; i++)
- for (j = 0; j < XkbKeyGroupWidth(key, i); j++)
- UpdateActionMods(keymap, &key->groups[i].levels[j].action,
- key->modmap);
-
- /* Update vmod -> led maps. */
- darray_foreach(led, keymap->leds)
- ComputeEffectiveMask(keymap, &led->mods);
-
- /* Find maximum number of groups out of all keys in the keymap. */
- xkb_foreach_key(key, keymap)
- keymap->num_groups = MAX(keymap->num_groups, key->num_groups);
-
- return true;
-}
-
-typedef bool (*compile_file_fn)(XkbFile *file,
- struct xkb_keymap *keymap,
- enum merge_mode merge);
-
-static const compile_file_fn compile_file_fns[LAST_KEYMAP_FILE_TYPE + 1] = {
- [FILE_TYPE_KEYCODES] = CompileKeycodes,
- [FILE_TYPE_TYPES] = CompileKeyTypes,
- [FILE_TYPE_COMPAT] = CompileCompatMap,
- [FILE_TYPE_SYMBOLS] = CompileSymbols,
-};
-
-bool
-CompileKeymap(XkbFile *file, struct xkb_keymap *keymap, enum merge_mode merge)
-{
- bool ok;
- const char *main_name;
- XkbFile *files[LAST_KEYMAP_FILE_TYPE + 1] = { NULL };
- enum xkb_file_type type;
- struct xkb_context *ctx = keymap->ctx;
-
- main_name = file->name ? file->name : "(unnamed)";
-
- /* Collect section files and check for duplicates. */
- for (file = (XkbFile *) file->defs; file;
- file = (XkbFile *) file->common.next) {
- if (file->file_type < FIRST_KEYMAP_FILE_TYPE ||
- file->file_type > LAST_KEYMAP_FILE_TYPE) {
- log_err(ctx, "Cannot define %s in a keymap file\n",
- xkb_file_type_to_string(file->file_type));
- continue;
- }
-
- if (files[file->file_type]) {
- log_err(ctx,
- "More than one %s section in keymap file; "
- "All sections after the first ignored\n",
- xkb_file_type_to_string(file->file_type));
- continue;
- }
-
- if (!file->topName) {
- free(file->topName);
- file->topName = strdup(main_name);
- }
-
- files[file->file_type] = file;
- }
-
- /*
- * Check that all required section were provided.
- * Report everything before failing.
- */
- ok = true;
- for (type = FIRST_KEYMAP_FILE_TYPE;
- type <= LAST_KEYMAP_FILE_TYPE;
- type++) {
- if (files[type] == NULL) {
- log_err(ctx, "Required section %s missing from keymap\n",
- xkb_file_type_to_string(type));
- ok = false;
- }
- }
- if (!ok)
- return false;
-
- /* Compile sections. */
- for (type = FIRST_KEYMAP_FILE_TYPE;
- type <= LAST_KEYMAP_FILE_TYPE;
- type++) {
- log_dbg(ctx, "Compiling %s \"%s\"\n",
- xkb_file_type_to_string(type), files[type]->topName);
-
- ok = compile_file_fns[type](files[type], keymap, merge);
- if (!ok) {
- log_err(ctx, "Failed to compile %s\n",
- xkb_file_type_to_string(type));
- return false;
- }
- }
-
- return UpdateDerivedKeymapFields(keymap);
-}
diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/parser-priv.h b/src/3rdparty/xkbcommon/src/xkbcomp/parser-priv.h
index 0675e55a8f..76b5047eb6 100644
--- a/src/3rdparty/xkbcommon/src/xkbcomp/parser-priv.h
+++ b/src/3rdparty/xkbcommon/src/xkbcomp/parser-priv.h
@@ -28,8 +28,8 @@
#define XKBCOMP_PARSER_PRIV_H
struct parser_param;
+struct scanner;
-#include "scanner-utils.h"
#include "parser.h"
int
diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/parser.c b/src/3rdparty/xkbcommon/src/xkbcomp/parser.c
deleted file mode 100644
index eaa7384369..0000000000
--- a/src/3rdparty/xkbcommon/src/xkbcomp/parser.c
+++ /dev/null
@@ -1,3610 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.5. */
-
-/* Bison implementation for Yacc-like parsers in C
-
- Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-/* As a special exception, you may create a larger work that contains
- part or all of the Bison parser skeleton and distribute that work
- under terms of your choice, so long as that work isn't itself a
- parser generator using the skeleton or a modified version thereof
- as a parser skeleton. Alternatively, if you modify or redistribute
- the parser skeleton itself, you may (at your option) remove this
- special exception, which will cause the skeleton and the resulting
- Bison output files to be licensed under the GNU General Public
- License without this special exception.
-
- This special exception was added by the Free Software Foundation in
- version 2.2 of Bison. */
-
-/* C LALR(1) parser skeleton written by Richard Stallman, by
- simplifying the original so-called "semantic" parser. */
-
-/* All symbols defined below should begin with yy or YY, to avoid
- infringing on user name space. This should be done even for local
- variables, as they might otherwise be expanded by user macros.
- There are some unavoidable exceptions within include files to
- define necessary library symbols; they are noted "INFRINGES ON
- USER NAME SPACE" below. */
-
-/* Identify Bison output. */
-#define YYBISON 1
-
-/* Bison version. */
-#define YYBISON_VERSION "2.5"
-
-/* Skeleton name. */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers. */
-#define YYPURE 1
-
-/* Push parsers. */
-#define YYPUSH 0
-
-/* Pull parsers. */
-#define YYPULL 1
-
-/* Using locations. */
-#define YYLSP_NEEDED 0
-
-/* Substitute the variable and function names. */
-#define yyparse _xkbcommon_parse
-#define yylex _xkbcommon_lex
-#define yyerror _xkbcommon_error
-#define yylval _xkbcommon_lval
-#define yychar _xkbcommon_char
-#define yydebug _xkbcommon_debug
-#define yynerrs _xkbcommon_nerrs
-
-
-/* Copy the first part of user declarations. */
-
-/* Line 268 of yacc.c */
-#line 33 "parser.y"
-
-#include "xkbcomp-priv.h"
-#include "ast-build.h"
-#include "parser-priv.h"
-
-struct parser_param {
- struct xkb_context *ctx;
- struct scanner *scanner;
- XkbFile *rtrn;
- bool more_maps;
-};
-
-#define parser_err(param, fmt, ...) \
- scanner_err((param)->scanner, fmt, ##__VA_ARGS__)
-
-#define parser_warn(param, fmt, ...) \
- scanner_warn((param)->scanner, fmt, ##__VA_ARGS__)
-
-static void
-_xkbcommon_error(struct parser_param *param, const char *msg)
-{
- parser_err(param, "%s", msg);
-}
-
-static bool
-resolve_keysym(const char *str, xkb_keysym_t *sym_rtrn)
-{
- xkb_keysym_t sym;
-
- if (!str || istreq(str, "any") || istreq(str, "nosymbol")) {
- *sym_rtrn = XKB_KEY_NoSymbol;
- return true;
- }
-
- if (istreq(str, "none") || istreq(str, "voidsymbol")) {
- *sym_rtrn = XKB_KEY_VoidSymbol;
- return true;
- }
-
- sym = xkb_keysym_from_name(str, XKB_KEYSYM_NO_FLAGS);
- if (sym != XKB_KEY_NoSymbol) {
- *sym_rtrn = sym;
- return true;
- }
-
- return false;
-}
-
-#define param_scanner param->scanner
-
-
-/* Line 268 of yacc.c */
-#line 131 "src/xkbcomp/parser.c"
-
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-
-/* Enabling verbose error messages. */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-/* Enabling the token table. */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
-
-
-/* Tokens. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
- /* Put the tokens into the symbol table, so that GDB and other debuggers
- know about them. */
- enum yytokentype {
- END_OF_FILE = 0,
- ERROR_TOK = 255,
- XKB_KEYMAP = 1,
- XKB_KEYCODES = 2,
- XKB_TYPES = 3,
- XKB_SYMBOLS = 4,
- XKB_COMPATMAP = 5,
- XKB_GEOMETRY = 6,
- XKB_SEMANTICS = 7,
- XKB_LAYOUT = 8,
- INCLUDE = 10,
- OVERRIDE = 11,
- AUGMENT = 12,
- REPLACE = 13,
- ALTERNATE = 14,
- VIRTUAL_MODS = 20,
- TYPE = 21,
- INTERPRET = 22,
- ACTION_TOK = 23,
- KEY = 24,
- ALIAS = 25,
- GROUP = 26,
- MODIFIER_MAP = 27,
- INDICATOR = 28,
- SHAPE = 29,
- KEYS = 30,
- ROW = 31,
- SECTION = 32,
- OVERLAY = 33,
- TEXT = 34,
- OUTLINE = 35,
- SOLID = 36,
- LOGO = 37,
- VIRTUAL = 38,
- EQUALS = 40,
- PLUS = 41,
- MINUS = 42,
- DIVIDE = 43,
- TIMES = 44,
- OBRACE = 45,
- CBRACE = 46,
- OPAREN = 47,
- CPAREN = 48,
- OBRACKET = 49,
- CBRACKET = 50,
- DOT = 51,
- COMMA = 52,
- SEMI = 53,
- EXCLAM = 54,
- INVERT = 55,
- STRING = 60,
- INTEGER = 61,
- FLOAT = 62,
- IDENT = 63,
- KEYNAME = 64,
- PARTIAL = 70,
- DEFAULT = 71,
- HIDDEN = 72,
- ALPHANUMERIC_KEYS = 73,
- MODIFIER_KEYS = 74,
- KEYPAD_KEYS = 75,
- FUNCTION_KEYS = 76,
- ALTERNATE_GROUP = 77
- };
-#endif
-/* Tokens. */
-#define END_OF_FILE 0
-#define ERROR_TOK 255
-#define XKB_KEYMAP 1
-#define XKB_KEYCODES 2
-#define XKB_TYPES 3
-#define XKB_SYMBOLS 4
-#define XKB_COMPATMAP 5
-#define XKB_GEOMETRY 6
-#define XKB_SEMANTICS 7
-#define XKB_LAYOUT 8
-#define INCLUDE 10
-#define OVERRIDE 11
-#define AUGMENT 12
-#define REPLACE 13
-#define ALTERNATE 14
-#define VIRTUAL_MODS 20
-#define TYPE 21
-#define INTERPRET 22
-#define ACTION_TOK 23
-#define KEY 24
-#define ALIAS 25
-#define GROUP 26
-#define MODIFIER_MAP 27
-#define INDICATOR 28
-#define SHAPE 29
-#define KEYS 30
-#define ROW 31
-#define SECTION 32
-#define OVERLAY 33
-#define TEXT 34
-#define OUTLINE 35
-#define SOLID 36
-#define LOGO 37
-#define VIRTUAL 38
-#define EQUALS 40
-#define PLUS 41
-#define MINUS 42
-#define DIVIDE 43
-#define TIMES 44
-#define OBRACE 45
-#define CBRACE 46
-#define OPAREN 47
-#define CPAREN 48
-#define OBRACKET 49
-#define CBRACKET 50
-#define DOT 51
-#define COMMA 52
-#define SEMI 53
-#define EXCLAM 54
-#define INVERT 55
-#define STRING 60
-#define INTEGER 61
-#define FLOAT 62
-#define IDENT 63
-#define KEYNAME 64
-#define PARTIAL 70
-#define DEFAULT 71
-#define HIDDEN 72
-#define ALPHANUMERIC_KEYS 73
-#define MODIFIER_KEYS 74
-#define KEYPAD_KEYS 75
-#define FUNCTION_KEYS 76
-#define ALTERNATE_GROUP 77
-
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-{
-
-/* Line 293 of yacc.c */
-#line 161 "parser.y"
-
- int ival;
- int64_t num;
- enum xkb_file_type file_type;
- char *str;
- xkb_atom_t sval;
- enum merge_mode merge;
- enum xkb_map_flags mapFlags;
- xkb_keysym_t keysym;
- ParseCommon *any;
- ExprDef *expr;
- VarDef *var;
- VModDef *vmod;
- InterpDef *interp;
- KeyTypeDef *keyType;
- SymbolsDef *syms;
- ModMapDef *modMask;
- GroupCompatDef *groupCompat;
- LedMapDef *ledMap;
- LedNameDef *ledName;
- KeycodeDef *keyCode;
- KeyAliasDef *keyAlias;
- void *geom;
- XkbFile *file;
-
-
-
-/* Line 293 of yacc.c */
-#line 325 "src/xkbcomp/parser.c"
-} YYSTYPE;
-# define YYSTYPE_IS_TRIVIAL 1
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-#endif
-
-
-/* Copy the second part of user declarations. */
-
-
-/* Line 343 of yacc.c */
-#line 337 "src/xkbcomp/parser.c"
-
-#ifdef short
-# undef short
-#endif
-
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
-#endif
-
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
-#else
-typedef short int yytype_int8;
-#endif
-
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
-typedef unsigned short int yytype_uint16;
-#endif
-
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
-#else
-typedef short int yytype_int16;
-#endif
-
-#ifndef YYSIZE_T
-# ifdef __SIZE_TYPE__
-# define YYSIZE_T __SIZE_TYPE__
-# elif defined size_t
-# define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-# define YYSIZE_T size_t
-# else
-# define YYSIZE_T unsigned int
-# endif
-#endif
-
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
-
-#ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
-# if ENABLE_NLS
-# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-# define YY_(msgid) dgettext ("bison-runtime", msgid)
-# endif
-# endif
-# ifndef YY_
-# define YY_(msgid) msgid
-# endif
-#endif
-
-/* Suppress unused-variable warnings by "using" E. */
-#if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
-#else
-# define YYUSE(e) /* empty */
-#endif
-
-/* Identity function, used to suppress warnings about constant conditions. */
-#ifndef lint
-# define YYID(n) (n)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int yyi)
-#else
-static int
-YYID (yyi)
- int yyi;
-#endif
-{
- return yyi;
-}
-#endif
-
-#if ! defined yyoverflow || YYERROR_VERBOSE
-
-/* The parser invokes alloca or malloc; define the necessary symbols. */
-
-# ifdef YYSTACK_USE_ALLOCA
-# if YYSTACK_USE_ALLOCA
-# ifdef __GNUC__
-# define YYSTACK_ALLOC __builtin_alloca
-# elif defined __BUILTIN_VA_ARG_INCR
-# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
-# elif defined _AIX
-# define YYSTACK_ALLOC __alloca
-# elif defined _MSC_VER
-# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
-# define alloca _alloca
-# else
-# define YYSTACK_ALLOC alloca
-# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# ifndef EXIT_SUCCESS
-# define EXIT_SUCCESS 0
-# endif
-# endif
-# endif
-# endif
-# endif
-
-# ifdef YYSTACK_ALLOC
- /* Pacify GCC's `empty if-body' warning. */
-# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
-# ifndef YYSTACK_ALLOC_MAXIMUM
- /* The OS might guarantee only one guard page at the bottom of the stack,
- and a page size can be as small as 4096 bytes. So we cannot safely
- invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
- to allow for a few compiler-allocated temporary stack slots. */
-# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
-# endif
-# else
-# define YYSTACK_ALLOC YYMALLOC
-# define YYSTACK_FREE YYFREE
-# ifndef YYSTACK_ALLOC_MAXIMUM
-# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
-# endif
-# if (defined __cplusplus && ! defined EXIT_SUCCESS \
- && ! ((defined YYMALLOC || defined malloc) \
- && (defined YYFREE || defined free)))
-# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# ifndef EXIT_SUCCESS
-# define EXIT_SUCCESS 0
-# endif
-# endif
-# ifndef YYMALLOC
-# define YYMALLOC malloc
-# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
-# endif
-# endif
-# ifndef YYFREE
-# define YYFREE free
-# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-void free (void *); /* INFRINGES ON USER NAME SPACE */
-# endif
-# endif
-# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
-
-#if (! defined yyoverflow \
- && (! defined __cplusplus \
- || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member. */
-union yyalloc
-{
- yytype_int16 yyss_alloc;
- YYSTYPE yyvs_alloc;
-};
-
-/* The size of the maximum gap between one aligned stack and the next. */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
- N elements. */
-# define YYSTACK_BYTES(N) \
- ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
- + YYSTACK_GAP_MAXIMUM)
-
-# define YYCOPY_NEEDED 1
-
-/* Relocate STACK from its old location to the new one. The
- local variables YYSIZE and YYSTACKSIZE give the old and new number of
- elements in the stack, and YYPTR gives the new location of the
- stack. Advance YYPTR to a properly aligned location for the next
- stack. */
-# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
- do \
- { \
- YYSIZE_T yynewbytes; \
- YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
- Stack = &yyptr->Stack_alloc; \
- yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
- yyptr += yynewbytes / sizeof (*yyptr); \
- } \
- while (YYID (0))
-
-#endif
-
-#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
-/* Copy COUNT objects from FROM to TO. The source and destination do
- not overlap. */
-# ifndef YYCOPY
-# if defined __GNUC__ && 1 < __GNUC__
-# define YYCOPY(To, From, Count) \
- __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-# else
-# define YYCOPY(To, From, Count) \
- do \
- { \
- YYSIZE_T yyi; \
- for (yyi = 0; yyi < (Count); yyi++) \
- (To)[yyi] = (From)[yyi]; \
- } \
- while (YYID (0))
-# endif
-# endif
-#endif /* !YYCOPY_NEEDED */
-
-/* YYFINAL -- State number of the termination state. */
-#define YYFINAL 16
-/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 735
-
-/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 65
-/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 72
-/* YYNRULES -- Number of rules. */
-#define YYNRULES 184
-/* YYNRULES -- Number of states. */
-#define YYNSTATES 334
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
-#define YYUNDEFTOK 2
-#define YYMAXUTOK 257
-
-#define YYTRANSLATE(YYX) \
- ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
-static const yytype_uint8 yytranslate[] =
-{
- 0, 4, 5, 6, 7, 8, 9, 10, 11, 2,
- 12, 13, 14, 15, 16, 2, 2, 2, 2, 2,
- 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
- 27, 28, 29, 30, 31, 32, 33, 34, 35, 2,
- 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
- 46, 47, 48, 49, 50, 51, 2, 2, 2, 2,
- 52, 53, 54, 55, 56, 2, 2, 2, 2, 2,
- 57, 58, 59, 60, 61, 62, 63, 64, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 3, 1, 2
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
- YYRHS. */
-static const yytype_uint16 yyprhs[] =
-{
- 0, 0, 3, 5, 7, 9, 17, 19, 21, 23,
- 26, 28, 36, 38, 40, 42, 44, 46, 48, 49,
- 52, 54, 56, 58, 60, 62, 64, 66, 68, 70,
- 73, 74, 77, 80, 83, 86, 89, 92, 95, 98,
- 101, 104, 107, 110, 113, 116, 119, 124, 127, 131,
- 136, 142, 146, 150, 152, 154, 158, 165, 169, 171,
- 174, 176, 183, 190, 194, 196, 197, 201, 205, 207,
- 210, 212, 216, 220, 226, 233, 240, 246, 253, 260,
- 267, 274, 277, 279, 285, 287, 289, 291, 293, 296,
- 298, 304, 306, 310, 312, 314, 318, 325, 329, 331,
- 335, 339, 341, 345, 351, 355, 359, 361, 367, 374,
- 376, 378, 380, 382, 384, 386, 388, 390, 392, 394,
- 396, 398, 400, 402, 404, 406, 408, 410, 411, 413,
- 415, 417, 419, 421, 423, 424, 428, 430, 434, 438,
- 442, 446, 450, 452, 455, 458, 461, 464, 466, 471,
- 473, 477, 481, 483, 488, 490, 494, 499, 506, 508,
- 510, 512, 514, 516, 517, 521, 525, 527, 529, 533,
- 535, 537, 539, 542, 544, 546, 548, 550, 552, 554,
- 556, 558, 560, 562, 563
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS. */
-static const yytype_int16 yyrhs[] =
-{
- 66, 0, -1, 67, -1, 70, -1, 0, -1, 72,
- 68, 135, 41, 69, 42, 49, -1, 4, -1, 10,
- -1, 11, -1, 69, 70, -1, 70, -1, 72, 71,
- 135, 41, 75, 42, 49, -1, 5, -1, 6, -1,
- 8, -1, 7, -1, 9, -1, 73, -1, -1, 73,
- 74, -1, 74, -1, 57, -1, 58, -1, 59, -1,
- 60, -1, 61, -1, 62, -1, 63, -1, 64, -1,
- 75, 76, -1, -1, 114, 77, -1, 114, 80, -1,
- 114, 83, -1, 114, 78, -1, 114, 79, -1, 114,
- 86, -1, 114, 87, -1, 114, 92, -1, 114, 91,
- -1, 114, 93, -1, 114, 94, -1, 114, 95, -1,
- 114, 96, -1, 114, 110, -1, 115, 52, -1, 122,
- 36, 118, 49, -1, 133, 49, -1, 50, 133, 49,
- -1, 56, 36, 132, 49, -1, 22, 56, 36, 56,
- 49, -1, 17, 81, 49, -1, 81, 48, 82, -1,
- 82, -1, 133, -1, 133, 36, 118, -1, 19, 84,
- 41, 85, 42, 49, -1, 127, 37, 118, -1, 127,
- -1, 85, 77, -1, 77, -1, 18, 134, 41, 85,
- 42, 49, -1, 21, 56, 41, 88, 42, 49, -1,
- 88, 48, 89, -1, 89, -1, -1, 122, 36, 118,
- -1, 122, 36, 90, -1, 133, -1, 50, 133, -1,
- 90, -1, 45, 124, 46, -1, 45, 120, 46, -1,
- 23, 131, 36, 118, 49, -1, 24, 133, 41, 117,
- 42, 49, -1, 25, 134, 41, 85, 42, 49, -1,
- 25, 131, 36, 118, 49, -1, 35, 25, 131, 36,
- 118, 49, -1, 26, 134, 41, 106, 42, 49, -1,
- 26, 134, 41, 108, 42, 49, -1, 29, 134, 41,
- 97, 42, 49, -1, 97, 98, -1, 98, -1, 28,
- 41, 99, 42, 49, -1, 77, -1, 110, -1, 93,
- -1, 103, -1, 99, 100, -1, 100, -1, 27, 41,
- 101, 42, 49, -1, 77, -1, 101, 48, 102, -1,
- 102, -1, 56, -1, 41, 117, 42, -1, 30, 134,
- 41, 104, 42, 49, -1, 104, 48, 105, -1, 105,
- -1, 56, 36, 56, -1, 106, 48, 107, -1, 107,
- -1, 41, 108, 42, -1, 133, 36, 41, 108, 42,
- -1, 133, 36, 118, -1, 108, 48, 109, -1, 109,
- -1, 45, 128, 48, 128, 46, -1, 111, 134, 41,
- 85, 42, 49, -1, 31, -1, 32, -1, 33, -1,
- 34, -1, 133, -1, 113, -1, 20, -1, 19, -1,
- 18, -1, 21, -1, 23, -1, 24, -1, 25, -1,
- 26, -1, 28, -1, 29, -1, 31, -1, 115, -1,
- -1, 12, -1, 14, -1, 13, -1, 15, -1, 16,
- -1, 117, -1, -1, 117, 48, 118, -1, 118, -1,
- 118, 39, 118, -1, 118, 37, 118, -1, 118, 38,
- 118, -1, 118, 40, 118, -1, 122, 36, 118, -1,
- 119, -1, 38, 119, -1, 37, 119, -1, 50, 119,
- -1, 51, 119, -1, 122, -1, 112, 43, 116, 44,
- -1, 123, -1, 43, 118, 44, -1, 120, 48, 121,
- -1, 121, -1, 112, 43, 116, 44, -1, 112, -1,
- 112, 47, 112, -1, 112, 45, 118, 46, -1, 112,
- 47, 112, 45, 118, 46, -1, 134, -1, 131, -1,
- 130, -1, 56, -1, 125, -1, -1, 125, 48, 127,
- -1, 125, 48, 126, -1, 127, -1, 126, -1, 41,
- 125, 42, -1, 55, -1, 29, -1, 131, -1, 38,
- 129, -1, 129, -1, 54, -1, 53, -1, 54, -1,
- 53, -1, 53, -1, 55, -1, 58, -1, 52, -1,
- 136, -1, -1, 52, -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
-static const yytype_uint16 yyrline[] =
-{
- 0, 232, 232, 234, 236, 240, 246, 247, 248, 251,
- 259, 263, 278, 279, 280, 281, 282, 285, 286, 289,
- 290, 293, 294, 295, 296, 297, 298, 299, 300, 303,
- 305, 308, 313, 318, 323, 328, 333, 338, 343, 348,
- 353, 358, 363, 364, 365, 366, 373, 375, 377, 381,
- 385, 389, 393, 396, 400, 402, 406, 412, 414, 418,
- 421, 425, 431, 437, 440, 442, 445, 446, 447, 448,
- 449, 452, 454, 458, 462, 466, 470, 472, 476, 478,
- 482, 486, 487, 490, 492, 494, 496, 498, 502, 503,
- 506, 507, 511, 512, 515, 517, 521, 525, 526, 529,
- 532, 534, 538, 540, 542, 546, 548, 552, 556, 560,
- 561, 562, 563, 566, 567, 570, 572, 574, 576, 578,
- 580, 582, 584, 586, 588, 590, 594, 595, 598, 599,
- 600, 601, 602, 612, 613, 616, 619, 623, 625, 627,
- 629, 631, 633, 637, 639, 641, 643, 645, 647, 649,
- 651, 655, 658, 662, 666, 668, 670, 672, 676, 678,
- 680, 682, 686, 687, 690, 692, 694, 696, 700, 704,
- 710, 711, 731, 732, 735, 736, 739, 742, 745, 748,
- 749, 752, 755, 756, 759
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
- First, the terminals, then, starting at YYNTOKENS, nonterminals. */
-static const char *const yytname[] =
-{
- "END_OF_FILE", "error", "$undefined", "ERROR_TOK", "XKB_KEYMAP",
- "XKB_KEYCODES", "XKB_TYPES", "XKB_SYMBOLS", "XKB_COMPATMAP",
- "XKB_GEOMETRY", "XKB_SEMANTICS", "XKB_LAYOUT", "INCLUDE", "OVERRIDE",
- "AUGMENT", "REPLACE", "ALTERNATE", "VIRTUAL_MODS", "TYPE", "INTERPRET",
- "ACTION_TOK", "KEY", "ALIAS", "GROUP", "MODIFIER_MAP", "INDICATOR",
- "SHAPE", "KEYS", "ROW", "SECTION", "OVERLAY", "TEXT", "OUTLINE", "SOLID",
- "LOGO", "VIRTUAL", "EQUALS", "PLUS", "MINUS", "DIVIDE", "TIMES",
- "OBRACE", "CBRACE", "OPAREN", "CPAREN", "OBRACKET", "CBRACKET", "DOT",
- "COMMA", "SEMI", "EXCLAM", "INVERT", "STRING", "INTEGER", "FLOAT",
- "IDENT", "KEYNAME", "PARTIAL", "DEFAULT", "HIDDEN", "ALPHANUMERIC_KEYS",
- "MODIFIER_KEYS", "KEYPAD_KEYS", "FUNCTION_KEYS", "ALTERNATE_GROUP",
- "$accept", "XkbFile", "XkbCompositeMap", "XkbCompositeType",
- "XkbMapConfigList", "XkbMapConfig", "FileType", "OptFlags", "Flags",
- "Flag", "DeclList", "Decl", "VarDecl", "KeyNameDecl", "KeyAliasDecl",
- "VModDecl", "VModDefList", "VModDef", "InterpretDecl", "InterpretMatch",
- "VarDeclList", "KeyTypeDecl", "SymbolsDecl", "SymbolsBody",
- "SymbolsVarDecl", "ArrayInit", "GroupCompatDecl", "ModMapDecl",
- "LedMapDecl", "LedNameDecl", "ShapeDecl", "SectionDecl", "SectionBody",
- "SectionBodyItem", "RowBody", "RowBodyItem", "Keys", "Key",
- "OverlayDecl", "OverlayKeyList", "OverlayKey", "OutlineList",
- "OutlineInList", "CoordList", "Coord", "DoodadDecl", "DoodadType",
- "FieldSpec", "Element", "OptMergeMode", "MergeMode", "OptExprList",
- "ExprList", "Expr", "Term", "ActionList", "Action", "Lhs", "Terminal",
- "OptKeySymList", "KeySymList", "KeySyms", "KeySym", "SignedNumber",
- "Number", "Float", "Integer", "KeyCode", "Ident", "String", "OptMapName",
- "MapName", 0
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
- token YYLEX-NUM. */
-static const yytype_uint16 yytoknum[] =
-{
- 0, 256, 257, 255, 1, 2, 3, 4, 5, 6,
- 7, 8, 10, 11, 12, 13, 14, 20, 21, 22,
- 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
- 33, 34, 35, 36, 37, 38, 40, 41, 42, 43,
- 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 60, 61, 62, 63, 64, 70, 71, 72,
- 73, 74, 75, 76, 77
-};
-# endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
-static const yytype_uint8 yyr1[] =
-{
- 0, 65, 66, 66, 66, 67, 68, 68, 68, 69,
- 69, 70, 71, 71, 71, 71, 71, 72, 72, 73,
- 73, 74, 74, 74, 74, 74, 74, 74, 74, 75,
- 75, 76, 76, 76, 76, 76, 76, 76, 76, 76,
- 76, 76, 76, 76, 76, 76, 77, 77, 77, 78,
- 79, 80, 81, 81, 82, 82, 83, 84, 84, 85,
- 85, 86, 87, 88, 88, 88, 89, 89, 89, 89,
- 89, 90, 90, 91, 92, 93, 94, 94, 95, 95,
- 96, 97, 97, 98, 98, 98, 98, 98, 99, 99,
- 100, 100, 101, 101, 102, 102, 103, 104, 104, 105,
- 106, 106, 107, 107, 107, 108, 108, 109, 110, 111,
- 111, 111, 111, 112, 112, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 114, 114, 115, 115,
- 115, 115, 115, 116, 116, 117, 117, 118, 118, 118,
- 118, 118, 118, 119, 119, 119, 119, 119, 119, 119,
- 119, 120, 120, 121, 122, 122, 122, 122, 123, 123,
- 123, 123, 124, 124, 125, 125, 125, 125, 126, 127,
- 127, 127, 128, 128, 129, 129, 130, 131, 132, 133,
- 133, 134, 135, 135, 136
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
-static const yytype_uint8 yyr2[] =
-{
- 0, 2, 1, 1, 1, 7, 1, 1, 1, 2,
- 1, 7, 1, 1, 1, 1, 1, 1, 0, 2,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
- 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 4, 2, 3, 4,
- 5, 3, 3, 1, 1, 3, 6, 3, 1, 2,
- 1, 6, 6, 3, 1, 0, 3, 3, 1, 2,
- 1, 3, 3, 5, 6, 6, 5, 6, 6, 6,
- 6, 2, 1, 5, 1, 1, 1, 1, 2, 1,
- 5, 1, 3, 1, 1, 3, 6, 3, 1, 3,
- 3, 1, 3, 5, 3, 3, 1, 5, 6, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 0, 1, 1,
- 1, 1, 1, 1, 0, 3, 1, 3, 3, 3,
- 3, 3, 1, 2, 2, 2, 2, 1, 4, 1,
- 3, 3, 1, 4, 1, 3, 4, 6, 1, 1,
- 1, 1, 1, 0, 3, 3, 1, 1, 3, 1,
- 1, 1, 2, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 0, 1
-};
-
-/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
- Performed when YYTABLE doesn't specify something else to do. Zero
- means the default is an error. */
-static const yytype_uint8 yydefact[] =
-{
- 18, 4, 21, 22, 23, 24, 25, 26, 27, 28,
- 0, 2, 3, 0, 17, 20, 1, 6, 12, 13,
- 15, 14, 16, 7, 8, 183, 183, 19, 184, 0,
- 182, 0, 18, 30, 18, 10, 0, 127, 0, 9,
- 128, 130, 129, 131, 132, 0, 29, 0, 126, 5,
- 11, 0, 117, 116, 115, 118, 0, 119, 120, 121,
- 122, 123, 124, 125, 110, 111, 112, 0, 0, 179,
- 0, 180, 31, 34, 35, 32, 33, 36, 37, 39,
- 38, 40, 41, 42, 43, 44, 0, 154, 114, 0,
- 113, 45, 0, 53, 54, 181, 0, 170, 177, 169,
- 0, 58, 171, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 47, 0,
- 51, 0, 0, 0, 0, 65, 0, 0, 0, 0,
- 0, 0, 0, 0, 48, 178, 0, 0, 117, 116,
- 118, 119, 120, 121, 122, 124, 125, 0, 0, 0,
- 0, 0, 176, 161, 154, 0, 142, 147, 149, 160,
- 159, 113, 158, 155, 0, 52, 55, 60, 0, 0,
- 57, 163, 0, 0, 64, 70, 0, 113, 0, 0,
- 0, 136, 0, 0, 0, 0, 0, 101, 0, 106,
- 0, 121, 123, 0, 84, 86, 0, 82, 87, 85,
- 0, 49, 0, 144, 147, 143, 0, 145, 146, 134,
- 0, 0, 0, 0, 156, 0, 0, 46, 0, 59,
- 0, 170, 0, 169, 0, 0, 152, 0, 162, 167,
- 166, 69, 0, 0, 0, 50, 73, 0, 0, 76,
- 0, 0, 0, 175, 174, 0, 173, 0, 0, 0,
- 0, 0, 0, 0, 0, 81, 0, 0, 150, 0,
- 133, 138, 139, 137, 140, 141, 0, 61, 56, 0,
- 134, 72, 0, 71, 0, 62, 63, 67, 66, 74,
- 135, 75, 102, 172, 0, 78, 100, 79, 105, 0,
- 104, 0, 91, 0, 89, 0, 80, 77, 108, 148,
- 157, 168, 0, 151, 165, 164, 0, 0, 0, 0,
- 88, 0, 0, 98, 153, 107, 103, 0, 94, 0,
- 93, 83, 0, 0, 0, 0, 0, 0, 99, 96,
- 97, 95, 90, 92
-};
-
-/* YYDEFGOTO[NTERM-NUM]. */
-static const yytype_int16 yydefgoto[] =
-{
- -1, 10, 11, 25, 34, 12, 26, 36, 14, 15,
- 37, 46, 167, 73, 74, 75, 92, 93, 76, 100,
- 168, 77, 78, 173, 174, 175, 79, 80, 195, 82,
- 83, 84, 196, 197, 293, 294, 319, 320, 198, 312,
- 313, 186, 187, 188, 189, 199, 86, 154, 88, 47,
- 48, 259, 260, 181, 156, 225, 226, 157, 158, 227,
- 228, 229, 230, 245, 246, 159, 160, 136, 161, 162,
- 29, 30
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
- STATE-NUM. */
-#define YYPACT_NINF -182
-static const yytype_int16 yypact[] =
-{
- 176, -182, -182, -182, -182, -182, -182, -182, -182, -182,
- 6, -182, -182, 271, 227, -182, -182, -182, -182, -182,
- -182, -182, -182, -182, -182, -38, -38, -182, -182, -24,
- -182, 33, 227, -182, 210, -182, 353, 44, 5, -182,
- -182, -182, -182, -182, -182, 32, -182, 13, 41, -182,
- -182, -48, 55, 11, -182, 79, 87, 58, -48, -2,
- 55, -182, 55, 72, -182, -182, -182, 107, -48, -182,
- 110, -182, -182, -182, -182, -182, -182, -182, -182, -182,
- -182, -182, -182, -182, -182, -182, 55, -18, -182, 127,
- 121, -182, 66, -182, 138, -182, 136, -182, -182, -182,
- 144, 147, -182, 152, 180, 182, 178, 184, 187, 188,
- 190, 58, 198, 201, 214, 367, 677, 367, -182, -48,
- -182, 367, 663, 663, 367, 494, 200, 367, 367, 367,
- 663, 68, 449, 223, -182, -182, 212, 663, -182, -182,
- -182, -182, -182, -182, -182, -182, -182, 367, 367, 367,
- 367, 367, -182, -182, 57, 157, -182, 224, -182, -182,
- -182, -182, -182, 218, 91, -182, 333, -182, 509, 537,
- 333, 552, -48, 1, -182, -182, 228, 40, 216, 143,
- 70, 333, 150, 593, 247, -30, 97, -182, 105, -182,
- 261, 55, 259, 55, -182, -182, 408, -182, -182, -182,
- 367, -182, 608, -182, -182, -182, 287, -182, -182, 367,
- 367, 367, 367, 367, -182, 367, 367, -182, 252, -182,
- 253, 264, 24, 269, 272, 163, -182, 273, 270, -182,
- -182, -182, 280, 494, 285, -182, -182, 283, 367, -182,
- 284, 112, 8, -182, -182, 294, -182, 299, -36, 304,
- 247, 326, 649, 279, 307, -182, 204, 316, -182, 322,
- 320, 111, 111, -182, -182, 333, 211, -182, -182, 116,
- 367, -182, 677, -182, 24, -182, -182, -182, 333, -182,
- 333, -182, -182, -182, -30, -182, -182, -182, -182, 247,
- 333, 334, -182, 466, -182, 318, -182, -182, -182, -182,
- -182, -182, 339, -182, -182, -182, 343, 120, 14, 345,
- -182, 361, 124, -182, -182, -182, -182, 367, -182, 131,
- -182, -182, 344, 350, 318, 166, 352, 14, -182, -182,
- -182, -182, -182, -182
-};
-
-/* YYPGOTO[NTERM-NUM]. */
-static const yytype_int16 yypgoto[] =
-{
- -182, -182, -182, -182, -182, 181, -182, 402, -182, 389,
- -182, -182, -35, -182, -182, -182, -182, 288, -182, -182,
- -50, -182, -182, -182, 173, 174, -182, -182, 362, -182,
- -182, -182, -182, 215, -182, 119, -182, 86, -182, -182,
- 90, -182, 167, -181, 185, 369, -182, -27, -182, -182,
- -182, 154, -126, 83, 76, -182, 158, -31, -182, -182,
- 221, 170, -52, 161, 205, -182, -44, -182, -47, -34,
- 420, -182
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
- positive, shift that token. If negative, reduce the rule which
- number is the opposite. If YYTABLE_NINF, syntax error. */
-#define YYTABLE_NINF -180
-static const yytype_int16 yytable[] =
-{
- 90, 101, 180, 241, 94, 184, 16, 69, 242, 102,
- 71, 106, 72, 105, 28, 107, 89, 32, 96, 69,
- 87, 112, 71, 243, 244, 108, 109, 115, 110, 116,
- 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
- 97, 61, 62, 232, 63, 64, 65, 66, 67, 233,
- 95, 98, 114, 97, 49, 317, 40, 41, 42, 43,
- 44, 243, 244, 68, 98, 222, 99, 133, 69, 70,
- 318, 71, 94, 169, 33, 90, 90, 98, 177, 99,
- 183, 50, -68, 90, 190, 90, 45, 202, -68, 163,
- 90, 89, 89, 91, 176, 87, 87, 194, 87, 89,
- 209, 89, 115, 87, 116, 87, 89, 95, 307, 184,
- 87, 98, 237, 185, 119, 120, 204, 204, 238, 204,
- 204, 90, 90, 69, -109, 231, 71, 102, 210, 211,
- 212, 213, 111, 219, 219, 103, 90, 89, 89, 247,
- 217, 87, 87, 104, 224, 248, 113, 249, 219, 90,
- 212, 213, 89, 250, 282, 90, 87, 108, 301, 253,
- 250, 194, 316, 117, 274, 89, 323, 219, 250, 87,
- 118, 89, 324, 326, 121, 87, 1, 122, 102, 327,
- 210, 211, 212, 213, 124, 123, 177, 210, 211, 212,
- 213, 325, 236, 125, 210, 211, 212, 213, 155, 239,
- 164, 190, 176, 214, 166, 90, 87, 170, 331, 271,
- 179, 272, 182, 35, 238, 39, 126, 292, 127, 128,
- 129, 89, 305, 203, 205, 87, 207, 208, 130, 131,
- 102, 132, 206, 2, 3, 4, 5, 6, 7, 8,
- 9, 210, 211, 212, 213, 224, 90, 134, 210, 211,
- 212, 213, 38, 297, 135, 137, 178, 300, 292, 200,
- 215, 201, 89, 216, 234, 235, 87, 2, 3, 4,
- 5, 6, 7, 8, 9, 17, 18, 19, 20, 21,
- 22, 23, 24, 256, 2, 3, 4, 5, 6, 7,
- 8, 9, 185, 261, 262, 263, 264, 251, 265, 266,
- 252, 267, 268, 138, 139, 54, 140, -124, 141, 142,
- 143, 144, -179, 61, 145, 270, 146, 278, 274, 273,
- 295, 280, 147, 148, 210, 211, 212, 213, 149, 275,
- 171, 258, 279, 281, 290, 150, 151, 95, 98, 152,
- 69, 153, 284, 71, 138, 139, 54, 140, 285, 141,
- 142, 143, 144, 287, 61, 145, 296, 146, 18, 19,
- 20, 21, 22, 147, 148, 298, 299, 289, 238, 149,
- 210, 211, 212, 213, 311, 308, 150, 151, 95, 98,
- 152, 69, 153, 314, 71, 138, 139, 54, 140, 315,
- 141, 142, 143, 144, 321, 61, 145, 322, 146, 329,
- 328, 332, 13, 27, 147, 148, 276, 165, 277, 81,
- 149, 255, 310, 333, 330, 286, 85, 150, 151, 95,
- 98, 152, 69, 153, 302, 71, 138, 139, 54, 140,
- 303, 141, 142, 191, 144, 288, 192, 145, 193, 63,
- 64, 65, 66, 269, 304, 306, 31, 283, 0, 0,
- 254, 0, 0, 0, 0, 0, 0, 0, 68, 0,
- 0, 0, 0, 69, 0, 0, 71, 138, 139, 54,
- 140, 0, 141, 142, 191, 144, 0, 192, 145, 193,
- 63, 64, 65, 66, 138, 139, 54, 140, 0, 141,
- 142, 143, 144, 291, 61, 145, 0, 146, 0, 68,
- 0, 0, 0, 0, 69, 0, 0, 71, 309, 0,
- 0, 0, 138, 139, 54, 140, 68, 141, 142, 143,
- 144, 69, 61, 145, 71, 146, 0, 138, 139, 54,
- 140, 0, 141, 142, 143, 144, 0, 61, 145, 171,
- 146, 0, 0, 0, 172, 0, 0, 0, 0, 69,
- 0, 218, 71, 0, 0, 138, 139, 54, 140, 68,
- 141, 142, 143, 144, 69, 61, 145, 71, 146, 0,
- 138, 139, 54, 140, 0, 141, 142, 143, 144, 220,
- 61, 221, 0, 146, 0, 0, 0, 68, 0, 0,
- 0, 0, 69, 222, 0, 71, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 98, 0, 223, 0, 0,
- 71, 138, 139, 54, 140, 0, 141, 142, 143, 144,
- 0, 61, 145, 0, 146, 0, 138, 139, 54, 140,
- 0, 141, 142, 143, 144, 240, 61, 145, 0, 146,
- 0, 0, 0, 68, 0, 0, 0, 0, 69, 0,
- 257, 71, 0, 0, 0, 0, 0, 0, 68, 0,
- 0, 0, 0, 69, 0, 0, 71, 138, 139, 54,
- 140, 0, 141, 142, 143, 144, 291, 61, 145, 0,
- 146, 138, 139, 54, 140, 0, 141, 142, 143, 144,
- 0, 61, 145, 0, 146, 138, 139, 54, 140, 68,
- 141, 142, 143, 144, 69, 61, 145, 71, 146, 0,
- 0, 0, 0, 68, 0, 0, 0, 0, 69, 0,
- 0, 71, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 69, 0, 0, 71
-};
-
-#define yypact_value_is_default(yystate) \
- ((yystate) == (-182))
-
-#define yytable_value_is_error(yytable_value) \
- YYID (0)
-
-static const yytype_int16 yycheck[] =
-{
- 47, 53, 128, 184, 51, 41, 0, 55, 38, 53,
- 58, 58, 47, 57, 52, 59, 47, 41, 52, 55,
- 47, 68, 58, 53, 54, 59, 60, 45, 62, 47,
- 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
- 29, 28, 29, 42, 31, 32, 33, 34, 35, 48,
- 52, 53, 86, 29, 49, 41, 12, 13, 14, 15,
- 16, 53, 54, 50, 53, 41, 55, 111, 55, 56,
- 56, 58, 119, 123, 41, 122, 123, 53, 125, 55,
- 130, 49, 42, 130, 131, 132, 42, 137, 48, 116,
- 137, 122, 123, 52, 125, 122, 123, 132, 125, 130,
- 43, 132, 45, 130, 47, 132, 137, 52, 289, 41,
- 137, 53, 42, 45, 48, 49, 147, 148, 48, 150,
- 151, 168, 169, 55, 52, 172, 58, 171, 37, 38,
- 39, 40, 25, 168, 169, 56, 183, 168, 169, 42,
- 49, 168, 169, 56, 171, 48, 36, 42, 183, 196,
- 39, 40, 183, 48, 42, 202, 183, 191, 42, 193,
- 48, 196, 42, 36, 48, 196, 42, 202, 48, 196,
- 49, 202, 48, 42, 36, 202, 0, 41, 222, 48,
- 37, 38, 39, 40, 37, 41, 233, 37, 38, 39,
- 40, 317, 49, 41, 37, 38, 39, 40, 115, 49,
- 117, 248, 233, 46, 121, 252, 233, 124, 42, 46,
- 127, 48, 129, 32, 48, 34, 36, 252, 36, 41,
- 36, 252, 274, 147, 148, 252, 150, 151, 41, 41,
- 274, 41, 149, 57, 58, 59, 60, 61, 62, 63,
- 64, 37, 38, 39, 40, 272, 293, 49, 37, 38,
- 39, 40, 42, 49, 53, 41, 56, 46, 293, 36,
- 36, 49, 293, 45, 36, 49, 293, 57, 58, 59,
- 60, 61, 62, 63, 64, 4, 5, 6, 7, 8,
- 9, 10, 11, 200, 57, 58, 59, 60, 61, 62,
- 63, 64, 45, 210, 211, 212, 213, 36, 215, 216,
- 41, 49, 49, 18, 19, 20, 21, 43, 23, 24,
- 25, 26, 43, 28, 29, 43, 31, 234, 48, 46,
- 41, 238, 37, 38, 37, 38, 39, 40, 43, 49,
- 45, 44, 49, 49, 251, 50, 51, 52, 53, 54,
- 55, 56, 48, 58, 18, 19, 20, 21, 49, 23,
- 24, 25, 26, 49, 28, 29, 49, 31, 5, 6,
- 7, 8, 9, 37, 38, 49, 44, 41, 48, 43,
- 37, 38, 39, 40, 56, 41, 50, 51, 52, 53,
- 54, 55, 56, 44, 58, 18, 19, 20, 21, 46,
- 23, 24, 25, 26, 49, 28, 29, 36, 31, 49,
- 56, 49, 0, 14, 37, 38, 233, 119, 234, 47,
- 43, 196, 293, 327, 324, 248, 47, 50, 51, 52,
- 53, 54, 55, 56, 270, 58, 18, 19, 20, 21,
- 272, 23, 24, 25, 26, 250, 28, 29, 30, 31,
- 32, 33, 34, 222, 274, 284, 26, 242, -1, -1,
- 42, -1, -1, -1, -1, -1, -1, -1, 50, -1,
- -1, -1, -1, 55, -1, -1, 58, 18, 19, 20,
- 21, -1, 23, 24, 25, 26, -1, 28, 29, 30,
- 31, 32, 33, 34, 18, 19, 20, 21, -1, 23,
- 24, 25, 26, 27, 28, 29, -1, 31, -1, 50,
- -1, -1, -1, -1, 55, -1, -1, 58, 42, -1,
- -1, -1, 18, 19, 20, 21, 50, 23, 24, 25,
- 26, 55, 28, 29, 58, 31, -1, 18, 19, 20,
- 21, -1, 23, 24, 25, 26, -1, 28, 29, 45,
- 31, -1, -1, -1, 50, -1, -1, -1, -1, 55,
- -1, 42, 58, -1, -1, 18, 19, 20, 21, 50,
- 23, 24, 25, 26, 55, 28, 29, 58, 31, -1,
- 18, 19, 20, 21, -1, 23, 24, 25, 26, 42,
- 28, 29, -1, 31, -1, -1, -1, 50, -1, -1,
- -1, -1, 55, 41, -1, 58, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 53, -1, 55, -1, -1,
- 58, 18, 19, 20, 21, -1, 23, 24, 25, 26,
- -1, 28, 29, -1, 31, -1, 18, 19, 20, 21,
- -1, 23, 24, 25, 26, 42, 28, 29, -1, 31,
- -1, -1, -1, 50, -1, -1, -1, -1, 55, -1,
- 42, 58, -1, -1, -1, -1, -1, -1, 50, -1,
- -1, -1, -1, 55, -1, -1, 58, 18, 19, 20,
- 21, -1, 23, 24, 25, 26, 27, 28, 29, -1,
- 31, 18, 19, 20, 21, -1, 23, 24, 25, 26,
- -1, 28, 29, -1, 31, 18, 19, 20, 21, 50,
- 23, 24, 25, 26, 55, 28, 29, 58, 31, -1,
- -1, -1, -1, 50, -1, -1, -1, -1, 55, -1,
- -1, 58, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 55, -1, -1, 58
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
- symbol of state STATE-NUM. */
-static const yytype_uint8 yystos[] =
-{
- 0, 0, 57, 58, 59, 60, 61, 62, 63, 64,
- 66, 67, 70, 72, 73, 74, 0, 4, 5, 6,
- 7, 8, 9, 10, 11, 68, 71, 74, 52, 135,
- 136, 135, 41, 41, 69, 70, 72, 75, 42, 70,
- 12, 13, 14, 15, 16, 42, 76, 114, 115, 49,
- 49, 17, 18, 19, 20, 21, 22, 23, 24, 25,
- 26, 28, 29, 31, 32, 33, 34, 35, 50, 55,
- 56, 58, 77, 78, 79, 80, 83, 86, 87, 91,
- 92, 93, 94, 95, 96, 110, 111, 112, 113, 122,
- 133, 52, 81, 82, 133, 52, 134, 29, 53, 55,
- 84, 127, 131, 56, 56, 131, 133, 131, 134, 134,
- 134, 25, 133, 36, 134, 45, 47, 36, 49, 48,
- 49, 36, 41, 41, 37, 41, 36, 36, 41, 36,
- 41, 41, 41, 131, 49, 53, 132, 41, 18, 19,
- 21, 23, 24, 25, 26, 29, 31, 37, 38, 43,
- 50, 51, 54, 56, 112, 118, 119, 122, 123, 130,
- 131, 133, 134, 112, 118, 82, 118, 77, 85, 85,
- 118, 45, 50, 88, 89, 90, 122, 133, 56, 118,
- 117, 118, 118, 85, 41, 45, 106, 107, 108, 109,
- 133, 25, 28, 30, 77, 93, 97, 98, 103, 110,
- 36, 49, 85, 119, 122, 119, 118, 119, 119, 43,
- 37, 38, 39, 40, 46, 36, 45, 49, 42, 77,
- 42, 29, 41, 55, 112, 120, 121, 124, 125, 126,
- 127, 133, 42, 48, 36, 49, 49, 42, 48, 49,
- 42, 108, 38, 53, 54, 128, 129, 42, 48, 42,
- 48, 36, 41, 134, 42, 98, 118, 42, 44, 116,
- 117, 118, 118, 118, 118, 118, 118, 49, 49, 125,
- 43, 46, 48, 46, 48, 49, 89, 90, 118, 49,
- 118, 49, 42, 129, 48, 49, 107, 49, 109, 41,
- 118, 27, 77, 99, 100, 41, 49, 49, 49, 44,
- 46, 42, 116, 121, 126, 127, 128, 108, 41, 42,
- 100, 56, 104, 105, 44, 46, 42, 41, 56, 101,
- 102, 49, 36, 42, 48, 117, 42, 48, 56, 49,
- 105, 42, 49, 102
-};
-
-#define yyerrok (yyerrstatus = 0)
-#define yyclearin (yychar = YYEMPTY)
-#define YYEMPTY (-2)
-#define YYEOF 0
-
-#define YYACCEPT goto yyacceptlab
-#define YYABORT goto yyabortlab
-#define YYERROR goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror. This remains here temporarily
- to ease the transition to the new meaning of YYERROR, for GCC.
- Once GCC version 2 has supplanted version 1, this can go. However,
- YYFAIL appears to be in use. Nevertheless, it is formally deprecated
- in Bison 2.4.2's NEWS entry, where a plan to phase it out is
- discussed. */
-
-#define YYFAIL goto yyerrlab
-#if defined YYFAIL
- /* This is here to suppress warnings from the GCC cpp's
- -Wunused-macros. Normally we don't worry about that warning, but
- some users do, and we want to make it easy for users to remove
- YYFAIL uses, which will produce warnings from Bison 2.5. */
-#endif
-
-#define YYRECOVERING() (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value) \
-do \
- if (yychar == YYEMPTY && yylen == 1) \
- { \
- yychar = (Token); \
- yylval = (Value); \
- YYPOPSTACK (1); \
- goto yybackup; \
- } \
- else \
- { \
- yyerror (param, YY_("syntax error: cannot back up")); \
- YYERROR; \
- } \
-while (YYID (0))
-
-
-#define YYTERROR 1
-#define YYERRCODE 256
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
- If N is 0, then set CURRENT to the empty location which ends
- the previous symbol: RHS[0] (always defined). */
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N) \
- do \
- if (YYID (N)) \
- { \
- (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
- (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
- (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
- (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
- } \
- else \
- { \
- (Current).first_line = (Current).last_line = \
- YYRHSLOC (Rhs, 0).last_line; \
- (Current).first_column = (Current).last_column = \
- YYRHSLOC (Rhs, 0).last_column; \
- } \
- while (YYID (0))
-#endif
-
-
-/* This macro is provided for backward compatibility. */
-
-#ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-#endif
-
-
-/* YYLEX -- calling `yylex' with the right arguments. */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (&yylval, YYLEX_PARAM)
-#else
-# define YYLEX yylex (&yylval, param_scanner)
-#endif
-
-/* Enable debugging if requested. */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-# define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args) \
-do { \
- if (yydebug) \
- YYFPRINTF Args; \
-} while (YYID (0))
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
-do { \
- if (yydebug) \
- { \
- YYFPRINTF (stderr, "%s ", Title); \
- yy_symbol_print (stderr, \
- Type, Value, param); \
- YYFPRINTF (stderr, "\n"); \
- } \
-} while (YYID (0))
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, struct parser_param *param)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep, param)
- FILE *yyoutput;
- int yytype;
- YYSTYPE const * const yyvaluep;
- struct parser_param *param;
-#endif
-{
- if (!yyvaluep)
- return;
- YYUSE (param);
-# ifdef YYPRINT
- if (yytype < YYNTOKENS)
- YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
- YYUSE (yyoutput);
-# endif
- switch (yytype)
- {
- default:
- break;
- }
-}
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, struct parser_param *param)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep, param)
- FILE *yyoutput;
- int yytype;
- YYSTYPE const * const yyvaluep;
- struct parser_param *param;
-#endif
-{
- if (yytype < YYNTOKENS)
- YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
- else
- YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
- yy_symbol_value_print (yyoutput, yytype, yyvaluep, param);
- YYFPRINTF (yyoutput, ")");
-}
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included). |
-`------------------------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
-#else
-static void
-yy_stack_print (yybottom, yytop)
- yytype_int16 *yybottom;
- yytype_int16 *yytop;
-#endif
-{
- YYFPRINTF (stderr, "Stack now");
- for (; yybottom <= yytop; yybottom++)
- {
- int yybot = *yybottom;
- YYFPRINTF (stderr, " %d", yybot);
- }
- YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top) \
-do { \
- if (yydebug) \
- yy_stack_print ((Bottom), (Top)); \
-} while (YYID (0))
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced. |
-`------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule, struct parser_param *param)
-#else
-static void
-yy_reduce_print (yyvsp, yyrule, param)
- YYSTYPE *yyvsp;
- int yyrule;
- struct parser_param *param;
-#endif
-{
- int yynrhs = yyr2[yyrule];
- int yyi;
- unsigned long int yylno = yyrline[yyrule];
- YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
- yyrule - 1, yylno);
- /* The symbols being reduced. */
- for (yyi = 0; yyi < yynrhs; yyi++)
- {
- YYFPRINTF (stderr, " $%d = ", yyi + 1);
- yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
- &(yyvsp[(yyi + 1) - (yynrhs)])
- , param);
- YYFPRINTF (stderr, "\n");
- }
-}
-
-# define YY_REDUCE_PRINT(Rule) \
-do { \
- if (yydebug) \
- yy_reduce_print (yyvsp, Rule, param); \
-} while (YYID (0))
-
-/* Nonzero means print parse trace. It is left uninitialized so that
- multiple parsers can coexist. */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks. */
-#ifndef YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
- if the built-in stack extension method is used).
-
- Do not make this value too large; the results are undefined if
- YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
- evaluated with infinite-precision integer arithmetic. */
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-# if defined __GLIBC__ && defined _STRING_H
-# define yystrlen strlen
-# else
-/* Return the length of YYSTR. */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static YYSIZE_T
-yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
- const char *yystr;
-#endif
-{
- YYSIZE_T yylen;
- for (yylen = 0; yystr[yylen]; yylen++)
- continue;
- return yylen;
-}
-# endif
-# endif
-
-# ifndef yystpcpy
-# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-# define yystpcpy stpcpy
-# else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
- YYDEST. */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static char *
-yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
- char *yydest;
- const char *yysrc;
-#endif
-{
- char *yyd = yydest;
- const char *yys = yysrc;
-
- while ((*yyd++ = *yys++) != '\0')
- continue;
-
- return yyd - 1;
-}
-# endif
-# endif
-
-# ifndef yytnamerr
-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
- quotes and backslashes, so that it's suitable for yyerror. The
- heuristic is that double-quoting is unnecessary unless the string
- contains an apostrophe, a comma, or backslash (other than
- backslash-backslash). YYSTR is taken from yytname. If YYRES is
- null, do not copy; instead, return the length of what the result
- would have been. */
-static YYSIZE_T
-yytnamerr (char *yyres, const char *yystr)
-{
- if (*yystr == '"')
- {
- YYSIZE_T yyn = 0;
- char const *yyp = yystr;
-
- for (;;)
- switch (*++yyp)
- {
- case '\'':
- case ',':
- goto do_not_strip_quotes;
-
- case '\\':
- if (*++yyp != '\\')
- goto do_not_strip_quotes;
- /* Fall through. */
- default:
- if (yyres)
- yyres[yyn] = *yyp;
- yyn++;
- break;
-
- case '"':
- if (yyres)
- yyres[yyn] = '\0';
- return yyn;
- }
- do_not_strip_quotes: ;
- }
-
- if (! yyres)
- return yystrlen (yystr);
-
- return yystpcpy (yyres, yystr) - yyres;
-}
-# endif
-
-/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
- about the unexpected token YYTOKEN for the state stack whose top is
- YYSSP.
-
- Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is
- not large enough to hold the message. In that case, also set
- *YYMSG_ALLOC to the required number of bytes. Return 2 if the
- required number of bytes is too large to store. */
-static int
-yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
- yytype_int16 *yyssp, int yytoken)
-{
- YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]);
- YYSIZE_T yysize = yysize0;
- YYSIZE_T yysize1;
- enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
- /* Internationalized format string. */
- const char *yyformat = 0;
- /* Arguments of yyformat. */
- char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
- /* Number of reported tokens (one for the "unexpected", one per
- "expected"). */
- int yycount = 0;
-
- /* There are many possibilities here to consider:
- - Assume YYFAIL is not used. It's too flawed to consider. See
- <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
- for details. YYERROR is fine as it does not invoke this
- function.
- - If this state is a consistent state with a default action, then
- the only way this function was invoked is if the default action
- is an error action. In that case, don't check for expected
- tokens because there are none.
- - The only way there can be no lookahead present (in yychar) is if
- this state is a consistent state with a default action. Thus,
- detecting the absence of a lookahead is sufficient to determine
- that there is no unexpected or expected token to report. In that
- case, just report a simple "syntax error".
- - Don't assume there isn't a lookahead just because this state is a
- consistent state with a default action. There might have been a
- previous inconsistent state, consistent state with a non-default
- action, or user semantic action that manipulated yychar.
- - Of course, the expected token list depends on states to have
- correct lookahead information, and it depends on the parser not
- to perform extra reductions after fetching a lookahead from the
- scanner and before detecting a syntax error. Thus, state merging
- (from LALR or IELR) and default reductions corrupt the expected
- token list. However, the list is correct for canonical LR with
- one exception: it will still contain any token that will not be
- accepted due to an error action in a later state.
- */
- if (yytoken != YYEMPTY)
- {
- int yyn = yypact[*yyssp];
- yyarg[yycount++] = yytname[yytoken];
- if (!yypact_value_is_default (yyn))
- {
- /* Start YYX at -YYN if negative to avoid negative indexes in
- YYCHECK. In other words, skip the first -YYN actions for
- this state because they are default actions. */
- int yyxbegin = yyn < 0 ? -yyn : 0;
- /* Stay within bounds of both yycheck and yytname. */
- int yychecklim = YYLAST - yyn + 1;
- int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
- int yyx;
-
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
- && !yytable_value_is_error (yytable[yyx + yyn]))
- {
- if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
- {
- yycount = 1;
- yysize = yysize0;
- break;
- }
- yyarg[yycount++] = yytname[yyx];
- yysize1 = yysize + yytnamerr (0, yytname[yyx]);
- if (! (yysize <= yysize1
- && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
- return 2;
- yysize = yysize1;
- }
- }
- }
-
- switch (yycount)
- {
-# define YYCASE_(N, S) \
- case N: \
- yyformat = S; \
- break
- YYCASE_(0, YY_("syntax error"));
- YYCASE_(1, YY_("syntax error, unexpected %s"));
- YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
- YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
- YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
- YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
-# undef YYCASE_
- }
-
- yysize1 = yysize + yystrlen (yyformat);
- if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
- return 2;
- yysize = yysize1;
-
- if (*yymsg_alloc < yysize)
- {
- *yymsg_alloc = 2 * yysize;
- if (! (yysize <= *yymsg_alloc
- && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
- *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
- return 1;
- }
-
- /* Avoid sprintf, as that infringes on the user's name space.
- Don't have undefined behavior even if the translation
- produced a string with the wrong number of "%s"s. */
- {
- char *yyp = *yymsg;
- int yyi = 0;
- while ((*yyp = *yyformat) != '\0')
- if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
- {
- yyp += yytnamerr (yyp, yyarg[yyi++]);
- yyformat += 2;
- }
- else
- {
- yyp++;
- yyformat++;
- }
- }
- return 0;
-}
-#endif /* YYERROR_VERBOSE */
-
-/*-----------------------------------------------.
-| Release the memory associated to this symbol. |
-`-----------------------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, struct parser_param *param)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep, param)
- const char *yymsg;
- int yytype;
- YYSTYPE *yyvaluep;
- struct parser_param *param;
-#endif
-{
- YYUSE (yyvaluep);
- YYUSE (param);
-
- if (!yymsg)
- yymsg = "Deleting";
- YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
-
- switch (yytype)
- {
-
- default:
- break;
- }
-}
-
-
-/* Prevent warnings from -Wmissing-prototypes. */
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (struct parser_param *param);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-
-/*----------.
-| yyparse. |
-`----------*/
-
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
- void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (struct parser_param *param)
-#else
-int
-yyparse (param)
- struct parser_param *param;
-#endif
-#endif
-{
-/* The lookahead symbol. */
-int yychar;
-
-/* The semantic value of the lookahead symbol. */
-YYSTYPE yylval;
-
- /* Number of syntax errors so far. */
- int yynerrs;
-
- int yystate;
- /* Number of tokens to shift before error messages enabled. */
- int yyerrstatus;
-
- /* The stacks and their tools:
- `yyss': related to states.
- `yyvs': related to semantic values.
-
- Refer to the stacks thru separate pointers, to allow yyoverflow
- to reallocate them elsewhere. */
-
- /* The state stack. */
- yytype_int16 yyssa[YYINITDEPTH];
- yytype_int16 *yyss;
- yytype_int16 *yyssp;
-
- /* The semantic value stack. */
- YYSTYPE yyvsa[YYINITDEPTH];
- YYSTYPE *yyvs;
- YYSTYPE *yyvsp;
-
- YYSIZE_T yystacksize;
-
- int yyn;
- int yyresult;
- /* Lookahead token as an internal (translated) token number. */
- int yytoken;
- /* The variables used to return semantic value and location from the
- action routines. */
- YYSTYPE yyval;
-
-#if YYERROR_VERBOSE
- /* Buffer for error messages, and its allocated size. */
- char yymsgbuf[128];
- char *yymsg = yymsgbuf;
- YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
-
-#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
-
- /* The number of symbols on the RHS of the reduced rule.
- Keep to zero when no symbol should be popped. */
- int yylen = 0;
-
- yytoken = 0;
- yyss = yyssa;
- yyvs = yyvsa;
- yystacksize = YYINITDEPTH;
-
- YYDPRINTF ((stderr, "Starting parse\n"));
-
- yystate = 0;
- yyerrstatus = 0;
- yynerrs = 0;
- yychar = YYEMPTY; /* Cause a token to be read. */
-
- /* Initialize stack pointers.
- Waste one element of value and location stack
- so that they stay on the same level as the state stack.
- The wasted elements are never initialized. */
- yyssp = yyss;
- yyvsp = yyvs;
-
- goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate. |
-`------------------------------------------------------------*/
- yynewstate:
- /* In all cases, when you get here, the value and location stacks
- have just been pushed. So pushing a state here evens the stacks. */
- yyssp++;
-
- yysetstate:
- *yyssp = yystate;
-
- if (yyss + yystacksize - 1 <= yyssp)
- {
- /* Get the current used size of the three stacks, in elements. */
- YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
- {
- /* Give user a chance to reallocate the stack. Use copies of
- these so that the &'s don't force the real ones into
- memory. */
- YYSTYPE *yyvs1 = yyvs;
- yytype_int16 *yyss1 = yyss;
-
- /* Each stack pointer address is followed by the size of the
- data in use in that stack, in bytes. This used to be a
- conditional around just the two extra args, but that might
- be undefined if yyoverflow is a macro. */
- yyoverflow (YY_("memory exhausted"),
- &yyss1, yysize * sizeof (*yyssp),
- &yyvs1, yysize * sizeof (*yyvsp),
- &yystacksize);
-
- yyss = yyss1;
- yyvs = yyvs1;
- }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
- goto yyexhaustedlab;
-# else
- /* Extend the stack our own way. */
- if (YYMAXDEPTH <= yystacksize)
- goto yyexhaustedlab;
- yystacksize *= 2;
- if (YYMAXDEPTH < yystacksize)
- yystacksize = YYMAXDEPTH;
-
- {
- yytype_int16 *yyss1 = yyss;
- union yyalloc *yyptr =
- (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
- if (! yyptr)
- goto yyexhaustedlab;
- YYSTACK_RELOCATE (yyss_alloc, yyss);
- YYSTACK_RELOCATE (yyvs_alloc, yyvs);
-# undef YYSTACK_RELOCATE
- if (yyss1 != yyssa)
- YYSTACK_FREE (yyss1);
- }
-# endif
-#endif /* no yyoverflow */
-
- yyssp = yyss + yysize - 1;
- yyvsp = yyvs + yysize - 1;
-
- YYDPRINTF ((stderr, "Stack size increased to %lu\n",
- (unsigned long int) yystacksize));
-
- if (yyss + yystacksize - 1 <= yyssp)
- YYABORT;
- }
-
- YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
- if (yystate == YYFINAL)
- YYACCEPT;
-
- goto yybackup;
-
-/*-----------.
-| yybackup. |
-`-----------*/
-yybackup:
-
- /* Do appropriate processing given the current state. Read a
- lookahead token if we need one and don't already have one. */
-
- /* First try to decide what to do without reference to lookahead token. */
- yyn = yypact[yystate];
- if (yypact_value_is_default (yyn))
- goto yydefault;
-
- /* Not known => get a lookahead token if don't already have one. */
-
- /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
- if (yychar == YYEMPTY)
- {
- YYDPRINTF ((stderr, "Reading a token: "));
- yychar = YYLEX;
- }
-
- if (yychar <= YYEOF)
- {
- yychar = yytoken = YYEOF;
- YYDPRINTF ((stderr, "Now at end of input.\n"));
- }
- else
- {
- yytoken = YYTRANSLATE (yychar);
- YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
- }
-
- /* If the proper action on seeing token YYTOKEN is to reduce or to
- detect an error, take that action. */
- yyn += yytoken;
- if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
- goto yydefault;
- yyn = yytable[yyn];
- if (yyn <= 0)
- {
- if (yytable_value_is_error (yyn))
- goto yyerrlab;
- yyn = -yyn;
- goto yyreduce;
- }
-
- /* Count tokens shifted since error; after three, turn off error
- status. */
- if (yyerrstatus)
- yyerrstatus--;
-
- /* Shift the lookahead token. */
- YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
- /* Discard the shifted token. */
- yychar = YYEMPTY;
-
- yystate = yyn;
- *++yyvsp = yylval;
-
- goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state. |
-`-----------------------------------------------------------*/
-yydefault:
- yyn = yydefact[yystate];
- if (yyn == 0)
- goto yyerrlab;
- goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction. |
-`-----------------------------*/
-yyreduce:
- /* yyn is the number of a rule to reduce with. */
- yylen = yyr2[yyn];
-
- /* If YYLEN is nonzero, implement the default value of the action:
- `$$ = $1'.
-
- Otherwise, the following line sets YYVAL to garbage.
- This behavior is undocumented and Bison
- users should not rely upon it. Assigning to YYVAL
- unconditionally makes the parser a bit smaller, and it avoids a
- GCC warning that YYVAL may be used uninitialized. */
- yyval = yyvsp[1-yylen];
-
-
- YY_REDUCE_PRINT (yyn);
- switch (yyn)
- {
- case 2:
-
-/* Line 1806 of yacc.c */
-#line 233 "parser.y"
- { (yyval.file) = param->rtrn = (yyvsp[(1) - (1)].file); param->more_maps = true; }
- break;
-
- case 3:
-
-/* Line 1806 of yacc.c */
-#line 235 "parser.y"
- { (yyval.file) = param->rtrn = (yyvsp[(1) - (1)].file); param->more_maps = true; YYACCEPT; }
- break;
-
- case 4:
-
-/* Line 1806 of yacc.c */
-#line 237 "parser.y"
- { (yyval.file) = param->rtrn = NULL; param->more_maps = false; }
- break;
-
- case 5:
-
-/* Line 1806 of yacc.c */
-#line 243 "parser.y"
- { (yyval.file) = XkbFileCreate((yyvsp[(2) - (7)].file_type), (yyvsp[(3) - (7)].str), (ParseCommon *) (yyvsp[(5) - (7)].file), (yyvsp[(1) - (7)].mapFlags)); }
- break;
-
- case 6:
-
-/* Line 1806 of yacc.c */
-#line 246 "parser.y"
- { (yyval.file_type) = FILE_TYPE_KEYMAP; }
- break;
-
- case 7:
-
-/* Line 1806 of yacc.c */
-#line 247 "parser.y"
- { (yyval.file_type) = FILE_TYPE_KEYMAP; }
- break;
-
- case 8:
-
-/* Line 1806 of yacc.c */
-#line 248 "parser.y"
- { (yyval.file_type) = FILE_TYPE_KEYMAP; }
- break;
-
- case 9:
-
-/* Line 1806 of yacc.c */
-#line 252 "parser.y"
- {
- if (!(yyvsp[(2) - (2)].file))
- (yyval.file) = (yyvsp[(1) - (2)].file);
- else
- (yyval.file) = (XkbFile *) AppendStmt((ParseCommon *) (yyvsp[(1) - (2)].file),
- (ParseCommon *) (yyvsp[(2) - (2)].file));
- }
- break;
-
- case 10:
-
-/* Line 1806 of yacc.c */
-#line 260 "parser.y"
- { (yyval.file) = (yyvsp[(1) - (1)].file); }
- break;
-
- case 11:
-
-/* Line 1806 of yacc.c */
-#line 266 "parser.y"
- {
- if ((yyvsp[(2) - (7)].file_type) == FILE_TYPE_GEOMETRY) {
- free((yyvsp[(3) - (7)].str));
- FreeStmt((yyvsp[(5) - (7)].any));
- (yyval.file) = NULL;
- }
- else {
- (yyval.file) = XkbFileCreate((yyvsp[(2) - (7)].file_type), (yyvsp[(3) - (7)].str), (yyvsp[(5) - (7)].any), (yyvsp[(1) - (7)].mapFlags));
- }
- }
- break;
-
- case 12:
-
-/* Line 1806 of yacc.c */
-#line 278 "parser.y"
- { (yyval.file_type) = FILE_TYPE_KEYCODES; }
- break;
-
- case 13:
-
-/* Line 1806 of yacc.c */
-#line 279 "parser.y"
- { (yyval.file_type) = FILE_TYPE_TYPES; }
- break;
-
- case 14:
-
-/* Line 1806 of yacc.c */
-#line 280 "parser.y"
- { (yyval.file_type) = FILE_TYPE_COMPAT; }
- break;
-
- case 15:
-
-/* Line 1806 of yacc.c */
-#line 281 "parser.y"
- { (yyval.file_type) = FILE_TYPE_SYMBOLS; }
- break;
-
- case 16:
-
-/* Line 1806 of yacc.c */
-#line 282 "parser.y"
- { (yyval.file_type) = FILE_TYPE_GEOMETRY; }
- break;
-
- case 17:
-
-/* Line 1806 of yacc.c */
-#line 285 "parser.y"
- { (yyval.mapFlags) = (yyvsp[(1) - (1)].mapFlags); }
- break;
-
- case 18:
-
-/* Line 1806 of yacc.c */
-#line 286 "parser.y"
- { (yyval.mapFlags) = 0; }
- break;
-
- case 19:
-
-/* Line 1806 of yacc.c */
-#line 289 "parser.y"
- { (yyval.mapFlags) = ((yyvsp[(1) - (2)].mapFlags) | (yyvsp[(2) - (2)].mapFlags)); }
- break;
-
- case 20:
-
-/* Line 1806 of yacc.c */
-#line 290 "parser.y"
- { (yyval.mapFlags) = (yyvsp[(1) - (1)].mapFlags); }
- break;
-
- case 21:
-
-/* Line 1806 of yacc.c */
-#line 293 "parser.y"
- { (yyval.mapFlags) = MAP_IS_PARTIAL; }
- break;
-
- case 22:
-
-/* Line 1806 of yacc.c */
-#line 294 "parser.y"
- { (yyval.mapFlags) = MAP_IS_DEFAULT; }
- break;
-
- case 23:
-
-/* Line 1806 of yacc.c */
-#line 295 "parser.y"
- { (yyval.mapFlags) = MAP_IS_HIDDEN; }
- break;
-
- case 24:
-
-/* Line 1806 of yacc.c */
-#line 296 "parser.y"
- { (yyval.mapFlags) = MAP_HAS_ALPHANUMERIC; }
- break;
-
- case 25:
-
-/* Line 1806 of yacc.c */
-#line 297 "parser.y"
- { (yyval.mapFlags) = MAP_HAS_MODIFIER; }
- break;
-
- case 26:
-
-/* Line 1806 of yacc.c */
-#line 298 "parser.y"
- { (yyval.mapFlags) = MAP_HAS_KEYPAD; }
- break;
-
- case 27:
-
-/* Line 1806 of yacc.c */
-#line 299 "parser.y"
- { (yyval.mapFlags) = MAP_HAS_FN; }
- break;
-
- case 28:
-
-/* Line 1806 of yacc.c */
-#line 300 "parser.y"
- { (yyval.mapFlags) = MAP_IS_ALTGR; }
- break;
-
- case 29:
-
-/* Line 1806 of yacc.c */
-#line 304 "parser.y"
- { (yyval.any) = AppendStmt((yyvsp[(1) - (2)].any), (yyvsp[(2) - (2)].any)); }
- break;
-
- case 30:
-
-/* Line 1806 of yacc.c */
-#line 305 "parser.y"
- { (yyval.any) = NULL; }
- break;
-
- case 31:
-
-/* Line 1806 of yacc.c */
-#line 309 "parser.y"
- {
- (yyvsp[(2) - (2)].var)->merge = (yyvsp[(1) - (2)].merge);
- (yyval.any) = (ParseCommon *) (yyvsp[(2) - (2)].var);
- }
- break;
-
- case 32:
-
-/* Line 1806 of yacc.c */
-#line 314 "parser.y"
- {
- (yyvsp[(2) - (2)].vmod)->merge = (yyvsp[(1) - (2)].merge);
- (yyval.any) = (ParseCommon *) (yyvsp[(2) - (2)].vmod);
- }
- break;
-
- case 33:
-
-/* Line 1806 of yacc.c */
-#line 319 "parser.y"
- {
- (yyvsp[(2) - (2)].interp)->merge = (yyvsp[(1) - (2)].merge);
- (yyval.any) = (ParseCommon *) (yyvsp[(2) - (2)].interp);
- }
- break;
-
- case 34:
-
-/* Line 1806 of yacc.c */
-#line 324 "parser.y"
- {
- (yyvsp[(2) - (2)].keyCode)->merge = (yyvsp[(1) - (2)].merge);
- (yyval.any) = (ParseCommon *) (yyvsp[(2) - (2)].keyCode);
- }
- break;
-
- case 35:
-
-/* Line 1806 of yacc.c */
-#line 329 "parser.y"
- {
- (yyvsp[(2) - (2)].keyAlias)->merge = (yyvsp[(1) - (2)].merge);
- (yyval.any) = (ParseCommon *) (yyvsp[(2) - (2)].keyAlias);
- }
- break;
-
- case 36:
-
-/* Line 1806 of yacc.c */
-#line 334 "parser.y"
- {
- (yyvsp[(2) - (2)].keyType)->merge = (yyvsp[(1) - (2)].merge);
- (yyval.any) = (ParseCommon *) (yyvsp[(2) - (2)].keyType);
- }
- break;
-
- case 37:
-
-/* Line 1806 of yacc.c */
-#line 339 "parser.y"
- {
- (yyvsp[(2) - (2)].syms)->merge = (yyvsp[(1) - (2)].merge);
- (yyval.any) = (ParseCommon *) (yyvsp[(2) - (2)].syms);
- }
- break;
-
- case 38:
-
-/* Line 1806 of yacc.c */
-#line 344 "parser.y"
- {
- (yyvsp[(2) - (2)].modMask)->merge = (yyvsp[(1) - (2)].merge);
- (yyval.any) = (ParseCommon *) (yyvsp[(2) - (2)].modMask);
- }
- break;
-
- case 39:
-
-/* Line 1806 of yacc.c */
-#line 349 "parser.y"
- {
- (yyvsp[(2) - (2)].groupCompat)->merge = (yyvsp[(1) - (2)].merge);
- (yyval.any) = (ParseCommon *) (yyvsp[(2) - (2)].groupCompat);
- }
- break;
-
- case 40:
-
-/* Line 1806 of yacc.c */
-#line 354 "parser.y"
- {
- (yyvsp[(2) - (2)].ledMap)->merge = (yyvsp[(1) - (2)].merge);
- (yyval.any) = (ParseCommon *) (yyvsp[(2) - (2)].ledMap);
- }
- break;
-
- case 41:
-
-/* Line 1806 of yacc.c */
-#line 359 "parser.y"
- {
- (yyvsp[(2) - (2)].ledName)->merge = (yyvsp[(1) - (2)].merge);
- (yyval.any) = (ParseCommon *) (yyvsp[(2) - (2)].ledName);
- }
- break;
-
- case 42:
-
-/* Line 1806 of yacc.c */
-#line 363 "parser.y"
- { (yyval.any) = NULL; }
- break;
-
- case 43:
-
-/* Line 1806 of yacc.c */
-#line 364 "parser.y"
- { (yyval.any) = NULL; }
- break;
-
- case 44:
-
-/* Line 1806 of yacc.c */
-#line 365 "parser.y"
- { (yyval.any) = NULL; }
- break;
-
- case 45:
-
-/* Line 1806 of yacc.c */
-#line 367 "parser.y"
- {
- (yyval.any) = (ParseCommon *) IncludeCreate(param->ctx, (yyvsp[(2) - (2)].str), (yyvsp[(1) - (2)].merge));
- free((yyvsp[(2) - (2)].str));
- }
- break;
-
- case 46:
-
-/* Line 1806 of yacc.c */
-#line 374 "parser.y"
- { (yyval.var) = VarCreate((yyvsp[(1) - (4)].expr), (yyvsp[(3) - (4)].expr)); }
- break;
-
- case 47:
-
-/* Line 1806 of yacc.c */
-#line 376 "parser.y"
- { (yyval.var) = BoolVarCreate((yyvsp[(1) - (2)].sval), true); }
- break;
-
- case 48:
-
-/* Line 1806 of yacc.c */
-#line 378 "parser.y"
- { (yyval.var) = BoolVarCreate((yyvsp[(2) - (3)].sval), false); }
- break;
-
- case 49:
-
-/* Line 1806 of yacc.c */
-#line 382 "parser.y"
- { (yyval.keyCode) = KeycodeCreate((yyvsp[(1) - (4)].sval), (yyvsp[(3) - (4)].num)); }
- break;
-
- case 50:
-
-/* Line 1806 of yacc.c */
-#line 386 "parser.y"
- { (yyval.keyAlias) = KeyAliasCreate((yyvsp[(2) - (5)].sval), (yyvsp[(4) - (5)].sval)); }
- break;
-
- case 51:
-
-/* Line 1806 of yacc.c */
-#line 390 "parser.y"
- { (yyval.vmod) = (yyvsp[(2) - (3)].vmod); }
- break;
-
- case 52:
-
-/* Line 1806 of yacc.c */
-#line 394 "parser.y"
- { (yyval.vmod) = (VModDef *) AppendStmt((ParseCommon *) (yyvsp[(1) - (3)].vmod),
- (ParseCommon *) (yyvsp[(3) - (3)].vmod)); }
- break;
-
- case 53:
-
-/* Line 1806 of yacc.c */
-#line 397 "parser.y"
- { (yyval.vmod) = (yyvsp[(1) - (1)].vmod); }
- break;
-
- case 54:
-
-/* Line 1806 of yacc.c */
-#line 401 "parser.y"
- { (yyval.vmod) = VModCreate((yyvsp[(1) - (1)].sval), NULL); }
- break;
-
- case 55:
-
-/* Line 1806 of yacc.c */
-#line 403 "parser.y"
- { (yyval.vmod) = VModCreate((yyvsp[(1) - (3)].sval), (yyvsp[(3) - (3)].expr)); }
- break;
-
- case 56:
-
-/* Line 1806 of yacc.c */
-#line 409 "parser.y"
- { (yyvsp[(2) - (6)].interp)->def = (yyvsp[(4) - (6)].var); (yyval.interp) = (yyvsp[(2) - (6)].interp); }
- break;
-
- case 57:
-
-/* Line 1806 of yacc.c */
-#line 413 "parser.y"
- { (yyval.interp) = InterpCreate((yyvsp[(1) - (3)].keysym), (yyvsp[(3) - (3)].expr)); }
- break;
-
- case 58:
-
-/* Line 1806 of yacc.c */
-#line 415 "parser.y"
- { (yyval.interp) = InterpCreate((yyvsp[(1) - (1)].keysym), NULL); }
- break;
-
- case 59:
-
-/* Line 1806 of yacc.c */
-#line 419 "parser.y"
- { (yyval.var) = (VarDef *) AppendStmt((ParseCommon *) (yyvsp[(1) - (2)].var),
- (ParseCommon *) (yyvsp[(2) - (2)].var)); }
- break;
-
- case 60:
-
-/* Line 1806 of yacc.c */
-#line 422 "parser.y"
- { (yyval.var) = (yyvsp[(1) - (1)].var); }
- break;
-
- case 61:
-
-/* Line 1806 of yacc.c */
-#line 428 "parser.y"
- { (yyval.keyType) = KeyTypeCreate((yyvsp[(2) - (6)].sval), (yyvsp[(4) - (6)].var)); }
- break;
-
- case 62:
-
-/* Line 1806 of yacc.c */
-#line 434 "parser.y"
- { (yyval.syms) = SymbolsCreate((yyvsp[(2) - (6)].sval), (yyvsp[(4) - (6)].var)); }
- break;
-
- case 63:
-
-/* Line 1806 of yacc.c */
-#line 438 "parser.y"
- { (yyval.var) = (VarDef *) AppendStmt((ParseCommon *) (yyvsp[(1) - (3)].var),
- (ParseCommon *) (yyvsp[(3) - (3)].var)); }
- break;
-
- case 64:
-
-/* Line 1806 of yacc.c */
-#line 441 "parser.y"
- { (yyval.var) = (yyvsp[(1) - (1)].var); }
- break;
-
- case 65:
-
-/* Line 1806 of yacc.c */
-#line 442 "parser.y"
- { (yyval.var) = NULL; }
- break;
-
- case 66:
-
-/* Line 1806 of yacc.c */
-#line 445 "parser.y"
- { (yyval.var) = VarCreate((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
- break;
-
- case 67:
-
-/* Line 1806 of yacc.c */
-#line 446 "parser.y"
- { (yyval.var) = VarCreate((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
- break;
-
- case 68:
-
-/* Line 1806 of yacc.c */
-#line 447 "parser.y"
- { (yyval.var) = BoolVarCreate((yyvsp[(1) - (1)].sval), true); }
- break;
-
- case 69:
-
-/* Line 1806 of yacc.c */
-#line 448 "parser.y"
- { (yyval.var) = BoolVarCreate((yyvsp[(2) - (2)].sval), false); }
- break;
-
- case 70:
-
-/* Line 1806 of yacc.c */
-#line 449 "parser.y"
- { (yyval.var) = VarCreate(NULL, (yyvsp[(1) - (1)].expr)); }
- break;
-
- case 71:
-
-/* Line 1806 of yacc.c */
-#line 453 "parser.y"
- { (yyval.expr) = (yyvsp[(2) - (3)].expr); }
- break;
-
- case 72:
-
-/* Line 1806 of yacc.c */
-#line 455 "parser.y"
- { (yyval.expr) = ExprCreateUnary(EXPR_ACTION_LIST, EXPR_TYPE_ACTION, (yyvsp[(2) - (3)].expr)); }
- break;
-
- case 73:
-
-/* Line 1806 of yacc.c */
-#line 459 "parser.y"
- { (yyval.groupCompat) = GroupCompatCreate((yyvsp[(2) - (5)].ival), (yyvsp[(4) - (5)].expr)); }
- break;
-
- case 74:
-
-/* Line 1806 of yacc.c */
-#line 463 "parser.y"
- { (yyval.modMask) = ModMapCreate((yyvsp[(2) - (6)].sval), (yyvsp[(4) - (6)].expr)); }
- break;
-
- case 75:
-
-/* Line 1806 of yacc.c */
-#line 467 "parser.y"
- { (yyval.ledMap) = LedMapCreate((yyvsp[(2) - (6)].sval), (yyvsp[(4) - (6)].var)); }
- break;
-
- case 76:
-
-/* Line 1806 of yacc.c */
-#line 471 "parser.y"
- { (yyval.ledName) = LedNameCreate((yyvsp[(2) - (5)].ival), (yyvsp[(4) - (5)].expr), false); }
- break;
-
- case 77:
-
-/* Line 1806 of yacc.c */
-#line 473 "parser.y"
- { (yyval.ledName) = LedNameCreate((yyvsp[(3) - (6)].ival), (yyvsp[(5) - (6)].expr), true); }
- break;
-
- case 78:
-
-/* Line 1806 of yacc.c */
-#line 477 "parser.y"
- { (yyval.geom) = NULL; }
- break;
-
- case 79:
-
-/* Line 1806 of yacc.c */
-#line 479 "parser.y"
- { (yyval.geom) = NULL; }
- break;
-
- case 80:
-
-/* Line 1806 of yacc.c */
-#line 483 "parser.y"
- { (yyval.geom) = NULL; }
- break;
-
- case 81:
-
-/* Line 1806 of yacc.c */
-#line 486 "parser.y"
- { (yyval.geom) = NULL;}
- break;
-
- case 82:
-
-/* Line 1806 of yacc.c */
-#line 487 "parser.y"
- { (yyval.geom) = NULL; }
- break;
-
- case 83:
-
-/* Line 1806 of yacc.c */
-#line 491 "parser.y"
- { (yyval.geom) = NULL; }
- break;
-
- case 84:
-
-/* Line 1806 of yacc.c */
-#line 493 "parser.y"
- { FreeStmt((ParseCommon *) (yyvsp[(1) - (1)].var)); (yyval.geom) = NULL; }
- break;
-
- case 85:
-
-/* Line 1806 of yacc.c */
-#line 495 "parser.y"
- { (yyval.geom) = NULL; }
- break;
-
- case 86:
-
-/* Line 1806 of yacc.c */
-#line 497 "parser.y"
- { FreeStmt((ParseCommon *) (yyvsp[(1) - (1)].ledMap)); (yyval.geom) = NULL; }
- break;
-
- case 87:
-
-/* Line 1806 of yacc.c */
-#line 499 "parser.y"
- { (yyval.geom) = NULL; }
- break;
-
- case 88:
-
-/* Line 1806 of yacc.c */
-#line 502 "parser.y"
- { (yyval.geom) = NULL;}
- break;
-
- case 89:
-
-/* Line 1806 of yacc.c */
-#line 503 "parser.y"
- { (yyval.geom) = NULL; }
- break;
-
- case 90:
-
-/* Line 1806 of yacc.c */
-#line 506 "parser.y"
- { (yyval.geom) = NULL; }
- break;
-
- case 91:
-
-/* Line 1806 of yacc.c */
-#line 508 "parser.y"
- { FreeStmt((ParseCommon *) (yyvsp[(1) - (1)].var)); (yyval.geom) = NULL; }
- break;
-
- case 92:
-
-/* Line 1806 of yacc.c */
-#line 511 "parser.y"
- { (yyval.geom) = NULL; }
- break;
-
- case 93:
-
-/* Line 1806 of yacc.c */
-#line 512 "parser.y"
- { (yyval.geom) = NULL; }
- break;
-
- case 94:
-
-/* Line 1806 of yacc.c */
-#line 516 "parser.y"
- { (yyval.geom) = NULL; }
- break;
-
- case 95:
-
-/* Line 1806 of yacc.c */
-#line 518 "parser.y"
- { FreeStmt((ParseCommon *) (yyvsp[(2) - (3)].expr)); (yyval.geom) = NULL; }
- break;
-
- case 96:
-
-/* Line 1806 of yacc.c */
-#line 522 "parser.y"
- { (yyval.geom) = NULL; }
- break;
-
- case 97:
-
-/* Line 1806 of yacc.c */
-#line 525 "parser.y"
- { (yyval.geom) = NULL; }
- break;
-
- case 98:
-
-/* Line 1806 of yacc.c */
-#line 526 "parser.y"
- { (yyval.geom) = NULL; }
- break;
-
- case 99:
-
-/* Line 1806 of yacc.c */
-#line 529 "parser.y"
- { (yyval.geom) = NULL; }
- break;
-
- case 100:
-
-/* Line 1806 of yacc.c */
-#line 533 "parser.y"
- { (yyval.geom) = NULL;}
- break;
-
- case 101:
-
-/* Line 1806 of yacc.c */
-#line 535 "parser.y"
- { (yyval.geom) = NULL; }
- break;
-
- case 102:
-
-/* Line 1806 of yacc.c */
-#line 539 "parser.y"
- { (yyval.geom) = NULL; }
- break;
-
- case 103:
-
-/* Line 1806 of yacc.c */
-#line 541 "parser.y"
- { (yyval.geom) = NULL; }
- break;
-
- case 104:
-
-/* Line 1806 of yacc.c */
-#line 543 "parser.y"
- { FreeStmt((ParseCommon *) (yyvsp[(3) - (3)].expr)); (yyval.geom) = NULL; }
- break;
-
- case 105:
-
-/* Line 1806 of yacc.c */
-#line 547 "parser.y"
- { (yyval.expr) = NULL; }
- break;
-
- case 106:
-
-/* Line 1806 of yacc.c */
-#line 549 "parser.y"
- { (yyval.expr) = NULL; }
- break;
-
- case 107:
-
-/* Line 1806 of yacc.c */
-#line 553 "parser.y"
- { (yyval.expr) = NULL; }
- break;
-
- case 108:
-
-/* Line 1806 of yacc.c */
-#line 557 "parser.y"
- { FreeStmt((ParseCommon *) (yyvsp[(4) - (6)].var)); (yyval.geom) = NULL; }
- break;
-
- case 109:
-
-/* Line 1806 of yacc.c */
-#line 560 "parser.y"
- { (yyval.ival) = 0; }
- break;
-
- case 110:
-
-/* Line 1806 of yacc.c */
-#line 561 "parser.y"
- { (yyval.ival) = 0; }
- break;
-
- case 111:
-
-/* Line 1806 of yacc.c */
-#line 562 "parser.y"
- { (yyval.ival) = 0; }
- break;
-
- case 112:
-
-/* Line 1806 of yacc.c */
-#line 563 "parser.y"
- { (yyval.ival) = 0; }
- break;
-
- case 113:
-
-/* Line 1806 of yacc.c */
-#line 566 "parser.y"
- { (yyval.sval) = (yyvsp[(1) - (1)].sval); }
- break;
-
- case 114:
-
-/* Line 1806 of yacc.c */
-#line 567 "parser.y"
- { (yyval.sval) = (yyvsp[(1) - (1)].sval); }
- break;
-
- case 115:
-
-/* Line 1806 of yacc.c */
-#line 571 "parser.y"
- { (yyval.sval) = xkb_atom_intern_literal(param->ctx, "action"); }
- break;
-
- case 116:
-
-/* Line 1806 of yacc.c */
-#line 573 "parser.y"
- { (yyval.sval) = xkb_atom_intern_literal(param->ctx, "interpret"); }
- break;
-
- case 117:
-
-/* Line 1806 of yacc.c */
-#line 575 "parser.y"
- { (yyval.sval) = xkb_atom_intern_literal(param->ctx, "type"); }
- break;
-
- case 118:
-
-/* Line 1806 of yacc.c */
-#line 577 "parser.y"
- { (yyval.sval) = xkb_atom_intern_literal(param->ctx, "key"); }
- break;
-
- case 119:
-
-/* Line 1806 of yacc.c */
-#line 579 "parser.y"
- { (yyval.sval) = xkb_atom_intern_literal(param->ctx, "group"); }
- break;
-
- case 120:
-
-/* Line 1806 of yacc.c */
-#line 581 "parser.y"
- {(yyval.sval) = xkb_atom_intern_literal(param->ctx, "modifier_map");}
- break;
-
- case 121:
-
-/* Line 1806 of yacc.c */
-#line 583 "parser.y"
- { (yyval.sval) = xkb_atom_intern_literal(param->ctx, "indicator"); }
- break;
-
- case 122:
-
-/* Line 1806 of yacc.c */
-#line 585 "parser.y"
- { (yyval.sval) = XKB_ATOM_NONE; }
- break;
-
- case 123:
-
-/* Line 1806 of yacc.c */
-#line 587 "parser.y"
- { (yyval.sval) = XKB_ATOM_NONE; }
- break;
-
- case 124:
-
-/* Line 1806 of yacc.c */
-#line 589 "parser.y"
- { (yyval.sval) = XKB_ATOM_NONE; }
- break;
-
- case 125:
-
-/* Line 1806 of yacc.c */
-#line 591 "parser.y"
- { (yyval.sval) = XKB_ATOM_NONE; }
- break;
-
- case 126:
-
-/* Line 1806 of yacc.c */
-#line 594 "parser.y"
- { (yyval.merge) = (yyvsp[(1) - (1)].merge); }
- break;
-
- case 127:
-
-/* Line 1806 of yacc.c */
-#line 595 "parser.y"
- { (yyval.merge) = MERGE_DEFAULT; }
- break;
-
- case 128:
-
-/* Line 1806 of yacc.c */
-#line 598 "parser.y"
- { (yyval.merge) = MERGE_DEFAULT; }
- break;
-
- case 129:
-
-/* Line 1806 of yacc.c */
-#line 599 "parser.y"
- { (yyval.merge) = MERGE_AUGMENT; }
- break;
-
- case 130:
-
-/* Line 1806 of yacc.c */
-#line 600 "parser.y"
- { (yyval.merge) = MERGE_OVERRIDE; }
- break;
-
- case 131:
-
-/* Line 1806 of yacc.c */
-#line 601 "parser.y"
- { (yyval.merge) = MERGE_REPLACE; }
- break;
-
- case 132:
-
-/* Line 1806 of yacc.c */
-#line 603 "parser.y"
- {
- /*
- * This used to be MERGE_ALT_FORM. This functionality was
- * unused and has been removed.
- */
- (yyval.merge) = MERGE_DEFAULT;
- }
- break;
-
- case 133:
-
-/* Line 1806 of yacc.c */
-#line 612 "parser.y"
- { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
- break;
-
- case 134:
-
-/* Line 1806 of yacc.c */
-#line 613 "parser.y"
- { (yyval.expr) = NULL; }
- break;
-
- case 135:
-
-/* Line 1806 of yacc.c */
-#line 617 "parser.y"
- { (yyval.expr) = (ExprDef *) AppendStmt((ParseCommon *) (yyvsp[(1) - (3)].expr),
- (ParseCommon *) (yyvsp[(3) - (3)].expr)); }
- break;
-
- case 136:
-
-/* Line 1806 of yacc.c */
-#line 620 "parser.y"
- { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
- break;
-
- case 137:
-
-/* Line 1806 of yacc.c */
-#line 624 "parser.y"
- { (yyval.expr) = ExprCreateBinary(EXPR_DIVIDE, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
- break;
-
- case 138:
-
-/* Line 1806 of yacc.c */
-#line 626 "parser.y"
- { (yyval.expr) = ExprCreateBinary(EXPR_ADD, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
- break;
-
- case 139:
-
-/* Line 1806 of yacc.c */
-#line 628 "parser.y"
- { (yyval.expr) = ExprCreateBinary(EXPR_SUBTRACT, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
- break;
-
- case 140:
-
-/* Line 1806 of yacc.c */
-#line 630 "parser.y"
- { (yyval.expr) = ExprCreateBinary(EXPR_MULTIPLY, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
- break;
-
- case 141:
-
-/* Line 1806 of yacc.c */
-#line 632 "parser.y"
- { (yyval.expr) = ExprCreateBinary(EXPR_ASSIGN, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
- break;
-
- case 142:
-
-/* Line 1806 of yacc.c */
-#line 634 "parser.y"
- { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
- break;
-
- case 143:
-
-/* Line 1806 of yacc.c */
-#line 638 "parser.y"
- { (yyval.expr) = ExprCreateUnary(EXPR_NEGATE, (yyvsp[(2) - (2)].expr)->expr.value_type, (yyvsp[(2) - (2)].expr)); }
- break;
-
- case 144:
-
-/* Line 1806 of yacc.c */
-#line 640 "parser.y"
- { (yyval.expr) = ExprCreateUnary(EXPR_UNARY_PLUS, (yyvsp[(2) - (2)].expr)->expr.value_type, (yyvsp[(2) - (2)].expr)); }
- break;
-
- case 145:
-
-/* Line 1806 of yacc.c */
-#line 642 "parser.y"
- { (yyval.expr) = ExprCreateUnary(EXPR_NOT, EXPR_TYPE_BOOLEAN, (yyvsp[(2) - (2)].expr)); }
- break;
-
- case 146:
-
-/* Line 1806 of yacc.c */
-#line 644 "parser.y"
- { (yyval.expr) = ExprCreateUnary(EXPR_INVERT, (yyvsp[(2) - (2)].expr)->expr.value_type, (yyvsp[(2) - (2)].expr)); }
- break;
-
- case 147:
-
-/* Line 1806 of yacc.c */
-#line 646 "parser.y"
- { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
- break;
-
- case 148:
-
-/* Line 1806 of yacc.c */
-#line 648 "parser.y"
- { (yyval.expr) = ExprCreateAction((yyvsp[(1) - (4)].sval), (yyvsp[(3) - (4)].expr)); }
- break;
-
- case 149:
-
-/* Line 1806 of yacc.c */
-#line 650 "parser.y"
- { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
- break;
-
- case 150:
-
-/* Line 1806 of yacc.c */
-#line 652 "parser.y"
- { (yyval.expr) = (yyvsp[(2) - (3)].expr); }
- break;
-
- case 151:
-
-/* Line 1806 of yacc.c */
-#line 656 "parser.y"
- { (yyval.expr) = (ExprDef *) AppendStmt((ParseCommon *) (yyvsp[(1) - (3)].expr),
- (ParseCommon *) (yyvsp[(3) - (3)].expr)); }
- break;
-
- case 152:
-
-/* Line 1806 of yacc.c */
-#line 659 "parser.y"
- { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
- break;
-
- case 153:
-
-/* Line 1806 of yacc.c */
-#line 663 "parser.y"
- { (yyval.expr) = ExprCreateAction((yyvsp[(1) - (4)].sval), (yyvsp[(3) - (4)].expr)); }
- break;
-
- case 154:
-
-/* Line 1806 of yacc.c */
-#line 667 "parser.y"
- { (yyval.expr) = ExprCreateIdent((yyvsp[(1) - (1)].sval)); }
- break;
-
- case 155:
-
-/* Line 1806 of yacc.c */
-#line 669 "parser.y"
- { (yyval.expr) = ExprCreateFieldRef((yyvsp[(1) - (3)].sval), (yyvsp[(3) - (3)].sval)); }
- break;
-
- case 156:
-
-/* Line 1806 of yacc.c */
-#line 671 "parser.y"
- { (yyval.expr) = ExprCreateArrayRef(XKB_ATOM_NONE, (yyvsp[(1) - (4)].sval), (yyvsp[(3) - (4)].expr)); }
- break;
-
- case 157:
-
-/* Line 1806 of yacc.c */
-#line 673 "parser.y"
- { (yyval.expr) = ExprCreateArrayRef((yyvsp[(1) - (6)].sval), (yyvsp[(3) - (6)].sval), (yyvsp[(5) - (6)].expr)); }
- break;
-
- case 158:
-
-/* Line 1806 of yacc.c */
-#line 677 "parser.y"
- { (yyval.expr) = ExprCreateString((yyvsp[(1) - (1)].sval)); }
- break;
-
- case 159:
-
-/* Line 1806 of yacc.c */
-#line 679 "parser.y"
- { (yyval.expr) = ExprCreateInteger((yyvsp[(1) - (1)].ival)); }
- break;
-
- case 160:
-
-/* Line 1806 of yacc.c */
-#line 681 "parser.y"
- { (yyval.expr) = NULL; }
- break;
-
- case 161:
-
-/* Line 1806 of yacc.c */
-#line 683 "parser.y"
- { (yyval.expr) = ExprCreateKeyName((yyvsp[(1) - (1)].sval)); }
- break;
-
- case 162:
-
-/* Line 1806 of yacc.c */
-#line 686 "parser.y"
- { (yyval.expr) = (yyvsp[(1) - (1)].expr); }
- break;
-
- case 163:
-
-/* Line 1806 of yacc.c */
-#line 687 "parser.y"
- { (yyval.expr) = NULL; }
- break;
-
- case 164:
-
-/* Line 1806 of yacc.c */
-#line 691 "parser.y"
- { (yyval.expr) = ExprAppendKeysymList((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].keysym)); }
- break;
-
- case 165:
-
-/* Line 1806 of yacc.c */
-#line 693 "parser.y"
- { (yyval.expr) = ExprAppendMultiKeysymList((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
- break;
-
- case 166:
-
-/* Line 1806 of yacc.c */
-#line 695 "parser.y"
- { (yyval.expr) = ExprCreateKeysymList((yyvsp[(1) - (1)].keysym)); }
- break;
-
- case 167:
-
-/* Line 1806 of yacc.c */
-#line 697 "parser.y"
- { (yyval.expr) = ExprCreateMultiKeysymList((yyvsp[(1) - (1)].expr)); }
- break;
-
- case 168:
-
-/* Line 1806 of yacc.c */
-#line 701 "parser.y"
- { (yyval.expr) = (yyvsp[(2) - (3)].expr); }
- break;
-
- case 169:
-
-/* Line 1806 of yacc.c */
-#line 705 "parser.y"
- {
- if (!resolve_keysym((yyvsp[(1) - (1)].str), &(yyval.keysym)))
- parser_warn(param, "unrecognized keysym");
- free((yyvsp[(1) - (1)].str));
- }
- break;
-
- case 170:
-
-/* Line 1806 of yacc.c */
-#line 710 "parser.y"
- { (yyval.keysym) = XKB_KEY_section; }
- break;
-
- case 171:
-
-/* Line 1806 of yacc.c */
-#line 712 "parser.y"
- {
- if ((yyvsp[(1) - (1)].ival) < 0) {
- parser_warn(param, "unrecognized keysym");
- (yyval.keysym) = XKB_KEY_NoSymbol;
- }
- else if ((yyvsp[(1) - (1)].ival) < 10) { /* XKB_KEY_0 .. XKB_KEY_9 */
- (yyval.keysym) = XKB_KEY_0 + (xkb_keysym_t) (yyvsp[(1) - (1)].ival);
- }
- else {
- char buf[17];
- snprintf(buf, sizeof(buf), "0x%x", (yyvsp[(1) - (1)].ival));
- if (!resolve_keysym(buf, &(yyval.keysym))) {
- parser_warn(param, "unrecognized keysym");
- (yyval.keysym) = XKB_KEY_NoSymbol;
- }
- }
- }
- break;
-
- case 172:
-
-/* Line 1806 of yacc.c */
-#line 731 "parser.y"
- { (yyval.ival) = -(yyvsp[(2) - (2)].ival); }
- break;
-
- case 173:
-
-/* Line 1806 of yacc.c */
-#line 732 "parser.y"
- { (yyval.ival) = (yyvsp[(1) - (1)].ival); }
- break;
-
- case 174:
-
-/* Line 1806 of yacc.c */
-#line 735 "parser.y"
- { (yyval.ival) = (yyvsp[(1) - (1)].num); }
- break;
-
- case 175:
-
-/* Line 1806 of yacc.c */
-#line 736 "parser.y"
- { (yyval.ival) = (yyvsp[(1) - (1)].num); }
- break;
-
- case 176:
-
-/* Line 1806 of yacc.c */
-#line 739 "parser.y"
- { (yyval.ival) = 0; }
- break;
-
- case 177:
-
-/* Line 1806 of yacc.c */
-#line 742 "parser.y"
- { (yyval.ival) = (yyvsp[(1) - (1)].num); }
- break;
-
- case 178:
-
-/* Line 1806 of yacc.c */
-#line 745 "parser.y"
- { (yyval.num) = (yyvsp[(1) - (1)].num); }
- break;
-
- case 179:
-
-/* Line 1806 of yacc.c */
-#line 748 "parser.y"
- { (yyval.sval) = xkb_atom_steal(param->ctx, (yyvsp[(1) - (1)].str)); }
- break;
-
- case 180:
-
-/* Line 1806 of yacc.c */
-#line 749 "parser.y"
- { (yyval.sval) = xkb_atom_intern_literal(param->ctx, "default"); }
- break;
-
- case 181:
-
-/* Line 1806 of yacc.c */
-#line 752 "parser.y"
- { (yyval.sval) = xkb_atom_steal(param->ctx, (yyvsp[(1) - (1)].str)); }
- break;
-
- case 182:
-
-/* Line 1806 of yacc.c */
-#line 755 "parser.y"
- { (yyval.str) = (yyvsp[(1) - (1)].str); }
- break;
-
- case 183:
-
-/* Line 1806 of yacc.c */
-#line 756 "parser.y"
- { (yyval.str) = NULL; }
- break;
-
- case 184:
-
-/* Line 1806 of yacc.c */
-#line 759 "parser.y"
- { (yyval.str) = (yyvsp[(1) - (1)].str); }
- break;
-
-
-
-/* Line 1806 of yacc.c */
-#line 3331 "src/xkbcomp/parser.c"
- default: break;
- }
- /* User semantic actions sometimes alter yychar, and that requires
- that yytoken be updated with the new translation. We take the
- approach of translating immediately before every use of yytoken.
- One alternative is translating here after every semantic action,
- but that translation would be missed if the semantic action invokes
- YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
- if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an
- incorrect destructor might then be invoked immediately. In the
- case of YYERROR or YYBACKUP, subsequent parser actions might lead
- to an incorrect destructor call or verbose syntax error message
- before the lookahead is translated. */
- YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
-
- YYPOPSTACK (yylen);
- yylen = 0;
- YY_STACK_PRINT (yyss, yyssp);
-
- *++yyvsp = yyval;
-
- /* Now `shift' the result of the reduction. Determine what state
- that goes to, based on the state we popped back to and the rule
- number reduced by. */
-
- yyn = yyr1[yyn];
-
- yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
- if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
- yystate = yytable[yystate];
- else
- yystate = yydefgoto[yyn - YYNTOKENS];
-
- goto yynewstate;
-
-
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
-yyerrlab:
- /* Make sure we have latest lookahead translation. See comments at
- user semantic actions for why this is necessary. */
- yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
-
- /* If not already recovering from an error, report this error. */
- if (!yyerrstatus)
- {
- ++yynerrs;
-#if ! YYERROR_VERBOSE
- yyerror (param, YY_("syntax error"));
-#else
-# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
- yyssp, yytoken)
- {
- char const *yymsgp = YY_("syntax error");
- int yysyntax_error_status;
- yysyntax_error_status = YYSYNTAX_ERROR;
- if (yysyntax_error_status == 0)
- yymsgp = yymsg;
- else if (yysyntax_error_status == 1)
- {
- if (yymsg != yymsgbuf)
- YYSTACK_FREE (yymsg);
- yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
- if (!yymsg)
- {
- yymsg = yymsgbuf;
- yymsg_alloc = sizeof yymsgbuf;
- yysyntax_error_status = 2;
- }
- else
- {
- yysyntax_error_status = YYSYNTAX_ERROR;
- yymsgp = yymsg;
- }
- }
- yyerror (param, yymsgp);
- if (yysyntax_error_status == 2)
- goto yyexhaustedlab;
- }
-# undef YYSYNTAX_ERROR
-#endif
- }
-
-
-
- if (yyerrstatus == 3)
- {
- /* If just tried and failed to reuse lookahead token after an
- error, discard it. */
-
- if (yychar <= YYEOF)
- {
- /* Return failure if at end of input. */
- if (yychar == YYEOF)
- YYABORT;
- }
- else
- {
- yydestruct ("Error: discarding",
- yytoken, &yylval, param);
- yychar = YYEMPTY;
- }
- }
-
- /* Else will try to reuse lookahead token after shifting the error
- token. */
- goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR. |
-`---------------------------------------------------*/
-yyerrorlab:
-
- /* Pacify compilers like GCC when the user code never invokes
- YYERROR and the label yyerrorlab therefore never appears in user
- code. */
- if (/*CONSTCOND*/ 0)
- goto yyerrorlab;
-
- /* Do not reclaim the symbols of the rule which action triggered
- this YYERROR. */
- YYPOPSTACK (yylen);
- yylen = 0;
- YY_STACK_PRINT (yyss, yyssp);
- yystate = *yyssp;
- goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR. |
-`-------------------------------------------------------------*/
-yyerrlab1:
- yyerrstatus = 3; /* Each real token shifted decrements this. */
-
- for (;;)
- {
- yyn = yypact[yystate];
- if (!yypact_value_is_default (yyn))
- {
- yyn += YYTERROR;
- if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
- {
- yyn = yytable[yyn];
- if (0 < yyn)
- break;
- }
- }
-
- /* Pop the current state because it cannot handle the error token. */
- if (yyssp == yyss)
- YYABORT;
-
-
- yydestruct ("Error: popping",
- yystos[yystate], yyvsp, param);
- YYPOPSTACK (1);
- yystate = *yyssp;
- YY_STACK_PRINT (yyss, yyssp);
- }
-
- *++yyvsp = yylval;
-
-
- /* Shift the error token. */
- YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
-
- yystate = yyn;
- goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here. |
-`-------------------------------------*/
-yyacceptlab:
- yyresult = 0;
- goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here. |
-`-----------------------------------*/
-yyabortlab:
- yyresult = 1;
- goto yyreturn;
-
-#if !defined(yyoverflow) || YYERROR_VERBOSE
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here. |
-`-------------------------------------------------*/
-yyexhaustedlab:
- yyerror (param, YY_("memory exhausted"));
- yyresult = 2;
- /* Fall through. */
-#endif
-
-yyreturn:
- if (yychar != YYEMPTY)
- {
- /* Make sure we have latest lookahead translation. See comments at
- user semantic actions for why this is necessary. */
- yytoken = YYTRANSLATE (yychar);
- yydestruct ("Cleanup: discarding lookahead",
- yytoken, &yylval, param);
- }
- /* Do not reclaim the symbols of the rule which action triggered
- this YYABORT or YYACCEPT. */
- YYPOPSTACK (yylen);
- YY_STACK_PRINT (yyss, yyssp);
- while (yyssp != yyss)
- {
- yydestruct ("Cleanup: popping",
- yystos[*yyssp], yyvsp, param);
- YYPOPSTACK (1);
- }
-#ifndef yyoverflow
- if (yyss != yyssa)
- YYSTACK_FREE (yyss);
-#endif
-#if YYERROR_VERBOSE
- if (yymsg != yymsgbuf)
- YYSTACK_FREE (yymsg);
-#endif
- /* Make sure YYID is used. */
- return YYID (yyresult);
-}
-
-
-
-/* Line 2067 of yacc.c */
-#line 762 "parser.y"
-
-
-XkbFile *
-parse(struct xkb_context *ctx, struct scanner *scanner, const char *map)
-{
- int ret;
- XkbFile *first = NULL;
- struct parser_param param = {
- .scanner = scanner,
- .ctx = ctx,
- };
-
- /*
- * If we got a specific map, we look for it exclusively and return
- * immediately upon finding it. Otherwise, we need to get the
- * default map. If we find a map marked as default, we return it
- * immediately. If there are no maps marked as default, we return
- * the first map in the file.
- */
-
- while ((ret = yyparse(&param)) == 0 && param.more_maps) {
- if (map) {
- if (streq_not_null(map, param.rtrn->name))
- return param.rtrn;
- else
- FreeXkbFile(param.rtrn);
- }
- else {
- if (param.rtrn->flags & MAP_IS_DEFAULT) {
- FreeXkbFile(first);
- return param.rtrn;
- }
- else if (!first) {
- first = param.rtrn;
- }
- else {
- FreeXkbFile(param.rtrn);
- }
- }
- }
-
- if (ret != 0) {
- FreeXkbFile(first);
- return NULL;
- }
-
- return first;
-}
-
diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/parser.h b/src/3rdparty/xkbcommon/src/xkbcomp/parser.h
index ee9b4468b5..655eca3133 100644
--- a/src/3rdparty/xkbcommon/src/xkbcomp/parser.h
+++ b/src/3rdparty/xkbcommon/src/xkbcomp/parser.h
@@ -1,19 +1,19 @@
-/* A Bison parser, made by GNU Bison 2.5. */
+/* A Bison parser, made by GNU Bison 3.0.4. */
/* Bison interface for Yacc-like parsers in C
-
- Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
-
+
+ Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
@@ -26,162 +26,103 @@
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
-
+
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
+#ifndef YY__XKBCOMMON_XKBCOMMON_INTERNAL_STA_PARSER_H_INCLUDED
+# define YY__XKBCOMMON_XKBCOMMON_INTERNAL_STA_PARSER_H_INCLUDED
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int _xkbcommon_debug;
+#endif
-/* Tokens. */
+/* Token type. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
- /* Put the tokens into the symbol table, so that GDB and other debuggers
- know about them. */
- enum yytokentype {
- END_OF_FILE = 0,
- ERROR_TOK = 255,
- XKB_KEYMAP = 1,
- XKB_KEYCODES = 2,
- XKB_TYPES = 3,
- XKB_SYMBOLS = 4,
- XKB_COMPATMAP = 5,
- XKB_GEOMETRY = 6,
- XKB_SEMANTICS = 7,
- XKB_LAYOUT = 8,
- INCLUDE = 10,
- OVERRIDE = 11,
- AUGMENT = 12,
- REPLACE = 13,
- ALTERNATE = 14,
- VIRTUAL_MODS = 20,
- TYPE = 21,
- INTERPRET = 22,
- ACTION_TOK = 23,
- KEY = 24,
- ALIAS = 25,
- GROUP = 26,
- MODIFIER_MAP = 27,
- INDICATOR = 28,
- SHAPE = 29,
- KEYS = 30,
- ROW = 31,
- SECTION = 32,
- OVERLAY = 33,
- TEXT = 34,
- OUTLINE = 35,
- SOLID = 36,
- LOGO = 37,
- VIRTUAL = 38,
- EQUALS = 40,
- PLUS = 41,
- MINUS = 42,
- DIVIDE = 43,
- TIMES = 44,
- OBRACE = 45,
- CBRACE = 46,
- OPAREN = 47,
- CPAREN = 48,
- OBRACKET = 49,
- CBRACKET = 50,
- DOT = 51,
- COMMA = 52,
- SEMI = 53,
- EXCLAM = 54,
- INVERT = 55,
- STRING = 60,
- INTEGER = 61,
- FLOAT = 62,
- IDENT = 63,
- KEYNAME = 64,
- PARTIAL = 70,
- DEFAULT = 71,
- HIDDEN = 72,
- ALPHANUMERIC_KEYS = 73,
- MODIFIER_KEYS = 74,
- KEYPAD_KEYS = 75,
- FUNCTION_KEYS = 76,
- ALTERNATE_GROUP = 77
- };
+ enum yytokentype
+ {
+ END_OF_FILE = 0,
+ ERROR_TOK = 255,
+ XKB_KEYMAP = 1,
+ XKB_KEYCODES = 2,
+ XKB_TYPES = 3,
+ XKB_SYMBOLS = 4,
+ XKB_COMPATMAP = 5,
+ XKB_GEOMETRY = 6,
+ XKB_SEMANTICS = 7,
+ XKB_LAYOUT = 8,
+ INCLUDE = 10,
+ OVERRIDE = 11,
+ AUGMENT = 12,
+ REPLACE = 13,
+ ALTERNATE = 14,
+ VIRTUAL_MODS = 20,
+ TYPE = 21,
+ INTERPRET = 22,
+ ACTION_TOK = 23,
+ KEY = 24,
+ ALIAS = 25,
+ GROUP = 26,
+ MODIFIER_MAP = 27,
+ INDICATOR = 28,
+ SHAPE = 29,
+ KEYS = 30,
+ ROW = 31,
+ SECTION = 32,
+ OVERLAY = 33,
+ TEXT = 34,
+ OUTLINE = 35,
+ SOLID = 36,
+ LOGO = 37,
+ VIRTUAL = 38,
+ EQUALS = 40,
+ PLUS = 41,
+ MINUS = 42,
+ DIVIDE = 43,
+ TIMES = 44,
+ OBRACE = 45,
+ CBRACE = 46,
+ OPAREN = 47,
+ CPAREN = 48,
+ OBRACKET = 49,
+ CBRACKET = 50,
+ DOT = 51,
+ COMMA = 52,
+ SEMI = 53,
+ EXCLAM = 54,
+ INVERT = 55,
+ STRING = 60,
+ INTEGER = 61,
+ FLOAT = 62,
+ IDENT = 63,
+ KEYNAME = 64,
+ PARTIAL = 70,
+ DEFAULT = 71,
+ HIDDEN = 72,
+ ALPHANUMERIC_KEYS = 73,
+ MODIFIER_KEYS = 74,
+ KEYPAD_KEYS = 75,
+ FUNCTION_KEYS = 76,
+ ALTERNATE_GROUP = 77
+ };
#endif
-/* Tokens. */
-#define END_OF_FILE 0
-#define ERROR_TOK 255
-#define XKB_KEYMAP 1
-#define XKB_KEYCODES 2
-#define XKB_TYPES 3
-#define XKB_SYMBOLS 4
-#define XKB_COMPATMAP 5
-#define XKB_GEOMETRY 6
-#define XKB_SEMANTICS 7
-#define XKB_LAYOUT 8
-#define INCLUDE 10
-#define OVERRIDE 11
-#define AUGMENT 12
-#define REPLACE 13
-#define ALTERNATE 14
-#define VIRTUAL_MODS 20
-#define TYPE 21
-#define INTERPRET 22
-#define ACTION_TOK 23
-#define KEY 24
-#define ALIAS 25
-#define GROUP 26
-#define MODIFIER_MAP 27
-#define INDICATOR 28
-#define SHAPE 29
-#define KEYS 30
-#define ROW 31
-#define SECTION 32
-#define OVERLAY 33
-#define TEXT 34
-#define OUTLINE 35
-#define SOLID 36
-#define LOGO 37
-#define VIRTUAL 38
-#define EQUALS 40
-#define PLUS 41
-#define MINUS 42
-#define DIVIDE 43
-#define TIMES 44
-#define OBRACE 45
-#define CBRACE 46
-#define OPAREN 47
-#define CPAREN 48
-#define OBRACKET 49
-#define CBRACKET 50
-#define DOT 51
-#define COMMA 52
-#define SEMI 53
-#define EXCLAM 54
-#define INVERT 55
-#define STRING 60
-#define INTEGER 61
-#define FLOAT 62
-#define IDENT 63
-#define KEYNAME 64
-#define PARTIAL 70
-#define DEFAULT 71
-#define HIDDEN 72
-#define ALPHANUMERIC_KEYS 73
-#define MODIFIER_KEYS 74
-#define KEYPAD_KEYS 75
-#define FUNCTION_KEYS 76
-#define ALTERNATE_GROUP 77
-
-
-
+/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-{
-/* Line 2068 of yacc.c */
-#line 161 "parser.y"
+union YYSTYPE
+{
+#line 162 "../src/xkbcomp/parser.y" /* yacc.c:1909 */
int ival;
int64_t num;
enum xkb_file_type file_type;
char *str;
- xkb_atom_t sval;
+ xkb_atom_t atom;
enum merge_mode merge;
enum xkb_map_flags mapFlags;
xkb_keysym_t keysym;
@@ -201,16 +142,16 @@ typedef union YYSTYPE
void *geom;
XkbFile *file;
+#line 146 "xkbcommon-internal@sta/parser.h" /* yacc.c:1909 */
+};
-
-/* Line 2068 of yacc.c */
-#line 208 "src/xkbcomp/parser.h"
-} YYSTYPE;
+typedef union YYSTYPE YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
#endif
+int _xkbcommon_parse (struct parser_param *param);
+#endif /* !YY__XKBCOMMON_XKBCOMMON_INTERNAL_STA_PARSER_H_INCLUDED */
diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/rules.c b/src/3rdparty/xkbcommon/src/xkbcomp/rules.c
index 61799e7059..2a364c8aed 100644
--- a/src/3rdparty/xkbcommon/src/xkbcomp/rules.c
+++ b/src/3rdparty/xkbcommon/src/xkbcomp/rules.c
@@ -85,7 +85,7 @@ skip_more_whitespace_and_comments:
/* Skip comments. */
if (lit(s, "//")) {
- while (!eof(s) && !eol(s)) next(s);
+ skip_to_eol(s);
}
/* New line. */
@@ -182,15 +182,23 @@ static const struct sval rules_kccgst_svals[_KCCGST_NUM_ENTRIES] = {
[KCCGST_GEOMETRY] = SVAL_LIT("geometry"),
};
+/* We use this to keep score whether an mlvo was matched or not; if not,
+ * we warn the user that his preference was ignored. */
+struct matched_sval {
+ struct sval sval;
+ bool matched;
+};
+typedef darray(struct matched_sval) darray_matched_sval;
+
/*
* A broken-down version of xkb_rule_names (without the rules,
* obviously).
*/
struct rule_names {
- struct sval model;
- darray_sval layouts;
- darray_sval variants;
- darray_sval options;
+ struct matched_sval model;
+ darray_matched_sval layouts;
+ darray_matched_sval variants;
+ darray_matched_sval options;
};
struct group {
@@ -253,10 +261,10 @@ strip_spaces(struct sval v)
return v;
}
-static darray_sval
-split_comma_separated_string(const char *s)
+static darray_matched_sval
+split_comma_separated_mlvo(const char *s)
{
- darray_sval arr = darray_new();
+ darray_matched_sval arr = darray_new();
/*
* Make sure the array returned by this function always includes at
@@ -264,15 +272,16 @@ split_comma_separated_string(const char *s)
*/
if (!s) {
- struct sval val = { NULL, 0 };
+ struct matched_sval val = { .sval = { NULL, 0 } };
darray_append(arr, val);
return arr;
}
while (true) {
- struct sval val = { s, 0 };
- while (*s != '\0' && *s != ',') { s++; val.len++; }
- darray_append(arr, strip_spaces(val));
+ struct matched_sval val = { .sval = { s, 0 } };
+ while (*s != '\0' && *s != ',') { s++; val.sval.len++; }
+ val.sval = strip_spaces(val.sval);
+ darray_append(arr, val);
if (*s == '\0') break;
if (*s == ',') s++;
}
@@ -289,11 +298,11 @@ matcher_new(struct xkb_context *ctx,
return NULL;
m->ctx = ctx;
- m->rmlvo.model.start = rmlvo->model;
- m->rmlvo.model.len = strlen_safe(rmlvo->model);
- m->rmlvo.layouts = split_comma_separated_string(rmlvo->layout);
- m->rmlvo.variants = split_comma_separated_string(rmlvo->variant);
- m->rmlvo.options = split_comma_separated_string(rmlvo->options);
+ m->rmlvo.model.sval.start = rmlvo->model;
+ m->rmlvo.model.sval.len = strlen_safe(rmlvo->model);
+ m->rmlvo.layouts = split_comma_separated_mlvo(rmlvo->layout);
+ m->rmlvo.variants = split_comma_separated_mlvo(rmlvo->variant);
+ m->rmlvo.options = split_comma_separated_mlvo(rmlvo->options);
return m;
}
@@ -309,6 +318,8 @@ matcher_free(struct matcher *m)
darray_free(m->rmlvo.options);
darray_foreach(group, m->groups)
darray_free(group->elements);
+ for (int i = 0; i < _KCCGST_NUM_ENTRIES; i++)
+ darray_free(m->kccgst[i]);
darray_free(m->groups);
free(m);
}
@@ -584,7 +595,7 @@ match_group(struct matcher *m, struct sval group_name, struct sval to)
static bool
match_value(struct matcher *m, struct sval val, struct sval to,
- enum mlvo_match_type match_type)
+ enum mlvo_match_type match_type)
{
if (match_type == MLVO_MATCH_WILDCARD)
return true;
@@ -593,6 +604,16 @@ match_value(struct matcher *m, struct sval val, struct sval to,
return svaleq(val, to);
}
+static bool
+match_value_and_mark(struct matcher *m, struct sval val,
+ struct matched_sval *to, enum mlvo_match_type match_type)
+{
+ bool matched = match_value(m, val, to->sval, match_type);
+ if (matched)
+ to->matched = true;
+ return matched;
+}
+
/*
* This function performs %-expansion on @value (see overview above),
* and appends the result to @to.
@@ -614,7 +635,7 @@ append_expanded_kccgst_value(struct matcher *m, darray_char *to,
enum rules_mlvo mlv;
xkb_layout_index_t idx;
char pfx, sfx;
- struct sval expanded_value;
+ struct matched_sval *expanded_value;
/* Check if that's a start of an expansion. */
if (s[i] != '%') {
@@ -664,40 +685,42 @@ append_expanded_kccgst_value(struct matcher *m, darray_char *to,
}
/* Get the expanded value. */
- expanded_value.len = 0;
+ expanded_value = NULL;
if (mlv == MLVO_LAYOUT) {
if (idx != XKB_LAYOUT_INVALID &&
idx < darray_size(m->rmlvo.layouts) &&
darray_size(m->rmlvo.layouts) > 1)
- expanded_value = darray_item(m->rmlvo.layouts, idx);
+ expanded_value = &darray_item(m->rmlvo.layouts, idx);
else if (idx == XKB_LAYOUT_INVALID &&
darray_size(m->rmlvo.layouts) == 1)
- expanded_value = darray_item(m->rmlvo.layouts, 0);
+ expanded_value = &darray_item(m->rmlvo.layouts, 0);
}
else if (mlv == MLVO_VARIANT) {
if (idx != XKB_LAYOUT_INVALID &&
idx < darray_size(m->rmlvo.variants) &&
darray_size(m->rmlvo.variants) > 1)
- expanded_value = darray_item(m->rmlvo.variants, idx);
+ expanded_value = &darray_item(m->rmlvo.variants, idx);
else if (idx == XKB_LAYOUT_INVALID &&
darray_size(m->rmlvo.variants) == 1)
- expanded_value = darray_item(m->rmlvo.variants, 0);
+ expanded_value = &darray_item(m->rmlvo.variants, 0);
}
else if (mlv == MLVO_MODEL) {
- expanded_value = m->rmlvo.model;
+ expanded_value = &m->rmlvo.model;
}
/* If we didn't get one, skip silently. */
- if (expanded_value.len <= 0)
+ if (!expanded_value || expanded_value->sval.len == 0)
continue;
if (pfx != 0)
darray_appends_nullterminate(expanded, &pfx, 1);
darray_appends_nullterminate(expanded,
- expanded_value.start, expanded_value.len);
+ expanded_value->sval.start,
+ expanded_value->sval.len);
if (sfx != 0)
darray_appends_nullterminate(expanded, &sfx, 1);
+ expanded_value->matched = true;
}
/*
@@ -743,29 +766,28 @@ matcher_rule_apply_if_matches(struct matcher *m)
enum rules_mlvo mlvo = m->mapping.mlvo_at_pos[i];
struct sval value = m->rule.mlvo_value_at_pos[i];
enum mlvo_match_type match_type = m->rule.match_type_at_pos[i];
+ struct matched_sval *to;
bool matched = false;
if (mlvo == MLVO_MODEL) {
- matched = match_value(m, value, m->rmlvo.model, match_type);
+ to = &m->rmlvo.model;
+ matched = match_value_and_mark(m, value, to, match_type);
}
else if (mlvo == MLVO_LAYOUT) {
xkb_layout_index_t idx = m->mapping.layout_idx;
idx = (idx == XKB_LAYOUT_INVALID ? 0 : idx);
- matched = match_value(m, value,
- darray_item(m->rmlvo.layouts, idx),
- match_type);
+ to = &darray_item(m->rmlvo.layouts, idx);
+ matched = match_value_and_mark(m, value, to, match_type);
}
else if (mlvo == MLVO_VARIANT) {
xkb_layout_index_t idx = m->mapping.layout_idx;
idx = (idx == XKB_LAYOUT_INVALID ? 0 : idx);
- matched = match_value(m, value,
- darray_item(m->rmlvo.variants, idx),
- match_type);
+ to = &darray_item(m->rmlvo.variants, idx);
+ matched = match_value_and_mark(m, value, to, match_type);
}
else if (mlvo == MLVO_OPTION) {
- struct sval *option;
- darray_foreach(option, m->rmlvo.options) {
- matched = match_value(m, value, *option, match_type);
+ darray_foreach(to, m->rmlvo.options) {
+ matched = match_value_and_mark(m, value, to, match_type);
if (matched)
break;
}
@@ -801,11 +823,12 @@ matcher_match(struct matcher *m, const char *string, size_t len,
const char *file_name, struct xkb_component_names *out)
{
enum rules_token tok;
+ struct matched_sval *mval;
if (!m)
return false;
- scanner_init(&m->scanner, m->ctx, string, len, file_name);
+ scanner_init(&m->scanner, m->ctx, string, len, file_name, NULL);
initial:
switch (tok = gettok(m)) {
@@ -944,12 +967,29 @@ finish:
darray_empty(m->kccgst[KCCGST_SYMBOLS]))
goto error;
- out->keycodes = darray_mem(m->kccgst[KCCGST_KEYCODES], 0);
- out->types = darray_mem(m->kccgst[KCCGST_TYPES], 0);
- out->compat = darray_mem(m->kccgst[KCCGST_COMPAT], 0);
- /* out->geometry = darray_mem(m->kccgst[KCCGST_GEOMETRY], 0); */
+ darray_steal(m->kccgst[KCCGST_KEYCODES], &out->keycodes, NULL);
+ darray_steal(m->kccgst[KCCGST_TYPES], &out->types, NULL);
+ darray_steal(m->kccgst[KCCGST_COMPAT], &out->compat, NULL);
+ darray_steal(m->kccgst[KCCGST_SYMBOLS], &out->symbols, NULL);
darray_free(m->kccgst[KCCGST_GEOMETRY]);
- out->symbols = darray_mem(m->kccgst[KCCGST_SYMBOLS], 0);
+
+
+ mval = &m->rmlvo.model;
+ if (!mval->matched && mval->sval.len > 0)
+ log_err(m->ctx, "Unrecognized RMLVO model \"%.*s\" was ignored\n",
+ mval->sval.len, mval->sval.start);
+ darray_foreach(mval, m->rmlvo.layouts)
+ if (!mval->matched && mval->sval.len > 0)
+ log_err(m->ctx, "Unrecognized RMLVO layout \"%.*s\" was ignored\n",
+ mval->sval.len, mval->sval.start);
+ darray_foreach(mval, m->rmlvo.variants)
+ if (!mval->matched && mval->sval.len > 0)
+ log_err(m->ctx, "Unrecognized RMLVO variant \"%.*s\" was ignored\n",
+ mval->sval.len, mval->sval.start);
+ darray_foreach(mval, m->rmlvo.options)
+ if (!mval->matched && mval->sval.len > 0)
+ log_err(m->ctx, "Unrecognized RMLVO option \"%.*s\" was ignored\n",
+ mval->sval.len, mval->sval.start);
return true;
@@ -967,7 +1007,7 @@ xkb_components_from_rules(struct xkb_context *ctx,
bool ret = false;
FILE *file;
char *path;
- const char *string;
+ char *string;
size_t size;
struct matcher *matcher;
diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/scanner.c b/src/3rdparty/xkbcommon/src/xkbcomp/scanner.c
index 9f200bbec4..1ce6137bf3 100644
--- a/src/3rdparty/xkbcommon/src/xkbcomp/scanner.c
+++ b/src/3rdparty/xkbcommon/src/xkbcomp/scanner.c
@@ -23,6 +23,7 @@
#include "xkbcomp-priv.h"
#include "parser-priv.h"
+#include "scanner-utils.h"
static bool
number(struct scanner *s, int64_t *out, int *out_tok)
@@ -68,7 +69,7 @@ skip_more_whitespace_and_comments:
/* Skip comments. */
if (lit(s, "//") || chr(s, '#')) {
- while (!eof(s) && !eol(s)) next(s);
+ skip_to_eol(s);
goto skip_more_whitespace_and_comments;
}
@@ -121,7 +122,7 @@ skip_more_whitespace_and_comments:
return ERROR_TOK;
}
/* Empty key name literals are allowed. */
- yylval->sval = xkb_atom_intern(s->ctx, s->buf, s->buf_pos - 1);
+ yylval->atom = xkb_atom_intern(s->ctx, s->buf, s->buf_pos - 1);
return KEYNAME;
}
@@ -181,7 +182,7 @@ XkbParseString(struct xkb_context *ctx, const char *string, size_t len,
const char *file_name, const char *map)
{
struct scanner scanner;
- scanner_init(&scanner, ctx, string, len, file_name);
+ scanner_init(&scanner, ctx, string, len, file_name, NULL);
return parse(ctx, &scanner, map);
}
@@ -191,7 +192,7 @@ XkbParseFile(struct xkb_context *ctx, FILE *file,
{
bool ok;
XkbFile *xkb_file;
- const char *string;
+ char *string;
size_t size;
ok = map_file(file, &string, &size);
diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/symbols.c b/src/3rdparty/xkbcommon/src/xkbcomp/symbols.c
index bd7f73d4f1..9b05ec924f 100644
--- a/src/3rdparty/xkbcommon/src/xkbcomp/symbols.c
+++ b/src/3rdparty/xkbcommon/src/xkbcomp/symbols.c
@@ -72,10 +72,10 @@ enum group_field {
};
enum key_field {
- KEY_FIELD_REPEAT = (1 << 0),
+ KEY_FIELD_REPEAT = (1 << 0),
KEY_FIELD_DEFAULT_TYPE = (1 << 1),
KEY_FIELD_GROUPINFO = (1 << 2),
- KEY_FIELD_VMODMAP = (1 << 3),
+ KEY_FIELD_VMODMAP = (1 << 3),
};
typedef struct {
@@ -177,19 +177,24 @@ typedef struct {
ActionsInfo *actions;
darray(xkb_atom_t) group_names;
darray(ModMapEntry) modmaps;
+ struct xkb_mod_set mods;
- struct xkb_keymap *keymap;
+ struct xkb_context *ctx;
+ /* Needed for AddKeySymbols. */
+ const struct xkb_keymap *keymap;
} SymbolsInfo;
static void
-InitSymbolsInfo(SymbolsInfo *info, struct xkb_keymap *keymap,
- ActionsInfo *actions)
+InitSymbolsInfo(SymbolsInfo *info, const struct xkb_keymap *keymap,
+ ActionsInfo *actions, const struct xkb_mod_set *mods)
{
memset(info, 0, sizeof(*info));
+ info->ctx = keymap->ctx;
info->keymap = keymap;
info->merge = MERGE_OVERRIDE;
InitKeyInfo(keymap->ctx, &info->default_key);
info->actions = actions;
+ info->mods = *mods;
info->explicit_group = XKB_LAYOUT_INVALID;
}
@@ -209,7 +214,7 @@ ClearSymbolsInfo(SymbolsInfo *info)
static const char *
KeyInfoText(SymbolsInfo *info, KeyInfo *keyi)
{
- return KeyNameText(info->keymap->ctx, keyi->name);
+ return KeyNameText(info->ctx, keyi->name);
}
static bool
@@ -217,7 +222,7 @@ MergeGroups(SymbolsInfo *info, GroupInfo *into, GroupInfo *from, bool clobber,
bool report, xkb_layout_index_t group, xkb_atom_t key_name)
{
xkb_level_index_t i, levels_in_both;
- struct xkb_context *ctx = info->keymap->ctx;
+ struct xkb_level *level;
/* First find the type of the merged group. */
if (into->type != from->type) {
@@ -231,11 +236,12 @@ MergeGroups(SymbolsInfo *info, GroupInfo *into, GroupInfo *from, bool clobber,
xkb_atom_t ignore = (clobber ? into->type : from->type);
if (report)
- log_warn(info->keymap->ctx,
+ log_warn(info->ctx,
"Multiple definitions for group %d type of key %s; "
"Using %s, ignoring %s\n",
- group + 1, KeyNameText(ctx, key_name),
- xkb_atom_text(ctx, use), xkb_atom_text(ctx, ignore));
+ group + 1, KeyNameText(info->ctx, key_name),
+ xkb_atom_text(info->ctx, use),
+ xkb_atom_text(info->ctx, ignore));
into->type = use;
}
@@ -273,10 +279,10 @@ MergeGroups(SymbolsInfo *info, GroupInfo *into, GroupInfo *from, bool clobber,
ignore = (clobber ? &intoLevel->action : &fromLevel->action);
if (report)
- log_warn(ctx,
+ log_warn(info->ctx,
"Multiple actions for level %d/group %u on key %s; "
"Using %s, ignoring %s\n",
- i + 1, group + 1, KeyNameText(ctx, key_name),
+ i + 1, group + 1, KeyNameText(info->ctx, key_name),
ActionTypeText(use->type),
ActionTypeText(ignore->type));
@@ -293,12 +299,12 @@ MergeGroups(SymbolsInfo *info, GroupInfo *into, GroupInfo *from, bool clobber,
intoLevel->u.sym = fromLevel->u.sym;
fromLevel->num_syms = 0;
}
- else {
+ else if (!XkbLevelsSameSyms(fromLevel, intoLevel)) {
if (report)
- log_warn(ctx,
+ log_warn(info->ctx,
"Multiple symbols for level %d/group %u on key %s; "
"Using %s, ignoring %s\n",
- i + 1, group + 1, KeyNameText(ctx, key_name),
+ i + 1, group + 1, KeyNameText(info->ctx, key_name),
(clobber ? "from" : "to"),
(clobber ? "to" : "from"));
@@ -314,9 +320,9 @@ MergeGroups(SymbolsInfo *info, GroupInfo *into, GroupInfo *from, bool clobber,
}
}
/* If @from has extra levels, get them as well. */
- for (i = levels_in_both; i < darray_size(from->levels); i++) {
- darray_append(into->levels, darray_item(from->levels, i));
- darray_item(from->levels, i).num_syms = 0;
+ darray_foreach_from(level, from->levels, levels_in_both) {
+ darray_append(into->levels, *level);
+ level->num_syms = 0;
}
into->defined |= (from->defined & GROUP_FIELD_ACTS);
into->defined |= (from->defined & GROUP_FIELD_SYMS);
@@ -348,14 +354,14 @@ MergeKeys(SymbolsInfo *info, KeyInfo *into, KeyInfo *from, bool same_file)
xkb_layout_index_t i;
xkb_layout_index_t groups_in_both;
enum key_field collide = 0;
- const int verbosity = xkb_context_get_log_verbosity(info->keymap->ctx);
+ const int verbosity = xkb_context_get_log_verbosity(info->ctx);
const bool clobber = (from->merge != MERGE_AUGMENT);
const bool report = (same_file && verbosity > 0) || verbosity > 9;
if (from->merge == MERGE_REPLACE) {
ClearKeyInfo(into);
*into = *from;
- InitKeyInfo(info->keymap->ctx, from);
+ InitKeyInfo(info->ctx, from);
return true;
}
@@ -394,17 +400,18 @@ MergeKeys(SymbolsInfo *info, KeyInfo *into, KeyInfo *from, bool same_file)
}
if (collide)
- log_warn(info->keymap->ctx,
+ log_warn(info->ctx,
"Symbol map for key %s redefined; "
"Using %s definition for conflicting fields\n",
- KeyNameText(info->keymap->ctx, into->name),
+ KeyNameText(info->ctx, into->name),
(clobber ? "first" : "last"));
ClearKeyInfo(from);
- InitKeyInfo(info->keymap->ctx, from);
+ InitKeyInfo(info->ctx, from);
return true;
}
+/* TODO: Make it so this function doesn't need the entire keymap. */
static bool
AddKeySymbols(SymbolsInfo *info, KeyInfo *keyi, bool same_file)
{
@@ -426,7 +433,7 @@ AddKeySymbols(SymbolsInfo *info, KeyInfo *keyi, bool same_file)
return MergeKeys(info, iter, keyi, same_file);
darray_append(info->keys, *keyi);
- InitKeyInfo(info->keymap->ctx, keyi);
+ InitKeyInfo(info->ctx, keyi);
return true;
}
@@ -451,19 +458,19 @@ AddModMapEntry(SymbolsInfo *info, ModMapEntry *new)
ignore = (clobber ? old->modifier : new->modifier);
if (new->haveSymbol)
- log_err(info->keymap->ctx,
+ log_err(info->ctx,
"Symbol \"%s\" added to modifier map for multiple modifiers; "
"Using %s, ignoring %s\n",
- KeysymText(info->keymap->ctx, new->u.keySym),
- ModIndexText(info->keymap, use),
- ModIndexText(info->keymap, ignore));
+ KeysymText(info->ctx, new->u.keySym),
+ ModIndexText(info->ctx, &info->mods, use),
+ ModIndexText(info->ctx, &info->mods, ignore));
else
- log_err(info->keymap->ctx,
+ log_err(info->ctx,
"Key \"%s\" added to modifier map for multiple modifiers; "
"Using %s, ignoring %s\n",
- KeyNameText(info->keymap->ctx, new->u.keyName),
- ModIndexText(info->keymap, use),
- ModIndexText(info->keymap, ignore));
+ KeyNameText(info->ctx, new->u.keyName),
+ ModIndexText(info->ctx, &info->mods, use),
+ ModIndexText(info->ctx, &info->mods, ignore));
old->modifier = use;
return true;
@@ -479,8 +486,6 @@ static void
MergeIncludedSymbols(SymbolsInfo *into, SymbolsInfo *from,
enum merge_mode merge)
{
- KeyInfo *keyi;
- ModMapEntry *mm;
xkb_atom_t *group_name;
xkb_layout_index_t group_names_in_both;
@@ -489,6 +494,8 @@ MergeIncludedSymbols(SymbolsInfo *into, SymbolsInfo *from,
return;
}
+ into->mods = from->mods;
+
if (into->name == NULL) {
into->name = from->name;
from->name = NULL;
@@ -514,6 +521,7 @@ MergeIncludedSymbols(SymbolsInfo *into, SymbolsInfo *from,
darray_init(from->keys);
}
else {
+ KeyInfo *keyi;
darray_foreach(keyi, from->keys) {
keyi->merge = (merge == MERGE_DEFAULT ? keyi->merge : merge);
if (!AddKeySymbols(into, keyi, false))
@@ -526,6 +534,7 @@ MergeIncludedSymbols(SymbolsInfo *into, SymbolsInfo *from,
darray_init(from->modmaps);
}
else {
+ ModMapEntry *mm;
darray_foreach(mm, from->modmaps) {
mm->merge = (merge == MERGE_DEFAULT ? mm->merge : merge);
if (!AddModMapEntry(into, mm))
@@ -542,7 +551,7 @@ HandleIncludeSymbols(SymbolsInfo *info, IncludeStmt *include)
{
SymbolsInfo included;
- InitSymbolsInfo(&included, info->keymap, info->actions);
+ InitSymbolsInfo(&included, info->keymap, info->actions, &info->mods);
included.name = include->stmt;
include->stmt = NULL;
@@ -550,18 +559,19 @@ HandleIncludeSymbols(SymbolsInfo *info, IncludeStmt *include)
SymbolsInfo next_incl;
XkbFile *file;
- file = ProcessIncludeFile(info->keymap->ctx, stmt, FILE_TYPE_SYMBOLS);
+ file = ProcessIncludeFile(info->ctx, stmt, FILE_TYPE_SYMBOLS);
if (!file) {
info->errorCount += 10;
ClearSymbolsInfo(&included);
return false;
}
- InitSymbolsInfo(&next_incl, info->keymap, info->actions);
+ InitSymbolsInfo(&next_incl, info->keymap, info->actions,
+ &included.mods);
if (stmt->modifier) {
next_incl.explicit_group = atoi(stmt->modifier) - 1;
if (next_incl.explicit_group >= XKB_MAX_GROUPS) {
- log_err(info->keymap->ctx,
+ log_err(info->ctx,
"Cannot set explicit group to %d - must be between 1..%d; "
"Ignoring group number\n",
next_incl.explicit_group + 1, XKB_MAX_GROUPS);
@@ -609,7 +619,7 @@ GetGroupIndex(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
}
if (i >= XKB_MAX_GROUPS) {
- log_err(info->keymap->ctx,
+ log_err(info->ctx,
"Too many groups of %s for key %s (max %u); "
"Ignoring %s defined for extra groups\n",
name, KeyInfoText(info, keyi), XKB_MAX_GROUPS, name);
@@ -621,8 +631,8 @@ GetGroupIndex(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
return true;
}
- if (!ExprResolveGroup(info->keymap->ctx, arrayNdx, ndx_rtrn)) {
- log_err(info->keymap->ctx,
+ if (!ExprResolveGroup(info->ctx, arrayNdx, ndx_rtrn)) {
+ log_err(info->ctx,
"Illegal group index for %s of key %s\n"
"Definition with non-integer array index ignored\n",
name, KeyInfoText(info, keyi));
@@ -655,7 +665,7 @@ AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
}
if (value->expr.op != EXPR_KEYSYM_LIST) {
- log_err(info->keymap->ctx,
+ log_err(info->ctx,
"Expected a list of symbols, found %s; "
"Ignoring symbols for group %u of %s\n",
expr_op_type_to_string(value->expr.op), ndx + 1,
@@ -664,7 +674,7 @@ AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
}
if (groupi->defined & GROUP_FIELD_SYMS) {
- log_err(info->keymap->ctx,
+ log_err(info->ctx,
"Symbols for key %s, group %u already defined; "
"Ignoring duplicate definition\n",
KeyInfoText(info, keyi), ndx + 1);
@@ -725,7 +735,7 @@ AddActionsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
}
if (value->expr.op != EXPR_ACTION_LIST) {
- log_wsgo(info->keymap->ctx,
+ log_wsgo(info->ctx,
"Bad expression type (%d) for action list value; "
"Ignoring actions for group %u of %s\n",
value->expr.op, ndx, KeyInfoText(info, keyi));
@@ -733,7 +743,7 @@ AddActionsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
}
if (groupi->defined & GROUP_FIELD_ACTS) {
- log_wsgo(info->keymap->ctx,
+ log_wsgo(info->ctx,
"Actions for key %s, group %u already defined\n",
KeyInfoText(info, keyi), ndx);
return false;
@@ -752,8 +762,8 @@ AddActionsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx,
for (unsigned i = 0; i < nActs; i++) {
union xkb_action *toAct = &darray_item(groupi->levels, i).action;
- if (!HandleActionDef(act, info->keymap, toAct, info->actions))
- log_err(info->keymap->ctx,
+ if (!HandleActionDef(info->ctx, info->actions, &info->mods, act, toAct))
+ log_err(info->ctx,
"Illegal action definition for %s; "
"Action for group %u/level %u ignored\n",
KeyInfoText(info, keyi), ndx + 1, i + 1);
@@ -779,14 +789,12 @@ static bool
SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
ExprDef *arrayNdx, ExprDef *value)
{
- struct xkb_context *ctx = info->keymap->ctx;
-
if (istreq(field, "type")) {
xkb_layout_index_t ndx;
xkb_atom_t val;
- if (!ExprResolveString(ctx, value, &val)) {
- log_err(ctx,
+ if (!ExprResolveString(info->ctx, value, &val)) {
+ log_err(info->ctx,
"The type field of a key symbol map must be a string; "
"Ignoring illegal type definition\n");
return false;
@@ -796,8 +804,8 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
keyi->default_type = val;
keyi->defined |= KEY_FIELD_DEFAULT_TYPE;
}
- else if (!ExprResolveGroup(ctx, arrayNdx, &ndx)) {
- log_err(ctx,
+ else if (!ExprResolveGroup(info->ctx, arrayNdx, &ndx)) {
+ log_err(info->ctx,
"Illegal group index for type of key %s; "
"Definition with non-integer array index ignored\n",
KeyInfoText(info, keyi));
@@ -822,8 +830,9 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
istreq(field, "virtualmodifiers")) {
xkb_mod_mask_t mask;
- if (!ExprResolveModMask(info->keymap, value, MOD_VIRT, &mask)) {
- log_err(ctx,
+ if (!ExprResolveModMask(info->ctx, value, MOD_VIRT, &info->mods,
+ &mask)) {
+ log_err(info->ctx,
"Expected a virtual modifier mask, found %s; "
"Ignoring virtual modifiers definition for key %s\n",
expr_op_type_to_string(value->expr.op),
@@ -837,7 +846,7 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
else if (istreq(field, "locking") ||
istreq(field, "lock") ||
istreq(field, "locks")) {
- log_vrb(ctx, 1,
+ log_vrb(info->ctx, 1,
"Key behaviors not supported; "
"Ignoring locking specification for key %s\n",
KeyInfoText(info, keyi));
@@ -845,14 +854,14 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
else if (istreq(field, "radiogroup") ||
istreq(field, "permanentradiogroup") ||
istreq(field, "allownone")) {
- log_vrb(ctx, 1,
+ log_vrb(info->ctx, 1,
"Radio groups not supported; "
"Ignoring radio group specification for key %s\n",
KeyInfoText(info, keyi));
}
else if (istreq_prefix("overlay", field) ||
istreq_prefix("permanentoverlay", field)) {
- log_vrb(ctx, 1,
+ log_vrb(info->ctx, 1,
"Overlays not supported; "
"Ignoring overlay specification for key %s\n",
KeyInfoText(info, keyi));
@@ -862,8 +871,8 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
istreq(field, "repeat")) {
unsigned int val;
- if (!ExprResolveEnum(ctx, value, &val, repeatEntries)) {
- log_err(ctx,
+ if (!ExprResolveEnum(info->ctx, value, &val, repeatEntries)) {
+ log_err(info->ctx,
"Illegal repeat setting for %s; "
"Non-boolean repeat setting ignored\n",
KeyInfoText(info, keyi));
@@ -877,8 +886,8 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
istreq(field, "wrapgroups")) {
bool set;
- if (!ExprResolveBoolean(ctx, value, &set)) {
- log_err(ctx,
+ if (!ExprResolveBoolean(info->ctx, value, &set)) {
+ log_err(info->ctx,
"Illegal groupsWrap setting for %s; "
"Non-boolean value ignored\n",
KeyInfoText(info, keyi));
@@ -892,8 +901,8 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
istreq(field, "clampgroups")) {
bool set;
- if (!ExprResolveBoolean(ctx, value, &set)) {
- log_err(ctx,
+ if (!ExprResolveBoolean(info->ctx, value, &set)) {
+ log_err(info->ctx,
"Illegal groupsClamp setting for %s; "
"Non-boolean value ignored\n",
KeyInfoText(info, keyi));
@@ -907,8 +916,8 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
istreq(field, "redirectgroups")) {
xkb_layout_index_t grp;
- if (!ExprResolveGroup(ctx, value, &grp)) {
- log_err(ctx,
+ if (!ExprResolveGroup(info->ctx, value, &grp)) {
+ log_err(info->ctx,
"Illegal group index for redirect of key %s; "
"Definition with non-integer group ignored\n",
KeyInfoText(info, keyi));
@@ -920,7 +929,7 @@ SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field,
keyi->defined |= KEY_FIELD_GROUPINFO;
}
else {
- log_err(ctx,
+ log_err(info->ctx,
"Unknown field %s in a symbol interpretation; "
"Definition ignored\n",
field);
@@ -937,21 +946,21 @@ SetGroupName(SymbolsInfo *info, ExprDef *arrayNdx, ExprDef *value)
xkb_atom_t name;
if (!arrayNdx) {
- log_vrb(info->keymap->ctx, 1,
+ log_vrb(info->ctx, 1,
"You must specify an index when specifying a group name; "
"Group name definition without array subscript ignored\n");
return false;
}
- if (!ExprResolveGroup(info->keymap->ctx, arrayNdx, &group)) {
- log_err(info->keymap->ctx,
+ if (!ExprResolveGroup(info->ctx, arrayNdx, &group)) {
+ log_err(info->ctx,
"Illegal index in group name definition; "
"Definition with non-integer array index ignored\n");
return false;
}
- if (!ExprResolveString(info->keymap->ctx, value, &name)) {
- log_err(info->keymap->ctx,
+ if (!ExprResolveString(info->ctx, value, &name)) {
+ log_err(info->ctx,
"Group name must be a string; "
"Illegal name for group %d ignored\n", group);
return false;
@@ -964,12 +973,12 @@ SetGroupName(SymbolsInfo *info, ExprDef *arrayNdx, ExprDef *value)
group_to_use = info->explicit_group;
}
else {
- log_warn(info->keymap->ctx,
+ log_warn(info->ctx,
"An explicit group was specified for the '%s' map, "
"but it provides a name for a group other than Group1 (%d); "
"Ignoring group name '%s'\n",
info->name, group,
- xkb_atom_text(info->keymap->ctx, name));
+ xkb_atom_text(info->ctx, name));
return false;
}
@@ -987,7 +996,7 @@ HandleGlobalVar(SymbolsInfo *info, VarDef *stmt)
ExprDef *arrayNdx;
bool ret;
- if (!ExprResolveLhs(info->keymap->ctx, stmt->name, &elem, &field, &arrayNdx))
+ if (!ExprResolveLhs(info->ctx, stmt->name, &elem, &field, &arrayNdx))
return false;
if (elem && istreq(elem, "key")) {
@@ -1000,31 +1009,31 @@ HandleGlobalVar(SymbolsInfo *info, VarDef *stmt)
}
else if (!elem && (istreq(field, "groupswrap") ||
istreq(field, "wrapgroups"))) {
- log_err(info->keymap->ctx,
+ log_err(info->ctx,
"Global \"groupswrap\" not supported; Ignored\n");
ret = true;
}
else if (!elem && (istreq(field, "groupsclamp") ||
istreq(field, "clampgroups"))) {
- log_err(info->keymap->ctx,
+ log_err(info->ctx,
"Global \"groupsclamp\" not supported; Ignored\n");
ret = true;
}
else if (!elem && (istreq(field, "groupsredirect") ||
istreq(field, "redirectgroups"))) {
- log_err(info->keymap->ctx,
+ log_err(info->ctx,
"Global \"groupsredirect\" not supported; Ignored\n");
ret = true;
}
else if (!elem && istreq(field, "allownone")) {
- log_err(info->keymap->ctx,
+ log_err(info->ctx,
"Radio groups not supported; "
"Ignoring \"allownone\" specification\n");
ret = true;
}
else {
- ret = SetActionField(info->keymap, elem, field, arrayNdx, stmt->value,
- info->actions);
+ ret = SetActionField(info->ctx, info->actions, &info->mods,
+ elem, field, arrayNdx, stmt->value);
}
return ret;
@@ -1039,7 +1048,7 @@ HandleSymbolsBody(SymbolsInfo *info, VarDef *def, KeyInfo *keyi)
for (; def; def = (VarDef *) def->common.next) {
if (def->name && def->name->expr.op == EXPR_FIELD_REF) {
- log_err(info->keymap->ctx,
+ log_err(info->ctx,
"Cannot set a global default value from within a key statement; "
"Move statements to the global file scope\n");
continue;
@@ -1053,7 +1062,7 @@ HandleSymbolsBody(SymbolsInfo *info, VarDef *def, KeyInfo *keyi)
arrayNdx = NULL;
}
else {
- ok = ExprResolveLhs(info->keymap->ctx, def->name, &elem, &field,
+ ok = ExprResolveLhs(info->ctx, def->name, &elem, &field,
&arrayNdx);
}
@@ -1083,7 +1092,7 @@ SetExplicitGroup(SymbolsInfo *info, KeyInfo *keyi)
}
if (warn)
- log_warn(info->keymap->ctx,
+ log_warn(info->ctx,
"For the map %s an explicit group specified, "
"but key %s has more than one group defined; "
"All groups except first one will be ignored\n",
@@ -1137,11 +1146,11 @@ HandleModMapDef(SymbolsInfo *info, ModMapDef *def)
ModMapEntry tmp;
xkb_mod_index_t ndx;
bool ok;
- struct xkb_context *ctx = info->keymap->ctx;
+ struct xkb_context *ctx = info->ctx;
- ndx = ModNameToIndex(info->keymap, def->modifier, MOD_REAL);
+ ndx = XkbModNameToIndex(&info->mods, def->modifier, MOD_REAL);
if (ndx == XKB_MOD_INVALID) {
- log_err(info->keymap->ctx,
+ log_err(info->ctx,
"Illegal modifier map definition; "
"Ignoring map for non-modifier \"%s\"\n",
xkb_atom_text(ctx, def->modifier));
@@ -1165,10 +1174,10 @@ HandleModMapDef(SymbolsInfo *info, ModMapDef *def)
tmp.u.keySym = sym;
}
else {
- log_err(info->keymap->ctx,
+ log_err(info->ctx,
"Modmap entries may contain only key names or keysyms; "
"Illegal definition for %s modifier ignored\n",
- ModIndexText(info->keymap, tmp.modifier));
+ ModIndexText(info->ctx, &info->mods, tmp.modifier));
continue;
}
@@ -1197,13 +1206,13 @@ HandleSymbolsFile(SymbolsInfo *info, XkbFile *file, enum merge_mode merge)
ok = HandleGlobalVar(info, (VarDef *) stmt);
break;
case STMT_VMOD:
- ok = HandleVModDef(info->keymap, (VModDef *) stmt, merge);
+ ok = HandleVModDef(info->ctx, &info->mods, (VModDef *) stmt, merge);
break;
case STMT_MODMAP:
ok = HandleModMapDef(info, (ModMapDef *) stmt);
break;
default:
- log_err(info->keymap->ctx,
+ log_err(info->ctx,
"Symbols files may not include other types; "
"Ignoring %s\n", stmt_type_to_string(stmt->type));
ok = false;
@@ -1214,8 +1223,8 @@ HandleSymbolsFile(SymbolsInfo *info, XkbFile *file, enum merge_mode merge)
info->errorCount++;
if (info->errorCount > 10) {
- log_err(info->keymap->ctx, "Abandoning symbols file \"%s\"\n",
- file->topName);
+ log_err(info->ctx, "Abandoning symbols file \"%s\"\n",
+ file->name);
break;
}
}
@@ -1234,38 +1243,31 @@ HandleSymbolsFile(SymbolsInfo *info, XkbFile *file, enum merge_mode merge)
static struct xkb_key *
FindKeyForSymbol(struct xkb_keymap *keymap, xkb_keysym_t sym)
{
- struct xkb_key *key, *ret = NULL;
- xkb_layout_index_t group, min_group = UINT32_MAX;
- xkb_level_index_t level, min_level = UINT16_MAX;
-
- xkb_foreach_key(key, keymap) {
- for (group = 0; group < key->num_groups; group++) {
- for (level = 0; level < XkbKeyGroupWidth(key, group); level++) {
- if (key->groups[group].levels[level].num_syms != 1 ||
- key->groups[group].levels[level].u.sym != sym)
- continue;
-
- /*
- * If the keysym was found in a group or level > 0, we must
- * keep looking since we might find a key in which the keysym
- * is in a lower group or level.
- */
- if (group < min_group ||
- (group == min_group && level < min_level)) {
- ret = key;
- if (group == 0 && level == 0) {
- return ret;
- }
- else {
- min_group = group;
- min_level = level;
- }
+ struct xkb_key *key;
+ xkb_layout_index_t group;
+ bool got_one_group, got_one_level;
+
+ group = 0;
+ do {
+ xkb_level_index_t level = 0;
+ got_one_group = false;
+ do {
+ got_one_level = false;
+ xkb_keys_foreach(key, keymap) {
+ if (group < key->num_groups &&
+ level < XkbKeyNumLevels(key, group)) {
+ got_one_group = got_one_level = true;
+ if (key->groups[group].levels[level].num_syms == 1 &&
+ key->groups[group].levels[level].u.sym == sym)
+ return key;
}
}
- }
- }
+ level++;
+ } while (got_one_level);
+ group++;
+ } while (got_one_group);
- return ret;
+ return NULL;
}
/*
@@ -1283,8 +1285,8 @@ FindKeyForSymbol(struct xkb_keymap *keymap, xkb_keysym_t sym)
static xkb_atom_t
FindAutomaticType(struct xkb_context *ctx, GroupInfo *groupi)
{
- xkb_keysym_t sym0, sym1, sym2, sym3;
- xkb_level_index_t width = darray_size(groupi->levels);
+ xkb_keysym_t sym0, sym1;
+ const xkb_level_index_t width = darray_size(groupi->levels);
#define GET_SYM(level) \
(darray_item(groupi->levels, level).num_syms == 0 ? \
@@ -1312,6 +1314,7 @@ FindAutomaticType(struct xkb_context *ctx, GroupInfo *groupi)
if (width <= 4) {
if (xkb_keysym_is_lower(sym0) && xkb_keysym_is_upper(sym1)) {
+ xkb_keysym_t sym2, sym3;
sym2 = GET_SYM(2);
sym3 = (width == 4 ? GET_SYM(3) : XKB_KEY_NoSymbol);
@@ -1386,9 +1389,9 @@ use_default:
}
static bool
-CopySymbolsDef(SymbolsInfo *info, KeyInfo *keyi)
+CopySymbolsDefToKeymap(struct xkb_keymap *keymap, SymbolsInfo *info,
+ KeyInfo *keyi)
{
- struct xkb_keymap *keymap = info->keymap;
struct xkb_key *key;
GroupInfo *groupi;
const GroupInfo *group0;
@@ -1400,7 +1403,7 @@ CopySymbolsDef(SymbolsInfo *info, KeyInfo *keyi)
*/
key = XkbKeyByName(keymap, keyi->name, false);
if (!key) {
- log_vrb(info->keymap->ctx, 5,
+ log_vrb(info->ctx, 5,
"Key %s not found in keycodes; Symbols ignored\n",
KeyInfoText(info, keyi));
return false;
@@ -1443,7 +1446,7 @@ CopySymbolsDef(SymbolsInfo *info, KeyInfo *keyi)
if (type->num_levels < darray_size(groupi->levels)) {
struct xkb_level *leveli;
- log_vrb(info->keymap->ctx, 1,
+ log_vrb(info->ctx, 1,
"Type \"%s\" has %d levels, but %s has %d levels; "
"Ignoring extra symbols\n",
xkb_atom_text(keymap->ctx, type->name), type->num_levels,
@@ -1460,10 +1463,8 @@ CopySymbolsDef(SymbolsInfo *info, KeyInfo *keyi)
}
/* Copy levels. */
- darray_enumerate(i, groupi, keyi->groups) {
- key->groups[i].levels = darray_mem(groupi->levels, 0);
- darray_init(groupi->levels);
- }
+ darray_enumerate(i, groupi, keyi->groups)
+ darray_steal(groupi->levels, &key->groups[i].levels, NULL);
key->out_of_range_group_number = keyi->out_of_range_group_number;
key->out_of_range_group_action = keyi->out_of_range_group_action;
@@ -1489,30 +1490,30 @@ CopySymbolsDef(SymbolsInfo *info, KeyInfo *keyi)
}
static bool
-CopyModMapDef(SymbolsInfo *info, ModMapEntry *entry)
+CopyModMapDefToKeymap(struct xkb_keymap *keymap, SymbolsInfo *info,
+ ModMapEntry *entry)
{
struct xkb_key *key;
- struct xkb_keymap *keymap = info->keymap;
if (!entry->haveSymbol) {
key = XkbKeyByName(keymap, entry->u.keyName, true);
if (!key) {
- log_vrb(info->keymap->ctx, 5,
+ log_vrb(info->ctx, 5,
"Key %s not found in keycodes; "
"Modifier map entry for %s not updated\n",
- KeyNameText(keymap->ctx, entry->u.keyName),
- ModIndexText(info->keymap, entry->modifier));
+ KeyNameText(info->ctx, entry->u.keyName),
+ ModIndexText(info->ctx, &info->mods, entry->modifier));
return false;
}
}
else {
key = FindKeyForSymbol(keymap, entry->u.keySym);
if (!key) {
- log_vrb(info->keymap->ctx, 5,
+ log_vrb(info->ctx, 5,
"Key \"%s\" not found in symbol map; "
"Modifier map entry for %s not updated\n",
- KeysymText(info->keymap->ctx, entry->u.keySym),
- ModIndexText(info->keymap, entry->modifier));
+ KeysymText(info->ctx, entry->u.keySym),
+ ModIndexText(info->ctx, &info->mods, entry->modifier));
return false;
}
}
@@ -1530,30 +1531,31 @@ CopySymbolsToKeymap(struct xkb_keymap *keymap, SymbolsInfo *info)
keymap->symbols_section_name = strdup_safe(info->name);
XkbEscapeMapName(keymap->symbols_section_name);
- keymap->num_group_names = darray_size(info->group_names);
- keymap->group_names = darray_mem(info->group_names, 0);
- darray_init(info->group_names);
+ keymap->mods = info->mods;
+
+ darray_steal(info->group_names,
+ &keymap->group_names, &keymap->num_group_names);
darray_foreach(keyi, info->keys)
- if (!CopySymbolsDef(info, keyi))
+ if (!CopySymbolsDefToKeymap(keymap, info, keyi))
info->errorCount++;
if (xkb_context_get_log_verbosity(keymap->ctx) > 3) {
struct xkb_key *key;
- xkb_foreach_key(key, keymap) {
+ xkb_keys_foreach(key, keymap) {
if (key->name == XKB_ATOM_NONE)
continue;
if (key->num_groups < 1)
- log_info(keymap->ctx,
+ log_info(info->ctx,
"No symbols defined for %s\n",
- KeyNameText(keymap->ctx, key->name));
+ KeyNameText(info->ctx, key->name));
}
}
darray_foreach(mm, info->modmaps)
- if (!CopyModMapDef(info, mm))
+ if (!CopyModMapDefToKeymap(keymap, info, mm))
info->errorCount++;
/* XXX: If we don't ignore errorCount, things break. */
@@ -1571,7 +1573,7 @@ CompileSymbols(XkbFile *file, struct xkb_keymap *keymap,
if (!actions)
return false;
- InitSymbolsInfo(&info, keymap, actions);
+ InitSymbolsInfo(&info, keymap, actions, &keymap->mods);
info.default_key.merge = merge;
HandleSymbolsFile(&info, file, merge);
diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/types.c b/src/3rdparty/xkbcommon/src/xkbcomp/types.c
index 7708da3882..e85b67e893 100644
--- a/src/3rdparty/xkbcommon/src/xkbcomp/types.c
+++ b/src/3rdparty/xkbcommon/src/xkbcomp/types.c
@@ -31,9 +31,9 @@
#include "include.h"
enum type_field {
- TYPE_FIELD_MASK = (1 << 0),
- TYPE_FIELD_MAP = (1 << 1),
- TYPE_FIELD_PRESERVE = (1 << 2),
+ TYPE_FIELD_MASK = (1 << 0),
+ TYPE_FIELD_MAP = (1 << 1),
+ TYPE_FIELD_PRESERVE = (1 << 2),
TYPE_FIELD_LEVEL_NAME = (1 << 3),
};
@@ -53,7 +53,9 @@ typedef struct {
int errorCount;
darray(KeyTypeInfo) types;
- struct xkb_keymap *keymap;
+ struct xkb_mod_set mods;
+
+ struct xkb_context *ctx;
} KeyTypesInfo;
/***====================================================================***/
@@ -61,26 +63,26 @@ typedef struct {
static inline const char *
MapEntryTxt(KeyTypesInfo *info, struct xkb_key_type_entry *entry)
{
- return ModMaskText(info->keymap, entry->mods.mods);
+ return ModMaskText(info->ctx, &info->mods, entry->mods.mods);
}
static inline const char *
TypeTxt(KeyTypesInfo *info, KeyTypeInfo *type)
{
- return xkb_atom_text(info->keymap->ctx, type->name);
+ return xkb_atom_text(info->ctx, type->name);
}
static inline const char *
TypeMaskTxt(KeyTypesInfo *info, KeyTypeInfo *type)
{
- return ModMaskText(info->keymap, type->mods);
+ return ModMaskText(info->ctx, &info->mods, type->mods);
}
static inline bool
ReportTypeShouldBeArray(KeyTypesInfo *info, KeyTypeInfo *type,
const char *field)
{
- return ReportShouldBeArray(info->keymap->ctx, "key type", field,
+ return ReportShouldBeArray(info->ctx, "key type", field,
TypeTxt(info, type));
}
@@ -88,17 +90,19 @@ static inline bool
ReportTypeBadType(KeyTypesInfo *info, KeyTypeInfo *type,
const char *field, const char *wanted)
{
- return ReportBadType(info->keymap->ctx, "key type", field,
+ return ReportBadType(info->ctx, "key type", field,
TypeTxt(info, type), wanted);
}
/***====================================================================***/
static void
-InitKeyTypesInfo(KeyTypesInfo *info, struct xkb_keymap *keymap)
+InitKeyTypesInfo(KeyTypesInfo *info, struct xkb_context *ctx,
+ const struct xkb_mod_set *mods)
{
memset(info, 0, sizeof(*info));
- info->keymap = keymap;
+ info->ctx = ctx;
+ info->mods = *mods;
}
static void
@@ -131,16 +135,16 @@ static bool
AddKeyType(KeyTypesInfo *info, KeyTypeInfo *new, bool same_file)
{
KeyTypeInfo *old;
- const int verbosity = xkb_context_get_log_verbosity(info->keymap->ctx);
+ const int verbosity = xkb_context_get_log_verbosity(info->ctx);
old = FindMatchingKeyType(info, new->name);
if (old) {
if (new->merge == MERGE_REPLACE || new->merge == MERGE_OVERRIDE) {
if ((same_file && verbosity > 0) || verbosity > 9) {
- log_warn(info->keymap->ctx,
+ log_warn(info->ctx,
"Multiple definitions of the %s key type; "
"Earlier definition ignored\n",
- xkb_atom_text(info->keymap->ctx, new->name));
+ xkb_atom_text(info->ctx, new->name));
}
ClearKeyTypeInfo(old);
@@ -151,10 +155,10 @@ AddKeyType(KeyTypesInfo *info, KeyTypeInfo *new, bool same_file)
}
if (same_file)
- log_vrb(info->keymap->ctx, 4,
+ log_vrb(info->ctx, 4,
"Multiple definitions of the %s key type; "
"Later definition ignored\n",
- xkb_atom_text(info->keymap->ctx, new->name));
+ xkb_atom_text(info->ctx, new->name));
ClearKeyTypeInfo(new);
return true;
@@ -170,13 +174,13 @@ static void
MergeIncludedKeyTypes(KeyTypesInfo *into, KeyTypesInfo *from,
enum merge_mode merge)
{
- KeyTypeInfo *type;
-
if (from->errorCount > 0) {
into->errorCount += from->errorCount;
return;
}
+ into->mods = from->mods;
+
if (into->name == NULL) {
into->name = from->name;
from->name = NULL;
@@ -187,6 +191,7 @@ MergeIncludedKeyTypes(KeyTypesInfo *into, KeyTypesInfo *from,
darray_init(from->types);
}
else {
+ KeyTypeInfo *type;
darray_foreach(type, from->types) {
type->merge = (merge == MERGE_DEFAULT ? type->merge : merge);
if (!AddKeyType(into, type, false))
@@ -203,7 +208,7 @@ HandleIncludeKeyTypes(KeyTypesInfo *info, IncludeStmt *include)
{
KeyTypesInfo included;
- InitKeyTypesInfo(&included, info->keymap);
+ InitKeyTypesInfo(&included, info->ctx, &info->mods);
included.name = include->stmt;
include->stmt = NULL;
@@ -211,14 +216,14 @@ HandleIncludeKeyTypes(KeyTypesInfo *info, IncludeStmt *include)
KeyTypesInfo next_incl;
XkbFile *file;
- file = ProcessIncludeFile(info->keymap->ctx, stmt, FILE_TYPE_TYPES);
+ file = ProcessIncludeFile(info->ctx, stmt, FILE_TYPE_TYPES);
if (!file) {
info->errorCount += 10;
ClearKeyTypesInfo(&included);
return false;
}
- InitKeyTypesInfo(&next_incl, info->keymap);
+ InitKeyTypesInfo(&next_incl, info->ctx, &included.mods);
HandleKeyTypesFile(&next_incl, file, stmt->merge);
@@ -243,24 +248,24 @@ SetModifiers(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
xkb_mod_mask_t mods;
if (arrayNdx)
- log_warn(info->keymap->ctx,
+ log_warn(info->ctx,
"The modifiers field of a key type is not an array; "
"Illegal array subscript ignored\n");
- if (!ExprResolveModMask(info->keymap, value, MOD_BOTH, &mods)) {
- log_err(info->keymap->ctx,
+ if (!ExprResolveModMask(info->ctx, value, MOD_BOTH, &info->mods, &mods)) {
+ log_err(info->ctx,
"Key type mask field must be a modifier mask; "
"Key type definition ignored\n");
return false;
}
if (type->defined & TYPE_FIELD_MASK) {
- log_warn(info->keymap->ctx,
+ log_warn(info->ctx,
"Multiple modifier mask definitions for key type %s; "
"Using %s, ignoring %s\n",
- xkb_atom_text(info->keymap->ctx, type->name),
+ xkb_atom_text(info->ctx, type->name),
TypeMaskTxt(info, type),
- ModMaskText(info->keymap, mods));
+ ModMaskText(info->ctx, &info->mods, mods));
return false;
}
@@ -291,7 +296,7 @@ AddMapEntry(KeyTypesInfo *info, KeyTypeInfo *type,
old = FindMatchingMapEntry(type, new->mods.mods);
if (old) {
if (report && old->level != new->level) {
- log_warn(info->keymap->ctx,
+ log_warn(info->ctx,
"Multiple map entries for %s in %s; "
"Using %d, ignoring %d\n",
MapEntryTxt(info, new), TypeTxt(info, type),
@@ -299,7 +304,7 @@ AddMapEntry(KeyTypesInfo *info, KeyTypeInfo *type,
(clobber ? old->level : new->level) + 1);
}
else {
- log_vrb(info->keymap->ctx, 10,
+ log_vrb(info->ctx, 10,
"Multiple occurrences of map[%s]= %d in %s; Ignored\n",
MapEntryTxt(info, new), new->level + 1,
TypeTxt(info, type));
@@ -331,21 +336,23 @@ SetMapEntry(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
if (arrayNdx == NULL)
return ReportTypeShouldBeArray(info, type, "map entry");
- if (!ExprResolveModMask(info->keymap, arrayNdx, MOD_BOTH, &entry.mods.mods))
+ if (!ExprResolveModMask(info->ctx, arrayNdx, MOD_BOTH, &info->mods,
+ &entry.mods.mods))
return ReportTypeBadType(info, type, "map entry", "modifier mask");
if (entry.mods.mods & (~type->mods)) {
- log_vrb(info->keymap->ctx, 1,
+ log_vrb(info->ctx, 1,
"Map entry for unused modifiers in %s; "
"Using %s instead of %s\n",
TypeTxt(info, type),
- ModMaskText(info->keymap, entry.mods.mods & type->mods),
+ ModMaskText(info->ctx, &info->mods,
+ entry.mods.mods & type->mods),
MapEntryTxt(info, &entry));
entry.mods.mods &= type->mods;
}
- if (!ExprResolveLevel(info->keymap->ctx, value, &entry.level)) {
- log_err(info->keymap->ctx,
+ if (!ExprResolveLevel(info->ctx, value, &entry.level)) {
+ log_err(info->ctx,
"Level specifications in a key type must be integer; "
"Ignoring malformed level specification\n");
return false;
@@ -377,22 +384,22 @@ AddPreserve(KeyTypesInfo *info, KeyTypeInfo *type,
/* Map exists with same preserve; do nothing. */
if (entry->preserve.mods == preserve_mods) {
- log_vrb(info->keymap->ctx, 10,
+ log_vrb(info->ctx, 10,
"Identical definitions for preserve[%s] in %s; "
"Ignored\n",
- ModMaskText(info->keymap, mods),
+ ModMaskText(info->ctx, &info->mods, mods),
TypeTxt(info, type));
return true;
}
/* Map exists with different preserve; latter wins. */
- log_vrb(info->keymap->ctx, 1,
+ log_vrb(info->ctx, 1,
"Multiple definitions for preserve[%s] in %s; "
"Using %s, ignoring %s\n",
- ModMaskText(info->keymap, mods),
+ ModMaskText(info->ctx, &info->mods, mods),
TypeTxt(info, type),
- ModMaskText(info->keymap, preserve_mods),
- ModMaskText(info->keymap, entry->preserve.mods));
+ ModMaskText(info->ctx, &info->mods, preserve_mods),
+ ModMaskText(info->ctx, &info->mods, entry->preserve.mods));
entry->preserve.mods = preserve_mods;
return true;
@@ -419,28 +426,29 @@ SetPreserve(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
if (arrayNdx == NULL)
return ReportTypeShouldBeArray(info, type, "preserve entry");
- if (!ExprResolveModMask(info->keymap, arrayNdx, MOD_BOTH, &mods))
+ if (!ExprResolveModMask(info->ctx, arrayNdx, MOD_BOTH, &info->mods, &mods))
return ReportTypeBadType(info, type, "preserve entry",
"modifier mask");
if (mods & ~type->mods) {
const char *before, *after;
- before = ModMaskText(info->keymap, mods);
+ before = ModMaskText(info->ctx, &info->mods, mods);
mods &= type->mods;
- after = ModMaskText(info->keymap, mods);
+ after = ModMaskText(info->ctx, &info->mods, mods);
- log_vrb(info->keymap->ctx, 1,
+ log_vrb(info->ctx, 1,
"Preserve for modifiers not used by the %s type; "
"Index %s converted to %s\n",
TypeTxt(info, type), before, after);
}
- if (!ExprResolveModMask(info->keymap, value, MOD_BOTH, &preserve_mods)) {
- log_err(info->keymap->ctx,
+ if (!ExprResolveModMask(info->ctx, value, MOD_BOTH, &info->mods,
+ &preserve_mods)) {
+ log_err(info->ctx,
"Preserve value in a key type is not a modifier mask; "
"Ignoring preserve[%s] in type %s\n",
- ModMaskText(info->keymap, mods),
+ ModMaskText(info->ctx, &info->mods, mods),
TypeTxt(info, type));
return false;
}
@@ -448,14 +456,14 @@ SetPreserve(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
if (preserve_mods & ~mods) {
const char *before, *after;
- before = ModMaskText(info->keymap, preserve_mods);
+ before = ModMaskText(info->ctx, &info->mods, preserve_mods);
preserve_mods &= mods;
- after = ModMaskText(info->keymap, preserve_mods);
+ after = ModMaskText(info->ctx, &info->mods, preserve_mods);
- log_vrb(info->keymap->ctx, 1,
+ log_vrb(info->ctx, 1,
"Illegal value for preserve[%s] in type %s; "
"Converted %s to %s\n",
- ModMaskText(info->keymap, mods),
+ ModMaskText(info->ctx, &info->mods, mods),
TypeTxt(info, type), before, after);
}
@@ -476,7 +484,7 @@ AddLevelName(KeyTypesInfo *info, KeyTypeInfo *type,
/* Same level, same name. */
if (darray_item(type->level_names, level) == name) {
- log_vrb(info->keymap->ctx, 10,
+ log_vrb(info->ctx, 10,
"Duplicate names for level %d of key type %s; Ignored\n",
level + 1, TypeTxt(info, type));
return true;
@@ -485,10 +493,10 @@ AddLevelName(KeyTypesInfo *info, KeyTypeInfo *type,
/* Same level, different name. */
if (darray_item(type->level_names, level) != XKB_ATOM_NONE) {
const char *old, *new;
- old = xkb_atom_text(info->keymap->ctx,
+ old = xkb_atom_text(info->ctx,
darray_item(type->level_names, level));
- new = xkb_atom_text(info->keymap->ctx, name);
- log_vrb(info->keymap->ctx, 1,
+ new = xkb_atom_text(info->ctx, name);
+ log_vrb(info->ctx, 1,
"Multiple names for level %d of key type %s; "
"Using %s, ignoring %s\n",
level + 1, TypeTxt(info, type),
@@ -511,19 +519,18 @@ SetLevelName(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx,
{
xkb_level_index_t level;
xkb_atom_t level_name;
- struct xkb_context *ctx = info->keymap->ctx;
if (arrayNdx == NULL)
return ReportTypeShouldBeArray(info, type, "level name");
- if (!ExprResolveLevel(ctx, arrayNdx, &level))
+ if (!ExprResolveLevel(info->ctx, arrayNdx, &level))
return ReportTypeBadType(info, type, "level name", "integer");
- if (!ExprResolveString(ctx, value, &level_name)) {
- log_err(info->keymap->ctx,
+ if (!ExprResolveString(info->ctx, value, &level_name)) {
+ log_err(info->ctx,
"Non-string name for level %d in key type %s; "
"Ignoring illegal level name definition\n",
- level + 1, xkb_atom_text(ctx, type->name));
+ level + 1, xkb_atom_text(info->ctx, type->name));
return false;
}
@@ -555,7 +562,7 @@ SetKeyTypeField(KeyTypesInfo *info, KeyTypeInfo *type,
type_field = TYPE_FIELD_LEVEL_NAME;
ok = SetLevelName(info, type, arrayNdx, value);
} else {
- log_err(info->keymap->ctx,
+ log_err(info->ctx,
"Unknown field %s in key type %s; Definition ignored\n",
field, TypeTxt(info, type));
}
@@ -572,13 +579,13 @@ HandleKeyTypeBody(KeyTypesInfo *info, VarDef *def, KeyTypeInfo *type)
ExprDef *arrayNdx;
for (; def; def = (VarDef *) def->common.next) {
- ok = ExprResolveLhs(info->keymap->ctx, def->name, &elem, &field,
+ ok = ExprResolveLhs(info->ctx, def->name, &elem, &field,
&arrayNdx);
if (!ok)
continue;
if (elem && istreq(elem, "type")) {
- log_err(info->keymap->ctx,
+ log_err(info->ctx,
"Support for changing the default type has been removed; "
"Statement ignored\n");
continue;
@@ -633,16 +640,16 @@ HandleKeyTypesFile(KeyTypesInfo *info, XkbFile *file, enum merge_mode merge)
ok = HandleKeyTypeDef(info, (KeyTypeDef *) stmt, merge);
break;
case STMT_VAR:
- log_err(info->keymap->ctx,
+ log_err(info->ctx,
"Support for changing the default type has been removed; "
"Statement ignored\n");
ok = true;
break;
case STMT_VMOD:
- ok = HandleVModDef(info->keymap, (VModDef *) stmt, merge);
+ ok = HandleVModDef(info->ctx, &info->mods, (VModDef *) stmt, merge);
break;
default:
- log_err(info->keymap->ctx,
+ log_err(info->ctx,
"Key type files may not include other declarations; "
"Ignoring %s\n", stmt_type_to_string(stmt->type));
ok = false;
@@ -653,8 +660,8 @@ HandleKeyTypesFile(KeyTypesInfo *info, XkbFile *file, enum merge_mode merge)
info->errorCount++;
if (info->errorCount > 10) {
- log_err(info->keymap->ctx,
- "Abandoning keytypes file \"%s\"\n", file->topName);
+ log_err(info->ctx,
+ "Abandoning keytypes file \"%s\"\n", file->name);
break;
}
}
@@ -665,21 +672,20 @@ HandleKeyTypesFile(KeyTypesInfo *info, XkbFile *file, enum merge_mode merge)
static bool
CopyKeyTypesToKeymap(struct xkb_keymap *keymap, KeyTypesInfo *info)
{
- keymap->types_section_name = strdup_safe(info->name);
- XkbEscapeMapName(keymap->types_section_name);
-
- keymap->num_types = darray_size(info->types);
- if (keymap->num_types == 0)
- keymap->num_types = 1;
+ unsigned num_types;
+ struct xkb_key_type *types;
- keymap->types = calloc(keymap->num_types, sizeof(*keymap->types));
+ num_types = darray_empty(info->types) ? 1 : darray_size(info->types);
+ types = calloc(num_types, sizeof(*types));
+ if (!types)
+ return false;
/*
* If no types were specified, a default unnamed one-level type is
* used for all keys.
*/
if (darray_empty(info->types)) {
- struct xkb_key_type *type = &keymap->types[0];
+ struct xkb_key_type *type = &types[0];
type->mods.mods = 0;
type->num_levels = 1;
@@ -687,24 +693,26 @@ CopyKeyTypesToKeymap(struct xkb_keymap *keymap, KeyTypesInfo *info)
type->num_entries = 0;
type->name = xkb_atom_intern_literal(keymap->ctx, "default");
type->level_names = NULL;
-
- return true;
+ type->num_level_names = 0;
}
-
- for (unsigned i = 0; i < keymap->num_types; i++) {
- KeyTypeInfo *def = &darray_item(info->types, i);
- struct xkb_key_type *type = &keymap->types[i];
-
- type->mods.mods = def->mods;
- type->num_levels = def->num_levels;
- type->entries = darray_mem(def->entries, 0);
- type->num_entries = darray_size(def->entries);
- darray_init(def->entries);
- type->name = def->name;
- type->level_names = darray_mem(def->level_names, 0);
- darray_init(def->level_names);
+ else {
+ for (unsigned i = 0; i < num_types; i++) {
+ KeyTypeInfo *def = &darray_item(info->types, i);
+ struct xkb_key_type *type = &types[i];
+
+ type->name = def->name;
+ type->mods.mods = def->mods;
+ type->num_levels = def->num_levels;
+ darray_steal(def->level_names, &type->level_names, &type->num_level_names);
+ darray_steal(def->entries, &type->entries, &type->num_entries);
+ }
}
+ keymap->types_section_name = strdup_safe(info->name);
+ XkbEscapeMapName(keymap->types_section_name);
+ keymap->num_types = num_types;
+ keymap->types = types;
+ keymap->mods = info->mods;
return true;
}
@@ -716,7 +724,7 @@ CompileKeyTypes(XkbFile *file, struct xkb_keymap *keymap,
{
KeyTypesInfo info;
- InitKeyTypesInfo(&info, keymap);
+ InitKeyTypesInfo(&info, keymap->ctx, &keymap->mods);
HandleKeyTypesFile(&info, file, merge);
if (info.errorCount != 0)
diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/vmod.c b/src/3rdparty/xkbcommon/src/xkbcomp/vmod.c
index 86e7bec786..a0b029af4f 100644
--- a/src/3rdparty/xkbcommon/src/xkbcomp/vmod.c
+++ b/src/3rdparty/xkbcommon/src/xkbcomp/vmod.c
@@ -30,13 +30,12 @@
#include "vmod.h"
bool
-HandleVModDef(struct xkb_keymap *keymap, VModDef *stmt,
- enum merge_mode merge)
+HandleVModDef(struct xkb_context *ctx, struct xkb_mod_set *mods,
+ VModDef *stmt, enum merge_mode merge)
{
xkb_mod_index_t i;
struct xkb_mod *mod;
xkb_mod_mask_t mapping;
- struct xkb_mod new;
merge = (merge == MERGE_DEFAULT ? stmt->merge : merge);
@@ -46,10 +45,10 @@ HandleVModDef(struct xkb_keymap *keymap, VModDef *stmt,
* it sets the vmod-to-real-mod[s] mapping directly instead of going
* through modifier_map or some such.
*/
- if (!ExprResolveModMask(keymap, stmt->value, MOD_REAL, &mapping)) {
- log_err(keymap->ctx,
+ if (!ExprResolveModMask(ctx, stmt->value, MOD_REAL, mods, &mapping)) {
+ log_err(ctx,
"Declaration of %s ignored\n",
- xkb_atom_text(keymap->ctx, stmt->name));
+ xkb_atom_text(ctx, stmt->name));
return false;
}
}
@@ -57,13 +56,13 @@ HandleVModDef(struct xkb_keymap *keymap, VModDef *stmt,
mapping = 0;
}
- darray_enumerate(i, mod, keymap->mods) {
+ xkb_mods_enumerate(i, mod, mods) {
if (mod->name == stmt->name) {
if (mod->type != MOD_VIRT) {
- log_err(keymap->ctx,
+ log_err(ctx,
"Can't add a virtual modifier named \"%s\"; "
"there is already a non-virtual modifier with this name! Ignored\n",
- xkb_atom_text(keymap->ctx, mod->name));
+ xkb_atom_text(ctx, mod->name));
return false;
}
@@ -76,12 +75,12 @@ HandleVModDef(struct xkb_keymap *keymap, VModDef *stmt,
use = (merge == MERGE_OVERRIDE ? mapping : mod->mapping);
ignore = (merge == MERGE_OVERRIDE ? mod->mapping : mapping);
- log_warn(keymap->ctx,
+ log_warn(ctx,
"Virtual modifier %s defined multiple times; "
"Using %s, ignoring %s\n",
- xkb_atom_text(keymap->ctx, stmt->name),
- ModMaskText(keymap, use),
- ModMaskText(keymap, ignore));
+ xkb_atom_text(ctx, stmt->name),
+ ModMaskText(ctx, mods, use),
+ ModMaskText(ctx, mods, ignore));
mapping = use;
}
@@ -91,16 +90,16 @@ HandleVModDef(struct xkb_keymap *keymap, VModDef *stmt,
}
}
- if (darray_size(keymap->mods) >= XKB_MAX_MODS) {
- log_err(keymap->ctx,
+ if (mods->num_mods >= XKB_MAX_MODS) {
+ log_err(ctx,
"Too many modifiers defined (maximum %d)\n",
XKB_MAX_MODS);
return false;
}
- new.name = stmt->name;
- new.mapping = mapping;
- new.type = MOD_VIRT;
- darray_append(keymap->mods, new);
+ mods->mods[mods->num_mods].name = stmt->name;
+ mods->mods[mods->num_mods].type = MOD_VIRT;
+ mods->mods[mods->num_mods].mapping = mapping;
+ mods->num_mods++;
return true;
}
diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/vmod.h b/src/3rdparty/xkbcommon/src/xkbcomp/vmod.h
index 1ba59f73cd..546cf7ee42 100644
--- a/src/3rdparty/xkbcommon/src/xkbcomp/vmod.h
+++ b/src/3rdparty/xkbcommon/src/xkbcomp/vmod.h
@@ -28,7 +28,7 @@
#define XKBCOMP_VMOD_H
bool
-HandleVModDef(struct xkb_keymap *keymap, VModDef *stmt,
- enum merge_mode merge);
+HandleVModDef(struct xkb_context *ctx, struct xkb_mod_set *mods,
+ VModDef *stmt, enum merge_mode merge);
#endif
diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/xkbcomp-keymap.c b/src/3rdparty/xkbcommon/src/xkbcomp/xkbcomp-keymap.c
new file mode 100644
index 0000000000..e95e50c371
--- /dev/null
+++ b/src/3rdparty/xkbcommon/src/xkbcomp/xkbcomp-keymap.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright © 2009 Dan Nicholson
+ * Copyright © 2012 Intel Corporation
+ * Copyright © 2012 Ran Benita <ran234@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Dan Nicholson <dbn.lists@gmail.com>
+ * Daniel Stone <daniel@fooishbar.org>
+ * Ran Benita <ran234@gmail.com>
+ */
+
+#include "xkbcomp-priv.h"
+
+static void
+ComputeEffectiveMask(struct xkb_keymap *keymap, struct xkb_mods *mods)
+{
+ mods->mask = mod_mask_get_effective(keymap, mods->mods);
+}
+
+static void
+UpdateActionMods(struct xkb_keymap *keymap, union xkb_action *act,
+ xkb_mod_mask_t modmap)
+{
+ switch (act->type) {
+ case ACTION_TYPE_MOD_SET:
+ case ACTION_TYPE_MOD_LATCH:
+ case ACTION_TYPE_MOD_LOCK:
+ if (act->mods.flags & ACTION_MODS_LOOKUP_MODMAP)
+ act->mods.mods.mods = modmap;
+ ComputeEffectiveMask(keymap, &act->mods.mods);
+ break;
+ default:
+ break;
+ }
+}
+
+static const struct xkb_sym_interpret default_interpret = {
+ .sym = XKB_KEY_NoSymbol,
+ .repeat = true,
+ .match = MATCH_ANY_OR_NONE,
+ .mods = 0,
+ .virtual_mod = XKB_MOD_INVALID,
+ .action = { .type = ACTION_TYPE_NONE },
+};
+
+/**
+ * Find an interpretation which applies to this particular level, either by
+ * finding an exact match for the symbol and modifier combination, or a
+ * generic XKB_KEY_NoSymbol match.
+ */
+static const struct xkb_sym_interpret *
+FindInterpForKey(struct xkb_keymap *keymap, const struct xkb_key *key,
+ xkb_layout_index_t group, xkb_level_index_t level)
+{
+ const xkb_keysym_t *syms;
+ int num_syms;
+
+ num_syms = xkb_keymap_key_get_syms_by_level(keymap, key->keycode, group,
+ level, &syms);
+ if (num_syms == 0)
+ return NULL;
+
+ /*
+ * There may be multiple matchings interprets; we should always return
+ * the most specific. Here we rely on compat.c to set up the
+ * sym_interprets array from the most specific to the least specific,
+ * such that when we find a match we return immediately.
+ */
+ for (unsigned i = 0; i < keymap->num_sym_interprets; i++) {
+ const struct xkb_sym_interpret *interp = &keymap->sym_interprets[i];
+
+ xkb_mod_mask_t mods;
+ bool found = false;
+
+ if ((num_syms > 1 || interp->sym != syms[0]) &&
+ interp->sym != XKB_KEY_NoSymbol)
+ continue;
+
+ if (interp->level_one_only && level != 0)
+ mods = 0;
+ else
+ mods = key->modmap;
+
+ switch (interp->match) {
+ case MATCH_NONE:
+ found = !(interp->mods & mods);
+ break;
+ case MATCH_ANY_OR_NONE:
+ found = (!mods || (interp->mods & mods));
+ break;
+ case MATCH_ANY:
+ found = (interp->mods & mods);
+ break;
+ case MATCH_ALL:
+ found = ((interp->mods & mods) == interp->mods);
+ break;
+ case MATCH_EXACTLY:
+ found = (interp->mods == mods);
+ break;
+ }
+
+ if (found)
+ return interp;
+ }
+
+ return &default_interpret;
+}
+
+static bool
+ApplyInterpsToKey(struct xkb_keymap *keymap, struct xkb_key *key)
+{
+ xkb_mod_mask_t vmodmap = 0;
+ xkb_layout_index_t group;
+ xkb_level_index_t level;
+
+ /* If we've been told not to bind interps to this key, then don't. */
+ if (key->explicit & EXPLICIT_INTERP)
+ return true;
+
+ for (group = 0; group < key->num_groups; group++) {
+ for (level = 0; level < XkbKeyNumLevels(key, group); level++) {
+ const struct xkb_sym_interpret *interp;
+
+ interp = FindInterpForKey(keymap, key, group, level);
+ if (!interp)
+ continue;
+
+ /* Infer default key behaviours from the base level. */
+ if (group == 0 && level == 0)
+ if (!(key->explicit & EXPLICIT_REPEAT) && interp->repeat)
+ key->repeats = true;
+
+ if ((group == 0 && level == 0) || !interp->level_one_only)
+ if (interp->virtual_mod != XKB_MOD_INVALID)
+ vmodmap |= (1u << interp->virtual_mod);
+
+ if (interp->action.type != ACTION_TYPE_NONE)
+ key->groups[group].levels[level].action = interp->action;
+ }
+ }
+
+ if (!(key->explicit & EXPLICIT_VMODMAP))
+ key->vmodmap = vmodmap;
+
+ return true;
+}
+
+/**
+ * This collects a bunch of disparate functions which was done in the server
+ * at various points that really should've been done within xkbcomp. Turns out
+ * your actions and types are a lot more useful when any of your modifiers
+ * other than Shift actually do something ...
+ */
+static bool
+UpdateDerivedKeymapFields(struct xkb_keymap *keymap)
+{
+ struct xkb_key *key;
+ struct xkb_mod *mod;
+ struct xkb_led *led;
+ unsigned int i, j;
+
+ /* Find all the interprets for the key and bind them to actions,
+ * which will also update the vmodmap. */
+ xkb_keys_foreach(key, keymap)
+ if (!ApplyInterpsToKey(keymap, key))
+ return false;
+
+ /* Update keymap->mods, the virtual -> real mod mapping. */
+ xkb_keys_foreach(key, keymap)
+ xkb_mods_enumerate(i, mod, &keymap->mods)
+ if (key->vmodmap & (1u << i))
+ mod->mapping |= key->modmap;
+
+ /* Now update the level masks for all the types to reflect the vmods. */
+ for (i = 0; i < keymap->num_types; i++) {
+ ComputeEffectiveMask(keymap, &keymap->types[i].mods);
+
+ for (j = 0; j < keymap->types[i].num_entries; j++) {
+ ComputeEffectiveMask(keymap, &keymap->types[i].entries[j].mods);
+ ComputeEffectiveMask(keymap, &keymap->types[i].entries[j].preserve);
+ }
+ }
+
+ /* Update action modifiers. */
+ xkb_keys_foreach(key, keymap)
+ for (i = 0; i < key->num_groups; i++)
+ for (j = 0; j < XkbKeyNumLevels(key, i); j++)
+ UpdateActionMods(keymap, &key->groups[i].levels[j].action,
+ key->modmap);
+
+ /* Update vmod -> led maps. */
+ xkb_leds_foreach(led, keymap)
+ ComputeEffectiveMask(keymap, &led->mods);
+
+ /* Find maximum number of groups out of all keys in the keymap. */
+ xkb_keys_foreach(key, keymap)
+ keymap->num_groups = MAX(keymap->num_groups, key->num_groups);
+
+ return true;
+}
+
+typedef bool (*compile_file_fn)(XkbFile *file,
+ struct xkb_keymap *keymap,
+ enum merge_mode merge);
+
+static const compile_file_fn compile_file_fns[LAST_KEYMAP_FILE_TYPE + 1] = {
+ [FILE_TYPE_KEYCODES] = CompileKeycodes,
+ [FILE_TYPE_TYPES] = CompileKeyTypes,
+ [FILE_TYPE_COMPAT] = CompileCompatMap,
+ [FILE_TYPE_SYMBOLS] = CompileSymbols,
+};
+
+bool
+CompileKeymap(XkbFile *file, struct xkb_keymap *keymap, enum merge_mode merge)
+{
+ bool ok;
+ XkbFile *files[LAST_KEYMAP_FILE_TYPE + 1] = { NULL };
+ enum xkb_file_type type;
+ struct xkb_context *ctx = keymap->ctx;
+
+ /* Collect section files and check for duplicates. */
+ for (file = (XkbFile *) file->defs; file;
+ file = (XkbFile *) file->common.next) {
+ if (file->file_type < FIRST_KEYMAP_FILE_TYPE ||
+ file->file_type > LAST_KEYMAP_FILE_TYPE) {
+ if (file->file_type == FILE_TYPE_GEOMETRY) {
+ log_vrb(ctx, 1,
+ "Geometry sections are not supported; ignoring\n");
+ } else {
+ log_err(ctx, "Cannot define %s in a keymap file\n",
+ xkb_file_type_to_string(file->file_type));
+ }
+ continue;
+ }
+
+ if (files[file->file_type]) {
+ log_err(ctx,
+ "More than one %s section in keymap file; "
+ "All sections after the first ignored\n",
+ xkb_file_type_to_string(file->file_type));
+ continue;
+ }
+
+ files[file->file_type] = file;
+ }
+
+ /*
+ * Check that all required section were provided.
+ * Report everything before failing.
+ */
+ ok = true;
+ for (type = FIRST_KEYMAP_FILE_TYPE;
+ type <= LAST_KEYMAP_FILE_TYPE;
+ type++) {
+ if (files[type] == NULL) {
+ log_err(ctx, "Required section %s missing from keymap\n",
+ xkb_file_type_to_string(type));
+ ok = false;
+ }
+ }
+ if (!ok)
+ return false;
+
+ /* Compile sections. */
+ for (type = FIRST_KEYMAP_FILE_TYPE;
+ type <= LAST_KEYMAP_FILE_TYPE;
+ type++) {
+ log_dbg(ctx, "Compiling %s \"%s\"\n",
+ xkb_file_type_to_string(type), files[type]->name);
+
+ ok = compile_file_fns[type](files[type], keymap, merge);
+ if (!ok) {
+ log_err(ctx, "Failed to compile %s\n",
+ xkb_file_type_to_string(type));
+ return false;
+ }
+ }
+
+ return UpdateDerivedKeymapFields(keymap);
+}
diff --git a/src/3rdparty/xkbcommon/src/xkbcomp/xkbcomp-parser.c b/src/3rdparty/xkbcommon/src/xkbcomp/xkbcomp-parser.c
new file mode 100644
index 0000000000..520cc5b9c5
--- /dev/null
+++ b/src/3rdparty/xkbcommon/src/xkbcomp/xkbcomp-parser.c
@@ -0,0 +1,3392 @@
+/* A Bison parser, made by GNU Bison 3.0.4. */
+
+/* Bison implementation for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "3.0.4"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 1
+
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
+
+/* Substitute the variable and function names. */
+#define yyparse _xkbcommon_parse
+#define yylex _xkbcommon_lex
+#define yyerror _xkbcommon_error
+#define yydebug _xkbcommon_debug
+#define yynerrs _xkbcommon_nerrs
+
+
+/* Copy the first part of user declarations. */
+#line 33 "../src/xkbcomp/parser.y" /* yacc.c:339 */
+
+#include "xkbcomp/xkbcomp-priv.h"
+#include "xkbcomp/ast-build.h"
+#include "xkbcomp/parser-priv.h"
+#include "scanner-utils.h"
+
+struct parser_param {
+ struct xkb_context *ctx;
+ struct scanner *scanner;
+ XkbFile *rtrn;
+ bool more_maps;
+};
+
+#define parser_err(param, fmt, ...) \
+ scanner_err((param)->scanner, fmt, ##__VA_ARGS__)
+
+#define parser_warn(param, fmt, ...) \
+ scanner_warn((param)->scanner, fmt, ##__VA_ARGS__)
+
+static void
+_xkbcommon_error(struct parser_param *param, const char *msg)
+{
+ parser_err(param, "%s", msg);
+}
+
+static bool
+resolve_keysym(const char *name, xkb_keysym_t *sym_rtrn)
+{
+ xkb_keysym_t sym;
+
+ if (!name || istreq(name, "any") || istreq(name, "nosymbol")) {
+ *sym_rtrn = XKB_KEY_NoSymbol;
+ return true;
+ }
+
+ if (istreq(name, "none") || istreq(name, "voidsymbol")) {
+ *sym_rtrn = XKB_KEY_VoidSymbol;
+ return true;
+ }
+
+ sym = xkb_keysym_from_name(name, XKB_KEYSYM_NO_FLAGS);
+ if (sym != XKB_KEY_NoSymbol) {
+ *sym_rtrn = sym;
+ return true;
+ }
+
+ return false;
+}
+
+#define param_scanner param->scanner
+
+#line 124 "xkbcommon-internal@sta/parser.c" /* yacc.c:339 */
+
+# ifndef YY_NULLPTR
+# if defined __cplusplus && 201103L <= __cplusplus
+# define YY_NULLPTR nullptr
+# else
+# define YY_NULLPTR 0
+# endif
+# endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* In a future release of Bison, this section will be replaced
+ by #include "parser.h". */
+#ifndef YY__XKBCOMMON_XKBCOMMON_INTERNAL_STA_PARSER_H_INCLUDED
+# define YY__XKBCOMMON_XKBCOMMON_INTERNAL_STA_PARSER_H_INCLUDED
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int _xkbcommon_debug;
+#endif
+
+/* Token type. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ enum yytokentype
+ {
+ END_OF_FILE = 0,
+ ERROR_TOK = 255,
+ XKB_KEYMAP = 1,
+ XKB_KEYCODES = 2,
+ XKB_TYPES = 3,
+ XKB_SYMBOLS = 4,
+ XKB_COMPATMAP = 5,
+ XKB_GEOMETRY = 6,
+ XKB_SEMANTICS = 7,
+ XKB_LAYOUT = 8,
+ INCLUDE = 10,
+ OVERRIDE = 11,
+ AUGMENT = 12,
+ REPLACE = 13,
+ ALTERNATE = 14,
+ VIRTUAL_MODS = 20,
+ TYPE = 21,
+ INTERPRET = 22,
+ ACTION_TOK = 23,
+ KEY = 24,
+ ALIAS = 25,
+ GROUP = 26,
+ MODIFIER_MAP = 27,
+ INDICATOR = 28,
+ SHAPE = 29,
+ KEYS = 30,
+ ROW = 31,
+ SECTION = 32,
+ OVERLAY = 33,
+ TEXT = 34,
+ OUTLINE = 35,
+ SOLID = 36,
+ LOGO = 37,
+ VIRTUAL = 38,
+ EQUALS = 40,
+ PLUS = 41,
+ MINUS = 42,
+ DIVIDE = 43,
+ TIMES = 44,
+ OBRACE = 45,
+ CBRACE = 46,
+ OPAREN = 47,
+ CPAREN = 48,
+ OBRACKET = 49,
+ CBRACKET = 50,
+ DOT = 51,
+ COMMA = 52,
+ SEMI = 53,
+ EXCLAM = 54,
+ INVERT = 55,
+ STRING = 60,
+ INTEGER = 61,
+ FLOAT = 62,
+ IDENT = 63,
+ KEYNAME = 64,
+ PARTIAL = 70,
+ DEFAULT = 71,
+ HIDDEN = 72,
+ ALPHANUMERIC_KEYS = 73,
+ MODIFIER_KEYS = 74,
+ KEYPAD_KEYS = 75,
+ FUNCTION_KEYS = 76,
+ ALTERNATE_GROUP = 77
+ };
+#endif
+
+/* Value type. */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+
+union YYSTYPE
+{
+#line 162 "../src/xkbcomp/parser.y" /* yacc.c:355 */
+
+ int ival;
+ int64_t num;
+ enum xkb_file_type file_type;
+ char *str;
+ xkb_atom_t atom;
+ enum merge_mode merge;
+ enum xkb_map_flags mapFlags;
+ xkb_keysym_t keysym;
+ ParseCommon *any;
+ ExprDef *expr;
+ VarDef *var;
+ VModDef *vmod;
+ InterpDef *interp;
+ KeyTypeDef *keyType;
+ SymbolsDef *syms;
+ ModMapDef *modMask;
+ GroupCompatDef *groupCompat;
+ LedMapDef *ledMap;
+ LedNameDef *ledName;
+ KeycodeDef *keyCode;
+ KeyAliasDef *keyAlias;
+ void *geom;
+ XkbFile *file;
+
+#line 256 "xkbcommon-internal@sta/parser.c" /* yacc.c:355 */
+};
+
+typedef union YYSTYPE YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+int _xkbcommon_parse (struct parser_param *param);
+
+#endif /* !YY__XKBCOMMON_XKBCOMMON_INTERNAL_STA_PARSER_H_INCLUDED */
+
+/* Copy the second part of user declarations. */
+
+#line 272 "xkbcommon-internal@sta/parser.c" /* yacc.c:358 */
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#else
+typedef signed char yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__ \
+ && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \
+ || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+# define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+# define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+#endif
+
+#if !defined _Noreturn \
+ && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
+# if defined _MSC_VER && 1200 <= _MSC_VER
+# define _Noreturn __declspec (noreturn)
+# else
+# define _Noreturn YY_ATTRIBUTE ((__noreturn__))
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(E) ((void) (E))
+#else
+# define YYUSE(E) /* empty */
+#endif
+
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized. */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+ _Pragma ("GCC diagnostic pop")
+#else
+# define YY_INITIAL_VALUE(Value) Value
+#endif
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+ /* Use EXIT_SUCCESS as a witness for stdlib.h. */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's 'empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined EXIT_SUCCESS \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined EXIT_SUCCESS
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined EXIT_SUCCESS
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss_alloc;
+ YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+# define YYCOPY_NEEDED 1
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (0)
+
+#endif
+
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(Dst, Src, Count) \
+ __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+# else
+# define YYCOPY(Dst, Src, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (Dst)[yyi] = (Src)[yyi]; \
+ } \
+ while (0)
+# endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 16
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 735
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 65
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 72
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 184
+/* YYNSTATES -- Number of states. */
+#define YYNSTATES 334
+
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+ by yylex, with out-of-bounds checking. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 257
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+ as returned by yylex, without out-of-bounds checking. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 4, 5, 6, 7, 8, 9, 10, 11, 2,
+ 12, 13, 14, 15, 16, 2, 2, 2, 2, 2,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 32, 33, 34, 35, 2,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, 51, 2, 2, 2, 2,
+ 52, 53, 54, 55, 56, 2, 2, 2, 2, 2,
+ 57, 58, 59, 60, 61, 62, 63, 64, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 3, 1, 2
+};
+
+#if YYDEBUG
+ /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
+{
+ 0, 241, 241, 243, 245, 249, 255, 256, 257, 260,
+ 268, 272, 280, 281, 282, 283, 284, 287, 288, 291,
+ 292, 295, 296, 297, 298, 299, 300, 301, 302, 305,
+ 307, 310, 315, 320, 325, 330, 335, 340, 345, 350,
+ 355, 360, 365, 366, 367, 368, 375, 377, 379, 383,
+ 387, 391, 395, 398, 402, 404, 408, 414, 416, 420,
+ 423, 427, 433, 439, 442, 444, 447, 448, 449, 450,
+ 451, 454, 456, 460, 464, 468, 472, 474, 478, 480,
+ 484, 488, 489, 492, 494, 496, 498, 500, 504, 505,
+ 508, 509, 513, 514, 517, 519, 523, 527, 528, 531,
+ 534, 536, 540, 542, 544, 548, 550, 554, 558, 562,
+ 563, 564, 565, 568, 569, 572, 574, 576, 578, 580,
+ 582, 584, 586, 588, 590, 592, 596, 597, 600, 601,
+ 602, 603, 604, 614, 615, 618, 621, 625, 627, 629,
+ 631, 633, 635, 639, 641, 643, 645, 647, 649, 651,
+ 653, 657, 660, 664, 668, 670, 672, 674, 678, 680,
+ 682, 684, 688, 689, 692, 694, 696, 698, 702, 706,
+ 712, 713, 733, 734, 737, 738, 741, 744, 747, 750,
+ 751, 754, 757, 758, 761
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || 0
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "END_OF_FILE", "error", "$undefined", "ERROR_TOK", "XKB_KEYMAP",
+ "XKB_KEYCODES", "XKB_TYPES", "XKB_SYMBOLS", "XKB_COMPATMAP",
+ "XKB_GEOMETRY", "XKB_SEMANTICS", "XKB_LAYOUT", "INCLUDE", "OVERRIDE",
+ "AUGMENT", "REPLACE", "ALTERNATE", "VIRTUAL_MODS", "TYPE", "INTERPRET",
+ "ACTION_TOK", "KEY", "ALIAS", "GROUP", "MODIFIER_MAP", "INDICATOR",
+ "SHAPE", "KEYS", "ROW", "SECTION", "OVERLAY", "TEXT", "OUTLINE", "SOLID",
+ "LOGO", "VIRTUAL", "EQUALS", "PLUS", "MINUS", "DIVIDE", "TIMES",
+ "OBRACE", "CBRACE", "OPAREN", "CPAREN", "OBRACKET", "CBRACKET", "DOT",
+ "COMMA", "SEMI", "EXCLAM", "INVERT", "STRING", "INTEGER", "FLOAT",
+ "IDENT", "KEYNAME", "PARTIAL", "DEFAULT", "HIDDEN", "ALPHANUMERIC_KEYS",
+ "MODIFIER_KEYS", "KEYPAD_KEYS", "FUNCTION_KEYS", "ALTERNATE_GROUP",
+ "$accept", "XkbFile", "XkbCompositeMap", "XkbCompositeType",
+ "XkbMapConfigList", "XkbMapConfig", "FileType", "OptFlags", "Flags",
+ "Flag", "DeclList", "Decl", "VarDecl", "KeyNameDecl", "KeyAliasDecl",
+ "VModDecl", "VModDefList", "VModDef", "InterpretDecl", "InterpretMatch",
+ "VarDeclList", "KeyTypeDecl", "SymbolsDecl", "SymbolsBody",
+ "SymbolsVarDecl", "ArrayInit", "GroupCompatDecl", "ModMapDecl",
+ "LedMapDecl", "LedNameDecl", "ShapeDecl", "SectionDecl", "SectionBody",
+ "SectionBodyItem", "RowBody", "RowBodyItem", "Keys", "Key",
+ "OverlayDecl", "OverlayKeyList", "OverlayKey", "OutlineList",
+ "OutlineInList", "CoordList", "Coord", "DoodadDecl", "DoodadType",
+ "FieldSpec", "Element", "OptMergeMode", "MergeMode", "OptExprList",
+ "ExprList", "Expr", "Term", "ActionList", "Action", "Lhs", "Terminal",
+ "OptKeySymList", "KeySymList", "KeySyms", "KeySym", "SignedNumber",
+ "Number", "Float", "Integer", "KeyCode", "Ident", "String", "OptMapName",
+ "MapName", YY_NULLPTR
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+ (internal) symbol number NUM (which must be that of a token). */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 255, 1, 2, 3, 4, 5, 6,
+ 7, 8, 10, 11, 12, 13, 14, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 60, 61, 62, 63, 64, 70, 71, 72,
+ 73, 74, 75, 76, 77
+};
+# endif
+
+#define YYPACT_NINF -182
+
+#define yypact_value_is_default(Yystate) \
+ (!!((Yystate) == (-182)))
+
+#define YYTABLE_NINF -180
+
+#define yytable_value_is_error(Yytable_value) \
+ 0
+
+ /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+static const yytype_int16 yypact[] =
+{
+ 176, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+ 6, -182, -182, 271, 227, -182, -182, -182, -182, -182,
+ -182, -182, -182, -182, -182, -38, -38, -182, -182, -24,
+ -182, 33, 227, -182, 210, -182, 353, 44, 5, -182,
+ -182, -182, -182, -182, -182, 32, -182, 13, 41, -182,
+ -182, -48, 55, 11, -182, 79, 87, 58, -48, -2,
+ 55, -182, 55, 72, -182, -182, -182, 107, -48, -182,
+ 110, -182, -182, -182, -182, -182, -182, -182, -182, -182,
+ -182, -182, -182, -182, -182, -182, 55, -18, -182, 127,
+ 121, -182, 66, -182, 138, -182, 136, -182, -182, -182,
+ 144, 147, -182, 152, 180, 182, 178, 184, 187, 188,
+ 190, 58, 198, 201, 214, 367, 677, 367, -182, -48,
+ -182, 367, 663, 663, 367, 494, 200, 367, 367, 367,
+ 663, 68, 449, 223, -182, -182, 212, 663, -182, -182,
+ -182, -182, -182, -182, -182, -182, -182, 367, 367, 367,
+ 367, 367, -182, -182, 57, 157, -182, 224, -182, -182,
+ -182, -182, -182, 218, 91, -182, 333, -182, 509, 537,
+ 333, 552, -48, 1, -182, -182, 228, 40, 216, 143,
+ 70, 333, 150, 593, 247, -30, 97, -182, 105, -182,
+ 261, 55, 259, 55, -182, -182, 408, -182, -182, -182,
+ 367, -182, 608, -182, -182, -182, 287, -182, -182, 367,
+ 367, 367, 367, 367, -182, 367, 367, -182, 252, -182,
+ 253, 264, 24, 269, 272, 163, -182, 273, 270, -182,
+ -182, -182, 280, 494, 285, -182, -182, 283, 367, -182,
+ 284, 112, 8, -182, -182, 294, -182, 299, -36, 304,
+ 247, 326, 649, 279, 307, -182, 204, 316, -182, 322,
+ 320, 111, 111, -182, -182, 333, 211, -182, -182, 116,
+ 367, -182, 677, -182, 24, -182, -182, -182, 333, -182,
+ 333, -182, -182, -182, -30, -182, -182, -182, -182, 247,
+ 333, 334, -182, 466, -182, 318, -182, -182, -182, -182,
+ -182, -182, 339, -182, -182, -182, 343, 120, 14, 345,
+ -182, 361, 124, -182, -182, -182, -182, 367, -182, 131,
+ -182, -182, 344, 350, 318, 166, 352, 14, -182, -182,
+ -182, -182, -182, -182
+};
+
+ /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+ Performed when YYTABLE does not specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
+{
+ 18, 4, 21, 22, 23, 24, 25, 26, 27, 28,
+ 0, 2, 3, 0, 17, 20, 1, 6, 12, 13,
+ 15, 14, 16, 7, 8, 183, 183, 19, 184, 0,
+ 182, 0, 18, 30, 18, 10, 0, 127, 0, 9,
+ 128, 130, 129, 131, 132, 0, 29, 0, 126, 5,
+ 11, 0, 117, 116, 115, 118, 0, 119, 120, 121,
+ 122, 123, 124, 125, 110, 111, 112, 0, 0, 179,
+ 0, 180, 31, 34, 35, 32, 33, 36, 37, 39,
+ 38, 40, 41, 42, 43, 44, 0, 154, 114, 0,
+ 113, 45, 0, 53, 54, 181, 0, 170, 177, 169,
+ 0, 58, 171, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 47, 0,
+ 51, 0, 0, 0, 0, 65, 0, 0, 0, 0,
+ 0, 0, 0, 0, 48, 178, 0, 0, 117, 116,
+ 118, 119, 120, 121, 122, 124, 125, 0, 0, 0,
+ 0, 0, 176, 161, 154, 0, 142, 147, 149, 160,
+ 159, 113, 158, 155, 0, 52, 55, 60, 0, 0,
+ 57, 163, 0, 0, 64, 70, 0, 113, 0, 0,
+ 0, 136, 0, 0, 0, 0, 0, 101, 0, 106,
+ 0, 121, 123, 0, 84, 86, 0, 82, 87, 85,
+ 0, 49, 0, 144, 147, 143, 0, 145, 146, 134,
+ 0, 0, 0, 0, 156, 0, 0, 46, 0, 59,
+ 0, 170, 0, 169, 0, 0, 152, 0, 162, 167,
+ 166, 69, 0, 0, 0, 50, 73, 0, 0, 76,
+ 0, 0, 0, 175, 174, 0, 173, 0, 0, 0,
+ 0, 0, 0, 0, 0, 81, 0, 0, 150, 0,
+ 133, 138, 139, 137, 140, 141, 0, 61, 56, 0,
+ 134, 72, 0, 71, 0, 62, 63, 67, 66, 74,
+ 135, 75, 102, 172, 0, 78, 100, 79, 105, 0,
+ 104, 0, 91, 0, 89, 0, 80, 77, 108, 148,
+ 157, 168, 0, 151, 165, 164, 0, 0, 0, 0,
+ 88, 0, 0, 98, 153, 107, 103, 0, 94, 0,
+ 93, 83, 0, 0, 0, 0, 0, 0, 99, 96,
+ 97, 95, 90, 92
+};
+
+ /* YYPGOTO[NTERM-NUM]. */
+static const yytype_int16 yypgoto[] =
+{
+ -182, -182, -182, -182, -182, 181, -182, 402, -182, 389,
+ -182, -182, -35, -182, -182, -182, -182, 288, -182, -182,
+ -50, -182, -182, -182, 173, 174, -182, -182, 362, -182,
+ -182, -182, -182, 215, -182, 119, -182, 86, -182, -182,
+ 90, -182, 167, -181, 185, 369, -182, -27, -182, -182,
+ -182, 154, -126, 83, 76, -182, 158, -31, -182, -182,
+ 221, 170, -52, 161, 205, -182, -44, -182, -47, -34,
+ 420, -182
+};
+
+ /* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int16 yydefgoto[] =
+{
+ -1, 10, 11, 25, 34, 12, 26, 36, 14, 15,
+ 37, 46, 167, 73, 74, 75, 92, 93, 76, 100,
+ 168, 77, 78, 173, 174, 175, 79, 80, 195, 82,
+ 83, 84, 196, 197, 293, 294, 319, 320, 198, 312,
+ 313, 186, 187, 188, 189, 199, 86, 154, 88, 47,
+ 48, 259, 260, 181, 156, 225, 226, 157, 158, 227,
+ 228, 229, 230, 245, 246, 159, 160, 136, 161, 162,
+ 29, 30
+};
+
+ /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule whose
+ number is the opposite. If YYTABLE_NINF, syntax error. */
+static const yytype_int16 yytable[] =
+{
+ 90, 101, 180, 241, 94, 184, 16, 69, 242, 102,
+ 71, 106, 72, 105, 28, 107, 89, 32, 96, 69,
+ 87, 112, 71, 243, 244, 108, 109, 115, 110, 116,
+ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 97, 61, 62, 232, 63, 64, 65, 66, 67, 233,
+ 95, 98, 114, 97, 49, 317, 40, 41, 42, 43,
+ 44, 243, 244, 68, 98, 222, 99, 133, 69, 70,
+ 318, 71, 94, 169, 33, 90, 90, 98, 177, 99,
+ 183, 50, -68, 90, 190, 90, 45, 202, -68, 163,
+ 90, 89, 89, 91, 176, 87, 87, 194, 87, 89,
+ 209, 89, 115, 87, 116, 87, 89, 95, 307, 184,
+ 87, 98, 237, 185, 119, 120, 204, 204, 238, 204,
+ 204, 90, 90, 69, -109, 231, 71, 102, 210, 211,
+ 212, 213, 111, 219, 219, 103, 90, 89, 89, 247,
+ 217, 87, 87, 104, 224, 248, 113, 249, 219, 90,
+ 212, 213, 89, 250, 282, 90, 87, 108, 301, 253,
+ 250, 194, 316, 117, 274, 89, 323, 219, 250, 87,
+ 118, 89, 324, 326, 121, 87, 1, 122, 102, 327,
+ 210, 211, 212, 213, 124, 123, 177, 210, 211, 212,
+ 213, 325, 236, 125, 210, 211, 212, 213, 155, 239,
+ 164, 190, 176, 214, 166, 90, 87, 170, 331, 271,
+ 179, 272, 182, 35, 238, 39, 126, 292, 127, 128,
+ 129, 89, 305, 203, 205, 87, 207, 208, 130, 131,
+ 102, 132, 206, 2, 3, 4, 5, 6, 7, 8,
+ 9, 210, 211, 212, 213, 224, 90, 134, 210, 211,
+ 212, 213, 38, 297, 135, 137, 178, 300, 292, 200,
+ 215, 201, 89, 216, 234, 235, 87, 2, 3, 4,
+ 5, 6, 7, 8, 9, 17, 18, 19, 20, 21,
+ 22, 23, 24, 256, 2, 3, 4, 5, 6, 7,
+ 8, 9, 185, 261, 262, 263, 264, 251, 265, 266,
+ 252, 267, 268, 138, 139, 54, 140, -124, 141, 142,
+ 143, 144, -179, 61, 145, 270, 146, 278, 274, 273,
+ 295, 280, 147, 148, 210, 211, 212, 213, 149, 275,
+ 171, 258, 279, 281, 290, 150, 151, 95, 98, 152,
+ 69, 153, 284, 71, 138, 139, 54, 140, 285, 141,
+ 142, 143, 144, 287, 61, 145, 296, 146, 18, 19,
+ 20, 21, 22, 147, 148, 298, 299, 289, 238, 149,
+ 210, 211, 212, 213, 311, 308, 150, 151, 95, 98,
+ 152, 69, 153, 314, 71, 138, 139, 54, 140, 315,
+ 141, 142, 143, 144, 321, 61, 145, 322, 146, 329,
+ 328, 332, 13, 27, 147, 148, 276, 165, 277, 81,
+ 149, 255, 310, 333, 330, 286, 85, 150, 151, 95,
+ 98, 152, 69, 153, 302, 71, 138, 139, 54, 140,
+ 303, 141, 142, 191, 144, 288, 192, 145, 193, 63,
+ 64, 65, 66, 269, 304, 306, 31, 283, 0, 0,
+ 254, 0, 0, 0, 0, 0, 0, 0, 68, 0,
+ 0, 0, 0, 69, 0, 0, 71, 138, 139, 54,
+ 140, 0, 141, 142, 191, 144, 0, 192, 145, 193,
+ 63, 64, 65, 66, 138, 139, 54, 140, 0, 141,
+ 142, 143, 144, 291, 61, 145, 0, 146, 0, 68,
+ 0, 0, 0, 0, 69, 0, 0, 71, 309, 0,
+ 0, 0, 138, 139, 54, 140, 68, 141, 142, 143,
+ 144, 69, 61, 145, 71, 146, 0, 138, 139, 54,
+ 140, 0, 141, 142, 143, 144, 0, 61, 145, 171,
+ 146, 0, 0, 0, 172, 0, 0, 0, 0, 69,
+ 0, 218, 71, 0, 0, 138, 139, 54, 140, 68,
+ 141, 142, 143, 144, 69, 61, 145, 71, 146, 0,
+ 138, 139, 54, 140, 0, 141, 142, 143, 144, 220,
+ 61, 221, 0, 146, 0, 0, 0, 68, 0, 0,
+ 0, 0, 69, 222, 0, 71, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 98, 0, 223, 0, 0,
+ 71, 138, 139, 54, 140, 0, 141, 142, 143, 144,
+ 0, 61, 145, 0, 146, 0, 138, 139, 54, 140,
+ 0, 141, 142, 143, 144, 240, 61, 145, 0, 146,
+ 0, 0, 0, 68, 0, 0, 0, 0, 69, 0,
+ 257, 71, 0, 0, 0, 0, 0, 0, 68, 0,
+ 0, 0, 0, 69, 0, 0, 71, 138, 139, 54,
+ 140, 0, 141, 142, 143, 144, 291, 61, 145, 0,
+ 146, 138, 139, 54, 140, 0, 141, 142, 143, 144,
+ 0, 61, 145, 0, 146, 138, 139, 54, 140, 68,
+ 141, 142, 143, 144, 69, 61, 145, 71, 146, 0,
+ 0, 0, 0, 68, 0, 0, 0, 0, 69, 0,
+ 0, 71, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 69, 0, 0, 71
+};
+
+static const yytype_int16 yycheck[] =
+{
+ 47, 53, 128, 184, 51, 41, 0, 55, 38, 53,
+ 58, 58, 47, 57, 52, 59, 47, 41, 52, 55,
+ 47, 68, 58, 53, 54, 59, 60, 45, 62, 47,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 29, 28, 29, 42, 31, 32, 33, 34, 35, 48,
+ 52, 53, 86, 29, 49, 41, 12, 13, 14, 15,
+ 16, 53, 54, 50, 53, 41, 55, 111, 55, 56,
+ 56, 58, 119, 123, 41, 122, 123, 53, 125, 55,
+ 130, 49, 42, 130, 131, 132, 42, 137, 48, 116,
+ 137, 122, 123, 52, 125, 122, 123, 132, 125, 130,
+ 43, 132, 45, 130, 47, 132, 137, 52, 289, 41,
+ 137, 53, 42, 45, 48, 49, 147, 148, 48, 150,
+ 151, 168, 169, 55, 52, 172, 58, 171, 37, 38,
+ 39, 40, 25, 168, 169, 56, 183, 168, 169, 42,
+ 49, 168, 169, 56, 171, 48, 36, 42, 183, 196,
+ 39, 40, 183, 48, 42, 202, 183, 191, 42, 193,
+ 48, 196, 42, 36, 48, 196, 42, 202, 48, 196,
+ 49, 202, 48, 42, 36, 202, 0, 41, 222, 48,
+ 37, 38, 39, 40, 37, 41, 233, 37, 38, 39,
+ 40, 317, 49, 41, 37, 38, 39, 40, 115, 49,
+ 117, 248, 233, 46, 121, 252, 233, 124, 42, 46,
+ 127, 48, 129, 32, 48, 34, 36, 252, 36, 41,
+ 36, 252, 274, 147, 148, 252, 150, 151, 41, 41,
+ 274, 41, 149, 57, 58, 59, 60, 61, 62, 63,
+ 64, 37, 38, 39, 40, 272, 293, 49, 37, 38,
+ 39, 40, 42, 49, 53, 41, 56, 46, 293, 36,
+ 36, 49, 293, 45, 36, 49, 293, 57, 58, 59,
+ 60, 61, 62, 63, 64, 4, 5, 6, 7, 8,
+ 9, 10, 11, 200, 57, 58, 59, 60, 61, 62,
+ 63, 64, 45, 210, 211, 212, 213, 36, 215, 216,
+ 41, 49, 49, 18, 19, 20, 21, 43, 23, 24,
+ 25, 26, 43, 28, 29, 43, 31, 234, 48, 46,
+ 41, 238, 37, 38, 37, 38, 39, 40, 43, 49,
+ 45, 44, 49, 49, 251, 50, 51, 52, 53, 54,
+ 55, 56, 48, 58, 18, 19, 20, 21, 49, 23,
+ 24, 25, 26, 49, 28, 29, 49, 31, 5, 6,
+ 7, 8, 9, 37, 38, 49, 44, 41, 48, 43,
+ 37, 38, 39, 40, 56, 41, 50, 51, 52, 53,
+ 54, 55, 56, 44, 58, 18, 19, 20, 21, 46,
+ 23, 24, 25, 26, 49, 28, 29, 36, 31, 49,
+ 56, 49, 0, 14, 37, 38, 233, 119, 234, 47,
+ 43, 196, 293, 327, 324, 248, 47, 50, 51, 52,
+ 53, 54, 55, 56, 270, 58, 18, 19, 20, 21,
+ 272, 23, 24, 25, 26, 250, 28, 29, 30, 31,
+ 32, 33, 34, 222, 274, 284, 26, 242, -1, -1,
+ 42, -1, -1, -1, -1, -1, -1, -1, 50, -1,
+ -1, -1, -1, 55, -1, -1, 58, 18, 19, 20,
+ 21, -1, 23, 24, 25, 26, -1, 28, 29, 30,
+ 31, 32, 33, 34, 18, 19, 20, 21, -1, 23,
+ 24, 25, 26, 27, 28, 29, -1, 31, -1, 50,
+ -1, -1, -1, -1, 55, -1, -1, 58, 42, -1,
+ -1, -1, 18, 19, 20, 21, 50, 23, 24, 25,
+ 26, 55, 28, 29, 58, 31, -1, 18, 19, 20,
+ 21, -1, 23, 24, 25, 26, -1, 28, 29, 45,
+ 31, -1, -1, -1, 50, -1, -1, -1, -1, 55,
+ -1, 42, 58, -1, -1, 18, 19, 20, 21, 50,
+ 23, 24, 25, 26, 55, 28, 29, 58, 31, -1,
+ 18, 19, 20, 21, -1, 23, 24, 25, 26, 42,
+ 28, 29, -1, 31, -1, -1, -1, 50, -1, -1,
+ -1, -1, 55, 41, -1, 58, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 53, -1, 55, -1, -1,
+ 58, 18, 19, 20, 21, -1, 23, 24, 25, 26,
+ -1, 28, 29, -1, 31, -1, 18, 19, 20, 21,
+ -1, 23, 24, 25, 26, 42, 28, 29, -1, 31,
+ -1, -1, -1, 50, -1, -1, -1, -1, 55, -1,
+ 42, 58, -1, -1, -1, -1, -1, -1, 50, -1,
+ -1, -1, -1, 55, -1, -1, 58, 18, 19, 20,
+ 21, -1, 23, 24, 25, 26, 27, 28, 29, -1,
+ 31, 18, 19, 20, 21, -1, 23, 24, 25, 26,
+ -1, 28, 29, -1, 31, 18, 19, 20, 21, 50,
+ 23, 24, 25, 26, 55, 28, 29, 58, 31, -1,
+ -1, -1, -1, 50, -1, -1, -1, -1, 55, -1,
+ -1, 58, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 55, -1, -1, 58
+};
+
+ /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint8 yystos[] =
+{
+ 0, 0, 57, 58, 59, 60, 61, 62, 63, 64,
+ 66, 67, 70, 72, 73, 74, 0, 4, 5, 6,
+ 7, 8, 9, 10, 11, 68, 71, 74, 52, 135,
+ 136, 135, 41, 41, 69, 70, 72, 75, 42, 70,
+ 12, 13, 14, 15, 16, 42, 76, 114, 115, 49,
+ 49, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 28, 29, 31, 32, 33, 34, 35, 50, 55,
+ 56, 58, 77, 78, 79, 80, 83, 86, 87, 91,
+ 92, 93, 94, 95, 96, 110, 111, 112, 113, 122,
+ 133, 52, 81, 82, 133, 52, 134, 29, 53, 55,
+ 84, 127, 131, 56, 56, 131, 133, 131, 134, 134,
+ 134, 25, 133, 36, 134, 45, 47, 36, 49, 48,
+ 49, 36, 41, 41, 37, 41, 36, 36, 41, 36,
+ 41, 41, 41, 131, 49, 53, 132, 41, 18, 19,
+ 21, 23, 24, 25, 26, 29, 31, 37, 38, 43,
+ 50, 51, 54, 56, 112, 118, 119, 122, 123, 130,
+ 131, 133, 134, 112, 118, 82, 118, 77, 85, 85,
+ 118, 45, 50, 88, 89, 90, 122, 133, 56, 118,
+ 117, 118, 118, 85, 41, 45, 106, 107, 108, 109,
+ 133, 25, 28, 30, 77, 93, 97, 98, 103, 110,
+ 36, 49, 85, 119, 122, 119, 118, 119, 119, 43,
+ 37, 38, 39, 40, 46, 36, 45, 49, 42, 77,
+ 42, 29, 41, 55, 112, 120, 121, 124, 125, 126,
+ 127, 133, 42, 48, 36, 49, 49, 42, 48, 49,
+ 42, 108, 38, 53, 54, 128, 129, 42, 48, 42,
+ 48, 36, 41, 134, 42, 98, 118, 42, 44, 116,
+ 117, 118, 118, 118, 118, 118, 118, 49, 49, 125,
+ 43, 46, 48, 46, 48, 49, 89, 90, 118, 49,
+ 118, 49, 42, 129, 48, 49, 107, 49, 109, 41,
+ 118, 27, 77, 99, 100, 41, 49, 49, 49, 44,
+ 46, 42, 116, 121, 126, 127, 128, 108, 41, 42,
+ 100, 56, 104, 105, 44, 46, 42, 41, 56, 101,
+ 102, 49, 36, 42, 48, 117, 42, 48, 56, 49,
+ 105, 42, 49, 102
+};
+
+ /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
+{
+ 0, 65, 66, 66, 66, 67, 68, 68, 68, 69,
+ 69, 70, 71, 71, 71, 71, 71, 72, 72, 73,
+ 73, 74, 74, 74, 74, 74, 74, 74, 74, 75,
+ 75, 76, 76, 76, 76, 76, 76, 76, 76, 76,
+ 76, 76, 76, 76, 76, 76, 77, 77, 77, 78,
+ 79, 80, 81, 81, 82, 82, 83, 84, 84, 85,
+ 85, 86, 87, 88, 88, 88, 89, 89, 89, 89,
+ 89, 90, 90, 91, 92, 93, 94, 94, 95, 95,
+ 96, 97, 97, 98, 98, 98, 98, 98, 99, 99,
+ 100, 100, 101, 101, 102, 102, 103, 104, 104, 105,
+ 106, 106, 107, 107, 107, 108, 108, 109, 110, 111,
+ 111, 111, 111, 112, 112, 113, 113, 113, 113, 113,
+ 113, 113, 113, 113, 113, 113, 114, 114, 115, 115,
+ 115, 115, 115, 116, 116, 117, 117, 118, 118, 118,
+ 118, 118, 118, 119, 119, 119, 119, 119, 119, 119,
+ 119, 120, 120, 121, 122, 122, 122, 122, 123, 123,
+ 123, 123, 124, 124, 125, 125, 125, 125, 126, 127,
+ 127, 127, 128, 128, 129, 129, 130, 131, 132, 133,
+ 133, 134, 135, 135, 136
+};
+
+ /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 1, 1, 1, 7, 1, 1, 1, 2,
+ 1, 7, 1, 1, 1, 1, 1, 1, 0, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 4, 2, 3, 4,
+ 5, 3, 3, 1, 1, 3, 6, 3, 1, 2,
+ 1, 6, 6, 3, 1, 0, 3, 3, 1, 2,
+ 1, 3, 3, 5, 6, 6, 5, 6, 6, 6,
+ 6, 2, 1, 5, 1, 1, 1, 1, 2, 1,
+ 5, 1, 3, 1, 1, 3, 6, 3, 1, 3,
+ 3, 1, 3, 5, 3, 3, 1, 5, 6, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 0, 1, 1,
+ 1, 1, 1, 1, 0, 3, 1, 3, 3, 3,
+ 3, 3, 1, 2, 2, 2, 2, 1, 4, 1,
+ 3, 3, 1, 4, 1, 3, 4, 6, 1, 1,
+ 1, 1, 1, 0, 3, 3, 1, 1, 3, 1,
+ 1, 1, 2, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 0, 1
+};
+
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ YYPOPSTACK (yylen); \
+ yystate = *yyssp; \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (param, YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (0)
+
+/* Error token number */
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (0)
+
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
+
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value, param); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (0)
+
+
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT. |
+`----------------------------------------*/
+
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, struct parser_param *param)
+{
+ FILE *yyo = yyoutput;
+ YYUSE (yyo);
+ YYUSE (param);
+ if (!yyvaluep)
+ return;
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+ YYUSE (yytype);
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, struct parser_param *param)
+{
+ YYFPRINTF (yyoutput, "%s %s (",
+ yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep, param);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+static void
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, struct parser_param *param)
+{
+ unsigned long int yylno = yyrline[yyrule];
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr,
+ yystos[yyssp[yyi + 1 - yynrhs]],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ , param);
+ YYFPRINTF (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyssp, yyvsp, Rule, param); \
+} while (0)
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+static YYSIZE_T
+yystrlen (const char *yystr)
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+ about the unexpected token YYTOKEN for the state stack whose top is
+ YYSSP.
+
+ Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is
+ not large enough to hold the message. In that case, also set
+ *YYMSG_ALLOC to the required number of bytes. Return 2 if the
+ required number of bytes is too large to store. */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+ yytype_int16 *yyssp, int yytoken)
+{
+ YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
+ YYSIZE_T yysize = yysize0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ /* Internationalized format string. */
+ const char *yyformat = YY_NULLPTR;
+ /* Arguments of yyformat. */
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ /* Number of reported tokens (one for the "unexpected", one per
+ "expected"). */
+ int yycount = 0;
+
+ /* There are many possibilities here to consider:
+ - If this state is a consistent state with a default action, then
+ the only way this function was invoked is if the default action
+ is an error action. In that case, don't check for expected
+ tokens because there are none.
+ - The only way there can be no lookahead present (in yychar) is if
+ this state is a consistent state with a default action. Thus,
+ detecting the absence of a lookahead is sufficient to determine
+ that there is no unexpected or expected token to report. In that
+ case, just report a simple "syntax error".
+ - Don't assume there isn't a lookahead just because this state is a
+ consistent state with a default action. There might have been a
+ previous inconsistent state, consistent state with a non-default
+ action, or user semantic action that manipulated yychar.
+ - Of course, the expected token list depends on states to have
+ correct lookahead information, and it depends on the parser not
+ to perform extra reductions after fetching a lookahead from the
+ scanner and before detecting a syntax error. Thus, state merging
+ (from LALR or IELR) and default reductions corrupt the expected
+ token list. However, the list is correct for canonical LR with
+ one exception: it will still contain any token that will not be
+ accepted due to an error action in a later state.
+ */
+ if (yytoken != YYEMPTY)
+ {
+ int yyn = yypact[*yyssp];
+ yyarg[yycount++] = yytname[yytoken];
+ if (!yypact_value_is_default (yyn))
+ {
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. In other words, skip the first -YYN actions for
+ this state because they are default actions. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yyx;
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+ && !yytable_value_is_error (yytable[yyx + yyn]))
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ {
+ YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+ if (! (yysize <= yysize1
+ && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
+ }
+ }
+ }
+
+ switch (yycount)
+ {
+# define YYCASE_(N, S) \
+ case N: \
+ yyformat = S; \
+ break
+ YYCASE_(0, YY_("syntax error"));
+ YYCASE_(1, YY_("syntax error, unexpected %s"));
+ YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+ YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+ YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+ YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+ }
+
+ {
+ YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+ if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
+
+ if (*yymsg_alloc < yysize)
+ {
+ *yymsg_alloc = 2 * yysize;
+ if (! (yysize <= *yymsg_alloc
+ && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+ *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+ return 1;
+ }
+
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ {
+ char *yyp = *yymsg;
+ int yyi = 0;
+ while ((*yyp = *yyformat) != '\0')
+ if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyformat += 2;
+ }
+ else
+ {
+ yyp++;
+ yyformat++;
+ }
+ }
+ return 0;
+}
+#endif /* YYERROR_VERBOSE */
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, struct parser_param *param)
+{
+ YYUSE (yyvaluep);
+ YYUSE (param);
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ switch (yytype)
+ {
+ case 52: /* STRING */
+#line 225 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { free(((*yyvaluep).str)); }
+#line 1429 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 55: /* IDENT */
+#line 225 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { free(((*yyvaluep).str)); }
+#line 1435 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 66: /* XkbFile */
+#line 224 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { if (!param->rtrn) FreeXkbFile(((*yyvaluep).file)); }
+#line 1441 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 67: /* XkbCompositeMap */
+#line 224 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { if (!param->rtrn) FreeXkbFile(((*yyvaluep).file)); }
+#line 1447 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 69: /* XkbMapConfigList */
+#line 224 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { if (!param->rtrn) FreeXkbFile(((*yyvaluep).file)); }
+#line 1453 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 70: /* XkbMapConfig */
+#line 224 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { if (!param->rtrn) FreeXkbFile(((*yyvaluep).file)); }
+#line 1459 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 75: /* DeclList */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).any)); }
+#line 1465 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 76: /* Decl */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).any)); }
+#line 1471 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 77: /* VarDecl */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).var)); }
+#line 1477 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 78: /* KeyNameDecl */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).keyCode)); }
+#line 1483 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 79: /* KeyAliasDecl */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).keyAlias)); }
+#line 1489 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 80: /* VModDecl */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).vmod)); }
+#line 1495 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 81: /* VModDefList */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).vmod)); }
+#line 1501 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 82: /* VModDef */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).vmod)); }
+#line 1507 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 83: /* InterpretDecl */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).interp)); }
+#line 1513 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 84: /* InterpretMatch */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).interp)); }
+#line 1519 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 85: /* VarDeclList */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).var)); }
+#line 1525 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 86: /* KeyTypeDecl */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).keyType)); }
+#line 1531 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 87: /* SymbolsDecl */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).syms)); }
+#line 1537 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 88: /* SymbolsBody */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).var)); }
+#line 1543 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 89: /* SymbolsVarDecl */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).var)); }
+#line 1549 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 90: /* ArrayInit */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).expr)); }
+#line 1555 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 91: /* GroupCompatDecl */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).groupCompat)); }
+#line 1561 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 92: /* ModMapDecl */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).modMask)); }
+#line 1567 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 93: /* LedMapDecl */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).ledMap)); }
+#line 1573 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 94: /* LedNameDecl */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).ledName)); }
+#line 1579 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 108: /* CoordList */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).expr)); }
+#line 1585 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 109: /* Coord */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).expr)); }
+#line 1591 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 116: /* OptExprList */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).expr)); }
+#line 1597 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 117: /* ExprList */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).expr)); }
+#line 1603 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 118: /* Expr */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).expr)); }
+#line 1609 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 119: /* Term */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).expr)); }
+#line 1615 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 120: /* ActionList */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).expr)); }
+#line 1621 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 121: /* Action */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).expr)); }
+#line 1627 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 122: /* Lhs */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).expr)); }
+#line 1633 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 123: /* Terminal */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).expr)); }
+#line 1639 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 124: /* OptKeySymList */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).expr)); }
+#line 1645 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 125: /* KeySymList */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).expr)); }
+#line 1651 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 126: /* KeySyms */
+#line 219 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { FreeStmt((ParseCommon *) ((*yyvaluep).expr)); }
+#line 1657 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 135: /* OptMapName */
+#line 225 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { free(((*yyvaluep).str)); }
+#line 1663 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+ case 136: /* MapName */
+#line 225 "../src/xkbcomp/parser.y" /* yacc.c:1257 */
+ { free(((*yyvaluep).str)); }
+#line 1669 "xkbcommon-internal@sta/parser.c" /* yacc.c:1257 */
+ break;
+
+
+ default:
+ break;
+ }
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+}
+
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+int
+yyparse (struct parser_param *param)
+{
+/* The lookahead symbol. */
+int yychar;
+
+
+/* The semantic value of the lookahead symbol. */
+/* Default value used for initialization, for pacifying older GCCs
+ or non-GCC compilers. */
+YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
+YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
+
+ /* Number of syntax errors so far. */
+ int yynerrs;
+
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+
+ /* The stacks and their tools:
+ 'yyss': related to states.
+ 'yyvs': related to semantic values.
+
+ Refer to the stacks through separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
+
+ YYSIZE_T yystacksize;
+
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken = 0;
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ yyssp = yyss = yyssa;
+ yyvsp = yyvs = yyvsa;
+ yystacksize = YYINITDEPTH;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ lookahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to lookahead token. */
+ yyn = yypact[yystate];
+ if (yypact_value_is_default (yyn))
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = yylex (&yylval, param_scanner);
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yytable_value_is_error (yyn))
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ *++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ '$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 2:
+#line 242 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.file) = param->rtrn = (yyvsp[0].file); param->more_maps = !!param->rtrn; }
+#line 1937 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 3:
+#line 244 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.file) = param->rtrn = (yyvsp[0].file); param->more_maps = !!param->rtrn; YYACCEPT; }
+#line 1943 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 4:
+#line 246 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.file) = param->rtrn = NULL; param->more_maps = false; }
+#line 1949 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 5:
+#line 252 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.file) = XkbFileCreate((yyvsp[-5].file_type), (yyvsp[-4].str), (ParseCommon *) (yyvsp[-2].file), (yyvsp[-6].mapFlags)); }
+#line 1955 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 6:
+#line 255 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.file_type) = FILE_TYPE_KEYMAP; }
+#line 1961 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 7:
+#line 256 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.file_type) = FILE_TYPE_KEYMAP; }
+#line 1967 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 8:
+#line 257 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.file_type) = FILE_TYPE_KEYMAP; }
+#line 1973 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 9:
+#line 261 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ {
+ if (!(yyvsp[0].file))
+ (yyval.file) = (yyvsp[-1].file);
+ else
+ (yyval.file) = (XkbFile *) AppendStmt((ParseCommon *) (yyvsp[-1].file),
+ (ParseCommon *) (yyvsp[0].file));
+ }
+#line 1985 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 10:
+#line 269 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.file) = (yyvsp[0].file); }
+#line 1991 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 11:
+#line 275 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ {
+ (yyval.file) = XkbFileCreate((yyvsp[-5].file_type), (yyvsp[-4].str), (yyvsp[-2].any), (yyvsp[-6].mapFlags));
+ }
+#line 1999 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 12:
+#line 280 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.file_type) = FILE_TYPE_KEYCODES; }
+#line 2005 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 13:
+#line 281 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.file_type) = FILE_TYPE_TYPES; }
+#line 2011 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 14:
+#line 282 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.file_type) = FILE_TYPE_COMPAT; }
+#line 2017 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 15:
+#line 283 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.file_type) = FILE_TYPE_SYMBOLS; }
+#line 2023 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 16:
+#line 284 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.file_type) = FILE_TYPE_GEOMETRY; }
+#line 2029 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 17:
+#line 287 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.mapFlags) = (yyvsp[0].mapFlags); }
+#line 2035 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 18:
+#line 288 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.mapFlags) = 0; }
+#line 2041 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 19:
+#line 291 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.mapFlags) = ((yyvsp[-1].mapFlags) | (yyvsp[0].mapFlags)); }
+#line 2047 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 20:
+#line 292 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.mapFlags) = (yyvsp[0].mapFlags); }
+#line 2053 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 21:
+#line 295 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.mapFlags) = MAP_IS_PARTIAL; }
+#line 2059 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 22:
+#line 296 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.mapFlags) = MAP_IS_DEFAULT; }
+#line 2065 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 23:
+#line 297 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.mapFlags) = MAP_IS_HIDDEN; }
+#line 2071 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 24:
+#line 298 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.mapFlags) = MAP_HAS_ALPHANUMERIC; }
+#line 2077 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 25:
+#line 299 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.mapFlags) = MAP_HAS_MODIFIER; }
+#line 2083 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 26:
+#line 300 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.mapFlags) = MAP_HAS_KEYPAD; }
+#line 2089 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 27:
+#line 301 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.mapFlags) = MAP_HAS_FN; }
+#line 2095 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 28:
+#line 302 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.mapFlags) = MAP_IS_ALTGR; }
+#line 2101 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 29:
+#line 306 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.any) = AppendStmt((yyvsp[-1].any), (yyvsp[0].any)); }
+#line 2107 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 30:
+#line 307 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.any) = NULL; }
+#line 2113 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 31:
+#line 311 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ {
+ (yyvsp[0].var)->merge = (yyvsp[-1].merge);
+ (yyval.any) = (ParseCommon *) (yyvsp[0].var);
+ }
+#line 2122 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 32:
+#line 316 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ {
+ (yyvsp[0].vmod)->merge = (yyvsp[-1].merge);
+ (yyval.any) = (ParseCommon *) (yyvsp[0].vmod);
+ }
+#line 2131 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 33:
+#line 321 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ {
+ (yyvsp[0].interp)->merge = (yyvsp[-1].merge);
+ (yyval.any) = (ParseCommon *) (yyvsp[0].interp);
+ }
+#line 2140 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 34:
+#line 326 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ {
+ (yyvsp[0].keyCode)->merge = (yyvsp[-1].merge);
+ (yyval.any) = (ParseCommon *) (yyvsp[0].keyCode);
+ }
+#line 2149 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 35:
+#line 331 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ {
+ (yyvsp[0].keyAlias)->merge = (yyvsp[-1].merge);
+ (yyval.any) = (ParseCommon *) (yyvsp[0].keyAlias);
+ }
+#line 2158 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 36:
+#line 336 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ {
+ (yyvsp[0].keyType)->merge = (yyvsp[-1].merge);
+ (yyval.any) = (ParseCommon *) (yyvsp[0].keyType);
+ }
+#line 2167 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 37:
+#line 341 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ {
+ (yyvsp[0].syms)->merge = (yyvsp[-1].merge);
+ (yyval.any) = (ParseCommon *) (yyvsp[0].syms);
+ }
+#line 2176 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 38:
+#line 346 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ {
+ (yyvsp[0].modMask)->merge = (yyvsp[-1].merge);
+ (yyval.any) = (ParseCommon *) (yyvsp[0].modMask);
+ }
+#line 2185 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 39:
+#line 351 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ {
+ (yyvsp[0].groupCompat)->merge = (yyvsp[-1].merge);
+ (yyval.any) = (ParseCommon *) (yyvsp[0].groupCompat);
+ }
+#line 2194 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 40:
+#line 356 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ {
+ (yyvsp[0].ledMap)->merge = (yyvsp[-1].merge);
+ (yyval.any) = (ParseCommon *) (yyvsp[0].ledMap);
+ }
+#line 2203 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 41:
+#line 361 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ {
+ (yyvsp[0].ledName)->merge = (yyvsp[-1].merge);
+ (yyval.any) = (ParseCommon *) (yyvsp[0].ledName);
+ }
+#line 2212 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 42:
+#line 365 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.any) = NULL; }
+#line 2218 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 43:
+#line 366 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.any) = NULL; }
+#line 2224 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 44:
+#line 367 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.any) = NULL; }
+#line 2230 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 45:
+#line 369 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ {
+ (yyval.any) = (ParseCommon *) IncludeCreate(param->ctx, (yyvsp[0].str), (yyvsp[-1].merge));
+ free((yyvsp[0].str));
+ }
+#line 2239 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 46:
+#line 376 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.var) = VarCreate((yyvsp[-3].expr), (yyvsp[-1].expr)); }
+#line 2245 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 47:
+#line 378 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.var) = BoolVarCreate((yyvsp[-1].atom), true); }
+#line 2251 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 48:
+#line 380 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.var) = BoolVarCreate((yyvsp[-1].atom), false); }
+#line 2257 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 49:
+#line 384 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.keyCode) = KeycodeCreate((yyvsp[-3].atom), (yyvsp[-1].num)); }
+#line 2263 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 50:
+#line 388 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.keyAlias) = KeyAliasCreate((yyvsp[-3].atom), (yyvsp[-1].atom)); }
+#line 2269 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 51:
+#line 392 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.vmod) = (yyvsp[-1].vmod); }
+#line 2275 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 52:
+#line 396 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.vmod) = (VModDef *) AppendStmt((ParseCommon *) (yyvsp[-2].vmod),
+ (ParseCommon *) (yyvsp[0].vmod)); }
+#line 2282 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 53:
+#line 399 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.vmod) = (yyvsp[0].vmod); }
+#line 2288 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 54:
+#line 403 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.vmod) = VModCreate((yyvsp[0].atom), NULL); }
+#line 2294 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 55:
+#line 405 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.vmod) = VModCreate((yyvsp[-2].atom), (yyvsp[0].expr)); }
+#line 2300 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 56:
+#line 411 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyvsp[-4].interp)->def = (yyvsp[-2].var); (yyval.interp) = (yyvsp[-4].interp); }
+#line 2306 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 57:
+#line 415 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.interp) = InterpCreate((yyvsp[-2].keysym), (yyvsp[0].expr)); }
+#line 2312 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 58:
+#line 417 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.interp) = InterpCreate((yyvsp[0].keysym), NULL); }
+#line 2318 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 59:
+#line 421 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.var) = (VarDef *) AppendStmt((ParseCommon *) (yyvsp[-1].var),
+ (ParseCommon *) (yyvsp[0].var)); }
+#line 2325 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 60:
+#line 424 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.var) = (yyvsp[0].var); }
+#line 2331 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 61:
+#line 430 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.keyType) = KeyTypeCreate((yyvsp[-4].atom), (yyvsp[-2].var)); }
+#line 2337 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 62:
+#line 436 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.syms) = SymbolsCreate((yyvsp[-4].atom), (yyvsp[-2].var)); }
+#line 2343 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 63:
+#line 440 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.var) = (VarDef *) AppendStmt((ParseCommon *) (yyvsp[-2].var),
+ (ParseCommon *) (yyvsp[0].var)); }
+#line 2350 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 64:
+#line 443 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.var) = (yyvsp[0].var); }
+#line 2356 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 65:
+#line 444 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.var) = NULL; }
+#line 2362 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 66:
+#line 447 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.var) = VarCreate((yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 2368 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 67:
+#line 448 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.var) = VarCreate((yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 2374 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 68:
+#line 449 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.var) = BoolVarCreate((yyvsp[0].atom), true); }
+#line 2380 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 69:
+#line 450 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.var) = BoolVarCreate((yyvsp[0].atom), false); }
+#line 2386 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 70:
+#line 451 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.var) = VarCreate(NULL, (yyvsp[0].expr)); }
+#line 2392 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 71:
+#line 455 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = (yyvsp[-1].expr); }
+#line 2398 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 72:
+#line 457 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = ExprCreateUnary(EXPR_ACTION_LIST, EXPR_TYPE_ACTION, (yyvsp[-1].expr)); }
+#line 2404 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 73:
+#line 461 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.groupCompat) = GroupCompatCreate((yyvsp[-3].ival), (yyvsp[-1].expr)); }
+#line 2410 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 74:
+#line 465 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.modMask) = ModMapCreate((yyvsp[-4].atom), (yyvsp[-2].expr)); }
+#line 2416 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 75:
+#line 469 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.ledMap) = LedMapCreate((yyvsp[-4].atom), (yyvsp[-2].var)); }
+#line 2422 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 76:
+#line 473 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.ledName) = LedNameCreate((yyvsp[-3].ival), (yyvsp[-1].expr), false); }
+#line 2428 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 77:
+#line 475 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.ledName) = LedNameCreate((yyvsp[-3].ival), (yyvsp[-1].expr), true); }
+#line 2434 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 78:
+#line 479 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.geom) = NULL; }
+#line 2440 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 79:
+#line 481 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (void) (yyvsp[-2].expr); (yyval.geom) = NULL; }
+#line 2446 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 80:
+#line 485 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.geom) = NULL; }
+#line 2452 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 81:
+#line 488 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.geom) = NULL;}
+#line 2458 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 82:
+#line 489 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.geom) = NULL; }
+#line 2464 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 83:
+#line 493 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.geom) = NULL; }
+#line 2470 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 84:
+#line 495 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { FreeStmt((ParseCommon *) (yyvsp[0].var)); (yyval.geom) = NULL; }
+#line 2476 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 85:
+#line 497 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.geom) = NULL; }
+#line 2482 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 86:
+#line 499 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { FreeStmt((ParseCommon *) (yyvsp[0].ledMap)); (yyval.geom) = NULL; }
+#line 2488 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 87:
+#line 501 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.geom) = NULL; }
+#line 2494 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 88:
+#line 504 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.geom) = NULL;}
+#line 2500 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 89:
+#line 505 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.geom) = NULL; }
+#line 2506 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 90:
+#line 508 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.geom) = NULL; }
+#line 2512 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 91:
+#line 510 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { FreeStmt((ParseCommon *) (yyvsp[0].var)); (yyval.geom) = NULL; }
+#line 2518 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 92:
+#line 513 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.geom) = NULL; }
+#line 2524 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 93:
+#line 514 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.geom) = NULL; }
+#line 2530 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 94:
+#line 518 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.geom) = NULL; }
+#line 2536 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 95:
+#line 520 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { FreeStmt((ParseCommon *) (yyvsp[-1].expr)); (yyval.geom) = NULL; }
+#line 2542 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 96:
+#line 524 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.geom) = NULL; }
+#line 2548 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 97:
+#line 527 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.geom) = NULL; }
+#line 2554 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 98:
+#line 528 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.geom) = NULL; }
+#line 2560 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 99:
+#line 531 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.geom) = NULL; }
+#line 2566 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 100:
+#line 535 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.geom) = NULL;}
+#line 2572 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 101:
+#line 537 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.geom) = NULL; }
+#line 2578 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 102:
+#line 541 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (void) (yyvsp[-1].expr); (yyval.geom) = NULL; }
+#line 2584 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 103:
+#line 543 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (void) (yyvsp[-1].expr); (yyval.geom) = NULL; }
+#line 2590 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 104:
+#line 545 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { FreeStmt((ParseCommon *) (yyvsp[0].expr)); (yyval.geom) = NULL; }
+#line 2596 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 105:
+#line 549 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (void) (yyvsp[-2].expr); (void) (yyvsp[0].expr); (yyval.expr) = NULL; }
+#line 2602 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 106:
+#line 551 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (void) (yyvsp[0].expr); (yyval.expr) = NULL; }
+#line 2608 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 107:
+#line 555 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = NULL; }
+#line 2614 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 108:
+#line 559 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { FreeStmt((ParseCommon *) (yyvsp[-2].var)); (yyval.geom) = NULL; }
+#line 2620 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 109:
+#line 562 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.ival) = 0; }
+#line 2626 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 110:
+#line 563 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.ival) = 0; }
+#line 2632 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 111:
+#line 564 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.ival) = 0; }
+#line 2638 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 112:
+#line 565 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.ival) = 0; }
+#line 2644 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 113:
+#line 568 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.atom) = (yyvsp[0].atom); }
+#line 2650 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 114:
+#line 569 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.atom) = (yyvsp[0].atom); }
+#line 2656 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 115:
+#line 573 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.atom) = xkb_atom_intern_literal(param->ctx, "action"); }
+#line 2662 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 116:
+#line 575 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.atom) = xkb_atom_intern_literal(param->ctx, "interpret"); }
+#line 2668 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 117:
+#line 577 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.atom) = xkb_atom_intern_literal(param->ctx, "type"); }
+#line 2674 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 118:
+#line 579 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.atom) = xkb_atom_intern_literal(param->ctx, "key"); }
+#line 2680 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 119:
+#line 581 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.atom) = xkb_atom_intern_literal(param->ctx, "group"); }
+#line 2686 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 120:
+#line 583 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ {(yyval.atom) = xkb_atom_intern_literal(param->ctx, "modifier_map");}
+#line 2692 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 121:
+#line 585 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.atom) = xkb_atom_intern_literal(param->ctx, "indicator"); }
+#line 2698 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 122:
+#line 587 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.atom) = xkb_atom_intern_literal(param->ctx, "shape"); }
+#line 2704 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 123:
+#line 589 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.atom) = xkb_atom_intern_literal(param->ctx, "row"); }
+#line 2710 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 124:
+#line 591 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.atom) = xkb_atom_intern_literal(param->ctx, "section"); }
+#line 2716 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 125:
+#line 593 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.atom) = xkb_atom_intern_literal(param->ctx, "text"); }
+#line 2722 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 126:
+#line 596 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.merge) = (yyvsp[0].merge); }
+#line 2728 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 127:
+#line 597 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.merge) = MERGE_DEFAULT; }
+#line 2734 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 128:
+#line 600 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.merge) = MERGE_DEFAULT; }
+#line 2740 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 129:
+#line 601 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.merge) = MERGE_AUGMENT; }
+#line 2746 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 130:
+#line 602 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.merge) = MERGE_OVERRIDE; }
+#line 2752 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 131:
+#line 603 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.merge) = MERGE_REPLACE; }
+#line 2758 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 132:
+#line 605 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ {
+ /*
+ * This used to be MERGE_ALT_FORM. This functionality was
+ * unused and has been removed.
+ */
+ (yyval.merge) = MERGE_DEFAULT;
+ }
+#line 2770 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 133:
+#line 614 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = (yyvsp[0].expr); }
+#line 2776 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 134:
+#line 615 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = NULL; }
+#line 2782 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 135:
+#line 619 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = (ExprDef *) AppendStmt((ParseCommon *) (yyvsp[-2].expr),
+ (ParseCommon *) (yyvsp[0].expr)); }
+#line 2789 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 136:
+#line 622 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = (yyvsp[0].expr); }
+#line 2795 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 137:
+#line 626 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = ExprCreateBinary(EXPR_DIVIDE, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 2801 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 138:
+#line 628 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = ExprCreateBinary(EXPR_ADD, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 2807 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 139:
+#line 630 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = ExprCreateBinary(EXPR_SUBTRACT, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 2813 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 140:
+#line 632 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = ExprCreateBinary(EXPR_MULTIPLY, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 2819 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 141:
+#line 634 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = ExprCreateBinary(EXPR_ASSIGN, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 2825 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 142:
+#line 636 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = (yyvsp[0].expr); }
+#line 2831 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 143:
+#line 640 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = ExprCreateUnary(EXPR_NEGATE, (yyvsp[0].expr)->expr.value_type, (yyvsp[0].expr)); }
+#line 2837 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 144:
+#line 642 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = ExprCreateUnary(EXPR_UNARY_PLUS, (yyvsp[0].expr)->expr.value_type, (yyvsp[0].expr)); }
+#line 2843 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 145:
+#line 644 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = ExprCreateUnary(EXPR_NOT, EXPR_TYPE_BOOLEAN, (yyvsp[0].expr)); }
+#line 2849 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 146:
+#line 646 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = ExprCreateUnary(EXPR_INVERT, (yyvsp[0].expr)->expr.value_type, (yyvsp[0].expr)); }
+#line 2855 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 147:
+#line 648 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = (yyvsp[0].expr); }
+#line 2861 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 148:
+#line 650 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = ExprCreateAction((yyvsp[-3].atom), (yyvsp[-1].expr)); }
+#line 2867 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 149:
+#line 652 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = (yyvsp[0].expr); }
+#line 2873 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 150:
+#line 654 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = (yyvsp[-1].expr); }
+#line 2879 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 151:
+#line 658 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = (ExprDef *) AppendStmt((ParseCommon *) (yyvsp[-2].expr),
+ (ParseCommon *) (yyvsp[0].expr)); }
+#line 2886 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 152:
+#line 661 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = (yyvsp[0].expr); }
+#line 2892 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 153:
+#line 665 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = ExprCreateAction((yyvsp[-3].atom), (yyvsp[-1].expr)); }
+#line 2898 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 154:
+#line 669 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = ExprCreateIdent((yyvsp[0].atom)); }
+#line 2904 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 155:
+#line 671 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = ExprCreateFieldRef((yyvsp[-2].atom), (yyvsp[0].atom)); }
+#line 2910 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 156:
+#line 673 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = ExprCreateArrayRef(XKB_ATOM_NONE, (yyvsp[-3].atom), (yyvsp[-1].expr)); }
+#line 2916 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 157:
+#line 675 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = ExprCreateArrayRef((yyvsp[-5].atom), (yyvsp[-3].atom), (yyvsp[-1].expr)); }
+#line 2922 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 158:
+#line 679 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = ExprCreateString((yyvsp[0].atom)); }
+#line 2928 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 159:
+#line 681 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = ExprCreateInteger((yyvsp[0].ival)); }
+#line 2934 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 160:
+#line 683 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = ExprCreateFloat(/* Discard $1 */); }
+#line 2940 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 161:
+#line 685 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = ExprCreateKeyName((yyvsp[0].atom)); }
+#line 2946 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 162:
+#line 688 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = (yyvsp[0].expr); }
+#line 2952 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 163:
+#line 689 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = NULL; }
+#line 2958 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 164:
+#line 693 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = ExprAppendKeysymList((yyvsp[-2].expr), (yyvsp[0].keysym)); }
+#line 2964 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 165:
+#line 695 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = ExprAppendMultiKeysymList((yyvsp[-2].expr), (yyvsp[0].expr)); }
+#line 2970 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 166:
+#line 697 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = ExprCreateKeysymList((yyvsp[0].keysym)); }
+#line 2976 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 167:
+#line 699 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = ExprCreateMultiKeysymList((yyvsp[0].expr)); }
+#line 2982 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 168:
+#line 703 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.expr) = (yyvsp[-1].expr); }
+#line 2988 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 169:
+#line 707 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ {
+ if (!resolve_keysym((yyvsp[0].str), &(yyval.keysym)))
+ parser_warn(param, "unrecognized keysym \"%s\"", (yyvsp[0].str));
+ free((yyvsp[0].str));
+ }
+#line 2998 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 170:
+#line 712 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.keysym) = XKB_KEY_section; }
+#line 3004 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 171:
+#line 714 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ {
+ if ((yyvsp[0].ival) < 0) {
+ parser_warn(param, "unrecognized keysym \"%d\"", (yyvsp[0].ival));
+ (yyval.keysym) = XKB_KEY_NoSymbol;
+ }
+ else if ((yyvsp[0].ival) < 10) { /* XKB_KEY_0 .. XKB_KEY_9 */
+ (yyval.keysym) = XKB_KEY_0 + (xkb_keysym_t) (yyvsp[0].ival);
+ }
+ else {
+ char buf[17];
+ snprintf(buf, sizeof(buf), "0x%x", (yyvsp[0].ival));
+ if (!resolve_keysym(buf, &(yyval.keysym))) {
+ parser_warn(param, "unrecognized keysym \"%s\"", buf);
+ (yyval.keysym) = XKB_KEY_NoSymbol;
+ }
+ }
+ }
+#line 3026 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 172:
+#line 733 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.ival) = -(yyvsp[0].ival); }
+#line 3032 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 173:
+#line 734 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.ival) = (yyvsp[0].ival); }
+#line 3038 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 174:
+#line 737 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.ival) = (yyvsp[0].num); }
+#line 3044 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 175:
+#line 738 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.ival) = (yyvsp[0].num); }
+#line 3050 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 176:
+#line 741 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.ival) = 0; }
+#line 3056 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 177:
+#line 744 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.ival) = (yyvsp[0].num); }
+#line 3062 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 178:
+#line 747 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.num) = (yyvsp[0].num); }
+#line 3068 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 179:
+#line 750 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.atom) = xkb_atom_steal(param->ctx, (yyvsp[0].str)); }
+#line 3074 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 180:
+#line 751 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.atom) = xkb_atom_intern_literal(param->ctx, "default"); }
+#line 3080 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 181:
+#line 754 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.atom) = xkb_atom_steal(param->ctx, (yyvsp[0].str)); }
+#line 3086 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 182:
+#line 757 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.str) = (yyvsp[0].str); }
+#line 3092 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 183:
+#line 758 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.str) = NULL; }
+#line 3098 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+ case 184:
+#line 761 "../src/xkbcomp/parser.y" /* yacc.c:1646 */
+ { (yyval.str) = (yyvsp[0].str); }
+#line 3104 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ break;
+
+
+#line 3108 "xkbcommon-internal@sta/parser.c" /* yacc.c:1646 */
+ default: break;
+ }
+ /* User semantic actions sometimes alter yychar, and that requires
+ that yytoken be updated with the new translation. We take the
+ approach of translating immediately before every use of yytoken.
+ One alternative is translating here after every semantic action,
+ but that translation would be missed if the semantic action invokes
+ YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+ if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an
+ incorrect destructor might then be invoked immediately. In the
+ case of YYERROR or YYBACKUP, subsequent parser actions might lead
+ to an incorrect destructor call or verbose syntax error message
+ before the lookahead is translated. */
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+ /* Now 'shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*--------------------------------------.
+| yyerrlab -- here on detecting error. |
+`--------------------------------------*/
+yyerrlab:
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (param, YY_("syntax error"));
+#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+ yyssp, yytoken)
+ {
+ char const *yymsgp = YY_("syntax error");
+ int yysyntax_error_status;
+ yysyntax_error_status = YYSYNTAX_ERROR;
+ if (yysyntax_error_status == 0)
+ yymsgp = yymsg;
+ else if (yysyntax_error_status == 1)
+ {
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+ if (!yymsg)
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ yysyntax_error_status = 2;
+ }
+ else
+ {
+ yysyntax_error_status = YYSYNTAX_ERROR;
+ yymsgp = yymsg;
+ }
+ }
+ yyerror (param, yymsgp);
+ if (yysyntax_error_status == 2)
+ goto yyexhaustedlab;
+ }
+# undef YYSYNTAX_ERROR
+#endif
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval, param);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ /* Do not reclaim the symbols of the rule whose action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (!yypact_value_is_default (yyn))
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp, param);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ *++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#if !defined yyoverflow || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (param, YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEMPTY)
+ {
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = YYTRANSLATE (yychar);
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval, param);
+ }
+ /* Do not reclaim the symbols of the rule whose action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp, param);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ return yyresult;
+}
+#line 764 "../src/xkbcomp/parser.y" /* yacc.c:1906 */
+
+
+XkbFile *
+parse(struct xkb_context *ctx, struct scanner *scanner, const char *map)
+{
+ int ret;
+ XkbFile *first = NULL;
+ struct parser_param param = {
+ .scanner = scanner,
+ .ctx = ctx,
+ .rtrn = NULL,
+ .more_maps = false,
+ };
+
+ /*
+ * If we got a specific map, we look for it exclusively and return
+ * immediately upon finding it. Otherwise, we need to get the
+ * default map. If we find a map marked as default, we return it
+ * immediately. If there are no maps marked as default, we return
+ * the first map in the file.
+ */
+
+ while ((ret = yyparse(&param)) == 0 && param.more_maps) {
+ if (map) {
+ if (streq_not_null(map, param.rtrn->name))
+ return param.rtrn;
+ else
+ FreeXkbFile(param.rtrn);
+ }
+ else {
+ if (param.rtrn->flags & MAP_IS_DEFAULT) {
+ FreeXkbFile(first);
+ return param.rtrn;
+ }
+ else if (!first) {
+ first = param.rtrn;
+ }
+ else {
+ FreeXkbFile(param.rtrn);
+ }
+ }
+ param.rtrn = NULL;
+ }
+
+ if (ret != 0) {
+ FreeXkbFile(first);
+ return NULL;
+ }
+
+ if (first)
+ log_vrb(ctx, 5,
+ "No map in include statement, but \"%s\" contains several; "
+ "Using first defined map, \"%s\"\n",
+ scanner->file_name, first->name);
+
+ return first;
+}
diff --git a/src/3rdparty/xkbcommon/xkbcommon/xkbcommon-compose.h b/src/3rdparty/xkbcommon/xkbcommon/xkbcommon-compose.h
new file mode 100644
index 0000000000..25894b9394
--- /dev/null
+++ b/src/3rdparty/xkbcommon/xkbcommon/xkbcommon-compose.h
@@ -0,0 +1,493 @@
+/*
+ * Copyright © 2013 Ran Benita
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _XKBCOMMON_COMPOSE_H
+#define _XKBCOMMON_COMPOSE_H
+
+#include <xkbcommon/xkbcommon.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file
+ * libxkbcommon Compose API - support for Compose and dead-keys.
+ */
+
+/**
+ * @defgroup compose Compose and dead-keys support
+ * Support for Compose and dead-keys.
+ * @since 0.5.0
+ *
+ * @{
+ */
+
+/**
+ * @page compose-overview Overview
+ * @parblock
+ *
+ * Compose and dead-keys are a common feature of many keyboard input
+ * systems. They extend the range of the keysysm that can be produced
+ * directly from a keyboard by using a sequence of key strokes, instead
+ * of just one.
+ *
+ * Here are some example sequences, in the libX11 Compose file format:
+ *
+ * <dead_acute> <a> : "á" aacute # LATIN SMALL LETTER A WITH ACUTE
+ * <Multi_key> <A> <T> : "@" at # COMMERCIAL AT
+ *
+ * When the user presses a key which produces the `<dead_acute>` keysym,
+ * nothing initially happens (thus the key is dubbed a "dead-key"). But
+ * when the user enters `<a>`, "á" is "composed", in place of "a". If
+ * instead the user had entered a keysym which does not follow
+ * `<dead_acute>` in any compose sequence, the sequence is said to be
+ * "cancelled".
+ *
+ * Compose files define many such sequences. For a description of the
+ * common file format for Compose files, see the Compose(5) man page.
+ *
+ * A successfuly-composed sequence has two results: a keysym and a UTF-8
+ * string. At least one of the two is defined for each sequence. If only
+ * a keysym is given, the keysym's string representation is used for the
+ * result string (using xkb_keysym_to_utf8()).
+ *
+ * This library provides low-level support for Compose file parsing and
+ * processing. Higher-level APIs (such as libX11's `Xutf8LookupString`(3))
+ * may be built upon it, or it can be used directly.
+ *
+ * @endparblock
+ */
+
+/**
+ * @page compose-conflicting Conflicting Sequences
+ * @parblock
+ *
+ * To avoid ambiguity, a sequence is not allowed to be a prefix of another.
+ * In such a case, the conflict is resolved thus:
+ *
+ * 1. A longer sequence overrides a shorter one.
+ * 2. An equal sequence overrides an existing one.
+ * 3. A shorter sequence does not override a longer one.
+ *
+ * Sequences of length 1 are allowed.
+ *
+ * @endparblock
+ */
+
+/**
+ * @page compose-cancellation Cancellation Behavior
+ * @parblock
+ *
+ * What should happen when a sequence is cancelled? For example, consider
+ * there are only the above sequences, and the input keysyms are
+ * `<dead_acute> <b>`. There are a few approaches:
+ *
+ * 1. Swallow the cancelling keysym; that is, no keysym is produced.
+ * This is the approach taken by libX11.
+ * 2. Let the cancelling keysym through; that is, `<b>` is produced.
+ * 3. Replay the entire sequence; that is, `<dead_acute> <b>` is produced.
+ * This is the approach taken by Microsoft Windows (approximately;
+ * instead of `<dead_acute>`, the underlying key is used. This is
+ * difficult to simulate with XKB keymaps).
+ *
+ * You can program whichever approach best fits users' expectations.
+ *
+ * @endparblock
+ */
+
+/**
+ * @struct xkb_compose_table
+ * Opaque Compose table object.
+ *
+ * The compose table holds the definitions of the Compose sequences, as
+ * gathered from Compose files. It is immutable.
+ */
+struct xkb_compose_table;
+
+/**
+ * @struct xkb_compose_state
+ * Opaque Compose state object.
+ *
+ * The compose state maintains state for compose sequence matching, such
+ * as which possible sequences are being matched, and the position within
+ * these sequences. It acts as a simple state machine wherein keysyms are
+ * the input, and composed keysyms and strings are the output.
+ *
+ * The compose state is usually associated with a keyboard device.
+ */
+struct xkb_compose_state;
+
+/** Flags affecting Compose file compilation. */
+enum xkb_compose_compile_flags {
+ /** Do not apply any flags. */
+ XKB_COMPOSE_COMPILE_NO_FLAGS = 0
+};
+
+/** The recognized Compose file formats. */
+enum xkb_compose_format {
+ /** The classic libX11 Compose text format, described in Compose(5). */
+ XKB_COMPOSE_FORMAT_TEXT_V1 = 1
+};
+
+/**
+ * @page compose-locale Compose Locale
+ * @parblock
+ *
+ * Compose files are locale dependent:
+ * - Compose files are written for a locale, and the locale is used when
+ * searching for the appropriate file to use.
+ * - Compose files may reference the locale internally, with directives
+ * such as \%L.
+ *
+ * As such, functions like xkb_compose_table_new_from_locale() require
+ * a `locale` parameter. This will usually be the current locale (see
+ * locale(7) for more details). You may also want to allow the user to
+ * explicitly configure it, so he can use the Compose file of a given
+ * locale, but not use that locale for other things.
+ *
+ * You may query the current locale as follows:
+ * @code
+ * const char *locale;
+ * locale = setlocale(LC_CTYPE, NULL);
+ * @endcode
+ *
+ * This will only give useful results if the program had previously set
+ * the current locale using setlocale(3), with `LC_CTYPE` or `LC_ALL`
+ * and a non-NULL argument.
+ *
+ * If you prefer not to use the locale system of the C runtime library,
+ * you may nevertheless obtain the user's locale directly using
+ * environment variables, as described in locale(7). For example,
+ * @code
+ * const char *locale;
+ * locale = getenv("LC_ALL");
+ * if (!locale || !*locale)
+ * locale = getenv("LC_CTYPE");
+ * if (!locale || !*locale)
+ * locale = getenv("LANG");
+ * if (!locale || !*locale)
+ * locale = "C";
+ * @endcode
+ *
+ * Note that some locales supported by the C standard library may not
+ * have a Compose file assigned.
+ *
+ * @endparblock
+ */
+
+/**
+ * Create a compose table for a given locale.
+ *
+ * The locale is used for searching the file-system for an appropriate
+ * Compose file. The search order is described in Compose(5). It is
+ * affected by the following environment variables:
+ *
+ * 1. `XCOMPOSEFILE` - see Compose(5).
+ * 2. `HOME` - see Compose(5).
+ * 3. `XLOCALEDIR` - if set, used as the base directory for the system's
+ * X locale files, e.g. `/usr/share/X11/locale`, instead of the
+ * preconfigured directory.
+ *
+ * @param context
+ * The library context in which to create the compose table.
+ * @param locale
+ * The current locale. See @ref compose-locale.\n
+ *
+ * The value is copied, so it is safe to pass the result of getenv(3)
+ * (or similar) without fear of it being invalidated by a subsequent
+ * setenv(3) (or similar).
+ * @param flags
+ * Optional flags for the compose table, or 0.
+ *
+ * @returns A compose table for the given locale, or NULL if the
+ * compilation failed or a Compose file was not found.
+ *
+ * @memberof xkb_compose_table
+ */
+struct xkb_compose_table *
+xkb_compose_table_new_from_locale(struct xkb_context *context,
+ const char *locale,
+ enum xkb_compose_compile_flags flags);
+
+/**
+ * Create a new compose table from a Compose file.
+ *
+ * @param context
+ * The library context in which to create the compose table.
+ * @param file
+ * The Compose file to compile.
+ * @param locale
+ * The current locale. See @ref compose-locale.
+ * @param format
+ * The text format of the Compose file to compile.
+ * @param flags
+ * Optional flags for the compose table, or 0.
+ *
+ * @returns A compose table compiled from the given file, or NULL if
+ * the compilation failed.
+ *
+ * @memberof xkb_compose_table
+ */
+struct xkb_compose_table *
+xkb_compose_table_new_from_file(struct xkb_context *context,
+ FILE *file,
+ const char *locale,
+ enum xkb_compose_format format,
+ enum xkb_compose_compile_flags flags);
+
+/**
+ * Create a new compose table from a memory buffer.
+ *
+ * This is just like xkb_compose_table_new_from_file(), but instead of
+ * a file, gets the table as one enormous string.
+ *
+ * @see xkb_compose_table_new_from_file()
+ * @memberof xkb_compose_table
+ */
+struct xkb_compose_table *
+xkb_compose_table_new_from_buffer(struct xkb_context *context,
+ const char *buffer, size_t length,
+ const char *locale,
+ enum xkb_compose_format format,
+ enum xkb_compose_compile_flags flags);
+
+/**
+ * Take a new reference on a compose table.
+ *
+ * @returns The passed in object.
+ *
+ * @memberof xkb_compose_table
+ */
+struct xkb_compose_table *
+xkb_compose_table_ref(struct xkb_compose_table *table);
+
+/**
+ * Release a reference on a compose table, and possibly free it.
+ *
+ * @param table The object. If it is NULL, this function does nothing.
+ *
+ * @memberof xkb_compose_table
+ */
+void
+xkb_compose_table_unref(struct xkb_compose_table *table);
+
+/** Flags for compose state creation. */
+enum xkb_compose_state_flags {
+ /** Do not apply any flags. */
+ XKB_COMPOSE_STATE_NO_FLAGS = 0
+};
+
+/**
+ * Create a new compose state object.
+ *
+ * @param table
+ * The compose table the state will use.
+ * @param flags
+ * Optional flags for the compose state, or 0.
+ *
+ * @returns A new compose state, or NULL on failure.
+ *
+ * @memberof xkb_compose_state
+ */
+struct xkb_compose_state *
+xkb_compose_state_new(struct xkb_compose_table *table,
+ enum xkb_compose_state_flags flags);
+
+/**
+ * Take a new reference on a compose state object.
+ *
+ * @returns The passed in object.
+ *
+ * @memberof xkb_compose_state
+ */
+struct xkb_compose_state *
+xkb_compose_state_ref(struct xkb_compose_state *state);
+
+/**
+ * Release a reference on a compose state object, and possibly free it.
+ *
+ * @param state The object. If NULL, do nothing.
+ *
+ * @memberof xkb_compose_state
+ */
+void
+xkb_compose_state_unref(struct xkb_compose_state *state);
+
+/**
+ * Get the compose table which a compose state object is using.
+ *
+ * @returns The compose table which was passed to xkb_compose_state_new()
+ * when creating this state object.
+ *
+ * This function does not take a new reference on the compose table; you
+ * must explicitly reference it yourself if you plan to use it beyond the
+ * lifetime of the state.
+ *
+ * @memberof xkb_compose_state
+ */
+struct xkb_compose_table *
+xkb_compose_state_get_compose_table(struct xkb_compose_state *state);
+
+/** Status of the Compose sequence state machine. */
+enum xkb_compose_status {
+ /** The initial state; no sequence has started yet. */
+ XKB_COMPOSE_NOTHING,
+ /** In the middle of a sequence. */
+ XKB_COMPOSE_COMPOSING,
+ /** A complete sequence has been matched. */
+ XKB_COMPOSE_COMPOSED,
+ /** The last sequence was cancelled due to an unmatched keysym. */
+ XKB_COMPOSE_CANCELLED
+};
+
+/** The effect of a keysym fed to xkb_compose_state_feed(). */
+enum xkb_compose_feed_result {
+ /** The keysym had no effect - it did not affect the status. */
+ XKB_COMPOSE_FEED_IGNORED,
+ /** The keysym started, advanced or cancelled a sequence. */
+ XKB_COMPOSE_FEED_ACCEPTED
+};
+
+/**
+ * Feed one keysym to the Compose sequence state machine.
+ *
+ * This function can advance into a compose sequence, cancel a sequence,
+ * start a new sequence, or do nothing in particular. The resulting
+ * status may be observed with xkb_compose_state_get_status().
+ *
+ * Some keysyms, such as keysyms for modifier keys, are ignored - they
+ * have no effect on the status or otherwise.
+ *
+ * The following is a description of the possible status transitions, in
+ * the format CURRENT STATUS => NEXT STATUS, given a non-ignored input
+ * keysym `keysym`:
+ *
+ @verbatim
+ NOTHING or CANCELLED or COMPOSED =>
+ NOTHING if keysym does not start a sequence.
+ COMPOSING if keysym starts a sequence.
+ COMPOSED if keysym starts and terminates a single-keysym sequence.
+
+ COMPOSING =>
+ COMPOSING if keysym advances any of the currently possible
+ sequences but does not terminate any of them.
+ COMPOSED if keysym terminates one of the currently possible
+ sequences.
+ CANCELLED if keysym does not advance any of the currently
+ possible sequences.
+ @endverbatim
+ *
+ * The current Compose formats do not support multiple-keysyms.
+ * Therefore, if you are using a function such as xkb_state_key_get_syms()
+ * and it returns more than one keysym, consider feeding XKB_KEY_NoSymbol
+ * instead.
+ *
+ * @param state
+ * The compose state object.
+ * @param keysym
+ * A keysym, usually obtained after a key-press event, with a
+ * function such as xkb_state_key_get_one_sym().
+ *
+ * @returns Whether the keysym was ignored. This is useful, for example,
+ * if you want to keep a record of the sequence matched thus far.
+ *
+ * @memberof xkb_compose_state
+ */
+enum xkb_compose_feed_result
+xkb_compose_state_feed(struct xkb_compose_state *state,
+ xkb_keysym_t keysym);
+
+/**
+ * Reset the Compose sequence state machine.
+ *
+ * The status is set to XKB_COMPOSE_NOTHING, and the current sequence
+ * is discarded.
+ *
+ * @memberof xkb_compose_state
+ */
+void
+xkb_compose_state_reset(struct xkb_compose_state *state);
+
+/**
+ * Get the current status of the compose state machine.
+ *
+ * @see xkb_compose_status
+ * @memberof xkb_compose_state
+ **/
+enum xkb_compose_status
+xkb_compose_state_get_status(struct xkb_compose_state *state);
+
+/**
+ * Get the result Unicode/UTF-8 string for a composed sequence.
+ *
+ * See @ref compose-overview for more details. This function is only
+ * useful when the status is XKB_COMPOSE_COMPOSED.
+ *
+ * @param[in] state
+ * The compose state.
+ * @param[out] buffer
+ * A buffer to write the string into.
+ * @param[in] size
+ * Size of the buffer.
+ *
+ * @warning If the buffer passed is too small, the string is truncated
+ * (though still NUL-terminated).
+ *
+ * @returns
+ * The number of bytes required for the string, excluding the NUL byte.
+ * If the sequence is not complete, or does not have a viable result
+ * string, returns 0, and sets `buffer` to the empty string (if possible).
+ * @returns
+ * You may check if truncation has occurred by comparing the return value
+ * with the size of `buffer`, similarly to the `snprintf`(3) function.
+ * You may safely pass NULL and 0 to `buffer` and `size` to find the
+ * required size (without the NUL-byte).
+ *
+ * @memberof xkb_compose_state
+ **/
+int
+xkb_compose_state_get_utf8(struct xkb_compose_state *state,
+ char *buffer, size_t size);
+
+/**
+ * Get the result keysym for a composed sequence.
+ *
+ * See @ref compose-overview for more details. This function is only
+ * useful when the status is XKB_COMPOSE_COMPOSED.
+ *
+ * @returns The result keysym. If the sequence is not complete, or does
+ * not specify a result keysym, returns XKB_KEY_NoSymbol.
+ *
+ * @memberof xkb_compose_state
+ **/
+xkb_keysym_t
+xkb_compose_state_get_one_sym(struct xkb_compose_state *state);
+
+/** @} */
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* _XKBCOMMON_COMPOSE_H */
diff --git a/src/3rdparty/xkbcommon/xkbcommon/xkbcommon-keysyms.h b/src/3rdparty/xkbcommon/xkbcommon/xkbcommon-keysyms.h
index 69c582e45f..bd172a6efc 100644
--- a/src/3rdparty/xkbcommon/xkbcommon/xkbcommon-keysyms.h
+++ b/src/3rdparty/xkbcommon/xkbcommon/xkbcommon-keysyms.h
@@ -1,7 +1,7 @@
#ifndef _XKBCOMMON_KEYSYMS_H
#define _XKBCOMMON_KEYSYMS_H
-/* This file is autogenerated from Makefile.am; please do not commit directly. */
+/* This file is autogenerated; please do not commit directly. */
#define XKB_KEY_NoSymbol 0x000000 /* Special KeySym */
@@ -2451,29 +2451,6 @@ SOFTWARE.
*
* The XFree86 keysym range is 0x10080001 - 0x1008FFFF.
*
- * When adding new entries, the xc/lib/XKeysymDB file should also be
- * updated to make the new entries visible to Xlib.
- */
-
-/*
- * ModeLock
- *
- * This one is old, and not really used any more since XKB offers this
- * functionality.
- */
-
-#define XKB_KEY_XF86ModeLock 0x1008FF01 /* Mode Switch Lock */
-
-/*
- * Note, 0x1008FF07 - 0x1008FF0F are free and should be used for misc new
- * keysyms that don't fit into any of the groups below.
- *
- * 0x1008FF64, 0x1008FF6F, 0x1008FF71, 0x1008FF83 are no longer used,
- * and should be used first for new keysyms.
- *
- * Check in keysymdef.h for generic symbols before adding new XFree86-specific
- * symbols here.
- *
* X.Org will not be adding to the XF86 set of keysyms, though they have
* been adopted and are considered a "standard" part of X keysym definitions.
* XFree86 never properly commented these keysyms, so we have done our
@@ -2484,6 +2461,14 @@ SOFTWARE.
* these archives, these are from memory and usage.
*/
+/*
+ * ModeLock
+ *
+ * This one is old, and not really used any more since XKB offers this
+ * functionality.
+ */
+
+#define XKB_KEY_XF86ModeLock 0x1008FF01 /* Mode Switch Lock */
/* Backlight controls. */
#define XKB_KEY_XF86MonBrightnessUp 0x1008FF02 /* Monitor/panel brightness */
@@ -2660,6 +2645,13 @@ SOFTWARE.
#define XKB_KEY_XF86AudioMicMute 0x1008FFB2 /* Mute the Mic from the system */
+#define XKB_KEY_XF86Keyboard 0x1008FFB3 /* User defined keyboard related action */
+
+#define XKB_KEY_XF86WWAN 0x1008FFB4 /* Toggle WWAN (LTE, UMTS, etc.) radio */
+#define XKB_KEY_XF86RFKill 0x1008FFB5 /* Toggle radios on/off */
+
+#define XKB_KEY_XF86AudioPreset 0x1008FFB6 /* Select equalizer preset, e.g. theatre-mode */
+
/* Keys for special action keys (hot keys) */
/* Virtual terminals on some operating systems */
#define XKB_KEY_XF86Switch_VT_1 0x1008FE01
diff --git a/src/3rdparty/xkbcommon/xkbcommon/xkbcommon-x11.h b/src/3rdparty/xkbcommon/xkbcommon/xkbcommon-x11.h
index d9e2a4f11a..cf244d2559 100644
--- a/src/3rdparty/xkbcommon/xkbcommon/xkbcommon-x11.h
+++ b/src/3rdparty/xkbcommon/xkbcommon/xkbcommon-x11.h
@@ -39,11 +39,76 @@ extern "C" {
/**
* @defgroup x11 X11 support
* Additional X11 support for xkbcommon.
+ * @since 0.4.0
*
* @{
*/
/**
+ * @page x11-overview Overview
+ * @parblock
+ *
+ * The xkbcommon-x11 module provides a means for creating an xkb_keymap
+ * corresponding to the currently active keymap on the X server. To do
+ * so, it queries the XKB X11 extension using the xcb-xkb library. It
+ * can be used as a replacement for Xlib's keyboard handling.
+ *
+ * Following is an example workflow using xkbcommon-x11. A complete
+ * example may be found in the test/interactive-x11.c file in the
+ * xkbcommon source repository. On startup:
+ *
+ * 1. Connect to the X server using xcb_connect().
+ * 2. Setup the XKB X11 extension. You can do this either by using the
+ * xcb_xkb_use_extension() request directly, or by using the
+ * xkb_x11_setup_xkb_extension() helper function.
+ *
+ * The XKB extension supports using separate keymaps and states for
+ * different keyboard devices. The devices are identified by an integer
+ * device ID and are managed by another X11 extension, XInput. The
+ * original X11 protocol only had one keyboard device, called the "core
+ * keyboard", which is still supported as a "virtual device".
+ *
+ * 3. We will use the core keyboard as an example. To get its device ID,
+ * use either the xcb_xkb_get_device_info() request directly, or the
+ * xkb_x11_get_core_keyboard_device_id() helper function.
+ * 4. Create an initial xkb_keymap for this device, using the
+ * xkb_x11_keymap_new_from_device() function.
+ * 5. Create an initial xkb_state for this device, using the
+ * xkb_x11_state_new_from_device() function.
+ *
+ * @note At this point, you may consider setting various XKB controls and
+ * XKB per-client flags. For example, enabling detectable autorepeat: \n
+ * https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Detectable_Autorepeat
+ *
+ * Next, you need to react to state changes (e.g. a modifier was pressed,
+ * the layout was changed) and to keymap changes (e.g. a tool like xkbcomp,
+ * setxkbmap or xmodmap was used):
+ *
+ * 6. Select to listen to at least the following XKB events:
+ * NewKeyboardNotify, MapNotify, StateNotify; using the
+ * xcb_xkb_select_events_aux() request.
+ * 7. When NewKeyboardNotify or MapNotify are received, recreate the
+ * xkb_keymap and xkb_state as described above.
+ * 8. When StateNotify is received, update the xkb_state accordingly
+ * using the xkb_state_update_mask() function.
+ *
+ * @note It is also possible to use the KeyPress/KeyRelease @p state
+ * field to find the effective modifier and layout state, instead of
+ * using XkbStateNotify: \n
+ * https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Computing_A_State_Field_from_an_XKB_State
+ * \n However, XkbStateNotify is more accurate.
+ *
+ * @note There is no need to call xkb_state_update_key(); the state is
+ * already synchronized.
+ *
+ * Finally, when a key event is received, you can use ordinary xkbcommon
+ * functions, like xkb_state_key_get_one_sym() and xkb_state_key_get_utf8(),
+ * as you normally would.
+ *
+ * @endparblock
+ */
+
+/**
* The minimal compatible major version of the XKB X11 extension which
* this library can use.
*/
@@ -75,14 +140,18 @@ enum xkb_x11_setup_xkb_extension_flags {
*
* @param connection
* An XCB connection to the X server.
- * @param major_xkb_version, minor_xkb_version
+ * @param major_xkb_version
+ * See @p minor_xkb_version.
+ * @param minor_xkb_version
* The XKB extension version to request. To operate correctly, you
* must have (major_xkb_version, minor_xkb_version) >=
* (XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION),
* though this is not enforced.
* @param flags
* Optional flags, or 0.
- * @param[out] major_xkb_version_out, minor_xkb_version_out
+ * @param[out] major_xkb_version_out
+ * See @p minor_xkb_version_out.
+ * @param[out] minor_xkb_version_out
* Backfilled with the compatible XKB extension version numbers picked
* by the server. Can be NULL.
* @param[out] base_event_out
@@ -127,8 +196,9 @@ xkb_x11_get_core_keyboard_device_id(xcb_connection_t *connection);
* @param connection
* An XCB connection to the X server.
* @param device_id
- * An XInput 1 device ID (in the range 0-255) with input class KEY.
- * Passing values outside of this range is an error.
+ * An XInput device ID (in the range 0-127) with input class KEY.
+ * Passing values outside of this range is an error (the XKB protocol
+ * predates the XInput2 protocol, which first allowed IDs > 127).
* @param flags
* Optional flags for the keymap, or 0.
*
diff --git a/src/3rdparty/xkbcommon/xkbcommon/xkbcommon.h b/src/3rdparty/xkbcommon/xkbcommon/xkbcommon.h
index 36251db443..c28123f95e 100644
--- a/src/3rdparty/xkbcommon/xkbcommon/xkbcommon.h
+++ b/src/3rdparty/xkbcommon/xkbcommon/xkbcommon.h
@@ -152,6 +152,10 @@ struct xkb_state;
* underlying input system. For example, with an X11-compatible keymap
* and Linux evdev scan codes (see linux/input.h), a fixed offset is used:
*
+ * The keymap defines a canonical name for each key, plus possible aliases.
+ * Historically, the XKB protocol restricts these names to at most 4 (ASCII)
+ * characters, but this library does not share this limit.
+ *
* @code
* xkb_keycode_t keycode_A = KEY_A + 8;
* @endcode
@@ -173,7 +177,7 @@ typedef uint32_t xkb_keycode_t;
* somewhat more general, in that they can also represent some "function",
* such as "Left" or "Right" for the arrow keys. For more information,
* see:
- * http://www.x.org/releases/X11R7.7/doc/xproto/x11protocol.html#keysym_encoding
+ * https://www.x.org/releases/current/doc/xproto/x11protocol.html#keysym_encoding
*
* Specifically named keysyms can be found in the
* xkbcommon/xkbcommon-keysyms.h header file. Their name does not include
@@ -370,6 +374,35 @@ struct xkb_rule_names {
*/
/**
+ * @page keysym-transformations Keysym Transformations
+ *
+ * Keysym translation is subject to several "keysym transformations",
+ * as described in the XKB specification. These are:
+ *
+ * - Capitalization transformation. If the Caps Lock modifier is
+ * active and was not consumed by the translation process, a single
+ * keysym is transformed to its upper-case form (if applicable).
+ * Similarly, the UTF-8/UTF-32 string produced is capitalized.
+ *
+ * This is described in:
+ * https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Lock_Modifier
+ *
+ * - Control transformation. If the Control modifier is active and
+ * was not consumed by the translation process, the string produced
+ * is transformed to its matching ASCII control character (if
+ * applicable). Keysyms are not affected.
+ *
+ * This is described in:
+ * https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Control_Modifier
+ *
+ * Each relevant function discusses which transformations it performs.
+ *
+ * These transformations are not applicable when a key produces multiple
+ * keysyms.
+ */
+
+
+/**
* Get the name of a keysym.
*
* For a description of how keysyms are named, see @ref xkb_keysym_t.
@@ -416,6 +449,9 @@ enum xkb_keysym_flags {
* fails, only then to try with this flag, while possibly warning the user
* he had misspelled the name, and might get wrong results.
*
+ * Case folding is done according to the C locale; the current locale is not
+ * consulted.
+ *
* @returns The keysym. If the name is invalid, returns XKB_KEY_NoSymbol.
*
* @sa xkb_keysym_t
@@ -434,8 +470,8 @@ xkb_keysym_from_name(const char *name, enum xkb_keysym_flags flags);
* terminating byte). If the keysym does not have a Unicode
* representation, returns 0. If the buffer is too small, returns -1.
*
- * Prefer not to use this function on keysyms obtained from an
- * xkb_state. In this case, use xkb_state_key_get_utf8() instead.
+ * This function does not perform any @ref keysym-transformations.
+ * Therefore, prefer to use xkb_state_key_get_utf8() if possible.
*
* @sa xkb_state_key_get_utf8()
*/
@@ -449,14 +485,34 @@ xkb_keysym_to_utf8(xkb_keysym_t keysym, char *buffer, size_t size);
* compatible with UCS-4. If the keysym does not have a Unicode
* representation, returns 0.
*
- * Prefer not to use this function on keysyms obtained from an
- * xkb_state. In this case, use xkb_state_key_get_utf32() instead.
+ * This function does not perform any @ref keysym-transformations.
+ * Therefore, prefer to use xkb_state_key_get_utf32() if possible.
*
* @sa xkb_state_key_get_utf32()
*/
uint32_t
xkb_keysym_to_utf32(xkb_keysym_t keysym);
+/**
+ * Convert a keysym to its uppercase form.
+ *
+ * If there is no such form, the keysym is returned unchanged.
+ *
+ * The conversion rules may be incomplete; prefer to work with the Unicode
+ * representation instead, when possible.
+ */
+xkb_keysym_t
+xkb_keysym_to_upper(xkb_keysym_t ks);
+
+/**
+ * Convert a keysym to its lowercase form.
+ *
+ * The conversion rules may be incomplete; prefer to work with the Unicode
+ * representation instead, when possible.
+ */
+xkb_keysym_t
+xkb_keysym_to_lower(xkb_keysym_t ks);
+
/** @} */
/**
@@ -469,14 +525,29 @@ xkb_keysym_to_utf32(xkb_keysym_t keysym);
* @{
*/
+/**
+ * @page envvars Environment Variables
+ *
+ * The user may set some environment variables which affect the library:
+ *
+ * - `XKB_CONFIG_ROOT`, `HOME` - see @ref include-path.
+ * - `XKB_LOG_LEVEL` - see xkb_context_set_log_level().
+ * - `XKB_LOG_VERBOSITY` - see xkb_context_set_log_verbosity().
+ * - `XKB_DEFAULT_RULES`, `XKB_DEFAULT_MODEL`, `XKB_DEFAULT_LAYOUT`,
+ * `XKB_DEFAULT_VARIANT`, `XKB_DEFAULT_OPTIONS` - see xkb_rule_names.
+ */
+
/** Flags for context creation. */
enum xkb_context_flags {
/** Do not apply any context flags. */
XKB_CONTEXT_NO_FLAGS = 0,
/** Create this context with an empty include path. */
XKB_CONTEXT_NO_DEFAULT_INCLUDES = (1 << 0),
- /** Don't take RMLVO names from the environment. */
- XKB_CONTEXT_NO_ENVIRONMENT_NAMES = (1 << 1),
+ /**
+ * Don't take RMLVO names from the environment.
+ * @since 0.3.0
+ */
+ XKB_CONTEXT_NO_ENVIRONMENT_NAMES = (1 << 1)
};
/**
@@ -486,10 +557,6 @@ enum xkb_context_flags {
*
* @returns A new context, or NULL on failure.
*
- * The user may set some environment variables to affect default values in
- * the context. See e.g. xkb_context_set_log_level() and
- * xkb_context_set_log_verbosity().
- *
* @memberof xkb_context
*/
struct xkb_context *
@@ -548,7 +615,12 @@ xkb_context_get_user_data(struct xkb_context *context);
*
* The include paths are the file-system paths that are searched when an
* include statement is encountered during keymap compilation.
- * In most cases, the default include paths are sufficient.
+ *
+ * The default include paths are:
+ * - The system XKB root, defined at library configuration time.
+ * If * the `XKB_CONFIG_ROOT` environment is defined, it is used instead.
+ * - The path `$HOME/.xkb`, where $HOME is the value of the environment
+ * variable `HOME`.
*
* @{
*/
@@ -784,7 +856,7 @@ xkb_keymap_new_from_file(struct xkb_context *context, FILE *file,
* This is just like xkb_keymap_new_from_file(), but instead of a file, gets
* the keymap as one enormous string.
*
- * @see xkb_keymap_new_from_string()
+ * @see xkb_keymap_new_from_file()
* @memberof xkb_keymap
*/
struct xkb_keymap *
@@ -800,6 +872,7 @@ xkb_keymap_new_from_string(struct xkb_context *context, const char *string,
*
* @see xkb_keymap_new_from_string()
* @memberof xkb_keymap
+ * @since 0.3.0
*/
struct xkb_keymap *
xkb_keymap_new_from_buffer(struct xkb_context *context, const char *buffer,
@@ -842,7 +915,7 @@ xkb_keymap_unref(struct xkb_keymap *keymap);
*
* @returns The keymap as a NUL-terminated string, or NULL if unsuccessful.
*
- * The returned string may be fed back into xkb_map_new_from_string() to get
+ * The returned string may be fed back into xkb_keymap_new_from_string() to get
* the exact same keymap (possibly in another process, etc.).
*
* The returned string is dynamically allocated and should be freed by the
@@ -868,6 +941,7 @@ xkb_keymap_get_as_string(struct xkb_keymap *keymap,
*
* @sa xkb_keycode_t
* @memberof xkb_keymap
+ * @since 0.3.1
*/
xkb_keycode_t
xkb_keymap_min_keycode(struct xkb_keymap *keymap);
@@ -877,6 +951,7 @@ xkb_keymap_min_keycode(struct xkb_keymap *keymap);
*
* @sa xkb_keycode_t
* @memberof xkb_keymap
+ * @since 0.3.1
*/
xkb_keycode_t
xkb_keymap_max_keycode(struct xkb_keymap *keymap);
@@ -886,6 +961,7 @@ xkb_keymap_max_keycode(struct xkb_keymap *keymap);
*
* @sa xkb_keymap_key_for_each
* @memberof xkb_keymap
+ * @since 0.3.1
*/
typedef void
(*xkb_keymap_key_iter_t)(struct xkb_keymap *keymap, xkb_keycode_t key,
@@ -898,12 +974,44 @@ typedef void
*
* @sa xkb_keymap_min_keycode() xkb_keymap_max_keycode() xkb_keycode_t
* @memberof xkb_keymap
+ * @since 0.3.1
*/
void
xkb_keymap_key_for_each(struct xkb_keymap *keymap, xkb_keymap_key_iter_t iter,
void *data);
/**
+ * Find the name of the key with the given keycode.
+ *
+ * This function always returns the canonical name of the key (see
+ * description in xkb_keycode_t).
+ *
+ * @returns The key name. If no key with this keycode exists,
+ * returns NULL.
+ *
+ * @sa xkb_keycode_t
+ * @memberof xkb_keymap
+ * @since 0.6.0
+ */
+const char *
+xkb_keymap_key_get_name(struct xkb_keymap *keymap, xkb_keycode_t key);
+
+/**
+ * Find the keycode of the key with the given name.
+ *
+ * The name can be either a canonical name or an alias.
+ *
+ * @returns The keycode. If no key with this name exists,
+ * returns XKB_KEYCODE_INVALID.
+ *
+ * @sa xkb_keycode_t
+ * @memberof xkb_keymap
+ * @since 0.6.0
+ */
+xkb_keycode_t
+xkb_keymap_key_by_name(struct xkb_keymap *keymap, const char *name);
+
+/**
* Get the number of modifiers in the keymap.
*
* @sa xkb_mod_index_t
@@ -969,6 +1077,41 @@ xkb_layout_index_t
xkb_keymap_layout_get_index(struct xkb_keymap *keymap, const char *name);
/**
+ * Get the number of LEDs in the keymap.
+ *
+ * @warning The range [ 0...xkb_keymap_num_leds() ) includes all of the LEDs
+ * in the keymap, but may also contain inactive LEDs. When iterating over
+ * this range, you need the handle this case when calling functions such as
+ * xkb_keymap_led_get_name() or xkb_state_led_index_is_active().
+ *
+ * @sa xkb_led_index_t
+ * @memberof xkb_keymap
+ */
+xkb_led_index_t
+xkb_keymap_num_leds(struct xkb_keymap *keymap);
+
+/**
+ * Get the name of a LED by index.
+ *
+ * @returns The name. If the index is invalid, returns NULL.
+ *
+ * @memberof xkb_keymap
+ */
+const char *
+xkb_keymap_led_get_name(struct xkb_keymap *keymap, xkb_led_index_t idx);
+
+/**
+ * Get the index of a LED by name.
+ *
+ * @returns The index. If no LED with this name exists, returns
+ * XKB_LED_INVALID.
+ *
+ * @memberof xkb_keymap
+ */
+xkb_led_index_t
+xkb_keymap_led_get_index(struct xkb_keymap *keymap, const char *name);
+
+/**
* Get the number of layouts for a specific key.
*
* This number can be different from xkb_keymap_num_layouts(), but is always
@@ -1008,8 +1151,8 @@ xkb_keymap_num_levels_for_key(struct xkb_keymap *keymap, xkb_keycode_t key,
* @param[in] layout The layout for which to get the keysyms.
* @param[in] level The shift level in the layout for which to get the
* keysyms. This must be smaller than:
- * @code xkb_keymap_num_layouts_for_key(keymap, key) @endcode
- * @param[out] syms_out An immutible array of keysyms corresponding to the
+ * @code xkb_keymap_num_levels_for_key(keymap, key) @endcode
+ * @param[out] syms_out An immutable array of keysyms corresponding to the
* key in the given layout and shift level.
*
* If @c layout is out of range for this key (that is, larger or equal to
@@ -1031,41 +1174,6 @@ xkb_keymap_key_get_syms_by_level(struct xkb_keymap *keymap,
const xkb_keysym_t **syms_out);
/**
- * Get the number of LEDs in the keymap.
- *
- * @warning The range [ 0...xkb_keymap_num_leds() ) includes all of the LEDs
- * in the keymap, but may also contain inactive LEDs. When iterating over
- * this range, you need the handle this case when calling functions such as
- * xkb_keymap_led_get_name() or xkb_state_led_index_is_active().
- *
- * @sa xkb_led_index_t
- * @memberof xkb_keymap
- */
-xkb_led_index_t
-xkb_keymap_num_leds(struct xkb_keymap *keymap);
-
-/**
- * Get the name of a LED by index.
- *
- * @returns The name. If the index is invalid, returns NULL.
- *
- * @memberof xkb_keymap
- */
-const char *
-xkb_keymap_led_get_name(struct xkb_keymap *keymap, xkb_led_index_t idx);
-
-/**
- * Get the index of a LED by name.
- *
- * @returns The index. If no LED with this name exists, returns
- * XKB_LED_INVALID.
- *
- * @memberof xkb_keymap
- */
-xkb_led_index_t
-xkb_keymap_led_get_index(struct xkb_keymap *keymap, const char *name);
-
-/**
* Determine whether a key should repeat or not.
*
* A keymap may specify different repeat behaviors for different keys.
@@ -1264,9 +1372,11 @@ xkb_state_update_mask(struct xkb_state *state,
* key in the given keyboard state.
*
* As an extension to XKB, this function can return more than one keysym.
- * If you do not want to handle this case, you should use
- * xkb_state_key_get_one_sym(), which additionally performs transformations
- * which are specific to the one-keysym case.
+ * If you do not want to handle this case, you can use
+ * xkb_state_key_get_one_sym() for a simpler interface.
+ *
+ * This function does not perform any @ref keysym-transformations.
+ * (This might change).
*
* @returns The number of keysyms in the syms_out array. If no keysyms
* are produced by the key in the given keyboard state, returns 0 and sets
@@ -1298,7 +1408,11 @@ xkb_state_key_get_syms(struct xkb_state *state, xkb_keycode_t key,
* You may safely pass NULL and 0 to @p buffer and @p size to find the
* required size (without the NUL-byte).
*
+ * This function performs Capitalization and Control @ref
+ * keysym-transformations.
+ *
* @memberof xkb_state
+ * @since 0.4.1
*/
int
xkb_state_key_get_utf8(struct xkb_state *state, xkb_keycode_t key,
@@ -1311,7 +1425,11 @@ xkb_state_key_get_utf8(struct xkb_state *state, xkb_keycode_t key,
* @returns The UTF-32 representation for the key, if it consists of only
* a single codepoint. Otherwise, returns 0.
*
+ * This function performs Capitalization and Control @ref
+ * keysym-transformations.
+ *
* @memberof xkb_state
+ * @since 0.4.1
*/
uint32_t
xkb_state_key_get_utf32(struct xkb_state *state, xkb_keycode_t key);
@@ -1328,6 +1446,8 @@ xkb_state_key_get_utf32(struct xkb_state *state, xkb_keycode_t key);
* @returns The keysym. If the key does not have exactly one keysym,
* returns XKB_KEY_NoSymbol
*
+ * This function performs Capitalization @ref keysym-transformations.
+ *
* @sa xkb_state_key_get_syms()
* @memberof xkb_state
*/
@@ -1378,8 +1498,8 @@ xkb_state_key_get_level(struct xkb_state *state, xkb_keycode_t key,
xkb_layout_index_t layout);
/**
- * Match flags for xkb_state_mod_indices_are_active and
- * xkb_state_mod_names_are_active, specifying how the conditions for a
+ * Match flags for xkb_state_mod_indices_are_active() and
+ * xkb_state_mod_names_are_active(), specifying the conditions for a
* successful match. XKB_STATE_MATCH_NON_EXCLUSIVE is bitmaskable with
* the other modes.
*/
@@ -1508,67 +1628,160 @@ xkb_state_mod_indices_are_active(struct xkb_state *state,
...);
/**
- * Test whether a modifier is consumed by keyboard state translation for
- * a key.
+ * @page consumed-modifiers Consumed Modifiers
+ * @parblock
*
* Some functions, like xkb_state_key_get_syms(), look at the state of
* the modifiers in the keymap and derive from it the correct shift level
* to use for the key. For example, in a US layout, pressing the key
- * labeled \<A\> while the Shift modifier is active, generates the keysym 'A'.
- * In this case, the Shift modifier is said to be consumed. However, the
- * Num Lock modifier does not affect this translation at all, even if it
- * active, so it is not consumed by this translation.
+ * labeled \<A\> while the Shift modifier is active, generates the keysym
+ * 'A'. In this case, the Shift modifier is said to be "consumed".
+ * However, the Num Lock modifier does not affect this translation at all,
+ * even if it is active, so it is not consumed by this translation.
*
* It may be desirable for some application to not reuse consumed modifiers
- * for further processing, e.g. for hotkeys or keyboard shortcuts. To
+ * for further processing, e.g. for hotkeys or keyboard shortcuts. To
* understand why, consider some requirements from a standard shortcut
* mechanism, and how they are implemented:
*
- * 1. The shortcut's modifiers must match exactly to the state. For example,
- * it is possible to bind separate actions to \<Alt\>\<Tab\> and to
- * \<Alt\>\<Shift\>\<Tab\>. Further, if only \<Alt\>\<Tab\> is bound to
- * an action, pressing \<Alt\>\<Shift\>\<Tab\> should not trigger the
- * shortcut.
+ * 1. The shortcut's modifiers must match exactly to the state. For
+ * example, it is possible to bind separate actions to \<Alt\>\<Tab\>
+ * and to \<Alt\>\<Shift\>\<Tab\>. Further, if only \<Alt\>\<Tab\> is
+ * bound to an action, pressing \<Alt\>\<Shift\>\<Tab\> should not
+ * trigger the shortcut.
* Effectively, this means that the modifiers are compared using the
* equality operator (==).
- * 2. Only relevant modifiers are considered for the matching. For example,
+ *
+ * 2. Only relevant modifiers are considered for the matching. For example,
* Caps Lock and Num Lock should not generally affect the matching, e.g.
* when matching \<Alt\>\<Tab\> against the state, it does not matter
- * whether Num Lock is active or not. These relevant, or significant,
+ * whether Num Lock is active or not. These relevant, or "significant",
* modifiers usually include Alt, Control, Shift, Super and similar.
* Effectively, this means that non-significant modifiers are masked out,
* before doing the comparison as described above.
- * 3. The matching must be independent of the layout/keymap. For example,
+ *
+ * 3. The matching must be independent of the layout/keymap. For example,
* the \<Plus\> (+) symbol is found on the first level on some layouts,
- * and requires holding Shift on others. If you simply bind the action
+ * but requires holding Shift on others. If you simply bind the action
* to the \<Plus\> keysym, it would work for the unshifted kind, but
- * not for the others, because the match against Shift would fail. If
+ * not for the others, because the match against Shift would fail. If
* you bind the action to \<Shift\>\<Plus\>, only the shifted kind would
- * work. So what is needed is to recognize that Shift is used up in the
+ * work. So what is needed is to recognize that Shift is used up in the
* translation of the keysym itself, and therefore should not be included
* in the matching.
* Effectively, this means that consumed modifiers (Shift in this example)
* are masked out as well, before doing the comparison.
*
- * To summarize, this is how the matching would be performed:
+ * In summary, this is approximately how the matching would be performed:
* @code
* (keysym == shortcut_keysym) &&
- * ((state_modifiers & ~consumed_modifiers & significant_modifiers) == shortcut_modifiers)
+ * ((state_mods & ~consumed_mods & significant_mods) == shortcut_mods)
* @endcode
*
- * @c state_modifiers are the modifiers reported by
+ * @c state_mods are the modifiers reported by
* xkb_state_mod_index_is_active() and similar functions.
- * @c consumed_modifiers are the modifiers reported by
- * xkb_state_mod_index_is_consumed().
- * @c significant_modifiers are decided upon by the application/toolkit/user;
+ * @c consumed_mods are the modifiers reported by
+ * xkb_state_mod_index_is_consumed() and similar functions.
+ * @c significant_mods are decided upon by the application/toolkit/user;
* it is up to them to decide whether these are configurable or hard-coded.
*
+ * @endparblock
+ */
+
+/**
+ * Consumed modifiers mode.
+ *
+ * There are several possible methods for deciding which modifiers are
+ * consumed and which are not, each applicable for different systems or
+ * situations. The mode selects the method to use.
+ *
+ * Keep in mind that in all methods, the keymap may decide to "preserve"
+ * a modifier, meaning it is not reported as consumed even if it would
+ * have otherwise.
+ */
+enum xkb_consumed_mode {
+ /**
+ * This is the mode defined in the XKB specification and used by libX11.
+ *
+ * A modifier is consumed if and only if it *may affect* key translation.
+ *
+ * For example, if `Control+Alt+<Backspace>` produces some assigned keysym,
+ * then when pressing just `<Backspace>`, `Control` and `Alt` are consumed,
+ * even though they are not active, since if they *were* active they would
+ * have affected key translation.
+ */
+ XKB_CONSUMED_MODE_XKB,
+ /**
+ * This is the mode used by the GTK+ toolkit.
+ *
+ * The mode consists of the following two independent heuristics:
+ *
+ * - The currently active set of modifiers, excluding modifiers which do
+ * not affect the key (as described for @ref XKB_CONSUMED_MODE_XKB), are
+ * considered consumed, if the keysyms produced when all of them are
+ * active are different from the keysyms produced when no modifiers are
+ * active.
+ *
+ * - A single modifier is considered consumed if the keysyms produced for
+ * the key when it is the only active modifier are different from the
+ * keysyms produced when no modifiers are active.
+ */
+ XKB_CONSUMED_MODE_GTK
+};
+
+/**
+ * Get the mask of modifiers consumed by translating a given key.
+ *
+ * @param state The keyboard state.
+ * @param key The keycode of the key.
+ * @param mode The consumed modifiers mode to use; see enum description.
+ *
+ * @returns a mask of the consumed modifiers.
+ *
+ * @memberof xkb_state
+ * @since 0.7.0
+ */
+xkb_mod_mask_t
+xkb_state_key_get_consumed_mods2(struct xkb_state *state, xkb_keycode_t key,
+ enum xkb_consumed_mode mode);
+
+/**
+ * Same as xkb_state_key_get_consumed_mods2() with mode XKB_CONSUMED_MODE_XKB.
+ *
+ * @memberof xkb_state
+ * @since 0.4.1
+ */
+xkb_mod_mask_t
+xkb_state_key_get_consumed_mods(struct xkb_state *state, xkb_keycode_t key);
+
+/**
+ * Test whether a modifier is consumed by keyboard state translation for
+ * a key.
+ *
+ * @param state The keyboard state.
+ * @param key The keycode of the key.
+ * @param idx The index of the modifier to check.
+ * @param mode The consumed modifiers mode to use; see enum description.
+ *
* @returns 1 if the modifier is consumed, 0 if it is not. If the modifier
* index is not valid in the keymap, returns -1.
*
* @sa xkb_state_mod_mask_remove_consumed()
* @sa xkb_state_key_get_consumed_mods()
* @memberof xkb_state
+ * @since 0.7.0
+ */
+int
+xkb_state_mod_index_is_consumed2(struct xkb_state *state,
+ xkb_keycode_t key,
+ xkb_mod_index_t idx,
+ enum xkb_consumed_mode mode);
+
+/**
+ * Same as xkb_state_mod_index_is_consumed2() with mode XKB_CONSUMED_MOD_XKB.
+ *
+ * @memberof xkb_state
+ * @since 0.4.1
*/
int
xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t key,
@@ -1577,6 +1790,8 @@ xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t key,
/**
* Remove consumed modifiers from a modifier mask for a key.
*
+ * @deprecated Use xkb_state_key_get_consumed_mods2() instead.
+ *
* Takes the given modifier mask, and removes all modifiers which are
* consumed for that particular key (as in xkb_state_mod_index_is_consumed()).
*
@@ -1588,17 +1803,6 @@ xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t key,
xkb_mod_mask_t mask);
/**
- * Get the mask of modifiers consumed by translating a given key.
- *
- * @returns a mask of the consumed modifiers.
- *
- * @sa xkb_state_mod_index_is_consumed()
- * @memberof xkb_state
- */
-xkb_mod_mask_t
-xkb_state_key_get_consumed_mods(struct xkb_state *state, xkb_keycode_t key);
-
-/**
* Test whether a layout is active in a given keyboard state by name.
*
* @returns 1 if the layout is active, 0 if it is not. If no layout with
diff --git a/src/android/jar/jar.pro b/src/android/jar/jar.pro
index 683866a345..bda15a0a00 100644
--- a/src/android/jar/jar.pro
+++ b/src/android/jar/jar.pro
@@ -19,7 +19,7 @@ JAVASOURCES += \
$$PATHPREFIX/QtNativeLibrariesDir.java \
$$PATHPREFIX/QtSurface.java \
$$PATHPREFIX/ExtractStyle.java \
- $$PATHPREFIX/EditMenu.java \
+ $$PATHPREFIX/EditContextView.java \
$$PATHPREFIX/EditPopupMenu.java \
$$PATHPREFIX/CursorHandle.java \
$$PATHPREFIX/QtThread.java
diff --git a/src/android/jar/src/org/qtproject/qt5/android/CursorHandle.java b/src/android/jar/src/org/qtproject/qt5/android/CursorHandle.java
index 4f2c06644d..788a5c2b3d 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/CursorHandle.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/CursorHandle.java
@@ -142,7 +142,6 @@ public class CursorHandle implements ViewTreeObserver.OnPreDrawListener
m_cursorView = new CursorView(context, this);
m_cursorView.setImageDrawable(drawable);
- // m_layout.addView(m_cursorView);
m_popup = new PopupWindow(context, null, android.R.attr.textSelectHandleWindowStyle);
m_popup.setSplitTouchEnabled(true);
@@ -185,6 +184,14 @@ public class CursorHandle implements ViewTreeObserver.OnPreDrawListener
m_posY = y;
}
+ public int bottom()
+ {
+ initOverlay();
+ final int[] location = new int[2];
+ m_cursorView.getLocationOnScreen(location);
+ return location[1] + m_cursorView.getHeight();
+ }
+
public void hide() {
if (m_popup != null) {
m_popup.dismiss();
diff --git a/src/android/jar/src/org/qtproject/qt5/android/EditContextView.java b/src/android/jar/src/org/qtproject/qt5/android/EditContextView.java
new file mode 100644
index 0000000000..6d9987ca2a
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt5/android/EditContextView.java
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 BogDan Vatra <bogdan@kde.org>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Android port of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+package org.qtproject.qt5.android;
+
+
+import android.content.Context;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.R;
+
+import java.util.HashMap;
+
+public class EditContextView extends LinearLayout implements View.OnClickListener
+{
+ public static final int CUT_BUTTON = 1 << 0;
+ public static final int COPY_BUTTON = 1 << 1;
+ public static final int PASTE_BUTTON = 1 << 2;
+ public static final int SALL_BUTTON = 1 << 3;
+
+ HashMap<Integer, ContextButton> m_buttons = new HashMap<Integer, ContextButton>(4);
+ OnClickListener m_onClickListener;
+
+ public interface OnClickListener
+ {
+ void contextButtonClicked(int buttonId);
+ }
+
+ private class ContextButton extends TextView
+ {
+ public int m_buttonId;
+ public ContextButton(Context context, int stringId) {
+ super(context);
+ m_buttonId = stringId;
+ setText(stringId);
+ setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT));
+ setGravity(Gravity.CENTER);
+ setTextColor(getResources().getColor(R.color.widget_edittext_dark));
+ EditContextView.this.setBackground(getResources().getDrawable(R.drawable.editbox_background_normal));
+ float scale = getResources().getDisplayMetrics().density;
+ int hPadding = (int)(16 * scale + 0.5f);
+ int vPadding = (int)(8 * scale + 0.5f);
+ setPadding(hPadding, vPadding, hPadding, vPadding);
+ setOnClickListener(EditContextView.this);
+ }
+ }
+
+ @Override
+ public void onClick(View v)
+ {
+ ContextButton button = (ContextButton)v;
+ m_onClickListener.contextButtonClicked(button.m_buttonId);
+ }
+
+ void addButton(int id)
+ {
+ ContextButton button = new ContextButton(getContext(), id);
+ m_buttons.put(id, button);
+ addView(button);
+ }
+
+ public void updateButtons(int buttonsLayout)
+ {
+ m_buttons.get(R.string.cut).setVisibility((buttonsLayout & CUT_BUTTON) != 0 ? View.VISIBLE : View.GONE);
+ m_buttons.get(R.string.copy).setVisibility((buttonsLayout & COPY_BUTTON) != 0 ? View.VISIBLE : View.GONE);
+ m_buttons.get(R.string.paste).setVisibility((buttonsLayout & PASTE_BUTTON) != 0 ? View.VISIBLE : View.GONE);
+ m_buttons.get(R.string.selectAll).setVisibility((buttonsLayout & SALL_BUTTON) != 0 ? View.VISIBLE : View.GONE);
+ }
+
+ public EditContextView(Context context, OnClickListener onClickListener) {
+ super(context);
+ m_onClickListener = onClickListener;
+ setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+
+ addButton(R.string.cut);
+ addButton(R.string.copy);
+ addButton(R.string.paste);
+ addButton(R.string.selectAll);
+ }
+}
diff --git a/src/android/jar/src/org/qtproject/qt5/android/EditMenu.java b/src/android/jar/src/org/qtproject/qt5/android/EditMenu.java
deleted file mode 100644
index afe7797914..0000000000
--- a/src/android/jar/src/org/qtproject/qt5/android/EditMenu.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com>
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the Android port of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-package org.qtproject.qt5.android;
-
-import android.view.ActionMode;
-import android.view.ActionMode.Callback;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.app.Activity;
-import android.content.Context;
-import android.content.res.TypedArray;
-
-/**
- * The edit menu actions (when there is selection)
- */
-class EditMenu implements ActionMode.Callback {
-
- private final Activity m_activity;
- private ActionMode m_actionMode;
-
- public EditMenu(Activity activity) {
- m_activity = activity;
- }
-
- @Override
- public boolean onCreateActionMode(ActionMode mode, Menu menu) {
- mode.setTitle(null);
- mode.setSubtitle(null);
- mode.setTitleOptionalHint(true);
-
- Context context = m_activity;
- int[] attrs = {
- android.R.attr.actionModeSelectAllDrawable, android.R.attr.actionModeCutDrawable,
- android.R.attr.actionModeCopyDrawable, android.R.attr.actionModePasteDrawable
- };
- TypedArray a = context.getTheme().obtainStyledAttributes(attrs);
-
- menu.add(Menu.NONE, android.R.id.selectAll, Menu.NONE, android.R.string.selectAll)
- .setIcon(a.getResourceId(0, 0))
- .setAlphabeticShortcut('a')
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
-
- menu.add(Menu.NONE, android.R.id.cut, Menu.NONE, android.R.string.cut)
- .setIcon(a.getResourceId(1, 0))
- .setAlphabeticShortcut('x')
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
-
- menu.add(Menu.NONE, android.R.id.copy, Menu.NONE, android.R.string.copy)
- .setIcon(a.getResourceId(2, 0))
- .setAlphabeticShortcut('c')
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
-
- menu.add(Menu.NONE, android.R.id.paste, Menu.NONE, android.R.string.paste)
- .setIcon(a.getResourceId(3, 0))
- .setAlphabeticShortcut('v')
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
-
- return true;
- }
-
- @Override
- public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
- return true;
- }
-
- @Override
- public void onDestroyActionMode(ActionMode mode) {
- m_actionMode = null;
- }
-
- @Override
- public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
-
- switch (item.getItemId()) {
- case android.R.id.cut:
- return QtNativeInputConnection.cut();
- case android.R.id.copy:
- return QtNativeInputConnection.copy();
- case android.R.id.paste:
- return QtNativeInputConnection.paste();
- case android.R.id.selectAll:
- return QtNativeInputConnection.selectAll();
- }
- return false;
- }
-
- public void hide()
- {
- if (m_actionMode != null) {
- m_actionMode.finish();
- }
- }
-
- public void show()
- {
- if (m_actionMode == null) {
- m_actionMode = m_activity.startActionMode(this);
- }
- }
-
- public boolean isShown()
- {
- return m_actionMode != null;
- }
-}
diff --git a/src/android/jar/src/org/qtproject/qt5/android/EditPopupMenu.java b/src/android/jar/src/org/qtproject/qt5/android/EditPopupMenu.java
index 246be1aeb2..d065cd8549 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/EditPopupMenu.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/EditPopupMenu.java
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2018 BogDan Vatra <bogdan@kde.org>
** Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com>
** Contact: http://www.qt.io/licensing/
**
@@ -55,59 +56,51 @@ import android.view.ViewTreeObserver;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewGroup;
+import android.R;
// Helper class that manages a cursor or selection handle
-public class EditPopupMenu implements ViewTreeObserver.OnPreDrawListener, OnClickListener
+public class EditPopupMenu implements ViewTreeObserver.OnPreDrawListener, EditContextView.OnClickListener
{
private View m_layout = null;
- private View m_view = null;
+ private EditContextView m_view = null;
private PopupWindow m_popup = null;
- private Activity m_activity;
private int m_posX;
private int m_posY;
+ private int m_buttons;
- public EditPopupMenu(Activity activity, View layout) {
- m_activity = activity;
+ public EditPopupMenu(Activity activity, View layout)
+ {
+ m_view = new EditContextView(activity, this);
m_layout = layout;
}
- private boolean initOverlay(){
- if (m_popup == null){
- Context context = m_layout.getContext();
- int[] attrs = { android.R.attr.textEditPasteWindowLayout };
- TypedArray a = context.getTheme().obtainStyledAttributes(attrs);
- final int layout = a.getResourceId(0, 0);
- LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- m_view = inflater.inflate(layout, null);
-
- final int size = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
- m_view.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
- ViewGroup.LayoutParams.WRAP_CONTENT));
- m_view.measure(size, size);
- m_view.setOnClickListener(this);
-
- m_popup = new PopupWindow(context, null, android.R.attr.textSelectHandleWindowStyle);
- m_popup.setSplitTouchEnabled(true);
- m_popup.setClippingEnabled(false);
- m_popup.setContentView(m_view);
- m_popup.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
- m_popup.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
-
- m_layout.getViewTreeObserver().addOnPreDrawListener(this);
- }
- return true;
+ private void initOverlay()
+ {
+ if (m_popup != null)
+ return;
+
+ Context context = m_layout.getContext();
+ m_popup = new PopupWindow(context, null, android.R.attr.textSelectHandleWindowStyle);
+ m_popup.setSplitTouchEnabled(true);
+ m_popup.setClippingEnabled(false);
+ m_popup.setContentView(m_view);
+ m_popup.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
+ m_popup.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
+
+ m_layout.getViewTreeObserver().addOnPreDrawListener(this);
}
public int getHeight()
{
- initOverlay();
return m_view.getHeight();
}
// Show the handle at a given position (or move it if it is already shown)
- public void setPosition(final int x, final int y){
+ public void setPosition(final int x, final int y, final int buttons)
+ {
initOverlay();
+ m_view.updateButtons(buttons);
final int[] location = new int[2];
m_layout.getLocationOnScreen(location);
@@ -115,9 +108,12 @@ public class EditPopupMenu implements ViewTreeObserver.OnPreDrawListener, OnClic
int y2 = y + location[1];
x2 -= m_view.getWidth() / 2 ;
+
+ if (m_layout.getWidth() < x + m_view.getWidth() / 2)
+ x2 = m_layout.getWidth() - m_view.getWidth();
+
if (x2 < 0)
x2 = 0;
- y2 -= m_view.getHeight();
if (m_popup.isShowing())
m_popup.update(x2, y2, -1, -1);
@@ -126,12 +122,13 @@ public class EditPopupMenu implements ViewTreeObserver.OnPreDrawListener, OnClic
m_posX = x;
m_posY = y;
-
+ m_buttons = buttons;
}
public void hide() {
if (m_popup != null) {
m_popup.dismiss();
+ m_popup = null;
}
}
@@ -141,15 +138,27 @@ public class EditPopupMenu implements ViewTreeObserver.OnPreDrawListener, OnClic
// For example if the keyboard appears.
// Adjust the position of the handle accordingly
if (m_popup != null && m_popup.isShowing())
- setPosition(m_posX, m_posY);
+ setPosition(m_posX, m_posY, m_buttons);
return true;
}
@Override
- public void onClick(View v) {
- QtNativeInputConnection.paste();
+ public void contextButtonClicked(int buttonId) {
+ switch (buttonId) {
+ case R.string.cut:
+ QtNativeInputConnection.cut();
+ break;
+ case R.string.copy:
+ QtNativeInputConnection.copy();
+ break;
+ case R.string.paste:
+ QtNativeInputConnection.paste();
+ break;
+ case R.string.selectAll:
+ QtNativeInputConnection.selectAll();
+ break;
+ }
hide();
}
}
-
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 fa7508921d..8f218d34f0 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
@@ -140,7 +140,6 @@ public class QtActivityDelegate
private QtEditText m_editText = null;
private InputMethodManager m_imm = null;
private boolean m_quitApp = true;
- private Process m_debuggerProcess = null; // debugger process
private View m_dummyView = null;
private boolean m_keyboardIsVisible = false;
public boolean m_backKeyPressedSent = false;
@@ -151,7 +150,6 @@ public class QtActivityDelegate
private CursorHandle m_cursorHandle;
private CursorHandle m_leftSelectionHandle;
private CursorHandle m_rightSelectionHandle;
- private EditMenu m_editMenu;
private EditPopupMenu m_editPopupMenu;
public void setFullScreen(boolean enterFullScreen)
@@ -484,77 +482,87 @@ public class QtActivityDelegate
}
// Values coming from QAndroidInputContext::CursorHandleShowMode
- private static final int CursorHandleNotShown = 0;
- private static final int CursorHandleShowNormal = 1;
- private static final int CursorHandleShowSelection = 2;
- private static final int CursorHandleShowPopup = 3;
+ private static final int CursorHandleNotShown = 0;
+ private static final int CursorHandleShowNormal = 1;
+ private static final int CursorHandleShowSelection = 2;
+ private static final int CursorHandleShowEdit = 0x100;
/* called from the C++ code when the position of the cursor or selection handles needs to
be adjusted.
mode is one of QAndroidInputContext::CursorHandleShowMode
*/
- public void updateHandles(int mode, int x1, int y1, int x2, int y2, boolean rtl)
+ public void updateHandles(int mode, int editX, int editY, int editButtons, int x1, int y1, int x2, int y2, boolean rtl)
{
- if (mode == CursorHandleNotShown) {
- if (m_cursorHandle != null)
- m_cursorHandle.hide();
- if (m_rightSelectionHandle != null) {
- m_rightSelectionHandle.hide();
- m_leftSelectionHandle.hide();
- m_rightSelectionHandle = null;
- m_leftSelectionHandle = null;
- }
- if (m_editMenu != null)
- m_editMenu.hide();
- if (m_editPopupMenu != null)
+ switch (mode & 0xff)
+ {
+ case CursorHandleNotShown:
+ if (m_cursorHandle != null) {
+ m_cursorHandle.hide();
+ m_cursorHandle = null;
+ }
+ if (m_rightSelectionHandle != null) {
+ m_rightSelectionHandle.hide();
+ m_leftSelectionHandle.hide();
+ m_rightSelectionHandle = null;
+ m_leftSelectionHandle = null;
+ }
m_editPopupMenu.hide();
- } else if (mode == CursorHandleShowNormal || mode == CursorHandleShowPopup) {
- if (m_cursorHandle == null) {
- m_cursorHandle = new CursorHandle(m_activity, m_layout, QtNative.IdCursorHandle,
- android.R.attr.textSelectHandle, false);
- }
- m_cursorHandle.setPosition(x1, y1);
- if (m_rightSelectionHandle != null) {
- m_rightSelectionHandle.hide();
- m_leftSelectionHandle.hide();
- m_rightSelectionHandle = null;
- m_leftSelectionHandle = null;
- }
- } else if (mode == CursorHandleShowSelection) {
- if (m_rightSelectionHandle == null) {
- m_leftSelectionHandle = new CursorHandle(m_activity, m_layout, QtNative.IdLeftHandle,
- !rtl ? android.R.attr.textSelectHandleLeft :
- android.R.attr.textSelectHandleRight,
- rtl);
- m_rightSelectionHandle = new CursorHandle(m_activity, m_layout, QtNative.IdRightHandle,
- !rtl ? android.R.attr.textSelectHandleRight :
- android.R.attr.textSelectHandleLeft,
- rtl);
- }
- m_leftSelectionHandle.setPosition(x1,y1);
- m_rightSelectionHandle.setPosition(x2,y2);
- if (m_cursorHandle != null)
- m_cursorHandle.hide();
-
- if (m_editMenu == null)
- m_editMenu = new EditMenu(m_activity);
- m_editMenu.show();
+ break;
+
+ case CursorHandleShowNormal:
+ if (m_cursorHandle == null) {
+ m_cursorHandle = new CursorHandle(m_activity, m_layout, QtNative.IdCursorHandle,
+ android.R.attr.textSelectHandle, false);
+ }
+ m_cursorHandle.setPosition(x1, y1);
+ if (m_rightSelectionHandle != null) {
+ m_rightSelectionHandle.hide();
+ m_leftSelectionHandle.hide();
+ m_rightSelectionHandle = null;
+ m_leftSelectionHandle = null;
+ }
+ break;
+
+ case CursorHandleShowSelection:
+ if (m_rightSelectionHandle == null) {
+ m_leftSelectionHandle = new CursorHandle(m_activity, m_layout, QtNative.IdLeftHandle,
+ !rtl ? android.R.attr.textSelectHandleLeft :
+ android.R.attr.textSelectHandleRight,
+ rtl);
+ m_rightSelectionHandle = new CursorHandle(m_activity, m_layout, QtNative.IdRightHandle,
+ !rtl ? android.R.attr.textSelectHandleRight :
+ android.R.attr.textSelectHandleLeft,
+ rtl);
+ }
+ m_leftSelectionHandle.setPosition(x1,y1);
+ m_rightSelectionHandle.setPosition(x2,y2);
+ if (m_cursorHandle != null) {
+ m_cursorHandle.hide();
+ m_cursorHandle = null;
+ }
+ mode |= CursorHandleShowEdit;
+ break;
}
- // show the edit popup menu
- if (mode == CursorHandleShowPopup && (m_editMenu == null || !m_editMenu.isShown())
- && QtNative.hasClipboardText()) {
- if (m_editPopupMenu == null)
- m_editPopupMenu = new EditPopupMenu(m_activity, m_layout);
- if (y2 < m_editPopupMenu.getHeight()) {
- // If the popup cannot be shown over the text, it must be shown under the anchors
- y2 = y1 + 2 * m_editPopupMenu.getHeight();
+ if (QtNative.hasClipboardText())
+ editButtons |= EditContextView.PASTE_BUTTON;
+ else
+ editButtons &= ~EditContextView.PASTE_BUTTON;
+
+ if ((mode & CursorHandleShowEdit) == CursorHandleShowEdit && editButtons != 0) {
+ editY -= m_editPopupMenu.getHeight();
+ if (editY < 0) {
+ if (m_cursorHandle != null)
+ editY = m_cursorHandle.bottom();
+ else if (m_leftSelectionHandle != null && m_rightSelectionHandle != null)
+ editY = Math.max(m_leftSelectionHandle.bottom(), m_rightSelectionHandle.bottom());
+ else
+ return;
}
- m_editPopupMenu.setPosition(x2, y2);
- } else if (m_editPopupMenu != null) {
+ m_editPopupMenu.setPosition(editX, editY, editButtons);
+ } else {
m_editPopupMenu.hide();
}
-
}
public boolean loadApplication(Activity activity, ClassLoader classLoader, Bundle loaderParams)
@@ -658,70 +666,6 @@ public class QtActivityDelegate
return true;
}
- public static void debugLog(String msg)
- {
- Log.i(QtNative.QtTAG, "DEBUGGER: " + msg);
- }
-
- private class DebugWaitRunnable implements Runnable {
-
- public DebugWaitRunnable(String pingPongSocket) throws IOException {
- socket = new LocalServerSocket(pingPongSocket);
- }
-
- public boolean wasFailure;
- private LocalServerSocket socket;
-
- public void run() {
- final int napTime = 200; // milliseconds between file accesses
- final int timeOut = 30000; // ms until we give up on ping and pong
- final int maxAttempts = timeOut / napTime;
-
- DataOutputStream outToClient = null;
- try {
- LocalSocket connectionFromClient = socket.accept();
- debugLog("Debug socket accepted");
- BufferedReader inFromClient =
- new BufferedReader(new InputStreamReader(connectionFromClient.getInputStream()));
- outToClient = new DataOutputStream(connectionFromClient.getOutputStream());
- outToClient.writeBytes("" + android.os.Process.myPid());
-
- for (int i = 0; i < maxAttempts; i++) {
- String clientData = inFromClient.readLine();
- debugLog("Incoming socket " + clientData);
- if (!clientData.isEmpty())
- break;
-
- if (connectionFromClient.isClosed()) {
- wasFailure = true;
- break;
- }
- Thread.sleep(napTime);
- }
- } catch (IOException ioEx) {
- ioEx.printStackTrace();
- wasFailure = true;
- Log.e(QtNative.QtTAG,"Can't start debugger" + ioEx.getMessage());
- } catch (InterruptedException interruptEx) {
- wasFailure = true;
- Log.e(QtNative.QtTAG,"Can't start debugger" + interruptEx.getMessage());
- } finally {
- try {
- if (outToClient != null)
- outToClient.close();
- } catch (IOException ignored) { }
- }
- }
-
- public void shutdown() throws IOException
- {
- wasFailure = true;
- try {
- socket.close();
- } catch (IOException ignored) { }
- }
- };
-
public boolean startApplication()
{
// start application
@@ -730,170 +674,6 @@ public class QtActivityDelegate
Bundle extras = m_activity.getIntent().getExtras();
if (extras != null) {
try {
- final String dc = "--Added-by-androiddeployqt--/debugger.command";
- String debuggerCommand =
- new BufferedReader(new InputStreamReader(m_activity.getAssets().open(dc))).readLine();
- if ( /*(ai.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0
- &&*/ extras.containsKey("debug_ping")
- && extras.getString("debug_ping").equals("true")) {
- try {
- String packagePath =
- m_activity.getPackageManager().getApplicationInfo(m_activity.getPackageName(),
- PackageManager.GET_CONFIGURATIONS).dataDir + "/";
-
- debugLog("extra parameters: " + extras);
- String packageName = m_activity.getPackageName();
- String pingFile = extras.getString("ping_file");
- String pongFile = extras.getString("pong_file");
- String gdbserverSocket = extras.getString("gdbserver_socket");
- String gdbserverCommand = packagePath + debuggerCommand + gdbserverSocket;
- String pingSocket = extras.getString("ping_socket");
- boolean usePing = pingFile != null;
- boolean usePong = pongFile != null;
- boolean useSocket = gdbserverSocket != null;
- boolean usePingSocket = pingSocket != null;
- int napTime = 200; // milliseconds between file accesses
- int timeOut = 30000; // ms until we give up on ping and pong
- int maxAttempts = timeOut / napTime;
-
- if (gdbserverSocket != null) {
- debugLog("removing gdb socket " + gdbserverSocket);
- new File(gdbserverSocket).delete();
- }
-
- if (usePing) {
- debugLog("removing ping file " + pingFile);
- File ping = new File(pingFile);
- if (ping.exists()) {
- if (!ping.delete())
- debugLog("ping file cannot be deleted");
- }
- }
-
- if (usePong) {
- debugLog("removing pong file " + pongFile);
- File pong = new File(pongFile);
- if (pong.exists()) {
- if (!pong.delete())
- debugLog("pong file cannot be deleted");
- }
- }
-
- debugLog("starting " + gdbserverCommand);
- m_debuggerProcess = Runtime.getRuntime().exec(gdbserverCommand);
- debugLog("gdbserver started");
-
- if (useSocket) {
- int i;
- for (i = 0; i < maxAttempts; ++i) {
- debugLog("waiting for socket at " + gdbserverSocket + ", attempt " + i);
- File file = new File(gdbserverSocket);
- if (file.exists()) {
- file.setReadable(true, false);
- file.setWritable(true, false);
- file.setExecutable(true, false);
- break;
- }
- Thread.sleep(napTime);
- }
-
- if (i == maxAttempts) {
- debugLog("time out when waiting for debug socket");
- return false;
- }
-
- debugLog("socket ok");
- } else {
- debugLog("socket not used");
- }
-
- if (usePingSocket) {
- DebugWaitRunnable runnable = new DebugWaitRunnable(pingSocket);
- Thread waitThread = new Thread(runnable);
- waitThread.start();
-
- int i;
- for (i = 0; i < maxAttempts && waitThread.isAlive(); ++i) {
- debugLog("Waiting for debug socket connect");
- debugLog("go to sleep");
- Thread.sleep(napTime);
- }
-
- if (i == maxAttempts) {
- debugLog("time out when waiting for ping socket");
- runnable.shutdown();
- return false;
- }
-
- if (runnable.wasFailure) {
- debugLog("Could not connect to debug client");
- return false;
- } else {
- debugLog("Got pid acknowledgment");
- }
- }
-
- if (usePing) {
- // Tell we are ready.
- debugLog("writing ping at " + pingFile);
- FileWriter writer = new FileWriter(pingFile);
- writer.write("" + android.os.Process.myPid());
- writer.close();
- File file = new File(pingFile);
- file.setReadable(true, false);
- file.setWritable(true, false);
- file.setExecutable(true, false);
- debugLog("wrote ping");
- } else {
- debugLog("ping not requested");
- }
-
- // Wait until other side is ready.
- if (usePong) {
- int i;
- for (i = 0; i < maxAttempts; ++i) {
- debugLog("waiting for pong at " + pongFile + ", attempt " + i);
- File file = new File(pongFile);
- if (file.exists()) {
- file.delete();
- break;
- }
- debugLog("go to sleep");
- Thread.sleep(napTime);
- }
- debugLog("Removing pingFile " + pingFile);
- new File(pingFile).delete();
-
- if (i == maxAttempts) {
- debugLog("time out when waiting for pong file");
- return false;
- }
-
- debugLog("got pong " + pongFile);
- } else {
- debugLog("pong not requested");
- }
-
- } catch (IOException ioe) {
- ioe.printStackTrace();
- } catch (SecurityException se) {
- se.printStackTrace();
- }
- }
-
- if (/*(ai.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0
- &&*/ extras.containsKey("qml_debug")
- && extras.getString("qml_debug").equals("true")) {
- String qmljsdebugger;
- if (extras.containsKey("qmljsdebugger")) {
- qmljsdebugger = extras.getString("qmljsdebugger");
- qmljsdebugger.replaceAll("\\s", ""); // remove whitespace for security
- } else {
- qmljsdebugger = "port:3768";
- }
- m_applicationParameters += "\t-qmljsdebugger=" + qmljsdebugger;
- }
-
if (extras.containsKey("extraenvvars")) {
try {
m_environmentVariables += "\t" + new String(Base64.decode(extras.getString("extraenvvars"), Base64.DEFAULT), "UTF-8");
@@ -1008,6 +788,7 @@ public class QtActivityDelegate
return true;
}
});
+ m_editPopupMenu = new EditPopupMenu(m_activity, m_layout);
}
public void hideSplashScreen()
@@ -1081,8 +862,6 @@ public class QtActivityDelegate
if (m_quitApp) {
QtNative.terminateQt();
QtNative.setActivity(null, null);
- if (m_debuggerProcess != null)
- m_debuggerProcess.destroy();
QtNative.m_qtThread.exit();
System.exit(0);
}
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 3db3453263..61f6afe85d 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
@@ -469,10 +469,11 @@ public class QtNative
case MotionEvent.TOOL_TYPE_ERASER:
pointerType = 3; // QTabletEvent::Eraser
break;
- // TODO TOOL_TYPE_MOUSE
}
- if (m_tabletEventSupported && pointerType != 0) {
+ if (event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE) {
+ sendMouseEvent(event, id);
+ } else if (m_tabletEventSupported && pointerType != 0) {
tabletEvent(id, event.getDeviceId(), event.getEventTime(), event.getAction(), pointerType,
event.getButtonState(), event.getX(), event.getY(), event.getPressure());
} else {
@@ -507,7 +508,22 @@ public class QtNative
static public void sendTrackballEvent(MotionEvent event, int id)
{
- switch (event.getAction()) {
+ sendMouseEvent(event,id);
+ }
+
+ static public boolean sendGenericMotionEvent(MotionEvent event, int id)
+ {
+ if (((event.getAction() & (MotionEvent.ACTION_SCROLL | MotionEvent.ACTION_HOVER_MOVE)) == 0)
+ || (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != InputDevice.SOURCE_CLASS_POINTER) {
+ return false;
+ }
+
+ return sendMouseEvent(event, id);
+ }
+
+ static public boolean sendMouseEvent(MotionEvent event, int id)
+ {
+ switch (event.getActionMasked()) {
case MotionEvent.ACTION_UP:
mouseUp(id, (int) event.getX(), (int) event.getY());
break;
@@ -517,28 +533,27 @@ public class QtNative
m_oldx = (int) event.getX();
m_oldy = (int) event.getY();
break;
-
+ case MotionEvent.ACTION_HOVER_MOVE:
case MotionEvent.ACTION_MOVE:
- int dx = (int) (event.getX() - m_oldx);
- int dy = (int) (event.getY() - m_oldy);
- if (Math.abs(dx) > 5 || Math.abs(dy) > 5) {
+ if (event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE) {
+ mouseMove(id, (int) event.getX(), (int) event.getY());
+ } else {
+ int dx = (int) (event.getX() - m_oldx);
+ int dy = (int) (event.getY() - m_oldy);
+ if (Math.abs(dx) > 5 || Math.abs(dy) > 5) {
mouseMove(id, (int) event.getX(), (int) event.getY());
m_oldx = (int) event.getX();
m_oldy = (int) event.getY();
+ }
}
break;
+ case MotionEvent.ACTION_SCROLL:
+ mouseWheel(id, (int) event.getX(), (int) event.getY(),
+ event.getAxisValue(MotionEvent.AXIS_HSCROLL), event.getAxisValue(MotionEvent.AXIS_VSCROLL));
+ break;
+ default:
+ return false;
}
- }
-
- static public boolean sendGenericMotionEvent(MotionEvent event, int id)
- {
- if (event.getActionMasked() != MotionEvent.ACTION_SCROLL
- || (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != InputDevice.SOURCE_CLASS_POINTER) {
- return false;
- }
-
- mouseWheel(id, (int) event.getX(), (int) event.getY(),
- event.getAxisValue(MotionEvent.AXIS_HSCROLL), event.getAxisValue(MotionEvent.AXIS_VSCROLL));
return true;
}
@@ -585,6 +600,9 @@ public class QtNative
}
private static void updateHandles(final int mode,
+ final int editX,
+ final int editY,
+ final int editButtons,
final int x1,
final int y1,
final int x2,
@@ -594,7 +612,7 @@ public class QtNative
runAction(new Runnable() {
@Override
public void run() {
- m_activityDelegate.updateHandles(mode, x1, y1, x2, y2, rtl);
+ m_activityDelegate.updateHandles(mode, editX, editY, editButtons, x1, y1, x2, y2, rtl);
}
});
}
diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java
index fc3d7e04ce..7826527918 100644
--- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java
+++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java
@@ -46,6 +46,7 @@ import android.content.ServiceConnection;
import android.content.pm.ComponentInfo;
import android.content.pm.PackageInfo;
import android.content.res.AssetManager;
+import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
@@ -651,15 +652,26 @@ public abstract class QtLoader {
String themePath = m_context.getApplicationInfo().dataDir + "/qt-reserved-files/android-style/";
String stylePath = themePath + m_displayDensity + "/";
- String extractOption = "full";
+ String extractOption = "default";
if (m_contextInfo.metaData.containsKey("android.app.extract_android_style")) {
extractOption = m_contextInfo.metaData.getString("android.app.extract_android_style");
- if (!extractOption.equals("full") && !extractOption.equals("minimal") && !extractOption.equals("none")) {
- Log.e(QtApplication.QtTAG, "Invalid extract_android_style option \"" + extractOption + "\", defaulting to full");
- extractOption = "full";
+ if (!extractOption.equals("default") && !extractOption.equals("full") && !extractOption.equals("minimal") && !extractOption.equals("none")) {
+ Log.e(QtApplication.QtTAG, "Invalid extract_android_style option \"" + extractOption + "\", defaulting to \"default\"");
+ extractOption = "default";
}
}
+ // QTBUG-69810: The extraction code will trigger compatibility warnings on Android SDK version >= 28
+ // when the target SDK version is set to something lower then 28, so default to "none" and issue a warning
+ // if that is the case.
+ if (extractOption.equals("default")) {
+ final int targetSdkVersion = m_context.getApplicationInfo().targetSdkVersion;
+ if (targetSdkVersion < 28 && Build.VERSION.SDK_INT >= 28) {
+ Log.e(QtApplication.QtTAG, "extract_android_style option set to \"none\" when targetSdkVersion is less then 28");
+ extractOption = "none";
+ }
+ }
+
if (!(new File(stylePath)).exists() && !extractOption.equals("none")) {
loaderParams.putString(EXTRACT_STYLE_KEY, stylePath);
loaderParams.putBoolean(EXTRACT_STYLE_MINIMAL_KEY, extractOption.equals("minimal"));
diff --git a/src/android/templates/AndroidManifest.xml b/src/android/templates/AndroidManifest.xml
index 62e9d0f11c..966ce23b14 100644
--- a/src/android/templates/AndroidManifest.xml
+++ b/src/android/templates/AndroidManifest.xml
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<manifest package="org.qtproject.example" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
<application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="-- %%INSERT_APP_NAME%% --">
- <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation"
+ <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density"
android:name="org.qtproject.qt5.android.bindings.QtActivity"
android:label="-- %%INSERT_APP_NAME%% --"
android:screenOrientation="unspecified"
@@ -57,11 +57,12 @@
<!-- extract android style -->
<!-- available android:values :
+ * default - In most cases this will be the same as "full", but it can also be something else if needed, e.g., for compatibility reasons
* full - useful QWidget & Quick Controls 1 apps
* minimal - useful for Quick Controls 2 apps, it is much faster than "full"
* none - useful for apps that don't use any of the above Qt modules
-->
- <meta-data android:name="android.app.extract_android_style" android:value="full"/>
+ <meta-data android:name="android.app.extract_android_style" android:value="default"/>
<!-- extract android style -->
</activity>
@@ -69,7 +70,7 @@
</application>
- <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="16"/>
+ <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="28"/>
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
diff --git a/src/android/templates/build.gradle b/src/android/templates/build.gradle
index 3a3e0cd165..bf5ce1388a 100644
--- a/src/android/templates/build.gradle
+++ b/src/android/templates/build.gradle
@@ -1,17 +1,17 @@
buildscript {
repositories {
+ google()
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.2.3'
+ classpath 'com.android.tools.build:gradle:3.2.0'
}
}
-allprojects {
- repositories {
- jcenter()
- }
+repositories {
+ google()
+ jcenter()
}
apply plugin: 'com.android.application'
diff --git a/src/angle/patches/0001-ANGLE-Improve-Windows-Phone-Support.patch b/src/angle/patches/0001-ANGLE-Improve-Windows-Phone-Support.patch
deleted file mode 100644
index e8f11b5172..0000000000
--- a/src/angle/patches/0001-ANGLE-Improve-Windows-Phone-Support.patch
+++ /dev/null
@@ -1,464 +0,0 @@
-From bbc3a5f89821030dd2772cd8015070a3da9ad57e Mon Sep 17 00:00:00 2001
-From: Oliver Wolff <oliver.wolff@theqtcompany.com>
-Date: Mon, 29 Feb 2016 11:09:24 +0100
-Subject: [PATCH 1/7] ANGLE: Improve Windows Phone Support
-
-This contains compile fixes for Windows Phone as well as improved
-orientation handling.
-
-Change-Id: I5011e9980957ff0797db179b36c3be9cac6df497
----
- src/3rdparty/angle/src/common/platform.h | 2 ++
- .../renderer/d3d/d3d11/DebugAnnotator11.cpp | 2 +-
- .../src/libANGLE/renderer/d3d/d3d11/NativeWindow.h | 4 +++
- .../src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp | 8 ++++-
- .../libANGLE/renderer/d3d/d3d11/SwapChain11.cpp | 40 ++++++++++++++++++++++
- .../d3d/d3d11/winrt/CoreWindowNativeWindow.cpp | 33 ++++++++++++++++--
- .../d3d/d3d11/winrt/CoreWindowNativeWindow.h | 35 ++++++++++++++++++-
- .../d3d/d3d11/winrt/InspectableNativeWindow.cpp | 12 +++++++
- .../d3d/d3d11/winrt/InspectableNativeWindow.h | 14 +++++++-
- src/3rdparty/angle/src/libANGLE/validationEGL.cpp | 4 ++-
- .../src/third_party/systeminfo/SystemInfo.cpp | 4 +--
- 11 files changed, 148 insertions(+), 10 deletions(-)
-
-diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h
-index 56db297..4e3851c 100644
---- a/src/3rdparty/angle/src/common/platform.h
-+++ b/src/3rdparty/angle/src/common/platform.h
-@@ -68,7 +68,9 @@
- # if defined(ANGLE_ENABLE_WINDOWS_STORE)
- # include <dxgi1_3.h>
- # if defined(_DEBUG)
-+# if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
- # include <DXProgrammableCapture.h>
-+# endif
- # include <dxgidebug.h>
- # endif
- # endif
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
-index f9d28e8..2e42859 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
-@@ -77,7 +77,7 @@ bool DebugAnnotator11::getStatus()
- }
-
- return true; // Default if initializeDevice() failed
--#elif defined(_DEBUG)
-+#elif defined(_DEBUG) && (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
- static bool underCapture = true;
-
- // ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
-index f28ce4f..1c94538 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
-@@ -54,6 +54,7 @@ namespace rx
- class NativeWindow
- {
- public:
-+ enum RotationFlags { RotateNone = 0, RotateLeft = 1, RotateRight = 2 };
- explicit NativeWindow(EGLNativeWindowType window,
- const egl::Config *config,
- bool directComposition);
-@@ -62,6 +63,9 @@ class NativeWindow
- bool initialize();
- bool getClientRect(LPRECT rect);
- bool isIconic();
-+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
-+ RotationFlags rotationFlags() const;
-+#endif
- static bool isValidNativeWindow(EGLNativeWindowType window);
-
- HRESULT createSwapChain(ID3D11Device* device, DXGIFactory* factory,
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
-index f7757df..03159bb 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
-@@ -10,7 +10,9 @@
-
- #include <EGL/eglext.h>
- #include <sstream>
-+#if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
- #include <VersionHelpers.h>
-+#endif
-
- #include "common/tls.h"
- #include "common/utilities.h"
-@@ -445,7 +447,11 @@ Renderer11::Renderer11(egl::Display *display)
- }
- }
-
-+#if defined(ANGLE_ENABLE_WINDOWS_STORE)
-+ if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9)
-+#else
- if (requestedMajorVersion == 9 && requestedMinorVersion == 3)
-+#endif
- {
- mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3);
- }
-@@ -946,12 +952,12 @@ egl::ConfigSet Renderer11::generateConfigs() const
- config.bindToTextureRGBA = (colorBufferFormatInfo.format == GL_RGBA ||
- colorBufferFormatInfo.format == GL_BGRA_EXT);
- config.colorBufferType = EGL_RGB_BUFFER;
-- config.configCaveat = EGL_NONE;
- config.configID = static_cast<EGLint>(configs.size() + 1);
- // Can only support a conformant ES2 with feature level greater than 10.0.
- config.conformant = (mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0)
- ? (EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR)
- : 0;
-+ config.configCaveat = config.conformant == EGL_NONE ? EGL_NON_CONFORMANT_CONFIG : EGL_NONE;
-
- // PresentPathFast may not be conformant
- if (mPresentPathFastEnabled)
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
-index a56d3fa..9432a7f 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
-@@ -222,8 +222,14 @@ EGLint SwapChain11::resetOffscreenColorBuffer(int backbufferWidth, int backbuffe
- const bool useSharedResource = !mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport();
-
- D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
-+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
-+ const int textureLength = std::max(backbufferWidth, backbufferHeight);
-+ offscreenTextureDesc.Width = textureLength;
-+ offscreenTextureDesc.Height = textureLength;
-+#else
- offscreenTextureDesc.Width = backbufferWidth;
- offscreenTextureDesc.Height = backbufferHeight;
-+#endif
- offscreenTextureDesc.Format = backbufferFormatInfo.texFormat;
- offscreenTextureDesc.MipLevels = 1;
- offscreenTextureDesc.ArraySize = 1;
-@@ -336,8 +342,14 @@ EGLint SwapChain11::resetOffscreenDepthBuffer(int backbufferWidth, int backbuffe
- d3d11::GetTextureFormatInfo(mDepthBufferFormat, mRenderer->getRenderer11DeviceCaps());
-
- D3D11_TEXTURE2D_DESC depthStencilTextureDesc;
-+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
-+ const int textureLength = std::max(backbufferWidth, backbufferHeight);
-+ depthStencilTextureDesc.Width = textureLength;
-+ depthStencilTextureDesc.Height = textureLength;
-+#else
- depthStencilTextureDesc.Width = backbufferWidth;
- depthStencilTextureDesc.Height = backbufferHeight;
-+#endif
- depthStencilTextureDesc.Format = depthBufferFormatInfo.texFormat;
- depthStencilTextureDesc.MipLevels = 1;
- depthStencilTextureDesc.ArraySize = 1;
-@@ -422,6 +434,7 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
- return EGL_SUCCESS;
- }
-
-+#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
- // Can only call resize if we have already created our swap buffer and resources
- ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView && mBackBufferSRView);
-
-@@ -479,6 +492,12 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
- mFirstSwap = true;
-
- return resetOffscreenBuffers(backbufferWidth, backbufferHeight);
-+#else
-+ // Do nothing on Windows Phone apart from updating the internal buffer/width height
-+ mWidth = backbufferWidth;
-+ mHeight = backbufferHeight;
-+ return EGL_SUCCESS;
-+#endif
- }
-
- DXGI_FORMAT SwapChain11::getSwapChainNativeFormat() const
-@@ -704,6 +723,21 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width,
- float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
- float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f;
-
-+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
-+ const float dim = std::max(mWidth, mHeight);
-+ float u1 = x / dim;
-+ float v1 = y / dim;
-+ float u2 = (x + width) / dim;
-+ float v2 = (y + height) / dim;
-+
-+ const NativeWindow::RotationFlags flags = mNativeWindow.rotationFlags();
-+ const bool rotateL = flags == NativeWindow::RotateLeft;
-+ const bool rotateR = flags == NativeWindow::RotateRight;
-+ d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, rotateL ? u2 : u1, rotateR ? v2 : v1);
-+ d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, rotateR ? u2 : u1, rotateL ? v1 : v2);
-+ d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, rotateR ? u1 : u2, rotateL ? v2 : v1);
-+ d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, rotateL ? u1 : u2, rotateR ? v1 : v2);
-+#else
- float u1 = x / float(mWidth);
- float v1 = y / float(mHeight);
- float u2 = (x + width) / float(mWidth);
-@@ -723,6 +757,7 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width,
- d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2);
- d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
- d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2);
-+#endif
-
- deviceContext->Unmap(mQuadVB, 0);
-
-@@ -752,8 +787,13 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width,
- D3D11_VIEWPORT viewport;
- viewport.TopLeftX = 0;
- viewport.TopLeftY = 0;
-+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
-+ viewport.Width = (rotateL || rotateR) ? mHeight : mWidth;
-+ viewport.Height = (rotateL || rotateR) ? mWidth : mHeight;
-+#else
- viewport.Width = static_cast<FLOAT>(mWidth);
- viewport.Height = static_cast<FLOAT>(mHeight);
-+#endif
- viewport.MinDepth = 0.0f;
- viewport.MaxDepth = 1.0f;
- deviceContext->RSSetViewports(1, &viewport);
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
-index 71f0e42..6a4795a 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
-@@ -8,8 +8,6 @@
-
- #include "libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h"
-
--#include <windows.graphics.display.h>
--
- using namespace ABI::Windows::Foundation::Collections;
-
- namespace rx
-@@ -21,6 +19,7 @@ CoreWindowNativeWindow::~CoreWindowNativeWindow()
-
- bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet)
- {
-+ mOrientationChangedEventToken.value = 0;
- ComPtr<IPropertySet> props = propertySet;
- ComPtr<IInspectable> win = window;
- SIZE swapChainSize = {};
-@@ -100,6 +99,16 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet
-
- if (SUCCEEDED(result))
- {
-+ ComPtr<ABI::Windows::Graphics::Display::IDisplayInformationStatics> displayInformation;
-+ result = GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayInformation).Get(), &displayInformation);
-+ if (SUCCEEDED(result))
-+ {
-+ result = displayInformation->GetForCurrentView(&mDisplayInformation);
-+ }
-+ }
-+
-+ if (SUCCEEDED(result))
-+ {
- mNewClientRect = mClientRect;
- mClientRectChanged = false;
- return registerForSizeChangeEvents();
-@@ -117,6 +126,15 @@ bool CoreWindowNativeWindow::registerForSizeChangeEvents()
- result = mCoreWindow->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken);
- }
-
-+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
-+ ComPtr<IDisplayOrientationEventHandler> orientationChangedHandler;
-+ result = sizeChangedHandler.As(&orientationChangedHandler);
-+ if (SUCCEEDED(result))
-+ {
-+ result = mDisplayInformation->add_OrientationChanged(orientationChangedHandler.Get(), &mOrientationChangedEventToken);
-+ }
-+#endif
-+
- if (SUCCEEDED(result))
- {
- return true;
-@@ -131,7 +149,16 @@ void CoreWindowNativeWindow::unregisterForSizeChangeEvents()
- {
- (void)mCoreWindow->remove_SizeChanged(mSizeChangedEventToken);
- }
-+
-+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
-+ if (mDisplayInformation)
-+ {
-+ (void)mDisplayInformation->remove_OrientationChanged(mOrientationChangedEventToken);
-+ }
-+#endif
-+
- mSizeChangedEventToken.value = 0;
-+ mOrientationChangedEventToken.value = 0;
- }
-
- HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device,
-@@ -168,7 +195,7 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device,
- if (SUCCEEDED(result))
- {
-
--#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
-+#if 0 //(WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) // Qt: allow Windows Phone to resize, but don't modify the backing texture in the swap chain.
- // Test if swapchain supports resize. On Windows Phone devices, this will return DXGI_ERROR_UNSUPPORTED. On
- // other devices DXGI_ERROR_INVALID_CALL should be returned because the combination of flags passed
- // (DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) are invalid flag combinations.
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h
-index 7747005..4de235a 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h
-@@ -12,8 +12,10 @@
- #include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h"
-
- #include <memory>
-+#include <windows.graphics.display.h>
-
- typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowSizeChangedEventArgs_t IWindowSizeChangedEventHandler;
-+typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CGraphics__CDisplay__CDisplayInformation_IInspectable_t IDisplayOrientationEventHandler;
-
- namespace rx
- {
-@@ -42,11 +44,13 @@ class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enabl
- private:
- ComPtr<ABI::Windows::UI::Core::ICoreWindow> mCoreWindow;
- ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap;
-+ ComPtr<ABI::Windows::Graphics::Display::IDisplayInformation> mDisplayInformation;
-+ EventRegistrationToken mOrientationChangedEventToken;
- };
-
- [uuid(7F924F66-EBAE-40E5-A10B-B8F35E245190)]
- class CoreWindowSizeChangedHandler :
-- public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, IWindowSizeChangedEventHandler>
-+ public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, IWindowSizeChangedEventHandler, IDisplayOrientationEventHandler>
- {
- public:
- CoreWindowSizeChangedHandler() { }
-@@ -78,6 +82,35 @@ class CoreWindowSizeChangedHandler :
- return S_OK;
- }
-
-+ IFACEMETHOD(Invoke)(ABI::Windows::Graphics::Display::IDisplayInformation *displayInformation, IInspectable *)
-+ {
-+ #if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
-+ NativeWindow::RotationFlags flags = NativeWindow::RotateNone;
-+ ABI::Windows::Graphics::Display::DisplayOrientations orientation;
-+ if (SUCCEEDED(displayInformation->get_CurrentOrientation(&orientation)))
-+ {
-+ switch (orientation)
-+ {
-+ case ABI::Windows::Graphics::Display::DisplayOrientations_Landscape:
-+ flags = NativeWindow::RotateLeft;
-+ break;
-+ case ABI::Windows::Graphics::Display::DisplayOrientations_LandscapeFlipped:
-+ flags = NativeWindow::RotateRight;
-+ break;
-+ default:
-+ break;
-+ }
-+ }
-+ std::shared_ptr<InspectableNativeWindow> host = mHost.lock();
-+ if (host)
-+ {
-+ host->setRotationFlags(flags);
-+ }
-+ #endif
-+ return S_OK;
-+ }
-+
-+
- private:
- std::weak_ptr<InspectableNativeWindow> mHost;
- };
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
-index 47a6dae..c9b203e 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
-@@ -80,6 +80,18 @@ bool NativeWindow::getClientRect(RECT *rect)
- return false;
- }
-
-+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
-+NativeWindow::RotationFlags NativeWindow::rotationFlags() const
-+{
-+ if (mImpl)
-+ {
-+ return mImpl->rotationFlags();
-+ }
-+
-+ return NativeWindow::RotateNone;
-+}
-+#endif
-+
- bool NativeWindow::isIconic()
- {
- return false;
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h
-index 4b9cf80..70e5fe7 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h
-@@ -36,7 +36,8 @@ class InspectableNativeWindow
- mSwapChainScale(1.0f),
- mClientRectChanged(false),
- mClientRect({0,0,0,0}),
-- mNewClientRect({0,0,0,0})
-+ mNewClientRect({0,0,0,0}),
-+ mRotationFlags(NativeWindow::RotateNone)
- {
- mSizeChangedEventToken.value = 0;
- }
-@@ -94,6 +95,16 @@ class InspectableNativeWindow
- }
- }
-
-+ NativeWindow::RotationFlags rotationFlags() const
-+ {
-+ return mRotationFlags;
-+ }
-+
-+ void setRotationFlags(NativeWindow::RotationFlags flags)
-+ {
-+ mRotationFlags = flags;
-+ }
-+
- protected:
- virtual HRESULT scaleSwapChain(const SIZE &windowSize, const RECT &clientRect) = 0;
-
-@@ -104,6 +115,7 @@ class InspectableNativeWindow
- RECT mClientRect;
- RECT mNewClientRect;
- bool mClientRectChanged;
-+ NativeWindow::RotationFlags mRotationFlags;
-
- EventRegistrationToken mSizeChangedEventToken;
- };
-diff --git a/src/3rdparty/angle/src/libANGLE/validationEGL.cpp b/src/3rdparty/angle/src/libANGLE/validationEGL.cpp
-index bff3c94..972f6a7 100644
---- a/src/3rdparty/angle/src/libANGLE/validationEGL.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/validationEGL.cpp
-@@ -269,7 +269,7 @@ Error ValidateCreateContext(Display *display, Config *configuration, gl::Context
- return Error(EGL_BAD_CONFIG);
- }
-
-- if (clientMajorVersion == 3 && !(configuration->conformant & EGL_OPENGL_ES3_BIT_KHR))
-+ if (clientMajorVersion == 3 && !(configuration->conformant & EGL_OPENGL_ES3_BIT_KHR) && !(configuration->configCaveat & EGL_NON_CONFORMANT_CONFIG))
- {
- return Error(EGL_BAD_CONFIG);
- }
-@@ -496,6 +496,7 @@ Error ValidateCreatePbufferSurface(Display *display, Config *config, const Attri
- return Error(EGL_BAD_MATCH);
- }
-
-+#if !defined(ANGLE_ENABLE_WINDOWS_STORE) // On Windows Store, we know the originating texture came from D3D11, so bypass this check
- const Caps &caps = display->getCaps();
-
- EGLenum textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
-@@ -519,6 +520,7 @@ Error ValidateCreatePbufferSurface(Display *display, Config *config, const Attri
- {
- return Error(EGL_BAD_MATCH);
- }
-+#endif
-
- return Error(EGL_SUCCESS);
- }
-diff --git a/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.cpp b/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.cpp
-index 97dfcaa..e082895 100644
---- a/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.cpp
-+++ b/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.cpp
-@@ -26,7 +26,7 @@
- #include <windows.h>
- #include "common/platform.h"
-
--#if _WIN32_WINNT_WINBLUE
-+#if _WIN32_WINNT_WINBLUE && WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
- #include <versionhelpers.h>
- #endif
-
---
-2.7.0.windows.1
-
diff --git a/src/angle/patches/0001-ANGLE-Use-pixel-sizes-in-the-XAML-swap-chain.patch b/src/angle/patches/0001-ANGLE-Use-pixel-sizes-in-the-XAML-swap-chain.patch
new file mode 100644
index 0000000000..618ad08b4b
--- /dev/null
+++ b/src/angle/patches/0001-ANGLE-Use-pixel-sizes-in-the-XAML-swap-chain.patch
@@ -0,0 +1,135 @@
+From b1f0b50c19ec17df554faa1335d2b989e262b831 Mon Sep 17 00:00:00 2001
+From: Oliver Wolff <oliver.wolff@qt.io>
+Date: Wed, 22 Aug 2018 09:21:04 +0200
+Subject: [PATCH 1/8] ANGLE: Use pixel sizes in the XAML swap chain
+
+This is necessary for Qt applications, as they render to GL in physical
+pixels. This is consistent with the CoreWindow swap chain behavior.
+
+In order to achieve proper scaling, the scale factor has to be initialized
+properly in InspectableNativeWindow.
+
+This change only affects Windows Runtime targets.
+
+Change-Id: I92a365f33752ed49c960e390bbf89cc33ccc8004
+---
+ .../d3d/d3d11/winrt/CoreWindowNativeWindow.cpp | 23 -------------------
+ .../d3d/d3d11/winrt/CoreWindowNativeWindow.h | 2 --
+ .../d3d/d3d11/winrt/InspectableNativeWindow.cpp | 26 +++++++++++++++++++---
+ .../d3d/d3d11/winrt/InspectableNativeWindow.h | 7 +++++-
+ 4 files changed, 29 insertions(+), 29 deletions(-)
+
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
+index dd37ace87e..1ef90e7b09 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
+@@ -205,27 +205,4 @@ HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWind
+
+ return result;
+ }
+-
+-static float GetLogicalDpi()
+-{
+- ComPtr<ABI::Windows::Graphics::Display::IDisplayPropertiesStatics> displayProperties;
+-
+- if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), displayProperties.GetAddressOf())))
+- {
+- float dpi = 96.0f;
+- if (SUCCEEDED(displayProperties->get_LogicalDpi(&dpi)))
+- {
+- return dpi;
+- }
+- }
+-
+- // Return 96 dpi as a default if display properties cannot be obtained.
+- return 96.0f;
+-}
+-
+-float ConvertDipsToPixels(float dips)
+-{
+- static const float dipsPerInch = 96.0f;
+- return dips * GetLogicalDpi() / dipsPerInch;
+-}
+ }
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h
+index d43bf0ba5f..21855c2c3b 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h
+@@ -19,8 +19,6 @@ typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CUI__CCore__C
+
+ namespace rx
+ {
+-float ConvertDipsToPixels(float dips);
+-
+ class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<CoreWindowNativeWindow>
+ {
+ public:
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
+index cc81521320..1bd796e58f 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
+@@ -270,8 +270,28 @@ HRESULT GetOptionalSinglePropertyValue(const ComPtr<ABI::Windows::Foundation::Co
+
+ RECT InspectableNativeWindow::clientRect(const Size &size)
+ {
+- // We don't have to check if a swapchain scale was specified here; the default value is 1.0f
+- // which will have no effect.
+- return {0, 0, lround(size.Width * mSwapChainScale), lround(size.Height * mSwapChainScale)};
++ return {0, 0, static_cast<long>(ConvertDipsToPixels(size.Width)),
++ static_cast<long>(ConvertDipsToPixels(size.Height))};
++}
++
++float GetLogicalDpi()
++{
++ ComPtr<ABI::Windows::Graphics::Display::IDisplayPropertiesStatics> displayProperties;
++ float dpi = 96.0f;
++
++ if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), displayProperties.GetAddressOf())))
++ {
++ if (SUCCEEDED(displayProperties->get_LogicalDpi(&dpi)))
++ {
++ return dpi;
++ }
++ }
++ return dpi;
++}
++
++float ConvertDipsToPixels(float dips)
++{
++ static const float dipsPerInch = 96.0f;
++ return lround((dips * GetLogicalDpi() / dipsPerInch));
+ }
+ }
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h
+index 3e67269f36..d81c3e5fb9 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h
+@@ -30,6 +30,9 @@ using namespace ABI::Windows::Foundation::Collections;
+
+ namespace rx
+ {
++float ConvertDipsToPixels(float dips);
++float GetLogicalDpi();
++
+ class InspectableNativeWindow
+ {
+ public:
+@@ -37,12 +40,14 @@ class InspectableNativeWindow
+ mSupportsSwapChainResize(true),
+ mSwapChainSizeSpecified(false),
+ mSwapChainScaleSpecified(false),
+- mSwapChainScale(1.0f),
+ mClientRectChanged(false),
+ mClientRect({0,0,0,0}),
+ mNewClientRect({0,0,0,0})
+ {
+ mSizeChangedEventToken.value = 0;
++ mSwapChainScale = 96.0f / GetLogicalDpi();
++ if (mSwapChainScale != 1.0f)
++ mSwapChainScaleSpecified = true;
+ }
+ virtual ~InspectableNativeWindow(){}
+
+--
+2.15.0.windows.1
+
diff --git a/src/angle/patches/0001-Fix-build-for-MinGW.patch b/src/angle/patches/0001-Fix-build-for-MinGW.patch
new file mode 100644
index 0000000000..186acd39dc
--- /dev/null
+++ b/src/angle/patches/0001-Fix-build-for-MinGW.patch
@@ -0,0 +1,26 @@
+From 75f877269a86aa111afbf816be14ef6c36ea6478 Mon Sep 17 00:00:00 2001
+From: Oliver Wolff <oliver.wolff@qt.io>
+Date: Mon, 2 Jul 2018 12:56:39 +0200
+Subject: [PATCH] Fix build for MinGW
+
+SSE is not properly supported for Mingw yet.
+---
+ src/common/platform.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/srccommon/platform.h
+index 0065fd2..47cd57b 100644
+--- a/src/3rdparty/angle/src/common/platform.h
++++ b/src/3rdparty/angle/src/common/platform.h
+@@ -86,7 +86,7 @@
+ #if defined(_MSC_VER) && !defined(_M_ARM)
+ #include <intrin.h>
+ #define ANGLE_USE_SSE
+-#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
++#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) && !defined(__MINGW32__)
+ #include <x86intrin.h>
+ #define ANGLE_USE_SSE
+ #endif
+--
+2.10.2.windows.1
+
diff --git a/src/angle/patches/0002-ANGLE-Add-support-for-querying-platform-device.patch b/src/angle/patches/0002-ANGLE-Add-support-for-querying-platform-device.patch
new file mode 100644
index 0000000000..d548ce465f
--- /dev/null
+++ b/src/angle/patches/0002-ANGLE-Add-support-for-querying-platform-device.patch
@@ -0,0 +1,83 @@
+From 2f2aabec376cb749a7d0db9e7f754fbfd28b8a72 Mon Sep 17 00:00:00 2001
+From: Oliver Wolff <oliver.wolff@qt.io>
+Date: Wed, 22 Aug 2018 12:58:13 +0200
+Subject: [PATCH 2/8] ANGLE: Add support for querying platform device
+
+The EGL_EXT_device_base extension allows for querying the platform
+device of the graphics hardware via eglQueryDisplayAttribEXT().
+As that extension is not supported by ANGLE, this patch adds similar
+functionality to the existing eglQuerySurfacePointerANGLE API. When
+EGL_DEVICE_EXT is passed as the queried attribute, the underlying
+D3D/DXGI device pointer is passed back to the caller via the value
+argument.
+
+The D3D device is needed for video support in QtMultimedia as well as
+the IDXGIDevice3::Trim() calls required by the Windows Store.
+
+Change-Id: Ib3dfd3edc47dbcc02b07f71980ba785508f2ee57
+---
+ src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp | 4 ++++
+ src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h | 1 +
+ src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp | 5 +++++
+ src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h | 2 ++
+ 4 files changed, 12 insertions(+)
+
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
+index 8e78b71a36..ceb022d14c 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
+@@ -351,6 +351,10 @@ egl::Error SurfaceD3D::querySurfacePointerANGLE(EGLint attribute, void **value)
+ {
+ *value = mSwapChain->getKeyedMutex();
+ }
++ else if (attribute == EGL_DEVICE_EXT)
++ {
++ *value = mSwapChain->getDevice();
++ }
+ else UNREACHABLE();
+
+ return egl::NoError();
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h
+index 81c3d13da4..017737b878 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h
+@@ -58,6 +58,7 @@ class SwapChainD3D : angle::NonCopyable
+ EGLint width,
+ EGLint height) = 0;
+ virtual void recreate() = 0;
++ virtual void *getDevice() { return nullptr; }
+
+ virtual RenderTargetD3D *getColorRenderTarget() = 0;
+ virtual RenderTargetD3D *getDepthStencilRenderTarget() = 0;
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
+index 19bcaae776..05bb5d9863 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
+@@ -1007,6 +1007,11 @@ void SwapChain11::recreate()
+ // possibly should use this method instead of reset
+ }
+
++void *rx::SwapChain11::getDevice()
++{
++ return mRenderer->getDevice();
++}
++
+ RenderTargetD3D *SwapChain11::getColorRenderTarget()
+ {
+ return &mColorRenderTarget;
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
+index 5ce2af193d..eca068210b 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
+@@ -61,6 +61,8 @@ class SwapChain11 final : public SwapChainD3D
+ void *getKeyedMutex() override;
+ EGLint getSamples() const { return mEGLSamples; }
+
++ void *getDevice() override;
++
+ egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override;
+
+ private:
+--
+2.15.0.windows.1
+
diff --git a/src/angle/patches/0002-ANGLE-Dynamically-load-D3D-compiler-from-a-list.patch b/src/angle/patches/0002-ANGLE-Dynamically-load-D3D-compiler-from-a-list.patch
deleted file mode 100644
index 9503ae1090..0000000000
--- a/src/angle/patches/0002-ANGLE-Dynamically-load-D3D-compiler-from-a-list.patch
+++ /dev/null
@@ -1,62 +0,0 @@
-From 7dd1de8a519324e6ec7dbfede1b446980cb5954f Mon Sep 17 00:00:00 2001
-From: Oliver Wolff <oliver.wolff@theqtcompany.com>
-Date: Tue, 1 Mar 2016 13:28:02 +0100
-Subject: [PATCH 2/7] ANGLE: Dynamically load D3D compiler from a list
-
-If the default compiler cannot be found, load it from a list of DLL names,
-including a non-versioned proxy DLL provided by Qt. On Desktop Windows,
-the default compiler can also be specified by an environment variable,
-QT_D3DCOMPILER_DLL.
-
-Change-Id: Ic6d6e37095b838b8a636b029b72467f156b850cb
----
- .../src/libANGLE/renderer/d3d/HLSLCompiler.cpp | 26 ++++++++++++++++++++++
- 1 file changed, 26 insertions(+)
-
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
-index e8b1af3..0d298bb 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
-@@ -12,6 +12,10 @@
- #include "libANGLE/histogram_macros.h"
- #include "third_party/trace_event/trace_event.h"
-
-+#ifndef QT_D3DCOMPILER_DLL
-+#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL
-+#endif
-+
- #if ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED
- namespace
- {
-@@ -128,6 +132,28 @@ gl::Error HLSLCompiler::initialize()
- }
- #endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES
-
-+ // Load the compiler DLL specified by the environment, or default to QT_D3DCOMPILER_DLL
-+ const wchar_t *defaultCompiler = _wgetenv(L"QT_D3DCOMPILER_DLL");
-+ if (!defaultCompiler)
-+ defaultCompiler = QT_D3DCOMPILER_DLL;
-+
-+ const wchar_t *compilerDlls[] = {
-+ defaultCompiler,
-+ L"d3dcompiler_47.dll",
-+ L"d3dcompiler_46.dll",
-+ L"d3dcompiler_43.dll",
-+ 0
-+ };
-+
-+ // Load the first available known compiler DLL
-+ for (int i = 0; compilerDlls[i]; ++i)
-+ {
-+ mD3DCompilerModule = LoadLibrary(compilerDlls[i]);
-+ if (mD3DCompilerModule)
-+ break;
-+ }
-+
-+
- if (!mD3DCompilerModule)
- {
- // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with.
---
-2.7.0.windows.1
-
diff --git a/src/angle/patches/0002-ANGLE-Fix-build-for-ARM.patch b/src/angle/patches/0002-ANGLE-Fix-build-for-ARM.patch
new file mode 100644
index 0000000000..04517a116e
--- /dev/null
+++ b/src/angle/patches/0002-ANGLE-Fix-build-for-ARM.patch
@@ -0,0 +1,43 @@
+From 416fb93dae5009bb51da9f6720a95918a2c79e78 Mon Sep 17 00:00:00 2001
+From: Oliver Wolff <oliver.wolff@qt.io>
+Date: Fri, 17 Aug 2018 09:54:15 +0200
+Subject: [PATCH] ANGLE: Fix build for ARM
+
+__popcnt is not available when building for ARM. This patch uses the
+approach that is also used in Microsoft's ANGLE fork.
+
+Change-Id: I98bac36a3b36b0aa81f3b483d3d12cce9f6c5c87
+---
+ src/3rdparty/angle/src/common/mathutil.h | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/src/3rdparty/angle/src/common/mathutil.h b/src/3rdparty/angle/src/common/mathutil.h
+index ca6efc567f..372e432066 100644
+--- a/src/3rdparty/angle/src/common/mathutil.h
++++ b/src/3rdparty/angle/src/common/mathutil.h
+@@ -884,6 +884,14 @@ inline uint32_t BitfieldReverse(uint32_t value)
+
+ // Count the 1 bits.
+ #if defined(ANGLE_PLATFORM_WINDOWS)
++#if defined(_M_ARM)
++inline int BitCount(uint32_t bits)
++{
++ bits = bits - ((bits >> 1) & 0x55555555);
++ bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333);
++ return (((bits + (bits >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
++}
++#else // _M_ARM
+ inline int BitCount(uint32_t bits)
+ {
+ return static_cast<int>(__popcnt(bits));
+@@ -893,6 +901,7 @@ inline int BitCount(uint64_t bits)
+ {
+ return static_cast<int>(__popcnt64(bits));
+ }
++#endif // !_M_ARM
+ #endif // defined(ANGLE_IS_64_BIT_CPU)
+ #endif // defined(ANGLE_PLATFORM_WINDOWS)
+
+--
+2.15.0.windows.1
+
diff --git a/src/angle/patches/0002-ANGLE-Fix-compilation-with-MinGW.patch b/src/angle/patches/0002-ANGLE-Fix-compilation-with-MinGW.patch
deleted file mode 100644
index f42ff2141b..0000000000
--- a/src/angle/patches/0002-ANGLE-Fix-compilation-with-MinGW.patch
+++ /dev/null
@@ -1,892 +0,0 @@
-From c6b9e598384563a641efdff56fdbdb0d7a561ec4 Mon Sep 17 00:00:00 2001
-From: Oliver Wolff <oliver.wolff@theqtcompany.com>
-Date: Thu, 10 Mar 2016 15:12:58 +0100
-Subject: [PATCH] ANGLE: Fix compilation with MinGW
-
-This adds definition guards for Direct3D 11 and DirectX SDK layers, which
-are only available in very recent versions (4.9.2 rev 4) of MinGW builds.
-It additionally adds a few missing includes needed for compilation.
-
-Change-Id: I254c208209c0071fae5efb6727f2b3cfd5542da6
----
- src/3rdparty/angle/src/common/platform.h | 10 ++-
- .../src/libANGLE/renderer/d3d/HLSLCompiler.cpp | 9 +++
- .../src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp | 6 ++
- .../src/libANGLE/renderer/d3d/d3d11/Clear11.cpp | 4 +
- .../renderer/d3d/d3d11/DebugAnnotator11.cpp | 10 +++
- .../libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h | 2 +
- .../libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp | 2 +
- .../src/libANGLE/renderer/d3d/d3d11/Query11.cpp | 14 ++++++++++++++
- .../src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp | 32 +++++++-
- .../src/libANGLE/renderer/d3d/d3d11/Renderer11.h | 4 +
- .../libANGLE/renderer/d3d/d3d11/SwapChain11.cpp | 10 +++
- .../src/libANGLE/renderer/d3d/d3d11/SwapChain11.h | 2 +
- .../renderer/d3d/d3d11/renderer11_utils.cpp | 92 ++++++++++++++++++++++
- .../renderer/d3d/d3d11/win32/NativeWindow.cpp | 8 ++
- .../src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp | 4 +-
- src/3rdparty/angle/src/libEGL/libEGL_mingw32.def | 27 ++++---
- src/3rdparty/angle/src/libEGL/libEGLd_mingw32.def | 19 +++++
- .../angle/src/libGLESv2/libGLESv2_mingw32.def | 32 +++++++-
- .../angle/src/libGLESv2/libGLESv2d_mingw32.def | 32 +++++++-
- 19 files changed, 296 insertions(+), 21 deletions(-)
-
-diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h
-index 4e3851c..be4cb94 100644
---- a/src/3rdparty/angle/src/common/platform.h
-+++ b/src/3rdparty/angle/src/common/platform.h
-@@ -59,9 +59,17 @@
- # if defined(ANGLE_ENABLE_D3D11)
- # include <d3d10_1.h>
- # include <d3d11.h>
--# include <d3d11_1.h>
- # include <dxgi.h>
-+# if defined(__MINGW32__) && !defined(__d3d11sdklayers_h__)
-+# define ANGLE_MINGW32_COMPAT
-+# endif
-+# if defined(_MSC_VER) && _MSC_VER >= 1800
-+# define ANGLE_ENABLE_D3D11_1
-+# endif
-+# if defined(ANGLE_ENABLE_D3D11_1)
-+# include <d3d11_1.h>
- # include <dxgi1_2.h>
-+# endif
- # include <d3dcompiler.h>
- # endif
-
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
-index 0d298bb..df0257e 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
-@@ -25,6 +25,15 @@ namespace
-
- #define CREATE_COMPILER_FLAG_INFO(flag) { flag, #flag }
-
-+#if defined(ANGLE_MINGW32_COMPAT)
-+#ifndef D3DCOMPILE_RESERVED16
-+#define D3DCOMPILE_RESERVED16 0x10000
-+#endif
-+#ifndef D3DCOMPILE_RESERVED17
-+#define D3DCOMPILE_RESERVED17 0x20000
-+#endif
-+#endif
-+
- struct CompilerFlagInfo
- {
- UINT mFlag;
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
-index 66e2d67..0d5dc08 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
-@@ -29,6 +29,12 @@ GLuint ReadIndexValueFromIndices(const uint8_t *data, size_t index)
- typedef GLuint (*ReadIndexValueFunction)(const uint8_t *data, size_t index);
- }
-
-+#if defined(ANGLE_MINGW32_COMPAT)
-+typedef enum D3D11_MAP_FLAG {
-+ D3D11_MAP_FLAG_DO_NOT_WAIT = 0x100000
-+} D3D11_MAP_FLAG;
-+#endif
-+
- namespace rx
- {
- PackPixelsParams::PackPixelsParams()
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
-index 03b28c2..cd95c65 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
-@@ -262,7 +262,9 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl
- RenderTarget11* maskedClearDepthStencil = nullptr;
-
- ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
-+#if defined(ANGLE_ENABLE_D3D11_1)
- ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
-+#endif
- ID3D11Device *device = mRenderer->getDevice();
-
- for (size_t colorAttachmentIndex = 0; colorAttachmentIndex < colorAttachments.size();
-@@ -347,6 +349,7 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl
- clearValues[3] = (clearParams.colorFClearValue.alpha >= 0.5f) ? 1.0f : 0.0f;
- }
-
-+#if defined(ANGLE_ENABLE_D3D11_1)
- if (needScissoredClear)
- {
- // We shouldn't reach here if deviceContext1 is unavailable.
-@@ -361,6 +364,7 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl
- deviceContext1->ClearView(framebufferRTV, clearValues, &rect, 1);
- }
- else
-+#endif
- {
- deviceContext->ClearRenderTargetView(framebufferRTV, clearValues);
- }
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
-index 2e42859..1c35ab4 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
-@@ -27,7 +27,9 @@ DebugAnnotator11::~DebugAnnotator11()
- {
- if (mInitialized)
- {
-+#if defined(ANGLE_ENABLE_D3D11_1)
- SafeRelease(mUserDefinedAnnotation);
-+#endif
-
- #if !defined(ANGLE_ENABLE_WINDOWS_STORE)
- FreeLibrary(mD3d11Module);
-@@ -41,7 +43,9 @@ void DebugAnnotator11::beginEvent(const wchar_t *eventName)
-
- if (mUserDefinedAnnotation != nullptr)
- {
-+#if defined(ANGLE_ENABLE_D3D11_1)
- mUserDefinedAnnotation->BeginEvent(eventName);
-+#endif
- }
- }
-
-@@ -51,7 +55,9 @@ void DebugAnnotator11::endEvent()
-
- if (mUserDefinedAnnotation != nullptr)
- {
-+#if defined(ANGLE_ENABLE_D3D11_1)
- mUserDefinedAnnotation->EndEvent();
-+#endif
- }
- }
-
-@@ -61,7 +67,9 @@ void DebugAnnotator11::setMarker(const wchar_t *markerName)
-
- if (mUserDefinedAnnotation != nullptr)
- {
-+#if defined(ANGLE_ENABLE_D3D11_1)
- mUserDefinedAnnotation->SetMarker(markerName);
-+#endif
- }
- }
-
-@@ -137,8 +145,10 @@ void DebugAnnotator11::initializeDevice()
- ASSERT(SUCCEEDED(hr));
- if (SUCCEEDED(hr))
- {
-+#if defined(ANGLE_ENABLE_D3D11_1)
- mUserDefinedAnnotation = d3d11::DynamicCastComObject<ID3DUserDefinedAnnotation>(context);
- ASSERT(mUserDefinedAnnotation != nullptr);
-+#endif
- mInitialized = true;
- }
-
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h
-index 9da4fa2..d1a0f7f 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h
-@@ -11,6 +11,8 @@
-
- #include "common/debug.h"
-
-+struct ID3DUserDefinedAnnotation;
-+
- namespace rx
- {
-
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
-index beffa30..186a035 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
-@@ -140,6 +140,7 @@ gl::Error Framebuffer11::discard(size_t count, const GLenum *attachments)
-
- gl::Error Framebuffer11::invalidateBase(size_t count, const GLenum *attachments, bool useEXTBehavior) const
- {
-+#if defined(ANGLE_ENABLE_D3D11_1)
- ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
-
- if (!deviceContext1)
-@@ -272,6 +273,7 @@ gl::Error Framebuffer11::invalidateBase(size_t count, const GLenum *attachments,
- deviceContext1->DiscardView(stencilView);
- }
- }
-+#endif // ANGLE_ENABLE_D3D11_1
-
- return gl::Error(GL_NO_ERROR);
- }
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
-index c015ff4..c0bed2b 100644
-index c015ff4..972c289 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
-@@ -13,6 +13,20 @@
-
- #include <GLES2/gl2ext.h>
-
-+#if defined(ANGLE_MINGW32_COMPAT)
-+typedef struct D3D11_QUERY_DATA_SO_STATISTICS {
-+ UINT64 NumPrimitivesWritten;
-+ UINT64 PrimitivesStorageNeeded;
-+} D3D11_QUERY_DATA_SO_STATISTICS;
-+#endif // ANGLE_MINGW32_COMPAT
-+
-+#ifdef __MINGW32__
-+typedef struct D3D11_QUERY_DATA_TIMESTAMP_DISJOINT {
-+ UINT64 Frequency;
-+ BOOL Disjoint;
-+} D3D11_QUERY_DATA_TIMESTAMP_DISJOINT;
-+#endif // MINGW32
-+
- namespace rx
- {
-
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
-index ea84783..62badcc 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
-@@ -10,7 +10,7 @@
-
- #include <EGL/eglext.h>
- #include <sstream>
--#if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
-+#if !defined(ANGLE_MINGW32_COMPAT) && WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
- #include <VersionHelpers.h>
- #endif
-
-@@ -89,6 +89,7 @@ enum
- MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16
- };
-
-+#if defined(ANGLE_ENABLE_D3D11_1)
- void CalculateConstantBufferParams(GLintptr offset, GLsizeiptr size, UINT *outFirstConstant, UINT *outNumConstants)
- {
- // The offset must be aligned to 256 bytes (should have been enforced by glBindBufferRange).
-@@ -105,6 +106,7 @@ void CalculateConstantBufferParams(GLintptr offset, GLsizeiptr size, UINT *outFi
- // This behaviour is explictly allowed according to the documentation on ID3D11DeviceContext1::PSSetConstantBuffers1
- // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx
- }
-+#endif
-
- enum ANGLEFeatureLevel
- {
-@@ -369,8 +371,10 @@ Renderer11::Renderer11(egl::Display *display)
- : RendererD3D(display),
- mStateCache(this),
- mStateManager(this),
-- mLastHistogramUpdateTime(ANGLEPlatformCurrent()->monotonicallyIncreasingTime()),
-- mDebug(nullptr)
-+ mLastHistogramUpdateTime(ANGLEPlatformCurrent()->monotonicallyIncreasingTime())
-+#if !defined(ANGLE_MINGW32_COMPAT)
-+ ,mDebug(nullptr)
-+#endif
- {
- mVertexDataManager = NULL;
- mIndexDataManager = NULL;
-@@ -572,7 +576,9 @@ egl::Error Renderer11::initialize()
- // Cast the DeviceContext to a DeviceContext1.
- // This could fail on Windows 7 without the Platform Update.
- // Don't error in this case- just don't use mDeviceContext1.
-+#if defined(ANGLE_ENABLE_D3D11_1)
- mDeviceContext1 = d3d11::DynamicCastComObject<ID3D11DeviceContext1>(mDeviceContext);
-+#endif
-
- IDXGIDevice *dxgiDevice = NULL;
- result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice);
-@@ -595,6 +601,7 @@ egl::Error Renderer11::initialize()
-
- SafeRelease(dxgiDevice);
-
-+#if defined(ANGLE_ENABLE_D3D11_1)
- IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter);
-
- // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter" for the description string.
-@@ -618,11 +625,14 @@ egl::Error Renderer11::initialize()
- }
- }
- else
-+#endif
- {
- result = mDxgiAdapter->GetDesc(&mAdapterDescription);
- }
-
-+#if defined(ANGLE_ENABLE_D3D11_1)
- SafeRelease(dxgiAdapter2);
-+#endif
-
- if (FAILED(result))
- {
-@@ -644,6 +654,7 @@ egl::Error Renderer11::initialize()
- }
- }
-
-+#if !defined(ANGLE_MINGW32_COMPAT)
- // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log
- #if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG)
- {
-@@ -671,6 +682,7 @@ egl::Error Renderer11::initialize()
- #if !defined(NDEBUG)
- mDebug = d3d11::DynamicCastComObject<ID3D11Debug>(mDevice);
- #endif
-+#endif // !ANGLE_MINGW32_COMPAT
-
- initializeDevice();
-
-@@ -859,6 +871,7 @@ void Renderer11::populateRenderer11DeviceCaps()
- {
- HRESULT hr = S_OK;
-
-+#if defined(ANGLE_ENABLE_D3D11_1)
- if (mDeviceContext1)
- {
- D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options;
-@@ -869,6 +882,7 @@ void Renderer11::populateRenderer11DeviceCaps()
- mRenderer11DeviceCaps.supportsConstantBufferOffsets = (d3d11Options.ConstantBufferOffsetting != FALSE);
- }
- }
-+#endif
-
- hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B5G6R5_UNORM, &(mRenderer11DeviceCaps.B5G6R5support));
- if (FAILED(hr))
-@@ -888,9 +902,11 @@ void Renderer11::populateRenderer11DeviceCaps()
- mRenderer11DeviceCaps.B5G5R5A1support = 0;
- }
-
-+#if defined(ANGLE_ENABLE_D3D11_1)
- IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter);
- mRenderer11DeviceCaps.supportsDXGI1_2 = (dxgiAdapter2 != nullptr);
- SafeRelease(dxgiAdapter2);
-+#endif
- }
-
- egl::ConfigSet Renderer11::generateConfigs() const
-@@ -1308,6 +1324,7 @@ gl::Error Renderer11::setUniformBuffers(const gl::Data &data,
- mCurrentConstantBufferVSOffset[uniformBufferIndex] != uniformBufferOffset ||
- mCurrentConstantBufferVSSize[uniformBufferIndex] != uniformBufferSize)
- {
-+#if defined(ANGLE_ENABLE_D3D11_1)
- if (mRenderer11DeviceCaps.supportsConstantBufferOffsets && uniformBufferSize != 0)
- {
- UINT firstConstant = 0, numConstants = 0;
-@@ -1318,6 +1335,7 @@ gl::Error Renderer11::setUniformBuffers(const gl::Data &data,
- 1, &constantBuffer, &firstConstant, &numConstants);
- }
- else
-+#endif
- {
- mDeviceContext->VSSetConstantBuffers(
- getReservedVertexUniformBuffers() +
-@@ -1369,6 +1387,7 @@ gl::Error Renderer11::setUniformBuffers(const gl::Data &data,
- mCurrentConstantBufferPSOffset[uniformBufferIndex] != uniformBufferOffset ||
- mCurrentConstantBufferPSSize[uniformBufferIndex] != uniformBufferSize)
- {
-+#if defined(ANGLE_ENABLE_D3D11_1)
- if (mRenderer11DeviceCaps.supportsConstantBufferOffsets && uniformBufferSize != 0)
- {
- UINT firstConstant = 0, numConstants = 0;
-@@ -1379,6 +1398,7 @@ gl::Error Renderer11::setUniformBuffers(const gl::Data &data,
- 1, &constantBuffer, &firstConstant, &numConstants);
- }
- else
-+#endif
- {
- mDeviceContext->PSSetConstantBuffers(
- getReservedFragmentUniformBuffers() +
-@@ -2448,7 +2468,9 @@ void Renderer11::release()
- SafeRelease(mDxgiFactory);
- SafeRelease(mDxgiAdapter);
-
-+#if defined(ANGLE_ENABLE_D3D11_1)
- SafeRelease(mDeviceContext1);
-+#endif
-
- if (mDeviceContext)
- {
-@@ -2458,7 +2480,9 @@ void Renderer11::release()
- }
-
- SafeRelease(mDevice);
-+#if !defined(ANGLE_MINGW32_COMPAT)
- SafeRelease(mDebug);
-+#endif
-
- if (mD3d11Module)
- {
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
-index 62e9816..b4e7761 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
-@@ -28,6 +28,8 @@ class FramebufferAttachment;
- struct ImageIndex;
- }
-
-+struct ID3D11DeviceContext1;
-+
- namespace rx
- {
-
-@@ -442,7 +444,9 @@ class Renderer11 : public RendererD3D
- DXGI_ADAPTER_DESC mAdapterDescription;
- char mDescription[128];
- DXGIFactory *mDxgiFactory;
-+#if !defined(ANGLE_MINGW32_COMPAT)
- ID3D11Debug *mDebug;
-+#endif
-
- std::vector<GLuint> mScratchIndexDataBuffer;
-
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
-index f669f56..f80f24b 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
-@@ -58,7 +58,9 @@ SwapChain11::SwapChain11(Renderer11 *renderer,
- mPassThroughResourcesInit(false),
- mFirstSwap(true),
- mSwapChain(nullptr),
-+#if defined(ANGLE_ENABLE_D3D11_1)
- mSwapChain1(nullptr),
-+#endif
- mKeyedMutex(nullptr),
- mBackBufferTexture(nullptr),
- mBackBufferRTView(nullptr),
-@@ -90,7 +92,9 @@ SwapChain11::~SwapChain11()
-
- void SwapChain11::release()
- {
-+#if defined(ANGLE_ENABLE_D3D11_1)
- SafeRelease(mSwapChain1);
-+#endif
- SafeRelease(mSwapChain);
- SafeRelease(mKeyedMutex);
- SafeRelease(mBackBufferTexture);
-@@ -533,7 +537,9 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap
-
- // Release specific resources to free up memory for the new render target, while the
- // old render target still exists for the purpose of preserving its contents.
-+#if defined(ANGLE_ENABLE_D3D11_1)
- SafeRelease(mSwapChain1);
-+#endif
- SafeRelease(mSwapChain);
- SafeRelease(mBackBufferTexture);
- SafeRelease(mBackBufferRTView);
-@@ -568,7 +574,9 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap
-
- if (mRenderer->getRenderer11DeviceCaps().supportsDXGI1_2)
- {
-+#if defined(ANGLE_ENABLE_D3D11_1)
- mSwapChain1 = d3d11::DynamicCastComObject<IDXGISwapChain1>(mSwapChain);
-+#endif
- }
-
- result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
-@@ -837,6 +845,7 @@ EGLint SwapChain11::present(EGLint x, EGLint y, EGLint width, EGLint height)
-
- HRESULT result = S_OK;
-
-+#if defined(ANGLE_ENABLE_D3D11_1)
- // Use IDXGISwapChain1::Present1 with a dirty rect if DXGI 1.2 is available.
- if (mSwapChain1 != nullptr)
- {
-@@ -855,6 +864,7 @@ EGLint SwapChain11::present(EGLint x, EGLint y, EGLint width, EGLint height)
- }
- }
- else
-+#endif
- {
- result = mSwapChain->Present(swapInterval, 0);
- }
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
-index 99198c6..adcd07a 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
-@@ -75,7 +75,9 @@ class SwapChain11 : public SwapChainD3D
-
- bool mFirstSwap;
- DXGISwapChain *mSwapChain;
-+#if defined(ANGLE_ENABLE_D3D11_1)
- IDXGISwapChain1 *mSwapChain1;
-+#endif
- IDXGIKeyedMutex *mKeyedMutex;
-
- ID3D11Texture2D *mBackBufferTexture;
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
-index d1f3ea0..a1175db 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
-@@ -23,6 +23,88 @@
- #include "libANGLE/renderer/d3d/FramebufferD3D.h"
- #include "libANGLE/renderer/d3d/WorkaroundsD3D.h"
-
-+#ifndef D3D_FL9_1_DEFAULT_MAX_ANISOTROPY
-+# define D3D_FL9_1_DEFAULT_MAX_ANISOTROPY 2
-+#endif
-+#ifndef D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT
-+# define D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT 1
-+#endif
-+#ifndef D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT
-+# define D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT 4
-+#endif
-+#ifndef D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT
-+# define D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT 65535
-+#endif
-+#ifndef D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT
-+# define D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT 1048575
-+#endif
-+#ifndef D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION
-+# define D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION 512
-+#endif
-+#ifndef D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION
-+# define D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION 4096
-+#endif
-+#ifndef D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION
-+# define D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION 2048
-+#endif
-+#ifndef D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION
-+# define D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 256
-+#endif
-+#ifndef D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION
-+# define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096
-+#endif
-+#ifndef D3D11_REQ_TEXTURECUBE_DIMENSION
-+# define D3D11_REQ_TEXTURECUBE_DIMENSION 16384
-+#endif
-+#ifndef D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION
-+# define D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION 2048
-+#endif
-+#ifndef D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION
-+# define D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 2048
-+#endif
-+#ifndef D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP
-+# define D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP 32
-+#endif
-+#ifndef D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP
-+# define D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP 32
-+#endif
-+#ifndef D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT
-+# define D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT 32
-+#endif
-+#ifndef D3D11_STANDARD_VERTEX_ELEMENT_COUNT
-+# define D3D11_STANDARD_VERTEX_ELEMENT_COUNT 32
-+#endif
-+#ifndef D3D10_1_SO_BUFFER_SLOT_COUNT
-+# define D3D10_1_SO_BUFFER_SLOT_COUNT 4
-+#endif
-+#ifndef D3D11_SO_BUFFER_SLOT_COUNT
-+# define D3D11_SO_BUFFER_SLOT_COUNT 4
-+#endif
-+#ifndef D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT
-+# define D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT 14
-+#endif
-+#ifndef D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT
-+# define D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT 16
-+#endif
-+#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE
-+# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE -8
-+#endif
-+#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE
-+# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE 7
-+#endif
-+#ifndef D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT
-+# define D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT 4096
-+#endif
-+#ifndef D3D11_PS_INPUT_REGISTER_COUNT
-+# define D3D11_PS_INPUT_REGISTER_COUNT 32
-+#endif
-+#ifndef D3D10_1_VS_OUTPUT_REGISTER_COUNT
-+# define D3D10_1_VS_OUTPUT_REGISTER_COUNT 32
-+#endif
-+#if defined(ANGLE_MINGW32_COMPAT)
-+static const IID WKPDID_D3DDebugObjectName = { 0x429b8c22, 0x9188, 0x4b0c, 0x87, 0x42, 0xac, 0xb0, 0xbf, 0x85, 0xc2, 0x00 };
-+#endif
-+
- namespace rx
- {
-
-@@ -601,7 +683,9 @@ static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel)
- {
- switch (featureLevel)
- {
-+#if defined(ANGLE_ENABLE_D3D11_1)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURECUBE_DIMENSION;
-
- case D3D_FEATURE_LEVEL_10_1:
-@@ -619,7 +703,9 @@ static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel)
- {
- switch (featureLevel)
- {
-+#if defined(ANGLE_ENABLE_D3D11_1)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
-
- case D3D_FEATURE_LEVEL_10_1:
-@@ -1266,7 +1352,9 @@ ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device)
-
- IDXGIDevice *dxgiDevice = nullptr;
- IDXGIAdapter *dxgiAdapter = nullptr;
-+#if defined(ANGLE_ENABLE_D3D11_1)
- IDXGIAdapter2 *dxgiAdapter2 = nullptr;
-+#endif
-
- ANGLED3D11DeviceType retDeviceType = ANGLE_D3D11_DEVICE_TYPE_UNKNOWN;
-
-@@ -1277,6 +1365,7 @@ ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device)
- if (SUCCEEDED(hr))
- {
- std::wstring adapterString;
-+#if defined(ANGLE_ENABLE_D3D11_1)
- HRESULT adapter2hr =
- dxgiAdapter->QueryInterface(__uuidof(dxgiAdapter2), (void **)&dxgiAdapter2);
- if (SUCCEEDED(adapter2hr))
-@@ -1289,6 +1378,7 @@ ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device)
- adapterString = std::wstring(adapterDesc2.Description);
- }
- else
-+#endif
- {
- DXGI_ADAPTER_DESC adapterDesc;
- dxgiAdapter->GetDesc(&adapterDesc);
-@@ -1320,7 +1410,9 @@ ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device)
-
- SafeRelease(dxgiDevice);
- SafeRelease(dxgiAdapter);
-+#if defined(ANGLE_ENABLE_D3D11_1)
- SafeRelease(dxgiAdapter2);
-+#endif
-
- return retDeviceType;
- }
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
-index 123b481..cd63789 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
-@@ -12,7 +12,9 @@
- #include "common/debug.h"
-
- #include <initguid.h>
-+#if !defined(__MINGW32__)
- #include <dcomp.h>
-+#endif
-
- namespace rx
- {
-@@ -31,9 +33,11 @@ NativeWindow::NativeWindow(EGLNativeWindowType window,
-
- NativeWindow::~NativeWindow()
- {
-+#if !defined(__MINGW32__)
- SafeRelease(mCompositionTarget);
- SafeRelease(mDevice);
- SafeRelease(mVisual);
-+#endif
- }
-
- bool NativeWindow::initialize()
-@@ -66,6 +70,7 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory
- return E_INVALIDARG;
- }
-
-+#if !defined(__MINGW32__)
- if (mDirectComposition)
- {
- HMODULE dcomp = ::GetModuleHandle(TEXT("dcomp.dll"));
-@@ -171,6 +176,7 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory
- SafeRelease(factory2);
- return result;
- }
-+#endif // !__MINGW32__
-
- DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
- swapChainDesc.BufferCount = 1;
-@@ -202,9 +208,11 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory
-
- void NativeWindow::commitChange()
- {
-+#if !defined(__MINGW32__)
- if (mDevice)
- {
- mDevice->Commit();
- }
-+#endif
- }
- }
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
-index cba74c1..6bb975b 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
-@@ -193,7 +193,7 @@ egl::Error Renderer9::initialize()
- {
- TRACE_EVENT0("gpu.angle", "D3d9Ex_QueryInterface");
- ASSERT(mD3d9Ex);
-- mD3d9Ex->QueryInterface(__uuidof(IDirect3D9), reinterpret_cast<void**>(&mD3d9));
-+ mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
- ASSERT(mD3d9);
- }
- else
-@@ -301,7 +301,7 @@ egl::Error Renderer9::initialize()
- if (mD3d9Ex)
- {
- TRACE_EVENT0("gpu.angle", "mDevice_QueryInterface");
-- result = mDevice->QueryInterface(__uuidof(IDirect3DDevice9Ex), (void**)&mDeviceEx);
-+ result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**)&mDeviceEx);
- ASSERT(SUCCEEDED(result));
- }
-
-diff --git a/src/3rdparty/angle/src/libEGL/libEGL_mingw32.def b/src/3rdparty/angle/src/libEGL/libEGL_mingw32.def
-index 6a771a5..c8f941a 100644
---- a/src/3rdparty/angle/src/libEGL/libEGL_mingw32.def
-+++ b/src/3rdparty/angle/src/libEGL/libEGL_mingw32.def
-@@ -39,15 +39,22 @@ EXPORTS
- eglGetPlatformDisplayEXT@12 @35
- eglQuerySurfacePointerANGLE@16 @36
- eglPostSubBufferNV@24 @37
-+ eglQueryDisplayAttribEXT@12 @48
-+ eglQueryDeviceAttribEXT@12 @49
-+ eglQueryDeviceStringEXT@8 @50
-+ eglCreateImageKHR@20 @51
-+ eglDestroyImageKHR@8 @52
-+ eglCreateDeviceANGLE@12 @53
-+ eglReleaseDeviceANGLE@4 @54
-
- ; 1.5 entry points
-- eglCreateSync @38
-- eglDestroySync @39
-- eglClientWaitSync @40
-- eglGetSyncAttrib @41
-- eglCreateImage @42
-- eglDestroyImage @43
-- eglGetPlatformDisplay @44
-- eglCreatePlatformWindowSurface @45
-- eglCreatePlatformPixmapSurface @46
-- eglWaitSync @47
-+ eglCreateSync@12 @38
-+ eglDestroySync@8 @39
-+ eglClientWaitSync@16 @40
-+ eglGetSyncAttrib@16 @41
-+ eglCreateImage@20 @42
-+ eglDestroyImage@8 @43
-+ eglGetPlatformDisplay@12 @44
-+ eglCreatePlatformWindowSurface@16 @45
-+ eglCreatePlatformPixmapSurface@16 @46
-+ eglWaitSync@12 @47
-diff --git a/src/3rdparty/angle/src/libEGL/libEGLd_mingw32.def b/src/3rdparty/angle/src/libEGL/libEGLd_mingw32.def
-index ab0320d..a4a9d95 100644
---- a/src/3rdparty/angle/src/libEGL/libEGLd_mingw32.def
-+++ b/src/3rdparty/angle/src/libEGL/libEGLd_mingw32.def
-@@ -39,3 +39,22 @@ EXPORTS
- eglGetPlatformDisplayEXT@12 @35
- eglQuerySurfacePointerANGLE@16 @36
- eglPostSubBufferNV@24 @37
-+ eglQueryDisplayAttribEXT@12 @48
-+ eglQueryDeviceAttribEXT@12 @49
-+ eglQueryDeviceStringEXT@8 @50
-+ eglCreateImageKHR@20 @51
-+ eglDestroyImageKHR@8 @52
-+ eglCreateDeviceANGLE@12 @53
-+ eglReleaseDeviceANGLE@4 @54
-+
-+ ; 1.5 entry points
-+ eglCreateSync@12 @38
-+ eglDestroySync@8 @39
-+ eglClientWaitSync@16 @40
-+ eglGetSyncAttrib@16 @41
-+ eglCreateImage@20 @42
-+ eglDestroyImage@8 @43
-+ eglGetPlatformDisplay@12 @44
-+ eglCreatePlatformWindowSurface@16 @45
-+ eglCreatePlatformPixmapSurface@16 @46
-+ eglWaitSync@12 @47
-diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def
-index e02b85b..db17bb4 100644
---- a/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def
-+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def
-@@ -177,6 +177,31 @@ EXPORTS
- glGetBufferPointervOES@12 @287
- glMapBufferRangeEXT@16 @288
- glFlushMappedBufferRangeEXT@12 @289
-+ glDiscardFramebufferEXT@12 @293
-+ glInsertEventMarkerEXT@8 @294
-+ glPushGroupMarkerEXT@8 @295
-+ glPopGroupMarkerEXT@0 @296
-+ glEGLImageTargetTexture2DOES@8 @297
-+ glEGLImageTargetRenderbufferStorageOES@8 @298
-+ glBindVertexArrayOES@4 @299
-+ glDeleteVertexArraysOES@8 @300
-+ glGenVertexArraysOES@8 @301
-+ glIsVertexArrayOES@4 @302
-+ glDebugMessageControlKHR@24 @303
-+ glDebugMessageInsertKHR@24 @304
-+ glDebugMessageCallbackKHR@8 @305
-+ glGetDebugMessageLogKHR@32 @306
-+ glPushDebugGroupKHR@16 @307
-+ glPopDebugGroupKHR@0 @308
-+ glObjectLabelKHR@16 @309
-+ glGetObjectLabelKHR@20 @310
-+ glObjectPtrLabelKHR@12 @311
-+ glGetObjectPtrLabelKHR@16 @312
-+ glGetPointervKHR@8 @313
-+ glQueryCounterEXT@8 @314
-+ glGetQueryObjectivEXT@12 @315
-+ glGetQueryObjecti64vEXT@12 @316
-+ glGetQueryObjectui64vEXT@12 @317
-
- ; GLES 3.0 Functions
- glReadBuffer@4 @180
-@@ -284,5 +309,8 @@ EXPORTS
- glTexStorage3D@24 @282
- glGetInternalformativ@20 @283
-
-- ; Setting up TRACE macro callbacks
-- SetTraceFunctionPointers@8 @284
-+ ; ANGLE Platform Implementation
-+ ANGLEPlatformCurrent@0 @290
-+ ANGLEPlatformInitialize@4 @291
-+ ANGLEPlatformShutdown@0 @292
-+
-\ No newline at end of file
-diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def
-index e2b2c33..5a4966f 100644
---- a/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def
-+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def
-@@ -177,6 +177,31 @@ EXPORTS
- glGetBufferPointervOES@12 @287
- glMapBufferRangeEXT@16 @288
- glFlushMappedBufferRangeEXT@12 @289
-+ glDiscardFramebufferEXT@12 @293
-+ glInsertEventMarkerEXT@8 @294
-+ glPushGroupMarkerEXT@8 @295
-+ glPopGroupMarkerEXT@0 @296
-+ glEGLImageTargetTexture2DOES@8 @297
-+ glEGLImageTargetRenderbufferStorageOES@8 @298
-+ glBindVertexArrayOES@4 @299
-+ glDeleteVertexArraysOES@8 @300
-+ glGenVertexArraysOES@8 @301
-+ glIsVertexArrayOES@4 @302
-+ glDebugMessageControlKHR@24 @303
-+ glDebugMessageInsertKHR@24 @304
-+ glDebugMessageCallbackKHR@8 @305
-+ glGetDebugMessageLogKHR@32 @306
-+ glPushDebugGroupKHR@16 @307
-+ glPopDebugGroupKHR@0 @308
-+ glObjectLabelKHR@16 @309
-+ glGetObjectLabelKHR@20 @310
-+ glObjectPtrLabelKHR@12 @311
-+ glGetObjectPtrLabelKHR@16 @312
-+ glGetPointervKHR@8 @313
-+ glQueryCounterEXT@8 @314
-+ glGetQueryObjectivEXT@12 @315
-+ glGetQueryObjecti64vEXT@12 @316
-+ glGetQueryObjectui64vEXT@12 @317
-
- ; GLES 3.0 Functions
- glReadBuffer@4 @180
-@@ -284,5 +309,8 @@ EXPORTS
- glTexStorage3D@24 @282
- glGetInternalformativ@20 @283
-
-- ; Setting up TRACE macro callbacks
-- SetTraceFunctionPointers@8 @284
-+ ; ANGLE Platform Implementation
-+ ANGLEPlatformCurrent@0 @290
-+ ANGLEPlatformInitialize@4 @291
-+ ANGLEPlatformShutdown@0 @292
-+
-\ No newline at end of file
---
-2.7.0.windows.1
-
diff --git a/src/angle/patches/0003-ANGLE-Add-support-for-querying-platform-device.patch b/src/angle/patches/0003-ANGLE-Add-support-for-querying-platform-device.patch
deleted file mode 100644
index ed0f7247cb..0000000000
--- a/src/angle/patches/0003-ANGLE-Add-support-for-querying-platform-device.patch
+++ /dev/null
@@ -1,81 +0,0 @@
-From 037550af14ce0ecebad96d637d7185b60d760b5d Mon Sep 17 00:00:00 2001
-From: Oliver Wolff <oliver.wolff@theqtcompany.com>
-Date: Tue, 1 Mar 2016 13:31:08 +0100
-Subject: [PATCH 3/7] ANGLE: Add support for querying platform device
-
-The EGL_EXT_device_base extension allows for querying the platform
-device of the graphics hardware via eglQueryDisplayAttribEXT().
-As that extension is not supported by ANGLE, this patch adds similar
-functionality to the existing eglQuerySurfacePointerANGLE API. When
-EGL_DEVICE_EXT is passed as the queried attribute, the underlying
-D3D/DXGI device pointer is passed back to the caller via the value
-argument.
-
-The D3D device is needed for video support in QtMultimedia as well as
-the IDXGIDevice3::Trim() calls required by the Windows Store.
-
-Change-Id: Ib3dfd3edc47dbcc02b07f71980ba785508f2ee57
----
- src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp | 4 ++++
- src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h | 1 +
- src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp | 5 +++++
- src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h | 2 ++
- 4 files changed, 12 insertions(+)
-
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
-index 93f6990..0347828 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
-@@ -334,6 +334,10 @@ egl::Error SurfaceD3D::querySurfacePointerANGLE(EGLint attribute, void **value)
- {
- *value = mSwapChain->getKeyedMutex();
- }
-+ else if (attribute == EGL_DEVICE_EXT)
-+ {
-+ *value = mSwapChain->getDevice();
-+ }
- else UNREACHABLE();
-
- return egl::Error(EGL_SUCCESS);
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h
-index 1ef6611..171cab5 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h
-@@ -41,6 +41,7 @@ class SwapChainD3D : angle::NonCopyable
- virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval) = 0;
- virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height) = 0;
- virtual void recreate() = 0;
-+ virtual void *getDevice() { return NULL; }
-
- virtual RenderTargetD3D *getColorRenderTarget() = 0;
- virtual RenderTargetD3D *getDepthStencilRenderTarget() = 0;
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
-index 9432a7f..5a6f202 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
-@@ -915,4 +915,9 @@ void SwapChain11::recreate()
- // possibly should use this method instead of reset
- }
-
-+void *rx::SwapChain11::getDevice()
-+{
-+ return mRenderer->getDevice();
-+}
-+
- }
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
-index 583e29c..99198c6 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
-@@ -48,6 +48,8 @@ class SwapChain11 : public SwapChainD3D
- EGLint getHeight() const { return mHeight; }
- void *getKeyedMutex() override { return mKeyedMutex; }
-
-+ virtual void *getDevice();
-+
- private:
- void release();
- void initPassThroughResources();
---
-2.7.0.windows.1
-
diff --git a/src/angle/patches/0003-ANGLE-Fix-Windows-Store-D3D-Trim-and-Level-9-require.patch b/src/angle/patches/0003-ANGLE-Fix-Windows-Store-D3D-Trim-and-Level-9-require.patch
new file mode 100644
index 0000000000..1f51619f18
--- /dev/null
+++ b/src/angle/patches/0003-ANGLE-Fix-Windows-Store-D3D-Trim-and-Level-9-require.patch
@@ -0,0 +1,58 @@
+From 9b37d0fa0e9eaab3d8bb1dcbba85c072302ee08c Mon Sep 17 00:00:00 2001
+From: Oliver Wolff <oliver.wolff@qt.io>
+Date: Wed, 22 Aug 2018 13:01:10 +0200
+Subject: [PATCH 3/8] ANGLE: Fix Windows Store D3D Trim and Level 9
+ requirements
+
+Due to additional validation not covered in previous patches, the Windows
+Store certification compatibility had regressed. These changes ensure that
+the required D3D behaviors are met.
+
+Change-Id: If8bc2f8cd4b2f84e1d92a1627951da2537212125
+---
+ .../angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp | 15 ++++++++++++++-
+ src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp | 2 ++
+ 2 files changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
+index bd14f4de2a..f696e360ef 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
+@@ -523,7 +523,20 @@ Renderer11::Renderer11(egl::Display *display)
+
+ if (requestedMajorVersion == 9 && requestedMinorVersion == 3)
+ {
+- mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3);
++ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 3)
++ {
++ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3);
++ }
++#if defined(ANGLE_ENABLE_WINDOWS_STORE)
++ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 2)
++ {
++ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2);
++ }
++ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
++ {
++ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1);
++ }
++#endif
+ }
+
+ EGLint requestedDeviceType = static_cast<EGLint>(attributes.get(
+diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp
+index b863817920..ee8cdb94dc 100644
+--- a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp
++++ b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp
+@@ -54,6 +54,8 @@ EGLBoolean EGLAPIENTRY QuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surfa
+ // validate the attribute parameter
+ switch (attribute)
+ {
++ case EGL_DEVICE_EXT:
++ break;
+ case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
+ if (!display->getExtensions().surfaceD3DTexture2DShareHandle)
+ {
+--
+2.15.0.windows.1
+
diff --git a/src/angle/patches/0004-ANGLE-Allow-Windows-Phone-to-communicate-swap-region.patch b/src/angle/patches/0004-ANGLE-Allow-Windows-Phone-to-communicate-swap-region.patch
deleted file mode 100644
index 4d7080e77d..0000000000
--- a/src/angle/patches/0004-ANGLE-Allow-Windows-Phone-to-communicate-swap-region.patch
+++ /dev/null
@@ -1,146 +0,0 @@
-From a0c84bec77dd2dab4dd87add17dd1f21e6d8087d Mon Sep 17 00:00:00 2001
-From: Oliver Wolff <oliver.wolff@theqtcompany.com>
-Date: Tue, 1 Mar 2016 13:39:06 +0100
-Subject: [PATCH 4/7] ANGLE: Allow Windows Phone to communicate swap region
-
-eglPostSubBufferNV is used to communicate the size of the window, as
-otherwise there is no way for the renderer to know if the last frame was
-rendered in landscape or portrait, causing rendering glitches when the
-orientation changes. The rotation flags are utilized in a few additional
-places now to fix some corner cases where the rotation was not applied.
-
-This patch should be squashed into "ANGLE-Improve-Windows-Phone-Support"
-during the next ANGLE rebase.
-
-Task-number: QTBUG-44333
-Task-number: QTBUG-43502
-
-Change-Id: I2b35c41ed17004524f383350253a936e6bf85117
----
- .../angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp | 2 ++
- .../libANGLE/renderer/d3d/d3d11/SwapChain11.cpp | 28 +++++++++++++---------
- .../d3d/d3d11/winrt/CoreWindowNativeWindow.cpp | 5 ++--
- .../angle/src/libGLESv2/entry_points_egl_ext.cpp | 2 ++
- 4 files changed, 24 insertions(+), 13 deletions(-)
-
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
-index 0347828..3d27548 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
-@@ -211,6 +211,7 @@ egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
- return egl::Error(EGL_SUCCESS);
- }
-
-+#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (defined(ANGLE_ENABLE_WINDOWS_STORE) && WINAPI_FAMILY == WINAPI_FAMILY_PC_APP) // Qt WP: eglPostSubBufferNV comes here
- if (x + width > mWidth)
- {
- width = mWidth - x;
-@@ -220,6 +221,7 @@ egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
- {
- height = mHeight - y;
- }
-+#endif
-
- if (width != 0 && height != 0)
- {
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
-index 5a6f202..f669f56 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
-@@ -717,18 +717,18 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width,
-
- d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
-
-+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
- // Create a quad in homogeneous coordinates
-- float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
-- float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
-- float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
-- float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f;
-+ float x1 = -1.0f;
-+ float y1 = -1.0f;
-+ float x2 = 1.0f;
-+ float y2 = 1.0f;
-
--#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
- const float dim = std::max(mWidth, mHeight);
-- float u1 = x / dim;
-- float v1 = y / dim;
-- float u2 = (x + width) / dim;
-- float v2 = (y + height) / dim;
-+ float u1 = 0;
-+ float v1 = 0;
-+ float u2 = float(width) / dim;
-+ float v2 = float(height) / dim;
-
- const NativeWindow::RotationFlags flags = mNativeWindow.rotationFlags();
- const bool rotateL = flags == NativeWindow::RotateLeft;
-@@ -738,6 +738,12 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width,
- d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, rotateR ? u1 : u2, rotateL ? v2 : v1);
- d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, rotateL ? u1 : u2, rotateR ? v1 : v2);
- #else
-+ // Create a quad in homogeneous coordinates
-+ float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
-+ float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
-+ float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
-+ float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f;
-+
- float u1 = x / float(mWidth);
- float v1 = y / float(mHeight);
- float u2 = (x + width) / float(mWidth);
-@@ -788,8 +794,8 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width,
- viewport.TopLeftX = 0;
- viewport.TopLeftY = 0;
- #if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
-- viewport.Width = (rotateL || rotateR) ? mHeight : mWidth;
-- viewport.Height = (rotateL || rotateR) ? mWidth : mHeight;
-+ viewport.Width = (rotateL || rotateR) ? height : width;
-+ viewport.Height = (rotateL || rotateR) ? width : height;
- #else
- viewport.Width = static_cast<FLOAT>(mWidth);
- viewport.Height = static_cast<FLOAT>(mHeight);
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
-index 6a4795a..b074e8c 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
-@@ -132,6 +132,7 @@ bool CoreWindowNativeWindow::registerForSizeChangeEvents()
- if (SUCCEEDED(result))
- {
- result = mDisplayInformation->add_OrientationChanged(orientationChangedHandler.Get(), &mOrientationChangedEventToken);
-+ orientationChangedHandler->Invoke(mDisplayInformation.Get(), nullptr);
- }
- #endif
-
-@@ -175,8 +176,8 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device,
- }
-
- DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 };
-- swapChainDesc.Width = width;
-- swapChainDesc.Height = height;
-+ swapChainDesc.Width = mRotationFlags ? height : width;
-+ swapChainDesc.Height = mRotationFlags ? width : height;
- swapChainDesc.Format = format;
- swapChainDesc.Stereo = FALSE;
- swapChainDesc.SampleDesc.Count = 1;
-diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp
-index 7536b19..e3c35d5 100644
---- a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp
-@@ -108,12 +108,14 @@ EGLBoolean EGLAPIENTRY PostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLin
- return EGL_FALSE;
- }
-
-+#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (defined(ANGLE_ENABLE_WINDOWS_STORE) && WINAPI_FAMILY == WINAPI_FAMILY_PC_APP) // Qt WP: Allow this entry point as a workaround
- if (!display->getExtensions().postSubBuffer)
- {
- // Spec is not clear about how this should be handled.
- SetGlobalError(Error(EGL_SUCCESS));
- return EGL_TRUE;
- }
-+#endif
-
- error = eglSurface->postSubBuffer(x, y, width, height);
- if (error.isError())
---
-2.7.0.windows.1
-
diff --git a/src/angle/patches/0004-ANGLE-fix-usage-of-shared-handles-for-WinRT-applicat.patch b/src/angle/patches/0004-ANGLE-fix-usage-of-shared-handles-for-WinRT-applicat.patch
new file mode 100644
index 0000000000..72a72f15be
--- /dev/null
+++ b/src/angle/patches/0004-ANGLE-fix-usage-of-shared-handles-for-WinRT-applicat.patch
@@ -0,0 +1,37 @@
+From 67125df3f31dfad0feec81c49c2b317c6d418f4e Mon Sep 17 00:00:00 2001
+From: Oliver Wolff <oliver.wolff@qt.io>
+Date: Wed, 22 Aug 2018 13:08:19 +0200
+Subject: [PATCH 4/8] ANGLE: fix usage of shared handles for WinRT applications
+
+The check is not relevant in Qt's context and was skipped before but
+it sneaked back in with the latest ANGLE update.
+
+Change-Id: Ic44de5468a3254afd76ef4804d97d245676daeb1
+---
+ src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
+index f696e360ef..cb4e51e42a 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
+@@ -2270,6 +2270,8 @@ bool Renderer11::getShareHandleSupport() const
+ return false;
+ }
+
++ // Qt: we don't care about the 9_3 limitation
++#if 0
+ // Also disable share handles on Feature Level 9_3, since it doesn't support share handles on
+ // RGBA8 textures/swapchains.
+ if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3)
+@@ -2277,6 +2279,7 @@ bool Renderer11::getShareHandleSupport() const
+ mSupportsShareHandles = false;
+ return false;
+ }
++#endif
+
+ // Find out which type of D3D11 device the Renderer11 is using
+ d3d11::ANGLED3D11DeviceType deviceType = getDeviceType();
+--
+2.15.0.windows.1
+
diff --git a/src/angle/patches/0005-ANGLE-Fix-compilation-without-d3d11.patch b/src/angle/patches/0005-ANGLE-Fix-compilation-without-d3d11.patch
deleted file mode 100644
index f32702dadf..0000000000
--- a/src/angle/patches/0005-ANGLE-Fix-compilation-without-d3d11.patch
+++ /dev/null
@@ -1,59 +0,0 @@
-From c224d27faf33fe2830b35eba22af0a637e1309cb Mon Sep 17 00:00:00 2001
-From: Oliver Wolff <oliver.wolff@theqtcompany.com>
-Date: Tue, 1 Mar 2016 14:14:29 +0100
-Subject: [PATCH 5/7] ANGLE: Fix compilation without d3d11
-
-Change-Id: I70ca8ef8ed205465a20c47756634ef6efc16ce85
----
- src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h | 4 +++-
- .../angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp | 2 ++
- 2 files changed, 5 insertions(+), 1 deletion(-)
-
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
-index 1c94538..612b06b 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
-@@ -39,7 +39,7 @@ class InspectableNativeWindow;
- using namespace Microsoft::WRL;
- using namespace Microsoft::WRL::Wrappers;
-
--#else
-+#elif defined(ANGLE_ENABLE_D3D11)
- typedef IDXGISwapChain DXGISwapChain;
- typedef IDXGIFactory DXGIFactory;
- #endif
-@@ -68,9 +68,11 @@ class NativeWindow
- #endif
- static bool isValidNativeWindow(EGLNativeWindowType window);
-
-+#if defined(ANGLE_ENABLE_D3D11)
- HRESULT createSwapChain(ID3D11Device* device, DXGIFactory* factory,
- DXGI_FORMAT format, UINT width, UINT height,
- DXGISwapChain** swapChain);
-+#endif
-
- inline EGLNativeWindowType getNativeWindow() const { return mWindow; }
-
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
-index 05d7a46..d96fed7 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
-@@ -56,6 +56,7 @@ bool NativeWindow::isValidNativeWindow(EGLNativeWindowType window)
- return IsWindow(window) == TRUE;
- }
-
-+#if defined(ANGLE_ENABLE_D3D11)
- HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory,
- DXGI_FORMAT format, unsigned int width, unsigned int height,
- DXGISwapChain** swapChain)
-@@ -191,6 +192,7 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory
-
- return factory->CreateSwapChain(device, &swapChainDesc, swapChain);
- }
-+#endif
-
- void NativeWindow::commitChange()
- {
---
-2.7.0.windows.1
-
diff --git a/src/angle/patches/0005-ANGLE-Fix-initialization-of-zero-sized-window.patch b/src/angle/patches/0005-ANGLE-Fix-initialization-of-zero-sized-window.patch
new file mode 100644
index 0000000000..eb67278628
--- /dev/null
+++ b/src/angle/patches/0005-ANGLE-Fix-initialization-of-zero-sized-window.patch
@@ -0,0 +1,32 @@
+From 8e649097b0e11d8b975ba321f343142dd97889cb Mon Sep 17 00:00:00 2001
+From: Oliver Wolff <oliver.wolff@qt.io>
+Date: Wed, 22 Aug 2018 13:12:07 +0200
+Subject: [PATCH 5/8] ANGLE: Fix initialization of zero-sized window
+
+The clientRect might be empty when creating a window of zero size. The
+side effect of a division by zero is that matrix transformation fails
+and hence the swapchain gets into an invalid state.
+
+Change-Id: Idbaed72deadb7b87052ac27e194a40d1810e6f7a
+---
+ .../libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp
+index c6d07fc888..3425fad95d 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp
+@@ -324,8 +324,8 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device,
+
+ HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const Size &windowSize, const RECT &clientRect)
+ {
+- Size renderScale = {windowSize.Width / (float)clientRect.right,
+- windowSize.Height / (float)clientRect.bottom};
++ Size renderScale = {windowSize.Width / std::max(LONG(1), clientRect.right),
++ windowSize.Height / std::max(LONG(1), clientRect.bottom)};
+ // Setup a scale matrix for the swap chain
+ DXGI_MATRIX_3X2_F scaleMatrix = {};
+ scaleMatrix._11 = renderScale.Width;
+--
+2.15.0.windows.1
+
diff --git a/src/angle/patches/0006-ANGLE-Fix-Windows-Store-D3D-Trim-and-Level-9-requirements.patch b/src/angle/patches/0006-ANGLE-Fix-Windows-Store-D3D-Trim-and-Level-9-requirements.patch
deleted file mode 100644
index eb0572f201..0000000000
--- a/src/angle/patches/0006-ANGLE-Fix-Windows-Store-D3D-Trim-and-Level-9-requirements.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-From b250c8e9c04cd1adccab7a6885273c9e6129131f Mon Sep 17 00:00:00 2001
-From: Oliver Wolff <oliver.wolff@theqtcompany.com>
-Date: Tue, 1 Mar 2016 14:16:52 +0100
-Subject: [PATCH 6/7] ANGLE: Fix Windows Store D3D Trim and Level 9 requirements
-
-Due to additional validation not covered in previous patches, the Windows
-Store certification compatibility had regressed. These changes ensure that
-the required D3D behaviors are met.
-
-Change-Id: If8bc2f8cd4b2f84e1d92a1627951da2537212125
----
- .../angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp | 15 ++++++++++++++-
- src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp | 2 ++
- 2 files changed, 16 insertions(+), 1 deletion(-)
-
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
-index 03159bb..ea84783 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
-@@ -453,7 +453,20 @@ Renderer11::Renderer11(egl::Display *display)
- if (requestedMajorVersion == 9 && requestedMinorVersion == 3)
- #endif
- {
-- mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3);
-+ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 3)
-+ {
-+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3);
-+ }
-+#if defined(ANGLE_ENABLE_WINDOWS_STORE)
-+ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 2)
-+ {
-+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2);
-+ }
-+ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
-+ {
-+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1);
-+ }
-+#endif
- }
-
- EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
-diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp
-index e3c35d5..6c7e2ff 100644
---- a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp
-@@ -50,6 +50,8 @@ EGLBoolean EGLAPIENTRY QuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surfa
- // validate the attribute parameter
- switch (attribute)
- {
-+ case EGL_DEVICE_EXT:
-+ break;
- case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
- if (!display->getExtensions().surfaceD3DTexture2DShareHandle)
- {
---
-2.7.0.windows.1
-
diff --git a/src/angle/patches/0006-ANGLE-Fix-flickering-on-resize-when-D3D9-is-used.patch b/src/angle/patches/0006-ANGLE-Fix-flickering-on-resize-when-D3D9-is-used.patch
new file mode 100644
index 0000000000..f515b0a072
--- /dev/null
+++ b/src/angle/patches/0006-ANGLE-Fix-flickering-on-resize-when-D3D9-is-used.patch
@@ -0,0 +1,165 @@
+From 0fc1b9c7e87ab6cdb6bf7c81a1eee0a1d1f74e92 Mon Sep 17 00:00:00 2001
+From: Oliver Wolff <oliver.wolff@qt.io>
+Date: Wed, 22 Aug 2018 13:24:43 +0200
+Subject: [PATCH 6/8] ANGLE: Fix flickering on resize when D3D9 is used
+
+By reverting ANGLE change d3b84ab51db09de238459b0dff2e8420c09aabf3
+we get rid of the flickering that happens on resize when D3D9 is
+used. The issue that was fixed there is not relevant in Qt's
+context so it is safe to revert the change.
+
+Task-number: QTBUG-59893
+Change-Id: I9306314b892612fbd1f7a058a2e606aedc0367bb
+---
+ .../angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp | 89 ++++++++++++++++++++++
+ .../angle/src/libANGLE/renderer/d3d/SurfaceD3D.h | 4 +
+ 2 files changed, 93 insertions(+)
+
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
+index ceb022d14c..8d3f44f2ad 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
+@@ -38,6 +38,7 @@ SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state,
+ mDepthStencilFormat(state.config->depthStencilFormat),
+ mSwapChain(nullptr),
+ mSwapIntervalDirty(true),
++ mWindowSubclassed(false),
+ mNativeWindow(renderer->createNativeWindow(window, state.config, attribs)),
+ mWidth(static_cast<EGLint>(attribs.get(EGL_WIDTH, 0))),
+ mHeight(static_cast<EGLint>(attribs.get(EGL_HEIGHT, 0))),
+@@ -45,6 +46,7 @@ SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state,
+ mShareHandle(0),
+ mD3DTexture(nullptr)
+ {
++ subclassWindow();
+ if (window != nullptr && !mFixedSize)
+ {
+ mWidth = -1;
+@@ -72,6 +74,7 @@ SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state,
+
+ SurfaceD3D::~SurfaceD3D()
+ {
++ unsubclassWindow();
+ releaseSwapChain();
+ SafeDelete(mNativeWindow);
+ SafeRelease(mD3DTexture);
+@@ -256,6 +259,92 @@ egl::Error SurfaceD3D::swapRect(const gl::Context *context,
+ return egl::NoError();
+ }
+
++#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
++#define kSurfaceProperty _TEXT("Egl::SurfaceOwner")
++#define kParentWndProc _TEXT("Egl::SurfaceParentWndProc")
++#define kDisplayProperty _TEXT("Egl::Display")
++
++static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
++{
++ if (message == WM_SIZE)
++ {
++ SurfaceD3D* surf = reinterpret_cast<SurfaceD3D*>(GetProp(hwnd, kSurfaceProperty));
++ if(surf)
++ {
++ egl::Display *display = reinterpret_cast<egl::Display *>(GetProp(hwnd, kDisplayProperty));
++ surf->checkForOutOfDateSwapChain(display->getProxyContext());
++ }
++ }
++ WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc));
++ return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam);
++}
++#endif
++
++void SurfaceD3D::subclassWindow()
++{
++#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
++ HWND window = mNativeWindow->getNativeWindow();
++ if (!window)
++ {
++ return;
++ }
++
++ DWORD processId;
++ DWORD threadId = GetWindowThreadProcessId(window, &processId);
++ if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId())
++ {
++ return;
++ }
++
++ SetLastError(0);
++ LONG_PTR oldWndProc = SetWindowLongPtr(window, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
++ if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS)
++ {
++ mWindowSubclassed = false;
++ return;
++ }
++
++ SetProp(window, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
++ SetProp(window, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc));
++ SetProp(window, kDisplayProperty, reinterpret_cast<HANDLE>(mDisplay));
++ mWindowSubclassed = true;
++#endif
++}
++
++void SurfaceD3D::unsubclassWindow()
++{
++ if (!mWindowSubclassed)
++ {
++ return;
++ }
++
++#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
++ HWND window = mNativeWindow->getNativeWindow();
++ if (!window)
++ {
++ return;
++ }
++
++ // un-subclass
++ LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(GetProp(window, kParentWndProc));
++
++ // Check the windowproc is still SurfaceWindowProc.
++ // If this assert fails, then it is likely the application has subclassed the
++ // hwnd as well and did not unsubclass before destroying its EGL context. The
++ // application should be modified to either subclass before initializing the
++ // EGL context, or to unsubclass before destroying the EGL context.
++ if(parentWndFunc)
++ {
++ LONG_PTR prevWndFunc = SetWindowLongPtr(window, GWLP_WNDPROC, parentWndFunc);
++ ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
++ }
++
++ RemoveProp(window, kSurfaceProperty);
++ RemoveProp(window, kParentWndProc);
++ RemoveProp(window, kDisplayProperty);
++#endif
++ mWindowSubclassed = false;
++}
++
++
+ egl::Error SurfaceD3D::checkForOutOfDateSwapChain(const gl::Context *context)
+ {
+ RECT client;
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h
+index 4fd45a6dfd..01d2573244 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h
+@@ -82,6 +82,9 @@ class SurfaceD3D : public SurfaceImpl
+ int backbufferWidth,
+ int backbufferHeight);
+
++ void subclassWindow();
++ void unsubclassWindow();
++
+ RendererD3D *mRenderer;
+ egl::Display *mDisplay;
+
+@@ -93,6 +96,7 @@ class SurfaceD3D : public SurfaceImpl
+
+ SwapChainD3D *mSwapChain;
+ bool mSwapIntervalDirty;
++ bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking
+
+ NativeWindowD3D *mNativeWindow; // Handler for the Window that the surface is created for.
+ EGLint mWidth;
+--
+2.15.0.windows.1
+
diff --git a/src/angle/patches/0007-ANGLE-D3D11-Suppress-keyboard-handling-of-DXGI.patch b/src/angle/patches/0007-ANGLE-D3D11-Suppress-keyboard-handling-of-DXGI.patch
deleted file mode 100644
index badd1d7201..0000000000
--- a/src/angle/patches/0007-ANGLE-D3D11-Suppress-keyboard-handling-of-DXGI.patch
+++ /dev/null
@@ -1,45 +0,0 @@
-From 955357382b1bb02043ec744ef3b5929e29c4f8cc Mon Sep 17 00:00:00 2001
-From: Oliver Wolff <oliver.wolff@theqtcompany.com>
-Date: Tue, 12 Apr 2016 14:44:26 +0200
-Subject: [PATCH 7/7] ANGLE/D3D11: Suppress keyboard handling of DXGI.
-
-Set the DXGI_MWA_NO_ALT_ENTER to suppress the Alt-Enter shortcut
-causing the window to become full screen.
-
-Task-number: QTBUG-44904
-Change-Id: If24c32df69a5a47e29d14be8f2624abfac5cd634
----
- .../src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp | 10 +++++++++-
- 1 file changed, 9 insertions(+), 1 deletion(-)
-
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
-index 7da7f31..da6460b 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
-@@ -171,6 +171,8 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory
- HRESULT result = factory2->CreateSwapChainForHwnd(device, mWindow, &swapChainDesc, nullptr, nullptr, &swapChain1);
- if (SUCCEEDED(result))
- {
-+ const HRESULT makeWindowAssociationResult = factory->MakeWindowAssociation(mWindow, DXGI_MWA_NO_ALT_ENTER);
-+ UNUSED_VARIABLE(makeWindowAssociationResult);
- *swapChain = static_cast<DXGISwapChain*>(swapChain1);
- }
- SafeRelease(factory2);
-@@ -196,7 +198,13 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory
- swapChainDesc.Windowed = TRUE;
- swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
-
-- return factory->CreateSwapChain(device, &swapChainDesc, swapChain);;
-+ const HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, swapChain);
-+ if (SUCCEEDED(result))
-+ {
-+ const HRESULT makeWindowAssociationResult = factory->MakeWindowAssociation(mWindow, DXGI_MWA_NO_ALT_ENTER);
-+ UNUSED_VARIABLE(makeWindowAssociationResult);
-+ }
-+ return result;
- }
- #endif
-
---
-2.7.0.windows.1
-
diff --git a/src/angle/patches/0007-ANGLE-Fix-resizing-of-windows.patch b/src/angle/patches/0007-ANGLE-Fix-resizing-of-windows.patch
new file mode 100644
index 0000000000..2b4938be9b
--- /dev/null
+++ b/src/angle/patches/0007-ANGLE-Fix-resizing-of-windows.patch
@@ -0,0 +1,48 @@
+From f1568e10c2bd46450adebbd838bd32e4833a0a5c Mon Sep 17 00:00:00 2001
+From: Oliver Wolff <oliver.wolff@qt.io>
+Date: Wed, 22 Aug 2018 13:32:44 +0200
+Subject: [PATCH 7/8] ANGLE: Fix resizing of windows
+
+Use the correct height/width values when calculating
+the vector for resizing the window content and the
+new size as viewport size.
+
+Task-number: QTBUG-62475
+Change-Id: I33a8dc1379a908e991b04bc31dfc6254a6d005c9
+---
+ .../src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp | 19 +++++++++----------
+ 1 file changed, 9 insertions(+), 10 deletions(-)
+
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
+index 05bb5d9863..dcfd06484d 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
+@@ -796,16 +796,15 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(const gl::Context *context,
+ d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
+
+ // Create a quad in homogeneous coordinates
+- float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
+- float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
+- float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
+- float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f;
+-
+- float u1 = x / float(mWidth);
+- float v1 = y / float(mHeight);
+- float u2 = (x + width) / float(mWidth);
+- float v2 = (y + height) / float(mHeight);
+-
++ float x1 = (x / float(width)) * 2.0f - 1.0f;
++ float y1 = (y / float(height)) * 2.0f - 1.0f;
++ float x2 = ((x + width) / float(width)) * 2.0f - 1.0f;
++ float y2 = ((y + height) / float(height)) * 2.0f - 1.0f;
++
++ float u1 = x / float(width);
++ float v1 = y / float(height);
++ float u2 = (x + width) / float(width);
++ float v2 = (y + height) / float(height);
+ // Invert the quad vertices depending on the surface orientation.
+ if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE) != 0)
+ {
+--
+2.15.0.windows.1
+
diff --git a/src/angle/patches/0008-ANGLE-Use-pixel-sizes-in-the-XAML-swap-chain.patch b/src/angle/patches/0008-ANGLE-Use-pixel-sizes-in-the-XAML-swap-chain.patch
deleted file mode 100644
index 7f7517e554..0000000000
--- a/src/angle/patches/0008-ANGLE-Use-pixel-sizes-in-the-XAML-swap-chain.patch
+++ /dev/null
@@ -1,401 +0,0 @@
-From 7a3851e74393eb254826face20b8e9af74bbdf0b Mon Sep 17 00:00:00 2001
-From: Oliver Wolff <oliver.wolff@theqtcompany.com>
-Date: Thu, 17 Mar 2016 15:46:56 +0100
-Subject: [PATCH] ANGLE: Use pixel sizes in the XAML swap chain
-
-This is necessary for Qt applications, as they render to GL in physical
-pixels. This is consistent with the CoreWindow swap chain behavior.
-
-This includes a partial revert of "ANGLE: Improve Windows Phone Support"
-as the modifications to SwapChain11 are incompatible with the XAML swap
-chain.
-
-This change only affects Windows Runtime targets.
-
-Change-Id: I401ae81028a9dfdb9da37f51c60844467c476f76
----
- .../libANGLE/renderer/d3d/d3d11/SwapChain11.cpp | 46 ----------------------
- .../d3d/d3d11/winrt/CoreWindowNativeWindow.cpp | 25 +-----------
- .../d3d/d3d11/winrt/CoreWindowNativeWindow.h | 7 +---
- .../d3d/d3d11/winrt/InspectableNativeWindow.cpp | 20 ++++++++++
- .../d3d/d3d11/winrt/InspectableNativeWindow.h | 9 +++--
- .../d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp | 43 ++++++++++++--------
- .../d3d/d3d11/winrt/SwapChainPanelNativeWindow.h | 7 ++--
- 7 files changed, 58 insertions(+), 99 deletions(-)
-
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
-index f80f24b..785a83c 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
-@@ -226,14 +226,8 @@ EGLint SwapChain11::resetOffscreenColorBuffer(int backbufferWidth, int backbuffe
- const bool useSharedResource = !mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport();
-
- D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
--#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
-- const int textureLength = std::max(backbufferWidth, backbufferHeight);
-- offscreenTextureDesc.Width = textureLength;
-- offscreenTextureDesc.Height = textureLength;
--#else
- offscreenTextureDesc.Width = backbufferWidth;
- offscreenTextureDesc.Height = backbufferHeight;
--#endif
- offscreenTextureDesc.Format = backbufferFormatInfo.texFormat;
- offscreenTextureDesc.MipLevels = 1;
- offscreenTextureDesc.ArraySize = 1;
-@@ -346,14 +340,8 @@ EGLint SwapChain11::resetOffscreenDepthBuffer(int backbufferWidth, int backbuffe
- d3d11::GetTextureFormatInfo(mDepthBufferFormat, mRenderer->getRenderer11DeviceCaps());
-
- D3D11_TEXTURE2D_DESC depthStencilTextureDesc;
--#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
-- const int textureLength = std::max(backbufferWidth, backbufferHeight);
-- depthStencilTextureDesc.Width = textureLength;
-- depthStencilTextureDesc.Height = textureLength;
--#else
- depthStencilTextureDesc.Width = backbufferWidth;
- depthStencilTextureDesc.Height = backbufferHeight;
--#endif
- depthStencilTextureDesc.Format = depthBufferFormatInfo.texFormat;
- depthStencilTextureDesc.MipLevels = 1;
- depthStencilTextureDesc.ArraySize = 1;
-@@ -438,7 +426,6 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
- return EGL_SUCCESS;
- }
-
--#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
- // Can only call resize if we have already created our swap buffer and resources
- ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView && mBackBufferSRView);
-
-@@ -496,12 +483,6 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
- mFirstSwap = true;
-
- return resetOffscreenBuffers(backbufferWidth, backbufferHeight);
--#else
-- // Do nothing on Windows Phone apart from updating the internal buffer/width height
-- mWidth = backbufferWidth;
-- mHeight = backbufferHeight;
-- return EGL_SUCCESS;
--#endif
- }
-
- DXGI_FORMAT SwapChain11::getSwapChainNativeFormat() const
-@@ -725,27 +706,6 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width,
-
- d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
-
--#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
-- // Create a quad in homogeneous coordinates
-- float x1 = -1.0f;
-- float y1 = -1.0f;
-- float x2 = 1.0f;
-- float y2 = 1.0f;
--
-- const float dim = std::max(mWidth, mHeight);
-- float u1 = 0;
-- float v1 = 0;
-- float u2 = float(width) / dim;
-- float v2 = float(height) / dim;
--
-- const NativeWindow::RotationFlags flags = mNativeWindow.rotationFlags();
-- const bool rotateL = flags == NativeWindow::RotateLeft;
-- const bool rotateR = flags == NativeWindow::RotateRight;
-- d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, rotateL ? u2 : u1, rotateR ? v2 : v1);
-- d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, rotateR ? u2 : u1, rotateL ? v1 : v2);
-- d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, rotateR ? u1 : u2, rotateL ? v2 : v1);
-- d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, rotateL ? u1 : u2, rotateR ? v1 : v2);
--#else
- // Create a quad in homogeneous coordinates
- float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
- float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
-@@ -771,7 +731,6 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width,
- d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2);
- d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
- d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2);
--#endif
-
- deviceContext->Unmap(mQuadVB, 0);
-
-@@ -801,13 +760,8 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width,
- D3D11_VIEWPORT viewport;
- viewport.TopLeftX = 0;
- viewport.TopLeftY = 0;
--#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
-- viewport.Width = (rotateL || rotateR) ? height : width;
-- viewport.Height = (rotateL || rotateR) ? width : height;
--#else
- viewport.Width = static_cast<FLOAT>(mWidth);
- viewport.Height = static_cast<FLOAT>(mHeight);
--#endif
- viewport.MinDepth = 0.0f;
- viewport.MaxDepth = 1.0f;
- deviceContext->RSSetViewports(1, &viewport);
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
-index b074e8c..f401db6 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
-@@ -222,7 +222,7 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device,
- return result;
- }
-
--inline HRESULT CoreWindowNativeWindow::scaleSwapChain(const SIZE &windowSize, const RECT &clientRect)
-+inline HRESULT CoreWindowNativeWindow::scaleSwapChain(const Size &windowSize, const RECT &clientRect)
- {
- // We don't need to do any additional work to scale CoreWindow swapchains.
- // Using DXGI_SCALING_STRETCH to create the swapchain above does all the necessary work.
-@@ -240,27 +240,4 @@ HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWind
-
- return result;
- }
--
--static float GetLogicalDpi()
--{
-- ComPtr<ABI::Windows::Graphics::Display::IDisplayPropertiesStatics> displayProperties;
--
-- if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), displayProperties.GetAddressOf())))
-- {
-- float dpi = 96.0f;
-- if (SUCCEEDED(displayProperties->get_LogicalDpi(&dpi)))
-- {
-- return dpi;
-- }
-- }
--
-- // Return 96 dpi as a default if display properties cannot be obtained.
-- return 96.0f;
--}
--
--long ConvertDipsToPixels(float dips)
--{
-- static const float dipsPerInch = 96.0f;
-- return lround((dips * GetLogicalDpi() / dipsPerInch));
--}
- }
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h
-index 4de235a..fc1cd12 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h
-@@ -19,8 +19,6 @@ typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CGraphics__CD
-
- namespace rx
- {
--long ConvertDipsToPixels(float dips);
--
- class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<CoreWindowNativeWindow>
- {
- public:
-@@ -36,7 +34,7 @@ class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enabl
- DXGISwapChain **swapChain) override;
-
- protected:
-- HRESULT scaleSwapChain(const SIZE &windowSize, const RECT &clientRect) override;
-+ HRESULT scaleSwapChain(const Size &windowSize, const RECT &clientRect) override;
-
- bool registerForSizeChangeEvents();
- void unregisterForSizeChangeEvents();
-@@ -74,8 +72,7 @@ class CoreWindowSizeChangedHandler :
- ABI::Windows::Foundation::Size windowSize;
- if (SUCCEEDED(sizeChangedEventArgs->get_Size(&windowSize)))
- {
-- SIZE windowSizeInPixels = { ConvertDipsToPixels(windowSize.Width), ConvertDipsToPixels(windowSize.Height) };
-- host->setNewClientSize(windowSizeInPixels);
-+ host->setNewClientSize(windowSize);
- }
- }
-
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
-index c9b203e..aacfadd 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
-@@ -381,4 +381,24 @@ HRESULT GetOptionalSinglePropertyValue(const ComPtr<ABI::Windows::Foundation::Co
- return result;
- }
-
-+static float GetLogicalDpi()
-+{
-+ ComPtr<ABI::Windows::Graphics::Display::IDisplayPropertiesStatics> displayProperties;
-+ float dpi = 96.0f;
-+
-+ if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), displayProperties.GetAddressOf())))
-+ {
-+ if (SUCCEEDED(displayProperties->get_LogicalDpi(&dpi)))
-+ {
-+ return dpi;
-+ }
-+ }
-+ return dpi;
-+}
-+
-+long ConvertDipsToPixels(float dips)
-+{
-+ static const float dipsPerInch = 96.0f;
-+ return lround((dips * GetLogicalDpi() / dipsPerInch));
-+}
- }
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h
-index 70e5fe7..cdbf40e 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h
-@@ -26,6 +26,8 @@ using namespace ABI::Windows::Foundation::Collections;
-
- namespace rx
- {
-+long ConvertDipsToPixels(float dips);
-+
- class InspectableNativeWindow
- {
- public:
-@@ -65,7 +67,7 @@ class InspectableNativeWindow
- }
-
- // setNewClientSize is used by the WinRT size change handler. It isn't used by the rest of ANGLE.
-- void setNewClientSize(const SIZE &newWindowSize)
-+ void setNewClientSize(const Size &newWindowSize)
- {
- // If the client doesn't support swapchain resizing then we should have already unregistered from size change handler
- ASSERT(mSupportsSwapChainResize);
-@@ -76,7 +78,8 @@ class InspectableNativeWindow
- if (!mSwapChainSizeSpecified)
- {
- // We don't have to check if a swapchain scale was specified here; the default value is 1.0f which will have no effect.
-- mNewClientRect = { 0, 0, static_cast<long>(newWindowSize.cx * mSwapChainScale), static_cast<long>(newWindowSize.cy * mSwapChainScale) };
-+ mNewClientRect = { 0, 0, ConvertDipsToPixels(newSize.Width), ConvertDipsToPixels(newSize.Height) };
- mClientRectChanged = true;
-
- // If a scale was specified, then now is the time to apply the scale matrix for the new swapchain size and window size
-@@ -106,7 +109,7 @@ class InspectableNativeWindow
- }
-
- protected:
-- virtual HRESULT scaleSwapChain(const SIZE &windowSize, const RECT &clientRect) = 0;
-+ virtual HRESULT scaleSwapChain(const Size &windowSize, const RECT &clientRect) = 0;
-
- bool mSupportsSwapChainResize; // Support for IDXGISwapChain::ResizeBuffers method
- bool mSwapChainSizeSpecified; // If an EGLRenderSurfaceSizeProperty was specified
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp
-index 1ed3645..d3ed35b 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp
-@@ -171,12 +171,15 @@ bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropert
- {
- SIZE swapChainPanelSize;
- result = GetSwapChainPanelSize(mSwapChainPanel, mSwapChainPanelDispatcher,
-- &swapChainPanelSize);
-+ &swapChainPanelSize, &mSwapChainScale);
-+ if (mSwapChainScale != 1.0f)
-+ mSwapChainScaleSpecified = true;
-
- if (SUCCEEDED(result))
- {
- // Update the client rect to account for any swapchain scale factor
-- mClientRect = { 0, 0, static_cast<long>(swapChainPanelSize.cx * mSwapChainScale), static_cast<long>(swapChainPanelSize.cy * mSwapChainScale) };
-+ mClientRect = { 0, 0, static_cast<long>(ConvertDipsToPixels(swapChainPanelSize.cx * mSwapChainScale)),
-+ static_cast<long>(ConvertDipsToPixels(swapChainPanelSize.cy * mSwapChainScale)) };
- }
- }
- }
-@@ -269,7 +272,6 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device,
-
- ComPtr<IDXGISwapChain1> newSwapChain;
- ComPtr<ISwapChainPanelNative> swapChainPanelNative;
-- SIZE currentPanelSize = {};
-
- HRESULT result = factory->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf());
-
-@@ -304,24 +306,24 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device,
- {
- if (mSwapChainSizeSpecified || mSwapChainScaleSpecified)
- {
-- result = GetSwapChainPanelSize(mSwapChainPanel, mSwapChainPanelDispatcher,
-- &currentPanelSize);
--
-- // Scale the swapchain to fit inside the contents of the panel.
-- if (SUCCEEDED(result))
-- {
-- result = scaleSwapChain(currentPanelSize, mClientRect);
-- }
-+ ComPtr<ABI::Windows::UI::Xaml::IUIElement> uiElement;
-+ result = mSwapChainPanel.As(&uiElement);
-+ ASSERT(SUCCEEDED(result));
-+
-+ Size currentSize;
-+ result = uiElement->get_RenderSize(&currentSize);
-+ ASSERT(SUCCEEDED(result));
-+ result = scaleSwapChain(currentSize, mClientRect);
- }
- }
-
- return result;
- }
-
--HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const SIZE &windowSize, const RECT &clientRect)
-+HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const Size &windowSize, const RECT &clientRect)
- {
-- Size renderScale = {(float)windowSize.cx / (float)clientRect.right,
-- (float)windowSize.cy / (float)clientRect.bottom};
-+ Size renderScale = {windowSize.Width / clientRect.right,
-+ windowSize.Height / clientRect.bottom};
- // Setup a scale matrix for the swap chain
- DXGI_MATRIX_3X2_F scaleMatrix = {};
- scaleMatrix._11 = renderScale.Width;
-@@ -340,7 +342,7 @@ HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const SIZE &windowSize, const
- HRESULT GetSwapChainPanelSize(
- const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel,
- const ComPtr<ICoreDispatcher> &dispatcher,
-- SIZE *windowSize)
-+ SIZE *windowSize, float *scaleFactor)
- {
- ComPtr<IUIElement> uiElement;
- Size renderSize = {0, 0};
-@@ -357,9 +359,16 @@ HRESULT GetSwapChainPanelSize(
-
- if (SUCCEEDED(result))
- {
-- *windowSize = { lround(renderSize.Width), lround(renderSize.Height) };
-+ long width = ConvertDipsToPixels(renderSize.Width);
-+ long height = ConvertDipsToPixels(renderSize.Height);
-+ *windowSize = { width, height };
-+
-+ if (scaleFactor)
-+ {
-+ *scaleFactor = renderSize.Width / width;
-+ }
- }
-
- return result;
- }
--}
-\ No newline at end of file
-+}
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h
-index 9cc051d..09d87ad 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h
-@@ -28,7 +28,7 @@ class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::e
- DXGISwapChain **swapChain) override;
-
- protected:
-- HRESULT scaleSwapChain(const SIZE &windowSize, const RECT &clientRect) override;
-+ HRESULT scaleSwapChain(const Size &windowSize, const RECT &clientRect) override;
-
- bool registerForSizeChangeEvents();
- void unregisterForSizeChangeEvents();
-@@ -72,8 +72,7 @@ class SwapChainPanelSizeChangedHandler :
- HRESULT result = sizeChangedEventArgs->get_NewSize(&newSize);
- if (SUCCEEDED(result))
- {
-- SIZE windowSize = { lround(newSize.Width), lround(newSize.Height) };
-- host->setNewClientSize(windowSize);
-+ host->setNewClientSize(newSize);
- }
- }
-
-@@ -87,6 +86,6 @@ class SwapChainPanelSizeChangedHandler :
- HRESULT GetSwapChainPanelSize(
- const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel,
- const ComPtr<ABI::Windows::UI::Core::ICoreDispatcher> &dispatcher,
-- SIZE *windowSize);
-+ SIZE *windowSize, float *scaleFactor);
- }
- #endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_
---
-2.7.0.windows.1
-
diff --git a/src/angle/patches/0008-ANGLE-winrt-Do-full-screen-update-if-the-the-window-.patch b/src/angle/patches/0008-ANGLE-winrt-Do-full-screen-update-if-the-the-window-.patch
new file mode 100644
index 0000000000..d9b51fc411
--- /dev/null
+++ b/src/angle/patches/0008-ANGLE-winrt-Do-full-screen-update-if-the-the-window-.patch
@@ -0,0 +1,40 @@
+From 5a58c6c7d97f003aa4a34ae130697dc81cc8fdf8 Mon Sep 17 00:00:00 2001
+From: Oliver Wolff <oliver.wolff@qt.io>
+Date: Wed, 22 Aug 2018 15:17:52 +0200
+Subject: [PATCH 8/8] ANGLE: winrt: Do full screen update if the the window
+ size is reduced
+
+We cannot do partial updates if the window size is reduced as this will
+result in a "pDstBox is not a valid box for the destination subresource."
+error.
+
+Change-Id: I9a8d91bca961f52e1aab1bec5321922cfc842fb3
+---
+ .../src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
+index 8f76d16c30..b702450ded 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
+@@ -664,9 +664,14 @@ gl::Error TextureStorage11::setData(const gl::Context *context,
+ // with compressed formats in the calling logic.
+ ASSERT(!internalFormatInfo.compressed);
+
+- const int width = destBox ? destBox->width : static_cast<int>(image->getWidth());
+- const int height = destBox ? destBox->height : static_cast<int>(image->getHeight());
+- const int depth = destBox ? destBox->depth : static_cast<int>(image->getDepth());
++ const int imageWidth = static_cast<int>(image->getWidth());
++ const int width = destBox ? destBox->width : imageWidth;
++ const int imageHeight = static_cast<int>(image->getHeight());
++ const int height = destBox ? destBox->height : imageHeight;
++ const int imageDepth = static_cast<int>(image->getDepth());
++ const int depth = destBox ? destBox->depth : imageDepth;
++ if (imageWidth < width || imageHeight < height || imageDepth < depth)
++ fullUpdate = true;
+ GLuint srcRowPitch = 0;
+ ANGLE_TRY_RESULT(
+ internalFormatInfo.computeRowPitch(type, width, unpack.alignment, unpack.rowLength),
+--
+2.15.0.windows.1
+
diff --git a/src/angle/patches/0009-ANGLE-glGetUniform-v-functions-to-work-properly.patch b/src/angle/patches/0009-ANGLE-glGetUniform-v-functions-to-work-properly.patch
deleted file mode 100644
index b53e11038b..0000000000
--- a/src/angle/patches/0009-ANGLE-glGetUniform-v-functions-to-work-properly.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 2d4a7aec7957e507cbf0b4b8dcf68abb26667e33 Mon Sep 17 00:00:00 2001
-From: Miikka Heikkinen <miikka.heikkinen@qt.io>
-Date: Mon, 9 May 2016 13:13:20 +0300
-Subject: [PATCH] Fix ANGLE glGetUniform*v functions to work properly array
- uniforms
-
-glGetUniform*v functions are supposed to return just a single
-array element, so returning the whole array is always incorrect.
-
-Task-number: QTBUG-53072
-Change-Id: I22f05d420082d4d9de06d975b3d0f5e64d3e0c41
----
- src/3rdparty/angle/src/libANGLE/Program.cpp | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/3rdparty/angle/src/libANGLE/Program.cpp b/src/3rdparty/angle/src/libANGLE/Program.cpp
-index 748ceae..69497c4 100644
---- a/src/3rdparty/angle/src/libANGLE/Program.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/Program.cpp
-@@ -2510,7 +2510,7 @@ void Program::getUniformInternal(GLint location, DestT *dataOut) const
- return;
- }
-
-- int components = VariableComponentCount(uniform.type) * uniform.elementCount();
-+ int components = VariableComponentCount(uniform.type);
-
- switch (componentType)
- {
---
-2.6.3.windows.1
-
diff --git a/src/angle/patches/0009-Revert-Fix-scanForWantedComponents-not-ignoring-attr.patch b/src/angle/patches/0009-Revert-Fix-scanForWantedComponents-not-ignoring-attr.patch
new file mode 100644
index 0000000000..f57f528ad8
--- /dev/null
+++ b/src/angle/patches/0009-Revert-Fix-scanForWantedComponents-not-ignoring-attr.patch
@@ -0,0 +1,67 @@
+From 2fb4d8087c4f324b7a3f2e21554374de7060e996 Mon Sep 17 00:00:00 2001
+From: Andre de la Rocha <andre.rocha@qt.io>
+Date: Tue, 11 Sep 2018 12:52:28 +0200
+Subject: [PATCH] Revert "Fix scanForWantedComponents not ignoring
+ attribute values of 0."
+
+This patch reverts commit 2648d9297f25a0d1fa2837f020975a45d4e8a8b9 as a
+workaround for the "banding" artifacts we were seeing in Qt. Angle
+returns a list of supported graphic formats or configurations, sorting
+it in a way that the first one should be the one that fits better the
+requested format. In Qt we use the first thing we receive in the list.
+In the current Angle version, however, a fix has changed the way in
+which the list is sorted. In the old version the first element would be
+a 32-bit graphic format, while now it's a 16-bit one, resulting in the
+"banding" artifacts. The workaround reverts back to the previous sorting
+behavior.
+---
+ .../libANGLE/Config.cpp | 29 +++++++++++++++++------------
+ 1 file changed, 17 insertions(+), 12 deletions(-)
+
+diff --git a/src/3rdparty/angle/src/libANGLE/Config.cpp b/src/3rdparty/angle/src/libANGLE/Config.cpp
+index ccf64c8f8..4f14e73ef 100644
+--- a/src/3rdparty/angle/src/libANGLE/Config.cpp
++++ b/src/3rdparty/angle/src/libANGLE/Config.cpp
+@@ -181,22 +181,27 @@ class ConfigSorter
+ }
+
+ private:
+- static bool wantsComponent(const AttributeMap &attributeMap, EGLAttrib component)
++ void scanForWantedComponents(const AttributeMap &attributeMap)
+ {
+ // [EGL 1.5] section 3.4.1.2 page 30
+ // Sorting rule #3: by larger total number of color bits, not considering
+ // components that are 0 or don't-care.
+- EGLAttrib value = attributeMap.get(component, 0);
+- return value != 0 && value != EGL_DONT_CARE;
+- }
+-
+- void scanForWantedComponents(const AttributeMap &attributeMap)
+- {
+- mWantRed = wantsComponent(attributeMap, EGL_RED_SIZE);
+- mWantGreen = wantsComponent(attributeMap, EGL_GREEN_SIZE);
+- mWantBlue = wantsComponent(attributeMap, EGL_BLUE_SIZE);
+- mWantAlpha = wantsComponent(attributeMap, EGL_ALPHA_SIZE);
+- mWantLuminance = wantsComponent(attributeMap, EGL_LUMINANCE_SIZE);
++ for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++)
++ {
++ EGLAttrib attributeKey = attribIter->first;
++ EGLAttrib attributeValue = attribIter->second;
++ if (attributeKey != 0 && attributeValue != EGL_DONT_CARE)
++ {
++ switch (attributeKey)
++ {
++ case EGL_RED_SIZE: mWantRed = true; break;
++ case EGL_GREEN_SIZE: mWantGreen = true; break;
++ case EGL_BLUE_SIZE: mWantBlue = true; break;
++ case EGL_ALPHA_SIZE: mWantAlpha = true; break;
++ case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
++ }
++ }
++ }
+ }
+
+ EGLint wantedComponentsSize(const Config &config) const
+--
+2.14.1.windows.1
+
diff --git a/src/angle/patches/0010-ANGLE-Disable-multisampling-to-avoid-crash-in-Qt-app.patch b/src/angle/patches/0010-ANGLE-Disable-multisampling-to-avoid-crash-in-Qt-app.patch
new file mode 100644
index 0000000000..2fb65ce220
--- /dev/null
+++ b/src/angle/patches/0010-ANGLE-Disable-multisampling-to-avoid-crash-in-Qt-app.patch
@@ -0,0 +1,41 @@
+From d239cceef88fbbe4cf7479025f12934d9c3c83a5 Mon Sep 17 00:00:00 2001
+From: Andre de la Rocha <andre.rocha@qt.io>
+Date: Tue, 11 Sep 2018 12:57:23 +0200
+Subject: [PATCH] ANGLE: Disable multisampling to avoid crash in Qt
+ applications
+
+This patch adds a workaround for the crash that occurs with multisampling
+enabled in some Qt applications (e.g., the 2dpainting example). The old
+Angle release we were using lacked support for multisampling, so it was
+ignored when requested. This current version seems to support it, but is
+causing a crash in the D3D11 shaders, so this workaround disables that
+support.
+---
+ .../libANGLE/renderer/d3d/d3d11/Renderer11.cpp | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
+index bd14f4de2..f487538a5 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
+@@ -997,6 +997,8 @@ gl::SupportedSampleSet Renderer11::generateSampleSetForEGLConfig(
+ {
+ gl::SupportedSampleSet sampleCounts;
+
++#if 0 // Qt: Disabling support for multisampling as it is causing a crash in the D3D11 shaders.
++
+ // Generate a new set from the set intersection of sample counts between the color and depth
+ // format caps.
+ std::set_intersection(colorBufferFormatCaps.sampleCounts.begin(),
+@@ -1017,6 +1019,8 @@ gl::SupportedSampleSet Renderer11::generateSampleSetForEGLConfig(
+ sampleCounts = depthStencilBufferFormatCaps.sampleCounts;
+ }
+
++#endif
++
+ // Always support 0 samples
+ sampleCounts.insert(0);
+
+--
+2.14.1.windows.1
+
diff --git a/src/angle/patches/0010-ANGLE-fixed-usage-of-shared-handles-for-WinRT-WinPho.patch b/src/angle/patches/0010-ANGLE-fixed-usage-of-shared-handles-for-WinRT-WinPho.patch
deleted file mode 100644
index 8f17018e6e..0000000000
--- a/src/angle/patches/0010-ANGLE-fixed-usage-of-shared-handles-for-WinRT-WinPho.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-From 5cacddc702624d64a4917a7a704dbbb92aeba53c Mon Sep 17 00:00:00 2001
-From: Oliver Wolff <oliver.wolff@qt.io>
-Date: Thu, 19 May 2016 10:55:46 +0200
-Subject: [PATCH] ANGLE: fixed usage of shared handles for WinRT/WinPhone
- applications
-
-Both checks are not relevant in Qt's context and were skipped before but
-they sneaked back in with the latest ANGLE update.
-
-Change-Id: Ic44de5468a3254afd76ef4804d97d245676daeb1
----
- src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp | 3 +++
- src/3rdparty/angle/src/libANGLE/validationEGL.cpp | 3 +++
- 2 files changed, 6 insertions(+)
-
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
-index 62badcc..0173311 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
-@@ -2618,12 +2618,15 @@ bool Renderer11::getShareHandleSupport() const
- return false;
- }
-
-+ // Qt: we don't care about the 9_3 limitation
-+#if 0
- // Also disable share handles on Feature Level 9_3, since it doesn't support share handles on RGBA8 textures/swapchains.
- if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3)
- {
- mSupportsShareHandles = false;
- return false;
- }
-+#endif
-
- // Find out which type of D3D11 device the Renderer11 is using
- d3d11::ANGLED3D11DeviceType deviceType = getDeviceType();
-diff --git a/src/3rdparty/angle/src/libANGLE/validationEGL.cpp b/src/3rdparty/angle/src/libANGLE/validationEGL.cpp
-index 972f6a7..903f51b 100644
---- a/src/3rdparty/angle/src/libANGLE/validationEGL.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/validationEGL.cpp
-@@ -642,11 +642,14 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, E
- return Error(EGL_BAD_ATTRIBUTE);
- }
-
-+// On Windows Store, we know the originating texture came from D3D11, so bypass this check
-+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
- const Caps &caps = display->getCaps();
- if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height)))
- {
- return Error(EGL_BAD_MATCH);
- }
-+#endif
- }
-
- return Error(EGL_SUCCESS);
---
-2.7.0.windows.1
-
diff --git a/src/angle/patches/0011-ANGLE-Disable-support-for-shared-handles-in-warp-mod.patch b/src/angle/patches/0011-ANGLE-Disable-support-for-shared-handles-in-warp-mod.patch
deleted file mode 100644
index 1c4ee1d513..0000000000
--- a/src/angle/patches/0011-ANGLE-Disable-support-for-shared-handles-in-warp-mod.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From db13a9cf7e41207660f080827983655864df802d Mon Sep 17 00:00:00 2001
-From: Oliver Wolff <oliver.wolff@qt.io>
-Date: Wed, 11 May 2016 13:51:54 +0200
-Subject: [PATCH] ANGLE: Disable support for shared handles in warp mode on
- Windows < 8
-
-Shared handles are not supported on Windows 7 and below. If the
-according flag is set CreateTexture2D will fail with E_OUTOFMEMORY. The
-check already happens with newer ANGLE versions, which we use in 5.7
-but has to happen here as well. Otherwise Qt applications running on
-Windows 7 and below will crash at startup.
-
-Change-Id: I8f539f16dce298611fb1ec7b2f6804d4a04d04e0
----
- .../angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp | 13 +++++++++++++
- 1 file changed, 13 insertions(+)
-
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
-index 223e2b0..dd554f4 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
-@@ -2370,6 +2370,19 @@ unsigned int Renderer11::getReservedFragmentUniformBuffers() const
-
- bool Renderer11::getShareHandleSupport() const
- {
-+ if (mDriverType == D3D_DRIVER_TYPE_WARP)
-+ {
-+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
-+ // Warp mode does not support shared handles in Windows versions below Windows 8
-+ OSVERSIONINFO result = { sizeof(OSVERSIONINFO), 0, 0, 0, 0, {'\0'}};
-+ if (GetVersionEx(&result) &&
-+ ((result.dwMajorVersion == 6 && result.dwMinorVersion < 2) || result.dwMajorVersion < 6))
-+ {
-+ // WARP on Windows 7 doesn't support shared handles
-+ return false;
-+ }
-+#endif // ANGLE_ENABLE_WINDOWS_STORE
-+ }
- // We only currently support share handles with BGRA surfaces, because
- // chrome needs BGRA. Once chrome fixes this, we should always support them.
- // PIX doesn't seem to support using share handles, so disable them.
---
-2.7.0.windows.1
-
diff --git a/src/angle/patches/0012-ANGLE-Fix-initialization-of-zero-sized-window.patch b/src/angle/patches/0012-ANGLE-Fix-initialization-of-zero-sized-window.patch
deleted file mode 100644
index fe65af7948..0000000000
--- a/src/angle/patches/0012-ANGLE-Fix-initialization-of-zero-sized-window.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From 79d2bac44cb2a0793c00886f0499422ab6ffa09c Mon Sep 17 00:00:00 2001
-From: Maurice Kalinowski <maurice.kalinowski@qt.io>
-Date: Fri, 12 Aug 2016 08:11:16 +0200
-Subject: [PATCH] ANGLE: Fix initialization of zero-sized window
-
-The clientRect might be empty when creating a window of zero size. The
-side effect of a division by zero is that matrix transformation fails
-and hence the swapchain gets into an invalid state.
-
-Change-Id: Idbaed72deadb7b87052ac27e194a40d1810e6f7a
----
- .../libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp
-index d3ed35b..548b460 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp
-@@ -322,8 +322,8 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device,
-
- HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const Size &windowSize, const RECT &clientRect)
- {
-- Size renderScale = {windowSize.Width / clientRect.right,
-- windowSize.Height / clientRect.bottom};
-+ Size renderScale = {windowSize.Width / std::max(LONG(1), clientRect.right),
-+ windowSize.Height / std::max(LONG(1), clientRect.bottom)};
- // Setup a scale matrix for the swap chain
- DXGI_MATRIX_3X2_F scaleMatrix = {};
- scaleMatrix._11 = renderScale.Width;
---
-2.9.2.windows.1
-
diff --git a/src/angle/patches/0013-ANGLE-Fix-crash-with-ltcg-on-Visual-Studio-2015-Upda.patch b/src/angle/patches/0013-ANGLE-Fix-crash-with-ltcg-on-Visual-Studio-2015-Upda.patch
deleted file mode 100644
index ee847d3d9a..0000000000
--- a/src/angle/patches/0013-ANGLE-Fix-crash-with-ltcg-on-Visual-Studio-2015-Upda.patch
+++ /dev/null
@@ -1,110 +0,0 @@
-From c30bdc7d961ff09d74117e038c1bb9f06ad49738 Mon Sep 17 00:00:00 2001
-From: Oliver Wolff <oliver.wolff@qt.io>
-Date: Wed, 7 Jun 2017 10:07:43 +0200
-Subject: [PATCH] ANGLE: Fix crash with ltcg on Visual Studio 2015 Update 3
-
-Release builds of applications that used Qt configured with "link time
-code generation" crashed (memory access violation), when calling
-GetInternalFormatInfo in Context::initCaps.
-
-It looks like this is a compiler problem that can be avoided by not
-using a reference for the return value.
-
-Task-number: QTBUG-55718
-Change-Id: Ic1fb95d7b518a49859f41c819e860864387a8d3c
----
- src/3rdparty/angle/src/libANGLE/formatutils.cpp | 2 +-
- src/3rdparty/angle/src/libANGLE/formatutils.h | 2 +-
- src/3rdparty/angle/src/libANGLE/validationES3.cpp | 18 +++++++++---------
- 3 files changed, 11 insertions(+), 11 deletions(-)
-
-diff --git a/src/3rdparty/angle/src/libANGLE/formatutils.cpp b/src/3rdparty/angle/src/libANGLE/formatutils.cpp
-index 3a4df12..f8b9a8b 100644
---- a/src/3rdparty/angle/src/libANGLE/formatutils.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/formatutils.cpp
-@@ -652,7 +652,7 @@ const Type &GetTypeInfo(GLenum type)
- }
- }
-
--const InternalFormat &GetInternalFormatInfo(GLenum internalFormat)
-+const InternalFormat GetInternalFormatInfo(GLenum internalFormat)
- {
- const InternalFormatInfoMap &formatMap = GetInternalFormatMap();
- InternalFormatInfoMap::const_iterator iter = formatMap.find(internalFormat);
-diff --git a/src/3rdparty/angle/src/libANGLE/formatutils.h b/src/3rdparty/angle/src/libANGLE/formatutils.h
-index 6863e4d..2165e6b 100644
---- a/src/3rdparty/angle/src/libANGLE/formatutils.h
-+++ b/src/3rdparty/angle/src/libANGLE/formatutils.h
-@@ -79,7 +79,7 @@ struct InternalFormat
- GLint skipRows,
- GLint skipPixels) const;
- };
--const InternalFormat &GetInternalFormatInfo(GLenum internalFormat);
-+const InternalFormat GetInternalFormatInfo(GLenum internalFormat);
-
- GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type);
-
-diff --git a/src/3rdparty/angle/src/libANGLE/validationES3.cpp b/src/3rdparty/angle/src/libANGLE/validationES3.cpp
-index e08e5d2..2db64ec 100644
---- a/src/3rdparty/angle/src/libANGLE/validationES3.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/validationES3.cpp
-@@ -775,20 +775,20 @@ static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLen
- // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the
- // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING
- // is SRGB.
-- const InternalFormat *sourceEffectiveFormat = NULL;
-+ InternalFormat sourceEffectiveFormat;
- if (readBufferHandle != 0)
- {
- // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
- if (framebufferInternalFormatInfo.pixelBytes > 0)
- {
-- sourceEffectiveFormat = &framebufferInternalFormatInfo;
-+ sourceEffectiveFormat = framebufferInternalFormatInfo;
- }
- else
- {
- // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
- // texture. We can use the same table we use when creating textures to get its effective sized format.
- GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferInternalFormatInfo.format, framebufferInternalFormatInfo.type);
-- sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
-+ sourceEffectiveFormat = GetInternalFormatInfo(sizedInternalFormat);
- }
- }
- else
-@@ -800,7 +800,7 @@ static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLen
- GLenum effectiveFormat;
- if (GetEffectiveInternalFormat(framebufferInternalFormatInfo, textureInternalFormatInfo, &effectiveFormat))
- {
-- sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
-+ sourceEffectiveFormat = GetInternalFormatInfo(effectiveFormat);
- }
- else
- {
-@@ -816,7 +816,7 @@ static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLen
- (framebufferInternalFormatInfo.blueBits >= 1 && framebufferInternalFormatInfo.blueBits <= 8) &&
- (framebufferInternalFormatInfo.alphaBits >= 1 && framebufferInternalFormatInfo.alphaBits <= 8))
- {
-- sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
-+ sourceEffectiveFormat = GetInternalFormatInfo(GL_SRGB8_ALPHA8);
- }
- else
- {
-@@ -834,10 +834,10 @@ static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLen
- {
- // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is sized,
- // component sizes of the source and destination formats must exactly match
-- if (textureInternalFormatInfo.redBits != sourceEffectiveFormat->redBits ||
-- textureInternalFormatInfo.greenBits != sourceEffectiveFormat->greenBits ||
-- textureInternalFormatInfo.blueBits != sourceEffectiveFormat->blueBits ||
-- textureInternalFormatInfo.alphaBits != sourceEffectiveFormat->alphaBits)
-+ if (textureInternalFormatInfo.redBits != sourceEffectiveFormat.redBits ||
-+ textureInternalFormatInfo.greenBits != sourceEffectiveFormat.greenBits ||
-+ textureInternalFormatInfo.blueBits != sourceEffectiveFormat.blueBits ||
-+ textureInternalFormatInfo.alphaBits != sourceEffectiveFormat.alphaBits)
- {
- return false;
- }
---
-2.5.3.windows.1
-
diff --git a/src/angle/patches/0014-ANGLE-Fix-flickering-on-resize-when-D3D9-is-used.patch b/src/angle/patches/0014-ANGLE-Fix-flickering-on-resize-when-D3D9-is-used.patch
deleted file mode 100644
index e389219976..0000000000
--- a/src/angle/patches/0014-ANGLE-Fix-flickering-on-resize-when-D3D9-is-used.patch
+++ /dev/null
@@ -1,157 +0,0 @@
-From 0a6fe2a93f451997d01e5e326846e0911d22622b Mon Sep 17 00:00:00 2001
-From: Oliver Wolff <oliver.wolff@qt.io>
-Date: Wed, 31 May 2017 15:50:28 +0200
-Subject: [PATCH] ANGLE: Fix flickering on resize when D3D9 is used
-
-By reverting ANGLE change d3b84ab51db09de238459b0dff2e8420c09aabf3
-we get rid of the flickering that happens on resize when D3D9 is
-used. The issue that was fixed there is not relevant in Qt's
-context so it is safe to revert the change.
-
-Task-number: QTBUG-59893
-Change-Id: I9306314b892612fbd1f7a058a2e606aedc0367bb
----
- .../angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp | 87 ++++++++++++++++++++++
- .../angle/src/libANGLE/renderer/d3d/SurfaceD3D.h | 4 +
- 2 files changed, 91 insertions(+)
-
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
-index 3d27548..f567f47 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
-@@ -61,16 +61,19 @@ SurfaceD3D::SurfaceD3D(RendererD3D *renderer,
- mDepthStencilFormat(config->depthStencilFormat),
- mSwapChain(nullptr),
- mSwapIntervalDirty(true),
-+ mWindowSubclassed(false),
- mNativeWindow(window, config, directComposition == EGL_TRUE),
- mWidth(width),
- mHeight(height),
- mSwapInterval(1),
- mShareHandle(reinterpret_cast<HANDLE *>(shareHandle))
- {
-+ subclassWindow();
- }
-
- SurfaceD3D::~SurfaceD3D()
- {
-+ unsubclassWindow();
- releaseSwapChain();
- }
-
-@@ -243,6 +246,90 @@ egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
- return egl::Error(EGL_SUCCESS);
- }
-
-+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
-+#define kSurfaceProperty _TEXT("Egl::SurfaceOwner")
-+#define kParentWndProc _TEXT("Egl::SurfaceParentWndProc")
-+
-+static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
-+{
-+ if (message == WM_SIZE)
-+ {
-+ SurfaceD3D* surf = reinterpret_cast<SurfaceD3D*>(GetProp(hwnd, kSurfaceProperty));
-+ if(surf)
-+ {
-+ surf->checkForOutOfDateSwapChain();
-+ }
-+ }
-+ WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc));
-+ return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam);
-+}
-+#endif
-+
-+void SurfaceD3D::subclassWindow()
-+{
-+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
-+ HWND window = mNativeWindow.getNativeWindow();
-+ if (!window)
-+ {
-+ return;
-+ }
-+
-+ DWORD processId;
-+ DWORD threadId = GetWindowThreadProcessId(window, &processId);
-+ if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId())
-+ {
-+ return;
-+ }
-+
-+ SetLastError(0);
-+ LONG_PTR oldWndProc = SetWindowLongPtr(window, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
-+ if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS)
-+ {
-+ mWindowSubclassed = false;
-+ return;
-+ }
-+
-+ SetProp(window, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
-+ SetProp(window, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc));
-+ mWindowSubclassed = true;
-+#endif
-+}
-+
-+void SurfaceD3D::unsubclassWindow()
-+{
-+ if (!mWindowSubclassed)
-+ {
-+ return;
-+ }
-+
-+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
-+ HWND window = mNativeWindow.getNativeWindow();
-+ if (!window)
-+ {
-+ return;
-+ }
-+
-+ // un-subclass
-+ LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(GetProp(window, kParentWndProc));
-+
-+ // Check the windowproc is still SurfaceWindowProc.
-+ // If this assert fails, then it is likely the application has subclassed the
-+ // hwnd as well and did not unsubclass before destroying its EGL context. The
-+ // application should be modified to either subclass before initializing the
-+ // EGL context, or to unsubclass before destroying the EGL context.
-+ if(parentWndFunc)
-+ {
-+ LONG_PTR prevWndFunc = SetWindowLongPtr(window, GWLP_WNDPROC, parentWndFunc);
-+ UNUSED_ASSERTION_VARIABLE(prevWndFunc);
-+ ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
-+ }
-+
-+ RemoveProp(window, kSurfaceProperty);
-+ RemoveProp(window, kParentWndProc);
-+#endif
-+ mWindowSubclassed = false;
-+}
-+
- bool SurfaceD3D::checkForOutOfDateSwapChain()
- {
- RECT client;
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h
-index b925bfc..67d408d 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h
-@@ -82,6 +82,9 @@ class SurfaceD3D : public SurfaceImpl
- egl::Error resetSwapChain(int backbufferWidth, int backbufferHeight);
- egl::Error resizeSwapChain(int backbufferWidth, int backbufferHeight);
-
-+ void subclassWindow();
-+ void unsubclassWindow();
-+
- RendererD3D *mRenderer;
- egl::Display *mDisplay;
-
-@@ -93,6 +96,7 @@ class SurfaceD3D : public SurfaceImpl
-
- SwapChainD3D *mSwapChain;
- bool mSwapIntervalDirty;
-+ bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking
-
- NativeWindow mNativeWindow; // Handler for the Window that the surface is created for.
- EGLint mWidth;
---
-2.10.2.windows.1
-
diff --git a/src/angle/patches/0015-ANGLE-Use-ANGLE_D3D11_QDTD_AVAILABLE-to-check-struct-.patch b/src/angle/patches/0015-ANGLE-Use-ANGLE_D3D11_QDTD_AVAILABLE-to-check-struct-.patch
deleted file mode 100644
index 9809fefd9d..0000000000
--- a/src/angle/patches/0015-ANGLE-Use-ANGLE_D3D11_QDTD_AVAILABLE-to-check-struct-.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From 640361e72369d612270c6e59126019c917e33c9a Mon Sep 17 00:00:00 2001
-From: Oliver Wolff <oliver.wolff@qt.io>
-Date: Fri, 28 Jul 2017 09:02:50 +0200
-Subject: [PATCH] ANGLE: Use ANGLE_D3D11_QDTD_AVAILABLE to check struct's
- availability
-
-Checking mingw when defining the structure is not enough, as it is
-available in recent versions of MinGW. The define that is used is set
-depending on a configure test which works independently of the used
-toolchain.
-
-Change-Id: Ia9cb48f3e673841101a93cbc8ea23aff9547f639
----
- src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
-index 972c289..97c65e1 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
-@@ -20,7 +20,7 @@ typedef struct D3D11_QUERY_DATA_SO_STATISTICS {
- } D3D11_QUERY_DATA_SO_STATISTICS;
- #endif // ANGLE_MINGW32_COMPAT
-
--#ifdef __MINGW32__
-+#ifndef ANGLE_D3D11_QDTD_AVAILABLE
- typedef struct D3D11_QUERY_DATA_TIMESTAMP_DISJOINT {
- UINT64 Frequency;
- BOOL Disjoint;
---
-2.10.2.windows.1
-
diff --git a/src/angle/patches/0016-ANGLE-Fix-resizing-of-windows.patch b/src/angle/patches/0016-ANGLE-Fix-resizing-of-windows.patch
deleted file mode 100644
index 7ba92052f2..0000000000
--- a/src/angle/patches/0016-ANGLE-Fix-resizing-of-windows.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-From 55821d34b2208e7858dbba5648760b83c66b58a5 Mon Sep 17 00:00:00 2001
-From: Oliver Wolff <oliver.wolff@qt.io>
-Date: Mon, 29 Aug 2016 09:48:28 +0200
-Subject: [PATCH] ANGLE: Fix resizing of windows
-
-Use the correct height/width values when calculating
-the vector for resizing the window content and the
-new size as viewport size.
-
-Task-number: QTBUG-62475
-Change-Id: I33a8dc1379a908e991b04bc31dfc6254a6d005c9
----
- .../libANGLE/renderer/d3d/d3d11/SwapChain11.cpp | 35 +++++++++++-----------
- 1 file changed, 17 insertions(+), 18 deletions(-)
-
-diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
-index 785a83cd77..fe72bc935d 100644
---- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
-+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
-@@ -707,15 +706,15 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width,
- d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
-
- // Create a quad in homogeneous coordinates
-- float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
-- float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
-- float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
-- float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f;
-+ float x1 = (x / float(width)) * 2.0f - 1.0f;
-+ float y1 = (y / float(height)) * 2.0f - 1.0f;
-+ float x2 = ((x + width) / float(width)) * 2.0f - 1.0f;
-+ float y2 = ((y + height) / float(height)) * 2.0f - 1.0f;
-
-- float u1 = x / float(mWidth);
-- float v1 = y / float(mHeight);
-- float u2 = (x + width) / float(mWidth);
-- float v2 = (y + height) / float(mHeight);
-+ float u1 = x / float(width);
-+ float v1 = y / float(height);
-+ float u2 = (x + width) / float(width);
-+ float v2 = (y + height) / float(height);
-
- // Invert the quad vertices depending on the surface orientation.
- if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE) != 0)
-@@ -760,8 +759,8 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width,
- D3D11_VIEWPORT viewport;
- viewport.TopLeftX = 0;
- viewport.TopLeftY = 0;
-- viewport.Width = static_cast<FLOAT>(mWidth);
-- viewport.Height = static_cast<FLOAT>(mHeight);
-+ viewport.Width = static_cast<FLOAT>(width);
-+ viewport.Height = static_cast<FLOAT>(height);
- viewport.MinDepth = 0.0f;
- viewport.MaxDepth = 1.0f;
- deviceContext->RSSetViewports(1, &viewport);
---
-2.15.0.windows.1
-
diff --git a/src/angle/patches/0017-Remove-usage-of-auto_ptr-in-MacroExpander.patch b/src/angle/patches/0017-Remove-usage-of-auto_ptr-in-MacroExpander.patch
deleted file mode 100644
index 314a985bab..0000000000
--- a/src/angle/patches/0017-Remove-usage-of-auto_ptr-in-MacroExpander.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 946903d23ae361ddb05d2c0f64b339eb1694311b Mon Sep 17 00:00:00 2001
-From: Corentin Wallez <cwallez@chromium.org>
-Date: Mon, 18 Apr 2016 17:30:07 -0400
-Subject: [PATCH] Remove usage of auto_ptr in MacroExpander
-
-BUG=angleproject:1269
-
-Change-Id: I1fafa102b065f6da1797e8790ec3ed498d9d8b45
-Reviewed-on: https://chromium-review.googlesource.com/339379
-Reviewed-by: Jamie Madill <jmadill@chromium.org>
-Commit-Queue: Corentin Wallez <cwallez@chromium.org>
----
- src/compiler/preprocessor/MacroExpander.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/compiler/preprocessor/MacroExpander.h b/src/compiler/preprocessor/MacroExpander.h
-index 3cc860d75..dc870f626 100644
---- a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h
-+++ b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h
-@@ -83,7 +83,7 @@ class MacroExpander : public Lexer
- Diagnostics *mDiagnostics;
- bool mParseDefined;
-
-- std::auto_ptr<Token> mReserveToken;
-+ std::unique_ptr<Token> mReserveToken;
- std::vector<MacroContext *> mContextStack;
- };
-
---
-2.15.0.windows.1
-
diff --git a/src/angle/src/common/common.pri b/src/angle/src/common/common.pri
index c1fad14951..b64dbd3e36 100644
--- a/src/angle/src/common/common.pri
+++ b/src/angle/src/common/common.pri
@@ -10,7 +10,8 @@ include (../config.pri)
INCLUDEPATH += \
$$ANGLE_DIR/src \
- $$ANGLE_DIR/include
+ $$ANGLE_DIR/include \
+ $$ANGLE_DIR/src/common/third_party/base
LIBS_PRIVATE = $$QMAKE_LIBS_GUI
@@ -37,4 +38,9 @@ winrt|msvc {
}
}
+win32 {
+ VERSION = $$MODULE_VERSION
+ CONFIG += skip_target_version_ext
+}
+
static: DEFINES *= LIBGLESV2_EXPORT_H_ ANGLE_EXPORT=
diff --git a/src/angle/src/common/gles_common.pri b/src/angle/src/common/gles_common.pri
index 82d38a62e6..fdd0e45971 100644
--- a/src/angle/src/common/gles_common.pri
+++ b/src/angle/src/common/gles_common.pri
@@ -1,7 +1,10 @@
CONFIG += simd no_batch object_parallel_to_source
include(common.pri)
-INCLUDEPATH += $$OUT_PWD/.. $$ANGLE_DIR/src/libANGLE
+INCLUDEPATH += \
+ $$OUT_PWD/.. \
+ $$ANGLE_DIR \
+ $$ANGLE_DIR/src/libANGLE
# Remember to adapt src/gui/configure.* if the Direct X version changes.
!winrt: \
@@ -30,10 +33,8 @@ qtConfig(angle_d3d11_qdtd): DEFINES += ANGLE_D3D11_QDTD_AVAILABLE
HEADERS += \
$$ANGLE_DIR/src/common/mathutil.h \
- $$ANGLE_DIR/src/common/blocklayout.h \
- $$ANGLE_DIR/src/common/NativeWindow.h \
- $$ANGLE_DIR/src/common/shadervars.h \
$$ANGLE_DIR/src/common/utilities.h \
+ $$ANGLE_DIR/src/common/version.h \
$$ANGLE_DIR/src/common/MemoryBuffer.h \
$$ANGLE_DIR/src/common/angleutils.h \
$$ANGLE_DIR/src/common/debug.h \
@@ -47,7 +48,6 @@ HEADERS += \
$$ANGLE_DIR/src/libANGLE/Config.h \
$$ANGLE_DIR/src/libANGLE/Constants.h \
$$ANGLE_DIR/src/libANGLE/Context.h \
- $$ANGLE_DIR/src/libANGLE/Data.h \
$$ANGLE_DIR/src/libANGLE/Debug.h \
$$ANGLE_DIR/src/libANGLE/Device.h \
$$ANGLE_DIR/src/libANGLE/Display.h \
@@ -81,21 +81,16 @@ HEADERS += \
$$ANGLE_DIR/src/libANGLE/VertexAttribute.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/BufferD3D.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/CompilerD3D.h \
- $$ANGLE_DIR/src/libANGLE/renderer/d3d/copyimage.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/DeviceD3D.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/DisplayD3D.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/DynamicHLSL.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/EGLImageD3D.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/formatutilsD3D.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/FramebufferD3D.h \
- $$ANGLE_DIR/src/libANGLE/renderer/d3d/generatemip.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/HLSLCompiler.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/ImageD3D.h \
- $$ANGLE_DIR/src/libANGLE/renderer/d3d/imageformats.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/IndexBuffer.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/IndexDataManager.h \
- $$ANGLE_DIR/src/libANGLE/renderer/d3d/loadimage.h \
- $$ANGLE_DIR/src/libANGLE/renderer/d3d/loadimage_etc.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/ProgramD3D.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/RenderbufferD3D.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/RendererD3D.h \
@@ -106,8 +101,6 @@ HEADERS += \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/SwapChainD3D.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/TextureD3D.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/TextureStorage.h \
- $$ANGLE_DIR/src/libANGLE/renderer/d3d/TransformFeedbackD3D.h \
- $$ANGLE_DIR/src/libANGLE/renderer/d3d/VaryingPacking.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/VertexBuffer.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/VertexDataManager.h \
$$ANGLE_DIR/src/libANGLE/renderer/BufferImpl.h \
@@ -115,21 +108,15 @@ HEADERS += \
$$ANGLE_DIR/src/libANGLE/renderer/DeviceImpl.h \
$$ANGLE_DIR/src/libANGLE/renderer/DisplayImpl.h \
$$ANGLE_DIR/src/libANGLE/renderer/FenceNVImpl.h \
- $$ANGLE_DIR/src/libANGLE/renderer/FenceSyncImpl.h \
$$ANGLE_DIR/src/libANGLE/renderer/FramebufferImpl.h \
- $$ANGLE_DIR/src/libANGLE/renderer/Image.h \
- $$ANGLE_DIR/src/libANGLE/renderer/ImplFactory.h \
$$ANGLE_DIR/src/libANGLE/renderer/ProgramImpl.h \
$$ANGLE_DIR/src/libANGLE/renderer/QueryImpl.h \
$$ANGLE_DIR/src/libANGLE/renderer/RenderbufferImpl.h \
- $$ANGLE_DIR/src/libANGLE/renderer/Renderer.h \
$$ANGLE_DIR/src/libANGLE/renderer/ShaderImpl.h \
$$ANGLE_DIR/src/libANGLE/renderer/SurfaceImpl.h \
$$ANGLE_DIR/src/libANGLE/renderer/TextureImpl.h \
$$ANGLE_DIR/src/libANGLE/renderer/TransformFeedbackImpl.h \
$$ANGLE_DIR/src/libANGLE/renderer/VertexArrayImpl.h \
- $$ANGLE_DIR/src/libANGLE/renderer/Workarounds.h \
- $$ANGLE_DIR/src/libANGLE/resource.h \
$$ANGLE_DIR/src/libANGLE/ResourceManager.h \
$$ANGLE_DIR/src/libANGLE/Sampler.h \
$$ANGLE_DIR/src/libANGLE/Shader.h \
@@ -142,16 +129,11 @@ HEADERS += \
$$ANGLE_DIR/src/libANGLE/validationES.h \
$$ANGLE_DIR/src/libANGLE/VertexArray.h \
$$ANGLE_DIR/src/libANGLE/VertexAttribute.h \
- $$ANGLE_DIR/src/libANGLE/vertexconversion.h \
$$ANGLE_DIR/src/libGLESv2/entry_points_egl.h \
$$ANGLE_DIR/src/libGLESv2/entry_points_egl_ext.h \
- $$ANGLE_DIR/src/libGLESv2/entry_points_gles_2_0.h \
$$ANGLE_DIR/src/libGLESv2/entry_points_gles_2_0_ext.h \
- $$ANGLE_DIR/src/libGLESv2/entry_points_gles_3_0.h \
- $$ANGLE_DIR/src/libGLESv2/entry_points_gles_3_0_ext.h \
$$ANGLE_DIR/src/libGLESv2/global_state.h \
- $$ANGLE_DIR/src/libGLESv2/resource.h \
- $$ANGLE_DIR/src/third_party/murmurhash/MurmurHash3.h
+ $$ANGLE_DIR/src/libGLESv2/resource.h
SOURCES += \
$$ANGLE_DIR/src/common/mathutil.cpp \
@@ -161,7 +143,14 @@ SOURCES += \
$$ANGLE_DIR/src/common/debug.cpp \
$$ANGLE_DIR/src/common/event_tracer.cpp \
$$ANGLE_DIR/src/common/Float16ToFloat32.cpp \
- $$ANGLE_DIR/src/third_party/murmurhash/MurmurHash3.cpp \
+ $$ANGLE_DIR/src/common/string_utils.cpp \
+ $$ANGLE_DIR/src/common/uniform_type_info_autogen.cpp \
+ $$ANGLE_DIR/src/common/third_party/smhasher/src/PMurHash.cpp \
+ $$ANGLE_DIR/src/common/third_party/base/anglebase/sha1.cc \
+ $$ANGLE_DIR/src/image_util/copyimage.cpp \
+ $$ANGLE_DIR/src/image_util/imageformats.cpp \
+ $$ANGLE_DIR/src/image_util/loadimage.cpp \
+ $$ANGLE_DIR/src/image_util/loadimage_etc.cpp \
$$ANGLE_DIR/src/libANGLE/angletypes.cpp \
$$ANGLE_DIR/src/libANGLE/AttributeMap.cpp \
$$ANGLE_DIR/src/libANGLE/Buffer.cpp \
@@ -169,57 +158,75 @@ SOURCES += \
$$ANGLE_DIR/src/libANGLE/Compiler.cpp \
$$ANGLE_DIR/src/libANGLE/Config.cpp \
$$ANGLE_DIR/src/libANGLE/Context.cpp \
- $$ANGLE_DIR/src/libANGLE/Data.cpp \
+ $$ANGLE_DIR/src/libANGLE/ContextState.cpp \
$$ANGLE_DIR/src/libANGLE/Debug.cpp \
$$ANGLE_DIR/src/libANGLE/Device.cpp \
$$ANGLE_DIR/src/libANGLE/Display.cpp \
$$ANGLE_DIR/src/libANGLE/Error.cpp \
+ $$ANGLE_DIR/src/libANGLE/es3_copy_conversion_table_autogen.cpp \
$$ANGLE_DIR/src/libANGLE/Fence.cpp \
$$ANGLE_DIR/src/libANGLE/formatutils.cpp \
+ $$ANGLE_DIR/src/libANGLE/format_map_autogen.cpp \
$$ANGLE_DIR/src/libANGLE/Framebuffer.cpp \
$$ANGLE_DIR/src/libANGLE/FramebufferAttachment.cpp \
$$ANGLE_DIR/src/libANGLE/HandleAllocator.cpp \
+ $$ANGLE_DIR/src/libANGLE/HandleRangeAllocator.cpp \
$$ANGLE_DIR/src/libANGLE/Image.cpp \
$$ANGLE_DIR/src/libANGLE/ImageIndex.cpp \
$$ANGLE_DIR/src/libANGLE/IndexRangeCache.cpp \
+ $$ANGLE_DIR/src/libANGLE/LoggingAnnotator.cpp \
+ $$ANGLE_DIR/src/libANGLE/MemoryProgramCache.cpp \
+ $$ANGLE_DIR/src/libANGLE/PackedGLEnums_autogen.cpp \
+ $$ANGLE_DIR/src/libANGLE/params.cpp \
+ $$ANGLE_DIR/src/libANGLE/Path.cpp \
$$ANGLE_DIR/src/libANGLE/Platform.cpp \
$$ANGLE_DIR/src/libANGLE/Program.cpp \
+ $$ANGLE_DIR/src/libANGLE/ProgramLinkedResources.cpp \
+ $$ANGLE_DIR/src/libANGLE/ProgramPipeline.cpp \
$$ANGLE_DIR/src/libANGLE/Query.cpp \
$$ANGLE_DIR/src/libANGLE/queryconversions.cpp \
+ $$ANGLE_DIR/src/libANGLE/queryutils.cpp \
$$ANGLE_DIR/src/libANGLE/Renderbuffer.cpp \
$$ANGLE_DIR/src/libANGLE/ResourceManager.cpp \
$$ANGLE_DIR/src/libANGLE/Sampler.cpp \
$$ANGLE_DIR/src/libANGLE/Shader.cpp \
$$ANGLE_DIR/src/libANGLE/State.cpp \
+ $$ANGLE_DIR/src/libANGLE/Stream.cpp \
$$ANGLE_DIR/src/libANGLE/Surface.cpp \
$$ANGLE_DIR/src/libANGLE/Texture.cpp \
+ $$ANGLE_DIR/src/libANGLE/Thread.cpp \
$$ANGLE_DIR/src/libANGLE/TransformFeedback.cpp \
$$ANGLE_DIR/src/libANGLE/Uniform.cpp \
$$ANGLE_DIR/src/libANGLE/validationEGL.cpp \
$$ANGLE_DIR/src/libANGLE/validationES.cpp \
$$ANGLE_DIR/src/libANGLE/validationES2.cpp \
$$ANGLE_DIR/src/libANGLE/validationES3.cpp \
+ $$ANGLE_DIR/src/libANGLE/validationES31.cpp \
+ $$ANGLE_DIR/src/libANGLE/VaryingPacking.cpp \
$$ANGLE_DIR/src/libANGLE/VertexArray.cpp \
$$ANGLE_DIR/src/libANGLE/VertexAttribute.cpp \
+ $$ANGLE_DIR/src/libANGLE/WorkerThread.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/ContextImpl.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/DeviceImpl.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/DisplayImpl.cpp \
- $$ANGLE_DIR/src/libANGLE/renderer/Renderer.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/driver_utils.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/Format_table_autogen.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/load_functions_table_autogen.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/renderer_utils.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/SurfaceImpl.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/TextureImpl.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/BufferD3D.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/CompilerD3D.cpp \
- $$ANGLE_DIR/src/libANGLE/renderer/d3d/copyimage.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/DeviceD3D.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/DisplayD3D.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/DynamicHLSL.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/EGLImageD3D.cpp \
- $$ANGLE_DIR/src/libANGLE/renderer/d3d/formatutilsD3D.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/FramebufferD3D.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/HLSLCompiler.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/ImageD3D.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/IndexBuffer.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/IndexDataManager.cpp \
- $$ANGLE_DIR/src/libANGLE/renderer/d3d/loadimage.cpp \
- $$ANGLE_DIR/src/libANGLE/renderer/d3d/loadimage_etc.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/NativeWindowD3D.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/ProgramD3D.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/RendererD3D.cpp \
@@ -227,22 +234,20 @@ SOURCES += \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/ShaderD3D.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/SurfaceD3D.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/SwapChainD3D.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/TextureD3D.cpp \
- $$ANGLE_DIR/src/libANGLE/renderer/d3d/TransformFeedbackD3D.cpp \
- $$ANGLE_DIR/src/libANGLE/renderer/d3d/VaryingPacking.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/VertexBuffer.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/VertexDataManager.cpp \
$$ANGLE_DIR/src/libGLESv2/entry_points_egl.cpp \
$$ANGLE_DIR/src/libGLESv2/entry_points_egl_ext.cpp \
- $$ANGLE_DIR/src/libGLESv2/entry_points_gles_2_0.cpp \
+ $$ANGLE_DIR/src/libGLESv2/entry_points_gles_2_0_autogen.cpp \
+ $$ANGLE_DIR/src/libGLESv2/proc_table_autogen.cpp \
$$ANGLE_DIR/src/libGLESv2/entry_points_gles_2_0_ext.cpp \
- $$ANGLE_DIR/src/libGLESv2/entry_points_gles_3_0.cpp \
- $$ANGLE_DIR/src/libGLESv2/entry_points_gles_3_0_ext.cpp \
+ $$ANGLE_DIR/src/libGLESv2/entry_points_gles_3_0_autogen.cpp \
+ $$ANGLE_DIR/src/libGLESv2/entry_points_gles_3_1_autogen.cpp \
$$ANGLE_DIR/src/libGLESv2/global_state.cpp \
$$ANGLE_DIR/src/libGLESv2/libGLESv2.cpp
-SSE2_SOURCES += $$ANGLE_DIR/src/libANGLE/renderer/d3d/loadimageSSE2.cpp
-
angle_d3d11 {
HEADERS += \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Blit11.h \
@@ -256,8 +261,7 @@ angle_d3d11 {
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Image11.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h \
- $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h \
- $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/load_functions_table.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Query11.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Renderer11.h \
@@ -267,7 +271,6 @@ angle_d3d11 {
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/StateManager11.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h \
- $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Trim11.h \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h \
@@ -277,7 +280,9 @@ angle_d3d11 {
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Context11.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/dxgi_format_map_autogen.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp \
@@ -285,21 +290,24 @@ angle_d3d11 {
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Image11.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp \
- $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.cpp \
- $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Query11.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp \
- $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info_autogen.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp
}
@@ -327,12 +335,14 @@ angle_d3d11 {
SOURCES += \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Context9.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Image9.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Query9.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp \
@@ -343,7 +353,7 @@ angle_d3d11 {
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp \
- $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp \
$$ANGLE_DIR/src/third_party/systeminfo/SystemInfo.cpp
} else {
HEADERS += \
@@ -354,6 +364,7 @@ angle_d3d11 {
SOURCES += \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.cpp \
$$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp
}
@@ -367,9 +378,6 @@ BLITVS = $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs
standardvs.input = BLITVS
standardvs.type = vs_2_0
standardvs.output = standardvs.h
-flipyvs.input = BLITVS
-flipyvs.type = vs_2_0
-flipyvs.output = flipyvs.h
BLITPS = $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps
passthroughps.input = BLITPS
@@ -378,9 +386,21 @@ passthroughps.output = passthroughps.h
luminanceps.input = BLITPS
luminanceps.type = ps_2_0
luminanceps.output = luminanceps.h
+luminancepremultps.input = BLITPS
+luminancepremultps.type = ps_2_0
+luminancepremultps.output = luminancepremultps.h
+luminanceunmultps.input = BLITPS
+luminanceunmultps.type = ps_2_0
+luminanceunmultps.output = luminanceunmultps.h
componentmaskps.input = BLITPS
componentmaskps.type = ps_2_0
componentmaskps.output = componentmaskps.h
+componentmaskpremultps.input = BLITPS
+componentmaskpremultps.type = ps_2_0
+componentmaskpremultps.output = componentmaskpremultps.h
+componentmaskunmultps.input = BLITPS
+componentmaskunmultps.type = ps_2_0
+componentmaskunmultps.output = componentmaskunmultps.h
PASSTHROUGH2D = $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl
VS_Passthrough2D.input = PASSTHROUGH2D
@@ -431,29 +451,104 @@ PS_PassthroughR2DUI.output = passthroughr2dui11ps.h
PS_PassthroughR2DI.input = PASSTHROUGH2D
PS_PassthroughR2DI.type = ps_4_0
PS_PassthroughR2DI.output = passthroughr2di11ps.h
+PS_PassthroughA2D.input = PASSTHROUGH2D
+PS_PassthroughA2D.type = ps_4_0_level_9_3
+PS_PassthroughA2D.output = passthrougha2d11ps.h
+PS_PassthroughRGBA2DMS.input = PASSTHROUGH2D
+PS_PassthroughRGBA2DMS.type = ps_4_1
+PS_PassthroughRGBA2DMS.output = passthroughrgba2dms11ps.h
CLEAR = $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl
-VS_ClearFloat.input = CLEAR
-VS_ClearFloat.type = vs_4_0_level_9_3
-VS_ClearFloat.output = clearfloat11vs.h
+VS_Clear_FL9.input = CLEAR
+VS_Clear_FL9.type = vs_4_0_level_9_3
+VS_Clear_FL9.output = clear11_fl9vs.h
PS_ClearFloat_FL9.input = CLEAR
PS_ClearFloat_FL9.type = ps_4_0_level_9_3
PS_ClearFloat_FL9.output = clearfloat11_fl9ps.h
-PS_ClearFloat.input = CLEAR
-PS_ClearFloat.type = ps_4_0
-PS_ClearFloat.output = clearfloat11ps.h
-VS_ClearUint.input = CLEAR
-VS_ClearUint.type = vs_4_0
-VS_ClearUint.output = clearuint11vs.h
-PS_ClearUint.input = CLEAR
-PS_ClearUint.type = ps_4_0
-PS_ClearUint.output = clearuint11ps.h
-VS_ClearSint.input = CLEAR
-VS_ClearSint.type = vs_4_0
-VS_ClearSint.output = clearsint11vs.h
-PS_ClearSint.input = CLEAR
-PS_ClearSint.type = ps_4_0
-PS_ClearSint.output = clearsint11ps.h
+VS_Clear.input = CLEAR
+VS_Clear.type = vs_4_0
+VS_Clear.output = clear11vs.h
+VS_Multiview_Clear.input = CLEAR
+VS_Multiview_Clear.type = vs_4_0
+VS_Multiview_Clear.output = clear11multiviewvs.h
+GS_Multiview_Clear.input = CLEAR
+GS_Multiview_Clear.type = gs_4_0
+GS_Multiview_Clear.output = clear11multiviewgs.h
+PS_ClearDepth.input = CLEAR
+PS_ClearDepth.type = ps_4_0
+PS_ClearDepth.output = cleardepth11ps.h
+PS_ClearFloat1.input = CLEAR
+PS_ClearFloat1.type = ps_4_0
+PS_ClearFloat1.output = clearfloat11ps1.h
+PS_ClearFloat2.input = CLEAR
+PS_ClearFloat2.type = ps_4_0
+PS_ClearFloat2.output = clearfloat11ps2.h
+PS_ClearFloat3.input = CLEAR
+PS_ClearFloat3.type = ps_4_0
+PS_ClearFloat3.output = clearfloat11ps3.h
+PS_ClearFloat4.input = CLEAR
+PS_ClearFloat4.type = ps_4_0
+PS_ClearFloat4.output = clearfloat11ps4.h
+PS_ClearFloat5.input = CLEAR
+PS_ClearFloat5.type = ps_4_0
+PS_ClearFloat5.output = clearfloat11ps5.h
+PS_ClearFloat6.input = CLEAR
+PS_ClearFloat6.type = ps_4_0
+PS_ClearFloat6.output = clearfloat11ps6.h
+PS_ClearFloat7.input = CLEAR
+PS_ClearFloat7.type = ps_4_0
+PS_ClearFloat7.output = clearfloat11ps7.h
+PS_ClearFloat8.input = CLEAR
+PS_ClearFloat8.type = ps_4_0
+PS_ClearFloat8.output = clearfloat11ps8.h
+PS_ClearUint1.input = CLEAR
+PS_ClearUint1.type = ps_4_0
+PS_ClearUint1.output = clearuint11ps1.h
+PS_ClearUint2.input = CLEAR
+PS_ClearUint2.type = ps_4_0
+PS_ClearUint2.output = clearuint11ps2.h
+PS_ClearUint3.input = CLEAR
+PS_ClearUint3.type = ps_4_0
+PS_ClearUint3.output = clearuint11ps3.h
+PS_ClearUint4.input = CLEAR
+PS_ClearUint4.type = ps_4_0
+PS_ClearUint4.output = clearuint11ps4.h
+PS_ClearUint5.input = CLEAR
+PS_ClearUint5.type = ps_4_0
+PS_ClearUint5.output = clearuint11ps5.h
+PS_ClearUint6.input = CLEAR
+PS_ClearUint6.type = ps_4_0
+PS_ClearUint6.output = clearuint11ps6.h
+PS_ClearUint7.input = CLEAR
+PS_ClearUint7.type = ps_4_0
+PS_ClearUint7.output = clearuint11ps7.h
+PS_ClearUint8.input = CLEAR
+PS_ClearUint8.type = ps_4_0
+PS_ClearUint8.output = clearuint11ps8.h
+PS_ClearSint1.input = CLEAR
+PS_ClearSint1.type = ps_4_0
+PS_ClearSint1.output = clearsint11ps1.h
+PS_ClearSint2.input = CLEAR
+PS_ClearSint2.type = ps_4_0
+PS_ClearSint2.output = clearsint11ps2.h
+PS_ClearSint3.input = CLEAR
+PS_ClearSint3.type = ps_4_0
+PS_ClearSint3.output = clearsint11ps3.h
+PS_ClearSint4.input = CLEAR
+PS_ClearSint4.type = ps_4_0
+PS_ClearSint4.output = clearsint11ps4.h
+PS_ClearSint5.input = CLEAR
+PS_ClearSint5.type = ps_4_0
+PS_ClearSint5.output = clearsint11ps5.h
+PS_ClearSint6.input = CLEAR
+PS_ClearSint6.type = ps_4_0
+PS_ClearSint6.output = clearsint11ps6.h
+PS_ClearSint7.input = CLEAR
+PS_ClearSint7.type = ps_4_0
+PS_ClearSint7.output = clearsint11ps7.h
+PS_ClearSint8.input = CLEAR
+PS_ClearSint8.type = ps_4_0
+PS_ClearSint8.output = clearsint11ps8.h
PASSTHROUGH3D = $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl
VS_Passthrough3D.input = PASSTHROUGH3D
@@ -551,15 +646,81 @@ PS_BufferToTexture_4UI.input = BUFFERTOTEXTURE
PS_BufferToTexture_4UI.type = ps_4_0
PS_BufferToTexture_4UI.output = buffertotexture11_ps_4ui.h
+MULTIPLYALPHA = $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/shaders/MultiplyAlpha.hlsl
+PS_FtoF_PM_RGBA.input = MULTIPLYALPHA
+PS_FtoF_PM_RGBA.type = ps_4_0
+PS_FtoF_PM_RGBA.output = multiplyalpha_ftof_pm_rgba_ps.h
+PS_FtoF_UM_RGBA.input = MULTIPLYALPHA
+PS_FtoF_UM_RGBA.type = ps_4_0
+PS_FtoF_UM_RGBA.output = multiplyalpha_ftof_um_rgba_ps.h
+PS_FtoF_PM_RGB.input = MULTIPLYALPHA
+PS_FtoF_PM_RGB.type = ps_4_0
+PS_FtoF_PM_RGB.output = multiplyalpha_ftof_pm_rgb_ps.h
+PS_FtoF_UM_RGB.input = MULTIPLYALPHA
+PS_FtoF_UM_RGB.type = ps_4_0
+PS_FtoF_UM_RGB.output = multiplyalpha_ftof_um_rgb_ps.h
+PS_FtoU_PT_RGBA.input = MULTIPLYALPHA
+PS_FtoU_PT_RGBA.type = ps_4_0
+PS_FtoU_PT_RGBA.output = multiplyalpha_ftou_pt_rgba_ps.h
+PS_FtoU_PM_RGBA.input = MULTIPLYALPHA
+PS_FtoU_PM_RGBA.type = ps_4_0
+PS_FtoU_PM_RGBA.output = multiplyalpha_ftou_pm_rgba_ps.h
+PS_FtoU_UM_RGBA.input = MULTIPLYALPHA
+PS_FtoU_UM_RGBA.type = ps_4_0
+PS_FtoU_UM_RGBA.output = multiplyalpha_ftou_um_rgba_ps.h
+PS_FtoU_PT_RGB.input = MULTIPLYALPHA
+PS_FtoU_PT_RGB.type = ps_4_0
+PS_FtoU_PT_RGB.output = multiplyalpha_ftou_pt_rgb_ps.h
+PS_FtoU_PM_RGB.input = MULTIPLYALPHA
+PS_FtoU_PM_RGB.type = ps_4_0
+PS_FtoU_PM_RGB.output = multiplyalpha_ftou_pm_rgb_ps.h
+PS_FtoU_UM_RGB.input = MULTIPLYALPHA
+PS_FtoU_UM_RGB.type = ps_4_0
+PS_FtoU_UM_RGB.output = multiplyalpha_ftou_um_rgb_ps.h
+PS_FtoF_PM_LUMA.input = MULTIPLYALPHA
+PS_FtoF_PM_LUMA.type = ps_4_0
+PS_FtoF_PM_LUMA.output = multiplyalpha_ftof_pm_luma_ps.h
+PS_FtoF_UM_LUMA.input = MULTIPLYALPHA
+PS_FtoF_UM_LUMA.type = ps_4_0
+PS_FtoF_UM_LUMA.output = multiplyalpha_ftof_um_luma_ps.h
+PS_FtoF_PM_LUMAALPHA.input = MULTIPLYALPHA
+PS_FtoF_PM_LUMAALPHA.type = ps_4_0
+PS_FtoF_PM_LUMAALPHA.output = multiplyalpha_ftof_pm_lumaalpha_ps.h
+PS_FtoF_UM_LUMAALPHA.input = MULTIPLYALPHA
+PS_FtoF_UM_LUMAALPHA.type = ps_4_0
+PS_FtoF_UM_LUMAALPHA.output = multiplyalpha_ftof_um_lumaalpha_ps.h
+
+RESOLVEDEPTHSTENCIL = \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/shaders/ResolveDepthStencil.hlsl
+VS_ResolveDepthStencil.input = RESOLVEDEPTHSTENCIL
+VS_ResolveDepthStencil.type = vs_4_1
+VS_ResolveDepthStencil.output = resolvedepthstencil11_vs.h
+PS_ResolveDepth.input = RESOLVEDEPTHSTENCIL
+PS_ResolveDepth.type = ps_4_1
+PS_ResolveDepth.output = resolvedepth11_ps.h
+PS_ResolveDepthStencil.input = RESOLVEDEPTHSTENCIL
+PS_ResolveDepthStencil.type = ps_4_1
+PS_ResolveDepthStencil.output = resolvedepthstencil11_ps.h
+PS_ResolveStencil.input = RESOLVEDEPTHSTENCIL
+PS_ResolveStencil.type = ps_4_1
+PS_ResolveStencil.output = resolvestencil11_ps.h
+
# D3D11
angle_d3d11: SHADERS = VS_Passthrough2D \
PS_PassthroughRGB2D PS_PassthroughRGB2DUI PS_PassthroughRGB2DI \
PS_PassthroughRGBA2D PS_PassthroughRGBA2DUI PS_PassthroughRGBA2DI \
PS_PassthroughRG2D PS_PassthroughRG2DUI PS_PassthroughRG2DI \
PS_PassthroughR2D PS_PassthroughR2DUI PS_PassthroughR2DI \
+ PS_PassthroughA2D \
PS_PassthroughLum2D PS_PassthroughLumAlpha2D PS_PassthroughDepth2D \
- VS_ClearFloat VS_ClearUint VS_ClearSint \
- PS_ClearFloat PS_ClearFloat_FL9 PS_ClearUint PS_ClearSint \
+ VS_Clear_FL9 PS_ClearFloat_FL9 VS_Clear VS_Multiview_Clear \
+ GS_Multiview_Clear PS_ClearDepth \
+ PS_ClearFloat1 PS_ClearFloat2 PS_ClearFloat3 PS_ClearFloat4 PS_ClearFloat5 \
+ PS_ClearFloat6 PS_ClearFloat7 PS_ClearFloat8 \
+ PS_ClearUint1 PS_ClearUint2 PS_ClearUint3 PS_ClearUint4 \
+ PS_ClearUint5 PS_ClearUint6 PS_ClearUint7 PS_ClearUint8 \
+ PS_ClearSint1 PS_ClearSint2 PS_ClearSint3 PS_ClearSint4 \
+ PS_ClearSint5 PS_ClearSint6 PS_ClearSint7 PS_ClearSint8 \
VS_Passthrough3D GS_Passthrough3D \
PS_PassthroughRGBA3D PS_PassthroughRGBA3DUI PS_PassthroughRGBA3DI \
PS_PassthroughRGB3D PS_PassthroughRGB3DUI PS_PassthroughRGB3DI \
@@ -570,10 +731,22 @@ angle_d3d11: SHADERS = VS_Passthrough2D \
PS_SwizzleF3D PS_SwizzleI3D PS_SwizzleUI3D \
PS_SwizzleF2DArray PS_SwizzleI2DArray PS_SwizzleUI2DArray \
VS_BufferToTexture GS_BufferToTexture \
- PS_BufferToTexture_4F PS_BufferToTexture_4I PS_BufferToTexture_4UI
+ PS_BufferToTexture_4F PS_BufferToTexture_4I PS_BufferToTexture_4UI \
+ PS_FtoF_PM_RGBA PS_FtoF_UM_RGBA PS_FtoF_PM_RGB PS_FtoF_UM_RGB \
+ PS_FtoU_PT_RGBA PS_FtoU_PM_RGBA PS_FtoU_UM_RGBA \
+ PS_FtoU_PT_RGB PS_FtoU_PM_RGB PS_FtoU_UM_RGB \
+ PS_FtoF_PM_LUMA PS_FtoF_UM_LUMA \
+ PS_FtoF_PM_LUMAALPHA PS_FtoF_UM_LUMAALPHA \
+ VS_ResolveDepthStencil PS_ResolveDepth PS_ResolveDepthStencil PS_ResolveStencil
+
+# This shader causes an internal compiler error in mingw73. Re-enable it, when
+# our mingw version can handle it.
+!mingw: angle_d3d11: SHADERS += PS_PassthroughRGBA2DMS
# D3D9
-!winrt: SHADERS += standardvs flipyvs passthroughps luminanceps componentmaskps
+!winrt: SHADERS += standardvs passthroughps \
+ luminanceps luminancepremultps luminanceunmultps \
+ componentmaskps componentmaskpremultps componentmaskunmultps
# Generate headers
for (SHADER, SHADERS) {
@@ -593,11 +766,11 @@ khr_headers.path = $$[QT_INSTALL_HEADERS]/QtANGLE/KHR
gles2_headers.files = \
$$ANGLE_DIR/include/GLES2/gl2.h \
$$ANGLE_DIR/include/GLES2/gl2ext.h \
+ $$ANGLE_DIR/include/GLES2/gl2ext_angle.h \
$$ANGLE_DIR/include/GLES2/gl2platform.h
gles2_headers.path = $$[QT_INSTALL_HEADERS]/QtANGLE/GLES2
gles3_headers.files = \
$$ANGLE_DIR/include/GLES3/gl3.h \
- $$ANGLE_DIR/include/GLES3/gl3ext.h \
$$ANGLE_DIR/include/GLES3/gl3platform.h
gles3_headers.path = $$[QT_INSTALL_HEADERS]/QtANGLE/GLES3
INSTALLS += khr_headers gles2_headers
diff --git a/src/angle/src/compiler/preprocessor/preprocessor.pro b/src/angle/src/compiler/preprocessor/preprocessor.pro
index 9d0728a72d..66bc59a5ff 100644
--- a/src/angle/src/compiler/preprocessor/preprocessor.pro
+++ b/src/angle/src/compiler/preprocessor/preprocessor.pro
@@ -3,7 +3,10 @@ include($$OUT_PWD/../../../../gui/qtgui-config.pri)
qtConfig(dynamicgl): CONFIG += not_installed
include(../../config.pri)
-INCLUDEPATH = $$ANGLE_DIR/src/compiler/preprocessor
+INCLUDEPATH = \
+ $$ANGLE_DIR/src \
+ $$ANGLE_DIR/src/common/third_party/base \
+ $$ANGLE_DIR/src/compiler/preprocessor
DEFINES += _SECURE_SCL=0
@@ -20,12 +23,10 @@ HEADERS += \
$$ANGLE_DIR/src/compiler/preprocessor/DirectiveParser.h \
$$ANGLE_DIR/src/compiler/preprocessor/ExpressionParser.h \
$$ANGLE_DIR/src/compiler/preprocessor/Input.h \
- $$ANGLE_DIR/src/compiler/preprocessor/length_limits.h \
$$ANGLE_DIR/src/compiler/preprocessor/Lexer.h \
$$ANGLE_DIR/src/compiler/preprocessor/Macro.h \
$$ANGLE_DIR/src/compiler/preprocessor/MacroExpander.h \
$$ANGLE_DIR/src/compiler/preprocessor/numeric_lex.h \
- $$ANGLE_DIR/src/compiler/preprocessor/pp_utils.h \
$$ANGLE_DIR/src/compiler/preprocessor/Preprocessor.h \
$$ANGLE_DIR/src/compiler/preprocessor/SourceLocation.h \
$$ANGLE_DIR/src/compiler/preprocessor/Token.h \
diff --git a/src/angle/src/compiler/translator.pro b/src/angle/src/compiler/translator.pro
index 398b9230cc..c1bf73bdc6 100644
--- a/src/angle/src/compiler/translator.pro
+++ b/src/angle/src/compiler/translator.pro
@@ -5,7 +5,8 @@ include(../config.pri)
INCLUDEPATH += \
$$ANGLE_DIR/src \
- $$ANGLE_DIR/include
+ $$ANGLE_DIR/include \
+ $$ANGLE_DIR/src/common/third_party/base
DEFINES += _SECURE_SCL=0 _LIB ANGLE_TRANSLATOR_IMPLEMENTATION ANGLE_TRANSLATOR_STATIC ANGLE_ENABLE_HLSL
@@ -13,11 +14,9 @@ FLEX_SOURCES = $$ANGLE_DIR/src/compiler/translator/glslang.l
BISON_SOURCES = $$ANGLE_DIR/src/compiler/translator/glslang.y
HEADERS += \
- $$ANGLE_DIR/include/GLSLANG/ResourceLimits.h \
$$ANGLE_DIR/include/GLSLANG/ShaderLang.h \
$$ANGLE_DIR/include/GLSLANG/ShaderVars.h \
$$ANGLE_DIR/src/common/angleutils.h \
- $$ANGLE_DIR/src/common/blocklayout.h \
$$ANGLE_DIR/src/common/debug.h \
$$ANGLE_DIR/src/common/platform.h \
$$ANGLE_DIR/src/common/tls.h \
@@ -35,27 +34,18 @@ HEADERS += \
$$ANGLE_DIR/src/compiler/translator/Common.h \
$$ANGLE_DIR/src/compiler/translator/Compiler.h \
$$ANGLE_DIR/src/compiler/translator/ConstantUnion.h \
- $$ANGLE_DIR/src/compiler/translator/depgraph/DependencyGraphBuilder.h \
- $$ANGLE_DIR/src/compiler/translator/depgraph/DependencyGraph.h \
- $$ANGLE_DIR/src/compiler/translator/depgraph/DependencyGraphOutput.h \
$$ANGLE_DIR/src/compiler/translator/Diagnostics.h \
$$ANGLE_DIR/src/compiler/translator/DirectiveHandler.h \
$$ANGLE_DIR/src/compiler/translator/ExtensionBehavior.h \
$$ANGLE_DIR/src/compiler/translator/EmulatePrecision.h \
$$ANGLE_DIR/src/compiler/translator/FlagStd140Structs.h \
- $$ANGLE_DIR/src/compiler/translator/ForLoopUnroll.h \
$$ANGLE_DIR/src/compiler/translator/HashNames.h \
$$ANGLE_DIR/src/compiler/translator/InfoSink.h \
$$ANGLE_DIR/src/compiler/translator/InitializeDll.h \
$$ANGLE_DIR/src/compiler/translator/Initialize.h \
- $$ANGLE_DIR/src/compiler/translator/InitializeParseContext.h \
$$ANGLE_DIR/src/compiler/translator/InitializeVariables.h \
- $$ANGLE_DIR/src/compiler/translator/intermediate.h \
$$ANGLE_DIR/src/compiler/translator/IntermNode.h \
- $$ANGLE_DIR/src/compiler/translator/LoopInfo.h \
- $$ANGLE_DIR/src/compiler/translator/MMap.h \
$$ANGLE_DIR/src/compiler/translator/NodeSearch.h \
- $$ANGLE_DIR/src/compiler/translator/osinclude.h \
$$ANGLE_DIR/src/compiler/translator/Operator.h \
$$ANGLE_DIR/src/compiler/translator/OutputESSL.h \
$$ANGLE_DIR/src/compiler/translator/OutputGLSLBase.h \
@@ -63,25 +53,20 @@ HEADERS += \
$$ANGLE_DIR/src/compiler/translator/OutputHLSL.h \
$$ANGLE_DIR/src/compiler/translator/ParseContext.h \
$$ANGLE_DIR/src/compiler/translator/PoolAlloc.h \
- $$ANGLE_DIR/src/compiler/translator/PruneEmptyDeclarations.h \
$$ANGLE_DIR/src/compiler/translator/Pragma.h \
$$ANGLE_DIR/src/compiler/translator/RegenerateStructNames.h \
$$ANGLE_DIR/src/compiler/translator/RemovePow.h \
$$ANGLE_DIR/src/compiler/translator/RemoveDynamicIndexing.h \
$$ANGLE_DIR/src/compiler/translator/RemoveSwitchFallThrough.h \
- $$ANGLE_DIR/src/compiler/translator/RenameFunction.h \
$$ANGLE_DIR/src/compiler/translator/RewriteDoWhile.h \
$$ANGLE_DIR/src/compiler/translator/RewriteElseBlocks.h \
$$ANGLE_DIR/src/compiler/translator/SeparateArrayInitialization.h \
$$ANGLE_DIR/src/compiler/translator/SeparateDeclarations.h \
$$ANGLE_DIR/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h \
$$ANGLE_DIR/src/compiler/translator/SearchSymbol.h \
- $$ANGLE_DIR/src/compiler/translator/ShHandle.h \
$$ANGLE_DIR/src/compiler/translator/SeparateExpressionsReturningArrays.h \
$$ANGLE_DIR/src/compiler/translator/StructureHLSL.h \
$$ANGLE_DIR/src/compiler/translator/SymbolTable.h \
- $$ANGLE_DIR/src/compiler/translator/timing/RestrictFragmentShaderTiming.h \
- $$ANGLE_DIR/src/compiler/translator/timing/RestrictVertexShaderTiming.h \
$$ANGLE_DIR/src/compiler/translator/TranslatorESSL.h \
$$ANGLE_DIR/src/compiler/translator/TranslatorGLSL.h \
$$ANGLE_DIR/src/compiler/translator/TranslatorHLSL.h \
@@ -95,7 +80,6 @@ HEADERS += \
$$ANGLE_DIR/src/compiler/translator/ValidateLimitations.h \
$$ANGLE_DIR/src/compiler/translator/ValidateOutputs.h \
$$ANGLE_DIR/src/compiler/translator/ValidateSwitch.h \
- $$ANGLE_DIR/src/compiler/translator/VariableInfo.h \
$$ANGLE_DIR/src/compiler/translator/VariablePacker.h \
$$ANGLE_DIR/src/compiler/translator/VersionGLSL.h \
$$ANGLE_DIR/src/third_party/compiler/ArrayBoundsClamper.h
@@ -104,77 +88,108 @@ HEADERS += \
SOURCES += \
$$ANGLE_DIR/src/common/debug.cpp \
$$ANGLE_DIR/src/common/tls.cpp \
+ $$ANGLE_DIR/src/compiler/translator/AddAndTrueToLoopCondition.cpp \
+ $$ANGLE_DIR/src/compiler/translator/AddDefaultReturnStatements.cpp \
$$ANGLE_DIR/src/compiler/translator/ArrayReturnValueToOutParameter.cpp \
$$ANGLE_DIR/src/compiler/translator/ASTMetadataHLSL.cpp \
$$ANGLE_DIR/src/compiler/translator/blocklayout.cpp \
$$ANGLE_DIR/src/compiler/translator/blocklayoutHLSL.cpp \
+ $$ANGLE_DIR/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp \
$$ANGLE_DIR/src/compiler/translator/BuiltInFunctionEmulator.cpp \
$$ANGLE_DIR/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp \
$$ANGLE_DIR/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp \
$$ANGLE_DIR/src/compiler/translator/Cache.cpp \
$$ANGLE_DIR/src/compiler/translator/CallDAG.cpp \
+ $$ANGLE_DIR/src/compiler/translator/ClampPointSize.cpp \
$$ANGLE_DIR/src/compiler/translator/CodeGen.cpp \
+ $$ANGLE_DIR/src/compiler/translator/CollectVariables.cpp \
$$ANGLE_DIR/src/compiler/translator/Compiler.cpp \
- $$ANGLE_DIR/src/compiler/translator/depgraph/DependencyGraph.cpp \
- $$ANGLE_DIR/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp \
- $$ANGLE_DIR/src/compiler/translator/depgraph/DependencyGraphOutput.cpp \
- $$ANGLE_DIR/src/compiler/translator/depgraph/DependencyGraphTraverse.cpp \
+ $$ANGLE_DIR/src/compiler/translator/ConstantUnion.cpp \
+ $$ANGLE_DIR/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp \
+ $$ANGLE_DIR/src/compiler/translator/DeferGlobalInitializers.cpp \
$$ANGLE_DIR/src/compiler/translator/Diagnostics.cpp \
$$ANGLE_DIR/src/compiler/translator/DirectiveHandler.cpp \
+ $$ANGLE_DIR/src/compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp \
+ $$ANGLE_DIR/src/compiler/translator/EmulateGLFragColorBroadcast.cpp \
$$ANGLE_DIR/src/compiler/translator/EmulatePrecision.cpp \
+ $$ANGLE_DIR/src/compiler/translator/ExpandIntegerPowExpressions.cpp \
+ $$ANGLE_DIR/src/compiler/translator/ExtensionBehavior.cpp \
+ $$ANGLE_DIR/src/compiler/translator/ExtensionGLSL.cpp \
+ $$ANGLE_DIR/src/compiler/translator/FindMain.cpp \
+ $$ANGLE_DIR/src/compiler/translator/FindSymbolNode.cpp \
$$ANGLE_DIR/src/compiler/translator/FlagStd140Structs.cpp \
- $$ANGLE_DIR/src/compiler/translator/ForLoopUnroll.cpp \
+ $$ANGLE_DIR/src/compiler/translator/HashNames.cpp \
+ $$ANGLE_DIR/src/compiler/translator/ImageFunctionHLSL.cpp \
$$ANGLE_DIR/src/compiler/translator/InfoSink.cpp \
$$ANGLE_DIR/src/compiler/translator/Initialize.cpp \
$$ANGLE_DIR/src/compiler/translator/InitializeDll.cpp \
- $$ANGLE_DIR/src/compiler/translator/InitializeParseContext.cpp \
$$ANGLE_DIR/src/compiler/translator/InitializeVariables.cpp \
- $$ANGLE_DIR/src/compiler/translator/Intermediate.cpp \
$$ANGLE_DIR/src/compiler/translator/IntermNode.cpp \
- $$ANGLE_DIR/src/compiler/translator/intermOut.cpp \
+ $$ANGLE_DIR/src/compiler/translator/IntermNodePatternMatcher.cpp \
+ $$ANGLE_DIR/src/compiler/translator/IntermNode_util.cpp \
$$ANGLE_DIR/src/compiler/translator/IntermTraverse.cpp \
- $$ANGLE_DIR/src/compiler/translator/LoopInfo.cpp \
+ $$ANGLE_DIR/src/compiler/translator/IsASTDepthBelowLimit.cpp \
$$ANGLE_DIR/src/compiler/translator/Operator.cpp \
$$ANGLE_DIR/src/compiler/translator/OutputESSL.cpp \
$$ANGLE_DIR/src/compiler/translator/OutputGLSL.cpp \
$$ANGLE_DIR/src/compiler/translator/OutputGLSLBase.cpp \
$$ANGLE_DIR/src/compiler/translator/OutputHLSL.cpp \
+ $$ANGLE_DIR/src/compiler/translator/OutputTree.cpp \
+ $$ANGLE_DIR/src/compiler/translator/OutputVulkanGLSL.cpp \
$$ANGLE_DIR/src/compiler/translator/ParseContext.cpp \
$$ANGLE_DIR/src/compiler/translator/PoolAlloc.cpp \
- $$ANGLE_DIR/src/compiler/translator/PruneEmptyDeclarations.cpp \
+ $$ANGLE_DIR/src/compiler/translator/PruneNoOps.cpp \
+ $$ANGLE_DIR/src/compiler/translator/QualifierTypes.cpp \
+ $$ANGLE_DIR/src/compiler/translator/RecordConstantPrecision.cpp \
$$ANGLE_DIR/src/compiler/translator/RegenerateStructNames.cpp \
- $$ANGLE_DIR/src/compiler/translator/RemovePow.cpp \
+ $$ANGLE_DIR/src/compiler/translator/RemoveArrayLengthMethod.cpp \
$$ANGLE_DIR/src/compiler/translator/RemoveDynamicIndexing.cpp \
+ $$ANGLE_DIR/src/compiler/translator/RemoveEmptySwitchStatements.cpp \
+ $$ANGLE_DIR/src/compiler/translator/RemoveInvariantDeclaration.cpp \
+ $$ANGLE_DIR/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.cpp \
+ $$ANGLE_DIR/src/compiler/translator/RemovePow.cpp \
$$ANGLE_DIR/src/compiler/translator/RemoveSwitchFallThrough.cpp \
+ $$ANGLE_DIR/src/compiler/translator/RemoveUnreferencedVariables.cpp \
$$ANGLE_DIR/src/compiler/translator/RewriteDoWhile.cpp \
$$ANGLE_DIR/src/compiler/translator/RewriteElseBlocks.cpp \
- $$ANGLE_DIR/src/compiler/translator/SeparateArrayInitialization.cpp \
- $$ANGLE_DIR/src/compiler/translator/SeparateDeclarations.cpp \
+ $$ANGLE_DIR/src/compiler/translator/RewriteTexelFetchOffset.cpp \
+ $$ANGLE_DIR/src/compiler/translator/RewriteUnaryMinusOperatorFloat.cpp \
+ $$ANGLE_DIR/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp \
+ $$ANGLE_DIR/src/compiler/translator/RunAtTheEndOfShader.cpp \
$$ANGLE_DIR/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp \
$$ANGLE_DIR/src/compiler/translator/SearchSymbol.cpp \
+ $$ANGLE_DIR/src/compiler/translator/SeparateArrayInitialization.cpp \
+ $$ANGLE_DIR/src/compiler/translator/SeparateDeclarations.cpp \
+ $$ANGLE_DIR/src/compiler/translator/SeparateExpressionsReturningArrays.cpp \
$$ANGLE_DIR/src/compiler/translator/ShaderLang.cpp \
$$ANGLE_DIR/src/compiler/translator/ShaderVars.cpp \
- $$ANGLE_DIR/src/compiler/translator/SeparateExpressionsReturningArrays.cpp \
+ $$ANGLE_DIR/src/compiler/translator/SimplifyLoopConditions.cpp \
+ $$ANGLE_DIR/src/compiler/translator/SplitSequenceOperator.cpp \
$$ANGLE_DIR/src/compiler/translator/StructureHLSL.cpp \
$$ANGLE_DIR/src/compiler/translator/SymbolTable.cpp \
- $$ANGLE_DIR/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp \
- $$ANGLE_DIR/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp \
+ $$ANGLE_DIR/src/compiler/translator/SymbolUniqueId.cpp \
+ $$ANGLE_DIR/src/compiler/translator/TextureFunctionHLSL.cpp \
$$ANGLE_DIR/src/compiler/translator/TranslatorESSL.cpp \
$$ANGLE_DIR/src/compiler/translator/TranslatorGLSL.cpp \
$$ANGLE_DIR/src/compiler/translator/TranslatorHLSL.cpp \
+ $$ANGLE_DIR/src/compiler/translator/TranslatorVulkan.cpp \
$$ANGLE_DIR/src/compiler/translator/Types.cpp \
- $$ANGLE_DIR/src/compiler/translator/UnfoldShortCircuitToIf.cpp \
$$ANGLE_DIR/src/compiler/translator/UnfoldShortCircuitAST.cpp \
+ $$ANGLE_DIR/src/compiler/translator/UnfoldShortCircuitToIf.cpp \
$$ANGLE_DIR/src/compiler/translator/UniformHLSL.cpp \
+ $$ANGLE_DIR/src/compiler/translator/UseInterfaceBlockFields.cpp \
$$ANGLE_DIR/src/compiler/translator/UtilsHLSL.cpp \
$$ANGLE_DIR/src/compiler/translator/util.cpp \
$$ANGLE_DIR/src/compiler/translator/ValidateGlobalInitializer.cpp \
$$ANGLE_DIR/src/compiler/translator/ValidateLimitations.cpp \
+ $$ANGLE_DIR/src/compiler/translator/ValidateMaxParameters.cpp \
$$ANGLE_DIR/src/compiler/translator/ValidateOutputs.cpp \
$$ANGLE_DIR/src/compiler/translator/ValidateSwitch.cpp \
- $$ANGLE_DIR/src/compiler/translator/VariableInfo.cpp \
$$ANGLE_DIR/src/compiler/translator/VariablePacker.cpp \
+ $$ANGLE_DIR/src/compiler/translator/ValidateVaryingLocations.cpp \
$$ANGLE_DIR/src/compiler/translator/VersionGLSL.cpp \
+ $$ANGLE_DIR/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp \
+ $$ANGLE_DIR/src/compiler/translator/WrapSwitchStatementsInBlocks.cpp \
$$ANGLE_DIR/src/third_party/compiler/ArrayBoundsClamper.cpp
diff --git a/src/angle/src/config.pri b/src/angle/src/config.pri
index 4beb095217..5c521281a6 100644
--- a/src/angle/src/config.pri
+++ b/src/angle/src/config.pri
@@ -55,7 +55,7 @@ CONFIG(debug, debug|release) {
!isEmpty(BUILD_PASS): BUILDSUBDIR = $$lower($$BUILD_PASS)/
# c++11 is needed by MinGW to get support for unordered_map.
-CONFIG += stl exceptions c++11
+CONFIG += stl exceptions c++11 c++14
INCLUDEPATH += . .. $$PWD/../include
diff --git a/src/angle/src/libEGL/libEGL.pro b/src/angle/src/libEGL/libEGL.pro
index 9e9c639002..889f39890e 100644
--- a/src/angle/src/libEGL/libEGL.pro
+++ b/src/angle/src/libEGL/libEGL.pro
@@ -21,6 +21,7 @@ SOURCES += \
egl_headers.files = \
$$ANGLE_DIR/include/EGL/egl.h \
$$ANGLE_DIR/include/EGL/eglext.h \
+ $$ANGLE_DIR/include/EGL/eglext_angle.h \
$$ANGLE_DIR/include/EGL/eglplatform.h
egl_headers.path = $$[QT_INSTALL_HEADERS]/QtANGLE/EGL
INSTALLS += egl_headers
diff --git a/src/corelib/Qt5CoreMacros.cmake b/src/corelib/Qt5CoreMacros.cmake
index 819b48f973..620795d2cf 100644
--- a/src/corelib/Qt5CoreMacros.cmake
+++ b/src/corelib/Qt5CoreMacros.cmake
@@ -285,7 +285,7 @@ function(QT5_ADD_RESOURCES outfiles )
COMMAND ${Qt5Core_RCC_EXECUTABLE}
ARGS ${rcc_options} --name ${outfilename} --output ${outfile} ${infile}
MAIN_DEPENDENCY ${infile}
- DEPENDS ${_rc_depends} "${out_depends}" VERBATIM)
+ DEPENDS ${_rc_depends} "${_out_depends}" VERBATIM)
set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOMOC ON)
set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOUIC ON)
list(APPEND ${outfiles} ${outfile})
@@ -293,6 +293,49 @@ function(QT5_ADD_RESOURCES outfiles )
set(${outfiles} ${${outfiles}} PARENT_SCOPE)
endfunction()
+# qt5_add_big_resources(outfiles inputfile ... )
+
+function(QT5_ADD_BIG_RESOURCES outfiles )
+
+ set(options)
+ set(oneValueArgs)
+ set(multiValueArgs OPTIONS)
+
+ cmake_parse_arguments(_RCC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ set(rcc_files ${_RCC_UNPARSED_ARGUMENTS})
+ set(rcc_options ${_RCC_OPTIONS})
+
+ if("${rcc_options}" MATCHES "-binary")
+ message(WARNING "Use qt5_add_binary_resources for binary option")
+ endif()
+
+ foreach(it ${rcc_files})
+ get_filename_component(outfilename ${it} NAME_WE)
+ get_filename_component(infile ${it} ABSOLUTE)
+ set(tmpoutfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${outfilename}tmp.cpp)
+ set(outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${outfilename}.o)
+
+ _QT5_PARSE_QRC_FILE(${infile} _out_depends _rc_depends)
+ set_source_files_properties(${infile} PROPERTIES SKIP_AUTORCC ON)
+ add_custom_command(OUTPUT ${tmpoutfile}
+ COMMAND ${Qt5Core_RCC_EXECUTABLE} ${rcc_options} --name ${outfilename} --pass 1 --output ${tmpoutfile} ${infile}
+ DEPENDS ${infile} ${_rc_depends} "${out_depends}" VERBATIM)
+ set_source_files_properties(${tmpoutfile} PROPERTIES SKIP_AUTOMOC ON)
+ set_source_files_properties(${tmpoutfile} PROPERTIES SKIP_AUTOUIC ON)
+ add_custom_target(big_resources_${outfilename} ALL DEPENDS ${tmpoutfile})
+ add_library(rcc_object_${outfilename} OBJECT ${tmpoutfile})
+ add_dependencies(rcc_object_${outfilename} big_resources_${outfilename})
+ add_custom_command(OUTPUT ${outfile}
+ COMMAND ${Qt5Core_RCC_EXECUTABLE}
+ ARGS ${rcc_options} --name ${outfilename} --pass 2 --temp $<TARGET_OBJECTS:rcc_object_${outfilename}> --output ${outfile} ${infile}
+ DEPENDS rcc_object_${outfilename}
+ VERBATIM)
+ list(APPEND ${outfiles} ${outfile})
+ endforeach()
+ set(${outfiles} ${${outfiles}} PARENT_SCOPE)
+endfunction()
+
set(_Qt5_COMPONENT_PATH "${CMAKE_CURRENT_LIST_DIR}/..")
if (NOT CMAKE_VERSION VERSION_LESS 2.8.9)
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp
index 4d7ce038dd..9dd81b2ecd 100644
--- a/src/corelib/animation/qabstractanimation.cpp
+++ b/src/corelib/animation/qabstractanimation.cpp
@@ -213,9 +213,7 @@ typedef QList<QAbstractAnimation*>::ConstIterator AnimationListConstIt;
QUnifiedTimer drives animations indirectly, via QAbstractAnimationTimer.
*/
-#ifndef QT_NO_THREAD
Q_GLOBAL_STATIC(QThreadStorage<QUnifiedTimer *>, unifiedTimer)
-#endif
QUnifiedTimer::QUnifiedTimer() :
QObject(), defaultDriver(this), lastTick(0), timingInterval(DEFAULT_TIMER_INTERVAL),
@@ -232,18 +230,12 @@ QUnifiedTimer::QUnifiedTimer() :
QUnifiedTimer *QUnifiedTimer::instance(bool create)
{
QUnifiedTimer *inst;
-#ifndef QT_NO_THREAD
if (create && !unifiedTimer()->hasLocalData()) {
inst = new QUnifiedTimer;
unifiedTimer()->setLocalData(inst);
} else {
inst = unifiedTimer() ? unifiedTimer()->localData() : 0;
}
-#else
- Q_UNUSED(create);
- static QUnifiedTimer unifiedTimer;
- inst = &unifiedTimer;
-#endif
return inst;
}
@@ -552,7 +544,7 @@ bool QUnifiedTimer::canUninstallAnimationDriver(QAnimationDriver *d)
return d == driver && driver != &defaultDriver;
}
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
Q_GLOBAL_STATIC(QThreadStorage<QAnimationTimer *>, animationTimer)
#endif
@@ -567,7 +559,7 @@ QAnimationTimer::QAnimationTimer() :
QAnimationTimer *QAnimationTimer::instance(bool create)
{
QAnimationTimer *inst;
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
if (create && !animationTimer()->hasLocalData()) {
inst = new QAnimationTimer;
animationTimer()->setLocalData(inst);
diff --git a/src/corelib/animation/qparallelanimationgroup.cpp b/src/corelib/animation/qparallelanimationgroup.cpp
index 1dcf006dd3..492fb82e2b 100644
--- a/src/corelib/animation/qparallelanimationgroup.cpp
+++ b/src/corelib/animation/qparallelanimationgroup.cpp
@@ -53,13 +53,7 @@
You can treat QParallelAnimationGroup as any other QAbstractAnimation,
e.g., pause, resume, or add it to other animation groups.
- \code
- QParallelAnimationGroup *group = new QParallelAnimationGroup;
- group->addAnimation(anim1);
- group->addAnimation(anim2);
-
- group->start();
- \endcode
+ \snippet code/src_corelib_animation_qparallelanimationgroup.cpp 0
In this example, \c anim1 and \c anim2 are two
\l{QPropertyAnimation}s that have already been set up.
diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp
index 174121516b..28c03553c5 100644
--- a/src/corelib/animation/qpropertyanimation.cpp
+++ b/src/corelib/animation/qpropertyanimation.cpp
@@ -56,14 +56,7 @@
makes it possible to animate many of Qt's widgets. Let's look at
an example:
- \code
- QPropertyAnimation *animation = new QPropertyAnimation(myWidget, "geometry");
- animation->setDuration(10000);
- animation->setStartValue(QRect(0, 0, 100, 30));
- animation->setEndValue(QRect(250, 250, 100, 30));
-
- animation->start();
- \endcode
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp 0
The property name and the QObject instance of which property
should be animated are passed to the constructor. You can then
diff --git a/src/corelib/animation/qsequentialanimationgroup.cpp b/src/corelib/animation/qsequentialanimationgroup.cpp
index 8af6b33722..150e74d7d6 100644
--- a/src/corelib/animation/qsequentialanimationgroup.cpp
+++ b/src/corelib/animation/qsequentialanimationgroup.cpp
@@ -61,14 +61,7 @@
groups. You can also call addPause() or insertPause() to add a
pause to a sequential animation group.
- \code
- QSequentialAnimationGroup *group = new QSequentialAnimationGroup;
-
- group->addAnimation(anim1);
- group->addAnimation(anim2);
-
- group->start();
- \endcode
+ \snippet code/src_corelib_animation_qsequentialanimationgroup.cpp 0
In this example, \c anim1 and \c anim2 are two already set up
\l{QPropertyAnimation}s.
diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp
index df533c5f4d..e935ac711e 100644
--- a/src/corelib/animation/qvariantanimation.cpp
+++ b/src/corelib/animation/qvariantanimation.cpp
@@ -116,15 +116,7 @@ QT_BEGIN_NAMESPACE
and the current progress.
Example:
- \code
- QVariant myColorInterpolator(const QColor &start, const QColor &end, qreal progress)
- {
- ...
- return QColor(...);
- }
- ...
- qRegisterAnimationInterpolator<QColor>(myColorInterpolator);
- \endcode
+ \snippet code/src_corelib_animation_qvariantanimation.cpp 0
Another option is to reimplement interpolated(), which returns
interpolation values for the value being interpolated.
@@ -416,9 +408,7 @@ static QBasicMutex registeredInterpolatorsMutex;
This is a typedef for a pointer to a function with the following
signature:
- \code
- QVariant myInterpolator(const QVariant &from, const QVariant &to, qreal progress);
- \endcode
+ \snippet code/src_corelib_animation_qvariantanimation.cpp 1
*/
diff --git a/src/corelib/codecs/qeucjpcodec_p.h b/src/corelib/codecs/qeucjpcodec_p.h
index 535e830ad0..d79e2435e3 100644
--- a/src/corelib/codecs/qeucjpcodec_p.h
+++ b/src/corelib/codecs/qeucjpcodec_p.h
@@ -94,12 +94,12 @@ public:
static QList<QByteArray> _aliases() { return QList<QByteArray>(); }
static int _mibEnum();
- QByteArray name() const { return _name(); }
- QList<QByteArray> aliases() const { return _aliases(); }
- int mibEnum() const { return _mibEnum(); }
+ QByteArray name() const override { return _name(); }
+ QList<QByteArray> aliases() const override { return _aliases(); }
+ int mibEnum() const override { return _mibEnum(); }
- QString convertToUnicode(const char *, int, ConverterState *) const;
- QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const;
+ QString convertToUnicode(const char *, int, ConverterState *) const override;
+ QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const override;
QEucJpCodec();
~QEucJpCodec();
diff --git a/src/corelib/codecs/qeuckrcodec_p.h b/src/corelib/codecs/qeuckrcodec_p.h
index 9e85ca8c20..6180548aab 100644
--- a/src/corelib/codecs/qeuckrcodec_p.h
+++ b/src/corelib/codecs/qeuckrcodec_p.h
@@ -90,12 +90,12 @@ public:
static QList<QByteArray> _aliases() { return QList<QByteArray>(); }
static int _mibEnum();
- QByteArray name() const { return _name(); }
- QList<QByteArray> aliases() const { return _aliases(); }
- int mibEnum() const { return _mibEnum(); }
+ QByteArray name() const override { return _name(); }
+ QList<QByteArray> aliases() const override { return _aliases(); }
+ int mibEnum() const override { return _mibEnum(); }
- QString convertToUnicode(const char *, int, ConverterState *) const;
- QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const;
+ QString convertToUnicode(const char *, int, ConverterState *) const override;
+ QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const override;
};
class QCP949Codec : public QTextCodec {
@@ -104,12 +104,12 @@ public:
static QList<QByteArray> _aliases();
static int _mibEnum();
- QByteArray name() const { return _name(); }
- QList<QByteArray> aliases() const { return _aliases(); }
- int mibEnum() const { return _mibEnum(); }
+ QByteArray name() const override { return _name(); }
+ QList<QByteArray> aliases() const override { return _aliases(); }
+ int mibEnum() const override { return _mibEnum(); }
- QString convertToUnicode(const char *, int, ConverterState *) const;
- QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const;
+ QString convertToUnicode(const char *, int, ConverterState *) const override;
+ QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const override;
};
QT_END_NAMESPACE
diff --git a/src/corelib/codecs/qgb18030codec_p.h b/src/corelib/codecs/qgb18030codec_p.h
index 2fea21b5b3..c263309357 100644
--- a/src/corelib/codecs/qgb18030codec_p.h
+++ b/src/corelib/codecs/qgb18030codec_p.h
@@ -69,12 +69,12 @@ public:
static QList<QByteArray> _aliases() { return QList<QByteArray>(); }
static int _mibEnum() { return 114; }
- QByteArray name() const { return _name(); }
- QList<QByteArray> aliases() const { return _aliases(); }
- int mibEnum() const { return _mibEnum(); }
+ QByteArray name() const override { return _name(); }
+ QList<QByteArray> aliases() const override { return _aliases(); }
+ int mibEnum() const override { return _mibEnum(); }
- QString convertToUnicode(const char *, int, ConverterState *) const;
- QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const;
+ QString convertToUnicode(const char *, int, ConverterState *) const override;
+ QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const override;
};
class QGbkCodec : public QGb18030Codec {
@@ -85,12 +85,12 @@ public:
static QList<QByteArray> _aliases();
static int _mibEnum();
- QByteArray name() const { return _name(); }
- QList<QByteArray> aliases() const { return _aliases(); }
- int mibEnum() const { return _mibEnum(); }
+ QByteArray name() const override { return _name(); }
+ QList<QByteArray> aliases() const override { return _aliases(); }
+ int mibEnum() const override { return _mibEnum(); }
- QString convertToUnicode(const char *, int, ConverterState *) const;
- QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const;
+ QString convertToUnicode(const char *, int, ConverterState *) const override;
+ QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const override;
};
class QGb2312Codec : public QGb18030Codec {
@@ -101,11 +101,11 @@ public:
static QList<QByteArray> _aliases() { return QList<QByteArray>(); }
static int _mibEnum();
- QByteArray name() const { return _name(); }
- int mibEnum() const { return _mibEnum(); }
+ QByteArray name() const override { return _name(); }
+ int mibEnum() const override { return _mibEnum(); }
- QString convertToUnicode(const char *, int, ConverterState *) const;
- QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const;
+ QString convertToUnicode(const char *, int, ConverterState *) const override;
+ QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const override;
};
QT_END_NAMESPACE
diff --git a/src/corelib/codecs/qiconvcodec_p.h b/src/corelib/codecs/qiconvcodec_p.h
index 9b8500538b..7d192232d7 100644
--- a/src/corelib/codecs/qiconvcodec_p.h
+++ b/src/corelib/codecs/qiconvcodec_p.h
@@ -69,11 +69,11 @@ public:
QIconvCodec();
~QIconvCodec();
- QString convertToUnicode(const char *, int, ConverterState *) const;
- QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const;
+ QString convertToUnicode(const char *, int, ConverterState *) const override;
+ QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const override;
- QByteArray name() const;
- int mibEnum() const;
+ QByteArray name() const override;
+ int mibEnum() const override;
void init() const;
iconv_t createIconv_t(const char *to, const char *from) const;
diff --git a/src/corelib/codecs/qjiscodec_p.h b/src/corelib/codecs/qjiscodec_p.h
index c3eda25bdf..41195af108 100644
--- a/src/corelib/codecs/qjiscodec_p.h
+++ b/src/corelib/codecs/qjiscodec_p.h
@@ -94,12 +94,12 @@ public:
static QList<QByteArray> _aliases();
static int _mibEnum();
- QByteArray name() const { return _name(); }
- QList<QByteArray> aliases() const { return _aliases(); }
- int mibEnum() const { return _mibEnum(); }
+ QByteArray name() const override { return _name(); }
+ QList<QByteArray> aliases() const override { return _aliases(); }
+ int mibEnum() const override { return _mibEnum(); }
- QString convertToUnicode(const char *, int, ConverterState *) const;
- QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const;
+ QString convertToUnicode(const char *, int, ConverterState *) const override;
+ QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const override;
QJisCodec();
~QJisCodec();
diff --git a/src/corelib/codecs/qjpunicode.cpp b/src/corelib/codecs/qjpunicode.cpp
index a3f3448bb6..61f6eac93a 100644
--- a/src/corelib/codecs/qjpunicode.cpp
+++ b/src/corelib/codecs/qjpunicode.cpp
@@ -347,15 +347,15 @@ public:
// uint Jisx0201ToUnicode(uint h, uint l) const;
// uint Jisx0201LatinToUnicode(uint h, uint l) const;
// uint Jisx0201KanaToUnicode(uint h, uint l) const;
- uint jisx0208ToUnicode(uint h, uint l) const;
- uint jisx0212ToUnicode(uint h, uint l) const;
+ uint jisx0208ToUnicode(uint h, uint l) const override;
+ uint jisx0212ToUnicode(uint h, uint l) const override;
// uint UnicodeToAscii(uint h, uint l) const;
// uint UnicodeToJisx0201(uint h, uint l) const;
// uint UnicodeToJisx0201Latin(uint h, uint l) const;
// uint UnicodeToJisx0201Kana(uint h, uint l) const;
- uint unicodeToJisx0208(uint h, uint l) const;
- uint unicodeToJisx0212(uint h, uint l) const;
+ uint unicodeToJisx0208(uint h, uint l) const override;
+ uint unicodeToJisx0212(uint h, uint l) const override;
};
uint QJpUnicodeConv_Unicode_ASCII::jisx0208ToUnicode(uint h, uint l) const
@@ -404,18 +404,18 @@ class QJpUnicodeConv_JISX0221_JISX0201 : public QJpUnicodeConv {
public:
QJpUnicodeConv_JISX0221_JISX0201(int r) : QJpUnicodeConv(r) {}
- uint asciiToUnicode(uint h, uint l) const;
+ uint asciiToUnicode(uint h, uint l) const override;
// uint Jisx0201ToUnicode(uint h, uint l) const;
// uint Jisx0201LatinToUnicode(uint h, uint l) const;
// uint Jisx0201KanaToUnicode(uint h, uint l) const;
- uint jisx0208ToUnicode(uint h, uint l) const;
+ uint jisx0208ToUnicode(uint h, uint l) const override;
// uint Jisx0212ToUnicode(uint h, uint l) const;
- uint unicodeToAscii(uint h, uint l) const;
+ uint unicodeToAscii(uint h, uint l) const override;
// uint UnicodeToJisx0201(uint h, uint l) const;
// uint UnicodeToJisx0201Latin(uint h, uint l) const;
// uint UnicodeToJisx0201Kana(uint h, uint l) const;
- uint unicodeToJisx0208(uint h, uint l) const;
+ uint unicodeToJisx0208(uint h, uint l) const override;
// uint UnicodeToJisx0212(uint h, uint l) const;
};
@@ -460,17 +460,17 @@ public:
// uint AsciiToUnicode(uint h, uint l) const;
// uint Jisx0201ToUnicode(uint h, uint l) const;
- uint jisx0201LatinToUnicode(uint h, uint l) const;
+ uint jisx0201LatinToUnicode(uint h, uint l) const override;
// uint Jisx0201KanaToUnicode(uint h, uint l) const;
- uint jisx0208ToUnicode(uint h, uint l) const;
- uint jisx0212ToUnicode(uint h, uint l) const;
+ uint jisx0208ToUnicode(uint h, uint l) const override;
+ uint jisx0212ToUnicode(uint h, uint l) const override;
// uint UnicodeToAscii(uint h, uint l) const;
// uint UnicodeToJisx0201(uint h, uint l) const;
- uint unicodeToJisx0201Latin(uint h, uint l) const;
+ uint unicodeToJisx0201Latin(uint h, uint l) const override;
// uint UnicodeToJisx0201Kana(uint h, uint l) const;
- uint unicodeToJisx0208(uint h, uint l) const;
- uint unicodeToJisx0212(uint h, uint l) const;
+ uint unicodeToJisx0208(uint h, uint l) const override;
+ uint unicodeToJisx0212(uint h, uint l) const override;
};
uint QJpUnicodeConv_JISX0221_ASCII::jisx0201LatinToUnicode(uint h, uint l) const
@@ -556,17 +556,17 @@ public:
// uint AsciiToUnicode(uint h, uint l) const;
// uint Jisx0201ToUnicode(uint h, uint l) const;
- uint jisx0201LatinToUnicode(uint h, uint l) const;
+ uint jisx0201LatinToUnicode(uint h, uint l) const override;
// uint Jisx0201KanaToUnicode(uint h, uint l) const;
- uint jisx0208ToUnicode(uint h, uint l) const;
- uint jisx0212ToUnicode(uint h, uint l) const;
+ uint jisx0208ToUnicode(uint h, uint l) const override;
+ uint jisx0212ToUnicode(uint h, uint l) const override;
- uint unicodeToAscii(uint h, uint l) const;
+ uint unicodeToAscii(uint h, uint l) const override;
// uint UnicodeToJisx0201(uint h, uint l) const;
- uint unicodeToJisx0201Latin(uint h, uint l) const;
+ uint unicodeToJisx0201Latin(uint h, uint l) const override;
// uint UnicodeToJisx0201Kana(uint h, uint l) const;
- uint unicodeToJisx0208(uint h, uint l) const;
- uint unicodeToJisx0212(uint h, uint l) const;
+ uint unicodeToJisx0208(uint h, uint l) const override;
+ uint unicodeToJisx0212(uint h, uint l) const override;
};
uint QJpUnicodeConv_Sun::jisx0201LatinToUnicode(uint h, uint l) const
@@ -645,17 +645,17 @@ public:
// uint AsciiToUnicode(uint h, uint l) const;
// uint Jisx0201ToUnicode(uint h, uint l) const;
- uint jisx0201LatinToUnicode(uint h, uint l) const;
+ uint jisx0201LatinToUnicode(uint h, uint l) const override;
// uint Jisx0201KanaToUnicode(uint h, uint l) const;
- uint jisx0208ToUnicode(uint h, uint l) const;
- uint jisx0212ToUnicode(uint h, uint l) const;
+ uint jisx0208ToUnicode(uint h, uint l) const override;
+ uint jisx0212ToUnicode(uint h, uint l) const override;
// uint UnicodeToAscii(uint h, uint l) const;
// uint UnicodeToJisx0201(uint h, uint l) const;
- uint unicodeToJisx0201Latin(uint h, uint l) const;
+ uint unicodeToJisx0201Latin(uint h, uint l) const override;
// uint UnicodeToJisx0201Kana(uint h, uint l) const;
- uint unicodeToJisx0208(uint h, uint l) const;
- uint unicodeToJisx0212(uint h, uint l) const;
+ uint unicodeToJisx0208(uint h, uint l) const override;
+ uint unicodeToJisx0212(uint h, uint l) const override;
};
uint QJpUnicodeConv_Microsoft::jisx0201LatinToUnicode(uint h, uint l) const
diff --git a/src/corelib/codecs/qsjiscodec_p.h b/src/corelib/codecs/qsjiscodec_p.h
index 9d7ea5d6d2..1e5cd44f26 100644
--- a/src/corelib/codecs/qsjiscodec_p.h
+++ b/src/corelib/codecs/qsjiscodec_p.h
@@ -94,12 +94,12 @@ public:
static QList<QByteArray> _aliases();
static int _mibEnum();
- QByteArray name() const { return _name(); }
- QList<QByteArray> aliases() const { return _aliases(); }
- int mibEnum() const { return _mibEnum(); }
+ QByteArray name() const override { return _name(); }
+ QList<QByteArray> aliases() const override { return _aliases(); }
+ int mibEnum() const override { return _mibEnum(); }
- QString convertToUnicode(const char *, int, ConverterState *) const;
- QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const;
+ QString convertToUnicode(const char *, int, ConverterState *) const override;
+ QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const override;
QSjisCodec();
~QSjisCodec();
diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp
index 790921610a..fedd39e104 100644
--- a/src/corelib/codecs/qtextcodec.cpp
+++ b/src/corelib/codecs/qtextcodec.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -494,6 +495,24 @@ QTextCodec::QTextCodec()
*/
QTextCodec::~QTextCodec()
{
+ QCoreGlobalData *globalData = QCoreGlobalData::instance();
+ if (!globalData)
+ return;
+
+ globalData->codecForLocale.testAndSetRelaxed(this, nullptr);
+
+ QMutexLocker locker(textCodecsMutex());
+
+ globalData->allCodecs.removeOne(this);
+
+ auto it = globalData->codecCache.cbegin();
+
+ while (it != globalData->codecCache.cend()) {
+ if (it.value() == this)
+ it = globalData->codecCache.erase(it);
+ else
+ ++it;
+ }
}
/*!
@@ -1220,6 +1239,19 @@ bool QTextDecoder::hasFailure() const
return state.invalidChars != 0;
}
+/*!
+ \internal
+ \since 5.12
+
+ Determines whether the decoder needs more bytes to continue decoding. That
+ is, this signifies that the input string ended in the middle of a
+ multi-byte sequence. Note that it's possible some codecs do not report this.
+ */
+bool QTextDecoder::needsMoreData() const
+{
+ return state.remainingChars;
+}
+
QT_END_NAMESPACE
#endif // QT_NO_TEXTCODEC
diff --git a/src/corelib/codecs/qtextcodec.h b/src/corelib/codecs/qtextcodec.h
index 8153bebac8..09d21166d8 100644
--- a/src/corelib/codecs/qtextcodec.h
+++ b/src/corelib/codecs/qtextcodec.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -162,6 +162,7 @@ public:
QString toUnicode(const QByteArray &ba);
void toUnicode(QString *target, const char *chars, int len);
bool hasFailure() const;
+ bool needsMoreData() const;
private:
const QTextCodec *c;
QTextCodec::ConverterState state;
diff --git a/src/corelib/codecs/qtextcodec_p.h b/src/corelib/codecs/qtextcodec_p.h
index f3c2d090c9..be0cab93e6 100644
--- a/src/corelib/codecs/qtextcodec_p.h
+++ b/src/corelib/codecs/qtextcodec_p.h
@@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_TEXTCODEC
-#if defined(Q_OS_MAC) || defined(Q_OS_ANDROID) || defined(Q_OS_QNX)
+#if defined(Q_OS_MAC) || defined(Q_OS_ANDROID) || defined(Q_OS_QNX) || defined(Q_OS_WASM)
#define QT_LOCALE_IS_UTF8
#endif
diff --git a/src/corelib/codecs/qutfcodec.cpp b/src/corelib/codecs/qutfcodec.cpp
index ce1b092a54..26c68cdee5 100644
--- a/src/corelib/codecs/qutfcodec.cpp
+++ b/src/corelib/codecs/qutfcodec.cpp
@@ -102,6 +102,26 @@ static inline bool simdEncodeAscii(uchar *&dst, const ushort *&nextAscii, const
return false;
}
}
+
+ if (end - src >= 8) {
+ // do eight characters at a time
+ __m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src));
+ __m128i packed = _mm_packus_epi16(data, data);
+ __m128i nonAscii = _mm_cmpgt_epi8(packed, _mm_setzero_si128());
+
+ // store even non-ASCII
+ _mm_storel_epi64(reinterpret_cast<__m128i *>(dst), packed);
+
+ uchar n = ~_mm_movemask_epi8(nonAscii);
+ if (n) {
+ nextAscii = src + qBitScanReverse(n) + 1;
+ n = qCountTrailingZeroBits(n);
+ dst += n;
+ src += n;
+ return false;
+ }
+ }
+
return src == end;
}
@@ -150,11 +170,52 @@ static inline bool simdDecodeAscii(ushort *&dst, const uchar *&nextAscii, const
return false;
}
+
+ if (end - src >= 8) {
+ __m128i data = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(src));
+ uint n = _mm_movemask_epi8(data) & 0xff;
+ if (!n) {
+ // unpack and store
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(dst), _mm_unpacklo_epi8(data, _mm_setzero_si128()));
+ } else {
+ while (!(n & 1)) {
+ *dst++ = *src++;
+ n >>= 1;
+ }
+
+ n = qBitScanReverse(n);
+ nextAscii = src + n + 1;
+ return false;
+ }
+ }
+
return src == end;
}
static inline const uchar *simdFindNonAscii(const uchar *src, const uchar *end, const uchar *&nextAscii)
{
+#ifdef __AVX2__
+ // do 32 characters at a time
+ // (this is similar to simdTestMask in qstring.cpp)
+ const __m256i mask = _mm256_set1_epi8(0x80);
+ for ( ; end - src >= 32; src += 32) {
+ __m256i data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(src));
+ if (_mm256_testz_si256(mask, data))
+ continue;
+
+ uint n = _mm256_movemask_epi8(data);
+ Q_ASSUME(n);
+
+ // find the next probable ASCII character
+ // we don't want to load 32 bytes again in this loop if we know there are non-ASCII
+ // characters still coming
+ nextAscii = src + qBitScanReverse(n) + 1;
+
+ // return the non-ASCII character
+ return src + qCountTrailingZeroBits(n);
+ }
+#endif
+
// do sixteen characters at a time
for ( ; end - src >= 16; src += 16) {
__m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i*>(src));
@@ -695,26 +756,16 @@ QByteArray QUtf16::convertFromUnicode(const QChar *uc, int len, QTextCodec::Conv
char *data = d.data();
if (!state || !(state->flags & QTextCodec::IgnoreHeader)) {
QChar bom(QChar::ByteOrderMark);
- if (endian == BigEndianness) {
- data[0] = bom.row();
- data[1] = bom.cell();
- } else {
- data[0] = bom.cell();
- data[1] = bom.row();
- }
+ if (endian == BigEndianness)
+ qToBigEndian(bom.unicode(), data);
+ else
+ qToLittleEndian(bom.unicode(), data);
data += 2;
}
- if (endian == BigEndianness) {
- for (int i = 0; i < len; ++i) {
- *(data++) = uc[i].row();
- *(data++) = uc[i].cell();
- }
- } else {
- for (int i = 0; i < len; ++i) {
- *(data++) = uc[i].cell();
- *(data++) = uc[i].row();
- }
- }
+ if (endian == BigEndianness)
+ qToBigEndian<ushort>(uc, len, data);
+ else
+ qToLittleEndian<ushort>(uc, len, data);
if (state) {
state->remainingChars = 0;
@@ -830,20 +881,14 @@ QByteArray QUtf32::convertFromUnicode(const QChar *uc, int len, QTextCodec::Conv
if (endian == BigEndianness) {
while (i.hasNext()) {
uint cp = i.next();
-
- *(data++) = cp >> 24;
- *(data++) = (cp >> 16) & 0xff;
- *(data++) = (cp >> 8) & 0xff;
- *(data++) = cp & 0xff;
+ qToBigEndian(cp, data);
+ data += 4;
}
} else {
while (i.hasNext()) {
uint cp = i.next();
-
- *(data++) = cp & 0xff;
- *(data++) = (cp >> 8) & 0xff;
- *(data++) = (cp >> 16) & 0xff;
- *(data++) = cp >> 24;
+ qToLittleEndian(cp, data);
+ data += 4;
}
}
diff --git a/src/corelib/codecs/qutfcodec_p.h b/src/corelib/codecs/qutfcodec_p.h
index 659a229dae..7405996fba 100644
--- a/src/corelib/codecs/qutfcodec_p.h
+++ b/src/corelib/codecs/qutfcodec_p.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
+** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
diff --git a/src/corelib/codecs/qwindowscodec_p.h b/src/corelib/codecs/qwindowscodec_p.h
index 2fd3c35378..1a74d618be 100644
--- a/src/corelib/codecs/qwindowscodec_p.h
+++ b/src/corelib/codecs/qwindowscodec_p.h
@@ -61,12 +61,12 @@ public:
QWindowsLocalCodec();
~QWindowsLocalCodec();
- QString convertToUnicode(const char *, int, ConverterState *) const;
- QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const;
+ QString convertToUnicode(const char *, int, ConverterState *) const override;
+ QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const override;
QString convertToUnicodeCharByChar(const char *chars, int length, ConverterState *state) const;
- QByteArray name() const;
- int mibEnum() const;
+ QByteArray name() const override;
+ int mibEnum() const override;
};
diff --git a/src/corelib/configure.json b/src/corelib/configure.json
index dfb575da0d..183eb3a13e 100644
--- a/src/corelib/configure.json
+++ b/src/corelib/configure.json
@@ -64,13 +64,6 @@
"UCollator *collator = ucol_open(\"ru_RU\", &status);",
"if (!U_FAILURE(status))",
" ucol_close(collator);"
- ],
- "qmake": [
- "CONFIG += build_all",
- "CONFIG(debug, debug|release): \\",
- " LIBS += $$LIBS_DEBUG",
- "else: \\",
- " LIBS += $$LIBS_RELEASE"
]
},
"sources": [
@@ -488,7 +481,7 @@
},
"eventfd": {
"label": "eventfd",
- "condition": "tests.eventfd",
+ "condition": "!config.wasm && tests.eventfd",
"output": [ "feature" ]
},
"futimens": {
@@ -599,7 +592,7 @@
"poll_ppoll": {
"label": "Native ppoll()",
"emitIf": "!config.win32",
- "condition": "tests.ppoll",
+ "condition": "!config.wasm && tests.ppoll",
"output": [ "privateFeature" ]
},
"poll_pollts": {
diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro
index 1e4823f566..181780c475 100644
--- a/src/corelib/corelib.pro
+++ b/src/corelib/corelib.pro
@@ -4,6 +4,7 @@ CONFIG += exceptions
MODULE = core # not corelib, as per project file
MODULE_CONFIG = moc resources
+qtConfig(gc_binaries): MODULE_CONFIG += gc_binaries
!isEmpty(QT_NAMESPACE): MODULE_DEFINES = QT_NAMESPACE=$$QT_NAMESPACE
TRACEPOINT_PROVIDER = $$PWD/qtcore.tracepoints
diff --git a/src/corelib/doc/snippets/code/src_corelib_animation_qparallelanimationgroup.cpp b/src/corelib/doc/snippets/code/src_corelib_animation_qparallelanimationgroup.cpp
new file mode 100644
index 0000000000..3fc53bc58b
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_animation_qparallelanimationgroup.cpp
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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$
+**
+****************************************************************************/
+
+//! [0]
+ QParallelAnimationGroup *group = new QParallelAnimationGroup;
+ group->addAnimation(anim1);
+ group->addAnimation(anim2);
+
+ group->start();
+//! [0]
diff --git a/src/corelib/doc/snippets/code/src_corelib_animation_qpropertyanimation.cpp b/src/corelib/doc/snippets/code/src_corelib_animation_qpropertyanimation.cpp
new file mode 100644
index 0000000000..a6dbd909d7
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_animation_qpropertyanimation.cpp
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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$
+**
+****************************************************************************/
+
+
+//! [0]
+ QPropertyAnimation *animation = new QPropertyAnimation(myWidget, "geometry");
+ animation->setDuration(10000);
+ animation->setStartValue(QRect(0, 0, 100, 30));
+ animation->setEndValue(QRect(250, 250, 100, 30));
+
+ animation->start();
+//! [0]
diff --git a/src/corelib/doc/snippets/code/src_corelib_animation_qsequentialanimationgroup.cpp b/src/corelib/doc/snippets/code/src_corelib_animation_qsequentialanimationgroup.cpp
new file mode 100644
index 0000000000..1f1363f127
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_animation_qsequentialanimationgroup.cpp
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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$
+**
+****************************************************************************/
+
+//! [0]
+ QSequentialAnimationGroup *group = new QSequentialAnimationGroup;
+
+ group->addAnimation(anim1);
+ group->addAnimation(anim2);
+
+ group->start();
+//! [0]
diff --git a/src/corelib/doc/snippets/code/src_corelib_animation_qvariantanimation.cpp b/src/corelib/doc/snippets/code/src_corelib_animation_qvariantanimation.cpp
new file mode 100644
index 0000000000..b462ff2d6a
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_animation_qvariantanimation.cpp
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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$
+**
+****************************************************************************/
+
+//! [0]
+ QVariant myColorInterpolator(const QColor &start, const QColor &end, qreal progress)
+ {
+ ...
+ return QColor(...);
+ }
+ ...
+ qRegisterAnimationInterpolator<QColor>(myColorInterpolator);
+//! [0]
+
+//! [1]
+ QVariant myInterpolator(const QVariant &from, const QVariant &to, qreal progress);
+//! [1]
diff --git a/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp b/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp
index 2d7b9a9ac8..c73e782b76 100644
--- a/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_global_qglobal.cpp
@@ -440,6 +440,54 @@ QString global_greeting(int type)
//! [36]
+//! [qttrnnoop]
+static const char * const StatusClass::status_strings[] = {
+ QT_TR_N_NOOP("There are %n new message(s)"),
+ QT_TR_N_NOOP("There are %n total message(s)")
+};
+
+QString StatusClass::status(int type, int count)
+{
+ return tr(status_strings[type], nullptr, count);
+}
+//! [qttrnnoop]
+
+//! [qttranslatennoop]
+static const char * const greeting_strings[] = {
+ QT_TRANSLATE_N_NOOP("Welcome Msg", "Hello, you have %n message(s)"),
+ QT_TRANSLATE_N_NOOP("Welcome Msg", "Hi, you have %n message(s)")
+};
+
+QString global_greeting(int type, int msgcnt)
+{
+ return translate("Welcome Msg", greeting_strings[type], nullptr, msgcnt);
+}
+//! [qttranslatennoop]
+
+//! [qttranslatennoop3]
+static { const char * const source; const char * const comment; } status_strings[] = {
+ QT_TRANSLATE_N_NOOP3("Message Status", "Hello, you have %n message(s)",
+ "A login message status"),
+ QT_TRANSLATE_N_NOOP3("Message status", "You have %n new message(s)",
+ "A new message query status")
+};
+
+QString FriendlyConversation::greeting(int type, int count)
+{
+ return tr(status_strings[type].source,
+ status_strings[type].comment, count);
+}
+
+QString global_greeting(int type, int count)
+{
+ return qApp->translate("Message Status",
+ status_strings[type].source,
+ status_strings[type].comment,
+ count);
+}
+//! [qttranslatennoop3]
+
+
//! [qttrid]
//% "%n fooish bar(s) found.\n"
//% "Do you want to continue?"
@@ -677,3 +725,64 @@ bool readConfiguration(const QFile &file)
#include <QtGui>
#endif
//! [qt-version-check]
+
+//! [is-empty]
+ qgetenv(varName).isEmpty()
+//! [is-empty]
+
+//! [to-int]
+ qgetenv(varName).toInt(ok, 0)
+//! [to-int]
+
+//! [is-null]
+ !qgetenv(varName).isNull()
+//! [is-null]
+
+//! [as-const-0]
+ QString s = ...;
+ for (QChar ch : s) // detaches 's' (performs a deep-copy if 's' was shared)
+ process(ch);
+ for (QChar ch : qAsConst(s)) // ok, no detach attempt
+ process(ch);
+//! [as-const-0]
+
+//! [as-const-1]
+ const QString s = ...;
+ for (QChar ch : s) // ok, no detach attempt on const objects
+ process(ch);
+//! [as-const-1]
+
+//! [as-const-2]
+ for (QChar ch : funcReturningQString())
+ process(ch); // OK, the returned object is kept alive for the loop's duration
+//! [as-const-2]
+
+//! [as-const-3]
+ for (QChar ch : qAsConst(funcReturningQString()))
+ process(ch); // ERROR: ch is copied from deleted memory
+//! [as-const-3]
+
+//! [as-const-4]
+ for (QChar ch : qAsConst(funcReturningQString()))
+ process(ch); // ERROR: ch is copied from deleted memory
+//! [as-const-4]
+
+//! [qterminate]
+ try { expr; } catch(...) { qTerminate(); }
+//! [qterminate]
+
+//! [qdecloverride]
+ // generate error if this doesn't actually override anything:
+ virtual void MyWidget::paintEvent(QPaintEvent*) Q_DECL_OVERRIDE;
+//! [qdecloverride]
+
+//! [qdeclfinal-1]
+ // more-derived classes no longer permitted to override this:
+ virtual void MyWidget::paintEvent(QPaintEvent*) Q_DECL_FINAL;
+//! [qdeclfinal-1]
+
+//! [qdeclfinal-2]
+ class QRect Q_DECL_FINAL { // cannot be derived from
+ // ...
+ };
+//! [qdeclfinal-2]
diff --git a/src/corelib/doc/snippets/code/src_corelib_global_qlogging.cpp b/src/corelib/doc/snippets/code/src_corelib_global_qlogging.cpp
new file mode 100644
index 0000000000..7b0b357cff
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_global_qlogging.cpp
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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$
+**
+****************************************************************************/
+
+//! [0]
+ QT_MESSAGE_PATTERN="[%{time yyyyMMdd h:mm:ss.zzz t} %{if-debug}D%{endif}%{if-info}I%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}] %{file}:%{line} - %{message}"
+//! [0]
diff --git a/src/corelib/doc/snippets/code/src_corelib_global_qnumeric.cpp b/src/corelib/doc/snippets/code/src_corelib_global_qnumeric.cpp
new file mode 100644
index 0000000000..5d64070b1b
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_global_qnumeric.cpp
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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$
+**
+****************************************************************************/
+
+//! [0]
+ if (qFloatDistance(a, b) < (1 << 7)) { // The last 7 bits are not
+ // significant
+ // precise enough
+ }
+//! [0]
diff --git a/src/corelib/doc/snippets/code/src_corelib_global_qoperatingsystemversion.cpp b/src/corelib/doc/snippets/code/src_corelib_global_qoperatingsystemversion.cpp
new file mode 100644
index 0000000000..d9e927c55a
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_global_qoperatingsystemversion.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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$
+**
+****************************************************************************/
+
+//! [0]
+ QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 9)
+//! [0]
+
+//! [1]
+ auto current = QOperatingSystemVersion::current();
+ if (current >= QOperatingSystemVersion::OSXYosemite ||
+ current >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) {
+ // returns true on macOS >= 10.10 and iOS >= 8.0, but false on macOS < 10.10 and iOS < 8.0
+ }
+//! [1]
diff --git a/src/corelib/doc/snippets/code/src_corelib_global_qrandom.cpp b/src/corelib/doc/snippets/code/src_corelib_global_qrandom.cpp
new file mode 100644
index 0000000000..b03e656b64
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_global_qrandom.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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$
+**
+****************************************************************************/
+
+//! [0]
+ quint32 value = QRandomGenerator::global()->generate();
+//! [0]
+
+//! [1]
+ QRandomGenerator prng1(1234), prng2(1234);
+ Q_ASSERT(prng1.generate() == prng2.generate());
+ Q_ASSERT(prng1.generate64() == prng2.generate64());
+//! [1]
+
+//! [2]
+ int x = QRandomGenerator::global()->generate();
+ int y = QRandomGenerator::global()->generate();
+ int w = QRandomGenerator::global()->bounded(16384);
+ int h = QRandomGenerator::global()->bounded(16384);
+//! [2]
+
+//! [3]
+ std::uniform_real_distribution dist(1, 2.5);
+ return dist(*QRandomGenerator::global());
+//! [3]
+
+//! [4]
+ std::seed_seq sseq(seedBuffer, seedBuffer + len);
+ QRandomGenerator generator(sseq);
+//! [4]
+
+//! [5]
+ std::seed_seq sseq(begin, end);
+ QRandomGenerator generator(sseq);
+//! [5]
+
+//! [6]
+ while (z--)
+ generator.generate();
+//! [6]
+
+//! [7]
+ std::generate(begin, end, [this]() { return generate(); });
+//! [7]
+
+//! [8]
+ std::generate(begin, end, []() { return QRandomGenerator::global()->generate64(); });
+//! [8]
+
+//! [9]
+ QVector<quint32> vector;
+ vector.resize(16);
+ QRandomGenerator::fillRange(vector.data(), vector.size());
+//! [9]
+
+//! [10]
+ quint32 array[2];
+ QRandomGenerator::fillRange(array);
+//! [10]
+
+//! [11]
+ QRandomGenerator64 rd;
+ return std::generate_canonical<qreal, std::numeric_limits<qreal>::digits>(rd);
+//! [11]
+
+//! [12]
+ return generateDouble() * highest;
+//! [12]
+
+//! [13]
+ quint32 v = QRandomGenerator::bounded(256);
+//! [13]
+
+//! [14]
+ quint32 v = QRandomGenerator::bounded(1000, 2000);
+//! [14]
+
+//! [15]
+ return QColor::fromRgb(QRandomGenerator::global()->generate());
+//! [15]
+
+//! [16]
+ qint64 value = QRandomGenerator64::generate() & std::numeric_limits<qint64>::max();
+//! [16]
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qdebug.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qdebug.cpp
new file mode 100644
index 0000000000..4bbdc509ca
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qdebug.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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$
+**
+****************************************************************************/
+
+//! [0]
+ QString s;
+
+ s = "a";
+ qDebug().noquote() << s; // prints: a
+ qDebug() << s; // prints: "a"
+
+ s = "\"a\r\n\"";
+ qDebug() << s; // prints: "\"a\r\n\""
+
+ s = "\033"; // escape character
+ qDebug() << s; // prints: "\u001B"
+
+ s = "\u00AD"; // SOFT HYPHEN
+ qDebug() << s; // prints: "\u00AD"
+
+ s = "\u00E1"; // LATIN SMALL LETTER A WITH ACUTE
+ qDebug() << s; // prints: "á"
+
+ s = "a\u0301"; // "a" followed by COMBINING ACUTE ACCENT
+ qDebug() << s; // prints: "aÌ";
+
+ s = "\u0430\u0301"; // CYRILLIC SMALL LETTER A followed by COMBINING ACUTE ACCENT
+ qDebug() << s; // prints: "аÌ"
+//! [0]
+
+//! [1]
+ QByteArray ba;
+
+ ba = "a";
+ qDebug().noquote() << ba; // prints: a
+ qDebug() << ba; // prints: "a"
+
+ ba = "\"a\r\n\"";
+ qDebug() << ba; // prints: "\"a\r\n\""
+
+ ba = "\033"; // escape character
+ qDebug() << ba; // prints: "\x1B"
+
+ ba = "\xC3\xA1";
+ qDebug() << ba; // prints: "\xC3\xA1"
+
+ ba = QByteArray("a\0b", 3);
+ qDebug() << ba // prints: "\a\x00""b"
+//! [1]
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qfileselector.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qfileselector.cpp
new file mode 100644
index 0000000000..91c94eb762
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qfileselector.cpp
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWidgets module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+ QString defaultsBasePath = "data/";
+ QString defaultsPath = defaultsBasePath + "defaults.conf";
+ QString localizedPath = defaultsBasePath
+ + QString("%1/defaults.conf").arg(QLocale().name());
+ if (QFile::exists(localizedPath))
+ defaultsPath = localizedPath;
+ QFile defaults(defaultsPath);
+//! [0]
+
+//! [1]
+ QString defaultsPath = "data/defaults.conf";
+#if defined(Q_OS_ANDROID)
+ defaultsPath = "data/android/defaults.conf";
+#elif defined(Q_OS_IOS)
+ defaultsPath = "data/ios/defaults.conf";
+#endif
+ QFile defaults(defaultsPath);
+//! [1]
+
+//! [2]
+ QFileSelector selector;
+ QFile defaultsFile(selector.select("data/defaults.conf"));
+//! [2]
+
+//! [3]
+ data/defaults.conf
+ data/+android/defaults.conf
+ data/+ios/+en_GB/defaults.conf
+//! [3]
+
+//! [4]
+ images/background.png
+ images/+android/+en_GB/background.png
+//! [4]
+
+//! [5]
+ images/background.png
+ images/+linux/background.png
+ images/+windows/background.png
+ images/+admin/background.png
+ images/+admin/+linux/background.png
+//! [5]
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qloggingcategory.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qloggingcategory.cpp
new file mode 100644
index 0000000000..20ae52a251
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qloggingcategory.cpp
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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$
+**
+****************************************************************************/
+
+//! [0]
+ <category>[.<type>] = true|false
+//! [0]
+
+//! [1]
+ QLoggingCategory::setFilterRules("*.debug=false\n"
+ "driver.usb.debug=true");
+//! [1]
+
+//! [2]
+ [Rules]
+ *.debug=false
+ driver.usb.debug=true
+//! [2]
+
+//! [3]
+ QT_LOGGING_RULES="*.debug=false;driver.usb.debug=true"
+//! [3]
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qtemporaryfile.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qtemporaryfile.cpp
index 127c7bd0d9..4e864b3dcd 100644
--- a/src/corelib/doc/snippets/code/src_corelib_io_qtemporaryfile.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qtemporaryfile.cpp
@@ -61,3 +61,11 @@
// as it goes out of scope.
//! [0]
}
+
+//! [1]
+ QFile f(":/resources/file.txt");
+ QTemporaryFile::createNativeFile(f); // Returns a pointer to a temporary file
+
+ QFile f("/users/qt/file.txt");
+ QTemporaryFile::createNativeFile(f); // Returns 0
+//! [1]
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qurl.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qurl.cpp
index b2a2282085..79af776ce4 100644
--- a/src/corelib/doc/snippets/code/src_corelib_io_qurl.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qurl.cpp
@@ -101,3 +101,89 @@ QUrl url("http://qt-project.org/support/file.html");
// url.adjusted(RemoveFilename) == "http://qt-project.org/support/"
// url.fileName() == "file.html"
//! [7]
+
+//! [8]
+ qDebug() << QUrl("main.qml").isRelative(); // true: no scheme
+ qDebug() << QUrl("qml/main.qml").isRelative(); // true: no scheme
+ qDebug() << QUrl("file:main.qml").isRelative(); // false: has "file" scheme
+ qDebug() << QUrl("file:qml/main.qml").isRelative(); // false: has "file" scheme
+//! [8]
+
+//! [9]
+ // Absolute URL, relative path
+ QUrl url("file:file.txt");
+ qDebug() << url.isRelative(); // false: has "file" scheme
+ qDebug() << QDir::isAbsolutePath(url.path()); // false: relative path
+
+ // Relative URL, absolute path
+ url = QUrl("/home/user/file.txt");
+ qDebug() << url.isRelative(); // true: has no scheme
+ qDebug() << QDir::isAbsolutePath(url.path()); // true: absolute path
+//! [9]
+
+//! [10]
+ QUrl original("http://example.com/?q=a%2B%3Db%26c");
+ QUrl copy(original);
+ copy.setQuery(copy.query(QUrl::FullyDecoded), QUrl::DecodedMode);
+
+ qDebug() << original.toString(); // prints: http://example.com/?q=a%2B%3Db%26c
+ qDebug() << copy.toString(); // prints: http://example.com/?q=a+=b&c
+//! [10]
+
+//! [11]
+ QUrl url;
+ url.setScheme("ftp");
+//! [11]
+
+//! [12]
+ qDebug() << QUrl("file:file.txt").path(); // "file.txt"
+ qDebug() << QUrl("/home/user/file.txt").path(); // "/home/user/file.txt"
+ qDebug() << QUrl("http://www.example.com/test/123").path(); // "/test/123"
+//! [12]
+
+//! [13]
+ qDebug() << QUrl("/foo%FFbar").path();
+//! [13]
+
+//! [14]
+ qDebug() << QUrl("/foo+bar%2B").path(); // "/foo+bar+"
+//! [14]
+
+//! [15]
+ const QUrl url("/tmp/Mambo %235%3F.mp3");
+ qDebug() << url.path(QUrl::FullyDecoded); // "/tmp/Mambo #5?.mp3"
+ qDebug() << url.path(QUrl::PrettyDecoded); // "/tmp/Mambo #5?.mp3"
+ qDebug() << url.path(QUrl::FullyEncoded); // "/tmp/Mambo%20%235%3F.mp3"
+//! [15]
+
+//! [16]
+ qDebug() << QUrl::fromLocalFile("file.txt"); // QUrl("file:file.txt")
+ qDebug() << QUrl::fromLocalFile("/home/user/file.txt"); // QUrl("file:///home/user/file.txt")
+ qDebug() << QUrl::fromLocalFile("file:file.txt"); // doesn't make sense; expects path, not url with scheme
+//! [16]
+
+//! [17]
+ QUrl url = QUrl::fromLocalFile("file.txt");
+ QUrl baseUrl = QUrl("file:/home/user/");
+ // wrong: prints QUrl("file:file.txt"), as url already has a scheme
+ qDebug() << baseUrl.resolved(url);
+//! [17]
+
+//! [18]
+ // correct: prints QUrl("file:///home/user/file.txt")
+ url.setScheme(QString());
+ qDebug() << baseUrl.resolved(url);
+//! [18]
+
+//! [19]
+ QUrl url = QUrl("file.txt");
+ QUrl baseUrl = QUrl("file:/home/user/");
+ // prints QUrl("file:///home/user/file.txt")
+ qDebug() << baseUrl.resolved(url);
+//! [19]
+
+//! [20]
+ qDebug() << QUrl("file:file.txt").toLocalFile(); // "file:file.txt"
+ qDebug() << QUrl("file:/home/user/file.txt").toLocalFile(); // "file:///home/user/file.txt"
+ qDebug() << QUrl("file.txt").toLocalFile(); // ""; wasn't a local file as it had no scheme
+//! [20]
diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qurlquery.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qurlquery.cpp
new file mode 100644
index 0000000000..da87bfd143
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_io_qurlquery.cpp
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWidgets module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+ / "*" / "+" / "," / ";" / "="
+//! [0]
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qdeadlinetimer.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qdeadlinetimer.cpp
new file mode 100644
index 0000000000..eb291d7b18
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qdeadlinetimer.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWidgets module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+ void executeOperation(int msecs)
+ {
+ QDeadlineTimer deadline(msecs);
+ do {
+ if (readFromDevice(deadline.remainingTime())
+ break;
+ waitForReadyRead(deadline);
+ } while (!deadline.hasExpired());
+ }
+//! [0]
+
+//! [1]
+ using namespace std::chrono;
+ using namespace std::chrono_literals;
+
+ QDeadlineTimer deadline(30s);
+ device->waitForReadyRead(deadline);
+ if (deadline.remainingTime<nanoseconds>() > 300ms)
+ cleanup();
+//! [1]
+
+//! [2]
+ using namespace std::chrono;
+ using namespace std::chrono_literals;
+ auto now = steady_clock::now();
+ QDeadlineTimer deadline(now + 1s);
+ Q_ASSERT(deadline == now + 1s);
+//! [2]
+
+//! [3]
+ using namespace std::chrono_literals;
+ QDeadlineTimer deadline(250ms);
+//! [3]
+
+//! [4]
+ using namespace std::chrono_literals;
+ deadline.setRemainingTime(250ms);
+//! [4]
+
+//! [5]
+ mutex.tryLock(deadline.remainingTime());
+//! [5]
+
+//! [6]
+ qint64 realTimeLeft = deadline.deadline();
+ if (realTimeLeft != (std::numeric_limits<qint64>::max)()) {
+ realTimeLeft -= QDeadlineTimer::current().deadline();
+ // or:
+ //QElapsedTimer timer;
+ //timer.start();
+ //realTimeLeft -= timer.msecsSinceReference();
+ }
+//! [6]
+
+//! [7]
+ qint64 realTimeLeft = deadline.deadlineNSecs();
+ if (realTimeLeft != std::numeric_limits<qint64>::max())
+ realTimeLeft -= QDeadlineTimer::current().deadlineNSecs();
+//! [7]
+
+//! [8]
+ return d1.deadlineNSecs() == d2.deadlineNSecs();
+//! [8]
+
+//! [9]
+ return d1.deadlineNSecs() != d2.deadlineNSecs();
+//! [9]
+
+//! [10]
+ return d1.deadlineNSecs() < d2.deadlineNSecs();
+//! [10]
+
+//! [11]
+ return d1.deadlineNSecs() <= d2.deadlineNSecs();
+//! [11]
+
+//! [12]
+ return d1.deadlineNSecs() > d2.deadlineNSecs();
+//! [12]
+
+//! [13]
+ return d1.deadlineNSecs() >= d2.deadlineNSecs();
+//! [13]
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qmetaobject.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qmetaobject.cpp
index eda52cfacd..56d1fa5a63 100644
--- a/src/corelib/doc/snippets/code/src_corelib_kernel_qmetaobject.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qmetaobject.cpp
@@ -147,4 +147,23 @@ method.invoke(obj,
QMetaMethod destroyedSignal = QMetaMethod::fromSignal(&QObject::destroyed);
//! [9]
+//! [10]
+ // In the class MainWindow declaration
+ #ifndef Q_MOC_RUN
+ // define the tag text as empty, so the compiler doesn't see it
+ # define MY_CUSTOM_TAG
+ #endif
+ ...
+ private slots:
+ MY_CUSTOM_TAG void testFunc();
+//! [10]
+
+//! [11]
+ MainWindow win;
+ win.show();
+
+ int functionIndex = win.metaObject()->indexOfSlot("testFunc()");
+ QMetaMethod mm = win.metaObject()->method(functionIndex);
+ qDebug() << mm.tag(); // prints MY_CUSTOM_TAG
+//! [11]
}
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp
index 6451f46b36..1e31a5292f 100644
--- a/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp
@@ -538,3 +538,16 @@ QString text = MyMagicClass::tr("Sim sala bim.");
//! [explicit tr context]
QString text = QScrollBar::tr("Page up");
//! [explicit tr context]
+
+//! [53]
+{
+const QSignalBlocker blocker(someQObject);
+// no signals here
+}
+//! [53]
+
+//! [54]
+const bool wasBlocked = someQObject->blockSignals(true);
+// no signals here
+someQObject->blockSignals(wasBlocked);
+//! [54]
diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qtestsupport_core.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qtestsupport_core.cpp
new file mode 100644
index 0000000000..ed3e9bd0c0
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qtestsupport_core.cpp
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+ MyObject obj;
+ obj.startup();
+ QTest::qWaitFor([&]() {
+ return obj.isReady();
+ }, 3000);
+//! [0]
+
+//! [1]
+ int i = 0;
+ while (myNetworkServerNotResponding() && i++ < 50)
+ QTest::qWait(250);
+//! [1]
diff --git a/src/corelib/doc/snippets/code/src_corelib_mimetype_qmimedatabase.cpp b/src/corelib/doc/snippets/code/src_corelib_mimetype_qmimedatabase.cpp
index c5874d83b8..3092e32f6f 100644
--- a/src/corelib/doc/snippets/code/src_corelib_mimetype_qmimedatabase.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_mimetype_qmimedatabase.cpp
@@ -55,3 +55,18 @@ if (mime.inherits("text/plain")) {
// The file is plain text, we can display it in a QTextEdit
}
//! [0]
+
+//! [1]
+QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/packages"),
+ QStandardPaths::LocateDirectory);
+//! [1]
+
+//! [2]
+<?xml version="1.0" encoding="UTF-8"?>
+<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
+ <mime-type type="application/vnd.qt.qmakeprofile">
+ <comment xml:lang="en">Qt qmake Profile</comment>
+ <glob pattern="*.pro" weight="50"/>
+ </mime-type>
+</mime-info>
+//! [2]
diff --git a/src/corelib/doc/snippets/code/src_corelib_serialization_qcborstream.cpp b/src/corelib/doc/snippets/code/src_corelib_serialization_qcborstream.cpp
new file mode 100644
index 0000000000..dbe38aa4b5
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_serialization_qcborstream.cpp
@@ -0,0 +1,347 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWidgets module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+ QCborValue(QCborTag(2), QByteArray("\x01\0\0\0\0\0\0\0\0", 9));
+//! [0]
+
+//! [1]
+ writer.startMap(4); // 4 elements in the map
+
+ writer.append(QLatin1String("label"));
+ writer.append(QLatin1String("journald"));
+
+ writer.append(QLatin1String("autoDetect"));
+ writer.append(false);
+
+ writer.append(QLatin1String("condition"));
+ writer.append(QLatin1String("libs.journald"));
+
+ writer.append(QLatin1String("output"));
+ writer.startArray(1);
+ writer.append(QLatin1String("privateFeature"));
+ writer.endArray();
+
+ writer.endMap();
+//! [1]
+
+//! [2]
+ QFile f("output", QIODevice::WriteOnly);
+ QCborStreamWriter writer(&f);
+ writer.startMap(0);
+ writer.endMap();
+//! [2]
+
+//! [3]
+ QByteArray encodedNumber(qint64 value)
+ {
+ QByteArray ba;
+ QCborStreamWriter writer(&ba);
+ writer.append(value);
+ return ba;
+ }
+//! [3]
+
+//! [4]
+ writer.append(0U);
+ writer.append(Q_UINT64_C(4294967296));
+ writer.append(std::numeric_limits<quint64>::max());
+//! [4]
+
+//! [5]
+ writer.append(0);
+ writer.append(-1);
+ writer.append(Q_INT64_C(4294967296));
+ writer.append(std::numeric_limits<qint64>::max());
+//! [5]
+
+//! [6]
+ writer.append(QCborNegativeInteger(1));
+ writer.append(QCborNegativeInteger(Q_INT64_C(4294967296)));
+ writer.append(QCborNegativeInteger(-quint64(std::numeric_limits<qint64>::min())));
+//! [6]
+
+//! [7]
+ void writeFile(QCborStreamWriter &writer, const QString &fileName)
+ {
+ QFile f(fileName);
+ if (f.open(QIODevice::ReadOnly))
+ writer.append(f.readAll());
+ }
+//! [7]
+
+//! [8]
+ writer.append(QLatin1String("Hello, World"));
+//! [8]
+
+//! [9]
+ void writeString(QCborStreamWriter &writer, const QString &str)
+ {
+ writer.append(str);
+ }
+//! [9]
+
+//! [10]
+ void writeRxPattern(QCborStreamWriter &writer, const QRegularExpression &rx)
+ {
+ writer.append(QCborTag(36));
+ writer.append(rx.pattern());
+ }
+//! [10]
+
+//! [11]
+ void writeCurrentTime(QCborStreamWriter &writer)
+ {
+ writer.append(QCborKnownTags::UnixTime_t);
+ writer.append(time(nullptr));
+ }
+//! [11]
+
+//! [12]
+ writer.append(QCborSimpleType::Null);
+ writer.append(QCborSimpleType(32));
+//! [12]
+
+//! [13]
+ void writeFloat(QCborStreamWriter &writer, float f)
+ {
+ qfloat16 f16 = f;
+ if (qIsNaN(f) || f16 == f)
+ writer.append(f16);
+ else
+ writer.append(f);
+ }
+//! [13]
+
+//! [14]
+ void writeFloat(QCborStreamWriter &writer, double d)
+ {
+ float f = d;
+ if (qIsNaN(d) || d == f)
+ writer.append(f);
+ else
+ writer.append(d);
+ }
+//! [14]
+
+//! [15]
+ void writeDouble(QCborStreamWriter &writer, double d)
+ {
+ float f;
+ if (qIsNaN(d)) {
+ writer.append(qfloat16(qQNaN()));
+ } else if (qIsInf(d)) {
+ writer.append(d < 0 ? -qInf() : qInf());
+ } else if ((f = d) == d) {
+ qfloat16 f16 = f;
+ if (f16 == f)
+ writer.append(f16);
+ else
+ writer.append(f);
+ } else {
+ writer.append(d);
+ }
+ }
+//! [15]
+
+//! [16]
+ writer.append(b ? QCborSimpleType::True : QCborSimpleType::False);
+//! [16]
+
+//! [17]
+ writer.append(QCborSimpleType::Null);
+//! [17]
+
+//! [18]
+ writer.append(QCborSimpleType::Null);
+//! [18]
+
+//! [19]
+ writer.append(QCborSimpleType::Undefined);
+//! [19]
+
+//! [20]
+ void appendList(QCborStreamWriter &writer, const QLinkedList<QString> &list)
+ {
+ writer.startArray();
+ for (const QString &s : list)
+ writer.append(s);
+ writer.endArray();
+ }
+//! [20]
+
+//! [21]
+ void appendList(QCborStreamWriter &writer, const QStringList &list)
+ {
+ writer.startArray(list.size());
+ for (const QString &s : list)
+ writer.append(s);
+ writer.endArray();
+ }
+//! [21]
+
+//! [22]
+ void appendMap(QCborStreamWriter &writer, const QLinkedList<QPair<int, QString>> &list)
+ {
+ writer.startMap();
+ for (const auto pair : list) {
+ writer.append(pair.first)
+ writer.append(pair.second);
+ }
+ writer.endMap();
+ }
+//! [22]
+
+//! [23]
+ void appendMap(QCborStreamWriter &writer, const QMap<int, QString> &map)
+ {
+ writer.startMap(map.size());
+ for (auto it = map.begin(); it != map.end(); ++it) {
+ writer.append(it.key());
+ writer.append(it.value());
+ }
+ writer.endMap();
+ }
+//! [23]
+
+//! [24]
+ void handleStream(QCborStreamReader &reader)
+ {
+ switch (reader.type())
+ case QCborStreamReader::UnsignedInteger:
+ case QCborStreamReader::NegativeInteger:
+ case QCborStreamReader::SimpleType:
+ case QCborStreamReader::Float16:
+ case QCborStreamReader::Float:
+ case QCborStreamReader::Double:
+ handleFixedWidth(reader);
+ reader.next();
+ break;
+ case QCborStreamReader::ByteArray:
+ case QCborStreamReader::String:
+ handleString(reader);
+ break;
+ case QCborStreamReader::Array:
+ case QCborStreamReader::Map:
+ reader.enterContainer();
+ while (reader.lastError() == QCborError::NoError)
+ handleStream(reader);
+ if (reader.lastError() == QCborError::NoError)
+ reader.leaveContainer();
+ }
+ }
+//! [24]
+
+//! [25]
+ QVariantList populateFromCbor(QCborStreamReader &reader)
+ {
+ QVariantList list;
+ if (reader.isLengthKnown())
+ list.reserve(reader.length());
+
+ reader.enterContainer();
+ while (reader.lastError() == QCborError::NoError && reader.hasNext())
+ list.append(readOneElement(reader));
+ if (reader.lastError() == QCborError::NoError)
+ reader.leaveContainer();
+ }
+//! [25]
+
+//! [26]
+ QVariantMap populateFromCbor(QCborStreamReader &reader)
+ {
+ QVariantMap map;
+ if (reader.isLengthKnown())
+ map.reserve(reader.length());
+
+ reader.enterContainer();
+ while (reader.lastError() == QCborError::NoError && reader.hasNext()) {
+ QString key = readElementAsString(reader);
+ map.insert(key, readOneElement(reader));
+ }
+ if (reader.lastError() == QCborError::NoError)
+ reader.leaveContainer();
+ }
+//! [26]
+
+//! [27]
+ QString decodeString(QCborStreamReader &reader)
+ {
+ QString result;
+ auto r = reader.readString();
+ while (r.code == QCborStreamReader::Ok) {
+ result += r.data;
+ r = reader.readString();
+ }
+
+ if (r.code == QCborStreamReader::Error) {
+ // handle error condition
+ result.clear();
+ }
+ return result;
+ }
+//! [27]
+
+//! [28]
+ QBytearray decodeBytearray(QCborStreamReader &reader)
+ {
+ QBytearray result;
+ auto r = reader.readBytearray();
+ while (r.code == QCborStreamReader::Ok) {
+ result += r.data;
+ r = reader.readByteArray();
+ }
+
+ if (r.code == QCborStreamReader::Error) {
+ // handle error condition
+ result.clear();
+ }
+ return result;
+ }
+//! [28]
+
+//! [29]
+ QCborStreamReader<qsizetype> result;
+ do {
+ qsizetype size = reader.currentStringChunkSize();
+ qsizetype oldsize = buffer.size();
+ buffer.resize(oldsize + size);
+ result = reader.readStringChunk(buffer.data() + oldsize, size);
+ } while (result.status() == QCborStreamReader::Ok);
+//! [29]
diff --git a/src/corelib/doc/snippets/code/src_corelib_serialization_qcborvalue.cpp b/src/corelib/doc/snippets/code/src_corelib_serialization_qcborvalue.cpp
new file mode 100644
index 0000000000..63f813cf69
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_serialization_qcborvalue.cpp
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWidgets module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+ QCborValue(uuid) == QCborValue(QCborKnownTags::Uuid, uuid.toRfc4122());
+//! [0]
+
+//! [1]
+ QCborValue value(QCborSimpleType(12));
+//! [1]
+
+//! [2]
+ value.isSimpleType(QCborSimpleType(12));
+//! [2]
+
+//! [3]
+ QCborValue(QUrl("https://example.com")) == QCborValue(QCborKnownTags::Url, "https://example.com");
+//! [3]
+
+//! [4]
+ value.toMap().value(key);
+//! [4]
+
+//! [5]
+ value.toMap().value(key);
+//! [5]
+
+//! [6]
+ if (reader.isTag() && reader.toTag() == QCborKnownTags::Signature)
+ reader.next();
+
+ QCborValue contents = QCborValue::fromCbor(reader);
+//! [6]
diff --git a/src/corelib/doc/snippets/code/src_corelib_serialization_qdatastream.cpp b/src/corelib/doc/snippets/code/src_corelib_serialization_qdatastream.cpp
new file mode 100644
index 0000000000..5caaa16727
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_serialization_qdatastream.cpp
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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$
+**
+****************************************************************************/
+
+//! [0]
+ QDataStream &operator<<(QDataStream &, const QXxx &);
+ QDataStream &operator>>(QDataStream &, QXxx &);
+//! [0]
+
+//! [1]
+ QDataStream & operator<< (QDataStream& stream, const QImage& image);
+ QDataStream & operator>> (QDataStream& stream, QImage& image);
+//! [1]
diff --git a/src/corelib/doc/snippets/code/src_corelib_serialization_qjsondocument.cpp b/src/corelib/doc/snippets/code/src_corelib_serialization_qjsondocument.cpp
new file mode 100644
index 0000000000..c4913b1740
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_serialization_qjsondocument.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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$
+**
+****************************************************************************/
+
+//! [0]
+ {
+ "Array": [
+ true,
+ 999,
+ "string"
+ ],
+ "Key": "Value",
+ "null": null
+ }
+//! [0]
+
+//! [1]
+ {"Array":[true,999,"string"],"Key":"Value","null":null}
+//! [1]
diff --git a/src/corelib/doc/snippets/code/src_corelib_thread_qsemaphore.cpp b/src/corelib/doc/snippets/code/src_corelib_thread_qsemaphore.cpp
index 2081e4fdd0..52105bce0b 100644
--- a/src/corelib/doc/snippets/code/src_corelib_thread_qsemaphore.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_thread_qsemaphore.cpp
@@ -81,3 +81,32 @@ QSemaphore sem(5); // sem.available() == 5
sem.tryAcquire(250, 1000); // sem.available() == 5, waits 1000 milliseconds and returns false
sem.tryAcquire(3, 30000); // sem.available() == 2, returns true without waiting
//! [3]
+
+//! [4]
+// ... do something that may throw or return early
+sem.release();
+//! [4]
+
+//! [5]
+const QSemaphoreReleaser releaser(sem);
+// ... do something that may throw or early return
+// implicitly calls sem.release() here and at every other return in between
+//! [5]
+
+//! [6]
+{ // some scope
+ QSemaphoreReleaser releaser; // does nothing
+ // ...
+ if (someCondition) {
+ releaser = QSemaphoreReleaser(sem);
+ // ...
+ }
+ // ...
+} // conditionally calls sem.release(), depending on someCondition
+//! [6]
+
+//! [7]
+releaser.cancel(); // avoid releasing old semaphore()
+releaser = QSemaphoreReleaser(sem, 42);
+// now will call sem.release(42) when 'releaser' is destroyed
+//! [7]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp
index d163129d54..32fccbefbf 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp
@@ -353,9 +353,21 @@ long dec = str.toLong(&ok, 10); // dec == 0, ok == false
//! [38]
QByteArray string("1234.56");
-double a = string.toDouble(); // a == 1234.56
+bool ok;
+double a = string.toDouble(&ok); // a == 1234.56, ok == true
+
+string = "1234.56 Volt";
+a = str.toDouble(&ok); // a == 0, ok == false
//! [38]
+//! [38float]
+QByteArray string("1234.56");
+bool ok;
+float a = string.toFloat(&ok); // a == 1234.56, ok == true
+
+string = "1234.56 Volt";
+a = str.toFloat(&ok); // a == 0, ok == false
+//! [38float]
//! [39]
QByteArray text("Qt is great!");
@@ -458,6 +470,33 @@ ba4.size(); // Returns 6.
ba4.constData(); // Returns "ca\0r\0t" without terminating \0.
//! [48]
+//! [49]
+QByteArray ba("ab");
+ba.repeated(4); // returns "abababab"
+//! [49]
+
+//! [50]
+QByteArray macAddress = QByteArray::fromHex("123456abcdef");
+macAddress.toHex(':'); // returns "12:34:56:ab:cd:ef"
+macAddress.toHex(0); // returns "123456abcdef"
+//! [50]
+
+//! [51]
+QByteArray text = QByteArray::fromPercentEncoding("Qt%20is%20great%33");
+text.data(); // returns "Qt is great!"
+//! [51]
+
+//! [52]
+QByteArray text = "{a fishy string?}";
+QByteArray ba = text.toPercentEncoding("{}", "s");
+qDebug(ba.constData());
+// prints "{a fi%73hy %73tring%3F}"
+//! [52]
+
+//! [53]
+QByteArray ba = QByteArrayLiteral("byte array contents");
+//! [53]
+
}
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearraymatcher.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearraymatcher.cpp
new file mode 100644
index 0000000000..63fc1f91e7
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearraymatcher.cpp
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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$
+**
+****************************************************************************/
+
+//! [0]
+static const auto matcher = qMakeStaticByteArrayMatcher("needle");
+//! [0]
+
+//! [1]
+static const auto matcher = qMakeStaticByteArrayMatcher("needle");
+//! [1]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qcontiguouscache.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qcontiguouscache.cpp
new file mode 100644
index 0000000000..6bc9604243
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qcontiguouscache.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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$
+**
+****************************************************************************/
+
+//! [0]
+MyRecord record(int row) const
+{
+ Q_ASSERT(row >= 0 && row < count());
+
+ while (row > cache.lastIndex())
+ cache.append(slowFetchRecord(cache.lastIndex()+1));
+ while (row < cache.firstIndex())
+ cache.prepend(slowFetchRecord(cache.firstIndex()-1));
+
+ return cache.at(row);
+}
+//! [0]
+
+//! [1]
+QContiguousCache<int> cache(10);
+cache.insert(INT_MAX, 1); // cache contains one value and has valid indexes, INT_MAX to INT_MAX
+cache.append(2); // cache contains two values but does not have valid indexes.
+cache.normalizeIndexes(); // cache has two values, 1 and 2. New first index will be in the range of 0 to capacity().
+//! [1]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qeasingcurve.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qeasingcurve.cpp
index 97453e2b06..88f1e90713 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qeasingcurve.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qeasingcurve.cpp
@@ -48,11 +48,15 @@
**
****************************************************************************/
+//! [typedef]
+qreal myEasingFunction(qreal progress);
+//! [typedef]
+
//! [0]
QEasingCurve easing(QEasingCurve::InOutQuad);
- for (qreal t = 0.0; t < 1.0; t+=0.1)
- qWarning() << "Effective progress" << t << " is
+ for (qreal t = 0.0; t < 1.0; t += 0.1)
+ qWarning() << "Effective progress" << t << "is"
<< easing.valueForProgress(t);
//! [0]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp
index c7df6f6090..a3d2dd7f9e 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp
@@ -350,3 +350,23 @@ inline uint qHash(const std::unordered_set<int> &key, uint seed = 0)
return qHashRangeCommutative(key.begin(), key.end(), seed);
}
//! [qhashrangecommutative]
+
+//! [29]
+qHash(qMakePair(key.first, key.second), seed);
+//! [29]
+
+//! [30]
+{0, 1, 2}
+//! [30]
+
+//! [31]
+{1, 2, 0}
+//! [31]
+
+//! [32]
+uint qHash(K key);
+uint qHash(const K &key);
+
+uint qHash(K key, uint seed);
+uint qHash(const K &key, uint seed);
+//! [32]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qrect.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qrect.cpp
index 4bdaa4d657..a19dc086ac 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qrect.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qrect.cpp
@@ -58,3 +58,13 @@ QRect r2(QPoint(100, 200), QSize(11, 16));
QRectF r1(100.0, 200.1, 11.2, 16.3);
QRectF r2(QPointF(100.0, 200.1), QSizeF(11.2, 16.3));
//! [1]
+
+//! [2]
+QRect r = {15, 51, 42, 24};
+r = r.transposed(); // r == {15, 51, 24, 42}
+//! [2]
+
+//! [3]
+QRectF r = {1.5, 5.1, 4.2, 2.4};
+r = r.transposed(); // r == {1.5, 5.1, 2.4, 4.2}
+//! [3]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qregularexpression.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qregularexpression.cpp
index 5f0a175374..afdd9c3d25 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qregularexpression.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qregularexpression.cpp
@@ -350,4 +350,22 @@ while (i.hasNext()) {
//! [30]
}
+{
+//! [31]
+QString wildcard = QRegularExpression::wildcardToRegularExpression("*.jpeg");
+// Will match files with names like:
+// foo.jpeg
+// f_o_o.jpeg
+// föö.jpeg
+//! [31]
+}
+
+//! [32]
+ (?<day>\d\d)-(?<month>\d\d)-(?<year>\d\d\d\d) (\w+) (?<name>\w+)
+//! [32]
+
+//! [33]
+ ("", "day", "month", "year", "", "name")
+//! [33]
+
}
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qscopeguard.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qscopeguard.cpp
new file mode 100644
index 0000000000..c8c5f694c6
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qscopeguard.cpp
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Sérgio Martins <sergio.martins@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+void myComplexCodeWithMultipleReturnPoints(int v)
+{
+ // The lambda will be executed right before your function returns
+ auto cleanup = qScopeGuard([] { code you want executed goes HERE; });
+
+ if (v == -1)
+ return;
+
+ int v2 = code_that_might_through_exceptions();
+
+ if (v2 == -1)
+ return;
+
+ (...)
+}
+//! [0]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qshareddata.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qshareddata.cpp
new file mode 100644
index 0000000000..45e8b0a965
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qshareddata.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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$
+**
+****************************************************************************/
+
+//! [0]
+ class EmployeeData;
+//! [0]
+
+//! [1]
+ template<>
+ EmployeeData *QSharedDataPointer<EmployeeData>::clone()
+ {
+ return d->clone();
+ }
+//! [1]
+
+//! [2]
+ QExplicitlySharedDataPointer<Base> base(new Base);
+ QExplicitlySharedDataPointer<Derived> derived(base); // !!! DANGER !!!
+//! [2]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qsharedpointer.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qsharedpointer.cpp
new file mode 100644
index 0000000000..69061ce298
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qsharedpointer.cpp
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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$
+**
+****************************************************************************/
+
+//! [0]
+ class Y: public QEnableSharedFromThis<Y>
+ {
+ public:
+ QSharedPointer<Y> f()
+ {
+ return sharedFromThis();
+ }
+ };
+
+ int main()
+ {
+ QSharedPointer<Y> p(new Y());
+ QSharedPointer<Y> y = p->f();
+ Q_ASSERT(p == y); // p and q must share ownership
+ }
+//! [0]
+
+//! [1]
+ class ScriptInterface : public QObject
+ {
+ Q_OBJECT
+
+ // ...
+
+ public slots:
+ void slotCalledByScript(Y *managedBySharedPointer)
+ {
+ QSharedPointer<Y> yPtr = managedBySharedPointer->sharedFromThis();
+ // Some other code unrelated to scripts that expects a QSharedPointer<Y> ...
+ }
+ };
+//! [1]
+
+//! [2]
+ static void doDeleteLater(MyObject *obj)
+ {
+ obj->deleteLater();
+ }
+
+ void otherFunction()
+ {
+ QSharedPointer<MyObject> obj =
+ QSharedPointer<MyObject>(new MyObject, doDeleteLater);
+
+ // continue using obj
+ obj.clear(); // calls obj->deleteLater();
+ }
+//! [2]
+
+//! [3]
+ QSharedPointer<MyObject> obj =
+ QSharedPointer<MyObject>(new MyObject, &QObject::deleteLater);
+//! [3]
+
+//! [4]
+ if (sharedptr) { ... }
+//! [4]
+
+//! [5]
+ if (!sharedptr) { ... }
+//! [5]
+
+//! [6]
+ QSharedPointer<T> other(t); this->swap(other);
+//! [6]
+
+//! [7]
+ QSharedPointer<T> other(t, deleter); this->swap(other);
+//! [7]
+
+//! [8]
+ if (weakref) { ... }
+//! [8]
+
+//! [9]
+ if (!weakref) { ... }
+//! [9]
+
+//! [10]
+ qDebug("Tracking %p", weakref.data());
+//! [10]
+
+//! [11]
+ // this pointer cannot be used in another thread
+ // so other threads cannot delete it
+ QWeakPointer<int> weakref = obtainReference();
+
+ Object *obj = weakref.data();
+ if (obj) {
+ // if the pointer wasn't deleted yet, we know it can't get
+ // deleted by our own code here nor the functions we call
+ otherFunction(obj);
+ }
+//! [11]
+
+//! [12]
+ QWeakPointer<int> weakref;
+
+ // ...
+
+ QSharedPointer<int> strong = weakref.toStrongRef();
+ if (strong)
+ qDebug() << "The value is:" << *strong;
+ else
+ qDebug() << "The value has already been deleted";
+//! [12]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qstring.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qstring.cpp
index 9b3e89e5c4..4e79d1e27a 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qstring.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qstring.cpp
@@ -102,3 +102,21 @@ QString plain = "#include <QtCore>"
QString html = plain.toHtmlEscaped();
// html == "#include &lt;QtCore&gt;"
//! [7]
+
+//! [8]
+QString str("ab");
+str.repeated(4); // returns "abababab"
+//! [8]
+
+//! [9]
+// hasAttribute takes a QString argument
+if (node.hasAttribute("http-contents-length")) //...
+//! [9]
+
+//! [10]
+if (node.hasAttribute(QStringLiteral(u"http-contents-length"))) //...
+//! [10]
+
+//! [11]
+if (attribute.name() == QLatin1String("http-contents-length")) //...
+//! [11]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qstringview.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qstringview.cpp
new file mode 100644
index 0000000000..5dc153372c
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qstringview.cpp
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWidgets module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+ void myfun1(QStringView sv); // preferred
+ void myfun2(const QStringView &sv); // compiles and works, but slower
+//! [0]
+
+//! [1]
+ void fun(QChar ch) { fun(QStringView(&ch, 1)); }
+//! [1]
+
+//! [2]
+ auto sv = QStringView(array, std::size(array)); // using C++17 std::size()
+//! [2]
diff --git a/src/corelib/doc/snippets/qstring/main.cpp b/src/corelib/doc/snippets/qstring/main.cpp
index c8842eec00..ac7fc7d078 100644
--- a/src/corelib/doc/snippets/qstring/main.cpp
+++ b/src/corelib/doc/snippets/qstring/main.cpp
@@ -853,6 +853,8 @@ void Widget::toDoubleFunction()
double d;
d = QString( "1234.56e-02" ).toDouble(&ok); // ok == true, d == 12.3456
+
+ d = QString( "1234.56e-02 Volt" ).toDouble(&ok); // ok == false, d == 0
//! [67]
//! [68]
@@ -875,6 +877,9 @@ void Widget::toFloatFunction()
bool ok;
QString str2 = "R2D2";
str2.toFloat(&ok); // returns 0.0, sets ok to false
+
+ QString str3 = "1234.56 Volt";
+ str3.toFloat(&ok); // returns 0.0, sets ok to false
//! [71]
}
diff --git a/src/corelib/doc/src/objectmodel/signalsandslots.qdoc b/src/corelib/doc/src/objectmodel/signalsandslots.qdoc
index 213caa6c59..fcf091458a 100644
--- a/src/corelib/doc/src/objectmodel/signalsandslots.qdoc
+++ b/src/corelib/doc/src/objectmodel/signalsandslots.qdoc
@@ -321,8 +321,8 @@
callbacks, you'd have to find five different names and keep track
of the types yourself.
- \sa QLCDNumber, QObject::connect(), {Digital Clock Example}, and
- {Tetrix Example}.
+ \sa QLCDNumber, QObject::connect(), {Digital Clock Example},
+ {Tetrix Example}
\section1 Signals And Slots With Default Arguments
diff --git a/src/corelib/doc/src/resource-system.qdoc b/src/corelib/doc/src/resource-system.qdoc
index e32343bb1b..9b6b613f79 100644
--- a/src/corelib/doc/src/resource-system.qdoc
+++ b/src/corelib/doc/src/resource-system.qdoc
@@ -42,6 +42,7 @@
\l rcc (Qt's resource compiler), and QFile.
\section1 Resource Collection Files (\c{.qrc})
+ \target {Resource Collection Files}
The resources associated with an application are specified in a
\c .qrc file, an XML-based file format that lists files on the
diff --git a/src/corelib/global/archdetect.cpp b/src/corelib/global/archdetect.cpp
index 6c1a026fa8..422df3ff90 100644
--- a/src/corelib/global/archdetect.cpp
+++ b/src/corelib/global/archdetect.cpp
@@ -51,6 +51,8 @@
# define ARCH_PROCESSOR "avr32"
#elif defined(Q_PROCESSOR_BLACKFIN)
# define ARCH_PROCESSOR "bfin"
+#elif defined(Q_PROCESSOR_WASM)
+# define ARCH_PROCESSOR "wasm"
#elif defined(Q_PROCESSOR_X86_32)
# define ARCH_PROCESSOR "i386"
#elif defined(Q_PROCESSOR_X86_64)
diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri
index 2b4fd6d661..a4d132a4f4 100644
--- a/src/corelib/global/global.pri
+++ b/src/corelib/global/global.pri
@@ -29,6 +29,7 @@ HEADERS += \
SOURCES += \
global/archdetect.cpp \
+ global/qendian.cpp \
global/qglobal.cpp \
global/qlibraryinfo.cpp \
global/qmalloc.cpp \
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index f46ff73527..345ab9e8ad 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -206,6 +206,9 @@
# define Q_DECL_NS_RETURNS_AUTORELEASED __attribute__((ns_returns_autoreleased))
# endif
# endif
+# ifdef __EMSCRIPTEN__
+# define Q_CC_EMSCRIPTEN
+# endif
# else
/* Plain GCC */
# if Q_CC_GNU >= 405
@@ -898,7 +901,7 @@
/* C11 features supported in GCC 4.7: */
# define Q_COMPILER_STATIC_ASSERT
# endif
-# if Q_CC_GNU >= 409
+# if Q_CC_GNU >= 409 && defined(__has_include)
/* C11 features supported in GCC 4.9: */
# if __has_include(<threads.h>)
# define Q_COMPILER_THREAD_LOCAL
@@ -1152,6 +1155,19 @@
# define Q_REQUIRED_RESULT [[nodiscard]]
#endif
+#if defined(__cpp_enumerator_attributes) && __cpp_enumerator_attributes >= 201411
+#if defined(Q_CC_MSVC)
+// Can't mark enum values as __declspec(deprecated) with MSVC, also can't move
+// everything to [[deprecated]] because MSVC gives a compilation error when marking
+// friend methods of a class as [[deprecated("text")]], breaking qstring.h
+# define Q_DECL_ENUMERATOR_DEPRECATED [[deprecated]]
+# define Q_DECL_ENUMERATOR_DEPRECATED_X(x) [[deprecated(x)]]
+#else
+# define Q_DECL_ENUMERATOR_DEPRECATED Q_DECL_DEPRECATED
+# define Q_DECL_ENUMERATOR_DEPRECATED_X(x) Q_DECL_DEPRECATED_X(x)
+#endif
+#endif
+
/*
* Fallback macros to certain compiler features
*/
@@ -1186,6 +1202,12 @@
#ifndef Q_DECL_DEPRECATED_X
# define Q_DECL_DEPRECATED_X(text) Q_DECL_DEPRECATED
#endif
+#ifndef Q_DECL_ENUMERATOR_DEPRECATED
+# define Q_DECL_ENUMERATOR_DEPRECATED
+#endif
+#ifndef Q_DECL_ENUMERATOR_DEPRECATED_X
+# define Q_DECL_ENUMERATOR_DEPRECATED_X(x)
+#endif
#ifndef Q_DECL_EXPORT
# define Q_DECL_EXPORT
#endif
diff --git a/src/corelib/global/qconfig-bootstrapped.h b/src/corelib/global/qconfig-bootstrapped.h
index da66e3bcd3..f6a5d6b1d4 100644
--- a/src/corelib/global/qconfig-bootstrapped.h
+++ b/src/corelib/global/qconfig-bootstrapped.h
@@ -104,6 +104,7 @@
#else
# define QT_FEATURE_renameat2 -1
#endif
+#define QT_FEATURE_settings -1
#define QT_FEATURE_sharedmemory -1
#define QT_FEATURE_slog2 -1
#ifdef __GLIBC_PREREQ
@@ -116,7 +117,7 @@
#define QT_FEATURE_systemsemaphore -1
#define QT_FEATURE_temporaryfile 1
#define QT_FEATURE_textdate 1
-#define QT_NO_THREAD
+#define QT_FEATURE_thread -1
#define QT_FEATURE_timezone -1
#define QT_FEATURE_topleveldomain -1
#define QT_NO_TRANSLATION
diff --git a/src/corelib/global/qendian.cpp b/src/corelib/global/qendian.cpp
new file mode 100644
index 0000000000..7fd6e13d3b
--- /dev/null
+++ b/src/corelib/global/qendian.cpp
@@ -0,0 +1,919 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://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 "qendian.h"
+
+#include "qalgorithms.h"
+#include <private/qsimd_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \headerfile <QtEndian>
+ \title Endian Conversion Functions
+ \ingroup funclists
+ \brief The <QtEndian> header provides functions to convert between
+ little and big endian representations of numbers.
+*/
+
+/*!
+ \fn template <typename T> T qFromUnaligned(const void *ptr)
+ \internal
+ \since 5.5
+
+ Loads a \c{T} from address \a ptr, which may be misaligned.
+
+ Use of this function avoids the undefined behavior that the C++ standard
+ otherwise attributes to unaligned loads.
+*/
+
+/*!
+ \fn template <typename T> void qToUnaligned(const T t, void *ptr)
+ \internal
+ \since 4.5
+
+ Stores \a t to address \a ptr, which may be misaligned.
+
+ Use of this function avoids the undefined behavior that the C++ standard
+ otherwise attributes to unaligned stores.
+*/
+
+
+/*!
+ \fn template <typename T> T qFromBigEndian(const void *src)
+ \since 4.3
+ \relates <QtEndian>
+
+ Reads a big-endian number from memory location \a src and returns the number in the
+ host byte order representation.
+ On CPU architectures where the host byte order is little-endian (such as x86) this
+ will swap the byte order; otherwise it will just read from \a src.
+
+ \note Template type \c{T} can either be a quint16, qint16, quint32, qint32,
+ quint64, or qint64. Other types of integers, e.g., qlong, are not
+ applicable.
+
+ \note Since Qt 5.7, the type of the \a src parameter is a void pointer.
+
+ There are no data alignment constraints for \a src.
+
+ \sa qFromLittleEndian()
+ \sa qToBigEndian()
+ \sa qToLittleEndian()
+*/
+/*!
+ \fn template <typename T> T qFromBigEndian(T src)
+ \since 4.3
+ \relates <QtEndian>
+ \overload
+
+ Converts \a src from big-endian byte order and returns the number in host byte order
+ representation of that number.
+ On CPU architectures where the host byte order is little-endian (such as x86) this
+ will return \a src with the byte order swapped; otherwise it will return \a src
+ unmodified.
+*/
+/*!
+ \fn template <typename T> T qFromBigEndian(const void *src, qsizetype count, void *dest)
+ \since 5.12
+ \relates <QtEndian>
+
+ Reads \a count big-endian numbers from memory location \a src and stores
+ them in the host byte order representation at \a dest. On CPU architectures
+ where the host byte order is little-endian (such as x86) this will swap the
+ byte order; otherwise it will just perform a \c memcpy from \a src to \a
+ dest.
+
+ \note Template type \c{T} can either be a quint16, qint16, quint32, qint32,
+ quint64, or qint64. Other types of integers, e.g., qlong, are not
+ applicable.
+
+ There are no data alignment constraints for \a src. However, \a dest is
+ expected to be naturally aligned for type \c{T}.
+
+ If \a src and \a dest can be the same pointer, this function will perform
+ an in-place swap (if necessary). If they are not the same, the memory
+ regions must not overlap.
+
+ \sa qFromLittleEndian()
+ \sa qToBigEndian()
+ \sa qToLittleEndian()
+*/
+/*!
+ \fn template <typename T> T qFromLittleEndian(const void *src)
+ \since 4.3
+ \relates <QtEndian>
+
+ Reads a little-endian number from memory location \a src and returns the number in
+ the host byte order representation.
+ On CPU architectures where the host byte order is big-endian (such as PowerPC) this
+ will swap the byte order; otherwise it will just read from \a src.
+
+ \note Template type \c{T} can either be a quint16, qint16, quint32, qint32,
+ quint64, or qint64. Other types of integers, e.g., qlong, are not
+ applicable.
+
+ \note Since Qt 5.7, the type of the \a src parameter is a void pointer.
+
+ There are no data alignment constraints for \a src.
+
+ \sa qFromBigEndian()
+ \sa qToBigEndian()
+ \sa qToLittleEndian()
+*/
+/*!
+ \fn template <typename T> T qFromLittleEndian(T src)
+ \since 4.3
+ \relates <QtEndian>
+ \overload
+
+ Converts \a src from little-endian byte order and returns the number in host byte
+ order representation of that number.
+ On CPU architectures where the host byte order is big-endian (such as PowerPC) this
+ will return \a src with the byte order swapped; otherwise it will return \a src
+ unmodified.
+*/
+/*!
+ \fn template <typename T> T qFromLittleEndian(const void *src, qsizetype count, void *dest)
+ \since 5.12
+ \relates <QtEndian>
+
+ Reads \a count little-endian numbers from memory location \a src and stores
+ them in the host byte order representation at \a dest. On CPU architectures
+ where the host byte order is big-endian (such as PowerPC) this will swap the
+ byte order; otherwise it will just perform a \c memcpy from \a src to \a
+ dest.
+
+ \note Template type \c{T} can either be a quint16, qint16, quint32, qint32,
+ quint64, or qint64. Other types of integers, e.g., qlong, are not
+ applicable.
+
+ There are no data alignment constraints for \a src. However, \a dest is
+ expected to be naturally aligned for type \c{T}.
+
+ If \a src and \a dest can be the same pointer, this function will perform
+ an in-place swap (if necessary). If they are not the same, the memory
+ regions must not overlap.
+
+ \sa qFromLittleEndian()
+ \sa qToBigEndian()
+ \sa qToLittleEndian()
+*/
+/*!
+ \fn template <typename T> void qToBigEndian(T src, void *dest)
+ \since 4.3
+ \relates <QtEndian>
+
+ Writes the number \a src with template type \c{T} to the memory location at \a dest
+ in big-endian byte order.
+
+ \note Template type \c{T} can either be a quint16, qint16, quint32, qint32,
+ quint64, or qint64. Other types of integers, e.g., qlong, are not
+ applicable.
+
+ There are no data alignment constraints for \a dest.
+
+ \note Since Qt 5.7, the type of the \a dest parameter is a void pointer.
+
+ \sa qFromBigEndian()
+ \sa qFromLittleEndian()
+ \sa qToLittleEndian()
+*/
+/*!
+ \fn template <typename T> T qToBigEndian(T src)
+ \since 4.3
+ \relates <QtEndian>
+ \overload
+
+ Converts \a src from host byte order and returns the number in big-endian byte order
+ representation of that number.
+ On CPU architectures where the host byte order is little-endian (such as x86) this
+ will return \a src with the byte order swapped; otherwise it will return \a src
+ unmodified.
+*/
+/*!
+ \fn template <typename T> T qToBigEndian(const void *src, qsizetype count, void *dest)
+ \since 5.12
+ \relates <QtEndian>
+
+ Reads \a count numbers from memory location \a src in the host byte order
+ and stores them in big-endian representation at \a dest. On CPU
+ architectures where the host byte order is little-endian (such as x86) this
+ will swap the byte order; otherwise it will just perform a \c memcpy from
+ \a src to \a dest.
+
+ \note Template type \c{T} can either be a quint16, qint16, quint32, qint32,
+ quint64, or qint64. Other types of integers, e.g., qlong, are not
+ applicable.
+
+ There are no data alignment constraints for \a dest. However, \a src is
+ expected to be naturally aligned for type \c{T}.
+
+ If \a src and \a dest can be the same pointer, this function will perform
+ an in-place swap (if necessary). If they are not the same, the memory
+ regions must not overlap.
+
+ \sa qFromLittleEndian()
+ \sa qToBigEndian()
+ \sa qToLittleEndian()
+*/
+/*!
+ \fn template <typename T> void qToLittleEndian(T src, void *dest)
+ \since 4.3
+ \relates <QtEndian>
+
+ Writes the number \a src with template type \c{T} to the memory location at \a dest
+ in little-endian byte order.
+
+ \note Template type \c{T} can either be a quint16, qint16, quint32, qint32,
+ quint64, or qint64. Other types of integers, e.g., qlong, are not
+ applicable.
+
+ There are no data alignment constraints for \a dest.
+
+ \note Since Qt 5.7, the type of the \a dest parameter is a void pointer.
+
+ \sa qFromBigEndian()
+ \sa qFromLittleEndian()
+ \sa qToBigEndian()
+*/
+/*!
+ \fn template <typename T> T qToLittleEndian(T src)
+ \since 4.3
+ \relates <QtEndian>
+ \overload
+
+ Converts \a src from host byte order and returns the number in little-endian byte
+ order representation of that number.
+ On CPU architectures where the host byte order is big-endian (such as PowerPC) this
+ will return \a src with the byte order swapped; otherwise it will return \a src
+ unmodified.
+*/
+/*!
+ \fn template <typename T> T qToLittleEndian(const void *src, qsizetype count, void *dest)
+ \since 5.12
+ \relates <QtEndian>
+
+ Reads \a count numbers from memory location \a src in the host byte order
+ and stores them in little-endian representation at \a dest. On CPU
+ architectures where the host byte order is big-endian (such as PowerPC)
+ this will swap the byte order; otherwise it will just perform a \c memcpy
+ from \a src to \a dest.
+
+ \note Template type \c{T} can either be a quint16, qint16, quint32, qint32,
+ quint64, or qint64. Other types of integers, e.g., qlong, are not
+ applicable.
+
+ There are no data alignment constraints for \a dest. However, \a src is
+ expected to be naturally aligned for type \c{T}.
+
+ If \a src and \a dest can be the same pointer, this function will perform
+ an in-place swap (if necessary). If they are not the same, the memory
+ regions must not overlap.
+
+ \sa qFromLittleEndian()
+ \sa qToBigEndian()
+ \sa qToLittleEndian()
+*/
+
+/*!
+ \class QLEInteger
+ \inmodule QtCore
+ \brief The QLEInteger class provides platform-independent little-endian integers.
+ \since 5.10
+
+ The template parameter \c T must be a C++ integer type:
+ \list
+ \li 8-bit: char, signed char, unsigned char, qint8, quint8
+ \li 16-bit: short, unsigned short, qint16, quint16, char16_t
+ \li 32-bit: int, unsigned int, qint32, quint32, char32_t
+ \li 64-bit: long long, unsigned long long, qint64, quint64
+ \li platform-specific size: long, unsigned long
+ \li pointer size: qintptr, quintptr, qptrdiff
+ \endlist
+
+ \note Using this class may be slower than using native integers, so only use it when
+ an exact endianness is needed.
+*/
+
+/*! \fn template <typename T> QLEInteger<T>::QLEInteger(T value)
+
+ Constructs a QLEInteger with the given \a value.
+*/
+
+/*! \fn template <typename T> QLEInteger &QLEInteger<T>::operator=(T i)
+
+ Assigns \a i to this QLEInteger and returns a reference to
+ this QLEInteger.
+*/
+
+/*!
+ \fn template <typename T> QLEInteger<T>::operator T() const
+
+ Returns the value of this QLEInteger as a native integer.
+*/
+
+/*!
+ \fn template <typename T> bool QLEInteger<T>::operator==(QLEInteger other) const
+
+ Returns \c true if the value of this QLEInteger is equal to the value of \a other.
+*/
+
+/*!
+ \fn template <typename T> bool QLEInteger<T>::operator!=(QLEInteger other) const
+
+ Returns \c true if the value of this QLEInteger is not equal to the value of \a other.
+*/
+
+/*!
+ \fn template <typename T> QLEInteger &QLEInteger<T>::operator+=(T i)
+
+ Adds \a i to this QLEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn template <typename T> QLEInteger &QLEInteger<T>::operator-=(T i)
+
+ Subtracts \a i from this QLEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn template <typename T> QLEInteger &QLEInteger<T>::operator*=(T i)
+
+ Multiplies \a i with this QLEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn template <typename T> QLEInteger &QLEInteger<T>::operator/=(T i)
+
+ Divides this QLEInteger with \a i and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn template <typename T> QLEInteger &QLEInteger<T>::operator%=(T i)
+
+ Sets this QLEInteger to the remainder of a division by \a i and
+ returns a reference to this object.
+*/
+
+/*!
+ \fn template <typename T> QLEInteger &QLEInteger<T>::operator>>=(T i)
+
+ Performs a left-shift by \a i on this QLEInteger and returns a
+ reference to this object.
+*/
+
+/*!
+ \fn template <typename T> QLEInteger &QLEInteger<T>::operator<<=(T i)
+
+ Performs a right-shift by \a i on this QLEInteger and returns a
+ reference to this object.
+*/
+
+/*!
+ \fn template <typename T> QLEInteger &QLEInteger<T>::operator|=(T i)
+
+ Performs a bitwise OR with \a i onto this QLEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn template <typename T> QLEInteger &QLEInteger<T>::operator&=(T i)
+
+ Performs a bitwise AND with \a i onto this QLEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn template <typename T> QLEInteger &QLEInteger<T>::operator^=(T i)
+
+ Performs a bitwise XOR with \a i onto this QLEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn template <typename T> QLEInteger &QLEInteger<T>::operator++()
+
+ Performs a prefix ++ (increment) on this QLEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn template <typename T> QLEInteger QLEInteger<T>::operator++(int)
+
+ Performs a postfix ++ (increment) on this QLEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn template <typename T> QLEInteger &QLEInteger<T>::operator--()
+
+ Performs a prefix -- (decrement) on this QLEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn template <typename T> QLEInteger QLEInteger<T>::operator--(int)
+
+ Performs a postfix -- (decrement) on this QLEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn template <typename T> QLEInteger QLEInteger<T>::max()
+
+ Returns the maximum (finite) value representable by the numeric type T.
+*/
+
+/*!
+ \fn template <typename T> QLEInteger QLEInteger<T>::min()
+
+ Returns the minimum (finite) value representable by the numeric type T.
+*/
+
+/*!
+ \class QBEInteger
+ \inmodule QtCore
+ \brief The QBEInteger class provides platform-independent big-endian integers.
+ \since 5.10
+
+ The template parameter \c T must be a C++ integer type:
+ \list
+ \li 8-bit: char, signed char, unsigned char, qint8, quint8
+ \li 16-bit: short, unsigned short, qint16, quint16, char16_t (C++11)
+ \li 32-bit: int, unsigned int, qint32, quint32, char32_t (C++11)
+ \li 64-bit: long long, unsigned long long, qint64, quint64
+ \li platform-specific size: long, unsigned long
+ \li pointer size: qintptr, quintptr, qptrdiff
+ \endlist
+
+ \note Using this class may be slower than using native integers, so only use it when
+ an exact endianness is needed.
+*/
+
+/*! \fn template <typename T> QBEInteger<T>::QBEInteger(T value)
+
+ Constructs a QBEInteger with the given \a value.
+*/
+
+/*! \fn template <typename T> QBEInteger &QBEInteger<T>::operator=(T i)
+
+ Assigns \a i to this QBEInteger and returns a reference to
+ this QBEInteger.
+*/
+
+/*!
+ \fn template <typename T> QBEInteger<T>::operator T() const
+
+ Returns the value of this QBEInteger as a native integer.
+*/
+
+/*!
+ \fn template <typename T> bool QBEInteger<T>::operator==(QBEInteger other) const
+
+ Returns \c true if the value of this QBEInteger is equal to the value of \a other.
+*/
+
+/*!
+ \fn template <typename T> bool QBEInteger<T>::operator!=(QBEInteger other) const
+
+ Returns \c true if the value of this QBEInteger is not equal to the value of \a other.
+*/
+
+/*!
+ \fn template <typename T> QBEInteger &QBEInteger<T>::operator+=(T i)
+
+ Adds \a i to this QBEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn template <typename T> QBEInteger &QBEInteger<T>::operator-=(T i)
+
+ Subtracts \a i from this QBEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn template <typename T> QBEInteger &QBEInteger<T>::operator*=(T i)
+
+ Multiplies \a i with this QBEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn template <typename T> QBEInteger &QBEInteger<T>::operator/=(T i)
+
+ Divides this QBEInteger with \a i and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn template <typename T> QBEInteger &QBEInteger<T>::operator%=(T i)
+
+ Sets this QBEInteger to the remainder of a division by \a i and
+ returns a reference to this object.
+*/
+
+/*!
+ \fn template <typename T> QBEInteger &QBEInteger<T>::operator>>=(T i)
+
+ Performs a left-shift by \a i on this QBEInteger and returns a
+ reference to this object.
+*/
+
+/*!
+ \fn template <typename T> QBEInteger &QBEInteger<T>::operator<<=(T i)
+
+ Performs a right-shift by \a i on this QBEInteger and returns a
+ reference to this object.
+*/
+
+/*!
+ \fn template <typename T> QBEInteger &QBEInteger<T>::operator|=(T i)
+
+ Performs a bitwise OR with \a i onto this QBEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn template <typename T> QBEInteger &QBEInteger<T>::operator&=(T i)
+
+ Performs a bitwise AND with \a i onto this QBEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn template <typename T> QBEInteger &QBEInteger<T>::operator^=(T i)
+
+ Performs a bitwise XOR with \a i onto this QBEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn template <typename T> QBEInteger &QBEInteger<T>::operator++()
+
+ Performs a prefix ++ (increment) on this QBEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn template <typename T> QBEInteger QBEInteger<T>::operator++(int)
+
+ Performs a postfix ++ (increment) on this QBEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn template <typename T> QBEInteger &QBEInteger<T>::operator--()
+
+ Performs a prefix -- (decrement) on this QBEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn template <typename T> QBEInteger QBEInteger<T>::operator--(int)
+
+ Performs a postfix -- (decrement) on this QBEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn template <typename T> QBEInteger QBEInteger<T>::max()
+
+ Returns the maximum (finite) value representable by the numeric type T.
+*/
+
+/*!
+ \fn template <typename T> QBEInteger QBEInteger<T>::min()
+
+ Returns the minimum (finite) value representable by the numeric type T.
+*/
+
+/*!
+ \typedef quint16_le
+ \relates <QtEndian>
+ \since 5.10
+
+ Typedef for QLEInteger<quint16>. This type is guaranteed to be stored in memory as
+ a 16-bit little-endian unsigned integer on all platforms supported by Qt.
+
+ \sa quint16
+*/
+
+/*!
+ \typedef quint32_le
+ \relates <QtEndian>
+ \since 5.10
+
+ Typedef for QLEInteger<quint32>. This type is guaranteed to be stored in memory as
+ a 32-bit little-endian unsigned integer on all platforms supported by Qt.
+
+ \sa quint32
+*/
+
+/*!
+ \typedef quint64_le
+ \relates <QtEndian>
+ \since 5.10
+
+ Typedef for QLEInteger<quint64>. This type is guaranteed to be stored in memory as
+ a 64-bit little-endian unsigned integer on all platforms supported by Qt.
+
+ \sa quint64
+*/
+
+/*!
+ \typedef quint16_be
+ \relates <QtEndian>
+ \since 5.10
+
+ Typedef for QBEInteger<quint16>. This type is guaranteed to be stored in memory as
+ a 16-bit big-endian unsigned integer on all platforms supported by Qt.
+
+ \sa quint16
+*/
+
+/*!
+ \typedef quint32_be
+ \relates <QtEndian>
+ \since 5.10
+
+ Typedef for QBEInteger<quint32>. This type is guaranteed to be stored in memory as
+ a 32-bit big-endian unsigned integer on all platforms supported by Qt.
+
+ \sa quint32
+*/
+
+/*!
+ \typedef quint64_be
+ \relates <QtEndian>
+ \since 5.10
+
+ Typedef for QBEInteger<quint64>. This type is guaranteed to be stored in memory as
+ a 64-bit big-endian unsigned integer on all platforms supported by Qt.
+
+ \sa quint64
+*/
+
+/*!
+ \typedef qint16_le
+ \relates <QtEndian>
+ \since 5.10
+
+ Typedef for QLEInteger<qint16>. This type is guaranteed to be stored in memory as
+ a 16-bit little-endian signed integer on all platforms supported by Qt.
+
+ \sa qint16
+*/
+
+/*!
+ \typedef qint32_le
+ \relates <QtEndian>
+ \since 5.10
+
+ Typedef for QLEInteger<qint32>. This type is guaranteed to be stored in memory as
+ a 32-bit little-endian signed integer on all platforms supported by Qt.
+
+ \sa qint32
+*/
+
+/*!
+ \typedef qint64_le
+ \relates <QtEndian>
+ \since 5.10
+
+ Typedef for QLEInteger<qint64>. This type is guaranteed to be stored in memory as
+ a 64-bit little-endian signed integer on all platforms supported by Qt.
+
+ \sa qint64
+*/
+
+/*!
+ \typedef qint16_be
+ \relates <QtEndian>
+ \since 5.10
+
+ Typedef for QBEInteger<qint16>. This type is guaranteed to be stored in memory as
+ a 16-bit big-endian signed integer on all platforms supported by Qt.
+
+ \sa qint16
+*/
+
+/*!
+ \typedef qint32_be
+ \relates <QtEndian>
+ \since 5.10
+
+ Typedef for QBEInteger<qint32>. This type is guaranteed to be stored in memory as
+ a 32-bit big-endian signed integer on all platforms supported by Qt.
+
+ \sa qint32
+*/
+
+/*!
+ \typedef qint64_be
+ \relates <QtEndian>
+ \since 5.10
+
+ Typedef for QBEInteger<qint64>. This type is guaranteed to be stored in memory as
+ a 64-bit big-endian signed integer on all platforms supported by Qt.
+
+ \sa qint64
+*/
+
+#if defined(__SSSE3__)
+using ShuffleMask = uchar[16];
+Q_DECL_ALIGN(16) static const ShuffleMask shuffleMasks[3] = {
+ // 16-bit
+ {1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14},
+ // 32-bit
+ {3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12},
+ // 64-bit
+ {7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8}
+};
+
+static size_t sseSwapLoop(const uchar *src, size_t bytes, uchar *dst,
+ const __m128i *shuffleMaskPtr) noexcept
+{
+ size_t i = 0;
+ const __m128i shuffleMask = _mm_load_si128(shuffleMaskPtr);
+
+# ifdef __AVX2__
+ const __m256i shuffleMask256 = _mm256_inserti128_si256(_mm256_castsi128_si256(shuffleMask), shuffleMask, 1);
+ for ( ; i + sizeof(__m256i) <= bytes; i += sizeof(__m256i)) {
+ __m256i data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(src + i));
+ data = _mm256_shuffle_epi8(data, shuffleMask256);
+ _mm256_storeu_si256(reinterpret_cast<__m256i *>(dst + i), data);
+ }
+# else
+ for ( ; i + 2 * sizeof(__m128i) <= bytes; i += 2 * sizeof(__m128i)) {
+ __m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + i));
+ __m128i data2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + i) + 1);
+ data1 = _mm_shuffle_epi8(data1, shuffleMask);
+ data2 = _mm_shuffle_epi8(data2, shuffleMask);
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + i), data1);
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + i) + 1, data2);
+ }
+# endif
+
+ if (i + sizeof(__m128i) <= bytes) {
+ __m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + i));
+ data = _mm_shuffle_epi8(data, shuffleMask);
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + i), data);
+ i += sizeof(__m128i);
+ }
+
+ return i;
+}
+
+template <typename T> static Q_ALWAYS_INLINE
+size_t simdSwapLoop(const uchar *src, size_t bytes, uchar *dst) noexcept
+{
+ auto shuffleMaskPtr = reinterpret_cast<const __m128i *>(shuffleMasks[0]);
+ shuffleMaskPtr += qCountTrailingZeroBits(sizeof(T)) - 1;
+ size_t i = sseSwapLoop(src, bytes, dst, shuffleMaskPtr);
+
+ // epilogue
+ for (size_t _i = 0 ; i < bytes && _i < sizeof(__m128i); i += sizeof(T), _i += sizeof(T))
+ qbswap(qFromUnaligned<T>(src + i), dst + i);
+
+ // return the total, so the bswapLoop below does nothing
+ return bytes;
+}
+#elif defined(__SSE2__)
+template <typename T> static
+size_t simdSwapLoop(const uchar *, size_t, uchar *) noexcept
+{
+ // no generic version: we can't do 32- and 64-bit swaps easily,
+ // so we won't try
+ return 0;
+}
+
+template <> size_t simdSwapLoop<quint16>(const uchar *src, size_t bytes, uchar *dst) noexcept
+{
+ auto swapEndian = [](__m128i &data) {
+ __m128i lows = _mm_srli_epi16(data, 8);
+ __m128i highs = _mm_slli_epi16(data, 8);
+ data = _mm_xor_si128(lows, highs);
+ };
+
+ size_t i = 0;
+ for ( ; i + 2 * sizeof(__m128i) <= bytes; i += 2 * sizeof(__m128i)) {
+ __m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + i));
+ __m128i data2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + i) + 1);
+ swapEndian(data1);
+ swapEndian(data2);
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + i), data1);
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + i) + 1, data2);
+ }
+
+ if (i + sizeof(__m128i) <= bytes) {
+ __m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + i));
+ swapEndian(data);
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + i), data);
+ i += sizeof(__m128i);
+ }
+
+ // epilogue
+ for (size_t _i = 0 ; i < bytes && _i < sizeof(__m128i); i += sizeof(quint16), _i += sizeof(quint16))
+ qbswap(qFromUnaligned<quint16>(src + i), dst + i);
+
+ // return the total, so the bswapLoop below does nothing
+ return bytes;
+}
+#else
+template <typename T> static Q_ALWAYS_INLINE
+size_t simdSwapLoop(const uchar *, size_t, uchar *) noexcept
+{
+ return 0;
+}
+#endif
+
+template <typename T> static Q_ALWAYS_INLINE
+void *bswapLoop(const uchar *src, size_t n, uchar *dst) noexcept
+{
+ // Buffers cannot partially overlap: either they're identical or totally
+ // disjoint (note: they can be adjacent).
+ if (src != dst) {
+ quintptr s = quintptr(src);
+ quintptr d = quintptr(dst);
+ if (s < d)
+ Q_ASSERT(s + n <= d);
+ else
+ Q_ASSERT(d + n <= s);
+ }
+
+ size_t i = simdSwapLoop<T>(src, n, dst);
+
+ for ( ; i < n; i += sizeof(T))
+ qbswap(qFromUnaligned<T>(src + i), dst + i);
+ return dst + i;
+}
+
+template <> void *qbswap<2>(const void *source, qsizetype n, void *dest) noexcept
+{
+ const uchar *src = reinterpret_cast<const uchar *>(source);
+ uchar *dst = reinterpret_cast<uchar *>(dest);
+
+ return bswapLoop<quint16>(src, n << 1, dst);
+}
+
+template <> void *qbswap<4>(const void *source, qsizetype n, void *dest) noexcept
+{
+ const uchar *src = reinterpret_cast<const uchar *>(source);
+ uchar *dst = reinterpret_cast<uchar *>(dest);
+
+ return bswapLoop<quint32>(src, n << 2, dst);
+}
+
+template <> void *qbswap<8>(const void *source, qsizetype n, void *dest) noexcept
+{
+ const uchar *src = reinterpret_cast<const uchar *>(source);
+ uchar *dst = reinterpret_cast<uchar *>(dest);
+
+ return bswapLoop<quint64>(src, n << 3, dst);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/global/qendian.h b/src/corelib/global/qendian.h
index a14fce23f8..0e67a1ab8e 100644
--- a/src/corelib/global/qendian.h
+++ b/src/corelib/global/qendian.h
@@ -41,12 +41,18 @@
#ifndef QENDIAN_H
#define QENDIAN_H
+#include <QtCore/qfloat16.h>
#include <QtCore/qglobal.h>
// include stdlib.h and hope that it defines __GLIBC__ for glibc-based systems
#include <stdlib.h>
#include <string.h>
+#ifdef min // MSVC
+#undef min
+#undef max
+#endif
+
QT_BEGIN_NAMESPACE
/*
@@ -146,6 +152,31 @@ template <> inline Q_DECL_CONSTEXPR qint8 qbswap<qint8>(qint8 source)
return source;
}
+// floating specializations
+template<typename Float>
+Float qbswapFloatHelper(Float source)
+{
+ // memcpy call in qFromUnaligned is recognized by optimizer as a correct way of type prunning
+ auto temp = qFromUnaligned<typename QIntegerForSizeof<Float>::Unsigned>(&source);
+ temp = qbswap(temp);
+ return qFromUnaligned<Float>(&temp);
+}
+
+template <> inline qfloat16 qbswap<qfloat16>(qfloat16 source)
+{
+ return qbswapFloatHelper(source);
+}
+
+template <> inline float qbswap<float>(float source)
+{
+ return qbswapFloatHelper(source);
+}
+
+template <> inline double qbswap<double>(double source)
+{
+ return qbswapFloatHelper(source);
+}
+
/*
* qbswap(const T src, const void *dest);
* Changes the byte order of \a src from big endian to little endian or vice versa
@@ -157,6 +188,14 @@ template <typename T> inline void qbswap(const T src, void *dest)
qToUnaligned<T>(qbswap<T>(src), dest);
}
+template <int Size> void *qbswap(const void *source, qsizetype count, void *dest) noexcept;
+template<> inline void *qbswap<1>(const void *source, qsizetype count, void *dest) noexcept
+{
+ return source != dest ? memcpy(dest, source, size_t(count)) : dest;
+}
+template<> Q_CORE_EXPORT void *qbswap<2>(const void *source, qsizetype count, void *dest) noexcept;
+template<> Q_CORE_EXPORT void *qbswap<4>(const void *source, qsizetype count, void *dest) noexcept;
+template<> Q_CORE_EXPORT void *qbswap<8>(const void *source, qsizetype count, void *dest) noexcept;
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
@@ -172,6 +211,15 @@ template <typename T> inline void qToBigEndian(T src, void *dest)
{ qToUnaligned<T>(src, dest); }
template <typename T> inline void qToLittleEndian(T src, void *dest)
{ qbswap<T>(src, dest); }
+
+template <typename T> inline void qToBigEndian(const void *source, qsizetype count, void *dest)
+{ if (source != dest) memcpy(dest, source, count * sizeof(T)); }
+template <typename T> inline void qToLittleEndian(const void *source, qsizetype count, void *dest)
+{ qbswap<sizeof(T)>(source, count, dest); }
+template <typename T> inline void qFromBigEndian(const void *source, qsizetype count, void *dest)
+{ if (source != dest) memcpy(dest, source, count * sizeof(T)); }
+template <typename T> inline void qFromLittleEndian(const void *source, qsizetype count, void *dest)
+{ qbswap<sizeof(T)>(source, count, dest); }
#else // Q_LITTLE_ENDIAN
template <typename T> inline Q_DECL_CONSTEXPR T qToBigEndian(T source)
@@ -187,6 +235,14 @@ template <typename T> inline void qToBigEndian(T src, void *dest)
template <typename T> inline void qToLittleEndian(T src, void *dest)
{ qToUnaligned<T>(src, dest); }
+template <typename T> inline void qToBigEndian(const void *source, qsizetype count, void *dest)
+{ qbswap<sizeof(T)>(source, count, dest); }
+template <typename T> inline void qToLittleEndian(const void *source, qsizetype count, void *dest)
+{ if (source != dest) memcpy(dest, source, count * sizeof(T)); }
+template <typename T> inline void qFromBigEndian(const void *source, qsizetype count, void *dest)
+{ qbswap<sizeof(T)>(source, count, dest); }
+template <typename T> inline void qFromLittleEndian(const void *source, qsizetype count, void *dest)
+{ if (source != dest) memcpy(dest, source, count * sizeof(T)); }
#endif // Q_BYTE_ORDER == Q_BIG_ENDIAN
@@ -254,6 +310,27 @@ public:
{ return (*this = S::fromSpecial(val) & i); }
QSpecialInteger &operator ^=(T i)
{ return (*this = S::fromSpecial(val) ^ i); }
+ QSpecialInteger &operator ++()
+ { return (*this = S::fromSpecial(val) + 1); }
+ QSpecialInteger &operator --()
+ { return (*this = S::fromSpecial(val) - 1); }
+ QSpecialInteger operator ++(int)
+ {
+ QSpecialInteger<S> pre = *this;
+ *this += 1;
+ return pre;
+ }
+ QSpecialInteger operator --(int)
+ {
+ QSpecialInteger<S> pre = *this;
+ *this -= 1;
+ return pre;
+ }
+
+ static constexpr QSpecialInteger max()
+ { return QSpecialInteger(std::numeric_limits<T>::max()); }
+ static constexpr QSpecialInteger min()
+ { return QSpecialInteger(std::numeric_limits<T>::min()); }
};
template<typename T>
@@ -291,6 +368,13 @@ public:
QLEInteger &operator |=(T i);
QLEInteger &operator &=(T i);
QLEInteger &operator ^=(T i);
+ QLEInteger &operator ++();
+ QLEInteger &operator --();
+ QLEInteger &operator ++(int);
+ QLEInteger &operator --(int);
+
+ static constexpr QLEInteger max();
+ static constexpr QLEInteger min();
};
template<typename T>
@@ -311,6 +395,13 @@ public:
QBEInteger &operator |=(T i);
QBEInteger &operator &=(T i);
QBEInteger &operator ^=(T i);
+ QBEInteger &operator ++();
+ QBEInteger &operator --();
+ QBEInteger &operator ++(int);
+ QBEInteger &operator --(int);
+
+ static constexpr QBEInteger max();
+ static constexpr QBEInteger min();
};
#else
diff --git a/src/corelib/global/qendian.qdoc b/src/corelib/global/qendian.qdoc
deleted file mode 100644
index 65df25a205..0000000000
--- a/src/corelib/global/qendian.qdoc
+++ /dev/null
@@ -1,554 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE: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$
-**
-****************************************************************************/
-
-/*!
- \headerfile <QtEndian>
- \title Endian Conversion Functions
- \ingroup funclists
- \brief The <QtEndian> header provides functions to convert between
- little and big endian representations of numbers.
-*/
-
-/*!
- \fn template <typename T> T qFromUnaligned(const void *ptr)
- \internal
- \since 5.5
-
- Loads a \c{T} from address \a ptr, which may be misaligned.
-
- Use of this function avoids the undefined behavior that the C++ standard
- otherwise attributes to unaligned loads.
-*/
-
-/*!
- \fn template <typename T> void qToUnaligned(const T t, void *ptr)
- \internal
- \since 4.5
-
- Stores \a t to address \a ptr, which may be misaligned.
-
- Use of this function avoids the undefined behavior that the C++ standard
- otherwise attributes to unaligned stores.
-*/
-
-
-/*!
- \fn template <typename T> T qFromBigEndian(const void *src)
- \since 4.3
- \relates <QtEndian>
-
- Reads a big-endian number from memory location \a src and returns the number in the
- host byte order representation.
- On CPU architectures where the host byte order is little-endian (such as x86) this
- will swap the byte order; otherwise it will just read from \a src.
-
- \note Template type \c{T} can either be a qint16, qint32 or qint64. Other types of
- integers, e.g., qlong, are not applicable.
-
- \note Since Qt 5.7, the type of the \a src parameter is a void pointer.
-
- There are no data alignment constraints for \a src.
-
- \sa qFromLittleEndian()
- \sa qToBigEndian()
- \sa qToLittleEndian()
-*/
-/*!
- \fn template <typename T> T qFromBigEndian(T src)
- \since 4.3
- \relates <QtEndian>
- \overload
-
- Converts \a src from big-endian byte order and returns the number in host byte order
- representation of that number.
- On CPU architectures where the host byte order is little-endian (such as x86) this
- will return \a src with the byte order swapped; otherwise it will return \a src
- unmodified.
-*/
-/*!
- \fn template <typename T> T qFromLittleEndian(const void *src)
- \since 4.3
- \relates <QtEndian>
-
- Reads a little-endian number from memory location \a src and returns the number in
- the host byte order representation.
- On CPU architectures where the host byte order is big-endian (such as PowerPC) this
- will swap the byte order; otherwise it will just read from \a src.
-
- \note Template type \c{T} can either be a qint16, qint32 or qint64. Other types of
- integers, e.g., qlong, are not applicable.
-
- \note Since Qt 5.7, the type of the \a src parameter is a void pointer.
-
- There are no data alignment constraints for \a src.
-
- \sa qFromBigEndian()
- \sa qToBigEndian()
- \sa qToLittleEndian()
-*/
-/*!
- \fn template <typename T> T qFromLittleEndian(T src)
- \since 4.3
- \relates <QtEndian>
- \overload
-
- Converts \a src from little-endian byte order and returns the number in host byte
- order representation of that number.
- On CPU architectures where the host byte order is big-endian (such as PowerPC) this
- will return \a src with the byte order swapped; otherwise it will return \a src
- unmodified.
-*/
-/*!
- \fn template <typename T> void qToBigEndian(T src, void *dest)
- \since 4.3
- \relates <QtEndian>
-
- Writes the number \a src with template type \c{T} to the memory location at \a dest
- in big-endian byte order.
-
- Note that template type \c{T} can only be an integer data type (signed or unsigned).
-
- There are no data alignment constraints for \a dest.
-
- \note Since Qt 5.7, the type of the \a dest parameter is a void pointer.
-
- \sa qFromBigEndian()
- \sa qFromLittleEndian()
- \sa qToLittleEndian()
-*/
-/*!
- \fn template <typename T> T qToBigEndian(T src)
- \since 4.3
- \relates <QtEndian>
- \overload
-
- Converts \a src from host byte order and returns the number in big-endian byte order
- representation of that number.
- On CPU architectures where the host byte order is little-endian (such as x86) this
- will return \a src with the byte order swapped; otherwise it will return \a src
- unmodified.
-*/
-/*!
- \fn template <typename T> void qToLittleEndian(T src, void *dest)
- \since 4.3
- \relates <QtEndian>
-
- Writes the number \a src with template type \c{T} to the memory location at \a dest
- in little-endian byte order.
-
- Note that template type \c{T} can only be an integer data type (signed or unsigned).
-
- There are no data alignment constraints for \a dest.
-
- \note Since Qt 5.7, the type of the \a dest parameter is a void pointer.
-
- \sa qFromBigEndian()
- \sa qFromLittleEndian()
- \sa qToBigEndian()
-*/
-/*!
- \fn template <typename T> T qToLittleEndian(T src)
- \since 4.3
- \relates <QtEndian>
- \overload
-
- Converts \a src from host byte order and returns the number in little-endian byte
- order representation of that number.
- On CPU architectures where the host byte order is big-endian (such as PowerPC) this
- will return \a src with the byte order swapped; otherwise it will return \a src
- unmodified.
-*/
-
-/*!
- \class QLEInteger
- \inmodule QtCore
- \brief The QLEInteger class provides platform-independent little-endian integers.
- \since 5.10
-
- The template parameter \c T must be a C++ integer type:
- \list
- \li 8-bit: char, signed char, unsigned char, qint8, quint8
- \li 16-bit: short, unsigned short, qint16, quint16, char16_t
- \li 32-bit: int, unsigned int, qint32, quint32, char32_t
- \li 64-bit: long long, unsigned long long, qint64, quint64
- \li platform-specific size: long, unsigned long
- \li pointer size: qintptr, quintptr, qptrdiff
- \endlist
-
- \note Using this class may be slower than using native integers, so only use it when
- an exact endian is needed.
-*/
-
-/*! \fn template <typename T> QLEInteger<T>::QLEInteger(T value)
-
- Constructs a QLEInteger with the given \a value.
-*/
-
-/*! \fn template <typename T> QLEInteger &QLEInteger<T>::operator=(T i)
-
- Assigns \a i to this QLEInteger and returns a reference to
- this QLEInteger.
-*/
-
-/*!
- \fn template <typename T> QLEInteger<T>::operator T() const
-
- Returns the value of this QLEInteger as a native integer.
-*/
-
-/*!
- \fn template <typename T> bool QLEInteger<T>::operator==(QLEInteger other) const
-
- Returns \c true if the value of this QLEInteger is equal to the value of \a other.
-*/
-
-/*!
- \fn template <typename T> bool QLEInteger<T>::operator!=(QLEInteger other) const
-
- Returns \c true if the value of this QLEInteger is not equal to the value of \a other.
-*/
-
-/*!
- \fn template <typename T> QLEInteger &QLEInteger<T>::operator+=(T i)
-
- Adds \a i to this QLEInteger and returns a reference to
- this object.
-*/
-
-/*!
- \fn template <typename T> QLEInteger &QLEInteger<T>::operator-=(T i)
-
- Subtracts \a i from this QLEInteger and returns a reference to
- this object.
-*/
-
-/*!
- \fn template <typename T> QLEInteger &QLEInteger<T>::operator*=(T i)
-
- Multiplies \a i with this QLEInteger and returns a reference to
- this object.
-*/
-
-/*!
- \fn template <typename T> QLEInteger &QLEInteger<T>::operator/=(T i)
-
- Divides this QLEInteger with \a i and returns a reference to
- this object.
-*/
-
-/*!
- \fn template <typename T> QLEInteger &QLEInteger<T>::operator%=(T i)
-
- Sets this QLEInteger to the remainder of a division by \a i and
- returns a reference to this object.
-*/
-
-/*!
- \fn template <typename T> QLEInteger &QLEInteger<T>::operator>>=(T i)
-
- Performs a left-shift by \a i on this QLEInteger and returns a
- reference to this object.
-*/
-
-/*!
- \fn template <typename T> QLEInteger &QLEInteger<T>::operator<<=(T i)
-
- Performs a right-shift by \a i on this QLEInteger and returns a
- reference to this object.
-*/
-
-/*!
- \fn template <typename T> QLEInteger &QLEInteger<T>::operator|=(T i)
-
- Performs a bitwise OR with \a i onto this QLEInteger and returns a reference to
- this object.
-*/
-
-/*!
- \fn template <typename T> QLEInteger &QLEInteger<T>::operator&=(T i)
-
- Performs a bitwise AND with \a i onto this QLEInteger and returns a reference to
- this object.
-*/
-
-/*!
- \fn template <typename T> QLEInteger &QLEInteger<T>::operator^=(T i)
-
- Performs a bitwise XOR with \a i onto this QLEInteger and returns a reference to
- this object.
-*/
-
-/*!
- \class QBEInteger
- \inmodule QtCore
- \brief The QBEInteger class provides platform-independent big-endian integers.
- \since 5.10
-
- The template parameter \c T must be a C++ integer type:
- \list
- \li 8-bit: char, signed char, unsigned char, qint8, quint8
- \li 16-bit: short, unsigned short, qint16, quint16, char16_t (C++11)
- \li 32-bit: int, unsigned int, qint32, quint32, char32_t (C++11)
- \li 64-bit: long long, unsigned long long, qint64, quint64
- \li platform-specific size: long, unsigned long
- \li pointer size: qintptr, quintptr, qptrdiff
- \endlist
-
- \note Using this class may be slower than using native integers, so only use it when
- an exact endian is needed.
-*/
-
-/*! \fn template <typename T> QBEInteger<T>::QBEInteger(T value)
-
- Constructs a QBEInteger with the given \a value.
-*/
-
-/*! \fn template <typename T> QBEInteger &QBEInteger<T>::operator=(T i)
-
- Assigns \a i to this QBEInteger and returns a reference to
- this QBEInteger.
-*/
-
-/*!
- \fn template <typename T> QBEInteger<T>::operator T() const
-
- Returns the value of this QBEInteger as a native integer.
-*/
-
-/*!
- \fn template <typename T> bool QBEInteger<T>::operator==(QBEInteger other) const
-
- Returns \c true if the value of this QBEInteger is equal to the value of \a other.
-*/
-
-/*!
- \fn template <typename T> bool QBEInteger<T>::operator!=(QBEInteger other) const
-
- Returns \c true if the value of this QBEInteger is not equal to the value of \a other.
-*/
-
-/*!
- \fn template <typename T> QBEInteger &QBEInteger<T>::operator+=(T i)
-
- Adds \a i to this QBEInteger and returns a reference to
- this object.
-*/
-
-/*!
- \fn template <typename T> QBEInteger &QBEInteger<T>::operator-=(T i)
-
- Subtracts \a i from this QBEInteger and returns a reference to
- this object.
-*/
-
-/*!
- \fn template <typename T> QBEInteger &QBEInteger<T>::operator*=(T i)
-
- Multiplies \a i with this QBEInteger and returns a reference to
- this object.
-*/
-
-/*!
- \fn template <typename T> QBEInteger &QBEInteger<T>::operator/=(T i)
-
- Divides this QBEInteger with \a i and returns a reference to
- this object.
-*/
-
-/*!
- \fn template <typename T> QBEInteger &QBEInteger<T>::operator%=(T i)
-
- Sets this QBEInteger to the remainder of a division by \a i and
- returns a reference to this object.
-*/
-
-/*!
- \fn template <typename T> QBEInteger &QBEInteger<T>::operator>>=(T i)
-
- Performs a left-shift by \a i on this QBEInteger and returns a
- reference to this object.
-*/
-
-/*!
- \fn template <typename T> QBEInteger &QBEInteger<T>::operator<<=(T i)
-
- Performs a right-shift by \a i on this QBEInteger and returns a
- reference to this object.
-*/
-
-/*!
- \fn template <typename T> QBEInteger &QBEInteger<T>::operator|=(T i)
-
- Performs a bitwise OR with \a i onto this QBEInteger and returns a reference to
- this object.
-*/
-
-/*!
- \fn template <typename T> QBEInteger &QBEInteger<T>::operator&=(T i)
-
- Performs a bitwise AND with \a i onto this QBEInteger and returns a reference to
- this object.
-*/
-
-/*!
- \fn template <typename T> QBEInteger &QBEInteger<T>::operator^=(T i)
-
- Performs a bitwise XOR with \a i onto this QBEInteger and returns a reference to
- this object.
-*/
-
-/*!
- \typedef quint16_le
- \relates <QtEndian>
- \since 5.10
-
- Typedef for QLEInteger<quint16>. This type is guaranteed to be stored in memory as
- a 16-bit little-endian unsigned integer on all platforms supported by Qt.
-
- \sa quint16
-*/
-
-/*!
- \typedef quint32_le
- \relates <QtEndian>
- \since 5.10
-
- Typedef for QLEInteger<quint32>. This type is guaranteed to be stored in memory as
- a 32-bit little-endian unsigned integer on all platforms supported by Qt.
-
- \sa quint32
-*/
-
-/*!
- \typedef quint64_le
- \relates <QtEndian>
- \since 5.10
-
- Typedef for QLEInteger<quint64>. This type is guaranteed to be stored in memory as
- a 64-bit little-endian unsigned integer on all platforms supported by Qt.
-
- \sa quint64
-*/
-
-/*!
- \typedef quint16_be
- \relates <QtEndian>
- \since 5.10
-
- Typedef for QBEInteger<quint16>. This type is guaranteed to be stored in memory as
- a 16-bit big-endian unsigned integer on all platforms supported by Qt.
-
- \sa quint16
-*/
-
-/*!
- \typedef quint32_be
- \relates <QtEndian>
- \since 5.10
-
- Typedef for QBEInteger<quint32>. This type is guaranteed to be stored in memory as
- a 32-bit big-endian unsigned integer on all platforms supported by Qt.
-
- \sa quint32
-*/
-
-/*!
- \typedef quint64_be
- \relates <QtEndian>
- \since 5.10
-
- Typedef for QBEInteger<quint64>. This type is guaranteed to be stored in memory as
- a 64-bit big-endian unsigned integer on all platforms supported by Qt.
-
- \sa quint64
-*/
-
-/*!
- \typedef qint16_le
- \relates <QtEndian>
- \since 5.10
-
- Typedef for QLEInteger<qint16>. This type is guaranteed to be stored in memory as
- a 16-bit little-endian signed integer on all platforms supported by Qt.
-
- \sa qint16
-*/
-
-/*!
- \typedef qint32_le
- \relates <QtEndian>
- \since 5.10
-
- Typedef for QLEInteger<qint32>. This type is guaranteed to be stored in memory as
- a 32-bit little-endian signed integer on all platforms supported by Qt.
-
- \sa qint32
-*/
-
-/*!
- \typedef qint64_le
- \relates <QtEndian>
- \since 5.10
-
- Typedef for QLEInteger<qint64>. This type is guaranteed to be stored in memory as
- a 64-bit little-endian signed integer on all platforms supported by Qt.
-
- \sa qint64
-*/
-
-/*!
- \typedef qint16_be
- \relates <QtEndian>
- \since 5.10
-
- Typedef for QBEInteger<qint16>. This type is guaranteed to be stored in memory as
- a 16-bit big-endian signed integer on all platforms supported by Qt.
-
- \sa qint16
-*/
-
-/*!
- \typedef qint32_be
- \relates <QtEndian>
- \since 5.10
-
- Typedef for QBEInteger<qint32>. This type is guaranteed to be stored in memory as
- a 32-bit big-endian signed integer on all platforms supported by Qt.
-
- \sa qint32
-*/
-
-/*!
- \typedef qint64_be
- \relates <QtEndian>
- \since 5.10
-
- Typedef for QBEInteger<qint64>. This type is guaranteed to be stored in memory as
- a 64-bit big-endian signed integer on all platforms supported by Qt.
-
- \sa qint64
-*/
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index b30d690025..5c1665fa00 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -53,10 +53,6 @@
#include <qmutex.h>
-#ifndef QT_NO_QOBJECT
-#include <private/qthread_p.h>
-#endif
-
#include <stdlib.h>
#include <limits.h>
#include <stdarg.h>
@@ -650,7 +646,8 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value));
The remaining macros are convenience macros for larger operations:
The QT_TR_NOOP(), QT_TRANSLATE_NOOP(), and QT_TRANSLATE_NOOP3()
macros provide the possibility of marking strings for delayed
- translation.
+ translation. QT_TR_N_NOOP(), QT_TRANSLATE_N_NOOP(), and
+ QT_TRANSLATE_N_NOOP3() are numerator dependent variants of these.
The Q_ASSERT() and Q_ASSERT_X() enables warning messages of various
level of refinement. The Q_FOREACH() and foreach() macros
implement Qt's foreach loop.
@@ -3379,9 +3376,7 @@ QString qEnvironmentVariable(const char *varName)
Returns whether the environment variable \a varName is empty.
Equivalent to
- \code
- qgetenv(varName).isEmpty()
- \endcode
+ \snippet code/src_corelib_global_qglobal.cpp is-empty
except that it's potentially much faster, and can't throw exceptions.
\sa qgetenv(), qEnvironmentVariable(), qEnvironmentVariableIsSet()
@@ -3411,9 +3406,7 @@ bool qEnvironmentVariableIsEmpty(const char *varName) Q_DECL_NOEXCEPT
on the success of the conversion.
Equivalent to
- \code
- qgetenv(varName).toInt(ok, 0)
- \endcode
+ \snippet code/src_corelib_global_qglobal.cpp to-int
except that it's much faster, and can't throw exceptions.
\note there's a limit on the length of the value, which is sufficient for
@@ -3450,7 +3443,27 @@ int qEnvironmentVariableIntValue(const char *varName, bool *ok) Q_DECL_NOEXCEPT
bool ok_ = true;
const char *endptr;
const qlonglong value = qstrtoll(buffer, &endptr, 0, &ok_);
- if (int(value) != value || *endptr != '\0') { // this is the check in QByteArray::toInt(), keep it in sync
+
+ // Keep the following checks in sync with QByteArray::toInt()
+ if (!ok_) {
+ if (ok)
+ *ok = false;
+ return 0;
+ }
+
+ if (*endptr != '\0') {
+ while (ascii_isspace(*endptr))
+ ++endptr;
+ }
+
+ if (*endptr != '\0') {
+ // we stopped at a non-digit character after converting some digits
+ if (ok)
+ *ok = false;
+ return 0;
+ }
+
+ if (int(value) != value) {
if (ok)
*ok = false;
return 0;
@@ -3467,9 +3480,7 @@ int qEnvironmentVariableIntValue(const char *varName, bool *ok) Q_DECL_NOEXCEPT
Returns whether the environment variable \a varName is set.
Equivalent to
- \code
- !qgetenv(varName).isNull()
- \endcode
+ \snippet code/src_corelib_global_qglobal.cpp is-null
except that it's potentially much faster, and can't throw exceptions.
\sa qgetenv(), qEnvironmentVariable(), qEnvironmentVariableIsEmpty()
@@ -3645,37 +3656,21 @@ bool qunsetenv(const char *varName)
Its main use in Qt is to prevent implicitly-shared Qt containers
from detaching:
- \code
- QString s = ...;
- for (QChar ch : s) // detaches 's' (performs a deep-copy if 's' was shared)
- process(ch);
- for (QChar ch : qAsConst(s)) // ok, no detach attempt
- process(ch);
- \endcode
+ \snippet code/src_corelib_global_qglobal.cpp as-const-0
Of course, in this case, you could (and probably should) have declared
\c s as \c const in the first place:
- \code
- const QString s = ...;
- for (QChar ch : s) // ok, no detach attempt on const objects
- process(ch);
- \endcode
+ \snippet code/src_corelib_global_qglobal.cpp as-const-1
but often that is not easily possible.
It is important to note that qAsConst() does not copy its argument,
it just performs a \c{const_cast<const T&>(t)}. This is also the reason
why it is designed to fail for rvalues: The returned reference would go
stale too soon. So while this works (but detaches the returned object):
- \code
- for (QChar ch : funcReturningQString())
- process(ch); // OK, the returned object is kept alive for the loop's duration
- \endcode
+ \snippet code/src_corelib_global_qglobal.cpp as-const-2
this would not:
- \code
- for (QChar ch : qAsConst(funcReturningQString()))
- process(ch); // ERROR: ch is copied from deleted memory
- \endcode
+ \snippet code/src_corelib_global_qglobal.cpp as-const-3
To prevent this construct from compiling (and failing at runtime), qAsConst() has
a second, deleted, overload which binds to rvalues.
@@ -3688,10 +3683,7 @@ bool qunsetenv(const char *varName)
\overload
This overload is deleted to prevent a dangling reference in code like
- \code
- for (QChar ch : qAsConst(funcReturningQString()))
- process(ch); // ERROR: ch is copied from deleted memory
- \endcode
+ \snippet code/src_corelib_global_qglobal.cpp as-const-4
*/
/*!
@@ -3755,6 +3747,71 @@ bool qunsetenv(const char *varName)
*/
/*!
+ \macro QT_TR_N_NOOP(sourceText)
+ \relates <QtGlobal>
+ \since 5.12
+
+ Marks the UTF-8 encoded string literal \a sourceText for numerator
+ dependent delayed translation in the current context (class).
+
+ The macro tells lupdate to collect the string, and expands to
+ \a sourceText itself.
+
+ The macro expands to \a sourceText.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp qttrnnoop
+
+ \sa QT_TR_NOOP, {Internationalization with Qt}
+*/
+
+/*!
+ \macro QT_TRANSLATE_N_NOOP(context, sourceText)
+ \relates <QtGlobal>
+ \since 5.12
+
+ Marks the UTF-8 encoded string literal \a sourceText for numerator
+ dependent delayed translation in the given \a context.
+ The \a context is typically a class name and also needs to be
+ specified as a string literal.
+
+ The macro tells lupdate to collect the string, and expands to
+ \a sourceText itself.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp qttranslatennoop
+
+ \sa QT_TRANSLATE_NOOP(), QT_TRANSLATE_N_NOOP3(),
+ {Internationalization with Qt}
+*/
+
+/*!
+ \macro QT_TRANSLATE_N_NOOP3(context, sourceText, comment)
+ \relates <QtGlobal>
+ \since 5.12
+
+ Marks the UTF-8 encoded string literal \a sourceText for numerator
+ dependent delayed translation in the given \a context with the given
+ \a comment.
+ The \a context is typically a class and also needs to be specified
+ as a string literal. The string literal \a disambiguation should be
+ a short semantic tag to tell apart otherwise identical strings.
+
+ The macro tells lupdate to collect the string, and expands to an
+ anonymous struct of the two string literals passed as \a sourceText
+ and \a comment.
+
+ Example:
+
+ \snippet code/src_corelib_global_qglobal.cpp qttranslatennoop3
+
+ \sa QT_TR_NOOP(), QT_TRANSLATE_NOOP(), QT_TRANSLATE_NOOP3(),
+ {Internationalization with Qt}
+*/
+
+/*!
\fn QString qtTrId(const char *id, int n = -1)
\relates <QtGlobal>
\reentrant
@@ -4560,9 +4617,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
purpose. It either expands to \c expr (if Qt is compiled without
exception support or the compiler supports C++11 noexcept
semantics) or to
- \code
- try { expr; } catch(...) { qTerminate(); }
- \endcode
+ \snippet code/src_corelib_global_qglobal.cpp qterminate
otherwise.
Since this macro expands to just \c expr if the compiler supports
@@ -4632,10 +4687,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
The macro goes at the end of the function, usually after the
\c{const}, if any:
- \code
- // generate error if this doesn't actually override anything:
- virtual void MyWidget::paintEvent(QPaintEvent*) Q_DECL_OVERRIDE;
- \endcode
+ \snippet code/src_corelib_global_qglobal.cpp qdecloverride
\sa Q_DECL_FINAL
*/
@@ -4657,18 +4709,11 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
The macro goes at the end of the function, usually after the
\c{const}, if any:
- \code
- // more-derived classes no longer permitted to override this:
- virtual void MyWidget::paintEvent(QPaintEvent*) Q_DECL_FINAL;
- \endcode
+ \snippet code/src_corelib_global_qglobal.cpp qdeclfinal-1
For classes, it goes in front of the \c{:} in the class
definition, if any:
- \code
- class QRect Q_DECL_FINAL { // cannot be derived from
- // ...
- };
- \endcode
+ \snippet code/src_corelib_global_qglobal.cpp qdeclfinal-2
\sa Q_DECL_OVERRIDE
*/
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 3684c6b5de..b608489576 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -1034,8 +1034,8 @@ for (auto _container_ = QtPrivate::qMakeForeachContainer(container); \
# endif
#endif
-template <typename T> static inline T *qGetPtrHelper(T *ptr) { return ptr; }
-template <typename Wrapper> static inline typename Wrapper::pointer qGetPtrHelper(const Wrapper &p) { return p.data(); }
+template <typename T> inline T *qGetPtrHelper(T *ptr) { return ptr; }
+template <typename Ptr> inline auto qGetPtrHelper(const Ptr &ptr) -> decltype(ptr.operator->()) { return ptr.operator->(); }
#define Q_DECLARE_PRIVATE(Class) \
inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr)); } \
@@ -1064,6 +1064,10 @@ template <typename Wrapper> static inline typename Wrapper::pointer qGetPtrHelpe
#ifndef QT_NO_TRANSLATION // ### Qt6: This should enclose the NOOPs above
+#define QT_TR_N_NOOP(x) x
+#define QT_TRANSLATE_N_NOOP(scope, x) x
+#define QT_TRANSLATE_N_NOOP3(scope, x, comment) {x, comment}
+
// Defined in qcoreapplication.cpp
// The better name qTrId() is reserved for an upcoming function which would
// return a much more powerful QStringFormatter instead of a QString.
diff --git a/src/corelib/global/qglobalstatic.h b/src/corelib/global/qglobalstatic.h
index 7a6dea9b92..555bdf04c1 100644
--- a/src/corelib/global/qglobalstatic.h
+++ b/src/corelib/global/qglobalstatic.h
@@ -55,7 +55,7 @@ enum GuardValues {
};
}
-#if defined(QT_NO_THREAD) || defined(Q_COMPILER_THREADSAFE_STATICS)
+#if !QT_CONFIG(thread) || defined(Q_COMPILER_THREADSAFE_STATICS)
// some compilers support thread-safe statics
// The IA-64 C++ ABI requires this, so we know that all GCC versions since 3.4
// support it. C++11 also requires this behavior.
diff --git a/src/corelib/global/qglobalstatic.qdoc b/src/corelib/global/qglobalstatic.qdoc
index 303709bb1d..dbea04ecab 100644
--- a/src/corelib/global/qglobalstatic.qdoc
+++ b/src/corelib/global/qglobalstatic.qdoc
@@ -264,7 +264,7 @@
[stmt.decl], but as of the time of this writing, only compilers based on
the IA-64 C++ ABI implemented it properly. The implementation requiring
thread-safe initialization is also used on the Qt bootstrapped tools, which
- define QT_NO_THREAD.
+ disable the "thread" feature.
The implementation requiring thread-safe initialization from the compiler
is the simplest: it creates the \a Type object as a function-local static
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index 563e658c65..396aee8696 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -2,7 +2,7 @@
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com>
-** Copyright (C) 2016 Intel Corporation.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -61,6 +61,9 @@
#ifdef Q_OS_WIN
#include <qt_windows.h>
#endif
+#ifdef Q_CC_MSVC
+#include <intrin.h>
+#endif
#if QT_CONFIG(slog2)
#include <sys/slog2.h>
#endif
@@ -91,6 +94,10 @@
# include "private/qcore_unix_p.h"
#endif
+#ifdef Q_OS_WASM
+#include <emscripten/emscripten.h>
+#endif
+
#if QT_CONFIG(regularexpression)
# ifdef __UCLIBC__
# if __UCLIBC_HAS_BACKTRACE__
@@ -240,7 +247,7 @@ static bool systemHasStderr()
\internal
\sa systemHasStderr()
*/
-bool stderrHasConsoleAttached()
+static bool stderrHasConsoleAttached()
{
static const bool stderrHasConsoleAttached = []() -> bool {
if (!systemHasStderr())
@@ -1208,8 +1215,8 @@ void QMessagePattern::setPattern(const QString &pattern)
tokens[i] = backtraceTokenC;
QString backtraceSeparator = QStringLiteral("|");
int backtraceDepth = 5;
- QRegularExpression depthRx(QStringLiteral(" depth=(?|\"([^\"]*)\"|([^ }]*))"));
- QRegularExpression separatorRx(QStringLiteral(" separator=(?|\"([^\"]*)\"|([^ }]*))"));
+ static const QRegularExpression depthRx(QStringLiteral(" depth=(?|\"([^\"]*)\"|([^ }]*))"));
+ static const QRegularExpression separatorRx(QStringLiteral(" separator=(?|\"([^\"]*)\"|([^ }]*))"));
QRegularExpressionMatch m = depthRx.match(lexeme);
if (m.hasMatch()) {
int depth = m.capturedRef(1).toInt();
@@ -1295,8 +1302,7 @@ static QStringList backtraceFramesForLogMessage(int frameCount)
// The offset and function name are optional.
// This regexp tries to extract the library name (without the path) and the function name.
// This code is protected by QMessagePattern::mutex so it is thread safe on all compilers
- static QRegularExpression rx(QStringLiteral("^(?:[^(]*/)?([^(/]+)\\(([^+]*)(?:[\\+[a-f0-9x]*)?\\) \\[[a-f0-9x]*\\]$"),
- QRegularExpression::OptimizeOnFirstUsageOption);
+ static const QRegularExpression rx(QStringLiteral("^(?:[^(]*/)?([^(/]+)\\(([^+]*)(?:[\\+[a-f0-9x]*)?\\) \\[[a-f0-9x]*\\]$"));
QVarLengthArray<void*, 32> buffer(8 + frameCount);
int n = backtrace(buffer.data(), buffer.size());
@@ -1686,6 +1692,37 @@ static bool win_message_handler(QtMsgType type, const QMessageLogContext &contex
}
#endif
+#ifdef Q_OS_WASM
+static bool wasm_default_message_handler(QtMsgType type,
+ const QMessageLogContext &context,
+ const QString &message)
+{
+ if (shouldLogToStderr())
+ return false; // Leave logging up to stderr handler
+
+ QString formattedMessage = qFormatLogMessage(type, context, message);
+ int emOutputFlags = (EM_LOG_CONSOLE | EM_LOG_DEMANGLE);
+ QByteArray localMsg = message.toLocal8Bit();
+ switch (type) {
+ case QtDebugMsg:
+ break;
+ case QtInfoMsg:
+ break;
+ case QtWarningMsg:
+ emOutputFlags |= EM_LOG_WARN;
+ break;
+ case QtCriticalMsg:
+ emOutputFlags |= EM_LOG_ERROR;
+ break;
+ case QtFatalMsg:
+ emOutputFlags |= EM_LOG_ERROR;
+ }
+ emscripten_log(emOutputFlags, "%s\n", qPrintable(formattedMessage));
+
+ return true; // Prevent further output to stderr
+}
+#endif
+
#endif // Bootstrap check
// --------------------------------------------------------------------------
@@ -1729,8 +1766,9 @@ static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &con
# elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
handledStderr |= android_default_message_handler(type, context, message);
# elif defined(QT_USE_APPLE_UNIFIED_LOGGING)
- if (__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *))
- handledStderr |= AppleUnifiedLogger::messageHandler(type, context, message);
+ handledStderr |= AppleUnifiedLogger::messageHandler(type, context, message);
+# elif defined Q_OS_WASM
+ handledStderr |= wasm_default_message_handler(type, context, message);
# endif
#endif
@@ -1837,7 +1875,31 @@ static void qt_message_fatal(QtMsgType, const QMessageLogContext &context, const
Q_UNUSED(message);
#endif
+#ifdef Q_OS_WIN
+ // std::abort() in the MSVC runtime will call _exit(3) if the abort
+ // behavior is _WRITE_ABORT_MSG - see also _set_abort_behavior(). This is
+ // the default for a debug-mode build of the runtime. Worse, MinGW's
+ // std::abort() implementation (in msvcrt.dll) is basically a call to
+ // _exit(3) too. Unfortunately, _exit() and _Exit() *do* run the static
+ // destructors of objects in DLLs, a violation of the C++ standard (see
+ // [support.start.term]). So we bypass std::abort() and directly
+ // terminate the application.
+
+# ifdef Q_CC_MSVC
+ if (IsProcessorFeaturePresent(PF_FASTFAIL_AVAILABLE))
+ __fastfail(FAST_FAIL_FATAL_APP_EXIT);
+# else
+ RaiseFailFastException(nullptr, nullptr, 0);
+# endif
+
+ // Fallback
+ TerminateProcess(GetCurrentProcess(), STATUS_FATAL_APP_EXIT);
+
+ // Tell the compiler the application has stopped.
+ Q_UNREACHABLE_IMPL();
+#else // !Q_OS_WIN
std::abort();
+#endif
}
@@ -2000,9 +2062,7 @@ void qErrnoWarning(int code, const char *msg, ...)
is not the default one.
Example:
- \code
- QT_MESSAGE_PATTERN="[%{time yyyyMMdd h:mm:ss.zzz t} %{if-debug}D%{endif}%{if-info}I%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}] %{file}:%{line} - %{message}"
- \endcode
+ \snippet code/src_corelib_global_qlogging.cpp 0
The default \a pattern is "%{if-category}%{category}: %{endif}%{message}".
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index 31b1823690..dec2c44637 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -107,6 +107,7 @@ public:
KeyboardModifierMask = 0xfe000000
};
Q_DECLARE_FLAGS(KeyboardModifiers, KeyboardModifier)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(KeyboardModifiers)
//shorter names for shortcuts
// The use of all-caps identifiers has the potential for clashing with
@@ -163,6 +164,7 @@ public:
MouseButtonMask = 0xffffffff
};
Q_DECLARE_FLAGS(MouseButtons, MouseButton)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(MouseButtons)
enum Orientation {
Horizontal = 0x1,
@@ -170,6 +172,7 @@ public:
};
Q_DECLARE_FLAGS(Orientations, Orientation)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(Orientations)
enum FocusPolicy {
NoFocus = 0,
@@ -225,6 +228,7 @@ public:
};
Q_DECLARE_FLAGS(Alignment, AlignmentFlag)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(Alignment)
enum TextFlag {
TextSingleLine = 0x0100,
@@ -308,6 +312,7 @@ public:
};
Q_DECLARE_FLAGS(WindowFlags, WindowType)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(WindowFlags)
enum WindowState {
WindowNoState = 0x00000000,
@@ -318,6 +323,7 @@ public:
};
Q_DECLARE_FLAGS(WindowStates, WindowState)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(WindowStates)
enum ApplicationState {
ApplicationSuspended = 0x00000000,
@@ -337,6 +343,7 @@ public:
};
Q_DECLARE_FLAGS(ScreenOrientations, ScreenOrientation)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(ScreenOrientations)
enum WidgetAttribute {
WA_Disabled = 0,
@@ -479,6 +486,8 @@ public:
WA_ContentsMarginsRespectsSafeArea = 130,
+ WA_StyleSheetTarget = 131,
+
// Add new attributes before this line
WA_AttributeCount
};
@@ -553,6 +562,7 @@ public:
NoFormatConversion = 0x00000200
};
Q_DECLARE_FLAGS(ImageConversionFlags, ImageConversionFlag)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(ImageConversionFlags)
enum BGMode {
TransparentMode,
@@ -1210,6 +1220,7 @@ public:
};
Q_DECLARE_FLAGS(DockWidgetAreas, DockWidgetArea)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(DockWidgetAreas)
enum ToolBarArea {
LeftToolBarArea = 0x1,
@@ -1227,6 +1238,7 @@ public:
};
Q_DECLARE_FLAGS(ToolBarAreas, ToolBarArea)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(ToolBarAreas)
enum DateFormat {
TextDate, // default Qt
@@ -1285,6 +1297,7 @@ public:
};
Q_DECLARE_FLAGS(Edges, Edge)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(Edges)
enum ConnectionType {
AutoConnection,
@@ -1387,6 +1400,7 @@ public:
ImQueryAll = 0xffffffff
};
Q_DECLARE_FLAGS(InputMethodQueries, InputMethodQuery)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(InputMethodQueries)
enum InputMethodHint {
ImhNone = 0x0,
@@ -1421,6 +1435,7 @@ public:
ImhExclusiveInputMask = 0xffff0000
};
Q_DECLARE_FLAGS(InputMethodHints, InputMethodHint)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(InputMethodHints)
enum EnterKeyType {
EnterKeyDefault,
@@ -1471,6 +1486,7 @@ public:
IgnoreAction = 0x0
};
Q_DECLARE_FLAGS(DropActions, DropAction)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(DropActions)
enum CheckState {
Unchecked,
@@ -1525,6 +1541,7 @@ public:
ItemIsUserTristate = 256
};
Q_DECLARE_FLAGS(ItemFlags, ItemFlag)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(ItemFlags)
enum MatchFlag {
MatchExactly = 0,
@@ -1539,6 +1556,7 @@ public:
MatchRecursive = 64
};
Q_DECLARE_FLAGS(MatchFlags, MatchFlag)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(MatchFlags)
typedef void * HANDLE;
#if QT_DEPRECATED_SINCE(5, 0)
@@ -1563,6 +1581,7 @@ public:
TextBrowserInteraction = TextSelectableByMouse | LinksAccessibleByMouse | LinksAccessibleByKeyboard
};
Q_DECLARE_FLAGS(TextInteractionFlags, TextInteractionFlag)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(TextInteractionFlags)
enum EventPriority {
HighEventPriority = 1,
@@ -1614,6 +1633,7 @@ public:
TouchPointReleased = 0x08
};
Q_DECLARE_FLAGS(TouchPointStates, TouchPointState)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(TouchPointStates)
#ifndef QT_NO_GESTURES
enum GestureState
@@ -1645,6 +1665,7 @@ public:
IgnoredGesturesPropagateToParent = 0x04
};
Q_DECLARE_FLAGS(GestureFlags, GestureFlag)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(GestureFlags)
enum NativeGestureType
{
@@ -1683,7 +1704,8 @@ public:
NoScrollPhase = 0,
ScrollBegin,
ScrollUpdate,
- ScrollEnd
+ ScrollEnd,
+ ScrollMomentum
};
enum MouseEventSource {
@@ -1698,6 +1720,7 @@ public:
MouseEventFlagMask = 0xFF
};
Q_DECLARE_FLAGS(MouseEventFlags, MouseEventFlag)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(MouseEventFlags)
enum ChecksumType {
ChecksumIso3309,
@@ -1800,29 +1823,6 @@ public:
#undef QT_Q_ENUM
#undef QT_Q_FLAG
-Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::MouseButtons)
-Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::Orientations)
-Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::KeyboardModifiers)
-Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::WindowFlags)
-Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::Alignment)
-Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::Edges)
-Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::ImageConversionFlags)
-Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::DockWidgetAreas)
-Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::ToolBarAreas)
-Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::WindowStates)
-Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::ScreenOrientations)
-Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::DropActions)
-Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::ItemFlags)
-Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::MatchFlags)
-Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::TextInteractionFlags)
-Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::InputMethodQueries)
-Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::InputMethodHints)
-Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::TouchPointStates)
-Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::MouseEventFlags)
-#ifndef QT_NO_GESTURES
-Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::GestureFlags)
-#endif
-
typedef bool (*qInternalCallback)(void **);
class Q_CORE_EXPORT QInternal {
@@ -1864,16 +1864,6 @@ public:
static bool activateCallbacks(Callback, void **);
};
-#if defined(Q_CLANG_QDOC)
-// Declared here for qdoc; actual declarations in qtextdocument.h
-namespace Qt
-{
- bool mightBeRichText(const QString&);
- QString convertFromPlainText(const QString &plain, WhiteSpaceMode mode = WhiteSpacePre);
- QTextCodec *codecForHtml(const QByteArray &ba);
-}
-#endif // Q_CLANG_QDOC
-
QT_END_NAMESPACE
#endif // QNAMESPACE_H
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index d6191d1585..42009e0b5e 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -245,7 +245,10 @@
QEvent::MouseMove, QEvent::TouchUpdate, and changes in window size and
position will be combined whenever they occur more frequently than the
application handles them, so that they don't accumulate and overwhelm the
- application later. On other platforms, the default is false.
+ application later.
+ On Windows 8 and above the default value is also true, but it only applies
+ to touch events. Mouse and window events remain unaffected by this flag.
+ On other platforms, the default is false.
(In the future, the compression feature may be implemented across platforms.)
You can test the attribute to see whether compression is enabled.
If your application needs to handle all events with no compression,
@@ -256,8 +259,9 @@
\value AA_CompressTabletEvents Enables compression of input events from tablet devices.
Notice that AA_CompressHighFrequencyEvents must be true for events compression
- to be enabled, and that this flag extends the former to tablet events. Its default
- value is false.
+ to be enabled, and that this flag extends the former to tablet events.
+ Currently supported on the X11 windowing system, Windows 8 and above.
+ The default value is false.
This value was added in Qt 5.10.
\value AA_DontCheckOpenGLContextThreadAffinity When making a context
@@ -383,7 +387,8 @@
\value AltModifier An Alt key on the keyboard is pressed.
\value MetaModifier A Meta key on the keyboard is pressed.
\value KeypadModifier A keypad button is pressed.
- \value GroupSwitchModifier X11 only. A Mode_switch key on the keyboard is pressed.
+ \value GroupSwitchModifier X11 only (unless activated on Windows by a command line argument).
+ A Mode_switch key on the keyboard is pressed.
\omitvalue KeyboardModifierMask
@@ -1155,7 +1160,12 @@
the widget's author.
\value WA_StyleSheet Indicates that the widget is styled using a
- \l{Qt Style Sheets}{style sheet}.
+ \l{Qt Style Sheets}{style sheet}. WA_StyleSheet is set whenever a widget
+ is subject to a style sheet, even if the style sheet did not affect the
+ widget appearance.
+
+ \value WA_StyleSheetTarget Indicates that the widget appearance was modified
+ by a \l{Qt Style Sheets}{style sheet}. WA_StyleSheet will also be set.
\value WA_TabletTracking Indicates that the widget has tablet
tracking enabled. See QWidget::tabletTracking.
@@ -3232,37 +3242,3 @@
\value ChecksumItuV41 Checksum calculation based on ITU-V.41.
*/
-
-/*!
- \fn bool Qt::mightBeRichText(const QString& text)
-
- Returns \c true if the string \a text is likely to be rich text;
- otherwise returns \c false.
-
- This function uses a fast and therefore simple heuristic. It
- mainly checks whether there is something that looks like a tag
- before the first line break. Although the result may be correct
- for common cases, there is no guarantee.
-
- This function is defined in the \c <QTextDocument> header file.
-*/
-
-/*!
- \fn QString Qt::convertFromPlainText(const QString &plain, Qt::WhiteSpaceMode mode)
-
- Converts the plain text string \a plain to an HTML-formatted
- paragraph while preserving most of its look.
-
- \a mode defines how whitespace is handled.
-
- This function is defined in the \c <QTextDocument> header file.
-
- \sa escape(), mightBeRichText()
-*/
-
-/*!
- \fn QTextCodec *Qt::codecForHtml(const QByteArray &ba)
- \internal
-
- This function is defined in the \c <QTextDocument> header file.
-*/
diff --git a/src/corelib/global/qnumeric.cpp b/src/corelib/global/qnumeric.cpp
index c03b139c9f..fc2b052edf 100644
--- a/src/corelib/global/qnumeric.cpp
+++ b/src/corelib/global/qnumeric.cpp
@@ -130,12 +130,7 @@ static inline quint32 f2i(float f)
two 32-bit floating point numbers and all you need is an approximated 24-bit precision, you can
use this function like this:
- \code
- if (qFloatDistance(a, b) < (1 << 7)) { // The last 7 bits are not
- // significant
- // precise enough
- }
- \endcode
+ \snippet code/src_corelib_global_qnumeric.cpp 0
\sa qFuzzyCompare()
\since 5.2
diff --git a/src/corelib/global/qnumeric_p.h b/src/corelib/global/qnumeric_p.h
index 5f8a124bcc..9c8514f5a3 100644
--- a/src/corelib/global/qnumeric_p.h
+++ b/src/corelib/global/qnumeric_p.h
@@ -163,6 +163,58 @@ Q_DECL_CONST_FUNCTION static inline bool qt_is_finite(float f)
#ifndef Q_CLANG_QDOC
namespace {
+/*!
+ Returns true if the double \a v can be converted to type \c T, false if
+ it's out of range. If the conversion is successful, the converted value is
+ stored in \a value; if it was not successful, \a value will contain the
+ minimum or maximum of T, depending on the sign of \a d. If \c T is
+ unsigned, then \a value contains the absolute value of \a v.
+
+ This function works for v containing infinities, but not NaN. It's the
+ caller's responsibility to exclude that possibility before calling it.
+*/
+template <typename T> static inline bool convertDoubleTo(double v, T *value)
+{
+ Q_STATIC_ASSERT(std::numeric_limits<T>::is_integer);
+
+ // The [conv.fpint] (7.10 Floating-integral conversions) section of the C++
+ // standard says only exact conversions are guaranteed. Converting
+ // integrals to floating-point with loss of precision has implementation-
+ // defined behavior whether the next higher or next lower is returned;
+ // converting FP to integral is UB if it can't be represented.
+ //
+ // That means we can't write UINT64_MAX+1. Writing ldexp(1, 64) would be
+ // correct, but Clang, ICC and MSVC don't realize that it's a constant and
+ // the math call stays in the compiled code.
+
+ double supremum;
+ if (std::numeric_limits<T>::is_signed) {
+ supremum = -1.0 * std::numeric_limits<T>::min(); // -1 * (-2^63) = 2^63, exact (for T = qint64)
+ *value = std::numeric_limits<T>::min();
+ if (v < std::numeric_limits<T>::min())
+ return false;
+ } else {
+ using ST = typename std::make_signed<T>::type;
+ supremum = -2.0 * std::numeric_limits<ST>::min(); // -2 * (-2^63) = 2^64, exact (for T = quint64)
+ v = fabs(v);
+ }
+
+ *value = std::numeric_limits<T>::max();
+ if (v >= supremum)
+ return false;
+
+ // Now we can convert, these two conversions cannot be UB
+ *value = T(v);
+
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Wfloat-equal")
+QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
+
+ return *value == v;
+
+QT_WARNING_POP
+}
+
// Overflow math.
// This provides efficient implementations for int, unsigned, qsizetype and
// size_t. Implementations for 8- and 16-bit types will work but may not be as
diff --git a/src/corelib/global/qoperatingsystemversion.cpp b/src/corelib/global/qoperatingsystemversion.cpp
index 2f8d339ca7..94dc261b41 100644
--- a/src/corelib/global/qoperatingsystemversion.cpp
+++ b/src/corelib/global/qoperatingsystemversion.cpp
@@ -106,20 +106,12 @@ QT_BEGIN_NAMESPACE
major version number component of the object on the left hand side of the expression (10) is
greater than that of the object on the right (9):
- \code
- QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 9)
- \endcode
+ \snippet code/src_corelib_global_qoperatingsystemversion.cpp 0
This allows expressions for multiple operating systems to be joined with a logical OR operator
and still work as expected. For example:
- \code
- auto current = QOperatingSystemVersion::current();
- if (current >= QOperatingSystemVersion::OSXYosemite ||
- current >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) {
- // returns true on macOS >= 10.10 and iOS >= 8.0, but false on macOS < 10.10 and iOS < 8.0
- }
- \endcode
+ \snippet code/src_corelib_global_qoperatingsystemversion.cpp 1
A more naive comparison algorithm might incorrectly return true on all versions of macOS,
including Mac OS 9. This behavior is achieved by overloading the comparison operators to return
diff --git a/src/corelib/global/qoperatingsystemversion_win.cpp b/src/corelib/global/qoperatingsystemversion_win.cpp
index 7659fb2550..2da190da48 100644
--- a/src/corelib/global/qoperatingsystemversion_win.cpp
+++ b/src/corelib/global/qoperatingsystemversion_win.cpp
@@ -103,7 +103,7 @@ static inline OSVERSIONINFOEX determineWinOsVersion()
// GetVersionEx() has been deprecated in Windows 8.1 and will return
// only Windows 8 from that version on, so use the kernel API function.
- pRtlGetVersion((LPOSVERSIONINFO) &result); // always returns STATUS_SUCCESS
+ pRtlGetVersion(reinterpret_cast<LPOSVERSIONINFO>(&result)); // always returns STATUS_SUCCESS
#else // !Q_OS_WINCE
GetVersionEx(&result);
#endif
diff --git a/src/corelib/global/qprocessordetection.h b/src/corelib/global/qprocessordetection.h
index 0b260d01e3..aaa27dff4a 100644
--- a/src/corelib/global/qprocessordetection.h
+++ b/src/corelib/global/qprocessordetection.h
@@ -57,7 +57,7 @@
optional and usually dependent on how the compiler was invoked. Variants
that are a superset of another should have a define for the superset.
- In addition to the procesor family, variants, and revisions, we also set
+ In addition to the processor family, variants, and revisions, we also set
Q_BYTE_ORDER appropriately for the target processor. For bi-endian
processors, we try to auto-detect the byte order using the __BIG_ENDIAN__,
__LITTLE_ENDIAN__, or __BYTE_ORDER__ preprocessor macros.
@@ -320,6 +320,12 @@
# endif
# define Q_BYTE_ORDER Q_BIG_ENDIAN
+// -- Web Assembly --
+#elif defined(__EMSCRIPTEN__)
+# define Q_PROCESSOR_WASM
+# define Q_PROCESSOR_X86 6 // enables SIMD support
+# define Q_BYTE_ORDER Q_LITTLE_ENDIAN
+# define Q_PROCESSOR_WORDSIZE 8
#endif
/*
diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp
index ebf9864b15..23e5e499b2 100644
--- a/src/corelib/global/qrandom.cpp
+++ b/src/corelib/global/qrandom.cpp
@@ -510,9 +510,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
those. The most common way of generating new values is to call the generate(),
generate64() or fillRange() functions. One would use it as:
- \code
- quint32 value = QRandomGenerator::global()->generate();
- \endcode
+ \snippet code/src_corelib_global_qrandom.cpp 0
Additionally, it provides a floating-point function generateDouble() that
returns a number in the range [0, 1) (that is, inclusive of zero and
@@ -525,11 +523,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
the numbers generated by the object will always be the same, as in the
following example:
- \code
- QRandomGenerator prng1(1234), prng2(1234);
- Q_ASSERT(prng1.generate32() == prng2.generate32());
- Q_ASSERT(prng1.generate64() == prng2.generate64());
- \endcode
+ \snippet code/src_corelib_global_qrandom.cpp 1
The seed data takes the form of one or more 32-bit words. The ideal seed
size is approximately equal to the size of the QRandomGenerator class
@@ -552,12 +546,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
For ease of use, QRandomGenerator provides a global object that can
be easily used, as in the following example:
- \code
- int x = QRandomGenerator::global()->generate32();
- int y = QRandomGenerator::global()->generate32();
- int w = QRandomGenerator::global()->bounded(16384);
- int h = QRandomGenerator::global()->bounded(16384);
- \endcode
+ \snippet code/src_corelib_global_qrandom.cpp 2
\section1 System-wide random number generator
@@ -645,10 +634,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
following code may be used to generate a floating-point number in the range
[1, 2.5):
- \code
- std::uniform_real_distribution dist(1, 2.5);
- return dist(*QRandomGenerator::global());
- \endcode
+ \snippet code/src_corelib_global_qrandom.cpp 3
\sa QRandomGenerator64, qrand()
*/
@@ -688,10 +674,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
with the same seed value will produce the same number sequence.
This constructor is equivalent to:
- \code
- std::seed_seq sseq(seedBuffer, seedBuffer + len);
- QRandomGenerator generator(sseq);
- \endcode
+ \snippet code/src_corelib_global_qrandom.cpp 4
\sa seed(), securelySeeded()
*/
@@ -705,10 +688,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
with the same seed value will produce the same number sequence.
This constructor is equivalent to:
- \code
- std::seed_seq sseq(begin, end);
- QRandomGenerator generator(sseq);
- \endcode
+ \snippet code/src_corelib_global_qrandom.cpp 5
\sa seed(), securelySeeded()
*/
@@ -828,10 +808,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
Discards the next \a z entries from the sequence. This method is equivalent
to calling generate() \a z times and discarding the result, as in:
- \code
- while (z--)
- generator.generate();
- \endcode
+ \snippet code/src_corelib_global_qrandom.cpp 6
*/
/*!
@@ -840,9 +817,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
Generates 32-bit quantities and stores them in the range between \a begin
and \a end. This function is equivalent to (and is implemented as):
- \code
- std::generate(begin, end, [this]() { return generate(); });
- \endcode
+ \snippet code/src_corelib_global_qrandom.cpp 7
This function complies with the requirements for the function
\l{http://en.cppreference.com/w/cpp/numeric/random/seed_seq/generate}{\c std::seed_seq::generate},
@@ -853,9 +828,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
32 bits of data. Any other bits will be zero. To fill the range with 64 bit
quantities, one can write:
- \code
- std::generate(begin, end, []() { return QRandomGenerator::global()->generate64(); });
- \endcode
+ \snippet code/src_corelib_global_qrandom.cpp 8
If the range refers to contiguous memory (such as an array or the data from
a QVector), the fillRange() function may be used too.
@@ -882,11 +855,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
For example, to fill a vector of 16 entries with random values, one may
write:
- \code
- QVector<quint32> vector;
- vector.resize(16);
- QRandomGenerator::fillRange(vector.data(), vector.size());
- \endcode
+ \snippet code/src_corelib_global_qrandom.cpp 9
\sa generate()
*/
@@ -901,10 +870,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
For example, to fill generate two 32-bit quantities, one may write:
- \code
- quint32 array[2];
- QRandomGenerator::fillRange(array);
- \endcode
+ \snippet code/src_corelib_global_qrandom.cpp 10
It would have also been possible to make one call to generate64() and then split
the two halves of the 64-bit value.
@@ -919,10 +885,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
inclusive of zero and exclusive of 1).
This function is equivalent to:
- \code
- QRandomGenerator64 rd;
- return std::generate_canonical<qreal, std::numeric_limits<qreal>::digits>(rd);
- \endcode
+ \snippet code/src_corelib_global_qrandom.cpp 11
The same may also be obtained by using
\l{http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution}{\c std::uniform_real_distribution}
@@ -937,9 +900,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
Generates one random double in the range between 0 (inclusive) and \a
highest (exclusive). This function is equivalent to and is implemented as:
- \code
- return generateDouble() * highest;
- \endcode
+ \snippet code/src_corelib_global_qrandom.cpp 12
\sa generateDouble(), bounded()
*/
@@ -956,9 +917,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
For example, to obtain a value between 0 and 255 (inclusive), one would write:
- \code
- quint32 v = QRandomGenerator::bounded(256);
- \endcode
+ \snippet code/src_corelib_global_qrandom.cpp 13
Naturally, the same could also be obtained by masking the result of generate()
to only the lower 8 bits. Either solution is as efficient.
@@ -995,9 +954,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
For example, to obtain a value between 1000 (incl.) and 2000 (excl.), one
would write:
- \code
- quint32 v = QRandomGenerator::bounded(1000, 2000);
- \endcode
+ \snippet code/src_corelib_global_qrandom.cpp 14
Note that this function cannot be used to obtain values in the full 32-bit
@@ -1053,9 +1010,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
For example, the following creates a random RGB color:
- \code
- return QColor::fromRgb(QRandomGenerator::global()->generate());
- \endcode
+ \snippet code/src_corelib_global_qrandom.cpp 15
Accesses to this object are thread-safe and it may therefore be used in any
thread without locks. The object may also be copied and the sequence
@@ -1123,9 +1078,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel
set. If you wish to cast the returned value to qint64 and keep it positive,
you should mask the sign bit off:
- \code
- qint64 value = QRandomGenerator64::generate() & std::numeric_limits<qint64>::max();
- \endcode
+ \snippet code/src_corelib_global_qrandom.cpp 16
\sa QRandomGenerator, QRandomGenerator::generate64()
*/
@@ -1298,7 +1251,7 @@ struct QRandEngine
};
}
-#if defined(QT_NO_THREAD) || defined(Q_OS_WIN)
+#if defined(Q_OS_WIN)
// On Windows srand() and rand() already use Thread-Local-Storage
// to store the seed between calls
static inline QRandEngine *randTLS()
diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h
index cacb95b674..aabe46f3c2 100644
--- a/src/corelib/global/qsystemdetection.h
+++ b/src/corelib/global/qsystemdetection.h
@@ -137,6 +137,8 @@
# define Q_OS_HPUX
#elif defined(__native_client__)
# define Q_OS_NACL
+#elif defined(__EMSCRIPTEN__)
+# define Q_OS_WASM
#elif defined(__linux__) || defined(__linux)
# define Q_OS_LINUX
#elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
diff --git a/src/corelib/global/qtrace_p.h b/src/corelib/global/qtrace_p.h
index ab8fc14af5..3d04a7311d 100644
--- a/src/corelib/global/qtrace_p.h
+++ b/src/corelib/global/qtrace_p.h
@@ -109,6 +109,8 @@
* qcoreapplication_baz above.
*/
+#include <QtCore/qglobal.h>
+
QT_BEGIN_NAMESPACE
#if defined(Q_TRACEPOINT) && !defined(QT_BOOTSTRAPPED)
diff --git a/src/corelib/global/qversiontagging.cpp b/src/corelib/global/qversiontagging.cpp
index cbfd93f135..b5e524bf4c 100644
--- a/src/corelib/global/qversiontagging.cpp
+++ b/src/corelib/global/qversiontagging.cpp
@@ -93,7 +93,16 @@ make_versioned_symbol(SYM, QT_VERSION_MAJOR, 11, "@");
make_versioned_symbol(SYM, QT_VERSION_MAJOR, 12, "@");
#endif
#if QT_VERSION_MINOR > 13
-// We don't expect there will be a Qt 5.13
+make_versioned_symbol(SYM, QT_VERSION_MAJOR, 13, "@");
+#endif
+#if QT_VERSION_MINOR > 14
+make_versioned_symbol(SYM, QT_VERSION_MAJOR, 14, "@");
+#endif
+#if QT_VERSION_MINOR > 15
+make_versioned_symbol(SYM, QT_VERSION_MAJOR, 15, "@");
+#endif
+#if QT_VERSION_MINOR > 16
+// We don't expect there will be a Qt 5.17
# error "Please update this file with more Qt versions."
#endif
diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp
index 013d531581..4d56d1a179 100644
--- a/src/corelib/io/qdebug.cpp
+++ b/src/corelib/io/qdebug.cpp
@@ -606,31 +606,7 @@ QDebug &QDebug::resetFormat()
clean.
Output examples:
- \code
- QString s;
-
- s = "a";
- qDebug().noquote() << s; // prints: a
- qDebug() << s; // prints: "a"
-
- s = "\"a\r\n\"";
- qDebug() << s; // prints: "\"a\r\n\""
-
- s = "\033"; // escape character
- qDebug() << s; // prints: "\u001B"
-
- s = "\u00AD"; // SOFT HYPHEN
- qDebug() << s; // prints: "\u00AD"
-
- s = "\u00E1"; // LATIN SMALL LETTER A WITH ACUTE
- qDebug() << s; // prints: "á"
-
- s = "a\u0301"; // "a" followed by COMBINING ACUTE ACCENT
- qDebug() << s; // prints: "aÌ";
-
- s = "\u0430\u0301"; // CYRILLIC SMALL LETTER A followed by COMBINING ACUTE ACCENT
- qDebug() << s; // prints: "аÌ"
- \endcode
+ \snippet code/src_corelib_io_qdebug.cpp 0
*/
/*!
@@ -690,25 +666,7 @@ QDebug &QDebug::resetFormat()
clean.
Output examples:
- \code
- QByteArray ba;
-
- ba = "a";
- qDebug().noquote() << ba; // prints: a
- qDebug() << ba; // prints: "a"
-
- ba = "\"a\r\n\"";
- qDebug() << ba; // prints: "\"a\r\n\""
-
- ba = "\033"; // escape character
- qDebug() << ba; // prints: "\x1B"
-
- ba = "\xC3\xA1";
- qDebug() << ba; // prints: "\xC3\xA1"
-
- ba = QByteArray("a\0b", 3);
- qDebug() << ba // prints: "\a\x00""b"
- \endcode
+ \snippet code/src_corelib_io_qdebug.cpp 1
Note how QDebug needed to close and reopen the string in the way C and C++
languages concatenate string literals so that the letter 'b' is not
@@ -939,14 +897,18 @@ void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, int value)
QDebug qt_QMetaEnum_debugOperator(QDebug &dbg, int value, const QMetaObject *meta, const char *name)
{
QDebugStateSaver saver(dbg);
+ dbg.nospace();
QMetaEnum me = meta->enumerator(meta->indexOfEnumerator(name));
const char *key = me.valueToKey(value);
- dbg.nospace() << meta->className() << "::" << name << '(';
- if (key)
+ if (key) {
+ if (const char *scope = me.scope())
+ dbg << scope << "::";
+ if (me.isScoped())
+ dbg << me.enumName() << "::";
dbg << key;
- else
- dbg << value;
- dbg << ')';
+ } else {
+ dbg << meta->className() << "::" << name << "(" << value << ")";
+ }
return dbg;
}
@@ -960,7 +922,7 @@ QDebug qt_QMetaEnum_flagDebugOperator(QDebug &debug, quint64 value, const QMetaO
const QMetaEnum me = meta->enumerator(meta->indexOfEnumerator(name));
if (const char *scope = me.scope())
debug << scope << "::";
- debug << me.name() << ">(" << me.valueToKeys(value) << ')';
+ debug << me.enumName() << ">(" << me.valueToKeys(value) << ')';
return debug;
}
#endif // !QT_NO_QOBJECT
diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h
index ee8ef679a9..ae1869f89e 100644
--- a/src/corelib/io/qdebug.h
+++ b/src/corelib/io/qdebug.h
@@ -376,6 +376,19 @@ operator<<(QDebug dbg, T value)
return qt_QMetaEnum_debugOperator(dbg, typename QFlags<T>::Int(value), obj, name);
}
+template<typename T,
+ typename A = typename std::enable_if<std::is_enum<T>::value, void>::type,
+ typename B = typename std::enable_if<sizeof(T) <= sizeof(int), void>::type,
+ typename C = typename std::enable_if<!QtPrivate::IsQEnumHelper<T>::Value, void>::type,
+ typename D = typename std::enable_if<QtPrivate::IsQEnumHelper<QFlags<T>>::Value, void>::type>
+inline QDebug operator<<(QDebug dbg, T value)
+{
+ typedef QFlags<T> FlagsT;
+ const QMetaObject *obj = qt_getEnumMetaObject(FlagsT());
+ const char *name = qt_getEnumName(FlagsT());
+ return qt_QMetaEnum_debugOperator(dbg, typename FlagsT::Int(value), obj, name);
+}
+
template <class T>
inline typename std::enable_if<
QtPrivate::IsQEnumHelper<T>::Value || QtPrivate::IsQEnumHelper<QFlags<T> >::Value,
diff --git a/src/corelib/io/qdebug_p.h b/src/corelib/io/qdebug_p.h
index a1887655d2..dcb906d156 100644
--- a/src/corelib/io/qdebug_p.h
+++ b/src/corelib/io/qdebug_p.h
@@ -93,7 +93,7 @@ static inline void formatQEnum(QDebug &debug, QEnum value)
{
const QMetaObject *metaObject = qt_getEnumMetaObject(value);
const QMetaEnum me = metaObject->enumerator(metaObject->indexOfEnumerator(qt_getEnumName(value)));
- if (const char *key = me.valueToKey(value))
+ if (const char *key = me.valueToKey(int(value)))
debug << key;
else
debug << int(value);
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
index 10aee73a2f..75fd0f8e0a 100644
--- a/src/corelib/io/qdir.cpp
+++ b/src/corelib/io/qdir.cpp
@@ -48,7 +48,9 @@
#include "qdiriterator.h"
#include "qdatetime.h"
#include "qstring.h"
-#include "qregexp.h"
+#if QT_CONFIG(regularexpression)
+# include <qregularexpression.h>
+#endif
#include "qvector.h"
#include "qvarlengtharray.h"
#include "qfilesystementry_p.h"
@@ -72,7 +74,7 @@ static QString driveSpec(const QString &path)
if (path.size() < 2)
return QString();
char c = path.at(0).toLatin1();
- if (c < 'a' && c > 'z' && c < 'A' && c > 'Z')
+ if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z'))
return QString();
if (path.at(1).toLatin1() != ':')
return QString();
@@ -1038,7 +1040,7 @@ QStringList QDir::nameFilters() const
list of filters specified by \a nameFilters.
Each name filter is a wildcard (globbing) filter that understands
- \c{*} and \c{?} wildcards. (See \l{QRegExp wildcard matching}.)
+ \c{*} and \c{?} wildcards. (See \l{QRegularExpression wildcard matching}.)
For example, the following code sets three name filters on a QDir
to ensure that only files with extensions typically used for C++
@@ -2059,7 +2061,7 @@ QString QDir::homePath()
Returns the system's temporary directory.
- The directory is constructed using the absolute path of the temporary directory,
+ The directory is constructed using the absolute canonical path of the temporary directory,
ensuring that its path() will be the same as its absolutePath().
See tempPath() for details.
@@ -2068,7 +2070,7 @@ QString QDir::homePath()
*/
/*!
- Returns the absolute path of the system's temporary directory.
+ Returns the absolute canonical path of the system's temporary directory.
On Unix/Linux systems this is the path in the \c TMPDIR environment
variable or \c{/tmp} if \c TMPDIR is not defined. On Windows this is
@@ -2110,7 +2112,7 @@ QString QDir::rootPath()
return QFileSystemEngine::rootPath();
}
-#ifndef QT_NO_REGEXP
+#if QT_CONFIG(regularexpression)
/*!
\overload
@@ -2118,13 +2120,18 @@ QString QDir::rootPath()
patterns in the list of \a filters; otherwise returns \c false. The
matching is case insensitive.
- \sa {QRegExp wildcard matching}, QRegExp::exactMatch(), entryList(), entryInfoList()
+ \sa {QRegularExpression Wildcard matching}, QRegularExpression::wildcardToRegularExpression(),
+ entryList(), entryInfoList()
*/
bool QDir::match(const QStringList &filters, const QString &fileName)
{
for (QStringList::ConstIterator sit = filters.constBegin(); sit != filters.constEnd(); ++sit) {
- QRegExp rx(*sit, Qt::CaseInsensitive, QRegExp::Wildcard);
- if (rx.exactMatch(fileName))
+ QString wildcard = QRegularExpression::wildcardToRegularExpression(*sit);
+ // Insensitive exact match
+ // (see Notes for QRegExp Users in QRegularExpression's documentation)
+ QRegularExpression rx(QRegularExpression::anchoredPattern(wildcard),
+ QRegularExpression::CaseInsensitiveOption);
+ if (rx.match(fileName).hasMatch())
return true;
}
return false;
@@ -2136,13 +2143,14 @@ bool QDir::match(const QStringList &filters, const QString &fileName)
contain multiple patterns separated by spaces or semicolons.
The matching is case insensitive.
- \sa {QRegExp wildcard matching}, QRegExp::exactMatch(), entryList(), entryInfoList()
+ \sa {QRegularExpression wildcard matching}, QRegularExpression::wildcardToRegularExpression,
+ entryList(), entryInfoList()
*/
bool QDir::match(const QString &filter, const QString &fileName)
{
return match(nameFiltersFromString(filter), fileName);
}
-#endif // QT_NO_REGEXP
+#endif // QT_CONFIG(regularexpression)
/*!
\internal
diff --git a/src/corelib/io/qdir.h b/src/corelib/io/qdir.h
index 950a26f327..45c59d9e1d 100644
--- a/src/corelib/io/qdir.h
+++ b/src/corelib/io/qdir.h
@@ -206,7 +206,7 @@ public:
static inline QDir temp() { return QDir(tempPath()); }
static QString tempPath();
-#ifndef QT_NO_REGEXP
+#if QT_CONFIG(regularexpression)
static bool match(const QStringList &filters, const QString &fileName);
static bool match(const QString &filter, const QString &fileName);
#endif
diff --git a/src/corelib/io/qfileselector.cpp b/src/corelib/io/qfileselector.cpp
index 0ba8b124f7..ce06c8e00b 100644
--- a/src/corelib/io/qfileselector.cpp
+++ b/src/corelib/io/qfileselector.cpp
@@ -81,27 +81,11 @@ QFileSelectorPrivate::QFileSelectorPrivate()
Consider the following example usage, where you want to use different settings files on
different locales. You might select code between locales like this:
- \code
- QString defaultsBasePath = "data/";
- QString defaultsPath = defaultsBasePath + "defaults.conf";
- QString localizedPath = defaultsBasePath
- + QString("%1/defaults.conf").arg(QLocale().name());
- if (QFile::exists(localizedPath))
- defaultsPath = localizedPath;
- QFile defaults(defaultsPath);
- \endcode
+ \snippet code/src_corelib_io_qfileselector.cpp 0
Similarly, if you want to pick a different data file based on target platform,
your code might look something like this:
- \code
- QString defaultsPath = "data/defaults.conf";
-#if defined(Q_OS_ANDROID)
- defaultsPath = "data/android/defaults.conf";
-#elif defined(Q_OS_IOS)
- defaultsPath = "data/ios/defaults.conf";
-#endif
- QFile defaults(defaultsPath);
- \endcode
+ \snippet code/src_corelib_io_qfileselector.cpp 1
QFileSelector provides a convenient alternative to writing such boilerplate code, and in the
latter case it allows you to start using an platform-specific configuration without a recompile.
@@ -109,27 +93,17 @@ QFileSelectorPrivate::QFileSelectorPrivate()
selecting a different file only on certain combinations of platform and locale. For example, to
select based on platform and/or locale, the code is as follows:
- \code
- QFileSelector selector;
- QFile defaultsFile(selector.select("data/defaults.conf"));
- \endcode
+ \snippet code/src_corelib_io_qfileselector.cpp 2
The files to be selected are placed in directories named with a \c'+' and a selector name. In the above
example you could have the platform configurations selected by placing them in the following locations:
- \code
- data/defaults.conf
- data/+android/defaults.conf
- data/+ios/+en_GB/defaults.conf
- \endcode
+ \snippet code/src_corelib_io_qfileselector.cpp 3
To find selected files, QFileSelector looks in the same directory as the base file. If there are
any directories of the form +<selector> with an active selector, QFileSelector will prefer a file
with the same file name from that directory over the base file. These directories can be nested to
check against multiple selectors, for example:
- \code
- images/background.png
- images/+android/+en_GB/background.png
- \endcode
+ \snippet code/src_corelib_io_qfileselector.cpp 4
With those files available, you would select a different file on the android platform,
but only if the locale was en_GB.
@@ -178,13 +152,7 @@ QFileSelectorPrivate::QFileSelectorPrivate()
credentials. The example is sorted so that the lowest matching file would be chosen if all
selectors were present:
- \code
- images/background.png
- images/+linux/background.png
- images/+windows/background.png
- images/+admin/background.png
- images/+admin/+linux/background.png
- \endcode
+ \snippet code/src_corelib_io_qfileselector.cpp 5
Because extra selectors are checked before platform the \c{+admin/background.png} will be chosen
on Windows when the admin selector is set, and \c{+windows/background.png} will be chosen on
diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp
index 964dcebeb2..5a5a3a82c6 100644
--- a/src/corelib/io/qfilesystemengine_unix.cpp
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -76,9 +76,7 @@
#endif
#if defined(Q_OS_DARWIN)
-# if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(101200, 100000, 100000, 30000)
-# include <sys/clonefile.h>
-# endif
+# include <sys/clonefile.h>
# include <copyfile.h>
// We cannot include <Foundation/Foundation.h> (it's an Objective-C header), but
// we need these declarations:
@@ -744,7 +742,7 @@ QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry,
QString canonicalPath = QDir::cleanPath(QFile::decodeName(ret));
free(ret);
return QFileSystemEntry(canonicalPath);
- } else if (errno == ENOENT) { // file doesn't exist
+ } else if (errno == ENOENT || errno == ENOTDIR) { // file doesn't exist
data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
data.entryFlags &= ~(QFileSystemMetaData::ExistsAttribute);
return QFileSystemEntry();
@@ -823,16 +821,16 @@ QByteArray QFileSystemEngine::id(int id)
//static
QString QFileSystemEngine::resolveUserName(uint userId)
{
-#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD)
+#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD)
int size_max = sysconf(_SC_GETPW_R_SIZE_MAX);
if (size_max == -1)
size_max = 1024;
QVarLengthArray<char, 1024> buf(size_max);
#endif
-#if !defined(Q_OS_INTEGRITY)
+#if !defined(Q_OS_INTEGRITY) && !defined(Q_OS_WASM)
struct passwd *pw = 0;
-#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS)
+#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS)
struct passwd entry;
getpwuid_r(userId, &entry, buf.data(), buf.size(), &pw);
#else
@@ -847,16 +845,16 @@ QString QFileSystemEngine::resolveUserName(uint userId)
//static
QString QFileSystemEngine::resolveGroupName(uint groupId)
{
-#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD)
+#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD)
int size_max = sysconf(_SC_GETPW_R_SIZE_MAX);
if (size_max == -1)
size_max = 1024;
QVarLengthArray<char, 1024> buf(size_max);
#endif
-#if !defined(Q_OS_INTEGRITY)
+#if !defined(Q_OS_INTEGRITY) && !defined(Q_OS_WASM)
struct group *gr = 0;
-#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID) && (__ANDROID_API__ >= 24))
+#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID) && (__ANDROID_API__ >= 24))
size_max = sysconf(_SC_GETGR_R_SIZE_MAX);
if (size_max == -1)
size_max = 1024;
@@ -1228,20 +1226,18 @@ 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)
- if (__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *)) {
- if (::clonefile(source.nativeFilePath().constData(),
- target.nativeFilePath().constData(), 0) == 0)
- return true;
- error = QSystemError(errno, QSystemError::StandardLibraryError);
- return false;
- }
+#if defined(Q_OS_DARWIN)
+ 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;
+#endif
}
//static
@@ -1263,13 +1259,11 @@ bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSy
}
#endif
#if defined(Q_OS_DARWIN) && defined(RENAME_EXCL)
- if (__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *)) {
- if (renameatx_np(AT_FDCWD, srcPath, AT_FDCWD, tgtPath, RENAME_EXCL) == 0)
- return true;
- if (errno != ENOTSUP) {
- error = QSystemError(errno, QSystemError::StandardLibraryError);
- return false;
- }
+ if (renameatx_np(AT_FDCWD, srcPath, AT_FDCWD, tgtPath, RENAME_EXCL) == 0)
+ return true;
+ if (errno != ENOTSUP) {
+ error = QSystemError(errno, QSystemError::StandardLibraryError);
+ return false;
}
#endif
@@ -1492,7 +1486,7 @@ QString QFileSystemEngine::tempPath()
temp = QLatin1String(_PATH_TMP);
}
}
- return QDir::cleanPath(temp);
+ return QDir(QDir::cleanPath(temp)).canonicalPath();
#endif
}
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp
index fadc058110..a796fd005a 100644
--- a/src/corelib/io/qfilesystemengine_win.cpp
+++ b/src/corelib/io/qfilesystemengine_win.cpp
@@ -204,10 +204,12 @@ GlobalSid::GlobalSid()
::GetTokenInformation(token, TokenUser, 0, 0, &retsize);
if (retsize) {
void *tokenBuffer = malloc(retsize);
+ Q_CHECK_PTR(tokenBuffer);
if (::GetTokenInformation(token, TokenUser, tokenBuffer, retsize, &retsize)) {
PSID tokenSid = reinterpret_cast<PTOKEN_USER>(tokenBuffer)->User.Sid;
DWORD sidLen = ::GetLengthSid(tokenSid);
currentUserSID = reinterpret_cast<PSID>(malloc(sidLen));
+ Q_CHECK_PTR(currentUserSID);
if (::CopySid(sidLen, currentUserSID, tokenSid))
BuildTrusteeWithSid(&currentUserTrusteeW, currentUserSID);
}
@@ -294,6 +296,7 @@ static QString readSymLink(const QFileSystemEntry &link)
if (handle != INVALID_HANDLE_VALUE) {
DWORD bufsize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER*)malloc(bufsize);
+ Q_CHECK_PTR(rdb);
DWORD retsize = 0;
if (::DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, 0, 0, rdb, bufsize, &retsize, 0)) {
if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
@@ -935,7 +938,7 @@ static bool tryFindFallback(const QFileSystemEntry &fname, QFileSystemMetaData &
bool QFileSystemEngine::fillMetaData(int fd, QFileSystemMetaData &data,
QFileSystemMetaData::MetaDataFlags what)
{
- HANDLE fHandle = (HANDLE)_get_osfhandle(fd);
+ auto fHandle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
if (fHandle != INVALID_HANDLE_VALUE) {
return fillMetaData(fHandle, data, what);
}
@@ -1014,7 +1017,8 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
WIN32_FIND_DATA findData;
// The memory structure for WIN32_FIND_DATA is same as WIN32_FILE_ATTRIBUTE_DATA
// for all members used by fillFindData().
- bool ok = ::GetFileAttributesEx((wchar_t*)fname.nativeFilePath().utf16(), GetFileExInfoStandard,
+ bool ok = ::GetFileAttributesEx(reinterpret_cast<const wchar_t*>(fname.nativeFilePath().utf16()),
+ GetFileExInfoStandard,
reinterpret_cast<WIN32_FILE_ATTRIBUTE_DATA *>(&findData));
if (ok) {
data.fillFromFindData(findData, false, fname.isDriveRoot());
@@ -1069,19 +1073,22 @@ static bool isDirPath(const QString &dirPath, bool *existed)
if (path.length() == 2 && path.at(1) == QLatin1Char(':'))
path += QLatin1Char('\\');
+ const QString longPath = QFSFileEnginePrivate::longFileName(path);
#ifndef Q_OS_WINRT
- DWORD fileAttrib = ::GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16());
+ DWORD fileAttrib = ::GetFileAttributes(reinterpret_cast<const wchar_t*>(longPath.utf16()));
#else // Q_OS_WINRT
DWORD fileAttrib = INVALID_FILE_ATTRIBUTES;
WIN32_FILE_ATTRIBUTE_DATA data;
- if (::GetFileAttributesEx((const wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(), GetFileExInfoStandard, &data))
+ if (::GetFileAttributesEx(reinterpret_cast<const wchar_t*>(longPath.utf16()),
+ GetFileExInfoStandard, &data)) {
fileAttrib = data.dwFileAttributes;
+ }
#endif // Q_OS_WINRT
if (fileAttrib == INVALID_FILE_ATTRIBUTES) {
int errorCode = GetLastError();
if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) {
WIN32_FIND_DATA findData;
- if (getFindData(QFSFileEnginePrivate::longFileName(path), findData))
+ if (getFindData(longPath, findData))
fileAttrib = findData.dwFileAttributes;
}
}
@@ -1411,7 +1418,7 @@ bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Per
if (mode == 0) // not supported
return false;
- bool ret = (::_wchmod((wchar_t*)entry.nativeFilePath().utf16(), mode) == 0);
+ bool ret = ::_wchmod(reinterpret_cast<const wchar_t*>(entry.nativeFilePath().utf16()), mode) == 0;
if(!ret)
error = QSystemError(errno, QSystemError::StandardLibraryError);
return ret;
diff --git a/src/corelib/io/qfilesystemiterator_win.cpp b/src/corelib/io/qfilesystemiterator_win.cpp
index 2905a8e54e..6741282881 100644
--- a/src/corelib/io/qfilesystemiterator_win.cpp
+++ b/src/corelib/io/qfilesystemiterator_win.cpp
@@ -106,8 +106,7 @@ bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaDa
QLatin1String("\\\\") + parts.at(2), &uncShares)) {
if (uncShares.isEmpty())
return false; // No shares found in the server
- else
- uncFallback = true;
+ uncFallback = true;
}
}
}
diff --git a/src/corelib/io/qfilesystemwatcher_fsevents.mm b/src/corelib/io/qfilesystemwatcher_fsevents.mm
index 3672b1b8f9..f594fad803 100644
--- a/src/corelib/io/qfilesystemwatcher_fsevents.mm
+++ b/src/corelib/io/qfilesystemwatcher_fsevents.mm
@@ -497,7 +497,7 @@ bool QFseventsFileSystemWatcherEngine::startStream()
DEBUG() << "Starting stream with paths" << watchingState.watchedPaths.keys();
- NSMutableArray *pathsToWatch = [NSMutableArray arrayWithCapacity:watchingState.watchedPaths.size()];
+ NSMutableArray<NSString *> *pathsToWatch = [NSMutableArray<NSString *> arrayWithCapacity:watchingState.watchedPaths.size()];
for (PathRefCounts::const_iterator i = watchingState.watchedPaths.begin(), ei = watchingState.watchedPaths.end(); i != ei; ++i)
[pathsToWatch addObject:i.key().toNSString()];
diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp
index 338bec5d6e..66985f8982 100644
--- a/src/corelib/io/qfilesystemwatcher_win.cpp
+++ b/src/corelib/io/qfilesystemwatcher_win.cpp
@@ -55,6 +55,7 @@
# include <qcoreapplication.h>
# include <qdir.h>
# include <private/qeventdispatcher_win_p.h>
+# include <private/qthread_p.h>
# include <dbt.h>
# include <algorithm>
# include <vector>
@@ -306,7 +307,8 @@ void QWindowsRemovableDriveListener::addPath(const QString &p)
notify.dbch_size = sizeof(notify);
notify.dbch_devicetype = DBT_DEVTYP_HANDLE;
notify.dbch_handle = volumeHandle;
- QEventDispatcherWin32 *winEventDispatcher = static_cast<QEventDispatcherWin32 *>(QAbstractEventDispatcher::instance());
+ QThreadData *currentData = QThreadData::current();
+ QEventDispatcherWin32 *winEventDispatcher = static_cast<QEventDispatcherWin32 *>(currentData->ensureEventDispatcher());
re.devNotify = RegisterDeviceNotification(winEventDispatcher->internalHwnd(),
&notify, DEVICE_NOTIFY_WINDOW_HANDLE);
// Empirically found: The notifications also work when the handle is immediately
@@ -663,7 +665,8 @@ void QWindowsFileSystemWatcherEngineThread::run()
if (m != '@')
DEBUG() << "QWindowsFileSystemWatcherEngine: unknown message sent to thread: " << char(m);
break;
- } else if (r > WAIT_OBJECT_0 && r < WAIT_OBJECT_0 + uint(handlesCopy.count())) {
+ }
+ if (r > WAIT_OBJECT_0 && r < WAIT_OBJECT_0 + uint(handlesCopy.count())) {
int at = r - WAIT_OBJECT_0;
Q_ASSERT(at < handlesCopy.count());
HANDLE handle = handlesCopy.at(at);
diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp
index bbd262e2f9..90ad0126d6 100644
--- a/src/corelib/io/qfsfileengine_unix.cpp
+++ b/src/corelib/io/qfsfileengine_unix.cpp
@@ -82,12 +82,11 @@ static inline int openModeToOpenFlags(QIODevice::OpenMode mode)
if (QFSFileEnginePrivate::openModeCanCreate(mode))
oflags |= QT_OPEN_CREAT;
- if (mode & QFile::Append) {
+ if (mode & QFile::Truncate)
+ oflags |= QT_OPEN_TRUNC;
+
+ if (mode & QFile::Append)
oflags |= QT_OPEN_APPEND;
- } else if (mode & QFile::WriteOnly) {
- if ((mode & QFile::Truncate) || !(mode & QFile::ReadOnly))
- oflags |= QT_OPEN_TRUNC;
- }
if (mode & QFile::NewOnly)
oflags |= QT_OPEN_EXCL;
@@ -531,29 +530,32 @@ QByteArray QFSFileEngine::id() const
QString QFSFileEngine::fileName(FileName file) const
{
Q_D(const QFSFileEngine);
- if (file == BundleName) {
+ switch (file) {
+ case BundleName:
return QFileSystemEngine::bundleName(d->fileEntry);
- } else if (file == BaseName) {
+ case BaseName:
return d->fileEntry.fileName();
- } else if (file == PathName) {
+ case PathName:
return d->fileEntry.path();
- } else if (file == AbsoluteName || file == AbsolutePathName) {
+ case AbsoluteName:
+ case AbsolutePathName: {
QFileSystemEntry entry(QFileSystemEngine::absoluteName(d->fileEntry));
- if (file == AbsolutePathName) {
- return entry.path();
- }
- return entry.filePath();
- } else if (file == CanonicalName || file == CanonicalPathName) {
+ return file == AbsolutePathName ? entry.path() : entry.filePath();
+ }
+ case CanonicalName:
+ case CanonicalPathName: {
QFileSystemEntry entry(QFileSystemEngine::canonicalName(d->fileEntry, d->metaData));
- if (file == CanonicalPathName)
- return entry.path();
- return entry.filePath();
- } else if (file == LinkName) {
+ return file == CanonicalPathName ? entry.path() : entry.filePath();
+ }
+ case LinkName:
if (d->isSymlink()) {
QFileSystemEntry entry = QFileSystemEngine::getLinkTarget(d->fileEntry, d->metaData);
return entry.filePath();
}
return QString();
+ case DefaultName:
+ case NFileNames:
+ break;
}
return d->fileEntry.filePath();
}
diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp
index 8199f6a846..19cc3e6402 100644
--- a/src/corelib/io/qfsfileengine_win.cpp
+++ b/src/corelib/io/qfsfileengine_win.cpp
@@ -45,7 +45,6 @@
#include "qfile.h"
#include "qdir.h"
-#include "private/qmutexpool_p.h"
#include "qvarlengtharray.h"
#include "qdatetime.h"
#include "qt_windows.h"
@@ -546,23 +545,33 @@ QString QFSFileEngine::tempPath()
return QFileSystemEngine::tempPath();
}
+#if !defined(Q_OS_WINRT)
+// cf QStorageInfo::isReady
+static inline bool isDriveReady(const wchar_t *path)
+{
+ DWORD fileSystemFlags;
+ const UINT driveType = GetDriveType(path);
+ return (driveType != DRIVE_REMOVABLE && driveType != DRIVE_CDROM)
+ || GetVolumeInformation(path, nullptr, 0, nullptr, nullptr,
+ &fileSystemFlags, nullptr, 0) == TRUE;
+}
+#endif // !Q_OS_WINRT
+
QFileInfoList QFSFileEngine::drives()
{
QFileInfoList ret;
#if !defined(Q_OS_WINRT)
-# if defined(Q_OS_WIN32)
const UINT oldErrorMode = ::SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
quint32 driveBits = (quint32) GetLogicalDrives() & 0x3ffffff;
- ::SetErrorMode(oldErrorMode);
-# endif
- char driveName[] = "A:/";
+ wchar_t driveName[] = L"A:\\";
while (driveBits) {
- if (driveBits & 1)
- ret.append(QFileInfo(QLatin1String(driveName)));
+ if ((driveBits & 1) && isDriveReady(driveName))
+ ret.append(QFileInfo(QString::fromWCharArray(driveName)));
driveName[0]++;
driveBits = driveBits >> 1;
}
+ ::SetErrorMode(oldErrorMode);
return ret;
#else // !Q_OS_WINRT
ret.append(QFileInfo(QLatin1String("/")));
@@ -591,7 +600,6 @@ bool QFSFileEnginePrivate::doStat(QFileSystemMetaData::MetaDataFlags flags) cons
bool QFSFileEngine::link(const QString &newName)
{
#if !defined(Q_OS_WINRT)
-# if QT_CONFIG(library)
bool ret = false;
QString linkName = newName;
@@ -600,23 +608,27 @@ bool QFSFileEngine::link(const QString &newName)
IShellLink *psl;
bool neededCoInit = false;
- HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
+ HRESULT hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink,
+ reinterpret_cast<void **>(&psl));
if (hres == CO_E_NOTINITIALIZED) { // COM was not initialized
neededCoInit = true;
- CoInitialize(NULL);
- hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
+ CoInitialize(nullptr);
+ hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink,
+ reinterpret_cast<void **>(&psl));
}
if (SUCCEEDED(hres)) {
- hres = psl->SetPath((wchar_t *)fileName(AbsoluteName).replace(QLatin1Char('/'), QLatin1Char('\\')).utf16());
+ const QString nativeAbsoluteName = fileName(AbsoluteName).replace(QLatin1Char('/'), QLatin1Char('\\'));
+ hres = psl->SetPath(reinterpret_cast<const wchar_t *>(nativeAbsoluteName.utf16()));
if (SUCCEEDED(hres)) {
- hres = psl->SetWorkingDirectory((wchar_t *)fileName(AbsolutePathName).replace(QLatin1Char('/'), QLatin1Char('\\')).utf16());
+ const QString nativeAbsolutePathName = fileName(AbsolutePathName).replace(QLatin1Char('/'), QLatin1Char('\\'));
+ hres = psl->SetWorkingDirectory(reinterpret_cast<const wchar_t *>(nativeAbsolutePathName.utf16()));
if (SUCCEEDED(hres)) {
IPersistFile *ppf;
- hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
+ hres = psl->QueryInterface(IID_IPersistFile, reinterpret_cast<void **>(&ppf));
if (SUCCEEDED(hres)) {
- hres = ppf->Save((wchar_t*)linkName.utf16(), TRUE);
+ hres = ppf->Save(reinterpret_cast<const wchar_t *>(linkName.utf16()), TRUE);
if (SUCCEEDED(hres))
ret = true;
ppf->Release();
@@ -632,10 +644,6 @@ bool QFSFileEngine::link(const QString &newName)
CoUninitialize();
return ret;
-# else // QT_CONFIG(library)
- Q_UNUSED(newName);
- return false;
-# endif // QT_CONFIG(library)
#else // !Q_OS_WINRT
Q_UNUSED(newName);
Q_UNIMPLEMENTED();
@@ -768,10 +776,9 @@ QString QFSFileEngine::fileName(FileName file) const
int slash = ret.lastIndexOf(QLatin1Char('/'));
if (slash < 0)
return ret;
- else if (ret.at(0) != QLatin1Char('/') && slash == 2)
+ if (ret.at(0) != QLatin1Char('/') && slash == 2)
return ret.left(3); // include the slash
- else
- return ret.left(slash > 0 ? slash : 1);
+ return ret.left(slash > 0 ? slash : 1);
}
return ret;
} else if (file == CanonicalName || file == CanonicalPathName) {
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp
index 95a5fb27cf..86e21f0a66 100644
--- a/src/corelib/io/qiodevice.cpp
+++ b/src/corelib/io/qiodevice.cpp
@@ -312,8 +312,9 @@ QIODevicePrivate::~QIODevicePrivate()
\value NotOpen The device is not open.
\value ReadOnly The device is open for reading.
- \value WriteOnly The device is open for writing. Note that this mode implies
- Truncate.
+ \value WriteOnly The device is open for writing. Note that, for file-system
+ subclasses (e.g. QFile), this mode implies Truncate unless
+ combined with ReadOnly, Append or NewOnly.
\value ReadWrite The device is open for reading and writing.
\value Append The device is opened in append mode so that all data is
written to the end of the file.
@@ -332,7 +333,7 @@ QIODevicePrivate::~QIODevicePrivate()
allowed. This flag currently only affects QFile. Other
classes might use this flag in the future, but until then
using this flag with any classes other than QFile may
- result in undefined behavior.
+ result in undefined behavior. (since Qt 5.11)
\value ExistingOnly Fail if the file to be opened does not exist. This flag
must be specified alongside ReadOnly, WriteOnly, or
ReadWrite. Note that using this flag with ReadOnly alone
@@ -340,7 +341,7 @@ QIODevicePrivate::~QIODevicePrivate()
not exist. This flag currently only affects QFile. Other
classes might use this flag in the future, but until then
using this flag with any classes other than QFile may
- result in undefined behavior.
+ result in undefined behavior. (since Qt 5.11)
Certain flags, such as \c Unbuffered and \c Truncate, are
meaningless when used with some subclasses. Some of these
diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp
index aa84f56368..33253429a2 100644
--- a/src/corelib/io/qloggingcategory.cpp
+++ b/src/corelib/io/qloggingcategory.cpp
@@ -135,9 +135,7 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
flexible way. Rules are specified in text, where every line must have the
format
- \code
- <category>[.<type>] = true|false
- \endcode
+ \snippet code/src_corelib_io_qloggingcategory.cpp 0
\c <category> is the name of the category, potentially with \c{*} as a
wildcard symbol as the first or last character (or at both positions).
@@ -149,10 +147,7 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
Rules can be set via \l setFilterRules():
- \code
- QLoggingCategory::setFilterRules("*.debug=false\n"
- "driver.usb.debug=true");
- \endcode
+ \snippet code/src_corelib_io_qloggingcategory.cpp 1
Since Qt 5.3, logging rules are also
automatically loaded from the \c [Rules] section of a logging
@@ -160,19 +155,13 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
configuration directory, or explicitly set in a \c QT_LOGGING_CONF
environment variable:
- \code
- [Rules]
- *.debug=false
- driver.usb.debug=true
- \endcode
+ \snippet code/src_corelib_io_qloggingcategory.cpp 2
Since Qt 5.3, logging rules can also be specified in a \c QT_LOGGING_RULES
environment variable. And since Qt 5.6, multiple rules can also be
separated by semicolons:
- \code
- QT_LOGGING_RULES="*.debug=false;driver.usb.debug=true"
- \endcode
+ \snippet code/src_corelib_io_qloggingcategory.cpp 3
Rules set by \l setFilterRules() take precedence over rules specified
in the QtProject configuration directory, and can, in turn, be
diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp
index cd97268d71..9792d956cc 100644
--- a/src/corelib/io/qloggingregistry.cpp
+++ b/src/corelib/io/qloggingregistry.cpp
@@ -46,6 +46,11 @@
#include <QtCore/qdir.h>
#include <QtCore/qcoreapplication.h>
+#if QT_CONFIG(settings)
+#include <QtCore/qsettings.h>
+#include <QtCore/private/qsettings_p.h>
+#endif
+
// We can't use the default macros because this would lead to recursion.
// Instead let's define our own one that unconditionally logs...
#define debugMsg QMessageLogger(__FILE__, __LINE__, __FUNCTION__, "qt.core.logging").debug
@@ -230,7 +235,14 @@ void QLoggingSettingsParser::parseNextLine(QStringRef line)
int equalPos = line.indexOf(QLatin1Char('='));
if (equalPos != -1) {
if (line.lastIndexOf(QLatin1Char('=')) == equalPos) {
- const auto pattern = line.left(equalPos).trimmed();
+ const auto key = line.left(equalPos).trimmed();
+#if QT_CONFIG(settings)
+ QString tmp;
+ QSettingsPrivate::iniUnescapedKey(key.toUtf8(), 0, key.length(), tmp);
+ QStringRef pattern = QStringRef(&tmp, 0, tmp.length());
+#else
+ QStringRef pattern = key;
+#endif
const auto valueStr = line.mid(equalPos + 1).trimmed();
int value = -1;
if (valueStr == QLatin1String("true"))
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index 713af9bd40..7a2daa2a57 100644
--- a/src/corelib/io/qprocess_unix.cpp
+++ b/src/corelib/io/qprocess_unix.cpp
@@ -101,7 +101,6 @@ QT_END_NAMESPACE
#include <qdir.h>
#include <qlist.h>
#include <qmutex.h>
-#include <qsemaphore.h>
#include <qsocketnotifier.h>
#include <qthread.h>
#include <qelapsedtimer.h>
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index 8c4e5b41b4..cb4b2f9f91 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -149,7 +149,26 @@ static void qt_create_pipe(Q_PIPE *pipe, bool isInputPipe)
}
// Wait until connection is in place.
- ConnectNamedPipe(hServer, NULL);
+ OVERLAPPED overlapped;
+ ZeroMemory(&overlapped, sizeof(overlapped));
+ overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (ConnectNamedPipe(hServer, &overlapped) == 0) {
+ DWORD dwError = GetLastError();
+ switch (dwError) {
+ case ERROR_PIPE_CONNECTED:
+ break;
+ case ERROR_IO_PENDING:
+ WaitForSingleObject(overlapped.hEvent, INFINITE);
+ break;
+ default:
+ qErrnoWarning(dwError, "QProcess: ConnectNamedPipe failed.");
+ CloseHandle(overlapped.hEvent);
+ CloseHandle(hClient);
+ CloseHandle(hServer);
+ return;
+ }
+ }
+ CloseHandle(overlapped.hEvent);
if (isInputPipe) {
pipe[0] = hClient;
@@ -183,7 +202,8 @@ bool QProcessPrivate::openChannel(Channel &channel)
&stderrChannel.pipe[1], 0, TRUE, DUPLICATE_SAME_ACCESS);
}
- if (channel.type == Channel::Normal) {
+ switch (channel.type) {
+ case Channel::Normal:
// we're piping this channel to our own process
if (&channel == &stdinChannel) {
if (inputChannelMode != QProcess::ForwardedInputChannel) {
@@ -223,9 +243,8 @@ bool QProcessPrivate::openChannel(Channel &channel)
channel.reader->startAsyncRead();
}
}
-
return true;
- } else if (channel.type == Channel::Redirect) {
+ case Channel::Redirect: {
// we're redirecting the channel to/from a file
SECURITY_ATTRIBUTES secAtt = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
@@ -270,65 +289,65 @@ bool QProcessPrivate::openChannel(Channel &channel)
}
cleanup();
return false;
- } else {
+ }
+ case Channel::PipeSource: {
Q_ASSERT_X(channel.process, "QProcess::start", "Internal error");
+ // we are the source
+ Channel *source = &channel;
+ Channel *sink = &channel.process->stdinChannel;
+
+ if (source->pipe[1] != INVALID_Q_PIPE) {
+ // already constructed by the sink
+ // make it inheritable
+ HANDLE tmpHandle = source->pipe[1];
+ if (!DuplicateHandle(GetCurrentProcess(), tmpHandle,
+ GetCurrentProcess(), &source->pipe[1],
+ 0, TRUE, DUPLICATE_SAME_ACCESS)) {
+ return false;
+ }
- Channel *source;
- Channel *sink;
+ CloseHandle(tmpHandle);
+ return true;
+ }
- if (channel.type == Channel::PipeSource) {
- // we are the source
- source = &channel;
- sink = &channel.process->stdinChannel;
+ Q_ASSERT(source == &stdoutChannel);
+ Q_ASSERT(sink->process == this && sink->type == Channel::PipeSink);
- if (source->pipe[1] != INVALID_Q_PIPE) {
- // already constructed by the sink
- // make it inheritable
- HANDLE tmpHandle = source->pipe[1];
- if (!DuplicateHandle(GetCurrentProcess(), tmpHandle,
- GetCurrentProcess(), &source->pipe[1],
- 0, TRUE, DUPLICATE_SAME_ACCESS))
- return false;
+ qt_create_pipe(source->pipe, /* in = */ false); // source is stdout
+ sink->pipe[0] = source->pipe[0];
+ source->pipe[0] = INVALID_Q_PIPE;
- CloseHandle(tmpHandle);
- return true;
+ return true;
+ }
+ case Channel::PipeSink: { // we are the sink;
+ Q_ASSERT_X(channel.process, "QProcess::start", "Internal error");
+ Channel *source = &channel.process->stdoutChannel;
+ Channel *sink = &channel;
+
+ if (sink->pipe[0] != INVALID_Q_PIPE) {
+ // already constructed by the source
+ // make it inheritable
+ HANDLE tmpHandle = sink->pipe[0];
+ if (!DuplicateHandle(GetCurrentProcess(), tmpHandle,
+ GetCurrentProcess(), &sink->pipe[0],
+ 0, TRUE, DUPLICATE_SAME_ACCESS)) {
+ return false;
}
- Q_ASSERT(source == &stdoutChannel);
- Q_ASSERT(sink->process == this && sink->type == Channel::PipeSink);
-
- qt_create_pipe(source->pipe, /* in = */ false); // source is stdout
- sink->pipe[0] = source->pipe[0];
- source->pipe[0] = INVALID_Q_PIPE;
-
+ CloseHandle(tmpHandle);
return true;
- } else {
- // we are the sink;
- source = &channel.process->stdoutChannel;
- sink = &channel;
-
- if (sink->pipe[0] != INVALID_Q_PIPE) {
- // already constructed by the source
- // make it inheritable
- HANDLE tmpHandle = sink->pipe[0];
- if (!DuplicateHandle(GetCurrentProcess(), tmpHandle,
- GetCurrentProcess(), &sink->pipe[0],
- 0, TRUE, DUPLICATE_SAME_ACCESS))
- return false;
-
- CloseHandle(tmpHandle);
- return true;
- }
- Q_ASSERT(sink == &stdinChannel);
- Q_ASSERT(source->process == this && source->type == Channel::PipeSource);
+ }
+ Q_ASSERT(sink == &stdinChannel);
+ Q_ASSERT(source->process == this && source->type == Channel::PipeSource);
- qt_create_pipe(sink->pipe, /* in = */ true); // sink is stdin
- source->pipe[1] = sink->pipe[1];
- sink->pipe[1] = INVALID_Q_PIPE;
+ qt_create_pipe(sink->pipe, /* in = */ true); // sink is stdin
+ source->pipe[1] = sink->pipe[1];
+ sink->pipe[1] = INVALID_Q_PIPE;
- return true;
- }
+ return true;
}
+ } // switch (channel.type)
+ return false;
}
void QProcessPrivate::destroyPipe(Q_PIPE pipe[2])
diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp
index 7502fb57a3..367cd78d65 100644
--- a/src/corelib/io/qresource.cpp
+++ b/src/corelib/io/qresource.cpp
@@ -52,7 +52,9 @@
#include "qendian.h"
#include <qshareddata.h>
#include <qplatformdefs.h>
+#include <qendian.h>
#include "private/qabstractfileengine_p.h"
+#include "private/qsimd_p.h"
#include "private/qsystemerror_p.h"
#ifdef Q_OS_UNIX
@@ -629,17 +631,13 @@ inline QString QResourceRoot::name(int node) const
QString ret;
qint32 name_offset = qFromBigEndian<qint32>(tree + offset);
- const qint16 name_length = qFromBigEndian<qint16>(names + name_offset);
+ quint16 name_length = qFromBigEndian<qint16>(names + name_offset);
name_offset += 2;
name_offset += 4; //jump past hash
ret.resize(name_length);
QChar *strData = ret.data();
- for(int i = 0; i < name_length*2; i+=2) {
- QChar c(names[name_offset+i+1], names[name_offset+i]);
- *strData = c;
- ++strData;
- }
+ qFromBigEndian<ushort>(names + name_offset, name_length, strData);
return ret;
}
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index 4b1b9888d8..391d2a49af 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -77,6 +77,10 @@
# include <ioLib.h>
#endif
+#ifdef Q_OS_WASM
+#include <emscripten.h>
+#endif
+
#include <algorithm>
#include <stdlib.h>
@@ -1544,6 +1548,13 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
perms |= QFile::ReadGroup | QFile::ReadOther;
QFile(confFile->name).setPermissions(perms);
}
+#ifdef Q_OS_WASM
+ EM_ASM(
+ // Sync sandbox filesystem to persistent database filesystem. See QTBUG-70002
+ FS.syncfs(false, function(err) {
+ });
+ );
+#endif
} else {
setStatus(QSettings::AccessError);
}
@@ -1694,10 +1705,10 @@ bool QConfFileSettingsPrivate::readIniFile(const QByteArray &data,
iniSection = iniSection.trimmed();
- if (qstricmp(iniSection.constData(), "general") == 0) {
+ if (iniSection.compare("general", Qt::CaseInsensitive) == 0) {
currentSection.clear();
} else {
- if (qstricmp(iniSection.constData(), "%general") == 0) {
+ if (iniSection.compare("%general", Qt::CaseInsensitive) == 0) {
currentSection = QLatin1String(iniSection.constData() + 1);
} else {
currentSection.clear();
@@ -1857,7 +1868,7 @@ bool QConfFileSettingsPrivate::writeIniFile(QIODevice &device, const ParsedSetti
if (realSection.isEmpty()) {
realSection = "[General]";
- } else if (qstricmp(realSection.constData(), "general") == 0) {
+ } else if (realSection.compare("general", Qt::CaseInsensitive) == 0) {
realSection = "[%General]";
} else {
realSection.prepend('[');
diff --git a/src/corelib/io/qsettings_mac.cpp b/src/corelib/io/qsettings_mac.cpp
index aa14d8435a..28f01eae4d 100644
--- a/src/corelib/io/qsettings_mac.cpp
+++ b/src/corelib/io/qsettings_mac.cpp
@@ -355,15 +355,15 @@ public:
const QString &application);
~QMacSettingsPrivate();
- void remove(const QString &key);
- void set(const QString &key, const QVariant &value);
- bool get(const QString &key, QVariant *value) const;
- QStringList children(const QString &prefix, ChildSpec spec) const;
- void clear();
- void sync();
- void flush();
- bool isWritable() const;
- QString fileName() const;
+ void remove(const QString &key) override;
+ void set(const QString &key, const QVariant &value) override;
+ bool get(const QString &key, QVariant *value) const override;
+ QStringList children(const QString &prefix, ChildSpec spec) const override;
+ void clear() override;
+ void sync() override;
+ void flush() override;
+ bool isWritable() const override;
+ QString fileName() const override;
private:
struct SearchDomain
diff --git a/src/corelib/io/qsettings_win.cpp b/src/corelib/io/qsettings_win.cpp
index edcae16776..1881d0dc7e 100644
--- a/src/corelib/io/qsettings_win.cpp
+++ b/src/corelib/io/qsettings_win.cpp
@@ -377,23 +377,24 @@ typedef QVector<RegistryKey> RegistryKeyList;
class QWinSettingsPrivate : public QSettingsPrivate
{
+ Q_DISABLE_COPY(QWinSettingsPrivate)
public:
QWinSettingsPrivate(QSettings::Scope scope, const QString &organization,
const QString &application, REGSAM access = 0);
QWinSettingsPrivate(QString rKey, REGSAM access = 0);
- ~QWinSettingsPrivate();
-
- void remove(const QString &uKey);
- void set(const QString &uKey, const QVariant &value);
- bool get(const QString &uKey, QVariant *value) const;
- QStringList children(const QString &uKey, ChildSpec spec) const;
- void clear();
- void sync();
- void flush();
- bool isWritable() const;
+ ~QWinSettingsPrivate() override;
+
+ void remove(const QString &uKey) override;
+ void set(const QString &uKey, const QVariant &value) override;
+ bool get(const QString &uKey, QVariant *value) const override;
+ QStringList children(const QString &uKey, ChildSpec spec) const override;
+ void clear() override;
+ void sync() override;
+ void flush() override;
+ bool isWritable() const override;
HKEY writeHandle() const;
bool readKey(HKEY parentHandle, const QString &rSubKey, QVariant *value) const;
- QString fileName() const;
+ QString fileName() const override;
private:
RegistryKeyList regList; // list of registry locations to search for keys
@@ -515,7 +516,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa
case REG_SZ: {
QString s;
if (dataSize) {
- s = QString::fromWCharArray(((const wchar_t *)data.constData()));
+ s = QString::fromWCharArray(reinterpret_cast<const wchar_t *>(data.constData()));
}
if (value != 0)
*value = stringToVariant(s);
@@ -527,7 +528,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa
if (dataSize) {
int i = 0;
for (;;) {
- QString s = QString::fromWCharArray((const wchar_t *)data.constData() + i);
+ QString s = QString::fromWCharArray(reinterpret_cast<const wchar_t *>(data.constData()) + i);
i += s.length() + 1;
if (s.isEmpty())
@@ -544,7 +545,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa
case REG_BINARY: {
QString s;
if (dataSize) {
- s = QString::fromWCharArray((const wchar_t *)data.constData(), data.size() / 2);
+ s = QString::fromWCharArray(reinterpret_cast<const wchar_t *>(data.constData()), data.size() / 2);
}
if (value != 0)
*value = stringToVariant(s);
@@ -555,7 +556,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa
case REG_DWORD: {
Q_ASSERT(data.size() == sizeof(int));
int i;
- memcpy((char*)&i, data.constData(), sizeof(int));
+ memcpy(reinterpret_cast<char*>(&i), data.constData(), sizeof(int));
if (value != 0)
*value = i;
break;
@@ -564,7 +565,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa
case REG_QWORD: {
Q_ASSERT(data.size() == sizeof(qint64));
qint64 i;
- memcpy((char*)&i, data.constData(), sizeof(qint64));
+ memcpy(reinterpret_cast<char*>(&i), data.constData(), sizeof(qint64));
if (value != 0)
*value = i;
break;
@@ -629,11 +630,9 @@ void QWinSettingsPrivate::remove(const QString &uKey)
deleteChildGroups(handle, access);
if (rKey.isEmpty()) {
- QStringList childKeys = childKeysOrGroups(handle, QSettingsPrivate::ChildKeys);
-
- for (int i = 0; i < childKeys.size(); ++i) {
- QString group = childKeys.at(i);
+ const QStringList childKeys = childKeysOrGroups(handle, QSettingsPrivate::ChildKeys);
+ for (const QString &group : childKeys) {
LONG res = RegDeleteValue(handle, reinterpret_cast<const wchar_t *>(group.utf16()));
if (res != ERROR_SUCCESS) {
qWarning("QSettings: RegDeleteValue failed on subkey \"%s\": %s",
@@ -688,12 +687,12 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
if (type == REG_BINARY) {
QString s = variantToString(value);
- regValueBuff = QByteArray((const char*)s.utf16(), s.length() * 2);
+ regValueBuff = QByteArray(reinterpret_cast<const char*>(s.utf16()), s.length() * 2);
} else {
QStringList::const_iterator it = l.constBegin();
for (; it != l.constEnd(); ++it) {
const QString &s = *it;
- regValueBuff += QByteArray((const char*)s.utf16(), (s.length() + 1) * 2);
+ regValueBuff += QByteArray(reinterpret_cast<const char*>(s.utf16()), (s.length() + 1) * 2);
}
regValueBuff.append((char)0);
regValueBuff.append((char)0);
@@ -705,7 +704,7 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
case QVariant::UInt: {
type = REG_DWORD;
qint32 i = value.toInt();
- regValueBuff = QByteArray((const char*)&i, sizeof(qint32));
+ regValueBuff = QByteArray(reinterpret_cast<const char*>(&i), sizeof(qint32));
break;
}
@@ -713,7 +712,7 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
case QVariant::ULongLong: {
type = REG_QWORD;
qint64 i = value.toLongLong();
- regValueBuff = QByteArray((const char*)&i, sizeof(qint64));
+ regValueBuff = QByteArray(reinterpret_cast<const char*>(&i), sizeof(qint64));
break;
}
@@ -725,11 +724,11 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
// string type. Otherwise we use REG_BINARY.
QString s = variantToString(value);
type = s.contains(QChar::Null) ? REG_BINARY : REG_SZ;
- if (type == REG_BINARY) {
- regValueBuff = QByteArray((const char*)s.utf16(), s.length() * 2);
- } else {
- regValueBuff = QByteArray((const char*)s.utf16(), (s.length() + 1) * 2);
- }
+ int length = s.length();
+ if (type == REG_SZ)
+ ++length;
+ regValueBuff = QByteArray(reinterpret_cast<const char *>(s.utf16()),
+ int(sizeof(wchar_t)) * length);
break;
}
}
@@ -754,8 +753,8 @@ bool QWinSettingsPrivate::get(const QString &uKey, QVariant *value) const
{
QString rKey = escapedKey(uKey);
- for (int i = 0; i < regList.size(); ++i) {
- HKEY handle = regList.at(i).handle();
+ for (const RegistryKey &r : regList) {
+ HKEY handle = r.handle();
if (handle != 0 && readKey(handle, rKey, value))
return true;
@@ -771,8 +770,8 @@ QStringList QWinSettingsPrivate::children(const QString &uKey, ChildSpec spec) c
NameSet result;
QString rKey = escapedKey(uKey);
- for (int i = 0; i < regList.size(); ++i) {
- HKEY parent_handle = regList.at(i).handle();
+ for (const RegistryKey &r : regList) {
+ HKEY parent_handle = r.handle();
if (parent_handle == 0)
continue;
HKEY handle = openKey(parent_handle, KEY_READ, rKey, access);
@@ -836,26 +835,32 @@ bool QWinSettingsPrivate::isWritable() const
QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format, QSettings::Scope scope,
const QString &organization, const QString &application)
{
- if (format == QSettings::NativeFormat)
+ switch (format) {
+ case QSettings::NativeFormat:
return new QWinSettingsPrivate(scope, organization, application);
- else if (format == QSettings::Registry32Format)
+ case QSettings::Registry32Format:
return new QWinSettingsPrivate(scope, organization, application, KEY_WOW64_32KEY);
- else if (format == QSettings::Registry64Format)
+ case QSettings::Registry64Format:
return new QWinSettingsPrivate(scope, organization, application, KEY_WOW64_64KEY);
- else
- return new QConfFileSettingsPrivate(format, scope, organization, application);
+ default:
+ break;
+ }
+ return new QConfFileSettingsPrivate(format, scope, organization, application);
}
QSettingsPrivate *QSettingsPrivate::create(const QString &fileName, QSettings::Format format)
{
- if (format == QSettings::NativeFormat)
+ switch (format) {
+ case QSettings::NativeFormat:
return new QWinSettingsPrivate(fileName);
- else if (format == QSettings::Registry32Format)
+ case QSettings::Registry32Format:
return new QWinSettingsPrivate(fileName, KEY_WOW64_32KEY);
- else if (format == QSettings::Registry64Format)
+ case QSettings::Registry64Format:
return new QWinSettingsPrivate(fileName, KEY_WOW64_64KEY);
- else
- return new QConfFileSettingsPrivate(fileName, format);
+ default:
+ break;
+ }
+ return new QConfFileSettingsPrivate(fileName, format);
}
QT_END_NAMESPACE
diff --git a/src/corelib/io/qsettings_winrt.cpp b/src/corelib/io/qsettings_winrt.cpp
index 209b56d920..4c757f9dda 100644
--- a/src/corelib/io/qsettings_winrt.cpp
+++ b/src/corelib/io/qsettings_winrt.cpp
@@ -290,15 +290,15 @@ public:
QWinRTSettingsPrivate(const QString &rKey);
~QWinRTSettingsPrivate();
- void remove(const QString &uKey);
- void set(const QString &uKey, const QVariant &value);
- bool get(const QString &uKey, QVariant *value) const;
- QStringList children(const QString &uKey, ChildSpec spec) const;
- void clear();
- void sync();
- void flush();
- bool isWritable() const;
- QString fileName() const;
+ void remove(const QString &uKey) override;
+ void set(const QString &uKey, const QVariant &value) override;
+ bool get(const QString &uKey, QVariant *value) const override;
+ QStringList children(const QString &uKey, ChildSpec spec) const override;
+ void clear() override;
+ void sync() override;
+ void flush() override;
+ bool isWritable() const override;
+ QString fileName() const override;
private:
void init(QSettings::Scope scope);
diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp
index b3a5bd797a..dbf650d5f6 100644
--- a/src/corelib/io/qstandardpaths.cpp
+++ b/src/corelib/io/qstandardpaths.cpp
@@ -94,7 +94,8 @@ QT_BEGIN_NAMESPACE
Data interchange with other users is out of the scope of QStandardPaths.
\value DesktopLocation Returns the user's desktop directory. This is a generic value.
- On systems with no concept of a desktop.
+ On systems with no concept of a desktop, this is the same as
+ QStandardPaths::HomeLocation.
\value DocumentsLocation Returns the directory containing user document files.
This is a generic value. The returned path is never empty.
\value FontsLocation Returns the directory containing user's fonts. This is a generic value.
diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
index 1983a22c65..7e3be9ef36 100644
--- a/src/corelib/io/qtemporaryfile.cpp
+++ b/src/corelib/io/qtemporaryfile.cpp
@@ -893,13 +893,7 @@ bool QTemporaryFile::rename(const QString &newName)
For example:
- \code
- QFile f(":/resources/file.txt");
- QTemporaryFile::createNativeFile(f); // Returns a pointer to a temporary file
-
- QFile f("/users/qt/file.txt");
- QTemporaryFile::createNativeFile(f); // Returns 0
- \endcode
+ \snippet code/src_corelib_io_qtemporaryfile.cpp 1
\sa QFileInfo::isNativePath()
*/
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index e7ad13d28f..b324df53b2 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -116,27 +116,12 @@
Calling isRelative() will return whether or not the URL is relative.
A relative URL has no \l {scheme}. For example:
- \code
- qDebug() << QUrl("main.qml").isRelative(); // true: no scheme
- qDebug() << QUrl("qml/main.qml").isRelative(); // true: no scheme
- qDebug() << QUrl("file:main.qml").isRelative(); // false: has "file" scheme
- qDebug() << QUrl("file:qml/main.qml").isRelative(); // false: has "file" scheme
- \endcode
+ \snippet code/src_corelib_io_qurl.cpp 8
Notice that a URL can be absolute while containing a relative path, and
vice versa:
- \code
- // Absolute URL, relative path
- QUrl url("file:file.txt");
- qDebug() << url.isRelative(); // false: has "file" scheme
- qDebug() << QDir::isAbsolutePath(url.path()); // false: relative path
-
- // Relative URL, absolute path
- url = QUrl("/home/user/file.txt");
- qDebug() << url.isRelative(); // true: has no scheme
- qDebug() << QDir::isAbsolutePath(url.path()); // true: absolute path
- \endcode
+ \snippet code/src_corelib_io_qurl.cpp 9
A relative URL can be resolved by passing it as an argument to resolved(),
which returns an absolute URL. isParentOf() is used for determining whether
@@ -369,14 +354,7 @@
The following example illustrates the problem:
- \code
- QUrl original("http://example.com/?q=a%2B%3Db%26c");
- QUrl copy(original);
- copy.setQuery(copy.query(QUrl::FullyDecoded), QUrl::DecodedMode);
-
- qDebug() << original.toString(); // prints: http://example.com/?q=a%2B%3Db%26c
- qDebug() << copy.toString(); // prints: http://example.com/?q=a+=b&c
- \endcode
+ \snippet code/src_corelib_io_qurl.cpp 10
If the two URLs were used via HTTP GET, the interpretation by the web
server would probably be different. In the first case, it would interpret
@@ -472,16 +450,10 @@ static inline QString webDavSslTag()
return QStringLiteral("@SSL");
}
-#ifdef Q_COMPILER_CLASS_ENUM
-# define colon_uchar : uchar
-#else
-# define colon_uchar
-#endif
-
class QUrlPrivate
{
public:
- enum Section colon_uchar {
+ enum Section : uchar {
Scheme = 0x01,
UserName = 0x02,
Password = 0x04,
@@ -496,7 +468,7 @@ public:
FullUrl = 0xff
};
- enum Flags colon_uchar {
+ enum Flags : uchar {
IsLocalFile = 0x01
};
@@ -616,7 +588,6 @@ public:
// 32-bit: 2 bytes tail padding available
// 64-bit: 6 bytes tail padding available
};
-#undef colon_uchar
inline QUrlPrivate::QUrlPrivate()
: ref(1), port(-1),
@@ -1203,15 +1174,13 @@ inline void QUrlPrivate::setQuery(const QString &value, int from, int iend)
inline void QUrlPrivate::appendHost(QString &appendTo, QUrl::FormattingOptions options) const
{
- // EncodeUnicode is the only flag that matters
- if ((options & QUrl::FullyDecoded) == QUrl::FullyDecoded)
- options = 0;
- else
- options &= QUrl::EncodeUnicode;
if (host.isEmpty())
return;
if (host.at(0).unicode() == '[') {
- // IPv6Address and IPvFuture address never require any transformation
+ // IPv6 addresses might contain a zone-id which needs to be recoded
+ if (options != 0)
+ if (qt_urlRecode(appendTo, host.constBegin(), host.constEnd(), options, 0))
+ return;
appendTo += host;
} else {
// this is either an IPv4Address or a reg-name
@@ -1278,31 +1247,44 @@ static const QChar *parseIpFuture(QString &host, const QChar *begin, const QChar
// ONLY the IPv6 address is parsed here, WITHOUT the brackets
static const QChar *parseIp6(QString &host, const QChar *begin, const QChar *end, QUrl::ParsingMode mode)
{
- QIPAddressUtils::IPv6Address address;
- const QChar *ret = QIPAddressUtils::parseIp6(address, begin, end);
- if (ret) {
+ // ### Update to use QStringView once QStringView::indexOf and QStringView::lastIndexOf exists
+ QString decoded;
+ if (mode == QUrl::TolerantMode) {
// this struct is kept in automatic storage because it's only 4 bytes
const ushort decodeColon[] = { decode(':'), 0 };
+ if (qt_urlRecode(decoded, begin, end, QUrl::ComponentFormattingOption::PrettyDecoded, decodeColon) == 0)
+ decoded = QString(begin, end-begin);
+ } else {
+ decoded = QString(begin, end-begin);
+ }
- // IPv6 failed parsing, check if it was a percent-encoded character in
- // the middle and try again
- QString decoded;
- if (mode == QUrl::TolerantMode && qt_urlRecode(decoded, begin, end, 0, decodeColon)) {
- // recurse
- // if the parsing fails again, the qt_urlRecode above will return 0
- ret = parseIp6(host, decoded.constBegin(), decoded.constEnd(), mode);
+ const QLatin1String zoneIdIdentifier("%25");
+ QIPAddressUtils::IPv6Address address;
+ QString zoneId;
- // we can't return ret, otherwise it would be dangling
- return ret ? end : 0;
- }
+ const QChar *endBeforeZoneId = decoded.constEnd();
+
+ int zoneIdPosition = decoded.indexOf(zoneIdIdentifier);
+ if ((zoneIdPosition != -1) && (decoded.lastIndexOf(zoneIdIdentifier) == zoneIdPosition)) {
+ zoneId = decoded.mid(zoneIdPosition + zoneIdIdentifier.size());
+ endBeforeZoneId = decoded.constBegin() + zoneIdPosition;
- // no transformation, nothing to re-parse
- return ret;
+ if (zoneId.isEmpty())
+ return end;
}
- host.reserve(host.size() + (end - begin));
+ const QChar *ret = QIPAddressUtils::parseIp6(address, decoded.constBegin(), endBeforeZoneId);
+ if (ret)
+ return begin + (ret - decoded.constBegin());
+
+ host.reserve(host.size() + (decoded.constEnd() - decoded.constBegin()));
host += QLatin1Char('[');
QIPAddressUtils::toString(host, address);
+
+ if (!zoneId.isEmpty()) {
+ host += zoneIdIdentifier;
+ host += zoneId;
+ }
host += QLatin1Char(']');
return 0;
}
@@ -1987,10 +1969,7 @@ void QUrl::setUrl(const QString &url, ParsingMode parsingMode)
\image qurl-authority2.png
To set the scheme, the following call is used:
- \code
- QUrl url;
- url.setScheme("ftp");
- \endcode
+ \snippet code/src_corelib_io_qurl.cpp 11
The scheme can also be empty, in which case the URL is interpreted
as relative.
@@ -2565,11 +2544,7 @@ void QUrl::setPath(const QString &path, ParsingMode mode)
/*!
Returns the path of the URL.
- \code
- qDebug() << QUrl("file:file.txt").path(); // "file.txt"
- qDebug() << QUrl("/home/user/file.txt").path(); // "/home/user/file.txt"
- qDebug() << QUrl("http://www.example.com/test/123").path(); // "/test/123"
- \endcode
+ \snippet code/src_corelib_io_qurl.cpp 12
The \a options argument controls how to format the path component. All
values produce an unambiguous result. With QUrl::FullyDecoded, all
@@ -2584,27 +2559,18 @@ void QUrl::setPath(const QString &path, ParsingMode mode)
An example of data loss is when you have non-Unicode percent-encoded sequences
and use FullyDecoded (the default):
- \code
- qDebug() << QUrl("/foo%FFbar").path();
- \endcode
+ \snippet code/src_corelib_io_qurl.cpp 13
In this example, there will be some level of data loss because the \c %FF cannot
be converted.
Data loss can also occur when the path contains sub-delimiters (such as \c +):
- \code
- qDebug() << QUrl("/foo+bar%2B").path(); // "/foo+bar+"
- \endcode
+ \snippet code/src_corelib_io_qurl.cpp 14
Other decoding examples:
- \code
- const QUrl url("/tmp/Mambo %235%3F.mp3");
- qDebug() << url.path(QUrl::FullyDecoded); // "/tmp/Mambo #5?.mp3"
- qDebug() << url.path(QUrl::PrettyDecoded); // "/tmp/Mambo #5?.mp3"
- qDebug() << url.path(QUrl::FullyEncoded); // "/tmp/Mambo%20%235%3F.mp3"
- \endcode
+ \snippet code/src_corelib_io_qurl.cpp 15
\sa setPath()
*/
@@ -3855,40 +3821,22 @@ bool QUrl::isDetached() const
An empty \a localFile leads to an empty URL (since Qt 5.4).
- \code
- qDebug() << QUrl::fromLocalFile("file.txt"); // QUrl("file:file.txt")
- qDebug() << QUrl::fromLocalFile("/home/user/file.txt"); // QUrl("file:///home/user/file.txt")
- qDebug() << QUrl::fromLocalFile("file:file.txt"); // doesn't make sense; expects path, not url with scheme
- \endcode
+ \snippet code/src_corelib_io_qurl.cpp 16
In the first line in snippet above, a file URL is constructed from a
local, relative path. A file URL with a relative path only makes sense
if there is a base URL to resolve it against. For example:
- \code
- QUrl url = QUrl::fromLocalFile("file.txt");
- QUrl baseUrl = QUrl("file:/home/user/");
- // wrong: prints QUrl("file:file.txt"), as url already has a scheme
- qDebug() << baseUrl.resolved(url);
- \endcode
+ \snippet code/src_corelib_io_qurl.cpp 17
To resolve such a URL, it's necessary to remove the scheme beforehand:
- \code
- // correct: prints QUrl("file:///home/user/file.txt")
- url.setScheme(QString());
- qDebug() << baseUrl.resolved(url);
- \endcode
+ \snippet code/src_corelib_io_qurl.cpp 18
For this reason, it is better to use a relative URL (that is, no scheme)
for relative file paths:
- \code
- QUrl url = QUrl("file.txt");
- QUrl baseUrl = QUrl("file:/home/user/");
- // prints QUrl("file:///home/user/file.txt")
- qDebug() << baseUrl.resolved(url);
- \endcode
+ \snippet code/src_corelib_io_qurl.cpp 19
\sa toLocalFile(), isLocalFile(), QDir::toNativeSeparators()
*/
@@ -3934,11 +3882,7 @@ QUrl QUrl::fromLocalFile(const QString &localFile)
returned value in the form found on SMB networks (for example,
"//servername/path/to/file.txt").
- \code
- qDebug() << QUrl("file:file.txt").toLocalFile(); // "file:file.txt"
- qDebug() << QUrl("file:/home/user/file.txt").toLocalFile(); // "file:///home/user/file.txt"
- qDebug() << QUrl("file.txt").toLocalFile(); // ""; wasn't a local file as it had no scheme
- \endcode
+ \snippet code/src_corelib_io_qurl.cpp 20
Note: if the path component of this URL contains a non-UTF-8 binary
sequence (such as %80), the behaviour of this function is undefined.
diff --git a/src/corelib/io/qurlquery.cpp b/src/corelib/io/qurlquery.cpp
index 231a26c211..97e7b8a4eb 100644
--- a/src/corelib/io/qurlquery.cpp
+++ b/src/corelib/io/qurlquery.cpp
@@ -129,10 +129,7 @@ QT_BEGIN_NAMESPACE
Non-standard delimiters should be chosen from among what RFC 3986 calls
"sub-delimiters". They are:
- \code
- sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
- / "*" / "+" / "," / ";" / "="
- \endcode
+ \snippet code/src_corelib_io_qurlquery.cpp 0
Use of other characters is not supported and may result in unexpected
behaviour. QUrlQuery does not verify that you passed a valid delimiter.
@@ -570,10 +567,7 @@ QString QUrlQuery::query(QUrl::ComponentFormattingOptions encoding) const
\note Non-standard delimiters should be chosen from among what RFC 3986 calls
"sub-delimiters". They are:
- \code
- sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
- / "*" / "+" / "," / ";" / "="
- \endcode
+ \snippet code/src_corelib_io_qurlquery.cpp 0
Use of other characters is not supported and may result in unexpected
behaviour. This method does not verify that you passed a valid delimiter.
diff --git a/src/corelib/io/qurlrecode.cpp b/src/corelib/io/qurlrecode.cpp
index a9b23babc0..443ae18b21 100644
--- a/src/corelib/io/qurlrecode.cpp
+++ b/src/corelib/io/qurlrecode.cpp
@@ -40,6 +40,7 @@
#include "qurl.h"
#include "private/qutfcodec_p.h"
#include "private/qtools_p.h"
+#include "private/qsimd_p.h"
QT_BEGIN_NAMESPACE
@@ -474,6 +475,88 @@ non_trivial:
return 0;
}
+/*
+ * Returns true if the input it checked (if it checked anything) is not
+ * encoded. A return of false indicates there's a percent at \a input that
+ * needs to be decoded.
+ */
+#ifdef __SSE2__
+static bool simdCheckNonEncoded(ushort *&output, const ushort *&input, const ushort *end)
+{
+# ifdef __AVX2__
+ const __m256i percents256 = _mm256_broadcastw_epi16(_mm_cvtsi32_si128('%'));
+ const __m128i percents = _mm256_castsi256_si128(percents256);
+# else
+ const __m128i percents = _mm_set1_epi16('%');
+# endif
+
+ uint idx = 0;
+ quint32 mask = 0;
+ if (input + 16 <= end) {
+ qptrdiff offset = 0;
+ for ( ; input + offset + 16 <= end; offset += 16) {
+# ifdef __AVX2__
+ // do 32 bytes at a time using AVX2
+ __m256i data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(input + offset));
+ __m256i comparison = _mm256_cmpeq_epi16(data, percents256);
+ mask = _mm256_movemask_epi8(comparison);
+ _mm256_storeu_si256(reinterpret_cast<__m256i *>(output + offset), data);
+# else
+ // do 32 bytes at a time using unrolled SSE2
+ __m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(input + offset));
+ __m128i data2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(input + offset + 8));
+ __m128i comparison1 = _mm_cmpeq_epi16(data1, percents);
+ __m128i comparison2 = _mm_cmpeq_epi16(data2, percents);
+ uint mask1 = _mm_movemask_epi8(comparison1);
+ uint mask2 = _mm_movemask_epi8(comparison2);
+
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(output + offset), data1);
+ if (!mask1)
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(output + offset + 8), data2);
+ mask = mask1 | (mask2 << 16);
+# endif
+
+ if (mask) {
+ idx = qCountTrailingZeroBits(mask) / 2;
+ break;
+ }
+ }
+
+ input += offset;
+ if (output)
+ output += offset;
+ } else if (input + 8 <= end) {
+ // do 16 bytes at a time
+ __m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(input));
+ __m128i comparison = _mm_cmpeq_epi16(data, percents);
+ mask = _mm_movemask_epi8(comparison);
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(output), data);
+ idx = qCountTrailingZeroBits(quint16(mask)) / 2;
+ } else if (input + 4 <= end) {
+ // do 8 bytes only
+ __m128i data = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(input));
+ __m128i comparison = _mm_cmpeq_epi16(data, percents);
+ mask = _mm_movemask_epi8(comparison) & 0xffu;
+ _mm_storel_epi64(reinterpret_cast<__m128i *>(output), data);
+ idx = qCountTrailingZeroBits(quint8(mask)) / 2;
+ } else {
+ // no percents found (because we didn't check)
+ return true;
+ }
+
+ // advance to the next non-encoded
+ input += idx;
+ output += idx;
+
+ return !mask;
+}
+#else
+static bool simdCheckNonEncoded(...)
+{
+ return true;
+}
+#endif
+
/*!
\since 5.0
\internal
@@ -497,16 +580,21 @@ non_trivial:
*/
static int decode(QString &appendTo, const ushort *begin, const ushort *end)
{
+ // fast check whether there's anything to be decoded in the first place
+ const ushort *input = QtPrivate::qustrchr(QStringView(begin, end), '%');
+ if (Q_LIKELY(input == end))
+ return 0; // nothing to do, it was already decoded!
+
+ // detach
const int origSize = appendTo.size();
- const ushort *input = begin;
- ushort *output = 0;
+ appendTo.resize(origSize + (end - begin));
+ ushort *output = reinterpret_cast<ushort *>(appendTo.begin()) + origSize;
+ memcpy(static_cast<void *>(output), static_cast<const void *>(begin), (input - begin) * sizeof(ushort));
+ output += input - begin;
+
while (input != end) {
- if (*input != '%') {
- if (output)
- *output++ = *input;
- ++input;
- continue;
- }
+ // something was encoded
+ Q_ASSERT(*input == '%');
if (Q_UNLIKELY(end - input < 3 || !isHex(input[1]) || !isHex(input[2]))) {
// badly-encoded data
@@ -515,27 +603,27 @@ static int decode(QString &appendTo, const ushort *begin, const ushort *end)
return end - begin;
}
- if (Q_UNLIKELY(!output)) {
- // detach
- appendTo.resize(origSize + (end - begin));
- output = reinterpret_cast<ushort *>(appendTo.begin()) + origSize;
- memcpy(static_cast<void *>(output), static_cast<const void *>(begin), (input - begin) * sizeof(ushort));
- output += input - begin;
- }
-
++input;
*output++ = decodeNibble(input[0]) << 4 | decodeNibble(input[1]);
if (output[-1] >= 0x80)
output[-1] = QChar::ReplacementCharacter;
input += 2;
- }
- if (output) {
- int len = output - reinterpret_cast<ushort *>(appendTo.begin());
- appendTo.truncate(len);
- return len - origSize;
+ // search for the next percent, copying from input to output
+ if (simdCheckNonEncoded(output, input, end)) {
+ while (input != end) {
+ ushort uc = *input;
+ if (uc == '%')
+ break;
+ *output++ = uc;
+ ++input;
+ }
+ }
}
- return 0;
+
+ int len = output - reinterpret_cast<ushort *>(appendTo.begin());
+ appendTo.truncate(len);
+ return len - origSize;
}
template <size_t N>
@@ -603,6 +691,9 @@ qt_urlRecode(QString &appendTo, const QChar *begin, const QChar *end,
encoding, actionTable, false);
}
+// qstring.cpp
+bool qt_is_ascii(const char *&ptr, const char *end) Q_DECL_NOTHROW;
+
/*!
\internal
\since 5.0
@@ -623,12 +714,7 @@ QString qt_urlRecodeByteArray(const QByteArray &ba)
// control points below 0x20 are fine in QString
const char *in = ba.constData();
const char *const end = ba.constEnd();
- for ( ; in < end; ++in) {
- if (*in & 0x80)
- break;
- }
-
- if (in == end) {
+ if (qt_is_ascii(in, end)) {
// no non-ASCII found, we're safe to convert to QString
return QString::fromLatin1(ba, ba.size());
}
diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp
index 2312d5ca63..15c9f52cf3 100644
--- a/src/corelib/io/qwindowspipereader.cpp
+++ b/src/corelib/io/qwindowspipereader.cpp
@@ -270,13 +270,11 @@ void QWindowsPipeReader::readFileCompleted(DWORD errorCode, DWORD numberOfBytesT
DWORD QWindowsPipeReader::checkPipeState()
{
DWORD bytes;
- if (PeekNamedPipe(handle, NULL, 0, NULL, &bytes, NULL)) {
+ if (PeekNamedPipe(handle, nullptr, 0, nullptr, &bytes, nullptr))
return bytes;
- } else {
- if (!pipeBroken) {
- pipeBroken = true;
- emit pipeClosed();
- }
+ if (!pipeBroken) {
+ pipeBroken = true;
+ emit pipeClosed();
}
return 0;
}
diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp
index 3a6f67521f..e816add91d 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.cpp
+++ b/src/corelib/itemmodels/qabstractitemmodel.cpp
@@ -1866,6 +1866,23 @@ bool QAbstractItemModel::setData(const QModelIndex &index, const QVariant &value
return false;
}
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+/*!
+ \since 6.0
+ Removes the data stored in all the roles for the given \a index.
+ Returns \c{true} if successful; otherwise returns \c{false}.
+ The dataChanged() signal should be emitted if the data was successfully
+ removed.
+ The base class implementation returns \c{false}
+ \sa data(), itemData(), setData(), setItemData()
+*/
+bool QAbstractItemModel::clearItemData(const QModelIndex &index)
+{
+ Q_UNUSED(index);
+ return false;
+}
+#endif
+
/*!
\fn QVariant QAbstractItemModel::data(const QModelIndex &index, int role) const = 0
diff --git a/src/corelib/itemmodels/qabstractitemmodel.h b/src/corelib/itemmodels/qabstractitemmodel.h
index 21171124f9..bec71b0606 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.h
+++ b/src/corelib/itemmodels/qabstractitemmodel.h
@@ -198,6 +198,9 @@ public:
virtual QMap<int, QVariant> itemData(const QModelIndex &index) const;
virtual bool setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles);
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ virtual bool clearItemData(const QModelIndex &index);
+#endif
virtual QStringList mimeTypes() const;
virtual QMimeData *mimeData(const QModelIndexList &indexes) const;
diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
index 6728f0106b..21fbf83382 100644
--- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp
+++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
@@ -146,6 +146,133 @@ private:
int end;
};
+class RegularExpressionData {
+
+private:
+ enum class ExpressionType {
+ RegExp,
+#if QT_CONFIG(regularexpression)
+ RegularExpression
+#endif
+ };
+
+public:
+ RegularExpressionData() :
+ m_type(ExpressionType::RegExp)
+ {}
+
+#if QT_CONFIG(regularexpression)
+ QRegularExpression regularExpression() const
+ {
+ if (m_type == ExpressionType::RegularExpression)
+ return m_regularExpression;
+ return QRegularExpression();
+ }
+
+ void setRegularExpression(const QRegularExpression &rx)
+ {
+ m_type = ExpressionType::RegularExpression;
+ m_regularExpression = rx;
+ m_regExp = QRegExp();
+ }
+#endif
+
+ QRegExp regExp() const
+ {
+ if (m_type == ExpressionType::RegExp)
+ return m_regExp;
+ return QRegExp();
+ }
+
+ void setRegExp(const QRegExp &rx)
+ {
+ m_type = ExpressionType::RegExp;
+ m_regExp = rx;
+#if QT_CONFIG(regularexpression)
+ m_regularExpression = QRegularExpression();
+#endif
+
+ }
+
+ bool isEmpty() const
+ {
+ bool result = true;
+ switch (m_type) {
+ case ExpressionType::RegExp:
+ result = m_regExp.isEmpty();
+ break;
+#if QT_CONFIG(regularexpression)
+ case ExpressionType::RegularExpression:
+ result = m_regularExpression.pattern().isEmpty();
+ break;
+#endif
+ }
+ return result;
+ }
+
+ Qt::CaseSensitivity caseSensitivity() const
+ {
+ Qt::CaseSensitivity sensitivity = Qt::CaseInsensitive;
+ switch (m_type) {
+ case ExpressionType::RegExp:
+ sensitivity = m_regExp.caseSensitivity();
+ break;
+#if QT_CONFIG(regularexpression)
+ case ExpressionType::RegularExpression:
+ {
+ QRegularExpression::PatternOptions options = m_regularExpression.patternOptions();
+ if (!(options & QRegularExpression::CaseInsensitiveOption))
+ sensitivity = Qt::CaseSensitive;
+ }
+ break;
+#endif
+ }
+ return sensitivity;
+ }
+
+ void setCaseSensitivity(Qt::CaseSensitivity cs)
+ {
+ switch (m_type) {
+ case ExpressionType::RegExp:
+ m_regExp.setCaseSensitivity(cs);
+ break;
+#if QT_CONFIG(regularexpression)
+ case ExpressionType::RegularExpression:
+ {
+ QRegularExpression::PatternOptions options = m_regularExpression.patternOptions();
+ options.setFlag(QRegularExpression::CaseInsensitiveOption, cs == Qt::CaseSensitive);
+ m_regularExpression.setPatternOptions(options);
+ }
+ break;
+#endif
+ }
+ }
+
+ bool hasMatch(const QString &str) const
+ {
+ bool result = false;
+ switch (m_type) {
+ case ExpressionType::RegExp:
+ result = str.contains(m_regExp);
+ break;
+#if QT_CONFIG(regularexpression)
+ case ExpressionType::RegularExpression:
+ result = str.contains(m_regularExpression);
+ break;
+#endif
+ }
+ return result;
+ }
+
+private:
+ ExpressionType m_type;
+ QRegExp m_regExp;
+#if QT_CONFIG(regularexpression)
+ QRegularExpression m_regularExpression;
+#endif
+};
+
+
class QSortFilterProxyModelPrivate : public QAbstractProxyModelPrivate
{
Q_DECLARE_PUBLIC(QSortFilterProxyModel)
@@ -171,7 +298,7 @@ public:
int filter_column;
int filter_role;
- QRegExp filter_regexp;
+ RegularExpressionData filter_data;
QModelIndex last_top_source;
bool filter_recursive;
@@ -574,6 +701,19 @@ QVector<QPair<int, int > > QSortFilterProxyModelPrivate::proxy_intervals_for_sou
proxy_intervals.append(QPair<int, int>(first_proxy_item, last_proxy_item));
}
std::stable_sort(proxy_intervals.begin(), proxy_intervals.end());
+ // Consolidate adjacent intervals
+ for (int i = proxy_intervals.size()-1; i > 0; --i) {
+ QPair<int, int> &interval = proxy_intervals[i];
+ QPair<int, int> &preceeding_interval = proxy_intervals[i - 1];
+ if (interval.first == preceeding_interval.second + 1) {
+ preceeding_interval.second = interval.second;
+ interval.first = interval.second = -1;
+ }
+ }
+ proxy_intervals.erase(
+ std::remove_if(proxy_intervals.begin(), proxy_intervals.end(),
+ [](QPair<int, int> &interval) { return interval.first < 0; }),
+ proxy_intervals.end());
return proxy_intervals;
}
@@ -1096,7 +1236,7 @@ void QSortFilterProxyModelPrivate::update_persistent_indexes(
*/
void QSortFilterProxyModelPrivate::filter_about_to_be_changed(const QModelIndex &source_parent)
{
- if (!filter_regexp.pattern().isEmpty() &&
+ if (!filter_data.isEmpty() &&
source_index_mapping.constFind(source_parent) == source_index_mapping.constEnd())
create_mapping(source_parent);
}
@@ -1773,9 +1913,9 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsMoved(
If a parent item doesn't match the filter, none of its children will be
shown.
- A common use case is to let the user specify the filter regexp, wildcard
- pattern, or fixed string in a QLineEdit and to connect the
- \l{QLineEdit::textChanged()}{textChanged()} signal to setFilterRegExp(),
+ A common use case is to let the user specify the filter regular expression,
+ wildcard pattern, or fixed string in a QLineEdit and to connect the
+ \l{QLineEdit::textChanged()}{textChanged()} signal to setFilterRegularExpression(),
setFilterWildcard(), or setFilterFixedString() to reapply the filter.
Custom filtering behavior can be achieved by reimplementing the
@@ -1812,6 +1952,21 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsMoved(
\note Some general guidelines for subclassing models are available in the
\l{Model Subclassing Reference}.
+ \note With Qt 5, regular expression support has been improved through the
+ QRegularExpression class. QSortFilterProxyModel dating back prior to that
+ class creation, it originally supported only QRegExp. Since Qt 5.12,
+ QRegularExpression APIs have been added. Therefore, QRegExp APIs should be
+ considered deprecated and the QRegularExpression version should be used in
+ place.
+
+ \warning Don't mix calls to the getters and setters of different regexp types
+ as this will lead to unexpected results. For maximum compatibility, the original
+ implementation has been kept. Therefore, if, for example, a call to
+ setFilterRegularExpression is made followed by another one to
+ setFilterFixedString, the first call will setup a QRegularExpression object
+ to use as filter while the second will setup a QRegExp in FixedString mode.
+ However, this is an implementation detail that might change in the future.
+
\sa QAbstractProxyModel, QAbstractItemModel, {Model/View Programming},
{Basic Sort/Filter Model Example}, {Custom Sort/Filter Model Example}, QIdentityProxyModel
*/
@@ -2424,17 +2579,47 @@ Qt::SortOrder QSortFilterProxyModel::sortOrder() const
QRegExp QSortFilterProxyModel::filterRegExp() const
{
Q_D(const QSortFilterProxyModel);
- return d->filter_regexp;
+ return d->filter_data.regExp();
}
void QSortFilterProxyModel::setFilterRegExp(const QRegExp &regExp)
{
Q_D(QSortFilterProxyModel);
d->filter_about_to_be_changed();
- d->filter_regexp = regExp;
+ d->filter_data.setRegExp(regExp);
d->filter_changed();
}
+#if QT_CONFIG(regularexpression)
+/*!
+ \since 5.12
+ \property QSortFilterProxyModel::filterRegularExpression
+ \brief the QRegularExpression used to filter the contents of the source model
+
+ Setting this property overwrites the current
+ \l{QSortFilterProxyModel::filterCaseSensitivity}{filterCaseSensitivity}.
+ By default, the QRegularExpression is an empty string matching all contents.
+
+ If no QRegularExpression or an empty string is set, everything in the source
+ model will be accepted.
+
+ \sa filterCaseSensitivity, setFilterWildcard(), setFilterFixedString()
+*/
+QRegularExpression QSortFilterProxyModel::filterRegularExpression() const
+{
+ Q_D(const QSortFilterProxyModel);
+ return d->filter_data.regularExpression();
+}
+
+void QSortFilterProxyModel::setFilterRegularExpression(const QRegularExpression &regularExpression)
+{
+ Q_D(QSortFilterProxyModel);
+ d->filter_about_to_be_changed();
+ d->filter_data.setRegularExpression(regularExpression);
+ d->filter_changed();
+}
+#endif
+
/*!
\property QSortFilterProxyModel::filterKeyColumn
\brief the column where the key used to filter the contents of the
@@ -2470,16 +2655,16 @@ void QSortFilterProxyModel::setFilterKeyColumn(int column)
Qt::CaseSensitivity QSortFilterProxyModel::filterCaseSensitivity() const
{
Q_D(const QSortFilterProxyModel);
- return d->filter_regexp.caseSensitivity();
+ return d->filter_data.caseSensitivity();
}
void QSortFilterProxyModel::setFilterCaseSensitivity(Qt::CaseSensitivity cs)
{
Q_D(QSortFilterProxyModel);
- if (cs == d->filter_regexp.caseSensitivity())
+ if (cs == d->filter_data.caseSensitivity())
return;
d->filter_about_to_be_changed();
- d->filter_regexp.setCaseSensitivity(cs);
+ d->filter_data.setCaseSensitivity(cs);
d->filter_changed();
}
@@ -2545,11 +2730,34 @@ void QSortFilterProxyModel::setFilterRegExp(const QString &pattern)
{
Q_D(QSortFilterProxyModel);
d->filter_about_to_be_changed();
- d->filter_regexp.setPatternSyntax(QRegExp::RegExp);
- d->filter_regexp.setPattern(pattern);
+ QRegExp rx(pattern);
+ rx.setCaseSensitivity(d->filter_data.caseSensitivity());
+ d->filter_data.setRegExp(rx);
d->filter_changed();
}
+#if QT_CONFIG(regularexpression)
+/*!
+ \since 5.12
+
+ Sets the regular expression used to filter the contents
+ of the source model to \a pattern.
+
+ This method should be preferred for new code as it will use
+ QRegularExpression internally.
+
+ \sa setFilterCaseSensitivity(), setFilterWildcard(), setFilterFixedString(), filterRegularExpression()
+*/
+void QSortFilterProxyModel::setFilterRegularExpression(const QString &pattern)
+{
+ Q_D(QSortFilterProxyModel);
+ d->filter_about_to_be_changed();
+ QRegularExpression rx(pattern);
+ d->filter_data.setRegularExpression(rx);
+ d->filter_changed();
+}
+#endif
+
/*!
Sets the wildcard expression used to filter the contents
of the source model to the given \a pattern.
@@ -2560,8 +2768,8 @@ void QSortFilterProxyModel::setFilterWildcard(const QString &pattern)
{
Q_D(QSortFilterProxyModel);
d->filter_about_to_be_changed();
- d->filter_regexp.setPatternSyntax(QRegExp::Wildcard);
- d->filter_regexp.setPattern(pattern);
+ QRegExp rx(pattern, d->filter_data.caseSensitivity(), QRegExp::Wildcard);
+ d->filter_data.setRegExp(rx);
d->filter_changed();
}
@@ -2575,8 +2783,8 @@ void QSortFilterProxyModel::setFilterFixedString(const QString &pattern)
{
Q_D(QSortFilterProxyModel);
d->filter_about_to_be_changed();
- d->filter_regexp.setPatternSyntax(QRegExp::FixedString);
- d->filter_regexp.setPattern(pattern);
+ QRegExp rx(pattern, d->filter_data.caseSensitivity(), QRegExp::FixedString);
+ d->filter_data.setRegExp(rx);
d->filter_changed();
}
@@ -2801,14 +3009,15 @@ bool QSortFilterProxyModel::lessThan(const QModelIndex &source_left, const QMode
bool QSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
Q_D(const QSortFilterProxyModel);
- if (d->filter_regexp.isEmpty())
+
+ if (d->filter_data.isEmpty())
return true;
if (d->filter_column == -1) {
int column_count = d->model->columnCount(source_parent);
for (int column = 0; column < column_count; ++column) {
QModelIndex source_index = d->model->index(source_row, column, source_parent);
QString key = d->model->data(source_index, d->filter_role).toString();
- if (key.contains(d->filter_regexp))
+ if (d->filter_data.hasMatch(key))
return true;
}
return false;
@@ -2817,7 +3026,7 @@ bool QSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &
if (!source_index.isValid()) // the column may not exist
return true;
QString key = d->model->data(source_index, d->filter_role).toString();
- return key.contains(d->filter_regexp);
+ return d->filter_data.hasMatch(key);
}
/*!
diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.h b/src/corelib/itemmodels/qsortfilterproxymodel.h
index 907ceb8e6d..0be8b88672 100644
--- a/src/corelib/itemmodels/qsortfilterproxymodel.h
+++ b/src/corelib/itemmodels/qsortfilterproxymodel.h
@@ -43,6 +43,10 @@
#include <QtCore/qabstractproxymodel.h>
#include <QtCore/qregexp.h>
+#if QT_CONFIG(regularexpression)
+# include <QtCore/qregularexpression.h>
+#endif
+
QT_REQUIRE_CONFIG(sortfilterproxymodel);
QT_BEGIN_NAMESPACE
@@ -59,6 +63,9 @@ class Q_CORE_EXPORT QSortFilterProxyModel : public QAbstractProxyModel
Q_OBJECT
Q_PROPERTY(QRegExp filterRegExp READ filterRegExp WRITE setFilterRegExp)
+#if QT_CONFIG(regularexpression)
+ Q_PROPERTY(QRegularExpression filterRegularExpression READ filterRegularExpression WRITE setFilterRegularExpression)
+#endif
Q_PROPERTY(int filterKeyColumn READ filterKeyColumn WRITE setFilterKeyColumn)
Q_PROPERTY(bool dynamicSortFilter READ dynamicSortFilter WRITE setDynamicSortFilter)
Q_PROPERTY(Qt::CaseSensitivity filterCaseSensitivity READ filterCaseSensitivity WRITE setFilterCaseSensitivity)
@@ -81,7 +88,10 @@ public:
QItemSelection mapSelectionFromSource(const QItemSelection &sourceSelection) const override;
QRegExp filterRegExp() const;
- void setFilterRegExp(const QRegExp &regExp);
+
+#if QT_CONFIG(regularexpression)
+ QRegularExpression filterRegularExpression() const;
+#endif
int filterKeyColumn() const;
void setFilterKeyColumn(int column);
@@ -112,6 +122,11 @@ public:
public Q_SLOTS:
void setFilterRegExp(const QString &pattern);
+ void setFilterRegExp(const QRegExp &regExp);
+#if QT_CONFIG(regularexpression)
+ void setFilterRegularExpression(const QString &pattern);
+ void setFilterRegularExpression(const QRegularExpression &regularExpression);
+#endif
void setFilterWildcard(const QString &pattern);
void setFilterFixedString(const QString &pattern);
#if QT_DEPRECATED_SINCE(5, 11)
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
index c528b16f9c..3f7bf3cd47 100644
--- a/src/corelib/kernel/kernel.pri
+++ b/src/corelib/kernel/kernel.pri
@@ -43,6 +43,7 @@ HEADERS += \
kernel/qsystemerror_p.h \
kernel/qmetatype_p.h \
kernel/qmetatypeswitcher_p.h \
+ kernel/qtestsupport_core.h
SOURCES += \
kernel/qabstracteventdispatcher.cpp \
@@ -69,7 +70,8 @@ SOURCES += \
kernel/qsystemsemaphore.cpp \
kernel/qpointer.cpp \
kernel/qmath.cpp \
- kernel/qsystemerror.cpp
+ kernel/qsystemerror.cpp \
+ kernel/qtestsupport_core.cpp
win32 {
SOURCES += \
diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp
index 304a7bda08..8e1b560874 100644
--- a/src/corelib/kernel/qabstracteventdispatcher.cpp
+++ b/src/corelib/kernel/qabstracteventdispatcher.cpp
@@ -207,6 +207,15 @@ QAbstractEventDispatcher *QAbstractEventDispatcher::instance(QThread *thread)
\sa hasPendingEvents()
*/
+/*!
+ \internal
+
+ \note processEvents() only processes events queued before the function
+ is called. Events that are posted while the function runs will be queued
+ until a later round of event processing. This only applies to posted Qt
+ events. For timers and system level events, the situation is unknown.
+*/
+
/*! \fn bool QAbstractEventDispatcher::hasPendingEvents()
\deprecated
@@ -309,6 +318,15 @@ int QAbstractEventDispatcher::registerTimer(int interval, Qt::TimerType timerTyp
Wakes up the event loop.
+ \omit
+ ### FIXME - QTBUG-70229
+ On Unix and Glib event dispatchers, if the dispatcher is already awake when
+ this function is called, it is ensured that the current iteration won't block
+ waiting for more events, but will instead do another event loop iteration.
+
+ ### TODO - does other event dispatchers behave the same?
+ \endomit
+
\sa awake()
*/
diff --git a/src/corelib/kernel/qcfsocketnotifier.cpp b/src/corelib/kernel/qcfsocketnotifier.cpp
index 1fee2aa5fc..920ec9cd86 100644
--- a/src/corelib/kernel/qcfsocketnotifier.cpp
+++ b/src/corelib/kernel/qcfsocketnotifier.cpp
@@ -86,7 +86,7 @@ CFRunLoopSourceRef qt_mac_add_socket_to_runloop(const CFSocketRef socket)
if (!loopSource)
return 0;
- CFRunLoopAddSource(CFRunLoopGetMain(), loopSource, kCFRunLoopCommonModes);
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), loopSource, kCFRunLoopCommonModes);
return loopSource;
}
@@ -96,7 +96,7 @@ CFRunLoopSourceRef qt_mac_add_socket_to_runloop(const CFSocketRef socket)
void qt_mac_remove_socket_from_runloop(const CFSocketRef socket, CFRunLoopSourceRef runloop)
{
Q_ASSERT(runloop);
- CFRunLoopRemoveSource(CFRunLoopGetMain(), runloop, kCFRunLoopCommonModes);
+ CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runloop, kCFRunLoopCommonModes);
CFSocketDisableCallBacks(socket, kCFSocketReadCallBack);
CFSocketDisableCallBacks(socket, kCFSocketWriteCallBack);
}
@@ -188,7 +188,7 @@ void QCFSocketNotifier::registerSocketNotifier(QSocketNotifier *notifier)
enableNotifiersObserver = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopBeforeSources,
true, 0, enableSocketNotifiers, &context);
Q_ASSERT(enableNotifiersObserver);
- CFRunLoopAddObserver(CFRunLoopGetMain(), enableNotifiersObserver, kCFRunLoopCommonModes);
+ CFRunLoopAddObserver(CFRunLoopGetCurrent(), enableNotifiersObserver, kCFRunLoopCommonModes);
}
}
diff --git a/src/corelib/kernel/qcore_mac.cpp b/src/corelib/kernel/qcore_mac.cpp
index b5df0db232..e78b2d1171 100644
--- a/src/corelib/kernel/qcore_mac.cpp
+++ b/src/corelib/kernel/qcore_mac.cpp
@@ -42,6 +42,7 @@
#include "qhash.h"
#include "qpair.h"
+#include "qmutex.h"
#include "qvarlengtharray.h"
QT_BEGIN_NAMESPACE
@@ -64,6 +65,7 @@ QCFString::operator CFStringRef() const
#if defined(QT_USE_APPLE_UNIFIED_LOGGING)
+QT_MAC_WEAK_IMPORT(_os_log_default);
bool AppleUnifiedLogger::messageHandler(QtMsgType msgType, const QMessageLogContext &context,
const QString &message, const QString &optionalSubsystem)
{
diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm
index 6b11e90a4e..4ca9c2e996 100644
--- a/src/corelib/kernel/qcore_mac_objc.mm
+++ b/src/corelib/kernel/qcore_mac_objc.mm
@@ -40,8 +40,13 @@
#include <private/qcore_mac_p.h>
-#ifdef Q_OS_OSX
-#include <AppKit/NSText.h>
+#ifdef Q_OS_MACOS
+# include <AppKit/AppKit.h>
+# if !QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
+@interface NSApplication (MojaveForwardDeclarations)
+@property (strong) NSAppearance *effectiveAppearance NS_AVAILABLE_MAC(10_14);
+@end
+# endif
#endif
#if defined(QT_PLATFORM_UIKIT)
@@ -91,19 +96,20 @@ QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(QT_DECLARE_WEAK_QDEBUG_OPERATOR_FOR_CF_TY
QT_END_NAMESPACE
QT_USE_NAMESPACE
@interface QT_MANGLE_NAMESPACE(QMacAutoReleasePoolTracker) : NSObject
-{
+@end
+
+@implementation QT_MANGLE_NAMESPACE(QMacAutoReleasePoolTracker) {
NSAutoreleasePool **m_pool;
}
--(id)initWithPool:(NSAutoreleasePool**)pool;
-@end
-@implementation QT_MANGLE_NAMESPACE(QMacAutoReleasePoolTracker)
--(id)initWithPool:(NSAutoreleasePool**)pool
+
+- (instancetype)initWithPool:(NSAutoreleasePool **)pool
{
- if (self = [super init])
+ if ((self = [self init]))
m_pool = pool;
return self;
}
--(void)dealloc
+
+- (void)dealloc
{
if (*m_pool) {
// The pool is still valid, which means we're not being drained from
@@ -165,6 +171,16 @@ QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool)
}
#endif // !QT_NO_DEBUG_STREAM
+#ifdef Q_OS_MACOS
+bool qt_mac_applicationIsInDarkMode()
+{
+ if (__builtin_available(macOS 10.14, *))
+ return [NSApp.effectiveAppearance.name hasSuffix:@"DarkAqua"];
+ else
+ return false;
+}
+#endif
+
bool qt_apple_isApplicationExtension()
{
static bool isExtension = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSExtension"];
@@ -432,16 +448,23 @@ void qt_apple_check_os_version()
version / 10000, version / 100 % 100, version % 100};
const NSOperatingSystemVersion current = NSProcessInfo.processInfo.operatingSystemVersion;
if (![NSProcessInfo.processInfo isOperatingSystemAtLeastVersion:required]) {
- fprintf(stderr, "You can't use this version of %s with this version of %s. "
- "You have %s %ld.%ld.%ld. Qt requires %s %ld.%ld.%ld or later.\n",
- (reinterpret_cast<const NSString *>(
- NSBundle.mainBundle.infoDictionary[@"CFBundleName"]).UTF8String),
- os,
- os, long(current.majorVersion), long(current.minorVersion), long(current.patchVersion),
- os, long(required.majorVersion), long(required.minorVersion), long(required.patchVersion));
- abort();
+ NSDictionary *plist = NSBundle.mainBundle.infoDictionary;
+ NSString *applicationName = plist[@"CFBundleDisplayName"];
+ if (!applicationName)
+ applicationName = plist[@"CFBundleName"];
+ if (!applicationName)
+ applicationName = NSProcessInfo.processInfo.processName;
+
+ fprintf(stderr, "Sorry, \"%s\" can not be run on this version of %s. "
+ "Qt requires %s %ld.%ld.%ld or later, you have %s %ld.%ld.%ld.\n",
+ applicationName.UTF8String, os,
+ os, long(required.majorVersion), long(required.minorVersion), long(required.patchVersion),
+ os, long(current.majorVersion), long(current.minorVersion), long(current.patchVersion));
+
+ exit(1);
}
}
+Q_CONSTRUCTOR_FUNCTION(qt_apple_check_os_version);
// -------------------------------------------------------------------------
diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h
index af939abaac..b14a494296 100644
--- a/src/corelib/kernel/qcore_mac_p.h
+++ b/src/corelib/kernel/qcore_mac_p.h
@@ -51,18 +51,20 @@
// We mean it.
//
+#include "private/qglobal_p.h"
+
#ifndef __IMAGECAPTURE__
# define __IMAGECAPTURE__
#endif
+// --------------------------------------------------------------------------
+
#if defined(QT_BOOTSTRAPPED)
#include <ApplicationServices/ApplicationServices.h>
#else
#include <CoreFoundation/CoreFoundation.h>
#endif
-#include "private/qglobal_p.h"
-
#ifdef __OBJC__
#include <Foundation/Foundation.h>
#endif
@@ -76,6 +78,8 @@
#define QT_NAMESPACE_ALIAS_OBJC_CLASS(__KLASS__)
#endif
+#define QT_MAC_WEAK_IMPORT(symbol) extern "C" decltype(symbol) symbol __attribute__((weak_import));
+
QT_BEGIN_NAMESPACE
template <typename T, typename U, U (*RetainFunction)(U), void (*ReleaseFunction)(U)>
class QAppleRefCounted
@@ -148,16 +152,16 @@ private:
QString string;
};
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
Q_CORE_EXPORT QChar qt_mac_qtKey2CocoaKey(Qt::Key key);
Q_CORE_EXPORT Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode);
+Q_CORE_EXPORT bool qt_mac_applicationIsInDarkMode();
#endif
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool);
#endif
-Q_CORE_EXPORT void qt_apple_check_os_version();
Q_CORE_EXPORT bool qt_apple_isApplicationExtension();
#if defined(Q_OS_MACOS) && !defined(QT_BOOTSTRAPPED)
@@ -186,35 +190,153 @@ Q_CORE_EXPORT AppleApplication *qt_apple_sharedApplication();
// --------------------------------------------------------------------------
-#if !defined(QT_BOOTSTRAPPED) && (QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12) || !defined(Q_OS_MACOS))
+#if !defined(QT_BOOTSTRAPPED)
#define QT_USE_APPLE_UNIFIED_LOGGING
QT_END_NAMESPACE
#include <os/log.h>
-
-// The compiler isn't smart enough to realize that we're calling these functions
-// guarded by __builtin_available, so we need to also tag each function with the
-// runtime requirements.
-#include <os/availability.h>
-#define OS_LOG_AVAILABILITY API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT AppleUnifiedLogger
{
public:
static bool messageHandler(QtMsgType msgType, const QMessageLogContext &context, const QString &message,
- const QString &subsystem = QString()) OS_LOG_AVAILABILITY;
+ const QString &subsystem = QString());
private:
- static os_log_type_t logTypeForMessageType(QtMsgType msgType) OS_LOG_AVAILABILITY;
- static os_log_t cachedLog(const QString &subsystem, const QString &category) OS_LOG_AVAILABILITY;
+ static os_log_type_t logTypeForMessageType(QtMsgType msgType);
+ static os_log_t cachedLog(const QString &subsystem, const QString &category);
};
-#undef OS_LOG_AVAILABILITY
-
#endif
// --------------------------------------------------------------------------
+#if !defined(QT_BOOTSTRAPPED)
+
+QT_END_NAMESPACE
+#include <os/activity.h>
+QT_BEGIN_NAMESPACE
+
+template <typename T> using QAppleOsType = QAppleRefCounted<T, void *, os_retain, os_release>;
+
+class Q_CORE_EXPORT QAppleLogActivity
+{
+public:
+ QAppleLogActivity() : activity(nullptr) {}
+ QAppleLogActivity(os_activity_t activity) : activity(activity) {}
+ ~QAppleLogActivity() { if (activity) leave(); }
+
+ QAppleLogActivity(const QAppleLogActivity &) = delete;
+ QAppleLogActivity& operator=(const QAppleLogActivity &) = delete;
+
+ QAppleLogActivity(QAppleLogActivity&& other)
+ : activity(other.activity), state(other.state) { other.activity = nullptr; }
+
+ QAppleLogActivity& operator=(QAppleLogActivity &&other)
+ {
+ if (this != &other) {
+ activity = other.activity;
+ state = other.state;
+ other.activity = nullptr;
+ }
+ return *this;
+ }
+
+ QAppleLogActivity&& enter()
+ {
+ if (activity)
+ os_activity_scope_enter(static_cast<os_activity_t>(*this), &state);
+ return std::move(*this);
+ }
+
+ void leave() {
+ if (activity)
+ os_activity_scope_leave(&state);
+ }
+
+ operator os_activity_t()
+ {
+ return reinterpret_cast<os_activity_t>(static_cast<void *>(activity));
+ }
+
+private:
+ // Work around API_AVAILABLE not working for templates by using void*
+ QAppleOsType<void *> activity;
+ os_activity_scope_state_s state;
+};
+
+#define QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, parent) []() { \
+ if (!(condition)) \
+ return QAppleLogActivity(); \
+ return QAppleLogActivity(os_activity_create(description, parent, OS_ACTIVITY_FLAG_DEFAULT)); \
+ }()
+
+#define QT_VA_ARGS_CHOOSE(_1, _2, _3, _4, _5, _6, _7, _8, _9, N, ...) N
+#define QT_VA_ARGS_COUNT(...) QT_VA_ARGS_CHOOSE(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1)
+
+#define QT_OVERLOADED_MACRO(MACRO, ...) _QT_OVERLOADED_MACRO(MACRO, QT_VA_ARGS_COUNT(__VA_ARGS__))(__VA_ARGS__)
+#define _QT_OVERLOADED_MACRO(MACRO, ARGC) _QT_OVERLOADED_MACRO_EXPAND(MACRO, ARGC)
+#define _QT_OVERLOADED_MACRO_EXPAND(MACRO, ARGC) MACRO##ARGC
+
+#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT3(condition, description, parent) QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, parent)
+#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT2(description, parent) QT_APPLE_LOG_ACTIVITY_WITH_PARENT3(true, description, parent)
+#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT(...) QT_OVERLOADED_MACRO(QT_APPLE_LOG_ACTIVITY_WITH_PARENT, __VA_ARGS__)
+
+QT_MAC_WEAK_IMPORT(_os_activity_current);
+#define QT_APPLE_LOG_ACTIVITY2(condition, description) QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, OS_ACTIVITY_CURRENT)
+#define QT_APPLE_LOG_ACTIVITY1(description) QT_APPLE_LOG_ACTIVITY2(true, description)
+#define QT_APPLE_LOG_ACTIVITY(...) QT_OVERLOADED_MACRO(QT_APPLE_LOG_ACTIVITY, __VA_ARGS__)
+
+#define QT_APPLE_SCOPED_LOG_ACTIVITY(...) QAppleLogActivity scopedLogActivity = QT_APPLE_LOG_ACTIVITY(__VA_ARGS__).enter();
+
+#endif // !defined(QT_BOOTSTRAPPED)
+
+// -------------------------------------------------------------------------
+
+#if defined( __OBJC__)
+class QMacScopedObserver
+{
+public:
+ QMacScopedObserver() {}
+
+ template<typename Functor>
+ QMacScopedObserver(id object, NSNotificationName name, Functor callback) {
+ observer = [[NSNotificationCenter defaultCenter] addObserverForName:name
+ object:object queue:nil usingBlock:^(NSNotification *) {
+ callback();
+ }
+ ];
+ }
+
+ QMacScopedObserver(const QMacScopedObserver& other) = delete;
+ QMacScopedObserver(QMacScopedObserver&& other) : observer(other.observer) {
+ other.observer = nil;
+ }
+
+ QMacScopedObserver &operator=(const QMacScopedObserver& other) = delete;
+ QMacScopedObserver &operator=(QMacScopedObserver&& other) {
+ if (this != &other) {
+ remove();
+ observer = other.observer;
+ other.observer = nil;
+ }
+ return *this;
+ }
+
+ void remove() {
+ if (observer)
+ [[NSNotificationCenter defaultCenter] removeObserver:observer];
+ observer = nil;
+ }
+ ~QMacScopedObserver() { remove(); }
+
+private:
+ id observer = nil;
+};
+#endif
+
+// -------------------------------------------------------------------------
+
QT_END_NAMESPACE
#endif // QCORE_MAC_P_H
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 4e32f90964..463e30e1c3 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -58,9 +58,11 @@
#include <qtextcodec.h>
#ifndef QT_NO_QOBJECT
#include <qthread.h>
-#include <qthreadpool.h>
#include <qthreadstorage.h>
#include <private/qthread_p.h>
+#if QT_CONFIG(thread)
+#include <qthreadpool.h>
+#endif
#endif
#include <qelapsedtimer.h>
#include <qlibraryinfo.h>
@@ -116,6 +118,10 @@
# include <taskLib.h>
#endif
+#ifdef Q_OS_WASM
+#include <emscripten.h>
+#endif
+
#ifdef QT_BOOTSTRAPPED
#include <private/qtrace_p.h>
#else
@@ -268,9 +274,7 @@ typedef QList<QtStartUpFunction> QStartUpFuncList;
Q_GLOBAL_STATIC(QStartUpFuncList, preRList)
typedef QList<QtCleanUpFunction> QVFuncList;
Q_GLOBAL_STATIC(QVFuncList, postRList)
-#ifndef QT_NO_QOBJECT
static QBasicMutex globalRoutinesMutex;
-#endif
/*!
\internal
@@ -289,9 +293,7 @@ void qAddPreRoutine(QtStartUpFunction p)
// Due to C++11 parallel dynamic initialization, this can be called
// from multiple threads.
-#ifndef QT_NO_THREAD
QMutexLocker locker(&globalRoutinesMutex);
-#endif
list->prepend(p); // in case QCoreApplication is re-created, see qt_call_pre_routines
}
@@ -300,9 +302,7 @@ void qAddPostRoutine(QtCleanUpFunction p)
QVFuncList *list = postRList();
if (!list)
return;
-#ifndef QT_NO_THREAD
QMutexLocker locker(&globalRoutinesMutex);
-#endif
list->prepend(p);
}
@@ -311,9 +311,7 @@ void qRemovePostRoutine(QtCleanUpFunction p)
QVFuncList *list = postRList();
if (!list)
return;
-#ifndef QT_NO_THREAD
QMutexLocker locker(&globalRoutinesMutex);
-#endif
list->removeAll(p);
}
@@ -324,9 +322,7 @@ static void qt_call_pre_routines()
QVFuncList list;
{
-#ifndef QT_NO_THREAD
QMutexLocker locker(&globalRoutinesMutex);
-#endif
// Unlike qt_call_post_routines, we don't empty the list, because
// Q_COREAPP_STARTUP_FUNCTION is a macro, so the user expects
// the function to be executed every time QCoreApplication is created.
@@ -345,9 +341,7 @@ void Q_CORE_EXPORT qt_call_post_routines()
QVFuncList list;
{
// extract the current list and make the stored list empty
-#ifndef QT_NO_THREAD
QMutexLocker locker(&globalRoutinesMutex);
-#endif
qSwap(*postRList, list);
}
@@ -466,9 +460,6 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint
, q_ptr(0)
#endif
{
-#if defined(Q_OS_DARWIN)
- qt_apple_check_os_version();
-#endif
app_compile_version = flags & 0xffffff;
static const char *const empty = "";
if (argc == 0 || argv == 0) {
@@ -491,6 +482,10 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint
qFatal("FATAL: The application binary appears to be running setuid, this is a security hole.");
# endif // Q_OS_UNIX
+#ifdef Q_OS_WINRT
+ QThreadData::setMainThread();
+#endif
+
QThread *cur = QThread::currentThread(); // note: this may end up setting theMainThread!
if (cur != theMainThread)
qWarning("WARNING: QApplication was not created in the main() thread.");
@@ -499,6 +494,13 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint
QCoreApplicationPrivate::~QCoreApplicationPrivate()
{
+#ifdef Q_OS_WASM
+ EM_ASM(
+ // unmount persistent directory as IDBFS
+ // see also QTBUG-70002
+ FS.unmount('/home/web_user');
+ );
+#endif
#ifndef QT_NO_QOBJECT
cleanupThreadData();
#endif
@@ -513,7 +515,7 @@ QCoreApplicationPrivate::~QCoreApplicationPrivate()
void QCoreApplicationPrivate::cleanupThreadData()
{
if (threadData && !threadData_clean) {
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
void *data = &threadData->tls;
QThreadStorageData::finish((void **)data);
#endif
@@ -540,7 +542,7 @@ void QCoreApplicationPrivate::createEventDispatcher()
Q_Q(QCoreApplication);
QThreadData *data = QThreadData::current();
Q_ASSERT(!data->hasEventDispatcher());
- eventDispatcher = QThreadPrivate::createEventDispatcher(data);
+ eventDispatcher = data->createEventDispatcher();
eventDispatcher->setParent(q);
}
@@ -777,7 +779,7 @@ QCoreApplication::QCoreApplication(int &argc, char **argv
void QCoreApplicationPrivate::init()
{
- Q_TRACE(qcoreapplicationprivate_init_entry);
+ Q_TRACE(QCoreApplicationPrivate_init_entry);
#if defined(Q_OS_MACOS)
QMacAutoReleasePool pool;
@@ -790,6 +792,17 @@ void QCoreApplicationPrivate::init()
Q_ASSERT_X(!QCoreApplication::self, "QCoreApplication", "there should be only one application object");
QCoreApplication::self = q;
+#ifdef Q_OS_WASM
+ EM_ASM(
+ // mount and sync persistent filesystem to sandbox
+ FS.mount(IDBFS, {}, '/home/web_user');
+ FS.syncfs(true, function(err) {
+ if (err)
+ Module.print(err);
+ });
+ );
+#endif
+
// Store app name/version (so they're still available after QCoreApplication is destroyed)
if (!coreappdata()->applicationNameSet)
coreappdata()->application = appName();
@@ -872,7 +885,7 @@ void QCoreApplicationPrivate::init()
is_app_running = true; // No longer starting up.
#endif
- Q_TRACE(qcoreapplicationprivate_init_exit);
+ Q_TRACE(QCoreApplicationPrivate_init_exit);
}
/*!
@@ -888,7 +901,7 @@ QCoreApplication::~QCoreApplication()
QCoreApplicationPrivate::is_app_running = false;
#endif
-#if !defined(QT_NO_THREAD)
+#if QT_CONFIG(thread)
// Synchronize and stop the global thread pool threads.
QThreadPool *globalThreadPool = 0;
QT_TRY {
@@ -1185,16 +1198,31 @@ bool QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject *receiver, Q
*/
bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event)
{
+ // Note: when adjusting the tracepoints in here
+ // consider adjusting QApplicationPrivate::notify_helper too.
+ Q_TRACE(QCoreApplication_notify_entry, receiver, event, event->type());
+
// send to all application event filters (only does anything in the main thread)
if (QCoreApplication::self
&& receiver->d_func()->threadData->thread == mainThread()
- && QCoreApplication::self->d_func()->sendThroughApplicationEventFilters(receiver, event))
+ && QCoreApplication::self->d_func()->sendThroughApplicationEventFilters(receiver, event)) {
+ Q_TRACE(QCoreApplication_notify_event_filtered, receiver, event, event->type());
return true;
+ }
// send to all receiver event filters
- if (sendThroughObjectEventFilters(receiver, event))
+ if (sendThroughObjectEventFilters(receiver, event)) {
+ Q_TRACE(QCoreApplication_notify_event_filtered, receiver, event, event->type());
return true;
+ }
+
+ Q_TRACE(QCoreApplication_notify_before_delivery, receiver, event, event->type());
+
// deliver the event
- return receiver->event(event);
+ const bool consumed = receiver->event(event);
+
+ Q_TRACE(QCoreApplication_notify_after_delivery, receiver, event, event->type(), consumed);
+
+ return consumed;
}
/*!
@@ -1399,6 +1427,7 @@ void QCoreApplication::exit(int returnCode)
QCoreApplication management of posted events
*****************************************************************************/
+#ifndef QT_NO_QOBJECT
/*!
\fn bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)
@@ -1413,6 +1442,28 @@ void QCoreApplication::exit(int returnCode)
\sa postEvent(), notify()
*/
+bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)
+{
+ Q_TRACE(QCoreApplication_sendEvent, receiver, event, event->type());
+
+ if (event)
+ event->spont = false;
+ return notifyInternal2(receiver, event);
+}
+
+/*!
+ \internal
+*/
+bool QCoreApplication::sendSpontaneousEvent(QObject *receiver, QEvent *event)
+{
+ Q_TRACE(QCoreApplication_sendSpontaneousEvent, receiver, event, event->type());
+
+ if (event)
+ event->spont = true;
+ return notifyInternal2(receiver, event);
+}
+
+#endif // QT_NO_QOBJECT
/*!
\since 4.3
@@ -1441,6 +1492,8 @@ void QCoreApplication::exit(int returnCode)
*/
void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
{
+ Q_TRACE(QCoreApplication_postEvent_entry, receiver, event, event->type());
+
if (receiver == 0) {
qWarning("QCoreApplication::postEvent: Unexpected null receiver");
delete event;
@@ -1477,6 +1530,7 @@ void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
// if this is one of the compressible events, do compression
if (receiver->d_func()->postedEvents
&& self && self->compressEvent(event, receiver, &data->postEventList)) {
+ Q_TRACE(QCoreApplication_postEvent_event_compressed, receiver, event);
return;
}
@@ -1508,6 +1562,7 @@ void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
// delete the event on exceptions to protect against memory leaks till the event is
// properly owned in the postEventList
QScopedPointer<QEvent> eventDeleter(event);
+ Q_TRACE(QCoreApplication_postEvent_event_posted, receiver, event, event->type());
data->postEventList.addEvent(QPostEvent(receiver, event, priority));
eventDeleter.take();
event->posted = true;
@@ -1766,8 +1821,7 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type
If \a receiver is null, the events of \a eventType are removed for
all objects. If \a eventType is 0, all the events are removed for
\a receiver. You should never call this function with \a eventType
- of 0. If you do call it in this way, be aware that killing events
- may cause \a receiver to break one or more invariants.
+ of 0.
\threadsafe
*/
@@ -1818,9 +1872,7 @@ void QCoreApplication::removePostedEvents(QObject *receiver, int eventType)
}
locker.unlock();
- for (int i = 0; i < events.count(); ++i) {
- delete events[i];
- }
+ qDeleteAll(events);
}
/*!
@@ -1889,7 +1941,7 @@ bool QCoreApplication::event(QEvent *e)
\value UnicodeUTF8 UTF-8.
\omitvalue Latin1
- \omitvalue DefaultCodec UTF-8.
+ \omitvalue DefaultCodec \omit UTF-8. \endomit
\omitvalue CodecForTr
\sa QObject::tr(), QString::fromUtf8()
diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h
index a886c9d1d2..3581970765 100644
--- a/src/corelib/kernel/qcoreapplication.h
+++ b/src/corelib/kernel/qcoreapplication.h
@@ -229,14 +229,6 @@ private:
friend class QClassFactory;
};
-#ifndef QT_NO_QOBJECT
-inline bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)
-{ if (event) event->spont = false; return notifyInternal2(receiver, event); }
-
-inline bool QCoreApplication::sendSpontaneousEvent(QObject *receiver, QEvent *event)
-{ if (event) event->spont = true; return notifyInternal2(receiver, event); }
-#endif
-
#ifdef QT_NO_DEPRECATED
# define QT_DECLARE_DEPRECATED_TR_FUNCTIONS(context)
#else
diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp
index 00548365d2..0109e2c658 100644
--- a/src/corelib/kernel/qcoreapplication_win.cpp
+++ b/src/corelib/kernel/qcoreapplication_win.cpp
@@ -192,7 +192,7 @@ Q_CORE_EXPORT int qWinAppCmdShow() // get main window sho
#if defined(Q_OS_WIN) && !defined(QT_NO_DEBUG_STREAM)
/*****************************************************************************
Convenience functions for convert WM_* messages into human readable strings,
- including a nifty QDebug operator<< for simpel QDebug() << msg output.
+ including a nifty QDebug operator<< for simple QDebug() << msg output.
*****************************************************************************/
QT_BEGIN_INCLUDE_NAMESPACE
#include <windowsx.h>
@@ -207,10 +207,48 @@ QT_END_INCLUDE_NAMESPACE
// The values below should never change. Note that none of the usual
// WM_...FIRST & WM_...LAST values are in the list, as they normally have other
// WM_... representations
-struct KnownWM {
- uint WM;
- const char* str;
-} knownWM[] =
+
+template <class IntType>
+struct QWinMessageMapping {
+ IntType value;
+ const char *name;
+};
+
+#define FLAG_ENTRY(x) {x, #x} // for populating arrays
+
+// Looks up a value in a list of QWinMessageMapping
+template <class IntType>
+static const char *findWinMessageMapping(const QWinMessageMapping<IntType> *haystack,
+ size_t haystackSize,
+ IntType needle)
+{
+ for (auto p = haystack, end = haystack + haystackSize; p < end; ++p) {
+ if (p->value == needle)
+ return p->name;
+ }
+ return nullptr;
+}
+
+// Format flags using a mapping as "Flag1 | Flag2"...
+template <class IntType>
+static QString flagsValue(const QWinMessageMapping<IntType> *haystack,
+ size_t haystackSize, IntType value)
+{
+ QString result;
+ for (auto p = haystack, end = haystack + haystackSize; p < end; ++p) {
+ if ((p->value & value) == p->value) {
+ if (!result.isEmpty())
+ result += QLatin1String(" | ");
+ result += QLatin1String(p->name);
+ }
+ }
+ return result;
+}
+
+// Looks up the WM_ message in the table inside
+static const char *findWMstr(uint msg)
+{
+ static const QWinMessageMapping<uint> knownWM[] =
{{ 0x0000, "WM_NULL" },
{ 0x0001, "WM_CREATE" },
{ 0x0002, "WM_DESTROY" },
@@ -505,84 +543,146 @@ struct KnownWM {
{ 0x038E, "WM_PENWINFIRST + 14" },
{ 0x038F, "WM_PENWINLAST" },
{ 0x0400, "WM_USER" },
- { 0x8000, "WM_APP" },
- { 0,0 }}; // End of known messages
+ { 0x8000, "WM_APP" }
+ };
-// Looks up the WM_ message in the table above
-static const char* findWMstr(uint msg)
-{
- uint i = 0;
- const char* result = 0;
- // Known WM_'s
- while (knownWM[i].str && (knownWM[i].WM != msg))
- ++i;
- result = knownWM[i].str;
- return result;
-};
+ return findWinMessageMapping(knownWM, sizeof(knownWM) / sizeof(knownWM[0]), msg);
+}
-// Convenience function for converting flags and values into readable strings
-struct FLAG_STRING_STRUCT
+static const char *activateParameter(uint p)
{
- uint value;
- const char* str;
-};
+ static const QWinMessageMapping<uint> activeEnum[] = {
+ {WA_ACTIVE, "Activate"}, {WA_INACTIVE, "Deactivate"},
+ {WA_CLICKACTIVE, "Activate by mouseclick"}
+ };
-FLAG_STRING_STRUCT FLAG_STRING(uint value = 0, const char *c = 0)
+ return findWinMessageMapping(activeEnum, sizeof(activeEnum) / sizeof(activeEnum[0]), p);
+}
+
+static QString styleFlags(uint style)
{
- FLAG_STRING_STRUCT s = {value, c};
- return s;
+ static const QWinMessageMapping<uint> styleFlags[] = {
+ FLAG_ENTRY(WS_BORDER), FLAG_ENTRY(WS_CAPTION), FLAG_ENTRY(WS_CHILD),
+ FLAG_ENTRY(WS_CLIPCHILDREN), FLAG_ENTRY(WS_CLIPSIBLINGS),
+ FLAG_ENTRY(WS_DISABLED), FLAG_ENTRY(WS_DLGFRAME), FLAG_ENTRY(WS_GROUP),
+ FLAG_ENTRY(WS_HSCROLL), FLAG_ENTRY(WS_OVERLAPPED),
+ FLAG_ENTRY(WS_OVERLAPPEDWINDOW), FLAG_ENTRY(WS_ICONIC),
+ FLAG_ENTRY(WS_MAXIMIZE), FLAG_ENTRY(WS_MAXIMIZEBOX),
+ FLAG_ENTRY(WS_MINIMIZE), FLAG_ENTRY(WS_MINIMIZEBOX),
+ FLAG_ENTRY(WS_OVERLAPPEDWINDOW), FLAG_ENTRY(WS_POPUP),
+ FLAG_ENTRY(WS_POPUPWINDOW), FLAG_ENTRY(WS_SIZEBOX),
+ FLAG_ENTRY(WS_SYSMENU), FLAG_ENTRY(WS_TABSTOP), FLAG_ENTRY(WS_THICKFRAME),
+ FLAG_ENTRY(WS_TILED), FLAG_ENTRY(WS_TILEDWINDOW), FLAG_ENTRY(WS_VISIBLE),
+ FLAG_ENTRY(WS_VSCROLL)
+ };
+
+ return flagsValue(styleFlags, sizeof(styleFlags) / sizeof(styleFlags[0]), style);
}
-#define FLGSTR(x) FLAG_STRING(x, #x)
+static QString exStyleFlags(uint exStyle)
+{
+ static const QWinMessageMapping<uint> exStyleFlags[] = {
+ FLAG_ENTRY(WS_EX_ACCEPTFILES), FLAG_ENTRY(WS_EX_APPWINDOW),
+ FLAG_ENTRY(WS_EX_CLIENTEDGE), FLAG_ENTRY(WS_EX_DLGMODALFRAME),
+ FLAG_ENTRY(WS_EX_LEFT), FLAG_ENTRY(WS_EX_LEFTSCROLLBAR),
+ FLAG_ENTRY(WS_EX_LTRREADING), FLAG_ENTRY(WS_EX_MDICHILD),
+ FLAG_ENTRY(WS_EX_NOACTIVATE), FLAG_ENTRY(WS_EX_NOPARENTNOTIFY),
+ FLAG_ENTRY(WS_EX_OVERLAPPEDWINDOW), FLAG_ENTRY(WS_EX_PALETTEWINDOW),
+ FLAG_ENTRY(WS_EX_RIGHT), FLAG_ENTRY(WS_EX_RIGHTSCROLLBAR),
+ FLAG_ENTRY(WS_EX_RTLREADING), FLAG_ENTRY(WS_EX_STATICEDGE),
+ FLAG_ENTRY(WS_EX_TOOLWINDOW), FLAG_ENTRY(WS_EX_TOPMOST),
+ FLAG_ENTRY(WS_EX_TRANSPARENT), FLAG_ENTRY(WS_EX_WINDOWEDGE)
+ };
+
+ return flagsValue(exStyleFlags, sizeof(exStyleFlags) / sizeof(exStyleFlags[0]), exStyle);
+}
-// Returns an ORed (" | ") together string for the flags active in the actual
-// value. (...) must consist of FLAG_STRING, with a FLAG_STRING() as the last
-// value in the list passed to the function
-QString flagCheck(uint actual, ...)
+static const char *imeCommand(uint cmd)
{
- va_list ap;
- va_start(ap, actual);
+ static const QWinMessageMapping<uint> commands[] = {
+ FLAG_ENTRY(IMN_CHANGECANDIDATE), FLAG_ENTRY(IMN_CLOSECANDIDATE),
+ FLAG_ENTRY(IMN_CLOSESTATUSWINDOW), FLAG_ENTRY(IMN_GUIDELINE),
+ FLAG_ENTRY(IMN_OPENCANDIDATE), FLAG_ENTRY(IMN_OPENSTATUSWINDOW),
+ FLAG_ENTRY(IMN_SETCANDIDATEPOS), FLAG_ENTRY(IMN_SETCOMPOSITIONFONT),
+ FLAG_ENTRY(IMN_SETCOMPOSITIONWINDOW), FLAG_ENTRY(IMN_SETCONVERSIONMODE),
+ FLAG_ENTRY(IMN_SETOPENSTATUS), FLAG_ENTRY(IMN_SETSENTENCEMODE),
+ FLAG_ENTRY(IMN_SETSTATUSWINDOWPOS)
+ };
+
+ return findWinMessageMapping(commands, sizeof(commands) / sizeof(commands[0]), cmd);
+}
- QString result;
- int count = 0;
- FLAG_STRING_STRUCT v;
- while((v=va_arg(ap,FLAG_STRING_STRUCT)).str) {
- if ((actual & v.value) == v.value) {
- if (count++)
- result += QLatin1String(" | ");
- result += QString::fromLatin1(v.str);
- }
- }
- va_end(ap);
- return result;
-};
+static QString imeShowFlags(uint flags)
+{
+ static const QWinMessageMapping<uint> showFlags[] = {
+ FLAG_ENTRY(ISC_SHOWUICOMPOSITIONWINDOW),
+ FLAG_ENTRY(ISC_SHOWUICANDIDATEWINDOW),
+ FLAG_ENTRY(ISC_SHOWUICANDIDATEWINDOW << 1),
+ FLAG_ENTRY(ISC_SHOWUICANDIDATEWINDOW << 2),
+ FLAG_ENTRY(ISC_SHOWUICANDIDATEWINDOW << 3)
+ };
+
+ return flagsValue(showFlags, sizeof(showFlags) / sizeof(showFlags[0]), flags);
+}
-// Returns the string representation of the value in 'actual'. (...) must
-// consist of FLAG_STRING, with a FLAG_STRING() as the last value in the list
-// passed to the function
-QString valueCheck(uint actual, ...)
+static const char *wmSizeParam(uint p)
{
- va_list ap;
- va_start(ap, actual);
+ static const QWinMessageMapping<uint> sizeParams[] = {
+ FLAG_ENTRY(SIZE_MAXHIDE), FLAG_ENTRY(SIZE_MAXIMIZED),
+ FLAG_ENTRY(SIZE_MAXSHOW), FLAG_ENTRY(SIZE_MINIMIZED),
+ FLAG_ENTRY(SIZE_RESTORED)
+ };
- QString result;
- FLAG_STRING_STRUCT v;
- while((v=va_arg(ap,FLAG_STRING_STRUCT)).str && (actual != v.value))
- ;
- result = QString::fromLatin1(v.str);
+ return findWinMessageMapping(sizeParams, sizeof(sizeParams) / sizeof(sizeParams[0]), p);
+}
- va_end(ap);
- return result;
-};
+static QString virtualKeys(uint vk)
+{
+ static const QWinMessageMapping<uint> keys[] = {
+ FLAG_ENTRY(MK_CONTROL), FLAG_ENTRY(MK_LBUTTON), FLAG_ENTRY(MK_MBUTTON),
+ FLAG_ENTRY(MK_RBUTTON), FLAG_ENTRY(MK_SHIFT), FLAG_ENTRY(MK_XBUTTON1),
+ FLAG_ENTRY(MK_XBUTTON2)
+ };
-#ifdef Q_CC_BOR
+ return flagsValue(keys, sizeof(keys) / sizeof(keys[0]), vk);
+}
-QString decodeMSG(const MSG& msg)
+static QString winPosFlags(uint f)
{
- return QString::fromLatin1("THis is not supported on Borland");
+ static const QWinMessageMapping<uint> winPosValues[] = {
+ FLAG_ENTRY(SWP_DRAWFRAME), FLAG_ENTRY(SWP_FRAMECHANGED),
+ FLAG_ENTRY(SWP_HIDEWINDOW), FLAG_ENTRY(SWP_NOACTIVATE),
+ FLAG_ENTRY(SWP_NOCOPYBITS), FLAG_ENTRY(SWP_NOMOVE),
+ FLAG_ENTRY(SWP_NOOWNERZORDER), FLAG_ENTRY(SWP_NOREDRAW),
+ FLAG_ENTRY(SWP_NOREPOSITION), FLAG_ENTRY(SWP_NOSENDCHANGING),
+ FLAG_ENTRY(SWP_NOSIZE), FLAG_ENTRY(SWP_NOZORDER),
+ FLAG_ENTRY(SWP_SHOWWINDOW)
+ };
+
+ return flagsValue(winPosValues, sizeof(winPosValues) / sizeof(winPosValues[0]), f);
}
-#else
+static const char *winPosInsertAfter(quintptr h)
+{
+ static const QWinMessageMapping<quintptr> insertAfterValues[] = {
+ {quintptr(HWND_BOTTOM), "HWND_BOTTOM"},
+ {quintptr(HWND_NOTOPMOST), "HWND_NOTOPMOST"},
+ {quintptr(HWND_TOP), "HWND_TOP"},
+ {quintptr(HWND_TOPMOST), "HWND_TOPMOST"}
+ };
+ return findWinMessageMapping(insertAfterValues, sizeof(insertAfterValues) / sizeof(insertAfterValues[0]), h);
+}
+
+static const char *sessionMgrLogOffOption(uint p)
+{
+ static const QWinMessageMapping<uint> values[] = {
+ {ENDSESSION_CLOSEAPP, "Close application"},
+ {ENDSESSION_CRITICAL, "Force application end"},
+ {ENDSESSION_LOGOFF, "User logoff"}
+ };
+
+ return findWinMessageMapping(values, sizeof(values) / sizeof(values[0]), p);
+}
// Returns a "human readable" string representation of the MSG and the
// information it points to
@@ -590,400 +690,177 @@ QString decodeMSG(const MSG& msg)
{
const WPARAM wParam = msg.wParam;
const LPARAM lParam = msg.lParam;
- QString wmmsg = QString::fromLatin1(findWMstr(msg.message));
- // Unknown WM_, so use number
- if (wmmsg.isEmpty())
- wmmsg = QString::fromLatin1("WM_(%1)").arg(msg.message);
-
- const QString rawParameters = QString::asprintf("hwnd(0x%p) ", (void *)msg.hwnd);
+ QString message;
// Custom WM_'s
if (msg.message > WM_APP)
- wmmsg = QString::fromLatin1("WM_APP + %1").arg(msg.message - WM_APP);
+ message= QString::fromLatin1("WM_APP + %1").arg(msg.message - WM_APP);
else if (msg.message > WM_USER)
- wmmsg = QString::fromLatin1("WM_USER + %1").arg(msg.message - WM_USER);
+ message = QString::fromLatin1("WM_USER + %1").arg(msg.message - WM_USER);
+ else if (const char *wmmsgC = findWMstr(msg.message))
+ message = QString::fromLatin1(wmmsgC);
+ else
+ message = QString::fromLatin1("WM_(%1)").arg(msg.message); // Unknown WM_, so use number
+
+ // Yes, we want to give the WM_ names 20 chars of space before showing the
+ // decoded message, since some of the common messages are quite long, and
+ // we don't want the decoded information to vary in output position
+ if (message.size() < 20)
+ message.prepend(QString(20 - message.size(), QLatin1Char(' ')));
+ message += QLatin1String(": ");
+
+ const QString hwndS = QString::asprintf("(%p)", reinterpret_cast<void *>(msg.hwnd));
+ const QString wParamS = QString::asprintf("(%p)", reinterpret_cast<void *>(wParam));
+ const QString lParamS = QString::asprintf("(%p)", reinterpret_cast<void *>(lParam));
QString parameters;
switch (msg.message) {
-#ifdef WM_ACTIVATE
case WM_ACTIVATE:
- {
- QString activation = valueCheck(wParam,
- FLAG_STRING(WA_ACTIVE, "Activate"),
- FLAG_STRING(WA_INACTIVE, "Deactivate"),
- FLAG_STRING(WA_CLICKACTIVE, "Activate by mouseclick"),
- FLAG_STRING());
- parameters = QString::asprintf("%s Hwnd (0x%p)", activation.toLatin1().data(), (void *)msg.hwnd);
- }
+ if (const char *a = activateParameter(uint(wParam)))
+ parameters += QLatin1String(a);
+ parameters += QLatin1String(" Hwnd ") + hwndS;
break;
-#endif
-#ifdef WM_CAPTURECHANGED
case WM_CAPTURECHANGED:
- parameters = QString::asprintf("Hwnd gaining capture (0x%p)", (void *)lParam);
+ parameters = QLatin1String("Hwnd gaining capture ") + hwndS;
break;
-#endif
-#ifdef WM_CREATE
case WM_CREATE:
{
- LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
- QString styles = flagCheck(lpcs->style,
- FLGSTR(WS_BORDER),
- FLGSTR(WS_CAPTION),
- FLGSTR(WS_CHILD),
- FLGSTR(WS_CLIPCHILDREN),
- FLGSTR(WS_CLIPSIBLINGS),
- FLGSTR(WS_DISABLED),
- FLGSTR(WS_DLGFRAME),
- FLGSTR(WS_GROUP),
- FLGSTR(WS_HSCROLL),
- FLGSTR(WS_OVERLAPPED),
-#if defined(WS_OVERLAPPEDWINDOW) && (WS_OVERLAPPEDWINDOW != 0)
- FLGSTR(WS_OVERLAPPEDWINDOW),
-#endif
-#ifdef WS_ICONIC
- FLGSTR(WS_ICONIC),
-#endif
- FLGSTR(WS_MAXIMIZE),
- FLGSTR(WS_MAXIMIZEBOX),
- FLGSTR(WS_MINIMIZE),
- FLGSTR(WS_MINIMIZEBOX),
- FLGSTR(WS_OVERLAPPEDWINDOW),
- FLGSTR(WS_POPUP),
-#ifdef WS_POPUPWINDOW
- FLGSTR(WS_POPUPWINDOW),
-#endif
- FLGSTR(WS_SIZEBOX),
- FLGSTR(WS_SYSMENU),
- FLGSTR(WS_TABSTOP),
- FLGSTR(WS_THICKFRAME),
-#ifdef WS_TILED
- FLGSTR(WS_TILED),
-#endif
-#ifdef WS_TILEDWINDOW
- FLGSTR(WS_TILEDWINDOW),
-#endif
- FLGSTR(WS_VISIBLE),
- FLGSTR(WS_VSCROLL),
- FLAG_STRING());
-
- QString exStyles = flagCheck(lpcs->dwExStyle,
-#ifdef WS_EX_ACCEPTFILES
- FLGSTR(WS_EX_ACCEPTFILES),
-#endif
-#ifdef WS_EX_APPWINDOW
- FLGSTR(WS_EX_APPWINDOW),
-#endif
- FLGSTR(WS_EX_CLIENTEDGE),
- FLGSTR(WS_EX_DLGMODALFRAME),
-#ifdef WS_EX_LEFT
- FLGSTR(WS_EX_LEFT),
-#endif
- FLGSTR(WS_EX_LEFTSCROLLBAR),
-#ifdef WS_EX_LTRREADING
- FLGSTR(WS_EX_LTRREADING),
-#endif
-#ifdef WS_EX_MDICHILD
- FLGSTR(WS_EX_MDICHILD),
-#endif
-#ifdef WS_EX_NOACTIVATE
- FLGSTR(WS_EX_NOACTIVATE),
-#endif
-#ifdef WS_EX_NOANIMATION
- FLGSTR(WS_EX_NOANIMATION),
-#endif
- FLGSTR(WS_EX_NOPARENTNOTIFY),
- FLGSTR(WS_EX_OVERLAPPEDWINDOW),
-#ifdef WS_EX_PALETTEWINDOW
- FLGSTR(WS_EX_PALETTEWINDOW),
-#endif
-#ifdef WS_EX_RIGHT
- FLGSTR(WS_EX_RIGHT),
-#endif
-#ifdef WS_EX_RIGHTSCROLLBAR
- FLGSTR(WS_EX_RIGHTSCROLLBAR),
-#endif
-#ifdef WS_EX_RTLREADING
- FLGSTR(WS_EX_RTLREADING),
-#endif
- FLGSTR(WS_EX_STATICEDGE),
- FLGSTR(WS_EX_TOOLWINDOW),
- FLGSTR(WS_EX_TOPMOST),
-#ifdef WS_EX_TRANSPARENT
- FLGSTR(WS_EX_TRANSPARENT),
-#endif
- FLGSTR(WS_EX_WINDOWEDGE),
-#ifdef WS_EX_CAPTIONOKBTN
- FLGSTR(WS_EX_CAPTIONOKBTN),
-#endif
- FLAG_STRING());
-
+ auto lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
QString className;
- if (lpcs->lpszClass != 0) {
- if (HIWORD(lpcs->lpszClass) == 0) // Atom
- className = QString::number(LOWORD(lpcs->lpszClass), 16);
- else // String
- className = QString((QChar*)lpcs->lpszClass,
- (int)wcslen(reinterpret_cast<const wchar_t *>(lpcs->lpszClass)));
+ if (lpcs->lpszClass != nullptr) {
+ className = HIWORD(lpcs->lpszClass) == 0
+ ? QString::number(LOWORD(lpcs->lpszClass), 16) // Atom
+ : QString::fromWCharArray(lpcs->lpszClass);
}
- QString windowName;
- if (lpcs->lpszName != 0)
- windowName = QString((QChar*)lpcs->lpszName,
- (int)wcslen(reinterpret_cast<const wchar_t *>(lpcs->lpszName)));
+ const QString windowName = lpcs->lpszName
+ ? QString::fromWCharArray(lpcs->lpszName) : QString();
parameters = QString::asprintf("x,y(%4d,%4d) w,h(%4d,%4d) className(%s) windowName(%s) parent(0x%p) style(%s) exStyle(%s)",
- lpcs->x, lpcs->y, lpcs->cx, lpcs->cy, className.toLatin1().data(),
- windowName.toLatin1().data(), (void *)lpcs->hwndParent,
- styles.toLatin1().data(), exStyles.toLatin1().data());
+ lpcs->x, lpcs->y, lpcs->cx, lpcs->cy,
+ className.toLatin1().constData(),
+ windowName.toLatin1().constData(),
+ reinterpret_cast<void *>(lpcs->hwndParent),
+ styleFlags(uint(lpcs->style)).toLatin1().constData(),
+ exStyleFlags(lpcs->dwExStyle).toLatin1().constData());
}
break;
-#endif
-#ifdef WM_DESTROY
case WM_DESTROY:
- parameters = QString::asprintf("Destroy hwnd (0x%p)", (void *)msg.hwnd);
+ parameters = QLatin1String("Destroy hwnd ") + hwndS;
break;
-#endif
-#ifdef WM_IME_NOTIFY
case WM_IME_NOTIFY:
{
- QString imnCommand = valueCheck(wParam,
- FLGSTR(IMN_CHANGECANDIDATE),
- FLGSTR(IMN_CLOSECANDIDATE),
- FLGSTR(IMN_CLOSESTATUSWINDOW),
- FLGSTR(IMN_GUIDELINE),
- FLGSTR(IMN_OPENCANDIDATE),
- FLGSTR(IMN_OPENSTATUSWINDOW),
- FLGSTR(IMN_SETCANDIDATEPOS),
- FLGSTR(IMN_SETCOMPOSITIONFONT),
- FLGSTR(IMN_SETCOMPOSITIONWINDOW),
- FLGSTR(IMN_SETCONVERSIONMODE),
- FLGSTR(IMN_SETOPENSTATUS),
- FLGSTR(IMN_SETSENTENCEMODE),
- FLGSTR(IMN_SETSTATUSWINDOWPOS),
- FLAG_STRING());
- parameters = QString::asprintf("Command(%s : 0x%p)", imnCommand.toLatin1().data(), (void *)lParam);
+ parameters = QLatin1String("Command(");
+ if (const char *c = imeCommand(uint(wParam)))
+ parameters += QLatin1String(c);
+ parameters += QLatin1String(" : ") + lParamS;
}
break;
-#endif
-#ifdef WM_IME_SETCONTEXT
case WM_IME_SETCONTEXT:
- {
- bool fSet = (BOOL)wParam;
- DWORD fShow = (DWORD)lParam;
- QString showFlgs = flagCheck(fShow,
-#ifdef ISC_SHOWUICOMPOSITIONWINDOW
- FLGSTR(ISC_SHOWUICOMPOSITIONWINDOW),
-#endif
-#ifdef ISC_SHOWUIGUIDWINDOW
- FLGSTR(ISC_SHOWUIGUIDWINDOW),
-#endif
-#ifdef ISC_SHOWUISOFTKBD
- FLGSTR(ISC_SHOWUISOFTKBD),
-#endif
- FLGSTR(ISC_SHOWUICANDIDATEWINDOW),
- FLGSTR(ISC_SHOWUICANDIDATEWINDOW << 1),
- FLGSTR(ISC_SHOWUICANDIDATEWINDOW << 2),
- FLGSTR(ISC_SHOWUICANDIDATEWINDOW << 3),
- FLAG_STRING());
- parameters = QString::asprintf("Input context(%s) Show flags(%s)", (fSet? "Active" : "Inactive"), showFlgs.toLatin1().data());
- }
+ parameters = QLatin1String("Input context(")
+ + QLatin1String(wParam == TRUE ? "Active" : "Inactive")
+ + QLatin1String(") Show flags(")
+ + imeShowFlags(DWORD(lParam)) + QLatin1Char(')');
break;
-#endif
-#ifdef WM_KILLFOCUS
case WM_KILLFOCUS:
- parameters = QString::asprintf("Hwnd gaining keyboard focus (0x%p)", (void *)wParam);
+ parameters = QLatin1String("Hwnd gaining keyboard focus ") + wParamS;
break;
-#endif
-#ifdef WM_CHAR
case WM_CHAR:
-#endif
-#ifdef WM_IME_CHAR
case WM_IME_CHAR:
-#endif
-#ifdef WM_KEYDOWN
case WM_KEYDOWN:
-#endif
-#ifdef WM_KEYUP
case WM_KEYUP:
{
- int nVirtKey = (int)wParam;
- long lKeyData = (long)lParam;
+ const int nVirtKey = int(wParam);
+ const long lKeyData = long(lParam);
int repCount = (lKeyData & 0xffff); // Bit 0-15
int scanCode = (lKeyData & 0xf0000) >> 16; // Bit 16-23
bool contextCode = !!(lKeyData & 0x20000000); // Bit 29
bool prevState = !!(lKeyData & 0x40000000); // Bit 30
bool transState = !!(lKeyData & 0x80000000); // Bit 31
- parameters = QString::asprintf("Virual-key(0x%x) Scancode(%d) Rep(%d) Contextcode(%d), Prev state(%d), Trans state(%d)",
- nVirtKey, scanCode, repCount, contextCode, prevState, transState);
+ parameters = QString::asprintf("Virtual-key(0x%x) Scancode(%d) Rep(%d) Contextcode(%d), Prev state(%d), Trans state(%d)",
+ nVirtKey, scanCode, repCount,
+ contextCode, prevState, transState);
}
break;
-#endif
-#ifdef WM_INPUTLANGCHANGE
case WM_INPUTLANGCHANGE:
parameters = QStringLiteral("Keyboard layout changed");
break;
-#endif // WM_INPUTLANGCHANGE
-#ifdef WM_NCACTIVATE
case WM_NCACTIVATE:
- {
parameters = (msg.wParam? QLatin1String("Active Titlebar") : QLatin1String("Inactive Titlebar"));
- }
break;
-#endif
-#ifdef WM_MOUSEACTIVATE
case WM_MOUSEACTIVATE:
{
- QString mouseMsg = QString::fromLatin1(findWMstr(HIWORD(lParam)));
- parameters = QString::asprintf("TLW(0x%p) HittestCode(0x%x) MouseMsg(%s)", (void *)wParam, LOWORD(lParam), mouseMsg.toLatin1().data());
+ const char *mouseMsg = findWMstr(HIWORD(lParam));
+ parameters = QString::asprintf("TLW(0x%p) HittestCode(0x%x) MouseMsg(%s)",
+ reinterpret_cast<void *>(wParam),
+ LOWORD(lParam), mouseMsg ? mouseMsg : "");
}
break;
-#endif
-#ifdef WM_MOUSELEAVE
case WM_MOUSELEAVE:
break; // wParam & lParam not used
-#endif
-#ifdef WM_MOUSEHOVER
case WM_MOUSEHOVER:
-#endif
-#ifdef WM_MOUSEWHEEL
case WM_MOUSEWHEEL:
-#endif
-#ifdef WM_MOUSEHWHEEL
case WM_MOUSEHWHEEL:
-#endif
-#ifdef WM_LBUTTONDBLCLK
case WM_LBUTTONDBLCLK:
-#endif
-#ifdef WM_LBUTTONDOWN
case WM_LBUTTONDOWN:
-#endif
-#ifdef WM_LBUTTONUP
case WM_LBUTTONUP:
-#endif
-#ifdef WM_MBUTTONDBLCLK
case WM_MBUTTONDBLCLK:
-#endif
-#ifdef WM_MBUTTONDOWN
case WM_MBUTTONDOWN:
-#endif
-#ifdef WM_MBUTTONUP
case WM_MBUTTONUP:
-#endif
-#ifdef WM_RBUTTONDBLCLK
case WM_RBUTTONDBLCLK:
-#endif
-#ifdef WM_RBUTTONDOWN
case WM_RBUTTONDOWN:
-#endif
-#ifdef WM_RBUTTONUP
case WM_RBUTTONUP:
-#endif
-#ifdef WM_MOUSEMOVE
case WM_MOUSEMOVE:
- {
- QString vrtKeys = flagCheck(wParam,
- FLGSTR(MK_CONTROL),
- FLGSTR(MK_LBUTTON),
- FLGSTR(MK_MBUTTON),
- FLGSTR(MK_RBUTTON),
- FLGSTR(MK_SHIFT),
-#ifdef MK_XBUTTON1
- FLGSTR(MK_XBUTTON1),
-#endif
-#ifdef MK_XBUTTON2
- FLGSTR(MK_XBUTTON2),
-#endif
- FLAG_STRING());
- parameters = QString::asprintf("x,y(%4d,%4d) Virtual Keys(%s)", GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), vrtKeys.toLatin1().data());
- }
+ parameters = QString::asprintf("x,y(%4d,%4d) Virtual Keys(",
+ GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))
+ + virtualKeys(uint(wParam)) + QLatin1Char(')');
break;
-#endif
-#ifdef WM_MOVE
case WM_MOVE:
parameters = QString::asprintf("x,y(%4d,%4d)", LOWORD(lParam), HIWORD(lParam));
break;
-#endif
-#if defined(WM_PAINT) && defined(WM_ERASEBKGND)
case WM_ERASEBKGND:
case WM_PAINT:
- parameters = QString::asprintf("hdc(0x%p)", (void *)wParam);
+ parameters = QLatin1String("hdc") + wParamS;
break;
-#endif
-#ifdef WM_QUERYNEWPALETTE
case WM_QUERYNEWPALETTE:
break; // lParam & wParam are unused
-#endif
-#ifdef WM_SETCURSOR
case WM_SETCURSOR:
- {
- QString mouseMsg = QString::fromLatin1(findWMstr(HIWORD(lParam)));
- parameters = QString::asprintf("HitTestCode(0x%x) MouseMsg(%s)", LOWORD(lParam), mouseMsg.toLatin1().data());
- }
+ parameters = QString::asprintf("HitTestCode(0x%x) MouseMsg(", LOWORD(lParam));
+ if (const char *mouseMsg = findWMstr(HIWORD(lParam)))
+ parameters += QLatin1String(mouseMsg);
+ parameters += QLatin1Char(')');
break;
-#endif
-#ifdef WM_SETFOCUS
case WM_SETFOCUS:
- parameters = QString::asprintf("Lost Focus (0x%p)", (void *)wParam);
+ parameters = QLatin1String("Lost Focus ") + wParamS;
break;
-#endif
-#ifdef WM_SETTEXT
case WM_SETTEXT:
- parameters = QString::asprintf("Set Text (%s)", QString((QChar*)lParam, (int)wcslen(reinterpret_cast<const wchar_t *>(lParam))).toLatin1().data()); //Unicode string
+ parameters = QLatin1String("Set Text (")
+ + QString::fromWCharArray(reinterpret_cast<const wchar_t *>(lParam))
+ + QLatin1Char(')');
break;
-#endif
-#ifdef WM_SIZE
case WM_SIZE:
- {
- QString showMode = valueCheck(wParam,
- FLGSTR(SIZE_MAXHIDE),
- FLGSTR(SIZE_MAXIMIZED),
- FLGSTR(SIZE_MAXSHOW),
- FLGSTR(SIZE_MINIMIZED),
- FLGSTR(SIZE_RESTORED),
- FLAG_STRING());
-
- parameters = QString::asprintf("w,h(%4d,%4d) showmode(%s)", LOWORD(lParam), HIWORD(lParam), showMode.toLatin1().data());
- }
+ parameters = QString::asprintf("w,h(%4d,%4d) showmode(",
+ LOWORD(lParam), HIWORD(lParam));
+ if (const char *showMode = wmSizeParam(uint(wParam)))
+ parameters += QLatin1String(showMode);
+ parameters += QLatin1Char(')');
break;
-#endif
-#ifdef WM_WINDOWPOSCHANGED
case WM_WINDOWPOSCHANGED:
{
- LPWINDOWPOS winPos = (LPWINDOWPOS)lParam;
+ auto winPos = reinterpret_cast<LPWINDOWPOS>(lParam);
if (!winPos)
break;
- QString hwndAfter = valueCheck(quint64(winPos->hwndInsertAfter),
- FLAG_STRING((qptrdiff)HWND_BOTTOM, "HWND_BOTTOM"),
- FLAG_STRING((qptrdiff)HWND_NOTOPMOST, "HWND_NOTOPMOST"),
- FLAG_STRING((qptrdiff)HWND_TOP, "HWND_TOP"),
- FLAG_STRING((qptrdiff)HWND_TOPMOST, "HWND_TOPMOST"),
- FLAG_STRING());
- if (hwndAfter.isEmpty())
- hwndAfter = QString::number((quintptr)winPos->hwndInsertAfter, 16);
- QString flags = flagCheck(winPos->flags,
- FLGSTR(SWP_DRAWFRAME),
- FLGSTR(SWP_FRAMECHANGED),
- FLGSTR(SWP_HIDEWINDOW),
- FLGSTR(SWP_NOACTIVATE),
-#ifdef SWP_NOCOPYBITS
- FLGSTR(SWP_NOCOPYBITS),
-#endif
- FLGSTR(SWP_NOMOVE),
- FLGSTR(SWP_NOOWNERZORDER),
- FLGSTR(SWP_NOREDRAW),
- FLGSTR(SWP_NOREPOSITION),
-#ifdef SWP_NOSENDCHANGING
- FLGSTR(SWP_NOSENDCHANGING),
-#endif
- FLGSTR(SWP_NOSIZE),
- FLGSTR(SWP_NOZORDER),
- FLGSTR(SWP_SHOWWINDOW),
- FLAG_STRING());
- parameters = QString::asprintf("x,y(%4d,%4d) w,h(%4d,%4d) flags(%s) hwndAfter(%s)", winPos->x, winPos->y, winPos->cx, winPos->cy, flags.toLatin1().data(), hwndAfter.toLatin1().data());
+ const auto insertAfter = quintptr(winPos->hwndInsertAfter);
+ parameters = QString::asprintf("x,y(%4d,%4d) w,h(%4d,%4d) flags(%s) hwndAfter(",
+ winPos->x, winPos->y, winPos->cx, winPos->cy,
+ winPosFlags(winPos->flags).toLatin1().constData());
+ if (const char *h = winPosInsertAfter(insertAfter))
+ parameters += QLatin1String(h);
+ else
+ parameters += QString::number(insertAfter, 16);
+ parameters += QLatin1Char(')');
}
break;
-#endif
-#ifdef WM_QUERYENDSESSION
#ifndef ENDSESSION_CLOSEAPP
#define ENDSESSION_CLOSEAPP 0x00000001
#endif
@@ -991,34 +868,23 @@ QString decodeMSG(const MSG& msg)
#define ENDSESSION_CRITICAL 0x40000000
#endif
case WM_QUERYENDSESSION:
- {
- QString logoffOption = valueCheck(wParam,
- FLAG_STRING(ENDSESSION_CLOSEAPP, "Close application"),
- FLAG_STRING(ENDSESSION_CRITICAL, "Force application end"),
- FLAG_STRING(ENDSESSION_LOGOFF, "User logoff"),
- FLAG_STRING());
- parameters = QLatin1String("End session: ") + logoffOption;
- }
- break;
-#endif
+ parameters = QLatin1String("End session: ");
+ if (const char *logoffOption = sessionMgrLogOffOption(uint(wParam)))
+ parameters += QLatin1String(logoffOption);
+ break;
default:
- parameters = QString::asprintf("wParam(0x%p) lParam(0x%p)", (void *)wParam, (void *)lParam);
+ parameters = QLatin1String("wParam") + wParamS + QLatin1String(" lParam") + lParamS;
break;
}
- // Yes, we want to give the WM_ names 20 chars of space before showing the
- // decoded message, since some of the common messages are quite long, and
- // we don't want the decoded information to vary in output position
- QString message = QString::fromLatin1("%1: ").arg(wmmsg, 20);
- message += rawParameters;
- message += parameters;
- return message;
-}
-#endif
+ return message + QLatin1String("hwnd") + hwndS + QLatin1Char(' ') + parameters;
+}
QDebug operator<<(QDebug dbg, const MSG &msg)
{
QDebugStateSaver saver(dbg);
+ dbg.noquote();
+ dbg.nospace();
dbg << decodeMSG(msg);
return dbg;
}
diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp
index 3d0a9dd05d..cacbb1e495 100644
--- a/src/corelib/kernel/qcoreevent.cpp
+++ b/src/corelib/kernel/qcoreevent.cpp
@@ -44,6 +44,8 @@
#include "qbasicatomic.h"
+#include <qtcore_tracepoints_p.h>
+
#include <limits>
QT_BEGIN_NAMESPACE
@@ -294,7 +296,9 @@ QT_BEGIN_NAMESPACE
*/
QEvent::QEvent(Type type)
: d(0), t(type), posted(false), spont(false), m_accept(true)
-{}
+{
+ Q_TRACE(QEvent_ctor, this, t);
+}
/*!
\internal
@@ -307,6 +311,7 @@ QEvent::QEvent(const QEvent &other)
: d(other.d), t(other.t), posted(other.posted), spont(other.spont),
m_accept(other.m_accept)
{
+ Q_TRACE(QEvent_ctor, this, t);
// if QEventPrivate becomes available, make sure to implement a
// virtual QEventPrivate *clone() const; function so we can copy here
Q_ASSERT_X(!d, "QEvent", "Impossible, this can't happen: QEventPrivate isn't defined anywhere");
@@ -339,6 +344,7 @@ QEvent &QEvent::operator=(const QEvent &other)
QEvent::~QEvent()
{
+ Q_TRACE(QEvent_dtor, this, t);
if (posted && QCoreApplication::instance())
QCoreApplicationPrivate::removePostedEvent(this);
Q_ASSERT_X(!d, "QEvent", "Impossible, this can't happen: QEventPrivate isn't defined anywhere");
diff --git a/src/corelib/kernel/qcoreglobaldata.cpp b/src/corelib/kernel/qcoreglobaldata.cpp
index e2087b9e64..88a45ef4ee 100644
--- a/src/corelib/kernel/qcoreglobaldata.cpp
+++ b/src/corelib/kernel/qcoreglobaldata.cpp
@@ -55,7 +55,10 @@ QCoreGlobalData::~QCoreGlobalData()
{
#if QT_CONFIG(textcodec)
codecForLocale = 0;
- for (QList<QTextCodec *>::const_iterator it = allCodecs.constBegin(); it != allCodecs.constEnd(); ++it)
+ QList<QTextCodec *> tmp = allCodecs;
+ allCodecs.clear();
+ codecCache.clear();
+ for (QList<QTextCodec *>::const_iterator it = tmp.constBegin(); it != tmp.constEnd(); ++it)
delete *it;
#endif
}
diff --git a/src/corelib/kernel/qdeadlinetimer.cpp b/src/corelib/kernel/qdeadlinetimer.cpp
index 8a5bd5d681..466056d513 100644
--- a/src/corelib/kernel/qdeadlinetimer.cpp
+++ b/src/corelib/kernel/qdeadlinetimer.cpp
@@ -39,7 +39,6 @@
#include "qdeadlinetimer.h"
#include "qdeadlinetimer_p.h"
-#include <qpair.h>
QT_BEGIN_NAMESPACE
@@ -76,17 +75,7 @@ Q_DECL_CONST_FUNCTION static inline QPair<qint64, qint64> toSecsAndNSecs(qint64
QDeadlineTimer objects can be passed to functions being called to execute
this operation so they know how long to still operate.
- \code
- void executeOperation(int msecs)
- {
- QDeadlineTimer deadline(msecs);
- do {
- if (readFromDevice(deadline.remainingTime())
- break;
- waitForReadyRead(deadline);
- } while (!deadline.hasExpired());
- }
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 0
Many QDeadlineTimer functions deal with time out values, which all are
measured in milliseconds. There are two special values, the same as many
@@ -126,15 +115,7 @@ Q_DECL_CONST_FUNCTION static inline QPair<qint64, qint64> toSecsAndNSecs(qint64
\c{std::chrono::time_point} objects. In addition, it is fully compatible
with the time literals from C++14, which allow one to write code as:
- \code
- using namespace std::chrono;
- using namespace std::chrono_literals;
-
- QDeadlineTimer deadline(30s);
- device->waitForReadyRead(deadline);
- if (deadline.remainingTime<nanoseconds>() > 300ms)
- cleanup();
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 1
As can be seen in the example above, QDeadlineTimer offers a templated
version of remainingTime() and deadline() that can be used to return
@@ -146,13 +127,7 @@ Q_DECL_CONST_FUNCTION static inline QPair<qint64, qint64> toSecsAndNSecs(qint64
Also note that, due to this conversion, the deadlines will not be precise,
so the following code is not expected to compare equally:
- \code
- using namespace std::chrono;
- using namespace std::chrono_literals;
- auto now = steady_clock::now();
- QDeadlineTimer deadline(now + 1s);
- Q_ASSERT(deadline == now + 1s);
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 2
\sa QTime, QTimer, QDeadlineTimer, Qt::TimerType
*/
@@ -247,10 +222,7 @@ QDeadlineTimer::QDeadlineTimer(qint64 msecs, Qt::TimerType type) Q_DECL_NOTHROW
This constructor can be used with C++14's user-defined literals for time, such as in:
- \code
- using namespace std::chrono_literals;
- QDeadlineTimer deadline(250ms);
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 3
For optimization purposes, if \a remaining is zero or negative, this
function may skip obtaining the current time and may instead use a value
@@ -340,10 +312,7 @@ void QDeadlineTimer::setPreciseRemainingTime(qint64 secs, qint64 nsecs, Qt::Time
This function can be used with C++14's user-defined literals for time, such as in:
- \code
- using namespace std::chrono_literals;
- deadline.setRemainingTime(250ms);
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 4
\note Qt detects the necessary C++14 compiler support by way of the feature
test recommendations from
@@ -416,9 +385,7 @@ void QDeadlineTimer::setTimerType(Qt::TimerType timerType)
lock functions in \l QMutex, \l QWaitCondition, \l QSemaphore, or
\l QReadWriteLock. For example:
- \code
- mutex.tryLock(deadline.remainingTime());
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 5
\sa remainingTimeNSecs(), isForever(), hasExpired()
*/
@@ -470,16 +437,7 @@ qint64 QDeadlineTimer::rawRemainingTimeNSecs() const Q_DECL_NOTHROW
overdue, by subtracting QDeadlineTimer::current() or
QElapsedTimer::msecsSinceReference(), as in the following example:
- \code
- qint64 realTimeLeft = deadline.deadline();
- if (realTimeLeft != (std::numeric_limits<qint64>::max)()) {
- realTimeLeft -= QDeadlineTimer::current().deadline();
- // or:
- //QElapsedTimer timer;
- //timer.start();
- //realTimeLeft -= timer.msecsSinceReference();
- }
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 6
\note Timers that were created as expired have an indetermine time point in
the past as their deadline, so the above calculation may not work.
@@ -506,11 +464,7 @@ qint64 QDeadlineTimer::deadline() const Q_DECL_NOTHROW
overdue, by subtracting QDeadlineTimer::current(), as in the following
example:
- \code
- qint64 realTimeLeft = deadline.deadlineNSecs();
- if (realTimeLeft != std::numeric_limits<qint64>::max())
- realTimeLeft -= QDeadlineTimer::current().deadlineNSecs();
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 7
\note Timers that were created as expired have an indetermine time point in
the past as their deadline, so the above calculation may not work.
@@ -615,9 +569,7 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_
same, false otherwise. The timer type used to create the two deadlines is
ignored. This function is equivalent to:
- \code
- return d1.deadlineNSecs() == d2.deadlineNSecs();
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 8
\note comparing QDeadlineTimer objects with different timer types is
not supported and may result in unpredictable behavior.
@@ -631,9 +583,7 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_
diferent, false otherwise. The timer type used to create the two deadlines
is ignored. This function is equivalent to:
- \code
- return d1.deadlineNSecs() != d2.deadlineNSecs();
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 9
\note comparing QDeadlineTimer objects with different timer types is
not supported and may result in unpredictable behavior.
@@ -647,9 +597,7 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_
d2, false otherwise. The timer type used to create the two deadlines is
ignored. This function is equivalent to:
- \code
- return d1.deadlineNSecs() < d2.deadlineNSecs();
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 10
\note comparing QDeadlineTimer objects with different timer types is
not supported and may result in unpredictable behavior.
@@ -663,9 +611,7 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_
deadline in \a d2, false otherwise. The timer type used to create the two
deadlines is ignored. This function is equivalent to:
- \code
- return d1.deadlineNSecs() <= d2.deadlineNSecs();
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 11
\note comparing QDeadlineTimer objects with different timer types is
not supported and may result in unpredictable behavior.
@@ -679,9 +625,7 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_
d2, false otherwise. The timer type used to create the two deadlines is
ignored. This function is equivalent to:
- \code
- return d1.deadlineNSecs() > d2.deadlineNSecs();
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 12
\note comparing QDeadlineTimer objects with different timer types is
not supported and may result in unpredictable behavior.
@@ -695,9 +639,7 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_
deadline in \a d2, false otherwise. The timer type used to create the two
deadlines is ignored. This function is equivalent to:
- \code
- return d1.deadlineNSecs() >= d2.deadlineNSecs();
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 13
\note comparing QDeadlineTimer objects with different timer types is
not supported and may result in unpredictable behavior.
diff --git a/src/corelib/kernel/qdeadlinetimer.h b/src/corelib/kernel/qdeadlinetimer.h
index 6c10e1025e..1a4ee04a96 100644
--- a/src/corelib/kernel/qdeadlinetimer.h
+++ b/src/corelib/kernel/qdeadlinetimer.h
@@ -43,6 +43,7 @@
#include <QtCore/qelapsedtimer.h>
#include <QtCore/qmetatype.h>
#include <QtCore/qnamespace.h>
+#include <QtCore/qpair.h>
#ifdef max
// un-pollute the namespace. We need std::numeric_limits::max() and std::chrono::duration::max()
@@ -186,6 +187,10 @@ private:
unsigned type;
qint64 rawRemainingTimeNSecs() const Q_DECL_NOTHROW;
+
+public:
+ // This is not a public function, it's here only for Qt's internal convenience...
+ QPair<qint64, unsigned> _q_data() const { return qMakePair(t1, t2); }
};
Q_DECLARE_SHARED(QDeadlineTimer)
diff --git a/src/corelib/kernel/qelapsedtimer_win.cpp b/src/corelib/kernel/qelapsedtimer_win.cpp
index 0c380b2f6a..a63290d2f8 100644
--- a/src/corelib/kernel/qelapsedtimer_win.cpp
+++ b/src/corelib/kernel/qelapsedtimer_win.cpp
@@ -72,10 +72,9 @@ static inline qint64 ticksToNanoseconds(qint64 ticks)
qint64 seconds = ticks / counterFrequency;
qint64 nanoSeconds = (ticks - seconds * counterFrequency) * 1000000000 / counterFrequency;
return seconds * 1000000000 + nanoSeconds;
- } else {
- // GetTickCount(64) return milliseconds
- return ticks * 1000000;
}
+ // GetTickCount(64) returns milliseconds
+ return ticks * 1000000;
}
static inline qint64 nanosecondsToTicks(qint64 nsec)
@@ -83,10 +82,9 @@ static inline qint64 nanosecondsToTicks(qint64 nsec)
if (counterFrequency > 0) {
// QueryPerformanceCounter uses an arbitrary frequency
return double(nsec) * counterFrequency / 1000000000.;
- } else {
- // GetTickCount(64) uses milliseconds
- return nsec / 1000000;
}
+ // GetTickCount(64) uses milliseconds
+ return nsec / 1000000;
}
static quint64 getTickCount()
@@ -116,10 +114,7 @@ QElapsedTimer::ClockType QElapsedTimer::clockType() Q_DECL_NOTHROW
{
resolveCounterFrequency();
- if (counterFrequency > 0)
- return PerformanceCounter;
- else
- return TickCounter;
+ return counterFrequency > 0 ? PerformanceCounter : TickCounter;
}
bool QElapsedTimer::isMonotonic() Q_DECL_NOTHROW
diff --git a/src/corelib/kernel/qeventdispatcher_cf.mm b/src/corelib/kernel/qeventdispatcher_cf.mm
index 503836d071..8881305b18 100644
--- a/src/corelib/kernel/qeventdispatcher_cf.mm
+++ b/src/corelib/kernel/qeventdispatcher_cf.mm
@@ -58,18 +58,36 @@
QT_USE_NAMESPACE
-@interface QT_MANGLE_NAMESPACE(RunLoopModeTracker) : NSObject {
- QStack<CFStringRef> m_runLoopModes;
-}
+/*!
+ During scroll view panning, and possibly other gestures, UIKit will
+ request a switch to UITrackingRunLoopMode via GSEventPushRunLoopMode,
+ which records the new runloop mode and stops the current runloop.
+
+ Unfortunately the runloop mode is just stored on an internal stack, used
+ when UIKit itself is running the runloop, and is not available through e.g.
+ CFRunLoopCopyCurrentMode, which only knows about the current running
+ runloop mode, not the requested future runloop mode.
+
+ To ensure that we pick up this new runloop mode and use it when calling
+ CFRunLoopRunInMode from processEvents, we listen for the notification
+ emitted by [UIApplication pushRunLoopMode:requester:].
+
+ Without this workaround we end up always running in the default runloop
+ mode, resulting in missing momentum-phases in UIScrollViews such as the
+ emoji keyboard.
+*/
+@interface QT_MANGLE_NAMESPACE(RunLoopModeTracker) : NSObject
@end
QT_NAMESPACE_ALIAS_OBJC_CLASS(RunLoopModeTracker);
-@implementation RunLoopModeTracker
+@implementation RunLoopModeTracker {
+ QStack<CFStringRef> m_runLoopModes;
+}
-- (id) init
+- (instancetype)init
{
- if (self = [super init]) {
+ if ((self = [super init])) {
m_runLoopModes.push(kCFRunLoopDefaultMode);
#if !defined(Q_OS_WATCHOS)
@@ -84,9 +102,9 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(RunLoopModeTracker);
return self;
}
-- (void) dealloc
+- (void)dealloc
{
- [[NSNotificationCenter defaultCenter] removeObserver:self];
+ [NSNotificationCenter.defaultCenter removeObserver:self];
[super dealloc];
}
@@ -95,13 +113,13 @@ static CFStringRef runLoopMode(NSDictionary *dictionary)
{
for (NSString *key in dictionary) {
if (CFStringHasSuffix((CFStringRef)key, CFSTR("RunLoopMode")))
- return (CFStringRef)[dictionary objectForKey: key];
+ return (CFStringRef)dictionary[key];
}
return nil;
}
-- (void) receivedNotification:(NSNotification *) notification
+- (void)receivedNotification:(NSNotification *)notification
{
if (CFStringHasSuffix((CFStringRef)notification.name, CFSTR("RunLoopModePushNotification"))) {
if (CFStringRef mode = runLoopMode(notification.userInfo))
@@ -111,7 +129,7 @@ static CFStringRef runLoopMode(NSDictionary *dictionary)
} else if (CFStringHasSuffix((CFStringRef)notification.name, CFSTR("RunLoopModePopNotification"))) {
CFStringRef mode = runLoopMode(notification.userInfo);
- if (CFStringCompare(mode, [self currentMode], 0) == kCFCompareEqualTo)
+ if (CFStringCompare(mode, self.currentMode, 0) == kCFCompareEqualTo)
m_runLoopModes.pop();
else
qCWarning(lcEventDispatcher) << "Tried to pop run loop mode"
@@ -121,7 +139,7 @@ static CFStringRef runLoopMode(NSDictionary *dictionary)
}
}
-- (CFStringRef) currentMode
+- (CFStringRef)currentMode
{
return m_runLoopModes.top();
}
@@ -191,8 +209,16 @@ QEventDispatcherCoreFoundation::QEventDispatcherCoreFoundation(QObject *parent)
, m_blockedRunLoopTimer(0)
, m_overdueTimerScheduled(false)
{
- m_cfSocketNotifier.setHostEventDispatcher(this);
+}
+
+void QEventDispatcherCoreFoundation::startingUp()
+{
+ // The following code must run on the event dispatcher thread, so that
+ // CFRunLoopGetCurrent() returns the correct run loop.
+ Q_ASSERT(QThread::currentThread() == thread());
+ m_runLoop = QCFType<CFRunLoopRef>::constructFromGet(CFRunLoopGetCurrent());
+ m_cfSocketNotifier.setHostEventDispatcher(this);
m_postedEventsRunLoopSource.addToMode(kCFRunLoopCommonModes);
m_runLoopActivityObserver.addToMode(kCFRunLoopCommonModes);
}
@@ -233,6 +259,8 @@ QEventLoop *QEventDispatcherCoreFoundation::currentEventLoop() const
*/
bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlags flags)
{
+ QT_APPLE_SCOPED_LOG_ACTIVITY(lcEventDispatcher().isDebugEnabled(), "processEvents");
+
bool eventsProcessed = false;
if (flags & (QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers))
@@ -385,6 +413,8 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag
bool QEventDispatcherCoreFoundation::processPostedEvents()
{
+ QT_APPLE_SCOPED_LOG_ACTIVITY(lcEventDispatcher().isDebugEnabled(), "processPostedEvents");
+
if (m_processEvents.processedPostedEvents && !(m_processEvents.flags & QEventLoop::EventLoopExec)) {
qCDebug(lcEventDispatcher) << "Already processed events this pass";
return false;
@@ -392,7 +422,8 @@ bool QEventDispatcherCoreFoundation::processPostedEvents()
m_processEvents.processedPostedEvents = true;
- qCDebug(lcEventDispatcher) << "Sending posted events for" << m_processEvents.flags;
+ qCDebug(lcEventDispatcher) << "Sending posted events for"
+ << QEventLoop::ProcessEventsFlags(m_processEvents.flags.load());
QCoreApplication::sendPostedEvents();
return true;
@@ -400,6 +431,8 @@ bool QEventDispatcherCoreFoundation::processPostedEvents()
void QEventDispatcherCoreFoundation::processTimers(CFRunLoopTimerRef timer)
{
+ QT_APPLE_SCOPED_LOG_ACTIVITY(lcEventDispatcher().isDebugEnabled(), "processTimers");
+
if (m_processEvents.processedTimers && !(m_processEvents.flags & QEventLoop::EventLoopExec)) {
qCDebug(lcEventDispatcher) << "Already processed timers this pass";
m_processEvents.deferredUpdateTimers = true;
@@ -473,7 +506,7 @@ bool QEventDispatcherCoreFoundation::hasPendingEvents()
// 'maybeHasPendingEvents' in our case.
extern uint qGlobalPostedEventsCount();
- return qGlobalPostedEventsCount() || !CFRunLoopIsWaiting(CFRunLoopGetMain());
+ return qGlobalPostedEventsCount() || !CFRunLoopIsWaiting(m_runLoop);
}
void QEventDispatcherCoreFoundation::wakeUp()
@@ -493,7 +526,8 @@ void QEventDispatcherCoreFoundation::wakeUp()
}
m_postedEventsRunLoopSource.signal();
- CFRunLoopWakeUp(CFRunLoopGetMain());
+ if (m_runLoop)
+ CFRunLoopWakeUp(m_runLoop);
qCDebug(lcEventDispatcher) << "Signaled posted event run-loop source";
}
@@ -502,7 +536,7 @@ void QEventDispatcherCoreFoundation::interrupt()
{
qCDebug(lcEventDispatcher) << "Marking current processEvent as interrupted";
m_processEvents.wasInterrupted = true;
- CFRunLoopStop(CFRunLoopGetMain());
+ CFRunLoopStop(m_runLoop);
}
void QEventDispatcherCoreFoundation::flush()
@@ -597,7 +631,7 @@ void QEventDispatcherCoreFoundation::updateTimers()
processTimers(timer);
});
- CFRunLoopAddTimer(CFRunLoopGetMain(), m_runLoopTimer, kCFRunLoopCommonModes);
+ CFRunLoopAddTimer(m_runLoop, m_runLoopTimer, kCFRunLoopCommonModes);
qCDebug(lcEventDispatcherTimers) << "Created new CFRunLoopTimer" << m_runLoopTimer;
} else {
diff --git a/src/corelib/kernel/qeventdispatcher_cf_p.h b/src/corelib/kernel/qeventdispatcher_cf_p.h
index a607ab7a15..26191d520c 100644
--- a/src/corelib/kernel/qeventdispatcher_cf_p.h
+++ b/src/corelib/kernel/qeventdispatcher_cf_p.h
@@ -208,24 +208,25 @@ class Q_CORE_EXPORT QEventDispatcherCoreFoundation : public QAbstractEventDispat
public:
explicit QEventDispatcherCoreFoundation(QObject *parent = 0);
+ void startingUp() override;
~QEventDispatcherCoreFoundation();
- bool processEvents(QEventLoop::ProcessEventsFlags flags);
- bool hasPendingEvents();
+ bool processEvents(QEventLoop::ProcessEventsFlags flags) override;
+ bool hasPendingEvents() override;
- void registerSocketNotifier(QSocketNotifier *notifier);
- void unregisterSocketNotifier(QSocketNotifier *notifier);
+ void registerSocketNotifier(QSocketNotifier *notifier) override;
+ void unregisterSocketNotifier(QSocketNotifier *notifier) override;
- void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object);
- bool unregisterTimer(int timerId);
- bool unregisterTimers(QObject *object);
- QList<QAbstractEventDispatcher::TimerInfo> registeredTimers(QObject *object) const;
+ void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) override;
+ bool unregisterTimer(int timerId) override;
+ bool unregisterTimers(QObject *object) override;
+ QList<QAbstractEventDispatcher::TimerInfo> registeredTimers(QObject *object) const override;
- int remainingTime(int timerId);
+ int remainingTime(int timerId) override;
- void wakeUp();
- void interrupt();
- void flush();
+ void wakeUp() override;
+ void interrupt() override;
+ void flush() override;
protected:
QEventLoop *currentEventLoop() const;
@@ -239,11 +240,11 @@ protected:
, processedPostedEvents(false), processedTimers(false)
, deferredWakeUp(false), deferredUpdateTimers(false) {}
- QEventLoop::ProcessEventsFlags flags;
- bool wasInterrupted;
- bool processedPostedEvents;
- bool processedTimers;
- bool deferredWakeUp;
+ QAtomicInt flags;
+ QAtomicInteger<char> wasInterrupted;
+ QAtomicInteger<char> processedPostedEvents;
+ QAtomicInteger<char> processedTimers;
+ QAtomicInteger<char> deferredWakeUp;
bool deferredUpdateTimers;
};
@@ -258,6 +259,7 @@ private:
QTimerInfoList m_timerInfoList;
CFRunLoopTimerRef m_runLoopTimer;
CFRunLoopTimerRef m_blockedRunLoopTimer;
+ QCFType<CFRunLoopRef> m_runLoop;
bool m_overdueTimerScheduled;
QCFSocketNotifier m_cfSocketNotifier;
diff --git a/src/corelib/kernel/qeventdispatcher_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp
index 4c780a9294..45c6e29e4b 100644
--- a/src/corelib/kernel/qeventdispatcher_glib.cpp
+++ b/src/corelib/kernel/qeventdispatcher_glib.cpp
@@ -260,8 +260,8 @@ static gboolean postEventSourcePrepare(GSource *s, gint *timeout)
*timeout = canWait ? -1 : 0;
GPostEventSource *source = reinterpret_cast<GPostEventSource *>(s);
- return (!canWait
- || (source->serialNumber.load() != source->lastSerialNumber));
+ source->d->wakeUpCalled = source->serialNumber.load() != source->lastSerialNumber;
+ return !canWait || source->d->wakeUpCalled;
}
static gboolean postEventSourceCheck(GSource *source)
diff --git a/src/corelib/kernel/qeventdispatcher_glib_p.h b/src/corelib/kernel/qeventdispatcher_glib_p.h
index 799f23b14a..88ff316ee5 100644
--- a/src/corelib/kernel/qeventdispatcher_glib_p.h
+++ b/src/corelib/kernel/qeventdispatcher_glib_p.h
@@ -108,6 +108,7 @@ public:
GSocketNotifierSource *socketNotifierSource;
GTimerSource *timerSource;
GIdleTimerSource *idleTimerSource;
+ bool wakeUpCalled = true;
void runTimersOnceWithNormalPriority();
};
diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp
index a28f2e3f0a..535f86fefe 100644
--- a/src/corelib/kernel/qeventdispatcher_unix.cpp
+++ b/src/corelib/kernel/qeventdispatcher_unix.cpp
@@ -130,7 +130,7 @@ static void initThreadPipeFD(int fd)
bool QThreadPipe::init()
{
-#if defined(Q_OS_NACL)
+#if defined(Q_OS_NACL) || defined(Q_OS_WASM)
// do nothing.
#elif defined(Q_OS_VXWORKS)
qsnprintf(name, sizeof(name), "/pipe/qt_%08x", int(taskIdSelf()));
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp
index 330870f219..0bddf89b15 100644
--- a/src/corelib/kernel/qeventdispatcher_win.cpp
+++ b/src/corelib/kernel/qeventdispatcher_win.cpp
@@ -120,7 +120,7 @@ void WINAPI QT_WIN_CALLBACK qt_fast_timer_proc(uint timerId, uint /*reserved*/,
{
if (!timerId) // sanity check
return;
- WinTimerInfo *t = (WinTimerInfo*)user;
+ auto t = reinterpret_cast<WinTimerInfo*>(user);
Q_ASSERT(t);
QCoreApplication::postEvent(t->dispatcher, new QTimerEvent(t->timerId));
}
@@ -141,20 +141,21 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
if (message == WM_TIMER)
KillTimer(hwnd, wp);
return 0;
- } else if (dispatcher->filterNativeEvent(QByteArrayLiteral("windows_dispatcher_MSG"), &msg, &result)) {
- return result;
}
+ if (dispatcher->filterNativeEvent(QByteArrayLiteral("windows_dispatcher_MSG"), &msg, &result))
+ return result;
#ifdef GWLP_USERDATA
- QEventDispatcherWin32 *q = (QEventDispatcherWin32 *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ auto q = reinterpret_cast<QEventDispatcherWin32 *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
#else
- QEventDispatcherWin32 *q = (QEventDispatcherWin32 *) GetWindowLong(hwnd, GWL_USERDATA);
+ auto q = reinterpret_cast<QEventDispatcherWin32 *>(GetWindowLong(hwnd, GWL_USERDATA));
#endif
QEventDispatcherWin32Private *d = 0;
if (q != 0)
d = q->d_func();
- if (message == WM_QT_SOCKETNOTIFIER) {
+ switch (message) {
+ case WM_QT_SOCKETNOTIFIER: {
// socket notifier message
int type = -1;
switch (WSAGETSELECTEVENT(lp)) {
@@ -202,7 +203,8 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
}
}
return 0;
- } else if (message == WM_QT_ACTIVATENOTIFIERS) {
+ }
+ case WM_QT_ACTIVATENOTIFIERS: {
Q_ASSERT(d != 0);
// Postpone activation if we have unhandled socket notifier messages
@@ -226,22 +228,25 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
}
d->activateNotifiersPosted = false;
return 0;
- } else if (message == WM_QT_SENDPOSTEDEVENTS
- // we also use a Windows timer to send posted events when the message queue is full
- || (message == WM_TIMER
- && d->sendPostedEventsWindowsTimerId != 0
- && wp == (uint)d->sendPostedEventsWindowsTimerId)) {
+ }
+ case WM_TIMER:
+ if (d->sendPostedEventsWindowsTimerId == 0
+ || wp != uint(d->sendPostedEventsWindowsTimerId)) {
+ Q_ASSERT(d != 0);
+ d->sendTimerEvent(wp);
+ return 0;
+ }
+ // we also use a Windows timer to send posted events when the message queue is full
+ Q_FALLTHROUGH();
+ case WM_QT_SENDPOSTEDEVENTS: {
const int localSerialNumber = d->serialNumber.load();
if (localSerialNumber != d->lastSerialNumber) {
d->lastSerialNumber = localSerialNumber;
q->sendPostedEvents();
}
return 0;
- } else if (message == WM_TIMER) {
- Q_ASSERT(d != 0);
- d->sendTimerEvent(wp);
- return 0;
}
+ } // switch (message)
return DefWindowProc(hwnd, message, wp, lp);
}
@@ -369,9 +374,9 @@ static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatch
}
#ifdef GWLP_USERDATA
- SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)eventDispatcher);
+ SetWindowLongPtr(wnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(eventDispatcher));
#else
- SetWindowLong(wnd, GWL_USERDATA, (LONG)eventDispatcher);
+ SetWindowLong(wnd, GWL_USERDATA, reinterpret_cast<LONG>(eventDispatcher));
#endif
return wnd;
@@ -522,6 +527,22 @@ QEventDispatcherWin32::~QEventDispatcherWin32()
{
}
+static bool isUserInputMessage(UINT message)
+{
+ return (message >= WM_KEYFIRST && message <= WM_KEYLAST)
+ || (message >= WM_MOUSEFIRST && message <= WM_MOUSELAST)
+ || message == WM_MOUSEWHEEL
+ || message == WM_MOUSEHWHEEL
+ || message == WM_TOUCH
+#ifndef QT_NO_GESTURES
+ || message == WM_GESTURE
+ || message == WM_GESTURENOTIFY
+#endif
+// Pointer input: Exclude WM_NCPOINTERUPDATE .. WM_POINTERROUTEDRELEASED
+ || (message >= 0x0241 && message <= 0x0253)
+ || message == WM_CLOSE;
+}
+
bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
{
Q_D(QEventDispatcherWin32);
@@ -562,19 +583,8 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
} else {
haveMessage = PeekMessage(&msg, 0, 0, 0, PM_REMOVE);
if (haveMessage) {
- if ((flags & QEventLoop::ExcludeUserInputEvents)
- && ((msg.message >= WM_KEYFIRST
- && msg.message <= WM_KEYLAST)
- || (msg.message >= WM_MOUSEFIRST
- && msg.message <= WM_MOUSELAST)
- || msg.message == WM_MOUSEWHEEL
- || msg.message == WM_MOUSEHWHEEL
- || msg.message == WM_TOUCH
-#ifndef QT_NO_GESTURES
- || msg.message == WM_GESTURE
- || msg.message == WM_GESTURENOTIFY
-#endif
- || msg.message == WM_CLOSE)) {
+ if (flags.testFlag(QEventLoop::ExcludeUserInputEvents)
+ && isUserInputMessage(msg.message)) {
// queue user input events for later processing
d->queuedUserInputEvents.append(msg);
continue;
@@ -598,7 +608,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
if (haveMessage) {
// WinCE doesn't support hooks at all, so we have to call this by hand :(
if (!d->getMessageHook)
- (void) qt_GetMessageHook(0, PM_REMOVE, (LPARAM) &msg);
+ (void) qt_GetMessageHook(0, PM_REMOVE, reinterpret_cast<LPARAM>(&msg));
if (d->internalHwnd == msg.hwnd && msg.message == WM_QT_SENDPOSTEDEVENTS) {
if (seenWM_QT_SENDPOSTEDEVENTS) {
@@ -678,7 +688,8 @@ void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier)
if (sockfd < 0) {
qWarning("QSocketNotifier: Internal error");
return;
- } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
+ }
+ if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread");
return;
}
@@ -738,7 +749,8 @@ void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier)
if (sockfd < 0) {
qWarning("QSocketNotifier: Internal error");
return;
- } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
+ }
+ if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
qWarning("QSocketNotifier: socket notifiers cannot be disabled from another thread");
return;
}
@@ -784,7 +796,8 @@ void QEventDispatcherWin32::registerTimer(int timerId, int interval, Qt::TimerTy
if (timerId < 1 || interval < 0 || !object) {
qWarning("QEventDispatcherWin32::registerTimer: invalid arguments");
return;
- } else if (object->thread() != thread() || thread() != QThread::currentThread()) {
+ }
+ if (object->thread() != thread() || thread() != QThread::currentThread()) {
qWarning("QEventDispatcherWin32::registerTimer: timers cannot be started from another thread");
return;
}
@@ -881,8 +894,7 @@ QEventDispatcherWin32::registeredTimers(QObject *object) const
Q_D(const QEventDispatcherWin32);
QList<TimerInfo> list;
- for (int i = 0; i < d->timerVec.size(); ++i) {
- const WinTimerInfo *t = d->timerVec.at(i);
+ for (const WinTimerInfo *t : qAsConst(d->timerVec)) {
if (t && t->obj == object)
list << TimerInfo(t->timerId, t->interval, t->timerType);
}
@@ -979,17 +991,9 @@ int QEventDispatcherWin32::remainingTime(int timerId)
quint64 currentTime = qt_msectime();
- WinTimerInfo *t;
- for (int i=0; i<d->timerVec.size(); i++) {
- t = d->timerVec.at(i);
- if (t && t->timerId == timerId) { // timer found
- if (currentTime < t->timeout) {
- // time to wait
- return t->timeout - currentTime;
- } else {
- return 0;
- }
- }
+ for (const WinTimerInfo *t : qAsConst(d->timerVec)) {
+ if (t && t->timerId == timerId) // timer found, return time to wait
+ return t->timeout > currentTime ? t->timeout - currentTime : 0;
}
#ifndef QT_NO_DEBUG
@@ -1049,7 +1053,8 @@ void QEventDispatcherWin32::closingDown()
bool QEventDispatcherWin32::event(QEvent *e)
{
Q_D(QEventDispatcherWin32);
- if (e->type() == QEvent::ZeroTimerEvent) {
+ switch (e->type()) {
+ case QEvent::ZeroTimerEvent: {
QZeroTimerEvent *zte = static_cast<QZeroTimerEvent*>(e);
WinTimerInfo *t = d->timerDict.value(zte->timerId());
if (t) {
@@ -1071,9 +1076,12 @@ bool QEventDispatcherWin32::event(QEvent *e)
}
}
return true;
- } else if (e->type() == QEvent::Timer) {
- QTimerEvent *te = static_cast<QTimerEvent*>(e);
- d->sendTimerEvent(te->timerId());
+ }
+ case QEvent::Timer:
+ d->sendTimerEvent(static_cast<const QTimerEvent*>(e)->timerId());
+ break;
+ default:
+ break;
}
return QAbstractEventDispatcher::event(e);
}
diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp
index 33753ed507..600c6c38fd 100644
--- a/src/corelib/kernel/qeventdispatcher_winrt.cpp
+++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp
@@ -43,6 +43,8 @@
#include <QtCore/QThread>
#include <QtCore/QHash>
#include <QtCore/QMutex>
+#include <QtCore/QSemaphore>
+#include <QtCore/QSharedPointer>
#include <QtCore/qfunctions_winrt.h>
#include <private/qabstracteventdispatcher_p.h>
#include <private/qcoreapplication_p.h>
@@ -293,6 +295,26 @@ HRESULT QEventDispatcherWinRT::runOnXamlThread(const std::function<HRESULT ()> &
return QWinRTFunctions::await(op);
}
+HRESULT QEventDispatcherWinRT::runOnMainThread(const std::function<HRESULT()> &delegate, int timeout)
+{
+ if (QThread::currentThread() == QCoreApplication::instance()->thread())
+ return delegate();
+
+ auto semaphore = QSharedPointer<QSemaphore>(new QSemaphore);
+ auto ptrSemaphore = new QSharedPointer<QSemaphore>(semaphore);
+ auto result = QSharedPointer<HRESULT>(new HRESULT);
+ auto ptrResult = new QSharedPointer<HRESULT>(result);
+
+ QMetaObject::invokeMethod(QCoreApplication::instance(), [delegate, ptrSemaphore, ptrResult]() {
+ **ptrResult = delegate();
+ delete ptrResult;
+ (*ptrSemaphore)->release();
+ delete ptrSemaphore;
+ }, nullptr);
+
+ return semaphore->tryAcquire(1, timeout) ? *result : E_FAIL;
+}
+
bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
{
Q_D(QEventDispatcherWinRT);
diff --git a/src/corelib/kernel/qeventdispatcher_winrt_p.h b/src/corelib/kernel/qeventdispatcher_winrt_p.h
index f69bb9cf3f..8b998a7958 100644
--- a/src/corelib/kernel/qeventdispatcher_winrt_p.h
+++ b/src/corelib/kernel/qeventdispatcher_winrt_p.h
@@ -75,6 +75,7 @@ public:
~QEventDispatcherWinRT();
static HRESULT runOnXamlThread(const std::function<HRESULT()> &delegate, bool waitForRun = true);
+ static HRESULT runOnMainThread(const std::function<HRESULT()> &delegate, int timeout = 100);
bool processEvents(QEventLoop::ProcessEventsFlags flags);
bool hasPendingEvents();
diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp
index 6034698349..a6cc51621a 100644
--- a/src/corelib/kernel/qeventloop.cpp
+++ b/src/corelib/kernel/qeventloop.cpp
@@ -48,6 +48,10 @@
#include "qeventloop_p.h"
#include <private/qthread_p.h>
+#ifdef Q_OS_WASM
+#include <emscripten.h>
+#endif
+
QT_BEGIN_NAMESPACE
/*!
@@ -101,10 +105,8 @@ QEventLoop::QEventLoop(QObject *parent)
Q_D(QEventLoop);
if (!QCoreApplication::instance() && QCoreApplicationPrivate::threadRequiresCoreApplication()) {
qWarning("QEventLoop: Cannot be used without QApplication");
- } else if (!d->threadData->hasEventDispatcher()) {
- QAbstractEventDispatcher *eventDispatcher = QThreadPrivate::createEventDispatcher(d->threadData);
- d->threadData->eventDispatcher.storeRelease(eventDispatcher);
- eventDispatcher->startingUp();
+ } else {
+ d->threadData->ensureEventDispatcher();
}
}
@@ -210,6 +212,15 @@ int QEventLoop::exec(ProcessEventsFlags flags)
if (app && app->thread() == thread())
QCoreApplication::removePostedEvents(app, QEvent::Quit);
+#ifdef Q_OS_WASM
+ // Partial support for nested event loops: Make the runtime throw a JavaSrcript
+ // exception, which returns control to the browser while preserving the C++ stack.
+ // Event processing then continues as normal. The sleep call below never returns.
+ // QTBUG-70185
+ if (d->threadData->loopLevel > 1)
+ emscripten_sleep(1);
+#endif
+
while (!d->exit.loadAcquire())
processEvents(flags | WaitForMoreEvents | EventLoopExec);
@@ -271,6 +282,17 @@ void QEventLoop::exit(int returnCode)
d->returnCode.store(returnCode);
d->exit.storeRelease(true);
d->threadData->eventDispatcher.load()->interrupt();
+
+#ifdef Q_OS_WASM
+ // QEventLoop::exec() never returns in emscripten. We implement approximate behavior here.
+ // QTBUG-70185
+ if (d->threadData->loopLevel == 1) {
+ emscripten_force_exit(returnCode);
+ } else {
+ d->inExec = false;
+ --d->threadData->loopLevel;
+ }
+#endif
}
/*!
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index 27138dd075..c642cd07f2 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -50,7 +50,9 @@
#include <qthread.h>
#include <qvariant.h>
#include <qdebug.h>
+#if QT_CONFIG(thread)
#include <qsemaphore.h>
+#endif
#include "private/qobject_p.h"
#include "private/qmetaobject_p.h"
@@ -970,8 +972,23 @@ int QMetaObject::indexOfEnumerator(const char *name) const
const QMetaObject *m = this;
while (m) {
const QMetaObjectPrivate *d = priv(m->d.data);
+ const int intsPerEnum = d->revision >= 8 ? 5 : 4;
+ for (int i = d->enumeratorCount - 1; i >= 0; --i) {
+ const char *prop = rawStringData(m, m->d.data[d->enumeratorData + intsPerEnum * i]);
+ if (name[0] == prop[0] && strcmp(name + 1, prop + 1) == 0) {
+ i += m->enumeratorOffset();
+ return i;
+ }
+ }
+ m = m->d.superdata;
+ }
+ // Check alias names:
+ m = this;
+ while (m) {
+ const QMetaObjectPrivate *d = priv(m->d.data);
+ const int intsPerEnum = d->revision >= 8 ? 5 : 4;
for (int i = d->enumeratorCount - 1; i >= 0; --i) {
- const char *prop = rawStringData(m, m->d.data[d->enumeratorData + 4*i]);
+ const char *prop = rawStringData(m, m->d.data[d->enumeratorData + intsPerEnum * i + 1]);
if (name[0] == prop[0] && strcmp(name + 1, prop + 1) == 0) {
i += m->enumeratorOffset();
return i;
@@ -1086,10 +1103,11 @@ QMetaEnum QMetaObject::enumerator(int index) const
if (i < 0 && d.superdata)
return d.superdata->enumerator(index);
+ const int intsPerEnum = priv(d.data)->revision >= 8 ? 5 : 4;
QMetaEnum result;
if (i >= 0 && i < priv(d.data)->enumeratorCount) {
result.mobj = this;
- result.handle = priv(d.data)->enumeratorData + 4*i;
+ result.handle = priv(d.data)->enumeratorData + intsPerEnum * i;
}
return result;
}
@@ -1525,14 +1543,14 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *
QCoreApplication::postEvent(object, new QMetaCallEvent(slot, 0, -1, 1, types, args));
} else if (type == Qt::BlockingQueuedConnection) {
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
if (currentThread == objectThread)
qWarning("QMetaObject::invokeMethod: Dead lock detected");
QSemaphore semaphore;
QCoreApplication::postEvent(object, new QMetaCallEvent(slot, 0, -1, 0, 0, argv, &semaphore));
semaphore.acquire();
-#endif // QT_NO_THREAD
+#endif // QT_CONFIG(thread)
} else {
qWarning("QMetaObject::invokeMethod: Unknown connection type");
return false;
@@ -1950,9 +1968,8 @@ QList<QByteArray> QMetaMethod::parameterTypes() const
*/
QList<QByteArray> QMetaMethod::parameterNames() const
{
- QList<QByteArray> list;
if (!mobj)
- return list;
+ return QList<QByteArray>();
return QMetaMethodPrivate::get(this)->parameterNames();
}
@@ -1978,27 +1995,11 @@ const char *QMetaMethod::typeName() const
Tag information can be added in the following
way in the function declaration:
- \code
- // In the class MainWindow declaration
- #ifndef Q_MOC_RUN
- // define the tag text as empty, so the compiler doesn't see it
- # define MY_CUSTOM_TAG
- #endif
- ...
- private slots:
- MY_CUSTOM_TAG void testFunc();
- \endcode
+ \snippet code/src_corelib_kernel_qmetaobject.cpp 10
and the information can be accessed by using:
- \code
- MainWindow win;
- win.show();
-
- int functionIndex = win.metaObject()->indexOfSlot("testFunc()");
- QMetaMethod mm = win.metaObject()->method(functionIndex);
- qDebug() << mm.tag(); // prints MY_CUSTOM_TAG
- \endcode
+ \snippet code/src_corelib_kernel_qmetaobject.cpp 11
For the moment, \c moc will extract and record all tags, but it will not
handle any of them specially. You can use the tags to annotate your methods
@@ -2257,7 +2258,7 @@ bool QMetaMethod::invoke(QObject *object,
: Qt::QueuedConnection;
}
-#ifdef QT_NO_THREAD
+#if !QT_CONFIG(thread)
if (connectionType == Qt::BlockingQueuedConnection) {
connectionType = Qt::DirectConnection;
}
@@ -2333,7 +2334,7 @@ bool QMetaMethod::invoke(QObject *object,
QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction,
0, -1, nargs, types, args));
} else { // blocking queued connection
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
if (currentThread == objectThread) {
qWarning("QMetaMethod::invoke: Dead lock detected in "
"BlockingQueuedConnection: Receiver is %s(%p)",
@@ -2344,7 +2345,7 @@ bool QMetaMethod::invoke(QObject *object,
QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction,
0, -1, 0, 0, param, &semaphore));
semaphore.acquire();
-#endif // QT_NO_THREAD
+#endif // QT_CONFIG(thread)
}
return true;
}
@@ -2552,12 +2553,15 @@ bool QMetaMethod::invokeOnGadget(void* gadget, QGenericReturnArgument returnValu
*/
/*!
- Returns the name of the enumerator (without the scope).
+ Returns the name of the type (without the scope).
- For example, the Qt::AlignmentFlag enumeration has \c
- AlignmentFlag as the name and \l Qt as the scope.
+ For example, the Qt::Key enumeration has \c
+ Key as the type name and \l Qt as the scope.
- \sa isValid(), scope()
+ For flags this returns the name of the flag type, not the
+ name of the enum type.
+
+ \sa isValid(), scope(), enumName()
*/
const char *QMetaEnum::name() const
{
@@ -2567,6 +2571,28 @@ const char *QMetaEnum::name() const
}
/*!
+ Returns the enum name of the flag (without the scope).
+
+ For example, the Qt::AlignmentFlag flag has \c
+ AlignmentFlag as the enum name, but \c Alignment as as the type name.
+ Non flag enums has the same type and enum names.
+
+ Enum names have the same scope as the type name.
+
+ \since 5.12
+ \sa isValid(), name()
+*/
+const char *QMetaEnum::enumName() const
+{
+ if (!mobj)
+ return 0;
+ const bool rev8p = priv(mobj->d.data)->revision >= 8;
+ if (rev8p)
+ return rawStringData(mobj, mobj->d.data[handle + 1]);
+ return name();
+}
+
+/*!
Returns the number of keys.
\sa key()
@@ -2575,10 +2601,10 @@ int QMetaEnum::keyCount() const
{
if (!mobj)
return 0;
- return mobj->d.data[handle + 2];
+ const int offset = priv(mobj->d.data)->revision >= 8 ? 3 : 2;
+ return mobj->d.data[handle + offset];
}
-
/*!
Returns the key with the given \a index, or 0 if no such key exists.
@@ -2588,8 +2614,9 @@ const char *QMetaEnum::key(int index) const
{
if (!mobj)
return 0;
- int count = mobj->d.data[handle + 2];
- int data = mobj->d.data[handle + 3];
+ const int offset = priv(mobj->d.data)->revision >= 8 ? 3 : 2;
+ int count = mobj->d.data[handle + offset];
+ int data = mobj->d.data[handle + offset + 1];
if (index >= 0 && index < count)
return rawStringData(mobj, mobj->d.data[data + 2*index]);
return 0;
@@ -2605,8 +2632,9 @@ int QMetaEnum::value(int index) const
{
if (!mobj)
return 0;
- int count = mobj->d.data[handle + 2];
- int data = mobj->d.data[handle + 3];
+ const int offset = priv(mobj->d.data)->revision >= 8 ? 3 : 2;
+ int count = mobj->d.data[handle + offset];
+ int data = mobj->d.data[handle + offset + 1];
if (index >= 0 && index < count)
return mobj->d.data[data + 2*index + 1];
return -1;
@@ -2624,7 +2652,10 @@ int QMetaEnum::value(int index) const
*/
bool QMetaEnum::isFlag() const
{
- return mobj && mobj->d.data[handle + 1] & EnumIsFlag;
+ if (!mobj)
+ return false;
+ const int offset = priv(mobj->d.data)->revision >= 8 ? 2 : 1;
+ return mobj->d.data[handle + offset] & EnumIsFlag;
}
/*!
@@ -2635,7 +2666,10 @@ bool QMetaEnum::isFlag() const
*/
bool QMetaEnum::isScoped() const
{
- return mobj && mobj->d.data[handle + 1] & EnumIsScoped;
+ if (!mobj)
+ return false;
+ const int offset = priv(mobj->d.data)->revision >= 8 ? 2 : 1;
+ return mobj->d.data[handle + offset] & EnumIsScoped;
}
/*!
@@ -2677,8 +2711,9 @@ int QMetaEnum::keyToValue(const char *key, bool *ok) const
scope = s - key - 1;
key += scope + 2;
}
- int count = mobj->d.data[handle + 2];
- int data = mobj->d.data[handle + 3];
+ const int offset = priv(mobj->d.data)->revision >= 8 ? 3 : 2;
+ int count = mobj->d.data[handle + offset];
+ int data = mobj->d.data[handle + offset + 1];
for (int i = 0; i < count; ++i) {
const QByteArray className = stringData(mobj, priv(mobj->d.data)->className);
if ((!scope || (className.size() == int(scope) && strncmp(qualified_key, className.constData(), scope) == 0))
@@ -2703,8 +2738,9 @@ const char* QMetaEnum::valueToKey(int value) const
{
if (!mobj)
return 0;
- int count = mobj->d.data[handle + 2];
- int data = mobj->d.data[handle + 3];
+ const int offset = priv(mobj->d.data)->revision >= 8 ? 3 : 2;
+ int count = mobj->d.data[handle + offset];
+ int data = mobj->d.data[handle + offset + 1];
for (int i = 0; i < count; ++i)
if (value == (int)mobj->d.data[data + 2*i + 1])
return rawStringData(mobj, mobj->d.data[data + 2*i]);
@@ -2735,8 +2771,9 @@ int QMetaEnum::keysToValue(const char *keys, bool *ok) const
return 0;
// ### TODO write proper code: do not allocate memory, so we can go nothrow
int value = 0;
- int count = mobj->d.data[handle + 2];
- int data = mobj->d.data[handle + 3];
+ const int offset = priv(mobj->d.data)->revision >= 8 ? 3 : 2;
+ int count = mobj->d.data[handle + offset];
+ int data = mobj->d.data[handle + offset + 1];
for (const QStringRef &untrimmed : splitKeys) {
const QStringRef trimmed = untrimmed.trimmed();
QByteArray qualified_key = trimmed.toLatin1();
@@ -2778,8 +2815,9 @@ QByteArray QMetaEnum::valueToKeys(int value) const
QByteArray keys;
if (!mobj)
return keys;
- int count = mobj->d.data[handle + 2];
- int data = mobj->d.data[handle + 3];
+ const int offset = priv(mobj->d.data)->revision >= 8 ? 3 : 2;
+ int count = mobj->d.data[handle + offset];
+ int data = mobj->d.data[handle + offset + 1];
int v = value;
// reverse iterate to ensure values like Qt::Dialog=0x2|Qt::Window are processed first.
for (int i = count - 1; i >= 0; --i) {
diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h
index 51df8faad3..51ace3d5f7 100644
--- a/src/corelib/kernel/qmetaobject.h
+++ b/src/corelib/kernel/qmetaobject.h
@@ -209,6 +209,7 @@ public:
Q_DECL_CONSTEXPR inline QMetaEnum() : mobj(nullptr), handle(0) {}
const char *name() const;
+ const char *enumName() const;
bool isFlag() const;
bool isScoped() const;
diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h
index 434ef84808..522bd78e42 100644
--- a/src/corelib/kernel/qmetaobject_p.h
+++ b/src/corelib/kernel/qmetaobject_p.h
@@ -60,6 +60,8 @@
#include <QtCore/qvarlengtharray.h>
QT_BEGIN_NAMESPACE
+// ### TODO Qt6: add a proper namespace with Q_NAMESPACE and use scoped enums
+// A namespace and scoped are needed to avoid enum clashes
enum PropertyFlags {
Invalid = 0x00000000,
@@ -103,7 +105,7 @@ enum MethodFlags {
MethodRevisioned = 0x80
};
-enum MetaObjectFlags {
+enum MetaObjectFlags { // keep it in sync with QMetaObjectBuilder::MetaObjectFlag enum
DynamicMetaObject = 0x01,
RequiresVariantMetaObject = 0x02,
PropertyAccessInStaticMetaCall = 0x04 // since Qt 5.5, property code is in the static metacall
@@ -171,7 +173,8 @@ class QMutex;
struct QMetaObjectPrivate
{
// revision 7 is Qt 5.0 everything lower is not supported
- enum { OutputRevision = 7 }; // Used by moc, qmetaobjectbuilder and qdbus
+ // revision 8 is Qt 5.12: It adds the enum name to QMetaEnum
+ enum { OutputRevision = 8 }; // Used by moc, qmetaobjectbuilder and qdbus
int revision;
int className;
diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp
index e3b70638c6..d2030f0275 100644
--- a/src/corelib/kernel/qmetaobjectbuilder.cpp
+++ b/src/corelib/kernel/qmetaobjectbuilder.cpp
@@ -190,11 +190,12 @@ class QMetaEnumBuilderPrivate
{
public:
QMetaEnumBuilderPrivate(const QByteArray& _name)
- : name(_name), isFlag(false), isScoped(false)
+ : name(_name), enumName(_name), isFlag(false), isScoped(false)
{
}
QByteArray name;
+ QByteArray enumName;
bool isFlag;
bool isScoped;
QList<QByteArray> keys;
@@ -637,6 +638,7 @@ QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QByteArray& name)
QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QMetaEnum& prototype)
{
QMetaEnumBuilder en = addEnumerator(prototype.name());
+ en.setEnumName(prototype.enumName());
en.setIsFlag(prototype.isFlag());
en.setIsScoped(prototype.isScoped());
int count = prototype.keyCount();
@@ -1216,7 +1218,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
- int(d->methods.size()) // return "parameters" don't have names
- int(d->constructors.size()); // "this" parameters don't have names
if (buf) {
- Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 7, "QMetaObjectBuilder should generate the same version as moc");
+ Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 8, "QMetaObjectBuilder should generate the same version as moc");
pmeta->revision = QMetaObjectPrivate::OutputRevision;
pmeta->flags = d->flags;
pmeta->className = 0; // Class name is always the first string.
@@ -1244,7 +1246,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
pmeta->enumeratorCount = int(d->enumerators.size());
pmeta->enumeratorData = dataIndex;
- dataIndex += 4 * int(d->enumerators.size());
+ dataIndex += 5 * int(d->enumerators.size());
pmeta->constructorCount = int(d->constructors.size());
pmeta->constructorData = dataIndex;
@@ -1261,7 +1263,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
dataIndex += int(d->properties.size());
if (hasRevisionedProperties)
dataIndex += int(d->properties.size());
- dataIndex += 4 * int(d->enumerators.size());
+ dataIndex += 5 * int(d->enumerators.size());
dataIndex += 5 * int(d->constructors.size());
}
@@ -1410,15 +1412,17 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
Q_ASSERT(!buf || dataIndex == pmeta->enumeratorData);
for (const auto &enumerator : d->enumerators) {
int name = strings.enter(enumerator.name);
+ int enumName = strings.enter(enumerator.enumName);
int isFlag = enumerator.isFlag ? EnumIsFlag : 0;
int isScoped = enumerator.isScoped ? EnumIsScoped : 0;
int count = enumerator.keys.size();
int enumOffset = enumIndex;
if (buf) {
data[dataIndex] = name;
- data[dataIndex + 1] = isFlag | isScoped;
- data[dataIndex + 2] = count;
- data[dataIndex + 3] = enumOffset;
+ data[dataIndex + 1] = enumName;
+ data[dataIndex + 2] = isFlag | isScoped;
+ data[dataIndex + 3] = count;
+ data[dataIndex + 4] = enumOffset;
}
for (int key = 0; key < count; ++key) {
int keyIndex = strings.enter(enumerator.keys[key]);
@@ -1427,7 +1431,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
data[enumOffset++] = enumerator.values[key];
}
}
- dataIndex += 4;
+ dataIndex += 5;
enumIndex += 2 * count;
}
@@ -2599,7 +2603,7 @@ QMetaEnumBuilderPrivate *QMetaEnumBuilder::d_func() const
*/
/*!
- Returns the name of the enumerator (without the scope).
+ Returns the type name of the enumerator (without the scope).
*/
QByteArray QMetaEnumBuilder::name() const
{
@@ -2611,6 +2615,33 @@ QByteArray QMetaEnumBuilder::name() const
}
/*!
+ Returns the enum name of the enumerator (without the scope).
+
+ \since 5.12
+*/
+QByteArray QMetaEnumBuilder::enumName() const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ return d->enumName;
+ else
+ return QByteArray();
+}
+
+/*!
+ Sets this enumerator to have the enum name \c alias.
+
+ \since 5.12
+ \sa isFlag(), enumName()
+*/
+void QMetaEnumBuilder::setEnumName(const QByteArray &alias)
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ d->enumName = alias;
+}
+
+/*!
Returns \c true if this enumerator is used as a flag; otherwise returns
false.
diff --git a/src/corelib/kernel/qmetaobjectbuilder_p.h b/src/corelib/kernel/qmetaobjectbuilder_p.h
index 03b2afaebc..115ec835aa 100644
--- a/src/corelib/kernel/qmetaobjectbuilder_p.h
+++ b/src/corelib/kernel/qmetaobjectbuilder_p.h
@@ -93,8 +93,11 @@ public:
};
Q_DECLARE_FLAGS(AddMembers, AddMember)
- enum MetaObjectFlag {
- DynamicMetaObject = 0x01
+ // ### TODO Qt6: remove me and use the MetaObjectFlags enum from qmetaobject_p.h
+ enum MetaObjectFlag { // keep it in sync with enum MetaObjectFlags from qmetaobject_p.h
+ DynamicMetaObject = 0x01,
+ RequiresVariantMetaObject = 0x02,
+ PropertyAccessInStaticMetaCall = 0x04 // since Qt 5.5, property code is in the static metacall
};
Q_DECLARE_FLAGS(MetaObjectFlags, MetaObjectFlag)
@@ -297,6 +300,9 @@ public:
QByteArray name() const;
+ QByteArray enumName() const;
+ void setEnumName(const QByteArray &alias);
+
bool isFlag() const;
void setIsFlag(bool value);
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index fc40668c9a..eb67544f21 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -65,6 +65,9 @@
# include "qjsonobject.h"
# include "qjsonarray.h"
# include "qjsondocument.h"
+# include "qcborvalue.h"
+# include "qcborarray.h"
+# include "qcbormap.h"
# include "qbytearraylist.h"
#endif
@@ -316,7 +319,7 @@ struct DefinedTypesFilter {
\omitvalue WeakPointerToQObject
\omitvalue TrackingPointerToQObject
\omitvalue WasDeclaredAsMetaType
- \omitvalue IsGadget This type is a Q_GADGET and it's corresponding QMetaObject can be accessed with QMetaType::metaObject Since 5.5.
+ \omitvalue IsGadget \omit This type is a Q_GADGET and it's corresponding QMetaObject can be accessed with QMetaType::metaObject Since 5.5. \endomit
\omitvalue PointerToGadget
*/
@@ -835,15 +838,14 @@ void QMetaType::registerStreamOperators(int idx, SaveOperator saveOp,
}
#endif // QT_NO_DATASTREAM
-#if defined(Q_COMPILER_CONSTEXPR) || (defined(Q_CC_MSVC) && Q_CC_MSVC >= 1900)
// We don't officially support constexpr in MSVC 2015, but the limited support it
// has is enough for the code below.
-# define STRINGIFY_TYPE_NAME(MetaTypeName, TypeId, RealName) \
+#define STRINGIFY_TYPE_NAME(MetaTypeName, TypeId, RealName) \
#RealName "\0"
-# define CALCULATE_TYPE_LEN(MetaTypeName, TypeId, RealName) \
+#define CALCULATE_TYPE_LEN(MetaTypeName, TypeId, RealName) \
short(sizeof(#RealName)),
-# define MAP_TYPE_ID_TO_IDX(MetaTypeName, TypeId, RealName) \
+#define MAP_TYPE_ID_TO_IDX(MetaTypeName, TypeId, RealName) \
TypeId,
namespace {
@@ -911,10 +913,9 @@ template <int... TypeIds> struct MetaTypeOffsets<QtPrivate::IndexesList<TypeIds.
} // anonymous namespace
constexpr MetaTypeOffsets<QtPrivate::Indexes<QMetaType::HighestInternalId + 1>::Value> metaTypeNames {};
-# undef STRINGIFY_TYPE_NAME
-# undef CALCULATE_TYPE_LEN
-# undef MAP_TYPE_ID_TO_IDX
-#endif
+#undef STRINGIFY_TYPE_NAME
+#undef CALCULATE_TYPE_LEN
+#undef MAP_TYPE_ID_TO_IDX
/*!
Returns the type name associated with the given \a typeId, or a null
@@ -926,20 +927,8 @@ constexpr MetaTypeOffsets<QtPrivate::Indexes<QMetaType::HighestInternalId + 1>::
const char *QMetaType::typeName(int typeId)
{
const uint type = typeId;
-#define QT_METATYPE_TYPEID_TYPENAME_CONVERTER(MetaTypeName, TypeId, RealName) \
- case QMetaType::MetaTypeName: return #RealName; break;
-
if (Q_LIKELY(type <= QMetaType::HighestInternalId)) {
-#if defined(Q_COMPILER_CONSTEXPR) || (defined(Q_CC_MSVC) && Q_CC_MSVC >= 1900)
return metaTypeNames[typeId];
-#else
- switch (QMetaType::Type(type)) {
- QT_FOR_EACH_STATIC_TYPE(QT_METATYPE_TYPEID_TYPENAME_CONVERTER)
- case QMetaType::UnknownType:
- case QMetaType::User:
- break;
- }
-#endif
} else if (Q_UNLIKELY(type < QMetaType::User)) {
return nullptr; // It can happen when someone cast int to QVariant::Type, we should not crash...
}
@@ -1065,45 +1054,40 @@ int QMetaType::registerType(const char *typeName, Deleter deleter,
return registerNormalizedType(normalizedTypeName, deleter, creator, destructor, constructor, size, flags, metaObject);
}
-
/*!
- \internal
- \since 5.0
- \overload
- Don't use, kept for binary compatibility
+ \internal
+ \since 5.12
- ### TODO Qt6: remove me
-*/
-int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName, Deleter deleter,
- Creator creator,
- Destructor destructor,
- Constructor constructor,
- int size, TypeFlags flags, const QMetaObject *metaObject)
+ Registers a user type for marshalling, with \a typeName, a
+ \a destructor, a \a constructor, and a \a size. Returns the
+ type's handle, or -1 if the type could not be registered.
+ */
+int QMetaType::registerType(const char *typeName,
+ TypedDestructor destructor,
+ TypedConstructor constructor,
+ int size,
+ TypeFlags flags,
+ const QMetaObject *metaObject)
{
- Q_UNUSED(deleter);
- Q_UNUSED(creator);
+#ifdef QT_NO_QOBJECT
+ NS(QByteArray) normalizedTypeName = typeName;
+#else
+ NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
+#endif
+
return registerNormalizedType(normalizedTypeName, destructor, constructor, size, flags, metaObject);
}
-/*!
- \internal
- \since 5.5
-
- Registers a user type for marshalling, with \a normalizedTypeName,
- a \a destructor, a \a constructor, and a \a size. Returns the type's
- handle, or -1 if the type could not be registered.
-
- \note normalizedTypeName is not checked for conformance with
- Qt's normalized format, so it must already conform.
- */
-int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
- Destructor destructor,
- Constructor constructor,
- int size, TypeFlags flags, const QMetaObject *metaObject)
+static int registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
+ QMetaType::Destructor destructor,
+ QMetaType::Constructor constructor,
+ QMetaType::TypedDestructor typedDestructor,
+ QMetaType::TypedConstructor typedConstructor,
+ int size, QMetaType::TypeFlags flags, const QMetaObject *metaObject)
{
QVector<QCustomTypeInfo> *ct = customTypes();
- if (!ct || normalizedTypeName.isEmpty() || !destructor || !constructor)
+ if (!ct || normalizedTypeName.isEmpty() || (!destructor && !typedDestructor) || (!constructor && !typedConstructor))
return -1;
int idx = qMetaTypeStaticType(normalizedTypeName.constData(),
@@ -1111,13 +1095,13 @@ int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
int previousSize = 0;
QMetaType::TypeFlags::Int previousFlags = 0;
- if (idx == UnknownType) {
+ if (idx == QMetaType::UnknownType) {
QWriteLocker locker(customTypesLock());
int posInVector = -1;
idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
normalizedTypeName.size(),
&posInVector);
- if (idx == UnknownType) {
+ if (idx == QMetaType::UnknownType) {
QCustomTypeInfo inf;
inf.typeName = normalizedTypeName;
#ifndef QT_NO_DATASTREAM
@@ -1125,30 +1109,32 @@ int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
inf.saveOp = 0;
#endif
inf.alias = -1;
+ inf.typedConstructor = typedConstructor;
+ inf.typedDestructor = typedDestructor;
inf.constructor = constructor;
inf.destructor = destructor;
inf.size = size;
inf.flags = flags;
inf.metaObject = metaObject;
if (posInVector == -1) {
- idx = ct->size() + User;
+ idx = ct->size() + QMetaType::User;
ct->append(inf);
} else {
- idx = posInVector + User;
+ idx = posInVector + QMetaType::User;
ct->data()[posInVector] = inf;
}
return idx;
}
- if (idx >= User) {
- previousSize = ct->at(idx - User).size;
- previousFlags = ct->at(idx - User).flags;
+ if (idx >= QMetaType::User) {
+ previousSize = ct->at(idx - QMetaType::User).size;
+ previousFlags = ct->at(idx - QMetaType::User).flags;
// Set new/additional flags in case of old library/app.
// Ensures that older code works in conjunction with new Qt releases
// requiring the new flags.
if (flags != previousFlags) {
- QCustomTypeInfo &inf = ct->data()[idx - User];
+ QCustomTypeInfo &inf = ct->data()[idx - QMetaType::User];
inf.flags |= flags;
if (metaObject)
inf.metaObject = metaObject;
@@ -1156,7 +1142,7 @@ int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
}
}
- if (idx < User) {
+ if (idx < QMetaType::User) {
previousSize = QMetaType::sizeOf(idx);
previousFlags = QMetaType::typeFlags(idx);
}
@@ -1169,8 +1155,8 @@ int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
}
// these flags cannot change in a binary compatible way:
- const int binaryCompatibilityFlag = PointerToQObject | IsEnumeration | SharedPointerToQObject
- | WeakPointerToQObject | TrackingPointerToQObject;
+ const int binaryCompatibilityFlag = QMetaType::PointerToQObject | QMetaType::IsEnumeration | QMetaType::SharedPointerToQObject
+ | QMetaType::WeakPointerToQObject | QMetaType::TrackingPointerToQObject;
if (Q_UNLIKELY((previousFlags ^ flags) & binaryCompatibilityFlag)) {
const char *msg = "QMetaType::registerType: Binary compatibility break. "
@@ -1184,6 +1170,66 @@ int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
}
/*!
+ \internal
+ \since 5.0
+ \overload
+ Don't use, kept for binary compatibility
+
+ ### TODO Qt6: remove me
+*/
+int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName, Deleter deleter,
+ Creator creator,
+ Destructor destructor,
+ Constructor constructor,
+ int size, TypeFlags flags, const QMetaObject *metaObject)
+{
+ Q_UNUSED(deleter);
+ Q_UNUSED(creator);
+ return registerNormalizedType(normalizedTypeName, destructor, constructor, size, flags, metaObject);
+}
+
+
+/*!
+ \internal
+ \since 5.5
+
+ Registers a user type for marshalling, with \a normalizedTypeName,
+ a \a destructor, a \a constructor, and a \a size. Returns the type's
+ handle, or -1 if the type could not be registered.
+
+ \note normalizedTypeName is not checked for conformance with
+ Qt's normalized format, so it must already conform.
+
+ ### TODO Qt6: remove me
+ */
+int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
+ Destructor destructor,
+ Constructor constructor,
+ int size, TypeFlags flags, const QMetaObject *metaObject)
+{
+ return NS(registerNormalizedType)(normalizedTypeName, destructor, constructor, nullptr, nullptr, size, flags, metaObject);
+}
+
+/*!
+ \internal
+ \since 5.12
+
+ Registers a user type for marshalling, with \a normalizedTypeName,
+ a \a destructor, a \a constructor, and a \a size. Returns the type's
+ handle, or -1 if the type could not be registered.
+
+ \note normalizedTypeName is not checked for conformance with
+ Qt's normalized format, so it must already conform.
+ */
+int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
+ TypedDestructor destructor,
+ TypedConstructor constructor,
+ int size, TypeFlags flags, const QMetaObject *metaObject)
+{
+ return NS(registerNormalizedType)(normalizedTypeName, nullptr, nullptr, destructor, constructor, size, flags, metaObject);
+}
+
+/*!
\internal
\since 4.7
@@ -1360,6 +1406,9 @@ bool QMetaType::save(QDataStream &stream, int type, const void *data)
case QMetaType::QJsonObject:
case QMetaType::QJsonArray:
case QMetaType::QJsonDocument:
+ case QMetaType::QCborValue:
+ case QMetaType::QCborArray:
+ case QMetaType::QCborMap:
return false;
case QMetaType::Nullptr:
stream << *static_cast<const std::nullptr_t *>(data);
@@ -1498,6 +1547,9 @@ bool QMetaType::save(QDataStream &stream, int type, const void *data)
case QMetaType::QEasingCurve:
stream << *static_cast<const NS(QEasingCurve)*>(data);
break;
+ case QMetaType::QCborSimpleType:
+ stream << *static_cast<const quint8 *>(data);
+ break;
#endif // QT_BOOTSTRAPPED
case QMetaType::QFont:
case QMetaType::QPixmap:
@@ -1586,6 +1638,9 @@ bool QMetaType::load(QDataStream &stream, int type, void *data)
case QMetaType::QJsonObject:
case QMetaType::QJsonArray:
case QMetaType::QJsonDocument:
+ case QMetaType::QCborValue:
+ case QMetaType::QCborArray:
+ case QMetaType::QCborMap:
return false;
case QMetaType::Nullptr:
stream >> *static_cast<std::nullptr_t *>(data);
@@ -1730,6 +1785,9 @@ bool QMetaType::load(QDataStream &stream, int type, void *data)
case QMetaType::QEasingCurve:
stream >> *static_cast< NS(QEasingCurve)*>(data);
break;
+ case QMetaType::QCborSimpleType:
+ stream >> *static_cast<quint8 *>(data);
+ break;
#endif // QT_BOOTSTRAPPED
case QMetaType::QFont:
case QMetaType::QPixmap:
@@ -1849,14 +1907,19 @@ private:
static void *customTypeConstructor(const int type, void *where, const void *copy)
{
QMetaType::Constructor ctor;
+ QMetaType::TypedConstructor tctor;
const QVector<QCustomTypeInfo> * const ct = customTypes();
{
QReadLocker locker(customTypesLock());
if (Q_UNLIKELY(type < QMetaType::User || !ct || ct->count() <= type - QMetaType::User))
return 0;
- ctor = ct->at(type - QMetaType::User).constructor;
+ const auto &typeInfo = ct->at(type - QMetaType::User);
+ ctor = typeInfo.constructor;
+ tctor = typeInfo.typedConstructor;
}
- Q_ASSERT_X(ctor, "void *QMetaType::construct(int type, void *where, const void *copy)", "The type was not properly registered");
+ Q_ASSERT_X((ctor || tctor) , "void *QMetaType::construct(int type, void *where, const void *copy)", "The type was not properly registered");
+ if (Q_UNLIKELY(tctor))
+ return tctor(type, where, copy);
return ctor(where, copy);
}
@@ -1942,14 +2005,19 @@ private:
static void customTypeDestructor(const int type, void *where)
{
QMetaType::Destructor dtor;
+ QMetaType::TypedDestructor tdtor;
const QVector<QCustomTypeInfo> * const ct = customTypes();
{
QReadLocker locker(customTypesLock());
if (Q_UNLIKELY(type < QMetaType::User || !ct || ct->count() <= type - QMetaType::User))
return;
- dtor = ct->at(type - QMetaType::User).destructor;
+ const auto &typeInfo = ct->at(type - QMetaType::User);
+ dtor = typeInfo.destructor;
+ tdtor = typeInfo.typedDestructor;
}
- Q_ASSERT_X(dtor, "void QMetaType::destruct(int type, void *where)", "The type was not properly registered");
+ Q_ASSERT_X((dtor || tdtor), "void QMetaType::destruct(int type, void *where)", "The type was not properly registered");
+ if (Q_UNLIKELY(tdtor))
+ return tdtor(type, where);
dtor(where);
}
@@ -2362,10 +2430,12 @@ QMetaType QMetaType::typeInfo(const int type)
{
TypeInfo typeInfo(type);
QMetaTypeSwitcher::switcher<void>(typeInfo, type, 0);
- return typeInfo.info.constructor ? QMetaType(static_cast<ExtensionFlag>(QMetaType::CreateEx | QMetaType::DestroyEx)
- , static_cast<const QMetaTypeInterface *>(0) // typeInfo::info is a temporary variable, we can't return address of it.
- , 0 // unused
- , 0 // unused
+ return (typeInfo.info.constructor || typeInfo.info.typedConstructor)
+ ? QMetaType(static_cast<ExtensionFlag>(QMetaType::CreateEx | QMetaType::DestroyEx |
+ (typeInfo.info.typedConstructor ? QMetaType::ConstructEx | QMetaType::DestructEx : 0))
+ , static_cast<const QMetaTypeInterface *>(nullptr) // typeInfo::info is a temporary variable, we can't return address of it.
+ , typeInfo.info.typedConstructor
+ , typeInfo.info.typedDestructor
, typeInfo.info.saveOp
, typeInfo.info.loadOp
, typeInfo.info.constructor
@@ -2407,8 +2477,8 @@ QMetaType::QMetaType(const int typeId)
Copy constructs a QMetaType object.
*/
QMetaType::QMetaType(const QMetaType &other)
- : m_creator_unused(other.m_creator_unused)
- , m_deleter_unused(other.m_deleter_unused)
+ : m_typedConstructor(other.m_typedConstructor)
+ , m_typedDestructor(other.m_typedDestructor)
, m_saveOp(other.m_saveOp)
, m_loadOp(other.m_loadOp)
, m_constructor(other.m_constructor)
@@ -2423,8 +2493,8 @@ QMetaType::QMetaType(const QMetaType &other)
QMetaType &QMetaType::operator =(const QMetaType &other)
{
- m_creator_unused = other.m_creator_unused;
- m_deleter_unused = other.m_deleter_unused;
+ m_typedConstructor = other.m_typedConstructor;
+ m_typedDestructor = other.m_typedDestructor;
m_saveOp = other.m_saveOp;
m_loadOp = other.m_loadOp;
m_constructor = other.m_constructor;
@@ -2480,6 +2550,8 @@ void *QMetaType::createExtended(const void *copy) const
{
if (m_typeId == QMetaType::UnknownType)
return 0;
+ if (Q_UNLIKELY(m_typedConstructor && !m_constructor))
+ return m_typedConstructor(m_typeId, operator new(m_size), copy);
return m_constructor(operator new(m_size), copy);
}
@@ -2494,7 +2566,10 @@ void *QMetaType::createExtended(const void *copy) const
*/
void QMetaType::destroyExtended(void *data) const
{
- m_destructor(data);
+ if (Q_UNLIKELY(m_typedDestructor && !m_destructor))
+ m_typedDestructor(m_typeId, data);
+ else
+ m_destructor(data);
operator delete(data);
}
@@ -2507,9 +2582,9 @@ void QMetaType::destroyExtended(void *data) const
*/
void *QMetaType::constructExtended(void *where, const void *copy) const
{
- Q_UNUSED(where);
- Q_UNUSED(copy);
- return 0;
+ if (m_typedConstructor && !m_constructor)
+ return m_typedConstructor(m_typeId, where, copy);
+ return nullptr;
}
/*!
@@ -2521,7 +2596,8 @@ void *QMetaType::constructExtended(void *where, const void *copy) const
*/
void QMetaType::destructExtended(void *data) const
{
- Q_UNUSED(data);
+ if (m_typedDestructor && !m_destructor)
+ m_typedDestructor(m_typeId, data);
}
/*!
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index cf68752f85..ed7feee775 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
** Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com>
** Contact: https://www.qt.io/licensing/
**
@@ -60,6 +61,9 @@
QT_BEGIN_NAMESPACE
+// from qcborcommon.h
+enum class QCborSimpleType : quint8;
+
template <typename T>
struct QMetaTypeId2;
@@ -85,6 +89,7 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(Float, 38, float) \
F(SChar, 40, signed char) \
F(Nullptr, 51, std::nullptr_t) \
+ F(QCborSimpleType, 52, QCborSimpleType) \
#define QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(F)\
F(VoidStar, 31, void*) \
@@ -125,6 +130,9 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(QJsonObject, 46, QJsonObject) \
F(QJsonArray, 47, QJsonArray) \
F(QJsonDocument, 48, QJsonDocument) \
+ F(QCborValue, 53, QCborValue) \
+ F(QCborArray, 54, QCborArray) \
+ F(QCborMap, 55, QCborMap) \
QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)
#define QT_FOR_EACH_STATIC_CORE_POINTER(F)\
@@ -420,7 +428,7 @@ public:
QT_FOR_EACH_STATIC_TYPE(QT_DEFINE_METATYPE_ID)
FirstCoreType = Bool,
- LastCoreType = Nullptr,
+ LastCoreType = QCborMap,
FirstGuiType = QFont,
LastGuiType = QPolygonF,
FirstWidgetsType = QSizePolicy,
@@ -450,13 +458,18 @@ public:
Void = 43,
Nullptr = 51,
QVariantMap = 8, QVariantList = 9, QVariantHash = 28,
+ QCborSimpleType = 52, QCborValue = 53, QCborArray = 54, QCborMap = 55,
+
+ // Gui types
QFont = 64, QPixmap = 65, QBrush = 66, QColor = 67, QPalette = 68,
QIcon = 69, QImage = 70, QPolygon = 71, QRegion = 72, QBitmap = 73,
QCursor = 74, QKeySequence = 75, QPen = 76, QTextLength = 77, QTextFormat = 78,
QMatrix = 79, QTransform = 80, QMatrix4x4 = 81, QVector2D = 82,
QVector3D = 83, QVector4D = 84, QQuaternion = 85, QPolygonF = 86,
+
+ // Widget types
QSizePolicy = 121,
- LastCoreType = Nullptr,
+ LastCoreType = QCborMap,
LastGuiType = QPolygonF,
User = 1024
};
@@ -480,8 +493,12 @@ public:
typedef void (*Deleter)(void *);
typedef void *(*Creator)(const void *);
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
typedef void (*Destructor)(void *);
- typedef void *(*Constructor)(void *, const void *);
+ typedef void *(*Constructor)(void *, const void *); // TODO Qt6: remove me
+#endif
+ typedef void (*TypedDestructor)(int, void *);
+ typedef void *(*TypedConstructor)(int, void *, const void *);
typedef void (*SaveOperator)(QDataStream &, const void *);
typedef void (*LoadOperator)(QDataStream &, void *);
@@ -500,6 +517,12 @@ public:
int size,
QMetaType::TypeFlags flags,
const QMetaObject *metaObject);
+ static int registerType(const char *typeName,
+ TypedDestructor destructor,
+ TypedConstructor constructor,
+ int size,
+ QMetaType::TypeFlags flags,
+ const QMetaObject *metaObject);
static bool unregisterType(int type);
static int registerNormalizedType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, Deleter deleter,
Creator creator,
@@ -513,6 +536,11 @@ public:
int size,
QMetaType::TypeFlags flags,
const QMetaObject *metaObject);
+ static int registerNormalizedType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, TypedDestructor destructor,
+ TypedConstructor constructor,
+ int size,
+ QMetaType::TypeFlags flags,
+ const QMetaObject *metaObject);
static int registerTypedef(const char *typeName, int aliasId);
static int registerNormalizedTypedef(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, int aliasId);
static int type(const char *typeName);
@@ -670,8 +698,8 @@ public:
private:
static QMetaType typeInfo(const int type);
inline QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeInterface *info,
- Creator creator,
- Deleter deleter,
+ TypedConstructor creator,
+ TypedDestructor deleter,
SaveOperator saveOp,
LoadOperator loadOp,
Constructor constructor,
@@ -718,8 +746,8 @@ public:
static void unregisterConverterFunction(int from, int to);
private:
- Creator m_creator_unused;
- Deleter m_deleter_unused;
+ TypedConstructor m_typedConstructor;
+ TypedDestructor m_typedDestructor;
SaveOperator m_saveOp;
LoadOperator m_loadOp;
Constructor m_constructor;
@@ -2150,8 +2178,8 @@ QT_BEGIN_NAMESPACE
#undef Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER
inline QMetaType::QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeInterface *info,
- Creator creator,
- Deleter deleter,
+ TypedConstructor creator,
+ TypedDestructor deleter,
SaveOperator saveOp,
LoadOperator loadOp,
Constructor constructor,
@@ -2160,8 +2188,8 @@ inline QMetaType::QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeI
uint theTypeFlags,
int typeId,
const QMetaObject *_metaObject)
- : m_creator_unused(creator)
- , m_deleter_unused(deleter)
+ : m_typedConstructor(creator)
+ , m_typedDestructor(deleter)
, m_saveOp(saveOp)
, m_loadOp(loadOp)
, m_constructor(constructor)
diff --git a/src/corelib/kernel/qmetatype_p.h b/src/corelib/kernel/qmetatype_p.h
index cef20a5d12..94e9228778 100644
--- a/src/corelib/kernel/qmetatype_p.h
+++ b/src/corelib/kernel/qmetatype_p.h
@@ -126,11 +126,13 @@ class QMetaTypeInterface
public:
QMetaType::SaveOperator saveOp;
QMetaType::LoadOperator loadOp;
- QMetaType::Constructor constructor;
+ QMetaType::Constructor constructor; // TODO Qt6: remove me
QMetaType::Destructor destructor;
int size;
QMetaType::TypeFlags::Int flags;
const QMetaObject *metaObject;
+ QMetaType::TypedConstructor typedConstructor;
+ QMetaType::TypedDestructor typedDestructor;
};
#ifndef QT_NO_DATASTREAM
@@ -161,7 +163,9 @@ public:
/*destructor*/(QtMetaTypePrivate::QMetaTypeFunctionHelper<Type, QtMetaTypePrivate::TypeDefinition<Type>::IsAvailable>::Destruct), \
/*size*/(QTypeInfo<Type>::sizeOf), \
/*flags*/QtPrivate::QMetaTypeTypeFlags<Type>::Flags, \
- /*metaObject*/METAOBJECT_DELEGATE(Type) \
+ /*metaObject*/METAOBJECT_DELEGATE(Type), \
+ /*typedConstructor*/ nullptr, \
+ /*typedDestructor*/ nullptr \
}
@@ -184,7 +188,9 @@ public:
/*destructor*/ 0, \
/*size*/ 0, \
/*flags*/ 0, \
- /*metaObject*/ 0 \
+ /*metaObject*/ 0 , \
+ /*typedConstructor*/ nullptr, \
+ /*typedDestructor*/ nullptr \
}
namespace QtMetaTypePrivate {
@@ -196,6 +202,10 @@ struct TypeDefinition {
// Ignore these types, as incomplete
#ifdef QT_BOOTSTRAPPED
template<> struct TypeDefinition<QBitArray> { static const bool IsAvailable = false; };
+template<> struct TypeDefinition<QCborArray> { static const bool IsAvailable = false; };
+template<> struct TypeDefinition<QCborMap> { static const bool IsAvailable = false; };
+template<> struct TypeDefinition<QCborSimpleType> { static const bool IsAvailable = false; };
+template<> struct TypeDefinition<QCborValue> { static const bool IsAvailable = false; };
template<> struct TypeDefinition<QEasingCurve> { static const bool IsAvailable = false; };
template<> struct TypeDefinition<QJsonArray> { static const bool IsAvailable = false; };
template<> struct TypeDefinition<QJsonDocument> { static const bool IsAvailable = false; };
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index c6fe787e03..07208b7f40 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -59,11 +59,14 @@
#include <qpair.h>
#include <qvarlengtharray.h>
#include <qset.h>
+#if QT_CONFIG(thread)
#include <qsemaphore.h>
+#endif
#include <qsharedpointer.h>
#include <private/qorderedmutexlocker_p.h>
#include <private/qhooks_p.h>
+#include <qtcore_tracepoints_p.h>
#include <new>
@@ -487,7 +490,7 @@ QMetaCallEvent::~QMetaCallEvent()
free(types_);
free(args_);
}
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
if (semaphore_)
semaphore_->release();
#endif
@@ -523,18 +526,9 @@ void QMetaCallEvent::placeMetaCall(QObject *object)
constructor and in the destructor it resets the state to what
it was before the constructor ran.
- \code
- {
- const QSignalBlocker blocker(someQObject);
- // no signals here
- }
- \endcode
+ \snippet code/src_corelib_kernel_qobject.cpp 53
is thus equivalent to
- \code
- const bool wasBlocked = someQObject->blockSignals(true);
- // no signals here
- someQObject->blockSignals(wasBlocked);
- \endcode
+ \snippet code/src_corelib_kernel_qobject.cpp 54
except the code using QSignalBlocker is safe in the face of
exceptions.
@@ -820,6 +814,7 @@ QObject::QObject(QObject *parent)
#endif
if (Q_UNLIKELY(qtHookData[QHooks::AddQObject]))
reinterpret_cast<QHooks::AddQObjectCallback>(qtHookData[QHooks::AddQObject])(this);
+ Q_TRACE(QObject_ctor, this);
}
/*!
@@ -855,6 +850,7 @@ QObject::QObject(QObjectPrivate &dd, QObject *parent)
#endif
if (Q_UNLIKELY(qtHookData[QHooks::AddQObject]))
reinterpret_cast<QHooks::AddQObjectCallback>(qtHookData[QHooks::AddQObject])(this);
+ Q_TRACE(QObject_ctor, this);
}
/*!
@@ -1030,6 +1026,8 @@ QObject::~QObject()
if (Q_UNLIKELY(qtHookData[QHooks::RemoveQObject]))
reinterpret_cast<QHooks::RemoveQObjectCallback>(qtHookData[QHooks::RemoveQObject])(this);
+ Q_TRACE(QObject_dtor, this);
+
if (d->parent) // remove it from parent object
d->setParent_helper(0);
}
@@ -3645,13 +3643,17 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i
if (sender->d_func()->isDeclarativeSignalConnected(signal_index)
&& QAbstractDeclarativeData::signalEmitted) {
+ Q_TRACE(QMetaObject_activate_begin_declarative_signal, sender, signal_index);
QAbstractDeclarativeData::signalEmitted(sender->d_func()->declarativeData, sender,
signal_index, argv);
+ Q_TRACE(QMetaObject_activate_end_declarative_signal, sender, signal_index);
}
if (!sender->d_func()->isSignalConnected(signal_index, /*checkDeclarative =*/ false)
&& !qt_signal_spy_callback_set.signal_begin_callback
- && !qt_signal_spy_callback_set.signal_end_callback) {
+ && !qt_signal_spy_callback_set.signal_end_callback
+ && !Q_TRACE_ENABLED(QMetaObject_activate_begin_signal)
+ && !Q_TRACE_ENABLED(QMetaObject_activate_end_signal)) {
// The possible declarative connection is done, and nothing else is connected, so:
return;
}
@@ -3661,6 +3663,7 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i
qt_signal_spy_callback_set.signal_begin_callback(sender, signal_index,
argv ? argv : empty_argv);
}
+ Q_TRACE(QMetaObject_activate_begin_signal, sender, signal_index);
{
QMutexLocker locker(signalSlotLock(sender));
@@ -3691,6 +3694,7 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i
locker.unlock();
if (qt_signal_spy_callback_set.signal_end_callback != 0)
qt_signal_spy_callback_set.signal_end_callback(sender, signal_index);
+ Q_TRACE(QMetaObject_activate_end_signal, sender, signal_index);
return;
}
@@ -3722,7 +3726,7 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i
|| (c->connectionType == Qt::QueuedConnection)) {
queued_activate(sender, signal_index, c, argv ? argv : empty_argv, locker);
continue;
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
} else if (c->connectionType == Qt::BlockingQueuedConnection) {
if (receiverInSameThread) {
qWarning("Qt: Dead lock detected while activating a BlockingQueuedConnection: "
@@ -3751,7 +3755,9 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i
c->slotObj->ref();
QScopedPointer<QtPrivate::QSlotObjectBase, QSlotObjectBaseDeleter> obj(c->slotObj);
locker.unlock();
+ Q_TRACE(QMetaObject_activate_begin_slot_functor, obj.data());
obj->call(receiver, argv ? argv : empty_argv);
+ Q_TRACE(QMetaObject_activate_end_slot_functor, obj.data());
// Make sure the slot object gets destroyed before the mutex is locked again, as the
// destructor of the slot object might also lock a mutex from the signalSlotLock() mutex pool,
@@ -3767,9 +3773,11 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i
locker.unlock();
if (qt_signal_spy_callback_set.slot_begin_callback != 0)
qt_signal_spy_callback_set.slot_begin_callback(receiver, methodIndex, argv ? argv : empty_argv);
+ Q_TRACE(QMetaObject_activate_begin_slot, receiver, methodIndex);
callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv ? argv : empty_argv);
+ Q_TRACE(QMetaObject_activate_end_slot, receiver, methodIndex);
if (qt_signal_spy_callback_set.slot_end_callback != 0)
qt_signal_spy_callback_set.slot_end_callback(receiver, methodIndex);
locker.relock();
@@ -3782,9 +3790,11 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i
method,
argv ? argv : empty_argv);
}
+ Q_TRACE(QMetaObject_activate_begin_slot, receiver, method);
metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
+ Q_TRACE(QMetaObject_activate_end_slot, receiver, method);
if (qt_signal_spy_callback_set.slot_end_callback != 0)
qt_signal_spy_callback_set.slot_end_callback(receiver, method);
@@ -3805,7 +3815,7 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i
if (qt_signal_spy_callback_set.signal_end_callback != 0)
qt_signal_spy_callback_set.signal_end_callback(sender, signal_index);
-
+ Q_TRACE(QMetaObject_activate_end_signal, sender, signal_index);
}
/*!
@@ -4534,6 +4544,11 @@ QDebug operator<<(QDebug dbg, const QObject *o)
invoked using QMetaObject::invokeMethod().
Since \c normalMethod() function is not registered in this way, it cannot
be invoked using QMetaObject::invokeMethod().
+
+ If an invokable member function returns a pointer to a QObject or a
+ subclass of QObject and it is invoked from QML, special ownership rules
+ apply. See \l{qtqml-cppintegration-data.html}{Data Type Conversion Between QML and C++}
+ for more information.
*/
/*!
@@ -4681,7 +4696,7 @@ void qDeleteInEventHandler(QObject *o)
The signal must be a function declared as a signal in the header.
The slot function can be any function or functor that can be connected
to the signal.
- A function can be connected to a given signal if the signal as at
+ A function can be connected to a given signal if the signal has at
least as many argument as the slot. A functor can be connected to a signal
if they have exactly the same number of arguments. There must exist implicit
conversion between the types of the corresponding arguments in the
@@ -4721,7 +4736,7 @@ void qDeleteInEventHandler(QObject *o)
The signal must be a function declared as a signal in the header.
The slot function can be any function or functor that can be connected
to the signal.
- A function can be connected to a given signal if the signal as at
+ A function can be connected to a given signal if the signal has at
least as many argument as the slot. A functor can be connected to a signal
if they have exactly the same number of arguments. There must exist implicit
conversion between the types of the corresponding arguments in the
@@ -4804,7 +4819,12 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s
const int *types, const QMetaObject *senderMetaObject)
{
if (!sender || !receiver || !slotObj || !senderMetaObject) {
- qWarning("QObject::connect: invalid null parameter");
+ const char *senderString = sender ? sender->metaObject()->className()
+ : senderMetaObject ? senderMetaObject->className()
+ : "Unknown";
+ const char *receiverString = receiver ? receiver->metaObject()->className()
+ : "Unknown";
+ qWarning("QObject::connect(%s, %s): invalid null parameter", senderString, receiverString);
if (slotObj)
slotObj->destroyIfLastRef();
return QMetaObject::Connection();
diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h
index a6ad00ea22..8afff1fb98 100644
--- a/src/corelib/kernel/qobjectdefs_impl.h
+++ b/src/corelib/kernel/qobjectdefs_impl.h
@@ -112,13 +112,31 @@ namespace QtPrivate {
The Functor<Func,N> struct is the helper to call a functor of N argument.
its call function is the same as the FunctionPointer::call function.
*/
- template <int...> struct IndexesList {};
- template <typename IndexList, int Right> struct IndexesAppend;
- template <int... Left, int Right> struct IndexesAppend<IndexesList<Left...>, Right>
- { typedef IndexesList<Left..., Right> Value; };
- template <int N> struct Indexes
- { typedef typename IndexesAppend<typename Indexes<N - 1>::Value, N - 1>::Value Value; };
- template <> struct Indexes<0> { typedef IndexesList<> Value; };
+ template<class T> using InvokeGenSeq = typename T::Type;
+
+ template<int...> struct IndexesList { using Type = IndexesList; };
+
+ template<int N, class S1, class S2> struct ConcatSeqImpl;
+
+ template<int N, int... I1, int... I2>
+ struct ConcatSeqImpl<N, IndexesList<I1...>, IndexesList<I2...>>
+ : IndexesList<I1..., (N + I2)...>{};
+
+ template<int N, class S1, class S2>
+ using ConcatSeq = InvokeGenSeq<ConcatSeqImpl<N, S1, S2>>;
+
+ template<int N> struct GenSeq;
+ template<int N> using makeIndexSequence = InvokeGenSeq<GenSeq<N>>;
+
+ template<int N>
+ struct GenSeq : ConcatSeq<N/2, makeIndexSequence<N/2>, makeIndexSequence<N - N/2>>{};
+
+ template<> struct GenSeq<0> : IndexesList<>{};
+ template<> struct GenSeq<1> : IndexesList<0>{};
+
+ template<int N>
+ struct Indexes { using Value = makeIndexSequence<N>; };
+
template<typename Func> struct FunctionPointer { enum {ArgumentCount = -1, IsPointerToMemberFunction = false}; };
template <typename, typename, typename, typename> struct FunctorCall;
diff --git a/src/corelib/kernel/qsharedmemory_win.cpp b/src/corelib/kernel/qsharedmemory_win.cpp
index be42a369c2..c1dba30e2b 100644
--- a/src/corelib/kernel/qsharedmemory_win.cpp
+++ b/src/corelib/kernel/qsharedmemory_win.cpp
@@ -101,7 +101,8 @@ HANDLE QSharedMemoryPrivate::handle()
#if defined(Q_OS_WINRT)
hand = OpenFileMappingFromApp(FILE_MAP_ALL_ACCESS, FALSE, reinterpret_cast<PCWSTR>(nativeKey.utf16()));
#else
- hand = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, (wchar_t*)nativeKey.utf16());
+ hand = OpenFileMapping(FILE_MAP_ALL_ACCESS, false,
+ reinterpret_cast<const wchar_t*>(nativeKey.utf16()));
#endif
if (!hand) {
setErrorString(function);
@@ -133,17 +134,16 @@ bool QSharedMemoryPrivate::create(int size)
// Create the file mapping.
#if defined(Q_OS_WINRT)
- hand = CreateFileMappingFromApp(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, size, (PCWSTR)nativeKey.utf16());
+ hand = CreateFileMappingFromApp(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, size,
+ reinterpret_cast<PCWSTR>(nativeKey.utf16()));
#else
- hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, size, (wchar_t*)nativeKey.utf16());
+ hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, size,
+ reinterpret_cast<const wchar_t*>(nativeKey.utf16()));
#endif
setErrorString(function);
// hand is valid when it already exists unlike unix so explicitly check
- if (error == QSharedMemory::AlreadyExists || !hand)
- return false;
-
- return true;
+ return error != QSharedMemory::AlreadyExists && hand;
}
bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
diff --git a/src/corelib/kernel/qsystemerror.cpp b/src/corelib/kernel/qsystemerror.cpp
index fc825257ec..53c3136857 100644
--- a/src/corelib/kernel/qsystemerror.cpp
+++ b/src/corelib/kernel/qsystemerror.cpp
@@ -49,7 +49,7 @@
QT_BEGIN_NAMESPACE
-#if !defined(Q_OS_WIN) && !defined(QT_NO_THREAD) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) && \
+#if !defined(Q_OS_WIN) && QT_CONFIG(thread) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) && \
defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L
namespace {
// There are two incompatible versions of strerror_r:
@@ -130,7 +130,7 @@ static QString standardLibraryErrorString(int errorCode)
s = QT_TRANSLATE_NOOP("QIODevice", "No space left on device");
break;
default: {
- #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX)
+ #if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX)
QByteArray buf(1024, Qt::Uninitialized);
ret = fromstrerror_helper(strerror_r(errorCode, buf.data(), buf.size()), buf);
#else
diff --git a/src/corelib/kernel/qsystemsemaphore_win.cpp b/src/corelib/kernel/qsystemsemaphore_win.cpp
index 3395f5641e..2b35803291 100644
--- a/src/corelib/kernel/qsystemsemaphore_win.cpp
+++ b/src/corelib/kernel/qsystemsemaphore_win.cpp
@@ -86,9 +86,12 @@ HANDLE QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode)
// Create it if it doesn't already exists.
if (semaphore == 0) {
#if defined(Q_OS_WINRT)
- semaphore = CreateSemaphoreEx(0, initialValue, MAXLONG, (wchar_t*)fileName.utf16(), 0, SEMAPHORE_ALL_ACCESS);
+ semaphore = CreateSemaphoreEx(0, initialValue, MAXLONG,
+ reinterpret_cast<const wchar_t*>(fileName.utf16()),
+ 0, SEMAPHORE_ALL_ACCESS);
#else
- semaphore = CreateSemaphore(0, initialValue, MAXLONG, (wchar_t*)fileName.utf16());
+ semaphore = CreateSemaphore(0, initialValue, MAXLONG,
+ reinterpret_cast<const wchar_t*>(fileName.utf16()));
#endif
if (semaphore == NULL)
setErrorString(QLatin1String("QSystemSemaphore::handle"));
diff --git a/src/corelib/kernel/qtcore_eval.cpp b/src/corelib/kernel/qtcore_eval.cpp
index 86992ce10b..5437210699 100644
--- a/src/corelib/kernel/qtcore_eval.cpp
+++ b/src/corelib/kernel/qtcore_eval.cpp
@@ -168,7 +168,7 @@ public:
}
}
- void timerEvent(QTimerEvent *e) {
+ void timerEvent(QTimerEvent *e) override {
if (e->timerId() == warn) {
killTimer(warn);
fprintf(stderr, "%s\n", will_shutdown_1min);
diff --git a/src/corelib/kernel/qtestsupport_core.cpp b/src/corelib/kernel/qtestsupport_core.cpp
new file mode 100644
index 0000000000..d69551a227
--- /dev/null
+++ b/src/corelib/kernel/qtestsupport_core.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 "qtestsupport_core.h"
+
+#ifdef Q_OS_WIN
+#include <qt_windows.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+Q_CORE_EXPORT void QTestPrivate::qSleep(int ms)
+{
+ Q_ASSERT(ms > 0);
+
+#if defined(Q_OS_WINRT)
+ WaitForSingleObjectEx(GetCurrentThread(), ms, true);
+#elif defined(Q_OS_WIN)
+ Sleep(uint(ms));
+#else
+ struct timespec ts = { time_t(ms / 1000), (ms % 1000) * 1000 * 1000 };
+ nanosleep(&ts, NULL);
+#endif
+}
+
+/*! \fn template <typename Functor> bool qWaitFor(Functor predicate, int timeout)
+ \relates QTest
+
+ Waits for \a timeout milliseconds or until the \a predicate returns true.
+
+ Returns \c true if the \a predicate returned true at any point, otherwise returns \c false.
+
+ Example:
+
+ \snippet code/src_corelib_kernel_qtestsupport_core.cpp 0
+
+ The code above will wait for the object to become ready, for a
+ maximum of three seconds.
+
+ \since 5.10
+*/
+
+
+/*! \fn void qWait(int ms)
+ \relates QTest
+
+ Waits for \a ms milliseconds. While waiting, events will be processed and
+ your test will stay responsive to user interface events or network communication.
+
+ Example:
+
+ \snippet code/src_corelib_kernel_qtestsupport_core.cpp 1
+
+ The code above will wait until the network server is responding for a
+ maximum of about 12.5 seconds.
+
+ \sa QTest::qSleep(), QSignalSpy::wait()
+*/
+Q_CORE_EXPORT void QTest::qWait(int ms)
+{
+ // Ideally this method would be implemented in terms of qWaitFor, with
+ // a predicate that always returns false, but due to a compiler bug in
+ // GCC 6 we can't do that.
+
+ Q_ASSERT(QCoreApplication::instance());
+
+ QDeadlineTimer timer(ms, Qt::PreciseTimer);
+ int remaining = ms;
+ do {
+ QCoreApplication::processEvents(QEventLoop::AllEvents, remaining);
+ QCoreApplication::sendPostedEvents(Q_NULLPTR, QEvent::DeferredDelete);
+ remaining = timer.remainingTime();
+ if (remaining <= 0)
+ break;
+ QTestPrivate::qSleep(qMin(10, remaining));
+ remaining = timer.remainingTime();
+ } while (remaining > 0);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qtestsupport_core.h b/src/corelib/kernel/qtestsupport_core.h
new file mode 100644
index 0000000000..7fc0054580
--- /dev/null
+++ b/src/corelib/kernel/qtestsupport_core.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 QTESTSUPPORT_CORE_H
+#define QTESTSUPPORT_CORE_H
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qdeadlinetimer.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QTestPrivate {
+Q_CORE_EXPORT void qSleep(int ms);
+}
+
+namespace QTest {
+
+template <typename Functor>
+Q_REQUIRED_RESULT static bool qWaitFor(Functor predicate, int timeout = 5000)
+{
+ // We should not spin the event loop in case the predicate is already true,
+ // otherwise we might send new events that invalidate the predicate.
+ if (predicate())
+ return true;
+
+ // qWait() is expected to spin the event loop, even when called with a small
+ // timeout like 1ms, so we we can't use a simple while-loop here based on
+ // the deadline timer not having timed out. Use do-while instead.
+
+ int remaining = timeout;
+ QDeadlineTimer deadline(remaining, Qt::PreciseTimer);
+
+ do {
+ QCoreApplication::processEvents(QEventLoop::AllEvents, remaining);
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
+
+ remaining = deadline.remainingTime();
+ if (remaining > 0)
+ QTestPrivate::qSleep(qMin(10, remaining));
+
+ if (predicate())
+ return true;
+
+ remaining = deadline.remainingTime();
+ } while (remaining > 0);
+
+ return predicate(); // Last chance
+}
+
+Q_CORE_EXPORT void qWait(int ms);
+
+} // namespace QTest
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp
index 3edd1f056e..90f29aa630 100644
--- a/src/corelib/kernel/qtimer.cpp
+++ b/src/corelib/kernel/qtimer.cpp
@@ -571,6 +571,48 @@ void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiv
*/
/*!
+ \fn template<typename Functor> QMetaObject::Connection callOnTimeout(Functor functor, Qt::ConnectionType connectionType = Qt::AutoConnection)
+ \since 5.12
+ \overload
+
+ Creates a connection from the timeout() signal to \a functor, and returns a
+ handle to the connection.
+
+ This method is provided for convenience.
+ It's equivalent to calling \c {QObject::connect(timer, &QTimer::timeout, timer, functor, connectionType)}.
+
+ \sa QObject::connect(), timeout()
+*/
+
+/*!
+ \fn template<typename Functor> QMetaObject::Connection callOnTimeout(QObject *context, Functor functor, Qt::ConnectionType connectionType = Qt::AutoConnection)
+ \since 5.12
+ \overload callOnTimeout()
+
+ Creates a connection from the timeout() signal to \a functor to be placed in a specific
+ event loop of \a context, and returns a handle to the connection.
+
+ This method is provided for convenience. It's equivalent to calling
+ \c {QObject::connect(timer, &QTimer::timeout, context, functor, connectionType)}.
+
+ \sa QObject::connect(), timeout()
+*/
+
+/*!
+ \fn template<typename PointerToMemberFunction> QMetaObject::Connection callOnTimeout(QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType connectionType = Qt::AutoConnection)
+ \since 5.12
+ \overload callOnTimeout()
+
+ Creates a connection from the timeout() signal to the \a method in the \a receiver object. Returns
+ a handle to the connection.
+
+ This method is provided for convenience. It's equivalent to calling
+ \c {QObject::connect(timer, &QTimer::timeout, receiver, method, connectionType)}.
+
+ \sa QObject::connect(), timeout()
+*/
+
+/*!
\fn void QTimer::start(std::chrono::milliseconds msec)
\since 5.8
\overload
diff --git a/src/corelib/kernel/qtimer.h b/src/corelib/kernel/qtimer.h
index e6db586aa0..66f317c567 100644
--- a/src/corelib/kernel/qtimer.h
+++ b/src/corelib/kernel/qtimer.h
@@ -96,6 +96,12 @@ public:
static void singleShot(int msec, const QObject *context, Functor functor);
template<typename Functor, int>
static void singleShot(int msec, Qt::TimerType timerType, const QObject *context, Functor functor);
+ template <typename Functor>
+ QMetaObject::Connection callOnTimeout(Functor slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
+ template <typename Functor>
+ QMetaObject::Connection callOnTimeout(const QObject *context, Functor slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
+ template <typename PointerToMemberFunction>
+ QMetaObject::Connection callOnTimeout(const QObject *receiver, PointerToMemberFunction slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
#else
// singleShot to a QObject slot
template <typename Duration, typename Func1>
@@ -135,14 +141,14 @@ public:
template <typename Duration, typename Func1>
static inline typename std::enable_if<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
!std::is_same<const char*, Func1>::value, void>::type
- singleShot(Duration interval, QObject *context, Func1 slot)
+ singleShot(Duration interval, const QObject *context, Func1 slot)
{
singleShot(interval, defaultTypeFor(interval), context, std::move(slot));
}
template <typename Duration, typename Func1>
static inline typename std::enable_if<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
!std::is_same<const char*, Func1>::value, void>::type
- singleShot(Duration interval, Qt::TimerType timerType, QObject *context, Func1 slot)
+ singleShot(Duration interval, Qt::TimerType timerType, const QObject *context, Func1 slot)
{
//compilation error if the slot has arguments.
typedef QtPrivate::FunctionPointer<Func1> SlotType;
@@ -152,6 +158,13 @@ public:
new QtPrivate::QFunctorSlotObject<Func1, 0,
typename QtPrivate::List_Left<void, 0>::Value, void>(std::move(slot)));
}
+
+ template <typename ... Args>
+ QMetaObject::Connection callOnTimeout(Args && ...args)
+ {
+ return QObject::connect(this, &QTimer::timeout, std::forward<Args>(args)... );
+ }
+
#endif
public Q_SLOTS:
diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp
index c868f6d266..744bbfbff5 100644
--- a/src/corelib/kernel/qtranslator.cpp
+++ b/src/corelib/kernel/qtranslator.cpp
@@ -49,6 +49,7 @@
#include "qcoreapplication.h"
#include "qcoreapplication_p.h"
#include "qdatastream.h"
+#include "qendian.h"
#include "qfile.h"
#include "qmap.h"
#include "qalgorithms.h"
@@ -532,7 +533,7 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo
// memory, so no need to use QFile to copy it again.
Q_ASSERT(!d->resource);
d->resource = new QResource(realname);
- if (resource->isValid() && !resource->isCompressed() && resource->size() > MagicLength
+ if (resource->isValid() && !resource->isCompressed() && resource->size() >= MagicLength
&& !memcmp(resource->data(), magic, MagicLength)) {
d->unmapLength = resource->size();
d->unmapPointer = reinterpret_cast<char *>(const_cast<uchar *>(resource->data()));
@@ -552,7 +553,7 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo
return false;
qint64 fileSize = file.size();
- if (fileSize <= MagicLength || quint32(-1) <= fileSize)
+ if (fileSize < MagicLength || quint32(-1) <= fileSize)
return false;
{
@@ -857,8 +858,6 @@ bool QTranslatorPrivate::do_load(const uchar *data, int len, const QString &dire
data += blockLen;
}
- if (dependencies.isEmpty() && (!offsetArray || !messageArray))
- ok = false;
if (ok && !isValidNumerusRules(numerusRulesArray, numerusRulesLength))
ok = false;
if (ok) {
@@ -957,8 +956,8 @@ end:
return QString();
QString str = QString((const QChar *)tn, tn_length/2);
if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
- for (int i = 0; i < str.length(); ++i)
- str[i] = QChar((str.at(i).unicode() >> 8) + ((str.at(i).unicode() << 8) & 0xff00));
+ QChar *data = str.data();
+ qbswap<sizeof(QChar)>(data, str.length(), data);
}
return str;
}
@@ -1137,8 +1136,8 @@ QString QTranslator::translate(const char *context, const char *sourceText, cons
bool QTranslator::isEmpty() const
{
Q_D(const QTranslator);
- return !d->unmapPointer && !d->unmapLength && !d->messageArray &&
- !d->offsetArray && !d->contextArray && d->subTranslators.isEmpty();
+ return !d->messageArray && !d->offsetArray && !d->contextArray
+ && d->subTranslators.isEmpty();
}
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 57c25a9423..0b4c3f387f 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
+** Copyright (C) 2018 Intel Corporation.
** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
** Contact: https://www.qt.io/licensing/
**
@@ -60,6 +60,9 @@
#include "qabstractitemmodel.h"
#endif
#ifndef QT_BOOTSTRAPPED
+#include "qcborarray.h"
+#include "qcborcommon.h"
+#include "qcbormap.h"
#include "qjsonvalue.h"
#include "qjsonobject.h"
#include "qjsonarray.h"
@@ -167,6 +170,8 @@ static qlonglong qMetaTypeNumber(const QVariant::Private *d)
#ifndef QT_BOOTSTRAPPED
case QMetaType::QJsonValue:
return v_cast<QJsonValue>(d)->toDouble();
+ case QMetaType::QCborValue:
+ return v_cast<QCborValue>(d)->toInteger();
#endif
}
Q_ASSERT(false);
@@ -205,6 +210,10 @@ static qlonglong qConvertToNumber(const QVariant::Private *d, bool *ok)
case QVariant::Bool:
return qlonglong(d->data.b);
#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QCborValue:
+ if (!v_cast<QCborValue>(d)->isInteger() && !v_cast<QCborValue>(d)->isDouble())
+ break;
+ return qMetaTypeNumber(d);
case QMetaType::QJsonValue:
if (!v_cast<QJsonValue>(d)->isDouble())
break;
@@ -229,7 +238,7 @@ static qlonglong qConvertToNumber(const QVariant::Private *d, bool *ok)
}
QMetaType typeInfo(d->type);
- if (typeInfo.flags() & QMetaType::IsEnumeration) {
+ if (typeInfo.flags() & QMetaType::IsEnumeration || d->type == QMetaType::QCborSimpleType) {
switch (typeInfo.sizeOf()) {
case 1:
return d->is_shared ? *reinterpret_cast<signed char *>(d->data.shared->ptr) : d->data.sc;
@@ -261,6 +270,8 @@ static qreal qConvertToRealNumber(const QVariant::Private *d, bool *ok)
case QMetaType::ULong:
return qreal(qMetaTypeUNumber(d));
#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QCborValue:
+ return v_cast<QCborValue>(d)->toDouble();
case QMetaType::QJsonValue:
return v_cast<QJsonValue>(d)->toDouble();
#endif
@@ -284,6 +295,12 @@ static qulonglong qConvertToUnsignedNumber(const QVariant::Private *d, bool *ok)
case QVariant::Bool:
return qulonglong(d->data.b);
#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QCborValue:
+ if (v_cast<QCborValue>(d)->isDouble())
+ return qulonglong(qConvertToRealNumber(d, ok));
+ if (!v_cast<QCborValue>(d)->isInteger())
+ return false;
+ return qulonglong(qMetaTypeNumber(d));
case QMetaType::QJsonValue:
if (!v_cast<QJsonValue>(d)->isDouble())
break;
@@ -391,6 +408,12 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
case QVariant::String:
*static_cast<QUrl *>(result) = QUrl(*v_cast<QString>(d));
break;
+ case QMetaType::QCborValue:
+ if (v_cast<QCborValue>(d)->isUrl()) {
+ *static_cast<QUrl *>(result) = v_cast<QCborValue>(d)->toUrl();
+ break;
+ }
+ return false;
default:
return false;
}
@@ -476,6 +499,11 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
else if (!v_cast<QJsonValue>(d)->isNull())
return false;
break;
+ case QMetaType::QCborValue:
+ if (v_cast<QCborValue>(d)->isContainer() || v_cast<QCborValue>(d)->isTag())
+ return false;
+ *str = v_cast<QCborValue>(d)->toVariant().toString();
+ break;
#endif
case QVariant::Uuid:
*str = v_cast<QUuid>(d)->toString();
@@ -621,6 +649,14 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
case QVariant::String:
*dt = QDateTime::fromString(*v_cast<QString>(d), Qt::ISODate);
break;
+# ifndef QT_BOOTSTRAPPED
+ case QMetaType::QCborValue:
+ if (v_cast<QCborValue>(d)->isDateTime())
+ *dt = v_cast<QCborValue>(d)->toDateTime();
+ else
+ return false;
+ break;
+# endif
#endif
case QVariant::Date:
*dt = QDateTime(*v_cast<QDate>(d));
@@ -668,6 +704,14 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
case QMetaType::Nullptr:
*ba = QByteArray();
break;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QCborValue:
+ if (v_cast<QCborValue>(d)->isByteArray())
+ *ba = v_cast<QCborValue>(d)->toByteArray();
+ else
+ return false;
+ break;
+#endif
default:
#ifndef QT_NO_QOBJECT
{
@@ -746,6 +790,11 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
*b = qMetaTypeUNumber(d) != Q_UINT64_C(0);
break;
#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QCborValue:
+ *b = v_cast<QCborValue>(d)->toBool();
+ if (!v_cast<QCborValue>(d)->isBool())
+ return false;
+ break;
case QMetaType::QJsonValue:
*b = v_cast<QJsonValue>(d)->toBool(false);
if (!v_cast<QJsonValue>(d)->isBool())
@@ -789,6 +838,11 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
*f = double(qMetaTypeUNumber(d));
break;
#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QCborValue:
+ *f = v_cast<QCborValue>(d)->toDouble();
+ if (!v_cast<QCborValue>(d)->isDouble())
+ return false;
+ break;
case QMetaType::QJsonValue:
*f = v_cast<QJsonValue>(d)->toDouble(0.0);
if (!v_cast<QJsonValue>(d)->isDouble())
@@ -832,6 +886,11 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
*f = float(qMetaTypeUNumber(d));
break;
#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QCborValue:
+ *f = v_cast<QCborValue>(d)->toDouble();
+ if (!v_cast<QCborValue>(d)->isDouble())
+ return false;
+ break;
case QMetaType::QJsonValue:
*f = v_cast<QJsonValue>(d)->toDouble(0.0);
if (!v_cast<QJsonValue>(d)->isDouble())
@@ -856,6 +915,12 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
*static_cast<QVariantList *>(result) =
*static_cast<QList<QVariant> *>(d->data.shared->ptr);
#ifndef QT_BOOTSTRAPPED
+ } else if (d->type == QMetaType::QCborValue) {
+ if (!v_cast<QCborValue>(d)->isArray())
+ return false;
+ *static_cast<QVariantList *>(result) = v_cast<QCborValue>(d)->toArray().toVariantList();
+ } else if (d->type == QMetaType::QCborArray) {
+ *static_cast<QVariantList *>(result) = v_cast<QCborArray>(d)->toVariantList();
} else if (d->type == QMetaType::QJsonValue) {
if (!v_cast<QJsonValue>(d)->isArray())
return false;
@@ -878,6 +943,12 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
for (auto it = hash->begin(); it != end; ++it)
map->insertMulti(it.key(), it.value());
#ifndef QT_BOOTSTRAPPED
+ } else if (d->type == QMetaType::QCborValue) {
+ if (!v_cast<QCborValue>(d)->isMap())
+ return false;
+ *static_cast<QVariantMap *>(result) = v_cast<QCborValue>(d)->toMap().toVariantMap();
+ } else if (d->type == QMetaType::QCborMap) {
+ *static_cast<QVariantMap *>(result) = v_cast<QCborMap>(d)->toVariantMap();
} else if (d->type == QMetaType::QJsonValue) {
if (!v_cast<QJsonValue>(d)->isObject())
return false;
@@ -900,6 +971,12 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
for (auto it = map->begin(); it != end; ++it)
hash->insertMulti(it.key(), it.value());
#ifndef QT_BOOTSTRAPPED
+ } else if (d->type == QMetaType::QCborValue) {
+ if (!v_cast<QCborValue>(d)->isMap())
+ return false;
+ *static_cast<QVariantHash *>(result) = v_cast<QCborValue>(d)->toMap().toVariantHash();
+ } else if (d->type == QMetaType::QCborMap) {
+ *static_cast<QVariantHash *>(result) = v_cast<QCborMap>(d)->toVariantHash();
} else if (d->type == QMetaType::QJsonValue) {
if (!v_cast<QJsonValue>(d)->isObject())
return false;
@@ -950,11 +1027,36 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
case QVariant::ByteArray:
*static_cast<QUuid *>(result) = QUuid(*v_cast<QByteArray>(d));
break;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QCborValue:
+ if (!v_cast<QCborValue>(d)->isUuid())
+ return false;
+ *static_cast<QUuid *>(result) = v_cast<QCborValue>(d)->toUuid();
+ break;
+#endif
default:
return false;
}
break;
+ case QMetaType::Nullptr:
+ *static_cast<std::nullptr_t *>(result) = nullptr;
+ if (QMetaType::typeFlags(t) & (QMetaType::PointerToGadget | QMetaType::PointerToQObject)
+ || d->type == QMetaType::VoidStar) {
+ if (v_cast<const void *>(d) == nullptr)
+ break;
+ }
#ifndef QT_BOOTSTRAPPED
+ if (d->type == QMetaType::QCborValue && v_cast<QCborValue>(d)->isNull())
+ break;
+#endif
+ return false;
+
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QRegularExpression:
+ if (d->type != QMetaType::QCborValue || !v_cast<QCborValue>(d)->isRegularExpression())
+ return false;
+ *static_cast<QRegularExpression *>(result) = v_cast<QCborValue>(d)->toRegularExpression();
+ break;
case QMetaType::QJsonValue:
switch (d->type) {
case QMetaType::Nullptr:
@@ -1005,6 +1107,15 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
*static_cast<QJsonValue *>(result) = doc.isArray() ? QJsonValue(doc.array()) : QJsonValue(doc.object());
break;
}
+ case QMetaType::QCborValue:
+ *static_cast<QJsonValue *>(result) = v_cast<QCborValue>(d)->toJsonValue();
+ break;
+ case QMetaType::QCborMap:
+ *static_cast<QJsonValue *>(result) = v_cast<QCborMap>(d)->toJsonObject();
+ break;
+ case QMetaType::QCborArray:
+ *static_cast<QJsonValue *>(result) = v_cast<QCborArray>(d)->toJsonArray();
+ break;
default:
*static_cast<QJsonValue *>(result) = QJsonValue(QJsonValue::Undefined);
return false;
@@ -1028,6 +1139,14 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
return false;
*static_cast<QJsonArray *>(result) = v_cast<QJsonDocument>(d)->array();
break;
+ case QMetaType::QCborValue:
+ if (!v_cast<QCborValue>(d)->isArray())
+ return false;
+ *static_cast<QJsonArray *>(result) = v_cast<QCborValue>(d)->toArray().toJsonArray();
+ break;
+ case QMetaType::QCborArray:
+ *static_cast<QJsonArray *>(result) = v_cast<QCborArray>(d)->toJsonArray();
+ break;
default:
return false;
}
@@ -1050,11 +1169,177 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
return false;
*static_cast<QJsonObject *>(result) = v_cast<QJsonDocument>(d)->object();
break;
+ case QMetaType::QCborValue:
+ if (!v_cast<QCborValue>(d)->isMap())
+ return false;
+ *static_cast<QJsonObject *>(result) = v_cast<QCborValue>(d)->toMap().toJsonObject();
+ break;
+ case QMetaType::QCborMap:
+ *static_cast<QJsonObject *>(result) = v_cast<QCborMap>(d)->toJsonObject();
+ break;
+ default:
+ return false;
+ }
+ break;
+ case QMetaType::QCborSimpleType:
+ if (d->type == QMetaType::QCborValue && v_cast<QCborValue>(d)->isSimpleType()) {
+ *static_cast<QCborSimpleType *>(result) = v_cast<QCborValue>(d)->toSimpleType();
+ break;
+ }
+ return false;
+ case QMetaType::QCborValue:
+ switch (d->type) {
+ case QMetaType::Nullptr:
+ *static_cast<QCborValue *>(result) = QCborValue(QCborValue::Null);
+ break;
+ case QVariant::Bool:
+ *static_cast<QCborValue *>(result) = QCborValue(d->data.b);
+ break;
+ case QMetaType::Int:
+ case QMetaType::UInt:
+ case QMetaType::ULong:
+ case QMetaType::Long:
+ case QMetaType::LongLong:
+ case QMetaType::ULongLong:
+ case QMetaType::UShort:
+ case QMetaType::UChar:
+ case QMetaType::Char:
+ case QMetaType::SChar:
+ case QMetaType::Short:
+ *static_cast<QCborValue *>(result) = QCborValue(qConvertToNumber(d, ok));
+ Q_ASSERT(ok);
+ break;
+ case QMetaType::Double:
+ case QMetaType::Float:
+ *static_cast<QCborValue *>(result) = QCborValue(qConvertToRealNumber(d, ok));
+ Q_ASSERT(ok);
+ break;
+ case QVariant::String:
+ *static_cast<QCborValue *>(result) = *v_cast<QString>(d);
+ break;
+ case QVariant::StringList:
+ *static_cast<QCborValue *>(result) = QCborArray::fromStringList(*v_cast<QStringList>(d));
+ break;
+ case QVariant::ByteArray:
+ *static_cast<QCborValue *>(result) = *v_cast<QByteArray>(d);
+ break;
+ case QVariant::Date:
+ *static_cast<QCborValue *>(result) = QCborValue(QDateTime(*v_cast<QDate>(d)));
+ break;
+ case QVariant::DateTime:
+ *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QDateTime>(d));
+ break;
+ case QVariant::Url:
+ *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QUrl>(d));
+ break;
+ case QVariant::RegularExpression:
+ *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QRegularExpression>(d));
+ break;
+ case QVariant::Uuid:
+ *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QUuid>(d));
+ break;
+ case QVariant::List:
+ *static_cast<QCborValue *>(result) = QCborArray::fromVariantList(*v_cast<QVariantList>(d));
+ break;
+ case QVariant::Map:
+ *static_cast<QCborValue *>(result) = QCborMap::fromVariantMap(*v_cast<QVariantMap>(d));
+ break;
+ case QVariant::Hash:
+ *static_cast<QCborValue *>(result) = QCborMap::fromVariantHash(*v_cast<QVariantHash>(d));
+ break;
+ case QMetaType::QJsonValue:
+ *static_cast<QCborValue *>(result) = QCborValue::fromJsonValue(*v_cast<QJsonValue>(d));
+ break;
+ case QMetaType::QJsonObject:
+ *static_cast<QCborValue *>(result) = QCborMap::fromJsonObject(*v_cast<QJsonObject>(d));
+ break;
+ case QMetaType::QJsonArray:
+ *static_cast<QCborValue *>(result) = QCborArray::fromJsonArray(*v_cast<QJsonArray>(d));
+ break;
+ case QMetaType::QJsonDocument: {
+ QJsonDocument doc = *v_cast<QJsonDocument>(d);
+ if (doc.isArray())
+ *static_cast<QCborValue *>(result) = QCborArray::fromJsonArray(doc.array());
+ else
+ *static_cast<QCborValue *>(result) = QCborMap::fromJsonObject(doc.object());
+ break;
+ }
+ case QMetaType::QCborSimpleType:
+ *static_cast<QCborValue *>(result) = *v_cast<QCborSimpleType>(d);
+ break;
+ case QMetaType::QCborMap:
+ *static_cast<QCborValue *>(result) = *v_cast<QCborMap>(d);
+ break;
+ case QMetaType::QCborArray:
+ *static_cast<QCborValue *>(result) = *v_cast<QCborArray>(d);
+ break;
+ default:
+ *static_cast<QCborValue *>(result) = {};
+ return false;
+ }
+ break;
+ case QMetaType::QCborArray:
+ switch (d->type) {
+ case QVariant::StringList:
+ *static_cast<QCborArray *>(result) = QCborArray::fromStringList(*v_cast<QStringList>(d));
+ break;
+ case QVariant::List:
+ *static_cast<QCborArray *>(result) = QCborArray::fromVariantList(*v_cast<QVariantList>(d));
+ break;
+ case QMetaType::QCborValue:
+ if (!v_cast<QCborValue>(d)->isArray())
+ return false;
+ *static_cast<QCborArray *>(result) = v_cast<QCborValue>(d)->toArray();
+ break;
+ case QMetaType::QJsonDocument:
+ if (!v_cast<QJsonDocument>(d)->isArray())
+ return false;
+ *static_cast<QCborArray *>(result) = QCborArray::fromJsonArray(v_cast<QJsonDocument>(d)->array());
+ break;
+ case QMetaType::QJsonValue:
+ if (!v_cast<QJsonValue>(d)->isArray())
+ return false;
+ *static_cast<QCborArray *>(result) = QCborArray::fromJsonArray(v_cast<QJsonValue>(d)->toArray());
+ break;
+ case QMetaType::QJsonArray:
+ *static_cast<QCborArray *>(result) = QCborArray::fromJsonArray(*v_cast<QJsonArray>(d));
+ break;
+ default:
+ return false;
+ }
+ break;
+ case QMetaType::QCborMap:
+ switch (d->type) {
+ case QVariant::Map:
+ *static_cast<QCborMap *>(result) = QCborMap::fromVariantMap(*v_cast<QVariantMap>(d));
+ break;
+ case QVariant::Hash:
+ *static_cast<QCborMap *>(result) = QCborMap::fromVariantHash(*v_cast<QVariantHash>(d));
+ break;
+ case QMetaType::QCborValue:
+ if (!v_cast<QCborValue>(d)->isMap())
+ return false;
+ *static_cast<QCborMap *>(result) = v_cast<QCborValue>(d)->toMap();
+ break;
+ case QMetaType::QJsonDocument:
+ if (v_cast<QJsonDocument>(d)->isArray())
+ return false;
+ *static_cast<QCborMap *>(result) = QCborMap::fromJsonObject(v_cast<QJsonDocument>(d)->object());
+ break;
+ case QMetaType::QJsonValue:
+ if (!v_cast<QJsonValue>(d)->isObject())
+ return false;
+ *static_cast<QCborMap *>(result) = QCborMap::fromJsonObject(v_cast<QJsonValue>(d)->toObject());
+ break;
+ case QMetaType::QJsonObject:
+ *static_cast<QCborMap *>(result) = QCborMap::fromJsonObject(*v_cast<QJsonObject>(d));
+ break;
default:
return false;
}
break;
#endif
+
default:
#ifndef QT_NO_QOBJECT
if (d->type == QVariant::String || d->type == QVariant::ByteArray) {
@@ -1081,7 +1366,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
}
}
#endif
- if (QMetaType::typeFlags(t) & QMetaType::IsEnumeration) {
+ if (QMetaType::typeFlags(t) & QMetaType::IsEnumeration || d->type == QMetaType::QCborSimpleType) {
qlonglong value = qConvertToNumber(d, ok);
if (*ok) {
switch (QMetaType::sizeOf(t)) {
@@ -1175,9 +1460,16 @@ static void customConstruct(QVariant::Private *d, const void *copy)
type.construct(&d->data.ptr, copy);
d->is_shared = false;
} else {
- void *ptr = type.create(copy);
+ // Private::Data contains long long, and long double is the biggest standard type.
+ const size_t maxAlignment =
+ qMax(Q_ALIGNOF(QVariant::Private::Data), Q_ALIGNOF(long double));
+ const size_t s = sizeof(QVariant::PrivateShared);
+ const size_t offset = s + ((s * maxAlignment - s) % maxAlignment);
+ void *data = operator new(offset + size);
+ void *ptr = static_cast<char *>(data) + offset;
+ type.construct(ptr, copy);
d->is_shared = true;
- d->data.shared = new QVariant::PrivateShared(ptr);
+ d->data.shared = new (data) QVariant::PrivateShared(ptr);
}
}
@@ -1186,8 +1478,9 @@ static void customClear(QVariant::Private *d)
if (!d->is_shared) {
QMetaType::destruct(d->type, &d->data.ptr);
} else {
- QMetaType::destroy(d->type, d->data.shared->ptr);
- delete d->data.shared;
+ QMetaType::destruct(d->type, d->data.shared->ptr);
+ d->data.shared->~PrivateShared();
+ operator delete(d->data.shared);
}
}
@@ -3272,15 +3565,66 @@ bool QVariant::canConvert(int targetTypeId) const
case QMetaType::QVariantList:
case QMetaType::QVariantMap:
case QMetaType::QVariantHash:
+ case QMetaType::QCborValue:
+ case QMetaType::QCborArray:
+ case QMetaType::QCborMap:
return true;
default:
return false;
}
}
if (currentType == QMetaType::QJsonArray)
- return targetTypeId == QMetaType::QVariantList;
+ return targetTypeId == QMetaType::QVariantList || targetTypeId == QMetaType::QCborValue
+ || targetTypeId == QMetaType::QCborArray;
if (currentType == QMetaType::QJsonObject)
- return targetTypeId == QMetaType::QVariantMap || targetTypeId == QMetaType::QVariantHash;
+ return targetTypeId == QMetaType::QVariantMap || targetTypeId == QMetaType::QVariantHash
+ || targetTypeId == QMetaType::QCborValue || targetTypeId == QMetaType::QCborMap;
+
+ if (currentType == QMetaType::QCborValue || targetTypeId == QMetaType::QCborValue) {
+ switch (currentType == QMetaType::QCborValue ? targetTypeId : currentType) {
+ case QMetaType::UnknownType:
+ case QMetaType::Nullptr:
+ case QMetaType::Bool:
+ case QMetaType::Int:
+ case QMetaType::UInt:
+ case QMetaType::Double:
+ case QMetaType::Float:
+ case QMetaType::ULong:
+ case QMetaType::Long:
+ case QMetaType::LongLong:
+ case QMetaType::ULongLong:
+ case QMetaType::UShort:
+ case QMetaType::UChar:
+ case QMetaType::Char:
+ case QMetaType::SChar:
+ case QMetaType::Short:
+ case QMetaType::QString:
+ case QMetaType::QByteArray:
+ case QMetaType::QDateTime:
+ case QMetaType::QUrl:
+ case QMetaType::QRegularExpression:
+ case QMetaType::QUuid:
+ case QMetaType::QVariantList:
+ case QMetaType::QVariantMap:
+ case QMetaType::QVariantHash:
+ case QMetaType::QJsonValue:
+ case QMetaType::QJsonArray:
+ case QMetaType::QJsonObject:
+ case QMetaType::QJsonDocument:
+ case QMetaType::QCborArray:
+ case QMetaType::QCborMap:
+ case QMetaType::QCborSimpleType:
+ return true;
+ default:
+ return false;
+ }
+ }
+ if (currentType == QMetaType::QCborArray)
+ return targetTypeId == QMetaType::QVariantList || targetTypeId == QMetaType::QCborValue
+ || targetTypeId == QMetaType::QJsonArray;
+ if (currentType == QMetaType::QCborMap)
+ return targetTypeId == QMetaType::QVariantMap || targetTypeId == QMetaType::QVariantHash
+ || targetTypeId == QMetaType::QCborValue || targetTypeId == QMetaType::QJsonObject;
// FIXME It should be LastCoreType intead of Uuid
if (currentType > int(QMetaType::QUuid) || targetTypeId > int(QMetaType::QUuid)) {
@@ -3380,7 +3724,7 @@ bool QVariant::convert(int targetTypeId)
create(targetTypeId, 0);
// Fail if the value is not initialized or was forced null by a previous failed convert.
- if (oldValue.d.is_null)
+ if (oldValue.d.is_null && oldValue.d.type != QMetaType::Nullptr)
return false;
if ((QMetaType::typeFlags(oldValue.userType()) & QMetaType::PointerToQObject) && (QMetaType::typeFlags(targetTypeId) & QMetaType::PointerToQObject)) {
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index 9a5fc63d03..ff73c27b6e 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -633,6 +633,7 @@ public:
const_iterator &operator-=(int j);
const_iterator operator+(int j) const;
const_iterator operator-(int j) const;
+ friend inline const_iterator operator+(int j, const_iterator k) { return k + j; }
};
friend struct const_iterator;
@@ -690,6 +691,7 @@ public:
const_iterator &operator-=(int j);
const_iterator operator+(int j) const;
const_iterator operator-(int j) const;
+ friend inline const_iterator operator+(int j, const_iterator k) { return k + j; }
};
friend struct const_iterator;
diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp
index fe086acb5d..3c73c0b851 100644
--- a/src/corelib/kernel/qwineventnotifier.cpp
+++ b/src/corelib/kernel/qwineventnotifier.cpp
@@ -157,7 +157,6 @@ void QWinEventNotifier::setHandle(HANDLE hEvent)
Q_D(QWinEventNotifier);
setEnabled(false);
d->handleToEvent = hEvent;
- d->signaledCount = 0;
}
/*!
@@ -209,10 +208,12 @@ void QWinEventNotifier::setEnabled(bool enable)
return;
}
- if (enable)
+ if (enable) {
+ d->signaledCount = 0;
eventDispatcher->registerEventNotifier(this);
- else
+ } else {
eventDispatcher->unregisterEventNotifier(this);
+ }
}
/*!
diff --git a/src/corelib/kernel/qwineventnotifier.h b/src/corelib/kernel/qwineventnotifier.h
index 624e77e638..71a1d29057 100644
--- a/src/corelib/kernel/qwineventnotifier.h
+++ b/src/corelib/kernel/qwineventnotifier.h
@@ -70,7 +70,7 @@ Q_SIGNALS:
void activated(HANDLE hEvent, QPrivateSignal);
protected:
- bool event(QEvent * e);
+ bool event(QEvent *e) override;
};
QT_END_NAMESPACE
diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp
index b31fef5bf5..bfe9be559a 100644
--- a/src/corelib/mimetypes/qmimedatabase.cpp
+++ b/src/corelib/mimetypes/qmimedatabase.cpp
@@ -149,7 +149,9 @@ void QMimeDatabasePrivate::loadProviders()
QVector<QMimeProviderBase *> QMimeDatabasePrivate::providers()
{
+#ifndef Q_OS_WASM // stub implementation always returns true
Q_ASSERT(!mutex.tryLock()); // caller should have locked mutex
+#endif
if (m_providers.isEmpty()) {
loadProviders();
m_lastCheck.start();
@@ -380,9 +382,12 @@ QMimeType QMimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileNa
// Disambiguate conflicting extensions (if magic matching found something)
if (candidateByData.isValid() && magicAccuracy > 0) {
- // "for glob_match in glob_matches:"
- // "if glob_match is subclass or equal to sniffed_type, use glob_match"
const QString sniffedMime = candidateByData.name();
+ // If the sniffedMime matches a glob match, use it
+ if (candidatesByName.m_matchingMimeTypes.contains(sniffedMime)) {
+ *accuracyPtr = 100;
+ return candidateByData;
+ }
for (const QString &m : qAsConst(candidatesByName.m_matchingMimeTypes)) {
if (inherits(m, sniffedMime)) {
// We have magic + pattern pointing to this, so it's a pretty good match
@@ -446,25 +451,14 @@ bool QMimeDatabasePrivate::inherits(const QString &mime, const QString &parent)
Applications which want to define custom MIME types need to install an
XML file into the locations searched for MIME definitions.
These locations can be queried with
- \code
- QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/packages"),
- QStandardPaths::LocateDirectory);
- \endcode
+ \snippet code/src_corelib_mimetype_qmimedatabase.cpp 1
On a typical Unix system, this will be /usr/share/mime/packages/, but it is also
possible to extend the list of directories by setting the environment variable
\c XDG_DATA_DIRS. For instance adding /opt/myapp/share to \c XDG_DATA_DIRS will result
in /opt/myapp/share/mime/packages/ being searched for MIME definitions.
Here is an example of MIME XML:
- \code
- <?xml version="1.0" encoding="UTF-8"?>
- <mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
- <mime-type type="application/vnd.qt.qmakeprofile">
- <comment xml:lang="en">Qt qmake Profile</comment>
- <glob pattern="*.pro" weight="50"/>
- </mime-type>
- </mime-info>
- \endcode
+ \snippet code/src_corelib_mimetype_qmimedatabase.cpp 2
For more details about the syntax of XML MIME definitions, including defining
"magic" in order to detect MIME types based on data as well, read the
diff --git a/src/corelib/plugin/plugin.pri b/src/corelib/plugin/plugin.pri
index a0e0d76044..13153e8d0a 100644
--- a/src/corelib/plugin/plugin.pri
+++ b/src/corelib/plugin/plugin.pri
@@ -4,6 +4,7 @@ HEADERS += \
plugin/qfactoryinterface.h \
plugin/qpluginloader.h \
plugin/qplugin.h \
+ plugin/qplugin_p.h \
plugin/quuid.h \
plugin/qfactoryloader_p.h
diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp
index dc1424fd0c..35c64180d4 100644
--- a/src/corelib/plugin/qfactoryloader.cpp
+++ b/src/corelib/plugin/qfactoryloader.cpp
@@ -47,9 +47,12 @@
#include <qdebug.h>
#include "qmutex.h"
#include "qplugin.h"
+#include "qplugin_p.h"
#include "qpluginloader.h"
#include "private/qobject_p.h"
#include "private/qcoreapplication_p.h"
+#include "qcbormap.h"
+#include "qcborvalue.h"
#include "qjsondocument.h"
#include "qjsonvalue.h"
#include "qjsonobject.h"
@@ -64,22 +67,86 @@ static inline int metaDataSignatureLength()
return sizeof("QTMETADATA ") - 1;
}
-QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype sectionSize)
+static QJsonDocument jsonFromCborMetaData(const char *raw, qsizetype size, QString *errMsg)
+{
+ // extract the keys not stored in CBOR
+ int qt_metadataVersion = quint8(raw[0]);
+ int qt_version = qFromBigEndian<quint16>(raw + 1);
+ int qt_archRequirements = quint8(raw[3]);
+ if (Q_UNLIKELY(raw[-1] != '!' || qt_metadataVersion != 0)) {
+ *errMsg = QStringLiteral("Invalid metadata version");
+ return QJsonDocument();
+ }
+
+ raw += 4;
+ size -= 4;
+ QByteArray ba = QByteArray::fromRawData(raw, int(size));
+ QCborParserError err;
+ QCborValue metadata = QCborValue::fromCbor(ba, &err);
+
+ if (err.error != QCborError::NoError) {
+ *errMsg = QLatin1String("Metadata parsing error: ") + err.error.toString();
+ return QJsonDocument();
+ }
+
+ if (!metadata.isMap()) {
+ *errMsg = QStringLiteral("Unexpected metadata contents");
+ return QJsonDocument();
+ }
+
+ QJsonObject o;
+ o.insert(QLatin1String("version"), qt_version << 8);
+ o.insert(QLatin1String("debug"), bool(qt_archRequirements & 1));
+ o.insert(QLatin1String("archreq"), qt_archRequirements);
+
+ // convert the top-level map integer keys
+ for (auto it : metadata.toMap()) {
+ QString key;
+ if (it.first.isInteger()) {
+ switch (it.first.toInteger()) {
+#define CONVERT_TO_STRING(IntKey, StringKey, Description) \
+ case int(IntKey): key = QStringLiteral(StringKey); break;
+ QT_PLUGIN_FOREACH_METADATA(CONVERT_TO_STRING)
+#undef CONVERT_TO_STRING
+
+ case int(QtPluginMetaDataKeys::Requirements):
+ // special case: recreate the debug key
+ o.insert(QLatin1String("debug"), bool(it.second.toInteger() & 1));
+ key = QStringLiteral("archreq");
+ break;
+ }
+ } else {
+ key = it.first.toString();
+ }
+
+ if (!key.isEmpty())
+ o.insert(key, it.second.toJsonValue());
+ }
+ return QJsonDocument(o);
+}
+
+QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype sectionSize, QString *errMsg)
{
raw += metaDataSignatureLength();
sectionSize -= metaDataSignatureLength();
- // the size of the embedded JSON object can be found 8 bytes into the data (see qjson_p.h)
- uint size = qFromLittleEndian<uint>(raw + 8);
- // but the maximum size of binary JSON is 128 MB
- size = qMin(size, 128U * 1024 * 1024);
- // and it doesn't include the size of the header (8 bytes)
- size += 8;
- // finally, it can't be bigger than the file or section size
- size = qMin(sectionSize, qsizetype(size));
-
- QByteArray json(raw, size);
- return QJsonDocument::fromBinaryData(json);
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ if (Q_UNLIKELY(raw[-1] == ' ')) {
+ // the size of the embedded JSON object can be found 8 bytes into the data (see qjson_p.h)
+ uint size = qFromLittleEndian<uint>(raw + 8);
+ // but the maximum size of binary JSON is 128 MB
+ size = qMin(size, 128U * 1024 * 1024);
+ // and it doesn't include the size of the header (8 bytes)
+ size += 8;
+ // finally, it can't be bigger than the file or section size
+ size = qMin(sectionSize, qsizetype(size));
+
+ QByteArray json(raw, size);
+ return QJsonDocument::fromBinaryData(json);
+ }
+#endif
+
+ return jsonFromCborMetaData(raw, sectionSize, errMsg);
}
class QFactoryLoaderPrivate : public QObjectPrivate
@@ -141,35 +208,33 @@ void QFactoryLoader::update()
QDir::Files);
QLibraryPrivate *library = 0;
-#ifdef Q_OS_MAC
- // Loading both the debug and release version of the cocoa plugins causes the objective-c runtime
- // to print "duplicate class definitions" warnings. Detect if QFactoryLoader is about to load both,
- // skip one of them (below).
- //
- // ### FIXME find a proper solution
- //
- 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));
#ifdef Q_OS_MAC
- if (isLoadingDebugAndReleaseCocoa) {
-#ifdef QT_DEBUG
- if (fileName.contains(QLatin1String("libqcocoa.dylib")))
- continue; // Skip release plugin in debug mode
-#else
- if (fileName.contains(QLatin1String("libqcocoa_debug.dylib")))
- continue; // Skip debug plugin in release mode
-#endif
+ const bool isDebugPlugin = fileName.endsWith(QLatin1String("_debug.dylib"));
+ const bool isDebugLibrary =
+ #ifdef QT_DEBUG
+ true;
+ #else
+ false;
+ #endif
+
+ // Skip mismatching plugins so that we don't end up loading both debug and release
+ // versions of the same Qt libraries (due to the plugin's dependencies).
+ if (isDebugPlugin != isDebugLibrary)
+ continue;
+#elif defined(Q_PROCESSOR_X86)
+ if (fileName.endsWith(QLatin1String(".avx2")) || fileName.endsWith(QLatin1String(".avx512"))) {
+ // ignore AVX2-optimized file, we'll do a bait-and-switch to it later
+ continue;
}
#endif
if (qt_debug_component()) {
qDebug() << "QFactoryLoader::QFactoryLoader() looking at" << fileName;
}
- Q_TRACE(qfactoryloader_update, fileName);
+ Q_TRACE(QFactoryLoader_update, fileName);
library = QLibraryPrivate::findOrCreate(QFileInfo(fileName).canonicalFilePath());
if (!library->isPlugin()) {
diff --git a/src/corelib/plugin/qfactoryloader_p.h b/src/corelib/plugin/qfactoryloader_p.h
index fe722999ae..7815ea0b5d 100644
--- a/src/corelib/plugin/qfactoryloader_p.h
+++ b/src/corelib/plugin/qfactoryloader_p.h
@@ -56,6 +56,7 @@
#include "QtCore/qobject.h"
#include "QtCore/qstringlist.h"
+#include "QtCore/qcborvalue.h"
#include "QtCore/qjsonobject.h"
#include "QtCore/qjsondocument.h"
#include "QtCore/qmap.h"
@@ -66,7 +67,7 @@
QT_BEGIN_NAMESPACE
-QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype size);
+QJsonDocument qJsonFromRawLibraryMetaData(const char *raw, qsizetype size, QString *errMsg);
class QFactoryLoaderPrivate;
class Q_CORE_EXPORT QFactoryLoader : public QObject
diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp
index 5256a09ff2..aa63ed1a6b 100644
--- a/src/corelib/plugin/qlibrary.cpp
+++ b/src/corelib/plugin/qlibrary.cpp
@@ -268,7 +268,7 @@ static bool findPatternUnloaded(const QString &library, QLibraryPrivate *lib)
*/
bool hasMetaData = false;
qsizetype pos = 0;
- char pattern[] = "qTMETADATA ";
+ char pattern[] = "qTMETADATA ";
pattern[0] = 'Q'; // Ensure the pattern "QTMETADATA" is not found in this library should QPluginLoader ever encounter it.
const ulong plen = qstrlen(pattern);
#if defined (Q_OF_ELF) && defined(Q_CC_GNU)
@@ -314,10 +314,14 @@ static bool findPatternUnloaded(const QString &library, QLibraryPrivate *lib)
bool ret = false;
- if (pos >= 0) {
- if (hasMetaData) {
- const char *data = filedata + pos;
- QJsonDocument doc = qJsonFromRawLibraryMetaData(data, qsizetype(fdlen));
+ if (pos >= 0 && hasMetaData) {
+ const char *data = filedata + pos;
+ QString errMsg;
+ QJsonDocument doc = qJsonFromRawLibraryMetaData(data, fdlen, &errMsg);
+ if (doc.isNull()) {
+ qWarning("Found invalid metadata in lib %s: %s",
+ qPrintable(library), qPrintable(errMsg));
+ } else {
lib->metaData = doc.object();
if (qt_debug_component())
qWarning("Found metadata in lib %s, metadata=\n%s\n",
@@ -544,7 +548,7 @@ bool QLibraryPrivate::load()
if (fileName.isEmpty())
return false;
- Q_TRACE(qlibraryprivate_load_entry, fileName);
+ Q_TRACE(QLibraryPrivate_load_entry, fileName);
bool ret = load_sys();
if (qt_debug_component()) {
@@ -562,7 +566,7 @@ bool QLibraryPrivate::load()
installCoverageTool(this);
}
- Q_TRACE(qlibraryprivate_load_exit, ret);
+ Q_TRACE(QLibraryPrivate_load_exit, ret);
return ret;
}
@@ -679,20 +683,26 @@ bool QLibrary::isLibrary(const QString &fileName)
#endif
}
-typedef const char * (*QtPluginQueryVerificationDataFunction)();
-
-static bool qt_get_metadata(QtPluginQueryVerificationDataFunction pfn, QLibraryPrivate *priv)
+static bool qt_get_metadata(QLibraryPrivate *priv, QString *errMsg)
{
- const char *szData = 0;
- if (!pfn)
- return false;
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ auto getMetaData = [](QFunctionPointer fptr) {
+ auto f = reinterpret_cast<const char * (*)()>(fptr);
+ return qMakePair<const char *, size_t>(f(), INT_MAX);
+ };
+#else
+ auto getMetaData = [](QFunctionPointer fptr) {
+ auto f = reinterpret_cast<QPair<const char *, size_t> (*)()>(fptr);
+ return f();
+ };
+#endif
- szData = pfn();
- if (!szData)
+ QFunctionPointer pfn = priv->resolve("qt_plugin_query_metadata");
+ if (!pfn)
return false;
- // the data is already loaded, so the size doesn't matter
- QJsonDocument doc = qJsonFromRawLibraryMetaData(szData, INT_MAX);
+ auto metaData = getMetaData(pfn);
+ QJsonDocument doc = qJsonFromRawLibraryMetaData(metaData.first, metaData.second, errMsg);
if (doc.isNull())
return false;
priv->metaData = doc.object();
@@ -735,9 +745,7 @@ void QLibraryPrivate::updatePluginState()
} else {
// library is already loaded (probably via QLibrary)
// simply get the target function and call it.
- QtPluginQueryVerificationDataFunction getMetaData = NULL;
- getMetaData = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_metadata");
- success = qt_get_metadata(getMetaData, this);
+ success = qt_get_metadata(this, &errorString);
}
if (!success) {
diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp
index 23b9ad6434..e03814984c 100644
--- a/src/corelib/plugin/qlibrary_unix.cpp
+++ b/src/corelib/plugin/qlibrary_unix.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -43,6 +44,7 @@
#include "qlibrary_p.h"
#include <qcoreapplication.h>
#include <private/qfilesystementry_p.h>
+#include <private/qsimd_p.h>
#include <dlfcn.h>
@@ -155,7 +157,7 @@ bool QLibraryPrivate::load_sys()
// Do not unload the library during dlclose(). Consequently, the
// library's specific static variables are not reinitialized if the
// library is reloaded with dlopen() at a later time.
-#ifdef RTLD_NODELETE
+#if defined(RTLD_NODELETE) && !defined(Q_OS_ANDROID)
if (loadHints & QLibrary::PreventUnloadHint) {
dlFlags |= RTLD_NODELETE;
}
@@ -178,6 +180,29 @@ bool QLibraryPrivate::load_sys()
prefixes.append(QString());
}
+#if defined(Q_PROCESSOR_X86) && !defined(Q_OS_DARWIN)
+ if (qCpuHasFeature(ArchHaswell)) {
+ auto transform = [](QStringList &list, void (*f)(QString *)) {
+ QStringList tmp;
+ qSwap(tmp, list);
+ list.reserve(tmp.size() * 2);
+ for (const QString &s : qAsConst(tmp)) {
+ QString modifiedPath = s;
+ f(&modifiedPath);
+ list.append(modifiedPath);
+ list.append(s);
+ }
+ };
+ if (pluginState == IsAPlugin) {
+ // add ".avx2" to each suffix in the list
+ transform(suffixes, [](QString *s) { s->append(QLatin1String(".avx2")); });
+ } else {
+ // prepend "haswell/" to each prefix in the list
+ transform(prefixes, [](QString *s) { s->prepend(QLatin1String("haswell/")); });
+ }
+ }
+#endif
+
bool retry = true;
for(int prefix = 0; retry && !pHnd && prefix < prefixes.size(); prefix++) {
for(int suffix = 0; retry && !pHnd && suffix < suffixes.size(); suffix++) {
diff --git a/src/corelib/plugin/qlibrary_win.cpp b/src/corelib/plugin/qlibrary_win.cpp
index 9368e53b3f..05a93d467e 100644
--- a/src/corelib/plugin/qlibrary_win.cpp
+++ b/src/corelib/plugin/qlibrary_win.cpp
@@ -97,10 +97,10 @@ bool QLibraryPrivate::load_sys()
for (const QString &attempt : qAsConst(attempts)) {
#ifndef Q_OS_WINRT
- pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16());
+ pHnd = LoadLibrary(reinterpret_cast<const wchar_t*>(QDir::toNativeSeparators(attempt).utf16()));
#else // Q_OS_WINRT
QString path = QDir::toNativeSeparators(QDir::current().relativeFilePath(attempt));
- pHnd = LoadPackagedLibrary((LPCWSTR)path.utf16(), 0);
+ pHnd = LoadPackagedLibrary(reinterpret_cast<LPCWSTR>(path.utf16()), 0);
if (pHnd)
qualifiedFileName = attempt;
#endif // !Q_OS_WINRT
diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h
index b644d47856..5aca22497a 100644
--- a/src/corelib/plugin/qplugin.h
+++ b/src/corelib/plugin/qplugin.h
@@ -55,6 +55,21 @@ QT_BEGIN_NAMESPACE
# endif
#endif
+inline constexpr unsigned char qPluginArchRequirements()
+{
+ return 0
+#ifndef QT_NO_DEBUG
+ | 1
+#endif
+#ifdef __AVX2__
+ | 2
+# ifdef __AVX512F__
+ | 4
+# endif
+#endif
+ ;
+}
+
typedef QObject *(*QtPluginInstanceFunction)();
typedef const char *(*QtPluginMetaDataFunction)();
@@ -90,7 +105,6 @@ void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin);
# define QT_PLUGIN_METADATA_SECTION \
__declspec(allocate(".qtmetadata"))
#else
-# define QT_PLUGIN_VERIFICATION_SECTION
# define QT_PLUGIN_METADATA_SECTION
#endif
@@ -105,11 +119,21 @@ void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin);
}; \
static Static##PLUGIN##PluginInstance static##PLUGIN##Instance;
+#if defined(QT_PLUGIN_RESOURCE_INIT_FUNCTION)
+# define QT_PLUGIN_RESOURCE_INIT \
+ extern void QT_PLUGIN_RESOURCE_INIT_FUNCTION(); \
+ QT_PLUGIN_RESOURCE_INIT_FUNCTION();
+#else
+# define QT_PLUGIN_RESOURCE_INIT
+#endif
+
#define Q_PLUGIN_INSTANCE(IMPLEMENTATION) \
{ \
static QT_PREPEND_NAMESPACE(QPointer)<QT_PREPEND_NAMESPACE(QObject)> _instance; \
- if (!_instance) \
+ if (!_instance) { \
+ QT_PLUGIN_RESOURCE_INIT \
_instance = new IMPLEMENTATION; \
+ } \
return _instance; \
}
diff --git a/src/corelib/plugin/qplugin_p.h b/src/corelib/plugin/qplugin_p.h
new file mode 100644
index 0000000000..717129268b
--- /dev/null
+++ b/src/corelib/plugin/qplugin_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://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 QPLUGIN_P_H
+#define QPLUGIN_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qglobal_p.h>
+
+QT_BEGIN_NAMESPACE
+
+enum class QtPluginMetaDataKeys {
+ QtVersion,
+ Requirements,
+ IID,
+ ClassName,
+ MetaData
+};
+
+// F(IntKey, StringKey, Description)
+// Keep this list sorted in the order moc should output.
+#define QT_PLUGIN_FOREACH_METADATA(F) \
+ F(QtPluginMetaDataKeys::IID, "IID", "Plugin's Interface ID") \
+ F(QtPluginMetaDataKeys::ClassName, "className", "Plugin class name") \
+ F(QtPluginMetaDataKeys::MetaData, "MetaData", "Other meta data")
+
+QT_END_NAMESPACE
+
+#endif // QPLUGIN_P_H
diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp
index 83cbcd2b44..0f94bb6adf 100644
--- a/src/corelib/plugin/qpluginloader.cpp
+++ b/src/corelib/plugin/qpluginloader.cpp
@@ -475,10 +475,19 @@ QVector<QStaticPlugin> QPluginLoader::staticPlugins()
*/
QJsonObject QStaticPlugin::metaData() const
{
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
// the data is already loaded, so this doesn't matter
qsizetype rawMetaDataSize = INT_MAX;
+ const char *ptr = rawMetaData();
+#else
+ auto ptr = static_cast<const char *>(rawMetaData);
+#endif
- return qJsonFromRawLibraryMetaData(rawMetaData(), rawMetaDataSize).object();
+ QString errMsg;
+ QJsonDocument doc = qJsonFromRawLibraryMetaData(ptr, rawMetaDataSize, &errMsg);
+ Q_ASSERT(doc.isObject());
+ Q_ASSERT(errMsg.isEmpty());
+ return doc.object();
}
QT_END_NAMESPACE
diff --git a/src/corelib/plugin/qsystemlibrary.cpp b/src/corelib/plugin/qsystemlibrary.cpp
index 7c80fbbd42..1f8cef790c 100644
--- a/src/corelib/plugin/qsystemlibrary.cpp
+++ b/src/corelib/plugin/qsystemlibrary.cpp
@@ -121,7 +121,7 @@ HINSTANCE QSystemLibrary::load(const wchar_t *libraryName, bool onlySystemDirect
fullPathAttempt.append(QLatin1Char('\\'));
}
fullPathAttempt.append(fileName);
- HINSTANCE inst = ::LoadLibrary((const wchar_t *)fullPathAttempt.utf16());
+ HINSTANCE inst = ::LoadLibrary(reinterpret_cast<const wchar_t *>(fullPathAttempt.utf16()));
if (inst != 0)
return inst;
}
diff --git a/src/corelib/qtcore.tracepoints b/src/corelib/qtcore.tracepoints
index e6b666ac74..33734a4274 100644
--- a/src/corelib/qtcore.tracepoints
+++ b/src/corelib/qtcore.tracepoints
@@ -1,5 +1,34 @@
-qcoreapplicationprivate_init_entry()
-qcoreapplicationprivate_init_exit()
-qfactoryloader_update(const QString &fileName)
-qlibraryprivate_load_entry(const QString &fileName)
-qlibraryprivate_load_exit(bool success)
+QCoreApplicationPrivate_init_entry()
+QCoreApplicationPrivate_init_exit()
+
+QFactoryLoader_update(const QString &fileName)
+
+QLibraryPrivate_load_entry(const QString &fileName)
+QLibraryPrivate_load_exit(bool success)
+
+QEvent_ctor(QEvent *event, int type)
+QEvent_dtor(QEvent *event, int type)
+
+QCoreApplication_postEvent_entry(QObject *receiver, QEvent *event, int type)
+QCoreApplication_postEvent_event_compressed(QObject *receiver, QEvent *event)
+QCoreApplication_postEvent_event_posted(QObject *receiver, QEvent *event, int type)
+
+QCoreApplication_sendEvent(QObject *receiver, QEvent *event, int type)
+QCoreApplication_sendSpontaneousEvent(QObject *receiver, QEvent *event, int type)
+
+QCoreApplication_notify_entry(QObject *receiver, QEvent *event, int type)
+QCoreApplication_notify_event_filtered(QObject *receiver, QEvent *event, int type)
+QCoreApplication_notify_before_delivery(QObject *receiver, QEvent *event, int type)
+QCoreApplication_notify_after_delivery(QObject *receiver, QEvent *event, int type, bool consumed)
+
+QObject_ctor(QObject *object)
+QObject_dtor(QObject *object)
+
+QMetaObject_activate_begin_signal(QObject *sender, int signalIndex)
+QMetaObject_activate_end_signal(QObject *sender, int signalIndex)
+QMetaObject_activate_begin_slot(QObject *receiver, int slotIndex)
+QMetaObject_activate_end_slot(QObject *receiver, int slotIndex)
+QMetaObject_activate_begin_slot_functor(void *slotObject)
+QMetaObject_activate_end_slot_functor(void *slotObject)
+QMetaObject_activate_begin_declarative_signal(QObject *sender, int signalIndex)
+QMetaObject_activate_end_declarative_signal(QObject *sender, int signalIndex)
diff --git a/src/corelib/serialization/qcborarray.cpp b/src/corelib/serialization/qcborarray.cpp
new file mode 100644
index 0000000000..c56536cdb1
--- /dev/null
+++ b/src/corelib/serialization/qcborarray.cpp
@@ -0,0 +1,1221 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://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 "qcborarray.h"
+#include "qcborvalue_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QtCbor;
+
+/*!
+ \class QCborArray
+ \inmodule QtCore
+ \ingroup cbor
+ \reentrant
+ \since 5.12
+
+ \brief The QCborArray class is used to hold an array of CBOR elements.
+
+ This class can be used to hold one sequential container in CBOR (an array).
+ CBOR is the Concise Binary Object Representation, a very compact form of
+ binary data encoding that is a superset of JSON. It was created by the IETF
+ Constrained RESTful Environments (CoRE) WG, which has used it in many new
+ RFCs. It is meant to be used alongside the
+ \l{https://tools.ietf.org/html/rfc7252}{CoAP protocol}.
+
+ QCborArray is very similar to \l QVariantList and \l QJsonArray and its API
+ is almost identical to those two classes. It can also be converted to and
+ from those two, though there may be loss of information in some
+ conversions.
+
+ \sa QCborValue, QCborMap, QJsonArray, QList, QVector
+ */
+
+/*!
+ \typedef QCborArray::size_type
+
+ A typedef to qsizetype.
+ */
+
+/*!
+ \typedef QCborArray::difference_type
+
+ A typedef to qsizetype.
+ */
+
+/*!
+ \typedef QCborArray::value_type
+
+ The type of values that can be held in a QCborArray: that is, QCborValue.
+ */
+
+/*!
+ \typedef QCborArray::pointer
+
+ A typedef to \c{QCborValue *}, for compatibility with generic algorithms.
+ */
+
+/*!
+ \typedef QCborArray::const_pointer
+
+ A typedef to \c{const QCborValue *}, for compatibility with generic algorithms.
+ */
+
+/*!
+ \typedef QCborArray::reference
+
+ A typedef to \c{QCborValue &}, for compatibility with generic algorithms.
+ */
+
+/*!
+ \typedef QCborArray::const_reference
+
+ A typedef to \c{const QCborValue &}, for compatibility with generic algorithms.
+ */
+
+/*!
+ Constructs an empty QCborArray.
+ */
+QCborArray::QCborArray() noexcept
+ : d(nullptr)
+{
+}
+
+/*!
+ Copies the contents of \a other into this object.
+ */
+QCborArray::QCborArray(const QCborArray &other) noexcept
+ : d(other.d)
+{
+}
+
+/*!
+ \fn QCborArray::QCborArray(std::initializer_list<QCborValue> args)
+
+ Initializes this QCborArray from the C++ brace-enclosed list found in \a
+ args, as in the following example:
+
+ \code
+ QCborArray a = { null, 0, 1, 1.5, 2, "Hello", QByteArray("World") };
+ \endcode
+ */
+
+/*!
+ Destroys this QCborArray and frees any associated resources.
+ */
+QCborArray::~QCborArray()
+{
+}
+
+/*!
+ Replaces the contents of this array with that found in \a other, then
+ returns a reference to this object.
+ */
+QCborArray &QCborArray::operator=(const QCborArray &other) noexcept
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ \fn void QCborArray::swap(QCborArray &other)
+
+ Swaps the contents of this object and \a other.
+ */
+
+/*!
+ \fn QCborValue QCborArray::toCborValue() const
+
+ Explicitly construcuts a \l QCborValue object that represents this array.
+ This function is usually not necessary since QCborValue has a constructor
+ for QCborArray, so the conversion is implicit.
+
+ Converting QCborArray to QCborValue allows it to be used in any context
+ where QCborValues can be used, including as items in QCborArrays and as keys
+ and mapped types in QCborMap. Converting an array to QCborValue allows
+ access to QCborValue::toCbor().
+
+ \sa QCborValue::QCborValue(const QCborArray &)
+ */
+
+/*!
+ Returns the size of this array.
+
+ \sa isEmpty()
+ */
+qsizetype QCborArray::size() const noexcept
+{
+ return d ? d->elements.size() : 0;
+}
+
+/*!
+ Empties this array.
+
+ \sa isEmpty()
+ */
+void QCborArray::clear()
+{
+ d.reset();
+}
+
+/*!
+ \fn bool QCborArray::isEmpty() const
+
+ Returns true if this QCborArray is empty (that is if size() is 0).
+
+ \sa size(), clear()
+ */
+
+/*!
+ Returns the QCborValue element at position \a i in the array.
+
+ If the array is smaller than \a i elements, this function returns a
+ QCborValue containing an undefined value. For that reason, it is not
+ possible with this function to tell apart the situation where the array is
+ not large enough from the case where the array starts with an undefined
+ value.
+
+ \sa operator[](), first(), last(), insert(), prepend(), append(),
+ removeAt(), takeAt()
+ */
+QCborValue QCborArray::at(qsizetype i) const
+{
+ if (!d || size_t(i) >= size_t(size()))
+ return QCborValue();
+ return d->valueAt(i);
+}
+
+/*!
+ \fn QCborValue QCborArray::first() const
+
+ Returns the first QCborValue of this array.
+
+ If the array is empty, this function returns a QCborValue containing an
+ undefined value. For that reason, it is not possible with this function to
+ tell apart the situation where the array is not large enough from the case
+ where the array ends with an undefined value.
+
+ \sa operator[](), at(), last(), insert(), prepend(), append(),
+ removeAt(), takeAt()
+ */
+
+/*!
+ \fn QCborValue QCborArray::last() const
+
+ Returns the last QCborValue of this array.
+
+ If the array is empty, this function returns a QCborValue containing an
+ undefined value. For that reason, it is not possible with this function to
+ tell apart the situation where the array is not large enough from the case
+ where the array ends with an undefined value.
+
+ \sa operator[](), at(), first(), insert(), prepend(), append(),
+ removeAt(), takeAt()
+ */
+
+/*!
+ \fn QCborValue QCborArray::operator[](qsizetype i) const
+
+ Returns the QCborValue element at position \a i in the array.
+
+ If the array is smaller than \a i elements, this function returns a
+ QCborValue containing an undefined value. For that reason, it is not
+ possible with this function to tell apart the situation where the array is
+ not large enough from the case where the array contains an undefined value
+ at position \a i.
+
+ \sa at(), first(), last(), insert(), prepend(), append(),
+ removeAt(), takeAt()
+ */
+
+/*!
+ \fn QCborValueRef QCborArray::first()
+
+ Returns a reference to the first QCborValue of this array. The array must
+ not be empty.
+
+ QCborValueRef has the exact same API as \l QCborValue, with one important
+ difference: if you assign new values to it, this map will be updated with
+ that new value.
+
+ \sa operator[](), at(), last(), insert(), prepend(), append(),
+ removeAt(), takeAt()
+ */
+
+/*!
+ \fn QCborValueRef QCborArray::last()
+
+ Returns a reference to the last QCborValue of this array. The array must
+ not be empty.
+
+ QCborValueRef has the exact same API as \l QCborValue, with one important
+ difference: if you assign new values to it, this map will be updated with
+ that new value.
+
+ \sa operator[](), at(), first(), insert(), prepend(), append(),
+ removeAt(), takeAt()
+ */
+
+/*!
+ \fn QCborValueRef QCborArray::operator[](qsizetype i)
+
+ Returns a reference to the QCborValue element at position \a i in the
+ array. Indices beyond the end of the array will grow the array, filling
+ with undefined entries, until it has an entry at the specified index.
+
+ QCborValueRef has the exact same API as \l QCborValue, with one important
+ difference: if you assign new values to it, this map will be updated with
+ that new value.
+
+ \sa at(), first(), last(), insert(), prepend(), append(),
+ removeAt(), takeAt()
+ */
+
+/*!
+ \fn void QCborArray::insert(qsizetype i, const QCborValue &value)
+ \fn void QCborArray::insert(qsizetype i, QCborValue &&value)
+
+ Inserts \a value into the array at position \a i in this array. If \a i is
+ -1, the entry is appended to the array. Pads the array with invalid entries
+ if \a i is greater than the prior size of the array.
+
+ \sa at(), operator[](), first(), last(), prepend(), append(),
+ removeAt(), takeAt(), extract()
+ */
+void QCborArray::insert(qsizetype i, const QCborValue &value)
+{
+ if (i < 0) {
+ Q_ASSERT(i == -1);
+ i = size();
+ detach(i + 1);
+ } else {
+ d = QCborContainerPrivate::grow(d.data(), i); // detaches
+ }
+ d->insertAt(i, value);
+}
+
+void QCborArray::insert(qsizetype i, QCborValue &&value)
+{
+ if (i < 0) {
+ Q_ASSERT(i == -1);
+ i = size();
+ detach(i + 1);
+ } else {
+ d = QCborContainerPrivate::grow(d.data(), i); // detaches
+ }
+ d->insertAt(i, value, QCborContainerPrivate::MoveContainer);
+ QCborContainerPrivate::resetValue(value);
+}
+
+/*!
+ \fn QCborValue QCborArray::extract(Iterator it)
+ \fn QCborValue QCborArray::extract(ConstIterator it)
+
+ Extracts a value from the array at the position indicated by iterator \a it
+ and returns the value so extracted.
+
+ \sa insert(), erase(), takeAt(), removeAt()
+ */
+QCborValue QCborArray::extract(iterator it)
+{
+ detach();
+
+ QCborValue v = d->extractAt(it.item.i);
+ d->removeAt(it.item.i);
+ return v;
+}
+
+/*!
+ \fn void QCborArray::prepend(const QCborValue &value)
+ \fn void QCborArray::prepend(QCborValue &&value)
+
+ Prepends \a value into the array before any other elements it may already
+ contain.
+
+ \sa at(), operator[](), first(), last(), insert(), append(),
+ removeAt(), takeAt()
+ */
+
+/*!
+ \fn void QCborArray::append(const QCborValue &value)
+ \fn void QCborArray::append(QCborValue &&value)
+
+ Appends \a value into the array after all other elements it may already
+ contain.
+
+ \sa at(), operator[](), first(), last(), insert(), prepend(),
+ removeAt(), takeAt()
+ */
+
+/*!
+ Removes the item at position \a i from the array. The array must have more
+ than \a i elements before the removal.
+
+ \sa takeAt(), removeFirst(), removeLast(), at(), operator[](), insert(),
+ prepend(), append()
+ */
+void QCborArray::removeAt(qsizetype i)
+{
+ detach(size());
+ d->removeAt(i);
+}
+
+/*!
+ \fn QCborValue QCborArray::takeAt(qsizetype i)
+
+ Removes the item at position \a i from the array and returns it. The array
+ must have more than \a i elements before the removal.
+
+ \sa removeAt(), removeFirst(), removeLast(), at(), operator[](), insert(),
+ prepend(), append()
+ */
+
+/*!
+ \fn void QCborArray::removeFirst()
+
+ Removes the first item in the array, making the second element become the
+ first. The array must not be empty before this call.
+
+ \sa removeAt(), takeFirst(), removeLast(), at(), operator[](), insert(),
+ prepend(), append()
+ */
+
+/*!
+ \fn void QCborArray::removeLast()
+
+ Removes the last item in the array. The array must not be empty before this
+ call.
+
+ \sa removeAt(), takeLast(), removeFirst(), at(), operator[](), insert(),
+ prepend(), append()
+ */
+
+/*!
+ \fn void QCborArray::takeFirst()
+
+ Removes the first item in the array and returns it, making the second
+ element become the first. The array must not be empty before this call.
+
+ \sa takeAt(), removeFirst(), removeLast(), at(), operator[](), insert(),
+ prepend(), append()
+ */
+
+/*!
+ \fn void QCborArray::takeLast()
+
+ Removes the last item in the array and returns it. The array must not be
+ empty before this call.
+
+ \sa takeAt(), removeLast(), removeFirst(), at(), operator[](), insert(),
+ prepend(), append()
+ */
+
+/*!
+ Returns true if this array contains an element that is equal to \a value.
+ */
+bool QCborArray::contains(const QCborValue &value) const
+{
+ for (qsizetype i = 0; i < size(); ++i) {
+ int cmp = d->compareElement(i, value);
+ if (cmp == 0)
+ return true;
+ }
+ return false;
+}
+
+/*!
+ \fn int QCborArray::compare(const QCborArray &other) const
+
+ Compares this array and \a other, comparing each element in sequence, and
+ returns an integer that indicates whether this array should be sorted
+ before (if the result is negative) or after \a other (if the result is
+ positive). If this function returns 0, the two arrays are equal and contain
+ the same elements.
+
+ For more information on CBOR sorting order, see QCborValue::compare().
+
+ \sa QCborValue::compare(), QCborMap::compare(), operator==()
+ */
+
+/*!
+ \fn bool QCborArray::operator==(const QCborArray &other) const
+
+ Compares this array and \a other, comparing each element in sequence, and
+ returns true if both arrays contains the same elements, false otherwise.
+
+ For more information on CBOR equality in Qt, see, QCborValue::compare().
+
+ \sa compare(), QCborValue::operator==(), QCborMap::operator==(),
+ operator!=(), operator<()
+ */
+
+/*!
+ \fn bool QCborArray::operator!=(const QCborArray &other) const
+
+ Compares this array and \a other, comparing each element in sequence, and
+ returns true if the two arrays' contents are different, false otherwise.
+
+ For more information on CBOR equality in Qt, see, QCborValue::compare().
+
+ \sa compare(), QCborValue::operator==(), QCborMap::operator==(),
+ operator==(), operator<()
+ */
+
+/*!
+ \fn bool QCborArray::operator<(const QCborArray &other) const
+
+ Compares this array and \a other, comparing each element in sequence, and
+ returns true if this array should be sorted before \a other, false
+ otherwise.
+
+ For more information on CBOR sorting order, see QCborValue::compare().
+
+ \sa compare(), QCborValue::operator==(), QCborMap::operator==(),
+ operator==(), operator!=()
+ */
+
+/*!
+ \typedef QCborArray::iterator
+
+ A synonym to QCborArray::Iterator.
+ */
+
+/*!
+ \typedef QCborArray::const_iterator
+
+ A synonym to QCborArray::ConstIterator.
+ */
+
+/*!
+ \fn QCborArray::iterator QCborArray::begin()
+
+ Returns an array iterator pointing to the first item in this array. If the
+ array is empty, then this function returns the same as end().
+
+ \sa constBegin(), end()
+ */
+
+/*!
+ \fn QCborArray::const_iterator QCborArray::begin() const
+
+ Returns an array iterator pointing to the first item in this array. If the
+ array is empty, then this function returns the same as end().
+
+ \sa constBegin(), constEnd()
+ */
+
+/*!
+ \fn QCborArray::const_iterator QCborArray::cbegin() const
+
+ Returns an array iterator pointing to the first item in this array. If the
+ array is empty, then this function returns the same as end().
+
+ \sa constBegin(), constEnd()
+ */
+
+/*!
+ \fn QCborArray::const_iterator QCborArray::constBegin() const
+
+ Returns an array iterator pointing to the first item in this array. If the
+ array is empty, then this function returns the same as end().
+
+ \sa begin(), constEnd()
+ */
+
+/*!
+ \fn QCborArray::iterator QCborArray::end()
+
+ Returns an array iterator pointing to just after the last element in this
+ array.
+
+ \sa begin(), constEnd()
+ */
+
+/*!
+ \fn QCborArray::const_iterator QCborArray::end() const
+
+ Returns an array iterator pointing to just after the last element in this
+ array.
+
+ \sa constBegin(), constEnd()
+ */
+
+/*!
+ \fn QCborArray::const_iterator QCborArray::cend() const
+
+ Returns an array iterator pointing to just after the last element in this
+ array.
+
+ \sa constBegin(), constEnd()
+ */
+
+/*!
+ \fn QCborArray::const_iterator QCborArray::constEnd() const
+
+ Returns an array iterator pointing to just after the last element in this
+ array.
+
+ \sa constBegin(), end()
+ */
+
+/*!
+ \fn QCborArray::iterator QCborArray::insert(iterator before, const QCborValue &value)
+ \fn QCborArray::iterator QCborArray::insert(const_iterator before, const QCborValue &value)
+ \overload
+
+ Inserts \a value into this array before element \a before and returns an
+ array iterator pointing to the just-inserted element.
+
+ \sa erase(), removeAt(), prepend(), append()
+ */
+
+/*!
+ \fn QCborArray::iterator QCborArray::erase(iterator it)
+ \fn QCborArray::iterator QCborArray::erase(const_iterator it)
+
+ Removes the element pointed to by the array iterator \a it from this array,
+ then returns an iterator to the next element (the one that took the same
+ position in the array that \a it used to occupy).
+
+ \sa insert(), removeAt(), takeAt(), takeFirst(), takeLast()
+ */
+
+/*!
+ \fn void QCborArray::push_back(const QCborValue &t)
+
+ Synonym for append(). This function is provided for compatibility with
+ generic code that uses the Standard Library API.
+
+ Appends the element \a t to this array.
+
+ \sa append(), push_front(), pop_back(), prepend(), insert()
+ */
+
+/*!
+ \fn void QCborArray::push_front(const QCborValue &t)
+
+ Synonym for prepend(). This function is provided for compatibility with
+ generic code that uses the Standard Library API.
+
+ Prepends the element \a t to this array.
+
+ \sa prepend(), push_back(), pop_front(), append(), insert()
+ */
+
+/*!
+ \fn void QCborArray::pop_front()
+
+ Synonym for removeFirst(). This function is provided for compatibility with
+ generic code that uses the Standard Library API.
+
+ Removes the first element of this array. The array must not be empty before
+ the removal
+
+ \sa removeFirst(), takeFirst(), pop_back(), push_front(), prepend(), insert()
+ */
+
+/*!
+ \fn void QCborArray::pop_back()
+
+ Synonym for removeLast(). This function is provided for compatibility with
+ generic code that uses the Standard Library API.
+
+ Removes the last element of this array. The array must not be empty before
+ the removal
+
+ \sa removeLast(), takeLast(), pop_front(), push_back(), append(), insert()
+ */
+
+/*!
+ \fn bool QCborArray::empty() const
+
+ Synonym for isEmpty(). This function is provided for compatibility with
+ generic code that uses the Standard Library API.
+
+ Returns true if this array is empty (size() == 0).
+
+ \sa isEmpty(), size()
+ */
+
+/*!
+ \fn QCborArray QCborArray::operator+(const QCborValue &v) const
+
+ Returns a new QCborArray containing the same elements as this array, plus
+ \a v appended as the last element.
+
+ \sa operator+=(), operator<<(), append()
+ */
+
+/*!
+ \fn QCborArray &QCborArray::operator+=(const QCborValue &v)
+
+ Appends \a v to this array and returns a reference to this array.
+
+ \sa append(), insert(), operator+(), operator<<()
+ */
+
+/*!
+ \fn QCborArray &QCborArray::operator<<(const QCborValue &v)
+
+ Appends \a v to this array and returns a reference to this array.
+
+ \sa append(), insert(), operator+(), operator+=()
+ */
+
+void QCborArray::detach(qsizetype reserved)
+{
+ d = QCborContainerPrivate::detach(d.data(), reserved ? reserved : size());
+}
+
+/*!
+ \class QCborArray::Iterator
+ \inmodule QtCore
+ \ingroup cbor
+ \since 5.12
+
+ \brief The QCborArray::Iterator class provides an STL-style non-const iterator for QCborArray.
+
+ QCborArray::Iterator allows you to iterate over a QCborArray and to modify
+ the array item associated with the iterator. If you want to iterate over a
+ const QCborArray, use QCborArray::ConstIterator instead. It is generally a
+ good practice to use QCborArray::ConstIterator on a non-const QCborArray as
+ well, unless you need to change the QCborArray through the iterator. Const
+ iterators are slightly faster and improve code readability.
+
+ Iterators are initialized by using a QCborArray function like
+ QCborArray::begin(), QCborArray::end(), or QCborArray::insert(). Iteration
+ is only possible after that.
+
+ Most QCborArray functions accept an integer index rather than an iterator.
+ For that reason, iterators are rarely useful in connection with QCborArray.
+ One place where STL-style iterators do make sense is as arguments to
+ \l{generic algorithms}.
+
+ Multiple iterators can be used on the same array. However, be aware that
+ any non-const function call performed on the QCborArray will render all
+ existing iterators undefined.
+
+ \sa QCborArray::ConstIterator
+*/
+
+/*!
+ \typedef QCborArray::Iterator::iterator_category
+
+ A synonym for \e {std::random_access_iterator_tag} indicating this iterator
+ is a random access iterator.
+ */
+
+/*!
+ \typedef QCborArray::Iterator::difference_type
+ \internal
+*/
+
+/*!
+ \typedef QCborArray::Iterator::value_type
+ \internal
+*/
+
+/*!
+ \typedef QCborArray::Iterator::reference
+ \internal
+*/
+
+/*!
+ \typedef QCborArray::Iterator::pointer
+ \internal
+*/
+
+/*!
+ \fn QCborArray::Iterator::Iterator()
+
+ Constructs an uninitialized iterator.
+
+ Functions like operator*() and operator++() should not be called on an
+ uninitialized iterator. Use operator=() to assign a value to it before
+ using it.
+
+ \sa QCborArray::begin(), QCborArray::end()
+*/
+
+/*!
+ \fn QCborArray::Iterator::Iterator(const Iterator &other)
+
+ Makes a copy of \a other.
+ */
+
+/*!
+ \fn QCborArray::Iterator &QCborArray::Iterator::operator=(const Iterator &other)
+
+ Makes this iterator a copy of \a other and returns a reference to this iterator.
+ */
+
+/*!
+ \fn QCborValueRef QCborArray::Iterator::operator*() const
+
+ Returns a modifiable reference to the current item.
+
+ You can change the value of an item by using operator*() on the left side
+ of an assignment.
+
+ The return value is of type QCborValueRef, a helper class for QCborArray
+ and QCborMap. When you get an object of type QCborValueRef, you can use it
+ as if it were a reference to a QCborValue. If you assign to it, the
+ assignment will apply to the element in the QCborArray or QCborMap from
+ which you got the reference.
+*/
+
+/*!
+ \fn QCborValueRef *QCborArray::Iterator::operator->() const
+
+ Returns a pointer to a modifiable reference to the current item.
+*/
+
+/*!
+ \fn QCborValueRef QCborArray::Iterator::operator[](qsizetype j)
+
+ Returns a modifiable reference to the item at a position \a j steps forward
+ from the item pointed to by this iterator.
+
+ This function is provided to make QCborArray iterators behave like C++
+ pointers.
+
+ The return value is of type QCborValueRef, a helper class for QCborArray
+ and QCborMap. When you get an object of type QCborValueRef, you can use it
+ as if it were a reference to a QCborValue. If you assign to it, the
+ assignment will apply to the element in the QCborArray or QCborMap from
+ which you got the reference.
+
+ \sa operator+()
+*/
+
+/*!
+ \fn bool QCborArray::Iterator::operator==(const Iterator &other) const
+ \fn bool QCborArray::Iterator::operator==(const ConstIterator &other) const
+
+ Returns \c true if \a other points to the same entry in the array as this
+ iterator; otherwise returns \c false.
+
+ \sa operator!=()
+*/
+
+/*!
+ \fn bool QCborArray::Iterator::operator!=(const Iterator &other) const
+ \fn bool QCborArray::Iterator::operator!=(const ConstIterator &other) const
+
+ Returns \c true if \a other points to a different entry in the array than
+ this iterator; otherwise returns \c false.
+
+ \sa operator==()
+*/
+
+/*!
+ \fn bool QCborArray::Iterator::operator<(const Iterator& other) const
+ \fn bool QCborArray::Iterator::operator<(const ConstIterator& other) const
+
+ Returns \c true if the entry in the array pointed to by this iterator
+ occurs before the entry pointed to by the \a other iterator.
+*/
+
+/*!
+ \fn bool QCborArray::Iterator::operator<=(const Iterator& other) const
+ \fn bool QCborArray::Iterator::operator<=(const ConstIterator& other) const
+
+ Returns \c true if the entry in the array pointed to by this iterator
+ occurs before or is the same entry as is pointed to by the \a other
+ iterator.
+*/
+
+/*!
+ \fn bool QCborArray::Iterator::operator>(const Iterator& other) const
+ \fn bool QCborArray::Iterator::operator>(const ConstIterator& other) const
+
+ Returns \c true if the entry in the array pointed to by this iterator
+ occurs after the entry pointed to by the \a other iterator.
+ */
+
+/*!
+ \fn bool QCborArray::Iterator::operator>=(const Iterator& other) const
+ \fn bool QCborArray::Iterator::operator>=(const ConstIterator& other) const
+
+ Returns \c true if the entry in the array pointed to by this iterator
+ occurs after or is the same entry as is pointed to by the \a other
+ iterator.
+*/
+
+/*!
+ \fn QCborArray::Iterator &QCborArray::Iterator::operator++()
+
+ The prefix ++ operator, \c{++it}, advances the iterator to the next item in
+ the array and returns this iterator.
+
+ Calling this function on QCborArray::end() leads to undefined results.
+
+ \sa operator--()
+*/
+
+/*!
+ \fn QCborArray::Iterator QCborArray::Iterator::operator++(int)
+ \overload
+
+ The postfix ++ operator, \c{it++}, advances the iterator to the next item
+ in the array and returns an iterator to the previously current item.
+*/
+
+/*!
+ \fn QCborArray::Iterator &QCborArray::Iterator::operator--()
+
+ The prefix -- operator, \c{--it}, makes the preceding item current and
+ returns this iterator.
+
+ Calling this function on QCborArray::begin() leads to undefined results.
+
+ \sa operator++()
+*/
+
+/*!
+ \fn QCborArray::Iterator QCborArray::Iterator::operator--(int)
+ \overload
+
+ The postfix -- operator, \c{it--}, makes the preceding item current and
+ returns an iterator to the previously current item.
+*/
+
+/*!
+ \fn QCborArray::Iterator &QCborArray::Iterator::operator+=(qsizetype j)
+
+ Advances the iterator by \a j positions. If \a j is negative, the iterator
+ goes backward. Returns a reference to this iterator.
+
+ \sa operator-=(), operator+()
+*/
+
+/*!
+ \fn QCborArray::Iterator &QCborArray::Iterator::operator-=(qsizetype j)
+
+ Makes the iterator go back by \a j positions. If \a j is negative, the
+ iterator goes forward. Returns a reference to this iterator.
+
+ \sa operator+=(), operator-()
+*/
+
+/*!
+ \fn QCborArray::Iterator QCborArray::Iterator::operator+(qsizetype j) const
+
+ Returns an iterator to the item at position \a j steps forward from this
+ iterator. If \a j is negative, the iterator goes backward.
+
+ \sa operator-(), operator+=()
+*/
+
+/*!
+ \fn QCborArray::Iterator QCborArray::Iterator::operator-(qsizetype j) const
+
+ Returns an iterator to the item at position \a j steps backward from this
+ iterator. If \a j is negative, the iterator goes forward.
+
+ \sa operator+(), operator-=()
+*/
+
+/*!
+ \fn qsizetype QCborArray::Iterator::operator-(Iterator other) const
+
+ Returns the offset of this iterator relative to \a other.
+*/
+
+/*!
+ \class QCborArray::ConstIterator
+ \inmodule QtCore
+ \ingroup cbor
+ \since 5.12
+
+ \brief The QCborArray::ConstIterator class provides an STL-style const iterator for QCborArray.
+
+ QCborArray::ConstIterator allows you to iterate over a QCborArray. If you
+ want to modify the QCborArray as you iterate over it, use
+ QCborArray::Iterator instead. It is generally good practice to use
+ QCborArray::ConstIterator, even on a non-const QCborArray, when you don't
+ need to change the QCborArray through the iterator. Const iterators are
+ slightly faster and improves code readability.
+
+ Iterators are initialized by using a QCborArray function like
+ QCborArray::begin() or QCborArray::end(). Iteration is only possible after
+ that.
+
+ Most QCborArray functions accept an integer index rather than an iterator.
+ For that reason, iterators are rarely useful in connection with QCborArray.
+ One place where STL-style iterators do make sense is as arguments to
+ \l{generic algorithms}.
+
+ Multiple iterators can be used on the same array. However, be aware that
+ any non-const function call performed on the QCborArray will render all
+ existing iterators undefined.
+
+ \sa QCborArray::Iterator
+*/
+
+/*!
+ \fn QCborArray::ConstIterator::ConstIterator()
+
+ Constructs an uninitialized iterator.
+
+ Functions like operator*() and operator++() should not be called on an
+ uninitialized iterator. Use operator=() to assign a value to it before
+ using it.
+
+ \sa QCborArray::constBegin(), QCborArray::constEnd()
+*/
+
+/*!
+ \fn QCborArray::ConstIterator &QCborArray::ConstIterator::operator=(const ConstIterator &other)
+
+ Makes this iterator a copy of \a other and returns a reference to this iterator.
+*/
+
+/*!
+ \typedef QCborArray::ConstIterator::iterator_category
+
+ A synonym for \e {std::random_access_iterator_tag} indicating this iterator
+ is a random access iterator.
+*/
+
+/*!
+ \typedef QCborArray::ConstIterator::difference_type
+ \internal
+*/
+
+/*!
+ \typedef QCborArray::ConstIterator::value_type
+ \internal
+*/
+
+/*!
+ \typedef QCborArray::ConstIterator::reference
+ \internal
+*/
+
+/*!
+ \typedef QCborArray::ConstIterator::pointer
+ \internal
+*/
+
+/*!
+ \fn QCborArray::ConstIterator::ConstIterator(const ConstIterator &other)
+
+ Constructs a copy of \a other.
+*/
+
+/*!
+ \fn QCborValue QCborArray::ConstIterator::operator*() const
+
+ Returns the current item.
+*/
+
+/*!
+ \fn const QCborValue *QCborArray::ConstIterator::operator->() const
+
+ Returns a pointer to the current item.
+*/
+
+/*!
+ \fn const QCborValueRef QCborArray::ConstIterator::operator[](qsizetype j)
+
+ Returns the item at a position \a j steps forward from the item pointed to
+ by this iterator.
+
+ This function is provided to make QCborArray iterators behave like C++
+ pointers.
+
+ \sa operator+()
+*/
+
+/*!
+ \fn bool QCborArray::ConstIterator::operator==(const Iterator &other) const
+ \fn bool QCborArray::ConstIterator::operator==(const ConstIterator &other) const
+
+ Returns \c true if \a other points to the same entry in the array as this
+ iterator; otherwise returns \c false.
+
+ \sa operator!=()
+*/
+
+/*!
+ \fn bool QCborArray::ConstIterator::operator!=(const Iterator &o) const
+ \fn bool QCborArray::ConstIterator::operator!=(const ConstIterator &o) const
+
+ Returns \c true if \a o points to a different entry in the array than
+ this iterator; otherwise returns \c false.
+
+ \sa operator==()
+*/
+
+/*!
+ \fn bool QCborArray::ConstIterator::operator<(const Iterator &other) const
+ \fn bool QCborArray::ConstIterator::operator<(const ConstIterator &other) const
+
+ Returns \c true if the entry in the array pointed to by this iterator
+ occurs before the entry pointed to by the \a other iterator.
+*/
+
+/*!
+ \fn bool QCborArray::ConstIterator::operator<=(const Iterator &other) const
+ \fn bool QCborArray::ConstIterator::operator<=(const ConstIterator &other) const
+
+ Returns \c true if the entry in the array pointed to by this iterator
+ occurs before or is the same entry as is pointed to by the \a other
+ iterator.
+*/
+
+/*!
+ \fn bool QCborArray::ConstIterator::operator>(const Iterator &other) const
+ \fn bool QCborArray::ConstIterator::operator>(const ConstIterator &other) const
+
+ Returns \c true if the entry in the array pointed to by this iterator
+ occurs after the entry pointed to by the \a other iterator.
+*/
+
+/*!
+ \fn bool QCborArray::ConstIterator::operator>=(const Iterator &other) const
+ \fn bool QCborArray::ConstIterator::operator>=(const ConstIterator &other) const
+
+ Returns \c true if the entry in the array pointed to by this iterator
+ occurs after or is the same entry as is pointed to by the \a other
+ iterator.
+*/
+
+/*!
+ \fn QCborArray::ConstIterator &QCborArray::ConstIterator::operator++()
+
+ The prefix ++ operator, \c{++it}, advances the iterator to the next item in
+ the array and returns this iterator.
+
+ Calling this function on QCborArray::end() leads to undefined results.
+
+ \sa operator--()
+*/
+
+/*!
+ \fn QCborArray::ConstIterator QCborArray::ConstIterator::operator++(int)
+ \overload
+
+ The postfix ++ operator, \c{it++}, advances the iterator to the next item
+ in the array and returns an iterator to the previously current item.
+*/
+
+/*!
+ \fn QCborArray::ConstIterator &QCborArray::ConstIterator::operator--()
+
+ The prefix -- operator, \c{--it}, makes the preceding item current and
+ returns this iterator.
+
+ Calling this function on QCborArray::begin() leads to undefined results.
+
+ \sa operator++()
+*/
+
+/*!
+ \fn QCborArray::ConstIterator QCborArray::ConstIterator::operator--(int)
+ \overload
+
+ The postfix -- operator, \c{it--}, makes the preceding item current and
+ returns an iterator to the previously current item.
+*/
+
+/*!
+ \fn QCborArray::ConstIterator &QCborArray::ConstIterator::operator+=(qsizetype j)
+
+ Advances the iterator by \a j positions. If \a j is negative, the iterator
+ goes backward. Returns a reference to this iterator.
+
+ \sa operator-=(), operator+()
+*/
+
+/*!
+ \fn QCborArray::ConstIterator &QCborArray::ConstIterator::operator-=(qsizetype j)
+
+ Makes the iterator go back by \a j positions. If \a j is negative, the
+ iterator goes forward. Returns a reference to this iterator.
+
+ \sa operator+=(), operator-()
+*/
+
+/*!
+ \fn QCborArray::ConstIterator QCborArray::ConstIterator::operator+(qsizetype j) const
+
+ Returns an iterator to the item at a position \a j steps forward from this
+ iterator. If \a j is negative, the iterator goes backward.
+
+ \sa operator-(), operator+=()
+*/
+
+/*!
+ \fn QCborArray::ConstIterator QCborArray::ConstIterator::operator-(qsizetype j) const
+
+ Returns an iterator to the item at a position \a j steps backward from this
+ iterator. If \a j is negative, the iterator goes forward.
+
+ \sa operator+(), operator-=()
+*/
+
+/*!
+ \fn qsizetype QCborArray::ConstIterator::operator-(ConstIterator other) const
+
+ Returns the offset of this iterator relative to \a other.
+*/
+
+uint qHash(const QCborArray &array, uint seed)
+{
+ return qHashRange(array.begin(), array.end(), seed);
+}
+
+#if !defined(QT_NO_DEBUG_STREAM)
+QDebug operator<<(QDebug dbg, const QCborArray &a)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QCborArray{";
+ const char *comma = "";
+ for (auto v : a) {
+ dbg << comma << v;
+ comma = ", ";
+ }
+ return dbg << '}';
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qcborarray.h b/src/corelib/serialization/qcborarray.h
new file mode 100644
index 0000000000..ed0f4912ba
--- /dev/null
+++ b/src/corelib/serialization/qcborarray.h
@@ -0,0 +1,303 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://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 QCBORARRAY_H
+#define QCBORARRAY_H
+
+#include <QtCore/qcborvalue.h>
+
+#include <initializer_list>
+
+QT_BEGIN_NAMESPACE
+
+class QJsonArray;
+
+class QCborContainerPrivate;
+class Q_CORE_EXPORT QCborArray
+{
+public:
+ class ConstIterator;
+ class Iterator {
+ mutable QCborValueRef item;
+ friend class ConstIterator;
+ friend class QCborArray;
+ Iterator(QCborContainerPrivate *dd, qsizetype ii) : item(dd, ii) {}
+ public:
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef qsizetype difference_type;
+ typedef QCborValue value_type;
+ typedef QCborValueRef reference;
+ typedef QCborValueRef *pointer;
+
+ Q_DECL_CONSTEXPR Iterator() = default;
+ Q_DECL_CONSTEXPR Iterator(const Iterator &) = default;
+ Iterator &operator=(const Iterator &other)
+ {
+ // rebind the reference
+ item.d = other.item.d;
+ item.i = other.item.i;
+ return *this;
+ }
+
+ QCborValueRef operator*() const { return item; }
+ QCborValueRef *operator->() const { return &item; }
+ QCborValueRef operator[](qsizetype j) { return { item.d, item.i + j }; }
+
+ bool operator==(const Iterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
+ bool operator!=(const Iterator &o) const { return !(*this == o); }
+ bool operator<(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
+ bool operator<=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
+ bool operator>(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
+ bool operator>=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
+ bool operator==(const ConstIterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
+ bool operator!=(const ConstIterator &o) const { return !(*this == o); }
+ bool operator<(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
+ bool operator<=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
+ bool operator>(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
+ bool operator>=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
+ Iterator &operator++() { ++item.i; return *this; }
+ Iterator operator++(int) { Iterator n = *this; ++item.i; return n; }
+ Iterator &operator--() { item.i--; return *this; }
+ Iterator operator--(int) { Iterator n = *this; item.i--; return n; }
+ Iterator &operator+=(qsizetype j) { item.i += j; return *this; }
+ Iterator &operator-=(qsizetype j) { item.i -= j; return *this; }
+ Iterator operator+(qsizetype j) const { return Iterator({ item.d, item.i + j }); }
+ Iterator operator-(qsizetype j) const { return Iterator({ item.d, item.i - j }); }
+ qsizetype operator-(Iterator j) const { return item.i - j.item.i; }
+ };
+
+ class ConstIterator {
+ QCborValueRef item;
+ friend class Iterator;
+ friend class QCborArray;
+ ConstIterator(QCborContainerPrivate *dd, qsizetype ii) : item(dd, ii) {}
+ public:
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef qsizetype difference_type;
+ typedef const QCborValue value_type;
+ typedef const QCborValueRef reference;
+ typedef const QCborValueRef *pointer;
+
+ Q_DECL_CONSTEXPR ConstIterator() = default;
+ Q_DECL_CONSTEXPR ConstIterator(const ConstIterator &) = default;
+ ConstIterator &operator=(const ConstIterator &other)
+ {
+ // rebind the reference
+ item.d = other.item.d;
+ item.i = other.item.i;
+ return *this;
+ }
+
+ const QCborValueRef operator*() const { return item; }
+ const QCborValueRef *operator->() const { return &item; }
+ const QCborValueRef operator[](qsizetype j) { return { item.d, item.i + j }; }
+
+ bool operator==(const Iterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
+ bool operator!=(const Iterator &o) const { return !(*this == o); }
+ bool operator<(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
+ bool operator<=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
+ bool operator>(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
+ bool operator>=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
+ bool operator==(const ConstIterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
+ bool operator!=(const ConstIterator &o) const { return !(*this == o); }
+ bool operator<(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
+ bool operator<=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
+ bool operator>(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
+ bool operator>=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
+ ConstIterator &operator++() { ++item.i; return *this; }
+ ConstIterator operator++(int) { ConstIterator n = *this; ++item.i; return n; }
+ ConstIterator &operator--() { item.i--; return *this; }
+ ConstIterator operator--(int) { ConstIterator n = *this; item.i--; return n; }
+ ConstIterator &operator+=(qsizetype j) { item.i += j; return *this; }
+ ConstIterator &operator-=(qsizetype j) { item.i -= j; return *this; }
+ ConstIterator operator+(qsizetype j) const { return ConstIterator({ item.d, item.i + j }); }
+ ConstIterator operator-(qsizetype j) const { return ConstIterator({ item.d, item.i - j }); }
+ qsizetype operator-(ConstIterator j) const { return item.i - j.item.i; }
+ };
+
+ typedef qsizetype size_type;
+ typedef QCborValue value_type;
+ typedef value_type *pointer;
+ typedef const value_type *const_pointer;
+ typedef QCborValue &reference;
+ typedef const QCborValue &const_reference;
+ typedef qsizetype difference_type;
+
+ QCborArray() noexcept;
+ QCborArray(const QCborArray &other) noexcept;
+ QCborArray &operator=(const QCborArray &other) noexcept;
+ QCborArray(std::initializer_list<QCborValue> args)
+ : QCborArray()
+ {
+ detach(qsizetype(args.size()));
+ for (const QCborValue &v : args)
+ append(v);
+ }
+ ~QCborArray();
+
+ void swap(QCborArray &other) noexcept
+ {
+ qSwap(d, other.d);
+ }
+
+ QCborValue toCborValue() const { return *this; }
+
+ qsizetype size() const noexcept;
+ bool isEmpty() const { return size() == 0; }
+ void clear();
+
+ QCborValue at(qsizetype i) const;
+ QCborValue first() const { return at(0); }
+ QCborValue last() const { return at(size() - 1); }
+ const QCborValue operator[](qsizetype i) const { return at(i); }
+ QCborValueRef first() { Q_ASSERT(!isEmpty()); return begin()[0]; }
+ QCborValueRef last() { Q_ASSERT(!isEmpty()); return begin()[size() - 1]; }
+ QCborValueRef operator[](qsizetype i)
+ {
+ if (i >= size())
+ insert(i, QCborValue());
+ return begin()[i];
+ }
+
+ void insert(qsizetype i, const QCborValue &value);
+ void insert(qsizetype i, QCborValue &&value);
+ void prepend(const QCborValue &value) { insert(0, value); }
+ void prepend(QCborValue &&value) { insert(0, std::move(value)); }
+ void append(const QCborValue &value) { insert(-1, value); }
+ void append(QCborValue &&value) { insert(-1, std::move(value)); }
+ QCborValue extract(ConstIterator it) { return extract(Iterator{ it.item.d, it.item.i }); }
+ QCborValue extract(Iterator it);
+ void removeAt(qsizetype i);
+ QCborValue takeAt(qsizetype i) { Q_ASSERT(i < size()); return extract(begin() + i); }
+ void removeFirst() { removeAt(0); }
+ void removeLast() { removeAt(size() - 1); }
+ QCborValue takeFirst() { return takeAt(0); }
+ QCborValue takeLast() { return takeAt(size() - 1); }
+
+ bool contains(const QCborValue &value) const;
+
+ int compare(const QCborArray &other) const noexcept Q_DECL_PURE_FUNCTION;
+#if 0 && QT_HAS_INCLUDE(<compare>)
+ std::strong_ordering operator<=>(const QCborArray &other) const
+ {
+ int c = compare(other);
+ if (c > 0) return std::strong_ordering::greater;
+ if (c == 0) return std::strong_ordering::equivalent;
+ return std::strong_ordering::less;
+ }
+#else
+ bool operator==(const QCborArray &other) const noexcept
+ { return compare(other) == 0; }
+ bool operator!=(const QCborArray &other) const noexcept
+ { return !(*this == other); }
+ bool operator<(const QCborArray &other) const
+ { return compare(other) < 0; }
+#endif
+
+ typedef Iterator iterator;
+ typedef ConstIterator const_iterator;
+ iterator begin() { detach(); return iterator{d.data(), 0}; }
+ const_iterator constBegin() const { return const_iterator{d.data(), 0}; }
+ const_iterator begin() const { return constBegin(); }
+ const_iterator cbegin() const { return constBegin(); }
+ iterator end() { detach(); return iterator{d.data(), size()}; }
+ const_iterator constEnd() const { return const_iterator{d.data(), size()}; }
+ const_iterator end() const { return constEnd(); }
+ const_iterator cend() const { return constEnd(); }
+ iterator insert(iterator before, const QCborValue &value)
+ { insert(before.item.i, value); return iterator{d.data(), before.item.i}; }
+ iterator insert(const_iterator before, const QCborValue &value)
+ { insert(before.item.i, value); return iterator{d.data(), before.item.i}; }
+ iterator erase(iterator it) { removeAt(it.item.i); return iterator{d.data(), it.item.i}; }
+ iterator erase(const_iterator it) { removeAt(it.item.i); return iterator{d.data(), it.item.i}; }
+
+ void push_back(const QCborValue &t) { append(t); }
+ void push_front(const QCborValue &t) { prepend(t); }
+ void pop_front() { removeFirst(); }
+ void pop_back() { removeLast(); }
+ bool empty() const { return isEmpty(); }
+
+ // convenience
+ QCborArray operator+(const QCborValue &v) const
+ { QCborArray n = *this; n += v; return n; }
+ QCborArray &operator+=(const QCborValue &v)
+ { append(v); return *this; }
+ QCborArray &operator<<(const QCborValue &v)
+ { append(v); return *this; }
+
+ static QCborArray fromStringList(const QStringList &list);
+ static QCborArray fromVariantList(const QVariantList &list);
+ static QCborArray fromJsonArray(const QJsonArray &array);
+ QVariantList toVariantList() const;
+ QJsonArray toJsonArray() const;
+
+private:
+ void detach(qsizetype reserve = 0);
+
+ friend QCborValue;
+ explicit QCborArray(QCborContainerPrivate &dd) noexcept;
+ QExplicitlySharedDataPointer<QCborContainerPrivate> d;
+};
+
+Q_DECLARE_SHARED(QCborArray)
+
+inline QCborValue::QCborValue(QCborArray &&a)
+ : n(-1), container(a.d.take()), t(Array)
+{
+}
+
+inline QCborArray QCborValueRef::toArray() const
+{
+ return concrete().toArray();
+}
+
+inline QCborArray QCborValueRef::toArray(const QCborArray &a) const
+{
+ return concrete().toArray(a);
+}
+
+Q_CORE_EXPORT uint qHash(const QCborArray &array, uint seed = 0);
+
+#if !defined(QT_NO_DEBUG_STREAM)
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborArray &a);
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QCBORARRAY_H
diff --git a/src/corelib/serialization/qcborcommon.h b/src/corelib/serialization/qcborcommon.h
new file mode 100644
index 0000000000..9661cd70bb
--- /dev/null
+++ b/src/corelib/serialization/qcborcommon.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://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 QCBORCOMMON_H
+#define QCBORCOMMON_H
+
+#include <QtCore/qobjectdefs.h>
+#include <QtCore/qmetatype.h>
+#include <QtCore/qdebug.h>
+
+#if 0
+#pragma qt_class(QtCborCommon)
+#endif
+
+/* X11 headers use these values too, but as defines */
+#if defined(False) && defined(True)
+# define QT_X11_DEFINES_FOUND 1
+# undef True
+# undef False
+#endif
+
+QT_BEGIN_NAMESPACE
+
+enum class QCborSimpleType : quint8 {
+ False = 20,
+ True = 21,
+ Null = 22,
+ Undefined = 23
+};
+
+enum class QCborTag : quint64 {};
+enum class QCborKnownTags {
+ DateTimeString = 0,
+ UnixTime_t = 1,
+ PositiveBignum = 2,
+ NegativeBignum = 3,
+ Decimal = 4,
+ Bigfloat = 5,
+ COSE_Encrypt0 = 16,
+ COSE_Mac0 = 17,
+ COSE_Sign1 = 18,
+ ExpectedBase64url = 21,
+ ExpectedBase64 = 22,
+ ExpectedBase16 = 23,
+ EncodedCbor = 24,
+ Url = 32,
+ Base64url = 33,
+ Base64 = 34,
+ RegularExpression = 35,
+ MimeMessage = 36,
+ Uuid = 37,
+ COSE_Encrypt = 96,
+ COSE_Mac = 97,
+ COSE_Sign = 98,
+ Signature = 55799
+};
+
+inline bool operator==(QCborTag t, QCborKnownTags kt) { return quint64(t) == quint64(kt); }
+inline bool operator==(QCborKnownTags kt, QCborTag t) { return quint64(t) == quint64(kt); }
+inline bool operator!=(QCborTag t, QCborKnownTags kt) { return quint64(t) != quint64(kt); }
+inline bool operator!=(QCborKnownTags kt, QCborTag t) { return quint64(t) != quint64(kt); }
+
+struct Q_CORE_EXPORT QCborError
+{
+ Q_GADGET
+public:
+ enum Code : int {
+ UnknownError = 1,
+ AdvancePastEnd = 3,
+ InputOutputError = 4,
+ GarbageAtEnd = 256,
+ EndOfFile,
+ UnexpectedBreak,
+ UnknownType,
+ IllegalType,
+ IllegalNumber,
+ IllegalSimpleType,
+
+ InvalidUtf8String = 516,
+
+ DataTooLarge = 1024,
+ NestingTooDeep,
+ UnsupportedType,
+
+ NoError = 0
+ };
+ Q_ENUM(Code)
+
+ Code c;
+ operator Code() const { return c; }
+ QString toString() const;
+};
+
+#if !defined(QT_NO_DEBUG_STREAM)
+Q_CORE_EXPORT QDebug operator<<(QDebug, QCborSimpleType st);
+Q_CORE_EXPORT QDebug operator<<(QDebug, QCborKnownTags tg);
+Q_CORE_EXPORT QDebug operator<<(QDebug, QCborTag tg);
+#endif
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QCborTag)
+
+// To avoid changing namespace we need to reinstate defines, even though our .cpp
+// will then have to remove them again.
+#if defined(QT_X11_DEFINES_FOUND)
+# define True 1
+# define False 0
+#endif
+
+#endif // QCBORSTREAM_H
diff --git a/src/corelib/serialization/qcbordiagnostic.cpp b/src/corelib/serialization/qcbordiagnostic.cpp
new file mode 100644
index 0000000000..75feaded17
--- /dev/null
+++ b/src/corelib/serialization/qcbordiagnostic.cpp
@@ -0,0 +1,347 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://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 "qcborvalue.h"
+#include "qcborvalue_p.h"
+
+#include "qcborarray.h"
+#include "qcbormap.h"
+
+#include <private/qnumeric_p.h>
+#include <qstack.h>
+#include <private/qtools_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+class DiagnosticNotation
+{
+public:
+ static QString create(const QCborValue &v, QCborValue::DiagnosticNotationOptions opts)
+ {
+ DiagnosticNotation dn(opts);
+ dn.appendValue(v);
+ return dn.result;
+ }
+
+private:
+ QStack<int> byteArrayFormatStack;
+ QString separator;
+ QString result;
+ QCborValue::DiagnosticNotationOptions opts;
+ int nestingLevel = 0;
+
+ struct Nest {
+ enum { IndentationWidth = 4 };
+ DiagnosticNotation *dn;
+ Nest(DiagnosticNotation *that) : dn(that)
+ {
+ ++dn->nestingLevel;
+ static const char indent[IndentationWidth + 1] = " ";
+ if (dn->opts & QCborValue::LineWrapped)
+ dn->separator += QLatin1String(indent, IndentationWidth);
+ }
+ ~Nest()
+ {
+ --dn->nestingLevel;
+ if (dn->opts & QCborValue::LineWrapped)
+ dn->separator.chop(IndentationWidth);
+ }
+ };
+
+ DiagnosticNotation(QCborValue::DiagnosticNotationOptions opts_)
+ : separator(QLatin1String(opts_ & QCborValue::LineWrapped ? "\n" : "")), opts(opts_)
+ {
+ byteArrayFormatStack.push(int(QCborKnownTags::ExpectedBase16));
+ }
+
+ void appendString(const QString &s);
+ void appendArray(const QCborArray &a);
+ void appendMap(const QCborMap &m);
+ void appendValue(const QCborValue &v);
+};
+}
+
+static QString makeFpString(double d)
+{
+ QString s;
+ quint64 v;
+ if (qt_is_inf(d)) {
+ s = (d < 0) ? QStringLiteral("-inf") : QStringLiteral("inf");
+ } else if (qt_is_nan(d)) {
+ s = QStringLiteral("nan");
+ } else if (convertDoubleTo(d, &v)) {
+ s = QString::fromLatin1("%1.0").arg(v);
+ if (d < 0)
+ s.prepend(QLatin1Char('-'));
+ } else {
+ s = QString::number(d, 'g', QLocale::FloatingPointShortest);
+ if (!s.contains(QLatin1Char('.')) && !s.contains('e'))
+ s += QLatin1Char('.');
+ }
+ return s;
+}
+
+static bool isByteArrayEncodingTag(QCborTag tag)
+{
+ switch (quint64(tag)) {
+ case quint64(QCborKnownTags::ExpectedBase16):
+ case quint64(QCborKnownTags::ExpectedBase64):
+ case quint64(QCborKnownTags::ExpectedBase64url):
+ return true;
+ }
+ return false;
+}
+
+void DiagnosticNotation::appendString(const QString &s)
+{
+ result += QLatin1Char('"');
+
+ const QChar *begin = s.begin();
+ const QChar *end = s.end();
+ while (begin < end) {
+ // find the longest span comprising only non-escaped characters
+ const QChar *ptr = begin;
+ for ( ; ptr < end; ++ptr) {
+ ushort uc = ptr->unicode();
+ if (uc == '\\' || uc == '"' || uc < ' ' || uc >= 0x7f)
+ break;
+ }
+
+ if (ptr != begin)
+ result.append(begin, ptr - begin);
+
+ if (ptr == end)
+ break;
+
+ // there's an escaped character
+ static const char escapeMap[16] = {
+ // The C escape characters \a \b \t \n \v \f and \r indexed by
+ // their ASCII values
+ 0, 0, 0, 0,
+ 0, 0, 0, 'a',
+ 'b', 't', 'n', 'v',
+ 'f', 'r', 0, 0
+ };
+ int buflen = 2;
+ QChar buf[10];
+ buf[0] = QLatin1Char('\\');
+ buf[1] = QChar::Null;
+ char16_t uc = ptr->unicode();
+
+ if (uc < sizeof(escapeMap))
+ buf[1] = QLatin1Char(escapeMap[uc]);
+ else if (uc == '"' || uc == '\\')
+ buf[1] = QChar(uc);
+
+ if (buf[1] == QChar::Null) {
+ using QtMiscUtils::toHexUpper;
+ if (ptr->isHighSurrogate() && (ptr + 1) != end && ptr[1].isLowSurrogate()) {
+ // properly-paired surrogates
+ ++ptr;
+ char32_t ucs4 = QChar::surrogateToUcs4(uc, ptr->unicode());
+ buf[1] = 'U';
+ buf[2] = '0'; // toHexUpper(ucs4 >> 28);
+ buf[3] = '0'; // toHexUpper(ucs4 >> 24);
+ buf[4] = toHexUpper(ucs4 >> 20);
+ buf[5] = toHexUpper(ucs4 >> 16);
+ buf[6] = toHexUpper(ucs4 >> 12);
+ buf[7] = toHexUpper(ucs4 >> 8);
+ buf[8] = toHexUpper(ucs4 >> 4);
+ buf[9] = toHexUpper(ucs4);
+ buflen = 10;
+ } else {
+ buf[1] = 'u';
+ buf[2] = toHexUpper(uc >> 12);
+ buf[3] = toHexUpper(uc >> 8);
+ buf[4] = toHexUpper(uc >> 4);
+ buf[5] = toHexUpper(uc);
+ buflen = 6;
+ }
+ }
+
+ result.append(buf, buflen);
+ begin = ptr + 1;
+ }
+
+ result += QLatin1Char('"');
+}
+
+void DiagnosticNotation::appendArray(const QCborArray &a)
+{
+ result += QLatin1Char('[');
+
+ // length 2 (including the space) when not line wrapping
+ QLatin1String commaValue(", ", opts & QCborValue::LineWrapped ? 1 : 2);
+ {
+ Nest n(this);
+ QLatin1String comma;
+ for (auto v : a) {
+ result += comma + separator;
+ comma = commaValue;
+ appendValue(v);
+ }
+ }
+
+ result += separator + QLatin1Char(']');
+}
+
+void DiagnosticNotation::appendMap(const QCborMap &m)
+{
+ result += QLatin1Char('{');
+
+ // length 2 (including the space) when not line wrapping
+ QLatin1String commaValue(", ", opts & QCborValue::LineWrapped ? 1 : 2);
+ {
+ Nest n(this);
+ QLatin1String comma;
+ for (auto v : m) {
+ result += comma + separator;
+ comma = commaValue;
+ appendValue(v.first);
+ result += QLatin1String(": ");
+ appendValue(v.second);
+ }
+ }
+
+ result += separator + QLatin1Char('}');
+};
+
+void DiagnosticNotation::appendValue(const QCborValue &v)
+{
+ switch (v.type()) {
+ case QCborValue::Integer:
+ result += QString::number(v.toInteger());
+ return;
+ case QCborValue::ByteArray:
+ switch (byteArrayFormatStack.top()) {
+ case int(QCborKnownTags::ExpectedBase16):
+ result += QString::fromLatin1("h'" +
+ v.toByteArray().toHex(opts & QCborValue::ExtendedFormat ? ' ' : '\0') +
+ '\'');
+ return;
+ case int(QCborKnownTags::ExpectedBase64):
+ result += QString::fromLatin1("b64'" + v.toByteArray().toBase64() + '\'');
+ return;
+ default:
+ case int(QCborKnownTags::ExpectedBase64url):
+ result += QString::fromLatin1("b64'" +
+ v.toByteArray().toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals) +
+ '\'');
+ return;
+ }
+ case QCborValue::String:
+ return appendString(v.toString());
+ case QCborValue::Array:
+ return appendArray(v.toArray());
+ case QCborValue::Map:
+ return appendMap(v.toMap());
+ case QCborValue::False:
+ result += QLatin1String("false");
+ return;
+ case QCborValue::True:
+ result += QLatin1String("true");
+ return;
+ case QCborValue::Null:
+ result += QLatin1String("null");
+ return;
+ case QCborValue::Undefined:
+ result += QLatin1String("undefined");
+ return;
+ case QCborValue::Double:
+ result += makeFpString(v.toDouble());
+ return;
+ case QCborValue::Invalid:
+ result += QStringLiteral("<invalid>");
+ return;
+
+ default:
+ // Only tags, extended types, and simple types remain; see below.
+ break;
+ }
+
+ if (v.isTag()) {
+ // We handle all extended types as regular tags, so it won't matter
+ // whether we understand that tag or not.
+ bool byteArrayFormat = opts & QCborValue::ExtendedFormat && isByteArrayEncodingTag(v.tag());
+ if (byteArrayFormat)
+ byteArrayFormatStack.push(int(v.tag()));
+ result += QString::number(quint64(v.tag())) + QLatin1Char('(');
+ appendValue(v.taggedValue());
+ result += QLatin1Char(')');
+ if (byteArrayFormat)
+ byteArrayFormatStack.pop();
+ } else {
+ // must be a simple type
+ result += QString::fromLatin1("simple(%1)").arg(quint8(v.toSimpleType()));
+ }
+}
+
+/*!
+ Creates the diagnostic notation equivalent of this CBOR object and returns
+ it. The \a opts parameter controls the dialect of the notation. Diagnostic
+ notation is useful in debugging, to aid the developer in understanding what
+ value is stored in the QCborValue or in a CBOR stream. For that reason, the
+ Qt API provides no support for parsing the diagnostic back into the
+ in-memory format or CBOR stream, though the representation is unique and it
+ would be possible.
+
+ CBOR diagnostic notation is specified by
+ \l{https://tools.ietf.org/html/rfc7049#section-6}{section 6} of RFC 7049.
+ It is a text representation of the CBOR stream and it is very similar to
+ JSON, but it supports the CBOR types not found in JSON. The extended format
+ enabled by the \l{DiagnosticNotationOption}{ExtendedFormat} flag is
+ currently in some IETF drafts and its format is subject to change.
+
+ This function produces the equivalent representation of the stream that
+ toCbor() would produce, without any transformation option provided there.
+ This also implies this function may not produce a representation of the
+ stream that was used to create the object, if it was created using
+ fromCbor(), as that function may have applied transformations. For a
+ high-fidelity notation of a stream, without transformation, see the \c
+ cbordump example.
+
+ \sa toCbor(), QJsonDocument::toJson()
+ */
+QString QCborValue::toDiagnosticNotation(DiagnosticNotationOptions opts) const
+{
+ return DiagnosticNotation::create(*this, opts);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qcbormap.cpp b/src/corelib/serialization/qcbormap.cpp
new file mode 100644
index 0000000000..33f9249993
--- /dev/null
+++ b/src/corelib/serialization/qcbormap.cpp
@@ -0,0 +1,1766 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://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 "qcbormap.h"
+#include "qcborvalue_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QtCbor;
+
+/*!
+ \class QCborMap
+ \inmodule QtCore
+ \ingroup cbor
+ \reentrant
+ \since 5.12
+
+ \brief The QCborMap class is used to hold an associative container representable in CBOR.
+
+ This class can be used to hold an associative container in CBOR, a map
+ between a key and a value type. CBOR is the Concise Binary Object
+ Representation, a very compact form of binary data encoding that is a
+ superset of JSON. It was created by the IETF Constrained RESTful
+ Environments (CoRE) WG, which has used it in many new RFCs. It is meant to
+ be used alongside the \l{https://tools.ietf.org/html/rfc7252}{CoAP
+ protocol}.
+
+ Unlike JSON and \l QVariantMap, CBOR map keys can be of any type, not just
+ strings. For that reason, QCborMap is effectively a map between QCborValue
+ keys to QCborValue value elements.
+
+ However, for all member functions that take a key parameter, QCborMap
+ provides overloads that will work efficiently with integers and strings. In
+ fact, the use of integer keys is encouraged, since they occupy fewer bytes
+ to transmit and are simpler to encode and decode. Newer protocols designed
+ by the IETF CoRE WG to work specifically with CBOR are known to use them.
+
+ QCborMap is not sorted, because of that, searching for keys has linear
+ complexity (O(n)). QCborMap actually keeps the elements in the order that
+ they were inserted, which means that it is possible to make sorted
+ QCborMaps by carefully inserting elements in sorted order. CBOR does not
+ require sorting, but recommends it.
+
+ QCborMap can also be converted to and from QVariantMap and QJsonObject.
+ However, when performing the conversion, any non-string keys will be
+ stringified using a one-way method that the conversion back to QCborMap
+ will not undo.
+
+ \sa QCborArray, QCborValue, QJsonDocument, QVariantMap
+ */
+
+/*!
+ \typedef QCborMap::value_type
+
+ The value that is stored in this container: a pair of QCborValues
+ */
+
+/*!
+ \typedef QCborMap::key_type
+
+ The key type for this map. Since QCborMap keys can be any CBOR type, this
+ is a QCborValue.
+ */
+
+/*!
+ \typedef QCborMap::mapped_type
+
+ The type that is mapped to (the value), that is, a QCborValue.
+ */
+
+/*!
+ \typedef QCborMap::size_type
+
+ The type that QCborMap uses for sizes.
+ */
+
+/*!
+ \typedef QCborMap::iterator
+
+ A synonym for QCborMap::Iterator.
+ */
+
+/*!
+ \typedef QCborMap::const_iterator
+
+ A synonym for QCborMap::ConstIterator
+ */
+
+/*!
+ \fn QCborMap::iterator QCborMap::begin()
+
+ Returns a map iterator pointing to the first key-value pair of this map. If
+ this map is empty, the returned iterator will be the same as end().
+
+ \sa constBegin(), end()
+ */
+
+/*!
+ \fn QCborMap::const_iterator QCborMap::constBegin() const
+
+ Returns a map iterator pointing to the first key-value pair of this map. If
+ this map is empty, the returned iterator will be the same as constEnd().
+
+ \sa begin(), constEnd()
+ */
+
+/*!
+ \fn QCborMap::const_iterator QCborMap::begin() const
+
+ Returns a map iterator pointing to the first key-value pair of this map. If
+ this map is empty, the returned iterator will be the same as constEnd().
+
+ \sa begin(), constEnd()
+ */
+
+/*!
+ \fn QCborMap::const_iterator QCborMap::cbegin() const
+
+ Returns a map iterator pointing to the first key-value pair of this map. If
+ this map is empty, the returned iterator will be the same as constEnd().
+
+ \sa begin(), constEnd()
+ */
+
+/*!
+ \fn QCborMap::iterator QCborMap::end()
+
+ Returns a map iterator representing an element just past the last element
+ in the map.
+
+ \sa begin(), constBegin(), find(), constFind()
+ */
+
+/*!
+ \fn QCborMap::iterator QCborMap::constEnd() const
+
+ Returns a map iterator representing an element just past the last element
+ in the map.
+
+ \sa begin(), constBegin(), find(), constFind()
+ */
+
+/*!
+ \fn QCborMap::iterator QCborMap::end() const
+
+ Returns a map iterator representing an element just past the last element
+ in the map.
+
+ \sa begin(), constBegin(), find(), constFind()
+ */
+
+/*!
+ \fn QCborMap::iterator QCborMap::cend() const
+
+ Returns a map iterator representing an element just past the last element
+ in the map.
+
+ \sa begin(), constBegin(), find(), constFind()
+ */
+
+/*!
+ Constructs an empty CBOR Map object.
+
+ \sa isEmpty()
+ */
+QCborMap::QCborMap() noexcept
+ : d(nullptr)
+{
+}
+
+/*!
+ Creates a QCborMap object that is a copy of \a other.
+ */
+QCborMap::QCborMap(const QCborMap &other) noexcept
+ : d(other.d)
+{
+}
+
+/*!
+ \fn QCborMap::QCborMap(std::initializer_list<value_type> args)
+
+ Constructs a QCborMap with items from a brace-initialization list found in
+ \a args, as in the following example:
+
+ \code
+ QCborMap map = {
+ {0, "Hello"},
+ {1, "World"},
+ {"foo", nullptr},
+ {"bar", QCborArray{0, 1, 2, 3, 4}}
+ };
+ \endcode
+ */
+
+/*!
+ Destroys this QCborMap object and frees any associated resources it owns.
+ */
+QCborMap::~QCborMap()
+{
+}
+
+/*!
+ Replaces the contents of this object with a copy of \a other, then returns
+ a reference to this object.
+ */
+QCborMap &QCborMap::operator=(const QCborMap &other) noexcept
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ \fn void QCborMap::swap(QCborMap &other)
+
+ Swaps the contents of this map and \a other.
+ */
+
+/*!
+ \fn QCborValue QCborMap::toCborValue() const
+
+ Explicitly constructs a \l QCborValue object that represents this map.
+ This function is usually not necessary since QCborValue has a constructor
+ for QCborMap, so the conversion is implicit.
+
+ Converting QCborMap to QCborValue allows it to be used in any context where
+ QCborValues can be used, including as keys and mapped types in QCborMap, as
+ well as QCborValue::toCbor().
+
+ \sa QCborValue::QCborValue(const QCborMap &)
+ */
+
+/*!
+ \fn bool QCborMap::isEmpty() const
+
+ Returns true if this map is empty (that is, size() is 0).
+
+ \sa size(), clear()
+ */
+
+/*!
+ Returns the number of elements in this map.
+
+ \sa isEmpty()
+ */
+qsizetype QCborMap::size() const noexcept
+{
+ return d ? d->elements.size() / 2 : 0;
+}
+
+/*!
+ Empties this map.
+
+ \sa isEmpty()
+ */
+void QCborMap::clear()
+{
+ d.reset();
+}
+
+/*!
+ Returns a list of all keys in this map.
+
+ \sa QMap::keys(), QHash::keys()
+ */
+QVector<QCborValue> QCborMap::keys() const
+{
+ QVector<QCborValue> result;
+ if (d) {
+ result.reserve(size());
+ for (qsizetype i = 0; i < d->elements.size(); i += 2)
+ result << d->valueAt(i);
+ }
+ return result;
+}
+
+/*!
+ \fn QCborValue QCborMap::value(qint64 key) const
+
+ Returns the QCborValue element in this map that corresponds to key \a key,
+ if there is one. CBOR recommends using integer keys, since they occupy less
+ space and are simpler to encode and decode.
+
+ If the map does not contain key \a key, this function returns a QCborValue
+ containing an undefined value. For that reason, it is not possible with
+ this function to tell apart the situation where the key was not present
+ from the situation where the key was mapped to an undefined value.
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one the return from function will reference. QCborMap does not allow
+ inserting duplicate keys, but it is possible to create such a map by
+ decoding a CBOR stream with them. They are usually not permitted and having
+ duplicate keys is usually an indication of a problem in the sender.
+
+ \sa operator[](qint64), find(qint64), constFind(qint64), remove(qint64), contains(qint64)
+ value(QLatin1String), value(const QString &), value(const QCborValue &)
+ */
+
+/*!
+ \fn QCborValue QCborMap::operator[](qint64 key) const
+
+ Returns the QCborValue element in this map that corresponds to key \a key,
+ if there is one. CBOR recommends using integer keys, since they occupy less
+ space and are simpler to encode and decode.
+
+ If the map does not contain key \a key, this function returns a QCborValue
+ containing an undefined value. For that reason, it is not possible with
+ this function to tell apart the situation where the key was not present
+ from the situation where the key was mapped to an undefined value.
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one this function will return. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa value(qint64), find(qint64), constFind(qint64), remove(qint64), contains(qint64)
+ operator[](QLatin1String), operator[](const QString &), operator[](const QCborOperator[] &)
+ */
+
+/*!
+ \fn QCborValue QCborMap::take(qint64 key)
+
+ Removes the key \a key and the corresponding value from the map and returns
+ the value, if it is found. If the map contains no such key, this function does nothing.
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one this function will remove. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa value(qint64), operator[](qint64), find(qint64), contains(qint64),
+ take(QLatin1String), take(const QString &), take(const QCborValue &), insert()
+ */
+
+/*!
+ \fn void QCborMap::remove(qint64 key)
+
+ Removes the key \a key and the corresponding value from the map, if it is
+ found. If the map contains no such key, this function does nothing.
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one this function will remove. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa value(qint64), operator[](qint64), find(qint64), contains(qint64)
+ remove(QLatin1String), remove(const QString &), remove(const QCborValue &)
+ */
+
+/*!
+ \fn bool QCborMap::contains(qint64 key) const
+
+ Returns true if this map contains a key-value pair identified by key \a
+ key. CBOR recommends using integer keys, since they occupy less space and
+ are simpler to encode and decode.
+
+ \sa value(qint64), operator[](qint64), find(qint64), remove(qint64),
+ contains(QLatin1String), remove(const QString &), remove(const QCborValue &)
+ */
+
+/*!
+ Returns a QCborValueRef to the value in this map that corresponds to key \a
+ key. CBOR recommends using integer keys, since they occupy less space and
+ are simpler to encode and decode.
+
+ QCborValueRef has the exact same API as \l QCborValue, with one important
+ difference: if you assign new values to it, this map will be updated with
+ that new value.
+
+ If the map did not have a key equal to \a key, one is inserted and this
+ function returns a reference to the new value, which will be a QCborValue
+ with an undefined value. For that reason, it is not possible with this
+ function to tell apart the situation where the key was not present from the
+ situation where the key was mapped to an undefined value.
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one the return will reference. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa value(qint64), find(qint64), contains(qint64), remove(qint64),
+ operator[](QLatin1String), operator[](const QString &), operator[](const QCborValue &)
+ */
+QCborValueRef QCborMap::operator[](qint64 key)
+{
+ auto it = find(key);
+ if (it == constEnd()) {
+ // insert element
+ detach(it.item.i + 2);
+ d->append(key);
+ d->append(Undefined{});
+ }
+ return { d.data(), it.item.i };
+}
+
+/*!
+ \fn QCborValue QCborMap::value(QLatin1String key) const
+ \overload
+
+ Returns the QCborValue element in this map that corresponds to key \a key,
+ if there is one.
+
+ If the map does not contain key \a key, this function returns a QCborValue
+ containing an undefined value. For that reason, it is not possible with
+ this function to tell apart the situation where the key was not present
+ from the situation where the key was mapped to an undefined value.
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one this function will return. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa operator[](QLatin1String), find(QLatin1String), constFind(QLatin1String),
+ remove(QLatin1String), contains(QLatin1String)
+ value(qint64), value(const QString &), value(const QCborValue &)
+ */
+
+/*!
+ \fn QCborValue QCborMap::operator[](QLatin1String key) const
+ \overload
+
+ Returns the QCborValue element in this map that corresponds to key \a key,
+ if there is one.
+
+ If the map does not contain key \a key, this function returns a QCborValue
+ containing an undefined value. For that reason, it is not possible with
+ this function to tell apart the situation where the key was not present
+ from the situation where the key was mapped to an undefined value.
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one this function will return. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa value(QLatin1String), find(QLatin1String), constFind(QLatin1String),
+ remove(QLatin1String), contains(QLatin1String)
+ operator[](qint64), operator[](const QString &), operator[](const QCborOperator[] &)
+ */
+
+/*!
+ \fn QCborValue QCborMap::take(QLatin1String key)
+
+ Removes the key \a key and the corresponding value from the map and returns
+ the value, if it is found. If the map contains no such key, this function does nothing.
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one this function will remove. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa value(QLatin1String), operator[](QLatin1String), find(QLatin1String), contains(QLatin1String),
+ take(qint64), take(const QString &), take(const QCborValue &), insert()
+ */
+
+/*!
+ \fn void QCborMap::remove(QLatin1String key)
+ \overload
+
+ Removes the key \a key and the corresponding value from the map, if it is
+ found. If the map contains no such key, this function does nothing.
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one this function will remove. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa value(QLatin1String), operator[](QLatin1String), find(QLatin1String), contains(QLatin1String)
+ remove(qint64), remove(const QString &), remove(const QCborValue &)
+ */
+
+/*!
+ \fn bool QCborMap::contains(QLatin1String key) const
+ \overload
+
+ Returns true if this map contains a key-value pair identified by key \a
+ key.
+
+ \sa value(QLatin1String), operator[](QLatin1String), find(QLatin1String), remove(QLatin1String),
+ contains(qint64), remove(const QString &), remove(const QCborValue &)
+ */
+
+/*!
+ \overload
+
+ Returns a QCborValueRef to the value in this map that corresponds to key \a
+ key.
+
+ QCborValueRef has the exact same API as \l QCborValue, with one important
+ difference: if you assign new values to it, this map will be updated with
+ that new value.
+
+ If the map did not have a key equal to \a key, one is inserted and this
+ function returns a reference to the new value, which will be a QCborValue
+ with an undefined value. For that reason, it is not possible with this
+ function to tell apart the situation where the key was not present from the
+ situation where the key was mapped to an undefined value.
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one the return will reference. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa value(QLatin1String), find(QLatin1String), contains(QLatin1String), remove(QLatin1String),
+ operator[](qint64), operator[](const QString &), operator[](const QCborValue &)
+ */
+QCborValueRef QCborMap::operator[](QLatin1String key)
+{
+ auto it = find(key);
+ if (it == constEnd()) {
+ // insert element
+ detach(it.item.i + 2);
+ d->append(key);
+ d->append(Undefined{});
+ }
+ return { d.data(), it.item.i };
+}
+
+/*!
+ \fn QCborValue QCborMap::value(const QString &key) const
+ \overload
+
+ Returns the QCborValue element in this map that corresponds to key \a key,
+ if there is one.
+
+ If the map does not contain key \a key, this function returns a QCborValue
+ containing an undefined value. For that reason, it is not possible with
+ this function to tell apart the situation where the key was not present
+ from the situation where the key was mapped to an undefined value.
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one this function will return. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa operator[](const QString &), find(const QString &), constFind(const QString &),
+ remove(const QString &), contains(const QString &)
+ value(qint64), value(QLatin1String), value(const QCborValue &)
+ */
+
+/*!
+ \fn QCborValue QCborMap::operator[](const QString &key) const
+ \overload
+
+ Returns the QCborValue element in this map that corresponds to key \a key,
+ if there is one.
+
+ If the map does not contain key \a key, this function returns a QCborValue
+ containing an undefined value. For that reason, it is not possible with
+ this function to tell apart the situation where the key was not present
+ from the situation where the key was mapped to an undefined value.
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one this function will return. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa value(const QString &), find(const QString &), constFind(const QString &),
+ remove(const QString &), contains(const QString &)
+ operator[](qint64), operator[](QLatin1String), operator[](const QCborOperator[] &)
+ */
+
+/*!
+ \fn QCborValue QCborMap::take(const QString &key)
+
+ Removes the key \a key and the corresponding value from the map and returns
+ the value, if it is found. If the map contains no such key, this function does nothing.
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one this function will remove. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa value(const QString &), operator[](const QString &), find(const QString &), contains(const QString &),
+ take(QLatin1String), take(qint64), take(const QCborValue &), insert()
+ */
+
+/*!
+ \fn void QCborMap::remove(const QString &key)
+ \overload
+
+ Removes the key \a key and the corresponding value from the map, if it is
+ found. If the map contains no such key, this function does nothing.
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one this function will remove. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa value(const QString &), operator[](const QString &), find(const QString &),
+ contains(const QString &)
+ remove(qint64), remove(QLatin1String), remove(const QCborValue &)
+ */
+
+/*!
+ \fn bool QCborMap::contains(const QString &key) const
+ \overload
+
+ Returns true if this map contains a key-value pair identified by key \a
+ key.
+
+ \sa value(const QString &), operator[](const QString &), find(const QString &),
+ remove(const QString &),
+ contains(qint64), remove(QLatin1String), remove(const QCborValue &)
+ */
+
+/*!
+ \overload
+
+ Returns a QCborValueRef to the value in this map that corresponds to key \a
+ key.
+
+ QCborValueRef has the exact same API as \l QCborValue, with one important
+ difference: if you assign new values to it, this map will be updated with
+ that new value.
+
+ If the map did not have a key equal to \a key, one is inserted and this
+ function returns a reference to the new value, which will be a QCborValue
+ with an undefined value. For that reason, it is not possible with this
+ function to tell apart the situation where the key was not present from the
+ situation where the key was mapped to an undefined value.
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one the return will reference. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa value(const QString &), find(const QString &), contains(const QString &), remove(const QString &),
+ operator[](qint64), operator[](QLatin1String), operator[](const QCborValue &)
+ */
+QCborValueRef QCborMap::operator[](const QString & key)
+{
+ auto it = find(key);
+ if (it == constEnd()) {
+ // insert element
+ detach(it.item.i + 2);
+ d->append(key);
+ d->append(Undefined{});
+ }
+ return { d.data(), it.item.i };
+}
+
+/*!
+ \fn QCborValue QCborMap::value(const QCborValue &key) const
+
+ Returns the QCborValue element in this map that corresponds to key \a key,
+ if there is one.
+
+ If the map does not contain key \a key, this function returns a QCborValue
+ containing an undefined value. For that reason, it is not possible with
+ this function to tell apart the situation where the key was not present
+ from the situation where the key was mapped to an undefined value.
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one this function will return. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa operator[](const QCborValue &), find(const QCborValue &), constFind(const QCborValue &),
+ remove(const QCborValue &), contains(const QCborValue &)
+ value(qint64), value(QLatin1String), value(const QString &)
+ */
+
+/*!
+ \fn QCborValue QCborMap::operator[](const QCborValue &key) const
+
+ Returns the QCborValue element in this map that corresponds to key \a key,
+ if there is one.
+
+ If the map does not contain key \a key, this function returns a QCborValue
+ containing an undefined value. For that reason, it is not possible with
+ this function to tell apart the situation where the key was not present
+ from the situation where the key was mapped to an undefined value.
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one this function will return. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa value(const QCborValue &), find(const QCborValue &), constFind(const QCborValue &),
+ remove(const QCborValue &), contains(const QCborValue &)
+ operator[](qint64), operator[](QLatin1String), operator[](const QCborOperator[] &)
+ */
+
+/*!
+ \fn QCborValue QCborMap::take(const QCborValue &key)
+
+ Removes the key \a key and the corresponding value from the map and returns
+ the value, if it is found. If the map contains no such key, this function does nothing.
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one this function will remove. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa value(const QCborValue &), operator[](const QCborValue &), find(const QCborValue &), contains(const QCborValue &),
+ take(QLatin1String), take(const QString &), take(qint64), insert()
+ */
+
+/*!
+ \fn void QCborMap::remove(const QCborValue &key)
+
+ Removes the key \a key and the corresponding value from the map, if it is
+ found. If the map contains no such key, this function does nothing.
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one this function will remove. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa value(const QCborValue &), operator[](const QCborValue &), find(const QCborValue &),
+ contains(const QCborValue &)
+ remove(qint64), remove(QLatin1String), remove(const QString &)
+ */
+
+/*!
+ \fn bool QCborMap::contains(const QCborValue &key) const
+
+ Returns true if this map contains a key-value pair identified by key \a
+ key.
+
+ \sa value(const QCborValue &), operator[](const QCborValue &), find(const QCborValue &),
+ remove(const QCborValue &),
+ contains(qint64), remove(QLatin1String), remove(const QString &)
+ */
+
+/*!
+ \overload
+
+ Returns a QCborValueRef to the value in this map that corresponds to key \a
+ key.
+
+ QCborValueRef has the exact same API as \l QCborValue, with one important
+ difference: if you assign new values to it, this map will be updated with
+ that new value.
+
+ If the map did not have a key equal to \a key, one is inserted and this
+ function returns a reference to the new value, which will be a QCborValue
+ with an undefined value. For that reason, it is not possible with this
+ function to tell apart the situation where the key was not present from the
+ situation where the key was mapped to an undefined value.
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one the return will reference. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa value(const QCborValue &), find(const QCborValue &), contains(const QCborValue &), remove(const QCborValue &),
+ operator[](qint64), operator[](QLatin1String), operator[](const QString &)
+ */
+QCborValueRef QCborMap::operator[](const QCborValue &key)
+{
+ auto it = find(key);
+ if (it == constEnd()) {
+ // insert element
+ detach(it.item.i + 2);
+ d->append(key);
+ d->append(Undefined{});
+ }
+ return { d.data(), it.item.i };
+}
+
+/*!
+ \fn QCborMap::iterator QCborMap::find(qint64 key)
+ \fn QCborMap::const_iterator QCborMap::find(qint64 key) const
+
+ Returns a map iterator to the key-value pair whose key is \a key, if the
+ map contains such a pair. If it doesn't, this function returns end().
+
+ CBOR recommends using integer keys, since they occupy less
+ space and are simpler to encode and decode.
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one this function will find. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa value(qint64), operator[](qint64), constFind(qint64), remove(qint64), contains(qint64)
+ value(QLatin1String), value(const QString &), value(const QCborValue &)
+ */
+QCborMap::iterator QCborMap::find(qint64 key)
+{
+ auto it = constFind(key);
+ if (it != constEnd())
+ detach();
+ return { d.data(), it.item.i };
+}
+
+/*!
+ \fn QCborMap::iterator QCborMap::find(QLatin1String key)
+ \fn QCborMap::const_iterator QCborMap::find(QLatin1String key) const
+ \overload
+
+ Returns a map iterator to the key-value pair whose key is \a key, if the
+ map contains such a pair. If it doesn't, this function returns end().
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one this function will find. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa value(QLatin1String), operator[](QLatin1String), constFind(QLatin1String),
+ remove(QLatin1String), contains(QLatin1String)
+ value(qint64), value(const QString &), value(const QCborValue &)
+ */
+QCborMap::iterator QCborMap::find(QLatin1String key)
+{
+ auto it = constFind(key);
+ if (it != constEnd())
+ detach();
+ return { d.data(), it.item.i };
+}
+
+/*!
+ \fn QCborMap::iterator QCborMap::find(const QString & key)
+ \fn QCborMap::const_iterator QCborMap::find(const QString & key) const
+ \overload
+
+ Returns a map iterator to the key-value pair whose key is \a key, if the
+ map contains such a pair. If it doesn't, this function returns end().
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one this function will find. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa value(const QString &), operator[](const QString &), constFind(const QString &),
+ remove(const QString &), contains(const QString &)
+ value(qint64), value(QLatin1String), value(const QCborValue &)
+ */
+QCborMap::iterator QCborMap::find(const QString & key)
+{
+ auto it = constFind(key);
+ if (it != constEnd())
+ detach();
+ return { d.data(), it.item.i };
+}
+
+/*!
+ \fn QCborMap::iterator QCborMap::find(const QCborValue &key)
+ \fn QCborMap::const_iterator QCborMap::find(const QCborValue &key) const
+ \overload
+
+ Returns a map iterator to the key-value pair whose key is \a key, if the
+ map contains such a pair. If it doesn't, this function returns end().
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one this function will find. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa value(const QCborValue &), operator[](const QCborValue &), constFind(const QCborValue &),
+ remove(const QCborValue &), contains(const QCborValue &)
+ value(qint64), value(QLatin1String), value(const QString &)
+ */
+QCborMap::iterator QCborMap::find(const QCborValue &key)
+{
+ auto it = constFind(key);
+ if (it != constEnd())
+ detach();
+ return { d.data(), it.item.i };
+}
+
+/*!
+ Returns a map iterator to the key-value pair whose key is \a key, if the
+ map contains such a pair. If it doesn't, this function returns constEnd().
+
+ CBOR recommends using integer keys, since they occupy less
+ space and are simpler to encode and decode.
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one this function will find. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa value(qint64), operator[](qint64), find(qint64), remove(qint64), contains(qint64)
+ value(QLatin1String), value(const QString &), value(const QCborValue &)
+ */
+QCborMap::const_iterator QCborMap::constFind(qint64 key) const
+{
+ for (qsizetype i = 0; i < 2 * size(); i += 2) {
+ const auto &e = d->elements.at(i);
+ if (e.type == QCborValue::Integer && e.value == key)
+ return { d.data(), i + 1 };
+ }
+ return constEnd();
+}
+
+/*!
+ \overload
+
+ Returns a map iterator to the key-value pair whose key is \a key, if the
+ map contains such a pair. If it doesn't, this function returns constEnd().
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one this function will find. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa value(QLatin1String), operator[](QLatin1String), find(QLatin1String),
+ remove(QLatin1String), contains(QLatin1String)
+ value(qint64), value(const QString &), value(const QCborValue &)
+ */
+QCborMap::const_iterator QCborMap::constFind(QLatin1String key) const
+{
+ for (qsizetype i = 0; i < 2 * size(); i += 2) {
+ if (d->stringEqualsElement(i, key))
+ return { d.data(), i + 1 };
+ }
+ return constEnd();
+}
+
+/*!
+ \overload
+
+ Returns a map iterator to the key-value pair whose key is \a key, if the
+ map contains such a pair. If it doesn't, this function returns constEnd().
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one this function will find. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa value(const QString &), operator[](const QString &), find(const QString &),
+ remove(const QString &), contains(const QString &)
+ value(qint64), value(QLatin1String), value(const QCborValue &)
+ */
+QCborMap::const_iterator QCborMap::constFind(const QString & key) const
+{
+ for (qsizetype i = 0; i < 2 * size(); i += 2) {
+ if (d->stringEqualsElement(i, key))
+ return { d.data(), i + 1 };
+ }
+ return constEnd();
+}
+
+/*!
+ \overload
+
+ Returns a map iterator to the key-value pair whose key is \a key, if the
+ map contains such a pair. If it doesn't, this function returns constEnd().
+
+ If the map contains more than one key equal to \a key, it is undefined
+ which one this function will find. QCborMap does not allow inserting
+ duplicate keys, but it is possible to create such a map by decoding a CBOR
+ stream with them. They are usually not permitted and having duplicate keys
+ is usually an indication of a problem in the sender.
+
+ \sa value(const QCborValue &), operator[](const QCborValue &), find(const QCborValue &),
+ remove(const QCborValue &), contains(const QCborValue &),
+ value(qint64), value(QLatin1String), value(const QString &)
+ */
+QCborMap::const_iterator QCborMap::constFind(const QCborValue &key) const
+{
+ for (qsizetype i = 0; i < 2 * size(); i += 2) {
+ int cmp = d->compareElement(i, key);
+ if (cmp == 0)
+ return { d.data(), i + 1 };
+ }
+ return constEnd();
+}
+
+/*!
+ \fn QCborMap::iterator QCborMap::insert(qint64 key, const QCborValue &value)
+ \overload
+
+ Inserts the key \a key and value \a value into this map and returns a map
+ iterator pointing to the newly inserted pair.
+
+ If the map already had a key equal to \a key, its value will be overwritten
+ by \a value.
+
+ \sa erase(), remove(qint64), value(qint64), operator[](qint64), find(qint64),
+ contains(qint64), take(qint64), extract()
+ */
+
+/*!
+ \fn QCborMap::iterator QCborMap::insert(QLatin1String key, const QCborValue &value)
+ \overload
+
+ Inserts the key \a key and value \a value into this map and returns a map
+ iterator pointing to the newly inserted pair.
+
+ If the map already had a key equal to \a key, its value will be overwritten
+ by \a value.
+
+ \sa erase(), remove(QLatin1String), value(QLatin1String), operator[](QLatin1String),
+ find(QLatin1String), contains(QLatin1String), take(QLatin1String), extract()
+ */
+
+/*!
+ \fn QCborMap::iterator QCborMap::insert(const QString &key, const QCborValue &value)
+ \overload
+
+ Inserts the key \a key and value \a value into this map and returns a map
+ iterator pointing to the newly inserted pair.
+
+ If the map already had a key equal to \a key, its value will be overwritten
+ by \a value.
+
+ \sa erase(), remove(const QString &), value(const QString &), operator[](const QString &),
+ find(const QString &), contains(const QString &), take(const QString &), extract()
+ */
+
+/*!
+ \fn QCborMap::iterator QCborMap::insert(const QCborValue &key, const QCborValue &value)
+ \overload
+
+ Inserts the key \a key and value \a value into this map and returns a map
+ iterator pointing to the newly inserted pair.
+
+ If the map already had a key equal to \a key, its value will be overwritten
+ by \a value.
+
+ \sa erase(), remove(const QCborValue &), value(const QCborValue &), operator[](const QCborValue &),
+ find(const QCborValue &), contains(const QCborValue &), take(const QCborValue &), extract()
+ */
+
+/*!
+ \fn QCborMap::iterator QCborMap::insert(value_type v)
+ \overload
+
+ Inserts the key-value pair in \a v into this map and returns a map iterator
+ pointing to the newly inserted pair.
+
+ If the map already had a key equal to \c{v.first}, its value will be
+ overwritten by \c{v.second}.
+
+ \sa operator[], erase(), extract()
+ */
+
+
+/*!
+ \fn QCborMap::iterator QCborMap::erase(const_iterator it)
+
+ Removes the key-value pair pointed to by the map iterator \a it and returns a
+ pointer to the next element, after removal.
+
+ \sa remove(), begin(), end(), insert(), extract()
+ */
+
+/*!
+ \overload
+
+ Removes the key-value pair pointed to by the map iterator \a it and returns a
+ pointer to the next element, after removal.
+
+ \sa remove(), begin(), end(), insert()
+ */
+QCborMap::iterator QCborMap::erase(QCborMap::iterator it)
+{
+ detach();
+
+ // remove both key and value
+ // ### optimize?
+ d->removeAt(it.item.i - 1);
+ d->removeAt(it.item.i - 1);
+ return it;
+}
+
+/*!
+ \fn QCborValue QCborMap::extract(iterator it)
+ \fn QCborValue QCborMap::extract(const_iterator it)
+
+ Extracts a value from the map at the position indicated by iterator \a it
+ and returns the value so extracted.
+
+ \sa insert(), erase(), take(), remove()
+ */
+QCborValue QCborMap::extract(iterator it)
+{
+ detach();
+ QCborValue v = d->extractAt(it.item.i);
+ // remove both key and value
+ // ### optimize?
+ d->removeAt(it.item.i - 1);
+ d->removeAt(it.item.i - 1);
+
+ return v;
+}
+
+/*!
+ \fn bool QCborMap::empty() const
+
+ Synonym for isEmpty(). This function is provided for compatibility with
+ generic code that uses the Standard Library API.
+
+ Returns true if this map is empty (size() == 0).
+
+ \sa isEmpty(), size()
+ */
+
+/*!
+ \fn int QCborMap::compare(const QCborMap &other) const
+
+ Compares this map and \a other, comparing each element in sequence, and
+ returns an integer that indicates whether this map should be sorted prior
+ to (if the result is negative) or after \a other (if the result is
+ positive). If this function returns 0, the two maps are equal and contain
+ the same elements.
+
+ Note that CBOR maps are unordered, which means that two maps containing the
+ very same pairs but in different order will still compare differently. To
+ avoid this, it is recommended to insert elements into the map in a
+ predictable order, such as by ascending key value. In fact, maps with keys
+ in sorted order are required for Canonical CBOR representation.
+
+ For more information on CBOR sorting order, see QCborValue::compare().
+
+ \sa QCborValue::compare(), QCborArray::compare(), operator==()
+ */
+
+/*!
+ \fn bool QCborMap::operator==(const QCborMap &other) const
+
+ Compares this map and \a other, comparing each element in sequence, and
+ returns true if the two maps contains the same elements in the same order,
+ false otherwise.
+
+ Note that CBOR maps are unordered, which means that two maps containing the
+ very same pairs but in different order will still compare differently. To
+ avoid this, it is recommended to insert elements into the map in a
+ predictable order, such as by ascending key value. In fact, maps with keys
+ in sorted order are required for Canonical CBOR representation.
+
+ For more information on CBOR equality in Qt, see, QCborValue::compare().
+
+ \sa compare(), QCborValue::operator==(), QCborMap::operator==(),
+ operator!=(), operator<()
+ */
+
+/*!
+ \fn bool QCborMap::operator!=(const QCborMap &other) const
+
+ Compares this map and \a other, comparing each element in sequence, and
+ returns true if the two maps contains any different elements or elements in
+ different orders, false otherwise.
+
+ Note that CBOR maps are unordered, which means that two maps containing the
+ very same pairs but in different order will still compare differently. To
+ avoid this, it is recommended to insert elements into the map in a
+ predictable order, such as by ascending key value. In fact, maps with keys
+ in sorted order are required for Canonical CBOR representation.
+
+ For more information on CBOR equality in Qt, see, QCborValue::compare().
+
+ \sa compare(), QCborValue::operator==(), QCborMap::operator==(),
+ operator==(), operator<()
+ */
+
+/*!
+ \fn bool QCborMap::operator<(const QCborMap &other) const
+
+ Compares this map and \a other, comparing each element in sequence, and
+ returns true if this map should be sorted before \a other, false
+ otherwise.
+
+ Note that CBOR maps are unordered, which means that two maps containing the
+ very same pairs but in different order will still compare differently. To
+ avoid this, it is recommended to insert elements into the map in a
+ predictable order, such as by ascending key value. In fact, maps with keys
+ in sorted order are required for Canonical CBOR representation.
+
+ For more information on CBOR sorting order, see QCborValue::compare().
+
+ \sa compare(), QCborValue::operator==(), QCborMap::operator==(),
+ operator==(), operator!=()
+ */
+
+void QCborMap::detach(qsizetype reserved)
+{
+ d = QCborContainerPrivate::detach(d.data(), reserved ? reserved : size() * 2);
+}
+
+/*!
+ \class QCborMap::Iterator
+ \inmodule QtCore
+ \ingroup cbor
+ \reentrant
+ \since 5.12
+
+ \brief The QCborMap::Iterator class provides an STL-style non-const iterator for QCborMap.
+
+ QCborMap::Iterator allows you to iterate over a QCborMap and to modify the
+ value (but not the key) stored under a particular key. If you want to
+ iterate over a const QCborMap, you should use QCborMap::ConstIterator. It
+ is generally good practice to use QCborMap::ConstIterator on a non-const
+ QCborMap as well, unless you need to change the QCborMap through the
+ iterator. Const iterators are slightly faster, and improve code
+ readability.
+
+ You must initialize the iterator using a QCborMap function like
+ QCborMap::begin(), QCborMap::end(), or QCborMap::find() before you can
+ start iterating..
+
+ Multiple iterators can be used on the same object. Existing iterators will however
+ become dangling once the object gets modified.
+
+ \sa QCborMap::ConstIterator
+*/
+
+/*!
+ \typedef QCborMap::Iterator::difference_type
+ \internal
+*/
+
+/*!
+ \typedef QCborMap::Iterator::iterator_category
+
+ A synonym for \e {std::random_access_iterator_tag} indicating
+ this iterator is a random-access iterator.
+*/
+
+/*!
+ \typedef QCborMap::Iterator::reference
+ \internal
+*/
+
+/*!
+ \typedef QCborMap::Iterator::value_type
+ \internal
+*/
+
+/*!
+ \typedef QCborMap::Iterator::pointer
+ \internal
+*/
+
+/*!
+ \fn QCborMap::Iterator::Iterator()
+
+ Constructs an uninitialized iterator.
+
+ Functions like key(), value(), and operator++() must not be
+ called on an uninitialized iterator. Use operator=() to assign a
+ value to it before using it.
+
+ \sa QCborMap::begin(), QCborMap::end()
+*/
+
+/*!
+ \fn QCborMap::Iterator::Iterator(const Iterator &other)
+
+ Constructs an iterator as a copy of \a other.
+ */
+
+/*!
+ \fn QCborMap::Iterator &QCborMap::Iterator::operator=(const Iterator &other)
+
+ Makes this iterator a copy of \a other and returns a reference to this
+ iterator.
+ */
+
+/*!
+ \fn QCborValue QCborMap::Iterator::key() const
+
+ Returns the current item's key.
+
+ There is no direct way of changing an item's key through an iterator,
+ although it can be done by calling QCborMap::erase() followed by
+ QCborMap::insert().
+
+ \sa value()
+*/
+
+/*!
+ \fn QCborValueRef QCborMap::Iterator::value() const
+
+ Returns a modifiable reference to the current item's value.
+
+ You can change the value for a key by using value() on the left side of an
+ assignment.
+
+ The return value is of type QCborValueRef, a helper class for QCborArray
+ and QCborMap. When you get an object of type QCborValueRef, you can use it
+ as if it were a reference to a QCborValue. If you assign to it, the
+ assignment will apply to the element in the QCborArray or QCborMap from
+ which you got the reference.
+
+ \sa key(), operator*()
+*/
+
+/*!
+ \fn QCborMap::Iterator::value_type QCborMap::Iterator::operator*() const
+
+ Returns a pair containing the current item's key and a modifiable reference
+ to the current item's value.
+
+ The second element of the pair is of type QCborValueRef, a helper class for
+ QCborArray and QCborMap. When you get an object of type QCborValueRef, you
+ can use it as if it were a reference to a QCborValue. If you assign to it,
+ the assignment will apply to the element in the QCborArray or QCborMap from
+ which you got the reference.
+
+ \sa key(), value()
+*/
+
+/*!
+ \fn QCborValueRef *QCborMap::Iterator::operator->() const
+
+ Returns a pointer to a modifiable reference to the current pair's value.
+*/
+
+/*!
+ \fn bool QCborMap::Iterator::operator==(const Iterator &other) const
+ \fn bool QCborMap::Iterator::operator==(const ConstIterator &other) const
+
+ Returns \c true if \a other points to the same entry in the map as this
+ iterator; otherwise returns \c false.
+
+ \sa operator!=()
+*/
+
+/*!
+ \fn bool QCborMap::Iterator::operator!=(const Iterator &other) const
+ \fn bool QCborMap::Iterator::operator!=(const ConstIterator &other) const
+
+ Returns \c true if \a other points to a different entry in the map than
+ this iterator; otherwise returns \c false.
+
+ \sa operator==()
+*/
+
+/*!
+ \fn bool QCborMap::Iterator::operator<(const Iterator& other) const
+ \fn bool QCborMap::Iterator::operator<(const ConstIterator& other) const
+
+ Returns \c true if the entry in the map pointed to by this iterator
+ occurs before the entry pointed to by the \a other iterator.
+*/
+
+/*!
+ \fn bool QCborMap::Iterator::operator<=(const Iterator& other) const
+ \fn bool QCborMap::Iterator::operator<=(const ConstIterator& other) const
+
+ Returns \c true if the entry in the map pointed to by this iterator
+ occurs before or is the same entry as is pointed to by the \a other
+ iterator.
+*/
+
+/*!
+ \fn bool QCborMap::Iterator::operator>(const Iterator& other) const
+ \fn bool QCborMap::Iterator::operator>(const ConstIterator& other) const
+
+ Returns \c true if the entry in the map pointed to by this iterator
+ occurs after the entry pointed to by the \a other iterator.
+ */
+
+/*!
+ \fn bool QCborMap::Iterator::operator>=(const Iterator& other) const
+ \fn bool QCborMap::Iterator::operator>=(const ConstIterator& other) const
+
+ Returns \c true if the entry in the map pointed to by this iterator
+ occurs after or is the same entry as is pointed to by the \a other
+ iterator.
+*/
+
+/*!
+ \fn QCborMap::Iterator &QCborMap::Iterator::operator++()
+
+ The prefix ++ operator, \c{++i}, advances the iterator to the next item in
+ the map and returns this iterator.
+
+ Calling this function on QCborMap::end() leads to undefined results.
+
+ \sa operator--()
+*/
+
+/*!
+ \fn QCborMap::Iterator QCborMap::Iterator::operator++(int)
+ \overload
+
+ The postfix ++ operator, \c{i++}, advances the iterator to the next item in
+ the map and returns an iterator to the previously current item.
+*/
+
+/*!
+ \fn QCborMap::Iterator QCborMap::Iterator::operator--()
+
+ The prefix -- operator, \c{--i}, makes the preceding item current and
+ returns this iterator.
+
+ Calling this function on QCborMap::begin() leads to undefined results.
+
+ \sa operator++()
+*/
+
+/*!
+ \fn QCborMap::Iterator QCborMap::Iterator::operator--(int)
+ \overload
+
+ The postfix -- operator, \c{i--}, makes the preceding item current and
+ returns an iterator pointing to the previously current item.
+*/
+
+/*!
+ \fn QCborMap::Iterator QCborMap::Iterator::operator+(qsizetype j) const
+
+ Returns an iterator to the item at \a j positions forward from this
+ iterator. If \a j is negative, the iterator goes backward.
+
+ \sa operator-()
+*/
+
+/*!
+ \fn QCborMap::Iterator QCborMap::Iterator::operator-(qsizetype j) const
+
+ Returns an iterator to the item at \a j positions backward from this
+ iterator. If \a j is negative, the iterator goes forward.
+
+ \sa operator+()
+*/
+
+/*!
+ \fn qsizetype QCborMap::Iterator::operator-(QCborMap::Iterator j) const
+
+ Returns the position of the item at iterator \a j relative to the item
+ at this iterator. If the item at \a j is forward of this time, the returned
+ value is negative.
+
+ \sa operator+()
+*/
+
+/*!
+ \fn QCborMap::Iterator &QCborMap::Iterator::operator+=(qsizetype j)
+
+ Advances the iterator by \a j items. If \a j is negative, the iterator goes
+ backward. Returns a reference to this iterator.
+
+ \sa operator-=(), operator+()
+*/
+
+/*!
+ \fn QCborMap::Iterator &QCborMap::Iterator::operator-=(qsizetype j)
+
+ Makes the iterator go back by \a j items. If \a j is negative, the iterator
+ goes forward. Returns a reference to this iterator.
+
+ \sa operator+=(), operator-()
+*/
+
+/*!
+ \class QCborMap::ConstIterator
+ \inmodule QtCore
+ \ingroup cbor
+ \since 5.12
+
+ \brief The QCborMap::ConstIterator class provides an STL-style const iterator for QCborMap.
+
+ QCborMap::ConstIterator allows you to iterate over a QCborMap. If you want
+ to modify the QCborMap as you iterate over it, you must use
+ QCborMap::Iterator instead. It is generally good practice to use
+ QCborMap::ConstIterator, even on a non-const QCborMap, when you don't need
+ to change the QCborMap through the iterator. Const iterators are slightly
+ faster and improve code readability.
+
+ You must initialize the iterator using a QCborMap function like
+ QCborMap::begin(), QCborMap::end(), or QCborMap::find() before you can
+ start iterating..
+
+ Multiple iterators can be used on the same object. Existing iterators
+ will however become dangling if the object gets modified.
+
+ \sa QCborMap::Iterator
+*/
+
+/*!
+ \typedef QCborMap::ConstIterator::difference_type
+ \internal
+*/
+
+/*!
+ \typedef QCborMap::ConstIterator::iterator_category
+
+ A synonym for \e {std::random_access_iterator_tag} indicating
+ this iterator is a random-access iterator.
+*/
+
+/*!
+ \typedef QCborMap::ConstIterator::reference
+ \internal
+*/
+
+/*!
+ \typedef QCborMap::ConstIterator::value_type
+ \internal
+*/
+
+/*!
+ \typedef QCborMap::ConstIterator::pointer
+ \internal
+*/
+
+/*!
+ \fn QCborMap::ConstIterator::ConstIterator()
+
+ Constructs an uninitialized iterator.
+
+ Functions like key(), value(), and operator++() must not be
+ called on an uninitialized iterator. Use operator=() to assign a
+ value to it before using it.
+
+ \sa QCborMap::constBegin(), QCborMap::constEnd()
+*/
+
+/*!
+ \fn QCborMap::ConstIterator::ConstIterator(const ConstIterator &other)
+
+ Constructs an iterator as a copy of \a other.
+ */
+
+/*!
+ \fn QCborMap::ConstIterator &QCborMap::ConstIterator::operator=(const ConstIterator &other)
+
+ Makes this iterator a copy of \a other and returns a reference to this
+ iterator.
+ */
+
+/*!
+ \fn QString QCborMap::ConstIterator::key() const
+
+ Returns the current item's key.
+
+ \sa value()
+*/
+
+/*!
+ \fn QCborValue QCborMap::ConstIterator::value() const
+
+ Returns the current item's value.
+
+ \sa key(), operator*()
+*/
+
+/*!
+ \fn QCborMap::ConstIterator::value_type QCborMap::ConstIterator::operator*() const
+
+ Returns a pair containing the curent item's key and value.
+
+ \sa key(), value()
+ */
+
+/*!
+ \fn const QCborValueRef *QCborMap::ConstIterator::operator->() const
+
+ Returns a pointer to the current pair's value.
+ */
+
+/*!
+ \fn bool QCborMap::ConstIterator::operator==(const ConstIterator &other) const
+ \fn bool QCborMap::ConstIterator::operator==(const Iterator &other) const
+
+ Returns \c true if \a other points to the same entry in the map as this
+ iterator; otherwise returns \c false.
+
+ \sa operator!=()
+*/
+
+/*!
+ \fn bool QCborMap::ConstIterator::operator!=(const ConstIterator &other) const
+ \fn bool QCborMap::ConstIterator::operator!=(const Iterator &other) const
+
+ Returns \c true if \a other points to a different entry in the map than
+ this iterator; otherwise returns \c false.
+
+ \sa operator==()
+ */
+
+/*!
+ \fn bool QCborMap::ConstIterator::operator<(const Iterator &other) const
+ \fn bool QCborMap::ConstIterator::operator<(const ConstIterator &other) const
+
+ Returns \c true if the entry in the map pointed to by this iterator
+ occurs before the entry pointed to by the \a other iterator.
+*/
+
+/*!
+ \fn bool QCborMap::ConstIterator::operator<=(const Iterator &other) const
+ \fn bool QCborMap::ConstIterator::operator<=(const ConstIterator &other) const
+
+ Returns \c true if the entry in the map pointed to by this iterator
+ occurs before or is the same entry as is pointed to by the \a other
+ iterator.
+*/
+
+/*!
+ \fn bool QCborMap::ConstIterator::operator>(const Iterator &other) const
+ \fn bool QCborMap::ConstIterator::operator>(const ConstIterator &other) const
+
+ Returns \c true if the entry in the map pointed to by this iterator
+ occurs after the entry pointed to by the \a other iterator.
+*/
+
+/*!
+ \fn bool QCborMap::ConstIterator::operator>=(const Iterator &other) const
+ \fn bool QCborMap::ConstIterator::operator>=(const ConstIterator &other) const
+
+ Returns \c true if the entry in the map pointed to by this iterator
+ occurs after or is the same entry as is pointed to by the \a other
+ iterator.
+*/
+
+/*!
+ \fn QCborMap::ConstIterator &QCborMap::ConstIterator::operator++()
+
+ The prefix ++ operator, \c{++i}, advances the iterator to the next item in
+ the map and returns this iterator.
+
+ Calling this function on QCborMap::end() leads to undefined results.
+
+ \sa operator--()
+*/
+
+/*!
+ \fn QCborMap::ConstIterator QCborMap::ConstIterator::operator++(int)
+ \overload
+
+ The postfix ++ operator, \c{i++}, advances the iterator to the next item in
+ the map and returns an iterator to the previously current item.
+ */
+
+/*!
+ \fn QCborMap::ConstIterator &QCborMap::ConstIterator::operator--()
+
+ The prefix -- operator, \c{--i}, makes the preceding item current and
+ returns this iterator.
+
+ Calling this function on QCborMap::begin() leads to undefined results.
+
+ \sa operator++()
+*/
+
+/*!
+ \fn QCborMap::ConstIterator QCborMap::ConstIterator::operator--(int)
+ \overload
+
+ The postfix -- operator, \c{i--}, makes the preceding item current and
+ returns an iterator pointing to the previously current item.
+ */
+
+/*!
+ \fn QCborMap::ConstIterator QCborMap::ConstIterator::operator+(qsizetype j) const
+
+ Returns an iterator to the item at \a j positions forward from this
+ iterator. If \a j is negative, the iterator goes backward.
+
+ \sa operator-()
+*/
+
+/*!
+ \fn QCborMap::ConstIterator QCborMap::ConstIterator::operator-(qsizetype j) const
+
+ Returns an iterator to the item at \a j positions backward from this
+ iterator. If \a j is negative, the iterator goes forward.
+
+ \sa operator+()
+*/
+
+/*!
+ \fn qsizetype QCborMap::ConstIterator::operator-(QCborMap::ConstIterator j) const
+
+ Returns the position of the item at iterator \a j relative to the item
+ at this iterator. If the item at \a j is forward of this time, the returned
+ value is negative.
+
+ \sa operator+()
+*/
+
+/*!
+ \fn QCborMap::ConstIterator &QCborMap::ConstIterator::operator+=(qsizetype j)
+
+ Advances the iterator by \a j items. If \a j is negative, the iterator goes
+ backward. Returns a reference to this iterator.
+
+ \sa operator-=(), operator+()
+*/
+
+/*!
+ \fn QCborMap::ConstIterator &QCborMap::ConstIterator::operator-=(qsizetype j)
+
+ Makes the iterator go back by \a j items. If \a j is negative, the iterator
+ goes forward. Returns a reference to this iterator.
+
+ \sa operator+=(), operator-()
+*/
+
+uint qHash(const QCborMap &map, uint seed)
+{
+ return qHashRange(map.begin(), map.end(), seed);
+}
+
+#if !defined(QT_NO_DEBUG_STREAM)
+QDebug operator<<(QDebug dbg, const QCborMap &m)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QCborMap{";
+ const char *open = "{";
+ for (auto pair : m) {
+ dbg << open << pair.first << ", " << pair.second << '}';
+ open = ", {";
+ }
+ return dbg << '}';
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qcbormap.h b/src/corelib/serialization/qcbormap.h
new file mode 100644
index 0000000000..3eb2107691
--- /dev/null
+++ b/src/corelib/serialization/qcbormap.h
@@ -0,0 +1,357 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://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 QCBORMAP_H
+#define QCBORMAP_H
+
+#include <QtCore/qcborvalue.h>
+#include <QtCore/qpair.h>
+
+#include <initializer_list>
+
+QT_BEGIN_NAMESPACE
+
+template <class Key, class T> class QMap;
+typedef QMap<QString, QVariant> QVariantMap;
+template <class Key, class T> class QHash;
+typedef QHash<QString, QVariant> QVariantHash;
+class QJsonObject;
+
+class QCborContainerPrivate;
+class Q_CORE_EXPORT QCborMap
+{
+public:
+ typedef QPair<QCborValue, QCborValue> value_type;
+ typedef QCborValue key_type;
+ typedef QCborValue mapped_type;
+ typedef qsizetype size_type;
+
+ class ConstIterator;
+ class Iterator {
+ mutable QCborValueRef item; // points to the value
+ friend class ConstIterator;
+ friend class QCborMap;
+ Iterator(QCborContainerPrivate *dd, qsizetype ii) : item(dd, ii) {}
+ public:
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef qsizetype difference_type;
+ typedef QPair<const QCborValueRef, QCborValueRef> value_type;
+ typedef QPair<const QCborValueRef, QCborValueRef> reference;
+ typedef QPair<const QCborValueRef, QCborValueRef> pointer;
+
+ Q_DECL_CONSTEXPR Iterator() = default;
+ Q_DECL_CONSTEXPR Iterator(const Iterator &) = default;
+ Iterator &operator=(const Iterator &other)
+ {
+ // rebind the reference
+ item.d = other.item.d;
+ item.i = other.item.i;
+ return *this;
+ }
+
+ value_type operator*() const { return { {item.d, item.i - 1}, item }; }
+ QCborValueRef *operator->() const { return &item; }
+ QCborValue key() const { return QCborValueRef(item.d, item.i - 1); }
+ QCborValueRef value() const { return item; }
+
+ bool operator==(const Iterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
+ bool operator!=(const Iterator &o) const { return !(*this == o); }
+ bool operator<(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
+ bool operator<=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
+ bool operator>(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
+ bool operator>=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
+ bool operator==(const ConstIterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
+ bool operator!=(const ConstIterator &o) const { return !(*this == o); }
+ bool operator<(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
+ bool operator<=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
+ bool operator>(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
+ bool operator>=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
+ Iterator &operator++() { item.i += 2; return *this; }
+ Iterator operator++(int) { Iterator n = *this; item.i += 2; return n; }
+ Iterator &operator--() { item.i -= 2; return *this; }
+ Iterator operator--(int) { Iterator n = *this; item.i -= 2; return n; }
+ Iterator &operator+=(qsizetype j) { item.i += 2 * j; return *this; }
+ Iterator &operator-=(qsizetype j) { item.i -= 2 * j; return *this; }
+ Iterator operator+(qsizetype j) const { return Iterator({ item.d, item.i + 2 * j }); }
+ Iterator operator-(qsizetype j) const { return Iterator({ item.d, item.i - 2 * j }); }
+ qsizetype operator-(Iterator j) const { return (item.i - j.item.i) / 2; }
+ };
+
+ class ConstIterator {
+ QCborValueRef item; // points to the value
+ friend class Iterator;
+ friend class QCborMap;
+ ConstIterator(QCborContainerPrivate *dd, qsizetype ii) : item(dd, ii) {}
+ public:
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef qsizetype difference_type;
+ typedef QPair<const QCborValueRef, const QCborValueRef> value_type;
+ typedef QPair<const QCborValueRef, const QCborValueRef> reference;
+ typedef QPair<const QCborValueRef, const QCborValueRef> pointer;
+
+ Q_DECL_CONSTEXPR ConstIterator() = default;
+ Q_DECL_CONSTEXPR ConstIterator(const ConstIterator &) = default;
+ ConstIterator &operator=(const ConstIterator &other)
+ {
+ // rebind the reference
+ item.d = other.item.d;
+ item.i = other.item.i;
+ return *this;
+ }
+
+ value_type operator*() const { return { {item.d, item.i - 1}, item }; }
+ const QCborValueRef *operator->() const { return &item; }
+ QCborValue key() const { return QCborValueRef(item.d, item.i - 1); }
+ QCborValueRef value() const { return item; }
+
+ bool operator==(const Iterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
+ bool operator!=(const Iterator &o) const { return !(*this == o); }
+ bool operator<(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
+ bool operator<=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
+ bool operator>(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
+ bool operator>=(const Iterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
+ bool operator==(const ConstIterator &o) const { return item.d == o.item.d && item.i == o.item.i; }
+ bool operator!=(const ConstIterator &o) const { return !(*this == o); }
+ bool operator<(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i < other.item.i; }
+ bool operator<=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i <= other.item.i; }
+ bool operator>(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i > other.item.i; }
+ bool operator>=(const ConstIterator& other) const { Q_ASSERT(item.d == other.item.d); return item.i >= other.item.i; }
+ ConstIterator &operator++() { item.i += 2; return *this; }
+ ConstIterator operator++(int) { ConstIterator n = *this; item.i += 2; return n; }
+ ConstIterator &operator--() { item.i -= 2; return *this; }
+ ConstIterator operator--(int) { ConstIterator n = *this; item.i -= 2; return n; }
+ ConstIterator &operator+=(qsizetype j) { item.i += 2 * j; return *this; }
+ ConstIterator &operator-=(qsizetype j) { item.i -= 2 * j; return *this; }
+ ConstIterator operator+(qsizetype j) const { return ConstIterator({ item.d, item.i + 2 * j }); }
+ ConstIterator operator-(qsizetype j) const { return ConstIterator({ item.d, item.i - 2 * j }); }
+ qsizetype operator-(ConstIterator j) const { return (item.i - j.item.i) / 2; }
+ };
+
+ QCborMap() noexcept;
+ QCborMap(const QCborMap &other) noexcept;
+ QCborMap &operator=(const QCborMap &other) noexcept;
+ QCborMap(std::initializer_list<value_type> args)
+ : QCborMap()
+ {
+ detach(args.size());
+ for (auto pair : args)
+ insert(pair.first, pair.second);
+ }
+ ~QCborMap();
+
+ void swap(QCborMap &other) noexcept
+ {
+ qSwap(d, other.d);
+ }
+
+ QCborValue toCborValue() const { return *this; }
+
+ qsizetype size() const noexcept Q_DECL_PURE_FUNCTION;
+ bool isEmpty() const { return size() == 0; }
+ void clear();
+ QVector<QCborValue> keys() const;
+
+ QCborValue value(qint64 key) const
+ { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
+ QCborValue value(QLatin1String key) const
+ { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
+ QCborValue value(const QString & key) const
+ { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
+ QCborValue value(const QCborValue &key) const
+ { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
+#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
+ template<size_t N> QT_ASCII_CAST_WARN const QCborValue value(const char (&key)[N]) const
+ { return value(QString::fromUtf8(key, N - 1)); }
+#endif
+ const QCborValue operator[](qint64 key) const
+ { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
+ const QCborValue operator[](QLatin1String key) const
+ { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
+ const QCborValue operator[](const QString & key) const
+ { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
+ const QCborValue operator[](const QCborValue &key) const
+ { const_iterator it = find(key); return it == end() ? QCborValue() : it.value(); }
+#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
+ template<size_t N> QT_ASCII_CAST_WARN const QCborValue operator[](const char (&key)[N]) const
+ { return operator[](QString::fromUtf8(key, N - 1)); }
+#endif
+ QCborValueRef operator[](qint64 key);
+ QCborValueRef operator[](QLatin1String key);
+ QCborValueRef operator[](const QString & key);
+ QCborValueRef operator[](const QCborValue &key);
+
+ QCborValue take(qint64 key)
+ { const_iterator it = constFind(key); if (it != constEnd()) return extract(it); return QCborValue(); }
+ QCborValue take(QLatin1String key)
+ { const_iterator it = constFind(key); if (it != constEnd()) return extract(it); return QCborValue(); }
+ QCborValue take(const QString &key)
+ { const_iterator it = constFind(key); if (it != constEnd()) return extract(it); return QCborValue(); }
+ QCborValue take(const QCborValue &key)
+ { const_iterator it = constFind(key); if (it != constEnd()) return extract(it); return QCborValue(); }
+ void remove(qint64 key)
+ { const_iterator it = constFind(key); if (it != constEnd()) erase(it); }
+ void remove(QLatin1String key)
+ { const_iterator it = constFind(key); if (it != constEnd()) erase(it); }
+ void remove(const QString & key)
+ { const_iterator it = constFind(key); if (it != constEnd()) erase(it); }
+ void remove(const QCborValue &key)
+ { const_iterator it = constFind(key); if (it != constEnd()) erase(it); }
+ bool contains(qint64 key) const
+ { const_iterator it = find(key); return it != end(); }
+ bool contains(QLatin1String key) const
+ { const_iterator it = find(key); return it != end(); }
+ bool contains(const QString & key) const
+ { const_iterator it = find(key); return it != end(); }
+ bool contains(const QCborValue &key) const
+ { const_iterator it = find(key); return it != end(); }
+
+ int compare(const QCborMap &other) const noexcept Q_DECL_PURE_FUNCTION;
+#if 0 && QT_HAS_INCLUDE(<compare>)
+ std::strong_ordering operator<=>(const QCborMap &other) const
+ {
+ int c = compare(other);
+ if (c > 0) return std::strong_ordering::greater;
+ if (c == 0) return std::strong_ordering::equivalent;
+ return std::strong_ordering::less;
+ }
+#else
+ bool operator==(const QCborMap &other) const noexcept
+ { return compare(other) == 0; }
+ bool operator!=(const QCborMap &other) const noexcept
+ { return !(*this == other); }
+ bool operator<(const QCborMap &other) const
+ { return compare(other) < 0; }
+#endif
+
+ typedef Iterator iterator;
+ typedef ConstIterator const_iterator;
+ iterator begin() { detach(); return iterator{d.data(), 1}; }
+ const_iterator constBegin() const { return const_iterator{d.data(), 1}; }
+ const_iterator begin() const { return constBegin(); }
+ const_iterator cbegin() const { return constBegin(); }
+ iterator end() { detach(); return iterator{d.data(), 2 * size() + 1}; }
+ const_iterator constEnd() const { return const_iterator{d.data(), 2 * size() + 1}; }
+ const_iterator end() const { return constEnd(); }
+ const_iterator cend() const { return constEnd(); }
+ iterator erase(iterator it);
+ iterator erase(const_iterator it) { return erase(iterator{ it.item.d, it.item.i }); }
+ QCborValue extract(iterator it);
+ QCborValue extract(const_iterator it) { return extract(iterator{ it.item.d, it.item.i }); }
+ bool empty() const { return isEmpty(); }
+
+ iterator find(qint64 key);
+ iterator find(QLatin1String key);
+ iterator find(const QString & key);
+ iterator find(const QCborValue &key);
+ const_iterator constFind(qint64 key) const;
+ const_iterator constFind(QLatin1String key) const;
+ const_iterator constFind(const QString & key) const;
+ const_iterator constFind(const QCborValue &key) const;
+ const_iterator find(qint64 key) const { return constFind(key); }
+ const_iterator find(QLatin1String key) const { return constFind(key); }
+ const_iterator find(const QString & key) const { return constFind(key); }
+ const_iterator find(const QCborValue &key) const { return constFind(key); }
+
+ iterator insert(qint64 key, const QCborValue &value_)
+ {
+ QCborValueRef v = operator[](key); // detaches
+ v = value_;
+ return { d.data(), v.i };
+ }
+ iterator insert(QLatin1String key, const QCborValue &value_)
+ {
+ QCborValueRef v = operator[](key); // detaches
+ v = value_;
+ return { d.data(), v.i };
+ }
+ iterator insert(const QString &key, const QCborValue &value_)
+ {
+ QCborValueRef v = operator[](key); // detaches
+ v = value_;
+ return { d.data(), v.i };
+ }
+ iterator insert(const QCborValue &key, const QCborValue &value_)
+ {
+ QCborValueRef v = operator[](key); // detaches
+ v = value_;
+ return { d.data(), v.i };
+ }
+ iterator insert(value_type v) { return insert(v.first, v.second); }
+
+ static QCborMap fromVariantMap(const QVariantMap &map);
+ static QCborMap fromVariantHash(const QVariantHash &hash);
+ static QCborMap fromJsonObject(const QJsonObject &o);
+ QVariantMap toVariantMap() const;
+ QVariantHash toVariantHash() const;
+ QJsonObject toJsonObject() const;
+
+private:
+ void detach(qsizetype reserve = 0);
+
+ friend QCborValue;
+ explicit QCborMap(QCborContainerPrivate &dd) noexcept;
+ QExplicitlySharedDataPointer<QCborContainerPrivate> d;
+};
+
+Q_DECLARE_SHARED(QCborMap)
+
+inline QCborValue::QCborValue(QCborMap &&m)
+ : n(-1), container(m.d.take()), t(Map)
+{
+}
+
+inline QCborMap QCborValueRef::toMap() const
+{
+ return concrete().toMap();
+}
+
+inline QCborMap QCborValueRef::toMap(const QCborMap &m) const
+{
+ return concrete().toMap(m);
+}
+
+Q_CORE_EXPORT uint qHash(const QCborMap &map, uint seed = 0);
+
+#if !defined(QT_NO_DEBUG_STREAM)
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborMap &m);
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QCBORMAP_H
diff --git a/src/corelib/serialization/qcborstream.cpp b/src/corelib/serialization/qcborstream.cpp
new file mode 100644
index 0000000000..22286188b8
--- /dev/null
+++ b/src/corelib/serialization/qcborstream.cpp
@@ -0,0 +1,2705 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://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 "qcborstream.h"
+
+#include <private/qnumeric_p.h>
+#include <private/qutfcodec_p.h>
+#include <qbuffer.h>
+#include <qdebug.h>
+#include <qstack.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QT_NO_DEBUG
+# define NDEBUG 1
+#endif
+#undef assert
+#define assert Q_ASSERT
+
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Wunused-function")
+QT_WARNING_DISABLE_CLANG("-Wunused-function")
+QT_WARNING_DISABLE_CLANG("-Wundefined-internal")
+QT_WARNING_DISABLE_MSVC(4334) // '<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)
+
+#define CBOR_ENCODER_NO_CHECK_USER
+
+#define CBOR_NO_VALIDATION_API 1
+#define CBOR_NO_PRETTY_API 1
+#define CBOR_API static inline
+#define CBOR_PRIVATE_API static inline
+#define CBOR_INLINE_API static inline
+
+#include <cbor.h>
+
+static CborError qt_cbor_encoder_write_callback(void *token, const void *data, size_t len, CborEncoderAppendType);
+static bool qt_cbor_decoder_can_read(void *token, size_t len);
+static void qt_cbor_decoder_advance(void *token, size_t len);
+static void *qt_cbor_decoder_read(void *token, void *userptr, size_t offset, size_t len);
+static CborError qt_cbor_decoder_transfer_string(void *token, const void **userptr, size_t offset, size_t len);
+
+#define CBOR_ENCODER_WRITER_CONTROL 1
+#define CBOR_ENCODER_WRITE_FUNCTION qt_cbor_encoder_write_callback
+
+#define CBOR_PARSER_READER_CONTROL 1
+#define CBOR_PARSER_CAN_READ_BYTES_FUNCTION qt_cbor_decoder_can_read
+#define CBOR_PARSER_ADVANCE_BYTES_FUNCTION qt_cbor_decoder_advance
+#define CBOR_PARSER_TRANSFER_STRING_FUNCTION qt_cbor_decoder_transfer_string
+#define CBOR_PARSER_READ_BYTES_FUNCTION qt_cbor_decoder_read
+
+#include "../3rdparty/tinycbor/src/cborencoder.c"
+#include "../3rdparty/tinycbor/src/cborerrorstrings.c"
+#include "../3rdparty/tinycbor/src/cborparser.c"
+
+// silence compilers that complain about this being a static function declared
+// but never defined
+static CborError cbor_encoder_close_container_checked(CborEncoder*, const CborEncoder*)
+{
+ Q_UNREACHABLE();
+ return CborErrorInternalError;
+}
+static CborError _cbor_value_dup_string(const CborValue *, void **, size_t *, CborValue *)
+{
+ Q_UNREACHABLE();
+ return CborErrorInternalError;
+}
+QT_WARNING_POP
+
+Q_DECLARE_TYPEINFO(CborEncoder, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(CborValue, Q_PRIMITIVE_TYPE);
+
+// confirm our constants match TinyCBOR's
+Q_STATIC_ASSERT(int(QCborStreamReader::UnsignedInteger) == CborIntegerType);
+Q_STATIC_ASSERT(int(QCborStreamReader::ByteString) == CborByteStringType);
+Q_STATIC_ASSERT(int(QCborStreamReader::TextString) == CborTextStringType);
+Q_STATIC_ASSERT(int(QCborStreamReader::Array) == CborArrayType);
+Q_STATIC_ASSERT(int(QCborStreamReader::Map) == CborMapType);
+Q_STATIC_ASSERT(int(QCborStreamReader::Tag) == CborTagType);
+Q_STATIC_ASSERT(int(QCborStreamReader::SimpleType) == CborSimpleType);
+Q_STATIC_ASSERT(int(QCborStreamReader::HalfFloat) == CborHalfFloatType);
+Q_STATIC_ASSERT(int(QCborStreamReader::Float) == CborFloatType);
+Q_STATIC_ASSERT(int(QCborStreamReader::Double) == CborDoubleType);
+Q_STATIC_ASSERT(int(QCborStreamReader::Invalid) == CborInvalidType);
+
+/*!
+ \headerfile <QtCborCommon>
+
+ \brief The <QtCborCommon> header contains definitions common to both the
+ streaming classes (QCborStreamReader and QCborStreamWriter) and to
+ QCborValue.
+ */
+
+/*!
+ \enum QCborSimpleType
+ \relates <QtCborCommon>
+
+ This enum contains the possible "Simple Types" for CBOR. Simple Types range
+ from 0 to 255 and are types that carry no further value.
+
+ The following values are currently known:
+
+ \value False A "false" boolean.
+ \value True A "true" boolean.
+ \value Null Absence of value (null).
+ \value Undefined Missing or deleted value, usually an error.
+
+ Qt CBOR API supports encoding and decoding any Simple Type, whether one of
+ those above or any other value.
+
+ Applications should only use further values if a corresponding specification
+ has been published, otherwise interpretation and validation by the remote
+ may fail. Values 24 to 31 are reserved and must not be used.
+
+ The current authoritative list is maintained by IANA in the
+ \l{https://www.iana.org/assignments/cbor-simple-values/cbor-simple-values.xml}{Simple
+ Values registry}.
+
+ \sa QCborStreamWriter::append(QCborSimpleType), QCborStreamReader::isSimpleType(),
+ QCborStreamReader::toSimpleType(), QCborValue::isSimpleType(), QCborValue::toSimpleType()
+ */
+
+Q_CORE_EXPORT const char *qt_cbor_simpletype_id(QCborSimpleType st)
+{
+ switch (st) {
+ case QCborSimpleType::False:
+ return "False";
+ case QCborSimpleType::True:
+ return "True";
+ case QCborSimpleType::Null:
+ return "Null";
+ case QCborSimpleType::Undefined:
+ return "Undefined";
+ }
+ return nullptr;
+}
+
+#if !defined(QT_NO_DEBUG_STREAM)
+QDebug operator<<(QDebug dbg, QCborSimpleType st)
+{
+ QDebugStateSaver saver(dbg);
+ const char *id = qt_cbor_simpletype_id(st);
+ if (id)
+ return dbg.nospace() << "QCborSimpleType::" << id;
+
+ return dbg.nospace() << "QCborSimpleType(" << uint(st) << ')';
+}
+#endif
+
+/*!
+ \enum QCborTag
+ \relates <QtCborCommon>
+
+ This enum contains no enumeration and is used only to provide type-safe
+ access to a CBOR tag.
+
+ CBOR tags are 64-bit numbers that are attached to generic CBOR types to
+ provide further semantic meaning. QCborTag may be constructed from an
+ enumeration found in QCborKnownTags or directly by providing the numeric
+ representation.
+
+ For example, the following creates a QCborValue containing a byte array
+ tagged with a tag 2.
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 0
+
+ \sa QCborKnownTags, QCborStreamWriter::append(QCborTag),
+ QCborStreamReader::isTag(), QCborStreamReader::toTag(),
+ QCborValue::isTag(), QCborValue::tag()
+ */
+
+Q_CORE_EXPORT const char *qt_cbor_tag_id(QCborTag tag)
+{
+ // Casting to QCborKnownTags's underlying type will make the comparison
+ // below fail if the tag value is out of range.
+ auto n = std::underlying_type<QCborKnownTags>::type(tag);
+ if (QCborTag(n) == tag) {
+ switch (QCborKnownTags(n)) {
+ case QCborKnownTags::DateTimeString:
+ return "DateTimeString";
+ case QCborKnownTags::UnixTime_t:
+ return "UnixTime_t";
+ case QCborKnownTags::PositiveBignum:
+ return "PositiveBignum";
+ case QCborKnownTags::NegativeBignum:
+ return "NegativeBignum";
+ case QCborKnownTags::Decimal:
+ return "Decimal";
+ case QCborKnownTags::Bigfloat:
+ return "Bigfloat";
+ case QCborKnownTags::COSE_Encrypt0:
+ return "COSE_Encrypt0";
+ case QCborKnownTags::COSE_Mac0:
+ return "COSE_Mac0";
+ case QCborKnownTags::COSE_Sign1:
+ return "COSE_Sign1";
+ case QCborKnownTags::ExpectedBase64url:
+ return "ExpectedBase64url";
+ case QCborKnownTags::ExpectedBase64:
+ return "ExpectedBase64";
+ case QCborKnownTags::ExpectedBase16:
+ return "ExpectedBase16";
+ case QCborKnownTags::EncodedCbor:
+ return "EncodedCbor";
+ case QCborKnownTags::Url:
+ return "Url";
+ case QCborKnownTags::Base64url:
+ return "Base64url";
+ case QCborKnownTags::Base64:
+ return "Base64";
+ case QCborKnownTags::RegularExpression:
+ return "RegularExpression";
+ case QCborKnownTags::MimeMessage:
+ return "MimeMessage";
+ case QCborKnownTags::Uuid:
+ return "Uuid";
+ case QCborKnownTags::COSE_Encrypt:
+ return "COSE_Encrypt";
+ case QCborKnownTags::COSE_Mac:
+ return "COSE_Mac";
+ case QCborKnownTags::COSE_Sign:
+ return "COSE_Sign";
+ case QCborKnownTags::Signature:
+ return "Signature";
+ }
+ }
+ return nullptr;
+}
+
+#if !defined(QT_NO_DEBUG_STREAM)
+QDebug operator<<(QDebug dbg, QCborTag tag)
+{
+ QDebugStateSaver saver(dbg);
+ const char *id = qt_cbor_tag_id(tag);
+ dbg.nospace() << "QCborTag(";
+ if (id)
+ dbg.nospace() << "QCborKnownTags::" << id;
+ else
+ dbg.nospace() << quint64(tag);
+
+ return dbg << ')';
+}
+#endif
+
+/*!
+ \enum QCborKnownTags
+ \relates <QtCborCommon>
+
+ This enum contains a list of CBOR tags, known at the time of the Qt
+ implementation. This list is not meant to be complete and contains only
+ tags that are either backed by an RFC or specifically used by the Qt
+ implementation.
+
+ The authoritative list is maintained by IANA in the
+ \l{https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml}{CBOR tag
+ registry}.
+
+ \value DateTimeString A date and time string, formatted according to RFC 3339, as refined
+ by RFC 4287. It is the same format as Qt::ISODate and
+ Qt::ISODateWithMs.
+ \value UnixTime_t A numerical representation of seconds elapsed since
+ 1970-01-01T00:00Z.
+ \value PositiveBignum A positive number of arbitrary length, encoded as a byte array in
+ network byte order. For example, the number 2\sup{64} is represented by
+ a byte array containing the byte value 0x01 followed by 8 zero bytes.
+ \value NegativeBignum A negative number of arbirary length, encoded as the absolute value
+ of that number, minus one. For example, a byte array containing
+ byte value 0x02 followed by 8 zero bytes represents the number
+ -2\sup{65} - 1.
+ \value Decimal A decimal fraction, encoded as an array of two integers: the first
+ is the exponent of the power of 10, the second the integral
+ mantissa. The value 273.15 would be encoded as array \c{[-2, 27315]}.
+ \value Bigfloat Similar to Decimal, but the exponent is a power of 2 instead.
+ \value COSE_Encrypt0 An \c Encrypt0 map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
+ (CBOR Object Signing and Encryption).
+ \value COSE_Mac0 A \c Mac0 map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
+ (CBOR Object Signing and Encryption).
+ \value COSE_Sign1 A \c Sign1 map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
+ (CBOR Object Signing and Encryption).
+ \value ExpectedBase64url Indicates that the byte array should be encoded using Base64url
+ if the stream is converted to JSON.
+ \value ExpectedBase64 Indicates that the byte array should be encoded using Base64
+ if the stream is converted to JSON.
+ \value ExpectedBase16 Indicates that the byte array should be encoded using Base16 (hex)
+ if the stream is converted to JSON.
+ \value EncodedCbor Indicates that the byte array contains a CBOR stream.
+ \value Url Indicates that the string contains a URL.
+ \value Base64url Indicates that the string contains data encoded using Base64url.
+ \value Base64 Indicates that the string contains data encoded using Base64.
+ \value RegularExpression Indicates that the string contains a Perl-Compatible Regular
+ Expression pattern.
+ \value MimeMessage Indicates that the string contains a MIME message (according to
+ \l{https://tools.ietf.org/html/rfc2045}){RFC 2045}.
+ \value Uuid Indicates that the byte array contains a UUID.
+ \value COSE_Encrypt An \c Encrypt map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
+ (CBOR Object Signing and Encryption).
+ \value COSE_Mac A \c Mac map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
+ (CBOR Object Signing and Encryption).
+ \value COSE_Sign A \c Sign map as specified by \l{https://tools.ietf.org/html/rfc8152}{RFC 8152}
+ (CBOR Object Signing and Encryption).
+ \value Signature No change in interpretation; this tag can be used as the outermost
+ tag in a CBOR stream as the file header.
+
+ The following tags are interpreted by QCborValue during decoding and will
+ produce objects with extended Qt types, and it will use those tags when
+ encoding the same extended types.
+
+ \value DateTimeString \l QDateTime
+ \value UnixTime_t \l QDateTime (only in decoding)
+ \value Url \l QUrl
+ \value Uuid \l QUuid
+
+ Additionally, if a QCborValue containing a QByteArray is tagged using one of
+ \c ExpectedBase64url, \c ExpectedBase64 or \c ExpectedBase16, QCborValue
+ will use the expected encoding when converting to JSON (see
+ QCborValue::toJsonValue).
+
+ \sa QCborTag, QCborStreamWriter::append(QCborTag),
+ QCborStreamReader::isTag(), QCborStreamReader::toTag(),
+ QCborValue::isTag(), QCborValue::tag()
+ */
+
+#if !defined(QT_NO_DEBUG_STREAM)
+QDebug operator<<(QDebug dbg, QCborKnownTags tag)
+{
+ QDebugStateSaver saver(dbg);
+ const char *id = qt_cbor_tag_id(QCborTag(int(tag)));
+ if (id)
+ return dbg.nospace() << "QCborKnownTags::" << id;
+
+ return dbg.nospace() << "QCborKnownTags(" << int(tag) << ')';
+}
+#endif
+
+/*!
+ \class QCborError
+ \inmodule QtCore
+ \relates <QtCborCommon>
+ \reentrant
+ \since 5.12
+
+ \brief The QCborError class holds the error condition found while parsing or
+ validating a CBOR stream.
+
+ \sa QCborStreamReader, QCborValue, QCborParserError
+ */
+
+/*!
+ \enum QCborError::Code
+
+ This enum contains the possible error condition codes.
+
+ \value NoError No error was detected.
+ \value UnknownError An unknown error occurred and no further details are available.
+ \value AdvancePastEnd QCborStreamReader::next() was called but there are no more elements in
+ the current context.
+ \value InputOutputError An I/O error with the QIODevice occurred.
+ \value GarbageAtEnd Data was found in the input stream after the last element.
+ \value EndOfFile The end of the input stream was unexpectedly reached while processing an
+ element.
+ \value UnexpectedBreak The CBOR stream contains a Break where it is not allowed (data is
+ corrupt and the error is not recoverable).
+ \value UnknownType The CBOR stream contains an unknown/unparseable Type (data is corrupt
+ and the and the error is not recoverable).
+ \value IllegalType The CBOR stream contains a known type in a position it is not allowed
+ to exist (data is corrupt and the error is not recoverable).
+ \value IllegalNumber The CBOR stream appears to be encoding a number larger than 64-bit
+ (data is corrupt and the error is not recoverable).
+ \value IllegalSimpleType The CBOR stream contains a Simple Type encoded incorrectly (data is
+ corrupt and the error is not recoverable).
+ \value InvalidUtf8String The CBOR stream contains a text string that does not decode properly
+ as UTF (data is corrupt and the error is not recoverable).
+ \value DataTooLarge CBOR string, map or array is too big and cannot be parsed by Qt
+ (internal limitation, but the error is not recoverable).
+ \value NestingTooDeep Too many levels of arrays or maps encountered while processing the
+ input (internal limitation, but the error is not recoverable).
+ \value UnsupportedType The CBOR stream contains a known type that the implementation does not
+ support (internal limitation, but the error is not recoverable).
+ */
+
+/*!
+ \variable QCborError::c
+ \internal
+ */
+
+/*!
+ \fn QCborError::operator Code() const
+
+ Returns the error code that this QCborError object stores.
+ */
+
+/*!
+ Returns a text string that matches the error code in this QCborError object.
+
+ Note: the string is not translated. Applications whose interface allow users
+ to parse CBOR streams need to provide their own, translated strings.
+
+ \sa QCborError::Code
+ */
+QString QCborError::toString() const
+{
+ switch (c) {
+ case NoError:
+ Q_STATIC_ASSERT(int(NoError) == int(CborNoError));
+ return QString();
+
+ case UnknownError:
+ Q_STATIC_ASSERT(int(UnknownError) == int(CborUnknownError));
+ return QStringLiteral("Unknown error");
+ case AdvancePastEnd:
+ Q_STATIC_ASSERT(int(AdvancePastEnd) == int(CborErrorAdvancePastEOF));
+ return QStringLiteral("Read past end of buffer (more bytes needed)");
+ case InputOutputError:
+ Q_STATIC_ASSERT(int(InputOutputError) == int(CborErrorIO));
+ return QStringLiteral("Input/Output error");
+ case GarbageAtEnd:
+ Q_STATIC_ASSERT(int(GarbageAtEnd) == int(CborErrorGarbageAtEnd));
+ return QStringLiteral("Data found after the end of the stream");
+ case EndOfFile:
+ Q_STATIC_ASSERT(int(EndOfFile) == int(CborErrorUnexpectedEOF));
+ return QStringLiteral("Unexpected end of input data (more bytes needed)");
+ case UnexpectedBreak:
+ Q_STATIC_ASSERT(int(UnexpectedBreak) == int(CborErrorUnexpectedBreak));
+ return QStringLiteral("Invalid CBOR stream: unexpected 'break' byte");
+ case UnknownType:
+ Q_STATIC_ASSERT(int(UnknownType) == int(CborErrorUnknownType));
+ return QStringLiteral("Invalid CBOR stream: unknown type");
+ case IllegalType:
+ Q_STATIC_ASSERT(int(IllegalType) == int(CborErrorIllegalType));
+ return QStringLiteral("Invalid CBOR stream: illegal type found");
+ case IllegalNumber:
+ Q_STATIC_ASSERT(int(IllegalNumber) == int(CborErrorIllegalNumber));
+ return QStringLiteral("Invalid CBOR stream: illegal number encoding (future extension)");
+ case IllegalSimpleType:
+ Q_STATIC_ASSERT(int(IllegalSimpleType) == int(CborErrorIllegalSimpleType));
+ return QStringLiteral("Invalid CBOR stream: illegal simple type");
+ case InvalidUtf8String:
+ Q_STATIC_ASSERT(int(InvalidUtf8String) == int(CborErrorInvalidUtf8TextString));
+ return QStringLiteral("Invalid CBOR stream: invalid UTF-8 text string");
+ case DataTooLarge:
+ Q_STATIC_ASSERT(int(DataTooLarge) == int(CborErrorDataTooLarge));
+ return QStringLiteral("Internal limitation: data set too large");
+ case NestingTooDeep:
+ Q_STATIC_ASSERT(int(NestingTooDeep) == int(CborErrorNestingTooDeep));
+ return QStringLiteral("Internal limitation: data nesting too deep");
+ case UnsupportedType:
+ Q_STATIC_ASSERT(int(UnsupportedType) == int(CborErrorUnsupportedType));
+ return QStringLiteral("Internal limitation: unsupported type");
+ }
+
+ // get the error from TinyCBOR
+ CborError err = CborError(int(c));
+ return QString::fromLatin1(cbor_error_string(err));
+}
+
+/*!
+ \class QCborStreamWriter
+ \inmodule QtCore
+ \ingroup cbor
+ \reentrant
+ \since 5.12
+
+ \brief The QCborStreamWriter class is a simple CBOR encoder operating on a
+ one-way stream.
+
+ This class can be used to quickly encode a stream of CBOR content directly
+ to either a QByteArray or QIODevice. CBOR is the Concise Binary Object
+ Representation, a very compact form of binary data encoding that is
+ compatible with JSON. It was created by the IETF Constrained RESTful
+ Environments (CoRE) WG, which has used it in many new RFCs. It is meant to
+ be used alongside the \l{https://tools.ietf.org/html/rfc7252}{CoAP
+ protocol}.
+
+ QCborStreamWriter provides a StAX-like API, similar to that of
+ \l{QXmlStreamWriter}. It is rather low-level and requires a bit of knowledge
+ of CBOR encoding. For a simpler API, see \l{QCborValue} and especially the
+ encoding function QCborValue::toCbor().
+
+ The typical use of QCborStreamWriter is to create the object on the target
+ QByteArray or QIODevice, then call one of the append() overloads with the
+ desired type to be encoded. To create arrays and maps, QCborStreamWriter
+ provides startArray() and startMap() overloads, which must be terminated by
+ the corresponding endArray() and endMap() functions.
+
+ The following example encodes the equivalent of this JSON content:
+
+ \div{class="pre"}
+ {
+ "label": "journald",
+ "autoDetect": false,
+ "condition": "libs.journald",
+ "output": [ "privateFeature" ]
+ }
+ \enddiv
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 1
+
+ \section1 CBOR support
+
+ QCborStreamWriter supports all CBOR features required to create canonical
+ and strict streams. It implements almost all of the features specified in
+ \l {https://tools.ietf.org/html/rfc7049}{RFC 7049}.
+
+ The following table lists the CBOR features that QCborStreamWriter supports.
+
+ \table
+ \header \li Feature \li Support
+ \row \li Unsigned numbers \li Yes (full range)
+ \row \li Negative numbers \li Yes (full range)
+ \row \li Byte strings \li Yes
+ \row \li Text strings \li Yes
+ \row \li Chunked strings \li No
+ \row \li Tags \li Yes (arbitrary)
+ \row \li Booleans \li Yes
+ \row \li Null \li Yes
+ \row \li Undefined \li Yes
+ \row \li Arbitrary simple values \li Yes
+ \row \li Half-precision float (16-bit) \li Yes
+ \row \li Single-precision float (32-bit) \li Yes
+ \row \li Double-precision float (64-bit) \li Yes
+ \row \li Infinities and NaN floating point \li Yes
+ \row \li Determinate-length arrays and maps \li Yes
+ \row \li Indeterminate-length arrays and maps \li Yes
+ \row \li Map key types other than strings and integers \li Yes (arbitrary)
+ \endtable
+
+ \section2 Canonical CBOR encoding
+
+ Canonical CBOR encoding is defined by
+ \l{https://tools.ietf.org/html/rfc7049#section-3.9}{Section 3.9 of RFC
+ 7049}. Canonical encoding is not a requirement for Qt's CBOR decoding
+ functionality, but it may be required for some protocols. In particular,
+ protocols that require the ability to reproduce the same stream identically
+ may require this.
+
+ In order to be considered "canonical", a CBOR stream must meet the
+ following requirements:
+
+ \list
+ \li Integers must be as small as possible. QCborStreamWriter always
+ does this (no user action is required and it is not possible
+ to write overlong integers).
+ \li Array, map and string lengths must be as short as possible. As
+ above, QCborStreamWriter automatically does this.
+ \li Arrays, maps and strings must use explicit length. QCborStreamWriter
+ always does this for strings; for arrays and maps, be sure to call
+ startArray() and startMap() overloads with explicit length.
+ \li Keys in every map must be sorted in ascending order. QCborStreamWriter
+ offers no help in this item: the developer must ensure that before
+ calling append() for the map pairs.
+ \li Floating point values should be as small as possible. QCborStreamWriter
+ will not convert floating point values; it is up to the developer
+ to perform this check prior to calling append() (see those functions'
+ examples).
+ \endlist
+
+ \section2 Strict CBOR mode
+
+ Strict mode is defined by
+ \l{https://tools.ietf.org/html/rfc7049#section-3.10}{Section 3.10 of RFC
+ 7049}. As for Canonical encoding above, QCborStreamWriter makes it possible
+ to create strict CBOR streams, but does not require them or validate that
+ the output is so.
+
+ \list
+ \li Keys in a map must be unique. QCborStreamWriter performs no validation
+ of map keys.
+ \li Tags may be required to be paired only with the correct types,
+ according to their specification. QCborStreamWriter performs no
+ validation of tag usage.
+ \li Text Strings must be properly-encoded UTF-8. QCborStreamWriter always
+ writes proper UTF-8 for strings added with append(), but performs no
+ validation for strings added with appendTextString().
+ \endlist
+
+ \section2 Invalid CBOR stream
+
+ It is also possible to misuse QCborStreamWriter and produce invalid CBOR
+ streams that will fail to be decoded by a receiver. The following actions
+ will produce invalid streams:
+
+ \list
+ \li Append a tag and not append the corresponding tagged value
+ (QCborStreamWriter produces no diagnostic).
+ \li Append too many or too few items to an array or map with explicit
+ length (endMap() and endArray() will return false and
+ QCborStreamWriter will log with qWarning()).
+ \endlist
+
+ \sa QCborStreamReader, QCborValue, QXmlStreamWriter
+ */
+
+class QCborStreamWriterPrivate
+{
+public:
+ static Q_CONSTEXPR quint64 IndefiniteLength = (std::numeric_limits<quint64>::max)();
+
+ QIODevice *device;
+ CborEncoder encoder;
+ QStack<CborEncoder> containerStack;
+ bool deleteDevice = false;
+
+ QCborStreamWriterPrivate(QIODevice *device)
+ : device(device)
+ {
+ cbor_encoder_init_writer(&encoder, qt_cbor_encoder_write_callback, this);
+ }
+
+ ~QCborStreamWriterPrivate()
+ {
+ if (deleteDevice)
+ delete device;
+ }
+
+ template <typename... Args> void executeAppend(CborError (*f)(CborEncoder *, Args...), Args... args)
+ {
+ f(&encoder, std::forward<Args>(args)...);
+ }
+
+ void createContainer(CborError (*f)(CborEncoder *, CborEncoder *, size_t), quint64 len = IndefiniteLength)
+ {
+ Q_STATIC_ASSERT(size_t(IndefiniteLength) == CborIndefiniteLength);
+ if (sizeof(len) != sizeof(size_t) && len != IndefiniteLength) {
+ if (Q_UNLIKELY(len >= CborIndefiniteLength)) {
+ // TinyCBOR can't do this in 32-bit mode
+ qWarning("QCborStreamWriter: container of size %llu is too big for a 32-bit build; "
+ "will use indeterminate length instead", len);
+ len = CborIndefiniteLength;
+ }
+ }
+
+ containerStack.push(encoder);
+ f(&containerStack.top(), &encoder, len);
+ }
+
+ bool closeContainer()
+ {
+ if (containerStack.isEmpty()) {
+ qWarning("QCborStreamWriter: closing map or array that wasn't open");
+ return false;
+ }
+
+ CborEncoder container = containerStack.pop();
+ CborError err = cbor_encoder_close_container(&container, &encoder);
+ encoder = container;
+
+ if (Q_UNLIKELY(err)) {
+ if (err == CborErrorTooFewItems)
+ qWarning("QCborStreamWriter: not enough items added to array or map");
+ else if (err == CborErrorTooManyItems)
+ qWarning("QCborStreamWriter: too many items added to array or map");
+ return false;
+ }
+
+ return true;
+ }
+};
+
+static CborError qt_cbor_encoder_write_callback(void *self, const void *data, size_t len, CborEncoderAppendType)
+{
+ auto that = static_cast<QCborStreamWriterPrivate *>(self);
+ if (!that->device)
+ return CborNoError;
+ qint64 written = that->device->write(static_cast<const char *>(data), len);
+ return (written == qsizetype(len) ? CborNoError : CborErrorIO);
+}
+
+/*!
+ Creates a QCborStreamWriter object that will write the stream to \a device.
+ The device must be opened before the first append() call is made. This
+ constructor can be used with any class that derives from QIODevice, such as
+ QFile, QProcess or QTcpSocket.
+
+ QCborStreamWriter has no buffering, so every append() call will result in
+ one or more calls to the device's \l {QIODevice::}{write()} method.
+
+ The following example writes an empty map to a file:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 2
+
+ QCborStreamWriter does not take ownership of \a device.
+
+ \sa device(), setDevice()
+ */
+QCborStreamWriter::QCborStreamWriter(QIODevice *device)
+ : d(new QCborStreamWriterPrivate(device))
+{
+}
+
+/*!
+ Creates a QCborStreamWriter object that will append the stream to \a data.
+ All streaming is done immediately to the byte array, without the need for
+ flushing any buffers.
+
+ The following example writes a number to a byte array then returns
+ it.
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 3
+
+ QCborStreamWriter does not take ownership of \a data.
+ */
+QCborStreamWriter::QCborStreamWriter(QByteArray *data)
+ : d(new QCborStreamWriterPrivate(new QBuffer(data)))
+{
+ d->deleteDevice = true;
+ d->device->open(QIODevice::WriteOnly | QIODevice::Unbuffered);
+}
+
+/*!
+ Destroys this QCborStreamWriter object and frees any resources associated.
+
+ QCborStreamWriter does not perform error checking to see if all required
+ items were written to the stream prior to the object being destroyed. It is
+ the programmer's responsibility to ensure that it was done.
+ */
+QCborStreamWriter::~QCborStreamWriter()
+{
+}
+
+/*!
+ Replaces the device or byte array that this QCborStreamWriter object is
+ writing to with \a device.
+
+ \sa device()
+ */
+void QCborStreamWriter::setDevice(QIODevice *device)
+{
+ if (d->deleteDevice)
+ delete d->device;
+ d->device = device;
+ d->deleteDevice = false;
+}
+
+/*!
+ Returns the QIODevice that this QCborStreamWriter object is writing to. The
+ device must have previously been set with either the constructor or with
+ setDevice().
+
+ If this object was created by writing to a QByteArray, this function will
+ return an internal instance of QBuffer, which is owned by QCborStreamWriter.
+
+ \sa setDevice()
+ */
+QIODevice *QCborStreamWriter::device() const
+{
+ return d->device;
+}
+
+/*!
+ \overload
+
+ Appends the 64-bit unsigned value \a u to the CBOR stream, creating a CBOR
+ Unsigned Integer value. In the following example, we write the values 0,
+ 2\sup{32} and \c UINT64_MAX:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 4
+
+ \sa QCborStreamReader::isUnsignedInteger(), QCborStreamReader::toUnsignedInteger()
+ */
+void QCborStreamWriter::append(quint64 u)
+{
+ d->executeAppend(cbor_encode_uint, uint64_t(u));
+}
+
+/*!
+ \overload
+
+ Appends the 64-bit signed value \a i to the CBOR stream. This will create
+ either a CBOR Unsigned Integer or CBOR NegativeInteger value based on the
+ sign of the parameter. In the following example, we write the values 0, -1,
+ 2\sup{32} and \c INT64_MAX:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 5
+
+ \sa QCborStreamReader::isInteger(), QCborStreamReader::toInteger()
+ */
+void QCborStreamWriter::append(qint64 i)
+{
+ d->executeAppend(cbor_encode_int, int64_t(i));
+}
+
+/*!
+ \overload
+
+ Appends the 64-bit negative value \a n to the CBOR stream.
+ QCborNegativeInteger is a 64-bit enum that holds the absolute value of the
+ negative number we want to write. If n is zero, the value written will be
+ equivalent to 2\sup{64} (that is, -18,446,744,073,709,551,616).
+
+ In the following example, we write the values -1, -2\sup{32} and INT64_MIN:
+ \snippet code/src_corelib_serialization_qcborstream.cpp 6
+
+ Note how this function can be used to encode numbers that cannot fit a
+ standard computer's 64-bit signed integer like \l qint64. That is, if \a n
+ is larger than \c{std::numeric_limits<qint64>::max()} or is 0, this will
+ represent a negative number smaller than
+ \c{std::numeric_limits<qint64>::min()}.
+
+ \sa QCborStreamReader::isNegativeInteger(), QCborStreamReader::toNegativeInteger()
+ */
+void QCborStreamWriter::append(QCborNegativeInteger n)
+{
+ d->executeAppend(cbor_encode_negative_int, uint64_t(n));
+}
+
+/*!
+ \fn void QCborStreamWriter::append(const QByteArray &ba)
+ \overload
+
+ Appends the byte array \a ba to the stream, creating a CBOR Byte String
+ value. QCborStreamWriter will attempt to write the entire string in one
+ chunk.
+
+ The following example will load and append the contents of a file to the
+ stream:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 7
+
+ As the example shows, unlike JSON, CBOR requires no escaping for binary
+ content.
+
+ \sa appendByteString(), QCborStreamReader::isByteArray(),
+ QCborStreamReader::readByteArray()
+ */
+
+/*!
+ \overload
+
+ Appends the text string \a str to the stream, creating a CBOR Text String
+ value. QCborStreamWriter will attempt to write the entire string in one
+ chunk.
+
+ The following example appends a simple string to the stream:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 8
+
+ \b{Performance note}: CBOR requires that all Text Strings be encoded in
+ UTF-8, so this function will iterate over the characters in the string to
+ determine whether the contents are US-ASCII or not. If the string is found
+ to contain characters outside of US-ASCII, it will allocate memory and
+ convert to UTF-8. If this check is unnecessary, use appendTextString()
+ instead.
+
+ \sa QCborStreamReader::isString(), QCborStreamReader::readString()
+ */
+void QCborStreamWriter::append(QLatin1String str)
+{
+ // We've got Latin-1 but CBOR wants UTF-8, so check if the string is the
+ // common subset (US-ASCII).
+ if (QtPrivate::isAscii(str)) {
+ // it is plain US-ASCII
+ appendTextString(str.latin1(), str.size());
+ } else {
+ // non-ASCII, so we need a pass-through UTF-16
+ append(QString(str));
+ }
+}
+
+/*!
+ \overload
+
+ Appends the text string \a str to the stream, creating a CBOR Text String
+ value. QCborStreamWriter will attempt to write the entire string in one
+ chunk.
+
+ The following example writes an arbitrary QString to the stream:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 9
+
+ \sa QCborStreamReader::isString(), QCborStreamReader::readString()
+ */
+void QCborStreamWriter::append(QStringView str)
+{
+ QByteArray utf8 = str.toUtf8();
+ appendTextString(utf8.constData(), utf8.size());
+}
+
+/*!
+ \overload
+
+ Appends the CBOR tag \a tag to the stream, creating a CBOR Tag value. All
+ tags must be followed by another type which they provide meaning for.
+
+ In the following example, we append a CBOR Tag 36 (Regular Expression) and a
+ QRegularExpression's pattern to the stream:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 10
+
+ \sa QCborStreamReader::isTag(), QCborStreamReader::toTag()
+ */
+void QCborStreamWriter::append(QCborTag tag)
+{
+ d->executeAppend(cbor_encode_tag, CborTag(tag));
+}
+
+/*!
+ \fn void QCborStreamWriter::append(QCborKnownTags tag)
+ \overload
+
+ Appends the CBOR tag \a tag to the stream, creating a CBOR Tag value. All
+ tags must be followed by another type which they provide meaning for.
+
+ In the following example, we append a CBOR Tag 1 (Unix \c time_t) and an
+ integer representing the current time to the stream, obtained using the \c
+ time() function:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 11
+
+ \sa QCborStreamReader::isTag(), QCborStreamReader::toTag()
+ */
+
+/*!
+ \overload
+
+ Appends the CBOR simple type \a st to the stream, creating a CBOR Simple
+ Type value. In the following example, we write the simple type for Null as
+ well as for type 32, which Qt has no support for.
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 12
+
+ \note Using Simple Types for which there is no specification can lead to
+ validation errors by the remote receiver. In addition, simple type values 24
+ through 31 (inclusive) are reserved and must not be used.
+
+ \sa QCborStreamReader::isSimpleType(), QCborStreamReader::toSimpleType()
+ */
+void QCborStreamWriter::append(QCborSimpleType st)
+{
+ d->executeAppend(cbor_encode_simple_value, uint8_t(st));
+}
+
+/*!
+ \overload
+
+ Appends the floating point number \a f to the stream, creating a CBOR 16-bit
+ Half-Precision Floating Point value. The following code can be used to convert
+ a C++ \tt float to \c qfloat16 if there's no loss of precision and append it, or
+ instead append the \tt float.
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 13
+
+ \sa QCborStreamReader::isFloat16(), QCborStreamReader::toFloat16()
+ */
+void QCborStreamWriter::append(qfloat16 f)
+{
+ d->executeAppend(cbor_encode_half_float, static_cast<const void *>(&f));
+}
+
+/*!
+ \overload
+
+ Appends the floating point number \a f to the stream, creating a CBOR 32-bit
+ Single-Precision Floating Point value. The following code can be used to convert
+ a C++ \tt double to \tt float if there's no loss of precision and append it, or
+ instead append the \tt double.
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 14
+
+ \sa QCborStreamReader::isFloat(), QCborStreamReader::toFloat()
+ */
+void QCborStreamWriter::append(float f)
+{
+ d->executeAppend(cbor_encode_float, f);
+}
+
+/*!
+ \overload
+
+ Appends the floating point number \a d to the stream, creating a CBOR 64-bit
+ Double-Precision Floating Point value. QCborStreamWriter always appends the
+ number as-is, performing no check for whether the number is the canonical
+ form for NaN, an infinite, whether it is denormal or if it could be written
+ with a shorter format.
+
+ The following code performs all those checks, except for the denormal one,
+ which is expected to be taken into account by the system FPU or floating
+ point emulation directly.
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 15
+
+ Determining if a double can be converted to an integral with no loss of
+ precision is left as an exercise to the reader.
+
+ \sa QCborStreamReader::isDouble(), QCborStreamReader::toDouble()
+ */
+void QCborStreamWriter::append(double d)
+{
+ this->d->executeAppend(cbor_encode_double, d);
+}
+
+/*!
+ Appends \a len bytes of data starting from \a data to the stream, creating a
+ CBOR Byte String value. QCborStreamWriter will attempt to write the entire
+ string in one chunk.
+
+ Unlike the QByteArray overload of append(), this function is not limited by
+ QByteArray's size limits. However, note that neither
+ QCborStreamReader::readByteArray() nor QCborValue support reading CBOR
+ streams with byte arrays larger than 2 GB.
+
+ \sa append(), appendTextString(),
+ QCborStreamReader::isByteArray(), QCborStreamReader::readByteArray()
+ */
+void QCborStreamWriter::appendByteString(const char *data, qsizetype len)
+{
+ d->executeAppend(cbor_encode_byte_string, reinterpret_cast<const uint8_t *>(data), size_t(len));
+}
+
+/*!
+ Appends \a len bytes of text starting from \a utf8 to the stream, creating a
+ CBOR Text String value. QCborStreamWriter will attempt to write the entire
+ string in one chunk.
+
+ The string pointed to by \a utf8 is expected to be properly encoded UTF-8.
+ QCborStreamWriter performs no validation that this is the case.
+
+ Unlike the QLatin1String overload of append(), this function is not limited
+ to 2 GB. However, note that neither QCborStreamReader::readString() nor
+ QCborValue support reading CBOR streams with text strings larger than 2 GB.
+
+ \sa append(QLatin1String), append(QStringView),
+ QCborStreamReader::isString(), QCborStreamReader::readString()
+ */
+void QCborStreamWriter::appendTextString(const char *utf8, qsizetype len)
+{
+ d->executeAppend(cbor_encode_text_string, utf8, size_t(len));
+}
+
+/*!
+ \fn void QCborStreamWriter::append(const char *str, qsizetype size)
+ \overload
+
+ Appends \a size bytes of text starting from \a str to the stream, creating a
+ CBOR Text String value. QCborStreamWriter will attempt to write the entire
+ string in one chunk. If \a size is -1, this function will write \c strlen(\a
+ str) bytes.
+
+ The string pointed to by \a str is expected to be properly encoded UTF-8.
+ QCborStreamWriter performs no validation that this is the case.
+
+ Unlike the QLatin1String overload of append(), this function is not limited
+ to 2 GB. However, note that neither QCborStreamReader nor QCborValue support
+ reading CBOR streams with text strings larger than 2 GB.
+
+ \sa append(QLatin1String), append(QStringView),
+ QCborStreamReader::isString(), QCborStreamReader::readString()
+ */
+
+/*!
+ \fn void QCborStreamWriter::append(bool b)
+ \overload
+
+ Appends the boolean value \a b to the stream, creating either a CBOR False
+ value or a CBOR True value. This function is equivalent to (and implemented
+ as):
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 16
+
+ \sa appendNull(), appendUndefined(),
+ QCborStreamReader::isBool(), QCborStreamReader::toBool()
+ */
+
+/*!
+ \fn void QCborStreamWriter::append(std::nullptr_t)
+ \overload
+
+ Appends a CBOR Null value to the stream. This function is equivalent to (and
+ implemented as): The parameter is ignored.
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 17
+
+ \sa appendNull(), append(QCborSimpleType), QCborStreamReader::isNull()
+ */
+
+/*!
+ \fn void QCborStreamWriter::appendNull()
+
+ Appends a CBOR Null value to the stream. This function is equivalent to (and
+ implemented as):
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 18
+
+ \sa append(std::nullptr_t), append(QCborSimpleType), QCborStreamReader::isNull()
+ */
+
+/*!
+ \fn void QCborStreamWriter::appendUndefined()
+
+ Appends a CBOR Undefined value to the stream. This function is equivalent to (and
+ implemented as):
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 19
+
+ \sa append(QCborSimpleType), QCborStreamReader::isUndefined()
+ */
+
+/*!
+ Starts a CBOR Array with indeterminate length in the CBOR stream. Each
+ startArray() call must be paired with one endArray() call and the current
+ CBOR element extends until the end of the array.
+
+ The array created by this function has no explicit length. Instead, its
+ length is implied by the elements contained in it. Note, however, that use
+ of indeterminate-length arrays is not compliant with canonical CBOR encoding.
+
+ The following example appends elements from the linked list of strings
+ passed as input:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 20
+
+ \sa startArray(quint64), endArray(), startMap(), QCborStreamReader::isArray(),
+ QCborStreamReader::isLengthKnown()
+ */
+void QCborStreamWriter::startArray()
+{
+ d->createContainer(cbor_encoder_create_array);
+}
+
+/*!
+ \overload
+
+ Starts a CBOR Array with explicit length of \a count items in the CBOR
+ stream. Each startArray call must be paired with one endArray() call and the
+ current CBOR element extends until the end of the array.
+
+ The array created by this function has an explicit length and therefore
+ exactly \a count items must be added to the CBOR stream. Adding fewer or
+ more items will result in failure during endArray() and the CBOR stream will
+ be corrupt. However, explicit-length arrays are required by canonical CBOR
+ encoding.
+
+ The following example appends all strings found in the \l QStringList passed as input:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 21
+
+ \b{Size limitations}: The parameter to this function is quint64, which would
+ seem to allow up to 2\sup{64}-1 elements in the array. However, both
+ QCborStreamWriter and QCborStreamReader are currently limited to 2\sup{32}-2
+ items on 32-bit systems and 2\sup{64}-2 items on 64-bit ones. Also note that
+ QCborArray is currently limited to 2\sup{27} elements in any platform.
+
+ \sa startArray(), endArray(), startMap(), QCborStreamReader::isArray(),
+ QCborStreamReader::isLengthKnown()
+ */
+void QCborStreamWriter::startArray(quint64 count)
+{
+ d->createContainer(cbor_encoder_create_array, count);
+}
+
+/*!
+ Terminates the array started by either overload of startArray() and returns
+ true if the correct number of elements was added to the array. This function
+ must be called for every startArray() used.
+
+ A return of false indicates error in the application and an unrecoverable
+ error in this stream. QCborStreamWriter also writes a warning using
+ qWarning() if that happens.
+
+ Calling this function when the current container is not an array is also an
+ error, though QCborStreamWriter cannot currently detect this condition.
+
+ \sa startArray(), startArray(quint64), endMap()
+ */
+bool QCborStreamWriter::endArray()
+{
+ return d->closeContainer();
+}
+
+/*!
+ Starts a CBOR Map with indeterminate length in the CBOR stream. Each
+ startMap() call must be paired with one endMap() call and the current CBOR
+ element extends until the end of the map.
+
+ The map created by this function has no explicit length. Instead, its length
+ is implied by the elements contained in it. Note, however, that use of
+ indeterminate-length maps is not compliant with canonical CBOR encoding
+ (canonical encoding also requires keys to be unique and in sorted order).
+
+ The following example appends elements from the linked list of int and
+ string pairs passed as input:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 22
+
+ \sa startMap(quint64), endMap(), startArray(), QCborStreamReader::isMap(),
+ QCborStreamReader::isLengthKnown()
+ */
+void QCborStreamWriter::startMap()
+{
+ d->createContainer(cbor_encoder_create_map);
+}
+
+/*!
+ \overload
+
+ Starts a CBOR Map with explicit length of \a count items in the CBOR
+ stream. Each startMap call must be paired with one endMap() call and the
+ current CBOR element extends until the end of the map.
+
+ The map created by this function has an explicit length and therefore
+ exactly \a count pairs of items must be added to the CBOR stream. Adding
+ fewer or more items will result in failure during endMap() and the CBOR
+ stream will be corrupt. However, explicit-length map are required by
+ canonical CBOR encoding.
+
+ The following example appends all strings found in the \l QMap passed as input:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 23
+
+ \b{Size limitations}: The parameter to this function is quint64, which would
+ seem to allow up to 2\sup{64}-1 pairs in the map. However, both
+ QCborStreamWriter and QCborStreamReader are currently limited to 2\sup{31}-1
+ items on 32-bit systems and 2\sup{63}-1 items on 64-bit ones. Also note that
+ QCborMap is currently limited to 2\sup{26} elements in any platform.
+
+ \sa startMap(), endMap(), startArray(), QCborStreamReader::isMap(),
+ QCborStreamReader::isLengthKnown()
+ */
+void QCborStreamWriter::startMap(quint64 count)
+{
+ d->createContainer(cbor_encoder_create_map, count);
+}
+
+/*!
+ Terminates the map started by either overload of startMap() and returns
+ true if the correct number of elements was added to the array. This function
+ must be called for every startMap() used.
+
+ A return of false indicates error in the application and an unrecoverable
+ error in this stream. QCborStreamWriter also writes a warning using
+ qWarning() if that happens.
+
+ Calling this function when the current container is not a map is also an
+ error, though QCborStreamWriter cannot currently detect this condition.
+
+ \sa startMap(), startMap(quint64), endArray()
+ */
+bool QCborStreamWriter::endMap()
+{
+ return d->closeContainer();
+}
+
+/*!
+ \class QCborStreamReader
+ \inmodule QtCore
+ \ingroup cbor
+ \reentrant
+ \since 5.12
+
+ \brief The QCborStreamReader class is a simple CBOR stream decoder, operating
+ on either a QByteArray or QIODevice.
+
+ This class can be used to decode a stream of CBOR content directly from
+ either a QByteArray or a QIODevice. CBOR is the Concise Binary Object
+ Representation, a very compact form of binary data encoding that is
+ compatible with JSON. It was created by the IETF Constrained RESTful
+ Environments (CoRE) WG, which has used it in many new RFCs. It is meant to
+ be used alongside the \l{https://tools.ietf.org/html/rfc7252}{CoAP
+ protocol}.
+
+ QCborStreamReader provides a StAX-like API, similar to that of
+ \l{QXmlStreamReader}. Using it requires a bit of knowledge of CBOR encoding.
+ For a simpler API, see \l{QCborValue} and especially the decoding function
+ QCborValue::fromCbor().
+
+ Typically, one creates a QCborStreamReader by passing the source QByteArray
+ or QIODevice as a parameter to the constructor, then pop elements off the
+ stream if there were no errors in decoding. There are three kinds of CBOR
+ types:
+
+ \table
+ \header \li Kind \li Types \li Behavior
+ \row \li Fixed-width \li Integers, Tags, Simple types, Floating point
+ \li Value is pre-parsed by QCborStreamReader, so accessor functions
+ are \c const. Must call next() to advance.
+ \row \li Strings \li Byte arrays, Text strings
+ \li Length (if known) is pre-parsed, but the string itself is not.
+ The accessor functions are not const and may allocate memory.
+ Once called, the accessor functions automatically advance to
+ the next element.
+ \row \li Containers \li Arrays, Maps
+ \li Length (if known) is pre-parsed. To access the elements, you
+ must call enterContainer(), read all elements, then call
+ leaveContainer(). That function advances to the next element.
+ \endtable
+
+ So a processor function typically looks like this:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 24
+
+ \section1 CBOR support
+
+ The following table lists the CBOR features that QCborStreamReader supports.
+
+ \table
+ \header \li Feature \li Support
+ \row \li Unsigned numbers \li Yes (full range)
+ \row \li Negative numbers \li Yes (full range)
+ \row \li Byte strings \li Yes
+ \row \li Text strings \li Yes
+ \row \li Chunked strings \li Yes
+ \row \li Tags \li Yes (arbitrary)
+ \row \li Booleans \li Yes
+ \row \li Null \li Yes
+ \row \li Undefined \li Yes
+ \row \li Arbitrary simple values \li Yes
+ \row \li Half-precision float (16-bit) \li Yes
+ \row \li Single-precision float (32-bit) \li Yes
+ \row \li Double-precision float (64-bit) \li Yes
+ \row \li Infinities and NaN floating point \li Yes
+ \row \li Determinate-length arrays and maps \li Yes
+ \row \li Indeterminate-length arrays and maps \li Yes
+ \row \li Map key types other than strings and integers \li Yes (arbitrary)
+ \endtable
+
+ \section1 Dealing with invalid or incomplete CBOR streams
+
+ QCborStreamReader is capable of detecting corrupt input on its own. The
+ library it uses has been extensively tested against invalid input of any
+ kind and is quite able to report errors. If any is detected,
+ QCborStreamReader will set lastError() to a value besides
+ QCborError::NoError, indicating which situation was detected.
+
+ Most errors detected by QCborStreamReader during normal item parsing are not
+ recoverable. The code using QCborStreamReader may opt to handle the data
+ that was properly decoded or it can opt to discard the entire data.
+
+ The only recoverable error is QCborError::EndOfFile, which indicates that
+ more data is required in order to complete the parsing. This situation is
+ useful when data is being read from an asynchronous source, such as a pipe
+ (QProcess) or a socket (QTcpSocket, QUdpSocket, QNetworkReply, etc.). When
+ more data arrives, the surrounding code needs to call either addData(), if
+ parsing from a QByteArray, or reparse(), if it is instead reading directly
+ a the QIDOevice that now has more data available (see setDevice()).
+
+ \sa QCborStreamWriter, QCborValue, QXmlStreamReader
+ */
+
+/*!
+ \enum QCborStreamReader::Type
+
+ This enumeration contains all possible CBOR types as decoded by
+ QCborStreamReader. CBOR has 7 major types, plus a number of simple types
+ carrying no value, and floating point values.
+
+ \value UnsignedInteger (Major type 0) Ranges from 0 to 2\sup{64} - 1
+ (18,446,744,073,709,551,616)
+ \value NegativeInteger (Major type 1) Ranges from -1 to -2\sup{64}
+ (-18,446,744,073,709,551,616)
+ \value ByteArray (Major type 2) Arbitrary binary data.
+ \value ByteString An alias to ByteArray.
+ \value String (Major type 3) Unicode text, possibly containing NULs.
+ \value TextString An alias to String
+ \value Array (Major type 4) Array of heterogeneous items.
+ \value Map (Major type 5) Map/dictionary of heterogeneous items.
+ \value Tag (Major type 6) Numbers giving further semantic value
+ to generic CBOR items. See \l QCborTag for more information.
+ \value SimpleType (Major type 7) Types carrying no further value. Includes
+ booleans (true and false), null, undefined.
+ \value Float16 IEEE 754 half-precision floating point (\c qfloat16).
+ \value HalfFloat An alias to Float16.
+ \value Float IEEE 754 single-precision floating point (\tt float).
+ \value Double IEEE 754 double-precision floating point (\tt double).
+ \value Invalid Not a valid type, either due to parsing error or due to
+ reaching the end of an array or map.
+ */
+
+/*!
+ \enum QCborStreamReader::StringResultCode
+
+ This enum is returned by readString() and readByteArray() and is used to
+ indicate what the status of the parsing is.
+
+ \value EndOfString The parsing for the string is complete, with no error.
+ \value Ok The function returned data; there was no error.
+ \value Error Parsing failed with an error.
+ */
+
+/*!
+ \class QCborStreamReader::StringResult
+
+ This class is returned by readString() and readByteArray(), with either the
+ contents of the string that was read or an indication that the parsing is
+ done or found an error.
+
+ The contents of \l data are valid only if \l status is
+ \l{StringResultCode}{Ok}. Otherwise, it should be null.
+ */
+
+/*!
+ \variable Container QCborStreamReader::StringResult::data
+ Contains the actual data from the string if \l status is \c Ok.
+ */
+
+/*!
+ \variable QCborStreamReader::StringResultCode QCborStreamReader::StringResult::status
+ Contains the status of the attempt of reading the string from the stream.
+ */
+
+/*!
+ \fn QCborStreamReader::Type QCborStreamReader::type() const
+
+ Returns the type of the current element. It is one of the valid types or
+ Invalid.
+
+ \sa isValid(), isUnsignedInteger(), isNegativeInteger(), isInteger(),
+ isByteArray(), isString(), isArray(), isMap(), isTag(), isSimpleType(),
+ isBool(), isFalse(), isTrue(), isNull(), isUndefined(), isFloat16(),
+ isFloat(), isDouble()
+ */
+
+/*!
+ \fn bool QCborStreamReader::isValid() const
+
+ Returns true if the current element is valid, false otherwise. The current
+ element may be invalid if there was a decoding error or we've just parsed
+ the last element in an array or map.
+
+ \note This function is not the opposite of isNull(). Null is a normal CBOR
+ type that must be handled by the application.
+
+ \sa type(), isInvalid()
+ */
+
+/*!
+ \fn bool QCborStreamReader::isInvalid() const
+
+ Returns true if the current element is invalid, false otherwise. The current
+ element may be invalid if there was a decoding error or we've just parsed
+ the last element in an array or map.
+
+ \note This function is not to be confused with isNull(). Null is a normal
+ CBOR type that must be handled by the application.
+
+ \sa type(), isValid()
+ */
+
+/*!
+ \fn bool QCborStreamReader::isUnsignedInteger() const
+
+ Returns true if the type of the current element is an unsigned integer (that
+ is if type() returns QCborStreamReader::UnsignedInteger). If this function
+ returns true, you may call toUnsignedInteger() or toInteger() to read that value.
+
+ \sa type(), toUnsignedInteger(), toInteger(), isInteger(), isNegativeInteger()
+ */
+
+/*!
+ \fn bool QCborStreamReader::isNegativeInteger() const
+
+ Returns true if the type of the current element is a negative integer (that
+ is if type() returns QCborStreamReader::NegativeInteger). If this function
+ returns true, you may call toNegativeInteger() or toInteger() to read that value.
+
+ \sa type(), toNegativeInteger(), toInteger(), isInteger(), isUnsignedInteger()
+ */
+
+/*!
+ \fn bool QCborStreamReader::isInteger() const
+
+ Returns true if the type of the current element is either an unsigned
+ integer or a negative one (that is, if type() returns
+ QCborStreamReader::UnsignedInteger or QCborStreamReader::NegativeInteger).
+ If this function returns true, you may call toInteger() to read that
+ value.
+
+ \sa type(), toInteger(), toUnsignedInteger(), toNegativeInteger(),
+ isUnsignedInteger(), isNegativeInteger()
+ */
+
+/*!
+ \fn bool QCborStreamReader::isByteArray() const
+
+ Returns true if the type of the current element is a byte array (that is,
+ if type() returns QCborStreamReader::ByteArray). If this function returns
+ true, you may call readByteArray() to read that data.
+
+ \sa type(), readByteArray(), isString()
+ */
+
+/*!
+ \fn bool QCborStreamReader::isString() const
+
+ Returns true if the type of the current element is a text string (that is,
+ if type() returns QCborStreamReader::String). If this function returns
+ true, you may call readString() to read that data.
+
+ \sa type(), readString(), isByteArray()
+ */
+
+/*!
+ \fn bool QCborStreamReader::isArray() const
+
+ Returns true if the type of the current element is an array (that is,
+ if type() returns QCborStreamReader::Array). If this function returns
+ true, you may call enterContainer() to begin parsing that container.
+
+ When the current element is an array, you may also call isLengthKnown() to
+ find out if the array's size is explicit in the CBOR stream. If it is, that
+ size can be obtained by calling length().
+
+ The following example pre-allocates a QVariantList given the array's size
+ for more efficient decoding:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 25
+
+ \note The code above does not validate that the length is a sensible value.
+ If the input stream reports that the length is 1 billion elements, the above
+ function will try to allocate some 16 GB or more of RAM, which can lead to a
+ crash.
+
+ \sa type(), isMap(), isLengthKnown(), length(), enterContainer(), leaveContainer()
+ */
+
+/*!
+ \fn bool QCborStreamReader::isMap() const
+
+ Returns true if the type of the current element is a map (that is, if type()
+ returns QCborStreamReader::Map). If this function returns true, you may call
+ enterContainer() to begin parsing that container.
+
+ When the current element is a map, you may also call isLengthKnown() to
+ find out if the map's size is explicit in the CBOR stream. If it is, that
+ size can be obtained by calling length().
+
+ The following example pre-allocates a QVariantMap given the map's size
+ for more efficient decoding:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 26
+
+ The example above uses a function called \c readElementAsString to read the
+ map's keys and obtain a string. That is because CBOR maps may contain any
+ type as keys, not just strings. User code needs to either perform this
+ conversion, reject non-string keys, or instead use a different container
+ besides \l QVariantMap and \l QVariantHash. For example, if the map is
+ expected to contain integer keys, which is recommended as it reduces stream
+ size and parsing, the correct container would be \c{\l{QMap}<int, QVariant>}
+ or \c{\l{QHash}<int, QVariant>}.
+
+ \note The code above does not validate that the length is a sensible value.
+ If the input stream reports that the length is 1 billion elements, the above
+ function will try to allocate some 24 GB or more of RAM, which can lead to a
+ crash.
+
+ \sa type(), isArray(), isLengthKnown(), length(), enterContainer(), leaveContainer()
+ */
+
+/*!
+ \fn bool QCborStreamReader::isTag() const
+
+ Returns true if the type of the current element is a CBOR tag (that is,
+ if type() returns QCborStreamReader::Tag). If this function returns
+ true, you may call toTag() to read that data.
+
+ \sa type(), toTag()
+ */
+
+/*!
+ \fn bool QCborStreamReader::isFloat16() const
+
+ Returns true if the type of the current element is an IEEE 754
+ half-precision floating point (that is, if type() returns
+ QCborStreamReader::Float16). If this function returns true, you may call
+ toFloat16() to read that data.
+
+ \sa type(), toFloat16(), isFloat(), isDouble()
+ */
+
+/*!
+ \fn bool QCborStreamReader::isFloat() const
+
+ Returns true if the type of the current element is an IEEE 754
+ single-precision floating point (that is, if type() returns
+ QCborStreamReader::Float). If this function returns true, you may call
+ toFloat() to read that data.
+
+ \sa type(), toFloat(), isFloat16(), isDouble()
+ */
+
+/*!
+ \fn bool QCborStreamReader::isDouble() const
+
+ Returns true if the type of the current element is an IEEE 754
+ double-precision floating point (that is, if type() returns
+ QCborStreamReader::Double). If this function returns true, you may call
+ toDouble() to read that data.
+
+ \sa type(), toDouble(), isFloat16(), isFloat()
+ */
+
+/*!
+ \fn bool QCborStreamReader::isSimpleType() const
+
+ Returns true if the type of the current element is any CBOR simple type,
+ including a boolean value (true and false) as well as null and undefined. To
+ find out which simple type this is, call toSimpleType(). Alternatively, to
+ test for one specific simple type, call the overload that takes a
+ QCborSimpleType parameter.
+
+ CBOR simple types are types that do not carry extra value. There are 255
+ possibilities, but there are currently only four values that have defined
+ meaning. Code is not expected to cope with unknown simple types and may
+ simply discard the stream as invalid if it finds an unknown one.
+
+ \sa QCborSimpleType, type(), isSimpleType(QCborSimpleType), toSimpleType()
+ */
+
+/*!
+ \fn bool QCborStreamReader::isSimpleType(QCborSimpleType st) const
+
+ Returns true if the type of the current element is the simple type \a st,
+ false otherwise. If this function returns true, then toSimpleType() will
+ return \a st.
+
+ CBOR simple types are types that do not carry extra value. There are 255
+ possibilities, but there are currently only four values that have defined
+ meaning. Code is not expected to cope with unknown simple types and may
+ simply discard the stream as invalid if it finds an unknown one.
+
+ \sa QCborSimpleType, type(), isSimpleType(), toSimpleType()
+ */
+
+/*!
+ \fn bool QCborStreamReader::isFalse() const
+
+ Returns true if the current element is the \c false value, false if it is
+ anything else.
+
+ \sa type(), isTrue(), isBool(), toBool(), isSimpleType(), toSimpleType()
+ */
+
+/*!
+ \fn bool QCborStreamReader::isTrue() const
+
+ Returns true if the current element is the \c true value, false if it is
+ anything else.
+
+ \sa type(), isFalse(), isBool(), toBool(), isSimpleType(), toSimpleType()
+ */
+
+/*!
+ \fn bool QCborStreamReader::isBool() const
+
+ Returns true if the current element is a boolean value (\c true or \c
+ false), false if it is anything else. If this function returns true, you may
+ call toBool() to retrieve the value of the boolean. You may also call
+ toSimpleType() and compare to either QCborSimpleValue::True or
+ QCborSimpleValue::False.
+
+ \sa type(), isFalse(), isTrue(), toBool(), isSimpleType(), toSimpleType()
+ */
+
+/*!
+ \fn bool QCborStreamReader::isNull() const
+
+ Returns true if the current element is the \c null value, false if it is
+ anything else. Null values may be used to indicate the absence of some
+ optional data.
+
+ \note This function is not the opposite of isValid(). A Null value is a
+ valid CBOR value.
+
+ \sa type(), isSimpleType(), toSimpleType()
+ */
+
+/*!
+ \fn bool QCborStreamReader::isUndefined() const
+
+ Returns true if the current element is the \c undefined value, false if it
+ is anything else. Undefined values may be encoded to indicate that some
+ conversion failed or was not possible when creating the stream.
+ QCborStreamReader never performs any replacement and this function will only
+ return true if the stream contains an explicit undefined value.
+
+ \sa type(), isSimpleType(), toSimpleType()
+ */
+
+/*!
+ \fn bool QCborStreamReader::isContainer() const
+
+ Returns true if the current element is a container (that is, an array or a
+ map), false if it is anything else. If the current element is a container,
+ the isLengthKnown() function may be used to find out if the container's size
+ is explicit in the stream and, if so, length() can be used to get that size.
+
+ More importantly, for a container, the enterContainer() function is
+ available to begin iterating through the elements contained therein.
+
+ \sa type(), isArray(), isMap(), isLengthKnown(), length(), enterContainer(),
+ leaveContainer(), containerDepth()
+ */
+
+class QCborStreamReaderPrivate
+{
+public:
+ enum {
+ // 9 bytes is the maximum size for any integer, floating point or
+ // length in CBOR.
+ MaxCborIndividualSize = 9,
+ IdealIoBufferSize = 256
+ };
+
+ QIODevice *device;
+ QByteArray buffer;
+ QStack<CborValue> containerStack;
+
+ CborParser parser;
+ CborValue currentElement;
+ QCborError lastError = {};
+
+ QByteArray::size_type bufferStart;
+ bool corrupt = false;
+
+ QCborStreamReaderPrivate(const QByteArray &data)
+ : device(nullptr), buffer(data)
+ {
+ initDecoder();
+ }
+
+ QCborStreamReaderPrivate(QIODevice *device)
+ {
+ setDevice(device);
+ }
+
+ ~QCborStreamReaderPrivate()
+ {
+ }
+
+ void setDevice(QIODevice *dev)
+ {
+ buffer.clear();
+ device = dev;
+ initDecoder();
+ }
+
+ void initDecoder()
+ {
+ containerStack.clear();
+ bufferStart = 0;
+ if (device) {
+ buffer.clear();
+ buffer.reserve(IdealIoBufferSize); // sets the CapacityReserved flag
+ }
+
+ preread();
+ if (CborError err = cbor_parser_init_reader(nullptr, &parser, &currentElement, this))
+ handleError(err);
+ }
+
+ char *bufferPtr()
+ {
+ Q_ASSERT(buffer.isDetached());
+ return const_cast<char *>(buffer.constData()) + bufferStart;
+ }
+
+ void preread()
+ {
+ if (device && buffer.size() - bufferStart < MaxCborIndividualSize) {
+ // load more, but only if there's more to be read
+ qint64 avail = device->bytesAvailable();
+ Q_ASSERT(avail >= buffer.size());
+ if (avail == buffer.size())
+ return;
+
+ if (bufferStart)
+ device->skip(bufferStart); // skip what we've already parsed
+
+ if (buffer.size() != IdealIoBufferSize)
+ buffer.resize(IdealIoBufferSize);
+
+ bufferStart = 0;
+ qint64 read = device->peek(bufferPtr(), IdealIoBufferSize);
+ if (read < 0)
+ buffer.clear();
+ else if (read != IdealIoBufferSize)
+ buffer.truncate(read);
+ }
+ }
+
+ void handleError(CborError err) noexcept
+ {
+ Q_ASSERT(err);
+
+ // is the error fatal?
+ if (err != CborErrorUnexpectedEOF)
+ corrupt = true;
+
+ // our error codes are the same (for now)
+ lastError = { QCborError::Code(err) };
+ }
+
+ void updateBufferAfterString(qsizetype offset, qsizetype size)
+ {
+ Q_ASSERT(device);
+
+ bufferStart += offset;
+ qsizetype newStart = bufferStart + size;
+ qsizetype remainingInBuffer = buffer.size() - newStart;
+
+ if (remainingInBuffer <= 0) {
+ // We've read from the QIODevice more than what was in the buffer.
+ buffer.truncate(0);
+ } else {
+ // There's still data buffered, but we need to move it around.
+ char *ptr = buffer.data();
+ memmove(ptr, ptr + newStart, remainingInBuffer);
+ buffer.truncate(remainingInBuffer);
+ }
+
+ bufferStart = 0;
+ }
+
+ bool ensureStringIteration();
+};
+
+void qt_cbor_stream_set_error(QCborStreamReaderPrivate *d, QCborError error)
+{
+ d->handleError(CborError(error.c));
+}
+
+static inline bool qt_cbor_decoder_can_read(void *token, size_t len)
+{
+ Q_ASSERT(len <= QCborStreamReaderPrivate::MaxCborIndividualSize);
+ auto self = static_cast<QCborStreamReaderPrivate *>(token);
+
+ qint64 avail = self->buffer.size() - self->bufferStart;
+ return len <= quint64(avail);
+}
+
+static void qt_cbor_decoder_advance(void *token, size_t len)
+{
+ Q_ASSERT(len <= QCborStreamReaderPrivate::MaxCborIndividualSize);
+ auto self = static_cast<QCborStreamReaderPrivate *>(token);
+ Q_ASSERT(len <= size_t(self->buffer.size() - self->bufferStart));
+
+ self->bufferStart += int(len);
+ self->preread();
+}
+
+static void *qt_cbor_decoder_read(void *token, void *userptr, size_t offset, size_t len)
+{
+ Q_ASSERT(len == 1 || len == 2 || len == 4 || len == 8);
+ Q_ASSERT(offset == 0 || offset == 1);
+ auto self = static_cast<const QCborStreamReaderPrivate *>(token);
+
+ // we must have pre-read the data
+ Q_ASSERT(len + offset <= size_t(self->buffer.size() - self->bufferStart));
+ return memcpy(userptr, self->buffer.constData() + self->bufferStart + offset, len);
+}
+
+static CborError qt_cbor_decoder_transfer_string(void *token, const void **userptr, size_t offset, size_t len)
+{
+ auto self = static_cast<QCborStreamReaderPrivate *>(token);
+ Q_ASSERT(offset <= size_t(self->buffer.size()));
+ Q_STATIC_ASSERT(sizeof(size_t) >= sizeof(QByteArray::size_type));
+ Q_STATIC_ASSERT(sizeof(size_t) == sizeof(qsizetype));
+
+ // check that we will have enough data from the QIODevice before we advance
+ // (otherwise, we'd lose the length information)
+ qsizetype total;
+ if (len > size_t(std::numeric_limits<QByteArray::size_type>::max())
+ || add_overflow<qsizetype>(offset, len, &total))
+ return CborErrorDataTooLarge;
+
+ // our string transfer is just saving the offset to the userptr
+ *userptr = reinterpret_cast<void *>(offset);
+
+ qint64 avail = (self->device ? self->device->bytesAvailable() : self->buffer.size()) -
+ self->bufferStart;
+ return total > avail ? CborErrorUnexpectedEOF : CborNoError;
+}
+
+bool QCborStreamReaderPrivate::ensureStringIteration()
+{
+ if (currentElement.flags & CborIteratorFlag_IteratingStringChunks)
+ return true;
+
+ CborError err = cbor_value_begin_string_iteration(&currentElement);
+ if (!err)
+ return true;
+ handleError(err);
+ return false;
+}
+
+/*!
+ \internal
+ */
+inline void QCborStreamReader::preparse()
+{
+ if (lastError() == QCborError::NoError) {
+ type_ = cbor_value_get_type(&d->currentElement);
+
+ if (type_ != CborInvalidType) {
+ d->lastError = {};
+ // Undo the type mapping that TinyCBOR does (we have an explicit type
+ // for negative integer and we don't have separate types for Boolean,
+ // Null and Undefined).
+ if (type_ == CborBooleanType || type_ == CborNullType || type_ == CborUndefinedType) {
+ type_ = SimpleType;
+ value64 = quint8(d->buffer.at(d->bufferStart)) - CborSimpleType;
+ } else {
+ // Using internal TinyCBOR API!
+ value64 = _cbor_value_extract_int64_helper(&d->currentElement);
+
+ if (cbor_value_is_negative_integer(&d->currentElement))
+ type_ = quint8(QCborStreamReader::NegativeInteger);
+ }
+ }
+ } else {
+ type_ = Invalid;
+ }
+}
+
+/*!
+ Creates a QCborStreamReader object with no source data. After construction,
+ QCborStreamReader will report an error parsing.
+
+ You can add more data by calling addData() or by setting a different source
+ device using setDevice().
+
+ \sa addData(), isValid()
+ */
+QCborStreamReader::QCborStreamReader()
+ : QCborStreamReader(QByteArray())
+{
+}
+
+/*!
+ \overload
+
+ Creates a QCborStreamReader object with \a len bytes of data starting at \a
+ data. The pointer must remain valid until QCborStreamReader is destroyed.
+ */
+QCborStreamReader::QCborStreamReader(const char *data, qsizetype len)
+ : QCborStreamReader(QByteArray::fromRawData(data, len))
+{
+}
+
+/*!
+ \overload
+
+ Creates a QCborStreamReader object with \a len bytes of data starting at \a
+ data. The pointer must remain valid until QCborStreamReader is destroyed.
+ */
+QCborStreamReader::QCborStreamReader(const quint8 *data, qsizetype len)
+ : QCborStreamReader(QByteArray::fromRawData(reinterpret_cast<const char *>(data), len))
+{
+}
+
+/*!
+ \overload
+
+ Creates a QCborStreamReader object that will parse the CBOR stream found in
+ \a data.
+ */
+QCborStreamReader::QCborStreamReader(const QByteArray &data)
+ : d(new QCborStreamReaderPrivate(data))
+{
+ preparse();
+}
+
+/*!
+ \overload
+
+ Creates a QCborStreamReader object that will parse the CBOR stream found by
+ reading from \a device. QCborStreamReader does not take ownership of \a
+ device, so it must remain valid until this oject is destroyed.
+ */
+QCborStreamReader::QCborStreamReader(QIODevice *device)
+ : d(new QCborStreamReaderPrivate(device))
+{
+ preparse();
+}
+
+/*!
+ Destroys this QCborStreamReader object and frees any associated resources.
+ */
+QCborStreamReader::~QCborStreamReader()
+{
+}
+
+/*!
+ Sets the source of data to \a device, resetting the decoder to its initial
+ state.
+ */
+void QCborStreamReader::setDevice(QIODevice *device)
+{
+ d->setDevice(device);
+ preparse();
+}
+
+/*!
+ Returns the QIODevice that was set with either setDevice() or the
+ QCborStreamReader constructor. If this object was reading from a QByteArray,
+ this function returns nullptr instead.
+ */
+QIODevice *QCborStreamReader::device() const
+{
+ return d->device;
+}
+
+/*!
+ Adds \a data to the CBOR stream and reparses the current element. This
+ function is useful if the end of the data was previously reached while
+ processing the stream, but now more data is available.
+ */
+void QCborStreamReader::addData(const QByteArray &data)
+{
+ addData(data.constData(), data.size());
+}
+
+/*!
+ \fn void QCborStreamReader::addData(const quint8 *data, qsizetype len)
+ \overload
+
+ Adds \a len bytes of data starting at \a data to the CBOR stream and
+ reparses the current element. This function is useful if the end of the data
+ was previously reached while processing the stream, but now more data is
+ available.
+ */
+
+/*!
+ \overload
+
+ Adds \a len bytes of data starting at \a data to the CBOR stream and
+ reparses the current element. This function is useful if the end of the data
+ was previously reached while processing the stream, but now more data is
+ available.
+ */
+void QCborStreamReader::addData(const char *data, qsizetype len)
+{
+ if (!d->device) {
+ if (len > 0)
+ d->buffer.append(data, len);
+ reparse();
+ } else {
+ qWarning("QCborStreamReader: addData() with device()");
+ }
+}
+
+/*!
+ Reparses the current element. This function must be called when more data
+ becomes available in the source QIODevice after parsing failed due to
+ reaching the end of the input data before the end of the CBOR stream.
+
+ When reading from QByteArray(), the addData() function automatically calls
+ this function. Calling it when the reading had not failed is a no-op.
+ */
+void QCborStreamReader::reparse()
+{
+ d->lastError = {};
+ d->preread();
+ if (CborError err = cbor_value_reparse(&d->currentElement))
+ d->handleError(err);
+ else
+ preparse();
+}
+
+/*!
+ Clears the decoder state and resets the input source data to an empty byte
+ array. After this function is called, QCborStreamReader will be indicating
+ an error parsing.
+
+ Call addData() to add more data to be parsed.
+
+ \sa reset(), setDevice()
+ */
+void QCborStreamReader::clear()
+{
+ setDevice(nullptr);
+}
+
+/*!
+ Resets the source back to the beginning and clears the decoder state. If the
+ source data was a QByteArray, QCborStreamReader will restart from the
+ beginning of the array.
+
+ If the source data is a QIODevice, this function will call
+ QIODevice::reset(), which will seek to byte position 0. If the CBOR stream
+ is not found at the beginning of the device (e.g., beginning of a file),
+ then this function will likely do the wrong thing. Instead, position the
+ QIODevice to the right offset and call setDevice().
+
+ \sa clear(), setDevice()
+ */
+void QCborStreamReader::reset()
+{
+ if (d->device)
+ d->device->reset();
+ d->lastError = {};
+ d->initDecoder();
+ preparse();
+}
+
+/*!
+ Returns the last error in decoding the stream, if any. If no error
+ was encountered, this returns an QCborError::NoError.
+
+ \sa isValid()
+ */
+QCborError QCborStreamReader::lastError()
+{
+ return d->lastError;
+}
+
+/*!
+ Returns the offset in the input stream of the item currently being decoded.
+ The current offset is the number of decoded bytes so far only if the source
+ data is a QByteArray or it is a QIODevice that was positioned at its
+ beginning when decoding started.
+
+ \sa reset(), clear(), device()
+ */
+qint64 QCborStreamReader::currentOffset() const
+{
+ return (d->device ? d->device->pos() : 0) + d->bufferStart;
+}
+
+/*!
+ Returns the number of containers that this stream has entered with
+ enterContainer() but not yet left.
+
+ \sa enterContainer(), leaveContainer()
+ */
+int QCborStreamReader::containerDepth() const
+{
+ return d->containerStack.size();
+}
+
+/*!
+ Returns either QCborStreamReader::Array or QCborStreamReader::Map,
+ indicating whether the container that contains the current item was an array
+ or map, respectively. If we're currently parsing the root element, this
+ function returns QCborStreamReader::Invalid.
+
+ \sa containerDepth(), enterContainer()
+ */
+QCborStreamReader::Type QCborStreamReader::parentContainerType() const
+{
+ if (d->containerStack.isEmpty())
+ return Invalid;
+ return Type(cbor_value_get_type(&qAsConst(d->containerStack).top()));
+}
+
+/*!
+ Returns true if there are more items to be decoded in the current container
+ or false of we've reached its end. If we're parsing the root element,
+ hasNext() returning false indicates the parsing is complete; otherwise, if
+ the container depth is non-zero, then the outer code needs to call
+ leaveContainer().
+
+ \sa parentContainerType(), containerDepth(), leaveContainer()
+ */
+bool QCborStreamReader::hasNext() const noexcept
+{
+ return cbor_value_is_valid(&d->currentElement) &&
+ !cbor_value_at_end(&d->currentElement);
+}
+
+/*!
+ Advance the CBOR stream decoding one element. You should usually call this
+ function when parsing fixed-width basic elements (that is, integers, simple
+ values, tags and floating point values). But this function can be called
+ when the current item is a string, array or map too and it will skip over
+ that entire element, including all contained elements.
+
+ This function returns true if advancing was successful, false otherwise. It
+ may fail if the stream is corrupt, incomplete or if the nesting level of
+ arrays and maps exceeds \a maxRecursion. Calling this function when
+ hasNext() has returned false is also an error. If this function returns
+ false, lastError() will return the error code detailing what the failure
+ was.
+
+ \sa lastError(), isValid(), hasNext()
+ */
+bool QCborStreamReader::next(int maxRecursion)
+{
+ if (lastError() != QCborError::NoError)
+ return false;
+
+ if (!hasNext()) {
+ d->handleError(CborErrorAdvancePastEOF);
+ } else if (maxRecursion < 0) {
+ d->handleError(CborErrorNestingTooDeep);
+ } else if (isContainer()) {
+ // iterate over each element
+ enterContainer();
+ while (lastError() == QCborError::NoError && hasNext())
+ next(maxRecursion - 1);
+ if (lastError() == QCborError::NoError)
+ leaveContainer();
+ } else if (isString() || isByteArray()) {
+ auto r = _readByteArray_helper();
+ while (r.status == Ok) {
+ if (isString() && !QUtf8::isValidUtf8(r.data, r.data.size()).isValidUtf8) {
+ d->handleError(CborErrorInvalidUtf8TextString);
+ break;
+ }
+ r = _readByteArray_helper();
+ }
+ } else {
+ // fixed types
+ CborError err = cbor_value_advance_fixed(&d->currentElement);
+ if (err)
+ d->handleError(err);
+ }
+
+ preparse();
+ return d->lastError == QCborError::NoError;
+}
+
+/*!
+ Returns true if the length of the current array, map, byte array or string
+ is known (explicit in the CBOR stream), false otherwise. This function
+ should only be called if the element is one of those.
+
+ If the length is known, it may be obtained by calling length().
+
+ If the length of a map or an array is not known, it is implied by the number
+ of elements present in the stream. QCborStreamReader has no API to calculate
+ the length in that condition.
+
+ Strings and byte arrays may also have indeterminate length (that is, they
+ may be transmitted in multiple chunks). Those cannot currently be created
+ with QCborStreamWriter, but they could be with other encoders, so
+ QCborStreamReader supports them.
+
+ \sa length(), QCborStreamWriter::startArray(), QCborStreamWriter::startMap()
+ */
+bool QCborStreamReader::isLengthKnown() const noexcept
+{
+ return cbor_value_is_length_known(&d->currentElement);
+}
+
+/*!
+ Returns the length of the string or byte array, or the number of items in an
+ array or the number, of item pairs in a map, if known. This function must
+ not be called if the length is unknown (that is, if isLengthKnown() returned
+ false). It is an error to do that and it will cause QCborStreamReader to
+ stop parsing the input stream.
+
+ \sa isLengthKnown(), QCborStreamWriter::startArray(), QCborStreamWriter::startMap()
+ */
+quint64 QCborStreamReader::length() const
+{
+ CborError err;
+ switch (type()) {
+ case String:
+ case ByteArray:
+ case Map:
+ case Array:
+ if (isLengthKnown())
+ return value64;
+ err = CborErrorUnknownLength;
+ break;
+
+ default:
+ err = CborErrorIllegalType;
+ break;
+ }
+
+ d->handleError(err);
+ return quint64(-1);
+}
+
+/*!
+ \fn bool QCborStreamReader::enterContainer()
+
+ Enters the array or map that is the current item and prepares for iterating
+ the elements contained in the container. Returns true if entering the
+ container succeeded, false otherwise (usually, a parsing error). Each call
+ to enterContainer() must be paired with a call to leaveContainer().
+
+ This function may only be called if the current item is an array or a map
+ (that is, if isArray(), isMap() or isContainer() is true). Calling it in any
+ other condition is an error.
+
+ \sa leaveContainer(), isContainer(), isArray(), isMap()
+ */
+bool QCborStreamReader::_enterContainer_helper()
+{
+ d->containerStack.push(d->currentElement);
+ CborError err = cbor_value_enter_container(&d->containerStack.top(), &d->currentElement);
+ if (!err) {
+ preparse();
+ return true;
+ }
+ d->handleError(err);
+ return false;
+}
+
+/*!
+ Leaves the array or map whose items were being processed and positions the
+ decoder at the next item after the end of the container. Returns true if
+ leaving the container succeeded, false otherwise (usually, a parsing error).
+ Each call to enterContainer() must be paired with a call to
+ leaveContainer().
+
+ This function may only be called if hasNext() has returned false and
+ containerDepth() is not zero. Calling it in any other condition is an error.
+
+ \sa enterContainer(), parentContainerType(), containerDepth()
+ */
+bool QCborStreamReader::leaveContainer()
+{
+ if (d->containerStack.isEmpty()) {
+ qWarning("QCborStreamReader::leaveContainer: trying to leave top-level element");
+ return false;
+ }
+ if (d->corrupt)
+ return false;
+
+ CborValue container = d->containerStack.pop();
+ CborError err = cbor_value_leave_container(&container, &d->currentElement);
+ d->currentElement = container;
+ if (err) {
+ d->handleError(err);
+ return false;
+ }
+
+ preparse();
+ return true;
+}
+
+/*!
+ \fn bool QCborStreamReader::toBool() const
+
+ Returns the boolean value of the current element.
+
+ This function does not perform any type conversions, including from integer.
+ Therefore, it may only be called if isTrue(), isFalse() or isBool() returned
+ true; calling it in any other condition is an error.
+
+ \sa isBool(), isTrue(), isFalse(), toInteger()
+ */
+
+/*!
+ \fn QCborTag QCborStreamReader::toTag() const
+
+ Returns the tag value of the current element.
+
+ This function does not perform any type conversions, including from integer.
+ Therefore, it may only be called if isTag() is true; calling it in any other
+ condition is an error.
+
+ Tags are 64-bit numbers attached to generic CBOR types that give them
+ further meaning. For a list of known tags, see the \l QCborKnownTags
+ enumeration.
+
+ \sa isTag(), toInteger(), QCborKnownTags
+ */
+
+/*!
+ \fn quint64 QCborStreamReader::toUnsignedInteger() const
+
+ Returns the unsigned integer value of the current element.
+
+ This function does not perform any type conversions, including from boolean
+ or CBOR tag. Therefore, it may only be called if isUnsignedInteger() is
+ true; calling it in any other condition is an error.
+
+ This function may be used to obtain numbers beyond the range of the return
+ type of toInteger().
+
+ \sa type(), toInteger(), isUnsignedInteger(), isNegativeInteger()
+ */
+
+/*!
+ \fn QCborNegativeValue QCborStreamReader::toNegativeInteger() const
+
+ Returns the negative integer value of the current element.
+ QCborNegativeValue is a 64-bit unsigned integer containing the absolute
+ value of the negative number that was stored in the CBOR stream.
+ Additionally, QCborNegativeValue(0) represents the number -2\sup{64}.
+
+ This function does not perform any type conversions, including from boolean
+ or CBOR tag. Therefore, it may only be called if isNegativeInteger() is
+ true; calling it in any other condition is an error.
+
+ This function may be used to obtain numbers beyond the range of the return
+ type of toInteger(). However, use of negative numbers smaller than -2\sup{63}
+ is extremely discouraged.
+
+ \sa type(), toInteger(), isNegativeInteger(), isUnsignedInteger()
+ */
+
+/*!
+ \fn qint64 QCborStreamReader::toInteger() const
+
+ Returns the integer value of the current element, be it negative, positive
+ or zero. If the value is larger than 2\sup{63} - 1 or smaller than
+ -2\sup{63}, the returned value will overflow and will have an incorrect
+ sign. If handling those values is required, use toUnsignedInteger() or
+ toNegativeInteger() instead.
+
+ This function does not perform any type conversions, including from boolean
+ or CBOR tag. Therefore, it may only be called if isInteger() is true;
+ calling it in any other condition is an error.
+
+ \sa isInteger(), toUnsignedInteger(), toNegativeInteger()
+ */
+
+/*!
+ \fn QCborSimpleType QCborStreamReader::toSimpleType() const
+
+ Returns value of the current simple type.
+
+ This function does not perform any type conversions, including from integer.
+ Therefore, it may only be called if isSimpleType() is true; calling it in
+ any other condition is an error.
+
+ \sa isSimpleType(), isTrue(), isFalse(), isBool(), isNull(), isUndefined()
+ */
+
+/*!
+ \fn qfloat16 QCborStreamReader::toFloat16() const
+
+ Returns the 16-bit half-precision floating point value of the current element.
+
+ This function does not perform any type conversions, including from other
+ floating point types or from integer values. Therefore, it may only be
+ called if isFloat16() is true; calling it in any other condition is an
+ error.
+
+ \sa isFloat16(), toFloat(), toDouble()
+ */
+
+/*!
+ \fn float QCborStreamReader::toFloat() const
+
+ Returns the 32-bit single-precision floating point value of the current
+ element.
+
+ This function does not perform any type conversions, including from other
+ floating point types or from integer values. Therefore, it may only be
+ called if isFloat() is true; calling it in any other condition is an error.
+
+ \sa isFloat(), toFloat16(), toDouble()
+ */
+
+/*!
+ \fn double QCborStreamReader::toDouble() const
+
+ Returns the 64-bit double-precision floating point value of the current
+ element.
+
+ This function does not perform any type conversions, including from other
+ floating point types or from integer values. Therefore, it may only be
+ called if isDouble() is true; calling it in any other condition is an error.
+
+ \sa isDouble(), toFloat16(), toFloat()
+ */
+
+/*!
+ \fn QCborStreamReader::StringResult<QString> QCborStreamReader::readString()
+
+ Decodes one string chunk from the CBOR string and returns it. This function
+ is used for both regular and chunked string contents, so the caller must
+ always loop around calling this function, even if isLengthKnown() has
+ is true. The typical use of this function is as follows:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 27
+
+ This function does not perform any type conversions, including from integers
+ or from byte arrays. Therefore, it may only be called if isString() returned
+ true; calling it in any other condition is an error.
+
+ \sa readByteArray(), isString(), readStringChunk()
+ */
+QCborStreamReader::StringResult<QString> QCborStreamReader::_readString_helper()
+{
+ auto r = _readByteArray_helper();
+ QCborStreamReader::StringResult<QString> result;
+ result.status = r.status;
+
+ if (r.status == Ok) {
+ QTextCodec::ConverterState cs;
+ result.data = QUtf8::convertToUnicode(r.data, r.data.size(), &cs);
+ if (cs.invalidChars == 0 && cs.remainingChars == 0)
+ return result;
+
+ d->handleError(CborErrorInvalidUtf8TextString);
+ result.data.clear();
+ result.status = Error;
+ return result;
+ }
+ return result;
+}
+
+/*!
+ \fn QCborStreamReader::StringResult<QString> QCborStreamReader::readByteArray()
+
+ Decodes one byte array chunk from the CBOR string and returns it. This
+ function is used for both regular and chunked contents, so the caller must
+ always loop around calling this function, even if isLengthKnown() has
+ is true. The typical use of this function is as follows:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 28
+
+ This function does not perform any type conversions, including from integers
+ or from strings. Therefore, it may only be called if isByteArray() is true;
+ calling it in any other condition is an error.
+
+ \sa readString(), isByteArray(), readStringChunk()
+ */
+QCborStreamReader::StringResult<QByteArray> QCborStreamReader::_readByteArray_helper()
+{
+ QCborStreamReader::StringResult<QByteArray> result;
+ result.status = Error;
+ qsizetype len = _currentStringChunkSize();
+ if (len < 0)
+ return result;
+
+ result.data.resize(len);
+ auto r = readStringChunk(result.data.data(), len);
+ Q_ASSERT(r.status != Ok || r.data == len);
+ result.status = r.status;
+ return result;
+}
+
+/*!
+ \fn qsizetype QCborStreamReader::currentStringChunkSize() const
+
+ Returns the size of the current text or byte string chunk. If the CBOR
+ stream contains a non-chunked string (that is, if isLengthKnown() returns
+ \c true), this function returns the size of the entire string, the same as
+ length().
+
+ This function is useful to pre-allocate the buffer whose pointer can be passed
+ to readStringChunk() later.
+
+ \sa readString(), readByteArray(), readStringChunk()
+ */
+qsizetype QCborStreamReader::_currentStringChunkSize() const
+{
+ if (!d->ensureStringIteration())
+ return -1;
+
+ size_t len;
+ CborError err = cbor_value_get_string_chunk_size(&d->currentElement, &len);
+ if (err == CborErrorNoMoreStringChunks)
+ return 0; // not a real error
+ else if (err)
+ d->handleError(err);
+ else if (qsizetype(len) < 0)
+ d->handleError(CborErrorDataTooLarge);
+ else
+ return qsizetype(len);
+ return -1;
+}
+
+/*!
+ Reads the current string chunk into the buffer pointed to by \a ptr, whose
+ size is \a maxlen. This function returns a \l StringResult object, with the
+ number of bytes copied into \a ptr saved in the \c \l StringResult::data
+ member. The \c \l StringResult::status member indicates whether there was
+ an error reading the string, whether data was copied or whether this was
+ the last chunk.
+
+ This function can be called for both \l String and \l ByteArray types.
+ For the latter, this function will read the same data that readByteArray()
+ would have returned. For strings, it returns the UTF-8 equivalent of the \l
+ QString that would have been returned.
+
+ This function is usually used alongside currentStringChunkSize() in a loop.
+ For example:
+
+ \snippet code/src_corelib_serialization_qcborstream.cpp 29
+
+ Unlike readByteArray() and readString(), this function is not limited by
+ implementation limits of QByteArray and QString.
+
+ \note This function does not perform verification that the UTF-8 contents
+ are properly formatted. That means this function does not produce the
+ QCborError::InvalidUtf8String error, even when readString() does.
+
+ \sa currentStringChunkSize(), readString(), readByteArray(),
+ isString(), isByteArray()
+ */
+QCborStreamReader::StringResult<qsizetype>
+QCborStreamReader::readStringChunk(char *ptr, qsizetype maxlen)
+{
+ CborError err;
+ size_t len;
+ const void *content = nullptr;
+ QCborStreamReader::StringResult<qsizetype> result;
+ result.data = 0;
+ result.status = Error;
+
+ d->lastError = {};
+ if (!d->ensureStringIteration())
+ return result;
+
+#if 1
+ // Using internal TinyCBOR API!
+ err = _cbor_value_get_string_chunk(&d->currentElement, &content, &len, &d->currentElement);
+#else
+ // the above is effectively the same as:
+ if (cbor_value_is_byte_string(&currentElement))
+ err = cbor_value_get_byte_string_chunk(&d->currentElement, reinterpret_cast<const uint8_t **>(&content),
+ &len, &d->currentElement);
+ else
+ err = cbor_value_get_text_string_chunk(&d->currentElement, reinterpret_cast<const char **>(&content),
+ &len, &d->currentElement);
+#endif
+
+ // Range check: using implementation-defined behavior in converting an
+ // unsigned value out of range of the destination signed type (same as
+ // "len > size_t(std::numeric_limits<qsizetype>::max())", but generates
+ // better code with ICC and MSVC).
+ if (!err && qsizetype(len) < 0)
+ err = CborErrorDataTooLarge;
+
+ if (err) {
+ if (err == CborErrorNoMoreStringChunks) {
+ d->preread();
+ err = cbor_value_finish_string_iteration(&d->currentElement);
+ result.status = EndOfString;
+ }
+ if (err)
+ d->handleError(err);
+ else
+ preparse();
+ return result;
+ }
+
+ // Read the chunk into the user's buffer.
+ qint64 actuallyRead;
+ qptrdiff offset = qptrdiff(content);
+ qsizetype toRead = qsizetype(len);
+ qsizetype left = toRead - maxlen;
+ if (left < 0)
+ left = 0; // buffer bigger than string
+ else
+ toRead = maxlen; // buffer smaller than string
+
+ if (d->device) {
+ // This first skip can't fail because we've already read this many bytes.
+ d->device->skip(d->bufferStart + qptrdiff(content));
+ actuallyRead = d->device->read(ptr, toRead);
+
+ if (actuallyRead != toRead) {
+ actuallyRead = -1;
+ } else if (left) {
+ qint64 skipped = d->device->skip(left);
+ if (skipped != left)
+ actuallyRead = -1;
+ }
+
+ if (actuallyRead < 0) {
+ d->handleError(CborErrorIO);
+ return result;
+ }
+
+ d->updateBufferAfterString(offset, len);
+ } else {
+ actuallyRead = toRead;
+ memcpy(ptr, d->buffer.constData() + d->bufferStart + offset, toRead);
+ d->bufferStart += QByteArray::size_type(offset + len);
+ }
+
+ d->preread();
+ result.data = actuallyRead;
+ result.status = Ok;
+ return result;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qcborcommon.cpp"
+#include "moc_qcborstream.cpp"
diff --git a/src/corelib/serialization/qcborstream.h b/src/corelib/serialization/qcborstream.h
new file mode 100644
index 0000000000..3b13a309ab
--- /dev/null
+++ b/src/corelib/serialization/qcborstream.h
@@ -0,0 +1,267 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://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 QCBORSTREAM_H
+#define QCBORSTREAM_H
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qcborcommon.h>
+#include <QtCore/qfloat16.h>
+#include <QtCore/qscopedpointer.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qstringview.h>
+
+// See qcborcommon.h for why we check
+#if defined(QT_X11_DEFINES_FOUND)
+# undef True
+# undef False
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QIODevice;
+
+enum class QCborNegativeInteger : quint64 {};
+
+class QCborStreamWriterPrivate;
+class Q_CORE_EXPORT QCborStreamWriter
+{
+public:
+ explicit QCborStreamWriter(QIODevice *device);
+ explicit QCborStreamWriter(QByteArray *data);
+ ~QCborStreamWriter();
+ Q_DISABLE_COPY(QCborStreamWriter)
+
+ void setDevice(QIODevice *device);
+ QIODevice *device() const;
+
+ void append(quint64 u);
+ void append(qint64 i);
+ void append(QCborNegativeInteger n);
+ void append(const QByteArray &ba) { appendByteString(ba.constData(), ba.size()); }
+ void append(QLatin1String str);
+ void append(QStringView str);
+ void append(QCborTag tag);
+ void append(QCborKnownTags tag) { append(QCborTag(tag)); }
+ void append(QCborSimpleType st);
+ void append(std::nullptr_t) { append(QCborSimpleType::Null); }
+ void append(qfloat16 f);
+ void append(float f);
+ void append(double d);
+
+ void appendByteString(const char *data, qsizetype len);
+ void appendTextString(const char *utf8, qsizetype len);
+
+ // convenience
+ void append(bool b) { append(b ? QCborSimpleType::True : QCborSimpleType::False); }
+ void appendNull() { append(QCborSimpleType::Null); }
+ void appendUndefined() { append(QCborSimpleType::Undefined); }
+
+#ifndef Q_QDOC
+ // overloads to make normal code not complain
+ void append(int i) { append(qint64(i)); }
+ void append(uint u) { append(quint64(u)); }
+#endif
+#ifndef QT_NO_CAST_FROM_ASCII
+ void append(const char *str, qsizetype size = -1)
+ { appendTextString(str, (str && size == -1) ? int(strlen(str)) : size); }
+#endif
+
+ void startArray();
+ void startArray(quint64 count);
+ bool endArray();
+ void startMap();
+ void startMap(quint64 count);
+ bool endMap();
+
+ // no API for encoding chunked strings
+
+private:
+ QScopedPointer<QCborStreamWriterPrivate> d;
+};
+
+class QCborStreamReaderPrivate;
+class Q_CORE_EXPORT QCborStreamReader
+{
+ Q_GADGET
+public:
+ enum Type : quint8 {
+ UnsignedInteger = 0x00,
+ NegativeInteger = 0x20,
+ ByteString = 0x40,
+ ByteArray = ByteString,
+ TextString = 0x60,
+ String = TextString,
+ Array = 0x80,
+ Map = 0xa0,
+ Tag = 0xc0,
+ SimpleType = 0xe0,
+ HalfFloat = 0xf9,
+ Float16 = HalfFloat,
+ Float = 0xfa,
+ Double = 0xfb,
+
+ Invalid = 0xff
+ };
+ Q_ENUM(Type)
+
+ enum StringResultCode {
+ EndOfString = 0,
+ Ok = 1,
+ Error = -1
+ };
+ template <typename Container> struct StringResult {
+ Container data;
+ StringResultCode status = Error;
+ };
+ Q_ENUM(StringResultCode)
+
+ QCborStreamReader();
+ QCborStreamReader(const char *data, qsizetype len);
+ QCborStreamReader(const quint8 *data, qsizetype len);
+ explicit QCborStreamReader(const QByteArray &data);
+ explicit QCborStreamReader(QIODevice *device);
+ ~QCborStreamReader();
+ Q_DISABLE_COPY(QCborStreamReader)
+
+ void setDevice(QIODevice *device);
+ QIODevice *device() const;
+ void addData(const QByteArray &data);
+ void addData(const char *data, qsizetype len);
+ void addData(const quint8 *data, qsizetype len)
+ { addData(reinterpret_cast<const char *>(data), len); }
+ void reparse();
+ void clear();
+ void reset();
+
+ QCborError lastError();
+
+ qint64 currentOffset() const;
+
+ bool isValid() const { return !isInvalid(); }
+
+ int containerDepth() const;
+ QCborStreamReader::Type parentContainerType() const;
+ bool hasNext() const noexcept Q_DECL_PURE_FUNCTION;
+ bool next(int maxRecursion = 10000);
+
+ Type type() const { return QCborStreamReader::Type(type_); }
+ bool isUnsignedInteger() const { return type() == UnsignedInteger; }
+ bool isNegativeInteger() const { return type() == NegativeInteger; }
+ bool isInteger() const { return quint8(type()) <= quint8(NegativeInteger); }
+ bool isByteArray() const { return type() == ByteArray; }
+ bool isString() const { return type() == String; }
+ bool isArray() const { return type() == Array; }
+ bool isMap() const { return type() == Map; }
+ bool isTag() const { return type() == Tag; }
+ bool isSimpleType() const { return type() == SimpleType; }
+ bool isFloat16() const { return type() == Float16; }
+ bool isFloat() const { return type() == Float; }
+ bool isDouble() const { return type() == Double; }
+ bool isInvalid() const { return type() == Invalid; }
+
+ bool isSimpleType(QCborSimpleType st) const { return isSimpleType() && toSimpleType() == st; }
+ bool isFalse() const { return isSimpleType(QCborSimpleType::False); }
+ bool isTrue() const { return isSimpleType(QCborSimpleType::True); }
+ bool isBool() const { return isFalse() || isTrue(); }
+ bool isNull() const { return isSimpleType(QCborSimpleType::Null); }
+ bool isUndefined() const { return isSimpleType(QCborSimpleType::Undefined); }
+
+ bool isLengthKnown() const noexcept Q_DECL_PURE_FUNCTION;
+ quint64 length() const;
+
+ bool isContainer() const { return isMap() || isArray(); }
+ bool enterContainer() { Q_ASSERT(isContainer()); return _enterContainer_helper(); }
+ bool leaveContainer();
+
+ StringResult<QString> readString() { Q_ASSERT(isString()); return _readString_helper(); }
+ StringResult<QByteArray> readByteArray(){ Q_ASSERT(isByteArray()); return _readByteArray_helper(); }
+ qsizetype currentStringChunkSize() const{ Q_ASSERT(isString() || isByteArray()); return _currentStringChunkSize(); }
+ StringResult<qsizetype> readStringChunk(char *ptr, qsizetype maxlen);
+
+ bool toBool() const { Q_ASSERT(isBool()); return value64 - int(QCborSimpleType::False); }
+ QCborTag toTag() const { Q_ASSERT(isTag()); return QCborTag(value64); }
+ quint64 toUnsignedInteger() const { Q_ASSERT(isUnsignedInteger()); return value64; }
+ QCborNegativeInteger toNegativeInteger() const { Q_ASSERT(isNegativeInteger()); return QCborNegativeInteger(value64 + 1); }
+ QCborSimpleType toSimpleType() const{ Q_ASSERT(isSimpleType()); return QCborSimpleType(value64); }
+ qfloat16 toFloat16() const { Q_ASSERT(isFloat16()); return _toFloatingPoint<qfloat16>(); }
+ float toFloat() const { Q_ASSERT(isFloat()); return _toFloatingPoint<float>(); }
+ double toDouble() const { Q_ASSERT(isDouble()); return _toFloatingPoint<double>(); }
+
+ qint64 toInteger() const
+ {
+ Q_ASSERT(isInteger());
+ qint64 v = qint64(value64);
+ if (isNegativeInteger())
+ return -v - 1;
+ return v;
+ }
+
+private:
+ void preparse();
+ bool _enterContainer_helper();
+ StringResult<QString> _readString_helper();
+ StringResult<QByteArray> _readByteArray_helper();
+ qsizetype _currentStringChunkSize() const;
+
+ template <typename FP> FP _toFloatingPoint() const noexcept
+ {
+ using UInt = typename QIntegerForSizeof<FP>::Unsigned;
+ UInt u = UInt(value64);
+ FP f;
+ memcpy(static_cast<void *>(&f), &u, sizeof(f));
+ return f;
+ }
+
+ friend QCborStreamReaderPrivate;
+ friend class QCborContainerPrivate;
+ quint64 value64;
+ QScopedPointer<QCborStreamReaderPrivate> d;
+ quint8 type_;
+ quint8 reserved[3] = {};
+};
+
+QT_END_NAMESPACE
+
+#if defined(QT_X11_DEFINES_FOUND)
+# define True 1
+# define False 0
+#endif
+
+#endif // QCBORSTREAM_H
diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp
new file mode 100644
index 0000000000..5d97a6a06a
--- /dev/null
+++ b/src/corelib/serialization/qcborvalue.cpp
@@ -0,0 +1,2477 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://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 "qcborvalue.h"
+#include "qcborvalue_p.h"
+
+#include "qcborarray.h"
+#include "qcbormap.h"
+#include "qcborstream.h"
+
+#include <qendian.h>
+#include <qlocale.h>
+#include <private/qnumeric_p.h>
+#include <private/qsimd_p.h>
+
+#include <new>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QCborValue
+ \inmodule QtCore
+ \ingroup cbor
+ \reentrant
+ \since 5.12
+
+ \brief The QCborValue class encapsulates a value in CBOR.
+
+ This class can be used to hold one of the many types available in CBOR.
+ CBOR is the Concise Binary Object Representation, a very compact form of
+ binary data encoding that is a superset of JSON. It was created by the IETF
+ Constrained RESTful Environments (CoRE) WG, which has used it in many
+ new RFCs. It is meant to be used alongside the
+ \l{https://tools.ietf.org/html/rfc7252}{CoAP protocol}.
+
+ CBOR has three groups of built-in types:
+
+ \list
+ \li Basic types: integers, floating point (double), boolean, null, etc.
+ \li String-like types: strings and byte arrays
+ \li Containers: arrays and maps
+ \endlist
+
+ Additionally, CBOR supports a form of type extensibility by associating a
+ "tag" to one of the above types to convey more information. For example, a
+ UUID is represented by a tag and a byte array containing the 16 bytes of
+ the UUID content. QCborValue supports creating and decoding several of those
+ extended types directly with Qt classes (like QUuid).
+
+ For the complete list, see \l QCborValue::Type. The type of a QCborValue can
+ be queried using type() or one of the "isXxxx" functions.
+
+ \section1 Extended types and tagged values
+
+ A tagged value is a normal QCborValue that is paired with a number that
+ is its tag. See \l QCborKnownTags for more information on what tags are in
+ the API as well as the full, official list. Such combinations form extended
+ types.
+
+ QCborValue has support for certain extended types in the API, like URL
+ (with \l QUrl) and UUID (with \l QUuid). Other extended types not supported
+ in the API are represented by a QCborValue of \l {Type}{Tag} type. The tag
+ can later be retrieved by tag() and the tagged value using taggedValue().
+
+ In order to support future compatibility, QCborValues containing extended
+ Qt types compare equal to the tag type of the same contents. In other
+ words, the following expression is true:
+
+ \snippet code/src_corelib_serialization_qcborvalue.cpp 0
+
+ \section1 Undefined and null values
+
+ QCborValue can contain a value of "null", which is not of any specific type.
+ It resembles the C++ \c {std::nullptr_t} type, whose only possible value is
+ \c nullptr. QCborValue has a constructor taking such a type and creates a
+ null QCborValue.
+
+ Null values are used to indicate that an optional value is not present. In
+ that aspect, it is similar to the C++ Standard Library type \c
+ {std::optional} when that is disengaged. Unlike the C++ type, CBOR nulls
+ are simply of type "Null" and it is not possible to determine what concrete
+ type it is replacing.
+
+ QCborValue can also be of the undefined type, which represents a value of
+ "undefined". In fact, that is what the QCborValue default constructor
+ creates.
+
+ Undefined values are different from null values. While nulls are used to
+ indicate an optional value that is not provided, Undefined is usually
+ used to indicate that an expected value could not be provided, usually due
+ to an error or a precondition that could not be satisfied.
+
+ Such values are completely valid and may appear in CBOR streams, unlike
+ JSON content and QJsonValue's undefined bit. But like QJsonValue's
+ Undefined, it is returned by QCborArray::value() when out of range or
+ QCborMap::operator[] when the key is not found in the container. It is not
+ possible to tell such a case apart from the value of Undefined, so if that
+ is required, check the QCborArray size and use the QCborMap iterator API.
+
+ \section1 Simple types
+
+ CBOR supports additional simple types that, like Null and Undefined, carry
+ no other value. They are called interchangeably "Simple Types" and "Simple
+ Values". CBOR encodes booleans as two distinct types (one for \c true and
+ one for \c false), but QCborValue has a convenience API for them.
+
+ There are currently no other defined CBOR simple types. QCborValue supports
+ them simply by their number with API like isSimpleType() and
+ toSimpleType(), available for compatibility with future specifications
+ before the Qt API can be updated. Their use before such a specification is
+ discouraged, as other CBOR implementations may not support them fully.
+
+ \section1 CBOR support
+
+ QCborValue supports all CBOR features required to create canonical and
+ strict streams. It implements almost all of the features specified in \l
+ {https://tools.ietf.org/html/rfc7049}{RFC 7049}.
+
+ The following table lists the CBOR features that QCborValue supports.
+
+ \table
+ \header \li Feature \li Support
+ \row \li Unsigned numbers \li Yes (\l qint64 range)
+ \row \li Negative numbers \li Yes (\l qint64 range)
+ \row \li Byte strings \li Yes
+ \row \li Text strings \li Yes
+ \row \li Chunked strings \li See below
+ \row \li Tags \li Yes (arbitrary)
+ \row \li Booleans \li Yes
+ \row \li Null \li Yes
+ \row \li Undefined \li Yes
+ \row \li Arbitrary simple values \li Yes
+ \row \li Half-precision float (16-bit) \li Yes
+ \row \li Single-precision float (32-bit) \li Yes
+ \row \li Double-precision float (64-bit) \li Yes
+ \row \li Infinities and NaN floating point \li Yes
+ \row \li Determinate-length arrays and maps \li Yes
+ \row \li Indeterminate-length arrays and maps \li Yes
+ \row \li Map key types other than strings and integers \li Yes (arbitrary)
+ \endtable
+
+ Integers in QCborValue are limited to the range of the \l qint64 type. That
+ is, from -9,223,372,036,854,775,808 (-2\sup{63}) to
+ 9,223,372,036,854,775,807 (2\sup{63} - 1). CBOR itself can represent integer
+ values outside of this range, which QCborValue does not support. When
+ decoding a stream using fromCbor() containing one of those values,
+ QCborValue will convert automatically to \l {Type}{Double}, but that may
+ lose up to 11 bits of precision.
+
+ fromCbor() is able to decode chunked strings, but will always merge the
+ chunks together into a single QCborValue. For that reason, it always writes
+ non-chunked strings when using toCbor() (which is required by the Canonical
+ format anyway).
+
+ QCborValue will always convert half- and single-precision floating point
+ values in the CBOR stream to double-precision. The toCbor() function can
+ take a parameter indicating to recreate them.
+
+ \section1 QCborValueRef
+
+ QCborValueRef is a helper class for QCborArray and QCborMap. It is the type
+ you get when using one of the mutating APIs in those classes. Unlike
+ QCborValue, new values can be assigned to that class. When that is done, the
+ array or map it refers to will be modified with the new value. In all other
+ aspects, its API is identical to QCborValue.
+
+ \sa QCborArray, QCborMap, QCborStreamReader, QCborStreamWriter
+ QJsonValue, QJsonDocument
+ */
+
+/*!
+ \class QCborParserError
+ \inmodule QtCore
+ \ingroup cbor
+ \reentrant
+ \since 5.12
+
+ \brief The QCborParserError is used by QCborValue to report a parsing error.
+
+ This class is used by \l {QCborValue::fromCbor(const QByteArray &ba,
+ QCborParserError *error)} to report a parser error and the byte offset
+ where the error was detected.
+
+ \sa QCborValue, QCborError
+ */
+
+/*!
+ \variable qint64 QCborParserError::offset
+
+ This field contains the offset from the beginning of the data where the
+ error was detected. The offset should point to the beginning of the item
+ that contained the error, even if the error itself was elsewhere (for
+ example, for UTF-8 decoding issues).
+
+ \sa QCborValue::fromCbor()
+ */
+
+/*!
+ \variable QCborError QCborParserError::error
+
+ This field contains the error code that indicates what decoding problem was
+ found.
+
+ \sa QCborValue::fromCbor()
+ */
+
+/*!
+ \fn QString QCborParserError::errorString() const
+
+ Returns a string representation of the error code. This string is not
+ translated.
+
+ \sa QCborError::toString(), QCborValue::fromCbor()
+ */
+
+/*!
+ \enum QCborValue::EncodingOption
+
+ This enum is used in the options argument to toCbor(), modifying the
+ behavior of the encoder.
+
+ \omitvalue SortKeysInMaps
+ \value NoTransformation (Default) Performs no transformations.
+ \value UseFloat Tells the encoder to use IEEE 754 single-precision floating point
+ (that is, \c float) whenever possible.
+ \value UseFloat16 Tells the encoder to use IEEE 754 half-precision floating point
+ (that is, \c qfloat16), whenever possible. Implies \c UseFloat.
+ \value UseIntegers Tells the encoder to use integers whenever a value of type \l
+ {Type}{Double} contains an integer.
+
+ The use of \c UseFloat16 is required to encode the stream in Canonical
+ Format, but is not otherwise necessary.
+
+ \sa toCbor()
+ */
+
+/*!
+ \enum QCborValue::DiagnosticNotationOption
+
+ This enum is used in the option argument to toDiagnosticNotation(), to
+ modify the output format.
+
+ \value Compact Does not use any line-breaks, producing a compact representation.
+ \value LineWrapped Uses line-breaks, one QCborValue per line.
+ \value ExtendedFormat Uses some different options to represent values, not found in
+ RFC 7049. Those options are subject to change.
+
+ Currently, \c ExtendedFormat will change how byte arrays are represented.
+ Without it, they are always hex-encoded and without spaces. With it,
+ QCborValue::toCbor() will either use hex with spaces, base64 or base64url
+ encoding, depending on the context.
+
+ \sa toDiagnosticNotation()
+ */
+
+/*!
+ \enum QCborValue::Type
+
+ This enum represents the QCborValue type. It is returned by the type()
+ function.
+
+ The CBOR built-in types are:
+
+ \value Integer \c qint64: An integer value
+ \value ByteArray \l QByteArray: a byte array ("byte string")
+ \value String \l QString: a Unicode string ("text string")
+ \value Array \l QCborArray: an array of QCborValues
+ \value Map \l QCborMap: an associative container of QCborValues
+ \value SimpleType \l QCborSimpleType: one of several simple types/values
+ \value False \c bool: the simple type for value \c false
+ \value True \c bool: the simple type for value \c true
+ \value Null \c std::nullptr_t: the simple type for the null value
+ \value Undefined (no type) the simple type for the undefined value
+ \value Double \c double: a double-precision floating point
+ \value Invalid Not a valid value, this usually indicates a CBOR decoding error
+
+ Additionally, QCborValue can represent extended types:
+
+ \value Tag An unknown or unrecognized extended type, represented by its
+ tag (a \l QCborTag) and the tagged value (a QCborValue)
+ \value DateTime \l QDateTime: a date and time stamp
+ \value Url \l QUrl: a URL or URI
+ \value RegularExpression \l QRegularExpression: the pattern of a regular expression
+ \value Uuid \l QUuid: a UUID
+
+ \sa type()
+ */
+
+/*!
+ \fn QCborValue::QCborValue()
+
+ Creates a QCborValue of the \l {Type}{Undefined} type.
+
+ CBOR undefined values are used to indicate missing information, usually as
+ a result of a previous operation that did not complete as expected. They
+ are also used by the QCborArray and QCborMap API to indicate the searched
+ item was not found.
+
+ Undefined values are represented by the \l {QCborSimpleType}{Undefined
+ simple type}. Because of that, QCborValues with undefined values will also
+ return true for isSimpleType() and
+ \c{isSimpleType(QCborSimpleType::Undefined)}.
+
+ Undefined values are different from null values.
+
+ QCborValue objects with undefined values are also different from invalid
+ QCborValue objects. The API will not create invalid QCborValues, but they
+ may exist as a result of a parsing error.
+
+ \sa isUndefined(), isNull(), isSimpleType()
+ */
+
+/*!
+ \fn QCborValue::QCborValue(Type t_)
+
+ Creates a QCborValue of type \a t_. The value associated with such a type
+ (if any) will be default constructed.
+
+ \sa type()
+ */
+
+/*!
+ \fn QCborValue::QCborValue(std::nullptr_t)
+
+ Creates a QCborValue of the \l {Type}{Null} type.
+
+ CBOR null values are used to indicate optional values that were not
+ provided. They are distinct from undefined values, in that null values are
+ usually not the result of an earlier error or problem.
+
+ \sa isNull(), isUndefined(), isSimpleType()
+ */
+
+/*!
+ \fn QCborValue::QCborValue(bool b)
+
+ Creates a QCborValue with boolean value \a b. The value can later be
+ retrieved using toBool().
+
+ Internally, CBOR booleans are represented by a pair of types, one for true
+ and one for false. For that reason, boolean QCborValues will return true
+ for isSimpleType() and one of \c{isSimpleType(QCborSimpleType::False)} or
+ \c{isSimpleType(QCborSimpleType::True)}.
+
+ \sa toBool(), isBool(), isTrue(), isFalse(), isSimpleType()
+ */
+
+/*!
+ \fn QCborValue::QCborValue(qint64 i)
+
+ Creates a QCborValue with integer value \a i. The value can later be
+ retrieved using toInteger().
+
+ CBOR integer values are distinct from floating point values. Therefore,
+ QCborValue objects with integers will compare differently to QCborValue
+ objects containing floating-point, even if the values contained in the
+ objects are equivalent.
+
+ \sa toInteger(), isInteger(), isDouble()
+ */
+
+/*!
+ \fn QCborValue::QCborValue(double d)
+
+ Creates a QCborValue with floating point value \a d. The value can later be
+ retrieved using toDouble().
+
+ CBOR floating point values are distinct from integer values. Therefore,
+ QCborValue objects with integers will compare differently to QCborValue
+ objects containing floating-point, even if the values contained in the
+ objects are equivalent.
+
+ \sa toDouble(), isDouble(), isInteger()
+ */
+
+/*!
+ \fn QCborValue::QCborValue(QCborSimpleType st)
+
+ Creates a QCborValue of simple type \a st. The type can later later be retrieved
+ using toSimpleType() as well as isSimpleType(st).
+
+ CBOR simple types are types that do not have any associated value, like
+ C++'s \c{std::nullptr_t} type, whose only possible value is \c nullptr.
+
+ If \a st is \c{QCborSimpleType::Null}, the resulting QCborValue will be of
+ the \l{Type}{Null} type and similarly for \c{QCborSimpleType::Undefined}.
+ If \a st is \c{QCborSimpleType::False} or \c{QCborSimpleType::True}, the
+ created QCborValue will be a boolean containing a value of false or true,
+ respectively.
+
+ This function can be used with simple types not defined in the API. For
+ example, to create a QCborValue with simple type 12, one could write:
+
+ \snippet code/src_corelib_serialization_qcborvalue.cpp 1
+
+ Simple types should not be used until a specification for them has been
+ published, since other implementations may not support them properly.
+ Simple type values 24 to 31 are reserved and must not be used.
+
+ isSimpleType(), isNull(), isUndefined(), isTrue(), isFalse()
+ */
+
+/*!
+ \fn QCborValue::QCborValue(QCborKnownTags tag, const QCborValue &taggedValue)
+ \overload
+
+ Creates a QCborValue for the extended type represented by the tag value \a
+ tag, tagging value \a taggedValue. The tag can later be retrieved using
+ tag() and the tagged value using taggedValue().
+
+ \sa isTag(), tag(), taggedValue(), QCborKnownTags
+ */
+
+/*!
+ \fn QCborValue::~QCborValue()
+
+ Disposes of the current QCborValue object and frees any associated resources.
+ */
+
+/*!
+ \fn QCborValue::QCborValue(QCborValue &&other)
+ \overload
+
+ Moves the contents of the \a other CBorValue object into this one and frees
+ the resources of this one.
+ */
+
+/*!
+ \fn QCborValue &&QCborValue::operator=(QCborValue &&other)
+ \overload
+
+ Moves the contents of the \a other CBorValue object into this one and frees
+ the resources of this one. Returns a reference to this object.
+ */
+
+/*!
+ \fn void QCborValue::swap(QCborValue &other)
+
+ Swaps the contents of this QCborValue object and \a other.
+ */
+
+/*!
+ \fn QCborValue::Type QCborValue::type() const
+
+ Returns the type of this QCborValue. The type can also later be retrieved by one
+ of the "isXxx" functions.
+
+ \sa isInteger(), isByteArray(), isString(), isArray(), isMap(),
+ isTag(), isFalse(), isTrue(), isBool(), isNull(), isUndefined, isDouble(),
+ isDateTime(), isUrl(), isRegularExpression(), isUuid()
+ */
+
+/*!
+ \fn bool QCborValue::isInteger() const
+
+ Returns true if this QCborValue is of the integer type. The integer value
+ can be retrieved using toInteger().
+
+ \sa type(), toInteger()
+ */
+
+/*!
+ \fn bool QCborValue::isByteArray() const
+
+ Returns true if this QCborValue is of the byte array type. The byte array
+ value can be retrieved using toByteArray().
+
+ \sa type(), toByteArray()
+ */
+
+/*!
+ \fn bool QCborValue::isString() const
+
+ Returns true if this QCborValue is of the string type. The string value
+ can be retrieved using toString().
+
+ \sa type(), toString()
+ */
+
+/*!
+ \fn bool QCborValue::isArray() const
+
+ Returns true if this QCborValue is of the array type. The array value can
+ be retrieved using toArray().
+
+ \sa type(), toArray()
+ */
+
+/*!
+ \fn bool QCborValue::isMap() const
+
+ Returns true if this QCborValue is of the map type. The map value can be
+ retrieved using toMap().
+
+ \sa type(), toMap()
+ */
+
+/*!
+ \fn bool QCborValue::isTag() const
+
+ Returns true if this QCborValue is of the tag type. The tag value can be
+ retrieved using tag() and the tagged value using taggedValue().
+
+ This function also returns true for extended types that the API
+ recognizes. For code that handles extended types directly before the Qt API
+ is updated to support them, it is possible to recreate the tag + tagged
+ value pair by using taggedValue().
+
+ \sa type(), tag(), taggedValue(), taggedValue()
+ */
+
+/*!
+ \fn bool QCborValue::isFalse() const
+
+ Returns true if this QCborValue is a boolean with false value. This
+ function exists because, internally, CBOR booleans are stored as two
+ separate types, one for true and one for false.
+
+ \sa type(), isBool(), isTrue(), toBool()
+ */
+
+/*!
+ \fn bool QCborValue::isTrue() const
+
+ Returns true if this QCborValue is a boolean with true value. This
+ function exists because, internally, CBOR booleans are stored as two
+ separate types, one for false and one for true.
+
+ \sa type(), isBool(), isFalse(), toBool()
+ */
+
+/*!
+ \fn bool QCborValue::isBool() const
+
+ Returns true if this QCborValue is a boolean. The value can be retrieved
+ using toBool().
+
+ \sa type(), toBool(), isTrue(), isFalse()
+ */
+
+/*!
+ \fn bool QCborValue::isUndefined() const
+
+ Returns true if this QCborValue is of the undefined type.
+
+ CBOR undefined values are used to indicate missing information, usually as
+ a result of a previous operation that did not complete as expected. They
+ are also used by the QCborArray and QCborMap API to indicate the searched
+ item was not found.
+
+ Undefined values are distinct from null values.
+
+ QCborValue objects with undefined values are also different from invalid
+ QCborValue objects. The API will not create invalid QCborValues, but they
+ may exist as a result of a parsing error.
+
+ \sa type(), isNull(), isInvalid()
+ */
+
+/*!
+ \fn bool QCborValue::isNull() const
+
+ Returns true if this QCborValue is of the null type.
+
+ CBOR null values are used to indicate optional values that were not
+ provided. They are distinct from undefined values, in that null values are
+ usually not the result of an earlier error or problem.
+
+ Null values are distinct from undefined values and from invalid QCborValue
+ objects. The API will not create invalid QCborValues, but they may exist as
+ a result of a parsing error.
+
+ \sa type(), isUndefined(), isInvalid()
+ */
+
+/*!
+ \fn bool QCborValue::isDouble() const
+
+ Returns true if this QCborValue is of the floating-point type. The value
+ can be retrieved using toDouble().
+
+ \sa type(), toDouble()
+ */
+
+/*!
+ \fn bool QCborValue::isDateTime() const
+
+ Returns true if this QCborValue is of the date/time type. The value can be
+ retrieved using toDateTime(). Date/times are extended types that use the
+ tag \l{QCborKnownTags}{DateTime}.
+
+ Additionally, when decoding from a CBOR stream, QCborValue will interpret
+ tags of value \l{QCborKnownTags}{UnixTime_t} and convert them to the
+ equivalent date/time.
+
+ \sa type(), toDateTime()
+ */
+
+/*!
+ \fn bool QCborValue::isUrl() const
+
+ Returns true if this QCborValue is of the URL type. The URL value
+ can be retrieved using toUrl().
+
+ \sa type(), toUrl()
+ */
+
+/*!
+ \fn bool QCborValue::isRegularExpression() const
+
+ Returns true if this QCborValue contains a regular expression's pattern.
+ The pattern can be retrieved using toRegularExpression().
+
+ \sa type(), toRegularExpression()
+ */
+
+/*!
+ \fn bool QCborValue::isUuid() const
+
+ Returns true if this QCborValue contains a UUID. The value can be retrieved
+ using toUuid().
+
+ \sa type(), toUuid()
+ */
+
+/*!
+ \fn bool QCborValue::isInvalid() const
+
+ Returns true if this QCborValue is not of any valid type. Invalid
+ QCborValues are distinct from those with undefined values and they usually
+ represent a decoding error.
+
+ \sa isUndefined(), isNull()
+ */
+
+/*!
+ \fn bool QCborValue::isContainer() const
+
+ This convenience function returns true if the QCborValue is either an array
+ or a map.
+
+ \sa isArray(), isMap()
+ */
+
+/*!
+ \fn bool QCborValue::isSimpleType() const
+
+ Returns true if this QCborValue is of one of the CBOR simple types. The
+ type itself can later be retrieved using type(), even for types that don't have an
+ enumeration in the API. They can also be checked with the
+ \l{isSimpleType(QCborSimpleType)} overload.
+
+ \sa QCborSimpleType, isSimpleType(QCborSimpleType), toSimpleType()
+ */
+
+/*!
+ \fn bool QCborValue::isSimpleType(QCborSimpleType st) const
+ \overload
+
+ Returns true if this QCborValue is of a simple type and toSimpleType()
+ would return \a st, false otherwise. This function can be used to check for
+ any CBOR simple type, even those for which there is no enumeration in the
+ API. For example, for the simple type of value 12, you could write:
+
+ \snippet code/src_corelib_serialization_qcborvalue.cpp 2
+
+ \sa QCborValue::QCborValue(QCborSimpleType), isSimpleType(), isFalse(),
+ isTrue(), isNull, isUndefined(), toSimpleType()
+ */
+
+/*!
+ \fn QCborSimpleType QCborValue::toSimpleType(QCborSimpleType defaultValue) const
+
+ Returns the simple type this QCborValue is of, if it is a simple type. If
+ it is not a simple type, it returns \a defaultValue.
+
+ The following types are simple types and this function will return the
+ listed values:
+
+ \table
+ \row \li QCborValue::False \li QCborSimpleType::False
+ \row \li QCborValue::True \li QCborSimpleType::True
+ \row \li QCborValue::Null \li QCborSimpleType::Null
+ \row \li QCborValue::Undefined \li QCborSimpleType::Undefined
+ \endtable
+
+ \sa type(), isSimpleType(), isBool(), isTrue(), isFalse(), isTrue(),
+ isNull(), isUndefined()
+ */
+
+/*!
+ \fn qint64 QCborValue::toInteger(qint64 defaultValue) const
+
+ Returns the integer value stored in this QCborValue, if it is of the
+ integer type. If it is of the Double type, this function returns the
+ floating point value converted to integer. In any other case, it returns \a
+ defaultValue.
+
+ \sa isInteger(), isDouble(), toDouble()
+ */
+
+/*!
+ \fn bool QCborValue::toBool(bool defaultValue) const
+
+ Returns the boolean value stored in this QCborValue, if it is of a boolean
+ type. Otherwise, it returns \a defaultValue.
+
+ \sa isBool(), isTrue(), isFalse()
+ */
+
+/*!
+ \fn double QCborValue::toDouble(double defaultValue) const
+
+ Returns the floating point value stored in this QCborValue, if it is of the
+ Double type. If it is of the Integer type, this function returns the
+ integer value converted to double. In any other case, it returns \a
+ defaultValue.
+
+ \sa isDouble(), isInteger(), toInteger()
+ */
+
+using namespace QtCbor;
+
+// in qcborstream.cpp
+extern void qt_cbor_stream_set_error(QCborStreamReaderPrivate *d, QCborError error);
+
+static void writeDoubleToCbor(QCborStreamWriter &writer, double d, QCborValue::EncodingOptions opt)
+{
+ if (qt_is_nan(d)) {
+ if (opt & QCborValue::UseFloat16) {
+ if ((opt & QCborValue::UseFloat16) == QCborValue::UseFloat16)
+ return writer.append(qfloat16(qt_qnan()));
+ return writer.append(float(qt_qnan()));
+ }
+ return writer.append(qt_qnan());
+ }
+
+ if (qt_is_inf(d)) {
+ d = d > 0 ? qt_inf() : -qt_inf();
+ } else if (opt & QCborValue::UseIntegers) {
+ quint64 i;
+ if (convertDoubleTo(d, &i)) {
+ if (d < 0)
+ return writer.append(QCborNegativeInteger(i));
+ return writer.append(i);
+ }
+ }
+
+ if (opt & QCborValue::UseFloat16) {
+ float f = float(d);
+ if (f == d) {
+ // no data loss, we could use float
+ if ((opt & QCborValue::UseFloat16) == QCborValue::UseFloat16) {
+ qfloat16 f16 = f;
+ if (f16 == f)
+ return writer.append(f16);
+ }
+
+ return writer.append(f);
+ }
+ }
+
+ writer.append(d);
+}
+
+static inline int typeOrder(Element e1, Element e2)
+{
+ auto comparable = [](Element e) {
+ if (e.type >= 0x10000) // see QCborValue::isTag_helper()
+ return QCborValue::Tag;
+ return e.type;
+ };
+ return comparable(e1) - comparable(e2);
+}
+
+QCborContainerPrivate::~QCborContainerPrivate()
+{
+ // delete our elements
+ for (Element &e : elements) {
+ if (e.flags & Element::IsContainer)
+ e.container->deref();
+ }
+}
+
+void QCborContainerPrivate::compact(qsizetype reserved)
+{
+ if (usedData > data.size() / 2)
+ return;
+
+ // 50% savings if we recreate the byte data
+ // ### TBD
+ Q_UNUSED(reserved);
+}
+
+QCborContainerPrivate *QCborContainerPrivate::clone(QCborContainerPrivate *d, qsizetype reserved)
+{
+ if (!d) {
+ d = new QCborContainerPrivate;
+ } else {
+ d = new QCborContainerPrivate(*d);
+ if (reserved >= 0) {
+ d->elements.reserve(reserved);
+ d->compact(reserved);
+ }
+ for (auto &e : qAsConst(d->elements)) {
+ if (e.flags & Element::IsContainer)
+ e.container->ref.ref();
+ }
+ }
+ return d;
+}
+
+QCborContainerPrivate *QCborContainerPrivate::detach(QCborContainerPrivate *d, qsizetype reserved)
+{
+ if (!d || d->ref.load() != 1)
+ return clone(d, reserved);
+ return d;
+}
+
+/*!
+ Prepare for an insertion at position \a index
+
+ Detaches and ensures there are at least index entries in the array, padding
+ with Undefined as needed.
+*/
+QCborContainerPrivate *QCborContainerPrivate::grow(QCborContainerPrivate *d, qsizetype index)
+{
+ Q_ASSERT(index >= 0);
+ d = detach(d, index + 1);
+ Q_ASSERT(d);
+ int j = d->elements.size();
+ while (j < index)
+ d->append(Undefined());
+ return d;
+}
+
+// Copies or moves \a value into element at position \a e. If \a disp is
+// CopyContainer, then this function increases the reference count of the
+// container, but otherwise leaves it unmodified. If \a disp is MoveContainer,
+// then it transfers ownership (move semantics) and the caller must set
+// value.container back to nullptr.
+void QCborContainerPrivate::replaceAt_complex(Element &e, const QCborValue &value, ContainerDisposition disp)
+{
+ if (value.n < 0) {
+ // This QCborValue is an array, map, or tagged value (container points
+ // to itself).
+
+ // detect self-assignment
+ if (Q_UNLIKELY(this == value.container)) {
+ Q_ASSERT(ref.load() >= 2);
+ if (disp == MoveContainer)
+ ref.deref(); // not deref() because it can't drop to 0
+ QCborContainerPrivate *d = QCborContainerPrivate::clone(this);
+ d->elements.detach();
+ d->ref.store(1);
+ e.container = d;
+ } else {
+ e.container = value.container;
+ if (disp == CopyContainer)
+ e.container->ref.ref();
+ }
+
+ e.type = value.type();
+ e.flags = Element::IsContainer;
+ } else {
+ // String data, copy contents
+ e = value.container->elements.at(value.n);
+
+ // Copy string data, if any
+ if (const ByteData *b = value.container->byteData(value.n))
+ e.value = addByteData(b->byte(), b->len);
+
+ if (disp == MoveContainer)
+ value.container->deref();
+ }
+}
+
+// in qstring.cpp
+void qt_to_latin1_unchecked(uchar *dst, const ushort *uc, qsizetype len);
+
+Q_NEVER_INLINE void QCborContainerPrivate::appendAsciiString(const QString &s)
+{
+ qsizetype len = s.size();
+ QtCbor::Element e;
+ e.value = addByteData(nullptr, len);
+ e.type = QCborValue::String;
+ e.flags = Element::HasByteData | Element::StringIsAscii;
+ elements.append(e);
+
+ char *ptr = data.data() + e.value + sizeof(ByteData);
+ uchar *l = reinterpret_cast<uchar *>(ptr);
+ const ushort *uc = (const ushort *)s.unicode();
+ qt_to_latin1_unchecked(l, uc, len);
+}
+
+QCborValue QCborContainerPrivate::extractAt_complex(Element e)
+{
+ // create a new container for the returned value, containing the byte data
+ // from this element, if it's worth it
+ Q_ASSERT(e.flags & Element::HasByteData);
+ auto b = byteData(e);
+ auto container = new QCborContainerPrivate;
+
+ if (b->len + qsizetype(sizeof(*b)) < data.size() / 4) {
+ // make a shallow copy of the byte data
+ container->appendByteData(b->byte(), b->len, e.type, e.flags);
+ usedData -= b->len + qsizetype(sizeof(*b));
+ compact(elements.size());
+ } else {
+ // just share with the original byte data
+ container->data = data;
+ container->elements.reserve(1);
+ container->elements.append(e);
+ }
+
+ return makeValue(e.type, 0, container);
+}
+
+QT_WARNING_DISABLE_MSVC(4146) // unary minus operator applied to unsigned type, result still unsigned
+static int compareContainer(const QCborContainerPrivate *c1, const QCborContainerPrivate *c2);
+static int compareElementNoData(const Element &e1, const Element &e2)
+{
+ Q_ASSERT(e1.type == e2.type);
+
+ if (e1.type == QCborValue::Integer) {
+ // CBOR sorting order is 0, 1, 2, ..., INT64_MAX, -1, -2, -3, ... INT64_MIN
+ // So we transform:
+ // 0 -> 0
+ // 1 -> 1
+ // INT64_MAX -> INT64_MAX
+ // -1 -> INT64_MAX + 1 = INT64_MAX - (-1)
+ // -2 -> INT64_MAX + 2 = INT64_MAX - (-2)
+ // INT64_MIN -> UINT64_MAX = INT64_MAX - INT64_MIN
+ // Note how the unsigned arithmethic is well defined in C++ (it's
+ // always performed modulo 2^64).
+ auto makeSortable = [](qint64 v) {
+ quint64 u = quint64(v);
+ if (v < 0)
+ return quint64(std::numeric_limits<qint64>::max()) + (-u);
+ return u;
+ };
+ quint64 u1 = makeSortable(e1.value);
+ quint64 u2 = makeSortable(e2.value);
+ if (u1 < u2)
+ return -1;
+ if (u1 > u2)
+ return 1;
+ }
+
+ if (e1.type == QCborValue::Tag || e1.type == QCborValue::Double) {
+ // Perform unsigned comparisons for the tag value and floating point
+ quint64 u1 = quint64(e1.value);
+ quint64 u2 = quint64(e2.value);
+ if (u1 != u2)
+ return u1 < u2 ? -1 : 1;
+ }
+
+ // Any other type is equal at this point:
+ // - simple types carry no value
+ // - empty strings, arrays and maps
+ return 0;
+}
+
+static int compareElementRecursive(const QCborContainerPrivate *c1, const Element &e1,
+ const QCborContainerPrivate *c2, const Element &e2)
+{
+ int cmp = typeOrder(e1, e2);
+ if (cmp != 0)
+ return cmp;
+
+ if ((e1.flags & Element::IsContainer) || (e2.flags & Element::IsContainer))
+ return compareContainer(e1.flags & Element::IsContainer ? e1.container : nullptr,
+ e2.flags & Element::IsContainer ? e2.container : nullptr);
+
+ // string data?
+ const ByteData *b1 = c1 ? c1->byteData(e1) : nullptr;
+ const ByteData *b2 = c2 ? c2->byteData(e2) : nullptr;
+ if (b1 || b2) {
+ auto len1 = b1 ? b1->len : 0;
+ auto len2 = b2 ? b2->len : 0;
+
+ if (e1.flags & Element::StringIsUtf16)
+ len1 /= 2;
+ if (e2.flags & Element::StringIsUtf16)
+ len2 /= 2;
+ if (len1 == 0 || len2 == 0)
+ return len1 < len2 ? -1 : len1 == len2 ? 0 : 1;
+
+ // we definitely have data from this point forward
+ Q_ASSERT(b1);
+ Q_ASSERT(b2);
+
+ // Officially with CBOR, we sort first the string with the shortest
+ // UTF-8 length. The length of an ASCII string is the same as its UTF-8
+ // and UTF-16 ones, but the UTF-8 length of a string is bigger than the
+ // UTF-16 equivalent. Combinations are:
+ // 1) UTF-16 and UTF-16
+ // 2) UTF-16 and UTF-8 <=== this is the problem case
+ // 3) UTF-16 and US-ASCII
+ // 4) UTF-8 and UTF-8
+ // 5) UTF-8 and US-ASCII
+ // 6) US-ASCII and US-ASCII
+ if ((e1.flags & Element::StringIsUtf16) && (e2.flags & Element::StringIsUtf16)) {
+ // Case 1: both UTF-16, so lengths are comparable.
+ // (we can't use memcmp in little-endian machines)
+ if (len1 == len2)
+ return QtPrivate::compareStrings(b1->asStringView(), b2->asStringView());
+ return len1 < len2 ? -1 : 1;
+ }
+
+ if (!(e1.flags & Element::StringIsUtf16) && !(e2.flags & Element::StringIsUtf16)) {
+ // Cases 4, 5 and 6: neither is UTF-16, so lengths are comparable too
+ // (this case includes byte arrays too)
+ if (len1 == len2)
+ return memcmp(b1->byte(), b2->byte(), size_t(len1));
+ return len1 < len2 ? -1 : 1;
+ }
+
+ if (!(e1.flags & Element::StringIsAscii) || !(e2.flags & Element::StringIsAscii)) {
+ // Case 2: one of them is UTF-8 and the other is UTF-16, so lengths
+ // are NOT comparable. We need to convert to UTF-16 first...
+ auto string = [](const Element &e, const ByteData *b) {
+ return e.flags & Element::StringIsUtf16 ? b->asQStringRaw() : b->toUtf8String();
+ };
+
+ QString s1 = string(e1, b1);
+ QString s2 = string(e2, b2);
+ if (s1.size() == s2.size())
+ return s1.compare(s2);
+ return s1.size() < s2.size() ? -1 : 1;
+ }
+
+ // Case 3 (UTF-16 and US-ASCII) remains, so lengths are comparable again
+ if (len1 != len2)
+ return len1 < len2 ? -1 : 1;
+ if (e1.flags & Element::StringIsUtf16)
+ return QtPrivate::compareStrings(b1->asStringView(), b2->asLatin1());
+ return QtPrivate::compareStrings(b1->asLatin1(), b2->asStringView());
+ }
+
+ return compareElementNoData(e1, e2);
+}
+
+static int compareContainer(const QCborContainerPrivate *c1, const QCborContainerPrivate *c2)
+{
+ auto len1 = c1 ? c1->elements.size() : 0;
+ auto len2 = c2 ? c2->elements.size() : 0;
+ if (len1 != len2) {
+ // sort the shorter container first
+ return len1 < len2 ? -1 : 1;
+ }
+
+ for (qsizetype i = 0; i < len1; ++i) {
+ const Element &e1 = c1->elements.at(i);
+ const Element &e2 = c2->elements.at(i);
+ int cmp = QCborContainerPrivate::compareElement_helper(c1, e1, c2, e2);
+ if (cmp)
+ return cmp;
+ }
+
+ return 0;
+}
+
+inline int QCborContainerPrivate::compareElement_helper(const QCborContainerPrivate *c1, Element e1,
+ const QCborContainerPrivate *c2, Element e2)
+{
+ return compareElementRecursive(c1, e1, c2, e2);
+}
+
+/*!
+ \fn bool QCborValue::operator==(const QCborValue &other) const
+
+ Compares this value and \a other, and returns true if they hold the same
+ contents, false otherwise. If each QCborValue contains an array or map, the
+ comparison is recursive to elements contained in them.
+
+ For more information on CBOR equality in Qt, see, compare().
+
+ \sa compare(), QCborValue::operator==(), QCborMap::operator==(),
+ operator!=(), operator<()
+ */
+
+/*!
+ \fn bool QCborValue::operator!=(const QCborValue &other) const
+
+ Compares this value and \a other, and returns true if contents differ,
+ false otherwise. If each QCborValue contains an array or map, the comparison
+ is recursive to elements contained in them.
+
+ For more information on CBOR equality in Qt, see, QCborValue::compare().
+
+ \sa compare(), QCborValue::operator==(), QCborMap::operator==(),
+ operator==(), operator<()
+ */
+
+/*!
+ \fn bool QCborValue::operator<(const QCborValue &other) const
+
+ Compares this value and \a other, and returns true if this value should be
+ sorted before \a other, false otherwise. If each QCborValue contains an
+ array or map, the comparison is recursive to elements contained in them.
+
+ For more information on CBOR sorting order, see QCborValue::compare().
+
+ \sa compare(), QCborValue::operator==(), QCborMap::operator==(),
+ operator==(), operator!=()
+ */
+
+/*!
+ Compares this value and \a other, and returns an integer that indicates
+ whether this value should be sorted prior to (if the result is negative) or
+ after \a other (if the result is positive). If this function returns 0, the
+ two values are equal and hold the same contents.
+
+ If each QCborValue contains an array or map, the comparison is recursive to
+ elements contained in them.
+
+ \section3 Extended types
+
+ QCborValue compares equal a QCborValue containing an extended type, like
+ \l{Type}{Url} and \l{Type}{Url} and its equivalent tagged representation.
+ So, for example, the following expression is true:
+
+ \snippet code/src_corelib_serialization_qcborvalue.cpp 3
+
+ Do note that Qt types like \l QUrl and \l QDateTime will normalize and
+ otherwise modify their arguments. The expression above is true only because
+ the string on the right side is the normalized value that the QCborValue on
+ the left would take. If, for example, the "https" part were uppercase in
+ both sides, the comparison would fail. For information on normalizations
+ performed by QCborValue, please consult the documentation of the
+ constructor taking the Qt type in question.
+
+ \section3 Sorting order
+
+ Sorting order in CBOR is defined in RFC 7049
+ {https://tools.ietf.org/html/rfc7049#section-3.9}{section 3.9}, which
+ discusses the sorting of keys in a map when following the Canonical
+ encoding. According to the specification, "sorting is performed on the
+ bytes of the representation of the key data items" and lists as
+ consequences that:
+
+ \list
+ \li "If two keys have different lengths, the shorter one sorts earlier;"
+ \li "If two keys have the same length, the one with the lower value in
+ (byte-wise) lexical order sorts earlier."
+ \endlist
+
+ This results in surprising sorting of QCborValues, where the result of this
+ function is different from that which would later be retrieved by comparing the
+ contained elements. For example, the QCborValue containing string "zzz"
+ sorts before the QCborValue with string "foobar", even though when
+ comparing as \l{QString::compare()}{QStrings} or
+ \l{QByteArray}{QByteArrays} the "zzz" sorts after "foobar"
+ (dictionary order).
+
+ The specification does not clearly indicate what sorting order should be
+ done for values of different types (it says sorting should not pay
+ "attention to the 3/5 bit splitting for major types"). QCborValue makes the
+ assumption that types should be sorted too. The numeric values of the
+ QCborValue::Type enumeration are in that order, with the exception of the
+ extended types, which compare as their tagged equivalents.
+
+ \note Sorting order is preliminary and is subject to change. Applications
+ should not depend on the order returned by this function for the time
+ being.
+
+ \sa QCborArray::compare(), QCborMap::compare(), operator==()
+ */
+int QCborValue::compare(const QCborValue &other) const
+{
+ Element e1 = QCborContainerPrivate::elementFromValue(*this);
+ Element e2 = QCborContainerPrivate::elementFromValue(other);
+ return compareElementRecursive(container, e1, other.container, e2);
+}
+
+int QCborArray::compare(const QCborArray &other) const noexcept
+{
+ return compareContainer(d.data(), other.d.data());
+}
+
+int QCborMap::compare(const QCborMap &other) const noexcept
+{
+ return compareContainer(d.data(), other.d.data());
+}
+
+static void encodeToCbor(QCborStreamWriter &writer, const QCborContainerPrivate *d, qsizetype idx,
+ QCborValue::EncodingOptions opt)
+{
+ if (idx == -QCborValue::Array || idx == -QCborValue::Map) {
+ bool isArray = (idx == -QCborValue::Array);
+ qsizetype len = d ? d->elements.size() : 0;
+ if (isArray)
+ writer.startArray(quint64(len));
+ else
+ writer.startMap(quint64(len) / 2);
+
+ for (idx = 0; idx < len; ++idx)
+ encodeToCbor(writer, d, idx, opt);
+
+ if (isArray)
+ writer.endArray();
+ else
+ writer.endMap();
+ } else if (idx < 0) {
+ if (d->elements.size() != 2) {
+ // invalid state!
+ qWarning("QCborValue: invalid tag state; are you encoding something that was improperly decoded?");
+ return;
+ }
+
+ // write the tag and the tagged element
+ writer.append(QCborTag(d->elements.at(0).value));
+ encodeToCbor(writer, d, 1, opt);
+ } else {
+ // just one element
+ auto e = d->elements.at(idx);
+ const ByteData *b = d->byteData(idx);
+ switch (e.type) {
+ case QCborValue::Integer:
+ return writer.append(qint64(e.value));
+
+ case QCborValue::ByteArray:
+ if (b)
+ return writer.appendByteString(b->byte(), b->len);
+ return writer.appendByteString("", 0);
+
+ case QCborValue::String:
+ if (b) {
+ if (e.flags & Element::StringIsUtf16)
+ return writer.append(b->asStringView());
+ return writer.appendTextString(b->byte(), b->len);
+ }
+ return writer.append(QLatin1String());
+
+ case QCborValue::Array:
+ case QCborValue::Map:
+ case QCborValue::Tag:
+ // recurse
+ return encodeToCbor(writer,
+ e.flags & Element::IsContainer ? e.container : nullptr,
+ -qsizetype(e.type), opt);
+
+ case QCborValue::SimpleType:
+ case QCborValue::False:
+ case QCborValue::True:
+ case QCborValue::Null:
+ case QCborValue::Undefined:
+ break;
+
+ case QCborValue::Double:
+ return writeDoubleToCbor(writer, e.fpvalue(), opt);
+
+ case QCborValue::Invalid:
+ return;
+
+ case QCborValue::DateTime:
+ case QCborValue::Url:
+ case QCborValue::RegularExpression:
+ case QCborValue::Uuid:
+ // recurse as tag
+ return encodeToCbor(writer, e.container, -QCborValue::Tag, opt);
+ }
+
+ // maybe it's a simple type
+ int simpleType = e.type - QCborValue::SimpleType;
+ if (unsigned(simpleType) < 0x100)
+ return writer.append(QCborSimpleType(simpleType));
+
+ // if we got here, we've got an unknown type
+ qWarning("QCborValue: found unknown type 0x%x", e.type);
+ }
+}
+
+static inline double integerOutOfRange(const QCborStreamReader &reader)
+{
+ Q_ASSERT(reader.isInteger());
+ if (reader.isUnsignedInteger()) {
+ quint64 v = reader.toUnsignedInteger();
+ if (qint64(v) < 0)
+ return double(v);
+ } else {
+ quint64 v = quint64(reader.toNegativeInteger());
+ if (qint64(v - 1) < 0)
+ return -double(v);
+ }
+
+ // result is in range
+ return 0;
+}
+
+static Element decodeBasicValueFromCbor(QCborStreamReader &reader)
+{
+ Element e = {};
+
+ switch (reader.type()) {
+ case QCborStreamReader::UnsignedInteger:
+ case QCborStreamReader::NegativeInteger:
+ if (double d = integerOutOfRange(reader)) {
+ e.type = QCborValue::Double;
+ qToUnaligned(d, &e.value);
+ } else {
+ e.type = QCborValue::Integer;
+ e.value = reader.toInteger();
+ }
+ break;
+ case QCborStreamReader::SimpleType:
+ e.type = QCborValue::Type(quint8(reader.toSimpleType()) + 0x100);
+ break;
+ case QCborStreamReader::Float16:
+ e.type = QCborValue::Double;
+ qToUnaligned(double(reader.toFloat16()), &e.value);
+ break;
+ case QCborStreamReader::Float:
+ e.type = QCborValue::Double;
+ qToUnaligned(double(reader.toFloat()), &e.value);
+ break;
+ case QCborStreamReader::Double:
+ e.type = QCborValue::Double;
+ qToUnaligned(reader.toDouble(), &e.value);
+ break;
+
+ default:
+ Q_UNREACHABLE();
+ }
+
+ reader.next();
+ return e;
+}
+
+static inline QCborContainerPrivate *createContainerFromCbor(QCborStreamReader &reader)
+{
+ auto d = new QCborContainerPrivate;
+ d->ref.store(1);
+ d->decodeFromCbor(reader);
+ return d;
+}
+
+static QCborValue taggedValueFromCbor(QCborStreamReader &reader)
+{
+ auto d = new QCborContainerPrivate;
+ d->append(reader.toTag());
+ reader.next();
+
+ if (reader.lastError() == QCborError::NoError) {
+ // decode tagged value
+ d->decodeValueFromCbor(reader);
+ }
+
+ QCborValue::Type type = QCborValue::Tag;
+ if (reader.lastError() == QCborError::NoError) {
+ // post-process to create our extended types
+ qint64 tag = d->elements.at(0).value;
+ auto &e = d->elements[1];
+ const ByteData *b = d->byteData(e);
+
+ auto replaceByteData = [&](const char *buf, qsizetype len) {
+ d->data.clear();
+ d->usedData = 0;
+ e.flags = Element::HasByteData | Element::StringIsAscii;
+ e.value = d->addByteData(buf, len);
+ };
+
+ switch (tag) {
+ case qint64(QCborKnownTags::DateTimeString):
+ case qint64(QCborKnownTags::UnixTime_t): {
+ QDateTime dt;
+ if (tag == qint64(QCborKnownTags::DateTimeString) && b &&
+ e.type == QCborValue::String && (e.flags & Element::StringIsUtf16) == 0) {
+ // The data is supposed to be US-ASCII. If it isn't,
+ // QDateTime::fromString will fail anyway.
+ dt = QDateTime::fromString(b->asLatin1(), Qt::ISODateWithMs);
+ } else if (tag == qint64(QCborKnownTags::UnixTime_t) && e.type == QCborValue::Integer) {
+ dt = QDateTime::fromSecsSinceEpoch(e.value, Qt::UTC);
+ } else if (tag == qint64(QCborKnownTags::UnixTime_t) && e.type == QCborValue::Double) {
+ dt = QDateTime::fromMSecsSinceEpoch(qint64(e.fpvalue() * 1000), Qt::UTC);
+ }
+ if (dt.isValid()) {
+ QByteArray text = dt.toString(Qt::ISODateWithMs).toLatin1();
+ replaceByteData(text, text.size());
+ e.type = QCborValue::String;
+ d->elements[0].value = qint64(QCborKnownTags::DateTimeString);
+ type = QCborValue::DateTime;
+ }
+ break;
+ }
+
+ case qint64(QCborKnownTags::Url):
+ if (e.type == QCborValue::String) {
+ if (b) {
+ // normalize to a short (decoded) form, so as to save space
+ QUrl url(e.flags & Element::StringIsUtf16 ?
+ b->asQStringRaw() :
+ b->toUtf8String());
+ QByteArray encoded = url.toString(QUrl::DecodeReserved).toUtf8();
+ replaceByteData(encoded, encoded.size());
+ }
+ type = QCborValue::Url;
+ }
+ break;
+
+ case quint64(QCborKnownTags::RegularExpression):
+ if (e.type == QCborValue::String) {
+ // no normalization is necessary
+ type = QCborValue::RegularExpression;
+ }
+ break;
+
+ case qint64(QCborKnownTags::Uuid):
+ if (e.type == QCborValue::ByteArray) {
+ // force the size to 16
+ char buf[sizeof(QUuid)] = {};
+ if (b)
+ memcpy(buf, b->byte(), qMin(sizeof(buf), size_t(b->len)));
+ replaceByteData(buf, sizeof(buf));
+
+ type = QCborValue::Uuid;
+ }
+ break;
+ }
+ } else {
+ // decoding error
+ type = QCborValue::Invalid;
+ }
+
+ // note: may return invalid state!
+ return QCborContainerPrivate::makeValue(type, -1, d);
+}
+
+void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
+{
+ auto addByteData_local = [this](QByteArray::size_type len) -> qint64 {
+ // this duplicates a lot of addByteData, but with overflow checking
+ QByteArray::size_type newSize;
+ QByteArray::size_type increment = sizeof(QtCbor::ByteData);
+ QByteArray::size_type alignment = alignof(QtCbor::ByteData);
+ QByteArray::size_type offset = data.size();
+
+ // calculate the increment we want
+ if (add_overflow(increment, len, &increment))
+ return -1;
+
+ // align offset
+ if (add_overflow(offset, alignment - 1, &offset))
+ return -1;
+ offset &= ~(alignment - 1);
+
+ // and calculate the final size
+ if (add_overflow(offset, increment, &newSize))
+ return -1;
+
+ // since usedData <= data.size(), this can't overflow
+ usedData += increment;
+ data.resize(newSize);
+ return offset;
+ };
+ auto dataPtr = [this]() {
+ // Null happens when we're reading zero bytes.
+ Q_ASSERT(data.isNull() || data.isDetached());
+ return const_cast<char *>(data.constData());
+ };
+
+ Element e = {};
+ e.type = (reader.isByteArray() ? QCborValue::ByteArray : QCborValue::String);
+ if (reader.lastError() != QCborError::NoError)
+ return;
+
+ qsizetype rawlen = reader.currentStringChunkSize();
+ QByteArray::size_type len = rawlen;
+ if (rawlen < 0)
+ return; // error
+ if (len != rawlen) {
+ // truncation
+ qt_cbor_stream_set_error(reader.d.data(), { QCborError::DataTooLarge });
+ return;
+ }
+
+ // allocate space, but only if there will be data
+ if (len != 0 || !reader.isLengthKnown()) {
+ e.flags = Element::HasByteData;
+ e.value = addByteData_local(len);
+ if (e.value < 0) {
+ // overflow
+ qt_cbor_stream_set_error(reader.d.data(), { QCborError::DataTooLarge });
+ return;
+ }
+ }
+
+ // read chunks
+ bool isAscii = (e.type == QCborValue::String);
+ auto r = reader.readStringChunk(dataPtr() + e.value + sizeof(ByteData), len);
+ while (r.status == QCborStreamReader::Ok) {
+ if (e.type == QCborValue::String && len) {
+ // verify UTF-8 string validity
+ auto utf8result = QUtf8::isValidUtf8(dataPtr() + data.size() - len, len);
+ if (!utf8result.isValidUtf8) {
+ r.status = QCborStreamReader::Error;
+ qt_cbor_stream_set_error(reader.d.data(), { QCborError::InvalidUtf8String });
+ break;
+ }
+ isAscii = isAscii && utf8result.isValidAscii;
+ }
+
+ // allocate space for the next chunk
+ rawlen = reader.currentStringChunkSize();
+ len = rawlen;
+ if (len == rawlen) {
+ auto oldSize = data.size();
+ auto newSize = oldSize;
+ if (!add_overflow(newSize, len, &newSize)) {
+ if (newSize != oldSize)
+ data.resize(newSize);
+
+ // read the chunk
+ r = reader.readStringChunk(dataPtr() + oldSize, len);
+ continue;
+ }
+ }
+
+ // error
+ r.status = QCborStreamReader::Error;
+ qt_cbor_stream_set_error(reader.d.data(), { QCborError::DataTooLarge });
+ }
+
+ if (r.status == QCborStreamReader::Error) {
+ // There can only be errors if there was data to be read.
+ Q_ASSERT(e.flags & Element::HasByteData);
+ data.truncate(e.value);
+ return;
+ }
+
+ // update size
+ if (e.flags & Element::HasByteData) {
+ auto b = new (dataPtr() + e.value) ByteData;
+ b->len = data.size() - e.value - int(sizeof(*b));
+ usedData += b->len;
+
+ if (isAscii) {
+ // set the flag if it is US-ASCII only (as it often is)
+ Q_ASSERT(e.type == QCborValue::String);
+ e.flags |= Element::StringIsAscii;
+ }
+ }
+
+ elements.append(e);
+}
+
+void QCborContainerPrivate::decodeValueFromCbor(QCborStreamReader &reader)
+{
+ switch (reader.type()) {
+ case QCborStreamReader::UnsignedInteger:
+ case QCborStreamReader::NegativeInteger:
+ case QCborStreamReader::SimpleType:
+ case QCborStreamReader::Float16:
+ case QCborStreamReader::Float:
+ case QCborStreamReader::Double:
+ elements.append(decodeBasicValueFromCbor(reader));
+ break;
+
+ case QCborStreamReader::ByteArray:
+ case QCborStreamReader::String:
+ decodeStringFromCbor(reader);
+ break;
+
+ case QCborStreamReader::Array:
+ case QCborStreamReader::Map:
+ case QCborStreamReader::Tag:
+ return append(QCborValue::fromCbor(reader));
+
+ case QCborStreamReader::Invalid:
+ return; // probably a decode error
+ }
+}
+
+void QCborContainerPrivate::decodeFromCbor(QCborStreamReader &reader)
+{
+ int mapShift = reader.isMap() ? 1 : 0;
+ if (reader.isLengthKnown()) {
+ quint64 len = reader.length();
+
+ // Clamp allocation to 1M elements (avoids crashing due to corrupt
+ // stream or loss of precision when converting from quint64 to
+ // QVector::size_type).
+ len = qMin(len, quint64(1024 * 1024 - 1));
+ elements.reserve(qsizetype(len) << mapShift);
+ }
+
+ reader.enterContainer();
+ if (reader.lastError() != QCborError::NoError)
+ return;
+
+ while (reader.hasNext() && reader.lastError() == QCborError::NoError)
+ decodeValueFromCbor(reader);
+
+ if (reader.lastError() == QCborError::NoError)
+ reader.leaveContainer();
+}
+
+/*!
+ Creates a QCborValue with byte array value \a ba. The value can later be
+ retrieved using toByteArray().
+
+ \sa toByteArray(), isByteArray(), isString()
+ */
+QCborValue::QCborValue(const QByteArray &ba)
+ : n(0), container(new QCborContainerPrivate), t(ByteArray)
+{
+ container->appendByteData(ba.constData(), ba.size(), t);
+ container->ref.store(1);
+}
+
+/*!
+ Creates a QCborValue with string value \a s. The value can later be
+ retrieved using toString().
+
+ \sa toString(), isString(), isByteArray()
+ */
+QCborValue::QCborValue(const QString &s)
+ : n(0), container(new QCborContainerPrivate), t(String)
+{
+ container->append(s);
+ container->ref.store(1);
+}
+
+/*!
+ \overload
+
+ Creates a QCborValue with string value \a s. The value can later be
+ retrieved using toString().
+
+ \sa toString(), isString(), isByteArray()
+ */
+QCborValue::QCborValue(QLatin1String s)
+ : n(0), container(new QCborContainerPrivate), t(String)
+{
+ container->append(s);
+ container->ref.store(1);
+}
+
+/*!
+ \fn QCborValue::QCborValue(const QCborArray &a)
+ \fn QCborValue::QCborValue(QCborArray &&a)
+
+ Creates a QCborValue with the array \a a. The array can later be retrieved
+ using toArray().
+
+ \sa toArray(), isArray(), isMap()
+ */
+QCborValue::QCborValue(const QCborArray &a)
+ : n(-1), container(a.d.data()), t(Array)
+{
+ if (container)
+ container->ref.ref();
+}
+
+/*!
+ \fn QCborValue::QCborValue(const QCborMap &m)
+ \fn QCborValue::QCborValue(QCborMap &&m)
+
+ Creates a QCborValue with the map \a m. The map can later be retrieved
+ using toMap().
+
+ \sa toMap(), isMap(), isArray()
+ */
+QCborValue::QCborValue(const QCborMap &m)
+ : n(-1), container(m.d.data()), t(Map)
+{
+ if (container)
+ container->ref.ref();
+}
+
+/*!
+ \fn QCborValue::QCborValue(QCborTag t, const QCborValue &tv)
+ \fn QCborValue::QCborValue(QCborKnownTags t, const QCborValue &tv)
+
+ Creates a QCborValue for the extended type represented by the tag value \a
+ t, tagging value \a tv. The tag can later be retrieved using tag() and
+ the tagged value using taggedValue().
+
+ \sa isTag(), tag(), taggedValue(), QCborKnownTags
+ */
+QCborValue::QCborValue(QCborTag t, const QCborValue &tv)
+ : n(-1), container(new QCborContainerPrivate), t(Tag)
+{
+ container->ref.store(1);
+ container->append(t);
+ container->append(tv);
+}
+
+/*!
+ Copies the contents of \a other into this object.
+ */
+QCborValue::QCborValue(const QCborValue &other)
+ : n(other.n), container(other.container), t(other.t)
+{
+ if (container)
+ container->ref.ref();
+}
+
+/*!
+ Creates a QCborValue object of the date/time extended type and containing
+ the value represented by \a dt. The value can later be retrieved using
+ toDateTime().
+
+ The CBOR date/time types are extension types using tags: either a string
+ (in ISO date format) tagged as a \l{QCborKnownTags}{DateTime} or a number
+ (of seconds since the start of 1970, UTC) tagged as a
+ \l{QCborKnownTags}{UnixTime_t}. When parsing CBOR streams, QCborValue will
+ convert \l{QCborKnownTags}{UnixTime_t} to the string-based type.
+
+ \sa toDateTime(), isDateTime(), taggedValue()
+ */
+QCborValue::QCborValue(const QDateTime &dt)
+ : QCborValue(QCborKnownTags::DateTimeString, dt.toString(Qt::ISODateWithMs).toLatin1())
+{
+ // change types
+ t = DateTime;
+ container->elements[1].type = String;
+}
+
+/*!
+ Creates a QCborValue object of the URL extended type and containing the
+ value represented by \a url. The value can later be retrieved using toUrl().
+
+ The CBOR URL type is an extended type represented by a string tagged as an
+ \l{QCborKnownTags}{Url}.
+
+ \sa toUrl(), isUrl(), taggedValue()
+ */
+QCborValue::QCborValue(const QUrl &url)
+ : QCborValue(QCborKnownTags::Url, url.toString(QUrl::DecodeReserved).toUtf8())
+{
+ // change types
+ t = Url;
+ container->elements[1].type = String;
+}
+
+/*!
+ Creates a QCborValue object of the regular expression pattern extended type
+ and containing the value represented by \a rx. The value can later be retrieved
+ using toRegularExpression().
+
+ The CBOR regular expression type is an extended type represented by a
+ string tagged as an \l{QCborKnownTags}{RegularExpression}. Note that CBOR
+ regular expressions only store the patterns, so any flags that the
+ QRegularExpression object may carry will be lost.
+
+ \sa toRegularExpression(), isRegularExpression(), taggedValue()
+ */
+QCborValue::QCborValue(const QRegularExpression &rx)
+ : QCborValue(QCborKnownTags::RegularExpression, rx.pattern())
+{
+ // change type
+ t = RegularExpression;
+}
+
+/*!
+ Creates a QCborValue object of the UUID extended type and containing the
+ value represented by \a uuid. The value can later be retrieved using
+ toUuid().
+
+ The CBOR UUID type is an extended type represented by a byte array tagged
+ as an \l{QCborKnownTags}{Uuid}.
+
+ \sa toUuid(), isUuid(), taggedValue()
+ */
+QCborValue::QCborValue(const QUuid &uuid)
+ : QCborValue(QCborKnownTags::Uuid, uuid.toRfc4122())
+{
+ // change our type
+ t = Uuid;
+}
+
+// destructor
+void QCborValue::dispose()
+{
+ container->deref();
+}
+
+/*!
+ Replaces the contents of this QCborObject with a copy of \a other.
+ */
+QCborValue &QCborValue::operator=(const QCborValue &other)
+{
+ if (other.container)
+ other.container->ref.ref();
+ if (container)
+ container->deref();
+
+ n = other.n;
+ container = other.container;
+ t = other.t;
+ return *this;
+}
+
+/*!
+ Returns the tag of this extended QCborValue object, if it is of the tag
+ type, \a defaultValue otherwise.
+
+ CBOR represents extended types by associating a number (the tag) with a
+ stored representation. This function returns that number. To retrieve the
+ representation, use taggedValue().
+
+ \sa isTag(), taggedValue(), isDateTime(), isUrl(), isRegularExpression(), isUuid()
+ */
+QCborTag QCborValue::tag(QCborTag defaultValue) const
+{
+ return isTag() && container && container->elements.size() == 2 ?
+ QCborTag(container->elements.at(0).value) : defaultValue;
+}
+
+/*!
+ Returns the tagged value of this extended QCborValue object, if it is of
+ the tag type, \a defaultValue otherwise.
+
+ CBOR represents extended types by associating a number (the tag) with a
+ stored representation. This function returns that representation. To
+ retrieve the tag, use tag().
+
+ \sa isTag(), tag(), isDateTime(), isUrl(), isRegularExpression(), isUuid()
+ */
+QCborValue QCborValue::taggedValue(const QCborValue &defaultValue) const
+{
+ return isTag() && container && container->elements.size() == 2 ?
+ container->valueAt(1) : defaultValue;
+}
+
+/*!
+ Returns the byte array value stored in this QCborValue, if it is of the byte
+ array type. Otherwise, it returns \a defaultValue.
+
+ Note that this function performs no conversion from other types to
+ QByteArray.
+
+ \sa isByteArray(), isString(), toString()
+ */
+QByteArray QCborValue::toByteArray(const QByteArray &defaultValue) const
+{
+ if (!container || !isByteArray())
+ return defaultValue;
+
+ Q_ASSERT(n >= 0);
+ return container->byteArrayAt(n);
+}
+
+/*!
+ Returns the string value stored in this QCborValue, if it is of the string
+ type. Otherwise, it returns \a defaultValue.
+
+ Note that this function performs no conversion from other types to
+ QString.
+
+ \sa isString(), isByteArray(), toByteArray()
+ */
+QString QCborValue::toString(const QString &defaultValue) const
+{
+ if (!container || !isString())
+ return defaultValue;
+
+ Q_ASSERT(n >= 0);
+ return container->stringAt(n);
+}
+
+/*!
+ Returns the date/time value stored in this QCborValue, if it is of the
+ date/time extended type. Otherwise, it returns \a defaultValue.
+
+ Note that this function performs no conversion from other types to
+ QDateTime.
+
+ \sa isDateTime(), isTag(), taggedValue()
+ */
+QDateTime QCborValue::toDateTime(const QDateTime &defaultValue) const
+{
+ if (!container || !isDateTime() || container->elements.size() != 2)
+ return defaultValue;
+
+ Q_ASSERT(n == -1);
+ const ByteData *byteData = container->byteData(1);
+ if (!byteData)
+ return defaultValue; // date/times are never empty, so this must be invalid
+
+ // Our data must be US-ASCII.
+ Q_ASSERT((container->elements.at(1).flags & Element::StringIsUtf16) == 0);
+ return QDateTime::fromString(byteData->asLatin1(), Qt::ISODateWithMs);
+}
+
+/*!
+ Returns the URL value stored in this QCborValue, if it is of the URL
+ extended type. Otherwise, it returns \a defaultValue.
+
+ Note that this function performs no conversion from other types to QUrl.
+
+ \sa isUrl(), isTag(), taggedValue()
+ */
+QUrl QCborValue::toUrl(const QUrl &defaultValue) const
+{
+ if (!container || !isUrl() || container->elements.size() != 2)
+ return defaultValue;
+
+ Q_ASSERT(n == -1);
+ const ByteData *byteData = container->byteData(1);
+ if (!byteData)
+ return QUrl(); // valid, empty URL
+
+ return QUrl::fromEncoded(byteData->asByteArrayView());
+}
+
+/*!
+ Returns the regular expression value stored in this QCborValue, if it is of
+ the regular expression pattern extended type. Otherwise, it returns \a
+ defaultValue.
+
+ Note that this function performs no conversion from other types to
+ QRegularExpression.
+
+ \sa isRegularExpression(), isTag(), taggedValue()
+ */
+QRegularExpression QCborValue::toRegularExpression(const QRegularExpression &defaultValue) const
+{
+ if (!container || !isRegularExpression() || container->elements.size() != 2)
+ return defaultValue;
+
+ Q_ASSERT(n == -1);
+ return QRegularExpression(container->stringAt(1));
+}
+
+/*!
+ Returns the UUID value stored in this QCborValue, if it is of the UUID
+ extended type. Otherwise, it returns \a defaultValue.
+
+ Note that this function performs no conversion from other types to QUuid.
+
+ \sa isUuid(), isTag(), taggedValue()
+ */
+QUuid QCborValue::toUuid(const QUuid &defaultValue) const
+{
+ if (!container || !isUuid() || container->elements.size() != 2)
+ return defaultValue;
+
+ Q_ASSERT(n == -1);
+ const ByteData *byteData = container->byteData(1);
+ if (!byteData)
+ return defaultValue; // UUIDs must always be 16 bytes, so this must be invalid
+
+ return QUuid::fromRfc4122(byteData->asByteArrayView());
+}
+
+QCborArray QCborValue::toArray() const
+{
+ return toArray(QCborArray());
+}
+
+/*!
+ Returns the array value stored in this QCborValue, if it is of the array
+ type. Otherwise, it returns \a defaultValue.
+
+ Note that this function performs no conversion from other types to
+ QCborArray.
+
+ \sa isArray(), isByteArray(), isMap(), isContainer(), toMap()
+ */
+QCborArray QCborValue::toArray(const QCborArray &defaultValue) const
+{
+ if (!isArray())
+ return defaultValue;
+ QCborContainerPrivate *dd = nullptr;
+ Q_ASSERT(n == -1 || container == nullptr);
+ if (n < 0)
+ dd = container;
+ return dd ? QCborArray(*dd) : defaultValue;
+}
+
+QCborMap QCborValue::toMap() const
+{
+ return toMap(QCborMap());
+}
+
+/*!
+ Returns the map value stored in this QCborValue, if it is of the map type.
+ Otherwise, it returns \a defaultValue.
+
+ Note that this function performs no conversion from other types to
+ QCborMap.
+
+ \sa isMap(), isArray(), isContainer(), toArray()
+ */
+QCborMap QCborValue::toMap(const QCborMap &defaultValue) const
+{
+ if (!isMap())
+ return defaultValue;
+ QCborContainerPrivate *dd = nullptr;
+ Q_ASSERT(n == -1 || container == nullptr);
+ if (n < 0)
+ dd = container;
+ return dd ? QCborMap(*dd) : defaultValue;
+}
+
+/*!
+ If this QCborValue is a QCborMap, searches elements for the value whose key
+ matches \a key. If there's no key matching \a key in the map or if this
+ QCborValue object is not a map, returns the undefined value.
+
+ This function is equivalent to:
+
+ \snippet code/src_corelib_serialization_qcborvalue.cpp 4
+
+ \sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
+ QCborMap::find()
+ */
+const QCborValue QCborValue::operator[](const QString &key) const
+{
+ if (isMap())
+ return toMap().value(key);
+ return QCborValue();
+}
+
+/*!
+ \overload
+
+ If this QCborValue is a QCborMap, searches elements for the value whose key
+ matches \a key. If there's no key matching \a key in the map or if this
+ QCborValue object is not a map, returns the undefined value.
+
+ This function is equivalent to:
+
+ \snippet code/src_corelib_serialization_qcborvalue.cpp 5
+
+ \sa operator[](qint64), QCborMap::operator[], QCborMap::value(),
+ QCborMap::find()
+ */
+const QCborValue QCborValue::operator[](QLatin1String key) const
+{
+ if (isMap())
+ return toMap().value(key);
+ return QCborValue();
+}
+
+/*!
+ If this QCborValue is a QCborMap, searches elements for the value whose key
+ matches \a key. If this is an array, returns the element whose index is \a
+ key. If there's no matching value in the array or map, or if this
+ QCborValue object is not an array or map, returns the undefined value.
+
+ \sa operator[], QCborMap::operator[], QCborMap::value(),
+ QCborMap::find(), QCborArray::operator[], QCborArray::at()
+ */
+
+const QCborValue QCborValue::operator[](qint64 key) const
+{
+ if (isMap())
+ return toMap().value(key);
+ if (isArray())
+ return toArray().at(key);
+ return QCborValue();
+}
+
+/*!
+ Decodes one item from the CBOR stream found in \a reader and returns the
+ equivalent representation. This function is recursive: if the item is a map
+ or array, it will decode all items found in that map or array, until the
+ outermost object is finished.
+
+ This function need not be used on the root element of a \l
+ QCborStreamReader. For example, the following code illustrates how to skip
+ the CBOR signature tag from the beginning of a file:
+
+ \snippet code/src_corelib_serialization_qcborvalue.cpp 6
+
+ The returned value may be partially complete and indistinguishable from a
+ valid QCborValue even if the decoding failed. To determine if there was an
+ error, check if \l{QCborStreamReader::lastError()}{reader.lastError()} is
+ indicating an error condition. This function stops decoding immediately
+ after the first error.
+
+ \sa toCbor(), toDiagnosticNotation(), toVariant(), toJsonValue()
+ */
+QCborValue QCborValue::fromCbor(QCborStreamReader &reader)
+{
+ QCborValue result;
+ auto t = reader.type();
+ if (reader.lastError() != QCborError::NoError)
+ t = QCborStreamReader::Invalid;
+
+ switch (t) {
+ // basic types, no container needed:
+ case QCborStreamReader::UnsignedInteger:
+ case QCborStreamReader::NegativeInteger:
+ case QCborStreamReader::SimpleType:
+ case QCborStreamReader::Float16:
+ case QCborStreamReader::Float:
+ case QCborStreamReader::Double: {
+ Element e = decodeBasicValueFromCbor(reader);
+ result.n = e.value;
+ result.t = e.type;
+ break;
+ }
+
+ case QCborStreamReader::Invalid:
+ result.t = QCborValue::Invalid;
+ break; // probably a decode error
+
+ // strings
+ case QCborStreamReader::ByteArray:
+ case QCborStreamReader::String:
+ result.n = 0;
+ result.t = reader.isString() ? String : ByteArray;
+ result.container = new QCborContainerPrivate;
+ result.container->ref.ref();
+ result.container->decodeStringFromCbor(reader);
+ break;
+
+ // containers
+ case QCborStreamReader::Array:
+ case QCborStreamReader::Map:
+ result.n = -1;
+ result.t = reader.isArray() ? Array : Map;
+ result.container = createContainerFromCbor(reader);
+ break;
+
+ // tag
+ case QCborStreamReader::Tag:
+ result = taggedValueFromCbor(reader);
+ break;
+ }
+
+ return result;
+}
+
+/*!
+ \overload
+
+ Decodes one item from the CBOR stream found in the byte array \a ba and
+ returns the equivalent representation. This function is recursive: if the
+ item is a map or array, it will decode all items found in that map or
+ array, until the outermost object is finished.
+
+ This function stores the error state, if any, in the object pointed to by
+ \a error, along with the offset of where the error occurred. If no error
+ happened, it stores \l{QCborError}{NoError} in the error state and the
+ number of bytes that it consumed (that is, it stores the offset for the
+ first unused byte). Using that information makes it possible to parse
+ further data that may exist in the same byte array.
+
+ The returned value may be partially complete and indistinguishable from a
+ valid QCborValue even if the decoding failed. To determine if there was an
+ error, check if there was an error stored in \a error. This function stops
+ decoding immediately after the first error.
+
+ \sa toCbor(), toDiagnosticNotation(), toVariant(), toJsonValue()
+ */
+QCborValue QCborValue::fromCbor(const QByteArray &ba, QCborParserError *error)
+{
+ QCborStreamReader reader(ba);
+ QCborValue result = fromCbor(reader);
+ if (error) {
+ error->error = reader.lastError();
+ error->offset = reader.currentOffset();
+ }
+ return result;
+}
+
+/*!
+ \fn QCborValue QCborValue::fromCbor(const char *data, qsizetype len, QCborParserError *error)
+ \fn QCborValue QCborValue::fromCbor(const quint8 *data, qsizetype len, QCborParserError *error)
+ \overload
+
+ Converts \a len bytes of \a data to a QByteArray and then calls the
+ overload of this function that accepts a QByteArray, also passing \a error,
+ if provided.
+*/
+
+/*!
+ Encodes this QCborValue object to its CBOR representation, using the
+ options specified in \a opt, and return the byte array containing that
+ representation.
+
+ This function will not fail, except if this QCborValue or any of the
+ contained items, if this is a map or array, are invalid. Invalid types are
+ not produced normally by the API, but can result from decoding errors.
+
+ By default, this function performs no transformation on the values in the
+ QCborValue, writing all floating point directly as double-precision (\c
+ double) types. If the \l{EncodingOption}{UseFloat} option is specified, it
+ will use single precision (\c float) for any floating point value for which
+ there's no loss of precision in using that representation. That includes
+ infinities and NaN values.
+
+ Similarly, if \l{EncodingOption}{UseFloat16} is specified, this function
+ will try to use half-precision (\c qfloat16) floating point if the
+ conversion to that results in no loss of precision. This is always true for
+ infinities and NaN.
+
+ If \l{EncodingOption}{UseIntegers} is specified, it will use integers for
+ any floating point value that contains an actual integer.
+
+ \sa fromCbor(), fromVariant(), fromJsonValue()
+ */
+QByteArray QCborValue::toCbor(EncodingOptions opt)
+{
+ QByteArray result;
+ QCborStreamWriter writer(&result);
+ toCbor(writer, opt);
+ return result;
+}
+
+/*!
+ \overload
+
+ Encodes this QCborValue object to its CBOR representation, using the
+ options specified in \a opt, to the writer specified by \a writer. The same
+ writer can be used by multiple QCborValues, for example, in order to encode
+ different elements in a larger array.
+
+ This function will not fail, except if this QCborValue or any of the
+ contained items, if this is a map or array, are invalid. Invalid types are
+ not produced normally by the API, but can result from decoding errors.
+
+ By default, this function performs no transformation on the values in the
+ QCborValue, writing all floating point directly as double-precision
+ (binary64) types. If the \l{EncodingOption}{UseFloat} option is
+ specified, it will use single precision (binary32) for any floating point
+ value for which there's no loss of precision in using that representation.
+ That includes infinities and NaN values.
+
+ Similarly, if \l{EncodingOption}{UseFloat16} is specified, this function
+ will try to use half-precision (binary16) floating point if the conversion
+ to that results in no loss of precision. This is always true for infinities
+ and NaN.
+
+ If \l{EncodingOption}{UseIntegers} is specified, it will use integers
+ for any floating point value that contains an actual integer.
+
+ \sa fromCbor(), fromVariant(), fromJsonValue()
+ */
+Q_NEVER_INLINE void QCborValue::toCbor(QCborStreamWriter &writer, EncodingOptions opt)
+{
+ if (isContainer() || isTag())
+ return encodeToCbor(writer, container, -type(), opt);
+ if (container)
+ return encodeToCbor(writer, container, n, opt);
+
+ // very simple types
+ if (isSimpleType())
+ return writer.append(toSimpleType());
+
+ switch (type()) {
+ case Integer:
+ return writer.append(n);
+
+ case Double:
+ return writeDoubleToCbor(writer, fp_helper(), opt);
+
+ case Invalid:
+ return;
+
+ case SimpleType:
+ case False:
+ case True:
+ case Null:
+ case Undefined:
+ // handled by "if (isSimpleType())"
+ Q_UNREACHABLE();
+ break;
+
+ case ByteArray:
+ // Byte array with no container is empty
+ return writer.appendByteString("", 0);
+
+ case String:
+ // String with no container is empty
+ return writer.appendTextString("", 0);
+
+ case Array:
+ case Map:
+ case Tag:
+ // handled by "if (isContainer() || isTag())"
+ Q_UNREACHABLE();
+ break;
+
+ case DateTime:
+ case Url:
+ case RegularExpression:
+ case Uuid:
+ // not possible
+ Q_UNREACHABLE();
+ break;
+ }
+}
+
+void QCborValueRef::toCbor(QCborStreamWriter &writer, QCborValue::EncodingOptions opt)
+{
+ concrete().toCbor(writer, opt);
+}
+
+void QCborValueRef::assign(QCborValueRef that, const QCborValue &other)
+{
+ that.d->replaceAt(that.i, other);
+}
+
+void QCborValueRef::assign(QCborValueRef that, QCborValue &&other)
+{
+ that.d->replaceAt(that.i, other, QCborContainerPrivate::MoveContainer);
+}
+
+void QCborValueRef::assign(QCborValueRef that, const QCborValueRef other)
+{
+ // ### optimize?
+ assign(that, other.concrete());
+}
+
+QCborValue QCborValueRef::concrete(QCborValueRef self) noexcept
+{
+ return self.d->valueAt(self.i);
+}
+
+QCborValue::Type QCborValueRef::concreteType(QCborValueRef self) noexcept
+{
+ return self.d->elements.at(self.i).type;
+}
+
+inline QCborArray::QCborArray(QCborContainerPrivate &dd) noexcept
+ : d(&dd)
+{
+}
+
+inline QCborMap::QCborMap(QCborContainerPrivate &dd) noexcept
+ : d(&dd)
+{
+}
+
+uint qHash(const QCborValue &value, uint seed)
+{
+ switch (value.type()) {
+ case QCborValue::Integer:
+ return qHash(value.toInteger(), seed);
+ case QCborValue::ByteArray:
+ return qHash(value.toByteArray(), seed);
+ case QCborValue::String:
+ return qHash(value.toString(), seed);
+ case QCborValue::Array:
+ return qHash(value.toArray(), seed);
+ case QCborValue::Map:
+ return qHash(value.toMap(), seed);
+ case QCborValue::Tag: {
+ QtPrivate::QHashCombine hash;
+ seed = hash(seed, value.tag());
+ seed = hash(seed, value.taggedValue());
+ return seed;
+ }
+ case QCborValue::SimpleType:
+ break;
+ case QCborValue::False:
+ return qHash(false, seed);
+ case QCborValue::True:
+ return qHash(true, seed);
+ case QCborValue::Null:
+ return qHash(nullptr, seed);
+ case QCborValue::Undefined:
+ return seed;
+ case QCborValue::Double:
+ return qHash(value.toDouble(), seed);
+ case QCborValue::DateTime:
+ return qHash(value.toDateTime(), seed);
+ case QCborValue::Url:
+ return qHash(value.toUrl(), seed);
+ case QCborValue::RegularExpression:
+ return qHash(value.toRegularExpression(), seed);
+ case QCborValue::Uuid:
+ return qHash(value.toUuid(), seed);
+ case QCborValue::Invalid:
+ return seed;
+ }
+
+ Q_ASSERT(value.isSimpleType());
+ return qHash(value.toSimpleType(), seed);
+}
+
+#if !defined(QT_NO_DEBUG_STREAM)
+static QDebug debugContents(QDebug &dbg, const QCborValue &v)
+{
+ switch (v.type()) {
+ case QCborValue::Integer:
+ return dbg << v.toInteger();
+ case QCborValue::ByteArray:
+ return dbg << "QByteArray(" << v.toByteArray() << ')';
+ case QCborValue::String:
+ return dbg << v.toString();
+ case QCborValue::Array:
+ return dbg << v.toArray();
+ case QCborValue::Map:
+ return dbg << v.toMap();
+ case QCborValue::Tag:
+ dbg << v.tag() << ", ";
+ return debugContents(dbg, v.taggedValue());
+ case QCborValue::SimpleType:
+ break;
+ case QCborValue::True:
+ return dbg << true;
+ case QCborValue::False:
+ return dbg << false;
+ case QCborValue::Null:
+ return dbg << "nullptr";
+ case QCborValue::Undefined:
+ return dbg;
+ case QCborValue::Double: {
+ qint64 i = qint64(v.toDouble());
+ if (i == v.toDouble())
+ return dbg << i << ".0";
+ else
+ return dbg << v.toDouble();
+ }
+ case QCborValue::DateTime:
+ return dbg << v.toDateTime();
+ case QCborValue::Url:
+ return dbg << v.toUrl();
+ case QCborValue::RegularExpression:
+ return dbg << v.toRegularExpression();
+ case QCborValue::Uuid:
+ return dbg << v.toUuid();
+ case QCborValue::Invalid:
+ return dbg << "<invalid>";
+ }
+ if (v.isSimpleType())
+ return dbg << v.toSimpleType();
+ return dbg << "<unknown type " << hex << int(v.type()) << dec << '>';
+}
+QDebug operator<<(QDebug dbg, const QCborValue &v)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QCborValue(";
+ return debugContents(dbg, v) << ')';
+}
+#endif
+
+QT_END_NAMESPACE
+
+#include "qcborarray.cpp"
+#include "qcbormap.cpp"
+
+#include "moc_qcborvalue.cpp"
diff --git a/src/corelib/serialization/qcborvalue.h b/src/corelib/serialization/qcborvalue.h
new file mode 100644
index 0000000000..6d9ed0810a
--- /dev/null
+++ b/src/corelib/serialization/qcborvalue.h
@@ -0,0 +1,467 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://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 QCBORVALUE_H
+#define QCBORVALUE_H
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qcborcommon.h>
+#include <QtCore/qregularexpression.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qstringview.h>
+#include <QtCore/qurl.h>
+#include <QtCore/quuid.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qvector.h>
+
+// See qcborcommon.h for why we check
+#if defined(QT_X11_DEFINES_FOUND)
+# undef True
+# undef False
+#endif
+
+#if 0 && QT_HAS_INCLUDE(<compare>)
+# include <compare>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QCborArray;
+class QCborMap;
+class QCborStreamReader;
+class QCborStreamWriter;
+
+struct QCborParserError
+{
+ qint64 offset = 0;
+ QCborError error = {};
+
+ QString errorString() const { return error.toString(); }
+};
+
+class QCborContainerPrivate;
+class Q_CORE_EXPORT QCborValue
+{
+ Q_GADGET
+public:
+ enum EncodingOption {
+ SortKeysInMaps = 0x01,
+ UseFloat = 0x02,
+ UseFloat16 = UseFloat | 0x04,
+ UseIntegers = 0x08,
+
+ NoTransformation = 0
+ };
+ Q_DECLARE_FLAGS(EncodingOptions, EncodingOption)
+
+ enum DiagnosticNotationOption {
+ Compact = 0x00,
+ LineWrapped = 0x01,
+ ExtendedFormat = 0x02
+ };
+ Q_DECLARE_FLAGS(DiagnosticNotationOptions, DiagnosticNotationOption)
+
+ // different from QCborStreamReader::Type because we have more types
+ enum Type : int {
+ Integer = 0x00,
+ ByteArray = 0x40,
+ String = 0x60,
+ Array = 0x80,
+ Map = 0xa0,
+ Tag = 0xc0,
+
+ // range 0x100 - 0x1ff for Simple Types
+ SimpleType = 0x100,
+ False = SimpleType + int(QCborSimpleType::False),
+ True = SimpleType + int(QCborSimpleType::True),
+ Null = SimpleType + int(QCborSimpleType::Null),
+ Undefined = SimpleType + int(QCborSimpleType::Undefined),
+
+ Double = 0x202,
+
+ // extended (tagged) types
+ DateTime = 0x10000,
+ Url = 0x10020,
+ RegularExpression = 0x10023,
+ Uuid = 0x10025,
+
+ Invalid = -1
+ };
+ Q_ENUM(Type)
+
+ QCborValue() {}
+ QCborValue(Type t_) : t(t_) {}
+ QCborValue(std::nullptr_t) : t(Null) {}
+ QCborValue(bool b_) : t(b_ ? True : False) {}
+#ifndef Q_QDOC
+ QCborValue(int i) : QCborValue(qint64(i)) {}
+ QCborValue(unsigned u) : QCborValue(qint64(u)) {}
+#endif
+ QCborValue(qint64 i) : n(i), t(Integer) {}
+ QCborValue(double v) : t(Double) { memcpy(&n, &v, sizeof(n)); }
+ QCborValue(QCborSimpleType st) : t(type_helper(st)) {}
+
+ QCborValue(const QByteArray &ba);
+ QCborValue(const QString &s);
+ QCborValue(QLatin1String s);
+#ifndef QT_NO_CAST_FROM_ASCII
+ QT_ASCII_CAST_WARN QCborValue(const char *s) : QCborValue(QString::fromUtf8(s)) {}
+#endif
+ QCborValue(const QCborArray &a);
+ QCborValue(QCborArray &&a);
+ QCborValue(const QCborMap &m);
+ QCborValue(QCborMap &&m);
+ QCborValue(QCborTag tag, const QCborValue &taggedValue = QCborValue());
+ QCborValue(QCborKnownTags t_, const QCborValue &tv = QCborValue())
+ : QCborValue(QCborTag(t_), tv)
+ {}
+
+ explicit QCborValue(const QDateTime &dt);
+ explicit QCborValue(const QUrl &url);
+ explicit QCborValue(const QRegularExpression &rx);
+ explicit QCborValue(const QUuid &uuid);
+
+ ~QCborValue() { if (container) dispose(); }
+
+ // make sure const char* doesn't go call the bool constructor
+ QCborValue(const void *) = delete;
+
+ QCborValue(const QCborValue &other);
+ QCborValue(QCborValue &&other) noexcept
+ : n(other.n), container(other.container), t(other.t)
+ {
+ other.t = Undefined;
+ other.container = nullptr;
+ }
+ QCborValue &operator=(const QCborValue &other);
+ QCborValue &operator=(QCborValue &&other) noexcept
+ {
+ QCborValue tmp;
+ qSwap(*this, tmp);
+ qSwap(other, *this);
+ return *this;
+ }
+
+ void swap(QCborValue &other) noexcept
+ {
+ qSwap(n, other.n);
+ qSwap(container, other.container);
+ qSwap(t, other.t);
+ }
+
+ Type type() const { return t; }
+ bool isInteger() const { return type() == Integer; }
+ bool isByteArray() const { return type() == ByteArray; }
+ bool isString() const { return type() == String; }
+ bool isArray() const { return type() == Array; }
+ bool isMap() const { return type() == Map; }
+ bool isTag() const { return isTag_helper(type()); }
+ bool isFalse() const { return type() == False; }
+ bool isTrue() const { return type() == True; }
+ bool isBool() const { return isFalse() || isTrue(); }
+ bool isNull() const { return type() == Null; }
+ bool isUndefined() const { return type() == Undefined; }
+ bool isDouble() const { return type() == Double; }
+ bool isDateTime() const { return type() == DateTime; }
+ bool isUrl() const { return type() == Url; }
+ bool isRegularExpression() const { return type() == RegularExpression; }
+ bool isUuid() const { return type() == Uuid; }
+ bool isInvalid() const { return type() == Invalid; }
+ bool isContainer() const { return isMap() || isArray(); }
+
+ bool isSimpleType() const
+ {
+ return int(type()) >> 8 == int(SimpleType) >> 8;
+ }
+ bool isSimpleType(QCborSimpleType st) const
+ {
+ return type() == type_helper(st);
+ }
+ QCborSimpleType toSimpleType(QCborSimpleType defaultValue = QCborSimpleType::Undefined) const
+ {
+ return isSimpleType() ? QCborSimpleType(type() & 0xff) : defaultValue;
+ }
+
+ qint64 toInteger(qint64 defaultValue = 0) const
+ { return isInteger() ? value_helper() : isDouble() ? qint64(fp_helper()) : defaultValue; }
+ bool toBool(bool defaultValue = false) const
+ { return isBool() ? isTrue() : defaultValue; }
+ double toDouble(double defaultValue = 0) const
+ { return isDouble() ? fp_helper() : isInteger() ? double(value_helper()) : defaultValue; }
+
+ QCborTag tag(QCborTag defaultValue = QCborTag(-1)) const;
+ QCborValue taggedValue(const QCborValue &defaultValue = QCborValue()) const;
+
+ QByteArray toByteArray(const QByteArray &defaultValue = {}) const;
+ QString toString(const QString &defaultValue = {}) const;
+ QDateTime toDateTime(const QDateTime &defaultValue = {}) const;
+ QUrl toUrl(const QUrl &defaultValue = {}) const;
+ QRegularExpression toRegularExpression(const QRegularExpression &defaultValue = {}) const;
+ QUuid toUuid(const QUuid &defaultValue = {}) const;
+
+#ifdef Q_QDOC
+ QCborArray toArray(const QCborArray &a = {}) const;
+ QCborMap toMap(const QCborMap &m = {}) const;
+#else
+ // only forward-declared, need split functions
+ QCborArray toArray() const;
+ QCborArray toArray(const QCborArray &defaultValue) const;
+ QCborMap toMap() const;
+ QCborMap toMap(const QCborMap &defaultValue) const;
+#endif
+
+ const QCborValue operator[](const QString &key) const;
+ const QCborValue operator[](QLatin1String key) const;
+ const QCborValue operator[](qint64 key) const;
+
+ int compare(const QCborValue &other) const;
+#if 0 && QT_HAS_INCLUDE(<compare>)
+ std::strong_ordering operator<=>(const QCborValue &other) const
+ {
+ int c = compare(other);
+ if (c > 0) return std::partial_ordering::greater;
+ if (c == 0) return std::partial_ordering::equivalent;
+ return std::partial_ordering::less;
+ }
+#else
+ bool operator==(const QCborValue &other) const noexcept
+ { return compare(other) == 0; }
+ bool operator!=(const QCborValue &other) const noexcept
+ { return !(*this == other); }
+ bool operator<(const QCborValue &other) const
+ { return compare(other) < 0; }
+#endif
+
+ static QCborValue fromVariant(const QVariant &variant);
+ QVariant toVariant() const;
+ static QCborValue fromJsonValue(const QJsonValue &v);
+ QJsonValue toJsonValue() const;
+
+ static QCborValue fromCbor(QCborStreamReader &reader);
+ static QCborValue fromCbor(const QByteArray &ba, QCborParserError *error = nullptr);
+ static QCborValue fromCbor(const char *data, qsizetype len, QCborParserError *error = nullptr)
+ { return fromCbor(QByteArray(data, int(len)), error); }
+ static QCborValue fromCbor(const quint8 *data, qsizetype len, QCborParserError *error = nullptr)
+ { return fromCbor(QByteArray(reinterpret_cast<const char *>(data), int(len)), error); }
+ QByteArray toCbor(EncodingOptions opt = NoTransformation);
+ void toCbor(QCborStreamWriter &writer, EncodingOptions opt = NoTransformation);
+
+ QString toDiagnosticNotation(DiagnosticNotationOptions opts = Compact) const;
+
+private:
+ friend class QCborValueRef;
+ friend class QCborContainerPrivate;
+ qint64 n = 0;
+ QCborContainerPrivate *container = nullptr;
+ Type t = Undefined;
+
+ void dispose();
+ qint64 value_helper() const
+ {
+ return n;
+ }
+
+ double fp_helper() const
+ {
+ Q_STATIC_ASSERT(sizeof(double) == sizeof(n));
+ double d;
+ memcpy(&d, &n, sizeof(d));
+ return d;
+ }
+
+ Q_DECL_CONSTEXPR static Type type_helper(QCborSimpleType st)
+ {
+ return Type(quint8(st) | SimpleType);
+ }
+
+ Q_DECL_CONSTEXPR static bool isTag_helper(Type t)
+ {
+ return t == Tag || t >= 0x10000;
+ }
+};
+Q_DECLARE_SHARED(QCborValue)
+
+class Q_CORE_EXPORT QCborValueRef
+{
+public:
+ operator QCborValue() const { return concrete(); }
+
+ QCborValueRef(const QCborValueRef &) noexcept = default;
+ QCborValueRef(QCborValueRef &&) noexcept = default;
+ QCborValueRef &operator=(const QCborValue &other)
+ { assign(*this, other); return *this; }
+ QCborValueRef &operator=(QCborValue &&other)
+ { assign(*this, std::move(other)); other.container = nullptr; return *this; }
+ QCborValueRef &operator=(const QCborValueRef &other)
+ { assign(*this, other); return *this; }
+
+ QCborValue::Type type() const { return concreteType(); }
+ bool isInteger() const { return type() == QCborValue::Integer; }
+ bool isByteArray() const { return type() == QCborValue::ByteArray; }
+ bool isString() const { return type() == QCborValue::String; }
+ bool isArray() const { return type() == QCborValue::Array; }
+ bool isMap() const { return type() == QCborValue::Map; }
+ bool isTag() const { return QCborValue::isTag_helper(type()); }
+ bool isFalse() const { return type() == QCborValue::False; }
+ bool isTrue() const { return type() == QCborValue::True; }
+ bool isBool() const { return isFalse() || isTrue(); }
+ bool isNull() const { return type() == QCborValue::Null; }
+ bool isUndefined() const { return type() == QCborValue::Undefined; }
+ bool isDouble() const { return type() == QCborValue::Double; }
+ bool isDateTime() const { return type() == QCborValue::DateTime; }
+ bool isUrl() const { return type() == QCborValue::Url; }
+ bool isRegularExpression() const { return type() == QCborValue::RegularExpression; }
+ bool isUuid() const { return type() == QCborValue::Uuid; }
+ bool isInvalid() const { return type() == QCborValue::Invalid; }
+ bool isContainer() const { return isMap() || isArray(); }
+ bool isSimpleType() const
+ {
+ return type() >= QCborValue::SimpleType && type() < QCborValue::SimpleType + 0x100;
+ }
+ bool isSimpleType(QCborSimpleType st) const
+ {
+ return type() == QCborValue::type_helper(st);
+ }
+
+ QCborTag tag(QCborTag defaultValue = QCborTag(-1)) const
+ { return concrete().tag(defaultValue); }
+ QCborValue taggedValue(const QCborValue &defaultValue = QCborValue()) const
+ { return concrete().taggedValue(defaultValue); }
+
+ qint64 toInteger(qint64 defaultValue = 0) const
+ { return concrete().toInteger(defaultValue); }
+ bool toBool(bool defaultValue = false) const
+ { return concrete().toBool(defaultValue); }
+ double toDouble(double defaultValue = 0) const
+ { return concrete().toDouble(defaultValue); }
+
+ QByteArray toByteArray(const QByteArray &defaultValue = {}) const
+ { return concrete().toByteArray(defaultValue); }
+ QString toString(const QString &defaultValue = {}) const
+ { return concrete().toString(defaultValue); }
+ QDateTime toDateTime(const QDateTime &defaultValue = {}) const
+ { return concrete().toDateTime(defaultValue); }
+ QUrl toUrl(const QUrl &defaultValue = {}) const
+ { return concrete().toUrl(defaultValue); }
+ QRegularExpression toRegularExpression(const QRegularExpression &defaultValue = {}) const
+ { return concrete().toRegularExpression(defaultValue); }
+ QUuid toUuid(const QUuid &defaultValue = {}) const
+ { return concrete().toUuid(defaultValue); }
+
+#ifdef Q_QDOC
+ QCborArray toArray(const QCborArray &a = {}) const;
+ QCborMap toMap(const QCborMap &m = {}) const;
+#else
+ // only forward-declared, need split functions. Implemented in qcbor{array,map}.h
+ QCborArray toArray() const;
+ QCborArray toArray(const QCborArray &a) const;
+ QCborMap toMap() const;
+ QCborMap toMap(const QCborMap &m) const;
+#endif
+
+ int compare(const QCborValue &other) const
+ { return concrete().compare(other); }
+#if 0 && QT_HAS_INCLUDE(<compare>)
+ std::strong_ordering operator<=>(const QCborValue &other) const
+ {
+ int c = compare(other);
+ if (c > 0) return std::strong_ordering::greater;
+ if (c == 0) return std::strong_ordering::equivalent;
+ return std::strong_ordering::less;
+ }
+#else
+ bool operator==(const QCborValue &other) const
+ { return compare(other) == 0; }
+ bool operator!=(const QCborValue &other) const
+ { return !(*this == other); }
+ bool operator<(const QCborValue &other) const
+ { return compare(other) < 0; }
+#endif
+
+ QVariant toVariant() const { return concrete().toVariant(); }
+ QJsonValue toJsonValue() const;
+
+ QByteArray toCbor(QCborValue::EncodingOptions opt = QCborValue::NoTransformation)
+ { return concrete().toCbor(opt); }
+ void toCbor(QCborStreamWriter &writer, QCborValue::EncodingOptions opt = QCborValue::NoTransformation);
+
+ QString toDiagnosticNotation(QCborValue::DiagnosticNotationOptions opt = QCborValue::Compact)
+ { return concrete().toDiagnosticNotation(opt); }
+
+private:
+ friend class QCborArray;
+ friend class QCborMap;
+ friend class QCborContainerPrivate;
+ friend class QCborValueRefPtr;
+
+ // static so we can pass this by value
+ static void assign(QCborValueRef that, const QCborValue &other);
+ static void assign(QCborValueRef that, QCborValue &&other);
+ static void assign(QCborValueRef that, const QCborValueRef other);
+ static QCborValue concrete(QCborValueRef that) noexcept;
+ QCborValue concrete() const noexcept { return concrete(*this); }
+
+ static QCborValue::Type concreteType(QCborValueRef self) noexcept Q_DECL_PURE_FUNCTION;
+ QCborValue::Type concreteType() const noexcept { return concreteType(*this); }
+
+ // this will actually be invalid...
+ Q_DECL_CONSTEXPR QCborValueRef() : d(nullptr), i(0) {}
+
+ QCborValueRef(QCborContainerPrivate *dd, qsizetype ii)
+ : d(dd), i(ii)
+ {}
+ QCborContainerPrivate *d;
+ qsizetype i;
+};
+
+Q_CORE_EXPORT uint qHash(const QCborValue &value, uint seed = 0);
+
+#if !defined(QT_NO_DEBUG_STREAM)
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborValue &v);
+#endif
+
+QT_END_NAMESPACE
+
+#if defined(QT_X11_DEFINES_FOUND)
+# define True 1
+# define False 0
+#endif
+
+#endif // QCBORVALUE_H
diff --git a/src/corelib/serialization/qcborvalue_p.h b/src/corelib/serialization/qcborvalue_p.h
new file mode 100644
index 0000000000..4050d18fa9
--- /dev/null
+++ b/src/corelib/serialization/qcborvalue_p.h
@@ -0,0 +1,399 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://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 QCBORVALUE_P_H
+#define QCBORVALUE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API.
+// This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qcborvalue.h"
+
+#include <private/qglobal_p.h>
+#include <private/qutfcodec_p.h>
+
+#include <math.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtCbor {
+struct Undefined {};
+struct Element
+{
+ enum ValueFlag : quint32 {
+ IsContainer = 0x0001,
+ HasByteData = 0x0002,
+ StringIsUtf16 = 0x0004,
+ StringIsAscii = 0x0008
+ };
+ Q_DECLARE_FLAGS(ValueFlags, ValueFlag)
+
+ union {
+ qint64 value;
+ QCborContainerPrivate *container;
+ };
+ QCborValue::Type type;
+ ValueFlags flags = {};
+
+ Element(qint64 v = 0, QCborValue::Type t = QCborValue::Undefined, ValueFlags f = {})
+ : value(v), type(t), flags(f)
+ {}
+
+ Element(QCborContainerPrivate *d, QCborValue::Type t, ValueFlags f = {})
+ : container(d), type(t), flags(f | IsContainer)
+ {}
+
+ double fpvalue() const
+ {
+ double d;
+ memcpy(&d, &value, sizeof(d));
+ return d;
+ }
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(Element::ValueFlags)
+Q_STATIC_ASSERT(sizeof(Element) == 16);
+
+struct ByteData
+{
+ QByteArray::size_type len;
+
+ const char *byte() const { return reinterpret_cast<const char *>(this + 1); }
+ char *byte() { return reinterpret_cast<char *>(this + 1); }
+ const QChar *utf16() const { return reinterpret_cast<const QChar *>(this + 1); }
+ QChar *utf16() { return reinterpret_cast<QChar *>(this + 1); }
+
+ QByteArray toByteArray() const { return QByteArray(byte(), len); }
+ QString toString() const { return QString(utf16(), len / 2); }
+ QString toUtf8String() const { return QString::fromUtf8(byte(), len); }
+
+ QByteArray asByteArrayView() const { return QByteArray::fromRawData(byte(), len); }
+ QLatin1String asLatin1() const { return QLatin1String(byte(), len); }
+ QStringView asStringView() const{ return QStringView(utf16(), len / 2); }
+ QString asQStringRaw() const { return QString::fromRawData(utf16(), len / 2); }
+};
+Q_STATIC_ASSERT(std::is_pod<ByteData>::value);
+} // namespace QtCbor
+
+Q_DECLARE_TYPEINFO(QtCbor::Element, Q_PRIMITIVE_TYPE);
+
+class QCborContainerPrivate : public QSharedData
+{
+ friend class QExplicitlySharedDataPointer<QCborContainerPrivate>;
+ ~QCborContainerPrivate();
+
+public:
+ enum ContainerDisposition { CopyContainer, MoveContainer };
+
+ QByteArray::size_type usedData = 0;
+ QByteArray data;
+ QVector<QtCbor::Element> elements;
+
+ void deref() { if (!ref.deref()) delete this; }
+ void compact(qsizetype reserved);
+ static QCborContainerPrivate *clone(QCborContainerPrivate *d, qsizetype reserved = -1);
+ static QCborContainerPrivate *detach(QCborContainerPrivate *d, qsizetype reserved);
+ static QCborContainerPrivate *grow(QCborContainerPrivate *d, qsizetype index);
+
+ qptrdiff addByteData(const char *block, qsizetype len)
+ {
+ // This function does not do overflow checking, since the len parameter
+ // is expected to be trusted. There's another version of this function
+ // in decodeStringFromCbor(), which checks.
+
+ qptrdiff offset = data.size();
+
+ // align offset
+ offset += Q_ALIGNOF(QtCbor::ByteData) - 1;
+ offset &= ~(Q_ALIGNOF(QtCbor::ByteData) - 1);
+
+ qptrdiff increment = qptrdiff(sizeof(QtCbor::ByteData)) + len;
+
+ usedData += increment;
+ data.resize(offset + increment);
+
+ char *ptr = data.begin() + offset;
+ auto b = new (ptr) QtCbor::ByteData;
+ b->len = len;
+ if (block)
+ memcpy(b->byte(), block, len);
+
+ return offset;
+ }
+
+ const QtCbor::ByteData *byteData(QtCbor::Element e) const
+ {
+ if ((e.flags & QtCbor::Element::HasByteData) == 0)
+ return nullptr;
+
+ size_t offset = size_t(e.value);
+ Q_ASSERT((offset % Q_ALIGNOF(QtCbor::ByteData)) == 0);
+ Q_ASSERT(offset + sizeof(QtCbor::ByteData) <= size_t(data.size()));
+
+ auto b = reinterpret_cast<const QtCbor::ByteData *>(data.constData() + offset);
+ Q_ASSERT(offset + sizeof(*b) + size_t(b->len) <= size_t(data.size()));
+ return b;
+ }
+ const QtCbor::ByteData *byteData(qsizetype idx) const
+ {
+ return byteData(elements.at(idx));
+ }
+
+ QCborContainerPrivate *containerAt(qsizetype idx, QCborValue::Type type) const
+ {
+ const QtCbor::Element &e = elements.at(idx);
+ if (e.type != type || (e.flags & QtCbor::Element::IsContainer) == 0)
+ return nullptr;
+ return e.container;
+ }
+
+ void replaceAt_complex(QtCbor::Element &e, const QCborValue &value, ContainerDisposition disp);
+ void replaceAt_internal(QtCbor::Element &e, const QCborValue &value, ContainerDisposition disp)
+ {
+ if (value.container)
+ return replaceAt_complex(e, value, disp);
+
+ e.value = value.value_helper();
+ e.type = value.type();
+ if (value.isContainer())
+ e.container = nullptr;
+ }
+ void replaceAt(qsizetype idx, const QCborValue &value, ContainerDisposition disp = CopyContainer)
+ {
+ QtCbor::Element &e = elements[idx];
+ if (e.flags & QtCbor::Element::IsContainer) {
+ e.container->deref();
+ e.container = nullptr;
+ e.flags = {};
+ } else if (auto b = byteData(e)) {
+ usedData -= b->len + sizeof(QtCbor::ByteData);
+ }
+ replaceAt_internal(e, value, disp);
+ }
+ void insertAt(qsizetype idx, const QCborValue &value, ContainerDisposition disp = CopyContainer)
+ {
+ replaceAt_internal(*elements.insert(elements.begin() + idx, {}), value, disp);
+ }
+
+ void append(QtCbor::Undefined)
+ {
+ elements.append(QtCbor::Element());
+ }
+ void append(qint64 value)
+ {
+ elements.append(QtCbor::Element(value , QCborValue::Integer));
+ }
+ void append(QCborTag tag)
+ {
+ elements.append(QtCbor::Element(qint64(tag), QCborValue::Tag));
+ }
+ void appendByteData(const char *data, qsizetype len, QCborValue::Type type,
+ QtCbor::Element::ValueFlags extraFlags = {})
+ {
+ elements.append(QtCbor::Element(addByteData(data, len), type,
+ QtCbor::Element::HasByteData | extraFlags));
+ }
+ void append(QLatin1String s)
+ {
+ if (!QtPrivate::isAscii(s))
+ return append(QString(s));
+
+ // US-ASCII is a subset of UTF-8, so we can keep in 8-bit
+ appendByteData(s.latin1(), s.size(), QCborValue::String,
+ QtCbor::Element::StringIsAscii);
+ }
+ void appendAsciiString(const QString &s);
+ void append(const QString &s)
+ {
+ if (QtPrivate::isAscii(s))
+ appendAsciiString(s);
+ else
+ appendByteData(reinterpret_cast<const char *>(s.constData()), s.size() * 2,
+ QCborValue::String, QtCbor::Element::StringIsUtf16);
+ }
+ void append(const QCborValue &v)
+ {
+ insertAt(elements.size(), v);
+ }
+
+ QByteArray byteArrayAt(qsizetype idx) const
+ {
+ const auto &e = elements.at(idx);
+ const auto data = byteData(e);
+ if (!data)
+ return QByteArray();
+ return data->toByteArray();
+ }
+ QString stringAt(qsizetype idx) const
+ {
+ const auto &e = elements.at(idx);
+ const auto data = byteData(e);
+ if (!data)
+ return QString();
+ if (e.flags & QtCbor::Element::StringIsUtf16)
+ return data->toString();
+ if (e.flags & QtCbor::Element::StringIsAscii)
+ return data->asLatin1();
+ return data->toUtf8String();
+ }
+
+ static void resetValue(QCborValue &v)
+ {
+ v.container = nullptr;
+ }
+
+ static QCborValue makeValue(QCborValue::Type type, qint64 n, QCborContainerPrivate *d = nullptr,
+ ContainerDisposition disp = CopyContainer)
+ {
+ QCborValue result(type);
+ result.n = n;
+ result.container = d;
+ if (d && disp == CopyContainer)
+ d->ref.ref();
+ return result;
+ }
+
+ QCborValue valueAt(qsizetype idx) const
+ {
+ const auto &e = elements.at(idx);
+
+ if (e.flags & QtCbor::Element::IsContainer) {
+ if (e.type == QCborValue::Tag && e.container->elements.size() != 2) {
+ // invalid tags can be created due to incomplete parsing
+ return makeValue(QCborValue::Invalid, 0, nullptr);
+ }
+ return makeValue(e.type, -1, e.container);
+ } else if (e.flags & QtCbor::Element::HasByteData) {
+ return makeValue(e.type, idx, const_cast<QCborContainerPrivate *>(this));
+ }
+ return makeValue(e.type, e.value);
+ }
+ QCborValue extractAt_complex(QtCbor::Element e);
+ QCborValue extractAt(qsizetype idx)
+ {
+ QtCbor::Element e;
+ qSwap(e, elements[idx]);
+
+ if (e.flags & QtCbor::Element::IsContainer) {
+ if (e.type == QCborValue::Tag && e.container->elements.size() != 2) {
+ // invalid tags can be created due to incomplete parsing
+ e.container->deref();
+ return makeValue(QCborValue::Invalid, 0, nullptr);
+ }
+ return makeValue(e.type, -1, e.container, MoveContainer);
+ } else if (e.flags & QtCbor::Element::HasByteData) {
+ return extractAt_complex(e);
+ }
+ return makeValue(e.type, e.value);
+ }
+
+ static QtCbor::Element elementFromValue(const QCborValue &value)
+ {
+ if (value.n >= 0 && value.container)
+ return value.container->elements.at(value.n);
+
+ QtCbor::Element e;
+ e.value = value.n;
+ e.type = value.t;
+ if (value.container) {
+ e.container = value.container;
+ e.flags = QtCbor::Element::IsContainer;
+ }
+ return e;
+ }
+
+ bool stringEqualsElement(qsizetype idx, QLatin1String s) const
+ {
+ const auto &e = elements.at(idx);
+ if (e.type != QCborValue::String)
+ return false;
+
+ const QtCbor::ByteData *b = byteData(idx);
+ if (!b)
+ return s.isEmpty();
+
+ if (e.flags & QtCbor::Element::StringIsUtf16)
+ return QtPrivate::compareStrings(b->asStringView(), s) == 0;
+ return QUtf8::compareUtf8(b->byte(), b->len, s) == 0;
+ }
+ bool stringEqualsElement(qsizetype idx, const QString &s) const
+ {
+ const auto &e = elements.at(idx);
+ if (e.type != QCborValue::String)
+ return false;
+
+ const QtCbor::ByteData *b = byteData(idx);
+ if (!b)
+ return s.isEmpty();
+
+ if (e.flags & QtCbor::Element::StringIsUtf16)
+ return QtPrivate::compareStrings(b->asStringView(), s) == 0;
+ return QUtf8::compareUtf8(b->byte(), b->len, s.data(), s.size()) == 0;
+ }
+
+ static int compareElement_helper(const QCborContainerPrivate *c1, QtCbor::Element e1,
+ const QCborContainerPrivate *c2, QtCbor::Element e2);
+ int compareElement(qsizetype idx, const QCborValue &value) const
+ {
+ auto &e1 = elements.at(idx);
+ auto e2 = elementFromValue(value);
+ return compareElement_helper(this, e1, value.container, e2);
+ }
+
+ void removeAt(qsizetype idx)
+ {
+ replaceAt(idx, {});
+ elements.remove(idx);
+ }
+
+ void decodeValueFromCbor(QCborStreamReader &reader);
+ void decodeFromCbor(QCborStreamReader &reader);
+ void decodeStringFromCbor(QCborStreamReader &reader);
+};
+
+QT_END_NAMESPACE
+
+#endif // QCBORVALUE_P_H
diff --git a/src/corelib/serialization/qdatastream.cpp b/src/corelib/serialization/qdatastream.cpp
index 09e98cb2b4..951f6c9736 100644
--- a/src/corelib/serialization/qdatastream.cpp
+++ b/src/corelib/serialization/qdatastream.cpp
@@ -170,18 +170,12 @@ QT_BEGIN_NAMESPACE
will have appropriate stream operators declared as non-member of
the class:
- \code
- QDataStream &operator<<(QDataStream &, const QXxx &);
- QDataStream &operator>>(QDataStream &, QXxx &);
- \endcode
+ \snippet code/src_corelib_serialization_qdatastream.cpp 0
For example, here are the stream operators declared as non-members
of the QImage class:
- \code
- QDataStream & operator<< (QDataStream& stream, const QImage& image);
- QDataStream & operator>> (QDataStream& stream, QImage& image);
- \endcode
+ \snippet code/src_corelib_serialization_qdatastream.cpp 1
To see if your favorite Qt class has similar stream operators
defined, check the \b {Related Non-Members} section of the
@@ -564,6 +558,7 @@ void QDataStream::setByteOrder(ByteOrder bo)
\value Qt_5_9 Same as Qt_5_6
\value Qt_5_10 Same as Qt_5_6
\value Qt_5_11 Same as Qt_5_6
+ \value Qt_5_12 Version 18 (Qt 5.12)
\omitvalue Qt_DefaultCompiledVersion
\sa setVersion(), version()
diff --git a/src/corelib/serialization/qdatastream.h b/src/corelib/serialization/qdatastream.h
index 1775022355..eae0146553 100644
--- a/src/corelib/serialization/qdatastream.h
+++ b/src/corelib/serialization/qdatastream.h
@@ -98,10 +98,11 @@ public:
Qt_5_9 = Qt_5_8,
Qt_5_10 = Qt_5_9,
Qt_5_11 = Qt_5_10,
-#if QT_VERSION >= 0x050c00
+ Qt_5_12 = 18,
+#if QT_VERSION >= 0x050d00
#error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion
#endif
- Qt_DefaultCompiledVersion = Qt_5_11
+ Qt_DefaultCompiledVersion = Qt_5_12
};
enum ByteOrder {
diff --git a/src/corelib/serialization/qjson.cpp b/src/corelib/serialization/qjson.cpp
index b82923fe0c..d74ffb2a20 100644
--- a/src/corelib/serialization/qjson.cpp
+++ b/src/corelib/serialization/qjson.cpp
@@ -70,6 +70,7 @@ void Data::compact()
int size = sizeof(Base) + reserve + base->length*sizeof(offset);
int alloc = sizeof(Header) + size;
Header *h = (Header *) malloc(alloc);
+ Q_CHECK_PTR(h);
h->tag = QJsonDocument::BinaryFormatTag;
h->version = 1;
Base *b = h->root();
diff --git a/src/corelib/serialization/qjson_p.h b/src/corelib/serialization/qjson_p.h
index dc56a49084..feba1faac6 100644
--- a/src/corelib/serialization/qjson_p.h
+++ b/src/corelib/serialization/qjson_p.h
@@ -69,6 +69,9 @@
QT_BEGIN_NAMESPACE
+// in qstring.cpp
+void qt_to_latin1_unchecked(uchar *dst, const ushort *uc, qsizetype len);
+
/*
This defines a binary data structure for Json data. The data structure is optimised for fast reading
and minimum allocations. The whole data structure can be mmap'ed and used directly.
@@ -294,31 +297,10 @@ public:
int len = d->length = str.length();
uchar *l = (uchar *)d->latin1;
const ushort *uc = (const ushort *)str.unicode();
- int i = 0;
-#ifdef __SSE2__
- for ( ; i + 16 <= len; i += 16) {
- __m128i chunk1 = _mm_loadu_si128((__m128i*)&uc[i]); // load
- __m128i chunk2 = _mm_loadu_si128((__m128i*)&uc[i + 8]); // load
- // pack the two vector to 16 x 8bits elements
- const __m128i result = _mm_packus_epi16(chunk1, chunk2);
- _mm_storeu_si128((__m128i*)&l[i], result); // store
- }
-# ifdef Q_PROCESSOR_X86_64
- // we can do one more round, of 8 characters
- if (i + 8 <= len) {
- __m128i chunk = _mm_loadu_si128((__m128i*)&uc[i]); // load
- // pack with itself, we'll discard the high part anyway
- chunk = _mm_packus_epi16(chunk, chunk);
- // unaligned 64-bit store
- qToUnaligned(_mm_cvtsi128_si64(chunk), l + i);
- i += 8;
- }
-# endif
-#endif
- for ( ; i < len; ++i)
- l[i] = uc[i];
- for ( ; (quintptr)(l+i) & 0x3; ++i)
- l[i] = 0;
+ qt_to_latin1_unchecked(l, uc, len);
+
+ for ( ; (quintptr)(l+len) & 0x3; ++len)
+ l[len] = 0;
return *this;
}
diff --git a/src/corelib/serialization/qjsonarray.cpp b/src/corelib/serialization/qjsonarray.cpp
index 8ee9ce0de7..1187bb03a3 100644
--- a/src/corelib/serialization/qjsonarray.cpp
+++ b/src/corelib/serialization/qjsonarray.cpp
@@ -1237,6 +1237,10 @@ void QJsonArray::compact()
a = static_cast<QJsonPrivate::Array *>(d->header->root());
}
+uint qHash(const QJsonArray &array, uint seed)
+{
+ return qHashRange(array.begin(), array.end(), seed);
+}
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
QDebug operator<<(QDebug dbg, const QJsonArray &a)
diff --git a/src/corelib/serialization/qjsonarray.h b/src/corelib/serialization/qjsonarray.h
index 8d41138c97..5dff4a0aa9 100644
--- a/src/corelib/serialization/qjsonarray.h
+++ b/src/corelib/serialization/qjsonarray.h
@@ -265,6 +265,8 @@ private:
Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonArray)
+Q_CORE_EXPORT uint qHash(const QJsonArray &array, uint seed = 0);
+
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonArray &);
#endif
diff --git a/src/corelib/serialization/qjsoncbor.cpp b/src/corelib/serialization/qjsoncbor.cpp
new file mode 100644
index 0000000000..158f1950d0
--- /dev/null
+++ b/src/corelib/serialization/qjsoncbor.cpp
@@ -0,0 +1,954 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://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 "qcborvalue.h"
+#include "qcborvalue_p.h"
+
+#include "qcborarray.h"
+#include "qcbormap.h"
+#include "qjson_p.h"
+
+#include <private/qnumeric_p.h>
+#include <quuid.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QtCbor;
+
+static QJsonValue fpToJson(double v)
+{
+ return qt_is_finite(v) ? QJsonValue(v) : QJsonValue();
+}
+
+static QString simpleTypeString(QCborValue::Type t)
+{
+ int simpleType = t - QCborValue::SimpleType;
+ if (unsigned(simpleType) < 0x100)
+ return QString::fromLatin1("simple(%1)").arg(simpleType);
+
+ // if we got here, we got an unknown type
+ qWarning("QCborValue: found unknown type 0x%x", t);
+ return QString();
+
+}
+
+static QString encodeByteArray(const QCborContainerPrivate *d, qsizetype idx, QCborTag encoding)
+{
+ const ByteData *b = d->byteData(idx);
+ if (!b)
+ return QString();
+
+ QByteArray data = QByteArray::fromRawData(b->byte(), b->len);
+ if (encoding == QCborKnownTags::ExpectedBase16)
+ data = data.toHex();
+ else if (encoding == QCborKnownTags::ExpectedBase64)
+ data = data.toBase64();
+ else
+ data = data.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
+
+ return QString::fromLatin1(data, data.size());
+}
+
+static QString makeString(const QCborContainerPrivate *d, qsizetype idx);
+
+static QString maybeEncodeTag(const QCborContainerPrivate *d)
+{
+ qint64 tag = d->elements.at(0).value;
+ const Element &e = d->elements.at(1);
+ const ByteData *b = d->byteData(e);
+
+ switch (tag) {
+ case qint64(QCborKnownTags::DateTimeString):
+ case qint64(QCborKnownTags::Url):
+ if (e.type == QCborValue::String)
+ return makeString(d, 1);
+ break;
+
+ case qint64(QCborKnownTags::ExpectedBase64url):
+ case qint64(QCborKnownTags::ExpectedBase64):
+ case qint64(QCborKnownTags::ExpectedBase16):
+ if (e.type == QCborValue::ByteArray)
+ return encodeByteArray(d, 1, QCborTag(tag));
+ break;
+
+ case qint64(QCborKnownTags::Uuid):
+ if (e.type == QCborValue::ByteArray && b->len == sizeof(QUuid))
+ return QUuid::fromRfc4122(b->asByteArrayView()).toString(QUuid::WithoutBraces);
+ }
+
+ // don't know what to do, bail out
+ return QString();
+}
+
+static QString encodeTag(const QCborContainerPrivate *d)
+{
+ QString s;
+ if (!d || d->elements.size() != 2)
+ return s; // invalid (incomplete?) tag state
+
+ s = maybeEncodeTag(d);
+ if (s.isNull()) {
+ // conversion failed, ignore the tag and convert the tagged value
+ s = makeString(d, 1);
+ }
+ return s;
+}
+
+static Q_NEVER_INLINE QString makeString(const QCborContainerPrivate *d, qsizetype idx)
+{
+ const auto &e = d->elements.at(idx);
+
+ switch (e.type) {
+ case QCborValue::Integer:
+ return QString::number(qint64(e.value));
+
+ case QCborValue::Double:
+ return QString::number(e.fpvalue());
+
+ case QCborValue::ByteArray:
+ return encodeByteArray(d, idx, QCborTag(QCborKnownTags::ExpectedBase64url));
+
+ case QCborValue::String:
+ return d->stringAt(idx);
+
+ case QCborValue::Array:
+ case QCborValue::Map:
+ return d->valueAt(idx).toDiagnosticNotation(QCborValue::Compact);
+
+ case QCborValue::SimpleType:
+ break;
+
+ case QCborValue::False:
+ return QStringLiteral("false");
+
+ case QCborValue::True:
+ return QStringLiteral("true");
+
+ case QCborValue::Null:
+ return QStringLiteral("null");
+
+ case QCborValue::Undefined:
+ return QStringLiteral("undefined");
+
+ case QCborValue::Invalid:
+ return QString();
+
+ case QCborValue::Tag:
+ case QCborValue::DateTime:
+ case QCborValue::Url:
+ case QCborValue::RegularExpression:
+ case QCborValue::Uuid:
+ return encodeTag(e.flags & Element::IsContainer ? e.container : nullptr);
+ }
+
+ // maybe it's a simple type
+ return simpleTypeString(e.type);
+}
+
+static QJsonValue convertToJson(const QCborContainerPrivate *d, qsizetype idx);
+
+static QJsonArray convertToJsonArray(const QCborContainerPrivate *d)
+{
+ QJsonArray a;
+ if (d) {
+ for (qsizetype idx = 0; idx < d->elements.size(); ++idx)
+ a.append(convertToJson(d, idx));
+ }
+ return a;
+}
+
+static QJsonObject convertToJsonObject(const QCborContainerPrivate *d)
+{
+ QJsonObject o;
+ if (d) {
+ for (qsizetype idx = 0; idx < d->elements.size(); idx += 2)
+ o.insert(makeString(d, idx), convertToJson(d, idx + 1));
+ }
+ return o;
+}
+
+static QJsonValue convertExtendedTypeToJson(const QCborContainerPrivate *d)
+{
+ qint64 tag = d->elements.at(0).value;
+
+ switch (tag) {
+ case qint64(QCborKnownTags::Url):
+ // use the fullly-encoded URL form
+ if (d->elements.at(1).type == QCborValue::String)
+ return QUrl::fromEncoded(d->byteData(1)->asByteArrayView()).toString(QUrl::FullyEncoded);
+ Q_FALLTHROUGH();
+
+ case qint64(QCborKnownTags::DateTimeString):
+ case qint64(QCborKnownTags::ExpectedBase64url):
+ case qint64(QCborKnownTags::ExpectedBase64):
+ case qint64(QCborKnownTags::ExpectedBase16):
+ case qint64(QCborKnownTags::Uuid): {
+ // use the string conversion
+ QString s = maybeEncodeTag(d);
+ if (!s.isNull())
+ return s;
+ }
+ }
+
+ // for all other tags, ignore it and return the converted tagged item
+ return convertToJson(d, 1);
+}
+
+static QJsonValue convertToJson(const QCborContainerPrivate *d, qsizetype idx)
+{
+ // encoding the container itself
+ if (idx == -QCborValue::Array)
+ return convertToJsonArray(d);
+ if (idx == -QCborValue::Map)
+ return convertToJsonObject(d);
+ if (idx < 0) {
+ // tag-like type
+ if (!d || d->elements.size() != 2)
+ return QJsonValue::Undefined; // invalid state
+ return convertExtendedTypeToJson(d);
+ }
+
+ // an element in the container
+ const auto &e = d->elements.at(idx);
+ switch (e.type) {
+ case QCborValue::Integer:
+ return qint64(e.value);
+
+ case QCborValue::ByteArray:
+ case QCborValue::String:
+ case QCborValue::SimpleType:
+ // make string
+ break;
+
+ case QCborValue::Array:
+ case QCborValue::Map:
+ case QCborValue::Tag:
+ case QCborValue::DateTime:
+ case QCborValue::Url:
+ case QCborValue::RegularExpression:
+ case QCborValue::Uuid:
+ // recurse
+ return convertToJson(e.flags & Element::IsContainer ? e.container : nullptr, -e.type);
+
+ case QCborValue::Null:
+ return QJsonValue();
+
+ case QCborValue::Undefined:
+ case QCborValue::Invalid:
+ return QJsonValue(QJsonValue::Undefined);
+
+ case QCborValue::False:
+ return false;
+
+ case QCborValue::True:
+ return true;
+
+ case QCborValue::Double:
+ return fpToJson(e.fpvalue());
+ }
+
+ return makeString(d, idx);
+}
+
+/*!
+ Converts this QCborValue object to an equivalent representation in JSON and
+ returns it as a QJsonValue.
+
+ Please note that CBOR contains a richer and wider type set than JSON, so
+ some information may be lost in this conversion. The following table
+ compares CBOR types to JSON types and indicates whether information may be
+ lost or not.
+
+ \table
+ \header \li CBOR Type \li JSON Type \li Comments
+ \row \li Bool \li Bool \li No data loss possible
+ \row \li Double \li Number \li Infinities and NaN will be converted to Null;
+ no data loss for other values
+ \row \li Integer \li Number \li Data loss possible in the conversion if the
+ integer is larger than 2\sup{53} or smaller
+ than -2\sup{53}.
+ \row \li Null \li Null \li No data loss possible
+ \row \li Undefined \li Null \li Type information lost
+ \row \li String \li String \li No data loss possible
+ \row \li Byte Array \li String \li Converted to a lossless encoding like Base64url,
+ but the distinction between strings and byte
+ arrays is lost
+ \row \li Other simple types \li String \li Type information lost
+ \row \li Array \li Array \li Conversion applies to each contained value
+ \row \li Map \li Object \li Keys are converted to string; values converted
+ according to this table
+ \row \li Tags and extended types \li Special \li The tag number itself is lost and the tagged
+ value is converted to JSON
+ \endtable
+
+ For information on the conversion of CBOR map keys to string, see
+ QCborMap::toJsonObject().
+
+ If this QCborValue contains the undefined value, this function will return
+ an undefined QJsonValue too. Note that JSON does not support undefined
+ values and undefined QJsonValues are an extension to the specification.
+ They cannot be held in a QJsonArray or QJsonObject, but can be returned
+ from functions to indicate a failure. For all other intents and purposes,
+ they are the same as null.
+
+ \section3 Special handling of tags and extended types
+
+ Some tags are handled specially and change the transformation of the tagged
+ value from CBOR to JSON. The following table lists those special cases:
+
+ \table
+ \header \li Tag \li CBOR type \li Transformation
+ \row \li ExpectedBase64url \li Byte array \li Encodes the byte array as Base64url
+ \row \li ExpectedBase64 \li Byte array \li Encodes the byte array as Base64
+ \row \li ExpectedBase16 \li Byte array \li Encodes the byte array as hex
+ \row \li Url \li Url and String \li Uses QUrl::toEncoded() to normalize the
+ encoding to the URL's fully encoded format
+ \row \li Uuid \li Uuid and Byte array \li Uses QUuid::toString() to create
+ the string representation
+ \endtable
+
+ \sa fromJsonValue(), toVariant(), QCborArray::toJsonArray(), QCborMap::toJsonObject()
+ */
+QJsonValue QCborValue::toJsonValue() const
+{
+ if (container)
+ return convertToJson(container, n < 0 ? -type() : n);
+
+ // simple values
+ switch (type()) {
+ case Integer:
+ return n;
+
+ case Null:
+ return QJsonValue();
+
+ case False:
+ return false;
+
+ case True:
+ return true;
+
+ case Double:
+ return fpToJson(fp_helper());
+
+ case SimpleType:
+ break;
+
+ case Undefined:
+ case Invalid:
+ return QJsonValue(QJsonValue::Undefined);
+
+ case ByteArray:
+ case String:
+ // empty strings
+ return QString();
+
+ case Array:
+ // empty array
+ return QJsonArray();
+
+ case Map:
+ // empty map
+ return QJsonObject();
+
+ case Tag:
+ case DateTime:
+ case Url:
+ case RegularExpression:
+ case Uuid:
+ Q_UNREACHABLE();
+ return QJsonValue::Undefined;
+ }
+
+ return simpleTypeString(type());
+}
+
+QJsonValue QCborValueRef::toJsonValue() const
+{
+ return convertToJson(d, i);
+}
+
+/*!
+ Recursively converts every \l QCborValue element in this array to JSON
+ using QCborValue::toJsonValue() and returns the corresponding QJsonArray
+ composed of those elements.
+
+ Please note that CBOR contains a richer and wider type set than JSON, so
+ some information may be lost in this conversion. For more details on what
+ conversions are applied, see QCborValue::toJsonValue().
+
+ \sa fromJsonArray(), QCborValue::toJsonValue(), QCborMap::toJsonObject(), toVariantList()
+ */
+QJsonArray QCborArray::toJsonArray() const
+{
+ return convertToJsonArray(d.data());
+}
+
+/*!
+ Recursively converts every \l QCborValue value in this array to JSON using
+ QCborValue::toJsonValue() and creates a string key for all keys that aren't
+ strings, then returns the corresponding QJsonObject composed of those
+ associations.
+
+ Please note that CBOR contains a richer and wider type set than JSON, so
+ some information may be lost in this conversion. For more details on what
+ conversions are applied, see QCborValue::toJsonValue().
+
+ \section3 Map key conversion to string
+
+ JSON objects are defined as having string keys, unlike CBOR, so the
+ conversion of a QCborMap to QJsonObject will imply a step of
+ "stringification" of the key values. The conversion will use the special
+ handling of tags and extended types from above and will also convert the
+ rest of the types as follows:
+
+ \table
+ \header \li Type \li Transformation
+ \row \li Bool \li "true" and "false"
+ \row \li Null \li "null"
+ \row \li Undefined \li "undefined"
+ \row \li Integer \li The decimal string form of the number
+ \row \li Double \li The decimal string form of the number
+ \row \li Byte array \li Unless tagged differently (see above), encoded as
+ Base64url
+ \row \li Array \li Replaced by the compact form of its
+ \l{QCborValue::toDiagnosticNotation()}{Diagnostic notation}
+ \row \li Map \li Replaced by the compact form of its
+ \l{QCborValue::toDiagnosticNotation()}{Diagnostic notation}
+ \row \li Tags and extended types \li Tag number is dropped and the tagged value is converted
+ to string
+ \endtable
+
+ \sa fromJsonObject(), QCborValue::toJsonValue(), QCborArray::toJsonArray(), toVariantMap()
+ */
+QJsonObject QCborMap::toJsonObject() const
+{
+ return convertToJsonObject(d.data());
+}
+
+/*!
+ Converts this value to a native Qt type and returns the corresponding QVariant.
+
+ The following table lists the mapping performed between \l{Type}{QCborValue
+ types} and \l{QMetaType::Type}{Qt meta types}.
+
+ \table
+ \header \li CBOR Type \li Qt or C++ type \li Notes
+ \row \li Integer \li \l qint64 \li
+ \row \li Double \li \c double \li
+ \row \li Bool \li \c bool \li
+ \row \li Null \li \c std::nullptr_t \li
+ \row \li Undefined \li no type (QVariant()) \li
+ \row \li Byte array \li \l QByteArray \li
+ \row \li String \li \l QString \li
+ \row \li Array \li \l QVariantList \li Recursively converts all values
+ \row \li Map \li \l QVariantMap \li Key types are "stringified"
+ \row \li Other simple types \li \l QCborSimpleType \li
+ \row \li DateTime \li \l QDateTime \li
+ \row \li Url \li \l QUrl \li
+ \row \li RegularExpression \li \l QRegularExpression \li
+ \row \li Uuid \li \l QUuid \li
+ \row \li Other tags \li Special \li The tag is ignored and the tagged
+ value is converted using this
+ function
+ \endtable
+
+ Note that values in both CBOR Maps and Arrays are converted recursively
+ using this function too and placed in QVariantMap and QVariantList instead.
+ You will not find QCborMap and QCborArray stored inside the QVariants.
+
+ QVariantMaps have string keys, unlike CBOR, so the conversion of a QCborMap
+ to QVariantMap will imply a step of "stringification" of the key values.
+ See QCborMap::toJsonObject() for details.
+
+ \sa fromVariant(), toJsonValue(), QCborArray::toVariantList(), QCborMap::toVariantMap()
+ */
+QVariant QCborValue::toVariant() const
+{
+ switch (type()) {
+ case Integer:
+ return toInteger();
+
+ case Double:
+ return toDouble();
+
+ case SimpleType:
+ break;
+
+ case False:
+ case True:
+ return isTrue();
+
+ case Null:
+ return QVariant::fromValue(nullptr);
+
+ case Undefined:
+ return QVariant();
+
+ case ByteArray:
+ return toByteArray();
+
+ case String:
+ return toString();
+
+ case Array:
+ return toArray().toVariantList();
+
+ case Map:
+ return toMap().toVariantMap();
+
+ case Tag:
+ // ignore tags
+ return taggedValue().toVariant();
+
+ case DateTime:
+ return toDateTime();
+
+ case Url:
+ return toUrl();
+
+ case RegularExpression:
+ return toRegularExpression();
+
+ case Uuid:
+ return toUuid();
+
+ case Invalid:
+ return QVariant();
+ }
+
+ if (isSimpleType())
+ return QVariant::fromValue(toSimpleType());
+
+ Q_UNREACHABLE();
+ return QVariant();
+}
+
+/*!
+ Converts the JSON value contained in \a v into its corresponding CBOR value
+ and returns it. There is no data loss in converting from JSON to CBOR, as
+ the CBOR type set is richer than JSON's. Additionally, values converted to
+ CBOR using this function can be converted back to JSON using toJsonValue()
+ with no data loss.
+
+ The following table lists the mapping of JSON types to CBOR types:
+
+ \table
+ \header \li JSON Type \li CBOR Type
+ \row \li Bool \li Bool
+ \row \li Number \li Integer (if the number has no fraction and is in the \l qint64
+ range) or Double
+ \row \li String \li String
+ \row \li Array \li Array
+ \row \li Object \li Map
+ \row \li Null \li Null
+ \endtable
+
+ \l QJsonValue can also be undefined, indicating a previous operation that
+ failed to complete (for example, searching for a key not present in an
+ object). Undefined values are not JSON types and may not appear in JSON
+ arrays and objects, but this function does return the QCborValue undefined
+ value if the corresponding QJsonValue is undefined.
+
+ \sa toJsonValue(), fromVariant(), QCborArray::fromJsonArray(), QCborMap::fromJsonObject()
+ */
+QCborValue QCborValue::fromJsonValue(const QJsonValue &v)
+{
+ switch (v.type()) {
+ case QJsonValue::Bool:
+ return v.b;
+ case QJsonValue::Double:
+ if (v.dbl == qint64(v.dbl))
+ return qint64(v.dbl);
+ return v.dbl;
+ case QJsonValue::String:
+ return v.toString();
+ case QJsonValue::Array:
+ return QCborArray::fromJsonArray(v.toArray());
+ case QJsonValue::Object:
+ return QCborMap::fromJsonObject(v.toObject());
+ case QJsonValue::Null:
+ return nullptr;
+ case QJsonValue::Undefined:
+ break;
+ }
+ return QCborValue();
+}
+
+static void appendVariant(QCborContainerPrivate *d, const QVariant &variant)
+{
+ // Handle strings and byte arrays directly, to avoid creating a temporary
+ // dummy container to hold their data.
+ int type = variant.userType();
+ if (type == QVariant::String) {
+ d->append(variant.toString());
+ } else if (type == QVariant::ByteArray) {
+ QByteArray ba = variant.toByteArray();
+ d->appendByteData(ba.constData(), ba.size(), QCborValue::ByteArray);
+ } else {
+ // For everything else, use the function below.
+ d->append(QCborValue::fromVariant(variant));
+ }
+}
+
+/*!
+ Converts the QVariant \a variant into QCborValue and returns it.
+
+ QVariants may contain a large list of different meta types, many of which
+ have no corresponding representation in CBOR. That includes all
+ user-defined meta types. When preparing transmission using CBOR, it is
+ suggested to encode carefully each value to prevent loss of representation.
+
+ The following table lists the conversion this function will apply:
+
+ \table
+ \header \li Qt (C++) type \li CBOR type
+ \row \li invalid (QVariant()) \li Undefined
+ \row \li \c bool \li Bool
+ \row \li \c std::nullptr_t \li Null
+ \row \li \c short, \c ushort, \c int, \c uint, \l qint64 \li Integer
+ \row \li \l quint64 \li Integer, but they are cast to \c qint64 first so
+ values higher than 2\sup{63}-1 (\c INT64_MAX) will
+ be wrapped to negative
+ \row \li \c float, \c double \li Double
+ \row \li \l QByteArray \li ByteArray
+ \row \li \l QDateTime \li DateTime
+ \row \li \l QCborSimpleType \li Simple type
+ \row \li \l QJsonArray \li Array, converted using QCborArray::formJsonArray()
+ \row \li \l QJsonDocument \li Array or Map
+ \row \li \l QJsonObject \li Map, converted using QCborMap::fromJsonObject()
+ \row \li \l QJsonValue \li converted using fromJsonValue()
+ \row \li \l QRegularExpression \li RegularExpression
+ \row \li \l QString \li String
+ \row \li \l QStringList \li Array
+ \row \li \l QVariantHash \li Map
+ \row \li \l QVariantList \li Array
+ \row \li \l QVariantMap \li Map
+ \row \li \l QUrl \li Url
+ \row \li \l QUuid \li Uuid
+ \endtable
+
+ For any other types, this function will return Null if the QVariant itself
+ is null, and otherwise will try to convert to string using
+ QVariant::toString(). If the conversion to string fails, this function
+ returns Undefined.
+
+ Please note that the conversions via QVariant::toString() are subject to
+ change at any time. QCborValue may be extended in the future to support
+ more types, which will result in a change in how this function performs
+ conversions.
+
+ \sa toVariant(), fromJsonValue(), QCborArray::toVariantList(), QCborMap::toVariantMap()
+ */
+QCborValue QCborValue::fromVariant(const QVariant &variant)
+{
+ switch (variant.userType()) {
+ case QVariant::Invalid:
+ return {};
+ case QMetaType::Nullptr:
+ return nullptr;
+ case QVariant::Bool:
+ return variant.toBool();
+ case QMetaType::Short:
+ case QMetaType::UShort:
+ case QVariant::Int:
+ case QVariant::LongLong:
+ case QVariant::ULongLong:
+ case QVariant::UInt:
+ return variant.toLongLong();
+ case QMetaType::Float:
+ case QVariant::Double:
+ return variant.toDouble();
+ case QVariant::String:
+ return variant.toString();
+ case QVariant::StringList:
+ return QCborArray::fromStringList(variant.toStringList());
+ case QVariant::ByteArray:
+ return variant.toByteArray();
+ case QVariant::DateTime:
+ return QCborValue(variant.toDateTime());
+ case QVariant::Url:
+ return QCborValue(variant.toUrl());
+ case QVariant::Uuid:
+ return QCborValue(variant.toUuid());
+ case QVariant::List:
+ return QCborArray::fromVariantList(variant.toList());
+ case QVariant::Map:
+ return QCborMap::fromVariantMap(variant.toMap());
+ case QVariant::Hash:
+ return QCborMap::fromVariantHash(variant.toHash());
+#ifndef QT_BOOTSTRAPPED
+ case QVariant::RegularExpression:
+ return QCborValue(variant.toRegularExpression());
+ case QMetaType::QJsonValue:
+ return fromJsonValue(variant.toJsonValue());
+ case QMetaType::QJsonObject:
+ return QCborMap::fromJsonObject(variant.toJsonObject());
+ case QMetaType::QJsonArray:
+ return QCborArray::fromJsonArray(variant.toJsonArray());
+ case QMetaType::QJsonDocument: {
+ QJsonDocument doc = variant.toJsonDocument();
+ if (doc.isArray())
+ return QCborArray::fromJsonArray(doc.array());
+ return QCborMap::fromJsonObject(doc.object());
+ }
+ case QMetaType::QCborValue:
+ return variant.value<QCborValue>();
+ case QMetaType::QCborArray:
+ return variant.value<QCborArray>();
+ case QMetaType::QCborMap:
+ return variant.value<QCborMap>();
+ case QMetaType::QCborSimpleType:
+ return variant.value<QCborSimpleType>();
+#endif
+ default:
+ break;
+ }
+
+ if (variant.isNull())
+ return QCborValue(nullptr);
+
+ QString string = variant.toString();
+ if (string.isNull())
+ return QCborValue(); // undefined
+ return string;
+}
+
+/*!
+ Recursively converts each \l QCborValue in this array using
+ QCborValue::toVariant() and returns the QVariantList composed of the
+ converted items.
+
+ Conversion to \l QVariant is not completely lossless. Please see the
+ documentation in QCborValue::toVariant() for more information.
+
+ \sa fromVariantList(), fromStringList(), toJsonArray(),
+ QCborValue::toVariant(), QCborMap::toVariantMap()
+ */
+QVariantList QCborArray::toVariantList() const
+{
+ QVariantList retval;
+ retval.reserve(size());
+ for (qsizetype i = 0; i < size(); ++i)
+ retval.append(d->valueAt(i).toVariant());
+ return retval;
+}
+
+/*!
+ Returns a QCborArray containing all the strings found in the \a list list.
+
+ \sa fromVariantList(), fromJsonArray()
+ */
+QCborArray QCborArray::fromStringList(const QStringList &list)
+{
+ QCborArray a;
+ a.detach(list.size());
+ for (const QString &s : list)
+ a.d->append(s);
+ return a;
+}
+
+/*!
+ Converts all the items in the \a list to CBOR using
+ QCborValue::fromVariant() and returns the array composed of those elements.
+
+ Conversion from \l QVariant is not completely lossless. Please see the
+ documentation in QCborValue::fromVariant() for more information.
+
+ \sa toVariantList(), fromStringList(), fromJsonArray(), QCborMap::fromVariantMap()
+ */
+QCborArray QCborArray::fromVariantList(const QVariantList &list)
+{
+ QCborArray a;
+ a.detach(list.size());
+ for (const QVariant &v : list)
+ appendVariant(a.d.data(), v);
+ return a;
+}
+
+/*!
+ Converts all JSON items found in the \a array array to CBOR using
+ QCborValue::fromJson(), and returns the CBOR array composed of those
+ elements.
+
+ This conversion is lossless, as the CBOR type system is a superset of
+ JSON's. Moreover, the array returned by this function can be converted back
+ to the original \a array by using toJsonArray().
+
+ \sa toJsonArray(), toVariantList(), QCborValue::fromJsonValue(), QCborMap::fromJsonObject()
+ */
+QCborArray QCborArray::fromJsonArray(const QJsonArray &array)
+{
+ QCborArray a;
+ a.detach(array.size());
+ for (const QJsonValue v : array) {
+ if (v.isString())
+ a.d->append(v.toString());
+ else
+ a.d->append(QCborValue::fromJsonValue(v));
+ }
+ return a;
+}
+
+/*!
+ Converts the CBOR values to QVariant using QCborValue::toVariant() and
+ "stringifies" all the CBOR keys in this map, returning the QVariantMap that
+ results from that association list.
+
+ QVariantMaps have string keys, unlike CBOR, so the conversion of a QCborMap
+ to QVariantMap will imply a step of "stringification" of the key values.
+ See QCborMap::toJsonObject() for details.
+
+ In addition, the conversion to \l QVariant is not completely lossless.
+ Please see the documentation in QCborValue::toVariant() for more
+ information.
+
+ \sa fromVariantMap(), toVariantHash(), toJsonObject(), QCborValue::toVariant(),
+ QCborArray::toVariantList()
+ */
+QVariantMap QCborMap::toVariantMap() const
+{
+ QVariantMap retval;
+ for (qsizetype i = 0; i < 2 * size(); i += 2)
+ retval.insert(makeString(d.data(), i), d->valueAt(i + 1).toVariant());
+ return retval;
+}
+
+/*!
+ Converts the CBOR values to QVariant using QCborValue::toVariant() and
+ "stringifies" all the CBOR keys in this map, returning the QVariantHash that
+ results from that association list.
+
+ QVariantMaps have string keys, unlike CBOR, so the conversion of a QCborMap
+ to QVariantMap will imply a step of "stringification" of the key values.
+ See QCborMap::toJsonObject() for details.
+
+ In addition, the conversion to \l QVariant is not completely lossless.
+ Please see the documentation in QCborValue::toVariant() for more
+ information.
+
+ \sa fromVariantHash(), toVariantMap(), toJsonObject(), QCborValue::toVariant(),
+ QCborArray::toVariantList()
+ */
+QVariantHash QCborMap::toVariantHash() const
+{
+ QVariantHash retval;
+ retval.reserve(size());
+ for (qsizetype i = 0; i < 2 * size(); i += 2)
+ retval.insert(makeString(d.data(), i), d->valueAt(i + 1).toVariant());
+ return retval;
+}
+
+/*!
+ Converts all the items in \a map to CBOR using QCborValue::fromVariant()
+ and returns the map composed of those elements.
+
+ Conversion from \l QVariant is not completely lossless. Please see the
+ documentation in QCborValue::fromVariant() for more information.
+
+ \sa toVariantMap(), fromVariantHash(), fromJsonObject(), QCborValue::fromVariant()
+ */
+QCborMap QCborMap::fromVariantMap(const QVariantMap &map)
+{
+ QCborMap m;
+ m.detach(map.size());
+ QCborContainerPrivate *d = m.d.data();
+
+ auto it = map.begin();
+ auto end = map.end();
+ for ( ; it != end; ++it) {
+ d->append(it.key());
+ appendVariant(d, it.value());
+ }
+ return m;
+}
+
+/*!
+ Converts all the items in \a hash to CBOR using QCborValue::fromVariant()
+ and returns the map composed of those elements.
+
+ Conversion from \l QVariant is not completely lossless. Please see the
+ documentation in QCborValue::fromVariant() for more information.
+
+ \sa toVariantHash(), fromVariantMap(), fromJsonObject(), QCborValue::fromVariant()
+ */
+QCborMap QCborMap::fromVariantHash(const QVariantHash &hash)
+{
+ QCborMap m;
+ m.detach(hash.size());
+ QCborContainerPrivate *d = m.d.data();
+
+ auto it = hash.begin();
+ auto end = hash.end();
+ for ( ; it != end; ++it) {
+ d->append(it.key());
+ appendVariant(d, it.value());
+ }
+ return m;
+}
+
+/*!
+ Converts all JSON items found in the \a obj object to CBOR using
+ QCborValue::fromJson(), and returns the map composed of those elements.
+
+ This conversion is lossless, as the CBOR type system is a superset of
+ JSON's. Moreover, the map returned by this function can be converted back
+ to the original \a obj by using toJsonObject().
+
+ \sa toJsonObject(), toVariantMap(), QCborValue::fromJsonValue(), QCborArray::fromJsonArray()
+ */
+QCborMap QCborMap::fromJsonObject(const QJsonObject &obj)
+{
+ QCborMap m;
+ m.detach(obj.size());
+ QCborContainerPrivate *d = m.d.data();
+
+ auto it = obj.begin();
+ auto end = obj.end();
+ for ( ; it != end; ++it) {
+ d->append(it.key());
+ if (it.value().isString())
+ d->append(it.value().toString());
+ else
+ d->append(QCborValue::fromJsonValue(it.value()));
+ }
+ return m;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/serialization/qjsondocument.cpp b/src/corelib/serialization/qjsondocument.cpp
index 5018f7c267..0cd86d3ded 100644
--- a/src/corelib/serialization/qjsondocument.cpp
+++ b/src/corelib/serialization/qjsondocument.cpp
@@ -350,22 +350,10 @@ QByteArray QJsonDocument::toJson() const
when converting to a QJsonDocument using toJson().
\value Indented Defines human readable output as follows:
- \code
- {
- "Array": [
- true,
- 999,
- "string"
- ],
- "Key": "Value",
- "null": null
- }
- \endcode
+ \snippet code/src_corelib_serialization_qjsondocument.cpp 0
\value Compact Defines a compact output as follows:
- \code
- {"Array":[true,999,"string"],"Key":"Value","null":null}
- \endcode
+ \snippet code/src_corelib_serialization_qjsondocument.cpp 1
*/
/*!
diff --git a/src/corelib/serialization/qjsonobject.cpp b/src/corelib/serialization/qjsonobject.cpp
index 4a316c8a6f..950bec535b 100644
--- a/src/corelib/serialization/qjsonobject.cpp
+++ b/src/corelib/serialization/qjsonobject.cpp
@@ -1292,6 +1292,17 @@ void QJsonObject::setValueAt(int i, const QJsonValue &val)
insert(e->key(), val);
}
+uint qHash(const QJsonObject &object, uint seed)
+{
+ QtPrivate::QHashCombine hash;
+ for (auto it = object.begin(), end = object.end(); it != end; ++it) {
+ const QString key = it.key();
+ const QJsonValue value = it.value();
+ seed = hash(seed, std::pair<const QString&, const QJsonValue&>(key, value));
+ }
+ return seed;
+}
+
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
QDebug operator<<(QDebug dbg, const QJsonObject &o)
{
diff --git a/src/corelib/serialization/qjsonobject.h b/src/corelib/serialization/qjsonobject.h
index 610bce694c..be42d3747a 100644
--- a/src/corelib/serialization/qjsonobject.h
+++ b/src/corelib/serialization/qjsonobject.h
@@ -262,6 +262,8 @@ private:
Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonObject)
+Q_CORE_EXPORT uint qHash(const QJsonObject &object, uint seed = 0);
+
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonObject &);
#endif
diff --git a/src/corelib/serialization/qjsonparser.cpp b/src/corelib/serialization/qjsonparser.cpp
index 39738b90a8..bfba95520e 100644
--- a/src/corelib/serialization/qjsonparser.cpp
+++ b/src/corelib/serialization/qjsonparser.cpp
@@ -304,6 +304,7 @@ QJsonDocument Parser::parse(QJsonParseError *error)
// allocate some space
dataLength = qMax(end - json, (ptrdiff_t) 256);
data = (char *)malloc(dataLength);
+ Q_CHECK_PTR(data);
// fill in Header data
QJsonPrivate::Header *h = (QJsonPrivate::Header *)data;
diff --git a/src/corelib/serialization/qjsonvalue.cpp b/src/corelib/serialization/qjsonvalue.cpp
index aa44305fce..2c04da4885 100644
--- a/src/corelib/serialization/qjsonvalue.cpp
+++ b/src/corelib/serialization/qjsonvalue.cpp
@@ -46,6 +46,11 @@
#include <qstringlist.h>
#include <qdebug.h>
+#ifndef QT_BOOTSTRAPPED
+# include <qcborarray.h>
+# include <qcbormap.h>
+#endif
+
#include "qjson_p.h"
QT_BEGIN_NAMESPACE
@@ -423,6 +428,25 @@ QJsonValue &QJsonValue::operator =(const QJsonValue &other)
\li QMetaType::QUuid
\endlist
\li QJsonValue::String. Since Qt 5.11, the resulting string will not include braces
+ \row
+ \li
+ \list
+ \li QMetaType::QCborValue
+ \endlist
+ \li Whichever type QCborValue::toJsonValue() returns.
+ \row
+ \li
+ \list
+ \li QMetaType::QCborArray
+ \endlist
+ \li QJsonValue::Array. See QCborValue::toJsonValue() for conversion restrictions.
+ \row
+ \li
+ \list
+ \li QMetaType::QCborMap
+ \endlist
+ \li QJsonValue::Map. See QCborValue::toJsonValue() for conversion restrictions and the
+ "stringification" of map keys.
\endtable
For all other QVariant types a conversion to a QString will be attempted. If the returned string
@@ -469,6 +493,12 @@ QJsonValue QJsonValue::fromVariant(const QVariant &variant)
QJsonDocument doc = variant.toJsonDocument();
return doc.isArray() ? QJsonValue(doc.array()) : QJsonValue(doc.object());
}
+ case QMetaType::QCborValue:
+ return variant.value<QCborValue>().toJsonValue();
+ case QMetaType::QCborArray:
+ return variant.value<QCborArray>().toJsonArray();
+ case QMetaType::QCborMap:
+ return variant.value<QCborMap>().toJsonObject();
#endif
default:
break;
@@ -846,6 +876,28 @@ QJsonValue QJsonValueRef::toValue() const
return o->valueAt(index);
}
+uint qHash(const QJsonValue &value, uint seed)
+{
+ switch (value.type()) {
+ case QJsonValue::Null:
+ return qHash(nullptr, seed);
+ case QJsonValue::Bool:
+ return qHash(value.toBool(), seed);
+ case QJsonValue::Double:
+ return qHash(value.toDouble(), seed);
+ case QJsonValue::String:
+ return qHash(value.toString(), seed);
+ case QJsonValue::Array:
+ return qHash(value.toArray(), seed);
+ case QJsonValue::Object:
+ return qHash(value.toObject(), seed);
+ case QJsonValue::Undefined:
+ return seed;
+ }
+ Q_UNREACHABLE();
+ return 0;
+}
+
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
QDebug operator<<(QDebug dbg, const QJsonValue &o)
{
diff --git a/src/corelib/serialization/qjsonvalue.h b/src/corelib/serialization/qjsonvalue.h
index 96538ebbf9..d8e121524d 100644
--- a/src/corelib/serialization/qjsonvalue.h
+++ b/src/corelib/serialization/qjsonvalue.h
@@ -150,6 +150,7 @@ private:
friend class QJsonPrivate::Value;
friend class QJsonArray;
friend class QJsonObject;
+ friend class QCborValue;
friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonValue &);
QJsonValue(QJsonPrivate::Data *d, QJsonPrivate::Base *b, const QJsonPrivate::Value& v);
@@ -246,6 +247,8 @@ public:
Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonValue)
+Q_CORE_EXPORT uint qHash(const QJsonValue &value, uint seed = 0);
+
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonValue &);
#endif
diff --git a/src/corelib/serialization/qtextstream.cpp b/src/corelib/serialization/qtextstream.cpp
index ee3cb4efcb..05a5a55926 100644
--- a/src/corelib/serialization/qtextstream.cpp
+++ b/src/corelib/serialization/qtextstream.cpp
@@ -2595,6 +2595,21 @@ QTextStream &QTextStream::operator<<(const QString &string)
Writes \a string to the stream, and returns a reference to the
QTextStream.
+ \since 5.12
+*/
+QTextStream &QTextStream::operator<<(QStringView string)
+{
+ Q_D(QTextStream);
+ CHECK_VALID_STREAM(*this);
+ d->putString(string.cbegin(), int(string.size()));
+ return *this;
+}
+
+/*!
+ \overload
+
+ Writes \a string to the stream, and returns a reference to the
+ QTextStream.
*/
QTextStream &QTextStream::operator<<(QLatin1String string)
{
diff --git a/src/corelib/serialization/qtextstream.h b/src/corelib/serialization/qtextstream.h
index ee0b09419d..ee90d01779 100644
--- a/src/corelib/serialization/qtextstream.h
+++ b/src/corelib/serialization/qtextstream.h
@@ -184,6 +184,7 @@ public:
QTextStream &operator<<(float f);
QTextStream &operator<<(double f);
QTextStream &operator<<(const QString &s);
+ QTextStream &operator<<(QStringView s);
QTextStream &operator<<(QLatin1String s);
QTextStream &operator<<(const QStringRef &s);
QTextStream &operator<<(const QByteArray &array);
diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp
index f18c4cc8e7..5002848d83 100644
--- a/src/corelib/serialization/qxmlstream.cpp
+++ b/src/corelib/serialization/qxmlstream.cpp
@@ -3956,13 +3956,13 @@ void QXmlStreamWriter::writeCurrentToken(const QXmlStreamReader &reader)
writeEndDocument();
break;
case QXmlStreamReader::StartElement: {
+ writeStartElement(reader.namespaceUri().toString(), reader.name().toString());
QXmlStreamNamespaceDeclarations namespaceDeclarations = reader.namespaceDeclarations();
for (int i = 0; i < namespaceDeclarations.size(); ++i) {
const QXmlStreamNamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.at(i);
writeNamespace(namespaceDeclaration.namespaceUri().toString(),
namespaceDeclaration.prefix().toString());
}
- writeStartElement(reader.namespaceUri().toString(), reader.name().toString());
writeAttributes(reader.attributes());
} break;
case QXmlStreamReader::EndElement:
diff --git a/src/corelib/serialization/serialization.pri b/src/corelib/serialization/serialization.pri
index 3d039dc30f..4f2dc64e4f 100644
--- a/src/corelib/serialization/serialization.pri
+++ b/src/corelib/serialization/serialization.pri
@@ -1,6 +1,12 @@
# Qt data formats core module
HEADERS += \
+ serialization/qcborarray.h \
+ serialization/qcborcommon.h \
+ serialization/qcbormap.h \
+ serialization/qcborvalue.h \
+ serialization/qcborvalue_p.h \
+ serialization/qcborstream.h \
serialization/qdatastream.h \
serialization/qdatastream_p.h \
serialization/qjson_p.h \
@@ -17,8 +23,12 @@ HEADERS += \
serialization/qxmlutils_p.h
SOURCES += \
+ serialization/qcborstream.cpp \
+ serialization/qcbordiagnostic.cpp \
+ serialization/qcborvalue.cpp \
serialization/qdatastream.cpp \
serialization/qjson.cpp \
+ serialization/qjsoncbor.cpp \
serialization/qjsondocument.cpp \
serialization/qjsonobject.cpp \
serialization/qjsonarray.cpp \
@@ -28,3 +38,9 @@ SOURCES += \
serialization/qtextstream.cpp \
serialization/qxmlstream.cpp \
serialization/qxmlutils.cpp
+
+false: SOURCES += \
+ serialization/qcborarray.cpp \
+ serialization/qcbormap.cpp
+
+INCLUDEPATH += ../3rdparty/tinycbor/src
diff --git a/src/corelib/statemachine/qhistorystate.cpp b/src/corelib/statemachine/qhistorystate.cpp
index d4fb214a31..ccf04d4799 100644
--- a/src/corelib/statemachine/qhistorystate.cpp
+++ b/src/corelib/statemachine/qhistorystate.cpp
@@ -126,6 +126,25 @@ QT_BEGIN_NAMESPACE
descendant state the parent was in the last time it was exited.
*/
+namespace {
+class DefaultStateTransition: public QAbstractTransition
+{
+ Q_OBJECT
+
+public:
+ DefaultStateTransition(QHistoryState *source, QAbstractState *target);
+
+protected:
+ // It doesn't matter whether this transition matches any event or not. It is always associated
+ // with a QHistoryState, and as soon as the state-machine detects that it enters a history
+ // state, it will handle this transition as a special case. The history state itself is never
+ // entered either: either the stored configuration will be used, or the target(s) of this
+ // transition are used.
+ bool eventTest(QEvent *event) override { Q_UNUSED(event); return false; }
+ void onTransition(QEvent *event) override { Q_UNUSED(event); }
+};
+}
+
QHistoryStatePrivate::QHistoryStatePrivate()
: QAbstractStatePrivate(HistoryState)
, defaultTransition(0)
@@ -312,4 +331,4 @@ bool QHistoryState::event(QEvent *e)
QT_END_NAMESPACE
#include "moc_qhistorystate.cpp"
-#include "moc_qhistorystate_p.cpp"
+#include "qhistorystate.moc"
diff --git a/src/corelib/statemachine/qhistorystate_p.h b/src/corelib/statemachine/qhistorystate_p.h
index d22e5c4aaf..18d571feb7 100644
--- a/src/corelib/statemachine/qhistorystate_p.h
+++ b/src/corelib/statemachine/qhistorystate_p.h
@@ -75,23 +75,6 @@ public:
QList<QAbstractState*> configuration;
};
-class DefaultStateTransition: public QAbstractTransition
-{
- Q_OBJECT
-
-public:
- DefaultStateTransition(QHistoryState *source, QAbstractState *target);
-
-protected:
- // It doesn't matter whether this transition matches any event or not. It is always associated
- // with a QHistoryState, and as soon as the state-machine detects that it enters a history
- // state, it will handle this transition as a special case. The history state itself is never
- // entered either: either the stored configuration will be used, or the target(s) of this
- // transition are used.
- bool eventTest(QEvent *event) override { Q_UNUSED(event); return false; }
- void onTransition(QEvent *event) override { Q_UNUSED(event); }
-};
-
QT_END_NAMESPACE
#endif // QHISTORYSTATE_P_H
diff --git a/src/corelib/thread/qfuture.h b/src/corelib/thread/qfuture.h
index af599c26db..a456dd9139 100644
--- a/src/corelib/thread/qfuture.h
+++ b/src/corelib/thread/qfuture.h
@@ -136,6 +136,7 @@ public:
inline const_iterator operator-(int j) const { return const_iterator(future, index - j); }
inline const_iterator &operator+=(int j) { index += j; return *this; }
inline const_iterator &operator-=(int j) { index -= j; return *this; }
+ friend inline const_iterator operator+(int j, const_iterator k) { return k + j; }
private:
QFuture const * future;
int index;
diff --git a/src/corelib/thread/qfutureinterface.h b/src/corelib/thread/qfutureinterface.h
index 3dd236752c..d5e2401eee 100644
--- a/src/corelib/thread/qfutureinterface.h
+++ b/src/corelib/thread/qfutureinterface.h
@@ -178,7 +178,7 @@ public:
inline void reportResult(const T *result, int index = -1);
inline void reportResult(const T &result, int index = -1);
inline void reportResults(const QVector<T> &results, int beginIndex = -1, int count = -1);
- inline void reportFinished(const T *result = 0);
+ inline void reportFinished(const T *result = nullptr);
inline const T &resultReference(int index) const;
inline const T *resultPointer(int index) const;
diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp
index 63fb6f3efb..3881ac017e 100644
--- a/src/corelib/thread/qmutex.cpp
+++ b/src/corelib/thread/qmutex.cpp
@@ -42,8 +42,6 @@
#include "qplatformdefs.h"
#include "qmutex.h"
#include <qdebug.h>
-
-#ifndef QT_NO_THREAD
#include "qatomic.h"
#include "qelapsedtimer.h"
#include "qthread.h"
@@ -739,5 +737,3 @@ QT_END_NAMESPACE
#else
# include "qmutex_unix.cpp"
#endif
-
-#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h
index 7cda53db5f..837355a602 100644
--- a/src/corelib/thread/qmutex.h
+++ b/src/corelib/thread/qmutex.h
@@ -54,7 +54,7 @@ class tst_QMutex;
QT_BEGIN_NAMESPACE
-#if !defined(QT_NO_THREAD) || defined(Q_CLANG_QDOC)
+#if QT_CONFIG(thread) || defined(Q_CLANG_QDOC)
#ifdef Q_OS_LINUX
# define QT_MUTEX_LOCK_NOEXCEPT Q_DECL_NOTHROW
@@ -250,7 +250,7 @@ private:
quintptr val;
};
-#else // QT_NO_THREAD && !Q_CLANG_QDOC
+#else // !QT_CONFIG(thread) && !Q_CLANG_QDOC
class Q_CORE_EXPORT QMutex
{
@@ -301,7 +301,7 @@ private:
typedef QMutex QBasicMutex;
-#endif // QT_NO_THREAD && !Q_CLANG_QDOC
+#endif // !QT_CONFIG(thread) && !Q_CLANG_QDOC
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qmutex_linux.cpp b/src/corelib/thread/qmutex_linux.cpp
index d3d97ea108..507e72cb76 100644
--- a/src/corelib/thread/qmutex_linux.cpp
+++ b/src/corelib/thread/qmutex_linux.cpp
@@ -40,8 +40,6 @@
#include "qplatformdefs.h"
#include "qmutex.h"
-
-#ifndef QT_NO_THREAD
#include "qatomic.h"
#include "qmutex_p.h"
#include "qfutex_p.h"
@@ -54,7 +52,6 @@
# define FUTEX_PRIVATE_FLAG 0
#endif
-
QT_BEGIN_NAMESPACE
using namespace QtFutex;
@@ -183,5 +180,3 @@ void QBasicMutex::unlockInternal() Q_DECL_NOTHROW
}
QT_END_NAMESPACE
-
-#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/qmutex_mac.cpp b/src/corelib/thread/qmutex_mac.cpp
index 67498611c9..9a8d9bc750 100644
--- a/src/corelib/thread/qmutex_mac.cpp
+++ b/src/corelib/thread/qmutex_mac.cpp
@@ -39,9 +39,6 @@
#include "qplatformdefs.h"
#include "qmutex.h"
-
-#if !defined(QT_NO_THREAD)
-
#include "qmutex_p.h"
#include <mach/mach.h>
@@ -89,5 +86,3 @@ void QMutexPrivate::wakeUp() Q_DECL_NOTHROW
QT_END_NAMESPACE
-
-#endif //QT_NO_THREAD
diff --git a/src/corelib/thread/qmutex_p.h b/src/corelib/thread/qmutex_p.h
index 4e6f522a37..ec9bfc1152 100644
--- a/src/corelib/thread/qmutex_p.h
+++ b/src/corelib/thread/qmutex_p.h
@@ -58,6 +58,7 @@
#include <QtCore/qnamespace.h>
#include <QtCore/qmutex.h>
#include <QtCore/qatomic.h>
+#include <QtCore/qdeadlinetimer.h>
#if defined(Q_OS_MAC)
# include <mach/semaphore.h>
@@ -146,7 +147,7 @@ public:
// helper functions for qmutex_unix.cpp and qwaitcondition_unix.cpp
// they are in qwaitcondition_unix.cpp actually
void qt_initialize_pthread_cond(pthread_cond_t *cond, const char *where);
-void qt_abstime_for_timeout(struct timespec *ts, int timeout);
+void qt_abstime_for_timeout(struct timespec *ts, QDeadlineTimer deadline);
#endif
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp
index 3e1e531be4..3ee24a292c 100644
--- a/src/corelib/thread/qmutex_unix.cpp
+++ b/src/corelib/thread/qmutex_unix.cpp
@@ -42,8 +42,6 @@
#include "qmutex.h"
#include "qstring.h"
#include "qelapsedtimer.h"
-
-#ifndef QT_NO_THREAD
#include "qatomic.h"
#include "qmutex_p.h"
#include <errno.h>
@@ -130,7 +128,7 @@ bool QMutexPrivate::wait(int timeout)
errorCode = pthread_cond_wait(&cond, &mutex);
} else {
timespec ti;
- qt_abstime_for_timeout(&ti, timeout);
+ qt_abstime_for_timeout(&ti, QDeadlineTimer(timeout));
errorCode = pthread_cond_timedwait(&cond, &mutex, &ti);
}
if (errorCode) {
@@ -159,5 +157,3 @@ void QMutexPrivate::wakeUp() Q_DECL_NOTHROW
#endif
QT_END_NAMESPACE
-
-#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/qmutexpool.cpp b/src/corelib/thread/qmutexpool.cpp
index 90b6989467..3f9e8da942 100644
--- a/src/corelib/thread/qmutexpool.cpp
+++ b/src/corelib/thread/qmutexpool.cpp
@@ -40,8 +40,6 @@
#include "qatomic.h"
#include "qmutexpool_p.h"
-#ifndef QT_NO_THREAD
-
QT_BEGIN_NAMESPACE
Q_GLOBAL_STATIC_WITH_ARGS(QMutexPool, globalMutexPool, (QMutex::Recursive))
@@ -148,5 +146,3 @@ QMutex *QMutexPool::globalInstanceGet(const void *address)
}
QT_END_NAMESPACE
-
-#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/qmutexpool_p.h b/src/corelib/thread/qmutexpool_p.h
index 58d853b0e3..89d006ac29 100644
--- a/src/corelib/thread/qmutexpool_p.h
+++ b/src/corelib/thread/qmutexpool_p.h
@@ -56,7 +56,7 @@
#include "QtCore/qmutex.h"
#include "QtCore/qvarlengtharray.h"
-#ifndef QT_NO_THREAD
+QT_REQUIRE_CONFIG(thread);
QT_BEGIN_NAMESPACE
@@ -85,6 +85,4 @@ private:
QT_END_NAMESPACE
-#endif // QT_NO_THREAD
-
#endif // QMUTEXPOOL_P_H
diff --git a/src/corelib/thread/qreadwritelock.cpp b/src/corelib/thread/qreadwritelock.cpp
index 42befc4b80..d7cf7a7284 100644
--- a/src/corelib/thread/qreadwritelock.cpp
+++ b/src/corelib/thread/qreadwritelock.cpp
@@ -42,7 +42,6 @@
#include "qplatformdefs.h"
#include "qreadwritelock.h"
-#ifndef QT_NO_THREAD
#include "qmutex.h"
#include "qthread.h"
#include "qwaitcondition.h"
@@ -623,14 +622,14 @@ QReadWriteLockPrivate *QReadWriteLockPrivate::allocate()
QReadWriteLockPrivate *d = &(*freelist)[i];
d->id = i;
Q_ASSERT(!d->recursive);
- Q_ASSERT(!d->waitingReaders && !d->waitingReaders && !d->readerCount && !d->writerCount);
+ Q_ASSERT(!d->waitingReaders && !d->waitingWriters && !d->readerCount && !d->writerCount);
return d;
}
void QReadWriteLockPrivate::release()
{
Q_ASSERT(!recursive);
- Q_ASSERT(!waitingReaders && !waitingReaders && !readerCount && !writerCount);
+ Q_ASSERT(!waitingReaders && !waitingWriters && !readerCount && !writerCount);
freelist->release(id);
}
@@ -781,5 +780,3 @@ void QReadWriteLockPrivate::release()
*/
QT_END_NAMESPACE
-
-#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/qreadwritelock.h b/src/corelib/thread/qreadwritelock.h
index ecdb98f2f5..65fa76fd6d 100644
--- a/src/corelib/thread/qreadwritelock.h
+++ b/src/corelib/thread/qreadwritelock.h
@@ -45,7 +45,7 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
class QReadWriteLockPrivate;
@@ -174,7 +174,7 @@ inline QWriteLocker::QWriteLocker(QReadWriteLock *areadWriteLock)
#pragma warning( pop )
#endif
-#else // QT_NO_THREAD
+#else // QT_CONFIG(thread)
class Q_CORE_EXPORT QReadWriteLock
{
@@ -225,7 +225,7 @@ private:
Q_DISABLE_COPY(QWriteLocker)
};
-#endif // QT_NO_THREAD
+#endif // QT_CONFIG(thread)
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qreadwritelock_p.h b/src/corelib/thread/qreadwritelock_p.h
index 04dd45a2e1..31da2401c0 100644
--- a/src/corelib/thread/qreadwritelock_p.h
+++ b/src/corelib/thread/qreadwritelock_p.h
@@ -54,9 +54,9 @@
#include <QtCore/private/qglobal_p.h>
#include <QtCore/qhash.h>
-#include <QtCore/QWaitCondition>
+#include <QtCore/qwaitcondition.h>
-#ifndef QT_NO_THREAD
+QT_REQUIRE_CONFIG(thread);
QT_BEGIN_NAMESPACE
@@ -99,6 +99,4 @@ public:
QT_END_NAMESPACE
-#endif // QT_NO_THREAD
-
#endif // QREADWRITELOCK_P_H
diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp
index 74e0746f43..aa04fb10ff 100644
--- a/src/corelib/thread/qsemaphore.cpp
+++ b/src/corelib/thread/qsemaphore.cpp
@@ -39,8 +39,6 @@
****************************************************************************/
#include "qsemaphore.h"
-
-#ifndef QT_NO_THREAD
#include "qmutex.h"
#include "qfutex_p.h"
#include "qwaitcondition.h"
@@ -487,11 +485,9 @@ bool QSemaphore::tryAcquire(int n, int timeout)
QDeadlineTimer timer(timeout);
QMutexLocker locker(&d->mutex);
- qint64 remainingTime = timer.remainingTime();
- while (n > d->avail && remainingTime != 0) {
- if (!d->cond.wait(locker.mutex(), remainingTime))
+ while (n > d->avail && !timer.hasExpired()) {
+ if (!d->cond.wait(locker.mutex(), timer))
return false;
- remainingTime = timer.remainingTime();
}
if (n > d->avail)
return false;
@@ -519,10 +515,7 @@ bool QSemaphore::tryAcquire(int n, int timeout)
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
+ \snippet code/src_corelib_thread_qsemaphore.cpp 4
If an early return is taken or an exception is thrown before the
\c{sem.release()} call is reached, the semaphore is not released,
@@ -531,11 +524,7 @@ bool QSemaphore::tryAcquire(int n, int timeout)
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
+ \snippet code/src_corelib_thread_qsemaphore.cpp 5
this can no longer happen, because the compiler will make sure that
the QSemaphoreReleaser destructor is always called, and therefore
@@ -545,17 +534,7 @@ bool QSemaphore::tryAcquire(int n, int timeout)
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
+ \snippet code/src_corelib_thread_qsemaphore.cpp 6
A QSemaphoreReleaser can be canceled by a call to cancel(). A canceled
semaphore releaser will no longer call QSemaphore::release() in its
@@ -639,14 +618,8 @@ bool QSemaphore::tryAcquire(int n, int timeout)
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
+ \snippet code/src_corelib_thread_qsemaphore.cpp 7
*/
QT_END_NAMESPACE
-
-#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/qsemaphore.h b/src/corelib/thread/qsemaphore.h
index 2639085e99..b830ff1bfd 100644
--- a/src/corelib/thread/qsemaphore.h
+++ b/src/corelib/thread/qsemaphore.h
@@ -42,10 +42,9 @@
#include <QtCore/qglobal.h>
-QT_BEGIN_NAMESPACE
-
+QT_REQUIRE_CONFIG(thread);
-#ifndef QT_NO_THREAD
+QT_BEGIN_NAMESPACE
class QSemaphorePrivate;
@@ -113,8 +112,6 @@ private:
int m_n;
};
-#endif // QT_NO_THREAD
-
QT_END_NAMESPACE
#endif // QSEMAPHORE_H
diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp
index 23606411ff..d2d6435004 100644
--- a/src/corelib/thread/qthread.cpp
+++ b/src/corelib/thread/qthread.cpp
@@ -103,7 +103,7 @@ QThreadData::~QThreadData()
void QThreadData::ref()
{
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
(void) _ref.ref();
Q_ASSERT(_ref.load() != 0);
#endif
@@ -111,12 +111,20 @@ void QThreadData::ref()
void QThreadData::deref()
{
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
if (!_ref.deref())
delete this;
#endif
}
+QAbstractEventDispatcher *QThreadData::createEventDispatcher()
+{
+ QAbstractEventDispatcher *ed = QThreadPrivate::createEventDispatcher(this);
+ eventDispatcher.storeRelease(ed);
+ ed->startingUp();
+ return ed;
+}
+
/*
QAdoptedThread
*/
@@ -126,7 +134,7 @@ QAdoptedThread::QAdoptedThread(QThreadData *data)
{
// thread should be running and not finished for the lifetime
// of the application (even if QCoreApplication goes away)
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
d_func()->running = true;
d_func()->finished = false;
init();
@@ -140,12 +148,13 @@ QAdoptedThread::~QAdoptedThread()
// fprintf(stderr, "~QAdoptedThread = %p\n", this);
}
+#if QT_CONFIG(thread)
void QAdoptedThread::run()
{
// this function should never be called
qFatal("QAdoptedThread::run(): Internal error, this implementation should never be called.");
}
-#ifndef QT_NO_THREAD
+
/*
QThreadPrivate
*/
@@ -747,31 +756,112 @@ int QThread::loopLevel() const
return d->data->eventLoops.size();
}
-#else // QT_NO_THREAD
+#else // QT_CONFIG(thread)
QThread::QThread(QObject *parent)
- : QObject(*(new QThreadPrivate), (QObject*)0){
+ : QObject(*(new QThreadPrivate), parent)
+{
Q_D(QThread);
d->data->thread = this;
}
+QThread::~QThread()
+{
+
+}
+
+void QThread::run()
+{
+
+}
+
+int QThread::exec()
+{
+ return 0;
+}
+
+void QThread::start(Priority priority)
+{
+ Q_D(QThread);
+ Q_UNUSED(priority);
+ d->running = true;
+}
+
+void QThread::terminate()
+{
+
+}
+
+void QThread::quit()
+{
+
+}
+
+bool QThread::wait(unsigned long time)
+{
+ Q_UNUSED(time);
+ return false;
+}
+
+bool QThread::event(QEvent* event)
+{
+ return QObject::event(event);
+}
+
+Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW
+{
+ return Qt::HANDLE(currentThread());
+}
+
QThread *QThread::currentThread()
{
return QThreadData::current()->thread;
}
-QThreadData* QThreadData::current()
+int QThread::idealThreadCount() Q_DECL_NOTHROW
+{
+ return 1;
+}
+
+void QThread::yieldCurrentThread()
+{
+
+}
+
+bool QThread::isFinished() const
+{
+ return false;
+}
+
+bool QThread::isRunning() const
+{
+ Q_D(const QThread);
+ return d->running;
+}
+
+// No threads: so we can just use static variables
+static QThreadData *data = 0;
+
+QThreadData *QThreadData::current(bool createIfNecessary)
{
- static QThreadData *data = 0; // reinterpret_cast<QThreadData *>(pthread_getspecific(current_thread_data_key));
- if (!data) {
- QScopedPointer<QThreadData> newdata(new QThreadData);
- newdata->thread = new QAdoptedThread(newdata.data());
- data = newdata.take();
+ if (!data && createIfNecessary) {
+ data = new QThreadData;
+ data->thread = new QAdoptedThread(data);
+ data->threadId.store(Qt::HANDLE(data->thread));
data->deref();
+ data->isAdopted = true;
+ if (!QCoreApplicationPrivate::theMainThread)
+ QCoreApplicationPrivate::theMainThread = data->thread.load();
}
return data;
}
+void QThreadData::clearCurrentThreadData()
+{
+ delete data;
+ data = 0;
+}
+
/*!
\internal
*/
@@ -783,7 +873,17 @@ QThread::QThread(QThreadPrivate &dd, QObject *parent)
d->data->thread = this;
}
-#endif // QT_NO_THREAD
+QThreadPrivate::QThreadPrivate(QThreadData *d) : data(d ? d : new QThreadData)
+{
+}
+
+QThreadPrivate::~QThreadPrivate()
+{
+ data->thread = nullptr; // prevent QThreadData from deleting the QThreadPrivate (again).
+ delete data;
+}
+
+#endif // QT_CONFIG(thread)
/*!
\since 5.0
@@ -820,6 +920,8 @@ void QThread::setEventDispatcher(QAbstractEventDispatcher *eventDispatcher)
}
}
+#if QT_CONFIG(thread)
+
/*!
\reimp
*/
@@ -983,6 +1085,8 @@ QDaemonThread::~QDaemonThread()
{
}
+#endif // QT_CONFIG(thread)
+
QT_END_NAMESPACE
#include "moc_qthread.cpp"
diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h
index 3df76077e1..b6c5bf47d0 100644
--- a/src/corelib/thread/qthread.h
+++ b/src/corelib/thread/qthread.h
@@ -66,7 +66,6 @@ class QThreadData;
class QThreadPrivate;
class QAbstractEventDispatcher;
-#ifndef QT_NO_THREAD
class Q_CORE_EXPORT QThread : public QObject
{
Q_OBJECT
@@ -239,29 +238,6 @@ QThread *QThread::create(Function &&f)
#endif // QT_CONFIG(cxx11_future)
-#else // QT_NO_THREAD
-
-class Q_CORE_EXPORT QThread : public QObject
-{
-public:
- static Qt::HANDLE currentThreadId() { return Qt::HANDLE(currentThread()); }
- static QThread* currentThread();
-
-protected:
- QThread(QThreadPrivate &dd, QObject *parent = nullptr);
-
-private:
- explicit QThread(QObject *parent = nullptr);
- static QThread *instance;
-
- friend class QCoreApplication;
- friend class QThreadData;
- friend class QAdoptedThread;
- Q_DECLARE_PRIVATE(QThread)
-};
-
-#endif // QT_NO_THREAD
-
QT_END_NAMESPACE
#endif // QTHREAD_H
diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h
index 46294a5fc8..7d9442ab79 100644
--- a/src/corelib/thread/qthread_p.h
+++ b/src/corelib/thread/qthread_p.h
@@ -57,7 +57,9 @@
#include "QtCore/qthread.h"
#include "QtCore/qmutex.h"
#include "QtCore/qstack.h"
+#if QT_CONFIG(thread)
#include "QtCore/qwaitcondition.h"
+#endif
#include "QtCore/qmap.h"
#include "QtCore/qcoreapplication.h"
#include "private/qobject_p.h"
@@ -141,7 +143,7 @@ private:
using QVector<QPostEvent>::insert;
};
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
class Q_CORE_EXPORT QDaemonThread : public QThread
{
@@ -210,15 +212,17 @@ public:
}
};
-#else // QT_NO_THREAD
+#else // QT_CONFIG(thread)
class QThreadPrivate : public QObjectPrivate
{
public:
- QThreadPrivate(QThreadData *d = 0) : data(d ? d : new QThreadData) {}
- ~QThreadPrivate() { delete data; }
+ QThreadPrivate(QThreadData *d = 0);
+ ~QThreadPrivate();
+ mutable QMutex mutex;
QThreadData *data;
+ bool running = false;
static void setCurrentThread(QThread*) {}
static QThread *threadForId(int) { return QThread::currentThread(); }
@@ -230,7 +234,7 @@ public:
Q_DECLARE_PUBLIC(QThread)
};
-#endif // QT_NO_THREAD
+#endif // QT_CONFIG(thread)
class QThreadData
{
@@ -239,6 +243,9 @@ public:
~QThreadData();
static Q_AUTOTEST_EXPORT QThreadData *current(bool createIfNecessary = true);
+#ifdef Q_OS_WINRT
+ static void setMainThread();
+#endif
static void clearCurrentThreadData();
static QThreadData *get2(QThread *thread)
{ Q_ASSERT_X(thread != 0, "QThread", "internal error"); return thread->d_func()->data; }
@@ -247,7 +254,15 @@ public:
void ref();
void deref();
inline bool hasEventDispatcher() const
- { return eventDispatcher.load() != 0; }
+ { return eventDispatcher.load() != nullptr; }
+ QAbstractEventDispatcher *createEventDispatcher();
+ QAbstractEventDispatcher *ensureEventDispatcher()
+ {
+ QAbstractEventDispatcher *ed = eventDispatcher.load();
+ if (Q_LIKELY(ed))
+ return ed;
+ return createEventDispatcher();
+ }
bool canWaitLocked()
{
@@ -318,7 +333,9 @@ public:
void init();
private:
+#if QT_CONFIG(thread)
void run() override;
+#endif
};
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index 9ad32b162d..329caa02ba 100644
--- a/src/corelib/thread/qthread_unix.cpp
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -103,7 +103,7 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
Q_STATIC_ASSERT(sizeof(pthread_t) <= sizeof(Qt::HANDLE));
@@ -270,7 +270,7 @@ extern "C" {
typedef void*(*QtThreadCallback)(void*);
}
-#endif // QT_NO_THREAD
+#endif // QT_CONFIG(thread)
QAbstractEventDispatcher *QThreadPrivate::createEventDispatcher(QThreadData *data)
{
@@ -295,7 +295,7 @@ QAbstractEventDispatcher *QThreadPrivate::createEventDispatcher(QThreadData *dat
#endif
}
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
#if (defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_QNX))
static void setCurrentThreadName(const char *name)
@@ -339,13 +339,7 @@ void *QThreadPrivate::start(void *arg)
data->quitNow = thr->d_func()->exited;
}
- QAbstractEventDispatcher *eventDispatcher = data->eventDispatcher.load();
- if (!eventDispatcher) {
- eventDispatcher = createEventDispatcher(data);
- data->eventDispatcher.storeRelease(eventDispatcher);
- }
-
- eventDispatcher->startingUp();
+ data->ensureEventDispatcher();
#if (defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_QNX))
{
@@ -519,6 +513,8 @@ void QThread::yieldCurrentThread()
sched_yield();
}
+#endif // QT_CONFIG(thread)
+
static timespec makeTimespec(time_t secs, long nsecs)
{
struct timespec ts;
@@ -542,6 +538,8 @@ void QThread::usleep(unsigned long usecs)
qt_nanosleep(makeTimespec(usecs / 1000 / 1000, usecs % (1000*1000) * 1000));
}
+#if QT_CONFIG(thread)
+
#ifdef QT_HAS_THREAD_PRIORITY_SCHEDULING
#if defined(Q_OS_QNX)
static bool calculateUnixPriority(int priority, int *sched_policy, int *sched_priority)
@@ -841,7 +839,7 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority)
#endif
}
-#endif // QT_NO_THREAD
+#endif // QT_CONFIG(thread)
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
index 4459ae87af..e04d27d7b6 100644
--- a/src/corelib/thread/qthread_win.cpp
+++ b/src/corelib/thread/qthread_win.cpp
@@ -61,9 +61,10 @@
# include <process.h>
#endif // Q_OS_WINRT
-#ifndef QT_NO_THREAD
QT_BEGIN_NAMESPACE
+#if QT_CONFIG(thread)
+
#ifdef Q_OS_WINRT
inline DWORD qWinRTTlsAlloc() {
return FlsAlloc(0);
@@ -139,11 +140,15 @@ QThreadData *QThreadData::current(bool createIfNecessary)
threadData->isAdopted = true;
threadData->threadId.store(reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId())));
+#ifndef Q_OS_WINRT
if (!QCoreApplicationPrivate::theMainThread) {
QCoreApplicationPrivate::theMainThread = threadData->thread.load();
- // TODO: is there a way to reflect the branch's behavior using
- // WinRT API?
} else {
+#else
+ // for winrt the main thread is set explicitly in QCoreApplication's constructor as the
+ // native main thread (Xaml thread) is not Qt's main thread.
+ {
+#endif
HANDLE realHandle = INVALID_HANDLE_VALUE;
DuplicateHandle(GetCurrentProcess(),
GetCurrentThread(),
@@ -158,6 +163,33 @@ QThreadData *QThreadData::current(bool createIfNecessary)
return threadData;
}
+#ifdef Q_OS_WINRT
+void QThreadData::setMainThread()
+{
+ Q_ASSERT(!QCoreApplicationPrivate::theMainThread);
+ qt_create_tls();
+ QThreadData *threadData = reinterpret_cast<QThreadData *>(TlsGetValue(qt_current_thread_data_tls_index));
+ if (!threadData) {
+ threadData = new QThreadData;
+ // This needs to be called prior to new AdoptedThread() to
+ // avoid recursion.
+ TlsSetValue(qt_current_thread_data_tls_index, threadData);
+ QT_TRY {
+ threadData->thread = new QAdoptedThread(threadData);
+ } QT_CATCH(...) {
+ TlsSetValue(qt_current_thread_data_tls_index, 0);
+ threadData->deref();
+ threadData = 0;
+ QT_RETHROW;
+ }
+ threadData->deref();
+ threadData->isAdopted = true;
+ threadData->threadId.store(reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId())));
+ }
+ QCoreApplicationPrivate::theMainThread = threadData->thread.load();
+}
+#endif
+
void QAdoptedThread::init()
{
d_func()->handle = GetCurrentThread();
@@ -259,31 +291,27 @@ DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID)
}
const int handleIndex = offset + ret - WAIT_OBJECT_0;
- if (handleIndex == 0){
- // New handle to watch was added.
+ if (handleIndex == 0) // New handle to watch was added.
continue;
- } else {
-// printf("(qt) - qt_adopted_thread_watcher_function... called\n");
- const int qthreadIndex = handleIndex - 1;
+ const int qthreadIndex = handleIndex - 1;
- qt_adopted_thread_watcher_mutex.lock();
- QThreadData *data = QThreadData::get2(qt_adopted_qthreads.at(qthreadIndex));
- qt_adopted_thread_watcher_mutex.unlock();
- if (data->isAdopted) {
- QThread *thread = data->thread;
- Q_ASSERT(thread);
- QThreadPrivate *thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
- Q_UNUSED(thread_p)
- Q_ASSERT(!thread_p->finished);
- thread_p->finish(thread);
- }
- data->deref();
-
- QMutexLocker lock(&qt_adopted_thread_watcher_mutex);
- CloseHandle(qt_adopted_thread_handles.at(handleIndex));
- qt_adopted_thread_handles.remove(handleIndex);
- qt_adopted_qthreads.remove(qthreadIndex);
+ qt_adopted_thread_watcher_mutex.lock();
+ QThreadData *data = QThreadData::get2(qt_adopted_qthreads.at(qthreadIndex));
+ qt_adopted_thread_watcher_mutex.unlock();
+ if (data->isAdopted) {
+ QThread *thread = data->thread;
+ Q_ASSERT(thread);
+ auto thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
+ Q_UNUSED(thread_p)
+ Q_ASSERT(!thread_p->finished);
+ QThreadPrivate::finish(thread);
}
+ data->deref();
+
+ QMutexLocker lock(&qt_adopted_thread_watcher_mutex);
+ CloseHandle(qt_adopted_thread_handles.at(handleIndex));
+ qt_adopted_thread_handles.remove(handleIndex);
+ qt_adopted_qthreads.remove(qthreadIndex);
}
QThreadData *threadData = reinterpret_cast<QThreadData *>(TlsGetValue(qt_current_thread_data_tls_index));
@@ -317,7 +345,8 @@ void qt_set_thread_name(HANDLE threadId, LPCSTR threadName)
__try
{
- RaiseException(0x406D1388, 0, sizeof(info)/sizeof(DWORD), (const ULONG_PTR*)&info);
+ RaiseException(0x406D1388, 0, sizeof(info)/sizeof(DWORD),
+ reinterpret_cast<const ULONG_PTR*>(&info));
}
__except (EXCEPTION_CONTINUE_EXECUTION)
{
@@ -329,7 +358,7 @@ void qt_set_thread_name(HANDLE threadId, LPCSTR threadName)
** QThreadPrivate
*************************************************************************/
-#endif // QT_NO_THREAD
+#endif // QT_CONFIG(thread)
QAbstractEventDispatcher *QThreadPrivate::createEventDispatcher(QThreadData *data)
{
@@ -341,7 +370,7 @@ QAbstractEventDispatcher *QThreadPrivate::createEventDispatcher(QThreadData *dat
#endif
}
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(void *arg) Q_DECL_NOEXCEPT
{
@@ -359,18 +388,12 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi
data->quitNow = thr->d_func()->exited;
}
- QAbstractEventDispatcher *eventDispatcher = data->eventDispatcher.load();
- if (!eventDispatcher) {
- eventDispatcher = createEventDispatcher(data);
- data->eventDispatcher.storeRelease(eventDispatcher);
- }
-
- eventDispatcher->startingUp();
+ data->ensureEventDispatcher();
#if !defined(QT_NO_DEBUG) && defined(Q_CC_MSVC) && !defined(Q_OS_WINRT)
// sets the name of the current thread.
QByteArray objectName = thr->objectName().toLocal8Bit();
- qt_set_thread_name((HANDLE)-1,
+ qt_set_thread_name(HANDLE(-1),
objectName.isEmpty() ?
thr->metaObject()->className() : objectName.constData());
#endif
@@ -449,6 +472,8 @@ void QThread::yieldCurrentThread()
#endif
}
+#endif // QT_CONFIG(thread)
+
void QThread::sleep(unsigned long secs)
{
::Sleep(secs * 1000);
@@ -464,6 +489,8 @@ void QThread::usleep(unsigned long usecs)
::Sleep((usecs / 1000) + 1);
}
+#if QT_CONFIG(thread)
+
void QThread::start(Priority priority)
{
Q_D(QThread);
@@ -509,12 +536,13 @@ void QThread::start(Priority priority)
this, CREATE_SUSPENDED, &(d->id));
#else
// MSVC -MD or -MDd or MinGW build
- d->handle = (Qt::HANDLE) CreateThread(NULL, d->stackSize, (LPTHREAD_START_ROUTINE)QThreadPrivate::start,
- this, CREATE_SUSPENDED, reinterpret_cast<LPDWORD>(&d->id));
+ d->handle = CreateThread(nullptr, d->stackSize,
+ reinterpret_cast<LPTHREAD_START_ROUTINE>(QThreadPrivate::start),
+ this, CREATE_SUSPENDED, reinterpret_cast<LPDWORD>(&d->id));
#endif // Q_OS_WINRT
if (!d->handle) {
- qErrnoWarning(errno, "QThread::start: Failed to create thread");
+ qErrnoWarning("QThread::start: Failed to create thread");
d->running = false;
d->finished = true;
return;
@@ -700,5 +728,6 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority)
}
}
+#endif // QT_CONFIG(thread)
+
QT_END_NAMESPACE
-#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp
index 157cbeaf4d..ea2c611082 100644
--- a/src/corelib/thread/qthreadpool.cpp
+++ b/src/corelib/thread/qthreadpool.cpp
@@ -43,8 +43,6 @@
#include <algorithm>
-#ifndef QT_NO_THREAD
-
QT_BEGIN_NAMESPACE
Q_GLOBAL_STATIC(QThreadPool, theInstance)
@@ -730,5 +728,3 @@ void QThreadPool::cancel(QRunnable *runnable)
QT_END_NAMESPACE
#include "moc_qthreadpool.cpp"
-
-#endif
diff --git a/src/corelib/thread/qthreadpool.h b/src/corelib/thread/qthreadpool.h
index 606e192768..cd27b7c08a 100644
--- a/src/corelib/thread/qthreadpool.h
+++ b/src/corelib/thread/qthreadpool.h
@@ -45,7 +45,7 @@
#include <QtCore/qthread.h>
#include <QtCore/qrunnable.h>
-#ifndef QT_NO_THREAD
+QT_REQUIRE_CONFIG(thread);
QT_BEGIN_NAMESPACE
@@ -97,6 +97,4 @@ public:
QT_END_NAMESPACE
-#endif // QT_NO_THREAD
-
#endif
diff --git a/src/corelib/thread/qthreadpool_p.h b/src/corelib/thread/qthreadpool_p.h
index d03ba9d77f..0e6a00d243 100644
--- a/src/corelib/thread/qthreadpool_p.h
+++ b/src/corelib/thread/qthreadpool_p.h
@@ -59,7 +59,7 @@
#include "QtCore/qqueue.h"
#include "private/qobject_p.h"
-#ifndef QT_NO_THREAD
+QT_REQUIRE_CONFIG(thread);
QT_BEGIN_NAMESPACE
@@ -184,5 +184,4 @@ public:
QT_END_NAMESPACE
-#endif // QT_NO_THREAD
#endif
diff --git a/src/corelib/thread/qthreadstorage.cpp b/src/corelib/thread/qthreadstorage.cpp
index c0b523a431..8b82118a5c 100644
--- a/src/corelib/thread/qthreadstorage.cpp
+++ b/src/corelib/thread/qthreadstorage.cpp
@@ -39,7 +39,6 @@
#include "qthreadstorage.h"
-#ifndef QT_NO_THREAD
#include "qthread.h"
#include "qthread_p.h"
#include "qmutex.h"
@@ -323,6 +322,4 @@ void QThreadStorageData::finish(void **p)
\sa localData(), hasLocalData()
*/
-#endif // QT_NO_THREAD
-
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qthreadstorage.h b/src/corelib/thread/qthreadstorage.h
index fed41a0760..55fc482da3 100644
--- a/src/corelib/thread/qthreadstorage.h
+++ b/src/corelib/thread/qthreadstorage.h
@@ -42,7 +42,7 @@
#include <QtCore/qglobal.h>
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
QT_BEGIN_NAMESPACE
@@ -152,6 +152,81 @@ public:
QT_END_NAMESPACE
-#endif // QT_NO_THREAD
+#else // !QT_CONFIG(thread)
+
+#include <QtCore/qscopedpointer.h>
+
+#include <type_traits>
+
+template <typename T, typename U>
+inline bool qThreadStorage_hasLocalData(const QScopedPointer<T, U> &data)
+{
+ return !!data;
+}
+
+template <typename T, typename U>
+inline bool qThreadStorage_hasLocalData(const QScopedPointer<T*, U> &data)
+{
+ return !!data ? *data != nullptr : false;
+}
+
+template <typename T>
+inline void qThreadStorage_deleteLocalData(T *t)
+{
+ delete t;
+}
+
+template <typename T>
+inline void qThreadStorage_deleteLocalData(T **t)
+{
+ delete *t;
+ delete t;
+}
+
+template <class T>
+class QThreadStorage
+{
+private:
+ struct ScopedPointerThreadStorageDeleter
+ {
+ static inline void cleanup(T *t)
+ {
+ if (t == nullptr)
+ return;
+ qThreadStorage_deleteLocalData(t);
+ }
+ };
+ QScopedPointer<T, ScopedPointerThreadStorageDeleter> data;
+
+public:
+ QThreadStorage() = default;
+ ~QThreadStorage() = default;
+ QThreadStorage(const QThreadStorage &rhs) = delete;
+ QThreadStorage &operator=(const QThreadStorage &rhs) = delete;
+
+ inline bool hasLocalData() const
+ {
+ return qThreadStorage_hasLocalData(data);
+ }
+
+ inline T& localData()
+ {
+ if (!data)
+ data.reset(new T());
+ return *data;
+ }
+
+ inline T localData() const
+ {
+ return !!data ? *data : T();
+ }
+
+ inline void setLocalData(T t)
+ {
+ data.reset(new T(t));
+ }
+};
+
+#endif // QT_CONFIG(thread)
#endif // QTHREADSTORAGE_H
diff --git a/src/corelib/thread/qwaitcondition.h b/src/corelib/thread/qwaitcondition.h
index a0c6766833..11520e4cfe 100644
--- a/src/corelib/thread/qwaitcondition.h
+++ b/src/corelib/thread/qwaitcondition.h
@@ -46,9 +46,9 @@
QT_BEGIN_NAMESPACE
+#if QT_CONFIG(thread)
-#ifndef QT_NO_THREAD
-
+class QDeadlineTimer;
class QWaitConditionPrivate;
class QMutex;
class QReadWriteLock;
@@ -59,8 +59,11 @@ public:
QWaitCondition();
~QWaitCondition();
+ // ### Qt 6: remove unsigned long overloads
bool wait(QMutex *lockedMutex, unsigned long time = ULONG_MAX);
+ bool wait(QMutex *lockedMutex, QDeadlineTimer deadline);
bool wait(QReadWriteLock *lockedReadWriteLock, unsigned long time = ULONG_MAX);
+ bool wait(QReadWriteLock *lockedReadWriteLock, QDeadlineTimer deadline);
void wakeOne();
void wakeAll();
@@ -94,7 +97,7 @@ public:
void wakeAll() {}
};
-#endif // QT_NO_THREAD
+#endif // QT_CONFIG(thread)
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qwaitcondition_unix.cpp b/src/corelib/thread/qwaitcondition_unix.cpp
index 6adee5412e..c93328b4bc 100644
--- a/src/corelib/thread/qwaitcondition_unix.cpp
+++ b/src/corelib/thread/qwaitcondition_unix.cpp
@@ -44,6 +44,8 @@
#include "qreadwritelock.h"
#include "qatomic.h"
#include "qstring.h"
+#include "qdeadlinetimer.h"
+#include "private/qdeadlinetimer_p.h"
#include "qelapsedtimer.h"
#include "private/qcore_unix_p.h"
@@ -54,8 +56,6 @@
#include <sys/time.h>
#include <time.h>
-#ifndef QT_NO_THREAD
-
QT_BEGIN_NAMESPACE
#ifdef Q_OS_ANDROID
@@ -93,23 +93,25 @@ void qt_initialize_pthread_cond(pthread_cond_t *cond, const char *where)
pthread_condattr_destroy(&condattr);
}
-void qt_abstime_for_timeout(timespec *ts, int timeout)
+void qt_abstime_for_timeout(timespec *ts, QDeadlineTimer deadline)
{
#ifdef Q_OS_MAC
// on Mac, qt_gettime() (on qelapsedtimer_mac.cpp) returns ticks related to the Mach absolute time
// that doesn't work with pthread
// Mac also doesn't have clock_gettime
struct timeval tv;
+ qint64 nsec = deadline.remainingTimeNSecs();
gettimeofday(&tv, 0);
- ts->tv_sec = tv.tv_sec;
- ts->tv_nsec = tv.tv_usec * 1000;
-#else
- *ts = qt_gettime();
-#endif
+ ts->tv_sec = tv.tv_sec + nsec / (1000 * 1000 * 1000);
+ ts->tv_nsec = tv.tv_usec * 1000 + nsec % (1000 * 1000 * 1000);
- ts->tv_sec += timeout / 1000;
- ts->tv_nsec += timeout % 1000 * Q_UINT64_C(1000) * 1000;
normalizedTimespec(*ts);
+#else
+ // depends on QDeadlineTimer's internals!!
+ Q_STATIC_ASSERT(QDeadlineTimerNanosecondsInT2);
+ ts->tv_sec = deadline._q_data().first;
+ ts->tv_nsec = deadline._q_data().second;
+#endif
}
class QWaitConditionPrivate {
@@ -119,26 +121,27 @@ public:
int waiters;
int wakeups;
- int wait_relative(unsigned long time)
+ int wait_relative(QDeadlineTimer deadline)
{
timespec ti;
#ifdef Q_OS_ANDROID
- if (local_cond_timedwait_relative) {
- ti.tv_sec = time / 1000;
- ti.tv_nsec = time % 1000 * Q_UINT64_C(1000) * 1000;
+ if (!local_condattr_setclock && local_cond_timedwait_relative) {
+ qint64 nsec = deadline.remainingTimeNSecs();
+ ti.tv_sec = nsec / (1000 * 1000 * 1000);
+ ti.tv_nsec = nsec - ti.tv_sec * 1000 * 1000 * 1000;
return local_cond_timedwait_relative(&cond, &mutex, &ti);
}
#endif
- qt_abstime_for_timeout(&ti, time);
+ qt_abstime_for_timeout(&ti, deadline);
return pthread_cond_timedwait(&cond, &mutex, &ti);
}
- bool wait(unsigned long time)
+ bool wait(QDeadlineTimer deadline)
{
int code;
forever {
- if (time != ULONG_MAX) {
- code = wait_relative(time);
+ if (!deadline.isForever()) {
+ code = wait_relative(deadline);
} else {
code = pthread_cond_wait(&cond, &mutex);
}
@@ -201,6 +204,13 @@ void QWaitCondition::wakeAll()
bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
{
+ if (quint64(time) > quint64(std::numeric_limits<qint64>::max()))
+ return wait(mutex, QDeadlineTimer(QDeadlineTimer::Forever));
+ return wait(mutex, QDeadlineTimer(time));
+}
+
+bool QWaitCondition::wait(QMutex *mutex, QDeadlineTimer deadline)
+{
if (! mutex)
return false;
if (mutex->isRecursive()) {
@@ -212,7 +222,7 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
++d->waiters;
mutex->unlock();
- bool returnValue = d->wait(time);
+ bool returnValue = d->wait(deadline);
mutex->lock();
@@ -221,6 +231,11 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
{
+ return wait(readWriteLock, QDeadlineTimer(time));
+}
+
+bool QWaitCondition::wait(QReadWriteLock *readWriteLock, QDeadlineTimer deadline)
+{
if (!readWriteLock)
return false;
auto previousState = readWriteLock->stateForWaitCondition();
@@ -236,7 +251,7 @@ bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
readWriteLock->unlock();
- bool returnValue = d->wait(time);
+ bool returnValue = d->wait(deadline);
if (previousState == QReadWriteLock::LockedForWrite)
readWriteLock->lockForWrite();
@@ -247,5 +262,3 @@ bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
}
QT_END_NAMESPACE
-
-#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/qwaitcondition_win.cpp b/src/corelib/thread/qwaitcondition_win.cpp
index e6610f18c8..a6ad95b397 100644
--- a/src/corelib/thread/qwaitcondition_win.cpp
+++ b/src/corelib/thread/qwaitcondition_win.cpp
@@ -38,14 +38,13 @@
****************************************************************************/
#include "qwaitcondition.h"
+#include "qdeadlinetimer.h"
#include "qnamespace.h"
#include "qmutex.h"
#include "qreadwritelock.h"
#include "qlist.h"
#include "qalgorithms.h"
-#ifndef QT_NO_THREAD
-
#define Q_MUTEX_T void*
#include <private/qmutex_p.h>
#include <private/qreadwritelock_p.h>
@@ -184,6 +183,11 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
return returnValue;
}
+bool QWaitCondition::wait(QMutex *mutex, QDeadlineTimer deadline)
+{
+ return wait(mutex, deadline.remainingTime());
+}
+
bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
{
if (!readWriteLock)
@@ -210,12 +214,16 @@ bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time)
return returnValue;
}
+bool QWaitCondition::wait(QReadWriteLock *readWriteLock, QDeadlineTimer deadline)
+{
+ return wait(readWriteLock, deadline.remainingTime());
+}
+
void QWaitCondition::wakeOne()
{
// wake up the first waiting thread in the queue
QMutexLocker locker(&d->mtx);
- for (int i = 0; i < d->queue.size(); ++i) {
- QWaitConditionEvent *current = d->queue.at(i);
+ for (QWaitConditionEvent *current : qAsConst(d->queue)) {
if (current->wokenUp)
continue;
SetEvent(current->event);
@@ -228,12 +236,10 @@ void QWaitCondition::wakeAll()
{
// wake up the all threads in the queue
QMutexLocker locker(&d->mtx);
- for (int i = 0; i < d->queue.size(); ++i) {
- QWaitConditionEvent *current = d->queue.at(i);
+ for (QWaitConditionEvent *current : qAsConst(d->queue)) {
SetEvent(current->event);
current->wokenUp = true;
}
}
QT_END_NAMESPACE
-#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri
index dae72564b4..22f0de0523 100644
--- a/src/corelib/thread/thread.pri
+++ b/src/corelib/thread/thread.pri
@@ -1,38 +1,66 @@
# Qt core thread module
-# public headers
-HEADERS += thread/qmutex.h \
- thread/qrunnable.h \
- thread/qreadwritelock.h \
- thread/qsemaphore.h \
- thread/qthread.h \
- thread/qthreadpool.h \
- thread/qthreadstorage.h \
- thread/qwaitcondition.h \
- thread/qatomic.h \
- thread/qatomic_bootstrap.h \
- thread/qatomic_cxx11.h \
- thread/qbasicatomic.h \
- thread/qgenericatomic.h
+HEADERS += \
+ thread/qmutex.h \
+ thread/qreadwritelock.h \
+ thread/qrunnable.h \
+ thread/qthread.h \
+ thread/qthreadstorage.h \
+ thread/qwaitcondition.h
-# private headers
-HEADERS += thread/qmutex_p.h \
- thread/qmutexpool_p.h \
- thread/qfutex_p.h \
- thread/qorderedmutexlocker_p.h \
- thread/qreadwritelock_p.h \
- thread/qthread_p.h \
- thread/qthreadpool_p.h
+SOURCES += \
+ thread/qrunnable.cpp \
+ thread/qthread.cpp
-SOURCES += thread/qatomic.cpp \
- thread/qmutex.cpp \
- thread/qreadwritelock.cpp \
- thread/qrunnable.cpp \
- thread/qmutexpool.cpp \
- thread/qsemaphore.cpp \
- thread/qthread.cpp \
- thread/qthreadpool.cpp \
- thread/qthreadstorage.cpp
+win32 {
+ HEADERS += thread/qatomic_msvc.h
+
+ SOURCES += thread/qthread_win.cpp
+} else {
+ SOURCES += thread/qthread_unix.cpp
+}
+
+qtConfig(thread) {
+ HEADERS += \
+ thread/qatomic.h \
+ thread/qatomic_bootstrap.h \
+ thread/qatomic_cxx11.h \
+ thread/qbasicatomic.h \
+ thread/qfutex_p.h \
+ thread/qgenericatomic.h \
+ thread/qmutexpool_p.h \
+ thread/qmutex_p.h \
+ thread/qorderedmutexlocker_p.h \
+ thread/qreadwritelock_p.h \
+ thread/qsemaphore.h \
+ thread/qthreadpool.h \
+ thread/qthreadpool_p.h \
+ thread/qthread_p.h
+
+ SOURCES += \
+ thread/qatomic.cpp \
+ thread/qmutex.cpp \
+ thread/qmutexpool.cpp \
+ thread/qreadwritelock.cpp \
+ thread/qsemaphore.cpp \
+ thread/qthreadpool.cpp \
+ thread/qthreadstorage.cpp
+
+ win32 {
+ SOURCES += \
+ thread/qmutex_win.cpp \
+ thread/qwaitcondition_win.cpp
+ } else {
+ darwin {
+ SOURCES += thread/qmutex_mac.cpp
+ } else: linux {
+ SOURCES += thread/qmutex_linux.cpp
+ } else {
+ SOURCES += thread/qmutex_unix.cpp
+ }
+ SOURCES += thread/qwaitcondition_unix.cpp
+ }
+}
qtConfig(future) {
HEADERS += \
@@ -52,24 +80,4 @@ qtConfig(future) {
thread/qresultstore.cpp
}
-win32 {
- HEADERS += thread/qatomic_msvc.h
-
- SOURCES += \
- thread/qmutex_win.cpp \
- thread/qthread_win.cpp \
- thread/qwaitcondition_win.cpp
-} else {
- darwin {
- SOURCES += thread/qmutex_mac.cpp
- } else: linux {
- SOURCES += thread/qmutex_linux.cpp
- } else {
- SOURCES += thread/qmutex_unix.cpp
- }
- SOURCES += \
- thread/qthread_unix.cpp \
- thread/qwaitcondition_unix.cpp
-}
-
qtConfig(std-atomic64): QMAKE_USE += libatomic
diff --git a/src/corelib/tools/qalgorithms.qdoc b/src/corelib/tools/qalgorithms.qdoc
index f0ac2701e7..a73ec1e22a 100644
--- a/src/corelib/tools/qalgorithms.qdoc
+++ b/src/corelib/tools/qalgorithms.qdoc
@@ -29,6 +29,7 @@
\headerfile <QtAlgorithms>
\title Generic Algorithms
\ingroup funclists
+ \keyword generic algorithms
\brief The <QtAlgorithms> header includes the generic, template-based algorithms.
diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h
index f0cc56e899..a642fb9b39 100644
--- a/src/corelib/tools/qarraydata.h
+++ b/src/corelib/tools/qarraydata.h
@@ -159,6 +159,7 @@ struct QTypedArrayData
inline iterator &operator-=(int j) { i-=j; return *this; }
inline iterator operator+(int j) const { return iterator(i+j); }
inline iterator operator-(int j) const { return iterator(i-j); }
+ friend inline iterator operator+(int j, iterator k) { return k + j; }
inline int operator-(iterator j) const { return i - j.i; }
inline operator T*() const { return i; }
};
@@ -194,6 +195,7 @@ struct QTypedArrayData
inline const_iterator &operator-=(int j) { i-=j; return *this; }
inline const_iterator operator+(int j) const { return const_iterator(i+j); }
inline const_iterator operator-(int j) const { return const_iterator(i-j); }
+ friend inline const_iterator operator+(int j, const_iterator k) { return k + j; }
inline int operator-(const_iterator j) const { return i - j.i; }
inline operator const T*() const { return i; }
};
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index 424420204a..8f2ad8c012 100644
--- a/src/corelib/tools/qbytearray.cpp
+++ b/src/corelib/tools/qbytearray.cpp
@@ -47,6 +47,7 @@
#include "qlocale_p.h"
#include "qlocale_tools_p.h"
#include "private/qnumeric_p.h"
+#include "private/qsimd_p.h"
#include "qstringalgorithms_p.h"
#include "qscopedpointer.h"
#include "qbytearray_p.h"
@@ -356,7 +357,8 @@ char *qstrncpy(char *dst, const char *src, uint len)
Special case 2: Returns an arbitrary non-zero value if \a str1 is
nullptr or \a str2 is nullptr (but not both).
- \sa qstrncmp(), qstricmp(), qstrnicmp(), {8-bit Character Comparisons}
+ \sa qstrncmp(), qstricmp(), qstrnicmp(), {8-bit Character Comparisons},
+ QByteArray::compare()
*/
int qstrcmp(const char *str1, const char *str2)
{
@@ -381,7 +383,8 @@ int qstrcmp(const char *str1, const char *str2)
Special case 2: Returns a random non-zero value if \a str1 is nullptr
or \a str2 is nullptr (but not both).
- \sa qstrcmp(), qstricmp(), qstrnicmp(), {8-bit Character Comparisons}
+ \sa qstrcmp(), qstricmp(), qstrnicmp(), {8-bit Character Comparisons},
+ QByteArray::compare()
*/
/*! \relates QByteArray
@@ -400,21 +403,80 @@ int qstrcmp(const char *str1, const char *str2)
Special case 2: Returns a random non-zero value if \a str1 is nullptr
or \a str2 is nullptr (but not both).
- \sa qstrcmp(), qstrncmp(), qstrnicmp(), {8-bit Character Comparisons}
+ \sa qstrcmp(), qstrncmp(), qstrnicmp(), {8-bit Character Comparisons},
+ QByteArray::compare()
*/
int qstricmp(const char *str1, const char *str2)
{
const uchar *s1 = reinterpret_cast<const uchar *>(str1);
const uchar *s2 = reinterpret_cast<const uchar *>(str2);
- int res;
- uchar c;
- if (!s1 || !s2)
- return s1 ? 1 : (s2 ? -1 : 0);
- for (; !(res = (c = latin1_lowercased[*s1]) - latin1_lowercased[*s2]); s1++, s2++)
- if (!c) // strings are equal
- break;
- return res;
+ if (!s1)
+ return s2 ? -1 : 0;
+ if (!s2)
+ return 1;
+
+ enum { Incomplete = 256 };
+ qptrdiff offset = 0;
+ auto innerCompare = [=, &offset](qptrdiff max, bool unlimited) {
+ max += offset;
+ do {
+ uchar c = latin1_lowercased[s1[offset]];
+ int res = c - latin1_lowercased[s2[offset]];
+ if (Q_UNLIKELY(res))
+ return res;
+ if (Q_UNLIKELY(!c))
+ return 0;
+ ++offset;
+ } while (unlimited || offset < max);
+ return int(Incomplete);
+ };
+
+#if defined(__SSE4_1__) && !(defined(__SANITIZE_ADDRESS__) || QT_HAS_FEATURE(address_sanitizer))
+ enum { PageSize = 4096, PageMask = PageSize - 1 };
+ const __m128i zero = _mm_setzero_si128();
+ forever {
+ // Calculate how many bytes we can load until we cross a page boundary
+ // for either source. This isn't an exact calculation, just something
+ // very quick.
+ quintptr u1 = quintptr(s1 + offset);
+ quintptr u2 = quintptr(s2 + offset);
+ uint n = PageSize - ((u1 | u2) & PageMask);
+
+ qptrdiff maxoffset = offset + n;
+ for ( ; offset + 16 <= maxoffset; offset += sizeof(__m128i)) {
+ // load 16 bytes from either source
+ __m128i a = _mm_loadu_si128(reinterpret_cast<const __m128i *>(s1 + offset));
+ __m128i b = _mm_loadu_si128(reinterpret_cast<const __m128i *>(s2 + offset));
+
+ // compare the two against each oher
+ __m128i cmp = _mm_cmpeq_epi8(a, b);
+
+ // find NUL terminators too
+ cmp = _mm_min_epu8(cmp, a);
+ cmp = _mm_cmpeq_epi8(cmp, zero);
+
+ // was there any difference or a NUL?
+ uint mask = _mm_movemask_epi8(cmp);
+ if (mask) {
+ // yes, find out where
+ uint start = qCountTrailingZeroBits(mask);
+ uint end = sizeof(mask) * 8 - qCountLeadingZeroBits(mask);
+ Q_ASSUME(end >= start);
+ offset += start;
+ n = end - start;
+ break;
+ }
+ }
+
+ // using SIMD could cause a page fault, so iterate byte by byte
+ int res = innerCompare(n, false);
+ if (res != Incomplete)
+ return res;
+ }
+#endif
+
+ return innerCompare(-1, true);
}
/*! \relates QByteArray
@@ -434,7 +496,8 @@ int qstricmp(const char *str1, const char *str2)
Special case 2: Returns a random non-zero value if \a str1 is nullptr
or \a str2 is nullptr (but not both).
- \sa qstrcmp(), qstrncmp(), qstricmp(), {8-bit Character Comparisons}
+ \sa qstrcmp(), qstrncmp(), qstricmp(), {8-bit Character Comparisons},
+ QByteArray::compare()
*/
int qstrnicmp(const char *str1, const char *str2, uint len)
@@ -456,6 +519,55 @@ int qstrnicmp(const char *str1, const char *str2, uint len)
/*!
\internal
+ \since 5.12
+
+ A helper for QByteArray::compare. Compares \a len1 bytes from \a str1 to \a
+ len2 bytes from \a str2. If \a len2 is -1, then \a str2 is expected to be
+ null-terminated.
+ */
+int qstrnicmp(const char *str1, qsizetype len1, const char *str2, qsizetype len2)
+{
+ Q_ASSERT(str1);
+ Q_ASSERT(len1 >= 0);
+ Q_ASSERT(len2 >= -1);
+ const uchar *s1 = reinterpret_cast<const uchar *>(str1);
+ const uchar *s2 = reinterpret_cast<const uchar *>(str2);
+ if (!s2)
+ return len1 == 0 ? 0 : 1;
+
+ int res;
+ uchar c;
+ if (len2 == -1) {
+ // null-terminated str2
+ qsizetype i;
+ for (i = 0; i < len1; ++i) {
+ c = latin1_lowercased[s2[i]];
+ if (!c)
+ return 1;
+
+ res = latin1_lowercased[s1[i]] - c;
+ if (res)
+ return res;
+ }
+ c = latin1_lowercased[s2[i]];
+ return c ? -1 : 0;
+ } else {
+ // not null-terminated
+ for (qsizetype i = 0; i < qMin(len1, len2); ++i) {
+ c = latin1_lowercased[s2[i]];
+ res = latin1_lowercased[s1[i]] - c;
+ if (res)
+ return res;
+ }
+ if (len1 == len2)
+ return 0;
+ return len1 < len2 ? -1 : 1;
+ }
+}
+
+/*!
+ \internal
+ ### Qt6: replace the QByteArray parameter with [pointer,len] pair
*/
int qstrcmp(const QByteArray &str1, const char *str2)
{
@@ -483,6 +595,7 @@ int qstrcmp(const QByteArray &str1, const char *str2)
/*!
\internal
+ ### Qt6: replace the QByteArray parameter with [pointer,len] pair
*/
int qstrcmp(const QByteArray &str1, const QByteArray &str2)
{
@@ -950,7 +1063,7 @@ QByteArray qUncompress(const uchar* data, int nbytes)
$LC_CTYPE is set, most Unix systems do "the right thing".)
Functions that this affects include contains(), indexOf(),
lastIndexOf(), operator<(), operator<=(), operator>(),
- operator>=(), toLower() and toUpper().
+ operator>=(), isLower(), isUpper(), toLower() and toUpper().
This issue does not apply to \l{QString}s since they represent
characters using Unicode.
@@ -2542,10 +2655,7 @@ QList<QByteArray> QByteArray::split(char sep) const
Example:
- \code
- QByteArray ba("ab");
- ba.repeated(4); // returns "abababab"
- \endcode
+ \snippet code/src_corelib_tools_qbytearray.cpp 49
*/
QByteArray QByteArray::repeated(int times) const
{
@@ -2864,6 +2974,31 @@ int QByteArray::count(char ch) const
*/
/*!
+ \fn int QByteArray::compare(const char *c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \since 5.12
+
+ Returns an integer less than, equal to, or greater than zero depending on
+ whether this QByteArray sorts before, at the same position, or after the
+ string pointed to by \a c. The comparison is performed according to case
+ sensitivity \a cs.
+
+ \sa operator==
+*/
+
+/*!
+ \fn int QByteArray::compare(const QByteArray &a, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \overload
+ \since 5.12
+
+ Returns an integer less than, equal to, or greater than zero depending on
+ whether this QByteArray sorts before, at the same position, or after the
+ QByteArray \a a. The comparison is performed according to case sensitivity
+ \a cs.
+
+ \sa operator==
+*/
+
+/*!
Returns \c true if this byte array starts with byte array \a ba;
otherwise returns \c false.
@@ -2941,6 +3076,78 @@ bool QByteArray::endsWith(const char *str) const
return qstrncmp(d->data() + d->size - len, str, len) == 0;
}
+/*!
+ Returns true if \a c is an uppercase Latin1 letter.
+ \note The multiplication sign 0xD7 and the sz ligature 0xDF are not
+ treated as uppercase Latin1.
+ */
+static inline bool isUpperCaseLatin1(char c)
+{
+ if (c >= 'A' && c <= 'Z')
+ return true;
+
+ return (uchar(c) >= 0xC0 && uchar(c) <= 0xDE && uchar(c) != 0xD7);
+}
+
+/*!
+ Returns \c true if this byte array contains only uppercase letters,
+ otherwise returns \c false. The byte array is interpreted as a Latin-1
+ encoded string.
+ \since 5.12
+
+ \sa isLower(), toUpper()
+*/
+bool QByteArray::isUpper() const
+{
+ if (isEmpty())
+ return false;
+
+ const char *d = data();
+
+ for (int i = 0, max = size(); i < max; ++i) {
+ if (!isUpperCaseLatin1(d[i]))
+ return false;
+ }
+
+ return true;
+}
+
+/*!
+ Returns true if \a c is an lowercase Latin1 letter.
+ \note The division sign 0xF7 is not treated as lowercase Latin1,
+ but the small y dieresis 0xFF is.
+ */
+static inline bool isLowerCaseLatin1(char c)
+{
+ if (c >= 'a' && c <= 'z')
+ return true;
+
+ return (uchar(c) >= 0xD0 && uchar(c) != 0xF7);
+}
+
+/*!
+ Returns \c true if this byte array contains only lowercase letters,
+ otherwise returns \c false. The byte array is interpreted as a Latin-1
+ encoded string.
+ \since 5.12
+
+ \sa isUpper(), toLower()
+ */
+bool QByteArray::isLower() const
+{
+ if (isEmpty())
+ return false;
+
+ const char *d = data();
+
+ for (int i = 0, max = size(); i < max; ++i) {
+ if (!isLowerCaseLatin1(d[i]))
+ return false;
+ }
+
+ return true;
+}
+
/*! \overload
Returns \c true if this byte array ends with character \a ch;
@@ -3052,7 +3259,7 @@ QByteArray QByteArray::mid(int pos, int len) const
Example:
\snippet code/src_corelib_tools_qbytearray.cpp 30
- \sa toUpper(), {8-bit Character Comparisons}
+ \sa isLower(), toUpper(), {8-bit Character Comparisons}
*/
// prevent the compiler from inlining the function in each of
@@ -3106,7 +3313,7 @@ QByteArray QByteArray::toLower_helper(QByteArray &a)
Example:
\snippet code/src_corelib_tools_qbytearray.cpp 31
- \sa toLower(), {8-bit Character Comparisons}
+ \sa isUpper(), toLower(), {8-bit Character Comparisons}
*/
QByteArray QByteArray::toUpper_helper(const QByteArray &a)
@@ -3295,6 +3502,8 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
Returns \c true if byte array \a a1 is equal to byte array \a a2;
otherwise returns \c false.
+
+ \sa QByteArray::compare()
*/
/*! \fn bool operator==(const QByteArray &a1, const char *a2)
@@ -3304,6 +3513,8 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
Returns \c true if byte array \a a1 is equal to string \a a2;
otherwise returns \c false.
+
+ \sa QByteArray::compare()
*/
/*! \fn bool operator==(const char *a1, const QByteArray &a2)
@@ -3313,6 +3524,8 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
Returns \c true if string \a a1 is equal to byte array \a a2;
otherwise returns \c false.
+
+ \sa QByteArray::compare()
*/
/*! \fn bool operator!=(const QByteArray &a1, const QByteArray &a2)
@@ -3322,6 +3535,8 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
Returns \c true if byte array \a a1 is not equal to byte array \a a2;
otherwise returns \c false.
+
+ \sa QByteArray::compare()
*/
/*! \fn bool operator!=(const QByteArray &a1, const char *a2)
@@ -3331,6 +3546,8 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
Returns \c true if byte array \a a1 is not equal to string \a a2;
otherwise returns \c false.
+
+ \sa QByteArray::compare()
*/
/*! \fn bool operator!=(const char *a1, const QByteArray &a2)
@@ -3340,6 +3557,8 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
Returns \c true if string \a a1 is not equal to byte array \a a2;
otherwise returns \c false.
+
+ \sa QByteArray::compare()
*/
/*! \fn bool operator<(const QByteArray &a1, const QByteArray &a2)
@@ -3349,6 +3568,8 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
Returns \c true if byte array \a a1 is lexically less than byte array
\a a2; otherwise returns \c false.
+
+ \sa QByteArray::compare()
*/
/*! \fn inline bool operator<(const QByteArray &a1, const char *a2)
@@ -3358,6 +3579,8 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
Returns \c true if byte array \a a1 is lexically less than string
\a a2; otherwise returns \c false.
+
+ \sa QByteArray::compare()
*/
/*! \fn bool operator<(const char *a1, const QByteArray &a2)
@@ -3367,6 +3590,8 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
Returns \c true if string \a a1 is lexically less than byte array
\a a2; otherwise returns \c false.
+
+ \sa QByteArray::compare()
*/
/*! \fn bool operator<=(const QByteArray &a1, const QByteArray &a2)
@@ -3376,6 +3601,8 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
Returns \c true if byte array \a a1 is lexically less than or equal
to byte array \a a2; otherwise returns \c false.
+
+ \sa QByteArray::compare()
*/
/*! \fn bool operator<=(const QByteArray &a1, const char *a2)
@@ -3385,6 +3612,8 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
Returns \c true if byte array \a a1 is lexically less than or equal
to string \a a2; otherwise returns \c false.
+
+ \sa QByteArray::compare()
*/
/*! \fn bool operator<=(const char *a1, const QByteArray &a2)
@@ -3394,6 +3623,8 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
Returns \c true if string \a a1 is lexically less than or equal
to byte array \a a2; otherwise returns \c false.
+
+ \sa QByteArray::compare()
*/
/*! \fn bool operator>(const QByteArray &a1, const QByteArray &a2)
@@ -3403,6 +3634,8 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
Returns \c true if byte array \a a1 is lexically greater than byte
array \a a2; otherwise returns \c false.
+
+ \sa QByteArray::compare()
*/
/*! \fn bool operator>(const QByteArray &a1, const char *a2)
@@ -3412,6 +3645,8 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
Returns \c true if byte array \a a1 is lexically greater than string
\a a2; otherwise returns \c false.
+
+ \sa QByteArray::compare()
*/
/*! \fn bool operator>(const char *a1, const QByteArray &a2)
@@ -3421,6 +3656,8 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
Returns \c true if string \a a1 is lexically greater than byte array
\a a2; otherwise returns \c false.
+
+ \sa QByteArray::compare()
*/
/*! \fn bool operator>=(const QByteArray &a1, const QByteArray &a2)
@@ -3430,6 +3667,8 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
Returns \c true if byte array \a a1 is lexically greater than or
equal to byte array \a a2; otherwise returns \c false.
+
+ \sa QByteArray::compare()
*/
/*! \fn bool operator>=(const QByteArray &a1, const char *a2)
@@ -3439,6 +3678,8 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
Returns \c true if byte array \a a1 is lexically greater than or
equal to string \a a2; otherwise returns \c false.
+
+ \sa QByteArray::compare()
*/
/*! \fn bool operator>=(const char *a1, const QByteArray &a2)
@@ -3448,6 +3689,8 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
Returns \c true if string \a a1 is lexically greater than or
equal to byte array \a a2; otherwise returns \c false.
+
+ \sa QByteArray::compare()
*/
/*! \fn const QByteArray operator+(const QByteArray &a1, const QByteArray &a2)
@@ -3878,9 +4121,16 @@ ushort QByteArray::toUShort(bool *ok, int base) const
\snippet code/src_corelib_tools_qbytearray.cpp 38
+ \warning The QByteArray content may only contain valid numerical characters
+ which includes the plus/minus sign, the character e used in scientific
+ notation, and the decimal point. Including the unit or additional characters
+ leads to a conversion error.
+
\note The conversion of the number is performed in the default C locale,
irrespective of the user's locale.
+ This function ignores leading and trailing whitespace.
+
\sa number()
*/
@@ -3889,7 +4139,8 @@ double QByteArray::toDouble(bool *ok) const
QByteArray nulled = nulTerminated();
bool nonNullOk = false;
int processed = 0;
- double d = asciiToDouble(nulled.constData(), nulled.length(), nonNullOk, processed);
+ double d = qt_asciiToDouble(nulled.constData(), nulled.length(),
+ nonNullOk, processed, WhitespacesAllowed);
if (ok)
*ok = nonNullOk;
return d;
@@ -3903,9 +4154,18 @@ double QByteArray::toDouble(bool *ok) const
If \a ok is not \c nullptr, failure is reported by setting *\a{ok}
to \c false, and success by setting *\a{ok} to \c true.
+ \snippet code/src_corelib_tools_qbytearray.cpp 38float
+
+ \warning The QByteArray content may only contain valid numerical characters
+ which includes the plus/minus sign, the character e used in scientific
+ notation, and the decimal point. Including the unit or additional characters
+ leads to a conversion error.
+
\note The conversion of the number is performed in the default C locale,
irrespective of the user's locale.
+ This function ignores leading and trailing whitespace.
+
\sa number()
*/
@@ -4469,11 +4729,7 @@ QByteArray QByteArray::toHex() const
If \a separator is not '\0', the separator character is inserted between the hex bytes.
Example:
- \code
- QByteArray macAddress = QByteArray::fromHex("123456abcdef");
- macAddress.toHex(':'); // returns "12:34:56:ab:cd:ef"
- macAddress.toHex(0); // returns "123456abcdef"
- \endcode
+ \snippet code/src_corelib_tools_qbytearray.cpp 50
\sa fromHex()
*/
@@ -4549,10 +4805,7 @@ void q_fromPercentEncoding(QByteArray *ba)
another (for instance, '_' or '=').
For example:
- \code
- QByteArray text = QByteArray::fromPercentEncoding("Qt%20is%20great%33");
- text.data(); // returns "Qt is great!"
- \endcode
+ \snippet code/src_corelib_tools_qbytearray.cpp 51
\note Given invalid input (such as a string containing the sequence "%G5",
which is not a valid hexadecimal number) the output will be invalid as
@@ -4674,12 +4927,7 @@ void q_normalizePercentEncoding(QByteArray *ba, const char *exclude)
Example:
- \code
- QByteArray text = "{a fishy string?}";
- QByteArray ba = text.toPercentEncoding("{}", "s");
- qDebug(ba.constData());
- // prints "{a fi%73hy %73tring%3F}"
- \endcode
+ \snippet code/src_corelib_tools_qbytearray.cpp 52
The hex encoding uses the numbers 0-9 and the uppercase letters A-F.
@@ -4797,9 +5045,7 @@ QByteArray QByteArray::toPercentEncoding(const QByteArray &exclude, const QByteA
For instance:
- \code
- QByteArray ba = QByteArrayLiteral("byte array contents");
- \endcode
+ \snippet code/src_corelib_tools_qbytearray.cpp 53
Using QByteArrayLiteral instead of a double quoted plain C++ string literal
can significantly speed up creation of QByteArray instances from data known
diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h
index 300f795469..8ee3a29ecc 100644
--- a/src/corelib/tools/qbytearray.h
+++ b/src/corelib/tools/qbytearray.h
@@ -99,6 +99,7 @@ inline int qstrncmp(const char *str1, const char *str2, uint len)
}
Q_CORE_EXPORT int qstricmp(const char *, const char *);
Q_CORE_EXPORT int qstrnicmp(const char *, const char *, uint len);
+Q_CORE_EXPORT int qstrnicmp(const char *, qsizetype, const char *, qsizetype = -1);
// implemented in qvsnprintf.cpp
Q_CORE_EXPORT int qvsnprintf(char *str, size_t n, const char *fmt, va_list ap);
@@ -231,6 +232,9 @@ public:
int count(const char *a) const;
int count(const QByteArray &a) const;
+ inline int compare(const char *c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ inline int compare(const QByteArray &a, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+
Q_REQUIRED_RESULT QByteArray left(int len) const;
Q_REQUIRED_RESULT QByteArray right(int len) const;
Q_REQUIRED_RESULT QByteArray mid(int index, int len = -1) const;
@@ -245,6 +249,9 @@ public:
bool endsWith(char c) const;
bool endsWith(const char *c) const;
+ bool isUpper() const;
+ bool isLower() const;
+
void truncate(int pos);
void chop(int n);
@@ -600,6 +607,16 @@ inline bool QByteArray::contains(const QByteArray &a) const
{ return indexOf(a) != -1; }
inline bool QByteArray::contains(char c) const
{ return indexOf(c) != -1; }
+inline int QByteArray::compare(const char *c, Qt::CaseSensitivity cs) const
+{
+ return cs == Qt::CaseSensitive ? qstrcmp(*this, c) :
+ qstrnicmp(data(), size(), c, -1);
+}
+inline int QByteArray::compare(const QByteArray &a, Qt::CaseSensitivity cs) const
+{
+ return cs == Qt::CaseSensitive ? qstrcmp(*this, a) :
+ qstrnicmp(data(), size(), a.data(), a.size());
+}
inline bool operator==(const QByteArray &a1, const QByteArray &a2) Q_DECL_NOTHROW
{ return (a1.size() == a2.size()) && (memcmp(a1.constData(), a2.constData(), a1.size())==0); }
inline bool operator==(const QByteArray &a1, const char *a2) Q_DECL_NOTHROW
diff --git a/src/corelib/tools/qbytearraymatcher.cpp b/src/corelib/tools/qbytearraymatcher.cpp
index a54afc5a9d..72f0e0519d 100644
--- a/src/corelib/tools/qbytearraymatcher.cpp
+++ b/src/corelib/tools/qbytearraymatcher.cpp
@@ -356,9 +356,7 @@ int qFindByteArray(
value of that function in a \c{static const auto} variable, so you don't need
to pass the \c{N} template parameter explicitly:
- \code
- static const auto matcher = qMakeStaticByteArrayMatcher("needle");
- \endcode
+ \snippet code/src_corelib_tools_qbytearraymatcher.cpp 0
Then call indexIn() on the QByteArray in which you want to search, just like
with QByteArrayMatcher.
@@ -430,9 +428,7 @@ int QStaticByteArrayMatcherBase::indexOfIn(const char *needle, uint nlen, const
To take full advantage of this function, assign the result to an
\c{auto} variable:
- \code
- static const auto matcher = qMakeStaticByteArrayMatcher("needle");
- \endcode
+ \snippet code/src_corelib_tools_qbytearraymatcher.cpp 1
*/
diff --git a/src/corelib/tools/qcollator.cpp b/src/corelib/tools/qcollator.cpp
index 5155badcf8..1cf223aae6 100644
--- a/src/corelib/tools/qcollator.cpp
+++ b/src/corelib/tools/qcollator.cpp
@@ -77,9 +77,8 @@ QT_BEGIN_NAMESPACE
\sa setLocale()
*/
QCollator::QCollator(const QLocale &locale)
- : d(new QCollatorPrivate)
+ : d(new QCollatorPrivate(locale))
{
- d->locale = locale;
d->init();
}
@@ -158,15 +157,13 @@ QCollator &QCollator::operator=(const QCollator &other)
void QCollator::detach()
{
if (d->ref.load() != 1) {
- QCollatorPrivate *x = new QCollatorPrivate;
- x->ref.store(1);
- x->locale = d->locale;
- x->collator = 0;
+ QCollatorPrivate *x = new QCollatorPrivate(d->locale);
if (!d->ref.deref())
delete d;
d = x;
- d->init();
}
+ // All callers need this, because about to modify the object:
+ d->dirty = true;
}
/*!
@@ -179,7 +176,6 @@ void QCollator::setLocale(const QLocale &locale)
detach();
d->locale = locale;
- d->dirty = true;
}
/*!
@@ -204,7 +200,6 @@ void QCollator::setCaseSensitivity(Qt::CaseSensitivity cs)
detach();
d->caseSensitivity = cs;
- d->dirty = true;
}
/*!
@@ -242,7 +237,6 @@ void QCollator::setNumericMode(bool on)
detach();
d->numericMode = on;
- d->dirty = true;
}
/*!
@@ -275,7 +269,6 @@ void QCollator::setIgnorePunctuation(bool on)
detach();
d->ignorePunctuation = on;
- d->dirty = true;
}
/*!
diff --git a/src/corelib/tools/qcollator_icu.cpp b/src/corelib/tools/qcollator_icu.cpp
index 43bbe0ea79..fd621983d3 100644
--- a/src/corelib/tools/qcollator_icu.cpp
+++ b/src/corelib/tools/qcollator_icu.cpp
@@ -61,7 +61,7 @@ void QCollatorPrivate::init()
collator = ucol_open(name.constData(), &status);
if (U_FAILURE(status)) {
qWarning("Could not create collator: %d", status);
- collator = 0;
+ collator = nullptr;
dirty = false;
return;
}
@@ -100,7 +100,7 @@ void QCollatorPrivate::cleanup()
{
if (collator)
ucol_close(collator);
- collator = 0;
+ collator = nullptr;
}
int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const
diff --git a/src/corelib/tools/qcollator_p.h b/src/corelib/tools/qcollator_p.h
index c03a3431db..e89c08447c 100644
--- a/src/corelib/tools/qcollator_p.h
+++ b/src/corelib/tools/qcollator_p.h
@@ -68,27 +68,31 @@ QT_BEGIN_NAMESPACE
#if QT_CONFIG(icu)
typedef UCollator *CollatorType;
typedef QByteArray CollatorKeyType;
+const CollatorType NoCollator = nullptr;
#elif defined(Q_OS_OSX)
typedef CollatorRef CollatorType;
typedef QVector<UCCollationValue> CollatorKeyType;
+const CollatorType NoCollator = 0;
#elif defined(Q_OS_WIN)
typedef QString CollatorKeyType;
typedef int CollatorType;
+const CollatorType NoCollator = 0;
# ifdef Q_OS_WINRT
# define USE_COMPARESTRINGEX
# endif
-#else //posix
+#else // posix - ignores CollatorType collator, only handles system locale
typedef QVector<wchar_t> CollatorKeyType;
-typedef int CollatorType;
+typedef bool CollatorType;
+const CollatorType NoCollator = false;
#endif
class QCollatorPrivate
{
public:
- QAtomicInt ref;
+ QAtomicInt ref = 1;
QLocale locale;
#if defined(Q_OS_WIN) && !QT_CONFIG(icu)
#ifdef USE_COMPARESTRINGEX
@@ -97,32 +101,25 @@ public:
LCID localeID;
#endif
#endif
- Qt::CaseSensitivity caseSensitivity;
- bool numericMode;
- bool ignorePunctuation;
- bool dirty;
+ Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive;
+ bool numericMode = false;
+ bool ignorePunctuation = false;
+ bool dirty = true;
+
+ CollatorType collator = NoCollator;
- CollatorType collator;
+ QCollatorPrivate(const QLocale &locale) : locale(locale) {}
+ ~QCollatorPrivate() { cleanup(); }
void clear() {
cleanup();
- collator = 0;
+ collator = NoCollator;
}
+ // Implemented by each back-end, in its own way:
void init();
void cleanup();
- QCollatorPrivate()
- : ref(1),
- caseSensitivity(Qt::CaseSensitive),
- numericMode(false),
- ignorePunctuation(false),
- dirty(true),
- collator(0)
- { cleanup(); }
-
- ~QCollatorPrivate() { cleanup(); }
-
private:
Q_DISABLE_COPY(QCollatorPrivate)
};
diff --git a/src/corelib/tools/qcontiguouscache.cpp b/src/corelib/tools/qcontiguouscache.cpp
index 2ded61c0be..64cbd7df4b 100644
--- a/src/corelib/tools/qcontiguouscache.cpp
+++ b/src/corelib/tools/qcontiguouscache.cpp
@@ -91,19 +91,7 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data)
The simplest way of using a contiguous cache is to use the append()
and prepend().
-\code
-MyRecord record(int row) const
-{
- Q_ASSERT(row >= 0 && row < count());
-
- while(row > cache.lastIndex())
- cache.append(slowFetchRecord(cache.lastIndex()+1));
- while(row < cache.firstIndex())
- cache.prepend(slowFetchRecord(cache.firstIndex()-1));
-
- return cache.at(row);
-}
-\endcode
+ \snippet code/src_corelib_tools_qcontiguouscache.cpp 0
If the cache is full then the item at the opposite end of the cache from
where the new item is appended or prepended will be removed.
@@ -463,12 +451,7 @@ MyRecord record(int row) const
It is provided so that index overflows can be corrected when using the
cache as a circular buffer.
- \code
- QContiguousCache<int> cache(10);
- cache.insert(INT_MAX, 1); // cache contains one value and has valid indexes, INT_MAX to INT_MAX
- cache.append(2); // cache contains two values but does not have valid indexes.
- cache.normalizeIndexes(); // cache has two values, 1 and 2. New first index will be in the range of 0 to capacity().
- \endcode
+ \snippet code/src_corelib_tools_qcontiguouscache.cpp 1
\sa areIndexesValid(), append(), prepend()
*/
diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h
index 18facf7e42..faa7263d6b 100644
--- a/src/corelib/tools/qcontiguouscache.h
+++ b/src/corelib/tools/qcontiguouscache.h
@@ -211,6 +211,7 @@ void QContiguousCache<T>::detach_helper()
template <typename T>
void QContiguousCache<T>::setCapacity(int asize)
{
+ Q_ASSERT(asize >= 0);
if (asize == d->alloc)
return;
detach();
@@ -285,6 +286,7 @@ inline QContiguousCacheData *QContiguousCache<T>::allocateData(int aalloc)
template <typename T>
QContiguousCache<T>::QContiguousCache(int cap)
{
+ Q_ASSERT(cap >= 0);
d = allocateData(cap);
d->ref.store(1);
d->alloc = cap;
diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp
index a1b121f1ee..3c79bb797d 100644
--- a/src/corelib/tools/qcryptographichash.cpp
+++ b/src/corelib/tools/qcryptographichash.cpp
@@ -544,6 +544,46 @@ QByteArray QCryptographicHash::hash(const QByteArray &data, Algorithm method)
return hash.result();
}
+/*!
+ Returns the size of the output of the selected hash \a method in bytes.
+
+ \since 5.12
+*/
+int QCryptographicHash::hashLength(QCryptographicHash::Algorithm method)
+{
+ switch (method) {
+ case QCryptographicHash::Sha1:
+ return 20;
+#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
+ case QCryptographicHash::Md4:
+ return 16;
+ case QCryptographicHash::Md5:
+ return 16;
+ case QCryptographicHash::Sha224:
+ return SHA224HashSize;
+ case QCryptographicHash::Sha256:
+ return SHA256HashSize;
+ case QCryptographicHash::Sha384:
+ return SHA384HashSize;
+ case QCryptographicHash::Sha512:
+ return SHA512HashSize;
+ case QCryptographicHash::RealSha3_224:
+ case QCryptographicHash::Keccak_224:
+ return 224 / 8;
+ case QCryptographicHash::RealSha3_256:
+ case QCryptographicHash::Keccak_256:
+ return 256 / 8;
+ case QCryptographicHash::RealSha3_384:
+ case QCryptographicHash::Keccak_384:
+ return 384 / 8;
+ case QCryptographicHash::RealSha3_512:
+ case QCryptographicHash::Keccak_512:
+ return 512 / 8;
+#endif
+ }
+ return 0;
+}
+
QT_END_NAMESPACE
#ifndef QT_NO_QOBJECT
diff --git a/src/corelib/tools/qcryptographichash.h b/src/corelib/tools/qcryptographichash.h
index 2f74d42405..ad1de7c756 100644
--- a/src/corelib/tools/qcryptographichash.h
+++ b/src/corelib/tools/qcryptographichash.h
@@ -101,6 +101,7 @@ public:
QByteArray result() const;
static QByteArray hash(const QByteArray &data, Algorithm method);
+ static int hashLength(Algorithm method);
private:
Q_DISABLE_COPY(QCryptographicHash)
QCryptographicHashPrivate *d;
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index f5e264798e..816bd974eb 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -326,20 +326,19 @@ static int fromOffsetString(const QStringRef &offsetString, bool *valid) Q_DECL_
\brief The QDate class provides date functions.
- A QDate object contains a calendar date, i.e. year, month, and day
- numbers, in the Gregorian calendar. It can read the current date
- from the system clock. It provides functions for comparing dates,
- and for manipulating dates. For example, it is possible to add
- and subtract days, months, and years to dates.
-
- A QDate object is typically created by giving the year,
- month, and day numbers explicitly. Note that QDate interprets two
- digit years as is, i.e., years 0 - 99. A QDate can also be
- constructed with the static function currentDate(), which creates
- a QDate object containing the system clock's date. An explicit
- date can also be set using setDate(). The fromString() function
- returns a QDate given a string and a date format which is used to
- interpret the date within the string.
+ A QDate object encodes a calendar date, i.e. year, month, and day numbers,
+ in the proleptic Gregorian calendar by default. It can read the current date
+ from the system clock. It provides functions for comparing dates, and for
+ manipulating dates. For example, it is possible to add and subtract days,
+ months, and years to dates.
+
+ A QDate object is typically created by giving the year, month, and day
+ numbers explicitly. Note that QDate interprets two digit years as presented,
+ i.e., as years 0 through 99, without adding any offset. A QDate can also be
+ constructed with the static function currentDate(), which creates a QDate
+ object containing the system clock's date. An explicit date can also be set
+ using setDate(). The fromString() function returns a QDate given a string
+ and a date format which is used to interpret the date within the string.
The year(), month(), and day() functions provide access to the
year, month, and day numbers. Also, dayOfWeek() and dayOfYear()
@@ -363,9 +362,9 @@ static int fromOffsetString(const QStringRef &offsetString, bool *valid) Q_DECL_
\section2 No Year 0
- There is no year 0. Dates in that year are considered invalid. The
- year -1 is the year "1 before Christ" or "1 before current era."
- The day before 1 January 1 CE is 31 December 1 BCE.
+ There is no year 0. Dates in that year are considered invalid. The year -1
+ is the year "1 before Christ" or "1 before current era." The day before 1
+ January 1 CE, QDate(1, 1, 1), is 31 December 1 BCE, QDate(-1, 12, 31).
\section2 Range of Valid Dates
@@ -1418,11 +1417,12 @@ bool QDate::isLeapYear(int y)
\brief The QTime class provides clock time functions.
- A QTime object contains a clock time, i.e. the number of hours,
- minutes, seconds, and milliseconds since midnight. It can read the
- current time from the system clock and measure a span of elapsed
- time. It provides functions for comparing times and for
- manipulating a time by adding a number of milliseconds.
+ A QTime object contains a clock time, which it can express as the
+ numbers of hours, minutes, seconds, and milliseconds since
+ midnight. It can read the current time from the system clock and
+ measure a span of elapsed time. It provides functions for
+ comparing times and for manipulating a time by adding a number of
+ milliseconds.
QTime uses the 24-hour clock format; it has no concept of AM/PM.
Unlike QDateTime, QTime knows nothing about time zones or
@@ -1440,15 +1440,15 @@ bool QDate::isLeapYear(int y)
of the time. The same information is provided in textual format by
the toString() function.
- QTime provides a full set of operators to compare two QTime
- objects. QTime A is considered smaller than QTime B if A is
- earlier than B.
-
The addSecs() and addMSecs() functions provide the time a given
number of seconds or milliseconds later than a given time.
Correspondingly, the number of seconds or milliseconds
between two times can be found using secsTo() or msecsTo().
+ QTime provides a full set of operators to compare two QTime
+ objects; an earlier time is considered smaller than a later one;
+ if A.msecsTo(B) is positive, then A < B.
+
QTime can be used to measure a span of elapsed time using the
start(), restart(), and elapsed() functions.
@@ -2341,7 +2341,7 @@ static bool qt_localtime(qint64 msecsSinceEpoch, QDate *localDate, QTime *localT
// localtime_r() does not have this requirement, so make an explicit call.
// The explicit call should also request the timezone info be re-parsed.
qt_tzset();
-#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
+#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
// Use the reentrant version of localtime() where available
// as is thread-safe and doesn't use a shared static data area
tm *res = 0;
@@ -2981,18 +2981,18 @@ inline QDateTime::Data QDateTimePrivate::create(const QDate &toDate, const QTime
// DST transitions are disambiguated by hint.
inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QTimeZone &zone,
DaylightStatus hint,
- QDate *localDate, QTime *localTime)
+ QDate *zoneDate, QTime *zoneTime)
{
// Get the effective data from QTimeZone
QTimeZonePrivate::Data data = zone.d->dataForLocalTime(zoneMSecs, int(hint));
- // Docs state any LocalTime before 1970-01-01 will *not* have any DST applied
+ // Docs state any time before 1970-01-01 will *not* have any DST applied
// but all affected times afterwards will have DST applied.
- if (data.atMSecsSinceEpoch >= 0) {
- msecsToTime(data.atMSecsSinceEpoch + (data.offsetFromUtc * 1000), localDate, localTime);
- return data.atMSecsSinceEpoch;
+ if (data.atMSecsSinceEpoch < 0) {
+ msecsToTime(zoneMSecs, zoneDate, zoneTime);
+ return zoneMSecs - data.standardTimeOffset * 1000;
} else {
- msecsToTime(zoneMSecs, localDate, localTime);
- return zoneMSecs - (data.standardTimeOffset * 1000);
+ msecsToTime(data.atMSecsSinceEpoch + data.offsetFromUtc * 1000, zoneDate, zoneTime);
+ return data.atMSecsSinceEpoch;
}
}
#endif // timezone
@@ -3009,8 +3009,8 @@ inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QT
\brief The QDateTime class provides date and time functions.
- A QDateTime object contains a calendar date and a clock time (a
- "datetime"). It is a combination of the QDate and QTime classes.
+ A QDateTime object encodes a calendar date and a clock time (a
+ "datetime"). It combines features of the QDate and QTime classes.
It can read the current datetime from the system clock. It
provides functions for comparing datetimes and for manipulating a
datetime by adding a number of seconds, days, months, or years.
diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp
index 235ca625c1..f82048db0f 100644
--- a/src/corelib/tools/qeasingcurve.cpp
+++ b/src/corelib/tools/qeasingcurve.cpp
@@ -292,7 +292,7 @@
This is a typedef for a pointer to a function with the following
signature:
- \snippet code/src_corelib_tools_qeasingcurve.cpp 0
+ \snippet code/src_corelib_tools_qeasingcurve.cpp typedef
*/
#include "qeasingcurve.h"
diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp
index 5f0b131342..32e9a4269c 100644
--- a/src/corelib/tools/qhash.cpp
+++ b/src/corelib/tools/qhash.cpp
@@ -755,9 +755,7 @@ void QHashData::checkSanity()
Types \c T1 and \c T2 must be supported by qHash().
\note The return type of this function is \e{not} the same as that of
- \code
- qHash(qMakePair(key.first, key.second), seed);
- \endcode
+ \snippet code/src_corelib_tools_qhash.cpp 29
The two functions use different hashing algorithms; due to binary compatibility
constraints, we cannot change the QPair algorithm to match the std::pair one before Qt 6.
*/
@@ -773,14 +771,10 @@ void QHashData::checkSanity()
The return value of this function depends on the order of elements
in the range. That means that
- \code
- {0, 1, 2}
- \endcode
+ \snippet code/src_corelib_tools_qhash.cpp 30
and
- \code
- {1, 2, 0}
- \endcode
+ \snippet code/src_corelib_tools_qhash.cpp 31
hash to \b{different} values. If order does not matter, for example for hash
tables, use qHashRangeCommutative() instead. If you are hashing raw
@@ -812,14 +806,10 @@ void QHashData::checkSanity()
The return value of this function does not depend on the order of
elements in the range. That means that
- \code
- {0, 1, 2}
- \endcode
+ \snippet code/src_corelib_tools_qhash.cpp 30
and
- \code
- {1, 2, 0}
- \endcode
+ \snippet code/src_corelib_tools_qhash.cpp 31
hash to the \b{same} values. If order matters, for example, for vectors
and arrays, use qHashRange() instead. If you are hashing raw
@@ -1100,9 +1090,8 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW
To avoid this problem, replace \c hash[i] with \c hash.value(i)
in the code above.
- Internally, QHash uses a hash table to perform lookups. Unlike Qt
- 3's \c QDict class, which needed to be initialized with a prime
- number, QHash's hash table automatically grows and shrinks to
+ Internally, QHash uses a hash table to perform lookups. This
+ hash table automatically grows and shrinks to
provide fast lookups without wasting too much memory. You can
still control the size of the hash table by calling reserve() if
you already know approximately how many items the QHash will
@@ -1178,13 +1167,7 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW
For a key type \c{K}, the qHash function must have one of these signatures:
- \code
- uint qHash(K key);
- uint qHash(const K &key);
-
- uint qHash(K key, uint seed);
- uint qHash(const K &key, uint seed);
- \endcode
+ \snippet code/src_corelib_tools_qhash.cpp 32
The two-arguments overloads take an unsigned integer that should be used to
seed the calculation of the hash function. This seed is provided by QHash
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index ce663ce2ca..a586ca5671 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -348,6 +348,7 @@ public:
inline iterator operator-(int j) const { return operator+(-j); }
inline iterator &operator+=(int j) { return *this = *this + j; }
inline iterator &operator-=(int j) { return *this = *this - j; }
+ friend inline iterator operator+(int j, iterator k) { return k + j; }
#ifndef QT_STRICT_ITERATORS
public:
@@ -413,6 +414,7 @@ public:
inline const_iterator operator-(int j) const { return operator+(-j); }
inline const_iterator &operator+=(int j) { return *this = *this + j; }
inline const_iterator &operator-=(int j) { return *this = *this - j; }
+ friend inline const_iterator operator+(int j, const_iterator k) { return k + j; }
// ### Qt 5: not sure this is necessary anymore
#ifdef QT_STRICT_ITERATORS
diff --git a/src/corelib/tools/qhashfunctions.h b/src/corelib/tools/qhashfunctions.h
index e6ae7a0b85..d013c26d66 100644
--- a/src/corelib/tools/qhashfunctions.h
+++ b/src/corelib/tools/qhashfunctions.h
@@ -104,6 +104,11 @@ Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QBitArray &key, uint seed =
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(QLatin1String key, uint seed = 0) Q_DECL_NOTHROW;
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qt_hash(QStringView key, uint chained = 0) Q_DECL_NOTHROW;
+Q_DECL_CONST_FUNCTION inline uint qHash(std::nullptr_t, uint seed = 0) Q_DECL_NOTHROW
+{
+ return qHash(reinterpret_cast<quintptr>(nullptr), seed);
+}
+
template <class T> inline uint qHash(const T *key, uint seed = 0) Q_DECL_NOTHROW
{
return qHash(reinterpret_cast<quintptr>(key), seed);
diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h
index c8f3f4c8c3..1e6d4df474 100644
--- a/src/corelib/tools/qlinkedlist.h
+++ b/src/corelib/tools/qlinkedlist.h
@@ -159,6 +159,7 @@ public:
inline iterator operator-(int j) const { return operator+(-j); }
inline iterator &operator+=(int j) { return *this = *this + j; }
inline iterator &operator-=(int j) { return *this = *this - j; }
+ friend inline iterator operator+(int j, iterator k) { return k + j; }
};
friend class iterator;
@@ -193,6 +194,7 @@ public:
inline const_iterator operator-(int j) const { return operator+(-j); }
inline const_iterator &operator+=(int j) { return *this = *this + j; }
inline const_iterator &operator-=(int j) { return *this = *this - j; }
+ friend inline const_iterator operator+(int j, const_iterator k) { return k + j; }
};
friend class const_iterator;
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index af7659e995..49ccbc9c9f 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -269,6 +269,7 @@ public:
inline iterator &operator-=(difference_type j) { i-=j; return *this; }
inline iterator operator+(difference_type j) const { return iterator(i+j); }
inline iterator operator-(difference_type j) const { return iterator(i-j); }
+ friend inline iterator operator+(difference_type j, iterator k) { return k + j; }
inline int operator-(iterator j) const { return int(i - j.i); }
};
friend class iterator;
@@ -312,6 +313,7 @@ public:
inline const_iterator &operator-=(difference_type j) { i-=j; return *this; }
inline const_iterator operator+(difference_type j) const { return const_iterator(i+j); }
inline const_iterator operator-(difference_type j) const { return const_iterator(i-j); }
+ friend inline const_iterator operator+(difference_type j, const_iterator k) { return k + j; }
inline int operator-(const_iterator j) const { return int(i - j.i); }
};
friend class const_iterator;
@@ -411,7 +413,8 @@ private:
bool isValidIterator(const iterator &i) const Q_DECL_NOTHROW
{
- return (constBegin().i <= i.i) && (i.i <= constEnd().i);
+ const std::less<const Node *> less = {};
+ return !less(i.i, cbegin().i) && !less(cend().i, i.i);
}
private:
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index 6361280bc7..ddc973cb37 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -83,7 +83,6 @@ public:
};
Q_GLOBAL_STATIC(QSystemLocaleSingleton, QSystemLocale_globalSystemLocale)
-static QLocaleData *system_data = 0;
static QLocaleData globalLocaleData;
#endif
@@ -233,14 +232,6 @@ QLocaleId QLocaleId::withLikelySubtagsAdded() const
if (addLikelySubtags(id))
return id;
}
- // language_script
- if (country_id) {
- QLocaleId id = QLocaleId::fromIds(language_id, script_id, 0);
- if (addLikelySubtags(id)) {
- id.country_id = country_id;
- return id;
- }
- }
// language_region
if (script_id) {
QLocaleId id = QLocaleId::fromIds(language_id, 0, country_id);
@@ -249,6 +240,14 @@ QLocaleId QLocaleId::withLikelySubtagsAdded() const
return id;
}
}
+ // language_script
+ if (country_id) {
+ QLocaleId id = QLocaleId::fromIds(language_id, script_id, 0);
+ if (addLikelySubtags(id)) {
+ id.country_id = country_id;
+ return id;
+ }
+ }
// language
if (script_id && country_id) {
QLocaleId id = QLocaleId::fromIds(language_id, 0, 0);
@@ -258,6 +257,14 @@ QLocaleId QLocaleId::withLikelySubtagsAdded() const
return id;
}
}
+ // und_script
+ if (language_id) {
+ QLocaleId id = QLocaleId::fromIds(0, script_id, 0);
+ if (addLikelySubtags(id)) {
+ id.language_id = language_id;
+ return id;
+ }
+ }
return *this;
}
@@ -382,6 +389,13 @@ const QLocaleData *QLocaleData::findLocaleData(QLocale::Language language, QLoca
QList<QLocaleId> tried;
tried.push_back(likelyId);
+ // No match; try again with raw data:
+ if (!tried.contains(localeId)) {
+ if (const QLocaleData *const data = findLocaleDataById(localeId))
+ return data;
+ tried.push_back(localeId);
+ }
+
// No match; try again with likely country
if (country != QLocale::AnyCountry
&& (language != QLocale::AnyLanguage || script != QLocale::AnyScript)) {
@@ -614,8 +628,7 @@ QSystemLocale::QSystemLocale()
{
_systemLocale = this;
- if (system_data)
- system_data->m_language_id = 0;
+ globalLocaleData.m_language_id = 0;
}
/*!
@@ -632,8 +645,7 @@ QSystemLocale::~QSystemLocale()
if (_systemLocale == this) {
_systemLocale = 0;
- if (system_data)
- system_data->m_language_id = 0;
+ globalLocaleData.m_language_id = 0;
}
}
@@ -646,48 +658,47 @@ static const QSystemLocale *systemLocale()
void QLocalePrivate::updateSystemPrivate()
{
+ // this function is NOT thread-safe!
const QSystemLocale *sys_locale = systemLocale();
- if (!system_data)
- system_data = &globalLocaleData;
// tell the object that the system locale has changed.
sys_locale->query(QSystemLocale::LocaleChanged, QVariant());
- *system_data = *sys_locale->fallbackUiLocale().d->m_data;
+ globalLocaleData = *sys_locale->fallbackUiLocale().d->m_data;
QVariant res = sys_locale->query(QSystemLocale::LanguageId, QVariant());
if (!res.isNull()) {
- system_data->m_language_id = res.toInt();
- system_data->m_script_id = QLocale::AnyScript; // default for compatibility
+ globalLocaleData.m_language_id = res.toInt();
+ globalLocaleData.m_script_id = QLocale::AnyScript; // default for compatibility
}
res = sys_locale->query(QSystemLocale::CountryId, QVariant());
if (!res.isNull()) {
- system_data->m_country_id = res.toInt();
- system_data->m_script_id = QLocale::AnyScript; // default for compatibility
+ globalLocaleData.m_country_id = res.toInt();
+ globalLocaleData.m_script_id = QLocale::AnyScript; // default for compatibility
}
res = sys_locale->query(QSystemLocale::ScriptId, QVariant());
if (!res.isNull())
- system_data->m_script_id = res.toInt();
+ globalLocaleData.m_script_id = res.toInt();
res = sys_locale->query(QSystemLocale::DecimalPoint, QVariant());
if (!res.isNull())
- system_data->m_decimal = res.toString().at(0).unicode();
+ globalLocaleData.m_decimal = res.toString().at(0).unicode();
res = sys_locale->query(QSystemLocale::GroupSeparator, QVariant());
if (!res.isNull())
- system_data->m_group = res.toString().at(0).unicode();
+ globalLocaleData.m_group = res.toString().at(0).unicode();
res = sys_locale->query(QSystemLocale::ZeroDigit, QVariant());
if (!res.isNull())
- system_data->m_zero = res.toString().at(0).unicode();
+ globalLocaleData.m_zero = res.toString().at(0).unicode();
res = sys_locale->query(QSystemLocale::NegativeSign, QVariant());
if (!res.isNull())
- system_data->m_minus = res.toString().at(0).unicode();
+ globalLocaleData.m_minus = res.toString().at(0).unicode();
res = sys_locale->query(QSystemLocale::PositiveSign, QVariant());
if (!res.isNull())
- system_data->m_plus = res.toString().at(0).unicode();
+ globalLocaleData.m_plus = res.toString().at(0).unicode();
}
#endif // !QT_NO_SYSTEMLOCALE
@@ -703,12 +714,12 @@ static const QLocaleData *systemData()
{
static QBasicMutex systemDataMutex;
systemDataMutex.lock();
- if (!system_data || system_data->m_language_id == 0)
+ if (globalLocaleData.m_language_id == 0)
QLocalePrivate::updateSystemPrivate();
systemDataMutex.unlock();
}
- return system_data;
+ return &globalLocaleData;
#else
return locale_data;
#endif
@@ -770,6 +781,8 @@ static const int locale_data_size = sizeof(locale_data)/sizeof(QLocaleData) - 1;
Q_GLOBAL_STATIC_WITH_ARGS(QSharedDataPointer<QLocalePrivate>, defaultLocalePrivate,
(QLocalePrivate::create(defaultData(), default_number_options)))
+Q_GLOBAL_STATIC_WITH_ARGS(QSharedDataPointer<QLocalePrivate>, systemLocalePrivate,
+ (QLocalePrivate::create(systemData())))
static QLocalePrivate *localePrivateByName(const QString &name)
{
@@ -1174,7 +1187,7 @@ T toIntegral_helper(const QLocalePrivate *d, QStringView str, bool *ok)
// we select the right overload by the last, unused parameter
Int64 val = toIntegral_helper(d->m_data, str, ok, d->m_numberOptions, Int64());
if (T(val) != val) {
- if (ok)
+ if (ok != nullptr)
*ok = false;
val = 0;
}
@@ -2340,7 +2353,9 @@ QString QLocale::toString(double i, char f, int prec) const
QLocale QLocale::system()
{
- return QLocale(*QLocalePrivate::create(systemData()));
+ // this function is NOT thread-safe!
+ QT_PREPEND_NAMESPACE(systemData)(); // trigger updating of the system data if necessary
+ return QLocale(*systemLocalePrivate->data());
}
@@ -3069,7 +3084,7 @@ QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const Q
QVarLengthArray<char> buf(bufSize);
int length;
- doubleToAscii(d, form, precision, buf.data(), bufSize, negative, length, decpt);
+ qt_doubleToAscii(d, form, precision, buf.data(), bufSize, negative, length, decpt);
if (qstrncmp(buf.data(), "inf", 3) == 0 || qstrncmp(buf.data(), "nan", 3) == 0) {
num_str = QString::fromLatin1(buf.data(), length);
@@ -3573,14 +3588,14 @@ double QLocaleData::stringToDouble(QStringView str, bool *ok,
{
CharBuff buff;
if (!numberToCLocale(str, number_options, &buff)) {
- if (ok != 0)
+ if (ok != nullptr)
*ok = false;
return 0.0;
}
int processed = 0;
bool nonNullOk = false;
- double d = asciiToDouble(buff.constData(), buff.length() - 1, nonNullOk, processed);
- if (ok)
+ double d = qt_asciiToDouble(buff.constData(), buff.length() - 1, nonNullOk, processed);
+ if (ok != nullptr)
*ok = nonNullOk;
return d;
}
@@ -3590,7 +3605,7 @@ qlonglong QLocaleData::stringToLongLong(QStringView str, int base, bool *ok,
{
CharBuff buff;
if (!numberToCLocale(str, number_options, &buff)) {
- if (ok != 0)
+ if (ok != nullptr)
*ok = false;
return 0;
}
@@ -3603,7 +3618,7 @@ qulonglong QLocaleData::stringToUnsLongLong(QStringView str, int base, bool *ok,
{
CharBuff buff;
if (!numberToCLocale(str, number_options, &buff)) {
- if (ok != 0)
+ if (ok != nullptr)
*ok = false;
return 0;
}
@@ -3617,8 +3632,8 @@ double QLocaleData::bytearrayToDouble(const char *num, bool *ok)
int len = static_cast<int>(strlen(num));
Q_ASSERT(len >= 0);
int processed = 0;
- double d = asciiToDouble(num, len, nonNullOk, processed);
- if (ok)
+ double d = qt_asciiToDouble(num, len, nonNullOk, processed);
+ if (ok != nullptr)
*ok = nonNullOk;
return d;
}
@@ -3629,7 +3644,7 @@ qlonglong QLocaleData::bytearrayToLongLong(const char *num, int base, bool *ok)
const char *endptr;
if (*num == '\0') {
- if (ok != 0)
+ if (ok != nullptr)
*ok = false;
return 0;
}
@@ -3637,19 +3652,24 @@ qlonglong QLocaleData::bytearrayToLongLong(const char *num, int base, bool *ok)
qlonglong l = qstrtoll(num, &endptr, base, &_ok);
if (!_ok) {
- if (ok != 0)
+ if (ok != nullptr)
*ok = false;
return 0;
}
if (*endptr != '\0') {
+ while (ascii_isspace(*endptr))
+ ++endptr;
+ }
+
+ if (*endptr != '\0') {
// we stopped at a non-digit character after converting some digits
- if (ok != 0)
+ if (ok != nullptr)
*ok = false;
return 0;
}
- if (ok != 0)
+ if (ok != nullptr)
*ok = true;
return l;
}
@@ -3660,13 +3680,24 @@ qulonglong QLocaleData::bytearrayToUnsLongLong(const char *num, int base, bool *
const char *endptr;
qulonglong l = qstrtoull(num, &endptr, base, &_ok);
- if (!_ok || *endptr != '\0') {
- if (ok != 0)
+ if (!_ok) {
+ if (ok != nullptr)
+ *ok = false;
+ return 0;
+ }
+
+ if (*endptr != '\0') {
+ while (ascii_isspace(*endptr))
+ ++endptr;
+ }
+
+ if (*endptr != '\0') {
+ if (ok != nullptr)
*ok = false;
return 0;
}
- if (ok != 0)
+ if (ok != nullptr)
*ok = true;
return l;
}
diff --git a/src/corelib/tools/qlocale.h b/src/corelib/tools/qlocale.h
index 681867d14a..f3afb8c406 100644
--- a/src/corelib/tools/qlocale.h
+++ b/src/corelib/tools/qlocale.h
@@ -437,19 +437,19 @@ public:
Osage = 358,
Tangut = 359,
- Norwegian = NorwegianBokmal,
- Moldavian = Romanian,
- SerboCroatian = Serbian,
- Tagalog = Filipino,
- Twi = Akan,
Afan = Oromo,
- Byelorussian = Belarusian,
Bhutani = Dzongkha,
+ Byelorussian = Belarusian,
Cambodian = Khmer,
- Kurundi = Rundi,
- RhaetoRomance = Romansh,
Chewa = Nyanja,
Frisian = WesternFrisian,
+ Kurundi = Rundi,
+ Moldavian = Romanian,
+ Norwegian = NorwegianBokmal,
+ RhaetoRomance = Romansh,
+ SerboCroatian = Serbian,
+ Tagalog = Filipino,
+ Twi = Akan,
Uigur = Uighur,
LastLanguage = Tangut
@@ -851,7 +851,7 @@ public:
Serbia = 243,
SaintBarthelemy = 244,
SaintMartin = 245,
- LatinAmericaAndTheCaribbean = 246,
+ LatinAmerica = 246,
AscensionIsland = 247,
AlandIslands = 248,
DiegoGarcia = 249,
@@ -865,17 +865,20 @@ public:
Kosovo = 257,
EuropeanUnion = 258,
OutlyingOceania = 259,
+ World = 260,
+ Europe = 261,
- Tokelau = TokelauCountry,
- Tuvalu = TuvaluCountry,
DemocraticRepublicOfCongo = CongoKinshasa,
- PeoplesRepublicOfCongo = CongoBrazzaville,
DemocraticRepublicOfKorea = NorthKorea,
+ LatinAmericaAndTheCaribbean = LatinAmerica,
+ PeoplesRepublicOfCongo = CongoBrazzaville,
RepublicOfKorea = SouthKorea,
RussianFederation = Russia,
SyrianArabRepublic = Syria,
+ Tokelau = TokelauCountry,
+ Tuvalu = TuvaluCountry,
- LastCountry = OutlyingOceania
+ LastCountry = Europe
};
// GENERATED PART ENDS HERE
diff --git a/src/corelib/tools/qlocale.qdoc b/src/corelib/tools/qlocale.qdoc
index c23e4e3439..76ca909d83 100644
--- a/src/corelib/tools/qlocale.qdoc
+++ b/src/corelib/tools/qlocale.qdoc
@@ -92,7 +92,7 @@
\note For the current keyboard input locale take a look at
QInputMethod::locale().
- QLocale's data is based on Common Locale Data Repository v31.0.1.
+ QLocale's data is based on Common Locale Data Repository v34.
\sa QString::arg(), QString::toInt(), QString::toDouble(),
QInputMethod::locale()
@@ -568,6 +568,7 @@
\value Estonia
\value Ethiopia
\value EuropeanUnion Since Qt 5.7
+ \value Europe Since Qt 5.12
\value FalklandIslands
\value FaroeIslands
\value Fiji
@@ -619,6 +620,8 @@
\value Kuwait
\value Kyrgyzstan
\value Laos
+ \value LatinAmerica
+ \value LatinAmericaAndTheCaribbean Obsolete, please use LatinAmerica
\value Latvia
\value Lebanon
\value Lesotho
@@ -742,6 +745,7 @@
\value UnitedStatesVirginIslands
\value WallisAndFutunaIslands
\value WesternSahara
+ \value World Since Qt 5.12
\value Yemen
\value Zambia
\value Zimbabwe
@@ -749,7 +753,6 @@
\value Serbia
\value SaintBarthelemy
\value SaintMartin
- \value LatinAmericaAndTheCaribbean
\value AscensionIsland
\value AlandIslands
\value DiegoGarcia
diff --git a/src/corelib/tools/qlocale_data_p.h b/src/corelib/tools/qlocale_data_p.h
index cf210454d4..507afdcecd 100644
--- a/src/corelib/tools/qlocale_data_p.h
+++ b/src/corelib/tools/qlocale_data_p.h
@@ -77,8 +77,8 @@ static const int ImperialMeasurementSystemsCount =
// GENERATED PART STARTS HERE
/*
- This part of the file was generated on 2017-06-07 from the
- Common Locale Data Repository v31.0.1
+ This part of the file was generated on 2018-10-19 from the
+ Common Locale Data Repository v34
http://www.unicode.org/cldr/
@@ -171,6 +171,7 @@ static const QLocaleId likely_subtags[] = {
{ 43, 0, 0 }, { 43, 16, 85 }, // el -> el_Grek_GR
{ 31, 0, 0 }, { 31, 7, 225 }, // en -> en_Latn_US
{ 31, 92, 0 }, { 31, 92, 224 }, // en_Shaw -> en_Shaw_GB
+ { 32, 0, 0 }, { 32, 7, 260 }, // eo -> eo_Latn_001
{ 111, 0, 0 }, { 111, 7, 197 }, // es -> es_Latn_ES
{ 33, 0, 0 }, { 33, 7, 68 }, // et -> et_Latn_EE
{ 278, 0, 0 }, { 278, 79, 106 }, // ett -> ett_Ital_IT
@@ -217,7 +218,7 @@ static const QLocaleId likely_subtags[] = {
{ 50, 0, 0 }, { 50, 7, 98 }, // hu -> hu_Latn_HU
{ 9, 0, 0 }, { 9, 10, 11 }, // hy -> hy_Armn_AM
{ 223, 0, 0 }, { 223, 7, 148 }, // hz -> hz_Latn_NA
- { 53, 0, 0 }, { 53, 7, 74 }, // ia -> ia_Latn_FR
+ { 53, 0, 0 }, { 53, 7, 260 }, // ia -> ia_Latn_001
{ 52, 0, 0 }, { 52, 7, 101 }, // id -> id_Latn_ID
{ 149, 0, 0 }, { 149, 7, 157 }, // ig -> ig_Latn_NG
{ 168, 0, 0 }, { 168, 34, 44 }, // ii -> ii_Yiii_CN
@@ -258,6 +259,7 @@ static const QLocaleId likely_subtags[] = {
{ 66, 0, 0 }, { 66, 22, 114 }, // ko -> ko_Kore_KR
{ 147, 0, 0 }, { 147, 13, 100 }, // kok -> kok_Deva_IN
{ 169, 0, 0 }, { 169, 7, 121 }, // kpe -> kpe_Latn_LR
+ { 225, 0, 0 }, { 225, 7, 0 }, // kr -> kr_Latn
{ 62, 0, 0 }, { 62, 1, 100 }, // ks -> ks_Arab_IN
{ 214, 0, 0 }, { 214, 7, 210 }, // ksb -> ksb_Latn_TZ
{ 243, 0, 0 }, { 243, 7, 37 }, // ksf -> ksf_Latn_CM
@@ -363,6 +365,7 @@ static const QLocaleId likely_subtags[] = {
{ 342, 0, 0 }, { 342, 41, 100 }, // pka -> pka_Brah_IN
{ 90, 0, 0 }, { 90, 7, 172 }, // pl -> pl_Latn_PL
{ 300, 0, 0 }, { 300, 64, 163 }, // pra -> pra_Khar_PK
+ { 322, 0, 0 }, { 322, 7, 260 }, // prg -> prg_Latn_001
{ 88, 0, 0 }, { 88, 1, 1 }, // ps -> ps_Arab_AF
{ 91, 0, 0 }, { 91, 7, 30 }, // pt -> pt_Latn_BR
{ 93, 0, 0 }, { 93, 7, 169 }, // qu -> qu_Latn_PE
@@ -460,6 +463,7 @@ static const QLocaleId likely_subtags[] = {
{ 252, 0, 0 }, { 252, 35, 121 }, // vai -> vai_Vaii_LR
{ 160, 0, 0 }, { 160, 7, 195 }, // ve -> ve_Latn_ZA
{ 132, 0, 0 }, { 132, 7, 232 }, // vi -> vi_Latn_VN
+ { 133, 0, 0 }, { 133, 7, 260 }, // vo -> vo_Latn_001
{ 187, 0, 0 }, { 187, 7, 210 }, // vun -> vun_Latn_TZ
{ 236, 0, 0 }, { 236, 7, 21 }, // wa -> wa_Latn_BE
{ 253, 0, 0 }, { 253, 7, 206 }, // wae -> wae_Latn_CH
@@ -477,6 +481,7 @@ static const QLocaleId likely_subtags[] = {
{ 298, 0, 0 }, { 298, 59, 102 }, // xpr -> xpr_Prti_IR
{ 302, 0, 0 }, { 302, 81, 237 }, // xsa -> xsa_Sarb_YE
{ 254, 0, 0 }, { 254, 7, 37 }, // yav -> yav_Latn_CM
+ { 137, 0, 0 }, { 137, 18, 260 }, // yi -> yi_Hebr_001
{ 138, 0, 0 }, { 138, 7, 157 }, // yo -> yo_Latn_NG
{ 357, 0, 0 }, { 357, 6, 97 }, // yue -> yue_Hant_HK
{ 357, 0, 44 }, { 357, 5, 44 }, // yue_CN -> yue_Hans_CN
@@ -504,6 +509,7 @@ static const QLocaleId likely_subtags[] = {
{ 25, 140, 0 }, { 25, 140, 208 }, // zh_Hanb -> zh_Hanb_TW
{ 25, 6, 0 }, { 25, 6, 208 }, // zh_Hant -> zh_Hant_TW
{ 140, 0, 0 }, { 140, 7, 195 }, // zu -> zu_Latn_ZA
+ { 0, 0, 261 }, { 96, 2, 178 }, // und_150 -> ru_Cyrl_RU
{ 0, 0, 246 }, { 111, 7, 246 }, // und_419 -> es_Latn_419
{ 0, 0, 5 }, { 24, 7, 5 }, // und_AD -> ca_Latn_AD
{ 0, 0, 223 }, { 8, 1, 223 }, // und_AE -> ar_Arab_AE
@@ -653,7 +659,7 @@ static const QLocaleId likely_subtags[] = {
{ 0, 0, 164 }, { 350, 7, 164 }, // und_PW -> pau_Latn_PW
{ 0, 0, 168 }, { 45, 7, 168 }, // und_PY -> gn_Latn_PY
{ 0, 0, 175 }, { 8, 1, 175 }, // und_QA -> ar_Arab_QA
- { 0, 0, 259 }, { 31, 7, 31 }, // und_QO -> en_Latn_IO
+ { 0, 0, 259 }, { 31, 7, 249 }, // und_QO -> en_Latn_DG
{ 0, 0, 176 }, { 37, 7, 176 }, // und_RE -> fr_Latn_RE
{ 0, 0, 177 }, { 95, 7, 177 }, // und_RO -> ro_Latn_RO
{ 0, 0, 243 }, { 100, 2, 243 }, // und_RS -> sr_Cyrl_RS
@@ -766,7 +772,6 @@ static const QLocaleId likely_subtags[] = {
{ 0, 56, 0 }, { 280, 56, 170 }, // und_Hano -> hnn_Hano_PH
{ 0, 5, 0 }, { 25, 5, 44 }, // und_Hans -> zh_Hans_CN
{ 0, 6, 0 }, { 25, 6, 208 }, // und_Hant -> zh_Hant_TW
- { 0, 6, 44 }, { 357, 6, 44 }, // und_Hant_CN -> yue_Hant_CN
{ 0, 130, 0 }, { 356, 130, 103 }, // und_Hatr -> mis_Hatr_IQ
{ 0, 18, 0 }, { 48, 18, 105 }, // und_Hebr -> he_Hebr_IL
{ 0, 18, 38 }, { 137, 18, 38 }, // und_Hebr_CA -> yi_Hebr_CA
@@ -896,218 +901,218 @@ static const quint16 locale_index[] = {
6, // Albanian
9, // Amharic
10, // Arabic
- 37, // Armenian
- 38, // Assamese
+ 38, // Armenian
+ 39, // Assamese
0, // Aymara
- 39, // Azerbaijani
- 42, // Bashkir
- 43, // Basque
- 44, // Bengali
- 46, // Dzongkha
+ 40, // Azerbaijani
+ 43, // Bashkir
+ 44, // Basque
+ 45, // Bengali
+ 47, // Dzongkha
0, // Bihari
0, // Bislama
- 47, // Breton
- 48, // Bulgarian
- 49, // Burmese
- 50, // Belarusian
- 51, // Khmer
- 52, // Catalan
- 56, // Chinese
- 63, // Corsican
- 64, // Croatian
- 66, // Czech
- 67, // Danish
- 69, // Dutch
- 76, // English
- 0, // Esperanto
- 179, // Estonian
- 180, // Faroese
+ 48, // Breton
+ 49, // Bulgarian
+ 50, // Burmese
+ 51, // Belarusian
+ 52, // Khmer
+ 53, // Catalan
+ 57, // Chinese
+ 64, // Corsican
+ 65, // Croatian
+ 67, // Czech
+ 68, // Danish
+ 70, // Dutch
+ 77, // English
+ 182, // Esperanto
+ 183, // Estonian
+ 184, // Faroese
0, // Fijian
- 182, // Finnish
- 183, // French
- 229, // Western Frisian
- 230, // Gaelic
- 231, // Galician
- 232, // Georgian
- 233, // German
- 240, // Greek
- 242, // Greenlandic
- 243, // Guarani
- 244, // Gujarati
- 245, // Hausa
- 249, // Hebrew
- 250, // Hindi
- 251, // Hungarian
- 252, // Icelandic
- 253, // Indonesian
- 254, // Interlingua
+ 186, // Finnish
+ 187, // French
+ 233, // Western Frisian
+ 234, // Gaelic
+ 235, // Galician
+ 236, // Georgian
+ 237, // German
+ 244, // Greek
+ 246, // Greenlandic
+ 247, // Guarani
+ 248, // Gujarati
+ 249, // Hausa
+ 253, // Hebrew
+ 254, // Hindi
+ 255, // Hungarian
+ 256, // Icelandic
+ 257, // Indonesian
+ 258, // Interlingua
0, // Interlingue
- 255, // Inuktitut
+ 259, // Inuktitut
0, // Inupiak
- 257, // Irish
- 258, // Italian
- 262, // Japanese
- 263, // Javanese
- 264, // Kannada
- 265, // Kashmiri
- 266, // Kazakh
- 267, // Kinyarwanda
- 268, // Kirghiz
- 269, // Korean
- 271, // Kurdish
- 272, // Rundi
- 273, // Lao
+ 261, // Irish
+ 262, // Italian
+ 266, // Japanese
+ 267, // Javanese
+ 268, // Kannada
+ 269, // Kashmiri
+ 270, // Kazakh
+ 271, // Kinyarwanda
+ 272, // Kirghiz
+ 273, // Korean
+ 275, // Kurdish
+ 276, // Rundi
+ 277, // Lao
0, // Latin
- 274, // Latvian
- 275, // Lingala
- 279, // Lithuanian
- 280, // Macedonian
- 281, // Malagasy
- 282, // Malay
- 286, // Malayalam
- 287, // Maltese
- 288, // Maori
- 289, // Marathi
+ 278, // Latvian
+ 279, // Lingala
+ 283, // Lithuanian
+ 284, // Macedonian
+ 285, // Malagasy
+ 286, // Malay
+ 290, // Malayalam
+ 291, // Maltese
+ 292, // Maori
+ 293, // Marathi
0, // Marshallese
- 290, // Mongolian
+ 294, // Mongolian
0, // Nauru
- 292, // Nepali
- 294, // NorwegianBokmal
- 296, // Occitan
- 297, // Oriya
- 298, // Pashto
- 299, // Persian
- 301, // Polish
- 302, // Portuguese
- 314, // Punjabi
- 316, // Quechua
- 319, // Romansh
- 320, // Romanian
- 322, // Russian
+ 296, // Nepali
+ 298, // Norwegian Bokmal
+ 300, // Occitan
+ 301, // Oriya
+ 302, // Pashto
+ 303, // Persian
+ 305, // Polish
+ 306, // Portuguese
+ 318, // Punjabi
+ 320, // Quechua
+ 323, // Romansh
+ 324, // Romanian
+ 326, // Russian
0, // Samoan
- 328, // Sango
- 329, // Sanskrit
- 330, // Serbian
- 338, // Ossetic
- 340, // Southern Sotho
- 341, // Tswana
- 342, // Shona
- 343, // Sindhi
- 344, // Sinhala
- 345, // Swati
- 346, // Slovak
- 347, // Slovenian
- 348, // Somali
- 352, // Spanish
+ 332, // Sango
+ 333, // Sanskrit
+ 334, // Serbian
+ 342, // Ossetic
+ 344, // Southern Sotho
+ 345, // Tswana
+ 346, // Shona
+ 347, // Sindhi
+ 348, // Sinhala
+ 349, // Swati
+ 350, // Slovak
+ 351, // Slovenian
+ 352, // Somali
+ 356, // Spanish
0, // Sundanese
- 380, // Swahili
- 384, // Swedish
- 0, // Sardinian
- 387, // Tajik
- 388, // Tamil
- 392, // Tatar
- 393, // Telugu
- 394, // Thai
- 395, // Tibetan
- 397, // Tigrinya
- 399, // Tongan
- 400, // Tsonga
- 401, // Turkish
- 403, // Turkmen
+ 384, // Swahili
+ 388, // Swedish
+ 391, // Sardinian
+ 392, // Tajik
+ 393, // Tamil
+ 397, // Tatar
+ 398, // Telugu
+ 399, // Thai
+ 400, // Tibetan
+ 402, // Tigrinya
+ 404, // Tongan
+ 405, // Tsonga
+ 406, // Turkish
+ 408, // Turkmen
0, // Tahitian
- 404, // Uighur
- 405, // Ukrainian
- 406, // Urdu
- 408, // Uzbek
- 411, // Vietnamese
- 0, // Volapuk
- 412, // Welsh
- 413, // Wolof
- 414, // Xhosa
- 0, // Yiddish
- 415, // Yoruba
+ 409, // Uighur
+ 410, // Ukrainian
+ 411, // Urdu
+ 413, // Uzbek
+ 416, // Vietnamese
+ 417, // Volapuk
+ 418, // Welsh
+ 419, // Wolof
+ 420, // Xhosa
+ 421, // Yiddish
+ 422, // Yoruba
0, // Zhuang
- 417, // Zulu
- 418, // NorwegianNynorsk
- 419, // Bosnian
- 421, // Divehi
- 422, // Manx
- 423, // Cornish
- 424, // Akan
- 425, // Konkani
- 426, // Ga
- 427, // Igbo
- 428, // Kamba
- 429, // Syriac
- 430, // Blin
- 431, // Geez
+ 424, // Zulu
+ 425, // Norwegian Nynorsk
+ 426, // Bosnian
+ 428, // Divehi
+ 429, // Manx
+ 430, // Cornish
+ 431, // Akan
+ 432, // Konkani
+ 433, // Ga
+ 434, // Igbo
+ 435, // Kamba
+ 436, // Syriac
+ 437, // Blin
+ 438, // Geez
0, // Koro
- 432, // Sidamo
- 433, // Atsam
- 434, // Tigre
- 435, // Jju
- 436, // Friulian
- 437, // Venda
- 438, // Ewe
- 440, // Walamo
- 441, // Hawaiian
- 442, // Tyap
- 443, // Nyanja
- 444, // Filipino
- 445, // Swiss German
- 448, // Sichuan Yi
- 449, // Kpelle
- 450, // Low German
- 452, // South Ndebele
- 453, // Northern Sotho
- 454, // Northern Sami
- 457, // Taroko
- 458, // Gusii
- 459, // Taita
- 460, // Fulah
- 464, // Kikuyu
- 465, // Samburu
- 466, // Sena
- 467, // North Ndebele
- 468, // Rombo
- 469, // Tachelhit
- 471, // Kabyle
- 472, // Nyankole
- 473, // Bena
- 474, // Vunjo
- 475, // Bambara
- 477, // Embu
- 478, // Cherokee
- 479, // Morisyen
- 480, // Makonde
- 481, // Langi
- 482, // Ganda
- 483, // Bemba
- 484, // Kabuverdianu
- 485, // Meru
- 486, // Kalenjin
- 487, // Nama
- 488, // Machame
- 489, // Colognian
- 490, // Masai
- 492, // Soga
- 493, // Luyia
- 494, // Asu
- 495, // Teso
- 497, // Saho
- 498, // Koyra Chiini
- 499, // Rwa
- 500, // Luo
- 501, // Chiga
- 502, // Central Morocco Tamazight
- 503, // Koyraboro Senni
- 504, // Shambala
- 505, // Bodo
+ 439, // Sidamo
+ 440, // Atsam
+ 441, // Tigre
+ 442, // Jju
+ 443, // Friulian
+ 444, // Venda
+ 445, // Ewe
+ 447, // Walamo
+ 448, // Hawaiian
+ 449, // Tyap
+ 450, // Nyanja
+ 451, // Filipino
+ 452, // Swiss German
+ 455, // Sichuan Yi
+ 456, // Kpelle
+ 457, // Low German
+ 459, // South Ndebele
+ 460, // Northern Sotho
+ 461, // Northern Sami
+ 464, // Taroko
+ 465, // Gusii
+ 466, // Taita
+ 467, // Fulah
+ 480, // Kikuyu
+ 481, // Samburu
+ 482, // Sena
+ 483, // North Ndebele
+ 484, // Rombo
+ 485, // Tachelhit
+ 487, // Kabyle
+ 488, // Nyankole
+ 489, // Bena
+ 490, // Vunjo
+ 491, // Bambara
+ 493, // Embu
+ 494, // Cherokee
+ 495, // Morisyen
+ 496, // Makonde
+ 497, // Langi
+ 498, // Ganda
+ 499, // Bemba
+ 500, // Kabuverdianu
+ 501, // Meru
+ 502, // Kalenjin
+ 503, // Nama
+ 504, // Machame
+ 505, // Colognian
+ 506, // Masai
+ 508, // Soga
+ 509, // Luyia
+ 510, // Asu
+ 511, // Teso
+ 513, // Saho
+ 514, // Koyra Chiini
+ 515, // Rwa
+ 516, // Luo
+ 517, // Chiga
+ 518, // Central Morocco Tamazight
+ 519, // Koyraboro Senni
+ 520, // Shambala
+ 521, // Bodo
0, // Avaric
0, // Chamorro
- 506, // Chechen
- 507, // Church
- 508, // Chuvash
+ 522, // Chechen
+ 523, // Church
+ 524, // Chuvash
0, // Cree
0, // Haitian
0, // Herero
@@ -1117,59 +1122,59 @@ static const quint16 locale_index[] = {
0, // Kongo
0, // Kwanyama
0, // Limburgish
- 509, // LubaKatanga
- 510, // Luxembourgish
+ 525, // Luba Katanga
+ 526, // Luxembourgish
0, // Navaho
0, // Ndonga
0, // Ojibwa
0, // Pali
- 511, // Walloon
- 512, // Aghem
- 513, // Basaa
- 514, // Zarma
- 515, // Duala
- 516, // JolaFonyi
- 517, // Ewondo
- 518, // Bafia
- 519, // MakhuwaMeetto
- 520, // Mundang
- 521, // Kwasio
- 522, // Nuer
- 523, // Sakha
- 524, // Sangu
+ 527, // Walloon
+ 528, // Aghem
+ 529, // Basaa
+ 530, // Zarma
+ 531, // Duala
+ 532, // Jola Fonyi
+ 533, // Ewondo
+ 534, // Bafia
+ 535, // Makhuwa Meetto
+ 536, // Mundang
+ 537, // Kwasio
+ 538, // Nuer
+ 539, // Sakha
+ 540, // Sangu
0, // Congo Swahili
- 525, // Tasawaq
- 526, // Vai
- 528, // Walser
- 529, // Yangben
+ 541, // Tasawaq
+ 542, // Vai
+ 544, // Walser
+ 545, // Yangben
0, // Avestan
- 530, // Asturian
- 531, // Ngomba
- 532, // Kako
- 533, // Meta
- 534, // Ngiemboon
+ 546, // Asturian
+ 547, // Ngomba
+ 548, // Kako
+ 549, // Meta
+ 550, // Ngiemboon
0, // Aragonese
0, // Akkadian
- 0, // AncientEgyptian
- 0, // AncientGreek
+ 0, // Ancient Egyptian
+ 0, // Ancient Greek
0, // Aramaic
0, // Balinese
0, // Bamun
- 0, // BatakToba
+ 0, // Batak Toba
0, // Buginese
0, // Buhid
0, // Carian
- 535, // Chakma
- 0, // ClassicalMandaic
+ 0, // Chakma
+ 0, // Classical Mandaic
0, // Coptic
0, // Dogri
- 0, // EasternCham
- 0, // EasternKayah
+ 0, // Eastern Cham
+ 0, // Eastern Kayah
0, // Etruscan
0, // Gothic
0, // Hanunoo
0, // Ingush
- 0, // LargeFloweryMiao
+ 0, // Large Flowery Miao
0, // Lepcha
0, // Limbu
0, // Lisu
@@ -1177,17 +1182,17 @@ static const quint16 locale_index[] = {
0, // Lycian
0, // Lydian
0, // Mandingo
- 536, // Manipuri
+ 551, // Manipuri
0, // Meroitic
- 0, // NorthernThai
- 0, // OldIrish
- 0, // OldNorse
- 0, // OldPersian
- 0, // OldTurkish
+ 0, // Northern Thai
+ 0, // Old Irish
+ 0, // Old Norse
+ 0, // Old Persian
+ 0, // Old Turkish
0, // Pahlavi
0, // Parthian
0, // Phoenician
- 0, // PrakritLanguage
+ 0, // Prakrit Language
0, // Rejang
0, // Sabaean
0, // Samaritan
@@ -1196,26 +1201,26 @@ static const quint16 locale_index[] = {
0, // Sora
0, // Sylheti
0, // Tagbanwa
- 537, // TaiDam
- 0, // TaiNua
+ 552, // Tai Dam
+ 0, // Tai Nua
0, // Ugaritic
- 538, // Akoose
- 539, // Lakota
- 540, // Standard Moroccan Tamazight
- 541, // Mapuche
- 542, // Central Kurdish
- 544, // LowerSorbian
- 545, // UpperSorbian
- 546, // Kenyang
- 547, // Mohawk
- 548, // Nko
- 0, // Prussian
- 549, // Kiche
- 550, // Southern Sami
- 551, // Lule Sami
- 552, // Inari Sami
- 553, // Skolt Sami
- 554, // Warlpiri
+ 553, // Akoose
+ 554, // Lakota
+ 555, // Standard Moroccan Tamazight
+ 556, // Mapuche
+ 557, // Central Kurdish
+ 559, // Lower Sorbian
+ 560, // Upper Sorbian
+ 561, // Kenyang
+ 562, // Mohawk
+ 563, // Nko
+ 564, // Prussian
+ 565, // Kiche
+ 566, // Southern Sami
+ 567, // Lule Sami
+ 568, // Inari Sami
+ 569, // Skolt Sami
+ 570, // Warlpiri
0, // Manichaean Middle Persian
0, // Mende
0, // Ancient North Arabian
@@ -1233,18 +1238,18 @@ static const quint16 locale_index[] = {
0, // Bhojpuri
0, // Hieroglyphic Luwian
0, // Literary Chinese
- 555, // Mazanderani
+ 571, // Mazanderani
0, // Mru
0, // Newari
- 556, // Northern Luri
+ 572, // Northern Luri
0, // Palauan
0, // Papiamento
0, // Saraiki
0, // Tokelau
0, // Tok Pisin
0, // Tuvalu
- 0, // UncodedLanguages
- 558, // Cantonese
+ 0, // Uncoded Languages
+ 574, // Cantonese
0, // Osage
0, // Tangut
0 // trailing 0
@@ -1256,561 +1261,578 @@ static const QLocaleData locale_data[] = {
{ 3, 7, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 35,18 , 18,7 , 25,12 , 185,48 , 233,111 , 134,24 , 185,48 , 233,111 , 134,24 , 113,28 , 141,55 , 85,14 , 113,28 , 141,55 , 85,14 , 2,2 , 2,2 , 45,4 , 5,17 , 22,23 , {69,84,66}, 0,2 , 7,24 , 4,4 , 4,0 , 0,6 , 6,10 , 2, 1, 7, 6, 7 }, // Oromo/Latin/Ethiopia
{ 3, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 35,18 , 37,5 , 8,10 , 185,48 , 233,111 , 344,24 , 185,48 , 233,111 , 134,24 , 113,28 , 141,55 , 196,14 , 113,28 , 141,55 , 196,14 , 2,2 , 2,2 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 0,7 , 4,4 , 4,0 , 0,6 , 16,8 , 2, 1, 7, 6, 7 }, // Oromo/Latin/Kenya
{ 4, 7, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,84,66}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Afar/Latin/Ethiopia
- { 5, 7, 195, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 6,8 , 6,8 , 53,10 , 80,18 , 37,5 , 8,10 , 416,59 , 475,92 , 134,24 , 416,59 , 475,92 , 134,24 , 210,28 , 238,58 , 296,14 , 210,28 , 238,58 , 296,14 , 4,3 , 4,3 , 49,5 , 5,17 , 22,23 , {90,65,82}, 5,1 , 31,67 , 4,4 , 4,0 , 24,9 , 33,11 , 2, 1, 7, 6, 7 }, // Afrikaans/Latin/SouthAfrica
- { 5, 7, 148, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 6,8 , 6,8 , 53,10 , 98,16 , 37,5 , 8,10 , 416,59 , 475,92 , 134,24 , 416,59 , 475,92 , 134,24 , 210,28 , 238,58 , 296,14 , 210,28 , 238,58 , 296,14 , 4,3 , 4,3 , 49,5 , 5,17 , 22,23 , {78,65,68}, 6,1 , 98,55 , 4,4 , 4,0 , 24,9 , 44,7 , 2, 1, 1, 6, 7 }, // Afrikaans/Latin/Namibia
- { 6, 7, 2, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 14,9 , 14,9 , 114,6 , 10,17 , 18,7 , 42,13 , 567,48 , 615,78 , 693,24 , 717,48 , 765,78 , 843,24 , 310,28 , 338,58 , 396,14 , 310,28 , 410,58 , 396,14 , 7,11 , 7,10 , 54,4 , 5,17 , 22,23 , {65,76,76}, 7,4 , 153,45 , 13,5 , 4,0 , 51,5 , 56,8 , 0, 0, 1, 6, 7 }, // Albanian/Latin/Albania
- { 6, 7, 127, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 14,9 , 14,9 , 114,6 , 10,17 , 37,5 , 8,10 , 567,48 , 615,78 , 693,24 , 717,48 , 765,78 , 843,24 , 310,28 , 338,58 , 396,14 , 310,28 , 410,58 , 396,14 , 7,11 , 7,10 , 54,4 , 5,17 , 22,23 , {77,75,68}, 11,3 , 198,54 , 13,5 , 4,0 , 51,5 , 64,8 , 2, 1, 1, 6, 7 }, // Albanian/Latin/Macedonia
- { 6, 7, 257, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 14,9 , 14,9 , 114,6 , 10,17 , 37,5 , 8,10 , 567,48 , 615,78 , 693,24 , 717,48 , 765,78 , 843,24 , 310,28 , 338,58 , 396,14 , 310,28 , 410,58 , 396,14 , 7,11 , 7,10 , 54,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 252,21 , 13,5 , 4,0 , 51,5 , 72,6 , 2, 1, 1, 6, 7 }, // Albanian/Latin/Kosovo
- { 7, 14, 69, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 23,6 , 23,6 , 29,9 , 38,8 , 120,10 , 130,17 , 18,7 , 25,12 , 867,46 , 913,61 , 974,24 , 867,46 , 913,61 , 974,24 , 468,27 , 495,28 , 523,14 , 468,27 , 495,28 , 523,14 , 18,3 , 17,4 , 58,3 , 61,23 , 22,23 , {69,84,66}, 15,2 , 273,34 , 4,4 , 4,0 , 78,4 , 82,5 , 2, 1, 7, 6, 7 }, // Amharic/Ethiopic/Ethiopia
- { 8, 1, 64, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {69,71,80}, 17,5 , 307,81 , 13,5 , 4,0 , 87,7 , 94,3 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/Egypt
- { 8, 1, 3, 44, 46, 59, 37, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 1097,71 , 1097,71 , 1168,24 , 1097,71 , 1097,71 , 1168,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {68,90,68}, 22,5 , 388,102 , 13,5 , 4,0 , 87,7 , 97,7 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/Algeria
- { 8, 1, 17, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {66,72,68}, 27,5 , 490,91 , 13,5 , 4,0 , 87,7 , 104,7 , 3, 0, 6, 5, 6 }, // Arabic/Arabic/Bahrain
- { 8, 1, 42, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {88,65,70}, 32,4 , 581,112 , 13,5 , 4,0 , 87,7 , 111,4 , 0, 0, 1, 6, 7 }, // Arabic/Arabic/Chad
- { 8, 1, 48, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 37,5 , 8,10 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {75,77,70}, 36,7 , 693,105 , 13,5 , 4,0 , 87,7 , 115,9 , 0, 0, 1, 6, 7 }, // Arabic/Arabic/Comoros
- { 8, 1, 59, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {68,74,70}, 43,3 , 798,84 , 13,5 , 4,0 , 87,7 , 124,6 , 0, 0, 6, 6, 7 }, // Arabic/Arabic/Djibouti
- { 8, 1, 67, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {69,82,78}, 46,3 , 882,91 , 13,5 , 4,0 , 87,7 , 130,7 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/Eritrea
- { 8, 1, 103, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 1192,92 , 1192,92 , 1284,24 , 1308,92 , 1192,92 , 1284,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {73,81,68}, 49,5 , 973,84 , 13,5 , 4,0 , 87,7 , 137,6 , 0, 0, 6, 5, 6 }, // Arabic/Arabic/Iraq
- { 8, 1, 105, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 55,4 , 59,9 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {73,76,83}, 54,1 , 1057,133 , 13,5 , 4,0 , 87,7 , 143,7 , 2, 1, 7, 5, 6 }, // Arabic/Arabic/Israel
- { 8, 1, 109, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 1192,92 , 1192,92 , 1284,24 , 1192,92 , 1192,92 , 1284,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {74,79,68}, 55,5 , 1190,84 , 13,5 , 4,0 , 87,7 , 150,6 , 3, 0, 6, 5, 6 }, // Arabic/Arabic/Jordan
- { 8, 1, 115, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {75,87,68}, 60,5 , 1274,84 , 13,5 , 4,0 , 87,7 , 156,6 , 3, 0, 6, 5, 6 }, // Arabic/Arabic/Kuwait
- { 8, 1, 119, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 1192,92 , 1192,92 , 1284,24 , 1192,92 , 1192,92 , 1284,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {76,66,80}, 65,5 , 1358,84 , 13,5 , 4,0 , 87,7 , 162,5 , 0, 0, 1, 6, 7 }, // Arabic/Arabic/Lebanon
- { 8, 1, 122, 44, 46, 59, 37, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {76,89,68}, 70,5 , 1442,88 , 13,5 , 4,0 , 87,7 , 167,5 , 3, 0, 6, 5, 6 }, // Arabic/Arabic/Libya
- { 8, 1, 136, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 1400,72 , 1400,72 , 1472,24 , 1400,72 , 1400,72 , 1472,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {77,82,79}, 75,5 , 1530,112 , 13,5 , 4,0 , 87,7 , 172,9 , 0, 0, 1, 6, 7 }, // Arabic/Arabic/Mauritania
- { 8, 1, 145, 44, 46, 59, 37, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 37,5 , 8,10 , 1496,70 , 1496,70 , 1566,24 , 1496,70 , 1496,70 , 1566,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {77,65,68}, 80,5 , 1642,87 , 13,5 , 4,0 , 87,7 , 181,6 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/Morocco
- { 8, 1, 162, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {79,77,82}, 85,5 , 1729,77 , 13,5 , 4,0 , 87,7 , 187,5 , 3, 0, 6, 5, 6 }, // Arabic/Arabic/Oman
- { 8, 1, 165, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 1192,92 , 1192,92 , 1284,24 , 1192,92 , 1192,92 , 1284,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {73,76,83}, 54,1 , 1057,133 , 13,5 , 4,0 , 87,7 , 192,18 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/PalestinianTerritories
- { 8, 1, 175, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {81,65,82}, 90,5 , 1806,70 , 13,5 , 4,0 , 87,7 , 210,3 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/Qatar
- { 8, 1, 186, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {83,65,82}, 95,5 , 1876,77 , 13,5 , 4,0 , 87,7 , 213,24 , 2, 1, 7, 5, 6 }, // Arabic/Arabic/SaudiArabia
- { 8, 1, 194, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {83,79,83}, 100,1 , 1953,77 , 13,5 , 4,0 , 87,7 , 237,7 , 0, 0, 1, 6, 7 }, // Arabic/Arabic/Somalia
- { 8, 1, 201, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {83,68,71}, 101,4 , 2030,91 , 13,5 , 4,0 , 87,7 , 244,7 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/Sudan
- { 8, 1, 207, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 1192,92 , 1192,92 , 1284,24 , 1192,92 , 1192,92 , 1284,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {83,89,80}, 105,5 , 2121,77 , 13,5 , 4,0 , 87,7 , 251,5 , 0, 0, 6, 5, 6 }, // Arabic/Arabic/Syria
- { 8, 1, 216, 44, 46, 59, 37, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 1097,71 , 1097,71 , 1168,24 , 1097,71 , 1097,71 , 1168,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {84,78,68}, 110,5 , 2198,95 , 13,5 , 4,0 , 87,7 , 256,4 , 3, 0, 7, 5, 6 }, // Arabic/Arabic/Tunisia
- { 8, 1, 223, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {65,69,68}, 115,5 , 2293,91 , 13,5 , 4,0 , 87,7 , 260,24 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/UnitedArabEmirates
- { 8, 1, 236, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {77,65,68}, 80,5 , 1642,87 , 13,5 , 4,0 , 87,7 , 284,15 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/WesternSahara
- { 8, 1, 237, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {89,69,82}, 120,5 , 2384,70 , 13,5 , 4,0 , 87,7 , 299,5 , 0, 0, 7, 5, 6 }, // Arabic/Arabic/Yemen
- { 8, 1, 254, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {83,83,80}, 125,1 , 2454,132 , 13,5 , 4,0 , 87,7 , 304,12 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/SouthSudan
- { 9, 10, 11, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 65,7 , 65,7 , 175,8 , 183,20 , 37,5 , 8,10 , 1590,48 , 1638,94 , 1732,24 , 1590,48 , 1756,106 , 1732,24 , 603,28 , 631,62 , 693,14 , 603,28 , 631,62 , 693,14 , 0,2 , 0,2 , 129,6 , 135,17 , 22,23 , {65,77,68}, 126,1 , 2586,46 , 8,5 , 4,0 , 316,7 , 323,8 , 0, 0, 1, 6, 7 }, // Armenian/Armenian/Armenia
- { 10, 11, 100, 46, 44, 59, 37, 2534, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 203,8 , 211,18 , 68,8 , 76,12 , 1862,62 , 1924,88 , 158,27 , 1862,62 , 1924,88 , 158,27 , 707,37 , 744,58 , 85,14 , 707,37 , 744,58 , 85,14 , 22,9 , 22,7 , 45,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 0,7 , 8,5 , 4,0 , 331,7 , 338,4 , 2, 1, 7, 7, 7 }, // Assamese/Bengali/India
- { 12, 7, 15, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 72,8 , 72,8 , 175,8 , 229,17 , 37,5 , 8,10 , 2012,48 , 2060,77 , 158,27 , 2012,48 , 2137,77 , 158,27 , 802,27 , 829,67 , 99,14 , 802,27 , 829,67 , 99,14 , 0,2 , 0,2 , 152,4 , 5,17 , 22,23 , {65,90,78}, 128,1 , 2632,58 , 8,5 , 4,0 , 342,10 , 352,10 , 2, 1, 1, 6, 7 }, // Azerbaijani/Latin/Azerbaijan
+ { 5, 7, 195, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 6,8 , 6,8 , 53,10 , 80,17 , 37,5 , 8,10 , 416,59 , 475,92 , 134,24 , 416,59 , 475,92 , 134,24 , 210,28 , 238,58 , 296,14 , 210,28 , 238,58 , 296,14 , 4,3 , 4,3 , 49,5 , 5,17 , 22,23 , {90,65,82}, 5,1 , 31,67 , 4,4 , 4,0 , 24,9 , 33,11 , 2, 1, 7, 6, 7 }, // Afrikaans/Latin/South Africa
+ { 5, 7, 148, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 6,8 , 6,8 , 53,10 , 97,16 , 37,5 , 8,10 , 416,59 , 475,92 , 134,24 , 416,59 , 475,92 , 134,24 , 210,28 , 238,58 , 296,14 , 210,28 , 238,58 , 296,14 , 4,3 , 4,3 , 49,5 , 5,17 , 22,23 , {78,65,68}, 6,1 , 98,55 , 4,4 , 4,0 , 24,9 , 44,7 , 2, 1, 1, 6, 7 }, // Afrikaans/Latin/Namibia
+ { 6, 7, 2, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 14,9 , 14,9 , 113,6 , 10,17 , 18,7 , 42,13 , 567,50 , 617,78 , 695,27 , 567,50 , 617,78 , 695,27 , 310,28 , 338,58 , 396,15 , 411,28 , 338,58 , 396,15 , 7,11 , 7,10 , 54,4 , 5,17 , 22,23 , {65,76,76}, 7,4 , 153,45 , 13,5 , 4,0 , 51,5 , 56,8 , 0, 0, 1, 6, 7 }, // Albanian/Latin/Albania
+ { 6, 7, 127, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 14,9 , 14,9 , 113,6 , 10,17 , 37,5 , 8,10 , 567,50 , 617,78 , 695,27 , 567,50 , 617,78 , 695,27 , 310,28 , 338,58 , 396,15 , 411,28 , 338,58 , 396,15 , 7,11 , 7,10 , 54,4 , 5,17 , 22,23 , {77,75,68}, 11,3 , 198,54 , 13,5 , 4,0 , 51,5 , 64,8 , 2, 1, 1, 6, 7 }, // Albanian/Latin/Macedonia
+ { 6, 7, 257, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 14,9 , 14,9 , 113,6 , 10,17 , 37,5 , 8,10 , 567,50 , 617,78 , 695,27 , 567,50 , 617,78 , 695,27 , 310,28 , 338,58 , 396,15 , 411,28 , 338,58 , 396,15 , 7,11 , 7,10 , 54,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 252,21 , 13,5 , 4,0 , 51,5 , 72,6 , 2, 1, 1, 6, 7 }, // Albanian/Latin/Kosovo
+ { 7, 14, 69, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 23,6 , 23,6 , 29,9 , 38,8 , 119,10 , 63,17 , 18,7 , 25,12 , 722,46 , 768,61 , 829,24 , 722,46 , 768,61 , 829,24 , 439,27 , 466,28 , 494,14 , 439,27 , 466,28 , 494,14 , 18,3 , 17,4 , 58,3 , 61,23 , 22,23 , {69,84,66}, 15,2 , 273,34 , 4,4 , 4,0 , 78,4 , 82,5 , 2, 1, 7, 6, 7 }, // Amharic/Ethiopic/Ethiopia
+ { 8, 1, 64, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 853,75 , 853,75 , 928,24 , 853,75 , 853,75 , 928,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {69,71,80}, 17,5 , 307,81 , 13,5 , 4,0 , 87,7 , 94,3 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/Egypt
+ { 8, 1, 3, 44, 46, 59, 37, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 952,71 , 952,71 , 1023,24 , 952,71 , 952,71 , 1023,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {68,90,68}, 22,5 , 388,102 , 13,5 , 4,0 , 87,7 , 97,7 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/Algeria
+ { 8, 1, 17, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 853,75 , 853,75 , 928,24 , 853,75 , 853,75 , 928,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {66,72,68}, 27,5 , 490,91 , 13,5 , 4,0 , 87,7 , 104,7 , 3, 0, 6, 5, 6 }, // Arabic/Arabic/Bahrain
+ { 8, 1, 42, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 853,75 , 853,75 , 928,24 , 853,75 , 853,75 , 928,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {88,65,70}, 32,4 , 581,112 , 13,5 , 4,0 , 87,7 , 111,4 , 0, 0, 1, 6, 7 }, // Arabic/Arabic/Chad
+ { 8, 1, 48, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 37,5 , 8,10 , 853,75 , 853,75 , 928,24 , 853,75 , 853,75 , 928,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {75,77,70}, 36,2 , 693,105 , 13,5 , 4,0 , 87,7 , 115,9 , 0, 0, 1, 6, 7 }, // Arabic/Arabic/Comoros
+ { 8, 1, 59, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 853,75 , 853,75 , 928,24 , 853,75 , 853,75 , 928,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {68,74,70}, 38,3 , 798,84 , 13,5 , 4,0 , 87,7 , 124,6 , 0, 0, 6, 6, 7 }, // Arabic/Arabic/Djibouti
+ { 8, 1, 67, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 853,75 , 853,75 , 928,24 , 853,75 , 853,75 , 928,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {69,82,78}, 41,3 , 882,91 , 13,5 , 4,0 , 87,7 , 130,7 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/Eritrea
+ { 8, 1, 103, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 1047,92 , 1047,92 , 1139,24 , 1163,92 , 1047,92 , 1139,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {73,81,68}, 44,5 , 973,84 , 13,5 , 4,0 , 87,7 , 137,6 , 0, 0, 6, 5, 6 }, // Arabic/Arabic/Iraq
+ { 8, 1, 105, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 55,4 , 59,9 , 853,75 , 853,75 , 928,24 , 853,75 , 853,75 , 928,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {73,76,83}, 49,1 , 1057,133 , 13,5 , 4,0 , 87,7 , 143,7 , 2, 1, 7, 5, 6 }, // Arabic/Arabic/Israel
+ { 8, 1, 109, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 1047,92 , 1047,92 , 1139,24 , 1047,92 , 1047,92 , 1139,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {74,79,68}, 50,5 , 1190,84 , 13,5 , 4,0 , 87,7 , 150,6 , 3, 0, 6, 5, 6 }, // Arabic/Arabic/Jordan
+ { 8, 1, 115, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 853,75 , 853,75 , 928,24 , 853,75 , 853,75 , 928,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {75,87,68}, 55,5 , 1274,84 , 13,5 , 4,0 , 87,7 , 156,6 , 3, 0, 6, 5, 6 }, // Arabic/Arabic/Kuwait
+ { 8, 1, 119, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 1047,92 , 1047,92 , 1139,24 , 1047,92 , 1047,92 , 1139,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {76,66,80}, 60,5 , 1358,84 , 13,5 , 4,0 , 87,7 , 162,5 , 0, 0, 1, 6, 7 }, // Arabic/Arabic/Lebanon
+ { 8, 1, 122, 44, 46, 59, 37, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 853,75 , 853,75 , 928,24 , 853,75 , 853,75 , 928,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {76,89,68}, 65,5 , 1442,88 , 13,5 , 4,0 , 87,7 , 167,5 , 3, 0, 6, 5, 6 }, // Arabic/Arabic/Libya
+ { 8, 1, 136, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 1255,72 , 1255,72 , 1327,24 , 1255,72 , 1255,72 , 1327,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {77,82,85}, 70,4 , 1530,112 , 13,5 , 4,0 , 87,7 , 172,9 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/Mauritania
+ { 8, 1, 145, 44, 46, 59, 37, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 37,5 , 8,10 , 1351,70 , 1351,70 , 1421,24 , 1351,70 , 1351,70 , 1421,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {77,65,68}, 74,5 , 1642,87 , 13,5 , 4,0 , 87,7 , 181,6 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/Morocco
+ { 8, 1, 162, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 853,75 , 853,75 , 928,24 , 853,75 , 853,75 , 928,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {79,77,82}, 79,5 , 1729,77 , 13,5 , 4,0 , 87,7 , 187,5 , 3, 0, 6, 5, 6 }, // Arabic/Arabic/Oman
+ { 8, 1, 165, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 1047,92 , 1047,92 , 1139,24 , 1047,92 , 1047,92 , 1139,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {73,76,83}, 49,1 , 1057,133 , 13,5 , 4,0 , 87,7 , 192,18 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/Palestinian Territories
+ { 8, 1, 175, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 853,75 , 853,75 , 928,24 , 853,75 , 853,75 , 928,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {81,65,82}, 84,5 , 1806,70 , 13,5 , 4,0 , 87,7 , 210,3 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/Qatar
+ { 8, 1, 186, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 853,75 , 853,75 , 928,24 , 853,75 , 853,75 , 928,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {83,65,82}, 89,5 , 1876,77 , 13,5 , 4,0 , 87,7 , 213,24 , 2, 1, 7, 5, 6 }, // Arabic/Arabic/Saudi Arabia
+ { 8, 1, 194, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 853,75 , 853,75 , 928,24 , 853,75 , 853,75 , 928,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {83,79,83}, 94,1 , 1953,77 , 13,5 , 4,0 , 87,7 , 237,7 , 0, 0, 1, 6, 7 }, // Arabic/Arabic/Somalia
+ { 8, 1, 201, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 853,75 , 853,75 , 928,24 , 853,75 , 853,75 , 928,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {83,68,71}, 95,4 , 2030,91 , 13,5 , 4,0 , 87,7 , 244,7 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/Sudan
+ { 8, 1, 207, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 1047,92 , 1047,92 , 1139,24 , 1047,92 , 1047,92 , 1139,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {83,89,80}, 99,5 , 2121,77 , 13,5 , 4,0 , 87,7 , 251,5 , 0, 0, 6, 5, 6 }, // Arabic/Arabic/Syria
+ { 8, 1, 216, 44, 46, 59, 37, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 952,71 , 952,71 , 1023,24 , 952,71 , 952,71 , 1023,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {84,78,68}, 104,5 , 2198,95 , 13,5 , 4,0 , 87,7 , 256,4 , 3, 0, 1, 6, 7 }, // Arabic/Arabic/Tunisia
+ { 8, 1, 223, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 853,75 , 853,75 , 928,24 , 853,75 , 853,75 , 928,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {65,69,68}, 109,5 , 2293,91 , 13,5 , 4,0 , 87,7 , 260,24 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/United Arab Emirates
+ { 8, 1, 236, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 853,75 , 853,75 , 928,24 , 853,75 , 853,75 , 928,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {77,65,68}, 74,5 , 1642,87 , 13,5 , 4,0 , 87,7 , 284,15 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/Western Sahara
+ { 8, 1, 237, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 853,75 , 853,75 , 928,24 , 853,75 , 853,75 , 928,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {89,69,82}, 114,5 , 2384,70 , 13,5 , 4,0 , 87,7 , 299,5 , 0, 0, 7, 5, 6 }, // Arabic/Arabic/Yemen
+ { 8, 1, 254, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 853,75 , 853,75 , 928,24 , 853,75 , 853,75 , 928,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {83,83,80}, 119,1 , 2454,132 , 13,5 , 4,0 , 87,7 , 304,12 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/South Sudan
+ { 8, 1, 260, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 129,10 , 139,17 , 18,7 , 25,12 , 853,75 , 853,75 , 928,24 , 853,75 , 853,75 , 928,24 , 508,52 , 508,52 , 560,14 , 508,52 , 508,52 , 560,14 , 21,1 , 21,1 , 84,4 , 88,47 , 22,23 , {0,0,0}, 0,0 , 2586,0 , 13,5 , 4,0 , 316,23 , 339,6 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/World
+ { 9, 10, 11, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 65,7 , 65,7 , 156,8 , 164,20 , 37,5 , 8,10 , 1445,48 , 1493,94 , 1587,24 , 1445,48 , 1611,106 , 1587,24 , 574,28 , 602,62 , 664,14 , 574,28 , 602,62 , 664,14 , 0,2 , 0,2 , 135,6 , 141,17 , 22,23 , {65,77,68}, 120,1 , 2586,46 , 13,5 , 4,0 , 345,7 , 352,8 , 2, 0, 1, 6, 7 }, // Armenian/Armenian/Armenia
+ { 10, 11, 100, 46, 44, 59, 37, 2534, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 72,9 , 72,9 , 184,8 , 192,18 , 68,7 , 75,12 , 1717,64 , 1781,89 , 1870,24 , 1717,64 , 1781,89 , 1870,24 , 678,32 , 710,58 , 768,14 , 678,32 , 710,58 , 768,14 , 22,9 , 22,7 , 158,4 , 162,37 , 22,23 , {73,78,82}, 121,1 , 2632,43 , 8,5 , 4,0 , 360,7 , 367,4 , 2, 1, 7, 7, 7 }, // Assamese/Bengali/India
+ { 12, 7, 15, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 81,8 , 81,8 , 156,8 , 210,17 , 37,5 , 8,10 , 1894,48 , 1942,77 , 158,27 , 1894,48 , 2019,77 , 158,27 , 782,27 , 809,67 , 99,14 , 782,27 , 809,67 , 99,14 , 0,2 , 0,2 , 199,4 , 5,17 , 22,23 , {65,90,78}, 122,1 , 2675,58 , 13,5 , 4,0 , 371,10 , 381,10 , 2, 1, 1, 6, 7 }, // Azerbaijani/Latin/Azerbaijan
{ 12, 1, 102, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,82,82}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 6, 5, 5 }, // Azerbaijani/Arabic/Iran
- { 12, 2, 15, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 0,6 , 0,6 , 175,8 , 229,17 , 37,5 , 8,10 , 2214,48 , 2262,77 , 158,27 , 2214,48 , 2339,77 , 158,27 , 896,27 , 923,67 , 99,14 , 896,27 , 923,67 , 99,14 , 31,2 , 29,2 , 45,4 , 5,17 , 22,23 , {65,90,78}, 128,1 , 2690,12 , 8,5 , 4,0 , 362,10 , 372,10 , 2, 1, 1, 6, 7 }, // Azerbaijani/Cyrillic/Azerbaijan
- { 13, 2, 178, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {82,85,66}, 129,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Bashkir/Cyrillic/Russia
- { 14, 7, 197, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8220, 8221, 0,6 , 0,6 , 80,9 , 80,9 , 246,6 , 252,26 , 37,5 , 88,12 , 2416,60 , 2476,93 , 2569,24 , 2416,60 , 2593,93 , 2569,24 , 990,28 , 1018,68 , 1086,14 , 990,28 , 1100,68 , 1086,14 , 0,2 , 0,2 , 156,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 2702,20 , 13,5 , 4,0 , 382,7 , 389,8 , 2, 1, 1, 6, 7 }, // Basque/Latin/Spain
- { 15, 11, 18, 46, 44, 59, 37, 2534, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 89,9 , 89,9 , 278,6 , 211,18 , 18,7 , 25,12 , 2686,90 , 2686,90 , 2776,33 , 2809,77 , 2686,90 , 2776,33 , 1168,37 , 1205,58 , 1263,18 , 1168,37 , 1281,58 , 1263,18 , 0,2 , 0,2 , 163,4 , 5,17 , 22,23 , {66,68,84}, 130,1 , 2722,49 , 0,4 , 4,0 , 397,5 , 402,8 , 2, 1, 5, 6, 7 }, // Bengali/Bengali/Bangladesh
- { 15, 11, 100, 46, 44, 59, 37, 2534, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 89,9 , 89,9 , 278,6 , 211,18 , 18,7 , 25,12 , 2686,90 , 2686,90 , 2776,33 , 2809,77 , 2686,90 , 2776,33 , 1168,37 , 1205,58 , 1263,18 , 1168,37 , 1281,58 , 1263,18 , 0,2 , 0,2 , 163,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 2771,43 , 0,4 , 4,0 , 397,5 , 410,4 , 2, 1, 7, 7, 7 }, // Bengali/Bengali/India
- { 16, 31, 25, 46, 44, 59, 37, 3872, 45, 43, 101, 8220, 8221, 8216, 8217, 98,9 , 98,9 , 98,9 , 98,9 , 53,10 , 284,30 , 100,22 , 122,27 , 2886,63 , 2949,191 , 3140,27 , 3167,27 , 3194,132 , 3326,27 , 1339,34 , 1373,79 , 1452,27 , 1339,34 , 1373,79 , 1452,27 , 33,5 , 31,6 , 45,4 , 5,17 , 22,23 , {66,84,78}, 131,3 , 2814,15 , 4,4 , 4,0 , 414,6 , 420,5 , 2, 1, 7, 6, 7 }, // Dzongkha/Tibetan/Bhutan
- { 19, 7, 74, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 3353,63 , 3416,78 , 3494,36 , 3530,63 , 3416,78 , 3494,36 , 1479,33 , 1512,43 , 1555,18 , 1479,33 , 1512,43 , 1555,18 , 38,4 , 37,4 , 167,7 , 174,17 , 191,23 , {69,85,82}, 14,1 , 2829,36 , 13,5 , 4,0 , 425,9 , 434,5 , 2, 1, 1, 6, 7 }, // Breton/Latin/France
- { 20, 2, 33, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 8222, 8220, 0,6 , 0,6 , 107,7 , 107,7 , 314,12 , 326,22 , 55,4 , 59,9 , 3593,49 , 3642,82 , 3724,24 , 3593,49 , 3642,82 , 3724,24 , 1573,21 , 1594,55 , 1649,14 , 1573,21 , 1594,55 , 1649,14 , 42,6 , 41,6 , 214,7 , 5,17 , 22,23 , {66,71,78}, 134,3 , 2865,47 , 13,5 , 4,0 , 439,9 , 448,8 , 2, 1, 1, 6, 7 }, // Bulgarian/Cyrillic/Bulgaria
- { 21, 25, 147, 46, 44, 4170, 37, 4160, 45, 43, 101, 8220, 8221, 8216, 8217, 114,5 , 114,5 , 119,10 , 119,10 , 348,8 , 98,16 , 37,5 , 149,10 , 3748,43 , 3791,88 , 3879,24 , 3748,43 , 3791,88 , 3879,24 , 1663,54 , 1663,54 , 1717,14 , 1663,54 , 1663,54 , 1717,14 , 48,5 , 47,3 , 221,5 , 5,17 , 22,23 , {77,77,75}, 137,1 , 2912,27 , 13,5 , 4,0 , 456,6 , 456,6 , 0, 0, 7, 6, 7 }, // Burmese/Myanmar/Myanmar
- { 22, 2, 20, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 129,7 , 129,7 , 356,7 , 326,22 , 37,5 , 159,11 , 3903,48 , 3951,95 , 4046,24 , 4070,48 , 4118,98 , 4046,24 , 1731,21 , 1752,56 , 1808,14 , 1731,21 , 1752,56 , 1808,14 , 0,2 , 0,2 , 226,5 , 231,17 , 22,23 , {66,89,78}, 0,2 , 2939,89 , 13,5 , 4,0 , 462,10 , 472,8 , 2, 0, 1, 6, 7 }, // Belarusian/Cyrillic/Belarus
- { 23, 20, 36, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 136,9 , 145,9 , 278,6 , 98,16 , 18,7 , 25,12 , 4216,71 , 4216,71 , 4287,24 , 4216,71 , 4216,71 , 4287,24 , 1822,47 , 1822,47 , 1869,14 , 1822,47 , 1822,47 , 1869,14 , 0,2 , 0,2 , 248,2 , 5,17 , 22,23 , {75,72,82}, 138,1 , 3028,29 , 0,4 , 4,0 , 480,5 , 485,7 , 2, 1, 7, 6, 7 }, // Khmer/Khmer/Cambodia
- { 24, 7, 197, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 154,7 , 154,7 , 278,6 , 363,22 , 55,4 , 59,9 , 4311,60 , 4371,82 , 4453,36 , 4489,93 , 4582,115 , 4453,36 , 1883,28 , 1911,60 , 1971,21 , 1883,28 , 1911,60 , 1971,21 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 492,6 , 498,7 , 2, 1, 1, 6, 7 }, // Catalan/Latin/Spain
- { 24, 7, 5, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 154,7 , 154,7 , 278,6 , 363,22 , 55,4 , 59,9 , 4311,60 , 4371,82 , 4453,36 , 4489,93 , 4582,115 , 4453,36 , 1883,28 , 1911,60 , 1971,21 , 1883,28 , 1911,60 , 1971,21 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 492,6 , 505,7 , 2, 1, 1, 6, 7 }, // Catalan/Latin/Andorra
- { 24, 7, 74, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 154,7 , 154,7 , 278,6 , 363,22 , 55,4 , 59,9 , 4311,60 , 4371,82 , 4453,36 , 4489,93 , 4582,115 , 4453,36 , 1883,28 , 1911,60 , 1971,21 , 1883,28 , 1911,60 , 1971,21 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 492,6 , 512,6 , 2, 1, 1, 6, 7 }, // Catalan/Latin/France
- { 24, 7, 106, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 154,7 , 154,7 , 278,6 , 363,22 , 55,4 , 59,9 , 4311,60 , 4371,82 , 4453,36 , 4489,93 , 4582,115 , 4453,36 , 1883,28 , 1911,60 , 1971,21 , 1883,28 , 1911,60 , 1971,21 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 492,6 , 518,6 , 2, 1, 1, 6, 7 }, // Catalan/Latin/Italy
- { 25, 5, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 161,5 , 161,5 , 166,5 , 166,5 , 385,8 , 393,13 , 170,6 , 176,11 , 4697,39 , 4736,38 , 158,27 , 4697,39 , 4736,38 , 158,27 , 1992,21 , 2013,28 , 2041,14 , 1992,21 , 2013,28 , 2041,14 , 58,2 , 55,2 , 250,2 , 252,21 , 22,23 , {67,78,89}, 139,1 , 3077,13 , 4,4 , 4,0 , 524,4 , 528,2 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/China
- { 25, 5, 97, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 161,5 , 161,5 , 166,5 , 166,5 , 278,6 , 393,13 , 170,6 , 176,11 , 4697,39 , 4736,38 , 158,27 , 4697,39 , 4736,38 , 158,27 , 1992,21 , 2013,28 , 2041,14 , 1992,21 , 2013,28 , 2041,14 , 58,2 , 55,2 , 250,2 , 252,21 , 22,23 , {72,75,68}, 140,3 , 3090,11 , 4,4 , 4,0 , 524,4 , 530,9 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/HongKong
- { 25, 5, 126, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 161,5 , 161,5 , 166,5 , 166,5 , 278,6 , 393,13 , 170,6 , 176,11 , 4697,39 , 4736,38 , 158,27 , 4697,39 , 4736,38 , 158,27 , 1992,21 , 2013,28 , 2041,14 , 1992,21 , 2013,28 , 2041,14 , 58,2 , 55,2 , 250,2 , 252,21 , 22,23 , {77,79,80}, 143,4 , 3101,13 , 4,4 , 4,0 , 524,4 , 539,9 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/Macau
- { 25, 5, 190, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 161,5 , 161,5 , 166,5 , 166,5 , 27,8 , 393,13 , 170,6 , 176,11 , 4697,39 , 4736,38 , 158,27 , 4697,39 , 4736,38 , 158,27 , 1992,21 , 2013,28 , 2041,14 , 1992,21 , 2013,28 , 2041,14 , 58,2 , 55,2 , 250,2 , 252,21 , 22,23 , {83,71,68}, 6,1 , 3114,15 , 4,4 , 4,0 , 524,4 , 548,3 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/Singapore
- { 25, 6, 97, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 161,5 , 161,5 , 171,5 , 171,5 , 406,8 , 393,13 , 170,6 , 187,13 , 4697,39 , 4697,39 , 158,27 , 4697,39 , 4697,39 , 158,27 , 2055,21 , 2013,28 , 2041,14 , 2055,21 , 2013,28 , 2041,14 , 58,2 , 55,2 , 273,3 , 5,17 , 22,23 , {72,75,68}, 140,3 , 3090,11 , 18,5 , 4,0 , 551,4 , 555,9 , 2, 1, 7, 6, 7 }, // Chinese/Traditional Han/HongKong
- { 25, 6, 126, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 161,5 , 161,5 , 171,5 , 171,5 , 406,8 , 393,13 , 170,6 , 187,13 , 4697,39 , 4697,39 , 158,27 , 4697,39 , 4697,39 , 158,27 , 2055,21 , 2013,28 , 2041,14 , 2055,21 , 2013,28 , 2041,14 , 58,2 , 55,2 , 273,3 , 5,17 , 22,23 , {77,79,80}, 143,4 , 3129,13 , 18,5 , 4,0 , 551,4 , 564,9 , 2, 1, 7, 6, 7 }, // Chinese/Traditional Han/Macau
- { 25, 6, 208, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 161,5 , 161,5 , 166,5 , 166,5 , 385,8 , 414,14 , 170,6 , 187,13 , 4697,39 , 4697,39 , 158,27 , 4697,39 , 4697,39 , 158,27 , 2055,21 , 2013,28 , 2041,14 , 2055,21 , 2013,28 , 2041,14 , 58,2 , 55,2 , 45,4 , 5,17 , 22,23 , {84,87,68}, 6,1 , 3142,13 , 4,4 , 4,0 , 551,4 , 573,2 , 2, 0, 7, 6, 7 }, // Chinese/Traditional Han/Taiwan
+ { 12, 2, 15, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 0,6 , 0,6 , 156,8 , 210,17 , 37,5 , 8,10 , 2096,48 , 2144,77 , 158,27 , 2096,48 , 2221,77 , 158,27 , 876,27 , 903,67 , 99,14 , 876,27 , 903,67 , 99,14 , 31,2 , 29,2 , 45,4 , 5,17 , 22,23 , {65,90,78}, 122,1 , 2733,12 , 13,5 , 4,0 , 391,10 , 401,10 , 2, 1, 1, 6, 7 }, // Azerbaijani/Cyrillic/Azerbaijan
+ { 13, 2, 178, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {82,85,66}, 123,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Bashkir/Cyrillic/Russia
+ { 14, 7, 197, 44, 46, 59, 37, 48, 8722, 43, 101, 8220, 8221, 8220, 8221, 0,6 , 0,6 , 89,9 , 89,9 , 227,6 , 233,36 , 37,5 , 87,12 , 2298,60 , 2358,93 , 2451,24 , 2298,60 , 2358,93 , 2451,24 , 970,28 , 998,68 , 1066,14 , 970,28 , 998,68 , 1066,14 , 0,2 , 0,2 , 203,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 2745,20 , 13,5 , 4,0 , 411,7 , 418,8 , 2, 1, 1, 6, 7 }, // Basque/Latin/Spain
+ { 15, 11, 18, 46, 44, 59, 37, 2534, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 98,9 , 98,9 , 269,6 , 192,18 , 18,7 , 25,12 , 2475,90 , 2475,90 , 2565,33 , 2598,77 , 2475,90 , 2565,33 , 1080,37 , 1117,58 , 1175,18 , 1080,37 , 1117,58 , 1175,18 , 0,2 , 0,2 , 158,4 , 5,17 , 22,23 , {66,68,84}, 124,1 , 2765,49 , 0,4 , 4,0 , 426,5 , 431,8 , 2, 1, 7, 6, 7 }, // Bengali/Bengali/Bangladesh
+ { 15, 11, 100, 46, 44, 59, 37, 2534, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 98,9 , 98,9 , 269,6 , 192,18 , 18,7 , 25,12 , 2475,90 , 2475,90 , 2565,33 , 2598,77 , 2475,90 , 2565,33 , 1080,37 , 1117,58 , 1175,18 , 1080,37 , 1117,58 , 1175,18 , 0,2 , 0,2 , 158,4 , 5,17 , 22,23 , {73,78,82}, 121,1 , 2814,43 , 0,4 , 4,0 , 426,5 , 439,4 , 2, 1, 7, 7, 7 }, // Bengali/Bengali/India
+ { 16, 31, 25, 46, 44, 59, 37, 3872, 45, 43, 101, 8220, 8221, 8216, 8217, 107,9 , 107,9 , 107,9 , 107,9 , 53,10 , 275,30 , 99,22 , 121,27 , 2675,63 , 2738,191 , 2929,27 , 2956,27 , 2983,132 , 3115,27 , 1193,34 , 1227,79 , 1306,27 , 1193,34 , 1227,79 , 1306,27 , 33,5 , 31,6 , 45,4 , 5,17 , 22,23 , {66,84,78}, 125,3 , 2857,15 , 4,4 , 4,0 , 443,6 , 449,5 , 2, 1, 7, 6, 7 }, // Dzongkha/Tibetan/Bhutan
+ { 19, 7, 74, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 171, 187, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 97,16 , 37,5 , 8,10 , 3142,63 , 3205,78 , 3283,36 , 3142,63 , 3205,78 , 3283,36 , 1333,33 , 1366,43 , 1409,18 , 1333,33 , 1366,43 , 1409,18 , 38,4 , 37,4 , 210,7 , 217,17 , 22,23 , {69,85,82}, 14,1 , 2872,36 , 13,5 , 4,0 , 454,9 , 463,5 , 2, 1, 1, 6, 7 }, // Breton/Latin/France
+ { 20, 2, 33, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 8222, 8220, 0,6 , 0,6 , 116,7 , 116,7 , 305,12 , 317,22 , 148,9 , 157,14 , 3319,49 , 3368,82 , 3450,24 , 3319,49 , 3368,82 , 3450,24 , 1427,21 , 1448,55 , 1503,14 , 1427,21 , 1448,55 , 1503,14 , 42,6 , 41,6 , 234,7 , 5,17 , 22,23 , {66,71,78}, 128,3 , 2908,47 , 13,5 , 4,0 , 468,9 , 477,8 , 2, 1, 1, 6, 7 }, // Bulgarian/Cyrillic/Bulgaria
+ { 21, 25, 147, 46, 44, 4170, 37, 4160, 45, 43, 101, 8220, 8221, 8216, 8217, 123,5 , 123,5 , 128,10 , 128,10 , 339,8 , 347,18 , 171,6 , 177,10 , 3474,43 , 3517,88 , 3605,24 , 3474,43 , 3517,88 , 3605,24 , 1517,54 , 1517,54 , 1571,14 , 1517,54 , 1517,54 , 1571,14 , 48,5 , 47,3 , 241,5 , 5,17 , 22,23 , {77,77,75}, 131,1 , 2955,29 , 13,5 , 4,0 , 485,6 , 485,6 , 0, 0, 7, 6, 7 }, // Burmese/Myanmar/Myanmar
+ { 22, 2, 20, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 138,7 , 138,7 , 365,7 , 317,22 , 37,5 , 187,11 , 3629,48 , 3677,95 , 3772,24 , 3796,48 , 3844,98 , 3772,24 , 1585,21 , 1606,56 , 1662,14 , 1585,21 , 1606,56 , 1662,14 , 0,2 , 0,2 , 246,5 , 251,17 , 22,23 , {66,89,78}, 0,2 , 2984,89 , 13,5 , 4,0 , 491,10 , 501,8 , 2, 0, 1, 6, 7 }, // Belarusian/Cyrillic/Belarus
+ { 23, 20, 36, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 145,9 , 154,9 , 269,6 , 97,16 , 18,7 , 25,12 , 3942,71 , 3942,71 , 4013,24 , 3942,71 , 3942,71 , 4013,24 , 1676,40 , 1716,46 , 1762,14 , 1676,40 , 1776,47 , 1762,14 , 0,2 , 0,2 , 268,2 , 5,17 , 22,23 , {75,72,82}, 132,1 , 3073,29 , 0,4 , 4,0 , 509,5 , 514,7 , 2, 1, 7, 6, 7 }, // Khmer/Khmer/Cambodia
+ { 24, 7, 197, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 163,7 , 163,7 , 269,6 , 372,22 , 55,4 , 59,9 , 4037,60 , 4097,82 , 4179,36 , 4215,93 , 4308,115 , 4179,36 , 1823,28 , 1851,60 , 1911,21 , 1823,28 , 1851,60 , 1911,21 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 521,6 , 527,7 , 2, 1, 1, 6, 7 }, // Catalan/Latin/Spain
+ { 24, 7, 5, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 163,7 , 163,7 , 269,6 , 372,22 , 55,4 , 59,9 , 4037,60 , 4097,82 , 4179,36 , 4215,93 , 4308,115 , 4179,36 , 1823,28 , 1851,60 , 1911,21 , 1823,28 , 1851,60 , 1911,21 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 521,6 , 534,7 , 2, 1, 1, 6, 7 }, // Catalan/Latin/Andorra
+ { 24, 7, 74, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 163,7 , 163,7 , 269,6 , 372,22 , 55,4 , 59,9 , 4037,60 , 4097,82 , 4179,36 , 4215,93 , 4308,115 , 4179,36 , 1823,28 , 1851,60 , 1911,21 , 1823,28 , 1851,60 , 1911,21 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 521,6 , 541,6 , 2, 1, 1, 6, 7 }, // Catalan/Latin/France
+ { 24, 7, 106, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 163,7 , 163,7 , 269,6 , 372,22 , 55,4 , 59,9 , 4037,60 , 4097,82 , 4179,36 , 4215,93 , 4308,115 , 4179,36 , 1823,28 , 1851,60 , 1911,21 , 1823,28 , 1851,60 , 1911,21 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 521,6 , 547,6 , 2, 1, 1, 6, 7 }, // Catalan/Latin/Italy
+ { 25, 5, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 170,5 , 170,5 , 175,5 , 175,5 , 394,8 , 402,13 , 198,6 , 204,11 , 4423,39 , 4462,38 , 158,27 , 4423,39 , 4462,38 , 158,27 , 1932,21 , 1953,28 , 1981,14 , 1932,21 , 1953,28 , 1981,14 , 58,2 , 55,2 , 270,2 , 272,21 , 22,23 , {67,78,89}, 133,1 , 3122,13 , 4,4 , 4,0 , 553,4 , 557,2 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/China
+ { 25, 5, 97, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 170,5 , 170,5 , 175,5 , 175,5 , 269,6 , 402,13 , 198,6 , 204,11 , 4423,39 , 4462,38 , 158,27 , 4423,39 , 4462,38 , 158,27 , 1932,21 , 1953,28 , 1981,14 , 1932,21 , 1953,28 , 1981,14 , 58,2 , 55,2 , 270,2 , 272,21 , 22,23 , {72,75,68}, 134,3 , 3135,11 , 4,4 , 4,0 , 553,4 , 559,9 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/Hong Kong
+ { 25, 5, 126, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 170,5 , 170,5 , 175,5 , 175,5 , 269,6 , 402,13 , 198,6 , 204,11 , 4423,39 , 4462,38 , 158,27 , 4423,39 , 4462,38 , 158,27 , 1932,21 , 1953,28 , 1981,14 , 1932,21 , 1953,28 , 1981,14 , 58,2 , 55,2 , 270,2 , 272,21 , 22,23 , {77,79,80}, 137,4 , 3146,13 , 4,4 , 4,0 , 553,4 , 568,9 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/Macau
+ { 25, 5, 190, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 170,5 , 170,5 , 175,5 , 175,5 , 27,8 , 402,13 , 198,6 , 204,11 , 4423,39 , 4462,38 , 158,27 , 4423,39 , 4462,38 , 158,27 , 1932,21 , 1953,28 , 1981,14 , 1932,21 , 1953,28 , 1981,14 , 58,2 , 55,2 , 270,2 , 272,21 , 22,23 , {83,71,68}, 6,1 , 3159,15 , 4,4 , 4,0 , 553,4 , 577,3 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/Singapore
+ { 25, 6, 97, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 170,5 , 170,5 , 180,5 , 180,5 , 415,8 , 402,13 , 198,6 , 215,13 , 4423,39 , 4423,39 , 158,27 , 4423,39 , 4423,39 , 158,27 , 1995,21 , 1953,28 , 1981,14 , 1995,21 , 1953,28 , 1981,14 , 58,2 , 55,2 , 293,3 , 5,17 , 22,23 , {72,75,68}, 134,3 , 3135,11 , 18,5 , 4,0 , 580,4 , 584,9 , 2, 1, 7, 6, 7 }, // Chinese/Traditional Han/Hong Kong
+ { 25, 6, 126, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 170,5 , 170,5 , 180,5 , 180,5 , 415,8 , 402,13 , 198,6 , 215,13 , 4423,39 , 4423,39 , 158,27 , 4423,39 , 4423,39 , 158,27 , 1995,21 , 1953,28 , 1981,14 , 1995,21 , 1953,28 , 1981,14 , 58,2 , 55,2 , 293,3 , 5,17 , 22,23 , {77,79,80}, 137,4 , 3174,13 , 18,5 , 4,0 , 580,4 , 593,9 , 2, 1, 7, 6, 7 }, // Chinese/Traditional Han/Macau
+ { 25, 6, 208, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 170,5 , 170,5 , 175,5 , 175,5 , 394,8 , 423,14 , 198,6 , 215,13 , 4423,39 , 4423,39 , 158,27 , 4423,39 , 4423,39 , 158,27 , 1995,21 , 1953,28 , 1981,14 , 1995,21 , 1953,28 , 1981,14 , 58,2 , 55,2 , 45,4 , 5,17 , 22,23 , {84,87,68}, 6,1 , 3187,13 , 4,4 , 4,0 , 580,4 , 602,2 , 2, 0, 7, 6, 7 }, // Chinese/Traditional Han/Taiwan
{ 26, 7, 74, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Corsican/Latin/France
- { 27, 7, 54, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 154,7 , 154,7 , 428,13 , 441,19 , 37,5 , 88,12 , 4774,49 , 4823,94 , 4917,39 , 4774,49 , 4956,98 , 4917,39 , 2076,28 , 2104,58 , 2162,14 , 2076,28 , 2104,58 , 2176,14 , 0,2 , 0,2 , 276,7 , 5,17 , 22,23 , {72,82,75}, 147,3 , 3155,60 , 13,5 , 4,0 , 575,8 , 583,8 , 2, 1, 1, 6, 7 }, // Croatian/Latin/Croatia
- { 27, 7, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 154,7 , 154,7 , 460,9 , 441,19 , 37,5 , 88,12 , 4774,49 , 4823,94 , 4917,39 , 4774,49 , 4956,98 , 4917,39 , 2076,28 , 2104,58 , 2176,14 , 2076,28 , 2104,58 , 2176,14 , 0,2 , 0,2 , 276,7 , 5,17 , 22,23 , {66,65,77}, 150,2 , 3215,85 , 13,5 , 4,0 , 575,8 , 591,19 , 2, 1, 1, 6, 7 }, // Croatian/Latin/BosniaAndHerzegowina
- { 28, 7, 57, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 176,7 , 176,7 , 175,8 , 469,17 , 55,4 , 59,9 , 5054,48 , 5102,82 , 158,27 , 5054,48 , 5184,84 , 158,27 , 2190,21 , 2211,49 , 2260,14 , 2190,21 , 2211,49 , 2260,14 , 60,4 , 57,4 , 283,5 , 5,17 , 22,23 , {67,90,75}, 152,2 , 3300,68 , 13,5 , 4,0 , 610,7 , 617,5 , 2, 0, 1, 6, 7 }, // Czech/Latin/CzechRepublic
- { 29, 7, 58, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 183,8 , 183,8 , 120,10 , 486,23 , 200,5 , 205,10 , 5268,59 , 5327,84 , 134,24 , 5268,59 , 5327,84 , 134,24 , 2274,28 , 2302,51 , 2353,14 , 2367,35 , 2302,51 , 2353,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {68,75,75}, 154,3 , 3368,42 , 13,5 , 4,0 , 622,5 , 627,7 , 2, 1, 1, 6, 7 }, // Danish/Latin/Denmark
- { 29, 7, 86, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 183,8 , 183,8 , 120,10 , 486,23 , 215,7 , 76,12 , 5268,59 , 5327,84 , 134,24 , 5268,59 , 5327,84 , 134,24 , 2274,28 , 2302,51 , 2353,14 , 2367,35 , 2302,51 , 2353,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {68,75,75}, 154,3 , 3368,42 , 13,5 , 4,0 , 622,5 , 634,8 , 2, 1, 1, 6, 7 }, // Danish/Latin/Greenland
- { 30, 7, 151, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 348,8 , 98,16 , 37,5 , 8,10 , 5411,59 , 5470,88 , 134,24 , 5411,59 , 5470,88 , 134,24 , 2402,21 , 2423,59 , 2482,14 , 2402,21 , 2423,59 , 2482,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3410,19 , 13,5 , 4,0 , 642,10 , 652,9 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Netherlands
- { 30, 7, 12, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 348,8 , 98,16 , 37,5 , 8,10 , 5411,59 , 5470,88 , 134,24 , 5411,59 , 5470,88 , 134,24 , 2402,21 , 2423,59 , 2482,14 , 2402,21 , 2423,59 , 2482,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {65,87,71}, 157,4 , 3429,55 , 13,5 , 4,0 , 642,10 , 661,5 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Aruba
- { 30, 7, 21, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 509,7 , 98,16 , 37,5 , 8,10 , 5411,59 , 5470,88 , 134,24 , 5411,59 , 5470,88 , 134,24 , 2402,21 , 2423,59 , 2482,14 , 2402,21 , 2423,59 , 2482,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3410,19 , 13,5 , 4,0 , 642,10 , 666,6 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Belgium
- { 30, 7, 152, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 348,8 , 98,16 , 37,5 , 8,10 , 5411,59 , 5470,88 , 134,24 , 5411,59 , 5470,88 , 134,24 , 2402,21 , 2423,59 , 2482,14 , 2402,21 , 2423,59 , 2482,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {65,78,71}, 161,4 , 3484,97 , 13,5 , 4,0 , 642,10 , 672,7 , 2, 1, 1, 6, 7 }, // Dutch/Latin/CuraSao
- { 30, 7, 202, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 348,8 , 98,16 , 37,5 , 8,10 , 5411,59 , 5470,88 , 134,24 , 5411,59 , 5470,88 , 134,24 , 2402,21 , 2423,59 , 2482,14 , 2402,21 , 2423,59 , 2482,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {83,82,68}, 6,1 , 3581,58 , 13,5 , 4,0 , 642,10 , 679,8 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Suriname
- { 30, 7, 255, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 348,8 , 98,16 , 37,5 , 8,10 , 5411,59 , 5470,88 , 134,24 , 5411,59 , 5470,88 , 134,24 , 2402,21 , 2423,59 , 2482,14 , 2402,21 , 2423,59 , 2482,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3639,61 , 13,5 , 4,0 , 642,10 , 687,19 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Bonaire
- { 30, 7, 256, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 348,8 , 98,16 , 37,5 , 8,10 , 5411,59 , 5470,88 , 134,24 , 5411,59 , 5470,88 , 134,24 , 2402,21 , 2423,59 , 2482,14 , 2402,21 , 2423,59 , 2482,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {65,78,71}, 161,4 , 3484,97 , 13,5 , 4,0 , 642,10 , 706,12 , 2, 1, 1, 6, 7 }, // Dutch/Latin/SintMaarten
- { 31, 7, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 516,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3700,35 , 4,4 , 4,0 , 718,16 , 734,13 , 2, 1, 7, 6, 7 }, // English/Latin/UnitedStates
- { 31, 3, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,83,68}, 165,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // English/Deseret/UnitedStates
- { 31, 7, 4, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 516,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3700,35 , 4,4 , 4,0 , 747,7 , 754,14 , 2, 1, 7, 6, 7 }, // English/Latin/AmericanSamoa
- { 31, 7, 7, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3735,71 , 4,4 , 4,0 , 747,7 , 768,8 , 2, 1, 1, 6, 7 }, // English/Latin/Anguilla
- { 31, 7, 9, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3735,71 , 4,4 , 4,0 , 747,7 , 776,17 , 2, 1, 7, 6, 7 }, // English/Latin/AntiguaAndBarbuda
- { 31, 7, 13, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 201,9 , 201,9 , 278,6 , 10,17 , 18,7 , 25,12 , 5558,59 , 48,86 , 134,24 , 5558,59 , 48,86 , 134,24 , 2496,35 , 28,57 , 2531,25 , 2496,35 , 28,57 , 2531,25 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3806,59 , 4,4 , 4,0 , 793,18 , 811,9 , 2, 1, 7, 6, 7 }, // English/Latin/Australia
- { 31, 7, 14, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3865,20 , 8,5 , 4,0 , 747,7 , 820,7 , 2, 1, 1, 6, 7 }, // English/Latin/Austria
- { 31, 7, 16, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {66,83,68}, 6,1 , 3885,53 , 4,4 , 4,0 , 747,7 , 827,7 , 2, 1, 7, 6, 7 }, // English/Latin/Bahamas
- { 31, 7, 19, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {66,66,68}, 6,1 , 3938,56 , 4,4 , 4,0 , 747,7 , 834,8 , 2, 1, 1, 6, 7 }, // English/Latin/Barbados
- { 31, 7, 21, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 27,8 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3865,20 , 13,5 , 4,0 , 747,7 , 842,7 , 2, 1, 1, 6, 7 }, // English/Latin/Belgium
- { 31, 7, 22, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 27,8 , 80,18 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {66,90,68}, 6,1 , 3994,47 , 4,4 , 4,0 , 747,7 , 849,6 , 2, 1, 7, 6, 7 }, // English/Latin/Belize
- { 31, 7, 24, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {66,77,68}, 6,1 , 4041,53 , 4,4 , 4,0 , 747,7 , 855,7 , 2, 1, 1, 6, 7 }, // English/Latin/Bermuda
- { 31, 7, 28, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 27,8 , 80,18 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {66,87,80}, 168,1 , 4094,50 , 4,4 , 4,0 , 747,7 , 862,8 , 2, 1, 7, 6, 7 }, // English/Latin/Botswana
- { 31, 7, 31, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 165,3 , 3700,35 , 4,4 , 4,0 , 747,7 , 870,30 , 2, 1, 1, 6, 7 }, // English/Latin/BritishIndianOceanTerritory
- { 31, 7, 35, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 516,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {66,73,70}, 169,3 , 4144,53 , 4,4 , 4,0 , 747,7 , 900,7 , 0, 0, 1, 6, 7 }, // English/Latin/Burundi
- { 31, 7, 37, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,65,70}, 32,4 , 4197,83 , 4,4 , 4,0 , 747,7 , 907,8 , 0, 0, 1, 6, 7 }, // English/Latin/Cameroon
- { 31, 7, 38, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 53,10 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {67,65,68}, 6,1 , 4280,53 , 4,4 , 4,0 , 915,16 , 931,6 , 2, 0, 7, 6, 7 }, // English/Latin/Canada
- { 31, 7, 40, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {75,89,68}, 6,1 , 4333,71 , 4,4 , 4,0 , 747,7 , 937,14 , 2, 1, 1, 6, 7 }, // English/Latin/CaymanIslands
- { 31, 7, 45, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3806,59 , 4,4 , 4,0 , 747,7 , 951,16 , 2, 1, 1, 6, 7 }, // English/Latin/ChristmasIsland
- { 31, 7, 46, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3806,59 , 4,4 , 4,0 , 747,7 , 967,23 , 2, 1, 1, 6, 7 }, // English/Latin/CocosIslands
- { 31, 7, 51, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {78,90,68}, 6,1 , 4404,62 , 4,4 , 4,0 , 747,7 , 990,12 , 2, 1, 1, 6, 7 }, // English/Latin/CookIslands
- { 31, 7, 56, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3865,20 , 4,4 , 4,0 , 747,7 , 1002,6 , 2, 1, 1, 6, 7 }, // English/Latin/Cyprus
- { 31, 7, 58, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 200,5 , 205,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {68,75,75}, 154,3 , 4466,44 , 13,5 , 4,0 , 747,7 , 1008,7 , 2, 1, 1, 6, 7 }, // English/Latin/Denmark
- { 31, 7, 60, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3735,71 , 4,4 , 4,0 , 747,7 , 1015,8 , 2, 1, 7, 6, 7 }, // English/Latin/Dominica
- { 31, 7, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,82,78}, 46,3 , 4510,50 , 4,4 , 4,0 , 747,7 , 1023,7 , 2, 1, 1, 6, 7 }, // English/Latin/Eritrea
- { 31, 7, 70, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {70,75,80}, 125,1 , 4560,74 , 4,4 , 4,0 , 747,7 , 1030,16 , 2, 1, 1, 6, 7 }, // English/Latin/FalklandIslands
- { 31, 7, 72, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {70,74,68}, 6,1 , 4634,47 , 4,4 , 4,0 , 747,7 , 1046,4 , 2, 1, 1, 6, 7 }, // English/Latin/Fiji
- { 31, 7, 73, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 222,4 , 226,9 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3865,20 , 13,5 , 4,0 , 747,7 , 1050,7 , 2, 1, 1, 6, 7 }, // English/Latin/Finland
- { 31, 7, 75, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {71,66,80}, 125,1 , 4681,32 , 4,4 , 4,0 , 747,7 , 1057,8 , 2, 1, 1, 6, 7 }, // English/Latin/Guernsey
- { 31, 7, 80, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {71,77,68}, 172,1 , 4713,50 , 4,4 , 4,0 , 747,7 , 1065,6 , 2, 1, 1, 6, 7 }, // English/Latin/Gambia
- { 31, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3865,20 , 13,5 , 4,0 , 747,7 , 1071,7 , 2, 1, 1, 6, 7 }, // English/Latin/Germany
- { 31, 7, 83, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {71,72,83}, 173,3 , 4763,47 , 4,4 , 4,0 , 747,7 , 1078,5 , 2, 1, 1, 6, 7 }, // English/Latin/Ghana
- { 31, 7, 84, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {71,73,80}, 125,1 , 4810,53 , 4,4 , 4,0 , 747,7 , 1083,9 , 2, 1, 1, 6, 7 }, // English/Latin/Gibraltar
- { 31, 7, 87, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3735,71 , 4,4 , 4,0 , 747,7 , 1092,7 , 2, 1, 1, 6, 7 }, // English/Latin/Grenada
- { 31, 7, 89, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 516,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3700,35 , 4,4 , 4,0 , 747,7 , 1099,4 , 2, 1, 7, 6, 7 }, // English/Latin/Guam
- { 31, 7, 93, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {71,89,68}, 6,1 , 4863,56 , 4,4 , 4,0 , 747,7 , 1103,6 , 0, 0, 1, 6, 7 }, // English/Latin/Guyana
- { 31, 7, 97, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 406,8 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {72,75,68}, 140,3 , 4919,56 , 4,4 , 4,0 , 747,7 , 1109,19 , 2, 1, 7, 6, 7 }, // English/Latin/HongKong
- { 31, 7, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 27,8 , 98,16 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {73,78,82}, 127,1 , 4975,44 , 8,5 , 4,0 , 747,7 , 1128,5 , 2, 1, 7, 7, 7 }, // English/Latin/India
- { 31, 7, 104, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 98,16 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 64,4 , 61,4 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3865,20 , 4,4 , 4,0 , 747,7 , 1133,7 , 2, 1, 7, 6, 7 }, // English/Latin/Ireland
- { 31, 7, 105, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 55,4 , 59,9 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {73,76,83}, 54,1 , 5019,62 , 4,4 , 4,0 , 747,7 , 1140,6 , 2, 1, 7, 5, 6 }, // English/Latin/Israel
- { 31, 7, 107, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 278,6 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {74,77,68}, 6,1 , 5081,53 , 4,4 , 4,0 , 747,7 , 1146,7 , 2, 1, 7, 6, 7 }, // English/Latin/Jamaica
- { 31, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {75,69,83}, 2,3 , 5134,53 , 4,4 , 4,0 , 747,7 , 1153,5 , 2, 1, 7, 6, 7 }, // English/Latin/Kenya
- { 31, 7, 112, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3806,59 , 4,4 , 4,0 , 747,7 , 1158,8 , 2, 1, 1, 6, 7 }, // English/Latin/Kiribati
- { 31, 7, 120, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {90,65,82}, 5,1 , 5187,61 , 4,4 , 4,0 , 747,7 , 1166,7 , 2, 1, 1, 6, 7 }, // English/Latin/Lesotho
- { 31, 7, 121, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {76,82,68}, 6,1 , 5248,53 , 4,4 , 4,0 , 747,7 , 1173,7 , 2, 1, 1, 6, 7 }, // English/Latin/Liberia
- { 31, 7, 126, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {77,79,80}, 143,4 , 5301,53 , 4,4 , 4,0 , 747,7 , 1180,15 , 2, 1, 7, 6, 7 }, // English/Latin/Macau
- { 31, 7, 128, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {77,71,65}, 176,2 , 5354,54 , 4,4 , 4,0 , 747,7 , 1195,10 , 0, 0, 1, 6, 7 }, // English/Latin/Madagascar
- { 31, 7, 129, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {77,87,75}, 178,2 , 5408,53 , 4,4 , 4,0 , 747,7 , 1205,6 , 2, 1, 1, 6, 7 }, // English/Latin/Malawi
- { 31, 7, 130, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {77,89,82}, 180,2 , 5461,59 , 4,4 , 4,0 , 747,7 , 1211,8 , 2, 1, 1, 6, 7 }, // English/Latin/Malaysia
- { 31, 7, 133, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3865,20 , 4,4 , 4,0 , 747,7 , 1219,5 , 2, 1, 7, 6, 7 }, // English/Latin/Malta
- { 31, 7, 134, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 516,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3700,35 , 4,4 , 4,0 , 747,7 , 1224,16 , 2, 1, 7, 6, 7 }, // English/Latin/MarshallIslands
- { 31, 7, 137, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {77,85,82}, 182,2 , 5520,53 , 4,4 , 4,0 , 747,7 , 1240,9 , 0, 0, 1, 6, 7 }, // English/Latin/Mauritius
- { 31, 7, 140, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 165,3 , 3700,35 , 4,4 , 4,0 , 747,7 , 1249,10 , 2, 1, 1, 6, 7 }, // English/Latin/Micronesia
- { 31, 7, 144, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3735,71 , 4,4 , 4,0 , 747,7 , 1259,10 , 2, 1, 1, 6, 7 }, // English/Latin/Montserrat
- { 31, 7, 148, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {78,65,68}, 6,1 , 5573,53 , 4,4 , 4,0 , 747,7 , 1269,7 , 2, 1, 1, 6, 7 }, // English/Latin/Namibia
- { 31, 7, 149, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3806,59 , 4,4 , 4,0 , 747,7 , 1276,5 , 2, 1, 1, 6, 7 }, // English/Latin/Nauru
- { 31, 7, 151, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3865,20 , 8,5 , 23,6 , 747,7 , 1281,11 , 2, 1, 1, 6, 7 }, // English/Latin/Netherlands
- { 31, 7, 154, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 509,7 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {78,90,68}, 6,1 , 4404,62 , 4,4 , 4,0 , 747,7 , 1292,11 , 2, 1, 7, 6, 7 }, // English/Latin/NewZealand
- { 31, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {78,71,78}, 184,1 , 5626,50 , 4,4 , 4,0 , 747,7 , 1303,7 , 2, 1, 1, 6, 7 }, // English/Latin/Nigeria
- { 31, 7, 158, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {78,90,68}, 6,1 , 4404,62 , 4,4 , 4,0 , 747,7 , 1310,4 , 2, 1, 1, 6, 7 }, // English/Latin/Niue
- { 31, 7, 159, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3806,59 , 4,4 , 4,0 , 747,7 , 1314,14 , 2, 1, 1, 6, 7 }, // English/Latin/NorfolkIsland
- { 31, 7, 160, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 516,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3700,35 , 4,4 , 4,0 , 747,7 , 1328,24 , 2, 1, 1, 6, 7 }, // English/Latin/NorthernMarianaIslands
- { 31, 7, 163, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {80,75,82}, 182,2 , 5676,53 , 4,4 , 4,0 , 747,7 , 1352,8 , 0, 0, 7, 6, 7 }, // English/Latin/Pakistan
- { 31, 7, 164, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 165,3 , 3700,35 , 4,4 , 4,0 , 747,7 , 1360,5 , 2, 1, 1, 6, 7 }, // English/Latin/Palau
- { 31, 7, 167, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {80,71,75}, 137,1 , 5729,73 , 4,4 , 4,0 , 747,7 , 1365,16 , 2, 1, 1, 6, 7 }, // English/Latin/PapuaNewGuinea
- { 31, 7, 170, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {80,72,80}, 185,1 , 5802,53 , 4,4 , 4,0 , 747,7 , 1381,11 , 2, 1, 7, 6, 7 }, // English/Latin/Philippines
- { 31, 7, 171, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {78,90,68}, 6,1 , 4404,62 , 4,4 , 4,0 , 747,7 , 1392,16 , 2, 1, 1, 6, 7 }, // English/Latin/Pitcairn
- { 31, 7, 174, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 516,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3700,35 , 4,4 , 4,0 , 747,7 , 1408,11 , 2, 1, 7, 6, 7 }, // English/Latin/PuertoRico
- { 31, 7, 179, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {82,87,70}, 186,2 , 5855,47 , 4,4 , 4,0 , 747,7 , 1419,6 , 0, 0, 1, 6, 7 }, // English/Latin/Rwanda
- { 31, 7, 180, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3735,71 , 4,4 , 4,0 , 747,7 , 1425,17 , 2, 1, 1, 6, 7 }, // English/Latin/SaintKittsAndNevis
- { 31, 7, 181, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3735,71 , 4,4 , 4,0 , 747,7 , 1442,9 , 2, 1, 1, 6, 7 }, // English/Latin/SaintLucia
- { 31, 7, 182, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3735,71 , 4,4 , 4,0 , 747,7 , 1451,24 , 2, 1, 1, 6, 7 }, // English/Latin/SaintVincentAndTheGrenadines
- { 31, 7, 183, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {87,83,84}, 188,3 , 5902,40 , 4,4 , 4,0 , 747,7 , 1475,5 , 2, 1, 7, 6, 7 }, // English/Latin/Samoa
- { 31, 7, 188, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,67,82}, 191,2 , 5942,59 , 4,4 , 4,0 , 747,7 , 1480,10 , 2, 1, 1, 6, 7 }, // English/Latin/Seychelles
- { 31, 7, 189, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,76,76}, 193,2 , 6001,68 , 4,4 , 4,0 , 747,7 , 1490,12 , 0, 0, 1, 6, 7 }, // English/Latin/SierraLeone
- { 31, 7, 190, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 278,6 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,71,68}, 6,1 , 6069,56 , 4,4 , 4,0 , 747,7 , 1502,9 , 2, 1, 7, 6, 7 }, // English/Latin/Singapore
- { 31, 7, 192, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3865,20 , 13,5 , 29,7 , 747,7 , 1511,8 , 2, 1, 1, 6, 7 }, // English/Latin/Slovenia
- { 31, 7, 193, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,66,68}, 6,1 , 6125,74 , 4,4 , 4,0 , 747,7 , 1519,15 , 2, 1, 1, 6, 7 }, // English/Latin/SolomonIslands
- { 31, 7, 195, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 522,10 , 80,18 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {90,65,82}, 5,1 , 5187,61 , 4,4 , 4,0 , 747,7 , 1534,12 , 2, 1, 7, 6, 7 }, // English/Latin/SouthAfrica
- { 31, 7, 199, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,72,80}, 125,1 , 6199,56 , 4,4 , 4,0 , 747,7 , 1546,10 , 2, 1, 1, 6, 7 }, // English/Latin/SaintHelena
- { 31, 7, 201, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,68,71}, 0,0 , 6255,50 , 4,4 , 4,0 , 747,7 , 1556,5 , 2, 1, 6, 5, 6 }, // English/Latin/Sudan
- { 31, 7, 204, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,90,76}, 195,1 , 6305,53 , 4,4 , 4,0 , 747,7 , 1561,9 , 2, 1, 1, 6, 7 }, // English/Latin/Swaziland
- { 31, 7, 205, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 53,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,69,75}, 196,2 , 6358,47 , 13,5 , 4,0 , 747,7 , 1570,6 , 2, 1, 1, 6, 7 }, // English/Latin/Sweden
- { 31, 7, 206, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {67,72,70}, 0,0 , 6405,41 , 8,5 , 36,5 , 747,7 , 1576,11 , 2, 0, 1, 6, 7 }, // English/Latin/Switzerland
- { 31, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {84,90,83}, 198,3 , 6446,62 , 4,4 , 4,0 , 747,7 , 1587,8 , 0, 0, 1, 6, 7 }, // English/Latin/Tanzania
- { 31, 7, 213, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {78,90,68}, 6,1 , 4404,62 , 4,4 , 4,0 , 747,7 , 1595,7 , 2, 1, 1, 6, 7 }, // English/Latin/Tokelau
- { 31, 7, 214, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {84,79,80}, 201,2 , 6508,49 , 4,4 , 4,0 , 747,7 , 1602,5 , 2, 1, 1, 6, 7 }, // English/Latin/Tonga
- { 31, 7, 215, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {84,84,68}, 6,1 , 6557,80 , 4,4 , 4,0 , 747,7 , 1607,17 , 2, 1, 7, 6, 7 }, // English/Latin/TrinidadAndTobago
- { 31, 7, 219, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 165,3 , 3700,35 , 4,4 , 4,0 , 747,7 , 1624,22 , 2, 1, 1, 6, 7 }, // English/Latin/TurksAndCaicosIslands
- { 31, 7, 220, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3806,59 , 4,4 , 4,0 , 747,7 , 1646,6 , 2, 1, 1, 6, 7 }, // English/Latin/Tuvalu
- { 31, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,71,88}, 203,3 , 6637,56 , 4,4 , 4,0 , 747,7 , 1652,6 , 0, 0, 1, 6, 7 }, // English/Latin/Uganda
- { 31, 7, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 201,9 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {71,66,80}, 125,1 , 6693,47 , 4,4 , 4,0 , 1658,15 , 1673,14 , 2, 1, 1, 6, 7 }, // English/Latin/UnitedKingdom
- { 31, 7, 226, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 516,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3700,35 , 4,4 , 4,0 , 747,7 , 1687,21 , 2, 1, 7, 6, 7 }, // English/Latin/UnitedStatesMinorOutlyingIslands
- { 31, 7, 229, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {86,85,86}, 206,2 , 6740,44 , 4,4 , 4,0 , 747,7 , 1708,7 , 0, 0, 1, 6, 7 }, // English/Latin/Vanuatu
- { 31, 7, 233, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 165,3 , 3700,35 , 4,4 , 4,0 , 747,7 , 1715,22 , 2, 1, 1, 6, 7 }, // English/Latin/BritishVirginIslands
- { 31, 7, 234, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 516,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3700,35 , 4,4 , 4,0 , 747,7 , 1737,19 , 2, 1, 7, 6, 7 }, // English/Latin/UnitedStatesVirginIslands
- { 31, 7, 239, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {90,77,87}, 137,1 , 6784,50 , 4,4 , 4,0 , 747,7 , 1756,6 , 2, 1, 1, 6, 7 }, // English/Latin/Zambia
- { 31, 7, 240, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 406,8 , 80,18 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 165,3 , 3700,35 , 4,4 , 4,0 , 747,7 , 1762,8 , 2, 1, 7, 6, 7 }, // English/Latin/Zimbabwe
- { 31, 7, 249, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 165,3 , 3700,35 , 4,4 , 4,0 , 747,7 , 1770,12 , 2, 1, 1, 6, 7 }, // English/Latin/DiegoGarcia
- { 31, 7, 251, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {71,66,80}, 125,1 , 4681,32 , 4,4 , 4,0 , 747,7 , 1782,11 , 2, 1, 1, 6, 7 }, // English/Latin/IsleOfMan
- { 31, 7, 252, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {71,66,80}, 125,1 , 4681,32 , 4,4 , 4,0 , 747,7 , 1793,6 , 2, 1, 1, 6, 7 }, // English/Latin/Jersey
- { 31, 7, 254, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,83,80}, 125,1 , 6834,68 , 4,4 , 4,0 , 747,7 , 1799,11 , 2, 1, 1, 6, 7 }, // English/Latin/SouthSudan
- { 31, 7, 256, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {65,78,71}, 161,4 , 6902,95 , 4,4 , 4,0 , 747,7 , 1810,12 , 2, 1, 1, 6, 7 }, // English/Latin/SintMaarten
- { 33, 7, 68, 44, 160, 59, 37, 48, 8722, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 210,8 , 210,8 , 175,8 , 532,18 , 37,5 , 8,10 , 5617,59 , 5676,91 , 5767,24 , 5617,59 , 5676,91 , 5767,24 , 2556,14 , 2570,63 , 2556,14 , 2556,14 , 2570,63 , 2556,14 , 0,2 , 0,2 , 288,6 , 5,17 , 22,23 , {69,85,82}, 14,1 , 6997,20 , 13,5 , 4,0 , 1822,5 , 1827,5 , 2, 1, 1, 6, 7 }, // Estonian/Latin/Estonia
- { 34, 7, 71, 44, 46, 59, 37, 48, 8722, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 183,8 , 183,8 , 175,8 , 532,18 , 37,5 , 8,10 , 5791,48 , 5839,83 , 134,24 , 5922,59 , 5839,83 , 134,24 , 2633,28 , 2661,74 , 2735,14 , 2749,35 , 2661,74 , 2735,14 , 0,2 , 0,2 , 294,3 , 297,17 , 22,23 , {68,75,75}, 196,2 , 7017,43 , 13,5 , 4,0 , 1832,8 , 1840,7 , 2, 1, 1, 6, 7 }, // Faroese/Latin/FaroeIslands
- { 34, 7, 58, 44, 46, 59, 37, 48, 8722, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 183,8 , 183,8 , 175,8 , 532,18 , 37,5 , 8,10 , 5791,48 , 5839,83 , 134,24 , 5922,59 , 5839,83 , 134,24 , 2633,28 , 2661,74 , 2735,14 , 2749,35 , 2661,74 , 2735,14 , 0,2 , 0,2 , 294,3 , 297,17 , 22,23 , {68,75,75}, 154,3 , 7017,43 , 13,5 , 4,0 , 1832,8 , 627,7 , 2, 1, 1, 6, 7 }, // Faroese/Latin/Denmark
- { 36, 7, 73, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 210,8 , 210,8 , 550,8 , 469,17 , 222,4 , 226,9 , 5981,69 , 6050,105 , 6155,24 , 6179,93 , 6272,129 , 6155,24 , 2784,21 , 2805,67 , 2872,14 , 2784,21 , 2886,81 , 2872,14 , 70,3 , 67,3 , 314,5 , 319,17 , 336,23 , {69,85,82}, 14,1 , 7060,20 , 13,5 , 4,0 , 1847,5 , 1852,5 , 2, 1, 1, 6, 7 }, // Finnish/Latin/Finland
- { 37, 7, 74, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 1857,8 , 1865,6 , 2, 1, 1, 6, 7 }, // French/Latin/France
- { 37, 7, 3, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {68,90,68}, 208,2 , 7080,51 , 13,5 , 4,0 , 1857,8 , 1871,7 , 2, 1, 6, 5, 6 }, // French/Latin/Algeria
- { 37, 7, 21, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 509,7 , 98,16 , 37,5 , 235,23 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 1857,8 , 1878,8 , 2, 1, 1, 6, 7 }, // French/Latin/Belgium
- { 37, 7, 23, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,79,70}, 210,3 , 7131,59 , 13,5 , 4,0 , 1857,8 , 1886,5 , 0, 0, 1, 6, 7 }, // French/Latin/Benin
- { 37, 7, 34, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,79,70}, 210,3 , 7131,59 , 13,5 , 4,0 , 1857,8 , 1891,12 , 0, 0, 1, 6, 7 }, // French/Latin/BurkinaFaso
- { 37, 7, 35, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {66,73,70}, 169,3 , 7190,53 , 13,5 , 4,0 , 1857,8 , 900,7 , 0, 0, 1, 6, 7 }, // French/Latin/Burundi
- { 37, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 73,5 , 70,4 , 359,6 , 174,17 , 191,23 , {88,65,70}, 32,4 , 7243,56 , 13,5 , 4,0 , 1857,8 , 1903,8 , 0, 0, 1, 6, 7 }, // French/Latin/Cameroon
- { 37, 7, 38, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8221, 8220, 0,6 , 0,6 , 218,8 , 218,8 , 558,8 , 98,16 , 258,9 , 8,10 , 6549,64 , 6464,85 , 134,24 , 6549,64 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 64,4 , 61,4 , 359,6 , 174,17 , 191,23 , {67,65,68}, 6,1 , 7299,54 , 41,8 , 4,0 , 1911,17 , 931,6 , 2, 0, 7, 6, 7 }, // French/Latin/Canada
- { 37, 7, 41, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,65,70}, 32,4 , 7243,56 , 13,5 , 4,0 , 1857,8 , 1928,25 , 0, 0, 1, 6, 7 }, // French/Latin/CentralAfricanRepublic
- { 37, 7, 42, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,65,70}, 32,4 , 7243,56 , 13,5 , 4,0 , 1857,8 , 1953,5 , 0, 0, 1, 6, 7 }, // French/Latin/Chad
- { 37, 7, 48, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {75,77,70}, 213,2 , 7353,51 , 13,5 , 4,0 , 1857,8 , 1958,7 , 0, 0, 1, 6, 7 }, // French/Latin/Comoros
- { 37, 7, 49, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {67,68,70}, 215,2 , 7404,53 , 13,5 , 4,0 , 1857,8 , 1965,14 , 2, 1, 1, 6, 7 }, // French/Latin/CongoKinshasa
- { 37, 7, 50, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,65,70}, 32,4 , 7243,56 , 13,5 , 4,0 , 1857,8 , 1979,17 , 0, 0, 1, 6, 7 }, // French/Latin/CongoBrazzaville
- { 37, 7, 53, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,79,70}, 210,3 , 7131,59 , 13,5 , 4,0 , 1857,8 , 1996,13 , 0, 0, 1, 6, 7 }, // French/Latin/IvoryCoast
- { 37, 7, 59, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {68,74,70}, 43,3 , 7457,57 , 13,5 , 4,0 , 1857,8 , 2009,8 , 0, 0, 6, 6, 7 }, // French/Latin/Djibouti
- { 37, 7, 66, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,65,70}, 32,4 , 7243,56 , 13,5 , 4,0 , 1857,8 , 2017,18 , 0, 0, 1, 6, 7 }, // French/Latin/EquatorialGuinea
- { 37, 7, 76, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 1857,8 , 2035,16 , 2, 1, 1, 6, 7 }, // French/Latin/FrenchGuiana
- { 37, 7, 77, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,80,70}, 217,4 , 7514,35 , 13,5 , 4,0 , 1857,8 , 2051,19 , 0, 0, 1, 6, 7 }, // French/Latin/FrenchPolynesia
- { 37, 7, 79, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,65,70}, 32,4 , 7243,56 , 13,5 , 4,0 , 1857,8 , 2070,5 , 0, 0, 1, 6, 7 }, // French/Latin/Gabon
- { 37, 7, 88, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 1857,8 , 2075,10 , 2, 1, 1, 6, 7 }, // French/Latin/Guadeloupe
- { 37, 7, 91, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {71,78,70}, 221,2 , 7549,48 , 13,5 , 4,0 , 1857,8 , 2085,6 , 0, 0, 1, 6, 7 }, // French/Latin/Guinea
- { 37, 7, 94, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {72,84,71}, 223,1 , 7597,57 , 13,5 , 4,0 , 1857,8 , 2091,5 , 2, 1, 1, 6, 7 }, // French/Latin/Haiti
- { 37, 7, 125, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 1857,8 , 2096,10 , 2, 1, 1, 6, 7 }, // French/Latin/Luxembourg
- { 37, 7, 128, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {77,71,65}, 176,2 , 7654,54 , 13,5 , 4,0 , 1857,8 , 1195,10 , 0, 0, 1, 6, 7 }, // French/Latin/Madagascar
- { 37, 7, 132, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,79,70}, 210,3 , 7131,59 , 13,5 , 4,0 , 1857,8 , 2106,4 , 0, 0, 1, 6, 7 }, // French/Latin/Mali
- { 37, 7, 135, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 1857,8 , 2110,10 , 2, 1, 1, 6, 7 }, // French/Latin/Martinique
- { 37, 7, 136, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {77,82,79}, 224,2 , 7708,66 , 13,5 , 4,0 , 1857,8 , 2120,10 , 0, 0, 1, 6, 7 }, // French/Latin/Mauritania
- { 37, 7, 137, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {77,85,82}, 182,2 , 7774,63 , 13,5 , 4,0 , 1857,8 , 2130,7 , 0, 0, 1, 6, 7 }, // French/Latin/Mauritius
- { 37, 7, 138, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 1857,8 , 2137,7 , 2, 1, 1, 6, 7 }, // French/Latin/Mayotte
- { 37, 7, 142, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 1857,8 , 2144,6 , 2, 1, 1, 6, 7 }, // French/Latin/Monaco
- { 37, 7, 145, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6613,61 , 6464,85 , 134,24 , 6613,61 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 64,4 , 61,4 , 359,6 , 174,17 , 191,23 , {77,65,68}, 226,3 , 7837,54 , 13,5 , 4,0 , 1857,8 , 2150,5 , 2, 1, 6, 5, 6 }, // French/Latin/Morocco
- { 37, 7, 153, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,80,70}, 217,4 , 7514,35 , 13,5 , 4,0 , 1857,8 , 2155,18 , 0, 0, 1, 6, 7 }, // French/Latin/NewCaledonia
- { 37, 7, 156, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,79,70}, 210,3 , 7131,59 , 13,5 , 4,0 , 1857,8 , 2173,5 , 0, 0, 1, 6, 7 }, // French/Latin/Niger
- { 37, 7, 176, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 1857,8 , 2178,10 , 2, 1, 1, 6, 7 }, // French/Latin/Reunion
- { 37, 7, 179, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {82,87,70}, 186,2 , 7891,50 , 13,5 , 4,0 , 1857,8 , 1419,6 , 0, 0, 1, 6, 7 }, // French/Latin/Rwanda
- { 37, 7, 187, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,79,70}, 210,3 , 7131,59 , 13,5 , 4,0 , 1857,8 , 2188,7 , 0, 0, 1, 6, 7 }, // French/Latin/Senegal
- { 37, 7, 188, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {83,67,82}, 191,2 , 7941,71 , 13,5 , 4,0 , 1857,8 , 1480,10 , 2, 1, 1, 6, 7 }, // French/Latin/Seychelles
- { 37, 7, 200, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 1857,8 , 2195,24 , 2, 1, 1, 6, 7 }, // French/Latin/SaintPierreAndMiquelon
- { 37, 7, 206, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 218,8 , 218,8 , 175,8 , 10,17 , 37,5 , 267,14 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {67,72,70}, 229,3 , 8012,45 , 13,5 , 4,0 , 2219,15 , 2234,6 , 2, 0, 1, 6, 7 }, // French/Latin/Switzerland
- { 37, 7, 207, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {83,89,80}, 232,2 , 8057,51 , 13,5 , 4,0 , 1857,8 , 2240,5 , 0, 0, 6, 5, 6 }, // French/Latin/Syria
- { 37, 7, 212, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,79,70}, 210,3 , 7131,59 , 13,5 , 4,0 , 1857,8 , 2245,4 , 0, 0, 1, 6, 7 }, // French/Latin/Togo
- { 37, 7, 216, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {84,78,68}, 234,2 , 8108,51 , 13,5 , 4,0 , 1857,8 , 2249,7 , 3, 0, 7, 5, 6 }, // French/Latin/Tunisia
- { 37, 7, 229, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {86,85,86}, 206,2 , 8159,51 , 13,5 , 4,0 , 1857,8 , 1708,7 , 0, 0, 1, 6, 7 }, // French/Latin/Vanuatu
- { 37, 7, 235, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,80,70}, 217,4 , 7514,35 , 13,5 , 4,0 , 1857,8 , 2256,16 , 0, 0, 1, 6, 7 }, // French/Latin/WallisAndFutunaIslands
- { 37, 7, 244, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 1857,8 , 2272,16 , 2, 1, 1, 6, 7 }, // French/Latin/Saint Barthelemy
- { 37, 7, 245, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 1857,8 , 2288,12 , 2, 1, 1, 6, 7 }, // French/Latin/Saint Martin
- { 38, 7, 151, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 6,8 , 6,8 , 348,8 , 98,16 , 37,5 , 8,10 , 6674,48 , 6722,95 , 134,24 , 6674,48 , 6722,95 , 134,24 , 3068,21 , 3089,54 , 85,14 , 3068,21 , 3089,54 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3410,19 , 8,5 , 49,6 , 2300,10 , 2310,8 , 2, 1, 1, 6, 7 }, // Western Frisian/Latin/Netherlands
- { 39, 7, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 226,10 , 226,10 , 120,10 , 566,21 , 37,5 , 8,10 , 6817,61 , 6878,142 , 7020,24 , 6817,61 , 7044,167 , 7020,24 , 3143,28 , 3171,69 , 3240,14 , 3143,28 , 3171,69 , 3240,14 , 78,1 , 74,1 , 365,6 , 5,17 , 22,23 , {71,66,80}, 125,1 , 8210,86 , 4,4 , 4,0 , 2318,8 , 2326,22 , 2, 1, 1, 6, 7 }, // Gaelic/Latin/UnitedKingdom
- { 40, 7, 197, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 587,27 , 37,5 , 8,10 , 7211,60 , 7271,87 , 7358,24 , 7382,60 , 7442,87 , 7529,36 , 3254,35 , 3289,49 , 3338,14 , 3352,35 , 3387,49 , 3436,21 , 64,4 , 61,4 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3865,20 , 13,5 , 4,0 , 2348,6 , 2354,6 , 2, 1, 1, 6, 7 }, // Galician/Latin/Spain
- { 41, 15, 81, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 171, 187, 0,6 , 0,6 , 243,8 , 243,8 , 175,8 , 614,19 , 37,5 , 8,10 , 7565,48 , 7613,99 , 7712,24 , 7565,48 , 7613,99 , 7712,24 , 3457,28 , 3485,62 , 3547,14 , 3457,28 , 3485,62 , 3547,14 , 0,2 , 0,2 , 371,5 , 376,33 , 22,23 , {71,69,76}, 236,1 , 8296,43 , 13,5 , 4,0 , 2360,7 , 2367,10 , 2, 1, 1, 6, 7 }, // Georgian/Georgian/Georgia
- { 42, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 251,9 , 251,9 , 175,8 , 532,18 , 37,5 , 8,10 , 7736,48 , 7784,83 , 134,24 , 7867,59 , 7784,83 , 134,24 , 3561,21 , 3582,60 , 3642,14 , 3656,28 , 3582,60 , 3642,14 , 79,5 , 75,6 , 409,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8339,19 , 13,5 , 4,0 , 2377,7 , 2384,11 , 2, 1, 1, 6, 7 }, // German/Latin/Germany
- { 42, 7, 14, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 251,9 , 251,9 , 175,8 , 532,18 , 37,5 , 8,10 , 7926,48 , 7974,83 , 134,24 , 8057,59 , 7974,83 , 134,24 , 3561,21 , 3582,60 , 3642,14 , 3656,28 , 3582,60 , 3642,14 , 79,5 , 75,6 , 409,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8339,19 , 8,5 , 4,0 , 2395,24 , 2419,10 , 2, 1, 1, 6, 7 }, // German/Latin/Austria
- { 42, 7, 21, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 251,9 , 251,9 , 175,8 , 532,18 , 37,5 , 8,10 , 7736,48 , 7784,83 , 134,24 , 7867,59 , 7784,83 , 134,24 , 3561,21 , 3582,60 , 3642,14 , 3656,28 , 3582,60 , 3642,14 , 79,5 , 75,6 , 409,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8339,19 , 13,5 , 4,0 , 2377,7 , 2429,7 , 2, 1, 1, 6, 7 }, // German/Latin/Belgium
- { 42, 7, 106, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 251,9 , 251,9 , 175,8 , 532,18 , 37,5 , 8,10 , 7926,48 , 7974,83 , 134,24 , 8057,59 , 7974,83 , 134,24 , 3561,21 , 3582,60 , 3642,14 , 3656,28 , 3582,60 , 3642,14 , 79,5 , 75,6 , 409,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8339,19 , 13,5 , 4,0 , 2377,7 , 2436,7 , 2, 1, 1, 6, 7 }, // German/Latin/Italy
- { 42, 7, 123, 46, 8217, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 251,9 , 251,9 , 175,8 , 532,18 , 37,5 , 8,10 , 7736,48 , 7784,83 , 134,24 , 7867,59 , 7784,83 , 134,24 , 3561,21 , 3582,60 , 3642,14 , 3656,28 , 3582,60 , 3642,14 , 79,5 , 75,6 , 409,5 , 5,17 , 22,23 , {67,72,70}, 229,3 , 8358,58 , 8,5 , 4,0 , 2377,7 , 2443,13 , 2, 0, 1, 6, 7 }, // German/Latin/Liechtenstein
- { 42, 7, 125, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 251,9 , 251,9 , 175,8 , 532,18 , 37,5 , 8,10 , 7736,48 , 7784,83 , 134,24 , 7867,59 , 7784,83 , 134,24 , 3561,21 , 3582,60 , 3642,14 , 3656,28 , 3582,60 , 3642,14 , 79,5 , 75,6 , 409,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8339,19 , 13,5 , 4,0 , 2377,7 , 2456,9 , 2, 1, 1, 6, 7 }, // German/Latin/Luxembourg
- { 42, 7, 206, 46, 8217, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 251,9 , 251,9 , 175,8 , 532,18 , 37,5 , 8,10 , 7736,48 , 7784,83 , 134,24 , 7867,59 , 7784,83 , 134,24 , 3561,21 , 3582,60 , 3642,14 , 3656,28 , 3582,60 , 3642,14 , 79,5 , 75,6 , 409,5 , 5,17 , 22,23 , {67,72,70}, 229,3 , 8358,58 , 8,5 , 36,5 , 2465,21 , 2486,7 , 2, 0, 1, 6, 7 }, // German/Latin/Switzerland
- { 43, 16, 85, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 260,9 , 260,9 , 278,6 , 10,17 , 18,7 , 25,12 , 8116,50 , 8166,115 , 8281,24 , 8305,50 , 8355,115 , 8281,24 , 3684,28 , 3712,55 , 3767,14 , 3684,28 , 3712,55 , 3767,14 , 84,4 , 81,4 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8416,19 , 13,5 , 4,0 , 2493,8 , 2501,6 , 2, 1, 1, 6, 7 }, // Greek/Greek/Greece
- { 43, 16, 56, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 260,9 , 260,9 , 278,6 , 10,17 , 18,7 , 25,12 , 8116,50 , 8166,115 , 8281,24 , 8305,50 , 8355,115 , 8281,24 , 3684,28 , 3712,55 , 3767,14 , 3684,28 , 3712,55 , 3767,14 , 84,4 , 81,4 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8416,19 , 13,5 , 4,0 , 2493,8 , 2507,6 , 2, 1, 1, 6, 7 }, // Greek/Greek/Cyprus
- { 44, 7, 86, 44, 46, 59, 37, 48, 8722, 43, 101, 187, 171, 8250, 8249, 0,6 , 0,6 , 269,11 , 269,11 , 53,10 , 633,17 , 18,7 , 25,12 , 8470,48 , 8518,96 , 134,24 , 8470,48 , 8518,96 , 134,24 , 3781,28 , 3809,98 , 3907,14 , 3781,28 , 3809,98 , 3907,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {68,75,75}, 154,3 , 8435,62 , 4,4 , 55,5 , 2513,11 , 2524,16 , 2, 1, 1, 6, 7 }, // Greenlandic/Latin/Greenland
- { 45, 7, 168, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {80,89,71}, 237,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 7, 6, 7 }, // Guarani/Latin/Paraguay
- { 46, 17, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 280,9 , 280,9 , 278,6 , 211,18 , 281,8 , 289,13 , 8614,67 , 8681,87 , 8768,31 , 8614,67 , 8681,87 , 8768,31 , 3921,32 , 3953,53 , 4006,19 , 3921,32 , 3953,53 , 4006,19 , 0,2 , 0,2 , 414,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 8497,46 , 4,4 , 4,0 , 2540,7 , 2547,4 , 2, 1, 7, 7, 7 }, // Gujarati/Gujarati/India
- { 47, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 278,6 , 211,18 , 37,5 , 8,10 , 8799,48 , 8847,85 , 8932,24 , 8799,48 , 8847,85 , 8932,24 , 4025,28 , 4053,52 , 4105,14 , 4025,28 , 4053,52 , 4105,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {78,71,78}, 184,1 , 8543,12 , 8,5 , 4,0 , 2551,5 , 2556,8 , 2, 1, 1, 6, 7 }, // Hausa/Latin/Nigeria
- { 47, 1, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {78,71,78}, 184,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Hausa/Arabic/Nigeria
- { 47, 7, 83, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 278,6 , 211,18 , 37,5 , 8,10 , 8799,48 , 8847,85 , 8932,24 , 8799,48 , 8847,85 , 8932,24 , 4025,28 , 4053,52 , 4105,14 , 4025,28 , 4053,52 , 4105,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {71,72,83}, 173,3 , 0,7 , 8,5 , 4,0 , 2551,5 , 2564,4 , 2, 1, 1, 6, 7 }, // Hausa/Latin/Ghana
- { 47, 7, 156, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 278,6 , 211,18 , 37,5 , 8,10 , 8799,48 , 8847,85 , 8932,24 , 8799,48 , 8847,85 , 8932,24 , 4025,28 , 4053,52 , 4105,14 , 4025,28 , 4053,52 , 4105,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,79,70}, 210,3 , 8555,36 , 8,5 , 4,0 , 2551,5 , 2568,5 , 0, 0, 1, 6, 7 }, // Hausa/Latin/Niger
- { 48, 18, 105, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 289,6 , 289,6 , 550,8 , 650,18 , 55,4 , 59,9 , 8956,58 , 9014,72 , 158,27 , 8956,58 , 9014,72 , 158,27 , 4119,46 , 4165,65 , 4230,21 , 4119,46 , 4165,65 , 4230,21 , 88,6 , 85,5 , 418,4 , 5,17 , 22,23 , {73,76,83}, 54,1 , 8591,54 , 60,6 , 66,8 , 2573,5 , 2578,5 , 2, 1, 7, 5, 6 }, // Hebrew/Hebrew/Israel
- { 49, 13, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 295,9 , 304,8 , 278,6 , 10,17 , 18,7 , 25,12 , 9086,59 , 9145,73 , 9218,30 , 9086,59 , 9145,73 , 9218,30 , 4251,32 , 4283,53 , 4336,19 , 4251,32 , 4283,53 , 4336,19 , 94,9 , 90,7 , 422,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 8645,42 , 4,4 , 4,0 , 2583,6 , 2589,4 , 2, 1, 7, 7, 7 }, // Hindi/Devanagari/India
- { 50, 7, 98, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 187, 171, 0,6 , 0,6 , 312,8 , 312,8 , 668,13 , 681,19 , 55,4 , 59,9 , 9248,64 , 9312,98 , 9410,25 , 9248,64 , 9312,98 , 9410,25 , 4355,19 , 4374,52 , 4426,17 , 4355,19 , 4374,52 , 4426,17 , 103,3 , 97,3 , 426,4 , 5,17 , 22,23 , {72,85,70}, 238,2 , 8687,46 , 13,5 , 4,0 , 2593,6 , 2599,12 , 2, 0, 1, 6, 7 }, // Hungarian/Latin/Hungary
- { 51, 7, 99, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 183,8 , 183,8 , 550,8 , 532,18 , 37,5 , 8,10 , 9435,59 , 9494,82 , 9576,24 , 9435,59 , 9494,82 , 9576,24 , 4443,35 , 4478,81 , 4559,14 , 4443,35 , 4478,81 , 4559,14 , 106,4 , 100,4 , 430,4 , 5,17 , 22,23 , {73,83,75}, 240,3 , 8733,49 , 13,5 , 4,0 , 2611,8 , 2619,6 , 0, 0, 1, 6, 7 }, // Icelandic/Latin/Iceland
- { 52, 7, 101, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 320,10 , 330,9 , 27,8 , 80,18 , 200,5 , 205,10 , 9600,48 , 9648,87 , 134,24 , 9600,48 , 9648,87 , 134,24 , 4573,28 , 4601,43 , 4644,14 , 4573,28 , 4601,43 , 4644,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,68,82}, 243,2 , 8782,39 , 4,4 , 4,0 , 2625,9 , 2625,9 , 0, 0, 7, 6, 7 }, // Indonesian/Latin/Indonesia
- { 53, 7, 74, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Interlingua/Latin/France
- { 55, 44, 38, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,65,68}, 245,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 0, 7, 6, 7 }, // Inuktitut/CanadianAboriginal/Canada
- { 55, 7, 38, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,65,68}, 245,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 0, 7, 6, 7 }, // Inuktitut/Latin/Canada
- { 57, 7, 104, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 339,11 , 226,10 , 120,10 , 98,16 , 37,5 , 8,10 , 9735,62 , 9797,107 , 9904,24 , 9735,62 , 9797,107 , 9904,24 , 4658,37 , 4695,75 , 4770,14 , 4658,37 , 4695,75 , 4770,14 , 64,4 , 61,4 , 434,6 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8821,31 , 4,4 , 4,0 , 2634,7 , 2641,4 , 2, 1, 7, 6, 7 }, // Irish/Latin/Ireland
- { 58, 7, 106, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 98,16 , 37,5 , 8,10 , 9928,48 , 9976,94 , 10070,24 , 9928,48 , 9976,94 , 10070,24 , 4784,28 , 4812,57 , 4869,14 , 4784,28 , 4812,57 , 4869,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8852,19 , 13,5 , 4,0 , 2645,8 , 2653,6 , 2, 1, 1, 6, 7 }, // Italian/Latin/Italy
- { 58, 7, 184, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 98,16 , 37,5 , 8,10 , 9928,48 , 9976,94 , 10070,24 , 9928,48 , 9976,94 , 10070,24 , 4784,28 , 4812,57 , 4869,14 , 4784,28 , 4812,57 , 4869,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8852,19 , 13,5 , 4,0 , 2645,8 , 2659,10 , 2, 1, 1, 6, 7 }, // Italian/Latin/SanMarino
- { 58, 7, 206, 46, 8217, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 236,7 , 236,7 , 175,8 , 10,17 , 37,5 , 8,10 , 9928,48 , 9976,94 , 10070,24 , 9928,48 , 9976,94 , 10070,24 , 4784,28 , 4812,57 , 4869,14 , 4784,28 , 4812,57 , 4869,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,72,70}, 229,3 , 8871,53 , 8,5 , 36,5 , 2645,8 , 2669,8 , 2, 0, 1, 6, 7 }, // Italian/Latin/Switzerland
- { 58, 7, 230, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 98,16 , 37,5 , 8,10 , 9928,48 , 9976,94 , 10070,24 , 9928,48 , 9976,94 , 10070,24 , 4784,28 , 4812,57 , 4869,14 , 4784,28 , 4812,57 , 4869,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8852,19 , 13,5 , 4,0 , 2645,8 , 2677,18 , 2, 1, 1, 6, 7 }, // Italian/Latin/VaticanCityState
- { 59, 19, 108, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 161,5 , 161,5 , 161,5 , 161,5 , 522,10 , 393,13 , 55,4 , 302,10 , 4697,39 , 4697,39 , 158,27 , 4697,39 , 4697,39 , 158,27 , 4883,14 , 4897,28 , 4883,14 , 4883,14 , 4897,28 , 4883,14 , 110,2 , 104,2 , 440,3 , 297,17 , 22,23 , {74,80,89}, 139,1 , 8924,11 , 4,4 , 4,0 , 2695,3 , 2698,2 , 0, 0, 7, 6, 7 }, // Japanese/Japanese/Japan
- { 60, 7, 101, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,68,82}, 243,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 7, 6, 7 }, // Javanese/Latin/Indonesia
- { 61, 21, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 350,12 , 362,11 , 278,6 , 35,18 , 281,8 , 289,13 , 10094,63 , 10157,87 , 10244,31 , 10094,63 , 10157,87 , 10244,31 , 4925,33 , 4958,54 , 5012,20 , 4925,33 , 4958,54 , 5012,20 , 112,9 , 106,7 , 443,8 , 451,33 , 22,23 , {73,78,82}, 127,1 , 8935,49 , 4,4 , 4,0 , 2700,5 , 2705,4 , 2, 1, 7, 7, 7 }, // Kannada/Kannada/India
- { 62, 1, 100, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 516,6 , 35,18 , 18,7 , 25,12 , 10275,72 , 10275,72 , 10347,24 , 10275,72 , 10275,72 , 10347,24 , 5032,54 , 5086,56 , 5142,14 , 5032,54 , 5086,56 , 5142,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 8984,23 , 8,5 , 4,0 , 2709,5 , 2714,10 , 2, 1, 7, 7, 7 }, // Kashmiri/Arabic/India
- { 63, 2, 110, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 373,10 , 175,8 , 700,22 , 37,5 , 8,10 , 10371,60 , 10431,83 , 10514,24 , 10538,60 , 10598,83 , 10514,24 , 5156,21 , 5177,56 , 5233,14 , 5156,21 , 5247,56 , 5233,14 , 0,2 , 0,2 , 484,4 , 488,17 , 505,23 , {75,90,84}, 248,1 , 9007,58 , 13,5 , 4,0 , 2724,10 , 2734,9 , 2, 1, 1, 6, 7 }, // Kazakh/Cyrillic/Kazakhstan
- { 64, 7, 179, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 10681,60 , 10741,101 , 158,27 , 10681,60 , 10741,101 , 158,27 , 5303,35 , 5338,84 , 85,14 , 5303,35 , 5338,84 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {82,87,70}, 186,2 , 0,7 , 8,5 , 4,0 , 2743,11 , 1419,6 , 0, 0, 1, 6, 7 }, // Kinyarwanda/Latin/Rwanda
- { 65, 2, 116, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 383,10 , 383,10 , 278,6 , 722,23 , 37,5 , 8,10 , 10842,48 , 10890,80 , 10970,24 , 10994,59 , 11053,80 , 10970,24 , 5422,38 , 5460,57 , 5517,14 , 5422,38 , 5460,57 , 5517,14 , 121,5 , 113,14 , 484,4 , 528,17 , 22,23 , {75,71,83}, 249,3 , 9065,52 , 13,5 , 4,0 , 2754,8 , 2762,10 , 2, 1, 1, 6, 7 }, // Kirghiz/Cyrillic/Kyrgyzstan
- { 66, 22, 114, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 393,7 , 393,7 , 745,9 , 754,16 , 312,7 , 319,13 , 11133,39 , 11133,39 , 11133,39 , 11133,39 , 11133,39 , 11133,39 , 5531,14 , 5545,28 , 5531,14 , 5531,14 , 5545,28 , 5531,14 , 126,2 , 127,2 , 545,3 , 5,17 , 22,23 , {75,82,87}, 252,1 , 9117,19 , 4,4 , 4,0 , 2772,3 , 2775,4 , 0, 0, 7, 6, 7 }, // Korean/Korean/SouthKorea
- { 66, 22, 113, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 393,7 , 393,7 , 745,9 , 754,16 , 312,7 , 319,13 , 11133,39 , 11133,39 , 11133,39 , 11133,39 , 11133,39 , 11133,39 , 5531,14 , 5545,28 , 5531,14 , 5531,14 , 5545,28 , 5531,14 , 126,2 , 127,2 , 545,3 , 5,17 , 22,23 , {75,80,87}, 253,3 , 9136,39 , 4,4 , 4,0 , 2772,3 , 2779,11 , 0, 0, 1, 6, 7 }, // Korean/Korean/NorthKorea
- { 67, 7, 217, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {84,82,89}, 256,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Kurdish/Latin/Turkey
- { 68, 7, 35, 44, 46, 59, 37, 48, 45, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 11172,60 , 11232,106 , 158,27 , 11172,60 , 11232,106 , 158,27 , 5573,34 , 5607,89 , 85,14 , 5573,34 , 5607,89 , 85,14 , 128,5 , 129,5 , 45,4 , 5,17 , 22,23 , {66,73,70}, 169,3 , 9175,27 , 0,4 , 4,0 , 2790,8 , 2798,8 , 0, 0, 1, 6, 7 }, // Rundi/Latin/Burundi
- { 69, 23, 117, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 400,9 , 406,8 , 770,19 , 55,4 , 332,24 , 11338,61 , 11399,75 , 158,27 , 11338,61 , 11399,75 , 158,27 , 5696,36 , 5732,57 , 5789,17 , 5696,36 , 5732,57 , 5789,17 , 133,8 , 134,8 , 45,4 , 5,17 , 22,23 , {76,65,75}, 257,1 , 9202,21 , 4,4 , 36,5 , 2806,3 , 2806,3 , 0, 0, 7, 6, 7 }, // Lao/Lao/Laos
- { 71, 7, 118, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 409,8 , 409,8 , 175,8 , 789,26 , 37,5 , 8,10 , 11474,65 , 11539,101 , 134,24 , 11474,65 , 11539,101 , 134,24 , 5806,51 , 5857,72 , 5929,14 , 5943,51 , 5994,72 , 5929,14 , 141,14 , 142,11 , 548,5 , 297,17 , 22,23 , {69,85,82}, 14,1 , 9223,23 , 13,5 , 4,0 , 2809,8 , 2817,7 , 2, 1, 1, 6, 7 }, // Latvian/Latin/Latvia
- { 72, 7, 49, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 417,9 , 417,9 , 406,8 , 98,16 , 37,5 , 8,10 , 11640,48 , 11688,203 , 11891,24 , 11640,48 , 11688,203 , 11891,24 , 6066,28 , 6094,100 , 6194,14 , 6066,28 , 6094,100 , 6194,14 , 155,8 , 153,6 , 45,4 , 5,17 , 22,23 , {67,68,70}, 215,2 , 9246,23 , 13,5 , 4,0 , 2824,7 , 2831,30 , 2, 1, 1, 6, 7 }, // Lingala/Latin/CongoKinshasa
- { 72, 7, 6, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 417,9 , 417,9 , 406,8 , 98,16 , 37,5 , 8,10 , 11640,48 , 11688,203 , 11891,24 , 11640,48 , 11688,203 , 11891,24 , 6066,28 , 6094,100 , 6194,14 , 6066,28 , 6094,100 , 6194,14 , 155,8 , 153,6 , 45,4 , 5,17 , 22,23 , {65,79,65}, 258,2 , 9269,23 , 13,5 , 4,0 , 2824,7 , 2861,6 , 2, 1, 1, 6, 7 }, // Lingala/Latin/Angola
- { 72, 7, 41, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 417,9 , 417,9 , 406,8 , 98,16 , 37,5 , 8,10 , 11640,48 , 11688,203 , 11891,24 , 11640,48 , 11688,203 , 11891,24 , 6066,28 , 6094,100 , 6194,14 , 6066,28 , 6094,100 , 6194,14 , 155,8 , 153,6 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 9292,23 , 13,5 , 4,0 , 2824,7 , 2867,26 , 0, 0, 1, 6, 7 }, // Lingala/Latin/CentralAfricanRepublic
- { 72, 7, 50, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 417,9 , 417,9 , 406,8 , 98,16 , 37,5 , 8,10 , 11640,48 , 11688,203 , 11891,24 , 11640,48 , 11688,203 , 11891,24 , 6066,28 , 6094,100 , 6194,14 , 6066,28 , 6094,100 , 6194,14 , 155,8 , 153,6 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 9292,23 , 13,5 , 4,0 , 2824,7 , 2893,5 , 0, 0, 1, 6, 7 }, // Lingala/Latin/CongoBrazzaville
- { 73, 7, 124, 44, 160, 59, 37, 48, 8722, 43, 101, 8222, 8220, 8222, 8220, 0,6 , 0,6 , 426,8 , 426,8 , 53,10 , 815,27 , 37,5 , 8,10 , 11915,70 , 11985,96 , 12081,24 , 11915,70 , 12105,98 , 12081,24 , 6208,21 , 6229,89 , 6318,14 , 6208,21 , 6229,89 , 6318,14 , 163,9 , 159,6 , 553,6 , 5,17 , 22,23 , {69,85,82}, 14,1 , 9315,30 , 13,5 , 4,0 , 2898,8 , 2906,7 , 2, 1, 1, 6, 7 }, // Lithuanian/Latin/Lithuania
- { 74, 2, 127, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 107,7 , 107,7 , 842,7 , 80,18 , 37,5 , 8,10 , 12203,61 , 12264,85 , 12349,24 , 12203,61 , 12264,85 , 12349,24 , 6332,35 , 6367,54 , 1649,14 , 6421,34 , 6367,54 , 1649,14 , 172,10 , 165,8 , 559,5 , 5,17 , 22,23 , {77,75,68}, 260,3 , 9345,56 , 13,5 , 4,0 , 2913,10 , 2923,10 , 2, 1, 1, 6, 7 }, // Macedonian/Cyrillic/Macedonia
- { 75, 7, 128, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 98,16 , 37,5 , 8,10 , 12373,48 , 12421,92 , 134,24 , 12373,48 , 12421,92 , 134,24 , 6455,34 , 6489,60 , 6549,14 , 6455,34 , 6489,60 , 6549,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {77,71,65}, 176,2 , 9401,13 , 8,5 , 4,0 , 2933,8 , 2941,12 , 0, 0, 1, 6, 7 }, // Malagasy/Latin/Madagascar
- { 76, 7, 130, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 330,9 , 330,9 , 509,7 , 10,17 , 18,7 , 25,12 , 12513,48 , 12561,82 , 12643,24 , 12513,48 , 12561,82 , 12643,24 , 6563,28 , 6591,43 , 6634,14 , 6563,28 , 6591,43 , 6634,14 , 182,2 , 173,3 , 564,4 , 5,17 , 22,23 , {77,89,82}, 180,2 , 9414,39 , 4,4 , 4,0 , 2953,13 , 1211,8 , 2, 1, 1, 6, 7 }, // Malay/Latin/Malaysia
- { 76, 1, 130, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {77,89,82}, 180,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Malay/Arabic/Malaysia
- { 76, 7, 32, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 330,9 , 330,9 , 509,7 , 849,12 , 18,7 , 25,12 , 12513,48 , 12561,82 , 12643,24 , 12513,48 , 12561,82 , 12643,24 , 6563,28 , 6591,43 , 6634,14 , 6563,28 , 6591,43 , 6634,14 , 182,2 , 173,3 , 564,4 , 5,17 , 22,23 , {66,78,68}, 6,1 , 9453,31 , 8,5 , 4,0 , 2953,13 , 2966,6 , 2, 1, 1, 6, 7 }, // Malay/Latin/Brunei
- { 76, 7, 190, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 330,9 , 330,9 , 509,7 , 10,17 , 18,7 , 25,12 , 12513,48 , 12561,82 , 12643,24 , 12513,48 , 12561,82 , 12643,24 , 6563,28 , 6591,43 , 6634,14 , 6563,28 , 6591,43 , 6634,14 , 182,2 , 173,3 , 564,4 , 5,17 , 22,23 , {83,71,68}, 6,1 , 9484,37 , 4,4 , 4,0 , 2953,13 , 2972,9 , 2, 1, 7, 6, 7 }, // Malay/Latin/Singapore
- { 77, 24, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 434,13 , 447,12 , 278,6 , 861,18 , 18,7 , 25,12 , 12667,62 , 12729,88 , 12817,32 , 12667,62 , 12729,88 , 12849,31 , 6648,41 , 6689,77 , 6766,22 , 6648,41 , 6788,76 , 6864,21 , 0,2 , 0,2 , 568,6 , 574,31 , 22,23 , {73,78,82}, 127,1 , 9521,40 , 4,4 , 4,0 , 2981,6 , 2987,6 , 2, 1, 7, 7, 7 }, // Malayalam/Malayalam/India
- { 78, 7, 133, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 459,8 , 467,7 , 120,10 , 879,23 , 37,5 , 8,10 , 12880,48 , 12928,86 , 13014,36 , 12880,48 , 12928,86 , 13050,24 , 6885,28 , 6913,63 , 6976,21 , 6885,28 , 6913,63 , 6997,20 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 9561,27 , 4,4 , 4,0 , 2993,5 , 1219,5 , 2, 1, 7, 6, 7 }, // Maltese/Latin/Malta
- { 79, 7, 154, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {78,90,68}, 263,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Maori/Latin/NewZealand
- { 80, 13, 100, 46, 44, 59, 37, 2406, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 474,9 , 474,9 , 278,6 , 211,18 , 18,7 , 25,12 , 13074,66 , 13140,86 , 13226,32 , 13074,66 , 13140,86 , 13226,32 , 7017,32 , 7049,53 , 4336,19 , 7017,32 , 7049,53 , 4336,19 , 184,5 , 176,4 , 422,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 9588,43 , 4,4 , 4,0 , 2998,5 , 2589,4 , 2, 1, 7, 7, 7 }, // Marathi/Devanagari/India
- { 82, 2, 143, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 902,29 , 37,5 , 8,10 , 13258,99 , 13357,189 , 158,27 , 13258,99 , 13357,189 , 158,27 , 7102,21 , 7123,43 , 7102,21 , 7102,21 , 7123,43 , 7102,21 , 189,3 , 180,3 , 484,4 , 528,17 , 22,23 , {77,78,84}, 266,1 , 9631,25 , 8,5 , 4,0 , 3003,6 , 3009,6 , 0, 0, 1, 6, 7 }, // Mongolian/Cyrillic/Mongolia
- { 82, 8, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,78,89}, 267,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Mongolian/Mongolian/China
- { 84, 13, 150, 46, 44, 59, 37, 2406, 45, 43, 101, 8220, 8221, 8216, 8217, 483,5 , 0,6 , 488,7 , 488,7 , 53,10 , 63,17 , 37,5 , 8,10 , 13546,85 , 13546,85 , 13631,27 , 13546,85 , 13658,85 , 13631,27 , 7166,33 , 7199,54 , 7253,18 , 7166,33 , 7199,54 , 7253,18 , 94,9 , 90,7 , 422,4 , 5,17 , 22,23 , {78,80,82}, 270,4 , 9656,49 , 8,5 , 4,0 , 3015,6 , 3021,5 , 2, 1, 7, 6, 7 }, // Nepali/Devanagari/Nepal
- { 84, 13, 100, 46, 44, 59, 37, 2406, 45, 43, 101, 8220, 8221, 8216, 8217, 483,5 , 0,6 , 488,7 , 488,7 , 53,10 , 63,17 , 18,7 , 25,12 , 13546,85 , 13546,85 , 13631,27 , 13546,85 , 13658,85 , 13631,27 , 7166,33 , 7199,54 , 7253,18 , 7166,33 , 7199,54 , 7253,18 , 94,9 , 90,7 , 422,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 9705,49 , 8,5 , 4,0 , 3015,6 , 2589,4 , 2, 1, 7, 7, 7 }, // Nepali/Devanagari/India
- { 85, 7, 161, 44, 160, 59, 37, 48, 8722, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 183,8 , 183,8 , 931,10 , 469,17 , 37,5 , 8,10 , 5791,48 , 13743,83 , 134,24 , 5922,59 , 13743,83 , 134,24 , 2367,35 , 2302,51 , 2353,14 , 2367,35 , 2302,51 , 2353,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {78,79,75}, 196,2 , 9754,44 , 8,5 , 4,0 , 3026,12 , 3038,5 , 2, 1, 1, 6, 7 }, // NorwegianBokmal/Latin/Norway
- { 85, 7, 203, 44, 160, 59, 37, 48, 8722, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 183,8 , 183,8 , 931,10 , 469,17 , 37,5 , 8,10 , 5791,48 , 13743,83 , 134,24 , 5922,59 , 13743,83 , 134,24 , 2367,35 , 2302,51 , 2353,14 , 2367,35 , 2302,51 , 2353,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {78,79,75}, 196,2 , 9754,44 , 8,5 , 4,0 , 3026,12 , 3043,21 , 2, 1, 1, 6, 7 }, // NorwegianBokmal/Latin/SvalbardAndJanMayenIslands
+ { 27, 7, 54, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 163,7 , 163,7 , 437,13 , 450,19 , 37,5 , 87,12 , 4500,49 , 4549,94 , 4643,39 , 4500,49 , 4682,98 , 4643,39 , 2016,28 , 2044,58 , 2102,14 , 2016,28 , 2044,58 , 2116,14 , 0,2 , 0,2 , 296,7 , 5,17 , 22,23 , {72,82,75}, 141,3 , 3200,60 , 13,5 , 4,0 , 604,8 , 612,8 , 2, 1, 1, 6, 7 }, // Croatian/Latin/Croatia
+ { 27, 7, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 163,7 , 163,7 , 469,9 , 450,19 , 37,5 , 87,12 , 4500,49 , 4549,94 , 4643,39 , 4500,49 , 4682,98 , 4643,39 , 2016,28 , 2044,58 , 2116,14 , 2016,28 , 2044,58 , 2116,14 , 0,2 , 0,2 , 296,7 , 5,17 , 22,23 , {66,65,77}, 144,2 , 3260,85 , 13,5 , 4,0 , 604,8 , 620,19 , 2, 1, 1, 6, 7 }, // Croatian/Latin/Bosnia And Herzegowina
+ { 28, 7, 57, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 185,7 , 185,7 , 156,8 , 478,17 , 55,4 , 59,9 , 4780,48 , 4828,82 , 158,27 , 4780,48 , 4910,84 , 158,27 , 2130,21 , 2151,49 , 2200,14 , 2130,21 , 2151,49 , 2200,14 , 60,4 , 57,4 , 303,5 , 5,17 , 22,23 , {67,90,75}, 146,2 , 3345,68 , 13,5 , 4,0 , 639,7 , 646,5 , 2, 0, 1, 6, 7 }, // Czech/Latin/Czech Republic
+ { 29, 7, 58, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 192,8 , 192,8 , 495,10 , 505,23 , 228,5 , 233,10 , 4994,59 , 5053,84 , 134,24 , 4994,59 , 5053,84 , 134,24 , 2214,28 , 2242,51 , 2293,14 , 2307,35 , 2242,51 , 2293,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {68,75,75}, 148,3 , 3413,42 , 13,5 , 4,0 , 651,5 , 656,7 , 2, 0, 1, 6, 7 }, // Danish/Latin/Denmark
+ { 29, 7, 86, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 192,8 , 192,8 , 495,10 , 505,23 , 228,5 , 233,10 , 4994,59 , 5053,84 , 134,24 , 4994,59 , 5053,84 , 134,24 , 2214,28 , 2242,51 , 2293,14 , 2307,35 , 2242,51 , 2293,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {68,75,75}, 148,3 , 3413,42 , 13,5 , 4,0 , 651,5 , 663,8 , 2, 0, 1, 6, 7 }, // Danish/Latin/Greenland
+ { 30, 7, 151, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 528,10 , 97,16 , 37,5 , 8,10 , 5137,59 , 5196,88 , 134,24 , 5137,59 , 5196,88 , 134,24 , 2342,21 , 2363,59 , 2422,14 , 2342,21 , 2363,59 , 2422,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3455,19 , 13,5 , 4,0 , 671,10 , 681,9 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Netherlands
+ { 30, 7, 12, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 528,10 , 97,16 , 37,5 , 8,10 , 5137,59 , 5196,88 , 134,24 , 5137,59 , 5196,88 , 134,24 , 2342,21 , 2363,59 , 2422,14 , 2342,21 , 2363,59 , 2422,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {65,87,71}, 151,4 , 3474,55 , 13,5 , 4,0 , 671,10 , 690,5 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Aruba
+ { 30, 7, 21, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 538,9 , 97,16 , 37,5 , 8,10 , 5137,59 , 5196,88 , 134,24 , 5137,59 , 5196,88 , 134,24 , 2342,21 , 2363,59 , 2422,14 , 2342,21 , 2363,59 , 2422,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3455,19 , 8,5 , 4,0 , 671,10 , 695,6 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Belgium
+ { 30, 7, 152, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 528,10 , 97,16 , 37,5 , 8,10 , 5137,59 , 5196,88 , 134,24 , 5137,59 , 5196,88 , 134,24 , 2342,21 , 2363,59 , 2422,14 , 2342,21 , 2363,59 , 2422,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {65,78,71}, 155,4 , 3529,97 , 13,5 , 4,0 , 671,10 , 701,7 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Cura Sao
+ { 30, 7, 202, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 528,10 , 97,16 , 37,5 , 8,10 , 5137,59 , 5196,88 , 134,24 , 5137,59 , 5196,88 , 134,24 , 2342,21 , 2363,59 , 2422,14 , 2342,21 , 2363,59 , 2422,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {83,82,68}, 6,1 , 3626,58 , 13,5 , 4,0 , 671,10 , 708,8 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Suriname
+ { 30, 7, 255, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 528,10 , 97,16 , 37,5 , 8,10 , 5137,59 , 5196,88 , 134,24 , 5137,59 , 5196,88 , 134,24 , 2342,21 , 2363,59 , 2422,14 , 2342,21 , 2363,59 , 2422,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3684,61 , 13,5 , 4,0 , 671,10 , 716,19 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Bonaire
+ { 30, 7, 256, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 528,10 , 97,16 , 37,5 , 8,10 , 5137,59 , 5196,88 , 134,24 , 5137,59 , 5196,88 , 134,24 , 2342,21 , 2363,59 , 2422,14 , 2342,21 , 2363,59 , 2422,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {65,78,71}, 155,4 , 3529,97 , 13,5 , 4,0 , 671,10 , 735,12 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Sint Maarten
+ { 31, 7, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 547,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3745,35 , 4,4 , 4,0 , 747,16 , 763,13 , 2, 1, 7, 6, 7 }, // English/Latin/United States
+ { 31, 3, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,83,68}, 159,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // English/Deseret/United States
+ { 31, 7, 4, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 547,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3745,35 , 4,4 , 4,0 , 776,7 , 783,14 , 2, 1, 7, 6, 7 }, // English/Latin/American Samoa
+ { 31, 7, 7, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3780,71 , 4,4 , 4,0 , 776,7 , 797,8 , 2, 1, 1, 6, 7 }, // English/Latin/Anguilla
+ { 31, 7, 9, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3780,71 , 4,4 , 4,0 , 776,7 , 805,17 , 2, 1, 7, 6, 7 }, // English/Latin/Antigua And Barbuda
+ { 31, 7, 13, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 210,9 , 210,9 , 269,6 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 2436,25 , 0,28 , 28,57 , 2436,25 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3851,59 , 4,4 , 4,0 , 822,18 , 840,9 , 2, 1, 7, 6, 7 }, // English/Latin/Australia
+ { 31, 7, 14, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3910,20 , 8,5 , 4,0 , 776,7 , 849,7 , 2, 1, 1, 6, 7 }, // English/Latin/Austria
+ { 31, 7, 16, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {66,83,68}, 6,1 , 3930,53 , 4,4 , 4,0 , 776,7 , 856,7 , 2, 1, 7, 6, 7 }, // English/Latin/Bahamas
+ { 31, 7, 19, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {66,66,68}, 6,1 , 3983,56 , 4,4 , 4,0 , 776,7 , 863,8 , 2, 1, 1, 6, 7 }, // English/Latin/Barbados
+ { 31, 7, 21, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 27,8 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3910,20 , 13,5 , 4,0 , 776,7 , 871,7 , 2, 1, 1, 6, 7 }, // English/Latin/Belgium
+ { 31, 7, 22, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 27,8 , 553,18 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {66,90,68}, 6,1 , 4039,47 , 4,4 , 4,0 , 776,7 , 878,6 , 2, 1, 7, 6, 7 }, // English/Latin/Belize
+ { 31, 7, 24, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {66,77,68}, 6,1 , 4086,53 , 4,4 , 4,0 , 776,7 , 884,7 , 2, 1, 1, 6, 7 }, // English/Latin/Bermuda
+ { 31, 7, 28, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 27,8 , 553,18 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {66,87,80}, 162,1 , 4139,50 , 4,4 , 4,0 , 776,7 , 891,8 , 2, 1, 7, 6, 7 }, // English/Latin/Botswana
+ { 31, 7, 31, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 159,3 , 3745,35 , 4,4 , 4,0 , 776,7 , 899,30 , 2, 1, 1, 6, 7 }, // English/Latin/British Indian Ocean Territory
+ { 31, 7, 35, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 547,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {66,73,70}, 163,3 , 4189,53 , 4,4 , 4,0 , 776,7 , 929,7 , 0, 0, 1, 6, 7 }, // English/Latin/Burundi
+ { 31, 7, 37, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {88,65,70}, 32,4 , 4242,83 , 4,4 , 4,0 , 776,7 , 936,8 , 0, 0, 1, 6, 7 }, // English/Latin/Cameroon
+ { 31, 7, 38, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 53,10 , 35,18 , 18,7 , 25,12 , 5284,59 , 48,86 , 134,24 , 5284,59 , 48,86 , 134,24 , 2461,35 , 28,57 , 85,14 , 2461,35 , 28,57 , 85,14 , 64,4 , 61,4 , 0,5 , 5,17 , 22,23 , {67,65,68}, 6,1 , 4325,53 , 4,4 , 4,0 , 944,16 , 960,6 , 2, 0, 7, 6, 7 }, // English/Latin/Canada
+ { 31, 7, 40, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {75,89,68}, 6,1 , 4378,71 , 4,4 , 4,0 , 776,7 , 966,14 , 2, 1, 1, 6, 7 }, // English/Latin/Cayman Islands
+ { 31, 7, 45, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3851,59 , 4,4 , 4,0 , 776,7 , 980,16 , 2, 1, 1, 6, 7 }, // English/Latin/Christmas Island
+ { 31, 7, 46, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3851,59 , 4,4 , 4,0 , 776,7 , 996,23 , 2, 1, 1, 6, 7 }, // English/Latin/Cocos Islands
+ { 31, 7, 51, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {78,90,68}, 6,1 , 4449,62 , 4,4 , 4,0 , 776,7 , 1019,12 , 2, 1, 1, 6, 7 }, // English/Latin/Cook Islands
+ { 31, 7, 56, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3910,20 , 4,4 , 4,0 , 776,7 , 1031,6 , 2, 1, 1, 6, 7 }, // English/Latin/Cyprus
+ { 31, 7, 58, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 228,5 , 233,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {68,75,75}, 148,3 , 4511,44 , 13,5 , 4,0 , 776,7 , 1037,7 , 2, 0, 1, 6, 7 }, // English/Latin/Denmark
+ { 31, 7, 60, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3780,71 , 4,4 , 4,0 , 776,7 , 1044,8 , 2, 1, 7, 6, 7 }, // English/Latin/Dominica
+ { 31, 7, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {69,82,78}, 41,3 , 4555,50 , 4,4 , 4,0 , 776,7 , 1052,7 , 2, 1, 1, 6, 7 }, // English/Latin/Eritrea
+ { 31, 7, 70, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {70,75,80}, 119,1 , 4605,74 , 4,4 , 4,0 , 776,7 , 1059,16 , 2, 1, 1, 6, 7 }, // English/Latin/Falkland Islands
+ { 31, 7, 72, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {70,74,68}, 6,1 , 4679,47 , 4,4 , 4,0 , 776,7 , 1075,4 , 2, 1, 1, 6, 7 }, // English/Latin/Fiji
+ { 31, 7, 73, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 243,4 , 247,9 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3910,20 , 13,5 , 4,0 , 776,7 , 1079,7 , 2, 1, 1, 6, 7 }, // English/Latin/Finland
+ { 31, 7, 75, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {71,66,80}, 119,1 , 4726,32 , 4,4 , 4,0 , 776,7 , 1086,8 , 2, 1, 1, 6, 7 }, // English/Latin/Guernsey
+ { 31, 7, 80, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {71,77,68}, 166,1 , 4758,50 , 4,4 , 4,0 , 776,7 , 1094,6 , 2, 1, 1, 6, 7 }, // English/Latin/Gambia
+ { 31, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3910,20 , 13,5 , 4,0 , 776,7 , 1100,7 , 2, 1, 1, 6, 7 }, // English/Latin/Germany
+ { 31, 7, 83, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {71,72,83}, 167,3 , 4808,47 , 4,4 , 4,0 , 776,7 , 1107,5 , 2, 1, 1, 6, 7 }, // English/Latin/Ghana
+ { 31, 7, 84, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {71,73,80}, 119,1 , 4855,53 , 4,4 , 4,0 , 776,7 , 1112,9 , 2, 1, 1, 6, 7 }, // English/Latin/Gibraltar
+ { 31, 7, 87, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3780,71 , 4,4 , 4,0 , 776,7 , 1121,7 , 2, 1, 1, 6, 7 }, // English/Latin/Grenada
+ { 31, 7, 89, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 547,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3745,35 , 4,4 , 4,0 , 776,7 , 1128,4 , 2, 1, 7, 6, 7 }, // English/Latin/Guam
+ { 31, 7, 93, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {71,89,68}, 6,1 , 4908,56 , 4,4 , 4,0 , 776,7 , 1132,6 , 2, 0, 1, 6, 7 }, // English/Latin/Guyana
+ { 31, 7, 97, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 415,8 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {72,75,68}, 134,3 , 4964,56 , 4,4 , 4,0 , 776,7 , 1138,19 , 2, 1, 7, 6, 7 }, // English/Latin/Hong Kong
+ { 31, 7, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 27,8 , 192,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {73,78,82}, 121,1 , 5020,44 , 8,5 , 4,0 , 776,7 , 1157,5 , 2, 1, 7, 7, 7 }, // English/Latin/India
+ { 31, 7, 104, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 97,16 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 64,4 , 61,4 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3910,20 , 4,4 , 4,0 , 776,7 , 1162,7 , 2, 1, 1, 6, 7 }, // English/Latin/Ireland
+ { 31, 7, 105, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 55,4 , 59,9 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {73,76,83}, 49,1 , 5064,62 , 4,4 , 4,0 , 776,7 , 1169,6 , 2, 1, 7, 5, 6 }, // English/Latin/Israel
+ { 31, 7, 107, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 269,6 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {74,77,68}, 6,1 , 5126,53 , 4,4 , 4,0 , 776,7 , 1175,7 , 2, 1, 7, 6, 7 }, // English/Latin/Jamaica
+ { 31, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {75,69,83}, 2,3 , 5179,53 , 4,4 , 4,0 , 776,7 , 1182,5 , 2, 1, 7, 6, 7 }, // English/Latin/Kenya
+ { 31, 7, 112, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3851,59 , 4,4 , 4,0 , 776,7 , 1187,8 , 2, 1, 1, 6, 7 }, // English/Latin/Kiribati
+ { 31, 7, 120, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {90,65,82}, 5,1 , 5232,61 , 4,4 , 4,0 , 776,7 , 1195,7 , 2, 1, 1, 6, 7 }, // English/Latin/Lesotho
+ { 31, 7, 121, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {76,82,68}, 6,1 , 5293,53 , 4,4 , 4,0 , 776,7 , 1202,7 , 2, 1, 1, 6, 7 }, // English/Latin/Liberia
+ { 31, 7, 126, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {77,79,80}, 137,4 , 5346,53 , 4,4 , 4,0 , 776,7 , 1209,15 , 2, 1, 7, 6, 7 }, // English/Latin/Macau
+ { 31, 7, 128, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {77,71,65}, 170,2 , 5399,54 , 4,4 , 4,0 , 776,7 , 1224,10 , 0, 0, 1, 6, 7 }, // English/Latin/Madagascar
+ { 31, 7, 129, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {77,87,75}, 172,2 , 5453,53 , 4,4 , 4,0 , 776,7 , 1234,6 , 2, 1, 1, 6, 7 }, // English/Latin/Malawi
+ { 31, 7, 130, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {77,89,82}, 174,2 , 5506,59 , 4,4 , 4,0 , 776,7 , 1240,8 , 2, 1, 1, 6, 7 }, // English/Latin/Malaysia
+ { 31, 7, 133, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3910,20 , 4,4 , 4,0 , 776,7 , 1248,5 , 2, 1, 7, 6, 7 }, // English/Latin/Malta
+ { 31, 7, 134, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 547,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3745,35 , 4,4 , 4,0 , 776,7 , 1253,16 , 2, 1, 7, 6, 7 }, // English/Latin/Marshall Islands
+ { 31, 7, 137, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {77,85,82}, 176,2 , 5565,53 , 4,4 , 4,0 , 776,7 , 1269,9 , 2, 0, 1, 6, 7 }, // English/Latin/Mauritius
+ { 31, 7, 140, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 159,3 , 3745,35 , 4,4 , 4,0 , 776,7 , 1278,10 , 2, 1, 1, 6, 7 }, // English/Latin/Micronesia
+ { 31, 7, 144, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3780,71 , 4,4 , 4,0 , 776,7 , 1288,10 , 2, 1, 1, 6, 7 }, // English/Latin/Montserrat
+ { 31, 7, 148, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {78,65,68}, 6,1 , 5618,53 , 4,4 , 4,0 , 776,7 , 1298,7 , 2, 1, 1, 6, 7 }, // English/Latin/Namibia
+ { 31, 7, 149, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3851,59 , 4,4 , 4,0 , 776,7 , 1305,5 , 2, 1, 1, 6, 7 }, // English/Latin/Nauru
+ { 31, 7, 151, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3910,20 , 8,5 , 23,6 , 776,7 , 1310,11 , 2, 1, 1, 6, 7 }, // English/Latin/Netherlands
+ { 31, 7, 154, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 571,7 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {78,90,68}, 6,1 , 4449,62 , 4,4 , 4,0 , 776,7 , 1321,11 , 2, 1, 1, 6, 7 }, // English/Latin/New Zealand
+ { 31, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {78,71,78}, 178,1 , 5671,50 , 4,4 , 4,0 , 776,7 , 1332,7 , 2, 1, 1, 6, 7 }, // English/Latin/Nigeria
+ { 31, 7, 158, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {78,90,68}, 6,1 , 4449,62 , 4,4 , 4,0 , 776,7 , 1339,4 , 2, 1, 1, 6, 7 }, // English/Latin/Niue
+ { 31, 7, 159, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3851,59 , 4,4 , 4,0 , 776,7 , 1343,14 , 2, 1, 1, 6, 7 }, // English/Latin/Norfolk Island
+ { 31, 7, 160, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 547,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3745,35 , 4,4 , 4,0 , 776,7 , 1357,24 , 2, 1, 1, 6, 7 }, // English/Latin/Northern Mariana Islands
+ { 31, 7, 163, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {80,75,82}, 176,2 , 5721,53 , 4,4 , 4,0 , 776,7 , 1381,8 , 2, 0, 7, 6, 7 }, // English/Latin/Pakistan
+ { 31, 7, 164, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 159,3 , 3745,35 , 4,4 , 4,0 , 776,7 , 1389,5 , 2, 1, 1, 6, 7 }, // English/Latin/Palau
+ { 31, 7, 167, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {80,71,75}, 131,1 , 5774,73 , 4,4 , 4,0 , 776,7 , 1394,16 , 2, 1, 1, 6, 7 }, // English/Latin/Papua New Guinea
+ { 31, 7, 170, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {80,72,80}, 179,1 , 5847,53 , 4,4 , 4,0 , 776,7 , 1410,11 , 2, 1, 7, 6, 7 }, // English/Latin/Philippines
+ { 31, 7, 171, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {78,90,68}, 6,1 , 4449,62 , 4,4 , 4,0 , 776,7 , 1421,16 , 2, 1, 1, 6, 7 }, // English/Latin/Pitcairn
+ { 31, 7, 174, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 547,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3745,35 , 4,4 , 4,0 , 776,7 , 1437,11 , 2, 1, 7, 6, 7 }, // English/Latin/Puerto Rico
+ { 31, 7, 179, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {82,87,70}, 180,2 , 5900,47 , 4,4 , 4,0 , 776,7 , 1448,6 , 0, 0, 1, 6, 7 }, // English/Latin/Rwanda
+ { 31, 7, 180, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3780,71 , 4,4 , 4,0 , 776,7 , 1454,17 , 2, 1, 1, 6, 7 }, // English/Latin/Saint Kitts And Nevis
+ { 31, 7, 181, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3780,71 , 4,4 , 4,0 , 776,7 , 1471,9 , 2, 1, 1, 6, 7 }, // English/Latin/Saint Lucia
+ { 31, 7, 182, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3780,71 , 4,4 , 4,0 , 776,7 , 1480,24 , 2, 1, 1, 6, 7 }, // English/Latin/Saint Vincent And The Grenadines
+ { 31, 7, 183, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {87,83,84}, 182,3 , 5947,40 , 4,4 , 4,0 , 776,7 , 1504,5 , 2, 1, 7, 6, 7 }, // English/Latin/Samoa
+ { 31, 7, 188, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {83,67,82}, 185,2 , 5987,59 , 4,4 , 4,0 , 776,7 , 1509,10 , 2, 1, 1, 6, 7 }, // English/Latin/Seychelles
+ { 31, 7, 189, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {83,76,76}, 187,2 , 6046,68 , 4,4 , 4,0 , 776,7 , 1519,12 , 0, 0, 1, 6, 7 }, // English/Latin/Sierra Leone
+ { 31, 7, 190, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 269,6 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {83,71,68}, 6,1 , 6114,56 , 4,4 , 4,0 , 776,7 , 1531,9 , 2, 1, 7, 6, 7 }, // English/Latin/Singapore
+ { 31, 7, 192, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3910,20 , 13,5 , 29,7 , 776,7 , 1540,8 , 2, 1, 1, 6, 7 }, // English/Latin/Slovenia
+ { 31, 7, 193, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {83,66,68}, 6,1 , 6170,74 , 4,4 , 4,0 , 776,7 , 1548,15 , 2, 1, 1, 6, 7 }, // English/Latin/Solomon Islands
+ { 31, 7, 195, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 578,10 , 553,18 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {90,65,82}, 5,1 , 5232,61 , 4,4 , 4,0 , 776,7 , 1563,12 , 2, 1, 7, 6, 7 }, // English/Latin/South Africa
+ { 31, 7, 199, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {83,72,80}, 119,1 , 6244,56 , 4,4 , 4,0 , 776,7 , 1575,10 , 2, 1, 1, 6, 7 }, // English/Latin/Saint Helena
+ { 31, 7, 201, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {83,68,71}, 0,0 , 6300,50 , 4,4 , 4,0 , 776,7 , 1585,5 , 2, 1, 6, 5, 6 }, // English/Latin/Sudan
+ { 31, 7, 204, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {83,90,76}, 189,1 , 6350,53 , 4,4 , 4,0 , 776,7 , 1590,9 , 2, 1, 1, 6, 7 }, // English/Latin/Swaziland
+ { 31, 7, 205, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 53,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {83,69,75}, 190,2 , 6403,47 , 13,5 , 4,0 , 776,7 , 1599,6 , 2, 0, 1, 6, 7 }, // English/Latin/Sweden
+ { 31, 7, 206, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {67,72,70}, 0,0 , 6450,41 , 8,5 , 36,5 , 776,7 , 1605,11 , 2, 0, 1, 6, 7 }, // English/Latin/Switzerland
+ { 31, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {84,90,83}, 192,3 , 6491,62 , 4,4 , 4,0 , 776,7 , 1616,8 , 2, 0, 1, 6, 7 }, // English/Latin/Tanzania
+ { 31, 7, 213, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {78,90,68}, 6,1 , 4449,62 , 4,4 , 4,0 , 776,7 , 1624,7 , 2, 1, 1, 6, 7 }, // English/Latin/Tokelau
+ { 31, 7, 214, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {84,79,80}, 195,2 , 6553,49 , 4,4 , 4,0 , 776,7 , 1631,5 , 2, 1, 1, 6, 7 }, // English/Latin/Tonga
+ { 31, 7, 215, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {84,84,68}, 6,1 , 6602,80 , 4,4 , 4,0 , 776,7 , 1636,17 , 2, 1, 7, 6, 7 }, // English/Latin/Trinidad And Tobago
+ { 31, 7, 219, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 159,3 , 3745,35 , 4,4 , 4,0 , 776,7 , 1653,22 , 2, 1, 1, 6, 7 }, // English/Latin/Turks And Caicos Islands
+ { 31, 7, 220, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3851,59 , 4,4 , 4,0 , 776,7 , 1675,6 , 2, 1, 1, 6, 7 }, // English/Latin/Tuvalu
+ { 31, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {85,71,88}, 197,3 , 6682,56 , 4,4 , 4,0 , 776,7 , 1681,6 , 0, 0, 1, 6, 7 }, // English/Latin/Uganda
+ { 31, 7, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 210,9 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {71,66,80}, 119,1 , 6738,47 , 4,4 , 4,0 , 1687,15 , 1702,14 , 2, 1, 1, 6, 7 }, // English/Latin/United Kingdom
+ { 31, 7, 226, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 547,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3745,35 , 4,4 , 4,0 , 776,7 , 1716,21 , 2, 1, 7, 6, 7 }, // English/Latin/United States Minor Outlying Islands
+ { 31, 7, 229, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {86,85,86}, 200,2 , 6785,44 , 4,4 , 4,0 , 776,7 , 1737,7 , 0, 0, 1, 6, 7 }, // English/Latin/Vanuatu
+ { 31, 7, 233, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 159,3 , 3745,35 , 4,4 , 4,0 , 776,7 , 1744,22 , 2, 1, 1, 6, 7 }, // English/Latin/British Virgin Islands
+ { 31, 7, 234, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 547,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3745,35 , 4,4 , 4,0 , 776,7 , 1766,19 , 2, 1, 7, 6, 7 }, // English/Latin/United States Virgin Islands
+ { 31, 7, 239, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {90,77,87}, 131,1 , 6829,50 , 4,4 , 4,0 , 776,7 , 1785,6 , 2, 1, 1, 6, 7 }, // English/Latin/Zambia
+ { 31, 7, 240, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 415,8 , 553,18 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 159,3 , 3745,35 , 4,4 , 4,0 , 776,7 , 1791,8 , 2, 1, 7, 6, 7 }, // English/Latin/Zimbabwe
+ { 31, 7, 249, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 159,3 , 3745,35 , 4,4 , 4,0 , 776,7 , 1799,12 , 2, 1, 1, 6, 7 }, // English/Latin/Diego Garcia
+ { 31, 7, 251, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {71,66,80}, 119,1 , 4726,32 , 4,4 , 4,0 , 776,7 , 1811,11 , 2, 1, 1, 6, 7 }, // English/Latin/Isle Of Man
+ { 31, 7, 252, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {71,66,80}, 119,1 , 4726,32 , 4,4 , 4,0 , 776,7 , 1822,6 , 2, 1, 1, 6, 7 }, // English/Latin/Jersey
+ { 31, 7, 254, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {83,83,80}, 119,1 , 6879,68 , 4,4 , 4,0 , 776,7 , 1828,11 , 2, 1, 1, 6, 7 }, // English/Latin/South Sudan
+ { 31, 7, 256, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {65,78,71}, 155,4 , 6947,95 , 4,4 , 4,0 , 776,7 , 1839,12 , 2, 1, 1, 6, 7 }, // English/Latin/Sint Maarten
+ { 31, 7, 260, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {0,0,0}, 0,0 , 2586,0 , 4,4 , 4,0 , 776,7 , 1851,5 , 2, 1, 1, 6, 7 }, // English/Latin/World
+ { 31, 7, 261, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 119,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {0,0,0}, 0,0 , 2586,0 , 13,5 , 4,0 , 776,7 , 1856,6 , 2, 1, 1, 6, 7 }, // English/Latin/Europe
+ { 32, 7, 260, 44, 160, 59, 37, 48, 8722, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 219,9 , 219,9 , 588,8 , 596,26 , 37,5 , 256,25 , 5343,48 , 5391,91 , 134,24 , 5343,48 , 5391,91 , 134,24 , 2496,21 , 2517,51 , 2568,14 , 2496,21 , 2517,51 , 2568,14 , 70,3 , 67,3 , 308,6 , 5,17 , 22,23 , {0,0,0}, 0,0 , 2586,0 , 41,6 , 4,0 , 1862,9 , 0,0 , 2, 1, 1, 6, 7 }, // Esperanto/Latin/World
+ { 33, 7, 68, 44, 160, 59, 37, 48, 8722, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 228,8 , 228,8 , 156,8 , 622,18 , 37,5 , 8,10 , 5482,59 , 5541,91 , 5632,24 , 5482,59 , 5541,91 , 5632,24 , 2582,14 , 2596,63 , 2582,14 , 2582,14 , 2596,63 , 2582,14 , 0,2 , 0,2 , 314,6 , 5,17 , 22,23 , {69,85,82}, 14,1 , 7042,20 , 13,5 , 4,0 , 1871,5 , 1876,5 , 2, 1, 1, 6, 7 }, // Estonian/Latin/Estonia
+ { 34, 7, 71, 44, 46, 59, 37, 48, 8722, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 192,8 , 192,8 , 156,8 , 622,18 , 37,5 , 8,10 , 5656,48 , 5704,83 , 134,24 , 5787,59 , 5704,83 , 134,24 , 2659,28 , 2687,74 , 2761,14 , 2775,35 , 2687,74 , 2761,14 , 0,2 , 0,2 , 320,3 , 323,17 , 22,23 , {68,75,75}, 190,2 , 7062,43 , 13,5 , 4,0 , 1881,8 , 1889,7 , 2, 0, 1, 6, 7 }, // Faroese/Latin/Faroe Islands
+ { 34, 7, 58, 44, 46, 59, 37, 48, 8722, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 192,8 , 192,8 , 156,8 , 622,18 , 37,5 , 8,10 , 5656,48 , 5704,83 , 134,24 , 5787,59 , 5704,83 , 134,24 , 2659,28 , 2687,74 , 2761,14 , 2775,35 , 2687,74 , 2761,14 , 0,2 , 0,2 , 320,3 , 323,17 , 22,23 , {68,75,75}, 148,3 , 7062,43 , 13,5 , 4,0 , 1881,8 , 656,7 , 2, 0, 1, 6, 7 }, // Faroese/Latin/Denmark
+ { 36, 7, 73, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 228,8 , 228,8 , 640,8 , 478,17 , 243,4 , 247,9 , 5846,69 , 5915,105 , 6020,24 , 6044,93 , 6137,129 , 6020,24 , 2810,21 , 2831,67 , 2898,14 , 2810,21 , 2912,81 , 2898,14 , 73,3 , 70,3 , 340,5 , 345,17 , 362,23 , {69,85,82}, 14,1 , 7105,20 , 13,5 , 4,0 , 1896,5 , 1901,5 , 2, 1, 1, 6, 7 }, // Finnish/Latin/Finland
+ { 37, 7, 74, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 1906,8 , 1914,6 , 2, 1, 1, 6, 7 }, // French/Latin/France
+ { 37, 7, 3, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 18,7 , 25,12 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {68,90,68}, 202,2 , 7125,51 , 13,5 , 4,0 , 1906,8 , 1920,7 , 2, 1, 6, 5, 6 }, // French/Latin/Algeria
+ { 37, 7, 21, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 571,7 , 97,16 , 37,5 , 281,23 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 1906,8 , 1927,8 , 2, 1, 1, 6, 7 }, // French/Latin/Belgium
+ { 37, 7, 23, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {88,79,70}, 204,3 , 7176,59 , 13,5 , 4,0 , 1906,8 , 1935,5 , 0, 0, 1, 6, 7 }, // French/Latin/Benin
+ { 37, 7, 34, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {88,79,70}, 204,3 , 7176,59 , 13,5 , 4,0 , 1906,8 , 1940,12 , 0, 0, 1, 6, 7 }, // French/Latin/Burkina Faso
+ { 37, 7, 35, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {66,73,70}, 163,3 , 7235,53 , 13,5 , 4,0 , 1906,8 , 929,7 , 0, 0, 1, 6, 7 }, // French/Latin/Burundi
+ { 37, 7, 37, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 76,5 , 73,4 , 385,6 , 391,17 , 408,23 , {88,65,70}, 32,4 , 7288,56 , 13,5 , 4,0 , 1906,8 , 1952,8 , 0, 0, 1, 6, 7 }, // French/Latin/Cameroon
+ { 37, 7, 38, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8221, 8220, 0,6 , 0,6 , 236,8 , 236,8 , 588,8 , 97,16 , 304,9 , 313,24 , 6414,64 , 6329,85 , 134,24 , 6414,64 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 64,4 , 61,4 , 385,6 , 391,17 , 408,23 , {67,65,68}, 6,1 , 7344,54 , 47,6 , 4,0 , 1960,17 , 960,6 , 2, 0, 7, 6, 7 }, // French/Latin/Canada
+ { 37, 7, 41, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {88,65,70}, 32,4 , 7288,56 , 13,5 , 4,0 , 1906,8 , 1977,25 , 0, 0, 1, 6, 7 }, // French/Latin/Central African Republic
+ { 37, 7, 42, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 18,7 , 25,12 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {88,65,70}, 32,4 , 7288,56 , 13,5 , 4,0 , 1906,8 , 2002,5 , 0, 0, 1, 6, 7 }, // French/Latin/Chad
+ { 37, 7, 48, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {75,77,70}, 36,2 , 7398,51 , 13,5 , 4,0 , 1906,8 , 2007,7 , 0, 0, 1, 6, 7 }, // French/Latin/Comoros
+ { 37, 7, 49, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {67,68,70}, 207,2 , 7449,53 , 13,5 , 4,0 , 1906,8 , 2014,14 , 2, 1, 1, 6, 7 }, // French/Latin/Congo Kinshasa
+ { 37, 7, 50, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {88,65,70}, 32,4 , 7288,56 , 13,5 , 4,0 , 1906,8 , 2028,17 , 0, 0, 1, 6, 7 }, // French/Latin/Congo Brazzaville
+ { 37, 7, 53, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {88,79,70}, 204,3 , 7176,59 , 13,5 , 4,0 , 1906,8 , 2045,13 , 0, 0, 1, 6, 7 }, // French/Latin/Ivory Coast
+ { 37, 7, 59, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 18,7 , 25,12 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {68,74,70}, 38,3 , 7502,57 , 13,5 , 4,0 , 1906,8 , 2058,8 , 0, 0, 6, 6, 7 }, // French/Latin/Djibouti
+ { 37, 7, 66, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {88,65,70}, 32,4 , 7288,56 , 13,5 , 4,0 , 1906,8 , 2066,18 , 0, 0, 1, 6, 7 }, // French/Latin/Equatorial Guinea
+ { 37, 7, 76, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 1906,8 , 2084,16 , 2, 1, 1, 6, 7 }, // French/Latin/French Guiana
+ { 37, 7, 77, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {88,80,70}, 209,4 , 7559,35 , 13,5 , 4,0 , 1906,8 , 2100,19 , 0, 0, 1, 6, 7 }, // French/Latin/French Polynesia
+ { 37, 7, 79, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {88,65,70}, 32,4 , 7288,56 , 13,5 , 4,0 , 1906,8 , 2119,5 , 0, 0, 1, 6, 7 }, // French/Latin/Gabon
+ { 37, 7, 88, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 1906,8 , 2124,10 , 2, 1, 1, 6, 7 }, // French/Latin/Guadeloupe
+ { 37, 7, 91, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {71,78,70}, 213,2 , 7594,48 , 13,5 , 4,0 , 1906,8 , 2134,6 , 0, 0, 1, 6, 7 }, // French/Latin/Guinea
+ { 37, 7, 94, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {72,84,71}, 215,1 , 7642,57 , 13,5 , 4,0 , 1906,8 , 2140,5 , 2, 1, 1, 6, 7 }, // French/Latin/Haiti
+ { 37, 7, 125, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 1906,8 , 2145,10 , 2, 1, 1, 6, 7 }, // French/Latin/Luxembourg
+ { 37, 7, 128, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {77,71,65}, 170,2 , 7699,54 , 13,5 , 4,0 , 1906,8 , 1224,10 , 0, 0, 1, 6, 7 }, // French/Latin/Madagascar
+ { 37, 7, 132, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {88,79,70}, 204,3 , 7176,59 , 13,5 , 4,0 , 1906,8 , 2155,4 , 0, 0, 1, 6, 7 }, // French/Latin/Mali
+ { 37, 7, 135, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 1906,8 , 2159,10 , 2, 1, 1, 6, 7 }, // French/Latin/Martinique
+ { 37, 7, 136, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 18,7 , 25,12 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {77,82,85}, 216,2 , 7753,66 , 13,5 , 4,0 , 1906,8 , 2169,10 , 2, 1, 1, 6, 7 }, // French/Latin/Mauritania
+ { 37, 7, 137, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {77,85,82}, 176,2 , 7819,63 , 13,5 , 4,0 , 1906,8 , 2179,7 , 2, 0, 1, 6, 7 }, // French/Latin/Mauritius
+ { 37, 7, 138, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 1906,8 , 2186,7 , 2, 1, 1, 6, 7 }, // French/Latin/Mayotte
+ { 37, 7, 142, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 1906,8 , 2193,6 , 2, 1, 1, 6, 7 }, // French/Latin/Monaco
+ { 37, 7, 145, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6478,61 , 6329,85 , 134,24 , 6478,61 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 64,4 , 61,4 , 385,6 , 391,17 , 408,23 , {77,65,68}, 218,3 , 7882,54 , 13,5 , 4,0 , 1906,8 , 2199,5 , 2, 1, 1, 6, 7 }, // French/Latin/Morocco
+ { 37, 7, 153, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {88,80,70}, 209,4 , 7559,35 , 13,5 , 4,0 , 1906,8 , 2204,18 , 0, 0, 1, 6, 7 }, // French/Latin/New Caledonia
+ { 37, 7, 156, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {88,79,70}, 204,3 , 7176,59 , 13,5 , 4,0 , 1906,8 , 2222,5 , 0, 0, 1, 6, 7 }, // French/Latin/Niger
+ { 37, 7, 176, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 1906,8 , 2227,10 , 2, 1, 1, 6, 7 }, // French/Latin/Reunion
+ { 37, 7, 179, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {82,87,70}, 180,2 , 7936,50 , 13,5 , 4,0 , 1906,8 , 1448,6 , 0, 0, 1, 6, 7 }, // French/Latin/Rwanda
+ { 37, 7, 187, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {88,79,70}, 204,3 , 7176,59 , 13,5 , 4,0 , 1906,8 , 2237,7 , 0, 0, 1, 6, 7 }, // French/Latin/Senegal
+ { 37, 7, 188, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {83,67,82}, 185,2 , 7986,71 , 13,5 , 4,0 , 1906,8 , 1509,10 , 2, 1, 1, 6, 7 }, // French/Latin/Seychelles
+ { 37, 7, 200, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 1906,8 , 2244,24 , 2, 1, 1, 6, 7 }, // French/Latin/Saint Pierre And Miquelon
+ { 37, 7, 206, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 236,8 , 236,8 , 156,8 , 10,17 , 37,5 , 337,14 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {67,72,70}, 221,3 , 8057,45 , 13,5 , 53,6 , 2268,15 , 2283,6 , 2, 0, 1, 6, 7 }, // French/Latin/Switzerland
+ { 37, 7, 207, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 18,7 , 25,12 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {83,89,80}, 224,2 , 8102,51 , 13,5 , 4,0 , 1906,8 , 2289,5 , 0, 0, 6, 5, 6 }, // French/Latin/Syria
+ { 37, 7, 212, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {88,79,70}, 204,3 , 7176,59 , 13,5 , 4,0 , 1906,8 , 2294,4 , 0, 0, 1, 6, 7 }, // French/Latin/Togo
+ { 37, 7, 216, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 18,7 , 25,12 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {84,78,68}, 226,2 , 8153,51 , 13,5 , 4,0 , 1906,8 , 2298,7 , 3, 0, 1, 6, 7 }, // French/Latin/Tunisia
+ { 37, 7, 229, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 18,7 , 25,12 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {86,85,86}, 200,2 , 8204,51 , 13,5 , 4,0 , 1906,8 , 1737,7 , 0, 0, 1, 6, 7 }, // French/Latin/Vanuatu
+ { 37, 7, 235, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {88,80,70}, 209,4 , 7559,35 , 13,5 , 4,0 , 1906,8 , 2305,16 , 0, 0, 1, 6, 7 }, // French/Latin/Wallis And Futuna Islands
+ { 37, 7, 244, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 1906,8 , 2321,16 , 2, 1, 1, 6, 7 }, // French/Latin/Saint Barthelemy
+ { 37, 7, 245, 44, 8239, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 119,10 , 97,16 , 37,5 , 8,10 , 6266,63 , 6329,85 , 134,24 , 6266,63 , 6329,85 , 134,24 , 2993,35 , 3028,52 , 3080,14 , 2993,35 , 3028,52 , 3080,14 , 0,2 , 0,2 , 385,6 , 391,17 , 408,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 1906,8 , 2337,12 , 2, 1, 1, 6, 7 }, // French/Latin/Saint Martin
+ { 38, 7, 151, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 6,8 , 6,8 , 339,8 , 97,16 , 37,5 , 8,10 , 6539,48 , 6587,95 , 134,24 , 6539,48 , 6587,95 , 134,24 , 3094,21 , 3115,54 , 85,14 , 3094,21 , 3115,54 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3455,19 , 8,5 , 59,6 , 2349,5 , 2354,8 , 2, 1, 1, 6, 7 }, // Western Frisian/Latin/Netherlands
+ { 39, 7, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 244,10 , 244,10 , 119,10 , 648,21 , 37,5 , 8,10 , 6682,61 , 6743,142 , 6885,24 , 6682,61 , 6909,167 , 6885,24 , 3169,28 , 3197,69 , 3266,14 , 3169,28 , 3197,69 , 3266,14 , 81,1 , 77,1 , 431,6 , 5,17 , 22,23 , {71,66,80}, 119,1 , 8255,86 , 4,4 , 4,0 , 2362,8 , 2370,22 , 2, 1, 1, 6, 7 }, // Gaelic/Latin/United Kingdom
+ { 40, 7, 197, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 669,27 , 37,5 , 8,10 , 7076,60 , 7136,87 , 7223,24 , 7247,60 , 7307,87 , 7394,36 , 3280,35 , 3315,49 , 3364,14 , 3378,35 , 3413,49 , 3462,21 , 64,4 , 61,4 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3910,20 , 13,5 , 4,0 , 2392,6 , 2398,6 , 2, 1, 1, 6, 7 }, // Galician/Latin/Spain
+ { 41, 15, 81, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 171, 187, 0,6 , 0,6 , 261,8 , 261,8 , 156,8 , 696,19 , 37,5 , 8,10 , 7430,48 , 7478,99 , 7577,24 , 7430,48 , 7478,99 , 7577,24 , 3483,28 , 3511,62 , 3573,14 , 3483,28 , 3511,62 , 3573,14 , 0,2 , 0,2 , 437,5 , 442,37 , 22,23 , {71,69,76}, 228,1 , 8341,43 , 13,5 , 4,0 , 2404,7 , 2411,10 , 2, 1, 1, 6, 7 }, // Georgian/Georgian/Georgia
+ { 42, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 269,9 , 269,9 , 156,8 , 622,18 , 37,5 , 8,10 , 7601,48 , 7649,83 , 134,24 , 7732,60 , 7649,83 , 134,24 , 3587,21 , 3608,60 , 3668,14 , 3682,28 , 3608,60 , 3668,14 , 0,2 , 0,2 , 479,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8384,19 , 13,5 , 4,0 , 2421,7 , 2428,11 , 2, 1, 1, 6, 7 }, // German/Latin/Germany
+ { 42, 7, 14, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 269,9 , 269,9 , 156,8 , 622,18 , 37,5 , 8,10 , 7792,48 , 7840,83 , 134,24 , 7923,59 , 7840,83 , 134,24 , 3587,21 , 3608,60 , 3668,14 , 3682,28 , 3608,60 , 3668,14 , 0,2 , 0,2 , 479,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8384,19 , 8,5 , 4,0 , 2439,24 , 2463,10 , 2, 1, 1, 6, 7 }, // German/Latin/Austria
+ { 42, 7, 21, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 269,9 , 269,9 , 156,8 , 622,18 , 37,5 , 8,10 , 7601,48 , 7649,83 , 134,24 , 7732,60 , 7649,83 , 134,24 , 3587,21 , 3608,60 , 3668,14 , 3682,28 , 3608,60 , 3668,14 , 0,2 , 0,2 , 479,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8384,19 , 13,5 , 4,0 , 2421,7 , 2473,7 , 2, 1, 1, 6, 7 }, // German/Latin/Belgium
+ { 42, 7, 106, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 269,9 , 269,9 , 156,8 , 622,18 , 37,5 , 8,10 , 7792,48 , 7840,83 , 134,24 , 7923,59 , 7840,83 , 134,24 , 3587,21 , 3608,60 , 3668,14 , 3682,28 , 3608,60 , 3668,14 , 0,2 , 0,2 , 479,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8384,19 , 13,5 , 4,0 , 2421,7 , 2480,7 , 2, 1, 1, 6, 7 }, // German/Latin/Italy
+ { 42, 7, 123, 46, 8217, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 269,9 , 269,9 , 156,8 , 622,18 , 37,5 , 8,10 , 7601,48 , 7649,83 , 134,24 , 7732,60 , 7649,83 , 134,24 , 3587,21 , 3608,60 , 3668,14 , 3682,28 , 3608,60 , 3668,14 , 0,2 , 0,2 , 479,5 , 5,17 , 22,23 , {67,72,70}, 221,3 , 8403,58 , 8,5 , 4,0 , 2421,7 , 2487,13 , 2, 0, 1, 6, 7 }, // German/Latin/Liechtenstein
+ { 42, 7, 125, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 269,9 , 269,9 , 156,8 , 622,18 , 37,5 , 8,10 , 7601,48 , 7649,83 , 134,24 , 7732,60 , 7649,83 , 134,24 , 3587,21 , 3608,60 , 3668,14 , 3682,28 , 3608,60 , 3668,14 , 0,2 , 0,2 , 479,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8384,19 , 13,5 , 4,0 , 2421,7 , 2500,9 , 2, 1, 1, 6, 7 }, // German/Latin/Luxembourg
+ { 42, 7, 206, 46, 8217, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 269,9 , 269,9 , 156,8 , 622,18 , 37,5 , 8,10 , 7601,48 , 7649,83 , 134,24 , 7732,60 , 7649,83 , 134,24 , 3587,21 , 3608,60 , 3668,14 , 3682,28 , 3608,60 , 3668,14 , 0,2 , 0,2 , 479,5 , 5,17 , 22,23 , {67,72,70}, 221,3 , 8403,58 , 8,5 , 36,5 , 2509,21 , 2530,7 , 2, 0, 1, 6, 7 }, // German/Latin/Switzerland
+ { 43, 16, 85, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 278,9 , 278,9 , 269,6 , 10,17 , 18,7 , 25,12 , 7982,50 , 8032,115 , 8147,24 , 8171,50 , 8221,115 , 8147,24 , 3710,28 , 3738,55 , 3793,14 , 3710,28 , 3738,55 , 3793,14 , 82,4 , 78,4 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8461,19 , 13,5 , 4,0 , 2537,8 , 2545,6 , 2, 1, 1, 6, 7 }, // Greek/Greek/Greece
+ { 43, 16, 56, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 278,9 , 278,9 , 269,6 , 10,17 , 18,7 , 25,12 , 7982,50 , 8032,115 , 8147,24 , 8171,50 , 8221,115 , 8147,24 , 3710,28 , 3738,55 , 3793,14 , 3710,28 , 3738,55 , 3793,14 , 82,4 , 78,4 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8461,19 , 13,5 , 4,0 , 2537,8 , 2551,6 , 2, 1, 1, 6, 7 }, // Greek/Greek/Cyprus
+ { 44, 7, 86, 44, 46, 59, 37, 48, 8722, 43, 101, 187, 171, 8250, 8249, 0,6 , 0,6 , 287,11 , 287,11 , 53,10 , 80,17 , 228,5 , 233,10 , 8336,48 , 8384,96 , 134,24 , 8336,48 , 8384,96 , 134,24 , 3807,28 , 3835,98 , 3933,14 , 3807,28 , 3835,98 , 3933,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {68,75,75}, 148,3 , 8480,62 , 4,4 , 65,5 , 2557,11 , 2568,16 , 2, 0, 1, 6, 7 }, // Greenlandic/Latin/Greenland
+ { 45, 7, 168, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {80,89,71}, 229,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 7, 6, 7 }, // Guarani/Latin/Paraguay
+ { 46, 17, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 298,9 , 298,9 , 269,6 , 192,18 , 351,8 , 359,13 , 8480,67 , 8547,87 , 8634,31 , 8480,67 , 8547,87 , 8634,31 , 3947,32 , 3979,53 , 4032,19 , 3947,32 , 3979,53 , 4032,19 , 0,2 , 0,2 , 484,4 , 488,19 , 22,23 , {73,78,82}, 121,1 , 8542,46 , 4,4 , 4,0 , 2584,7 , 2591,4 , 2, 1, 7, 7, 7 }, // Gujarati/Gujarati/India
+ { 47, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 269,6 , 192,18 , 37,5 , 8,10 , 8665,48 , 8713,85 , 8798,24 , 8665,48 , 8713,85 , 8798,24 , 4051,28 , 4079,52 , 4131,14 , 4051,28 , 4079,52 , 4131,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {78,71,78}, 178,1 , 8588,12 , 8,5 , 4,0 , 2595,5 , 2600,8 , 2, 1, 1, 6, 7 }, // Hausa/Latin/Nigeria
+ { 47, 1, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {78,71,78}, 178,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Hausa/Arabic/Nigeria
+ { 47, 7, 83, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 269,6 , 192,18 , 37,5 , 8,10 , 8665,48 , 8713,85 , 8798,24 , 8665,48 , 8713,85 , 8798,24 , 4051,28 , 4079,52 , 4131,14 , 4051,28 , 4079,52 , 4131,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {71,72,83}, 167,3 , 0,7 , 8,5 , 4,0 , 2595,5 , 2608,4 , 2, 1, 1, 6, 7 }, // Hausa/Latin/Ghana
+ { 47, 7, 156, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 269,6 , 192,18 , 37,5 , 8,10 , 8665,48 , 8713,85 , 8798,24 , 8665,48 , 8713,85 , 8798,24 , 4051,28 , 4079,52 , 4131,14 , 4051,28 , 4079,52 , 4131,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,79,70}, 204,3 , 8600,36 , 8,5 , 4,0 , 2595,5 , 2612,5 , 0, 0, 1, 6, 7 }, // Hausa/Latin/Niger
+ { 48, 18, 105, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 307,6 , 307,6 , 640,8 , 715,18 , 55,4 , 59,9 , 8822,58 , 8880,72 , 158,27 , 8822,58 , 8880,72 , 158,27 , 4145,46 , 4191,65 , 4256,21 , 4145,46 , 4191,65 , 4256,21 , 86,6 , 82,5 , 507,4 , 5,17 , 22,23 , {73,76,83}, 49,1 , 8636,54 , 70,6 , 76,8 , 2617,5 , 2622,5 , 2, 1, 7, 5, 6 }, // Hebrew/Hebrew/Israel
+ { 49, 13, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 313,9 , 322,8 , 269,6 , 10,17 , 18,7 , 25,12 , 8952,59 , 9011,73 , 9084,30 , 8952,59 , 9011,73 , 9084,30 , 4277,32 , 4309,53 , 4362,19 , 4277,32 , 4309,53 , 4362,19 , 92,9 , 87,7 , 511,4 , 5,17 , 22,23 , {73,78,82}, 121,1 , 8690,42 , 4,4 , 4,0 , 2627,6 , 2633,4 , 2, 1, 7, 7, 7 }, // Hindi/Devanagari/India
+ { 50, 7, 98, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 187, 171, 0,6 , 0,6 , 330,8 , 330,8 , 733,13 , 746,19 , 55,4 , 59,9 , 9114,64 , 9178,98 , 9276,25 , 9114,64 , 9178,98 , 9276,25 , 4381,19 , 4400,52 , 4452,17 , 4381,19 , 4400,52 , 4452,17 , 101,3 , 94,3 , 515,4 , 5,17 , 22,23 , {72,85,70}, 230,2 , 8732,46 , 13,5 , 4,0 , 2637,6 , 2643,12 , 2, 0, 1, 6, 7 }, // Hungarian/Latin/Hungary
+ { 51, 7, 99, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 192,8 , 192,8 , 640,8 , 622,18 , 37,5 , 8,10 , 9301,59 , 9360,82 , 9442,24 , 9301,59 , 9360,82 , 9442,24 , 4469,35 , 4504,81 , 4585,14 , 4469,35 , 4504,81 , 4585,14 , 104,4 , 97,4 , 519,4 , 5,17 , 22,23 , {73,83,75}, 232,3 , 8778,49 , 13,5 , 4,0 , 2655,8 , 2663,6 , 0, 0, 1, 6, 7 }, // Icelandic/Latin/Iceland
+ { 52, 7, 101, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 338,10 , 348,9 , 27,8 , 553,18 , 228,5 , 233,10 , 9466,48 , 9514,87 , 134,24 , 9466,48 , 9514,87 , 134,24 , 4599,28 , 4627,43 , 4670,14 , 4599,28 , 4627,43 , 4670,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,68,82}, 235,2 , 8827,39 , 4,4 , 4,0 , 2669,9 , 2669,9 , 2, 0, 7, 6, 7 }, // Indonesian/Latin/Indonesia
+ { 53, 7, 260, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 528,10 , 765,26 , 37,5 , 8,10 , 9601,48 , 9649,93 , 158,27 , 9601,48 , 9649,93 , 9742,24 , 4684,28 , 4712,57 , 4769,14 , 4684,28 , 4712,57 , 4769,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {0,0,0}, 0,0 , 2586,0 , 8,5 , 4,0 , 2678,11 , 2689,5 , 2, 1, 1, 6, 7 }, // Interlingua/Latin/World
+ { 55, 44, 38, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,65,68}, 237,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 0, 7, 6, 7 }, // Inuktitut/Canadian Aboriginal/Canada
+ { 55, 7, 38, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,65,68}, 237,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 0, 7, 6, 7 }, // Inuktitut/Latin/Canada
+ { 57, 7, 104, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 357,11 , 244,10 , 119,10 , 97,16 , 37,5 , 8,10 , 9766,62 , 9828,107 , 9935,24 , 9766,62 , 9828,107 , 9935,24 , 4783,37 , 4820,75 , 4895,14 , 4783,37 , 4820,75 , 4895,14 , 108,4 , 101,4 , 523,6 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8866,31 , 4,4 , 4,0 , 2694,7 , 2701,4 , 2, 1, 1, 6, 7 }, // Irish/Latin/Ireland
+ { 58, 7, 106, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 97,16 , 37,5 , 8,10 , 9959,48 , 10007,94 , 10101,24 , 9959,48 , 10007,94 , 10101,24 , 4909,28 , 4937,57 , 4994,14 , 4909,28 , 4937,57 , 4994,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8897,19 , 13,5 , 4,0 , 2705,8 , 2713,6 , 2, 1, 1, 6, 7 }, // Italian/Latin/Italy
+ { 58, 7, 184, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 97,16 , 37,5 , 8,10 , 9959,48 , 10007,94 , 10101,24 , 9959,48 , 10007,94 , 10101,24 , 4909,28 , 4937,57 , 4994,14 , 4909,28 , 4937,57 , 4994,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8897,19 , 13,5 , 4,0 , 2705,8 , 2719,10 , 2, 1, 1, 6, 7 }, // Italian/Latin/San Marino
+ { 58, 7, 206, 46, 8217, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 254,7 , 254,7 , 156,8 , 10,17 , 37,5 , 8,10 , 9959,48 , 10007,94 , 10101,24 , 9959,48 , 10007,94 , 10101,24 , 4909,28 , 4937,57 , 4994,14 , 4909,28 , 4937,57 , 4994,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,72,70}, 221,3 , 8916,53 , 8,5 , 36,5 , 2705,8 , 2729,8 , 2, 0, 1, 6, 7 }, // Italian/Latin/Switzerland
+ { 58, 7, 230, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 97,16 , 37,5 , 8,10 , 9959,48 , 10007,94 , 10101,24 , 9959,48 , 10007,94 , 10101,24 , 4909,28 , 4937,57 , 4994,14 , 4909,28 , 4937,57 , 4994,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8897,19 , 13,5 , 4,0 , 2705,8 , 2737,18 , 2, 1, 1, 6, 7 }, // Italian/Latin/Vatican City State
+ { 59, 19, 108, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 170,5 , 170,5 , 170,5 , 170,5 , 578,10 , 402,13 , 55,4 , 372,10 , 4423,39 , 4423,39 , 158,27 , 4423,39 , 4423,39 , 158,27 , 5008,14 , 5022,28 , 5008,14 , 5008,14 , 5022,28 , 5008,14 , 112,2 , 105,2 , 529,3 , 323,17 , 22,23 , {74,80,89}, 133,1 , 8969,11 , 4,4 , 4,0 , 2755,3 , 2758,2 , 0, 0, 7, 6, 7 }, // Japanese/Japanese/Japan
+ { 60, 7, 101, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 368,10 , 378,9 , 528,10 , 10,17 , 37,5 , 8,10 , 10125,48 , 9514,87 , 134,24 , 10125,48 , 9514,87 , 134,24 , 5050,28 , 5078,41 , 5119,14 , 5050,28 , 5078,41 , 5119,14 , 114,4 , 107,5 , 532,4 , 5,17 , 22,23 , {73,68,82}, 235,2 , 8827,39 , 8,5 , 4,0 , 2760,4 , 2764,9 , 2, 0, 7, 6, 7 }, // Javanese/Latin/Indonesia
+ { 61, 21, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 387,12 , 399,11 , 269,6 , 35,18 , 351,8 , 359,13 , 10173,63 , 10236,87 , 10323,31 , 10354,69 , 10236,87 , 10323,31 , 5133,33 , 5166,54 , 5220,20 , 5133,33 , 5166,54 , 5220,20 , 118,9 , 112,7 , 536,8 , 544,35 , 22,23 , {73,78,82}, 121,1 , 8980,49 , 4,4 , 4,0 , 2773,5 , 2778,4 , 2, 1, 7, 7, 7 }, // Kannada/Kannada/India
+ { 62, 1, 100, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 547,6 , 35,18 , 18,7 , 25,12 , 10423,72 , 10423,72 , 10495,24 , 10423,72 , 10423,72 , 10495,24 , 5240,54 , 5294,56 , 5350,14 , 5240,54 , 5294,56 , 5350,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,78,82}, 121,1 , 9029,23 , 8,5 , 4,0 , 2782,5 , 2787,10 , 2, 1, 7, 7, 7 }, // Kashmiri/Arabic/India
+ { 63, 2, 110, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 410,10 , 156,8 , 791,22 , 37,5 , 8,10 , 10519,60 , 10579,83 , 10662,24 , 10519,60 , 10686,83 , 10662,24 , 5364,21 , 5385,56 , 5441,14 , 5364,21 , 5385,56 , 5441,14 , 0,2 , 0,2 , 579,4 , 583,17 , 600,23 , {75,90,84}, 240,1 , 9052,58 , 13,5 , 4,0 , 2797,10 , 2807,9 , 2, 1, 1, 6, 7 }, // Kazakh/Cyrillic/Kazakhstan
+ { 64, 7, 179, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 10769,60 , 10829,101 , 158,27 , 10769,60 , 10829,101 , 158,27 , 5455,35 , 5490,84 , 85,14 , 5455,35 , 5490,84 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {82,87,70}, 180,2 , 0,7 , 8,5 , 4,0 , 2816,11 , 2827,8 , 0, 0, 1, 6, 7 }, // Kinyarwanda/Latin/Rwanda
+ { 65, 2, 116, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 420,10 , 420,10 , 269,6 , 813,23 , 37,5 , 8,10 , 10930,48 , 10978,80 , 11058,24 , 11082,59 , 11141,80 , 11058,24 , 5574,38 , 5612,57 , 5669,14 , 5574,38 , 5612,57 , 5669,14 , 127,5 , 119,14 , 579,4 , 623,18 , 22,23 , {75,71,83}, 241,3 , 9110,52 , 13,5 , 4,0 , 2835,8 , 2843,10 , 2, 1, 1, 6, 7 }, // Kirghiz/Cyrillic/Kyrgyzstan
+ { 66, 22, 114, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 430,7 , 430,7 , 836,9 , 845,16 , 382,7 , 389,13 , 11221,39 , 11221,39 , 11221,39 , 11221,39 , 11221,39 , 11221,39 , 5683,14 , 5697,28 , 5683,14 , 5683,14 , 5697,28 , 5683,14 , 132,2 , 133,2 , 641,3 , 5,17 , 22,23 , {75,82,87}, 244,1 , 9162,19 , 4,4 , 4,0 , 2853,3 , 2856,4 , 0, 0, 7, 6, 7 }, // Korean/Korean/South Korea
+ { 66, 22, 113, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 430,7 , 430,7 , 836,9 , 845,16 , 382,7 , 389,13 , 11221,39 , 11221,39 , 11221,39 , 11221,39 , 11221,39 , 11221,39 , 5683,14 , 5697,28 , 5683,14 , 5683,14 , 5697,28 , 5683,14 , 132,2 , 133,2 , 641,3 , 5,17 , 22,23 , {75,80,87}, 245,3 , 9181,39 , 4,4 , 4,0 , 2853,3 , 2860,11 , 0, 0, 1, 6, 7 }, // Korean/Korean/North Korea
+ { 67, 7, 217, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 437,7 , 437,7 , 53,10 , 63,17 , 37,5 , 8,10 , 11260,48 , 11308,88 , 11396,24 , 11260,48 , 11420,101 , 11396,24 , 5725,20 , 5745,42 , 5787,14 , 5725,20 , 5745,42 , 5787,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {84,82,89}, 248,1 , 0,7 , 13,5 , 4,0 , 2871,5 , 2876,7 , 2, 1, 1, 6, 7 }, // Kurdish/Latin/Turkey
+ { 68, 7, 35, 44, 46, 59, 37, 48, 45, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 11521,60 , 11581,106 , 158,27 , 11521,60 , 11581,106 , 158,27 , 5801,34 , 5835,89 , 85,14 , 5801,34 , 5835,89 , 85,14 , 134,5 , 135,5 , 45,4 , 5,17 , 22,23 , {66,73,70}, 163,3 , 9220,27 , 0,4 , 4,0 , 2883,8 , 2891,8 , 0, 0, 1, 6, 7 }, // Rundi/Latin/Burundi
+ { 69, 23, 117, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 444,9 , 415,8 , 861,19 , 55,4 , 402,24 , 11687,61 , 11748,75 , 158,27 , 11687,61 , 11748,75 , 158,27 , 5924,36 , 5960,57 , 6017,17 , 5924,36 , 5960,57 , 6017,17 , 139,8 , 140,8 , 45,4 , 5,17 , 22,23 , {76,65,75}, 249,1 , 9247,21 , 4,4 , 36,5 , 2899,3 , 2899,3 , 0, 0, 7, 6, 7 }, // Lao/Lao/Laos
+ { 71, 7, 118, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 453,8 , 453,8 , 156,8 , 880,26 , 37,5 , 8,10 , 11823,65 , 11888,101 , 134,24 , 11823,65 , 11888,101 , 134,24 , 6034,51 , 6085,72 , 6157,14 , 6171,51 , 6222,72 , 6157,14 , 147,14 , 148,11 , 644,5 , 323,17 , 22,23 , {69,85,82}, 14,1 , 9268,23 , 13,5 , 4,0 , 2902,8 , 2910,7 , 2, 1, 1, 6, 7 }, // Latvian/Latin/Latvia
+ { 72, 7, 49, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 461,9 , 461,9 , 415,8 , 97,16 , 37,5 , 8,10 , 11989,48 , 12037,203 , 12240,24 , 11989,48 , 12037,203 , 12240,24 , 6294,28 , 6322,100 , 6422,14 , 6294,28 , 6322,100 , 6422,14 , 161,8 , 159,6 , 45,4 , 5,17 , 22,23 , {67,68,70}, 207,2 , 9291,23 , 13,5 , 4,0 , 2917,7 , 2924,30 , 2, 1, 1, 6, 7 }, // Lingala/Latin/Congo Kinshasa
+ { 72, 7, 6, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 461,9 , 461,9 , 415,8 , 97,16 , 37,5 , 8,10 , 11989,48 , 12037,203 , 12240,24 , 11989,48 , 12037,203 , 12240,24 , 6294,28 , 6322,100 , 6422,14 , 6294,28 , 6322,100 , 6422,14 , 161,8 , 159,6 , 45,4 , 5,17 , 22,23 , {65,79,65}, 250,2 , 9314,23 , 13,5 , 4,0 , 2917,7 , 2954,6 , 2, 1, 1, 6, 7 }, // Lingala/Latin/Angola
+ { 72, 7, 41, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 461,9 , 461,9 , 415,8 , 97,16 , 37,5 , 8,10 , 11989,48 , 12037,203 , 12240,24 , 11989,48 , 12037,203 , 12240,24 , 6294,28 , 6322,100 , 6422,14 , 6294,28 , 6322,100 , 6422,14 , 161,8 , 159,6 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 9337,23 , 13,5 , 4,0 , 2917,7 , 2960,26 , 0, 0, 1, 6, 7 }, // Lingala/Latin/Central African Republic
+ { 72, 7, 50, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 461,9 , 461,9 , 415,8 , 97,16 , 37,5 , 8,10 , 11989,48 , 12037,203 , 12240,24 , 11989,48 , 12037,203 , 12240,24 , 6294,28 , 6322,100 , 6422,14 , 6294,28 , 6322,100 , 6422,14 , 161,8 , 159,6 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 9337,23 , 13,5 , 4,0 , 2917,7 , 2986,5 , 0, 0, 1, 6, 7 }, // Lingala/Latin/Congo Brazzaville
+ { 73, 7, 124, 44, 160, 59, 37, 48, 8722, 43, 101, 8222, 8220, 8222, 8220, 0,6 , 0,6 , 470,8 , 470,8 , 53,10 , 906,27 , 37,5 , 8,10 , 12264,70 , 12334,96 , 12430,24 , 12264,70 , 12454,98 , 12430,24 , 6436,21 , 6457,89 , 6546,14 , 6436,21 , 6457,89 , 6546,14 , 169,9 , 165,6 , 649,6 , 5,17 , 22,23 , {69,85,82}, 14,1 , 9360,30 , 13,5 , 4,0 , 2991,8 , 2999,7 , 2, 1, 1, 6, 7 }, // Lithuanian/Latin/Lithuania
+ { 74, 2, 127, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 116,7 , 116,7 , 933,7 , 553,18 , 37,5 , 8,10 , 12552,61 , 12613,85 , 12698,24 , 12552,61 , 12613,85 , 12698,24 , 6560,35 , 6595,54 , 1503,14 , 6649,34 , 6595,54 , 1503,14 , 178,10 , 171,8 , 655,5 , 5,17 , 22,23 , {77,75,68}, 252,3 , 9390,56 , 13,5 , 4,0 , 3006,10 , 3016,10 , 2, 1, 1, 6, 7 }, // Macedonian/Cyrillic/Macedonia
+ { 75, 7, 128, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 97,16 , 37,5 , 8,10 , 12722,48 , 12770,92 , 134,24 , 12722,48 , 12770,92 , 134,24 , 6683,34 , 6717,60 , 6777,14 , 6683,34 , 6717,60 , 6777,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {77,71,65}, 170,2 , 9446,13 , 8,5 , 4,0 , 3026,8 , 3034,12 , 0, 0, 1, 6, 7 }, // Malagasy/Latin/Madagascar
+ { 76, 7, 130, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 348,9 , 348,9 , 571,7 , 10,17 , 18,7 , 25,12 , 12862,48 , 12910,82 , 12992,24 , 12862,48 , 12910,82 , 12992,24 , 6791,28 , 6819,43 , 6862,14 , 6791,28 , 6819,43 , 6862,14 , 188,2 , 179,3 , 660,4 , 5,17 , 22,23 , {77,89,82}, 174,2 , 9459,39 , 4,4 , 4,0 , 3046,6 , 1240,8 , 2, 1, 1, 6, 7 }, // Malay/Latin/Malaysia
+ { 76, 1, 130, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {77,89,82}, 174,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Malay/Arabic/Malaysia
+ { 76, 7, 32, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 348,9 , 348,9 , 571,7 , 940,12 , 18,7 , 25,12 , 12862,48 , 12910,82 , 12992,24 , 12862,48 , 12910,82 , 12992,24 , 6791,28 , 6819,43 , 6862,14 , 6791,28 , 6819,43 , 6862,14 , 188,2 , 179,3 , 660,4 , 5,17 , 22,23 , {66,78,68}, 6,1 , 9498,31 , 8,5 , 4,0 , 3046,6 , 3052,6 , 2, 1, 1, 6, 7 }, // Malay/Latin/Brunei
+ { 76, 7, 190, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 348,9 , 348,9 , 571,7 , 10,17 , 18,7 , 25,12 , 12862,48 , 12910,82 , 12992,24 , 12862,48 , 12910,82 , 12992,24 , 6791,28 , 6819,43 , 6862,14 , 6791,28 , 6819,43 , 6862,14 , 188,2 , 179,3 , 660,4 , 5,17 , 22,23 , {83,71,68}, 6,1 , 9529,37 , 4,4 , 4,0 , 3046,6 , 3058,9 , 2, 1, 7, 6, 7 }, // Malay/Latin/Singapore
+ { 77, 24, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 478,13 , 491,12 , 269,6 , 952,18 , 18,7 , 25,12 , 13016,62 , 13078,88 , 13166,32 , 13016,62 , 13078,88 , 13166,32 , 6876,41 , 6917,77 , 6994,22 , 6876,41 , 7016,76 , 7092,21 , 0,2 , 0,2 , 664,6 , 670,31 , 22,23 , {73,78,82}, 121,1 , 9566,40 , 4,4 , 4,0 , 3067,6 , 3073,6 , 2, 1, 7, 7, 7 }, // Malayalam/Malayalam/India
+ { 78, 7, 133, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 503,8 , 511,7 , 119,10 , 970,23 , 37,5 , 8,10 , 13198,48 , 13246,86 , 13332,36 , 13198,48 , 13246,86 , 13368,24 , 7113,28 , 7141,63 , 7204,21 , 7113,28 , 7141,63 , 7225,20 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 9606,27 , 4,4 , 4,0 , 3079,5 , 1248,5 , 2, 1, 7, 6, 7 }, // Maltese/Latin/Malta
+ { 79, 7, 154, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 426,4 , 25,12 , 13392,59 , 13451,133 , 13584,24 , 13392,59 , 13451,133 , 13584,24 , 7245,27 , 7272,47 , 7319,14 , 7245,27 , 7272,47 , 7319,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {78,90,68}, 6,1 , 9633,41 , 8,5 , 4,0 , 3084,5 , 3089,8 , 2, 1, 1, 6, 7 }, // Maori/Latin/New Zealand
+ { 80, 13, 100, 46, 44, 59, 37, 2406, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 518,9 , 518,9 , 269,6 , 192,18 , 18,7 , 25,12 , 13608,66 , 13674,86 , 13760,32 , 13608,66 , 13674,86 , 13760,32 , 7333,32 , 7365,53 , 4362,19 , 7333,32 , 7365,53 , 4362,19 , 190,5 , 182,4 , 511,4 , 5,17 , 22,23 , {73,78,82}, 121,1 , 9674,43 , 4,4 , 4,0 , 3097,5 , 2633,4 , 2, 1, 7, 7, 7 }, // Marathi/Devanagari/India
+ { 82, 2, 143, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 993,10 , 1003,16 , 37,5 , 87,12 , 13792,99 , 13891,192 , 14083,38 , 13792,99 , 14121,192 , 14083,38 , 7418,21 , 7439,43 , 7418,21 , 7418,21 , 7482,43 , 7418,21 , 195,4 , 186,4 , 579,4 , 701,17 , 22,23 , {77,78,84}, 255,1 , 9717,25 , 8,5 , 4,0 , 3102,6 , 3108,6 , 2, 0, 1, 6, 7 }, // Mongolian/Cyrillic/Mongolia
+ { 82, 8, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,78,89}, 256,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Mongolian/Mongolian/China
+ { 84, 13, 150, 46, 44, 59, 37, 2406, 45, 43, 101, 8220, 8221, 8216, 8217, 527,5 , 0,6 , 532,7 , 532,7 , 227,6 , 63,17 , 37,5 , 8,10 , 14313,85 , 14313,85 , 14398,53 , 14313,85 , 14313,85 , 14451,52 , 7525,33 , 7558,54 , 7612,18 , 7525,33 , 7558,54 , 7612,18 , 92,9 , 87,7 , 511,4 , 718,19 , 22,23 , {78,80,82}, 259,4 , 9742,49 , 8,5 , 4,0 , 3114,6 , 3120,5 , 2, 1, 7, 6, 7 }, // Nepali/Devanagari/Nepal
+ { 84, 13, 100, 46, 44, 59, 37, 2406, 45, 43, 101, 8220, 8221, 8216, 8217, 527,5 , 0,6 , 532,7 , 532,7 , 227,6 , 63,17 , 18,7 , 25,12 , 14313,85 , 14313,85 , 14398,53 , 14313,85 , 14313,85 , 14451,52 , 7525,33 , 7558,54 , 7612,18 , 7525,33 , 7558,54 , 7612,18 , 92,9 , 87,7 , 511,4 , 718,19 , 22,23 , {73,78,82}, 121,1 , 9791,49 , 8,5 , 4,0 , 3114,6 , 2633,4 , 2, 1, 7, 7, 7 }, // Nepali/Devanagari/India
+ { 85, 7, 161, 44, 160, 59, 37, 48, 8722, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 192,8 , 192,8 , 495,10 , 478,17 , 37,5 , 8,10 , 5656,48 , 14503,83 , 134,24 , 5787,59 , 14503,83 , 134,24 , 2307,35 , 2242,51 , 2293,14 , 2307,35 , 2242,51 , 2293,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {78,79,75}, 190,2 , 9840,44 , 8,5 , 4,0 , 3125,12 , 3137,5 , 2, 0, 1, 6, 7 }, // Norwegian Bokmal/Latin/Norway
+ { 85, 7, 203, 44, 160, 59, 37, 48, 8722, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 192,8 , 192,8 , 495,10 , 478,17 , 37,5 , 8,10 , 5656,48 , 14503,83 , 134,24 , 5787,59 , 14503,83 , 134,24 , 2307,35 , 2242,51 , 2293,14 , 2307,35 , 2242,51 , 2293,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {78,79,75}, 190,2 , 9840,44 , 8,5 , 4,0 , 3125,12 , 3142,21 , 2, 0, 1, 6, 7 }, // Norwegian Bokmal/Latin/Svalbard And Jan Mayen Islands
{ 86, 7, 74, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Occitan/Latin/France
- { 87, 26, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 941,6 , 10,17 , 18,7 , 25,12 , 13826,86 , 13826,86 , 13912,32 , 13826,86 , 13826,86 , 13912,32 , 7271,33 , 7304,54 , 7358,18 , 7271,33 , 7304,54 , 7358,18 , 68,2 , 65,2 , 45,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 9798,11 , 8,5 , 4,0 , 3064,5 , 3069,4 , 2, 1, 7, 7, 7 }, // Oriya/Oriya/India
- { 88, 1, 1, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 385,8 , 947,20 , 55,4 , 356,11 , 13944,68 , 13944,68 , 158,27 , 13944,68 , 13944,68 , 158,27 , 7376,49 , 7376,49 , 85,14 , 7376,49 , 7376,49 , 85,14 , 192,4 , 183,4 , 45,4 , 5,17 , 22,23 , {65,70,78}, 274,1 , 9809,25 , 13,5 , 4,0 , 3073,4 , 3077,9 , 0, 0, 6, 4, 5 }, // Pashto/Arabic/Afghanistan
- { 89, 1, 102, 1643, 1644, 1563, 37, 1776, 45, 43, 101, 171, 187, 8249, 8250, 495,7 , 495,7 , 502,8 , 510,7 , 385,8 , 98,16 , 55,4 , 356,11 , 14012,70 , 14012,70 , 14082,24 , 14106,74 , 14106,74 , 14082,24 , 7376,49 , 7376,49 , 7425,14 , 7376,49 , 7376,49 , 7425,14 , 196,9 , 187,8 , 605,4 , 609,39 , 22,23 , {73,82,82}, 275,4 , 9834,37 , 74,5 , 4,0 , 3086,5 , 3091,5 , 0, 0, 6, 5, 5 }, // Persian/Arabic/Iran
- { 89, 1, 1, 1643, 1644, 1563, 37, 1776, 45, 43, 101, 171, 187, 8249, 8250, 495,7 , 495,7 , 502,8 , 510,7 , 385,8 , 98,16 , 55,4 , 356,11 , 14180,68 , 14180,68 , 14248,24 , 14272,62 , 14180,68 , 14248,24 , 7376,49 , 7376,49 , 7425,14 , 7376,49 , 7376,49 , 7425,14 , 196,9 , 187,8 , 605,4 , 609,39 , 22,23 , {65,70,78}, 274,1 , 9871,55 , 8,5 , 4,0 , 3096,3 , 3077,9 , 0, 0, 6, 4, 5 }, // Persian/Arabic/Afghanistan
- { 90, 7, 172, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 171, 187, 0,6 , 0,6 , 154,7 , 154,7 , 931,10 , 10,17 , 37,5 , 8,10 , 14334,48 , 14382,97 , 14479,24 , 14334,48 , 14503,99 , 14602,24 , 7439,34 , 7473,59 , 7532,14 , 7439,34 , 7473,59 , 7546,14 , 0,2 , 0,2 , 283,5 , 5,17 , 22,23 , {80,76,78}, 279,2 , 9926,77 , 13,5 , 4,0 , 3099,6 , 3105,6 , 2, 1, 1, 6, 7 }, // Polish/Latin/Poland
- { 91, 7, 30, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 236,7 , 236,7 , 120,10 , 587,27 , 37,5 , 8,10 , 14626,48 , 14674,89 , 134,24 , 14626,48 , 14674,89 , 134,24 , 7560,28 , 7588,79 , 7667,14 , 7560,28 , 7588,79 , 7667,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {66,82,76}, 281,2 , 10003,54 , 4,4 , 4,0 , 3111,9 , 3120,6 , 2, 1, 7, 6, 7 }, // Portuguese/Latin/Brazil
- { 91, 7, 6, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 587,27 , 37,5 , 8,10 , 14626,48 , 14674,89 , 134,24 , 14626,48 , 14674,89 , 134,24 , 7681,49 , 7588,79 , 7667,14 , 7681,49 , 7588,79 , 7667,14 , 205,8 , 195,8 , 0,5 , 5,17 , 22,23 , {65,79,65}, 258,2 , 10057,54 , 13,5 , 4,0 , 3111,9 , 3126,6 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/Angola
- { 91, 7, 39, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 587,27 , 37,5 , 8,10 , 14626,48 , 14674,89 , 134,24 , 14626,48 , 14674,89 , 134,24 , 7681,49 , 7588,79 , 7667,14 , 7681,49 , 7588,79 , 7667,14 , 205,8 , 195,8 , 0,5 , 5,17 , 22,23 , {67,86,69}, 283,1 , 10111,69 , 13,5 , 4,0 , 3111,9 , 3132,10 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/CapeVerde
- { 91, 7, 62, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 587,27 , 37,5 , 8,10 , 14626,48 , 14674,89 , 134,24 , 14626,48 , 14674,89 , 134,24 , 7681,49 , 7588,79 , 7667,14 , 7681,49 , 7588,79 , 7667,14 , 205,8 , 195,8 , 0,5 , 5,17 , 22,23 , {85,83,68}, 165,3 , 10180,81 , 13,5 , 4,0 , 3111,9 , 3142,11 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/EastTimor
- { 91, 7, 66, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 587,27 , 37,5 , 8,10 , 14626,48 , 14674,89 , 134,24 , 14626,48 , 14674,89 , 134,24 , 7681,49 , 7588,79 , 7667,14 , 7681,49 , 7588,79 , 7667,14 , 205,8 , 195,8 , 0,5 , 5,17 , 22,23 , {88,65,70}, 32,4 , 10261,59 , 13,5 , 4,0 , 3111,9 , 3153,16 , 0, 0, 1, 6, 7 }, // Portuguese/Latin/EquatorialGuinea
- { 91, 7, 92, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 587,27 , 37,5 , 8,10 , 14626,48 , 14674,89 , 134,24 , 14626,48 , 14674,89 , 134,24 , 7681,49 , 7588,79 , 7667,14 , 7681,49 , 7588,79 , 7667,14 , 205,8 , 195,8 , 0,5 , 5,17 , 22,23 , {88,79,70}, 210,3 , 10320,62 , 13,5 , 4,0 , 3111,9 , 3169,12 , 0, 0, 1, 6, 7 }, // Portuguese/Latin/GuineaBissau
- { 91, 7, 125, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 587,27 , 37,5 , 8,10 , 14626,48 , 14674,89 , 134,24 , 14626,48 , 14674,89 , 134,24 , 7681,49 , 7588,79 , 7667,14 , 7681,49 , 7588,79 , 7667,14 , 205,8 , 195,8 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 10382,20 , 13,5 , 4,0 , 3111,9 , 3181,10 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/Luxembourg
- { 91, 7, 126, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 587,27 , 18,7 , 25,12 , 14626,48 , 14674,89 , 134,24 , 14626,48 , 14674,89 , 134,24 , 7681,49 , 7588,79 , 7667,14 , 7681,49 , 7588,79 , 7667,14 , 205,8 , 195,8 , 0,5 , 5,17 , 22,23 , {77,79,80}, 143,4 , 10402,53 , 13,5 , 4,0 , 3111,9 , 3191,19 , 2, 1, 7, 6, 7 }, // Portuguese/Latin/Macau
- { 91, 7, 146, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 587,27 , 37,5 , 8,10 , 14626,48 , 14674,89 , 134,24 , 14626,48 , 14674,89 , 134,24 , 7681,49 , 7588,79 , 7667,14 , 7681,49 , 7588,79 , 7667,14 , 205,8 , 195,8 , 0,5 , 5,17 , 22,23 , {77,90,78}, 284,3 , 10455,72 , 13,5 , 4,0 , 3111,9 , 3210,10 , 2, 1, 7, 6, 7 }, // Portuguese/Latin/Mozambique
- { 91, 7, 173, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 587,27 , 37,5 , 8,10 , 14626,48 , 14674,89 , 134,24 , 14626,48 , 14674,89 , 134,24 , 7681,49 , 7588,79 , 7667,14 , 7681,49 , 7588,79 , 7667,14 , 205,8 , 195,8 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 10382,20 , 13,5 , 4,0 , 3220,17 , 3237,8 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/Portugal
- { 91, 7, 185, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 587,27 , 37,5 , 8,10 , 14626,48 , 14674,89 , 134,24 , 14626,48 , 14674,89 , 134,24 , 7681,49 , 7588,79 , 7667,14 , 7681,49 , 7588,79 , 7667,14 , 205,8 , 195,8 , 0,5 , 5,17 , 22,23 , {83,84,68}, 287,2 , 10527,92 , 13,5 , 4,0 , 3111,9 , 3245,19 , 0, 0, 1, 6, 7 }, // Portuguese/Latin/SaoTomeAndPrincipe
- { 91, 7, 206, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 587,27 , 37,5 , 8,10 , 14626,48 , 14674,89 , 134,24 , 14626,48 , 14674,89 , 134,24 , 7681,49 , 7588,79 , 7667,14 , 7681,49 , 7588,79 , 7667,14 , 205,8 , 195,8 , 0,5 , 5,17 , 22,23 , {67,72,70}, 229,3 , 10619,45 , 13,5 , 4,0 , 3111,9 , 3264,5 , 2, 0, 1, 6, 7 }, // Portuguese/Latin/Switzerland
- { 92, 4, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 517,9 , 517,9 , 278,6 , 10,17 , 18,7 , 25,12 , 14763,50 , 14813,68 , 14881,28 , 14763,50 , 14813,68 , 14881,28 , 7730,36 , 7766,57 , 7823,23 , 7730,36 , 7766,57 , 7823,23 , 213,6 , 203,6 , 648,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 10664,39 , 4,4 , 4,0 , 3269,6 , 3275,4 , 2, 1, 7, 7, 7 }, // Punjabi/Gurmukhi/India
- { 92, 1, 163, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 80,18 , 18,7 , 25,12 , 14909,67 , 14909,67 , 158,27 , 14909,67 , 14909,67 , 158,27 , 7846,37 , 7846,37 , 85,14 , 7846,37 , 7846,37 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {80,75,82}, 289,1 , 10703,13 , 79,6 , 4,0 , 3279,6 , 3285,7 , 0, 0, 7, 6, 7 }, // Punjabi/Arabic/Pakistan
- { 93, 7, 169, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 211,18 , 37,5 , 8,10 , 14976,48 , 15024,128 , 158,27 , 14976,48 , 15024,128 , 158,27 , 7883,28 , 7911,53 , 7964,14 , 7883,28 , 7911,53 , 7964,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {80,69,78}, 290,2 , 0,7 , 8,5 , 4,0 , 3292,8 , 3300,4 , 2, 1, 7, 6, 7 }, // Quechua/Latin/Peru
- { 93, 7, 26, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 211,18 , 37,5 , 8,10 , 14976,48 , 15024,128 , 158,27 , 14976,48 , 15024,128 , 158,27 , 7883,28 , 7911,53 , 7964,14 , 7883,28 , 7911,53 , 7964,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {66,79,66}, 292,2 , 0,7 , 8,5 , 4,0 , 3292,8 , 3304,7 , 2, 1, 1, 6, 7 }, // Quechua/Latin/Bolivia
- { 93, 7, 63, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 211,18 , 37,5 , 8,10 , 14976,48 , 15024,128 , 158,27 , 14976,48 , 15024,128 , 158,27 , 7883,28 , 7911,53 , 7964,14 , 7883,28 , 7911,53 , 7964,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {85,83,68}, 6,1 , 0,7 , 8,5 , 4,0 , 3292,8 , 3311,7 , 2, 1, 1, 6, 7 }, // Quechua/Latin/Ecuador
- { 94, 7, 206, 46, 8217, 59, 37, 48, 8722, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 0,6 , 0,6 , 348,8 , 967,28 , 37,5 , 8,10 , 15152,67 , 15219,92 , 15311,24 , 15152,67 , 15219,92 , 15311,24 , 7978,23 , 8001,56 , 8057,14 , 7978,23 , 8001,56 , 8057,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,72,70}, 229,3 , 10716,46 , 13,5 , 4,0 , 3318,9 , 3327,6 , 2, 0, 1, 6, 7 }, // Romansh/Latin/Switzerland
- { 95, 7, 177, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8221, 171, 187, 0,6 , 0,6 , 526,8 , 526,8 , 931,10 , 10,17 , 37,5 , 8,10 , 15335,60 , 15395,98 , 15493,24 , 15335,60 , 15395,98 , 15493,24 , 8071,34 , 8105,48 , 3054,14 , 8071,34 , 8105,48 , 3054,14 , 64,4 , 61,4 , 652,4 , 5,17 , 22,23 , {82,79,78}, 294,3 , 10762,57 , 13,5 , 4,0 , 3333,6 , 3339,7 , 2, 1, 1, 6, 7 }, // Romanian/Latin/Romania
- { 95, 7, 141, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8221, 171, 187, 0,6 , 0,6 , 526,8 , 526,8 , 931,10 , 10,17 , 37,5 , 8,10 , 15335,60 , 15395,98 , 15493,24 , 15335,60 , 15395,98 , 15493,24 , 8153,28 , 8105,48 , 8181,16 , 8153,28 , 8105,48 , 8181,16 , 64,4 , 61,4 , 652,4 , 5,17 , 22,23 , {77,68,76}, 297,1 , 10819,69 , 13,5 , 4,0 , 3346,13 , 3359,17 , 2, 1, 1, 6, 7 }, // Romanian/Latin/Moldova
- { 96, 2, 178, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 107,7 , 107,7 , 931,10 , 326,22 , 55,4 , 59,9 , 15517,62 , 11053,80 , 10970,24 , 15579,62 , 15641,82 , 10970,24 , 8197,21 , 8218,62 , 8280,14 , 8197,21 , 8218,62 , 8197,21 , 219,2 , 209,2 , 226,5 , 528,17 , 22,23 , {82,85,66}, 129,1 , 10888,89 , 13,5 , 4,0 , 3376,7 , 3383,6 , 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Russia
- { 96, 2, 20, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 107,7 , 107,7 , 931,10 , 326,22 , 55,4 , 59,9 , 15517,62 , 11053,80 , 10970,24 , 15579,62 , 15641,82 , 10970,24 , 8197,21 , 8218,62 , 8280,14 , 8197,21 , 8218,62 , 8197,21 , 219,2 , 209,2 , 226,5 , 528,17 , 22,23 , {66,89,78}, 0,2 , 10977,94 , 13,5 , 4,0 , 3376,7 , 472,8 , 2, 0, 1, 6, 7 }, // Russian/Cyrillic/Belarus
- { 96, 2, 110, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 107,7 , 107,7 , 931,10 , 326,22 , 55,4 , 59,9 , 15517,62 , 11053,80 , 10970,24 , 15579,62 , 15641,82 , 10970,24 , 8197,21 , 8218,62 , 8280,14 , 8197,21 , 8218,62 , 8197,21 , 219,2 , 209,2 , 226,5 , 528,17 , 22,23 , {75,90,84}, 248,1 , 11071,83 , 13,5 , 4,0 , 3376,7 , 3389,9 , 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Kazakhstan
- { 96, 2, 116, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 107,7 , 107,7 , 931,10 , 326,22 , 55,4 , 59,9 , 15517,62 , 11053,80 , 10970,24 , 15579,62 , 15641,82 , 10970,24 , 8197,21 , 8218,62 , 8280,14 , 8197,21 , 8218,62 , 8197,21 , 219,2 , 209,2 , 226,5 , 528,17 , 22,23 , {75,71,83}, 249,3 , 11154,82 , 13,5 , 4,0 , 3376,7 , 3398,8 , 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Kyrgyzstan
- { 96, 2, 141, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 107,7 , 107,7 , 931,10 , 326,22 , 55,4 , 59,9 , 15517,62 , 11053,80 , 10970,24 , 15579,62 , 15641,82 , 10970,24 , 8197,21 , 8218,62 , 8280,14 , 8197,21 , 8218,62 , 8197,21 , 219,2 , 209,2 , 226,5 , 528,17 , 22,23 , {77,68,76}, 297,1 , 11236,79 , 13,5 , 4,0 , 3376,7 , 3406,7 , 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Moldova
- { 96, 2, 222, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 107,7 , 107,7 , 931,10 , 326,22 , 37,5 , 8,10 , 15517,62 , 11053,80 , 10970,24 , 15579,62 , 15641,82 , 10970,24 , 8197,21 , 8218,62 , 8280,14 , 8197,21 , 8218,62 , 8197,21 , 0,2 , 0,2 , 226,5 , 528,17 , 22,23 , {85,65,72}, 298,1 , 11315,92 , 13,5 , 4,0 , 3376,7 , 3413,7 , 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Ukraine
- { 98, 7, 41, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 15723,48 , 15771,91 , 15862,24 , 15723,48 , 15771,91 , 15862,24 , 8294,28 , 8322,66 , 8388,14 , 8294,28 , 8322,66 , 8388,14 , 221,2 , 211,2 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 11407,25 , 4,4 , 36,5 , 3420,5 , 3425,22 , 0, 0, 1, 6, 7 }, // Sango/Latin/CentralAfricanRepublic
- { 99, 13, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 7, 7 }, // Sanskrit/Devanagari/India
- { 100, 2, 243, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 107,7 , 107,7 , 995,7 , 1002,20 , 37,5 , 8,10 , 15886,48 , 15934,81 , 12349,24 , 15886,48 , 15934,81 , 12349,24 , 8402,28 , 8430,52 , 8482,14 , 8402,28 , 8430,52 , 8482,14 , 223,9 , 213,8 , 656,7 , 5,17 , 22,23 , {82,83,68}, 299,3 , 11432,58 , 13,5 , 4,0 , 3447,6 , 3453,6 , 0, 0, 1, 6, 7 }, // Serbian/Cyrillic/Serbia
- { 100, 2, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 107,7 , 107,7 , 995,7 , 1002,20 , 37,5 , 8,10 , 16015,58 , 15934,81 , 12349,24 , 16015,58 , 15934,81 , 12349,24 , 8496,33 , 8529,55 , 8482,14 , 8496,33 , 8529,55 , 8482,14 , 232,11 , 213,8 , 656,7 , 5,17 , 22,23 , {66,65,77}, 302,2 , 11490,174 , 13,5 , 4,0 , 3447,6 , 3459,19 , 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/BosniaAndHerzegowina
- { 100, 2, 242, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 107,7 , 107,7 , 995,7 , 1002,20 , 37,5 , 8,10 , 16015,58 , 15934,81 , 12349,24 , 16015,58 , 15934,81 , 12349,24 , 8496,33 , 8529,55 , 8482,14 , 8496,33 , 8529,55 , 8482,14 , 232,11 , 213,8 , 656,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 11664,23 , 13,5 , 4,0 , 3447,6 , 3478,9 , 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/Montenegro
- { 100, 2, 257, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 107,7 , 107,7 , 995,7 , 1002,20 , 37,5 , 8,10 , 16015,58 , 15934,81 , 12349,24 , 16015,58 , 15934,81 , 12349,24 , 8496,33 , 8430,52 , 8482,14 , 8496,33 , 8430,52 , 8482,14 , 223,9 , 213,8 , 656,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 11664,23 , 13,5 , 4,0 , 3447,6 , 3487,6 , 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/Kosovo
- { 100, 7, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 154,7 , 154,7 , 995,7 , 1002,20 , 37,5 , 8,10 , 16073,58 , 16131,81 , 16212,24 , 16073,58 , 16131,81 , 16212,24 , 8584,33 , 8617,57 , 2162,14 , 8584,33 , 8617,57 , 2162,14 , 243,11 , 221,8 , 276,7 , 5,17 , 22,23 , {66,65,77}, 150,2 , 11687,174 , 13,5 , 4,0 , 3493,6 , 591,19 , 2, 1, 1, 6, 7 }, // Serbian/Latin/BosniaAndHerzegowina
- { 100, 7, 242, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 154,7 , 154,7 , 995,7 , 1002,20 , 37,5 , 8,10 , 16073,58 , 16131,81 , 16212,24 , 16073,58 , 16131,81 , 16212,24 , 8584,33 , 8617,57 , 2162,14 , 8584,33 , 8617,57 , 2162,14 , 243,11 , 221,8 , 276,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 11861,23 , 13,5 , 4,0 , 3493,6 , 3499,9 , 2, 1, 1, 6, 7 }, // Serbian/Latin/Montenegro
- { 100, 7, 243, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 154,7 , 154,7 , 995,7 , 1002,20 , 37,5 , 8,10 , 16236,48 , 16131,81 , 16212,24 , 16236,48 , 16131,81 , 16212,24 , 8674,28 , 8702,54 , 2162,14 , 8674,28 , 8702,54 , 2162,14 , 254,9 , 221,8 , 276,7 , 5,17 , 22,23 , {82,83,68}, 299,3 , 11884,58 , 13,5 , 4,0 , 3493,6 , 3508,6 , 0, 0, 1, 6, 7 }, // Serbian/Latin/Serbia
- { 100, 7, 257, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 154,7 , 154,7 , 995,7 , 1002,20 , 37,5 , 8,10 , 16073,58 , 16131,81 , 16212,24 , 16073,58 , 16131,81 , 16212,24 , 8584,33 , 8702,54 , 2162,14 , 8584,33 , 8702,54 , 2162,14 , 254,9 , 221,8 , 276,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 11861,23 , 13,5 , 4,0 , 3493,6 , 3514,6 , 2, 1, 1, 6, 7 }, // Serbian/Latin/Kosovo
- { 101, 2, 81, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 534,9 , 534,9 , 175,8 , 1022,23 , 37,5 , 8,10 , 16284,63 , 16347,82 , 10970,24 , 16429,60 , 16489,86 , 10970,24 , 8756,28 , 8784,61 , 8845,14 , 8859,28 , 8887,61 , 8845,14 , 263,15 , 229,15 , 45,4 , 5,17 , 22,23 , {71,69,76}, 236,1 , 11942,17 , 8,5 , 4,0 , 3520,4 , 3524,11 , 2, 1, 1, 6, 7 }, // Ossetic/Cyrillic/Georgia
- { 101, 2, 178, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 534,9 , 534,9 , 175,8 , 1022,23 , 37,5 , 8,10 , 16284,63 , 16347,82 , 10970,24 , 16429,60 , 16489,86 , 10970,24 , 8756,28 , 8784,61 , 8845,14 , 8859,28 , 8887,61 , 8845,14 , 263,15 , 229,15 , 45,4 , 5,17 , 22,23 , {82,85,66}, 129,1 , 11959,17 , 8,5 , 4,0 , 3520,4 , 3535,6 , 2, 1, 1, 6, 7 }, // Ossetic/Cyrillic/Russia
- { 102, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Southern Sotho/Latin/SouthAfrica
- { 103, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Tswana/Latin/SouthAfrica
- { 104, 7, 240, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 16575,48 , 16623,100 , 16723,24 , 16575,48 , 16623,100 , 16723,24 , 8948,28 , 8976,55 , 9031,14 , 8948,28 , 8976,55 , 9031,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,83,68}, 165,3 , 11976,22 , 4,4 , 4,0 , 3541,8 , 1762,8 , 2, 1, 7, 6, 7 }, // Shona/Latin/Zimbabwe
- { 105, 1, 163, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {80,75,82}, 182,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 7, 6, 7 }, // Sindhi/Arabic/Pakistan
- { 106, 32, 198, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 543,9 , 552,8 , 53,10 , 63,17 , 200,5 , 205,10 , 16747,59 , 16806,96 , 16902,32 , 16934,61 , 16806,96 , 16902,32 , 9045,39 , 9084,62 , 9146,19 , 9045,39 , 9084,62 , 9146,19 , 278,5 , 244,4 , 663,5 , 668,37 , 22,23 , {76,75,82}, 304,3 , 11998,58 , 4,4 , 4,0 , 3549,5 , 3554,11 , 2, 1, 1, 6, 7 }, // Sinhala/Sinhala/SriLanka
- { 107, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Swati/Latin/SouthAfrica
- { 108, 7, 191, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 176,7 , 560,7 , 1045,10 , 532,18 , 55,4 , 59,9 , 16995,48 , 17043,82 , 16212,24 , 16995,48 , 17125,89 , 16212,24 , 9165,21 , 9186,52 , 9238,14 , 9165,21 , 9186,52 , 9238,14 , 0,2 , 0,2 , 283,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 12056,26 , 13,5 , 4,0 , 3565,10 , 3575,9 , 2, 1, 1, 6, 7 }, // Slovak/Latin/Slovakia
- { 109, 7, 192, 44, 46, 59, 37, 48, 8722, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 567,8 , 567,8 , 1055,9 , 1064,19 , 37,5 , 8,10 , 17214,59 , 17273,86 , 16212,24 , 17214,59 , 17273,86 , 16212,24 , 9252,35 , 9287,52 , 9339,14 , 9252,35 , 9287,52 , 9339,14 , 60,4 , 248,4 , 54,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 12082,28 , 13,5 , 4,0 , 3584,11 , 3595,9 , 2, 1, 1, 6, 7 }, // Slovenian/Latin/Slovenia
- { 110, 7, 194, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1083,19 , 18,7 , 25,12 , 17359,48 , 17407,189 , 17596,24 , 17359,48 , 17407,189 , 17596,24 , 9353,28 , 9381,47 , 9428,15 , 9353,28 , 9381,47 , 9428,15 , 283,3 , 252,3 , 45,4 , 5,17 , 22,23 , {83,79,83}, 100,1 , 12110,22 , 4,4 , 4,0 , 3604,8 , 3612,10 , 0, 0, 1, 6, 7 }, // Somali/Latin/Somalia
- { 110, 7, 59, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1083,19 , 18,7 , 25,12 , 17359,48 , 17407,189 , 17596,24 , 17359,48 , 17407,189 , 17596,24 , 9353,28 , 9381,47 , 9428,15 , 9353,28 , 9381,47 , 9428,15 , 283,3 , 252,3 , 45,4 , 5,17 , 22,23 , {68,74,70}, 43,3 , 12132,21 , 4,4 , 4,0 , 3604,8 , 3622,7 , 0, 0, 6, 6, 7 }, // Somali/Latin/Djibouti
- { 110, 7, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1083,19 , 18,7 , 25,12 , 17359,48 , 17407,189 , 17596,24 , 17359,48 , 17407,189 , 17596,24 , 9353,28 , 9381,47 , 9428,15 , 9353,28 , 9381,47 , 9428,15 , 283,3 , 252,3 , 45,4 , 5,17 , 22,23 , {69,84,66}, 0,2 , 12153,22 , 4,4 , 4,0 , 3604,8 , 3629,8 , 2, 1, 7, 6, 7 }, // Somali/Latin/Ethiopia
- { 110, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1083,19 , 37,5 , 8,10 , 17359,48 , 17407,189 , 17596,24 , 17359,48 , 17407,189 , 17596,24 , 9353,28 , 9381,47 , 9428,15 , 9353,28 , 9381,47 , 9428,15 , 283,3 , 252,3 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 0,7 , 4,4 , 4,0 , 3604,8 , 3637,7 , 2, 1, 7, 6, 7 }, // Somali/Latin/Kenya
- { 111, 7, 197, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 55,4 , 356,11 , 17620,61 , 17681,89 , 17770,24 , 17620,61 , 17681,89 , 17770,24 , 9443,35 , 9478,53 , 7964,14 , 9443,35 , 9478,53 , 7964,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 3644,17 , 2354,6 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Spain
- { 111, 7, 10, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 3054,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {65,82,83}, 6,1 , 12175,51 , 8,5 , 4,0 , 3661,7 , 3668,9 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Argentina
- { 111, 7, 22, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 64,4 , 61,4 , 0,5 , 5,17 , 22,23 , {66,90,68}, 6,1 , 12226,52 , 4,4 , 4,0 , 3661,7 , 3677,6 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Belize
- { 111, 7, 26, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17770,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {66,79,66}, 292,2 , 12278,35 , 4,4 , 4,0 , 3661,7 , 3304,7 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Bolivia
- { 111, 7, 30, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 64,4 , 61,4 , 0,5 , 5,17 , 22,23 , {66,82,76}, 281,2 , 12313,52 , 4,4 , 4,0 , 3661,7 , 3120,6 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Brazil
- { 111, 7, 43, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 348,8 , 587,27 , 37,5 , 8,10 , 17620,61 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {67,76,80}, 6,1 , 12365,45 , 4,4 , 36,5 , 3661,7 , 3683,5 , 0, 0, 1, 6, 7 }, // Spanish/Latin/Chile
- { 111, 7, 47, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 509,7 , 587,27 , 18,7 , 25,12 , 17620,61 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 9531,14 , 9443,35 , 9478,53 , 3054,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {67,79,80}, 6,1 , 12410,54 , 8,5 , 4,0 , 3661,7 , 3688,8 , 0, 0, 7, 6, 7 }, // Spanish/Latin/Colombia
- { 111, 7, 52, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {67,82,67}, 307,1 , 12464,67 , 4,4 , 4,0 , 3661,7 , 3696,10 , 2, 0, 1, 6, 7 }, // Spanish/Latin/CostaRica
- { 111, 7, 55, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 64,4 , 61,4 , 0,5 , 5,17 , 22,23 , {67,85,80}, 6,1 , 12531,42 , 4,4 , 4,0 , 3661,7 , 3706,4 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Cuba
- { 111, 7, 61, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 18,7 , 25,12 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 3054,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {68,79,80}, 308,3 , 12573,54 , 4,4 , 85,6 , 3661,7 , 3710,20 , 2, 1, 7, 6, 7 }, // Spanish/Latin/DominicanRepublic
- { 111, 7, 63, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 12627,70 , 4,4 , 36,5 , 3661,7 , 3311,7 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Ecuador
- { 111, 7, 65, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 12627,70 , 4,4 , 4,0 , 3661,7 , 3730,11 , 2, 1, 7, 6, 7 }, // Spanish/Latin/ElSalvador
- { 111, 7, 66, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 55,4 , 356,11 , 17620,61 , 17681,89 , 17770,24 , 17620,61 , 17681,89 , 17770,24 , 9443,35 , 9478,53 , 7964,14 , 9443,35 , 9478,53 , 7964,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {88,65,70}, 32,4 , 12697,53 , 4,4 , 4,0 , 3661,7 , 3741,17 , 0, 0, 1, 6, 7 }, // Spanish/Latin/EquatorialGuinea
- { 111, 7, 90, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 509,7 , 587,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {71,84,81}, 311,1 , 12750,30 , 18,5 , 4,0 , 3661,7 , 3758,9 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Guatemala
- { 111, 7, 96, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 1102,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {72,78,76}, 297,1 , 12780,60 , 4,4 , 4,0 , 3661,7 , 3767,8 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Honduras
- { 111, 7, 139, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 27,8 , 587,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17878,48 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 3054,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {77,88,78}, 6,1 , 12840,48 , 4,4 , 4,0 , 3775,17 , 3792,6 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Mexico
- { 111, 7, 155, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {78,73,79}, 312,2 , 12888,69 , 4,4 , 4,0 , 3661,7 , 3798,9 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Nicaragua
- { 111, 7, 166, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 1129,8 , 587,27 , 18,7 , 25,12 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17770,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {80,65,66}, 314,3 , 12957,54 , 4,4 , 4,0 , 3661,7 , 3807,6 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Panama
- { 111, 7, 168, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 37,5 , 8,10 , 17620,61 , 17681,89 , 17770,24 , 17620,61 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {80,89,71}, 317,3 , 13011,61 , 8,5 , 23,6 , 3661,7 , 3813,8 , 0, 0, 7, 6, 7 }, // Spanish/Latin/Paraguay
- { 111, 7, 169, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 509,7 , 587,27 , 37,5 , 8,10 , 17926,60 , 17986,88 , 17770,24 , 18074,60 , 18134,88 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {80,69,78}, 290,2 , 13072,43 , 4,4 , 4,0 , 3661,7 , 3300,4 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Peru
- { 111, 7, 170, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 18,7 , 25,12 , 17620,61 , 17681,89 , 17770,24 , 17620,61 , 17681,89 , 17770,24 , 9443,35 , 9478,53 , 7964,14 , 9443,35 , 9478,53 , 7964,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {80,72,80}, 185,1 , 13115,48 , 13,5 , 4,0 , 3661,7 , 3821,9 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Philippines
- { 111, 7, 174, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 1129,8 , 587,27 , 18,7 , 25,12 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 12627,70 , 4,4 , 4,0 , 3661,7 , 1408,11 , 2, 1, 7, 6, 7 }, // Spanish/Latin/PuertoRico
- { 111, 7, 225, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 18,7 , 25,12 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 12627,70 , 4,4 , 4,0 , 3661,7 , 3830,7 , 2, 1, 7, 6, 7 }, // Spanish/Latin/UnitedStates
- { 111, 7, 227, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 37,5 , 8,10 , 17926,60 , 17986,88 , 17770,24 , 18074,60 , 18134,88 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {85,89,85}, 6,1 , 13163,48 , 8,5 , 4,0 , 3661,7 , 3837,7 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Uruguay
- { 111, 7, 231, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 18,7 , 25,12 , 17620,61 , 17681,89 , 17770,24 , 17620,61 , 17681,89 , 17770,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {86,69,70}, 320,3 , 13211,64 , 4,4 , 36,5 , 3661,7 , 3844,9 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Venezuela
- { 111, 7, 238, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 55,4 , 356,11 , 17620,61 , 17681,89 , 17770,24 , 17620,61 , 17681,89 , 17770,24 , 9443,35 , 9478,53 , 7964,14 , 9443,35 , 9478,53 , 7964,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 3661,7 , 3853,8 , 2, 1, 1, 6, 7 }, // Spanish/Latin/CanaryIslands
- { 111, 7, 246, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 64,4 , 61,4 , 0,5 , 5,17 , 22,23 , {0,0,0}, 0,0 , 13275,0 , 4,4 , 4,0 , 3861,23 , 3884,13 , 2, 1, 1, 6, 7 }, // Spanish/Latin/LatinAmericaAndTheCaribbean
- { 111, 7, 250, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 55,4 , 356,11 , 17620,61 , 17681,89 , 17770,24 , 17620,61 , 17681,89 , 17770,24 , 9443,35 , 9478,53 , 7964,14 , 9443,35 , 9478,53 , 7964,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 3661,7 , 3897,15 , 2, 1, 1, 6, 7 }, // Spanish/Latin/CeutaAndMelilla
- { 113, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 582,8 , 582,8 , 120,10 , 10,17 , 37,5 , 8,10 , 18222,48 , 18270,84 , 134,24 , 18222,48 , 18270,84 , 134,24 , 9545,60 , 9545,60 , 85,14 , 9545,60 , 9545,60 , 85,14 , 286,7 , 255,6 , 548,5 , 705,47 , 22,23 , {84,90,83}, 198,3 , 13275,67 , 4,4 , 4,0 , 3912,9 , 1587,8 , 0, 0, 1, 6, 7 }, // Swahili/Latin/Tanzania
- { 113, 7, 49, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 582,8 , 582,8 , 120,10 , 10,17 , 37,5 , 8,10 , 18222,48 , 18270,84 , 134,24 , 18222,48 , 18270,84 , 134,24 , 9545,60 , 9545,60 , 85,14 , 9545,60 , 9545,60 , 85,14 , 286,7 , 255,6 , 548,5 , 705,47 , 22,23 , {67,68,70}, 215,2 , 13342,55 , 4,4 , 4,0 , 3921,8 , 3929,32 , 2, 1, 1, 6, 7 }, // Swahili/Latin/CongoKinshasa
- { 113, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 582,8 , 582,8 , 120,10 , 10,17 , 37,5 , 8,10 , 18222,48 , 18270,84 , 134,24 , 18222,48 , 18270,84 , 134,24 , 9545,60 , 9545,60 , 85,14 , 9545,60 , 9545,60 , 85,14 , 0,2 , 0,2 , 548,5 , 705,47 , 22,23 , {75,69,83}, 2,3 , 13397,58 , 4,4 , 4,0 , 3912,9 , 1153,5 , 2, 1, 7, 6, 7 }, // Swahili/Latin/Kenya
- { 113, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 582,8 , 582,8 , 120,10 , 10,17 , 37,5 , 8,10 , 18222,48 , 18270,84 , 134,24 , 18222,48 , 18270,84 , 134,24 , 9545,60 , 9545,60 , 85,14 , 9545,60 , 9545,60 , 85,14 , 286,7 , 255,6 , 548,5 , 705,47 , 22,23 , {85,71,88}, 203,3 , 13455,61 , 4,4 , 4,0 , 3912,9 , 1652,6 , 0, 0, 1, 6, 7 }, // Swahili/Latin/Uganda
- { 114, 7, 205, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 590,9 , 590,9 , 53,10 , 98,16 , 37,5 , 367,16 , 18354,59 , 18413,86 , 134,24 , 18354,59 , 18413,86 , 134,24 , 9605,29 , 9634,50 , 2353,14 , 9605,29 , 9634,50 , 2353,14 , 293,2 , 261,2 , 45,4 , 5,17 , 22,23 , {83,69,75}, 196,2 , 13516,45 , 13,5 , 4,0 , 3961,7 , 3968,7 , 2, 1, 1, 6, 7 }, // Swedish/Latin/Sweden
- { 114, 7, 73, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 590,9 , 590,9 , 1137,10 , 98,16 , 37,5 , 367,16 , 18354,59 , 18413,86 , 134,24 , 18354,59 , 18413,86 , 134,24 , 9605,29 , 9634,50 , 2353,14 , 9605,29 , 9634,50 , 2353,14 , 293,2 , 261,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8852,19 , 13,5 , 4,0 , 3961,7 , 1050,7 , 2, 1, 1, 6, 7 }, // Swedish/Latin/Finland
- { 114, 7, 248, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 590,9 , 590,9 , 53,10 , 98,16 , 37,5 , 367,16 , 18354,59 , 18413,86 , 134,24 , 18354,59 , 18413,86 , 134,24 , 9605,29 , 9634,50 , 2353,14 , 9605,29 , 9634,50 , 2353,14 , 293,2 , 261,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8852,19 , 13,5 , 4,0 , 3961,7 , 3975,5 , 2, 1, 1, 6, 7 }, // Swedish/Latin/AlandIslands
- { 116, 2, 209, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {84,74,83}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Tajik/Cyrillic/Tajikistan
- { 117, 27, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 599,13 , 599,13 , 278,6 , 211,18 , 312,7 , 383,12 , 18499,58 , 18557,86 , 18643,31 , 18499,58 , 18557,86 , 18643,31 , 9684,39 , 9723,49 , 9772,20 , 9684,39 , 9723,49 , 9772,20 , 295,8 , 263,8 , 752,7 , 5,17 , 22,23 , {73,78,82}, 127,1 , 13561,49 , 8,5 , 4,0 , 3980,5 , 3985,7 , 2, 1, 7, 7, 7 }, // Tamil/Tamil/India
- { 117, 27, 130, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 599,13 , 599,13 , 278,6 , 211,18 , 312,7 , 383,12 , 18499,58 , 18557,86 , 18643,31 , 18499,58 , 18557,86 , 18643,31 , 9684,39 , 9723,49 , 9772,20 , 9684,39 , 9723,49 , 9772,20 , 295,8 , 263,8 , 752,7 , 5,17 , 22,23 , {77,89,82}, 180,2 , 13610,61 , 8,5 , 4,0 , 3980,5 , 3992,7 , 2, 1, 1, 6, 7 }, // Tamil/Tamil/Malaysia
- { 117, 27, 190, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 599,13 , 599,13 , 278,6 , 211,18 , 312,7 , 383,12 , 18499,58 , 18557,86 , 18643,31 , 18499,58 , 18557,86 , 18643,31 , 9684,39 , 9723,49 , 9772,20 , 9684,39 , 9723,49 , 9772,20 , 295,8 , 263,8 , 752,7 , 5,17 , 22,23 , {83,71,68}, 6,1 , 13671,61 , 8,5 , 4,0 , 3980,5 , 3999,11 , 2, 1, 7, 6, 7 }, // Tamil/Tamil/Singapore
- { 117, 27, 198, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 599,13 , 599,13 , 278,6 , 211,18 , 37,5 , 8,10 , 18499,58 , 18557,86 , 18643,31 , 18499,58 , 18557,86 , 18643,31 , 9684,39 , 9723,49 , 9772,20 , 9684,39 , 9723,49 , 9772,20 , 295,8 , 263,8 , 752,7 , 5,17 , 22,23 , {76,75,82}, 323,3 , 13732,49 , 8,5 , 4,0 , 3980,5 , 4010,6 , 2, 1, 1, 6, 7 }, // Tamil/Tamil/SriLanka
- { 118, 2, 178, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {82,85,66}, 129,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Tatar/Cyrillic/Russia
- { 119, 28, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 612,11 , 612,11 , 348,8 , 1147,18 , 18,7 , 25,12 , 18674,66 , 18740,86 , 18826,31 , 18857,62 , 18740,86 , 18826,31 , 9792,32 , 9824,60 , 9884,18 , 9792,32 , 9824,60 , 9884,18 , 0,2 , 0,2 , 759,7 , 766,27 , 22,23 , {73,78,82}, 127,1 , 13781,26 , 4,4 , 4,0 , 4016,6 , 4022,9 , 2, 1, 7, 7, 7 }, // Telugu/Telugu/India
- { 120, 30, 211, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 114,5 , 114,5 , 623,8 , 631,7 , 278,6 , 1165,19 , 37,5 , 395,28 , 18919,63 , 18982,98 , 18919,63 , 18919,63 , 18982,98 , 18919,63 , 9902,23 , 9925,68 , 9993,16 , 9902,23 , 9925,68 , 9993,16 , 303,10 , 271,10 , 793,4 , 5,17 , 22,23 , {84,72,66}, 326,3 , 13807,19 , 4,4 , 4,0 , 4031,3 , 4031,3 , 2, 1, 7, 6, 7 }, // Thai/Thai/Thailand
- { 121, 31, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 1184,23 , 18,7 , 25,12 , 2886,63 , 19080,159 , 158,27 , 2886,63 , 19239,147 , 158,27 , 10009,51 , 10060,79 , 10139,27 , 10009,51 , 10060,79 , 10139,27 , 313,7 , 281,8 , 45,4 , 5,17 , 22,23 , {67,78,89}, 329,1 , 13826,13 , 8,5 , 4,0 , 4034,8 , 4042,6 , 2, 1, 7, 6, 7 }, // Tibetan/Tibetan/China
- { 121, 31, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 1184,23 , 18,7 , 25,12 , 2886,63 , 19080,159 , 158,27 , 2886,63 , 19239,147 , 158,27 , 10009,51 , 10060,79 , 10139,27 , 10009,51 , 10060,79 , 10139,27 , 313,7 , 281,8 , 45,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 13839,19 , 8,5 , 4,0 , 4034,8 , 4048,7 , 2, 1, 7, 7, 7 }, // Tibetan/Tibetan/India
- { 122, 14, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1207,23 , 18,7 , 25,12 , 19386,36 , 19422,54 , 19476,24 , 19386,36 , 19422,54 , 19476,24 , 10166,21 , 10187,29 , 10216,14 , 10166,21 , 10230,29 , 10259,14 , 320,7 , 289,7 , 45,4 , 5,17 , 22,23 , {69,84,66}, 0,2 , 13858,16 , 4,4 , 4,0 , 4055,4 , 82,5 , 2, 1, 7, 6, 7 }, // Tigrinya/Ethiopic/Ethiopia
- { 122, 14, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1207,23 , 18,7 , 25,12 , 19386,36 , 19422,54 , 19476,24 , 19386,36 , 19422,54 , 19476,24 , 10166,21 , 10187,29 , 10259,14 , 10166,21 , 10230,29 , 10259,14 , 320,7 , 289,7 , 45,4 , 5,17 , 22,23 , {69,82,78}, 46,3 , 0,7 , 4,4 , 4,0 , 4055,4 , 4059,4 , 2, 1, 1, 6, 7 }, // Tigrinya/Ethiopic/Eritrea
- { 123, 7, 214, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 638,8 , 638,8 , 638,8 , 638,8 , 278,6 , 98,16 , 18,7 , 25,12 , 19500,51 , 19551,87 , 19638,24 , 19500,51 , 19551,87 , 19638,24 , 10273,29 , 10302,60 , 10362,14 , 10273,29 , 10302,60 , 10362,14 , 327,10 , 296,6 , 797,5 , 802,59 , 861,65 , {84,79,80}, 201,2 , 13874,41 , 8,5 , 4,0 , 4063,13 , 1602,5 , 2, 1, 1, 6, 7 }, // Tongan/Latin/Tonga
- { 124, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Tsonga/Latin/SouthAfrica
- { 125, 7, 217, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 646,8 , 646,8 , 1230,9 , 1239,16 , 37,5 , 8,10 , 19662,48 , 19710,75 , 19785,24 , 19662,48 , 19710,75 , 19785,24 , 10376,28 , 10404,54 , 10458,14 , 10376,28 , 10404,54 , 10458,14 , 337,2 , 302,2 , 152,4 , 5,17 , 22,23 , {84,82,89}, 256,1 , 13915,40 , 4,4 , 4,0 , 4076,6 , 4082,7 , 2, 1, 1, 6, 7 }, // Turkish/Latin/Turkey
- { 125, 7, 56, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 646,8 , 646,8 , 1230,9 , 1239,16 , 18,7 , 25,12 , 19662,48 , 19710,75 , 19785,24 , 19662,48 , 19710,75 , 19785,24 , 10376,28 , 10404,54 , 10458,14 , 10376,28 , 10404,54 , 10458,14 , 337,2 , 302,2 , 152,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8339,19 , 4,4 , 4,0 , 4076,6 , 4089,6 , 2, 1, 1, 6, 7 }, // Turkish/Latin/Cyprus
- { 126, 7, 218, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8220, 8221, 0,6 , 0,6 , 654,8 , 654,8 , 931,10 , 1239,16 , 37,5 , 8,10 , 19809,51 , 19860,77 , 19937,24 , 19809,51 , 19860,77 , 19937,24 , 10472,21 , 10493,54 , 10547,14 , 10472,21 , 10493,54 , 10547,14 , 0,2 , 0,2 , 926,4 , 5,17 , 22,23 , {84,77,84}, 330,3 , 13955,49 , 13,5 , 4,0 , 4095,9 , 4104,12 , 2, 1, 1, 6, 7 }, // Turkmen/Latin/Turkmenistan
- { 128, 1, 44, 46, 44, 59, 37, 48, 45, 43, 101, 187, 171, 8250, 8249, 0,6 , 0,6 , 191,10 , 201,9 , 53,10 , 1255,17 , 18,7 , 25,12 , 19961,84 , 19961,84 , 158,27 , 19961,84 , 19961,84 , 158,27 , 10561,21 , 10582,55 , 10637,14 , 10561,21 , 10582,55 , 10637,14 , 339,12 , 304,12 , 45,4 , 5,17 , 22,23 , {67,78,89}, 139,1 , 14004,40 , 4,4 , 4,0 , 4116,8 , 4124,5 , 2, 1, 7, 6, 7 }, // Uighur/Arabic/China
- { 129, 2, 222, 44, 160, 59, 37, 48, 45, 43, 1077, 171, 187, 8222, 8220, 0,6 , 0,6 , 129,7 , 129,7 , 175,8 , 1272,22 , 37,5 , 8,10 , 20045,48 , 20093,95 , 20188,24 , 20212,67 , 20279,87 , 20366,24 , 1573,21 , 10651,56 , 10707,14 , 1573,21 , 10651,56 , 10707,14 , 351,2 , 316,2 , 930,5 , 528,17 , 22,23 , {85,65,72}, 298,1 , 14044,49 , 13,5 , 4,0 , 4129,10 , 4139,7 , 2, 1, 1, 6, 7 }, // Ukrainian/Cyrillic/Ukraine
- { 130, 1, 163, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 662,10 , 672,9 , 278,6 , 157,18 , 18,7 , 25,12 , 20390,68 , 20390,68 , 134,24 , 20390,68 , 20390,68 , 134,24 , 10721,39 , 10721,39 , 85,14 , 10721,39 , 10721,39 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {80,75,82}, 182,2 , 14093,49 , 4,4 , 4,0 , 4146,4 , 3285,7 , 0, 0, 7, 6, 7 }, // Urdu/Arabic/Pakistan
- { 130, 1, 100, 46, 44, 59, 37, 1776, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 681,6 , 681,6 , 278,6 , 157,18 , 18,7 , 25,12 , 20390,68 , 20390,68 , 134,24 , 20390,68 , 20390,68 , 134,24 , 10760,36 , 10760,36 , 85,14 , 10760,36 , 10760,36 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 14142,42 , 8,5 , 4,0 , 4146,4 , 4150,5 , 2, 1, 7, 7, 7 }, // Urdu/Arabic/India
- { 131, 7, 228, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8217, 8216, 0,6 , 0,6 , 687,8 , 687,8 , 27,8 , 1294,18 , 37,5 , 356,11 , 20458,48 , 20506,75 , 20581,24 , 20605,48 , 20653,75 , 20581,24 , 10796,32 , 10828,61 , 10889,14 , 10796,32 , 10828,61 , 10889,14 , 353,2 , 318,2 , 152,4 , 297,17 , 22,23 , {85,90,83}, 333,4 , 14184,58 , 13,5 , 4,0 , 4155,6 , 4161,11 , 0, 0, 1, 6, 7 }, // Uzbek/Latin/Uzbekistan
- { 131, 1, 1, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 385,8 , 1312,33 , 55,4 , 356,11 , 20728,47 , 14180,68 , 158,27 , 20728,47 , 14180,68 , 158,27 , 10903,21 , 7376,49 , 85,14 , 10903,21 , 7376,49 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {65,70,78}, 274,1 , 14242,13 , 13,5 , 4,0 , 4172,6 , 3077,9 , 0, 0, 6, 4, 5 }, // Uzbek/Arabic/Afghanistan
- { 131, 2, 228, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 614,19 , 37,5 , 88,12 , 10842,48 , 20775,71 , 10970,24 , 20846,48 , 20894,71 , 10970,24 , 10924,28 , 10952,53 , 11005,14 , 11019,28 , 11047,53 , 11005,14 , 355,2 , 320,2 , 45,4 , 5,17 , 22,23 , {85,90,83}, 337,3 , 14255,49 , 13,5 , 4,0 , 4178,7 , 4185,10 , 0, 0, 1, 6, 7 }, // Uzbek/Cyrillic/Uzbekistan
- { 132, 7, 232, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 695,8 , 695,8 , 120,10 , 211,18 , 37,5 , 8,10 , 20965,75 , 21040,99 , 158,27 , 21139,75 , 21214,99 , 158,27 , 11100,33 , 11133,55 , 11188,21 , 11100,33 , 11133,55 , 11188,21 , 357,2 , 322,2 , 45,4 , 5,17 , 22,23 , {86,78,68}, 340,1 , 14304,33 , 8,5 , 4,0 , 4195,10 , 4205,8 , 0, 0, 1, 6, 7 }, // Vietnamese/Latin/Vietnam
- { 134, 7, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 10,17 , 37,5 , 8,10 , 21313,52 , 21365,87 , 21452,26 , 21478,59 , 21365,87 , 21452,26 , 11209,29 , 11238,77 , 11315,15 , 11330,30 , 11238,77 , 11315,15 , 359,2 , 324,2 , 935,7 , 5,17 , 22,23 , {71,66,80}, 125,1 , 14337,92 , 4,4 , 4,0 , 4213,7 , 4220,16 , 2, 1, 1, 6, 7 }, // Welsh/Latin/UnitedKingdom
- { 135, 7, 187, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,79,70}, 210,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Wolof/Latin/Senegal
- { 136, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Xhosa/Latin/SouthAfrica
- { 138, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 21537,73 , 21610,121 , 158,27 , 21537,73 , 21610,121 , 158,27 , 11360,44 , 11404,69 , 85,14 , 11360,44 , 11404,69 , 85,14 , 361,5 , 326,5 , 45,4 , 5,17 , 22,23 , {78,71,78}, 184,1 , 14429,34 , 4,4 , 4,0 , 4236,10 , 4246,18 , 2, 1, 1, 6, 7 }, // Yoruba/Latin/Nigeria
- { 138, 7, 23, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 21731,74 , 21805,134 , 158,27 , 21731,74 , 21805,134 , 158,27 , 11473,44 , 11517,69 , 85,14 , 11473,44 , 11517,69 , 85,14 , 366,5 , 331,5 , 45,4 , 5,17 , 22,23 , {88,79,70}, 210,3 , 14463,34 , 4,4 , 4,0 , 4236,10 , 4264,16 , 0, 0, 1, 6, 7 }, // Yoruba/Latin/Benin
- { 140, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 703,9 , 712,8 , 516,6 , 35,18 , 37,5 , 8,10 , 21939,48 , 21987,91 , 134,24 , 21939,48 , 22078,93 , 22171,24 , 11586,28 , 11614,74 , 11688,14 , 11586,28 , 11614,74 , 11688,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {90,65,82}, 5,1 , 14497,67 , 4,4 , 4,0 , 4280,7 , 4287,14 , 2, 1, 7, 6, 7 }, // Zulu/Latin/SouthAfrica
- { 141, 7, 161, 44, 160, 59, 37, 48, 8722, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 183,8 , 183,8 , 931,10 , 469,17 , 37,5 , 367,16 , 5791,48 , 13743,83 , 134,24 , 22195,59 , 13743,83 , 134,24 , 11702,28 , 11730,51 , 2353,14 , 11781,28 , 11730,51 , 2353,14 , 371,9 , 336,11 , 45,4 , 5,17 , 22,23 , {78,79,75}, 196,2 , 14564,42 , 13,5 , 4,0 , 4301,7 , 4308,5 , 2, 1, 1, 6, 7 }, // NorwegianNynorsk/Latin/Norway
- { 142, 7, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8221, 8216, 8217, 0,6 , 0,6 , 154,7 , 154,7 , 995,7 , 441,19 , 37,5 , 8,10 , 16236,48 , 22254,83 , 16212,24 , 16236,48 , 22254,83 , 16212,24 , 2076,28 , 2104,58 , 2162,14 , 2076,28 , 2104,58 , 2176,14 , 380,10 , 347,7 , 276,7 , 5,17 , 22,23 , {66,65,77}, 150,2 , 14606,170 , 13,5 , 4,0 , 4313,8 , 591,19 , 2, 1, 1, 6, 7 }, // Bosnian/Latin/BosniaAndHerzegowina
- { 142, 2, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 107,7 , 107,7 , 995,7 , 1002,20 , 37,5 , 8,10 , 15886,48 , 22337,83 , 12349,24 , 15886,48 , 22337,83 , 12349,24 , 11809,28 , 11837,54 , 8482,14 , 11809,28 , 11837,54 , 8482,14 , 223,9 , 354,7 , 45,4 , 5,17 , 22,23 , {66,65,77}, 302,2 , 14776,151 , 13,5 , 4,0 , 4321,8 , 3459,19 , 2, 1, 1, 6, 7 }, // Bosnian/Cyrillic/BosniaAndHerzegowina
+ { 87, 26, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 539,8 , 547,7 , 547,6 , 35,18 , 18,7 , 25,12 , 14586,86 , 14586,86 , 14672,32 , 14586,86 , 14586,86 , 14672,32 , 7630,33 , 7663,54 , 7717,18 , 7630,33 , 7663,54 , 7717,18 , 0,2 , 0,2 , 737,5 , 5,17 , 22,23 , {73,78,82}, 121,1 , 9884,43 , 4,4 , 4,0 , 3163,5 , 3168,4 , 2, 1, 7, 7, 7 }, // Oriya/Oriya/India
+ { 88, 1, 1, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 46,6 , 46,6 , 554,9 , 563,8 , 394,8 , 1019,20 , 55,4 , 430,11 , 14704,68 , 14772,69 , 158,27 , 14841,69 , 14841,69 , 14910,24 , 7735,39 , 7735,39 , 85,14 , 7735,39 , 7735,39 , 85,14 , 199,4 , 190,4 , 742,5 , 5,17 , 22,23 , {65,70,78}, 263,1 , 9927,25 , 13,5 , 4,0 , 3172,4 , 3176,9 , 0, 0, 6, 4, 5 }, // Pashto/Arabic/Afghanistan
+ { 89, 1, 102, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 171, 187, 8249, 8250, 571,7 , 571,7 , 578,8 , 586,7 , 394,8 , 97,16 , 55,4 , 430,11 , 14934,70 , 14934,70 , 15004,24 , 15028,74 , 15028,74 , 15004,24 , 7774,49 , 7774,49 , 7823,14 , 7774,49 , 7774,49 , 7823,14 , 203,9 , 194,8 , 747,4 , 751,44 , 22,23 , {73,82,82}, 264,4 , 9952,37 , 84,5 , 4,0 , 3185,5 , 3190,5 , 0, 0, 6, 5, 5 }, // Persian/Arabic/Iran
+ { 89, 1, 1, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 171, 187, 8249, 8250, 571,7 , 571,7 , 578,8 , 586,7 , 394,8 , 97,16 , 55,4 , 430,11 , 15102,68 , 15102,68 , 14910,24 , 15170,62 , 15102,68 , 14910,24 , 7774,49 , 7774,49 , 7823,14 , 7774,49 , 7774,49 , 7823,14 , 203,9 , 194,8 , 747,4 , 751,44 , 22,23 , {65,70,78}, 263,1 , 9989,55 , 8,5 , 4,0 , 3195,3 , 3176,9 , 0, 0, 6, 4, 5 }, // Persian/Arabic/Afghanistan
+ { 90, 7, 172, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 171, 187, 0,6 , 0,6 , 163,7 , 163,7 , 495,10 , 10,17 , 37,5 , 8,10 , 15232,48 , 15280,97 , 15377,24 , 15232,48 , 15401,99 , 15500,24 , 7837,34 , 7871,59 , 7930,14 , 7837,34 , 7871,59 , 7944,14 , 0,2 , 0,2 , 303,5 , 5,17 , 22,23 , {80,76,78}, 268,2 , 10044,77 , 13,5 , 4,0 , 3198,6 , 3204,6 , 2, 1, 1, 6, 7 }, // Polish/Latin/Poland
+ { 91, 7, 30, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 254,7 , 254,7 , 119,10 , 669,27 , 37,5 , 8,10 , 15524,48 , 15572,89 , 134,24 , 15524,48 , 15572,89 , 134,24 , 7958,28 , 7986,79 , 8065,14 , 7958,28 , 7986,79 , 8065,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {66,82,76}, 270,2 , 10121,54 , 8,5 , 4,0 , 3210,9 , 3219,6 , 2, 1, 7, 6, 7 }, // Portuguese/Latin/Brazil
+ { 91, 7, 6, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 669,27 , 37,5 , 8,10 , 15524,48 , 15572,89 , 134,24 , 15524,48 , 15572,89 , 134,24 , 8079,49 , 7986,79 , 8065,14 , 8079,49 , 7986,79 , 8065,14 , 212,8 , 202,8 , 0,5 , 5,17 , 22,23 , {65,79,65}, 250,2 , 10175,54 , 13,5 , 4,0 , 3210,9 , 3225,6 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/Angola
+ { 91, 7, 39, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 669,27 , 37,5 , 8,10 , 15524,48 , 15572,89 , 134,24 , 15524,48 , 15572,89 , 134,24 , 8079,49 , 7986,79 , 8065,14 , 8079,49 , 7986,79 , 8065,14 , 212,8 , 202,8 , 0,5 , 5,17 , 22,23 , {67,86,69}, 272,1 , 10229,69 , 13,5 , 4,0 , 3210,9 , 3231,10 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/Cape Verde
+ { 91, 7, 62, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 669,27 , 37,5 , 8,10 , 15524,48 , 15572,89 , 134,24 , 15524,48 , 15572,89 , 134,24 , 8079,49 , 7986,79 , 8065,14 , 8079,49 , 7986,79 , 8065,14 , 212,8 , 202,8 , 0,5 , 5,17 , 22,23 , {85,83,68}, 159,3 , 10298,81 , 13,5 , 4,0 , 3210,9 , 3241,11 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/East Timor
+ { 91, 7, 66, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 669,27 , 37,5 , 8,10 , 15524,48 , 15572,89 , 134,24 , 15524,48 , 15572,89 , 134,24 , 8079,49 , 7986,79 , 8065,14 , 8079,49 , 7986,79 , 8065,14 , 212,8 , 202,8 , 0,5 , 5,17 , 22,23 , {88,65,70}, 32,4 , 10379,59 , 13,5 , 4,0 , 3210,9 , 3252,16 , 0, 0, 1, 6, 7 }, // Portuguese/Latin/Equatorial Guinea
+ { 91, 7, 92, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 669,27 , 37,5 , 8,10 , 15524,48 , 15572,89 , 134,24 , 15524,48 , 15572,89 , 134,24 , 8079,49 , 7986,79 , 8065,14 , 8079,49 , 7986,79 , 8065,14 , 212,8 , 202,8 , 0,5 , 5,17 , 22,23 , {88,79,70}, 204,3 , 10438,62 , 13,5 , 4,0 , 3210,9 , 3268,12 , 0, 0, 1, 6, 7 }, // Portuguese/Latin/Guinea Bissau
+ { 91, 7, 125, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 669,27 , 37,5 , 8,10 , 15524,48 , 15572,89 , 134,24 , 15524,48 , 15572,89 , 134,24 , 8079,49 , 7986,79 , 8065,14 , 8079,49 , 7986,79 , 8065,14 , 212,8 , 202,8 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 3210,9 , 3280,10 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/Luxembourg
+ { 91, 7, 126, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 669,27 , 18,7 , 25,12 , 15524,48 , 15572,89 , 134,24 , 15524,48 , 15572,89 , 134,24 , 8079,49 , 7986,79 , 8065,14 , 8079,49 , 7986,79 , 8065,14 , 212,8 , 202,8 , 0,5 , 5,17 , 22,23 , {77,79,80}, 137,4 , 10500,53 , 13,5 , 4,0 , 3210,9 , 3290,19 , 2, 1, 7, 6, 7 }, // Portuguese/Latin/Macau
+ { 91, 7, 146, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 669,27 , 37,5 , 8,10 , 15524,48 , 15572,89 , 134,24 , 15524,48 , 15572,89 , 134,24 , 8079,49 , 7986,79 , 8065,14 , 8079,49 , 7986,79 , 8065,14 , 212,8 , 202,8 , 0,5 , 5,17 , 22,23 , {77,90,78}, 273,3 , 10553,66 , 13,5 , 4,0 , 3210,9 , 3309,10 , 2, 1, 7, 6, 7 }, // Portuguese/Latin/Mozambique
+ { 91, 7, 173, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 669,27 , 37,5 , 8,10 , 15524,48 , 15572,89 , 134,24 , 15524,48 , 15572,89 , 134,24 , 8079,49 , 7986,79 , 8065,14 , 8079,49 , 7986,79 , 8065,14 , 212,8 , 202,8 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 3319,17 , 3336,8 , 2, 1, 7, 6, 7 }, // Portuguese/Latin/Portugal
+ { 91, 7, 185, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 669,27 , 37,5 , 8,10 , 15524,48 , 15572,89 , 134,24 , 15524,48 , 15572,89 , 134,24 , 8079,49 , 7986,79 , 8065,14 , 8079,49 , 7986,79 , 8065,14 , 212,8 , 202,8 , 0,5 , 5,17 , 22,23 , {83,84,78}, 276,2 , 10619,92 , 13,5 , 4,0 , 3210,9 , 3344,19 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/Sao Tome And Principe
+ { 91, 7, 206, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 669,27 , 37,5 , 8,10 , 15524,48 , 15572,89 , 134,24 , 15524,48 , 15572,89 , 134,24 , 8079,49 , 7986,79 , 8065,14 , 8079,49 , 7986,79 , 8065,14 , 212,8 , 202,8 , 0,5 , 5,17 , 22,23 , {67,72,70}, 221,3 , 10711,45 , 13,5 , 4,0 , 3210,9 , 3363,5 , 2, 0, 1, 6, 7 }, // Portuguese/Latin/Switzerland
+ { 92, 4, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 593,9 , 593,9 , 269,6 , 10,17 , 18,7 , 25,12 , 15661,50 , 15711,68 , 15779,28 , 15661,50 , 15711,68 , 15779,28 , 8128,36 , 8164,57 , 8221,23 , 8128,36 , 8164,57 , 8221,23 , 220,6 , 210,6 , 795,4 , 5,17 , 22,23 , {73,78,82}, 121,1 , 10756,39 , 4,4 , 4,0 , 3368,6 , 3374,4 , 2, 1, 7, 7, 7 }, // Punjabi/Gurmukhi/India
+ { 92, 1, 163, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 553,18 , 18,7 , 25,12 , 15807,67 , 15807,67 , 158,27 , 15807,67 , 15807,67 , 158,27 , 8244,37 , 8244,37 , 85,14 , 8244,37 , 8244,37 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {80,75,82}, 278,1 , 10795,13 , 41,6 , 4,0 , 3378,6 , 3384,7 , 2, 0, 7, 6, 7 }, // Punjabi/Arabic/Pakistan
+ { 93, 7, 169, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 192,18 , 37,5 , 8,10 , 15874,48 , 15922,88 , 158,27 , 15874,48 , 15922,88 , 158,27 , 8281,28 , 8309,53 , 8362,14 , 8281,28 , 8309,53 , 8362,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {80,69,78}, 279,2 , 0,7 , 8,5 , 4,0 , 3391,8 , 3399,4 , 2, 1, 7, 6, 7 }, // Quechua/Latin/Peru
+ { 93, 7, 26, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 192,18 , 37,5 , 8,10 , 15874,48 , 15922,88 , 158,27 , 15874,48 , 15922,88 , 158,27 , 8281,28 , 8309,53 , 8362,14 , 8281,28 , 8309,53 , 8362,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {66,79,66}, 281,2 , 0,7 , 8,5 , 4,0 , 3391,8 , 3403,7 , 2, 1, 1, 6, 7 }, // Quechua/Latin/Bolivia
+ { 93, 7, 63, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 192,18 , 37,5 , 8,10 , 15874,48 , 15922,88 , 158,27 , 15874,48 , 15922,88 , 158,27 , 8281,28 , 8309,53 , 8362,14 , 8281,28 , 8309,53 , 8362,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {85,83,68}, 6,1 , 0,7 , 8,5 , 4,0 , 3391,8 , 3410,7 , 2, 1, 1, 6, 7 }, // Quechua/Latin/Ecuador
+ { 94, 7, 206, 46, 8217, 59, 37, 48, 8722, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 0,6 , 0,6 , 339,8 , 1039,28 , 37,5 , 8,10 , 16010,67 , 16077,92 , 16169,24 , 16010,67 , 16077,92 , 16169,24 , 8376,23 , 8399,56 , 8455,14 , 8376,23 , 8399,56 , 8455,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,72,70}, 221,3 , 10808,46 , 13,5 , 4,0 , 3417,9 , 3426,6 , 2, 0, 1, 6, 7 }, // Romansh/Latin/Switzerland
+ { 95, 7, 177, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8221, 171, 187, 0,6 , 0,6 , 602,8 , 602,8 , 495,10 , 10,17 , 37,5 , 8,10 , 16193,60 , 16253,98 , 16351,24 , 16193,60 , 16253,98 , 16351,24 , 8469,34 , 8503,48 , 3080,14 , 8469,34 , 8503,48 , 3080,14 , 64,4 , 61,4 , 799,4 , 5,17 , 22,23 , {82,79,78}, 283,3 , 10854,57 , 13,5 , 4,0 , 3432,6 , 3438,7 , 2, 1, 1, 6, 7 }, // Romanian/Latin/Romania
+ { 95, 7, 141, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8221, 171, 187, 0,6 , 0,6 , 602,8 , 602,8 , 495,10 , 10,17 , 37,5 , 8,10 , 16193,60 , 16253,98 , 16351,24 , 16193,60 , 16253,98 , 16351,24 , 8551,28 , 8503,48 , 8579,16 , 8551,28 , 8503,48 , 8579,16 , 64,4 , 61,4 , 799,4 , 5,17 , 22,23 , {77,68,76}, 286,1 , 10911,69 , 13,5 , 4,0 , 3432,6 , 3445,17 , 2, 1, 1, 6, 7 }, // Romanian/Latin/Moldova
+ { 96, 2, 178, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 116,7 , 116,7 , 495,10 , 317,22 , 37,5 , 8,10 , 16375,62 , 11141,80 , 11058,24 , 16437,62 , 16499,82 , 11058,24 , 8595,21 , 8616,62 , 8678,14 , 8595,21 , 8616,62 , 8595,21 , 0,2 , 0,2 , 246,5 , 701,17 , 22,23 , {82,85,66}, 123,1 , 10980,89 , 13,5 , 4,0 , 3462,7 , 3469,6 , 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Russia
+ { 96, 2, 20, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 116,7 , 116,7 , 495,10 , 317,22 , 37,5 , 8,10 , 16375,62 , 11141,80 , 11058,24 , 16437,62 , 16499,82 , 11058,24 , 8595,21 , 8616,62 , 8678,14 , 8595,21 , 8616,62 , 8595,21 , 0,2 , 0,2 , 246,5 , 701,17 , 22,23 , {66,89,78}, 0,2 , 11069,94 , 13,5 , 4,0 , 3462,7 , 501,8 , 2, 0, 1, 6, 7 }, // Russian/Cyrillic/Belarus
+ { 96, 2, 110, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 116,7 , 116,7 , 495,10 , 317,22 , 37,5 , 8,10 , 16375,62 , 11141,80 , 11058,24 , 16437,62 , 16499,82 , 11058,24 , 8595,21 , 8616,62 , 8678,14 , 8595,21 , 8616,62 , 8595,21 , 0,2 , 0,2 , 246,5 , 701,17 , 22,23 , {75,90,84}, 240,1 , 11163,83 , 13,5 , 4,0 , 3462,7 , 3475,9 , 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Kazakhstan
+ { 96, 2, 116, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 116,7 , 116,7 , 495,10 , 317,22 , 37,5 , 8,10 , 16375,62 , 11141,80 , 11058,24 , 16437,62 , 16499,82 , 11058,24 , 8595,21 , 8616,62 , 8678,14 , 8595,21 , 8616,62 , 8595,21 , 0,2 , 0,2 , 246,5 , 701,17 , 22,23 , {75,71,83}, 241,3 , 11246,82 , 13,5 , 4,0 , 3462,7 , 3484,8 , 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Kyrgyzstan
+ { 96, 2, 141, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 116,7 , 116,7 , 495,10 , 317,22 , 37,5 , 8,10 , 16375,62 , 11141,80 , 11058,24 , 16437,62 , 16499,82 , 11058,24 , 8595,21 , 8616,62 , 8678,14 , 8595,21 , 8616,62 , 8595,21 , 0,2 , 0,2 , 246,5 , 701,17 , 22,23 , {77,68,76}, 286,1 , 11328,79 , 13,5 , 4,0 , 3462,7 , 3492,7 , 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Moldova
+ { 96, 2, 222, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 116,7 , 116,7 , 495,10 , 317,22 , 37,5 , 8,10 , 16375,62 , 11141,80 , 11058,24 , 16437,62 , 16499,82 , 11058,24 , 8595,21 , 8616,62 , 8678,14 , 8595,21 , 8616,62 , 8595,21 , 0,2 , 0,2 , 246,5 , 701,17 , 22,23 , {85,65,72}, 287,1 , 11407,92 , 13,5 , 4,0 , 3462,7 , 3499,7 , 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Ukraine
+ { 98, 7, 41, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 16581,48 , 16629,91 , 16720,24 , 16581,48 , 16629,91 , 16720,24 , 8692,28 , 8720,66 , 8786,14 , 8692,28 , 8720,66 , 8786,14 , 226,2 , 216,2 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 11499,25 , 4,4 , 36,5 , 3506,5 , 3511,22 , 0, 0, 1, 6, 7 }, // Sango/Latin/Central African Republic
+ { 99, 13, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,78,82}, 121,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 7, 7 }, // Sanskrit/Devanagari/India
+ { 100, 2, 243, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 116,7 , 116,7 , 1067,7 , 1074,20 , 37,5 , 8,10 , 16744,48 , 16792,81 , 12698,24 , 16744,48 , 16792,81 , 12698,24 , 8800,28 , 8828,52 , 8880,14 , 8800,28 , 8828,52 , 8880,14 , 228,9 , 218,8 , 803,7 , 5,17 , 22,23 , {82,83,68}, 288,3 , 11524,58 , 13,5 , 4,0 , 3533,6 , 3539,6 , 0, 0, 1, 6, 7 }, // Serbian/Cyrillic/Serbia
+ { 100, 2, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 116,7 , 116,7 , 1067,7 , 1074,20 , 37,5 , 8,10 , 16873,50 , 16792,81 , 12698,24 , 16744,48 , 16792,81 , 12698,24 , 8894,26 , 8920,55 , 8880,14 , 8894,26 , 8920,55 , 8880,14 , 237,11 , 218,8 , 803,7 , 5,17 , 22,23 , {66,65,77}, 291,2 , 11582,174 , 13,5 , 4,0 , 3533,6 , 3545,19 , 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/Bosnia And Herzegowina
+ { 100, 2, 242, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 116,7 , 116,7 , 1067,7 , 1074,20 , 37,5 , 8,10 , 16923,58 , 16792,81 , 12698,24 , 16923,58 , 16792,81 , 12698,24 , 8975,33 , 8920,55 , 8880,14 , 8975,33 , 8920,55 , 8880,14 , 237,11 , 218,8 , 803,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 11756,23 , 13,5 , 4,0 , 3533,6 , 3564,9 , 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/Montenegro
+ { 100, 2, 257, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 116,7 , 116,7 , 1067,7 , 1074,20 , 37,5 , 8,10 , 16923,58 , 16792,81 , 12698,24 , 16923,58 , 16792,81 , 12698,24 , 8975,33 , 8828,52 , 8880,14 , 8975,33 , 8828,52 , 8880,14 , 228,9 , 218,8 , 803,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 11756,23 , 13,5 , 4,0 , 3533,6 , 3573,6 , 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/Kosovo
+ { 100, 7, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 163,7 , 163,7 , 1067,7 , 1074,20 , 37,5 , 8,10 , 16981,50 , 17031,81 , 9742,24 , 17112,48 , 17031,81 , 9742,24 , 9008,26 , 9034,57 , 2102,14 , 9008,26 , 9034,57 , 2102,14 , 248,11 , 226,8 , 296,7 , 5,17 , 22,23 , {66,65,77}, 144,2 , 11779,174 , 13,5 , 4,0 , 3579,6 , 620,19 , 2, 1, 1, 6, 7 }, // Serbian/Latin/Bosnia And Herzegowina
+ { 100, 7, 242, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 163,7 , 163,7 , 1067,7 , 1074,20 , 37,5 , 8,10 , 17160,58 , 17031,81 , 9742,24 , 17160,58 , 17031,81 , 9742,24 , 9091,33 , 9034,57 , 2102,14 , 9091,33 , 9034,57 , 2102,14 , 248,11 , 226,8 , 296,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 11953,23 , 13,5 , 4,0 , 3579,6 , 3585,9 , 2, 1, 1, 6, 7 }, // Serbian/Latin/Montenegro
+ { 100, 7, 243, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 163,7 , 163,7 , 1067,7 , 1074,20 , 37,5 , 8,10 , 17112,48 , 17031,81 , 9742,24 , 17112,48 , 17031,81 , 9742,24 , 9124,28 , 9152,54 , 2102,14 , 9124,28 , 9152,54 , 2102,14 , 259,9 , 226,8 , 296,7 , 5,17 , 22,23 , {82,83,68}, 288,3 , 11976,58 , 13,5 , 4,0 , 3579,6 , 3594,6 , 0, 0, 1, 6, 7 }, // Serbian/Latin/Serbia
+ { 100, 7, 257, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 163,7 , 163,7 , 1067,7 , 1074,20 , 37,5 , 8,10 , 17160,58 , 17031,81 , 9742,24 , 17160,58 , 17031,81 , 9742,24 , 9091,33 , 9152,54 , 2102,14 , 9091,33 , 9152,54 , 2102,14 , 259,9 , 226,8 , 296,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 11953,23 , 13,5 , 4,0 , 3579,6 , 3600,6 , 2, 1, 1, 6, 7 }, // Serbian/Latin/Kosovo
+ { 101, 2, 81, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 610,9 , 610,9 , 156,8 , 1094,23 , 37,5 , 8,10 , 17218,63 , 17281,82 , 11058,24 , 17363,60 , 17423,86 , 11058,24 , 9206,28 , 9234,61 , 9295,14 , 9309,28 , 9337,61 , 9295,14 , 268,15 , 234,15 , 45,4 , 5,17 , 22,23 , {71,69,76}, 228,1 , 12034,17 , 8,5 , 4,0 , 3606,4 , 3610,11 , 2, 1, 1, 6, 7 }, // Ossetic/Cyrillic/Georgia
+ { 101, 2, 178, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 610,9 , 610,9 , 156,8 , 1094,23 , 37,5 , 8,10 , 17218,63 , 17281,82 , 11058,24 , 17363,60 , 17423,86 , 11058,24 , 9206,28 , 9234,61 , 9295,14 , 9309,28 , 9337,61 , 9295,14 , 268,15 , 234,15 , 45,4 , 5,17 , 22,23 , {82,85,66}, 123,1 , 12051,17 , 8,5 , 4,0 , 3606,4 , 3621,6 , 2, 1, 1, 6, 7 }, // Ossetic/Cyrillic/Russia
+ { 102, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Southern Sotho/Latin/South Africa
+ { 103, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Tswana/Latin/South Africa
+ { 104, 7, 240, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 17509,48 , 17557,100 , 17657,24 , 17509,48 , 17557,100 , 17657,24 , 9398,28 , 9426,55 , 9481,14 , 9398,28 , 9426,55 , 9481,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,83,68}, 159,3 , 12068,22 , 4,4 , 4,0 , 3627,8 , 1791,8 , 2, 1, 7, 6, 7 }, // Shona/Latin/Zimbabwe
+ { 105, 1, 163, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 619,8 , 627,7 , 53,10 , 63,17 , 18,7 , 25,12 , 17681,72 , 17681,72 , 134,24 , 17681,72 , 17681,72 , 134,24 , 9495,35 , 9495,35 , 9530,31 , 9495,35 , 9495,35 , 9530,31 , 283,11 , 249,11 , 810,6 , 816,61 , 22,23 , {80,75,82}, 176,2 , 12090,43 , 8,5 , 4,0 , 3635,4 , 3639,7 , 2, 0, 7, 6, 7 }, // Sindhi/Arabic/Pakistan
+ { 106, 32, 198, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 634,9 , 643,8 , 53,10 , 63,17 , 228,5 , 233,10 , 17753,59 , 17812,96 , 17908,32 , 17940,61 , 17812,96 , 17908,32 , 9561,39 , 9600,62 , 9662,19 , 9561,39 , 9600,62 , 9662,19 , 294,5 , 260,4 , 877,5 , 882,42 , 22,23 , {76,75,82}, 293,3 , 12133,58 , 4,4 , 4,0 , 3646,5 , 3651,11 , 2, 1, 1, 6, 7 }, // Sinhala/Sinhala/Sri Lanka
+ { 107, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Swati/Latin/South Africa
+ { 108, 7, 191, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 185,7 , 651,7 , 1117,10 , 478,17 , 55,4 , 59,9 , 18001,48 , 18049,82 , 9742,24 , 18001,48 , 18131,89 , 9742,24 , 9681,21 , 9702,52 , 9754,14 , 9681,21 , 9702,52 , 9754,14 , 0,2 , 0,2 , 303,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 12191,26 , 13,5 , 4,0 , 3662,10 , 3672,9 , 2, 1, 1, 6, 7 }, // Slovak/Latin/Slovakia
+ { 109, 7, 192, 44, 46, 59, 37, 48, 8722, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 658,8 , 658,8 , 1127,9 , 1136,19 , 37,5 , 8,10 , 18220,59 , 18279,86 , 9742,24 , 18220,59 , 18279,86 , 9742,24 , 9768,35 , 9803,52 , 9855,14 , 9768,35 , 9803,52 , 9855,14 , 60,4 , 264,4 , 54,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 12217,28 , 13,5 , 4,0 , 3681,11 , 3692,9 , 2, 1, 1, 6, 7 }, // Slovenian/Latin/Slovenia
+ { 110, 7, 194, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 666,9 , 666,9 , 27,8 , 1155,19 , 18,7 , 25,12 , 18365,52 , 18417,92 , 18509,24 , 18533,68 , 18601,189 , 18790,24 , 9869,28 , 9897,47 , 9944,15 , 9869,28 , 9897,47 , 9944,15 , 299,3 , 268,3 , 924,4 , 5,17 , 22,23 , {83,79,83}, 94,1 , 12245,27 , 4,4 , 4,0 , 3701,8 , 3709,10 , 0, 0, 1, 6, 7 }, // Somali/Latin/Somalia
+ { 110, 7, 59, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 666,9 , 666,9 , 27,8 , 1155,19 , 18,7 , 25,12 , 18365,52 , 18417,92 , 18509,24 , 18533,68 , 18601,189 , 18790,24 , 9869,28 , 9897,47 , 9944,15 , 9869,28 , 9897,47 , 9944,15 , 299,3 , 268,3 , 924,4 , 5,17 , 22,23 , {68,74,70}, 38,3 , 12272,49 , 4,4 , 4,0 , 3701,8 , 3719,7 , 0, 0, 6, 6, 7 }, // Somali/Latin/Djibouti
+ { 110, 7, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 666,9 , 666,9 , 27,8 , 1155,19 , 18,7 , 25,12 , 18365,52 , 18417,92 , 18509,24 , 18533,68 , 18601,189 , 18790,24 , 9869,28 , 9897,47 , 9944,15 , 9869,28 , 9897,47 , 9944,15 , 299,3 , 268,3 , 924,4 , 5,17 , 22,23 , {69,84,66}, 0,2 , 12321,22 , 4,4 , 4,0 , 3701,8 , 3726,8 , 2, 1, 7, 6, 7 }, // Somali/Latin/Ethiopia
+ { 110, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 666,9 , 666,9 , 27,8 , 1155,19 , 37,5 , 8,10 , 18365,52 , 18417,92 , 18509,24 , 18533,68 , 18601,189 , 18790,24 , 9869,28 , 9897,47 , 9944,15 , 9869,28 , 9897,47 , 9944,15 , 299,3 , 268,3 , 924,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 12343,50 , 4,4 , 4,0 , 3701,8 , 1182,5 , 2, 1, 7, 6, 7 }, // Somali/Latin/Kenya
+ { 111, 7, 197, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 675,7 , 675,7 , 269,6 , 669,27 , 55,4 , 430,11 , 18814,61 , 18875,89 , 18964,24 , 18814,61 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 8362,14 , 9959,35 , 9994,53 , 8362,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 3734,17 , 2398,6 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Spain
+ { 111, 7, 10, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 675,7 , 675,7 , 269,6 , 669,27 , 37,5 , 8,10 , 18988,60 , 18875,89 , 18964,24 , 18988,60 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 3080,14 , 9959,35 , 9994,53 , 3080,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {65,82,83}, 6,1 , 12393,51 , 8,5 , 4,0 , 3751,7 , 3758,9 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Argentina
+ { 111, 7, 22, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 675,7 , 675,7 , 269,6 , 669,27 , 37,5 , 8,10 , 18988,60 , 18875,89 , 18964,24 , 18988,60 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 3080,14 , 9959,35 , 9994,53 , 4769,14 , 64,4 , 61,4 , 0,5 , 5,17 , 22,23 , {66,90,68}, 6,1 , 12444,52 , 4,4 , 4,0 , 3751,7 , 3767,6 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Belize
+ { 111, 7, 26, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 675,7 , 675,7 , 269,6 , 669,27 , 37,5 , 8,10 , 18988,60 , 18875,89 , 18964,24 , 18988,60 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 3080,14 , 9959,35 , 9994,53 , 4769,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {66,79,66}, 281,2 , 12496,35 , 4,4 , 4,0 , 3751,7 , 3403,7 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Bolivia
+ { 111, 7, 30, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 675,7 , 675,7 , 269,6 , 669,27 , 37,5 , 8,10 , 18988,60 , 18875,89 , 18964,24 , 18988,60 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 3080,14 , 9959,35 , 9994,53 , 4769,14 , 64,4 , 61,4 , 0,5 , 5,17 , 22,23 , {66,82,76}, 270,2 , 12531,52 , 4,4 , 4,0 , 3751,7 , 3219,6 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Brazil
+ { 111, 7, 43, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 675,7 , 675,7 , 339,8 , 669,27 , 37,5 , 8,10 , 18814,61 , 18875,89 , 18964,24 , 18988,60 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 3080,14 , 9959,35 , 9994,53 , 4769,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {67,76,80}, 6,1 , 12583,45 , 4,4 , 36,5 , 3751,7 , 3773,5 , 0, 0, 1, 6, 7 }, // Spanish/Latin/Chile
+ { 111, 7, 47, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 675,7 , 675,7 , 571,7 , 669,27 , 18,7 , 25,12 , 18814,61 , 18875,89 , 18964,24 , 18988,60 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 4769,14 , 9959,35 , 9994,53 , 3080,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {67,79,80}, 6,1 , 12628,54 , 8,5 , 4,0 , 3751,7 , 3778,8 , 2, 0, 7, 6, 7 }, // Spanish/Latin/Colombia
+ { 111, 7, 52, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 675,7 , 675,7 , 269,6 , 669,27 , 37,5 , 8,10 , 18988,60 , 18875,89 , 18964,24 , 18988,60 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 3080,14 , 9959,35 , 9994,53 , 4769,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {67,82,67}, 296,1 , 12682,67 , 4,4 , 4,0 , 3751,7 , 3786,10 , 2, 0, 1, 6, 7 }, // Spanish/Latin/Costa Rica
+ { 111, 7, 55, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 675,7 , 675,7 , 269,6 , 669,27 , 37,5 , 8,10 , 18988,60 , 18875,89 , 18964,24 , 18988,60 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 3080,14 , 9959,35 , 9994,53 , 4769,14 , 64,4 , 61,4 , 0,5 , 5,17 , 22,23 , {67,85,80}, 6,1 , 12749,42 , 4,4 , 4,0 , 3751,7 , 3796,4 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Cuba
+ { 111, 7, 61, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 675,7 , 675,7 , 269,6 , 669,27 , 18,7 , 25,12 , 18988,60 , 18875,89 , 18964,24 , 18988,60 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 3080,14 , 9959,35 , 9994,53 , 3080,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {68,79,80}, 297,3 , 12791,54 , 4,4 , 89,6 , 3751,7 , 3800,20 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Dominican Republic
+ { 111, 7, 63, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 675,7 , 675,7 , 269,6 , 669,27 , 37,5 , 8,10 , 18988,60 , 18875,89 , 18964,24 , 18988,60 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 3080,14 , 9959,35 , 9994,53 , 4769,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 12845,70 , 4,4 , 36,5 , 3751,7 , 3410,7 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Ecuador
+ { 111, 7, 65, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 675,7 , 675,7 , 269,6 , 669,27 , 37,5 , 8,10 , 18988,60 , 18875,89 , 18964,24 , 18988,60 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 3080,14 , 9959,35 , 9994,53 , 4769,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 12845,70 , 4,4 , 4,0 , 3751,7 , 3820,11 , 2, 1, 7, 6, 7 }, // Spanish/Latin/El Salvador
+ { 111, 7, 66, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 675,7 , 675,7 , 269,6 , 669,27 , 55,4 , 430,11 , 18814,61 , 18875,89 , 18964,24 , 18814,61 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 8362,14 , 9959,35 , 9994,53 , 8362,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {88,65,70}, 32,4 , 12915,92 , 4,4 , 4,0 , 3751,7 , 3831,17 , 0, 0, 1, 6, 7 }, // Spanish/Latin/Equatorial Guinea
+ { 111, 7, 90, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 675,7 , 675,7 , 571,7 , 669,27 , 37,5 , 8,10 , 18988,60 , 18875,89 , 18964,24 , 18988,60 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 3080,14 , 9959,35 , 9994,53 , 4769,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {71,84,81}, 300,1 , 13007,30 , 18,5 , 4,0 , 3751,7 , 3848,9 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Guatemala
+ { 111, 7, 96, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 675,7 , 675,7 , 269,6 , 1174,27 , 37,5 , 8,10 , 18988,60 , 18875,89 , 18964,24 , 18988,60 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 3080,14 , 9959,35 , 9994,53 , 4769,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {72,78,76}, 286,1 , 13037,60 , 4,4 , 4,0 , 3751,7 , 3857,8 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Honduras
+ { 111, 7, 139, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 675,7 , 675,7 , 27,8 , 669,27 , 55,4 , 59,9 , 18988,60 , 18875,89 , 18964,24 , 19048,48 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 3080,14 , 9959,35 , 9994,53 , 3080,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {77,88,78}, 6,1 , 13097,48 , 47,6 , 4,0 , 3865,17 , 3882,6 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Mexico
+ { 111, 7, 155, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 675,7 , 675,7 , 269,6 , 669,27 , 37,5 , 8,10 , 18988,60 , 18875,89 , 18964,24 , 18988,60 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 3080,14 , 9959,35 , 9994,53 , 4769,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {78,73,79}, 301,2 , 13145,69 , 4,4 , 4,0 , 3751,7 , 3888,9 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Nicaragua
+ { 111, 7, 166, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 675,7 , 675,7 , 1201,8 , 669,27 , 18,7 , 25,12 , 18988,60 , 18875,89 , 18964,24 , 18988,60 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 3080,14 , 9959,35 , 9994,53 , 4769,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {80,65,66}, 303,3 , 13214,54 , 4,4 , 4,0 , 3751,7 , 3897,6 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Panama
+ { 111, 7, 168, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 675,7 , 675,7 , 269,6 , 669,27 , 37,5 , 8,10 , 18814,61 , 18875,89 , 18964,24 , 18814,61 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 3080,14 , 9959,35 , 9994,53 , 4769,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {80,89,71}, 306,3 , 13268,61 , 8,5 , 23,6 , 3751,7 , 3903,8 , 0, 0, 7, 6, 7 }, // Spanish/Latin/Paraguay
+ { 111, 7, 169, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 675,7 , 675,7 , 571,7 , 669,27 , 37,5 , 8,10 , 19096,60 , 15922,88 , 18964,24 , 19156,60 , 19216,88 , 18964,24 , 9959,35 , 9994,53 , 3080,14 , 9959,35 , 9994,53 , 4769,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {80,69,78}, 279,2 , 13329,43 , 4,4 , 4,0 , 3751,7 , 3399,4 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Peru
+ { 111, 7, 170, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 675,7 , 675,7 , 269,6 , 669,27 , 18,7 , 25,12 , 18814,61 , 18875,89 , 18964,24 , 18814,61 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 8362,14 , 9959,35 , 9994,53 , 8362,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {80,72,80}, 179,1 , 13372,48 , 13,5 , 4,0 , 3751,7 , 3911,9 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Philippines
+ { 111, 7, 174, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 675,7 , 675,7 , 1201,8 , 669,27 , 18,7 , 25,12 , 18988,60 , 18875,89 , 18964,24 , 18988,60 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 3080,14 , 9959,35 , 9994,53 , 4769,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 12845,70 , 4,4 , 4,0 , 3751,7 , 1437,11 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Puerto Rico
+ { 111, 7, 225, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 675,7 , 675,7 , 415,8 , 669,27 , 18,7 , 25,12 , 18988,60 , 18875,89 , 18964,24 , 18988,60 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 3080,14 , 9959,35 , 9994,53 , 3080,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 12845,70 , 95,7 , 4,0 , 3751,7 , 3920,14 , 2, 1, 7, 6, 7 }, // Spanish/Latin/United States
+ { 111, 7, 227, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 675,7 , 675,7 , 269,6 , 669,27 , 37,5 , 8,10 , 19096,60 , 15922,88 , 18964,24 , 19156,60 , 19216,88 , 18964,24 , 9959,35 , 9994,53 , 3080,14 , 9959,35 , 9994,53 , 4769,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {85,89,85}, 6,1 , 13420,48 , 8,5 , 4,0 , 3751,7 , 3934,7 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Uruguay
+ { 111, 7, 231, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 675,7 , 675,7 , 269,6 , 669,27 , 18,7 , 25,12 , 18814,61 , 18875,89 , 18964,24 , 18814,61 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 3080,14 , 9959,35 , 9994,53 , 4769,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {86,69,83}, 309,4 , 13468,58 , 4,4 , 36,5 , 3751,7 , 3941,9 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Venezuela
+ { 111, 7, 238, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 675,7 , 675,7 , 269,6 , 669,27 , 55,4 , 430,11 , 18814,61 , 18875,89 , 18964,24 , 18814,61 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 8362,14 , 9959,35 , 9994,53 , 8362,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 3751,7 , 3950,8 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Canary Islands
+ { 111, 7, 246, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 675,7 , 675,7 , 269,6 , 669,27 , 37,5 , 8,10 , 18988,60 , 18875,89 , 18964,24 , 18988,60 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 3080,14 , 9959,35 , 9994,53 , 4769,14 , 64,4 , 61,4 , 0,5 , 5,17 , 22,23 , {0,0,0}, 0,0 , 2586,0 , 4,4 , 4,0 , 3958,23 , 3981,13 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Latin America
+ { 111, 7, 250, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 675,7 , 675,7 , 269,6 , 669,27 , 55,4 , 430,11 , 18814,61 , 18875,89 , 18964,24 , 18814,61 , 18875,89 , 18964,24 , 9959,35 , 9994,53 , 8362,14 , 9959,35 , 9994,53 , 8362,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 3751,7 , 3994,15 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Ceuta And Melilla
+ { 113, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 682,8 , 682,8 , 119,10 , 10,17 , 37,5 , 8,10 , 19304,48 , 19352,84 , 134,24 , 19304,48 , 19352,84 , 134,24 , 10047,60 , 10047,60 , 85,14 , 10047,60 , 10047,60 , 85,14 , 0,2 , 0,2 , 644,5 , 928,51 , 22,23 , {84,90,83}, 192,3 , 13526,67 , 8,5 , 4,0 , 4009,9 , 1616,8 , 2, 0, 1, 6, 7 }, // Swahili/Latin/Tanzania
+ { 113, 7, 49, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 682,8 , 682,8 , 119,10 , 10,17 , 37,5 , 8,10 , 19304,48 , 19352,84 , 134,24 , 19304,48 , 19352,84 , 134,24 , 10047,60 , 10047,60 , 85,14 , 10047,60 , 10047,60 , 85,14 , 0,2 , 0,2 , 644,5 , 928,51 , 22,23 , {67,68,70}, 207,2 , 13593,55 , 8,5 , 4,0 , 4009,9 , 4018,32 , 2, 1, 1, 6, 7 }, // Swahili/Latin/Congo Kinshasa
+ { 113, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 682,8 , 682,8 , 119,10 , 10,17 , 37,5 , 8,10 , 19304,48 , 19352,84 , 134,24 , 19304,48 , 19352,84 , 134,24 , 10047,60 , 10047,60 , 85,14 , 10047,60 , 10047,60 , 85,14 , 0,2 , 0,2 , 644,5 , 928,51 , 22,23 , {75,69,83}, 2,3 , 13648,58 , 8,5 , 4,0 , 4009,9 , 1182,5 , 2, 1, 7, 6, 7 }, // Swahili/Latin/Kenya
+ { 113, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 682,8 , 682,8 , 119,10 , 10,17 , 37,5 , 8,10 , 19304,48 , 19352,84 , 134,24 , 19304,48 , 19352,84 , 134,24 , 10047,60 , 10047,60 , 85,14 , 10047,60 , 10047,60 , 85,14 , 0,2 , 0,2 , 644,5 , 928,51 , 22,23 , {85,71,88}, 197,3 , 13706,61 , 8,5 , 4,0 , 4009,9 , 1681,6 , 0, 0, 1, 6, 7 }, // Swahili/Latin/Uganda
+ { 114, 7, 205, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 690,9 , 690,9 , 53,10 , 97,16 , 37,5 , 441,16 , 19436,59 , 19495,86 , 134,24 , 19436,59 , 19495,86 , 134,24 , 10107,29 , 10136,50 , 2293,14 , 10107,29 , 10136,50 , 2293,14 , 302,2 , 271,2 , 45,4 , 5,17 , 22,23 , {83,69,75}, 190,2 , 13767,45 , 13,5 , 4,0 , 4050,7 , 4057,7 , 2, 0, 1, 6, 7 }, // Swedish/Latin/Sweden
+ { 114, 7, 73, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 690,9 , 690,9 , 528,10 , 97,16 , 37,5 , 441,16 , 19436,59 , 19495,86 , 134,24 , 19436,59 , 19495,86 , 134,24 , 10107,29 , 10136,50 , 2293,14 , 10107,29 , 10136,50 , 2293,14 , 302,2 , 271,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8897,19 , 13,5 , 4,0 , 4050,7 , 1079,7 , 2, 1, 1, 6, 7 }, // Swedish/Latin/Finland
+ { 114, 7, 248, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 690,9 , 690,9 , 53,10 , 97,16 , 37,5 , 441,16 , 19436,59 , 19495,86 , 134,24 , 19436,59 , 19495,86 , 134,24 , 10107,29 , 10136,50 , 2293,14 , 10107,29 , 10136,50 , 2293,14 , 302,2 , 271,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8897,19 , 13,5 , 4,0 , 4050,7 , 4064,5 , 2, 1, 1, 6, 7 }, // Swedish/Latin/Aland Islands
+ { 115, 7, 106, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Sardinian/Latin/Italy
+ { 116, 2, 209, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 553,18 , 37,5 , 8,10 , 10930,48 , 19581,71 , 11058,24 , 10930,48 , 19581,71 , 11058,24 , 10186,28 , 10214,55 , 10269,14 , 10186,28 , 10214,55 , 10269,14 , 304,7 , 273,7 , 45,4 , 5,17 , 22,23 , {84,74,83}, 313,4 , 13812,19 , 13,5 , 4,0 , 4069,6 , 4075,10 , 2, 1, 1, 6, 7 }, // Tajik/Cyrillic/Tajikistan
+ { 117, 27, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 699,13 , 699,13 , 269,6 , 192,18 , 382,7 , 457,12 , 19652,58 , 19710,86 , 19796,31 , 19652,58 , 19710,86 , 19796,31 , 10283,39 , 10322,49 , 10371,20 , 10283,39 , 10322,49 , 10371,20 , 311,8 , 280,8 , 979,7 , 5,17 , 22,23 , {73,78,82}, 121,1 , 13831,49 , 8,5 , 4,0 , 4085,5 , 4090,7 , 2, 1, 7, 7, 7 }, // Tamil/Tamil/India
+ { 117, 27, 130, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 699,13 , 699,13 , 269,6 , 192,18 , 382,7 , 457,12 , 19652,58 , 19710,86 , 19796,31 , 19652,58 , 19710,86 , 19796,31 , 10283,39 , 10322,49 , 10371,20 , 10283,39 , 10322,49 , 10371,20 , 311,8 , 280,8 , 979,7 , 5,17 , 22,23 , {77,89,82}, 174,2 , 13880,61 , 8,5 , 4,0 , 4085,5 , 4097,7 , 2, 1, 1, 6, 7 }, // Tamil/Tamil/Malaysia
+ { 117, 27, 190, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 699,13 , 699,13 , 269,6 , 192,18 , 382,7 , 457,12 , 19652,58 , 19710,86 , 19796,31 , 19652,58 , 19710,86 , 19796,31 , 10283,39 , 10322,49 , 10371,20 , 10283,39 , 10322,49 , 10371,20 , 311,8 , 280,8 , 979,7 , 5,17 , 22,23 , {83,71,68}, 6,1 , 13941,61 , 8,5 , 4,0 , 4085,5 , 4104,11 , 2, 1, 7, 6, 7 }, // Tamil/Tamil/Singapore
+ { 117, 27, 198, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 699,13 , 699,13 , 269,6 , 192,18 , 37,5 , 8,10 , 19652,58 , 19710,86 , 19796,31 , 19652,58 , 19710,86 , 19796,31 , 10283,39 , 10322,49 , 10371,20 , 10283,39 , 10322,49 , 10371,20 , 311,8 , 280,8 , 979,7 , 5,17 , 22,23 , {76,75,82}, 317,3 , 14002,49 , 8,5 , 4,0 , 4085,5 , 4115,6 , 2, 1, 1, 6, 7 }, // Tamil/Tamil/Sri Lanka
+ { 118, 2, 178, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 712,9 , 712,9 , 495,10 , 1209,23 , 55,4 , 59,9 , 19827,62 , 19889,81 , 158,27 , 19827,62 , 19889,81 , 158,27 , 10391,36 , 10427,56 , 10483,14 , 10391,36 , 10427,56 , 10483,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {82,85,66}, 123,1 , 14051,21 , 0,4 , 4,0 , 4121,5 , 3469,6 , 2, 1, 1, 6, 7 }, // Tatar/Cyrillic/Russia
+ { 119, 28, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 721,11 , 721,11 , 339,8 , 1232,18 , 18,7 , 25,12 , 19970,62 , 20032,86 , 20118,31 , 19970,62 , 20032,86 , 20118,31 , 10497,32 , 10529,60 , 10589,18 , 10497,32 , 10529,60 , 10589,18 , 0,2 , 0,2 , 986,7 , 993,29 , 22,23 , {73,78,82}, 121,1 , 14072,26 , 4,4 , 4,0 , 4126,6 , 4132,8 , 2, 1, 7, 7, 7 }, // Telugu/Telugu/India
+ { 120, 30, 211, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 123,5 , 123,5 , 732,8 , 740,7 , 269,6 , 1250,19 , 37,5 , 469,28 , 20149,63 , 20212,98 , 20149,63 , 20149,63 , 20212,98 , 20149,63 , 10607,23 , 10630,68 , 10698,16 , 10607,23 , 10630,68 , 10698,16 , 319,10 , 288,10 , 1022,4 , 5,17 , 22,23 , {84,72,66}, 320,1 , 14098,16 , 4,4 , 4,0 , 4140,3 , 4140,3 , 2, 1, 7, 6, 7 }, // Thai/Thai/Thailand
+ { 121, 31, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 1269,23 , 18,7 , 25,12 , 2675,63 , 20310,159 , 158,27 , 2675,63 , 20469,147 , 158,27 , 10714,51 , 10765,79 , 10844,27 , 10714,51 , 10765,79 , 10844,27 , 329,7 , 298,8 , 45,4 , 5,17 , 22,23 , {67,78,89}, 321,1 , 14114,13 , 8,5 , 4,0 , 4143,8 , 4151,6 , 2, 1, 7, 6, 7 }, // Tibetan/Tibetan/China
+ { 121, 31, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 1269,23 , 18,7 , 25,12 , 2675,63 , 20310,159 , 158,27 , 2675,63 , 20469,147 , 158,27 , 10714,51 , 10765,79 , 10844,27 , 10714,51 , 10765,79 , 10844,27 , 329,7 , 298,8 , 45,4 , 5,17 , 22,23 , {73,78,82}, 121,1 , 14127,19 , 8,5 , 4,0 , 4143,8 , 4157,7 , 2, 1, 7, 7, 7 }, // Tibetan/Tibetan/India
+ { 122, 14, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1292,23 , 18,7 , 25,12 , 20616,36 , 20652,54 , 20706,24 , 20616,36 , 20652,54 , 20706,24 , 10871,21 , 10892,29 , 10921,14 , 10871,21 , 10892,29 , 10935,14 , 336,7 , 306,7 , 45,4 , 5,17 , 22,23 , {69,84,66}, 0,2 , 14146,16 , 4,4 , 4,0 , 4164,4 , 82,5 , 2, 1, 7, 6, 7 }, // Tigrinya/Ethiopic/Ethiopia
+ { 122, 14, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1292,23 , 18,7 , 25,12 , 20616,36 , 20652,54 , 20706,24 , 20616,36 , 20652,54 , 20706,24 , 10871,21 , 10892,29 , 10935,14 , 10871,21 , 10892,29 , 10935,14 , 336,7 , 306,7 , 45,4 , 5,17 , 22,23 , {69,82,78}, 41,3 , 0,7 , 4,4 , 4,0 , 4164,4 , 4168,4 , 2, 1, 1, 6, 7 }, // Tigrinya/Ethiopic/Eritrea
+ { 123, 7, 214, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 747,8 , 747,8 , 747,8 , 747,8 , 269,6 , 97,16 , 18,7 , 25,12 , 20730,51 , 20781,87 , 20868,24 , 20730,51 , 20781,87 , 20868,24 , 10949,29 , 10978,60 , 11038,14 , 10949,29 , 10978,60 , 11038,14 , 343,10 , 313,6 , 1026,5 , 1031,59 , 1090,65 , {84,79,80}, 195,2 , 14162,41 , 13,5 , 4,0 , 4172,13 , 1631,5 , 2, 1, 1, 6, 7 }, // Tongan/Latin/Tonga
+ { 124, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Tsonga/Latin/South Africa
+ { 125, 7, 217, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 755,8 , 755,8 , 1315,9 , 1324,16 , 37,5 , 8,10 , 20892,48 , 20940,75 , 21015,24 , 20892,48 , 20940,75 , 21015,24 , 11052,28 , 11080,54 , 11134,14 , 11052,28 , 11080,54 , 11134,14 , 353,2 , 319,2 , 199,4 , 5,17 , 22,23 , {84,82,89}, 248,1 , 14203,40 , 4,4 , 4,0 , 4185,6 , 4191,7 , 2, 1, 1, 6, 7 }, // Turkish/Latin/Turkey
+ { 125, 7, 56, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 755,8 , 755,8 , 1315,9 , 1324,16 , 18,7 , 25,12 , 20892,48 , 20940,75 , 21015,24 , 20892,48 , 20940,75 , 21015,24 , 11052,28 , 11080,54 , 11134,14 , 11052,28 , 11080,54 , 11134,14 , 353,2 , 319,2 , 199,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8384,19 , 4,4 , 4,0 , 4185,6 , 4198,6 , 2, 1, 1, 6, 7 }, // Turkish/Latin/Cyprus
+ { 126, 7, 218, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8220, 8221, 0,6 , 0,6 , 763,8 , 763,8 , 495,10 , 1324,16 , 37,5 , 8,10 , 21039,50 , 21089,77 , 21166,24 , 21190,51 , 21241,77 , 21166,24 , 11148,28 , 11176,54 , 11230,14 , 11244,28 , 11272,54 , 11230,14 , 355,13 , 321,14 , 1155,4 , 5,17 , 22,23 , {84,77,84}, 322,3 , 14243,49 , 13,5 , 4,0 , 4204,12 , 4216,12 , 2, 1, 1, 6, 7 }, // Turkmen/Latin/Turkmenistan
+ { 128, 1, 44, 46, 44, 59, 37, 48, 45, 43, 101, 187, 171, 8250, 8249, 0,6 , 0,6 , 200,10 , 210,9 , 53,10 , 1340,17 , 18,7 , 25,12 , 21318,84 , 21318,84 , 158,27 , 21318,84 , 21318,84 , 158,27 , 11326,21 , 11347,55 , 11402,14 , 11326,21 , 11347,55 , 11402,14 , 368,12 , 335,12 , 45,4 , 5,17 , 22,23 , {67,78,89}, 133,1 , 14292,40 , 4,4 , 4,0 , 4228,8 , 4236,5 , 2, 1, 7, 6, 7 }, // Uighur/Arabic/China
+ { 129, 2, 222, 44, 160, 59, 37, 48, 45, 43, 1077, 171, 187, 8222, 8220, 0,6 , 0,6 , 138,7 , 138,7 , 156,8 , 1357,22 , 37,5 , 8,10 , 21402,48 , 21450,95 , 21545,24 , 21569,67 , 21636,87 , 21723,24 , 1427,21 , 11416,56 , 11472,14 , 1427,21 , 11416,56 , 11472,14 , 380,2 , 347,2 , 1159,5 , 701,17 , 22,23 , {85,65,72}, 287,1 , 14332,49 , 13,5 , 4,0 , 4241,10 , 4251,7 , 2, 1, 1, 6, 7 }, // Ukrainian/Cyrillic/Ukraine
+ { 130, 1, 163, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 771,10 , 781,9 , 269,6 , 1379,18 , 18,7 , 25,12 , 21747,68 , 21747,68 , 134,24 , 21747,68 , 21747,68 , 134,24 , 11486,36 , 11486,36 , 85,14 , 11486,36 , 11486,36 , 85,14 , 0,2 , 0,2 , 1164,4 , 1168,20 , 22,23 , {80,75,82}, 176,2 , 14381,49 , 4,4 , 4,0 , 4258,4 , 3384,7 , 2, 0, 7, 6, 7 }, // Urdu/Arabic/Pakistan
+ { 130, 1, 100, 1643, 1644, 59, 37, 1776, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 790,6 , 790,6 , 269,6 , 1379,18 , 18,7 , 25,12 , 21747,68 , 21747,68 , 134,24 , 21747,68 , 21747,68 , 134,24 , 11486,36 , 11486,36 , 85,14 , 11486,36 , 11486,36 , 85,14 , 0,2 , 0,2 , 1164,4 , 1168,20 , 22,23 , {73,78,82}, 121,1 , 14430,42 , 8,5 , 4,0 , 4258,4 , 4262,5 , 2, 1, 7, 7, 7 }, // Urdu/Arabic/India
+ { 131, 7, 228, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8217, 8216, 0,6 , 0,6 , 796,8 , 796,8 , 27,8 , 1397,18 , 37,5 , 430,11 , 21815,48 , 21863,75 , 21938,24 , 21962,48 , 22010,75 , 21938,24 , 11522,32 , 11554,61 , 11615,14 , 11522,32 , 11554,61 , 11615,14 , 382,2 , 349,2 , 199,4 , 323,17 , 22,23 , {85,90,83}, 325,4 , 14472,58 , 13,5 , 4,0 , 4267,6 , 4273,11 , 2, 0, 1, 6, 7 }, // Uzbek/Latin/Uzbekistan
+ { 131, 1, 1, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 394,8 , 1415,33 , 55,4 , 430,11 , 22085,47 , 15102,68 , 158,27 , 22085,47 , 15102,68 , 158,27 , 11629,21 , 7774,49 , 85,14 , 11629,21 , 7774,49 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {65,70,78}, 263,1 , 14530,13 , 13,5 , 4,0 , 4284,6 , 3176,9 , 0, 0, 6, 4, 5 }, // Uzbek/Arabic/Afghanistan
+ { 131, 2, 228, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 696,19 , 37,5 , 87,12 , 22132,48 , 22180,71 , 11058,24 , 22132,48 , 22180,71 , 11058,24 , 11650,28 , 11678,53 , 11731,14 , 11650,28 , 11678,53 , 11731,14 , 384,2 , 351,2 , 45,4 , 5,17 , 22,23 , {85,90,83}, 329,3 , 14543,49 , 13,5 , 4,0 , 4290,7 , 4297,10 , 2, 0, 1, 6, 7 }, // Uzbek/Cyrillic/Uzbekistan
+ { 132, 7, 232, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 804,8 , 804,8 , 119,10 , 192,18 , 37,5 , 8,10 , 22251,75 , 22326,99 , 158,27 , 22425,75 , 22500,99 , 158,27 , 11745,33 , 11778,55 , 11833,21 , 11745,33 , 11778,55 , 11833,21 , 386,2 , 353,2 , 45,4 , 5,17 , 22,23 , {86,78,68}, 332,1 , 14592,33 , 13,5 , 4,0 , 4307,10 , 4317,8 , 0, 0, 1, 6, 7 }, // Vietnamese/Latin/Vietnam
+ { 133, 7, 260, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 1448,23 , 37,5 , 8,10 , 22599,48 , 22647,74 , 22721,24 , 22745,48 , 22647,74 , 22721,24 , 11854,21 , 11875,43 , 11918,14 , 11932,28 , 11875,43 , 11918,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {0,0,0}, 0,0 , 2586,0 , 8,5 , 4,0 , 4325,7 , 0,0 , 2, 1, 1, 6, 7 }, // Volapuk/Latin/World
+ { 134, 7, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 812,11 , 823,10 , 27,8 , 10,17 , 37,5 , 8,10 , 22793,52 , 22845,87 , 22932,26 , 22958,59 , 22845,87 , 22932,26 , 11960,29 , 11989,77 , 12066,15 , 12081,30 , 11989,77 , 12066,15 , 388,2 , 355,2 , 1188,7 , 5,17 , 22,23 , {71,66,80}, 119,1 , 14625,92 , 4,4 , 4,0 , 4332,7 , 4339,16 , 2, 1, 1, 6, 7 }, // Welsh/Latin/United Kingdom
+ { 135, 7, 187, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 528,10 , 1471,17 , 37,5 , 8,10 , 23017,47 , 23064,84 , 158,27 , 23017,47 , 23064,84 , 158,27 , 12111,28 , 12139,50 , 12111,28 , 12111,28 , 12139,50 , 12111,28 , 390,3 , 357,3 , 45,4 , 5,17 , 22,23 , {88,79,70}, 204,3 , 14717,65 , 8,5 , 4,0 , 4355,5 , 4360,8 , 0, 0, 1, 6, 7 }, // Wolof/Latin/Senegal
+ { 136, 7, 195, 46, 160, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 23148,48 , 23196,91 , 158,27 , 23148,48 , 23196,91 , 158,27 , 12189,28 , 12217,61 , 85,14 , 12189,28 , 12217,61 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 14782,79 , 4,4 , 4,0 , 4368,8 , 4376,15 , 2, 1, 7, 6, 7 }, // Xhosa/Latin/South Africa
+ { 137, 18, 260, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 833,9 , 833,9 , 27,8 , 1488,19 , 37,5 , 8,10 , 23287,58 , 23345,92 , 158,27 , 23345,92 , 23345,92 , 158,27 , 12278,54 , 12278,54 , 85,14 , 12278,54 , 12278,54 , 85,14 , 393,11 , 360,10 , 45,4 , 5,17 , 22,23 , {0,0,0}, 0,0 , 2586,0 , 41,6 , 4,0 , 4391,6 , 4397,5 , 2, 1, 1, 6, 7 }, // Yiddish/Hebrew/World
+ { 138, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 23437,73 , 23510,121 , 158,27 , 23437,73 , 23510,121 , 158,27 , 12332,44 , 12376,69 , 85,14 , 12332,44 , 12376,69 , 85,14 , 404,5 , 370,5 , 45,4 , 5,17 , 22,23 , {78,71,78}, 178,1 , 14861,34 , 4,4 , 4,0 , 4402,10 , 4412,18 , 2, 1, 1, 6, 7 }, // Yoruba/Latin/Nigeria
+ { 138, 7, 23, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 23631,74 , 23705,134 , 158,27 , 23631,74 , 23705,134 , 158,27 , 12445,44 , 12489,69 , 85,14 , 12445,44 , 12489,69 , 85,14 , 409,5 , 375,5 , 45,4 , 5,17 , 22,23 , {88,79,70}, 204,3 , 14895,34 , 4,4 , 4,0 , 4402,10 , 4430,16 , 0, 0, 1, 6, 7 }, // Yoruba/Latin/Benin
+ { 140, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 842,9 , 851,8 , 547,6 , 35,18 , 37,5 , 8,10 , 23839,48 , 23887,91 , 134,24 , 23839,48 , 23887,91 , 23978,24 , 12558,28 , 12586,74 , 12660,14 , 12558,28 , 12586,74 , 12660,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {90,65,82}, 5,1 , 14929,67 , 4,4 , 4,0 , 4446,7 , 4453,17 , 2, 1, 7, 6, 7 }, // Zulu/Latin/South Africa
+ { 141, 7, 161, 44, 160, 59, 37, 48, 8722, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 192,8 , 192,8 , 495,10 , 478,17 , 37,5 , 441,16 , 5656,48 , 14503,83 , 134,24 , 24002,59 , 14503,83 , 134,24 , 12674,28 , 12702,51 , 2293,14 , 12753,28 , 12702,51 , 2293,14 , 414,9 , 380,11 , 45,4 , 5,17 , 22,23 , {78,79,75}, 190,2 , 9840,44 , 13,5 , 4,0 , 4470,7 , 4477,5 , 2, 0, 1, 6, 7 }, // Norwegian Nynorsk/Latin/Norway
+ { 142, 7, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8221, 8216, 8217, 0,6 , 0,6 , 163,7 , 163,7 , 1507,11 , 450,19 , 37,5 , 8,10 , 8336,48 , 24061,83 , 9742,24 , 8336,48 , 24061,83 , 9742,24 , 2016,28 , 2044,58 , 2102,14 , 2016,28 , 2044,58 , 2116,14 , 423,10 , 391,7 , 296,7 , 5,17 , 22,23 , {66,65,77}, 144,2 , 14996,170 , 13,5 , 4,0 , 4482,8 , 620,19 , 2, 1, 1, 6, 7 }, // Bosnian/Latin/Bosnia And Herzegowina
+ { 142, 2, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 116,7 , 116,7 , 1067,7 , 1074,20 , 37,5 , 8,10 , 24144,48 , 24192,83 , 12698,24 , 24144,48 , 24192,83 , 12698,24 , 12781,28 , 12809,56 , 8880,14 , 12781,28 , 12809,56 , 8880,14 , 228,9 , 398,7 , 45,4 , 5,17 , 22,23 , {66,65,77}, 291,2 , 15166,151 , 13,5 , 4,0 , 4490,8 , 3545,19 , 2, 1, 1, 6, 7 }, // Bosnian/Cyrillic/Bosnia And Herzegowina
{ 143, 29, 131, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {77,86,82}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 5, 6, 7 }, // Divehi/Thaana/Maldives
- { 144, 7, 251, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 633,17 , 37,5 , 8,10 , 22420,102 , 22522,140 , 158,27 , 22420,102 , 22522,140 , 158,27 , 11891,30 , 11921,57 , 85,14 , 11891,30 , 11921,57 , 85,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {71,66,80}, 125,1 , 0,7 , 4,4 , 4,0 , 4329,5 , 4334,12 , 2, 1, 1, 6, 7 }, // Manx/Latin/IsleOfMan
- { 145, 7, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 98,16 , 37,5 , 8,10 , 22662,46 , 22708,130 , 158,27 , 22662,46 , 22708,130 , 158,27 , 11978,28 , 12006,61 , 85,14 , 11978,28 , 12006,61 , 85,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {71,66,80}, 125,1 , 0,7 , 4,4 , 4,0 , 4346,8 , 4354,14 , 2, 1, 1, 6, 7 }, // Cornish/Latin/UnitedKingdom
- { 146, 7, 83, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 1345,8 , 1353,18 , 18,7 , 25,12 , 22838,48 , 22886,192 , 158,27 , 22838,48 , 22886,192 , 158,27 , 12067,28 , 12095,49 , 12144,14 , 12067,28 , 12095,49 , 12144,14 , 390,2 , 361,2 , 45,4 , 5,17 , 22,23 , {71,72,83}, 173,3 , 14927,17 , 4,4 , 4,0 , 4368,4 , 4372,5 , 2, 1, 1, 6, 7 }, // Akan/Latin/Ghana
- { 147, 13, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 941,6 , 98,16 , 18,7 , 25,12 , 23078,87 , 23078,87 , 158,27 , 23078,87 , 23078,87 , 158,27 , 7017,32 , 12158,55 , 85,14 , 7017,32 , 12158,55 , 85,14 , 184,5 , 363,5 , 45,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 0,7 , 8,5 , 4,0 , 4377,6 , 2589,4 , 2, 1, 7, 7, 7 }, // Konkani/Devanagari/India
+ { 144, 7, 251, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 80,17 , 37,5 , 8,10 , 24275,102 , 24377,140 , 158,27 , 24275,102 , 24377,140 , 158,27 , 12865,30 , 12895,57 , 85,14 , 12865,30 , 12895,57 , 85,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {71,66,80}, 119,1 , 0,7 , 4,4 , 4,0 , 4498,5 , 4503,12 , 2, 1, 1, 6, 7 }, // Manx/Latin/Isle Of Man
+ { 145, 7, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 97,16 , 37,5 , 8,10 , 24517,46 , 24563,130 , 158,27 , 24517,46 , 24563,130 , 158,27 , 12952,28 , 12980,61 , 85,14 , 12952,28 , 12980,61 , 85,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {71,66,80}, 119,1 , 0,7 , 4,4 , 4,0 , 4515,8 , 4523,14 , 2, 1, 1, 6, 7 }, // Cornish/Latin/United Kingdom
+ { 146, 7, 83, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 1518,8 , 1526,18 , 18,7 , 25,12 , 24693,48 , 24741,192 , 158,27 , 24693,48 , 24741,192 , 158,27 , 13041,28 , 13069,49 , 13118,14 , 13041,28 , 13069,49 , 13118,14 , 433,2 , 405,2 , 45,4 , 5,17 , 22,23 , {71,72,83}, 167,3 , 15317,17 , 4,4 , 4,0 , 4537,4 , 4541,5 , 2, 1, 1, 6, 7 }, // Akan/Latin/Ghana
+ { 147, 13, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 1544,6 , 97,16 , 18,7 , 25,12 , 24933,88 , 24933,88 , 158,27 , 24933,88 , 24933,88 , 158,27 , 13132,49 , 13132,49 , 13181,20 , 13132,49 , 13132,49 , 13181,20 , 190,5 , 407,5 , 45,4 , 5,17 , 22,23 , {73,78,82}, 121,1 , 15334,13 , 8,5 , 4,0 , 4546,6 , 2633,4 , 2, 1, 7, 7, 7 }, // Konkani/Devanagari/India
{ 148, 7, 83, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {71,72,83}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Ga/Latin/Ghana
- { 149, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 23165,48 , 23213,86 , 158,27 , 23165,48 , 23213,86 , 158,27 , 12213,29 , 12242,57 , 85,14 , 12213,29 , 12242,57 , 85,14 , 38,4 , 368,4 , 45,4 , 5,17 , 22,23 , {78,71,78}, 184,1 , 14944,12 , 4,4 , 4,0 , 4383,4 , 1303,7 , 2, 1, 1, 6, 7 }, // Igbo/Latin/Nigeria
- { 150, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 23299,48 , 23347,189 , 23536,24 , 23299,48 , 23347,189 , 23536,24 , 12299,28 , 12327,74 , 12401,14 , 12299,28 , 12327,74 , 12401,14 , 392,9 , 372,7 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 14956,23 , 4,4 , 4,0 , 4387,7 , 1153,5 , 2, 1, 7, 6, 7 }, // Kamba/Latin/Kenya
+ { 149, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 25021,48 , 25069,86 , 158,27 , 25021,48 , 25069,86 , 158,27 , 13201,29 , 13230,57 , 85,14 , 13201,29 , 13230,57 , 85,14 , 38,4 , 412,4 , 45,4 , 5,17 , 22,23 , {78,71,78}, 178,1 , 15347,12 , 4,4 , 4,0 , 4552,4 , 4556,8 , 2, 1, 1, 6, 7 }, // Igbo/Latin/Nigeria
+ { 150, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 25155,48 , 25203,189 , 25392,24 , 25155,48 , 25203,189 , 25392,24 , 13287,28 , 13315,74 , 13389,14 , 13287,28 , 13315,74 , 13389,14 , 435,9 , 416,7 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 15359,23 , 4,4 , 4,0 , 4564,7 , 1182,5 , 2, 1, 7, 6, 7 }, // Kamba/Latin/Kenya
{ 151, 33, 103, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,81,68}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 6, 5, 6 }, // Syriac/Syriac/Iraq
{ 152, 14, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,82,78}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Blin/Ethiopic/Eritrea
{ 153, 14, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,84,66}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Geez/Ethiopic/Ethiopia
{ 155, 7, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,84,66}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Sidamo/Latin/Ethiopia
- { 156, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {78,71,78}, 184,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Atsam/Latin/Nigeria
+ { 156, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {78,71,78}, 178,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Atsam/Latin/Nigeria
{ 157, 14, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,82,78}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Tigre/Ethiopic/Eritrea
- { 158, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {78,71,78}, 184,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Jju/Latin/Nigeria
- { 159, 7, 106, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 1371,27 , 37,5 , 8,10 , 23560,48 , 23608,77 , 23685,24 , 23560,48 , 23608,77 , 23685,24 , 12415,28 , 12443,50 , 3054,14 , 12415,28 , 12443,50 , 3054,14 , 401,2 , 379,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3057,20 , 8,5 , 4,0 , 4394,6 , 4400,6 , 2, 1, 1, 6, 7 }, // Friulian/Latin/Italy
- { 160, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Venda/Latin/SouthAfrica
- { 161, 7, 83, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 720,11 , 731,10 , 516,6 , 1398,23 , 423,12 , 435,17 , 23709,48 , 23757,87 , 23844,24 , 23709,48 , 23757,87 , 23844,24 , 12493,28 , 12521,44 , 12565,14 , 12493,28 , 12521,44 , 12565,14 , 403,3 , 381,5 , 45,4 , 5,17 , 22,23 , {71,72,83}, 173,3 , 14979,37 , 4,4 , 4,0 , 4406,6 , 4412,12 , 2, 1, 1, 6, 7 }, // Ewe/Latin/Ghana
- { 161, 7, 212, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 720,11 , 731,10 , 516,6 , 1398,23 , 37,5 , 8,10 , 23709,48 , 23757,87 , 23844,24 , 23709,48 , 23757,87 , 23844,24 , 12493,28 , 12521,44 , 12565,14 , 12493,28 , 12521,44 , 12565,14 , 403,3 , 381,5 , 45,4 , 5,17 , 22,23 , {88,79,70}, 210,3 , 15016,106 , 4,4 , 4,0 , 4406,6 , 4424,11 , 0, 0, 1, 6, 7 }, // Ewe/Latin/Togo
+ { 158, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {78,71,78}, 178,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Jju/Latin/Nigeria
+ { 159, 7, 106, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 1550,27 , 37,5 , 8,10 , 25416,48 , 25464,77 , 25541,24 , 25416,48 , 25464,77 , 25541,24 , 13403,28 , 13431,50 , 3080,14 , 13403,28 , 13431,50 , 3080,14 , 444,2 , 423,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3102,20 , 8,5 , 4,0 , 4571,6 , 4577,6 , 2, 1, 1, 6, 7 }, // Friulian/Latin/Italy
+ { 160, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Venda/Latin/South Africa
+ { 161, 7, 83, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 859,11 , 870,10 , 547,6 , 1577,23 , 497,12 , 509,17 , 25565,48 , 25613,87 , 25700,24 , 25565,48 , 25613,87 , 25700,24 , 13481,28 , 13509,44 , 13553,14 , 13481,28 , 13509,44 , 13553,14 , 446,3 , 425,5 , 45,4 , 5,17 , 22,23 , {71,72,83}, 167,3 , 15382,37 , 4,4 , 4,0 , 4583,6 , 4589,12 , 2, 1, 1, 6, 7 }, // Ewe/Latin/Ghana
+ { 161, 7, 212, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 859,11 , 870,10 , 547,6 , 1577,23 , 37,5 , 8,10 , 25565,48 , 25613,87 , 25700,24 , 25565,48 , 25613,87 , 25700,24 , 13481,28 , 13509,44 , 13553,14 , 13481,28 , 13509,44 , 13553,14 , 446,3 , 425,5 , 45,4 , 5,17 , 22,23 , {88,79,70}, 204,3 , 15419,106 , 4,4 , 4,0 , 4583,6 , 4601,11 , 0, 0, 1, 6, 7 }, // Ewe/Latin/Togo
{ 162, 14, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,84,66}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Walamo/Ethiopic/Ethiopia
- { 163, 7, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 278,6 , 10,17 , 18,7 , 25,12 , 23868,59 , 23927,95 , 158,27 , 23868,59 , 23927,95 , 158,27 , 12579,21 , 12600,57 , 85,14 , 12579,21 , 12600,57 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,83,68}, 6,1 , 0,7 , 4,4 , 4,0 , 4435,14 , 4449,19 , 2, 1, 7, 6, 7 }, // Hawaiian/Latin/UnitedStates
- { 164, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {78,71,78}, 184,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Tyap/Latin/Nigeria
+ { 163, 7, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 269,6 , 10,17 , 18,7 , 25,12 , 25724,59 , 25783,95 , 158,27 , 25724,59 , 25783,95 , 158,27 , 13567,21 , 13588,57 , 85,14 , 13567,21 , 13588,57 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,83,68}, 6,1 , 0,7 , 4,4 , 4,0 , 4612,14 , 4626,19 , 2, 1, 7, 6, 7 }, // Hawaiian/Latin/United States
+ { 164, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {78,71,78}, 178,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Tyap/Latin/Nigeria
{ 165, 7, 129, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {77,87,75}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Nyanja/Latin/Malawi
- { 166, 7, 170, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 741,9 , 750,8 , 516,6 , 35,18 , 18,7 , 25,12 , 24022,48 , 24070,88 , 24158,38 , 24022,48 , 24070,88 , 24022,48 , 12657,28 , 12685,55 , 12657,28 , 12657,28 , 12685,55 , 12657,28 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {80,72,80}, 185,1 , 15122,58 , 4,4 , 4,0 , 4468,8 , 4476,9 , 2, 1, 7, 6, 7 }, // Filipino/Latin/Philippines
- { 167, 7, 206, 46, 8217, 59, 37, 48, 8722, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 251,9 , 251,9 , 175,8 , 532,18 , 37,5 , 8,10 , 7736,48 , 24196,86 , 134,24 , 7736,48 , 24196,86 , 134,24 , 12740,28 , 12768,63 , 3642,14 , 12740,28 , 12768,63 , 3642,14 , 406,12 , 386,11 , 45,4 , 5,17 , 22,23 , {67,72,70}, 229,3 , 15180,55 , 13,5 , 4,0 , 4485,16 , 4501,7 , 2, 0, 1, 6, 7 }, // Swiss German/Latin/Switzerland
- { 167, 7, 74, 46, 8217, 59, 37, 48, 8722, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 251,9 , 251,9 , 175,8 , 532,18 , 37,5 , 8,10 , 7736,48 , 24196,86 , 134,24 , 7736,48 , 24196,86 , 134,24 , 12740,28 , 12768,63 , 3642,14 , 12740,28 , 12768,63 , 3642,14 , 406,12 , 386,11 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8339,19 , 13,5 , 4,0 , 4485,16 , 4508,10 , 2, 1, 1, 6, 7 }, // Swiss German/Latin/France
- { 167, 7, 123, 46, 8217, 59, 37, 48, 8722, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 251,9 , 251,9 , 175,8 , 532,18 , 37,5 , 8,10 , 7736,48 , 24196,86 , 134,24 , 7736,48 , 24196,86 , 134,24 , 12740,28 , 12768,63 , 3642,14 , 12740,28 , 12768,63 , 3642,14 , 406,12 , 386,11 , 45,4 , 5,17 , 22,23 , {67,72,70}, 229,3 , 15180,55 , 13,5 , 4,0 , 4485,16 , 4518,13 , 2, 0, 1, 6, 7 }, // Swiss German/Latin/Liechtenstein
- { 168, 34, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 18,7 , 25,12 , 24282,38 , 24282,38 , 158,27 , 24282,38 , 24282,38 , 158,27 , 12831,21 , 12852,28 , 12880,14 , 12831,21 , 12852,28 , 12880,14 , 418,2 , 397,2 , 45,4 , 5,17 , 22,23 , {67,78,89}, 329,1 , 0,7 , 8,5 , 4,0 , 4531,3 , 4534,2 , 2, 1, 7, 6, 7 }, // Sichuan Yi/Yi/China
+ { 166, 7, 170, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 880,9 , 889,8 , 547,6 , 35,18 , 18,7 , 25,12 , 25878,48 , 25926,88 , 26014,38 , 25878,48 , 25926,88 , 25878,48 , 13645,28 , 13673,55 , 13645,28 , 13645,28 , 13673,55 , 13645,28 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {80,72,80}, 179,1 , 15525,58 , 4,4 , 4,0 , 4645,8 , 4653,9 , 2, 1, 7, 6, 7 }, // Filipino/Latin/Philippines
+ { 167, 7, 206, 46, 8217, 59, 37, 48, 8722, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 269,9 , 269,9 , 156,8 , 622,18 , 37,5 , 8,10 , 7601,48 , 26052,86 , 134,24 , 7601,48 , 26052,86 , 134,24 , 13728,28 , 13756,63 , 3668,14 , 13728,28 , 13756,63 , 3668,14 , 449,12 , 430,11 , 45,4 , 5,17 , 22,23 , {67,72,70}, 221,3 , 15583,55 , 13,5 , 4,0 , 4662,16 , 4678,7 , 2, 0, 1, 6, 7 }, // Swiss German/Latin/Switzerland
+ { 167, 7, 74, 46, 8217, 59, 37, 48, 8722, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 269,9 , 269,9 , 156,8 , 622,18 , 37,5 , 8,10 , 7601,48 , 26052,86 , 134,24 , 7601,48 , 26052,86 , 134,24 , 13728,28 , 13756,63 , 3668,14 , 13728,28 , 13756,63 , 3668,14 , 449,12 , 430,11 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8384,19 , 13,5 , 4,0 , 4662,16 , 4685,10 , 2, 1, 1, 6, 7 }, // Swiss German/Latin/France
+ { 167, 7, 123, 46, 8217, 59, 37, 48, 8722, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 269,9 , 269,9 , 156,8 , 622,18 , 37,5 , 8,10 , 7601,48 , 26052,86 , 134,24 , 7601,48 , 26052,86 , 134,24 , 13728,28 , 13756,63 , 3668,14 , 13728,28 , 13756,63 , 3668,14 , 449,12 , 430,11 , 45,4 , 5,17 , 22,23 , {67,72,70}, 221,3 , 15583,55 , 13,5 , 4,0 , 4662,16 , 4695,13 , 2, 0, 1, 6, 7 }, // Swiss German/Latin/Liechtenstein
+ { 168, 34, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 18,7 , 25,12 , 26138,38 , 26138,38 , 158,27 , 26138,38 , 26138,38 , 158,27 , 13819,21 , 13840,28 , 13868,14 , 13819,21 , 13840,28 , 13868,14 , 461,2 , 441,2 , 45,4 , 5,17 , 22,23 , {67,78,89}, 321,1 , 0,7 , 8,5 , 4,0 , 4708,3 , 4711,2 , 2, 1, 7, 6, 7 }, // Sichuan Yi/Yi/China
{ 169, 7, 121, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {76,82,68}, 6,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Kpelle/Latin/Liberia
- { 170, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 409,8 , 409,8 , 356,7 , 1421,23 , 452,10 , 462,19 , 7867,59 , 24320,85 , 134,24 , 7867,59 , 24320,85 , 134,24 , 12894,28 , 12922,65 , 3642,14 , 12894,28 , 12922,65 , 3642,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 15235,15 , 13,5 , 4,0 , 4536,14 , 4550,11 , 2, 1, 1, 6, 7 }, // Low German/Latin/Germany
- { 170, 7, 151, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 409,8 , 409,8 , 356,7 , 1421,23 , 452,10 , 462,19 , 7867,59 , 24320,85 , 134,24 , 7867,59 , 24320,85 , 134,24 , 12894,28 , 12922,65 , 3642,14 , 12894,28 , 12922,65 , 3642,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 15235,15 , 13,5 , 4,0 , 4536,14 , 4561,12 , 2, 1, 1, 6, 7 }, // Low German/Latin/Netherlands
- { 171, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // South Ndebele/Latin/SouthAfrica
- { 172, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Northern Sotho/Latin/SouthAfrica
- { 173, 7, 161, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 210,8 , 210,8 , 53,10 , 63,17 , 37,5 , 8,10 , 24405,59 , 24464,145 , 24609,24 , 24405,59 , 24464,145 , 24609,24 , 12987,33 , 13020,75 , 13095,14 , 12987,33 , 13020,75 , 13095,14 , 420,11 , 399,13 , 45,4 , 5,17 , 22,23 , {78,79,75}, 196,2 , 15250,63 , 13,5 , 4,0 , 4573,15 , 4588,5 , 2, 1, 1, 6, 7 }, // Northern Sami/Latin/Norway
- { 173, 7, 73, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 210,8 , 210,8 , 53,10 , 63,17 , 37,5 , 8,10 , 24405,59 , 24464,145 , 24609,24 , 24405,59 , 24464,145 , 24609,24 , 12987,33 , 13020,75 , 13109,14 , 12987,33 , 13123,79 , 13109,14 , 420,11 , 399,13 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 15313,23 , 13,5 , 4,0 , 4573,15 , 4593,6 , 2, 1, 1, 6, 7 }, // Northern Sami/Latin/Finland
- { 173, 7, 205, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 210,8 , 210,8 , 53,10 , 63,17 , 37,5 , 8,10 , 24405,59 , 24464,145 , 24609,24 , 24405,59 , 24464,145 , 24609,24 , 12987,33 , 13020,75 , 13095,14 , 12987,33 , 13020,75 , 13095,14 , 420,11 , 399,13 , 45,4 , 5,17 , 22,23 , {83,69,75}, 196,2 , 15336,63 , 13,5 , 4,0 , 4573,15 , 4599,6 , 2, 1, 1, 6, 7 }, // Northern Sami/Latin/Sweden
- { 174, 7, 208, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {84,87,68}, 341,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 0, 7, 6, 7 }, // Taroko/Latin/Taiwan
- { 175, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 24633,48 , 24681,88 , 24769,24 , 24633,48 , 24681,88 , 24769,24 , 13202,28 , 13230,62 , 13292,14 , 13202,28 , 13230,62 , 13292,14 , 431,6 , 412,3 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 15399,24 , 4,4 , 4,0 , 4605,8 , 1153,5 , 2, 1, 7, 6, 7 }, // Gusii/Latin/Kenya
- { 176, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 24793,48 , 24841,221 , 25062,24 , 24793,48 , 24841,221 , 25062,24 , 13306,28 , 13334,105 , 13439,14 , 13306,28 , 13334,105 , 13439,14 , 437,10 , 415,10 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 15399,24 , 4,4 , 4,0 , 4613,7 , 1153,5 , 2, 1, 7, 6, 7 }, // Taita/Latin/Kenya
- { 177, 7, 187, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 25086,48 , 25134,77 , 25211,24 , 25086,48 , 25134,77 , 25211,24 , 13453,28 , 13481,59 , 13540,14 , 13453,28 , 13481,59 , 13540,14 , 447,6 , 425,7 , 45,4 , 5,17 , 22,23 , {88,79,70}, 210,3 , 15423,26 , 13,5 , 4,0 , 4620,6 , 4626,8 , 0, 0, 1, 6, 7 }, // Fulah/Latin/Senegal
- { 177, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 25086,48 , 25134,77 , 25211,24 , 25086,48 , 25134,77 , 25211,24 , 13453,28 , 13481,59 , 13540,14 , 13453,28 , 13481,59 , 13540,14 , 447,6 , 425,7 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 15449,25 , 13,5 , 4,0 , 4620,6 , 4634,8 , 0, 0, 1, 6, 7 }, // Fulah/Latin/Cameroon
- { 177, 7, 91, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 25086,48 , 25134,77 , 25211,24 , 25086,48 , 25134,77 , 25211,24 , 13453,28 , 13481,59 , 13540,14 , 13453,28 , 13481,59 , 13540,14 , 447,6 , 425,7 , 45,4 , 5,17 , 22,23 , {71,78,70}, 221,2 , 0,7 , 13,5 , 4,0 , 4620,6 , 4642,4 , 0, 0, 1, 6, 7 }, // Fulah/Latin/Guinea
- { 177, 7, 136, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 18,7 , 25,12 , 25086,48 , 25134,77 , 25211,24 , 25086,48 , 25134,77 , 25211,24 , 13453,28 , 13481,59 , 13540,14 , 13453,28 , 13481,59 , 13540,14 , 447,6 , 425,7 , 45,4 , 5,17 , 22,23 , {77,82,79}, 224,2 , 15474,22 , 13,5 , 4,0 , 4620,6 , 4646,8 , 0, 0, 1, 6, 7 }, // Fulah/Latin/Mauritania
- { 178, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 25235,48 , 25283,185 , 25468,24 , 25235,48 , 25283,185 , 25468,24 , 13554,28 , 13582,63 , 13645,14 , 13554,28 , 13582,63 , 13645,14 , 453,6 , 432,8 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 15496,23 , 4,4 , 4,0 , 4654,6 , 1153,5 , 2, 1, 7, 6, 7 }, // Kikuyu/Latin/Kenya
- { 179, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 25492,48 , 25540,173 , 25713,24 , 25492,48 , 25540,173 , 25713,24 , 13659,28 , 13687,105 , 13792,14 , 13659,28 , 13687,105 , 13792,14 , 459,7 , 440,5 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 15519,25 , 4,4 , 4,0 , 4660,8 , 1153,5 , 2, 1, 7, 6, 7 }, // Samburu/Latin/Kenya
- { 180, 7, 146, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 587,27 , 37,5 , 8,10 , 25737,48 , 25785,88 , 134,24 , 25737,48 , 25785,88 , 134,24 , 13806,28 , 13834,55 , 13889,14 , 13806,28 , 13834,55 , 13889,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {77,90,78}, 284,3 , 15544,28 , 0,4 , 4,0 , 4668,4 , 3210,10 , 2, 1, 7, 6, 7 }, // Sena/Latin/Mozambique
- { 181, 7, 240, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 25873,52 , 25925,112 , 26037,24 , 25873,52 , 25925,112 , 26037,24 , 13903,28 , 13931,50 , 13981,14 , 13903,28 , 13931,50 , 13981,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,83,68}, 165,3 , 15572,24 , 4,4 , 4,0 , 4672,10 , 1762,8 , 2, 1, 7, 6, 7 }, // North Ndebele/Latin/Zimbabwe
- { 182, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 26061,39 , 26100,194 , 26294,24 , 26061,39 , 26100,194 , 26294,24 , 13995,29 , 14024,65 , 14089,14 , 13995,29 , 14024,65 , 14089,14 , 466,8 , 445,7 , 45,4 , 5,17 , 22,23 , {84,90,83}, 198,3 , 15596,25 , 4,4 , 4,0 , 4682,9 , 1587,8 , 0, 0, 1, 6, 7 }, // Rombo/Latin/Tanzania
- { 183, 9, 145, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 26318,48 , 26366,81 , 26447,24 , 26318,48 , 26366,81 , 26447,24 , 14103,30 , 14133,47 , 85,14 , 14103,30 , 14133,47 , 85,14 , 474,6 , 452,8 , 45,4 , 5,17 , 22,23 , {77,65,68}, 0,0 , 15621,21 , 0,4 , 4,0 , 4691,7 , 4698,6 , 2, 1, 6, 5, 6 }, // Tachelhit/Tifinagh/Morocco
- { 183, 7, 145, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 26471,48 , 26519,81 , 26600,24 , 26471,48 , 26519,81 , 26600,24 , 14180,30 , 14210,48 , 85,14 , 14180,30 , 14210,48 , 85,14 , 480,6 , 460,8 , 45,4 , 5,17 , 22,23 , {77,65,68}, 0,0 , 15642,21 , 0,4 , 4,0 , 4704,10 , 4714,6 , 2, 1, 6, 5, 6 }, // Tachelhit/Latin/Morocco
- { 184, 7, 3, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 18,7 , 25,12 , 26624,48 , 26672,84 , 26756,24 , 26624,48 , 26672,84 , 26756,24 , 14258,30 , 14288,51 , 14339,14 , 14258,30 , 14288,51 , 14339,14 , 486,7 , 468,9 , 45,4 , 5,17 , 22,23 , {68,90,68}, 208,2 , 15663,21 , 0,4 , 4,0 , 4720,9 , 4729,8 , 2, 1, 6, 5, 6 }, // Kabyle/Latin/Algeria
- { 185, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 26780,48 , 26828,152 , 134,24 , 26780,48 , 26828,152 , 134,24 , 14353,28 , 14381,74 , 14455,14 , 14353,28 , 14381,74 , 14455,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,71,88}, 203,3 , 15684,26 , 4,4 , 4,0 , 4737,10 , 1652,6 , 0, 0, 1, 6, 7 }, // Nyankole/Latin/Uganda
- { 186, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 26980,48 , 27028,254 , 27282,24 , 26980,48 , 27028,254 , 27282,24 , 14469,28 , 14497,82 , 14579,14 , 14469,28 , 14497,82 , 14579,14 , 493,7 , 477,7 , 45,4 , 5,17 , 22,23 , {84,90,83}, 198,3 , 15710,29 , 0,4 , 4,0 , 4747,6 , 4753,10 , 0, 0, 1, 6, 7 }, // Bena/Latin/Tanzania
- { 187, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 18222,48 , 27306,87 , 134,24 , 18222,48 , 27306,87 , 134,24 , 14593,28 , 14621,62 , 14683,14 , 14593,28 , 14621,62 , 14683,14 , 500,5 , 484,9 , 45,4 , 5,17 , 22,23 , {84,90,83}, 198,3 , 15739,27 , 4,4 , 4,0 , 4763,8 , 1587,8 , 0, 0, 1, 6, 7 }, // Vunjo/Latin/Tanzania
- { 188, 7, 132, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 27393,47 , 27440,92 , 27532,24 , 27393,47 , 27440,92 , 27532,24 , 14697,28 , 14725,44 , 14769,14 , 14697,28 , 14725,44 , 14769,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,79,70}, 210,3 , 15766,24 , 4,4 , 4,0 , 4771,9 , 2106,4 , 0, 0, 1, 6, 7 }, // Bambara/Latin/Mali
- { 188, 75, 132, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,79,70}, 210,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Bambara/Nko/Mali
- { 189, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 27556,48 , 27604,207 , 27811,24 , 27556,48 , 27604,207 , 27811,24 , 14783,28 , 14811,64 , 14875,14 , 14783,28 , 14811,64 , 14875,14 , 505,2 , 493,2 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 15399,24 , 4,4 , 4,0 , 4780,6 , 1153,5 , 2, 1, 7, 6, 7 }, // Embu/Latin/Kenya
- { 190, 12, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 758,8 , 758,8 , 516,6 , 35,18 , 18,7 , 25,12 , 27835,36 , 27871,58 , 27929,24 , 27835,36 , 27871,58 , 27929,24 , 14889,28 , 14917,49 , 14966,14 , 14889,28 , 14917,49 , 14966,14 , 507,3 , 495,6 , 942,6 , 5,17 , 22,23 , {85,83,68}, 6,1 , 15790,25 , 4,4 , 4,0 , 4786,3 , 4789,15 , 2, 1, 7, 6, 7 }, // Cherokee/Cherokee/UnitedStates
- { 191, 7, 137, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 27953,47 , 28000,68 , 28068,24 , 27953,47 , 28000,68 , 28068,24 , 14980,27 , 15007,48 , 15055,14 , 14980,27 , 15007,48 , 15055,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {77,85,82}, 182,2 , 15815,21 , 79,6 , 4,0 , 4804,14 , 4818,5 , 0, 0, 1, 6, 7 }, // Morisyen/Latin/Mauritius
- { 192, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 18222,48 , 28092,264 , 134,24 , 18222,48 , 28092,264 , 134,24 , 15069,28 , 15097,133 , 14089,14 , 15069,28 , 15097,133 , 14089,14 , 510,4 , 501,5 , 45,4 , 5,17 , 22,23 , {84,90,83}, 198,3 , 15739,27 , 4,4 , 4,0 , 4823,10 , 1587,8 , 0, 0, 1, 6, 7 }, // Makonde/Latin/Tanzania
- { 193, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 28356,83 , 28439,111 , 28550,24 , 28356,83 , 28439,111 , 28550,24 , 15230,36 , 15266,63 , 15329,14 , 15230,36 , 15266,63 , 15329,14 , 514,3 , 506,3 , 45,4 , 5,17 , 22,23 , {84,90,83}, 198,3 , 15836,29 , 79,6 , 4,0 , 4833,8 , 4841,9 , 0, 0, 1, 6, 7 }, // Langi/Latin/Tanzania
- { 194, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 28574,48 , 28622,97 , 134,24 , 28574,48 , 28622,97 , 134,24 , 15343,28 , 15371,66 , 15437,14 , 15343,28 , 15371,66 , 15437,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,71,88}, 203,3 , 15865,26 , 0,4 , 4,0 , 4850,7 , 4857,7 , 0, 0, 1, 6, 7 }, // Ganda/Latin/Uganda
- { 195, 7, 239, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 18,7 , 25,12 , 28719,48 , 28767,83 , 28850,24 , 28719,48 , 28767,83 , 28850,24 , 15451,80 , 15451,80 , 85,14 , 15451,80 , 15451,80 , 85,14 , 517,8 , 509,7 , 45,4 , 5,17 , 22,23 , {90,77,87}, 137,1 , 0,7 , 4,4 , 4,0 , 4864,9 , 1756,6 , 2, 1, 1, 6, 7 }, // Bemba/Latin/Zambia
- { 196, 7, 39, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 154,7 , 154,7 , 406,8 , 1444,27 , 37,5 , 8,10 , 28874,48 , 28922,85 , 134,24 , 28874,48 , 28922,85 , 134,24 , 15531,28 , 15559,73 , 15632,14 , 15531,28 , 15646,73 , 15632,14 , 68,2 , 65,2 , 45,4 , 297,17 , 22,23 , {67,86,69}, 283,1 , 15891,43 , 13,5 , 4,0 , 4873,12 , 4885,10 , 2, 1, 1, 6, 7 }, // Kabuverdianu/Latin/CapeVerde
- { 197, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 29007,48 , 29055,86 , 29141,24 , 29007,48 , 29055,86 , 29141,24 , 15719,28 , 15747,51 , 15798,14 , 15719,28 , 15747,51 , 15798,14 , 525,2 , 516,2 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 15399,24 , 4,4 , 4,0 , 4895,6 , 1153,5 , 2, 1, 7, 6, 7 }, // Meru/Latin/Kenya
- { 198, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 29165,49 , 29214,121 , 29335,24 , 29165,49 , 29214,121 , 29335,24 , 15812,28 , 15840,53 , 15893,14 , 15812,28 , 15840,53 , 15893,14 , 527,6 , 518,10 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 15934,26 , 4,4 , 4,0 , 4901,8 , 4909,12 , 2, 1, 7, 6, 7 }, // Kalenjin/Latin/Kenya
- { 199, 7, 148, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 29359,136 , 134,24 , 0,48 , 29359,136 , 134,24 , 15907,23 , 15930,92 , 16022,14 , 15907,23 , 15930,92 , 16022,14 , 533,7 , 528,5 , 45,4 , 5,17 , 22,23 , {78,65,68}, 6,1 , 15960,22 , 4,4 , 4,0 , 4921,13 , 4934,8 , 2, 1, 1, 6, 7 }, // Nama/Latin/Namibia
- { 200, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 18222,48 , 27306,87 , 134,24 , 18222,48 , 27306,87 , 134,24 , 14593,28 , 14621,62 , 14683,14 , 14593,28 , 14621,62 , 14683,14 , 500,5 , 484,9 , 45,4 , 5,17 , 22,23 , {84,90,83}, 198,3 , 15739,27 , 4,4 , 4,0 , 4942,9 , 1587,8 , 0, 0, 1, 6, 7 }, // Machame/Latin/Tanzania
- { 201, 7, 82, 44, 160, 59, 37, 48, 8722, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 409,8 , 409,8 , 1045,10 , 1471,23 , 37,5 , 8,10 , 29495,59 , 29554,87 , 12643,24 , 29641,48 , 29554,87 , 12643,24 , 16036,28 , 16064,72 , 3642,14 , 16036,28 , 16064,72 , 3642,14 , 540,16 , 533,16 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 15982,11 , 13,5 , 4,0 , 4951,6 , 4957,11 , 2, 1, 1, 6, 7 }, // Colognian/Latin/Germany
- { 202, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 29689,51 , 29740,132 , 158,27 , 29689,51 , 29740,132 , 158,27 , 14593,28 , 16136,58 , 14089,14 , 14593,28 , 16136,58 , 14089,14 , 556,9 , 549,6 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 15993,25 , 4,4 , 4,0 , 4968,3 , 1153,5 , 2, 1, 7, 6, 7 }, // Masai/Latin/Kenya
- { 202, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 29689,51 , 29740,132 , 158,27 , 29689,51 , 29740,132 , 158,27 , 14593,28 , 16136,58 , 14089,14 , 14593,28 , 16136,58 , 14089,14 , 556,9 , 549,6 , 45,4 , 5,17 , 22,23 , {84,90,83}, 198,3 , 16018,28 , 4,4 , 4,0 , 4968,3 , 4971,8 , 0, 0, 1, 6, 7 }, // Masai/Latin/Tanzania
- { 203, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 28574,48 , 28622,97 , 134,24 , 28574,48 , 28622,97 , 134,24 , 16194,35 , 16229,65 , 16294,14 , 16194,35 , 16229,65 , 16294,14 , 565,6 , 555,6 , 45,4 , 5,17 , 22,23 , {85,71,88}, 203,3 , 15865,26 , 13,5 , 4,0 , 4979,7 , 4857,7 , 0, 0, 1, 6, 7 }, // Soga/Latin/Uganda
- { 204, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 29872,48 , 18270,84 , 134,24 , 29872,48 , 18270,84 , 134,24 , 16308,21 , 16329,75 , 85,14 , 16308,21 , 16329,75 , 85,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 16046,23 , 4,4 , 91,6 , 4986,7 , 1153,5 , 2, 1, 7, 6, 7 }, // Luyia/Latin/Kenya
- { 205, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 29920,48 , 18270,84 , 134,24 , 29920,48 , 18270,84 , 134,24 , 16404,28 , 9545,60 , 14683,14 , 16404,28 , 9545,60 , 14683,14 , 571,9 , 561,8 , 45,4 , 5,17 , 22,23 , {84,90,83}, 198,3 , 16069,28 , 13,5 , 4,0 , 4993,6 , 4999,8 , 0, 0, 1, 6, 7 }, // Asu/Latin/Tanzania
- { 206, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 29968,48 , 30016,94 , 30110,24 , 29968,48 , 30016,94 , 30110,24 , 16432,28 , 16460,69 , 16529,14 , 16432,28 , 16460,69 , 16529,14 , 580,9 , 569,6 , 45,4 , 5,17 , 22,23 , {85,71,88}, 203,3 , 16097,28 , 4,4 , 4,0 , 5007,6 , 1652,6 , 0, 0, 1, 6, 7 }, // Teso/Latin/Uganda
- { 206, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 29968,48 , 30016,94 , 30110,24 , 29968,48 , 30016,94 , 30110,24 , 16432,28 , 16460,69 , 16529,14 , 16432,28 , 16460,69 , 16529,14 , 580,9 , 569,6 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 16125,27 , 4,4 , 4,0 , 5007,6 , 5013,5 , 2, 1, 7, 6, 7 }, // Teso/Latin/Kenya
+ { 170, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 453,8 , 453,8 , 365,7 , 1600,23 , 526,10 , 536,19 , 26176,59 , 26235,85 , 134,24 , 26176,59 , 26235,85 , 134,24 , 13882,28 , 13910,65 , 3668,14 , 13882,28 , 13910,65 , 3668,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 15638,15 , 13,5 , 4,0 , 4713,14 , 4727,11 , 2, 1, 1, 6, 7 }, // Low German/Latin/Germany
+ { 170, 7, 151, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 453,8 , 453,8 , 365,7 , 1600,23 , 526,10 , 536,19 , 26176,59 , 26235,85 , 134,24 , 26176,59 , 26235,85 , 134,24 , 13882,28 , 13910,65 , 3668,14 , 13882,28 , 13910,65 , 3668,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 15638,15 , 13,5 , 4,0 , 4713,14 , 4738,12 , 2, 1, 1, 6, 7 }, // Low German/Latin/Netherlands
+ { 171, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // South Ndebele/Latin/South Africa
+ { 172, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Northern Sotho/Latin/South Africa
+ { 173, 7, 161, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 228,8 , 228,8 , 53,10 , 63,17 , 37,5 , 8,10 , 26320,59 , 26379,145 , 26524,24 , 26320,59 , 26379,145 , 26524,24 , 13975,33 , 14008,75 , 14083,14 , 13975,33 , 14008,75 , 14083,14 , 463,11 , 443,13 , 45,4 , 5,17 , 22,23 , {78,79,75}, 190,2 , 15653,63 , 13,5 , 4,0 , 4750,15 , 4765,5 , 2, 0, 1, 6, 7 }, // Northern Sami/Latin/Norway
+ { 173, 7, 73, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 228,8 , 228,8 , 495,10 , 97,16 , 37,5 , 8,10 , 26548,60 , 26379,145 , 26524,24 , 26548,60 , 26379,145 , 26524,24 , 14097,21 , 14118,70 , 14188,14 , 14097,21 , 14118,70 , 14188,14 , 474,2 , 456,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 15716,23 , 13,5 , 4,0 , 4750,15 , 4770,6 , 2, 1, 1, 6, 7 }, // Northern Sami/Latin/Finland
+ { 173, 7, 205, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 228,8 , 228,8 , 53,10 , 63,17 , 37,5 , 8,10 , 26320,59 , 26379,145 , 26524,24 , 26320,59 , 26379,145 , 26524,24 , 13975,33 , 14008,75 , 14083,14 , 13975,33 , 14008,75 , 14083,14 , 463,11 , 443,13 , 45,4 , 5,17 , 22,23 , {83,69,75}, 190,2 , 15739,63 , 13,5 , 4,0 , 4750,15 , 4776,6 , 2, 0, 1, 6, 7 }, // Northern Sami/Latin/Sweden
+ { 174, 7, 208, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {84,87,68}, 333,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 0, 7, 6, 7 }, // Taroko/Latin/Taiwan
+ { 175, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 26608,48 , 26656,88 , 26744,24 , 26608,48 , 26656,88 , 26744,24 , 14202,28 , 14230,62 , 14292,14 , 14202,28 , 14230,62 , 14292,14 , 476,6 , 458,3 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 15802,24 , 4,4 , 4,0 , 4782,8 , 1182,5 , 2, 1, 7, 6, 7 }, // Gusii/Latin/Kenya
+ { 176, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 26768,48 , 26816,221 , 27037,24 , 26768,48 , 26816,221 , 27037,24 , 14306,28 , 14334,105 , 14439,14 , 14306,28 , 14334,105 , 14439,14 , 482,10 , 461,10 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 15802,24 , 4,4 , 4,0 , 4790,7 , 1182,5 , 2, 1, 7, 6, 7 }, // Taita/Latin/Kenya
+ { 177, 7, 187, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 27061,48 , 27109,77 , 27186,24 , 27061,48 , 27109,77 , 27186,24 , 14453,28 , 14481,59 , 14540,14 , 14453,28 , 14481,59 , 14540,14 , 492,6 , 471,7 , 45,4 , 5,17 , 22,23 , {88,79,70}, 204,3 , 15826,26 , 13,5 , 4,0 , 4797,6 , 4360,8 , 0, 0, 1, 6, 7 }, // Fulah/Latin/Senegal
+ { 177, 7, 34, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 27061,48 , 27109,77 , 27186,24 , 27061,48 , 27109,77 , 27186,24 , 14453,28 , 14481,59 , 14540,14 , 14453,28 , 14481,59 , 14540,14 , 492,6 , 471,7 , 45,4 , 5,17 , 22,23 , {88,79,70}, 204,3 , 15826,26 , 13,5 , 4,0 , 4797,6 , 4803,14 , 0, 0, 1, 6, 7 }, // Fulah/Latin/Burkina Faso
+ { 177, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 27061,48 , 27109,77 , 27186,24 , 27061,48 , 27109,77 , 27186,24 , 14453,28 , 14481,59 , 14540,14 , 14453,28 , 14481,59 , 14540,14 , 492,6 , 471,7 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 15852,25 , 13,5 , 4,0 , 4797,6 , 4817,8 , 0, 0, 1, 6, 7 }, // Fulah/Latin/Cameroon
+ { 177, 7, 80, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 27061,48 , 27109,77 , 27186,24 , 27061,48 , 27109,77 , 27186,24 , 14453,28 , 14481,59 , 14540,14 , 14453,28 , 14481,59 , 14540,14 , 492,6 , 471,7 , 45,4 , 5,17 , 22,23 , {71,77,68}, 166,1 , 15877,20 , 13,5 , 4,0 , 4797,6 , 4825,6 , 2, 1, 1, 6, 7 }, // Fulah/Latin/Gambia
+ { 177, 7, 83, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 27061,48 , 27109,77 , 27186,24 , 27061,48 , 27109,77 , 27186,24 , 14453,28 , 14481,59 , 14540,14 , 14453,28 , 14481,59 , 14540,14 , 492,6 , 471,7 , 45,4 , 5,17 , 22,23 , {71,72,83}, 167,3 , 0,7 , 13,5 , 4,0 , 4797,6 , 4831,5 , 2, 1, 1, 6, 7 }, // Fulah/Latin/Ghana
+ { 177, 7, 91, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 27061,48 , 27109,77 , 27186,24 , 27061,48 , 27109,77 , 27186,24 , 14453,28 , 14481,59 , 14540,14 , 14453,28 , 14481,59 , 14540,14 , 492,6 , 471,7 , 45,4 , 5,17 , 22,23 , {71,78,70}, 213,2 , 0,7 , 13,5 , 4,0 , 4797,6 , 4836,4 , 0, 0, 1, 6, 7 }, // Fulah/Latin/Guinea
+ { 177, 7, 92, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 27061,48 , 27109,77 , 27186,24 , 27061,48 , 27109,77 , 27186,24 , 14453,28 , 14481,59 , 14540,14 , 14453,28 , 14481,59 , 14540,14 , 492,6 , 471,7 , 45,4 , 5,17 , 22,23 , {88,79,70}, 204,3 , 15826,26 , 13,5 , 4,0 , 4797,6 , 4840,12 , 0, 0, 1, 6, 7 }, // Fulah/Latin/Guinea Bissau
+ { 177, 7, 121, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 27061,48 , 27109,77 , 27186,24 , 27061,48 , 27109,77 , 27186,24 , 14453,28 , 14481,59 , 14540,14 , 14453,28 , 14481,59 , 14540,14 , 492,6 , 471,7 , 45,4 , 5,17 , 22,23 , {76,82,68}, 6,1 , 15897,23 , 13,5 , 4,0 , 4797,6 , 4852,9 , 2, 1, 1, 6, 7 }, // Fulah/Latin/Liberia
+ { 177, 7, 136, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 18,7 , 25,12 , 27061,48 , 27109,77 , 27186,24 , 27061,48 , 27109,77 , 27186,24 , 14453,28 , 14481,59 , 14540,14 , 14453,28 , 14481,59 , 14540,14 , 492,6 , 471,7 , 45,4 , 5,17 , 22,23 , {77,82,85}, 216,2 , 15920,22 , 13,5 , 4,0 , 4797,6 , 4861,8 , 2, 1, 1, 6, 7 }, // Fulah/Latin/Mauritania
+ { 177, 7, 156, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 27061,48 , 27109,77 , 27186,24 , 27061,48 , 27109,77 , 27186,24 , 14453,28 , 14481,59 , 14540,14 , 14453,28 , 14481,59 , 14540,14 , 492,6 , 471,7 , 45,4 , 5,17 , 22,23 , {88,79,70}, 204,3 , 15826,26 , 13,5 , 4,0 , 4797,6 , 4869,6 , 0, 0, 1, 6, 7 }, // Fulah/Latin/Niger
+ { 177, 7, 157, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 27061,48 , 27109,77 , 27186,24 , 27061,48 , 27109,77 , 27186,24 , 14453,28 , 14481,59 , 14540,14 , 14453,28 , 14481,59 , 14540,14 , 492,6 , 471,7 , 45,4 , 5,17 , 22,23 , {78,71,78}, 178,1 , 15942,23 , 13,5 , 4,0 , 4797,6 , 4875,9 , 2, 1, 1, 6, 7 }, // Fulah/Latin/Nigeria
+ { 177, 7, 189, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 27061,48 , 27109,77 , 27186,24 , 27061,48 , 27109,77 , 27186,24 , 14453,28 , 14481,59 , 14540,14 , 14453,28 , 14481,59 , 14540,14 , 492,6 , 471,7 , 45,4 , 5,17 , 22,23 , {83,76,76}, 187,2 , 15965,25 , 13,5 , 4,0 , 4797,6 , 4884,11 , 0, 0, 1, 6, 7 }, // Fulah/Latin/Sierra Leone
+ { 177, 134, 91, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {71,78,70}, 213,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Fulah/Adlam/Guinea
+ { 178, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 27210,48 , 27258,185 , 27443,24 , 27210,48 , 27258,185 , 27443,24 , 14554,28 , 14582,63 , 14645,14 , 14554,28 , 14582,63 , 14645,14 , 498,6 , 478,8 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 15990,23 , 4,4 , 4,0 , 4895,6 , 1182,5 , 2, 1, 7, 6, 7 }, // Kikuyu/Latin/Kenya
+ { 179, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 27467,48 , 27515,173 , 27688,24 , 27467,48 , 27515,173 , 27688,24 , 14659,28 , 14687,105 , 14792,14 , 14659,28 , 14687,105 , 14792,14 , 504,7 , 486,5 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 16013,25 , 4,4 , 4,0 , 4901,8 , 1182,5 , 2, 1, 7, 6, 7 }, // Samburu/Latin/Kenya
+ { 180, 7, 146, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 669,27 , 37,5 , 8,10 , 27712,48 , 27760,88 , 134,24 , 27712,48 , 27760,88 , 134,24 , 14806,28 , 14834,55 , 14889,14 , 14806,28 , 14834,55 , 14889,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {77,90,78}, 273,3 , 16038,28 , 0,4 , 4,0 , 4909,4 , 3309,10 , 2, 1, 7, 6, 7 }, // Sena/Latin/Mozambique
+ { 181, 7, 240, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 27848,52 , 27900,112 , 28012,24 , 27848,52 , 27900,112 , 28012,24 , 14903,28 , 14931,50 , 14981,14 , 14903,28 , 14931,50 , 14981,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,83,68}, 159,3 , 16066,24 , 4,4 , 4,0 , 4913,10 , 1791,8 , 2, 1, 7, 6, 7 }, // North Ndebele/Latin/Zimbabwe
+ { 182, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 28036,39 , 28075,194 , 28269,24 , 28036,39 , 28075,194 , 28269,24 , 14995,29 , 15024,65 , 15089,14 , 14995,29 , 15024,65 , 15089,14 , 511,8 , 491,7 , 45,4 , 5,17 , 22,23 , {84,90,83}, 192,3 , 16090,25 , 4,4 , 4,0 , 4923,9 , 1616,8 , 2, 0, 1, 6, 7 }, // Rombo/Latin/Tanzania
+ { 183, 9, 145, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 28293,48 , 28341,81 , 28422,24 , 28293,48 , 28341,81 , 28422,24 , 15103,30 , 15133,47 , 85,14 , 15103,30 , 15133,47 , 85,14 , 519,6 , 498,8 , 45,4 , 5,17 , 22,23 , {77,65,68}, 0,0 , 16115,21 , 0,4 , 4,0 , 4932,7 , 4939,6 , 2, 1, 1, 6, 7 }, // Tachelhit/Tifinagh/Morocco
+ { 183, 7, 145, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 28446,48 , 28494,81 , 28575,24 , 28446,48 , 28494,81 , 28575,24 , 15180,30 , 15210,48 , 85,14 , 15180,30 , 15210,48 , 85,14 , 525,6 , 506,8 , 45,4 , 5,17 , 22,23 , {77,65,68}, 0,0 , 16136,21 , 0,4 , 4,0 , 4945,10 , 4955,6 , 2, 1, 1, 6, 7 }, // Tachelhit/Latin/Morocco
+ { 184, 7, 3, 44, 160, 59, 37, 48, 45, 43, 122, 171, 187, 8220, 8221, 0,6 , 0,6 , 897,12 , 909,11 , 415,8 , 97,16 , 18,7 , 25,12 , 28599,48 , 28647,82 , 28729,24 , 28753,48 , 28801,84 , 28885,24 , 15258,28 , 15286,34 , 15320,14 , 15334,30 , 15364,51 , 15415,14 , 531,7 , 514,9 , 1195,7 , 1202,21 , 22,23 , {68,90,68}, 202,2 , 16157,53 , 0,4 , 4,0 , 4961,9 , 4970,8 , 2, 1, 6, 5, 6 }, // Kabyle/Latin/Algeria
+ { 185, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 28909,48 , 28957,152 , 134,24 , 28909,48 , 28957,152 , 134,24 , 15429,28 , 15457,74 , 15531,14 , 15429,28 , 15457,74 , 15531,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,71,88}, 197,3 , 16210,26 , 4,4 , 4,0 , 4978,10 , 1681,6 , 0, 0, 1, 6, 7 }, // Nyankole/Latin/Uganda
+ { 186, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 29109,48 , 29157,254 , 29411,24 , 29109,48 , 29157,254 , 29411,24 , 15545,28 , 15573,82 , 15655,14 , 15545,28 , 15573,82 , 15655,14 , 538,7 , 523,7 , 45,4 , 5,17 , 22,23 , {84,90,83}, 192,3 , 16236,29 , 0,4 , 4,0 , 4988,6 , 4994,10 , 2, 0, 1, 6, 7 }, // Bena/Latin/Tanzania
+ { 187, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 19304,48 , 29435,87 , 134,24 , 19304,48 , 29435,87 , 134,24 , 15669,28 , 15697,62 , 15759,14 , 15669,28 , 15697,62 , 15759,14 , 545,5 , 530,9 , 45,4 , 5,17 , 22,23 , {84,90,83}, 192,3 , 16265,27 , 4,4 , 4,0 , 5004,8 , 1616,8 , 2, 0, 1, 6, 7 }, // Vunjo/Latin/Tanzania
+ { 188, 7, 132, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 29522,47 , 29569,92 , 29661,24 , 29522,47 , 29569,92 , 29661,24 , 15773,28 , 15801,44 , 15845,14 , 15773,28 , 15801,44 , 15845,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,79,70}, 204,3 , 16292,24 , 4,4 , 4,0 , 5012,9 , 2155,4 , 0, 0, 1, 6, 7 }, // Bambara/Latin/Mali
+ { 188, 75, 132, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,79,70}, 204,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Bambara/Nko/Mali
+ { 189, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 29685,48 , 29733,207 , 29940,24 , 29685,48 , 29733,207 , 29940,24 , 15859,28 , 15887,64 , 15951,14 , 15859,28 , 15887,64 , 15951,14 , 550,2 , 539,2 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 15802,24 , 4,4 , 4,0 , 5021,6 , 1182,5 , 2, 1, 7, 6, 7 }, // Embu/Latin/Kenya
+ { 190, 12, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 920,9 , 929,8 , 547,6 , 35,18 , 18,7 , 25,12 , 29964,36 , 30000,58 , 30058,24 , 29964,36 , 30000,58 , 30058,24 , 15965,28 , 15993,49 , 16042,14 , 15965,28 , 15993,49 , 16042,14 , 552,3 , 541,6 , 1223,6 , 5,17 , 22,23 , {85,83,68}, 6,1 , 16316,25 , 4,4 , 4,0 , 5027,3 , 5030,15 , 2, 1, 7, 6, 7 }, // Cherokee/Cherokee/United States
+ { 191, 7, 137, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 30082,47 , 30129,68 , 30197,24 , 30082,47 , 30129,68 , 30197,24 , 16056,27 , 16083,48 , 16131,14 , 16056,27 , 16083,48 , 16131,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {77,85,82}, 176,2 , 16341,21 , 41,6 , 4,0 , 5045,14 , 5059,5 , 2, 0, 1, 6, 7 }, // Morisyen/Latin/Mauritius
+ { 192, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 19304,48 , 30221,264 , 134,24 , 19304,48 , 30221,264 , 134,24 , 16145,28 , 16173,133 , 15089,14 , 16145,28 , 16173,133 , 15089,14 , 555,4 , 547,5 , 45,4 , 5,17 , 22,23 , {84,90,83}, 192,3 , 16265,27 , 4,4 , 4,0 , 5064,10 , 1616,8 , 2, 0, 1, 6, 7 }, // Makonde/Latin/Tanzania
+ { 193, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 30485,83 , 30568,111 , 30679,24 , 30485,83 , 30568,111 , 30679,24 , 16306,36 , 16342,63 , 16405,14 , 16306,36 , 16342,63 , 16405,14 , 559,3 , 552,3 , 45,4 , 5,17 , 22,23 , {84,90,83}, 192,3 , 16362,29 , 41,6 , 4,0 , 5074,8 , 5082,9 , 2, 0, 1, 6, 7 }, // Langi/Latin/Tanzania
+ { 194, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 30703,48 , 30751,97 , 134,24 , 30703,48 , 30751,97 , 134,24 , 16419,28 , 16447,66 , 16513,14 , 16419,28 , 16447,66 , 16513,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,71,88}, 197,3 , 16391,26 , 0,4 , 4,0 , 5091,7 , 5098,7 , 0, 0, 1, 6, 7 }, // Ganda/Latin/Uganda
+ { 195, 7, 239, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 18,7 , 25,12 , 30848,48 , 30896,83 , 30979,24 , 30848,48 , 30896,83 , 30979,24 , 16527,80 , 16527,80 , 85,14 , 16527,80 , 16527,80 , 85,14 , 562,8 , 555,7 , 45,4 , 5,17 , 22,23 , {90,77,87}, 131,1 , 0,7 , 4,4 , 4,0 , 5105,9 , 1785,6 , 2, 1, 1, 6, 7 }, // Bemba/Latin/Zambia
+ { 196, 7, 39, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 163,7 , 163,7 , 415,8 , 1623,27 , 37,5 , 8,10 , 31003,48 , 31051,85 , 134,24 , 31003,48 , 31051,85 , 134,24 , 16607,28 , 16635,73 , 16708,14 , 16607,28 , 16722,73 , 16708,14 , 68,2 , 65,2 , 45,4 , 323,17 , 22,23 , {67,86,69}, 272,1 , 16417,43 , 13,5 , 4,0 , 5114,12 , 5126,10 , 2, 1, 1, 6, 7 }, // Kabuverdianu/Latin/Cape Verde
+ { 197, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 31136,48 , 31184,86 , 31270,24 , 31136,48 , 31184,86 , 31270,24 , 16795,28 , 16823,51 , 16874,14 , 16795,28 , 16823,51 , 16874,14 , 570,2 , 562,2 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 15802,24 , 4,4 , 4,0 , 5136,6 , 1182,5 , 2, 1, 7, 6, 7 }, // Meru/Latin/Kenya
+ { 198, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 31294,49 , 31343,121 , 31464,24 , 31294,49 , 31343,121 , 31464,24 , 16888,28 , 16916,53 , 16969,14 , 16888,28 , 16916,53 , 16969,14 , 572,6 , 564,10 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 16460,26 , 4,4 , 4,0 , 5142,8 , 5150,12 , 2, 1, 7, 6, 7 }, // Kalenjin/Latin/Kenya
+ { 199, 7, 148, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 18,7 , 25,12 , 0,48 , 31488,136 , 134,24 , 0,48 , 31488,136 , 134,24 , 16983,23 , 17006,92 , 17098,14 , 16983,23 , 17006,92 , 17098,14 , 578,7 , 574,5 , 45,4 , 5,17 , 22,23 , {78,65,68}, 6,1 , 16486,22 , 4,4 , 4,0 , 5162,13 , 5175,8 , 2, 1, 1, 6, 7 }, // Nama/Latin/Namibia
+ { 200, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 19304,48 , 29435,87 , 134,24 , 19304,48 , 29435,87 , 134,24 , 15669,28 , 15697,62 , 15759,14 , 15669,28 , 15697,62 , 15759,14 , 545,5 , 530,9 , 45,4 , 5,17 , 22,23 , {84,90,83}, 192,3 , 16265,27 , 4,4 , 4,0 , 5183,9 , 1616,8 , 2, 0, 1, 6, 7 }, // Machame/Latin/Tanzania
+ { 201, 7, 82, 44, 160, 59, 37, 48, 8722, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 453,8 , 453,8 , 1117,10 , 1650,23 , 37,5 , 8,10 , 31624,59 , 31683,87 , 12992,24 , 31770,48 , 31683,87 , 12992,24 , 17112,28 , 17140,72 , 3668,14 , 17112,28 , 17140,72 , 3668,14 , 585,16 , 579,16 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 16508,11 , 13,5 , 4,0 , 5192,6 , 5198,11 , 2, 1, 1, 6, 7 }, // Colognian/Latin/Germany
+ { 202, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 31818,51 , 31869,132 , 158,27 , 31818,51 , 31869,132 , 158,27 , 15669,28 , 17212,58 , 15089,14 , 15669,28 , 17212,58 , 15089,14 , 601,9 , 595,6 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 16519,25 , 4,4 , 4,0 , 5209,3 , 1182,5 , 2, 1, 7, 6, 7 }, // Masai/Latin/Kenya
+ { 202, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 31818,51 , 31869,132 , 158,27 , 31818,51 , 31869,132 , 158,27 , 15669,28 , 17212,58 , 15089,14 , 15669,28 , 17212,58 , 15089,14 , 601,9 , 595,6 , 45,4 , 5,17 , 22,23 , {84,90,83}, 192,3 , 16544,28 , 4,4 , 4,0 , 5209,3 , 5212,8 , 2, 0, 1, 6, 7 }, // Masai/Latin/Tanzania
+ { 203, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 30703,48 , 30751,97 , 134,24 , 30703,48 , 30751,97 , 134,24 , 17270,35 , 17305,65 , 17370,14 , 17270,35 , 17305,65 , 17370,14 , 610,6 , 601,6 , 45,4 , 5,17 , 22,23 , {85,71,88}, 197,3 , 16391,26 , 13,5 , 4,0 , 5220,7 , 5098,7 , 0, 0, 1, 6, 7 }, // Soga/Latin/Uganda
+ { 204, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 32001,48 , 19352,84 , 134,24 , 32001,48 , 19352,84 , 134,24 , 17384,21 , 17405,75 , 85,14 , 17384,21 , 17405,75 , 85,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 16572,23 , 4,4 , 102,6 , 5227,7 , 1182,5 , 2, 1, 7, 6, 7 }, // Luyia/Latin/Kenya
+ { 205, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 32049,48 , 19352,84 , 134,24 , 32049,48 , 19352,84 , 134,24 , 17480,28 , 10047,60 , 15759,14 , 17480,28 , 10047,60 , 15759,14 , 616,9 , 607,8 , 45,4 , 5,17 , 22,23 , {84,90,83}, 192,3 , 16595,28 , 13,5 , 4,0 , 5234,6 , 5240,8 , 2, 0, 1, 6, 7 }, // Asu/Latin/Tanzania
+ { 206, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 32097,48 , 32145,94 , 32239,24 , 32097,48 , 32145,94 , 32239,24 , 17508,28 , 17536,69 , 17605,14 , 17508,28 , 17536,69 , 17605,14 , 625,9 , 615,6 , 45,4 , 5,17 , 22,23 , {85,71,88}, 197,3 , 16623,28 , 4,4 , 4,0 , 5248,6 , 1681,6 , 0, 0, 1, 6, 7 }, // Teso/Latin/Uganda
+ { 206, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 32097,48 , 32145,94 , 32239,24 , 32097,48 , 32145,94 , 32239,24 , 17508,28 , 17536,69 , 17605,14 , 17508,28 , 17536,69 , 17605,14 , 625,9 , 615,6 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 16651,27 , 4,4 , 4,0 , 5248,6 , 5254,5 , 2, 1, 7, 6, 7 }, // Teso/Latin/Kenya
{ 207, 7, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,82,78}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Saho/Latin/Eritrea
- { 208, 7, 132, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 30134,46 , 30180,88 , 30268,24 , 30134,46 , 30180,88 , 30268,24 , 16543,28 , 16571,53 , 16624,14 , 16543,28 , 16571,53 , 16624,14 , 589,6 , 575,6 , 45,4 , 5,17 , 22,23 , {88,79,70}, 210,3 , 16152,23 , 0,4 , 4,0 , 5018,11 , 5029,5 , 0, 0, 1, 6, 7 }, // Koyra Chiini/Latin/Mali
- { 209, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 18222,48 , 27306,87 , 134,24 , 18222,48 , 27306,87 , 134,24 , 14593,28 , 14621,62 , 14683,14 , 14593,28 , 14621,62 , 14683,14 , 500,5 , 484,9 , 45,4 , 5,17 , 22,23 , {84,90,83}, 198,3 , 15739,27 , 0,4 , 4,0 , 5034,6 , 1587,8 , 0, 0, 1, 6, 7 }, // Rwa/Latin/Tanzania
- { 210, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 30292,48 , 30340,186 , 30526,24 , 30292,48 , 30340,186 , 30526,24 , 16638,28 , 16666,69 , 16735,14 , 16638,28 , 16666,69 , 16735,14 , 595,2 , 581,2 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 16175,23 , 0,4 , 4,0 , 5040,6 , 1153,5 , 2, 1, 7, 6, 7 }, // Luo/Latin/Kenya
- { 211, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 26780,48 , 26828,152 , 134,24 , 26780,48 , 26828,152 , 134,24 , 14353,28 , 14381,74 , 14455,14 , 14353,28 , 14381,74 , 14455,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,71,88}, 203,3 , 15684,26 , 4,4 , 4,0 , 5046,6 , 1652,6 , 0, 0, 1, 6, 7 }, // Chiga/Latin/Uganda
- { 212, 7, 145, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 30550,48 , 30598,86 , 30684,24 , 30550,48 , 30598,86 , 30684,24 , 16749,28 , 16777,48 , 16825,14 , 16749,28 , 16777,48 , 16825,14 , 597,9 , 583,10 , 45,4 , 5,17 , 22,23 , {77,65,68}, 0,0 , 16198,22 , 13,5 , 4,0 , 5052,17 , 5069,6 , 2, 1, 6, 5, 6 }, // Central Morocco Tamazight/Latin/Morocco
- { 213, 7, 132, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 30134,46 , 30180,88 , 30268,24 , 30134,46 , 30180,88 , 30268,24 , 16839,28 , 16867,54 , 16624,14 , 16839,28 , 16867,54 , 16624,14 , 589,6 , 575,6 , 45,4 , 5,17 , 22,23 , {88,79,70}, 210,3 , 16152,23 , 0,4 , 4,0 , 5075,15 , 5029,5 , 0, 0, 1, 6, 7 }, // Koyraboro Senni/Latin/Mali
- { 214, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 18222,48 , 30708,84 , 134,24 , 18222,48 , 30708,84 , 134,24 , 16921,28 , 16949,63 , 17012,14 , 16921,28 , 16949,63 , 17012,14 , 606,5 , 593,8 , 45,4 , 5,17 , 22,23 , {84,90,83}, 198,3 , 16220,27 , 0,4 , 4,0 , 5090,9 , 1587,8 , 0, 0, 1, 6, 7 }, // Shambala/Latin/Tanzania
- { 215, 13, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 516,6 , 35,18 , 18,7 , 25,12 , 30792,88 , 30792,88 , 30880,31 , 30792,88 , 30792,88 , 30880,31 , 17026,33 , 17059,54 , 17113,19 , 17026,33 , 17059,54 , 17113,19 , 611,3 , 601,6 , 45,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 16247,10 , 8,5 , 4,0 , 5099,4 , 2589,4 , 2, 1, 7, 7, 7 }, // Bodo/Devanagari/India
- { 218, 2, 178, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 20846,48 , 11053,80 , 158,27 , 20846,48 , 11053,80 , 158,27 , 17132,74 , 17132,74 , 85,14 , 17132,74 , 17132,74 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {82,85,66}, 129,1 , 16257,43 , 13,5 , 4,0 , 5103,7 , 5110,5 , 2, 1, 1, 6, 7 }, // Chechen/Cyrillic/Russia
- { 219, 2, 178, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 766,8 , 766,8 , 1494,10 , 1504,23 , 37,5 , 8,10 , 30911,65 , 30976,117 , 31093,30 , 30911,65 , 31123,117 , 31093,30 , 17206,37 , 17243,68 , 10707,14 , 17206,37 , 17243,68 , 10707,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {82,85,66}, 129,1 , 16300,44 , 13,5 , 4,0 , 5115,19 , 5134,7 , 2, 1, 1, 6, 7 }, // Church/Cyrillic/Russia
- { 220, 2, 178, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {82,85,66}, 129,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Chuvash/Cyrillic/Russia
- { 230, 7, 49, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 31240,49 , 31289,99 , 31388,24 , 31240,49 , 31289,99 , 31388,24 , 17311,28 , 17339,50 , 17389,14 , 17311,28 , 17339,50 , 17389,14 , 614,5 , 607,6 , 45,4 , 5,17 , 22,23 , {67,68,70}, 215,2 , 16344,24 , 0,4 , 4,0 , 5141,8 , 5149,16 , 2, 1, 1, 6, 7 }, // LubaKatanga/Latin/CongoKinshasa
- { 231, 7, 125, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 774,10 , 774,10 , 175,8 , 532,18 , 37,5 , 8,10 , 31412,48 , 31460,85 , 134,24 , 31545,59 , 31460,85 , 134,24 , 17403,28 , 17431,65 , 3642,14 , 17496,35 , 17431,65 , 3642,14 , 619,5 , 613,8 , 409,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8339,19 , 13,5 , 4,0 , 5165,14 , 5179,10 , 2, 1, 1, 6, 7 }, // Luxembourgish/Latin/Luxembourg
+ { 208, 7, 132, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 32263,46 , 32309,88 , 32397,24 , 32263,46 , 32309,88 , 32397,24 , 17619,28 , 17647,53 , 17700,14 , 17619,28 , 17647,53 , 17700,14 , 634,6 , 621,6 , 45,4 , 5,17 , 22,23 , {88,79,70}, 204,3 , 16678,23 , 0,4 , 4,0 , 5259,11 , 5270,5 , 0, 0, 1, 6, 7 }, // Koyra Chiini/Latin/Mali
+ { 209, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 19304,48 , 29435,87 , 134,24 , 19304,48 , 29435,87 , 134,24 , 15669,28 , 15697,62 , 15759,14 , 15669,28 , 15697,62 , 15759,14 , 545,5 , 530,9 , 45,4 , 5,17 , 22,23 , {84,90,83}, 192,3 , 16265,27 , 0,4 , 4,0 , 5275,6 , 1616,8 , 2, 0, 1, 6, 7 }, // Rwa/Latin/Tanzania
+ { 210, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 32421,48 , 32469,186 , 32655,24 , 32421,48 , 32469,186 , 32655,24 , 17714,28 , 17742,69 , 17811,14 , 17714,28 , 17742,69 , 17811,14 , 640,2 , 627,2 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 16701,23 , 0,4 , 4,0 , 5281,6 , 1182,5 , 2, 1, 7, 6, 7 }, // Luo/Latin/Kenya
+ { 211, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 28909,48 , 28957,152 , 134,24 , 28909,48 , 28957,152 , 134,24 , 15429,28 , 15457,74 , 15531,14 , 15429,28 , 15457,74 , 15531,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,71,88}, 197,3 , 16210,26 , 4,4 , 4,0 , 5287,6 , 1681,6 , 0, 0, 1, 6, 7 }, // Chiga/Latin/Uganda
+ { 212, 7, 145, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 32679,48 , 32727,86 , 32813,24 , 32679,48 , 32727,86 , 32813,24 , 17825,28 , 17853,48 , 17901,14 , 17825,28 , 17853,48 , 17901,14 , 642,9 , 629,10 , 45,4 , 5,17 , 22,23 , {77,65,68}, 0,0 , 16724,22 , 13,5 , 4,0 , 5293,17 , 5310,6 , 2, 1, 1, 6, 7 }, // Central Morocco Tamazight/Latin/Morocco
+ { 213, 7, 132, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 32263,46 , 32309,88 , 32397,24 , 32263,46 , 32309,88 , 32397,24 , 17915,28 , 17943,54 , 17700,14 , 17915,28 , 17943,54 , 17700,14 , 634,6 , 621,6 , 45,4 , 5,17 , 22,23 , {88,79,70}, 204,3 , 16678,23 , 0,4 , 4,0 , 5316,15 , 5270,5 , 0, 0, 1, 6, 7 }, // Koyraboro Senni/Latin/Mali
+ { 214, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 19304,48 , 32837,84 , 134,24 , 19304,48 , 32837,84 , 134,24 , 17997,28 , 18025,63 , 18088,14 , 17997,28 , 18025,63 , 18088,14 , 651,5 , 639,8 , 45,4 , 5,17 , 22,23 , {84,90,83}, 192,3 , 16746,27 , 0,4 , 4,0 , 5331,9 , 1616,8 , 2, 0, 1, 6, 7 }, // Shambala/Latin/Tanzania
+ { 215, 13, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 547,6 , 35,18 , 18,7 , 25,12 , 32921,88 , 32921,88 , 33009,31 , 32921,88 , 32921,88 , 33009,31 , 18102,33 , 18135,54 , 18189,19 , 18102,33 , 18135,54 , 18189,19 , 656,3 , 647,6 , 45,4 , 5,17 , 22,23 , {73,78,82}, 121,1 , 16773,10 , 8,5 , 4,0 , 5340,4 , 2633,4 , 2, 1, 7, 7, 7 }, // Bodo/Devanagari/India
+ { 218, 2, 178, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 22132,48 , 11141,80 , 11058,24 , 22132,48 , 11141,80 , 11058,24 , 18208,25 , 18233,45 , 18278,17 , 18208,25 , 18233,45 , 18208,25 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {82,85,66}, 123,1 , 16783,43 , 13,5 , 4,0 , 5344,7 , 5351,5 , 2, 1, 1, 6, 7 }, // Chechen/Cyrillic/Russia
+ { 219, 2, 178, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 937,8 , 937,8 , 993,10 , 1673,23 , 37,5 , 8,10 , 33040,65 , 33105,117 , 33222,30 , 33040,65 , 33252,117 , 33222,30 , 18295,37 , 18332,68 , 11472,14 , 18295,37 , 18332,68 , 11472,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {82,85,66}, 123,1 , 16826,44 , 13,5 , 4,0 , 5356,19 , 5375,7 , 2, 1, 1, 6, 7 }, // Church/Cyrillic/Russia
+ { 220, 2, 178, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {82,85,66}, 123,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Chuvash/Cyrillic/Russia
+ { 230, 7, 49, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 33369,49 , 33418,99 , 33517,24 , 33369,49 , 33418,99 , 33517,24 , 18400,28 , 18428,50 , 18478,14 , 18400,28 , 18428,50 , 18478,14 , 659,5 , 653,6 , 45,4 , 5,17 , 22,23 , {67,68,70}, 207,2 , 16870,24 , 0,4 , 4,0 , 5382,8 , 5390,16 , 2, 1, 1, 6, 7 }, // Luba Katanga/Latin/Congo Kinshasa
+ { 231, 7, 125, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 945,10 , 945,10 , 156,8 , 622,18 , 37,5 , 8,10 , 33541,48 , 33589,85 , 134,24 , 33674,59 , 33589,85 , 134,24 , 18492,28 , 18520,65 , 3668,14 , 18585,35 , 18520,65 , 3668,14 , 664,5 , 659,8 , 479,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8384,19 , 13,5 , 4,0 , 5406,14 , 5420,10 , 2, 1, 1, 6, 7 }, // Luxembourgish/Latin/Luxembourg
{ 236, 7, 21, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Walloon/Latin/Belgium
- { 237, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 31604,48 , 31652,195 , 31847,24 , 31604,48 , 31652,195 , 31847,24 , 17531,28 , 17559,72 , 17631,14 , 17531,28 , 17559,72 , 17631,14 , 624,3 , 621,3 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16368,21 , 0,4 , 4,0 , 5189,5 , 5194,7 , 0, 0, 1, 6, 7 }, // Aghem/Latin/Cameroon
- { 238, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 31871,48 , 31919,90 , 32009,24 , 31871,48 , 31919,90 , 32009,24 , 17645,28 , 17673,70 , 17743,14 , 17645,28 , 17673,70 , 17743,14 , 627,10 , 624,9 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16389,22 , 13,5 , 4,0 , 5201,5 , 5206,8 , 0, 0, 1, 6, 7 }, // Basaa/Latin/Cameroon
- { 239, 7, 156, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 30134,46 , 30180,88 , 30268,24 , 30134,46 , 30180,88 , 30268,24 , 16839,28 , 17757,53 , 17810,14 , 16839,28 , 17757,53 , 17810,14 , 637,8 , 633,10 , 45,4 , 5,17 , 22,23 , {88,79,70}, 210,3 , 16152,23 , 0,4 , 4,0 , 5214,10 , 5224,5 , 0, 0, 1, 6, 7 }, // Zarma/Latin/Niger
- { 240, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 32033,49 , 32082,99 , 32181,24 , 32033,49 , 32082,99 , 32181,24 , 17824,28 , 17852,45 , 17897,14 , 17824,28 , 17852,45 , 17897,14 , 645,5 , 643,6 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 0,7 , 13,5 , 4,0 , 5229,5 , 1903,8 , 0, 0, 1, 6, 7 }, // Duala/Latin/Cameroon
- { 241, 7, 187, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 32205,36 , 32241,82 , 32323,24 , 32205,36 , 32241,82 , 32323,24 , 17911,28 , 17939,50 , 17989,14 , 17911,28 , 17939,50 , 17989,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,79,70}, 210,3 , 16411,23 , 13,5 , 4,0 , 5234,5 , 5239,7 , 0, 0, 1, 6, 7 }, // JolaFonyi/Latin/Senegal
- { 242, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 32347,50 , 32397,141 , 32538,24 , 32347,50 , 32397,141 , 32538,24 , 18003,30 , 18033,85 , 18118,14 , 18003,30 , 18033,85 , 18118,14 , 650,7 , 649,9 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16434,23 , 13,5 , 4,0 , 5246,6 , 5252,7 , 0, 0, 1, 6, 7 }, // Ewondo/Latin/Cameroon
- { 243, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 32562,39 , 32601,191 , 158,27 , 32562,39 , 32601,191 , 158,27 , 18132,29 , 18161,45 , 18206,14 , 18132,29 , 18161,45 , 18206,14 , 657,6 , 658,7 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16457,11 , 13,5 , 4,0 , 5259,5 , 5264,7 , 0, 0, 1, 6, 7 }, // Bafia/Latin/Cameroon
- { 244, 7, 146, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 32792,48 , 32840,213 , 33053,24 , 32792,48 , 32840,213 , 33053,24 , 18220,28 , 18248,59 , 18307,14 , 18220,28 , 18248,59 , 18307,14 , 663,8 , 665,10 , 45,4 , 5,17 , 22,23 , {77,90,78}, 284,3 , 0,7 , 79,6 , 4,0 , 5271,5 , 5276,10 , 2, 1, 7, 6, 7 }, // MakhuwaMeetto/Latin/Mozambique
- { 245, 7, 37, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 33077,48 , 33125,139 , 33264,24 , 33077,48 , 33125,139 , 33264,24 , 18321,28 , 18349,74 , 18423,14 , 18321,28 , 18349,74 , 18423,14 , 671,5 , 675,5 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16468,17 , 4,4 , 4,0 , 5286,6 , 5292,7 , 0, 0, 1, 6, 7 }, // Mundang/Latin/Cameroon
- { 246, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 171, 187, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 33288,51 , 33339,143 , 158,27 , 33288,51 , 33339,143 , 158,27 , 18437,30 , 18467,89 , 18556,14 , 18437,30 , 18467,89 , 18556,14 , 676,4 , 680,4 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16485,20 , 13,5 , 4,0 , 5299,6 , 5305,7 , 0, 0, 1, 6, 7 }, // Kwasio/Latin/Cameroon
- { 247, 7, 254, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 1527,9 , 98,16 , 18,7 , 481,12 , 33482,54 , 33536,96 , 33632,24 , 33482,54 , 33536,96 , 33632,24 , 18570,38 , 18608,79 , 18687,14 , 18570,38 , 18608,79 , 18687,14 , 680,2 , 684,2 , 45,4 , 5,17 , 22,23 , {83,83,80}, 125,1 , 0,7 , 4,4 , 4,0 , 5312,9 , 0,0 , 2, 1, 1, 6, 7 }, // Nuer/Latin/SouthSudan
- { 248, 2, 178, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 784,11 , 784,11 , 246,6 , 1536,30 , 37,5 , 8,10 , 33656,50 , 33706,116 , 33822,24 , 33656,50 , 33846,121 , 33822,24 , 18701,21 , 18722,71 , 18793,14 , 18701,21 , 18722,71 , 18793,14 , 682,2 , 686,2 , 948,5 , 953,17 , 22,23 , {82,85,66}, 129,1 , 16505,47 , 13,5 , 4,0 , 5321,9 , 5330,9 , 2, 1, 1, 6, 7 }, // Sakha/Cyrillic/Russia
- { 249, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 33967,48 , 34015,117 , 158,27 , 33967,48 , 34015,117 , 158,27 , 18807,28 , 18835,60 , 18895,14 , 18807,28 , 18835,60 , 18895,14 , 684,9 , 688,9 , 45,4 , 5,17 , 22,23 , {84,90,83}, 198,3 , 16552,25 , 0,4 , 4,0 , 5339,9 , 5348,9 , 0, 0, 1, 6, 7 }, // Sangu/Latin/Tanzania
- { 251, 7, 156, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 30134,46 , 30180,88 , 30268,24 , 30134,46 , 30180,88 , 30268,24 , 16839,28 , 16867,54 , 16624,14 , 16839,28 , 16867,54 , 16624,14 , 637,8 , 633,10 , 45,4 , 5,17 , 22,23 , {88,79,70}, 210,3 , 16152,23 , 0,4 , 4,0 , 5357,13 , 5224,5 , 0, 0, 1, 6, 7 }, // Tasawaq/Latin/Niger
- { 252, 35, 121, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 18,7 , 25,12 , 34132,50 , 34132,50 , 158,27 , 34132,50 , 34132,50 , 158,27 , 18909,30 , 18909,30 , 85,14 , 18909,30 , 18909,30 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {76,82,68}, 6,1 , 16577,15 , 4,4 , 4,0 , 5370,2 , 5372,4 , 2, 1, 1, 6, 7 }, // Vai/Vai/Liberia
- { 252, 7, 121, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 18,7 , 25,12 , 34182,81 , 34182,81 , 158,27 , 34182,81 , 34182,81 , 158,27 , 18939,48 , 18939,48 , 85,14 , 18939,48 , 18939,48 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {76,82,68}, 6,1 , 16592,20 , 4,4 , 4,0 , 5376,3 , 5379,8 , 2, 1, 1, 6, 7 }, // Vai/Latin/Liberia
- { 253, 7, 206, 44, 8217, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 251,9 , 251,9 , 53,10 , 532,18 , 37,5 , 8,10 , 34263,48 , 34311,99 , 34410,24 , 34263,48 , 34311,99 , 34410,24 , 18987,28 , 19015,53 , 19068,14 , 18987,28 , 19015,53 , 19068,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,72,70}, 0,0 , 0,7 , 79,6 , 4,0 , 5387,6 , 5393,6 , 2, 0, 1, 6, 7 }, // Walser/Latin/Switzerland
- { 254, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 34434,51 , 34485,191 , 158,27 , 34434,51 , 34485,191 , 158,27 , 19082,21 , 19103,71 , 19174,14 , 19082,21 , 19103,71 , 19174,14 , 693,8 , 697,8 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 0,7 , 13,5 , 4,0 , 5399,6 , 5405,7 , 0, 0, 1, 6, 7 }, // Yangben/Latin/Cameroon
- { 256, 7, 197, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 363,22 , 37,5 , 8,10 , 34676,48 , 34724,85 , 34809,24 , 34833,48 , 34881,117 , 34809,24 , 19188,28 , 19216,54 , 3338,14 , 19188,28 , 19216,54 , 3338,14 , 701,12 , 705,11 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 5412,9 , 2354,6 , 2, 1, 1, 6, 7 }, // Asturian/Latin/Spain
- { 257, 7, 37, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 795,11 , 795,11 , 806,16 , 822,9 , 53,10 , 1353,18 , 37,5 , 8,10 , 34998,174 , 34998,174 , 158,27 , 34998,174 , 34998,174 , 158,27 , 19270,60 , 19270,60 , 19330,25 , 19270,60 , 19270,60 , 19330,25 , 713,8 , 716,13 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16612,12 , 8,5 , 4,0 , 5421,5 , 5426,7 , 0, 0, 1, 6, 7 }, // Ngomba/Latin/Cameroon
- { 258, 7, 37, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 0,6 , 0,6 , 1566,10 , 633,17 , 37,5 , 8,10 , 35172,102 , 35172,102 , 158,27 , 35172,102 , 35172,102 , 158,27 , 19355,54 , 19355,54 , 19409,21 , 19355,54 , 19355,54 , 19409,21 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16624,16 , 79,6 , 4,0 , 5433,4 , 5437,7 , 0, 0, 1, 6, 7 }, // Kako/Latin/Cameroon
- { 259, 7, 37, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 1353,18 , 37,5 , 8,10 , 35274,137 , 35411,142 , 35553,36 , 35274,137 , 35411,142 , 35553,36 , 19430,49 , 19430,49 , 19479,21 , 19430,49 , 19430,49 , 19479,21 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16640,12 , 8,5 , 4,0 , 5444,5 , 5449,7 , 0, 0, 1, 6, 7 }, // Meta/Latin/Cameroon
- { 260, 7, 37, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1576,32 , 37,5 , 8,10 , 35589,165 , 35589,165 , 158,27 , 35589,165 , 35589,165 , 158,27 , 19500,111 , 19500,111 , 85,14 , 19500,111 , 19500,111 , 85,14 , 721,9 , 729,8 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16652,16 , 8,5 , 4,0 , 5456,16 , 5472,7 , 0, 0, 1, 6, 7 }, // Ngiemboon/Latin/Cameroon
- { 272, 46, 18, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {66,68,84}, 130,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 5, 6, 7 }, // Chakma/Chakma/Bangladesh
- { 290, 11, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 7, 7 }, // Manipuri/Bengali/India
- { 309, 100, 232, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {86,78,68}, 340,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // TaiDam/Tai Viet/Vietnam
+ { 237, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 33733,48 , 33781,195 , 33976,24 , 33733,48 , 33781,195 , 33976,24 , 18620,28 , 18648,72 , 18720,14 , 18620,28 , 18648,72 , 18720,14 , 669,3 , 667,3 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16894,21 , 0,4 , 4,0 , 5430,5 , 5435,7 , 0, 0, 1, 6, 7 }, // Aghem/Latin/Cameroon
+ { 238, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 34000,48 , 34048,90 , 34138,24 , 34000,48 , 34048,90 , 34138,24 , 18734,28 , 18762,70 , 18832,14 , 18734,28 , 18762,70 , 18832,14 , 672,10 , 670,9 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16915,22 , 13,5 , 4,0 , 5442,5 , 5447,8 , 0, 0, 1, 6, 7 }, // Basaa/Latin/Cameroon
+ { 239, 7, 156, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 32263,46 , 32309,88 , 32397,24 , 32263,46 , 32309,88 , 32397,24 , 17915,28 , 18846,53 , 18899,14 , 17915,28 , 18846,53 , 18899,14 , 682,8 , 679,10 , 45,4 , 5,17 , 22,23 , {88,79,70}, 204,3 , 16678,23 , 0,4 , 4,0 , 5455,10 , 5465,5 , 0, 0, 1, 6, 7 }, // Zarma/Latin/Niger
+ { 240, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 34162,49 , 34211,99 , 34310,24 , 34162,49 , 34211,99 , 34310,24 , 18913,28 , 18941,45 , 18986,14 , 18913,28 , 18941,45 , 18986,14 , 690,5 , 689,6 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 0,7 , 13,5 , 4,0 , 5470,5 , 1952,8 , 0, 0, 1, 6, 7 }, // Duala/Latin/Cameroon
+ { 241, 7, 187, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 34334,36 , 34370,82 , 34452,24 , 34334,36 , 34370,82 , 34452,24 , 19000,28 , 19028,50 , 19078,14 , 19000,28 , 19028,50 , 19078,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,79,70}, 204,3 , 16937,23 , 13,5 , 4,0 , 5475,5 , 5480,7 , 0, 0, 1, 6, 7 }, // Jola Fonyi/Latin/Senegal
+ { 242, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 34476,50 , 34526,141 , 34667,24 , 34476,50 , 34526,141 , 34667,24 , 19092,30 , 19122,85 , 19207,14 , 19092,30 , 19122,85 , 19207,14 , 695,7 , 695,9 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16960,23 , 13,5 , 4,0 , 5487,6 , 5493,7 , 0, 0, 1, 6, 7 }, // Ewondo/Latin/Cameroon
+ { 243, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 34691,39 , 34730,191 , 158,27 , 34691,39 , 34730,191 , 158,27 , 19221,29 , 19250,45 , 19295,14 , 19221,29 , 19250,45 , 19295,14 , 702,6 , 704,7 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16983,11 , 13,5 , 4,0 , 5500,5 , 5505,7 , 0, 0, 1, 6, 7 }, // Bafia/Latin/Cameroon
+ { 244, 7, 146, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 34921,48 , 34969,213 , 35182,24 , 34921,48 , 34969,213 , 35182,24 , 19309,28 , 19337,59 , 19396,14 , 19309,28 , 19337,59 , 19396,14 , 708,8 , 711,10 , 45,4 , 5,17 , 22,23 , {77,90,78}, 273,3 , 0,7 , 41,6 , 4,0 , 5512,5 , 5517,10 , 2, 1, 7, 6, 7 }, // Makhuwa Meetto/Latin/Mozambique
+ { 245, 7, 37, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 35206,48 , 35254,139 , 35393,24 , 35206,48 , 35254,139 , 35393,24 , 19410,28 , 19438,74 , 19512,14 , 19410,28 , 19438,74 , 19512,14 , 716,5 , 721,5 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16994,17 , 4,4 , 4,0 , 5527,6 , 5533,7 , 0, 0, 1, 6, 7 }, // Mundang/Latin/Cameroon
+ { 246, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 171, 187, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 35417,51 , 35468,143 , 158,27 , 35417,51 , 35468,143 , 158,27 , 19526,30 , 19556,89 , 19645,14 , 19526,30 , 19556,89 , 19645,14 , 721,4 , 726,4 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 17011,20 , 13,5 , 4,0 , 5540,6 , 5546,7 , 0, 0, 1, 6, 7 }, // Kwasio/Latin/Cameroon
+ { 247, 7, 254, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 538,9 , 97,16 , 18,7 , 555,12 , 35611,54 , 35665,96 , 35761,24 , 35611,54 , 35665,96 , 35761,24 , 19659,38 , 19697,79 , 19776,14 , 19659,38 , 19697,79 , 19776,14 , 725,2 , 730,2 , 45,4 , 5,17 , 22,23 , {83,83,80}, 119,1 , 0,7 , 4,4 , 4,0 , 5553,9 , 0,0 , 2, 1, 1, 6, 7 }, // Nuer/Latin/South Sudan
+ { 248, 2, 178, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 955,11 , 955,11 , 227,6 , 1696,30 , 37,5 , 8,10 , 35785,50 , 35835,116 , 35951,24 , 35785,50 , 35975,121 , 35951,24 , 19790,21 , 19811,71 , 19882,14 , 19790,21 , 19811,71 , 19882,14 , 727,2 , 732,2 , 1229,5 , 1234,17 , 22,23 , {82,85,66}, 123,1 , 17031,47 , 13,5 , 4,0 , 5562,9 , 5571,9 , 2, 1, 1, 6, 7 }, // Sakha/Cyrillic/Russia
+ { 249, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 37,5 , 8,10 , 36096,48 , 36144,117 , 158,27 , 36096,48 , 36144,117 , 158,27 , 19896,28 , 19924,60 , 19984,14 , 19896,28 , 19924,60 , 19984,14 , 729,9 , 734,9 , 45,4 , 5,17 , 22,23 , {84,90,83}, 192,3 , 17078,25 , 0,4 , 4,0 , 5580,9 , 5589,9 , 2, 0, 1, 6, 7 }, // Sangu/Latin/Tanzania
+ { 251, 7, 156, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 32263,46 , 32309,88 , 32397,24 , 32263,46 , 32309,88 , 32397,24 , 17915,28 , 17943,54 , 17700,14 , 17915,28 , 17943,54 , 17700,14 , 682,8 , 679,10 , 45,4 , 5,17 , 22,23 , {88,79,70}, 204,3 , 16678,23 , 0,4 , 4,0 , 5598,13 , 5465,5 , 0, 0, 1, 6, 7 }, // Tasawaq/Latin/Niger
+ { 252, 35, 121, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 18,7 , 25,12 , 36261,38 , 36299,61 , 158,27 , 36261,38 , 36299,61 , 158,27 , 19998,30 , 19998,30 , 85,14 , 19998,30 , 19998,30 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {76,82,68}, 6,1 , 17103,15 , 4,4 , 4,0 , 5611,2 , 5613,4 , 2, 1, 1, 6, 7 }, // Vai/Vai/Liberia
+ { 252, 7, 121, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 119,10 , 10,17 , 18,7 , 25,12 , 36360,81 , 36360,81 , 158,27 , 36360,81 , 36360,81 , 158,27 , 20028,48 , 20028,48 , 85,14 , 20028,48 , 20028,48 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {76,82,68}, 6,1 , 17118,20 , 4,4 , 4,0 , 5617,3 , 5620,8 , 2, 1, 1, 6, 7 }, // Vai/Latin/Liberia
+ { 253, 7, 206, 44, 8217, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 269,9 , 269,9 , 53,10 , 622,18 , 37,5 , 8,10 , 36441,48 , 36489,99 , 36588,24 , 36441,48 , 36489,99 , 36588,24 , 20076,28 , 20104,53 , 20157,14 , 20076,28 , 20104,53 , 20157,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,72,70}, 0,0 , 0,7 , 41,6 , 4,0 , 5628,6 , 5634,6 , 2, 0, 1, 6, 7 }, // Walser/Latin/Switzerland
+ { 254, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 36612,51 , 36663,191 , 158,27 , 36612,51 , 36663,191 , 158,27 , 20171,21 , 20192,71 , 20263,14 , 20171,21 , 20192,71 , 20263,14 , 738,8 , 743,8 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 0,7 , 13,5 , 4,0 , 5640,6 , 5646,7 , 0, 0, 1, 6, 7 }, // Yangben/Latin/Cameroon
+ { 256, 7, 197, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 675,7 , 675,7 , 269,6 , 372,22 , 37,5 , 8,10 , 36854,48 , 36902,85 , 36987,24 , 37011,48 , 37059,117 , 36987,24 , 20277,28 , 20305,54 , 3364,14 , 20277,28 , 20305,54 , 3364,14 , 746,12 , 751,11 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 5653,9 , 2398,6 , 2, 1, 1, 6, 7 }, // Asturian/Latin/Spain
+ { 257, 7, 37, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 966,11 , 966,11 , 977,16 , 993,9 , 53,10 , 1526,18 , 37,5 , 8,10 , 37176,174 , 37176,174 , 158,27 , 37176,174 , 37176,174 , 158,27 , 20359,60 , 20359,60 , 20419,25 , 20359,60 , 20359,60 , 20419,25 , 758,8 , 762,13 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 17138,12 , 8,5 , 4,0 , 5662,5 , 5667,7 , 0, 0, 1, 6, 7 }, // Ngomba/Latin/Cameroon
+ { 258, 7, 37, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 0,6 , 0,6 , 1726,10 , 80,17 , 37,5 , 8,10 , 37350,102 , 37350,102 , 158,27 , 37350,102 , 37350,102 , 158,27 , 20444,54 , 20444,54 , 20498,21 , 20444,54 , 20444,54 , 20498,21 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 17150,16 , 41,6 , 4,0 , 5674,4 , 5678,7 , 0, 0, 1, 6, 7 }, // Kako/Latin/Cameroon
+ { 259, 7, 37, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 1526,18 , 37,5 , 8,10 , 37452,137 , 37589,142 , 37731,36 , 37452,137 , 37589,142 , 37731,36 , 20519,49 , 20519,49 , 20568,21 , 20519,49 , 20519,49 , 20568,21 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 17166,12 , 8,5 , 4,0 , 5685,5 , 5690,7 , 0, 0, 1, 6, 7 }, // Meta/Latin/Cameroon
+ { 260, 7, 37, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1736,32 , 37,5 , 8,10 , 37767,165 , 37767,165 , 158,27 , 37767,165 , 37767,165 , 158,27 , 20589,111 , 20589,111 , 85,14 , 20589,111 , 20589,111 , 85,14 , 766,9 , 775,8 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 17178,16 , 8,5 , 4,0 , 5697,16 , 5713,7 , 0, 0, 1, 6, 7 }, // Ngiemboon/Latin/Cameroon
+ { 290, 11, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,78,82}, 121,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 7, 7 }, // Manipuri/Bengali/India
+ { 309, 100, 232, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {86,78,68}, 332,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Tai Dam/Tai Viet/Vietnam
{ 312, 7, 37, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Akoose/Latin/Cameroon
- { 313, 7, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 516,6 , 35,18 , 18,7 , 25,12 , 35754,180 , 35754,180 , 158,27 , 35754,180 , 35754,180 , 158,27 , 19611,87 , 19611,87 , 85,14 , 19611,87 , 19611,87 , 19698,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,83,68}, 6,1 , 0,7 , 79,6 , 4,0 , 5479,12 , 5491,22 , 2, 1, 7, 6, 7 }, // Lakota/Latin/UnitedStates
- { 314, 9, 145, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 26318,48 , 26366,81 , 26447,24 , 26318,48 , 26366,81 , 26447,24 , 14103,30 , 19712,48 , 85,14 , 14103,30 , 19712,48 , 85,14 , 474,6 , 452,8 , 45,4 , 5,17 , 22,23 , {77,65,68}, 0,0 , 15621,21 , 0,4 , 4,0 , 5513,8 , 4698,6 , 2, 1, 6, 5, 6 }, // Standard Moroccan Tamazight/Tifinagh/Morocco
+ { 313, 7, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 547,6 , 35,18 , 18,7 , 25,12 , 37932,180 , 37932,180 , 158,27 , 37932,180 , 37932,180 , 158,27 , 20700,87 , 20700,87 , 85,14 , 20700,87 , 20700,87 , 20787,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,83,68}, 6,1 , 0,7 , 41,6 , 4,0 , 5720,12 , 5732,22 , 2, 1, 7, 6, 7 }, // Lakota/Latin/United States
+ { 314, 9, 145, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 28293,48 , 28341,81 , 28422,24 , 28293,48 , 28341,81 , 28422,24 , 15103,30 , 20801,48 , 85,14 , 15103,30 , 20801,48 , 85,14 , 519,6 , 498,8 , 45,4 , 5,17 , 22,23 , {77,65,68}, 0,0 , 16115,21 , 0,4 , 4,0 , 5754,8 , 4939,6 , 2, 1, 1, 6, 7 }, // Standard Moroccan Tamazight/Tifinagh/Morocco
{ 315, 7, 43, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,76,80}, 6,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Mapuche/Latin/Chile
- { 316, 1, 103, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 18,7 , 25,12 , 35934,105 , 35934,105 , 36039,24 , 35934,105 , 35934,105 , 36039,24 , 19760,58 , 19760,58 , 19818,14 , 19760,58 , 19760,58 , 19818,14 , 730,3 , 737,3 , 45,4 , 5,17 , 22,23 , {73,81,68}, 0,0 , 16668,20 , 13,5 , 4,0 , 5521,14 , 5535,5 , 0, 0, 6, 5, 6 }, // Central Kurdish/Arabic/Iraq
- { 316, 1, 102, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 35934,105 , 35934,105 , 36039,24 , 35934,105 , 35934,105 , 36039,24 , 19760,58 , 19760,58 , 19818,14 , 19760,58 , 19760,58 , 19818,14 , 730,3 , 737,3 , 45,4 , 5,17 , 22,23 , {73,82,82}, 0,0 , 16688,19 , 13,5 , 4,0 , 5521,14 , 5540,5 , 0, 0, 6, 5, 5 }, // Central Kurdish/Arabic/Iran
- { 317, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 176,7 , 176,7 , 114,6 , 532,18 , 55,4 , 59,9 , 36063,48 , 36111,85 , 16212,24 , 36196,60 , 36256,93 , 16212,24 , 19832,28 , 19860,53 , 19913,14 , 19832,28 , 19860,53 , 19913,14 , 733,9 , 740,10 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 16707,27 , 13,5 , 4,0 , 5545,14 , 5559,6 , 2, 1, 1, 6, 7 }, // LowerSorbian/Latin/Germany
- { 318, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 176,7 , 176,7 , 114,6 , 532,18 , 493,12 , 59,9 , 36349,48 , 36397,86 , 16212,24 , 36483,60 , 36543,93 , 16212,24 , 19927,28 , 19955,53 , 20008,14 , 19927,28 , 19955,53 , 20008,14 , 733,9 , 750,9 , 970,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 16734,29 , 13,5 , 4,0 , 5565,15 , 5580,6 , 2, 1, 1, 6, 7 }, // UpperSorbian/Latin/Germany
+ { 316, 1, 103, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 18,7 , 25,12 , 38112,105 , 38112,105 , 38217,24 , 38112,105 , 38112,105 , 38217,24 , 20849,58 , 20849,58 , 20907,14 , 20849,58 , 20849,58 , 20907,14 , 775,3 , 783,3 , 45,4 , 5,17 , 22,23 , {73,81,68}, 44,5 , 17194,20 , 13,5 , 4,0 , 5762,14 , 5776,5 , 0, 0, 6, 5, 6 }, // Central Kurdish/Arabic/Iraq
+ { 316, 1, 102, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 38112,105 , 38112,105 , 38217,24 , 38112,105 , 38112,105 , 38217,24 , 20849,58 , 20849,58 , 20907,14 , 20849,58 , 20849,58 , 20907,14 , 775,3 , 783,3 , 45,4 , 5,17 , 22,23 , {73,82,82}, 0,0 , 17214,19 , 13,5 , 4,0 , 5762,14 , 5781,5 , 0, 0, 6, 5, 5 }, // Central Kurdish/Arabic/Iran
+ { 317, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 185,7 , 185,7 , 113,6 , 622,18 , 55,4 , 59,9 , 38241,48 , 38289,85 , 9742,24 , 38374,60 , 38434,93 , 9742,24 , 20921,28 , 20949,53 , 21002,14 , 20921,28 , 20949,53 , 21002,14 , 778,9 , 786,10 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 17233,27 , 13,5 , 4,0 , 5786,14 , 5800,6 , 2, 1, 1, 6, 7 }, // Lower Sorbian/Latin/Germany
+ { 318, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 185,7 , 185,7 , 113,6 , 622,18 , 567,12 , 59,9 , 38527,48 , 38575,86 , 9742,24 , 38661,60 , 38721,93 , 9742,24 , 21016,28 , 21044,53 , 21097,14 , 21016,28 , 21044,53 , 21097,14 , 778,9 , 796,9 , 1251,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 17260,29 , 13,5 , 4,0 , 5806,15 , 5821,6 , 2, 1, 1, 6, 7 }, // Upper Sorbian/Latin/Germany
{ 319, 7, 37, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Kenyang/Latin/Cameroon
- { 320, 7, 38, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,65,68}, 245,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 0, 7, 6, 7 }, // Mohawk/Latin/Canada
- { 321, 75, 91, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {71,78,70}, 221,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Nko/Nko/Guinea
- { 323, 7, 90, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {71,84,81}, 311,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Kiche/Latin/Guatemala
- { 324, 7, 205, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {83,69,75}, 196,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Southern Sami/Latin/Sweden
- { 325, 7, 205, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {83,69,75}, 196,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Lule Sami/Latin/Sweden
- { 326, 7, 73, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 550,8 , 1608,18 , 222,4 , 226,9 , 36636,77 , 36713,140 , 36853,25 , 36636,77 , 36713,140 , 36853,25 , 20022,28 , 20050,70 , 85,14 , 20022,28 , 20120,73 , 20193,14 , 742,3 , 759,3 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 16763,11 , 13,5 , 4,0 , 5586,11 , 5597,5 , 2, 1, 1, 6, 7 }, // Inari Sami/Latin/Finland
+ { 320, 7, 38, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,65,68}, 237,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 0, 7, 6, 7 }, // Mohawk/Latin/Canada
+ { 321, 75, 91, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {71,78,70}, 213,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Nko/Nko/Guinea
+ { 322, 7, 260, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 8222, 8220, 0,6 , 0,6 , 1002,8 , 1002,8 , 156,8 , 1768,27 , 37,5 , 8,10 , 38814,48 , 38862,91 , 38953,24 , 38814,48 , 38862,91 , 38953,24 , 21111,28 , 21139,69 , 21208,14 , 21111,28 , 21139,69 , 21208,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {0,0,0}, 0,0 , 2586,0 , 13,5 , 4,0 , 5827,9 , 5836,6 , 2, 1, 1, 6, 7 }, // Prussian/Latin/World
+ { 323, 7, 90, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {71,84,81}, 300,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Kiche/Latin/Guatemala
+ { 324, 7, 205, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {83,69,75}, 190,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 0, 1, 6, 7 }, // Southern Sami/Latin/Sweden
+ { 325, 7, 205, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {83,69,75}, 190,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 0, 1, 6, 7 }, // Lule Sami/Latin/Sweden
+ { 326, 7, 73, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 640,8 , 1795,18 , 243,4 , 247,9 , 38977,77 , 39054,140 , 39194,25 , 38977,77 , 39054,140 , 39194,25 , 21222,28 , 21250,70 , 85,14 , 21222,28 , 21320,73 , 21393,14 , 787,3 , 805,3 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 17289,11 , 13,5 , 4,0 , 5842,11 , 5853,5 , 2, 1, 1, 6, 7 }, // Inari Sami/Latin/Finland
{ 327, 7, 73, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Skolt Sami/Latin/Finland
- { 328, 7, 13, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {65,85,68}, 344,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Warlpiri/Latin/Australia
- { 346, 1, 102, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 14012,70 , 14012,70 , 158,27 , 14012,70 , 14012,70 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 605,4 , 609,39 , 22,23 , {73,82,82}, 346,3 , 16774,27 , 8,5 , 4,0 , 5602,7 , 3091,5 , 0, 0, 6, 5, 5 }, // Mazanderani/Arabic/Iran
- { 349, 1, 102, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 36878,77 , 36878,77 , 158,27 , 36878,77 , 36878,77 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,82,82}, 0,0 , 0,7 , 8,5 , 4,0 , 5609,11 , 0,0 , 0, 0, 6, 5, 5 }, // Northern Luri/Arabic/Iran
- { 349, 1, 103, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 18,7 , 25,12 , 36878,77 , 36878,77 , 158,27 , 36878,77 , 36878,77 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,81,68}, 0,0 , 0,7 , 8,5 , 4,0 , 5609,11 , 0,0 , 0, 0, 6, 5, 6 }, // Northern Luri/Arabic/Iraq
- { 357, 6, 97, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 161,5 , 161,5 , 831,5 , 831,5 , 385,8 , 414,14 , 170,6 , 187,13 , 4697,39 , 4697,39 , 158,27 , 4697,39 , 4697,39 , 158,27 , 2055,21 , 2013,28 , 2041,14 , 2055,21 , 2013,28 , 2041,14 , 58,2 , 55,2 , 45,4 , 5,17 , 22,23 , {72,75,68}, 140,3 , 16801,11 , 4,4 , 4,0 , 5620,2 , 5622,14 , 2, 1, 7, 6, 7 }, // Cantonese/Traditional Han/HongKong
+ { 328, 7, 13, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {65,85,68}, 336,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Warlpiri/Latin/Australia
+ { 346, 1, 102, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 14934,70 , 14934,70 , 158,27 , 14934,70 , 14934,70 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 747,4 , 1256,39 , 22,23 , {73,82,82}, 338,3 , 17300,27 , 8,5 , 4,0 , 5858,7 , 3190,5 , 0, 0, 6, 5, 5 }, // Mazanderani/Arabic/Iran
+ { 349, 1, 102, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 39219,77 , 39219,77 , 158,27 , 39219,77 , 39219,77 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,82,82}, 0,0 , 0,7 , 8,5 , 4,0 , 5865,11 , 0,0 , 0, 0, 6, 5, 5 }, // Northern Luri/Arabic/Iran
+ { 349, 1, 103, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 18,7 , 25,12 , 39219,77 , 39219,77 , 158,27 , 39219,77 , 39219,77 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,81,68}, 44,5 , 0,7 , 8,5 , 4,0 , 5865,11 , 0,0 , 0, 0, 6, 5, 6 }, // Northern Luri/Arabic/Iraq
+ { 357, 6, 97, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 170,5 , 170,5 , 1010,5 , 1010,5 , 394,8 , 423,14 , 198,6 , 215,13 , 4423,39 , 4423,39 , 158,27 , 4423,39 , 4423,39 , 158,27 , 1953,28 , 1953,28 , 1981,14 , 1953,28 , 1953,28 , 1981,14 , 58,2 , 55,2 , 45,4 , 5,17 , 22,23 , {72,75,68}, 134,3 , 17327,11 , 4,4 , 4,0 , 5876,2 , 5878,14 , 2, 1, 7, 6, 7 }, // Cantonese/Traditional Han/Hong Kong
+ { 357, 5, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 170,5 , 170,5 , 1010,5 , 1010,5 , 394,8 , 402,13 , 198,6 , 204,11 , 4423,39 , 4462,38 , 158,27 , 4423,39 , 4462,38 , 158,27 , 1932,21 , 1953,28 , 1981,14 , 1932,21 , 1953,28 , 1981,14 , 58,2 , 55,2 , 45,4 , 5,17 , 22,23 , {67,78,89}, 133,1 , 3122,13 , 4,4 , 4,0 , 5892,2 , 5894,7 , 2, 1, 7, 6, 7 }, // Cantonese/Simplified Han/China
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, {0,0,0}, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0, 0, 0, 0, 0 } // trailing 0s
};
@@ -1818,45 +1840,54 @@ static const ushort list_pattern_part_data[] = {
0x25, 0x31, 0x2c, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x65, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x64, 0x68, 0x65,
0x20, 0x25, 0x32, 0x25, 0x31, 0x1363, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x12a5, 0x1293, 0x20, 0x25, 0x32, 0x25, 0x31,
0x20, 0x12a5, 0x1293, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x20, 0x648, 0x25, 0x32, 0x25,
-0x31, 0x20, 0x648, 0x25, 0x32, 0x25, 0x31, 0x20, 0x587, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x76, 0x259, 0x20, 0x25, 0x32,
-0x25, 0x31, 0x20, 0x65, 0x74, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x98f, 0x9ac, 0x982, 0x20, 0x25, 0x32, 0x25, 0x31,
-0x20, 0xf51, 0xf44, 0xf0b, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x438, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x25, 0x32, 0x25,
-0x31, 0x1014, 0x103e, 0x1004, 0x1037, 0x103a, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x456, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x1793,
-0x17b7, 0x1784, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x1793, 0x17b7, 0x1784, 0x200b, 0x25, 0x32, 0x25, 0x31, 0x20, 0x69, 0x20, 0x25,
-0x32, 0x25, 0x31, 0x3001, 0x25, 0x32, 0x25, 0x31, 0x548c, 0x25, 0x32, 0x25, 0x31, 0x53ca, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61,
-0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6f, 0x67, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x25,
-0x32, 0x25, 0x31, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6a, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31,
-0x20, 0x65, 0x74, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x67, 0x75, 0x73, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x65,
-0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x10d3, 0x10d0, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x75, 0x6e, 0x64, 0x20, 0x25, 0x32,
-0x25, 0x31, 0x20, 0x3ba, 0x3b1, 0x3b9, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x61, 0x6d, 0x6d, 0x61, 0x20, 0x25, 0x32,
-0x25, 0x31, 0x20, 0xa85, 0xaa8, 0xac7, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x5d5, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x914,
-0x930, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x914, 0x930, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xe9, 0x73, 0x20, 0x25, 0x32,
-0x25, 0x31, 0x2c, 0x20, 0x64, 0x61, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x64, 0x61, 0x6e, 0x20, 0x25, 0x32, 0x25,
-0x31, 0x2c, 0x20, 0x61, 0x67, 0x75, 0x73, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0xcae, 0xca4, 0xccd, 0xca4, 0xcc1, 0x20,
-0x25, 0x32, 0x25, 0x31, 0x20, 0xcae, 0xca4, 0xccd, 0xca4, 0xcc1, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x436, 0x4d9, 0x43d, 0x435,
-0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x436, 0x430, 0x43d, 0x430, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xbc0f, 0x20, 0x25, 0x32,
-0x25, 0x31, 0x20, 0xec1, 0xea5, 0xeb0, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x75, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20,
-0x6d, 0x70, 0xe9, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x69, 0x72, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x25, 0x32,
-0x20, 0xd0e, 0xd28, 0xd4d, 0xd28, 0xd3f, 0xd35, 0x25, 0x31, 0x20, 0xd15, 0xd42, 0xd1f, 0xd3e, 0xd24, 0xd46, 0x20, 0x25, 0x32, 0x25,
-0x31, 0x2c, 0x20, 0x75, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x75, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x906, 0x923, 0x93f,
-0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x25, 0x32, 0x25, 0x31, 0x20, 0x930, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x200f, 0x20,
-0x25, 0x32, 0x25, 0x31, 0x60c, 0x20, 0x648, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x648, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20,
-0xa05, 0xa24, 0xa47, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x219, 0x69, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x4d5, 0x43c, 0x4d5,
-0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0xdc3, 0xdc4, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xdc3, 0xdc4, 0x20, 0x25, 0x32,
-0x25, 0x31, 0x20, 0x61, 0xa0, 0x25, 0x32, 0x25, 0x31, 0x20, 0x69, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x79, 0x20,
+0x31, 0x20, 0x648, 0x25, 0x32, 0x25, 0x31, 0x20, 0x587, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x986, 0x9f0, 0x9c1, 0x20, 0x25,
+0x32, 0x25, 0x31, 0x20, 0x76, 0x259, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x65, 0x74, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31,
+0x20, 0x98f, 0x9ac, 0x982, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xf51, 0xf44, 0xf0b, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x438,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x25, 0x32, 0x25, 0x31, 0x1014, 0x103e, 0x1004, 0x1037, 0x103a, 0x20, 0x25, 0x32, 0x25, 0x31,
+0x20, 0x456, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x1793, 0x17b7, 0x1784, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x1793, 0x17b7, 0x1784,
+0x200b, 0x25, 0x32, 0x25, 0x31, 0x20, 0x69, 0x20, 0x25, 0x32, 0x25, 0x31, 0x3001, 0x25, 0x32, 0x25, 0x31, 0x548c, 0x25, 0x32,
+0x25, 0x31, 0x53ca, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6f, 0x67, 0x20, 0x25, 0x32,
+0x25, 0x31, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x25, 0x32, 0x25,
+0x31, 0x20, 0x6b, 0x61, 0x6a, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6a, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x65,
+0x74, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x67, 0x75, 0x73, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x65, 0x20, 0x25,
+0x32, 0x25, 0x31, 0x20, 0x10d3, 0x10d0, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x75, 0x6e, 0x64, 0x20, 0x25, 0x32, 0x25, 0x31,
+0x20, 0x3ba, 0x3b1, 0x3b9, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x61, 0x6d, 0x6d, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31,
+0x20, 0xa85, 0xaa8, 0xac7, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x5d5, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x914, 0x930, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x20, 0x914, 0x930, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xe9, 0x73, 0x20, 0x25, 0x32, 0x25, 0x31,
+0x2c, 0x20, 0x64, 0x61, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x64, 0x61, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c,
+0x20, 0x61, 0x67, 0x75, 0x73, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x6c, 0x61, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31,
+0x20, 0x6c, 0x61, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0xcae, 0xca4, 0xccd, 0xca4, 0xcc1, 0x20, 0x25, 0x32, 0x25,
+0x31, 0x20, 0xcae, 0xca4, 0xccd, 0xca4, 0xcc1, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x436, 0x4d9, 0x43d, 0x435, 0x20, 0x25, 0x32,
+0x25, 0x31, 0x20, 0x436, 0x430, 0x43d, 0x430, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xbc0f, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20,
+0xfb, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xec1, 0xea5, 0xeb0, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x75, 0x6e, 0x20, 0x25,
+0x32, 0x25, 0x31, 0x20, 0x6d, 0x70, 0xe9, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x69, 0x72, 0x20, 0x25, 0x32, 0x25, 0x31,
+0x2c, 0x20, 0x25, 0x32, 0x20, 0xd0e, 0xd28, 0xd4d, 0xd28, 0xd3f, 0xd35, 0x25, 0x31, 0x20, 0xd15, 0xd42, 0xd1f, 0xd3e, 0xd24, 0xd46,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x75, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x75, 0x20, 0x25, 0x32, 0x25, 0x31,
+0x20, 0x906, 0x923, 0x93f, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x25, 0x32, 0x25, 0x31, 0x20, 0x930, 0x20, 0x25, 0x32, 0x25,
+0x31, 0x2c, 0x20, 0xb13, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xb13, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x20, 0x627, 0x648,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x627, 0x648, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x200f, 0x20, 0x25, 0x32, 0x25, 0x31,
+0x60c, 0x20, 0x648, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x648, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xa05, 0xa24, 0xa47, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x20, 0x219, 0x69, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x4d5, 0x43c, 0x4d5, 0x20, 0x25, 0x32, 0x25,
+0x31, 0x60c, 0x20, 0x6fd, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6fd, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0xdc3, 0xdc4,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xdc3, 0xdc4, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0xa0, 0x25, 0x32, 0x25, 0x31,
+0x20, 0x69, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x69, 0x79, 0x6f, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x79, 0x20,
0x25, 0x32, 0x25, 0x31, 0x20, 0x6e, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6f, 0x63, 0x68, 0x20, 0x25, 0x32, 0x25,
-0x31, 0x20, 0xbae, 0xbb1, 0xbcd, 0xbb1, 0xbc1, 0xbae, 0xbcd, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xc2e, 0xc30, 0xc3f, 0xc2f, 0xc41,
-0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xe41, 0xe25, 0xe30, 0x25, 0x32, 0x25, 0x31, 0xe41, 0xe25, 0xe30, 0x25, 0x32, 0x25, 0x31,
-0x20, 0x6d, 0x6f, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x76, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x77, 0x65, 0x20,
-0x25, 0x32, 0x25, 0x31, 0x60c, 0x20, 0x627, 0x648, 0x631, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x627, 0x648, 0x631, 0x20, 0x25,
-0x32, 0x25, 0x32, 0x60c, 0x20, 0x25, 0x31, 0x25, 0x31, 0x20, 0x76, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x76, 0xe0,
-0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x6e, 0x65, 0x2d, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6e, 0x65, 0x2d, 0x25, 0x32,
-0x25, 0x31, 0x2c, 0x20, 0x6b, 0x70, 0x6c, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6b, 0x70, 0x6c, 0x65, 0x20, 0x25,
-0x32, 0x25, 0x31, 0x2c, 0x20, 0x61, 0x74, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x74, 0x20, 0x25, 0x32, 0x25, 0x31,
-0x20, 0x13a0, 0x13b4, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x438, 0x486, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x28, 0x6e,
-0x29, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x443, 0x43e, 0x43d, 0x43d, 0x430, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x14b,
-0x301, 0x67, 0x25b, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x1e3f, 0x62, 0x25b, 0x6e, 0x20, 0x14b, 0x301, 0x67, 0x25b, 0x20,
-0x25, 0x32, 0x25, 0x31, 0x20, 0x70, 0x254, 0x70, 0x20, 0x25, 0x32, 0x25, 0x31, 0x540c, 0x25, 0x32
+0x31, 0x20, 0xbae, 0xbb1, 0xbcd, 0xbb1, 0xbc1, 0xbae, 0xbcd, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x4bb, 0x4d9, 0x43c, 0x20, 0x25,
+0x32, 0x25, 0x31, 0x20, 0xc2e, 0xc30, 0xc3f, 0xc2f, 0xc41, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xe41, 0xe25, 0xe30, 0x25, 0x32,
+0x25, 0x31, 0xe41, 0xe25, 0xe30, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6d, 0x6f, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x76, 0x65,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x77, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x20, 0x627, 0x648, 0x631, 0x20, 0x25,
+0x32, 0x25, 0x31, 0x20, 0x627, 0x648, 0x631, 0x20, 0x25, 0x32, 0x25, 0x32, 0x60c, 0x20, 0x25, 0x31, 0x25, 0x31, 0x20, 0x76,
+0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x76, 0xe0, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x61, 0x28, 0x63, 0x29,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x28, 0x63, 0x29, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x5d0, 0x5d5, 0x5df, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x6e, 0x65, 0x2d, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6e, 0x65, 0x2d, 0x25, 0x32, 0x25,
+0x31, 0x2c, 0x20, 0x6b, 0x70, 0x6c, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6b, 0x70, 0x6c, 0x65, 0x20, 0x25, 0x32,
+0x25, 0x31, 0x2c, 0x20, 0x61, 0x74, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x74, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c,
+0x20, 0x61, 0x6b, 0x6b, 0x65, 0x64, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x6b, 0x6b, 0x65, 0x64, 0x20, 0x25, 0x32,
+0x25, 0x31, 0x2c, 0x20, 0x13a0, 0x13b4, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x13a0, 0x13b4, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20,
+0x438, 0x486, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x28, 0x6e, 0x29, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x443, 0x43e,
+0x43d, 0x43d, 0x430, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x14b, 0x301, 0x67, 0x25b, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c,
+0x20, 0x1e3f, 0x62, 0x25b, 0x6e, 0x20, 0x14b, 0x301, 0x67, 0x25b, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x70, 0x254, 0x70, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x20, 0x62, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x540c, 0x25, 0x32
};
static const ushort date_format_data[] = {
@@ -1864,113 +1895,125 @@ static const ushort date_format_data[] = {
0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x2f, 0x4d, 0x4d, 0x2f, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c,
0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2d, 0x4d, 0x4d,
0x2d, 0x64, 0x64, 0x79, 0x79, 0x79, 0x79, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64,
-0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64,
-0x64, 0x64, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2e, 0x4d, 0x2e, 0x79, 0x79,
-0x64, 0x64, 0x2f, 0x4d, 0x4d, 0x2f, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x1363, 0x64, 0x20, 0x4d, 0x4d,
-0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x200f, 0x2f, 0x4d, 0x200f, 0x2f, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64,
-0x64, 0x60c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x60c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x2e, 0x4d, 0x4d,
-0x2e, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x20, 0x569, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2c, 0x20, 0x64,
-0x64, 0x64, 0x64, 0x64, 0x2d, 0x4d, 0x2d, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d,
-0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79,
-0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x2f, 0x4d, 0x2f, 0x64, 0x79, 0x79, 0x79, 0x79, 0x28, 0x27, 0x65, 0x27,
-0x29, 0x27, 0x6b, 0x6f, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2f,
-0x4d, 0x2f, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf63, 0xf7c, 0xf0b, 0x79, 0x79,
-0x79, 0x79, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0xf5a, 0xf7a, 0xf66, 0xf0b, 0x64, 0x64, 0x64, 0x2e, 0x4d, 0x4d, 0x2e, 0x79,
-0x79, 0x20, 0x27, 0x433, 0x27, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79,
-0x79, 0x79, 0x79, 0x20, 0x27, 0x433, 0x27, 0x2e, 0x64, 0x64, 0x2d, 0x4d, 0x4d, 0x2d, 0x79, 0x79, 0x64, 0x2e, 0x4d, 0x4d,
-0x2e, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x65, 0x27,
-0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2f, 0x4d, 0x2f, 0x64, 0x79, 0x79, 0x79, 0x79, 0x5e74, 0x4d, 0x6708,
-0x64, 0x65e5, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2f, 0x4d, 0x2f, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x5e74, 0x4d,
-0x6708, 0x64, 0x65e5, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x2e, 0x20, 0x79, 0x79, 0x79, 0x79,
-0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e,
-0x64, 0x2e, 0x20, 0x4d, 0x2e, 0x20, 0x79, 0x79, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d,
-0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x27, 0x64, 0x65, 0x6e, 0x27, 0x20, 0x64, 0x2e, 0x20,
-0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2f, 0x4d, 0x4d, 0x2f, 0x79, 0x79, 0x4d, 0x2f, 0x64, 0x2f,
-0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2f, 0x4d, 0x4d, 0x2f, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x2e,
-0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2e, 0x4d, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79,
-0x2d, 0x4d, 0x4d, 0x2d, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x27, 0x6d, 0x68, 0x27, 0x20, 0x4d, 0x4d,
-0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20,
-0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20,
-0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x64,
-0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x5d1, 0x4d,
-0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x20, 0x4d, 0x4d, 0x2e, 0x20, 0x64, 0x64,
-0x2e, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2e, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64,
-0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x436, 0x27, 0x2e, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x64, 0x64,
-0x64, 0x64, 0x79, 0x79, 0x79, 0x79, 0x2d, 0x27, 0x436, 0x27, 0x2e, 0x2c, 0x20, 0x64, 0x2d, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c,
-0x20, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x2e, 0x20, 0x4d, 0x2e, 0x20, 0x64, 0x2e, 0x79, 0x79, 0x79, 0x79, 0xb144, 0x20,
-0x4d, 0xc6d4, 0x20, 0x64, 0xc77c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x20, 0xe97, 0xeb5, 0x20, 0x64, 0x20,
-0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e,
-0x20, 0x27, 0x67, 0x61, 0x64, 0x61, 0x27, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x79, 0x79, 0x79, 0x79, 0x20,
-0x27, 0x6d, 0x27, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x20, 0x27, 0x64, 0x27, 0x2e, 0x2c, 0x20, 0x64, 0x64,
-0x64, 0x64, 0x64, 0x64, 0x2e, 0x4d, 0x2e, 0x79, 0x79, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79,
-0x79, 0x79, 0x79, 0x79, 0x79, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64,
-0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x27, 0x74, 0x61, 0x27, 0x2019, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79,
-0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x43e, 0x43d, 0x44b, 0x27, 0x20, 0x4d,
-0x4d, 0x20, 0x27, 0x441, 0x430, 0x440, 0x44b, 0x43d, 0x27, 0x20, 0x64, 0x64, 0x64, 0x2e, 0x4d, 0x4d, 0x2e, 0x79, 0x79, 0x79,
-0x79, 0x64, 0x2d, 0x4d, 0x2d, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x62f, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x62f,
-0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x27, 0x69, 0x6c, 0x73, 0x27, 0x20, 0x64,
-0x20, 0x27, 0x64, 0x61, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2e, 0x4d, 0x2e, 0x79,
-0x79, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79,
-0x79, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79,
-0x20, 0x27, 0x430, 0x437, 0x27, 0x64, 0x2e, 0x20, 0x4d, 0x2e, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2e, 0x20, 0x4d, 0x4d,
-0x2e, 0x20, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79,
-0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79,
-0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x64, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20,
-0x27, 0x64, 0x65, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x4d, 0x4d, 0x2f, 0x64, 0x64, 0x2f, 0x79, 0x79, 0x64, 0x64, 0x2d,
-0x4d, 0x4d, 0x2d, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2c,
-0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0xe17, 0xe35, 0xe48, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20,
-0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0xf60, 0xf72, 0xf0b, 0xf5a, 0xf7a, 0xf66, 0xf0b,
-0x64, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x1363, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d,
-0x20, 0x1218, 0x12d3, 0x120d, 0x1272, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2e, 0x4d, 0x4d, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x64,
-0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x79, 0x79, 0x20,
-0x64, 0x2d, 0x4d, 0x4d, 0x4d, 0x4d, 0x60c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20,
-0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x440, 0x27, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20,
-0x64, 0x2d, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x20, 0x646, 0x686, 0x6cc,
-0x20, 0x6cc, 0x6cc, 0x644, 0x20, 0x64, 0x20, 0x646, 0x686, 0x6cc, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64, 0x64, 0x64,
-0x20, 0x6a9, 0x648, 0x646, 0x6cc, 0x79, 0x79, 0x2f, 0x4d, 0x4d, 0x2f, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x79,
-0x79, 0x79, 0x79, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x20, 0x27, 0x64,
-0x69, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x61, 0x6c, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64,
-0x64, 0x64, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x20, 0x27, 0x6c, 0x69, 0x61, 0x27, 0x20, 0x79, 0x79, 0x79,
-0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20,
-0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x27, 0x64, 0x69, 0x27, 0x20, 0x4d, 0x4d, 0x4d,
-0x4d, 0x20, 0x27, 0x64, 0x69, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x27, 0x64, 0xe4,
-0x27, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x4d,
-0x4d, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x43b, 0x27,
-0x2e, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x64, 0x2f, 0x4d, 0x4d, 0x2f, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79,
+0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64,
+0x64, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2e, 0x4d, 0x2e, 0x79, 0x79, 0x64,
+0x64, 0x2f, 0x4d, 0x4d, 0x2f, 0x79, 0x79, 0x79, 0x79, 0x64, 0x200f, 0x2f, 0x4d, 0x200f, 0x2f, 0x79, 0x79, 0x79, 0x79, 0x64,
+0x64, 0x64, 0x64, 0x60c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x2e, 0x4d,
+0x4d, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x20, 0x569, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2c, 0x20,
+0x64, 0x64, 0x64, 0x64, 0x64, 0x2d, 0x4d, 0x2d, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20,
+0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79,
+0x79, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x2f, 0x4d, 0x2f, 0x64, 0x79, 0x79, 0x79, 0x79, 0x28, 0x27, 0x65,
+0x27, 0x29, 0x27, 0x6b, 0x6f, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x27, 0x72, 0x65, 0x6e, 0x27, 0x20, 0x64, 0x28, 0x27,
+0x61, 0x27, 0x29, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2f, 0x4d, 0x2f, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c,
+0x20, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf63, 0xf7c, 0xf0b, 0x79, 0x79, 0x79, 0x79, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0xf5a,
+0xf7a, 0xf66, 0xf0b, 0x64, 0x64, 0x64, 0x2e, 0x4d, 0x4d, 0x2e, 0x79, 0x79, 0x20, 0x27, 0x433, 0x27, 0x2e, 0x64, 0x64, 0x64,
+0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x433, 0x27, 0x2e, 0x64,
+0x64, 0x2d, 0x4d, 0x4d, 0x2d, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x104a, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x104a,
+0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2e, 0x4d, 0x4d, 0x2e, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20,
+0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2f, 0x4d,
+0x2f, 0x64, 0x79, 0x79, 0x79, 0x79, 0x5e74, 0x4d, 0x6708, 0x64, 0x65e5, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2f, 0x4d, 0x2f, 0x79,
+0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x5e74, 0x4d, 0x6708, 0x64, 0x65e5, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2e,
+0x20, 0x4d, 0x4d, 0x2e, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x2e, 0x20, 0x4d,
+0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x64, 0x2e, 0x20, 0x4d, 0x2e, 0x20, 0x79, 0x79, 0x2e, 0x64, 0x64,
+0x64, 0x64, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x2e, 0x4d, 0x4d,
+0x2e, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x27, 0x64, 0x65, 0x6e, 0x27, 0x20, 0x64, 0x2e, 0x20, 0x4d,
+0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x2d, 0x4d, 0x4d, 0x2d, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2f,
+0x4d, 0x4d, 0x2f, 0x79, 0x79, 0x79, 0x79, 0x4d, 0x2f, 0x64, 0x2f, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64,
+0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2f, 0x4d, 0x4d, 0x2f, 0x79, 0x79, 0x79, 0x79,
+0x79, 0x79, 0x2f, 0x4d, 0x4d, 0x2f, 0x64, 0x64, 0x79, 0x79, 0x2d, 0x4d, 0x4d, 0x2d, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
+0x2c, 0x20, 0x64, 0x2d, 0x27, 0x61, 0x27, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79,
+0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79,
+0x64, 0x2e, 0x4d, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x27, 0x6d, 0x68, 0x27, 0x20,
+0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x27, 0x64, 0x65,
+0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64,
+0x2c, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c,
+0x20, 0x64, 0x20, 0x5d1, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x20, 0x4d,
+0x4d, 0x2e, 0x20, 0x64, 0x64, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2e, 0x2c,
+0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x20, 0x27, 0x6c, 0x65, 0x27, 0x20, 0x64, 0x20, 0x27, 0x64, 0x65,
+0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x436, 0x27, 0x2e,
+0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x79, 0x79, 0x2d, 0x27, 0x436,
+0x27, 0x2e, 0x2c, 0x20, 0x64, 0x2d, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x2e, 0x20,
+0x4d, 0x2e, 0x20, 0x64, 0x2e, 0x79, 0x79, 0x79, 0x79, 0xb144, 0x20, 0x4d, 0xc6d4, 0x20, 0x64, 0xc77c, 0x20, 0x64, 0x64, 0x64,
+0x64, 0x64, 0x64, 0x64, 0x64, 0x20, 0xe97, 0xeb5, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79,
+0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x20, 0x27, 0x67, 0x61, 0x64, 0x61, 0x27, 0x20, 0x64,
+0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x6d, 0x27, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d,
+0x20, 0x64, 0x20, 0x27, 0x64, 0x27, 0x2e, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2e, 0x4d, 0x2e, 0x79, 0x79,
+0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2c, 0x20, 0x4d, 0x4d,
+0x4d, 0x4d, 0x20, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x27, 0x74,
+0x61, 0x27, 0x2019, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x4d, 0x4d,
+0x2e, 0x64, 0x64, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x4d, 0x4d, 0x2e, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64,
+0x64, 0x64, 0x64, 0x20, 0x62f, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x62f, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64,
+0x64, 0x64, 0x64, 0x2c, 0x20, 0x27, 0x69, 0x6c, 0x73, 0x27, 0x20, 0x64, 0x20, 0x27, 0x64, 0x61, 0x27, 0x20, 0x4d, 0x4d,
+0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2e, 0x4d, 0x2e, 0x79, 0x79, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20,
+0x64, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20,
+0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x430, 0x437, 0x27, 0x64, 0x2e, 0x20,
+0x4d, 0x2e, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x2e, 0x20, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64,
+0x2c, 0x20, 0x64, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c,
+0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64,
+0x64, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x79, 0x79, 0x79,
+0x79, 0x4d, 0x4d, 0x2f, 0x64, 0x64, 0x2f, 0x79, 0x79, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79,
+0x79, 0x20, 0x27, 0x435, 0x43b, 0x27, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20,
+0x79, 0x79, 0x79, 0x79, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0xe17, 0xe35, 0xe48, 0x20, 0x64, 0x20,
+0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0xf60, 0xf72,
+0xf0b, 0xf5a, 0xf7a, 0xf66, 0xf0b, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x1363, 0x20, 0x64, 0x64,
+0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x1218, 0x12d3, 0x120d, 0x1272, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2e, 0x4d, 0x4d, 0x2e,
+0x79, 0x79, 0x79, 0x79, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x64, 0x64, 0x64, 0x64,
+0x79, 0x79, 0x79, 0x79, 0x20, 0x64, 0x2d, 0x4d, 0x4d, 0x4d, 0x4d, 0x60c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
+0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x440, 0x27, 0x2e, 0x64,
+0x64, 0x64, 0x64, 0x60c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x60c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64,
+0x64, 0x2c, 0x20, 0x64, 0x2d, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x20,
+0x646, 0x686, 0x6cc, 0x20, 0x6cc, 0x6cc, 0x644, 0x20, 0x64, 0x20, 0x646, 0x686, 0x6cc, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64,
+0x64, 0x64, 0x64, 0x20, 0x6a9, 0x648, 0x646, 0x6cc, 0x79, 0x79, 0x79, 0x79, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x27, 0x61, 0x27,
+0x20, 0x27, 0x64, 0x27, 0x2e, 0x20, 0x64, 0x27, 0x69, 0x64, 0x27, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d,
+0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x5d8, 0x5df, 0x20, 0x4d, 0x4d,
+0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2e, 0x20, 0x4d, 0x2e, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x79, 0x79,
+0x2f, 0x4d, 0x4d, 0x2f, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x4d, 0x4d, 0x4d,
+0x4d, 0x20, 0x64, 0x64, 0x64, 0x2d, 0x4d, 0x2d, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x20, 0x27, 0x64, 0x69,
+0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x61, 0x6c, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64,
+0x64, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x20, 0x27, 0x6c, 0x69, 0x61, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79,
+0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79,
+0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x27, 0x64, 0x69, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d,
+0x20, 0x27, 0x64, 0x69, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x27, 0x64, 0xe4, 0x27,
+0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64,
+0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x43b, 0x27, 0x2e, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x79, 0x79, 0x79, 0x79,
0x20, 0x27, 0x441, 0x44b, 0x43b, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x20, 0x27, 0x43a, 0x4af, 0x43d, 0x44d, 0x27,
0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2f, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64,
0x20, 0x2c, 0x20, 0x27, 0x6c, 0x79, 0x25b, 0x27, 0x30c, 0x2bc, 0x20, 0x64, 0x20, 0x27, 0x6e, 0x61, 0x27, 0x20, 0x4d, 0x4d,
-0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64,
-0x2e, 0x20, 0x79, 0x79, 0x79, 0x79
+0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27,
+0x6d, 0x65, 0x74, 0x74, 0x61, 0x73, 0x27, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x64, 0x64, 0x64, 0x64, 0x2c,
+0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2e, 0x20, 0x79, 0x79, 0x79, 0x79
};
static const ushort time_format_data[] = {
0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x68, 0x3a,
0x6d, 0x6d, 0x20, 0x41, 0x50, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50, 0x20, 0x74, 0x48, 0x48, 0x3a,
0x6d, 0x6d, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50, 0x2c, 0x20, 0x74, 0x48, 0x3a, 0x6d, 0x6d, 0x48,
-0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x68, 0x2e, 0x6d, 0x6d, 0x2e, 0x20, 0x41, 0x50, 0x68, 0x2e, 0x6d, 0x6d,
-0x2e, 0x73, 0x73, 0x20, 0x41, 0x50, 0x20, 0x74, 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x28, 0x74, 0x29,
-0xf46, 0xf74, 0xf0b, 0xf5a, 0xf7c, 0xf51, 0xf0b, 0x20, 0x68, 0x20, 0xf66, 0xf90, 0xf62, 0xf0b, 0xf58, 0xf0b, 0x20, 0x6d, 0x6d, 0x20,
-0x41, 0x50, 0xf46, 0xf74, 0xf0b, 0xf5a, 0xf7c, 0xf51, 0xf0b, 0x20, 0x68, 0x20, 0xf66, 0xf90, 0xf62, 0xf0b, 0xf58, 0xf0b, 0x20, 0x6d,
-0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50, 0x20, 0x74, 0x74, 0x20, 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x48,
-0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x2c, 0x20, 0x74, 0x41, 0x50, 0x68, 0x3a, 0x6d, 0x6d, 0x74, 0x20, 0x41, 0x50,
-0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x41, 0x50, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x5b, 0x74, 0x5d,
-0x48, 0x48, 0x2e, 0x6d, 0x6d, 0x48, 0x48, 0x2e, 0x6d, 0x6d, 0x2e, 0x73, 0x73, 0x20, 0x74, 0x68, 0x2e, 0x6d, 0x6d, 0x20,
-0x41, 0x50, 0x48, 0x2e, 0x6d, 0x6d, 0x48, 0x2e, 0x6d, 0x6d, 0x2e, 0x73, 0x73, 0x20, 0x74, 0x48, 0x20, 0x27, 0x68, 0x27,
-0x20, 0x6d, 0x6d, 0x20, 0x27, 0x6d, 0x69, 0x6e, 0x27, 0x20, 0x73, 0x73, 0x20, 0x27, 0x73, 0x27, 0x20, 0x74, 0x48, 0x48,
-0x20, 0x27, 0x68, 0x27, 0x20, 0x6d, 0x6d, 0x48, 0x48, 0x2e, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x27, 0x68, 0x27, 0x20,
-0x74, 0x68, 0x68, 0x3a, 0x6d, 0x6d, 0x20, 0x41, 0x50, 0x68, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50,
-0x20, 0x74, 0x48, 0x6642, 0x6d, 0x6d, 0x5206, 0x73, 0x73, 0x79d2, 0x20, 0x74, 0x41, 0x50, 0x20, 0x68, 0x3a, 0x6d, 0x6d, 0x41,
-0x50, 0x20, 0x68, 0xc2dc, 0x20, 0x6d, 0xbd84, 0x20, 0x73, 0xcd08, 0x20, 0x74, 0x48, 0x20, 0xec2, 0xea1, 0xe87, 0x20, 0x6d, 0x20,
-0xe99, 0xeb2, 0xe97, 0xeb5, 0x20, 0x73, 0x73, 0x20, 0xea7, 0xeb4, 0xe99, 0xeb2, 0xe97, 0xeb5, 0x20, 0x74, 0x48, 0x3a, 0x6d, 0x6d,
-0x3a, 0x73, 0x73, 0x20, 0x28, 0x74, 0x29, 0x27, 0x6b, 0x6c, 0x27, 0x2e, 0x20, 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73,
-0x73, 0x20, 0x74, 0x41, 0x50, 0x20, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x48, 0x20, 0xe19, 0xe32, 0xe2c,
-0xe34, 0xe01, 0xe32, 0x20, 0x6d, 0x6d, 0x20, 0xe19, 0xe32, 0xe17, 0xe35, 0x20, 0x73, 0x73, 0x20, 0xe27, 0xe34, 0xe19, 0xe32, 0xe17,
-0xe35, 0x20, 0x74, 0x41, 0x50, 0x20, 0x27, 0x67, 0x61, 0x27, 0x20, 0x68, 0x3a, 0x6d, 0x6d, 0x41, 0x50, 0x20, 0x27, 0x67,
-0x61, 0x27, 0x20, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x27, 0x4b, 0x6c, 0x27, 0x2e, 0x20, 0x48, 0x2e,
-0x6d, 0x6d, 0x27, 0x4b, 0x6c, 0x6f, 0x63, 0x6b, 0x27, 0x20, 0x48, 0x2e, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x28, 0x74,
-0x29, 0x74, 0x20, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50, 0x48, 0x3a, 0x6d, 0x6d, 0x20, 0x27, 0x68,
-0x6f, 0x64, 0x17a, 0x27, 0x2e
+0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x41, 0x50, 0x20, 0x68, 0x2e, 0x6d, 0x6d, 0x41, 0x50, 0x20, 0x68, 0x2e,
+0x6d, 0x6d, 0x2e, 0x73, 0x73, 0x20, 0x74, 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x28, 0x74, 0x29, 0xf46,
+0xf74, 0xf0b, 0xf5a, 0xf7c, 0xf51, 0xf0b, 0x20, 0x68, 0x20, 0xf66, 0xf90, 0xf62, 0xf0b, 0xf58, 0xf0b, 0x20, 0x6d, 0x6d, 0x20, 0x41,
+0x50, 0xf46, 0xf74, 0xf0b, 0xf5a, 0xf7c, 0xf51, 0xf0b, 0x20, 0x68, 0x20, 0xf66, 0xf90, 0xf62, 0xf0b, 0xf58, 0xf0b, 0x20, 0x6d, 0x6d,
+0x3a, 0x73, 0x73, 0x20, 0x41, 0x50, 0x20, 0x74, 0x48, 0x3a, 0x6d, 0x6d, 0x20, 0x27, 0x447, 0x27, 0x2e, 0x48, 0x3a, 0x6d,
+0x6d, 0x3a, 0x73, 0x73, 0x20, 0x27, 0x447, 0x27, 0x2e, 0x20, 0x74, 0x42, 0x20, 0x48, 0x3a, 0x6d, 0x6d, 0x74, 0x20, 0x48,
+0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x2c, 0x20, 0x74, 0x41, 0x50,
+0x68, 0x3a, 0x6d, 0x6d, 0x74, 0x20, 0x41, 0x50, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x41, 0x50, 0x68, 0x3a, 0x6d,
+0x6d, 0x3a, 0x73, 0x73, 0x20, 0x5b, 0x74, 0x5d, 0x48, 0x48, 0x2e, 0x6d, 0x6d, 0x48, 0x48, 0x2e, 0x6d, 0x6d, 0x2e, 0x73,
+0x73, 0x20, 0x74, 0x48, 0x2e, 0x6d, 0x6d, 0x48, 0x2e, 0x6d, 0x6d, 0x2e, 0x73, 0x73, 0x20, 0x74, 0x48, 0x2d, 0x27, 0x61,
+0x27, 0x20, 0x27, 0x68, 0x6f, 0x72, 0x6f, 0x27, 0x20, 0x27, 0x6b, 0x61, 0x6a, 0x27, 0x20, 0x6d, 0x3a, 0x73, 0x73, 0x20,
+0x74, 0x48, 0x20, 0x27, 0x68, 0x27, 0x20, 0x6d, 0x6d, 0x20, 0x27, 0x6d, 0x69, 0x6e, 0x27, 0x20, 0x73, 0x73, 0x20, 0x27,
+0x73, 0x27, 0x20, 0x74, 0x48, 0x48, 0x20, 0x27, 0x68, 0x27, 0x20, 0x6d, 0x6d, 0x48, 0x48, 0x20, 0x27, 0x68, 0x27, 0x20,
+0x6d, 0x6d, 0x20, 0x27, 0x6d, 0x69, 0x6e, 0x27, 0x20, 0x73, 0x73, 0x20, 0x27, 0x73, 0x27, 0x20, 0x74, 0x48, 0x48, 0x2e,
+0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x27, 0x68, 0x27, 0x20, 0x74, 0x68, 0x68, 0x3a, 0x6d, 0x6d, 0x20, 0x41, 0x50, 0x68,
+0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50, 0x20, 0x74, 0x48, 0x6642, 0x6d, 0x6d, 0x5206, 0x73, 0x73, 0x79d2,
+0x20, 0x74, 0x41, 0x50, 0x20, 0x68, 0x3a, 0x6d, 0x6d, 0x41, 0x50, 0x20, 0x68, 0xc2dc, 0x20, 0x6d, 0xbd84, 0x20, 0x73, 0xcd08,
+0x20, 0x74, 0x48, 0x20, 0xec2, 0xea1, 0xe87, 0x20, 0x6d, 0x20, 0xe99, 0xeb2, 0xe97, 0xeb5, 0x20, 0x73, 0x73, 0x20, 0xea7, 0xeb4,
+0xe99, 0xeb2, 0xe97, 0xeb5, 0x20, 0x74, 0x68, 0x3a, 0x6d, 0x6d, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x28, 0x74,
+0x29, 0x27, 0x6b, 0x6c, 0x27, 0x2e, 0x20, 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x41, 0x50, 0x20,
+0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x48, 0x20, 0xe19, 0xe32, 0xe2c, 0xe34, 0xe01, 0xe32, 0x20, 0x6d, 0x6d,
+0x20, 0xe19, 0xe32, 0xe17, 0xe35, 0x20, 0x73, 0x73, 0x20, 0xe27, 0xe34, 0xe19, 0xe32, 0xe17, 0xe35, 0x20, 0x74, 0x41, 0x50, 0x20,
+0x27, 0x67, 0x61, 0x27, 0x20, 0x68, 0x3a, 0x6d, 0x6d, 0x41, 0x50, 0x20, 0x27, 0x67, 0x61, 0x27, 0x20, 0x68, 0x3a, 0x6d,
+0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x27, 0x4b, 0x6c, 0x27, 0x2e, 0x20, 0x48, 0x2e, 0x6d, 0x6d, 0x27, 0x4b, 0x6c, 0x6f,
+0x63, 0x6b, 0x27, 0x20, 0x48, 0x2e, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x28, 0x74, 0x29, 0x74, 0x20, 0x68, 0x3a, 0x6d,
+0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50, 0x48, 0x3a, 0x6d, 0x6d, 0x20, 0x27, 0x68, 0x6f, 0x64, 0x17a, 0x27, 0x2e
};
static const ushort months_data[] = {
@@ -2002,666 +2045,704 @@ static const ushort months_data[] = {
0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x65, 0x3b, 0x4a, 0x75, 0x6c, 0x69,
0x65, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72,
0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65,
-0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x53, 0x68, 0x6b, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x50,
-0x72, 0x69, 0x3b, 0x4d, 0x61, 0x6a, 0x3b, 0x51, 0x65, 0x72, 0x3b, 0x4b, 0x6f, 0x72, 0x3b, 0x47, 0x73, 0x68, 0x3b, 0x53,
-0x68, 0x74, 0x3b, 0x54, 0x65, 0x74, 0x3b, 0x4e, 0xeb, 0x6e, 0x3b, 0x44, 0x68, 0x6a, 0x3b, 0x4a, 0x61, 0x6e, 0x61, 0x72,
-0x3b, 0x53, 0x68, 0x6b, 0x75, 0x72, 0x74, 0x3b, 0x4d, 0x61, 0x72, 0x73, 0x3b, 0x50, 0x72, 0x69, 0x6c, 0x6c, 0x3b, 0x4d,
-0x61, 0x6a, 0x3b, 0x51, 0x65, 0x72, 0x73, 0x68, 0x6f, 0x72, 0x3b, 0x4b, 0x6f, 0x72, 0x72, 0x69, 0x6b, 0x3b, 0x47, 0x75,
-0x73, 0x68, 0x74, 0x3b, 0x53, 0x68, 0x74, 0x61, 0x74, 0x6f, 0x72, 0x3b, 0x54, 0x65, 0x74, 0x6f, 0x72, 0x3b, 0x4e, 0xeb,
-0x6e, 0x74, 0x6f, 0x72, 0x3b, 0x44, 0x68, 0x6a, 0x65, 0x74, 0x6f, 0x72, 0x3b, 0x4a, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x50,
-0x3b, 0x4d, 0x3b, 0x51, 0x3b, 0x4b, 0x3b, 0x47, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x6a, 0x61, 0x6e,
-0x3b, 0x73, 0x68, 0x6b, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x70, 0x72, 0x69, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x71, 0x65, 0x72,
-0x3b, 0x6b, 0x6f, 0x72, 0x3b, 0x67, 0x73, 0x68, 0x3b, 0x73, 0x68, 0x74, 0x3b, 0x74, 0x65, 0x74, 0x3b, 0x6e, 0xeb, 0x6e,
-0x3b, 0x64, 0x68, 0x6a, 0x3b, 0x6a, 0x61, 0x6e, 0x61, 0x72, 0x3b, 0x73, 0x68, 0x6b, 0x75, 0x72, 0x74, 0x3b, 0x6d, 0x61,
-0x72, 0x73, 0x3b, 0x70, 0x72, 0x69, 0x6c, 0x6c, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x71, 0x65, 0x72, 0x73, 0x68, 0x6f, 0x72,
-0x3b, 0x6b, 0x6f, 0x72, 0x72, 0x69, 0x6b, 0x3b, 0x67, 0x75, 0x73, 0x68, 0x74, 0x3b, 0x73, 0x68, 0x74, 0x61, 0x74, 0x6f,
-0x72, 0x3b, 0x74, 0x65, 0x74, 0x6f, 0x72, 0x3b, 0x6e, 0xeb, 0x6e, 0x74, 0x6f, 0x72, 0x3b, 0x64, 0x68, 0x6a, 0x65, 0x74,
-0x6f, 0x72, 0x3b, 0x6a, 0x3b, 0x73, 0x3b, 0x6d, 0x3b, 0x70, 0x3b, 0x6d, 0x3b, 0x71, 0x3b, 0x6b, 0x3b, 0x67, 0x3b, 0x73,
-0x3b, 0x74, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 0x1303, 0x1295, 0x12e9, 0x3b, 0x134c, 0x1265, 0x1229, 0x3b, 0x121b, 0x122d, 0x127d, 0x3b, 0x12a4,
-0x1355, 0x122a, 0x3b, 0x121c, 0x12ed, 0x3b, 0x1301, 0x1295, 0x3b, 0x1301, 0x120b, 0x12ed, 0x3b, 0x12a6, 0x1308, 0x1235, 0x3b, 0x1234, 0x1355, 0x1274,
-0x3b, 0x12a6, 0x12ad, 0x1276, 0x3b, 0x1296, 0x126c, 0x121d, 0x3b, 0x12f2, 0x1234, 0x121d, 0x3b, 0x1303, 0x1295, 0x12e9, 0x12c8, 0x122a, 0x3b, 0x134c,
-0x1265, 0x1229, 0x12c8, 0x122a, 0x3b, 0x121b, 0x122d, 0x127d, 0x3b, 0x12a4, 0x1355, 0x122a, 0x120d, 0x3b, 0x121c, 0x12ed, 0x3b, 0x1301, 0x1295, 0x3b,
-0x1301, 0x120b, 0x12ed, 0x3b, 0x12a6, 0x1308, 0x1235, 0x1275, 0x3b, 0x1234, 0x1355, 0x1274, 0x121d, 0x1260, 0x122d, 0x3b, 0x12a6, 0x12ad, 0x1276, 0x1260,
-0x122d, 0x3b, 0x1296, 0x126c, 0x121d, 0x1260, 0x122d, 0x3b, 0x12f2, 0x1234, 0x121d, 0x1260, 0x122d, 0x3b, 0x1303, 0x3b, 0x134c, 0x3b, 0x121b, 0x3b,
-0x12a4, 0x3b, 0x121c, 0x3b, 0x1301, 0x3b, 0x1301, 0x3b, 0x12a6, 0x3b, 0x1234, 0x3b, 0x12a6, 0x3b, 0x1296, 0x3b, 0x12f2, 0x3b, 0x64a, 0x646,
-0x627, 0x64a, 0x631, 0x3b, 0x641, 0x628, 0x631, 0x627, 0x64a, 0x631, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x623, 0x628, 0x631, 0x64a,
-0x644, 0x3b, 0x645, 0x627, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x646, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x644, 0x64a, 0x648, 0x3b, 0x623,
-0x63a, 0x633, 0x637, 0x633, 0x3b, 0x633, 0x628, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x623, 0x643, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646,
-0x648, 0x641, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x64a, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x64a, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x623,
-0x3b, 0x648, 0x3b, 0x646, 0x3b, 0x644, 0x3b, 0x63a, 0x3b, 0x633, 0x3b, 0x643, 0x3b, 0x628, 0x3b, 0x62f, 0x3b, 0x62c, 0x627, 0x646,
-0x641, 0x64a, 0x3b, 0x641, 0x64a, 0x641, 0x631, 0x64a, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x623, 0x641, 0x631, 0x64a, 0x644, 0x3b,
-0x645, 0x627, 0x64a, 0x3b, 0x62c, 0x648, 0x627, 0x646, 0x3b, 0x62c, 0x648, 0x64a, 0x644, 0x64a, 0x629, 0x3b, 0x623, 0x648, 0x62a, 0x3b,
+0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x73, 0x68, 0x6b, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x70,
+0x72, 0x69, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x71, 0x65, 0x72, 0x3b, 0x6b, 0x6f, 0x72, 0x72, 0x3b, 0x67, 0x75, 0x73, 0x68,
+0x3b, 0x73, 0x68, 0x74, 0x3b, 0x74, 0x65, 0x74, 0x3b, 0x6e, 0xeb, 0x6e, 0x3b, 0x64, 0x68, 0x6a, 0x3b, 0x6a, 0x61, 0x6e,
+0x61, 0x72, 0x3b, 0x73, 0x68, 0x6b, 0x75, 0x72, 0x74, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x70, 0x72, 0x69, 0x6c, 0x6c,
+0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x71, 0x65, 0x72, 0x73, 0x68, 0x6f, 0x72, 0x3b, 0x6b, 0x6f, 0x72, 0x72, 0x69, 0x6b, 0x3b,
+0x67, 0x75, 0x73, 0x68, 0x74, 0x3b, 0x73, 0x68, 0x74, 0x61, 0x74, 0x6f, 0x72, 0x3b, 0x74, 0x65, 0x74, 0x6f, 0x72, 0x3b,
+0x6e, 0xeb, 0x6e, 0x74, 0x6f, 0x72, 0x3b, 0x64, 0x68, 0x6a, 0x65, 0x74, 0x6f, 0x72, 0x3b, 0x6a, 0x3b, 0x73, 0x68, 0x3b,
+0x6d, 0x3b, 0x70, 0x3b, 0x6d, 0x3b, 0x71, 0x3b, 0x6b, 0x3b, 0x67, 0x3b, 0x73, 0x68, 0x3b, 0x74, 0x3b, 0x6e, 0x3b, 0x64,
+0x68, 0x3b, 0x1303, 0x1295, 0x12e9, 0x3b, 0x134c, 0x1265, 0x1229, 0x3b, 0x121b, 0x122d, 0x127d, 0x3b, 0x12a4, 0x1355, 0x122a, 0x3b, 0x121c, 0x12ed,
+0x3b, 0x1301, 0x1295, 0x3b, 0x1301, 0x120b, 0x12ed, 0x3b, 0x12a6, 0x1308, 0x1235, 0x3b, 0x1234, 0x1355, 0x1274, 0x3b, 0x12a6, 0x12ad, 0x1276, 0x3b,
+0x1296, 0x126c, 0x121d, 0x3b, 0x12f2, 0x1234, 0x121d, 0x3b, 0x1303, 0x1295, 0x12e9, 0x12c8, 0x122a, 0x3b, 0x134c, 0x1265, 0x1229, 0x12c8, 0x122a, 0x3b,
+0x121b, 0x122d, 0x127d, 0x3b, 0x12a4, 0x1355, 0x122a, 0x120d, 0x3b, 0x121c, 0x12ed, 0x3b, 0x1301, 0x1295, 0x3b, 0x1301, 0x120b, 0x12ed, 0x3b, 0x12a6,
+0x1308, 0x1235, 0x1275, 0x3b, 0x1234, 0x1355, 0x1274, 0x121d, 0x1260, 0x122d, 0x3b, 0x12a6, 0x12ad, 0x1276, 0x1260, 0x122d, 0x3b, 0x1296, 0x126c, 0x121d,
+0x1260, 0x122d, 0x3b, 0x12f2, 0x1234, 0x121d, 0x1260, 0x122d, 0x3b, 0x1303, 0x3b, 0x134c, 0x3b, 0x121b, 0x3b, 0x12a4, 0x3b, 0x121c, 0x3b, 0x1301,
+0x3b, 0x1301, 0x3b, 0x12a6, 0x3b, 0x1234, 0x3b, 0x12a6, 0x3b, 0x1296, 0x3b, 0x12f2, 0x3b, 0x64a, 0x646, 0x627, 0x64a, 0x631, 0x3b, 0x641,
+0x628, 0x631, 0x627, 0x64a, 0x631, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x623, 0x628, 0x631, 0x64a, 0x644, 0x3b, 0x645, 0x627, 0x64a,
+0x648, 0x3b, 0x64a, 0x648, 0x646, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x644, 0x64a, 0x648, 0x3b, 0x623, 0x63a, 0x633, 0x637, 0x633, 0x3b,
0x633, 0x628, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x623, 0x643, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x641, 0x645, 0x628, 0x631,
-0x3b, 0x62f, 0x64a, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x62c, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x623, 0x3b, 0x645, 0x3b, 0x62c, 0x3b,
-0x62c, 0x3b, 0x623, 0x3b, 0x633, 0x3b, 0x623, 0x3b, 0x646, 0x3b, 0x62f, 0x3b, 0x643, 0x627, 0x646, 0x648, 0x646, 0x20, 0x627, 0x644,
-0x62b, 0x627, 0x646, 0x64a, 0x3b, 0x634, 0x628, 0x627, 0x637, 0x3b, 0x622, 0x630, 0x627, 0x631, 0x3b, 0x646, 0x64a, 0x633, 0x627, 0x646,
-0x3b, 0x623, 0x64a, 0x627, 0x631, 0x3b, 0x62d, 0x632, 0x64a, 0x631, 0x627, 0x646, 0x3b, 0x62a, 0x645, 0x648, 0x632, 0x3b, 0x622, 0x628,
-0x3b, 0x623, 0x64a, 0x644, 0x648, 0x644, 0x3b, 0x62a, 0x634, 0x631, 0x64a, 0x646, 0x20, 0x627, 0x644, 0x623, 0x648, 0x644, 0x3b, 0x62a,
-0x634, 0x631, 0x64a, 0x646, 0x20, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x64a, 0x3b, 0x643, 0x627, 0x646, 0x648, 0x646, 0x20, 0x627, 0x644,
-0x623, 0x648, 0x644, 0x3b, 0x643, 0x3b, 0x634, 0x3b, 0x622, 0x3b, 0x646, 0x3b, 0x623, 0x3b, 0x62d, 0x3b, 0x62a, 0x3b, 0x622, 0x3b,
-0x623, 0x3b, 0x62a, 0x3b, 0x62a, 0x3b, 0x643, 0x3b, 0x643, 0x627, 0x646, 0x648, 0x646, 0x20, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x64a,
-0x3b, 0x634, 0x628, 0x627, 0x637, 0x3b, 0x622, 0x630, 0x627, 0x631, 0x3b, 0x646, 0x64a, 0x633, 0x627, 0x646, 0x3b, 0x623, 0x64a, 0x627,
-0x631, 0x3b, 0x62d, 0x632, 0x64a, 0x631, 0x627, 0x646, 0x3b, 0x62a, 0x645, 0x648, 0x632, 0x3b, 0x622, 0x628, 0x3b, 0x623, 0x64a, 0x644,
-0x648, 0x644, 0x3b, 0x62a, 0x634, 0x631, 0x6cc, 0x646, 0x20, 0x627, 0x644, 0x623, 0x648, 0x644, 0x3b, 0x62a, 0x634, 0x631, 0x64a, 0x646,
-0x20, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x64a, 0x3b, 0x643, 0x627, 0x646, 0x648, 0x646, 0x20, 0x627, 0x644, 0x623, 0x648, 0x644, 0x3b,
-0x64a, 0x646, 0x627, 0x64a, 0x631, 0x3b, 0x641, 0x628, 0x631, 0x627, 0x64a, 0x631, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x625, 0x628,
-0x631, 0x64a, 0x644, 0x3b, 0x645, 0x627, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x646, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x644, 0x64a, 0x648,
-0x3b, 0x623, 0x63a, 0x634, 0x62a, 0x3b, 0x634, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x623, 0x643, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646,
-0x648, 0x641, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x62c, 0x645, 0x628, 0x631, 0x3b, 0x64a, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x625, 0x3b,
-0x648, 0x3b, 0x646, 0x3b, 0x644, 0x3b, 0x63a, 0x3b, 0x634, 0x3b, 0x643, 0x3b, 0x628, 0x3b, 0x62f, 0x3b, 0x64a, 0x646, 0x627, 0x64a,
-0x631, 0x3b, 0x641, 0x628, 0x631, 0x627, 0x64a, 0x631, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x623, 0x628, 0x631, 0x64a, 0x644, 0x3b,
-0x645, 0x627, 0x64a, 0x3b, 0x64a, 0x648, 0x646, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x644, 0x64a, 0x648, 0x632, 0x3b, 0x63a, 0x634, 0x62a,
-0x3b, 0x634, 0x62a, 0x646, 0x628, 0x631, 0x3b, 0x623, 0x643, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x646, 0x628, 0x631, 0x3b,
-0x62f, 0x62c, 0x646, 0x628, 0x631, 0x3b, 0x64a, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x623, 0x3b, 0x645, 0x3b, 0x646, 0x3b, 0x644, 0x3b,
-0x63a, 0x3b, 0x634, 0x3b, 0x643, 0x3b, 0x628, 0x3b, 0x62f, 0x3b, 0x570, 0x576, 0x57e, 0x3b, 0x583, 0x57f, 0x57e, 0x3b, 0x574, 0x580,
-0x57f, 0x3b, 0x561, 0x57a, 0x580, 0x3b, 0x574, 0x575, 0x57d, 0x3b, 0x570, 0x576, 0x57d, 0x3b, 0x570, 0x56c, 0x57d, 0x3b, 0x585, 0x563,
-0x57d, 0x3b, 0x57d, 0x565, 0x57a, 0x3b, 0x570, 0x578, 0x56f, 0x3b, 0x576, 0x578, 0x575, 0x3b, 0x564, 0x565, 0x56f, 0x3b, 0x570, 0x578,
-0x582, 0x576, 0x57e, 0x561, 0x580, 0x3b, 0x583, 0x565, 0x57f, 0x580, 0x57e, 0x561, 0x580, 0x3b, 0x574, 0x561, 0x580, 0x57f, 0x3b, 0x561,
-0x57a, 0x580, 0x56b, 0x56c, 0x3b, 0x574, 0x561, 0x575, 0x56b, 0x57d, 0x3b, 0x570, 0x578, 0x582, 0x576, 0x56b, 0x57d, 0x3b, 0x570, 0x578,
-0x582, 0x56c, 0x56b, 0x57d, 0x3b, 0x585, 0x563, 0x578, 0x57d, 0x57f, 0x578, 0x57d, 0x3b, 0x57d, 0x565, 0x57a, 0x57f, 0x565, 0x574, 0x562,
-0x565, 0x580, 0x3b, 0x570, 0x578, 0x56f, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x3b, 0x576, 0x578, 0x575, 0x565, 0x574, 0x562, 0x565,
-0x580, 0x3b, 0x564, 0x565, 0x56f, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x3b, 0x540, 0x3b, 0x553, 0x3b, 0x544, 0x3b, 0x531, 0x3b,
-0x544, 0x3b, 0x540, 0x3b, 0x540, 0x3b, 0x555, 0x3b, 0x54d, 0x3b, 0x540, 0x3b, 0x546, 0x3b, 0x534, 0x3b, 0x570, 0x578, 0x582, 0x576,
-0x57e, 0x561, 0x580, 0x56b, 0x3b, 0x583, 0x565, 0x57f, 0x580, 0x57e, 0x561, 0x580, 0x56b, 0x3b, 0x574, 0x561, 0x580, 0x57f, 0x56b, 0x3b,
-0x561, 0x57a, 0x580, 0x56b, 0x56c, 0x56b, 0x3b, 0x574, 0x561, 0x575, 0x56b, 0x57d, 0x56b, 0x3b, 0x570, 0x578, 0x582, 0x576, 0x56b, 0x57d,
-0x56b, 0x3b, 0x570, 0x578, 0x582, 0x56c, 0x56b, 0x57d, 0x56b, 0x3b, 0x585, 0x563, 0x578, 0x57d, 0x57f, 0x578, 0x57d, 0x56b, 0x3b, 0x57d,
-0x565, 0x57a, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x56b, 0x3b, 0x570, 0x578, 0x56f, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x56b,
-0x3b, 0x576, 0x578, 0x575, 0x565, 0x574, 0x562, 0x565, 0x580, 0x56b, 0x3b, 0x564, 0x565, 0x56f, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580,
-0x56b, 0x3b, 0x99c, 0x9be, 0x9a8, 0x9c1, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x9cd, 0x9f0, 0x9c1, 0x3b, 0x9ae, 0x9be, 0x9f0, 0x9cd, 0x99a, 0x3b,
-0x98f, 0x9aa, 0x9cd, 0x9f0, 0x9bf, 0x9b2, 0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be, 0x987, 0x3b,
-0x986, 0x997, 0x3b, 0x9b8, 0x9c7, 0x9aa, 0x9cd, 0x99f, 0x3b, 0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x3b, 0x9a8, 0x9ad, 0x9c7, 0x3b, 0x9a1,
-0x9bf, 0x9b8, 0x9c7, 0x3b, 0x99c, 0x9be, 0x9a8, 0x9c1, 0x9f1, 0x9be, 0x9f0, 0x9c0, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x9cd, 0x9f0, 0x9c1, 0x9f1,
-0x9be, 0x9f0, 0x9c0, 0x3b, 0x9ae, 0x9be, 0x9f0, 0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9f0, 0x9bf, 0x9b2, 0x3b, 0x9ae, 0x9c7, 0x3b,
-0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be, 0x987, 0x3b, 0x986, 0x997, 0x9b7, 0x9cd, 0x99f, 0x3b, 0x99b, 0x9c7, 0x9aa, 0x9cd,
-0x9a4, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9f0, 0x3b, 0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x9ac, 0x9f0, 0x3b, 0x9a8, 0x9f1, 0x9c7, 0x9ae, 0x9cd,
-0x9ac, 0x9f0, 0x3b, 0x9a1, 0x9bf, 0x99a, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9f0, 0x3b, 0x79, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x76, 0x3b,
-0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x69, 0x79, 0x6e, 0x3b, 0x69, 0x79, 0x6c, 0x3b,
-0x61, 0x76, 0x71, 0x3b, 0x73, 0x65, 0x6e, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x79, 0x3b, 0x64, 0x65, 0x6b, 0x3b,
-0x59, 0x61, 0x6e, 0x76, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x76, 0x72, 0x61, 0x6c, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x3b, 0x41,
-0x70, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x130, 0x79, 0x75, 0x6e, 0x3b, 0x130, 0x79, 0x75, 0x6c, 0x3b, 0x41,
-0x76, 0x71, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x6e, 0x74, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x79, 0x61,
-0x62, 0x72, 0x3b, 0x4e, 0x6f, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x44, 0x65, 0x6b, 0x61, 0x62, 0x72, 0x3b, 0x79, 0x61, 0x6e,
-0x76, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x76, 0x72, 0x61, 0x6c, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x65,
-0x6c, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x69, 0x79, 0x75, 0x6e, 0x3b, 0x69, 0x79, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x71, 0x75,
-0x73, 0x74, 0x3b, 0x73, 0x65, 0x6e, 0x74, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x79, 0x61, 0x62, 0x72, 0x3b,
-0x6e, 0x6f, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x64, 0x65, 0x6b, 0x61, 0x62, 0x72, 0x3b, 0x458, 0x430, 0x43d, 0x3b, 0x444, 0x435,
-0x432, 0x3b, 0x43c, 0x430, 0x440, 0x3b, 0x430, 0x43f, 0x440, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x458, 0x43d, 0x3b, 0x438, 0x458,
-0x43b, 0x3b, 0x430, 0x432, 0x433, 0x3b, 0x441, 0x435, 0x43d, 0x3b, 0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x458, 0x3b, 0x434, 0x435,
-0x43a, 0x3b, 0x408, 0x430, 0x43d, 0x432, 0x430, 0x440, 0x3b, 0x424, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x3b, 0x41c, 0x430, 0x440, 0x442,
-0x3b, 0x410, 0x43f, 0x440, 0x435, 0x43b, 0x3b, 0x41c, 0x430, 0x439, 0x3b, 0x418, 0x458, 0x443, 0x43d, 0x3b, 0x418, 0x458, 0x443, 0x43b,
-0x3b, 0x410, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x421, 0x435, 0x43d, 0x442, 0x458, 0x430, 0x431, 0x440, 0x3b, 0x41e, 0x43a, 0x442,
-0x458, 0x430, 0x431, 0x440, 0x3b, 0x41d, 0x43e, 0x458, 0x430, 0x431, 0x440, 0x3b, 0x414, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x3b, 0x458,
-0x430, 0x43d, 0x432, 0x430, 0x440, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f,
-0x440, 0x435, 0x43b, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x458, 0x443, 0x43d, 0x3b, 0x438, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x432,
-0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x458, 0x430, 0x431, 0x440, 0x3b, 0x43e, 0x43a, 0x442, 0x458, 0x430, 0x431,
-0x440, 0x3b, 0x43d, 0x43e, 0x458, 0x430, 0x431, 0x440, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x3b, 0x75, 0x72, 0x74, 0x2e,
-0x3b, 0x6f, 0x74, 0x73, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x69, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x2e,
-0x3b, 0x65, 0x6b, 0x61, 0x2e, 0x3b, 0x75, 0x7a, 0x74, 0x2e, 0x3b, 0x61, 0x62, 0x75, 0x2e, 0x3b, 0x69, 0x72, 0x61, 0x2e,
-0x3b, 0x75, 0x72, 0x72, 0x2e, 0x3b, 0x61, 0x7a, 0x61, 0x2e, 0x3b, 0x61, 0x62, 0x65, 0x2e, 0x3b, 0x75, 0x72, 0x74, 0x61,
-0x72, 0x72, 0x69, 0x6c, 0x61, 0x3b, 0x4f, 0x74, 0x73, 0x61, 0x69, 0x6c, 0x61, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x78, 0x6f,
-0x61, 0x3b, 0x41, 0x70, 0x69, 0x72, 0x69, 0x6c, 0x61, 0x3b, 0x4d, 0x61, 0x69, 0x61, 0x74, 0x7a, 0x61, 0x3b, 0x45, 0x6b,
-0x61, 0x69, 0x6e, 0x61, 0x3b, 0x55, 0x7a, 0x74, 0x61, 0x69, 0x6c, 0x61, 0x3b, 0x41, 0x62, 0x75, 0x7a, 0x74, 0x75, 0x61,
-0x3b, 0x49, 0x72, 0x61, 0x69, 0x6c, 0x61, 0x3b, 0x55, 0x72, 0x72, 0x69, 0x61, 0x3b, 0x41, 0x7a, 0x61, 0x72, 0x6f, 0x61,
-0x3b, 0x41, 0x62, 0x65, 0x6e, 0x64, 0x75, 0x61, 0x3b, 0x55, 0x3b, 0x4f, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x45,
-0x3b, 0x55, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x55, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x75, 0x72, 0x74, 0x61, 0x72, 0x72, 0x69,
-0x6c, 0x61, 0x3b, 0x6f, 0x74, 0x73, 0x61, 0x69, 0x6c, 0x61, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x78, 0x6f, 0x61, 0x3b, 0x61,
-0x70, 0x69, 0x72, 0x69, 0x6c, 0x61, 0x3b, 0x6d, 0x61, 0x69, 0x61, 0x74, 0x7a, 0x61, 0x3b, 0x65, 0x6b, 0x61, 0x69, 0x6e,
-0x61, 0x3b, 0x75, 0x7a, 0x74, 0x61, 0x69, 0x6c, 0x61, 0x3b, 0x61, 0x62, 0x75, 0x7a, 0x74, 0x75, 0x61, 0x3b, 0x69, 0x72,
-0x61, 0x69, 0x6c, 0x61, 0x3b, 0x75, 0x72, 0x72, 0x69, 0x61, 0x3b, 0x61, 0x7a, 0x61, 0x72, 0x6f, 0x61, 0x3b, 0x61, 0x62,
-0x65, 0x6e, 0x64, 0x75, 0x61, 0x3b, 0x99c, 0x9be, 0x9a8, 0x9c1, 0x9af, 0x9bc, 0x9be, 0x9b0, 0x9c0, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x9cd,
-0x9b0, 0x9c1, 0x9af, 0x9bc, 0x9be, 0x9b0, 0x9c0, 0x3b, 0x9ae, 0x9be, 0x9b0, 0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9b0, 0x9bf, 0x9b2,
-0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be, 0x987, 0x3b, 0x986, 0x997, 0x9b8, 0x9cd, 0x99f, 0x3b,
-0x9b8, 0x9c7, 0x9aa, 0x9cd, 0x99f, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x9ac, 0x9b0, 0x3b, 0x9a8,
-0x9ad, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x9a1, 0x9bf, 0x9b8, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x99c, 0x9be, 0x3b, 0x9ab,
-0x9c7, 0x3b, 0x9ae, 0x9be, 0x3b, 0x98f, 0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x3b, 0x986, 0x3b, 0x9b8,
-0x9c7, 0x3b, 0x985, 0x3b, 0x9a8, 0x3b, 0x9a1, 0x9bf, 0x3b, 0x99c, 0x9be, 0x9a8, 0x9c1, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x3b, 0x9ae, 0x9be,
-0x9b0, 0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9b0, 0x9bf, 0x9b2, 0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1,
-0x9b2, 0x9be, 0x987, 0x3b, 0x986, 0x997, 0x9b8, 0x9cd, 0x99f, 0x3b, 0x9b8, 0x9c7, 0x9aa, 0x9cd, 0x99f, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0,
-0x3b, 0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x9ac, 0x9b0, 0x3b, 0x9a8, 0x9ad, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x9a1, 0x9bf, 0x9b8,
-0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf21, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf22, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf23,
-0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf24, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf25, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf26, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf27,
-0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf28, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf29, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf21, 0xf20, 0x3b, 0xf5f, 0xfb3, 0xf0b,
-0xf21, 0xf21, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf21, 0xf22, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xf44, 0xf54,
-0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4,
-0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf42, 0xf66, 0xf74, 0xf58, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f,
-0xfb3, 0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b, 0xf54, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf63, 0xf94, 0xf0b, 0xf54,
-0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xfb2, 0xf74, 0xf42, 0xf0b, 0xf54, 0x3b, 0xf66, 0xfa4, 0xfb1,
-0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf51, 0xf74, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3,
-0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1, 0xf51, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xf42,
-0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b,
-0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf45, 0xf72, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b,
-0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b,
-0xf21, 0x3b, 0xf22, 0x3b, 0xf23, 0x3b, 0xf24, 0x3b, 0xf25, 0x3b, 0xf26, 0x3b, 0xf27, 0x3b, 0xf28, 0x3b, 0xf29, 0x3b, 0xf21, 0xf20,
-0x3b, 0xf21, 0xf21, 0x3b, 0xf21, 0xf22, 0x3b, 0xf21, 0x3b, 0xf22, 0x3b, 0xf23, 0x3b, 0xf24, 0x3b, 0xf25, 0x3b, 0xf26, 0x3b, 0xf27,
-0x3b, 0xf28, 0x3b, 0xf29, 0x3b, 0xf21, 0xf20, 0x3b, 0xf21, 0xf21, 0x3b, 0x31, 0x32, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xf44, 0xf54,
-0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf42, 0xf66, 0xf74, 0xf58,
-0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf63, 0xf94, 0xf0b,
-0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xfb2, 0xf74, 0xf42, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf51, 0xf74, 0xf53,
-0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1, 0xf51, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf51,
-0xf42, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56,
-0xf45, 0xf74, 0xf0b, 0xf42, 0xf45, 0xf72, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf49,
-0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf21, 0x3b, 0xf22, 0x3b, 0xf23, 0x3b, 0x34, 0x3b, 0xf25, 0x3b, 0xf26, 0x3b, 0xf27, 0x3b,
-0xf28, 0x3b, 0x39, 0x3b, 0xf21, 0xf20, 0x3b, 0xf21, 0xf21, 0x3b, 0xf21, 0xf22, 0x3b, 0x47, 0x65, 0x6e, 0x2e, 0x3b, 0x43, 0x2bc,
-0x68, 0x77, 0x65, 0x2e, 0x3b, 0x4d, 0x65, 0x75, 0x72, 0x2e, 0x3b, 0x45, 0x62, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x65, 0x3b,
-0x4d, 0x65, 0x7a, 0x68, 0x2e, 0x3b, 0x47, 0x6f, 0x75, 0x65, 0x2e, 0x3b, 0x45, 0x6f, 0x73, 0x74, 0x3b, 0x47, 0x77, 0x65,
-0x6e, 0x2e, 0x3b, 0x48, 0x65, 0x72, 0x65, 0x3b, 0x44, 0x75, 0x3b, 0x4b, 0x65, 0x72, 0x2e, 0x3b, 0x47, 0x65, 0x6e, 0x76,
-0x65, 0x72, 0x3b, 0x43, 0x2bc, 0x68, 0x77, 0x65, 0x76, 0x72, 0x65, 0x72, 0x3b, 0x4d, 0x65, 0x75, 0x72, 0x7a, 0x68, 0x3b,
-0x45, 0x62, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x61, 0x65, 0x3b, 0x4d, 0x65, 0x7a, 0x68, 0x65, 0x76, 0x65, 0x6e, 0x3b, 0x47,
-0x6f, 0x75, 0x65, 0x72, 0x65, 0x3b, 0x45, 0x6f, 0x73, 0x74, 0x3b, 0x47, 0x77, 0x65, 0x6e, 0x67, 0x6f, 0x6c, 0x6f, 0x3b,
-0x48, 0x65, 0x72, 0x65, 0x3b, 0x44, 0x75, 0x3b, 0x4b, 0x65, 0x72, 0x7a, 0x75, 0x3b, 0x30, 0x31, 0x3b, 0x30, 0x32, 0x3b,
-0x30, 0x33, 0x3b, 0x30, 0x34, 0x3b, 0x30, 0x35, 0x3b, 0x30, 0x36, 0x3b, 0x30, 0x37, 0x3b, 0x30, 0x38, 0x3b, 0x30, 0x39,
-0x3b, 0x31, 0x30, 0x3b, 0x31, 0x31, 0x3b, 0x31, 0x32, 0x3b, 0x47, 0x65, 0x6e, 0x2e, 0x3b, 0x43, 0x2bc, 0x68, 0x77, 0x65,
-0x2e, 0x3b, 0x4d, 0x65, 0x75, 0x72, 0x2e, 0x3b, 0x45, 0x62, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x65, 0x3b, 0x4d, 0x65, 0x7a,
-0x68, 0x2e, 0x3b, 0x47, 0x6f, 0x75, 0x65, 0x2e, 0x3b, 0x45, 0x6f, 0x73, 0x74, 0x3b, 0x47, 0x77, 0x65, 0x6e, 0x2e, 0x3b,
-0x48, 0x65, 0x72, 0x65, 0x3b, 0x44, 0x75, 0x3b, 0x4b, 0x7a, 0x75, 0x2e, 0x3b, 0x44f, 0x43d, 0x443, 0x3b, 0x444, 0x435, 0x432,
-0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x44e, 0x43d, 0x438, 0x3b, 0x44e, 0x43b,
-0x438, 0x3b, 0x430, 0x432, 0x433, 0x3b, 0x441, 0x435, 0x43f, 0x3b, 0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x435, 0x3b, 0x434, 0x435,
-0x43a, 0x3b, 0x44f, 0x43d, 0x443, 0x430, 0x440, 0x438, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x443, 0x430, 0x440, 0x438, 0x3b, 0x43c, 0x430,
-0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x44e, 0x43d, 0x438, 0x3b, 0x44e, 0x43b, 0x438,
-0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x43e, 0x43a,
-0x442, 0x43e, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x43d, 0x43e, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x434, 0x435, 0x43a, 0x435, 0x43c,
-0x432, 0x440, 0x438, 0x3b, 0x44f, 0x3b, 0x444, 0x3b, 0x43c, 0x3b, 0x430, 0x3b, 0x43c, 0x3b, 0x44e, 0x3b, 0x44e, 0x3b, 0x430, 0x3b,
-0x441, 0x3b, 0x43e, 0x3b, 0x43d, 0x3b, 0x434, 0x3b, 0x1007, 0x1014, 0x103a, 0x3b, 0x1016, 0x1031, 0x3b, 0x1019, 0x1010, 0x103a, 0x3b, 0x1027,
-0x3b, 0x1019, 0x1031, 0x3b, 0x1007, 0x103d, 0x1014, 0x103a, 0x3b, 0x1007, 0x1030, 0x3b, 0x1029, 0x3b, 0x1005, 0x1000, 0x103a, 0x3b, 0x1021, 0x1031,
-0x102c, 0x1000, 0x103a, 0x3b, 0x1014, 0x102d, 0x102f, 0x3b, 0x1012, 0x102e, 0x3b, 0x1007, 0x1014, 0x103a, 0x1014, 0x101d, 0x102b, 0x101b, 0x102e, 0x3b,
-0x1016, 0x1031, 0x1016, 0x1031, 0x102c, 0x103a, 0x101d, 0x102b, 0x101b, 0x102e, 0x3b, 0x1019, 0x1010, 0x103a, 0x3b, 0x1027, 0x1015, 0x103c, 0x102e, 0x3b,
-0x1019, 0x1031, 0x3b, 0x1007, 0x103d, 0x1014, 0x103a, 0x3b, 0x1007, 0x1030, 0x101c, 0x102d, 0x102f, 0x1004, 0x103a, 0x3b, 0x1029, 0x1002, 0x102f, 0x1010,
-0x103a, 0x3b, 0x1005, 0x1000, 0x103a, 0x1010, 0x1004, 0x103a, 0x1018, 0x102c, 0x3b, 0x1021, 0x1031, 0x102c, 0x1000, 0x103a, 0x1010, 0x102d, 0x102f, 0x1018,
-0x102c, 0x3b, 0x1014, 0x102d, 0x102f, 0x101d, 0x1004, 0x103a, 0x1018, 0x102c, 0x3b, 0x1012, 0x102e, 0x1007, 0x1004, 0x103a, 0x1018, 0x102c, 0x3b, 0x1007,
-0x3b, 0x1016, 0x3b, 0x1019, 0x3b, 0x1027, 0x3b, 0x1019, 0x3b, 0x1007, 0x3b, 0x1007, 0x3b, 0x1029, 0x3b, 0x1005, 0x3b, 0x1021, 0x3b, 0x1014,
-0x3b, 0x1012, 0x3b, 0x441, 0x442, 0x443, 0x3b, 0x43b, 0x44e, 0x442, 0x3b, 0x441, 0x430, 0x43a, 0x3b, 0x43a, 0x440, 0x430, 0x3b, 0x43c,
-0x430, 0x439, 0x3b, 0x447, 0x44d, 0x440, 0x3b, 0x43b, 0x456, 0x43f, 0x3b, 0x436, 0x43d, 0x456, 0x3b, 0x432, 0x435, 0x440, 0x3b, 0x43a,
-0x430, 0x441, 0x3b, 0x43b, 0x456, 0x441, 0x3b, 0x441, 0x43d, 0x435, 0x3b, 0x441, 0x442, 0x443, 0x434, 0x437, 0x435, 0x43d, 0x44c, 0x3b,
-0x43b, 0x44e, 0x442, 0x44b, 0x3b, 0x441, 0x430, 0x43a, 0x430, 0x432, 0x456, 0x43a, 0x3b, 0x43a, 0x440, 0x430, 0x441, 0x430, 0x432, 0x456,
-0x43a, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x447, 0x44d, 0x440, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x43b, 0x456, 0x43f, 0x435, 0x43d, 0x44c,
-0x3b, 0x436, 0x43d, 0x456, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x432, 0x435, 0x440, 0x430, 0x441, 0x435, 0x43d, 0x44c, 0x3b, 0x43a, 0x430,
-0x441, 0x442, 0x440, 0x44b, 0x447, 0x43d, 0x456, 0x43a, 0x3b, 0x43b, 0x456, 0x441, 0x442, 0x430, 0x43f, 0x430, 0x434, 0x3b, 0x441, 0x43d,
-0x435, 0x436, 0x430, 0x43d, 0x44c, 0x3b, 0x441, 0x3b, 0x43b, 0x3b, 0x441, 0x3b, 0x43a, 0x3b, 0x43c, 0x3b, 0x447, 0x3b, 0x43b, 0x3b,
-0x436, 0x3b, 0x432, 0x3b, 0x43a, 0x3b, 0x43b, 0x3b, 0x441, 0x3b, 0x441, 0x442, 0x443, 0x3b, 0x43b, 0x44e, 0x442, 0x3b, 0x441, 0x430,
-0x43a, 0x3b, 0x43a, 0x440, 0x430, 0x3b, 0x43c, 0x430, 0x44f, 0x3b, 0x447, 0x44d, 0x440, 0x3b, 0x43b, 0x456, 0x43f, 0x3b, 0x436, 0x43d,
-0x456, 0x3b, 0x432, 0x435, 0x440, 0x3b, 0x43a, 0x430, 0x441, 0x3b, 0x43b, 0x456, 0x441, 0x3b, 0x441, 0x43d, 0x435, 0x3b, 0x441, 0x442,
-0x443, 0x434, 0x437, 0x435, 0x43d, 0x44f, 0x3b, 0x43b, 0x44e, 0x442, 0x430, 0x433, 0x430, 0x3b, 0x441, 0x430, 0x43a, 0x430, 0x432, 0x456,
-0x43a, 0x430, 0x3b, 0x43a, 0x440, 0x430, 0x441, 0x430, 0x432, 0x456, 0x43a, 0x430, 0x3b, 0x43c, 0x430, 0x44f, 0x3b, 0x447, 0x44d, 0x440,
-0x432, 0x435, 0x43d, 0x44f, 0x3b, 0x43b, 0x456, 0x43f, 0x435, 0x43d, 0x44f, 0x3b, 0x436, 0x43d, 0x456, 0x45e, 0x43d, 0x44f, 0x3b, 0x432,
-0x435, 0x440, 0x430, 0x441, 0x43d, 0x44f, 0x3b, 0x43a, 0x430, 0x441, 0x442, 0x440, 0x44b, 0x447, 0x43d, 0x456, 0x43a, 0x430, 0x3b, 0x43b,
-0x456, 0x441, 0x442, 0x430, 0x43f, 0x430, 0x434, 0x430, 0x3b, 0x441, 0x43d, 0x435, 0x436, 0x43d, 0x44f, 0x3b, 0x1798, 0x1780, 0x179a, 0x17b6,
-0x3b, 0x1780, 0x17bb, 0x1798, 0x17d2, 0x1797, 0x17c8, 0x3b, 0x1798, 0x17b8, 0x1793, 0x17b6, 0x3b, 0x1798, 0x17c1, 0x179f, 0x17b6, 0x3b, 0x17a7, 0x179f,
-0x1797, 0x17b6, 0x3b, 0x1798, 0x17b7, 0x1790, 0x17bb, 0x1793, 0x17b6, 0x3b, 0x1780, 0x1780, 0x17d2, 0x1780, 0x178a, 0x17b6, 0x3b, 0x179f, 0x17b8, 0x17a0,
-0x17b6, 0x3b, 0x1780, 0x1789, 0x17d2, 0x1789, 0x17b6, 0x3b, 0x178f, 0x17bb, 0x179b, 0x17b6, 0x3b, 0x179c, 0x17b7, 0x1785, 0x17d2, 0x1786, 0x17b7, 0x1780,
-0x17b6, 0x3b, 0x1792, 0x17d2, 0x1793, 0x17bc, 0x3b, 0x1798, 0x3b, 0x1780, 0x3b, 0x1798, 0x3b, 0x1798, 0x3b, 0x17a7, 0x3b, 0x1798, 0x3b, 0x1780,
-0x3b, 0x179f, 0x3b, 0x1780, 0x3b, 0x178f, 0x3b, 0x179c, 0x3b, 0x1792, 0x3b, 0x67, 0x65, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x72,
-0x2e, 0x3b, 0x6d, 0x61, 0x72, 0xe7, 0x3b, 0x61, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x67, 0x3b, 0x6a, 0x75, 0x6e,
-0x79, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e,
-0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x73, 0x2e, 0x3b, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x66, 0x65, 0x62,
-0x72, 0x65, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0xe7, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x67, 0x3b,
-0x6a, 0x75, 0x6e, 0x79, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6f, 0x6c, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x3b, 0x73, 0x65,
-0x74, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d,
-0x62, 0x72, 0x65, 0x3b, 0x64, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x47, 0x4e, 0x3b, 0x46, 0x42, 0x3b, 0x4d,
-0xc7, 0x3b, 0x41, 0x42, 0x3b, 0x4d, 0x47, 0x3b, 0x4a, 0x4e, 0x3b, 0x4a, 0x4c, 0x3b, 0x41, 0x47, 0x3b, 0x53, 0x54, 0x3b,
-0x4f, 0x43, 0x3b, 0x4e, 0x56, 0x3b, 0x44, 0x53, 0x3b, 0x64, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x2e, 0x3b, 0x64, 0x65, 0x20,
-0x66, 0x65, 0x62, 0x72, 0x2e, 0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x72, 0xe7, 0x3b, 0x64, 0x2019, 0x61, 0x62, 0x72, 0x2e,
-0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x69, 0x67, 0x3b, 0x64, 0x65, 0x20, 0x6a, 0x75, 0x6e, 0x79, 0x3b, 0x64, 0x65, 0x20,
-0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x64, 0x2019, 0x61, 0x67, 0x2e, 0x3b, 0x64, 0x65, 0x20, 0x73, 0x65, 0x74, 0x2e, 0x3b, 0x64,
-0x2019, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x64, 0x65, 0x20, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x20, 0x64, 0x65, 0x73,
-0x2e, 0x3b, 0x64, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x20, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72,
-0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x72, 0xe7, 0x3b, 0x64, 0x2019, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x64, 0x65, 0x20,
-0x6d, 0x61, 0x69, 0x67, 0x3b, 0x64, 0x65, 0x20, 0x6a, 0x75, 0x6e, 0x79, 0x3b, 0x64, 0x65, 0x20, 0x6a, 0x75, 0x6c, 0x69,
-0x6f, 0x6c, 0x3b, 0x64, 0x2019, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x3b, 0x64, 0x65, 0x20, 0x73, 0x65, 0x74, 0x65, 0x6d, 0x62,
-0x72, 0x65, 0x3b, 0x64, 0x2019, 0x6f, 0x63, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x65, 0x20, 0x6e, 0x6f, 0x76, 0x65,
-0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x65, 0x20, 0x64, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x31, 0x6708, 0x3b,
-0x32, 0x6708, 0x3b, 0x33, 0x6708, 0x3b, 0x34, 0x6708, 0x3b, 0x35, 0x6708, 0x3b, 0x36, 0x6708, 0x3b, 0x37, 0x6708, 0x3b, 0x38, 0x6708,
-0x3b, 0x39, 0x6708, 0x3b, 0x31, 0x30, 0x6708, 0x3b, 0x31, 0x31, 0x6708, 0x3b, 0x31, 0x32, 0x6708, 0x3b, 0x4e00, 0x6708, 0x3b, 0x4e8c,
-0x6708, 0x3b, 0x4e09, 0x6708, 0x3b, 0x56db, 0x6708, 0x3b, 0x4e94, 0x6708, 0x3b, 0x516d, 0x6708, 0x3b, 0x4e03, 0x6708, 0x3b, 0x516b, 0x6708, 0x3b,
-0x4e5d, 0x6708, 0x3b, 0x5341, 0x6708, 0x3b, 0x5341, 0x4e00, 0x6708, 0x3b, 0x5341, 0x4e8c, 0x6708, 0x3b, 0x73, 0x69, 0x6a, 0x3b, 0x76, 0x65,
-0x6c, 0x6a, 0x3b, 0x6f, 0x17e, 0x75, 0x3b, 0x74, 0x72, 0x61, 0x3b, 0x73, 0x76, 0x69, 0x3b, 0x6c, 0x69, 0x70, 0x3b, 0x73,
-0x72, 0x70, 0x3b, 0x6b, 0x6f, 0x6c, 0x3b, 0x72, 0x75, 0x6a, 0x3b, 0x6c, 0x69, 0x73, 0x3b, 0x73, 0x74, 0x75, 0x3b, 0x70,
-0x72, 0x6f, 0x3b, 0x73, 0x69, 0x6a, 0x65, 0x10d, 0x61, 0x6e, 0x6a, 0x3b, 0x76, 0x65, 0x6c, 0x6a, 0x61, 0x10d, 0x61, 0x3b,
-0x6f, 0x17e, 0x75, 0x6a, 0x61, 0x6b, 0x3b, 0x74, 0x72, 0x61, 0x76, 0x61, 0x6e, 0x6a, 0x3b, 0x73, 0x76, 0x69, 0x62, 0x61,
-0x6e, 0x6a, 0x3b, 0x6c, 0x69, 0x70, 0x61, 0x6e, 0x6a, 0x3b, 0x73, 0x72, 0x70, 0x61, 0x6e, 0x6a, 0x3b, 0x6b, 0x6f, 0x6c,
-0x6f, 0x76, 0x6f, 0x7a, 0x3b, 0x72, 0x75, 0x6a, 0x61, 0x6e, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x3b,
-0x73, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x69, 0x3b, 0x70, 0x72, 0x6f, 0x73, 0x69, 0x6e, 0x61, 0x63, 0x3b, 0x31, 0x2e, 0x3b,
-0x32, 0x2e, 0x3b, 0x33, 0x2e, 0x3b, 0x34, 0x2e, 0x3b, 0x35, 0x2e, 0x3b, 0x36, 0x2e, 0x3b, 0x37, 0x2e, 0x3b, 0x38, 0x2e,
-0x3b, 0x39, 0x2e, 0x3b, 0x31, 0x30, 0x2e, 0x3b, 0x31, 0x31, 0x2e, 0x3b, 0x31, 0x32, 0x2e, 0x3b, 0x73, 0x69, 0x6a, 0x65,
-0x10d, 0x6e, 0x6a, 0x61, 0x3b, 0x76, 0x65, 0x6c, 0x6a, 0x61, 0x10d, 0x65, 0x3b, 0x6f, 0x17e, 0x75, 0x6a, 0x6b, 0x61, 0x3b,
-0x74, 0x72, 0x61, 0x76, 0x6e, 0x6a, 0x61, 0x3b, 0x73, 0x76, 0x69, 0x62, 0x6e, 0x6a, 0x61, 0x3b, 0x6c, 0x69, 0x70, 0x6e,
-0x6a, 0x61, 0x3b, 0x73, 0x72, 0x70, 0x6e, 0x6a, 0x61, 0x3b, 0x6b, 0x6f, 0x6c, 0x6f, 0x76, 0x6f, 0x7a, 0x61, 0x3b, 0x72,
-0x75, 0x6a, 0x6e, 0x61, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x61, 0x3b, 0x73, 0x74, 0x75, 0x64, 0x65,
-0x6e, 0x6f, 0x67, 0x61, 0x3b, 0x70, 0x72, 0x6f, 0x73, 0x69, 0x6e, 0x63, 0x61, 0x3b, 0x6c, 0x65, 0x64, 0x3b, 0xfa, 0x6e,
-0x6f, 0x3b, 0x62, 0x159, 0x65, 0x3b, 0x64, 0x75, 0x62, 0x3b, 0x6b, 0x76, 0x11b, 0x3b, 0x10d, 0x76, 0x6e, 0x3b, 0x10d, 0x76,
-0x63, 0x3b, 0x73, 0x72, 0x70, 0x3b, 0x7a, 0xe1, 0x159, 0x3b, 0x159, 0xed, 0x6a, 0x3b, 0x6c, 0x69, 0x73, 0x3b, 0x70, 0x72,
-0x6f, 0x3b, 0x6c, 0x65, 0x64, 0x65, 0x6e, 0x3b, 0xfa, 0x6e, 0x6f, 0x72, 0x3b, 0x62, 0x159, 0x65, 0x7a, 0x65, 0x6e, 0x3b,
-0x64, 0x75, 0x62, 0x65, 0x6e, 0x3b, 0x6b, 0x76, 0x11b, 0x74, 0x65, 0x6e, 0x3b, 0x10d, 0x65, 0x72, 0x76, 0x65, 0x6e, 0x3b,
-0x10d, 0x65, 0x72, 0x76, 0x65, 0x6e, 0x65, 0x63, 0x3b, 0x73, 0x72, 0x70, 0x65, 0x6e, 0x3b, 0x7a, 0xe1, 0x159, 0xed, 0x3b,
-0x159, 0xed, 0x6a, 0x65, 0x6e, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x3b, 0x70, 0x72, 0x6f, 0x73, 0x69,
-0x6e, 0x65, 0x63, 0x3b, 0x6c, 0x65, 0x64, 0x6e, 0x61, 0x3b, 0xfa, 0x6e, 0x6f, 0x72, 0x61, 0x3b, 0x62, 0x159, 0x65, 0x7a,
-0x6e, 0x61, 0x3b, 0x64, 0x75, 0x62, 0x6e, 0x61, 0x3b, 0x6b, 0x76, 0x11b, 0x74, 0x6e, 0x61, 0x3b, 0x10d, 0x65, 0x72, 0x76,
-0x6e, 0x61, 0x3b, 0x10d, 0x65, 0x72, 0x76, 0x65, 0x6e, 0x63, 0x65, 0x3b, 0x73, 0x72, 0x70, 0x6e, 0x61, 0x3b, 0x7a, 0xe1,
-0x159, 0xed, 0x3b, 0x159, 0xed, 0x6a, 0x6e, 0x61, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x75, 0x3b, 0x70,
-0x72, 0x6f, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61,
-0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c,
-0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76,
-0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61,
-0x72, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75,
-0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65,
-0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65,
-0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e,
-0x3b, 0x6d, 0x72, 0x74, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x65, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b,
-0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b,
-0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x66, 0x65,
-0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x6d, 0x61, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d,
-0x65, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x75,
-0x73, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b,
-0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x61,
-0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0x61, 0x72, 0x2e, 0x3b, 0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x61,
-0x79, 0x3b, 0x4a, 0x75, 0x6e, 0x2e, 0x3b, 0x4a, 0x75, 0x6c, 0x2e, 0x3b, 0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65, 0x70,
-0x2e, 0x3b, 0x4f, 0x63, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x61,
-0x6e, 0x3b, 0x76, 0x65, 0x65, 0x62, 0x72, 0x3b, 0x6d, 0xe4, 0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61,
-0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x3b, 0x73, 0x65,
-0x70, 0x74, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x74, 0x73, 0x3b, 0x6a, 0x61, 0x61, 0x6e,
-0x75, 0x61, 0x72, 0x3b, 0x76, 0x65, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0xe4, 0x72, 0x74, 0x73, 0x3b, 0x61,
-0x70, 0x72, 0x69, 0x6c, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6c,
-0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f,
-0x6b, 0x74, 0x6f, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x74,
-0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a,
-0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d,
-0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61,
-0x75, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x73, 0x3b, 0x6a,
-0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61,
-0x70, 0x72, 0xed, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61,
-0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f,
-0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x65,
-0x72, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72,
-0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e,
-0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x73, 0x2e,
-0x3b, 0x74, 0x61, 0x6d, 0x6d, 0x69, 0x3b, 0x68, 0x65, 0x6c, 0x6d, 0x69, 0x3b, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x73, 0x3b,
-0x68, 0x75, 0x68, 0x74, 0x69, 0x3b, 0x74, 0x6f, 0x75, 0x6b, 0x6f, 0x3b, 0x6b, 0x65, 0x73, 0xe4, 0x3b, 0x68, 0x65, 0x69,
-0x6e, 0xe4, 0x3b, 0x65, 0x6c, 0x6f, 0x3b, 0x73, 0x79, 0x79, 0x73, 0x3b, 0x6c, 0x6f, 0x6b, 0x61, 0x3b, 0x6d, 0x61, 0x72,
-0x72, 0x61, 0x73, 0x3b, 0x6a, 0x6f, 0x75, 0x6c, 0x75, 0x3b, 0x74, 0x61, 0x6d, 0x6d, 0x69, 0x6b, 0x75, 0x75, 0x3b, 0x68,
-0x65, 0x6c, 0x6d, 0x69, 0x6b, 0x75, 0x75, 0x3b, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x73, 0x6b, 0x75, 0x75, 0x3b, 0x68, 0x75,
-0x68, 0x74, 0x69, 0x6b, 0x75, 0x75, 0x3b, 0x74, 0x6f, 0x75, 0x6b, 0x6f, 0x6b, 0x75, 0x75, 0x3b, 0x6b, 0x65, 0x73, 0xe4,
-0x6b, 0x75, 0x75, 0x3b, 0x68, 0x65, 0x69, 0x6e, 0xe4, 0x6b, 0x75, 0x75, 0x3b, 0x65, 0x6c, 0x6f, 0x6b, 0x75, 0x75, 0x3b,
-0x73, 0x79, 0x79, 0x73, 0x6b, 0x75, 0x75, 0x3b, 0x6c, 0x6f, 0x6b, 0x61, 0x6b, 0x75, 0x75, 0x3b, 0x6d, 0x61, 0x72, 0x72,
-0x61, 0x73, 0x6b, 0x75, 0x75, 0x3b, 0x6a, 0x6f, 0x75, 0x6c, 0x75, 0x6b, 0x75, 0x75, 0x3b, 0x54, 0x3b, 0x48, 0x3b, 0x4d,
-0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x48, 0x3b, 0x45, 0x3b, 0x53, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x74,
-0x61, 0x6d, 0x6d, 0x69, 0x6b, 0x2e, 0x3b, 0x68, 0x65, 0x6c, 0x6d, 0x69, 0x6b, 0x2e, 0x3b, 0x6d, 0x61, 0x61, 0x6c, 0x69,
-0x73, 0x6b, 0x2e, 0x3b, 0x68, 0x75, 0x68, 0x74, 0x69, 0x6b, 0x2e, 0x3b, 0x74, 0x6f, 0x75, 0x6b, 0x6f, 0x6b, 0x2e, 0x3b,
-0x6b, 0x65, 0x73, 0xe4, 0x6b, 0x2e, 0x3b, 0x68, 0x65, 0x69, 0x6e, 0xe4, 0x6b, 0x2e, 0x3b, 0x65, 0x6c, 0x6f, 0x6b, 0x2e,
-0x3b, 0x73, 0x79, 0x79, 0x73, 0x6b, 0x2e, 0x3b, 0x6c, 0x6f, 0x6b, 0x61, 0x6b, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x72, 0x61,
-0x73, 0x6b, 0x2e, 0x3b, 0x6a, 0x6f, 0x75, 0x6c, 0x75, 0x6b, 0x2e, 0x3b, 0x74, 0x61, 0x6d, 0x6d, 0x69, 0x6b, 0x75, 0x75,
-0x74, 0x61, 0x3b, 0x68, 0x65, 0x6c, 0x6d, 0x69, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x73,
-0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x68, 0x75, 0x68, 0x74, 0x69, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x74, 0x6f, 0x75,
-0x6b, 0x6f, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6b, 0x65, 0x73, 0xe4, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x68, 0x65,
-0x69, 0x6e, 0xe4, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x65, 0x6c, 0x6f, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x73, 0x79,
-0x79, 0x73, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6c, 0x6f, 0x6b, 0x61, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6d, 0x61,
-0x72, 0x72, 0x61, 0x73, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6a, 0x6f, 0x75, 0x6c, 0x75, 0x6b, 0x75, 0x75, 0x74, 0x61,
-0x3b, 0x6a, 0x61, 0x6e, 0x76, 0x2e, 0x3b, 0x66, 0xe9, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x76,
-0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x69, 0x6e, 0x3b, 0x6a, 0x75, 0x69, 0x6c, 0x2e, 0x3b, 0x61, 0x6f,
-0xfb, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64,
-0xe9, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x76, 0x69, 0x65, 0x72, 0x3b, 0x66, 0xe9, 0x76, 0x72, 0x69, 0x65, 0x72, 0x3b,
-0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x76, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x69, 0x6e, 0x3b,
-0x6a, 0x75, 0x69, 0x6c, 0x6c, 0x65, 0x74, 0x3b, 0x61, 0x6f, 0xfb, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62,
-0x72, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b,
-0x64, 0xe9, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6a, 0x61, 0x6e, 0x76, 0x2e, 0x3b, 0x66, 0xe9, 0x76, 0x72, 0x2e,
-0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x69, 0x6e, 0x3b,
-0x6a, 0x75, 0x69, 0x6c, 0x6c, 0x2e, 0x3b, 0x61, 0x6f, 0xfb, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x63,
-0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0xe9, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0xe9,
-0x76, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x69,
-0x2e, 0x3b, 0x6a, 0x75, 0x69, 0x6c, 0x2e, 0x3b, 0x61, 0x6f, 0xfb, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f,
-0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0xe9, 0x63, 0x2e, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65,
-0x62, 0x3b, 0x4d, 0x72, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75,
-0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65,
-0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x6e, 0x65, 0x77, 0x61, 0x72, 0x69, 0x73, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x65, 0x77, 0x61,
-0x72, 0x69, 0x73, 0x3b, 0x4d, 0x61, 0x61, 0x72, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x61, 0x69,
-0x65, 0x3b, 0x4a, 0x75, 0x6e, 0x79, 0x3b, 0x4a, 0x75, 0x6c, 0x79, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73,
-0x3b, 0x53, 0x65, 0x70, 0x74, 0x69, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e,
-0x6f, 0x76, 0x69, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x73, 0x69, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x46, 0x61, 0x6f,
-0x69, 0x3b, 0x47, 0x65, 0x61, 0x72, 0x72, 0x3b, 0x4d, 0xe0, 0x72, 0x74, 0x3b, 0x47, 0x69, 0x62, 0x6c, 0x3b, 0x43, 0xe8,
-0x69, 0x74, 0x3b, 0xd2, 0x67, 0x6d, 0x68, 0x3b, 0x49, 0x75, 0x63, 0x68, 0x3b, 0x4c, 0xf9, 0x6e, 0x61, 0x3b, 0x53, 0x75,
-0x6c, 0x74, 0x3b, 0x44, 0xe0, 0x6d, 0x68, 0x3b, 0x53, 0x61, 0x6d, 0x68, 0x3b, 0x44, 0xf9, 0x62, 0x68, 0x3b, 0x41, 0x6d,
-0x20, 0x46, 0x61, 0x6f, 0x69, 0x6c, 0x6c, 0x65, 0x61, 0x63, 0x68, 0x3b, 0x41, 0x6e, 0x20, 0x47, 0x65, 0x61, 0x72, 0x72,
-0x61, 0x6e, 0x3b, 0x41, 0x6d, 0x20, 0x4d, 0xe0, 0x72, 0x74, 0x3b, 0x41, 0x6e, 0x20, 0x47, 0x69, 0x62, 0x6c, 0x65, 0x61,
-0x6e, 0x3b, 0x41, 0x6e, 0x20, 0x43, 0xe8, 0x69, 0x74, 0x65, 0x61, 0x6e, 0x3b, 0x41, 0x6e, 0x20, 0x74, 0x2d, 0xd2, 0x67,
-0x6d, 0x68, 0x69, 0x6f, 0x73, 0x3b, 0x41, 0x6e, 0x20, 0x74, 0x2d, 0x49, 0x75, 0x63, 0x68, 0x61, 0x72, 0x3b, 0x41, 0x6e,
-0x20, 0x4c, 0xf9, 0x6e, 0x61, 0x73, 0x74, 0x61, 0x6c, 0x3b, 0x41, 0x6e, 0x20, 0x74, 0x2d, 0x53, 0x75, 0x6c, 0x74, 0x61,
-0x69, 0x6e, 0x3b, 0x41, 0x6e, 0x20, 0x44, 0xe0, 0x6d, 0x68, 0x61, 0x69, 0x72, 0x3b, 0x41, 0x6e, 0x20, 0x74, 0x2d, 0x53,
-0x61, 0x6d, 0x68, 0x61, 0x69, 0x6e, 0x3b, 0x41, 0x6e, 0x20, 0x44, 0xf9, 0x62, 0x68, 0x6c, 0x61, 0x63, 0x68, 0x64, 0x3b,
-0x46, 0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x43, 0x3b, 0xd2, 0x3b, 0x49, 0x3b, 0x4c, 0x3b, 0x53, 0x3b, 0x44, 0x3b,
-0x53, 0x3b, 0x44, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x46, 0x68, 0x61, 0x6f, 0x69, 0x6c, 0x6c, 0x65, 0x61, 0x63, 0x68,
-0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x47, 0x68, 0x65, 0x61, 0x72, 0x72, 0x61, 0x6e, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20,
-0x4d, 0x68, 0xe0, 0x72, 0x74, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x47, 0x68, 0x69, 0x62, 0x6c, 0x65, 0x61, 0x6e, 0x3b,
-0x64, 0x68, 0x65, 0x6e, 0x20, 0x43, 0x68, 0xe8, 0x69, 0x74, 0x65, 0x61, 0x6e, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0xd2,
-0x67, 0x6d, 0x68, 0x69, 0x6f, 0x73, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x49, 0x75, 0x63, 0x68, 0x61, 0x72, 0x3b, 0x64,
-0x68, 0x65, 0x6e, 0x20, 0x4c, 0xf9, 0x6e, 0x61, 0x73, 0x74, 0x61, 0x6c, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x2d,
-0x53, 0x75, 0x6c, 0x74, 0x61, 0x69, 0x6e, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x44, 0xe0, 0x6d, 0x68, 0x61, 0x69, 0x72,
-0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x2d, 0x53, 0x61, 0x6d, 0x68, 0x61, 0x69, 0x6e, 0x3b, 0x64, 0x68, 0x65, 0x6e,
-0x20, 0x44, 0xf9, 0x62, 0x68, 0x6c, 0x61, 0x63, 0x68, 0x64, 0x3b, 0x58, 0x61, 0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e,
-0x3b, 0x4d, 0x61, 0x72, 0x2e, 0x3b, 0x41, 0x62, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x69, 0x6f, 0x3b, 0x58, 0x75, 0xf1, 0x6f,
-0x3b, 0x58, 0x75, 0x6c, 0x2e, 0x3b, 0x41, 0x67, 0x6f, 0x2e, 0x3b, 0x53, 0x65, 0x74, 0x2e, 0x3b, 0x4f, 0x75, 0x74, 0x2e,
-0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x63, 0x2e, 0x3b, 0x58, 0x61, 0x6e, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x46,
-0x65, 0x62, 0x72, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x3b,
-0x4d, 0x61, 0x69, 0x6f, 0x3b, 0x58, 0x75, 0xf1, 0x6f, 0x3b, 0x58, 0x75, 0x6c, 0x6c, 0x6f, 0x3b, 0x41, 0x67, 0x6f, 0x73,
-0x74, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x4f, 0x75, 0x74, 0x75, 0x62, 0x72, 0x6f, 0x3b,
-0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x44, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x58, 0x3b,
-0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x58, 0x3b, 0x58, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b,
-0x44, 0x3b, 0x78, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x62, 0x72,
-0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x6f, 0x3b, 0x78, 0x75, 0xf1, 0x6f, 0x3b, 0x78, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x6f,
-0x2e, 0x3b, 0x73, 0x65, 0x74, 0x2e, 0x3b, 0x6f, 0x75, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63,
-0x2e, 0x3b, 0x78, 0x61, 0x6e, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x6d,
-0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x6f, 0x3b, 0x78, 0x75, 0xf1, 0x6f,
-0x3b, 0x78, 0x75, 0x6c, 0x6c, 0x6f, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x65, 0x6d, 0x62,
-0x72, 0x6f, 0x3b, 0x6f, 0x75, 0x74, 0x75, 0x62, 0x72, 0x6f, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b,
-0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x78, 0x2e, 0x3b, 0x66, 0x2e, 0x3b, 0x6d, 0x2e, 0x3b, 0x61, 0x2e,
-0x3b, 0x6d, 0x2e, 0x3b, 0x78, 0x2e, 0x3b, 0x78, 0x2e, 0x3b, 0x61, 0x2e, 0x3b, 0x73, 0x2e, 0x3b, 0x6f, 0x2e, 0x3b, 0x6e,
-0x2e, 0x3b, 0x64, 0x2e, 0x3b, 0x10d8, 0x10d0, 0x10dc, 0x3b, 0x10d7, 0x10d4, 0x10d1, 0x3b, 0x10db, 0x10d0, 0x10e0, 0x3b, 0x10d0, 0x10de, 0x10e0,
-0x3b, 0x10db, 0x10d0, 0x10d8, 0x3b, 0x10d8, 0x10d5, 0x10dc, 0x3b, 0x10d8, 0x10d5, 0x10da, 0x3b, 0x10d0, 0x10d2, 0x10d5, 0x3b, 0x10e1, 0x10d4, 0x10e5,
-0x3b, 0x10dd, 0x10e5, 0x10e2, 0x3b, 0x10dc, 0x10dd, 0x10d4, 0x3b, 0x10d3, 0x10d4, 0x10d9, 0x3b, 0x10d8, 0x10d0, 0x10dc, 0x10d5, 0x10d0, 0x10e0, 0x10d8,
-0x3b, 0x10d7, 0x10d4, 0x10d1, 0x10d4, 0x10e0, 0x10d5, 0x10d0, 0x10da, 0x10d8, 0x3b, 0x10db, 0x10d0, 0x10e0, 0x10e2, 0x10d8, 0x3b, 0x10d0, 0x10de, 0x10e0,
-0x10d8, 0x10da, 0x10d8, 0x3b, 0x10db, 0x10d0, 0x10d8, 0x10e1, 0x10d8, 0x3b, 0x10d8, 0x10d5, 0x10dc, 0x10d8, 0x10e1, 0x10d8, 0x3b, 0x10d8, 0x10d5, 0x10da,
-0x10d8, 0x10e1, 0x10d8, 0x3b, 0x10d0, 0x10d2, 0x10d5, 0x10d8, 0x10e1, 0x10e2, 0x10dd, 0x3b, 0x10e1, 0x10d4, 0x10e5, 0x10e2, 0x10d4, 0x10db, 0x10d1, 0x10d4,
-0x10e0, 0x10d8, 0x3b, 0x10dd, 0x10e5, 0x10e2, 0x10dd, 0x10db, 0x10d1, 0x10d4, 0x10e0, 0x10d8, 0x3b, 0x10dc, 0x10dd, 0x10d4, 0x10db, 0x10d1, 0x10d4, 0x10e0,
-0x10d8, 0x3b, 0x10d3, 0x10d4, 0x10d9, 0x10d4, 0x10db, 0x10d1, 0x10d4, 0x10e0, 0x10d8, 0x3b, 0x10d8, 0x3b, 0x10d7, 0x3b, 0x10db, 0x3b, 0x10d0, 0x3b,
-0x10db, 0x3b, 0x10d8, 0x3b, 0x10d8, 0x3b, 0x10d0, 0x3b, 0x10e1, 0x3b, 0x10dd, 0x3b, 0x10dc, 0x3b, 0x10d3, 0x3b, 0x4a, 0x61, 0x6e, 0x3b,
-0x46, 0x65, 0x62, 0x3b, 0x4d, 0xe4, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b,
-0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b,
-0x44, 0x65, 0x7a, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x4d,
-0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a,
-0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72,
-0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65,
-0x7a, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x61, 0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0xe4, 0x72,
-0x7a, 0x3b, 0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69,
-0x3b, 0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65, 0x70, 0x2e, 0x3b, 0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e,
-0x3b, 0x44, 0x65, 0x7a, 0x2e, 0x3b, 0x4a, 0xe4, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0xe4, 0x72, 0x3b, 0x41, 0x70,
-0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65,
-0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a, 0x3b, 0x4a, 0xe4, 0x6e, 0x6e, 0x65, 0x72,
-0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b,
-0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74,
-0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e,
-0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0xe4, 0x6e,
-0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x69,
-0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65, 0x70, 0x2e,
-0x3b, 0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x7a, 0x2e, 0x3b, 0x399, 0x3b1, 0x3bd, 0x3b,
-0x3a6, 0x3b5, 0x3b2, 0x3b, 0x39c, 0x3ac, 0x3c1, 0x3b, 0x391, 0x3c0, 0x3c1, 0x3b, 0x39c, 0x3ac, 0x3b9, 0x3b, 0x399, 0x3bf, 0x3cd, 0x3bd,
-0x3b, 0x399, 0x3bf, 0x3cd, 0x3bb, 0x3b, 0x391, 0x3cd, 0x3b3, 0x3b, 0x3a3, 0x3b5, 0x3c0, 0x3b, 0x39f, 0x3ba, 0x3c4, 0x3b, 0x39d, 0x3bf,
-0x3ad, 0x3b, 0x394, 0x3b5, 0x3ba, 0x3b, 0x399, 0x3b1, 0x3bd, 0x3bf, 0x3c5, 0x3ac, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x3a6, 0x3b5, 0x3b2,
-0x3c1, 0x3bf, 0x3c5, 0x3ac, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x39c, 0x3ac, 0x3c1, 0x3c4, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x391, 0x3c0, 0x3c1,
-0x3af, 0x3bb, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x39c, 0x3ac, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x399, 0x3bf, 0x3cd, 0x3bd, 0x3b9, 0x3bf, 0x3c2, 0x3b,
-0x399, 0x3bf, 0x3cd, 0x3bb, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x391, 0x3cd, 0x3b3, 0x3bf, 0x3c5, 0x3c3, 0x3c4, 0x3bf, 0x3c2, 0x3b, 0x3a3, 0x3b5,
-0x3c0, 0x3c4, 0x3ad, 0x3bc, 0x3b2, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x39f, 0x3ba, 0x3c4, 0x3ce, 0x3b2, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b,
-0x39d, 0x3bf, 0x3ad, 0x3bc, 0x3b2, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x394, 0x3b5, 0x3ba, 0x3ad, 0x3bc, 0x3b2, 0x3c1, 0x3b9, 0x3bf, 0x3c2,
-0x3b, 0x399, 0x3b, 0x3a6, 0x3b, 0x39c, 0x3b, 0x391, 0x3b, 0x39c, 0x3b, 0x399, 0x3b, 0x399, 0x3b, 0x391, 0x3b, 0x3a3, 0x3b, 0x39f,
-0x3b, 0x39d, 0x3b, 0x394, 0x3b, 0x399, 0x3b1, 0x3bd, 0x3b, 0x3a6, 0x3b5, 0x3b2, 0x3b, 0x39c, 0x3b1, 0x3c1, 0x3b, 0x391, 0x3c0, 0x3c1,
-0x3b, 0x39c, 0x3b1, 0x390, 0x3b, 0x399, 0x3bf, 0x3c5, 0x3bd, 0x3b, 0x399, 0x3bf, 0x3c5, 0x3bb, 0x3b, 0x391, 0x3c5, 0x3b3, 0x3b, 0x3a3,
-0x3b5, 0x3c0, 0x3b, 0x39f, 0x3ba, 0x3c4, 0x3b, 0x39d, 0x3bf, 0x3b5, 0x3b, 0x394, 0x3b5, 0x3ba, 0x3b, 0x399, 0x3b1, 0x3bd, 0x3bf, 0x3c5,
-0x3b1, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x3a6, 0x3b5, 0x3b2, 0x3c1, 0x3bf, 0x3c5, 0x3b1, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x39c, 0x3b1,
-0x3c1, 0x3c4, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x391, 0x3c0, 0x3c1, 0x3b9, 0x3bb, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x39c, 0x3b1, 0x390, 0x3bf, 0x3c5,
-0x3b, 0x399, 0x3bf, 0x3c5, 0x3bd, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x399, 0x3bf, 0x3c5, 0x3bb, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x391, 0x3c5, 0x3b3,
-0x3bf, 0x3cd, 0x3c3, 0x3c4, 0x3bf, 0x3c5, 0x3b, 0x3a3, 0x3b5, 0x3c0, 0x3c4, 0x3b5, 0x3bc, 0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x39f,
-0x3ba, 0x3c4, 0x3c9, 0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x39d, 0x3bf, 0x3b5, 0x3bc, 0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x394,
-0x3b5, 0x3ba, 0x3b5, 0x3bc, 0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61,
-0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x75,
-0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63, 0x3b, 0x6a, 0x61,
-0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x73,
-0x69, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x69, 0x3b, 0x6d, 0x61, 0x6a, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a,
-0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73, 0x69, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d,
-0x62, 0x65, 0x72, 0x69, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x69, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62,
-0x65, 0x72, 0x69, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x69, 0x3b, 0xa9c, 0xabe, 0xaa8, 0xacd, 0xaaf, 0xac1,
-0x3b, 0xaab, 0xac7, 0xaac, 0xacd, 0xab0, 0xac1, 0x3b, 0xaae, 0xabe, 0xab0, 0xacd, 0xa9a, 0x3b, 0xa8f, 0xaaa, 0xacd, 0xab0, 0xabf, 0xab2,
-0x3b, 0xaae, 0xac7, 0x3b, 0xa9c, 0xac2, 0xaa8, 0x3b, 0xa9c, 0xac1, 0xab2, 0xabe, 0xa88, 0x3b, 0xa91, 0xa97, 0xab8, 0xacd, 0xa9f, 0x3b,
-0xab8, 0xaaa, 0xacd, 0xa9f, 0xac7, 0x3b, 0xa91, 0xa95, 0xacd, 0xa9f, 0xacb, 0x3b, 0xaa8, 0xab5, 0xac7, 0x3b, 0xaa1, 0xabf, 0xab8, 0xac7,
-0x3b, 0xa9c, 0xabe, 0xaa8, 0xacd, 0xaaf, 0xac1, 0xa86, 0xab0, 0xac0, 0x3b, 0xaab, 0xac7, 0xaac, 0xacd, 0xab0, 0xac1, 0xa86, 0xab0, 0xac0,
-0x3b, 0xaae, 0xabe, 0xab0, 0xacd, 0xa9a, 0x3b, 0xa8f, 0xaaa, 0xacd, 0xab0, 0xabf, 0xab2, 0x3b, 0xaae, 0xac7, 0x3b, 0xa9c, 0xac2, 0xaa8,
-0x3b, 0xa9c, 0xac1, 0xab2, 0xabe, 0xa88, 0x3b, 0xa91, 0xa97, 0xab8, 0xacd, 0xa9f, 0x3b, 0xab8, 0xaaa, 0xacd, 0xa9f, 0xac7, 0xaae, 0xacd,
-0xaac, 0xab0, 0x3b, 0xa91, 0xa95, 0xacd, 0xa9f, 0xacb, 0xaac, 0xab0, 0x3b, 0xaa8, 0xab5, 0xac7, 0xaae, 0xacd, 0xaac, 0xab0, 0x3b, 0xaa1,
-0xabf, 0xab8, 0xac7, 0xaae, 0xacd, 0xaac, 0xab0, 0x3b, 0xa9c, 0xabe, 0x3b, 0xaab, 0xac7, 0x3b, 0xaae, 0xabe, 0x3b, 0xa8f, 0x3b, 0xaae,
-0xac7, 0x3b, 0xa9c, 0xac2, 0x3b, 0xa9c, 0xac1, 0x3b, 0xa91, 0x3b, 0xab8, 0x3b, 0xa91, 0x3b, 0xaa8, 0x3b, 0xaa1, 0xabf, 0x3b, 0x4a,
-0x61, 0x6e, 0x3b, 0x46, 0x61, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x66, 0x69, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x59,
-0x75, 0x6e, 0x3b, 0x59, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x75, 0x3b, 0x53, 0x61, 0x74, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e,
-0x75, 0x77, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x61, 0x69, 0x72, 0x75, 0x3b, 0x46, 0x61, 0x62, 0x75, 0x72,
-0x61, 0x69, 0x72, 0x75, 0x3b, 0x4d, 0x61, 0x72, 0x69, 0x73, 0x3b, 0x41, 0x66, 0x69, 0x72, 0x69, 0x6c, 0x75, 0x3b, 0x4d,
-0x61, 0x79, 0x75, 0x3b, 0x59, 0x75, 0x6e, 0x69, 0x3b, 0x59, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x67, 0x75, 0x73, 0x74, 0x61,
-0x3b, 0x53, 0x61, 0x74, 0x75, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x75, 0x77, 0x61,
-0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x61, 0x6d, 0x62, 0x61, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b,
-0x4d, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x5d9, 0x5e0, 0x5d5, 0x5f3,
-0x3b, 0x5e4, 0x5d1, 0x5e8, 0x5f3, 0x3b, 0x5de, 0x5e8, 0x5e5, 0x3b, 0x5d0, 0x5e4, 0x5e8, 0x5f3, 0x3b, 0x5de, 0x5d0, 0x5d9, 0x3b, 0x5d9,
-0x5d5, 0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dc, 0x5d9, 0x3b, 0x5d0, 0x5d5, 0x5d2, 0x5f3, 0x3b, 0x5e1, 0x5e4, 0x5d8, 0x5f3, 0x3b, 0x5d0,
-0x5d5, 0x5e7, 0x5f3, 0x3b, 0x5e0, 0x5d5, 0x5d1, 0x5f3, 0x3b, 0x5d3, 0x5e6, 0x5de, 0x5f3, 0x3b, 0x5d9, 0x5e0, 0x5d5, 0x5d0, 0x5e8, 0x3b,
-0x5e4, 0x5d1, 0x5e8, 0x5d5, 0x5d0, 0x5e8, 0x3b, 0x5de, 0x5e8, 0x5e5, 0x3b, 0x5d0, 0x5e4, 0x5e8, 0x5d9, 0x5dc, 0x3b, 0x5de, 0x5d0, 0x5d9,
-0x3b, 0x5d9, 0x5d5, 0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dc, 0x5d9, 0x3b, 0x5d0, 0x5d5, 0x5d2, 0x5d5, 0x5e1, 0x5d8, 0x3b, 0x5e1, 0x5e4,
-0x5d8, 0x5de, 0x5d1, 0x5e8, 0x3b, 0x5d0, 0x5d5, 0x5e7, 0x5d8, 0x5d5, 0x5d1, 0x5e8, 0x3b, 0x5e0, 0x5d5, 0x5d1, 0x5de, 0x5d1, 0x5e8, 0x3b,
-0x5d3, 0x5e6, 0x5de, 0x5d1, 0x5e8, 0x3b, 0x91c, 0x928, 0x970, 0x3b, 0x92b, 0x93c, 0x930, 0x970, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a,
-0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x948, 0x932, 0x3b, 0x92e, 0x908, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x970, 0x3b,
-0x905, 0x917, 0x970, 0x3b, 0x938, 0x93f, 0x924, 0x970, 0x3b, 0x905, 0x915, 0x94d, 0x924, 0x942, 0x970, 0x3b, 0x928, 0x935, 0x970, 0x3b,
-0x926, 0x93f, 0x938, 0x970, 0x3b, 0x91c, 0x928, 0x935, 0x930, 0x940, 0x3b, 0x92b, 0x93c, 0x930, 0x935, 0x930, 0x940, 0x3b, 0x92e, 0x93e,
-0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x948, 0x932, 0x3b, 0x92e, 0x908, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941,
-0x932, 0x93e, 0x908, 0x3b, 0x905, 0x917, 0x938, 0x94d, 0x924, 0x3b, 0x938, 0x93f, 0x924, 0x902, 0x92c, 0x930, 0x3b, 0x905, 0x915, 0x94d,
-0x924, 0x942, 0x92c, 0x930, 0x3b, 0x928, 0x935, 0x902, 0x92c, 0x930, 0x3b, 0x926, 0x93f, 0x938, 0x902, 0x92c, 0x930, 0x3b, 0x91c, 0x3b,
-0x92b, 0x93c, 0x3b, 0x92e, 0x93e, 0x3b, 0x905, 0x3b, 0x92e, 0x3b, 0x91c, 0x942, 0x3b, 0x91c, 0x941, 0x3b, 0x905, 0x3b, 0x938, 0x93f,
-0x3b, 0x905, 0x3b, 0x928, 0x3b, 0x926, 0x93f, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x2e, 0x3b, 0x6d,
-0xe1, 0x72, 0x63, 0x2e, 0x3b, 0xe1, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0xe1, 0x6a, 0x2e, 0x3b, 0x6a, 0xfa, 0x6e, 0x2e, 0x3b,
-0x6a, 0xfa, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x7a, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x6b, 0x74,
-0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0xe1, 0x72, 0x3b, 0x66,
-0x65, 0x62, 0x72, 0x75, 0xe1, 0x72, 0x3b, 0x6d, 0xe1, 0x72, 0x63, 0x69, 0x75, 0x73, 0x3b, 0xe1, 0x70, 0x72, 0x69, 0x6c,
-0x69, 0x73, 0x3b, 0x6d, 0xe1, 0x6a, 0x75, 0x73, 0x3b, 0x6a, 0xfa, 0x6e, 0x69, 0x75, 0x73, 0x3b, 0x6a, 0xfa, 0x6c, 0x69,
-0x75, 0x73, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x7a, 0x74, 0x75, 0x73, 0x3b, 0x73, 0x7a, 0x65, 0x70, 0x74, 0x65, 0x6d,
-0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0xf3, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72,
-0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0xc1, 0x3b, 0x4d, 0x3b,
-0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x7a, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b,
-0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0xed, 0x3b, 0x6a,
-0xfa, 0x6e, 0x2e, 0x3b, 0x6a, 0xfa, 0x6c, 0x2e, 0x3b, 0xe1, 0x67, 0xfa, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f,
-0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0xf3, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x73, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0xfa, 0x61, 0x72,
-0x3b, 0x66, 0x65, 0x62, 0x72, 0xfa, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0xed, 0x6c, 0x3b,
-0x6d, 0x61, 0xed, 0x3b, 0x6a, 0xfa, 0x6e, 0xed, 0x3b, 0x6a, 0xfa, 0x6c, 0xed, 0x3b, 0xe1, 0x67, 0xfa, 0x73, 0x74, 0x3b,
-0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0xf3, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0xf3,
-0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x3b, 0x46, 0x3b,
-0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0xc1, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b,
-0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b,
-0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b,
-0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72,
-0x75, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x72, 0x65, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x69,
-0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73, 0x3b, 0x53,
-0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76,
-0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x45, 0x61, 0x6e, 0x3b, 0x46,
-0x65, 0x61, 0x62, 0x68, 0x3b, 0x4d, 0xe1, 0x72, 0x74, 0x61, 0x3b, 0x41, 0x69, 0x62, 0x3b, 0x42, 0x65, 0x61, 0x6c, 0x3b,
-0x4d, 0x65, 0x69, 0x74, 0x68, 0x3b, 0x49, 0xfa, 0x69, 0x6c, 0x3b, 0x4c, 0xfa, 0x6e, 0x3b, 0x4d, 0x46, 0xf3, 0x6d, 0x68,
-0x3b, 0x44, 0x46, 0xf3, 0x6d, 0x68, 0x3b, 0x53, 0x61, 0x6d, 0x68, 0x3b, 0x4e, 0x6f, 0x6c, 0x6c, 0x3b, 0x45, 0x61, 0x6e,
-0xe1, 0x69, 0x72, 0x3b, 0x46, 0x65, 0x61, 0x62, 0x68, 0x72, 0x61, 0x3b, 0x4d, 0xe1, 0x72, 0x74, 0x61, 0x3b, 0x41, 0x69,
-0x62, 0x72, 0x65, 0xe1, 0x6e, 0x3b, 0x42, 0x65, 0x61, 0x6c, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x3b, 0x4d, 0x65, 0x69, 0x74,
-0x68, 0x65, 0x61, 0x6d, 0x68, 0x3b, 0x49, 0xfa, 0x69, 0x6c, 0x3b, 0x4c, 0xfa, 0x6e, 0x61, 0x73, 0x61, 0x3b, 0x4d, 0x65,
-0xe1, 0x6e, 0x20, 0x46, 0xf3, 0x6d, 0x68, 0x61, 0x69, 0x72, 0x3b, 0x44, 0x65, 0x69, 0x72, 0x65, 0x61, 0x64, 0x68, 0x20,
-0x46, 0xf3, 0x6d, 0x68, 0x61, 0x69, 0x72, 0x3b, 0x53, 0x61, 0x6d, 0x68, 0x61, 0x69, 0x6e, 0x3b, 0x4e, 0x6f, 0x6c, 0x6c,
-0x61, 0x69, 0x67, 0x3b, 0x45, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x42, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x4c, 0x3b,
-0x4d, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x67, 0x65, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b,
-0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x67, 0x3b, 0x67, 0x69, 0x75, 0x3b, 0x6c, 0x75, 0x67, 0x3b, 0x61, 0x67, 0x6f, 0x3b,
-0x73, 0x65, 0x74, 0x3b, 0x6f, 0x74, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x69, 0x63, 0x3b, 0x67, 0x65, 0x6e, 0x6e,
-0x61, 0x69, 0x6f, 0x3b, 0x66, 0x65, 0x62, 0x62, 0x72, 0x61, 0x69, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x61,
-0x70, 0x72, 0x69, 0x6c, 0x65, 0x3b, 0x6d, 0x61, 0x67, 0x67, 0x69, 0x6f, 0x3b, 0x67, 0x69, 0x75, 0x67, 0x6e, 0x6f, 0x3b,
-0x6c, 0x75, 0x67, 0x6c, 0x69, 0x6f, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x74, 0x65, 0x6d,
-0x62, 0x72, 0x65, 0x3b, 0x6f, 0x74, 0x74, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x65,
-0x3b, 0x64, 0x69, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x47, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b,
-0x47, 0x3b, 0x4c, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0xc9c, 0xca8, 0x3b, 0xcab, 0xcc6, 0xcac,
-0xccd, 0xcb0, 0x3b, 0xcae, 0xcbe, 0xcb0, 0xccd, 0xc9a, 0xccd, 0x3b, 0xc8f, 0xcaa, 0xccd, 0xcb0, 0xcbf, 0x3b, 0xcae, 0xcc7, 0x3b, 0xc9c,
-0xcc2, 0xca8, 0xccd, 0x3b, 0xc9c, 0xcc1, 0xcb2, 0xcc8, 0x3b, 0xc86, 0xc97, 0x3b, 0xcb8, 0xcc6, 0xcaa, 0xccd, 0xc9f, 0xcc6, 0xc82, 0x3b,
-0xc85, 0xc95, 0xccd, 0xc9f, 0xccb, 0x3b, 0xca8, 0xcb5, 0xcc6, 0xc82, 0x3b, 0xca1, 0xcbf, 0xcb8, 0xcc6, 0xc82, 0x3b, 0xc9c, 0xca8, 0xcb5,
-0xcb0, 0xcbf, 0x3b, 0xcab, 0xcc6, 0xcac, 0xccd, 0xcb0, 0xcb5, 0xcb0, 0xcbf, 0x3b, 0xcae, 0xcbe, 0xcb0, 0xccd, 0xc9a, 0xccd, 0x3b, 0xc8f,
-0xcaa, 0xccd, 0xcb0, 0xcbf, 0xcb2, 0xccd, 0x3b, 0xcae, 0xcc7, 0x3b, 0xc9c, 0xcc2, 0xca8, 0xccd, 0x3b, 0xc9c, 0xcc1, 0xcb2, 0xcc8, 0x3b,
-0xc86, 0xc97, 0xcb8, 0xccd, 0xc9f, 0xccd, 0x3b, 0xcb8, 0xcc6, 0xcaa, 0xccd, 0xc9f, 0xcc6, 0xc82, 0xcac, 0xcb0, 0xccd, 0x3b, 0xc85, 0xc95,
-0xccd, 0xc9f, 0xccb, 0xcac, 0xcb0, 0xccd, 0x3b, 0xca8, 0xcb5, 0xcc6, 0xc82, 0xcac, 0xcb0, 0xccd, 0x3b, 0xca1, 0xcbf, 0xcb8, 0xcc6, 0xc82,
-0xcac, 0xcb0, 0xccd, 0x3b, 0xc9c, 0x3b, 0xcab, 0xcc6, 0x3b, 0xcae, 0xcbe, 0x3b, 0xc8f, 0x3b, 0xcae, 0xcc7, 0x3b, 0xc9c, 0xcc2, 0x3b,
-0xc9c, 0xcc1, 0x3b, 0xc86, 0x3b, 0xcb8, 0xcc6, 0x3b, 0xc85, 0x3b, 0xca8, 0x3b, 0xca1, 0xcbf, 0x3b, 0x62c, 0x646, 0x624, 0x631, 0x6cc,
-0x3b, 0x641, 0x631, 0x624, 0x631, 0x6cc, 0x3b, 0x645, 0x627, 0x631, 0x655, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645,
-0x6cc, 0x654, 0x3b, 0x62c, 0x648, 0x657, 0x646, 0x3b, 0x62c, 0x648, 0x657, 0x644, 0x627, 0x6cc, 0x6cc, 0x3b, 0x627, 0x6af, 0x633, 0x62a,
-0x3b, 0x633, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x657, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631,
-0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x62c, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x627, 0x3b, 0x645, 0x3b, 0x62c, 0x3b, 0x62c,
-0x3b, 0x627, 0x3b, 0x633, 0x3b, 0x633, 0x3b, 0x627, 0x3b, 0x646, 0x3b, 0x49a, 0x430, 0x4a3, 0x2e, 0x3b, 0x410, 0x49b, 0x43f, 0x2e,
-0x3b, 0x41d, 0x430, 0x443, 0x2e, 0x3b, 0x421, 0x4d9, 0x443, 0x2e, 0x3b, 0x41c, 0x430, 0x43c, 0x2e, 0x3b, 0x41c, 0x430, 0x443, 0x2e,
-0x3b, 0x428, 0x456, 0x43b, 0x2e, 0x3b, 0x422, 0x430, 0x43c, 0x2e, 0x3b, 0x49a, 0x44b, 0x440, 0x2e, 0x3b, 0x49a, 0x430, 0x437, 0x2e,
-0x3b, 0x49a, 0x430, 0x440, 0x2e, 0x3b, 0x416, 0x435, 0x43b, 0x2e, 0x3b, 0x49a, 0x430, 0x4a3, 0x442, 0x430, 0x440, 0x3b, 0x410, 0x49b,
-0x43f, 0x430, 0x43d, 0x3b, 0x41d, 0x430, 0x443, 0x440, 0x44b, 0x437, 0x3b, 0x421, 0x4d9, 0x443, 0x456, 0x440, 0x3b, 0x41c, 0x430, 0x43c,
-0x44b, 0x440, 0x3b, 0x41c, 0x430, 0x443, 0x441, 0x44b, 0x43c, 0x3b, 0x428, 0x456, 0x43b, 0x434, 0x435, 0x3b, 0x422, 0x430, 0x43c, 0x44b,
-0x437, 0x3b, 0x49a, 0x44b, 0x440, 0x43a, 0x4af, 0x439, 0x435, 0x43a, 0x3b, 0x49a, 0x430, 0x437, 0x430, 0x43d, 0x3b, 0x49a, 0x430, 0x440,
-0x430, 0x448, 0x430, 0x3b, 0x416, 0x435, 0x43b, 0x442, 0x43e, 0x49b, 0x441, 0x430, 0x43d, 0x3b, 0x49a, 0x3b, 0x410, 0x3b, 0x41d, 0x3b,
-0x421, 0x3b, 0x41c, 0x3b, 0x41c, 0x3b, 0x428, 0x3b, 0x422, 0x3b, 0x49a, 0x3b, 0x49a, 0x3b, 0x49a, 0x3b, 0x416, 0x3b, 0x49b, 0x430,
-0x4a3, 0x2e, 0x3b, 0x430, 0x49b, 0x43f, 0x2e, 0x3b, 0x43d, 0x430, 0x443, 0x2e, 0x3b, 0x441, 0x4d9, 0x443, 0x2e, 0x3b, 0x43c, 0x430,
-0x43c, 0x2e, 0x3b, 0x43c, 0x430, 0x443, 0x2e, 0x3b, 0x448, 0x456, 0x43b, 0x2e, 0x3b, 0x442, 0x430, 0x43c, 0x2e, 0x3b, 0x49b, 0x44b,
-0x440, 0x2e, 0x3b, 0x49b, 0x430, 0x437, 0x2e, 0x3b, 0x49b, 0x430, 0x440, 0x2e, 0x3b, 0x436, 0x435, 0x43b, 0x2e, 0x3b, 0x49b, 0x430,
-0x4a3, 0x442, 0x430, 0x440, 0x3b, 0x430, 0x49b, 0x43f, 0x430, 0x43d, 0x3b, 0x43d, 0x430, 0x443, 0x440, 0x44b, 0x437, 0x3b, 0x441, 0x4d9,
-0x443, 0x456, 0x440, 0x3b, 0x43c, 0x430, 0x43c, 0x44b, 0x440, 0x3b, 0x43c, 0x430, 0x443, 0x441, 0x44b, 0x43c, 0x3b, 0x448, 0x456, 0x43b,
-0x434, 0x435, 0x3b, 0x442, 0x430, 0x43c, 0x44b, 0x437, 0x3b, 0x49b, 0x44b, 0x440, 0x43a, 0x4af, 0x439, 0x435, 0x43a, 0x3b, 0x49b, 0x430,
-0x437, 0x430, 0x43d, 0x3b, 0x49b, 0x430, 0x440, 0x430, 0x448, 0x430, 0x3b, 0x436, 0x435, 0x43b, 0x442, 0x43e, 0x49b, 0x441, 0x430, 0x43d,
-0x3b, 0x6d, 0x75, 0x74, 0x2e, 0x3b, 0x67, 0x61, 0x73, 0x2e, 0x3b, 0x77, 0x65, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x74, 0x2e,
-0x3b, 0x67, 0x69, 0x63, 0x2e, 0x3b, 0x6b, 0x61, 0x6d, 0x2e, 0x3b, 0x6e, 0x79, 0x61, 0x2e, 0x3b, 0x6b, 0x61, 0x6e, 0x2e,
-0x3b, 0x6e, 0x7a, 0x65, 0x2e, 0x3b, 0x75, 0x6b, 0x77, 0x2e, 0x3b, 0x75, 0x67, 0x75, 0x2e, 0x3b, 0x75, 0x6b, 0x75, 0x2e,
-0x3b, 0x4d, 0x75, 0x74, 0x61, 0x72, 0x61, 0x6d, 0x61, 0x3b, 0x47, 0x61, 0x73, 0x68, 0x79, 0x61, 0x6e, 0x74, 0x61, 0x72,
-0x65, 0x3b, 0x57, 0x65, 0x72, 0x75, 0x72, 0x77, 0x65, 0x3b, 0x4d, 0x61, 0x74, 0x61, 0x3b, 0x47, 0x69, 0x63, 0x75, 0x72,
-0x61, 0x6e, 0x73, 0x69, 0x3b, 0x4b, 0x61, 0x6d, 0x65, 0x6e, 0x61, 0x3b, 0x4e, 0x79, 0x61, 0x6b, 0x61, 0x6e, 0x67, 0x61,
-0x3b, 0x4b, 0x61, 0x6e, 0x61, 0x6d, 0x61, 0x3b, 0x4e, 0x7a, 0x65, 0x6c, 0x69, 0x3b, 0x55, 0x6b, 0x77, 0x61, 0x6b, 0x69,
-0x72, 0x61, 0x3b, 0x55, 0x67, 0x75, 0x73, 0x68, 0x79, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x55, 0x6b, 0x75, 0x62, 0x6f, 0x7a,
-0x61, 0x3b, 0x42f, 0x43d, 0x432, 0x3b, 0x424, 0x435, 0x432, 0x3b, 0x41c, 0x430, 0x440, 0x3b, 0x410, 0x43f, 0x440, 0x3b, 0x41c, 0x430,
-0x439, 0x3b, 0x418, 0x44e, 0x43d, 0x3b, 0x418, 0x44e, 0x43b, 0x3b, 0x410, 0x432, 0x433, 0x3b, 0x421, 0x435, 0x43d, 0x3b, 0x41e, 0x43a,
-0x442, 0x3b, 0x41d, 0x43e, 0x44f, 0x3b, 0x414, 0x435, 0x43a, 0x3b, 0x42f, 0x43d, 0x432, 0x430, 0x440, 0x44c, 0x3b, 0x424, 0x435, 0x432,
-0x440, 0x430, 0x43b, 0x44c, 0x3b, 0x41c, 0x430, 0x440, 0x442, 0x3b, 0x410, 0x43f, 0x440, 0x435, 0x43b, 0x44c, 0x3b, 0x41c, 0x430, 0x439,
-0x3b, 0x418, 0x44e, 0x43d, 0x44c, 0x3b, 0x418, 0x44e, 0x43b, 0x44c, 0x3b, 0x410, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x421, 0x435,
-0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x41e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x41d, 0x43e, 0x44f, 0x431, 0x440,
-0x44c, 0x3b, 0x414, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x44c, 0x3b, 0x42f, 0x3b, 0x424, 0x3b, 0x41c, 0x3b, 0x410, 0x3b, 0x41c, 0x3b,
-0x418, 0x3b, 0x418, 0x3b, 0x410, 0x3b, 0x421, 0x3b, 0x41e, 0x3b, 0x41d, 0x3b, 0x414, 0x3b, 0x44f, 0x43d, 0x432, 0x2e, 0x3b, 0x444,
-0x435, 0x432, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x2e, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x44e,
-0x43d, 0x2e, 0x3b, 0x438, 0x44e, 0x43b, 0x2e, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43d, 0x2e, 0x3b, 0x43e, 0x43a,
-0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x44f, 0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e, 0x3b, 0x44f, 0x43d, 0x432, 0x430, 0x440, 0x44c, 0x3b,
-0x444, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x44c, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x435, 0x43b, 0x44c, 0x3b,
-0x43c, 0x430, 0x439, 0x3b, 0x438, 0x44e, 0x43d, 0x44c, 0x3b, 0x438, 0x44e, 0x43b, 0x44c, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442,
-0x3b, 0x441, 0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x43e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x43d, 0x43e,
-0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x44c, 0x3b, 0x31, 0xc6d4, 0x3b, 0x32, 0xc6d4, 0x3b, 0x33,
-0xc6d4, 0x3b, 0x34, 0xc6d4, 0x3b, 0x35, 0xc6d4, 0x3b, 0x36, 0xc6d4, 0x3b, 0x37, 0xc6d4, 0x3b, 0x38, 0xc6d4, 0x3b, 0x39, 0xc6d4, 0x3b,
-0x31, 0x30, 0xc6d4, 0x3b, 0x31, 0x31, 0xc6d4, 0x3b, 0x31, 0x32, 0xc6d4, 0x3b, 0x4d, 0x75, 0x74, 0x2e, 0x3b, 0x47, 0x61, 0x73,
-0x2e, 0x3b, 0x57, 0x65, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x74, 0x2e, 0x3b, 0x47, 0x69, 0x63, 0x2e, 0x3b, 0x4b, 0x61, 0x6d,
-0x2e, 0x3b, 0x4e, 0x79, 0x61, 0x2e, 0x3b, 0x4b, 0x61, 0x6e, 0x2e, 0x3b, 0x4e, 0x7a, 0x65, 0x2e, 0x3b, 0x55, 0x6b, 0x77,
-0x2e, 0x3b, 0x55, 0x67, 0x75, 0x2e, 0x3b, 0x55, 0x6b, 0x75, 0x2e, 0x3b, 0x4e, 0x7a, 0x65, 0x72, 0x6f, 0x3b, 0x52, 0x75,
-0x68, 0x75, 0x68, 0x75, 0x6d, 0x61, 0x3b, 0x4e, 0x74, 0x77, 0x61, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x3b, 0x4e, 0x64, 0x61,
-0x6d, 0x75, 0x6b, 0x69, 0x7a, 0x61, 0x3b, 0x52, 0x75, 0x73, 0x61, 0x6d, 0x61, 0x3b, 0x52, 0x75, 0x68, 0x65, 0x73, 0x68,
-0x69, 0x3b, 0x4d, 0x75, 0x6b, 0x61, 0x6b, 0x61, 0x72, 0x6f, 0x3b, 0x4e, 0x79, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x61, 0x72,
-0x6f, 0x3b, 0x4e, 0x79, 0x61, 0x6b, 0x61, 0x6e, 0x67, 0x61, 0x3b, 0x47, 0x69, 0x74, 0x75, 0x67, 0x75, 0x74, 0x75, 0x3b,
-0x4d, 0x75, 0x6e, 0x79, 0x6f, 0x6e, 0x79, 0x6f, 0x3b, 0x4b, 0x69, 0x67, 0x61, 0x72, 0x61, 0x6d, 0x61, 0x3b, 0xea1, 0x2e,
-0xe81, 0x2e, 0x3b, 0xe81, 0x2e, 0xe9e, 0x2e, 0x3b, 0xea1, 0x2e, 0xe99, 0x2e, 0x3b, 0xea1, 0x2e, 0xeaa, 0x2e, 0x3b, 0xe9e, 0x2e,
-0xe9e, 0x2e, 0x3b, 0xea1, 0xeb4, 0x2e, 0xe96, 0x2e, 0x3b, 0xe81, 0x2e, 0xea5, 0x2e, 0x3b, 0xeaa, 0x2e, 0xeab, 0x2e, 0x3b, 0xe81,
-0x2e, 0xe8d, 0x2e, 0x3b, 0xe95, 0x2e, 0xea5, 0x2e, 0x3b, 0xe9e, 0x2e, 0xe88, 0x2e, 0x3b, 0xe97, 0x2e, 0xea7, 0x2e, 0x3b, 0xea1,
-0xeb1, 0xe87, 0xe81, 0xead, 0xe99, 0x3b, 0xe81, 0xeb8, 0xea1, 0xe9e, 0xeb2, 0x3b, 0xea1, 0xeb5, 0xe99, 0xeb2, 0x3b, 0xec0, 0xea1, 0xeaa,
-0xeb2, 0x3b, 0xe9e, 0xeb6, 0xe94, 0xeaa, 0xeb0, 0xe9e, 0xeb2, 0x3b, 0xea1, 0xeb4, 0xe96, 0xeb8, 0xe99, 0xeb2, 0x3b, 0xe81, 0xecd, 0xea5,
-0xeb0, 0xe81, 0xebb, 0xe94, 0x3b, 0xeaa, 0xeb4, 0xe87, 0xeab, 0xeb2, 0x3b, 0xe81, 0xeb1, 0xe99, 0xe8d, 0xeb2, 0x3b, 0xe95, 0xeb8, 0xea5,
-0xeb2, 0x3b, 0xe9e, 0xeb0, 0xe88, 0xeb4, 0xe81, 0x3b, 0xe97, 0xeb1, 0xe99, 0xea7, 0xeb2, 0x3b, 0x6a, 0x61, 0x6e, 0x76, 0x2e, 0x3b,
-0x66, 0x65, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69,
-0x6a, 0x73, 0x3b, 0x6a, 0x16b, 0x6e, 0x2e, 0x3b, 0x6a, 0x16b, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65,
-0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a,
-0x61, 0x6e, 0x76, 0x101, 0x72, 0x69, 0x73, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x101, 0x72, 0x69, 0x73, 0x3b, 0x6d, 0x61,
-0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x12b, 0x6c, 0x69, 0x73, 0x3b, 0x6d, 0x61, 0x69, 0x6a, 0x73, 0x3b, 0x6a, 0x16b,
-0x6e, 0x69, 0x6a, 0x73, 0x3b, 0x6a, 0x16b, 0x6c, 0x69, 0x6a, 0x73, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x73, 0x3b,
-0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x73, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x72, 0x69, 0x73, 0x3b,
-0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x73, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x73, 0x3b,
-0x79, 0x61, 0x6e, 0x3b, 0x66, 0x62, 0x6c, 0x3b, 0x6d, 0x73, 0x69, 0x3b, 0x61, 0x70, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x3b,
-0x79, 0x75, 0x6e, 0x3b, 0x79, 0x75, 0x6c, 0x3b, 0x61, 0x67, 0x74, 0x3b, 0x73, 0x74, 0x62, 0x3b, 0x254, 0x74, 0x62, 0x3b,
-0x6e, 0x76, 0x62, 0x3b, 0x64, 0x73, 0x62, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x79, 0x61, 0x6d,
-0x62, 0x6f, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x62, 0x61, 0x6c, 0xe9, 0x3b, 0x73,
-0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x73, 0xe1, 0x74, 0x6f, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1,
-0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x6e, 0x65, 0x69, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d,
-0xed, 0x74, 0xe1, 0x6e, 0x6f, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0x6f, 0x74, 0xf3, 0x62,
-0xe1, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6e, 0x73, 0x61, 0x6d, 0x62, 0x6f, 0x3b, 0x73, 0xe1,
-0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0x77, 0x61, 0x6d, 0x62, 0x65, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20,
-0x79, 0x61, 0x20, 0x6c, 0x69, 0x62, 0x77, 0x61, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x7a, 0xf3,
-0x6d, 0x69, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x7a, 0xf3, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20,
-0x6d, 0x254, 0x30c, 0x6b, 0x254, 0x301, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x7a, 0xf3, 0x6d, 0x69,
-0x20, 0x6e, 0x61, 0x20, 0x6d, 0xed, 0x62, 0x61, 0x6c, 0xe9, 0x3b, 0x79, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x61, 0x3b, 0x6d,
-0x3b, 0x79, 0x3b, 0x79, 0x3b, 0x61, 0x3b, 0x73, 0x3b, 0x254, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 0x73, 0x61, 0x75, 0x73, 0x2e,
-0x3b, 0x76, 0x61, 0x73, 0x2e, 0x3b, 0x6b, 0x6f, 0x76, 0x2e, 0x3b, 0x62, 0x61, 0x6c, 0x2e, 0x3b, 0x67, 0x65, 0x67, 0x2e,
-0x3b, 0x62, 0x69, 0x72, 0x17e, 0x2e, 0x3b, 0x6c, 0x69, 0x65, 0x70, 0x2e, 0x3b, 0x72, 0x75, 0x67, 0x70, 0x2e, 0x3b, 0x72,
-0x75, 0x67, 0x73, 0x2e, 0x3b, 0x73, 0x70, 0x61, 0x6c, 0x2e, 0x3b, 0x6c, 0x61, 0x70, 0x6b, 0x72, 0x2e, 0x3b, 0x67, 0x72,
-0x75, 0x6f, 0x64, 0x2e, 0x3b, 0x73, 0x61, 0x75, 0x73, 0x69, 0x73, 0x3b, 0x76, 0x61, 0x73, 0x61, 0x72, 0x69, 0x73, 0x3b,
-0x6b, 0x6f, 0x76, 0x61, 0x73, 0x3b, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x64, 0x69, 0x73, 0x3b, 0x67, 0x65, 0x67, 0x75, 0x17e,
-0x117, 0x3b, 0x62, 0x69, 0x72, 0x17e, 0x65, 0x6c, 0x69, 0x73, 0x3b, 0x6c, 0x69, 0x65, 0x70, 0x61, 0x3b, 0x72, 0x75, 0x67,
-0x70, 0x6a, 0x16b, 0x74, 0x69, 0x73, 0x3b, 0x72, 0x75, 0x67, 0x73, 0x117, 0x6a, 0x69, 0x73, 0x3b, 0x73, 0x70, 0x61, 0x6c,
-0x69, 0x73, 0x3b, 0x6c, 0x61, 0x70, 0x6b, 0x72, 0x69, 0x74, 0x69, 0x73, 0x3b, 0x67, 0x72, 0x75, 0x6f, 0x64, 0x69, 0x73,
-0x3b, 0x53, 0x3b, 0x56, 0x3b, 0x4b, 0x3b, 0x42, 0x3b, 0x47, 0x3b, 0x42, 0x3b, 0x4c, 0x3b, 0x52, 0x3b, 0x52, 0x3b, 0x53,
-0x3b, 0x4c, 0x3b, 0x47, 0x3b, 0x73, 0x61, 0x75, 0x73, 0x69, 0x6f, 0x3b, 0x76, 0x61, 0x73, 0x61, 0x72, 0x69, 0x6f, 0x3b,
-0x6b, 0x6f, 0x76, 0x6f, 0x3b, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x64, 0x17e, 0x69, 0x6f, 0x3b, 0x67, 0x65, 0x67, 0x75, 0x17e,
-0x117, 0x73, 0x3b, 0x62, 0x69, 0x72, 0x17e, 0x65, 0x6c, 0x69, 0x6f, 0x3b, 0x6c, 0x69, 0x65, 0x70, 0x6f, 0x73, 0x3b, 0x72,
-0x75, 0x67, 0x70, 0x6a, 0x16b, 0x10d, 0x69, 0x6f, 0x3b, 0x72, 0x75, 0x67, 0x73, 0x117, 0x6a, 0x6f, 0x3b, 0x73, 0x70, 0x61,
-0x6c, 0x69, 0x6f, 0x3b, 0x6c, 0x61, 0x70, 0x6b, 0x72, 0x69, 0x10d, 0x69, 0x6f, 0x3b, 0x67, 0x72, 0x75, 0x6f, 0x64, 0x17e,
-0x69, 0x6f, 0x3b, 0x458, 0x430, 0x43d, 0x2e, 0x3b, 0x444, 0x435, 0x432, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x2e, 0x3b, 0x430, 0x43f,
-0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x2e, 0x3b, 0x458, 0x443, 0x43b, 0x2e, 0x3b, 0x430, 0x432, 0x433,
-0x2e, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x2e, 0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x435, 0x43c, 0x2e, 0x3b, 0x434,
-0x435, 0x43a, 0x2e, 0x3b, 0x458, 0x430, 0x43d, 0x443, 0x430, 0x440, 0x438, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x443, 0x430, 0x440, 0x438,
-0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x438,
-0x3b, 0x458, 0x443, 0x43b, 0x438, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x435, 0x43c, 0x432,
-0x440, 0x438, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x43d, 0x43e, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b,
-0x434, 0x435, 0x43a, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x458, 0x3b, 0x444, 0x3b, 0x43c, 0x3b, 0x430, 0x3b, 0x43c, 0x3b, 0x458,
-0x3b, 0x458, 0x3b, 0x430, 0x3b, 0x441, 0x3b, 0x43e, 0x3b, 0x43d, 0x3b, 0x434, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62,
-0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x79, 0x3b, 0x4a, 0x6f, 0x6e, 0x3b, 0x4a, 0x6f, 0x6c,
-0x3b, 0x41, 0x6f, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73,
-0x3b, 0x4a, 0x61, 0x6e, 0x6f, 0x61, 0x72, 0x79, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x6f, 0x61, 0x72, 0x79, 0x3b, 0x4d, 0x61,
-0x72, 0x74, 0x73, 0x61, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x79, 0x3b, 0x4d, 0x65, 0x79, 0x3b, 0x4a, 0x6f, 0x6e, 0x61,
-0x3b, 0x4a, 0x6f, 0x6c, 0x61, 0x79, 0x3b, 0x41, 0x6f, 0x67, 0x6f, 0x73, 0x69, 0x74, 0x72, 0x61, 0x3b, 0x53, 0x65, 0x70,
-0x74, 0x61, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x72, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x61, 0x6d,
-0x62, 0x72, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x61, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62,
-0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c,
-0x3b, 0x4f, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73,
-0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61,
-0x63, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x61,
-0x69, 0x3b, 0x4f, 0x67, 0x6f, 0x73, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74,
-0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62,
-0x65, 0x72, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4f, 0x3b, 0x53,
-0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0xd1c, 0xd28, 0xd41, 0x3b, 0xd2b, 0xd46, 0xd2c, 0xd4d, 0xd30, 0xd41, 0x3b, 0xd2e, 0xd3e,
-0xd7c, 0x3b, 0xd0f, 0xd2a, 0xd4d, 0xd30, 0xd3f, 0x3b, 0xd2e, 0xd47, 0xd2f, 0xd4d, 0x3b, 0xd1c, 0xd42, 0xd7a, 0x3b, 0xd1c, 0xd42, 0xd32,
-0xd48, 0x3b, 0xd13, 0xd17, 0x3b, 0xd38, 0xd46, 0xd2a, 0xd4d, 0xd31, 0xd4d, 0xd31, 0xd02, 0x3b, 0xd12, 0xd15, 0xd4d, 0xd1f, 0xd4b, 0x3b,
-0xd28, 0xd35, 0xd02, 0x3b, 0xd21, 0xd3f, 0xd38, 0xd02, 0x3b, 0xd1c, 0xd28, 0xd41, 0xd35, 0xd30, 0xd3f, 0x3b, 0xd2b, 0xd46, 0xd2c, 0xd4d,
-0xd30, 0xd41, 0xd35, 0xd30, 0xd3f, 0x3b, 0xd2e, 0xd3e, 0xd7c, 0xd1a, 0xd4d, 0xd1a, 0xd4d, 0x3b, 0xd0f, 0xd2a, 0xd4d, 0xd30, 0xd3f, 0xd7d,
-0x3b, 0xd2e, 0xd47, 0xd2f, 0xd4d, 0x3b, 0xd1c, 0xd42, 0xd7a, 0x3b, 0xd1c, 0xd42, 0xd32, 0xd48, 0x3b, 0xd13, 0xd17, 0xd38, 0xd4d, 0xd31,
-0xd4d, 0xd31, 0xd4d, 0x3b, 0xd38, 0xd46, 0xd2a, 0xd4d, 0xd31, 0xd4d, 0xd31, 0xd02, 0xd2c, 0xd7c, 0x3b, 0xd12, 0xd15, 0xd4d, 0x200c, 0xd1f,
-0xd4b, 0xd2c, 0xd7c, 0x3b, 0xd28, 0xd35, 0xd02, 0xd2c, 0xd7c, 0x3b, 0xd21, 0xd3f, 0xd38, 0xd02, 0xd2c, 0xd7c, 0x3b, 0xd1c, 0x3b, 0xd2b,
-0xd46, 0x3b, 0xd2e, 0xd3e, 0x3b, 0xd0f, 0x3b, 0xd2e, 0xd46, 0x3b, 0xd1c, 0xd42, 0xd7a, 0x3b, 0xd1c, 0xd42, 0x3b, 0xd13, 0x3b, 0xd38,
-0xd46, 0x3b, 0xd12, 0x3b, 0xd28, 0x3b, 0xd21, 0xd3f, 0x3b, 0xd1c, 0x3b, 0xd2b, 0x3b, 0xd2e, 0xd3e, 0x3b, 0xd0f, 0x3b, 0xd2e, 0xd46,
-0x3b, 0xd1c, 0xd42, 0xd7a, 0x3b, 0xd1c, 0xd42, 0x3b, 0xd13, 0x3b, 0xd38, 0xd46, 0x3b, 0xd12, 0x3b, 0xd28, 0x3b, 0xd21, 0xd3f, 0x3b,
-0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x72, 0x61, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x6a, 0x3b,
-0x120, 0x75, 0x6e, 0x3b, 0x4c, 0x75, 0x6c, 0x3b, 0x41, 0x77, 0x77, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x74, 0x74, 0x3b,
-0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x10b, 0x3b, 0x4a, 0x61, 0x6e, 0x6e, 0x61, 0x72, 0x3b, 0x46, 0x72, 0x61, 0x72, 0x3b,
-0x4d, 0x61, 0x72, 0x7a, 0x75, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x6a, 0x6a, 0x75, 0x3b, 0x120, 0x75,
-0x6e, 0x6a, 0x75, 0x3b, 0x4c, 0x75, 0x6c, 0x6a, 0x75, 0x3b, 0x41, 0x77, 0x77, 0x69, 0x73, 0x73, 0x75, 0x3b, 0x53, 0x65,
-0x74, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x75, 0x3b, 0x4f, 0x74, 0x74, 0x75, 0x62, 0x72, 0x75, 0x3b, 0x4e, 0x6f, 0x76, 0x65,
-0x6d, 0x62, 0x72, 0x75, 0x3b, 0x44, 0x69, 0x10b, 0x65, 0x6d, 0x62, 0x72, 0x75, 0x3b, 0x4a, 0x6e, 0x3b, 0x46, 0x72, 0x3b,
-0x4d, 0x7a, 0x3b, 0x41, 0x70, 0x3b, 0x4d, 0x6a, 0x3b, 0x120, 0x6e, 0x3b, 0x4c, 0x6a, 0x3b, 0x41, 0x77, 0x3b, 0x53, 0x74,
-0x3b, 0x4f, 0x62, 0x3b, 0x4e, 0x76, 0x3b, 0x44, 0x10b, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b,
-0x120, 0x3b, 0x4c, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x91c, 0x93e, 0x928, 0x947, 0x3b, 0x92b,
-0x947, 0x92c, 0x94d, 0x930, 0x941, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x90f, 0x92a, 0x94d, 0x930, 0x93f, 0x3b, 0x92e, 0x947,
-0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x948, 0x3b, 0x911, 0x917, 0x3b, 0x938, 0x92a, 0x94d, 0x91f, 0x947, 0x902, 0x3b,
-0x911, 0x915, 0x94d, 0x91f, 0x94b, 0x3b, 0x928, 0x94b, 0x935, 0x94d, 0x939, 0x947, 0x902, 0x3b, 0x921, 0x93f, 0x938, 0x947, 0x902, 0x3b,
-0x91c, 0x93e, 0x928, 0x947, 0x935, 0x93e, 0x930, 0x940, 0x3b, 0x92b, 0x947, 0x92c, 0x94d, 0x930, 0x941, 0x935, 0x93e, 0x930, 0x940, 0x3b,
-0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x90f, 0x92a, 0x94d, 0x930, 0x93f, 0x932, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x942, 0x928, 0x3b,
-0x91c, 0x941, 0x932, 0x948, 0x3b, 0x911, 0x917, 0x938, 0x94d, 0x91f, 0x3b, 0x938, 0x92a, 0x94d, 0x91f, 0x947, 0x902, 0x92c, 0x930, 0x3b,
-0x911, 0x915, 0x94d, 0x91f, 0x94b, 0x92c, 0x930, 0x3b, 0x928, 0x94b, 0x935, 0x94d, 0x939, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x921, 0x93f,
-0x938, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x91c, 0x93e, 0x3b, 0x92b, 0x947, 0x3b, 0x92e, 0x93e, 0x3b, 0x90f, 0x3b, 0x92e, 0x947, 0x3b,
-0x91c, 0x942, 0x3b, 0x91c, 0x941, 0x3b, 0x911, 0x3b, 0x938, 0x3b, 0x911, 0x3b, 0x928, 0x94b, 0x3b, 0x921, 0x93f, 0x3b, 0x31, 0x2d,
-0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x32, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x33, 0x2d, 0x440, 0x20, 0x441, 0x430,
-0x440, 0x3b, 0x34, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x35, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x36, 0x2d,
-0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x37, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x38, 0x2d, 0x440, 0x20, 0x441, 0x430,
-0x440, 0x3b, 0x39, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x31, 0x30, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x31,
-0x31, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x31, 0x32, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x41d, 0x44d, 0x433,
-0x434, 0x4af, 0x433, 0x44d, 0x44d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x425, 0x43e, 0x451, 0x440, 0x434, 0x443, 0x433, 0x430, 0x430,
-0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x413, 0x443, 0x440, 0x430, 0x432, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430,
-0x440, 0x3b, 0x414, 0x4e9, 0x440, 0x4e9, 0x432, 0x434, 0x4af, 0x433, 0x44d, 0x44d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x422, 0x430,
-0x432, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x417, 0x443, 0x440, 0x433, 0x430, 0x434, 0x443, 0x433,
-0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x414, 0x43e, 0x43b, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430,
-0x440, 0x3b, 0x41d, 0x430, 0x439, 0x43c, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x415, 0x441, 0x434,
-0x4af, 0x433, 0x44d, 0x44d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x410, 0x440, 0x430, 0x432, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440,
-0x20, 0x441, 0x430, 0x440, 0x3b, 0x410, 0x440, 0x432, 0x430, 0x43d, 0x20, 0x43d, 0x44d, 0x433, 0x434, 0x4af, 0x433, 0x44d, 0x44d, 0x440,
-0x20, 0x441, 0x430, 0x440, 0x3b, 0x410, 0x440, 0x432, 0x430, 0x43d, 0x20, 0x445, 0x43e, 0x451, 0x440, 0x434, 0x443, 0x433, 0x430, 0x430,
-0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x91c, 0x928, 0x935, 0x930, 0x940, 0x3b, 0x92b, 0x947, 0x92c, 0x94d, 0x930, 0x941, 0x905, 0x930,
-0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x93f, 0x932, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x941,
-0x928, 0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x908, 0x3b, 0x905, 0x917, 0x938, 0x94d, 0x91f, 0x3b, 0x938, 0x947, 0x92a, 0x94d, 0x91f, 0x947,
-0x92e, 0x94d, 0x92c, 0x930, 0x3b, 0x905, 0x915, 0x94d, 0x91f, 0x94b, 0x92c, 0x930, 0x3b, 0x928, 0x94b, 0x92d, 0x947, 0x92e, 0x94d, 0x92c,
-0x930, 0x3b, 0x921, 0x93f, 0x938, 0x947, 0x92e, 0x94d, 0x92c, 0x930, 0x3b, 0x967, 0x3b, 0x968, 0x3b, 0x969, 0x3b, 0x96a, 0x3b, 0x96b,
-0x3b, 0x96c, 0x3b, 0x96d, 0x3b, 0x96e, 0x3b, 0x96f, 0x3b, 0x967, 0x966, 0x3b, 0x967, 0x967, 0x3b, 0x967, 0x968, 0x3b, 0x91c, 0x928,
-0x935, 0x930, 0x940, 0x3b, 0x92b, 0x947, 0x92c, 0x94d, 0x930, 0x941, 0x905, 0x930, 0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b,
-0x905, 0x92a, 0x94d, 0x930, 0x93f, 0x932, 0x3b, 0x92e, 0x908, 0x3b, 0x91c, 0x941, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x908, 0x3b,
-0x905, 0x917, 0x938, 0x94d, 0x91f, 0x3b, 0x938, 0x947, 0x92a, 0x94d, 0x91f, 0x947, 0x92e, 0x94d, 0x92c, 0x930, 0x3b, 0x905, 0x915, 0x94d,
-0x91f, 0x94b, 0x92c, 0x930, 0x3b, 0x928, 0x94b, 0x92d, 0x947, 0x92e, 0x94d, 0x92c, 0x930, 0x3b, 0x921, 0x93f, 0x938, 0x947, 0x92e, 0x94d,
-0x92c, 0x930, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61,
+0x3b, 0x62f, 0x64a, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x64a, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x623, 0x3b, 0x648, 0x3b, 0x646, 0x3b,
+0x644, 0x3b, 0x63a, 0x3b, 0x633, 0x3b, 0x643, 0x3b, 0x628, 0x3b, 0x62f, 0x3b, 0x62c, 0x627, 0x646, 0x641, 0x64a, 0x3b, 0x641, 0x64a,
+0x641, 0x631, 0x64a, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x623, 0x641, 0x631, 0x64a, 0x644, 0x3b, 0x645, 0x627, 0x64a, 0x3b, 0x62c,
+0x648, 0x627, 0x646, 0x3b, 0x62c, 0x648, 0x64a, 0x644, 0x64a, 0x629, 0x3b, 0x623, 0x648, 0x62a, 0x3b, 0x633, 0x628, 0x62a, 0x645, 0x628,
+0x631, 0x3b, 0x623, 0x643, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x641, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x64a, 0x633, 0x645,
+0x628, 0x631, 0x3b, 0x62c, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x623, 0x3b, 0x645, 0x3b, 0x62c, 0x3b, 0x62c, 0x3b, 0x623, 0x3b, 0x633,
+0x3b, 0x623, 0x3b, 0x646, 0x3b, 0x62f, 0x3b, 0x643, 0x627, 0x646, 0x648, 0x646, 0x20, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x64a, 0x3b,
+0x634, 0x628, 0x627, 0x637, 0x3b, 0x622, 0x630, 0x627, 0x631, 0x3b, 0x646, 0x64a, 0x633, 0x627, 0x646, 0x3b, 0x623, 0x64a, 0x627, 0x631,
+0x3b, 0x62d, 0x632, 0x64a, 0x631, 0x627, 0x646, 0x3b, 0x62a, 0x645, 0x648, 0x632, 0x3b, 0x622, 0x628, 0x3b, 0x623, 0x64a, 0x644, 0x648,
+0x644, 0x3b, 0x62a, 0x634, 0x631, 0x64a, 0x646, 0x20, 0x627, 0x644, 0x623, 0x648, 0x644, 0x3b, 0x62a, 0x634, 0x631, 0x64a, 0x646, 0x20,
+0x627, 0x644, 0x62b, 0x627, 0x646, 0x64a, 0x3b, 0x643, 0x627, 0x646, 0x648, 0x646, 0x20, 0x627, 0x644, 0x623, 0x648, 0x644, 0x3b, 0x643,
+0x3b, 0x634, 0x3b, 0x622, 0x3b, 0x646, 0x3b, 0x623, 0x3b, 0x62d, 0x3b, 0x62a, 0x3b, 0x622, 0x3b, 0x623, 0x3b, 0x62a, 0x3b, 0x62a,
+0x3b, 0x643, 0x3b, 0x643, 0x627, 0x646, 0x648, 0x646, 0x20, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x64a, 0x3b, 0x634, 0x628, 0x627, 0x637,
+0x3b, 0x622, 0x630, 0x627, 0x631, 0x3b, 0x646, 0x64a, 0x633, 0x627, 0x646, 0x3b, 0x623, 0x64a, 0x627, 0x631, 0x3b, 0x62d, 0x632, 0x64a,
+0x631, 0x627, 0x646, 0x3b, 0x62a, 0x645, 0x648, 0x632, 0x3b, 0x622, 0x628, 0x3b, 0x623, 0x64a, 0x644, 0x648, 0x644, 0x3b, 0x62a, 0x634,
+0x631, 0x64a, 0x646, 0xa0, 0x627, 0x644, 0x623, 0x648, 0x644, 0x3b, 0x62a, 0x634, 0x631, 0x64a, 0x646, 0x20, 0x627, 0x644, 0x62b, 0x627,
+0x646, 0x64a, 0x3b, 0x643, 0x627, 0x646, 0x648, 0x646, 0x20, 0x627, 0x644, 0x623, 0x648, 0x644, 0x3b, 0x64a, 0x646, 0x627, 0x64a, 0x631,
+0x3b, 0x641, 0x628, 0x631, 0x627, 0x64a, 0x631, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x625, 0x628, 0x631, 0x64a, 0x644, 0x3b, 0x645,
+0x627, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x646, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x644, 0x64a, 0x648, 0x3b, 0x623, 0x63a, 0x634, 0x62a,
+0x3b, 0x634, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x623, 0x643, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x641, 0x645, 0x628, 0x631,
+0x3b, 0x62f, 0x62c, 0x645, 0x628, 0x631, 0x3b, 0x64a, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x625, 0x3b, 0x648, 0x3b, 0x646, 0x3b, 0x644,
+0x3b, 0x63a, 0x3b, 0x634, 0x3b, 0x643, 0x3b, 0x628, 0x3b, 0x62f, 0x3b, 0x64a, 0x646, 0x627, 0x64a, 0x631, 0x3b, 0x641, 0x628, 0x631,
+0x627, 0x64a, 0x631, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x623, 0x628, 0x631, 0x64a, 0x644, 0x3b, 0x645, 0x627, 0x64a, 0x3b, 0x64a,
+0x648, 0x646, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x644, 0x64a, 0x648, 0x632, 0x3b, 0x63a, 0x634, 0x62a, 0x3b, 0x634, 0x62a, 0x646, 0x628,
+0x631, 0x3b, 0x623, 0x643, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x646, 0x628, 0x631, 0x3b, 0x62f, 0x62c, 0x646, 0x628, 0x631,
+0x3b, 0x64a, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x623, 0x3b, 0x645, 0x3b, 0x646, 0x3b, 0x644, 0x3b, 0x63a, 0x3b, 0x634, 0x3b, 0x643,
+0x3b, 0x628, 0x3b, 0x62f, 0x3b, 0x570, 0x576, 0x57e, 0x3b, 0x583, 0x57f, 0x57e, 0x3b, 0x574, 0x580, 0x57f, 0x3b, 0x561, 0x57a, 0x580,
+0x3b, 0x574, 0x575, 0x57d, 0x3b, 0x570, 0x576, 0x57d, 0x3b, 0x570, 0x56c, 0x57d, 0x3b, 0x585, 0x563, 0x57d, 0x3b, 0x57d, 0x565, 0x57a,
+0x3b, 0x570, 0x578, 0x56f, 0x3b, 0x576, 0x578, 0x575, 0x3b, 0x564, 0x565, 0x56f, 0x3b, 0x570, 0x578, 0x582, 0x576, 0x57e, 0x561, 0x580,
+0x3b, 0x583, 0x565, 0x57f, 0x580, 0x57e, 0x561, 0x580, 0x3b, 0x574, 0x561, 0x580, 0x57f, 0x3b, 0x561, 0x57a, 0x580, 0x56b, 0x56c, 0x3b,
+0x574, 0x561, 0x575, 0x56b, 0x57d, 0x3b, 0x570, 0x578, 0x582, 0x576, 0x56b, 0x57d, 0x3b, 0x570, 0x578, 0x582, 0x56c, 0x56b, 0x57d, 0x3b,
+0x585, 0x563, 0x578, 0x57d, 0x57f, 0x578, 0x57d, 0x3b, 0x57d, 0x565, 0x57a, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x3b, 0x570, 0x578,
+0x56f, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x3b, 0x576, 0x578, 0x575, 0x565, 0x574, 0x562, 0x565, 0x580, 0x3b, 0x564, 0x565, 0x56f,
+0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x3b, 0x540, 0x3b, 0x553, 0x3b, 0x544, 0x3b, 0x531, 0x3b, 0x544, 0x3b, 0x540, 0x3b, 0x540,
+0x3b, 0x555, 0x3b, 0x54d, 0x3b, 0x540, 0x3b, 0x546, 0x3b, 0x534, 0x3b, 0x570, 0x578, 0x582, 0x576, 0x57e, 0x561, 0x580, 0x56b, 0x3b,
+0x583, 0x565, 0x57f, 0x580, 0x57e, 0x561, 0x580, 0x56b, 0x3b, 0x574, 0x561, 0x580, 0x57f, 0x56b, 0x3b, 0x561, 0x57a, 0x580, 0x56b, 0x56c,
+0x56b, 0x3b, 0x574, 0x561, 0x575, 0x56b, 0x57d, 0x56b, 0x3b, 0x570, 0x578, 0x582, 0x576, 0x56b, 0x57d, 0x56b, 0x3b, 0x570, 0x578, 0x582,
+0x56c, 0x56b, 0x57d, 0x56b, 0x3b, 0x585, 0x563, 0x578, 0x57d, 0x57f, 0x578, 0x57d, 0x56b, 0x3b, 0x57d, 0x565, 0x57a, 0x57f, 0x565, 0x574,
+0x562, 0x565, 0x580, 0x56b, 0x3b, 0x570, 0x578, 0x56f, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x56b, 0x3b, 0x576, 0x578, 0x575, 0x565,
+0x574, 0x562, 0x565, 0x580, 0x56b, 0x3b, 0x564, 0x565, 0x56f, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x56b, 0x3b, 0x99c, 0x9be, 0x9a8,
+0x9c1, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x9cd, 0x9f0, 0x9c1, 0x3b, 0x9ae, 0x9be, 0x9f0, 0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9f0, 0x9bf,
+0x9b2, 0x3b, 0x9ae, 0x9c7, 0x2019, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be, 0x987, 0x3b, 0x986, 0x997, 0x3b, 0x99b,
+0x9c7, 0x9aa, 0x9cd, 0x9a4, 0x9c7, 0x3b, 0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x3b, 0x9a8, 0x9f1, 0x9c7, 0x3b, 0x9a1, 0x9bf, 0x99a, 0x9c7,
+0x3b, 0x99c, 0x9be, 0x9a8, 0x9c1, 0x9f1, 0x9be, 0x9f0, 0x9c0, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x9cd, 0x9f0, 0x9c1, 0x9f1, 0x9be, 0x9f0, 0x9c0,
+0x3b, 0x9ae, 0x9be, 0x9f0, 0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9f0, 0x9bf, 0x9b2, 0x3b, 0x9ae, 0x9c7, 0x2019, 0x3b, 0x99c, 0x9c1,
+0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be, 0x987, 0x3b, 0x986, 0x997, 0x9b7, 0x9cd, 0x99f, 0x3b, 0x99b, 0x9c7, 0x9aa, 0x9cd, 0x9a4, 0x9c7,
+0x9ae, 0x9cd, 0x9ac, 0x9f0, 0x3b, 0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x9ac, 0x9f0, 0x3b, 0x9a8, 0x9f1, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9f0,
+0x3b, 0x9a1, 0x9bf, 0x99a, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9f0, 0x3b, 0x99c, 0x3b, 0x9ab, 0x3b, 0x9ae, 0x3b, 0x98f, 0x3b, 0x9ae, 0x3b,
+0x99c, 0x3b, 0x99c, 0x3b, 0x986, 0x3b, 0x99b, 0x3b, 0x985, 0x3b, 0x9a8, 0x3b, 0x9a1, 0x3b, 0x79, 0x61, 0x6e, 0x3b, 0x66, 0x65,
+0x76, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x69, 0x79, 0x6e, 0x3b, 0x69, 0x79,
+0x6c, 0x3b, 0x61, 0x76, 0x71, 0x3b, 0x73, 0x65, 0x6e, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x79, 0x3b, 0x64, 0x65,
+0x6b, 0x3b, 0x59, 0x61, 0x6e, 0x76, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x76, 0x72, 0x61, 0x6c, 0x3b, 0x4d, 0x61, 0x72, 0x74,
+0x3b, 0x41, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x130, 0x79, 0x75, 0x6e, 0x3b, 0x130, 0x79, 0x75, 0x6c,
+0x3b, 0x41, 0x76, 0x71, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x6e, 0x74, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x4f, 0x6b, 0x74,
+0x79, 0x61, 0x62, 0x72, 0x3b, 0x4e, 0x6f, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x44, 0x65, 0x6b, 0x61, 0x62, 0x72, 0x3b, 0x79,
+0x61, 0x6e, 0x76, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x76, 0x72, 0x61, 0x6c, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70,
+0x72, 0x65, 0x6c, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x69, 0x79, 0x75, 0x6e, 0x3b, 0x69, 0x79, 0x75, 0x6c, 0x3b, 0x61, 0x76,
+0x71, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x6e, 0x74, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x79, 0x61, 0x62,
+0x72, 0x3b, 0x6e, 0x6f, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x64, 0x65, 0x6b, 0x61, 0x62, 0x72, 0x3b, 0x458, 0x430, 0x43d, 0x3b,
+0x444, 0x435, 0x432, 0x3b, 0x43c, 0x430, 0x440, 0x3b, 0x430, 0x43f, 0x440, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x458, 0x43d, 0x3b,
+0x438, 0x458, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x3b, 0x441, 0x435, 0x43d, 0x3b, 0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x458, 0x3b,
+0x434, 0x435, 0x43a, 0x3b, 0x408, 0x430, 0x43d, 0x432, 0x430, 0x440, 0x3b, 0x424, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x3b, 0x41c, 0x430,
+0x440, 0x442, 0x3b, 0x410, 0x43f, 0x440, 0x435, 0x43b, 0x3b, 0x41c, 0x430, 0x439, 0x3b, 0x418, 0x458, 0x443, 0x43d, 0x3b, 0x418, 0x458,
+0x443, 0x43b, 0x3b, 0x410, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x421, 0x435, 0x43d, 0x442, 0x458, 0x430, 0x431, 0x440, 0x3b, 0x41e,
+0x43a, 0x442, 0x458, 0x430, 0x431, 0x440, 0x3b, 0x41d, 0x43e, 0x458, 0x430, 0x431, 0x440, 0x3b, 0x414, 0x435, 0x43a, 0x430, 0x431, 0x440,
+0x3b, 0x458, 0x430, 0x43d, 0x432, 0x430, 0x440, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b,
+0x430, 0x43f, 0x440, 0x435, 0x43b, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x458, 0x443, 0x43d, 0x3b, 0x438, 0x458, 0x443, 0x43b, 0x3b,
+0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x458, 0x430, 0x431, 0x440, 0x3b, 0x43e, 0x43a, 0x442, 0x458,
+0x430, 0x431, 0x440, 0x3b, 0x43d, 0x43e, 0x458, 0x430, 0x431, 0x440, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x3b, 0x75, 0x72,
+0x74, 0x2e, 0x3b, 0x6f, 0x74, 0x73, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x69, 0x2e, 0x3b, 0x6d, 0x61,
+0x69, 0x2e, 0x3b, 0x65, 0x6b, 0x61, 0x2e, 0x3b, 0x75, 0x7a, 0x74, 0x2e, 0x3b, 0x61, 0x62, 0x75, 0x2e, 0x3b, 0x69, 0x72,
+0x61, 0x2e, 0x3b, 0x75, 0x72, 0x72, 0x2e, 0x3b, 0x61, 0x7a, 0x61, 0x2e, 0x3b, 0x61, 0x62, 0x65, 0x2e, 0x3b, 0x75, 0x72,
+0x74, 0x61, 0x72, 0x72, 0x69, 0x6c, 0x61, 0x3b, 0x6f, 0x74, 0x73, 0x61, 0x69, 0x6c, 0x61, 0x3b, 0x6d, 0x61, 0x72, 0x74,
+0x78, 0x6f, 0x61, 0x3b, 0x61, 0x70, 0x69, 0x72, 0x69, 0x6c, 0x61, 0x3b, 0x6d, 0x61, 0x69, 0x61, 0x74, 0x7a, 0x61, 0x3b,
+0x65, 0x6b, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x75, 0x7a, 0x74, 0x61, 0x69, 0x6c, 0x61, 0x3b, 0x61, 0x62, 0x75, 0x7a, 0x74,
+0x75, 0x61, 0x3b, 0x69, 0x72, 0x61, 0x69, 0x6c, 0x61, 0x3b, 0x75, 0x72, 0x72, 0x69, 0x61, 0x3b, 0x61, 0x7a, 0x61, 0x72,
+0x6f, 0x61, 0x3b, 0x61, 0x62, 0x65, 0x6e, 0x64, 0x75, 0x61, 0x3b, 0x55, 0x3b, 0x4f, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d,
+0x3b, 0x45, 0x3b, 0x55, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x55, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x99c, 0x9be, 0x9a8, 0x9c1, 0x9af,
+0x9bc, 0x9be, 0x9b0, 0x9c0, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x9cd, 0x9b0, 0x9c1, 0x9af, 0x9bc, 0x9be, 0x9b0, 0x9c0, 0x3b, 0x9ae, 0x9be, 0x9b0,
+0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9b0, 0x9bf, 0x9b2, 0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2,
+0x9be, 0x987, 0x3b, 0x986, 0x997, 0x9b8, 0x9cd, 0x99f, 0x3b, 0x9b8, 0x9c7, 0x9aa, 0x9cd, 0x99f, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b,
+0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x9ac, 0x9b0, 0x3b, 0x9a8, 0x9ad, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x9a1, 0x9bf, 0x9b8, 0x9c7,
+0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x99c, 0x9be, 0x3b, 0x9ab, 0x9c7, 0x3b, 0x9ae, 0x9be, 0x3b, 0x98f, 0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c,
+0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x3b, 0x986, 0x3b, 0x9b8, 0x9c7, 0x3b, 0x985, 0x3b, 0x9a8, 0x3b, 0x9a1, 0x9bf, 0x3b, 0x99c, 0x9be,
+0x9a8, 0x9c1, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x3b, 0x9ae, 0x9be, 0x9b0, 0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9b0, 0x9bf, 0x9b2, 0x3b,
+0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be, 0x987, 0x3b, 0x986, 0x997, 0x9b8, 0x9cd, 0x99f, 0x3b, 0x9b8,
+0x9c7, 0x9aa, 0x9cd, 0x99f, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x9ac, 0x9b0, 0x3b, 0x9a8, 0x9ad,
+0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x9a1, 0x9bf, 0x9b8, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf21, 0x3b,
+0xf5f, 0xfb3, 0xf0b, 0xf22, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf23, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf24, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf25, 0x3b,
+0xf5f, 0xfb3, 0xf0b, 0xf26, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf27, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf28, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf29, 0x3b,
+0xf5f, 0xfb3, 0xf0b, 0xf21, 0xf20, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf21, 0xf21, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf21, 0xf22, 0x3b, 0xf66, 0xfa4,
+0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xf44, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf42,
+0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf42, 0xf66, 0xf74, 0xf58, 0xf0b,
+0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b, 0xf54, 0x3b, 0xf66, 0xfa4, 0xfb1,
+0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf63, 0xf94, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf51,
+0xfb2, 0xf74, 0xf42, 0xf0b, 0xf54, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf51, 0xf74, 0xf53, 0xf0b, 0xf54,
+0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1, 0xf51, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66,
+0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xf42, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f,
+0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74,
+0xf0b, 0xf42, 0xf45, 0xf72, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74,
+0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf21, 0x3b, 0xf22, 0x3b, 0xf23, 0x3b, 0xf24, 0x3b, 0xf25, 0x3b, 0xf26,
+0x3b, 0xf27, 0x3b, 0xf28, 0x3b, 0xf29, 0x3b, 0xf21, 0xf20, 0x3b, 0xf21, 0xf21, 0x3b, 0xf21, 0xf22, 0x3b, 0xf21, 0x3b, 0xf22, 0x3b,
+0xf23, 0x3b, 0xf24, 0x3b, 0xf25, 0x3b, 0xf26, 0x3b, 0xf27, 0x3b, 0xf28, 0x3b, 0xf29, 0x3b, 0xf21, 0xf20, 0x3b, 0xf21, 0xf21, 0x3b,
+0x31, 0x32, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xf44, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54,
+0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf42, 0xf66, 0xf74, 0xf58, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b,
+0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf63, 0xf94, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xfb2, 0xf74, 0xf42, 0xf0b,
+0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf51, 0xf74, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1,
+0xf51, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xf42, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45,
+0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf45, 0xf72, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b,
+0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf21, 0x3b, 0xf22, 0x3b, 0xf23,
+0x3b, 0x34, 0x3b, 0xf25, 0x3b, 0xf26, 0x3b, 0xf27, 0x3b, 0xf28, 0x3b, 0x39, 0x3b, 0xf21, 0xf20, 0x3b, 0xf21, 0xf21, 0x3b, 0xf21,
+0xf22, 0x3b, 0x47, 0x65, 0x6e, 0x2e, 0x3b, 0x43, 0x2bc, 0x68, 0x77, 0x65, 0x2e, 0x3b, 0x4d, 0x65, 0x75, 0x72, 0x2e, 0x3b,
+0x45, 0x62, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x65, 0x3b, 0x4d, 0x65, 0x7a, 0x68, 0x2e, 0x3b, 0x47, 0x6f, 0x75, 0x65, 0x2e,
+0x3b, 0x45, 0x6f, 0x73, 0x74, 0x3b, 0x47, 0x77, 0x65, 0x6e, 0x2e, 0x3b, 0x48, 0x65, 0x72, 0x65, 0x3b, 0x44, 0x75, 0x3b,
+0x4b, 0x7a, 0x75, 0x2e, 0x3b, 0x47, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x3b, 0x43, 0x2bc, 0x68, 0x77, 0x65, 0x76, 0x72, 0x65,
+0x72, 0x3b, 0x4d, 0x65, 0x75, 0x72, 0x7a, 0x68, 0x3b, 0x45, 0x62, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x61, 0x65, 0x3b, 0x4d,
+0x65, 0x7a, 0x68, 0x65, 0x76, 0x65, 0x6e, 0x3b, 0x47, 0x6f, 0x75, 0x65, 0x72, 0x65, 0x3b, 0x45, 0x6f, 0x73, 0x74, 0x3b,
+0x47, 0x77, 0x65, 0x6e, 0x67, 0x6f, 0x6c, 0x6f, 0x3b, 0x48, 0x65, 0x72, 0x65, 0x3b, 0x44, 0x75, 0x3b, 0x4b, 0x65, 0x72,
+0x7a, 0x75, 0x3b, 0x30, 0x31, 0x3b, 0x30, 0x32, 0x3b, 0x30, 0x33, 0x3b, 0x30, 0x34, 0x3b, 0x30, 0x35, 0x3b, 0x30, 0x36,
+0x3b, 0x30, 0x37, 0x3b, 0x30, 0x38, 0x3b, 0x30, 0x39, 0x3b, 0x31, 0x30, 0x3b, 0x31, 0x31, 0x3b, 0x31, 0x32, 0x3b, 0x44f,
+0x43d, 0x443, 0x3b, 0x444, 0x435, 0x432, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x3b, 0x43c, 0x430, 0x439, 0x3b,
+0x44e, 0x43d, 0x438, 0x3b, 0x44e, 0x43b, 0x438, 0x3b, 0x430, 0x432, 0x433, 0x3b, 0x441, 0x435, 0x43f, 0x3b, 0x43e, 0x43a, 0x442, 0x3b,
+0x43d, 0x43e, 0x435, 0x3b, 0x434, 0x435, 0x43a, 0x3b, 0x44f, 0x43d, 0x443, 0x430, 0x440, 0x438, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x443,
+0x430, 0x440, 0x438, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x44e,
+0x43d, 0x438, 0x3b, 0x44e, 0x43b, 0x438, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x435, 0x43c,
+0x432, 0x440, 0x438, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x43d, 0x43e, 0x435, 0x43c, 0x432, 0x440, 0x438,
+0x3b, 0x434, 0x435, 0x43a, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x44f, 0x3b, 0x444, 0x3b, 0x43c, 0x3b, 0x430, 0x3b, 0x43c, 0x3b,
+0x44e, 0x3b, 0x44e, 0x3b, 0x430, 0x3b, 0x441, 0x3b, 0x43e, 0x3b, 0x43d, 0x3b, 0x434, 0x3b, 0x1007, 0x1014, 0x103a, 0x3b, 0x1016, 0x1031,
+0x3b, 0x1019, 0x1010, 0x103a, 0x3b, 0x1027, 0x3b, 0x1019, 0x1031, 0x3b, 0x1007, 0x103d, 0x1014, 0x103a, 0x3b, 0x1007, 0x1030, 0x3b, 0x1029, 0x3b,
+0x1005, 0x1000, 0x103a, 0x3b, 0x1021, 0x1031, 0x102c, 0x1000, 0x103a, 0x3b, 0x1014, 0x102d, 0x102f, 0x3b, 0x1012, 0x102e, 0x3b, 0x1007, 0x1014, 0x103a,
+0x1014, 0x101d, 0x102b, 0x101b, 0x102e, 0x3b, 0x1016, 0x1031, 0x1016, 0x1031, 0x102c, 0x103a, 0x101d, 0x102b, 0x101b, 0x102e, 0x3b, 0x1019, 0x1010, 0x103a,
+0x3b, 0x1027, 0x1015, 0x103c, 0x102e, 0x3b, 0x1019, 0x1031, 0x3b, 0x1007, 0x103d, 0x1014, 0x103a, 0x3b, 0x1007, 0x1030, 0x101c, 0x102d, 0x102f, 0x1004,
+0x103a, 0x3b, 0x1029, 0x1002, 0x102f, 0x1010, 0x103a, 0x3b, 0x1005, 0x1000, 0x103a, 0x1010, 0x1004, 0x103a, 0x1018, 0x102c, 0x3b, 0x1021, 0x1031, 0x102c,
+0x1000, 0x103a, 0x1010, 0x102d, 0x102f, 0x1018, 0x102c, 0x3b, 0x1014, 0x102d, 0x102f, 0x101d, 0x1004, 0x103a, 0x1018, 0x102c, 0x3b, 0x1012, 0x102e, 0x1007,
+0x1004, 0x103a, 0x1018, 0x102c, 0x3b, 0x1007, 0x3b, 0x1016, 0x3b, 0x1019, 0x3b, 0x1027, 0x3b, 0x1019, 0x3b, 0x1007, 0x3b, 0x1007, 0x3b, 0x1029,
+0x3b, 0x1005, 0x3b, 0x1021, 0x3b, 0x1014, 0x3b, 0x1012, 0x3b, 0x441, 0x442, 0x443, 0x3b, 0x43b, 0x44e, 0x442, 0x3b, 0x441, 0x430, 0x43a,
+0x3b, 0x43a, 0x440, 0x430, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x447, 0x44d, 0x440, 0x3b, 0x43b, 0x456, 0x43f, 0x3b, 0x436, 0x43d, 0x456,
+0x3b, 0x432, 0x435, 0x440, 0x3b, 0x43a, 0x430, 0x441, 0x3b, 0x43b, 0x456, 0x441, 0x3b, 0x441, 0x43d, 0x435, 0x3b, 0x441, 0x442, 0x443,
+0x434, 0x437, 0x435, 0x43d, 0x44c, 0x3b, 0x43b, 0x44e, 0x442, 0x44b, 0x3b, 0x441, 0x430, 0x43a, 0x430, 0x432, 0x456, 0x43a, 0x3b, 0x43a,
+0x440, 0x430, 0x441, 0x430, 0x432, 0x456, 0x43a, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x447, 0x44d, 0x440, 0x432, 0x435, 0x43d, 0x44c, 0x3b,
+0x43b, 0x456, 0x43f, 0x435, 0x43d, 0x44c, 0x3b, 0x436, 0x43d, 0x456, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x432, 0x435, 0x440, 0x430, 0x441,
+0x435, 0x43d, 0x44c, 0x3b, 0x43a, 0x430, 0x441, 0x442, 0x440, 0x44b, 0x447, 0x43d, 0x456, 0x43a, 0x3b, 0x43b, 0x456, 0x441, 0x442, 0x430,
+0x43f, 0x430, 0x434, 0x3b, 0x441, 0x43d, 0x435, 0x436, 0x430, 0x43d, 0x44c, 0x3b, 0x441, 0x3b, 0x43b, 0x3b, 0x441, 0x3b, 0x43a, 0x3b,
+0x43c, 0x3b, 0x447, 0x3b, 0x43b, 0x3b, 0x436, 0x3b, 0x432, 0x3b, 0x43a, 0x3b, 0x43b, 0x3b, 0x441, 0x3b, 0x441, 0x442, 0x443, 0x3b,
+0x43b, 0x44e, 0x442, 0x3b, 0x441, 0x430, 0x43a, 0x3b, 0x43a, 0x440, 0x430, 0x3b, 0x43c, 0x430, 0x44f, 0x3b, 0x447, 0x44d, 0x440, 0x3b,
+0x43b, 0x456, 0x43f, 0x3b, 0x436, 0x43d, 0x456, 0x3b, 0x432, 0x435, 0x440, 0x3b, 0x43a, 0x430, 0x441, 0x3b, 0x43b, 0x456, 0x441, 0x3b,
+0x441, 0x43d, 0x435, 0x3b, 0x441, 0x442, 0x443, 0x434, 0x437, 0x435, 0x43d, 0x44f, 0x3b, 0x43b, 0x44e, 0x442, 0x430, 0x433, 0x430, 0x3b,
+0x441, 0x430, 0x43a, 0x430, 0x432, 0x456, 0x43a, 0x430, 0x3b, 0x43a, 0x440, 0x430, 0x441, 0x430, 0x432, 0x456, 0x43a, 0x430, 0x3b, 0x43c,
+0x430, 0x44f, 0x3b, 0x447, 0x44d, 0x440, 0x432, 0x435, 0x43d, 0x44f, 0x3b, 0x43b, 0x456, 0x43f, 0x435, 0x43d, 0x44f, 0x3b, 0x436, 0x43d,
+0x456, 0x45e, 0x43d, 0x44f, 0x3b, 0x432, 0x435, 0x440, 0x430, 0x441, 0x43d, 0x44f, 0x3b, 0x43a, 0x430, 0x441, 0x442, 0x440, 0x44b, 0x447,
+0x43d, 0x456, 0x43a, 0x430, 0x3b, 0x43b, 0x456, 0x441, 0x442, 0x430, 0x43f, 0x430, 0x434, 0x430, 0x3b, 0x441, 0x43d, 0x435, 0x436, 0x43d,
+0x44f, 0x3b, 0x1798, 0x1780, 0x179a, 0x17b6, 0x3b, 0x1780, 0x17bb, 0x1798, 0x17d2, 0x1797, 0x17c8, 0x3b, 0x1798, 0x17b8, 0x1793, 0x17b6, 0x3b, 0x1798,
+0x17c1, 0x179f, 0x17b6, 0x3b, 0x17a7, 0x179f, 0x1797, 0x17b6, 0x3b, 0x1798, 0x17b7, 0x1790, 0x17bb, 0x1793, 0x17b6, 0x3b, 0x1780, 0x1780, 0x17d2, 0x1780,
+0x178a, 0x17b6, 0x3b, 0x179f, 0x17b8, 0x17a0, 0x17b6, 0x3b, 0x1780, 0x1789, 0x17d2, 0x1789, 0x17b6, 0x3b, 0x178f, 0x17bb, 0x179b, 0x17b6, 0x3b, 0x179c,
+0x17b7, 0x1785, 0x17d2, 0x1786, 0x17b7, 0x1780, 0x17b6, 0x3b, 0x1792, 0x17d2, 0x1793, 0x17bc, 0x3b, 0x1798, 0x3b, 0x1780, 0x3b, 0x1798, 0x3b, 0x1798,
+0x3b, 0x17a7, 0x3b, 0x1798, 0x3b, 0x1780, 0x3b, 0x179f, 0x3b, 0x1780, 0x3b, 0x178f, 0x3b, 0x179c, 0x3b, 0x1792, 0x3b, 0x67, 0x65, 0x6e,
+0x2e, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0xe7, 0x3b, 0x61, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61,
+0x69, 0x67, 0x3b, 0x6a, 0x75, 0x6e, 0x79, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x74,
+0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x73, 0x2e, 0x3b, 0x67, 0x65, 0x6e,
+0x65, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0xe7, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c,
+0x3b, 0x6d, 0x61, 0x69, 0x67, 0x3b, 0x6a, 0x75, 0x6e, 0x79, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6f, 0x6c, 0x3b, 0x61, 0x67,
+0x6f, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x75, 0x62, 0x72, 0x65,
+0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x47,
+0x4e, 0x3b, 0x46, 0x42, 0x3b, 0x4d, 0xc7, 0x3b, 0x41, 0x42, 0x3b, 0x4d, 0x47, 0x3b, 0x4a, 0x4e, 0x3b, 0x4a, 0x4c, 0x3b,
+0x41, 0x47, 0x3b, 0x53, 0x54, 0x3b, 0x4f, 0x43, 0x3b, 0x4e, 0x56, 0x3b, 0x44, 0x53, 0x3b, 0x64, 0x65, 0x20, 0x67, 0x65,
+0x6e, 0x2e, 0x3b, 0x64, 0x65, 0x20, 0x66, 0x65, 0x62, 0x72, 0x2e, 0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x72, 0xe7, 0x3b,
+0x64, 0x2019, 0x61, 0x62, 0x72, 0x2e, 0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x69, 0x67, 0x3b, 0x64, 0x65, 0x20, 0x6a, 0x75,
+0x6e, 0x79, 0x3b, 0x64, 0x65, 0x20, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x64, 0x2019, 0x61, 0x67, 0x2e, 0x3b, 0x64, 0x65, 0x20,
+0x73, 0x65, 0x74, 0x2e, 0x3b, 0x64, 0x2019, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x64, 0x65, 0x20, 0x6e, 0x6f, 0x76, 0x2e, 0x3b,
+0x64, 0x65, 0x20, 0x64, 0x65, 0x73, 0x2e, 0x3b, 0x64, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x20,
+0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x72, 0xe7, 0x3b, 0x64, 0x2019, 0x61, 0x62, 0x72,
+0x69, 0x6c, 0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x69, 0x67, 0x3b, 0x64, 0x65, 0x20, 0x6a, 0x75, 0x6e, 0x79, 0x3b, 0x64,
+0x65, 0x20, 0x6a, 0x75, 0x6c, 0x69, 0x6f, 0x6c, 0x3b, 0x64, 0x2019, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x3b, 0x64, 0x65, 0x20,
+0x73, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x2019, 0x6f, 0x63, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x64,
+0x65, 0x20, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x65, 0x20, 0x64, 0x65, 0x73, 0x65, 0x6d, 0x62,
+0x72, 0x65, 0x3b, 0x31, 0x6708, 0x3b, 0x32, 0x6708, 0x3b, 0x33, 0x6708, 0x3b, 0x34, 0x6708, 0x3b, 0x35, 0x6708, 0x3b, 0x36, 0x6708,
+0x3b, 0x37, 0x6708, 0x3b, 0x38, 0x6708, 0x3b, 0x39, 0x6708, 0x3b, 0x31, 0x30, 0x6708, 0x3b, 0x31, 0x31, 0x6708, 0x3b, 0x31, 0x32,
+0x6708, 0x3b, 0x4e00, 0x6708, 0x3b, 0x4e8c, 0x6708, 0x3b, 0x4e09, 0x6708, 0x3b, 0x56db, 0x6708, 0x3b, 0x4e94, 0x6708, 0x3b, 0x516d, 0x6708, 0x3b,
+0x4e03, 0x6708, 0x3b, 0x516b, 0x6708, 0x3b, 0x4e5d, 0x6708, 0x3b, 0x5341, 0x6708, 0x3b, 0x5341, 0x4e00, 0x6708, 0x3b, 0x5341, 0x4e8c, 0x6708, 0x3b,
+0x73, 0x69, 0x6a, 0x3b, 0x76, 0x65, 0x6c, 0x6a, 0x3b, 0x6f, 0x17e, 0x75, 0x3b, 0x74, 0x72, 0x61, 0x3b, 0x73, 0x76, 0x69,
+0x3b, 0x6c, 0x69, 0x70, 0x3b, 0x73, 0x72, 0x70, 0x3b, 0x6b, 0x6f, 0x6c, 0x3b, 0x72, 0x75, 0x6a, 0x3b, 0x6c, 0x69, 0x73,
+0x3b, 0x73, 0x74, 0x75, 0x3b, 0x70, 0x72, 0x6f, 0x3b, 0x73, 0x69, 0x6a, 0x65, 0x10d, 0x61, 0x6e, 0x6a, 0x3b, 0x76, 0x65,
+0x6c, 0x6a, 0x61, 0x10d, 0x61, 0x3b, 0x6f, 0x17e, 0x75, 0x6a, 0x61, 0x6b, 0x3b, 0x74, 0x72, 0x61, 0x76, 0x61, 0x6e, 0x6a,
+0x3b, 0x73, 0x76, 0x69, 0x62, 0x61, 0x6e, 0x6a, 0x3b, 0x6c, 0x69, 0x70, 0x61, 0x6e, 0x6a, 0x3b, 0x73, 0x72, 0x70, 0x61,
+0x6e, 0x6a, 0x3b, 0x6b, 0x6f, 0x6c, 0x6f, 0x76, 0x6f, 0x7a, 0x3b, 0x72, 0x75, 0x6a, 0x61, 0x6e, 0x3b, 0x6c, 0x69, 0x73,
+0x74, 0x6f, 0x70, 0x61, 0x64, 0x3b, 0x73, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x69, 0x3b, 0x70, 0x72, 0x6f, 0x73, 0x69, 0x6e,
+0x61, 0x63, 0x3b, 0x31, 0x2e, 0x3b, 0x32, 0x2e, 0x3b, 0x33, 0x2e, 0x3b, 0x34, 0x2e, 0x3b, 0x35, 0x2e, 0x3b, 0x36, 0x2e,
+0x3b, 0x37, 0x2e, 0x3b, 0x38, 0x2e, 0x3b, 0x39, 0x2e, 0x3b, 0x31, 0x30, 0x2e, 0x3b, 0x31, 0x31, 0x2e, 0x3b, 0x31, 0x32,
+0x2e, 0x3b, 0x73, 0x69, 0x6a, 0x65, 0x10d, 0x6e, 0x6a, 0x61, 0x3b, 0x76, 0x65, 0x6c, 0x6a, 0x61, 0x10d, 0x65, 0x3b, 0x6f,
+0x17e, 0x75, 0x6a, 0x6b, 0x61, 0x3b, 0x74, 0x72, 0x61, 0x76, 0x6e, 0x6a, 0x61, 0x3b, 0x73, 0x76, 0x69, 0x62, 0x6e, 0x6a,
+0x61, 0x3b, 0x6c, 0x69, 0x70, 0x6e, 0x6a, 0x61, 0x3b, 0x73, 0x72, 0x70, 0x6e, 0x6a, 0x61, 0x3b, 0x6b, 0x6f, 0x6c, 0x6f,
+0x76, 0x6f, 0x7a, 0x61, 0x3b, 0x72, 0x75, 0x6a, 0x6e, 0x61, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x61,
+0x3b, 0x73, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x6f, 0x67, 0x61, 0x3b, 0x70, 0x72, 0x6f, 0x73, 0x69, 0x6e, 0x63, 0x61, 0x3b,
+0x6c, 0x65, 0x64, 0x3b, 0xfa, 0x6e, 0x6f, 0x3b, 0x62, 0x159, 0x65, 0x3b, 0x64, 0x75, 0x62, 0x3b, 0x6b, 0x76, 0x11b, 0x3b,
+0x10d, 0x76, 0x6e, 0x3b, 0x10d, 0x76, 0x63, 0x3b, 0x73, 0x72, 0x70, 0x3b, 0x7a, 0xe1, 0x159, 0x3b, 0x159, 0xed, 0x6a, 0x3b,
+0x6c, 0x69, 0x73, 0x3b, 0x70, 0x72, 0x6f, 0x3b, 0x6c, 0x65, 0x64, 0x65, 0x6e, 0x3b, 0xfa, 0x6e, 0x6f, 0x72, 0x3b, 0x62,
+0x159, 0x65, 0x7a, 0x65, 0x6e, 0x3b, 0x64, 0x75, 0x62, 0x65, 0x6e, 0x3b, 0x6b, 0x76, 0x11b, 0x74, 0x65, 0x6e, 0x3b, 0x10d,
+0x65, 0x72, 0x76, 0x65, 0x6e, 0x3b, 0x10d, 0x65, 0x72, 0x76, 0x65, 0x6e, 0x65, 0x63, 0x3b, 0x73, 0x72, 0x70, 0x65, 0x6e,
+0x3b, 0x7a, 0xe1, 0x159, 0xed, 0x3b, 0x159, 0xed, 0x6a, 0x65, 0x6e, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64,
+0x3b, 0x70, 0x72, 0x6f, 0x73, 0x69, 0x6e, 0x65, 0x63, 0x3b, 0x6c, 0x65, 0x64, 0x6e, 0x61, 0x3b, 0xfa, 0x6e, 0x6f, 0x72,
+0x61, 0x3b, 0x62, 0x159, 0x65, 0x7a, 0x6e, 0x61, 0x3b, 0x64, 0x75, 0x62, 0x6e, 0x61, 0x3b, 0x6b, 0x76, 0x11b, 0x74, 0x6e,
+0x61, 0x3b, 0x10d, 0x65, 0x72, 0x76, 0x6e, 0x61, 0x3b, 0x10d, 0x65, 0x72, 0x76, 0x65, 0x6e, 0x63, 0x65, 0x3b, 0x73, 0x72,
+0x70, 0x6e, 0x61, 0x3b, 0x7a, 0xe1, 0x159, 0xed, 0x3b, 0x159, 0xed, 0x6a, 0x6e, 0x61, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f,
+0x70, 0x61, 0x64, 0x75, 0x3b, 0x70, 0x72, 0x6f, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66,
+0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75,
+0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b,
+0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b,
+0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b,
+0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74,
+0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e,
+0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6a, 0x61, 0x6e,
+0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x72, 0x74, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x65, 0x69,
+0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e,
+0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x75,
+0x61, 0x72, 0x69, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x6d, 0x61, 0x61, 0x72, 0x74, 0x3b, 0x61,
+0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x65, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61,
+0x75, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b,
+0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d,
+0x62, 0x65, 0x72, 0x3b, 0x4a, 0x61, 0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0x61, 0x72, 0x2e, 0x3b, 0x41,
+0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x4a, 0x75, 0x6e, 0x2e, 0x3b, 0x4a, 0x75, 0x6c, 0x2e, 0x3b, 0x41, 0x75,
+0x67, 0x2e, 0x3b, 0x53, 0x65, 0x70, 0x2e, 0x3b, 0x4f, 0x63, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65,
+0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d,
+0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x16d, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f,
+0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x6f, 0x3b, 0x66,
+0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x6f, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x6f,
+0x3b, 0x6d, 0x61, 0x6a, 0x6f, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6f, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6f, 0x3b, 0x61, 0x16d,
+0x67, 0x75, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x6f, 0x6b, 0x74, 0x6f,
+0x62, 0x72, 0x6f, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72,
+0x6f, 0x3b, 0x6a, 0x61, 0x61, 0x6e, 0x3b, 0x76, 0x65, 0x65, 0x62, 0x72, 0x3b, 0x6d, 0xe4, 0x72, 0x74, 0x73, 0x3b, 0x61,
+0x70, 0x72, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6c, 0x69, 0x3b, 0x61,
+0x75, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x74, 0x73,
+0x3b, 0x6a, 0x61, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x76, 0x65, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0xe4,
+0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6e, 0x69,
+0x3b, 0x6a, 0x75, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d,
+0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65,
+0x72, 0x3b, 0x64, 0x65, 0x74, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x4d, 0x3b, 0x41, 0x3b,
+0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x6a, 0x61, 0x6e, 0x3b,
+0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x3b,
+0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x75, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b,
+0x64, 0x65, 0x73, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d,
+0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0xed, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a,
+0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72,
+0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65,
+0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72,
+0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e,
+0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e,
+0x3b, 0x64, 0x65, 0x73, 0x2e, 0x3b, 0x74, 0x61, 0x6d, 0x6d, 0x69, 0x3b, 0x68, 0x65, 0x6c, 0x6d, 0x69, 0x3b, 0x6d, 0x61,
+0x61, 0x6c, 0x69, 0x73, 0x3b, 0x68, 0x75, 0x68, 0x74, 0x69, 0x3b, 0x74, 0x6f, 0x75, 0x6b, 0x6f, 0x3b, 0x6b, 0x65, 0x73,
+0xe4, 0x3b, 0x68, 0x65, 0x69, 0x6e, 0xe4, 0x3b, 0x65, 0x6c, 0x6f, 0x3b, 0x73, 0x79, 0x79, 0x73, 0x3b, 0x6c, 0x6f, 0x6b,
+0x61, 0x3b, 0x6d, 0x61, 0x72, 0x72, 0x61, 0x73, 0x3b, 0x6a, 0x6f, 0x75, 0x6c, 0x75, 0x3b, 0x74, 0x61, 0x6d, 0x6d, 0x69,
+0x6b, 0x75, 0x75, 0x3b, 0x68, 0x65, 0x6c, 0x6d, 0x69, 0x6b, 0x75, 0x75, 0x3b, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x73, 0x6b,
+0x75, 0x75, 0x3b, 0x68, 0x75, 0x68, 0x74, 0x69, 0x6b, 0x75, 0x75, 0x3b, 0x74, 0x6f, 0x75, 0x6b, 0x6f, 0x6b, 0x75, 0x75,
+0x3b, 0x6b, 0x65, 0x73, 0xe4, 0x6b, 0x75, 0x75, 0x3b, 0x68, 0x65, 0x69, 0x6e, 0xe4, 0x6b, 0x75, 0x75, 0x3b, 0x65, 0x6c,
+0x6f, 0x6b, 0x75, 0x75, 0x3b, 0x73, 0x79, 0x79, 0x73, 0x6b, 0x75, 0x75, 0x3b, 0x6c, 0x6f, 0x6b, 0x61, 0x6b, 0x75, 0x75,
+0x3b, 0x6d, 0x61, 0x72, 0x72, 0x61, 0x73, 0x6b, 0x75, 0x75, 0x3b, 0x6a, 0x6f, 0x75, 0x6c, 0x75, 0x6b, 0x75, 0x75, 0x3b,
+0x54, 0x3b, 0x48, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x48, 0x3b, 0x45, 0x3b, 0x53, 0x3b, 0x4c, 0x3b,
+0x4d, 0x3b, 0x4a, 0x3b, 0x74, 0x61, 0x6d, 0x6d, 0x69, 0x6b, 0x2e, 0x3b, 0x68, 0x65, 0x6c, 0x6d, 0x69, 0x6b, 0x2e, 0x3b,
+0x6d, 0x61, 0x61, 0x6c, 0x69, 0x73, 0x6b, 0x2e, 0x3b, 0x68, 0x75, 0x68, 0x74, 0x69, 0x6b, 0x2e, 0x3b, 0x74, 0x6f, 0x75,
+0x6b, 0x6f, 0x6b, 0x2e, 0x3b, 0x6b, 0x65, 0x73, 0xe4, 0x6b, 0x2e, 0x3b, 0x68, 0x65, 0x69, 0x6e, 0xe4, 0x6b, 0x2e, 0x3b,
+0x65, 0x6c, 0x6f, 0x6b, 0x2e, 0x3b, 0x73, 0x79, 0x79, 0x73, 0x6b, 0x2e, 0x3b, 0x6c, 0x6f, 0x6b, 0x61, 0x6b, 0x2e, 0x3b,
+0x6d, 0x61, 0x72, 0x72, 0x61, 0x73, 0x6b, 0x2e, 0x3b, 0x6a, 0x6f, 0x75, 0x6c, 0x75, 0x6b, 0x2e, 0x3b, 0x74, 0x61, 0x6d,
+0x6d, 0x69, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x68, 0x65, 0x6c, 0x6d, 0x69, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6d,
+0x61, 0x61, 0x6c, 0x69, 0x73, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x68, 0x75, 0x68, 0x74, 0x69, 0x6b, 0x75, 0x75, 0x74,
+0x61, 0x3b, 0x74, 0x6f, 0x75, 0x6b, 0x6f, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6b, 0x65, 0x73, 0xe4, 0x6b, 0x75, 0x75,
+0x74, 0x61, 0x3b, 0x68, 0x65, 0x69, 0x6e, 0xe4, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x65, 0x6c, 0x6f, 0x6b, 0x75, 0x75,
+0x74, 0x61, 0x3b, 0x73, 0x79, 0x79, 0x73, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6c, 0x6f, 0x6b, 0x61, 0x6b, 0x75, 0x75,
+0x74, 0x61, 0x3b, 0x6d, 0x61, 0x72, 0x72, 0x61, 0x73, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6a, 0x6f, 0x75, 0x6c, 0x75,
+0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6a, 0x61, 0x6e, 0x76, 0x2e, 0x3b, 0x66, 0xe9, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61,
+0x72, 0x73, 0x3b, 0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x69, 0x6e, 0x3b, 0x6a, 0x75, 0x69,
+0x6c, 0x2e, 0x3b, 0x61, 0x6f, 0xfb, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e,
+0x6f, 0x76, 0x2e, 0x3b, 0x64, 0xe9, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x76, 0x69, 0x65, 0x72, 0x3b, 0x66, 0xe9, 0x76,
+0x72, 0x69, 0x65, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x76, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x3b,
+0x6a, 0x75, 0x69, 0x6e, 0x3b, 0x6a, 0x75, 0x69, 0x6c, 0x6c, 0x65, 0x74, 0x3b, 0x61, 0x6f, 0xfb, 0x74, 0x3b, 0x73, 0x65,
+0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x65,
+0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0xe9, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6a, 0x61, 0x6e, 0x76, 0x2e, 0x3b,
+0x66, 0xe9, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b,
+0x6a, 0x75, 0x69, 0x6e, 0x3b, 0x6a, 0x75, 0x69, 0x6c, 0x6c, 0x2e, 0x3b, 0x61, 0x6f, 0xfb, 0x74, 0x3b, 0x73, 0x65, 0x70,
+0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0xe9, 0x63, 0x2e, 0x3b, 0x6a, 0x61,
+0x6e, 0x2e, 0x3b, 0x66, 0xe9, 0x76, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61,
+0x69, 0x3b, 0x6a, 0x75, 0x69, 0x2e, 0x3b, 0x6a, 0x75, 0x69, 0x6c, 0x2e, 0x3b, 0x61, 0x6f, 0xfb, 0x74, 0x3b, 0x73, 0x65,
+0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0xe9, 0x63, 0x2e, 0x3b, 0x4a,
+0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x72, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a,
+0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e,
+0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x6e, 0x65, 0x77, 0x61, 0x72, 0x69, 0x73, 0x3b, 0x46, 0x65,
+0x62, 0x72, 0x65, 0x77, 0x61, 0x72, 0x69, 0x73, 0x3b, 0x4d, 0x61, 0x61, 0x72, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c,
+0x3b, 0x4d, 0x61, 0x61, 0x69, 0x65, 0x3b, 0x4a, 0x75, 0x6e, 0x79, 0x3b, 0x4a, 0x75, 0x6c, 0x79, 0x3b, 0x41, 0x75, 0x67,
+0x75, 0x73, 0x74, 0x75, 0x73, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x69, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f,
+0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x69, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x73, 0x69, 0x6d, 0x62, 0x65,
+0x72, 0x3b, 0x46, 0x61, 0x6f, 0x69, 0x3b, 0x47, 0x65, 0x61, 0x72, 0x72, 0x3b, 0x4d, 0xe0, 0x72, 0x74, 0x3b, 0x47, 0x69,
+0x62, 0x6c, 0x3b, 0x43, 0xe8, 0x69, 0x74, 0x3b, 0xd2, 0x67, 0x6d, 0x68, 0x3b, 0x49, 0x75, 0x63, 0x68, 0x3b, 0x4c, 0xf9,
+0x6e, 0x61, 0x3b, 0x53, 0x75, 0x6c, 0x74, 0x3b, 0x44, 0xe0, 0x6d, 0x68, 0x3b, 0x53, 0x61, 0x6d, 0x68, 0x3b, 0x44, 0xf9,
+0x62, 0x68, 0x3b, 0x41, 0x6d, 0x20, 0x46, 0x61, 0x6f, 0x69, 0x6c, 0x6c, 0x65, 0x61, 0x63, 0x68, 0x3b, 0x41, 0x6e, 0x20,
+0x47, 0x65, 0x61, 0x72, 0x72, 0x61, 0x6e, 0x3b, 0x41, 0x6d, 0x20, 0x4d, 0xe0, 0x72, 0x74, 0x3b, 0x41, 0x6e, 0x20, 0x47,
+0x69, 0x62, 0x6c, 0x65, 0x61, 0x6e, 0x3b, 0x41, 0x6e, 0x20, 0x43, 0xe8, 0x69, 0x74, 0x65, 0x61, 0x6e, 0x3b, 0x41, 0x6e,
+0x20, 0x74, 0x2d, 0xd2, 0x67, 0x6d, 0x68, 0x69, 0x6f, 0x73, 0x3b, 0x41, 0x6e, 0x20, 0x74, 0x2d, 0x49, 0x75, 0x63, 0x68,
+0x61, 0x72, 0x3b, 0x41, 0x6e, 0x20, 0x4c, 0xf9, 0x6e, 0x61, 0x73, 0x74, 0x61, 0x6c, 0x3b, 0x41, 0x6e, 0x20, 0x74, 0x2d,
+0x53, 0x75, 0x6c, 0x74, 0x61, 0x69, 0x6e, 0x3b, 0x41, 0x6e, 0x20, 0x44, 0xe0, 0x6d, 0x68, 0x61, 0x69, 0x72, 0x3b, 0x41,
+0x6e, 0x20, 0x74, 0x2d, 0x53, 0x61, 0x6d, 0x68, 0x61, 0x69, 0x6e, 0x3b, 0x41, 0x6e, 0x20, 0x44, 0xf9, 0x62, 0x68, 0x6c,
+0x61, 0x63, 0x68, 0x64, 0x3b, 0x46, 0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x43, 0x3b, 0xd2, 0x3b, 0x49, 0x3b, 0x4c,
+0x3b, 0x53, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x44, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x46, 0x68, 0x61, 0x6f, 0x69, 0x6c,
+0x6c, 0x65, 0x61, 0x63, 0x68, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x47, 0x68, 0x65, 0x61, 0x72, 0x72, 0x61, 0x6e, 0x3b,
+0x64, 0x68, 0x65, 0x6e, 0x20, 0x4d, 0x68, 0xe0, 0x72, 0x74, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x47, 0x68, 0x69, 0x62,
+0x6c, 0x65, 0x61, 0x6e, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x43, 0x68, 0xe8, 0x69, 0x74, 0x65, 0x61, 0x6e, 0x3b, 0x64,
+0x68, 0x65, 0x6e, 0x20, 0xd2, 0x67, 0x6d, 0x68, 0x69, 0x6f, 0x73, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x49, 0x75, 0x63,
+0x68, 0x61, 0x72, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x4c, 0xf9, 0x6e, 0x61, 0x73, 0x74, 0x61, 0x6c, 0x3b, 0x64, 0x68,
+0x65, 0x6e, 0x20, 0x74, 0x2d, 0x53, 0x75, 0x6c, 0x74, 0x61, 0x69, 0x6e, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x44, 0xe0,
+0x6d, 0x68, 0x61, 0x69, 0x72, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x2d, 0x53, 0x61, 0x6d, 0x68, 0x61, 0x69, 0x6e,
+0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x44, 0xf9, 0x62, 0x68, 0x6c, 0x61, 0x63, 0x68, 0x64, 0x3b, 0x58, 0x61, 0x6e, 0x2e,
+0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0x61, 0x72, 0x2e, 0x3b, 0x41, 0x62, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x69, 0x6f,
+0x3b, 0x58, 0x75, 0xf1, 0x6f, 0x3b, 0x58, 0x75, 0x6c, 0x2e, 0x3b, 0x41, 0x67, 0x6f, 0x2e, 0x3b, 0x53, 0x65, 0x74, 0x2e,
+0x3b, 0x4f, 0x75, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x63, 0x2e, 0x3b, 0x58, 0x61, 0x6e, 0x65,
+0x69, 0x72, 0x6f, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x41,
+0x62, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x6f, 0x3b, 0x58, 0x75, 0xf1, 0x6f, 0x3b, 0x58, 0x75, 0x6c, 0x6c, 0x6f,
+0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x4f, 0x75, 0x74,
+0x75, 0x62, 0x72, 0x6f, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x44, 0x65, 0x63, 0x65, 0x6d, 0x62,
+0x72, 0x6f, 0x3b, 0x58, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x58, 0x3b, 0x58, 0x3b, 0x41, 0x3b, 0x53,
+0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x78, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72,
+0x2e, 0x3b, 0x61, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x6f, 0x3b, 0x78, 0x75, 0xf1, 0x6f, 0x3b, 0x78, 0x75, 0x6c,
+0x2e, 0x3b, 0x61, 0x67, 0x6f, 0x2e, 0x3b, 0x73, 0x65, 0x74, 0x2e, 0x3b, 0x6f, 0x75, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76,
+0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x78, 0x61, 0x6e, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x65,
+0x69, 0x72, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x6f,
+0x3b, 0x78, 0x75, 0xf1, 0x6f, 0x3b, 0x78, 0x75, 0x6c, 0x6c, 0x6f, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x73,
+0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x6f, 0x75, 0x74, 0x75, 0x62, 0x72, 0x6f, 0x3b, 0x6e, 0x6f, 0x76, 0x65,
+0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x78, 0x2e, 0x3b, 0x66, 0x2e, 0x3b,
+0x6d, 0x2e, 0x3b, 0x61, 0x2e, 0x3b, 0x6d, 0x2e, 0x3b, 0x78, 0x2e, 0x3b, 0x78, 0x2e, 0x3b, 0x61, 0x2e, 0x3b, 0x73, 0x2e,
+0x3b, 0x6f, 0x2e, 0x3b, 0x6e, 0x2e, 0x3b, 0x64, 0x2e, 0x3b, 0x10d8, 0x10d0, 0x10dc, 0x3b, 0x10d7, 0x10d4, 0x10d1, 0x3b, 0x10db, 0x10d0,
+0x10e0, 0x3b, 0x10d0, 0x10de, 0x10e0, 0x3b, 0x10db, 0x10d0, 0x10d8, 0x3b, 0x10d8, 0x10d5, 0x10dc, 0x3b, 0x10d8, 0x10d5, 0x10da, 0x3b, 0x10d0, 0x10d2,
+0x10d5, 0x3b, 0x10e1, 0x10d4, 0x10e5, 0x3b, 0x10dd, 0x10e5, 0x10e2, 0x3b, 0x10dc, 0x10dd, 0x10d4, 0x3b, 0x10d3, 0x10d4, 0x10d9, 0x3b, 0x10d8, 0x10d0,
+0x10dc, 0x10d5, 0x10d0, 0x10e0, 0x10d8, 0x3b, 0x10d7, 0x10d4, 0x10d1, 0x10d4, 0x10e0, 0x10d5, 0x10d0, 0x10da, 0x10d8, 0x3b, 0x10db, 0x10d0, 0x10e0, 0x10e2,
+0x10d8, 0x3b, 0x10d0, 0x10de, 0x10e0, 0x10d8, 0x10da, 0x10d8, 0x3b, 0x10db, 0x10d0, 0x10d8, 0x10e1, 0x10d8, 0x3b, 0x10d8, 0x10d5, 0x10dc, 0x10d8, 0x10e1,
+0x10d8, 0x3b, 0x10d8, 0x10d5, 0x10da, 0x10d8, 0x10e1, 0x10d8, 0x3b, 0x10d0, 0x10d2, 0x10d5, 0x10d8, 0x10e1, 0x10e2, 0x10dd, 0x3b, 0x10e1, 0x10d4, 0x10e5,
+0x10e2, 0x10d4, 0x10db, 0x10d1, 0x10d4, 0x10e0, 0x10d8, 0x3b, 0x10dd, 0x10e5, 0x10e2, 0x10dd, 0x10db, 0x10d1, 0x10d4, 0x10e0, 0x10d8, 0x3b, 0x10dc, 0x10dd,
+0x10d4, 0x10db, 0x10d1, 0x10d4, 0x10e0, 0x10d8, 0x3b, 0x10d3, 0x10d4, 0x10d9, 0x10d4, 0x10db, 0x10d1, 0x10d4, 0x10e0, 0x10d8, 0x3b, 0x10d8, 0x3b, 0x10d7,
+0x3b, 0x10db, 0x3b, 0x10d0, 0x3b, 0x10db, 0x3b, 0x10d8, 0x3b, 0x10d8, 0x3b, 0x10d0, 0x3b, 0x10e1, 0x3b, 0x10dd, 0x3b, 0x10dc, 0x3b, 0x10d3,
+0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0xe4, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x69,
+0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74,
+0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x62, 0x72,
+0x75, 0x61, 0x72, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a,
+0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74,
+0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62,
+0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x61, 0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62,
+0x2e, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69,
+0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x4f, 0x6b, 0x74,
+0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x7a, 0x2e, 0x3b, 0x4a, 0xe4, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b,
+0x4d, 0xe4, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b,
+0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a, 0x3b,
+0x4a, 0xe4, 0x6e, 0x6e, 0x65, 0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b,
+0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b,
+0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74,
+0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0x65, 0x6d, 0x62,
+0x65, 0x72, 0x3b, 0x4a, 0xe4, 0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70,
+0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67,
+0x2e, 0x3b, 0x53, 0x65, 0x70, 0x2e, 0x3b, 0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x7a,
+0x2e, 0x3b, 0x399, 0x3b1, 0x3bd, 0x3b, 0x3a6, 0x3b5, 0x3b2, 0x3b, 0x39c, 0x3ac, 0x3c1, 0x3b, 0x391, 0x3c0, 0x3c1, 0x3b, 0x39c, 0x3ac,
+0x3b9, 0x3b, 0x399, 0x3bf, 0x3cd, 0x3bd, 0x3b, 0x399, 0x3bf, 0x3cd, 0x3bb, 0x3b, 0x391, 0x3cd, 0x3b3, 0x3b, 0x3a3, 0x3b5, 0x3c0, 0x3b,
+0x39f, 0x3ba, 0x3c4, 0x3b, 0x39d, 0x3bf, 0x3ad, 0x3b, 0x394, 0x3b5, 0x3ba, 0x3b, 0x399, 0x3b1, 0x3bd, 0x3bf, 0x3c5, 0x3ac, 0x3c1, 0x3b9,
+0x3bf, 0x3c2, 0x3b, 0x3a6, 0x3b5, 0x3b2, 0x3c1, 0x3bf, 0x3c5, 0x3ac, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x39c, 0x3ac, 0x3c1, 0x3c4, 0x3b9,
+0x3bf, 0x3c2, 0x3b, 0x391, 0x3c0, 0x3c1, 0x3af, 0x3bb, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x39c, 0x3ac, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x399, 0x3bf,
+0x3cd, 0x3bd, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x399, 0x3bf, 0x3cd, 0x3bb, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x391, 0x3cd, 0x3b3, 0x3bf, 0x3c5, 0x3c3,
+0x3c4, 0x3bf, 0x3c2, 0x3b, 0x3a3, 0x3b5, 0x3c0, 0x3c4, 0x3ad, 0x3bc, 0x3b2, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x39f, 0x3ba, 0x3c4, 0x3ce,
+0x3b2, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x39d, 0x3bf, 0x3ad, 0x3bc, 0x3b2, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x394, 0x3b5, 0x3ba, 0x3ad,
+0x3bc, 0x3b2, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x399, 0x3b, 0x3a6, 0x3b, 0x39c, 0x3b, 0x391, 0x3b, 0x39c, 0x3b, 0x399, 0x3b, 0x399,
+0x3b, 0x391, 0x3b, 0x3a3, 0x3b, 0x39f, 0x3b, 0x39d, 0x3b, 0x394, 0x3b, 0x399, 0x3b1, 0x3bd, 0x3b, 0x3a6, 0x3b5, 0x3b2, 0x3b, 0x39c,
+0x3b1, 0x3c1, 0x3b, 0x391, 0x3c0, 0x3c1, 0x3b, 0x39c, 0x3b1, 0x390, 0x3b, 0x399, 0x3bf, 0x3c5, 0x3bd, 0x3b, 0x399, 0x3bf, 0x3c5, 0x3bb,
+0x3b, 0x391, 0x3c5, 0x3b3, 0x3b, 0x3a3, 0x3b5, 0x3c0, 0x3b, 0x39f, 0x3ba, 0x3c4, 0x3b, 0x39d, 0x3bf, 0x3b5, 0x3b, 0x394, 0x3b5, 0x3ba,
+0x3b, 0x399, 0x3b1, 0x3bd, 0x3bf, 0x3c5, 0x3b1, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x3a6, 0x3b5, 0x3b2, 0x3c1, 0x3bf, 0x3c5, 0x3b1, 0x3c1,
+0x3af, 0x3bf, 0x3c5, 0x3b, 0x39c, 0x3b1, 0x3c1, 0x3c4, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x391, 0x3c0, 0x3c1, 0x3b9, 0x3bb, 0x3af, 0x3bf, 0x3c5,
+0x3b, 0x39c, 0x3b1, 0x390, 0x3bf, 0x3c5, 0x3b, 0x399, 0x3bf, 0x3c5, 0x3bd, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x399, 0x3bf, 0x3c5, 0x3bb, 0x3af,
+0x3bf, 0x3c5, 0x3b, 0x391, 0x3c5, 0x3b3, 0x3bf, 0x3cd, 0x3c3, 0x3c4, 0x3bf, 0x3c5, 0x3b, 0x3a3, 0x3b5, 0x3c0, 0x3c4, 0x3b5, 0x3bc, 0x3b2,
+0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x39f, 0x3ba, 0x3c4, 0x3c9, 0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x39d, 0x3bf, 0x3b5, 0x3bc, 0x3b2,
+0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x394, 0x3b5, 0x3ba, 0x3b5, 0x3bc, 0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x6a, 0x61, 0x6e, 0x3b,
+0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b,
+0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x75, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b,
+0x64, 0x65, 0x63, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69,
+0x3b, 0x6d, 0x61, 0x72, 0x74, 0x73, 0x69, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x69, 0x3b, 0x6d, 0x61, 0x6a, 0x69, 0x3b,
+0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73, 0x69, 0x3b,
+0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x69, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x69, 0x3b,
+0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x69, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x69, 0x3b,
+0xa9c, 0xabe, 0xaa8, 0xacd, 0xaaf, 0xac1, 0x3b, 0xaab, 0xac7, 0xaac, 0xacd, 0xab0, 0xac1, 0x3b, 0xaae, 0xabe, 0xab0, 0xacd, 0xa9a, 0x3b,
+0xa8f, 0xaaa, 0xacd, 0xab0, 0xabf, 0xab2, 0x3b, 0xaae, 0xac7, 0x3b, 0xa9c, 0xac2, 0xaa8, 0x3b, 0xa9c, 0xac1, 0xab2, 0xabe, 0xa88, 0x3b,
+0xa91, 0xa97, 0xab8, 0xacd, 0xa9f, 0x3b, 0xab8, 0xaaa, 0xacd, 0xa9f, 0xac7, 0x3b, 0xa91, 0xa95, 0xacd, 0xa9f, 0xacb, 0x3b, 0xaa8, 0xab5,
+0xac7, 0x3b, 0xaa1, 0xabf, 0xab8, 0xac7, 0x3b, 0xa9c, 0xabe, 0xaa8, 0xacd, 0xaaf, 0xac1, 0xa86, 0xab0, 0xac0, 0x3b, 0xaab, 0xac7, 0xaac,
+0xacd, 0xab0, 0xac1, 0xa86, 0xab0, 0xac0, 0x3b, 0xaae, 0xabe, 0xab0, 0xacd, 0xa9a, 0x3b, 0xa8f, 0xaaa, 0xacd, 0xab0, 0xabf, 0xab2, 0x3b,
+0xaae, 0xac7, 0x3b, 0xa9c, 0xac2, 0xaa8, 0x3b, 0xa9c, 0xac1, 0xab2, 0xabe, 0xa88, 0x3b, 0xa91, 0xa97, 0xab8, 0xacd, 0xa9f, 0x3b, 0xab8,
+0xaaa, 0xacd, 0xa9f, 0xac7, 0xaae, 0xacd, 0xaac, 0xab0, 0x3b, 0xa91, 0xa95, 0xacd, 0xa9f, 0xacb, 0xaac, 0xab0, 0x3b, 0xaa8, 0xab5, 0xac7,
+0xaae, 0xacd, 0xaac, 0xab0, 0x3b, 0xaa1, 0xabf, 0xab8, 0xac7, 0xaae, 0xacd, 0xaac, 0xab0, 0x3b, 0xa9c, 0xabe, 0x3b, 0xaab, 0xac7, 0x3b,
+0xaae, 0xabe, 0x3b, 0xa8f, 0x3b, 0xaae, 0xac7, 0x3b, 0xa9c, 0xac2, 0x3b, 0xa9c, 0xac1, 0x3b, 0xa91, 0x3b, 0xab8, 0x3b, 0xa91, 0x3b,
+0xaa8, 0x3b, 0xaa1, 0xabf, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x61, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x66, 0x69,
+0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x59, 0x75, 0x6e, 0x3b, 0x59, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x75, 0x3b, 0x53, 0x61, 0x74,
+0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x75, 0x77, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x61, 0x69, 0x72, 0x75,
+0x3b, 0x46, 0x61, 0x62, 0x75, 0x72, 0x61, 0x69, 0x72, 0x75, 0x3b, 0x4d, 0x61, 0x72, 0x69, 0x73, 0x3b, 0x41, 0x66, 0x69,
+0x72, 0x69, 0x6c, 0x75, 0x3b, 0x4d, 0x61, 0x79, 0x75, 0x3b, 0x59, 0x75, 0x6e, 0x69, 0x3b, 0x59, 0x75, 0x6c, 0x69, 0x3b,
+0x41, 0x67, 0x75, 0x73, 0x74, 0x61, 0x3b, 0x53, 0x61, 0x74, 0x75, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62,
+0x61, 0x3b, 0x4e, 0x75, 0x77, 0x61, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x61, 0x6d, 0x62, 0x61, 0x3b, 0x4a, 0x3b,
+0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b,
+0x44, 0x3b, 0x5d9, 0x5e0, 0x5d5, 0x5f3, 0x3b, 0x5e4, 0x5d1, 0x5e8, 0x5f3, 0x3b, 0x5de, 0x5e8, 0x5e5, 0x3b, 0x5d0, 0x5e4, 0x5e8, 0x5f3,
+0x3b, 0x5de, 0x5d0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dc, 0x5d9, 0x3b, 0x5d0, 0x5d5, 0x5d2, 0x5f3, 0x3b,
+0x5e1, 0x5e4, 0x5d8, 0x5f3, 0x3b, 0x5d0, 0x5d5, 0x5e7, 0x5f3, 0x3b, 0x5e0, 0x5d5, 0x5d1, 0x5f3, 0x3b, 0x5d3, 0x5e6, 0x5de, 0x5f3, 0x3b,
+0x5d9, 0x5e0, 0x5d5, 0x5d0, 0x5e8, 0x3b, 0x5e4, 0x5d1, 0x5e8, 0x5d5, 0x5d0, 0x5e8, 0x3b, 0x5de, 0x5e8, 0x5e5, 0x3b, 0x5d0, 0x5e4, 0x5e8,
+0x5d9, 0x5dc, 0x3b, 0x5de, 0x5d0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dc, 0x5d9, 0x3b, 0x5d0, 0x5d5, 0x5d2,
+0x5d5, 0x5e1, 0x5d8, 0x3b, 0x5e1, 0x5e4, 0x5d8, 0x5de, 0x5d1, 0x5e8, 0x3b, 0x5d0, 0x5d5, 0x5e7, 0x5d8, 0x5d5, 0x5d1, 0x5e8, 0x3b, 0x5e0,
+0x5d5, 0x5d1, 0x5de, 0x5d1, 0x5e8, 0x3b, 0x5d3, 0x5e6, 0x5de, 0x5d1, 0x5e8, 0x3b, 0x91c, 0x928, 0x970, 0x3b, 0x92b, 0x93c, 0x930, 0x970,
+0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x948, 0x932, 0x3b, 0x92e, 0x908, 0x3b, 0x91c, 0x942, 0x928,
+0x3b, 0x91c, 0x941, 0x932, 0x970, 0x3b, 0x905, 0x917, 0x970, 0x3b, 0x938, 0x93f, 0x924, 0x970, 0x3b, 0x905, 0x915, 0x94d, 0x924, 0x942,
+0x970, 0x3b, 0x928, 0x935, 0x970, 0x3b, 0x926, 0x93f, 0x938, 0x970, 0x3b, 0x91c, 0x928, 0x935, 0x930, 0x940, 0x3b, 0x92b, 0x93c, 0x930,
+0x935, 0x930, 0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x948, 0x932, 0x3b, 0x92e, 0x908, 0x3b,
+0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x908, 0x3b, 0x905, 0x917, 0x938, 0x94d, 0x924, 0x3b, 0x938, 0x93f, 0x924, 0x902,
+0x92c, 0x930, 0x3b, 0x905, 0x915, 0x94d, 0x924, 0x942, 0x92c, 0x930, 0x3b, 0x928, 0x935, 0x902, 0x92c, 0x930, 0x3b, 0x926, 0x93f, 0x938,
+0x902, 0x92c, 0x930, 0x3b, 0x91c, 0x3b, 0x92b, 0x93c, 0x3b, 0x92e, 0x93e, 0x3b, 0x905, 0x3b, 0x92e, 0x3b, 0x91c, 0x942, 0x3b, 0x91c,
+0x941, 0x3b, 0x905, 0x3b, 0x938, 0x93f, 0x3b, 0x905, 0x3b, 0x928, 0x3b, 0x926, 0x93f, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66,
+0x65, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0xe1, 0x72, 0x63, 0x2e, 0x3b, 0xe1, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0xe1, 0x6a, 0x2e,
+0x3b, 0x6a, 0xfa, 0x6e, 0x2e, 0x3b, 0x6a, 0xfa, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x7a, 0x65, 0x70,
+0x74, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61,
+0x6e, 0x75, 0xe1, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0xe1, 0x72, 0x3b, 0x6d, 0xe1, 0x72, 0x63, 0x69, 0x75, 0x73,
+0x3b, 0xe1, 0x70, 0x72, 0x69, 0x6c, 0x69, 0x73, 0x3b, 0x6d, 0xe1, 0x6a, 0x75, 0x73, 0x3b, 0x6a, 0xfa, 0x6e, 0x69, 0x75,
+0x73, 0x3b, 0x6a, 0xfa, 0x6c, 0x69, 0x75, 0x73, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x7a, 0x74, 0x75, 0x73, 0x3b, 0x73,
+0x7a, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0xf3, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f,
+0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x3b, 0x46, 0x3b,
+0x4d, 0x3b, 0xc1, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x7a, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44,
+0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e,
+0x3b, 0x6d, 0x61, 0xed, 0x3b, 0x6a, 0xfa, 0x6e, 0x2e, 0x3b, 0x6a, 0xfa, 0x6c, 0x2e, 0x3b, 0xe1, 0x67, 0xfa, 0x2e, 0x3b,
+0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0xf3, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x73, 0x2e, 0x3b,
+0x6a, 0x61, 0x6e, 0xfa, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0xfa, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b,
+0x61, 0x70, 0x72, 0xed, 0x6c, 0x3b, 0x6d, 0x61, 0xed, 0x3b, 0x6a, 0xfa, 0x6e, 0xed, 0x3b, 0x6a, 0xfa, 0x6c, 0xed, 0x3b,
+0xe1, 0x67, 0xfa, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0xf3,
+0x62, 0x65, 0x72, 0x3b, 0x6e, 0xf3, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x65,
+0x72, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0xc1, 0x3b, 0x53, 0x3b,
+0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70,
+0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x75, 0x3b, 0x53, 0x65,
+0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72,
+0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x72, 0x65, 0x74, 0x3b, 0x41, 0x70, 0x72,
+0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x67, 0x75,
+0x73, 0x74, 0x75, 0x73, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62,
+0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72,
+0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x69,
+0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x75, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x63, 0x74,
+0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x6f, 0x3b, 0x66, 0x65,
+0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x69, 0x6f, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c,
+0x3b, 0x6d, 0x61, 0x69, 0x6f, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6f, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6f, 0x3b, 0x61, 0x75,
+0x67, 0x75, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x6f,
+0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72,
+0x65, 0x3b, 0x6a, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x61, 0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x6a, 0x3b, 0x61, 0x3b, 0x73, 0x3b,
+0x6f, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 0x45, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x61, 0x62, 0x68, 0x3b, 0x4d, 0xe1, 0x72, 0x74,
+0x61, 0x3b, 0x41, 0x69, 0x62, 0x3b, 0x42, 0x65, 0x61, 0x6c, 0x3b, 0x4d, 0x65, 0x69, 0x74, 0x68, 0x3b, 0x49, 0xfa, 0x69,
+0x6c, 0x3b, 0x4c, 0xfa, 0x6e, 0x3b, 0x4d, 0x46, 0xf3, 0x6d, 0x68, 0x3b, 0x44, 0x46, 0xf3, 0x6d, 0x68, 0x3b, 0x53, 0x61,
+0x6d, 0x68, 0x3b, 0x4e, 0x6f, 0x6c, 0x6c, 0x3b, 0x45, 0x61, 0x6e, 0xe1, 0x69, 0x72, 0x3b, 0x46, 0x65, 0x61, 0x62, 0x68,
+0x72, 0x61, 0x3b, 0x4d, 0xe1, 0x72, 0x74, 0x61, 0x3b, 0x41, 0x69, 0x62, 0x72, 0x65, 0xe1, 0x6e, 0x3b, 0x42, 0x65, 0x61,
+0x6c, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x3b, 0x4d, 0x65, 0x69, 0x74, 0x68, 0x65, 0x61, 0x6d, 0x68, 0x3b, 0x49, 0xfa, 0x69,
+0x6c, 0x3b, 0x4c, 0xfa, 0x6e, 0x61, 0x73, 0x61, 0x3b, 0x4d, 0x65, 0xe1, 0x6e, 0x20, 0x46, 0xf3, 0x6d, 0x68, 0x61, 0x69,
+0x72, 0x3b, 0x44, 0x65, 0x69, 0x72, 0x65, 0x61, 0x64, 0x68, 0x20, 0x46, 0xf3, 0x6d, 0x68, 0x61, 0x69, 0x72, 0x3b, 0x53,
+0x61, 0x6d, 0x68, 0x61, 0x69, 0x6e, 0x3b, 0x4e, 0x6f, 0x6c, 0x6c, 0x61, 0x69, 0x67, 0x3b, 0x45, 0x3b, 0x46, 0x3b, 0x4d,
+0x3b, 0x41, 0x3b, 0x42, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x67,
+0x65, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x67, 0x3b, 0x67,
+0x69, 0x75, 0x3b, 0x6c, 0x75, 0x67, 0x3b, 0x61, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x3b, 0x6f, 0x74, 0x74, 0x3b, 0x6e,
+0x6f, 0x76, 0x3b, 0x64, 0x69, 0x63, 0x3b, 0x67, 0x65, 0x6e, 0x6e, 0x61, 0x69, 0x6f, 0x3b, 0x66, 0x65, 0x62, 0x62, 0x72,
+0x61, 0x69, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x65, 0x3b, 0x6d, 0x61, 0x67,
+0x67, 0x69, 0x6f, 0x3b, 0x67, 0x69, 0x75, 0x67, 0x6e, 0x6f, 0x3b, 0x6c, 0x75, 0x67, 0x6c, 0x69, 0x6f, 0x3b, 0x61, 0x67,
+0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x74, 0x74, 0x6f, 0x62,
+0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x69, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x65,
+0x3b, 0x47, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x4c, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f,
+0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72,
+0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x74, 0x3b, 0x53, 0x65, 0x70,
+0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x3b, 0xc9c, 0xca8, 0x3b, 0xcab, 0xcc6, 0xcac, 0xccd,
+0xcb0, 0x3b, 0xcae, 0xcbe, 0xcb0, 0xccd, 0xc9a, 0xccd, 0x3b, 0xc8f, 0xcaa, 0xccd, 0xcb0, 0xcbf, 0x3b, 0xcae, 0xcc7, 0x3b, 0xc9c, 0xcc2,
+0xca8, 0xccd, 0x3b, 0xc9c, 0xcc1, 0xcb2, 0xcc8, 0x3b, 0xc86, 0xc97, 0x3b, 0xcb8, 0xcc6, 0xcaa, 0xccd, 0xc9f, 0xcc6, 0xc82, 0x3b, 0xc85,
+0xc95, 0xccd, 0xc9f, 0xccb, 0x3b, 0xca8, 0xcb5, 0xcc6, 0xc82, 0x3b, 0xca1, 0xcbf, 0xcb8, 0xcc6, 0xc82, 0x3b, 0xc9c, 0xca8, 0xcb5, 0xcb0,
+0xcbf, 0x3b, 0xcab, 0xcc6, 0xcac, 0xccd, 0xcb0, 0xcb5, 0xcb0, 0xcbf, 0x3b, 0xcae, 0xcbe, 0xcb0, 0xccd, 0xc9a, 0xccd, 0x3b, 0xc8f, 0xcaa,
+0xccd, 0xcb0, 0xcbf, 0xcb2, 0xccd, 0x3b, 0xcae, 0xcc7, 0x3b, 0xc9c, 0xcc2, 0xca8, 0xccd, 0x3b, 0xc9c, 0xcc1, 0xcb2, 0xcc8, 0x3b, 0xc86,
+0xc97, 0xcb8, 0xccd, 0xc9f, 0xccd, 0x3b, 0xcb8, 0xcc6, 0xcaa, 0xccd, 0xc9f, 0xcc6, 0xc82, 0xcac, 0xcb0, 0xccd, 0x3b, 0xc85, 0xc95, 0xccd,
+0xc9f, 0xccb, 0xcac, 0xcb0, 0xccd, 0x3b, 0xca8, 0xcb5, 0xcc6, 0xc82, 0xcac, 0xcb0, 0xccd, 0x3b, 0xca1, 0xcbf, 0xcb8, 0xcc6, 0xc82, 0xcac,
+0xcb0, 0xccd, 0x3b, 0xc9c, 0x3b, 0xcab, 0xcc6, 0x3b, 0xcae, 0xcbe, 0x3b, 0xc8f, 0x3b, 0xcae, 0xcc7, 0x3b, 0xc9c, 0xcc2, 0x3b, 0xc9c,
+0xcc1, 0x3b, 0xc86, 0x3b, 0xcb8, 0xcc6, 0x3b, 0xc85, 0x3b, 0xca8, 0x3b, 0xca1, 0xcbf, 0x3b, 0xc9c, 0xca8, 0xcb5, 0xcb0, 0xcbf, 0x3b,
+0xcab, 0xcc6, 0xcac, 0xccd, 0xcb0, 0xcb5, 0xcb0, 0xcbf, 0x3b, 0xcae, 0xcbe, 0xcb0, 0xccd, 0xc9a, 0xccd, 0x3b, 0xc8f, 0xcaa, 0xccd, 0xcb0,
+0xcbf, 0x3b, 0xcae, 0xcc7, 0x3b, 0xc9c, 0xcc2, 0xca8, 0xccd, 0x3b, 0xc9c, 0xcc1, 0xcb2, 0xcc8, 0x3b, 0xc86, 0xc97, 0x3b, 0xcb8, 0xcc6,
+0xcaa, 0xccd, 0xc9f, 0xcc6, 0xc82, 0x3b, 0xc85, 0xc95, 0xccd, 0xc9f, 0xccb, 0x3b, 0xca8, 0xcb5, 0xcc6, 0xc82, 0x3b, 0xca1, 0xcbf, 0xcb8,
+0xcc6, 0xc82, 0x3b, 0x62c, 0x646, 0x624, 0x631, 0x6cc, 0x3b, 0x641, 0x631, 0x624, 0x631, 0x6cc, 0x3b, 0x645, 0x627, 0x631, 0x655, 0x686,
+0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cc, 0x654, 0x3b, 0x62c, 0x648, 0x657, 0x646, 0x3b, 0x62c, 0x648, 0x657, 0x644,
+0x627, 0x6cc, 0x6cc, 0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x657,
+0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x62c, 0x3b, 0x641, 0x3b, 0x645,
+0x3b, 0x627, 0x3b, 0x645, 0x3b, 0x62c, 0x3b, 0x62c, 0x3b, 0x627, 0x3b, 0x633, 0x3b, 0x633, 0x3b, 0x627, 0x3b, 0x646, 0x3b, 0x49b,
+0x430, 0x4a3, 0x2e, 0x3b, 0x430, 0x49b, 0x43f, 0x2e, 0x3b, 0x43d, 0x430, 0x443, 0x2e, 0x3b, 0x441, 0x4d9, 0x443, 0x2e, 0x3b, 0x43c,
+0x430, 0x43c, 0x2e, 0x3b, 0x43c, 0x430, 0x443, 0x2e, 0x3b, 0x448, 0x456, 0x43b, 0x2e, 0x3b, 0x442, 0x430, 0x43c, 0x2e, 0x3b, 0x49b,
+0x44b, 0x440, 0x2e, 0x3b, 0x49b, 0x430, 0x437, 0x2e, 0x3b, 0x49b, 0x430, 0x440, 0x2e, 0x3b, 0x436, 0x435, 0x43b, 0x2e, 0x3b, 0x49a,
+0x430, 0x4a3, 0x442, 0x430, 0x440, 0x3b, 0x410, 0x49b, 0x43f, 0x430, 0x43d, 0x3b, 0x41d, 0x430, 0x443, 0x440, 0x44b, 0x437, 0x3b, 0x421,
+0x4d9, 0x443, 0x456, 0x440, 0x3b, 0x41c, 0x430, 0x43c, 0x44b, 0x440, 0x3b, 0x41c, 0x430, 0x443, 0x441, 0x44b, 0x43c, 0x3b, 0x428, 0x456,
+0x43b, 0x434, 0x435, 0x3b, 0x422, 0x430, 0x43c, 0x44b, 0x437, 0x3b, 0x49a, 0x44b, 0x440, 0x43a, 0x4af, 0x439, 0x435, 0x43a, 0x3b, 0x49a,
+0x430, 0x437, 0x430, 0x43d, 0x3b, 0x49a, 0x430, 0x440, 0x430, 0x448, 0x430, 0x3b, 0x416, 0x435, 0x43b, 0x442, 0x43e, 0x49b, 0x441, 0x430,
+0x43d, 0x3b, 0x49a, 0x3b, 0x410, 0x3b, 0x41d, 0x3b, 0x421, 0x3b, 0x41c, 0x3b, 0x41c, 0x3b, 0x428, 0x3b, 0x422, 0x3b, 0x49a, 0x3b,
+0x49a, 0x3b, 0x49a, 0x3b, 0x416, 0x3b, 0x49b, 0x430, 0x4a3, 0x442, 0x430, 0x440, 0x3b, 0x430, 0x49b, 0x43f, 0x430, 0x43d, 0x3b, 0x43d,
+0x430, 0x443, 0x440, 0x44b, 0x437, 0x3b, 0x441, 0x4d9, 0x443, 0x456, 0x440, 0x3b, 0x43c, 0x430, 0x43c, 0x44b, 0x440, 0x3b, 0x43c, 0x430,
+0x443, 0x441, 0x44b, 0x43c, 0x3b, 0x448, 0x456, 0x43b, 0x434, 0x435, 0x3b, 0x442, 0x430, 0x43c, 0x44b, 0x437, 0x3b, 0x49b, 0x44b, 0x440,
+0x43a, 0x4af, 0x439, 0x435, 0x43a, 0x3b, 0x49b, 0x430, 0x437, 0x430, 0x43d, 0x3b, 0x49b, 0x430, 0x440, 0x430, 0x448, 0x430, 0x3b, 0x436,
+0x435, 0x43b, 0x442, 0x43e, 0x49b, 0x441, 0x430, 0x43d, 0x3b, 0x6d, 0x75, 0x74, 0x2e, 0x3b, 0x67, 0x61, 0x73, 0x2e, 0x3b, 0x77,
+0x65, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x74, 0x2e, 0x3b, 0x67, 0x69, 0x63, 0x2e, 0x3b, 0x6b, 0x61, 0x6d, 0x2e, 0x3b, 0x6e,
+0x79, 0x61, 0x2e, 0x3b, 0x6b, 0x61, 0x6e, 0x2e, 0x3b, 0x6e, 0x7a, 0x65, 0x2e, 0x3b, 0x75, 0x6b, 0x77, 0x2e, 0x3b, 0x75,
+0x67, 0x75, 0x2e, 0x3b, 0x75, 0x6b, 0x75, 0x2e, 0x3b, 0x4d, 0x75, 0x74, 0x61, 0x72, 0x61, 0x6d, 0x61, 0x3b, 0x47, 0x61,
+0x73, 0x68, 0x79, 0x61, 0x6e, 0x74, 0x61, 0x72, 0x65, 0x3b, 0x57, 0x65, 0x72, 0x75, 0x72, 0x77, 0x65, 0x3b, 0x4d, 0x61,
+0x74, 0x61, 0x3b, 0x47, 0x69, 0x63, 0x75, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x3b, 0x4b, 0x61, 0x6d, 0x65, 0x6e, 0x61, 0x3b,
+0x4e, 0x79, 0x61, 0x6b, 0x61, 0x6e, 0x67, 0x61, 0x3b, 0x4b, 0x61, 0x6e, 0x61, 0x6d, 0x61, 0x3b, 0x4e, 0x7a, 0x65, 0x6c,
+0x69, 0x3b, 0x55, 0x6b, 0x77, 0x61, 0x6b, 0x69, 0x72, 0x61, 0x3b, 0x55, 0x67, 0x75, 0x73, 0x68, 0x79, 0x69, 0x6e, 0x67,
+0x6f, 0x3b, 0x55, 0x6b, 0x75, 0x62, 0x6f, 0x7a, 0x61, 0x3b, 0x42f, 0x43d, 0x432, 0x3b, 0x424, 0x435, 0x432, 0x3b, 0x41c, 0x430,
+0x440, 0x3b, 0x410, 0x43f, 0x440, 0x3b, 0x41c, 0x430, 0x439, 0x3b, 0x418, 0x44e, 0x43d, 0x3b, 0x418, 0x44e, 0x43b, 0x3b, 0x410, 0x432,
+0x433, 0x3b, 0x421, 0x435, 0x43d, 0x3b, 0x41e, 0x43a, 0x442, 0x3b, 0x41d, 0x43e, 0x44f, 0x3b, 0x414, 0x435, 0x43a, 0x3b, 0x42f, 0x43d,
+0x432, 0x430, 0x440, 0x44c, 0x3b, 0x424, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x44c, 0x3b, 0x41c, 0x430, 0x440, 0x442, 0x3b, 0x410, 0x43f,
+0x440, 0x435, 0x43b, 0x44c, 0x3b, 0x41c, 0x430, 0x439, 0x3b, 0x418, 0x44e, 0x43d, 0x44c, 0x3b, 0x418, 0x44e, 0x43b, 0x44c, 0x3b, 0x410,
+0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x421, 0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x41e, 0x43a, 0x442, 0x44f, 0x431,
+0x440, 0x44c, 0x3b, 0x41d, 0x43e, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x414, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x44c, 0x3b, 0x42f, 0x3b,
+0x424, 0x3b, 0x41c, 0x3b, 0x410, 0x3b, 0x41c, 0x3b, 0x418, 0x3b, 0x418, 0x3b, 0x410, 0x3b, 0x421, 0x3b, 0x41e, 0x3b, 0x41d, 0x3b,
+0x414, 0x3b, 0x44f, 0x43d, 0x432, 0x2e, 0x3b, 0x444, 0x435, 0x432, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x2e, 0x3b, 0x430, 0x43f, 0x440,
+0x2e, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x44e, 0x43d, 0x2e, 0x3b, 0x438, 0x44e, 0x43b, 0x2e, 0x3b, 0x430, 0x432, 0x433, 0x2e,
+0x3b, 0x441, 0x435, 0x43d, 0x2e, 0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x44f, 0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e,
+0x3b, 0x44f, 0x43d, 0x432, 0x430, 0x440, 0x44c, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x44c, 0x3b, 0x43c, 0x430, 0x440, 0x442,
+0x3b, 0x430, 0x43f, 0x440, 0x435, 0x43b, 0x44c, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x44e, 0x43d, 0x44c, 0x3b, 0x438, 0x44e, 0x43b,
+0x44c, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x43e, 0x43a,
+0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x44c,
+0x3b, 0x31, 0xc6d4, 0x3b, 0x32, 0xc6d4, 0x3b, 0x33, 0xc6d4, 0x3b, 0x34, 0xc6d4, 0x3b, 0x35, 0xc6d4, 0x3b, 0x36, 0xc6d4, 0x3b, 0x37,
+0xc6d4, 0x3b, 0x38, 0xc6d4, 0x3b, 0x39, 0xc6d4, 0x3b, 0x31, 0x30, 0xc6d4, 0x3b, 0x31, 0x31, 0xc6d4, 0x3b, 0x31, 0x32, 0xc6d4, 0x3b,
+0x72, 0xea, 0x62, 0x3b, 0x72, 0x65, 0x15f, 0x3b, 0x61, 0x64, 0x61, 0x3b, 0x61, 0x76, 0x72, 0x3b, 0x67, 0x75, 0x6c, 0x3b,
+0x70, 0xfb, 0x15f, 0x3b, 0x74, 0xee, 0x72, 0x3b, 0x67, 0x65, 0x6c, 0x3b, 0x72, 0x65, 0x7a, 0x3b, 0x6b, 0x65, 0x77, 0x3b,
+0x73, 0x65, 0x72, 0x3b, 0x62, 0x65, 0x72, 0x3b, 0x72, 0xea, 0x62, 0x65, 0x6e, 0x64, 0x61, 0x6e, 0x3b, 0x72, 0x65, 0x15f,
+0x65, 0x6d, 0xee, 0x3b, 0x61, 0x64, 0x61, 0x72, 0x3b, 0x61, 0x76, 0x72, 0xea, 0x6c, 0x3b, 0x67, 0x75, 0x6c, 0x61, 0x6e,
+0x3b, 0x70, 0xfb, 0x15f, 0x70, 0x65, 0x72, 0x3b, 0x74, 0xee, 0x72, 0x6d, 0x65, 0x68, 0x3b, 0x67, 0x65, 0x6c, 0x61, 0x77,
+0xea, 0x6a, 0x3b, 0x72, 0x65, 0x7a, 0x62, 0x65, 0x72, 0x3b, 0x6b, 0x65, 0x77, 0xe7, 0xea, 0x72, 0x3b, 0x73, 0x65, 0x72,
+0x6d, 0x61, 0x77, 0x65, 0x7a, 0x3b, 0x62, 0x65, 0x72, 0x66, 0x61, 0x6e, 0x62, 0x61, 0x72, 0x3b, 0x52, 0x3b, 0x52, 0x3b,
+0x41, 0x3b, 0x41, 0x3b, 0x47, 0x3b, 0x50, 0x3b, 0x54, 0x3b, 0x47, 0x3b, 0x52, 0x3b, 0x4b, 0x3b, 0x53, 0x3b, 0x42, 0x3b,
+0x72, 0xea, 0x62, 0x65, 0x6e, 0x64, 0x61, 0x6e, 0xea, 0x3b, 0x72, 0x65, 0x15f, 0x65, 0x6d, 0x69, 0x79, 0xea, 0x3b, 0x61,
+0x64, 0x61, 0x72, 0xea, 0x3b, 0x61, 0x76, 0x72, 0xea, 0x6c, 0xea, 0x3b, 0x67, 0x75, 0x6c, 0x61, 0x6e, 0xea, 0x3b, 0x70,
+0xfb, 0x15f, 0x70, 0x65, 0x72, 0xea, 0x3b, 0x74, 0xee, 0x72, 0x6d, 0x65, 0x68, 0xea, 0x3b, 0x67, 0x65, 0x6c, 0x61, 0x77,
+0xea, 0x6a, 0xea, 0x3b, 0x72, 0x65, 0x7a, 0x62, 0x65, 0x72, 0xea, 0x3b, 0x6b, 0x65, 0x77, 0xe7, 0xea, 0x72, 0xea, 0x3b,
+0x73, 0x65, 0x72, 0x6d, 0x61, 0x77, 0x65, 0x7a, 0xea, 0x3b, 0x62, 0x65, 0x72, 0x66, 0x61, 0x6e, 0x62, 0x61, 0x72, 0xea,
+0x3b, 0x4d, 0x75, 0x74, 0x2e, 0x3b, 0x47, 0x61, 0x73, 0x2e, 0x3b, 0x57, 0x65, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x74, 0x2e,
+0x3b, 0x47, 0x69, 0x63, 0x2e, 0x3b, 0x4b, 0x61, 0x6d, 0x2e, 0x3b, 0x4e, 0x79, 0x61, 0x2e, 0x3b, 0x4b, 0x61, 0x6e, 0x2e,
+0x3b, 0x4e, 0x7a, 0x65, 0x2e, 0x3b, 0x55, 0x6b, 0x77, 0x2e, 0x3b, 0x55, 0x67, 0x75, 0x2e, 0x3b, 0x55, 0x6b, 0x75, 0x2e,
+0x3b, 0x4e, 0x7a, 0x65, 0x72, 0x6f, 0x3b, 0x52, 0x75, 0x68, 0x75, 0x68, 0x75, 0x6d, 0x61, 0x3b, 0x4e, 0x74, 0x77, 0x61,
+0x72, 0x61, 0x6e, 0x74, 0x65, 0x3b, 0x4e, 0x64, 0x61, 0x6d, 0x75, 0x6b, 0x69, 0x7a, 0x61, 0x3b, 0x52, 0x75, 0x73, 0x61,
+0x6d, 0x61, 0x3b, 0x52, 0x75, 0x68, 0x65, 0x73, 0x68, 0x69, 0x3b, 0x4d, 0x75, 0x6b, 0x61, 0x6b, 0x61, 0x72, 0x6f, 0x3b,
+0x4e, 0x79, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x61, 0x72, 0x6f, 0x3b, 0x4e, 0x79, 0x61, 0x6b, 0x61, 0x6e, 0x67, 0x61, 0x3b,
+0x47, 0x69, 0x74, 0x75, 0x67, 0x75, 0x74, 0x75, 0x3b, 0x4d, 0x75, 0x6e, 0x79, 0x6f, 0x6e, 0x79, 0x6f, 0x3b, 0x4b, 0x69,
+0x67, 0x61, 0x72, 0x61, 0x6d, 0x61, 0x3b, 0xea1, 0x2e, 0xe81, 0x2e, 0x3b, 0xe81, 0x2e, 0xe9e, 0x2e, 0x3b, 0xea1, 0x2e, 0xe99,
+0x2e, 0x3b, 0xea1, 0x2e, 0xeaa, 0x2e, 0x3b, 0xe9e, 0x2e, 0xe9e, 0x2e, 0x3b, 0xea1, 0xeb4, 0x2e, 0xe96, 0x2e, 0x3b, 0xe81, 0x2e,
+0xea5, 0x2e, 0x3b, 0xeaa, 0x2e, 0xeab, 0x2e, 0x3b, 0xe81, 0x2e, 0xe8d, 0x2e, 0x3b, 0xe95, 0x2e, 0xea5, 0x2e, 0x3b, 0xe9e, 0x2e,
+0xe88, 0x2e, 0x3b, 0xe97, 0x2e, 0xea7, 0x2e, 0x3b, 0xea1, 0xeb1, 0xe87, 0xe81, 0xead, 0xe99, 0x3b, 0xe81, 0xeb8, 0xea1, 0xe9e, 0xeb2,
+0x3b, 0xea1, 0xeb5, 0xe99, 0xeb2, 0x3b, 0xec0, 0xea1, 0xeaa, 0xeb2, 0x3b, 0xe9e, 0xeb6, 0xe94, 0xeaa, 0xeb0, 0xe9e, 0xeb2, 0x3b, 0xea1,
+0xeb4, 0xe96, 0xeb8, 0xe99, 0xeb2, 0x3b, 0xe81, 0xecd, 0xea5, 0xeb0, 0xe81, 0xebb, 0xe94, 0x3b, 0xeaa, 0xeb4, 0xe87, 0xeab, 0xeb2, 0x3b,
+0xe81, 0xeb1, 0xe99, 0xe8d, 0xeb2, 0x3b, 0xe95, 0xeb8, 0xea5, 0xeb2, 0x3b, 0xe9e, 0xeb0, 0xe88, 0xeb4, 0xe81, 0x3b, 0xe97, 0xeb1, 0xe99,
+0xea7, 0xeb2, 0x3b, 0x6a, 0x61, 0x6e, 0x76, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x73,
+0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x6a, 0x73, 0x3b, 0x6a, 0x16b, 0x6e, 0x2e, 0x3b, 0x6a, 0x16b, 0x6c,
+0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f,
+0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x76, 0x101, 0x72, 0x69, 0x73, 0x3b, 0x66, 0x65, 0x62,
+0x72, 0x75, 0x101, 0x72, 0x69, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x12b, 0x6c, 0x69, 0x73,
+0x3b, 0x6d, 0x61, 0x69, 0x6a, 0x73, 0x3b, 0x6a, 0x16b, 0x6e, 0x69, 0x6a, 0x73, 0x3b, 0x6a, 0x16b, 0x6c, 0x69, 0x6a, 0x73,
+0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x73, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x73, 0x3b,
+0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x72, 0x69, 0x73, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x73, 0x3b, 0x64,
+0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x73, 0x3b, 0x79, 0x61, 0x6e, 0x3b, 0x66, 0x62, 0x6c, 0x3b, 0x6d, 0x73, 0x69,
+0x3b, 0x61, 0x70, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x79, 0x75, 0x6e, 0x3b, 0x79, 0x75, 0x6c, 0x3b, 0x61, 0x67, 0x74,
+0x3b, 0x73, 0x74, 0x62, 0x3b, 0x254, 0x74, 0x62, 0x3b, 0x6e, 0x76, 0x62, 0x3b, 0x64, 0x73, 0x62, 0x3b, 0x73, 0xe1, 0x6e,
+0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x79, 0x61, 0x6d, 0x62, 0x6f, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61,
+0x20, 0x6d, 0xed, 0x62, 0x61, 0x6c, 0xe9, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x73,
+0xe1, 0x74, 0x6f, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x6e, 0x65, 0x69, 0x3b, 0x73,
+0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x74, 0xe1, 0x6e, 0x6f, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1,
+0x20, 0x79, 0x61, 0x20, 0x6d, 0x6f, 0x74, 0xf3, 0x62, 0xe1, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20,
+0x6e, 0x73, 0x61, 0x6d, 0x62, 0x6f, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0x77, 0x61, 0x6d,
+0x62, 0x65, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6c, 0x69, 0x62, 0x77, 0x61, 0x3b, 0x73, 0xe1,
+0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x7a, 0xf3, 0x6d, 0x69, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61,
+0x20, 0x7a, 0xf3, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x254, 0x30c, 0x6b, 0x254, 0x301, 0x3b, 0x73, 0xe1, 0x6e, 0x7a,
+0xe1, 0x20, 0x79, 0x61, 0x20, 0x7a, 0xf3, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0xed, 0x62, 0x61, 0x6c, 0xe9, 0x3b,
+0x79, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x61, 0x3b, 0x6d, 0x3b, 0x79, 0x3b, 0x79, 0x3b, 0x61, 0x3b, 0x73, 0x3b, 0x254, 0x3b,
+0x6e, 0x3b, 0x64, 0x3b, 0x73, 0x61, 0x75, 0x73, 0x2e, 0x3b, 0x76, 0x61, 0x73, 0x2e, 0x3b, 0x6b, 0x6f, 0x76, 0x2e, 0x3b,
+0x62, 0x61, 0x6c, 0x2e, 0x3b, 0x67, 0x65, 0x67, 0x2e, 0x3b, 0x62, 0x69, 0x72, 0x17e, 0x2e, 0x3b, 0x6c, 0x69, 0x65, 0x70,
+0x2e, 0x3b, 0x72, 0x75, 0x67, 0x70, 0x2e, 0x3b, 0x72, 0x75, 0x67, 0x73, 0x2e, 0x3b, 0x73, 0x70, 0x61, 0x6c, 0x2e, 0x3b,
+0x6c, 0x61, 0x70, 0x6b, 0x72, 0x2e, 0x3b, 0x67, 0x72, 0x75, 0x6f, 0x64, 0x2e, 0x3b, 0x73, 0x61, 0x75, 0x73, 0x69, 0x73,
+0x3b, 0x76, 0x61, 0x73, 0x61, 0x72, 0x69, 0x73, 0x3b, 0x6b, 0x6f, 0x76, 0x61, 0x73, 0x3b, 0x62, 0x61, 0x6c, 0x61, 0x6e,
+0x64, 0x69, 0x73, 0x3b, 0x67, 0x65, 0x67, 0x75, 0x17e, 0x117, 0x3b, 0x62, 0x69, 0x72, 0x17e, 0x65, 0x6c, 0x69, 0x73, 0x3b,
+0x6c, 0x69, 0x65, 0x70, 0x61, 0x3b, 0x72, 0x75, 0x67, 0x70, 0x6a, 0x16b, 0x74, 0x69, 0x73, 0x3b, 0x72, 0x75, 0x67, 0x73,
+0x117, 0x6a, 0x69, 0x73, 0x3b, 0x73, 0x70, 0x61, 0x6c, 0x69, 0x73, 0x3b, 0x6c, 0x61, 0x70, 0x6b, 0x72, 0x69, 0x74, 0x69,
+0x73, 0x3b, 0x67, 0x72, 0x75, 0x6f, 0x64, 0x69, 0x73, 0x3b, 0x53, 0x3b, 0x56, 0x3b, 0x4b, 0x3b, 0x42, 0x3b, 0x47, 0x3b,
+0x42, 0x3b, 0x4c, 0x3b, 0x52, 0x3b, 0x52, 0x3b, 0x53, 0x3b, 0x4c, 0x3b, 0x47, 0x3b, 0x73, 0x61, 0x75, 0x73, 0x69, 0x6f,
+0x3b, 0x76, 0x61, 0x73, 0x61, 0x72, 0x69, 0x6f, 0x3b, 0x6b, 0x6f, 0x76, 0x6f, 0x3b, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x64,
+0x17e, 0x69, 0x6f, 0x3b, 0x67, 0x65, 0x67, 0x75, 0x17e, 0x117, 0x73, 0x3b, 0x62, 0x69, 0x72, 0x17e, 0x65, 0x6c, 0x69, 0x6f,
+0x3b, 0x6c, 0x69, 0x65, 0x70, 0x6f, 0x73, 0x3b, 0x72, 0x75, 0x67, 0x70, 0x6a, 0x16b, 0x10d, 0x69, 0x6f, 0x3b, 0x72, 0x75,
+0x67, 0x73, 0x117, 0x6a, 0x6f, 0x3b, 0x73, 0x70, 0x61, 0x6c, 0x69, 0x6f, 0x3b, 0x6c, 0x61, 0x70, 0x6b, 0x72, 0x69, 0x10d,
+0x69, 0x6f, 0x3b, 0x67, 0x72, 0x75, 0x6f, 0x64, 0x17e, 0x69, 0x6f, 0x3b, 0x458, 0x430, 0x43d, 0x2e, 0x3b, 0x444, 0x435, 0x432,
+0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x2e, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x2e,
+0x3b, 0x458, 0x443, 0x43b, 0x2e, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x2e, 0x3b, 0x43e, 0x43a, 0x442,
+0x2e, 0x3b, 0x43d, 0x43e, 0x435, 0x43c, 0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e, 0x3b, 0x458, 0x430, 0x43d, 0x443, 0x430, 0x440, 0x438,
+0x3b, 0x444, 0x435, 0x432, 0x440, 0x443, 0x430, 0x440, 0x438, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b,
+0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x438, 0x3b, 0x458, 0x443, 0x43b, 0x438, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441,
+0x442, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x43c, 0x432, 0x440, 0x438,
+0x3b, 0x43d, 0x43e, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x434, 0x435, 0x43a, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x458, 0x3b,
+0x444, 0x3b, 0x43c, 0x3b, 0x430, 0x3b, 0x43c, 0x3b, 0x458, 0x3b, 0x458, 0x3b, 0x430, 0x3b, 0x441, 0x3b, 0x43e, 0x3b, 0x43d, 0x3b,
+0x434, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65,
+0x79, 0x3b, 0x4a, 0x6f, 0x6e, 0x3b, 0x4a, 0x6f, 0x6c, 0x3b, 0x41, 0x6f, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b,
+0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x6f, 0x61, 0x72, 0x79, 0x3b, 0x46, 0x65,
+0x62, 0x72, 0x6f, 0x61, 0x72, 0x79, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x73, 0x61, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x79,
+0x3b, 0x4d, 0x65, 0x79, 0x3b, 0x4a, 0x6f, 0x6e, 0x61, 0x3b, 0x4a, 0x6f, 0x6c, 0x61, 0x79, 0x3b, 0x41, 0x6f, 0x67, 0x6f,
+0x73, 0x69, 0x74, 0x72, 0x61, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x61, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f,
+0x62, 0x72, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x61, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x61, 0x6d, 0x62, 0x72,
+0x61, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65,
+0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x4f, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b,
+0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65,
+0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x69,
+0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x4f, 0x67, 0x6f, 0x73, 0x3b, 0x53, 0x65, 0x70, 0x74,
+0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62,
+0x65, 0x72, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b,
+0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4f, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0xd1c, 0xd28, 0xd41, 0x3b,
+0xd2b, 0xd46, 0xd2c, 0xd4d, 0xd30, 0xd41, 0x3b, 0xd2e, 0xd3e, 0xd7c, 0x3b, 0xd0f, 0xd2a, 0xd4d, 0xd30, 0xd3f, 0x3b, 0xd2e, 0xd47, 0xd2f,
+0xd4d, 0x3b, 0xd1c, 0xd42, 0xd7a, 0x3b, 0xd1c, 0xd42, 0xd32, 0xd48, 0x3b, 0xd13, 0xd17, 0x3b, 0xd38, 0xd46, 0xd2a, 0xd4d, 0xd31, 0xd4d,
+0xd31, 0xd02, 0x3b, 0xd12, 0xd15, 0xd4d, 0xd1f, 0xd4b, 0x3b, 0xd28, 0xd35, 0xd02, 0x3b, 0xd21, 0xd3f, 0xd38, 0xd02, 0x3b, 0xd1c, 0xd28,
+0xd41, 0xd35, 0xd30, 0xd3f, 0x3b, 0xd2b, 0xd46, 0xd2c, 0xd4d, 0xd30, 0xd41, 0xd35, 0xd30, 0xd3f, 0x3b, 0xd2e, 0xd3e, 0xd7c, 0xd1a, 0xd4d,
+0xd1a, 0xd4d, 0x3b, 0xd0f, 0xd2a, 0xd4d, 0xd30, 0xd3f, 0xd7d, 0x3b, 0xd2e, 0xd47, 0xd2f, 0xd4d, 0x3b, 0xd1c, 0xd42, 0xd7a, 0x3b, 0xd1c,
+0xd42, 0xd32, 0xd48, 0x3b, 0xd13, 0xd17, 0xd38, 0xd4d, 0xd31, 0xd4d, 0xd31, 0xd4d, 0x3b, 0xd38, 0xd46, 0xd2a, 0xd4d, 0xd31, 0xd4d, 0xd31,
+0xd02, 0xd2c, 0xd7c, 0x3b, 0xd12, 0xd15, 0xd4d, 0x200c, 0xd1f, 0xd4b, 0xd2c, 0xd7c, 0x3b, 0xd28, 0xd35, 0xd02, 0xd2c, 0xd7c, 0x3b, 0xd21,
+0xd3f, 0xd38, 0xd02, 0xd2c, 0xd7c, 0x3b, 0xd1c, 0x3b, 0xd2b, 0xd46, 0x3b, 0xd2e, 0xd3e, 0x3b, 0xd0f, 0x3b, 0xd2e, 0xd46, 0x3b, 0xd1c,
+0xd42, 0xd7a, 0x3b, 0xd1c, 0xd42, 0x3b, 0xd13, 0x3b, 0xd38, 0xd46, 0x3b, 0xd12, 0x3b, 0xd28, 0x3b, 0xd21, 0xd3f, 0x3b, 0x4a, 0x61,
+0x6e, 0x3b, 0x46, 0x72, 0x61, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x6a, 0x3b, 0x120, 0x75,
+0x6e, 0x3b, 0x4c, 0x75, 0x6c, 0x3b, 0x41, 0x77, 0x77, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x74, 0x74, 0x3b, 0x4e, 0x6f,
+0x76, 0x3b, 0x44, 0x69, 0x10b, 0x3b, 0x4a, 0x61, 0x6e, 0x6e, 0x61, 0x72, 0x3b, 0x46, 0x72, 0x61, 0x72, 0x3b, 0x4d, 0x61,
+0x72, 0x7a, 0x75, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x6a, 0x6a, 0x75, 0x3b, 0x120, 0x75, 0x6e, 0x6a,
+0x75, 0x3b, 0x4c, 0x75, 0x6c, 0x6a, 0x75, 0x3b, 0x41, 0x77, 0x77, 0x69, 0x73, 0x73, 0x75, 0x3b, 0x53, 0x65, 0x74, 0x74,
+0x65, 0x6d, 0x62, 0x72, 0x75, 0x3b, 0x4f, 0x74, 0x74, 0x75, 0x62, 0x72, 0x75, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62,
+0x72, 0x75, 0x3b, 0x44, 0x69, 0x10b, 0x65, 0x6d, 0x62, 0x72, 0x75, 0x3b, 0x4a, 0x6e, 0x3b, 0x46, 0x72, 0x3b, 0x4d, 0x7a,
+0x3b, 0x41, 0x70, 0x3b, 0x4d, 0x6a, 0x3b, 0x120, 0x6e, 0x3b, 0x4c, 0x6a, 0x3b, 0x41, 0x77, 0x3b, 0x53, 0x74, 0x3b, 0x4f,
+0x62, 0x3b, 0x4e, 0x76, 0x3b, 0x44, 0x10b, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x120, 0x3b,
+0x4c, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x4b, 0x6f, 0x68, 0x69, 0x3b, 0x48, 0x75, 0x69,
+0x3b, 0x50, 0x6f, 0x75, 0x3b, 0x50, 0x61, 0x65, 0x3b, 0x48, 0x61, 0x72, 0x61, 0x3b, 0x50, 0x69, 0x70, 0x69, 0x3b, 0x48,
+0x14d, 0x6e, 0x67, 0x6f, 0x3b, 0x48, 0x65, 0x72, 0x65, 0x3b, 0x4d, 0x61, 0x68, 0x75, 0x3b, 0x4e, 0x75, 0x6b, 0x75, 0x3b,
+0x52, 0x61, 0x6e, 0x67, 0x69, 0x3b, 0x48, 0x61, 0x6b, 0x69, 0x3b, 0x4b, 0x6f, 0x68, 0x69, 0x74, 0x101, 0x74, 0x65, 0x61,
+0x3b, 0x48, 0x75, 0x69, 0x74, 0x61, 0x6e, 0x67, 0x75, 0x72, 0x75, 0x3b, 0x50, 0x6f, 0x75, 0x74, 0x16b, 0x74, 0x65, 0x72,
+0x61, 0x6e, 0x67, 0x69, 0x3b, 0x50, 0x61, 0x65, 0x6e, 0x67, 0x61, 0x77, 0x68, 0x101, 0x77, 0x68, 0x101, 0x3b, 0x48, 0x61,
+0x72, 0x61, 0x74, 0x75, 0x61, 0x3b, 0x50, 0x69, 0x70, 0x69, 0x72, 0x69, 0x3b, 0x48, 0x14d, 0x6e, 0x67, 0x6f, 0x6e, 0x67,
+0x6f, 0x69, 0x3b, 0x48, 0x65, 0x72, 0x65, 0x74, 0x75, 0x72, 0x69, 0x6b, 0x14d, 0x6b, 0x101, 0x3b, 0x4d, 0x61, 0x68, 0x75,
+0x72, 0x75, 0x3b, 0x57, 0x68, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x61, 0x2d, 0x101, 0x2d, 0x6e, 0x75, 0x6b, 0x75, 0x3b, 0x57,
+0x68, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x61, 0x2d, 0x101, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x69, 0x3b, 0x48, 0x61, 0x6b, 0x69,
+0x68, 0x65, 0x61, 0x3b, 0x4b, 0x3b, 0x48, 0x3b, 0x50, 0x3b, 0x50, 0x3b, 0x48, 0x3b, 0x50, 0x3b, 0x48, 0x3b, 0x48, 0x3b,
+0x4d, 0x3b, 0x4e, 0x3b, 0x52, 0x3b, 0x48, 0x3b, 0x91c, 0x93e, 0x928, 0x947, 0x3b, 0x92b, 0x947, 0x92c, 0x94d, 0x930, 0x941, 0x3b,
+0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x90f, 0x92a, 0x94d, 0x930, 0x93f, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c,
+0x941, 0x932, 0x948, 0x3b, 0x911, 0x917, 0x3b, 0x938, 0x92a, 0x94d, 0x91f, 0x947, 0x902, 0x3b, 0x911, 0x915, 0x94d, 0x91f, 0x94b, 0x3b,
+0x928, 0x94b, 0x935, 0x94d, 0x939, 0x947, 0x902, 0x3b, 0x921, 0x93f, 0x938, 0x947, 0x902, 0x3b, 0x91c, 0x93e, 0x928, 0x947, 0x935, 0x93e,
+0x930, 0x940, 0x3b, 0x92b, 0x947, 0x92c, 0x94d, 0x930, 0x941, 0x935, 0x93e, 0x930, 0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b,
+0x90f, 0x92a, 0x94d, 0x930, 0x93f, 0x932, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x948, 0x3b, 0x911,
+0x917, 0x938, 0x94d, 0x91f, 0x3b, 0x938, 0x92a, 0x94d, 0x91f, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x911, 0x915, 0x94d, 0x91f, 0x94b, 0x92c,
+0x930, 0x3b, 0x928, 0x94b, 0x935, 0x94d, 0x939, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x921, 0x93f, 0x938, 0x947, 0x902, 0x92c, 0x930, 0x3b,
+0x91c, 0x93e, 0x3b, 0x92b, 0x947, 0x3b, 0x92e, 0x93e, 0x3b, 0x90f, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x942, 0x3b, 0x91c, 0x941, 0x3b,
+0x911, 0x3b, 0x938, 0x3b, 0x911, 0x3b, 0x928, 0x94b, 0x3b, 0x921, 0x93f, 0x3b, 0x31, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b,
+0x32, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x33, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x34, 0x2d, 0x440, 0x20,
+0x441, 0x430, 0x440, 0x3b, 0x35, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x36, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b,
+0x37, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x38, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x39, 0x2d, 0x440, 0x20,
+0x441, 0x430, 0x440, 0x3b, 0x31, 0x30, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x31, 0x31, 0x2d, 0x440, 0x20, 0x441, 0x430,
+0x440, 0x3b, 0x31, 0x32, 0x2d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x41d, 0x44d, 0x433, 0x434, 0x4af, 0x433, 0x44d, 0x44d, 0x440,
+0x20, 0x441, 0x430, 0x440, 0x3b, 0x425, 0x43e, 0x451, 0x440, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b,
+0x413, 0x443, 0x440, 0x430, 0x432, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x414, 0x4e9, 0x440, 0x4e9,
+0x432, 0x434, 0x4af, 0x433, 0x44d, 0x44d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x422, 0x430, 0x432, 0x434, 0x443, 0x433, 0x430, 0x430,
+0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x417, 0x443, 0x440, 0x433, 0x430, 0x430, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441,
+0x430, 0x440, 0x3b, 0x414, 0x43e, 0x43b, 0x43e, 0x43e, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x41d,
+0x430, 0x439, 0x43c, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x415, 0x441, 0x434, 0x4af, 0x433, 0x44d,
+0x44d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x410, 0x440, 0x430, 0x432, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430,
+0x440, 0x3b, 0x410, 0x440, 0x432, 0x430, 0x43d, 0x20, 0x43d, 0x44d, 0x433, 0x434, 0x4af, 0x433, 0x44d, 0x44d, 0x440, 0x20, 0x441, 0x430,
+0x440, 0x3b, 0x410, 0x440, 0x432, 0x430, 0x43d, 0x20, 0x445, 0x43e, 0x451, 0x440, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441,
+0x430, 0x440, 0x3b, 0x49, 0x3b, 0x49, 0x49, 0x3b, 0x49, 0x49, 0x49, 0x3b, 0x49, 0x56, 0x3b, 0x56, 0x3b, 0x56, 0x49, 0x3b,
+0x56, 0x49, 0x49, 0x3b, 0x56, 0x49, 0x49, 0x49, 0x3b, 0x49, 0x58, 0x3b, 0x58, 0x3b, 0x58, 0x49, 0x3b, 0x58, 0x49, 0x49,
+0x3b, 0x43d, 0x44d, 0x433, 0x434, 0x4af, 0x433, 0x44d, 0x44d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x445, 0x43e, 0x451, 0x440, 0x434,
+0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x433, 0x443, 0x440, 0x430, 0x432, 0x434, 0x443, 0x433, 0x430, 0x430,
+0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x434, 0x4e9, 0x440, 0x4e9, 0x432, 0x434, 0x4af, 0x433, 0x44d, 0x44d, 0x440, 0x20, 0x441, 0x430,
+0x440, 0x3b, 0x442, 0x430, 0x432, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x437, 0x443, 0x440, 0x433,
+0x430, 0x430, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x434, 0x43e, 0x43b, 0x43e, 0x43e, 0x434, 0x443,
+0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x43d, 0x430, 0x439, 0x43c, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20,
+0x441, 0x430, 0x440, 0x3b, 0x435, 0x441, 0x434, 0x4af, 0x433, 0x44d, 0x44d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x430, 0x440, 0x430,
+0x432, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x430, 0x440, 0x432, 0x430, 0x43d, 0x20, 0x43d, 0x44d,
+0x433, 0x434, 0x4af, 0x433, 0x44d, 0x44d, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x430, 0x440, 0x432, 0x430, 0x43d, 0x20, 0x445, 0x43e,
+0x451, 0x440, 0x434, 0x443, 0x433, 0x430, 0x430, 0x440, 0x20, 0x441, 0x430, 0x440, 0x3b, 0x91c, 0x928, 0x935, 0x930, 0x940, 0x3b, 0x92b,
+0x947, 0x92c, 0x94d, 0x930, 0x941, 0x905, 0x930, 0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x93f,
+0x932, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x941, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x908, 0x3b, 0x905, 0x917, 0x938, 0x94d, 0x91f,
+0x3b, 0x938, 0x947, 0x92a, 0x94d, 0x91f, 0x947, 0x92e, 0x94d, 0x92c, 0x930, 0x3b, 0x905, 0x915, 0x94d, 0x91f, 0x94b, 0x92c, 0x930, 0x3b,
+0x928, 0x94b, 0x92d, 0x947, 0x92e, 0x94d, 0x92c, 0x930, 0x3b, 0x921, 0x93f, 0x938, 0x947, 0x92e, 0x94d, 0x92c, 0x930, 0x3b, 0x91c, 0x928,
+0x3b, 0x92b, 0x947, 0x947, 0x92c, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x3b, 0x92e, 0x947, 0x3b,
+0x91c, 0x941, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x3b, 0x905, 0x917, 0x3b, 0x938, 0x947, 0x92a, 0x3b, 0x905, 0x915, 0x94d, 0x91f, 0x94b,
+0x3b, 0x928, 0x94b, 0x92d, 0x947, 0x3b, 0x921, 0x93f, 0x938, 0x947, 0x3b, 0x91c, 0x928, 0x3b, 0x92b, 0x947, 0x92c, 0x3b, 0x92e, 0x93e,
+0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x941, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x3b,
+0x905, 0x917, 0x3b, 0x938, 0x947, 0x92a, 0x3b, 0x905, 0x915, 0x94d, 0x91f, 0x94b, 0x3b, 0x928, 0x94b, 0x92d, 0x947, 0x3b, 0x921, 0x93f,
+0x938, 0x947, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61,
0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75,
0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b,
0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x73,
@@ -2673,373 +2754,409 @@ static const ushort months_data[] = {
0x3b, 0xb05, 0x3b, 0xb2e, 0xb07, 0x3b, 0xb1c, 0xb41, 0x3b, 0xb1c, 0xb41, 0x3b, 0xb05, 0x3b, 0xb38, 0xb47, 0x3b, 0xb05, 0x3b, 0xb28,
0x3b, 0xb21, 0xb3f, 0x3b, 0x62c, 0x646, 0x648, 0x631, 0x64a, 0x3b, 0x641, 0x628, 0x631, 0x648, 0x631, 0x64a, 0x3b, 0x645, 0x627, 0x631,
0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cd, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x6cc,
-0x3b, 0x627, 0x6ab, 0x633, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b,
-0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x698, 0x627, 0x646, 0x648, 0x6cc, 0x647, 0x3b, 0x641,
-0x648, 0x631, 0x6cc, 0x647, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x622, 0x648, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x647, 0x3b, 0x698,
-0x648, 0x626, 0x646, 0x3b, 0x698, 0x648, 0x626, 0x6cc, 0x647, 0x3b, 0x627, 0x648, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x627, 0x645, 0x628,
+0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b,
+0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x62c, 0x646, 0x648, 0x631, 0x64a, 0x3b, 0x641, 0x6d0,
+0x628, 0x631, 0x648, 0x631, 0x64a, 0x3b, 0x645, 0x627, 0x631, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cd, 0x3b,
+0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x6cc, 0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x645, 0x628,
+0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631,
+0x3b, 0x62c, 0x646, 0x648, 0x631, 0x64a, 0x3b, 0x641, 0x628, 0x631, 0x648, 0x631, 0x64a, 0x3b, 0x645, 0x627, 0x631, 0x686, 0x3b, 0x627,
+0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cd, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x6cc, 0x3b, 0x627, 0x6af,
+0x633, 0x62a, 0x3b, 0x633, 0x6d0, 0x67e, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648,
+0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x62c, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x627, 0x3b, 0x645, 0x3b,
+0x62c, 0x3b, 0x62c, 0x3b, 0x627, 0x3b, 0x633, 0x3b, 0x627, 0x3b, 0x646, 0x3b, 0x62f, 0x3b, 0x698, 0x627, 0x646, 0x648, 0x6cc, 0x647,
+0x3b, 0x641, 0x648, 0x631, 0x6cc, 0x647, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x622, 0x648, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x647,
+0x3b, 0x698, 0x648, 0x626, 0x646, 0x3b, 0x698, 0x648, 0x626, 0x6cc, 0x647, 0x3b, 0x627, 0x648, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x627,
+0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x627, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x627,
+0x645, 0x628, 0x631, 0x3b, 0x698, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x622, 0x3b, 0x645, 0x3b, 0x698, 0x3b, 0x698, 0x3b, 0x627, 0x3b,
+0x633, 0x3b, 0x627, 0x3b, 0x646, 0x3b, 0x62f, 0x3b, 0x698, 0x627, 0x646, 0x648, 0x6cc, 0x647, 0x654, 0x3b, 0x641, 0x648, 0x631, 0x6cc,
+0x647, 0x654, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x622, 0x648, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x647, 0x654, 0x3b, 0x698, 0x648,
+0x626, 0x646, 0x3b, 0x698, 0x648, 0x626, 0x6cc, 0x647, 0x654, 0x3b, 0x627, 0x648, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x627, 0x645, 0x628,
0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x627, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x627, 0x645, 0x628,
-0x631, 0x3b, 0x698, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x622, 0x3b, 0x645, 0x3b, 0x698, 0x3b, 0x698, 0x3b, 0x627, 0x3b, 0x633, 0x3b,
-0x627, 0x3b, 0x646, 0x3b, 0x62f, 0x3b, 0x698, 0x627, 0x646, 0x648, 0x6cc, 0x647, 0x654, 0x3b, 0x641, 0x648, 0x631, 0x6cc, 0x647, 0x654,
-0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x622, 0x648, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x647, 0x654, 0x3b, 0x698, 0x648, 0x626, 0x646,
-0x3b, 0x698, 0x648, 0x626, 0x6cc, 0x647, 0x654, 0x3b, 0x627, 0x648, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x627, 0x645, 0x628, 0x631, 0x3b,
-0x627, 0x6a9, 0x62a, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x627, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x627, 0x645, 0x628, 0x631, 0x3b,
-0x62c, 0x646, 0x648, 0x631, 0x6cc, 0x3b, 0x641, 0x628, 0x631, 0x648, 0x631, 0x6cc, 0x3b, 0x645, 0x627, 0x631, 0x686, 0x3b, 0x627, 0x67e,
-0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x6cc, 0x3b, 0x627, 0x6af, 0x633,
-0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628,
-0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x62c, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x627, 0x3b, 0x645, 0x3b, 0x62c, 0x3b,
-0x62c, 0x3b, 0x627, 0x3b, 0x633, 0x3b, 0x627, 0x3b, 0x646, 0x3b, 0x62f, 0x3b, 0x62c, 0x646, 0x648, 0x3b, 0x641, 0x628, 0x631, 0x648,
-0x631, 0x6cc, 0x3b, 0x645, 0x627, 0x631, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cc, 0x3b, 0x62c, 0x648, 0x646,
-0x3b, 0x62c, 0x648, 0x644, 0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a,
-0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x3b, 0x73, 0x74, 0x79, 0x3b, 0x6c, 0x75,
-0x74, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6b, 0x77, 0x69, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x63, 0x7a, 0x65, 0x3b, 0x6c, 0x69,
-0x70, 0x3b, 0x73, 0x69, 0x65, 0x3b, 0x77, 0x72, 0x7a, 0x3b, 0x70, 0x61, 0x17a, 0x3b, 0x6c, 0x69, 0x73, 0x3b, 0x67, 0x72,
-0x75, 0x3b, 0x73, 0x74, 0x79, 0x63, 0x7a, 0x65, 0x144, 0x3b, 0x6c, 0x75, 0x74, 0x79, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x65,
-0x63, 0x3b, 0x6b, 0x77, 0x69, 0x65, 0x63, 0x69, 0x65, 0x144, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x63, 0x7a, 0x65, 0x72, 0x77,
-0x69, 0x65, 0x63, 0x3b, 0x6c, 0x69, 0x70, 0x69, 0x65, 0x63, 0x3b, 0x73, 0x69, 0x65, 0x72, 0x70, 0x69, 0x65, 0x144, 0x3b,
-0x77, 0x72, 0x7a, 0x65, 0x73, 0x69, 0x65, 0x144, 0x3b, 0x70, 0x61, 0x17a, 0x64, 0x7a, 0x69, 0x65, 0x72, 0x6e, 0x69, 0x6b,
-0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x3b, 0x67, 0x72, 0x75, 0x64, 0x7a, 0x69, 0x65, 0x144, 0x3b, 0x53,
-0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b, 0x43, 0x3b, 0x4c, 0x3b, 0x53, 0x3b, 0x57, 0x3b, 0x50, 0x3b, 0x4c,
-0x3b, 0x47, 0x3b, 0x73, 0x74, 0x79, 0x63, 0x7a, 0x6e, 0x69, 0x61, 0x3b, 0x6c, 0x75, 0x74, 0x65, 0x67, 0x6f, 0x3b, 0x6d,
-0x61, 0x72, 0x63, 0x61, 0x3b, 0x6b, 0x77, 0x69, 0x65, 0x74, 0x6e, 0x69, 0x61, 0x3b, 0x6d, 0x61, 0x6a, 0x61, 0x3b, 0x63,
-0x7a, 0x65, 0x72, 0x77, 0x63, 0x61, 0x3b, 0x6c, 0x69, 0x70, 0x63, 0x61, 0x3b, 0x73, 0x69, 0x65, 0x72, 0x70, 0x6e, 0x69,
-0x61, 0x3b, 0x77, 0x72, 0x7a, 0x65, 0x15b, 0x6e, 0x69, 0x61, 0x3b, 0x70, 0x61, 0x17a, 0x64, 0x7a, 0x69, 0x65, 0x72, 0x6e,
-0x69, 0x6b, 0x61, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x61, 0x3b, 0x67, 0x72, 0x75, 0x64, 0x6e, 0x69,
-0x61, 0x3b, 0x73, 0x3b, 0x6c, 0x3b, 0x6d, 0x3b, 0x6b, 0x3b, 0x6d, 0x3b, 0x63, 0x3b, 0x6c, 0x3b, 0x73, 0x3b, 0x77, 0x3b,
-0x70, 0x3b, 0x6c, 0x3b, 0x67, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x76, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x62,
-0x72, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x67, 0x6f, 0x3b, 0x73, 0x65,
-0x74, 0x3b, 0x6f, 0x75, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x7a, 0x3b, 0x6a, 0x61, 0x6e, 0x65, 0x69, 0x72,
-0x6f, 0x3b, 0x66, 0x65, 0x76, 0x65, 0x72, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0xe7, 0x6f, 0x3b, 0x61, 0x62,
-0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x6f, 0x3b, 0x6a, 0x75, 0x6e, 0x68, 0x6f, 0x3b, 0x6a, 0x75, 0x6c, 0x68, 0x6f,
-0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x6f, 0x75, 0x74,
-0x75, 0x62, 0x72, 0x6f, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x64, 0x65, 0x7a, 0x65, 0x6d, 0x62,
-0x72, 0x6f, 0x3b, 0xa1c, 0xa28, 0x3b, 0xa2b, 0xa3c, 0xa30, 0x3b, 0xa2e, 0xa3e, 0xa30, 0xa1a, 0x3b, 0xa05, 0xa2a, 0xa4d, 0xa30, 0xa48,
-0x3b, 0xa2e, 0xa08, 0x3b, 0xa1c, 0xa42, 0xa28, 0x3b, 0xa1c, 0xa41, 0xa32, 0xa3e, 0x3b, 0xa05, 0xa17, 0x3b, 0xa38, 0xa24, 0xa70, 0x3b,
-0xa05, 0xa15, 0xa24, 0xa42, 0x3b, 0xa28, 0xa35, 0xa70, 0x3b, 0xa26, 0xa38, 0xa70, 0x3b, 0xa1c, 0xa28, 0xa35, 0xa30, 0xa40, 0x3b, 0xa2b,
-0xa3c, 0xa30, 0xa35, 0xa30, 0xa40, 0x3b, 0xa2e, 0xa3e, 0xa30, 0xa1a, 0x3b, 0xa05, 0xa2a, 0xa4d, 0xa30, 0xa48, 0xa32, 0x3b, 0xa2e, 0xa08,
-0x3b, 0xa1c, 0xa42, 0xa28, 0x3b, 0xa1c, 0xa41, 0xa32, 0xa3e, 0xa08, 0x3b, 0xa05, 0xa17, 0xa38, 0xa24, 0x3b, 0xa38, 0xa24, 0xa70, 0xa2c,
-0xa30, 0x3b, 0xa05, 0xa15, 0xa24, 0xa42, 0xa2c, 0xa30, 0x3b, 0xa28, 0xa35, 0xa70, 0xa2c, 0xa30, 0x3b, 0xa26, 0xa38, 0xa70, 0xa2c, 0xa30,
-0x3b, 0xa1c, 0x3b, 0xa2b, 0xa3c, 0x3b, 0xa2e, 0xa3e, 0x3b, 0xa05, 0x3b, 0xa2e, 0x3b, 0xa1c, 0xa42, 0x3b, 0xa1c, 0xa41, 0x3b, 0xa05,
-0x3b, 0xa38, 0x3b, 0xa05, 0x3b, 0xa28, 0x3b, 0xa26, 0x3b, 0x62c, 0x646, 0x648, 0x631, 0x6cc, 0x3b, 0x641, 0x631, 0x648, 0x631, 0x6cc,
-0x3b, 0x645, 0x627, 0x631, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x626, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c,
-0x648, 0x644, 0x627, 0x626, 0x6cc, 0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a,
-0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x51, 0x75, 0x6c, 0x3b,
-0x48, 0x61, 0x74, 0x3b, 0x50, 0x61, 0x75, 0x3b, 0x41, 0x79, 0x72, 0x3b, 0x41, 0x79, 0x6d, 0x3b, 0x49, 0x6e, 0x74, 0x3b,
-0x41, 0x6e, 0x74, 0x3b, 0x51, 0x68, 0x61, 0x3b, 0x55, 0x6d, 0x61, 0x3b, 0x4b, 0x61, 0x6e, 0x3b, 0x41, 0x79, 0x61, 0x3b,
-0x4b, 0x61, 0x70, 0x3b, 0x51, 0x75, 0x6c, 0x6c, 0x61, 0x20, 0x70, 0x75, 0x71, 0x75, 0x79, 0x3b, 0x48, 0x61, 0x74, 0x75,
-0x6e, 0x20, 0x70, 0x75, 0x71, 0x75, 0x79, 0x3b, 0x50, 0x61, 0x75, 0x71, 0x61, 0x72, 0x20, 0x77, 0x61, 0x72, 0x61, 0x79,
-0x3b, 0x41, 0x79, 0x72, 0x69, 0x77, 0x61, 0x3b, 0x41, 0x79, 0x6d, 0x75, 0x72, 0x61, 0x79, 0x3b, 0x49, 0x6e, 0x74, 0x69,
-0x20, 0x72, 0x61, 0x79, 0x6d, 0x69, 0x3b, 0x41, 0x6e, 0x74, 0x61, 0x20, 0x53, 0x69, 0x74, 0x77, 0x61, 0x3b, 0x51, 0x68,
-0x61, 0x70, 0x61, 0x71, 0x20, 0x53, 0x69, 0x74, 0x77, 0x61, 0x3b, 0x55, 0x6d, 0x61, 0x20, 0x72, 0x61, 0x79, 0x6d, 0x69,
-0x3b, 0x4b, 0x61, 0x6e, 0x74, 0x61, 0x72, 0x61, 0x79, 0x3b, 0x41, 0x79, 0x61, 0x6d, 0x61, 0x72, 0x71, 0x2bc, 0x61, 0x3b,
-0x4b, 0x61, 0x70, 0x61, 0x71, 0x20, 0x52, 0x61, 0x79, 0x6d, 0x69, 0x3b, 0x73, 0x63, 0x68, 0x61, 0x6e, 0x2e, 0x3b, 0x66,
-0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x74, 0x67, 0x3b,
-0x7a, 0x65, 0x72, 0x63, 0x6c, 0x2e, 0x3b, 0x66, 0x61, 0x6e, 0x2e, 0x3b, 0x61, 0x76, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65,
-0x74, 0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x73,
-0x63, 0x68, 0x61, 0x6e, 0x65, 0x72, 0x3b, 0x66, 0x61, 0x76, 0x72, 0x65, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61,
-0x76, 0x72, 0x69, 0x67, 0x6c, 0x3b, 0x6d, 0x61, 0x74, 0x67, 0x3b, 0x7a, 0x65, 0x72, 0x63, 0x6c, 0x61, 0x64, 0x75, 0x72,
-0x3b, 0x66, 0x61, 0x6e, 0x61, 0x64, 0x75, 0x72, 0x3b, 0x61, 0x76, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x74, 0x74, 0x65,
-0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x63, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65,
-0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x53, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d,
-0x3b, 0x5a, 0x3b, 0x46, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x69, 0x61, 0x6e, 0x2e, 0x3b,
-0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x69,
-0x75, 0x6e, 0x2e, 0x3b, 0x69, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b,
-0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x69, 0x61, 0x6e, 0x75, 0x61,
-0x72, 0x69, 0x65, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x65, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x69, 0x65,
-0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x69, 0x65, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x69, 0x75, 0x6e, 0x69, 0x65, 0x3b, 0x69,
-0x75, 0x6c, 0x69, 0x65, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72,
-0x69, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x6f, 0x6d, 0x62, 0x72, 0x69, 0x65, 0x3b, 0x6e, 0x6f, 0x69, 0x65, 0x6d, 0x62, 0x72,
-0x69, 0x65, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x65, 0x3b, 0x49, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41,
-0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x44f, 0x43d, 0x432,
-0x2e, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430,
-0x439, 0x3b, 0x438, 0x44e, 0x43d, 0x44c, 0x3b, 0x438, 0x44e, 0x43b, 0x44c, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43d,
+0x631, 0x3b, 0x62c, 0x646, 0x648, 0x631, 0x6cc, 0x3b, 0x641, 0x628, 0x631, 0x648, 0x631, 0x6cc, 0x3b, 0x645, 0x627, 0x631, 0x686, 0x3b,
+0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x6cc, 0x3b, 0x627,
+0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648,
+0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x62c, 0x646, 0x648, 0x3b, 0x641, 0x628, 0x631, 0x648, 0x631, 0x6cc,
+0x3b, 0x645, 0x627, 0x631, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c,
+0x648, 0x644, 0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628,
+0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x3b, 0x73, 0x74, 0x79, 0x3b, 0x6c, 0x75, 0x74, 0x3b,
+0x6d, 0x61, 0x72, 0x3b, 0x6b, 0x77, 0x69, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x63, 0x7a, 0x65, 0x3b, 0x6c, 0x69, 0x70, 0x3b,
+0x73, 0x69, 0x65, 0x3b, 0x77, 0x72, 0x7a, 0x3b, 0x70, 0x61, 0x17a, 0x3b, 0x6c, 0x69, 0x73, 0x3b, 0x67, 0x72, 0x75, 0x3b,
+0x73, 0x74, 0x79, 0x63, 0x7a, 0x65, 0x144, 0x3b, 0x6c, 0x75, 0x74, 0x79, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x65, 0x63, 0x3b,
+0x6b, 0x77, 0x69, 0x65, 0x63, 0x69, 0x65, 0x144, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x63, 0x7a, 0x65, 0x72, 0x77, 0x69, 0x65,
+0x63, 0x3b, 0x6c, 0x69, 0x70, 0x69, 0x65, 0x63, 0x3b, 0x73, 0x69, 0x65, 0x72, 0x70, 0x69, 0x65, 0x144, 0x3b, 0x77, 0x72,
+0x7a, 0x65, 0x73, 0x69, 0x65, 0x144, 0x3b, 0x70, 0x61, 0x17a, 0x64, 0x7a, 0x69, 0x65, 0x72, 0x6e, 0x69, 0x6b, 0x3b, 0x6c,
+0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x3b, 0x67, 0x72, 0x75, 0x64, 0x7a, 0x69, 0x65, 0x144, 0x3b, 0x53, 0x3b, 0x4c,
+0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b, 0x43, 0x3b, 0x4c, 0x3b, 0x53, 0x3b, 0x57, 0x3b, 0x50, 0x3b, 0x4c, 0x3b, 0x47,
+0x3b, 0x73, 0x74, 0x79, 0x63, 0x7a, 0x6e, 0x69, 0x61, 0x3b, 0x6c, 0x75, 0x74, 0x65, 0x67, 0x6f, 0x3b, 0x6d, 0x61, 0x72,
+0x63, 0x61, 0x3b, 0x6b, 0x77, 0x69, 0x65, 0x74, 0x6e, 0x69, 0x61, 0x3b, 0x6d, 0x61, 0x6a, 0x61, 0x3b, 0x63, 0x7a, 0x65,
+0x72, 0x77, 0x63, 0x61, 0x3b, 0x6c, 0x69, 0x70, 0x63, 0x61, 0x3b, 0x73, 0x69, 0x65, 0x72, 0x70, 0x6e, 0x69, 0x61, 0x3b,
+0x77, 0x72, 0x7a, 0x65, 0x15b, 0x6e, 0x69, 0x61, 0x3b, 0x70, 0x61, 0x17a, 0x64, 0x7a, 0x69, 0x65, 0x72, 0x6e, 0x69, 0x6b,
+0x61, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x61, 0x3b, 0x67, 0x72, 0x75, 0x64, 0x6e, 0x69, 0x61, 0x3b,
+0x73, 0x3b, 0x6c, 0x3b, 0x6d, 0x3b, 0x6b, 0x3b, 0x6d, 0x3b, 0x63, 0x3b, 0x6c, 0x3b, 0x73, 0x3b, 0x77, 0x3b, 0x70, 0x3b,
+0x6c, 0x3b, 0x67, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x76, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x62, 0x72, 0x3b,
+0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x3b,
+0x6f, 0x75, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x7a, 0x3b, 0x6a, 0x61, 0x6e, 0x65, 0x69, 0x72, 0x6f, 0x3b,
+0x66, 0x65, 0x76, 0x65, 0x72, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0xe7, 0x6f, 0x3b, 0x61, 0x62, 0x72, 0x69,
+0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x6f, 0x3b, 0x6a, 0x75, 0x6e, 0x68, 0x6f, 0x3b, 0x6a, 0x75, 0x6c, 0x68, 0x6f, 0x3b, 0x61,
+0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x6f, 0x75, 0x74, 0x75, 0x62,
+0x72, 0x6f, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x64, 0x65, 0x7a, 0x65, 0x6d, 0x62, 0x72, 0x6f,
+0x3b, 0xa1c, 0xa28, 0x3b, 0xa2b, 0xa3c, 0xa30, 0x3b, 0xa2e, 0xa3e, 0xa30, 0xa1a, 0x3b, 0xa05, 0xa2a, 0xa4d, 0xa30, 0xa48, 0x3b, 0xa2e,
+0xa08, 0x3b, 0xa1c, 0xa42, 0xa28, 0x3b, 0xa1c, 0xa41, 0xa32, 0xa3e, 0x3b, 0xa05, 0xa17, 0x3b, 0xa38, 0xa24, 0xa70, 0x3b, 0xa05, 0xa15,
+0xa24, 0xa42, 0x3b, 0xa28, 0xa35, 0xa70, 0x3b, 0xa26, 0xa38, 0xa70, 0x3b, 0xa1c, 0xa28, 0xa35, 0xa30, 0xa40, 0x3b, 0xa2b, 0xa3c, 0xa30,
+0xa35, 0xa30, 0xa40, 0x3b, 0xa2e, 0xa3e, 0xa30, 0xa1a, 0x3b, 0xa05, 0xa2a, 0xa4d, 0xa30, 0xa48, 0xa32, 0x3b, 0xa2e, 0xa08, 0x3b, 0xa1c,
+0xa42, 0xa28, 0x3b, 0xa1c, 0xa41, 0xa32, 0xa3e, 0xa08, 0x3b, 0xa05, 0xa17, 0xa38, 0xa24, 0x3b, 0xa38, 0xa24, 0xa70, 0xa2c, 0xa30, 0x3b,
+0xa05, 0xa15, 0xa24, 0xa42, 0xa2c, 0xa30, 0x3b, 0xa28, 0xa35, 0xa70, 0xa2c, 0xa30, 0x3b, 0xa26, 0xa38, 0xa70, 0xa2c, 0xa30, 0x3b, 0xa1c,
+0x3b, 0xa2b, 0xa3c, 0x3b, 0xa2e, 0xa3e, 0x3b, 0xa05, 0x3b, 0xa2e, 0x3b, 0xa1c, 0xa42, 0x3b, 0xa1c, 0xa41, 0x3b, 0xa05, 0x3b, 0xa38,
+0x3b, 0xa05, 0x3b, 0xa28, 0x3b, 0xa26, 0x3b, 0x62c, 0x646, 0x648, 0x631, 0x6cc, 0x3b, 0x641, 0x631, 0x648, 0x631, 0x6cc, 0x3b, 0x645,
+0x627, 0x631, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x626, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644,
+0x627, 0x626, 0x6cc, 0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628,
+0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x45, 0x6e, 0x65, 0x3b, 0x46, 0x65,
+0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75,
+0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x63, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69,
+0x63, 0x3b, 0x45, 0x6e, 0x65, 0x72, 0x6f, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x7a,
+0x6f, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x6f, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x6f, 0x3b, 0x4a,
+0x75, 0x6c, 0x69, 0x6f, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x69, 0x65, 0x6d, 0x62, 0x72,
+0x65, 0x3b, 0x4f, 0x63, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x4e, 0x6f, 0x76, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b,
+0x44, 0x69, 0x63, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x73, 0x63, 0x68, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x61, 0x76,
+0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x74, 0x67, 0x3b, 0x7a, 0x65,
+0x72, 0x63, 0x6c, 0x2e, 0x3b, 0x66, 0x61, 0x6e, 0x2e, 0x3b, 0x61, 0x76, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x74, 0x74,
+0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x73, 0x63, 0x68,
+0x61, 0x6e, 0x65, 0x72, 0x3b, 0x66, 0x61, 0x76, 0x72, 0x65, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x76, 0x72,
+0x69, 0x67, 0x6c, 0x3b, 0x6d, 0x61, 0x74, 0x67, 0x3b, 0x7a, 0x65, 0x72, 0x63, 0x6c, 0x61, 0x64, 0x75, 0x72, 0x3b, 0x66,
+0x61, 0x6e, 0x61, 0x64, 0x75, 0x72, 0x3b, 0x61, 0x76, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x74, 0x74, 0x65, 0x6d, 0x62,
+0x65, 0x72, 0x3b, 0x6f, 0x63, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b,
+0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x53, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x5a,
+0x3b, 0x46, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x69, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65,
+0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x69, 0x75, 0x6e,
+0x2e, 0x3b, 0x69, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x63,
+0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x69, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69,
+0x65, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x65, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x69, 0x65, 0x3b, 0x61,
+0x70, 0x72, 0x69, 0x6c, 0x69, 0x65, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x69, 0x75, 0x6e, 0x69, 0x65, 0x3b, 0x69, 0x75, 0x6c,
+0x69, 0x65, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x65,
+0x3b, 0x6f, 0x63, 0x74, 0x6f, 0x6d, 0x62, 0x72, 0x69, 0x65, 0x3b, 0x6e, 0x6f, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x65,
+0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x65, 0x3b, 0x49, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d,
+0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x44f, 0x43d, 0x432, 0x2e, 0x3b,
+0x444, 0x435, 0x432, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x439, 0x3b,
+0x438, 0x44e, 0x43d, 0x44c, 0x3b, 0x438, 0x44e, 0x43b, 0x44c, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x2e,
+0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e, 0x3b, 0x44f, 0x43d, 0x432,
+0x2e, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x2e, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430,
+0x44f, 0x3b, 0x438, 0x44e, 0x43d, 0x2e, 0x3b, 0x438, 0x44e, 0x43b, 0x2e, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43d,
0x442, 0x2e, 0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e, 0x3b, 0x44f,
-0x43d, 0x432, 0x2e, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x2e, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b,
-0x43c, 0x430, 0x44f, 0x3b, 0x438, 0x44e, 0x43d, 0x2e, 0x3b, 0x438, 0x44e, 0x43b, 0x2e, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441,
-0x435, 0x43d, 0x442, 0x2e, 0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e,
-0x3b, 0x44f, 0x43d, 0x432, 0x430, 0x440, 0x44f, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x44f, 0x3b, 0x43c, 0x430, 0x440, 0x442,
-0x430, 0x3b, 0x430, 0x43f, 0x440, 0x435, 0x43b, 0x44f, 0x3b, 0x43c, 0x430, 0x44f, 0x3b, 0x438, 0x44e, 0x43d, 0x44f, 0x3b, 0x438, 0x44e,
-0x43b, 0x44f, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x430, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44f, 0x3b,
-0x43e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44f, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x440, 0x44f, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431,
-0x440, 0x44f, 0x3b, 0x4e, 0x79, 0x65, 0x3b, 0x46, 0x75, 0x6c, 0x3b, 0x4d, 0x62, 0xe4, 0x3b, 0x4e, 0x67, 0x75, 0x3b, 0x42,
-0xea, 0x6c, 0x3b, 0x46, 0xf6, 0x6e, 0x3b, 0x4c, 0x65, 0x6e, 0x3b, 0x4b, 0xfc, 0x6b, 0x3b, 0x4d, 0x76, 0x75, 0x3b, 0x4e,
-0x67, 0x62, 0x3b, 0x4e, 0x61, 0x62, 0x3b, 0x4b, 0x61, 0x6b, 0x3b, 0x4e, 0x79, 0x65, 0x6e, 0x79, 0x65, 0x3b, 0x46, 0x75,
-0x6c, 0x75, 0x6e, 0x64, 0xef, 0x67, 0x69, 0x3b, 0x4d, 0x62, 0xe4, 0x6e, 0x67, 0xfc, 0x3b, 0x4e, 0x67, 0x75, 0x62, 0xf9,
-0x65, 0x3b, 0x42, 0xea, 0x6c, 0xe4, 0x77, 0xfc, 0x3b, 0x46, 0xf6, 0x6e, 0x64, 0x6f, 0x3b, 0x4c, 0x65, 0x6e, 0x67, 0x75,
-0x61, 0x3b, 0x4b, 0xfc, 0x6b, 0xfc, 0x72, 0xfc, 0x3b, 0x4d, 0x76, 0x75, 0x6b, 0x61, 0x3b, 0x4e, 0x67, 0x62, 0x65, 0x72,
-0x65, 0x72, 0x65, 0x3b, 0x4e, 0x61, 0x62, 0xe4, 0x6e, 0x64, 0xfc, 0x72, 0x75, 0x3b, 0x4b, 0x61, 0x6b, 0x61, 0x75, 0x6b,
-0x61, 0x3b, 0x4e, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x42, 0x3b, 0x46, 0x3b, 0x4c, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b,
-0x4e, 0x3b, 0x4e, 0x3b, 0x4b, 0x3b, 0x458, 0x430, 0x43d, 0x3b, 0x444, 0x435, 0x431, 0x3b, 0x43c, 0x430, 0x440, 0x3b, 0x430, 0x43f,
-0x440, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x3b, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x3b, 0x441, 0x435,
-0x43f, 0x3b, 0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x432, 0x3b, 0x434, 0x435, 0x446, 0x3b, 0x458, 0x430, 0x43d, 0x443, 0x430, 0x440,
-0x3b, 0x444, 0x435, 0x431, 0x440, 0x443, 0x430, 0x440, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b, 0x3b,
-0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x3b, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441,
-0x435, 0x43f, 0x442, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x431, 0x430, 0x440, 0x3b, 0x43d, 0x43e, 0x432,
-0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x434, 0x435, 0x446, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x458, 0x430, 0x43d, 0x2e, 0x3b,
-0x444, 0x435, 0x431, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458,
-0x443, 0x43d, 0x3b, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x2e, 0x3b, 0x43e, 0x43a,
-0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x432, 0x2e, 0x3b, 0x434, 0x435, 0x446, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65,
-0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e,
-0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e,
-0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65,
+0x43d, 0x432, 0x430, 0x440, 0x44f, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x44f, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x430, 0x3b,
+0x430, 0x43f, 0x440, 0x435, 0x43b, 0x44f, 0x3b, 0x43c, 0x430, 0x44f, 0x3b, 0x438, 0x44e, 0x43d, 0x44f, 0x3b, 0x438, 0x44e, 0x43b, 0x44f,
+0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x430, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44f, 0x3b, 0x43e, 0x43a,
+0x442, 0x44f, 0x431, 0x440, 0x44f, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x440, 0x44f, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x44f,
+0x3b, 0x4e, 0x79, 0x65, 0x3b, 0x46, 0x75, 0x6c, 0x3b, 0x4d, 0x62, 0xe4, 0x3b, 0x4e, 0x67, 0x75, 0x3b, 0x42, 0xea, 0x6c,
+0x3b, 0x46, 0xf6, 0x6e, 0x3b, 0x4c, 0x65, 0x6e, 0x3b, 0x4b, 0xfc, 0x6b, 0x3b, 0x4d, 0x76, 0x75, 0x3b, 0x4e, 0x67, 0x62,
+0x3b, 0x4e, 0x61, 0x62, 0x3b, 0x4b, 0x61, 0x6b, 0x3b, 0x4e, 0x79, 0x65, 0x6e, 0x79, 0x65, 0x3b, 0x46, 0x75, 0x6c, 0x75,
+0x6e, 0x64, 0xef, 0x67, 0x69, 0x3b, 0x4d, 0x62, 0xe4, 0x6e, 0x67, 0xfc, 0x3b, 0x4e, 0x67, 0x75, 0x62, 0xf9, 0x65, 0x3b,
+0x42, 0xea, 0x6c, 0xe4, 0x77, 0xfc, 0x3b, 0x46, 0xf6, 0x6e, 0x64, 0x6f, 0x3b, 0x4c, 0x65, 0x6e, 0x67, 0x75, 0x61, 0x3b,
+0x4b, 0xfc, 0x6b, 0xfc, 0x72, 0xfc, 0x3b, 0x4d, 0x76, 0x75, 0x6b, 0x61, 0x3b, 0x4e, 0x67, 0x62, 0x65, 0x72, 0x65, 0x72,
+0x65, 0x3b, 0x4e, 0x61, 0x62, 0xe4, 0x6e, 0x64, 0xfc, 0x72, 0x75, 0x3b, 0x4b, 0x61, 0x6b, 0x61, 0x75, 0x6b, 0x61, 0x3b,
+0x4e, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x42, 0x3b, 0x46, 0x3b, 0x4c, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b,
+0x4e, 0x3b, 0x4b, 0x3b, 0x458, 0x430, 0x43d, 0x3b, 0x444, 0x435, 0x431, 0x3b, 0x43c, 0x430, 0x440, 0x3b, 0x430, 0x43f, 0x440, 0x3b,
+0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x3b, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x3b, 0x441, 0x435, 0x43f, 0x3b,
+0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x432, 0x3b, 0x434, 0x435, 0x446, 0x3b, 0x458, 0x430, 0x43d, 0x443, 0x430, 0x440, 0x3b, 0x444,
+0x435, 0x431, 0x440, 0x443, 0x430, 0x440, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b, 0x3b, 0x43c, 0x430,
+0x458, 0x3b, 0x458, 0x443, 0x43d, 0x3b, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43f,
+0x442, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x431, 0x430, 0x440, 0x3b, 0x43d, 0x43e, 0x432, 0x435, 0x43c,
+0x431, 0x430, 0x440, 0x3b, 0x434, 0x435, 0x446, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x458, 0x430, 0x43d, 0x3b, 0x444, 0x435, 0x431,
+0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x3b, 0x458, 0x443,
+0x43b, 0x3b, 0x430, 0x432, 0x433, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x3b, 0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x432, 0x3b, 0x434,
+0x435, 0x446, 0x3b, 0x458, 0x430, 0x43d, 0x2e, 0x3b, 0x444, 0x435, 0x431, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f,
+0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x3b, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b,
+0x441, 0x435, 0x43f, 0x442, 0x2e, 0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x432, 0x2e, 0x3b, 0x434, 0x435, 0x446, 0x2e,
+0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61,
+0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x3b, 0x6f,
+0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65,
0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x6a,
0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74,
0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62,
-0x61, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x6a, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x61, 0x3b,
-0x6d, 0x3b, 0x6a, 0x3b, 0x6a, 0x3b, 0x61, 0x3b, 0x73, 0x3b, 0x6f, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 0x6a, 0x61, 0x6e, 0x3b,
-0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b,
-0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b,
-0x64, 0x65, 0x63, 0x3b, 0x42f, 0x43d, 0x432, 0x2e, 0x3b, 0x424, 0x435, 0x432, 0x440, 0x2e, 0x3b, 0x41c, 0x430, 0x440, 0x442, 0x2e,
-0x3b, 0x410, 0x43f, 0x440, 0x2e, 0x3b, 0x41c, 0x430, 0x439, 0x3b, 0x418, 0x44e, 0x43d, 0x44c, 0x3b, 0x418, 0x44e, 0x43b, 0x44c, 0x3b,
-0x410, 0x432, 0x433, 0x2e, 0x3b, 0x421, 0x435, 0x43d, 0x442, 0x2e, 0x3b, 0x41e, 0x43a, 0x442, 0x2e, 0x3b, 0x41d, 0x43e, 0x44f, 0x431,
-0x2e, 0x3b, 0x414, 0x435, 0x43a, 0x2e, 0x3b, 0x42f, 0x43d, 0x432, 0x430, 0x440, 0x44c, 0x3b, 0x424, 0x435, 0x432, 0x440, 0x430, 0x43b,
-0x44c, 0x3b, 0x41c, 0x430, 0x440, 0x442, 0x44a, 0x438, 0x3b, 0x410, 0x43f, 0x440, 0x435, 0x43b, 0x44c, 0x3b, 0x41c, 0x430, 0x439, 0x3b,
-0x418, 0x44e, 0x43d, 0x44c, 0x3b, 0x418, 0x44e, 0x43b, 0x44c, 0x3b, 0x410, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x421, 0x435, 0x43d,
-0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x41e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x41d, 0x43e, 0x44f, 0x431, 0x440, 0x44c,
-0x3b, 0x414, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x44c, 0x3b, 0x44f, 0x43d, 0x432, 0x2e, 0x3b, 0x444, 0x435, 0x432, 0x2e, 0x3b, 0x43c,
-0x430, 0x440, 0x2e, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x439, 0x44b, 0x3b, 0x438, 0x44e, 0x43d, 0x44b, 0x3b, 0x438,
-0x44e, 0x43b, 0x44b, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43d, 0x2e, 0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d,
-0x43e, 0x44f, 0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e, 0x3b, 0x44f, 0x43d, 0x432, 0x430, 0x440, 0x44b, 0x3b, 0x444, 0x435, 0x432, 0x440,
-0x430, 0x43b, 0x44b, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x44a, 0x438, 0x439, 0x44b, 0x3b, 0x430, 0x43f, 0x440, 0x435, 0x43b, 0x44b, 0x3b,
-0x43c, 0x430, 0x439, 0x44b, 0x3b, 0x438, 0x44e, 0x43d, 0x44b, 0x3b, 0x438, 0x44e, 0x43b, 0x44b, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441,
-0x442, 0x44b, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44b, 0x3b, 0x43e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44b, 0x3b,
-0x43d, 0x43e, 0x44f, 0x431, 0x440, 0x44b, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x44b, 0x3b, 0x4e, 0x64, 0x69, 0x3b, 0x4b,
-0x75, 0x6b, 0x3b, 0x4b, 0x75, 0x72, 0x3b, 0x4b, 0x75, 0x62, 0x3b, 0x43, 0x68, 0x76, 0x3b, 0x43, 0x68, 0x6b, 0x3b, 0x43,
-0x68, 0x67, 0x3b, 0x4e, 0x79, 0x61, 0x3b, 0x47, 0x75, 0x6e, 0x3b, 0x47, 0x75, 0x6d, 0x3b, 0x4d, 0x62, 0x75, 0x3b, 0x5a,
-0x76, 0x69, 0x3b, 0x4e, 0x64, 0x69, 0x72, 0x61, 0x3b, 0x4b, 0x75, 0x6b, 0x61, 0x64, 0x7a, 0x69, 0x3b, 0x4b, 0x75, 0x72,
-0x75, 0x6d, 0x65, 0x3b, 0x4b, 0x75, 0x62, 0x76, 0x75, 0x6d, 0x62, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x76, 0x61, 0x62, 0x76,
-0x75, 0x3b, 0x43, 0x68, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x6b, 0x75, 0x6e, 0x67, 0x75, 0x72, 0x75,
-0x3b, 0x4e, 0x79, 0x61, 0x6d, 0x61, 0x76, 0x68, 0x75, 0x76, 0x68, 0x75, 0x3b, 0x47, 0x75, 0x6e, 0x79, 0x61, 0x6e, 0x61,
-0x3b, 0x47, 0x75, 0x6d, 0x69, 0x67, 0x75, 0x72, 0x75, 0x3b, 0x4d, 0x62, 0x75, 0x64, 0x7a, 0x69, 0x3b, 0x5a, 0x76, 0x69,
-0x74, 0x61, 0x3b, 0x4e, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x4e, 0x3b, 0x47,
-0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x5a, 0x3b, 0xda2, 0xdb1, 0x3b, 0xdb4, 0xdd9, 0xdb6, 0x3b, 0xdb8, 0xdcf, 0xdbb, 0xdca, 0x3b, 0xd85,
-0xdb4, 0xdca, 0x200d, 0xdbb, 0xdda, 0xdbd, 0xdca, 0x3b, 0xdb8, 0xdd0, 0xdba, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdb1, 0xdd2, 0x3b, 0xda2, 0xdd6,
-0xdbd, 0xdd2, 0x3b, 0xd85, 0xd9c, 0xddd, 0x3b, 0xdc3, 0xdd0, 0xdb4, 0xdca, 0x3b, 0xd94, 0xd9a, 0xdca, 0x3b, 0xdb1, 0xddc, 0xdc0, 0xdd0,
-0x3b, 0xdaf, 0xdd9, 0xdc3, 0xdd0, 0x3b, 0xda2, 0xdb1, 0xdc0, 0xdcf, 0xdbb, 0xdd2, 0x3b, 0xdb4, 0xdd9, 0xdb6, 0xdbb, 0xdc0, 0xdcf, 0xdbb,
-0xdd2, 0x3b, 0xdb8, 0xdcf, 0xdbb, 0xdca, 0xdad, 0xdd4, 0x3b, 0xd85, 0xdb4, 0xdca, 0x200d, 0xdbb, 0xdda, 0xdbd, 0xdca, 0x3b, 0xdb8, 0xdd0,
-0xdba, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdb1, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdbd, 0xdd2, 0x3b, 0xd85, 0xd9c, 0xddd, 0xdc3, 0xdca, 0xdad, 0xdd4,
-0x3b, 0xdc3, 0xdd0, 0xdb4, 0xdca, 0xdad, 0xdd0, 0xdb8, 0xdca, 0xdb6, 0xdbb, 0xdca, 0x3b, 0xd94, 0xd9a, 0xdca, 0xdad, 0xddd, 0xdb6, 0xdbb,
-0xdca, 0x3b, 0xdb1, 0xddc, 0xdc0, 0xdd0, 0xdb8, 0xdca, 0xdb6, 0xdbb, 0xdca, 0x3b, 0xdaf, 0xdd9, 0xdc3, 0xdd0, 0xdb8, 0xdca, 0xdb6, 0xdbb,
-0xdca, 0x3b, 0xda2, 0x3b, 0xdb4, 0xdd9, 0x3b, 0xdb8, 0xdcf, 0x3b, 0xd85, 0x3b, 0xdb8, 0xdd0, 0x3b, 0xda2, 0xdd6, 0x3b, 0xda2, 0xdd6,
-0x3b, 0xd85, 0x3b, 0xdc3, 0xdd0, 0x3b, 0xd94, 0x3b, 0xdb1, 0xdd9, 0x3b, 0xdaf, 0xdd9, 0x3b, 0xda2, 0xdb1, 0x3b, 0xdb4, 0xdd9, 0xdb6,
-0x3b, 0xdb8, 0xdcf, 0xdbb, 0xdca, 0xdad, 0xdd4, 0x3b, 0xd85, 0xdb4, 0xdca, 0x200d, 0xdbb, 0xdda, 0xdbd, 0xdca, 0x3b, 0xdb8, 0xdd0, 0xdba,
-0xdd2, 0x3b, 0xda2, 0xdd6, 0xdb1, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdbd, 0xdd2, 0x3b, 0xd85, 0xd9c, 0xddd, 0x3b, 0xdc3, 0xdd0, 0xdb4, 0xdca,
-0x3b, 0xd94, 0xd9a, 0xdca, 0x3b, 0xdb1, 0xddc, 0xdc0, 0xdd0, 0x3b, 0xdaf, 0xdd9, 0xdc3, 0xdd0, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66,
-0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0xe1, 0x6a, 0x3b, 0x6a, 0xfa, 0x6e, 0x3b, 0x6a,
-0xfa, 0x6c, 0x3b, 0x61, 0x75, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64,
-0x65, 0x63, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0xe1, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0xe1, 0x72, 0x3b, 0x6d, 0x61,
-0x72, 0x65, 0x63, 0x3b, 0x61, 0x70, 0x72, 0xed, 0x6c, 0x3b, 0x6d, 0xe1, 0x6a, 0x3b, 0x6a, 0xfa, 0x6e, 0x3b, 0x6a, 0xfa,
-0x6c, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f,
-0x6b, 0x74, 0xf3, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65,
-0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0xe1, 0x72, 0x61, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0xe1, 0x72,
-0x61, 0x3b, 0x6d, 0x61, 0x72, 0x63, 0x61, 0x3b, 0x61, 0x70, 0x72, 0xed, 0x6c, 0x61, 0x3b, 0x6d, 0xe1, 0x6a, 0x61, 0x3b,
-0x6a, 0xfa, 0x6e, 0x61, 0x3b, 0x6a, 0xfa, 0x6c, 0x61, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x61, 0x3b, 0x73, 0x65,
-0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x6f, 0x6b, 0x74, 0xf3, 0x62, 0x72, 0x61, 0x3b, 0x6e, 0x6f, 0x76, 0x65,
-0x6d, 0x62, 0x72, 0x61, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66,
-0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75,
-0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x76, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b,
-0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b,
-0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x65, 0x63, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b,
-0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6a, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6a, 0x3b, 0x61, 0x76, 0x67, 0x75,
-0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72,
-0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4b,
-0x6f, 0x62, 0x3b, 0x4c, 0x61, 0x62, 0x3b, 0x53, 0x61, 0x64, 0x3b, 0x41, 0x66, 0x72, 0x3b, 0x53, 0x68, 0x61, 0x3b, 0x4c,
-0x69, 0x78, 0x3b, 0x54, 0x6f, 0x64, 0x3b, 0x53, 0x69, 0x64, 0x3b, 0x53, 0x61, 0x67, 0x3b, 0x54, 0x6f, 0x62, 0x3b, 0x4b,
-0x49, 0x54, 0x3b, 0x4c, 0x49, 0x54, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4b, 0x6f, 0x6f, 0x62, 0x61, 0x61, 0x64,
-0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20,
-0x53, 0x61, 0x64, 0x64, 0x65, 0x78, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x41, 0x66, 0x72, 0x61,
-0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x53, 0x68, 0x61, 0x6e, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73,
-0x68, 0x61, 0x20, 0x4c, 0x69, 0x78, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x54, 0x6f, 0x64, 0x6f,
-0x62, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x53, 0x69, 0x64, 0x65, 0x65, 0x64, 0x61, 0x61, 0x64,
-0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x53, 0x61, 0x67, 0x61, 0x61, 0x6c, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73,
-0x68, 0x61, 0x20, 0x54, 0x6f, 0x62, 0x6e, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4b, 0x6f, 0x77,
-0x20, 0x69, 0x79, 0x6f, 0x20, 0x54, 0x6f, 0x62, 0x6e, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4c,
-0x61, 0x62, 0x61, 0x20, 0x69, 0x79, 0x6f, 0x20, 0x54, 0x6f, 0x62, 0x6e, 0x61, 0x61, 0x64, 0x3b, 0x4b, 0x3b, 0x4c, 0x3b,
-0x53, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4c, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x4c, 0x3b,
-0x65, 0x6e, 0x65, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x62, 0x72, 0x2e, 0x3b,
-0x6d, 0x61, 0x79, 0x2e, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x6f, 0x2e, 0x3b,
-0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x69, 0x63, 0x2e,
-0x3b, 0x65, 0x6e, 0x65, 0x72, 0x6f, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x6f,
-0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x79, 0x6f, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6f, 0x3b, 0x6a, 0x75,
-0x6c, 0x69, 0x6f, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x69, 0x65, 0x6d, 0x62, 0x72,
-0x65, 0x3b, 0x6f, 0x63, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b,
-0x64, 0x69, 0x63, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x45, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b,
-0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x65, 0x6e, 0x65, 0x2e, 0x3b, 0x66,
+0x61, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b,
+0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b,
+0x61, 0x76, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63, 0x3b,
+0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b,
+0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70,
+0x74, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x42f, 0x43d,
+0x432, 0x2e, 0x3b, 0x424, 0x435, 0x432, 0x440, 0x2e, 0x3b, 0x41c, 0x430, 0x440, 0x442, 0x2e, 0x3b, 0x410, 0x43f, 0x440, 0x2e, 0x3b,
+0x41c, 0x430, 0x439, 0x3b, 0x418, 0x44e, 0x43d, 0x44c, 0x3b, 0x418, 0x44e, 0x43b, 0x44c, 0x3b, 0x410, 0x432, 0x433, 0x2e, 0x3b, 0x421,
+0x435, 0x43d, 0x442, 0x2e, 0x3b, 0x41e, 0x43a, 0x442, 0x2e, 0x3b, 0x41d, 0x43e, 0x44f, 0x431, 0x2e, 0x3b, 0x414, 0x435, 0x43a, 0x2e,
+0x3b, 0x42f, 0x43d, 0x432, 0x430, 0x440, 0x44c, 0x3b, 0x424, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x44c, 0x3b, 0x41c, 0x430, 0x440, 0x442,
+0x44a, 0x438, 0x3b, 0x410, 0x43f, 0x440, 0x435, 0x43b, 0x44c, 0x3b, 0x41c, 0x430, 0x439, 0x3b, 0x418, 0x44e, 0x43d, 0x44c, 0x3b, 0x418,
+0x44e, 0x43b, 0x44c, 0x3b, 0x410, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x421, 0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b,
+0x41e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x41d, 0x43e, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x414, 0x435, 0x43a, 0x430, 0x431,
+0x440, 0x44c, 0x3b, 0x44f, 0x43d, 0x432, 0x2e, 0x3b, 0x444, 0x435, 0x432, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x2e, 0x3b, 0x430, 0x43f,
+0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x439, 0x44b, 0x3b, 0x438, 0x44e, 0x43d, 0x44b, 0x3b, 0x438, 0x44e, 0x43b, 0x44b, 0x3b, 0x430, 0x432,
+0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43d, 0x2e, 0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x44f, 0x2e, 0x3b, 0x434, 0x435,
+0x43a, 0x2e, 0x3b, 0x44f, 0x43d, 0x432, 0x430, 0x440, 0x44b, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x44b, 0x3b, 0x43c, 0x430,
+0x440, 0x442, 0x44a, 0x438, 0x439, 0x44b, 0x3b, 0x430, 0x43f, 0x440, 0x435, 0x43b, 0x44b, 0x3b, 0x43c, 0x430, 0x439, 0x44b, 0x3b, 0x438,
+0x44e, 0x43d, 0x44b, 0x3b, 0x438, 0x44e, 0x43b, 0x44b, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x44b, 0x3b, 0x441, 0x435, 0x43d,
+0x442, 0x44f, 0x431, 0x440, 0x44b, 0x3b, 0x43e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44b, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x440, 0x44b,
+0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x44b, 0x3b, 0x4e, 0x64, 0x69, 0x3b, 0x4b, 0x75, 0x6b, 0x3b, 0x4b, 0x75, 0x72,
+0x3b, 0x4b, 0x75, 0x62, 0x3b, 0x43, 0x68, 0x76, 0x3b, 0x43, 0x68, 0x6b, 0x3b, 0x43, 0x68, 0x67, 0x3b, 0x4e, 0x79, 0x61,
+0x3b, 0x47, 0x75, 0x6e, 0x3b, 0x47, 0x75, 0x6d, 0x3b, 0x4d, 0x62, 0x75, 0x3b, 0x5a, 0x76, 0x69, 0x3b, 0x4e, 0x64, 0x69,
+0x72, 0x61, 0x3b, 0x4b, 0x75, 0x6b, 0x61, 0x64, 0x7a, 0x69, 0x3b, 0x4b, 0x75, 0x72, 0x75, 0x6d, 0x65, 0x3b, 0x4b, 0x75,
+0x62, 0x76, 0x75, 0x6d, 0x62, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x76, 0x61, 0x62, 0x76, 0x75, 0x3b, 0x43, 0x68, 0x69, 0x6b,
+0x75, 0x6d, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x6b, 0x75, 0x6e, 0x67, 0x75, 0x72, 0x75, 0x3b, 0x4e, 0x79, 0x61, 0x6d, 0x61,
+0x76, 0x68, 0x75, 0x76, 0x68, 0x75, 0x3b, 0x47, 0x75, 0x6e, 0x79, 0x61, 0x6e, 0x61, 0x3b, 0x47, 0x75, 0x6d, 0x69, 0x67,
+0x75, 0x72, 0x75, 0x3b, 0x4d, 0x62, 0x75, 0x64, 0x7a, 0x69, 0x3b, 0x5a, 0x76, 0x69, 0x74, 0x61, 0x3b, 0x4e, 0x3b, 0x4b,
+0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x4e, 0x3b, 0x47, 0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x5a,
+0x3b, 0x62c, 0x646, 0x648, 0x631, 0x64a, 0x3b, 0x641, 0x64a, 0x628, 0x631, 0x648, 0x631, 0x64a, 0x3b, 0x645, 0x627, 0x631, 0x686, 0x3b,
+0x627, 0x67e, 0x631, 0x64a, 0x644, 0x3b, 0x645, 0x626, 0x64a, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x621, 0x650,
+0x3b, 0x622, 0x6af, 0x633, 0x67d, 0x3b, 0x633, 0x64a, 0x67e, 0x67d, 0x645, 0x628, 0x631, 0x3b, 0x622, 0x6aa, 0x67d, 0x648, 0x628, 0x631,
+0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x68a, 0x633, 0x645, 0x628, 0x631, 0x3b, 0xda2, 0xdb1, 0x3b, 0xdb4, 0xdd9, 0xdb6, 0x3b,
+0xdb8, 0xdcf, 0xdbb, 0xdca, 0x3b, 0xd85, 0xdb4, 0xdca, 0x200d, 0xdbb, 0xdda, 0xdbd, 0xdca, 0x3b, 0xdb8, 0xdd0, 0xdba, 0xdd2, 0x3b, 0xda2,
+0xdd6, 0xdb1, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdbd, 0xdd2, 0x3b, 0xd85, 0xd9c, 0xddd, 0x3b, 0xdc3, 0xdd0, 0xdb4, 0xdca, 0x3b, 0xd94, 0xd9a,
+0xdca, 0x3b, 0xdb1, 0xddc, 0xdc0, 0xdd0, 0x3b, 0xdaf, 0xdd9, 0xdc3, 0xdd0, 0x3b, 0xda2, 0xdb1, 0xdc0, 0xdcf, 0xdbb, 0xdd2, 0x3b, 0xdb4,
+0xdd9, 0xdb6, 0xdbb, 0xdc0, 0xdcf, 0xdbb, 0xdd2, 0x3b, 0xdb8, 0xdcf, 0xdbb, 0xdca, 0xdad, 0xdd4, 0x3b, 0xd85, 0xdb4, 0xdca, 0x200d, 0xdbb,
+0xdda, 0xdbd, 0xdca, 0x3b, 0xdb8, 0xdd0, 0xdba, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdb1, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdbd, 0xdd2, 0x3b, 0xd85,
+0xd9c, 0xddd, 0xdc3, 0xdca, 0xdad, 0xdd4, 0x3b, 0xdc3, 0xdd0, 0xdb4, 0xdca, 0xdad, 0xdd0, 0xdb8, 0xdca, 0xdb6, 0xdbb, 0xdca, 0x3b, 0xd94,
+0xd9a, 0xdca, 0xdad, 0xddd, 0xdb6, 0xdbb, 0xdca, 0x3b, 0xdb1, 0xddc, 0xdc0, 0xdd0, 0xdb8, 0xdca, 0xdb6, 0xdbb, 0xdca, 0x3b, 0xdaf, 0xdd9,
+0xdc3, 0xdd0, 0xdb8, 0xdca, 0xdb6, 0xdbb, 0xdca, 0x3b, 0xda2, 0x3b, 0xdb4, 0xdd9, 0x3b, 0xdb8, 0xdcf, 0x3b, 0xd85, 0x3b, 0xdb8, 0xdd0,
+0x3b, 0xda2, 0xdd6, 0x3b, 0xda2, 0xdd6, 0x3b, 0xd85, 0x3b, 0xdc3, 0xdd0, 0x3b, 0xd94, 0x3b, 0xdb1, 0xdd9, 0x3b, 0xdaf, 0xdd9, 0x3b,
+0xda2, 0xdb1, 0x3b, 0xdb4, 0xdd9, 0xdb6, 0x3b, 0xdb8, 0xdcf, 0xdbb, 0xdca, 0xdad, 0xdd4, 0x3b, 0xd85, 0xdb4, 0xdca, 0x200d, 0xdbb, 0xdda,
+0xdbd, 0xdca, 0x3b, 0xdb8, 0xdd0, 0xdba, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdb1, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdbd, 0xdd2, 0x3b, 0xd85, 0xd9c,
+0xddd, 0x3b, 0xdc3, 0xdd0, 0xdb4, 0xdca, 0x3b, 0xd94, 0xd9a, 0xdca, 0x3b, 0xdb1, 0xddc, 0xdc0, 0xdd0, 0x3b, 0xdaf, 0xdd9, 0xdc3, 0xdd0,
+0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0xe1, 0x6a,
+0x3b, 0x6a, 0xfa, 0x6e, 0x3b, 0x6a, 0xfa, 0x6c, 0x3b, 0x61, 0x75, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74,
+0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0xe1, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72,
+0x75, 0xe1, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x65, 0x63, 0x3b, 0x61, 0x70, 0x72, 0xed, 0x6c, 0x3b, 0x6d, 0xe1, 0x6a, 0x3b,
+0x6a, 0xfa, 0x6e, 0x3b, 0x6a, 0xfa, 0x6c, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65,
+0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0xf3, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65,
+0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0xe1, 0x72, 0x61, 0x3b, 0x66,
+0x65, 0x62, 0x72, 0x75, 0xe1, 0x72, 0x61, 0x3b, 0x6d, 0x61, 0x72, 0x63, 0x61, 0x3b, 0x61, 0x70, 0x72, 0xed, 0x6c, 0x61,
+0x3b, 0x6d, 0xe1, 0x6a, 0x61, 0x3b, 0x6a, 0xfa, 0x6e, 0x61, 0x3b, 0x6a, 0xfa, 0x6c, 0x61, 0x3b, 0x61, 0x75, 0x67, 0x75,
+0x73, 0x74, 0x61, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x6f, 0x6b, 0x74, 0xf3, 0x62, 0x72,
+0x61, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b,
+0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b,
+0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x76, 0x67, 0x2e, 0x3b, 0x73,
+0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a,
+0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x65, 0x63, 0x3b,
+0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6a, 0x3b, 0x6a, 0x75, 0x6c, 0x69,
+0x6a, 0x3b, 0x61, 0x76, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f,
+0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65,
+0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72,
+0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x4a, 0x75, 0x75, 0x6e, 0x3b, 0x4c, 0x75, 0x75, 0x6c, 0x69, 0x79, 0x6f, 0x3b, 0x4f, 0x67,
+0x3b, 0x53, 0x65, 0x62, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x66, 0x3b, 0x44, 0x65, 0x73, 0x3b, 0x4a, 0x61, 0x6e,
+0x6e, 0x61, 0x61, 0x79, 0x6f, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x61, 0x61, 0x79, 0x6f, 0x3b, 0x4d, 0x61, 0x61, 0x72, 0x73,
+0x6f, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x4a, 0x75, 0x75, 0x6e, 0x3b, 0x4c, 0x75,
+0x75, 0x6c, 0x69, 0x79, 0x6f, 0x3b, 0x4f, 0x67, 0x6f, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x62, 0x74, 0x65, 0x6d, 0x62, 0x61,
+0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x3b, 0x4e, 0x6f, 0x66, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b,
+0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a,
+0x3b, 0x4c, 0x3b, 0x4f, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x4b, 0x6f, 0x62, 0x3b, 0x4c, 0x61, 0x62,
+0x3b, 0x53, 0x61, 0x64, 0x3b, 0x41, 0x66, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x4a, 0x75, 0x75, 0x6e, 0x3b, 0x4c, 0x75,
+0x75, 0x6c, 0x69, 0x79, 0x6f, 0x3b, 0x4f, 0x67, 0x3b, 0x53, 0x65, 0x62, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x4f,
+0x6b, 0x74, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x3b, 0x4e, 0x6f, 0x66, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x44, 0x65, 0x63,
+0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4b, 0x6f, 0x6f, 0x62, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61,
+0x20, 0x4c, 0x61, 0x62, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x53, 0x61, 0x64, 0x64, 0x65, 0x78,
+0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x41, 0x66, 0x72, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73,
+0x68, 0x61, 0x20, 0x53, 0x68, 0x61, 0x6e, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4c, 0x69, 0x78,
+0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x54, 0x6f, 0x64, 0x6f, 0x62, 0x61, 0x61, 0x64, 0x3b, 0x42,
+0x69, 0x73, 0x68, 0x61, 0x20, 0x53, 0x69, 0x64, 0x65, 0x65, 0x64, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61,
+0x20, 0x53, 0x61, 0x67, 0x61, 0x61, 0x6c, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x54, 0x6f, 0x62,
+0x6e, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4b, 0x6f, 0x77, 0x20, 0x69, 0x79, 0x6f, 0x20, 0x54,
+0x6f, 0x62, 0x6e, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x20, 0x69, 0x79,
+0x6f, 0x20, 0x54, 0x6f, 0x62, 0x6e, 0x61, 0x61, 0x64, 0x3b, 0x4b, 0x3b, 0x4c, 0x3b, 0x53, 0x3b, 0x41, 0x3b, 0x53, 0x3b,
+0x4c, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x4c, 0x3b, 0x65, 0x6e, 0x65, 0x2e, 0x3b, 0x66,
0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x79, 0x2e, 0x3b, 0x6a,
-0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x6f, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f,
-0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x69, 0x63, 0x2e, 0x3b, 0x65, 0x3b, 0x66, 0x3b, 0x6d, 0x3b,
-0x61, 0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x6a, 0x3b, 0x61, 0x3b, 0x73, 0x3b, 0x6f, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 0x65, 0x6e,
-0x65, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x62, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x6a, 0x75,
-0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x63, 0x74, 0x3b, 0x6e, 0x6f,
-0x76, 0x3b, 0x64, 0x69, 0x63, 0x3b, 0x45, 0x6e, 0x65, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0x61, 0x72, 0x2e,
-0x3b, 0x41, 0x62, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x79, 0x2e, 0x3b, 0x4a, 0x75, 0x6e, 0x2e, 0x3b, 0x4a, 0x75, 0x6c, 0x2e,
-0x3b, 0x41, 0x67, 0x6f, 0x2e, 0x3b, 0x53, 0x65, 0x74, 0x2e, 0x3b, 0x4f, 0x63, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e,
-0x3b, 0x44, 0x69, 0x63, 0x2e, 0x3b, 0x45, 0x6e, 0x65, 0x72, 0x6f, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f, 0x3b,
-0x4d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x6f, 0x3b, 0x4a, 0x75, 0x6e,
-0x69, 0x6f, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x6f, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x69,
-0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x4f, 0x63, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x4e, 0x6f, 0x76, 0x69, 0x65, 0x6d,
-0x62, 0x72, 0x65, 0x3b, 0x44, 0x69, 0x63, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x65, 0x6e, 0x65, 0x2e, 0x3b, 0x66,
-0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x79, 0x2e, 0x3b, 0x6a,
-0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x6f, 0x2e, 0x3b, 0x73, 0x65, 0x74, 0x2e, 0x3b, 0x6f,
-0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x69, 0x63, 0x2e, 0x3b, 0x65, 0x6e, 0x65, 0x72, 0x6f, 0x3b,
-0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b,
-0x6d, 0x61, 0x79, 0x6f, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6f, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6f, 0x3b, 0x61, 0x67, 0x6f,
-0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x75, 0x62, 0x72,
-0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x69, 0x63, 0x69, 0x65, 0x6d, 0x62, 0x72,
-0x65, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65,
-0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b,
-0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65,
-0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x69, 0x3b,
-0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74,
-0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f,
-0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66,
-0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75,
-0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b,
-0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69,
-0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c,
-0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73,
-0x74, 0x69, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72,
-0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0xb9c,
-0xba9, 0x2e, 0x3b, 0xbaa, 0xbbf, 0xbaa, 0xbcd, 0x2e, 0x3b, 0xbae, 0xbbe, 0xbb0, 0xbcd, 0x2e, 0x3b, 0xb8f, 0xbaa, 0xbcd, 0x2e, 0x3b,
-0xbae, 0xbc7, 0x3b, 0xb9c, 0xbc2, 0xba9, 0xbcd, 0x3b, 0xb9c, 0xbc2, 0xbb2, 0xbc8, 0x3b, 0xb86, 0xb95, 0x2e, 0x3b, 0xb9a, 0xbc6, 0xbaa,
-0xbcd, 0x2e, 0x3b, 0xb85, 0xb95, 0xbcd, 0x2e, 0x3b, 0xba8, 0xbb5, 0x2e, 0x3b, 0xb9f, 0xbbf, 0xb9a, 0x2e, 0x3b, 0xb9c, 0xba9, 0xbb5,
-0xbb0, 0xbbf, 0x3b, 0xbaa, 0xbbf, 0xbaa, 0xbcd, 0xbb0, 0xbb5, 0xbb0, 0xbbf, 0x3b, 0xbae, 0xbbe, 0xbb0, 0xbcd, 0xb9a, 0xbcd, 0x3b, 0xb8f,
-0xbaa, 0xbcd, 0xbb0, 0xbb2, 0xbcd, 0x3b, 0xbae, 0xbc7, 0x3b, 0xb9c, 0xbc2, 0xba9, 0xbcd, 0x3b, 0xb9c, 0xbc2, 0xbb2, 0xbc8, 0x3b, 0xb86,
-0xb95, 0xbb8, 0xbcd, 0xb9f, 0xbcd, 0x3b, 0xb9a, 0xbc6, 0xbaa, 0xbcd, 0xb9f, 0xbae, 0xbcd, 0xbaa, 0xbb0, 0xbcd, 0x3b, 0xb85, 0xb95, 0xbcd,
-0xb9f, 0xbcb, 0xbaa, 0xbb0, 0xbcd, 0x3b, 0xba8, 0xbb5, 0xbae, 0xbcd, 0xbaa, 0xbb0, 0xbcd, 0x3b, 0xb9f, 0xbbf, 0xb9a, 0xbae, 0xbcd, 0xbaa,
-0xbb0, 0xbcd, 0x3b, 0xb9c, 0x3b, 0xbaa, 0xbbf, 0x3b, 0xbae, 0xbbe, 0x3b, 0xb8f, 0x3b, 0xbae, 0xbc7, 0x3b, 0xb9c, 0xbc2, 0x3b, 0xb9c,
-0xbc2, 0x3b, 0xb86, 0x3b, 0xb9a, 0xbc6, 0x3b, 0xb85, 0x3b, 0xba8, 0x3b, 0xb9f, 0xbbf, 0x3b, 0xc1c, 0xc28, 0x3b, 0xc2b, 0xc3f, 0xc2c,
-0xc4d, 0xc30, 0x3b, 0xc2e, 0xc3e, 0xc30, 0xc4d, 0xc1a, 0xc3f, 0x3b, 0xc0f, 0xc2a, 0xc4d, 0xc30, 0xc3f, 0x3b, 0xc2e, 0xc47, 0x3b, 0xc1c,
-0xc42, 0xc28, 0xc4d, 0x3b, 0xc1c, 0xc41, 0xc32, 0xc48, 0x3b, 0xc06, 0xc17, 0xc38, 0xc4d, 0xc1f, 0xc41, 0x3b, 0xc38, 0xc46, 0xc2a, 0xc4d,
-0xc1f, 0xc46, 0xc02, 0x3b, 0xc05, 0xc15, 0xc4d, 0xc1f, 0xc4b, 0x3b, 0xc28, 0xc35, 0xc02, 0x3b, 0xc21, 0xc3f, 0xc38, 0xc46, 0xc02, 0x3b,
-0xc1c, 0xc28, 0xc35, 0xc30, 0xc3f, 0x3b, 0xc2b, 0xc3f, 0xc2c, 0xc4d, 0xc30, 0xc35, 0xc30, 0xc3f, 0x3b, 0xc2e, 0xc3e, 0xc30, 0xc4d, 0xc1a,
-0xc3f, 0x3b, 0xc0f, 0xc2a, 0xc4d, 0xc30, 0xc3f, 0xc32, 0xc4d, 0x3b, 0xc2e, 0xc47, 0x3b, 0xc1c, 0xc42, 0xc28, 0xc4d, 0x3b, 0xc1c, 0xc41,
-0xc32, 0xc48, 0x3b, 0xc06, 0xc17, 0xc38, 0xc4d, 0xc1f, 0xc41, 0x3b, 0xc38, 0xc46, 0xc2a, 0xc4d, 0xc1f, 0xc46, 0xc02, 0xc2c, 0xc30, 0xc4d,
-0x3b, 0xc05, 0xc15, 0xc4d, 0xc1f, 0xc4b, 0xc2c, 0xc30, 0xc4d, 0x3b, 0xc28, 0xc35, 0xc02, 0xc2c, 0xc30, 0xc4d, 0x3b, 0xc21, 0xc3f, 0xc38,
-0xc46, 0xc02, 0xc2c, 0xc30, 0xc4d, 0x3b, 0xc1c, 0x3b, 0xc2b, 0xc3f, 0x3b, 0xc2e, 0xc3e, 0x3b, 0xc0f, 0x3b, 0xc2e, 0xc47, 0x3b, 0xc1c,
-0xc42, 0x3b, 0xc1c, 0xc41, 0x3b, 0xc06, 0x3b, 0xc38, 0xc46, 0x3b, 0xc05, 0x3b, 0xc28, 0x3b, 0xc21, 0xc3f, 0x3b, 0xc1c, 0xc28, 0x3b,
-0xc2b, 0xc3f, 0xc2c, 0xc4d, 0xc30, 0x3b, 0xc2e, 0xc3e, 0xc30, 0xc4d, 0xc1a, 0xc3f, 0x3b, 0xc0f, 0xc2a, 0xc4d, 0xc30, 0xc3f, 0x3b, 0xc2e,
-0xc47, 0x3b, 0xc1c, 0xc42, 0xc28, 0xc4d, 0x3b, 0xc1c, 0xc41, 0xc32, 0xc48, 0x3b, 0xc06, 0xc17, 0x3b, 0xc38, 0xc46, 0xc2a, 0xc4d, 0xc1f,
-0xc46, 0xc02, 0x3b, 0xc05, 0xc15, 0xc4d, 0xc1f, 0xc4b, 0x3b, 0xc28, 0xc35, 0xc02, 0x3b, 0xc21, 0xc3f, 0xc38, 0xc46, 0xc02, 0x3b, 0xe21,
-0x2e, 0xe04, 0x2e, 0x3b, 0xe01, 0x2e, 0xe1e, 0x2e, 0x3b, 0xe21, 0xe35, 0x2e, 0xe04, 0x2e, 0x3b, 0xe40, 0xe21, 0x2e, 0xe22, 0x2e,
-0x3b, 0xe1e, 0x2e, 0xe04, 0x2e, 0x3b, 0xe21, 0xe34, 0x2e, 0xe22, 0x2e, 0x3b, 0xe01, 0x2e, 0xe04, 0x2e, 0x3b, 0xe2a, 0x2e, 0xe04,
-0x2e, 0x3b, 0xe01, 0x2e, 0xe22, 0x2e, 0x3b, 0xe15, 0x2e, 0xe04, 0x2e, 0x3b, 0xe1e, 0x2e, 0xe22, 0x2e, 0x3b, 0xe18, 0x2e, 0xe04,
-0x2e, 0x3b, 0xe21, 0xe01, 0xe23, 0xe32, 0xe04, 0xe21, 0x3b, 0xe01, 0xe38, 0xe21, 0xe20, 0xe32, 0xe1e, 0xe31, 0xe19, 0xe18, 0xe4c, 0x3b,
-0xe21, 0xe35, 0xe19, 0xe32, 0xe04, 0xe21, 0x3b, 0xe40, 0xe21, 0xe29, 0xe32, 0xe22, 0xe19, 0x3b, 0xe1e, 0xe24, 0xe29, 0xe20, 0xe32, 0xe04,
-0xe21, 0x3b, 0xe21, 0xe34, 0xe16, 0xe38, 0xe19, 0xe32, 0xe22, 0xe19, 0x3b, 0xe01, 0xe23, 0xe01, 0xe0e, 0xe32, 0xe04, 0xe21, 0x3b, 0xe2a,
-0xe34, 0xe07, 0xe2b, 0xe32, 0xe04, 0xe21, 0x3b, 0xe01, 0xe31, 0xe19, 0xe22, 0xe32, 0xe22, 0xe19, 0x3b, 0xe15, 0xe38, 0xe25, 0xe32, 0xe04,
-0xe21, 0x3b, 0xe1e, 0xe24, 0xe28, 0xe08, 0xe34, 0xe01, 0xe32, 0xe22, 0xe19, 0x3b, 0xe18, 0xe31, 0xe19, 0xe27, 0xe32, 0xe04, 0xe21, 0x3b,
-0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xf44, 0xf0b, 0xf54, 0xf7c, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf42, 0xf49, 0xf72,
-0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf42, 0xf66, 0xf74, 0xf58, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3,
-0xf0b, 0xf56, 0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf63, 0xf94, 0xf0b, 0xf54, 0xf0b,
-0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xfb2, 0xf74, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56,
-0xf51, 0xf74, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1, 0xf51, 0xf0b, 0xf54, 0xf0b,
-0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xf42, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45,
-0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf45, 0xf72, 0xf42, 0xf0b, 0xf54,
-0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f,
-0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xf44, 0xf0b, 0xf54, 0xf7c, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b,
-0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf42, 0xf66, 0xf74, 0xf58, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56,
-0xf5e, 0xf72, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf63, 0xf94, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b,
-0xf51, 0xfb2, 0xf74, 0xf42, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf51, 0xf74, 0xf53, 0xf0b, 0xf54, 0x3b, 0xf5f,
-0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1, 0xf51, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xf42, 0xf74,
-0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56,
-0xf45, 0xf74, 0xf0b, 0xf42, 0xf45, 0xf72, 0xf42, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42,
-0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0x3b, 0x1325, 0x122a, 0x3b, 0x1208, 0x12ab, 0x3b, 0x1218, 0x130b, 0x3b, 0x121a, 0x12eb, 0x3b, 0x130d, 0x1295,
-0x3b, 0x1230, 0x1290, 0x3b, 0x1213, 0x121d, 0x3b, 0x1290, 0x1213, 0x3b, 0x1218, 0x1235, 0x3b, 0x1325, 0x1245, 0x3b, 0x1215, 0x12f3, 0x3b, 0x1273,
-0x1215, 0x3b, 0x1325, 0x122a, 0x3b, 0x1208, 0x12ab, 0x1272, 0x1275, 0x3b, 0x1218, 0x130b, 0x1262, 0x1275, 0x3b, 0x121a, 0x12eb, 0x12dd, 0x12eb, 0x3b,
-0x130d, 0x1295, 0x1266, 0x1275, 0x3b, 0x1230, 0x1290, 0x3b, 0x1213, 0x121d, 0x1208, 0x3b, 0x1290, 0x1213, 0x1230, 0x3b, 0x1218, 0x1235, 0x12a8, 0x1228,
-0x121d, 0x3b, 0x1325, 0x1245, 0x121d, 0x1272, 0x3b, 0x1215, 0x12f3, 0x122d, 0x3b, 0x1273, 0x1215, 0x1233, 0x1235, 0x3b, 0x1325, 0x3b, 0x1208, 0x3b,
-0x1218, 0x3b, 0x121a, 0x3b, 0x130d, 0x3b, 0x1230, 0x3b, 0x1213, 0x3b, 0x1290, 0x3b, 0x1218, 0x3b, 0x1325, 0x3b, 0x1215, 0x3b, 0x1273, 0x3b,
-0x53, 0x101, 0x6e, 0x3b, 0x46, 0x113, 0x70, 0x3b, 0x4d, 0x61, 0x2bb, 0x61, 0x3b, 0x2bb, 0x45, 0x70, 0x65, 0x3b, 0x4d, 0x113,
-0x3b, 0x53, 0x75, 0x6e, 0x3b, 0x53, 0x69, 0x75, 0x3b, 0x2bb, 0x41, 0x6f, 0x6b, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x2bb, 0x4f,
-0x6b, 0x61, 0x3b, 0x4e, 0x14d, 0x76, 0x3b, 0x54, 0x12b, 0x73, 0x3b, 0x53, 0x101, 0x6e, 0x75, 0x61, 0x6c, 0x69, 0x3b, 0x46,
-0x113, 0x70, 0x75, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x61, 0x2bb, 0x61, 0x73, 0x69, 0x3b, 0x2bb, 0x45, 0x70, 0x65, 0x6c, 0x65,
-0x6c, 0x69, 0x3b, 0x4d, 0x113, 0x3b, 0x53, 0x75, 0x6e, 0x65, 0x3b, 0x53, 0x69, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x2bb, 0x41,
-0x6f, 0x6b, 0x6f, 0x73, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x69, 0x74, 0x65, 0x6d, 0x61, 0x3b, 0x2bb, 0x4f, 0x6b, 0x61, 0x74,
-0x6f, 0x70, 0x61, 0x3b, 0x4e, 0x14d, 0x76, 0x65, 0x6d, 0x61, 0x3b, 0x54, 0x12b, 0x73, 0x65, 0x6d, 0x61, 0x3b, 0x53, 0x3b,
-0x46, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b,
-0x54, 0x3b, 0x4f, 0x63, 0x61, 0x3b, 0x15e, 0x75, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4e, 0x69, 0x73, 0x3b, 0x4d, 0x61,
-0x79, 0x3b, 0x48, 0x61, 0x7a, 0x3b, 0x54, 0x65, 0x6d, 0x3b, 0x41, 0x11f, 0x75, 0x3b, 0x45, 0x79, 0x6c, 0x3b, 0x45, 0x6b,
-0x69, 0x3b, 0x4b, 0x61, 0x73, 0x3b, 0x41, 0x72, 0x61, 0x3b, 0x4f, 0x63, 0x61, 0x6b, 0x3b, 0x15e, 0x75, 0x62, 0x61, 0x74,
-0x3b, 0x4d, 0x61, 0x72, 0x74, 0x3b, 0x4e, 0x69, 0x73, 0x61, 0x6e, 0x3b, 0x4d, 0x61, 0x79, 0x131, 0x73, 0x3b, 0x48, 0x61,
-0x7a, 0x69, 0x72, 0x61, 0x6e, 0x3b, 0x54, 0x65, 0x6d, 0x6d, 0x75, 0x7a, 0x3b, 0x41, 0x11f, 0x75, 0x73, 0x74, 0x6f, 0x73,
-0x3b, 0x45, 0x79, 0x6c, 0xfc, 0x6c, 0x3b, 0x45, 0x6b, 0x69, 0x6d, 0x3b, 0x4b, 0x61, 0x73, 0x131, 0x6d, 0x3b, 0x41, 0x72,
-0x61, 0x6c, 0x131, 0x6b, 0x3b, 0x4f, 0x3b, 0x15e, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x41,
-0x3b, 0x45, 0x3b, 0x45, 0x3b, 0x4b, 0x3b, 0x41, 0x3b, 0xfd, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x77, 0x3b, 0x6d, 0x61, 0x72,
-0x74, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0xfd, 0x3b, 0x69, 0xfd, 0x75, 0x6e, 0x3b, 0x69, 0xfd, 0x75, 0x6c, 0x3b,
-0x61, 0x77, 0x67, 0x3b, 0x73, 0x65, 0x6e, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0xfd, 0x3b, 0x64, 0x65, 0x6b, 0x3b,
-0xfd, 0x61, 0x6e, 0x77, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x77, 0x72, 0x61, 0x6c, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61,
-0x70, 0x72, 0x65, 0x6c, 0x3b, 0x6d, 0x61, 0xfd, 0x3b, 0x69, 0xfd, 0x75, 0x6e, 0x3b, 0x69, 0xfd, 0x75, 0x6c, 0x3b, 0x61,
-0x77, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x6e, 0x74, 0xfd, 0x61, 0x62, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0xfd, 0x61,
-0x62, 0x72, 0x3b, 0x6e, 0x6f, 0xfd, 0x61, 0x62, 0x72, 0x3b, 0x64, 0x65, 0x6b, 0x61, 0x62, 0x72, 0x3b, 0xdd, 0x3b, 0x46,
-0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44,
-0x3b, 0x64a, 0x627, 0x646, 0x6cb, 0x627, 0x631, 0x3b, 0x641, 0x6d0, 0x6cb, 0x631, 0x627, 0x644, 0x3b, 0x645, 0x627, 0x631, 0x62a, 0x3b,
-0x626, 0x627, 0x67e, 0x631, 0x6d0, 0x644, 0x3b, 0x645, 0x627, 0x64a, 0x3b, 0x626, 0x649, 0x64a, 0x6c7, 0x646, 0x3b, 0x626, 0x649, 0x64a,
-0x6c7, 0x644, 0x3b, 0x626, 0x627, 0x6cb, 0x63a, 0x6c7, 0x633, 0x62a, 0x3b, 0x633, 0x6d0, 0x646, 0x62a, 0x6d5, 0x628, 0x649, 0x631, 0x3b,
-0x626, 0x6c6, 0x643, 0x62a, 0x6d5, 0x628, 0x649, 0x631, 0x3b, 0x646, 0x648, 0x64a, 0x627, 0x628, 0x649, 0x631, 0x3b, 0x62f, 0x6d0, 0x643,
-0x627, 0x628, 0x649, 0x631, 0x3b, 0x441, 0x456, 0x447, 0x3b, 0x43b, 0x44e, 0x442, 0x3b, 0x431, 0x435, 0x440, 0x3b, 0x43a, 0x432, 0x456,
-0x3b, 0x442, 0x440, 0x430, 0x3b, 0x447, 0x435, 0x440, 0x3b, 0x43b, 0x438, 0x43f, 0x3b, 0x441, 0x435, 0x440, 0x3b, 0x432, 0x435, 0x440,
-0x3b, 0x436, 0x43e, 0x432, 0x3b, 0x43b, 0x438, 0x441, 0x3b, 0x433, 0x440, 0x443, 0x3b, 0x441, 0x456, 0x447, 0x435, 0x43d, 0x44c, 0x3b,
-0x43b, 0x44e, 0x442, 0x438, 0x439, 0x3b, 0x431, 0x435, 0x440, 0x435, 0x437, 0x435, 0x43d, 0x44c, 0x3b, 0x43a, 0x432, 0x456, 0x442, 0x435,
-0x43d, 0x44c, 0x3b, 0x442, 0x440, 0x430, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x447, 0x435, 0x440, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x43b,
-0x438, 0x43f, 0x435, 0x43d, 0x44c, 0x3b, 0x441, 0x435, 0x440, 0x43f, 0x435, 0x43d, 0x44c, 0x3b, 0x432, 0x435, 0x440, 0x435, 0x441, 0x435,
-0x43d, 0x44c, 0x3b, 0x436, 0x43e, 0x432, 0x442, 0x435, 0x43d, 0x44c, 0x3b, 0x43b, 0x438, 0x441, 0x442, 0x43e, 0x43f, 0x430, 0x434, 0x3b,
-0x433, 0x440, 0x443, 0x434, 0x435, 0x43d, 0x44c, 0x3b, 0x421, 0x3b, 0x41b, 0x3b, 0x411, 0x3b, 0x41a, 0x3b, 0x422, 0x3b, 0x427, 0x3b,
-0x41b, 0x3b, 0x421, 0x3b, 0x412, 0x3b, 0x416, 0x3b, 0x41b, 0x3b, 0x413, 0x3b, 0x441, 0x456, 0x447, 0x2e, 0x3b, 0x43b, 0x44e, 0x442,
-0x2e, 0x3b, 0x431, 0x435, 0x440, 0x2e, 0x3b, 0x43a, 0x432, 0x456, 0x442, 0x2e, 0x3b, 0x442, 0x440, 0x430, 0x432, 0x2e, 0x3b, 0x447,
-0x435, 0x440, 0x432, 0x2e, 0x3b, 0x43b, 0x438, 0x43f, 0x2e, 0x3b, 0x441, 0x435, 0x440, 0x43f, 0x2e, 0x3b, 0x432, 0x435, 0x440, 0x2e,
-0x3b, 0x436, 0x43e, 0x432, 0x442, 0x2e, 0x3b, 0x43b, 0x438, 0x441, 0x442, 0x2e, 0x3b, 0x433, 0x440, 0x443, 0x434, 0x2e, 0x3b, 0x441,
-0x456, 0x447, 0x43d, 0x44f, 0x3b, 0x43b, 0x44e, 0x442, 0x43e, 0x433, 0x43e, 0x3b, 0x431, 0x435, 0x440, 0x435, 0x437, 0x43d, 0x44f, 0x3b,
-0x43a, 0x432, 0x456, 0x442, 0x43d, 0x44f, 0x3b, 0x442, 0x440, 0x430, 0x432, 0x43d, 0x44f, 0x3b, 0x447, 0x435, 0x440, 0x432, 0x43d, 0x44f,
-0x3b, 0x43b, 0x438, 0x43f, 0x43d, 0x44f, 0x3b, 0x441, 0x435, 0x440, 0x43f, 0x43d, 0x44f, 0x3b, 0x432, 0x435, 0x440, 0x435, 0x441, 0x43d,
-0x44f, 0x3b, 0x436, 0x43e, 0x432, 0x442, 0x43d, 0x44f, 0x3b, 0x43b, 0x438, 0x441, 0x442, 0x43e, 0x43f, 0x430, 0x434, 0x430, 0x3b, 0x433,
-0x440, 0x443, 0x434, 0x43d, 0x44f, 0x3b, 0x441, 0x3b, 0x43b, 0x3b, 0x431, 0x3b, 0x43a, 0x3b, 0x442, 0x3b, 0x447, 0x3b, 0x43b, 0x3b,
-0x441, 0x3b, 0x432, 0x3b, 0x436, 0x3b, 0x43b, 0x3b, 0x433, 0x3b, 0x62c, 0x646, 0x648, 0x631, 0x6cc, 0x3b, 0x641, 0x631, 0x648, 0x631,
-0x6cc, 0x3b, 0x645, 0x627, 0x631, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x626, 0x6cc, 0x3b, 0x62c, 0x648, 0x646,
-0x3b, 0x62c, 0x648, 0x644, 0x627, 0x626, 0x6cc, 0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627,
-0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x59, 0x61,
-0x6e, 0x3b, 0x46, 0x65, 0x76, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x49, 0x79,
-0x6e, 0x3b, 0x49, 0x79, 0x6c, 0x3b, 0x41, 0x76, 0x67, 0x3b, 0x53, 0x65, 0x6e, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f,
-0x79, 0x3b, 0x44, 0x65, 0x6b, 0x3b, 0x59, 0x61, 0x6e, 0x76, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x76, 0x72, 0x61, 0x6c, 0x3b,
-0x4d, 0x61, 0x72, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x49, 0x79, 0x75, 0x6e, 0x3b,
-0x49, 0x79, 0x75, 0x6c, 0x3b, 0x41, 0x76, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x6e, 0x74, 0x61, 0x62, 0x72, 0x3b,
-0x4f, 0x6b, 0x74, 0x61, 0x62, 0x72, 0x3b, 0x4e, 0x6f, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x44, 0x65, 0x6b, 0x61, 0x62, 0x72,
-0x3b, 0x59, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f,
-0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x79, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x76, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72,
-0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x69, 0x79, 0x6e, 0x3b, 0x69, 0x79, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x3b, 0x73, 0x65, 0x6e,
-0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x79, 0x3b, 0x64, 0x65, 0x6b, 0x3b, 0x79, 0x61, 0x6e, 0x76, 0x61, 0x72, 0x3b,
-0x66, 0x65, 0x76, 0x72, 0x61, 0x6c, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x6d, 0x61,
-0x79, 0x3b, 0x69, 0x79, 0x75, 0x6e, 0x3b, 0x69, 0x79, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73,
-0x65, 0x6e, 0x74, 0x61, 0x62, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x61, 0x62, 0x72, 0x3b, 0x6e, 0x6f, 0x79, 0x61, 0x62, 0x72,
-0x3b, 0x64, 0x65, 0x6b, 0x61, 0x62, 0x72, 0x3b, 0x62c, 0x646, 0x648, 0x3b, 0x641, 0x628, 0x631, 0x3b, 0x645, 0x627, 0x631, 0x3b,
-0x627, 0x67e, 0x631, 0x3b, 0x645, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x3b, 0x627, 0x6af, 0x633, 0x3b, 0x633,
-0x67e, 0x62a, 0x3b, 0x627, 0x6a9, 0x62a, 0x3b, 0x646, 0x648, 0x645, 0x3b, 0x62f, 0x633, 0x645, 0x3b, 0x42f, 0x43d, 0x432, 0x430, 0x440,
-0x3b, 0x424, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x3b, 0x41c, 0x430, 0x440, 0x442, 0x3b, 0x410, 0x43f, 0x440, 0x435, 0x43b, 0x3b, 0x41c,
-0x430, 0x439, 0x3b, 0x418, 0x44e, 0x43d, 0x3b, 0x418, 0x44e, 0x43b, 0x3b, 0x410, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x421, 0x435,
-0x43d, 0x442, 0x44f, 0x431, 0x440, 0x3b, 0x41e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x3b, 0x41d, 0x43e, 0x44f, 0x431, 0x440, 0x3b, 0x414,
-0x435, 0x43a, 0x430, 0x431, 0x440, 0x3b, 0x44f, 0x43d, 0x432, 0x3b, 0x444, 0x435, 0x432, 0x3b, 0x43c, 0x430, 0x440, 0x3b, 0x430, 0x43f,
-0x440, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x44e, 0x43d, 0x3b, 0x438, 0x44e, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x3b, 0x441, 0x435,
-0x43d, 0x3b, 0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x44f, 0x3b, 0x434, 0x435, 0x43a, 0x3b, 0x44f, 0x43d, 0x432, 0x430, 0x440, 0x3b,
-0x444, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x435, 0x43b, 0x3b, 0x43c, 0x430,
-0x439, 0x3b, 0x438, 0x44e, 0x43d, 0x3b, 0x438, 0x44e, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43d,
-0x442, 0x44f, 0x431, 0x440, 0x3b, 0x43e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x440, 0x3b, 0x434, 0x435,
-0x43a, 0x430, 0x431, 0x440, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x31, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x32, 0x3b, 0x54, 0x68, 0x67,
-0x20, 0x33, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x34, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x35, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x36,
-0x3b, 0x54, 0x68, 0x67, 0x20, 0x37, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x38, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x39, 0x3b, 0x54,
-0x68, 0x67, 0x20, 0x31, 0x30, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x31, 0x31, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x31, 0x32, 0x3b,
-0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x32, 0x3b, 0x54, 0x68, 0xe1, 0x6e,
-0x67, 0x20, 0x33, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x34, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x35, 0x3b,
-0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x36, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x37, 0x3b, 0x54, 0x68, 0xe1, 0x6e,
-0x67, 0x20, 0x38, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x39, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31, 0x30,
-0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31, 0x31, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31, 0x32, 0x3b, 0x74,
-0x68, 0x67, 0x20, 0x31, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x32, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x33, 0x3b, 0x74, 0x68, 0x67,
-0x20, 0x34, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x35, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x36, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x37,
-0x3b, 0x74, 0x68, 0x67, 0x20, 0x38, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x39, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x31, 0x30, 0x3b,
-0x74, 0x68, 0x67, 0x20, 0x31, 0x31, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x31, 0x32, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20,
-0x31, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x32, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x33, 0x3b, 0x74, 0x68,
-0xe1, 0x6e, 0x67, 0x20, 0x34, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x35, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20,
-0x36, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x37, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x38, 0x3b, 0x74, 0x68,
-0xe1, 0x6e, 0x67, 0x20, 0x39, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31, 0x30, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67,
-0x20, 0x31, 0x31, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31, 0x32, 0x3b, 0x49, 0x6f, 0x6e, 0x3b, 0x43, 0x68, 0x77,
+0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x6f, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b,
+0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x69, 0x63, 0x2e, 0x3b, 0x65, 0x6e, 0x65, 0x72, 0x6f,
+0x3b, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c,
+0x3b, 0x6d, 0x61, 0x79, 0x6f, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6f, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6f, 0x3b, 0x61, 0x67,
+0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x75,
+0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x69, 0x63, 0x69, 0x65, 0x6d,
+0x62, 0x72, 0x65, 0x3b, 0x45, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b,
+0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x65, 0x6e, 0x65, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61,
+0x72, 0x2e, 0x3b, 0x61, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x79, 0x2e, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75,
+0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x6f, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f,
+0x76, 0x2e, 0x3b, 0x64, 0x69, 0x63, 0x2e, 0x3b, 0x65, 0x6e, 0x65, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b,
+0x61, 0x62, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x67, 0x6f, 0x3b,
+0x73, 0x65, 0x70, 0x3b, 0x6f, 0x63, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x69, 0x63, 0x3b, 0x45, 0x6e, 0x65, 0x2e,
+0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0x61, 0x72, 0x2e, 0x3b, 0x41, 0x62, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x79, 0x2e,
+0x3b, 0x4a, 0x75, 0x6e, 0x2e, 0x3b, 0x4a, 0x75, 0x6c, 0x2e, 0x3b, 0x41, 0x67, 0x6f, 0x2e, 0x3b, 0x53, 0x65, 0x74, 0x2e,
+0x3b, 0x4f, 0x63, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x69, 0x63, 0x2e, 0x3b, 0x65, 0x6e, 0x65, 0x2e,
+0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x79, 0x2e,
+0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x6f, 0x2e, 0x3b, 0x73, 0x65, 0x74, 0x2e,
+0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x69, 0x63, 0x2e, 0x3b, 0x65, 0x6e, 0x65, 0x72,
+0x6f, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x61, 0x62, 0x72, 0x69,
+0x6c, 0x3b, 0x6d, 0x61, 0x79, 0x6f, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6f, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6f, 0x3b, 0x61,
+0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x75,
+0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x69, 0x63, 0x69, 0x65, 0x6d,
+0x62, 0x72, 0x65, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x3b,
+0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x70, 0x3b,
+0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b,
+0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c,
+0x69, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x41, 0x67, 0x6f,
+0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b,
+0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x6a, 0x61, 0x6e, 0x2e,
+0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x6a, 0x3b,
+0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b,
+0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61,
+0x72, 0x69, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72,
+0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67,
+0x75, 0x73, 0x74, 0x69, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62,
+0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72,
+0x3b, 0x42f, 0x43d, 0x432, 0x430, 0x440, 0x3b, 0x424, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x3b, 0x41c, 0x430, 0x440, 0x442, 0x3b, 0x410,
+0x43f, 0x440, 0x435, 0x43b, 0x3b, 0x41c, 0x430, 0x439, 0x3b, 0x418, 0x44e, 0x43d, 0x3b, 0x418, 0x44e, 0x43b, 0x3b, 0x410, 0x432, 0x433,
+0x443, 0x441, 0x442, 0x3b, 0x421, 0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x3b, 0x41e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x3b, 0x41d,
+0x43e, 0x44f, 0x431, 0x440, 0x3b, 0x414, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x3b, 0xb9c, 0xba9, 0x2e, 0x3b, 0xbaa, 0xbbf, 0xbaa, 0xbcd,
+0x2e, 0x3b, 0xbae, 0xbbe, 0xbb0, 0xbcd, 0x2e, 0x3b, 0xb8f, 0xbaa, 0xbcd, 0x2e, 0x3b, 0xbae, 0xbc7, 0x3b, 0xb9c, 0xbc2, 0xba9, 0xbcd,
+0x3b, 0xb9c, 0xbc2, 0xbb2, 0xbc8, 0x3b, 0xb86, 0xb95, 0x2e, 0x3b, 0xb9a, 0xbc6, 0xbaa, 0xbcd, 0x2e, 0x3b, 0xb85, 0xb95, 0xbcd, 0x2e,
+0x3b, 0xba8, 0xbb5, 0x2e, 0x3b, 0xb9f, 0xbbf, 0xb9a, 0x2e, 0x3b, 0xb9c, 0xba9, 0xbb5, 0xbb0, 0xbbf, 0x3b, 0xbaa, 0xbbf, 0xbaa, 0xbcd,
+0xbb0, 0xbb5, 0xbb0, 0xbbf, 0x3b, 0xbae, 0xbbe, 0xbb0, 0xbcd, 0xb9a, 0xbcd, 0x3b, 0xb8f, 0xbaa, 0xbcd, 0xbb0, 0xbb2, 0xbcd, 0x3b, 0xbae,
+0xbc7, 0x3b, 0xb9c, 0xbc2, 0xba9, 0xbcd, 0x3b, 0xb9c, 0xbc2, 0xbb2, 0xbc8, 0x3b, 0xb86, 0xb95, 0xbb8, 0xbcd, 0xb9f, 0xbcd, 0x3b, 0xb9a,
+0xbc6, 0xbaa, 0xbcd, 0xb9f, 0xbae, 0xbcd, 0xbaa, 0xbb0, 0xbcd, 0x3b, 0xb85, 0xb95, 0xbcd, 0xb9f, 0xbcb, 0xbaa, 0xbb0, 0xbcd, 0x3b, 0xba8,
+0xbb5, 0xbae, 0xbcd, 0xbaa, 0xbb0, 0xbcd, 0x3b, 0xb9f, 0xbbf, 0xb9a, 0xbae, 0xbcd, 0xbaa, 0xbb0, 0xbcd, 0x3b, 0xb9c, 0x3b, 0xbaa, 0xbbf,
+0x3b, 0xbae, 0xbbe, 0x3b, 0xb8f, 0x3b, 0xbae, 0xbc7, 0x3b, 0xb9c, 0xbc2, 0x3b, 0xb9c, 0xbc2, 0x3b, 0xb86, 0x3b, 0xb9a, 0xbc6, 0x3b,
+0xb85, 0x3b, 0xba8, 0x3b, 0xb9f, 0xbbf, 0x3b, 0x433, 0x44b, 0x439, 0x43d, 0x2e, 0x3b, 0x444, 0x435, 0x432, 0x2e, 0x3b, 0x43c, 0x430,
+0x440, 0x2e, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x44e, 0x43d, 0x44c, 0x3b, 0x438, 0x44e, 0x43b,
+0x44c, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x2e, 0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e,
+0x44f, 0x431, 0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e, 0x3b, 0x433, 0x44b, 0x439, 0x43d, 0x432, 0x430, 0x440, 0x3b, 0x444, 0x435, 0x432,
+0x440, 0x430, 0x43b, 0x44c, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x435, 0x43b, 0x44c, 0x3b, 0x43c, 0x430, 0x439,
+0x3b, 0x438, 0x44e, 0x43d, 0x44c, 0x3b, 0x438, 0x44e, 0x43b, 0x44c, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435,
+0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x43e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x440,
+0x44c, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x44c, 0x3b, 0xc1c, 0xc28, 0x3b, 0xc2b, 0xc3f, 0xc2c, 0xc4d, 0xc30, 0x3b, 0xc2e,
+0xc3e, 0xc30, 0xc4d, 0xc1a, 0xc3f, 0x3b, 0xc0f, 0xc2a, 0xc4d, 0xc30, 0xc3f, 0x3b, 0xc2e, 0xc47, 0x3b, 0xc1c, 0xc42, 0xc28, 0xc4d, 0x3b,
+0xc1c, 0xc41, 0xc32, 0xc48, 0x3b, 0xc06, 0xc17, 0x3b, 0xc38, 0xc46, 0xc2a, 0xc4d, 0xc1f, 0xc46, 0xc02, 0x3b, 0xc05, 0xc15, 0xc4d, 0xc1f,
+0xc4b, 0x3b, 0xc28, 0xc35, 0xc02, 0x3b, 0xc21, 0xc3f, 0xc38, 0xc46, 0xc02, 0x3b, 0xc1c, 0xc28, 0xc35, 0xc30, 0xc3f, 0x3b, 0xc2b, 0xc3f,
+0xc2c, 0xc4d, 0xc30, 0xc35, 0xc30, 0xc3f, 0x3b, 0xc2e, 0xc3e, 0xc30, 0xc4d, 0xc1a, 0xc3f, 0x3b, 0xc0f, 0xc2a, 0xc4d, 0xc30, 0xc3f, 0xc32,
+0xc4d, 0x3b, 0xc2e, 0xc47, 0x3b, 0xc1c, 0xc42, 0xc28, 0xc4d, 0x3b, 0xc1c, 0xc41, 0xc32, 0xc48, 0x3b, 0xc06, 0xc17, 0xc38, 0xc4d, 0xc1f,
+0xc41, 0x3b, 0xc38, 0xc46, 0xc2a, 0xc4d, 0xc1f, 0xc46, 0xc02, 0xc2c, 0xc30, 0xc4d, 0x3b, 0xc05, 0xc15, 0xc4d, 0xc1f, 0xc4b, 0xc2c, 0xc30,
+0xc4d, 0x3b, 0xc28, 0xc35, 0xc02, 0xc2c, 0xc30, 0xc4d, 0x3b, 0xc21, 0xc3f, 0xc38, 0xc46, 0xc02, 0xc2c, 0xc30, 0xc4d, 0x3b, 0xc1c, 0x3b,
+0xc2b, 0xc3f, 0x3b, 0xc2e, 0xc3e, 0x3b, 0xc0f, 0x3b, 0xc2e, 0xc47, 0x3b, 0xc1c, 0xc42, 0x3b, 0xc1c, 0xc41, 0x3b, 0xc06, 0x3b, 0xc38,
+0xc46, 0x3b, 0xc05, 0x3b, 0xc28, 0x3b, 0xc21, 0xc3f, 0x3b, 0xe21, 0x2e, 0xe04, 0x2e, 0x3b, 0xe01, 0x2e, 0xe1e, 0x2e, 0x3b, 0xe21,
+0xe35, 0x2e, 0xe04, 0x2e, 0x3b, 0xe40, 0xe21, 0x2e, 0xe22, 0x2e, 0x3b, 0xe1e, 0x2e, 0xe04, 0x2e, 0x3b, 0xe21, 0xe34, 0x2e, 0xe22,
+0x2e, 0x3b, 0xe01, 0x2e, 0xe04, 0x2e, 0x3b, 0xe2a, 0x2e, 0xe04, 0x2e, 0x3b, 0xe01, 0x2e, 0xe22, 0x2e, 0x3b, 0xe15, 0x2e, 0xe04,
+0x2e, 0x3b, 0xe1e, 0x2e, 0xe22, 0x2e, 0x3b, 0xe18, 0x2e, 0xe04, 0x2e, 0x3b, 0xe21, 0xe01, 0xe23, 0xe32, 0xe04, 0xe21, 0x3b, 0xe01,
+0xe38, 0xe21, 0xe20, 0xe32, 0xe1e, 0xe31, 0xe19, 0xe18, 0xe4c, 0x3b, 0xe21, 0xe35, 0xe19, 0xe32, 0xe04, 0xe21, 0x3b, 0xe40, 0xe21, 0xe29,
+0xe32, 0xe22, 0xe19, 0x3b, 0xe1e, 0xe24, 0xe29, 0xe20, 0xe32, 0xe04, 0xe21, 0x3b, 0xe21, 0xe34, 0xe16, 0xe38, 0xe19, 0xe32, 0xe22, 0xe19,
+0x3b, 0xe01, 0xe23, 0xe01, 0xe0e, 0xe32, 0xe04, 0xe21, 0x3b, 0xe2a, 0xe34, 0xe07, 0xe2b, 0xe32, 0xe04, 0xe21, 0x3b, 0xe01, 0xe31, 0xe19,
+0xe22, 0xe32, 0xe22, 0xe19, 0x3b, 0xe15, 0xe38, 0xe25, 0xe32, 0xe04, 0xe21, 0x3b, 0xe1e, 0xe24, 0xe28, 0xe08, 0xe34, 0xe01, 0xe32, 0xe22,
+0xe19, 0x3b, 0xe18, 0xe31, 0xe19, 0xe27, 0xe32, 0xe04, 0xe21, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xf44, 0xf0b, 0xf54, 0xf7c,
+0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b,
+0xf42, 0xf66, 0xf74, 0xf58, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b, 0xf54, 0xf0b, 0x3b,
+0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf63, 0xf94, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xfb2, 0xf74, 0xf42,
+0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf51, 0xf74, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b,
+0xf56, 0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1, 0xf51, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xf42, 0xf74, 0xf0b,
+0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b,
+0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf45, 0xf72, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45, 0xf74,
+0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xf44, 0xf0b, 0xf54, 0xf7c, 0x3b,
+0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf42, 0xf66, 0xf74,
+0xf58, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b,
+0xf63, 0xf94, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xfb2, 0xf74, 0xf42, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b,
+0xf56, 0xf0b, 0xf56, 0xf51, 0xf74, 0xf53, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1, 0xf51, 0xf0b,
+0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xf42, 0xf74, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45,
+0xf74, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf45, 0xf72, 0xf42, 0xf0b, 0xf54, 0x3b,
+0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0x3b, 0x1325, 0x122a, 0x3b, 0x1208,
+0x12ab, 0x3b, 0x1218, 0x130b, 0x3b, 0x121a, 0x12eb, 0x3b, 0x130d, 0x1295, 0x3b, 0x1230, 0x1290, 0x3b, 0x1213, 0x121d, 0x3b, 0x1290, 0x1213, 0x3b,
+0x1218, 0x1235, 0x3b, 0x1325, 0x1245, 0x3b, 0x1215, 0x12f3, 0x3b, 0x1273, 0x1215, 0x3b, 0x1325, 0x122a, 0x3b, 0x1208, 0x12ab, 0x1272, 0x1275, 0x3b,
+0x1218, 0x130b, 0x1262, 0x1275, 0x3b, 0x121a, 0x12eb, 0x12dd, 0x12eb, 0x3b, 0x130d, 0x1295, 0x1266, 0x1275, 0x3b, 0x1230, 0x1290, 0x3b, 0x1213, 0x121d,
+0x1208, 0x3b, 0x1290, 0x1213, 0x1230, 0x3b, 0x1218, 0x1235, 0x12a8, 0x1228, 0x121d, 0x3b, 0x1325, 0x1245, 0x121d, 0x1272, 0x3b, 0x1215, 0x12f3, 0x122d,
+0x3b, 0x1273, 0x1215, 0x1233, 0x1235, 0x3b, 0x1325, 0x3b, 0x1208, 0x3b, 0x1218, 0x3b, 0x121a, 0x3b, 0x130d, 0x3b, 0x1230, 0x3b, 0x1213, 0x3b,
+0x1290, 0x3b, 0x1218, 0x3b, 0x1325, 0x3b, 0x1215, 0x3b, 0x1273, 0x3b, 0x53, 0x101, 0x6e, 0x3b, 0x46, 0x113, 0x70, 0x3b, 0x4d, 0x61,
+0x2bb, 0x61, 0x3b, 0x2bb, 0x45, 0x70, 0x65, 0x3b, 0x4d, 0x113, 0x3b, 0x53, 0x75, 0x6e, 0x3b, 0x53, 0x69, 0x75, 0x3b, 0x2bb,
+0x41, 0x6f, 0x6b, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x2bb, 0x4f, 0x6b, 0x61, 0x3b, 0x4e, 0x14d, 0x76, 0x3b, 0x54, 0x12b, 0x73,
+0x3b, 0x53, 0x101, 0x6e, 0x75, 0x61, 0x6c, 0x69, 0x3b, 0x46, 0x113, 0x70, 0x75, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x61, 0x2bb,
+0x61, 0x73, 0x69, 0x3b, 0x2bb, 0x45, 0x70, 0x65, 0x6c, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x113, 0x3b, 0x53, 0x75, 0x6e, 0x65,
+0x3b, 0x53, 0x69, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x2bb, 0x41, 0x6f, 0x6b, 0x6f, 0x73, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x69,
+0x74, 0x65, 0x6d, 0x61, 0x3b, 0x2bb, 0x4f, 0x6b, 0x61, 0x74, 0x6f, 0x70, 0x61, 0x3b, 0x4e, 0x14d, 0x76, 0x65, 0x6d, 0x61,
+0x3b, 0x54, 0x12b, 0x73, 0x65, 0x6d, 0x61, 0x3b, 0x53, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x4d, 0x3b, 0x53, 0x3b,
+0x53, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x4f, 0x63, 0x61, 0x3b, 0x15e, 0x75, 0x62, 0x3b,
+0x4d, 0x61, 0x72, 0x3b, 0x4e, 0x69, 0x73, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x48, 0x61, 0x7a, 0x3b, 0x54, 0x65, 0x6d, 0x3b,
+0x41, 0x11f, 0x75, 0x3b, 0x45, 0x79, 0x6c, 0x3b, 0x45, 0x6b, 0x69, 0x3b, 0x4b, 0x61, 0x73, 0x3b, 0x41, 0x72, 0x61, 0x3b,
+0x4f, 0x63, 0x61, 0x6b, 0x3b, 0x15e, 0x75, 0x62, 0x61, 0x74, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x3b, 0x4e, 0x69, 0x73, 0x61,
+0x6e, 0x3b, 0x4d, 0x61, 0x79, 0x131, 0x73, 0x3b, 0x48, 0x61, 0x7a, 0x69, 0x72, 0x61, 0x6e, 0x3b, 0x54, 0x65, 0x6d, 0x6d,
+0x75, 0x7a, 0x3b, 0x41, 0x11f, 0x75, 0x73, 0x74, 0x6f, 0x73, 0x3b, 0x45, 0x79, 0x6c, 0xfc, 0x6c, 0x3b, 0x45, 0x6b, 0x69,
+0x6d, 0x3b, 0x4b, 0x61, 0x73, 0x131, 0x6d, 0x3b, 0x41, 0x72, 0x61, 0x6c, 0x131, 0x6b, 0x3b, 0x4f, 0x3b, 0x15e, 0x3b, 0x4d,
+0x3b, 0x4e, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x45, 0x3b, 0x45, 0x3b, 0x4b, 0x3b, 0x41, 0x3b, 0xdd,
+0x61, 0x6e, 0x3b, 0x46, 0x65, 0x77, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0xfd, 0x3b, 0x49,
+0xfd, 0x75, 0x6e, 0x3b, 0x49, 0xfd, 0x75, 0x6c, 0x3b, 0x41, 0x77, 0x67, 0x3b, 0x53, 0x65, 0x6e, 0x3b, 0x4f, 0x6b, 0x74,
+0x3b, 0x4e, 0x6f, 0xfd, 0x3b, 0x44, 0x65, 0x6b, 0x3b, 0xdd, 0x61, 0x6e, 0x77, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x77, 0x72,
+0x61, 0x6c, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x61, 0xfd, 0x3b, 0x49, 0xfd,
+0x75, 0x6e, 0x3b, 0x49, 0xfd, 0x75, 0x6c, 0x3b, 0x41, 0x77, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x6e, 0x74, 0xfd,
+0x61, 0x62, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0xfd, 0x61, 0x62, 0x72, 0x3b, 0x4e, 0x6f, 0xfd, 0x61, 0x62, 0x72, 0x3b, 0x44,
+0x65, 0x6b, 0x61, 0x62, 0x72, 0x3b, 0xdd, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x49, 0x3b,
+0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0xfd, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x77, 0x3b, 0x6d, 0x61,
+0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0xfd, 0x3b, 0x69, 0xfd, 0x75, 0x6e, 0x3b, 0x69, 0xfd, 0x75, 0x6c,
+0x3b, 0x61, 0x77, 0x67, 0x3b, 0x73, 0x65, 0x6e, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0xfd, 0x3b, 0x64, 0x65, 0x6b,
+0x3b, 0xfd, 0x61, 0x6e, 0x77, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x77, 0x72, 0x61, 0x6c, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b,
+0x61, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x6d, 0x61, 0xfd, 0x3b, 0x69, 0xfd, 0x75, 0x6e, 0x3b, 0x69, 0xfd, 0x75, 0x6c, 0x3b,
+0x61, 0x77, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x6e, 0x74, 0xfd, 0x61, 0x62, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0xfd,
+0x61, 0x62, 0x72, 0x3b, 0x6e, 0x6f, 0xfd, 0x61, 0x62, 0x72, 0x3b, 0x64, 0x65, 0x6b, 0x61, 0x62, 0x72, 0x3b, 0x64a, 0x627,
+0x646, 0x6cb, 0x627, 0x631, 0x3b, 0x641, 0x6d0, 0x6cb, 0x631, 0x627, 0x644, 0x3b, 0x645, 0x627, 0x631, 0x62a, 0x3b, 0x626, 0x627, 0x67e,
+0x631, 0x6d0, 0x644, 0x3b, 0x645, 0x627, 0x64a, 0x3b, 0x626, 0x649, 0x64a, 0x6c7, 0x646, 0x3b, 0x626, 0x649, 0x64a, 0x6c7, 0x644, 0x3b,
+0x626, 0x627, 0x6cb, 0x63a, 0x6c7, 0x633, 0x62a, 0x3b, 0x633, 0x6d0, 0x646, 0x62a, 0x6d5, 0x628, 0x649, 0x631, 0x3b, 0x626, 0x6c6, 0x643,
+0x62a, 0x6d5, 0x628, 0x649, 0x631, 0x3b, 0x646, 0x648, 0x64a, 0x627, 0x628, 0x649, 0x631, 0x3b, 0x62f, 0x6d0, 0x643, 0x627, 0x628, 0x649,
+0x631, 0x3b, 0x441, 0x456, 0x447, 0x3b, 0x43b, 0x44e, 0x442, 0x3b, 0x431, 0x435, 0x440, 0x3b, 0x43a, 0x432, 0x456, 0x3b, 0x442, 0x440,
+0x430, 0x3b, 0x447, 0x435, 0x440, 0x3b, 0x43b, 0x438, 0x43f, 0x3b, 0x441, 0x435, 0x440, 0x3b, 0x432, 0x435, 0x440, 0x3b, 0x436, 0x43e,
+0x432, 0x3b, 0x43b, 0x438, 0x441, 0x3b, 0x433, 0x440, 0x443, 0x3b, 0x441, 0x456, 0x447, 0x435, 0x43d, 0x44c, 0x3b, 0x43b, 0x44e, 0x442,
+0x438, 0x439, 0x3b, 0x431, 0x435, 0x440, 0x435, 0x437, 0x435, 0x43d, 0x44c, 0x3b, 0x43a, 0x432, 0x456, 0x442, 0x435, 0x43d, 0x44c, 0x3b,
+0x442, 0x440, 0x430, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x447, 0x435, 0x440, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x43b, 0x438, 0x43f, 0x435,
+0x43d, 0x44c, 0x3b, 0x441, 0x435, 0x440, 0x43f, 0x435, 0x43d, 0x44c, 0x3b, 0x432, 0x435, 0x440, 0x435, 0x441, 0x435, 0x43d, 0x44c, 0x3b,
+0x436, 0x43e, 0x432, 0x442, 0x435, 0x43d, 0x44c, 0x3b, 0x43b, 0x438, 0x441, 0x442, 0x43e, 0x43f, 0x430, 0x434, 0x3b, 0x433, 0x440, 0x443,
+0x434, 0x435, 0x43d, 0x44c, 0x3b, 0x421, 0x3b, 0x41b, 0x3b, 0x411, 0x3b, 0x41a, 0x3b, 0x422, 0x3b, 0x427, 0x3b, 0x41b, 0x3b, 0x421,
+0x3b, 0x412, 0x3b, 0x416, 0x3b, 0x41b, 0x3b, 0x413, 0x3b, 0x441, 0x456, 0x447, 0x2e, 0x3b, 0x43b, 0x44e, 0x442, 0x2e, 0x3b, 0x431,
+0x435, 0x440, 0x2e, 0x3b, 0x43a, 0x432, 0x456, 0x442, 0x2e, 0x3b, 0x442, 0x440, 0x430, 0x432, 0x2e, 0x3b, 0x447, 0x435, 0x440, 0x432,
+0x2e, 0x3b, 0x43b, 0x438, 0x43f, 0x2e, 0x3b, 0x441, 0x435, 0x440, 0x43f, 0x2e, 0x3b, 0x432, 0x435, 0x440, 0x2e, 0x3b, 0x436, 0x43e,
+0x432, 0x442, 0x2e, 0x3b, 0x43b, 0x438, 0x441, 0x442, 0x2e, 0x3b, 0x433, 0x440, 0x443, 0x434, 0x2e, 0x3b, 0x441, 0x456, 0x447, 0x43d,
+0x44f, 0x3b, 0x43b, 0x44e, 0x442, 0x43e, 0x433, 0x43e, 0x3b, 0x431, 0x435, 0x440, 0x435, 0x437, 0x43d, 0x44f, 0x3b, 0x43a, 0x432, 0x456,
+0x442, 0x43d, 0x44f, 0x3b, 0x442, 0x440, 0x430, 0x432, 0x43d, 0x44f, 0x3b, 0x447, 0x435, 0x440, 0x432, 0x43d, 0x44f, 0x3b, 0x43b, 0x438,
+0x43f, 0x43d, 0x44f, 0x3b, 0x441, 0x435, 0x440, 0x43f, 0x43d, 0x44f, 0x3b, 0x432, 0x435, 0x440, 0x435, 0x441, 0x43d, 0x44f, 0x3b, 0x436,
+0x43e, 0x432, 0x442, 0x43d, 0x44f, 0x3b, 0x43b, 0x438, 0x441, 0x442, 0x43e, 0x43f, 0x430, 0x434, 0x430, 0x3b, 0x433, 0x440, 0x443, 0x434,
+0x43d, 0x44f, 0x3b, 0x441, 0x3b, 0x43b, 0x3b, 0x431, 0x3b, 0x43a, 0x3b, 0x442, 0x3b, 0x447, 0x3b, 0x43b, 0x3b, 0x441, 0x3b, 0x432,
+0x3b, 0x436, 0x3b, 0x43b, 0x3b, 0x433, 0x3b, 0x62c, 0x646, 0x648, 0x631, 0x6cc, 0x3b, 0x641, 0x631, 0x648, 0x631, 0x6cc, 0x3b, 0x645,
+0x627, 0x631, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x626, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648,
+0x644, 0x627, 0x626, 0x6cc, 0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648,
+0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x59, 0x61, 0x6e, 0x3b, 0x46,
+0x65, 0x76, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x49, 0x79, 0x6e, 0x3b, 0x49,
+0x79, 0x6c, 0x3b, 0x41, 0x76, 0x67, 0x3b, 0x53, 0x65, 0x6e, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x79, 0x3b, 0x44,
+0x65, 0x6b, 0x3b, 0x59, 0x61, 0x6e, 0x76, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x76, 0x72, 0x61, 0x6c, 0x3b, 0x4d, 0x61, 0x72,
+0x74, 0x3b, 0x41, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x49, 0x79, 0x75, 0x6e, 0x3b, 0x49, 0x79, 0x75,
+0x6c, 0x3b, 0x41, 0x76, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x6e, 0x74, 0x61, 0x62, 0x72, 0x3b, 0x4f, 0x6b, 0x74,
+0x61, 0x62, 0x72, 0x3b, 0x4e, 0x6f, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x44, 0x65, 0x6b, 0x61, 0x62, 0x72, 0x3b, 0x59, 0x3b,
+0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b,
+0x44, 0x3b, 0x79, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x76, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61,
+0x79, 0x3b, 0x69, 0x79, 0x6e, 0x3b, 0x69, 0x79, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x3b, 0x73, 0x65, 0x6e, 0x3b, 0x6f, 0x6b,
+0x74, 0x3b, 0x6e, 0x6f, 0x79, 0x3b, 0x64, 0x65, 0x6b, 0x3b, 0x79, 0x61, 0x6e, 0x76, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x76,
+0x72, 0x61, 0x6c, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x69,
+0x79, 0x75, 0x6e, 0x3b, 0x69, 0x79, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x6e, 0x74,
+0x61, 0x62, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x61, 0x62, 0x72, 0x3b, 0x6e, 0x6f, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x64, 0x65,
+0x6b, 0x61, 0x62, 0x72, 0x3b, 0x62c, 0x646, 0x648, 0x3b, 0x641, 0x628, 0x631, 0x3b, 0x645, 0x627, 0x631, 0x3b, 0x627, 0x67e, 0x631,
+0x3b, 0x645, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x3b, 0x627, 0x6af, 0x633, 0x3b, 0x633, 0x67e, 0x62a, 0x3b,
+0x627, 0x6a9, 0x62a, 0x3b, 0x646, 0x648, 0x645, 0x3b, 0x62f, 0x633, 0x645, 0x3b, 0x44f, 0x43d, 0x432, 0x3b, 0x444, 0x435, 0x432, 0x3b,
+0x43c, 0x430, 0x440, 0x3b, 0x430, 0x43f, 0x440, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x44e, 0x43d, 0x3b, 0x438, 0x44e, 0x43b, 0x3b,
+0x430, 0x432, 0x433, 0x3b, 0x441, 0x435, 0x43d, 0x3b, 0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x44f, 0x3b, 0x434, 0x435, 0x43a, 0x3b,
+0x44f, 0x43d, 0x432, 0x430, 0x440, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f,
+0x440, 0x435, 0x43b, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x44e, 0x43d, 0x3b, 0x438, 0x44e, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x443,
+0x441, 0x442, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x3b, 0x43e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x3b, 0x43d, 0x43e,
+0x44f, 0x431, 0x440, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x31, 0x3b, 0x54, 0x68, 0x67,
+0x20, 0x32, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x33, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x34, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x35,
+0x3b, 0x54, 0x68, 0x67, 0x20, 0x36, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x37, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x38, 0x3b, 0x54,
+0x68, 0x67, 0x20, 0x39, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x31, 0x30, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x31, 0x31, 0x3b, 0x54,
+0x68, 0x67, 0x20, 0x31, 0x32, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20,
+0x32, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x33, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x34, 0x3b, 0x54, 0x68,
+0xe1, 0x6e, 0x67, 0x20, 0x35, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x36, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20,
+0x37, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x38, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x39, 0x3b, 0x54, 0x68,
+0xe1, 0x6e, 0x67, 0x20, 0x31, 0x30, 0x3b, 0x54, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31, 0x31, 0x3b, 0x54, 0x68, 0xe1, 0x6e,
+0x67, 0x20, 0x31, 0x32, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x31, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x32, 0x3b, 0x74, 0x68, 0x67,
+0x20, 0x33, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x34, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x35, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x36,
+0x3b, 0x74, 0x68, 0x67, 0x20, 0x37, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x38, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x39, 0x3b, 0x74,
+0x68, 0x67, 0x20, 0x31, 0x30, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x31, 0x31, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x31, 0x32, 0x3b,
+0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x32, 0x3b, 0x74, 0x68, 0xe1, 0x6e,
+0x67, 0x20, 0x33, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x34, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x35, 0x3b,
+0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x36, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x37, 0x3b, 0x74, 0x68, 0xe1, 0x6e,
+0x67, 0x20, 0x38, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x39, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31, 0x30,
+0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31, 0x31, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x31, 0x32, 0x3b, 0x79,
+0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0xe4, 0x7a, 0x3b, 0x70, 0x72, 0x6c, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x79,
+0x75, 0x6e, 0x3b, 0x79, 0x75, 0x6c, 0x3b, 0x67, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x74, 0x3b, 0x74, 0x6f, 0x62, 0x3b, 0x6e,
+0x6f, 0x76, 0x3b, 0x64, 0x65, 0x6b, 0x3b, 0x79, 0x61, 0x6e, 0x75, 0x6c, 0x3b, 0x66, 0x65, 0x62, 0x75, 0x6c, 0x3b, 0x6d,
+0xe4, 0x7a, 0x75, 0x6c, 0x3b, 0x70, 0x72, 0x69, 0x6c, 0x75, 0x6c, 0x3b, 0x6d, 0x61, 0x79, 0x75, 0x6c, 0x3b, 0x79, 0x75,
+0x6e, 0x75, 0x6c, 0x3b, 0x79, 0x75, 0x6c, 0x75, 0x6c, 0x3b, 0x67, 0x75, 0x73, 0x74, 0x75, 0x6c, 0x3b, 0x73, 0x65, 0x74,
+0x75, 0x6c, 0x3b, 0x74, 0x6f, 0x62, 0x75, 0x6c, 0x3b, 0x6e, 0x6f, 0x76, 0x75, 0x6c, 0x3b, 0x64, 0x65, 0x6b, 0x75, 0x6c,
+0x3b, 0x59, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x50, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x47, 0x3b, 0x53, 0x3b, 0x54,
+0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x79, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0xe4, 0x7a, 0x3b, 0x70, 0x72, 0x6c,
+0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x79, 0x75, 0x6e, 0x3b, 0x79, 0x75, 0x6c, 0x3b, 0x67, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x74,
+0x3b, 0x74, 0x6f, 0x6e, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x6b, 0x3b, 0x49, 0x6f, 0x6e, 0x3b, 0x43, 0x68, 0x77,
0x3b, 0x4d, 0x61, 0x77, 0x3b, 0x45, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4d, 0x65, 0x68, 0x3b, 0x47, 0x6f, 0x72,
0x3b, 0x41, 0x77, 0x73, 0x74, 0x3b, 0x4d, 0x65, 0x64, 0x69, 0x3b, 0x48, 0x79, 0x64, 0x3b, 0x54, 0x61, 0x63, 0x68, 0x3b,
0x52, 0x68, 0x61, 0x67, 0x3b, 0x49, 0x6f, 0x6e, 0x61, 0x77, 0x72, 0x3b, 0x43, 0x68, 0x77, 0x65, 0x66, 0x72, 0x6f, 0x72,
@@ -3050,7 +3167,28 @@ static const ushort months_data[] = {
0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x52, 0x68, 0x3b, 0x49, 0x6f,
0x6e, 0x3b, 0x43, 0x68, 0x77, 0x65, 0x66, 0x3b, 0x4d, 0x61, 0x77, 0x3b, 0x45, 0x62, 0x72, 0x69, 0x6c, 0x6c, 0x3b, 0x4d,
0x61, 0x69, 0x3b, 0x4d, 0x65, 0x68, 0x3b, 0x47, 0x6f, 0x72, 0x66, 0x66, 0x3b, 0x41, 0x77, 0x73, 0x74, 0x3b, 0x4d, 0x65,
-0x64, 0x69, 0x3b, 0x48, 0x79, 0x64, 0x3b, 0x54, 0x61, 0x63, 0x68, 0x3b, 0x52, 0x68, 0x61, 0x67, 0x3b, 0x1e62, 0x1eb9, 0x301,
+0x64, 0x69, 0x3b, 0x48, 0x79, 0x64, 0x3b, 0x54, 0x61, 0x63, 0x68, 0x3b, 0x52, 0x68, 0x61, 0x67, 0x3b, 0x53, 0x61, 0x6d,
+0x3b, 0x46, 0x65, 0x77, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x77, 0x72, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x53, 0x75, 0x77,
+0x3b, 0x53, 0x75, 0x6c, 0x3b, 0x55, 0x74, 0x3b, 0x53, 0xe0, 0x74, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x77, 0x3b,
+0x44, 0x65, 0x73, 0x3b, 0x53, 0x61, 0x6d, 0x77, 0x69, 0x79, 0x65, 0x65, 0x3b, 0x46, 0x65, 0x77, 0x72, 0x69, 0x79, 0x65,
+0x65, 0x3b, 0x4d, 0x61, 0x72, 0x73, 0x3b, 0x41, 0x77, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x53, 0x75, 0x77,
+0x65, 0x3b, 0x53, 0x75, 0x6c, 0x65, 0x74, 0x3b, 0x55, 0x74, 0x3b, 0x53, 0xe0, 0x74, 0x74, 0x75, 0x6d, 0x62, 0x61, 0x72,
+0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x3b, 0x4e, 0x6f, 0x77, 0xe0, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x44,
+0x65, 0x73, 0xe0, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x74, 0x3b,
+0x45, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x79, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x61, 0x3b,
+0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x79,
+0x75, 0x77, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x77, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x74, 0x73,
+0x68, 0x69, 0x3b, 0x45, 0x70, 0x72, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x65, 0x79, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b,
+0x4a, 0x75, 0x6c, 0x61, 0x79, 0x69, 0x3b, 0x41, 0x67, 0x61, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d,
+0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x68, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44,
+0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x5d9, 0x5d0, 0x5b7, 0x5e0, 0x3b, 0x5e4, 0x5bf, 0x5e2, 0x5d1, 0x3b, 0x5de, 0x5e2, 0x5e8,
+0x5e5, 0x3b, 0x5d0, 0x5b7, 0x5e4, 0x5bc, 0x5e8, 0x3b, 0x5de, 0x5d9, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dc,
+0x5d9, 0x3b, 0x5d0, 0x5d5, 0x5d9, 0x5d2, 0x3b, 0x5e1, 0x5e2, 0x5e4, 0x5bc, 0x3b, 0x5d0, 0x5e7, 0x5d8, 0x3b, 0x5e0, 0x5d0, 0x5d5, 0x5d5,
+0x3b, 0x5d3, 0x5e2, 0x5e6, 0x3b, 0x5d9, 0x5d0, 0x5b7, 0x5e0, 0x5d5, 0x5d0, 0x5b7, 0x5e8, 0x3b, 0x5e4, 0x5bf, 0x5e2, 0x5d1, 0x5e8, 0x5d5,
+0x5d0, 0x5b7, 0x5e8, 0x3b, 0x5de, 0x5e2, 0x5e8, 0x5e5, 0x3b, 0x5d0, 0x5b7, 0x5e4, 0x5bc, 0x5e8, 0x5d9, 0x5dc, 0x3b, 0x5de, 0x5d9, 0x5d9,
+0x3b, 0x5d9, 0x5d5, 0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dc, 0x5d9, 0x3b, 0x5d0, 0x5d5, 0x5d9, 0x5d2, 0x5d5, 0x5e1, 0x5d8, 0x3b, 0x5e1,
+0x5e2, 0x5e4, 0x5bc, 0x5d8, 0x5e2, 0x5de, 0x5d1, 0x5e2, 0x5e8, 0x3b, 0x5d0, 0x5e7, 0x5d8, 0x5d0, 0x5d1, 0x5e2, 0x5e8, 0x3b, 0x5e0, 0x5d0,
+0x5d5, 0x5d5, 0x5e2, 0x5de, 0x5d1, 0x5e2, 0x5e8, 0x3b, 0x5d3, 0x5e2, 0x5e6, 0x5e2, 0x5de, 0x5d1, 0x5e2, 0x5e8, 0x3b, 0x1e62, 0x1eb9, 0x301,
0x72, 0x1eb9, 0x301, 0x3b, 0xc8, 0x72, 0xe8, 0x6c, 0xe8, 0x3b, 0x1eb8, 0x72, 0x1eb9, 0x300, 0x6e, 0xe0, 0x3b, 0xcc, 0x67, 0x62,
0xe9, 0x3b, 0x1eb8, 0x300, 0x62, 0x69, 0x62, 0x69, 0x3b, 0xd2, 0x6b, 0xfa, 0x64, 0x75, 0x3b, 0x41, 0x67, 0x1eb9, 0x6d, 0x1ecd,
0x3b, 0xd2, 0x67, 0xfa, 0x6e, 0x3b, 0x4f, 0x77, 0x65, 0x77, 0x65, 0x3b, 0x1ecc, 0x300, 0x77, 0xe0, 0x72, 0xe0, 0x3b, 0x42,
@@ -3077,751 +3215,773 @@ static const ushort months_data[] = {
0x75, 0x77, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x73, 0x68, 0x69, 0x3b, 0x45, 0x70, 0x68, 0x72, 0x65, 0x6c, 0x69, 0x3b,
0x4d, 0x65, 0x79, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x79, 0x69, 0x3b, 0x41, 0x67, 0x61,
0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x68, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x68, 0x6f, 0x62,
-0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x55, 0x4d,
-0x61, 0x73, 0x69, 0x6e, 0x67, 0x61, 0x6e, 0x61, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x77, 0x61, 0x72, 0x69, 0x3b, 0x4d,
-0x61, 0x73, 0x68, 0x69, 0x3b, 0x45, 0x70, 0x68, 0x72, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x65, 0x79, 0x69, 0x3b, 0x4a, 0x75,
-0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x79, 0x69, 0x3b, 0x41, 0x67, 0x61, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70,
-0x74, 0x68, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x68, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d,
-0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x4d,
-0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b,
-0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a,
-0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f,
-0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x73, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72,
-0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b,
-0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x76, 0x67, 0x75, 0x73, 0x74,
-0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x72, 0x3b, 0x6e,
-0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x458, 0x430, 0x43d,
-0x443, 0x430, 0x440, 0x3b, 0x444, 0x435, 0x431, 0x440, 0x443, 0x430, 0x440, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440,
-0x438, 0x43b, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x438, 0x3b, 0x458, 0x443, 0x43b, 0x438, 0x3b, 0x430, 0x432, 0x433,
-0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x431, 0x430,
-0x440, 0x3b, 0x43d, 0x43e, 0x432, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x434, 0x435, 0x446, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b,
-0x4a, 0x2d, 0x67, 0x75, 0x65, 0x72, 0x3b, 0x54, 0x2d, 0x61, 0x72, 0x72, 0x65, 0x65, 0x3b, 0x4d, 0x61, 0x79, 0x72, 0x6e,
-0x74, 0x3b, 0x41, 0x76, 0x72, 0x72, 0x69, 0x6c, 0x3b, 0x42, 0x6f, 0x61, 0x6c, 0x64, 0x79, 0x6e, 0x3b, 0x4d, 0x2d, 0x73,
-0x6f, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x4a, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x4c, 0x75, 0x61, 0x6e, 0x69,
-0x73, 0x74, 0x79, 0x6e, 0x3b, 0x4d, 0x2d, 0x66, 0x6f, 0x75, 0x79, 0x69, 0x72, 0x3b, 0x4a, 0x2d, 0x66, 0x6f, 0x75, 0x79,
-0x69, 0x72, 0x3b, 0x4d, 0x2d, 0x48, 0x6f, 0x75, 0x6e, 0x65, 0x79, 0x3b, 0x4d, 0x2d, 0x4e, 0x6f, 0x6c, 0x6c, 0x69, 0x63,
-0x6b, 0x3b, 0x4a, 0x65, 0x72, 0x72, 0x65, 0x79, 0x2d, 0x67, 0x65, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x54, 0x6f, 0x73, 0x68,
-0x69, 0x61, 0x67, 0x68, 0x74, 0x2d, 0x61, 0x72, 0x72, 0x65, 0x65, 0x3b, 0x4d, 0x61, 0x79, 0x72, 0x6e, 0x74, 0x3b, 0x41,
-0x76, 0x65, 0x72, 0x69, 0x6c, 0x3b, 0x42, 0x6f, 0x61, 0x6c, 0x64, 0x79, 0x6e, 0x3b, 0x4d, 0x65, 0x61, 0x6e, 0x2d, 0x73,
-0x6f, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x4a, 0x65, 0x72, 0x72, 0x65, 0x79, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x65, 0x65, 0x3b,
-0x4c, 0x75, 0x61, 0x6e, 0x69, 0x73, 0x74, 0x79, 0x6e, 0x3b, 0x4d, 0x65, 0x61, 0x6e, 0x2d, 0x66, 0x6f, 0x75, 0x79, 0x69,
-0x72, 0x3b, 0x4a, 0x65, 0x72, 0x72, 0x65, 0x79, 0x2d, 0x66, 0x6f, 0x75, 0x79, 0x69, 0x72, 0x3b, 0x4d, 0x65, 0x65, 0x20,
-0x48, 0x6f, 0x75, 0x6e, 0x65, 0x79, 0x3b, 0x4d, 0x65, 0x65, 0x20, 0x6e, 0x79, 0x20, 0x4e, 0x6f, 0x6c, 0x6c, 0x69, 0x63,
-0x6b, 0x3b, 0x47, 0x65, 0x6e, 0x3b, 0x48, 0x77, 0x65, 0x3b, 0x4d, 0x65, 0x75, 0x3b, 0x45, 0x62, 0x72, 0x3b, 0x4d, 0x65,
-0x3b, 0x4d, 0x65, 0x74, 0x3b, 0x47, 0x6f, 0x72, 0x3b, 0x45, 0x73, 0x74, 0x3b, 0x47, 0x77, 0x6e, 0x3b, 0x48, 0x65, 0x64,
-0x3b, 0x44, 0x75, 0x3b, 0x4b, 0x65, 0x76, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x47, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x3b, 0x6d,
-0x69, 0x73, 0x20, 0x48, 0x77, 0x65, 0x76, 0x72, 0x65, 0x72, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x4d, 0x65, 0x75, 0x72, 0x74,
-0x68, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x45, 0x62, 0x72, 0x65, 0x6c, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x4d, 0x65, 0x3b, 0x6d,
-0x69, 0x73, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x65, 0x76, 0x65, 0x6e, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x47, 0x6f, 0x72, 0x74,
-0x68, 0x65, 0x72, 0x65, 0x6e, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x45, 0x73, 0x74, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x47, 0x77,
-0x79, 0x6e, 0x6e, 0x67, 0x61, 0x6c, 0x61, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x48, 0x65, 0x64, 0x72, 0x61, 0x3b, 0x6d, 0x69,
-0x73, 0x20, 0x44, 0x75, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x4b, 0x65, 0x76, 0x61, 0x72, 0x64, 0x68, 0x75, 0x3b, 0x53, 0x2d,
-0x186, 0x3b, 0x4b, 0x2d, 0x186, 0x3b, 0x45, 0x2d, 0x186, 0x3b, 0x45, 0x2d, 0x4f, 0x3b, 0x45, 0x2d, 0x4b, 0x3b, 0x4f, 0x2d,
-0x41, 0x3b, 0x41, 0x2d, 0x4b, 0x3b, 0x44, 0x2d, 0x186, 0x3b, 0x46, 0x2d, 0x190, 0x3b, 0x186, 0x2d, 0x41, 0x3b, 0x186, 0x2d,
-0x4f, 0x3b, 0x4d, 0x2d, 0x186, 0x3b, 0x53, 0x61, 0x6e, 0x64, 0x61, 0x2d, 0x186, 0x70, 0x25b, 0x70, 0x254, 0x6e, 0x3b, 0x4b,
-0x77, 0x61, 0x6b, 0x77, 0x61, 0x72, 0x2d, 0x186, 0x67, 0x79, 0x65, 0x66, 0x75, 0x6f, 0x3b, 0x45, 0x62, 0x254, 0x77, 0x2d,
-0x186, 0x62, 0x65, 0x6e, 0x65, 0x6d, 0x3b, 0x45, 0x62, 0x254, 0x62, 0x69, 0x72, 0x61, 0x2d, 0x4f, 0x66, 0x6f, 0x72, 0x69,
-0x73, 0x75, 0x6f, 0x3b, 0x45, 0x73, 0x75, 0x73, 0x6f, 0x77, 0x20, 0x41, 0x6b, 0x65, 0x74, 0x73, 0x65, 0x61, 0x62, 0x61,
-0x2d, 0x4b, 0x254, 0x74, 0x254, 0x6e, 0x69, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x62, 0x69, 0x72, 0x61, 0x64, 0x65, 0x2d, 0x41,
-0x79, 0x25b, 0x77, 0x6f, 0x68, 0x6f, 0x6d, 0x75, 0x6d, 0x75, 0x3b, 0x41, 0x79, 0x25b, 0x77, 0x6f, 0x68, 0x6f, 0x2d, 0x4b,
-0x69, 0x74, 0x61, 0x77, 0x6f, 0x6e, 0x73, 0x61, 0x3b, 0x44, 0x69, 0x66, 0x75, 0x75, 0x2d, 0x186, 0x73, 0x61, 0x6e, 0x64,
-0x61, 0x61, 0x3b, 0x46, 0x61, 0x6e, 0x6b, 0x77, 0x61, 0x2d, 0x190, 0x62, 0x254, 0x3b, 0x186, 0x62, 0x25b, 0x73, 0x25b, 0x2d,
-0x41, 0x68, 0x69, 0x6e, 0x69, 0x6d, 0x65, 0x3b, 0x186, 0x62, 0x65, 0x72, 0x25b, 0x66, 0x25b, 0x77, 0x2d, 0x4f, 0x62, 0x75,
-0x62, 0x75, 0x6f, 0x3b, 0x4d, 0x75, 0x6d, 0x75, 0x2d, 0x186, 0x70, 0x25b, 0x6e, 0x69, 0x6d, 0x62, 0x61, 0x3b, 0x91c, 0x93e,
-0x928, 0x947, 0x935, 0x93e, 0x930, 0x940, 0x3b, 0x92b, 0x947, 0x92c, 0x94d, 0x930, 0x941, 0x935, 0x93e, 0x930, 0x940, 0x3b, 0x92e, 0x93e,
-0x930, 0x94d, 0x91a, 0x3b, 0x90f, 0x92a, 0x94d, 0x930, 0x93f, 0x932, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941,
-0x932, 0x948, 0x3b, 0x913, 0x917, 0x938, 0x94d, 0x91f, 0x3b, 0x938, 0x947, 0x92a, 0x94d, 0x91f, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x913,
-0x915, 0x94d, 0x91f, 0x94b, 0x92c, 0x930, 0x3b, 0x928, 0x94b, 0x935, 0x94d, 0x939, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x921, 0x93f, 0x938,
-0x947, 0x902, 0x92c, 0x930, 0x3b, 0x4a, 0x65, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x61, 0x3b, 0x45, 0x70, 0x72,
-0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75, 0x75, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x1ecc, 0x67, 0x1ecd, 0x3b, 0x53, 0x65, 0x70,
-0x3b, 0x1ecc, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x4a, 0x65, 0x6e, 0x1ee5, 0x77, 0x61, 0x72,
-0x1ecb, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x1ee5, 0x77, 0x61, 0x72, 0x1ecb, 0x3b, 0x4d, 0x61, 0x61, 0x63, 0x68, 0x1ecb, 0x3b, 0x45,
-0x70, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x1ecb, 0x3b,
-0x1ecc, 0x67, 0x1ecd, 0x1ecd, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x1ecc, 0x6b, 0x74, 0x6f,
-0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4d,
-0x62, 0x65, 0x3b, 0x4b, 0x65, 0x6c, 0x3b, 0x4b, 0x74, 0x169, 0x3b, 0x4b, 0x61, 0x6e, 0x3b, 0x4b, 0x74, 0x6e, 0x3b, 0x54,
-0x68, 0x61, 0x3b, 0x4d, 0x6f, 0x6f, 0x3b, 0x4e, 0x79, 0x61, 0x3b, 0x4b, 0x6e, 0x64, 0x3b, 0x128, 0x6b, 0x75, 0x3b, 0x128,
-0x6b, 0x6d, 0x3b, 0x128, 0x6b, 0x6c, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6d, 0x62, 0x65, 0x65, 0x3b,
-0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x65, 0x6c, 0x129, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61,
-0x20, 0x6b, 0x61, 0x74, 0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61,
-0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x61, 0x69,
-0x20, 0x77, 0x61, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x74, 0x68, 0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77,
-0x61, 0x20, 0x6d, 0x75, 0x6f, 0x6e, 0x7a, 0x61, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6e, 0x79, 0x61,
-0x61, 0x6e, 0x79, 0x61, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4d,
-0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x129, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61,
-0x20, 0x129, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x129, 0x6d, 0x77, 0x65, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20,
-0x77, 0x61, 0x20, 0x129, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x69, 0x6c, 0x129, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b,
-0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4b, 0x3b, 0x128, 0x3b, 0x128, 0x3b, 0x128, 0x3b,
-0x5a, 0x65, 0x6e, 0x3b, 0x46, 0x65, 0x76, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x76, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b,
-0x4a, 0x75, 0x67, 0x3b, 0x4c, 0x75, 0x69, 0x3b, 0x41, 0x76, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x74, 0x75, 0x3b,
-0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x63, 0x3b, 0x5a, 0x65, 0x6e, 0xe2, 0x72, 0x3b, 0x46, 0x65, 0x76, 0x72, 0xe2, 0x72,
-0x3b, 0x4d, 0x61, 0x72, 0xe7, 0x3b, 0x41, 0x76, 0x72, 0xee, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x67, 0x6e,
-0x3b, 0x4c, 0x75, 0x69, 0x3b, 0x41, 0x76, 0x6f, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b,
-0x4f, 0x74, 0x75, 0x62, 0x61, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x44, 0x69, 0x63, 0x65,
-0x6d, 0x62, 0x61, 0x72, 0x3b, 0x5a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4c, 0x3b, 0x41,
-0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x64, 0x7a, 0x76, 0x3b, 0x64, 0x7a, 0x64, 0x3b, 0x74, 0x65, 0x64,
-0x3b, 0x61, 0x66, 0x254, 0x3b, 0x64, 0x61, 0x6d, 0x3b, 0x6d, 0x61, 0x73, 0x3b, 0x73, 0x69, 0x61, 0x3b, 0x64, 0x65, 0x61,
-0x3b, 0x61, 0x6e, 0x79, 0x3b, 0x6b, 0x65, 0x6c, 0x3b, 0x61, 0x64, 0x65, 0x3b, 0x64, 0x7a, 0x6d, 0x3b, 0x64, 0x7a, 0x6f,
-0x76, 0x65, 0x3b, 0x64, 0x7a, 0x6f, 0x64, 0x7a, 0x65, 0x3b, 0x74, 0x65, 0x64, 0x6f, 0x78, 0x65, 0x3b, 0x61, 0x66, 0x254,
-0x66, 0x129, 0x65, 0x3b, 0x64, 0x61, 0x6d, 0x61, 0x3b, 0x6d, 0x61, 0x73, 0x61, 0x3b, 0x73, 0x69, 0x61, 0x6d, 0x6c, 0x254,
-0x6d, 0x3b, 0x64, 0x65, 0x61, 0x73, 0x69, 0x61, 0x6d, 0x69, 0x6d, 0x65, 0x3b, 0x61, 0x6e, 0x79, 0x254, 0x6e, 0x79, 0x254,
-0x3b, 0x6b, 0x65, 0x6c, 0x65, 0x3b, 0x61, 0x64, 0x65, 0x25b, 0x6d, 0x65, 0x6b, 0x70, 0x254, 0x78, 0x65, 0x3b, 0x64, 0x7a,
-0x6f, 0x6d, 0x65, 0x3b, 0x64, 0x3b, 0x64, 0x3b, 0x74, 0x3b, 0x61, 0x3b, 0x64, 0x3b, 0x6d, 0x3b, 0x73, 0x3b, 0x64, 0x3b,
-0x61, 0x3b, 0x6b, 0x3b, 0x61, 0x3b, 0x64, 0x3b, 0x49, 0x61, 0x6e, 0x2e, 0x3b, 0x50, 0x65, 0x70, 0x2e, 0x3b, 0x4d, 0x61,
-0x6c, 0x2e, 0x3b, 0x2bb, 0x41, 0x70, 0x2e, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x49, 0x75, 0x6e, 0x2e, 0x3b, 0x49, 0x75, 0x6c,
-0x2e, 0x3b, 0x2bb, 0x41, 0x75, 0x2e, 0x3b, 0x4b, 0x65, 0x70, 0x2e, 0x3b, 0x2bb, 0x4f, 0x6b, 0x2e, 0x3b, 0x4e, 0x6f, 0x77,
-0x2e, 0x3b, 0x4b, 0x65, 0x6b, 0x2e, 0x3b, 0x49, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x69, 0x3b, 0x50, 0x65, 0x70, 0x65, 0x6c,
-0x75, 0x61, 0x6c, 0x69, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x6b, 0x69, 0x3b, 0x2bb, 0x41, 0x70, 0x65, 0x6c, 0x69, 0x6c, 0x61,
-0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x49, 0x75, 0x6e, 0x65, 0x3b, 0x49, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x2bb, 0x41, 0x75, 0x6b,
-0x61, 0x6b, 0x65, 0x3b, 0x4b, 0x65, 0x70, 0x61, 0x6b, 0x65, 0x6d, 0x61, 0x70, 0x61, 0x3b, 0x2bb, 0x4f, 0x6b, 0x61, 0x6b,
-0x6f, 0x70, 0x61, 0x3b, 0x4e, 0x6f, 0x77, 0x65, 0x6d, 0x61, 0x70, 0x61, 0x3b, 0x4b, 0x65, 0x6b, 0x65, 0x6d, 0x61, 0x70,
-0x61, 0x3b, 0x45, 0x6e, 0x65, 0x3b, 0x50, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61,
-0x79, 0x3b, 0x48, 0x75, 0x6e, 0x3b, 0x48, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x6b,
-0x74, 0x3b, 0x4e, 0x6f, 0x62, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x45, 0x6e, 0x65, 0x72, 0x6f, 0x3b, 0x50, 0x65, 0x62, 0x72,
-0x65, 0x72, 0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x73, 0x6f, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x6f,
-0x3b, 0x48, 0x75, 0x6e, 0x79, 0x6f, 0x3b, 0x48, 0x75, 0x6c, 0x79, 0x6f, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b,
-0x53, 0x65, 0x74, 0x79, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x4f, 0x6b, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x4e, 0x6f,
-0x62, 0x79, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x44, 0x69, 0x73, 0x79, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x45, 0x3b,
-0x50, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x48, 0x75, 0x6e, 0x3b, 0x48, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b,
-0x53, 0x65, 0x74, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x62, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x75,
-0x61, 0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x69,
-0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x75,
-0x73, 0x63, 0x68, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x6f,
-0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0xe4, 0x6d, 0x62, 0x65,
-0x72, 0x3b, 0xa2cd, 0xa1aa, 0x3b, 0xa44d, 0xa1aa, 0x3b, 0xa315, 0xa1aa, 0x3b, 0xa1d6, 0xa1aa, 0x3b, 0xa26c, 0xa1aa, 0x3b, 0xa0d8, 0xa1aa, 0x3b,
-0xa3c3, 0xa1aa, 0x3b, 0xa246, 0xa1aa, 0x3b, 0xa22c, 0xa1aa, 0x3b, 0xa2b0, 0xa1aa, 0x3b, 0xa2b0, 0xa2aa, 0xa1aa, 0x3b, 0xa2b0, 0xa44b, 0xa1aa, 0x3b,
-0x4a, 0x61, 0x6e, 0x75, 0x61, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x61, 0x72, 0x3b, 0x4d, 0xe4, 0x72,
-0x7a, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c,
-0x69, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f,
-0x6b, 0x74, 0x6f, 0x76, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0x65,
-0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x111, 0x111, 0x6a, 0x3b, 0x67, 0x75, 0x6f, 0x76, 0x3b, 0x6e, 0x6a, 0x75, 0x6b, 0x3b,
-0x63, 0x75, 0x6f, 0x3b, 0x6d, 0x69, 0x65, 0x73, 0x3b, 0x67, 0x65, 0x61, 0x73, 0x3b, 0x73, 0x75, 0x6f, 0x69, 0x3b, 0x62,
-0x6f, 0x72, 0x67, 0x3b, 0x10d, 0x61, 0x6b, 0x10d, 0x3b, 0x67, 0x6f, 0x6c, 0x67, 0x3b, 0x73, 0x6b, 0xe1, 0x62, 0x3b, 0x6a,
-0x75, 0x6f, 0x76, 0x3b, 0x6f, 0x111, 0x111, 0x61, 0x6a, 0x61, 0x67, 0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x67, 0x75,
-0x6f, 0x76, 0x76, 0x61, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x6e, 0x6a, 0x75, 0x6b, 0x10d, 0x61, 0x6d, 0xe1, 0x6e, 0x6e,
-0x75, 0x3b, 0x63, 0x75, 0x6f, 0x14b, 0x6f, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x6d, 0x69, 0x65, 0x73, 0x73, 0x65, 0x6d,
-0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x67, 0x65, 0x61, 0x73, 0x73, 0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x73, 0x75, 0x6f,
-0x69, 0x64, 0x6e, 0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x62, 0x6f, 0x72, 0x67, 0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75,
-0x3b, 0x10d, 0x61, 0x6b, 0x10d, 0x61, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x67, 0x6f, 0x6c, 0x67, 0x67, 0x6f, 0x74, 0x6d,
-0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x73, 0x6b, 0xe1, 0x62, 0x6d, 0x61, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x6a, 0x75, 0x6f,
-0x76, 0x6c, 0x61, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x4f, 0x3b, 0x47, 0x3b, 0x4e, 0x3b, 0x43, 0x3b, 0x4d, 0x3b, 0x47,
-0x3b, 0x53, 0x3b, 0x42, 0x3b, 0x10c, 0x3b, 0x47, 0x3b, 0x53, 0x3b, 0x4a, 0x3b, 0x43, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62,
-0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x43, 0x75, 0x6c,
-0x3b, 0x41, 0x67, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x62, 0x3b, 0x44, 0x69, 0x73,
-0x3b, 0x43, 0x68, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x75, 0x72, 0x61, 0x72, 0x69, 0x3b, 0x4d,
-0x61, 0x63, 0x68, 0x69, 0x3b, 0x41, 0x70, 0x69, 0x72, 0x69, 0x72, 0x69, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e,
-0x69, 0x3b, 0x43, 0x68, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74,
-0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x69, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x62, 0x65, 0x6d, 0x62, 0x61,
-0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x43, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a,
-0x3b, 0x43, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x49, 0x6d, 0x62, 0x3b, 0x4b, 0x61, 0x77,
-0x3b, 0x4b, 0x61, 0x64, 0x3b, 0x4b, 0x61, 0x6e, 0x3b, 0x4b, 0x61, 0x73, 0x3b, 0x4b, 0x61, 0x72, 0x3b, 0x4d, 0x66, 0x75,
-0x3b, 0x57, 0x75, 0x6e, 0x3b, 0x49, 0x6b, 0x65, 0x3b, 0x49, 0x6b, 0x75, 0x3b, 0x49, 0x6d, 0x77, 0x3b, 0x49, 0x77, 0x69,
-0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x69, 0x6d, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4d, 0x6f,
-0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x77, 0x69, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68,
-0x77, 0x61, 0x20, 0x6b, 0x61, 0x64, 0x61, 0x64, 0x75, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20,
-0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x73, 0x61, 0x6e,
-0x75, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x64,
-0x75, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6d, 0x66, 0x75, 0x6e, 0x67, 0x61, 0x64, 0x65,
-0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x77, 0x75, 0x6e, 0x79, 0x61, 0x6e, 0x79, 0x61, 0x3b,
-0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4d, 0x6f, 0x72,
-0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68,
-0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x69, 0x6d, 0x77, 0x65, 0x72, 0x69, 0x3b, 0x4d,
-0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x69, 0x77,
-0x69, 0x3b, 0x49, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b, 0x57, 0x3b, 0x49, 0x3b,
-0x49, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x73, 0x69, 0x69, 0x3b, 0x63, 0x6f, 0x6c, 0x3b, 0x6d, 0x62, 0x6f, 0x3b, 0x73, 0x65,
-0x65, 0x3b, 0x64, 0x75, 0x75, 0x3b, 0x6b, 0x6f, 0x72, 0x3b, 0x6d, 0x6f, 0x72, 0x3b, 0x6a, 0x75, 0x6b, 0x3b, 0x73, 0x6c,
-0x74, 0x3b, 0x79, 0x61, 0x72, 0x3b, 0x6a, 0x6f, 0x6c, 0x3b, 0x62, 0x6f, 0x77, 0x3b, 0x73, 0x69, 0x69, 0x6c, 0x6f, 0x3b,
-0x63, 0x6f, 0x6c, 0x74, 0x65, 0x3b, 0x6d, 0x62, 0x6f, 0x6f, 0x79, 0x3b, 0x73, 0x65, 0x65, 0x257, 0x74, 0x6f, 0x3b, 0x64,
-0x75, 0x75, 0x6a, 0x61, 0x6c, 0x3b, 0x6b, 0x6f, 0x72, 0x73, 0x65, 0x3b, 0x6d, 0x6f, 0x72, 0x73, 0x6f, 0x3b, 0x6a, 0x75,
-0x6b, 0x6f, 0x3b, 0x73, 0x69, 0x69, 0x6c, 0x74, 0x6f, 0x3b, 0x79, 0x61, 0x72, 0x6b, 0x6f, 0x6d, 0x61, 0x61, 0x3b, 0x6a,
-0x6f, 0x6c, 0x61, 0x6c, 0x3b, 0x62, 0x6f, 0x77, 0x74, 0x65, 0x3b, 0x73, 0x3b, 0x63, 0x3b, 0x6d, 0x3b, 0x73, 0x3b, 0x64,
-0x3b, 0x6b, 0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x73, 0x3b, 0x79, 0x3b, 0x6a, 0x3b, 0x62, 0x3b, 0x4a, 0x45, 0x4e, 0x3b, 0x57,
-0x4b, 0x52, 0x3b, 0x57, 0x47, 0x54, 0x3b, 0x57, 0x4b, 0x4e, 0x3b, 0x57, 0x54, 0x4e, 0x3b, 0x57, 0x54, 0x44, 0x3b, 0x57,
-0x4d, 0x4a, 0x3b, 0x57, 0x4e, 0x4e, 0x3b, 0x57, 0x4b, 0x44, 0x3b, 0x57, 0x49, 0x4b, 0x3b, 0x57, 0x4d, 0x57, 0x3b, 0x44,
-0x49, 0x54, 0x3b, 0x4e, 0x6a, 0x65, 0x6e, 0x75, 0x61, 0x72, 0x129, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61,
-0x20, 0x6b, 0x65, 0x72, 0x129, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x74,
-0x169, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72,
-0x65, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61,
-0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20,
-0x6d, 0x169, 0x67, 0x77, 0x61, 0x6e, 0x6a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61,
-0x6e, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x65, 0x6e, 0x64, 0x61, 0x3b,
-0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x169, 0x6d, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65,
-0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x169, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x169, 0x6d, 0x77, 0x65, 0x3b, 0x4e, 0x64,
-0x69, 0x74, 0x68, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4a, 0x3b, 0x4b, 0x3b, 0x47, 0x3b, 0x4b, 0x3b, 0x47, 0x3b, 0x47, 0x3b,
-0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x44, 0x3b, 0x4f, 0x62, 0x6f, 0x3b, 0x57, 0x61, 0x61, 0x3b,
-0x4f, 0x6b, 0x75, 0x3b, 0x4f, 0x6e, 0x67, 0x3b, 0x49, 0x6d, 0x65, 0x3b, 0x49, 0x6c, 0x65, 0x3b, 0x53, 0x61, 0x70, 0x3b,
-0x49, 0x73, 0x69, 0x3b, 0x53, 0x61, 0x61, 0x3b, 0x54, 0x6f, 0x6d, 0x3b, 0x54, 0x6f, 0x62, 0x3b, 0x54, 0x6f, 0x77, 0x3b,
-0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x6f, 0x62, 0x6f, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20,
-0x77, 0x61, 0x61, 0x72, 0x65, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x6f, 0x6b, 0x75, 0x6e, 0x69, 0x3b,
-0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x6f, 0x6e, 0x67, 0x2019, 0x77, 0x61, 0x6e, 0x3b, 0x4c, 0x61, 0x70, 0x61,
-0x20, 0x6c, 0x65, 0x20, 0x69, 0x6d, 0x65, 0x74, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x69, 0x6c, 0x65,
-0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x73, 0x61, 0x70, 0x61, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c,
-0x65, 0x20, 0x69, 0x73, 0x69, 0x65, 0x74, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x73, 0x61, 0x61, 0x6c,
-0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x6d, 0x6f, 0x6e, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20,
-0x6c, 0x65, 0x20, 0x74, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x6f, 0x62, 0x6f, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65,
-0x20, 0x74, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x77, 0x61, 0x61, 0x72, 0x65, 0x3b, 0x4f, 0x3b, 0x57, 0x3b, 0x4f, 0x3b, 0x4f,
-0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4a, 0x61, 0x6e,
-0x3b, 0x46, 0x65, 0x76, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e,
-0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x74, 0x75, 0x3b, 0x4e, 0x6f, 0x76,
-0x3b, 0x44, 0x65, 0x63, 0x3b, 0x4a, 0x61, 0x6e, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x46, 0x65, 0x76, 0x72, 0x65, 0x69, 0x72,
-0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x63, 0x6f, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x6f, 0x3b, 0x4a,
-0x75, 0x6e, 0x68, 0x6f, 0x3b, 0x4a, 0x75, 0x6c, 0x68, 0x6f, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x6f, 0x3b, 0x53,
-0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x4f, 0x74, 0x75, 0x62, 0x72, 0x6f, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d,
-0x62, 0x72, 0x6f, 0x3b, 0x44, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x5a, 0x69, 0x62, 0x3b, 0x4e, 0x68, 0x6c,
-0x6f, 0x3b, 0x4d, 0x62, 0x69, 0x3b, 0x4d, 0x61, 0x62, 0x3b, 0x4e, 0x6b, 0x77, 0x3b, 0x4e, 0x68, 0x6c, 0x61, 0x3b, 0x4e,
-0x74, 0x75, 0x3b, 0x4e, 0x63, 0x77, 0x3b, 0x4d, 0x70, 0x61, 0x6e, 0x3b, 0x4d, 0x66, 0x75, 0x3b, 0x4c, 0x77, 0x65, 0x3b,
-0x4d, 0x70, 0x61, 0x6c, 0x3b, 0x5a, 0x69, 0x62, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x6c, 0x61, 0x3b, 0x4e, 0x68, 0x6c, 0x6f,
-0x6c, 0x61, 0x6e, 0x6a, 0x61, 0x3b, 0x4d, 0x62, 0x69, 0x6d, 0x62, 0x69, 0x74, 0x68, 0x6f, 0x3b, 0x4d, 0x61, 0x62, 0x61,
-0x73, 0x61, 0x3b, 0x4e, 0x6b, 0x77, 0x65, 0x6e, 0x6b, 0x77, 0x65, 0x7a, 0x69, 0x3b, 0x4e, 0x68, 0x6c, 0x61, 0x6e, 0x67,
-0x75, 0x6c, 0x61, 0x3b, 0x4e, 0x74, 0x75, 0x6c, 0x69, 0x6b, 0x61, 0x7a, 0x69, 0x3b, 0x4e, 0x63, 0x77, 0x61, 0x62, 0x61,
-0x6b, 0x61, 0x7a, 0x69, 0x3b, 0x4d, 0x70, 0x61, 0x6e, 0x64, 0x75, 0x6c, 0x61, 0x3b, 0x4d, 0x66, 0x75, 0x6d, 0x66, 0x75,
-0x3b, 0x4c, 0x77, 0x65, 0x7a, 0x69, 0x3b, 0x4d, 0x70, 0x61, 0x6c, 0x61, 0x6b, 0x61, 0x7a, 0x69, 0x3b, 0x5a, 0x3b, 0x4e,
-0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x4c, 0x3b, 0x4d,
-0x3b, 0x4d, 0x31, 0x3b, 0x4d, 0x32, 0x3b, 0x4d, 0x33, 0x3b, 0x4d, 0x34, 0x3b, 0x4d, 0x35, 0x3b, 0x4d, 0x36, 0x3b, 0x4d,
-0x37, 0x3b, 0x4d, 0x38, 0x3b, 0x4d, 0x39, 0x3b, 0x4d, 0x31, 0x30, 0x3b, 0x4d, 0x31, 0x31, 0x3b, 0x4d, 0x31, 0x32, 0x3b,
-0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x77, 0x61, 0x6e, 0x7a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72,
-0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x69, 0x6c, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20,
-0x6b, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x61, 0x6e,
-0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x74, 0x61, 0x6e, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x72,
-0x69, 0x20, 0x77, 0x61, 0x20, 0x73, 0x69, 0x74, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x73,
-0x61, 0x62, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6e, 0x61, 0x6e, 0x65, 0x3b, 0x4d, 0x77,
-0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x74, 0x69, 0x73, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61,
-0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d,
-0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x6f, 0x6a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69,
-0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x62, 0x69, 0x6c, 0x69, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b,
-0x4b, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x2d49, 0x2d4f,
-0x2d4f, 0x3b, 0x2d31, 0x2d55, 0x2d30, 0x3b, 0x2d4e, 0x2d30, 0x2d55, 0x3b, 0x2d49, 0x2d31, 0x2d54, 0x3b, 0x2d4e, 0x2d30, 0x2d62, 0x3b, 0x2d62, 0x2d53,
-0x2d4f, 0x3b, 0x2d62, 0x2d53, 0x2d4d, 0x3b, 0x2d56, 0x2d53, 0x2d5b, 0x3b, 0x2d5b, 0x2d53, 0x2d5c, 0x3b, 0x2d3d, 0x2d5c, 0x2d53, 0x3b, 0x2d4f, 0x2d53,
-0x2d61, 0x3b, 0x2d37, 0x2d53, 0x2d4a, 0x3b, 0x2d49, 0x2d4f, 0x2d4f, 0x2d30, 0x2d62, 0x2d54, 0x3b, 0x2d31, 0x2d55, 0x2d30, 0x2d62, 0x2d55, 0x3b, 0x2d4e,
-0x2d30, 0x2d55, 0x2d5a, 0x3b, 0x2d49, 0x2d31, 0x2d54, 0x2d49, 0x2d54, 0x3b, 0x2d4e, 0x2d30, 0x2d62, 0x2d62, 0x2d53, 0x3b, 0x2d62, 0x2d53, 0x2d4f, 0x2d62,
-0x2d53, 0x3b, 0x2d62, 0x2d53, 0x2d4d, 0x2d62, 0x2d53, 0x2d63, 0x3b, 0x2d56, 0x2d53, 0x2d5b, 0x2d5c, 0x3b, 0x2d5b, 0x2d53, 0x2d5c, 0x2d30, 0x2d4f, 0x2d31,
-0x2d49, 0x2d54, 0x3b, 0x2d3d, 0x2d5c, 0x2d53, 0x2d31, 0x2d54, 0x3b, 0x2d4f, 0x2d53, 0x2d61, 0x2d30, 0x2d4f, 0x2d31, 0x2d49, 0x2d54, 0x3b, 0x2d37, 0x2d53,
-0x2d4a, 0x2d30, 0x2d4f, 0x2d31, 0x2d49, 0x2d54, 0x3b, 0x2d49, 0x3b, 0x2d31, 0x3b, 0x2d4e, 0x3b, 0x2d49, 0x3b, 0x2d4e, 0x3b, 0x2d62, 0x3b, 0x2d62,
-0x3b, 0x2d56, 0x3b, 0x2d5b, 0x3b, 0x2d3d, 0x3b, 0x2d4f, 0x3b, 0x2d37, 0x3b, 0x69, 0x6e, 0x6e, 0x3b, 0x62, 0x1e5b, 0x61, 0x3b, 0x6d,
-0x61, 0x1e5b, 0x3b, 0x69, 0x62, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x79, 0x75, 0x6e, 0x3b, 0x79, 0x75, 0x6c, 0x3b, 0x263,
-0x75, 0x63, 0x3b, 0x63, 0x75, 0x74, 0x3b, 0x6b, 0x74, 0x75, 0x3b, 0x6e, 0x75, 0x77, 0x3b, 0x64, 0x75, 0x6a, 0x3b, 0x69,
-0x6e, 0x6e, 0x61, 0x79, 0x72, 0x3b, 0x62, 0x1e5b, 0x61, 0x79, 0x1e5b, 0x3b, 0x6d, 0x61, 0x1e5b, 0x1e63, 0x3b, 0x69, 0x62, 0x72,
-0x69, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x79, 0x75, 0x3b, 0x79, 0x75, 0x6e, 0x79, 0x75, 0x3b, 0x79, 0x75, 0x6c, 0x79, 0x75,
-0x7a, 0x3b, 0x263, 0x75, 0x63, 0x74, 0x3b, 0x63, 0x75, 0x74, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b, 0x6b, 0x74, 0x75, 0x62,
-0x72, 0x3b, 0x6e, 0x75, 0x77, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b, 0x64, 0x75, 0x6a, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b,
-0x69, 0x3b, 0x62, 0x3b, 0x6d, 0x3b, 0x69, 0x3b, 0x6d, 0x3b, 0x79, 0x3b, 0x79, 0x3b, 0x263, 0x3b, 0x63, 0x3b, 0x6b, 0x3b,
-0x6e, 0x3b, 0x64, 0x3b, 0x59, 0x65, 0x6e, 0x3b, 0x46, 0x75, 0x72, 0x3b, 0x4d, 0x65, 0x263, 0x3b, 0x59, 0x65, 0x62, 0x3b,
-0x4d, 0x61, 0x79, 0x3b, 0x59, 0x75, 0x6e, 0x3b, 0x59, 0x75, 0x6c, 0x3b, 0x194, 0x75, 0x63, 0x3b, 0x43, 0x74, 0x65, 0x3b,
-0x54, 0x75, 0x62, 0x3b, 0x4e, 0x75, 0x6e, 0x3b, 0x44, 0x75, 0x1e7, 0x3b, 0x59, 0x65, 0x6e, 0x6e, 0x61, 0x79, 0x65, 0x72,
-0x3b, 0x46, 0x75, 0x1e5b, 0x61, 0x72, 0x3b, 0x4d, 0x65, 0x263, 0x72, 0x65, 0x73, 0x3b, 0x59, 0x65, 0x62, 0x72, 0x69, 0x72,
-0x3b, 0x4d, 0x61, 0x79, 0x79, 0x75, 0x3b, 0x59, 0x75, 0x6e, 0x79, 0x75, 0x3b, 0x59, 0x75, 0x6c, 0x79, 0x75, 0x3b, 0x194,
-0x75, 0x63, 0x74, 0x3b, 0x43, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x1e5b, 0x3b, 0x54, 0x75, 0x62, 0x65, 0x1e5b, 0x3b, 0x4e, 0x75,
-0x6e, 0x65, 0x6d, 0x62, 0x65, 0x1e5b, 0x3b, 0x44, 0x75, 0x1e7, 0x65, 0x6d, 0x62, 0x65, 0x1e5b, 0x3b, 0x59, 0x3b, 0x46, 0x3b,
-0x4d, 0x3b, 0x59, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x194, 0x3b, 0x43, 0x3b, 0x54, 0x3b, 0x4e, 0x3b, 0x44, 0x3b,
-0x4b, 0x42, 0x5a, 0x3b, 0x4b, 0x42, 0x52, 0x3b, 0x4b, 0x53, 0x54, 0x3b, 0x4b, 0x4b, 0x4e, 0x3b, 0x4b, 0x54, 0x4e, 0x3b,
-0x4b, 0x4d, 0x4b, 0x3b, 0x4b, 0x4d, 0x53, 0x3b, 0x4b, 0x4d, 0x4e, 0x3b, 0x4b, 0x4d, 0x57, 0x3b, 0x4b, 0x4b, 0x4d, 0x3b,
-0x4b, 0x4e, 0x4b, 0x3b, 0x4b, 0x4e, 0x42, 0x3b, 0x4f, 0x6b, 0x77, 0x6f, 0x6b, 0x75, 0x62, 0x61, 0x6e, 0x7a, 0x61, 0x3b,
-0x4f, 0x6b, 0x77, 0x61, 0x6b, 0x61, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6b, 0x61, 0x73, 0x68, 0x61,
-0x74, 0x75, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6b, 0x61, 0x74, 0x61,
-0x61, 0x6e, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x61, 0x67, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61,
-0x6d, 0x75, 0x73, 0x68, 0x61, 0x6e, 0x6a, 0x75, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x75, 0x6e, 0x61, 0x61, 0x6e, 0x61,
-0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x77, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x69, 0x6b, 0x75, 0x6d,
-0x69, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6b, 0x75, 0x6d, 0x77, 0x65,
-0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x69, 0x62, 0x69, 0x72, 0x69, 0x3b,
-0x48, 0x75, 0x74, 0x3b, 0x56, 0x69, 0x6c, 0x3b, 0x44, 0x61, 0x74, 0x3b, 0x54, 0x61, 0x69, 0x3b, 0x48, 0x61, 0x6e, 0x3b,
-0x53, 0x69, 0x74, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x4e, 0x61, 0x6e, 0x3b, 0x54, 0x69, 0x73, 0x3b, 0x4b, 0x75, 0x6d, 0x3b,
-0x4b, 0x6d, 0x6a, 0x3b, 0x4b, 0x6d, 0x62, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77,
-0x61, 0x20, 0x68, 0x75, 0x74, 0x61, 0x6c, 0x61, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67,
-0x77, 0x61, 0x20, 0x77, 0x75, 0x76, 0x69, 0x6c, 0x69, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20,
-0x67, 0x77, 0x61, 0x20, 0x77, 0x75, 0x64, 0x61, 0x74, 0x75, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69,
-0x20, 0x67, 0x77, 0x61, 0x20, 0x77, 0x75, 0x74, 0x61, 0x69, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69,
-0x20, 0x67, 0x77, 0x61, 0x20, 0x77, 0x75, 0x68, 0x61, 0x6e, 0x75, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a,
-0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x73, 0x69, 0x74, 0x61, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69,
-0x20, 0x67, 0x77, 0x61, 0x20, 0x73, 0x61, 0x62, 0x61, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20,
-0x67, 0x77, 0x61, 0x20, 0x6e, 0x61, 0x6e, 0x65, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67,
-0x77, 0x61, 0x20, 0x74, 0x69, 0x73, 0x61, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77,
-0x61, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61,
-0x20, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x6f, 0x6a, 0x61, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65,
-0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x62, 0x69, 0x6c,
-0x69, 0x3b, 0x48, 0x3b, 0x56, 0x3b, 0x44, 0x3b, 0x54, 0x3b, 0x48, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x54, 0x3b,
-0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61,
-0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x79, 0x69, 0x3b, 0x4d, 0x65, 0x69,
-0x3b, 0x4a, 0x75, 0x6e, 0x79, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x79, 0x61, 0x69, 0x3b, 0x41, 0x67, 0x75, 0x73, 0x74, 0x69,
-0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76,
-0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x7a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62,
-0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x77, 0x69, 0x3b, 0x6d, 0x25b, 0x3b, 0x7a, 0x75, 0x77, 0x3b, 0x7a, 0x75, 0x6c, 0x3b,
-0x75, 0x74, 0x69, 0x3b, 0x73, 0x25b, 0x74, 0x3b, 0x254, 0x6b, 0x75, 0x3b, 0x6e, 0x6f, 0x77, 0x3b, 0x64, 0x65, 0x73, 0x3b,
-0x7a, 0x61, 0x6e, 0x77, 0x75, 0x79, 0x65, 0x3b, 0x66, 0x65, 0x62, 0x75, 0x72, 0x75, 0x79, 0x65, 0x3b, 0x6d, 0x61, 0x72,
-0x69, 0x73, 0x69, 0x3b, 0x61, 0x77, 0x69, 0x72, 0x69, 0x6c, 0x69, 0x3b, 0x6d, 0x25b, 0x3b, 0x7a, 0x75, 0x77, 0x25b, 0x6e,
-0x3b, 0x7a, 0x75, 0x6c, 0x75, 0x79, 0x65, 0x3b, 0x75, 0x74, 0x69, 0x3b, 0x73, 0x25b, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x72,
-0x75, 0x3b, 0x254, 0x6b, 0x75, 0x74, 0x254, 0x62, 0x75, 0x72, 0x75, 0x3b, 0x6e, 0x6f, 0x77, 0x61, 0x6e, 0x62, 0x75, 0x72,
-0x75, 0x3b, 0x64, 0x65, 0x73, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x75, 0x3b, 0x5a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b,
-0x4d, 0x3b, 0x5a, 0x3b, 0x5a, 0x3b, 0x55, 0x3b, 0x53, 0x3b, 0x186, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x4d, 0x62, 0x65, 0x3b,
-0x4b, 0x61, 0x69, 0x3b, 0x4b, 0x61, 0x74, 0x3b, 0x4b, 0x61, 0x6e, 0x3b, 0x47, 0x61, 0x74, 0x3b, 0x47, 0x61, 0x6e, 0x3b,
-0x4d, 0x75, 0x67, 0x3b, 0x4b, 0x6e, 0x6e, 0x3b, 0x4b, 0x65, 0x6e, 0x3b, 0x49, 0x6b, 0x75, 0x3b, 0x49, 0x6d, 0x77, 0x3b,
-0x49, 0x67, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6d, 0x62, 0x65, 0x72, 0x65, 0x3b, 0x4d,
-0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x129, 0x72, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20,
-0x77, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x68, 0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20,
-0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x6f,
-0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x74, 0x61, 0x74, 0x169, 0x3b,
-0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6d, 0x169, 0x67, 0x77, 0x61, 0x6e, 0x6a, 0x61, 0x3b, 0x4d, 0x77,
-0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20,
-0x77, 0x61, 0x20, 0x6b, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b,
-0x169, 0x6d, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x169, 0x6d, 0x69, 0x20, 0x6e,
-0x61, 0x20, 0x169, 0x6d, 0x77, 0x65, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x169, 0x6d,
-0x69, 0x20, 0x6e, 0x61, 0x20, 0x4b, 0x61, 0x129, 0x72, 0x129, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x47,
-0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x13a4, 0x13c3, 0x3b, 0x13a7, 0x13a6,
-0x3b, 0x13a0, 0x13c5, 0x3b, 0x13a7, 0x13ec, 0x3b, 0x13a0, 0x13c2, 0x3b, 0x13d5, 0x13ad, 0x3b, 0x13ab, 0x13f0, 0x3b, 0x13a6, 0x13b6, 0x3b, 0x13da,
-0x13b5, 0x3b, 0x13da, 0x13c2, 0x3b, 0x13c5, 0x13d3, 0x3b, 0x13a5, 0x13cd, 0x3b, 0x13a4, 0x13c3, 0x13b8, 0x13d4, 0x13c5, 0x3b, 0x13a7, 0x13a6, 0x13b5,
-0x3b, 0x13a0, 0x13c5, 0x13f1, 0x3b, 0x13a7, 0x13ec, 0x13c2, 0x3b, 0x13a0, 0x13c2, 0x13cd, 0x13ac, 0x13d8, 0x3b, 0x13d5, 0x13ad, 0x13b7, 0x13f1, 0x3b,
-0x13ab, 0x13f0, 0x13c9, 0x13c2, 0x3b, 0x13a6, 0x13b6, 0x13c2, 0x3b, 0x13da, 0x13b5, 0x13cd, 0x13d7, 0x3b, 0x13da, 0x13c2, 0x13c5, 0x13d7, 0x3b, 0x13c5,
-0x13d3, 0x13d5, 0x13c6, 0x3b, 0x13a5, 0x13cd, 0x13a9, 0x13f1, 0x3b, 0x13a4, 0x3b, 0x13a7, 0x3b, 0x13a0, 0x3b, 0x13a7, 0x3b, 0x13a0, 0x3b, 0x13d5,
-0x3b, 0x13ab, 0x3b, 0x13a6, 0x3b, 0x13da, 0x3b, 0x13da, 0x3b, 0x13c5, 0x3b, 0x13a5, 0x3b, 0x7a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x76,
-0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x76, 0x72, 0x3b, 0x6d, 0x65, 0x3b, 0x7a, 0x69, 0x6e, 0x3b, 0x7a, 0x69, 0x6c, 0x3b,
-0x6f, 0x75, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x73, 0x3b,
-0x7a, 0x61, 0x6e, 0x76, 0x69, 0x65, 0x3b, 0x66, 0x65, 0x76, 0x72, 0x69, 0x79, 0x65, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b,
-0x61, 0x76, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x65, 0x3b, 0x7a, 0x69, 0x6e, 0x3b, 0x7a, 0x69, 0x6c, 0x79, 0x65, 0x3b, 0x6f,
-0x75, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x61, 0x6d, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x3b, 0x6e, 0x6f, 0x76, 0x61,
-0x6d, 0x3b, 0x64, 0x65, 0x73, 0x61, 0x6d, 0x3b, 0x7a, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x61, 0x3b, 0x6d, 0x3b, 0x7a, 0x3b,
-0x7a, 0x3b, 0x6f, 0x3b, 0x73, 0x3b, 0x6f, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x4e, 0x74,
-0x61, 0x6e, 0x64, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x50, 0x69, 0x6c, 0x69, 0x3b, 0x4d,
-0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x54, 0x61, 0x74, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77,
-0x61, 0x20, 0x4e, 0x63, 0x68, 0x65, 0x63, 0x68, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e,
-0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e,
-0x6f, 0x20, 0x6e, 0x61, 0x20, 0x55, 0x6d, 0x6f, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e,
-0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4d, 0x69, 0x76, 0x69, 0x6c, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69,
-0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4d, 0x69, 0x74, 0x61, 0x74, 0x75,
-0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20,
-0x4e, 0x63, 0x68, 0x65, 0x63, 0x68, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79,
-0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20,
+0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4a, 0x3b,
+0x46, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b,
+0x44, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72,
+0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x2e,
+0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x73, 0x2e,
+0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x74,
+0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69,
+0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x6f, 0x6b,
+0x74, 0x6f, 0x62, 0x61, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d,
+0x62, 0x61, 0x72, 0x3b, 0x458, 0x430, 0x43d, 0x3b, 0x444, 0x435, 0x431, 0x3b, 0x43c, 0x430, 0x440, 0x3b, 0x430, 0x43f, 0x440, 0x3b,
+0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x3b, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x443, 0x433, 0x3b, 0x441, 0x435, 0x43f, 0x3b,
+0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x432, 0x3b, 0x434, 0x435, 0x446, 0x3b, 0x458, 0x430, 0x43d, 0x443, 0x430, 0x440, 0x3b, 0x444,
+0x435, 0x431, 0x440, 0x443, 0x430, 0x440, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b, 0x3b, 0x43c, 0x430,
+0x458, 0x3b, 0x458, 0x443, 0x43d, 0x438, 0x3b, 0x458, 0x443, 0x43b, 0x438, 0x3b, 0x430, 0x443, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441,
+0x435, 0x43f, 0x442, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x431, 0x430, 0x440, 0x3b, 0x43d, 0x43e, 0x432,
+0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x434, 0x435, 0x446, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x4a, 0x2d, 0x67, 0x75, 0x65,
+0x72, 0x3b, 0x54, 0x2d, 0x61, 0x72, 0x72, 0x65, 0x65, 0x3b, 0x4d, 0x61, 0x79, 0x72, 0x6e, 0x74, 0x3b, 0x41, 0x76, 0x72,
+0x72, 0x69, 0x6c, 0x3b, 0x42, 0x6f, 0x61, 0x6c, 0x64, 0x79, 0x6e, 0x3b, 0x4d, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x65, 0x65,
+0x3b, 0x4a, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x4c, 0x75, 0x61, 0x6e, 0x69, 0x73, 0x74, 0x79, 0x6e, 0x3b,
+0x4d, 0x2d, 0x66, 0x6f, 0x75, 0x79, 0x69, 0x72, 0x3b, 0x4a, 0x2d, 0x66, 0x6f, 0x75, 0x79, 0x69, 0x72, 0x3b, 0x4d, 0x2d,
+0x48, 0x6f, 0x75, 0x6e, 0x65, 0x79, 0x3b, 0x4d, 0x2d, 0x4e, 0x6f, 0x6c, 0x6c, 0x69, 0x63, 0x6b, 0x3b, 0x4a, 0x65, 0x72,
+0x72, 0x65, 0x79, 0x2d, 0x67, 0x65, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x54, 0x6f, 0x73, 0x68, 0x69, 0x61, 0x67, 0x68, 0x74,
+0x2d, 0x61, 0x72, 0x72, 0x65, 0x65, 0x3b, 0x4d, 0x61, 0x79, 0x72, 0x6e, 0x74, 0x3b, 0x41, 0x76, 0x65, 0x72, 0x69, 0x6c,
+0x3b, 0x42, 0x6f, 0x61, 0x6c, 0x64, 0x79, 0x6e, 0x3b, 0x4d, 0x65, 0x61, 0x6e, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x65, 0x65,
+0x3b, 0x4a, 0x65, 0x72, 0x72, 0x65, 0x79, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x4c, 0x75, 0x61, 0x6e, 0x69,
+0x73, 0x74, 0x79, 0x6e, 0x3b, 0x4d, 0x65, 0x61, 0x6e, 0x2d, 0x66, 0x6f, 0x75, 0x79, 0x69, 0x72, 0x3b, 0x4a, 0x65, 0x72,
+0x72, 0x65, 0x79, 0x2d, 0x66, 0x6f, 0x75, 0x79, 0x69, 0x72, 0x3b, 0x4d, 0x65, 0x65, 0x20, 0x48, 0x6f, 0x75, 0x6e, 0x65,
+0x79, 0x3b, 0x4d, 0x65, 0x65, 0x20, 0x6e, 0x79, 0x20, 0x4e, 0x6f, 0x6c, 0x6c, 0x69, 0x63, 0x6b, 0x3b, 0x47, 0x65, 0x6e,
+0x3b, 0x48, 0x77, 0x65, 0x3b, 0x4d, 0x65, 0x75, 0x3b, 0x45, 0x62, 0x72, 0x3b, 0x4d, 0x65, 0x3b, 0x4d, 0x65, 0x74, 0x3b,
+0x47, 0x6f, 0x72, 0x3b, 0x45, 0x73, 0x74, 0x3b, 0x47, 0x77, 0x6e, 0x3b, 0x48, 0x65, 0x64, 0x3b, 0x44, 0x75, 0x3b, 0x4b,
+0x65, 0x76, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x47, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x48, 0x77,
+0x65, 0x76, 0x72, 0x65, 0x72, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x4d, 0x65, 0x75, 0x72, 0x74, 0x68, 0x3b, 0x6d, 0x69, 0x73,
+0x20, 0x45, 0x62, 0x72, 0x65, 0x6c, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x4d, 0x65, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x4d, 0x65,
+0x74, 0x68, 0x65, 0x76, 0x65, 0x6e, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x47, 0x6f, 0x72, 0x74, 0x68, 0x65, 0x72, 0x65, 0x6e,
+0x3b, 0x6d, 0x69, 0x73, 0x20, 0x45, 0x73, 0x74, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x47, 0x77, 0x79, 0x6e, 0x6e, 0x67, 0x61,
+0x6c, 0x61, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x48, 0x65, 0x64, 0x72, 0x61, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x44, 0x75, 0x3b,
+0x6d, 0x69, 0x73, 0x20, 0x4b, 0x65, 0x76, 0x61, 0x72, 0x64, 0x68, 0x75, 0x3b, 0x53, 0x2d, 0x186, 0x3b, 0x4b, 0x2d, 0x186,
+0x3b, 0x45, 0x2d, 0x186, 0x3b, 0x45, 0x2d, 0x4f, 0x3b, 0x45, 0x2d, 0x4b, 0x3b, 0x4f, 0x2d, 0x41, 0x3b, 0x41, 0x2d, 0x4b,
+0x3b, 0x44, 0x2d, 0x186, 0x3b, 0x46, 0x2d, 0x190, 0x3b, 0x186, 0x2d, 0x41, 0x3b, 0x186, 0x2d, 0x4f, 0x3b, 0x4d, 0x2d, 0x186,
+0x3b, 0x53, 0x61, 0x6e, 0x64, 0x61, 0x2d, 0x186, 0x70, 0x25b, 0x70, 0x254, 0x6e, 0x3b, 0x4b, 0x77, 0x61, 0x6b, 0x77, 0x61,
+0x72, 0x2d, 0x186, 0x67, 0x79, 0x65, 0x66, 0x75, 0x6f, 0x3b, 0x45, 0x62, 0x254, 0x77, 0x2d, 0x186, 0x62, 0x65, 0x6e, 0x65,
+0x6d, 0x3b, 0x45, 0x62, 0x254, 0x62, 0x69, 0x72, 0x61, 0x2d, 0x4f, 0x66, 0x6f, 0x72, 0x69, 0x73, 0x75, 0x6f, 0x3b, 0x45,
+0x73, 0x75, 0x73, 0x6f, 0x77, 0x20, 0x41, 0x6b, 0x65, 0x74, 0x73, 0x65, 0x61, 0x62, 0x61, 0x2d, 0x4b, 0x254, 0x74, 0x254,
+0x6e, 0x69, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x62, 0x69, 0x72, 0x61, 0x64, 0x65, 0x2d, 0x41, 0x79, 0x25b, 0x77, 0x6f, 0x68,
+0x6f, 0x6d, 0x75, 0x6d, 0x75, 0x3b, 0x41, 0x79, 0x25b, 0x77, 0x6f, 0x68, 0x6f, 0x2d, 0x4b, 0x69, 0x74, 0x61, 0x77, 0x6f,
+0x6e, 0x73, 0x61, 0x3b, 0x44, 0x69, 0x66, 0x75, 0x75, 0x2d, 0x186, 0x73, 0x61, 0x6e, 0x64, 0x61, 0x61, 0x3b, 0x46, 0x61,
+0x6e, 0x6b, 0x77, 0x61, 0x2d, 0x190, 0x62, 0x254, 0x3b, 0x186, 0x62, 0x25b, 0x73, 0x25b, 0x2d, 0x41, 0x68, 0x69, 0x6e, 0x69,
+0x6d, 0x65, 0x3b, 0x186, 0x62, 0x65, 0x72, 0x25b, 0x66, 0x25b, 0x77, 0x2d, 0x4f, 0x62, 0x75, 0x62, 0x75, 0x6f, 0x3b, 0x4d,
+0x75, 0x6d, 0x75, 0x2d, 0x186, 0x70, 0x25b, 0x6e, 0x69, 0x6d, 0x62, 0x61, 0x3b, 0x91c, 0x93e, 0x928, 0x947, 0x935, 0x93e, 0x930,
+0x940, 0x3b, 0x92b, 0x947, 0x92c, 0x94d, 0x930, 0x941, 0x935, 0x93e, 0x930, 0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x90f,
+0x92a, 0x94d, 0x930, 0x93f, 0x932, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x92f, 0x3b, 0x906,
+0x917, 0x94b, 0x938, 0x94d, 0x924, 0x3b, 0x938, 0x92a, 0x94d, 0x91f, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x911, 0x915, 0x94d, 0x91f, 0x94b,
+0x92c, 0x930, 0x3b, 0x928, 0x94b, 0x935, 0x94d, 0x939, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x921, 0x93f, 0x938, 0x947, 0x902, 0x92c, 0x930,
+0x3b, 0x4a, 0x65, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x61, 0x3b, 0x45, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x65,
+0x3b, 0x4a, 0x75, 0x75, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x1ecc, 0x67, 0x1ecd, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x1ecc, 0x6b, 0x74,
+0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x4a, 0x65, 0x6e, 0x1ee5, 0x77, 0x61, 0x72, 0x1ecb, 0x3b, 0x46, 0x65,
+0x62, 0x72, 0x1ee5, 0x77, 0x61, 0x72, 0x1ecb, 0x3b, 0x4d, 0x61, 0x61, 0x63, 0x68, 0x1ecb, 0x3b, 0x45, 0x70, 0x72, 0x65, 0x6c,
+0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x1ecb, 0x3b, 0x1ecc, 0x67, 0x1ecd, 0x1ecd,
+0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x1ecc, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e,
+0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4d, 0x62, 0x65, 0x3b, 0x4b,
+0x65, 0x6c, 0x3b, 0x4b, 0x74, 0x169, 0x3b, 0x4b, 0x61, 0x6e, 0x3b, 0x4b, 0x74, 0x6e, 0x3b, 0x54, 0x68, 0x61, 0x3b, 0x4d,
+0x6f, 0x6f, 0x3b, 0x4e, 0x79, 0x61, 0x3b, 0x4b, 0x6e, 0x64, 0x3b, 0x128, 0x6b, 0x75, 0x3b, 0x128, 0x6b, 0x6d, 0x3b, 0x128,
+0x6b, 0x6c, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6d, 0x62, 0x65, 0x65, 0x3b, 0x4d, 0x77, 0x61, 0x69,
+0x20, 0x77, 0x61, 0x20, 0x6b, 0x65, 0x6c, 0x129, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x74,
+0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x61,
+0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20,
+0x74, 0x68, 0x61, 0x6e, 0x74, 0x68, 0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6d, 0x75,
+0x6f, 0x6e, 0x7a, 0x61, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6e, 0x79, 0x61, 0x61, 0x6e, 0x79, 0x61,
+0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20,
+0x77, 0x61, 0x20, 0x129, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x129, 0x6b, 0x75,
+0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x129, 0x6d, 0x77, 0x65, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x129,
+0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x69, 0x6c, 0x129, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b,
+0x4b, 0x3b, 0x54, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4b, 0x3b, 0x128, 0x3b, 0x128, 0x3b, 0x128, 0x3b, 0x5a, 0x65, 0x6e, 0x3b,
+0x46, 0x65, 0x76, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x76, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x67, 0x3b,
+0x4c, 0x75, 0x69, 0x3b, 0x41, 0x76, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x74, 0x75, 0x3b, 0x4e, 0x6f, 0x76, 0x3b,
+0x44, 0x69, 0x63, 0x3b, 0x5a, 0x65, 0x6e, 0xe2, 0x72, 0x3b, 0x46, 0x65, 0x76, 0x72, 0xe2, 0x72, 0x3b, 0x4d, 0x61, 0x72,
+0xe7, 0x3b, 0x41, 0x76, 0x72, 0xee, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x67, 0x6e, 0x3b, 0x4c, 0x75, 0x69,
+0x3b, 0x41, 0x76, 0x6f, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x4f, 0x74, 0x75, 0x62,
+0x61, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x44, 0x69, 0x63, 0x65, 0x6d, 0x62, 0x61, 0x72,
+0x3b, 0x5a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4c, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f,
+0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x64, 0x7a, 0x76, 0x3b, 0x64, 0x7a, 0x64, 0x3b, 0x74, 0x65, 0x64, 0x3b, 0x61, 0x66, 0x254,
+0x3b, 0x64, 0x61, 0x6d, 0x3b, 0x6d, 0x61, 0x73, 0x3b, 0x73, 0x69, 0x61, 0x3b, 0x64, 0x65, 0x61, 0x3b, 0x61, 0x6e, 0x79,
+0x3b, 0x6b, 0x65, 0x6c, 0x3b, 0x61, 0x64, 0x65, 0x3b, 0x64, 0x7a, 0x6d, 0x3b, 0x64, 0x7a, 0x6f, 0x76, 0x65, 0x3b, 0x64,
+0x7a, 0x6f, 0x64, 0x7a, 0x65, 0x3b, 0x74, 0x65, 0x64, 0x6f, 0x78, 0x65, 0x3b, 0x61, 0x66, 0x254, 0x66, 0x129, 0x65, 0x3b,
+0x64, 0x61, 0x6d, 0x61, 0x3b, 0x6d, 0x61, 0x73, 0x61, 0x3b, 0x73, 0x69, 0x61, 0x6d, 0x6c, 0x254, 0x6d, 0x3b, 0x64, 0x65,
+0x61, 0x73, 0x69, 0x61, 0x6d, 0x69, 0x6d, 0x65, 0x3b, 0x61, 0x6e, 0x79, 0x254, 0x6e, 0x79, 0x254, 0x3b, 0x6b, 0x65, 0x6c,
+0x65, 0x3b, 0x61, 0x64, 0x65, 0x25b, 0x6d, 0x65, 0x6b, 0x70, 0x254, 0x78, 0x65, 0x3b, 0x64, 0x7a, 0x6f, 0x6d, 0x65, 0x3b,
+0x64, 0x3b, 0x64, 0x3b, 0x74, 0x3b, 0x61, 0x3b, 0x64, 0x3b, 0x6d, 0x3b, 0x73, 0x3b, 0x64, 0x3b, 0x61, 0x3b, 0x6b, 0x3b,
+0x61, 0x3b, 0x64, 0x3b, 0x49, 0x61, 0x6e, 0x2e, 0x3b, 0x50, 0x65, 0x70, 0x2e, 0x3b, 0x4d, 0x61, 0x6c, 0x2e, 0x3b, 0x2bb,
+0x41, 0x70, 0x2e, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x49, 0x75, 0x6e, 0x2e, 0x3b, 0x49, 0x75, 0x6c, 0x2e, 0x3b, 0x2bb, 0x41,
+0x75, 0x2e, 0x3b, 0x4b, 0x65, 0x70, 0x2e, 0x3b, 0x2bb, 0x4f, 0x6b, 0x2e, 0x3b, 0x4e, 0x6f, 0x77, 0x2e, 0x3b, 0x4b, 0x65,
+0x6b, 0x2e, 0x3b, 0x49, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x69, 0x3b, 0x50, 0x65, 0x70, 0x65, 0x6c, 0x75, 0x61, 0x6c, 0x69,
+0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x6b, 0x69, 0x3b, 0x2bb, 0x41, 0x70, 0x65, 0x6c, 0x69, 0x6c, 0x61, 0x3b, 0x4d, 0x65, 0x69,
+0x3b, 0x49, 0x75, 0x6e, 0x65, 0x3b, 0x49, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x2bb, 0x41, 0x75, 0x6b, 0x61, 0x6b, 0x65, 0x3b,
+0x4b, 0x65, 0x70, 0x61, 0x6b, 0x65, 0x6d, 0x61, 0x70, 0x61, 0x3b, 0x2bb, 0x4f, 0x6b, 0x61, 0x6b, 0x6f, 0x70, 0x61, 0x3b,
+0x4e, 0x6f, 0x77, 0x65, 0x6d, 0x61, 0x70, 0x61, 0x3b, 0x4b, 0x65, 0x6b, 0x65, 0x6d, 0x61, 0x70, 0x61, 0x3b, 0x45, 0x6e,
+0x65, 0x3b, 0x50, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x48, 0x75,
+0x6e, 0x3b, 0x48, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f,
+0x62, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x45, 0x6e, 0x65, 0x72, 0x6f, 0x3b, 0x50, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f, 0x3b,
+0x4d, 0x61, 0x72, 0x73, 0x6f, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x6f, 0x3b, 0x48, 0x75, 0x6e,
+0x79, 0x6f, 0x3b, 0x48, 0x75, 0x6c, 0x79, 0x6f, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x79,
+0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x4f, 0x6b, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x4e, 0x6f, 0x62, 0x79, 0x65, 0x6d,
+0x62, 0x72, 0x65, 0x3b, 0x44, 0x69, 0x73, 0x79, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x45, 0x3b, 0x50, 0x3b, 0x4d, 0x3b,
+0x41, 0x3b, 0x4d, 0x3b, 0x48, 0x75, 0x6e, 0x3b, 0x48, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b,
+0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x62, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x46,
+0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61,
+0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x63, 0x68, 0x74,
+0x3b, 0x53, 0x65, 0x70, 0x74, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x6f, 0x62, 0x65, 0x72, 0x3b,
+0x4e, 0x6f, 0x76, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0xa2cd, 0xa1aa,
+0x3b, 0xa44d, 0xa1aa, 0x3b, 0xa315, 0xa1aa, 0x3b, 0xa1d6, 0xa1aa, 0x3b, 0xa26c, 0xa1aa, 0x3b, 0xa0d8, 0xa1aa, 0x3b, 0xa3c3, 0xa1aa, 0x3b, 0xa246,
+0xa1aa, 0x3b, 0xa22c, 0xa1aa, 0x3b, 0xa2b0, 0xa1aa, 0x3b, 0xa2b0, 0xa2aa, 0xa1aa, 0x3b, 0xa2b0, 0xa44b, 0xa1aa, 0x3b, 0x4a, 0x61, 0x6e, 0x2e,
+0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x69, 0x3b,
+0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65, 0x70, 0x2e, 0x3b,
+0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x7a, 0x2e, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61,
+0x61, 0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x61, 0x72, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72,
+0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67,
+0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x76, 0x65,
+0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b,
+0x6f, 0x111, 0x111, 0x6a, 0x3b, 0x67, 0x75, 0x6f, 0x76, 0x3b, 0x6e, 0x6a, 0x75, 0x6b, 0x3b, 0x63, 0x75, 0x6f, 0x3b, 0x6d,
+0x69, 0x65, 0x73, 0x3b, 0x67, 0x65, 0x61, 0x73, 0x3b, 0x73, 0x75, 0x6f, 0x69, 0x3b, 0x62, 0x6f, 0x72, 0x67, 0x3b, 0x10d,
+0x61, 0x6b, 0x10d, 0x3b, 0x67, 0x6f, 0x6c, 0x67, 0x3b, 0x73, 0x6b, 0xe1, 0x62, 0x3b, 0x6a, 0x75, 0x6f, 0x76, 0x3b, 0x6f,
+0x111, 0x111, 0x61, 0x6a, 0x61, 0x67, 0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x67, 0x75, 0x6f, 0x76, 0x76, 0x61, 0x6d,
+0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x6e, 0x6a, 0x75, 0x6b, 0x10d, 0x61, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x63, 0x75, 0x6f,
+0x14b, 0x6f, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x6d, 0x69, 0x65, 0x73, 0x73, 0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b,
+0x67, 0x65, 0x61, 0x73, 0x73, 0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x73, 0x75, 0x6f, 0x69, 0x64, 0x6e, 0x65, 0x6d,
+0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x62, 0x6f, 0x72, 0x67, 0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x10d, 0x61, 0x6b, 0x10d,
+0x61, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x67, 0x6f, 0x6c, 0x67, 0x67, 0x6f, 0x74, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b,
+0x73, 0x6b, 0xe1, 0x62, 0x6d, 0x61, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x6a, 0x75, 0x6f, 0x76, 0x6c, 0x61, 0x6d, 0xe1,
+0x6e, 0x6e, 0x75, 0x3b, 0x4f, 0x3b, 0x47, 0x3b, 0x4e, 0x3b, 0x43, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x53, 0x3b, 0x42, 0x3b,
+0x10c, 0x3b, 0x47, 0x3b, 0x53, 0x3b, 0x4a, 0x3b, 0x6f, 0x111, 0x111, 0x6a, 0x3b, 0x67, 0x75, 0x6f, 0x76, 0x3b, 0x6e, 0x6a,
+0x75, 0x6b, 0x3b, 0x63, 0x75, 0x6f, 0x14b, 0x3b, 0x6d, 0x69, 0x65, 0x73, 0x3b, 0x67, 0x65, 0x61, 0x73, 0x3b, 0x73, 0x75,
+0x6f, 0x69, 0x3b, 0x62, 0x6f, 0x72, 0x67, 0x3b, 0x10d, 0x61, 0x6b, 0x10d, 0x3b, 0x67, 0x6f, 0x6c, 0x67, 0x3b, 0x73, 0x6b,
+0xe1, 0x62, 0x3b, 0x6a, 0x75, 0x6f, 0x76, 0x3b, 0x43, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x63, 0x3b,
+0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x43, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x74, 0x3b,
+0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x62, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x43, 0x68, 0x61, 0x6e,
+0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x75, 0x72, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b,
+0x41, 0x70, 0x69, 0x72, 0x69, 0x72, 0x69, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x43, 0x68, 0x75,
+0x6c, 0x61, 0x69, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b,
+0x4f, 0x6b, 0x69, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x62, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65,
+0x6d, 0x62, 0x61, 0x3b, 0x43, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x43, 0x3b, 0x41, 0x3b,
+0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x49, 0x6d, 0x62, 0x3b, 0x4b, 0x61, 0x77, 0x3b, 0x4b, 0x61, 0x64, 0x3b,
+0x4b, 0x61, 0x6e, 0x3b, 0x4b, 0x61, 0x73, 0x3b, 0x4b, 0x61, 0x72, 0x3b, 0x4d, 0x66, 0x75, 0x3b, 0x57, 0x75, 0x6e, 0x3b,
+0x49, 0x6b, 0x65, 0x3b, 0x49, 0x6b, 0x75, 0x3b, 0x49, 0x6d, 0x77, 0x3b, 0x49, 0x77, 0x69, 0x3b, 0x4d, 0x6f, 0x72, 0x69,
+0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x69, 0x6d, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68,
+0x77, 0x61, 0x20, 0x6b, 0x61, 0x77, 0x69, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6b, 0x61,
+0x64, 0x61, 0x64, 0x75, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b,
+0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x73, 0x61, 0x6e, 0x75, 0x3b, 0x4d, 0x6f, 0x72,
+0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x64, 0x75, 0x3b, 0x4d, 0x6f, 0x72,
+0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6d, 0x66, 0x75, 0x6e, 0x67, 0x61, 0x64, 0x65, 0x3b, 0x4d, 0x6f, 0x72, 0x69,
+0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x77, 0x75, 0x6e, 0x79, 0x61, 0x6e, 0x79, 0x61, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20,
+0x67, 0x68, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77,
+0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x69, 0x6b,
+0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x69, 0x6d, 0x77, 0x65, 0x72, 0x69, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67,
+0x68, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x69, 0x77, 0x69, 0x3b, 0x49, 0x3b, 0x4b,
+0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b, 0x57, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49,
+0x3b, 0x73, 0x69, 0x69, 0x3b, 0x63, 0x6f, 0x6c, 0x3b, 0x6d, 0x62, 0x6f, 0x3b, 0x73, 0x65, 0x65, 0x3b, 0x64, 0x75, 0x75,
+0x3b, 0x6b, 0x6f, 0x72, 0x3b, 0x6d, 0x6f, 0x72, 0x3b, 0x6a, 0x75, 0x6b, 0x3b, 0x73, 0x6c, 0x74, 0x3b, 0x79, 0x61, 0x72,
+0x3b, 0x6a, 0x6f, 0x6c, 0x3b, 0x62, 0x6f, 0x77, 0x3b, 0x73, 0x69, 0x69, 0x6c, 0x6f, 0x3b, 0x63, 0x6f, 0x6c, 0x74, 0x65,
+0x3b, 0x6d, 0x62, 0x6f, 0x6f, 0x79, 0x3b, 0x73, 0x65, 0x65, 0x257, 0x74, 0x6f, 0x3b, 0x64, 0x75, 0x75, 0x6a, 0x61, 0x6c,
+0x3b, 0x6b, 0x6f, 0x72, 0x73, 0x65, 0x3b, 0x6d, 0x6f, 0x72, 0x73, 0x6f, 0x3b, 0x6a, 0x75, 0x6b, 0x6f, 0x3b, 0x73, 0x69,
+0x69, 0x6c, 0x74, 0x6f, 0x3b, 0x79, 0x61, 0x72, 0x6b, 0x6f, 0x6d, 0x61, 0x61, 0x3b, 0x6a, 0x6f, 0x6c, 0x61, 0x6c, 0x3b,
+0x62, 0x6f, 0x77, 0x74, 0x65, 0x3b, 0x73, 0x3b, 0x63, 0x3b, 0x6d, 0x3b, 0x73, 0x3b, 0x64, 0x3b, 0x6b, 0x3b, 0x6d, 0x3b,
+0x6a, 0x3b, 0x73, 0x3b, 0x79, 0x3b, 0x6a, 0x3b, 0x62, 0x3b, 0x4a, 0x45, 0x4e, 0x3b, 0x57, 0x4b, 0x52, 0x3b, 0x57, 0x47,
+0x54, 0x3b, 0x57, 0x4b, 0x4e, 0x3b, 0x57, 0x54, 0x4e, 0x3b, 0x57, 0x54, 0x44, 0x3b, 0x57, 0x4d, 0x4a, 0x3b, 0x57, 0x4e,
+0x4e, 0x3b, 0x57, 0x4b, 0x44, 0x3b, 0x57, 0x49, 0x4b, 0x3b, 0x57, 0x4d, 0x57, 0x3b, 0x44, 0x49, 0x54, 0x3b, 0x4e, 0x6a,
+0x65, 0x6e, 0x75, 0x61, 0x72, 0x129, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x65, 0x72, 0x129,
+0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77, 0x65,
+0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20,
+0x67, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61,
+0x6e, 0x64, 0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x6d, 0x169, 0x67, 0x77, 0x61,
+0x6e, 0x6a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x6e, 0x61, 0x3b,
+0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65,
+0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x169, 0x6d, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x69,
+0x6b, 0x169, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x169, 0x6d, 0x77, 0x65, 0x3b, 0x4e, 0x64, 0x69, 0x74, 0x68, 0x65, 0x6d,
+0x62, 0x61, 0x3b, 0x4a, 0x3b, 0x4b, 0x3b, 0x47, 0x3b, 0x4b, 0x3b, 0x47, 0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b,
+0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x44, 0x3b, 0x4f, 0x62, 0x6f, 0x3b, 0x57, 0x61, 0x61, 0x3b, 0x4f, 0x6b, 0x75, 0x3b, 0x4f,
+0x6e, 0x67, 0x3b, 0x49, 0x6d, 0x65, 0x3b, 0x49, 0x6c, 0x65, 0x3b, 0x53, 0x61, 0x70, 0x3b, 0x49, 0x73, 0x69, 0x3b, 0x53,
+0x61, 0x61, 0x3b, 0x54, 0x6f, 0x6d, 0x3b, 0x54, 0x6f, 0x62, 0x3b, 0x54, 0x6f, 0x77, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20,
+0x6c, 0x65, 0x20, 0x6f, 0x62, 0x6f, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x77, 0x61, 0x61, 0x72, 0x65,
+0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x6f, 0x6b, 0x75, 0x6e, 0x69, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20,
+0x6c, 0x65, 0x20, 0x6f, 0x6e, 0x67, 0x2019, 0x77, 0x61, 0x6e, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x69,
+0x6d, 0x65, 0x74, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x69, 0x6c, 0x65, 0x3b, 0x4c, 0x61, 0x70, 0x61,
+0x20, 0x6c, 0x65, 0x20, 0x73, 0x61, 0x70, 0x61, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x69, 0x73, 0x69,
+0x65, 0x74, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x73, 0x61, 0x61, 0x6c, 0x3b, 0x4c, 0x61, 0x70, 0x61,
+0x20, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x6d, 0x6f, 0x6e, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x74, 0x6f,
+0x6d, 0x6f, 0x6e, 0x20, 0x6f, 0x62, 0x6f, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x6d, 0x6f,
+0x6e, 0x20, 0x77, 0x61, 0x61, 0x72, 0x65, 0x3b, 0x4f, 0x3b, 0x57, 0x3b, 0x4f, 0x3b, 0x4f, 0x3b, 0x49, 0x3b, 0x49, 0x3b,
+0x53, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x76, 0x3b,
+0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b,
+0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x74, 0x75, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x63, 0x3b,
+0x4a, 0x61, 0x6e, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x46, 0x65, 0x76, 0x72, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x4d, 0x61, 0x72,
+0x63, 0x6f, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x6f, 0x3b, 0x4a, 0x75, 0x6e, 0x68, 0x6f, 0x3b,
+0x4a, 0x75, 0x6c, 0x68, 0x6f, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x65, 0x6d, 0x62,
+0x72, 0x6f, 0x3b, 0x4f, 0x74, 0x75, 0x62, 0x72, 0x6f, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x44,
+0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x5a, 0x69, 0x62, 0x3b, 0x4e, 0x68, 0x6c, 0x6f, 0x3b, 0x4d, 0x62, 0x69,
+0x3b, 0x4d, 0x61, 0x62, 0x3b, 0x4e, 0x6b, 0x77, 0x3b, 0x4e, 0x68, 0x6c, 0x61, 0x3b, 0x4e, 0x74, 0x75, 0x3b, 0x4e, 0x63,
+0x77, 0x3b, 0x4d, 0x70, 0x61, 0x6e, 0x3b, 0x4d, 0x66, 0x75, 0x3b, 0x4c, 0x77, 0x65, 0x3b, 0x4d, 0x70, 0x61, 0x6c, 0x3b,
+0x5a, 0x69, 0x62, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x6c, 0x61, 0x3b, 0x4e, 0x68, 0x6c, 0x6f, 0x6c, 0x61, 0x6e, 0x6a, 0x61,
+0x3b, 0x4d, 0x62, 0x69, 0x6d, 0x62, 0x69, 0x74, 0x68, 0x6f, 0x3b, 0x4d, 0x61, 0x62, 0x61, 0x73, 0x61, 0x3b, 0x4e, 0x6b,
+0x77, 0x65, 0x6e, 0x6b, 0x77, 0x65, 0x7a, 0x69, 0x3b, 0x4e, 0x68, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x61, 0x3b, 0x4e,
+0x74, 0x75, 0x6c, 0x69, 0x6b, 0x61, 0x7a, 0x69, 0x3b, 0x4e, 0x63, 0x77, 0x61, 0x62, 0x61, 0x6b, 0x61, 0x7a, 0x69, 0x3b,
+0x4d, 0x70, 0x61, 0x6e, 0x64, 0x75, 0x6c, 0x61, 0x3b, 0x4d, 0x66, 0x75, 0x6d, 0x66, 0x75, 0x3b, 0x4c, 0x77, 0x65, 0x7a,
+0x69, 0x3b, 0x4d, 0x70, 0x61, 0x6c, 0x61, 0x6b, 0x61, 0x7a, 0x69, 0x3b, 0x5a, 0x3b, 0x4e, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b,
+0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x31, 0x3b, 0x4d,
+0x32, 0x3b, 0x4d, 0x33, 0x3b, 0x4d, 0x34, 0x3b, 0x4d, 0x35, 0x3b, 0x4d, 0x36, 0x3b, 0x4d, 0x37, 0x3b, 0x4d, 0x38, 0x3b,
+0x4d, 0x39, 0x3b, 0x4d, 0x31, 0x30, 0x3b, 0x4d, 0x31, 0x31, 0x3b, 0x4d, 0x31, 0x32, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69,
+0x20, 0x77, 0x61, 0x20, 0x6b, 0x77, 0x61, 0x6e, 0x7a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20,
+0x6b, 0x61, 0x69, 0x6c, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x61, 0x74,
+0x75, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x65,
+0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x74, 0x61, 0x6e, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20,
+0x73, 0x69, 0x74, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x73, 0x61, 0x62, 0x61, 0x3b, 0x4d,
+0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6e, 0x61, 0x6e, 0x65, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77,
+0x61, 0x20, 0x74, 0x69, 0x73, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d,
+0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20,
+0x6d, 0x6f, 0x6a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20,
+0x6e, 0x61, 0x20, 0x6d, 0x62, 0x69, 0x6c, 0x69, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x53,
+0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x2d49, 0x2d4f, 0x2d4f, 0x3b, 0x2d31, 0x2d55, 0x2d30,
+0x3b, 0x2d4e, 0x2d30, 0x2d55, 0x3b, 0x2d49, 0x2d31, 0x2d54, 0x3b, 0x2d4e, 0x2d30, 0x2d62, 0x3b, 0x2d62, 0x2d53, 0x2d4f, 0x3b, 0x2d62, 0x2d53, 0x2d4d,
+0x3b, 0x2d56, 0x2d53, 0x2d5b, 0x3b, 0x2d5b, 0x2d53, 0x2d5c, 0x3b, 0x2d3d, 0x2d5c, 0x2d53, 0x3b, 0x2d4f, 0x2d53, 0x2d61, 0x3b, 0x2d37, 0x2d53, 0x2d4a,
+0x3b, 0x2d49, 0x2d4f, 0x2d4f, 0x2d30, 0x2d62, 0x2d54, 0x3b, 0x2d31, 0x2d55, 0x2d30, 0x2d62, 0x2d55, 0x3b, 0x2d4e, 0x2d30, 0x2d55, 0x2d5a, 0x3b, 0x2d49,
+0x2d31, 0x2d54, 0x2d49, 0x2d54, 0x3b, 0x2d4e, 0x2d30, 0x2d62, 0x2d62, 0x2d53, 0x3b, 0x2d62, 0x2d53, 0x2d4f, 0x2d62, 0x2d53, 0x3b, 0x2d62, 0x2d53, 0x2d4d,
+0x2d62, 0x2d53, 0x2d63, 0x3b, 0x2d56, 0x2d53, 0x2d5b, 0x2d5c, 0x3b, 0x2d5b, 0x2d53, 0x2d5c, 0x2d30, 0x2d4f, 0x2d31, 0x2d49, 0x2d54, 0x3b, 0x2d3d, 0x2d5c,
+0x2d53, 0x2d31, 0x2d54, 0x3b, 0x2d4f, 0x2d53, 0x2d61, 0x2d30, 0x2d4f, 0x2d31, 0x2d49, 0x2d54, 0x3b, 0x2d37, 0x2d53, 0x2d4a, 0x2d30, 0x2d4f, 0x2d31, 0x2d49,
+0x2d54, 0x3b, 0x2d49, 0x3b, 0x2d31, 0x3b, 0x2d4e, 0x3b, 0x2d49, 0x3b, 0x2d4e, 0x3b, 0x2d62, 0x3b, 0x2d62, 0x3b, 0x2d56, 0x3b, 0x2d5b, 0x3b,
+0x2d3d, 0x3b, 0x2d4f, 0x3b, 0x2d37, 0x3b, 0x69, 0x6e, 0x6e, 0x3b, 0x62, 0x1e5b, 0x61, 0x3b, 0x6d, 0x61, 0x1e5b, 0x3b, 0x69, 0x62,
+0x72, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x79, 0x75, 0x6e, 0x3b, 0x79, 0x75, 0x6c, 0x3b, 0x263, 0x75, 0x63, 0x3b, 0x63, 0x75,
+0x74, 0x3b, 0x6b, 0x74, 0x75, 0x3b, 0x6e, 0x75, 0x77, 0x3b, 0x64, 0x75, 0x6a, 0x3b, 0x69, 0x6e, 0x6e, 0x61, 0x79, 0x72,
+0x3b, 0x62, 0x1e5b, 0x61, 0x79, 0x1e5b, 0x3b, 0x6d, 0x61, 0x1e5b, 0x1e63, 0x3b, 0x69, 0x62, 0x72, 0x69, 0x72, 0x3b, 0x6d, 0x61,
+0x79, 0x79, 0x75, 0x3b, 0x79, 0x75, 0x6e, 0x79, 0x75, 0x3b, 0x79, 0x75, 0x6c, 0x79, 0x75, 0x7a, 0x3b, 0x263, 0x75, 0x63,
+0x74, 0x3b, 0x63, 0x75, 0x74, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b, 0x6b, 0x74, 0x75, 0x62, 0x72, 0x3b, 0x6e, 0x75, 0x77,
+0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b, 0x64, 0x75, 0x6a, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b, 0x69, 0x3b, 0x62, 0x3b, 0x6d,
+0x3b, 0x69, 0x3b, 0x6d, 0x3b, 0x79, 0x3b, 0x79, 0x3b, 0x263, 0x3b, 0x63, 0x3b, 0x6b, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 0x59,
+0x65, 0x6e, 0x3b, 0x46, 0x75, 0x72, 0x3b, 0x4d, 0x65, 0x263, 0x3b, 0x59, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x59,
+0x75, 0x6e, 0x3b, 0x59, 0x75, 0x6c, 0x3b, 0x194, 0x75, 0x63, 0x3b, 0x43, 0x74, 0x65, 0x3b, 0x54, 0x75, 0x62, 0x3b, 0x57,
+0x61, 0x6d, 0x3b, 0x44, 0x75, 0x6a, 0x3b, 0x59, 0x65, 0x6e, 0x6e, 0x61, 0x79, 0x65, 0x72, 0x3b, 0x46, 0x75, 0x1e5b, 0x61,
+0x72, 0x3b, 0x4d, 0x65, 0x263, 0x72, 0x65, 0x73, 0x3b, 0x59, 0x65, 0x62, 0x72, 0x69, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x79,
+0x75, 0x3b, 0x59, 0x75, 0x6e, 0x79, 0x75, 0x3b, 0x59, 0x75, 0x6c, 0x79, 0x75, 0x3b, 0x194, 0x75, 0x63, 0x74, 0x3b, 0x43,
+0x74, 0x65, 0x6d, 0x62, 0x65, 0x1e5b, 0x3b, 0x54, 0x75, 0x62, 0x65, 0x1e5b, 0x3b, 0x57, 0x61, 0x6d, 0x62, 0x65, 0x1e5b, 0x3b,
+0x44, 0x75, 0x1e7, 0x65, 0x6d, 0x62, 0x65, 0x1e5b, 0x3b, 0x59, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x4d, 0x3b, 0x59,
+0x3b, 0x59, 0x3b, 0x194, 0x3b, 0x43, 0x3b, 0x54, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x59, 0x65, 0x6e, 0x3b, 0x46, 0x75, 0x72,
+0x3b, 0x4d, 0x65, 0x263, 0x3b, 0x59, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x59, 0x75, 0x6e, 0x3b, 0x59, 0x75, 0x6c,
+0x3b, 0x194, 0x75, 0x63, 0x3b, 0x43, 0x74, 0x65, 0x3b, 0x54, 0x75, 0x62, 0x3b, 0x4e, 0x75, 0x6e, 0x3b, 0x44, 0x75, 0x1e7,
+0x3b, 0x59, 0x65, 0x6e, 0x6e, 0x61, 0x79, 0x65, 0x72, 0x3b, 0x46, 0x75, 0x1e5b, 0x61, 0x72, 0x3b, 0x4d, 0x65, 0x263, 0x72,
+0x65, 0x73, 0x3b, 0x59, 0x65, 0x62, 0x72, 0x69, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x79, 0x75, 0x3b, 0x59, 0x75, 0x6e, 0x79,
+0x75, 0x3b, 0x59, 0x75, 0x6c, 0x79, 0x75, 0x3b, 0x194, 0x75, 0x63, 0x74, 0x3b, 0x43, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x1e5b,
+0x3b, 0x54, 0x75, 0x62, 0x65, 0x1e5b, 0x3b, 0x4e, 0x75, 0x6e, 0x65, 0x6d, 0x62, 0x65, 0x1e5b, 0x3b, 0x44, 0x75, 0x1e7, 0x65,
+0x6d, 0x62, 0x65, 0x1e5b, 0x3b, 0x59, 0x3b, 0x46, 0x3b, 0x194, 0x3b, 0x42, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4c, 0x3b, 0x43,
+0x3b, 0x54, 0x3b, 0x52, 0x3b, 0x57, 0x3b, 0x44, 0x3b, 0x4b, 0x42, 0x5a, 0x3b, 0x4b, 0x42, 0x52, 0x3b, 0x4b, 0x53, 0x54,
+0x3b, 0x4b, 0x4b, 0x4e, 0x3b, 0x4b, 0x54, 0x4e, 0x3b, 0x4b, 0x4d, 0x4b, 0x3b, 0x4b, 0x4d, 0x53, 0x3b, 0x4b, 0x4d, 0x4e,
+0x3b, 0x4b, 0x4d, 0x57, 0x3b, 0x4b, 0x4b, 0x4d, 0x3b, 0x4b, 0x4e, 0x4b, 0x3b, 0x4b, 0x4e, 0x42, 0x3b, 0x4f, 0x6b, 0x77,
+0x6f, 0x6b, 0x75, 0x62, 0x61, 0x6e, 0x7a, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6b, 0x61, 0x62, 0x69, 0x72, 0x69, 0x3b,
+0x4f, 0x6b, 0x77, 0x61, 0x6b, 0x61, 0x73, 0x68, 0x61, 0x74, 0x75, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6b, 0x61, 0x6e, 0x61,
+0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6b, 0x61, 0x74, 0x61, 0x61, 0x6e, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x75, 0x6b,
+0x61, 0x61, 0x67, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x75, 0x73, 0x68, 0x61, 0x6e, 0x6a, 0x75, 0x3b, 0x4f, 0x6b,
+0x77, 0x61, 0x6d, 0x75, 0x6e, 0x61, 0x61, 0x6e, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x77, 0x65, 0x6e, 0x64, 0x61,
+0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x69, 0x6b, 0x75, 0x6d, 0x69,
+0x20, 0x6e, 0x61, 0x20, 0x6b, 0x75, 0x6d, 0x77, 0x65, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20,
+0x6e, 0x61, 0x20, 0x69, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x48, 0x75, 0x74, 0x3b, 0x56, 0x69, 0x6c, 0x3b, 0x44, 0x61, 0x74,
+0x3b, 0x54, 0x61, 0x69, 0x3b, 0x48, 0x61, 0x6e, 0x3b, 0x53, 0x69, 0x74, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x4e, 0x61, 0x6e,
+0x3b, 0x54, 0x69, 0x73, 0x3b, 0x4b, 0x75, 0x6d, 0x3b, 0x4b, 0x6d, 0x6a, 0x3b, 0x4b, 0x6d, 0x62, 0x3b, 0x70, 0x61, 0x20,
+0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x68, 0x75, 0x74, 0x61, 0x6c, 0x61, 0x3b, 0x70, 0x61,
+0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x77, 0x75, 0x76, 0x69, 0x6c, 0x69, 0x3b, 0x70,
+0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x77, 0x75, 0x64, 0x61, 0x74, 0x75, 0x3b,
+0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x77, 0x75, 0x74, 0x61, 0x69, 0x3b,
+0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x77, 0x75, 0x68, 0x61, 0x6e, 0x75,
+0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x73, 0x69, 0x74, 0x61, 0x3b,
+0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x73, 0x61, 0x62, 0x61, 0x3b, 0x70,
+0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x6e, 0x61, 0x6e, 0x65, 0x3b, 0x70, 0x61,
+0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x74, 0x69, 0x73, 0x61, 0x3b, 0x70, 0x61, 0x20,
+0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x70, 0x61, 0x20, 0x6d,
+0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x6f,
+0x6a, 0x61, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x6b, 0x75, 0x6d,
+0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x62, 0x69, 0x6c, 0x69, 0x3b, 0x48, 0x3b, 0x56, 0x3b, 0x44, 0x3b, 0x54, 0x3b, 0x48,
+0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61,
+0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x41, 0x70,
+0x72, 0x69, 0x6c, 0x79, 0x69, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x79, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x79,
+0x61, 0x69, 0x3b, 0x41, 0x67, 0x75, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f,
+0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62,
+0x61, 0x3b, 0x7a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x77, 0x69, 0x3b, 0x6d, 0x25b,
+0x3b, 0x7a, 0x75, 0x77, 0x3b, 0x7a, 0x75, 0x6c, 0x3b, 0x75, 0x74, 0x69, 0x3b, 0x73, 0x25b, 0x74, 0x3b, 0x254, 0x6b, 0x75,
+0x3b, 0x6e, 0x6f, 0x77, 0x3b, 0x64, 0x65, 0x73, 0x3b, 0x7a, 0x61, 0x6e, 0x77, 0x75, 0x79, 0x65, 0x3b, 0x66, 0x65, 0x62,
+0x75, 0x72, 0x75, 0x79, 0x65, 0x3b, 0x6d, 0x61, 0x72, 0x69, 0x73, 0x69, 0x3b, 0x61, 0x77, 0x69, 0x72, 0x69, 0x6c, 0x69,
+0x3b, 0x6d, 0x25b, 0x3b, 0x7a, 0x75, 0x77, 0x25b, 0x6e, 0x3b, 0x7a, 0x75, 0x6c, 0x75, 0x79, 0x65, 0x3b, 0x75, 0x74, 0x69,
+0x3b, 0x73, 0x25b, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x75, 0x3b, 0x254, 0x6b, 0x75, 0x74, 0x254, 0x62, 0x75, 0x72, 0x75,
+0x3b, 0x6e, 0x6f, 0x77, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x75, 0x3b, 0x64, 0x65, 0x73, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x75,
+0x3b, 0x5a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x5a, 0x3b, 0x5a, 0x3b, 0x55, 0x3b, 0x53, 0x3b, 0x186,
+0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x4d, 0x62, 0x65, 0x3b, 0x4b, 0x61, 0x69, 0x3b, 0x4b, 0x61, 0x74, 0x3b, 0x4b, 0x61, 0x6e,
+0x3b, 0x47, 0x61, 0x74, 0x3b, 0x47, 0x61, 0x6e, 0x3b, 0x4d, 0x75, 0x67, 0x3b, 0x4b, 0x6e, 0x6e, 0x3b, 0x4b, 0x65, 0x6e,
+0x3b, 0x49, 0x6b, 0x75, 0x3b, 0x49, 0x6d, 0x77, 0x3b, 0x49, 0x67, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77,
+0x61, 0x20, 0x6d, 0x62, 0x65, 0x72, 0x65, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x129,
+0x72, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x68, 0x61, 0x74, 0x169, 0x3b,
+0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20,
+0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x67,
+0x61, 0x74, 0x61, 0x6e, 0x74, 0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6d, 0x169,
+0x67, 0x77, 0x61, 0x6e, 0x6a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61,
+0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4d, 0x77,
+0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x169, 0x6d, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77,
+0x61, 0x20, 0x69, 0x6b, 0x169, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x169, 0x6d, 0x77, 0x65, 0x3b, 0x4d, 0x77, 0x65, 0x72,
+0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x169, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x4b, 0x61, 0x129, 0x72, 0x129, 0x3b,
+0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x47, 0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x49, 0x3b,
+0x49, 0x3b, 0x49, 0x3b, 0x13a4, 0x13c3, 0x3b, 0x13a7, 0x13a6, 0x3b, 0x13a0, 0x13c5, 0x3b, 0x13a7, 0x13ec, 0x3b, 0x13a0, 0x13c2, 0x3b, 0x13d5,
+0x13ad, 0x3b, 0x13ab, 0x13f0, 0x3b, 0x13a6, 0x13b6, 0x3b, 0x13da, 0x13b5, 0x3b, 0x13da, 0x13c2, 0x3b, 0x13c5, 0x13d3, 0x3b, 0x13a5, 0x13cd, 0x3b,
+0x13a4, 0x13c3, 0x13b8, 0x13d4, 0x13c5, 0x3b, 0x13a7, 0x13a6, 0x13b5, 0x3b, 0x13a0, 0x13c5, 0x13f1, 0x3b, 0x13a7, 0x13ec, 0x13c2, 0x3b, 0x13a0, 0x13c2,
+0x13cd, 0x13ac, 0x13d8, 0x3b, 0x13d5, 0x13ad, 0x13b7, 0x13f1, 0x3b, 0x13ab, 0x13f0, 0x13c9, 0x13c2, 0x3b, 0x13a6, 0x13b6, 0x13c2, 0x3b, 0x13da, 0x13b5,
+0x13cd, 0x13d7, 0x3b, 0x13da, 0x13c2, 0x13c5, 0x13d7, 0x3b, 0x13c5, 0x13d3, 0x13d5, 0x13c6, 0x3b, 0x13a5, 0x13cd, 0x13a9, 0x13f1, 0x3b, 0x13a4, 0x3b,
+0x13a7, 0x3b, 0x13a0, 0x3b, 0x13a7, 0x3b, 0x13a0, 0x3b, 0x13d5, 0x3b, 0x13ab, 0x3b, 0x13a6, 0x3b, 0x13da, 0x3b, 0x13da, 0x3b, 0x13c5, 0x3b,
+0x13a5, 0x3b, 0x7a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x76, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x76, 0x72, 0x3b, 0x6d, 0x65,
+0x3b, 0x7a, 0x69, 0x6e, 0x3b, 0x7a, 0x69, 0x6c, 0x3b, 0x6f, 0x75, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74,
+0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x73, 0x3b, 0x7a, 0x61, 0x6e, 0x76, 0x69, 0x65, 0x3b, 0x66, 0x65, 0x76, 0x72,
+0x69, 0x79, 0x65, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x76, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x65, 0x3b, 0x7a, 0x69,
+0x6e, 0x3b, 0x7a, 0x69, 0x6c, 0x79, 0x65, 0x3b, 0x6f, 0x75, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x61, 0x6d, 0x3b, 0x6f,
+0x6b, 0x74, 0x6f, 0x62, 0x3b, 0x6e, 0x6f, 0x76, 0x61, 0x6d, 0x3b, 0x64, 0x65, 0x73, 0x61, 0x6d, 0x3b, 0x7a, 0x3b, 0x66,
+0x3b, 0x6d, 0x3b, 0x61, 0x3b, 0x6d, 0x3b, 0x7a, 0x3b, 0x7a, 0x3b, 0x6f, 0x3b, 0x73, 0x3b, 0x6f, 0x3b, 0x6e, 0x3b, 0x64,
+0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x4e, 0x74, 0x61, 0x6e, 0x64, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20,
+0x77, 0x61, 0x20, 0x50, 0x69, 0x6c, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x54, 0x61, 0x74,
+0x75, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x63, 0x68, 0x65, 0x63, 0x68, 0x69, 0x3b, 0x4d,
+0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69,
+0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x55, 0x6d, 0x6f, 0x3b, 0x4d, 0x77,
+0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4d, 0x69, 0x76,
+0x69, 0x6c, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20,
+0x6e, 0x61, 0x20, 0x4d, 0x69, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e,
+0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4e, 0x63, 0x68, 0x65, 0x63, 0x68, 0x69, 0x3b, 0x4d, 0x77, 0x65,
+0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61,
+0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e,
+0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x55, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20,
0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20,
-0x6e, 0x61, 0x20, 0x55, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f,
-0x20, 0x6e, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4d, 0x3b, 0x46, 0xfa, 0x6e, 0x67,
-0x61, 0x74, 0x268, 0x3b, 0x4e, 0x61, 0x61, 0x6e, 0x268, 0x3b, 0x4b, 0x65, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x49, 0x6b, 0xfa,
-0x6d, 0x69, 0x3b, 0x49, 0x6e, 0x79, 0x61, 0x6d, 0x62, 0x61, 0x6c, 0x61, 0x3b, 0x49, 0x64, 0x77, 0x61, 0x61, 0x74, 0x61,
-0x3b, 0x4d, 0x289, 0x289, 0x6e, 0x63, 0x68, 0x268, 0x3b, 0x56, 0x268, 0x268, 0x72, 0x268, 0x3b, 0x53, 0x61, 0x61, 0x74, 0x289,
-0x3b, 0x49, 0x6e, 0x79, 0x69, 0x3b, 0x53, 0x61, 0x61, 0x6e, 0x6f, 0x3b, 0x53, 0x61, 0x73, 0x61, 0x74, 0x289, 0x3b, 0x4b,
-0x289, 0x66, 0xfa, 0x6e, 0x67, 0x61, 0x74, 0x268, 0x3b, 0x4b, 0x289, 0x6e, 0x61, 0x61, 0x6e, 0x268, 0x3b, 0x4b, 0x289, 0x6b,
-0x65, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4b, 0x77, 0x69, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x4b, 0x77, 0x69, 0x69, 0x6e,
-0x79, 0x61, 0x6d, 0x62, 0xe1, 0x6c, 0x61, 0x3b, 0x4b, 0x77, 0x69, 0x69, 0x64, 0x77, 0x61, 0x61, 0x74, 0x61, 0x3b, 0x4b,
-0x289, 0x6d, 0x289, 0x289, 0x6e, 0x63, 0x68, 0x268, 0x3b, 0x4b, 0x289, 0x76, 0x268, 0x268, 0x72, 0x268, 0x3b, 0x4b, 0x289, 0x73,
-0x61, 0x61, 0x74, 0x289, 0x3b, 0x4b, 0x77, 0x69, 0x69, 0x6e, 0x79, 0x69, 0x3b, 0x4b, 0x289, 0x73, 0x61, 0x61, 0x6e, 0x6f,
-0x3b, 0x4b, 0x289, 0x73, 0x61, 0x73, 0x61, 0x74, 0x289, 0x3b, 0x46, 0x3b, 0x4e, 0x3b, 0x4b, 0x3b, 0x49, 0x3b, 0x49, 0x3b,
-0x49, 0x3b, 0x4d, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65,
-0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x75, 0x3b, 0x4d, 0x61, 0x61, 0x3b, 0x4a, 0x75, 0x75, 0x3b, 0x4a, 0x75,
-0x6c, 0x3b, 0x41, 0x67, 0x75, 0x3b, 0x53, 0x65, 0x62, 0x3b, 0x4f, 0x6b, 0x69, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65,
-0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x77, 0x61, 0x6c, 0x69, 0x79, 0x6f, 0x3b, 0x46, 0x65, 0x62, 0x77, 0x61, 0x6c, 0x69, 0x79,
-0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x69, 0x73, 0x69, 0x3b, 0x41, 0x70, 0x75, 0x6c, 0x69, 0x3b, 0x4d, 0x61, 0x61, 0x79, 0x69,
-0x3b, 0x4a, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x61, 0x79, 0x69, 0x3b, 0x41, 0x67, 0x75, 0x73, 0x69,
-0x74, 0x6f, 0x3b, 0x53, 0x65, 0x62, 0x75, 0x74, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x69, 0x74, 0x6f, 0x62,
-0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4a,
-0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x45, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a,
-0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x4f, 0x67, 0x61, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e,
-0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75,
-0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x45, 0x70, 0x72, 0x65, 0x6f, 0x3b, 0x4d, 0x65, 0x69, 0x3b,
-0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x4f, 0x67, 0x61, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65,
-0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62,
-0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x4d, 0x3b,
-0x4a, 0x3b, 0x4a, 0x3b, 0x4f, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65,
-0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75,
-0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x74, 0x75, 0x3b, 0x4e, 0x75, 0x76, 0x3b, 0x44, 0x69,
-0x7a, 0x3b, 0x4a, 0x61, 0x6e, 0x65, 0x72, 0x75, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x65, 0x72, 0x75, 0x3b, 0x4d, 0x61, 0x72,
-0x73, 0x75, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x75, 0x3b, 0x4a, 0x75, 0x6e, 0x68, 0x75, 0x3b,
-0x4a, 0x75, 0x6c, 0x68, 0x75, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x75, 0x3b, 0x53, 0x65, 0x74, 0x65, 0x6e, 0x62, 0x72,
-0x75, 0x3b, 0x4f, 0x74, 0x75, 0x62, 0x72, 0x75, 0x3b, 0x4e, 0x75, 0x76, 0x65, 0x6e, 0x62, 0x72, 0x75, 0x3b, 0x44, 0x69,
-0x7a, 0x65, 0x6e, 0x62, 0x72, 0x75, 0x3b, 0x4a, 0x41, 0x4e, 0x3b, 0x46, 0x45, 0x42, 0x3b, 0x4d, 0x41, 0x43, 0x3b, 0x128,
-0x50, 0x55, 0x3b, 0x4d, 0x128, 0x128, 0x3b, 0x4e, 0x4a, 0x55, 0x3b, 0x4e, 0x4a, 0x52, 0x3b, 0x41, 0x47, 0x41, 0x3b, 0x53,
-0x50, 0x54, 0x3b, 0x4f, 0x4b, 0x54, 0x3b, 0x4e, 0x4f, 0x56, 0x3b, 0x44, 0x45, 0x43, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61,
-0x72, 0x129, 0x3b, 0x46, 0x65, 0x62, 0x75, 0x72, 0x75, 0x61, 0x72, 0x129, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x128,
-0x70, 0x75, 0x72, 0x169, 0x3b, 0x4d, 0x129, 0x129, 0x3b, 0x4e, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x4e, 0x6a, 0x75, 0x72, 0x61,
-0x129, 0x3b, 0x41, 0x67, 0x61, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b,
-0x74, 0x169, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x63, 0x65, 0x6d, 0x62, 0x61,
-0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x128, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f,
-0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x4d, 0x75, 0x6c, 0x3b, 0x4e, 0x67, 0x61, 0x74, 0x3b, 0x54, 0x61, 0x61, 0x3b, 0x49, 0x77,
-0x6f, 0x3b, 0x4d, 0x61, 0x6d, 0x3b, 0x50, 0x61, 0x61, 0x3b, 0x4e, 0x67, 0x65, 0x3b, 0x52, 0x6f, 0x6f, 0x3b, 0x42, 0x75,
-0x72, 0x3b, 0x45, 0x70, 0x65, 0x3b, 0x4b, 0x70, 0x74, 0x3b, 0x4b, 0x70, 0x61, 0x3b, 0x4d, 0x75, 0x6c, 0x67, 0x75, 0x6c,
-0x3b, 0x4e, 0x67, 0x2019, 0x61, 0x74, 0x79, 0x61, 0x61, 0x74, 0x6f, 0x3b, 0x4b, 0x69, 0x70, 0x74, 0x61, 0x61, 0x6d, 0x6f,
-0x3b, 0x49, 0x77, 0x6f, 0x6f, 0x74, 0x6b, 0x75, 0x75, 0x74, 0x3b, 0x4d, 0x61, 0x6d, 0x75, 0x75, 0x74, 0x3b, 0x50, 0x61,
-0x61, 0x67, 0x69, 0x3b, 0x4e, 0x67, 0x2019, 0x65, 0x69, 0x79, 0x65, 0x65, 0x74, 0x3b, 0x52, 0x6f, 0x6f, 0x70, 0x74, 0x75,
-0x69, 0x3b, 0x42, 0x75, 0x72, 0x65, 0x65, 0x74, 0x3b, 0x45, 0x70, 0x65, 0x65, 0x73, 0x6f, 0x3b, 0x4b, 0x69, 0x70, 0x73,
-0x75, 0x75, 0x6e, 0x64, 0x65, 0x20, 0x6e, 0x65, 0x20, 0x74, 0x61, 0x61, 0x69, 0x3b, 0x4b, 0x69, 0x70, 0x73, 0x75, 0x75,
-0x6e, 0x64, 0x65, 0x20, 0x6e, 0x65, 0x62, 0x6f, 0x20, 0x61, 0x65, 0x6e, 0x67, 0x2019, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x54,
-0x3b, 0x49, 0x3b, 0x4d, 0x3b, 0x50, 0x3b, 0x4e, 0x3b, 0x52, 0x3b, 0x42, 0x3b, 0x45, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x1c3,
-0x4b, 0x68, 0x61, 0x6e, 0x6e, 0x69, 0x3b, 0x1c3, 0x4b, 0x68, 0x61, 0x6e, 0x1c0, 0x67, 0xf4, 0x61, 0x62, 0x3b, 0x1c0, 0x4b,
-0x68, 0x75, 0x75, 0x1c1, 0x6b, 0x68, 0xe2, 0x62, 0x3b, 0x1c3, 0x48, 0xf4, 0x61, 0x1c2, 0x6b, 0x68, 0x61, 0x69, 0x62, 0x3b,
-0x1c3, 0x4b, 0x68, 0x61, 0x69, 0x74, 0x73, 0xe2, 0x62, 0x3b, 0x47, 0x61, 0x6d, 0x61, 0x1c0, 0x61, 0x65, 0x62, 0x3b, 0x1c2,
-0x4b, 0x68, 0x6f, 0x65, 0x73, 0x61, 0x6f, 0x62, 0x3b, 0x41, 0x6f, 0x1c1, 0x6b, 0x68, 0x75, 0x75, 0x6d, 0xfb, 0x1c1, 0x6b,
-0x68, 0xe2, 0x62, 0x3b, 0x54, 0x61, 0x72, 0x61, 0x1c0, 0x6b, 0x68, 0x75, 0x75, 0x6d, 0xfb, 0x1c1, 0x6b, 0x68, 0xe2, 0x62,
-0x3b, 0x1c2, 0x4e, 0xfb, 0x1c1, 0x6e, 0xe2, 0x69, 0x73, 0x65, 0x62, 0x3b, 0x1c0, 0x48, 0x6f, 0x6f, 0x1c2, 0x67, 0x61, 0x65,
-0x62, 0x3b, 0x48, 0xf4, 0x61, 0x73, 0x6f, 0x72, 0x65, 0x1c1, 0x6b, 0x68, 0xe2, 0x62, 0x3b, 0x4a, 0x61, 0x6e, 0x2e, 0x3b,
-0x46, 0xe4, 0x62, 0x2e, 0x3b, 0x4d, 0xe4, 0x7a, 0x2e, 0x3b, 0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a,
-0x75, 0x6e, 0x2e, 0x3b, 0x4a, 0x75, 0x6c, 0x2e, 0x3b, 0x4f, 0x75, 0x6a, 0x2e, 0x3b, 0x53, 0xe4, 0x70, 0x2e, 0x3b, 0x4f,
-0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x7a, 0x2e, 0x3b, 0x4a, 0x61, 0x6e, 0x6e, 0x65, 0x77,
-0x61, 0x3b, 0x46, 0xe4, 0x62, 0x72, 0x6f, 0x77, 0x61, 0x3b, 0x4d, 0xe4, 0xe4, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x65, 0x6c,
-0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x75, 0x6c, 0x69, 0x3b, 0x4f, 0x75,
-0x6a, 0x6f, 0xdf, 0x3b, 0x53, 0x65, 0x70, 0x74, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x68, 0x62,
-0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0xe4, 0x6d, 0x62, 0x65, 0x72,
-0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0xe4, 0x62, 0x3b, 0x4d, 0xe4, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x69,
-0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x4f, 0x75, 0x6a, 0x3b, 0x53, 0xe4, 0x70, 0x3b, 0x4f, 0x6b, 0x74,
-0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a, 0x3b, 0x44, 0x61, 0x6c, 0x3b, 0x41, 0x72, 0xe1, 0x3b, 0x186, 0x25b, 0x6e,
-0x3b, 0x44, 0x6f, 0x79, 0x3b, 0x4c, 0xe9, 0x70, 0x3b, 0x52, 0x6f, 0x6b, 0x3b, 0x53, 0xe1, 0x73, 0x3b, 0x42, 0x254, 0x301,
-0x72, 0x3b, 0x4b, 0xfa, 0x73, 0x3b, 0x47, 0xed, 0x73, 0x3b, 0x53, 0x68, 0x289, 0x301, 0x3b, 0x4e, 0x74, 0x289, 0x301, 0x3b,
-0x4f, 0x6c, 0x61, 0x64, 0x61, 0x6c, 0x289, 0x301, 0x3b, 0x41, 0x72, 0xe1, 0x74, 0x3b, 0x186, 0x25b, 0x6e, 0x268, 0x301, 0x254,
-0x268, 0x14b, 0x254, 0x6b, 0x3b, 0x4f, 0x6c, 0x6f, 0x64, 0x6f, 0x79, 0xed, 0xf3, 0x72, 0xed, 0xea, 0x20, 0x69, 0x6e, 0x6b,
-0xf3, 0x6b, 0xfa, 0xe2, 0x3b, 0x4f, 0x6c, 0x6f, 0x69, 0x6c, 0xe9, 0x70, 0x16b, 0x6e, 0x79, 0x12b, 0x113, 0x20, 0x69, 0x6e,
-0x6b, 0xf3, 0x6b, 0xfa, 0xe2, 0x3b, 0x4b, 0xfa, 0x6a, 0xfa, 0x254, 0x72, 0x254, 0x6b, 0x3b, 0x4d, 0xf3, 0x72, 0x75, 0x73,
-0xe1, 0x73, 0x69, 0x6e, 0x3b, 0x186, 0x6c, 0x254, 0x301, 0x268, 0x301, 0x62, 0x254, 0x301, 0x72, 0xe1, 0x72, 0x25b, 0x3b, 0x4b,
-0xfa, 0x73, 0x68, 0xee, 0x6e, 0x3b, 0x4f, 0x6c, 0x67, 0xed, 0x73, 0x61, 0x6e, 0x3b, 0x50, 0x289, 0x73, 0x68, 0x289, 0x301,
-0x6b, 0x61, 0x3b, 0x4e, 0x74, 0x289, 0x301, 0x14b, 0x289, 0x301, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b,
-0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b,
-0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x3b,
-0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b,
-0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b,
-0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x63, 0x3b, 0x52, 0x61, 0x72, 0x3b, 0x4d, 0x75, 0x6b, 0x3b, 0x4b, 0x77, 0x61, 0x3b,
-0x44, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4d, 0x6f, 0x64, 0x3b, 0x4a, 0x6f, 0x6c, 0x3b, 0x50, 0x65, 0x64, 0x3b,
-0x53, 0x6f, 0x6b, 0x3b, 0x54, 0x69, 0x62, 0x3b, 0x4c, 0x61, 0x62, 0x3b, 0x50, 0x6f, 0x6f, 0x3b, 0x4f, 0x72, 0x61, 0x72,
-0x61, 0x3b, 0x4f, 0x6d, 0x75, 0x6b, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x67, 0x2019, 0x3b, 0x4f, 0x64, 0x75, 0x6e, 0x67,
-0x2019, 0x65, 0x6c, 0x3b, 0x4f, 0x6d, 0x61, 0x72, 0x75, 0x6b, 0x3b, 0x4f, 0x6d, 0x6f, 0x64, 0x6f, 0x6b, 0x2019, 0x6b, 0x69,
-0x6e, 0x67, 0x2019, 0x6f, 0x6c, 0x3b, 0x4f, 0x6a, 0x6f, 0x6c, 0x61, 0x3b, 0x4f, 0x70, 0x65, 0x64, 0x65, 0x6c, 0x3b, 0x4f,
-0x73, 0x6f, 0x6b, 0x6f, 0x73, 0x6f, 0x6b, 0x6f, 0x6d, 0x61, 0x3b, 0x4f, 0x74, 0x69, 0x62, 0x61, 0x72, 0x3b, 0x4f, 0x6c,
-0x61, 0x62, 0x6f, 0x72, 0x3b, 0x4f, 0x70, 0x6f, 0x6f, 0x3b, 0x52, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x44, 0x3b, 0x4d, 0x3b,
-0x4d, 0x3b, 0x4a, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x50, 0x3b, 0x17d, 0x61, 0x6e, 0x3b, 0x46, 0x65,
-0x65, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x77, 0x69, 0x3b, 0x4d, 0x65, 0x3b, 0x17d, 0x75, 0x77, 0x3b, 0x17d, 0x75, 0x79,
-0x3b, 0x55, 0x74, 0x3b, 0x53, 0x65, 0x6b, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x6f, 0x3b, 0x44, 0x65, 0x65, 0x3b,
-0x17d, 0x61, 0x6e, 0x77, 0x69, 0x79, 0x65, 0x3b, 0x46, 0x65, 0x65, 0x77, 0x69, 0x72, 0x69, 0x79, 0x65, 0x3b, 0x4d, 0x61,
-0x72, 0x73, 0x69, 0x3b, 0x41, 0x77, 0x69, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x3b, 0x17d, 0x75, 0x77, 0x65, 0x14b, 0x3b,
-0x17d, 0x75, 0x79, 0x79, 0x65, 0x3b, 0x55, 0x74, 0x3b, 0x53, 0x65, 0x6b, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x3b, 0x4f,
-0x6b, 0x74, 0x6f, 0x6f, 0x62, 0x75, 0x72, 0x3b, 0x4e, 0x6f, 0x6f, 0x77, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x3b, 0x44, 0x65,
-0x65, 0x73, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x3b, 0x17d, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x17d, 0x3b,
-0x17d, 0x3b, 0x55, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x44, 0x41, 0x43, 0x3b, 0x44, 0x41, 0x52, 0x3b,
-0x44, 0x41, 0x44, 0x3b, 0x44, 0x41, 0x4e, 0x3b, 0x44, 0x41, 0x48, 0x3b, 0x44, 0x41, 0x55, 0x3b, 0x44, 0x41, 0x4f, 0x3b,
-0x44, 0x41, 0x42, 0x3b, 0x44, 0x4f, 0x43, 0x3b, 0x44, 0x41, 0x50, 0x3b, 0x44, 0x47, 0x49, 0x3b, 0x44, 0x41, 0x47, 0x3b,
-0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x63, 0x68, 0x69, 0x65, 0x6c, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d,
-0x61, 0x72, 0x20, 0x41, 0x72, 0x69, 0x79, 0x6f, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x64, 0x65,
-0x6b, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x6e, 0x67, 0x2019, 0x77, 0x65, 0x6e, 0x3b, 0x44, 0x77,
-0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x62, 0x69, 0x63, 0x68, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20,
-0x41, 0x75, 0x63, 0x68, 0x69, 0x65, 0x6c, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x62, 0x69, 0x72,
-0x69, 0x79, 0x6f, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x62, 0x6f, 0x72, 0x6f, 0x3b, 0x44, 0x77,
-0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x4f, 0x63, 0x68, 0x69, 0x6b, 0x6f, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72,
-0x20, 0x41, 0x70, 0x61, 0x72, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x67, 0x69, 0x20, 0x61, 0x63, 0x68,
-0x69, 0x65, 0x6c, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x70, 0x61, 0x72, 0x20, 0x67, 0x69, 0x20,
-0x61, 0x72, 0x69, 0x79, 0x6f, 0x3b, 0x43, 0x3b, 0x52, 0x3b, 0x44, 0x3b, 0x4e, 0x3b, 0x42, 0x3b, 0x55, 0x3b, 0x42, 0x3b,
-0x42, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x59, 0x65, 0x6e, 0x3b, 0x59, 0x65, 0x62, 0x3b, 0x4d, 0x61,
-0x72, 0x3b, 0x49, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x59, 0x75, 0x6e, 0x3b, 0x59, 0x75, 0x6c, 0x3b, 0x194, 0x75,
-0x63, 0x3b, 0x43, 0x75, 0x74, 0x3b, 0x4b, 0x1e6d, 0x75, 0x3b, 0x4e, 0x77, 0x61, 0x3b, 0x44, 0x75, 0x6a, 0x3b, 0x59, 0x65,
-0x6e, 0x6e, 0x61, 0x79, 0x65, 0x72, 0x3b, 0x59, 0x65, 0x62, 0x72, 0x61, 0x79, 0x65, 0x72, 0x3b, 0x4d, 0x61, 0x72, 0x73,
-0x3b, 0x49, 0x62, 0x72, 0x69, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x79, 0x75, 0x3b, 0x59, 0x75, 0x6e, 0x79, 0x75, 0x3b, 0x59,
-0x75, 0x6c, 0x79, 0x75, 0x7a, 0x3b, 0x194, 0x75, 0x63, 0x74, 0x3b, 0x43, 0x75, 0x74, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b,
-0x4b, 0x1e6d, 0x75, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x77, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b, 0x44, 0x75, 0x6a, 0x61, 0x6e,
-0x62, 0x69, 0x72, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x194, 0x3b,
-0x43, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x6c,
-0x75, 0x61, 0x6c, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x41, 0x70, 0x6c, 0x69, 0x6c, 0x69, 0x3b, 0x4d, 0x65,
-0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x69, 0x3b,
-0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65,
-0x6d, 0x62, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x91c, 0x93e, 0x928, 0x941, 0x935, 0x93e, 0x930, 0x940,
-0x3b, 0x92b, 0x947, 0x92c, 0x94d, 0x930, 0x941, 0x935, 0x93e, 0x930, 0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x938, 0x3b, 0x90f, 0x92b,
-0x94d, 0x930, 0x93f, 0x932, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x941, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x907, 0x3b, 0x906, 0x917,
-0x938, 0x94d, 0x925, 0x3b, 0x938, 0x947, 0x92c, 0x925, 0x947, 0x91c, 0x94d, 0x92c, 0x93c, 0x930, 0x3b, 0x905, 0x916, 0x925, 0x92c, 0x930,
-0x3b, 0x928, 0x92c, 0x947, 0x91c, 0x94d, 0x92c, 0x93c, 0x930, 0x3b, 0x926, 0x93f, 0x938, 0x947, 0x91c, 0x94d, 0x92c, 0x93c, 0x930, 0x3b,
-0x91c, 0x3b, 0x92b, 0x947, 0x3b, 0x92e, 0x93e, 0x3b, 0x90f, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x941, 0x3b, 0x91c, 0x941, 0x3b, 0x906,
-0x3b, 0x938, 0x947, 0x3b, 0x905, 0x3b, 0x928, 0x3b, 0x926, 0x93f, 0x3b, 0x456, 0x486, 0x430, 0x2de9, 0x487, 0x3b, 0x444, 0x435, 0x2de1,
-0x487, 0x3b, 0x43c, 0x430, 0x2dec, 0x487, 0x3b, 0x430, 0x486, 0x43f, 0x2dec, 0x487, 0x3b, 0x43c, 0x430, 0xa675, 0x3b, 0x456, 0x486, 0xa64b,
-0x2de9, 0x487, 0x3b, 0x456, 0x486, 0xa64b, 0x2de7, 0x487, 0x3b, 0x430, 0x486, 0x301, 0x475, 0x2de2, 0x487, 0x3b, 0x441, 0x435, 0x2deb, 0x487,
-0x3b, 0x47b, 0x486, 0x43a, 0x2dee, 0x3b, 0x43d, 0x43e, 0x435, 0x2de8, 0x3b, 0x434, 0x435, 0x2de6, 0x487, 0x3b, 0x456, 0x486, 0x430, 0x43d,
-0x43d, 0xa64b, 0x430, 0x301, 0x440, 0x457, 0x439, 0x3b, 0x444, 0x435, 0x432, 0x440, 0xa64b, 0x430, 0x301, 0x440, 0x457, 0x439, 0x3b, 0x43c,
-0x430, 0x301, 0x440, 0x442, 0x44a, 0x3b, 0x430, 0x486, 0x43f, 0x440, 0x456, 0x301, 0x43b, 0x43b, 0x457, 0x439, 0x3b, 0x43c, 0x430, 0x301,
-0x457, 0x439, 0x3b, 0x456, 0x486, 0xa64b, 0x301, 0x43d, 0x457, 0x439, 0x3b, 0x456, 0x486, 0xa64b, 0x301, 0x43b, 0x457, 0x439, 0x3b, 0x430,
-0x486, 0x301, 0x475, 0x433, 0xa64b, 0x441, 0x442, 0x44a, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x439,
-0x3b, 0x47b, 0x486, 0x43a, 0x442, 0x461, 0x301, 0x432, 0x440, 0x457, 0x439, 0x3b, 0x43d, 0x43e, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457,
-0x439, 0x3b, 0x434, 0x435, 0x43a, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x439, 0x3b, 0x406, 0x486, 0x3b, 0x424, 0x3b, 0x41c, 0x3b,
-0x410, 0x486, 0x3b, 0x41c, 0x3b, 0x406, 0x486, 0x3b, 0x406, 0x486, 0x3b, 0x410, 0x486, 0x3b, 0x421, 0x3b, 0x47a, 0x486, 0x3b, 0x41d,
-0x3b, 0x414, 0x3b, 0x456, 0x486, 0x430, 0x43d, 0x43d, 0xa64b, 0x430, 0x301, 0x440, 0x457, 0x430, 0x3b, 0x444, 0x435, 0x432, 0x440, 0xa64b,
-0x430, 0x301, 0x440, 0x457, 0x430, 0x3b, 0x43c, 0x430, 0x301, 0x440, 0x442, 0x430, 0x3b, 0x430, 0x486, 0x43f, 0x440, 0x456, 0x301, 0x43b,
-0x43b, 0x457, 0x430, 0x3b, 0x43c, 0x430, 0x301, 0x457, 0x430, 0x3b, 0x456, 0x486, 0xa64b, 0x301, 0x43d, 0x457, 0x430, 0x3b, 0x456, 0x486,
-0xa64b, 0x301, 0x43b, 0x457, 0x430, 0x3b, 0x430, 0x486, 0x301, 0x475, 0x433, 0xa64b, 0x441, 0x442, 0x430, 0x3b, 0x441, 0x435, 0x43f, 0x442,
-0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x430, 0x3b, 0x47b, 0x486, 0x43a, 0x442, 0x461, 0x301, 0x432, 0x440, 0x457, 0x430, 0x3b, 0x43d,
-0x43e, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x430, 0x3b, 0x434, 0x435, 0x43a, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x430, 0x3b,
-0x43, 0x69, 0x6f, 0x3b, 0x4c, 0x75, 0x69, 0x3b, 0x4c, 0x75, 0x73, 0x3b, 0x4d, 0x75, 0x75, 0x3b, 0x4c, 0x75, 0x6d, 0x3b,
-0x4c, 0x75, 0x66, 0x3b, 0x4b, 0x61, 0x62, 0x3b, 0x4c, 0x75, 0x73, 0x68, 0x3b, 0x4c, 0x75, 0x74, 0x3b, 0x4c, 0x75, 0x6e,
-0x3b, 0x4b, 0x61, 0x73, 0x3b, 0x43, 0x69, 0x73, 0x3b, 0x43, 0x69, 0x6f, 0x6e, 0x67, 0x6f, 0x3b, 0x4c, 0xf9, 0x69, 0x73,
-0x68, 0x69, 0x3b, 0x4c, 0x75, 0x73, 0xf2, 0x6c, 0x6f, 0x3b, 0x4d, 0xf9, 0x75, 0x79, 0xe0, 0x3b, 0x4c, 0x75, 0x6d, 0xf9,
-0x6e, 0x67, 0xf9, 0x6c, 0xf9, 0x3b, 0x4c, 0x75, 0x66, 0x75, 0x69, 0x6d, 0x69, 0x3b, 0x4b, 0x61, 0x62, 0xe0, 0x6c, 0xe0,
-0x73, 0x68, 0xec, 0x70, 0xf9, 0x3b, 0x4c, 0xf9, 0x73, 0x68, 0xec, 0x6b, 0xe0, 0x3b, 0x4c, 0x75, 0x74, 0x6f, 0x6e, 0x67,
-0x6f, 0x6c, 0x6f, 0x3b, 0x4c, 0x75, 0x6e, 0x67, 0xf9, 0x64, 0x69, 0x3b, 0x4b, 0x61, 0x73, 0x77, 0xe8, 0x6b, 0xe8, 0x73,
-0xe8, 0x3b, 0x43, 0x69, 0x73, 0x77, 0xe0, 0x3b, 0x43, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b,
-0x4b, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4b, 0x3b, 0x43, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b,
-0x4d, 0xe4, 0x65, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b,
-0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a, 0x3b,
-0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x4d, 0xe4, 0x65, 0x72, 0x7a,
-0x3b, 0x41, 0x62, 0x72, 0xeb, 0x6c, 0x6c, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c,
-0x69, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f,
-0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0x65,
-0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x61, 0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0xe4, 0x65, 0x2e, 0x3b,
-0x41, 0x62, 0x72, 0x2e, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41,
-0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65, 0x70, 0x2e, 0x3b, 0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44,
-0x65, 0x7a, 0x2e, 0x3b, 0x6e, 0xf9, 0x6d, 0x3b, 0x6b, 0x268, 0x7a, 0x3b, 0x74, 0x268, 0x64, 0x3b, 0x74, 0x61, 0x61, 0x3b,
-0x73, 0x65, 0x65, 0x3b, 0x6e, 0x7a, 0x75, 0x3b, 0x64, 0x75, 0x6d, 0x3b, 0x66, 0x254, 0x65, 0x3b, 0x64, 0x7a, 0x75, 0x3b,
-0x6c, 0x254, 0x6d, 0x3b, 0x6b, 0x61, 0x61, 0x3b, 0x66, 0x77, 0x6f, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300,
-0x6e, 0xf9, 0x6d, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x6b, 0x197, 0x300, 0x7a, 0xf9, 0x294, 0x3b, 0x6e,
-0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x74, 0x197, 0x300, 0x64, 0x289, 0x300, 0x67, 0x68, 0xe0, 0x3b, 0x6e, 0x64, 0x7a,
-0x254, 0x300, 0x14b, 0x254, 0x300, 0x74, 0x1ce, 0x61, 0x66, 0x289, 0x304, 0x67, 0x68, 0x101, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300,
-0x14b, 0xe8, 0x73, 0xe8, 0x65, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x6e, 0x7a, 0xf9, 0x67, 0x68, 0xf2,
-0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x64, 0xf9, 0x6d, 0x6c, 0x6f, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300,
-0x14b, 0x254, 0x300, 0x6b, 0x77, 0xee, 0x66, 0x254, 0x300, 0x65, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x74,
-0x197, 0x300, 0x66, 0x289, 0x300, 0x67, 0x68, 0xe0, 0x64, 0x7a, 0x75, 0x67, 0x68, 0xf9, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300,
-0x14b, 0x254, 0x300, 0x67, 0x68, 0x1d4, 0x75, 0x77, 0x65, 0x6c, 0x254, 0x300, 0x6d, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b,
-0x254, 0x300, 0x63, 0x68, 0x77, 0x61, 0x294, 0xe0, 0x6b, 0x61, 0x61, 0x20, 0x77, 0x6f, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300,
-0x14b, 0xe8, 0x66, 0x77, 0xf2, 0x6f, 0x3b, 0x6e, 0x3b, 0x6b, 0x3b, 0x74, 0x3b, 0x74, 0x3b, 0x73, 0x3b, 0x7a, 0x3b, 0x6b,
-0x3b, 0x66, 0x3b, 0x64, 0x3b, 0x6c, 0x3b, 0x63, 0x3b, 0x66, 0x3b, 0x6b, 0x254, 0x6e, 0x3b, 0x6d, 0x61, 0x63, 0x3b, 0x6d,
-0x61, 0x74, 0x3b, 0x6d, 0x74, 0x6f, 0x3b, 0x6d, 0x70, 0x75, 0x3b, 0x68, 0x69, 0x6c, 0x3b, 0x6e, 0x6a, 0x65, 0x3b, 0x68,
-0x69, 0x6b, 0x3b, 0x64, 0x69, 0x70, 0x3b, 0x62, 0x69, 0x6f, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x6c, 0x69, 0x253, 0x3b, 0x4b,
-0x254, 0x6e, 0x64, 0x254, 0x14b, 0x3b, 0x4d, 0xe0, 0x63, 0x25b, 0x302, 0x6c, 0x3b, 0x4d, 0xe0, 0x74, 0xf9, 0x6d, 0x62, 0x3b,
-0x4d, 0xe0, 0x74, 0x6f, 0x70, 0x3b, 0x4d, 0x300, 0x70, 0x75, 0x79, 0x25b, 0x3b, 0x48, 0xec, 0x6c, 0xf2, 0x6e, 0x64, 0x25b,
-0x300, 0x3b, 0x4e, 0x6a, 0xe8, 0x62, 0xe0, 0x3b, 0x48, 0xec, 0x6b, 0x61, 0x14b, 0x3b, 0x44, 0xec, 0x70, 0x254, 0x300, 0x73,
-0x3b, 0x42, 0xec, 0xf2, 0xf4, 0x6d, 0x3b, 0x4d, 0xe0, 0x79, 0x25b, 0x73, 0xe8, 0x70, 0x3b, 0x4c, 0xec, 0x62, 0x75, 0x79,
-0x20, 0x6c, 0x69, 0x20, 0x144, 0x79, 0xe8, 0x65, 0x3b, 0x6b, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x68,
-0x3b, 0x6e, 0x3b, 0x68, 0x3b, 0x64, 0x3b, 0x62, 0x3b, 0x6d, 0x3b, 0x6c, 0x3b, 0x64, 0x69, 0x3b, 0x14b, 0x67, 0x254, 0x6e,
-0x3b, 0x73, 0x254, 0x14b, 0x3b, 0x64, 0x69, 0x253, 0x3b, 0x65, 0x6d, 0x69, 0x3b, 0x65, 0x73, 0x254, 0x3b, 0x6d, 0x61, 0x64,
-0x3b, 0x64, 0x69, 0x14b, 0x3b, 0x6e, 0x79, 0x25b, 0x74, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x74, 0x69, 0x6e, 0x3b, 0x65, 0x6c,
-0xe1, 0x3b, 0x64, 0x69, 0x6d, 0x254, 0x301, 0x64, 0x69, 0x3b, 0x14b, 0x67, 0x254, 0x6e, 0x64, 0x25b, 0x3b, 0x73, 0x254, 0x14b,
-0x25b, 0x3b, 0x64, 0x69, 0x253, 0xe1, 0x253, 0xe1, 0x3b, 0x65, 0x6d, 0x69, 0x61, 0x73, 0x65, 0x6c, 0x65, 0x3b, 0x65, 0x73,
-0x254, 0x70, 0x25b, 0x73, 0x254, 0x70, 0x25b, 0x3b, 0x6d, 0x61, 0x64, 0x69, 0x253, 0x25b, 0x301, 0x64, 0xed, 0x253, 0x25b, 0x301,
-0x3b, 0x64, 0x69, 0x14b, 0x67, 0x69, 0x6e, 0x64, 0x69, 0x3b, 0x6e, 0x79, 0x25b, 0x74, 0x25b, 0x6b, 0x69, 0x3b, 0x6d, 0x61,
-0x79, 0xe9, 0x73, 0x25b, 0x301, 0x3b, 0x74, 0x69, 0x6e, 0xed, 0x6e, 0xed, 0x3b, 0x65, 0x6c, 0xe1, 0x14b, 0x67, 0x25b, 0x301,
-0x3b, 0x64, 0x3b, 0x14b, 0x3b, 0x73, 0x3b, 0x64, 0x3b, 0x65, 0x3b, 0x65, 0x3b, 0x6d, 0x3b, 0x64, 0x3b, 0x6e, 0x3b, 0x6d,
-0x3b, 0x74, 0x3b, 0x65, 0x3b, 0x53, 0x61, 0x3b, 0x46, 0x65, 0x3b, 0x4d, 0x61, 0x3b, 0x41, 0x62, 0x3b, 0x4d, 0x65, 0x3b,
-0x53, 0x75, 0x3b, 0x53, 0xfa, 0x3b, 0x55, 0x74, 0x3b, 0x53, 0x65, 0x3b, 0x4f, 0x6b, 0x3b, 0x4e, 0x6f, 0x3b, 0x44, 0x65,
-0x3b, 0x53, 0x61, 0x6e, 0x76, 0x69, 0x65, 0x3b, 0x46, 0xe9, 0x62, 0x69, 0x72, 0x69, 0x65, 0x3b, 0x4d, 0x61, 0x72, 0x73,
-0x3b, 0x41, 0x62, 0x75, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x53, 0x75, 0x65, 0x14b, 0x3b, 0x53, 0xfa, 0x75,
-0x79, 0x65, 0x65, 0x3b, 0x55, 0x74, 0x3b, 0x53, 0x65, 0x74, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x4f, 0x6b, 0x74,
-0x6f, 0x62, 0x61, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x44, 0x69, 0x73, 0x61, 0x6d, 0x62,
-0x61, 0x72, 0x3b, 0x53, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x55, 0x3b, 0x53,
-0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x6e, 0x67, 0x6f, 0x3b, 0x6e, 0x67, 0x62, 0x3b, 0x6e, 0x67, 0x6c, 0x3b, 0x6e,
-0x67, 0x6e, 0x3b, 0x6e, 0x67, 0x74, 0x3b, 0x6e, 0x67, 0x73, 0x3b, 0x6e, 0x67, 0x7a, 0x3b, 0x6e, 0x67, 0x6d, 0x3b, 0x6e,
-0x67, 0x65, 0x3b, 0x6e, 0x67, 0x61, 0x3b, 0x6e, 0x67, 0x61, 0x64, 0x3b, 0x6e, 0x67, 0x61, 0x62, 0x3b, 0x6e, 0x67, 0x254,
-0x6e, 0x20, 0x6f, 0x73, 0xfa, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x62, 0x25b, 0x30c, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20,
-0x6c, 0xe1, 0x6c, 0x61, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x6e, 0x79, 0x69, 0x6e, 0x61, 0x3b, 0x6e, 0x67, 0x254, 0x6e,
-0x20, 0x74, 0xe1, 0x6e, 0x61, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x73, 0x61, 0x6d, 0x259, 0x6e, 0x61, 0x3b, 0x6e, 0x67,
-0x254, 0x6e, 0x20, 0x7a, 0x61, 0x6d, 0x67, 0x62, 0xe1, 0x6c, 0x61, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x6d, 0x77, 0x6f,
-0x6d, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x65, 0x62, 0x75, 0x6c, 0xfa, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x61, 0x77,
-0xf3, 0x6d, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x61, 0x77, 0xf3, 0x6d, 0x20, 0x61, 0x69, 0x20, 0x64, 0x7a, 0x69, 0xe1,
-0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x61, 0x77, 0xf3, 0x6d, 0x20, 0x61, 0x69, 0x20, 0x62, 0x25b, 0x30c, 0x3b, 0x6f, 0x3b,
-0x62, 0x3b, 0x6c, 0x3b, 0x6e, 0x3b, 0x74, 0x3b, 0x73, 0x3b, 0x7a, 0x3b, 0x6d, 0x3b, 0x65, 0x3b, 0x61, 0x3b, 0x64, 0x3b,
-0x62, 0x3b, 0x14b, 0x31, 0x3b, 0x14b, 0x32, 0x3b, 0x14b, 0x33, 0x3b, 0x14b, 0x34, 0x3b, 0x14b, 0x35, 0x3b, 0x14b, 0x36, 0x3b,
-0x14b, 0x37, 0x3b, 0x14b, 0x38, 0x3b, 0x14b, 0x39, 0x3b, 0x14b, 0x31, 0x30, 0x3b, 0x14b, 0x31, 0x31, 0x3b, 0x14b, 0x31, 0x32,
-0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x20, 0x6e, 0x74, 0x254, 0x301, 0x6e, 0x74, 0x254, 0x3b, 0x14b, 0x77, 0xed, 0xed,
-0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x62, 0x25b, 0x301, 0x25b, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x72,
-0xe1, 0xe1, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x6e, 0x69, 0x6e, 0x3b, 0x14b, 0x77, 0xed, 0xed,
-0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x74, 0xe1, 0x61, 0x6e, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x74,
-0xe1, 0x61, 0x66, 0x254, 0x6b, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x74, 0xe1, 0x61, 0x62, 0x25b,
-0x25b, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x74, 0xe1, 0x61, 0x72, 0x61, 0x61, 0x3b, 0x14b, 0x77,
-0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x74, 0xe1, 0x61, 0x6e, 0x69, 0x6e, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61,
-0x6b, 0x1dd, 0x20, 0x6e, 0x74, 0x25b, 0x6b, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x6e, 0x74, 0x25b,
-0x6b, 0x20, 0x64, 0x69, 0x20, 0x62, 0x254, 0x301, 0x6b, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x6e,
-0x74, 0x25b, 0x6b, 0x20, 0x64, 0x69, 0x20, 0x62, 0x25b, 0x301, 0x25b, 0x3b, 0x4b, 0x77, 0x61, 0x3b, 0x55, 0x6e, 0x61, 0x3b,
-0x52, 0x61, 0x72, 0x3b, 0x43, 0x68, 0x65, 0x3b, 0x54, 0x68, 0x61, 0x3b, 0x4d, 0x6f, 0x63, 0x3b, 0x53, 0x61, 0x62, 0x3b,
-0x4e, 0x61, 0x6e, 0x3b, 0x54, 0x69, 0x73, 0x3b, 0x4b, 0x75, 0x6d, 0x3b, 0x4d, 0x6f, 0x6a, 0x3b, 0x59, 0x65, 0x6c, 0x3b,
-0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x6b, 0x77, 0x61, 0x6e, 0x7a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72,
-0x69, 0x20, 0x77, 0x6f, 0x20, 0x75, 0x6e, 0x61, 0x79, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77,
-0x6f, 0x20, 0x75, 0x6e, 0x65, 0x72, 0x61, 0x72, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x75,
-0x6e, 0x65, 0x63, 0x68, 0x65, 0x73, 0x68, 0x65, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x75, 0x6e,
-0x65, 0x74, 0x68, 0x61, 0x6e, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x6e,
-0x75, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x6f, 0x63, 0x68, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20,
-0x73, 0x61, 0x62, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x6e, 0x61, 0x6e, 0x65, 0x3b, 0x4d,
-0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x74, 0x69, 0x73, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77,
-0x6f, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x6b, 0x75, 0x6d, 0x69,
-0x20, 0x6e, 0x61, 0x20, 0x6d, 0x6f, 0x6a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x6b, 0x75,
-0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x79, 0x65, 0x6c, 0x2019, 0x6c, 0x69, 0x3b, 0x4b, 0x3b, 0x55, 0x3b, 0x52, 0x3b, 0x43,
-0x3b, 0x54, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x46, 0x4c, 0x4f,
-0x3b, 0x43, 0x4c, 0x41, 0x3b, 0x43, 0x4b, 0x49, 0x3b, 0x46, 0x4d, 0x46, 0x3b, 0x4d, 0x41, 0x44, 0x3b, 0x4d, 0x42, 0x49,
-0x3b, 0x4d, 0x4c, 0x49, 0x3b, 0x4d, 0x41, 0x4d, 0x3b, 0x46, 0x44, 0x45, 0x3b, 0x46, 0x4d, 0x55, 0x3b, 0x46, 0x47, 0x57,
-0x3b, 0x46, 0x59, 0x55, 0x3b, 0x46, 0x129, 0x69, 0x20, 0x4c, 0x6f, 0x6f, 0x3b, 0x43, 0x6f, 0x6b, 0x63, 0x77, 0x61, 0x6b,
-0x6c, 0x61, 0x14b, 0x6e, 0x65, 0x3b, 0x43, 0x6f, 0x6b, 0x63, 0x77, 0x61, 0x6b, 0x6c, 0x69, 0x69, 0x3b, 0x46, 0x129, 0x69,
-0x20, 0x4d, 0x61, 0x72, 0x66, 0x6f, 0x6f, 0x3b, 0x4d, 0x61, 0x64, 0x1dd, 0x1dd, 0x75, 0x75, 0x74, 0x1dd, 0x62, 0x69, 0x6a,
-0x61, 0x14b, 0x3b, 0x4d, 0x61, 0x6d, 0x1dd, 0x14b, 0x67, 0x77, 0xe3, 0x61, 0x66, 0x61, 0x68, 0x62, 0x69, 0x69, 0x3b, 0x4d,
-0x61, 0x6d, 0x1dd, 0x14b, 0x67, 0x77, 0xe3, 0x61, 0x6c, 0x69, 0x69, 0x3b, 0x4d, 0x61, 0x64, 0x1dd, 0x6d, 0x62, 0x69, 0x69,
-0x3b, 0x46, 0x129, 0x69, 0x20, 0x44, 0x1dd, 0x253, 0x6c, 0x69, 0x69, 0x3b, 0x46, 0x129, 0x69, 0x20, 0x4d, 0x75, 0x6e, 0x64,
-0x61, 0x14b, 0x3b, 0x46, 0x129, 0x69, 0x20, 0x47, 0x77, 0x61, 0x68, 0x6c, 0x6c, 0x65, 0x3b, 0x46, 0x129, 0x69, 0x20, 0x59,
-0x75, 0x72, 0x75, 0x3b, 0x4f, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x46, 0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b,
-0x45, 0x3b, 0x55, 0x3b, 0x57, 0x3b, 0x59, 0x3b, 0x6e, 0x67, 0x31, 0x3b, 0x6e, 0x67, 0x32, 0x3b, 0x6e, 0x67, 0x33, 0x3b,
-0x6e, 0x67, 0x34, 0x3b, 0x6e, 0x67, 0x35, 0x3b, 0x6e, 0x67, 0x36, 0x3b, 0x6e, 0x67, 0x37, 0x3b, 0x6e, 0x67, 0x38, 0x3b,
-0x6e, 0x67, 0x39, 0x3b, 0x6e, 0x67, 0x31, 0x30, 0x3b, 0x6e, 0x67, 0x31, 0x31, 0x3b, 0x6b, 0x72, 0x69, 0x73, 0x3b, 0x6e,
-0x67, 0x77, 0x25b, 0x6e, 0x20, 0x6d, 0x61, 0x74, 0xe1, 0x68, 0x72, 0x61, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x144,
-0x6d, 0x62, 0x61, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x144, 0x6c, 0x61, 0x6c, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e,
-0x20, 0x144, 0x6e, 0x61, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x144, 0x74, 0x61, 0x6e, 0x3b, 0x6e, 0x67, 0x77, 0x25b,
-0x6e, 0x20, 0x144, 0x74, 0x75, 0xf3, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x68, 0x25b, 0x6d, 0x62, 0x75, 0x25b, 0x72,
-0xed, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x6c, 0x254, 0x6d, 0x62, 0x69, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20,
-0x72, 0x25b, 0x62, 0x76, 0x75, 0xe2, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x77, 0x75, 0x6d, 0x3b, 0x6e, 0x67, 0x77,
-0x25b, 0x6e, 0x20, 0x77, 0x75, 0x6d, 0x20, 0x6e, 0x61, 0x76, 0x1d4, 0x72, 0x3b, 0x6b, 0x72, 0xed, 0x73, 0x69, 0x6d, 0x69,
-0x6e, 0x3b, 0x54, 0x69, 0x6f, 0x70, 0x3b, 0x50, 0x25b, 0x74, 0x3b, 0x44, 0x75, 0x254, 0x331, 0x254, 0x331, 0x3b, 0x47, 0x75,
-0x61, 0x6b, 0x3b, 0x44, 0x75, 0xe4, 0x3b, 0x4b, 0x6f, 0x72, 0x3b, 0x50, 0x61, 0x79, 0x3b, 0x54, 0x68, 0x6f, 0x6f, 0x3b,
-0x54, 0x25b, 0x25b, 0x3b, 0x4c, 0x61, 0x61, 0x3b, 0x4b, 0x75, 0x72, 0x3b, 0x54, 0x69, 0x64, 0x3b, 0x54, 0x69, 0x6f, 0x70,
-0x20, 0x74, 0x68, 0x61, 0x72, 0x20, 0x70, 0x25b, 0x74, 0x3b, 0x50, 0x25b, 0x74, 0x3b, 0x44, 0x75, 0x254, 0x331, 0x254, 0x331,
-0x14b, 0x3b, 0x47, 0x75, 0x61, 0x6b, 0x3b, 0x44, 0x75, 0xe4, 0x74, 0x3b, 0x4b, 0x6f, 0x72, 0x6e, 0x79, 0x6f, 0x6f, 0x74,
-0x3b, 0x50, 0x61, 0x79, 0x20, 0x79, 0x69, 0x65, 0x331, 0x74, 0x6e, 0x69, 0x3b, 0x54, 0x68, 0x6f, 0x331, 0x6f, 0x331, 0x72,
-0x3b, 0x54, 0x25b, 0x25b, 0x72, 0x3b, 0x4c, 0x61, 0x61, 0x74, 0x68, 0x3b, 0x4b, 0x75, 0x72, 0x3b, 0x54, 0x69, 0x6f, 0x331,
-0x70, 0x20, 0x69, 0x6e, 0x20, 0x64, 0x69, 0x331, 0x69, 0x331, 0x74, 0x3b, 0x54, 0x3b, 0x50, 0x3b, 0x44, 0x3b, 0x47, 0x3b,
-0x44, 0x3b, 0x4b, 0x3b, 0x50, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x422, 0x43e, 0x445, 0x441,
-0x3b, 0x41e, 0x43b, 0x443, 0x43d, 0x3b, 0x41a, 0x43b, 0x43d, 0x3b, 0x41c, 0x441, 0x443, 0x3b, 0x42b, 0x430, 0x43c, 0x3b, 0x411, 0x44d,
-0x441, 0x3b, 0x41e, 0x442, 0x439, 0x3b, 0x410, 0x442, 0x440, 0x3b, 0x411, 0x43b, 0x495, 0x3b, 0x410, 0x43b, 0x442, 0x3b, 0x421, 0x44d,
-0x442, 0x3b, 0x410, 0x445, 0x441, 0x3b, 0x442, 0x43e, 0x445, 0x441, 0x443, 0x43d, 0x43d, 0x44c, 0x443, 0x3b, 0x43e, 0x43b, 0x443, 0x43d,
-0x43d, 0x44c, 0x443, 0x3b, 0x43a, 0x443, 0x43b, 0x443, 0x43d, 0x20, 0x442, 0x443, 0x442, 0x430, 0x440, 0x3b, 0x43c, 0x443, 0x443, 0x441,
-0x20, 0x443, 0x441, 0x442, 0x430, 0x440, 0x3b, 0x44b, 0x430, 0x43c, 0x20, 0x44b, 0x439, 0x430, 0x3b, 0x431, 0x44d, 0x441, 0x20, 0x44b,
-0x439, 0x430, 0x3b, 0x43e, 0x442, 0x20, 0x44b, 0x439, 0x430, 0x3b, 0x430, 0x442, 0x44b, 0x440, 0x434, 0x44c, 0x44b, 0x445, 0x20, 0x44b,
-0x439, 0x430, 0x3b, 0x431, 0x430, 0x43b, 0x430, 0x495, 0x430, 0x43d, 0x20, 0x44b, 0x439, 0x430, 0x3b, 0x430, 0x43b, 0x442, 0x44b, 0x43d,
-0x43d, 0x44c, 0x44b, 0x3b, 0x441, 0x44d, 0x442, 0x438, 0x43d, 0x43d, 0x44c, 0x438, 0x3b, 0x430, 0x445, 0x441, 0x44b, 0x43d, 0x43d, 0x44c,
-0x44b, 0x3b, 0x422, 0x3b, 0x41e, 0x3b, 0x41a, 0x3b, 0x41c, 0x3b, 0x42b, 0x3b, 0x411, 0x3b, 0x41e, 0x3b, 0x410, 0x3b, 0x411, 0x3b,
-0x410, 0x3b, 0x421, 0x3b, 0x410, 0x3b, 0x422, 0x43e, 0x445, 0x441, 0x443, 0x43d, 0x43d, 0x44c, 0x443, 0x3b, 0x41e, 0x43b, 0x443, 0x43d,
-0x43d, 0x44c, 0x443, 0x3b, 0x41a, 0x443, 0x43b, 0x443, 0x43d, 0x20, 0x442, 0x443, 0x442, 0x430, 0x440, 0x3b, 0x41c, 0x443, 0x443, 0x441,
-0x20, 0x443, 0x441, 0x442, 0x430, 0x440, 0x3b, 0x42b, 0x430, 0x43c, 0x20, 0x44b, 0x439, 0x44b, 0x43d, 0x3b, 0x411, 0x44d, 0x441, 0x20,
-0x44b, 0x439, 0x44b, 0x43d, 0x3b, 0x41e, 0x442, 0x20, 0x44b, 0x439, 0x44b, 0x43d, 0x3b, 0x410, 0x442, 0x44b, 0x440, 0x434, 0x44c, 0x44b,
-0x445, 0x20, 0x44b, 0x439, 0x44b, 0x43d, 0x3b, 0x411, 0x430, 0x43b, 0x430, 0x495, 0x430, 0x43d, 0x20, 0x44b, 0x439, 0x44b, 0x43d, 0x3b,
-0x410, 0x43b, 0x442, 0x44b, 0x43d, 0x43d, 0x44c, 0x44b, 0x3b, 0x421, 0x44d, 0x442, 0x438, 0x43d, 0x43d, 0x44c, 0x438, 0x3b, 0x430, 0x445,
-0x441, 0x44b, 0x43d, 0x43d, 0x44c, 0x44b, 0x3b, 0x4d, 0x75, 0x70, 0x3b, 0x4d, 0x77, 0x69, 0x3b, 0x4d, 0x73, 0x68, 0x3b, 0x4d,
-0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x67, 0x3b, 0x4d, 0x75, 0x6a, 0x3b, 0x4d, 0x73, 0x70, 0x3b, 0x4d, 0x70, 0x67, 0x3b, 0x4d,
-0x79, 0x65, 0x3b, 0x4d, 0x6f, 0x6b, 0x3b, 0x4d, 0x75, 0x73, 0x3b, 0x4d, 0x75, 0x68, 0x3b, 0x4d, 0x75, 0x70, 0x61, 0x6c,
-0x61, 0x6e, 0x67, 0x75, 0x6c, 0x77, 0x61, 0x3b, 0x4d, 0x77, 0x69, 0x74, 0x6f, 0x70, 0x65, 0x3b, 0x4d, 0x75, 0x73, 0x68,
-0x65, 0x6e, 0x64, 0x65, 0x3b, 0x4d, 0x75, 0x6e, 0x79, 0x69, 0x3b, 0x4d, 0x75, 0x73, 0x68, 0x65, 0x6e, 0x64, 0x65, 0x20,
-0x4d, 0x61, 0x67, 0x61, 0x6c, 0x69, 0x3b, 0x4d, 0x75, 0x6a, 0x69, 0x6d, 0x62, 0x69, 0x3b, 0x4d, 0x75, 0x73, 0x68, 0x69,
-0x70, 0x65, 0x70, 0x6f, 0x3b, 0x4d, 0x75, 0x70, 0x75, 0x67, 0x75, 0x74, 0x6f, 0x3b, 0x4d, 0x75, 0x6e, 0x79, 0x65, 0x6e,
-0x73, 0x65, 0x3b, 0x4d, 0x6f, 0x6b, 0x68, 0x75, 0x3b, 0x4d, 0x75, 0x73, 0x6f, 0x6e, 0x67, 0x61, 0x6e, 0x64, 0x65, 0x6d,
-0x62, 0x77, 0x65, 0x3b, 0x4d, 0x75, 0x68, 0x61, 0x61, 0x6e, 0x6f, 0x3b, 0xa5a8, 0xa56a, 0xa583, 0x20, 0xa51e, 0xa56e, 0x3b, 0xa552,
-0xa561, 0xa59d, 0xa595, 0x3b, 0xa57e, 0xa5ba, 0x3b, 0xa5a2, 0xa595, 0x3b, 0xa591, 0xa571, 0x3b, 0x36, 0x3b, 0x37, 0x3b, 0xa5db, 0xa515, 0x3b,
-0xa562, 0xa54c, 0x3b, 0xa56d, 0xa583, 0x3b, 0xa51e, 0xa60b, 0xa554, 0xa57f, 0x20, 0xa578, 0xa583, 0xa5cf, 0x3b, 0xa5a8, 0xa56a, 0xa571, 0x20, 0xa5cf,
-0xa56e, 0x3b, 0x6c, 0x75, 0x75, 0x6b, 0x61, 0x6f, 0x20, 0x6b, 0x65, 0x6d, 0xe3, 0x3b, 0x253, 0x61, 0x6e, 0x64, 0x61, 0x253,
-0x75, 0x3b, 0x76, 0x254, 0x254, 0x3b, 0x66, 0x75, 0x6c, 0x75, 0x3b, 0x67, 0x6f, 0x6f, 0x3b, 0x36, 0x3b, 0x37, 0x3b, 0x6b,
-0x254, 0x6e, 0x64, 0x65, 0x3b, 0x73, 0x61, 0x61, 0x68, 0x3b, 0x67, 0x61, 0x6c, 0x6f, 0x3b, 0x6b, 0x65, 0x6e, 0x70, 0x6b,
-0x61, 0x74, 0x6f, 0x20, 0x253, 0x6f, 0x6c, 0x6f, 0x6c, 0x254, 0x3b, 0x6c, 0x75, 0x75, 0x6b, 0x61, 0x6f, 0x20, 0x6c, 0x254,
-0x6d, 0x61, 0x3b, 0x4a, 0x65, 0x6e, 0x3b, 0x48, 0x6f, 0x72, 0x3b, 0x4d, 0xe4, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d,
-0x65, 0x69, 0x3b, 0x42, 0x72, 0xe1, 0x3b, 0x48, 0x65, 0x69, 0x3b, 0xd6, 0x69, 0x67, 0x3b, 0x48, 0x65, 0x72, 0x3b, 0x57,
-0xed, 0x6d, 0x3b, 0x57, 0x69, 0x6e, 0x3b, 0x43, 0x68, 0x72, 0x3b, 0x4a, 0x65, 0x6e, 0x6e, 0x65, 0x72, 0x3b, 0x48, 0x6f,
-0x72, 0x6e, 0x69, 0x67, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x65, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x6c, 0x65, 0x3b, 0x4d,
-0x65, 0x69, 0x6a, 0x65, 0x3b, 0x42, 0x72, 0xe1, 0x10d, 0x65, 0x74, 0x3b, 0x48, 0x65, 0x69, 0x77, 0x65, 0x74, 0x3b, 0xd6,
-0x69, 0x67, 0x161, 0x74, 0x65, 0x3b, 0x48, 0x65, 0x72, 0x62, 0x161, 0x74, 0x6d, 0xe1, 0x6e, 0x65, 0x74, 0x3b, 0x57, 0xed,
-0x6d, 0xe1, 0x6e, 0x65, 0x74, 0x3b, 0x57, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0xe1, 0x6e, 0x65, 0x74, 0x3b, 0x43, 0x68,
-0x72, 0x69, 0x161, 0x74, 0x6d, 0xe1, 0x6e, 0x65, 0x74, 0x3b, 0x4a, 0x3b, 0x48, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b,
-0x42, 0x3b, 0x48, 0x3b, 0xd6, 0x3b, 0x48, 0x3b, 0x57, 0x3b, 0x57, 0x3b, 0x43, 0x3b, 0x6f, 0x2e, 0x31, 0x3b, 0x6f, 0x2e,
-0x32, 0x3b, 0x6f, 0x2e, 0x33, 0x3b, 0x6f, 0x2e, 0x34, 0x3b, 0x6f, 0x2e, 0x35, 0x3b, 0x6f, 0x2e, 0x36, 0x3b, 0x6f, 0x2e,
-0x37, 0x3b, 0x6f, 0x2e, 0x38, 0x3b, 0x6f, 0x2e, 0x39, 0x3b, 0x6f, 0x2e, 0x31, 0x30, 0x3b, 0x6f, 0x2e, 0x31, 0x31, 0x3b,
-0x6f, 0x2e, 0x31, 0x32, 0x3b, 0x70, 0x69, 0x6b, 0xed, 0x74, 0xed, 0x6b, 0xed, 0x74, 0x69, 0x65, 0x2c, 0x20, 0x6f, 0xf3,
-0x6c, 0xed, 0x20, 0xfa, 0x20, 0x6b, 0x75, 0x74, 0xfa, 0x61, 0x6e, 0x3b, 0x73, 0x69, 0x25b, 0x79, 0x25b, 0x301, 0x2c, 0x20,
-0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe1, 0x6e, 0x64, 0xed, 0x25b, 0x3b, 0x254, 0x6e, 0x73, 0xfa, 0x6d, 0x62,
-0x254, 0x6c, 0x2c, 0x20, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe1, 0x74, 0xe1, 0x74, 0xfa, 0x25b, 0x3b, 0x6d,
-0x65, 0x73, 0x69, 0x14b, 0x2c, 0x20, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe9, 0x6e, 0x69, 0x65, 0x3b, 0x65,
-0x6e, 0x73, 0x69, 0x6c, 0x2c, 0x20, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe1, 0x74, 0xe1, 0x6e, 0x75, 0x25b,
-0x3b, 0x254, 0x73, 0x254, 0x6e, 0x3b, 0x65, 0x66, 0x75, 0x74, 0x65, 0x3b, 0x70, 0x69, 0x73, 0x75, 0x79, 0xfa, 0x3b, 0x69,
-0x6d, 0x25b, 0x14b, 0x20, 0x69, 0x20, 0x70, 0x75, 0x254, 0x73, 0x3b, 0x69, 0x6d, 0x25b, 0x14b, 0x20, 0x69, 0x20, 0x70, 0x75,
-0x74, 0xfa, 0x6b, 0x2c, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe1, 0x74, 0xed, 0x25b, 0x3b, 0x6d, 0x61, 0x6b,
-0x61, 0x6e, 0x64, 0x69, 0x6b, 0x25b, 0x3b, 0x70, 0x69, 0x6c, 0x254, 0x6e, 0x64, 0x254, 0x301, 0x3b, 0x58, 0x69, 0x6e, 0x3b,
-0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x58, 0x75, 0x6e, 0x3b,
-0x58, 0x6e, 0x74, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x63, 0x68, 0x3b, 0x50, 0x61, 0x79, 0x3b,
-0x41, 0x76, 0x69, 0x3b, 0x78, 0x69, 0x6e, 0x65, 0x72, 0x75, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x75, 0x3b, 0x6d,
-0x61, 0x72, 0x7a, 0x75, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x79, 0x75, 0x3b, 0x78, 0x75, 0x6e, 0x75,
-0x3b, 0x78, 0x75, 0x6e, 0x65, 0x74, 0x75, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x75, 0x3b, 0x73, 0x65, 0x74, 0x69, 0x65,
-0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, 0x68, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x70, 0x61, 0x79, 0x61, 0x72, 0x65, 0x73,
-0x3b, 0x61, 0x76, 0x69, 0x65, 0x6e, 0x74, 0x75, 0x3b, 0x58, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x58,
-0x3b, 0x58, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x50, 0x3b, 0x41, 0x3b, 0x78, 0x69, 0x6e, 0x3b, 0x66, 0x65, 0x62,
-0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x62, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x78, 0x75, 0x6e, 0x3b, 0x78, 0x6e, 0x74,
-0x3b, 0x61, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x3b, 0x6f, 0x63, 0x68, 0x3b, 0x70, 0x61, 0x79, 0x3b, 0x61, 0x76, 0x69,
-0x3b, 0x64, 0x65, 0x20, 0x78, 0x69, 0x6e, 0x65, 0x72, 0x75, 0x3b, 0x64, 0x65, 0x20, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72,
-0x75, 0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x7a, 0x75, 0x3b, 0x64, 0x2019, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x64,
-0x65, 0x20, 0x6d, 0x61, 0x79, 0x75, 0x3b, 0x64, 0x65, 0x20, 0x78, 0x75, 0x6e, 0x75, 0x3b, 0x64, 0x65, 0x20, 0x78, 0x75,
-0x6e, 0x65, 0x74, 0x75, 0x3b, 0x64, 0x2019, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x75, 0x3b, 0x64, 0x65, 0x20, 0x73, 0x65, 0x74,
-0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x2019, 0x6f, 0x63, 0x68, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x65, 0x20,
-0x70, 0x61, 0x79, 0x61, 0x72, 0x65, 0x73, 0x3b, 0x64, 0x2019, 0x61, 0x76, 0x69, 0x65, 0x6e, 0x74, 0x75, 0x3b, 0x4e, 0x64,
-0x75, 0x14b, 0x6d, 0x62, 0x69, 0x20, 0x53, 0x61, 0x14b, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301, 0x70,
-0xe1, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301, 0x74, 0xe1, 0x74, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b,
-0x20, 0x50, 0x25b, 0x301, 0x6e, 0x25b, 0x301, 0x6b, 0x77, 0x61, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x61, 0x74,
-0x61, 0x61, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301, 0x6e, 0x25b, 0x301, 0x6e, 0x74, 0xfa, 0x6b, 0xfa,
-0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x53, 0x61, 0x61, 0x6d, 0x62, 0xe1, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20,
-0x50, 0x25b, 0x301, 0x6e, 0x25b, 0x301, 0x66, 0x254, 0x6d, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301, 0x6e,
-0x25b, 0x301, 0x70, 0x66, 0xfa, 0xa78b, 0xfa, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x4e, 0x25b, 0x67, 0x25b, 0x301, 0x6d,
-0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x4e, 0x74, 0x73, 0x254, 0x30c, 0x70, 0x6d, 0x254, 0x301, 0x3b, 0x50, 0x25b, 0x73,
-0x61, 0x14b, 0x20, 0x4e, 0x74, 0x73, 0x254, 0x30c, 0x70, 0x70, 0xe1, 0x3b, 0x70, 0x61, 0x6d, 0x62, 0x61, 0x3b, 0x77, 0x61,
-0x6e, 0x6a, 0x61, 0x3b, 0x6d, 0x62, 0x69, 0x79, 0x254, 0x20, 0x6d, 0x25b, 0x6e, 0x64, 0x6f, 0x14b, 0x67, 0x254, 0x3b, 0x4e,
-0x79, 0x254, 0x6c, 0x254, 0x6d, 0x62, 0x254, 0x14b, 0x67, 0x254, 0x3b, 0x4d, 0x254, 0x6e, 0x254, 0x20, 0x14b, 0x67, 0x62, 0x61,
-0x6e, 0x6a, 0x61, 0x3b, 0x4e, 0x79, 0x61, 0x14b, 0x67, 0x77, 0x25b, 0x20, 0x14b, 0x67, 0x62, 0x61, 0x6e, 0x6a, 0x61, 0x3b,
-0x6b, 0x75, 0x14b, 0x67, 0x77, 0x25b, 0x3b, 0x66, 0x25b, 0x3b, 0x6e, 0x6a, 0x61, 0x70, 0x69, 0x3b, 0x6e, 0x79, 0x75, 0x6b,
-0x75, 0x6c, 0x3b, 0x31, 0x31, 0x3b, 0x253, 0x75, 0x6c, 0x253, 0x75, 0x73, 0x25b, 0x3b, 0x6d, 0x62, 0x65, 0x67, 0x74, 0x75,
+0x6e, 0x61, 0x20, 0x4d, 0x3b, 0x46, 0xfa, 0x6e, 0x67, 0x61, 0x74, 0x268, 0x3b, 0x4e, 0x61, 0x61, 0x6e, 0x268, 0x3b, 0x4b,
+0x65, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x49, 0x6b, 0xfa, 0x6d, 0x69, 0x3b, 0x49, 0x6e, 0x79, 0x61, 0x6d, 0x62, 0x61, 0x6c,
+0x61, 0x3b, 0x49, 0x64, 0x77, 0x61, 0x61, 0x74, 0x61, 0x3b, 0x4d, 0x289, 0x289, 0x6e, 0x63, 0x68, 0x268, 0x3b, 0x56, 0x268,
+0x268, 0x72, 0x268, 0x3b, 0x53, 0x61, 0x61, 0x74, 0x289, 0x3b, 0x49, 0x6e, 0x79, 0x69, 0x3b, 0x53, 0x61, 0x61, 0x6e, 0x6f,
+0x3b, 0x53, 0x61, 0x73, 0x61, 0x74, 0x289, 0x3b, 0x4b, 0x289, 0x66, 0xfa, 0x6e, 0x67, 0x61, 0x74, 0x268, 0x3b, 0x4b, 0x289,
+0x6e, 0x61, 0x61, 0x6e, 0x268, 0x3b, 0x4b, 0x289, 0x6b, 0x65, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4b, 0x77, 0x69, 0x69, 0x6b,
+0x75, 0x6d, 0x69, 0x3b, 0x4b, 0x77, 0x69, 0x69, 0x6e, 0x79, 0x61, 0x6d, 0x62, 0xe1, 0x6c, 0x61, 0x3b, 0x4b, 0x77, 0x69,
+0x69, 0x64, 0x77, 0x61, 0x61, 0x74, 0x61, 0x3b, 0x4b, 0x289, 0x6d, 0x289, 0x289, 0x6e, 0x63, 0x68, 0x268, 0x3b, 0x4b, 0x289,
+0x76, 0x268, 0x268, 0x72, 0x268, 0x3b, 0x4b, 0x289, 0x73, 0x61, 0x61, 0x74, 0x289, 0x3b, 0x4b, 0x77, 0x69, 0x69, 0x6e, 0x79,
+0x69, 0x3b, 0x4b, 0x289, 0x73, 0x61, 0x61, 0x6e, 0x6f, 0x3b, 0x4b, 0x289, 0x73, 0x61, 0x73, 0x61, 0x74, 0x289, 0x3b, 0x46,
+0x3b, 0x4e, 0x3b, 0x4b, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x4d, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x49, 0x3b, 0x53,
+0x3b, 0x53, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x75, 0x3b, 0x4d,
+0x61, 0x61, 0x3b, 0x4a, 0x75, 0x75, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x75, 0x3b, 0x53, 0x65, 0x62, 0x3b, 0x4f,
+0x6b, 0x69, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x77, 0x61, 0x6c, 0x69, 0x79, 0x6f,
+0x3b, 0x46, 0x65, 0x62, 0x77, 0x61, 0x6c, 0x69, 0x79, 0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x69, 0x73, 0x69, 0x3b, 0x41, 0x70,
+0x75, 0x6c, 0x69, 0x3b, 0x4d, 0x61, 0x61, 0x79, 0x69, 0x3b, 0x4a, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61,
+0x61, 0x79, 0x69, 0x3b, 0x41, 0x67, 0x75, 0x73, 0x69, 0x74, 0x6f, 0x3b, 0x53, 0x65, 0x62, 0x75, 0x74, 0x74, 0x65, 0x6d,
+0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x69, 0x74, 0x6f, 0x62, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b,
+0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x63, 0x3b,
+0x45, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x4f, 0x67, 0x61, 0x3b,
+0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x75,
+0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x45,
+0x70, 0x72, 0x65, 0x6f, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x69, 0x3b,
+0x4f, 0x67, 0x61, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f,
+0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4a,
+0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4f, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e,
+0x3b, 0x44, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d,
+0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f,
+0x74, 0x75, 0x3b, 0x4e, 0x75, 0x76, 0x3b, 0x44, 0x69, 0x7a, 0x3b, 0x4a, 0x61, 0x6e, 0x65, 0x72, 0x75, 0x3b, 0x46, 0x65,
+0x62, 0x72, 0x65, 0x72, 0x75, 0x3b, 0x4d, 0x61, 0x72, 0x73, 0x75, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61,
+0x69, 0x75, 0x3b, 0x4a, 0x75, 0x6e, 0x68, 0x75, 0x3b, 0x4a, 0x75, 0x6c, 0x68, 0x75, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74,
+0x75, 0x3b, 0x53, 0x65, 0x74, 0x65, 0x6e, 0x62, 0x72, 0x75, 0x3b, 0x4f, 0x74, 0x75, 0x62, 0x72, 0x75, 0x3b, 0x4e, 0x75,
+0x76, 0x65, 0x6e, 0x62, 0x72, 0x75, 0x3b, 0x44, 0x69, 0x7a, 0x65, 0x6e, 0x62, 0x72, 0x75, 0x3b, 0x4a, 0x41, 0x4e, 0x3b,
+0x46, 0x45, 0x42, 0x3b, 0x4d, 0x41, 0x43, 0x3b, 0x128, 0x50, 0x55, 0x3b, 0x4d, 0x128, 0x128, 0x3b, 0x4e, 0x4a, 0x55, 0x3b,
+0x4e, 0x4a, 0x52, 0x3b, 0x41, 0x47, 0x41, 0x3b, 0x53, 0x50, 0x54, 0x3b, 0x4f, 0x4b, 0x54, 0x3b, 0x4e, 0x4f, 0x56, 0x3b,
+0x44, 0x45, 0x43, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x129, 0x3b, 0x46, 0x65, 0x62, 0x75, 0x72, 0x75, 0x61, 0x72,
+0x129, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x128, 0x70, 0x75, 0x72, 0x169, 0x3b, 0x4d, 0x129, 0x129, 0x3b, 0x4e, 0x6a,
+0x75, 0x6e, 0x69, 0x3b, 0x4e, 0x6a, 0x75, 0x72, 0x61, 0x129, 0x3b, 0x41, 0x67, 0x61, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65,
+0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x169, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62,
+0x61, 0x3b, 0x44, 0x69, 0x63, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x128, 0x3b, 0x4d, 0x3b,
+0x4e, 0x3b, 0x4e, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x4d, 0x75, 0x6c, 0x3b, 0x4e, 0x67,
+0x61, 0x74, 0x3b, 0x54, 0x61, 0x61, 0x3b, 0x49, 0x77, 0x6f, 0x3b, 0x4d, 0x61, 0x6d, 0x3b, 0x50, 0x61, 0x61, 0x3b, 0x4e,
+0x67, 0x65, 0x3b, 0x52, 0x6f, 0x6f, 0x3b, 0x42, 0x75, 0x72, 0x3b, 0x45, 0x70, 0x65, 0x3b, 0x4b, 0x70, 0x74, 0x3b, 0x4b,
+0x70, 0x61, 0x3b, 0x4d, 0x75, 0x6c, 0x67, 0x75, 0x6c, 0x3b, 0x4e, 0x67, 0x2019, 0x61, 0x74, 0x79, 0x61, 0x61, 0x74, 0x6f,
+0x3b, 0x4b, 0x69, 0x70, 0x74, 0x61, 0x61, 0x6d, 0x6f, 0x3b, 0x49, 0x77, 0x6f, 0x6f, 0x74, 0x6b, 0x75, 0x75, 0x74, 0x3b,
+0x4d, 0x61, 0x6d, 0x75, 0x75, 0x74, 0x3b, 0x50, 0x61, 0x61, 0x67, 0x69, 0x3b, 0x4e, 0x67, 0x2019, 0x65, 0x69, 0x79, 0x65,
+0x65, 0x74, 0x3b, 0x52, 0x6f, 0x6f, 0x70, 0x74, 0x75, 0x69, 0x3b, 0x42, 0x75, 0x72, 0x65, 0x65, 0x74, 0x3b, 0x45, 0x70,
+0x65, 0x65, 0x73, 0x6f, 0x3b, 0x4b, 0x69, 0x70, 0x73, 0x75, 0x75, 0x6e, 0x64, 0x65, 0x20, 0x6e, 0x65, 0x20, 0x74, 0x61,
+0x61, 0x69, 0x3b, 0x4b, 0x69, 0x70, 0x73, 0x75, 0x75, 0x6e, 0x64, 0x65, 0x20, 0x6e, 0x65, 0x62, 0x6f, 0x20, 0x61, 0x65,
+0x6e, 0x67, 0x2019, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x49, 0x3b, 0x4d, 0x3b, 0x50, 0x3b, 0x4e, 0x3b, 0x52, 0x3b,
+0x42, 0x3b, 0x45, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x1c3, 0x4b, 0x68, 0x61, 0x6e, 0x6e, 0x69, 0x3b, 0x1c3, 0x4b, 0x68, 0x61,
+0x6e, 0x1c0, 0x67, 0xf4, 0x61, 0x62, 0x3b, 0x1c0, 0x4b, 0x68, 0x75, 0x75, 0x1c1, 0x6b, 0x68, 0xe2, 0x62, 0x3b, 0x1c3, 0x48,
+0xf4, 0x61, 0x1c2, 0x6b, 0x68, 0x61, 0x69, 0x62, 0x3b, 0x1c3, 0x4b, 0x68, 0x61, 0x69, 0x74, 0x73, 0xe2, 0x62, 0x3b, 0x47,
+0x61, 0x6d, 0x61, 0x1c0, 0x61, 0x65, 0x62, 0x3b, 0x1c2, 0x4b, 0x68, 0x6f, 0x65, 0x73, 0x61, 0x6f, 0x62, 0x3b, 0x41, 0x6f,
+0x1c1, 0x6b, 0x68, 0x75, 0x75, 0x6d, 0xfb, 0x1c1, 0x6b, 0x68, 0xe2, 0x62, 0x3b, 0x54, 0x61, 0x72, 0x61, 0x1c0, 0x6b, 0x68,
+0x75, 0x75, 0x6d, 0xfb, 0x1c1, 0x6b, 0x68, 0xe2, 0x62, 0x3b, 0x1c2, 0x4e, 0xfb, 0x1c1, 0x6e, 0xe2, 0x69, 0x73, 0x65, 0x62,
+0x3b, 0x1c0, 0x48, 0x6f, 0x6f, 0x1c2, 0x67, 0x61, 0x65, 0x62, 0x3b, 0x48, 0xf4, 0x61, 0x73, 0x6f, 0x72, 0x65, 0x1c1, 0x6b,
+0x68, 0xe2, 0x62, 0x3b, 0x4a, 0x61, 0x6e, 0x2e, 0x3b, 0x46, 0xe4, 0x62, 0x2e, 0x3b, 0x4d, 0xe4, 0x7a, 0x2e, 0x3b, 0x41,
+0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x2e, 0x3b, 0x4a, 0x75, 0x6c, 0x2e, 0x3b, 0x4f, 0x75,
+0x6a, 0x2e, 0x3b, 0x53, 0xe4, 0x70, 0x2e, 0x3b, 0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65,
+0x7a, 0x2e, 0x3b, 0x4a, 0x61, 0x6e, 0x6e, 0x65, 0x77, 0x61, 0x3b, 0x46, 0xe4, 0x62, 0x72, 0x6f, 0x77, 0x61, 0x3b, 0x4d,
+0xe4, 0xe4, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x65, 0x6c, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x75, 0x6e, 0x69,
+0x3b, 0x4a, 0x75, 0x75, 0x6c, 0x69, 0x3b, 0x4f, 0x75, 0x6a, 0x6f, 0xdf, 0x3b, 0x53, 0x65, 0x70, 0x74, 0xe4, 0x6d, 0x62,
+0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x68, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0xe4, 0x6d, 0x62, 0x65, 0x72,
+0x3b, 0x44, 0x65, 0x7a, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0xe4, 0x62, 0x3b, 0x4d, 0xe4,
+0x7a, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x4f, 0x75,
+0x6a, 0x3b, 0x53, 0xe4, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a, 0x3b, 0x44, 0x61,
+0x6c, 0x3b, 0x41, 0x72, 0xe1, 0x3b, 0x186, 0x25b, 0x6e, 0x3b, 0x44, 0x6f, 0x79, 0x3b, 0x4c, 0xe9, 0x70, 0x3b, 0x52, 0x6f,
+0x6b, 0x3b, 0x53, 0xe1, 0x73, 0x3b, 0x42, 0x254, 0x301, 0x72, 0x3b, 0x4b, 0xfa, 0x73, 0x3b, 0x47, 0xed, 0x73, 0x3b, 0x53,
+0x68, 0x289, 0x301, 0x3b, 0x4e, 0x74, 0x289, 0x301, 0x3b, 0x4f, 0x6c, 0x61, 0x64, 0x61, 0x6c, 0x289, 0x301, 0x3b, 0x41, 0x72,
+0xe1, 0x74, 0x3b, 0x186, 0x25b, 0x6e, 0x268, 0x301, 0x254, 0x268, 0x14b, 0x254, 0x6b, 0x3b, 0x4f, 0x6c, 0x6f, 0x64, 0x6f, 0x79,
+0xed, 0xf3, 0x72, 0xed, 0xea, 0x20, 0x69, 0x6e, 0x6b, 0xf3, 0x6b, 0xfa, 0xe2, 0x3b, 0x4f, 0x6c, 0x6f, 0x69, 0x6c, 0xe9,
+0x70, 0x16b, 0x6e, 0x79, 0x12b, 0x113, 0x20, 0x69, 0x6e, 0x6b, 0xf3, 0x6b, 0xfa, 0xe2, 0x3b, 0x4b, 0xfa, 0x6a, 0xfa, 0x254,
+0x72, 0x254, 0x6b, 0x3b, 0x4d, 0xf3, 0x72, 0x75, 0x73, 0xe1, 0x73, 0x69, 0x6e, 0x3b, 0x186, 0x6c, 0x254, 0x301, 0x268, 0x301,
+0x62, 0x254, 0x301, 0x72, 0xe1, 0x72, 0x25b, 0x3b, 0x4b, 0xfa, 0x73, 0x68, 0xee, 0x6e, 0x3b, 0x4f, 0x6c, 0x67, 0xed, 0x73,
+0x61, 0x6e, 0x3b, 0x50, 0x289, 0x73, 0x68, 0x289, 0x301, 0x6b, 0x61, 0x3b, 0x4e, 0x74, 0x289, 0x301, 0x14b, 0x289, 0x301, 0x73,
+0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69,
+0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74,
+0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x63,
+0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f,
+0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x63, 0x3b, 0x52, 0x61, 0x72,
+0x3b, 0x4d, 0x75, 0x6b, 0x3b, 0x4b, 0x77, 0x61, 0x3b, 0x44, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4d, 0x6f, 0x64,
+0x3b, 0x4a, 0x6f, 0x6c, 0x3b, 0x50, 0x65, 0x64, 0x3b, 0x53, 0x6f, 0x6b, 0x3b, 0x54, 0x69, 0x62, 0x3b, 0x4c, 0x61, 0x62,
+0x3b, 0x50, 0x6f, 0x6f, 0x3b, 0x4f, 0x72, 0x61, 0x72, 0x61, 0x3b, 0x4f, 0x6d, 0x75, 0x6b, 0x3b, 0x4f, 0x6b, 0x77, 0x61,
+0x6d, 0x67, 0x2019, 0x3b, 0x4f, 0x64, 0x75, 0x6e, 0x67, 0x2019, 0x65, 0x6c, 0x3b, 0x4f, 0x6d, 0x61, 0x72, 0x75, 0x6b, 0x3b,
+0x4f, 0x6d, 0x6f, 0x64, 0x6f, 0x6b, 0x2019, 0x6b, 0x69, 0x6e, 0x67, 0x2019, 0x6f, 0x6c, 0x3b, 0x4f, 0x6a, 0x6f, 0x6c, 0x61,
+0x3b, 0x4f, 0x70, 0x65, 0x64, 0x65, 0x6c, 0x3b, 0x4f, 0x73, 0x6f, 0x6b, 0x6f, 0x73, 0x6f, 0x6b, 0x6f, 0x6d, 0x61, 0x3b,
+0x4f, 0x74, 0x69, 0x62, 0x61, 0x72, 0x3b, 0x4f, 0x6c, 0x61, 0x62, 0x6f, 0x72, 0x3b, 0x4f, 0x70, 0x6f, 0x6f, 0x3b, 0x52,
+0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x44, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x4c,
+0x3b, 0x50, 0x3b, 0x17d, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x65, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x77, 0x69, 0x3b, 0x4d,
+0x65, 0x3b, 0x17d, 0x75, 0x77, 0x3b, 0x17d, 0x75, 0x79, 0x3b, 0x55, 0x74, 0x3b, 0x53, 0x65, 0x6b, 0x3b, 0x4f, 0x6b, 0x74,
+0x3b, 0x4e, 0x6f, 0x6f, 0x3b, 0x44, 0x65, 0x65, 0x3b, 0x17d, 0x61, 0x6e, 0x77, 0x69, 0x79, 0x65, 0x3b, 0x46, 0x65, 0x65,
+0x77, 0x69, 0x72, 0x69, 0x79, 0x65, 0x3b, 0x4d, 0x61, 0x72, 0x73, 0x69, 0x3b, 0x41, 0x77, 0x69, 0x72, 0x69, 0x6c, 0x3b,
+0x4d, 0x65, 0x3b, 0x17d, 0x75, 0x77, 0x65, 0x14b, 0x3b, 0x17d, 0x75, 0x79, 0x79, 0x65, 0x3b, 0x55, 0x74, 0x3b, 0x53, 0x65,
+0x6b, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x6f, 0x62, 0x75, 0x72, 0x3b, 0x4e, 0x6f, 0x6f,
+0x77, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x3b, 0x44, 0x65, 0x65, 0x73, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x3b, 0x17d, 0x3b, 0x46,
+0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x17d, 0x3b, 0x17d, 0x3b, 0x55, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44,
+0x3b, 0x44, 0x41, 0x43, 0x3b, 0x44, 0x41, 0x52, 0x3b, 0x44, 0x41, 0x44, 0x3b, 0x44, 0x41, 0x4e, 0x3b, 0x44, 0x41, 0x48,
+0x3b, 0x44, 0x41, 0x55, 0x3b, 0x44, 0x41, 0x4f, 0x3b, 0x44, 0x41, 0x42, 0x3b, 0x44, 0x4f, 0x43, 0x3b, 0x44, 0x41, 0x50,
+0x3b, 0x44, 0x47, 0x49, 0x3b, 0x44, 0x41, 0x47, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x63, 0x68,
+0x69, 0x65, 0x6c, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x72, 0x69, 0x79, 0x6f, 0x3b, 0x44, 0x77,
+0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x64, 0x65, 0x6b, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41,
+0x6e, 0x67, 0x2019, 0x77, 0x65, 0x6e, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x62, 0x69, 0x63, 0x68,
+0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x75, 0x63, 0x68, 0x69, 0x65, 0x6c, 0x3b, 0x44, 0x77, 0x65,
+0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x62, 0x69, 0x72, 0x69, 0x79, 0x6f, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72,
+0x20, 0x41, 0x62, 0x6f, 0x72, 0x6f, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x4f, 0x63, 0x68, 0x69, 0x6b,
+0x6f, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x70, 0x61, 0x72, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d,
+0x61, 0x72, 0x20, 0x67, 0x69, 0x20, 0x61, 0x63, 0x68, 0x69, 0x65, 0x6c, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72,
+0x20, 0x41, 0x70, 0x61, 0x72, 0x20, 0x67, 0x69, 0x20, 0x61, 0x72, 0x69, 0x79, 0x6f, 0x3b, 0x43, 0x3b, 0x52, 0x3b, 0x44,
+0x3b, 0x4e, 0x3b, 0x42, 0x3b, 0x55, 0x3b, 0x42, 0x3b, 0x42, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x59,
+0x65, 0x6e, 0x3b, 0x59, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x49, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x59,
+0x75, 0x6e, 0x3b, 0x59, 0x75, 0x6c, 0x3b, 0x194, 0x75, 0x63, 0x3b, 0x43, 0x75, 0x74, 0x3b, 0x4b, 0x1e6d, 0x75, 0x3b, 0x4e,
+0x77, 0x61, 0x3b, 0x44, 0x75, 0x6a, 0x3b, 0x59, 0x65, 0x6e, 0x6e, 0x61, 0x79, 0x65, 0x72, 0x3b, 0x59, 0x65, 0x62, 0x72,
+0x61, 0x79, 0x65, 0x72, 0x3b, 0x4d, 0x61, 0x72, 0x73, 0x3b, 0x49, 0x62, 0x72, 0x69, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x79,
+0x75, 0x3b, 0x59, 0x75, 0x6e, 0x79, 0x75, 0x3b, 0x59, 0x75, 0x6c, 0x79, 0x75, 0x7a, 0x3b, 0x194, 0x75, 0x63, 0x74, 0x3b,
+0x43, 0x75, 0x74, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b, 0x4b, 0x1e6d, 0x75, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x77, 0x61, 0x6e,
+0x62, 0x69, 0x72, 0x3b, 0x44, 0x75, 0x6a, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x4d, 0x3b, 0x49,
+0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x194, 0x3b, 0x43, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x4a, 0x61, 0x6e,
+0x75, 0x61, 0x6c, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x6c, 0x75, 0x61, 0x6c, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b,
+0x41, 0x70, 0x6c, 0x69, 0x6c, 0x69, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61,
+0x69, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b,
+0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x61,
+0x3b, 0x91c, 0x93e, 0x928, 0x941, 0x935, 0x93e, 0x930, 0x940, 0x3b, 0x92b, 0x947, 0x92c, 0x94d, 0x930, 0x941, 0x935, 0x93e, 0x930, 0x940,
+0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x938, 0x3b, 0x90f, 0x92b, 0x94d, 0x930, 0x93f, 0x932, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x941, 0x928,
+0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x907, 0x3b, 0x906, 0x917, 0x938, 0x94d, 0x925, 0x3b, 0x938, 0x947, 0x92c, 0x925, 0x947, 0x91c, 0x94d,
+0x92c, 0x93c, 0x930, 0x3b, 0x905, 0x916, 0x925, 0x92c, 0x930, 0x3b, 0x928, 0x92c, 0x947, 0x91c, 0x94d, 0x92c, 0x93c, 0x930, 0x3b, 0x926,
+0x93f, 0x938, 0x947, 0x91c, 0x94d, 0x92c, 0x93c, 0x930, 0x3b, 0x91c, 0x3b, 0x92b, 0x947, 0x3b, 0x92e, 0x93e, 0x3b, 0x90f, 0x3b, 0x92e,
+0x947, 0x3b, 0x91c, 0x941, 0x3b, 0x91c, 0x941, 0x3b, 0x906, 0x3b, 0x938, 0x947, 0x3b, 0x905, 0x3b, 0x928, 0x3b, 0x926, 0x93f, 0x3b,
+0x456, 0x486, 0x430, 0x2de9, 0x487, 0x3b, 0x444, 0x435, 0x2de1, 0x487, 0x3b, 0x43c, 0x430, 0x2dec, 0x487, 0x3b, 0x430, 0x486, 0x43f, 0x2dec,
+0x487, 0x3b, 0x43c, 0x430, 0xa675, 0x3b, 0x456, 0x486, 0xa64b, 0x2de9, 0x487, 0x3b, 0x456, 0x486, 0xa64b, 0x2de7, 0x487, 0x3b, 0x430, 0x486,
+0x301, 0x475, 0x2de2, 0x487, 0x3b, 0x441, 0x435, 0x2deb, 0x487, 0x3b, 0x47b, 0x486, 0x43a, 0x2dee, 0x3b, 0x43d, 0x43e, 0x435, 0x2de8, 0x3b,
+0x434, 0x435, 0x2de6, 0x487, 0x3b, 0x456, 0x486, 0x430, 0x43d, 0x43d, 0xa64b, 0x430, 0x301, 0x440, 0x457, 0x439, 0x3b, 0x444, 0x435, 0x432,
+0x440, 0xa64b, 0x430, 0x301, 0x440, 0x457, 0x439, 0x3b, 0x43c, 0x430, 0x301, 0x440, 0x442, 0x44a, 0x3b, 0x430, 0x486, 0x43f, 0x440, 0x456,
+0x301, 0x43b, 0x43b, 0x457, 0x439, 0x3b, 0x43c, 0x430, 0x301, 0x457, 0x439, 0x3b, 0x456, 0x486, 0xa64b, 0x301, 0x43d, 0x457, 0x439, 0x3b,
+0x456, 0x486, 0xa64b, 0x301, 0x43b, 0x457, 0x439, 0x3b, 0x430, 0x486, 0x301, 0x475, 0x433, 0xa64b, 0x441, 0x442, 0x44a, 0x3b, 0x441, 0x435,
+0x43f, 0x442, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x439, 0x3b, 0x47b, 0x486, 0x43a, 0x442, 0x461, 0x301, 0x432, 0x440, 0x457, 0x439,
+0x3b, 0x43d, 0x43e, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x439, 0x3b, 0x434, 0x435, 0x43a, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457,
+0x439, 0x3b, 0x406, 0x486, 0x3b, 0x424, 0x3b, 0x41c, 0x3b, 0x410, 0x486, 0x3b, 0x41c, 0x3b, 0x406, 0x486, 0x3b, 0x406, 0x486, 0x3b,
+0x410, 0x486, 0x3b, 0x421, 0x3b, 0x47a, 0x486, 0x3b, 0x41d, 0x3b, 0x414, 0x3b, 0x456, 0x486, 0x430, 0x43d, 0x43d, 0xa64b, 0x430, 0x301,
+0x440, 0x457, 0x430, 0x3b, 0x444, 0x435, 0x432, 0x440, 0xa64b, 0x430, 0x301, 0x440, 0x457, 0x430, 0x3b, 0x43c, 0x430, 0x301, 0x440, 0x442,
+0x430, 0x3b, 0x430, 0x486, 0x43f, 0x440, 0x456, 0x301, 0x43b, 0x43b, 0x457, 0x430, 0x3b, 0x43c, 0x430, 0x301, 0x457, 0x430, 0x3b, 0x456,
+0x486, 0xa64b, 0x301, 0x43d, 0x457, 0x430, 0x3b, 0x456, 0x486, 0xa64b, 0x301, 0x43b, 0x457, 0x430, 0x3b, 0x430, 0x486, 0x301, 0x475, 0x433,
+0xa64b, 0x441, 0x442, 0x430, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x430, 0x3b, 0x47b, 0x486, 0x43a,
+0x442, 0x461, 0x301, 0x432, 0x440, 0x457, 0x430, 0x3b, 0x43d, 0x43e, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x430, 0x3b, 0x434, 0x435,
+0x43a, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x430, 0x3b, 0x43, 0x69, 0x6f, 0x3b, 0x4c, 0x75, 0x69, 0x3b, 0x4c, 0x75, 0x73,
+0x3b, 0x4d, 0x75, 0x75, 0x3b, 0x4c, 0x75, 0x6d, 0x3b, 0x4c, 0x75, 0x66, 0x3b, 0x4b, 0x61, 0x62, 0x3b, 0x4c, 0x75, 0x73,
+0x68, 0x3b, 0x4c, 0x75, 0x74, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4b, 0x61, 0x73, 0x3b, 0x43, 0x69, 0x73, 0x3b, 0x43, 0x69,
+0x6f, 0x6e, 0x67, 0x6f, 0x3b, 0x4c, 0xf9, 0x69, 0x73, 0x68, 0x69, 0x3b, 0x4c, 0x75, 0x73, 0xf2, 0x6c, 0x6f, 0x3b, 0x4d,
+0xf9, 0x75, 0x79, 0xe0, 0x3b, 0x4c, 0x75, 0x6d, 0xf9, 0x6e, 0x67, 0xf9, 0x6c, 0xf9, 0x3b, 0x4c, 0x75, 0x66, 0x75, 0x69,
+0x6d, 0x69, 0x3b, 0x4b, 0x61, 0x62, 0xe0, 0x6c, 0xe0, 0x73, 0x68, 0xec, 0x70, 0xf9, 0x3b, 0x4c, 0xf9, 0x73, 0x68, 0xec,
+0x6b, 0xe0, 0x3b, 0x4c, 0x75, 0x74, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x6f, 0x3b, 0x4c, 0x75, 0x6e, 0x67, 0xf9, 0x64, 0x69,
+0x3b, 0x4b, 0x61, 0x73, 0x77, 0xe8, 0x6b, 0xe8, 0x73, 0xe8, 0x3b, 0x43, 0x69, 0x73, 0x77, 0xe0, 0x3b, 0x43, 0x3b, 0x4c,
+0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4b, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4b, 0x3b, 0x43,
+0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0xe4, 0x65, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x65, 0x65,
+0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74,
+0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x62, 0x72,
+0x75, 0x61, 0x72, 0x3b, 0x4d, 0xe4, 0x65, 0x72, 0x7a, 0x3b, 0x41, 0x62, 0x72, 0xeb, 0x6c, 0x6c, 0x3b, 0x4d, 0x65, 0x65,
+0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65,
+0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65,
+0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x61, 0x6e, 0x2e, 0x3b, 0x46,
+0x65, 0x62, 0x2e, 0x3b, 0x4d, 0xe4, 0x65, 0x2e, 0x3b, 0x41, 0x62, 0x72, 0x2e, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75,
+0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65, 0x70, 0x2e, 0x3b, 0x4f, 0x6b,
+0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x7a, 0x2e, 0x3b, 0x6e, 0xf9, 0x6d, 0x3b, 0x6b, 0x268, 0x7a,
+0x3b, 0x74, 0x268, 0x64, 0x3b, 0x74, 0x61, 0x61, 0x3b, 0x73, 0x65, 0x65, 0x3b, 0x6e, 0x7a, 0x75, 0x3b, 0x64, 0x75, 0x6d,
+0x3b, 0x66, 0x254, 0x65, 0x3b, 0x64, 0x7a, 0x75, 0x3b, 0x6c, 0x254, 0x6d, 0x3b, 0x6b, 0x61, 0x61, 0x3b, 0x66, 0x77, 0x6f,
+0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x6e, 0xf9, 0x6d, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254,
+0x300, 0x6b, 0x197, 0x300, 0x7a, 0xf9, 0x294, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x74, 0x197, 0x300, 0x64,
+0x289, 0x300, 0x67, 0x68, 0xe0, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x74, 0x1ce, 0x61, 0x66, 0x289, 0x304,
+0x67, 0x68, 0x101, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0xe8, 0x73, 0xe8, 0x65, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300,
+0x14b, 0x254, 0x300, 0x6e, 0x7a, 0xf9, 0x67, 0x68, 0xf2, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x64, 0xf9,
+0x6d, 0x6c, 0x6f, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x6b, 0x77, 0xee, 0x66, 0x254, 0x300, 0x65, 0x3b,
+0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x74, 0x197, 0x300, 0x66, 0x289, 0x300, 0x67, 0x68, 0xe0, 0x64, 0x7a, 0x75,
+0x67, 0x68, 0xf9, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x67, 0x68, 0x1d4, 0x75, 0x77, 0x65, 0x6c, 0x254,
+0x300, 0x6d, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x63, 0x68, 0x77, 0x61, 0x294, 0xe0, 0x6b, 0x61, 0x61,
+0x20, 0x77, 0x6f, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0xe8, 0x66, 0x77, 0xf2, 0x6f, 0x3b, 0x6e, 0x3b, 0x6b, 0x3b,
+0x74, 0x3b, 0x74, 0x3b, 0x73, 0x3b, 0x7a, 0x3b, 0x6b, 0x3b, 0x66, 0x3b, 0x64, 0x3b, 0x6c, 0x3b, 0x63, 0x3b, 0x66, 0x3b,
+0x6b, 0x254, 0x6e, 0x3b, 0x6d, 0x61, 0x63, 0x3b, 0x6d, 0x61, 0x74, 0x3b, 0x6d, 0x74, 0x6f, 0x3b, 0x6d, 0x70, 0x75, 0x3b,
+0x68, 0x69, 0x6c, 0x3b, 0x6e, 0x6a, 0x65, 0x3b, 0x68, 0x69, 0x6b, 0x3b, 0x64, 0x69, 0x70, 0x3b, 0x62, 0x69, 0x6f, 0x3b,
+0x6d, 0x61, 0x79, 0x3b, 0x6c, 0x69, 0x253, 0x3b, 0x4b, 0x254, 0x6e, 0x64, 0x254, 0x14b, 0x3b, 0x4d, 0xe0, 0x63, 0x25b, 0x302,
+0x6c, 0x3b, 0x4d, 0xe0, 0x74, 0xf9, 0x6d, 0x62, 0x3b, 0x4d, 0xe0, 0x74, 0x6f, 0x70, 0x3b, 0x4d, 0x300, 0x70, 0x75, 0x79,
+0x25b, 0x3b, 0x48, 0xec, 0x6c, 0xf2, 0x6e, 0x64, 0x25b, 0x300, 0x3b, 0x4e, 0x6a, 0xe8, 0x62, 0xe0, 0x3b, 0x48, 0xec, 0x6b,
+0x61, 0x14b, 0x3b, 0x44, 0xec, 0x70, 0x254, 0x300, 0x73, 0x3b, 0x42, 0xec, 0xf2, 0xf4, 0x6d, 0x3b, 0x4d, 0xe0, 0x79, 0x25b,
+0x73, 0xe8, 0x70, 0x3b, 0x4c, 0xec, 0x62, 0x75, 0x79, 0x20, 0x6c, 0x69, 0x20, 0x144, 0x79, 0xe8, 0x65, 0x3b, 0x6b, 0x3b,
+0x6d, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x68, 0x3b, 0x6e, 0x3b, 0x68, 0x3b, 0x64, 0x3b, 0x62, 0x3b, 0x6d, 0x3b,
+0x6c, 0x3b, 0x64, 0x69, 0x3b, 0x14b, 0x67, 0x254, 0x6e, 0x3b, 0x73, 0x254, 0x14b, 0x3b, 0x64, 0x69, 0x253, 0x3b, 0x65, 0x6d,
+0x69, 0x3b, 0x65, 0x73, 0x254, 0x3b, 0x6d, 0x61, 0x64, 0x3b, 0x64, 0x69, 0x14b, 0x3b, 0x6e, 0x79, 0x25b, 0x74, 0x3b, 0x6d,
+0x61, 0x79, 0x3b, 0x74, 0x69, 0x6e, 0x3b, 0x65, 0x6c, 0xe1, 0x3b, 0x64, 0x69, 0x6d, 0x254, 0x301, 0x64, 0x69, 0x3b, 0x14b,
+0x67, 0x254, 0x6e, 0x64, 0x25b, 0x3b, 0x73, 0x254, 0x14b, 0x25b, 0x3b, 0x64, 0x69, 0x253, 0xe1, 0x253, 0xe1, 0x3b, 0x65, 0x6d,
+0x69, 0x61, 0x73, 0x65, 0x6c, 0x65, 0x3b, 0x65, 0x73, 0x254, 0x70, 0x25b, 0x73, 0x254, 0x70, 0x25b, 0x3b, 0x6d, 0x61, 0x64,
+0x69, 0x253, 0x25b, 0x301, 0x64, 0xed, 0x253, 0x25b, 0x301, 0x3b, 0x64, 0x69, 0x14b, 0x67, 0x69, 0x6e, 0x64, 0x69, 0x3b, 0x6e,
+0x79, 0x25b, 0x74, 0x25b, 0x6b, 0x69, 0x3b, 0x6d, 0x61, 0x79, 0xe9, 0x73, 0x25b, 0x301, 0x3b, 0x74, 0x69, 0x6e, 0xed, 0x6e,
+0xed, 0x3b, 0x65, 0x6c, 0xe1, 0x14b, 0x67, 0x25b, 0x301, 0x3b, 0x64, 0x3b, 0x14b, 0x3b, 0x73, 0x3b, 0x64, 0x3b, 0x65, 0x3b,
+0x65, 0x3b, 0x6d, 0x3b, 0x64, 0x3b, 0x6e, 0x3b, 0x6d, 0x3b, 0x74, 0x3b, 0x65, 0x3b, 0x53, 0x61, 0x3b, 0x46, 0x65, 0x3b,
+0x4d, 0x61, 0x3b, 0x41, 0x62, 0x3b, 0x4d, 0x65, 0x3b, 0x53, 0x75, 0x3b, 0x53, 0xfa, 0x3b, 0x55, 0x74, 0x3b, 0x53, 0x65,
+0x3b, 0x4f, 0x6b, 0x3b, 0x4e, 0x6f, 0x3b, 0x44, 0x65, 0x3b, 0x53, 0x61, 0x6e, 0x76, 0x69, 0x65, 0x3b, 0x46, 0xe9, 0x62,
+0x69, 0x72, 0x69, 0x65, 0x3b, 0x4d, 0x61, 0x72, 0x73, 0x3b, 0x41, 0x62, 0x75, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x65,
+0x3b, 0x53, 0x75, 0x65, 0x14b, 0x3b, 0x53, 0xfa, 0x75, 0x79, 0x65, 0x65, 0x3b, 0x55, 0x74, 0x3b, 0x53, 0x65, 0x74, 0x74,
+0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62,
+0x61, 0x72, 0x3b, 0x44, 0x69, 0x73, 0x61, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x53, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b,
+0x4d, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x55, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x6e, 0x67, 0x6f, 0x3b,
+0x6e, 0x67, 0x62, 0x3b, 0x6e, 0x67, 0x6c, 0x3b, 0x6e, 0x67, 0x6e, 0x3b, 0x6e, 0x67, 0x74, 0x3b, 0x6e, 0x67, 0x73, 0x3b,
+0x6e, 0x67, 0x7a, 0x3b, 0x6e, 0x67, 0x6d, 0x3b, 0x6e, 0x67, 0x65, 0x3b, 0x6e, 0x67, 0x61, 0x3b, 0x6e, 0x67, 0x61, 0x64,
+0x3b, 0x6e, 0x67, 0x61, 0x62, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x6f, 0x73, 0xfa, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20,
+0x62, 0x25b, 0x30c, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x6c, 0xe1, 0x6c, 0x61, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x6e,
+0x79, 0x69, 0x6e, 0x61, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x74, 0xe1, 0x6e, 0x61, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20,
+0x73, 0x61, 0x6d, 0x259, 0x6e, 0x61, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x7a, 0x61, 0x6d, 0x67, 0x62, 0xe1, 0x6c, 0x61,
+0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x6d, 0x77, 0x6f, 0x6d, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x65, 0x62, 0x75, 0x6c,
+0xfa, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x61, 0x77, 0xf3, 0x6d, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x61, 0x77, 0xf3,
+0x6d, 0x20, 0x61, 0x69, 0x20, 0x64, 0x7a, 0x69, 0xe1, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x61, 0x77, 0xf3, 0x6d, 0x20,
+0x61, 0x69, 0x20, 0x62, 0x25b, 0x30c, 0x3b, 0x6f, 0x3b, 0x62, 0x3b, 0x6c, 0x3b, 0x6e, 0x3b, 0x74, 0x3b, 0x73, 0x3b, 0x7a,
+0x3b, 0x6d, 0x3b, 0x65, 0x3b, 0x61, 0x3b, 0x64, 0x3b, 0x62, 0x3b, 0x14b, 0x31, 0x3b, 0x14b, 0x32, 0x3b, 0x14b, 0x33, 0x3b,
+0x14b, 0x34, 0x3b, 0x14b, 0x35, 0x3b, 0x14b, 0x36, 0x3b, 0x14b, 0x37, 0x3b, 0x14b, 0x38, 0x3b, 0x14b, 0x39, 0x3b, 0x14b, 0x31,
+0x30, 0x3b, 0x14b, 0x31, 0x31, 0x3b, 0x14b, 0x31, 0x32, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x20, 0x6e, 0x74, 0x254,
+0x301, 0x6e, 0x74, 0x254, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x62, 0x25b, 0x301, 0x25b, 0x3b, 0x14b,
+0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x72, 0xe1, 0xe1, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd,
+0x20, 0x6e, 0x69, 0x6e, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x74, 0xe1, 0x61, 0x6e, 0x3b, 0x14b,
+0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x74, 0xe1, 0x61, 0x66, 0x254, 0x6b, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20,
+0x61, 0x6b, 0x1dd, 0x20, 0x74, 0xe1, 0x61, 0x62, 0x25b, 0x25b, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20,
+0x74, 0xe1, 0x61, 0x72, 0x61, 0x61, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x74, 0xe1, 0x61, 0x6e,
+0x69, 0x6e, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x6e, 0x74, 0x25b, 0x6b, 0x3b, 0x14b, 0x77, 0xed,
+0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x6e, 0x74, 0x25b, 0x6b, 0x20, 0x64, 0x69, 0x20, 0x62, 0x254, 0x301, 0x6b, 0x3b, 0x14b,
+0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x6e, 0x74, 0x25b, 0x6b, 0x20, 0x64, 0x69, 0x20, 0x62, 0x25b, 0x301, 0x25b,
+0x3b, 0x4b, 0x77, 0x61, 0x3b, 0x55, 0x6e, 0x61, 0x3b, 0x52, 0x61, 0x72, 0x3b, 0x43, 0x68, 0x65, 0x3b, 0x54, 0x68, 0x61,
+0x3b, 0x4d, 0x6f, 0x63, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x4e, 0x61, 0x6e, 0x3b, 0x54, 0x69, 0x73, 0x3b, 0x4b, 0x75, 0x6d,
+0x3b, 0x4d, 0x6f, 0x6a, 0x3b, 0x59, 0x65, 0x6c, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x6b, 0x77,
+0x61, 0x6e, 0x7a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x75, 0x6e, 0x61, 0x79, 0x65, 0x6c,
+0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x75, 0x6e, 0x65, 0x72, 0x61, 0x72, 0x75, 0x3b, 0x4d,
+0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x75, 0x6e, 0x65, 0x63, 0x68, 0x65, 0x73, 0x68, 0x65, 0x3b, 0x4d, 0x77,
+0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x75, 0x6e, 0x65, 0x74, 0x68, 0x61, 0x6e, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x72,
+0x69, 0x20, 0x77, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x75, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x6f, 0x63, 0x68, 0x61, 0x3b,
+0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x73, 0x61, 0x62, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20,
+0x77, 0x6f, 0x20, 0x6e, 0x61, 0x6e, 0x65, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x74, 0x69, 0x73,
+0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72,
+0x69, 0x20, 0x77, 0x6f, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x6f, 0x6a, 0x61, 0x3b, 0x4d, 0x77,
+0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x79, 0x65, 0x6c, 0x2019, 0x6c,
+0x69, 0x3b, 0x4b, 0x3b, 0x55, 0x3b, 0x52, 0x3b, 0x43, 0x3b, 0x54, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x54, 0x3b,
+0x4b, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x46, 0x4c, 0x4f, 0x3b, 0x43, 0x4c, 0x41, 0x3b, 0x43, 0x4b, 0x49, 0x3b, 0x46, 0x4d,
+0x46, 0x3b, 0x4d, 0x41, 0x44, 0x3b, 0x4d, 0x42, 0x49, 0x3b, 0x4d, 0x4c, 0x49, 0x3b, 0x4d, 0x41, 0x4d, 0x3b, 0x46, 0x44,
+0x45, 0x3b, 0x46, 0x4d, 0x55, 0x3b, 0x46, 0x47, 0x57, 0x3b, 0x46, 0x59, 0x55, 0x3b, 0x46, 0x129, 0x69, 0x20, 0x4c, 0x6f,
+0x6f, 0x3b, 0x43, 0x6f, 0x6b, 0x63, 0x77, 0x61, 0x6b, 0x6c, 0x61, 0x14b, 0x6e, 0x65, 0x3b, 0x43, 0x6f, 0x6b, 0x63, 0x77,
+0x61, 0x6b, 0x6c, 0x69, 0x69, 0x3b, 0x46, 0x129, 0x69, 0x20, 0x4d, 0x61, 0x72, 0x66, 0x6f, 0x6f, 0x3b, 0x4d, 0x61, 0x64,
+0x1dd, 0x1dd, 0x75, 0x75, 0x74, 0x1dd, 0x62, 0x69, 0x6a, 0x61, 0x14b, 0x3b, 0x4d, 0x61, 0x6d, 0x1dd, 0x14b, 0x67, 0x77, 0xe3,
+0x61, 0x66, 0x61, 0x68, 0x62, 0x69, 0x69, 0x3b, 0x4d, 0x61, 0x6d, 0x1dd, 0x14b, 0x67, 0x77, 0xe3, 0x61, 0x6c, 0x69, 0x69,
+0x3b, 0x4d, 0x61, 0x64, 0x1dd, 0x6d, 0x62, 0x69, 0x69, 0x3b, 0x46, 0x129, 0x69, 0x20, 0x44, 0x1dd, 0x253, 0x6c, 0x69, 0x69,
+0x3b, 0x46, 0x129, 0x69, 0x20, 0x4d, 0x75, 0x6e, 0x64, 0x61, 0x14b, 0x3b, 0x46, 0x129, 0x69, 0x20, 0x47, 0x77, 0x61, 0x68,
+0x6c, 0x6c, 0x65, 0x3b, 0x46, 0x129, 0x69, 0x20, 0x59, 0x75, 0x72, 0x75, 0x3b, 0x4f, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x46,
+0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x55, 0x3b, 0x57, 0x3b, 0x59, 0x3b, 0x6e, 0x67, 0x31,
+0x3b, 0x6e, 0x67, 0x32, 0x3b, 0x6e, 0x67, 0x33, 0x3b, 0x6e, 0x67, 0x34, 0x3b, 0x6e, 0x67, 0x35, 0x3b, 0x6e, 0x67, 0x36,
+0x3b, 0x6e, 0x67, 0x37, 0x3b, 0x6e, 0x67, 0x38, 0x3b, 0x6e, 0x67, 0x39, 0x3b, 0x6e, 0x67, 0x31, 0x30, 0x3b, 0x6e, 0x67,
+0x31, 0x31, 0x3b, 0x6b, 0x72, 0x69, 0x73, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x6d, 0x61, 0x74, 0xe1, 0x68, 0x72,
+0x61, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x144, 0x6d, 0x62, 0x61, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x144,
+0x6c, 0x61, 0x6c, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x144, 0x6e, 0x61, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20,
+0x144, 0x74, 0x61, 0x6e, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x144, 0x74, 0x75, 0xf3, 0x3b, 0x6e, 0x67, 0x77, 0x25b,
+0x6e, 0x20, 0x68, 0x25b, 0x6d, 0x62, 0x75, 0x25b, 0x72, 0xed, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x6c, 0x254, 0x6d,
+0x62, 0x69, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x72, 0x25b, 0x62, 0x76, 0x75, 0xe2, 0x3b, 0x6e, 0x67, 0x77, 0x25b,
+0x6e, 0x20, 0x77, 0x75, 0x6d, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x77, 0x75, 0x6d, 0x20, 0x6e, 0x61, 0x76, 0x1d4,
+0x72, 0x3b, 0x6b, 0x72, 0xed, 0x73, 0x69, 0x6d, 0x69, 0x6e, 0x3b, 0x54, 0x69, 0x6f, 0x70, 0x3b, 0x50, 0x25b, 0x74, 0x3b,
+0x44, 0x75, 0x254, 0x331, 0x254, 0x331, 0x3b, 0x47, 0x75, 0x61, 0x6b, 0x3b, 0x44, 0x75, 0xe4, 0x3b, 0x4b, 0x6f, 0x72, 0x3b,
+0x50, 0x61, 0x79, 0x3b, 0x54, 0x68, 0x6f, 0x6f, 0x3b, 0x54, 0x25b, 0x25b, 0x3b, 0x4c, 0x61, 0x61, 0x3b, 0x4b, 0x75, 0x72,
+0x3b, 0x54, 0x69, 0x64, 0x3b, 0x54, 0x69, 0x6f, 0x70, 0x20, 0x74, 0x68, 0x61, 0x72, 0x20, 0x70, 0x25b, 0x74, 0x3b, 0x50,
+0x25b, 0x74, 0x3b, 0x44, 0x75, 0x254, 0x331, 0x254, 0x331, 0x14b, 0x3b, 0x47, 0x75, 0x61, 0x6b, 0x3b, 0x44, 0x75, 0xe4, 0x74,
+0x3b, 0x4b, 0x6f, 0x72, 0x6e, 0x79, 0x6f, 0x6f, 0x74, 0x3b, 0x50, 0x61, 0x79, 0x20, 0x79, 0x69, 0x65, 0x331, 0x74, 0x6e,
+0x69, 0x3b, 0x54, 0x68, 0x6f, 0x331, 0x6f, 0x331, 0x72, 0x3b, 0x54, 0x25b, 0x25b, 0x72, 0x3b, 0x4c, 0x61, 0x61, 0x74, 0x68,
+0x3b, 0x4b, 0x75, 0x72, 0x3b, 0x54, 0x69, 0x6f, 0x331, 0x70, 0x20, 0x69, 0x6e, 0x20, 0x64, 0x69, 0x331, 0x69, 0x331, 0x74,
+0x3b, 0x54, 0x3b, 0x50, 0x3b, 0x44, 0x3b, 0x47, 0x3b, 0x44, 0x3b, 0x4b, 0x3b, 0x50, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4c,
+0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x422, 0x43e, 0x445, 0x441, 0x3b, 0x41e, 0x43b, 0x443, 0x43d, 0x3b, 0x41a, 0x43b, 0x43d, 0x3b, 0x41c,
+0x441, 0x443, 0x3b, 0x42b, 0x430, 0x43c, 0x3b, 0x411, 0x44d, 0x441, 0x3b, 0x41e, 0x442, 0x439, 0x3b, 0x410, 0x442, 0x440, 0x3b, 0x411,
+0x43b, 0x495, 0x3b, 0x410, 0x43b, 0x442, 0x3b, 0x421, 0x44d, 0x442, 0x3b, 0x410, 0x445, 0x441, 0x3b, 0x442, 0x43e, 0x445, 0x441, 0x443,
+0x43d, 0x43d, 0x44c, 0x443, 0x3b, 0x43e, 0x43b, 0x443, 0x43d, 0x43d, 0x44c, 0x443, 0x3b, 0x43a, 0x443, 0x43b, 0x443, 0x43d, 0x20, 0x442,
+0x443, 0x442, 0x430, 0x440, 0x3b, 0x43c, 0x443, 0x443, 0x441, 0x20, 0x443, 0x441, 0x442, 0x430, 0x440, 0x3b, 0x44b, 0x430, 0x43c, 0x20,
+0x44b, 0x439, 0x430, 0x3b, 0x431, 0x44d, 0x441, 0x20, 0x44b, 0x439, 0x430, 0x3b, 0x43e, 0x442, 0x20, 0x44b, 0x439, 0x430, 0x3b, 0x430,
+0x442, 0x44b, 0x440, 0x434, 0x44c, 0x44b, 0x445, 0x20, 0x44b, 0x439, 0x430, 0x3b, 0x431, 0x430, 0x43b, 0x430, 0x495, 0x430, 0x43d, 0x20,
+0x44b, 0x439, 0x430, 0x3b, 0x430, 0x43b, 0x442, 0x44b, 0x43d, 0x43d, 0x44c, 0x44b, 0x3b, 0x441, 0x44d, 0x442, 0x438, 0x43d, 0x43d, 0x44c,
+0x438, 0x3b, 0x430, 0x445, 0x441, 0x44b, 0x43d, 0x43d, 0x44c, 0x44b, 0x3b, 0x422, 0x3b, 0x41e, 0x3b, 0x41a, 0x3b, 0x41c, 0x3b, 0x42b,
+0x3b, 0x411, 0x3b, 0x41e, 0x3b, 0x410, 0x3b, 0x411, 0x3b, 0x410, 0x3b, 0x421, 0x3b, 0x410, 0x3b, 0x422, 0x43e, 0x445, 0x441, 0x443,
+0x43d, 0x43d, 0x44c, 0x443, 0x3b, 0x41e, 0x43b, 0x443, 0x43d, 0x43d, 0x44c, 0x443, 0x3b, 0x41a, 0x443, 0x43b, 0x443, 0x43d, 0x20, 0x442,
+0x443, 0x442, 0x430, 0x440, 0x3b, 0x41c, 0x443, 0x443, 0x441, 0x20, 0x443, 0x441, 0x442, 0x430, 0x440, 0x3b, 0x42b, 0x430, 0x43c, 0x20,
+0x44b, 0x439, 0x44b, 0x43d, 0x3b, 0x411, 0x44d, 0x441, 0x20, 0x44b, 0x439, 0x44b, 0x43d, 0x3b, 0x41e, 0x442, 0x20, 0x44b, 0x439, 0x44b,
+0x43d, 0x3b, 0x410, 0x442, 0x44b, 0x440, 0x434, 0x44c, 0x44b, 0x445, 0x20, 0x44b, 0x439, 0x44b, 0x43d, 0x3b, 0x411, 0x430, 0x43b, 0x430,
+0x495, 0x430, 0x43d, 0x20, 0x44b, 0x439, 0x44b, 0x43d, 0x3b, 0x410, 0x43b, 0x442, 0x44b, 0x43d, 0x43d, 0x44c, 0x44b, 0x3b, 0x421, 0x44d,
+0x442, 0x438, 0x43d, 0x43d, 0x44c, 0x438, 0x3b, 0x430, 0x445, 0x441, 0x44b, 0x43d, 0x43d, 0x44c, 0x44b, 0x3b, 0x4d, 0x75, 0x70, 0x3b,
+0x4d, 0x77, 0x69, 0x3b, 0x4d, 0x73, 0x68, 0x3b, 0x4d, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x67, 0x3b, 0x4d, 0x75, 0x6a, 0x3b,
+0x4d, 0x73, 0x70, 0x3b, 0x4d, 0x70, 0x67, 0x3b, 0x4d, 0x79, 0x65, 0x3b, 0x4d, 0x6f, 0x6b, 0x3b, 0x4d, 0x75, 0x73, 0x3b,
+0x4d, 0x75, 0x68, 0x3b, 0x4d, 0x75, 0x70, 0x61, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x77, 0x61, 0x3b, 0x4d, 0x77, 0x69,
+0x74, 0x6f, 0x70, 0x65, 0x3b, 0x4d, 0x75, 0x73, 0x68, 0x65, 0x6e, 0x64, 0x65, 0x3b, 0x4d, 0x75, 0x6e, 0x79, 0x69, 0x3b,
+0x4d, 0x75, 0x73, 0x68, 0x65, 0x6e, 0x64, 0x65, 0x20, 0x4d, 0x61, 0x67, 0x61, 0x6c, 0x69, 0x3b, 0x4d, 0x75, 0x6a, 0x69,
+0x6d, 0x62, 0x69, 0x3b, 0x4d, 0x75, 0x73, 0x68, 0x69, 0x70, 0x65, 0x70, 0x6f, 0x3b, 0x4d, 0x75, 0x70, 0x75, 0x67, 0x75,
+0x74, 0x6f, 0x3b, 0x4d, 0x75, 0x6e, 0x79, 0x65, 0x6e, 0x73, 0x65, 0x3b, 0x4d, 0x6f, 0x6b, 0x68, 0x75, 0x3b, 0x4d, 0x75,
+0x73, 0x6f, 0x6e, 0x67, 0x61, 0x6e, 0x64, 0x65, 0x6d, 0x62, 0x77, 0x65, 0x3b, 0x4d, 0x75, 0x68, 0x61, 0x61, 0x6e, 0x6f,
+0x3b, 0xa5a8, 0xa595, 0xa51e, 0x3b, 0xa552, 0xa561, 0x3b, 0xa57e, 0xa5ba, 0x3b, 0xa5a2, 0xa595, 0x3b, 0xa591, 0xa571, 0x3b, 0xa5b1, 0xa60b, 0x3b,
+0xa5b1, 0xa55e, 0x3b, 0xa5db, 0xa515, 0x3b, 0xa562, 0xa54c, 0x3b, 0xa56d, 0xa583, 0x3b, 0xa51e, 0xa60b, 0x3b, 0xa5a8, 0xa595, 0xa5cf, 0x3b, 0xa5a8,
+0xa595, 0x20, 0xa56a, 0xa574, 0x20, 0xa51e, 0xa500, 0xa56e, 0xa54a, 0x3b, 0xa552, 0xa561, 0xa59d, 0xa595, 0x3b, 0xa57e, 0xa5ba, 0x3b, 0xa5a2, 0xa595,
+0x3b, 0xa591, 0xa571, 0x3b, 0xa5b1, 0xa60b, 0x3b, 0xa5b1, 0xa55e, 0xa524, 0x3b, 0xa5db, 0xa515, 0x3b, 0xa562, 0xa54c, 0x3b, 0xa56d, 0xa583, 0x3b,
+0xa51e, 0xa60b, 0xa554, 0xa57f, 0x20, 0xa578, 0xa583, 0xa5cf, 0x3b, 0xa5a8, 0xa595, 0x20, 0xa56a, 0xa574, 0x20, 0xa5cf, 0xa5ba, 0xa56e, 0xa54a, 0x3b,
+0x6c, 0x75, 0x75, 0x6b, 0x61, 0x6f, 0x20, 0x6b, 0x65, 0x6d, 0xe3, 0x3b, 0x253, 0x61, 0x6e, 0x64, 0x61, 0x253, 0x75, 0x3b,
+0x76, 0x254, 0x254, 0x3b, 0x66, 0x75, 0x6c, 0x75, 0x3b, 0x67, 0x6f, 0x6f, 0x3b, 0x36, 0x3b, 0x37, 0x3b, 0x6b, 0x254, 0x6e,
+0x64, 0x65, 0x3b, 0x73, 0x61, 0x61, 0x68, 0x3b, 0x67, 0x61, 0x6c, 0x6f, 0x3b, 0x6b, 0x65, 0x6e, 0x70, 0x6b, 0x61, 0x74,
+0x6f, 0x20, 0x253, 0x6f, 0x6c, 0x6f, 0x6c, 0x254, 0x3b, 0x6c, 0x75, 0x75, 0x6b, 0x61, 0x6f, 0x20, 0x6c, 0x254, 0x6d, 0x61,
+0x3b, 0x4a, 0x65, 0x6e, 0x3b, 0x48, 0x6f, 0x72, 0x3b, 0x4d, 0xe4, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x65, 0x69,
+0x3b, 0x42, 0x72, 0xe1, 0x3b, 0x48, 0x65, 0x69, 0x3b, 0xd6, 0x69, 0x67, 0x3b, 0x48, 0x65, 0x72, 0x3b, 0x57, 0xed, 0x6d,
+0x3b, 0x57, 0x69, 0x6e, 0x3b, 0x43, 0x68, 0x72, 0x3b, 0x4a, 0x65, 0x6e, 0x6e, 0x65, 0x72, 0x3b, 0x48, 0x6f, 0x72, 0x6e,
+0x69, 0x67, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x65, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x6c, 0x65, 0x3b, 0x4d, 0x65, 0x69,
+0x6a, 0x65, 0x3b, 0x42, 0x72, 0xe1, 0x10d, 0x65, 0x74, 0x3b, 0x48, 0x65, 0x69, 0x77, 0x65, 0x74, 0x3b, 0xd6, 0x69, 0x67,
+0x161, 0x74, 0x65, 0x3b, 0x48, 0x65, 0x72, 0x62, 0x161, 0x74, 0x6d, 0xe1, 0x6e, 0x65, 0x74, 0x3b, 0x57, 0xed, 0x6d, 0xe1,
+0x6e, 0x65, 0x74, 0x3b, 0x57, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0xe1, 0x6e, 0x65, 0x74, 0x3b, 0x43, 0x68, 0x72, 0x69,
+0x161, 0x74, 0x6d, 0xe1, 0x6e, 0x65, 0x74, 0x3b, 0x4a, 0x3b, 0x48, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x42, 0x3b,
+0x48, 0x3b, 0xd6, 0x3b, 0x48, 0x3b, 0x57, 0x3b, 0x57, 0x3b, 0x43, 0x3b, 0x6f, 0x2e, 0x31, 0x3b, 0x6f, 0x2e, 0x32, 0x3b,
+0x6f, 0x2e, 0x33, 0x3b, 0x6f, 0x2e, 0x34, 0x3b, 0x6f, 0x2e, 0x35, 0x3b, 0x6f, 0x2e, 0x36, 0x3b, 0x6f, 0x2e, 0x37, 0x3b,
+0x6f, 0x2e, 0x38, 0x3b, 0x6f, 0x2e, 0x39, 0x3b, 0x6f, 0x2e, 0x31, 0x30, 0x3b, 0x6f, 0x2e, 0x31, 0x31, 0x3b, 0x6f, 0x2e,
+0x31, 0x32, 0x3b, 0x70, 0x69, 0x6b, 0xed, 0x74, 0xed, 0x6b, 0xed, 0x74, 0x69, 0x65, 0x2c, 0x20, 0x6f, 0xf3, 0x6c, 0xed,
+0x20, 0xfa, 0x20, 0x6b, 0x75, 0x74, 0xfa, 0x61, 0x6e, 0x3b, 0x73, 0x69, 0x25b, 0x79, 0x25b, 0x301, 0x2c, 0x20, 0x6f, 0xf3,
+0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe1, 0x6e, 0x64, 0xed, 0x25b, 0x3b, 0x254, 0x6e, 0x73, 0xfa, 0x6d, 0x62, 0x254, 0x6c,
+0x2c, 0x20, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe1, 0x74, 0xe1, 0x74, 0xfa, 0x25b, 0x3b, 0x6d, 0x65, 0x73,
+0x69, 0x14b, 0x2c, 0x20, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe9, 0x6e, 0x69, 0x65, 0x3b, 0x65, 0x6e, 0x73,
+0x69, 0x6c, 0x2c, 0x20, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe1, 0x74, 0xe1, 0x6e, 0x75, 0x25b, 0x3b, 0x254,
+0x73, 0x254, 0x6e, 0x3b, 0x65, 0x66, 0x75, 0x74, 0x65, 0x3b, 0x70, 0x69, 0x73, 0x75, 0x79, 0xfa, 0x3b, 0x69, 0x6d, 0x25b,
+0x14b, 0x20, 0x69, 0x20, 0x70, 0x75, 0x254, 0x73, 0x3b, 0x69, 0x6d, 0x25b, 0x14b, 0x20, 0x69, 0x20, 0x70, 0x75, 0x74, 0xfa,
+0x6b, 0x2c, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe1, 0x74, 0xed, 0x25b, 0x3b, 0x6d, 0x61, 0x6b, 0x61, 0x6e,
+0x64, 0x69, 0x6b, 0x25b, 0x3b, 0x70, 0x69, 0x6c, 0x254, 0x6e, 0x64, 0x254, 0x301, 0x3b, 0x58, 0x69, 0x6e, 0x3b, 0x46, 0x65,
+0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x58, 0x75, 0x6e, 0x3b, 0x58, 0x6e,
+0x74, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x63, 0x68, 0x3b, 0x50, 0x61, 0x79, 0x3b, 0x41, 0x76,
+0x69, 0x3b, 0x78, 0x69, 0x6e, 0x65, 0x72, 0x75, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x75, 0x3b, 0x6d, 0x61, 0x72,
+0x7a, 0x75, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x79, 0x75, 0x3b, 0x78, 0x75, 0x6e, 0x75, 0x3b, 0x78,
+0x75, 0x6e, 0x65, 0x74, 0x75, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x75, 0x3b, 0x73, 0x65, 0x74, 0x69, 0x65, 0x6d, 0x62,
+0x72, 0x65, 0x3b, 0x6f, 0x63, 0x68, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x70, 0x61, 0x79, 0x61, 0x72, 0x65, 0x73, 0x3b, 0x61,
+0x76, 0x69, 0x65, 0x6e, 0x74, 0x75, 0x3b, 0x58, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x58, 0x3b, 0x58,
+0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x50, 0x3b, 0x41, 0x3b, 0x78, 0x69, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d,
+0x61, 0x72, 0x3b, 0x61, 0x62, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x78, 0x75, 0x6e, 0x3b, 0x78, 0x6e, 0x74, 0x3b, 0x61,
+0x67, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x3b, 0x6f, 0x63, 0x68, 0x3b, 0x70, 0x61, 0x79, 0x3b, 0x61, 0x76, 0x69, 0x3b, 0x64,
+0x65, 0x20, 0x78, 0x69, 0x6e, 0x65, 0x72, 0x75, 0x3b, 0x64, 0x65, 0x20, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x75, 0x3b,
+0x64, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x7a, 0x75, 0x3b, 0x64, 0x2019, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x64, 0x65, 0x20,
+0x6d, 0x61, 0x79, 0x75, 0x3b, 0x64, 0x65, 0x20, 0x78, 0x75, 0x6e, 0x75, 0x3b, 0x64, 0x65, 0x20, 0x78, 0x75, 0x6e, 0x65,
+0x74, 0x75, 0x3b, 0x64, 0x2019, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x75, 0x3b, 0x64, 0x65, 0x20, 0x73, 0x65, 0x74, 0x69, 0x65,
+0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x2019, 0x6f, 0x63, 0x68, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x65, 0x20, 0x70, 0x61,
+0x79, 0x61, 0x72, 0x65, 0x73, 0x3b, 0x64, 0x2019, 0x61, 0x76, 0x69, 0x65, 0x6e, 0x74, 0x75, 0x3b, 0x4e, 0x64, 0x75, 0x14b,
+0x6d, 0x62, 0x69, 0x20, 0x53, 0x61, 0x14b, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301, 0x70, 0xe1, 0x3b,
+0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301, 0x74, 0xe1, 0x74, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50,
+0x25b, 0x301, 0x6e, 0x25b, 0x301, 0x6b, 0x77, 0x61, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x61, 0x74, 0x61, 0x61,
+0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301, 0x6e, 0x25b, 0x301, 0x6e, 0x74, 0xfa, 0x6b, 0xfa, 0x3b, 0x50,
+0x25b, 0x73, 0x61, 0x14b, 0x20, 0x53, 0x61, 0x61, 0x6d, 0x62, 0xe1, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b,
+0x301, 0x6e, 0x25b, 0x301, 0x66, 0x254, 0x6d, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301, 0x6e, 0x25b, 0x301,
+0x70, 0x66, 0xfa, 0xa78b, 0xfa, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x4e, 0x25b, 0x67, 0x25b, 0x301, 0x6d, 0x3b, 0x50,
+0x25b, 0x73, 0x61, 0x14b, 0x20, 0x4e, 0x74, 0x73, 0x254, 0x30c, 0x70, 0x6d, 0x254, 0x301, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b,
+0x20, 0x4e, 0x74, 0x73, 0x254, 0x30c, 0x70, 0x70, 0xe1, 0x3b, 0x70, 0x61, 0x6d, 0x62, 0x61, 0x3b, 0x77, 0x61, 0x6e, 0x6a,
+0x61, 0x3b, 0x6d, 0x62, 0x69, 0x79, 0x254, 0x20, 0x6d, 0x25b, 0x6e, 0x64, 0x6f, 0x14b, 0x67, 0x254, 0x3b, 0x4e, 0x79, 0x254,
+0x6c, 0x254, 0x6d, 0x62, 0x254, 0x14b, 0x67, 0x254, 0x3b, 0x4d, 0x254, 0x6e, 0x254, 0x20, 0x14b, 0x67, 0x62, 0x61, 0x6e, 0x6a,
+0x61, 0x3b, 0x4e, 0x79, 0x61, 0x14b, 0x67, 0x77, 0x25b, 0x20, 0x14b, 0x67, 0x62, 0x61, 0x6e, 0x6a, 0x61, 0x3b, 0x6b, 0x75,
+0x14b, 0x67, 0x77, 0x25b, 0x3b, 0x66, 0x25b, 0x3b, 0x6e, 0x6a, 0x61, 0x70, 0x69, 0x3b, 0x6e, 0x79, 0x75, 0x6b, 0x75, 0x6c,
+0x3b, 0x31, 0x31, 0x3b, 0x253, 0x75, 0x6c, 0x253, 0x75, 0x73, 0x25b, 0x3b, 0x6d, 0x62, 0x65, 0x67, 0x74, 0x75, 0x67, 0x3b,
+0x69, 0x6d, 0x65, 0x67, 0x20, 0xe0, 0x62, 0xf9, 0x62, 0xec, 0x3b, 0x69, 0x6d, 0x65, 0x67, 0x20, 0x6d, 0x62, 0x259, 0x14b,
+0x63, 0x68, 0x75, 0x62, 0x69, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6e, 0x67, 0x77, 0x259, 0x300, 0x74, 0x3b, 0x69, 0x6d,
+0x259, 0x67, 0x20, 0x66, 0x6f, 0x67, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x69, 0x63, 0x68, 0x69, 0x69, 0x62, 0x254, 0x64,
+0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0xe0, 0x64, 0xf9, 0x6d, 0x62, 0x259, 0x300, 0x14b, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20,
+0x69, 0x63, 0x68, 0x69, 0x6b, 0x61, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6b, 0x75, 0x64, 0x3b, 0x69, 0x6d, 0x259, 0x67,
+0x20, 0x74, 0xe8, 0x73, 0x69, 0x2bc, 0x65, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x7a, 0xf2, 0x3b, 0x69, 0x6d, 0x259, 0x67,
+0x20, 0x6b, 0x72, 0x69, 0x7a, 0x6d, 0x65, 0x64, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6d, 0x62, 0x65, 0x67, 0x74, 0x75,
0x67, 0x3b, 0x69, 0x6d, 0x65, 0x67, 0x20, 0xe0, 0x62, 0xf9, 0x62, 0xec, 0x3b, 0x69, 0x6d, 0x65, 0x67, 0x20, 0x6d, 0x62,
0x259, 0x14b, 0x63, 0x68, 0x75, 0x62, 0x69, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6e, 0x67, 0x77, 0x259, 0x300, 0x74, 0x3b,
0x69, 0x6d, 0x259, 0x67, 0x20, 0x66, 0x6f, 0x67, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x69, 0x63, 0x68, 0x69, 0x69, 0x62,
0x254, 0x64, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0xe0, 0x64, 0xf9, 0x6d, 0x62, 0x259, 0x300, 0x14b, 0x3b, 0x69, 0x6d, 0x259,
0x67, 0x20, 0x69, 0x63, 0x68, 0x69, 0x6b, 0x61, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6b, 0x75, 0x64, 0x3b, 0x69, 0x6d,
0x259, 0x67, 0x20, 0x74, 0xe8, 0x73, 0x69, 0x2bc, 0x65, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x7a, 0xf2, 0x3b, 0x69, 0x6d,
-0x259, 0x67, 0x20, 0x6b, 0x72, 0x69, 0x7a, 0x6d, 0x65, 0x64, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6d, 0x62, 0x65, 0x67,
-0x74, 0x75, 0x67, 0x3b, 0x69, 0x6d, 0x65, 0x67, 0x20, 0xe0, 0x62, 0xf9, 0x62, 0xec, 0x3b, 0x69, 0x6d, 0x65, 0x67, 0x20,
-0x6d, 0x62, 0x259, 0x14b, 0x63, 0x68, 0x75, 0x62, 0x69, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6e, 0x67, 0x77, 0x259, 0x300,
-0x74, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x66, 0x6f, 0x67, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x69, 0x63, 0x68, 0x69,
-0x69, 0x62, 0x254, 0x64, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0xe0, 0x64, 0xf9, 0x6d, 0x62, 0x259, 0x300, 0x14b, 0x3b, 0x69,
-0x6d, 0x259, 0x67, 0x20, 0x69, 0x63, 0x68, 0x69, 0x6b, 0x61, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6b, 0x75, 0x64, 0x3b,
-0x69, 0x6d, 0x259, 0x67, 0x20, 0x74, 0xe8, 0x73, 0x69, 0x2bc, 0x65, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x7a, 0xf2, 0x3b,
-0x69, 0x6d, 0x259, 0x67, 0x20, 0x6b, 0x72, 0x69, 0x7a, 0x6d, 0x65, 0x64, 0x3b, 0x4d, 0x31, 0x3b, 0x41, 0x32, 0x3b, 0x4d,
-0x33, 0x3b, 0x4e, 0x34, 0x3b, 0x46, 0x35, 0x3b, 0x49, 0x36, 0x3b, 0x41, 0x37, 0x3b, 0x49, 0x38, 0x3b, 0x4b, 0x39, 0x3b,
-0x31, 0x30, 0x3b, 0x31, 0x31, 0x3b, 0x31, 0x32, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x74, 0x73, 0x65, 0x74, 0x73, 0x25b, 0x300,
-0x25b, 0x20, 0x6c, 0xf9, 0x6d, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6b, 0xe0, 0x67, 0x20, 0x6e, 0x67, 0x77, 0xf3, 0x14b, 0x3b,
-0x73, 0x61, 0x14b, 0x20, 0x6c, 0x65, 0x70, 0x79, 0xe8, 0x20, 0x73, 0x68, 0xfa, 0x6d, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x63,
-0xff, 0xf3, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x74, 0x73, 0x25b, 0x300, 0x25b, 0x20, 0x63, 0xff, 0xf3, 0x3b, 0x73, 0x61, 0x14b,
-0x20, 0x6e, 0x6a, 0xff, 0x6f, 0x6c, 0xe1, 0x2bc, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x74, 0x79, 0x25b, 0x300, 0x62, 0x20, 0x74,
-0x79, 0x25b, 0x300, 0x62, 0x20, 0x6d, 0x62, 0x289, 0x300, 0x14b, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6d, 0x62, 0x289, 0x300, 0x14b,
-0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6e, 0x67, 0x77, 0x254, 0x300, 0x2bc, 0x20, 0x6d, 0x62, 0xff, 0x25b, 0x3b, 0x73, 0x61, 0x14b,
-0x20, 0x74, 0xe0, 0x14b, 0x61, 0x20, 0x74, 0x73, 0x65, 0x74, 0x73, 0xe1, 0x2bc, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6d, 0x65,
-0x6a, 0x77, 0x6f, 0x14b, 0xf3, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6c, 0xf9, 0x6d, 0x3b, 0x57, 0x69, 0xf3, 0x74, 0x68, 0x65,
-0x21f, 0x69, 0x6b, 0x61, 0x20, 0x57, 0xed, 0x3b, 0x54, 0x68, 0x69, 0x79, 0xf3, 0x21f, 0x65, 0x79, 0x75, 0x14b, 0x6b, 0x61,
-0x20, 0x57, 0xed, 0x3b, 0x49, 0x161, 0x74, 0xe1, 0x77, 0x69, 0x10d, 0x68, 0x61, 0x79, 0x61, 0x7a, 0x61, 0x14b, 0x20, 0x57,
-0xed, 0x3b, 0x50, 0x21f, 0x65, 0x17e, 0xed, 0x74, 0x21f, 0x6f, 0x20, 0x57, 0xed, 0x3b, 0x10c, 0x68, 0x61, 0x14b, 0x77, 0xe1,
-0x70, 0x65, 0x74, 0x21f, 0x6f, 0x20, 0x57, 0xed, 0x3b, 0x57, 0xed, 0x70, 0x61, 0x7a, 0x75, 0x6b, 0x21f, 0x61, 0x2d, 0x77,
-0x61, 0x161, 0x74, 0xe9, 0x20, 0x57, 0xed, 0x3b, 0x10c, 0x68, 0x61, 0x14b, 0x70, 0x21f, 0xe1, 0x73, 0x61, 0x70, 0x61, 0x20,
-0x57, 0xed, 0x3b, 0x57, 0x61, 0x73, 0xfa, 0x74, 0x21f, 0x75, 0x14b, 0x20, 0x57, 0xed, 0x3b, 0x10c, 0x68, 0x61, 0x14b, 0x77,
-0xe1, 0x70, 0x65, 0x1e7, 0x69, 0x20, 0x57, 0xed, 0x3b, 0x10c, 0x68, 0x61, 0x14b, 0x77, 0xe1, 0x70, 0x65, 0x2d, 0x6b, 0x61,
-0x73, 0x6e, 0xe1, 0x20, 0x57, 0xed, 0x3b, 0x57, 0x61, 0x6e, 0xed, 0x79, 0x65, 0x74, 0x75, 0x20, 0x57, 0xed, 0x3b, 0x54,
-0x21f, 0x61, 0x68, 0xe9, 0x6b, 0x61, 0x70, 0x161, 0x75, 0x14b, 0x20, 0x57, 0xed, 0x3b, 0x6a9, 0x627, 0x646, 0x648, 0x648, 0x646,
-0x6cc, 0x20, 0x62f, 0x648, 0x648, 0x6d5, 0x645, 0x3b, 0x634, 0x648, 0x628, 0x627, 0x62a, 0x3b, 0x626, 0x627, 0x632, 0x627, 0x631, 0x3b,
-0x646, 0x6cc, 0x633, 0x627, 0x646, 0x3b, 0x626, 0x627, 0x6cc, 0x627, 0x631, 0x3b, 0x62d, 0x648, 0x632, 0x6d5, 0x6cc, 0x631, 0x627, 0x646,
-0x3b, 0x62a, 0x6d5, 0x645, 0x648, 0x648, 0x632, 0x3b, 0x626, 0x627, 0x628, 0x3b, 0x626, 0x6d5, 0x6cc, 0x644, 0x648, 0x648, 0x644, 0x3b,
-0x62a, 0x634, 0x631, 0x6cc, 0x646, 0x6cc, 0x20, 0x6cc, 0x6d5, 0x6a9, 0x6d5, 0x645, 0x3b, 0x62a, 0x634, 0x631, 0x6cc, 0x646, 0x6cc, 0x20,
-0x62f, 0x648, 0x648, 0x6d5, 0x645, 0x3b, 0x6a9, 0x627, 0x646, 0x648, 0x646, 0x6cc, 0x20, 0x6cc, 0x6d5, 0x6a9, 0x6d5, 0x645, 0x3b, 0x6a9,
-0x3b, 0x634, 0x3b, 0x626, 0x3b, 0x646, 0x3b, 0x626, 0x3b, 0x62d, 0x3b, 0x62a, 0x3b, 0x626, 0x3b, 0x626, 0x3b, 0x62a, 0x3b, 0x62a,
-0x3b, 0x6a9, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x11b, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d,
-0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x77, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f,
-0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x77, 0x3b, 0x64, 0x65, 0x63, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65,
-0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x11b, 0x72, 0x63, 0x3b, 0x61, 0x70, 0x72, 0x79, 0x6c, 0x3b, 0x6d, 0x61, 0x6a,
-0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6a, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6a, 0x3b, 0x61, 0x77, 0x67, 0x75, 0x73, 0x74, 0x3b,
-0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f,
-0x77, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6a, 0x61, 0x6e, 0x2e,
-0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x11b, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x6a, 0x2e,
-0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x77, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e,
-0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x77, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x75,
-0x61, 0x72, 0x61, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x61, 0x3b, 0x6d, 0x11b, 0x72, 0x63, 0x61, 0x3b, 0x61,
-0x70, 0x72, 0x79, 0x6c, 0x61, 0x3b, 0x6d, 0x61, 0x6a, 0x61, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6a, 0x61, 0x3b, 0x6a, 0x75,
-0x6c, 0x69, 0x6a, 0x61, 0x3b, 0x61, 0x77, 0x67, 0x75, 0x73, 0x74, 0x61, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62,
-0x72, 0x61, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x72, 0x61, 0x3b, 0x6e, 0x6f, 0x77, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b,
-0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x11b, 0x72,
-0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x65, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x77, 0x67,
-0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x77, 0x3b, 0x64, 0x65, 0x63, 0x3b, 0x6a, 0x61, 0x6e,
-0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x11b, 0x72, 0x63, 0x3b, 0x61, 0x70, 0x72,
-0x79, 0x6c, 0x3b, 0x6d, 0x65, 0x6a, 0x61, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6a, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6a, 0x3b,
-0x61, 0x77, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74,
-0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x77, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62,
-0x65, 0x72, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x11b, 0x72, 0x2e, 0x3b, 0x61, 0x70,
-0x72, 0x2e, 0x3b, 0x6d, 0x65, 0x6a, 0x2e, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x77,
-0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x77, 0x2e, 0x3b, 0x64, 0x65,
-0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x61, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x61, 0x3b,
-0x6d, 0x11b, 0x72, 0x63, 0x61, 0x3b, 0x61, 0x70, 0x72, 0x79, 0x6c, 0x61, 0x3b, 0x6d, 0x65, 0x6a, 0x65, 0x3b, 0x6a, 0x75,
-0x6e, 0x69, 0x6a, 0x61, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6a, 0x61, 0x3b, 0x61, 0x77, 0x67, 0x75, 0x73, 0x74, 0x61, 0x3b,
-0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x72, 0x61, 0x3b, 0x6e, 0x6f,
-0x77, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x75, 0x111, 0x69, 0x76,
-0x3b, 0x6b, 0x75, 0x6f, 0x76, 0xe2, 0x3b, 0x6e, 0x6a, 0x75, 0x68, 0x10d, 0xe2, 0x3b, 0x63, 0x75, 0xe1, 0x14b, 0x75, 0x69,
-0x3b, 0x76, 0x79, 0x65, 0x73, 0x69, 0x3b, 0x6b, 0x65, 0x73, 0x69, 0x3b, 0x73, 0x79, 0x65, 0x69, 0x6e, 0x69, 0x3b, 0x70,
-0x6f, 0x72, 0x67, 0x65, 0x3b, 0x10d, 0x6f, 0x68, 0x10d, 0xe2, 0x3b, 0x72, 0x6f, 0x6f, 0x76, 0x76, 0xe2, 0x64, 0x3b, 0x73,
-0x6b, 0x61, 0x6d, 0x6d, 0xe2, 0x3b, 0x6a, 0x75, 0x6f, 0x76, 0x6c, 0xe2, 0x3b, 0x75, 0x111, 0x111, 0xe2, 0x69, 0x76, 0x65,
-0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x6b, 0x75, 0x6f, 0x76, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x6e, 0x6a, 0x75,
-0x68, 0x10d, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x63, 0x75, 0xe1, 0x14b, 0x75, 0x69, 0x6d, 0xe1, 0xe1, 0x6e, 0x75,
-0x3b, 0x76, 0x79, 0x65, 0x73, 0x69, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x6b, 0x65, 0x73, 0x69, 0x6d, 0xe1, 0xe1, 0x6e,
-0x75, 0x3b, 0x73, 0x79, 0x65, 0x69, 0x6e, 0x69, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x70, 0x6f, 0x72, 0x67, 0x65, 0x6d,
-0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x10d, 0x6f, 0x68, 0x10d, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x72, 0x6f, 0x6f, 0x76,
-0x76, 0xe2, 0x64, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x73, 0x6b, 0x61, 0x6d, 0x6d, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e, 0x75,
-0x3b, 0x6a, 0x75, 0x6f, 0x76, 0x6c, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x55, 0x3b, 0x4b, 0x3b, 0x4e, 0x4a, 0x3b,
-0x43, 0x3b, 0x56, 0x3b, 0x4b, 0x3b, 0x53, 0x3b, 0x50, 0x3b, 0x10c, 0x3b, 0x52, 0x3b, 0x53, 0x3b, 0x4a, 0x3b, 0x62c, 0x627,
-0x646, 0x6a4, 0x6cc, 0x6d5, 0x3b, 0x641, 0x626, 0x6a4, 0x631, 0x6cc, 0x6d5, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x622, 0x6a4, 0x631,
-0x6cc, 0x644, 0x3b, 0x645, 0x626, 0x6cc, 0x3b, 0x62c, 0x648, 0x659, 0x623, 0x646, 0x3b, 0x62c, 0x648, 0x659, 0x644, 0x627, 0x3b, 0x622,
-0x6af, 0x648, 0x633, 0x62a, 0x3b, 0x633, 0x626, 0x67e, 0x62a, 0x627, 0x645, 0x631, 0x3b, 0x626, 0x648, 0x6a9, 0x62a, 0x648, 0x6a4, 0x631,
-0x3b, 0x646, 0x648, 0x6a4, 0x627, 0x645, 0x631, 0x3b, 0x62f, 0x626, 0x633, 0x627, 0x645, 0x631, 0x3b
+0x259, 0x67, 0x20, 0x6b, 0x72, 0x69, 0x7a, 0x6d, 0x65, 0x64, 0x3b, 0x4d, 0x31, 0x3b, 0x41, 0x32, 0x3b, 0x4d, 0x33, 0x3b,
+0x4e, 0x34, 0x3b, 0x46, 0x35, 0x3b, 0x49, 0x36, 0x3b, 0x41, 0x37, 0x3b, 0x49, 0x38, 0x3b, 0x4b, 0x39, 0x3b, 0x31, 0x30,
+0x3b, 0x31, 0x31, 0x3b, 0x31, 0x32, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x74, 0x73, 0x65, 0x74, 0x73, 0x25b, 0x300, 0x25b, 0x20,
+0x6c, 0xf9, 0x6d, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6b, 0xe0, 0x67, 0x20, 0x6e, 0x67, 0x77, 0xf3, 0x14b, 0x3b, 0x73, 0x61,
+0x14b, 0x20, 0x6c, 0x65, 0x70, 0x79, 0xe8, 0x20, 0x73, 0x68, 0xfa, 0x6d, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x63, 0xff, 0xf3,
+0x3b, 0x73, 0x61, 0x14b, 0x20, 0x74, 0x73, 0x25b, 0x300, 0x25b, 0x20, 0x63, 0xff, 0xf3, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6e,
+0x6a, 0xff, 0x6f, 0x6c, 0xe1, 0x2bc, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x74, 0x79, 0x25b, 0x300, 0x62, 0x20, 0x74, 0x79, 0x25b,
+0x300, 0x62, 0x20, 0x6d, 0x62, 0x289, 0x300, 0x14b, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6d, 0x62, 0x289, 0x300, 0x14b, 0x3b, 0x73,
+0x61, 0x14b, 0x20, 0x6e, 0x67, 0x77, 0x254, 0x300, 0x2bc, 0x20, 0x6d, 0x62, 0xff, 0x25b, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x74,
+0xe0, 0x14b, 0x61, 0x20, 0x74, 0x73, 0x65, 0x74, 0x73, 0xe1, 0x2bc, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6d, 0x65, 0x6a, 0x77,
+0x6f, 0x14b, 0xf3, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6c, 0xf9, 0x6d, 0x3b, 0x57, 0x69, 0xf3, 0x74, 0x68, 0x65, 0x21f, 0x69,
+0x6b, 0x61, 0x20, 0x57, 0xed, 0x3b, 0x54, 0x68, 0x69, 0x79, 0xf3, 0x21f, 0x65, 0x79, 0x75, 0x14b, 0x6b, 0x61, 0x20, 0x57,
+0xed, 0x3b, 0x49, 0x161, 0x74, 0xe1, 0x77, 0x69, 0x10d, 0x68, 0x61, 0x79, 0x61, 0x7a, 0x61, 0x14b, 0x20, 0x57, 0xed, 0x3b,
+0x50, 0x21f, 0x65, 0x17e, 0xed, 0x74, 0x21f, 0x6f, 0x20, 0x57, 0xed, 0x3b, 0x10c, 0x68, 0x61, 0x14b, 0x77, 0xe1, 0x70, 0x65,
+0x74, 0x21f, 0x6f, 0x20, 0x57, 0xed, 0x3b, 0x57, 0xed, 0x70, 0x61, 0x7a, 0x75, 0x6b, 0x21f, 0x61, 0x2d, 0x77, 0x61, 0x161,
+0x74, 0xe9, 0x20, 0x57, 0xed, 0x3b, 0x10c, 0x68, 0x61, 0x14b, 0x70, 0x21f, 0xe1, 0x73, 0x61, 0x70, 0x61, 0x20, 0x57, 0xed,
+0x3b, 0x57, 0x61, 0x73, 0xfa, 0x74, 0x21f, 0x75, 0x14b, 0x20, 0x57, 0xed, 0x3b, 0x10c, 0x68, 0x61, 0x14b, 0x77, 0xe1, 0x70,
+0x65, 0x1e7, 0x69, 0x20, 0x57, 0xed, 0x3b, 0x10c, 0x68, 0x61, 0x14b, 0x77, 0xe1, 0x70, 0x65, 0x2d, 0x6b, 0x61, 0x73, 0x6e,
+0xe1, 0x20, 0x57, 0xed, 0x3b, 0x57, 0x61, 0x6e, 0xed, 0x79, 0x65, 0x74, 0x75, 0x20, 0x57, 0xed, 0x3b, 0x54, 0x21f, 0x61,
+0x68, 0xe9, 0x6b, 0x61, 0x70, 0x161, 0x75, 0x14b, 0x20, 0x57, 0xed, 0x3b, 0x6a9, 0x627, 0x646, 0x648, 0x648, 0x646, 0x6cc, 0x20,
+0x62f, 0x648, 0x648, 0x6d5, 0x645, 0x3b, 0x634, 0x648, 0x628, 0x627, 0x62a, 0x3b, 0x626, 0x627, 0x632, 0x627, 0x631, 0x3b, 0x646, 0x6cc,
+0x633, 0x627, 0x646, 0x3b, 0x626, 0x627, 0x6cc, 0x627, 0x631, 0x3b, 0x62d, 0x648, 0x632, 0x6d5, 0x6cc, 0x631, 0x627, 0x646, 0x3b, 0x62a,
+0x6d5, 0x645, 0x648, 0x648, 0x632, 0x3b, 0x626, 0x627, 0x628, 0x3b, 0x626, 0x6d5, 0x6cc, 0x644, 0x648, 0x648, 0x644, 0x3b, 0x62a, 0x634,
+0x631, 0x6cc, 0x646, 0x6cc, 0x20, 0x6cc, 0x6d5, 0x6a9, 0x6d5, 0x645, 0x3b, 0x62a, 0x634, 0x631, 0x6cc, 0x646, 0x6cc, 0x20, 0x62f, 0x648,
+0x648, 0x6d5, 0x645, 0x3b, 0x6a9, 0x627, 0x646, 0x648, 0x646, 0x6cc, 0x20, 0x6cc, 0x6d5, 0x6a9, 0x6d5, 0x645, 0x3b, 0x6a9, 0x3b, 0x634,
+0x3b, 0x626, 0x3b, 0x646, 0x3b, 0x626, 0x3b, 0x62d, 0x3b, 0x62a, 0x3b, 0x626, 0x3b, 0x626, 0x3b, 0x62a, 0x3b, 0x62a, 0x3b, 0x6a9,
+0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x11b, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x6a,
+0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x77, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74,
+0x3b, 0x6e, 0x6f, 0x77, 0x3b, 0x64, 0x65, 0x63, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72,
+0x75, 0x61, 0x72, 0x3b, 0x6d, 0x11b, 0x72, 0x63, 0x3b, 0x61, 0x70, 0x72, 0x79, 0x6c, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a,
+0x75, 0x6e, 0x69, 0x6a, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6a, 0x3b, 0x61, 0x77, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65,
+0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x77, 0x65,
+0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66,
+0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x11b, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x6a, 0x2e, 0x3b, 0x6a,
+0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x77, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f,
+0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x77, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72,
+0x61, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x61, 0x3b, 0x6d, 0x11b, 0x72, 0x63, 0x61, 0x3b, 0x61, 0x70, 0x72,
+0x79, 0x6c, 0x61, 0x3b, 0x6d, 0x61, 0x6a, 0x61, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6a, 0x61, 0x3b, 0x6a, 0x75, 0x6c, 0x69,
+0x6a, 0x61, 0x3b, 0x61, 0x77, 0x67, 0x75, 0x73, 0x74, 0x61, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x61,
+0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x72, 0x61, 0x3b, 0x6e, 0x6f, 0x77, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x64, 0x65,
+0x63, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x11b, 0x72, 0x3b, 0x61,
+0x70, 0x72, 0x3b, 0x6d, 0x65, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x77, 0x67, 0x3b, 0x73,
+0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x77, 0x3b, 0x64, 0x65, 0x63, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61,
+0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x11b, 0x72, 0x63, 0x3b, 0x61, 0x70, 0x72, 0x79, 0x6c,
+0x3b, 0x6d, 0x65, 0x6a, 0x61, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6a, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6a, 0x3b, 0x61, 0x77,
+0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62,
+0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x77, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72,
+0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x11b, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e,
+0x3b, 0x6d, 0x65, 0x6a, 0x2e, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x77, 0x67, 0x2e,
+0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x77, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e,
+0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x61, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x61, 0x3b, 0x6d, 0x11b,
+0x72, 0x63, 0x61, 0x3b, 0x61, 0x70, 0x72, 0x79, 0x6c, 0x61, 0x3b, 0x6d, 0x65, 0x6a, 0x65, 0x3b, 0x6a, 0x75, 0x6e, 0x69,
+0x6a, 0x61, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6a, 0x61, 0x3b, 0x61, 0x77, 0x67, 0x75, 0x73, 0x74, 0x61, 0x3b, 0x73, 0x65,
+0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x72, 0x61, 0x3b, 0x6e, 0x6f, 0x77, 0x65,
+0x6d, 0x62, 0x72, 0x61, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x72, 0x61, 0x67, 0x3b, 0x77, 0x61,
+0x73, 0x3b, 0x70, 0x16b, 0x6c, 0x3b, 0x73, 0x61, 0x6b, 0x3b, 0x7a, 0x61, 0x6c, 0x3b, 0x73, 0x12b, 0x6d, 0x3b, 0x6c, 0x12b,
+0x70, 0x3b, 0x64, 0x61, 0x67, 0x3b, 0x73, 0x69, 0x6c, 0x3b, 0x73, 0x70, 0x61, 0x3b, 0x6c, 0x61, 0x70, 0x3b, 0x73, 0x61,
+0x6c, 0x3b, 0x72, 0x61, 0x67, 0x73, 0x3b, 0x77, 0x61, 0x73, 0x73, 0x61, 0x72, 0x69, 0x6e, 0x73, 0x3b, 0x70, 0x16b, 0x6c,
+0x69, 0x73, 0x3b, 0x73, 0x61, 0x6b, 0x6b, 0x69, 0x73, 0x3b, 0x7a, 0x61, 0x6c, 0x6c, 0x61, 0x77, 0x73, 0x3b, 0x73, 0x12b,
+0x6d, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x6c, 0x12b, 0x70, 0x61, 0x3b, 0x64, 0x61, 0x67, 0x67, 0x69, 0x73, 0x3b, 0x73, 0x69,
+0x6c, 0x6c, 0x69, 0x6e, 0x73, 0x3b, 0x73, 0x70, 0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x73, 0x3b, 0x6c, 0x61, 0x70, 0x6b, 0x72,
+0x16b, 0x74, 0x69, 0x73, 0x3b, 0x73, 0x61, 0x6c, 0x6c, 0x61, 0x77, 0x73, 0x3b, 0x52, 0x3b, 0x57, 0x3b, 0x50, 0x3b, 0x53,
+0x3b, 0x5a, 0x3b, 0x53, 0x3b, 0x4c, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x4c, 0x3b, 0x53, 0x3b, 0x75, 0x111, 0x69,
+0x76, 0x3b, 0x6b, 0x75, 0x6f, 0x76, 0xe2, 0x3b, 0x6e, 0x6a, 0x75, 0x68, 0x10d, 0xe2, 0x3b, 0x63, 0x75, 0xe1, 0x14b, 0x75,
+0x69, 0x3b, 0x76, 0x79, 0x65, 0x73, 0x69, 0x3b, 0x6b, 0x65, 0x73, 0x69, 0x3b, 0x73, 0x79, 0x65, 0x69, 0x6e, 0x69, 0x3b,
+0x70, 0x6f, 0x72, 0x67, 0x65, 0x3b, 0x10d, 0x6f, 0x68, 0x10d, 0xe2, 0x3b, 0x72, 0x6f, 0x6f, 0x76, 0x76, 0xe2, 0x64, 0x3b,
+0x73, 0x6b, 0x61, 0x6d, 0x6d, 0xe2, 0x3b, 0x6a, 0x75, 0x6f, 0x76, 0x6c, 0xe2, 0x3b, 0x75, 0x111, 0x111, 0xe2, 0x69, 0x76,
+0x65, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x6b, 0x75, 0x6f, 0x76, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x6e, 0x6a,
+0x75, 0x68, 0x10d, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x63, 0x75, 0xe1, 0x14b, 0x75, 0x69, 0x6d, 0xe1, 0xe1, 0x6e,
+0x75, 0x3b, 0x76, 0x79, 0x65, 0x73, 0x69, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x6b, 0x65, 0x73, 0x69, 0x6d, 0xe1, 0xe1,
+0x6e, 0x75, 0x3b, 0x73, 0x79, 0x65, 0x69, 0x6e, 0x69, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x70, 0x6f, 0x72, 0x67, 0x65,
+0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x10d, 0x6f, 0x68, 0x10d, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x72, 0x6f, 0x6f,
+0x76, 0x76, 0xe2, 0x64, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x73, 0x6b, 0x61, 0x6d, 0x6d, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e,
+0x75, 0x3b, 0x6a, 0x75, 0x6f, 0x76, 0x6c, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x55, 0x3b, 0x4b, 0x3b, 0x4e, 0x4a,
+0x3b, 0x43, 0x3b, 0x56, 0x3b, 0x4b, 0x3b, 0x53, 0x3b, 0x50, 0x3b, 0x10c, 0x3b, 0x52, 0x3b, 0x53, 0x3b, 0x4a, 0x3b, 0x62c,
+0x627, 0x646, 0x6a4, 0x6cc, 0x6d5, 0x3b, 0x641, 0x626, 0x6a4, 0x631, 0x6cc, 0x6d5, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x622, 0x6a4,
+0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x626, 0x6cc, 0x3b, 0x62c, 0x648, 0x659, 0x623, 0x646, 0x3b, 0x62c, 0x648, 0x659, 0x644, 0x627, 0x3b,
+0x622, 0x6af, 0x648, 0x633, 0x62a, 0x3b, 0x633, 0x626, 0x67e, 0x62a, 0x627, 0x645, 0x631, 0x3b, 0x626, 0x648, 0x6a9, 0x62a, 0x648, 0x6a4,
+0x631, 0x3b, 0x646, 0x648, 0x6a4, 0x627, 0x645, 0x631, 0x3b, 0x62f, 0x626, 0x633, 0x627, 0x645, 0x631, 0x3b
};
static const ushort days_data[] = {
@@ -3840,32 +4000,31 @@ static const ushort days_data[] = {
0x6e, 0x64, 0x61, 0x67, 0x3b, 0x4d, 0x61, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x44, 0x69, 0x6e, 0x73, 0x64, 0x61, 0x67,
0x3b, 0x57, 0x6f, 0x65, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x44, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x64, 0x61, 0x67, 0x3b,
0x56, 0x72, 0x79, 0x64, 0x61, 0x67, 0x3b, 0x53, 0x61, 0x74, 0x65, 0x72, 0x64, 0x61, 0x67, 0x3b, 0x53, 0x3b, 0x4d, 0x3b,
-0x44, 0x3b, 0x57, 0x3b, 0x44, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x44, 0x69, 0x65, 0x3b, 0x48, 0xeb, 0x6e, 0x3b, 0x4d, 0x61,
-0x72, 0x3b, 0x4d, 0xeb, 0x72, 0x3b, 0x45, 0x6e, 0x6a, 0x3b, 0x50, 0x72, 0x65, 0x3b, 0x53, 0x68, 0x74, 0x3b, 0x45, 0x20,
-0x64, 0x69, 0x65, 0x6c, 0x3b, 0x45, 0x20, 0x68, 0xeb, 0x6e, 0xeb, 0x3b, 0x45, 0x20, 0x6d, 0x61, 0x72, 0x74, 0xeb, 0x3b,
-0x45, 0x20, 0x6d, 0xeb, 0x72, 0x6b, 0x75, 0x72, 0xeb, 0x3b, 0x45, 0x20, 0x65, 0x6e, 0x6a, 0x74, 0x65, 0x3b, 0x45, 0x20,
-0x70, 0x72, 0x65, 0x6d, 0x74, 0x65, 0x3b, 0x45, 0x20, 0x73, 0x68, 0x74, 0x75, 0x6e, 0xeb, 0x3b, 0x44, 0x3b, 0x48, 0x3b,
-0x4d, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x65, 0x20, 0x64, 0x69, 0x65, 0x6c, 0x3b, 0x65, 0x20, 0x68,
-0xeb, 0x6e, 0xeb, 0x3b, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x74, 0xeb, 0x3b, 0x65, 0x20, 0x6d, 0xeb, 0x72, 0x6b, 0x75, 0x72,
-0xeb, 0x3b, 0x65, 0x20, 0x65, 0x6e, 0x6a, 0x74, 0x65, 0x3b, 0x65, 0x20, 0x70, 0x72, 0x65, 0x6d, 0x74, 0x65, 0x3b, 0x65,
-0x20, 0x73, 0x68, 0x74, 0x75, 0x6e, 0xeb, 0x3b, 0x12a5, 0x1211, 0x12f5, 0x3b, 0x1230, 0x129e, 0x3b, 0x121b, 0x12ad, 0x1230, 0x3b, 0x1228,
-0x1261, 0x12d5, 0x3b, 0x1210, 0x1219, 0x1235, 0x3b, 0x12d3, 0x122d, 0x1265, 0x3b, 0x1245, 0x12f3, 0x121c, 0x3b, 0x12a5, 0x1211, 0x12f5, 0x3b, 0x1230,
-0x129e, 0x3b, 0x121b, 0x12ad, 0x1230, 0x129e, 0x3b, 0x1228, 0x1261, 0x12d5, 0x3b, 0x1210, 0x1219, 0x1235, 0x3b, 0x12d3, 0x122d, 0x1265, 0x3b, 0x1245,
-0x12f3, 0x121c, 0x3b, 0x12a5, 0x3b, 0x1230, 0x3b, 0x121b, 0x3b, 0x1228, 0x3b, 0x1210, 0x3b, 0x12d3, 0x3b, 0x1245, 0x3b, 0x627, 0x644, 0x623,
-0x62d, 0x62f, 0x3b, 0x627, 0x644, 0x627, 0x62b, 0x646, 0x64a, 0x646, 0x3b, 0x627, 0x644, 0x62b, 0x644, 0x627, 0x62b, 0x627, 0x621, 0x3b,
-0x627, 0x644, 0x623, 0x631, 0x628, 0x639, 0x627, 0x621, 0x3b, 0x627, 0x644, 0x62e, 0x645, 0x64a, 0x633, 0x3b, 0x627, 0x644, 0x62c, 0x645,
-0x639, 0x629, 0x3b, 0x627, 0x644, 0x633, 0x628, 0x62a, 0x3b, 0x62d, 0x3b, 0x646, 0x3b, 0x62b, 0x3b, 0x631, 0x3b, 0x62e, 0x3b, 0x62c,
-0x3b, 0x633, 0x3b, 0x56f, 0x56b, 0x580, 0x3b, 0x565, 0x580, 0x56f, 0x3b, 0x565, 0x580, 0x584, 0x3b, 0x579, 0x580, 0x584, 0x3b, 0x570,
-0x576, 0x563, 0x3b, 0x578, 0x582, 0x580, 0x3b, 0x577, 0x562, 0x569, 0x3b, 0x56f, 0x56b, 0x580, 0x561, 0x56f, 0x56b, 0x3b, 0x565, 0x580,
-0x56f, 0x578, 0x582, 0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b, 0x565, 0x580, 0x565, 0x584, 0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b, 0x579,
-0x578, 0x580, 0x565, 0x584, 0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b, 0x570, 0x56b, 0x576, 0x563, 0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b,
-0x578, 0x582, 0x580, 0x562, 0x561, 0x569, 0x3b, 0x577, 0x561, 0x562, 0x561, 0x569, 0x3b, 0x53f, 0x3b, 0x535, 0x3b, 0x535, 0x3b, 0x549,
-0x3b, 0x540, 0x3b, 0x548, 0x3b, 0x547, 0x3b, 0x9f0, 0x9ac, 0x9bf, 0x3b, 0x9b8, 0x9cb, 0x9ae, 0x3b, 0x9ae, 0x999, 0x9cd, 0x997, 0x9b2,
-0x3b, 0x9ac, 0x9c1, 0x9a7, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x9b7, 0x9cd, 0x9aa, 0x9a4, 0x9bf, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9f0, 0x3b,
-0x9b6, 0x9a8, 0x9bf, 0x3b, 0x9a6, 0x9c7, 0x993, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9b8, 0x9cb, 0x9ae, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9ae, 0x999,
-0x9cd, 0x997, 0x9b2, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x9b7, 0x9cd, 0x9aa,
-0x9a4, 0x9bf, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9f0, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9b6, 0x9a8, 0x9bf, 0x9ac, 0x9be,
-0x9f0, 0x3b, 0x42, 0x2e, 0x3b, 0x42, 0x2e, 0x45, 0x2e, 0x3b, 0xc7, 0x2e, 0x41, 0x2e, 0x3b, 0xc7, 0x2e, 0x3b, 0x43, 0x2e,
+0x44, 0x3b, 0x57, 0x3b, 0x44, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x64, 0x69, 0x65, 0x3b, 0x68, 0xeb, 0x6e, 0x3b, 0x6d, 0x61,
+0x72, 0x3b, 0x6d, 0xeb, 0x72, 0x3b, 0x65, 0x6e, 0x6a, 0x3b, 0x70, 0x72, 0x65, 0x3b, 0x73, 0x68, 0x74, 0x3b, 0x65, 0x20,
+0x64, 0x69, 0x65, 0x6c, 0x3b, 0x65, 0x20, 0x68, 0xeb, 0x6e, 0xeb, 0x3b, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x74, 0xeb, 0x3b,
+0x65, 0x20, 0x6d, 0xeb, 0x72, 0x6b, 0x75, 0x72, 0xeb, 0x3b, 0x65, 0x20, 0x65, 0x6e, 0x6a, 0x74, 0x65, 0x3b, 0x65, 0x20,
+0x70, 0x72, 0x65, 0x6d, 0x74, 0x65, 0x3b, 0x65, 0x20, 0x73, 0x68, 0x74, 0x75, 0x6e, 0xeb, 0x3b, 0x64, 0x3b, 0x68, 0x3b,
+0x6d, 0x3b, 0x6d, 0x3b, 0x65, 0x3b, 0x70, 0x3b, 0x73, 0x68, 0x3b, 0x44, 0x69, 0x65, 0x3b, 0x48, 0xeb, 0x6e, 0x3b, 0x4d,
+0x61, 0x72, 0x3b, 0x4d, 0xeb, 0x72, 0x3b, 0x45, 0x6e, 0x6a, 0x3b, 0x50, 0x72, 0x65, 0x3b, 0x53, 0x68, 0x74, 0x3b, 0x12a5,
+0x1211, 0x12f5, 0x3b, 0x1230, 0x129e, 0x3b, 0x121b, 0x12ad, 0x1230, 0x3b, 0x1228, 0x1261, 0x12d5, 0x3b, 0x1210, 0x1219, 0x1235, 0x3b, 0x12d3, 0x122d,
+0x1265, 0x3b, 0x1245, 0x12f3, 0x121c, 0x3b, 0x12a5, 0x1211, 0x12f5, 0x3b, 0x1230, 0x129e, 0x3b, 0x121b, 0x12ad, 0x1230, 0x129e, 0x3b, 0x1228, 0x1261,
+0x12d5, 0x3b, 0x1210, 0x1219, 0x1235, 0x3b, 0x12d3, 0x122d, 0x1265, 0x3b, 0x1245, 0x12f3, 0x121c, 0x3b, 0x12a5, 0x3b, 0x1230, 0x3b, 0x121b, 0x3b,
+0x1228, 0x3b, 0x1210, 0x3b, 0x12d3, 0x3b, 0x1245, 0x3b, 0x627, 0x644, 0x623, 0x62d, 0x62f, 0x3b, 0x627, 0x644, 0x627, 0x62b, 0x646, 0x64a,
+0x646, 0x3b, 0x627, 0x644, 0x62b, 0x644, 0x627, 0x62b, 0x627, 0x621, 0x3b, 0x627, 0x644, 0x623, 0x631, 0x628, 0x639, 0x627, 0x621, 0x3b,
+0x627, 0x644, 0x62e, 0x645, 0x64a, 0x633, 0x3b, 0x627, 0x644, 0x62c, 0x645, 0x639, 0x629, 0x3b, 0x627, 0x644, 0x633, 0x628, 0x62a, 0x3b,
+0x62d, 0x3b, 0x646, 0x3b, 0x62b, 0x3b, 0x631, 0x3b, 0x62e, 0x3b, 0x62c, 0x3b, 0x633, 0x3b, 0x56f, 0x56b, 0x580, 0x3b, 0x565, 0x580,
+0x56f, 0x3b, 0x565, 0x580, 0x584, 0x3b, 0x579, 0x580, 0x584, 0x3b, 0x570, 0x576, 0x563, 0x3b, 0x578, 0x582, 0x580, 0x3b, 0x577, 0x562,
+0x569, 0x3b, 0x56f, 0x56b, 0x580, 0x561, 0x56f, 0x56b, 0x3b, 0x565, 0x580, 0x56f, 0x578, 0x582, 0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b,
+0x565, 0x580, 0x565, 0x584, 0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b, 0x579, 0x578, 0x580, 0x565, 0x584, 0x577, 0x561, 0x562, 0x569, 0x56b,
+0x3b, 0x570, 0x56b, 0x576, 0x563, 0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b, 0x578, 0x582, 0x580, 0x562, 0x561, 0x569, 0x3b, 0x577, 0x561,
+0x562, 0x561, 0x569, 0x3b, 0x53f, 0x3b, 0x535, 0x3b, 0x535, 0x3b, 0x549, 0x3b, 0x540, 0x3b, 0x548, 0x3b, 0x547, 0x3b, 0x9a6, 0x9c7,
+0x993, 0x3b, 0x9b8, 0x9cb, 0x9ae, 0x3b, 0x9ae, 0x999, 0x9cd, 0x997, 0x9b2, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x3b,
+0x9b6, 0x9c1, 0x995, 0x9cd, 0x9f0, 0x3b, 0x9b6, 0x9a8, 0x9bf, 0x3b, 0x9a6, 0x9c7, 0x993, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9b8, 0x9cb, 0x9ae,
+0x9ac, 0x9be, 0x9f0, 0x3b, 0x9ae, 0x999, 0x9cd, 0x997, 0x9b2, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x9ac, 0x9be, 0x9f0, 0x3b,
+0x9ac, 0x9c3, 0x9b9, 0x9b8, 0x9cd, 0x9aa, 0x9a4, 0x9bf, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9f0, 0x9ac, 0x9be, 0x9f0,
+0x3b, 0x9b6, 0x9a8, 0x9bf, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9a6, 0x3b, 0x9b8, 0x3b, 0x9ae, 0x3b, 0x9ac, 0x3b, 0x9ac, 0x3b, 0x9b6, 0x3b,
+0x9b6, 0x3b, 0x42, 0x2e, 0x3b, 0x42, 0x2e, 0x45, 0x2e, 0x3b, 0xc7, 0x2e, 0x41, 0x2e, 0x3b, 0xc7, 0x2e, 0x3b, 0x43, 0x2e,
0x41, 0x2e, 0x3b, 0x43, 0x2e, 0x3b, 0x15e, 0x2e, 0x3b, 0x62, 0x61, 0x7a, 0x61, 0x72, 0x3b, 0x62, 0x61, 0x7a, 0x61, 0x72,
0x20, 0x65, 0x72, 0x74, 0x259, 0x73, 0x69, 0x3b, 0xe7, 0x259, 0x72, 0x15f, 0x259, 0x6e, 0x62, 0x259, 0x20, 0x61, 0x78, 0x15f,
0x61, 0x6d, 0x131, 0x3b, 0xe7, 0x259, 0x72, 0x15f, 0x259, 0x6e, 0x62, 0x259, 0x3b, 0x63, 0xfc, 0x6d, 0x259, 0x20, 0x61, 0x78,
@@ -3875,51 +4034,49 @@ static const ushort days_data[] = {
0x438, 0x3b, 0x447, 0x4d9, 0x440, 0x448, 0x4d9, 0x43d, 0x431, 0x4d9, 0x20, 0x430, 0x445, 0x448, 0x430, 0x43c, 0x44b, 0x3b, 0x447, 0x4d9,
0x440, 0x448, 0x4d9, 0x43d, 0x431, 0x4d9, 0x3b, 0x4b9, 0x4af, 0x43c, 0x4d9, 0x20, 0x430, 0x445, 0x448, 0x430, 0x43c, 0x44b, 0x3b, 0x4b9,
0x4af, 0x43c, 0x4d9, 0x3b, 0x448, 0x4d9, 0x43d, 0x431, 0x4d9, 0x3b, 0x69, 0x67, 0x2e, 0x3b, 0x61, 0x6c, 0x2e, 0x3b, 0x61, 0x72,
-0x2e, 0x3b, 0x61, 0x7a, 0x2e, 0x3b, 0x6f, 0x67, 0x2e, 0x3b, 0x6f, 0x72, 0x2e, 0x3b, 0x6c, 0x72, 0x2e, 0x3b, 0x49, 0x67,
-0x61, 0x6e, 0x64, 0x65, 0x61, 0x3b, 0x41, 0x73, 0x74, 0x65, 0x6c, 0x65, 0x68, 0x65, 0x6e, 0x61, 0x3b, 0x41, 0x73, 0x74,
-0x65, 0x61, 0x72, 0x74, 0x65, 0x61, 0x3b, 0x41, 0x73, 0x74, 0x65, 0x61, 0x7a, 0x6b, 0x65, 0x6e, 0x61, 0x3b, 0x4f, 0x73,
-0x74, 0x65, 0x67, 0x75, 0x6e, 0x61, 0x3b, 0x4f, 0x73, 0x74, 0x69, 0x72, 0x61, 0x6c, 0x61, 0x3b, 0x4c, 0x61, 0x72, 0x75,
+0x2e, 0x3b, 0x61, 0x7a, 0x2e, 0x3b, 0x6f, 0x67, 0x2e, 0x3b, 0x6f, 0x72, 0x2e, 0x3b, 0x6c, 0x72, 0x2e, 0x3b, 0x69, 0x67,
+0x61, 0x6e, 0x64, 0x65, 0x61, 0x3b, 0x61, 0x73, 0x74, 0x65, 0x6c, 0x65, 0x68, 0x65, 0x6e, 0x61, 0x3b, 0x61, 0x73, 0x74,
+0x65, 0x61, 0x72, 0x74, 0x65, 0x61, 0x3b, 0x61, 0x73, 0x74, 0x65, 0x61, 0x7a, 0x6b, 0x65, 0x6e, 0x61, 0x3b, 0x6f, 0x73,
+0x74, 0x65, 0x67, 0x75, 0x6e, 0x61, 0x3b, 0x6f, 0x73, 0x74, 0x69, 0x72, 0x61, 0x6c, 0x61, 0x3b, 0x6c, 0x61, 0x72, 0x75,
0x6e, 0x62, 0x61, 0x74, 0x61, 0x3b, 0x49, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x4f, 0x3b, 0x4f, 0x3b, 0x4c, 0x3b,
-0x69, 0x67, 0x61, 0x6e, 0x64, 0x65, 0x61, 0x3b, 0x61, 0x73, 0x74, 0x65, 0x6c, 0x65, 0x68, 0x65, 0x6e, 0x61, 0x3b, 0x61,
-0x73, 0x74, 0x65, 0x61, 0x72, 0x74, 0x65, 0x61, 0x3b, 0x61, 0x73, 0x74, 0x65, 0x61, 0x7a, 0x6b, 0x65, 0x6e, 0x61, 0x3b,
-0x6f, 0x73, 0x74, 0x65, 0x67, 0x75, 0x6e, 0x61, 0x3b, 0x6f, 0x73, 0x74, 0x69, 0x72, 0x61, 0x6c, 0x61, 0x3b, 0x6c, 0x61,
-0x72, 0x75, 0x6e, 0x62, 0x61, 0x74, 0x61, 0x3b, 0x9b0, 0x9ac, 0x9bf, 0x3b, 0x9b8, 0x9cb, 0x9ae, 0x3b, 0x9ae, 0x999, 0x9cd, 0x997,
-0x9b2, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x9b8, 0x9cd, 0x9aa, 0x9a4, 0x9bf, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9b0,
-0x3b, 0x9b6, 0x9a8, 0x9bf, 0x3b, 0x9b0, 0x9ac, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b8, 0x9cb, 0x9ae, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ae,
-0x999, 0x9cd, 0x997, 0x9b2, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x9b7, 0x9cd,
-0x9aa, 0x9a4, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9b0, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b6, 0x9a8, 0x9bf, 0x9ac,
-0x9be, 0x9b0, 0x3b, 0x9b0, 0x3b, 0x9b8, 0x9cb, 0x3b, 0x9ae, 0x3b, 0x9ac, 0x9c1, 0x3b, 0x9ac, 0x9c3, 0x3b, 0x9b6, 0x9c1, 0x3b, 0x9b6,
-0x3b, 0x9b0, 0x9ac, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b8, 0x9cb, 0x9ae, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ae, 0x999, 0x9cd, 0x997, 0x9b2,
-0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x9b8, 0x9cd, 0x9aa, 0x9a4, 0x9bf, 0x9ac,
-0x9be, 0x9b0, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9b0, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b6, 0x9a8, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b, 0xf5f,
-0xfb3, 0xf0b, 0x3b, 0xf58, 0xf72, 0xf62, 0xf0b, 0x3b, 0xf63, 0xfb7, 0xf42, 0xf0b, 0x3b, 0xf55, 0xf74, 0xf62, 0xf0b, 0x3b, 0xf66, 0xf44,
-0xf66, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0xf0b, 0x3b, 0xf49, 0xf72, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf5f, 0xfb3, 0xf0b,
-0xf56, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf58, 0xf72, 0xf42, 0xf0b, 0xf51, 0xf58, 0xf62, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b,
-0xf63, 0xfb7, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf55, 0xf74, 0xf62, 0xf0b, 0xf56, 0xf74, 0xf0b, 0x3b, 0xf42,
-0xf5f, 0xf60, 0xf0b, 0xf54, 0xf0b, 0xf66, 0xf44, 0xf66, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0xf0b, 0xf54,
-0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf49, 0xf72, 0xf0b, 0xf58, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0x3b, 0xf58, 0xf72, 0xf62, 0x3b, 0xf63,
-0xfb7, 0xf42, 0x3b, 0xf55, 0xf74, 0xf62, 0x3b, 0xf66, 0xf44, 0xfb6, 0x3b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0x3b, 0xf49, 0xf72, 0x3b, 0x53,
-0x75, 0x6c, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x65, 0x75, 0x2e, 0x3b, 0x4d, 0x65, 0x72, 0x2e, 0x3b, 0x59, 0x61, 0x6f,
-0x75, 0x3b, 0x47, 0x77, 0x65, 0x2e, 0x3b, 0x53, 0x61, 0x64, 0x2e, 0x3b, 0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x75, 0x6e, 0x3b,
-0x4d, 0x65, 0x75, 0x72, 0x7a, 0x68, 0x3b, 0x4d, 0x65, 0x72, 0x63, 0x2bc, 0x68, 0x65, 0x72, 0x3b, 0x59, 0x61, 0x6f, 0x75,
-0x3b, 0x47, 0x77, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x53, 0x61, 0x64, 0x6f, 0x72, 0x6e, 0x3b, 0x53, 0x75, 0x3b, 0x4c, 0x3b,
-0x4d, 0x7a, 0x3b, 0x4d, 0x63, 0x3b, 0x59, 0x3b, 0x47, 0x3b, 0x53, 0x61, 0x3b, 0x43d, 0x434, 0x3b, 0x43f, 0x43d, 0x3b, 0x432,
-0x442, 0x3b, 0x441, 0x440, 0x3b, 0x447, 0x442, 0x3b, 0x43f, 0x442, 0x3b, 0x441, 0x431, 0x3b, 0x43d, 0x435, 0x434, 0x435, 0x43b, 0x44f,
-0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435, 0x43b, 0x43d, 0x438, 0x43a, 0x3b, 0x432, 0x442, 0x43e, 0x440, 0x43d, 0x438, 0x43a, 0x3b,
-0x441, 0x440, 0x44f, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x44a, 0x440, 0x442, 0x44a, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x44a,
-0x43a, 0x3b, 0x441, 0x44a, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x43d, 0x3b, 0x43f, 0x3b, 0x432, 0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f,
-0x3b, 0x441, 0x3b, 0x1010, 0x1014, 0x1004, 0x103a, 0x1039, 0x1002, 0x1014, 0x103d, 0x1031, 0x3b, 0x1010, 0x1014, 0x1004, 0x103a, 0x1039, 0x101c, 0x102c,
-0x3b, 0x1021, 0x1004, 0x103a, 0x1039, 0x1002, 0x102b, 0x3b, 0x1017, 0x102f, 0x1012, 0x1039, 0x1013, 0x101f, 0x1030, 0x1038, 0x3b, 0x1000, 0x103c, 0x102c,
-0x101e, 0x1015, 0x1010, 0x1031, 0x1038, 0x3b, 0x101e, 0x1031, 0x102c, 0x1000, 0x103c, 0x102c, 0x3b, 0x1005, 0x1014, 0x1031, 0x3b, 0x1010, 0x3b, 0x1010,
-0x3b, 0x1021, 0x3b, 0x1017, 0x3b, 0x1000, 0x3b, 0x101e, 0x3b, 0x1005, 0x3b, 0x43d, 0x434, 0x3b, 0x43f, 0x43d, 0x3b, 0x430, 0x45e, 0x3b,
-0x441, 0x440, 0x3b, 0x447, 0x446, 0x3b, 0x43f, 0x442, 0x3b, 0x441, 0x431, 0x3b, 0x43d, 0x44f, 0x434, 0x437, 0x435, 0x43b, 0x44f, 0x3b,
-0x43f, 0x430, 0x43d, 0x44f, 0x434, 0x437, 0x435, 0x43b, 0x430, 0x43a, 0x3b, 0x430, 0x45e, 0x442, 0x43e, 0x440, 0x430, 0x43a, 0x3b, 0x441,
-0x435, 0x440, 0x430, 0x434, 0x430, 0x3b, 0x447, 0x430, 0x446, 0x432, 0x435, 0x440, 0x3b, 0x43f, 0x44f, 0x442, 0x43d, 0x456, 0x446, 0x430,
-0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x43d, 0x3b, 0x43f, 0x3b, 0x430, 0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f, 0x3b,
-0x441, 0x3b, 0x17a2, 0x17b6, 0x1791, 0x17b7, 0x178f, 0x17d2, 0x1799, 0x3b, 0x1785, 0x17d0, 0x1793, 0x17d2, 0x1791, 0x3b, 0x17a2, 0x1784, 0x17d2, 0x1782,
-0x17b6, 0x179a, 0x3b, 0x1796, 0x17bb, 0x1792, 0x3b, 0x1796, 0x17d2, 0x179a, 0x17a0, 0x179f, 0x17d2, 0x1794, 0x178f, 0x17b7, 0x17cd, 0x3b, 0x179f, 0x17bb,
-0x1780, 0x17d2, 0x179a, 0x3b, 0x179f, 0x17c5, 0x179a, 0x17cd, 0x3b, 0x17a2, 0x3b, 0x1785, 0x3b, 0x17a2, 0x3b, 0x1796, 0x3b, 0x1796, 0x3b, 0x179f,
-0x3b, 0x179f, 0x3b, 0x64, 0x67, 0x2e, 0x3b, 0x64, 0x6c, 0x2e, 0x3b, 0x64, 0x74, 0x2e, 0x3b, 0x64, 0x63, 0x2e, 0x3b, 0x64,
+0x9b0, 0x9ac, 0x9bf, 0x3b, 0x9b8, 0x9cb, 0x9ae, 0x3b, 0x9ae, 0x999, 0x9cd, 0x997, 0x9b2, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x3b, 0x9ac, 0x9c3,
+0x9b9, 0x9b8, 0x9cd, 0x9aa, 0x9a4, 0x9bf, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9b0, 0x3b, 0x9b6, 0x9a8, 0x9bf, 0x3b, 0x9b0, 0x9ac, 0x9bf,
+0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b8, 0x9cb, 0x9ae, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ae, 0x999, 0x9cd, 0x997, 0x9b2, 0x9ac, 0x9be, 0x9b0, 0x3b,
+0x9ac, 0x9c1, 0x9a7, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x9b8, 0x9cd, 0x9aa, 0x9a4, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b6,
+0x9c1, 0x995, 0x9cd, 0x9b0, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b6, 0x9a8, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b0, 0x3b, 0x9b8, 0x9cb, 0x3b,
+0x9ae, 0x3b, 0x9ac, 0x9c1, 0x3b, 0x9ac, 0x9c3, 0x3b, 0x9b6, 0x9c1, 0x3b, 0x9b6, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x3b, 0xf58, 0xf72, 0xf62,
+0xf0b, 0x3b, 0xf63, 0xfb7, 0xf42, 0xf0b, 0x3b, 0xf55, 0xf74, 0xf62, 0xf0b, 0x3b, 0xf66, 0xf44, 0xf66, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xf7a,
+0xf53, 0xf0b, 0x3b, 0xf49, 0xf72, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60,
+0xf0b, 0xf58, 0xf72, 0xf42, 0xf0b, 0xf51, 0xf58, 0xf62, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf63, 0xfb7, 0xf42, 0xf0b, 0xf54, 0xf0b,
+0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf55, 0xf74, 0xf62, 0xf0b, 0xf56, 0xf74, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf54, 0xf0b, 0xf66,
+0xf44, 0xf66, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b,
+0xf49, 0xf72, 0xf0b, 0xf58, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0x3b, 0xf58, 0xf72, 0xf62, 0x3b, 0xf63, 0xfb7, 0xf42, 0x3b, 0xf55, 0xf74, 0xf62,
+0x3b, 0xf66, 0xf44, 0xfb6, 0x3b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0x3b, 0xf49, 0xf72, 0x3b, 0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x75, 0x6e,
+0x3b, 0x4d, 0x65, 0x75, 0x2e, 0x3b, 0x4d, 0x65, 0x72, 0x2e, 0x3b, 0x59, 0x61, 0x6f, 0x75, 0x3b, 0x47, 0x77, 0x65, 0x2e,
+0x3b, 0x53, 0x61, 0x64, 0x2e, 0x3b, 0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x65, 0x75, 0x72, 0x7a, 0x68,
+0x3b, 0x4d, 0x65, 0x72, 0x63, 0x2bc, 0x68, 0x65, 0x72, 0x3b, 0x59, 0x61, 0x6f, 0x75, 0x3b, 0x47, 0x77, 0x65, 0x6e, 0x65,
+0x72, 0x3b, 0x53, 0x61, 0x64, 0x6f, 0x72, 0x6e, 0x3b, 0x53, 0x75, 0x3b, 0x4c, 0x3b, 0x4d, 0x7a, 0x3b, 0x4d, 0x63, 0x3b,
+0x59, 0x3b, 0x47, 0x3b, 0x53, 0x61, 0x3b, 0x43d, 0x434, 0x3b, 0x43f, 0x43d, 0x3b, 0x432, 0x442, 0x3b, 0x441, 0x440, 0x3b, 0x447,
+0x442, 0x3b, 0x43f, 0x442, 0x3b, 0x441, 0x431, 0x3b, 0x43d, 0x435, 0x434, 0x435, 0x43b, 0x44f, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434,
+0x435, 0x43b, 0x43d, 0x438, 0x43a, 0x3b, 0x432, 0x442, 0x43e, 0x440, 0x43d, 0x438, 0x43a, 0x3b, 0x441, 0x440, 0x44f, 0x434, 0x430, 0x3b,
+0x447, 0x435, 0x442, 0x432, 0x44a, 0x440, 0x442, 0x44a, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x44a, 0x43a, 0x3b, 0x441, 0x44a, 0x431, 0x43e,
+0x442, 0x430, 0x3b, 0x43d, 0x3b, 0x43f, 0x3b, 0x432, 0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f, 0x3b, 0x441, 0x3b, 0x1010, 0x1014, 0x1004,
+0x103a, 0x1039, 0x1002, 0x1014, 0x103d, 0x1031, 0x3b, 0x1010, 0x1014, 0x1004, 0x103a, 0x1039, 0x101c, 0x102c, 0x3b, 0x1021, 0x1004, 0x103a, 0x1039, 0x1002,
+0x102b, 0x3b, 0x1017, 0x102f, 0x1012, 0x1039, 0x1013, 0x101f, 0x1030, 0x1038, 0x3b, 0x1000, 0x103c, 0x102c, 0x101e, 0x1015, 0x1010, 0x1031, 0x1038, 0x3b,
+0x101e, 0x1031, 0x102c, 0x1000, 0x103c, 0x102c, 0x3b, 0x1005, 0x1014, 0x1031, 0x3b, 0x1010, 0x3b, 0x1010, 0x3b, 0x1021, 0x3b, 0x1017, 0x3b, 0x1000,
+0x3b, 0x101e, 0x3b, 0x1005, 0x3b, 0x43d, 0x434, 0x3b, 0x43f, 0x43d, 0x3b, 0x430, 0x45e, 0x3b, 0x441, 0x440, 0x3b, 0x447, 0x446, 0x3b,
+0x43f, 0x442, 0x3b, 0x441, 0x431, 0x3b, 0x43d, 0x44f, 0x434, 0x437, 0x435, 0x43b, 0x44f, 0x3b, 0x43f, 0x430, 0x43d, 0x44f, 0x434, 0x437,
+0x435, 0x43b, 0x430, 0x43a, 0x3b, 0x430, 0x45e, 0x442, 0x43e, 0x440, 0x430, 0x43a, 0x3b, 0x441, 0x435, 0x440, 0x430, 0x434, 0x430, 0x3b,
+0x447, 0x430, 0x446, 0x432, 0x435, 0x440, 0x3b, 0x43f, 0x44f, 0x442, 0x43d, 0x456, 0x446, 0x430, 0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442,
+0x430, 0x3b, 0x43d, 0x3b, 0x43f, 0x3b, 0x430, 0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f, 0x3b, 0x441, 0x3b, 0x17a2, 0x17b6, 0x1791, 0x17b7,
+0x178f, 0x17d2, 0x1799, 0x3b, 0x1785, 0x1793, 0x17d2, 0x1791, 0x3b, 0x17a2, 0x1784, 0x17d2, 0x1782, 0x17b6, 0x179a, 0x3b, 0x1796, 0x17bb, 0x1792, 0x3b,
+0x1796, 0x17d2, 0x179a, 0x17a0, 0x3b, 0x179f, 0x17bb, 0x1780, 0x17d2, 0x179a, 0x3b, 0x179f, 0x17c5, 0x179a, 0x17cd, 0x3b, 0x17a2, 0x17b6, 0x1791, 0x17b7,
+0x178f, 0x17d2, 0x1799, 0x3b, 0x1785, 0x1793, 0x17d2, 0x1791, 0x3b, 0x17a2, 0x1784, 0x17d2, 0x1782, 0x17b6, 0x179a, 0x3b, 0x1796, 0x17bb, 0x1792, 0x3b,
+0x1796, 0x17d2, 0x179a, 0x17a0, 0x179f, 0x17d2, 0x1794, 0x178f, 0x17b7, 0x17cd, 0x3b, 0x179f, 0x17bb, 0x1780, 0x17d2, 0x179a, 0x3b, 0x179f, 0x17c5, 0x179a,
+0x17cd, 0x3b, 0x17a2, 0x3b, 0x1785, 0x3b, 0x17a2, 0x3b, 0x1796, 0x3b, 0x1796, 0x3b, 0x179f, 0x3b, 0x179f, 0x3b, 0x17a2, 0x17b6, 0x1791, 0x17b7,
+0x178f, 0x17d2, 0x1799, 0x3b, 0x1785, 0x17d0, 0x1793, 0x17d2, 0x1791, 0x3b, 0x17a2, 0x1784, 0x17d2, 0x1782, 0x17b6, 0x179a, 0x3b, 0x1796, 0x17bb, 0x1792,
+0x3b, 0x1796, 0x17d2, 0x179a, 0x17a0, 0x179f, 0x17d2, 0x1794, 0x178f, 0x17b7, 0x17cd, 0x3b, 0x179f, 0x17bb, 0x1780, 0x17d2, 0x179a, 0x3b, 0x179f, 0x17c5,
+0x179a, 0x17cd, 0x3b, 0x64, 0x67, 0x2e, 0x3b, 0x64, 0x6c, 0x2e, 0x3b, 0x64, 0x74, 0x2e, 0x3b, 0x64, 0x63, 0x2e, 0x3b, 0x64,
0x6a, 0x2e, 0x3b, 0x64, 0x76, 0x2e, 0x3b, 0x64, 0x73, 0x2e, 0x3b, 0x64, 0x69, 0x75, 0x6d, 0x65, 0x6e, 0x67, 0x65, 0x3b,
0x64, 0x69, 0x6c, 0x6c, 0x75, 0x6e, 0x73, 0x3b, 0x64, 0x69, 0x6d, 0x61, 0x72, 0x74, 0x73, 0x3b, 0x64, 0x69, 0x6d, 0x65,
0x63, 0x72, 0x65, 0x73, 0x3b, 0x64, 0x69, 0x6a, 0x6f, 0x75, 0x73, 0x3b, 0x64, 0x69, 0x76, 0x65, 0x6e, 0x64, 0x72, 0x65,
@@ -3949,543 +4106,596 @@ static const ushort days_data[] = {
0x7a, 0x61, 0x3b, 0x7a, 0x6f, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x6d, 0x61, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x64, 0x69,
0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x77, 0x6f, 0x65, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x64, 0x6f, 0x6e, 0x64, 0x65,
0x72, 0x64, 0x61, 0x67, 0x3b, 0x76, 0x72, 0x69, 0x6a, 0x64, 0x61, 0x67, 0x3b, 0x7a, 0x61, 0x74, 0x65, 0x72, 0x64, 0x61,
-0x67, 0x3b, 0x5a, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x57, 0x3b, 0x44, 0x3b, 0x56, 0x3b, 0x5a, 0x3b, 0x53, 0x75, 0x6e, 0x2e,
-0x3b, 0x4d, 0x6f, 0x6e, 0x2e, 0x3b, 0x54, 0x75, 0x65, 0x2e, 0x3b, 0x57, 0x65, 0x64, 0x2e, 0x3b, 0x54, 0x68, 0x75, 0x2e,
-0x3b, 0x46, 0x72, 0x69, 0x2e, 0x3b, 0x53, 0x61, 0x74, 0x2e, 0x3b, 0x53, 0x75, 0x2e, 0x3b, 0x4d, 0x2e, 0x3b, 0x54, 0x75,
-0x2e, 0x3b, 0x57, 0x2e, 0x3b, 0x54, 0x68, 0x2e, 0x3b, 0x46, 0x2e, 0x3b, 0x53, 0x61, 0x2e, 0x3b, 0x50, 0x3b, 0x45, 0x3b,
-0x54, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x52, 0x3b, 0x4c, 0x3b, 0x70, 0xfc, 0x68, 0x61, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x65,
-0x73, 0x6d, 0x61, 0x73, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x74, 0x65, 0x69, 0x73, 0x69, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x6b,
-0x6f, 0x6c, 0x6d, 0x61, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x6e, 0x65, 0x6c, 0x6a, 0x61, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x72,
-0x65, 0x65, 0x64, 0x65, 0x3b, 0x6c, 0x61, 0x75, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x73, 0x75, 0x6e, 0x3b, 0x6d, 0xe1, 0x6e,
-0x3b, 0x74, 0xfd, 0x73, 0x3b, 0x6d, 0x69, 0x6b, 0x3b, 0x68, 0xf3, 0x73, 0x3b, 0x66, 0x72, 0xed, 0x3b, 0x6c, 0x65, 0x79,
-0x3b, 0x73, 0x75, 0x6e, 0x6e, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6d, 0xe1, 0x6e, 0x61, 0x64, 0x61, 0x67, 0x75,
-0x72, 0x3b, 0x74, 0xfd, 0x73, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6d, 0x69, 0x6b, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72,
-0x3b, 0x68, 0xf3, 0x73, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x66, 0x72, 0xed, 0x67, 0x67, 0x6a, 0x61, 0x64, 0x61, 0x67,
-0x75, 0x72, 0x3b, 0x6c, 0x65, 0x79, 0x67, 0x61, 0x72, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x54,
-0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x46, 0x3b, 0x4c, 0x3b, 0x73, 0x75, 0x6e, 0x2e, 0x3b, 0x6d, 0xe1, 0x6e, 0x2e, 0x3b, 0x74,
-0xfd, 0x73, 0x2e, 0x3b, 0x6d, 0x69, 0x6b, 0x2e, 0x3b, 0x68, 0xf3, 0x73, 0x2e, 0x3b, 0x66, 0x72, 0xed, 0x2e, 0x3b, 0x6c,
-0x65, 0x79, 0x2e, 0x3b, 0x73, 0x75, 0x3b, 0x6d, 0x61, 0x3b, 0x74, 0x69, 0x3b, 0x6b, 0x65, 0x3b, 0x74, 0x6f, 0x3b, 0x70,
-0x65, 0x3b, 0x6c, 0x61, 0x3b, 0x73, 0x75, 0x6e, 0x6e, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x3b, 0x6d, 0x61, 0x61, 0x6e, 0x61,
-0x6e, 0x74, 0x61, 0x69, 0x3b, 0x74, 0x69, 0x69, 0x73, 0x74, 0x61, 0x69, 0x3b, 0x6b, 0x65, 0x73, 0x6b, 0x69, 0x76, 0x69,
-0x69, 0x6b, 0x6b, 0x6f, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x69, 0x3b, 0x70, 0x65, 0x72, 0x6a, 0x61, 0x6e, 0x74,
-0x61, 0x69, 0x3b, 0x6c, 0x61, 0x75, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x54, 0x3b, 0x4b, 0x3b,
-0x54, 0x3b, 0x50, 0x3b, 0x4c, 0x3b, 0x73, 0x75, 0x6e, 0x6e, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x6d, 0x61,
-0x61, 0x6e, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x74, 0x69, 0x69, 0x73, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b,
-0x6b, 0x65, 0x73, 0x6b, 0x69, 0x76, 0x69, 0x69, 0x6b, 0x6b, 0x6f, 0x6e, 0x61, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61,
-0x69, 0x6e, 0x61, 0x3b, 0x70, 0x65, 0x72, 0x6a, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x6c, 0x61, 0x75, 0x61,
-0x6e, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x64, 0x69, 0x6d, 0x2e, 0x3b, 0x6c, 0x75, 0x6e, 0x2e, 0x3b, 0x6d, 0x61, 0x72,
-0x2e, 0x3b, 0x6d, 0x65, 0x72, 0x2e, 0x3b, 0x6a, 0x65, 0x75, 0x2e, 0x3b, 0x76, 0x65, 0x6e, 0x2e, 0x3b, 0x73, 0x61, 0x6d,
-0x2e, 0x3b, 0x64, 0x69, 0x6d, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x3b, 0x6c, 0x75, 0x6e, 0x64, 0x69, 0x3b, 0x6d, 0x61, 0x72,
-0x64, 0x69, 0x3b, 0x6d, 0x65, 0x72, 0x63, 0x72, 0x65, 0x64, 0x69, 0x3b, 0x6a, 0x65, 0x75, 0x64, 0x69, 0x3b, 0x76, 0x65,
-0x6e, 0x64, 0x72, 0x65, 0x64, 0x69, 0x3b, 0x73, 0x61, 0x6d, 0x65, 0x64, 0x69, 0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b,
-0x4d, 0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x73, 0x69, 0x3b, 0x6d, 0x6f, 0x3b, 0x74, 0x69, 0x3b, 0x77, 0x6f, 0x3b,
-0x74, 0x6f, 0x3b, 0x66, 0x72, 0x3b, 0x73, 0x6f, 0x3b, 0x73, 0x6e, 0x65, 0x69, 0x6e, 0x3b, 0x6d, 0x6f, 0x61, 0x6e, 0x64,
-0x65, 0x69, 0x3b, 0x74, 0x69, 0x69, 0x73, 0x64, 0x65, 0x69, 0x3b, 0x77, 0x6f, 0x61, 0x6e, 0x73, 0x64, 0x65, 0x69, 0x3b,
-0x74, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x73, 0x64, 0x65, 0x69, 0x3b, 0x66, 0x72, 0x65, 0x65, 0x64, 0x3b, 0x73, 0x6e, 0x65,
-0x6f, 0x6e, 0x3b, 0x44, 0x69, 0x44, 0x3b, 0x44, 0x69, 0x4c, 0x3b, 0x44, 0x69, 0x4d, 0x3b, 0x44, 0x69, 0x43, 0x3b, 0x44,
-0x69, 0x61, 0x3b, 0x44, 0x69, 0x68, 0x3b, 0x44, 0x69, 0x53, 0x3b, 0x44, 0x69, 0x44, 0xf2, 0x6d, 0x68, 0x6e, 0x61, 0x69,
-0x63, 0x68, 0x3b, 0x44, 0x69, 0x4c, 0x75, 0x61, 0x69, 0x6e, 0x3b, 0x44, 0x69, 0x4d, 0xe0, 0x69, 0x72, 0x74, 0x3b, 0x44,
-0x69, 0x43, 0x69, 0x61, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x44, 0x69, 0x61, 0x72, 0x44, 0x61, 0x6f, 0x69, 0x6e, 0x3b, 0x44,
-0x69, 0x68, 0x41, 0x6f, 0x69, 0x6e, 0x65, 0x3b, 0x44, 0x69, 0x53, 0x61, 0x74, 0x68, 0x61, 0x69, 0x72, 0x6e, 0x65, 0x3b,
-0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x43, 0x3b, 0x41, 0x3b, 0x48, 0x3b, 0x53, 0x3b, 0x44, 0x6f, 0x6d, 0x2e, 0x3b, 0x4c,
-0x75, 0x6e, 0x73, 0x3b, 0x4d, 0x61, 0x72, 0x2e, 0x3b, 0x4d, 0xe9, 0x72, 0x2e, 0x3b, 0x58, 0x6f, 0x76, 0x2e, 0x3b, 0x56,
-0x65, 0x6e, 0x2e, 0x3b, 0x53, 0xe1, 0x62, 0x2e, 0x3b, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x4c, 0x75, 0x6e,
-0x73, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x4d, 0xe9, 0x72, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x3b, 0x58, 0x6f,
-0x76, 0x65, 0x73, 0x3b, 0x56, 0x65, 0x6e, 0x72, 0x65, 0x73, 0x3b, 0x53, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x3b, 0x44, 0x3b,
-0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x58, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x64, 0x6f, 0x6d, 0x2e, 0x3b, 0x6c, 0x75, 0x6e,
-0x73, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x6d, 0xe9, 0x72, 0x2e, 0x3b, 0x78, 0x6f, 0x76, 0x2e, 0x3b, 0x76, 0x65, 0x6e,
-0x2e, 0x3b, 0x73, 0xe1, 0x62, 0x2e, 0x3b, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x6c, 0x75, 0x6e, 0x73, 0x3b,
-0x6d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x6d, 0xe9, 0x72, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x3b, 0x78, 0x6f, 0x76, 0x65,
-0x73, 0x3b, 0x76, 0x65, 0x6e, 0x72, 0x65, 0x73, 0x3b, 0x73, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x3b, 0x64, 0x2e, 0x3b, 0x6c,
-0x2e, 0x3b, 0x6d, 0x2e, 0x3b, 0x6d, 0x2e, 0x3b, 0x78, 0x2e, 0x3b, 0x76, 0x2e, 0x3b, 0x73, 0x2e, 0x3b, 0x10d9, 0x10d5, 0x10d8,
-0x3b, 0x10dd, 0x10e0, 0x10e8, 0x3b, 0x10e1, 0x10d0, 0x10db, 0x3b, 0x10dd, 0x10d7, 0x10ee, 0x3b, 0x10ee, 0x10e3, 0x10d7, 0x3b, 0x10de, 0x10d0, 0x10e0,
-0x3b, 0x10e8, 0x10d0, 0x10d1, 0x3b, 0x10d9, 0x10d5, 0x10d8, 0x10e0, 0x10d0, 0x3b, 0x10dd, 0x10e0, 0x10e8, 0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8, 0x3b,
-0x10e1, 0x10d0, 0x10db, 0x10e8, 0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8, 0x3b, 0x10dd, 0x10d7, 0x10ee, 0x10e8, 0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8, 0x3b,
-0x10ee, 0x10e3, 0x10d7, 0x10e8, 0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8, 0x3b, 0x10de, 0x10d0, 0x10e0, 0x10d0, 0x10e1, 0x10d9, 0x10d4, 0x10d5, 0x10d8, 0x3b,
-0x10e8, 0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8, 0x3b, 0x10d9, 0x3b, 0x10dd, 0x3b, 0x10e1, 0x3b, 0x10dd, 0x3b, 0x10ee, 0x3b, 0x10de, 0x3b, 0x10e8,
-0x3b, 0x53, 0x6f, 0x3b, 0x4d, 0x6f, 0x3b, 0x44, 0x69, 0x3b, 0x4d, 0x69, 0x3b, 0x44, 0x6f, 0x3b, 0x46, 0x72, 0x3b, 0x53,
-0x61, 0x3b, 0x53, 0x6f, 0x6e, 0x6e, 0x74, 0x61, 0x67, 0x3b, 0x4d, 0x6f, 0x6e, 0x74, 0x61, 0x67, 0x3b, 0x44, 0x69, 0x65,
-0x6e, 0x73, 0x74, 0x61, 0x67, 0x3b, 0x4d, 0x69, 0x74, 0x74, 0x77, 0x6f, 0x63, 0x68, 0x3b, 0x44, 0x6f, 0x6e, 0x6e, 0x65,
-0x72, 0x73, 0x74, 0x61, 0x67, 0x3b, 0x46, 0x72, 0x65, 0x69, 0x74, 0x61, 0x67, 0x3b, 0x53, 0x61, 0x6d, 0x73, 0x74, 0x61,
-0x67, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x46, 0x3b, 0x53, 0x3b, 0x53, 0x6f, 0x2e, 0x3b,
-0x4d, 0x6f, 0x2e, 0x3b, 0x44, 0x69, 0x2e, 0x3b, 0x4d, 0x69, 0x2e, 0x3b, 0x44, 0x6f, 0x2e, 0x3b, 0x46, 0x72, 0x2e, 0x3b,
-0x53, 0x61, 0x2e, 0x3b, 0x39a, 0x3c5, 0x3c1, 0x3b, 0x394, 0x3b5, 0x3c5, 0x3b, 0x3a4, 0x3c1, 0x3af, 0x3b, 0x3a4, 0x3b5, 0x3c4, 0x3b,
-0x3a0, 0x3ad, 0x3bc, 0x3b, 0x3a0, 0x3b1, 0x3c1, 0x3b, 0x3a3, 0x3ac, 0x3b2, 0x3b, 0x39a, 0x3c5, 0x3c1, 0x3b9, 0x3b1, 0x3ba, 0x3ae, 0x3b,
-0x394, 0x3b5, 0x3c5, 0x3c4, 0x3ad, 0x3c1, 0x3b1, 0x3b, 0x3a4, 0x3c1, 0x3af, 0x3c4, 0x3b7, 0x3b, 0x3a4, 0x3b5, 0x3c4, 0x3ac, 0x3c1, 0x3c4,
-0x3b7, 0x3b, 0x3a0, 0x3ad, 0x3bc, 0x3c0, 0x3c4, 0x3b7, 0x3b, 0x3a0, 0x3b1, 0x3c1, 0x3b1, 0x3c3, 0x3ba, 0x3b5, 0x3c5, 0x3ae, 0x3b, 0x3a3,
-0x3ac, 0x3b2, 0x3b2, 0x3b1, 0x3c4, 0x3bf, 0x3b, 0x39a, 0x3b, 0x394, 0x3b, 0x3a4, 0x3b, 0x3a4, 0x3b, 0x3a0, 0x3b, 0x3a0, 0x3b, 0x3a3,
-0x3b, 0x73, 0x61, 0x62, 0x3b, 0x61, 0x74, 0x61, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x70, 0x69, 0x6e, 0x3b, 0x73, 0x69, 0x73,
-0x3b, 0x74, 0x61, 0x6c, 0x3b, 0x61, 0x72, 0x66, 0x3b, 0x73, 0x61, 0x62, 0x61, 0x61, 0x74, 0x3b, 0x61, 0x74, 0x61, 0x61,
-0x73, 0x69, 0x6e, 0x6e, 0x67, 0x6f, 0x72, 0x6e, 0x65, 0x71, 0x3b, 0x6d, 0x61, 0x72, 0x6c, 0x75, 0x6e, 0x6e, 0x67, 0x6f,
-0x72, 0x6e, 0x65, 0x71, 0x3b, 0x70, 0x69, 0x6e, 0x67, 0x61, 0x73, 0x75, 0x6e, 0x6e, 0x67, 0x6f, 0x72, 0x6e, 0x65, 0x71,
-0x3b, 0x73, 0x69, 0x73, 0x61, 0x6d, 0x61, 0x6e, 0x6e, 0x67, 0x6f, 0x72, 0x6e, 0x65, 0x71, 0x3b, 0x74, 0x61, 0x6c, 0x6c,
-0x69, 0x6d, 0x61, 0x6e, 0x6e, 0x67, 0x6f, 0x72, 0x6e, 0x65, 0x71, 0x3b, 0x61, 0x72, 0x66, 0x69, 0x6e, 0x69, 0x6e, 0x6e,
-0x67, 0x6f, 0x72, 0x6e, 0x65, 0x71, 0x3b, 0x53, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x41,
-0x3b, 0xab0, 0xab5, 0xabf, 0x3b, 0xab8, 0xacb, 0xaae, 0x3b, 0xaae, 0xa82, 0xa97, 0xab3, 0x3b, 0xaac, 0xac1, 0xaa7, 0x3b, 0xa97, 0xac1,
-0xab0, 0xac1, 0x3b, 0xab6, 0xac1, 0xa95, 0xacd, 0xab0, 0x3b, 0xab6, 0xaa8, 0xabf, 0x3b, 0xab0, 0xab5, 0xabf, 0xab5, 0xabe, 0xab0, 0x3b,
-0xab8, 0xacb, 0xaae, 0xab5, 0xabe, 0xab0, 0x3b, 0xaae, 0xa82, 0xa97, 0xab3, 0xab5, 0xabe, 0xab0, 0x3b, 0xaac, 0xac1, 0xaa7, 0xab5, 0xabe,
-0xab0, 0x3b, 0xa97, 0xac1, 0xab0, 0xac1, 0xab5, 0xabe, 0xab0, 0x3b, 0xab6, 0xac1, 0xa95, 0xacd, 0xab0, 0xab5, 0xabe, 0xab0, 0x3b, 0xab6,
-0xaa8, 0xabf, 0xab5, 0xabe, 0xab0, 0x3b, 0xab0, 0x3b, 0xab8, 0xacb, 0x3b, 0xaae, 0xa82, 0x3b, 0xaac, 0xac1, 0x3b, 0xa97, 0xac1, 0x3b,
-0xab6, 0xac1, 0x3b, 0xab6, 0x3b, 0x4c, 0x61, 0x68, 0x3b, 0x4c, 0x69, 0x74, 0x3b, 0x54, 0x61, 0x6c, 0x3b, 0x4c, 0x61, 0x72,
-0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x41, 0x73, 0x61, 0x3b, 0x4c, 0x61, 0x68, 0x61, 0x64, 0x69, 0x3b,
-0x4c, 0x69, 0x74, 0x69, 0x6e, 0x69, 0x6e, 0x3b, 0x54, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b, 0x4c, 0x61, 0x72, 0x61, 0x62,
-0x61, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x3b, 0x4a, 0x75, 0x6d, 0x6d, 0x61, 0x2bc, 0x61, 0x3b, 0x41, 0x73,
-0x61, 0x62, 0x61, 0x72, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x41, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x5d9,
-0x5d5, 0x5dd, 0x20, 0x5d0, 0x5f3, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d1, 0x5f3, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d2, 0x5f3, 0x3b,
-0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d3, 0x5f3, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d4, 0x5f3, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d5, 0x5f3,
-0x3b, 0x5e9, 0x5d1, 0x5ea, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e8, 0x5d0, 0x5e9, 0x5d5, 0x5df, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e9,
-0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e9, 0x5dc, 0x5d9, 0x5e9, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e8, 0x5d1, 0x5d9,
-0x5e2, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d7, 0x5de, 0x5d9, 0x5e9, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e9, 0x5d9, 0x5e9,
-0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e9, 0x5d1, 0x5ea, 0x3b, 0x5d0, 0x5f3, 0x3b, 0x5d1, 0x5f3, 0x3b, 0x5d2, 0x5f3, 0x3b, 0x5d3,
-0x5f3, 0x3b, 0x5d4, 0x5f3, 0x3b, 0x5d5, 0x5f3, 0x3b, 0x5e9, 0x5f3, 0x3b, 0x930, 0x935, 0x93f, 0x3b, 0x938, 0x94b, 0x92e, 0x3b, 0x92e,
-0x902, 0x917, 0x932, 0x3b, 0x92c, 0x941, 0x927, 0x3b, 0x917, 0x941, 0x930, 0x941, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x3b, 0x936,
-0x928, 0x93f, 0x3b, 0x930, 0x935, 0x93f, 0x935, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e, 0x935, 0x93e, 0x930, 0x3b, 0x92e, 0x902, 0x917,
-0x932, 0x935, 0x93e, 0x930, 0x3b, 0x92c, 0x941, 0x927, 0x935, 0x93e, 0x930, 0x3b, 0x917, 0x941, 0x930, 0x941, 0x935, 0x93e, 0x930, 0x3b,
-0x936, 0x941, 0x915, 0x94d, 0x930, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x935, 0x93e, 0x930, 0x3b, 0x930, 0x3b, 0x938, 0x94b,
-0x3b, 0x92e, 0x902, 0x3b, 0x92c, 0x941, 0x3b, 0x917, 0x941, 0x3b, 0x936, 0x941, 0x3b, 0x936, 0x3b, 0x56, 0x3b, 0x48, 0x3b, 0x4b,
-0x3b, 0x53, 0x7a, 0x65, 0x3b, 0x43, 0x73, 0x3b, 0x50, 0x3b, 0x53, 0x7a, 0x6f, 0x3b, 0x76, 0x61, 0x73, 0xe1, 0x72, 0x6e,
-0x61, 0x70, 0x3b, 0x68, 0xe9, 0x74, 0x66, 0x151, 0x3b, 0x6b, 0x65, 0x64, 0x64, 0x3b, 0x73, 0x7a, 0x65, 0x72, 0x64, 0x61,
-0x3b, 0x63, 0x73, 0xfc, 0x74, 0xf6, 0x72, 0x74, 0xf6, 0x6b, 0x3b, 0x70, 0xe9, 0x6e, 0x74, 0x65, 0x6b, 0x3b, 0x73, 0x7a,
-0x6f, 0x6d, 0x62, 0x61, 0x74, 0x3b, 0x56, 0x3b, 0x48, 0x3b, 0x4b, 0x3b, 0x53, 0x7a, 0x3b, 0x43, 0x73, 0x3b, 0x50, 0x3b,
-0x53, 0x7a, 0x3b, 0x73, 0x75, 0x6e, 0x2e, 0x3b, 0x6d, 0xe1, 0x6e, 0x2e, 0x3b, 0xfe, 0x72, 0x69, 0x2e, 0x3b, 0x6d, 0x69,
-0xf0, 0x2e, 0x3b, 0x66, 0x69, 0x6d, 0x2e, 0x3b, 0x66, 0xf6, 0x73, 0x2e, 0x3b, 0x6c, 0x61, 0x75, 0x2e, 0x3b, 0x73, 0x75,
-0x6e, 0x6e, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6d, 0xe1, 0x6e, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0xfe,
-0x72, 0x69, 0xf0, 0x6a, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6d, 0x69, 0xf0, 0x76, 0x69, 0x6b, 0x75, 0x64, 0x61,
-0x67, 0x75, 0x72, 0x3b, 0x66, 0x69, 0x6d, 0x6d, 0x74, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x66, 0xf6, 0x73, 0x74,
-0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6c, 0x61, 0x75, 0x67, 0x61, 0x72, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x53,
-0x3b, 0x4d, 0x3b, 0xde, 0x3b, 0x4d, 0x3b, 0x46, 0x3b, 0x46, 0x3b, 0x4c, 0x3b, 0x4d, 0x69, 0x6e, 0x3b, 0x53, 0x65, 0x6e,
-0x3b, 0x53, 0x65, 0x6c, 0x3b, 0x52, 0x61, 0x62, 0x3b, 0x4b, 0x61, 0x6d, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x53, 0x61, 0x62,
-0x3b, 0x4d, 0x69, 0x6e, 0x67, 0x67, 0x75, 0x3b, 0x53, 0x65, 0x6e, 0x69, 0x6e, 0x3b, 0x53, 0x65, 0x6c, 0x61, 0x73, 0x61,
-0x3b, 0x52, 0x61, 0x62, 0x75, 0x3b, 0x4b, 0x61, 0x6d, 0x69, 0x73, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x3b, 0x53, 0x61,
-0x62, 0x74, 0x75, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x52, 0x3b, 0x4b, 0x3b, 0x4a, 0x3b, 0x53, 0x3b, 0x44, 0x6f,
-0x6d, 0x68, 0x3b, 0x4c, 0x75, 0x61, 0x6e, 0x3b, 0x4d, 0xe1, 0x69, 0x72, 0x74, 0x3b, 0x43, 0xe9, 0x61, 0x64, 0x3b, 0x44,
-0xe9, 0x61, 0x72, 0x3b, 0x41, 0x6f, 0x69, 0x6e, 0x65, 0x3b, 0x53, 0x61, 0x74, 0x68, 0x3b, 0x44, 0xe9, 0x20, 0x44, 0x6f,
-0x6d, 0x68, 0x6e, 0x61, 0x69, 0x67, 0x68, 0x3b, 0x44, 0xe9, 0x20, 0x4c, 0x75, 0x61, 0x69, 0x6e, 0x3b, 0x44, 0xe9, 0x20,
-0x4d, 0xe1, 0x69, 0x72, 0x74, 0x3b, 0x44, 0xe9, 0x20, 0x43, 0xe9, 0x61, 0x64, 0x61, 0x6f, 0x69, 0x6e, 0x3b, 0x44, 0xe9,
-0x61, 0x72, 0x64, 0x61, 0x6f, 0x69, 0x6e, 0x3b, 0x44, 0xe9, 0x20, 0x68, 0x41, 0x6f, 0x69, 0x6e, 0x65, 0x3b, 0x44, 0xe9,
-0x20, 0x53, 0x61, 0x74, 0x68, 0x61, 0x69, 0x72, 0x6e, 0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x43, 0x3b, 0x44, 0x3b,
-0x41, 0x3b, 0x53, 0x3b, 0x64, 0x6f, 0x6d, 0x3b, 0x6c, 0x75, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d, 0x65, 0x72, 0x3b,
-0x67, 0x69, 0x6f, 0x3b, 0x76, 0x65, 0x6e, 0x3b, 0x73, 0x61, 0x62, 0x3b, 0x64, 0x6f, 0x6d, 0x65, 0x6e, 0x69, 0x63, 0x61,
-0x3b, 0x6c, 0x75, 0x6e, 0x65, 0x64, 0xec, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x65, 0x64, 0xec, 0x3b, 0x6d, 0x65, 0x72, 0x63,
-0x6f, 0x6c, 0x65, 0x64, 0xec, 0x3b, 0x67, 0x69, 0x6f, 0x76, 0x65, 0x64, 0xec, 0x3b, 0x76, 0x65, 0x6e, 0x65, 0x72, 0x64,
-0xec, 0x3b, 0x73, 0x61, 0x62, 0x61, 0x74, 0x6f, 0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x56,
-0x3b, 0x53, 0x3b, 0x65e5, 0x3b, 0x6708, 0x3b, 0x706b, 0x3b, 0x6c34, 0x3b, 0x6728, 0x3b, 0x91d1, 0x3b, 0x571f, 0x3b, 0x65e5, 0x66dc, 0x65e5,
-0x3b, 0x6708, 0x66dc, 0x65e5, 0x3b, 0x706b, 0x66dc, 0x65e5, 0x3b, 0x6c34, 0x66dc, 0x65e5, 0x3b, 0x6728, 0x66dc, 0x65e5, 0x3b, 0x91d1, 0x66dc, 0x65e5,
-0x3b, 0x571f, 0x66dc, 0x65e5, 0x3b, 0xcad, 0xcbe, 0xca8, 0xcc1, 0x3b, 0xcb8, 0xccb, 0xcae, 0x3b, 0xcae, 0xc82, 0xc97, 0xcb3, 0x3b, 0xcac,
-0xcc1, 0xca7, 0x3b, 0xc97, 0xcc1, 0xcb0, 0xcc1, 0x3b, 0xcb6, 0xcc1, 0xc95, 0xccd, 0xcb0, 0x3b, 0xcb6, 0xca8, 0xcbf, 0x3b, 0xcad, 0xcbe,
-0xca8, 0xcc1, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcb8, 0xccb, 0xcae, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcae, 0xc82, 0xc97, 0xcb3, 0xcb5, 0xcbe, 0xcb0,
-0x3b, 0xcac, 0xcc1, 0xca7, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xc97, 0xcc1, 0xcb0, 0xcc1, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcb6, 0xcc1, 0xc95, 0xccd,
-0xcb0, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcb6, 0xca8, 0xcbf, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcad, 0xcbe, 0x3b, 0xcb8, 0xccb, 0x3b, 0xcae, 0xc82,
-0x3b, 0xcac, 0xcc1, 0x3b, 0xc97, 0xcc1, 0x3b, 0xcb6, 0xcc1, 0x3b, 0xcb6, 0x3b, 0x622, 0x62a, 0x6be, 0x648, 0x627, 0x631, 0x3b, 0x698,
-0x654, 0x646, 0x65b, 0x62f, 0x655, 0x631, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x648, 0x65a, 0x645, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x648,
-0x62f, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x631, 0x65b, 0x66e, 0x6ea, 0x633, 0x648, 0x627, 0x631, 0x3b, 0x62c, 0x64f, 0x645, 0x6c1, 0x3b,
-0x628, 0x679, 0x648, 0x627, 0x631, 0x3b, 0x627, 0x64e, 0x62a, 0x6be, 0x648, 0x627, 0x631, 0x3b, 0x698, 0x654, 0x646, 0x65b, 0x62f, 0x631,
-0x655, 0x631, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x648, 0x65a, 0x645, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x648, 0x62f, 0x648, 0x627, 0x631,
-0x3b, 0x628, 0x631, 0x65b, 0x66e, 0x6ea, 0x633, 0x648, 0x627, 0x631, 0x3b, 0x62c, 0x64f, 0x645, 0x6c1, 0x3b, 0x628, 0x679, 0x648, 0x627,
-0x631, 0x3b, 0x627, 0x3b, 0x698, 0x3b, 0x628, 0x3b, 0x628, 0x3b, 0x628, 0x3b, 0x62c, 0x3b, 0x628, 0x3b, 0x416, 0x441, 0x3b, 0x414,
-0x441, 0x3b, 0x421, 0x441, 0x3b, 0x421, 0x440, 0x3b, 0x411, 0x441, 0x3b, 0x416, 0x43c, 0x3b, 0x421, 0x431, 0x3b, 0x416, 0x435, 0x43a,
-0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x414, 0x4af, 0x439, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x421, 0x435, 0x439, 0x441, 0x435,
-0x43d, 0x431, 0x456, 0x3b, 0x421, 0x4d9, 0x440, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x411, 0x435, 0x439, 0x441, 0x435, 0x43d, 0x431,
-0x456, 0x3b, 0x416, 0x4b1, 0x43c, 0x430, 0x3b, 0x421, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x416, 0x3b, 0x414, 0x3b, 0x421, 0x3b, 0x421,
-0x3b, 0x411, 0x3b, 0x416, 0x3b, 0x421, 0x3b, 0x436, 0x435, 0x43a, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x434, 0x4af, 0x439, 0x441,
-0x435, 0x43d, 0x431, 0x456, 0x3b, 0x441, 0x435, 0x439, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x441, 0x4d9, 0x440, 0x441, 0x435, 0x43d,
-0x431, 0x456, 0x3b, 0x431, 0x435, 0x439, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x436, 0x4b1, 0x43c, 0x430, 0x3b, 0x441, 0x435, 0x43d,
-0x431, 0x456, 0x3b, 0x63, 0x79, 0x75, 0x2e, 0x3b, 0x6d, 0x62, 0x65, 0x2e, 0x3b, 0x6b, 0x61, 0x62, 0x2e, 0x3b, 0x67, 0x74,
-0x75, 0x2e, 0x3b, 0x6b, 0x61, 0x6e, 0x2e, 0x3b, 0x67, 0x6e, 0x75, 0x2e, 0x3b, 0x67, 0x6e, 0x64, 0x2e, 0x3b, 0x4b, 0x75,
-0x20, 0x63, 0x79, 0x75, 0x6d, 0x77, 0x65, 0x72, 0x75, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x6d, 0x62, 0x65, 0x72, 0x65,
-0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x67, 0x61,
-0x74, 0x61, 0x74, 0x75, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x65, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20,
-0x67, 0x61, 0x74, 0x61, 0x6e, 0x75, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x74,
-0x75, 0x3b, 0x436, 0x435, 0x43a, 0x2e, 0x3b, 0x434, 0x4af, 0x439, 0x2e, 0x3b, 0x448, 0x435, 0x439, 0x448, 0x2e, 0x3b, 0x448, 0x430,
-0x440, 0x448, 0x2e, 0x3b, 0x431, 0x435, 0x439, 0x448, 0x2e, 0x3b, 0x436, 0x443, 0x43c, 0x430, 0x3b, 0x438, 0x448, 0x43c, 0x2e, 0x3b,
-0x436, 0x435, 0x43a, 0x448, 0x435, 0x43c, 0x431, 0x438, 0x3b, 0x434, 0x4af, 0x439, 0x448, 0x4e9, 0x43c, 0x431, 0x4af, 0x3b, 0x448, 0x435,
-0x439, 0x448, 0x435, 0x43c, 0x431, 0x438, 0x3b, 0x448, 0x430, 0x440, 0x448, 0x435, 0x43c, 0x431, 0x438, 0x3b, 0x431, 0x435, 0x439, 0x448,
-0x435, 0x43c, 0x431, 0x438, 0x3b, 0x436, 0x443, 0x43c, 0x430, 0x3b, 0x438, 0x448, 0x435, 0x43c, 0x431, 0x438, 0x3b, 0x416, 0x3b, 0x414,
-0x3b, 0x428, 0x3b, 0x428, 0x3b, 0x411, 0x3b, 0x416, 0x3b, 0x418, 0x3b, 0xc77c, 0x3b, 0xc6d4, 0x3b, 0xd654, 0x3b, 0xc218, 0x3b, 0xbaa9,
-0x3b, 0xae08, 0x3b, 0xd1a0, 0x3b, 0xc77c, 0xc694, 0xc77c, 0x3b, 0xc6d4, 0xc694, 0xc77c, 0x3b, 0xd654, 0xc694, 0xc77c, 0x3b, 0xc218, 0xc694, 0xc77c,
-0x3b, 0xbaa9, 0xc694, 0xc77c, 0x3b, 0xae08, 0xc694, 0xc77c, 0x3b, 0xd1a0, 0xc694, 0xc77c, 0x3b, 0x63, 0x75, 0x2e, 0x3b, 0x6d, 0x62, 0x65,
-0x2e, 0x3b, 0x6b, 0x61, 0x62, 0x2e, 0x3b, 0x67, 0x74, 0x75, 0x2e, 0x3b, 0x6b, 0x61, 0x6e, 0x2e, 0x3b, 0x67, 0x6e, 0x75,
-0x2e, 0x3b, 0x67, 0x6e, 0x64, 0x2e, 0x3b, 0x4b, 0x75, 0x20, 0x77, 0x2019, 0x69, 0x6e, 0x64, 0x77, 0x69, 0x3b, 0x4b, 0x75,
-0x20, 0x77, 0x61, 0x20, 0x6d, 0x62, 0x65, 0x72, 0x65, 0x3b, 0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x62, 0x69,
-0x72, 0x69, 0x3b, 0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4b, 0x75, 0x20, 0x77,
-0x61, 0x20, 0x6b, 0x61, 0x6e, 0x65, 0x3b, 0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x75, 0x3b,
-0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x74, 0x75, 0x3b, 0xead, 0xeb2, 0xe97, 0xeb4,
-0xe94, 0x3b, 0xe88, 0xeb1, 0xe99, 0x3b, 0xead, 0xeb1, 0xe87, 0xe84, 0xeb2, 0xe99, 0x3b, 0xe9e, 0xeb8, 0xe94, 0x3b, 0xe9e, 0xeb0, 0xeab,
-0xeb1, 0xe94, 0x3b, 0xeaa, 0xeb8, 0xe81, 0x3b, 0xec0, 0xeaa, 0xebb, 0xeb2, 0x3b, 0xea7, 0xeb1, 0xe99, 0xead, 0xeb2, 0xe97, 0xeb4, 0xe94,
-0x3b, 0xea7, 0xeb1, 0xe99, 0xe88, 0xeb1, 0xe99, 0x3b, 0xea7, 0xeb1, 0xe99, 0xead, 0xeb1, 0xe87, 0xe84, 0xeb2, 0xe99, 0x3b, 0xea7, 0xeb1,
-0xe99, 0xe9e, 0xeb8, 0xe94, 0x3b, 0xea7, 0xeb1, 0xe99, 0xe9e, 0xeb0, 0xeab, 0xeb1, 0xe94, 0x3b, 0xea7, 0xeb1, 0xe99, 0xeaa, 0xeb8, 0xe81,
-0x3b, 0xea7, 0xeb1, 0xe99, 0xec0, 0xeaa, 0xebb, 0xeb2, 0x3b, 0xead, 0xeb2, 0x3b, 0xe88, 0x3b, 0xead, 0x3b, 0xe9e, 0x3b, 0xe9e, 0xeab,
-0x3b, 0xeaa, 0xeb8, 0x3b, 0xeaa, 0x3b, 0x53, 0x76, 0x113, 0x74, 0x64, 0x2e, 0x3b, 0x50, 0x69, 0x72, 0x6d, 0x64, 0x2e, 0x3b,
-0x4f, 0x74, 0x72, 0x64, 0x2e, 0x3b, 0x54, 0x72, 0x65, 0x161, 0x64, 0x2e, 0x3b, 0x43, 0x65, 0x74, 0x75, 0x72, 0x74, 0x64,
-0x2e, 0x3b, 0x50, 0x69, 0x65, 0x6b, 0x74, 0x64, 0x2e, 0x3b, 0x53, 0x65, 0x73, 0x74, 0x64, 0x2e, 0x3b, 0x53, 0x76, 0x113,
-0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x50, 0x69, 0x72, 0x6d, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x4f, 0x74, 0x72,
-0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x54, 0x72, 0x65, 0x161, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x43, 0x65, 0x74, 0x75,
-0x72, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x50, 0x69, 0x65, 0x6b, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x53,
-0x65, 0x73, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x53, 0x3b, 0x50, 0x3b, 0x4f, 0x3b, 0x54, 0x3b, 0x43, 0x3b, 0x50,
-0x3b, 0x53, 0x3b, 0x73, 0x76, 0x113, 0x74, 0x64, 0x2e, 0x3b, 0x70, 0x69, 0x72, 0x6d, 0x64, 0x2e, 0x3b, 0x6f, 0x74, 0x72,
-0x64, 0x2e, 0x3b, 0x74, 0x72, 0x65, 0x161, 0x64, 0x2e, 0x3b, 0x63, 0x65, 0x74, 0x75, 0x72, 0x74, 0x64, 0x2e, 0x3b, 0x70,
-0x69, 0x65, 0x6b, 0x74, 0x64, 0x2e, 0x3b, 0x73, 0x65, 0x73, 0x74, 0x64, 0x2e, 0x3b, 0x73, 0x76, 0x113, 0x74, 0x64, 0x69,
-0x65, 0x6e, 0x61, 0x3b, 0x70, 0x69, 0x72, 0x6d, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x6f, 0x74, 0x72, 0x64, 0x69, 0x65,
-0x6e, 0x61, 0x3b, 0x74, 0x72, 0x65, 0x161, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x63, 0x65, 0x74, 0x75, 0x72, 0x74, 0x64,
-0x69, 0x65, 0x6e, 0x61, 0x3b, 0x70, 0x69, 0x65, 0x6b, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x73, 0x65, 0x73, 0x74,
-0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x65, 0x79, 0x65, 0x3b, 0x79, 0x62, 0x6f, 0x3b, 0x6d, 0x62, 0x6c, 0x3b, 0x6d, 0x73,
-0x74, 0x3b, 0x6d, 0x69, 0x6e, 0x3b, 0x6d, 0x74, 0x6e, 0x3b, 0x6d, 0x70, 0x73, 0x3b, 0x65, 0x79, 0x65, 0x6e, 0x67, 0x61,
-0x3b, 0x6d, 0x6f, 0x6b, 0x254, 0x6c, 0x254, 0x20, 0x6d, 0x77, 0x61, 0x20, 0x79, 0x61, 0x6d, 0x62, 0x6f, 0x3b, 0x6d, 0x6f,
-0x6b, 0x254, 0x6c, 0x254, 0x20, 0x6d, 0x77, 0x61, 0x20, 0x6d, 0xed, 0x62, 0x61, 0x6c, 0xe9, 0x3b, 0x6d, 0x6f, 0x6b, 0x254,
-0x6c, 0x254, 0x20, 0x6d, 0x77, 0x61, 0x20, 0x6d, 0xed, 0x73, 0xe1, 0x74, 0x6f, 0x3b, 0x6d, 0x6f, 0x6b, 0x254, 0x6c, 0x254,
-0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x6e, 0xe9, 0x69, 0x3b, 0x6d, 0x6f, 0x6b, 0x254, 0x6c, 0x254, 0x20, 0x79, 0x61, 0x20,
-0x6d, 0xed, 0x74, 0xe1, 0x6e, 0x6f, 0x3b, 0x6d, 0x70, 0x254, 0x301, 0x73, 0x254, 0x3b, 0x65, 0x3b, 0x79, 0x3b, 0x6d, 0x3b,
-0x6d, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x70, 0x3b, 0x73, 0x6b, 0x3b, 0x70, 0x72, 0x3b, 0x61, 0x6e, 0x3b, 0x74, 0x72, 0x3b,
-0x6b, 0x74, 0x3b, 0x70, 0x6e, 0x3b, 0x161, 0x74, 0x3b, 0x73, 0x65, 0x6b, 0x6d, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73,
-0x3b, 0x70, 0x69, 0x72, 0x6d, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x61, 0x6e, 0x74, 0x72, 0x61, 0x64, 0x69,
-0x65, 0x6e, 0x69, 0x73, 0x3b, 0x74, 0x72, 0x65, 0x10d, 0x69, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x6b, 0x65,
-0x74, 0x76, 0x69, 0x72, 0x74, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x70, 0x65, 0x6e, 0x6b, 0x74, 0x61, 0x64,
-0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x161, 0x65, 0x161, 0x74, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x53, 0x3b,
-0x50, 0x3b, 0x41, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x50, 0x3b, 0x160, 0x3b, 0x43d, 0x435, 0x434, 0x2e, 0x3b, 0x43f, 0x43e, 0x43d,
-0x2e, 0x3b, 0x432, 0x442, 0x43e, 0x2e, 0x3b, 0x441, 0x440, 0x435, 0x2e, 0x3b, 0x447, 0x435, 0x442, 0x2e, 0x3b, 0x43f, 0x435, 0x442,
-0x2e, 0x3b, 0x441, 0x430, 0x431, 0x2e, 0x3b, 0x43d, 0x435, 0x434, 0x435, 0x43b, 0x430, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435,
-0x43b, 0x43d, 0x438, 0x43a, 0x3b, 0x432, 0x442, 0x43e, 0x440, 0x43d, 0x438, 0x43a, 0x3b, 0x441, 0x440, 0x435, 0x434, 0x430, 0x3b, 0x447,
-0x435, 0x442, 0x432, 0x440, 0x442, 0x43e, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x43e, 0x43a, 0x3b, 0x441, 0x430, 0x431, 0x43e, 0x442, 0x430,
-0x3b, 0x43d, 0x435, 0x434, 0x2e, 0x3b, 0x43f, 0x43e, 0x43d, 0x2e, 0x3b, 0x432, 0x442, 0x2e, 0x3b, 0x441, 0x440, 0x435, 0x2e, 0x3b,
-0x447, 0x435, 0x442, 0x2e, 0x3b, 0x43f, 0x435, 0x442, 0x2e, 0x3b, 0x441, 0x430, 0x431, 0x2e, 0x3b, 0x41, 0x6c, 0x61, 0x68, 0x3b,
-0x41, 0x6c, 0x61, 0x74, 0x73, 0x3b, 0x54, 0x61, 0x6c, 0x3b, 0x41, 0x6c, 0x61, 0x72, 0x3b, 0x41, 0x6c, 0x61, 0x6b, 0x3b,
-0x5a, 0x6f, 0x6d, 0x3b, 0x41, 0x73, 0x61, 0x62, 0x3b, 0x41, 0x6c, 0x61, 0x68, 0x61, 0x64, 0x79, 0x3b, 0x41, 0x6c, 0x61,
-0x74, 0x73, 0x69, 0x6e, 0x61, 0x69, 0x6e, 0x79, 0x3b, 0x54, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x72,
-0x6f, 0x62, 0x69, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x6b, 0x61, 0x6d, 0x69, 0x73, 0x79, 0x3b, 0x5a, 0x6f, 0x6d, 0x61, 0x3b,
-0x41, 0x73, 0x61, 0x62, 0x6f, 0x74, 0x73, 0x79, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x5a,
-0x3b, 0x41, 0x3b, 0x41, 0x68, 0x64, 0x3b, 0x49, 0x73, 0x6e, 0x3b, 0x53, 0x65, 0x6c, 0x3b, 0x52, 0x61, 0x62, 0x3b, 0x4b,
-0x68, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x41, 0x68, 0x61, 0x64, 0x3b, 0x49, 0x73, 0x6e, 0x69,
-0x6e, 0x3b, 0x53, 0x65, 0x6c, 0x61, 0x73, 0x61, 0x3b, 0x52, 0x61, 0x62, 0x75, 0x3b, 0x4b, 0x68, 0x61, 0x6d, 0x69, 0x73,
-0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x74, 0x3b, 0x53, 0x61, 0x62, 0x74, 0x75, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x53, 0x3b,
-0x52, 0x3b, 0x4b, 0x3b, 0x4a, 0x3b, 0x53, 0x3b, 0xd1e, 0xd3e, 0xd2f, 0xd7c, 0x3b, 0xd24, 0xd3f, 0xd19, 0xd4d, 0xd15, 0xd7e, 0x3b,
-0xd1a, 0xd4a, 0xd35, 0xd4d, 0xd35, 0x3b, 0xd2c, 0xd41, 0xd27, 0xd7b, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e, 0xd34, 0xd02, 0x3b, 0xd35, 0xd46,
-0xd33, 0xd4d, 0xd33, 0xd3f, 0x3b, 0xd36, 0xd28, 0xd3f, 0x3b, 0xd1e, 0xd3e, 0xd2f, 0xd31, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd24,
-0xd3f, 0xd19, 0xd4d, 0xd15, 0xd33, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd1a, 0xd4a, 0xd35, 0xd4d, 0xd35, 0xd3e, 0xd34, 0xd4d, 0x200c,
-0xd1a, 0x3b, 0xd2c, 0xd41, 0xd27, 0xd28, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e, 0xd34, 0xd3e, 0xd34, 0xd4d,
-0x200c, 0xd1a, 0x3b, 0xd35, 0xd46, 0xd33, 0xd4d, 0xd33, 0xd3f, 0xd2f, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd36, 0xd28, 0xd3f, 0xd2f,
-0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd1e, 0xd3e, 0x3b, 0xd24, 0xd3f, 0x3b, 0xd1a, 0xd4a, 0x3b, 0xd2c, 0xd41, 0x3b, 0xd35, 0xd4d,
-0xd2f, 0xd3e, 0x3b, 0xd35, 0xd46, 0x3b, 0xd36, 0x3b, 0xd1e, 0xd3e, 0xd2f, 0xd31, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd24, 0xd3f,
-0xd19, 0xd4d, 0xd15, 0xd33, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd1a, 0xd4a, 0xd35, 0xd4d, 0xd35, 0xd3e, 0xd34, 0xd4d, 0xd1a, 0x3b,
-0xd2c, 0xd41, 0xd27, 0xd28, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e, 0xd34, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a,
-0x3b, 0xd35, 0xd46, 0xd33, 0xd4d, 0xd33, 0xd3f, 0xd2f, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd36, 0xd28, 0xd3f, 0xd2f, 0xd3e, 0xd34,
-0xd4d, 0x200c, 0xd1a, 0x3b, 0xd1e, 0x3b, 0xd24, 0xd3f, 0x3b, 0xd1a, 0xd4a, 0x3b, 0xd2c, 0xd41, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e, 0x3b,
-0xd35, 0xd46, 0x3b, 0xd36, 0x3b, 0x126, 0x61, 0x64, 0x3b, 0x54, 0x6e, 0x65, 0x3b, 0x54, 0x6c, 0x69, 0x3b, 0x45, 0x72, 0x62,
-0x3b, 0x126, 0x61, 0x6d, 0x3b, 0x120, 0x69, 0x6d, 0x3b, 0x53, 0x69, 0x62, 0x3b, 0x49, 0x6c, 0x2d, 0x126, 0x61, 0x64, 0x64,
-0x3b, 0x49, 0x74, 0x2d, 0x54, 0x6e, 0x65, 0x6a, 0x6e, 0x3b, 0x49, 0x74, 0x2d, 0x54, 0x6c, 0x69, 0x65, 0x74, 0x61, 0x3b,
-0x4c, 0x2d, 0x45, 0x72, 0x62, 0x67, 0x127, 0x61, 0x3b, 0x49, 0x6c, 0x2d, 0x126, 0x61, 0x6d, 0x69, 0x73, 0x3b, 0x49, 0x6c,
-0x2d, 0x120, 0x69, 0x6d, 0x67, 0x127, 0x61, 0x3b, 0x49, 0x73, 0x2d, 0x53, 0x69, 0x62, 0x74, 0x3b, 0x126, 0x64, 0x3b, 0x54,
-0x6e, 0x3b, 0x54, 0x6c, 0x3b, 0x45, 0x72, 0x3b, 0x126, 0x6d, 0x3b, 0x120, 0x6d, 0x3b, 0x53, 0x62, 0x3b, 0x126, 0x64, 0x3b,
-0x54, 0x3b, 0x54, 0x6c, 0x3b, 0x45, 0x72, 0x3b, 0x126, 0x6d, 0x3b, 0x120, 0x6d, 0x3b, 0x53, 0x62, 0x3b, 0x930, 0x935, 0x93f,
-0x3b, 0x938, 0x94b, 0x92e, 0x3b, 0x92e, 0x902, 0x917, 0x933, 0x3b, 0x92c, 0x941, 0x927, 0x3b, 0x917, 0x941, 0x930, 0x941, 0x3b, 0x936,
+0x67, 0x3b, 0x5a, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x57, 0x3b, 0x44, 0x3b, 0x56, 0x3b, 0x5a, 0x3b, 0x53, 0x75, 0x2e, 0x3b,
+0x4d, 0x2e, 0x3b, 0x54, 0x75, 0x2e, 0x3b, 0x57, 0x2e, 0x3b, 0x54, 0x68, 0x2e, 0x3b, 0x46, 0x2e, 0x3b, 0x53, 0x61, 0x2e,
+0x3b, 0x53, 0x75, 0x6e, 0x2e, 0x3b, 0x4d, 0x6f, 0x6e, 0x2e, 0x3b, 0x54, 0x75, 0x65, 0x2e, 0x3b, 0x57, 0x65, 0x64, 0x2e,
+0x3b, 0x54, 0x68, 0x75, 0x2e, 0x3b, 0x46, 0x72, 0x69, 0x2e, 0x3b, 0x53, 0x61, 0x74, 0x2e, 0x3b, 0x64, 0x69, 0x3b, 0x6c,
+0x75, 0x3b, 0x6d, 0x61, 0x3b, 0x6d, 0x65, 0x3b, 0x135, 0x61, 0x3b, 0x76, 0x65, 0x3b, 0x73, 0x61, 0x3b, 0x64, 0x69, 0x6d,
+0x61, 0x6e, 0x109, 0x6f, 0x3b, 0x6c, 0x75, 0x6e, 0x64, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x64, 0x6f, 0x3b, 0x6d, 0x65, 0x72,
+0x6b, 0x72, 0x65, 0x64, 0x6f, 0x3b, 0x135, 0x61, 0x16d, 0x64, 0x6f, 0x3b, 0x76, 0x65, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x6f,
+0x3b, 0x73, 0x61, 0x62, 0x61, 0x74, 0x6f, 0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x134, 0x3b, 0x56, 0x3b,
+0x53, 0x3b, 0x50, 0x3b, 0x45, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x52, 0x3b, 0x4c, 0x3b, 0x70, 0xfc, 0x68, 0x61,
+0x70, 0xe4, 0x65, 0x76, 0x3b, 0x65, 0x73, 0x6d, 0x61, 0x73, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x74, 0x65, 0x69, 0x73, 0x69,
+0x70, 0xe4, 0x65, 0x76, 0x3b, 0x6b, 0x6f, 0x6c, 0x6d, 0x61, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x6e, 0x65, 0x6c, 0x6a, 0x61,
+0x70, 0xe4, 0x65, 0x76, 0x3b, 0x72, 0x65, 0x65, 0x64, 0x65, 0x3b, 0x6c, 0x61, 0x75, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x73,
+0x75, 0x6e, 0x3b, 0x6d, 0xe1, 0x6e, 0x3b, 0x74, 0xfd, 0x73, 0x3b, 0x6d, 0x69, 0x6b, 0x3b, 0x68, 0xf3, 0x73, 0x3b, 0x66,
+0x72, 0xed, 0x3b, 0x6c, 0x65, 0x79, 0x3b, 0x73, 0x75, 0x6e, 0x6e, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6d, 0xe1,
+0x6e, 0x61, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x74, 0xfd, 0x73, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6d, 0x69, 0x6b,
+0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x68, 0xf3, 0x73, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x66, 0x72, 0xed, 0x67,
+0x67, 0x6a, 0x61, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6c, 0x65, 0x79, 0x67, 0x61, 0x72, 0x64, 0x61, 0x67, 0x75, 0x72,
+0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x54, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x46, 0x3b, 0x4c, 0x3b, 0x73, 0x75, 0x6e, 0x2e, 0x3b,
+0x6d, 0xe1, 0x6e, 0x2e, 0x3b, 0x74, 0xfd, 0x73, 0x2e, 0x3b, 0x6d, 0x69, 0x6b, 0x2e, 0x3b, 0x68, 0xf3, 0x73, 0x2e, 0x3b,
+0x66, 0x72, 0xed, 0x2e, 0x3b, 0x6c, 0x65, 0x79, 0x2e, 0x3b, 0x73, 0x75, 0x3b, 0x6d, 0x61, 0x3b, 0x74, 0x69, 0x3b, 0x6b,
+0x65, 0x3b, 0x74, 0x6f, 0x3b, 0x70, 0x65, 0x3b, 0x6c, 0x61, 0x3b, 0x73, 0x75, 0x6e, 0x6e, 0x75, 0x6e, 0x74, 0x61, 0x69,
+0x3b, 0x6d, 0x61, 0x61, 0x6e, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x3b, 0x74, 0x69, 0x69, 0x73, 0x74, 0x61, 0x69, 0x3b, 0x6b,
+0x65, 0x73, 0x6b, 0x69, 0x76, 0x69, 0x69, 0x6b, 0x6b, 0x6f, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x69, 0x3b, 0x70,
+0x65, 0x72, 0x6a, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x3b, 0x6c, 0x61, 0x75, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x3b, 0x53, 0x3b,
+0x4d, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x50, 0x3b, 0x4c, 0x3b, 0x73, 0x75, 0x6e, 0x6e, 0x75, 0x6e, 0x74, 0x61,
+0x69, 0x6e, 0x61, 0x3b, 0x6d, 0x61, 0x61, 0x6e, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x74, 0x69, 0x69, 0x73,
+0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x6b, 0x65, 0x73, 0x6b, 0x69, 0x76, 0x69, 0x69, 0x6b, 0x6b, 0x6f, 0x6e, 0x61, 0x3b,
+0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x70, 0x65, 0x72, 0x6a, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x6e,
+0x61, 0x3b, 0x6c, 0x61, 0x75, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x64, 0x69, 0x6d, 0x2e, 0x3b, 0x6c, 0x75,
+0x6e, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x6d, 0x65, 0x72, 0x2e, 0x3b, 0x6a, 0x65, 0x75, 0x2e, 0x3b, 0x76, 0x65,
+0x6e, 0x2e, 0x3b, 0x73, 0x61, 0x6d, 0x2e, 0x3b, 0x64, 0x69, 0x6d, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x3b, 0x6c, 0x75, 0x6e,
+0x64, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x64, 0x69, 0x3b, 0x6d, 0x65, 0x72, 0x63, 0x72, 0x65, 0x64, 0x69, 0x3b, 0x6a, 0x65,
+0x75, 0x64, 0x69, 0x3b, 0x76, 0x65, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x69, 0x3b, 0x73, 0x61, 0x6d, 0x65, 0x64, 0x69, 0x3b,
+0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x73, 0x69, 0x3b, 0x6d, 0x6f, 0x3b,
+0x74, 0x69, 0x3b, 0x77, 0x6f, 0x3b, 0x74, 0x6f, 0x3b, 0x66, 0x72, 0x3b, 0x73, 0x6f, 0x3b, 0x73, 0x6e, 0x65, 0x69, 0x6e,
+0x3b, 0x6d, 0x6f, 0x61, 0x6e, 0x64, 0x65, 0x69, 0x3b, 0x74, 0x69, 0x69, 0x73, 0x64, 0x65, 0x69, 0x3b, 0x77, 0x6f, 0x61,
+0x6e, 0x73, 0x64, 0x65, 0x69, 0x3b, 0x74, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x73, 0x64, 0x65, 0x69, 0x3b, 0x66, 0x72, 0x65,
+0x65, 0x64, 0x3b, 0x73, 0x6e, 0x65, 0x6f, 0x6e, 0x3b, 0x44, 0x69, 0x44, 0x3b, 0x44, 0x69, 0x4c, 0x3b, 0x44, 0x69, 0x4d,
+0x3b, 0x44, 0x69, 0x43, 0x3b, 0x44, 0x69, 0x61, 0x3b, 0x44, 0x69, 0x68, 0x3b, 0x44, 0x69, 0x53, 0x3b, 0x44, 0x69, 0x44,
+0xf2, 0x6d, 0x68, 0x6e, 0x61, 0x69, 0x63, 0x68, 0x3b, 0x44, 0x69, 0x4c, 0x75, 0x61, 0x69, 0x6e, 0x3b, 0x44, 0x69, 0x4d,
+0xe0, 0x69, 0x72, 0x74, 0x3b, 0x44, 0x69, 0x43, 0x69, 0x61, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x44, 0x69, 0x61, 0x72, 0x44,
+0x61, 0x6f, 0x69, 0x6e, 0x3b, 0x44, 0x69, 0x68, 0x41, 0x6f, 0x69, 0x6e, 0x65, 0x3b, 0x44, 0x69, 0x53, 0x61, 0x74, 0x68,
+0x61, 0x69, 0x72, 0x6e, 0x65, 0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x43, 0x3b, 0x41, 0x3b, 0x48, 0x3b, 0x53, 0x3b,
+0x44, 0x6f, 0x6d, 0x2e, 0x3b, 0x4c, 0x75, 0x6e, 0x73, 0x3b, 0x4d, 0x61, 0x72, 0x2e, 0x3b, 0x4d, 0xe9, 0x72, 0x2e, 0x3b,
+0x58, 0x6f, 0x76, 0x2e, 0x3b, 0x56, 0x65, 0x6e, 0x2e, 0x3b, 0x53, 0xe1, 0x62, 0x2e, 0x3b, 0x44, 0x6f, 0x6d, 0x69, 0x6e,
+0x67, 0x6f, 0x3b, 0x4c, 0x75, 0x6e, 0x73, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x4d, 0xe9, 0x72, 0x63, 0x6f,
+0x72, 0x65, 0x73, 0x3b, 0x58, 0x6f, 0x76, 0x65, 0x73, 0x3b, 0x56, 0x65, 0x6e, 0x72, 0x65, 0x73, 0x3b, 0x53, 0xe1, 0x62,
+0x61, 0x64, 0x6f, 0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x58, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x64, 0x6f,
+0x6d, 0x2e, 0x3b, 0x6c, 0x75, 0x6e, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x6d, 0xe9, 0x72, 0x2e, 0x3b, 0x78, 0x6f,
+0x76, 0x2e, 0x3b, 0x76, 0x65, 0x6e, 0x2e, 0x3b, 0x73, 0xe1, 0x62, 0x2e, 0x3b, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f,
+0x3b, 0x6c, 0x75, 0x6e, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x6d, 0xe9, 0x72, 0x63, 0x6f, 0x72, 0x65,
+0x73, 0x3b, 0x78, 0x6f, 0x76, 0x65, 0x73, 0x3b, 0x76, 0x65, 0x6e, 0x72, 0x65, 0x73, 0x3b, 0x73, 0xe1, 0x62, 0x61, 0x64,
+0x6f, 0x3b, 0x64, 0x2e, 0x3b, 0x6c, 0x2e, 0x3b, 0x6d, 0x2e, 0x3b, 0x6d, 0x2e, 0x3b, 0x78, 0x2e, 0x3b, 0x76, 0x2e, 0x3b,
+0x73, 0x2e, 0x3b, 0x10d9, 0x10d5, 0x10d8, 0x3b, 0x10dd, 0x10e0, 0x10e8, 0x3b, 0x10e1, 0x10d0, 0x10db, 0x3b, 0x10dd, 0x10d7, 0x10ee, 0x3b, 0x10ee,
+0x10e3, 0x10d7, 0x3b, 0x10de, 0x10d0, 0x10e0, 0x3b, 0x10e8, 0x10d0, 0x10d1, 0x3b, 0x10d9, 0x10d5, 0x10d8, 0x10e0, 0x10d0, 0x3b, 0x10dd, 0x10e0, 0x10e8,
+0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8, 0x3b, 0x10e1, 0x10d0, 0x10db, 0x10e8, 0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8, 0x3b, 0x10dd, 0x10d7, 0x10ee, 0x10e8,
+0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8, 0x3b, 0x10ee, 0x10e3, 0x10d7, 0x10e8, 0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8, 0x3b, 0x10de, 0x10d0, 0x10e0, 0x10d0,
+0x10e1, 0x10d9, 0x10d4, 0x10d5, 0x10d8, 0x3b, 0x10e8, 0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8, 0x3b, 0x10d9, 0x3b, 0x10dd, 0x3b, 0x10e1, 0x3b, 0x10dd,
+0x3b, 0x10ee, 0x3b, 0x10de, 0x3b, 0x10e8, 0x3b, 0x53, 0x6f, 0x3b, 0x4d, 0x6f, 0x3b, 0x44, 0x69, 0x3b, 0x4d, 0x69, 0x3b, 0x44,
+0x6f, 0x3b, 0x46, 0x72, 0x3b, 0x53, 0x61, 0x3b, 0x53, 0x6f, 0x6e, 0x6e, 0x74, 0x61, 0x67, 0x3b, 0x4d, 0x6f, 0x6e, 0x74,
+0x61, 0x67, 0x3b, 0x44, 0x69, 0x65, 0x6e, 0x73, 0x74, 0x61, 0x67, 0x3b, 0x4d, 0x69, 0x74, 0x74, 0x77, 0x6f, 0x63, 0x68,
+0x3b, 0x44, 0x6f, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x74, 0x61, 0x67, 0x3b, 0x46, 0x72, 0x65, 0x69, 0x74, 0x61, 0x67, 0x3b,
+0x53, 0x61, 0x6d, 0x73, 0x74, 0x61, 0x67, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x46, 0x3b,
+0x53, 0x3b, 0x53, 0x6f, 0x2e, 0x3b, 0x4d, 0x6f, 0x2e, 0x3b, 0x44, 0x69, 0x2e, 0x3b, 0x4d, 0x69, 0x2e, 0x3b, 0x44, 0x6f,
+0x2e, 0x3b, 0x46, 0x72, 0x2e, 0x3b, 0x53, 0x61, 0x2e, 0x3b, 0x39a, 0x3c5, 0x3c1, 0x3b, 0x394, 0x3b5, 0x3c5, 0x3b, 0x3a4, 0x3c1,
+0x3af, 0x3b, 0x3a4, 0x3b5, 0x3c4, 0x3b, 0x3a0, 0x3ad, 0x3bc, 0x3b, 0x3a0, 0x3b1, 0x3c1, 0x3b, 0x3a3, 0x3ac, 0x3b2, 0x3b, 0x39a, 0x3c5,
+0x3c1, 0x3b9, 0x3b1, 0x3ba, 0x3ae, 0x3b, 0x394, 0x3b5, 0x3c5, 0x3c4, 0x3ad, 0x3c1, 0x3b1, 0x3b, 0x3a4, 0x3c1, 0x3af, 0x3c4, 0x3b7, 0x3b,
+0x3a4, 0x3b5, 0x3c4, 0x3ac, 0x3c1, 0x3c4, 0x3b7, 0x3b, 0x3a0, 0x3ad, 0x3bc, 0x3c0, 0x3c4, 0x3b7, 0x3b, 0x3a0, 0x3b1, 0x3c1, 0x3b1, 0x3c3,
+0x3ba, 0x3b5, 0x3c5, 0x3ae, 0x3b, 0x3a3, 0x3ac, 0x3b2, 0x3b2, 0x3b1, 0x3c4, 0x3bf, 0x3b, 0x39a, 0x3b, 0x394, 0x3b, 0x3a4, 0x3b, 0x3a4,
+0x3b, 0x3a0, 0x3b, 0x3a0, 0x3b, 0x3a3, 0x3b, 0x73, 0x61, 0x70, 0x3b, 0x61, 0x74, 0x61, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x70,
+0x69, 0x6e, 0x3b, 0x73, 0x69, 0x73, 0x3b, 0x74, 0x61, 0x6c, 0x3b, 0x61, 0x72, 0x66, 0x3b, 0x73, 0x61, 0x70, 0x61, 0x61,
+0x74, 0x3b, 0x61, 0x74, 0x61, 0x61, 0x73, 0x69, 0x6e, 0x6e, 0x67, 0x6f, 0x72, 0x6e, 0x65, 0x71, 0x3b, 0x6d, 0x61, 0x72,
+0x6c, 0x75, 0x6e, 0x6e, 0x67, 0x6f, 0x72, 0x6e, 0x65, 0x71, 0x3b, 0x70, 0x69, 0x6e, 0x67, 0x61, 0x73, 0x75, 0x6e, 0x6e,
+0x67, 0x6f, 0x72, 0x6e, 0x65, 0x71, 0x3b, 0x73, 0x69, 0x73, 0x61, 0x6d, 0x61, 0x6e, 0x6e, 0x67, 0x6f, 0x72, 0x6e, 0x65,
+0x71, 0x3b, 0x74, 0x61, 0x6c, 0x6c, 0x69, 0x6d, 0x61, 0x6e, 0x6e, 0x67, 0x6f, 0x72, 0x6e, 0x65, 0x71, 0x3b, 0x61, 0x72,
+0x66, 0x69, 0x6e, 0x69, 0x6e, 0x6e, 0x67, 0x6f, 0x72, 0x6e, 0x65, 0x71, 0x3b, 0x53, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x50,
+0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0xab0, 0xab5, 0xabf, 0x3b, 0xab8, 0xacb, 0xaae, 0x3b, 0xaae, 0xa82, 0xa97, 0xab3, 0x3b,
+0xaac, 0xac1, 0xaa7, 0x3b, 0xa97, 0xac1, 0xab0, 0xac1, 0x3b, 0xab6, 0xac1, 0xa95, 0xacd, 0xab0, 0x3b, 0xab6, 0xaa8, 0xabf, 0x3b, 0xab0,
+0xab5, 0xabf, 0xab5, 0xabe, 0xab0, 0x3b, 0xab8, 0xacb, 0xaae, 0xab5, 0xabe, 0xab0, 0x3b, 0xaae, 0xa82, 0xa97, 0xab3, 0xab5, 0xabe, 0xab0,
+0x3b, 0xaac, 0xac1, 0xaa7, 0xab5, 0xabe, 0xab0, 0x3b, 0xa97, 0xac1, 0xab0, 0xac1, 0xab5, 0xabe, 0xab0, 0x3b, 0xab6, 0xac1, 0xa95, 0xacd,
+0xab0, 0xab5, 0xabe, 0xab0, 0x3b, 0xab6, 0xaa8, 0xabf, 0xab5, 0xabe, 0xab0, 0x3b, 0xab0, 0x3b, 0xab8, 0xacb, 0x3b, 0xaae, 0xa82, 0x3b,
+0xaac, 0xac1, 0x3b, 0xa97, 0xac1, 0x3b, 0xab6, 0xac1, 0x3b, 0xab6, 0x3b, 0x4c, 0x61, 0x68, 0x3b, 0x4c, 0x69, 0x74, 0x3b, 0x54,
+0x61, 0x6c, 0x3b, 0x4c, 0x61, 0x72, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x41, 0x73, 0x61, 0x3b, 0x4c,
+0x61, 0x68, 0x61, 0x64, 0x69, 0x3b, 0x4c, 0x69, 0x74, 0x69, 0x6e, 0x69, 0x6e, 0x3b, 0x54, 0x61, 0x6c, 0x61, 0x74, 0x61,
+0x3b, 0x4c, 0x61, 0x72, 0x61, 0x62, 0x61, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x3b, 0x4a, 0x75, 0x6d, 0x6d,
+0x61, 0x2bc, 0x61, 0x3b, 0x41, 0x73, 0x61, 0x62, 0x61, 0x72, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x41,
+0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d0, 0x5f3, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d1, 0x5f3, 0x3b, 0x5d9,
+0x5d5, 0x5dd, 0x20, 0x5d2, 0x5f3, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d3, 0x5f3, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d4, 0x5f3, 0x3b,
+0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d5, 0x5f3, 0x3b, 0x5e9, 0x5d1, 0x5ea, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e8, 0x5d0, 0x5e9, 0x5d5, 0x5df,
+0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e9, 0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e9, 0x5dc, 0x5d9, 0x5e9, 0x5d9, 0x3b, 0x5d9,
+0x5d5, 0x5dd, 0x20, 0x5e8, 0x5d1, 0x5d9, 0x5e2, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d7, 0x5de, 0x5d9, 0x5e9, 0x5d9, 0x3b, 0x5d9,
+0x5d5, 0x5dd, 0x20, 0x5e9, 0x5d9, 0x5e9, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e9, 0x5d1, 0x5ea, 0x3b, 0x5d0, 0x5f3, 0x3b, 0x5d1,
+0x5f3, 0x3b, 0x5d2, 0x5f3, 0x3b, 0x5d3, 0x5f3, 0x3b, 0x5d4, 0x5f3, 0x3b, 0x5d5, 0x5f3, 0x3b, 0x5e9, 0x5f3, 0x3b, 0x930, 0x935, 0x93f,
+0x3b, 0x938, 0x94b, 0x92e, 0x3b, 0x92e, 0x902, 0x917, 0x932, 0x3b, 0x92c, 0x941, 0x927, 0x3b, 0x917, 0x941, 0x930, 0x941, 0x3b, 0x936,
0x941, 0x915, 0x94d, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x3b, 0x930, 0x935, 0x93f, 0x935, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e, 0x935,
-0x93e, 0x930, 0x3b, 0x92e, 0x902, 0x917, 0x933, 0x935, 0x93e, 0x930, 0x3b, 0x92c, 0x941, 0x927, 0x935, 0x93e, 0x930, 0x3b, 0x917, 0x941,
+0x93e, 0x930, 0x3b, 0x92e, 0x902, 0x917, 0x932, 0x935, 0x93e, 0x930, 0x3b, 0x92c, 0x941, 0x927, 0x935, 0x93e, 0x930, 0x3b, 0x917, 0x941,
0x930, 0x941, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x935, 0x93e,
-0x930, 0x3b, 0x41d, 0x44f, 0x3b, 0x414, 0x430, 0x3b, 0x41c, 0x44f, 0x3b, 0x41b, 0x445, 0x3b, 0x41f, 0x4af, 0x3b, 0x411, 0x430, 0x3b,
-0x411, 0x44f, 0x3b, 0x43d, 0x44f, 0x43c, 0x3b, 0x434, 0x430, 0x432, 0x430, 0x430, 0x3b, 0x43c, 0x44f, 0x433, 0x43c, 0x430, 0x440, 0x3b,
-0x43b, 0x445, 0x430, 0x433, 0x432, 0x430, 0x3b, 0x43f, 0x4af, 0x440, 0x44d, 0x432, 0x3b, 0x431, 0x430, 0x430, 0x441, 0x430, 0x43d, 0x3b,
-0x431, 0x44f, 0x43c, 0x431, 0x430, 0x3b, 0x906, 0x907, 0x924, 0x3b, 0x938, 0x94b, 0x92e, 0x3b, 0x92e, 0x919, 0x94d, 0x917, 0x932, 0x3b,
-0x92c, 0x941, 0x927, 0x3b, 0x92c, 0x93f, 0x939, 0x93f, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x3b, 0x906,
-0x907, 0x924, 0x92c, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e, 0x92c, 0x93e, 0x930, 0x3b, 0x92e, 0x919, 0x94d, 0x917, 0x932, 0x92c, 0x93e,
-0x930, 0x3b, 0x92c, 0x941, 0x927, 0x92c, 0x93e, 0x930, 0x3b, 0x92c, 0x93f, 0x939, 0x93f, 0x92c, 0x93e, 0x930, 0x3b, 0x936, 0x941, 0x915,
-0x94d, 0x930, 0x92c, 0x93e, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x92c, 0x93e, 0x930, 0x3b, 0x906, 0x3b, 0x938, 0x94b, 0x3b, 0x92e, 0x3b,
-0x92c, 0x941, 0x3b, 0x92c, 0x93f, 0x3b, 0x936, 0x941, 0x3b, 0x936, 0x3b, 0xb30, 0xb2c, 0xb3f, 0x3b, 0xb38, 0xb4b, 0xb2e, 0x3b, 0xb2e,
-0xb19, 0xb4d, 0xb17, 0xb33, 0x3b, 0xb2c, 0xb41, 0xb27, 0x3b, 0xb17, 0xb41, 0xb30, 0xb41, 0x3b, 0xb36, 0xb41, 0xb15, 0xb4d, 0xb30, 0x3b,
-0xb36, 0xb28, 0xb3f, 0x3b, 0xb30, 0xb2c, 0xb3f, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb38, 0xb4b, 0xb2e, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb2e, 0xb19,
-0xb4d, 0xb17, 0xb33, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb2c, 0xb41, 0xb27, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb17, 0xb41, 0xb30, 0xb41, 0xb2c, 0xb3e,
-0xb30, 0x3b, 0xb36, 0xb41, 0xb15, 0xb4d, 0xb30, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb36, 0xb28, 0xb3f, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb30, 0x3b,
-0xb38, 0xb4b, 0x3b, 0xb2e, 0x3b, 0xb2c, 0xb41, 0x3b, 0xb17, 0xb41, 0x3b, 0xb36, 0xb41, 0x3b, 0xb36, 0x3b, 0x6cc, 0x6a9, 0x634, 0x646,
-0x628, 0x647, 0x3b, 0x62f, 0x648, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x633, 0x647, 0x200c, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x686, 0x647,
-0x627, 0x631, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x67e, 0x646, 0x62c, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x62c, 0x645, 0x639, 0x647, 0x3b,
-0x634, 0x646, 0x628, 0x647, 0x3b, 0x6cc, 0x3b, 0x62f, 0x3b, 0x633, 0x3b, 0x686, 0x3b, 0x67e, 0x3b, 0x62c, 0x3b, 0x634, 0x3b, 0x6e,
-0x69, 0x65, 0x64, 0x7a, 0x2e, 0x3b, 0x70, 0x6f, 0x6e, 0x2e, 0x3b, 0x77, 0x74, 0x2e, 0x3b, 0x15b, 0x72, 0x2e, 0x3b, 0x63,
-0x7a, 0x77, 0x2e, 0x3b, 0x70, 0x74, 0x2e, 0x3b, 0x73, 0x6f, 0x62, 0x2e, 0x3b, 0x6e, 0x69, 0x65, 0x64, 0x7a, 0x69, 0x65,
-0x6c, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x69, 0x65, 0x64, 0x7a, 0x69, 0x61, 0x142, 0x65, 0x6b, 0x3b, 0x77, 0x74, 0x6f, 0x72,
-0x65, 0x6b, 0x3b, 0x15b, 0x72, 0x6f, 0x64, 0x61, 0x3b, 0x63, 0x7a, 0x77, 0x61, 0x72, 0x74, 0x65, 0x6b, 0x3b, 0x70, 0x69,
-0x105, 0x74, 0x65, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x4e, 0x3b, 0x50, 0x3b, 0x57, 0x3b, 0x15a, 0x3b,
-0x43, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x6e, 0x3b, 0x70, 0x3b, 0x77, 0x3b, 0x15b, 0x3b, 0x63, 0x3b, 0x70, 0x3b, 0x73, 0x3b,
-0x64, 0x6f, 0x6d, 0x3b, 0x73, 0x65, 0x67, 0x3b, 0x74, 0x65, 0x72, 0x3b, 0x71, 0x75, 0x61, 0x3b, 0x71, 0x75, 0x69, 0x3b,
-0x73, 0x65, 0x78, 0x3b, 0x73, 0xe1, 0x62, 0x3b, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x67, 0x75,
-0x6e, 0x64, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x74, 0x65, 0x72, 0xe7, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72,
-0x61, 0x3b, 0x71, 0x75, 0x61, 0x72, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x71, 0x75, 0x69, 0x6e, 0x74,
-0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x73, 0x65, 0x78, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b,
-0x73, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x51, 0x3b, 0x51, 0x3b, 0x53, 0x3b, 0x53,
-0x3b, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x67, 0x75, 0x6e, 0x64, 0x61, 0x3b, 0x74, 0x65, 0x72,
-0xe7, 0x61, 0x3b, 0x71, 0x75, 0x61, 0x72, 0x74, 0x61, 0x3b, 0x71, 0x75, 0x69, 0x6e, 0x74, 0x61, 0x3b, 0x73, 0x65, 0x78,
-0x74, 0x61, 0x3b, 0x73, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x3b, 0xa10, 0xa24, 0x3b, 0xa38, 0xa4b, 0xa2e, 0x3b, 0xa2e, 0xa70, 0xa17,
-0xa32, 0x3b, 0xa2c, 0xa41, 0xa71, 0xa27, 0x3b, 0xa35, 0xa40, 0xa30, 0x3b, 0xa38, 0xa3c, 0xa41, 0xa71, 0xa15, 0xa30, 0x3b, 0xa38, 0xa3c,
-0xa28, 0xa3f, 0xa71, 0xa1a, 0xa30, 0x3b, 0xa10, 0xa24, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa38, 0xa4b, 0xa2e, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa2e,
-0xa70, 0xa17, 0xa32, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa2c, 0xa41, 0xa71, 0xa27, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa35, 0xa40, 0xa30, 0xa35, 0xa3e,
-0xa30, 0x3b, 0xa38, 0xa3c, 0xa41, 0xa71, 0xa15, 0xa30, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa38, 0xa3c, 0xa28, 0xa3f, 0xa71, 0xa1a, 0xa30, 0xa35,
-0xa3e, 0xa30, 0x3b, 0xa10, 0x3b, 0xa38, 0xa4b, 0x3b, 0xa2e, 0xa70, 0x3b, 0xa2c, 0xa41, 0xa71, 0x3b, 0xa35, 0xa40, 0x3b, 0xa38, 0xa3c,
-0xa41, 0xa71, 0x3b, 0xa38, 0xa3c, 0x3b, 0x627, 0x62a, 0x648, 0x627, 0x631, 0x3b, 0x67e, 0x6cc, 0x631, 0x3b, 0x645, 0x646, 0x6af, 0x644,
-0x3b, 0x628, 0x64f, 0x62f, 0x6be, 0x3b, 0x62c, 0x645, 0x639, 0x631, 0x627, 0x62a, 0x3b, 0x62c, 0x645, 0x639, 0x6c1, 0x3b, 0x6c1, 0x641,
-0x62a, 0x6c1, 0x3b, 0x44, 0x6f, 0x6d, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4d, 0x69, 0xe9, 0x3b, 0x4a,
-0x75, 0x65, 0x3b, 0x56, 0x69, 0x65, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x4c,
-0x75, 0x6e, 0x65, 0x73, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x4d, 0x69, 0xe9, 0x72, 0x63, 0x6f, 0x6c, 0x65,
-0x73, 0x3b, 0x4a, 0x75, 0x65, 0x76, 0x65, 0x73, 0x3b, 0x56, 0x69, 0x65, 0x72, 0x6e, 0x65, 0x73, 0x3b, 0x53, 0xe1, 0x62,
-0x61, 0x64, 0x6f, 0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x58, 0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x64, 0x75,
-0x3b, 0x67, 0x6c, 0x69, 0x3b, 0x6d, 0x61, 0x3b, 0x6d, 0x65, 0x3b, 0x67, 0x69, 0x65, 0x3b, 0x76, 0x65, 0x3b, 0x73, 0x6f,
-0x3b, 0x64, 0x75, 0x6d, 0x65, 0x6e, 0x67, 0x69, 0x61, 0x3b, 0x67, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x73, 0x64, 0x69, 0x3b,
-0x6d, 0x61, 0x72, 0x64, 0x69, 0x3b, 0x6d, 0x65, 0x73, 0x65, 0x6d, 0x6e, 0x61, 0x3b, 0x67, 0x69, 0x65, 0x76, 0x67, 0x69,
-0x61, 0x3b, 0x76, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x64, 0x69, 0x3b, 0x73, 0x6f, 0x6e, 0x64, 0x61, 0x3b, 0x44, 0x3b, 0x47,
-0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x64, 0x75, 0x6d, 0x2e, 0x3b, 0x6c, 0x75, 0x6e, 0x2e,
-0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x6d, 0x69, 0x65, 0x2e, 0x3b, 0x6a, 0x6f, 0x69, 0x3b, 0x76, 0x69, 0x6e, 0x2e, 0x3b,
-0x73, 0xe2, 0x6d, 0x2e, 0x3b, 0x64, 0x75, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x103, 0x3b, 0x6c, 0x75, 0x6e, 0x69, 0x3b, 0x6d,
-0x61, 0x72, 0x21b, 0x69, 0x3b, 0x6d, 0x69, 0x65, 0x72, 0x63, 0x75, 0x72, 0x69, 0x3b, 0x6a, 0x6f, 0x69, 0x3b, 0x76, 0x69,
-0x6e, 0x65, 0x72, 0x69, 0x3b, 0x73, 0xe2, 0x6d, 0x62, 0x103, 0x74, 0x103, 0x3b, 0x44, 0x75, 0x6d, 0x3b, 0x4c, 0x75, 0x6e,
-0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4d, 0x69, 0x65, 0x3b, 0x4a, 0x6f, 0x69, 0x3b, 0x56, 0x69, 0x6e, 0x3b, 0x53, 0xe2, 0x6d,
-0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x61, 0x3b, 0x4d, 0x69, 0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x432, 0x441, 0x3b,
-0x43f, 0x43d, 0x3b, 0x432, 0x442, 0x3b, 0x441, 0x440, 0x3b, 0x447, 0x442, 0x3b, 0x43f, 0x442, 0x3b, 0x441, 0x431, 0x3b, 0x432, 0x43e,
-0x441, 0x43a, 0x440, 0x435, 0x441, 0x435, 0x43d, 0x44c, 0x435, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435, 0x43b, 0x44c, 0x43d, 0x438,
-0x43a, 0x3b, 0x432, 0x442, 0x43e, 0x440, 0x43d, 0x438, 0x43a, 0x3b, 0x441, 0x440, 0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432,
-0x435, 0x440, 0x433, 0x3b, 0x43f, 0x44f, 0x442, 0x43d, 0x438, 0x446, 0x430, 0x3b, 0x441, 0x443, 0x431, 0x431, 0x43e, 0x442, 0x430, 0x3b,
-0x412, 0x3b, 0x41f, 0x3b, 0x412, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f, 0x3b, 0x421, 0x3b, 0x42, 0x6b, 0x31, 0x3b, 0x42, 0x6b,
-0x32, 0x3b, 0x42, 0x6b, 0x33, 0x3b, 0x42, 0x6b, 0x34, 0x3b, 0x42, 0x6b, 0x35, 0x3b, 0x4c, 0xe2, 0x70, 0x3b, 0x4c, 0xe2,
-0x79, 0x3b, 0x42, 0x69, 0x6b, 0x75, 0x61, 0x2d, 0xf4, 0x6b, 0x6f, 0x3b, 0x42, 0xef, 0x6b, 0x75, 0x61, 0x2d, 0xfb, 0x73,
-0x65, 0x3b, 0x42, 0xef, 0x6b, 0x75, 0x61, 0x2d, 0x70, 0x74, 0xe2, 0x3b, 0x42, 0xef, 0x6b, 0x75, 0x61, 0x2d, 0x75, 0x73,
-0xef, 0xf6, 0x3b, 0x42, 0xef, 0x6b, 0x75, 0x61, 0x2d, 0x6f, 0x6b, 0xfc, 0x3b, 0x4c, 0xe2, 0x70, 0xf4, 0x73, 0xf6, 0x3b,
-0x4c, 0xe2, 0x79, 0x65, 0x6e, 0x67, 0x61, 0x3b, 0x4b, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x4b, 0x3b, 0x50, 0x3b,
-0x59, 0x3b, 0x43d, 0x435, 0x434, 0x3b, 0x43f, 0x43e, 0x43d, 0x3b, 0x443, 0x442, 0x43e, 0x3b, 0x441, 0x440, 0x435, 0x3b, 0x447, 0x435,
-0x442, 0x3b, 0x43f, 0x435, 0x442, 0x3b, 0x441, 0x443, 0x431, 0x3b, 0x43d, 0x435, 0x434, 0x435, 0x459, 0x430, 0x3b, 0x43f, 0x43e, 0x43d,
-0x435, 0x434, 0x435, 0x459, 0x430, 0x43a, 0x3b, 0x443, 0x442, 0x43e, 0x440, 0x430, 0x43a, 0x3b, 0x441, 0x440, 0x435, 0x434, 0x430, 0x3b,
-0x447, 0x435, 0x442, 0x432, 0x440, 0x442, 0x430, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x430, 0x43a, 0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442,
-0x430, 0x3b, 0x43d, 0x3b, 0x43f, 0x3b, 0x443, 0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f, 0x3b, 0x441, 0x3b, 0x43d, 0x435, 0x434, 0x2e,
-0x3b, 0x43f, 0x43e, 0x43d, 0x2e, 0x3b, 0x443, 0x442, 0x2e, 0x3b, 0x441, 0x440, 0x2e, 0x3b, 0x447, 0x435, 0x442, 0x2e, 0x3b, 0x43f,
-0x435, 0x442, 0x2e, 0x3b, 0x441, 0x443, 0x431, 0x2e, 0x3b, 0x43d, 0x435, 0x434, 0x458, 0x435, 0x459, 0x430, 0x3b, 0x43f, 0x43e, 0x43d,
-0x435, 0x434, 0x435, 0x459, 0x430, 0x43a, 0x3b, 0x443, 0x442, 0x43e, 0x440, 0x430, 0x43a, 0x3b, 0x441, 0x440, 0x438, 0x458, 0x435, 0x434,
-0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x440, 0x442, 0x430, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x430, 0x43a, 0x3b, 0x441, 0x443, 0x431,
-0x43e, 0x442, 0x430, 0x3b, 0x6e, 0x65, 0x64, 0x2e, 0x3b, 0x70, 0x6f, 0x6e, 0x2e, 0x3b, 0x75, 0x74, 0x2e, 0x3b, 0x73, 0x72,
-0x2e, 0x3b, 0x10d, 0x65, 0x74, 0x2e, 0x3b, 0x70, 0x65, 0x74, 0x2e, 0x3b, 0x73, 0x75, 0x62, 0x2e, 0x3b, 0x6e, 0x65, 0x64,
-0x6a, 0x65, 0x6c, 0x6a, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x6b, 0x3b, 0x75, 0x74, 0x6f,
-0x72, 0x61, 0x6b, 0x3b, 0x73, 0x72, 0x69, 0x6a, 0x65, 0x64, 0x61, 0x3b, 0x10d, 0x65, 0x74, 0x76, 0x72, 0x74, 0x61, 0x6b,
-0x3b, 0x70, 0x65, 0x74, 0x61, 0x6b, 0x3b, 0x73, 0x75, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x6e, 0x65, 0x64, 0x3b, 0x70, 0x6f,
-0x6e, 0x3b, 0x75, 0x74, 0x6f, 0x3b, 0x73, 0x72, 0x65, 0x3b, 0x10d, 0x65, 0x74, 0x3b, 0x70, 0x65, 0x74, 0x3b, 0x73, 0x75,
-0x62, 0x3b, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x6b,
-0x3b, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x6b, 0x3b, 0x73, 0x72, 0x65, 0x64, 0x61, 0x3b, 0x10d, 0x65, 0x74, 0x76, 0x72, 0x74,
-0x61, 0x6b, 0x3b, 0x70, 0x65, 0x74, 0x61, 0x6b, 0x3b, 0x73, 0x75, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x425, 0x446, 0x431, 0x3b,
-0x41a, 0x440, 0x441, 0x3b, 0x414, 0x446, 0x433, 0x3b, 0x4d4, 0x440, 0x442, 0x3b, 0x426, 0x43f, 0x440, 0x3b, 0x41c, 0x440, 0x431, 0x3b,
-0x421, 0x431, 0x442, 0x3b, 0x425, 0x443, 0x44b, 0x446, 0x430, 0x443, 0x431, 0x43e, 0x43d, 0x3b, 0x41a, 0x44a, 0x443, 0x44b, 0x440, 0x438,
-0x441, 0x4d5, 0x440, 0x3b, 0x414, 0x44b, 0x446, 0x446, 0x4d5, 0x433, 0x3b, 0x4d4, 0x440, 0x442, 0x44b, 0x446, 0x446, 0x4d5, 0x433, 0x3b,
-0x426, 0x44b, 0x43f, 0x43f, 0x4d5, 0x440, 0x4d5, 0x43c, 0x3b, 0x41c, 0x430, 0x439, 0x440, 0x4d5, 0x43c, 0x431, 0x43e, 0x43d, 0x3b, 0x421,
-0x430, 0x431, 0x430, 0x442, 0x3b, 0x425, 0x3b, 0x41a, 0x3b, 0x414, 0x3b, 0x4d4, 0x3b, 0x426, 0x3b, 0x41c, 0x3b, 0x421, 0x3b, 0x445,
-0x446, 0x431, 0x3b, 0x43a, 0x440, 0x441, 0x3b, 0x434, 0x446, 0x433, 0x3b, 0x4d5, 0x440, 0x442, 0x3b, 0x446, 0x43f, 0x440, 0x3b, 0x43c,
-0x440, 0x431, 0x3b, 0x441, 0x431, 0x442, 0x3b, 0x445, 0x443, 0x44b, 0x446, 0x430, 0x443, 0x431, 0x43e, 0x43d, 0x3b, 0x43a, 0x44a, 0x443,
-0x44b, 0x440, 0x438, 0x441, 0x4d5, 0x440, 0x3b, 0x434, 0x44b, 0x446, 0x446, 0x4d5, 0x433, 0x3b, 0x4d5, 0x440, 0x442, 0x44b, 0x446, 0x446,
-0x4d5, 0x433, 0x3b, 0x446, 0x44b, 0x43f, 0x43f, 0x4d5, 0x440, 0x4d5, 0x43c, 0x3b, 0x43c, 0x430, 0x439, 0x440, 0x4d5, 0x43c, 0x431, 0x43e,
-0x43d, 0x3b, 0x441, 0x430, 0x431, 0x430, 0x442, 0x3b, 0x53, 0x76, 0x6f, 0x3b, 0x4d, 0x75, 0x76, 0x3b, 0x43, 0x68, 0x70, 0x3b,
-0x43, 0x68, 0x74, 0x3b, 0x43, 0x68, 0x6e, 0x3b, 0x43, 0x68, 0x73, 0x3b, 0x4d, 0x75, 0x67, 0x3b, 0x53, 0x76, 0x6f, 0x6e,
-0x64, 0x6f, 0x3b, 0x4d, 0x75, 0x76, 0x68, 0x75, 0x72, 0x6f, 0x3b, 0x43, 0x68, 0x69, 0x70, 0x69, 0x72, 0x69, 0x3b, 0x43,
-0x68, 0x69, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x3b, 0x43, 0x68, 0x69, 0x73, 0x68, 0x61, 0x6e,
-0x75, 0x3b, 0x4d, 0x75, 0x67, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x43,
-0x3b, 0x43, 0x3b, 0x4d, 0x3b, 0xd89, 0xdbb, 0xdd2, 0xdaf, 0xdcf, 0x3b, 0xdc3, 0xdb3, 0xdd4, 0xdaf, 0xdcf, 0x3b, 0xd85, 0xd9f, 0xdc4,
-0x3b, 0xdb6, 0xdaf, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xdb6, 0xdca, 0x200d, 0xdbb, 0xdc4, 0xdc3, 0xdca, 0x3b, 0xdc3, 0xdd2, 0xd9a, 0xdd4, 0x3b,
-0xdc3, 0xdd9, 0xdb1, 0x3b, 0xd89, 0xdbb, 0xdd2, 0xdaf, 0xdcf, 0x3b, 0xdc3, 0xdb3, 0xdd4, 0xdaf, 0xdcf, 0x3b, 0xd85, 0xd9f, 0xdc4, 0xdbb,
-0xdd4, 0xdc0, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xdb6, 0xdaf, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xdb6, 0xdca, 0x200d, 0xdbb, 0xdc4, 0xdc3, 0xdca, 0xdb4,
-0xdad, 0xdd2, 0xdb1, 0xdca, 0xdaf, 0xdcf, 0x3b, 0xdc3, 0xdd2, 0xd9a, 0xdd4, 0xdbb, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xdc3, 0xdd9, 0xdb1, 0xdc3,
-0xdd4, 0xdbb, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xd89, 0x3b, 0xdc3, 0x3b, 0xd85, 0x3b, 0xdb6, 0x3b, 0xdb6, 0xdca, 0x200d, 0xdbb, 0x3b, 0xdc3,
-0xdd2, 0x3b, 0xdc3, 0xdd9, 0x3b, 0x6e, 0x65, 0x3b, 0x70, 0x6f, 0x3b, 0x75, 0x74, 0x3b, 0x73, 0x74, 0x3b, 0x161, 0x74, 0x3b,
-0x70, 0x69, 0x3b, 0x73, 0x6f, 0x3b, 0x6e, 0x65, 0x64, 0x65, 0x13e, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x6c, 0x6f,
-0x6b, 0x3b, 0x75, 0x74, 0x6f, 0x72, 0x6f, 0x6b, 0x3b, 0x73, 0x74, 0x72, 0x65, 0x64, 0x61, 0x3b, 0x161, 0x74, 0x76, 0x72,
-0x74, 0x6f, 0x6b, 0x3b, 0x70, 0x69, 0x61, 0x74, 0x6f, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x6e, 0x3b,
-0x70, 0x3b, 0x75, 0x3b, 0x73, 0x3b, 0x161, 0x3b, 0x70, 0x3b, 0x73, 0x3b, 0x6e, 0x65, 0x64, 0x2e, 0x3b, 0x70, 0x6f, 0x6e,
-0x2e, 0x3b, 0x74, 0x6f, 0x72, 0x2e, 0x3b, 0x73, 0x72, 0x65, 0x2e, 0x3b, 0x10d, 0x65, 0x74, 0x2e, 0x3b, 0x70, 0x65, 0x74,
-0x2e, 0x3b, 0x73, 0x6f, 0x62, 0x2e, 0x3b, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x65, 0x64,
-0x65, 0x6c, 0x6a, 0x65, 0x6b, 0x3b, 0x74, 0x6f, 0x72, 0x65, 0x6b, 0x3b, 0x73, 0x72, 0x65, 0x64, 0x61, 0x3b, 0x10d, 0x65,
-0x74, 0x72, 0x74, 0x65, 0x6b, 0x3b, 0x70, 0x65, 0x74, 0x65, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x6e,
-0x3b, 0x70, 0x3b, 0x74, 0x3b, 0x73, 0x3b, 0x10d, 0x3b, 0x70, 0x3b, 0x73, 0x3b, 0x41, 0x78, 0x64, 0x3b, 0x49, 0x73, 0x6e,
-0x3b, 0x54, 0x61, 0x6c, 0x3b, 0x41, 0x72, 0x62, 0x3b, 0x4b, 0x68, 0x61, 0x3b, 0x4a, 0x69, 0x6d, 0x3b, 0x53, 0x61, 0x62,
-0x3b, 0x41, 0x78, 0x61, 0x64, 0x3b, 0x49, 0x73, 0x6e, 0x69, 0x69, 0x6e, 0x3b, 0x54, 0x61, 0x6c, 0x61, 0x61, 0x64, 0x6f,
-0x3b, 0x41, 0x72, 0x62, 0x61, 0x63, 0x6f, 0x3b, 0x4b, 0x68, 0x61, 0x6d, 0x69, 0x69, 0x73, 0x3b, 0x4a, 0x69, 0x6d, 0x63,
-0x6f, 0x3b, 0x53, 0x61, 0x62, 0x74, 0x69, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x4b, 0x68, 0x3b, 0x4a,
-0x3b, 0x53, 0x3b, 0x64, 0x6f, 0x6d, 0x2e, 0x3b, 0x6c, 0x75, 0x6e, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x6d, 0x69,
-0xe9, 0x2e, 0x3b, 0x6a, 0x75, 0x65, 0x2e, 0x3b, 0x76, 0x69, 0x65, 0x2e, 0x3b, 0x73, 0xe1, 0x62, 0x2e, 0x3b, 0x64, 0x6f,
-0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x6c, 0x75, 0x6e, 0x65, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x6d,
-0x69, 0xe9, 0x72, 0x63, 0x6f, 0x6c, 0x65, 0x73, 0x3b, 0x6a, 0x75, 0x65, 0x76, 0x65, 0x73, 0x3b, 0x76, 0x69, 0x65, 0x72,
-0x6e, 0x65, 0x73, 0x3b, 0x73, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x3b, 0x64, 0x3b, 0x6c, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x6a,
-0x3b, 0x76, 0x3b, 0x73, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0x69, 0x6c, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61,
-0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b,
-0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61,
-0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x73, 0xf6, 0x6e, 0x3b, 0x6d, 0xe5, 0x6e, 0x3b, 0x74, 0x69, 0x73, 0x3b, 0x6f, 0x6e, 0x73,
-0x3b, 0x74, 0x6f, 0x72, 0x73, 0x3b, 0x66, 0x72, 0x65, 0x3b, 0x6c, 0xf6, 0x72, 0x3b, 0x73, 0xf6, 0x6e, 0x64, 0x61, 0x67,
-0x3b, 0x6d, 0xe5, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x69, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x6f, 0x6e, 0x73, 0x64, 0x61,
-0x67, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x66, 0x72, 0x65, 0x64, 0x61, 0x67, 0x3b, 0x6c, 0xf6, 0x72,
-0x64, 0x61, 0x67, 0x3b, 0xb9e, 0xbbe, 0xbaf, 0xbbf, 0x2e, 0x3b, 0xba4, 0xbbf, 0xb99, 0xbcd, 0x2e, 0x3b, 0xb9a, 0xbc6, 0xbb5, 0xbcd,
-0x2e, 0x3b, 0xbaa, 0xbc1, 0xba4, 0x2e, 0x3b, 0xbb5, 0xbbf, 0xbaf, 0xbbe, 0x2e, 0x3b, 0xbb5, 0xbc6, 0xbb3, 0xbcd, 0x2e, 0x3b, 0xb9a,
-0xba9, 0xbbf, 0x3b, 0xb9e, 0xbbe, 0xbaf, 0xbbf, 0xbb1, 0xbc1, 0x3b, 0xba4, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbb3, 0xbcd, 0x3b, 0xb9a, 0xbc6,
-0xbb5, 0xbcd, 0xbb5, 0xbbe, 0xbaf, 0xbcd, 0x3b, 0xbaa, 0xbc1, 0xba4, 0xba9, 0xbcd, 0x3b, 0xbb5, 0xbbf, 0xbaf, 0xbbe, 0xbb4, 0xba9, 0xbcd,
-0x3b, 0xbb5, 0xbc6, 0xbb3, 0xbcd, 0xbb3, 0xbbf, 0x3b, 0xb9a, 0xba9, 0xbbf, 0x3b, 0xb9e, 0xbbe, 0x3b, 0xba4, 0xbbf, 0x3b, 0xb9a, 0xbc6,
-0x3b, 0xbaa, 0xbc1, 0x3b, 0xbb5, 0xbbf, 0x3b, 0xbb5, 0xbc6, 0x3b, 0xb9a, 0x3b, 0xc06, 0xc26, 0xc3f, 0x3b, 0xc38, 0xc4b, 0xc2e, 0x3b,
-0xc2e, 0xc02, 0xc17, 0xc33, 0x3b, 0xc2c, 0xc41, 0xc27, 0x3b, 0xc17, 0xc41, 0xc30, 0xc41, 0x3b, 0xc36, 0xc41, 0xc15, 0xc4d, 0xc30, 0x3b,
-0xc36, 0xc28, 0xc3f, 0x3b, 0xc06, 0xc26, 0xc3f, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc38, 0xc4b, 0xc2e, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b,
-0xc2e, 0xc02, 0xc17, 0xc33, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc2c, 0xc41, 0xc27, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc17, 0xc41, 0xc30,
-0xc41, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc36, 0xc41, 0xc15, 0xc4d, 0xc30, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc36, 0xc28, 0xc3f, 0xc35,
-0xc3e, 0xc30, 0xc02, 0x3b, 0xc06, 0x3b, 0xc38, 0xc4b, 0x3b, 0xc2e, 0x3b, 0xc2c, 0xc41, 0x3b, 0xc17, 0xc41, 0x3b, 0xc36, 0xc41, 0x3b,
-0xc36, 0x3b, 0xe2d, 0xe32, 0x2e, 0x3b, 0xe08, 0x2e, 0x3b, 0xe2d, 0x2e, 0x3b, 0xe1e, 0x2e, 0x3b, 0xe1e, 0xe24, 0x2e, 0x3b, 0xe28,
-0x2e, 0x3b, 0xe2a, 0x2e, 0x3b, 0xe27, 0xe31, 0xe19, 0xe2d, 0xe32, 0xe17, 0xe34, 0xe15, 0xe22, 0xe4c, 0x3b, 0xe27, 0xe31, 0xe19, 0xe08,
-0xe31, 0xe19, 0xe17, 0xe23, 0xe4c, 0x3b, 0xe27, 0xe31, 0xe19, 0xe2d, 0xe31, 0xe07, 0xe04, 0xe32, 0xe23, 0x3b, 0xe27, 0xe31, 0xe19, 0xe1e,
-0xe38, 0xe18, 0x3b, 0xe27, 0xe31, 0xe19, 0xe1e, 0xe24, 0xe2b, 0xe31, 0xe2a, 0xe1a, 0xe14, 0xe35, 0x3b, 0xe27, 0xe31, 0xe19, 0xe28, 0xe38,
-0xe01, 0xe23, 0xe4c, 0x3b, 0xe27, 0xe31, 0xe19, 0xe40, 0xe2a, 0xe32, 0xe23, 0xe4c, 0x3b, 0xe2d, 0xe32, 0x3b, 0xe08, 0x3b, 0xe2d, 0x3b,
-0xe1e, 0x3b, 0xe1e, 0xe24, 0x3b, 0xe28, 0x3b, 0xe2a, 0x3b, 0xf49, 0xf72, 0xf0b, 0xf58, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b,
-0x3b, 0xf58, 0xf72, 0xf42, 0xf0b, 0xf51, 0xf58, 0xf62, 0xf0b, 0x3b, 0xf63, 0xfb7, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf55, 0xf74, 0xf62,
-0xf0b, 0xf56, 0xf74, 0xf0b, 0x3b, 0xf54, 0xf0b, 0xf66, 0xf44, 0xf66, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b,
-0xf42, 0xf5f, 0xf60, 0xf0b, 0xf49, 0xf72, 0xf0b, 0xf58, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0x3b,
-0xf42, 0xf5f, 0xf60, 0xf0b, 0xf58, 0xf72, 0xf42, 0xf0b, 0xf51, 0xf58, 0xf62, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf63, 0xfb7, 0xf42,
-0xf0b, 0xf54, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf55, 0xf74, 0xf62, 0xf0b, 0xf56, 0xf74, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b,
-0xf54, 0xf0b, 0xf66, 0xf44, 0xf66, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf49,
-0xf72, 0x3b, 0xf5f, 0xfb3, 0x3b, 0xf58, 0xf72, 0xf42, 0x3b, 0xf63, 0xfb7, 0xf42, 0x3b, 0xf55, 0xf74, 0xf62, 0x3b, 0xf66, 0xf44, 0xf66,
-0x3b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0x3b, 0x1230, 0x1295, 0x3b, 0x1230, 0x1291, 0x3b, 0x1230, 0x1209, 0x3b, 0x1228, 0x1261, 0x3b, 0x1213, 0x1219,
-0x3b, 0x12d3, 0x122d, 0x3b, 0x1240, 0x12f3, 0x3b, 0x1230, 0x1295, 0x1260, 0x1275, 0x3b, 0x1230, 0x1291, 0x12ed, 0x3b, 0x1230, 0x1209, 0x1235, 0x3b,
-0x1228, 0x1261, 0x12d5, 0x3b, 0x1213, 0x1219, 0x1235, 0x3b, 0x12d3, 0x122d, 0x1262, 0x3b, 0x1240, 0x12f3, 0x121d, 0x3b, 0x1230, 0x3b, 0x1230, 0x3b,
-0x1220, 0x3b, 0x1228, 0x3b, 0x1213, 0x3b, 0x12d3, 0x3b, 0x1240, 0x3b, 0x1230, 0x1295, 0x1260, 0x1275, 0x3b, 0x1230, 0x1291, 0x12ed, 0x3b, 0x1220,
-0x1209, 0x1235, 0x3b, 0x1228, 0x1261, 0x12d5, 0x3b, 0x1283, 0x1219, 0x1235, 0x3b, 0x12d3, 0x122d, 0x1262, 0x3b, 0x1240, 0x12f3, 0x121d, 0x3b, 0x1230,
-0x3b, 0x1230, 0x3b, 0x1230, 0x3b, 0x1228, 0x3b, 0x1213, 0x3b, 0x12d3, 0x3b, 0x1240, 0x3b, 0x53, 0x101, 0x70, 0x3b, 0x4d, 0x14d, 0x6e,
-0x3b, 0x54, 0x16b, 0x73, 0x3b, 0x50, 0x75, 0x6c, 0x3b, 0x54, 0x75, 0x2bb, 0x61, 0x3b, 0x46, 0x61, 0x6c, 0x3b, 0x54, 0x6f,
-0x6b, 0x3b, 0x53, 0x101, 0x70, 0x61, 0x74, 0x65, 0x3b, 0x4d, 0x14d, 0x6e, 0x69, 0x74, 0x65, 0x3b, 0x54, 0x16b, 0x73, 0x69,
-0x74, 0x65, 0x3b, 0x50, 0x75, 0x6c, 0x65, 0x6c, 0x75, 0x6c, 0x75, 0x3b, 0x54, 0x75, 0x2bb, 0x61, 0x70, 0x75, 0x6c, 0x65,
-0x6c, 0x75, 0x6c, 0x75, 0x3b, 0x46, 0x61, 0x6c, 0x61, 0x69, 0x74, 0x65, 0x3b, 0x54, 0x6f, 0x6b, 0x6f, 0x6e, 0x61, 0x6b,
-0x69, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x54, 0x3b, 0x50, 0x3b, 0x54, 0x3b, 0x46, 0x3b, 0x54, 0x3b, 0x50, 0x61, 0x7a, 0x3b,
-0x50, 0x7a, 0x74, 0x3b, 0x53, 0x61, 0x6c, 0x3b, 0xc7, 0x61, 0x72, 0x3b, 0x50, 0x65, 0x72, 0x3b, 0x43, 0x75, 0x6d, 0x3b,
-0x43, 0x6d, 0x74, 0x3b, 0x50, 0x61, 0x7a, 0x61, 0x72, 0x3b, 0x50, 0x61, 0x7a, 0x61, 0x72, 0x74, 0x65, 0x73, 0x69, 0x3b,
-0x53, 0x61, 0x6c, 0x131, 0x3b, 0xc7, 0x61, 0x72, 0x15f, 0x61, 0x6d, 0x62, 0x61, 0x3b, 0x50, 0x65, 0x72, 0x15f, 0x65, 0x6d,
-0x62, 0x65, 0x3b, 0x43, 0x75, 0x6d, 0x61, 0x3b, 0x43, 0x75, 0x6d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x69, 0x3b, 0x50, 0x3b,
-0x50, 0x3b, 0x53, 0x3b, 0xc7, 0x3b, 0x50, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0xfd, 0x62, 0x3b, 0x64, 0x62, 0x3b, 0x73, 0x62,
-0x3b, 0xe7, 0x62, 0x3b, 0x70, 0x62, 0x3b, 0x61, 0x6e, 0x3b, 0x15f, 0x62, 0x3b, 0xfd, 0x65, 0x6b, 0x15f, 0x65, 0x6e, 0x62,
-0x65, 0x3b, 0x64, 0x75, 0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0x73, 0x69, 0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0xe7, 0x61,
-0x72, 0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0x70, 0x65, 0x6e, 0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0x61, 0x6e, 0x6e, 0x61,
-0x3b, 0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0xdd, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0xc7, 0x3b, 0x50, 0x3b, 0x41, 0x3b, 0x15e,
-0x3b, 0x64a, 0x6d5, 0x3b, 0x62f, 0x6c8, 0x3b, 0x633, 0x6d5, 0x3b, 0x686, 0x627, 0x3b, 0x67e, 0x6d5, 0x3b, 0x62c, 0x6c8, 0x3b, 0x634,
-0x6d5, 0x3b, 0x64a, 0x6d5, 0x643, 0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x3b, 0x62f, 0x6c8, 0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x3b, 0x633,
-0x6d5, 0x64a, 0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x3b, 0x686, 0x627, 0x631, 0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x3b, 0x67e, 0x6d5, 0x64a,
-0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x3b, 0x62c, 0x6c8, 0x645, 0x6d5, 0x3b, 0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x3b, 0x64a, 0x3b, 0x62f,
-0x3b, 0x633, 0x3b, 0x686, 0x3b, 0x67e, 0x3b, 0x62c, 0x3b, 0x634, 0x3b, 0x43d, 0x435, 0x434, 0x456, 0x43b, 0x44f, 0x3b, 0x43f, 0x43e,
-0x43d, 0x435, 0x434, 0x456, 0x43b, 0x43e, 0x43a, 0x3b, 0x432, 0x456, 0x432, 0x442, 0x43e, 0x440, 0x43e, 0x43a, 0x3b, 0x441, 0x435, 0x440,
-0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x435, 0x440, 0x3b, 0x43f, 0x2bc, 0x44f, 0x442, 0x43d, 0x438, 0x446, 0x44f, 0x3b,
-0x441, 0x443, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x41d, 0x3b, 0x41f, 0x3b, 0x412, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f, 0x3b, 0x421,
-0x3b, 0x627, 0x62a, 0x648, 0x627, 0x631, 0x3b, 0x633, 0x648, 0x645, 0x648, 0x627, 0x631, 0x3b, 0x645, 0x646, 0x6af, 0x644, 0x3b, 0x628,
-0x62f, 0x6be, 0x3b, 0x62c, 0x645, 0x639, 0x631, 0x627, 0x62a, 0x3b, 0x62c, 0x645, 0x639, 0x6c1, 0x3b, 0x6c1, 0x641, 0x62a, 0x6c1, 0x3b,
-0x627, 0x62a, 0x648, 0x627, 0x631, 0x3b, 0x67e, 0x6cc, 0x631, 0x3b, 0x645, 0x646, 0x6af, 0x644, 0x3b, 0x628, 0x62f, 0x6be, 0x3b, 0x62c,
-0x645, 0x639, 0x631, 0x627, 0x62a, 0x3b, 0x62c, 0x645, 0x639, 0x6c1, 0x3b, 0x6c1, 0x641, 0x62a, 0x6c1, 0x3b, 0x59, 0x61, 0x6b, 0x3b,
-0x44, 0x75, 0x73, 0x68, 0x3b, 0x53, 0x65, 0x73, 0x68, 0x3b, 0x43, 0x68, 0x6f, 0x72, 0x3b, 0x50, 0x61, 0x79, 0x3b, 0x4a,
-0x75, 0x6d, 0x3b, 0x53, 0x68, 0x61, 0x6e, 0x3b, 0x79, 0x61, 0x6b, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x61, 0x3b, 0x64, 0x75,
-0x73, 0x68, 0x61, 0x6e, 0x62, 0x61, 0x3b, 0x73, 0x65, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x61, 0x3b, 0x63, 0x68, 0x6f, 0x72,
-0x73, 0x68, 0x61, 0x6e, 0x62, 0x61, 0x3b, 0x70, 0x61, 0x79, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x61, 0x3b, 0x6a, 0x75, 0x6d,
-0x61, 0x3b, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x61, 0x3b, 0x59, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x4a,
-0x3b, 0x53, 0x3b, 0x6cc, 0x2e, 0x3b, 0x62f, 0x2e, 0x3b, 0x633, 0x2e, 0x3b, 0x686, 0x2e, 0x3b, 0x67e, 0x2e, 0x3b, 0x62c, 0x2e,
-0x3b, 0x634, 0x2e, 0x3b, 0x42f, 0x43a, 0x448, 0x3b, 0x414, 0x443, 0x448, 0x3b, 0x421, 0x435, 0x448, 0x3b, 0x427, 0x43e, 0x440, 0x3b,
-0x41f, 0x430, 0x439, 0x3b, 0x416, 0x443, 0x43c, 0x3b, 0x428, 0x430, 0x43d, 0x3b, 0x42f, 0x43a, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b,
-0x414, 0x443, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x421, 0x435, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x427, 0x43e, 0x440, 0x448,
-0x430, 0x43d, 0x431, 0x430, 0x3b, 0x41f, 0x430, 0x439, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x416, 0x443, 0x43c, 0x430, 0x3b, 0x428,
-0x430, 0x43d, 0x431, 0x430, 0x3b, 0x42f, 0x3b, 0x414, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f, 0x3b, 0x416, 0x3b, 0x428, 0x3b, 0x44f,
-0x43a, 0x448, 0x3b, 0x434, 0x443, 0x448, 0x3b, 0x441, 0x435, 0x448, 0x3b, 0x447, 0x43e, 0x440, 0x3b, 0x43f, 0x430, 0x439, 0x3b, 0x436,
-0x443, 0x43c, 0x3b, 0x448, 0x430, 0x43d, 0x3b, 0x44f, 0x43a, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x434, 0x443, 0x448, 0x430, 0x43d,
-0x431, 0x430, 0x3b, 0x441, 0x435, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x447, 0x43e, 0x440, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b,
-0x43f, 0x430, 0x439, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x436, 0x443, 0x43c, 0x430, 0x3b, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b,
-0x43, 0x4e, 0x3b, 0x54, 0x68, 0x20, 0x32, 0x3b, 0x54, 0x68, 0x20, 0x33, 0x3b, 0x54, 0x68, 0x20, 0x34, 0x3b, 0x54, 0x68,
-0x20, 0x35, 0x3b, 0x54, 0x68, 0x20, 0x36, 0x3b, 0x54, 0x68, 0x20, 0x37, 0x3b, 0x43, 0x68, 0x1ee7, 0x20, 0x4e, 0x68, 0x1ead,
-0x74, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x48, 0x61, 0x69, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x42, 0x61, 0x3b, 0x54, 0x68, 0x1ee9,
-0x20, 0x54, 0x1b0, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x4e, 0x103, 0x6d, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x53, 0xe1, 0x75, 0x3b,
-0x54, 0x68, 0x1ee9, 0x20, 0x42, 0x1ea3, 0x79, 0x3b, 0x43, 0x4e, 0x3b, 0x54, 0x32, 0x3b, 0x54, 0x33, 0x3b, 0x54, 0x34, 0x3b,
-0x54, 0x35, 0x3b, 0x54, 0x36, 0x3b, 0x54, 0x37, 0x3b, 0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x6c, 0x75, 0x6e, 0x3b, 0x4d, 0x61,
-0x77, 0x3b, 0x4d, 0x65, 0x72, 0x3b, 0x49, 0x61, 0x75, 0x3b, 0x47, 0x77, 0x65, 0x3b, 0x53, 0x61, 0x64, 0x3b, 0x44, 0x79,
-0x64, 0x64, 0x20, 0x53, 0x75, 0x6c, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x4c, 0x6c, 0x75, 0x6e, 0x3b, 0x44, 0x79, 0x64,
-0x64, 0x20, 0x4d, 0x61, 0x77, 0x72, 0x74, 0x68, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x4d, 0x65, 0x72, 0x63, 0x68, 0x65,
-0x72, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x49, 0x61, 0x75, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x47, 0x77, 0x65, 0x6e,
-0x65, 0x72, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x53, 0x61, 0x64, 0x77, 0x72, 0x6e, 0x3b, 0x53, 0x3b, 0x4c, 0x6c, 0x3b,
-0x4d, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x47, 0x3b, 0x53, 0x3b, 0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x6c, 0x75, 0x6e, 0x3b, 0x4d,
-0x61, 0x77, 0x3b, 0x4d, 0x65, 0x72, 0x3b, 0x49, 0x61, 0x75, 0x3b, 0x47, 0x77, 0x65, 0x6e, 0x3b, 0x53, 0x61, 0x64, 0x3b,
-0xc0, 0xec, 0x6b, 0xfa, 0x3b, 0x41, 0x6a, 0xe9, 0x3b, 0xcc, 0x73, 0x1eb9, 0x301, 0x67, 0x75, 0x6e, 0x3b, 0x1ecc, 0x6a, 0x1ecd,
-0x301, 0x72, 0xfa, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x62, 0x1ecd, 0x3b, 0x1eb8, 0x74, 0xec, 0x3b, 0xc0, 0x62, 0xe1, 0x6d, 0x1eb9,
-0x301, 0x74, 0x61, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20, 0xc0, 0xec, 0x6b, 0xfa, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20, 0x41,
-0x6a, 0xe9, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20, 0xcc, 0x73, 0x1eb9, 0x301, 0x67, 0x75, 0x6e, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301,
-0x72, 0xfa, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x62, 0x1ecd, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20, 0x1eb8, 0x74, 0xec, 0x3b, 0x1ecc,
-0x6a, 0x1ecd, 0x301, 0x20, 0xc0, 0x62, 0xe1, 0x6d, 0x1eb9, 0x301, 0x74, 0x61, 0x3b, 0xc0, 0xec, 0x6b, 0xfa, 0x3b, 0x41, 0x6a,
-0xe9, 0x3b, 0xcc, 0x73, 0x25b, 0x301, 0x67, 0x75, 0x6e, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x72, 0xfa, 0x3b, 0x186, 0x6a, 0x254,
-0x301, 0x62, 0x254, 0x3b, 0x190, 0x74, 0xec, 0x3b, 0xc0, 0x62, 0xe1, 0x6d, 0x25b, 0x301, 0x74, 0x61, 0x3b, 0x186, 0x6a, 0x254,
-0x301, 0x20, 0xc0, 0xec, 0x6b, 0xfa, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x20, 0x41, 0x6a, 0xe9, 0x3b, 0x186, 0x6a, 0x254, 0x301,
-0x20, 0xcc, 0x73, 0x25b, 0x301, 0x67, 0x75, 0x6e, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x72, 0xfa, 0x3b, 0x186, 0x6a, 0x254, 0x301,
-0x62, 0x254, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x20, 0x190, 0x74, 0xec, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x20, 0xc0, 0x62, 0xe1,
-0x6d, 0x25b, 0x301, 0x74, 0x61, 0x3b, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0x73, 0x6f, 0x3b, 0x42, 0x69, 0x6c, 0x3b, 0x54, 0x68,
-0x61, 0x3b, 0x53, 0x69, 0x6e, 0x3b, 0x48, 0x6c, 0x61, 0x3b, 0x4d, 0x67, 0x71, 0x3b, 0x49, 0x53, 0x6f, 0x6e, 0x74, 0x6f,
-0x3b, 0x55, 0x4d, 0x73, 0x6f, 0x6d, 0x62, 0x75, 0x6c, 0x75, 0x6b, 0x6f, 0x3b, 0x55, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x62,
-0x69, 0x6c, 0x69, 0x3b, 0x55, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x74, 0x68, 0x61, 0x74, 0x68, 0x75, 0x3b, 0x55, 0x4c, 0x77,
-0x65, 0x73, 0x69, 0x6e, 0x65, 0x3b, 0x55, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x68, 0x6c, 0x61, 0x6e, 0x75, 0x3b, 0x55, 0x4d,
-0x67, 0x71, 0x69, 0x62, 0x65, 0x6c, 0x6f, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x42, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x48, 0x3b,
-0x4d, 0x3b, 0x73, 0xf8, 0x6e, 0x3b, 0x6d, 0xe5, 0x6e, 0x3b, 0x74, 0x79, 0x73, 0x3b, 0x6f, 0x6e, 0x73, 0x3b, 0x74, 0x6f,
-0x72, 0x3b, 0x66, 0x72, 0x65, 0x3b, 0x6c, 0x61, 0x75, 0x3b, 0x73, 0xf8, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x6d, 0xe5, 0x6e,
-0x64, 0x61, 0x67, 0x3b, 0x74, 0x79, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x6f, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x6f,
-0x72, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x66, 0x72, 0x65, 0x64, 0x61, 0x67, 0x3b, 0x6c, 0x61, 0x75, 0x72, 0x64, 0x61, 0x67,
-0x3b, 0x73, 0xf8, 0x2e, 0x3b, 0x6d, 0xe5, 0x2e, 0x3b, 0x74, 0x79, 0x2e, 0x3b, 0x6f, 0x6e, 0x2e, 0x3b, 0x74, 0x6f, 0x2e,
-0x3b, 0x66, 0x72, 0x2e, 0x3b, 0x6c, 0x61, 0x2e, 0x3b, 0x43d, 0x435, 0x434, 0x3b, 0x43f, 0x43e, 0x43d, 0x3b, 0x443, 0x442, 0x43e,
-0x3b, 0x441, 0x440, 0x438, 0x3b, 0x447, 0x435, 0x442, 0x3b, 0x43f, 0x435, 0x442, 0x3b, 0x441, 0x443, 0x431, 0x3b, 0x43d, 0x435, 0x434,
-0x435, 0x459, 0x430, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435, 0x459, 0x430, 0x43a, 0x3b, 0x443, 0x442, 0x43e, 0x440, 0x430, 0x43a,
-0x3b, 0x441, 0x440, 0x438, 0x458, 0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x440, 0x442, 0x430, 0x43a, 0x3b, 0x43f, 0x435,
-0x442, 0x430, 0x43a, 0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x4a, 0x65, 0x64, 0x3b, 0x4a, 0x65, 0x6c, 0x3b, 0x4a,
-0x65, 0x6d, 0x3b, 0x4a, 0x65, 0x72, 0x63, 0x3b, 0x4a, 0x65, 0x72, 0x64, 0x3b, 0x4a, 0x65, 0x68, 0x3b, 0x4a, 0x65, 0x73,
-0x3b, 0x4a, 0x65, 0x64, 0x6f, 0x6f, 0x6e, 0x65, 0x65, 0x3b, 0x4a, 0x65, 0x6c, 0x68, 0x65, 0x69, 0x6e, 0x3b, 0x4a, 0x65,
-0x6d, 0x61, 0x79, 0x72, 0x74, 0x3b, 0x4a, 0x65, 0x72, 0x63, 0x65, 0x61, 0x6e, 0x3b, 0x4a, 0x65, 0x72, 0x64, 0x65, 0x69,
-0x6e, 0x3b, 0x4a, 0x65, 0x68, 0x65, 0x69, 0x6e, 0x65, 0x79, 0x3b, 0x4a, 0x65, 0x73, 0x61, 0x72, 0x6e, 0x3b, 0x53, 0x75,
-0x6c, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x74, 0x68, 0x3b, 0x4d, 0x68, 0x72, 0x3b, 0x59, 0x6f, 0x77, 0x3b, 0x47, 0x77,
-0x65, 0x3b, 0x53, 0x61, 0x64, 0x3b, 0x64, 0x79, 0x20, 0x53, 0x75, 0x6c, 0x3b, 0x64, 0x79, 0x20, 0x4c, 0x75, 0x6e, 0x3b,
-0x64, 0x79, 0x20, 0x4d, 0x65, 0x75, 0x72, 0x74, 0x68, 0x3b, 0x64, 0x79, 0x20, 0x4d, 0x65, 0x72, 0x68, 0x65, 0x72, 0x3b,
-0x64, 0x79, 0x20, 0x59, 0x6f, 0x77, 0x3b, 0x64, 0x79, 0x20, 0x47, 0x77, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x64, 0x79, 0x20,
-0x53, 0x61, 0x64, 0x6f, 0x72, 0x6e, 0x3b, 0x4b, 0x77, 0x65, 0x3b, 0x44, 0x77, 0x6f, 0x3b, 0x42, 0x65, 0x6e, 0x3b, 0x57,
-0x75, 0x6b, 0x3b, 0x59, 0x61, 0x77, 0x3b, 0x46, 0x69, 0x61, 0x3b, 0x4d, 0x65, 0x6d, 0x3b, 0x4b, 0x77, 0x65, 0x73, 0x69,
-0x64, 0x61, 0x3b, 0x44, 0x77, 0x6f, 0x77, 0x64, 0x61, 0x3b, 0x42, 0x65, 0x6e, 0x61, 0x64, 0x61, 0x3b, 0x57, 0x75, 0x6b,
-0x75, 0x64, 0x61, 0x3b, 0x59, 0x61, 0x77, 0x64, 0x61, 0x3b, 0x46, 0x69, 0x64, 0x61, 0x3b, 0x4d, 0x65, 0x6d, 0x65, 0x6e,
-0x65, 0x64, 0x61, 0x3b, 0x4b, 0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x57, 0x3b, 0x59, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x906, 0x926,
-0x93f, 0x924, 0x94d, 0x92f, 0x935, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e, 0x935, 0x93e, 0x930, 0x3b, 0x92e, 0x902, 0x917, 0x933, 0x93e,
-0x930, 0x3b, 0x92c, 0x941, 0x927, 0x935, 0x93e, 0x930, 0x3b, 0x917, 0x941, 0x930, 0x941, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x941, 0x915,
-0x94d, 0x930, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x935, 0x93e, 0x930, 0x3b, 0x1ee4, 0x6b, 0x61, 0x3b, 0x4d, 0x1ecd, 0x6e,
-0x3b, 0x54, 0x69, 0x75, 0x3b, 0x57, 0x65, 0x6e, 0x3b, 0x54, 0x1ecd, 0x1ecd, 0x3b, 0x46, 0x72, 0x61, 0x1ecb, 0x3b, 0x53, 0x61,
-0x74, 0x3b, 0x4d, 0x62, 0x1ecd, 0x73, 0x1ecb, 0x20, 0x1ee4, 0x6b, 0x61, 0x3b, 0x4d, 0x1ecd, 0x6e, 0x64, 0x65, 0x3b, 0x54, 0x69,
-0x75, 0x7a, 0x64, 0x65, 0x65, 0x3b, 0x57, 0x65, 0x6e, 0x65, 0x7a, 0x64, 0x65, 0x65, 0x3b, 0x54, 0x1ecd, 0x1ecd, 0x7a, 0x64,
-0x65, 0x65, 0x3b, 0x46, 0x72, 0x61, 0x1ecb, 0x64, 0x65, 0x65, 0x3b, 0x53, 0x61, 0x74, 0x1ecd, 0x64, 0x65, 0x65, 0x3b, 0x57,
-0x6b, 0x79, 0x3b, 0x57, 0x6b, 0x77, 0x3b, 0x57, 0x6b, 0x6c, 0x3b, 0x57, 0x74, 0x169, 0x3b, 0x57, 0x6b, 0x6e, 0x3b, 0x57,
-0x74, 0x6e, 0x3b, 0x57, 0x74, 0x68, 0x3b, 0x57, 0x61, 0x20, 0x6b, 0x79, 0x75, 0x6d, 0x77, 0x61, 0x3b, 0x57, 0x61, 0x20,
-0x6b, 0x77, 0x61, 0x6d, 0x62, 0x129, 0x6c, 0x129, 0x6c, 0x79, 0x61, 0x3b, 0x57, 0x61, 0x20, 0x6b, 0x65, 0x6c, 0x129, 0x3b,
-0x57, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x61, 0x74, 0x169, 0x3b, 0x57, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x57, 0x61,
-0x20, 0x6b, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x57, 0x61, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x74, 0x68, 0x61, 0x74, 0x169,
-0x3b, 0x59, 0x3b, 0x57, 0x3b, 0x45, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x64, 0x6f, 0x6d, 0x3b, 0x6c,
-0x75, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d, 0x69, 0x65, 0x3b, 0x6a, 0x6f, 0x69, 0x3b, 0x76, 0x69, 0x6e, 0x3b, 0x73,
-0x61, 0x62, 0x3b, 0x64, 0x6f, 0x6d, 0x65, 0x6e, 0x69, 0x65, 0x3b, 0x6c, 0x75, 0x6e, 0x69, 0x73, 0x3b, 0x6d, 0x61, 0x72,
-0x74, 0x61, 0x72, 0x73, 0x3b, 0x6d, 0x69, 0x65, 0x72, 0x63, 0x75, 0x73, 0x3b, 0x6a, 0x6f, 0x69, 0x62, 0x65, 0x3b, 0x76,
-0x69, 0x6e, 0x61, 0x72, 0x73, 0x3b, 0x73, 0x61, 0x62, 0x69, 0x64, 0x65, 0x3b, 0x6b, 0x254, 0x73, 0x3b, 0x64, 0x7a, 0x6f,
-0x3b, 0x62, 0x6c, 0x61, 0x3b, 0x6b, 0x75, 0x256, 0x3b, 0x79, 0x61, 0x77, 0x3b, 0x66, 0x69, 0x256, 0x3b, 0x6d, 0x65, 0x6d,
-0x3b, 0x6b, 0x254, 0x73, 0x69, 0x256, 0x61, 0x3b, 0x64, 0x7a, 0x6f, 0x256, 0x61, 0x3b, 0x62, 0x6c, 0x61, 0x256, 0x61, 0x3b,
-0x6b, 0x75, 0x256, 0x61, 0x3b, 0x79, 0x61, 0x77, 0x6f, 0x256, 0x61, 0x3b, 0x66, 0x69, 0x256, 0x61, 0x3b, 0x6d, 0x65, 0x6d,
-0x6c, 0x65, 0x256, 0x61, 0x3b, 0x6b, 0x3b, 0x64, 0x3b, 0x62, 0x3b, 0x6b, 0x3b, 0x79, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x4c,
-0x50, 0x3b, 0x50, 0x31, 0x3b, 0x50, 0x32, 0x3b, 0x50, 0x33, 0x3b, 0x50, 0x34, 0x3b, 0x50, 0x35, 0x3b, 0x50, 0x36, 0x3b,
-0x4c, 0x101, 0x70, 0x75, 0x6c, 0x65, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x6b, 0x61, 0x68, 0x69, 0x3b, 0x50, 0x6f, 0x2bb, 0x61,
-0x6c, 0x75, 0x61, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x6b, 0x6f, 0x6c, 0x75, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x68, 0x101, 0x3b,
-0x50, 0x6f, 0x2bb, 0x61, 0x6c, 0x69, 0x6d, 0x61, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x6f, 0x6e, 0x6f, 0x3b, 0x4c, 0x69, 0x6e,
-0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4d, 0x69, 0x79, 0x3b, 0x48, 0x75, 0x77, 0x3b, 0x42, 0x69, 0x79,
-0x3b, 0x53, 0x61, 0x62, 0x3b, 0x4c, 0x69, 0x6e, 0x67, 0x67, 0x6f, 0x3b, 0x4c, 0x75, 0x6e, 0x65, 0x73, 0x3b, 0x4d, 0x61,
-0x72, 0x74, 0x65, 0x73, 0x3b, 0x4d, 0x69, 0x79, 0x65, 0x72, 0x6b, 0x75, 0x6c, 0x65, 0x73, 0x3b, 0x48, 0x75, 0x77, 0x65,
-0x62, 0x65, 0x73, 0x3b, 0x42, 0x69, 0x79, 0x65, 0x72, 0x6e, 0x65, 0x73, 0x3b, 0x53, 0x61, 0x62, 0x61, 0x64, 0x6f, 0x3b,
-0x53, 0x75, 0x2e, 0x3b, 0x4d, 0xe4, 0x2e, 0x3b, 0x5a, 0x69, 0x2e, 0x3b, 0x4d, 0x69, 0x2e, 0x3b, 0x44, 0x75, 0x2e, 0x3b,
-0x46, 0x72, 0x2e, 0x3b, 0x53, 0x61, 0x2e, 0x3b, 0x53, 0x75, 0x6e, 0x6e, 0x74, 0x69, 0x67, 0x3b, 0x4d, 0xe4, 0xe4, 0x6e,
-0x74, 0x69, 0x67, 0x3b, 0x5a, 0x69, 0x69, 0x73, 0x63, 0x68, 0x74, 0x69, 0x67, 0x3b, 0x4d, 0x69, 0x74, 0x74, 0x77, 0x75,
-0x63, 0x68, 0x3b, 0x44, 0x75, 0x6e, 0x73, 0x63, 0x68, 0x74, 0x69, 0x67, 0x3b, 0x46, 0x72, 0x69, 0x69, 0x74, 0x69, 0x67,
-0x3b, 0x53, 0x61, 0x6d, 0x73, 0x63, 0x68, 0x74, 0x69, 0x67, 0x3b, 0xa46d, 0xa18f, 0x3b, 0xa18f, 0xa2cd, 0x3b, 0xa18f, 0xa44d, 0x3b,
-0xa18f, 0xa315, 0x3b, 0xa18f, 0xa1d6, 0x3b, 0xa18f, 0xa26c, 0x3b, 0xa18f, 0xa0d8, 0x3b, 0xa46d, 0xa18f, 0xa44d, 0x3b, 0xa18f, 0xa282, 0xa2cd, 0x3b,
-0xa18f, 0xa282, 0xa44d, 0x3b, 0xa18f, 0xa282, 0xa315, 0x3b, 0xa18f, 0xa282, 0xa1d6, 0x3b, 0xa18f, 0xa282, 0xa26c, 0x3b, 0xa18f, 0xa282, 0xa0d8, 0x3b,
-0xa18f, 0x3b, 0xa2cd, 0x3b, 0xa44d, 0x3b, 0xa315, 0x3b, 0xa1d6, 0x3b, 0xa26c, 0x3b, 0xa0d8, 0x3b, 0x53, 0xfc, 0x2e, 0x3b, 0x4d, 0x61,
-0x2e, 0x3b, 0x44, 0x69, 0x2e, 0x3b, 0x4d, 0x69, 0x2e, 0x3b, 0x44, 0x75, 0x2e, 0x3b, 0x46, 0x72, 0x2e, 0x3b, 0x53, 0x61,
-0x2e, 0x3b, 0x53, 0xfc, 0x6e, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x4d, 0x61, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x44, 0x69,
-0x6e, 0x67, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x4d, 0x69, 0x64, 0x64, 0x65, 0x77, 0x65, 0x6b, 0x65, 0x6e, 0x3b, 0x44, 0x75,
-0x6e, 0x6e, 0x65, 0x72, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x46, 0x72, 0x65, 0x65, 0x64, 0x61, 0x67, 0x3b, 0x53, 0xfc, 0x6e,
-0x6e, 0x61, 0x76, 0x65, 0x6e, 0x64, 0x3b, 0x73, 0x6f, 0x74, 0x6e, 0x3b, 0x76, 0x75, 0x6f, 0x73, 0x3b, 0x6d, 0x61, 0x14b,
-0x3b, 0x67, 0x61, 0x73, 0x6b, 0x3b, 0x64, 0x75, 0x6f, 0x72, 0x3b, 0x62, 0x65, 0x61, 0x72, 0x3b, 0x6c, 0xe1, 0x76, 0x3b,
-0x73, 0x6f, 0x74, 0x6e, 0x61, 0x62, 0x65, 0x61, 0x69, 0x76, 0x69, 0x3b, 0x76, 0x75, 0x6f, 0x73, 0x73, 0xe1, 0x72, 0x67,
-0x61, 0x3b, 0x6d, 0x61, 0x14b, 0x14b, 0x65, 0x62, 0xe1, 0x72, 0x67, 0x61, 0x3b, 0x67, 0x61, 0x73, 0x6b, 0x61, 0x76, 0x61,
-0x68, 0x6b, 0x6b, 0x75, 0x3b, 0x64, 0x75, 0x6f, 0x72, 0x61, 0x73, 0x64, 0x61, 0x74, 0x3b, 0x62, 0x65, 0x61, 0x72, 0x6a,
-0x61, 0x64, 0x61, 0x74, 0x3b, 0x6c, 0xe1, 0x76, 0x76, 0x61, 0x72, 0x64, 0x61, 0x74, 0x3b, 0x53, 0x3b, 0x56, 0x3b, 0x4d,
-0x3b, 0x47, 0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x4c, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x47, 0x3b, 0x44, 0x3b, 0x42,
-0x3b, 0x4c, 0x3b, 0x73, 0x6f, 0x74, 0x6e, 0x61, 0x62, 0x65, 0x61, 0x69, 0x76, 0x69, 0x3b, 0x76, 0x75, 0x6f, 0x73, 0x73,
-0xe1, 0x72, 0x67, 0x67, 0x61, 0x3b, 0x6d, 0x61, 0x14b, 0x14b, 0x65, 0x62, 0xe1, 0x72, 0x67, 0x67, 0x61, 0x3b, 0x67, 0x61,
-0x73, 0x6b, 0x61, 0x76, 0x61, 0x68, 0x6b, 0x75, 0x3b, 0x64, 0x75, 0x6f, 0x72, 0x61, 0x73, 0x74, 0x61, 0x67, 0x61, 0x3b,
-0x62, 0x65, 0x61, 0x72, 0x6a, 0x61, 0x64, 0x61, 0x67, 0x61, 0x3b, 0x6c, 0xe1, 0x76, 0x76, 0x61, 0x72, 0x64, 0x61, 0x67,
-0x61, 0x3b, 0x43, 0x70, 0x72, 0x3b, 0x43, 0x74, 0x74, 0x3b, 0x43, 0x6d, 0x6e, 0x3b, 0x43, 0x6d, 0x74, 0x3b, 0x41, 0x72,
+0x930, 0x3b, 0x930, 0x3b, 0x938, 0x94b, 0x3b, 0x92e, 0x902, 0x3b, 0x92c, 0x941, 0x3b, 0x917, 0x941, 0x3b, 0x936, 0x941, 0x3b, 0x936,
+0x3b, 0x56, 0x3b, 0x48, 0x3b, 0x4b, 0x3b, 0x53, 0x7a, 0x65, 0x3b, 0x43, 0x73, 0x3b, 0x50, 0x3b, 0x53, 0x7a, 0x6f, 0x3b,
+0x76, 0x61, 0x73, 0xe1, 0x72, 0x6e, 0x61, 0x70, 0x3b, 0x68, 0xe9, 0x74, 0x66, 0x151, 0x3b, 0x6b, 0x65, 0x64, 0x64, 0x3b,
+0x73, 0x7a, 0x65, 0x72, 0x64, 0x61, 0x3b, 0x63, 0x73, 0xfc, 0x74, 0xf6, 0x72, 0x74, 0xf6, 0x6b, 0x3b, 0x70, 0xe9, 0x6e,
+0x74, 0x65, 0x6b, 0x3b, 0x73, 0x7a, 0x6f, 0x6d, 0x62, 0x61, 0x74, 0x3b, 0x56, 0x3b, 0x48, 0x3b, 0x4b, 0x3b, 0x53, 0x7a,
+0x3b, 0x43, 0x73, 0x3b, 0x50, 0x3b, 0x53, 0x7a, 0x3b, 0x73, 0x75, 0x6e, 0x2e, 0x3b, 0x6d, 0xe1, 0x6e, 0x2e, 0x3b, 0xfe,
+0x72, 0x69, 0x2e, 0x3b, 0x6d, 0x69, 0xf0, 0x2e, 0x3b, 0x66, 0x69, 0x6d, 0x2e, 0x3b, 0x66, 0xf6, 0x73, 0x2e, 0x3b, 0x6c,
+0x61, 0x75, 0x2e, 0x3b, 0x73, 0x75, 0x6e, 0x6e, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6d, 0xe1, 0x6e, 0x75, 0x64,
+0x61, 0x67, 0x75, 0x72, 0x3b, 0xfe, 0x72, 0x69, 0xf0, 0x6a, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6d, 0x69, 0xf0,
+0x76, 0x69, 0x6b, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x66, 0x69, 0x6d, 0x6d, 0x74, 0x75, 0x64, 0x61, 0x67, 0x75,
+0x72, 0x3b, 0x66, 0xf6, 0x73, 0x74, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6c, 0x61, 0x75, 0x67, 0x61, 0x72, 0x64,
+0x61, 0x67, 0x75, 0x72, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0xde, 0x3b, 0x4d, 0x3b, 0x46, 0x3b, 0x46, 0x3b, 0x4c, 0x3b, 0x4d,
+0x69, 0x6e, 0x3b, 0x53, 0x65, 0x6e, 0x3b, 0x53, 0x65, 0x6c, 0x3b, 0x52, 0x61, 0x62, 0x3b, 0x4b, 0x61, 0x6d, 0x3b, 0x4a,
+0x75, 0x6d, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x4d, 0x69, 0x6e, 0x67, 0x67, 0x75, 0x3b, 0x53, 0x65, 0x6e, 0x69, 0x6e, 0x3b,
+0x53, 0x65, 0x6c, 0x61, 0x73, 0x61, 0x3b, 0x52, 0x61, 0x62, 0x75, 0x3b, 0x4b, 0x61, 0x6d, 0x69, 0x73, 0x3b, 0x4a, 0x75,
+0x6d, 0x61, 0x74, 0x3b, 0x53, 0x61, 0x62, 0x74, 0x75, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x52, 0x3b, 0x4b, 0x3b,
+0x4a, 0x3b, 0x53, 0x3b, 0x64, 0x6f, 0x6d, 0x3b, 0x6c, 0x75, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d, 0x65, 0x72, 0x3b,
+0x6a, 0x6f, 0x76, 0x3b, 0x76, 0x65, 0x6e, 0x3b, 0x73, 0x61, 0x62, 0x3b, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61,
+0x3b, 0x6c, 0x75, 0x6e, 0x65, 0x64, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x65, 0x64, 0x69, 0x3b, 0x6d, 0x65, 0x72, 0x63,
+0x75, 0x72, 0x69, 0x64, 0x69, 0x3b, 0x6a, 0x6f, 0x76, 0x65, 0x64, 0x69, 0x3b, 0x76, 0x65, 0x6e, 0x65, 0x72, 0x64, 0x69,
+0x3b, 0x73, 0x61, 0x62, 0x62, 0x61, 0x74, 0x6f, 0x3b, 0x64, 0x3b, 0x6c, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x76,
+0x3b, 0x73, 0x3b, 0x44, 0x6f, 0x6d, 0x68, 0x3b, 0x4c, 0x75, 0x61, 0x6e, 0x3b, 0x4d, 0xe1, 0x69, 0x72, 0x74, 0x3b, 0x43,
+0xe9, 0x61, 0x64, 0x3b, 0x44, 0xe9, 0x61, 0x72, 0x3b, 0x41, 0x6f, 0x69, 0x6e, 0x65, 0x3b, 0x53, 0x61, 0x74, 0x68, 0x3b,
+0x44, 0xe9, 0x20, 0x44, 0x6f, 0x6d, 0x68, 0x6e, 0x61, 0x69, 0x67, 0x68, 0x3b, 0x44, 0xe9, 0x20, 0x4c, 0x75, 0x61, 0x69,
+0x6e, 0x3b, 0x44, 0xe9, 0x20, 0x4d, 0xe1, 0x69, 0x72, 0x74, 0x3b, 0x44, 0xe9, 0x20, 0x43, 0xe9, 0x61, 0x64, 0x61, 0x6f,
+0x69, 0x6e, 0x3b, 0x44, 0xe9, 0x61, 0x72, 0x64, 0x61, 0x6f, 0x69, 0x6e, 0x3b, 0x44, 0xe9, 0x20, 0x68, 0x41, 0x6f, 0x69,
+0x6e, 0x65, 0x3b, 0x44, 0xe9, 0x20, 0x53, 0x61, 0x74, 0x68, 0x61, 0x69, 0x72, 0x6e, 0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d,
+0x3b, 0x43, 0x3b, 0x44, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x64, 0x6f, 0x6d, 0x3b, 0x6c, 0x75, 0x6e, 0x3b, 0x6d, 0x61, 0x72,
+0x3b, 0x6d, 0x65, 0x72, 0x3b, 0x67, 0x69, 0x6f, 0x3b, 0x76, 0x65, 0x6e, 0x3b, 0x73, 0x61, 0x62, 0x3b, 0x64, 0x6f, 0x6d,
+0x65, 0x6e, 0x69, 0x63, 0x61, 0x3b, 0x6c, 0x75, 0x6e, 0x65, 0x64, 0xec, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x65, 0x64, 0xec,
+0x3b, 0x6d, 0x65, 0x72, 0x63, 0x6f, 0x6c, 0x65, 0x64, 0xec, 0x3b, 0x67, 0x69, 0x6f, 0x76, 0x65, 0x64, 0xec, 0x3b, 0x76,
+0x65, 0x6e, 0x65, 0x72, 0x64, 0xec, 0x3b, 0x73, 0x61, 0x62, 0x61, 0x74, 0x6f, 0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b,
+0x4d, 0x3b, 0x47, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x65e5, 0x3b, 0x6708, 0x3b, 0x706b, 0x3b, 0x6c34, 0x3b, 0x6728, 0x3b, 0x91d1, 0x3b,
+0x571f, 0x3b, 0x65e5, 0x66dc, 0x65e5, 0x3b, 0x6708, 0x66dc, 0x65e5, 0x3b, 0x706b, 0x66dc, 0x65e5, 0x3b, 0x6c34, 0x66dc, 0x65e5, 0x3b, 0x6728, 0x66dc,
+0x65e5, 0x3b, 0x91d1, 0x66dc, 0x65e5, 0x3b, 0x571f, 0x66dc, 0x65e5, 0x3b, 0x41, 0x68, 0x64, 0x3b, 0x53, 0x65, 0x6e, 0x3b, 0x53, 0x65,
+0x6c, 0x3b, 0x52, 0x61, 0x62, 0x3b, 0x4b, 0x61, 0x6d, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x41, 0x68,
+0x61, 0x64, 0x3b, 0x53, 0x65, 0x6e, 0x69, 0x6e, 0x3b, 0x53, 0x65, 0x6c, 0x61, 0x73, 0x61, 0x3b, 0x52, 0x61, 0x62, 0x75,
+0x3b, 0x4b, 0x61, 0x6d, 0x69, 0x73, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x3b, 0x53, 0x61, 0x62, 0x74, 0x75, 0x3b, 0x41,
+0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x52, 0x3b, 0x4b, 0x3b, 0x4a, 0x3b, 0x53, 0x3b, 0xcad, 0xcbe, 0xca8, 0xcc1, 0x3b, 0xcb8, 0xccb,
+0xcae, 0x3b, 0xcae, 0xc82, 0xc97, 0xcb3, 0x3b, 0xcac, 0xcc1, 0xca7, 0x3b, 0xc97, 0xcc1, 0xcb0, 0xcc1, 0x3b, 0xcb6, 0xcc1, 0xc95, 0xccd,
+0xcb0, 0x3b, 0xcb6, 0xca8, 0xcbf, 0x3b, 0xcad, 0xcbe, 0xca8, 0xcc1, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcb8, 0xccb, 0xcae, 0xcb5, 0xcbe, 0xcb0,
+0x3b, 0xcae, 0xc82, 0xc97, 0xcb3, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcac, 0xcc1, 0xca7, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xc97, 0xcc1, 0xcb0, 0xcc1,
+0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcb6, 0xcc1, 0xc95, 0xccd, 0xcb0, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcb6, 0xca8, 0xcbf, 0xcb5, 0xcbe, 0xcb0, 0x3b,
+0xcad, 0xcbe, 0x3b, 0xcb8, 0xccb, 0x3b, 0xcae, 0xc82, 0x3b, 0xcac, 0xcc1, 0x3b, 0xc97, 0xcc1, 0x3b, 0xcb6, 0xcc1, 0x3b, 0xcb6, 0x3b,
+0x622, 0x62a, 0x6be, 0x648, 0x627, 0x631, 0x3b, 0x698, 0x654, 0x646, 0x65b, 0x62f, 0x655, 0x631, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x648,
+0x65a, 0x645, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x648, 0x62f, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x631, 0x65b, 0x66e, 0x6ea, 0x633, 0x648,
+0x627, 0x631, 0x3b, 0x62c, 0x64f, 0x645, 0x6c1, 0x3b, 0x628, 0x679, 0x648, 0x627, 0x631, 0x3b, 0x627, 0x64e, 0x62a, 0x6be, 0x648, 0x627,
+0x631, 0x3b, 0x698, 0x654, 0x646, 0x65b, 0x62f, 0x631, 0x655, 0x631, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x648, 0x65a, 0x645, 0x648, 0x627,
+0x631, 0x3b, 0x628, 0x648, 0x62f, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x631, 0x65b, 0x66e, 0x6ea, 0x633, 0x648, 0x627, 0x631, 0x3b, 0x62c,
+0x64f, 0x645, 0x6c1, 0x3b, 0x628, 0x679, 0x648, 0x627, 0x631, 0x3b, 0x627, 0x3b, 0x698, 0x3b, 0x628, 0x3b, 0x628, 0x3b, 0x628, 0x3b,
+0x62c, 0x3b, 0x628, 0x3b, 0x436, 0x441, 0x3b, 0x434, 0x441, 0x3b, 0x441, 0x441, 0x3b, 0x441, 0x440, 0x3b, 0x431, 0x441, 0x3b, 0x436,
+0x43c, 0x3b, 0x441, 0x431, 0x3b, 0x436, 0x435, 0x43a, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x434, 0x4af, 0x439, 0x441, 0x435, 0x43d,
+0x431, 0x456, 0x3b, 0x441, 0x435, 0x439, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x441, 0x4d9, 0x440, 0x441, 0x435, 0x43d, 0x431, 0x456,
+0x3b, 0x431, 0x435, 0x439, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x436, 0x4b1, 0x43c, 0x430, 0x3b, 0x441, 0x435, 0x43d, 0x431, 0x456,
+0x3b, 0x416, 0x3b, 0x414, 0x3b, 0x421, 0x3b, 0x421, 0x3b, 0x411, 0x3b, 0x416, 0x3b, 0x421, 0x3b, 0x63, 0x79, 0x75, 0x2e, 0x3b,
+0x6d, 0x62, 0x65, 0x2e, 0x3b, 0x6b, 0x61, 0x62, 0x2e, 0x3b, 0x67, 0x74, 0x75, 0x2e, 0x3b, 0x6b, 0x61, 0x6e, 0x2e, 0x3b,
+0x67, 0x6e, 0x75, 0x2e, 0x3b, 0x67, 0x6e, 0x64, 0x2e, 0x3b, 0x4b, 0x75, 0x20, 0x63, 0x79, 0x75, 0x6d, 0x77, 0x65, 0x72,
+0x75, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x6d, 0x62, 0x65, 0x72, 0x65, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x6b, 0x61,
+0x62, 0x69, 0x72, 0x69, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4b, 0x75, 0x77,
+0x61, 0x20, 0x6b, 0x61, 0x6e, 0x65, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x75, 0x3b, 0x4b,
+0x75, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x74, 0x75, 0x3b, 0x436, 0x435, 0x43a, 0x2e, 0x3b, 0x434,
+0x4af, 0x439, 0x2e, 0x3b, 0x448, 0x435, 0x439, 0x448, 0x2e, 0x3b, 0x448, 0x430, 0x440, 0x448, 0x2e, 0x3b, 0x431, 0x435, 0x439, 0x448,
+0x2e, 0x3b, 0x436, 0x443, 0x43c, 0x430, 0x3b, 0x438, 0x448, 0x43c, 0x2e, 0x3b, 0x436, 0x435, 0x43a, 0x448, 0x435, 0x43c, 0x431, 0x438,
+0x3b, 0x434, 0x4af, 0x439, 0x448, 0x4e9, 0x43c, 0x431, 0x4af, 0x3b, 0x448, 0x435, 0x439, 0x448, 0x435, 0x43c, 0x431, 0x438, 0x3b, 0x448,
+0x430, 0x440, 0x448, 0x435, 0x43c, 0x431, 0x438, 0x3b, 0x431, 0x435, 0x439, 0x448, 0x435, 0x43c, 0x431, 0x438, 0x3b, 0x436, 0x443, 0x43c,
+0x430, 0x3b, 0x438, 0x448, 0x435, 0x43c, 0x431, 0x438, 0x3b, 0x416, 0x3b, 0x414, 0x3b, 0x428, 0x3b, 0x428, 0x3b, 0x411, 0x3b, 0x416,
+0x3b, 0x418, 0x3b, 0xc77c, 0x3b, 0xc6d4, 0x3b, 0xd654, 0x3b, 0xc218, 0x3b, 0xbaa9, 0x3b, 0xae08, 0x3b, 0xd1a0, 0x3b, 0xc77c, 0xc694, 0xc77c,
+0x3b, 0xc6d4, 0xc694, 0xc77c, 0x3b, 0xd654, 0xc694, 0xc77c, 0x3b, 0xc218, 0xc694, 0xc77c, 0x3b, 0xbaa9, 0xc694, 0xc77c, 0x3b, 0xae08, 0xc694, 0xc77c,
+0x3b, 0xd1a0, 0xc694, 0xc77c, 0x3b, 0x79, 0x15f, 0x3b, 0x64, 0x15f, 0x3b, 0x73, 0x15f, 0x3b, 0xe7, 0x15f, 0x3b, 0x70, 0x15f, 0x3b,
+0xee, 0x6e, 0x3b, 0x15f, 0x3b, 0x79, 0x65, 0x6b, 0x15f, 0x65, 0x6d, 0x3b, 0x64, 0x75, 0x15f, 0x65, 0x6d, 0x3b, 0x73, 0xea,
+0x15f, 0x65, 0x6d, 0x3b, 0xe7, 0x61, 0x72, 0x15f, 0x65, 0x6d, 0x3b, 0x70, 0xea, 0x6e, 0x63, 0x15f, 0x65, 0x6d, 0x3b, 0xee,
+0x6e, 0x3b, 0x15f, 0x65, 0x6d, 0xee, 0x3b, 0x59, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0xc7, 0x3b, 0x50, 0x3b, 0xce, 0x3b, 0x15e,
+0x3b, 0x63, 0x75, 0x2e, 0x3b, 0x6d, 0x62, 0x65, 0x2e, 0x3b, 0x6b, 0x61, 0x62, 0x2e, 0x3b, 0x67, 0x74, 0x75, 0x2e, 0x3b,
+0x6b, 0x61, 0x6e, 0x2e, 0x3b, 0x67, 0x6e, 0x75, 0x2e, 0x3b, 0x67, 0x6e, 0x64, 0x2e, 0x3b, 0x4b, 0x75, 0x20, 0x77, 0x2019,
+0x69, 0x6e, 0x64, 0x77, 0x69, 0x3b, 0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x6d, 0x62, 0x65, 0x72, 0x65, 0x3b, 0x4b, 0x75,
+0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74,
+0x61, 0x74, 0x75, 0x3b, 0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x65, 0x3b, 0x4b, 0x75, 0x20, 0x77, 0x61,
+0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x75, 0x3b, 0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x64,
+0x61, 0x74, 0x75, 0x3b, 0xead, 0xeb2, 0xe97, 0xeb4, 0xe94, 0x3b, 0xe88, 0xeb1, 0xe99, 0x3b, 0xead, 0xeb1, 0xe87, 0xe84, 0xeb2, 0xe99,
+0x3b, 0xe9e, 0xeb8, 0xe94, 0x3b, 0xe9e, 0xeb0, 0xeab, 0xeb1, 0xe94, 0x3b, 0xeaa, 0xeb8, 0xe81, 0x3b, 0xec0, 0xeaa, 0xebb, 0xeb2, 0x3b,
+0xea7, 0xeb1, 0xe99, 0xead, 0xeb2, 0xe97, 0xeb4, 0xe94, 0x3b, 0xea7, 0xeb1, 0xe99, 0xe88, 0xeb1, 0xe99, 0x3b, 0xea7, 0xeb1, 0xe99, 0xead,
+0xeb1, 0xe87, 0xe84, 0xeb2, 0xe99, 0x3b, 0xea7, 0xeb1, 0xe99, 0xe9e, 0xeb8, 0xe94, 0x3b, 0xea7, 0xeb1, 0xe99, 0xe9e, 0xeb0, 0xeab, 0xeb1,
+0xe94, 0x3b, 0xea7, 0xeb1, 0xe99, 0xeaa, 0xeb8, 0xe81, 0x3b, 0xea7, 0xeb1, 0xe99, 0xec0, 0xeaa, 0xebb, 0xeb2, 0x3b, 0xead, 0xeb2, 0x3b,
+0xe88, 0x3b, 0xead, 0x3b, 0xe9e, 0x3b, 0xe9e, 0xeab, 0x3b, 0xeaa, 0xeb8, 0x3b, 0xeaa, 0x3b, 0x53, 0x76, 0x113, 0x74, 0x64, 0x2e,
+0x3b, 0x50, 0x69, 0x72, 0x6d, 0x64, 0x2e, 0x3b, 0x4f, 0x74, 0x72, 0x64, 0x2e, 0x3b, 0x54, 0x72, 0x65, 0x161, 0x64, 0x2e,
+0x3b, 0x43, 0x65, 0x74, 0x75, 0x72, 0x74, 0x64, 0x2e, 0x3b, 0x50, 0x69, 0x65, 0x6b, 0x74, 0x64, 0x2e, 0x3b, 0x53, 0x65,
+0x73, 0x74, 0x64, 0x2e, 0x3b, 0x53, 0x76, 0x113, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x50, 0x69, 0x72, 0x6d, 0x64,
+0x69, 0x65, 0x6e, 0x61, 0x3b, 0x4f, 0x74, 0x72, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x54, 0x72, 0x65, 0x161, 0x64, 0x69,
+0x65, 0x6e, 0x61, 0x3b, 0x43, 0x65, 0x74, 0x75, 0x72, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x50, 0x69, 0x65, 0x6b,
+0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x53, 0x65, 0x73, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x53, 0x3b, 0x50,
+0x3b, 0x4f, 0x3b, 0x54, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x73, 0x76, 0x113, 0x74, 0x64, 0x2e, 0x3b, 0x70, 0x69,
+0x72, 0x6d, 0x64, 0x2e, 0x3b, 0x6f, 0x74, 0x72, 0x64, 0x2e, 0x3b, 0x74, 0x72, 0x65, 0x161, 0x64, 0x2e, 0x3b, 0x63, 0x65,
+0x74, 0x75, 0x72, 0x74, 0x64, 0x2e, 0x3b, 0x70, 0x69, 0x65, 0x6b, 0x74, 0x64, 0x2e, 0x3b, 0x73, 0x65, 0x73, 0x74, 0x64,
+0x2e, 0x3b, 0x73, 0x76, 0x113, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x70, 0x69, 0x72, 0x6d, 0x64, 0x69, 0x65, 0x6e,
+0x61, 0x3b, 0x6f, 0x74, 0x72, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x74, 0x72, 0x65, 0x161, 0x64, 0x69, 0x65, 0x6e, 0x61,
+0x3b, 0x63, 0x65, 0x74, 0x75, 0x72, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x70, 0x69, 0x65, 0x6b, 0x74, 0x64, 0x69,
+0x65, 0x6e, 0x61, 0x3b, 0x73, 0x65, 0x73, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x65, 0x79, 0x65, 0x3b, 0x79, 0x62,
+0x6f, 0x3b, 0x6d, 0x62, 0x6c, 0x3b, 0x6d, 0x73, 0x74, 0x3b, 0x6d, 0x69, 0x6e, 0x3b, 0x6d, 0x74, 0x6e, 0x3b, 0x6d, 0x70,
+0x73, 0x3b, 0x65, 0x79, 0x65, 0x6e, 0x67, 0x61, 0x3b, 0x6d, 0x6f, 0x6b, 0x254, 0x6c, 0x254, 0x20, 0x6d, 0x77, 0x61, 0x20,
+0x79, 0x61, 0x6d, 0x62, 0x6f, 0x3b, 0x6d, 0x6f, 0x6b, 0x254, 0x6c, 0x254, 0x20, 0x6d, 0x77, 0x61, 0x20, 0x6d, 0xed, 0x62,
+0x61, 0x6c, 0xe9, 0x3b, 0x6d, 0x6f, 0x6b, 0x254, 0x6c, 0x254, 0x20, 0x6d, 0x77, 0x61, 0x20, 0x6d, 0xed, 0x73, 0xe1, 0x74,
+0x6f, 0x3b, 0x6d, 0x6f, 0x6b, 0x254, 0x6c, 0x254, 0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x6e, 0xe9, 0x69, 0x3b, 0x6d, 0x6f,
+0x6b, 0x254, 0x6c, 0x254, 0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x74, 0xe1, 0x6e, 0x6f, 0x3b, 0x6d, 0x70, 0x254, 0x301, 0x73,
+0x254, 0x3b, 0x65, 0x3b, 0x79, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x70, 0x3b, 0x73, 0x6b, 0x3b, 0x70,
+0x72, 0x3b, 0x61, 0x6e, 0x3b, 0x74, 0x72, 0x3b, 0x6b, 0x74, 0x3b, 0x70, 0x6e, 0x3b, 0x161, 0x74, 0x3b, 0x73, 0x65, 0x6b,
+0x6d, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x70, 0x69, 0x72, 0x6d, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73,
+0x3b, 0x61, 0x6e, 0x74, 0x72, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x74, 0x72, 0x65, 0x10d, 0x69, 0x61, 0x64,
+0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x6b, 0x65, 0x74, 0x76, 0x69, 0x72, 0x74, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73,
+0x3b, 0x70, 0x65, 0x6e, 0x6b, 0x74, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x161, 0x65, 0x161, 0x74, 0x61, 0x64,
+0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x53, 0x3b, 0x50, 0x3b, 0x41, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x50, 0x3b, 0x160, 0x3b,
+0x43d, 0x435, 0x434, 0x2e, 0x3b, 0x43f, 0x43e, 0x43d, 0x2e, 0x3b, 0x432, 0x442, 0x43e, 0x2e, 0x3b, 0x441, 0x440, 0x435, 0x2e, 0x3b,
+0x447, 0x435, 0x442, 0x2e, 0x3b, 0x43f, 0x435, 0x442, 0x2e, 0x3b, 0x441, 0x430, 0x431, 0x2e, 0x3b, 0x43d, 0x435, 0x434, 0x435, 0x43b,
+0x430, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435, 0x43b, 0x43d, 0x438, 0x43a, 0x3b, 0x432, 0x442, 0x43e, 0x440, 0x43d, 0x438, 0x43a,
+0x3b, 0x441, 0x440, 0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x440, 0x442, 0x43e, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x43e,
+0x43a, 0x3b, 0x441, 0x430, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x43d, 0x435, 0x434, 0x2e, 0x3b, 0x43f, 0x43e, 0x43d, 0x2e, 0x3b, 0x432,
+0x442, 0x2e, 0x3b, 0x441, 0x440, 0x435, 0x2e, 0x3b, 0x447, 0x435, 0x442, 0x2e, 0x3b, 0x43f, 0x435, 0x442, 0x2e, 0x3b, 0x441, 0x430,
+0x431, 0x2e, 0x3b, 0x41, 0x6c, 0x61, 0x68, 0x3b, 0x41, 0x6c, 0x61, 0x74, 0x73, 0x3b, 0x54, 0x61, 0x6c, 0x3b, 0x41, 0x6c,
+0x61, 0x72, 0x3b, 0x41, 0x6c, 0x61, 0x6b, 0x3b, 0x5a, 0x6f, 0x6d, 0x3b, 0x41, 0x73, 0x61, 0x62, 0x3b, 0x41, 0x6c, 0x61,
+0x68, 0x61, 0x64, 0x79, 0x3b, 0x41, 0x6c, 0x61, 0x74, 0x73, 0x69, 0x6e, 0x61, 0x69, 0x6e, 0x79, 0x3b, 0x54, 0x61, 0x6c,
+0x61, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x72, 0x6f, 0x62, 0x69, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x6b, 0x61, 0x6d, 0x69,
+0x73, 0x79, 0x3b, 0x5a, 0x6f, 0x6d, 0x61, 0x3b, 0x41, 0x73, 0x61, 0x62, 0x6f, 0x74, 0x73, 0x79, 0x3b, 0x41, 0x3b, 0x41,
+0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x5a, 0x3b, 0x41, 0x3b, 0x41, 0x68, 0x64, 0x3b, 0x49, 0x73, 0x6e, 0x3b, 0x53,
+0x65, 0x6c, 0x3b, 0x52, 0x61, 0x62, 0x3b, 0x4b, 0x68, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x41,
+0x68, 0x61, 0x64, 0x3b, 0x49, 0x73, 0x6e, 0x69, 0x6e, 0x3b, 0x53, 0x65, 0x6c, 0x61, 0x73, 0x61, 0x3b, 0x52, 0x61, 0x62,
+0x75, 0x3b, 0x4b, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x74, 0x3b, 0x53, 0x61, 0x62, 0x74,
+0x75, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x52, 0x3b, 0x4b, 0x3b, 0x4a, 0x3b, 0x53, 0x3b, 0xd1e, 0xd3e, 0xd2f, 0xd7c,
+0x3b, 0xd24, 0xd3f, 0xd19, 0xd4d, 0xd15, 0xd7e, 0x3b, 0xd1a, 0xd4a, 0xd35, 0xd4d, 0xd35, 0x3b, 0xd2c, 0xd41, 0xd27, 0xd7b, 0x3b, 0xd35,
+0xd4d, 0xd2f, 0xd3e, 0xd34, 0xd02, 0x3b, 0xd35, 0xd46, 0xd33, 0xd4d, 0xd33, 0xd3f, 0x3b, 0xd36, 0xd28, 0xd3f, 0x3b, 0xd1e, 0xd3e, 0xd2f,
+0xd31, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd24, 0xd3f, 0xd19, 0xd4d, 0xd15, 0xd33, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd1a,
+0xd4a, 0xd35, 0xd4d, 0xd35, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd2c, 0xd41, 0xd27, 0xd28, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b,
+0xd35, 0xd4d, 0xd2f, 0xd3e, 0xd34, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd35, 0xd46, 0xd33, 0xd4d, 0xd33, 0xd3f, 0xd2f, 0xd3e, 0xd34,
+0xd4d, 0x200c, 0xd1a, 0x3b, 0xd36, 0xd28, 0xd3f, 0xd2f, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd1e, 0xd3e, 0x3b, 0xd24, 0xd3f, 0x3b,
+0xd1a, 0xd4a, 0x3b, 0xd2c, 0xd41, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e, 0x3b, 0xd35, 0xd46, 0x3b, 0xd36, 0x3b, 0xd1e, 0xd3e, 0xd2f, 0xd31,
+0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd24, 0xd3f, 0xd19, 0xd4d, 0xd15, 0xd33, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd1a, 0xd4a,
+0xd35, 0xd4d, 0xd35, 0xd3e, 0xd34, 0xd4d, 0xd1a, 0x3b, 0xd2c, 0xd41, 0xd27, 0xd28, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd35, 0xd4d,
+0xd2f, 0xd3e, 0xd34, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd35, 0xd46, 0xd33, 0xd4d, 0xd33, 0xd3f, 0xd2f, 0xd3e, 0xd34, 0xd4d, 0x200c,
+0xd1a, 0x3b, 0xd36, 0xd28, 0xd3f, 0xd2f, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd1e, 0x3b, 0xd24, 0xd3f, 0x3b, 0xd1a, 0xd4a, 0x3b,
+0xd2c, 0xd41, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e, 0x3b, 0xd35, 0xd46, 0x3b, 0xd36, 0x3b, 0x126, 0x61, 0x64, 0x3b, 0x54, 0x6e, 0x65,
+0x3b, 0x54, 0x6c, 0x69, 0x3b, 0x45, 0x72, 0x62, 0x3b, 0x126, 0x61, 0x6d, 0x3b, 0x120, 0x69, 0x6d, 0x3b, 0x53, 0x69, 0x62,
+0x3b, 0x49, 0x6c, 0x2d, 0x126, 0x61, 0x64, 0x64, 0x3b, 0x49, 0x74, 0x2d, 0x54, 0x6e, 0x65, 0x6a, 0x6e, 0x3b, 0x49, 0x74,
+0x2d, 0x54, 0x6c, 0x69, 0x65, 0x74, 0x61, 0x3b, 0x4c, 0x2d, 0x45, 0x72, 0x62, 0x67, 0x127, 0x61, 0x3b, 0x49, 0x6c, 0x2d,
+0x126, 0x61, 0x6d, 0x69, 0x73, 0x3b, 0x49, 0x6c, 0x2d, 0x120, 0x69, 0x6d, 0x67, 0x127, 0x61, 0x3b, 0x49, 0x73, 0x2d, 0x53,
+0x69, 0x62, 0x74, 0x3b, 0x126, 0x64, 0x3b, 0x54, 0x6e, 0x3b, 0x54, 0x6c, 0x3b, 0x45, 0x72, 0x3b, 0x126, 0x6d, 0x3b, 0x120,
+0x6d, 0x3b, 0x53, 0x62, 0x3b, 0x126, 0x64, 0x3b, 0x54, 0x3b, 0x54, 0x6c, 0x3b, 0x45, 0x72, 0x3b, 0x126, 0x6d, 0x3b, 0x120,
+0x6d, 0x3b, 0x53, 0x62, 0x3b, 0x54, 0x61, 0x70, 0x3b, 0x48, 0x69, 0x6e, 0x3b, 0x54, 0x16b, 0x3b, 0x41, 0x70, 0x61, 0x3b,
+0x50, 0x61, 0x72, 0x3b, 0x4d, 0x65, 0x72, 0x3b, 0x48, 0x6f, 0x72, 0x3b, 0x52, 0x101, 0x74, 0x61, 0x70, 0x75, 0x3b, 0x52,
+0x101, 0x68, 0x69, 0x6e, 0x61, 0x3b, 0x52, 0x101, 0x74, 0x16b, 0x3b, 0x52, 0x101, 0x61, 0x70, 0x61, 0x3b, 0x52, 0x101, 0x70,
+0x61, 0x72, 0x65, 0x3b, 0x52, 0x101, 0x6d, 0x65, 0x72, 0x65, 0x3b, 0x52, 0x101, 0x68, 0x6f, 0x72, 0x6f, 0x69, 0x3b, 0x54,
+0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x50, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x930, 0x935, 0x93f, 0x3b, 0x938, 0x94b, 0x92e,
+0x3b, 0x92e, 0x902, 0x917, 0x933, 0x3b, 0x92c, 0x941, 0x927, 0x3b, 0x917, 0x941, 0x930, 0x941, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930,
+0x3b, 0x936, 0x928, 0x93f, 0x3b, 0x930, 0x935, 0x93f, 0x935, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e, 0x935, 0x93e, 0x930, 0x3b, 0x92e,
+0x902, 0x917, 0x933, 0x935, 0x93e, 0x930, 0x3b, 0x92c, 0x941, 0x927, 0x935, 0x93e, 0x930, 0x3b, 0x917, 0x941, 0x930, 0x941, 0x935, 0x93e,
+0x930, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x935, 0x93e, 0x930, 0x3b, 0x41d, 0x44f,
+0x3b, 0x414, 0x430, 0x3b, 0x41c, 0x44f, 0x3b, 0x41b, 0x445, 0x3b, 0x41f, 0x4af, 0x3b, 0x411, 0x430, 0x3b, 0x411, 0x44f, 0x3b, 0x41d,
+0x44f, 0x43c, 0x3b, 0x414, 0x430, 0x432, 0x430, 0x430, 0x3b, 0x41c, 0x44f, 0x433, 0x43c, 0x430, 0x440, 0x3b, 0x41b, 0x445, 0x430, 0x433,
+0x432, 0x430, 0x3b, 0x41f, 0x4af, 0x440, 0x44d, 0x432, 0x3b, 0x411, 0x430, 0x430, 0x441, 0x430, 0x43d, 0x3b, 0x411, 0x44f, 0x43c, 0x431,
+0x430, 0x3b, 0x43d, 0x44f, 0x43c, 0x3b, 0x434, 0x430, 0x432, 0x430, 0x430, 0x3b, 0x43c, 0x44f, 0x433, 0x43c, 0x430, 0x440, 0x3b, 0x43b,
+0x445, 0x430, 0x433, 0x432, 0x430, 0x3b, 0x43f, 0x4af, 0x440, 0x44d, 0x432, 0x3b, 0x431, 0x430, 0x430, 0x441, 0x430, 0x43d, 0x3b, 0x431,
+0x44f, 0x43c, 0x431, 0x430, 0x3b, 0x906, 0x907, 0x924, 0x3b, 0x938, 0x94b, 0x92e, 0x3b, 0x92e, 0x919, 0x94d, 0x917, 0x932, 0x3b, 0x92c,
+0x941, 0x927, 0x3b, 0x92c, 0x93f, 0x939, 0x93f, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x3b, 0x906, 0x907,
+0x924, 0x92c, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e, 0x92c, 0x93e, 0x930, 0x3b, 0x92e, 0x919, 0x94d, 0x917, 0x932, 0x92c, 0x93e, 0x930,
+0x3b, 0x92c, 0x941, 0x927, 0x92c, 0x93e, 0x930, 0x3b, 0x92c, 0x93f, 0x939, 0x93f, 0x92c, 0x93e, 0x930, 0x3b, 0x936, 0x941, 0x915, 0x94d,
+0x930, 0x92c, 0x93e, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x92c, 0x93e, 0x930, 0x3b, 0x906, 0x3b, 0x938, 0x94b, 0x3b, 0x92e, 0x3b, 0x92c,
+0x941, 0x3b, 0x92c, 0x93f, 0x3b, 0x936, 0x941, 0x3b, 0x936, 0x3b, 0xb30, 0xb2c, 0xb3f, 0x3b, 0xb38, 0xb4b, 0xb2e, 0x3b, 0xb2e, 0xb19,
+0xb4d, 0xb17, 0xb33, 0x3b, 0xb2c, 0xb41, 0xb27, 0x3b, 0xb17, 0xb41, 0xb30, 0xb41, 0x3b, 0xb36, 0xb41, 0xb15, 0xb4d, 0xb30, 0x3b, 0xb36,
+0xb28, 0xb3f, 0x3b, 0xb30, 0xb2c, 0xb3f, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb38, 0xb4b, 0xb2e, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb2e, 0xb19, 0xb4d,
+0xb17, 0xb33, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb2c, 0xb41, 0xb27, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb17, 0xb41, 0xb30, 0xb41, 0xb2c, 0xb3e, 0xb30,
+0x3b, 0xb36, 0xb41, 0xb15, 0xb4d, 0xb30, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb36, 0xb28, 0xb3f, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb30, 0x3b, 0xb38,
+0xb4b, 0x3b, 0xb2e, 0x3b, 0xb2c, 0xb41, 0x3b, 0xb17, 0xb41, 0x3b, 0xb36, 0xb41, 0x3b, 0xb36, 0x3b, 0x64a, 0x648, 0x646, 0x6cd, 0x3b,
+0x62f, 0x648, 0x646, 0x6cd, 0x3b, 0x62f, 0x631, 0x6d0, 0x646, 0x6cd, 0x3b, 0x685, 0x644, 0x631, 0x646, 0x6cd, 0x3b, 0x67e, 0x64a, 0x646,
+0x681, 0x646, 0x6cd, 0x3b, 0x62c, 0x645, 0x639, 0x647, 0x3b, 0x627, 0x648, 0x646, 0x6cd, 0x3b, 0x6cc, 0x6a9, 0x634, 0x646, 0x628, 0x647,
+0x3b, 0x62f, 0x648, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x633, 0x647, 0x200c, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x686, 0x647, 0x627, 0x631,
+0x634, 0x646, 0x628, 0x647, 0x3b, 0x67e, 0x646, 0x62c, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x62c, 0x645, 0x639, 0x647, 0x3b, 0x634, 0x646,
+0x628, 0x647, 0x3b, 0x6cc, 0x3b, 0x62f, 0x3b, 0x633, 0x3b, 0x686, 0x3b, 0x67e, 0x3b, 0x62c, 0x3b, 0x634, 0x3b, 0x6e, 0x69, 0x65,
+0x64, 0x7a, 0x2e, 0x3b, 0x70, 0x6f, 0x6e, 0x2e, 0x3b, 0x77, 0x74, 0x2e, 0x3b, 0x15b, 0x72, 0x2e, 0x3b, 0x63, 0x7a, 0x77,
+0x2e, 0x3b, 0x70, 0x74, 0x2e, 0x3b, 0x73, 0x6f, 0x62, 0x2e, 0x3b, 0x6e, 0x69, 0x65, 0x64, 0x7a, 0x69, 0x65, 0x6c, 0x61,
+0x3b, 0x70, 0x6f, 0x6e, 0x69, 0x65, 0x64, 0x7a, 0x69, 0x61, 0x142, 0x65, 0x6b, 0x3b, 0x77, 0x74, 0x6f, 0x72, 0x65, 0x6b,
+0x3b, 0x15b, 0x72, 0x6f, 0x64, 0x61, 0x3b, 0x63, 0x7a, 0x77, 0x61, 0x72, 0x74, 0x65, 0x6b, 0x3b, 0x70, 0x69, 0x105, 0x74,
+0x65, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x4e, 0x3b, 0x50, 0x3b, 0x57, 0x3b, 0x15a, 0x3b, 0x43, 0x3b,
+0x50, 0x3b, 0x53, 0x3b, 0x6e, 0x3b, 0x70, 0x3b, 0x77, 0x3b, 0x15b, 0x3b, 0x63, 0x3b, 0x70, 0x3b, 0x73, 0x3b, 0x64, 0x6f,
+0x6d, 0x3b, 0x73, 0x65, 0x67, 0x3b, 0x74, 0x65, 0x72, 0x3b, 0x71, 0x75, 0x61, 0x3b, 0x71, 0x75, 0x69, 0x3b, 0x73, 0x65,
+0x78, 0x3b, 0x73, 0xe1, 0x62, 0x3b, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x67, 0x75, 0x6e, 0x64,
+0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x74, 0x65, 0x72, 0xe7, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b,
+0x71, 0x75, 0x61, 0x72, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x71, 0x75, 0x69, 0x6e, 0x74, 0x61, 0x2d,
+0x66, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x73, 0x65, 0x78, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x73, 0xe1,
+0x62, 0x61, 0x64, 0x6f, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x51, 0x3b, 0x51, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x64,
+0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x67, 0x75, 0x6e, 0x64, 0x61, 0x3b, 0x74, 0x65, 0x72, 0xe7, 0x61,
+0x3b, 0x71, 0x75, 0x61, 0x72, 0x74, 0x61, 0x3b, 0x71, 0x75, 0x69, 0x6e, 0x74, 0x61, 0x3b, 0x73, 0x65, 0x78, 0x74, 0x61,
+0x3b, 0x73, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x3b, 0xa10, 0xa24, 0x3b, 0xa38, 0xa4b, 0xa2e, 0x3b, 0xa2e, 0xa70, 0xa17, 0xa32, 0x3b,
+0xa2c, 0xa41, 0xa71, 0xa27, 0x3b, 0xa35, 0xa40, 0xa30, 0x3b, 0xa38, 0xa3c, 0xa41, 0xa71, 0xa15, 0xa30, 0x3b, 0xa38, 0xa3c, 0xa28, 0xa3f,
+0xa71, 0xa1a, 0xa30, 0x3b, 0xa10, 0xa24, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa38, 0xa4b, 0xa2e, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa2e, 0xa70, 0xa17,
+0xa32, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa2c, 0xa41, 0xa71, 0xa27, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa35, 0xa40, 0xa30, 0xa35, 0xa3e, 0xa30, 0x3b,
+0xa38, 0xa3c, 0xa41, 0xa71, 0xa15, 0xa30, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa38, 0xa3c, 0xa28, 0xa3f, 0xa71, 0xa1a, 0xa30, 0xa35, 0xa3e, 0xa30,
+0x3b, 0xa10, 0x3b, 0xa38, 0xa4b, 0x3b, 0xa2e, 0xa70, 0x3b, 0xa2c, 0xa41, 0xa71, 0x3b, 0xa35, 0xa40, 0x3b, 0xa38, 0xa3c, 0xa41, 0xa71,
+0x3b, 0xa38, 0xa3c, 0x3b, 0x627, 0x62a, 0x648, 0x627, 0x631, 0x3b, 0x67e, 0x6cc, 0x631, 0x3b, 0x645, 0x646, 0x6af, 0x644, 0x3b, 0x628,
+0x64f, 0x62f, 0x6be, 0x3b, 0x62c, 0x645, 0x639, 0x631, 0x627, 0x62a, 0x3b, 0x62c, 0x645, 0x639, 0x6c1, 0x3b, 0x6c1, 0x641, 0x62a, 0x6c1,
+0x3b, 0x44, 0x6f, 0x6d, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4d, 0x69, 0xe9, 0x3b, 0x4a, 0x75, 0x65,
+0x3b, 0x56, 0x69, 0x65, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x4c, 0x75, 0x6e,
+0x65, 0x73, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x4d, 0x69, 0xe9, 0x72, 0x63, 0x6f, 0x6c, 0x65, 0x73, 0x3b,
+0x4a, 0x75, 0x65, 0x76, 0x65, 0x73, 0x3b, 0x56, 0x69, 0x65, 0x72, 0x6e, 0x65, 0x73, 0x3b, 0x53, 0xe1, 0x62, 0x61, 0x64,
+0x6f, 0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x58, 0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x64, 0x75, 0x3b, 0x67,
+0x6c, 0x69, 0x3b, 0x6d, 0x61, 0x3b, 0x6d, 0x65, 0x3b, 0x67, 0x69, 0x65, 0x3b, 0x76, 0x65, 0x3b, 0x73, 0x6f, 0x3b, 0x64,
+0x75, 0x6d, 0x65, 0x6e, 0x67, 0x69, 0x61, 0x3b, 0x67, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x73, 0x64, 0x69, 0x3b, 0x6d, 0x61,
+0x72, 0x64, 0x69, 0x3b, 0x6d, 0x65, 0x73, 0x65, 0x6d, 0x6e, 0x61, 0x3b, 0x67, 0x69, 0x65, 0x76, 0x67, 0x69, 0x61, 0x3b,
+0x76, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x64, 0x69, 0x3b, 0x73, 0x6f, 0x6e, 0x64, 0x61, 0x3b, 0x44, 0x3b, 0x47, 0x3b, 0x4d,
+0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x64, 0x75, 0x6d, 0x2e, 0x3b, 0x6c, 0x75, 0x6e, 0x2e, 0x3b, 0x6d,
+0x61, 0x72, 0x2e, 0x3b, 0x6d, 0x69, 0x65, 0x2e, 0x3b, 0x6a, 0x6f, 0x69, 0x3b, 0x76, 0x69, 0x6e, 0x2e, 0x3b, 0x73, 0xe2,
+0x6d, 0x2e, 0x3b, 0x64, 0x75, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x103, 0x3b, 0x6c, 0x75, 0x6e, 0x69, 0x3b, 0x6d, 0x61, 0x72,
+0x21b, 0x69, 0x3b, 0x6d, 0x69, 0x65, 0x72, 0x63, 0x75, 0x72, 0x69, 0x3b, 0x6a, 0x6f, 0x69, 0x3b, 0x76, 0x69, 0x6e, 0x65,
+0x72, 0x69, 0x3b, 0x73, 0xe2, 0x6d, 0x62, 0x103, 0x74, 0x103, 0x3b, 0x44, 0x75, 0x6d, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d,
+0x61, 0x72, 0x3b, 0x4d, 0x69, 0x65, 0x3b, 0x4a, 0x6f, 0x69, 0x3b, 0x56, 0x69, 0x6e, 0x3b, 0x53, 0xe2, 0x6d, 0x3b, 0x44,
+0x3b, 0x4c, 0x3b, 0x4d, 0x61, 0x3b, 0x4d, 0x69, 0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x432, 0x441, 0x3b, 0x43f, 0x43d,
+0x3b, 0x432, 0x442, 0x3b, 0x441, 0x440, 0x3b, 0x447, 0x442, 0x3b, 0x43f, 0x442, 0x3b, 0x441, 0x431, 0x3b, 0x432, 0x43e, 0x441, 0x43a,
+0x440, 0x435, 0x441, 0x435, 0x43d, 0x44c, 0x435, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435, 0x43b, 0x44c, 0x43d, 0x438, 0x43a, 0x3b,
+0x432, 0x442, 0x43e, 0x440, 0x43d, 0x438, 0x43a, 0x3b, 0x441, 0x440, 0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x435, 0x440,
+0x433, 0x3b, 0x43f, 0x44f, 0x442, 0x43d, 0x438, 0x446, 0x430, 0x3b, 0x441, 0x443, 0x431, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x412, 0x3b,
+0x41f, 0x3b, 0x412, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f, 0x3b, 0x421, 0x3b, 0x42, 0x6b, 0x31, 0x3b, 0x42, 0x6b, 0x32, 0x3b,
+0x42, 0x6b, 0x33, 0x3b, 0x42, 0x6b, 0x34, 0x3b, 0x42, 0x6b, 0x35, 0x3b, 0x4c, 0xe2, 0x70, 0x3b, 0x4c, 0xe2, 0x79, 0x3b,
+0x42, 0x69, 0x6b, 0x75, 0x61, 0x2d, 0xf4, 0x6b, 0x6f, 0x3b, 0x42, 0xef, 0x6b, 0x75, 0x61, 0x2d, 0xfb, 0x73, 0x65, 0x3b,
+0x42, 0xef, 0x6b, 0x75, 0x61, 0x2d, 0x70, 0x74, 0xe2, 0x3b, 0x42, 0xef, 0x6b, 0x75, 0x61, 0x2d, 0x75, 0x73, 0xef, 0xf6,
+0x3b, 0x42, 0xef, 0x6b, 0x75, 0x61, 0x2d, 0x6f, 0x6b, 0xfc, 0x3b, 0x4c, 0xe2, 0x70, 0xf4, 0x73, 0xf6, 0x3b, 0x4c, 0xe2,
+0x79, 0x65, 0x6e, 0x67, 0x61, 0x3b, 0x4b, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x4b, 0x3b, 0x50, 0x3b, 0x59, 0x3b,
+0x43d, 0x435, 0x434, 0x3b, 0x43f, 0x43e, 0x43d, 0x3b, 0x443, 0x442, 0x43e, 0x3b, 0x441, 0x440, 0x435, 0x3b, 0x447, 0x435, 0x442, 0x3b,
+0x43f, 0x435, 0x442, 0x3b, 0x441, 0x443, 0x431, 0x3b, 0x43d, 0x435, 0x434, 0x435, 0x459, 0x430, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434,
+0x435, 0x459, 0x430, 0x43a, 0x3b, 0x443, 0x442, 0x43e, 0x440, 0x430, 0x43a, 0x3b, 0x441, 0x440, 0x435, 0x434, 0x430, 0x3b, 0x447, 0x435,
+0x442, 0x432, 0x440, 0x442, 0x430, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x430, 0x43a, 0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442, 0x430, 0x3b,
+0x43d, 0x3b, 0x43f, 0x3b, 0x443, 0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f, 0x3b, 0x441, 0x3b, 0x43d, 0x435, 0x434, 0x3b, 0x43f, 0x43e,
+0x43d, 0x3b, 0x443, 0x442, 0x3b, 0x441, 0x440, 0x3b, 0x447, 0x435, 0x442, 0x3b, 0x43f, 0x435, 0x442, 0x3b, 0x441, 0x443, 0x431, 0x3b,
+0x43d, 0x435, 0x434, 0x458, 0x435, 0x459, 0x430, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435, 0x459, 0x430, 0x43a, 0x3b, 0x443, 0x442,
+0x43e, 0x440, 0x430, 0x43a, 0x3b, 0x441, 0x440, 0x438, 0x458, 0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x440, 0x442, 0x430,
+0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x430, 0x43a, 0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x43d, 0x435, 0x434, 0x2e, 0x3b,
+0x43f, 0x43e, 0x43d, 0x2e, 0x3b, 0x443, 0x442, 0x2e, 0x3b, 0x441, 0x440, 0x2e, 0x3b, 0x447, 0x435, 0x442, 0x2e, 0x3b, 0x43f, 0x435,
+0x442, 0x2e, 0x3b, 0x441, 0x443, 0x431, 0x2e, 0x3b, 0x6e, 0x65, 0x64, 0x3b, 0x70, 0x6f, 0x6e, 0x3b, 0x75, 0x74, 0x3b, 0x73,
+0x72, 0x3b, 0x10d, 0x65, 0x74, 0x3b, 0x70, 0x65, 0x74, 0x3b, 0x73, 0x75, 0x62, 0x3b, 0x6e, 0x65, 0x64, 0x6a, 0x65, 0x6c,
+0x6a, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x6b, 0x3b, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x6b,
+0x3b, 0x73, 0x72, 0x69, 0x6a, 0x65, 0x64, 0x61, 0x3b, 0x10d, 0x65, 0x74, 0x76, 0x72, 0x74, 0x61, 0x6b, 0x3b, 0x70, 0x65,
+0x74, 0x61, 0x6b, 0x3b, 0x73, 0x75, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x6e, 0x65, 0x64, 0x2e, 0x3b, 0x70, 0x6f, 0x6e, 0x2e,
+0x3b, 0x75, 0x74, 0x2e, 0x3b, 0x73, 0x72, 0x2e, 0x3b, 0x10d, 0x65, 0x74, 0x2e, 0x3b, 0x70, 0x65, 0x74, 0x2e, 0x3b, 0x73,
+0x75, 0x62, 0x2e, 0x3b, 0x6e, 0x65, 0x64, 0x3b, 0x70, 0x6f, 0x6e, 0x3b, 0x75, 0x74, 0x6f, 0x3b, 0x73, 0x72, 0x65, 0x3b,
+0x10d, 0x65, 0x74, 0x3b, 0x70, 0x65, 0x74, 0x3b, 0x73, 0x75, 0x62, 0x3b, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x3b,
+0x70, 0x6f, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x6b, 0x3b, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x6b, 0x3b, 0x73, 0x72,
+0x65, 0x64, 0x61, 0x3b, 0x10d, 0x65, 0x74, 0x76, 0x72, 0x74, 0x61, 0x6b, 0x3b, 0x70, 0x65, 0x74, 0x61, 0x6b, 0x3b, 0x73,
+0x75, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x425, 0x446, 0x431, 0x3b, 0x41a, 0x440, 0x441, 0x3b, 0x414, 0x446, 0x433, 0x3b, 0x4d4, 0x440,
+0x442, 0x3b, 0x426, 0x43f, 0x440, 0x3b, 0x41c, 0x440, 0x431, 0x3b, 0x421, 0x431, 0x442, 0x3b, 0x425, 0x443, 0x44b, 0x446, 0x430, 0x443,
+0x431, 0x43e, 0x43d, 0x3b, 0x41a, 0x44a, 0x443, 0x44b, 0x440, 0x438, 0x441, 0x4d5, 0x440, 0x3b, 0x414, 0x44b, 0x446, 0x446, 0x4d5, 0x433,
+0x3b, 0x4d4, 0x440, 0x442, 0x44b, 0x446, 0x446, 0x4d5, 0x433, 0x3b, 0x426, 0x44b, 0x43f, 0x43f, 0x4d5, 0x440, 0x4d5, 0x43c, 0x3b, 0x41c,
+0x430, 0x439, 0x440, 0x4d5, 0x43c, 0x431, 0x43e, 0x43d, 0x3b, 0x421, 0x430, 0x431, 0x430, 0x442, 0x3b, 0x425, 0x3b, 0x41a, 0x3b, 0x414,
+0x3b, 0x4d4, 0x3b, 0x426, 0x3b, 0x41c, 0x3b, 0x421, 0x3b, 0x445, 0x446, 0x431, 0x3b, 0x43a, 0x440, 0x441, 0x3b, 0x434, 0x446, 0x433,
+0x3b, 0x4d5, 0x440, 0x442, 0x3b, 0x446, 0x43f, 0x440, 0x3b, 0x43c, 0x440, 0x431, 0x3b, 0x441, 0x431, 0x442, 0x3b, 0x445, 0x443, 0x44b,
+0x446, 0x430, 0x443, 0x431, 0x43e, 0x43d, 0x3b, 0x43a, 0x44a, 0x443, 0x44b, 0x440, 0x438, 0x441, 0x4d5, 0x440, 0x3b, 0x434, 0x44b, 0x446,
+0x446, 0x4d5, 0x433, 0x3b, 0x4d5, 0x440, 0x442, 0x44b, 0x446, 0x446, 0x4d5, 0x433, 0x3b, 0x446, 0x44b, 0x43f, 0x43f, 0x4d5, 0x440, 0x4d5,
+0x43c, 0x3b, 0x43c, 0x430, 0x439, 0x440, 0x4d5, 0x43c, 0x431, 0x43e, 0x43d, 0x3b, 0x441, 0x430, 0x431, 0x430, 0x442, 0x3b, 0x53, 0x76,
+0x6f, 0x3b, 0x4d, 0x75, 0x76, 0x3b, 0x43, 0x68, 0x70, 0x3b, 0x43, 0x68, 0x74, 0x3b, 0x43, 0x68, 0x6e, 0x3b, 0x43, 0x68,
+0x73, 0x3b, 0x4d, 0x75, 0x67, 0x3b, 0x53, 0x76, 0x6f, 0x6e, 0x64, 0x6f, 0x3b, 0x4d, 0x75, 0x76, 0x68, 0x75, 0x72, 0x6f,
+0x3b, 0x43, 0x68, 0x69, 0x70, 0x69, 0x72, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x43, 0x68, 0x69,
+0x6e, 0x61, 0x3b, 0x43, 0x68, 0x69, 0x73, 0x68, 0x61, 0x6e, 0x75, 0x3b, 0x4d, 0x75, 0x67, 0x6f, 0x76, 0x65, 0x72, 0x61,
+0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x4d, 0x3b, 0x622, 0x686, 0x631, 0x3b, 0x633,
+0x648, 0x645, 0x631, 0x3b, 0x627, 0x6b1, 0x627, 0x631, 0x648, 0x3b, 0x627, 0x631, 0x628, 0x639, 0x3b, 0x62e, 0x645, 0x64a, 0x633, 0x3b,
+0x62c, 0x645, 0x639, 0x648, 0x3b, 0x687, 0x646, 0x687, 0x631, 0x3b, 0x622, 0x686, 0x631, 0x3b, 0x633, 0x648, 0x3b, 0x627, 0x6b1, 0x627,
+0x631, 0x648, 0x3b, 0x627, 0x631, 0x628, 0x639, 0x3b, 0x62e, 0x645, 0x3b, 0x62c, 0x645, 0x639, 0x648, 0x3b, 0x687, 0x646, 0x687, 0x631,
+0x3b, 0xd89, 0xdbb, 0xdd2, 0xdaf, 0xdcf, 0x3b, 0xdc3, 0xdb3, 0xdd4, 0xdaf, 0xdcf, 0x3b, 0xd85, 0xd9f, 0xdc4, 0x3b, 0xdb6, 0xdaf, 0xdcf,
+0xdaf, 0xdcf, 0x3b, 0xdb6, 0xdca, 0x200d, 0xdbb, 0xdc4, 0xdc3, 0xdca, 0x3b, 0xdc3, 0xdd2, 0xd9a, 0xdd4, 0x3b, 0xdc3, 0xdd9, 0xdb1, 0x3b,
+0xd89, 0xdbb, 0xdd2, 0xdaf, 0xdcf, 0x3b, 0xdc3, 0xdb3, 0xdd4, 0xdaf, 0xdcf, 0x3b, 0xd85, 0xd9f, 0xdc4, 0xdbb, 0xdd4, 0xdc0, 0xdcf, 0xdaf,
+0xdcf, 0x3b, 0xdb6, 0xdaf, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xdb6, 0xdca, 0x200d, 0xdbb, 0xdc4, 0xdc3, 0xdca, 0xdb4, 0xdad, 0xdd2, 0xdb1, 0xdca,
+0xdaf, 0xdcf, 0x3b, 0xdc3, 0xdd2, 0xd9a, 0xdd4, 0xdbb, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xdc3, 0xdd9, 0xdb1, 0xdc3, 0xdd4, 0xdbb, 0xdcf, 0xdaf,
+0xdcf, 0x3b, 0xd89, 0x3b, 0xdc3, 0x3b, 0xd85, 0x3b, 0xdb6, 0x3b, 0xdb6, 0xdca, 0x200d, 0xdbb, 0x3b, 0xdc3, 0xdd2, 0x3b, 0xdc3, 0xdd9,
+0x3b, 0x6e, 0x65, 0x3b, 0x70, 0x6f, 0x3b, 0x75, 0x74, 0x3b, 0x73, 0x74, 0x3b, 0x161, 0x74, 0x3b, 0x70, 0x69, 0x3b, 0x73,
+0x6f, 0x3b, 0x6e, 0x65, 0x64, 0x65, 0x13e, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x6c, 0x6f, 0x6b, 0x3b, 0x75, 0x74,
+0x6f, 0x72, 0x6f, 0x6b, 0x3b, 0x73, 0x74, 0x72, 0x65, 0x64, 0x61, 0x3b, 0x161, 0x74, 0x76, 0x72, 0x74, 0x6f, 0x6b, 0x3b,
+0x70, 0x69, 0x61, 0x74, 0x6f, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x6e, 0x3b, 0x70, 0x3b, 0x75, 0x3b,
+0x73, 0x3b, 0x161, 0x3b, 0x70, 0x3b, 0x73, 0x3b, 0x6e, 0x65, 0x64, 0x2e, 0x3b, 0x70, 0x6f, 0x6e, 0x2e, 0x3b, 0x74, 0x6f,
+0x72, 0x2e, 0x3b, 0x73, 0x72, 0x65, 0x2e, 0x3b, 0x10d, 0x65, 0x74, 0x2e, 0x3b, 0x70, 0x65, 0x74, 0x2e, 0x3b, 0x73, 0x6f,
+0x62, 0x2e, 0x3b, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x65,
+0x6b, 0x3b, 0x74, 0x6f, 0x72, 0x65, 0x6b, 0x3b, 0x73, 0x72, 0x65, 0x64, 0x61, 0x3b, 0x10d, 0x65, 0x74, 0x72, 0x74, 0x65,
+0x6b, 0x3b, 0x70, 0x65, 0x74, 0x65, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x6e, 0x3b, 0x70, 0x3b, 0x74,
+0x3b, 0x73, 0x3b, 0x10d, 0x3b, 0x70, 0x3b, 0x73, 0x3b, 0x41, 0x78, 0x64, 0x3b, 0x49, 0x73, 0x6e, 0x3b, 0x54, 0x61, 0x6c,
+0x3b, 0x41, 0x72, 0x62, 0x3b, 0x4b, 0x68, 0x61, 0x3b, 0x4a, 0x69, 0x6d, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x41, 0x78, 0x61,
+0x64, 0x3b, 0x49, 0x73, 0x6e, 0x69, 0x69, 0x6e, 0x3b, 0x54, 0x61, 0x6c, 0x61, 0x61, 0x64, 0x6f, 0x3b, 0x41, 0x72, 0x62,
+0x61, 0x63, 0x6f, 0x3b, 0x4b, 0x68, 0x61, 0x6d, 0x69, 0x69, 0x73, 0x3b, 0x4a, 0x69, 0x6d, 0x63, 0x6f, 0x3b, 0x53, 0x61,
+0x62, 0x74, 0x69, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x4b, 0x68, 0x3b, 0x4a, 0x3b, 0x53, 0x3b, 0x64,
+0x6f, 0x6d, 0x2e, 0x3b, 0x6c, 0x75, 0x6e, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x6d, 0x69, 0xe9, 0x2e, 0x3b, 0x6a,
+0x75, 0x65, 0x2e, 0x3b, 0x76, 0x69, 0x65, 0x2e, 0x3b, 0x73, 0xe1, 0x62, 0x2e, 0x3b, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x67,
+0x6f, 0x3b, 0x6c, 0x75, 0x6e, 0x65, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x6d, 0x69, 0xe9, 0x72, 0x63,
+0x6f, 0x6c, 0x65, 0x73, 0x3b, 0x6a, 0x75, 0x65, 0x76, 0x65, 0x73, 0x3b, 0x76, 0x69, 0x65, 0x72, 0x6e, 0x65, 0x73, 0x3b,
+0x73, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0x69, 0x6c, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61,
+0x74, 0x61, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e,
+0x6f, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75,
+0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x73, 0xf6, 0x6e, 0x3b, 0x6d, 0xe5, 0x6e, 0x3b, 0x74, 0x69, 0x73, 0x3b, 0x6f,
+0x6e, 0x73, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x3b, 0x66, 0x72, 0x65, 0x3b, 0x6c, 0xf6, 0x72, 0x3b, 0x73, 0xf6, 0x6e, 0x64,
+0x61, 0x67, 0x3b, 0x6d, 0xe5, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x69, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x6f, 0x6e, 0x73,
+0x64, 0x61, 0x67, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x66, 0x72, 0x65, 0x64, 0x61, 0x67, 0x3b, 0x6c,
+0xf6, 0x72, 0x64, 0x61, 0x67, 0x3b, 0x42f, 0x448, 0x431, 0x3b, 0x414, 0x448, 0x431, 0x3b, 0x421, 0x448, 0x431, 0x3b, 0x427, 0x448,
+0x431, 0x3b, 0x41f, 0x448, 0x431, 0x3b, 0x4b6, 0x43c, 0x44a, 0x3b, 0x428, 0x43d, 0x431, 0x3b, 0x42f, 0x43a, 0x448, 0x430, 0x43d, 0x431,
+0x435, 0x3b, 0x414, 0x443, 0x448, 0x430, 0x43d, 0x431, 0x435, 0x3b, 0x421, 0x435, 0x448, 0x430, 0x43d, 0x431, 0x435, 0x3b, 0x427, 0x43e,
+0x440, 0x448, 0x430, 0x43d, 0x431, 0x435, 0x3b, 0x41f, 0x430, 0x43d, 0x4b7, 0x448, 0x430, 0x43d, 0x431, 0x435, 0x3b, 0x4b6, 0x443, 0x43c,
+0x44a, 0x430, 0x3b, 0x428, 0x430, 0x43d, 0x431, 0x435, 0x3b, 0x42f, 0x3b, 0x414, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f, 0x3b, 0x4b6,
+0x3b, 0x428, 0x3b, 0xb9e, 0xbbe, 0xbaf, 0xbbf, 0x2e, 0x3b, 0xba4, 0xbbf, 0xb99, 0xbcd, 0x2e, 0x3b, 0xb9a, 0xbc6, 0xbb5, 0xbcd, 0x2e,
+0x3b, 0xbaa, 0xbc1, 0xba4, 0x2e, 0x3b, 0xbb5, 0xbbf, 0xbaf, 0xbbe, 0x2e, 0x3b, 0xbb5, 0xbc6, 0xbb3, 0xbcd, 0x2e, 0x3b, 0xb9a, 0xba9,
+0xbbf, 0x3b, 0xb9e, 0xbbe, 0xbaf, 0xbbf, 0xbb1, 0xbc1, 0x3b, 0xba4, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbb3, 0xbcd, 0x3b, 0xb9a, 0xbc6, 0xbb5,
+0xbcd, 0xbb5, 0xbbe, 0xbaf, 0xbcd, 0x3b, 0xbaa, 0xbc1, 0xba4, 0xba9, 0xbcd, 0x3b, 0xbb5, 0xbbf, 0xbaf, 0xbbe, 0xbb4, 0xba9, 0xbcd, 0x3b,
+0xbb5, 0xbc6, 0xbb3, 0xbcd, 0xbb3, 0xbbf, 0x3b, 0xb9a, 0xba9, 0xbbf, 0x3b, 0xb9e, 0xbbe, 0x3b, 0xba4, 0xbbf, 0x3b, 0xb9a, 0xbc6, 0x3b,
+0xbaa, 0xbc1, 0x3b, 0xbb5, 0xbbf, 0x3b, 0xbb5, 0xbc6, 0x3b, 0xb9a, 0x3b, 0x44f, 0x43a, 0x448, 0x2e, 0x3b, 0x434, 0x4af, 0x448, 0x2e,
+0x3b, 0x441, 0x438, 0x448, 0x2e, 0x3b, 0x447, 0x4d9, 0x440, 0x2e, 0x3b, 0x43f, 0x4d9, 0x43d, 0x497, 0x2e, 0x3b, 0x497, 0x43e, 0x43c,
+0x2e, 0x3b, 0x448, 0x438, 0x43c, 0x2e, 0x3b, 0x44f, 0x43a, 0x448, 0x4d9, 0x43c, 0x431, 0x435, 0x3b, 0x434, 0x4af, 0x448, 0x4d9, 0x43c,
+0x431, 0x435, 0x3b, 0x441, 0x438, 0x448, 0x4d9, 0x43c, 0x431, 0x435, 0x3b, 0x447, 0x4d9, 0x440, 0x448, 0x4d9, 0x43c, 0x431, 0x435, 0x3b,
+0x43f, 0x4d9, 0x43d, 0x497, 0x435, 0x448, 0x4d9, 0x43c, 0x431, 0x435, 0x3b, 0x497, 0x43e, 0x43c, 0x433, 0x430, 0x3b, 0x448, 0x438, 0x43c,
+0x431, 0x4d9, 0x3b, 0x42f, 0x3b, 0x414, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f, 0x3b, 0x496, 0x3b, 0x428, 0x3b, 0xc06, 0xc26, 0xc3f,
+0x3b, 0xc38, 0xc4b, 0xc2e, 0x3b, 0xc2e, 0xc02, 0xc17, 0xc33, 0x3b, 0xc2c, 0xc41, 0xc27, 0x3b, 0xc17, 0xc41, 0xc30, 0xc41, 0x3b, 0xc36,
+0xc41, 0xc15, 0xc4d, 0xc30, 0x3b, 0xc36, 0xc28, 0xc3f, 0x3b, 0xc06, 0xc26, 0xc3f, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc38, 0xc4b, 0xc2e,
+0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc2e, 0xc02, 0xc17, 0xc33, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc2c, 0xc41, 0xc27, 0xc35, 0xc3e, 0xc30,
+0xc02, 0x3b, 0xc17, 0xc41, 0xc30, 0xc41, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc36, 0xc41, 0xc15, 0xc4d, 0xc30, 0xc35, 0xc3e, 0xc30, 0xc02,
+0x3b, 0xc36, 0xc28, 0xc3f, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc06, 0x3b, 0xc38, 0xc4b, 0x3b, 0xc2e, 0x3b, 0xc2c, 0xc41, 0x3b, 0xc17,
+0xc41, 0x3b, 0xc36, 0xc41, 0x3b, 0xc36, 0x3b, 0xe2d, 0xe32, 0x2e, 0x3b, 0xe08, 0x2e, 0x3b, 0xe2d, 0x2e, 0x3b, 0xe1e, 0x2e, 0x3b,
+0xe1e, 0xe24, 0x2e, 0x3b, 0xe28, 0x2e, 0x3b, 0xe2a, 0x2e, 0x3b, 0xe27, 0xe31, 0xe19, 0xe2d, 0xe32, 0xe17, 0xe34, 0xe15, 0xe22, 0xe4c,
+0x3b, 0xe27, 0xe31, 0xe19, 0xe08, 0xe31, 0xe19, 0xe17, 0xe23, 0xe4c, 0x3b, 0xe27, 0xe31, 0xe19, 0xe2d, 0xe31, 0xe07, 0xe04, 0xe32, 0xe23,
+0x3b, 0xe27, 0xe31, 0xe19, 0xe1e, 0xe38, 0xe18, 0x3b, 0xe27, 0xe31, 0xe19, 0xe1e, 0xe24, 0xe2b, 0xe31, 0xe2a, 0xe1a, 0xe14, 0xe35, 0x3b,
+0xe27, 0xe31, 0xe19, 0xe28, 0xe38, 0xe01, 0xe23, 0xe4c, 0x3b, 0xe27, 0xe31, 0xe19, 0xe40, 0xe2a, 0xe32, 0xe23, 0xe4c, 0x3b, 0xe2d, 0xe32,
+0x3b, 0xe08, 0x3b, 0xe2d, 0x3b, 0xe1e, 0x3b, 0xe1e, 0xe24, 0x3b, 0xe28, 0x3b, 0xe2a, 0x3b, 0xf49, 0xf72, 0xf0b, 0xf58, 0xf0b, 0x3b,
+0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0x3b, 0xf58, 0xf72, 0xf42, 0xf0b, 0xf51, 0xf58, 0xf62, 0xf0b, 0x3b, 0xf63, 0xfb7, 0xf42, 0xf0b, 0xf54,
+0xf0b, 0x3b, 0xf55, 0xf74, 0xf62, 0xf0b, 0xf56, 0xf74, 0xf0b, 0x3b, 0xf54, 0xf0b, 0xf66, 0xf44, 0xf66, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xf7a,
+0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf49, 0xf72, 0xf0b, 0xf58, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf5f,
+0xfb3, 0xf0b, 0xf56, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf58, 0xf72, 0xf42, 0xf0b, 0xf51, 0xf58, 0xf62, 0xf0b, 0x3b, 0xf42, 0xf5f,
+0xf60, 0xf0b, 0xf63, 0xfb7, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf55, 0xf74, 0xf62, 0xf0b, 0xf56, 0xf74, 0xf0b,
+0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf54, 0xf0b, 0xf66, 0xf44, 0xf66, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf66, 0xfa4, 0xf7a, 0xf53,
+0xf0b, 0xf54, 0xf0b, 0x3b, 0xf49, 0xf72, 0x3b, 0xf5f, 0xfb3, 0x3b, 0xf58, 0xf72, 0xf42, 0x3b, 0xf63, 0xfb7, 0xf42, 0x3b, 0xf55, 0xf74,
+0xf62, 0x3b, 0xf66, 0xf44, 0xf66, 0x3b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0x3b, 0x1230, 0x1295, 0x3b, 0x1230, 0x1291, 0x3b, 0x1230, 0x1209, 0x3b,
+0x1228, 0x1261, 0x3b, 0x1213, 0x1219, 0x3b, 0x12d3, 0x122d, 0x3b, 0x1240, 0x12f3, 0x3b, 0x1230, 0x1295, 0x1260, 0x1275, 0x3b, 0x1230, 0x1291, 0x12ed,
+0x3b, 0x1220, 0x1209, 0x1235, 0x3b, 0x1228, 0x1261, 0x12d5, 0x3b, 0x1283, 0x1219, 0x1235, 0x3b, 0x12d3, 0x122d, 0x1262, 0x3b, 0x1240, 0x12f3, 0x121d,
+0x3b, 0x1230, 0x3b, 0x1230, 0x3b, 0x1220, 0x3b, 0x1228, 0x3b, 0x1213, 0x3b, 0x12d3, 0x3b, 0x1240, 0x3b, 0x1230, 0x3b, 0x1230, 0x3b, 0x1230,
+0x3b, 0x1228, 0x3b, 0x1213, 0x3b, 0x12d3, 0x3b, 0x1240, 0x3b, 0x53, 0x101, 0x70, 0x3b, 0x4d, 0x14d, 0x6e, 0x3b, 0x54, 0x16b, 0x73,
+0x3b, 0x50, 0x75, 0x6c, 0x3b, 0x54, 0x75, 0x2bb, 0x61, 0x3b, 0x46, 0x61, 0x6c, 0x3b, 0x54, 0x6f, 0x6b, 0x3b, 0x53, 0x101,
+0x70, 0x61, 0x74, 0x65, 0x3b, 0x4d, 0x14d, 0x6e, 0x69, 0x74, 0x65, 0x3b, 0x54, 0x16b, 0x73, 0x69, 0x74, 0x65, 0x3b, 0x50,
+0x75, 0x6c, 0x65, 0x6c, 0x75, 0x6c, 0x75, 0x3b, 0x54, 0x75, 0x2bb, 0x61, 0x70, 0x75, 0x6c, 0x65, 0x6c, 0x75, 0x6c, 0x75,
+0x3b, 0x46, 0x61, 0x6c, 0x61, 0x69, 0x74, 0x65, 0x3b, 0x54, 0x6f, 0x6b, 0x6f, 0x6e, 0x61, 0x6b, 0x69, 0x3b, 0x53, 0x3b,
+0x4d, 0x3b, 0x54, 0x3b, 0x50, 0x3b, 0x54, 0x3b, 0x46, 0x3b, 0x54, 0x3b, 0x50, 0x61, 0x7a, 0x3b, 0x50, 0x7a, 0x74, 0x3b,
+0x53, 0x61, 0x6c, 0x3b, 0xc7, 0x61, 0x72, 0x3b, 0x50, 0x65, 0x72, 0x3b, 0x43, 0x75, 0x6d, 0x3b, 0x43, 0x6d, 0x74, 0x3b,
+0x50, 0x61, 0x7a, 0x61, 0x72, 0x3b, 0x50, 0x61, 0x7a, 0x61, 0x72, 0x74, 0x65, 0x73, 0x69, 0x3b, 0x53, 0x61, 0x6c, 0x131,
+0x3b, 0xc7, 0x61, 0x72, 0x15f, 0x61, 0x6d, 0x62, 0x61, 0x3b, 0x50, 0x65, 0x72, 0x15f, 0x65, 0x6d, 0x62, 0x65, 0x3b, 0x43,
+0x75, 0x6d, 0x61, 0x3b, 0x43, 0x75, 0x6d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x69, 0x3b, 0x50, 0x3b, 0x50, 0x3b, 0x53, 0x3b,
+0xc7, 0x3b, 0x50, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0xdd, 0x65, 0x6b, 0x3b, 0x44, 0x75, 0x15f, 0x3b, 0x53, 0x69, 0x15f, 0x3b,
+0xc7, 0x61, 0x72, 0x3b, 0x50, 0x65, 0x6e, 0x3b, 0x41, 0x6e, 0x6e, 0x3b, 0x15e, 0x65, 0x6e, 0x3b, 0xdd, 0x65, 0x6b, 0x15f,
+0x65, 0x6e, 0x62, 0x65, 0x3b, 0x44, 0x75, 0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0x53, 0x69, 0x15f, 0x65, 0x6e, 0x62, 0x65,
+0x3b, 0xc7, 0x61, 0x72, 0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0x50, 0x65, 0x6e, 0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0x41,
+0x6e, 0x6e, 0x61, 0x3b, 0x15e, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0xdd, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0xc7, 0x3b, 0x50, 0x3b,
+0x41, 0x3b, 0x15e, 0x3b, 0xfd, 0x65, 0x6b, 0x3b, 0x64, 0x75, 0x15f, 0x3b, 0x73, 0x69, 0x15f, 0x3b, 0xe7, 0x61, 0x72, 0x3b,
+0x70, 0x65, 0x6e, 0x3b, 0x61, 0x6e, 0x6e, 0x3b, 0x15f, 0x65, 0x6e, 0x3b, 0xfd, 0x65, 0x6b, 0x15f, 0x65, 0x6e, 0x62, 0x65,
+0x3b, 0x64, 0x75, 0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0x73, 0x69, 0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0xe7, 0x61, 0x72,
+0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0x70, 0x65, 0x6e, 0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0x61, 0x6e, 0x6e, 0x61, 0x3b,
+0x15f, 0x65, 0x6e, 0x62, 0x65, 0x3b, 0x64a, 0x6d5, 0x3b, 0x62f, 0x6c8, 0x3b, 0x633, 0x6d5, 0x3b, 0x686, 0x627, 0x3b, 0x67e, 0x6d5,
+0x3b, 0x62c, 0x6c8, 0x3b, 0x634, 0x6d5, 0x3b, 0x64a, 0x6d5, 0x643, 0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x3b, 0x62f, 0x6c8, 0x634, 0x6d5,
+0x646, 0x628, 0x6d5, 0x3b, 0x633, 0x6d5, 0x64a, 0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x3b, 0x686, 0x627, 0x631, 0x634, 0x6d5, 0x646, 0x628,
+0x6d5, 0x3b, 0x67e, 0x6d5, 0x64a, 0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x3b, 0x62c, 0x6c8, 0x645, 0x6d5, 0x3b, 0x634, 0x6d5, 0x646, 0x628,
+0x6d5, 0x3b, 0x64a, 0x3b, 0x62f, 0x3b, 0x633, 0x3b, 0x686, 0x3b, 0x67e, 0x3b, 0x62c, 0x3b, 0x634, 0x3b, 0x43d, 0x435, 0x434, 0x456,
+0x43b, 0x44f, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x456, 0x43b, 0x43e, 0x43a, 0x3b, 0x432, 0x456, 0x432, 0x442, 0x43e, 0x440, 0x43e,
+0x43a, 0x3b, 0x441, 0x435, 0x440, 0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x435, 0x440, 0x3b, 0x43f, 0x2bc, 0x44f, 0x442,
+0x43d, 0x438, 0x446, 0x44f, 0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x41d, 0x3b, 0x41f, 0x3b, 0x412, 0x3b, 0x421, 0x3b,
+0x427, 0x3b, 0x41f, 0x3b, 0x421, 0x3b, 0x627, 0x62a, 0x648, 0x627, 0x631, 0x3b, 0x67e, 0x6cc, 0x631, 0x3b, 0x645, 0x646, 0x6af, 0x644,
+0x3b, 0x628, 0x62f, 0x6be, 0x3b, 0x62c, 0x645, 0x639, 0x631, 0x627, 0x62a, 0x3b, 0x62c, 0x645, 0x639, 0x6c1, 0x3b, 0x6c1, 0x641, 0x62a,
+0x6c1, 0x3b, 0x59, 0x61, 0x6b, 0x3b, 0x44, 0x75, 0x73, 0x68, 0x3b, 0x53, 0x65, 0x73, 0x68, 0x3b, 0x43, 0x68, 0x6f, 0x72,
+0x3b, 0x50, 0x61, 0x79, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x53, 0x68, 0x61, 0x6e, 0x3b, 0x79, 0x61, 0x6b, 0x73, 0x68, 0x61,
+0x6e, 0x62, 0x61, 0x3b, 0x64, 0x75, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x61, 0x3b, 0x73, 0x65, 0x73, 0x68, 0x61, 0x6e, 0x62,
+0x61, 0x3b, 0x63, 0x68, 0x6f, 0x72, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x61, 0x3b, 0x70, 0x61, 0x79, 0x73, 0x68, 0x61, 0x6e,
+0x62, 0x61, 0x3b, 0x6a, 0x75, 0x6d, 0x61, 0x3b, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x61, 0x3b, 0x59, 0x3b, 0x44, 0x3b, 0x53,
+0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x4a, 0x3b, 0x53, 0x3b, 0x6cc, 0x2e, 0x3b, 0x62f, 0x2e, 0x3b, 0x633, 0x2e, 0x3b, 0x686, 0x2e,
+0x3b, 0x67e, 0x2e, 0x3b, 0x62c, 0x2e, 0x3b, 0x634, 0x2e, 0x3b, 0x44f, 0x43a, 0x448, 0x3b, 0x434, 0x443, 0x448, 0x3b, 0x441, 0x435,
+0x448, 0x3b, 0x447, 0x43e, 0x440, 0x3b, 0x43f, 0x430, 0x439, 0x3b, 0x436, 0x443, 0x43c, 0x3b, 0x448, 0x430, 0x43d, 0x3b, 0x44f, 0x43a,
+0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x434, 0x443, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x441, 0x435, 0x448, 0x430, 0x43d, 0x431,
+0x430, 0x3b, 0x447, 0x43e, 0x440, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x43f, 0x430, 0x439, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b,
+0x436, 0x443, 0x43c, 0x430, 0x3b, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x42f, 0x3b, 0x414, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f,
+0x3b, 0x416, 0x3b, 0x428, 0x3b, 0x43, 0x4e, 0x3b, 0x54, 0x68, 0x20, 0x32, 0x3b, 0x54, 0x68, 0x20, 0x33, 0x3b, 0x54, 0x68,
+0x20, 0x34, 0x3b, 0x54, 0x68, 0x20, 0x35, 0x3b, 0x54, 0x68, 0x20, 0x36, 0x3b, 0x54, 0x68, 0x20, 0x37, 0x3b, 0x43, 0x68,
+0x1ee7, 0x20, 0x4e, 0x68, 0x1ead, 0x74, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x48, 0x61, 0x69, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x42,
+0x61, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x54, 0x1b0, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x4e, 0x103, 0x6d, 0x3b, 0x54, 0x68, 0x1ee9,
+0x20, 0x53, 0xe1, 0x75, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x42, 0x1ea3, 0x79, 0x3b, 0x43, 0x4e, 0x3b, 0x54, 0x32, 0x3b, 0x54,
+0x33, 0x3b, 0x54, 0x34, 0x3b, 0x54, 0x35, 0x3b, 0x54, 0x36, 0x3b, 0x54, 0x37, 0x3b, 0x53, 0x75, 0x3b, 0x4d, 0x75, 0x3b,
+0x54, 0x75, 0x3b, 0x56, 0x65, 0x3b, 0x44, 0xf6, 0x3b, 0x46, 0x72, 0x3b, 0x5a, 0xe4, 0x3b, 0x73, 0x75, 0x64, 0x65, 0x6c,
+0x3b, 0x6d, 0x75, 0x64, 0x65, 0x6c, 0x3b, 0x74, 0x75, 0x64, 0x65, 0x6c, 0x3b, 0x76, 0x65, 0x64, 0x65, 0x6c, 0x3b, 0x64,
+0xf6, 0x64, 0x65, 0x6c, 0x3b, 0x66, 0x72, 0x69, 0x64, 0x65, 0x6c, 0x3b, 0x7a, 0xe4, 0x64, 0x65, 0x6c, 0x3b, 0x53, 0x3b,
+0x4d, 0x3b, 0x54, 0x3b, 0x56, 0x3b, 0x44, 0x3b, 0x46, 0x3b, 0x5a, 0x3b, 0x73, 0x75, 0x2e, 0x3b, 0x6d, 0x75, 0x2e, 0x3b,
+0x74, 0x75, 0x2e, 0x3b, 0x76, 0x65, 0x2e, 0x3b, 0x64, 0xf6, 0x2e, 0x3b, 0x66, 0x72, 0x2e, 0x3b, 0x7a, 0xe4, 0x2e, 0x3b,
+0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x6c, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x77, 0x3b, 0x4d, 0x65, 0x72, 0x3b, 0x49, 0x61, 0x75,
+0x3b, 0x47, 0x77, 0x65, 0x3b, 0x53, 0x61, 0x64, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x53, 0x75, 0x6c, 0x3b, 0x44, 0x79,
+0x64, 0x64, 0x20, 0x4c, 0x6c, 0x75, 0x6e, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x4d, 0x61, 0x77, 0x72, 0x74, 0x68, 0x3b,
+0x44, 0x79, 0x64, 0x64, 0x20, 0x4d, 0x65, 0x72, 0x63, 0x68, 0x65, 0x72, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x49, 0x61,
+0x75, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x47, 0x77, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x53,
+0x61, 0x64, 0x77, 0x72, 0x6e, 0x3b, 0x53, 0x3b, 0x4c, 0x6c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x47, 0x3b, 0x53,
+0x3b, 0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x6c, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x77, 0x3b, 0x4d, 0x65, 0x72, 0x3b, 0x49, 0x61,
+0x75, 0x3b, 0x47, 0x77, 0x65, 0x6e, 0x3b, 0x53, 0x61, 0x64, 0x3b, 0x44, 0x69, 0x62, 0x3b, 0x41, 0x6c, 0x74, 0x3b, 0x54,
+0x61, 0x6c, 0x3b, 0xc0, 0x6c, 0x61, 0x3b, 0x41, 0x6c, 0x78, 0x3b, 0xc0, 0x6a, 0x6a, 0x3b, 0x41, 0x73, 0x65, 0x3b, 0x44,
+0x69, 0x62, 0xe9, 0x65, 0x72, 0x3b, 0x41, 0x6c, 0x74, 0x69, 0x6e, 0x65, 0x3b, 0x54, 0x61, 0x6c, 0x61, 0x61, 0x74, 0x61,
+0x3b, 0xc0, 0x6c, 0x61, 0x72, 0x62, 0x61, 0x3b, 0x41, 0x6c, 0x78, 0x61, 0x6d, 0x69, 0x73, 0x3b, 0xc0, 0x6a, 0x6a, 0x75,
+0x6d, 0x61, 0x3b, 0x41, 0x73, 0x65, 0x65, 0x72, 0x3b, 0x43, 0x61, 0x77, 0x3b, 0x4d, 0x76, 0x75, 0x3b, 0x42, 0x69, 0x6e,
+0x3b, 0x54, 0x68, 0x61, 0x3b, 0x53, 0x69, 0x6e, 0x3b, 0x48, 0x6c, 0x61, 0x3b, 0x4d, 0x67, 0x71, 0x3b, 0x43, 0x61, 0x77,
+0x65, 0x3b, 0x4d, 0x76, 0x75, 0x6c, 0x6f, 0x3b, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x62, 0x69, 0x6e, 0x69, 0x3b, 0x4c, 0x77,
+0x65, 0x73, 0x69, 0x74, 0x68, 0x61, 0x74, 0x68, 0x75, 0x3b, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x6e, 0x65, 0x3b, 0x4c, 0x77,
+0x65, 0x73, 0x69, 0x68, 0x6c, 0x61, 0x6e, 0x75, 0x3b, 0x4d, 0x67, 0x71, 0x69, 0x62, 0x65, 0x6c, 0x6f, 0x3b, 0x5d6, 0x5d5,
+0x5e0, 0x5d8, 0x5d9, 0x5e7, 0x3b, 0x5de, 0x5d0, 0x5b8, 0x5e0, 0x5d8, 0x5d9, 0x5e7, 0x3b, 0x5d3, 0x5d9, 0x5e0, 0x5e1, 0x5d8, 0x5d9, 0x5e7,
+0x3b, 0x5de, 0x5d9, 0x5d8, 0x5d5, 0x5d5, 0x5d0, 0x5da, 0x3b, 0x5d3, 0x5d0, 0x5e0, 0x5e2, 0x5e8, 0x5e9, 0x5d8, 0x5d9, 0x5e7, 0x3b, 0x5e4,
+0x5bf, 0x5e8, 0x5f2, 0x5b7, 0x5d8, 0x5d9, 0x5e7, 0x3b, 0x5e9, 0x5d1, 0x5ea, 0x3b, 0xc0, 0xec, 0x6b, 0xfa, 0x3b, 0x41, 0x6a, 0xe9,
+0x3b, 0xcc, 0x73, 0x1eb9, 0x301, 0x67, 0x75, 0x6e, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x72, 0xfa, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301,
+0x62, 0x1ecd, 0x3b, 0x1eb8, 0x74, 0xec, 0x3b, 0xc0, 0x62, 0xe1, 0x6d, 0x1eb9, 0x301, 0x74, 0x61, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301,
+0x20, 0xc0, 0xec, 0x6b, 0xfa, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20, 0x41, 0x6a, 0xe9, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20,
+0xcc, 0x73, 0x1eb9, 0x301, 0x67, 0x75, 0x6e, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x72, 0xfa, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x62,
+0x1ecd, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20, 0x1eb8, 0x74, 0xec, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20, 0xc0, 0x62, 0xe1, 0x6d,
+0x1eb9, 0x301, 0x74, 0x61, 0x3b, 0xc0, 0xec, 0x6b, 0xfa, 0x3b, 0x41, 0x6a, 0xe9, 0x3b, 0xcc, 0x73, 0x25b, 0x301, 0x67, 0x75,
+0x6e, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x72, 0xfa, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x62, 0x254, 0x3b, 0x190, 0x74, 0xec, 0x3b,
+0xc0, 0x62, 0xe1, 0x6d, 0x25b, 0x301, 0x74, 0x61, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x20, 0xc0, 0xec, 0x6b, 0xfa, 0x3b, 0x186,
+0x6a, 0x254, 0x301, 0x20, 0x41, 0x6a, 0xe9, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x20, 0xcc, 0x73, 0x25b, 0x301, 0x67, 0x75, 0x6e,
+0x3b, 0x186, 0x6a, 0x254, 0x301, 0x72, 0xfa, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x62, 0x254, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x20,
+0x190, 0x74, 0xec, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x20, 0xc0, 0x62, 0xe1, 0x6d, 0x25b, 0x301, 0x74, 0x61, 0x3b, 0x53, 0x6f,
+0x6e, 0x3b, 0x4d, 0x73, 0x6f, 0x3b, 0x42, 0x69, 0x6c, 0x3b, 0x54, 0x68, 0x61, 0x3b, 0x53, 0x69, 0x6e, 0x3b, 0x48, 0x6c,
+0x61, 0x3b, 0x4d, 0x67, 0x71, 0x3b, 0x49, 0x53, 0x6f, 0x6e, 0x74, 0x6f, 0x3b, 0x55, 0x4d, 0x73, 0x6f, 0x6d, 0x62, 0x75,
+0x6c, 0x75, 0x6b, 0x6f, 0x3b, 0x55, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x3b, 0x55, 0x4c, 0x77, 0x65,
+0x73, 0x69, 0x74, 0x68, 0x61, 0x74, 0x68, 0x75, 0x3b, 0x55, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x6e, 0x65, 0x3b, 0x55, 0x4c,
+0x77, 0x65, 0x73, 0x69, 0x68, 0x6c, 0x61, 0x6e, 0x75, 0x3b, 0x55, 0x4d, 0x67, 0x71, 0x69, 0x62, 0x65, 0x6c, 0x6f, 0x3b,
+0x53, 0x3b, 0x4d, 0x3b, 0x42, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x48, 0x3b, 0x4d, 0x3b, 0x73, 0xf8, 0x6e, 0x3b, 0x6d, 0xe5,
+0x6e, 0x3b, 0x74, 0x79, 0x73, 0x3b, 0x6f, 0x6e, 0x73, 0x3b, 0x74, 0x6f, 0x72, 0x3b, 0x66, 0x72, 0x65, 0x3b, 0x6c, 0x61,
+0x75, 0x3b, 0x73, 0xf8, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x6d, 0xe5, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x79, 0x73, 0x64,
+0x61, 0x67, 0x3b, 0x6f, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x66, 0x72,
+0x65, 0x64, 0x61, 0x67, 0x3b, 0x6c, 0x61, 0x75, 0x72, 0x64, 0x61, 0x67, 0x3b, 0x73, 0xf8, 0x2e, 0x3b, 0x6d, 0xe5, 0x2e,
+0x3b, 0x74, 0x79, 0x2e, 0x3b, 0x6f, 0x6e, 0x2e, 0x3b, 0x74, 0x6f, 0x2e, 0x3b, 0x66, 0x72, 0x2e, 0x3b, 0x6c, 0x61, 0x2e,
+0x3b, 0x43d, 0x435, 0x434, 0x3b, 0x43f, 0x43e, 0x43d, 0x3b, 0x443, 0x442, 0x43e, 0x3b, 0x441, 0x440, 0x438, 0x3b, 0x447, 0x435, 0x442,
+0x3b, 0x43f, 0x435, 0x442, 0x3b, 0x441, 0x443, 0x431, 0x3b, 0x43d, 0x435, 0x434, 0x458, 0x435, 0x459, 0x430, 0x3b, 0x43f, 0x43e, 0x43d,
+0x435, 0x434, 0x458, 0x435, 0x459, 0x430, 0x43a, 0x3b, 0x443, 0x442, 0x43e, 0x440, 0x430, 0x43a, 0x3b, 0x441, 0x440, 0x438, 0x458, 0x435,
+0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x440, 0x442, 0x430, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x430, 0x43a, 0x3b, 0x441, 0x443,
+0x431, 0x43e, 0x442, 0x430, 0x3b, 0x4a, 0x65, 0x64, 0x3b, 0x4a, 0x65, 0x6c, 0x3b, 0x4a, 0x65, 0x6d, 0x3b, 0x4a, 0x65, 0x72,
+0x63, 0x3b, 0x4a, 0x65, 0x72, 0x64, 0x3b, 0x4a, 0x65, 0x68, 0x3b, 0x4a, 0x65, 0x73, 0x3b, 0x4a, 0x65, 0x64, 0x6f, 0x6f,
+0x6e, 0x65, 0x65, 0x3b, 0x4a, 0x65, 0x6c, 0x68, 0x65, 0x69, 0x6e, 0x3b, 0x4a, 0x65, 0x6d, 0x61, 0x79, 0x72, 0x74, 0x3b,
+0x4a, 0x65, 0x72, 0x63, 0x65, 0x61, 0x6e, 0x3b, 0x4a, 0x65, 0x72, 0x64, 0x65, 0x69, 0x6e, 0x3b, 0x4a, 0x65, 0x68, 0x65,
+0x69, 0x6e, 0x65, 0x79, 0x3b, 0x4a, 0x65, 0x73, 0x61, 0x72, 0x6e, 0x3b, 0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x75, 0x6e, 0x3b,
+0x4d, 0x74, 0x68, 0x3b, 0x4d, 0x68, 0x72, 0x3b, 0x59, 0x6f, 0x77, 0x3b, 0x47, 0x77, 0x65, 0x3b, 0x53, 0x61, 0x64, 0x3b,
+0x64, 0x79, 0x20, 0x53, 0x75, 0x6c, 0x3b, 0x64, 0x79, 0x20, 0x4c, 0x75, 0x6e, 0x3b, 0x64, 0x79, 0x20, 0x4d, 0x65, 0x75,
+0x72, 0x74, 0x68, 0x3b, 0x64, 0x79, 0x20, 0x4d, 0x65, 0x72, 0x68, 0x65, 0x72, 0x3b, 0x64, 0x79, 0x20, 0x59, 0x6f, 0x77,
+0x3b, 0x64, 0x79, 0x20, 0x47, 0x77, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x64, 0x79, 0x20, 0x53, 0x61, 0x64, 0x6f, 0x72, 0x6e,
+0x3b, 0x4b, 0x77, 0x65, 0x3b, 0x44, 0x77, 0x6f, 0x3b, 0x42, 0x65, 0x6e, 0x3b, 0x57, 0x75, 0x6b, 0x3b, 0x59, 0x61, 0x77,
+0x3b, 0x46, 0x69, 0x61, 0x3b, 0x4d, 0x65, 0x6d, 0x3b, 0x4b, 0x77, 0x65, 0x73, 0x69, 0x64, 0x61, 0x3b, 0x44, 0x77, 0x6f,
+0x77, 0x64, 0x61, 0x3b, 0x42, 0x65, 0x6e, 0x61, 0x64, 0x61, 0x3b, 0x57, 0x75, 0x6b, 0x75, 0x64, 0x61, 0x3b, 0x59, 0x61,
+0x77, 0x64, 0x61, 0x3b, 0x46, 0x69, 0x64, 0x61, 0x3b, 0x4d, 0x65, 0x6d, 0x65, 0x6e, 0x65, 0x64, 0x61, 0x3b, 0x4b, 0x3b,
+0x44, 0x3b, 0x42, 0x3b, 0x57, 0x3b, 0x59, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x906, 0x92f, 0x924, 0x93e, 0x930, 0x3b, 0x938, 0x94b,
+0x92e, 0x93e, 0x930, 0x3b, 0x92e, 0x902, 0x917, 0x933, 0x93e, 0x930, 0x3b, 0x92c, 0x941, 0x927, 0x935, 0x93e, 0x930, 0x3b, 0x917, 0x941,
+0x930, 0x941, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x93e, 0x930, 0x3b, 0x936, 0x947, 0x928, 0x935, 0x93e, 0x930,
+0x3b, 0x906, 0x3b, 0x938, 0x94b, 0x3b, 0x92e, 0x902, 0x3b, 0x92c, 0x941, 0x3b, 0x917, 0x941, 0x3b, 0x936, 0x941, 0x3b, 0x936, 0x947,
+0x3b, 0x1ee4, 0x6b, 0x61, 0x3b, 0x4d, 0x1ecd, 0x6e, 0x3b, 0x54, 0x69, 0x75, 0x3b, 0x57, 0x65, 0x6e, 0x3b, 0x54, 0x1ecd, 0x1ecd,
+0x3b, 0x46, 0x72, 0x61, 0x1ecb, 0x3b, 0x53, 0x61, 0x74, 0x3b, 0x4d, 0x62, 0x1ecd, 0x73, 0x1ecb, 0x20, 0x1ee4, 0x6b, 0x61, 0x3b,
+0x4d, 0x1ecd, 0x6e, 0x64, 0x65, 0x3b, 0x54, 0x69, 0x75, 0x7a, 0x64, 0x65, 0x65, 0x3b, 0x57, 0x65, 0x6e, 0x65, 0x7a, 0x64,
+0x65, 0x65, 0x3b, 0x54, 0x1ecd, 0x1ecd, 0x7a, 0x64, 0x65, 0x65, 0x3b, 0x46, 0x72, 0x61, 0x1ecb, 0x64, 0x65, 0x65, 0x3b, 0x53,
+0x61, 0x74, 0x1ecd, 0x64, 0x65, 0x65, 0x3b, 0x57, 0x6b, 0x79, 0x3b, 0x57, 0x6b, 0x77, 0x3b, 0x57, 0x6b, 0x6c, 0x3b, 0x57,
+0x74, 0x169, 0x3b, 0x57, 0x6b, 0x6e, 0x3b, 0x57, 0x74, 0x6e, 0x3b, 0x57, 0x74, 0x68, 0x3b, 0x57, 0x61, 0x20, 0x6b, 0x79,
+0x75, 0x6d, 0x77, 0x61, 0x3b, 0x57, 0x61, 0x20, 0x6b, 0x77, 0x61, 0x6d, 0x62, 0x129, 0x6c, 0x129, 0x6c, 0x79, 0x61, 0x3b,
+0x57, 0x61, 0x20, 0x6b, 0x65, 0x6c, 0x129, 0x3b, 0x57, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x61, 0x74, 0x169, 0x3b, 0x57, 0x61,
+0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x57, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x57, 0x61, 0x20, 0x74,
+0x68, 0x61, 0x6e, 0x74, 0x68, 0x61, 0x74, 0x169, 0x3b, 0x59, 0x3b, 0x57, 0x3b, 0x45, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41,
+0x3b, 0x41, 0x3b, 0x64, 0x6f, 0x6d, 0x3b, 0x6c, 0x75, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d, 0x69, 0x65, 0x3b, 0x6a,
+0x6f, 0x69, 0x3b, 0x76, 0x69, 0x6e, 0x3b, 0x73, 0x61, 0x62, 0x3b, 0x64, 0x6f, 0x6d, 0x65, 0x6e, 0x69, 0x65, 0x3b, 0x6c,
+0x75, 0x6e, 0x69, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x61, 0x72, 0x73, 0x3b, 0x6d, 0x69, 0x65, 0x72, 0x63, 0x75, 0x73,
+0x3b, 0x6a, 0x6f, 0x69, 0x62, 0x65, 0x3b, 0x76, 0x69, 0x6e, 0x61, 0x72, 0x73, 0x3b, 0x73, 0x61, 0x62, 0x69, 0x64, 0x65,
+0x3b, 0x6b, 0x254, 0x73, 0x3b, 0x64, 0x7a, 0x6f, 0x3b, 0x62, 0x6c, 0x61, 0x3b, 0x6b, 0x75, 0x256, 0x3b, 0x79, 0x61, 0x77,
+0x3b, 0x66, 0x69, 0x256, 0x3b, 0x6d, 0x65, 0x6d, 0x3b, 0x6b, 0x254, 0x73, 0x69, 0x256, 0x61, 0x3b, 0x64, 0x7a, 0x6f, 0x256,
+0x61, 0x3b, 0x62, 0x6c, 0x61, 0x256, 0x61, 0x3b, 0x6b, 0x75, 0x256, 0x61, 0x3b, 0x79, 0x61, 0x77, 0x6f, 0x256, 0x61, 0x3b,
+0x66, 0x69, 0x256, 0x61, 0x3b, 0x6d, 0x65, 0x6d, 0x6c, 0x65, 0x256, 0x61, 0x3b, 0x6b, 0x3b, 0x64, 0x3b, 0x62, 0x3b, 0x6b,
+0x3b, 0x79, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x4c, 0x50, 0x3b, 0x50, 0x31, 0x3b, 0x50, 0x32, 0x3b, 0x50, 0x33, 0x3b, 0x50,
+0x34, 0x3b, 0x50, 0x35, 0x3b, 0x50, 0x36, 0x3b, 0x4c, 0x101, 0x70, 0x75, 0x6c, 0x65, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x6b,
+0x61, 0x68, 0x69, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x6c, 0x75, 0x61, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x6b, 0x6f, 0x6c, 0x75,
+0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x68, 0x101, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x6c, 0x69, 0x6d, 0x61, 0x3b, 0x50, 0x6f, 0x2bb,
+0x61, 0x6f, 0x6e, 0x6f, 0x3b, 0x4c, 0x69, 0x6e, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4d, 0x69, 0x79,
+0x3b, 0x48, 0x75, 0x77, 0x3b, 0x42, 0x69, 0x79, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x4c, 0x69, 0x6e, 0x67, 0x67, 0x6f, 0x3b,
+0x4c, 0x75, 0x6e, 0x65, 0x73, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x4d, 0x69, 0x79, 0x65, 0x72, 0x6b, 0x75,
+0x6c, 0x65, 0x73, 0x3b, 0x48, 0x75, 0x77, 0x65, 0x62, 0x65, 0x73, 0x3b, 0x42, 0x69, 0x79, 0x65, 0x72, 0x6e, 0x65, 0x73,
+0x3b, 0x53, 0x61, 0x62, 0x61, 0x64, 0x6f, 0x3b, 0x53, 0x75, 0x2e, 0x3b, 0x4d, 0xe4, 0x2e, 0x3b, 0x5a, 0x69, 0x2e, 0x3b,
+0x4d, 0x69, 0x2e, 0x3b, 0x44, 0x75, 0x2e, 0x3b, 0x46, 0x72, 0x2e, 0x3b, 0x53, 0x61, 0x2e, 0x3b, 0x53, 0x75, 0x6e, 0x6e,
+0x74, 0x69, 0x67, 0x3b, 0x4d, 0xe4, 0xe4, 0x6e, 0x74, 0x69, 0x67, 0x3b, 0x5a, 0x69, 0x69, 0x73, 0x63, 0x68, 0x74, 0x69,
+0x67, 0x3b, 0x4d, 0x69, 0x74, 0x74, 0x77, 0x75, 0x63, 0x68, 0x3b, 0x44, 0x75, 0x6e, 0x73, 0x63, 0x68, 0x74, 0x69, 0x67,
+0x3b, 0x46, 0x72, 0x69, 0x69, 0x74, 0x69, 0x67, 0x3b, 0x53, 0x61, 0x6d, 0x73, 0x63, 0x68, 0x74, 0x69, 0x67, 0x3b, 0xa46d,
+0xa18f, 0x3b, 0xa18f, 0xa2cd, 0x3b, 0xa18f, 0xa44d, 0x3b, 0xa18f, 0xa315, 0x3b, 0xa18f, 0xa1d6, 0x3b, 0xa18f, 0xa26c, 0x3b, 0xa18f, 0xa0d8, 0x3b,
+0xa46d, 0xa18f, 0xa44d, 0x3b, 0xa18f, 0xa282, 0xa2cd, 0x3b, 0xa18f, 0xa282, 0xa44d, 0x3b, 0xa18f, 0xa282, 0xa315, 0x3b, 0xa18f, 0xa282, 0xa1d6, 0x3b,
+0xa18f, 0xa282, 0xa26c, 0x3b, 0xa18f, 0xa282, 0xa0d8, 0x3b, 0xa18f, 0x3b, 0xa2cd, 0x3b, 0xa44d, 0x3b, 0xa315, 0x3b, 0xa1d6, 0x3b, 0xa26c, 0x3b,
+0xa0d8, 0x3b, 0x53, 0xfc, 0x2e, 0x3b, 0x4d, 0x61, 0x2e, 0x3b, 0x44, 0x69, 0x2e, 0x3b, 0x4d, 0x69, 0x2e, 0x3b, 0x44, 0x75,
+0x2e, 0x3b, 0x46, 0x72, 0x2e, 0x3b, 0x53, 0x61, 0x2e, 0x3b, 0x53, 0xfc, 0x6e, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x4d, 0x61,
+0x61, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x44, 0x69, 0x6e, 0x67, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x4d, 0x69, 0x64, 0x64, 0x65,
+0x77, 0x65, 0x6b, 0x65, 0x6e, 0x3b, 0x44, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x46, 0x72, 0x65,
+0x65, 0x64, 0x61, 0x67, 0x3b, 0x53, 0xfc, 0x6e, 0x6e, 0x61, 0x76, 0x65, 0x6e, 0x64, 0x3b, 0x73, 0x6f, 0x74, 0x6e, 0x3b,
+0x76, 0x75, 0x6f, 0x73, 0x3b, 0x6d, 0x61, 0x14b, 0x3b, 0x67, 0x61, 0x73, 0x6b, 0x3b, 0x64, 0x75, 0x6f, 0x72, 0x3b, 0x62,
+0x65, 0x61, 0x72, 0x3b, 0x6c, 0xe1, 0x76, 0x3b, 0x73, 0x6f, 0x74, 0x6e, 0x61, 0x62, 0x65, 0x61, 0x69, 0x76, 0x69, 0x3b,
+0x76, 0x75, 0x6f, 0x73, 0x73, 0xe1, 0x72, 0x67, 0x61, 0x3b, 0x6d, 0x61, 0x14b, 0x14b, 0x65, 0x62, 0xe1, 0x72, 0x67, 0x61,
+0x3b, 0x67, 0x61, 0x73, 0x6b, 0x61, 0x76, 0x61, 0x68, 0x6b, 0x6b, 0x75, 0x3b, 0x64, 0x75, 0x6f, 0x72, 0x61, 0x73, 0x64,
+0x61, 0x74, 0x3b, 0x62, 0x65, 0x61, 0x72, 0x6a, 0x61, 0x64, 0x61, 0x74, 0x3b, 0x6c, 0xe1, 0x76, 0x76, 0x61, 0x72, 0x64,
+0x61, 0x74, 0x3b, 0x53, 0x3b, 0x56, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x4c, 0x3b, 0x73, 0x6f, 0x3b,
+0x6d, 0xe1, 0x3b, 0x64, 0x69, 0x3b, 0x67, 0x61, 0x3b, 0x64, 0x75, 0x3b, 0x62, 0x65, 0x3b, 0x6c, 0xe1, 0x3b, 0x73, 0x6f,
+0x74, 0x6e, 0x61, 0x62, 0x65, 0x61, 0x69, 0x76, 0x69, 0x3b, 0x6d, 0xe1, 0x6e, 0x6e, 0x6f, 0x64, 0x61, 0x74, 0x3b, 0x64,
+0x69, 0x73, 0x64, 0x61, 0x74, 0x3b, 0x67, 0x61, 0x73, 0x6b, 0x61, 0x76, 0x61, 0x68, 0x6b, 0x6b, 0x75, 0x3b, 0x64, 0x75,
+0x6f, 0x72, 0x61, 0x73, 0x74, 0x61, 0x74, 0x3b, 0x62, 0x65, 0x61, 0x72, 0x6a, 0x61, 0x64, 0x61, 0x74, 0x3b, 0x6c, 0xe1,
+0x76, 0x76, 0x6f, 0x72, 0x64, 0x61, 0x74, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x47, 0x3b, 0x44, 0x3b, 0x42, 0x3b,
+0x4c, 0x3b, 0x43, 0x70, 0x72, 0x3b, 0x43, 0x74, 0x74, 0x3b, 0x43, 0x6d, 0x6e, 0x3b, 0x43, 0x6d, 0x74, 0x3b, 0x41, 0x72,
0x73, 0x3b, 0x49, 0x63, 0x6d, 0x3b, 0x45, 0x73, 0x74, 0x3b, 0x43, 0x68, 0x75, 0x6d, 0x61, 0x70, 0x69, 0x72, 0x69, 0x3b,
0x43, 0x68, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x6f, 0x3b, 0x43, 0x68, 0x75, 0x6d, 0x61, 0x69, 0x6e, 0x65, 0x3b, 0x43,
0x68, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x72, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x63, 0x68,
@@ -4537,296 +4747,306 @@ static const ushort days_data[] = {
0x61, 0x73, 0x61, 0x3b, 0x61, 0x79, 0x6e, 0x3b, 0x61, 0x73, 0x69, 0x3b, 0x61, 0x6b, 0x1e5b, 0x3b, 0x61, 0x6b, 0x77, 0x3b,
0x61, 0x73, 0x69, 0x6d, 0x3b, 0x61, 0x73, 0x69, 0x1e0d, 0x3b, 0x61, 0x73, 0x61, 0x6d, 0x61, 0x73, 0x3b, 0x61, 0x79, 0x6e,
0x61, 0x73, 0x3b, 0x61, 0x73, 0x69, 0x6e, 0x61, 0x73, 0x3b, 0x61, 0x6b, 0x1e5b, 0x61, 0x73, 0x3b, 0x61, 0x6b, 0x77, 0x61,
-0x73, 0x3b, 0x61, 0x73, 0x69, 0x6d, 0x77, 0x61, 0x73, 0x3b, 0x61, 0x73, 0x69, 0x1e0d, 0x79, 0x61, 0x73, 0x3b, 0x59, 0x61,
-0x6e, 0x3b, 0x53, 0x61, 0x6e, 0x3b, 0x4b, 0x72, 0x61, 0x1e0d, 0x3b, 0x4b, 0x75, 0x1e93, 0x3b, 0x53, 0x61, 0x6d, 0x3b, 0x53,
-0x1e0d, 0x69, 0x73, 0x3b, 0x53, 0x61, 0x79, 0x3b, 0x59, 0x61, 0x6e, 0x61, 0x73, 0x73, 0x3b, 0x53, 0x61, 0x6e, 0x61, 0x73,
-0x73, 0x3b, 0x4b, 0x72, 0x61, 0x1e0d, 0x61, 0x73, 0x73, 0x3b, 0x4b, 0x75, 0x1e93, 0x61, 0x73, 0x73, 0x3b, 0x53, 0x61, 0x6d,
-0x61, 0x73, 0x73, 0x3b, 0x53, 0x1e0d, 0x69, 0x73, 0x61, 0x73, 0x73, 0x3b, 0x53, 0x61, 0x79, 0x61, 0x73, 0x73, 0x3b, 0x59,
-0x3b, 0x53, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x53, 0x41, 0x4e, 0x3b, 0x4f, 0x52, 0x4b,
-0x3b, 0x4f, 0x4b, 0x42, 0x3b, 0x4f, 0x4b, 0x53, 0x3b, 0x4f, 0x4b, 0x4e, 0x3b, 0x4f, 0x4b, 0x54, 0x3b, 0x4f, 0x4d, 0x4b,
-0x3b, 0x53, 0x61, 0x6e, 0x64, 0x65, 0x3b, 0x4f, 0x72, 0x77, 0x6f, 0x6b, 0x75, 0x62, 0x61, 0x6e, 0x7a, 0x61, 0x3b, 0x4f,
-0x72, 0x77, 0x61, 0x6b, 0x61, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4f, 0x72, 0x77, 0x61, 0x6b, 0x61, 0x73, 0x68, 0x61, 0x74,
-0x75, 0x3b, 0x4f, 0x72, 0x77, 0x61, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4f, 0x72, 0x77, 0x61, 0x6b, 0x61, 0x74, 0x61, 0x61,
-0x6e, 0x6f, 0x3b, 0x4f, 0x72, 0x77, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x61, 0x67, 0x61, 0x3b, 0x53, 0x3b, 0x4b, 0x3b, 0x52,
-0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x4d, 0x3b, 0x4d, 0x75, 0x6c, 0x3b, 0x56, 0x69, 0x6c, 0x3b, 0x48, 0x69, 0x76,
-0x3b, 0x48, 0x69, 0x64, 0x3b, 0x48, 0x69, 0x74, 0x3b, 0x48, 0x69, 0x68, 0x3b, 0x4c, 0x65, 0x6d, 0x3b, 0x70, 0x61, 0x20,
-0x6d, 0x75, 0x6c, 0x75, 0x6e, 0x67, 0x75, 0x3b, 0x70, 0x61, 0x20, 0x73, 0x68, 0x61, 0x68, 0x75, 0x76, 0x69, 0x6c, 0x75,
-0x68, 0x61, 0x3b, 0x70, 0x61, 0x20, 0x68, 0x69, 0x76, 0x69, 0x6c, 0x69, 0x3b, 0x70, 0x61, 0x20, 0x68, 0x69, 0x64, 0x61,
-0x74, 0x75, 0x3b, 0x70, 0x61, 0x20, 0x68, 0x69, 0x74, 0x61, 0x79, 0x69, 0x3b, 0x70, 0x61, 0x20, 0x68, 0x69, 0x68, 0x61,
-0x6e, 0x75, 0x3b, 0x70, 0x61, 0x20, 0x73, 0x68, 0x61, 0x68, 0x75, 0x6c, 0x65, 0x6d, 0x62, 0x65, 0x6c, 0x61, 0x3b, 0x4d,
-0x3b, 0x4a, 0x3b, 0x48, 0x3b, 0x48, 0x3b, 0x48, 0x3b, 0x57, 0x3b, 0x4a, 0x3b, 0x4a, 0x70, 0x69, 0x3b, 0x4a, 0x74, 0x74,
-0x3b, 0x4a, 0x6e, 0x6e, 0x3b, 0x4a, 0x74, 0x6e, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x75, 0x3b, 0x4a, 0x6d, 0x6f,
-0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0x69, 0x6c, 0x79, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x75, 0x75,
-0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x75, 0x3b, 0x41, 0x6c,
-0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f,
-0x73, 0x69, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x4a, 0x3b, 0x6b, 0x61, 0x72,
-0x3b, 0x6e, 0x74, 0x25b, 0x3b, 0x74, 0x61, 0x72, 0x3b, 0x61, 0x72, 0x61, 0x3b, 0x61, 0x6c, 0x61, 0x3b, 0x6a, 0x75, 0x6d,
-0x3b, 0x73, 0x69, 0x62, 0x3b, 0x6b, 0x61, 0x72, 0x69, 0x3b, 0x6e, 0x74, 0x25b, 0x6e, 0x25b, 0x3b, 0x74, 0x61, 0x72, 0x61,
-0x74, 0x61, 0x3b, 0x61, 0x72, 0x61, 0x62, 0x61, 0x3b, 0x61, 0x6c, 0x61, 0x6d, 0x69, 0x73, 0x61, 0x3b, 0x6a, 0x75, 0x6d,
-0x61, 0x3b, 0x73, 0x69, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x4a,
-0x3b, 0x53, 0x3b, 0x4b, 0x6d, 0x61, 0x3b, 0x54, 0x61, 0x74, 0x3b, 0x49, 0x6e, 0x65, 0x3b, 0x54, 0x61, 0x6e, 0x3b, 0x41,
-0x72, 0x6d, 0x3b, 0x4d, 0x61, 0x61, 0x3b, 0x4e, 0x4d, 0x4d, 0x3b, 0x4b, 0x69, 0x75, 0x6d, 0x69, 0x61, 0x3b, 0x4e, 0x6a,
-0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x69, 0x6e, 0x65, 0x3b, 0x4e, 0x6a, 0x75,
-0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x72, 0x61, 0x6d, 0x69, 0x74, 0x68, 0x69, 0x3b, 0x4e, 0x6a, 0x75, 0x6d,
-0x61, 0x61, 0x3b, 0x4e, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x74, 0x68, 0x69, 0x69, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x4e,
-0x3b, 0x4e, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x13c6, 0x13cd, 0x13ac, 0x3b, 0x13c9, 0x13c5, 0x13af, 0x3b, 0x13d4, 0x13b5, 0x13c1,
-0x3b, 0x13e6, 0x13a2, 0x13c1, 0x3b, 0x13c5, 0x13a9, 0x13c1, 0x3b, 0x13e7, 0x13be, 0x13a9, 0x3b, 0x13c8, 0x13d5, 0x13be, 0x3b, 0x13a4, 0x13be, 0x13d9,
-0x13d3, 0x13c6, 0x13cd, 0x13ac, 0x3b, 0x13a4, 0x13be, 0x13d9, 0x13d3, 0x13c9, 0x13c5, 0x13af, 0x3b, 0x13d4, 0x13b5, 0x13c1, 0x13a2, 0x13a6, 0x3b, 0x13e6,
-0x13a2, 0x13c1, 0x13a2, 0x13a6, 0x3b, 0x13c5, 0x13a9, 0x13c1, 0x13a2, 0x13a6, 0x3b, 0x13e7, 0x13be, 0x13a9, 0x13b6, 0x13cd, 0x13d7, 0x3b, 0x13a4, 0x13be,
-0x13d9, 0x13d3, 0x13c8, 0x13d5, 0x13be, 0x3b, 0x13c6, 0x3b, 0x13c9, 0x3b, 0x13d4, 0x3b, 0x13e6, 0x3b, 0x13c5, 0x3b, 0x13e7, 0x3b, 0x13a4, 0x3b,
-0x64, 0x69, 0x6d, 0x3b, 0x6c, 0x69, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d, 0x65, 0x72, 0x3b, 0x7a, 0x65, 0x3b, 0x76,
-0x61, 0x6e, 0x3b, 0x73, 0x61, 0x6d, 0x3b, 0x64, 0x69, 0x6d, 0x61, 0x6e, 0x73, 0x3b, 0x6c, 0x69, 0x6e, 0x64, 0x69, 0x3b,
-0x6d, 0x61, 0x72, 0x64, 0x69, 0x3b, 0x6d, 0x65, 0x72, 0x6b, 0x72, 0x65, 0x64, 0x69, 0x3b, 0x7a, 0x65, 0x64, 0x69, 0x3b,
-0x76, 0x61, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x69, 0x3b, 0x73, 0x61, 0x6d, 0x64, 0x69, 0x3b, 0x64, 0x3b, 0x6c, 0x3b, 0x6d,
-0x3b, 0x6d, 0x3b, 0x7a, 0x3b, 0x76, 0x3b, 0x73, 0x3b, 0x4c, 0x6c, 0x32, 0x3b, 0x4c, 0x6c, 0x33, 0x3b, 0x4c, 0x6c, 0x34,
-0x3b, 0x4c, 0x6c, 0x35, 0x3b, 0x4c, 0x6c, 0x36, 0x3b, 0x4c, 0x6c, 0x37, 0x3b, 0x4c, 0x6c, 0x31, 0x3b, 0x4c, 0x69, 0x64,
-0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x70, 0x69, 0x6c, 0x69, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c,
-0x79, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x6e, 0x63, 0x68,
-0x65, 0x63, 0x68, 0x69, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x6e, 0x6e, 0x79, 0x61, 0x6e,
-0x6f, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x6e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e,
-0x61, 0x20, 0x6c, 0x69, 0x6e, 0x6a, 0x69, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x6e, 0x6e,
-0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x76, 0x69, 0x6c, 0x69, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76,
-0x61, 0x20, 0x6c, 0x69, 0x74, 0x61, 0x6e, 0x64, 0x69, 0x3b, 0x50, 0xed, 0x69, 0x6c, 0x69, 0x3b, 0x54, 0xe1, 0x61, 0x74,
-0x75, 0x3b, 0xcd, 0x6e, 0x65, 0x3b, 0x54, 0xe1, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x6d, 0x3b,
-0x4d, 0xf3, 0x6f, 0x73, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0xed, 0x69, 0x72, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61,
-0x74, 0xe1, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0xed, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0xe1, 0x61,
-0x6e, 0x6f, 0x3b, 0x41, 0x6c, 0x61, 0x6d, 0xed, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0xe1, 0x61, 0x3b, 0x4a,
-0x75, 0x6d, 0x61, 0x6d, 0xf3, 0x6f, 0x73, 0x69, 0x3b, 0x50, 0x3b, 0x54, 0x3b, 0x45, 0x3b, 0x4f, 0x3b, 0x41, 0x3b, 0x49,
-0x3b, 0x4d, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x42, 0x61, 0x6c, 0x3b, 0x4c, 0x77, 0x32, 0x3b, 0x4c, 0x77, 0x33, 0x3b, 0x4c,
-0x77, 0x34, 0x3b, 0x4c, 0x77, 0x35, 0x3b, 0x4c, 0x77, 0x36, 0x3b, 0x53, 0x61, 0x62, 0x62, 0x69, 0x69, 0x74, 0x69, 0x3b,
-0x42, 0x61, 0x6c, 0x61, 0x7a, 0x61, 0x3b, 0x4c, 0x77, 0x61, 0x6b, 0x75, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4c, 0x77, 0x61,
-0x6b, 0x75, 0x73, 0x61, 0x74, 0x75, 0x3b, 0x4c, 0x77, 0x61, 0x6b, 0x75, 0x6e, 0x61, 0x3b, 0x4c, 0x77, 0x61, 0x6b, 0x75,
-0x74, 0x61, 0x61, 0x6e, 0x6f, 0x3b, 0x4c, 0x77, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x61, 0x67, 0x61, 0x3b, 0x53, 0x3b, 0x42,
-0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x50, 0x61, 0x20, 0x4d, 0x75, 0x6c, 0x75, 0x6e, 0x67,
-0x75, 0x3b, 0x50, 0x61, 0x6c, 0x69, 0x63, 0x68, 0x69, 0x6d, 0x6f, 0x3b, 0x50, 0x61, 0x6c, 0x69, 0x63, 0x68, 0x69, 0x62,
-0x75, 0x6c, 0x69, 0x3b, 0x50, 0x61, 0x6c, 0x69, 0x63, 0x68, 0x69, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x50, 0x61, 0x6c, 0x69,
-0x63, 0x68, 0x69, 0x6e, 0x65, 0x3b, 0x50, 0x61, 0x6c, 0x69, 0x63, 0x68, 0x69, 0x73, 0x61, 0x6e, 0x6f, 0x3b, 0x50, 0x61,
-0x63, 0x68, 0x69, 0x62, 0x65, 0x6c, 0x75, 0x73, 0x68, 0x69, 0x3b, 0x64, 0x75, 0x6d, 0x3b, 0x73, 0x69, 0x67, 0x3b, 0x74,
-0x65, 0x72, 0x3b, 0x6b, 0x75, 0x61, 0x3b, 0x6b, 0x69, 0x6e, 0x3b, 0x73, 0x65, 0x73, 0x3b, 0x73, 0x61, 0x62, 0x3b, 0x64,
-0x75, 0x6d, 0x69, 0x6e, 0x67, 0x75, 0x3b, 0x73, 0x69, 0x67, 0x75, 0x6e, 0x64, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b,
-0x74, 0x65, 0x72, 0x73, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x6b, 0x75, 0x61, 0x72, 0x74, 0x61, 0x2d, 0x66, 0x65,
-0x72, 0x61, 0x3b, 0x6b, 0x69, 0x6e, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x73, 0x65, 0x73, 0x74, 0x61, 0x2d,
-0x66, 0x65, 0x72, 0x61, 0x3b, 0x73, 0xe1, 0x62, 0x61, 0x64, 0x75, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x4b, 0x3b,
-0x4b, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x64, 0x75, 0x6d, 0x69, 0x6e, 0x67, 0x75, 0x3b, 0x73, 0x69, 0x67, 0x75, 0x6e, 0x64,
-0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x74, 0x65, 0x72, 0x73, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x6b, 0x75,
-0x61, 0x72, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x6b, 0x69, 0x6e, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61,
-0x3b, 0x73, 0x65, 0x73, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x73, 0x61, 0x62, 0x61, 0x64, 0x75, 0x3b, 0x4b,
-0x49, 0x55, 0x3b, 0x4d, 0x52, 0x41, 0x3b, 0x57, 0x41, 0x49, 0x3b, 0x57, 0x45, 0x54, 0x3b, 0x57, 0x45, 0x4e, 0x3b, 0x57,
-0x54, 0x4e, 0x3b, 0x4a, 0x55, 0x4d, 0x3b, 0x4b, 0x69, 0x75, 0x6d, 0x69, 0x61, 0x3b, 0x4d, 0x75, 0x72, 0x61, 0x6d, 0x75,
-0x6b, 0x6f, 0x3b, 0x57, 0x61, 0x69, 0x72, 0x69, 0x3b, 0x57, 0x65, 0x74, 0x68, 0x61, 0x74, 0x75, 0x3b, 0x57, 0x65, 0x6e,
-0x61, 0x3b, 0x57, 0x65, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x4b, 0x3b,
-0x4d, 0x3b, 0x57, 0x3b, 0x57, 0x3b, 0x57, 0x3b, 0x57, 0x3b, 0x4a, 0x3b, 0x4b, 0x74, 0x73, 0x3b, 0x4b, 0x6f, 0x74, 0x3b,
-0x4b, 0x6f, 0x6f, 0x3b, 0x4b, 0x6f, 0x73, 0x3b, 0x4b, 0x6f, 0x61, 0x3b, 0x4b, 0x6f, 0x6d, 0x3b, 0x4b, 0x6f, 0x6c, 0x3b,
-0x4b, 0x6f, 0x74, 0x69, 0x73, 0x61, 0x70, 0x3b, 0x4b, 0x6f, 0x74, 0x61, 0x61, 0x69, 0x3b, 0x4b, 0x6f, 0x61, 0x65, 0x6e,
-0x67, 0x2019, 0x3b, 0x4b, 0x6f, 0x73, 0x6f, 0x6d, 0x6f, 0x6b, 0x3b, 0x4b, 0x6f, 0x61, 0x6e, 0x67, 0x2019, 0x77, 0x61, 0x6e,
-0x3b, 0x4b, 0x6f, 0x6d, 0x75, 0x75, 0x74, 0x3b, 0x4b, 0x6f, 0x6c, 0x6f, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4f, 0x3b, 0x53,
-0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4c, 0x3b, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0x61, 0x3b, 0x44, 0x65, 0x3b, 0x57, 0x75, 0x3b,
-0x44, 0x6f, 0x3b, 0x46, 0x72, 0x3b, 0x53, 0x61, 0x74, 0x3b, 0x53, 0x6f, 0x6e, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65,
-0x73, 0x3b, 0x4d, 0x61, 0x6e, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x44, 0x65, 0x6e, 0x73, 0x74, 0x61,
-0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x57, 0x75, 0x6e, 0x73, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b,
-0x44, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x46, 0x72, 0x61, 0x69, 0x74,
-0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x53, 0x61, 0x74, 0x65, 0x72, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65,
-0x73, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x57, 0x3b, 0x44, 0x3b, 0x46, 0x3b, 0x41, 0x3b, 0x53, 0x75, 0x2e, 0x3b,
-0x4d, 0x6f, 0x2e, 0x3b, 0x44, 0x69, 0x2e, 0x3b, 0x4d, 0x65, 0x2e, 0x3b, 0x44, 0x75, 0x2e, 0x3b, 0x46, 0x72, 0x2e, 0x3b,
-0x53, 0x61, 0x2e, 0x3b, 0x53, 0x75, 0x6e, 0x6e, 0x64, 0x61, 0x61, 0x63, 0x68, 0x3b, 0x4d, 0x6f, 0x68, 0x6e, 0x64, 0x61,
-0x61, 0x63, 0x68, 0x3b, 0x44, 0x69, 0x6e, 0x6e, 0x73, 0x64, 0x61, 0x61, 0x63, 0x68, 0x3b, 0x4d, 0x65, 0x74, 0x77, 0x6f,
-0x63, 0x68, 0x3b, 0x44, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x64, 0x61, 0x61, 0x63, 0x68, 0x3b, 0x46, 0x72, 0x69, 0x69,
-0x64, 0x61, 0x61, 0x63, 0x68, 0x3b, 0x53, 0x61, 0x6d, 0x73, 0x64, 0x61, 0x61, 0x63, 0x68, 0x3b, 0x4a, 0x75, 0x6d, 0x61,
-0x70, 0xed, 0x6c, 0xed, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0xe1, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x65,
-0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0xe1, 0x6e, 0x254, 0x3b, 0x41, 0x6c, 0x61, 0xe1, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x4a,
-0x75, 0x6d, 0xe1, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0xf3, 0x73, 0x69, 0x3b, 0x53, 0x61, 0x62, 0x69, 0x3b, 0x42,
-0x61, 0x6c, 0x61, 0x3b, 0x4b, 0x75, 0x62, 0x69, 0x3b, 0x4b, 0x75, 0x73, 0x61, 0x3b, 0x4b, 0x75, 0x6e, 0x61, 0x3b, 0x4b,
-0x75, 0x74, 0x61, 0x3b, 0x4d, 0x75, 0x6b, 0x61, 0x3b, 0x53, 0x61, 0x62, 0x69, 0x69, 0x74, 0x69, 0x3b, 0x42, 0x61, 0x6c,
-0x61, 0x7a, 0x61, 0x3b, 0x4f, 0x77, 0x6f, 0x6b, 0x75, 0x62, 0x69, 0x6c, 0x69, 0x3b, 0x4f, 0x77, 0x6f, 0x6b, 0x75, 0x73,
-0x61, 0x74, 0x75, 0x3b, 0x4f, 0x6c, 0x6f, 0x6b, 0x75, 0x6e, 0x61, 0x3b, 0x4f, 0x6c, 0x6f, 0x6b, 0x75, 0x74, 0x61, 0x61,
-0x6e, 0x75, 0x3b, 0x4f, 0x6c, 0x6f, 0x6d, 0x75, 0x6b, 0x61, 0x61, 0x67, 0x61, 0x3b, 0x53, 0x3b, 0x42, 0x3b, 0x42, 0x3b,
-0x53, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b, 0x4a, 0x32, 0x3b, 0x4a, 0x33, 0x3b, 0x4a, 0x34, 0x3b, 0x4a, 0x35, 0x3b,
-0x41, 0x6c, 0x3b, 0x49, 0x6a, 0x3b, 0x4a, 0x31, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0x69, 0x72, 0x69, 0x3b, 0x4a, 0x75,
-0x6d, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74,
-0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x75, 0x72, 0x77, 0x61, 0x20, 0x77, 0x61, 0x20, 0x4b, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4d,
-0x75, 0x72, 0x77, 0x61, 0x20, 0x77, 0x61, 0x20, 0x4b, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d,
-0x6f, 0x73, 0x69, 0x3b, 0x4a, 0x70, 0x69, 0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6e, 0x6e, 0x3b, 0x4a, 0x74, 0x6e, 0x3b,
-0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x6d, 0x3b, 0x4a, 0x6d, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x42, 0x61, 0x72, 0x3b,
-0x41, 0x61, 0x72, 0x3b, 0x55, 0x6e, 0x69, 0x3b, 0x55, 0x6e, 0x67, 0x3b, 0x4b, 0x61, 0x6e, 0x3b, 0x53, 0x61, 0x62, 0x3b,
-0x4e, 0x61, 0x6b, 0x61, 0x65, 0x6a, 0x75, 0x6d, 0x61, 0x3b, 0x4e, 0x61, 0x6b, 0x61, 0x65, 0x62, 0x61, 0x72, 0x61, 0x73,
-0x61, 0x3b, 0x4e, 0x61, 0x6b, 0x61, 0x61, 0x72, 0x65, 0x3b, 0x4e, 0x61, 0x6b, 0x61, 0x75, 0x6e, 0x69, 0x3b, 0x4e, 0x61,
-0x6b, 0x61, 0x75, 0x6e, 0x67, 0x2019, 0x6f, 0x6e, 0x3b, 0x4e, 0x61, 0x6b, 0x61, 0x6b, 0x61, 0x6e, 0x79, 0x3b, 0x4e, 0x61,
-0x6b, 0x61, 0x73, 0x61, 0x62, 0x69, 0x74, 0x69, 0x3b, 0x4a, 0x3b, 0x42, 0x3b, 0x41, 0x3b, 0x55, 0x3b, 0x55, 0x3b, 0x4b,
-0x3b, 0x53, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x41, 0x74, 0x69, 0x3b, 0x41, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x3b, 0x41,
-0x6c, 0x6d, 0x3b, 0x41, 0x6c, 0x6a, 0x3b, 0x41, 0x73, 0x73, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x64, 0x69, 0x3b, 0x41, 0x74,
-0x69, 0x6e, 0x69, 0x3b, 0x41, 0x74, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x72, 0x62, 0x61, 0x3b, 0x41,
-0x6c, 0x68, 0x61, 0x6d, 0x69, 0x69, 0x73, 0x61, 0x3b, 0x41, 0x6c, 0x6a, 0x75, 0x6d, 0x61, 0x3b, 0x41, 0x73, 0x73, 0x61,
-0x62, 0x64, 0x75, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x53, 0x3b, 0x4a, 0x4d,
-0x50, 0x3b, 0x57, 0x55, 0x54, 0x3b, 0x54, 0x41, 0x52, 0x3b, 0x54, 0x41, 0x44, 0x3b, 0x54, 0x41, 0x4e, 0x3b, 0x54, 0x41,
-0x42, 0x3b, 0x4e, 0x47, 0x53, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0x69, 0x6c, 0x3b, 0x57, 0x75, 0x6f, 0x6b, 0x20, 0x54,
-0x69, 0x63, 0x68, 0x3b, 0x54, 0x69, 0x63, 0x68, 0x20, 0x41, 0x72, 0x69, 0x79, 0x6f, 0x3b, 0x54, 0x69, 0x63, 0x68, 0x20,
-0x41, 0x64, 0x65, 0x6b, 0x3b, 0x54, 0x69, 0x63, 0x68, 0x20, 0x41, 0x6e, 0x67, 0x2019, 0x77, 0x65, 0x6e, 0x3b, 0x54, 0x69,
-0x63, 0x68, 0x20, 0x41, 0x62, 0x69, 0x63, 0x68, 0x3b, 0x4e, 0x67, 0x65, 0x73, 0x6f, 0x3b, 0x4a, 0x3b, 0x57, 0x3b, 0x54,
-0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4e, 0x3b, 0x41, 0x73, 0x61, 0x3b, 0x41, 0x79, 0x6e, 0x3b, 0x41, 0x73, 0x6e,
-0x3b, 0x41, 0x6b, 0x72, 0x3b, 0x41, 0x6b, 0x77, 0x3b, 0x41, 0x73, 0x6d, 0x3b, 0x41, 0x73, 0x1e0d, 0x3b, 0x41, 0x73, 0x61,
-0x6d, 0x61, 0x73, 0x3b, 0x41, 0x79, 0x6e, 0x61, 0x73, 0x3b, 0x41, 0x73, 0x69, 0x6e, 0x61, 0x73, 0x3b, 0x41, 0x6b, 0x72,
-0x61, 0x73, 0x3b, 0x41, 0x6b, 0x77, 0x61, 0x73, 0x3b, 0x41, 0x73, 0x69, 0x6d, 0x77, 0x61, 0x73, 0x3b, 0x41, 0x73, 0x69,
-0x1e0d, 0x79, 0x61, 0x73, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41,
+0x73, 0x3b, 0x61, 0x73, 0x69, 0x6d, 0x77, 0x61, 0x73, 0x3b, 0x61, 0x73, 0x69, 0x1e0d, 0x79, 0x61, 0x73, 0x3b, 0x41, 0x63,
+0x65, 0x3b, 0x41, 0x72, 0x69, 0x3b, 0x41, 0x72, 0x61, 0x3b, 0x41, 0x68, 0x61, 0x3b, 0x41, 0x6d, 0x68, 0x3b, 0x53, 0x65,
+0x6d, 0x3b, 0x53, 0x65, 0x64, 0x3b, 0x41, 0x63, 0x65, 0x72, 0x3b, 0x41, 0x72, 0x69, 0x6d, 0x3b, 0x41, 0x72, 0x61, 0x6d,
+0x3b, 0x41, 0x68, 0x61, 0x64, 0x3b, 0x41, 0x6d, 0x68, 0x61, 0x64, 0x3b, 0x53, 0x65, 0x6d, 0x3b, 0x53, 0x65, 0x64, 0x3b,
+0x59, 0x3b, 0x53, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x59, 0x61, 0x6e, 0x3b, 0x53, 0x61,
+0x6e, 0x3b, 0x4b, 0x72, 0x61, 0x1e0d, 0x3b, 0x4b, 0x75, 0x1e93, 0x3b, 0x53, 0x61, 0x6d, 0x3b, 0x53, 0x1e0d, 0x69, 0x73, 0x3b,
+0x53, 0x61, 0x79, 0x3b, 0x59, 0x61, 0x6e, 0x61, 0x73, 0x73, 0x3b, 0x53, 0x61, 0x6e, 0x61, 0x73, 0x73, 0x3b, 0x4b, 0x72,
+0x61, 0x1e0d, 0x61, 0x73, 0x73, 0x3b, 0x4b, 0x75, 0x1e93, 0x61, 0x73, 0x73, 0x3b, 0x53, 0x61, 0x6d, 0x61, 0x73, 0x73, 0x3b,
+0x53, 0x1e0d, 0x69, 0x73, 0x61, 0x73, 0x73, 0x3b, 0x53, 0x61, 0x79, 0x61, 0x73, 0x73, 0x3b, 0x43, 0x3b, 0x52, 0x3b, 0x41,
+0x3b, 0x48, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x44, 0x3b, 0x53, 0x41, 0x4e, 0x3b, 0x4f, 0x52, 0x4b, 0x3b, 0x4f, 0x4b, 0x42,
+0x3b, 0x4f, 0x4b, 0x53, 0x3b, 0x4f, 0x4b, 0x4e, 0x3b, 0x4f, 0x4b, 0x54, 0x3b, 0x4f, 0x4d, 0x4b, 0x3b, 0x53, 0x61, 0x6e,
+0x64, 0x65, 0x3b, 0x4f, 0x72, 0x77, 0x6f, 0x6b, 0x75, 0x62, 0x61, 0x6e, 0x7a, 0x61, 0x3b, 0x4f, 0x72, 0x77, 0x61, 0x6b,
+0x61, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4f, 0x72, 0x77, 0x61, 0x6b, 0x61, 0x73, 0x68, 0x61, 0x74, 0x75, 0x3b, 0x4f, 0x72,
+0x77, 0x61, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4f, 0x72, 0x77, 0x61, 0x6b, 0x61, 0x74, 0x61, 0x61, 0x6e, 0x6f, 0x3b, 0x4f,
+0x72, 0x77, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x61, 0x67, 0x61, 0x3b, 0x53, 0x3b, 0x4b, 0x3b, 0x52, 0x3b, 0x53, 0x3b, 0x4e,
+0x3b, 0x54, 0x3b, 0x4d, 0x3b, 0x4d, 0x75, 0x6c, 0x3b, 0x56, 0x69, 0x6c, 0x3b, 0x48, 0x69, 0x76, 0x3b, 0x48, 0x69, 0x64,
+0x3b, 0x48, 0x69, 0x74, 0x3b, 0x48, 0x69, 0x68, 0x3b, 0x4c, 0x65, 0x6d, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x75, 0x6c, 0x75,
+0x6e, 0x67, 0x75, 0x3b, 0x70, 0x61, 0x20, 0x73, 0x68, 0x61, 0x68, 0x75, 0x76, 0x69, 0x6c, 0x75, 0x68, 0x61, 0x3b, 0x70,
+0x61, 0x20, 0x68, 0x69, 0x76, 0x69, 0x6c, 0x69, 0x3b, 0x70, 0x61, 0x20, 0x68, 0x69, 0x64, 0x61, 0x74, 0x75, 0x3b, 0x70,
+0x61, 0x20, 0x68, 0x69, 0x74, 0x61, 0x79, 0x69, 0x3b, 0x70, 0x61, 0x20, 0x68, 0x69, 0x68, 0x61, 0x6e, 0x75, 0x3b, 0x70,
+0x61, 0x20, 0x73, 0x68, 0x61, 0x68, 0x75, 0x6c, 0x65, 0x6d, 0x62, 0x65, 0x6c, 0x61, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x48,
+0x3b, 0x48, 0x3b, 0x48, 0x3b, 0x57, 0x3b, 0x4a, 0x3b, 0x4a, 0x70, 0x69, 0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6e, 0x6e,
+0x3b, 0x4a, 0x74, 0x6e, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x75, 0x3b, 0x4a, 0x6d, 0x6f, 0x3b, 0x4a, 0x75, 0x6d,
+0x61, 0x70, 0x69, 0x6c, 0x79, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x75, 0x75, 0x3b, 0x4a, 0x75, 0x6d,
+0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x75, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69,
+0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x4a,
+0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x4a, 0x3b, 0x6b, 0x61, 0x72, 0x3b, 0x6e, 0x74, 0x25b,
+0x3b, 0x74, 0x61, 0x72, 0x3b, 0x61, 0x72, 0x61, 0x3b, 0x61, 0x6c, 0x61, 0x3b, 0x6a, 0x75, 0x6d, 0x3b, 0x73, 0x69, 0x62,
+0x3b, 0x6b, 0x61, 0x72, 0x69, 0x3b, 0x6e, 0x74, 0x25b, 0x6e, 0x25b, 0x3b, 0x74, 0x61, 0x72, 0x61, 0x74, 0x61, 0x3b, 0x61,
+0x72, 0x61, 0x62, 0x61, 0x3b, 0x61, 0x6c, 0x61, 0x6d, 0x69, 0x73, 0x61, 0x3b, 0x6a, 0x75, 0x6d, 0x61, 0x3b, 0x73, 0x69,
+0x62, 0x69, 0x72, 0x69, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x4a, 0x3b, 0x53, 0x3b, 0x4b,
+0x6d, 0x61, 0x3b, 0x54, 0x61, 0x74, 0x3b, 0x49, 0x6e, 0x65, 0x3b, 0x54, 0x61, 0x6e, 0x3b, 0x41, 0x72, 0x6d, 0x3b, 0x4d,
+0x61, 0x61, 0x3b, 0x4e, 0x4d, 0x4d, 0x3b, 0x4b, 0x69, 0x75, 0x6d, 0x69, 0x61, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x74,
+0x61, 0x74, 0x75, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x69, 0x6e, 0x65, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x74, 0x61,
+0x6e, 0x6f, 0x3b, 0x41, 0x72, 0x61, 0x6d, 0x69, 0x74, 0x68, 0x69, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4e,
+0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x74, 0x68, 0x69, 0x69, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x41,
+0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x13c6, 0x13cd, 0x13ac, 0x3b, 0x13c9, 0x13c5, 0x13af, 0x3b, 0x13d4, 0x13b5, 0x13c1, 0x3b, 0x13e6, 0x13a2, 0x13c1,
+0x3b, 0x13c5, 0x13a9, 0x13c1, 0x3b, 0x13e7, 0x13be, 0x13a9, 0x3b, 0x13c8, 0x13d5, 0x13be, 0x3b, 0x13a4, 0x13be, 0x13d9, 0x13d3, 0x13c6, 0x13cd, 0x13ac,
+0x3b, 0x13a4, 0x13be, 0x13d9, 0x13d3, 0x13c9, 0x13c5, 0x13af, 0x3b, 0x13d4, 0x13b5, 0x13c1, 0x13a2, 0x13a6, 0x3b, 0x13e6, 0x13a2, 0x13c1, 0x13a2, 0x13a6,
+0x3b, 0x13c5, 0x13a9, 0x13c1, 0x13a2, 0x13a6, 0x3b, 0x13e7, 0x13be, 0x13a9, 0x13b6, 0x13cd, 0x13d7, 0x3b, 0x13a4, 0x13be, 0x13d9, 0x13d3, 0x13c8, 0x13d5,
+0x13be, 0x3b, 0x13c6, 0x3b, 0x13c9, 0x3b, 0x13d4, 0x3b, 0x13e6, 0x3b, 0x13c5, 0x3b, 0x13e7, 0x3b, 0x13a4, 0x3b, 0x64, 0x69, 0x6d, 0x3b,
+0x6c, 0x69, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d, 0x65, 0x72, 0x3b, 0x7a, 0x65, 0x3b, 0x76, 0x61, 0x6e, 0x3b, 0x73,
+0x61, 0x6d, 0x3b, 0x64, 0x69, 0x6d, 0x61, 0x6e, 0x73, 0x3b, 0x6c, 0x69, 0x6e, 0x64, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x64,
+0x69, 0x3b, 0x6d, 0x65, 0x72, 0x6b, 0x72, 0x65, 0x64, 0x69, 0x3b, 0x7a, 0x65, 0x64, 0x69, 0x3b, 0x76, 0x61, 0x6e, 0x64,
+0x72, 0x65, 0x64, 0x69, 0x3b, 0x73, 0x61, 0x6d, 0x64, 0x69, 0x3b, 0x64, 0x3b, 0x6c, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x7a,
+0x3b, 0x76, 0x3b, 0x73, 0x3b, 0x4c, 0x6c, 0x32, 0x3b, 0x4c, 0x6c, 0x33, 0x3b, 0x4c, 0x6c, 0x34, 0x3b, 0x4c, 0x6c, 0x35,
+0x3b, 0x4c, 0x6c, 0x36, 0x3b, 0x4c, 0x6c, 0x37, 0x3b, 0x4c, 0x6c, 0x31, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20,
+0x6c, 0x79, 0x61, 0x70, 0x69, 0x6c, 0x69, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x74, 0x61,
+0x74, 0x75, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x63, 0x68, 0x69,
+0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x6e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x3b, 0x4c, 0x69,
+0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x6e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x6c, 0x69,
+0x6e, 0x6a, 0x69, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x6e, 0x6e, 0x79, 0x61, 0x6e, 0x6f,
+0x20, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x76, 0x69, 0x6c, 0x69, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x69,
+0x74, 0x61, 0x6e, 0x64, 0x69, 0x3b, 0x50, 0xed, 0x69, 0x6c, 0x69, 0x3b, 0x54, 0xe1, 0x61, 0x74, 0x75, 0x3b, 0xcd, 0x6e,
+0x65, 0x3b, 0x54, 0xe1, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x6d, 0x3b, 0x4d, 0xf3, 0x6f, 0x73,
+0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0xed, 0x69, 0x72, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0xe1, 0x74, 0x75,
+0x3b, 0x4a, 0x75, 0x6d, 0x61, 0xed, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0xe1, 0x61, 0x6e, 0x6f, 0x3b, 0x41,
+0x6c, 0x61, 0x6d, 0xed, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0xe1, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d,
+0xf3, 0x6f, 0x73, 0x69, 0x3b, 0x50, 0x3b, 0x54, 0x3b, 0x45, 0x3b, 0x4f, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x4d, 0x3b, 0x53,
+0x61, 0x62, 0x3b, 0x42, 0x61, 0x6c, 0x3b, 0x4c, 0x77, 0x32, 0x3b, 0x4c, 0x77, 0x33, 0x3b, 0x4c, 0x77, 0x34, 0x3b, 0x4c,
+0x77, 0x35, 0x3b, 0x4c, 0x77, 0x36, 0x3b, 0x53, 0x61, 0x62, 0x62, 0x69, 0x69, 0x74, 0x69, 0x3b, 0x42, 0x61, 0x6c, 0x61,
+0x7a, 0x61, 0x3b, 0x4c, 0x77, 0x61, 0x6b, 0x75, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4c, 0x77, 0x61, 0x6b, 0x75, 0x73, 0x61,
+0x74, 0x75, 0x3b, 0x4c, 0x77, 0x61, 0x6b, 0x75, 0x6e, 0x61, 0x3b, 0x4c, 0x77, 0x61, 0x6b, 0x75, 0x74, 0x61, 0x61, 0x6e,
+0x6f, 0x3b, 0x4c, 0x77, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x61, 0x67, 0x61, 0x3b, 0x53, 0x3b, 0x42, 0x3b, 0x4c, 0x3b, 0x4c,
+0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x50, 0x61, 0x20, 0x4d, 0x75, 0x6c, 0x75, 0x6e, 0x67, 0x75, 0x3b, 0x50, 0x61,
+0x6c, 0x69, 0x63, 0x68, 0x69, 0x6d, 0x6f, 0x3b, 0x50, 0x61, 0x6c, 0x69, 0x63, 0x68, 0x69, 0x62, 0x75, 0x6c, 0x69, 0x3b,
+0x50, 0x61, 0x6c, 0x69, 0x63, 0x68, 0x69, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x50, 0x61, 0x6c, 0x69, 0x63, 0x68, 0x69, 0x6e,
+0x65, 0x3b, 0x50, 0x61, 0x6c, 0x69, 0x63, 0x68, 0x69, 0x73, 0x61, 0x6e, 0x6f, 0x3b, 0x50, 0x61, 0x63, 0x68, 0x69, 0x62,
+0x65, 0x6c, 0x75, 0x73, 0x68, 0x69, 0x3b, 0x64, 0x75, 0x6d, 0x3b, 0x73, 0x69, 0x67, 0x3b, 0x74, 0x65, 0x72, 0x3b, 0x6b,
+0x75, 0x61, 0x3b, 0x6b, 0x69, 0x6e, 0x3b, 0x73, 0x65, 0x73, 0x3b, 0x73, 0x61, 0x62, 0x3b, 0x64, 0x75, 0x6d, 0x69, 0x6e,
+0x67, 0x75, 0x3b, 0x73, 0x69, 0x67, 0x75, 0x6e, 0x64, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x74, 0x65, 0x72, 0x73,
+0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x6b, 0x75, 0x61, 0x72, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x6b,
+0x69, 0x6e, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x73, 0x65, 0x73, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61,
+0x3b, 0x73, 0xe1, 0x62, 0x61, 0x64, 0x75, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x53, 0x3b,
+0x53, 0x3b, 0x64, 0x75, 0x6d, 0x69, 0x6e, 0x67, 0x75, 0x3b, 0x73, 0x69, 0x67, 0x75, 0x6e, 0x64, 0x61, 0x2d, 0x66, 0x65,
+0x72, 0x61, 0x3b, 0x74, 0x65, 0x72, 0x73, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x6b, 0x75, 0x61, 0x72, 0x74, 0x61,
+0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x6b, 0x69, 0x6e, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x73, 0x65, 0x73,
+0x74, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x73, 0x61, 0x62, 0x61, 0x64, 0x75, 0x3b, 0x4b, 0x49, 0x55, 0x3b, 0x4d,
+0x52, 0x41, 0x3b, 0x57, 0x41, 0x49, 0x3b, 0x57, 0x45, 0x54, 0x3b, 0x57, 0x45, 0x4e, 0x3b, 0x57, 0x54, 0x4e, 0x3b, 0x4a,
+0x55, 0x4d, 0x3b, 0x4b, 0x69, 0x75, 0x6d, 0x69, 0x61, 0x3b, 0x4d, 0x75, 0x72, 0x61, 0x6d, 0x75, 0x6b, 0x6f, 0x3b, 0x57,
+0x61, 0x69, 0x72, 0x69, 0x3b, 0x57, 0x65, 0x74, 0x68, 0x61, 0x74, 0x75, 0x3b, 0x57, 0x65, 0x6e, 0x61, 0x3b, 0x57, 0x65,
+0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b, 0x57, 0x3b,
+0x57, 0x3b, 0x57, 0x3b, 0x57, 0x3b, 0x4a, 0x3b, 0x4b, 0x74, 0x73, 0x3b, 0x4b, 0x6f, 0x74, 0x3b, 0x4b, 0x6f, 0x6f, 0x3b,
+0x4b, 0x6f, 0x73, 0x3b, 0x4b, 0x6f, 0x61, 0x3b, 0x4b, 0x6f, 0x6d, 0x3b, 0x4b, 0x6f, 0x6c, 0x3b, 0x4b, 0x6f, 0x74, 0x69,
+0x73, 0x61, 0x70, 0x3b, 0x4b, 0x6f, 0x74, 0x61, 0x61, 0x69, 0x3b, 0x4b, 0x6f, 0x61, 0x65, 0x6e, 0x67, 0x2019, 0x3b, 0x4b,
+0x6f, 0x73, 0x6f, 0x6d, 0x6f, 0x6b, 0x3b, 0x4b, 0x6f, 0x61, 0x6e, 0x67, 0x2019, 0x77, 0x61, 0x6e, 0x3b, 0x4b, 0x6f, 0x6d,
+0x75, 0x75, 0x74, 0x3b, 0x4b, 0x6f, 0x6c, 0x6f, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4f, 0x3b, 0x53, 0x3b, 0x41, 0x3b, 0x4d,
+0x3b, 0x4c, 0x3b, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0x61, 0x3b, 0x44, 0x65, 0x3b, 0x57, 0x75, 0x3b, 0x44, 0x6f, 0x3b, 0x46,
+0x72, 0x3b, 0x53, 0x61, 0x74, 0x3b, 0x53, 0x6f, 0x6e, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x4d, 0x61,
+0x6e, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x44, 0x65, 0x6e, 0x73, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65,
+0x65, 0x73, 0x3b, 0x57, 0x75, 0x6e, 0x73, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x44, 0x6f, 0x6e, 0x64,
+0x65, 0x72, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x46, 0x72, 0x61, 0x69, 0x74, 0x61, 0x78, 0x74, 0x73,
+0x65, 0x65, 0x73, 0x3b, 0x53, 0x61, 0x74, 0x65, 0x72, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x53, 0x3b,
+0x4d, 0x3b, 0x45, 0x3b, 0x57, 0x3b, 0x44, 0x3b, 0x46, 0x3b, 0x41, 0x3b, 0x53, 0x75, 0x2e, 0x3b, 0x4d, 0x6f, 0x2e, 0x3b,
+0x44, 0x69, 0x2e, 0x3b, 0x4d, 0x65, 0x2e, 0x3b, 0x44, 0x75, 0x2e, 0x3b, 0x46, 0x72, 0x2e, 0x3b, 0x53, 0x61, 0x2e, 0x3b,
+0x53, 0x75, 0x6e, 0x6e, 0x64, 0x61, 0x61, 0x63, 0x68, 0x3b, 0x4d, 0x6f, 0x68, 0x6e, 0x64, 0x61, 0x61, 0x63, 0x68, 0x3b,
+0x44, 0x69, 0x6e, 0x6e, 0x73, 0x64, 0x61, 0x61, 0x63, 0x68, 0x3b, 0x4d, 0x65, 0x74, 0x77, 0x6f, 0x63, 0x68, 0x3b, 0x44,
+0x75, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x64, 0x61, 0x61, 0x63, 0x68, 0x3b, 0x46, 0x72, 0x69, 0x69, 0x64, 0x61, 0x61, 0x63,
+0x68, 0x3b, 0x53, 0x61, 0x6d, 0x73, 0x64, 0x61, 0x61, 0x63, 0x68, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0xed, 0x6c, 0xed,
+0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0xe1, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d,
+0x61, 0x74, 0xe1, 0x6e, 0x254, 0x3b, 0x41, 0x6c, 0x61, 0xe1, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0xe1, 0x61,
+0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0xf3, 0x73, 0x69, 0x3b, 0x53, 0x61, 0x62, 0x69, 0x3b, 0x42, 0x61, 0x6c, 0x61, 0x3b,
+0x4b, 0x75, 0x62, 0x69, 0x3b, 0x4b, 0x75, 0x73, 0x61, 0x3b, 0x4b, 0x75, 0x6e, 0x61, 0x3b, 0x4b, 0x75, 0x74, 0x61, 0x3b,
+0x4d, 0x75, 0x6b, 0x61, 0x3b, 0x53, 0x61, 0x62, 0x69, 0x69, 0x74, 0x69, 0x3b, 0x42, 0x61, 0x6c, 0x61, 0x7a, 0x61, 0x3b,
+0x4f, 0x77, 0x6f, 0x6b, 0x75, 0x62, 0x69, 0x6c, 0x69, 0x3b, 0x4f, 0x77, 0x6f, 0x6b, 0x75, 0x73, 0x61, 0x74, 0x75, 0x3b,
+0x4f, 0x6c, 0x6f, 0x6b, 0x75, 0x6e, 0x61, 0x3b, 0x4f, 0x6c, 0x6f, 0x6b, 0x75, 0x74, 0x61, 0x61, 0x6e, 0x75, 0x3b, 0x4f,
+0x6c, 0x6f, 0x6d, 0x75, 0x6b, 0x61, 0x61, 0x67, 0x61, 0x3b, 0x53, 0x3b, 0x42, 0x3b, 0x42, 0x3b, 0x53, 0x3b, 0x4b, 0x3b,
+0x4b, 0x3b, 0x4d, 0x3b, 0x4a, 0x32, 0x3b, 0x4a, 0x33, 0x3b, 0x4a, 0x34, 0x3b, 0x4a, 0x35, 0x3b, 0x41, 0x6c, 0x3b, 0x49,
+0x6a, 0x3b, 0x4a, 0x31, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0x69, 0x72, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61,
+0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b,
+0x4d, 0x75, 0x72, 0x77, 0x61, 0x20, 0x77, 0x61, 0x20, 0x4b, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4d, 0x75, 0x72, 0x77, 0x61,
+0x20, 0x77, 0x61, 0x20, 0x4b, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x3b,
+0x4a, 0x70, 0x69, 0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6e, 0x6e, 0x3b, 0x4a, 0x74, 0x6e, 0x3b, 0x41, 0x6c, 0x68, 0x3b,
+0x49, 0x6a, 0x6d, 0x3b, 0x4a, 0x6d, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x42, 0x61, 0x72, 0x3b, 0x41, 0x61, 0x72, 0x3b,
+0x55, 0x6e, 0x69, 0x3b, 0x55, 0x6e, 0x67, 0x3b, 0x4b, 0x61, 0x6e, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x4e, 0x61, 0x6b, 0x61,
+0x65, 0x6a, 0x75, 0x6d, 0x61, 0x3b, 0x4e, 0x61, 0x6b, 0x61, 0x65, 0x62, 0x61, 0x72, 0x61, 0x73, 0x61, 0x3b, 0x4e, 0x61,
+0x6b, 0x61, 0x61, 0x72, 0x65, 0x3b, 0x4e, 0x61, 0x6b, 0x61, 0x75, 0x6e, 0x69, 0x3b, 0x4e, 0x61, 0x6b, 0x61, 0x75, 0x6e,
+0x67, 0x2019, 0x6f, 0x6e, 0x3b, 0x4e, 0x61, 0x6b, 0x61, 0x6b, 0x61, 0x6e, 0x79, 0x3b, 0x4e, 0x61, 0x6b, 0x61, 0x73, 0x61,
+0x62, 0x69, 0x74, 0x69, 0x3b, 0x4a, 0x3b, 0x42, 0x3b, 0x41, 0x3b, 0x55, 0x3b, 0x55, 0x3b, 0x4b, 0x3b, 0x53, 0x3b, 0x41,
0x6c, 0x68, 0x3b, 0x41, 0x74, 0x69, 0x3b, 0x41, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x3b, 0x41, 0x6c, 0x6d, 0x3b, 0x41,
-0x6c, 0x7a, 0x3b, 0x41, 0x73, 0x69, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x64, 0x69, 0x3b, 0x41, 0x74, 0x69, 0x6e, 0x6e, 0x69,
-0x3b, 0x41, 0x74, 0x61, 0x6c, 0x61, 0x61, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x72, 0x62, 0x61, 0x3b, 0x41, 0x6c, 0x68,
-0x61, 0x6d, 0x69, 0x69, 0x73, 0x61, 0x3b, 0x41, 0x6c, 0x7a, 0x75, 0x6d, 0x61, 0x3b, 0x41, 0x73, 0x69, 0x62, 0x74, 0x69,
-0x3b, 0x4a, 0x70, 0x69, 0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6d, 0x6e, 0x3b, 0x4a, 0x74, 0x6e, 0x3b, 0x41, 0x6c, 0x68,
-0x3b, 0x49, 0x6a, 0x75, 0x3b, 0x4a, 0x6d, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x70, 0x69, 0x69, 0x3b, 0x4a, 0x75,
-0x6d, 0x61, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61,
-0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61,
-0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x32, 0x3b, 0x33, 0x3b, 0x34, 0x3b, 0x35, 0x3b,
-0x41, 0x3b, 0x49, 0x3b, 0x31, 0x3b, 0x930, 0x92c, 0x93f, 0x3b, 0x938, 0x92e, 0x3b, 0x92e, 0x902, 0x917, 0x932, 0x3b, 0x92c, 0x941,
-0x926, 0x3b, 0x92c, 0x93f, 0x938, 0x925, 0x93f, 0x3b, 0x938, 0x941, 0x916, 0x941, 0x930, 0x3b, 0x938, 0x941, 0x928, 0x93f, 0x3b, 0x930,
-0x92c, 0x93f, 0x92c, 0x93e, 0x930, 0x3b, 0x938, 0x92e, 0x92c, 0x93e, 0x930, 0x3b, 0x92e, 0x902, 0x917, 0x932, 0x92c, 0x93e, 0x930, 0x3b,
-0x92c, 0x941, 0x926, 0x92c, 0x93e, 0x930, 0x3b, 0x92c, 0x93f, 0x938, 0x925, 0x93f, 0x92c, 0x93e, 0x930, 0x3b, 0x938, 0x941, 0x916, 0x941,
-0x930, 0x92c, 0x93e, 0x930, 0x3b, 0x938, 0x941, 0x928, 0x93f, 0x92c, 0x93e, 0x930, 0x3b, 0x930, 0x3b, 0x938, 0x3b, 0x92e, 0x902, 0x3b,
-0x92c, 0x941, 0x3b, 0x92c, 0x93f, 0x3b, 0x938, 0x941, 0x3b, 0x938, 0x941, 0x3b, 0x43a, 0x4c0, 0x438, 0x440, 0x430, 0x43d, 0x430, 0x43d,
-0x20, 0x434, 0x435, 0x3b, 0x43e, 0x440, 0x448, 0x43e, 0x442, 0x430, 0x43d, 0x20, 0x434, 0x435, 0x3b, 0x448, 0x438, 0x43d, 0x430, 0x440,
-0x438, 0x43d, 0x20, 0x434, 0x435, 0x3b, 0x43a, 0x445, 0x430, 0x430, 0x440, 0x438, 0x43d, 0x20, 0x434, 0x435, 0x3b, 0x435, 0x430, 0x440,
-0x438, 0x43d, 0x20, 0x434, 0x435, 0x3b, 0x43f, 0x4c0, 0x435, 0x440, 0x430, 0x441, 0x43a, 0x430, 0x43d, 0x20, 0x434, 0x435, 0x3b, 0x448,
-0x43e, 0x442, 0x20, 0x434, 0x435, 0x3b, 0x43d, 0x434, 0x2de7, 0x487, 0x467, 0x3b, 0x43f, 0x43d, 0x2de3, 0x435, 0x3b, 0x432, 0x442, 0x43e,
-0x2dec, 0x487, 0x3b, 0x441, 0x440, 0x2de3, 0x435, 0x3b, 0x447, 0x435, 0x2de6, 0x487, 0x3b, 0x43f, 0x467, 0x2de6, 0x487, 0x3b, 0x441, 0xa64b,
-0x2de0, 0x487, 0x3b, 0x43d, 0x435, 0x434, 0x463, 0x301, 0x43b, 0x467, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x463, 0x301, 0x43b, 0x44c,
-0x43d, 0x438, 0x43a, 0x44a, 0x3b, 0x432, 0x442, 0x43e, 0x301, 0x440, 0x43d, 0x438, 0x43a, 0x44a, 0x3b, 0x441, 0x440, 0x435, 0x434, 0x430,
-0x300, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x435, 0x440, 0x442, 0x43e, 0x301, 0x43a, 0x44a, 0x3b, 0x43f, 0x467, 0x442, 0x43e, 0x301, 0x43a,
-0x44a, 0x3b, 0x441, 0xa64b, 0x431, 0x431, 0x461, 0x301, 0x442, 0x430, 0x3b, 0x4c, 0x75, 0x6d, 0x3b, 0x4e, 0x6b, 0x6f, 0x3b, 0x4e,
-0x64, 0x79, 0x3b, 0x4e, 0x64, 0x67, 0x3b, 0x4e, 0x6a, 0x77, 0x3b, 0x4e, 0x67, 0x76, 0x3b, 0x4c, 0x75, 0x62, 0x3b, 0x4c,
-0x75, 0x6d, 0x69, 0x6e, 0x67, 0x75, 0x3b, 0x4e, 0x6b, 0x6f, 0x64, 0x79, 0x61, 0x3b, 0x4e, 0x64, 0xe0, 0x61, 0x79, 0xe0,
-0x3b, 0x4e, 0x64, 0x61, 0x6e, 0x67, 0xf9, 0x3b, 0x4e, 0x6a, 0xf2, 0x77, 0x61, 0x3b, 0x4e, 0x67, 0xf2, 0x76, 0x79, 0x61,
-0x3b, 0x4c, 0x75, 0x62, 0x69, 0x6e, 0x67, 0x75, 0x3b, 0x4c, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e,
-0x3b, 0x4c, 0x3b, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0xe9, 0x69, 0x3b, 0x44, 0xeb, 0x6e, 0x3b, 0x4d, 0xeb, 0x74, 0x3b, 0x44,
-0x6f, 0x6e, 0x3b, 0x46, 0x72, 0x65, 0x3b, 0x53, 0x61, 0x6d, 0x3b, 0x53, 0x6f, 0x6e, 0x6e, 0x64, 0x65, 0x67, 0x3b, 0x4d,
-0xe9, 0x69, 0x6e, 0x64, 0x65, 0x67, 0x3b, 0x44, 0xeb, 0x6e, 0x73, 0x63, 0x68, 0x64, 0x65, 0x67, 0x3b, 0x4d, 0xeb, 0x74,
-0x74, 0x77, 0x6f, 0x63, 0x68, 0x3b, 0x44, 0x6f, 0x6e, 0x6e, 0x65, 0x73, 0x63, 0x68, 0x64, 0x65, 0x67, 0x3b, 0x46, 0x72,
-0x65, 0x69, 0x64, 0x65, 0x67, 0x3b, 0x53, 0x61, 0x6d, 0x73, 0x63, 0x68, 0x64, 0x65, 0x67, 0x3b, 0x53, 0x6f, 0x6e, 0x2e,
-0x3b, 0x4d, 0xe9, 0x69, 0x2e, 0x3b, 0x44, 0xeb, 0x6e, 0x2e, 0x3b, 0x4d, 0xeb, 0x74, 0x2e, 0x3b, 0x44, 0x6f, 0x6e, 0x2e,
-0x3b, 0x46, 0x72, 0x65, 0x2e, 0x3b, 0x53, 0x61, 0x6d, 0x2e, 0x3b, 0x6e, 0x74, 0x73, 0x3b, 0x6b, 0x70, 0x61, 0x3b, 0x67,
-0x68, 0x254, 0x3b, 0x74, 0x254, 0x6d, 0x3b, 0x75, 0x6d, 0x65, 0x3b, 0x67, 0x68, 0x268, 0x3b, 0x64, 0x7a, 0x6b, 0x3b, 0x74,
-0x73, 0x75, 0x294, 0x6e, 0x74, 0x73, 0x268, 0x3b, 0x74, 0x73, 0x75, 0x294, 0x75, 0x6b, 0x70, 0xe0, 0x3b, 0x74, 0x73, 0x75,
-0x294, 0x75, 0x67, 0x68, 0x254, 0x65, 0x3b, 0x74, 0x73, 0x75, 0x294, 0x75, 0x74, 0x254, 0x300, 0x6d, 0x6c, 0xf2, 0x3b, 0x74,
-0x73, 0x75, 0x294, 0x75, 0x6d, 0xe8, 0x3b, 0x74, 0x73, 0x75, 0x294, 0x75, 0x67, 0x68, 0x268, 0x302, 0x6d, 0x3b, 0x74, 0x73,
-0x75, 0x294, 0x6e, 0x64, 0x7a, 0x268, 0x6b, 0x254, 0x294, 0x254, 0x3b, 0x6e, 0x3b, 0x6b, 0x3b, 0x67, 0x3b, 0x74, 0x3b, 0x75,
-0x3b, 0x67, 0x3b, 0x64, 0x3b, 0x6e, 0x254, 0x79, 0x3b, 0x6e, 0x6a, 0x61, 0x3b, 0x75, 0x75, 0x6d, 0x3b, 0x14b, 0x67, 0x65,
-0x3b, 0x6d, 0x62, 0x254, 0x3b, 0x6b, 0x254, 0x254, 0x3b, 0x6a, 0x6f, 0x6e, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6e, 0x254,
-0x302, 0x79, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6e, 0x6a, 0x61, 0x14b, 0x67, 0x75, 0x6d, 0x62, 0x61, 0x3b, 0x14b, 0x67,
-0x77, 0xe0, 0x20, 0xfb, 0x6d, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x14b, 0x67, 0xea, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20,
-0x6d, 0x62, 0x254, 0x6b, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6b, 0x254, 0x254, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6a,
-0xf4, 0x6e, 0x3b, 0x6e, 0x3b, 0x6e, 0x3b, 0x75, 0x3b, 0x14b, 0x3b, 0x6d, 0x3b, 0x6b, 0x3b, 0x6a, 0x3b, 0x41, 0x6c, 0x68,
-0x61, 0x64, 0x69, 0x3b, 0x41, 0x74, 0x69, 0x6e, 0x6e, 0x69, 0x3b, 0x41, 0x74, 0x61, 0x6c, 0x61, 0x61, 0x74, 0x61, 0x3b,
-0x41, 0x6c, 0x61, 0x72, 0x62, 0x61, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x41, 0x6c, 0x7a, 0x75,
-0x6d, 0x61, 0x3b, 0x41, 0x73, 0x69, 0x62, 0x74, 0x69, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b,
-0x5a, 0x3b, 0x53, 0x3b, 0xe9, 0x74, 0x3b, 0x6d, 0x254, 0x301, 0x73, 0x3b, 0x6b, 0x77, 0x61, 0x3b, 0x6d, 0x75, 0x6b, 0x3b,
-0x14b, 0x67, 0x69, 0x3b, 0x257, 0xf3, 0x6e, 0x3b, 0x65, 0x73, 0x61, 0x3b, 0xe9, 0x74, 0x69, 0x3b, 0x6d, 0x254, 0x301, 0x73,
-0xfa, 0x3b, 0x6b, 0x77, 0x61, 0x73, 0xfa, 0x3b, 0x6d, 0x75, 0x6b, 0x254, 0x301, 0x73, 0xfa, 0x3b, 0x14b, 0x67, 0x69, 0x73,
-0xfa, 0x3b, 0x257, 0xf3, 0x6e, 0x25b, 0x73, 0xfa, 0x3b, 0x65, 0x73, 0x61, 0x253, 0x61, 0x73, 0xfa, 0x3b, 0x65, 0x3b, 0x6d,
-0x3b, 0x6b, 0x3b, 0x6d, 0x3b, 0x14b, 0x3b, 0x257, 0x3b, 0x65, 0x3b, 0x44, 0x69, 0x6d, 0x3b, 0x54, 0x65, 0x6e, 0x3b, 0x54,
-0x61, 0x6c, 0x3b, 0x41, 0x6c, 0x61, 0x3b, 0x41, 0x72, 0x61, 0x3b, 0x41, 0x72, 0x6a, 0x3b, 0x53, 0x69, 0x62, 0x3b, 0x44,
-0x69, 0x6d, 0x61, 0x73, 0x3b, 0x54, 0x65, 0x6e, 0x65, 0x14b, 0x3b, 0x54, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b, 0x41, 0x6c,
-0x61, 0x72, 0x62, 0x61, 0x79, 0x3b, 0x41, 0x72, 0x61, 0x6d, 0x69, 0x73, 0x61, 0x79, 0x3b, 0x41, 0x72, 0x6a, 0x75, 0x6d,
-0x61, 0x3b, 0x53, 0x69, 0x62, 0x69, 0x74, 0x69, 0x3b, 0x44, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41,
-0x3b, 0x53, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x3b, 0x6d, 0x254, 0x301, 0x6e, 0x3b, 0x73, 0x6d, 0x62, 0x3b, 0x73, 0x6d, 0x6c,
-0x3b, 0x73, 0x6d, 0x6e, 0x3b, 0x66, 0xfa, 0x6c, 0x3b, 0x73, 0xe9, 0x72, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x3b,
-0x6d, 0x254, 0x301, 0x6e, 0x64, 0x69, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d, 0x259, 0x6c, 0xfa, 0x20, 0x6d,
-0x259, 0x301, 0x62, 0x25b, 0x30c, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d, 0x259, 0x6c, 0xfa, 0x20, 0x6d, 0x259,
-0x301, 0x6c, 0x25b, 0x301, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d, 0x259, 0x6c, 0xfa, 0x20, 0x6d, 0x259, 0x301,
-0x6e, 0x79, 0x69, 0x3b, 0x66, 0xfa, 0x6c, 0x61, 0x64, 0xe9, 0x3b, 0x73, 0xe9, 0x72, 0x61, 0x64, 0xe9, 0x3b, 0x73, 0x3b,
-0x6d, 0x3b, 0x73, 0x3b, 0x73, 0x3b, 0x73, 0x3b, 0x66, 0x3b, 0x73, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x3b, 0x6c, 0x1dd, 0x6e,
-0x3b, 0x6d, 0x61, 0x61, 0x3b, 0x6d, 0x25b, 0x6b, 0x3b, 0x6a, 0x1dd, 0x1dd, 0x3b, 0x6a, 0xfa, 0x6d, 0x3b, 0x73, 0x61, 0x6d,
-0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x1dd, 0x3b, 0x6c, 0x1dd, 0x6e, 0x64, 0xed, 0x3b, 0x6d, 0x61, 0x61, 0x64, 0xed, 0x3b,
-0x6d, 0x25b, 0x6b, 0x72, 0x25b, 0x64, 0xed, 0x3b, 0x6a, 0x1dd, 0x1dd, 0x64, 0xed, 0x3b, 0x6a, 0xfa, 0x6d, 0x62, 0xe1, 0x3b,
-0x73, 0x61, 0x6d, 0x64, 0xed, 0x3b, 0x73, 0x3b, 0x6c, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x6a, 0x3b, 0x73, 0x3b,
-0x53, 0x61, 0x62, 0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6e, 0x6e, 0x3b, 0x4a, 0x74, 0x6e, 0x3b, 0x41, 0x72, 0x61, 0x3b,
-0x49, 0x6a, 0x75, 0x3b, 0x4a, 0x6d, 0x6f, 0x3b, 0x53, 0x61, 0x62, 0x61, 0x74, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74,
-0x61, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f,
-0x3b, 0x41, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75,
-0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x53, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x4a,
-0x3b, 0x43, 0x79, 0x61, 0x3b, 0x43, 0x6c, 0x61, 0x3b, 0x43, 0x7a, 0x69, 0x3b, 0x43, 0x6b, 0x6f, 0x3b, 0x43, 0x6b, 0x61,
-0x3b, 0x43, 0x67, 0x61, 0x3b, 0x43, 0x7a, 0x65, 0x3b, 0x43, 0x6f, 0x6d, 0x2019, 0x79, 0x61, 0x6b, 0x6b, 0x65, 0x3b, 0x43,
-0x6f, 0x6d, 0x6c, 0x61, 0x61, 0x257, 0x69, 0x69, 0x3b, 0x43, 0x6f, 0x6d, 0x7a, 0x79, 0x69, 0x69, 0x257, 0x69, 0x69, 0x3b,
-0x43, 0x6f, 0x6d, 0x6b, 0x6f, 0x6c, 0x6c, 0x65, 0x3b, 0x43, 0x6f, 0x6d, 0x6b, 0x61, 0x6c, 0x64, 0x1dd, 0x253, 0x6c, 0x69,
-0x69, 0x3b, 0x43, 0x6f, 0x6d, 0x67, 0x61, 0x69, 0x73, 0x75, 0x75, 0x3b, 0x43, 0x6f, 0x6d, 0x7a, 0x79, 0x65, 0x253, 0x73,
-0x75, 0x75, 0x3b, 0x59, 0x3b, 0x4c, 0x3b, 0x5a, 0x3b, 0x4f, 0x3b, 0x41, 0x3b, 0x47, 0x3b, 0x45, 0x3b, 0x73, 0x254, 0x301,
-0x6e, 0x3b, 0x6d, 0x254, 0x301, 0x6e, 0x3b, 0x73, 0x6d, 0x62, 0x3b, 0x73, 0x6d, 0x6c, 0x3b, 0x73, 0x6d, 0x6e, 0x3b, 0x6d,
-0x62, 0x73, 0x3b, 0x73, 0x61, 0x73, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x3b, 0x6d, 0x254, 0x301, 0x6e, 0x64, 0x254,
-0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d, 0x61, 0x66, 0xfa, 0x20, 0x6d, 0xe1, 0x62, 0x61, 0x3b, 0x73, 0x254,
-0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d, 0x61, 0x66, 0xfa, 0x20, 0x6d, 0xe1, 0x6c, 0x61, 0x6c, 0x3b, 0x73, 0x254, 0x301, 0x6e,
-0x64, 0x254, 0x20, 0x6d, 0x61, 0x66, 0xfa, 0x20, 0x6d, 0xe1, 0x6e, 0x61, 0x3b, 0x6d, 0x61, 0x62, 0xe1, 0x67, 0xe1, 0x20,
-0x6d, 0xe1, 0x20, 0x73, 0x75, 0x6b, 0x75, 0x6c, 0x3b, 0x73, 0xe1, 0x73, 0x61, 0x64, 0x69, 0x3b, 0x73, 0x3b, 0x6d, 0x3b,
-0x73, 0x3b, 0x73, 0x3b, 0x73, 0x3b, 0x6d, 0x3b, 0x73, 0x3b, 0x43, 0xe4, 0x14b, 0x3b, 0x4a, 0x69, 0x65, 0x63, 0x3b, 0x52,
-0x25b, 0x77, 0x3b, 0x44, 0x69, 0x254, 0x331, 0x6b, 0x3b, 0x14a, 0x75, 0x61, 0x61, 0x6e, 0x3b, 0x44, 0x68, 0x69, 0x65, 0x65,
-0x63, 0x3b, 0x42, 0xe4, 0x6b, 0x25b, 0x6c, 0x3b, 0x43, 0xe4, 0x14b, 0x20, 0x6b, 0x75, 0x254, 0x74, 0x68, 0x3b, 0x4a, 0x69,
-0x65, 0x63, 0x20, 0x6c, 0x61, 0x331, 0x74, 0x3b, 0x52, 0x25b, 0x77, 0x20, 0x6c, 0xe4, 0x74, 0x6e, 0x69, 0x3b, 0x44, 0x69,
-0x254, 0x331, 0x6b, 0x20, 0x6c, 0xe4, 0x74, 0x6e, 0x69, 0x3b, 0x14a, 0x75, 0x61, 0x61, 0x6e, 0x20, 0x6c, 0xe4, 0x74, 0x6e,
-0x69, 0x3b, 0x44, 0x68, 0x69, 0x65, 0x65, 0x63, 0x20, 0x6c, 0xe4, 0x74, 0x6e, 0x69, 0x3b, 0x42, 0xe4, 0x6b, 0x25b, 0x6c,
-0x20, 0x6c, 0xe4, 0x74, 0x6e, 0x69, 0x3b, 0x43, 0x3b, 0x4a, 0x3b, 0x52, 0x3b, 0x44, 0x3b, 0x14a, 0x3b, 0x44, 0x3b, 0x42,
-0x3b, 0x431, 0x441, 0x3b, 0x431, 0x43d, 0x3b, 0x43e, 0x43f, 0x3b, 0x441, 0x44d, 0x3b, 0x447, 0x43f, 0x3b, 0x431, 0x44d, 0x3b, 0x441,
-0x431, 0x3b, 0x431, 0x430, 0x441, 0x43a, 0x44b, 0x4bb, 0x44b, 0x430, 0x43d, 0x43d, 0x44c, 0x430, 0x3b, 0x431, 0x44d, 0x43d, 0x438, 0x434,
-0x438, 0x44d, 0x43d, 0x43d, 0x44c, 0x438, 0x43a, 0x3b, 0x43e, 0x43f, 0x442, 0x443, 0x43e, 0x440, 0x443, 0x43d, 0x43d, 0x44c, 0x443, 0x43a,
-0x3b, 0x441, 0x44d, 0x440, 0x44d, 0x434, 0x44d, 0x3b, 0x447, 0x44d, 0x43f, 0x43f, 0x438, 0x44d, 0x440, 0x3b, 0x411, 0x44d, 0x44d, 0x442,
-0x438, 0x4a5, 0x441, 0x44d, 0x3b, 0x441, 0x443, 0x431, 0x443, 0x43e, 0x442, 0x430, 0x3b, 0x411, 0x3b, 0x411, 0x3b, 0x41e, 0x3b, 0x421,
-0x3b, 0x427, 0x3b, 0x411, 0x3b, 0x421, 0x3b, 0x4d, 0x75, 0x6c, 0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6e, 0x6e, 0x3b, 0x4a,
-0x74, 0x6e, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x75, 0x3b, 0x4a, 0x6d, 0x6f, 0x3b, 0x4d, 0x75, 0x6c, 0x75, 0x6e,
-0x67, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b,
-0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x6c, 0x61, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49,
-0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a,
-0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x4a, 0x3b, 0xa55e, 0xa54c, 0xa535, 0x3b, 0xa5f3, 0xa5e1, 0xa609, 0x3b, 0xa55a, 0xa55e, 0xa55a,
-0x3b, 0xa549, 0xa55e, 0xa552, 0x3b, 0xa549, 0xa524, 0xa546, 0xa562, 0x3b, 0xa549, 0xa524, 0xa540, 0xa56e, 0x3b, 0xa53b, 0xa52c, 0xa533, 0x3b, 0x6c,
-0x61, 0x68, 0x61, 0x64, 0x69, 0x3b, 0x74, 0x25b, 0x25b, 0x6e, 0x25b, 0x25b, 0x3b, 0x74, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b,
-0x61, 0x6c, 0x61, 0x62, 0x61, 0x3b, 0x61, 0x69, 0x6d, 0x69, 0x73, 0x61, 0x3b, 0x61, 0x69, 0x6a, 0x69, 0x6d, 0x61, 0x3b,
-0x73, 0x69, 0x253, 0x69, 0x74, 0x69, 0x3b, 0x53, 0x75, 0x6e, 0x3b, 0x4d, 0xe4, 0x6e, 0x3b, 0x5a, 0x69, 0x161, 0x3b, 0x4d,
-0x69, 0x74, 0x3b, 0x46, 0x72, 0xf3, 0x3b, 0x46, 0x72, 0x69, 0x3b, 0x53, 0x61, 0x6d, 0x3b, 0x53, 0x75, 0x6e, 0x6e, 0x74,
-0x61, 0x67, 0x3b, 0x4d, 0xe4, 0x6e, 0x74, 0x61, 0x67, 0x3b, 0x5a, 0x69, 0x161, 0x74, 0x61, 0x67, 0x3b, 0x4d, 0x69, 0x74,
-0x74, 0x77, 0x75, 0x10d, 0x3b, 0x46, 0x72, 0xf3, 0x6e, 0x74, 0x61, 0x67, 0x3b, 0x46, 0x72, 0x69, 0x74, 0x61, 0x67, 0x3b,
-0x53, 0x61, 0x6d, 0x161, 0x74, 0x61, 0x67, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x5a, 0x3b, 0x4d, 0x3b, 0x46, 0x3b, 0x46, 0x3b,
-0x53, 0x3b, 0x73, 0x64, 0x3b, 0x6d, 0x64, 0x3b, 0x6d, 0x77, 0x3b, 0x65, 0x74, 0x3b, 0x6b, 0x6c, 0x3b, 0x66, 0x6c, 0x3b,
-0x73, 0x73, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x69, 0x25b, 0x3b, 0x6d, 0xf3, 0x6e, 0x64, 0x69, 0x65, 0x3b, 0x6d, 0x75,
-0xe1, 0x6e, 0x79, 0xe1, 0x14b, 0x6d, 0xf3, 0x6e, 0x64, 0x69, 0x65, 0x3b, 0x6d, 0x65, 0x74, 0xfa, 0x6b, 0x70, 0xed, 0xe1,
-0x70, 0x25b, 0x3b, 0x6b, 0xfa, 0x70, 0xe9, 0x6c, 0x69, 0x6d, 0x65, 0x74, 0xfa, 0x6b, 0x70, 0x69, 0x61, 0x70, 0x25b, 0x3b,
-0x66, 0x65, 0x6c, 0xe9, 0x74, 0x65, 0x3b, 0x73, 0xe9, 0x73, 0x65, 0x6c, 0xe9, 0x3b, 0x73, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b,
-0x65, 0x3b, 0x6b, 0x3b, 0x66, 0x3b, 0x73, 0x3b, 0x64, 0x6f, 0x6d, 0x3b, 0x6c, 0x6c, 0x75, 0x3b, 0x6d, 0x61, 0x72, 0x3b,
-0x6d, 0x69, 0xe9, 0x3b, 0x78, 0x75, 0x65, 0x3b, 0x76, 0x69, 0x65, 0x3b, 0x73, 0xe1, 0x62, 0x3b, 0x64, 0x6f, 0x6d, 0x69,
-0x6e, 0x67, 0x75, 0x3b, 0x6c, 0x6c, 0x75, 0x6e, 0x65, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x6d, 0x69,
-0xe9, 0x72, 0x63, 0x6f, 0x6c, 0x65, 0x73, 0x3b, 0x78, 0x75, 0x65, 0x76, 0x65, 0x73, 0x3b, 0x76, 0x69, 0x65, 0x6e, 0x72,
-0x65, 0x73, 0x3b, 0x73, 0xe1, 0x62, 0x61, 0x64, 0x75, 0x3b, 0x53, 0x254, 0x301, 0x6e, 0x64, 0x69, 0x3b, 0x4d, 0x254, 0x301,
-0x6e, 0x64, 0x69, 0x3b, 0xc1, 0x70, 0x74, 0x61, 0x20, 0x4d, 0x254, 0x301, 0x6e, 0x64, 0x69, 0x3b, 0x57, 0x25b, 0x301, 0x6e,
-0x25b, 0x73, 0x25b, 0x64, 0x25b, 0x3b, 0x54, 0x254, 0x301, 0x73, 0x25b, 0x64, 0x25b, 0x3b, 0x46, 0x25b, 0x6c, 0xe2, 0x79, 0x25b,
-0x64, 0x25b, 0x3b, 0x53, 0xe1, 0x73, 0x69, 0x64, 0x25b, 0x3b, 0x53, 0x254, 0x301, 0x3b, 0x4d, 0x254, 0x301, 0x3b, 0xc1, 0x4d,
-0x3b, 0x57, 0x25b, 0x301, 0x3b, 0x54, 0x254, 0x301, 0x3b, 0x46, 0x25b, 0x3b, 0x53, 0xe1, 0x3b, 0x73, 0x254, 0x6e, 0x64, 0x69,
-0x3b, 0x6c, 0x75, 0x6e, 0x64, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x64, 0x69, 0x3b, 0x6d, 0x25b, 0x72, 0x6b, 0x25b, 0x72, 0x25b,
-0x64, 0x69, 0x3b, 0x79, 0x65, 0x64, 0x69, 0x3b, 0x76, 0x61, 0x14b, 0x64, 0x25b, 0x72, 0x25b, 0x64, 0x69, 0x3b, 0x6d, 0x254,
-0x6e, 0x254, 0x20, 0x73, 0x254, 0x6e, 0x64, 0x69, 0x3b, 0x73, 0x6f, 0x3b, 0x6c, 0x75, 0x3b, 0x6d, 0x61, 0x3b, 0x6d, 0x25b,
-0x3b, 0x79, 0x65, 0x3b, 0x76, 0x61, 0x3b, 0x6d, 0x73, 0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x31, 0x3b, 0x41, 0x6e, 0x65,
-0x67, 0x20, 0x32, 0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x33, 0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x34, 0x3b, 0x41, 0x6e,
-0x65, 0x67, 0x20, 0x35, 0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x36, 0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x37, 0x3b, 0x41,
-0x31, 0x3b, 0x41, 0x32, 0x3b, 0x41, 0x33, 0x3b, 0x41, 0x34, 0x3b, 0x41, 0x35, 0x3b, 0x41, 0x36, 0x3b, 0x41, 0x37, 0x3b,
-0x6c, 0x79, 0x25b, 0x2bc, 0x25b, 0x301, 0x20, 0x73, 0x1e85, 0xed, 0x14b, 0x74, 0xe8, 0x3b, 0x6d, 0x76, 0x66, 0xf2, 0x20, 0x6c,
-0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x6d, 0x62, 0x254, 0x301, 0x254, 0x6e, 0x74, 0xe8, 0x20, 0x6d, 0x76, 0x66, 0xf2, 0x20, 0x6c,
-0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x74, 0x73, 0xe8, 0x74, 0x73, 0x25b, 0x300, 0x25b, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b,
-0x6d, 0x62, 0x254, 0x301, 0x254, 0x6e, 0x74, 0xe8, 0x20, 0x74, 0x73, 0x65, 0x74, 0x73, 0x25b, 0x300, 0x25b, 0x20, 0x6c, 0x79,
-0x25b, 0x30c, 0x2bc, 0x3b, 0x6d, 0x76, 0x66, 0xf2, 0x20, 0x6d, 0xe0, 0x67, 0x61, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b,
-0x6d, 0xe0, 0x67, 0x61, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x77, 0x61, 0x6b,
-0x21f, 0x61, 0x14b, 0x3b, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x77, 0x61, 0x14b, 0x17e, 0x69, 0x3b, 0x41, 0x14b, 0x70, 0xe9,
-0x74, 0x75, 0x6e, 0x75, 0x14b, 0x70, 0x61, 0x3b, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x79, 0x61, 0x6d, 0x6e, 0x69, 0x3b,
-0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x74, 0x6f, 0x70, 0x61, 0x3b, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x7a, 0x61, 0x70,
-0x74, 0x61, 0x14b, 0x3b, 0x4f, 0x77, 0xe1, 0x14b, 0x67, 0x79, 0x75, 0x17e, 0x61, 0x17e, 0x61, 0x70, 0x69, 0x3b, 0x41, 0x3b,
-0x57, 0x3b, 0x4e, 0x3b, 0x59, 0x3b, 0x54, 0x3b, 0x5a, 0x3b, 0x4f, 0x3b, 0x2d30, 0x2d59, 0x2d30, 0x2d4e, 0x2d30, 0x2d59, 0x3b, 0x2d30,
-0x2d62, 0x2d4f, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d4f, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d3d, 0x2d55, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d3d,
-0x2d61, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d4e, 0x2d61, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d39, 0x2d62, 0x2d30, 0x2d59, 0x3b,
-0x6cc, 0x6d5, 0x6a9, 0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x62f, 0x648, 0x648, 0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x633, 0x6ce,
-0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x686, 0x648, 0x627, 0x631, 0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x67e, 0x6ce, 0x646, 0x62c,
-0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x6be, 0x6d5, 0x6cc, 0x646, 0x6cc, 0x3b, 0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x6cc, 0x3b,
-0x62f, 0x3b, 0x633, 0x3b, 0x686, 0x3b, 0x67e, 0x3b, 0x6be, 0x3b, 0x634, 0x3b, 0x6e, 0x6a, 0x65, 0x3b, 0x70, 0xf3, 0x6e, 0x3b,
-0x77, 0x61, 0x142, 0x3b, 0x73, 0x72, 0x6a, 0x3b, 0x73, 0x74, 0x77, 0x3b, 0x70, 0x11b, 0x74, 0x3b, 0x73, 0x6f, 0x62, 0x3b,
-0x6e, 0x6a, 0x65, 0x17a, 0x65, 0x6c, 0x61, 0x3b, 0x70, 0xf3, 0x6e, 0x6a, 0x65, 0x17a, 0x65, 0x6c, 0x65, 0x3b, 0x77, 0x61,
-0x142, 0x74, 0x6f, 0x72, 0x61, 0x3b, 0x73, 0x72, 0x6a, 0x6f, 0x64, 0x61, 0x3b, 0x73, 0x74, 0x77, 0xf3, 0x72, 0x74, 0x6b,
-0x3b, 0x70, 0x11b, 0x74, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x6e, 0x3b, 0x70, 0x3b, 0x77, 0x3b, 0x73,
-0x3b, 0x73, 0x3b, 0x70, 0x3b, 0x73, 0x3b, 0x6e, 0x6a, 0x65, 0x3b, 0x70, 0xf3, 0x6e, 0x3b, 0x77, 0x75, 0x74, 0x3b, 0x73,
-0x72, 0x6a, 0x3b, 0x161, 0x74, 0x77, 0x3b, 0x70, 0x6a, 0x61, 0x3b, 0x73, 0x6f, 0x62, 0x3b, 0x6e, 0x6a, 0x65, 0x64, 0x17a,
-0x65, 0x6c, 0x61, 0x3b, 0x70, 0xf3, 0x6e, 0x64, 0x17a, 0x65, 0x6c, 0x61, 0x3b, 0x77, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x3b,
-0x73, 0x72, 0x6a, 0x65, 0x64, 0x61, 0x3b, 0x161, 0x74, 0x77, 0xf3, 0x72, 0x74, 0x6b, 0x3b, 0x70, 0x6a, 0x61, 0x74, 0x6b,
-0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x6e, 0x3b, 0x70, 0x3b, 0x77, 0x3b, 0x73, 0x3b, 0x161, 0x3b, 0x70, 0x3b,
-0x73, 0x3b, 0x70, 0x61, 0x73, 0x3b, 0x76, 0x75, 0x6f, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6b, 0x6f, 0x73, 0x3b, 0x74, 0x75,
+0x6c, 0x6a, 0x3b, 0x41, 0x73, 0x73, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x64, 0x69, 0x3b, 0x41, 0x74, 0x69, 0x6e, 0x69, 0x3b,
+0x41, 0x74, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x72, 0x62, 0x61, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d,
+0x69, 0x69, 0x73, 0x61, 0x3b, 0x41, 0x6c, 0x6a, 0x75, 0x6d, 0x61, 0x3b, 0x41, 0x73, 0x73, 0x61, 0x62, 0x64, 0x75, 0x3b,
+0x48, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x53, 0x3b, 0x4a, 0x4d, 0x50, 0x3b, 0x57, 0x55,
+0x54, 0x3b, 0x54, 0x41, 0x52, 0x3b, 0x54, 0x41, 0x44, 0x3b, 0x54, 0x41, 0x4e, 0x3b, 0x54, 0x41, 0x42, 0x3b, 0x4e, 0x47,
+0x53, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0x69, 0x6c, 0x3b, 0x57, 0x75, 0x6f, 0x6b, 0x20, 0x54, 0x69, 0x63, 0x68, 0x3b,
+0x54, 0x69, 0x63, 0x68, 0x20, 0x41, 0x72, 0x69, 0x79, 0x6f, 0x3b, 0x54, 0x69, 0x63, 0x68, 0x20, 0x41, 0x64, 0x65, 0x6b,
+0x3b, 0x54, 0x69, 0x63, 0x68, 0x20, 0x41, 0x6e, 0x67, 0x2019, 0x77, 0x65, 0x6e, 0x3b, 0x54, 0x69, 0x63, 0x68, 0x20, 0x41,
+0x62, 0x69, 0x63, 0x68, 0x3b, 0x4e, 0x67, 0x65, 0x73, 0x6f, 0x3b, 0x4a, 0x3b, 0x57, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x54,
+0x3b, 0x54, 0x3b, 0x4e, 0x3b, 0x41, 0x73, 0x61, 0x3b, 0x41, 0x79, 0x6e, 0x3b, 0x41, 0x73, 0x6e, 0x3b, 0x41, 0x6b, 0x72,
+0x3b, 0x41, 0x6b, 0x77, 0x3b, 0x41, 0x73, 0x6d, 0x3b, 0x41, 0x73, 0x1e0d, 0x3b, 0x41, 0x73, 0x61, 0x6d, 0x61, 0x73, 0x3b,
+0x41, 0x79, 0x6e, 0x61, 0x73, 0x3b, 0x41, 0x73, 0x69, 0x6e, 0x61, 0x73, 0x3b, 0x41, 0x6b, 0x72, 0x61, 0x73, 0x3b, 0x41,
+0x6b, 0x77, 0x61, 0x73, 0x3b, 0x41, 0x73, 0x69, 0x6d, 0x77, 0x61, 0x73, 0x3b, 0x41, 0x73, 0x69, 0x1e0d, 0x79, 0x61, 0x73,
+0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x41,
+0x74, 0x69, 0x3b, 0x41, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x3b, 0x41, 0x6c, 0x6d, 0x3b, 0x41, 0x6c, 0x7a, 0x3b, 0x41,
+0x73, 0x69, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x64, 0x69, 0x3b, 0x41, 0x74, 0x69, 0x6e, 0x6e, 0x69, 0x3b, 0x41, 0x74, 0x61,
+0x6c, 0x61, 0x61, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x72, 0x62, 0x61, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x69,
+0x73, 0x61, 0x3b, 0x41, 0x6c, 0x7a, 0x75, 0x6d, 0x61, 0x3b, 0x41, 0x73, 0x69, 0x62, 0x74, 0x69, 0x3b, 0x4a, 0x70, 0x69,
+0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6d, 0x6e, 0x3b, 0x4a, 0x74, 0x6e, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x75,
+0x3b, 0x4a, 0x6d, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x70, 0x69, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x74,
+0x61, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x74, 0x61, 0x6e,
+0x6f, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75,
+0x6d, 0x61, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x32, 0x3b, 0x33, 0x3b, 0x34, 0x3b, 0x35, 0x3b, 0x41, 0x3b, 0x49, 0x3b,
+0x31, 0x3b, 0x930, 0x92c, 0x93f, 0x3b, 0x938, 0x92e, 0x3b, 0x92e, 0x902, 0x917, 0x932, 0x3b, 0x92c, 0x941, 0x926, 0x3b, 0x92c, 0x93f,
+0x938, 0x925, 0x93f, 0x3b, 0x938, 0x941, 0x916, 0x941, 0x930, 0x3b, 0x938, 0x941, 0x928, 0x93f, 0x3b, 0x930, 0x92c, 0x93f, 0x92c, 0x93e,
+0x930, 0x3b, 0x938, 0x92e, 0x92c, 0x93e, 0x930, 0x3b, 0x92e, 0x902, 0x917, 0x932, 0x92c, 0x93e, 0x930, 0x3b, 0x92c, 0x941, 0x926, 0x92c,
+0x93e, 0x930, 0x3b, 0x92c, 0x93f, 0x938, 0x925, 0x93f, 0x92c, 0x93e, 0x930, 0x3b, 0x938, 0x941, 0x916, 0x941, 0x930, 0x92c, 0x93e, 0x930,
+0x3b, 0x938, 0x941, 0x928, 0x93f, 0x92c, 0x93e, 0x930, 0x3b, 0x930, 0x3b, 0x938, 0x3b, 0x92e, 0x902, 0x3b, 0x92c, 0x941, 0x3b, 0x92c,
+0x93f, 0x3b, 0x938, 0x941, 0x3b, 0x938, 0x941, 0x3b, 0x43a, 0x4c0, 0x438, 0x3b, 0x43e, 0x440, 0x3b, 0x448, 0x438, 0x3b, 0x43a, 0x445,
+0x430, 0x3b, 0x435, 0x430, 0x3b, 0x43f, 0x4c0, 0x435, 0x3b, 0x448, 0x443, 0x43e, 0x3b, 0x43a, 0x4c0, 0x438, 0x440, 0x430, 0x3b, 0x43e,
+0x440, 0x448, 0x43e, 0x442, 0x3b, 0x448, 0x438, 0x43d, 0x430, 0x440, 0x430, 0x3b, 0x43a, 0x445, 0x430, 0x430, 0x440, 0x430, 0x3b, 0x435,
+0x430, 0x440, 0x430, 0x3b, 0x43f, 0x4c0, 0x435, 0x440, 0x430, 0x441, 0x43a, 0x430, 0x3b, 0x448, 0x443, 0x43e, 0x442, 0x3b, 0x43a, 0x4c0,
+0x3b, 0x43e, 0x3b, 0x448, 0x3b, 0x43a, 0x445, 0x3b, 0x435, 0x3b, 0x43f, 0x4c0, 0x3b, 0x448, 0x3b, 0x43d, 0x434, 0x2de7, 0x487, 0x467,
+0x3b, 0x43f, 0x43d, 0x2de3, 0x435, 0x3b, 0x432, 0x442, 0x43e, 0x2dec, 0x487, 0x3b, 0x441, 0x440, 0x2de3, 0x435, 0x3b, 0x447, 0x435, 0x2de6,
+0x487, 0x3b, 0x43f, 0x467, 0x2de6, 0x487, 0x3b, 0x441, 0xa64b, 0x2de0, 0x487, 0x3b, 0x43d, 0x435, 0x434, 0x463, 0x301, 0x43b, 0x467, 0x3b,
+0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x463, 0x301, 0x43b, 0x44c, 0x43d, 0x438, 0x43a, 0x44a, 0x3b, 0x432, 0x442, 0x43e, 0x301, 0x440, 0x43d,
+0x438, 0x43a, 0x44a, 0x3b, 0x441, 0x440, 0x435, 0x434, 0x430, 0x300, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x435, 0x440, 0x442, 0x43e, 0x301,
+0x43a, 0x44a, 0x3b, 0x43f, 0x467, 0x442, 0x43e, 0x301, 0x43a, 0x44a, 0x3b, 0x441, 0xa64b, 0x431, 0x431, 0x461, 0x301, 0x442, 0x430, 0x3b,
+0x4c, 0x75, 0x6d, 0x3b, 0x4e, 0x6b, 0x6f, 0x3b, 0x4e, 0x64, 0x79, 0x3b, 0x4e, 0x64, 0x67, 0x3b, 0x4e, 0x6a, 0x77, 0x3b,
+0x4e, 0x67, 0x76, 0x3b, 0x4c, 0x75, 0x62, 0x3b, 0x4c, 0x75, 0x6d, 0x69, 0x6e, 0x67, 0x75, 0x3b, 0x4e, 0x6b, 0x6f, 0x64,
+0x79, 0x61, 0x3b, 0x4e, 0x64, 0xe0, 0x61, 0x79, 0xe0, 0x3b, 0x4e, 0x64, 0x61, 0x6e, 0x67, 0xf9, 0x3b, 0x4e, 0x6a, 0xf2,
+0x77, 0x61, 0x3b, 0x4e, 0x67, 0xf2, 0x76, 0x79, 0x61, 0x3b, 0x4c, 0x75, 0x62, 0x69, 0x6e, 0x67, 0x75, 0x3b, 0x4c, 0x3b,
+0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4c, 0x3b, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0xe9, 0x69, 0x3b,
+0x44, 0xeb, 0x6e, 0x3b, 0x4d, 0xeb, 0x74, 0x3b, 0x44, 0x6f, 0x6e, 0x3b, 0x46, 0x72, 0x65, 0x3b, 0x53, 0x61, 0x6d, 0x3b,
+0x53, 0x6f, 0x6e, 0x6e, 0x64, 0x65, 0x67, 0x3b, 0x4d, 0xe9, 0x69, 0x6e, 0x64, 0x65, 0x67, 0x3b, 0x44, 0xeb, 0x6e, 0x73,
+0x63, 0x68, 0x64, 0x65, 0x67, 0x3b, 0x4d, 0xeb, 0x74, 0x74, 0x77, 0x6f, 0x63, 0x68, 0x3b, 0x44, 0x6f, 0x6e, 0x6e, 0x65,
+0x73, 0x63, 0x68, 0x64, 0x65, 0x67, 0x3b, 0x46, 0x72, 0x65, 0x69, 0x64, 0x65, 0x67, 0x3b, 0x53, 0x61, 0x6d, 0x73, 0x63,
+0x68, 0x64, 0x65, 0x67, 0x3b, 0x53, 0x6f, 0x6e, 0x2e, 0x3b, 0x4d, 0xe9, 0x69, 0x2e, 0x3b, 0x44, 0xeb, 0x6e, 0x2e, 0x3b,
+0x4d, 0xeb, 0x74, 0x2e, 0x3b, 0x44, 0x6f, 0x6e, 0x2e, 0x3b, 0x46, 0x72, 0x65, 0x2e, 0x3b, 0x53, 0x61, 0x6d, 0x2e, 0x3b,
+0x6e, 0x74, 0x73, 0x3b, 0x6b, 0x70, 0x61, 0x3b, 0x67, 0x68, 0x254, 0x3b, 0x74, 0x254, 0x6d, 0x3b, 0x75, 0x6d, 0x65, 0x3b,
+0x67, 0x68, 0x268, 0x3b, 0x64, 0x7a, 0x6b, 0x3b, 0x74, 0x73, 0x75, 0x294, 0x6e, 0x74, 0x73, 0x268, 0x3b, 0x74, 0x73, 0x75,
+0x294, 0x75, 0x6b, 0x70, 0xe0, 0x3b, 0x74, 0x73, 0x75, 0x294, 0x75, 0x67, 0x68, 0x254, 0x65, 0x3b, 0x74, 0x73, 0x75, 0x294,
+0x75, 0x74, 0x254, 0x300, 0x6d, 0x6c, 0xf2, 0x3b, 0x74, 0x73, 0x75, 0x294, 0x75, 0x6d, 0xe8, 0x3b, 0x74, 0x73, 0x75, 0x294,
+0x75, 0x67, 0x68, 0x268, 0x302, 0x6d, 0x3b, 0x74, 0x73, 0x75, 0x294, 0x6e, 0x64, 0x7a, 0x268, 0x6b, 0x254, 0x294, 0x254, 0x3b,
+0x6e, 0x3b, 0x6b, 0x3b, 0x67, 0x3b, 0x74, 0x3b, 0x75, 0x3b, 0x67, 0x3b, 0x64, 0x3b, 0x6e, 0x254, 0x79, 0x3b, 0x6e, 0x6a,
+0x61, 0x3b, 0x75, 0x75, 0x6d, 0x3b, 0x14b, 0x67, 0x65, 0x3b, 0x6d, 0x62, 0x254, 0x3b, 0x6b, 0x254, 0x254, 0x3b, 0x6a, 0x6f,
+0x6e, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6e, 0x254, 0x302, 0x79, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6e, 0x6a, 0x61,
+0x14b, 0x67, 0x75, 0x6d, 0x62, 0x61, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0xfb, 0x6d, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20,
+0x14b, 0x67, 0xea, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6d, 0x62, 0x254, 0x6b, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6b,
+0x254, 0x254, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6a, 0xf4, 0x6e, 0x3b, 0x6e, 0x3b, 0x6e, 0x3b, 0x75, 0x3b, 0x14b, 0x3b,
+0x6d, 0x3b, 0x6b, 0x3b, 0x6a, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x64, 0x69, 0x3b, 0x41, 0x74, 0x69, 0x6e, 0x6e, 0x69, 0x3b,
+0x41, 0x74, 0x61, 0x6c, 0x61, 0x61, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x72, 0x62, 0x61, 0x3b, 0x41, 0x6c, 0x68, 0x61,
+0x6d, 0x69, 0x73, 0x69, 0x3b, 0x41, 0x6c, 0x7a, 0x75, 0x6d, 0x61, 0x3b, 0x41, 0x73, 0x69, 0x62, 0x74, 0x69, 0x3b, 0x48,
+0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x5a, 0x3b, 0x53, 0x3b, 0xe9, 0x74, 0x3b, 0x6d, 0x254, 0x301, 0x73,
+0x3b, 0x6b, 0x77, 0x61, 0x3b, 0x6d, 0x75, 0x6b, 0x3b, 0x14b, 0x67, 0x69, 0x3b, 0x257, 0xf3, 0x6e, 0x3b, 0x65, 0x73, 0x61,
+0x3b, 0xe9, 0x74, 0x69, 0x3b, 0x6d, 0x254, 0x301, 0x73, 0xfa, 0x3b, 0x6b, 0x77, 0x61, 0x73, 0xfa, 0x3b, 0x6d, 0x75, 0x6b,
+0x254, 0x301, 0x73, 0xfa, 0x3b, 0x14b, 0x67, 0x69, 0x73, 0xfa, 0x3b, 0x257, 0xf3, 0x6e, 0x25b, 0x73, 0xfa, 0x3b, 0x65, 0x73,
+0x61, 0x253, 0x61, 0x73, 0xfa, 0x3b, 0x65, 0x3b, 0x6d, 0x3b, 0x6b, 0x3b, 0x6d, 0x3b, 0x14b, 0x3b, 0x257, 0x3b, 0x65, 0x3b,
+0x44, 0x69, 0x6d, 0x3b, 0x54, 0x65, 0x6e, 0x3b, 0x54, 0x61, 0x6c, 0x3b, 0x41, 0x6c, 0x61, 0x3b, 0x41, 0x72, 0x61, 0x3b,
+0x41, 0x72, 0x6a, 0x3b, 0x53, 0x69, 0x62, 0x3b, 0x44, 0x69, 0x6d, 0x61, 0x73, 0x3b, 0x54, 0x65, 0x6e, 0x65, 0x14b, 0x3b,
+0x54, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x72, 0x62, 0x61, 0x79, 0x3b, 0x41, 0x72, 0x61, 0x6d, 0x69,
+0x73, 0x61, 0x79, 0x3b, 0x41, 0x72, 0x6a, 0x75, 0x6d, 0x61, 0x3b, 0x53, 0x69, 0x62, 0x69, 0x74, 0x69, 0x3b, 0x44, 0x3b,
+0x54, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x3b, 0x6d, 0x254, 0x301,
+0x6e, 0x3b, 0x73, 0x6d, 0x62, 0x3b, 0x73, 0x6d, 0x6c, 0x3b, 0x73, 0x6d, 0x6e, 0x3b, 0x66, 0xfa, 0x6c, 0x3b, 0x73, 0xe9,
+0x72, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x3b, 0x6d, 0x254, 0x301, 0x6e, 0x64, 0x69, 0x3b, 0x73, 0x254, 0x301, 0x6e,
+0x64, 0x254, 0x20, 0x6d, 0x259, 0x6c, 0xfa, 0x20, 0x6d, 0x259, 0x301, 0x62, 0x25b, 0x30c, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64,
+0x254, 0x20, 0x6d, 0x259, 0x6c, 0xfa, 0x20, 0x6d, 0x259, 0x301, 0x6c, 0x25b, 0x301, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254,
+0x20, 0x6d, 0x259, 0x6c, 0xfa, 0x20, 0x6d, 0x259, 0x301, 0x6e, 0x79, 0x69, 0x3b, 0x66, 0xfa, 0x6c, 0x61, 0x64, 0xe9, 0x3b,
+0x73, 0xe9, 0x72, 0x61, 0x64, 0xe9, 0x3b, 0x73, 0x3b, 0x6d, 0x3b, 0x73, 0x3b, 0x73, 0x3b, 0x73, 0x3b, 0x66, 0x3b, 0x73,
+0x3b, 0x73, 0x254, 0x301, 0x6e, 0x3b, 0x6c, 0x1dd, 0x6e, 0x3b, 0x6d, 0x61, 0x61, 0x3b, 0x6d, 0x25b, 0x6b, 0x3b, 0x6a, 0x1dd,
+0x1dd, 0x3b, 0x6a, 0xfa, 0x6d, 0x3b, 0x73, 0x61, 0x6d, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x1dd, 0x3b, 0x6c, 0x1dd, 0x6e,
+0x64, 0xed, 0x3b, 0x6d, 0x61, 0x61, 0x64, 0xed, 0x3b, 0x6d, 0x25b, 0x6b, 0x72, 0x25b, 0x64, 0xed, 0x3b, 0x6a, 0x1dd, 0x1dd,
+0x64, 0xed, 0x3b, 0x6a, 0xfa, 0x6d, 0x62, 0xe1, 0x3b, 0x73, 0x61, 0x6d, 0x64, 0xed, 0x3b, 0x73, 0x3b, 0x6c, 0x3b, 0x6d,
+0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x6a, 0x3b, 0x73, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6e, 0x6e,
+0x3b, 0x4a, 0x74, 0x6e, 0x3b, 0x41, 0x72, 0x61, 0x3b, 0x49, 0x6a, 0x75, 0x3b, 0x4a, 0x6d, 0x6f, 0x3b, 0x53, 0x61, 0x62,
+0x61, 0x74, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65,
+0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b,
+0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x53, 0x3b, 0x4a, 0x3b,
+0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x4a, 0x3b, 0x43, 0x79, 0x61, 0x3b, 0x43, 0x6c, 0x61, 0x3b, 0x43, 0x7a,
+0x69, 0x3b, 0x43, 0x6b, 0x6f, 0x3b, 0x43, 0x6b, 0x61, 0x3b, 0x43, 0x67, 0x61, 0x3b, 0x43, 0x7a, 0x65, 0x3b, 0x43, 0x6f,
+0x6d, 0x2019, 0x79, 0x61, 0x6b, 0x6b, 0x65, 0x3b, 0x43, 0x6f, 0x6d, 0x6c, 0x61, 0x61, 0x257, 0x69, 0x69, 0x3b, 0x43, 0x6f,
+0x6d, 0x7a, 0x79, 0x69, 0x69, 0x257, 0x69, 0x69, 0x3b, 0x43, 0x6f, 0x6d, 0x6b, 0x6f, 0x6c, 0x6c, 0x65, 0x3b, 0x43, 0x6f,
+0x6d, 0x6b, 0x61, 0x6c, 0x64, 0x1dd, 0x253, 0x6c, 0x69, 0x69, 0x3b, 0x43, 0x6f, 0x6d, 0x67, 0x61, 0x69, 0x73, 0x75, 0x75,
+0x3b, 0x43, 0x6f, 0x6d, 0x7a, 0x79, 0x65, 0x253, 0x73, 0x75, 0x75, 0x3b, 0x59, 0x3b, 0x4c, 0x3b, 0x5a, 0x3b, 0x4f, 0x3b,
+0x41, 0x3b, 0x47, 0x3b, 0x45, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x3b, 0x6d, 0x254, 0x301, 0x6e, 0x3b, 0x73, 0x6d, 0x62, 0x3b,
+0x73, 0x6d, 0x6c, 0x3b, 0x73, 0x6d, 0x6e, 0x3b, 0x6d, 0x62, 0x73, 0x3b, 0x73, 0x61, 0x73, 0x3b, 0x73, 0x254, 0x301, 0x6e,
+0x64, 0x254, 0x3b, 0x6d, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d, 0x61, 0x66,
+0xfa, 0x20, 0x6d, 0xe1, 0x62, 0x61, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d, 0x61, 0x66, 0xfa, 0x20, 0x6d,
+0xe1, 0x6c, 0x61, 0x6c, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d, 0x61, 0x66, 0xfa, 0x20, 0x6d, 0xe1, 0x6e,
+0x61, 0x3b, 0x6d, 0x61, 0x62, 0xe1, 0x67, 0xe1, 0x20, 0x6d, 0xe1, 0x20, 0x73, 0x75, 0x6b, 0x75, 0x6c, 0x3b, 0x73, 0xe1,
+0x73, 0x61, 0x64, 0x69, 0x3b, 0x73, 0x3b, 0x6d, 0x3b, 0x73, 0x3b, 0x73, 0x3b, 0x73, 0x3b, 0x6d, 0x3b, 0x73, 0x3b, 0x43,
+0xe4, 0x14b, 0x3b, 0x4a, 0x69, 0x65, 0x63, 0x3b, 0x52, 0x25b, 0x77, 0x3b, 0x44, 0x69, 0x254, 0x331, 0x6b, 0x3b, 0x14a, 0x75,
+0x61, 0x61, 0x6e, 0x3b, 0x44, 0x68, 0x69, 0x65, 0x65, 0x63, 0x3b, 0x42, 0xe4, 0x6b, 0x25b, 0x6c, 0x3b, 0x43, 0xe4, 0x14b,
+0x20, 0x6b, 0x75, 0x254, 0x74, 0x68, 0x3b, 0x4a, 0x69, 0x65, 0x63, 0x20, 0x6c, 0x61, 0x331, 0x74, 0x3b, 0x52, 0x25b, 0x77,
+0x20, 0x6c, 0xe4, 0x74, 0x6e, 0x69, 0x3b, 0x44, 0x69, 0x254, 0x331, 0x6b, 0x20, 0x6c, 0xe4, 0x74, 0x6e, 0x69, 0x3b, 0x14a,
+0x75, 0x61, 0x61, 0x6e, 0x20, 0x6c, 0xe4, 0x74, 0x6e, 0x69, 0x3b, 0x44, 0x68, 0x69, 0x65, 0x65, 0x63, 0x20, 0x6c, 0xe4,
+0x74, 0x6e, 0x69, 0x3b, 0x42, 0xe4, 0x6b, 0x25b, 0x6c, 0x20, 0x6c, 0xe4, 0x74, 0x6e, 0x69, 0x3b, 0x43, 0x3b, 0x4a, 0x3b,
+0x52, 0x3b, 0x44, 0x3b, 0x14a, 0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x431, 0x441, 0x3b, 0x431, 0x43d, 0x3b, 0x43e, 0x43f, 0x3b, 0x441,
+0x44d, 0x3b, 0x447, 0x43f, 0x3b, 0x431, 0x44d, 0x3b, 0x441, 0x431, 0x3b, 0x431, 0x430, 0x441, 0x43a, 0x44b, 0x4bb, 0x44b, 0x430, 0x43d,
+0x43d, 0x44c, 0x430, 0x3b, 0x431, 0x44d, 0x43d, 0x438, 0x434, 0x438, 0x44d, 0x43d, 0x43d, 0x44c, 0x438, 0x43a, 0x3b, 0x43e, 0x43f, 0x442,
+0x443, 0x43e, 0x440, 0x443, 0x43d, 0x43d, 0x44c, 0x443, 0x43a, 0x3b, 0x441, 0x44d, 0x440, 0x44d, 0x434, 0x44d, 0x3b, 0x447, 0x44d, 0x43f,
+0x43f, 0x438, 0x44d, 0x440, 0x3b, 0x411, 0x44d, 0x44d, 0x442, 0x438, 0x4a5, 0x441, 0x44d, 0x3b, 0x441, 0x443, 0x431, 0x443, 0x43e, 0x442,
+0x430, 0x3b, 0x411, 0x3b, 0x411, 0x3b, 0x41e, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x411, 0x3b, 0x421, 0x3b, 0x4d, 0x75, 0x6c, 0x3b,
+0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6e, 0x6e, 0x3b, 0x4a, 0x74, 0x6e, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x75, 0x3b,
+0x4a, 0x6d, 0x6f, 0x3b, 0x4d, 0x75, 0x6c, 0x75, 0x6e, 0x67, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x75,
+0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x6c,
+0x61, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d,
+0x6f, 0x73, 0x69, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x4a, 0x3b, 0xa55e, 0xa54c,
+0xa535, 0x3b, 0xa5f3, 0xa5e1, 0xa609, 0x3b, 0xa55a, 0xa55e, 0xa55a, 0x3b, 0xa549, 0xa55e, 0xa552, 0x3b, 0xa549, 0xa524, 0xa546, 0xa562, 0x3b, 0xa549,
+0xa524, 0xa540, 0xa56e, 0x3b, 0xa53b, 0xa52c, 0xa533, 0x3b, 0x6c, 0x61, 0x68, 0x61, 0x64, 0x69, 0x3b, 0x74, 0x25b, 0x25b, 0x6e, 0x25b,
+0x25b, 0x3b, 0x74, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b, 0x61, 0x6c, 0x61, 0x62, 0x61, 0x3b, 0x61, 0x69, 0x6d, 0x69, 0x73,
+0x61, 0x3b, 0x61, 0x69, 0x6a, 0x69, 0x6d, 0x61, 0x3b, 0x73, 0x69, 0x253, 0x69, 0x74, 0x69, 0x3b, 0x53, 0x75, 0x6e, 0x3b,
+0x4d, 0xe4, 0x6e, 0x3b, 0x5a, 0x69, 0x161, 0x3b, 0x4d, 0x69, 0x74, 0x3b, 0x46, 0x72, 0xf3, 0x3b, 0x46, 0x72, 0x69, 0x3b,
+0x53, 0x61, 0x6d, 0x3b, 0x53, 0x75, 0x6e, 0x6e, 0x74, 0x61, 0x67, 0x3b, 0x4d, 0xe4, 0x6e, 0x74, 0x61, 0x67, 0x3b, 0x5a,
+0x69, 0x161, 0x74, 0x61, 0x67, 0x3b, 0x4d, 0x69, 0x74, 0x74, 0x77, 0x75, 0x10d, 0x3b, 0x46, 0x72, 0xf3, 0x6e, 0x74, 0x61,
+0x67, 0x3b, 0x46, 0x72, 0x69, 0x74, 0x61, 0x67, 0x3b, 0x53, 0x61, 0x6d, 0x161, 0x74, 0x61, 0x67, 0x3b, 0x53, 0x3b, 0x4d,
+0x3b, 0x5a, 0x3b, 0x4d, 0x3b, 0x46, 0x3b, 0x46, 0x3b, 0x53, 0x3b, 0x73, 0x64, 0x3b, 0x6d, 0x64, 0x3b, 0x6d, 0x77, 0x3b,
+0x65, 0x74, 0x3b, 0x6b, 0x6c, 0x3b, 0x66, 0x6c, 0x3b, 0x73, 0x73, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x69, 0x25b, 0x3b,
+0x6d, 0xf3, 0x6e, 0x64, 0x69, 0x65, 0x3b, 0x6d, 0x75, 0xe1, 0x6e, 0x79, 0xe1, 0x14b, 0x6d, 0xf3, 0x6e, 0x64, 0x69, 0x65,
+0x3b, 0x6d, 0x65, 0x74, 0xfa, 0x6b, 0x70, 0xed, 0xe1, 0x70, 0x25b, 0x3b, 0x6b, 0xfa, 0x70, 0xe9, 0x6c, 0x69, 0x6d, 0x65,
+0x74, 0xfa, 0x6b, 0x70, 0x69, 0x61, 0x70, 0x25b, 0x3b, 0x66, 0x65, 0x6c, 0xe9, 0x74, 0x65, 0x3b, 0x73, 0xe9, 0x73, 0x65,
+0x6c, 0xe9, 0x3b, 0x73, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x65, 0x3b, 0x6b, 0x3b, 0x66, 0x3b, 0x73, 0x3b, 0x64, 0x6f, 0x6d,
+0x3b, 0x6c, 0x6c, 0x75, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d, 0x69, 0xe9, 0x3b, 0x78, 0x75, 0x65, 0x3b, 0x76, 0x69, 0x65,
+0x3b, 0x73, 0xe1, 0x62, 0x3b, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x75, 0x3b, 0x6c, 0x6c, 0x75, 0x6e, 0x65, 0x73, 0x3b,
+0x6d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x6d, 0x69, 0xe9, 0x72, 0x63, 0x6f, 0x6c, 0x65, 0x73, 0x3b, 0x78, 0x75, 0x65,
+0x76, 0x65, 0x73, 0x3b, 0x76, 0x69, 0x65, 0x6e, 0x72, 0x65, 0x73, 0x3b, 0x73, 0xe1, 0x62, 0x61, 0x64, 0x75, 0x3b, 0x53,
+0x254, 0x301, 0x6e, 0x64, 0x69, 0x3b, 0x4d, 0x254, 0x301, 0x6e, 0x64, 0x69, 0x3b, 0xc1, 0x70, 0x74, 0x61, 0x20, 0x4d, 0x254,
+0x301, 0x6e, 0x64, 0x69, 0x3b, 0x57, 0x25b, 0x301, 0x6e, 0x25b, 0x73, 0x25b, 0x64, 0x25b, 0x3b, 0x54, 0x254, 0x301, 0x73, 0x25b,
+0x64, 0x25b, 0x3b, 0x46, 0x25b, 0x6c, 0xe2, 0x79, 0x25b, 0x64, 0x25b, 0x3b, 0x53, 0xe1, 0x73, 0x69, 0x64, 0x25b, 0x3b, 0x53,
+0x254, 0x301, 0x3b, 0x4d, 0x254, 0x301, 0x3b, 0xc1, 0x4d, 0x3b, 0x57, 0x25b, 0x301, 0x3b, 0x54, 0x254, 0x301, 0x3b, 0x46, 0x25b,
+0x3b, 0x53, 0xe1, 0x3b, 0x73, 0x254, 0x6e, 0x64, 0x69, 0x3b, 0x6c, 0x75, 0x6e, 0x64, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x64,
+0x69, 0x3b, 0x6d, 0x25b, 0x72, 0x6b, 0x25b, 0x72, 0x25b, 0x64, 0x69, 0x3b, 0x79, 0x65, 0x64, 0x69, 0x3b, 0x76, 0x61, 0x14b,
+0x64, 0x25b, 0x72, 0x25b, 0x64, 0x69, 0x3b, 0x6d, 0x254, 0x6e, 0x254, 0x20, 0x73, 0x254, 0x6e, 0x64, 0x69, 0x3b, 0x73, 0x6f,
+0x3b, 0x6c, 0x75, 0x3b, 0x6d, 0x61, 0x3b, 0x6d, 0x25b, 0x3b, 0x79, 0x65, 0x3b, 0x76, 0x61, 0x3b, 0x6d, 0x73, 0x3b, 0x41,
+0x6e, 0x65, 0x67, 0x20, 0x31, 0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x32, 0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x33, 0x3b,
+0x41, 0x6e, 0x65, 0x67, 0x20, 0x34, 0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x35, 0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x36,
+0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x37, 0x3b, 0x41, 0x31, 0x3b, 0x41, 0x32, 0x3b, 0x41, 0x33, 0x3b, 0x41, 0x34, 0x3b,
+0x41, 0x35, 0x3b, 0x41, 0x36, 0x3b, 0x41, 0x37, 0x3b, 0x6c, 0x79, 0x25b, 0x2bc, 0x25b, 0x301, 0x20, 0x73, 0x1e85, 0xed, 0x14b,
+0x74, 0xe8, 0x3b, 0x6d, 0x76, 0x66, 0xf2, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x6d, 0x62, 0x254, 0x301, 0x254, 0x6e,
+0x74, 0xe8, 0x20, 0x6d, 0x76, 0x66, 0xf2, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x74, 0x73, 0xe8, 0x74, 0x73, 0x25b,
+0x300, 0x25b, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x6d, 0x62, 0x254, 0x301, 0x254, 0x6e, 0x74, 0xe8, 0x20, 0x74, 0x73,
+0x65, 0x74, 0x73, 0x25b, 0x300, 0x25b, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x6d, 0x76, 0x66, 0xf2, 0x20, 0x6d, 0xe0,
+0x67, 0x61, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x6d, 0xe0, 0x67, 0x61, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b,
+0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x77, 0x61, 0x6b, 0x21f, 0x61, 0x14b, 0x3b, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x77,
+0x61, 0x14b, 0x17e, 0x69, 0x3b, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x6e, 0x75, 0x14b, 0x70, 0x61, 0x3b, 0x41, 0x14b, 0x70,
+0xe9, 0x74, 0x75, 0x79, 0x61, 0x6d, 0x6e, 0x69, 0x3b, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x74, 0x6f, 0x70, 0x61, 0x3b,
+0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x7a, 0x61, 0x70, 0x74, 0x61, 0x14b, 0x3b, 0x4f, 0x77, 0xe1, 0x14b, 0x67, 0x79, 0x75,
+0x17e, 0x61, 0x17e, 0x61, 0x70, 0x69, 0x3b, 0x41, 0x3b, 0x57, 0x3b, 0x4e, 0x3b, 0x59, 0x3b, 0x54, 0x3b, 0x5a, 0x3b, 0x4f,
+0x3b, 0x2d30, 0x2d59, 0x2d30, 0x2d4e, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d62, 0x2d4f, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d4f, 0x2d30, 0x2d59,
+0x3b, 0x2d30, 0x2d3d, 0x2d55, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d3d, 0x2d61, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d4e, 0x2d61, 0x2d30, 0x2d59,
+0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d39, 0x2d62, 0x2d30, 0x2d59, 0x3b, 0x6cc, 0x6d5, 0x6a9, 0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x62f, 0x648,
+0x648, 0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x633, 0x6ce, 0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x686, 0x648, 0x627, 0x631, 0x634,
+0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x67e, 0x6ce, 0x646, 0x62c, 0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x6be, 0x6d5, 0x6cc, 0x646, 0x6cc,
+0x3b, 0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x6cc, 0x3b, 0x62f, 0x3b, 0x633, 0x3b, 0x686, 0x3b, 0x67e, 0x3b, 0x6be, 0x3b, 0x634,
+0x3b, 0x6e, 0x6a, 0x65, 0x3b, 0x70, 0xf3, 0x6e, 0x3b, 0x77, 0x61, 0x142, 0x3b, 0x73, 0x72, 0x6a, 0x3b, 0x73, 0x74, 0x77,
+0x3b, 0x70, 0x11b, 0x74, 0x3b, 0x73, 0x6f, 0x62, 0x3b, 0x6e, 0x6a, 0x65, 0x17a, 0x65, 0x6c, 0x61, 0x3b, 0x70, 0xf3, 0x6e,
+0x6a, 0x65, 0x17a, 0x65, 0x6c, 0x65, 0x3b, 0x77, 0x61, 0x142, 0x74, 0x6f, 0x72, 0x61, 0x3b, 0x73, 0x72, 0x6a, 0x6f, 0x64,
+0x61, 0x3b, 0x73, 0x74, 0x77, 0xf3, 0x72, 0x74, 0x6b, 0x3b, 0x70, 0x11b, 0x74, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74,
+0x61, 0x3b, 0x6e, 0x3b, 0x70, 0x3b, 0x77, 0x3b, 0x73, 0x3b, 0x73, 0x3b, 0x70, 0x3b, 0x73, 0x3b, 0x6e, 0x6a, 0x65, 0x3b,
+0x70, 0xf3, 0x6e, 0x3b, 0x77, 0x75, 0x74, 0x3b, 0x73, 0x72, 0x6a, 0x3b, 0x161, 0x74, 0x77, 0x3b, 0x70, 0x6a, 0x61, 0x3b,
+0x73, 0x6f, 0x62, 0x3b, 0x6e, 0x6a, 0x65, 0x64, 0x17a, 0x65, 0x6c, 0x61, 0x3b, 0x70, 0xf3, 0x6e, 0x64, 0x17a, 0x65, 0x6c,
+0x61, 0x3b, 0x77, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x3b, 0x73, 0x72, 0x6a, 0x65, 0x64, 0x61, 0x3b, 0x161, 0x74, 0x77, 0xf3,
+0x72, 0x74, 0x6b, 0x3b, 0x70, 0x6a, 0x61, 0x74, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x6e, 0x3b, 0x70,
+0x3b, 0x77, 0x3b, 0x73, 0x3b, 0x161, 0x3b, 0x70, 0x3b, 0x73, 0x3b, 0x6e, 0x61, 0x64, 0x3b, 0x70, 0x61, 0x6e, 0x3b, 0x77,
+0x69, 0x73, 0x3b, 0x70, 0x75, 0x73, 0x3b, 0x6b, 0x65, 0x74, 0x3b, 0x70, 0x113, 0x6e, 0x3b, 0x73, 0x61, 0x62, 0x3b, 0x6e,
+0x61, 0x64, 0x12b, 0x6c, 0x69, 0x3b, 0x70, 0x61, 0x6e, 0x61, 0x64, 0x12b, 0x6c, 0x69, 0x3b, 0x77, 0x69, 0x73, 0x61, 0x73,
+0x12b, 0x64, 0x69, 0x73, 0x3b, 0x70, 0x75, 0x73, 0x73, 0x69, 0x73, 0x61, 0x77, 0x61, 0x69, 0x74, 0x69, 0x3b, 0x6b, 0x65,
+0x74, 0x77, 0x69, 0x72, 0x74, 0x69, 0x6b, 0x73, 0x3b, 0x70, 0x113, 0x6e, 0x74, 0x6e, 0x69, 0x6b, 0x73, 0x3b, 0x73, 0x61,
+0x62, 0x61, 0x74, 0x74, 0x69, 0x6b, 0x61, 0x3b, 0x4e, 0x3b, 0x50, 0x3b, 0x57, 0x3b, 0x50, 0x3b, 0x4b, 0x3b, 0x50, 0x3b,
+0x53, 0x3b, 0x70, 0x61, 0x73, 0x3b, 0x76, 0x75, 0x6f, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6b, 0x6f, 0x73, 0x3b, 0x74, 0x75,
0x6f, 0x3b, 0x76, 0xe1, 0x73, 0x3b, 0x6c, 0xe1, 0x76, 0x3b, 0x70, 0x61, 0x73, 0x65, 0x70, 0x65, 0x69, 0x76, 0x69, 0x3b,
0x76, 0x75, 0x6f, 0x73, 0x73, 0x61, 0x72, 0x67, 0xe2, 0x3b, 0x6d, 0x61, 0x6a, 0x65, 0x62, 0x61, 0x72, 0x67, 0xe2, 0x3b,
0x6b, 0x6f, 0x73, 0x6b, 0x6f, 0x6b, 0x6b, 0x6f, 0x3b, 0x74, 0x75, 0x6f, 0x72, 0xe2, 0x73, 0x74, 0xe2, 0x68, 0x3b, 0x76,
@@ -4842,156 +5062,176 @@ static const ushort byte_unit_data[] = {
0x62, 0x79, 0x74, 0x65, 0x73, 0x6b, 0x42, 0x3b, 0x4d, 0x42, 0x3b, 0x47, 0x42, 0x3b, 0x54, 0x42, 0x3b, 0x50, 0x42, 0x3b,
0x45, 0x42, 0x4b, 0x69, 0x42, 0x3b, 0x4d, 0x69, 0x42, 0x3b, 0x47, 0x69, 0x42, 0x3b, 0x54, 0x69, 0x42, 0x3b, 0x50, 0x69,
0x42, 0x3b, 0x45, 0x69, 0x42, 0x62, 0x79, 0x74, 0x65, 0x67, 0x72, 0x65, 0x70, 0x65, 0x62, 0x61, 0x6a, 0x74, 0x1263, 0x12ed,
-0x1275, 0x12aa, 0x1263, 0x3b, 0x121c, 0x130b, 0x1263, 0x12ed, 0x1275, 0x3b, 0x130a, 0x1263, 0x3b, 0x1274, 0x122b, 0x1263, 0x12ed, 0x1275, 0x3b, 0x50,
-0x42, 0x3b, 0x45, 0x42, 0x628, 0x627, 0x64a, 0x62a, 0x643, 0x64a, 0x644, 0x648, 0x628, 0x627, 0x64a, 0x62a, 0x3b, 0x645, 0x64a, 0x63a,
+0x1275, 0x12aa, 0x1263, 0x3b, 0x121c, 0x130b, 0x1263, 0x12ed, 0x1275, 0x3b, 0x130a, 0x1263, 0x3b, 0x1274, 0x122b, 0x1263, 0x12ed, 0x1275, 0x3b, 0x1354,
+0x1263, 0x3b, 0x45, 0x42, 0x628, 0x627, 0x64a, 0x62a, 0x643, 0x64a, 0x644, 0x648, 0x628, 0x627, 0x64a, 0x62a, 0x3b, 0x645, 0x64a, 0x63a,
0x627, 0x628, 0x627, 0x64a, 0x62a, 0x3b, 0x63a, 0x64a, 0x63a, 0x627, 0x628, 0x627, 0x64a, 0x62a, 0x3b, 0x62a, 0x64a, 0x631, 0x627, 0x628,
-0x627, 0x64a, 0x62a, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0x562, 0x561, 0x575, 0x569, 0x565, 0x580, 0x56f, 0x532, 0x3b, 0x544, 0x532,
-0x3b, 0x533, 0x532, 0x3b, 0x54f, 0x532, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0x62, 0x61, 0x79, 0x74, 0x62, 0x79, 0x74, 0x65,
-0x2d, 0x61, 0x6b, 0x9ac, 0x9be, 0x987, 0x99f, 0x6f, 0x6b, 0x74, 0x65, 0x64, 0x6f, 0xf9, 0x6b, 0x6f, 0x3b, 0x4d, 0x6f, 0x3b,
-0x47, 0x6f, 0x3b, 0x54, 0x6f, 0x3b, 0x50, 0x6f, 0x3b, 0x45, 0x6f, 0x4b, 0x69, 0x6f, 0x3b, 0x4d, 0x69, 0x6f, 0x3b, 0x47,
-0x69, 0x6f, 0x3b, 0x54, 0x69, 0x6f, 0x3b, 0x50, 0x69, 0x6f, 0x3b, 0x45, 0x69, 0x6f, 0x431, 0x430, 0x439, 0x442, 0x43e, 0x432,
+0x627, 0x64a, 0x62a, 0x3b, 0x628, 0x64a, 0x62a, 0x627, 0x628, 0x627, 0x64a, 0x62a, 0x3b, 0x45, 0x42, 0x562, 0x561, 0x575, 0x569, 0x565,
+0x580, 0x56f, 0x532, 0x3b, 0x544, 0x532, 0x3b, 0x533, 0x532, 0x3b, 0x54f, 0x532, 0x3b, 0x54a, 0x532, 0x3b, 0x45, 0x42, 0x9ac, 0x9be,
+0x987, 0x99f, 0x995, 0x9bf, 0x983, 0x20, 0x9ac, 0x9be, 0x983, 0x3b, 0x9ae, 0x9c7, 0x983, 0x20, 0x9ac, 0x9be, 0x983, 0x3b, 0x997, 0x9bf,
+0x983, 0x20, 0x9ac, 0x9be, 0x983, 0x3b, 0x99f, 0x9c7, 0x983, 0x20, 0x9ac, 0x9be, 0x983, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0x62,
+0x61, 0x79, 0x74, 0x62, 0x79, 0x74, 0x65, 0x2d, 0x61, 0x6b, 0x6f, 0x6b, 0x74, 0x65, 0x64, 0x6f, 0xf9, 0x6b, 0x6f, 0x3b,
+0x4d, 0x6f, 0x3b, 0x47, 0x6f, 0x3b, 0x54, 0x6f, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0x431, 0x430, 0x439, 0x442, 0x43e, 0x432,
0x435, 0x1018, 0x102d, 0x102f, 0x1000, 0x103a, 0x431, 0x430, 0x439, 0x442, 0x44b, 0x41a, 0x411, 0x3b, 0x41c, 0x411, 0x3b, 0x413, 0x411, 0x3b,
-0x422, 0x411, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0x1794, 0x17c3, 0x5b57, 0x8282, 0x5343, 0x5b57, 0x8282, 0x3b, 0x5146, 0x5b57, 0x8282, 0x3b,
+0x422, 0x411, 0x3b, 0x41f, 0x411, 0x3b, 0x45, 0x42, 0x1794, 0x17c3, 0x5b57, 0x8282, 0x5343, 0x5b57, 0x8282, 0x3b, 0x5146, 0x5b57, 0x8282, 0x3b,
0x5409, 0x5b57, 0x8282, 0x3b, 0x592a, 0x5b57, 0x8282, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0x4f4d, 0x5143, 0x7d44, 0x62, 0x61, 0x6a, 0x74,
-0x6f, 0x76, 0x69, 0x62, 0x61, 0x6a, 0x74, 0x79, 0x62, 0x61, 0x69, 0x64, 0x69, 0x64, 0x62, 0xfd, 0x74, 0x4b, 0x42, 0x3b,
-0x4d, 0x42, 0x3b, 0x47, 0x42, 0x3b, 0x54, 0x42, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0x74, 0x61, 0x76, 0x75, 0x74, 0x6b,
-0x74, 0x3b, 0x4d, 0x74, 0x3b, 0x47, 0x74, 0x3b, 0x54, 0x74, 0x3b, 0x50, 0x74, 0x3b, 0x45, 0x74, 0x4b, 0x69, 0x74, 0x3b,
-0x4d, 0x69, 0x74, 0x3b, 0x47, 0x69, 0x74, 0x3b, 0x54, 0x69, 0x74, 0x3b, 0x50, 0x69, 0x74, 0x3b, 0x45, 0x69, 0x74, 0x6f,
-0x63, 0x74, 0x65, 0x74, 0x73, 0x62, 0x61, 0x69, 0x64, 0x68, 0x74, 0x10d1, 0x10d0, 0x10d8, 0x10e2, 0x10d8, 0x10d9, 0x10d1, 0x10d0, 0x10d8,
-0x10e2, 0x10d8, 0x3b, 0x10db, 0x10d1, 0x10d0, 0x10d8, 0x10e2, 0x10d8, 0x3b, 0x10d2, 0x10d1, 0x10d0, 0x10d8, 0x10e2, 0x10d8, 0x3b, 0x10e2, 0x10d1, 0x10d0,
-0x10d8, 0x10e2, 0x10d8, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0x42, 0x79, 0x74, 0x65, 0x73, 0xaac, 0xabe, 0xa87, 0xa9f, 0x5d1, 0x5ea,
-0x5d9, 0x5dd, 0x92c, 0x93e, 0x907, 0x91f, 0x62, 0xe1, 0x6a, 0x74, 0x62, 0xe6, 0x74, 0x69, 0x62, 0x65, 0x61, 0x72, 0x74, 0x61,
-0x30d0, 0x30a4, 0x30c8, 0xcac, 0xcc8, 0xc9f, 0xccd, 0x200c, 0xc97, 0xcb3, 0xcc1, 0xc95, 0xcbf, 0x2e, 0xcac, 0xcc8, 0x2e, 0x3b, 0xcae, 0xcc6,
-0x2e, 0xcac, 0xcc8, 0x2e, 0x3b, 0xc97, 0xcbf, 0x2e, 0xcac, 0xcc8, 0x2e, 0x3b, 0xc9f, 0xcc6, 0x2e, 0xcac, 0xcc8, 0x2e, 0x3b, 0x50,
-0x42, 0x3b, 0x45, 0x42, 0x431, 0x430, 0x439, 0x442, 0x43a, 0x411, 0x3b, 0x4d, 0x411, 0x3b, 0x413, 0x411, 0x3b, 0x54, 0x411, 0x3b,
-0x50, 0x411, 0x3b, 0x45, 0x411, 0x4b, 0x69, 0x411, 0x3b, 0x4d, 0x69, 0x411, 0x3b, 0x47, 0x69, 0x411, 0x3b, 0x54, 0x69, 0x411,
-0x3b, 0x50, 0x69, 0x411, 0x3b, 0x45, 0x69, 0x411, 0x43a, 0x411, 0x3b, 0x41c, 0x411, 0x3b, 0x413, 0x411, 0x3b, 0x422, 0x411, 0x3b,
-0x50, 0x42, 0x3b, 0x45, 0x42, 0xbc14, 0xc774, 0xd2b8, 0x62, 0x61, 0x69, 0x74, 0x69, 0x62, 0x61, 0x69, 0x74, 0x61, 0x69, 0x431,
-0x430, 0x458, 0x442, 0x438, 0x62, 0x61, 0x69, 0x74, 0xd2c, 0xd48, 0xd31, 0xd4d, 0xd31, 0xd4d, 0xd15, 0xd3f, 0x2e, 0xd2c, 0xd3f, 0x2e,
-0x3b, 0xd2e, 0xd46, 0x2e, 0xd2c, 0xd48, 0x2e, 0x3b, 0xd1c, 0xd3f, 0x2e, 0xd2c, 0xd48, 0x2e, 0x3b, 0xd1f, 0xd3f, 0xd2c, 0xd3f, 0x3b,
-0x50, 0x42, 0x3b, 0x45, 0x42, 0x628, 0x627, 0x6cc, 0x62a, 0x6a9, 0x6cc, 0x644, 0x648, 0x628, 0x627, 0x6cc, 0x62a, 0x3b, 0x645, 0x6af,
-0x627, 0x628, 0x627, 0x6cc, 0x62a, 0x3b, 0x6af, 0x6cc, 0x6af, 0x627, 0x628, 0x627, 0x6cc, 0x62a, 0x3b, 0x62a, 0x631, 0x627, 0x628, 0x627,
-0x6cc, 0x62a, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0xa2c, 0xa3e, 0xa07, 0xa1f, 0x62, 0x79, 0x21b, 0x69, 0x431, 0x430, 0x458, 0x442,
-0x43e, 0x432, 0x438, 0xdb6, 0xdba, 0xdd2, 0xda7, 0xdca, 0xd9a, 0xdd2, 0xdb6, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0xdb8, 0xdd9, 0xdb6, 0x20,
-0x7b, 0x30, 0x7d, 0x3b, 0xd9c, 0xdd2, 0xdb6, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0xda7, 0xdd9, 0xdb6, 0x20, 0x7b, 0x30, 0x7d, 0x3b,
-0x50, 0x42, 0x3b, 0x45, 0x42, 0x6b, 0x69, 0x6c, 0x6f, 0x62, 0x61, 0x69, 0x74, 0x69, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x4d,
-0x42, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x47, 0x42, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x74, 0x65, 0x72, 0x61, 0x62, 0x61, 0x69,
-0x74, 0x69, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0xbaa, 0xbc8, 0xb9f, 0xbcd, 0xb95, 0xbb3, 0xbcd, 0xc2c,
-0xc48, 0xc1f, 0xc4d, 0x200c, 0xc32, 0xc41, 0xc15, 0xc47, 0xc2c, 0xc40, 0x3b, 0xc0e, 0xc2e, 0xc4d, 0x200c, 0xc2c, 0xc3f, 0x3b, 0xc1c, 0xc40,
-0xc2c, 0xc40, 0x3b, 0xc1f, 0xc40, 0xc2c, 0xc40, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0xe44, 0xe1a, 0xe15, 0xe4c, 0x70, 0x61, 0x69,
-0x74, 0x69, 0x6b, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x4d, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30,
-0x7d, 0x3b, 0x47, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x54, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30,
-0x7d, 0x3b, 0x50, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x45, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30,
-0x7d, 0x4b, 0x69, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x4d, 0x69, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b,
-0x30, 0x7d, 0x3b, 0x47, 0x69, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x54, 0x69, 0x42, 0x20, 0x2bb, 0x65,
-0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x50, 0x69, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x45, 0x69, 0x42, 0x20,
-0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x62, 0x61, 0xfd, 0x74, 0x431, 0x430, 0x439, 0x442, 0x438, 0x62, 0x65, 0x69, 0x74, 0x69,
-0x61, 0x75, 0x13d7, 0x13d3, 0x13cd, 0x13a6, 0x13b5, 0x13a9, 0x431, 0x430, 0x430, 0x439, 0x442, 0x43a, 0x411, 0x3b, 0x41c, 0x411, 0x3b, 0x47,
-0x42, 0x3b, 0x54, 0x42, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0x62, 0x79, 0x74, 0x65, 0x79
+0x6f, 0x76, 0x69, 0x62, 0x61, 0x6a, 0x74, 0x79, 0x62, 0x61, 0x6a, 0x74, 0x6f, 0x6a, 0x62, 0x61, 0x69, 0x64, 0x69, 0x64,
+0x62, 0xfd, 0x74, 0x4b, 0x42, 0x3b, 0x4d, 0x42, 0x3b, 0x47, 0x42, 0x3b, 0x54, 0x42, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42,
+0x74, 0x61, 0x76, 0x75, 0x74, 0x6b, 0x74, 0x3b, 0x4d, 0x74, 0x3b, 0x47, 0x74, 0x3b, 0x54, 0x74, 0x3b, 0x50, 0x74, 0x3b,
+0x45, 0x74, 0x4b, 0x69, 0x74, 0x3b, 0x4d, 0x69, 0x74, 0x3b, 0x47, 0x69, 0x74, 0x3b, 0x54, 0x69, 0x74, 0x3b, 0x50, 0x69,
+0x74, 0x3b, 0x45, 0x69, 0x74, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x73, 0x6b, 0x6f, 0x3b, 0x4d, 0x6f, 0x3b, 0x47, 0x6f, 0x3b,
+0x54, 0x6f, 0x3b, 0x50, 0x6f, 0x3b, 0x45, 0x6f, 0x4b, 0x69, 0x6f, 0x3b, 0x4d, 0x69, 0x6f, 0x3b, 0x47, 0x69, 0x6f, 0x3b,
+0x54, 0x69, 0x6f, 0x3b, 0x50, 0x69, 0x6f, 0x3b, 0x45, 0x69, 0x6f, 0x62, 0x61, 0x69, 0x64, 0x68, 0x74, 0x10d1, 0x10d0, 0x10d8,
+0x10e2, 0x10d8, 0x10d9, 0x10d1, 0x10d0, 0x10d8, 0x10e2, 0x10d8, 0x3b, 0x10db, 0x10d1, 0x10d0, 0x10d8, 0x10e2, 0x10d8, 0x3b, 0x10d2, 0x10d1, 0x10d0, 0x10d8,
+0x10e2, 0x10d8, 0x3b, 0x10e2, 0x10d1, 0x10d0, 0x10d8, 0x10e2, 0x10d8, 0x3b, 0x10de, 0x10d1, 0x10d0, 0x10d8, 0x10e2, 0x10d8, 0x3b, 0x45, 0x42, 0x42,
+0x79, 0x74, 0x65, 0x73, 0xaac, 0xabe, 0xa87, 0xa9f, 0x6b, 0x42, 0x3b, 0x4d, 0x42, 0x3b, 0x47, 0x42, 0x3b, 0x54, 0x42, 0x3b,
+0xaaa, 0xac0, 0xaac, 0xac0, 0x3b, 0x45, 0x42, 0x5d1, 0x5d9, 0x5d9, 0x5d8, 0x92c, 0x93e, 0x907, 0x91f, 0x62, 0xe1, 0x6a, 0x74, 0x62,
+0xe6, 0x74, 0x69, 0x62, 0x65, 0x61, 0x72, 0x74, 0x61, 0x30d0, 0x30a4, 0x30c8, 0x62, 0x69, 0x74, 0x65, 0xcac, 0xcc8, 0xc9f, 0xccd,
+0x200c, 0xc97, 0xcb3, 0xcc1, 0xc95, 0xcbf, 0x2e, 0xcac, 0xcc8, 0x2e, 0x3b, 0xcae, 0xcc6, 0x2e, 0xcac, 0xcc8, 0x2e, 0x3b, 0xc97, 0xcbf,
+0x2e, 0xcac, 0xcc8, 0x2e, 0x3b, 0xc9f, 0xcc6, 0x2e, 0xcac, 0xcc8, 0x2e, 0x3b, 0xcaa, 0xcc6, 0xcac, 0xcc8, 0x3b, 0x45, 0x42, 0x431,
+0x430, 0x439, 0x442, 0x43a, 0x411, 0x3b, 0x4d, 0x411, 0x3b, 0x413, 0x411, 0x3b, 0x54, 0x411, 0x3b, 0x41f, 0x411, 0x3b, 0x45, 0x411,
+0x4b, 0x69, 0x411, 0x3b, 0x4d, 0x69, 0x411, 0x3b, 0x47, 0x69, 0x411, 0x3b, 0x54, 0x69, 0x411, 0x3b, 0x50, 0x69, 0x411, 0x3b,
+0x45, 0x69, 0x411, 0x43a, 0x411, 0x3b, 0x41c, 0x411, 0x3b, 0x413, 0x411, 0x3b, 0x422, 0x411, 0x3b, 0x41f, 0x442, 0x431, 0x3b, 0x45,
+0x42, 0xbc14, 0xc774, 0xd2b8, 0x62, 0x61, 0x69, 0x74, 0x69, 0x62, 0x61, 0x69, 0x74, 0x61, 0x69, 0x431, 0x430, 0x458, 0x442, 0x438,
+0x62, 0x61, 0x69, 0x74, 0xd2c, 0xd48, 0xd31, 0xd4d, 0xd31, 0xd4d, 0xd15, 0xd3f, 0x2e, 0xd2c, 0xd3f, 0x2e, 0x3b, 0xd2e, 0xd46, 0x2e,
+0xd2c, 0xd48, 0x2e, 0x3b, 0xd1c, 0xd3f, 0x2e, 0xd2c, 0xd48, 0x2e, 0x3b, 0xd1f, 0xd3f, 0xd2c, 0xd3f, 0x3b, 0x50, 0x42, 0x3b, 0x45,
+0x42, 0x43a, 0x411, 0x3b, 0x41c, 0x411, 0x3b, 0x413, 0x411, 0x3b, 0x422, 0x411, 0x3b, 0x41f, 0x411, 0x3b, 0x45, 0x42, 0x6b, 0x42,
+0x3b, 0x4d, 0x42, 0x3b, 0x47, 0x42, 0x3b, 0x54, 0x42, 0x3b, 0x92a, 0x93f, 0x91f, 0x93e, 0x3b, 0x45, 0x42, 0xb2c, 0xb3e, 0xb07,
+0xb1f, 0xb4d, 0x628, 0x627, 0x64a, 0x67c, 0x633, 0x628, 0x627, 0x6cc, 0x62a, 0x6a9, 0x6cc, 0x644, 0x648, 0x628, 0x627, 0x6cc, 0x62a, 0x3b,
+0x645, 0x6af, 0x627, 0x628, 0x627, 0x6cc, 0x62a, 0x3b, 0x6af, 0x6cc, 0x6af, 0x627, 0x628, 0x627, 0x6cc, 0x62a, 0x3b, 0x62a, 0x631, 0x627,
+0x628, 0x627, 0x6cc, 0x62a, 0x3b, 0x67e, 0x62a, 0x627, 0x628, 0x627, 0x6cc, 0x62a, 0x3b, 0x45, 0x42, 0xa2c, 0xa3e, 0xa07, 0xa1f, 0x62,
+0x79, 0x21b, 0x69, 0x431, 0x430, 0x458, 0x442, 0x43e, 0x432, 0x438, 0x628, 0x627, 0x626, 0x64a, 0x67d, 0x632, 0x6aa, 0x644, 0x648, 0x20,
+0x628, 0x627, 0x626, 0x64a, 0x67d, 0x632, 0x3b, 0x645, 0x64a, 0x6af, 0x627, 0x20, 0x628, 0x627, 0x626, 0x64a, 0x67d, 0x632, 0x3b, 0x6af,
+0x64a, 0x6af, 0x627, 0x20, 0x628, 0x627, 0x626, 0x64a, 0x67d, 0x632, 0x3b, 0x67d, 0x64a, 0x631, 0x627, 0x20, 0x628, 0x627, 0x626, 0x64a,
+0x67d, 0x632, 0x3b, 0x67e, 0x64a, 0x631, 0x627, 0x20, 0x628, 0x627, 0x626, 0x64a, 0x67d, 0x633, 0x3b, 0x45, 0x42, 0xdb6, 0xdba, 0xdd2,
+0xda7, 0xdca, 0xd9a, 0xdd2, 0xdb6, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0xdb8, 0xdd9, 0xdb6, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0xd9c, 0xdd2,
+0xdb6, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0xda7, 0xdd9, 0xdb6, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0xdb4, 0xdd9, 0xdb6, 0x20, 0x7b, 0x30,
+0x7d, 0x3b, 0x45, 0x42, 0x62, 0x65, 0x79, 0x74, 0x6b, 0x69, 0x6c, 0x6f, 0x62, 0x61, 0x69, 0x74, 0x69, 0x20, 0x7b, 0x30,
+0x7d, 0x3b, 0x4d, 0x42, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x47, 0x42, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x74, 0x65, 0x72, 0x61,
+0x62, 0x61, 0x69, 0x74, 0x69, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x50, 0x42, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x45, 0x42, 0xbaa,
+0xbc8, 0xb9f, 0xbcd, 0xb95, 0xbb3, 0xbcd, 0xc2c, 0xc48, 0xc1f, 0xc4d, 0x200c, 0xc32, 0xc41, 0xc15, 0xc47, 0xc2c, 0xc40, 0x3b, 0xc0e, 0xc2e,
+0xc4d, 0x200c, 0xc2c, 0xc3f, 0x3b, 0xc1c, 0xc40, 0xc2c, 0xc40, 0x3b, 0xc1f, 0xc40, 0xc2c, 0xc40, 0x3b, 0xc2a, 0xc40, 0xc2c, 0xc40, 0x3b,
+0x45, 0x42, 0xe44, 0xe1a, 0xe15, 0xe4c, 0x70, 0x61, 0x69, 0x74, 0x69, 0x6b, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d,
+0x3b, 0x4d, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x47, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d,
+0x3b, 0x54, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x50, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d,
+0x3b, 0x45, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x4b, 0x69, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d,
+0x3b, 0x4d, 0x69, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x47, 0x69, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b,
+0x30, 0x7d, 0x3b, 0x54, 0x69, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x50, 0x69, 0x42, 0x20, 0x2bb, 0x65,
+0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x45, 0x69, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x62, 0x61, 0xfd, 0x74, 0x431,
+0x430, 0x439, 0x442, 0x438, 0x628, 0x627, 0x626, 0x679, 0x6b, 0x42, 0x3b, 0x4d, 0x42, 0x3b, 0x47, 0x42, 0x3b, 0x54, 0x42, 0x3b,
+0x67e, 0x6cc, 0x20, 0x628, 0x6cc, 0x3b, 0x45, 0x42, 0x62, 0x65, 0x69, 0x74, 0x69, 0x61, 0x75, 0x61, 0x1e6d, 0x61, 0x6d, 0x1e0d,
+0x61, 0x6e, 0x6b, 0x41, 0x1e6c, 0x3b, 0x4d, 0x41, 0x1e6c, 0x3b, 0x47, 0x41, 0x1e6c, 0x3b, 0x54, 0x41, 0x1e6c, 0x3b, 0x50, 0x42,
+0x3b, 0x45, 0x42, 0x13d7, 0x13d3, 0x13cd, 0x13a6, 0x13b5, 0x13a9, 0x431, 0x430, 0x430, 0x439, 0x442, 0x43a, 0x411, 0x3b, 0x41c, 0x411, 0x3b,
+0x47, 0x42, 0x3b, 0x54, 0x42, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0x62, 0x79, 0x74, 0x65, 0x79, 0x6a9, 0x6cc, 0x644, 0x648,
+0x628, 0x627, 0x6cc, 0x62a, 0x3b, 0x645, 0x6af, 0x627, 0x628, 0x627, 0x6cc, 0x62a, 0x3b, 0x6af, 0x6cc, 0x6af, 0x627, 0x628, 0x627, 0x6cc,
+0x62a, 0x3b, 0x62a, 0x631, 0x627, 0x628, 0x627, 0x6cc, 0x62a, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42
};
static const ushort am_data[] = {
0x41, 0x4d, 0x57, 0x44, 0x76, 0x6d, 0x2e, 0x65, 0x20, 0x70, 0x61, 0x72, 0x61, 0x64, 0x69, 0x74, 0x65, 0x73, 0x1325, 0x12cb,
-0x1275, 0x635, 0x9aa, 0x9c2, 0x9f0, 0x9cd, 0x9ac, 0x9be, 0x9b9, 0x9cd, 0x9a3, 0x410, 0x41c, 0xf66, 0xf94, 0xf0b, 0xf46, 0xf0b, 0x41, 0x2e,
+0x1275, 0x635, 0x9aa, 0x9c2, 0x9f0, 0x9cd, 0x9ac, 0x9be, 0x9b9, 0x9cd, 0x9a8, 0x410, 0x41c, 0xf66, 0xf94, 0xf0b, 0xf46, 0xf0b, 0x41, 0x2e,
0x4d, 0x2e, 0x43f, 0x440, 0x2e, 0x43e, 0x431, 0x2e, 0x1014, 0x1036, 0x1014, 0x1000, 0x103a, 0x61, 0x2e, 0x20, 0x6d, 0x2e, 0x4e0a, 0x5348,
-0x64, 0x6f, 0x70, 0x2e, 0x61, 0x2e, 0x6d, 0x2e, 0x61, 0x6d, 0x61, 0x70, 0x2e, 0x6d, 0x61, 0x74, 0x69, 0x6e, 0x6d, 0x76,
-0x6f, 0x72, 0x6d, 0x2e, 0x3c0, 0x2e, 0x3bc, 0x2e, 0x5dc, 0x5e4, 0x5e0, 0x5d4, 0x5f4, 0x5e6, 0x92a, 0x942, 0x930, 0x94d, 0x935, 0x93e,
-0x939, 0x94d, 0x928, 0x64, 0x65, 0x2e, 0x66, 0x2e, 0x68, 0x2e, 0x5348, 0x524d, 0xcaa, 0xcc2, 0xcb0, 0xccd, 0xcb5, 0xcbe, 0xcb9, 0xccd,
-0xca8, 0x442, 0x430, 0x4a3, 0x43a, 0x44b, 0xc624, 0xc804, 0x5a, 0x2e, 0x4d, 0x55, 0x2e, 0xe81, 0xec8, 0xead, 0xe99, 0xe97, 0xec8, 0xebd,
-0xe87, 0x70, 0x72, 0x69, 0x65, 0x6b, 0x161, 0x70, 0x75, 0x73, 0x64, 0x69, 0x65, 0x6e, 0x101, 0x6e, 0x74, 0x254, 0x301, 0x6e,
-0x67, 0x254, 0x301, 0x70, 0x72, 0x69, 0x65, 0x161, 0x70, 0x69, 0x65, 0x74, 0x43f, 0x440, 0x435, 0x442, 0x43f, 0x43b, 0x430, 0x434,
-0x43d, 0x435, 0x50, 0x47, 0x92e, 0x2e, 0x92a, 0x942, 0x2e, 0x4af, 0x2e, 0x4e9, 0x63a, 0x2e, 0x645, 0x2e, 0x642, 0x628, 0x644, 0x200c,
-0x627, 0x632, 0x638, 0x647, 0x631, 0x64, 0x61, 0x20, 0x6d, 0x61, 0x6e, 0x68, 0xe3, 0xa2a, 0xa42, 0x2e, 0xa26, 0xa41, 0x2e, 0x414,
-0x41f, 0x4e, 0x44, 0x43f, 0x440, 0x435, 0x20, 0x43f, 0x43e, 0x434, 0x43d, 0x435, 0x43f, 0x440, 0x438, 0x458, 0x435, 0x20, 0x43f, 0x43e,
-0x434, 0x43d, 0x435, 0x70, 0x72, 0x69, 0x6a, 0x65, 0x20, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x70, 0x72, 0x65, 0x20, 0x70, 0x6f,
-0x64, 0x6e, 0x65, 0x4d5, 0x43c, 0x431, 0x438, 0x441, 0x431, 0x43e, 0x43d, 0x44b, 0x20, 0x440, 0x430, 0x437, 0x43c, 0x4d5, 0xdb4, 0xdd9,
-0x2e, 0xdc0, 0x2e, 0x73, 0x6e, 0x2e, 0x41, 0x73, 0x75, 0x62, 0x75, 0x68, 0x69, 0x66, 0x6d, 0xbae, 0xbc1, 0xbb1, 0xbcd, 0xbaa,
-0xb95, 0xbb2, 0xbcd, 0xe01, 0xe48, 0xe2d, 0xe19, 0xe40, 0xe17, 0xe35, 0xe48, 0xe22, 0xe07, 0xf66, 0xf94, 0xf0b, 0xf51, 0xfb2, 0xf7c, 0xf0b,
-0x1295, 0x1309, 0x1206, 0x20, 0x1230, 0x12d3, 0x1270, 0x68, 0x65, 0x6e, 0x67, 0x69, 0x68, 0x65, 0x6e, 0x67, 0x69, 0xd6, 0xd6, 0x686,
-0x6c8, 0x634, 0x62a, 0x649, 0x646, 0x20, 0x628, 0x6c7, 0x631, 0x6c7, 0x646, 0x434, 0x43f, 0x54, 0x4f, 0x422, 0x41e, 0x53, 0x41, 0x79,
-0x62, 0xc0, 0xe1, 0x72, 0x1ecd, 0x300, 0xc0, 0xe1, 0x72, 0x254, 0x300, 0x66, 0x6f, 0x72, 0x6d, 0x69, 0x64, 0x64, 0x61, 0x67,
-0x70, 0x72, 0x69, 0x6a, 0x65, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x41, 0x4e, 0x128, 0x79, 0x61, 0x6b, 0x77, 0x61, 0x6b, 0x79,
-0x61, 0x61, 0x2e, 0x14b, 0x64, 0x69, 0x61, 0x6d, 0x20, 0x56, 0x6f, 0x72, 0x6d, 0x69, 0x74, 0x74, 0x61, 0x67, 0xa3b8, 0xa111,
-0x69, 0x111, 0x69, 0x74, 0x62, 0x65, 0x61, 0x69, 0x76, 0x65, 0x74, 0x4d, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x4c, 0x75, 0x6d,
-0x61, 0x20, 0x6c, 0x77, 0x61, 0x20, 0x4b, 0x73, 0x75, 0x62, 0x61, 0x6b, 0x61, 0x4b, 0x69, 0x72, 0x6f, 0x6b, 0x6f, 0x54,
-0x65, 0x73, 0x69, 0x72, 0x61, 0x6e, 0x6b, 0x61, 0x6e, 0x67, 0x2019, 0x61, 0x6d, 0x61, 0x2d5c, 0x2d49, 0x2d3c, 0x2d30, 0x2d61, 0x2d5c,
-0x74, 0x69, 0x66, 0x61, 0x77, 0x74, 0x6e, 0x20, 0x74, 0x75, 0x66, 0x61, 0x74, 0x70, 0x61, 0x6d, 0x69, 0x6c, 0x61, 0x75,
-0x75, 0x74, 0x75, 0x6b, 0x6f, 0x4b, 0x49, 0x13cc, 0x13be, 0x13b4, 0x4d, 0x75, 0x68, 0x69, 0x54, 0x4f, 0x4f, 0x75, 0x6c, 0x75,
-0x63, 0x68, 0x65, 0x6c, 0x6f, 0x52, 0x168, 0x6b, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x1c1, 0x67, 0x6f, 0x61, 0x67, 0x61, 0x73,
-0x55, 0x68, 0x72, 0x20, 0x76, 0xf6, 0x72, 0x6d, 0x69, 0x64, 0x64, 0x61, 0x61, 0x63, 0x68, 0x73, 0x190, 0x6e, 0x6b, 0x61,
-0x6b, 0x25b, 0x6e, 0x79, 0xe1, 0x4d, 0x75, 0x6e, 0x6b, 0x79, 0x6f, 0x69, 0x63, 0x68, 0x65, 0x68, 0x65, 0x61, 0x76, 0x6f,
-0x54, 0x61, 0x70, 0x61, 0x72, 0x61, 0x63, 0x68, 0x75, 0x41, 0x64, 0x64, 0x75, 0x68, 0x61, 0x4f, 0x44, 0x5a, 0x64, 0x61,
-0x74, 0x20, 0x61, 0x7a, 0x61, 0x6c, 0x6d, 0x61, 0x6b, 0x65, 0x6f, 0x92b, 0x941, 0x902, 0x44, 0x69, 0x6e, 0x64, 0x61, 0x6d,
-0x6f, 0x69, 0x65, 0x73, 0x61, 0x2e, 0x67, 0x49, 0x20, 0x62, 0x69, 0x6b, 0x25b, 0x302, 0x67, 0x6c, 0xe0, 0x53, 0x75, 0x62,
-0x62, 0x61, 0x61, 0x68, 0x69, 0x69, 0x64, 0x69, 0x253, 0x61, 0x6b, 0xed, 0x6b, 0xed, 0x72, 0xed, 0x67, 0x73, 0xe1, 0x72,
-0xfa, 0x77, 0xe1, 0x77, 0x69, 0x63, 0x68, 0x69, 0x73, 0x68, 0x75, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6d, 0x61, 0x6e, 0xe1,
-0x52, 0x57, 0x42d, 0x418, 0x4c, 0x77, 0x61, 0x6d, 0x69, 0x6c, 0x61, 0x77, 0x75, 0x6b, 0x69, 0x25b, 0x6d, 0x25b, 0x301, 0x25b,
-0x6d, 0x64, 0x65, 0x20, 0x6c, 0x61, 0x20, 0x6d, 0x61, 0xf1, 0x61, 0x6e, 0x61, 0x6d, 0x62, 0x61, 0xa78c, 0x6d, 0x62, 0x61,
-0xa78c, 0x6d, 0x62, 0x61, 0x2bc, 0xe1, 0x6d, 0x62, 0x61, 0x2bc, 0x628, 0x2e, 0x646, 0x64, 0x6f, 0x70, 0x6f, 0x142, 0x64, 0x6e,
-0x6a, 0x61, 0x69, 0x70, 0x2e
+0x64, 0x6f, 0x70, 0x2e, 0x61, 0x2e, 0x6d, 0x2e, 0x61, 0x6d, 0x61, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x6d, 0x61, 0x74, 0x69,
+0x6e, 0x6d, 0x3c0, 0x2e, 0x3bc, 0x2e, 0x5dc, 0x5e4, 0x5e0, 0x5d4, 0x5f4, 0x5e6, 0x92a, 0x942, 0x930, 0x94d, 0x935, 0x93e, 0x939, 0x94d,
+0x928, 0x64, 0x65, 0x2e, 0x66, 0x2e, 0x68, 0x2e, 0x72, 0x2e, 0x6e, 0x2e, 0x5348, 0x524d, 0x49, 0x73, 0x75, 0x6b, 0xcaa, 0xcc2,
+0xcb0, 0xccd, 0xcb5, 0xcbe, 0xcb9, 0xccd, 0xca8, 0x442, 0x430, 0x4a3, 0x43a, 0x44b, 0xc624, 0xc804, 0x5a, 0x2e, 0x4d, 0x55, 0x2e, 0xe81,
+0xec8, 0xead, 0xe99, 0xe97, 0xec8, 0xebd, 0xe87, 0x70, 0x72, 0x69, 0x65, 0x6b, 0x161, 0x70, 0x75, 0x73, 0x64, 0x69, 0x65, 0x6e,
+0x101, 0x6e, 0x74, 0x254, 0x301, 0x6e, 0x67, 0x254, 0x301, 0x70, 0x72, 0x69, 0x65, 0x161, 0x70, 0x69, 0x65, 0x74, 0x43f, 0x440,
+0x435, 0x442, 0x43f, 0x43b, 0x430, 0x434, 0x43d, 0x435, 0x50, 0x47, 0x92e, 0x2e, 0x92a, 0x942, 0x2e, 0x4af, 0x2e, 0x4e9, 0x2e, 0x63a,
+0x2e, 0x645, 0x2e, 0x642, 0x628, 0x644, 0x200c, 0x627, 0x632, 0x638, 0x647, 0x631, 0x64, 0x61, 0x20, 0x6d, 0x61, 0x6e, 0x68, 0xe3,
+0xa2a, 0xa42, 0x2e, 0xa26, 0xa41, 0x2e, 0x4e, 0x44, 0x43f, 0x440, 0x435, 0x20, 0x43f, 0x43e, 0x434, 0x43d, 0x435, 0x43f, 0x440, 0x438,
+0x458, 0x435, 0x20, 0x43f, 0x43e, 0x434, 0x43d, 0x435, 0x70, 0x72, 0x69, 0x6a, 0x65, 0x20, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x70,
+0x72, 0x65, 0x20, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x4d5, 0x43c, 0x431, 0x438, 0x441, 0x431, 0x43e, 0x43d, 0x44b, 0x20, 0x440, 0x430,
+0x437, 0x43c, 0x4d5, 0x635, 0x628, 0x62d, 0x60c, 0x20, 0x645, 0x646, 0x62c, 0x647, 0x646, 0x62f, 0xdb4, 0xdd9, 0x2e, 0xdc0, 0x2e, 0x73,
+0x6e, 0x2e, 0x66, 0x6d, 0x43f, 0x435, 0x2e, 0x20, 0x447, 0x43e, 0x2e, 0xbae, 0xbc1, 0xbb1, 0xbcd, 0xbaa, 0xb95, 0xbb2, 0xbcd, 0xe01,
+0xe48, 0xe2d, 0xe19, 0xe40, 0xe17, 0xe35, 0xe48, 0xe22, 0xe07, 0xf66, 0xf94, 0xf0b, 0xf51, 0xfb2, 0xf7c, 0xf0b, 0x1295, 0x1309, 0x1206, 0x20,
+0x1230, 0x12d3, 0x1270, 0x68, 0x65, 0x6e, 0x67, 0x69, 0x68, 0x65, 0x6e, 0x67, 0x69, 0xd6, 0xd6, 0x67, 0xfc, 0x6e, 0x6f, 0x72,
+0x74, 0x61, 0x64, 0x61, 0x6e, 0x20, 0xf6, 0x148, 0x686, 0x6c8, 0x634, 0x62a, 0x649, 0x646, 0x20, 0x628, 0x6c7, 0x631, 0x6c7, 0x646,
+0x434, 0x43f, 0x54, 0x4f, 0x422, 0x41e, 0x53, 0x41, 0x79, 0x62, 0x53, 0x75, 0x62, 0x5e4, 0x5bf, 0x5d0, 0x5b7, 0x5e8, 0x5de, 0x5d9,
+0x5d8, 0x5d0, 0x5b8, 0x5d2, 0xc0, 0xe1, 0x72, 0x1ecd, 0x300, 0xc0, 0xe1, 0x72, 0x254, 0x300, 0x66, 0x6f, 0x72, 0x6d, 0x69, 0x64,
+0x64, 0x61, 0x67, 0x70, 0x72, 0x69, 0x6a, 0x65, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x41, 0x4e, 0x128, 0x79, 0x61, 0x6b, 0x77,
+0x61, 0x6b, 0x79, 0x61, 0x61, 0x2e, 0x14b, 0x64, 0x69, 0x61, 0x6d, 0x20, 0x56, 0x6f, 0x72, 0x6d, 0x69, 0x74, 0x74, 0x61,
+0x67, 0xa3b8, 0xa111, 0x69, 0x111, 0x69, 0x74, 0x62, 0x65, 0x61, 0x69, 0x76, 0x65, 0x74, 0x69, 0x62, 0x4d, 0x61, 0x6d, 0x62,
+0x69, 0x61, 0x4c, 0x75, 0x6d, 0x61, 0x20, 0x6c, 0x77, 0x61, 0x20, 0x4b, 0x73, 0x75, 0x62, 0x61, 0x6b, 0x61, 0x4b, 0x69,
+0x72, 0x6f, 0x6b, 0x6f, 0x54, 0x65, 0x73, 0x69, 0x72, 0x61, 0x6e, 0x6b, 0x61, 0x6e, 0x67, 0x2019, 0x61, 0x6d, 0x61, 0x2d5c,
+0x2d49, 0x2d3c, 0x2d30, 0x2d61, 0x2d5c, 0x74, 0x69, 0x66, 0x61, 0x77, 0x74, 0x6e, 0x20, 0x74, 0x75, 0x66, 0x61, 0x74, 0x70, 0x61,
+0x6d, 0x69, 0x6c, 0x61, 0x75, 0x75, 0x74, 0x75, 0x6b, 0x6f, 0x4b, 0x49, 0x13cc, 0x13be, 0x13b4, 0x4d, 0x75, 0x68, 0x69, 0x54,
+0x4f, 0x4f, 0x75, 0x6c, 0x75, 0x63, 0x68, 0x65, 0x6c, 0x6f, 0x52, 0x168, 0x6b, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x1c1, 0x67,
+0x6f, 0x61, 0x67, 0x61, 0x73, 0x55, 0x68, 0x72, 0x20, 0x76, 0xf6, 0x72, 0x6d, 0x69, 0x64, 0x64, 0x61, 0x61, 0x63, 0x68,
+0x73, 0x190, 0x6e, 0x6b, 0x61, 0x6b, 0x25b, 0x6e, 0x79, 0xe1, 0x4d, 0x75, 0x6e, 0x6b, 0x79, 0x6f, 0x69, 0x63, 0x68, 0x65,
+0x68, 0x65, 0x61, 0x76, 0x6f, 0x54, 0x61, 0x70, 0x61, 0x72, 0x61, 0x63, 0x68, 0x75, 0x41, 0x64, 0x64, 0x75, 0x68, 0x61,
+0x4f, 0x44, 0x5a, 0x64, 0x61, 0x74, 0x20, 0x61, 0x7a, 0x61, 0x6c, 0x6d, 0x61, 0x6b, 0x65, 0x6f, 0x92b, 0x941, 0x902, 0x44,
+0x69, 0x6e, 0x64, 0x61, 0x6d, 0x6f, 0x69, 0x65, 0x73, 0x61, 0x2e, 0x67, 0x49, 0x20, 0x62, 0x69, 0x6b, 0x25b, 0x302, 0x67,
+0x6c, 0xe0, 0x53, 0x75, 0x62, 0x62, 0x61, 0x61, 0x68, 0x69, 0x69, 0x64, 0x69, 0x253, 0x61, 0x6b, 0xed, 0x6b, 0xed, 0x72,
+0xed, 0x67, 0x73, 0xe1, 0x72, 0xfa, 0x77, 0xe1, 0x77, 0x69, 0x63, 0x68, 0x69, 0x73, 0x68, 0x75, 0x63, 0x6f, 0x6d, 0x6d,
+0x65, 0x6d, 0x61, 0x6e, 0xe1, 0x52, 0x57, 0x42d, 0x418, 0x4c, 0x77, 0x61, 0x6d, 0x69, 0x6c, 0x61, 0x77, 0x75, 0x6b, 0x69,
+0x25b, 0x6d, 0x25b, 0x301, 0x25b, 0x6d, 0x64, 0x65, 0x20, 0x6c, 0x61, 0x20, 0x6d, 0x61, 0xf1, 0x61, 0x6e, 0x61, 0x6d, 0x62,
+0x61, 0xa78c, 0x6d, 0x62, 0x61, 0xa78c, 0x6d, 0x62, 0x61, 0x2bc, 0xe1, 0x6d, 0x62, 0x61, 0x2bc, 0x628, 0x2e, 0x646, 0x64, 0x6f,
+0x70, 0x6f, 0x142, 0x64, 0x6e, 0x6a, 0x61, 0x69, 0x70, 0x2e
};
static const ushort pm_data[] = {
0x50, 0x4d, 0x57, 0x42, 0x6e, 0x6d, 0x2e, 0x65, 0x20, 0x70, 0x61, 0x73, 0x64, 0x69, 0x74, 0x65, 0x73, 0x12a8, 0x1230, 0x12d3,
-0x1275, 0x645, 0x985, 0x9aa, 0x9f0, 0x9be, 0x9b9, 0x9cd, 0x9a3, 0x41f, 0x41c, 0xf55, 0xfb1, 0xf72, 0xf0b, 0xf46, 0xf0b, 0x47, 0x2e, 0x4d,
+0x1275, 0x645, 0x985, 0x9aa, 0x9f0, 0x9be, 0x9b9, 0x9cd, 0x9a8, 0x41f, 0x41c, 0xf55, 0xfb1, 0xf72, 0xf0b, 0xf46, 0xf0b, 0x47, 0x2e, 0x4d,
0x2e, 0x441, 0x43b, 0x2e, 0x43e, 0x431, 0x2e, 0x100a, 0x1014, 0x1031, 0x70, 0x2e, 0x20, 0x6d, 0x2e, 0x4e0b, 0x5348, 0x6f, 0x64, 0x70,
-0x2e, 0x70, 0x2e, 0x6d, 0x2e, 0x70, 0x6d, 0x69, 0x70, 0x2e, 0x73, 0x6f, 0x69, 0x72, 0x66, 0x6e, 0x61, 0x63, 0x68, 0x6d,
-0x2e, 0x3bc, 0x2e, 0x3bc, 0x2e, 0x5d0, 0x5d7, 0x5d4, 0x5f4, 0x5e6, 0x905, 0x92a, 0x930, 0x93e, 0x939, 0x94d, 0x928, 0x64, 0x75, 0x2e,
-0x65, 0x2e, 0x68, 0x2e, 0x5348, 0x5f8c, 0xc85, 0xcaa, 0xcb0, 0xcbe, 0xcb9, 0xccd, 0xca8, 0x442, 0x4af, 0x448, 0x442, 0x4e9, 0x43d, 0x20,
-0x43a, 0x438, 0x439, 0x438, 0x43d, 0x43a, 0x438, 0xc624, 0xd6c4, 0x5a, 0x2e, 0x4d, 0x57, 0x2e, 0xeab, 0xebc, 0xeb1, 0xe87, 0xe97, 0xec8,
-0xebd, 0xe87, 0x70, 0x113, 0x63, 0x70, 0x75, 0x73, 0x64, 0x69, 0x65, 0x6e, 0x101, 0x6d, 0x70, 0xf3, 0x6b, 0x77, 0x61, 0x70,
-0x6f, 0x70, 0x69, 0x65, 0x74, 0x43f, 0x43e, 0x43f, 0x43b, 0x430, 0x434, 0x43d, 0x435, 0x50, 0x54, 0x47, 0x92e, 0x2e, 0x909, 0x2e,
-0x4af, 0x2e, 0x445, 0x63a, 0x2e, 0x648, 0x2e, 0x628, 0x639, 0x62f, 0x627, 0x632, 0x638, 0x647, 0x631, 0x64, 0x61, 0x20, 0x74, 0x61,
-0x72, 0x64, 0x65, 0xa2c, 0xa3e, 0x2e, 0xa26, 0xa41, 0x2e, 0x41f, 0x41f, 0x4c, 0x4b, 0x43f, 0x43e, 0x20, 0x43f, 0x43e, 0x434, 0x43d,
-0x435, 0x70, 0x6f, 0x20, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x4d5, 0x43c, 0x431, 0x438, 0x441, 0x431, 0x43e, 0x43d, 0x44b, 0x20, 0x444,
-0x4d5, 0x441, 0x442, 0x4d5, 0xdb4, 0x2e, 0xdc0, 0x2e, 0x70, 0x6f, 0x70, 0x2e, 0x67, 0x6e, 0x2e, 0x4d, 0x63, 0x68, 0x61, 0x6e,
-0x61, 0x65, 0x6d, 0xbaa, 0xbbf, 0xbb1, 0xbcd, 0xbaa, 0xb95, 0xbb2, 0xbcd, 0xe2b, 0xe25, 0xe31, 0xe07, 0xe40, 0xe17, 0xe35, 0xe48, 0xe22,
-0xe07, 0xf55, 0xfb1, 0xf72, 0xf0b, 0xf51, 0xfb2, 0xf7c, 0xf0b, 0x12f5, 0x1215, 0x122d, 0x20, 0x1230, 0x12d3, 0x1275, 0x65, 0x66, 0x69, 0x61,
-0x66, 0x69, 0xd6, 0x53, 0x686, 0x6c8, 0x634, 0x62a, 0x649, 0x646, 0x20, 0x643, 0x6d0, 0x64a, 0x649, 0x646, 0x43f, 0x43f, 0x54, 0x4b,
-0x422, 0x41a, 0x43, 0x48, 0x79, 0x68, 0x1ecc, 0x300, 0x73, 0xe1, 0x6e, 0x186, 0x300, 0x73, 0xe1, 0x6e, 0x65, 0x74, 0x74, 0x65,
-0x72, 0x6d, 0x69, 0x64, 0x64, 0x61, 0x67, 0x70, 0x6f, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x43f, 0x43e, 0x43f, 0x43e, 0x434, 0x43d,
-0x435, 0x45, 0x57, 0x92e, 0x2e, 0x928, 0x902, 0x2e, 0x50, 0x2e, 0x4d, 0x2e, 0x128, 0x79, 0x61, 0x77, 0x129, 0x6f, 0x6f, 0x70,
-0x2e, 0x263, 0x65, 0x74, 0x72, 0x254, 0x61, 0x6d, 0x20, 0x4e, 0x61, 0x6d, 0x69, 0x74, 0x74, 0x61, 0x67, 0xa06f, 0xa2d2, 0x65,
-0x61, 0x68, 0x6b, 0x65, 0x74, 0x62, 0x65, 0x61, 0x69, 0x76, 0x65, 0x74, 0x4d, 0x6f, 0x67, 0x6c, 0x75, 0x6d, 0x61, 0x20,
-0x6c, 0x77, 0x61, 0x20, 0x70, 0x6b, 0x69, 0x6b, 0x69, 0x69, 0x257, 0x65, 0x48, 0x77, 0x61, 0x129, 0x2d, 0x69, 0x6e, 0x129,
-0x54, 0x65, 0x69, 0x70, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x6f, 0x74, 0x6f, 0x2d5c, 0x2d30, 0x2d37, 0x2d33, 0x2d33, 0x2d6f, 0x2d30, 0x2d5c,
-0x74, 0x61, 0x64, 0x67, 0x67, 0x2b7, 0x61, 0x74, 0x6e, 0x20, 0x74, 0x6d, 0x65, 0x64, 0x64, 0x69, 0x74, 0x70, 0x61, 0x6d,
-0x75, 0x6e, 0x79, 0x69, 0x6b, 0x79, 0x69, 0x75, 0x6b, 0x6f, 0x6e, 0x79, 0x69, 0x55, 0x54, 0x13d2, 0x13af, 0x13f1, 0x13a2, 0x13d7,
-0x13e2, 0x43, 0x68, 0x69, 0x6c, 0x6f, 0x4d, 0x55, 0x55, 0x61, 0x6b, 0x61, 0x73, 0x75, 0x62, 0x61, 0x168, 0x47, 0x6b, 0x6f,
-0x6f, 0x73, 0x6b, 0x6f, 0x6c, 0x69, 0x6e, 0x79, 0x1c3, 0x75, 0x69, 0x61, 0x73, 0x55, 0x68, 0x72, 0x20, 0x6e, 0x6f, 0x6d,
-0x6d, 0x65, 0x6e, 0x64, 0x61, 0x61, 0x63, 0x68, 0x73, 0x190, 0x6e, 0x64, 0xe1, 0x6d, 0xe2, 0x45, 0x69, 0x67, 0x75, 0x6c,
-0x6f, 0x69, 0x63, 0x68, 0x61, 0x6d, 0x74, 0x68, 0x69, 0x45, 0x62, 0x6f, 0x6e, 0x67, 0x69, 0x41, 0x6c, 0x75, 0x75, 0x6c,
-0x61, 0x4f, 0x54, 0x1e0c, 0x65, 0x66, 0x66, 0x69, 0x72, 0x20, 0x61, 0x7a, 0x61, 0x6e, 0x79, 0x69, 0x61, 0x67, 0x68, 0x75,
-0x6f, 0x92c, 0x947, 0x932, 0x93e, 0x938, 0x947, 0x44, 0x69, 0x6c, 0x6f, 0x6c, 0x6f, 0x6e, 0x6f, 0x6d, 0xeb, 0x74, 0x74, 0x65,
-0x73, 0x61, 0x2e, 0x6b, 0x49, 0x20, 0x253, 0x75, 0x67, 0x61, 0x6a, 0x254, 0x70, 0x5a, 0x61, 0x61, 0x72, 0x69, 0x6b, 0x61,
-0x79, 0x20, 0x62, 0x65, 0x62, 0x79, 0xe1, 0x6d, 0x75, 0x6e, 0x67, 0x259, 0x67, 0xf3, 0x67, 0x259, 0x6c, 0x65, 0x63, 0x25b,
-0x25b, 0x301, 0x6e, 0x6b, 0x6f, 0x6d, 0x63, 0x68, 0x6f, 0x63, 0x68, 0x69, 0x6c, 0x2019, 0x6c, 0x6c, 0x69, 0x6c, 0x6c, 0x69,
-0x6b, 0x75, 0x67, 0xfa, 0x54, 0x14a, 0x42d, 0x41a, 0x50, 0x61, 0x73, 0x68, 0x61, 0x6d, 0x69, 0x68, 0x65, 0x6b, 0x69, 0x73,
-0x25b, 0x301, 0x6e, 0x64, 0x25b, 0x64, 0x65, 0x20, 0x6c, 0x61, 0x20, 0x74, 0x61, 0x72, 0x64, 0x65, 0x14b, 0x6b, 0x61, 0x20,
-0x6d, 0x62, 0x254, 0x301, 0x74, 0x20, 0x6e, 0x6a, 0x69, 0x6e, 0x63, 0x77, 0xf2, 0x6e, 0x7a, 0xe9, 0x6d, 0x62f, 0x2e, 0x646,
-0x77, 0xf3, 0x74, 0x70, 0x6f, 0x142, 0x64, 0x6e, 0x6a, 0x61, 0x70, 0x6f, 0x70, 0x6f, 0x142, 0x64, 0x6e, 0x6a, 0x75, 0x65,
-0x70, 0x2e
+0x2e, 0x70, 0x2e, 0x6d, 0x2e, 0x70, 0x6d, 0x70, 0x74, 0x6d, 0x69, 0x70, 0x2e, 0x73, 0x6f, 0x69, 0x72, 0x66, 0x3bc, 0x2e,
+0x3bc, 0x2e, 0x5d0, 0x5d7, 0x5d4, 0x5f4, 0x5e6, 0x905, 0x92a, 0x930, 0x93e, 0x939, 0x94d, 0x928, 0x64, 0x75, 0x2e, 0x65, 0x2e, 0x68,
+0x2e, 0x69, 0x2e, 0x6e, 0x2e, 0x5348, 0x5f8c, 0x57, 0x65, 0x6e, 0x67, 0x69, 0xc85, 0xcaa, 0xcb0, 0xcbe, 0xcb9, 0xccd, 0xca8, 0x442,
+0x4af, 0x448, 0x442, 0x4e9, 0x43d, 0x20, 0x43a, 0x438, 0x439, 0x438, 0x43d, 0x43a, 0x438, 0xc624, 0xd6c4, 0x5a, 0x2e, 0x4d, 0x57, 0x2e,
+0xeab, 0xebc, 0xeb1, 0xe87, 0xe97, 0xec8, 0xebd, 0xe87, 0x70, 0x113, 0x63, 0x70, 0x75, 0x73, 0x64, 0x69, 0x65, 0x6e, 0x101, 0x6d,
+0x70, 0xf3, 0x6b, 0x77, 0x61, 0x70, 0x6f, 0x70, 0x69, 0x65, 0x74, 0x43f, 0x43e, 0x43f, 0x43b, 0x430, 0x434, 0x43d, 0x435, 0x50,
+0x54, 0x47, 0x92e, 0x2e, 0x909, 0x2e, 0x4af, 0x2e, 0x445, 0x2e, 0x63a, 0x2e, 0x648, 0x2e, 0x628, 0x639, 0x62f, 0x627, 0x632, 0x638,
+0x647, 0x631, 0x64, 0x61, 0x20, 0x74, 0x61, 0x72, 0x64, 0x65, 0xa2c, 0xa3e, 0x2e, 0xa26, 0xa41, 0x2e, 0x4c, 0x4b, 0x43f, 0x43e,
+0x20, 0x43f, 0x43e, 0x434, 0x43d, 0x435, 0x70, 0x6f, 0x20, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x4d5, 0x43c, 0x431, 0x438, 0x441, 0x431,
+0x43e, 0x43d, 0x44b, 0x20, 0x444, 0x4d5, 0x441, 0x442, 0x4d5, 0x645, 0x646, 0x62c, 0x647, 0x646, 0x62f, 0x60c, 0x20, 0x634, 0x627, 0x645,
+0xdb4, 0x2e, 0xdc0, 0x2e, 0x70, 0x6f, 0x70, 0x2e, 0x67, 0x6e, 0x2e, 0x65, 0x6d, 0x43f, 0x430, 0x2e, 0x20, 0x447, 0x43e, 0x2e,
+0xbaa, 0xbbf, 0xbb1, 0xbcd, 0xbaa, 0xb95, 0xbb2, 0xbcd, 0xe2b, 0xe25, 0xe31, 0xe07, 0xe40, 0xe17, 0xe35, 0xe48, 0xe22, 0xe07, 0xf55, 0xfb1,
+0xf72, 0xf0b, 0xf51, 0xfb2, 0xf7c, 0xf0b, 0x12f5, 0x1215, 0x122d, 0x20, 0x1230, 0x12d3, 0x1275, 0x65, 0x66, 0x69, 0x61, 0x66, 0x69, 0xd6,
+0x53, 0x67, 0xfc, 0x6e, 0x6f, 0x72, 0x74, 0x61, 0x64, 0x61, 0x6e, 0x20, 0x73, 0x6f, 0x148, 0x686, 0x6c8, 0x634, 0x62a, 0x649,
+0x646, 0x20, 0x643, 0x6d0, 0x64a, 0x649, 0x646, 0x43f, 0x43f, 0x54, 0x4b, 0x422, 0x41a, 0x43, 0x48, 0x79, 0x68, 0x4e, 0x67, 0x6f,
+0x5e0, 0x5d0, 0x5b8, 0x5db, 0x5de, 0x5d9, 0x5d8, 0x5d0, 0x5b8, 0x5d2, 0x1ecc, 0x300, 0x73, 0xe1, 0x6e, 0x186, 0x300, 0x73, 0xe1, 0x6e,
+0x65, 0x74, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x64, 0x64, 0x61, 0x67, 0x70, 0x6f, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x43f, 0x43e,
+0x43f, 0x43e, 0x434, 0x43d, 0x435, 0x45, 0x57, 0x92e, 0x2e, 0x928, 0x902, 0x2e, 0x50, 0x2e, 0x4d, 0x2e, 0x128, 0x79, 0x61, 0x77,
+0x129, 0x6f, 0x6f, 0x70, 0x2e, 0x263, 0x65, 0x74, 0x72, 0x254, 0x61, 0x6d, 0x20, 0x4e, 0x61, 0x6d, 0x69, 0x74, 0x74, 0x61,
+0x67, 0xa06f, 0xa2d2, 0x65, 0x61, 0x68, 0x6b, 0x65, 0x74, 0x62, 0x65, 0x61, 0x69, 0x76, 0x65, 0x74, 0x65, 0x62, 0x4d, 0x6f,
+0x67, 0x6c, 0x75, 0x6d, 0x61, 0x20, 0x6c, 0x77, 0x61, 0x20, 0x70, 0x6b, 0x69, 0x6b, 0x69, 0x69, 0x257, 0x65, 0x48, 0x77,
+0x61, 0x129, 0x2d, 0x69, 0x6e, 0x129, 0x54, 0x65, 0x69, 0x70, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x6f, 0x74, 0x6f, 0x2d5c, 0x2d30,
+0x2d37, 0x2d33, 0x2d33, 0x2d6f, 0x2d30, 0x2d5c, 0x74, 0x61, 0x64, 0x67, 0x67, 0x2b7, 0x61, 0x74, 0x6e, 0x20, 0x74, 0x6d, 0x65, 0x64,
+0x64, 0x69, 0x74, 0x70, 0x61, 0x6d, 0x75, 0x6e, 0x79, 0x69, 0x6b, 0x79, 0x69, 0x75, 0x6b, 0x6f, 0x6e, 0x79, 0x69, 0x55,
+0x54, 0x13d2, 0x13af, 0x13f1, 0x13a2, 0x13d7, 0x13e2, 0x43, 0x68, 0x69, 0x6c, 0x6f, 0x4d, 0x55, 0x55, 0x61, 0x6b, 0x61, 0x73, 0x75,
+0x62, 0x61, 0x168, 0x47, 0x6b, 0x6f, 0x6f, 0x73, 0x6b, 0x6f, 0x6c, 0x69, 0x6e, 0x79, 0x1c3, 0x75, 0x69, 0x61, 0x73, 0x55,
+0x68, 0x72, 0x20, 0x6e, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x61, 0x61, 0x63, 0x68, 0x73, 0x190, 0x6e, 0x64, 0xe1, 0x6d,
+0xe2, 0x45, 0x69, 0x67, 0x75, 0x6c, 0x6f, 0x69, 0x63, 0x68, 0x61, 0x6d, 0x74, 0x68, 0x69, 0x45, 0x62, 0x6f, 0x6e, 0x67,
+0x69, 0x41, 0x6c, 0x75, 0x75, 0x6c, 0x61, 0x4f, 0x54, 0x1e0c, 0x65, 0x66, 0x66, 0x69, 0x72, 0x20, 0x61, 0x7a, 0x61, 0x6e,
+0x79, 0x69, 0x61, 0x67, 0x68, 0x75, 0x6f, 0x92c, 0x947, 0x932, 0x93e, 0x938, 0x947, 0x44, 0x69, 0x6c, 0x6f, 0x6c, 0x6f, 0x6e,
+0x6f, 0x6d, 0xeb, 0x74, 0x74, 0x65, 0x73, 0x61, 0x2e, 0x6b, 0x49, 0x20, 0x253, 0x75, 0x67, 0x61, 0x6a, 0x254, 0x70, 0x5a,
+0x61, 0x61, 0x72, 0x69, 0x6b, 0x61, 0x79, 0x20, 0x62, 0x65, 0x62, 0x79, 0xe1, 0x6d, 0x75, 0x6e, 0x67, 0x259, 0x67, 0xf3,
+0x67, 0x259, 0x6c, 0x65, 0x63, 0x25b, 0x25b, 0x301, 0x6e, 0x6b, 0x6f, 0x6d, 0x63, 0x68, 0x6f, 0x63, 0x68, 0x69, 0x6c, 0x2019,
+0x6c, 0x6c, 0x69, 0x6c, 0x6c, 0x69, 0x6b, 0x75, 0x67, 0xfa, 0x54, 0x14a, 0x42d, 0x41a, 0x50, 0x61, 0x73, 0x68, 0x61, 0x6d,
+0x69, 0x68, 0x65, 0x6b, 0x69, 0x73, 0x25b, 0x301, 0x6e, 0x64, 0x25b, 0x64, 0x65, 0x20, 0x6c, 0x61, 0x20, 0x74, 0x61, 0x72,
+0x64, 0x65, 0x14b, 0x6b, 0x61, 0x20, 0x6d, 0x62, 0x254, 0x301, 0x74, 0x20, 0x6e, 0x6a, 0x69, 0x6e, 0x63, 0x77, 0xf2, 0x6e,
+0x7a, 0xe9, 0x6d, 0x62f, 0x2e, 0x646, 0x77, 0xf3, 0x74, 0x70, 0x6f, 0x142, 0x64, 0x6e, 0x6a, 0x61, 0x70, 0x6f, 0x70, 0x6f,
+0x142, 0x64, 0x6e, 0x6a, 0x75, 0x65, 0x70, 0x2e
};
static const ushort currency_symbol_data[] = {
0x42, 0x72, 0x4b, 0x73, 0x68, 0x52, 0x24, 0x4c, 0x65, 0x6b, 0xeb, 0x64, 0x65, 0x6e, 0x20ac, 0x1265, 0x122d, 0x62c, 0x2e, 0x645,
-0x2e, 0x200f, 0x62f, 0x2e, 0x62c, 0x2e, 0x200f, 0x62f, 0x2e, 0x628, 0x2e, 0x200f, 0x46, 0x43, 0x46, 0x41, 0x641, 0x2e, 0x62c, 0x2e,
-0x642, 0x2e, 0x200f, 0x46, 0x64, 0x6a, 0x4e, 0x66, 0x6b, 0x62f, 0x2e, 0x639, 0x2e, 0x200f, 0x20aa, 0x62f, 0x2e, 0x623, 0x2e, 0x200f,
-0x62f, 0x2e, 0x643, 0x2e, 0x200f, 0x644, 0x2e, 0x644, 0x2e, 0x200f, 0x62f, 0x2e, 0x644, 0x2e, 0x200f, 0x623, 0x2e, 0x645, 0x2e, 0x200f,
-0x62f, 0x2e, 0x645, 0x2e, 0x200f, 0x631, 0x2e, 0x639, 0x2e, 0x200f, 0x631, 0x2e, 0x642, 0x2e, 0x200f, 0x631, 0x2e, 0x633, 0x2e, 0x200f,
-0x53, 0x62c, 0x2e, 0x633, 0x2e, 0x644, 0x2e, 0x633, 0x2e, 0x200f, 0x62f, 0x2e, 0x62a, 0x2e, 0x200f, 0x62f, 0x2e, 0x625, 0x2e, 0x200f,
-0x631, 0x2e, 0x64a, 0x2e, 0x200f, 0xa3, 0x58f, 0x20b9, 0x20bc, 0x20bd, 0x9f3, 0x4e, 0x75, 0x2e, 0x43b, 0x432, 0x2e, 0x4b, 0x17db, 0xffe5,
-0x48, 0x4b, 0x24, 0x4d, 0x4f, 0x50, 0x24, 0x48, 0x52, 0x4b, 0x4b, 0x4d, 0x4b, 0x10d, 0x6b, 0x72, 0x2e, 0x41, 0x66, 0x6c,
-0x2e, 0x4e, 0x41, 0x66, 0x2e, 0x55, 0x53, 0x24, 0x50, 0x46, 0x42, 0x75, 0x44, 0x47, 0x48, 0x20b5, 0x41, 0x72, 0x4d, 0x4b,
-0x52, 0x4d, 0x52, 0x73, 0x20a6, 0x20b1, 0x52, 0x46, 0x57, 0x53, 0x24, 0x53, 0x52, 0x4c, 0x65, 0x45, 0x6b, 0x72, 0x54, 0x53,
-0x68, 0x54, 0x24, 0x55, 0x53, 0x68, 0x56, 0x54, 0x44, 0x41, 0x43, 0x46, 0x41, 0x43, 0x46, 0x46, 0x43, 0x46, 0x43, 0x46,
-0x50, 0x46, 0x47, 0x47, 0x55, 0x4d, 0x4d, 0x41, 0x44, 0x43, 0x48, 0x46, 0x4c, 0x53, 0x44, 0x54, 0x20be, 0x20b2, 0x46, 0x74,
-0x49, 0x53, 0x4b, 0x52, 0x70, 0x43, 0x41, 0x24, 0x20b8, 0x441, 0x43e, 0x43c, 0x20a9, 0x4b, 0x50, 0x57, 0x20ba, 0x20ad, 0x4b, 0x7a,
-0x434, 0x435, 0x43d, 0x4e, 0x5a, 0x24, 0x20ae, 0x43, 0x4e, 0xa5, 0x928, 0x947, 0x930, 0x942, 0x60b, 0x631, 0x6cc, 0x627, 0x644, 0x7a,
-0x142, 0x52, 0x24, 0x200b, 0x4d, 0x54, 0x6e, 0x44, 0x62, 0x631, 0x53, 0x2f, 0x42, 0x73, 0x52, 0x4f, 0x4e, 0x4c, 0x20b4, 0x52,
-0x53, 0x44, 0x41a, 0x41c, 0xdbb, 0xdd4, 0x2e, 0x20a1, 0x52, 0x44, 0x24, 0x51, 0x43, 0x24, 0x42, 0x2f, 0x2e, 0x47, 0x73, 0x2e,
-0x42, 0x73, 0x2e, 0x52, 0x73, 0x2e, 0x54, 0x48, 0x42, 0xa5, 0x54, 0x4d, 0x54, 0x73, 0x6f, 0x2bb, 0x6d, 0x441, 0x45e, 0x43c,
-0x20ab, 0x4e, 0x54, 0x24, 0x41, 0x24, 0x49, 0x52, 0x52
+0x2e, 0x200f, 0x62f, 0x2e, 0x62c, 0x2e, 0x200f, 0x62f, 0x2e, 0x628, 0x2e, 0x200f, 0x46, 0x43, 0x46, 0x41, 0x43, 0x46, 0x46, 0x64,
+0x6a, 0x4e, 0x66, 0x6b, 0x62f, 0x2e, 0x639, 0x2e, 0x200f, 0x20aa, 0x62f, 0x2e, 0x623, 0x2e, 0x200f, 0x62f, 0x2e, 0x643, 0x2e, 0x200f,
+0x644, 0x2e, 0x644, 0x2e, 0x200f, 0x62f, 0x2e, 0x644, 0x2e, 0x200f, 0x623, 0x2e, 0x645, 0x2e, 0x62f, 0x2e, 0x645, 0x2e, 0x200f, 0x631,
+0x2e, 0x639, 0x2e, 0x200f, 0x631, 0x2e, 0x642, 0x2e, 0x200f, 0x631, 0x2e, 0x633, 0x2e, 0x200f, 0x53, 0x62c, 0x2e, 0x633, 0x2e, 0x644,
+0x2e, 0x633, 0x2e, 0x200f, 0x62f, 0x2e, 0x62a, 0x2e, 0x200f, 0x62f, 0x2e, 0x625, 0x2e, 0x200f, 0x631, 0x2e, 0x64a, 0x2e, 0x200f, 0xa3,
+0x58f, 0x20b9, 0x20bc, 0x20bd, 0x9f3, 0x4e, 0x75, 0x2e, 0x43b, 0x432, 0x2e, 0x4b, 0x17db, 0xffe5, 0x48, 0x4b, 0x24, 0x4d, 0x4f, 0x50,
+0x24, 0x48, 0x52, 0x4b, 0x4b, 0x4d, 0x4b, 0x10d, 0x6b, 0x72, 0x2e, 0x41, 0x66, 0x6c, 0x2e, 0x4e, 0x41, 0x66, 0x2e, 0x55,
+0x53, 0x24, 0x50, 0x46, 0x42, 0x75, 0x44, 0x47, 0x48, 0x20b5, 0x41, 0x72, 0x4d, 0x4b, 0x52, 0x4d, 0x52, 0x73, 0x20a6, 0x20b1,
+0x52, 0x46, 0x57, 0x53, 0x24, 0x53, 0x52, 0x4c, 0x65, 0x45, 0x6b, 0x72, 0x54, 0x53, 0x68, 0x54, 0x24, 0x55, 0x53, 0x68,
+0x56, 0x54, 0x44, 0x41, 0x43, 0x46, 0x41, 0x46, 0x43, 0x46, 0x43, 0x46, 0x50, 0x46, 0x47, 0x47, 0x55, 0x4d, 0x4d, 0x41,
+0x44, 0x43, 0x48, 0x46, 0x4c, 0x53, 0x44, 0x54, 0x20be, 0x20b2, 0x46, 0x74, 0x49, 0x53, 0x4b, 0x52, 0x70, 0x43, 0x41, 0x24,
+0x20b8, 0x441, 0x43e, 0x43c, 0x20a9, 0x4b, 0x50, 0x57, 0x20ba, 0x20ad, 0x4b, 0x7a, 0x434, 0x435, 0x43d, 0x20ae, 0x43, 0x4e, 0xa5, 0x928,
+0x947, 0x930, 0x942, 0x60b, 0x631, 0x6cc, 0x627, 0x644, 0x7a, 0x142, 0x52, 0x24, 0x200b, 0x4d, 0x54, 0x6e, 0x44, 0x62, 0x631, 0x53,
+0x2f, 0x42, 0x73, 0x52, 0x4f, 0x4e, 0x4c, 0x20b4, 0x52, 0x53, 0x44, 0x41a, 0x41c, 0xdbb, 0xdd4, 0x2e, 0x20a1, 0x52, 0x44, 0x24,
+0x51, 0x43, 0x24, 0x42, 0x2f, 0x2e, 0x47, 0x73, 0x2e, 0x42, 0x73, 0x2e, 0x53, 0x441, 0x43e, 0x43c, 0x2e, 0x52, 0x73, 0x2e,
+0xe3f, 0xa5, 0x54, 0x4d, 0x54, 0x73, 0x6f, 0x2bb, 0x6d, 0x441, 0x45e, 0x43c, 0x20ab, 0x4e, 0x54, 0x24, 0x41, 0x24, 0x49, 0x52,
+0x52
};
static const ushort currency_display_name_data[] = {
@@ -5124,726 +5364,753 @@ static const ushort currency_display_name_data[] = {
0x627, 0x644, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x627, 0x62a, 0x20, 0x62c, 0x646, 0x648, 0x628, 0x20,
0x627, 0x644, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x64b, 0x627, 0x20, 0x62c, 0x646, 0x648, 0x628, 0x20,
0x627, 0x644, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x62c, 0x646, 0x648, 0x628, 0x20, 0x627, 0x644,
-0x633, 0x648, 0x62f, 0x627, 0x646, 0x3b, 0x540, 0x561, 0x575, 0x56f, 0x561, 0x56f, 0x561, 0x576, 0x20, 0x564, 0x580, 0x561, 0x574, 0x3b,
+0x633, 0x648, 0x62f, 0x627, 0x646, 0x3b, 0x570, 0x561, 0x575, 0x56f, 0x561, 0x56f, 0x561, 0x576, 0x20, 0x564, 0x580, 0x561, 0x574, 0x3b,
0x3b, 0x570, 0x561, 0x575, 0x56f, 0x561, 0x56f, 0x561, 0x576, 0x20, 0x564, 0x580, 0x561, 0x574, 0x3b, 0x3b, 0x3b, 0x3b, 0x570, 0x561,
-0x575, 0x56f, 0x561, 0x56f, 0x561, 0x576, 0x20, 0x564, 0x580, 0x561, 0x574, 0x3b, 0x41, 0x7a, 0x259, 0x72, 0x62, 0x61, 0x79, 0x63,
-0x61, 0x6e, 0x20, 0x4d, 0x61, 0x6e, 0x61, 0x74, 0x131, 0x3b, 0x3b, 0x41, 0x7a, 0x259, 0x72, 0x62, 0x61, 0x79, 0x63, 0x61,
-0x6e, 0x20, 0x6d, 0x61, 0x6e, 0x61, 0x74, 0x131, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x7a, 0x259, 0x72, 0x62, 0x61, 0x79, 0x63,
-0x61, 0x6e, 0x20, 0x6d, 0x61, 0x6e, 0x61, 0x74, 0x131, 0x3b, 0x43c, 0x430, 0x43d, 0x430, 0x442, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x61, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72,
-0x6f, 0x3b, 0x9ac, 0x9be, 0x982, 0x9b2, 0x9be, 0x9a6, 0x9c7, 0x9b6, 0x9c0, 0x20, 0x99f, 0x9be, 0x995, 0x9be, 0x3b, 0x3b, 0x9ac, 0x9be,
-0x982, 0x9b2, 0x9be, 0x9a6, 0x9c7, 0x9b6, 0x9c0, 0x20, 0x99f, 0x9be, 0x995, 0x9be, 0x3b, 0x3b, 0x3b, 0x3b, 0x9ac, 0x9be, 0x982, 0x9b2,
-0x9be, 0x9a6, 0x9c7, 0x9b6, 0x9c0, 0x20, 0x99f, 0x9be, 0x995, 0x9be, 0x3b, 0x9ad, 0x9be, 0x9b0, 0x9a4, 0x9c0, 0x9af, 0x9bc, 0x20, 0x9b0,
-0x9c1, 0x9aa, 0x9bf, 0x3b, 0x3b, 0x9ad, 0x9be, 0x9b0, 0x9a4, 0x9c0, 0x9af, 0x9bc, 0x20, 0x9b0, 0x9c1, 0x9aa, 0x9bf, 0x3b, 0x3b, 0x3b,
-0x3b, 0x9ad, 0x9be, 0x9b0, 0x9a4, 0x9c0, 0x9af, 0x9bc, 0x20, 0x9b0, 0x9c1, 0x9aa, 0x9bf, 0x3b, 0xf51, 0xf44, 0xf74, 0xf63, 0xf0b, 0xf40,
-0xfb2, 0xf58, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b,
-0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x61, 0x20, 0x65, 0x75, 0x72, 0x6f, 0x69, 0x6f, 0xf9, 0x3b,
-0x65, 0x75, 0x72, 0x6f, 0x3b, 0x411, 0x44a, 0x43b, 0x433, 0x430, 0x440, 0x441, 0x43a, 0x438, 0x20, 0x43b, 0x435, 0x432, 0x3b, 0x3b,
-0x431, 0x44a, 0x43b, 0x433, 0x430, 0x440, 0x441, 0x43a, 0x438, 0x20, 0x43b, 0x435, 0x432, 0x3b, 0x3b, 0x3b, 0x3b, 0x431, 0x44a, 0x43b,
-0x433, 0x430, 0x440, 0x441, 0x43a, 0x438, 0x20, 0x43b, 0x435, 0x432, 0x430, 0x3b, 0x1019, 0x103c, 0x1014, 0x103a, 0x1019, 0x102c, 0x1000, 0x103b,
-0x1015, 0x103a, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x1019, 0x103c, 0x1014, 0x103a, 0x1019, 0x102c, 0x1000, 0x103b, 0x1015, 0x103a, 0x3b, 0x431,
-0x435, 0x43b, 0x430, 0x440, 0x443, 0x441, 0x43a, 0x456, 0x20, 0x440, 0x443, 0x431, 0x435, 0x43b, 0x44c, 0x3b, 0x3b, 0x431, 0x435, 0x43b,
-0x430, 0x440, 0x443, 0x441, 0x43a, 0x456, 0x20, 0x440, 0x443, 0x431, 0x435, 0x43b, 0x44c, 0x3b, 0x3b, 0x431, 0x435, 0x43b, 0x430, 0x440,
-0x443, 0x441, 0x43a, 0x456, 0x44f, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x456, 0x3b, 0x431, 0x435, 0x43b, 0x430, 0x440, 0x443, 0x441, 0x43a,
-0x456, 0x445, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x451, 0x45e, 0x3b, 0x431, 0x435, 0x43b, 0x430, 0x440, 0x443, 0x441, 0x43a, 0x430, 0x433,
-0x430, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44f, 0x3b, 0x179a, 0x17c0, 0x179b, 0x200b, 0x1780, 0x1798, 0x17d2, 0x1796, 0x17bb, 0x1787, 0x17b6, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x179a, 0x17c0, 0x179b, 0x200b, 0x1780, 0x1798, 0x17d2, 0x1796, 0x17bb, 0x1787, 0x17b6, 0x3b, 0x65, 0x75, 0x72,
-0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x73, 0x3b, 0x4eba, 0x6c11, 0x5e01,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4eba, 0x6c11, 0x5e01, 0x3b, 0x6e2f, 0x5143, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x6e2f, 0x5143,
-0x3b, 0x6fb3, 0x95e8, 0x5e01, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x6fb3, 0x95e8, 0x5143, 0x3b, 0x65b0, 0x52a0, 0x5761, 0x5143, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x65b0, 0x52a0, 0x5761, 0x5143, 0x3b, 0x6fb3, 0x9580, 0x5143, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x6fb3, 0x9580,
-0x5143, 0x3b, 0x65b0, 0x53f0, 0x5e63, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x65b0, 0x53f0, 0x5e63, 0x3b, 0x68, 0x72, 0x76, 0x61, 0x74,
-0x73, 0x6b, 0x61, 0x20, 0x6b, 0x75, 0x6e, 0x61, 0x3b, 0x3b, 0x68, 0x72, 0x76, 0x61, 0x74, 0x73, 0x6b, 0x61, 0x20, 0x6b,
-0x75, 0x6e, 0x61, 0x3b, 0x3b, 0x68, 0x72, 0x76, 0x61, 0x74, 0x73, 0x6b, 0x65, 0x20, 0x6b, 0x75, 0x6e, 0x65, 0x3b, 0x3b,
-0x68, 0x72, 0x76, 0x61, 0x74, 0x73, 0x6b, 0x69, 0x68, 0x20, 0x6b, 0x75, 0x6e, 0x61, 0x3b, 0x6b, 0x6f, 0x6e, 0x76, 0x65,
-0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x3b, 0x3b, 0x6b, 0x6f, 0x6e, 0x76,
-0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x3b, 0x3b, 0x6b, 0x6f, 0x6e,
-0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x3b, 0x3b, 0x6b, 0x6f,
-0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x69, 0x68, 0x20, 0x6d, 0x61, 0x72, 0x61, 0x6b, 0x61, 0x3b,
-0x10d, 0x65, 0x73, 0x6b, 0xe1, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x6e, 0x61, 0x3b, 0x3b, 0x10d, 0x65, 0x73, 0x6b, 0xe1, 0x20,
-0x6b, 0x6f, 0x72, 0x75, 0x6e, 0x61, 0x3b, 0x3b, 0x10d, 0x65, 0x73, 0x6b, 0xe9, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x6e, 0x79,
-0x3b, 0x10d, 0x65, 0x73, 0x6b, 0xe9, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x6e, 0x79, 0x3b, 0x10d, 0x65, 0x73, 0x6b, 0xfd, 0x63,
-0x68, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x6e, 0x3b, 0x64, 0x61, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x3b,
-0x3b, 0x64, 0x61, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x61, 0x6e, 0x73,
-0x6b, 0x65, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x72, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f,
-0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x41, 0x72, 0x75, 0x62, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x67,
-0x75, 0x6c, 0x64, 0x65, 0x6e, 0x3b, 0x3b, 0x41, 0x72, 0x75, 0x62, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x67, 0x75, 0x6c,
-0x64, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x72, 0x75, 0x62, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x67, 0x75, 0x6c,
-0x64, 0x65, 0x6e, 0x3b, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x2d, 0x41, 0x6e, 0x74, 0x69, 0x6c,
-0x6c, 0x69, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x67, 0x75, 0x6c, 0x64, 0x65, 0x6e, 0x3b, 0x3b, 0x4e, 0x65, 0x64, 0x65,
-0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x2d, 0x41, 0x6e, 0x74, 0x69, 0x6c, 0x6c, 0x69, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20,
-0x67, 0x75, 0x6c, 0x64, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73,
-0x2d, 0x41, 0x6e, 0x74, 0x69, 0x6c, 0x6c, 0x69, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x67, 0x75, 0x6c, 0x64, 0x65, 0x6e,
-0x3b, 0x53, 0x75, 0x72, 0x69, 0x6e, 0x61, 0x61, 0x6d, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b,
-0x53, 0x75, 0x72, 0x69, 0x6e, 0x61, 0x61, 0x6d, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b,
-0x3b, 0x53, 0x75, 0x72, 0x69, 0x6e, 0x61, 0x61, 0x6d, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x41,
-0x6d, 0x65, 0x72, 0x69, 0x6b, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x41,
-0x6d, 0x65, 0x72, 0x69, 0x6b, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b,
-0x3b, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x6b, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b,
-0x55, 0x53, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x55, 0x53, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
-0x3b, 0x3b, 0x3b, 0x3b, 0x55, 0x53, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x45, 0x61, 0x73, 0x74, 0x20,
-0x43, 0x61, 0x72, 0x69, 0x62, 0x62, 0x65, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x45, 0x61,
-0x73, 0x74, 0x20, 0x43, 0x61, 0x72, 0x69, 0x62, 0x62, 0x65, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b,
-0x3b, 0x3b, 0x3b, 0x45, 0x61, 0x73, 0x74, 0x20, 0x43, 0x61, 0x72, 0x69, 0x62, 0x62, 0x65, 0x61, 0x6e, 0x20, 0x64, 0x6f,
-0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c,
-0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c,
-0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c,
-0x6c, 0x61, 0x72, 0x73, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65,
-0x75, 0x72, 0x6f, 0x73, 0x3b, 0x42, 0x61, 0x68, 0x61, 0x6d, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
-0x3b, 0x3b, 0x42, 0x61, 0x68, 0x61, 0x6d, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b,
-0x3b, 0x42, 0x61, 0x68, 0x61, 0x6d, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x42, 0x61,
-0x72, 0x62, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x42, 0x61, 0x72, 0x62,
-0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x61, 0x72, 0x62,
-0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65,
-0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c,
-0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73,
-0x3b, 0x42, 0x65, 0x72, 0x6d, 0x75, 0x64, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x42, 0x65,
-0x72, 0x6d, 0x75, 0x64, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x65, 0x72,
-0x6d, 0x75, 0x64, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x42, 0x6f, 0x74, 0x73, 0x77, 0x61,
-0x6e, 0x61, 0x6e, 0x20, 0x50, 0x75, 0x6c, 0x61, 0x3b, 0x3b, 0x42, 0x6f, 0x74, 0x73, 0x77, 0x61, 0x6e, 0x61, 0x6e, 0x20,
-0x70, 0x75, 0x6c, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x6f, 0x74, 0x73, 0x77, 0x61, 0x6e, 0x61, 0x6e, 0x20, 0x70, 0x75,
-0x6c, 0x61, 0x73, 0x3b, 0x42, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x3b,
-0x3b, 0x42, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x3b, 0x3b,
-0x42, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x3b, 0x43, 0x65, 0x6e,
-0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x43, 0x46, 0x41, 0x20, 0x46, 0x72, 0x61,
-0x6e, 0x63, 0x3b, 0x3b, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20,
-0x43, 0x46, 0x41, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x3b, 0x3b, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c,
-0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x43, 0x46, 0x41, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x3b,
-0x43, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x43, 0x61, 0x6e,
-0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x43, 0x61, 0x6e, 0x61,
-0x64, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x43, 0x61, 0x79, 0x6d, 0x61, 0x6e, 0x20,
-0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x43, 0x61, 0x79, 0x6d,
-0x61, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b,
+0x575, 0x56f, 0x561, 0x56f, 0x561, 0x576, 0x20, 0x564, 0x580, 0x561, 0x574, 0x3b, 0x9ad, 0x9be, 0x9f0, 0x9a4, 0x9c0, 0x9af, 0x9bc, 0x20,
+0x9f0, 0x9c1, 0x9aa, 0x9c0, 0x3b, 0x3b, 0x9ad, 0x9be, 0x9f0, 0x9a4, 0x9c0, 0x9af, 0x9bc, 0x20, 0x9f0, 0x9c1, 0x9aa, 0x9c0, 0x3b, 0x3b,
+0x3b, 0x3b, 0x9ad, 0x9be, 0x9f0, 0x9a4, 0x9c0, 0x9af, 0x9bc, 0x20, 0x9f0, 0x9c1, 0x9aa, 0x9c0, 0x3b, 0x41, 0x7a, 0x259, 0x72, 0x62,
+0x61, 0x79, 0x63, 0x61, 0x6e, 0x20, 0x4d, 0x61, 0x6e, 0x61, 0x74, 0x131, 0x3b, 0x3b, 0x41, 0x7a, 0x259, 0x72, 0x62, 0x61,
+0x79, 0x63, 0x61, 0x6e, 0x20, 0x6d, 0x61, 0x6e, 0x61, 0x74, 0x131, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x7a, 0x259, 0x72, 0x62,
+0x61, 0x79, 0x63, 0x61, 0x6e, 0x20, 0x6d, 0x61, 0x6e, 0x61, 0x74, 0x131, 0x3b, 0x43c, 0x430, 0x43d, 0x430, 0x442, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x61, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b,
+0x65, 0x75, 0x72, 0x6f, 0x3b, 0x9ac, 0x9be, 0x982, 0x9b2, 0x9be, 0x9a6, 0x9c7, 0x9b6, 0x9c0, 0x20, 0x99f, 0x9be, 0x995, 0x9be, 0x3b,
+0x3b, 0x9ac, 0x9be, 0x982, 0x9b2, 0x9be, 0x9a6, 0x9c7, 0x9b6, 0x9c0, 0x20, 0x99f, 0x9be, 0x995, 0x9be, 0x3b, 0x3b, 0x3b, 0x3b, 0x9ac,
+0x9be, 0x982, 0x9b2, 0x9be, 0x9a6, 0x9c7, 0x9b6, 0x9c0, 0x20, 0x99f, 0x9be, 0x995, 0x9be, 0x3b, 0x9ad, 0x9be, 0x9b0, 0x9a4, 0x9c0, 0x9af,
+0x9bc, 0x20, 0x9b0, 0x9c1, 0x9aa, 0x9bf, 0x3b, 0x3b, 0x9ad, 0x9be, 0x9b0, 0x9a4, 0x9c0, 0x9af, 0x9bc, 0x20, 0x9b0, 0x9c1, 0x9aa, 0x9bf,
+0x3b, 0x3b, 0x3b, 0x3b, 0x9ad, 0x9be, 0x9b0, 0x9a4, 0x9c0, 0x9af, 0x9bc, 0x20, 0x9b0, 0x9c1, 0x9aa, 0x9bf, 0x3b, 0xf51, 0xf44, 0xf74,
+0xf63, 0xf0b, 0xf40, 0xfb2, 0xf58, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75,
+0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x61, 0x20, 0x65, 0x75, 0x72, 0x6f, 0x69,
+0x6f, 0xf9, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x411, 0x44a, 0x43b, 0x433, 0x430, 0x440, 0x441, 0x43a, 0x438, 0x20, 0x43b, 0x435,
+0x432, 0x3b, 0x3b, 0x431, 0x44a, 0x43b, 0x433, 0x430, 0x440, 0x441, 0x43a, 0x438, 0x20, 0x43b, 0x435, 0x432, 0x3b, 0x3b, 0x3b, 0x3b,
+0x431, 0x44a, 0x43b, 0x433, 0x430, 0x440, 0x441, 0x43a, 0x438, 0x20, 0x43b, 0x435, 0x432, 0x430, 0x3b, 0x1019, 0x103c, 0x1014, 0x103a, 0x1019,
+0x102c, 0x20, 0x1000, 0x103b, 0x1015, 0x103a, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x1019, 0x103c, 0x1014, 0x103a, 0x1019, 0x102c, 0x20, 0x1000,
+0x103b, 0x1015, 0x103a, 0x3b, 0x431, 0x435, 0x43b, 0x430, 0x440, 0x443, 0x441, 0x43a, 0x456, 0x20, 0x440, 0x443, 0x431, 0x435, 0x43b, 0x44c,
+0x3b, 0x3b, 0x431, 0x435, 0x43b, 0x430, 0x440, 0x443, 0x441, 0x43a, 0x456, 0x20, 0x440, 0x443, 0x431, 0x435, 0x43b, 0x44c, 0x3b, 0x3b,
+0x431, 0x435, 0x43b, 0x430, 0x440, 0x443, 0x441, 0x43a, 0x456, 0x44f, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x456, 0x3b, 0x431, 0x435, 0x43b,
+0x430, 0x440, 0x443, 0x441, 0x43a, 0x456, 0x445, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x451, 0x45e, 0x3b, 0x431, 0x435, 0x43b, 0x430, 0x440,
+0x443, 0x441, 0x43a, 0x430, 0x433, 0x430, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44f, 0x3b, 0x179a, 0x17c0, 0x179b, 0x200b, 0x1780, 0x1798, 0x17d2,
+0x1796, 0x17bb, 0x1787, 0x17b6, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x179a, 0x17c0, 0x179b, 0x200b, 0x1780, 0x1798, 0x17d2, 0x1796, 0x17bb, 0x1787,
+0x17b6, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f,
+0x73, 0x3b, 0x4eba, 0x6c11, 0x5e01, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4eba, 0x6c11, 0x5e01, 0x3b, 0x6e2f, 0x5143, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x6e2f, 0x5143, 0x3b, 0x6fb3, 0x95e8, 0x5e01, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x6fb3, 0x95e8, 0x5143, 0x3b, 0x65b0,
+0x52a0, 0x5761, 0x5143, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x65b0, 0x52a0, 0x5761, 0x5143, 0x3b, 0x6fb3, 0x9580, 0x5143, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x6fb3, 0x9580, 0x5143, 0x3b, 0x65b0, 0x53f0, 0x5e63, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x65b0, 0x53f0, 0x5e63, 0x3b,
+0x68, 0x72, 0x76, 0x61, 0x74, 0x73, 0x6b, 0x61, 0x20, 0x6b, 0x75, 0x6e, 0x61, 0x3b, 0x3b, 0x68, 0x72, 0x76, 0x61, 0x74,
+0x73, 0x6b, 0x61, 0x20, 0x6b, 0x75, 0x6e, 0x61, 0x3b, 0x3b, 0x68, 0x72, 0x76, 0x61, 0x74, 0x73, 0x6b, 0x65, 0x20, 0x6b,
+0x75, 0x6e, 0x65, 0x3b, 0x3b, 0x68, 0x72, 0x76, 0x61, 0x74, 0x73, 0x6b, 0x69, 0x68, 0x20, 0x6b, 0x75, 0x6e, 0x61, 0x3b,
+0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x3b,
+0x3b, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61,
+0x3b, 0x3b, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x6b,
+0x65, 0x3b, 0x3b, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x69, 0x68, 0x20, 0x6d, 0x61,
+0x72, 0x61, 0x6b, 0x61, 0x3b, 0x10d, 0x65, 0x73, 0x6b, 0xe1, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x6e, 0x61, 0x3b, 0x3b, 0x10d,
+0x65, 0x73, 0x6b, 0xe1, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x6e, 0x61, 0x3b, 0x3b, 0x10d, 0x65, 0x73, 0x6b, 0xe9, 0x20, 0x6b,
+0x6f, 0x72, 0x75, 0x6e, 0x79, 0x3b, 0x10d, 0x65, 0x73, 0x6b, 0xe9, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x6e, 0x79, 0x3b, 0x10d,
+0x65, 0x73, 0x6b, 0xfd, 0x63, 0x68, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x6e, 0x3b, 0x64, 0x61, 0x6e, 0x73, 0x6b, 0x20, 0x6b,
+0x72, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x64, 0x61, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x3b,
+0x3b, 0x64, 0x61, 0x6e, 0x73, 0x6b, 0x65, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x72, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b,
+0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x41, 0x72, 0x75, 0x62, 0x61, 0x61,
+0x6e, 0x73, 0x65, 0x20, 0x67, 0x75, 0x6c, 0x64, 0x65, 0x6e, 0x3b, 0x3b, 0x41, 0x72, 0x75, 0x62, 0x61, 0x61, 0x6e, 0x73,
+0x65, 0x20, 0x67, 0x75, 0x6c, 0x64, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x72, 0x75, 0x62, 0x61, 0x61, 0x6e, 0x73,
+0x65, 0x20, 0x67, 0x75, 0x6c, 0x64, 0x65, 0x6e, 0x3b, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x2d,
+0x41, 0x6e, 0x74, 0x69, 0x6c, 0x6c, 0x69, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x67, 0x75, 0x6c, 0x64, 0x65, 0x6e, 0x3b,
+0x3b, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x2d, 0x41, 0x6e, 0x74, 0x69, 0x6c, 0x6c, 0x69, 0x61,
+0x61, 0x6e, 0x73, 0x65, 0x20, 0x67, 0x75, 0x6c, 0x64, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x65, 0x64, 0x65, 0x72,
+0x6c, 0x61, 0x6e, 0x64, 0x73, 0x2d, 0x41, 0x6e, 0x74, 0x69, 0x6c, 0x6c, 0x69, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x67,
+0x75, 0x6c, 0x64, 0x65, 0x6e, 0x3b, 0x53, 0x75, 0x72, 0x69, 0x6e, 0x61, 0x61, 0x6d, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c,
+0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x53, 0x75, 0x72, 0x69, 0x6e, 0x61, 0x61, 0x6d, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c,
+0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x75, 0x72, 0x69, 0x6e, 0x61, 0x61, 0x6d, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c,
+0x6c, 0x61, 0x72, 0x3b, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x6b, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c,
+0x61, 0x72, 0x3b, 0x3b, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x6b, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c,
+0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x6b, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x6f,
+0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x55, 0x53, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x55, 0x53, 0x20, 0x64,
+0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x55, 0x53, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b,
+0x45, 0x61, 0x73, 0x74, 0x20, 0x43, 0x61, 0x72, 0x69, 0x62, 0x62, 0x65, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61,
+0x72, 0x3b, 0x3b, 0x45, 0x61, 0x73, 0x74, 0x20, 0x43, 0x61, 0x72, 0x69, 0x62, 0x62, 0x65, 0x61, 0x6e, 0x20, 0x64, 0x6f,
+0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x61, 0x73, 0x74, 0x20, 0x43, 0x61, 0x72, 0x69, 0x62, 0x62, 0x65,
+0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
+0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x6e,
+0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
+0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f,
+0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x73, 0x3b, 0x42, 0x61, 0x68, 0x61, 0x6d, 0x69, 0x61, 0x6e, 0x20, 0x44,
+0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x42, 0x61, 0x68, 0x61, 0x6d, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c,
+0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x61, 0x68, 0x61, 0x6d, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61,
+0x72, 0x73, 0x3b, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b,
+0x3b, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b,
+0x3b, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x42,
+0x65, 0x6c, 0x69, 0x7a, 0x65, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65,
+0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65, 0x20, 0x64, 0x6f,
+0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x42, 0x65, 0x72, 0x6d, 0x75, 0x64, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61,
+0x72, 0x3b, 0x3b, 0x42, 0x65, 0x72, 0x6d, 0x75, 0x64, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b,
+0x3b, 0x3b, 0x42, 0x65, 0x72, 0x6d, 0x75, 0x64, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x42,
+0x6f, 0x74, 0x73, 0x77, 0x61, 0x6e, 0x61, 0x6e, 0x20, 0x50, 0x75, 0x6c, 0x61, 0x3b, 0x3b, 0x42, 0x6f, 0x74, 0x73, 0x77,
+0x61, 0x6e, 0x61, 0x6e, 0x20, 0x70, 0x75, 0x6c, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x6f, 0x74, 0x73, 0x77, 0x61, 0x6e,
+0x61, 0x6e, 0x20, 0x70, 0x75, 0x6c, 0x61, 0x73, 0x3b, 0x42, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x46,
+0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x42, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x66, 0x72, 0x61, 0x6e,
+0x63, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63,
+0x73, 0x3b, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x43, 0x46,
+0x41, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x66, 0x72,
+0x69, 0x63, 0x61, 0x6e, 0x20, 0x43, 0x46, 0x41, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x3b, 0x3b, 0x43, 0x65,
+0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x43, 0x46, 0x41, 0x20, 0x66, 0x72,
+0x61, 0x6e, 0x63, 0x73, 0x3b, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
+0x3b, 0x3b, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b,
+0x3b, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x43, 0x61,
+0x79, 0x6d, 0x61, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b,
0x3b, 0x43, 0x61, 0x79, 0x6d, 0x61, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x64, 0x6f, 0x6c, 0x6c,
-0x61, 0x72, 0x73, 0x3b, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x44, 0x6f, 0x6c, 0x6c,
-0x61, 0x72, 0x3b, 0x3b, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x6f, 0x6c, 0x6c,
-0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x6f,
-0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x44, 0x61, 0x6e, 0x69, 0x73, 0x68, 0x20, 0x4b, 0x72, 0x6f, 0x6e, 0x65, 0x3b, 0x3b,
-0x44, 0x61, 0x6e, 0x69, 0x73, 0x68, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x61, 0x6e, 0x69,
-0x73, 0x68, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x72, 0x3b, 0x45, 0x72, 0x69, 0x74, 0x72, 0x65, 0x61, 0x6e, 0x20, 0x4e,
-0x61, 0x6b, 0x66, 0x61, 0x3b, 0x3b, 0x45, 0x72, 0x69, 0x74, 0x72, 0x65, 0x61, 0x6e, 0x20, 0x6e, 0x61, 0x6b, 0x66, 0x61,
-0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x72, 0x69, 0x74, 0x72, 0x65, 0x61, 0x6e, 0x20, 0x6e, 0x61, 0x6b, 0x66, 0x61, 0x73, 0x3b,
-0x46, 0x61, 0x6c, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x50, 0x6f, 0x75,
-0x6e, 0x64, 0x3b, 0x3b, 0x46, 0x61, 0x6c, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73,
-0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x61, 0x6c, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x49,
-0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x3b, 0x46, 0x69, 0x6a, 0x69, 0x61, 0x6e,
-0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x46, 0x69, 0x6a, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c,
-0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x69, 0x6a, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73,
-0x3b, 0x55, 0x4b, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x55, 0x4b, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3b,
-0x3b, 0x3b, 0x3b, 0x55, 0x4b, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x3b, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e,
-0x20, 0x44, 0x61, 0x6c, 0x61, 0x73, 0x69, 0x3b, 0x3b, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x61, 0x6c,
-0x61, 0x73, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x61, 0x6c, 0x61, 0x73,
-0x69, 0x73, 0x3b, 0x47, 0x68, 0x61, 0x6e, 0x61, 0x69, 0x61, 0x6e, 0x20, 0x43, 0x65, 0x64, 0x69, 0x3b, 0x3b, 0x47, 0x68,
-0x61, 0x6e, 0x61, 0x69, 0x61, 0x6e, 0x20, 0x63, 0x65, 0x64, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x47, 0x68, 0x61, 0x6e, 0x61,
-0x69, 0x61, 0x6e, 0x20, 0x63, 0x65, 0x64, 0x69, 0x73, 0x3b, 0x47, 0x69, 0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x20,
-0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x47, 0x69, 0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x20, 0x70, 0x6f, 0x75,
-0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x47, 0x69, 0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x20, 0x70, 0x6f, 0x75, 0x6e,
-0x64, 0x73, 0x3b, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x65, 0x73, 0x65, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b,
-0x3b, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x65, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b,
-0x3b, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x65, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x48,
-0x6f, 0x6e, 0x67, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x48, 0x6f, 0x6e,
-0x67, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x48, 0x6f, 0x6e,
-0x67, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x49, 0x6e, 0x64, 0x69, 0x61,
-0x6e, 0x20, 0x52, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x75, 0x70, 0x65,
-0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x73, 0x3b, 0x49,
-0x73, 0x72, 0x61, 0x65, 0x6c, 0x69, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x53, 0x68, 0x65, 0x6b, 0x65, 0x6c, 0x3b, 0x3b, 0x49,
-0x73, 0x72, 0x61, 0x65, 0x6c, 0x69, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x73, 0x68, 0x65, 0x6b, 0x65, 0x6c, 0x3b, 0x3b, 0x3b,
-0x3b, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x69, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x73, 0x68, 0x65, 0x6b, 0x65, 0x6c, 0x73,
-0x3b, 0x4a, 0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x4a, 0x61,
-0x6d, 0x61, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x4a, 0x61, 0x6d,
-0x61, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x6e,
-0x20, 0x53, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x6e, 0x20, 0x73, 0x68,
-0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x3b, 0x3b, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x6e, 0x20, 0x73, 0x68, 0x69,
-0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x3b, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e,
-0x20, 0x52, 0x61, 0x6e, 0x64, 0x3b, 0x3b, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e,
-0x20, 0x72, 0x61, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63,
-0x61, 0x6e, 0x20, 0x72, 0x61, 0x6e, 0x64, 0x3b, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c,
-0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
-0x3b, 0x3b, 0x3b, 0x3b, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73,
-0x3b, 0x4d, 0x61, 0x63, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x50, 0x61, 0x74, 0x61, 0x63, 0x61, 0x3b, 0x3b, 0x4d, 0x61,
-0x63, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x70, 0x61, 0x74, 0x61, 0x63, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x61, 0x63,
-0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x70, 0x61, 0x74, 0x61, 0x63, 0x61, 0x73, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x67, 0x61,
-0x73, 0x79, 0x20, 0x41, 0x72, 0x69, 0x61, 0x72, 0x79, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x67, 0x61, 0x73, 0x79, 0x20,
-0x61, 0x72, 0x69, 0x61, 0x72, 0x79, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x67, 0x61, 0x73, 0x79, 0x20, 0x61,
-0x72, 0x69, 0x61, 0x72, 0x69, 0x65, 0x73, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x77, 0x69, 0x61, 0x6e, 0x20, 0x4b, 0x77, 0x61,
-0x63, 0x68, 0x61, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x77, 0x69, 0x61, 0x6e, 0x20, 0x6b, 0x77, 0x61, 0x63, 0x68, 0x61,
-0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x77, 0x69, 0x61, 0x6e, 0x20, 0x6b, 0x77, 0x61, 0x63, 0x68, 0x61, 0x73,
-0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x52, 0x69, 0x6e, 0x67, 0x67, 0x69, 0x74, 0x3b, 0x3b,
-0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x69, 0x6e, 0x67, 0x67, 0x69, 0x74, 0x3b, 0x3b, 0x3b,
-0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x69, 0x6e, 0x67, 0x67, 0x69, 0x74, 0x73, 0x3b,
-0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x61, 0x6e, 0x20, 0x52, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x4d, 0x61, 0x75,
-0x72, 0x69, 0x74, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x61, 0x75, 0x72,
-0x69, 0x74, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x73, 0x3b, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61,
-0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x64,
-0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f,
-0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x4e, 0x61, 0x69, 0x72, 0x61,
-0x3b, 0x3b, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x6e, 0x61, 0x69, 0x72, 0x61, 0x3b, 0x3b, 0x3b, 0x3b,
-0x4e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x6e, 0x61, 0x69, 0x72, 0x61, 0x73, 0x3b, 0x50, 0x61, 0x6b, 0x69,
-0x73, 0x74, 0x61, 0x6e, 0x69, 0x20, 0x52, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x50, 0x61, 0x6b, 0x69, 0x73, 0x74, 0x61,
-0x6e, 0x69, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x50, 0x61, 0x6b, 0x69, 0x73, 0x74, 0x61, 0x6e,
-0x69, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x73, 0x3b, 0x50, 0x61, 0x70, 0x75, 0x61, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x47,
-0x75, 0x69, 0x6e, 0x65, 0x61, 0x6e, 0x20, 0x4b, 0x69, 0x6e, 0x61, 0x3b, 0x3b, 0x50, 0x61, 0x70, 0x75, 0x61, 0x20, 0x4e,
-0x65, 0x77, 0x20, 0x47, 0x75, 0x69, 0x6e, 0x65, 0x61, 0x6e, 0x20, 0x6b, 0x69, 0x6e, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x50,
-0x61, 0x70, 0x75, 0x61, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x47, 0x75, 0x69, 0x6e, 0x65, 0x61, 0x6e, 0x20, 0x6b, 0x69, 0x6e,
-0x61, 0x3b, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x20, 0x50, 0x65, 0x73, 0x6f, 0x3b, 0x3b, 0x50,
-0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x20, 0x70, 0x65, 0x73, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x50, 0x68,
-0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x20, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x3b, 0x52, 0x77, 0x61, 0x6e, 0x64,
-0x61, 0x6e, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x52, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x6e, 0x20, 0x66, 0x72,
-0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x3b, 0x3b, 0x52, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x6e, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63,
-0x73, 0x3b, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x6e, 0x20, 0x54, 0x61, 0x6c, 0x61, 0x3b, 0x3b, 0x53, 0x61, 0x6d, 0x6f, 0x61,
-0x6e, 0x20, 0x74, 0x61, 0x6c, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x6e, 0x20, 0x74, 0x61, 0x6c,
-0x61, 0x3b, 0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x69, 0x73, 0x20, 0x52, 0x75, 0x70, 0x65, 0x65, 0x3b,
-0x3b, 0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x69, 0x73, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b,
-0x3b, 0x3b, 0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x69, 0x73, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x73,
-0x3b, 0x53, 0x69, 0x65, 0x72, 0x72, 0x61, 0x20, 0x4c, 0x65, 0x6f, 0x6e, 0x65, 0x61, 0x6e, 0x20, 0x4c, 0x65, 0x6f, 0x6e,
-0x65, 0x3b, 0x3b, 0x53, 0x69, 0x65, 0x72, 0x72, 0x61, 0x20, 0x4c, 0x65, 0x6f, 0x6e, 0x65, 0x61, 0x6e, 0x20, 0x6c, 0x65,
-0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x69, 0x65, 0x72, 0x72, 0x61, 0x20, 0x4c, 0x65, 0x6f, 0x6e, 0x65, 0x61,
-0x6e, 0x20, 0x6c, 0x65, 0x6f, 0x6e, 0x65, 0x73, 0x3b, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x20, 0x44,
-0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x20, 0x64, 0x6f, 0x6c,
-0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x20, 0x64, 0x6f, 0x6c,
-0x6c, 0x61, 0x72, 0x73, 0x3b, 0x53, 0x6f, 0x6c, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73,
-0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x53, 0x6f, 0x6c, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x49, 0x73, 0x6c,
-0x61, 0x6e, 0x64, 0x73, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x6f, 0x6c, 0x6f, 0x6d,
-0x6f, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x53,
-0x74, 0x2e, 0x20, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x53, 0x74, 0x2e,
-0x20, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x74, 0x2e,
-0x20, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x3b, 0x53, 0x75, 0x64, 0x61, 0x6e,
-0x65, 0x73, 0x65, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20,
-0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x70, 0x6f,
-0x75, 0x6e, 0x64, 0x73, 0x3b, 0x53, 0x77, 0x61, 0x7a, 0x69, 0x20, 0x4c, 0x69, 0x6c, 0x61, 0x6e, 0x67, 0x65, 0x6e, 0x69,
-0x3b, 0x3b, 0x53, 0x77, 0x61, 0x7a, 0x69, 0x20, 0x6c, 0x69, 0x6c, 0x61, 0x6e, 0x67, 0x65, 0x6e, 0x69, 0x3b, 0x3b, 0x3b,
-0x3b, 0x53, 0x77, 0x61, 0x7a, 0x69, 0x20, 0x65, 0x6d, 0x61, 0x6c, 0x61, 0x6e, 0x67, 0x65, 0x6e, 0x69, 0x3b, 0x53, 0x77,
-0x65, 0x64, 0x69, 0x73, 0x68, 0x20, 0x4b, 0x72, 0x6f, 0x6e, 0x61, 0x3b, 0x3b, 0x53, 0x77, 0x65, 0x64, 0x69, 0x73, 0x68,
-0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x77, 0x65, 0x64, 0x69, 0x73, 0x68, 0x20, 0x6b, 0x72,
-0x6f, 0x6e, 0x6f, 0x72, 0x3b, 0x53, 0x77, 0x69, 0x73, 0x73, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x53, 0x77,
-0x69, 0x73, 0x73, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x77, 0x69, 0x73, 0x73, 0x20, 0x66,
-0x72, 0x61, 0x6e, 0x63, 0x73, 0x3b, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x68, 0x69, 0x6c,
-0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x6e, 0x20, 0x73, 0x68, 0x69, 0x6c,
-0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x3b, 0x3b, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x6e, 0x20, 0x73, 0x68,
-0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x3b, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x6e, 0x20, 0x50, 0x61, 0x2bb, 0x61, 0x6e,
-0x67, 0x61, 0x3b, 0x3b, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x6e, 0x20, 0x70, 0x61, 0x2bb, 0x61, 0x6e, 0x67, 0x61, 0x3b, 0x3b,
-0x3b, 0x3b, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x6e, 0x20, 0x70, 0x61, 0x2bb, 0x61, 0x6e, 0x67, 0x61, 0x3b, 0x54, 0x72, 0x69,
-0x6e, 0x69, 0x64, 0x61, 0x64, 0x20, 0x26, 0x20, 0x54, 0x6f, 0x62, 0x61, 0x67, 0x6f, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61,
-0x72, 0x3b, 0x3b, 0x54, 0x72, 0x69, 0x6e, 0x69, 0x64, 0x61, 0x64, 0x20, 0x26, 0x20, 0x54, 0x6f, 0x62, 0x61, 0x67, 0x6f,
-0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x54, 0x72, 0x69, 0x6e, 0x69, 0x64, 0x61, 0x64, 0x20,
-0x26, 0x20, 0x54, 0x6f, 0x62, 0x61, 0x67, 0x6f, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x55, 0x67, 0x61,
-0x6e, 0x64, 0x61, 0x6e, 0x20, 0x53, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x55, 0x67, 0x61, 0x6e, 0x64,
-0x61, 0x6e, 0x20, 0x73, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x3b, 0x3b, 0x55, 0x67, 0x61, 0x6e, 0x64,
-0x61, 0x6e, 0x20, 0x73, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x3b, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68,
-0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68, 0x20, 0x70, 0x6f, 0x75, 0x6e,
-0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x3b,
-0x56, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x20, 0x56, 0x61, 0x74, 0x75, 0x3b, 0x3b, 0x56, 0x61, 0x6e, 0x75, 0x61, 0x74,
-0x75, 0x20, 0x76, 0x61, 0x74, 0x75, 0x3b, 0x3b, 0x3b, 0x3b, 0x56, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x20, 0x76, 0x61,
-0x74, 0x75, 0x73, 0x3b, 0x5a, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x4b, 0x77, 0x61, 0x63, 0x68, 0x61, 0x3b, 0x3b,
-0x5a, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x6b, 0x77, 0x61, 0x63, 0x68, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x5a, 0x61,
-0x6d, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x6b, 0x77, 0x61, 0x63, 0x68, 0x61, 0x73, 0x3b, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20,
-0x53, 0x75, 0x64, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x53, 0x6f, 0x75, 0x74,
-0x68, 0x20, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b,
-0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64,
-0x73, 0x3b, 0x4e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x41, 0x6e, 0x74, 0x69, 0x6c, 0x6c,
-0x65, 0x61, 0x6e, 0x20, 0x47, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x3b, 0x3b, 0x4e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6c,
-0x61, 0x6e, 0x64, 0x73, 0x20, 0x41, 0x6e, 0x74, 0x69, 0x6c, 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x67, 0x75, 0x69, 0x6c, 0x64,
-0x65, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x41, 0x6e,
-0x74, 0x69, 0x6c, 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x67, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x73, 0x3b, 0x65, 0x75, 0x72,
-0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x74, 0x3b, 0x64, 0x6f, 0x6e,
-0x73, 0x6b, 0x20, 0x6b, 0x72, 0xf3, 0x6e, 0x61, 0x3b, 0x3b, 0x64, 0x6f, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0xf3, 0x6e,
-0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x61, 0x6e, 0x73, 0x6b, 0x61, 0x72, 0x20, 0x6b, 0x72, 0xf3, 0x6e, 0x75, 0x72, 0x3b,
-0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x61, 0x3b,
-0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x61, 0x6c, 0x67, 0xe9, 0x72, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x64, 0x69, 0x6e, 0x61,
-0x72, 0x20, 0x61, 0x6c, 0x67, 0xe9, 0x72, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x73,
-0x20, 0x61, 0x6c, 0x67, 0xe9, 0x72, 0x69, 0x65, 0x6e, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x41,
-0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x41, 0x20,
-0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x43, 0x46,
-0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x62, 0x75, 0x72, 0x75,
-0x6e, 0x64, 0x61, 0x69, 0x73, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x62, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x61,
-0x69, 0x73, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x62, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x61,
-0x69, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b,
-0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b, 0x3b, 0x3b,
-0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b, 0x64,
-0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x20, 0x63, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x64, 0x6f, 0x6c, 0x6c,
-0x61, 0x72, 0x20, 0x63, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x6f, 0x6c, 0x6c, 0x61,
-0x72, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x63,
-0x6f, 0x6d, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x63, 0x6f, 0x6d, 0x6f, 0x72,
-0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x6f, 0x72, 0x69,
-0x65, 0x6e, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x63, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x69, 0x73, 0x3b,
-0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x63, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x69, 0x73, 0x3b, 0x3b, 0x3b, 0x3b,
-0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x69, 0x73, 0x3b, 0x66, 0x72, 0x61,
-0x6e, 0x63, 0x20, 0x64, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63,
-0x20, 0x64, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63,
-0x73, 0x20, 0x64, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x65, 0x6e, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20,
-0x43, 0x46, 0x50, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x50, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72,
-0x61, 0x6e, 0x63, 0x73, 0x20, 0x43, 0x46, 0x50, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x67, 0x75, 0x69, 0x6e, 0xe9,
-0x65, 0x6e, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x67, 0x75, 0x69, 0x6e, 0xe9, 0x65, 0x6e, 0x3b, 0x3b, 0x3b,
-0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x67, 0x75, 0x69, 0x6e, 0xe9, 0x65, 0x6e, 0x73, 0x3b, 0x67, 0x6f, 0x75,
-0x72, 0x64, 0x65, 0x20, 0x68, 0x61, 0xef, 0x74, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x67, 0x6f, 0x75, 0x72, 0x64,
-0x65, 0x20, 0x68, 0x61, 0xef, 0x74, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x67, 0x6f, 0x75, 0x72, 0x64,
-0x65, 0x73, 0x20, 0x68, 0x61, 0xef, 0x74, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x73, 0x3b, 0x61, 0x72, 0x69, 0x61, 0x72, 0x79,
-0x20, 0x6d, 0x61, 0x6c, 0x67, 0x61, 0x63, 0x68, 0x65, 0x3b, 0x3b, 0x61, 0x72, 0x69, 0x61, 0x72, 0x79, 0x20, 0x6d, 0x61,
-0x6c, 0x67, 0x61, 0x63, 0x68, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x61, 0x72, 0x69, 0x61, 0x72, 0x79, 0x73, 0x20, 0x6d, 0x61,
-0x6c, 0x67, 0x61, 0x63, 0x68, 0x65, 0x73, 0x3b, 0x6f, 0x75, 0x67, 0x75, 0x69, 0x79, 0x61, 0x20, 0x6d, 0x61, 0x75, 0x72,
-0x69, 0x74, 0x61, 0x6e, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x6f, 0x75, 0x67, 0x75, 0x69, 0x79, 0x61, 0x20, 0x6d, 0x61, 0x75,
-0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x6f, 0x75, 0x67, 0x75, 0x69, 0x79, 0x61, 0x73,
-0x20, 0x6d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x65, 0x6e, 0x73, 0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x65,
-0x20, 0x6d, 0x61, 0x75, 0x72, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x65,
-0x20, 0x6d, 0x61, 0x75, 0x72, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x72, 0x6f, 0x75, 0x70,
-0x69, 0x65, 0x73, 0x20, 0x6d, 0x61, 0x75, 0x72, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x73, 0x3b, 0x64, 0x69, 0x72,
-0x68, 0x61, 0x6d, 0x20, 0x6d, 0x61, 0x72, 0x6f, 0x63, 0x61, 0x69, 0x6e, 0x3b, 0x3b, 0x64, 0x69, 0x72, 0x68, 0x61, 0x6d,
-0x20, 0x6d, 0x61, 0x72, 0x6f, 0x63, 0x61, 0x69, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x69, 0x72, 0x68, 0x61, 0x6d, 0x73,
-0x20, 0x6d, 0x61, 0x72, 0x6f, 0x63, 0x61, 0x69, 0x6e, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x72, 0x77, 0x61,
-0x6e, 0x64, 0x61, 0x69, 0x73, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x72, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x69,
-0x73, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x72, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x69, 0x73,
-0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x65, 0x20, 0x64, 0x65, 0x73, 0x20, 0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c,
-0x65, 0x73, 0x3b, 0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x65, 0x20, 0x64, 0x65, 0x73, 0x20, 0x53, 0x65, 0x79, 0x63, 0x68,
-0x65, 0x6c, 0x6c, 0x65, 0x73, 0x3b, 0x3b, 0x3b, 0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x65, 0x73, 0x20, 0x64, 0x65, 0x73,
-0x20, 0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x65, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x73, 0x75,
-0x69, 0x73, 0x73, 0x65, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x73, 0x75, 0x69, 0x73, 0x73, 0x65, 0x3b, 0x3b,
-0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x73, 0x75, 0x69, 0x73, 0x73, 0x65, 0x73, 0x3b, 0x6c, 0x69, 0x76,
-0x72, 0x65, 0x20, 0x73, 0x79, 0x72, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x6c, 0x69, 0x76, 0x72, 0x65, 0x20, 0x73,
-0x79, 0x72, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x6c, 0x69, 0x76, 0x72, 0x65, 0x73, 0x20, 0x73, 0x79,
-0x72, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x73, 0x3b, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x74, 0x75, 0x6e, 0x69, 0x73, 0x69,
-0x65, 0x6e, 0x3b, 0x3b, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x74, 0x75, 0x6e, 0x69, 0x73, 0x69, 0x65, 0x6e, 0x3b, 0x3b,
-0x3b, 0x3b, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x73, 0x20, 0x74, 0x75, 0x6e, 0x69, 0x73, 0x69, 0x65, 0x6e, 0x73, 0x3b, 0x76,
-0x61, 0x74, 0x75, 0x20, 0x76, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x61, 0x6e, 0x3b, 0x3b, 0x76, 0x61, 0x74, 0x75, 0x20,
-0x76, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x61, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x76, 0x61, 0x74, 0x75, 0x73, 0x20, 0x76,
-0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x61, 0x6e, 0x73, 0x3b, 0x50, 0x75, 0x6e, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x73, 0x61,
-0x6e, 0x6e, 0x61, 0x63, 0x68, 0x3b, 0x3b, 0x70, 0x68, 0x75, 0x6e, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x73, 0x61, 0x6e, 0x6e,
-0x61, 0x63, 0x68, 0x3b, 0x70, 0x68, 0x75, 0x6e, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x73, 0x61, 0x6e, 0x6e, 0x61, 0x63, 0x68,
-0x3b, 0x70, 0x75, 0x69, 0x6e, 0x6e, 0x64, 0x20, 0x53, 0x68, 0x61, 0x73, 0x61, 0x6e, 0x6e, 0x61, 0x63, 0x68, 0x3b, 0x3b,
-0x70, 0x75, 0x6e, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x73, 0x61, 0x6e, 0x6e, 0x61, 0x63, 0x68, 0x3b, 0x10e5, 0x10d0, 0x10e0, 0x10d7,
-0x10e3, 0x10da, 0x10d8, 0x20, 0x10da, 0x10d0, 0x10e0, 0x10d8, 0x3b, 0x3b, 0x10e5, 0x10d0, 0x10e0, 0x10d7, 0x10e3, 0x10da, 0x10d8, 0x20, 0x10da, 0x10d0,
-0x10e0, 0x10d8, 0x3b, 0x3b, 0x3b, 0x3b, 0x10e5, 0x10d0, 0x10e0, 0x10d7, 0x10e3, 0x10da, 0x10d8, 0x20, 0x10da, 0x10d0, 0x10e0, 0x10d8, 0x3b, 0x45,
-0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x53, 0x63,
-0x68, 0x77, 0x65, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x6e, 0x3b, 0x3b, 0x53, 0x63, 0x68,
-0x77, 0x65, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x63,
-0x68, 0x77, 0x65, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x6e, 0x3b, 0x395, 0x3c5, 0x3c1, 0x3ce,
-0x3b, 0x3b, 0x3b5, 0x3c5, 0x3c1, 0x3ce, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b5, 0x3c5, 0x3c1, 0x3ce, 0x3b, 0x64, 0x61, 0x6e, 0x6d, 0x61,
-0x72, 0x6b, 0x69, 0x6d, 0x75, 0x74, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x3b, 0x64, 0x61, 0x6e, 0x73,
-0x6b, 0x69, 0x6e, 0x75, 0x74, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x61, 0x6e,
-0x6d, 0x61, 0x72, 0x6b, 0x69, 0x6d, 0x75, 0x74, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0xaad, 0xabe, 0xab0,
-0xaa4, 0xac0, 0xaaf, 0x20, 0xab0, 0xac2, 0xaaa, 0xabf, 0xaaf, 0xabe, 0x3b, 0x3b, 0xaad, 0xabe, 0xab0, 0xaa4, 0xac0, 0xaaf, 0x20, 0xab0,
-0xac2, 0xaaa, 0xabf, 0xaaf, 0xabe, 0x3b, 0x3b, 0x3b, 0x3b, 0xaad, 0xabe, 0xab0, 0xaa4, 0xac0, 0xaaf, 0x20, 0xab0, 0xac2, 0xaaa, 0xabf,
-0xaaf, 0xabe, 0x3b, 0x4e, 0x61, 0x69, 0x72, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4b, 0x75, 0x257, 0x69, 0x6e,
-0x20, 0x53, 0x65, 0x66, 0x61, 0x20, 0x6e, 0x61, 0x20, 0x41, 0x66, 0x69, 0x72, 0x6b, 0x61, 0x20, 0x54, 0x61, 0x20, 0x59,
-0x61, 0x6d, 0x6d, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x5e9, 0x5e7, 0x5dc, 0x20, 0x5d7, 0x5d3, 0x5e9, 0x3b, 0x3b,
-0x5e9, 0x5e7, 0x5dc, 0x20, 0x5d7, 0x5d3, 0x5e9, 0x3b, 0x5e9, 0x5e7, 0x5dc, 0x5d9, 0x5dd, 0x20, 0x5d7, 0x5d3, 0x5e9, 0x5d9, 0x5dd, 0x3b,
-0x3b, 0x5e9, 0x5e7, 0x5dc, 0x5d9, 0x5dd, 0x20, 0x5d7, 0x5d3, 0x5e9, 0x5d9, 0x5dd, 0x3b, 0x5e9, 0x5e7, 0x5dc, 0x5d9, 0x5dd, 0x20, 0x5d7,
-0x5d3, 0x5e9, 0x5d9, 0x5dd, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x941, 0x92a, 0x92f, 0x93e, 0x3b, 0x3b, 0x92d,
-0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x941, 0x92a, 0x92f, 0x93e, 0x3b, 0x3b, 0x3b, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940,
-0x92f, 0x20, 0x930, 0x942, 0x92a, 0x90f, 0x3b, 0x6d, 0x61, 0x67, 0x79, 0x61, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x69, 0x6e, 0x74,
-0x3b, 0x3b, 0x6d, 0x61, 0x67, 0x79, 0x61, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x69, 0x6e, 0x74, 0x3b, 0x3b, 0x3b, 0x3b, 0x6d,
-0x61, 0x67, 0x79, 0x61, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x69, 0x6e, 0x74, 0x3b, 0xed, 0x73, 0x6c, 0x65, 0x6e, 0x73, 0x6b,
-0x20, 0x6b, 0x72, 0xf3, 0x6e, 0x61, 0x3b, 0x3b, 0xed, 0x73, 0x6c, 0x65, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0xf3, 0x6e,
-0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0xed, 0x73, 0x6c, 0x65, 0x6e, 0x73, 0x6b, 0x61, 0x72, 0x20, 0x6b, 0x72, 0xf3, 0x6e, 0x75,
-0x72, 0x3b, 0x52, 0x75, 0x70, 0x69, 0x61, 0x68, 0x20, 0x49, 0x6e, 0x64, 0x6f, 0x6e, 0x65, 0x73, 0x69, 0x61, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x52, 0x75, 0x70, 0x69, 0x61, 0x68, 0x20, 0x49, 0x6e, 0x64, 0x6f, 0x6e, 0x65, 0x73, 0x69, 0x61,
-0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72,
-0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75,
-0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x73, 0x76,
-0x69, 0x7a, 0x7a, 0x65, 0x72, 0x6f, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x73, 0x76, 0x69, 0x7a, 0x7a,
-0x65, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x69, 0x20, 0x73, 0x76, 0x69, 0x7a, 0x7a,
-0x65, 0x72, 0x69, 0x3b, 0x65e5, 0x672c, 0x5186, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x5186, 0x3b, 0xcad, 0xcbe, 0xcb0, 0xca4, 0xcc0,
-0xcaf, 0x20, 0xcb0, 0xcc2, 0xcaa, 0xcbe, 0xcaf, 0xcbf, 0x3b, 0x3b, 0xcad, 0xcbe, 0xcb0, 0xca4, 0xcc0, 0xcaf, 0x20, 0xcb0, 0xcc2, 0xcaa,
-0xcbe, 0xcaf, 0xcbf, 0x3b, 0x3b, 0x3b, 0x3b, 0xcad, 0xcbe, 0xcb0, 0xca4, 0xcc0, 0xcaf, 0x20, 0xcb0, 0xcc2, 0xcaa, 0xcbe, 0xcaf, 0xcbf,
-0xc97, 0xcb3, 0xcc1, 0x3b, 0x6c1, 0x650, 0x646, 0x62f, 0x64f, 0x633, 0x62a, 0x672, 0x646, 0x6cd, 0x20, 0x631, 0x6c4, 0x67e, 0x64e, 0x6d2,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x49a, 0x430, 0x437, 0x430, 0x49b, 0x441, 0x442, 0x430, 0x43d, 0x20, 0x442, 0x435, 0x4a3,
-0x433, 0x435, 0x441, 0x456, 0x3b, 0x3b, 0x49a, 0x430, 0x437, 0x430, 0x49b, 0x441, 0x442, 0x430, 0x43d, 0x20, 0x442, 0x435, 0x4a3, 0x433,
-0x435, 0x441, 0x456, 0x3b, 0x3b, 0x3b, 0x3b, 0x49a, 0x430, 0x437, 0x430, 0x49b, 0x441, 0x442, 0x430, 0x43d, 0x20, 0x442, 0x435, 0x4a3,
-0x433, 0x435, 0x441, 0x456, 0x3b, 0x41a, 0x44b, 0x440, 0x433, 0x44b, 0x437, 0x441, 0x442, 0x430, 0x43d, 0x20, 0x441, 0x43e, 0x43c, 0x443,
-0x3b, 0x3b, 0x41a, 0x44b, 0x440, 0x433, 0x44b, 0x437, 0x441, 0x442, 0x430, 0x43d, 0x20, 0x441, 0x43e, 0x43c, 0x443, 0x3b, 0x3b, 0x3b,
-0x3b, 0x41a, 0x44b, 0x440, 0x433, 0x44b, 0x437, 0x441, 0x442, 0x430, 0x43d, 0x20, 0x441, 0x43e, 0x43c, 0x443, 0x3b, 0xb300, 0xd55c, 0xbbfc,
-0xad6d, 0x20, 0xc6d0, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xb300, 0xd55c, 0xbbfc, 0xad6d, 0x20, 0xc6d0, 0x3b, 0xc870, 0xc120, 0x20, 0xbbfc,
-0xc8fc, 0xc8fc, 0xc758, 0x20, 0xc778, 0xbbfc, 0x20, 0xacf5, 0xd654, 0xad6d, 0x20, 0xc6d0, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xc870, 0xc120,
-0x20, 0xbbfc, 0xc8fc, 0xc8fc, 0xc758, 0x20, 0xc778, 0xbbfc, 0x20, 0xacf5, 0xd654, 0xad6d, 0x20, 0xc6d0, 0x3b, 0x49, 0x66, 0x61, 0x72, 0x61,
-0x6e, 0x67, 0x61, 0x20, 0x72, 0x79, 0x2019, 0x55, 0x62, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x3b, 0x3b, 0xea5, 0xeb2, 0xea7, 0x20, 0xe81, 0xeb5, 0xe9a, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xea5, 0xeb2, 0xea7, 0x20, 0xe81,
-0xeb5, 0xe9a, 0x3b, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x3b, 0x3b,
-0x3b, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x46, 0x61, 0x6c, 0xe1, 0x6e, 0x67, 0x61, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x6f, 0x6e,
-0x67, 0xf3, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4b, 0x77, 0x61, 0x6e, 0x7a, 0x61, 0x20, 0x79, 0x61, 0x20, 0x41,
-0x6e, 0x67, 0xf3, 0x6c, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x61, 0x6c, 0xe1, 0x6e, 0x67, 0x61, 0x20,
-0x43, 0x46, 0x41, 0x20, 0x42, 0x45, 0x41, 0x43, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x75, 0x72, 0x61, 0x73,
-0x3b, 0x3b, 0x65, 0x75, 0x72, 0x61, 0x73, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x61, 0x69, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b,
-0x65, 0x75, 0x72, 0x173, 0x3b, 0x41c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d, 0x441, 0x43a, 0x438, 0x20, 0x434, 0x435, 0x43d, 0x430,
-0x440, 0x3b, 0x3b, 0x41c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d, 0x441, 0x43a, 0x438, 0x20, 0x434, 0x435, 0x43d, 0x430, 0x440, 0x3b,
-0x3b, 0x3b, 0x3b, 0x41c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d, 0x441, 0x43a, 0x438, 0x20, 0x434, 0x435, 0x43d, 0x430, 0x440, 0x438,
-0x3b, 0x41, 0x72, 0x69, 0x61, 0x72, 0x79, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x52, 0x69, 0x6e, 0x67, 0x67, 0x69,
-0x74, 0x20, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x52, 0x69, 0x6e, 0x67,
-0x67, 0x69, 0x74, 0x20, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x3b, 0x44, 0x6f, 0x6c, 0x61, 0x72, 0x20, 0x42,
-0x72, 0x75, 0x6e, 0x65, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x6f, 0x6c, 0x61, 0x72, 0x20, 0x42, 0x72, 0x75,
-0x6e, 0x65, 0x69, 0x3b, 0x44, 0x6f, 0x6c, 0x61, 0x72, 0x20, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x75, 0x72, 0x61, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x6f, 0x6c, 0x61, 0x72, 0x20, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x75, 0x72, 0x61,
-0x3b, 0xd07, 0xd28, 0xd4d, 0xd24, 0xd4d, 0xd2f, 0xd7b, 0x20, 0xd30, 0xd42, 0xd2a, 0x3b, 0x3b, 0xd07, 0xd28, 0xd4d, 0xd24, 0xd4d, 0xd2f,
-0xd7b, 0x20, 0xd30, 0xd42, 0xd2a, 0x3b, 0x3b, 0x3b, 0x3b, 0xd07, 0xd28, 0xd4d, 0xd24, 0xd4d, 0xd2f, 0xd7b, 0x20, 0xd30, 0xd42, 0xd2a,
-0x3b, 0x65, 0x77, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x77, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x77, 0x72, 0x6f, 0x3b, 0x65, 0x77,
-0x72, 0x6f, 0x3b, 0x65, 0x77, 0x72, 0x6f, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x941, 0x92a, 0x92f, 0x93e,
-0x3b, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x941, 0x92a, 0x92f, 0x93e, 0x3b, 0x3b, 0x3b, 0x3b, 0x92d, 0x93e,
-0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x941, 0x92a, 0x92f, 0x947, 0x3b, 0x442, 0x4e9, 0x433, 0x440, 0x4e9, 0x433, 0x3b, 0x3b, 0x442,
-0x4e9, 0x433, 0x440, 0x4e9, 0x433, 0x3b, 0x3b, 0x3b, 0x3b, 0x442, 0x4e9, 0x433, 0x440, 0x4e9, 0x433, 0x3b, 0x928, 0x947, 0x92a, 0x93e,
-0x932, 0x940, 0x20, 0x930, 0x942, 0x92a, 0x948, 0x92f, 0x93e, 0x901, 0x3b, 0x3b, 0x928, 0x947, 0x92a, 0x93e, 0x932, 0x940, 0x20, 0x930,
-0x942, 0x92a, 0x948, 0x92f, 0x93e, 0x901, 0x3b, 0x3b, 0x3b, 0x3b, 0x928, 0x947, 0x92a, 0x93e, 0x932, 0x940, 0x20, 0x930, 0x942, 0x92a,
-0x948, 0x92f, 0x93e, 0x901, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x942, 0x92a, 0x93f, 0x901, 0x92f, 0x93e, 0x3b,
-0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x942, 0x92a, 0x93f, 0x901, 0x92f, 0x93e, 0x3b, 0x3b, 0x3b, 0x3b, 0x92d,
-0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x942, 0x92a, 0x93f, 0x901, 0x92f, 0x93e, 0x3b, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x65,
-0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x72, 0x3b, 0x3b, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65,
-0x3b, 0x3b, 0x3b, 0x3b, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x65, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x72, 0x3b, 0xb1f, 0xb19,
-0xb15, 0xb3e, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cd, 0x3b, 0x3b, 0x627, 0x641, 0x63a,
-0x627, 0x646, 0x6cd, 0x3b, 0x3b, 0x3b, 0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cd, 0x3b, 0x631, 0x6cc, 0x627, 0x644, 0x20, 0x627,
-0x6cc, 0x631, 0x627, 0x646, 0x3b, 0x3b, 0x631, 0x6cc, 0x627, 0x644, 0x20, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x3b, 0x3b, 0x3b, 0x3b,
-0x631, 0x6cc, 0x627, 0x644, 0x20, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cc, 0x20, 0x627, 0x641,
-0x63a, 0x627, 0x646, 0x633, 0x62a, 0x627, 0x646, 0x3b, 0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cc, 0x20, 0x627, 0x641, 0x63a, 0x627,
-0x646, 0x633, 0x62a, 0x627, 0x646, 0x3b, 0x3b, 0x3b, 0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cc, 0x20, 0x627, 0x641, 0x63a, 0x627,
-0x646, 0x633, 0x62a, 0x627, 0x646, 0x3b, 0x7a, 0x142, 0x6f, 0x74, 0x79, 0x20, 0x70, 0x6f, 0x6c, 0x73, 0x6b, 0x69, 0x3b, 0x3b,
-0x7a, 0x142, 0x6f, 0x74, 0x79, 0x20, 0x70, 0x6f, 0x6c, 0x73, 0x6b, 0x69, 0x3b, 0x3b, 0x7a, 0x142, 0x6f, 0x74, 0x65, 0x20,
-0x70, 0x6f, 0x6c, 0x73, 0x6b, 0x69, 0x65, 0x3b, 0x7a, 0x142, 0x6f, 0x74, 0x79, 0x63, 0x68, 0x20, 0x70, 0x6f, 0x6c, 0x73,
-0x6b, 0x69, 0x63, 0x68, 0x3b, 0x7a, 0x142, 0x6f, 0x74, 0x65, 0x67, 0x6f, 0x20, 0x70, 0x6f, 0x6c, 0x73, 0x6b, 0x69, 0x65,
-0x67, 0x6f, 0x3b, 0x52, 0x65, 0x61, 0x6c, 0x20, 0x62, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x3b,
-0x52, 0x65, 0x61, 0x6c, 0x20, 0x62, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x52,
-0x65, 0x61, 0x69, 0x73, 0x20, 0x62, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x65, 0x69, 0x72, 0x6f, 0x73, 0x3b, 0x4b, 0x77, 0x61,
-0x6e, 0x7a, 0x61, 0x20, 0x61, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x4b, 0x77, 0x61, 0x6e, 0x7a, 0x61,
-0x20, 0x61, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x4b, 0x77, 0x61, 0x6e, 0x7a, 0x61, 0x73,
-0x20, 0x61, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x45, 0x73, 0x63, 0x75, 0x64, 0x6f, 0x20, 0x63, 0x61,
-0x62, 0x6f, 0x2d, 0x76, 0x65, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x45, 0x73, 0x63, 0x75, 0x64, 0x6f, 0x20,
-0x63, 0x61, 0x62, 0x6f, 0x2d, 0x76, 0x65, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x73, 0x63,
-0x75, 0x64, 0x6f, 0x73, 0x20, 0x63, 0x61, 0x62, 0x6f, 0x2d, 0x76, 0x65, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x6f, 0x73, 0x3b,
-0x44, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x64, 0x6f, 0x73, 0x20, 0x45, 0x73, 0x74, 0x61, 0x64, 0x6f, 0x73, 0x20, 0x55, 0x6e,
-0x69, 0x64, 0x6f, 0x73, 0x3b, 0x3b, 0x44, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x64, 0x6f, 0x73, 0x20, 0x45, 0x73, 0x74, 0x61,
-0x64, 0x6f, 0x73, 0x20, 0x55, 0x6e, 0x69, 0x64, 0x6f, 0x73, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0xf3, 0x6c, 0x61, 0x72, 0x65,
-0x73, 0x20, 0x64, 0x6f, 0x73, 0x20, 0x45, 0x73, 0x74, 0x61, 0x64, 0x6f, 0x73, 0x20, 0x55, 0x6e, 0x69, 0x64, 0x6f, 0x73,
-0x3b, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b, 0x3b,
-0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b, 0x3b, 0x3b,
-0x3b, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x73, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b,
-0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x3b,
-0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x3b,
-0x3b, 0x3b, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x73, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f,
-0x29, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x75, 0x72, 0x6f,
-0x73, 0x3b, 0x50, 0x61, 0x74, 0x61, 0x63, 0x61, 0x20, 0x64, 0x65, 0x20, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x3b, 0x3b, 0x50,
-0x61, 0x74, 0x61, 0x63, 0x61, 0x20, 0x64, 0x65, 0x20, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x3b, 0x3b, 0x3b, 0x3b, 0x50, 0x61,
-0x74, 0x61, 0x63, 0x61, 0x73, 0x20, 0x64, 0x65, 0x20, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x3b, 0x4d, 0x65, 0x74, 0x69, 0x63,
-0x61, 0x6c, 0x20, 0x64, 0x65, 0x20, 0x4d, 0x6f, 0xe7, 0x61, 0x6d, 0x62, 0x69, 0x71, 0x75, 0x65, 0x3b, 0x3b, 0x4d, 0x65,
-0x74, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x20, 0x4d, 0x6f, 0xe7, 0x61, 0x6d, 0x62, 0x69, 0x71, 0x75, 0x65, 0x3b,
-0x3b, 0x3b, 0x3b, 0x4d, 0x65, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x65, 0x73, 0x20, 0x64, 0x65, 0x20, 0x4d, 0x6f, 0xe7, 0x61,
-0x6d, 0x62, 0x69, 0x71, 0x75, 0x65, 0x3b, 0x44, 0x6f, 0x62, 0x72, 0x61, 0x20, 0x64, 0x65, 0x20, 0x53, 0xe3, 0x6f, 0x20,
-0x54, 0x6f, 0x6d, 0xe9, 0x20, 0x65, 0x20, 0x50, 0x72, 0xed, 0x6e, 0x63, 0x69, 0x70, 0x65, 0x3b, 0x3b, 0x44, 0x6f, 0x62,
-0x72, 0x61, 0x20, 0x64, 0x65, 0x20, 0x53, 0xe3, 0x6f, 0x20, 0x54, 0x6f, 0x6d, 0xe9, 0x20, 0x65, 0x20, 0x50, 0x72, 0xed,
-0x6e, 0x63, 0x69, 0x70, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x6f, 0x62, 0x72, 0x61, 0x73, 0x20, 0x64, 0x65, 0x20, 0x53,
-0xe3, 0x6f, 0x20, 0x54, 0x6f, 0x6d, 0xe9, 0x20, 0x65, 0x20, 0x50, 0x72, 0xed, 0x6e, 0x63, 0x69, 0x70, 0x65, 0x3b, 0x46,
-0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x73, 0x75, 0xed, 0xe7, 0x6f, 0x3b, 0x3b, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20,
-0x73, 0x75, 0xed, 0xe7, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x73, 0x20, 0x73, 0x75, 0xed,
-0xe7, 0x6f, 0x73, 0x3b, 0xa2d, 0xa3e, 0xa30, 0xa24, 0xa40, 0x20, 0xa30, 0xa41, 0xa2a, 0xa07, 0xa06, 0x3b, 0x3b, 0xa2d, 0xa3e, 0xa30,
-0xa24, 0xa40, 0x20, 0xa30, 0xa41, 0xa2a, 0xa07, 0xa06, 0x3b, 0x3b, 0x3b, 0x3b, 0xa2d, 0xa3e, 0xa30, 0xa24, 0xa40, 0x20, 0xa30, 0xa41,
-0xa2a, 0xa0f, 0x3b, 0x631, 0x648, 0x67e, 0x626, 0x6cc, 0x6c1, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e,
-0x63, 0x20, 0x73, 0x76, 0x69, 0x7a, 0x7a, 0x65, 0x72, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x73, 0x76, 0x69,
-0x7a, 0x7a, 0x65, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x73, 0x76, 0x69, 0x7a, 0x7a, 0x65,
-0x72, 0x3b, 0x6c, 0x65, 0x75, 0x20, 0x72, 0x6f, 0x6d, 0xe2, 0x6e, 0x65, 0x73, 0x63, 0x3b, 0x3b, 0x6c, 0x65, 0x75, 0x20,
-0x72, 0x6f, 0x6d, 0xe2, 0x6e, 0x65, 0x73, 0x63, 0x3b, 0x3b, 0x6c, 0x65, 0x69, 0x20, 0x72, 0x6f, 0x6d, 0xe2, 0x6e, 0x65,
-0x219, 0x74, 0x69, 0x3b, 0x3b, 0x6c, 0x65, 0x69, 0x20, 0x72, 0x6f, 0x6d, 0xe2, 0x6e, 0x65, 0x219, 0x74, 0x69, 0x3b, 0x6c,
-0x65, 0x75, 0x20, 0x6d, 0x6f, 0x6c, 0x64, 0x6f, 0x76, 0x65, 0x6e, 0x65, 0x73, 0x63, 0x3b, 0x3b, 0x6c, 0x65, 0x75, 0x20,
-0x6d, 0x6f, 0x6c, 0x64, 0x6f, 0x76, 0x65, 0x6e, 0x65, 0x73, 0x63, 0x3b, 0x3b, 0x6c, 0x65, 0x69, 0x20, 0x6d, 0x6f, 0x6c,
-0x64, 0x6f, 0x76, 0x65, 0x6e, 0x65, 0x219, 0x74, 0x69, 0x3b, 0x3b, 0x6c, 0x65, 0x69, 0x20, 0x6d, 0x6f, 0x6c, 0x64, 0x6f,
-0x76, 0x65, 0x6e, 0x65, 0x219, 0x74, 0x69, 0x3b, 0x420, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x440,
-0x443, 0x431, 0x43b, 0x44c, 0x3b, 0x3b, 0x440, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x440, 0x443, 0x431,
-0x43b, 0x44c, 0x3b, 0x3b, 0x440, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44f,
-0x3b, 0x440, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x435, 0x439, 0x3b, 0x440,
-0x43e, 0x441, 0x441, 0x438, 0x439, 0x441, 0x43a, 0x43e, 0x433, 0x43e, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44f, 0x3b, 0x411, 0x435, 0x43b,
-0x43e, 0x440, 0x443, 0x441, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44c, 0x3b, 0x3b, 0x431, 0x435, 0x43b, 0x43e,
-0x440, 0x443, 0x441, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44c, 0x3b, 0x3b, 0x431, 0x435, 0x43b, 0x43e, 0x440,
-0x443, 0x441, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44f, 0x3b, 0x431, 0x435, 0x43b, 0x43e, 0x440, 0x443, 0x441,
-0x441, 0x43a, 0x438, 0x445, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x435, 0x439, 0x3b, 0x431, 0x435, 0x43b, 0x43e, 0x440, 0x443, 0x441, 0x441,
-0x43a, 0x43e, 0x433, 0x43e, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44f, 0x3b, 0x41a, 0x430, 0x437, 0x430, 0x445, 0x441, 0x43a, 0x438, 0x439,
-0x20, 0x442, 0x435, 0x43d, 0x433, 0x435, 0x3b, 0x3b, 0x43a, 0x430, 0x437, 0x430, 0x445, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x442, 0x435,
-0x43d, 0x433, 0x435, 0x3b, 0x3b, 0x43a, 0x430, 0x437, 0x430, 0x445, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x442, 0x435, 0x43d, 0x433, 0x435,
-0x3b, 0x43a, 0x430, 0x437, 0x430, 0x445, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x442, 0x435, 0x43d, 0x433, 0x435, 0x3b, 0x43a, 0x430, 0x437,
-0x430, 0x445, 0x441, 0x43a, 0x43e, 0x433, 0x43e, 0x20, 0x442, 0x435, 0x43d, 0x433, 0x435, 0x3b, 0x41a, 0x438, 0x440, 0x433, 0x438, 0x437,
-0x441, 0x43a, 0x438, 0x439, 0x20, 0x441, 0x43e, 0x43c, 0x3b, 0x3b, 0x43a, 0x438, 0x440, 0x433, 0x438, 0x437, 0x441, 0x43a, 0x438, 0x439,
-0x20, 0x441, 0x43e, 0x43c, 0x3b, 0x3b, 0x43a, 0x438, 0x440, 0x433, 0x438, 0x437, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x441, 0x43e, 0x43c,
-0x430, 0x3b, 0x43a, 0x438, 0x440, 0x433, 0x438, 0x437, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x441, 0x43e, 0x43c, 0x43e, 0x432, 0x3b, 0x43a,
-0x438, 0x440, 0x433, 0x438, 0x437, 0x441, 0x43a, 0x43e, 0x433, 0x43e, 0x20, 0x441, 0x43e, 0x43c, 0x430, 0x3b, 0x41c, 0x43e, 0x43b, 0x434,
-0x430, 0x432, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x43b, 0x435, 0x439, 0x3b, 0x3b, 0x43c, 0x43e, 0x43b, 0x434, 0x430, 0x432, 0x441, 0x43a,
-0x438, 0x439, 0x20, 0x43b, 0x435, 0x439, 0x3b, 0x3b, 0x43c, 0x43e, 0x43b, 0x434, 0x430, 0x432, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x43b,
-0x435, 0x44f, 0x3b, 0x43c, 0x43e, 0x43b, 0x434, 0x430, 0x432, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x43b, 0x435, 0x435, 0x432, 0x3b, 0x43c,
-0x43e, 0x43b, 0x434, 0x430, 0x432, 0x441, 0x43a, 0x43e, 0x433, 0x43e, 0x20, 0x43b, 0x435, 0x44f, 0x3b, 0x423, 0x43a, 0x440, 0x430, 0x438,
-0x43d, 0x441, 0x43a, 0x430, 0x44f, 0x20, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x430, 0x3b, 0x3b, 0x443, 0x43a, 0x440, 0x430, 0x438, 0x43d,
-0x441, 0x43a, 0x430, 0x44f, 0x20, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x430, 0x3b, 0x3b, 0x443, 0x43a, 0x440, 0x430, 0x438, 0x43d, 0x441,
-0x43a, 0x438, 0x435, 0x20, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x44b, 0x3b, 0x443, 0x43a, 0x440, 0x430, 0x438, 0x43d, 0x441, 0x43a, 0x438,
-0x445, 0x20, 0x433, 0x440, 0x438, 0x432, 0x435, 0x43d, 0x3b, 0x443, 0x43a, 0x440, 0x430, 0x438, 0x43d, 0x441, 0x43a, 0x43e, 0x439, 0x20,
-0x433, 0x440, 0x438, 0x432, 0x43d, 0x44b, 0x3b, 0x66, 0x61, 0x72, 0xe2, 0x6e, 0x67, 0x61, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28,
-0x42, 0x45, 0x41, 0x43, 0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x421, 0x440, 0x43f, 0x441, 0x43a, 0x438, 0x20, 0x434,
-0x438, 0x43d, 0x430, 0x440, 0x3b, 0x3b, 0x441, 0x440, 0x43f, 0x441, 0x43a, 0x438, 0x20, 0x434, 0x438, 0x43d, 0x430, 0x440, 0x3b, 0x3b,
-0x441, 0x440, 0x43f, 0x441, 0x43a, 0x430, 0x20, 0x434, 0x438, 0x43d, 0x430, 0x440, 0x430, 0x3b, 0x3b, 0x441, 0x440, 0x43f, 0x441, 0x43a,
-0x438, 0x445, 0x20, 0x434, 0x438, 0x43d, 0x430, 0x440, 0x430, 0x3b, 0x411, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445,
-0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x430, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438,
-0x431, 0x438, 0x43b, 0x43d, 0x430, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x430, 0x3b, 0x3b, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a,
-0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x430, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435,
-0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x430, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x430, 0x3b, 0x3b, 0x431, 0x43e, 0x441, 0x430,
-0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x435, 0x20, 0x43a, 0x43e,
-0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x435, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x65, 0x3b, 0x3b, 0x431,
-0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x438,
-0x445, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x438, 0x445, 0x20, 0x43c, 0x430, 0x440,
-0x430, 0x43a, 0x430, 0x3b, 0x415, 0x432, 0x440, 0x43e, 0x3b, 0x3b, 0x435, 0x432, 0x440, 0x43e, 0x3b, 0x3b, 0x435, 0x432, 0x440, 0x430,
-0x3b, 0x3b, 0x435, 0x432, 0x440, 0x430, 0x3b, 0x42, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x68, 0x65, 0x72, 0x63,
-0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x61, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c,
-0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x68,
-0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x61, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69,
-0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b,
-0x6f, 0x2d, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x65, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65,
-0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61,
-0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x69, 0x68, 0x20, 0x6b,
-0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x69, 0x68, 0x20, 0x6d, 0x61, 0x72, 0x61, 0x6b, 0x61,
-0x3b, 0x45, 0x76, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x76, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x76, 0x72, 0x61, 0x3b, 0x3b, 0x65,
-0x76, 0x72, 0x61, 0x3b, 0x53, 0x72, 0x70, 0x73, 0x6b, 0x69, 0x20, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x3b, 0x3b, 0x73, 0x72,
-0x70, 0x73, 0x6b, 0x69, 0x20, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x3b, 0x3b, 0x73, 0x72, 0x70, 0x73, 0x6b, 0x61, 0x20, 0x64,
-0x69, 0x6e, 0x61, 0x72, 0x61, 0x3b, 0x3b, 0x73, 0x72, 0x70, 0x73, 0x6b, 0x69, 0x68, 0x20, 0x64, 0x69, 0x6e, 0x61, 0x72,
-0x61, 0x3b, 0x41b, 0x430, 0x440, 0x3b, 0x3b, 0x43b, 0x430, 0x440, 0x3b, 0x3b, 0x3b, 0x3b, 0x43b, 0x430, 0x440, 0x44b, 0x3b, 0x421,
-0x43e, 0x43c, 0x3b, 0x3b, 0x441, 0x43e, 0x43c, 0x3b, 0x3b, 0x3b, 0x3b, 0x441, 0x43e, 0x43c, 0x44b, 0x3b, 0x44, 0x6f, 0x72, 0x61,
-0x20, 0x72, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x6b, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xdc1, 0xdca,
-0x200d, 0xdbb, 0xdd3, 0x20, 0xdbd, 0xd82, 0xd9a, 0xdcf, 0x20, 0xdbb, 0xdd4, 0xdb4, 0xdd2, 0xdba, 0xdbd, 0x3b, 0x3b, 0xdc1, 0xdca, 0x200d,
-0xdbb, 0xdd3, 0x20, 0xdbd, 0xd82, 0xd9a, 0xdcf, 0x20, 0xdbb, 0xdd4, 0xdb4, 0xdd2, 0xdba, 0xdbd, 0x3b, 0x3b, 0x3b, 0x3b, 0xdc1, 0xdca,
-0x200d, 0xdbb, 0xdd3, 0x20, 0xdbd, 0xd82, 0xd9a, 0xdcf, 0x20, 0xdbb, 0xdd4, 0xdb4, 0xdd2, 0xdba, 0xdbd, 0x3b, 0x65, 0x75, 0x72, 0x6f,
-0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0xe1, 0x3b, 0x65, 0x75, 0x72, 0x61, 0x3b, 0x65, 0x75,
-0x72, 0x3b, 0x65, 0x76, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x76, 0x72, 0x6f, 0x3b, 0x65, 0x76, 0x72, 0x61, 0x3b, 0x65, 0x76,
-0x72, 0x69, 0x3b, 0x3b, 0x65, 0x76, 0x72, 0x6f, 0x76, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x20, 0x73, 0x6f, 0x6f,
-0x6d, 0x61, 0x61, 0x6c, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x61, 0x72, 0x61, 0x6e, 0x20, 0x4a, 0x61,
-0x62, 0x62, 0x75, 0x75, 0x74, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x69, 0x72, 0x74, 0x61, 0x20, 0x49,
-0x74, 0x6f, 0x6f, 0x62, 0x62, 0x69, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20,
-0x61, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x61, 0x72, 0x67, 0x65,
-0x6e, 0x74, 0x69, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x61, 0x72, 0x67, 0x65, 0x6e,
-0x74, 0x69, 0x6e, 0x6f, 0x73, 0x3b, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x62, 0x65, 0x6c, 0x69, 0x63, 0x65, 0xf1, 0x6f,
-0x3b, 0x3b, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x62, 0x65, 0x6c, 0x69, 0x63, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b,
-0x64, 0xf3, 0x6c, 0x61, 0x72, 0x65, 0x73, 0x20, 0x62, 0x65, 0x6c, 0x69, 0x63, 0x65, 0xf1, 0x6f, 0x73, 0x3b, 0x62, 0x6f,
-0x6c, 0x69, 0x76, 0x69, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x62, 0x6f, 0x6c, 0x69, 0x76, 0x69, 0x61, 0x6e, 0x6f, 0x3b, 0x3b,
-0x3b, 0x3b, 0x62, 0x6f, 0x6c, 0x69, 0x76, 0x69, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x72, 0x65, 0x61, 0x6c, 0x20, 0x62, 0x72,
-0x61, 0x73, 0x69, 0x6c, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x72, 0x65, 0x61, 0x6c, 0x20, 0x62, 0x72, 0x61, 0x73, 0x69, 0x6c,
-0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x72, 0x65, 0x61, 0x6c, 0x65, 0x73, 0x20, 0x62, 0x72, 0x61, 0x73, 0x69, 0x6c,
-0x65, 0xf1, 0x6f, 0x73, 0x3b, 0x50, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x65, 0x6e, 0x6f, 0x3b, 0x3b, 0x70,
-0x65, 0x73, 0x6f, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x65, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73,
-0x20, 0x63, 0x68, 0x69, 0x6c, 0x65, 0x6e, 0x6f, 0x73, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x6d,
-0x62, 0x69, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x69, 0x61,
-0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x69, 0x61,
-0x6e, 0x6f, 0x73, 0x3b, 0x63, 0x6f, 0x6c, 0xf3, 0x6e, 0x20, 0x63, 0x6f, 0x73, 0x74, 0x61, 0x72, 0x72, 0x69, 0x63, 0x65,
-0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x63, 0x6f, 0x6c, 0xf3, 0x6e, 0x20, 0x63, 0x6f, 0x73, 0x74, 0x61, 0x72, 0x72, 0x69, 0x63,
-0x65, 0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x63, 0x6f, 0x6c, 0x6f, 0x6e, 0x65, 0x73, 0x20, 0x63, 0x6f, 0x73, 0x74,
-0x61, 0x72, 0x72, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x75, 0x62, 0x61,
-0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x75, 0x62, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70,
-0x65, 0x73, 0x6f, 0x73, 0x20, 0x63, 0x75, 0x62, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x64, 0x6f,
-0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x64, 0x6f, 0x6d, 0x69, 0x6e,
-0x69, 0x63, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x64, 0x6f, 0x6d, 0x69, 0x6e,
-0x69, 0x63, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x65, 0x73, 0x74, 0x61, 0x64, 0x6f, 0x75,
-0x6e, 0x69, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x65, 0x73, 0x74, 0x61, 0x64,
-0x6f, 0x75, 0x6e, 0x69, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x65, 0x73,
-0x20, 0x65, 0x73, 0x74, 0x61, 0x64, 0x6f, 0x75, 0x6e, 0x69, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x3b, 0x66, 0x72, 0x61,
-0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x42, 0x45, 0x41, 0x43, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f,
-0x20, 0x43, 0x46, 0x41, 0x20, 0x42, 0x45, 0x41, 0x43, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x73,
-0x20, 0x43, 0x46, 0x41, 0x20, 0x42, 0x45, 0x41, 0x43, 0x3b, 0x71, 0x75, 0x65, 0x74, 0x7a, 0x61, 0x6c, 0x3b, 0x3b, 0x71,
-0x75, 0x65, 0x74, 0x7a, 0x61, 0x6c, 0x3b, 0x3b, 0x3b, 0x3b, 0x71, 0x75, 0x65, 0x74, 0x7a, 0x61, 0x6c, 0x65, 0x73, 0x3b,
-0x6c, 0x65, 0x6d, 0x70, 0x69, 0x72, 0x61, 0x20, 0x68, 0x6f, 0x6e, 0x64, 0x75, 0x72, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x6c,
-0x65, 0x6d, 0x70, 0x69, 0x72, 0x61, 0x20, 0x68, 0x6f, 0x6e, 0x64, 0x75, 0x72, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b,
-0x6c, 0x65, 0x6d, 0x70, 0x69, 0x72, 0x61, 0x73, 0x20, 0x68, 0x6f, 0x6e, 0x64, 0x75, 0x72, 0x65, 0xf1, 0x6f, 0x73, 0x3b,
-0x70, 0x65, 0x73, 0x6f, 0x20, 0x6d, 0x65, 0x78, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20,
-0x6d, 0x65, 0x78, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x6d, 0x65,
-0x78, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x63, 0xf3, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x20, 0x6e, 0x69, 0x63, 0x61,
-0x72, 0x61, 0x67, 0xfc, 0x65, 0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x63, 0xf3, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x20, 0x6e, 0x69,
-0x63, 0x61, 0x72, 0x61, 0x67, 0xfc, 0x65, 0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x63, 0xf3, 0x72, 0x64, 0x6f, 0x62,
-0x61, 0x73, 0x20, 0x6e, 0x69, 0x63, 0x61, 0x72, 0x61, 0x67, 0xfc, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x3b, 0x62, 0x61, 0x6c,
-0x62, 0x6f, 0x61, 0x20, 0x70, 0x61, 0x6e, 0x61, 0x6d, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x62, 0x61, 0x6c, 0x62, 0x6f, 0x61,
-0x20, 0x70, 0x61, 0x6e, 0x61, 0x6d, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x62, 0x61, 0x6c, 0x62, 0x6f, 0x61, 0x73,
-0x20, 0x70, 0x61, 0x6e, 0x61, 0x6d, 0x65, 0xf1, 0x6f, 0x73, 0x3b, 0x67, 0x75, 0x61, 0x72, 0x61, 0x6e, 0xed, 0x20, 0x70,
-0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x3b, 0x3b, 0x67, 0x75, 0x61, 0x72, 0x61, 0x6e, 0xed, 0x20, 0x70, 0x61,
-0x72, 0x61, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x67, 0x75, 0x61, 0x72, 0x61, 0x6e, 0xed, 0x65, 0x73,
-0x20, 0x70, 0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x73, 0x3b, 0x73, 0x6f, 0x6c, 0x20, 0x70, 0x65, 0x72, 0x75,
-0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x73, 0x6f, 0x6c, 0x20, 0x70, 0x65, 0x72, 0x75, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b,
-0x73, 0x6f, 0x6c, 0x65, 0x73, 0x20, 0x70, 0x65, 0x72, 0x75, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20,
-0x66, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x66, 0x69, 0x6c, 0x69, 0x70,
-0x69, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e,
-0x6f, 0x73, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x75, 0x72, 0x75, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x3b, 0x3b, 0x70, 0x65,
-0x73, 0x6f, 0x20, 0x75, 0x72, 0x75, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73,
-0x20, 0x75, 0x72, 0x75, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x73, 0x3b, 0x62, 0x6f, 0x6c, 0xed, 0x76, 0x61, 0x72, 0x20, 0x76,
-0x65, 0x6e, 0x65, 0x7a, 0x6f, 0x6c, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x62, 0x6f, 0x6c, 0xed, 0x76, 0x61, 0x72, 0x20, 0x76,
-0x65, 0x6e, 0x65, 0x7a, 0x6f, 0x6c, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x62, 0x6f, 0x6c, 0xed, 0x76, 0x61, 0x72,
-0x65, 0x73, 0x20, 0x76, 0x65, 0x6e, 0x65, 0x7a, 0x6f, 0x6c, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0x69,
-0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x73, 0x68, 0x69,
-0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x3b,
-0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x7a, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69,
-0x61, 0x3b, 0x46, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x3b, 0x3b,
-0x66, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b,
-0x66, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x7a, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x3b, 0x53, 0x68, 0x69,
-0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c,
-0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x68, 0x69,
-0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x7a, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0x69,
-0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69,
-0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x68, 0x69,
-0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x7a, 0x61, 0x20, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x3b, 0x73, 0x76, 0x65, 0x6e,
-0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x61, 0x3b, 0x3b, 0x73, 0x76, 0x65, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f,
-0x6e, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x76, 0x65, 0x6e, 0x73, 0x6b, 0x61, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x6f, 0x72,
-0x3b, 0xb87, 0xba8, 0xbcd, 0xba4, 0xbbf, 0xbaf, 0x20, 0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0x3b, 0x3b, 0xb87, 0xba8, 0xbcd, 0xba4,
-0xbbf, 0xbaf, 0x20, 0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0x3b, 0x3b, 0x3b, 0x3b, 0xb87, 0xba8, 0xbcd, 0xba4, 0xbbf, 0xbaf, 0x20,
-0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0xb95, 0xbb3, 0xbcd, 0x3b, 0xbae, 0xbb2, 0xbc7, 0xbb7, 0xbbf, 0xbaf, 0xba9, 0xbcd, 0x20, 0xbb0,
-0xbbf, 0xb99, 0xbcd, 0xb95, 0xbbf, 0xb9f, 0xbcd, 0x3b, 0x3b, 0xbae, 0xbb2, 0xbc7, 0xbb7, 0xbbf, 0xbaf, 0xba9, 0xbcd, 0x20, 0xbb0, 0xbbf,
-0xb99, 0xbcd, 0xb95, 0xbbf, 0xb9f, 0xbcd, 0x3b, 0x3b, 0x3b, 0x3b, 0xbae, 0xbb2, 0xbc7, 0xbb7, 0xbbf, 0xbaf, 0xba9, 0xbcd, 0x20, 0xbb0,
-0xbbf, 0xb99, 0xbcd, 0xb95, 0xbbf, 0xb9f, 0xbcd, 0xb95, 0xbb3, 0xbcd, 0x3b, 0xb9a, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbaa, 0xbcd, 0xbaa, 0xbc2,
-0xbb0, 0xbcd, 0x20, 0xb9f, 0xbbe, 0xbb2, 0xbb0, 0xbcd, 0x3b, 0x3b, 0xb9a, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbaa, 0xbcd, 0xbaa, 0xbc2, 0xbb0,
-0xbcd, 0x20, 0xb9f, 0xbbe, 0xbb2, 0xbb0, 0xbcd, 0x3b, 0x3b, 0x3b, 0x3b, 0xb9a, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbaa, 0xbcd, 0xbaa, 0xbc2,
-0xbb0, 0xbcd, 0x20, 0xb9f, 0xbbe, 0xbb2, 0xbb0, 0xbcd, 0xb95, 0xbb3, 0xbcd, 0x3b, 0xb87, 0xbb2, 0xb99, 0xbcd, 0xb95, 0xbc8, 0x20, 0xbb0,
-0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0x3b, 0x3b, 0xb87, 0xbb2, 0xb99, 0xbcd, 0xb95, 0xbc8, 0x20, 0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd,
-0x3b, 0x3b, 0x3b, 0x3b, 0xb87, 0xbb2, 0xb99, 0xbcd, 0xb95, 0xbc8, 0x20, 0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0xb95, 0xbb3, 0xbcd,
-0x3b, 0xc30, 0xc42, 0xc2a, 0xc3e, 0xc2f, 0xc3f, 0x3b, 0x3b, 0xc30, 0xc42, 0xc2a, 0xc3e, 0xc2f, 0xc3f, 0x3b, 0x3b, 0x3b, 0x3b, 0xc30,
-0xc42, 0xc2a, 0xc3e, 0xc2f, 0xc32, 0xc41, 0x3b, 0xe1a, 0xe32, 0xe17, 0xe44, 0xe17, 0xe22, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xe1a,
-0xe32, 0xe17, 0xe44, 0xe17, 0xe22, 0x3b, 0xf61, 0xf74, 0xf0b, 0xf68, 0xf53, 0xf0b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xf62,
-0xf92, 0xfb1, 0xf0b, 0xf42, 0xf62, 0xf0b, 0xf66, 0xf92, 0xf7c, 0xf62, 0xf0b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x12e8, 0x12a2,
-0x1275, 0x12ee, 0x1335, 0x12eb, 0x20, 0x1265, 0x122d, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x50, 0x61, 0x2bb, 0x61, 0x6e, 0x67,
-0x61, 0x20, 0x66, 0x61, 0x6b, 0x61, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x50, 0x61, 0x2bb,
-0x61, 0x6e, 0x67, 0x61, 0x20, 0x66, 0x61, 0x6b, 0x61, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x3b, 0x54, 0xfc, 0x72, 0x6b, 0x20,
-0x4c, 0x69, 0x72, 0x61, 0x73, 0x131, 0x3b, 0x3b, 0x54, 0xfc, 0x72, 0x6b, 0x20, 0x6c, 0x69, 0x72, 0x61, 0x73, 0x131, 0x3b,
-0x3b, 0x3b, 0x3b, 0x54, 0xfc, 0x72, 0x6b, 0x20, 0x6c, 0x69, 0x72, 0x61, 0x73, 0x131, 0x3b, 0x54, 0xfc, 0x72, 0x6b, 0x6d,
-0x65, 0x6e, 0x20, 0x6d, 0x61, 0x6e, 0x61, 0x74, 0x79, 0x3b, 0x3b, 0x74, 0xfc, 0x72, 0x6b, 0x6d, 0x65, 0x6e, 0x20, 0x6d,
-0x61, 0x6e, 0x61, 0x74, 0x79, 0x3b, 0x3b, 0x3b, 0x3b, 0x74, 0xfc, 0x72, 0x6b, 0x6d, 0x65, 0x6e, 0x20, 0x6d, 0x61, 0x6e,
-0x61, 0x74, 0x79, 0x3b, 0x62c, 0x6c7, 0x6ad, 0x6af, 0x648, 0x20, 0x64a, 0x6c8, 0x6d5, 0x646, 0x649, 0x3b, 0x3b, 0x62c, 0x6c7, 0x6ad,
-0x6af, 0x648, 0x20, 0x64a, 0x6c8, 0x6d5, 0x646, 0x649, 0x3b, 0x3b, 0x3b, 0x3b, 0x62c, 0x6c7, 0x6ad, 0x6af, 0x648, 0x20, 0x64a, 0x6c8,
-0x6d5, 0x646, 0x649, 0x3b, 0x443, 0x43a, 0x440, 0x430, 0x457, 0x43d, 0x441, 0x44c, 0x43a, 0x430, 0x20, 0x433, 0x440, 0x438, 0x432, 0x43d,
-0x44f, 0x3b, 0x3b, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x44f, 0x3b, 0x3b, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x456, 0x3b, 0x433, 0x440,
-0x438, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x456, 0x3b, 0x67e, 0x627, 0x6a9, 0x633, 0x62a, 0x627, 0x646,
-0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6cc, 0x6c1, 0x3b, 0x3b, 0x67e, 0x627, 0x6a9, 0x633, 0x62a, 0x627, 0x646, 0x6cc, 0x20, 0x631, 0x648,
-0x67e, 0x6cc, 0x6c1, 0x3b, 0x3b, 0x3b, 0x3b, 0x67e, 0x627, 0x6a9, 0x633, 0x62a, 0x627, 0x646, 0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6cc,
-0x6c1, 0x3b, 0x628, 0x6be, 0x627, 0x631, 0x62a, 0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6cc, 0x6c1, 0x3b, 0x3b, 0x628, 0x6be, 0x627, 0x631,
-0x62a, 0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6cc, 0x6c1, 0x3b, 0x3b, 0x3b, 0x3b, 0x628, 0x6be, 0x627, 0x631, 0x62a, 0x6cc, 0x20, 0x631,
-0x648, 0x67e, 0x6d2, 0x3b, 0x4f, 0x2018, 0x7a, 0x62, 0x65, 0x6b, 0x69, 0x73, 0x74, 0x6f, 0x6e, 0x20, 0x73, 0x6f, 0x2018, 0x6d,
-0x69, 0x3b, 0x3b, 0x4f, 0x2018, 0x7a, 0x62, 0x65, 0x6b, 0x69, 0x73, 0x74, 0x6f, 0x6e, 0x20, 0x73, 0x6f, 0x2018, 0x6d, 0x69,
-0x3b, 0x3b, 0x3b, 0x3b, 0x4f, 0x2018, 0x7a, 0x62, 0x65, 0x6b, 0x69, 0x73, 0x74, 0x6f, 0x6e, 0x20, 0x73, 0x6f, 0x2018, 0x6d,
-0x69, 0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cc, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x40e, 0x437, 0x431, 0x435, 0x43a,
-0x438, 0x441, 0x442, 0x43e, 0x43d, 0x20, 0x441, 0x45e, 0x43c, 0x3b, 0x3b, 0x40e, 0x437, 0x431, 0x435, 0x43a, 0x438, 0x441, 0x442, 0x43e,
-0x43d, 0x20, 0x441, 0x45e, 0x43c, 0x3b, 0x3b, 0x3b, 0x3b, 0x40e, 0x437, 0x431, 0x435, 0x43a, 0x438, 0x441, 0x442, 0x43e, 0x43d, 0x20,
-0x441, 0x45e, 0x43c, 0x3b, 0x110, 0x1ed3, 0x6e, 0x67, 0x20, 0x56, 0x69, 0x1ec7, 0x74, 0x20, 0x4e, 0x61, 0x6d, 0x3b, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x110, 0x1ed3, 0x6e, 0x67, 0x20, 0x56, 0x69, 0x1ec7, 0x74, 0x20, 0x4e, 0x61, 0x6d, 0x3b, 0x50, 0x75, 0x6e,
-0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x70, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61,
-0x69, 0x6e, 0x3b, 0x62, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x62, 0x75, 0x6e, 0x74,
-0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x70, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69,
-0x6e, 0x3b, 0x70, 0x68, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x70, 0x75, 0x6e, 0x74,
-0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x4e, 0x61, 0x69, 0x72, 0x61, 0x20, 0x74, 0x69, 0x20, 0x4f, 0x72,
-0xed, 0x6c, 0x1eb9, 0x301, 0xe8, 0x64, 0x65, 0x20, 0x4e, 0xe0, 0xec, 0x6a, 0xed, 0x72, 0xed, 0xe0, 0x3b, 0x3b, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x46, 0x61, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x20, 0x74, 0x69, 0x20, 0x4f, 0x72, 0xed, 0x6c, 0x25b, 0x301,
-0xe8, 0x64, 0x65, 0x20, 0x42, 0x49, 0x4b, 0x45, 0x41, 0x4f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x69, 0x2d, 0x53,
-0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x52, 0x61, 0x6e, 0x64, 0x3b, 0x3b, 0x69,
-0x2d, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x52, 0x61, 0x6e, 0x64, 0x3b,
-0x3b, 0x3b, 0x3b, 0x69, 0x2d, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x52,
-0x61, 0x6e, 0x64, 0x3b, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x6e, 0x6f, 0x72,
-0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x65, 0x20, 0x6b,
-0x72, 0x6f, 0x6e, 0x65, 0x72, 0x3b, 0x42, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67,
-0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x61, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61,
-0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x68, 0x65, 0x72, 0x63,
-0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x61, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c,
-0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x68, 0x65,
-0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x65, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62,
-0x69, 0x6c, 0x6e, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f,
-0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x69, 0x68, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72,
-0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x69, 0x68, 0x20, 0x6d, 0x61, 0x72, 0x61, 0x6b, 0x61, 0x3b, 0x41a, 0x43e, 0x43d, 0x432,
-0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x430, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x430, 0x3b, 0x3b, 0x431, 0x43e, 0x441,
-0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x430, 0x20, 0x43a,
-0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x430, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x430, 0x3b, 0x3b,
-0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a,
-0x435, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x435, 0x20, 0x43c, 0x430, 0x440, 0x43a,
-0x3b, 0x3b, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430,
-0x447, 0x43a, 0x438, 0x445, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x438, 0x445, 0x20,
-0x43c, 0x430, 0x440, 0x430, 0x43a, 0x430, 0x3b, 0x47, 0x68, 0x61, 0x6e, 0x61, 0x20, 0x53, 0x69, 0x64, 0x69, 0x3b, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x61, 0x1ecb, 0x72, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x69, 0x6c, 0x69,
-0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x67,
-0x68, 0x61, 0x6e, 0x61, 0x20, 0x73, 0x69, 0x256, 0x69, 0x3b, 0x3b, 0x67, 0x68, 0x61, 0x6e, 0x61, 0x20, 0x73, 0x69, 0x256,
-0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x67, 0x68, 0x61, 0x6e, 0x61, 0x20, 0x73, 0x69, 0x256, 0x69, 0x3b, 0x263, 0x65, 0x74, 0x6f,
-0x256, 0x6f, 0x66, 0x65, 0x20, 0x61, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x67, 0x61, 0x20, 0x43, 0x46, 0x41, 0x20, 0x66, 0x72,
-0x61, 0x6e, 0x63, 0x20, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x3b, 0x3b, 0x263, 0x65, 0x74, 0x6f, 0x256, 0x6f, 0x66, 0x65, 0x20,
+0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x43, 0x61, 0x79, 0x6d, 0x61, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73,
+0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c, 0x61, 0x6e, 0x64,
+0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c, 0x61, 0x6e, 0x64,
+0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c, 0x61,
+0x6e, 0x64, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x44, 0x61, 0x6e, 0x69, 0x73, 0x68, 0x20, 0x4b, 0x72,
+0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x44, 0x61, 0x6e, 0x69, 0x73, 0x68, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x3b,
+0x3b, 0x44, 0x61, 0x6e, 0x69, 0x73, 0x68, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x72, 0x3b, 0x45, 0x72, 0x69, 0x74, 0x72,
+0x65, 0x61, 0x6e, 0x20, 0x4e, 0x61, 0x6b, 0x66, 0x61, 0x3b, 0x3b, 0x45, 0x72, 0x69, 0x74, 0x72, 0x65, 0x61, 0x6e, 0x20,
+0x6e, 0x61, 0x6b, 0x66, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x72, 0x69, 0x74, 0x72, 0x65, 0x61, 0x6e, 0x20, 0x6e, 0x61,
+0x6b, 0x66, 0x61, 0x73, 0x3b, 0x46, 0x61, 0x6c, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64,
+0x73, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x46, 0x61, 0x6c, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x73,
+0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x61, 0x6c, 0x6b, 0x6c,
+0x61, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x3b, 0x46,
+0x69, 0x6a, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x46, 0x69, 0x6a, 0x69, 0x61, 0x6e,
+0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x69, 0x6a, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f,
+0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x55, 0x4b, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x55, 0x4b, 0x20, 0x70,
+0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x55, 0x4b, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x3b, 0x47, 0x61,
+0x6d, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x61, 0x6c, 0x61, 0x73, 0x69, 0x3b, 0x3b, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x61,
+0x6e, 0x20, 0x64, 0x61, 0x6c, 0x61, 0x73, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x20,
+0x64, 0x61, 0x6c, 0x61, 0x73, 0x69, 0x73, 0x3b, 0x47, 0x68, 0x61, 0x6e, 0x61, 0x69, 0x61, 0x6e, 0x20, 0x43, 0x65, 0x64,
+0x69, 0x3b, 0x3b, 0x47, 0x68, 0x61, 0x6e, 0x61, 0x69, 0x61, 0x6e, 0x20, 0x63, 0x65, 0x64, 0x69, 0x3b, 0x3b, 0x3b, 0x3b,
+0x47, 0x68, 0x61, 0x6e, 0x61, 0x69, 0x61, 0x6e, 0x20, 0x63, 0x65, 0x64, 0x69, 0x73, 0x3b, 0x47, 0x69, 0x62, 0x72, 0x61,
+0x6c, 0x74, 0x61, 0x72, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x47, 0x69, 0x62, 0x72, 0x61, 0x6c, 0x74, 0x61,
+0x72, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x47, 0x69, 0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72,
+0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x3b, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x65, 0x73, 0x65, 0x20, 0x44, 0x6f,
+0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x65, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c,
+0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x65, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c,
+0x61, 0x72, 0x73, 0x3b, 0x48, 0x6f, 0x6e, 0x67, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
+0x3b, 0x3b, 0x48, 0x6f, 0x6e, 0x67, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b,
+0x3b, 0x3b, 0x48, 0x6f, 0x6e, 0x67, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b,
+0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x52, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e,
+0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x75, 0x70,
+0x65, 0x65, 0x73, 0x3b, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x69, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x53, 0x68, 0x65, 0x6b,
+0x65, 0x6c, 0x3b, 0x3b, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x69, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x73, 0x68, 0x65, 0x6b,
+0x65, 0x6c, 0x3b, 0x3b, 0x3b, 0x3b, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x69, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x73, 0x68,
+0x65, 0x6b, 0x65, 0x6c, 0x73, 0x3b, 0x4a, 0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61,
+0x72, 0x3b, 0x3b, 0x4a, 0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b,
+0x3b, 0x3b, 0x4a, 0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x4b,
+0x65, 0x6e, 0x79, 0x61, 0x6e, 0x20, 0x53, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x4b, 0x65, 0x6e, 0x79,
+0x61, 0x6e, 0x20, 0x73, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x3b, 0x3b, 0x4b, 0x65, 0x6e, 0x79, 0x61,
+0x6e, 0x20, 0x73, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x3b, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66,
+0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x52, 0x61, 0x6e, 0x64, 0x3b, 0x3b, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66,
+0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x72, 0x61, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20,
+0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x72, 0x61, 0x6e, 0x64, 0x3b, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x69, 0x61,
+0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x64,
+0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f,
+0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x4d, 0x61, 0x63, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x50, 0x61, 0x74, 0x61, 0x63,
+0x61, 0x3b, 0x3b, 0x4d, 0x61, 0x63, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x70, 0x61, 0x74, 0x61, 0x63, 0x61, 0x3b, 0x3b,
+0x3b, 0x3b, 0x4d, 0x61, 0x63, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x70, 0x61, 0x74, 0x61, 0x63, 0x61, 0x73, 0x3b, 0x4d,
+0x61, 0x6c, 0x61, 0x67, 0x61, 0x73, 0x79, 0x20, 0x41, 0x72, 0x69, 0x61, 0x72, 0x79, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61,
+0x67, 0x61, 0x73, 0x79, 0x20, 0x61, 0x72, 0x69, 0x61, 0x72, 0x79, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x67,
+0x61, 0x73, 0x79, 0x20, 0x61, 0x72, 0x69, 0x61, 0x72, 0x69, 0x65, 0x73, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x77, 0x69, 0x61,
+0x6e, 0x20, 0x4b, 0x77, 0x61, 0x63, 0x68, 0x61, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x77, 0x69, 0x61, 0x6e, 0x20, 0x6b,
+0x77, 0x61, 0x63, 0x68, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x77, 0x69, 0x61, 0x6e, 0x20, 0x6b, 0x77,
+0x61, 0x63, 0x68, 0x61, 0x73, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x52, 0x69, 0x6e, 0x67,
+0x67, 0x69, 0x74, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x69, 0x6e, 0x67, 0x67,
+0x69, 0x74, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x69, 0x6e, 0x67,
+0x67, 0x69, 0x74, 0x73, 0x3b, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x61, 0x6e, 0x20, 0x52, 0x75, 0x70, 0x65, 0x65,
+0x3b, 0x3b, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x3b,
+0x3b, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x73, 0x3b, 0x4e, 0x61,
+0x6d, 0x69, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x4e, 0x61, 0x6d, 0x69, 0x62,
+0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69,
+0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20,
+0x4e, 0x61, 0x69, 0x72, 0x61, 0x3b, 0x3b, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x6e, 0x61, 0x69, 0x72,
+0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x6e, 0x61, 0x69, 0x72, 0x61, 0x73,
+0x3b, 0x50, 0x61, 0x6b, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x69, 0x20, 0x52, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x50, 0x61,
+0x6b, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x69, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x50, 0x61, 0x6b,
+0x69, 0x73, 0x74, 0x61, 0x6e, 0x69, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x73, 0x3b, 0x50, 0x61, 0x70, 0x75, 0x61, 0x20,
+0x4e, 0x65, 0x77, 0x20, 0x47, 0x75, 0x69, 0x6e, 0x65, 0x61, 0x6e, 0x20, 0x4b, 0x69, 0x6e, 0x61, 0x3b, 0x3b, 0x50, 0x61,
+0x70, 0x75, 0x61, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x47, 0x75, 0x69, 0x6e, 0x65, 0x61, 0x6e, 0x20, 0x6b, 0x69, 0x6e, 0x61,
+0x3b, 0x3b, 0x3b, 0x3b, 0x50, 0x61, 0x70, 0x75, 0x61, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x47, 0x75, 0x69, 0x6e, 0x65, 0x61,
+0x6e, 0x20, 0x6b, 0x69, 0x6e, 0x61, 0x3b, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x20, 0x50, 0x69,
+0x73, 0x6f, 0x3b, 0x3b, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x20, 0x70, 0x69, 0x73, 0x6f, 0x3b,
+0x3b, 0x3b, 0x3b, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x20, 0x70, 0x69, 0x73, 0x6f, 0x73, 0x3b,
+0x52, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x6e, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x52, 0x77, 0x61, 0x6e, 0x64,
+0x61, 0x6e, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x3b, 0x3b, 0x52, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x6e, 0x20,
+0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x3b, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x6e, 0x20, 0x54, 0x61, 0x6c, 0x61, 0x3b, 0x3b,
+0x53, 0x61, 0x6d, 0x6f, 0x61, 0x6e, 0x20, 0x74, 0x61, 0x6c, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x61, 0x6d, 0x6f, 0x61,
+0x6e, 0x20, 0x74, 0x61, 0x6c, 0x61, 0x3b, 0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x69, 0x73, 0x20, 0x52,
+0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x69, 0x73, 0x20, 0x72, 0x75,
+0x70, 0x65, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x69, 0x73, 0x20, 0x72,
+0x75, 0x70, 0x65, 0x65, 0x73, 0x3b, 0x53, 0x69, 0x65, 0x72, 0x72, 0x61, 0x20, 0x4c, 0x65, 0x6f, 0x6e, 0x65, 0x61, 0x6e,
+0x20, 0x4c, 0x65, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x53, 0x69, 0x65, 0x72, 0x72, 0x61, 0x20, 0x4c, 0x65, 0x6f, 0x6e, 0x65,
+0x61, 0x6e, 0x20, 0x6c, 0x65, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x69, 0x65, 0x72, 0x72, 0x61, 0x20, 0x4c,
+0x65, 0x6f, 0x6e, 0x65, 0x61, 0x6e, 0x20, 0x6c, 0x65, 0x6f, 0x6e, 0x65, 0x73, 0x3b, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70,
+0x6f, 0x72, 0x65, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72,
+0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72,
+0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x53, 0x6f, 0x6c, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x49, 0x73,
+0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x53, 0x6f, 0x6c, 0x6f, 0x6d, 0x6f,
+0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b,
+0x53, 0x6f, 0x6c, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x64, 0x6f, 0x6c, 0x6c,
+0x61, 0x72, 0x73, 0x3b, 0x53, 0x74, 0x2e, 0x20, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64,
+0x3b, 0x3b, 0x53, 0x74, 0x2e, 0x20, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b,
+0x3b, 0x3b, 0x53, 0x74, 0x2e, 0x20, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x3b,
+0x53, 0x75, 0x64, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x53, 0x75, 0x64, 0x61,
+0x6e, 0x65, 0x73, 0x65, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x65,
+0x73, 0x65, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x3b, 0x53, 0x77, 0x61, 0x7a, 0x69, 0x20, 0x4c, 0x69, 0x6c, 0x61,
+0x6e, 0x67, 0x65, 0x6e, 0x69, 0x3b, 0x3b, 0x53, 0x77, 0x61, 0x7a, 0x69, 0x20, 0x6c, 0x69, 0x6c, 0x61, 0x6e, 0x67, 0x65,
+0x6e, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x77, 0x61, 0x7a, 0x69, 0x20, 0x65, 0x6d, 0x61, 0x6c, 0x61, 0x6e, 0x67, 0x65,
+0x6e, 0x69, 0x3b, 0x53, 0x77, 0x65, 0x64, 0x69, 0x73, 0x68, 0x20, 0x4b, 0x72, 0x6f, 0x6e, 0x61, 0x3b, 0x3b, 0x53, 0x77,
+0x65, 0x64, 0x69, 0x73, 0x68, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x77, 0x65, 0x64, 0x69,
+0x73, 0x68, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x6f, 0x72, 0x3b, 0x53, 0x77, 0x69, 0x73, 0x73, 0x20, 0x46, 0x72, 0x61, 0x6e,
+0x63, 0x3b, 0x3b, 0x53, 0x77, 0x69, 0x73, 0x73, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x77,
+0x69, 0x73, 0x73, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x3b, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x6e,
+0x20, 0x53, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x6e,
+0x20, 0x73, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x3b, 0x3b, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69,
+0x61, 0x6e, 0x20, 0x73, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x3b, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x6e, 0x20,
+0x50, 0x61, 0x2bb, 0x61, 0x6e, 0x67, 0x61, 0x3b, 0x3b, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x6e, 0x20, 0x70, 0x61, 0x2bb, 0x61,
+0x6e, 0x67, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x6e, 0x20, 0x70, 0x61, 0x2bb, 0x61, 0x6e, 0x67,
+0x61, 0x3b, 0x54, 0x72, 0x69, 0x6e, 0x69, 0x64, 0x61, 0x64, 0x20, 0x26, 0x20, 0x54, 0x6f, 0x62, 0x61, 0x67, 0x6f, 0x20,
+0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x54, 0x72, 0x69, 0x6e, 0x69, 0x64, 0x61, 0x64, 0x20, 0x26, 0x20, 0x54,
+0x6f, 0x62, 0x61, 0x67, 0x6f, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x54, 0x72, 0x69, 0x6e,
+0x69, 0x64, 0x61, 0x64, 0x20, 0x26, 0x20, 0x54, 0x6f, 0x62, 0x61, 0x67, 0x6f, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
+0x73, 0x3b, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x6e, 0x20, 0x53, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b,
+0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x6e, 0x20, 0x73, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x3b, 0x3b,
+0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x6e, 0x20, 0x73, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x3b, 0x42, 0x72,
+0x69, 0x74, 0x69, 0x73, 0x68, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68,
+0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68, 0x20, 0x70, 0x6f,
+0x75, 0x6e, 0x64, 0x73, 0x3b, 0x56, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x20, 0x56, 0x61, 0x74, 0x75, 0x3b, 0x3b, 0x56,
+0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x20, 0x76, 0x61, 0x74, 0x75, 0x3b, 0x3b, 0x3b, 0x3b, 0x56, 0x61, 0x6e, 0x75, 0x61,
+0x74, 0x75, 0x20, 0x76, 0x61, 0x74, 0x75, 0x73, 0x3b, 0x5a, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x4b, 0x77, 0x61,
+0x63, 0x68, 0x61, 0x3b, 0x3b, 0x5a, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x6b, 0x77, 0x61, 0x63, 0x68, 0x61, 0x3b,
+0x3b, 0x3b, 0x3b, 0x5a, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x6b, 0x77, 0x61, 0x63, 0x68, 0x61, 0x73, 0x3b, 0x53,
+0x6f, 0x75, 0x74, 0x68, 0x20, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b,
+0x3b, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x70, 0x6f, 0x75, 0x6e,
+0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20,
+0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x3b, 0x4e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x41,
+0x6e, 0x74, 0x69, 0x6c, 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x47, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x3b, 0x3b, 0x4e, 0x65,
+0x74, 0x68, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x41, 0x6e, 0x74, 0x69, 0x6c, 0x6c, 0x65, 0x61, 0x6e, 0x20,
+0x67, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6c, 0x61, 0x6e,
+0x64, 0x73, 0x20, 0x41, 0x6e, 0x74, 0x69, 0x6c, 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x67, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72,
+0x73, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f,
+0x74, 0x3b, 0x64, 0x6f, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0xf3, 0x6e, 0x61, 0x3b, 0x3b, 0x64, 0x6f, 0x6e, 0x73, 0x6b,
+0x20, 0x6b, 0x72, 0xf3, 0x6e, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x61, 0x6e, 0x73, 0x6b, 0x61, 0x72, 0x20, 0x6b, 0x72,
+0xf3, 0x6e, 0x75, 0x72, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65,
+0x75, 0x72, 0x6f, 0x61, 0x3b, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x61, 0x6c, 0x67, 0xe9, 0x72, 0x69, 0x65, 0x6e, 0x3b,
+0x3b, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x61, 0x6c, 0x67, 0xe9, 0x72, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x64,
+0x69, 0x6e, 0x61, 0x72, 0x73, 0x20, 0x61, 0x6c, 0x67, 0xe9, 0x72, 0x69, 0x65, 0x6e, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e,
+0x63, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63,
+0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e,
+0x63, 0x73, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63,
+0x20, 0x62, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x61, 0x69, 0x73, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x62, 0x75,
+0x72, 0x75, 0x6e, 0x64, 0x61, 0x69, 0x73, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x62, 0x75,
+0x72, 0x75, 0x6e, 0x64, 0x61, 0x69, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42,
+0x45, 0x41, 0x43, 0x29, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41,
+0x43, 0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45,
+0x41, 0x43, 0x29, 0x3b, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x20, 0x63, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x3b,
+0x3b, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x20, 0x63, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b,
+0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x73, 0x3b, 0x66, 0x72,
+0x61, 0x6e, 0x63, 0x20, 0x63, 0x6f, 0x6d, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20,
+0x63, 0x6f, 0x6d, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x63,
+0x6f, 0x6d, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x63, 0x6f, 0x6e, 0x67, 0x6f,
+0x6c, 0x61, 0x69, 0x73, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x63, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x69,
+0x73, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x69,
+0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x64, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x65, 0x6e, 0x3b, 0x3b,
+0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x64, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b,
+0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x64, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x65, 0x6e, 0x73, 0x3b, 0x66,
+0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x50, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x50, 0x3b,
+0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x43, 0x46, 0x50, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20,
+0x67, 0x75, 0x69, 0x6e, 0xe9, 0x65, 0x6e, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x67, 0x75, 0x69, 0x6e, 0xe9,
+0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x67, 0x75, 0x69, 0x6e, 0xe9, 0x65, 0x6e,
+0x73, 0x3b, 0x67, 0x6f, 0x75, 0x72, 0x64, 0x65, 0x20, 0x68, 0x61, 0xef, 0x74, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b,
+0x67, 0x6f, 0x75, 0x72, 0x64, 0x65, 0x20, 0x68, 0x61, 0xef, 0x74, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b,
+0x67, 0x6f, 0x75, 0x72, 0x64, 0x65, 0x73, 0x20, 0x68, 0x61, 0xef, 0x74, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x73, 0x3b, 0x61,
+0x72, 0x69, 0x61, 0x72, 0x79, 0x20, 0x6d, 0x61, 0x6c, 0x67, 0x61, 0x63, 0x68, 0x65, 0x3b, 0x3b, 0x61, 0x72, 0x69, 0x61,
+0x72, 0x79, 0x20, 0x6d, 0x61, 0x6c, 0x67, 0x61, 0x63, 0x68, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x61, 0x72, 0x69, 0x61, 0x72,
+0x79, 0x73, 0x20, 0x6d, 0x61, 0x6c, 0x67, 0x61, 0x63, 0x68, 0x65, 0x73, 0x3b, 0x6f, 0x75, 0x67, 0x75, 0x69, 0x79, 0x61,
+0x20, 0x6d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x6f, 0x75, 0x67, 0x75, 0x69, 0x79,
+0x61, 0x20, 0x6d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x6f, 0x75, 0x67,
+0x75, 0x69, 0x79, 0x61, 0x73, 0x20, 0x6d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x65, 0x6e, 0x73, 0x3b, 0x72,
+0x6f, 0x75, 0x70, 0x69, 0x65, 0x20, 0x6d, 0x61, 0x75, 0x72, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x72,
+0x6f, 0x75, 0x70, 0x69, 0x65, 0x20, 0x6d, 0x61, 0x75, 0x72, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x3b,
+0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x65, 0x73, 0x20, 0x6d, 0x61, 0x75, 0x72, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x6e, 0x65,
+0x73, 0x3b, 0x64, 0x69, 0x72, 0x68, 0x61, 0x6d, 0x20, 0x6d, 0x61, 0x72, 0x6f, 0x63, 0x61, 0x69, 0x6e, 0x3b, 0x3b, 0x64,
+0x69, 0x72, 0x68, 0x61, 0x6d, 0x20, 0x6d, 0x61, 0x72, 0x6f, 0x63, 0x61, 0x69, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x69,
+0x72, 0x68, 0x61, 0x6d, 0x73, 0x20, 0x6d, 0x61, 0x72, 0x6f, 0x63, 0x61, 0x69, 0x6e, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e,
+0x63, 0x20, 0x72, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x69, 0x73, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x72, 0x77,
+0x61, 0x6e, 0x64, 0x61, 0x69, 0x73, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x72, 0x77, 0x61,
+0x6e, 0x64, 0x61, 0x69, 0x73, 0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x65, 0x20, 0x64, 0x65, 0x73, 0x20, 0x53, 0x65, 0x79,
+0x63, 0x68, 0x65, 0x6c, 0x6c, 0x65, 0x73, 0x3b, 0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x65, 0x20, 0x64, 0x65, 0x73, 0x20,
+0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x65, 0x73, 0x3b, 0x3b, 0x3b, 0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x65,
+0x73, 0x20, 0x64, 0x65, 0x73, 0x20, 0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x65, 0x73, 0x3b, 0x66, 0x72, 0x61,
+0x6e, 0x63, 0x20, 0x73, 0x75, 0x69, 0x73, 0x73, 0x65, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x73, 0x75, 0x69,
+0x73, 0x73, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x73, 0x75, 0x69, 0x73, 0x73, 0x65,
+0x73, 0x3b, 0x6c, 0x69, 0x76, 0x72, 0x65, 0x20, 0x73, 0x79, 0x72, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x6c, 0x69,
+0x76, 0x72, 0x65, 0x20, 0x73, 0x79, 0x72, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x6c, 0x69, 0x76, 0x72,
+0x65, 0x73, 0x20, 0x73, 0x79, 0x72, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x73, 0x3b, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x74,
+0x75, 0x6e, 0x69, 0x73, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x74, 0x75, 0x6e, 0x69, 0x73,
+0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x73, 0x20, 0x74, 0x75, 0x6e, 0x69, 0x73, 0x69,
+0x65, 0x6e, 0x73, 0x3b, 0x76, 0x61, 0x74, 0x75, 0x20, 0x76, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x61, 0x6e, 0x3b, 0x3b,
+0x76, 0x61, 0x74, 0x75, 0x20, 0x76, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x61, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x76, 0x61,
+0x74, 0x75, 0x73, 0x20, 0x76, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x61, 0x6e, 0x73, 0x3b, 0x50, 0x75, 0x6e, 0x6e, 0x64,
+0x20, 0x53, 0x61, 0x73, 0x61, 0x6e, 0x6e, 0x61, 0x63, 0x68, 0x3b, 0x3b, 0x70, 0x68, 0x75, 0x6e, 0x6e, 0x64, 0x20, 0x53,
+0x61, 0x73, 0x61, 0x6e, 0x6e, 0x61, 0x63, 0x68, 0x3b, 0x70, 0x68, 0x75, 0x6e, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x73, 0x61,
+0x6e, 0x6e, 0x61, 0x63, 0x68, 0x3b, 0x70, 0x75, 0x69, 0x6e, 0x6e, 0x64, 0x20, 0x53, 0x68, 0x61, 0x73, 0x61, 0x6e, 0x6e,
+0x61, 0x63, 0x68, 0x3b, 0x3b, 0x70, 0x75, 0x6e, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x73, 0x61, 0x6e, 0x6e, 0x61, 0x63, 0x68,
+0x3b, 0x10e5, 0x10d0, 0x10e0, 0x10d7, 0x10e3, 0x10da, 0x10d8, 0x20, 0x10da, 0x10d0, 0x10e0, 0x10d8, 0x3b, 0x3b, 0x10e5, 0x10d0, 0x10e0, 0x10d7, 0x10e3,
+0x10da, 0x10d8, 0x20, 0x10da, 0x10d0, 0x10e0, 0x10d8, 0x3b, 0x3b, 0x3b, 0x3b, 0x10e5, 0x10d0, 0x10e0, 0x10d7, 0x10e3, 0x10da, 0x10d8, 0x20, 0x10da,
+0x10d0, 0x10e0, 0x10d8, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x75,
+0x72, 0x6f, 0x3b, 0x53, 0x63, 0x68, 0x77, 0x65, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x6e,
+0x3b, 0x3b, 0x53, 0x63, 0x68, 0x77, 0x65, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x6e, 0x3b,
+0x3b, 0x3b, 0x3b, 0x53, 0x63, 0x68, 0x77, 0x65, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x6e,
+0x3b, 0x395, 0x3c5, 0x3c1, 0x3ce, 0x3b, 0x3b, 0x3b5, 0x3c5, 0x3c1, 0x3ce, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b5, 0x3c5, 0x3c1, 0x3ce, 0x3b,
+0x64, 0x61, 0x6e, 0x6d, 0x61, 0x72, 0x6b, 0x69, 0x6d, 0x75, 0x74, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x75, 0x6e, 0x69, 0x3b,
+0x3b, 0x64, 0x61, 0x6e, 0x73, 0x6b, 0x69, 0x6e, 0x75, 0x74, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x3b,
+0x3b, 0x3b, 0x64, 0x61, 0x6e, 0x6d, 0x61, 0x72, 0x6b, 0x69, 0x6d, 0x75, 0x74, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x75, 0x6e,
+0x69, 0x3b, 0xaad, 0xabe, 0xab0, 0xaa4, 0xac0, 0xaaf, 0x20, 0xab0, 0xac2, 0xaaa, 0xabf, 0xaaf, 0xabe, 0x3b, 0x3b, 0xaad, 0xabe, 0xab0,
+0xaa4, 0xac0, 0xaaf, 0x20, 0xab0, 0xac2, 0xaaa, 0xabf, 0xaaf, 0xabe, 0x3b, 0x3b, 0x3b, 0x3b, 0xaad, 0xabe, 0xab0, 0xaa4, 0xac0, 0xaaf,
+0x20, 0xab0, 0xac2, 0xaaa, 0xabf, 0xaaf, 0xabe, 0x3b, 0x4e, 0x61, 0x69, 0x72, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x4b, 0x75, 0x257, 0x69, 0x6e, 0x20, 0x53, 0x65, 0x66, 0x61, 0x20, 0x6e, 0x61, 0x20, 0x41, 0x66, 0x69, 0x72, 0x6b, 0x61,
+0x20, 0x54, 0x61, 0x20, 0x59, 0x61, 0x6d, 0x6d, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x5e9, 0x5e7, 0x5dc, 0x20,
+0x5d7, 0x5d3, 0x5e9, 0x3b, 0x3b, 0x5e9, 0x5e7, 0x5dc, 0x20, 0x5d7, 0x5d3, 0x5e9, 0x3b, 0x5e9, 0x5e7, 0x5dc, 0x5d9, 0x5dd, 0x20, 0x5d7,
+0x5d3, 0x5e9, 0x5d9, 0x5dd, 0x3b, 0x3b, 0x5e9, 0x5e7, 0x5dc, 0x5d9, 0x5dd, 0x20, 0x5d7, 0x5d3, 0x5e9, 0x5d9, 0x5dd, 0x3b, 0x5e9, 0x5e7,
+0x5dc, 0x5d9, 0x5dd, 0x20, 0x5d7, 0x5d3, 0x5e9, 0x5d9, 0x5dd, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x941, 0x92a,
+0x92f, 0x93e, 0x3b, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x941, 0x92a, 0x92f, 0x93e, 0x3b, 0x3b, 0x3b, 0x3b,
+0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x942, 0x92a, 0x90f, 0x3b, 0x6d, 0x61, 0x67, 0x79, 0x61, 0x72, 0x20, 0x66,
+0x6f, 0x72, 0x69, 0x6e, 0x74, 0x3b, 0x3b, 0x6d, 0x61, 0x67, 0x79, 0x61, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x69, 0x6e, 0x74,
+0x3b, 0x3b, 0x3b, 0x3b, 0x6d, 0x61, 0x67, 0x79, 0x61, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x69, 0x6e, 0x74, 0x3b, 0xed, 0x73,
+0x6c, 0x65, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0xf3, 0x6e, 0x61, 0x3b, 0x3b, 0xed, 0x73, 0x6c, 0x65, 0x6e, 0x73, 0x6b,
+0x20, 0x6b, 0x72, 0xf3, 0x6e, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0xed, 0x73, 0x6c, 0x65, 0x6e, 0x73, 0x6b, 0x61, 0x72, 0x20,
+0x6b, 0x72, 0xf3, 0x6e, 0x75, 0x72, 0x3b, 0x52, 0x75, 0x70, 0x69, 0x61, 0x68, 0x20, 0x49, 0x6e, 0x64, 0x6f, 0x6e, 0x65,
+0x73, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x52, 0x75, 0x70, 0x69, 0x61, 0x68, 0x20, 0x49, 0x6e, 0x64, 0x6f,
+0x6e, 0x65, 0x73, 0x69, 0x61, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72,
+0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72,
+0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x66, 0x72, 0x61, 0x6e,
+0x63, 0x6f, 0x20, 0x73, 0x76, 0x69, 0x7a, 0x7a, 0x65, 0x72, 0x6f, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20,
+0x73, 0x76, 0x69, 0x7a, 0x7a, 0x65, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x69, 0x20,
+0x73, 0x76, 0x69, 0x7a, 0x7a, 0x65, 0x72, 0x69, 0x3b, 0x65e5, 0x672c, 0x5186, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x5186, 0x3b,
+0xcad, 0xcbe, 0xcb0, 0xca4, 0xcc0, 0xcaf, 0x20, 0xcb0, 0xcc2, 0xcaa, 0xcbe, 0xcaf, 0xcbf, 0x3b, 0x3b, 0xcad, 0xcbe, 0xcb0, 0xca4, 0xcc0,
+0xcaf, 0x20, 0xcb0, 0xcc2, 0xcaa, 0xcbe, 0xcaf, 0xcbf, 0x3b, 0x3b, 0x3b, 0x3b, 0xcad, 0xcbe, 0xcb0, 0xca4, 0xcc0, 0xcaf, 0x20, 0xcb0,
+0xcc2, 0xcaa, 0xcbe, 0xcaf, 0xcbf, 0xc97, 0xcb3, 0xcc1, 0x3b, 0x6c1, 0x650, 0x646, 0x62f, 0x64f, 0x633, 0x62a, 0x672, 0x646, 0x6cd, 0x20,
+0x631, 0x6c4, 0x67e, 0x64e, 0x6d2, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x49a, 0x430, 0x437, 0x430, 0x49b, 0x441, 0x442, 0x430,
+0x43d, 0x20, 0x442, 0x435, 0x4a3, 0x433, 0x435, 0x441, 0x456, 0x3b, 0x3b, 0x49a, 0x430, 0x437, 0x430, 0x49b, 0x441, 0x442, 0x430, 0x43d,
+0x20, 0x442, 0x435, 0x4a3, 0x433, 0x435, 0x441, 0x456, 0x3b, 0x3b, 0x3b, 0x3b, 0x49a, 0x430, 0x437, 0x430, 0x49b, 0x441, 0x442, 0x430,
+0x43d, 0x20, 0x442, 0x435, 0x4a3, 0x433, 0x435, 0x441, 0x456, 0x3b, 0x41a, 0x44b, 0x440, 0x433, 0x44b, 0x437, 0x441, 0x442, 0x430, 0x43d,
+0x20, 0x441, 0x43e, 0x43c, 0x443, 0x3b, 0x3b, 0x41a, 0x44b, 0x440, 0x433, 0x44b, 0x437, 0x441, 0x442, 0x430, 0x43d, 0x20, 0x441, 0x43e,
+0x43c, 0x443, 0x3b, 0x3b, 0x3b, 0x3b, 0x41a, 0x44b, 0x440, 0x433, 0x44b, 0x437, 0x441, 0x442, 0x430, 0x43d, 0x20, 0x441, 0x43e, 0x43c,
+0x443, 0x3b, 0xb300, 0xd55c, 0xbbfc, 0xad6d, 0x20, 0xc6d0, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xb300, 0xd55c, 0xbbfc, 0xad6d, 0x20, 0xc6d0,
+0x3b, 0xc870, 0xc120, 0x20, 0xbbfc, 0xc8fc, 0xc8fc, 0xc758, 0x20, 0xc778, 0xbbfc, 0x20, 0xacf5, 0xd654, 0xad6d, 0x20, 0xc6d0, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0xc870, 0xc120, 0x20, 0xbbfc, 0xc8fc, 0xc8fc, 0xc758, 0x20, 0xc778, 0xbbfc, 0x20, 0xacf5, 0xd654, 0xad6d, 0x20, 0xc6d0, 0x3b,
+0x49, 0x66, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x72, 0x79, 0x2019, 0x55, 0x62, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xea5, 0xeb2, 0xea7, 0x20, 0xe81, 0xeb5, 0xe9a, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0xea5, 0xeb2, 0xea7, 0x20, 0xe81, 0xeb5, 0xe9a, 0x3b, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x65, 0x69,
+0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x46, 0x61, 0x6c, 0xe1, 0x6e, 0x67, 0x61, 0x20, 0x79,
+0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0xf3, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4b, 0x77, 0x61, 0x6e, 0x7a, 0x61,
+0x20, 0x79, 0x61, 0x20, 0x41, 0x6e, 0x67, 0xf3, 0x6c, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x61, 0x6c,
+0xe1, 0x6e, 0x67, 0x61, 0x20, 0x43, 0x46, 0x41, 0x20, 0x42, 0x45, 0x41, 0x43, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x45, 0x75, 0x72, 0x61, 0x73, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x61, 0x73, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x61, 0x69, 0x3b,
+0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x173, 0x3b, 0x41c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d, 0x441, 0x43a, 0x438,
+0x20, 0x434, 0x435, 0x43d, 0x430, 0x440, 0x3b, 0x3b, 0x41c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d, 0x441, 0x43a, 0x438, 0x20, 0x434,
+0x435, 0x43d, 0x430, 0x440, 0x3b, 0x3b, 0x3b, 0x3b, 0x41c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d, 0x441, 0x43a, 0x438, 0x20, 0x434,
+0x435, 0x43d, 0x430, 0x440, 0x438, 0x3b, 0x41, 0x72, 0x69, 0x61, 0x72, 0x79, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x52,
+0x69, 0x6e, 0x67, 0x67, 0x69, 0x74, 0x20, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x52, 0x69, 0x6e, 0x67, 0x67, 0x69, 0x74, 0x20, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x3b, 0x44, 0x6f,
+0x6c, 0x61, 0x72, 0x20, 0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x6f, 0x6c, 0x61,
+0x72, 0x20, 0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x3b, 0x44, 0x6f, 0x6c, 0x61, 0x72, 0x20, 0x53, 0x69, 0x6e, 0x67, 0x61,
+0x70, 0x75, 0x72, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x6f, 0x6c, 0x61, 0x72, 0x20, 0x53, 0x69, 0x6e, 0x67,
+0x61, 0x70, 0x75, 0x72, 0x61, 0x3b, 0xd07, 0xd28, 0xd4d, 0xd24, 0xd4d, 0xd2f, 0xd7b, 0x20, 0xd30, 0xd42, 0xd2a, 0x3b, 0x3b, 0xd07,
+0xd28, 0xd4d, 0xd24, 0xd4d, 0xd2f, 0xd7b, 0x20, 0xd30, 0xd42, 0xd2a, 0x3b, 0x3b, 0x3b, 0x3b, 0xd07, 0xd28, 0xd4d, 0xd24, 0xd4d, 0xd2f,
+0xd7b, 0x20, 0xd30, 0xd42, 0xd2a, 0x3b, 0x65, 0x77, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x77, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x77,
+0x72, 0x6f, 0x3b, 0x65, 0x77, 0x72, 0x6f, 0x3b, 0x65, 0x77, 0x72, 0x6f, 0x3b, 0x54, 0x101, 0x72, 0x61, 0x20, 0x6f, 0x20,
+0x41, 0x6f, 0x74, 0x65, 0x61, 0x72, 0x6f, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x67, 0x101, 0x20, 0x74, 0x101,
+0x72, 0x61, 0x20, 0x6f, 0x20, 0x41, 0x6f, 0x74, 0x65, 0x61, 0x72, 0x6f, 0x61, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f,
+0x20, 0x930, 0x941, 0x92a, 0x92f, 0x93e, 0x3b, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x941, 0x92a, 0x92f, 0x93e,
+0x3b, 0x3b, 0x3b, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x941, 0x92a, 0x92f, 0x947, 0x3b, 0x442, 0x4e9, 0x433,
+0x440, 0x4e9, 0x433, 0x3b, 0x3b, 0x442, 0x4e9, 0x433, 0x440, 0x4e9, 0x433, 0x3b, 0x3b, 0x3b, 0x3b, 0x442, 0x4e9, 0x433, 0x440, 0x4e9,
+0x433, 0x3b, 0x928, 0x947, 0x92a, 0x93e, 0x932, 0x940, 0x20, 0x930, 0x942, 0x92a, 0x948, 0x92f, 0x93e, 0x901, 0x3b, 0x3b, 0x928, 0x947,
+0x92a, 0x93e, 0x932, 0x940, 0x20, 0x930, 0x942, 0x92a, 0x948, 0x92f, 0x93e, 0x901, 0x3b, 0x3b, 0x3b, 0x3b, 0x928, 0x947, 0x92a, 0x93e,
+0x932, 0x940, 0x20, 0x930, 0x942, 0x92a, 0x948, 0x92f, 0x93e, 0x901, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x942,
+0x92a, 0x93f, 0x901, 0x92f, 0x93e, 0x3b, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x942, 0x92a, 0x93f, 0x901, 0x92f,
+0x93e, 0x3b, 0x3b, 0x3b, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x942, 0x92a, 0x93f, 0x901, 0x92f, 0x93e, 0x3b,
+0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x65, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x72, 0x3b, 0x3b, 0x6e, 0x6f, 0x72, 0x73, 0x6b,
+0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x65, 0x20, 0x6b, 0x72, 0x6f,
+0x6e, 0x65, 0x72, 0x3b, 0xb2d, 0xb3e, 0xb30, 0xb24, 0xb40, 0xb5f, 0x20, 0xb1f, 0xb19, 0xb4d, 0xb15, 0xb3e, 0x3b, 0x3b, 0xb2d, 0xb3e,
+0xb30, 0xb24, 0xb40, 0xb5f, 0x20, 0xb1f, 0xb19, 0xb4d, 0xb15, 0xb3e, 0x3b, 0x3b, 0x3b, 0x3b, 0xb2d, 0xb3e, 0xb30, 0xb24, 0xb40, 0xb5f,
+0x20, 0xb1f, 0xb19, 0xb4d, 0xb15, 0xb3e, 0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cd, 0x3b, 0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646,
+0x6cd, 0x3b, 0x3b, 0x3b, 0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cd, 0x3b, 0x631, 0x6cc, 0x627, 0x644, 0x20, 0x627, 0x6cc, 0x631,
+0x627, 0x646, 0x3b, 0x3b, 0x631, 0x6cc, 0x627, 0x644, 0x20, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x3b, 0x3b, 0x3b, 0x3b, 0x631, 0x6cc,
+0x627, 0x644, 0x20, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cc, 0x20, 0x627, 0x641, 0x63a, 0x627,
+0x646, 0x633, 0x62a, 0x627, 0x646, 0x3b, 0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cc, 0x20, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x633,
+0x62a, 0x627, 0x646, 0x3b, 0x3b, 0x3b, 0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cc, 0x20, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x633,
+0x62a, 0x627, 0x646, 0x3b, 0x7a, 0x142, 0x6f, 0x74, 0x79, 0x20, 0x70, 0x6f, 0x6c, 0x73, 0x6b, 0x69, 0x3b, 0x3b, 0x7a, 0x142,
+0x6f, 0x74, 0x79, 0x20, 0x70, 0x6f, 0x6c, 0x73, 0x6b, 0x69, 0x3b, 0x3b, 0x7a, 0x142, 0x6f, 0x74, 0x65, 0x20, 0x70, 0x6f,
+0x6c, 0x73, 0x6b, 0x69, 0x65, 0x3b, 0x7a, 0x142, 0x6f, 0x74, 0x79, 0x63, 0x68, 0x20, 0x70, 0x6f, 0x6c, 0x73, 0x6b, 0x69,
+0x63, 0x68, 0x3b, 0x7a, 0x142, 0x6f, 0x74, 0x65, 0x67, 0x6f, 0x20, 0x70, 0x6f, 0x6c, 0x73, 0x6b, 0x69, 0x65, 0x67, 0x6f,
+0x3b, 0x52, 0x65, 0x61, 0x6c, 0x20, 0x62, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x3b, 0x52, 0x65,
+0x61, 0x6c, 0x20, 0x62, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x52, 0x65, 0x61,
+0x69, 0x73, 0x20, 0x62, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x65, 0x69, 0x72, 0x6f, 0x73, 0x3b, 0x6b, 0x77, 0x61, 0x6e, 0x7a,
+0x61, 0x20, 0x61, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x6b, 0x77, 0x61, 0x6e, 0x7a, 0x61, 0x20, 0x61,
+0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x6b, 0x77, 0x61, 0x6e, 0x7a, 0x61, 0x73, 0x20, 0x61,
+0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x65, 0x73, 0x63, 0x75, 0x64, 0x6f, 0x20, 0x63, 0x61, 0x62, 0x6f,
+0x2d, 0x76, 0x65, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x65, 0x73, 0x63, 0x75, 0x64, 0x6f, 0x20, 0x63, 0x61,
+0x62, 0x6f, 0x2d, 0x76, 0x65, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x73, 0x63, 0x75, 0x64,
+0x6f, 0x73, 0x20, 0x63, 0x61, 0x62, 0x6f, 0x2d, 0x76, 0x65, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x64, 0xf3,
+0x6c, 0x61, 0x72, 0x20, 0x64, 0x6f, 0x73, 0x20, 0x45, 0x73, 0x74, 0x61, 0x64, 0x6f, 0x73, 0x20, 0x55, 0x6e, 0x69, 0x64,
+0x6f, 0x73, 0x3b, 0x3b, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x64, 0x6f, 0x73, 0x20, 0x45, 0x73, 0x74, 0x61, 0x64, 0x6f,
+0x73, 0x20, 0x55, 0x6e, 0x69, 0x64, 0x6f, 0x73, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x65, 0x73, 0x20,
+0x64, 0x6f, 0x73, 0x20, 0x45, 0x73, 0x74, 0x61, 0x64, 0x6f, 0x73, 0x20, 0x55, 0x6e, 0x69, 0x64, 0x6f, 0x73, 0x3b, 0x66,
+0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b, 0x3b, 0x66, 0x72,
+0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x66,
+0x72, 0x61, 0x6e, 0x63, 0x6f, 0x73, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b, 0x66, 0x72,
+0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x3b, 0x66, 0x72,
+0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x3b, 0x3b, 0x3b,
+0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x73, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b,
+0x50, 0x61, 0x74, 0x61, 0x63, 0x61, 0x20, 0x64, 0x65, 0x20, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x3b, 0x3b, 0x50, 0x61, 0x74,
+0x61, 0x63, 0x61, 0x20, 0x64, 0x65, 0x20, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x3b, 0x3b, 0x3b, 0x3b, 0x50, 0x61, 0x74, 0x61,
+0x63, 0x61, 0x73, 0x20, 0x64, 0x65, 0x20, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x3b, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x61, 0x6c,
+0x20, 0x6d, 0x6f, 0xe7, 0x61, 0x6d, 0x62, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x61,
+0x6c, 0x20, 0x6d, 0x6f, 0xe7, 0x61, 0x6d, 0x62, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x6d, 0x65, 0x74,
+0x69, 0x63, 0x61, 0x69, 0x73, 0x20, 0x6d, 0x6f, 0xe7, 0x61, 0x6d, 0x62, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x64,
+0x6f, 0x62, 0x72, 0x61, 0x20, 0x64, 0x65, 0x20, 0x53, 0xe3, 0x6f, 0x20, 0x54, 0x6f, 0x6d, 0xe9, 0x20, 0x65, 0x20, 0x50,
+0x72, 0xed, 0x6e, 0x63, 0x69, 0x70, 0x65, 0x3b, 0x3b, 0x64, 0x6f, 0x62, 0x72, 0x61, 0x20, 0x64, 0x65, 0x20, 0x53, 0xe3,
+0x6f, 0x20, 0x54, 0x6f, 0x6d, 0xe9, 0x20, 0x65, 0x20, 0x50, 0x72, 0xed, 0x6e, 0x63, 0x69, 0x70, 0x65, 0x3b, 0x3b, 0x3b,
+0x3b, 0x64, 0x6f, 0x62, 0x72, 0x61, 0x73, 0x20, 0x64, 0x65, 0x20, 0x53, 0xe3, 0x6f, 0x20, 0x54, 0x6f, 0x6d, 0xe9, 0x20,
+0x65, 0x20, 0x50, 0x72, 0xed, 0x6e, 0x63, 0x69, 0x70, 0x65, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x73, 0x75,
+0xed, 0xe7, 0x6f, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x73, 0x75, 0xed, 0xe7, 0x6f, 0x3b, 0x3b, 0x3b,
+0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x73, 0x20, 0x73, 0x75, 0xed, 0xe7, 0x6f, 0x73, 0x3b, 0xa2d, 0xa3e, 0xa30, 0xa24,
+0xa40, 0x20, 0xa30, 0xa41, 0xa2a, 0xa07, 0xa06, 0x3b, 0x3b, 0xa2d, 0xa3e, 0xa30, 0xa24, 0xa40, 0x20, 0xa30, 0xa41, 0xa2a, 0xa07, 0xa06,
+0x3b, 0x3b, 0x3b, 0x3b, 0xa2d, 0xa3e, 0xa30, 0xa24, 0xa40, 0x20, 0xa30, 0xa41, 0xa2a, 0xa0f, 0x3b, 0x631, 0x648, 0x67e, 0x626, 0x6cc,
+0x6c1, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x73, 0x76, 0x69, 0x7a, 0x7a, 0x65,
+0x72, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x73, 0x76, 0x69, 0x7a, 0x7a, 0x65, 0x72, 0x3b, 0x3b, 0x3b, 0x3b,
+0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x73, 0x76, 0x69, 0x7a, 0x7a, 0x65, 0x72, 0x3b, 0x6c, 0x65, 0x75, 0x20, 0x72, 0x6f,
+0x6d, 0xe2, 0x6e, 0x65, 0x73, 0x63, 0x3b, 0x3b, 0x6c, 0x65, 0x75, 0x20, 0x72, 0x6f, 0x6d, 0xe2, 0x6e, 0x65, 0x73, 0x63,
+0x3b, 0x3b, 0x6c, 0x65, 0x69, 0x20, 0x72, 0x6f, 0x6d, 0xe2, 0x6e, 0x65, 0x219, 0x74, 0x69, 0x3b, 0x3b, 0x6c, 0x65, 0x69,
+0x20, 0x72, 0x6f, 0x6d, 0xe2, 0x6e, 0x65, 0x219, 0x74, 0x69, 0x3b, 0x6c, 0x65, 0x75, 0x20, 0x6d, 0x6f, 0x6c, 0x64, 0x6f,
+0x76, 0x65, 0x6e, 0x65, 0x73, 0x63, 0x3b, 0x3b, 0x6c, 0x65, 0x75, 0x20, 0x6d, 0x6f, 0x6c, 0x64, 0x6f, 0x76, 0x65, 0x6e,
+0x65, 0x73, 0x63, 0x3b, 0x3b, 0x6c, 0x65, 0x69, 0x20, 0x6d, 0x6f, 0x6c, 0x64, 0x6f, 0x76, 0x65, 0x6e, 0x65, 0x219, 0x74,
+0x69, 0x3b, 0x3b, 0x6c, 0x65, 0x69, 0x20, 0x6d, 0x6f, 0x6c, 0x64, 0x6f, 0x76, 0x65, 0x6e, 0x65, 0x219, 0x74, 0x69, 0x3b,
+0x440, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44c, 0x3b, 0x3b, 0x440, 0x43e,
+0x441, 0x441, 0x438, 0x439, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44c, 0x3b, 0x3b, 0x440, 0x43e, 0x441, 0x441,
+0x438, 0x439, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44f, 0x3b, 0x440, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x441,
+0x43a, 0x438, 0x445, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x435, 0x439, 0x3b, 0x440, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x441, 0x43a, 0x43e,
+0x433, 0x43e, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44f, 0x3b, 0x431, 0x435, 0x43b, 0x43e, 0x440, 0x443, 0x441, 0x441, 0x43a, 0x438, 0x439,
+0x20, 0x440, 0x443, 0x431, 0x43b, 0x44c, 0x3b, 0x3b, 0x431, 0x435, 0x43b, 0x43e, 0x440, 0x443, 0x441, 0x441, 0x43a, 0x438, 0x439, 0x20,
+0x440, 0x443, 0x431, 0x43b, 0x44c, 0x3b, 0x3b, 0x431, 0x435, 0x43b, 0x43e, 0x440, 0x443, 0x441, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x440,
+0x443, 0x431, 0x43b, 0x44f, 0x3b, 0x431, 0x435, 0x43b, 0x43e, 0x440, 0x443, 0x441, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x440, 0x443, 0x431,
+0x43b, 0x435, 0x439, 0x3b, 0x431, 0x435, 0x43b, 0x43e, 0x440, 0x443, 0x441, 0x441, 0x43a, 0x43e, 0x433, 0x43e, 0x20, 0x440, 0x443, 0x431,
+0x43b, 0x44f, 0x3b, 0x43a, 0x430, 0x437, 0x430, 0x445, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x442, 0x435, 0x43d, 0x433, 0x435, 0x3b, 0x3b,
+0x43a, 0x430, 0x437, 0x430, 0x445, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x442, 0x435, 0x43d, 0x433, 0x435, 0x3b, 0x3b, 0x43a, 0x430, 0x437,
+0x430, 0x445, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x442, 0x435, 0x43d, 0x433, 0x435, 0x3b, 0x43a, 0x430, 0x437, 0x430, 0x445, 0x441, 0x43a,
+0x438, 0x445, 0x20, 0x442, 0x435, 0x43d, 0x433, 0x435, 0x3b, 0x43a, 0x430, 0x437, 0x430, 0x445, 0x441, 0x43a, 0x43e, 0x433, 0x43e, 0x20,
+0x442, 0x435, 0x43d, 0x433, 0x435, 0x3b, 0x43a, 0x438, 0x440, 0x433, 0x438, 0x437, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x441, 0x43e, 0x43c,
+0x3b, 0x3b, 0x43a, 0x438, 0x440, 0x433, 0x438, 0x437, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x441, 0x43e, 0x43c, 0x3b, 0x3b, 0x43a, 0x438,
+0x440, 0x433, 0x438, 0x437, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x441, 0x43e, 0x43c, 0x430, 0x3b, 0x43a, 0x438, 0x440, 0x433, 0x438, 0x437,
+0x441, 0x43a, 0x438, 0x445, 0x20, 0x441, 0x43e, 0x43c, 0x43e, 0x432, 0x3b, 0x43a, 0x438, 0x440, 0x433, 0x438, 0x437, 0x441, 0x43a, 0x43e,
+0x433, 0x43e, 0x20, 0x441, 0x43e, 0x43c, 0x430, 0x3b, 0x43c, 0x43e, 0x43b, 0x434, 0x430, 0x432, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x43b,
+0x435, 0x439, 0x3b, 0x3b, 0x43c, 0x43e, 0x43b, 0x434, 0x430, 0x432, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x43b, 0x435, 0x439, 0x3b, 0x3b,
+0x43c, 0x43e, 0x43b, 0x434, 0x430, 0x432, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x43b, 0x435, 0x44f, 0x3b, 0x43c, 0x43e, 0x43b, 0x434, 0x430,
+0x432, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x43b, 0x435, 0x435, 0x432, 0x3b, 0x43c, 0x43e, 0x43b, 0x434, 0x430, 0x432, 0x441, 0x43a, 0x43e,
+0x433, 0x43e, 0x20, 0x43b, 0x435, 0x44f, 0x3b, 0x443, 0x43a, 0x440, 0x430, 0x438, 0x43d, 0x441, 0x43a, 0x430, 0x44f, 0x20, 0x433, 0x440,
+0x438, 0x432, 0x43d, 0x430, 0x3b, 0x3b, 0x443, 0x43a, 0x440, 0x430, 0x438, 0x43d, 0x441, 0x43a, 0x430, 0x44f, 0x20, 0x433, 0x440, 0x438,
+0x432, 0x43d, 0x430, 0x3b, 0x3b, 0x443, 0x43a, 0x440, 0x430, 0x438, 0x43d, 0x441, 0x43a, 0x438, 0x435, 0x20, 0x433, 0x440, 0x438, 0x432,
+0x43d, 0x44b, 0x3b, 0x443, 0x43a, 0x440, 0x430, 0x438, 0x43d, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x433, 0x440, 0x438, 0x432, 0x435, 0x43d,
+0x3b, 0x443, 0x43a, 0x440, 0x430, 0x438, 0x43d, 0x441, 0x43a, 0x43e, 0x439, 0x20, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x44b, 0x3b, 0x66,
+0x61, 0x72, 0xe2, 0x6e, 0x67, 0x61, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x421, 0x440, 0x43f, 0x441, 0x43a, 0x438, 0x20, 0x434, 0x438, 0x43d, 0x430, 0x440, 0x3b, 0x3b, 0x441, 0x440,
+0x43f, 0x441, 0x43a, 0x438, 0x20, 0x434, 0x438, 0x43d, 0x430, 0x440, 0x3b, 0x3b, 0x441, 0x440, 0x43f, 0x441, 0x43a, 0x430, 0x20, 0x434,
+0x438, 0x43d, 0x430, 0x440, 0x430, 0x3b, 0x3b, 0x441, 0x440, 0x43f, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x434, 0x438, 0x43d, 0x430, 0x440,
+0x430, 0x3b, 0x411, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430,
+0x447, 0x43a, 0x430, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x430, 0x20, 0x43c, 0x430,
+0x440, 0x43a, 0x430, 0x3b, 0x3b, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433,
+0x43e, 0x432, 0x430, 0x447, 0x43a, 0x430, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x430,
+0x20, 0x43c, 0x430, 0x440, 0x43a, 0x430, 0x3b, 0x3b, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440,
+0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x435, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438,
+0x43b, 0x43d, 0x435, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x65, 0x3b, 0x3b, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d,
+0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x438, 0x445, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440,
+0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x438, 0x445, 0x20, 0x43c, 0x430, 0x440, 0x430, 0x43a, 0x430, 0x3b, 0x415, 0x432, 0x440, 0x43e,
+0x3b, 0x3b, 0x435, 0x432, 0x440, 0x43e, 0x3b, 0x3b, 0x435, 0x432, 0x440, 0x430, 0x3b, 0x3b, 0x435, 0x432, 0x440, 0x430, 0x3b, 0x42,
+0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x61,
+0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61,
+0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61,
+0x10d, 0x6b, 0x61, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d, 0x61,
+0x72, 0x6b, 0x61, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67,
+0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x65, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x65,
+0x20, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x68, 0x65, 0x72,
+0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x69, 0x68, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62,
+0x69, 0x6c, 0x6e, 0x69, 0x68, 0x20, 0x6d, 0x61, 0x72, 0x61, 0x6b, 0x61, 0x3b, 0x45, 0x76, 0x72, 0x6f, 0x3b, 0x3b, 0x65,
+0x76, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x76, 0x72, 0x61, 0x3b, 0x3b, 0x65, 0x76, 0x72, 0x61, 0x3b, 0x53, 0x72, 0x70, 0x73,
+0x6b, 0x69, 0x20, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x3b, 0x3b, 0x73, 0x72, 0x70, 0x73, 0x6b, 0x69, 0x20, 0x64, 0x69, 0x6e,
+0x61, 0x72, 0x3b, 0x3b, 0x73, 0x72, 0x70, 0x73, 0x6b, 0x61, 0x20, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x61, 0x3b, 0x3b, 0x73,
+0x72, 0x70, 0x73, 0x6b, 0x69, 0x68, 0x20, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x61, 0x3b, 0x41b, 0x430, 0x440, 0x3b, 0x3b, 0x43b,
+0x430, 0x440, 0x3b, 0x3b, 0x3b, 0x3b, 0x43b, 0x430, 0x440, 0x44b, 0x3b, 0x421, 0x43e, 0x43c, 0x3b, 0x3b, 0x441, 0x43e, 0x43c, 0x3b,
+0x3b, 0x3b, 0x3b, 0x441, 0x43e, 0x43c, 0x44b, 0x3b, 0x44, 0x6f, 0x72, 0x61, 0x20, 0x72, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72,
+0x69, 0x6b, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x67e, 0x627, 0x6aa, 0x633, 0x62a, 0x627, 0x646, 0x64a, 0x20, 0x631,
+0x67e, 0x64a, 0x3b, 0x3b, 0x67e, 0x627, 0x6aa, 0x633, 0x62a, 0x627, 0x646, 0x64a, 0x20, 0x631, 0x67e, 0x64a, 0x3b, 0x3b, 0x3b, 0x3b,
+0x67e, 0x627, 0x6aa, 0x633, 0x62a, 0x627, 0x646, 0x64a, 0x20, 0x631, 0x67e, 0x64a, 0x3b, 0xdc1, 0xdca, 0x200d, 0xdbb, 0xdd3, 0x20, 0xdbd,
+0xd82, 0xd9a, 0xdcf, 0x20, 0xdbb, 0xdd4, 0xdb4, 0xdd2, 0xdba, 0xdbd, 0x3b, 0x3b, 0xdc1, 0xdca, 0x200d, 0xdbb, 0xdd3, 0x20, 0xdbd, 0xd82,
+0xd9a, 0xdcf, 0x20, 0xdbb, 0xdd4, 0xdb4, 0xdd2, 0xdba, 0xdbd, 0x3b, 0x3b, 0x3b, 0x3b, 0xdc1, 0xdca, 0x200d, 0xdbb, 0xdd3, 0x20, 0xdbd,
+0xd82, 0xd9a, 0xdcf, 0x20, 0xdbb, 0xdd4, 0xdb4, 0xdd2, 0xdba, 0xdbd, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72,
+0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0xe1, 0x3b, 0x65, 0x75, 0x72, 0x61, 0x3b, 0x65, 0x75, 0x72, 0x3b, 0x65, 0x76, 0x72,
+0x6f, 0x3b, 0x3b, 0x65, 0x76, 0x72, 0x6f, 0x3b, 0x65, 0x76, 0x72, 0x61, 0x3b, 0x65, 0x76, 0x72, 0x69, 0x3b, 0x3b, 0x65,
+0x76, 0x72, 0x6f, 0x76, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x6b, 0x61, 0x20, 0x53, 0x6f, 0x6f, 0x6d, 0x61,
+0x61, 0x6c, 0x69, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x61, 0x72, 0x61, 0x6e, 0x20, 0x4a, 0x61,
+0x62, 0x62, 0x75, 0x75, 0x74, 0x69, 0x3b, 0x3b, 0x46, 0x61, 0x72, 0x61, 0x6e, 0x6b, 0x20, 0x4a, 0x61, 0x62, 0x75, 0x75,
+0x74, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x61, 0x72, 0x61, 0x6e, 0x6b, 0x20, 0x4a, 0x61, 0x62, 0x75, 0x75, 0x74, 0x69,
+0x3b, 0x42, 0x69, 0x72, 0x74, 0x61, 0x20, 0x49, 0x74, 0x6f, 0x6f, 0x62, 0x62, 0x69, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x6b, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b,
+0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x68, 0x69,
+0x6c, 0x69, 0x6e, 0x67, 0x6b, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x61, 0x72,
+0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x61, 0x72, 0x67, 0x65, 0x6e, 0x74,
+0x69, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x61, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69,
+0x6e, 0x6f, 0x73, 0x3b, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x62, 0x65, 0x6c, 0x69, 0x63, 0x65, 0xf1, 0x6f, 0x3b, 0x3b,
+0x64, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x62, 0x65, 0x6c, 0x69, 0x63, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0xf3,
+0x6c, 0x61, 0x72, 0x65, 0x73, 0x20, 0x62, 0x65, 0x6c, 0x69, 0x63, 0x65, 0xf1, 0x6f, 0x73, 0x3b, 0x62, 0x6f, 0x6c, 0x69,
+0x76, 0x69, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x62, 0x6f, 0x6c, 0x69, 0x76, 0x69, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b,
+0x62, 0x6f, 0x6c, 0x69, 0x76, 0x69, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x72, 0x65, 0x61, 0x6c, 0x20, 0x62, 0x72, 0x61, 0x73,
+0x69, 0x6c, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x72, 0x65, 0x61, 0x6c, 0x20, 0x62, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x65, 0xf1,
+0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x72, 0x65, 0x61, 0x6c, 0x65, 0x73, 0x20, 0x62, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x65, 0xf1,
+0x6f, 0x73, 0x3b, 0x50, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x65, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73,
+0x6f, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x65, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x63,
+0x68, 0x69, 0x6c, 0x65, 0x6e, 0x6f, 0x73, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x69,
+0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x6f,
+0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x6f,
+0x73, 0x3b, 0x63, 0x6f, 0x6c, 0xf3, 0x6e, 0x20, 0x63, 0x6f, 0x73, 0x74, 0x61, 0x72, 0x72, 0x69, 0x63, 0x65, 0x6e, 0x73,
+0x65, 0x3b, 0x3b, 0x63, 0x6f, 0x6c, 0xf3, 0x6e, 0x20, 0x63, 0x6f, 0x73, 0x74, 0x61, 0x72, 0x72, 0x69, 0x63, 0x65, 0x6e,
+0x73, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x63, 0x6f, 0x6c, 0x6f, 0x6e, 0x65, 0x73, 0x20, 0x63, 0x6f, 0x73, 0x74, 0x61, 0x72,
+0x72, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x75, 0x62, 0x61, 0x6e, 0x6f,
+0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x75, 0x62, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73,
+0x6f, 0x73, 0x20, 0x63, 0x75, 0x62, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x64, 0x6f, 0x6d, 0x69,
+0x6e, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63,
+0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63,
+0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x65, 0x73, 0x74, 0x61, 0x64, 0x6f, 0x75, 0x6e, 0x69,
+0x64, 0x65, 0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x65, 0x73, 0x74, 0x61, 0x64, 0x6f, 0x75,
+0x6e, 0x69, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x65, 0x73, 0x20, 0x65,
+0x73, 0x74, 0x61, 0x64, 0x6f, 0x75, 0x6e, 0x69, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63,
+0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x64, 0x65, 0x20, 0xc1, 0x66, 0x72, 0x69, 0x63, 0x61, 0x20, 0x43, 0x65, 0x6e, 0x74,
+0x72, 0x61, 0x6c, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x64, 0x65, 0x20, 0xc1,
+0x66, 0x72, 0x69, 0x63, 0x61, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61,
+0x6e, 0x63, 0x6f, 0x73, 0x20, 0x43, 0x46, 0x41, 0x20, 0x64, 0x65, 0x20, 0xc1, 0x66, 0x72, 0x69, 0x63, 0x61, 0x20, 0x43,
+0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x3b, 0x71, 0x75, 0x65, 0x74, 0x7a, 0x61, 0x6c, 0x3b, 0x3b, 0x71, 0x75, 0x65, 0x74,
+0x7a, 0x61, 0x6c, 0x3b, 0x3b, 0x3b, 0x3b, 0x71, 0x75, 0x65, 0x74, 0x7a, 0x61, 0x6c, 0x65, 0x73, 0x3b, 0x6c, 0x65, 0x6d,
+0x70, 0x69, 0x72, 0x61, 0x20, 0x68, 0x6f, 0x6e, 0x64, 0x75, 0x72, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x6c, 0x65, 0x6d, 0x70,
+0x69, 0x72, 0x61, 0x20, 0x68, 0x6f, 0x6e, 0x64, 0x75, 0x72, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x6c, 0x65, 0x6d,
+0x70, 0x69, 0x72, 0x61, 0x73, 0x20, 0x68, 0x6f, 0x6e, 0x64, 0x75, 0x72, 0x65, 0xf1, 0x6f, 0x73, 0x3b, 0x70, 0x65, 0x73,
+0x6f, 0x20, 0x6d, 0x65, 0x78, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x6d, 0x65, 0x78,
+0x69, 0x63, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x6d, 0x65, 0x78, 0x69, 0x63,
+0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x63, 0xf3, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x20, 0x6e, 0x69, 0x63, 0x61, 0x72, 0x61, 0x67,
+0xfc, 0x65, 0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x63, 0xf3, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x20, 0x6e, 0x69, 0x63, 0x61, 0x72,
+0x61, 0x67, 0xfc, 0x65, 0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x63, 0xf3, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x73, 0x20,
+0x6e, 0x69, 0x63, 0x61, 0x72, 0x61, 0x67, 0xfc, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x3b, 0x62, 0x61, 0x6c, 0x62, 0x6f, 0x61,
+0x20, 0x70, 0x61, 0x6e, 0x61, 0x6d, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x62, 0x61, 0x6c, 0x62, 0x6f, 0x61, 0x20, 0x70, 0x61,
+0x6e, 0x61, 0x6d, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x62, 0x61, 0x6c, 0x62, 0x6f, 0x61, 0x73, 0x20, 0x70, 0x61,
+0x6e, 0x61, 0x6d, 0x65, 0xf1, 0x6f, 0x73, 0x3b, 0x67, 0x75, 0x61, 0x72, 0x61, 0x6e, 0xed, 0x20, 0x70, 0x61, 0x72, 0x61,
+0x67, 0x75, 0x61, 0x79, 0x6f, 0x3b, 0x3b, 0x67, 0x75, 0x61, 0x72, 0x61, 0x6e, 0xed, 0x20, 0x70, 0x61, 0x72, 0x61, 0x67,
+0x75, 0x61, 0x79, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x67, 0x75, 0x61, 0x72, 0x61, 0x6e, 0xed, 0x65, 0x73, 0x20, 0x70, 0x61,
+0x72, 0x61, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x73, 0x3b, 0x73, 0x6f, 0x6c, 0x20, 0x70, 0x65, 0x72, 0x75, 0x61, 0x6e, 0x6f,
+0x3b, 0x3b, 0x73, 0x6f, 0x6c, 0x20, 0x70, 0x65, 0x72, 0x75, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x6f, 0x6c,
+0x65, 0x73, 0x20, 0x70, 0x65, 0x72, 0x75, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x66, 0x69, 0x6c,
+0x69, 0x70, 0x69, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x66, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x6f,
+0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x6f, 0x73, 0x3b,
+0x70, 0x65, 0x73, 0x6f, 0x20, 0x75, 0x72, 0x75, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20,
+0x75, 0x72, 0x75, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x75, 0x72,
+0x75, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x73, 0x3b, 0x62, 0x6f, 0x6c, 0xed, 0x76, 0x61, 0x72, 0x20, 0x73, 0x6f, 0x62, 0x65,
+0x72, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x62, 0x6f, 0x6c, 0xed, 0x76, 0x61, 0x72, 0x20, 0x73, 0x6f, 0x62, 0x65, 0x72, 0x61,
+0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x62, 0x6f, 0x6c, 0xed, 0x76, 0x61, 0x72, 0x65, 0x73, 0x20, 0x73, 0x6f, 0x62, 0x65,
+0x72, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61,
+0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20,
+0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69,
+0x20, 0x7a, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x46, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x61,
+0x20, 0x79, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x3b, 0x3b, 0x66, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x79,
+0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x7a,
+0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20,
+0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b,
+0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x7a, 0x61, 0x20,
+0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x55, 0x67,
+0x61, 0x6e, 0x64, 0x61, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x55, 0x67,
+0x61, 0x6e, 0x64, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x7a, 0x61, 0x20,
+0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x3b, 0x73, 0x76, 0x65, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x61, 0x3b,
+0x3b, 0x73, 0x76, 0x65, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x76, 0x65,
+0x6e, 0x73, 0x6b, 0x61, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x6f, 0x72, 0x3b, 0x421, 0x43e, 0x43c, 0x43e, 0x43d, 0x4e3, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x421, 0x43e, 0x43c, 0x43e, 0x43d, 0x4e3, 0x3b, 0xb87, 0xba8, 0xbcd, 0xba4, 0xbbf, 0xbaf, 0x20, 0xbb0, 0xbc2,
+0xbaa, 0xbbe, 0xbaf, 0xbcd, 0x3b, 0x3b, 0xb87, 0xba8, 0xbcd, 0xba4, 0xbbf, 0xbaf, 0x20, 0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0x3b,
+0x3b, 0x3b, 0x3b, 0xb87, 0xba8, 0xbcd, 0xba4, 0xbbf, 0xbaf, 0x20, 0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0xb95, 0xbb3, 0xbcd, 0x3b,
+0xbae, 0xbb2, 0xbc7, 0xbb7, 0xbbf, 0xbaf, 0xba9, 0xbcd, 0x20, 0xbb0, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbbf, 0xb9f, 0xbcd, 0x3b, 0x3b, 0xbae,
+0xbb2, 0xbc7, 0xbb7, 0xbbf, 0xbaf, 0xba9, 0xbcd, 0x20, 0xbb0, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbbf, 0xb9f, 0xbcd, 0x3b, 0x3b, 0x3b, 0x3b,
+0xbae, 0xbb2, 0xbc7, 0xbb7, 0xbbf, 0xbaf, 0xba9, 0xbcd, 0x20, 0xbb0, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbbf, 0xb9f, 0xbcd, 0xb95, 0xbb3, 0xbcd,
+0x3b, 0xb9a, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbaa, 0xbcd, 0xbaa, 0xbc2, 0xbb0, 0xbcd, 0x20, 0xb9f, 0xbbe, 0xbb2, 0xbb0, 0xbcd, 0x3b, 0x3b,
+0xb9a, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbaa, 0xbcd, 0xbaa, 0xbc2, 0xbb0, 0xbcd, 0x20, 0xb9f, 0xbbe, 0xbb2, 0xbb0, 0xbcd, 0x3b, 0x3b, 0x3b,
+0x3b, 0xb9a, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbaa, 0xbcd, 0xbaa, 0xbc2, 0xbb0, 0xbcd, 0x20, 0xb9f, 0xbbe, 0xbb2, 0xbb0, 0xbcd, 0xb95, 0xbb3,
+0xbcd, 0x3b, 0xb87, 0xbb2, 0xb99, 0xbcd, 0xb95, 0xbc8, 0x20, 0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0x3b, 0x3b, 0xb87, 0xbb2, 0xb99,
+0xbcd, 0xb95, 0xbc8, 0x20, 0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0x3b, 0x3b, 0x3b, 0x3b, 0xb87, 0xbb2, 0xb99, 0xbcd, 0xb95, 0xbc8,
+0x20, 0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0xb95, 0xbb3, 0xbcd, 0x3b, 0x420, 0x43e, 0x441, 0x441, 0x438, 0x44f, 0x20, 0x441, 0x443,
+0x43c, 0x44b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x441, 0x443, 0x43c, 0x3b, 0xc30, 0xc42, 0xc2a, 0xc3e, 0xc2f, 0xc3f, 0x3b, 0x3b,
+0xc30, 0xc42, 0xc2a, 0xc3e, 0xc2f, 0xc3f, 0x3b, 0x3b, 0x3b, 0x3b, 0xc30, 0xc42, 0xc2a, 0xc3e, 0xc2f, 0xc32, 0xc41, 0x3b, 0xe1a, 0xe32,
+0xe17, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xe1a, 0xe32, 0xe17, 0xe44, 0xe17, 0xe22, 0x3b, 0xf61, 0xf74, 0xf0b, 0xf68, 0xf53, 0xf0b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xf62, 0xf92, 0xfb1, 0xf0b, 0xf42, 0xf62, 0xf0b, 0xf66, 0xf92, 0xf7c, 0xf62, 0xf0b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x12e8, 0x12a2, 0x1275, 0x12ee, 0x1335, 0x12eb, 0x20, 0x1265, 0x122d, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x50, 0x61, 0x2bb, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x66, 0x61, 0x6b, 0x61, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x50, 0x61, 0x2bb, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x66, 0x61, 0x6b, 0x61, 0x74, 0x6f, 0x6e,
+0x67, 0x61, 0x3b, 0x54, 0xfc, 0x72, 0x6b, 0x20, 0x4c, 0x69, 0x72, 0x61, 0x73, 0x131, 0x3b, 0x3b, 0x54, 0xfc, 0x72, 0x6b,
+0x20, 0x6c, 0x69, 0x72, 0x61, 0x73, 0x131, 0x3b, 0x3b, 0x3b, 0x3b, 0x54, 0xfc, 0x72, 0x6b, 0x20, 0x6c, 0x69, 0x72, 0x61,
+0x73, 0x131, 0x3b, 0x54, 0xfc, 0x72, 0x6b, 0x6d, 0x65, 0x6e, 0x20, 0x6d, 0x61, 0x6e, 0x61, 0x64, 0x79, 0x3b, 0x3b, 0x74,
+0xfc, 0x72, 0x6b, 0x6d, 0x65, 0x6e, 0x20, 0x6d, 0x61, 0x6e, 0x61, 0x64, 0x79, 0x3b, 0x3b, 0x3b, 0x3b, 0x74, 0xfc, 0x72,
+0x6b, 0x6d, 0x65, 0x6e, 0x20, 0x6d, 0x61, 0x6e, 0x61, 0x64, 0x79, 0x3b, 0x62c, 0x6c7, 0x6ad, 0x6af, 0x648, 0x20, 0x64a, 0x6c8,
+0x6d5, 0x646, 0x649, 0x3b, 0x3b, 0x62c, 0x6c7, 0x6ad, 0x6af, 0x648, 0x20, 0x64a, 0x6c8, 0x6d5, 0x646, 0x649, 0x3b, 0x3b, 0x3b, 0x3b,
+0x62c, 0x6c7, 0x6ad, 0x6af, 0x648, 0x20, 0x64a, 0x6c8, 0x6d5, 0x646, 0x649, 0x3b, 0x443, 0x43a, 0x440, 0x430, 0x457, 0x43d, 0x441, 0x44c,
+0x43a, 0x430, 0x20, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x44f, 0x3b, 0x3b, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x44f, 0x3b, 0x3b, 0x433,
+0x440, 0x438, 0x432, 0x43d, 0x456, 0x3b, 0x433, 0x440, 0x438, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x456,
+0x3b, 0x67e, 0x627, 0x6a9, 0x633, 0x62a, 0x627, 0x646, 0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6cc, 0x6c1, 0x3b, 0x3b, 0x67e, 0x627, 0x6a9,
+0x633, 0x62a, 0x627, 0x646, 0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6cc, 0x6c1, 0x3b, 0x3b, 0x3b, 0x3b, 0x67e, 0x627, 0x6a9, 0x633, 0x62a,
+0x627, 0x646, 0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6cc, 0x6c1, 0x3b, 0x628, 0x6be, 0x627, 0x631, 0x62a, 0x6cc, 0x20, 0x631, 0x648, 0x67e,
+0x6cc, 0x6c1, 0x3b, 0x3b, 0x628, 0x6be, 0x627, 0x631, 0x62a, 0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6cc, 0x6c1, 0x3b, 0x3b, 0x3b, 0x3b,
+0x628, 0x6be, 0x627, 0x631, 0x62a, 0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6d2, 0x3b, 0x4f, 0x2018, 0x7a, 0x62, 0x65, 0x6b, 0x69, 0x73,
+0x74, 0x6f, 0x6e, 0x20, 0x73, 0x6f, 0x2018, 0x6d, 0x69, 0x3b, 0x3b, 0x4f, 0x2018, 0x7a, 0x62, 0x65, 0x6b, 0x69, 0x73, 0x74,
+0x6f, 0x6e, 0x20, 0x73, 0x6f, 0x2018, 0x6d, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x4f, 0x2018, 0x7a, 0x62, 0x65, 0x6b, 0x69, 0x73,
+0x74, 0x6f, 0x6e, 0x20, 0x73, 0x6f, 0x2018, 0x6d, 0x69, 0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cc, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x40e, 0x437, 0x431, 0x435, 0x43a, 0x438, 0x441, 0x442, 0x43e, 0x43d, 0x20, 0x441, 0x45e, 0x43c, 0x3b, 0x3b, 0x40e,
+0x437, 0x431, 0x435, 0x43a, 0x438, 0x441, 0x442, 0x43e, 0x43d, 0x20, 0x441, 0x45e, 0x43c, 0x3b, 0x3b, 0x3b, 0x3b, 0x40e, 0x437, 0x431,
+0x435, 0x43a, 0x438, 0x441, 0x442, 0x43e, 0x43d, 0x20, 0x441, 0x45e, 0x43c, 0x3b, 0x110, 0x1ed3, 0x6e, 0x67, 0x20, 0x56, 0x69, 0x1ec7,
+0x74, 0x20, 0x4e, 0x61, 0x6d, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x110, 0x1ed3, 0x6e, 0x67, 0x20, 0x56, 0x69, 0x1ec7, 0x74,
+0x20, 0x4e, 0x61, 0x6d, 0x3b, 0x50, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x70, 0x75,
+0x6e, 0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x62, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72, 0x79, 0x64,
+0x61, 0x69, 0x6e, 0x3b, 0x62, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x70, 0x75, 0x6e,
+0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x70, 0x68, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72, 0x79, 0x64,
+0x61, 0x69, 0x6e, 0x3b, 0x70, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x46, 0x72, 0x61,
+0x6e, 0x63, 0x20, 0x43, 0x46, 0x41, 0x20, 0x62, 0x75, 0x20, 0x41, 0x66, 0x72, 0x69, 0x6b, 0x20, 0x53, 0x6f, 0x77, 0x77,
+0x75, 0x2d, 0x6a, 0x61, 0x6e, 0x74, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46,
+0x41, 0x20, 0x79, 0x75, 0x20, 0x41, 0x66, 0x72, 0x69, 0x6b, 0x20, 0x53, 0x6f, 0x77, 0x77, 0x75, 0x2d, 0x6a, 0x61, 0x6e,
+0x74, 0x3b, 0x69, 0x52, 0x61, 0x6e, 0x64, 0x69, 0x20, 0x79, 0x61, 0x73, 0x65, 0x4d, 0x7a, 0x61, 0x6e, 0x7a, 0x69, 0x20,
+0x41, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x3b, 0x3b, 0x69, 0x52, 0x61, 0x6e, 0x64, 0x69, 0x20, 0x59, 0x61, 0x73, 0x65, 0x4d,
+0x7a, 0x61, 0x6e, 0x7a, 0x69, 0x20, 0x41, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x69, 0x52, 0x61, 0x6e,
+0x64, 0x69, 0x20, 0x79, 0x61, 0x73, 0x65, 0x4d, 0x7a, 0x61, 0x6e, 0x7a, 0x69, 0x20, 0x41, 0x66, 0x72, 0x69, 0x6b, 0x61,
+0x3b, 0x4e, 0x61, 0x69, 0x72, 0x61, 0x20, 0x74, 0x69, 0x20, 0x4f, 0x72, 0xed, 0x6c, 0x1eb9, 0x301, 0xe8, 0x64, 0x65, 0x20,
+0x4e, 0xe0, 0xec, 0x6a, 0xed, 0x72, 0xed, 0xe0, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x61, 0x72, 0x61, 0x6e,
+0x73, 0x69, 0x20, 0x74, 0x69, 0x20, 0x4f, 0x72, 0xed, 0x6c, 0x25b, 0x301, 0xe8, 0x64, 0x65, 0x20, 0x42, 0x49, 0x4b, 0x45,
+0x41, 0x4f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x69, 0x2d, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72,
+0x69, 0x63, 0x61, 0x6e, 0x20, 0x52, 0x61, 0x6e, 0x64, 0x3b, 0x3b, 0x69, 0x2d, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41,
+0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x52, 0x61, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x69, 0x2d, 0x53, 0x6f, 0x75,
+0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x52, 0x61, 0x6e, 0x64, 0x3b, 0x42, 0x6f, 0x73, 0x61,
+0x6e, 0x73, 0x6b, 0x6f, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x61, 0x20, 0x6b, 0x6f, 0x6e,
+0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x3b, 0x3b, 0x62, 0x6f,
+0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x61, 0x20, 0x6b,
+0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x3b, 0x3b,
+0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x65,
+0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x65,
+0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d,
+0x6b, 0x69, 0x68, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x69, 0x68, 0x20, 0x6d,
+0x61, 0x72, 0x61, 0x6b, 0x61, 0x3b, 0x41a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x430, 0x20,
+0x43c, 0x430, 0x440, 0x43a, 0x430, 0x3b, 0x3b, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446,
+0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x430, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b,
+0x43d, 0x430, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x430, 0x3b, 0x3b, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445,
+0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x435, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438,
+0x431, 0x438, 0x43b, 0x43d, 0x435, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x3b, 0x3b, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e,
+0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x438, 0x445, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435,
+0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x438, 0x445, 0x20, 0x43c, 0x430, 0x440, 0x430, 0x43a, 0x430, 0x3b, 0x47, 0x68, 0x61,
+0x6e, 0x61, 0x20, 0x53, 0x69, 0x64, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x49, 0x4e, 0x52, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x49, 0x4e, 0x52, 0x3b, 0x4e, 0x61, 0x1ecb, 0x72, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53,
+0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x67, 0x68, 0x61, 0x6e, 0x61, 0x20, 0x73, 0x69, 0x256, 0x69, 0x3b, 0x3b, 0x67, 0x68, 0x61, 0x6e, 0x61, 0x20,
+0x73, 0x69, 0x256, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x67, 0x68, 0x61, 0x6e, 0x61, 0x20, 0x73, 0x69, 0x256, 0x69, 0x3b, 0x263,
+0x65, 0x74, 0x6f, 0x256, 0x6f, 0x66, 0x65, 0x20, 0x61, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x67, 0x61, 0x20, 0x43, 0x46, 0x41,
+0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x3b, 0x3b, 0x263, 0x65, 0x74, 0x6f, 0x256, 0x6f,
+0x66, 0x65, 0x20, 0x61, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x67, 0x61, 0x20, 0x43, 0x46, 0x41, 0x20, 0x66, 0x72, 0x61, 0x6e,
+0x63, 0x20, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x3b, 0x3b, 0x3b, 0x3b, 0x263, 0x65, 0x74, 0x6f, 0x256, 0x6f, 0x66, 0x65, 0x20,
0x61, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x67, 0x61, 0x20, 0x43, 0x46, 0x41, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x42,
-0x43, 0x45, 0x41, 0x4f, 0x3b, 0x3b, 0x3b, 0x3b, 0x263, 0x65, 0x74, 0x6f, 0x256, 0x6f, 0x66, 0x65, 0x20, 0x61, 0x66, 0x72,
-0x69, 0x6b, 0x61, 0x67, 0x61, 0x20, 0x43, 0x46, 0x41, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x42, 0x43, 0x45, 0x41,
-0x4f, 0x3b, 0x50, 0x69, 0x73, 0x6f, 0x20, 0x6e, 0x67, 0x20, 0x50, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x61, 0x73, 0x3b,
-0x3b, 0x70, 0x69, 0x73, 0x6f, 0x20, 0x6e, 0x67, 0x20, 0x50, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x61, 0x73, 0x3b, 0x3b,
-0x3b, 0x3b, 0x70, 0x69, 0x73, 0x6f, 0x20, 0x6e, 0x67, 0x20, 0x50, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x61, 0x73, 0x3b,
-0x53, 0x63, 0x68, 0x77, 0x69, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x3b, 0x3b, 0x53, 0x63,
-0x68, 0x77, 0x69, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x63,
-0x68, 0x77, 0x69, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x6e, 0x6f, 0x72, 0x67, 0x67, 0x61, 0x20, 0x6b, 0x72, 0x75,
-0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x3b, 0x6e, 0x6f, 0x72, 0x67, 0x67, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f,
-0x3b, 0x6e, 0x6f, 0x72, 0x67, 0x67, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x6e, 0x6f,
-0x72, 0x67, 0x67, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65,
-0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x72, 0x75, 0x6f, 0x167,
-0x167, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x3b, 0x72, 0x75, 0x6f, 0x167, 0x167, 0x61, 0x20, 0x6b,
-0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x72, 0x75, 0x6f, 0x167, 0x167, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e,
-0x6f, 0x3b, 0x3b, 0x3b, 0x72, 0x75, 0x6f, 0x167, 0x167, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x53,
-0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x4d, 0x62, 0x75, 0x75, 0x257, 0x75, 0x20, 0x53, 0x65, 0x65, 0x66, 0x61, 0x61, 0x20, 0x42, 0x43, 0x45,
-0x41, 0x4f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x62, 0x75, 0x75, 0x257, 0x69, 0x20, 0x53, 0x65, 0x65, 0x66,
-0x61, 0x61, 0x20, 0x42, 0x45, 0x41, 0x43, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x55, 0x67, 0x69, 0x79, 0x79, 0x61,
-0x20, 0x4d, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x43, 0x69, 0x72, 0x69,
-0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e,
-0x6a, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x65, 0x65, 0x6c, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x65, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x20, 0x4d, 0x6f, 0xe7, 0x61, 0x6d,
-0x62, 0x69, 0x71, 0x75, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x6f, 0x6c, 0x61, 0x20, 0x79, 0x61, 0x73,
-0x65, 0x20, 0x41, 0x6d, 0x65, 0x6c, 0x69, 0x6b, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x68, 0x65, 0x6c, 0x65,
-0x72, 0x69, 0x20, 0x73, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x3b, 0x2d30, 0x2d37, 0x2d54, 0x2d49, 0x2d4e, 0x20, 0x2d4f, 0x20, 0x2d4d, 0x2d4e, 0x2d56, 0x2d54, 0x2d49, 0x2d31, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x3b, 0x3b, 0x61, 0x64, 0x72, 0x69, 0x6d, 0x20, 0x6e, 0x20, 0x6c, 0x6d, 0x263, 0x72, 0x69, 0x62, 0x3b, 0x3b, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x41, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x41, 0x7a, 0x7a, 0x61, 0x79, 0x72, 0x69, 0x3b, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x73, 0x68, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x55, 0x67, 0x61,
-0x6e, 0x64, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79,
-0x61, 0x20, 0x48, 0x75, 0x74, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53,
-0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x65, 0x66, 0x61, 0x20, 0x46, 0x72, 0x61, 0x14b, 0x20, 0x28, 0x42, 0x43, 0x45,
-0x41, 0x4f, 0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x55, 0x53, 0x20, 0x13a0, 0x13d5, 0x13b3, 0x3b, 0x3b, 0x55, 0x53,
-0x20, 0x13a0, 0x13d5, 0x13b3, 0x3b, 0x3b, 0x3b, 0x3b, 0x55, 0x53, 0x20, 0x13a0, 0x13d5, 0x13b3, 0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69,
-0x20, 0x6d, 0x6f, 0x72, 0x69, 0x73, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x68, 0x69, 0x6c,
-0xed, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61, 0x61, 0x6e, 0x73, 0x61, 0x6e, 0xed, 0x61, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x65, 0x79, 0x61, 0x20, 0x59, 0x75, 0x67,
-0x61, 0x6e, 0x64, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x6b, 0x75, 0x64, 0x75, 0x20, 0x4b, 0x61, 0x62,
-0x75, 0x76, 0x65, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x75, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x6b, 0x75, 0x64, 0x75,
-0x20, 0x4b, 0x61, 0x62, 0x75, 0x76, 0x65, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x75, 0x3b, 0x53, 0x69, 0x6c, 0x69, 0x6e, 0x67,
-0x69, 0x74, 0x61, 0x62, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x3b, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x49, 0x72, 0x6f, 0x70, 0x69, 0x79, 0x69,
-0x61, 0x6e, 0xed, 0x20, 0x65, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x49, 0x72,
-0x6f, 0x70, 0x69, 0x79, 0x69, 0x61, 0x6e, 0xed, 0x20, 0x65, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x69, 0x72, 0x69, 0x6e, 0x6a, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e,
-0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61,
-0x20, 0x54, 0x61, 0x6e, 0x64, 0x68, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x6e, 0x67,
-0x6f, 0x2019, 0x6f, 0x74, 0x6f, 0x6c, 0x20, 0x6c, 0x6f, 0x6b, 0x2019, 0x20, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x6e, 0x67, 0x6f, 0x2019, 0x6f, 0x74, 0x6f, 0x6c, 0x20, 0x6c, 0x6f, 0x6b, 0x2019, 0x20,
-0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x43, 0x46, 0x41, 0x20, 0x46, 0x72, 0x61, 0x14b,
-0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x69, 0x6c, 0x69, 0x6e,
-0x67, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x65,
-0x72, 0x68, 0x65, 0x6d, 0x20, 0x55, 0x6d, 0x65, 0x1e5b, 0x1e5b, 0x75, 0x6b, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x930, 0x93e, 0x902, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x420, 0x43e, 0x441,
-0x441, 0x438, 0x439, 0x43d, 0x20, 0x441, 0x43e, 0x43c, 0x3b, 0x3b, 0x420, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x43d, 0x20, 0x441, 0x43e,
-0x43c, 0x3b, 0x3b, 0x3b, 0x3b, 0x420, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x43d, 0x20, 0x441, 0x43e, 0x44c, 0x43c, 0x430, 0x448, 0x3b,
-0x440, 0x461, 0x441, 0x441, 0x456, 0x301, 0x439, 0x441, 0x43a, 0x457, 0x439, 0x20, 0x440, 0xa64b, 0x301, 0x431, 0x43b, 0x44c, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x440, 0x461, 0x441, 0x441, 0x456, 0x301, 0x439, 0x441, 0x43a, 0x430, 0x433, 0x461, 0x20, 0x440, 0xa64b, 0x431,
-0x43b, 0x467, 0x300, 0x3b, 0x4e, 0x66, 0x61, 0x6c, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x77, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67,
-0x75, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x43, 0x46, 0x41, 0x20, 0x46, 0xe0, 0x6c, 0xe2, 0x14b, 0x20, 0x42, 0x45,
-0x41, 0x43, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x72, 0x1ce, 0x14b, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42,
-0x45, 0x41, 0x43, 0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x65, 0x65, 0x66, 0x61, 0x20, 0x79, 0x61, 0x74,
-0x69, 0x20, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x259, 0x6c, 0xe1, 0x14b, 0x20,
-0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0xe1,
-0x14b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x6f, 0x6c, 0x61, 0x69, 0x20, 0x42, 0x45, 0x41, 0x43, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x72, 0x61, 0x14b, 0x20, 0x43, 0x46, 0x41, 0x20, 0x42, 0x45, 0x41, 0x43, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x410, 0x440, 0x430, 0x441, 0x441, 0x44b, 0x44b, 0x439, 0x430, 0x20, 0x441, 0x43e, 0x43b, 0x43a, 0x443,
-0x43e, 0x431, 0x430, 0x439, 0x430, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x410, 0x440, 0x430, 0x441, 0x441, 0x44b, 0x44b, 0x439, 0x430,
-0x20, 0x441, 0x43e, 0x43b, 0x43a, 0x443, 0x43e, 0x431, 0x430, 0x439, 0x430, 0x3b, 0x49, 0x68, 0x65, 0x6c, 0x61, 0x20, 0x79, 0x61,
-0x20, 0x54, 0x61, 0x6e, 0x73, 0x61, 0x6e, 0x69, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xa55e, 0xa524, 0xa52b,
-0xa569, 0x20, 0xa55c, 0xa55e, 0xa54c, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4c, 0x61, 0x69, 0x62, 0x68, 0x69, 0x79, 0x61,
-0x20, 0x44, 0x61, 0x6c, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x25b, 0x6c, 0xe2, 0x14b, 0x3b, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x41, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x73, 0x68, 0x69, 0x72, 0xe8, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x65, 0x6c, 0xe1, 0x14b, 0x20, 0x43, 0x46,
-0x41, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x62f, 0x6cc, 0x646, 0x627, 0x631, 0x6cc, 0x20, 0x639, 0x6ce, 0x631, 0x627, 0x642,
-0x6cc, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x695, 0x6cc, 0x627, 0x6b5, 0x6cc, 0x20, 0x626, 0x6ce, 0x631, 0x627, 0x646, 0x6cc,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75,
-0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b,
-0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x61, 0x6a, 0x3b, 0x65, 0x75, 0x72, 0x61, 0x3b, 0x3b, 0x65, 0x75, 0x72,
-0x6f, 0x77, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x20,
-0x631, 0x6cc, 0x627, 0x644, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x20, 0x631, 0x6cc, 0x627, 0x644,
-0x3b, 0x6e2f, 0x5e63, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x6e2f, 0x5e63, 0x3b
+0x43, 0x45, 0x41, 0x4f, 0x3b, 0x50, 0x69, 0x73, 0x6f, 0x20, 0x6e, 0x67, 0x20, 0x50, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e,
+0x61, 0x73, 0x3b, 0x3b, 0x70, 0x69, 0x73, 0x6f, 0x20, 0x6e, 0x67, 0x20, 0x50, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x61,
+0x73, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x69, 0x73, 0x6f, 0x20, 0x6e, 0x67, 0x20, 0x50, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e,
+0x61, 0x73, 0x3b, 0x53, 0x63, 0x68, 0x77, 0x69, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x3b,
+0x3b, 0x53, 0x63, 0x68, 0x77, 0x69, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x3b, 0x3b, 0x3b,
+0x3b, 0x53, 0x63, 0x68, 0x77, 0x69, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x3b, 0x45, 0x75,
+0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x6e, 0x6f, 0x72, 0x67, 0x67, 0x61, 0x20,
+0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x3b, 0x6e, 0x6f, 0x72, 0x67, 0x67, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76,
+0x64, 0x6e, 0x6f, 0x3b, 0x6e, 0x6f, 0x72, 0x67, 0x67, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x3b,
+0x3b, 0x6e, 0x6f, 0x72, 0x67, 0x67, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f,
+0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x72,
+0x75, 0x6f, 0x167, 0x167, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x3b, 0x72, 0x75, 0x6f, 0x167, 0x167,
+0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x72, 0x75, 0x6f, 0x167, 0x167, 0x61, 0x20, 0x6b, 0x72, 0x75,
+0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x72, 0x75, 0x6f, 0x167, 0x167, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e,
+0x6f, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x62, 0x75, 0x75, 0x257, 0x75, 0x20, 0x53, 0x65, 0x65, 0x66, 0x61, 0x61, 0x20,
+0x42, 0x43, 0x45, 0x41, 0x4f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x62, 0x75, 0x75, 0x257, 0x69, 0x20, 0x53,
+0x65, 0x65, 0x66, 0x61, 0x61, 0x20, 0x42, 0x45, 0x41, 0x43, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x61, 0x6c,
+0x61, 0x73, 0x69, 0x20, 0x47, 0x61, 0x6d, 0x6d, 0x62, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x6f, 0x6c,
+0x61, 0x61, 0x72, 0x20, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x69, 0x79, 0x61, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x55, 0x67, 0x69, 0x79, 0x79, 0x61, 0x20, 0x4d, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x4e, 0x61, 0x79, 0x72, 0x61, 0x61, 0x20, 0x4e, 0x69, 0x6a, 0x65, 0x72, 0x69, 0x79, 0x61, 0x61, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4c, 0x65, 0x77, 0x6f, 0x6f, 0x6e, 0x20, 0x53, 0x65, 0x72, 0x61, 0x61, 0x20, 0x4c, 0x69,
+0x79, 0x6f, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x43, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61,
+0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x6a, 0x69, 0x6c, 0x69, 0x6e, 0x67,
+0x69, 0x20, 0x65, 0x65, 0x6c, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x65,
+0x74, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x20, 0x4d, 0x6f, 0xe7, 0x61, 0x6d, 0x62, 0x69, 0x71, 0x75, 0x65, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x6f, 0x6c, 0x61, 0x20, 0x79, 0x61, 0x73, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x6c,
+0x69, 0x6b, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x68, 0x65, 0x6c, 0x65, 0x72, 0x69, 0x20, 0x73, 0x61, 0x20,
+0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x2d30, 0x2d37, 0x2d54, 0x2d49, 0x2d4e,
+0x20, 0x2d4f, 0x20, 0x2d4d, 0x2d4e, 0x2d56, 0x2d54, 0x2d49, 0x2d31, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x61, 0x64, 0x72, 0x69,
+0x6d, 0x20, 0x6e, 0x20, 0x6c, 0x6d, 0x263, 0x72, 0x69, 0x62, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x64, 0x69,
+0x6e, 0x61, 0x72, 0x20, 0x41, 0x7a, 0x7a, 0x61, 0x79, 0x72, 0x69, 0x3b, 0x3b, 0x41, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x20,
+0x6e, 0x20, 0x5a, 0x7a, 0x61, 0x79, 0x65, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x49, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x65, 0x6e,
+0x20, 0x6e, 0x20, 0x5a, 0x7a, 0x61, 0x79, 0x65, 0x72, 0x3b, 0x45, 0x73, 0x68, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x20,
+0x79, 0x61, 0x20, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x68, 0x69, 0x6c,
+0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x48, 0x75, 0x74, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61, 0x6e,
+0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x65, 0x66, 0x61, 0x20, 0x46, 0x72, 0x61,
+0x14b, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x55, 0x53, 0x20, 0x13a0,
+0x13d5, 0x13b3, 0x3b, 0x3b, 0x55, 0x53, 0x20, 0x13a0, 0x13d5, 0x13b3, 0x3b, 0x3b, 0x3b, 0x3b, 0x55, 0x53, 0x20, 0x13a0, 0x13d5, 0x13b3,
+0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x20, 0x6d, 0x6f, 0x72, 0x69, 0x73, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0xed, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61, 0x61, 0x6e, 0x73,
+0x61, 0x6e, 0xed, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x65,
+0x79, 0x61, 0x20, 0x59, 0x75, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x6b, 0x75,
+0x64, 0x75, 0x20, 0x4b, 0x61, 0x62, 0x75, 0x76, 0x65, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x75, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x53, 0x6b, 0x75, 0x64, 0x75, 0x20, 0x4b, 0x61, 0x62, 0x75, 0x76, 0x65, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x75, 0x3b,
+0x53, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x74, 0x61, 0x62, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
+0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x49,
+0x72, 0x6f, 0x70, 0x69, 0x79, 0x69, 0x61, 0x6e, 0xed, 0x20, 0x65, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x49, 0x72, 0x6f, 0x70, 0x69, 0x79, 0x69, 0x61, 0x6e, 0xed, 0x20, 0x65, 0x20, 0x54, 0x61, 0x6e,
+0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x69, 0x72, 0x69, 0x6e, 0x6a, 0x69, 0x20,
+0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69,
+0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x64, 0x68, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x41, 0x6e, 0x67, 0x6f, 0x2019, 0x6f, 0x74, 0x6f, 0x6c, 0x20, 0x6c, 0x6f, 0x6b, 0x2019, 0x20, 0x55, 0x67,
+0x61, 0x6e, 0x64, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x6e, 0x67, 0x6f, 0x2019, 0x6f, 0x74, 0x6f, 0x6c,
+0x20, 0x6c, 0x6f, 0x6b, 0x2019, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x43, 0x46,
+0x41, 0x20, 0x46, 0x72, 0x61, 0x14b, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x53, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x65, 0x72, 0x68, 0x65, 0x6d, 0x20, 0x55, 0x6d, 0x65, 0x1e5b, 0x1e5b, 0x75, 0x6b, 0x69, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61,
+0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x930, 0x93e, 0x902, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x420, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x43d, 0x20, 0x441, 0x43e, 0x43c, 0x3b, 0x3b, 0x420, 0x43e, 0x441, 0x441,
+0x438, 0x439, 0x43d, 0x20, 0x441, 0x43e, 0x43c, 0x3b, 0x3b, 0x3b, 0x3b, 0x420, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x43d, 0x20, 0x441,
+0x43e, 0x44c, 0x43c, 0x430, 0x448, 0x3b, 0x440, 0x461, 0x441, 0x441, 0x456, 0x301, 0x439, 0x441, 0x43a, 0x457, 0x439, 0x20, 0x440, 0xa64b,
+0x301, 0x431, 0x43b, 0x44c, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x440, 0x461, 0x441, 0x441, 0x456, 0x301, 0x439, 0x441, 0x43a, 0x430,
+0x433, 0x461, 0x20, 0x440, 0xa64b, 0x431, 0x43b, 0x467, 0x300, 0x3b, 0x4e, 0x66, 0x61, 0x6c, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x77,
+0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x75, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x43, 0x46, 0x41, 0x20, 0x46, 0xe0,
+0x6c, 0xe2, 0x14b, 0x20, 0x42, 0x45, 0x41, 0x43, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x72, 0x1ce, 0x14b, 0x20,
+0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x65, 0x65,
+0x66, 0x61, 0x20, 0x79, 0x61, 0x74, 0x69, 0x20, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x46, 0x259, 0x6c, 0xe1, 0x14b, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x66, 0x72, 0xe1, 0x14b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x6f, 0x6c, 0x61, 0x69, 0x20,
+0x42, 0x45, 0x41, 0x43, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x72, 0x61, 0x14b, 0x20, 0x43, 0x46, 0x41, 0x20,
+0x42, 0x45, 0x41, 0x43, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x410, 0x440, 0x430, 0x441, 0x441, 0x44b, 0x44b, 0x439, 0x430,
+0x20, 0x441, 0x43e, 0x43b, 0x43a, 0x443, 0x43e, 0x431, 0x430, 0x439, 0x430, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x410, 0x440, 0x430,
+0x441, 0x441, 0x44b, 0x44b, 0x439, 0x430, 0x20, 0x441, 0x43e, 0x43b, 0x43a, 0x443, 0x43e, 0x431, 0x430, 0x439, 0x430, 0x3b, 0x49, 0x68,
+0x65, 0x6c, 0x61, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x73, 0x61, 0x6e, 0x69, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0xa55e, 0xa524, 0xa52b, 0xa569, 0x20, 0xa55c, 0xa55e, 0xa54c, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4c, 0x61,
+0x69, 0x62, 0x68, 0x69, 0x79, 0x61, 0x20, 0x44, 0x61, 0x6c, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x25b,
+0x6c, 0xe2, 0x14b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x41, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x72, 0xe8, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x65,
+0x6c, 0xe1, 0x14b, 0x20, 0x43, 0x46, 0x41, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x62f, 0x6cc, 0x646, 0x627, 0x631, 0x6cc,
+0x20, 0x639, 0x6ce, 0x631, 0x627, 0x642, 0x6cc, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x695, 0x6cc, 0x627, 0x6b5, 0x6cc, 0x20,
+0x626, 0x6ce, 0x631, 0x627, 0x646, 0x6cc, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65,
+0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b,
+0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x61, 0x6a, 0x3b, 0x65, 0x75, 0x72,
+0x61, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x77, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x627, 0x6cc, 0x631, 0x627, 0x646, 0x20, 0x631, 0x6cc, 0x627, 0x644, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x627, 0x6cc, 0x631, 0x627,
+0x646, 0x20, 0x631, 0x6cc, 0x627, 0x644, 0x3b, 0x6e2f, 0x5e63, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x6e2f, 0x5e63, 0x3b
};
static const ushort currency_format_data[] = {
0x25, 0x31, 0x25, 0x32, 0x25, 0x32, 0x25, 0x31, 0x25, 0x32, 0xa0, 0x25, 0x31, 0x25, 0x31, 0xa0, 0x25, 0x32, 0x25, 0x32,
0x25, 0x31, 0x4b, 0x25, 0x32, 0xa0, 0x2d, 0x25, 0x31, 0x28, 0x25, 0x31, 0xa0, 0x25, 0x32, 0x29, 0x25, 0x32, 0x2d, 0x25,
-0x31, 0x25, 0x31, 0xa0, 0x6d, 0x6e, 0xa0, 0x25, 0x32, 0x25, 0x32, 0xa0, 0x25, 0x31, 0x2d, 0x25, 0x32, 0x2212, 0x25, 0x31,
-0x200f, 0x25, 0x31, 0xa0, 0x25, 0x32, 0x200f, 0x200e, 0x2d, 0x25, 0x31, 0xa0, 0x25, 0x32, 0x200e, 0x25, 0x32, 0x25, 0x31, 0x25,
-0x32, 0xa0, 0x25, 0x31, 0x4b, 0x28, 0x25, 0x32, 0x25, 0x31, 0x29, 0x25, 0x32, 0x2d, 0xa0, 0x25, 0x31
+0x31, 0x25, 0x32, 0xa0, 0x25, 0x31, 0x4b, 0x25, 0x31, 0xa0, 0x6b, 0x25, 0x32, 0x2d, 0x25, 0x31, 0xa0, 0x25, 0x32, 0x25,
+0x32, 0xa0, 0x25, 0x31, 0x2d, 0x25, 0x32, 0x2212, 0x25, 0x31, 0x200f, 0x25, 0x31, 0xa0, 0x25, 0x32, 0x200f, 0x200e, 0x2d, 0x25,
+0x31, 0xa0, 0x25, 0x32, 0x200e, 0x25, 0x32, 0x25, 0x31, 0x28, 0x25, 0x32, 0x25, 0x31, 0x29, 0x25, 0x31, 0xa0, 0x4b, 0xa0,
+0x25, 0x32, 0x25, 0x32, 0x2d, 0xa0, 0x25, 0x31
};
static const ushort endonyms_data[] = {
@@ -5862,273 +6129,287 @@ static const ushort endonyms_data[] = {
0x648, 0x645, 0x627, 0x644, 0x627, 0x644, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x633, 0x648, 0x631, 0x64a, 0x627, 0x62a, 0x648, 0x646, 0x633,
0x627, 0x644, 0x625, 0x645, 0x627, 0x631, 0x627, 0x62a, 0x20, 0x627, 0x644, 0x639, 0x631, 0x628, 0x64a, 0x629, 0x20, 0x627, 0x644, 0x645,
0x62a, 0x62d, 0x62f, 0x629, 0x627, 0x644, 0x635, 0x62d, 0x631, 0x627, 0x621, 0x20, 0x627, 0x644, 0x63a, 0x631, 0x628, 0x64a, 0x629, 0x627,
-0x644, 0x64a, 0x645, 0x646, 0x62c, 0x646, 0x648, 0x628, 0x20, 0x627, 0x644, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x570, 0x561, 0x575, 0x565,
-0x580, 0x565, 0x576, 0x540, 0x561, 0x575, 0x561, 0x57d, 0x57f, 0x561, 0x576, 0x985, 0x9b8, 0x9ae, 0x9c0, 0x9af, 0x9bc, 0x9be, 0x9ad, 0x9be,
-0x9f0, 0x9a4, 0x61, 0x7a, 0x259, 0x72, 0x62, 0x61, 0x79, 0x63, 0x61, 0x6e, 0x41, 0x7a, 0x259, 0x72, 0x62, 0x61, 0x79, 0x63,
-0x61, 0x6e, 0x430, 0x437, 0x4d9, 0x440, 0x431, 0x430, 0x458, 0x4b9, 0x430, 0x43d, 0x410, 0x437, 0x4d9, 0x440, 0x431, 0x430, 0x458, 0x4b9,
-0x430, 0x43d, 0x65, 0x75, 0x73, 0x6b, 0x61, 0x72, 0x61, 0x45, 0x73, 0x70, 0x61, 0x69, 0x6e, 0x69, 0x61, 0x9ac, 0x9be, 0x982,
-0x9b2, 0x9be, 0x9ac, 0x9be, 0x982, 0x9b2, 0x9be, 0x9a6, 0x9c7, 0x9b6, 0x9ad, 0x9be, 0x9b0, 0x9a4, 0xf62, 0xfab, 0xf7c, 0xf44, 0xf0b, 0xf41,
-0xf60, 0xf56, 0xfb2, 0xf74, 0xf42, 0x62, 0x72, 0x65, 0x7a, 0x68, 0x6f, 0x6e, 0x65, 0x67, 0x46, 0x72, 0x61, 0xf1, 0x73, 0x431,
-0x44a, 0x43b, 0x433, 0x430, 0x440, 0x441, 0x43a, 0x438, 0x411, 0x44a, 0x43b, 0x433, 0x430, 0x440, 0x438, 0x44f, 0x1019, 0x103c, 0x1014, 0x103a,
-0x1019, 0x102c, 0x431, 0x435, 0x43b, 0x430, 0x440, 0x443, 0x441, 0x43a, 0x430, 0x44f, 0x411, 0x435, 0x43b, 0x430, 0x440, 0x443, 0x441, 0x44c,
-0x1781, 0x17d2, 0x1798, 0x17c2, 0x179a, 0x1780, 0x1798, 0x17d2, 0x1796, 0x17bb, 0x1787, 0x17b6, 0x63, 0x61, 0x74, 0x61, 0x6c, 0xe0, 0x45, 0x73,
-0x70, 0x61, 0x6e, 0x79, 0x61, 0x41, 0x6e, 0x64, 0x6f, 0x72, 0x72, 0x61, 0x46, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x49, 0x74,
-0xe0, 0x6c, 0x69, 0x61, 0x7b80, 0x4f53, 0x4e2d, 0x6587, 0x4e2d, 0x56fd, 0x4e2d, 0x56fd, 0x9999, 0x6e2f, 0x7279, 0x522b, 0x884c, 0x653f, 0x533a, 0x4e2d,
-0x56fd, 0x6fb3, 0x95e8, 0x7279, 0x522b, 0x884c, 0x653f, 0x533a, 0x65b0, 0x52a0, 0x5761, 0x7e41, 0x9ad4, 0x4e2d, 0x6587, 0x4e2d, 0x570b, 0x9999, 0x6e2f, 0x7279,
-0x5225, 0x884c, 0x653f, 0x5340, 0x4e2d, 0x570b, 0x6fb3, 0x9580, 0x7279, 0x5225, 0x884c, 0x653f, 0x5340, 0x53f0, 0x7063, 0x68, 0x72, 0x76, 0x61, 0x74,
-0x73, 0x6b, 0x69, 0x48, 0x72, 0x76, 0x61, 0x74, 0x73, 0x6b, 0x61, 0x42, 0x6f, 0x73, 0x6e, 0x61, 0x20, 0x69, 0x20, 0x48,
-0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x69, 0x6e, 0x61, 0x10d, 0x65, 0x161, 0x74, 0x69, 0x6e, 0x61, 0x10c, 0x65, 0x73,
-0x6b, 0x6f, 0x64, 0x61, 0x6e, 0x73, 0x6b, 0x44, 0x61, 0x6e, 0x6d, 0x61, 0x72, 0x6b, 0x47, 0x72, 0xf8, 0x6e, 0x6c, 0x61,
-0x6e, 0x64, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e,
-0x64, 0x41, 0x72, 0x75, 0x62, 0x61, 0x42, 0x65, 0x6c, 0x67, 0x69, 0xeb, 0x43, 0x75, 0x72, 0x61, 0xe7, 0x61, 0x6f, 0x53,
-0x75, 0x72, 0x69, 0x6e, 0x61, 0x6d, 0x65, 0x43, 0x61, 0x72, 0x69, 0x62, 0x69, 0x73, 0x63, 0x68, 0x20, 0x4e, 0x65, 0x64,
-0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x53, 0x69, 0x6e, 0x74, 0x2d, 0x4d, 0x61, 0x61, 0x72, 0x74, 0x65, 0x6e, 0x41, 0x6d,
-0x65, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x55, 0x6e, 0x69, 0x74, 0x65, 0x64,
-0x20, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
-0x61, 0x6e, 0x20, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x41, 0x6e, 0x67, 0x75, 0x69, 0x6c, 0x6c, 0x61, 0x41, 0x6e, 0x74, 0x69,
-0x67, 0x75, 0x61, 0x20, 0x26, 0x20, 0x42, 0x61, 0x72, 0x62, 0x75, 0x64, 0x61, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c,
-0x69, 0x61, 0x6e, 0x20, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
-0x41, 0x75, 0x73, 0x74, 0x72, 0x69, 0x61, 0x42, 0x61, 0x68, 0x61, 0x6d, 0x61, 0x73, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64,
-0x6f, 0x73, 0x42, 0x65, 0x6c, 0x67, 0x69, 0x75, 0x6d, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65, 0x42, 0x65, 0x72, 0x6d, 0x75,
-0x64, 0x61, 0x42, 0x6f, 0x74, 0x73, 0x77, 0x61, 0x6e, 0x61, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68, 0x20, 0x49, 0x6e,
-0x64, 0x69, 0x61, 0x6e, 0x20, 0x4f, 0x63, 0x65, 0x61, 0x6e, 0x20, 0x54, 0x65, 0x72, 0x72, 0x69, 0x74, 0x6f, 0x72, 0x79,
-0x42, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x43, 0x61, 0x6d, 0x65, 0x72, 0x6f, 0x6f, 0x6e, 0x43, 0x61, 0x6e, 0x61, 0x64,
-0x69, 0x61, 0x6e, 0x20, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x43, 0x61, 0x79,
-0x6d, 0x61, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x43, 0x68, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73,
-0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x43, 0x6f, 0x63, 0x6f, 0x73, 0x20, 0x28, 0x4b, 0x65, 0x65, 0x6c, 0x69, 0x6e,
-0x67, 0x29, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x43, 0x6f, 0x6f, 0x6b, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e,
-0x64, 0x73, 0x43, 0x79, 0x70, 0x72, 0x75, 0x73, 0x44, 0x65, 0x6e, 0x6d, 0x61, 0x72, 0x6b, 0x44, 0x6f, 0x6d, 0x69, 0x6e,
-0x69, 0x63, 0x61, 0x45, 0x72, 0x69, 0x74, 0x72, 0x65, 0x61, 0x46, 0x61, 0x6c, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x49,
-0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x46, 0x69, 0x6a, 0x69, 0x46, 0x69, 0x6e, 0x6c, 0x61, 0x6e, 0x64, 0x47, 0x75, 0x65,
-0x72, 0x6e, 0x73, 0x65, 0x79, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x47, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x79, 0x47, 0x68,
-0x61, 0x6e, 0x61, 0x47, 0x69, 0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x47, 0x72, 0x65, 0x6e, 0x61, 0x64, 0x61, 0x47,
-0x75, 0x61, 0x6d, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x48, 0x6f, 0x6e, 0x67, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x20, 0x53,
-0x41, 0x52, 0x20, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x49, 0x72, 0x65, 0x6c, 0x61, 0x6e, 0x64,
-0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x4a, 0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x4b, 0x69,
-0x72, 0x69, 0x62, 0x61, 0x74, 0x69, 0x4c, 0x65, 0x73, 0x6f, 0x74, 0x68, 0x6f, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x69, 0x61,
-0x4d, 0x61, 0x63, 0x61, 0x75, 0x20, 0x53, 0x41, 0x52, 0x20, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x4d, 0x61, 0x64, 0x61, 0x67,
-0x61, 0x73, 0x63, 0x61, 0x72, 0x4d, 0x61, 0x6c, 0x61, 0x77, 0x69, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x4d,
-0x61, 0x6c, 0x74, 0x61, 0x4d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73,
-0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x6e, 0x65, 0x73, 0x69, 0x61, 0x4d,
-0x6f, 0x6e, 0x74, 0x73, 0x65, 0x72, 0x72, 0x61, 0x74, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61, 0x4e, 0x61, 0x75, 0x72,
-0x75, 0x4e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c,
-0x61, 0x6e, 0x64, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, 0x4e, 0x69, 0x75, 0x65, 0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c,
-0x6b, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x65, 0x72, 0x6e, 0x20, 0x4d, 0x61, 0x72,
-0x69, 0x61, 0x6e, 0x61, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x50, 0x61, 0x6b, 0x69, 0x73, 0x74, 0x61, 0x6e,
-0x50, 0x61, 0x6c, 0x61, 0x75, 0x50, 0x61, 0x70, 0x75, 0x61, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x47, 0x75, 0x69, 0x6e, 0x65,
-0x61, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x73, 0x50, 0x69, 0x74, 0x63, 0x61, 0x69, 0x72, 0x6e,
-0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x50, 0x75, 0x65, 0x72, 0x74, 0x6f, 0x20, 0x52, 0x69, 0x63, 0x6f, 0x52,
-0x77, 0x61, 0x6e, 0x64, 0x61, 0x53, 0x74, 0x2e, 0x20, 0x4b, 0x69, 0x74, 0x74, 0x73, 0x20, 0x26, 0x20, 0x4e, 0x65, 0x76,
-0x69, 0x73, 0x53, 0x74, 0x2e, 0x20, 0x4c, 0x75, 0x63, 0x69, 0x61, 0x53, 0x74, 0x2e, 0x20, 0x56, 0x69, 0x6e, 0x63, 0x65,
-0x6e, 0x74, 0x20, 0x26, 0x20, 0x47, 0x72, 0x65, 0x6e, 0x61, 0x64, 0x69, 0x6e, 0x65, 0x73, 0x53, 0x61, 0x6d, 0x6f, 0x61,
-0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x65, 0x73, 0x53, 0x69, 0x65, 0x72, 0x72, 0x61, 0x20, 0x4c, 0x65, 0x6f,
-0x6e, 0x65, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x53, 0x6c, 0x6f, 0x76, 0x65, 0x6e, 0x69, 0x61, 0x53,
-0x6f, 0x6c, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20,
-0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x53, 0x74, 0x2e, 0x20, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x53, 0x75, 0x64, 0x61,
-0x6e, 0x53, 0x77, 0x61, 0x7a, 0x69, 0x6c, 0x61, 0x6e, 0x64, 0x53, 0x77, 0x65, 0x64, 0x65, 0x6e, 0x53, 0x77, 0x69, 0x74,
-0x7a, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x54, 0x6f, 0x6b, 0x65, 0x6c,
-0x61, 0x75, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x54, 0x72, 0x69, 0x6e, 0x69, 0x64, 0x61, 0x64, 0x20, 0x26, 0x20, 0x54, 0x6f,
-0x62, 0x61, 0x67, 0x6f, 0x54, 0x75, 0x72, 0x6b, 0x73, 0x20, 0x26, 0x20, 0x43, 0x61, 0x69, 0x63, 0x6f, 0x73, 0x20, 0x49,
-0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x54, 0x75, 0x76, 0x61, 0x6c, 0x75, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x42, 0x72,
-0x69, 0x74, 0x69, 0x73, 0x68, 0x20, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x55, 0x6e, 0x69, 0x74, 0x65, 0x64, 0x20,
-0x4b, 0x69, 0x6e, 0x67, 0x64, 0x6f, 0x6d, 0x55, 0x2e, 0x53, 0x2e, 0x20, 0x4f, 0x75, 0x74, 0x6c, 0x79, 0x69, 0x6e, 0x67,
-0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x56, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x42, 0x72, 0x69, 0x74, 0x69,
-0x73, 0x68, 0x20, 0x56, 0x69, 0x72, 0x67, 0x69, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x55, 0x2e, 0x53,
-0x2e, 0x20, 0x56, 0x69, 0x72, 0x67, 0x69, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x5a, 0x61, 0x6d, 0x62,
-0x69, 0x61, 0x5a, 0x69, 0x6d, 0x62, 0x61, 0x62, 0x77, 0x65, 0x44, 0x69, 0x65, 0x67, 0x6f, 0x20, 0x47, 0x61, 0x72, 0x63,
-0x69, 0x61, 0x49, 0x73, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x4d, 0x61, 0x6e, 0x4a, 0x65, 0x72, 0x73, 0x65, 0x79, 0x53,
-0x6f, 0x75, 0x74, 0x68, 0x20, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x53, 0x69, 0x6e, 0x74, 0x20, 0x4d, 0x61, 0x61, 0x72, 0x74,
-0x65, 0x6e, 0x65, 0x65, 0x73, 0x74, 0x69, 0x45, 0x65, 0x73, 0x74, 0x69, 0x66, 0xf8, 0x72, 0x6f, 0x79, 0x73, 0x6b, 0x74,
-0x46, 0xf8, 0x72, 0x6f, 0x79, 0x61, 0x72, 0x73, 0x75, 0x6f, 0x6d, 0x69, 0x53, 0x75, 0x6f, 0x6d, 0x69, 0x66, 0x72, 0x61,
-0x6e, 0xe7, 0x61, 0x69, 0x73, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x6c, 0x67, 0xe9, 0x72, 0x69, 0x65, 0x42, 0x65,
-0x6c, 0x67, 0x69, 0x71, 0x75, 0x65, 0x42, 0xe9, 0x6e, 0x69, 0x6e, 0x42, 0x75, 0x72, 0x6b, 0x69, 0x6e, 0x61, 0x20, 0x46,
-0x61, 0x73, 0x6f, 0x43, 0x61, 0x6d, 0x65, 0x72, 0x6f, 0x75, 0x6e, 0x66, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x69, 0x73, 0x20,
-0x63, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x52, 0xe9, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x71, 0x75, 0x65, 0x20, 0x63,
-0x65, 0x6e, 0x74, 0x72, 0x61, 0x66, 0x72, 0x69, 0x63, 0x61, 0x69, 0x6e, 0x65, 0x54, 0x63, 0x68, 0x61, 0x64, 0x43, 0x6f,
-0x6d, 0x6f, 0x72, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x67, 0x6f, 0x2d, 0x4b, 0x69, 0x6e, 0x73, 0x68, 0x61, 0x73, 0x61, 0x43,
-0x6f, 0x6e, 0x67, 0x6f, 0x2d, 0x42, 0x72, 0x61, 0x7a, 0x7a, 0x61, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x43, 0xf4, 0x74, 0x65,
-0x20, 0x64, 0x2019, 0x49, 0x76, 0x6f, 0x69, 0x72, 0x65, 0x44, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x47, 0x75, 0x69,
-0x6e, 0xe9, 0x65, 0x20, 0xe9, 0x71, 0x75, 0x61, 0x74, 0x6f, 0x72, 0x69, 0x61, 0x6c, 0x65, 0x47, 0x75, 0x79, 0x61, 0x6e,
-0x65, 0x20, 0x66, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x69, 0x73, 0x65, 0x50, 0x6f, 0x6c, 0x79, 0x6e, 0xe9, 0x73, 0x69, 0x65,
-0x20, 0x66, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x69, 0x73, 0x65, 0x47, 0x61, 0x62, 0x6f, 0x6e, 0x47, 0x75, 0x61, 0x64, 0x65,
-0x6c, 0x6f, 0x75, 0x70, 0x65, 0x47, 0x75, 0x69, 0x6e, 0xe9, 0x65, 0x48, 0x61, 0xef, 0x74, 0x69, 0x4c, 0x75, 0x78, 0x65,
-0x6d, 0x62, 0x6f, 0x75, 0x72, 0x67, 0x4d, 0x61, 0x6c, 0x69, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x69, 0x71, 0x75, 0x65,
-0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x65, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x63, 0x65, 0x4d, 0x61, 0x79,
-0x6f, 0x74, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x61, 0x63, 0x6f, 0x4d, 0x61, 0x72, 0x6f, 0x63, 0x4e, 0x6f, 0x75, 0x76, 0x65,
-0x6c, 0x6c, 0x65, 0x2d, 0x43, 0x61, 0x6c, 0xe9, 0x64, 0x6f, 0x6e, 0x69, 0x65, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x4c, 0x61,
-0x20, 0x52, 0xe9, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x53, 0xe9, 0x6e, 0xe9, 0x67, 0x61, 0x6c, 0x53, 0x61, 0x69, 0x6e, 0x74,
-0x2d, 0x50, 0x69, 0x65, 0x72, 0x72, 0x65, 0x2d, 0x65, 0x74, 0x2d, 0x4d, 0x69, 0x71, 0x75, 0x65, 0x6c, 0x6f, 0x6e, 0x66,
-0x72, 0x61, 0x6e, 0xe7, 0x61, 0x69, 0x73, 0x20, 0x73, 0x75, 0x69, 0x73, 0x73, 0x65, 0x53, 0x75, 0x69, 0x73, 0x73, 0x65,
-0x53, 0x79, 0x72, 0x69, 0x65, 0x54, 0x6f, 0x67, 0x6f, 0x54, 0x75, 0x6e, 0x69, 0x73, 0x69, 0x65, 0x57, 0x61, 0x6c, 0x6c,
-0x69, 0x73, 0x2d, 0x65, 0x74, 0x2d, 0x46, 0x75, 0x74, 0x75, 0x6e, 0x61, 0x53, 0x61, 0x69, 0x6e, 0x74, 0x2d, 0x42, 0x61,
-0x72, 0x74, 0x68, 0xe9, 0x6c, 0x65, 0x6d, 0x79, 0x53, 0x61, 0x69, 0x6e, 0x74, 0x2d, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e,
-0x57, 0x65, 0x73, 0x74, 0x2d, 0x46, 0x72, 0x79, 0x73, 0x6b, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0xe2, 0x6e, 0x47, 0xe0,
-0x69, 0x64, 0x68, 0x6c, 0x69, 0x67, 0x41, 0x6e, 0x20, 0x52, 0xec, 0x6f, 0x67, 0x68, 0x61, 0x63, 0x68, 0x64, 0x20, 0x41,
-0x6f, 0x6e, 0x61, 0x69, 0x63, 0x68, 0x74, 0x65, 0x67, 0x61, 0x6c, 0x65, 0x67, 0x6f, 0x45, 0x73, 0x70, 0x61, 0xf1, 0x61,
-0x10e5, 0x10d0, 0x10e0, 0x10d7, 0x10e3, 0x10da, 0x10d8, 0x10e1, 0x10d0, 0x10e5, 0x10d0, 0x10e0, 0x10d7, 0x10d5, 0x10d4, 0x10da, 0x10dd, 0x44, 0x65, 0x75,
-0x74, 0x73, 0x63, 0x68, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x6c, 0x61, 0x6e, 0x64, 0xd6, 0x73, 0x74, 0x65, 0x72,
-0x72, 0x65, 0x69, 0x63, 0x68, 0x69, 0x73, 0x63, 0x68, 0x65, 0x73, 0x20, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0xd6,
-0x73, 0x74, 0x65, 0x72, 0x72, 0x65, 0x69, 0x63, 0x68, 0x42, 0x65, 0x6c, 0x67, 0x69, 0x65, 0x6e, 0x49, 0x74, 0x61, 0x6c,
-0x69, 0x65, 0x6e, 0x4c, 0x69, 0x65, 0x63, 0x68, 0x74, 0x65, 0x6e, 0x73, 0x74, 0x65, 0x69, 0x6e, 0x4c, 0x75, 0x78, 0x65,
-0x6d, 0x62, 0x75, 0x72, 0x67, 0x53, 0x63, 0x68, 0x77, 0x65, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x48, 0x6f, 0x63, 0x68, 0x64,
-0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x53, 0x63, 0x68, 0x77, 0x65, 0x69, 0x7a, 0x395, 0x3bb, 0x3bb, 0x3b7, 0x3bd, 0x3b9, 0x3ba,
-0x3ac, 0x395, 0x3bb, 0x3bb, 0x3ac, 0x3b4, 0x3b1, 0x39a, 0x3cd, 0x3c0, 0x3c1, 0x3bf, 0x3c2, 0x6b, 0x61, 0x6c, 0x61, 0x61, 0x6c, 0x6c,
-0x69, 0x73, 0x75, 0x74, 0x4b, 0x61, 0x6c, 0x61, 0x61, 0x6c, 0x6c, 0x69, 0x74, 0x20, 0x4e, 0x75, 0x6e, 0x61, 0x61, 0x74,
-0xa97, 0xac1, 0xa9c, 0xab0, 0xabe, 0xaa4, 0xac0, 0xaad, 0xabe, 0xab0, 0xaa4, 0x48, 0x61, 0x75, 0x73, 0x61, 0x4e, 0x61, 0x6a, 0x65,
-0x72, 0x69, 0x79, 0x61, 0x47, 0x61, 0x6e, 0x61, 0x4e, 0x69, 0x6a, 0x61, 0x72, 0x5e2, 0x5d1, 0x5e8, 0x5d9, 0x5ea, 0x5d9, 0x5e9,
-0x5e8, 0x5d0, 0x5dc, 0x939, 0x93f, 0x928, 0x94d, 0x926, 0x940, 0x92d, 0x93e, 0x930, 0x924, 0x6d, 0x61, 0x67, 0x79, 0x61, 0x72, 0x4d,
-0x61, 0x67, 0x79, 0x61, 0x72, 0x6f, 0x72, 0x73, 0x7a, 0xe1, 0x67, 0xed, 0x73, 0x6c, 0x65, 0x6e, 0x73, 0x6b, 0x61, 0xcd,
-0x73, 0x6c, 0x61, 0x6e, 0x64, 0x49, 0x6e, 0x64, 0x6f, 0x6e, 0x65, 0x73, 0x69, 0x61, 0x47, 0x61, 0x65, 0x69, 0x6c, 0x67,
+0x644, 0x64a, 0x645, 0x646, 0x62c, 0x646, 0x648, 0x628, 0x20, 0x627, 0x644, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x627, 0x644, 0x639, 0x631,
+0x628, 0x64a, 0x629, 0x20, 0x627, 0x644, 0x631, 0x633, 0x645, 0x64a, 0x629, 0x20, 0x627, 0x644, 0x62d, 0x62f, 0x64a, 0x62b, 0x629, 0x627,
+0x644, 0x639, 0x627, 0x644, 0x645, 0x570, 0x561, 0x575, 0x565, 0x580, 0x565, 0x576, 0x540, 0x561, 0x575, 0x561, 0x57d, 0x57f, 0x561, 0x576,
+0x985, 0x9b8, 0x9ae, 0x9c0, 0x9af, 0x9bc, 0x9be, 0x9ad, 0x9be, 0x9f0, 0x9a4, 0x61, 0x7a, 0x259, 0x72, 0x62, 0x61, 0x79, 0x63, 0x61,
+0x6e, 0x41, 0x7a, 0x259, 0x72, 0x62, 0x61, 0x79, 0x63, 0x61, 0x6e, 0x430, 0x437, 0x4d9, 0x440, 0x431, 0x430, 0x458, 0x4b9, 0x430,
+0x43d, 0x410, 0x437, 0x4d9, 0x440, 0x431, 0x430, 0x458, 0x4b9, 0x430, 0x43d, 0x65, 0x75, 0x73, 0x6b, 0x61, 0x72, 0x61, 0x45, 0x73,
+0x70, 0x61, 0x69, 0x6e, 0x69, 0x61, 0x9ac, 0x9be, 0x982, 0x9b2, 0x9be, 0x9ac, 0x9be, 0x982, 0x9b2, 0x9be, 0x9a6, 0x9c7, 0x9b6, 0x9ad,
+0x9be, 0x9b0, 0x9a4, 0xf62, 0xfab, 0xf7c, 0xf44, 0xf0b, 0xf41, 0xf60, 0xf56, 0xfb2, 0xf74, 0xf42, 0x62, 0x72, 0x65, 0x7a, 0x68, 0x6f,
+0x6e, 0x65, 0x67, 0x46, 0x72, 0x61, 0xf1, 0x73, 0x431, 0x44a, 0x43b, 0x433, 0x430, 0x440, 0x441, 0x43a, 0x438, 0x411, 0x44a, 0x43b,
+0x433, 0x430, 0x440, 0x438, 0x44f, 0x1019, 0x103c, 0x1014, 0x103a, 0x1019, 0x102c, 0x431, 0x435, 0x43b, 0x430, 0x440, 0x443, 0x441, 0x43a, 0x430,
+0x44f, 0x411, 0x435, 0x43b, 0x430, 0x440, 0x443, 0x441, 0x44c, 0x1781, 0x17d2, 0x1798, 0x17c2, 0x179a, 0x1780, 0x1798, 0x17d2, 0x1796, 0x17bb, 0x1787,
+0x17b6, 0x63, 0x61, 0x74, 0x61, 0x6c, 0xe0, 0x45, 0x73, 0x70, 0x61, 0x6e, 0x79, 0x61, 0x41, 0x6e, 0x64, 0x6f, 0x72, 0x72,
+0x61, 0x46, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x49, 0x74, 0xe0, 0x6c, 0x69, 0x61, 0x7b80, 0x4f53, 0x4e2d, 0x6587, 0x4e2d, 0x56fd, 0x4e2d,
+0x56fd, 0x9999, 0x6e2f, 0x7279, 0x522b, 0x884c, 0x653f, 0x533a, 0x4e2d, 0x56fd, 0x6fb3, 0x95e8, 0x7279, 0x522b, 0x884c, 0x653f, 0x533a, 0x65b0, 0x52a0, 0x5761,
+0x7e41, 0x9ad4, 0x4e2d, 0x6587, 0x4e2d, 0x570b, 0x9999, 0x6e2f, 0x7279, 0x5225, 0x884c, 0x653f, 0x5340, 0x4e2d, 0x570b, 0x6fb3, 0x9580, 0x7279, 0x5225, 0x884c,
+0x653f, 0x5340, 0x53f0, 0x7063, 0x68, 0x72, 0x76, 0x61, 0x74, 0x73, 0x6b, 0x69, 0x48, 0x72, 0x76, 0x61, 0x74, 0x73, 0x6b, 0x61,
+0x42, 0x6f, 0x73, 0x6e, 0x61, 0x20, 0x69, 0x20, 0x48, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x69, 0x6e, 0x61, 0x10d,
+0x65, 0x161, 0x74, 0x69, 0x6e, 0x61, 0x10c, 0x65, 0x73, 0x6b, 0x6f, 0x64, 0x61, 0x6e, 0x73, 0x6b, 0x44, 0x61, 0x6e, 0x6d,
+0x61, 0x72, 0x6b, 0x47, 0x72, 0xf8, 0x6e, 0x6c, 0x61, 0x6e, 0x64, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64,
+0x73, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x41, 0x72, 0x75, 0x62, 0x61, 0x42, 0x65, 0x6c, 0x67, 0x69,
+0xeb, 0x43, 0x75, 0x72, 0x61, 0xe7, 0x61, 0x6f, 0x53, 0x75, 0x72, 0x69, 0x6e, 0x61, 0x6d, 0x65, 0x43, 0x61, 0x72, 0x69,
+0x62, 0x69, 0x73, 0x63, 0x68, 0x20, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x53, 0x69, 0x6e, 0x74, 0x2d,
+0x4d, 0x61, 0x61, 0x72, 0x74, 0x65, 0x6e, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x45, 0x6e, 0x67, 0x6c,
+0x69, 0x73, 0x68, 0x55, 0x6e, 0x69, 0x74, 0x65, 0x64, 0x20, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x67, 0x6c,
+0x69, 0x73, 0x68, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x41, 0x6e, 0x67,
+0x75, 0x69, 0x6c, 0x6c, 0x61, 0x41, 0x6e, 0x74, 0x69, 0x67, 0x75, 0x61, 0x20, 0x26, 0x20, 0x42, 0x61, 0x72, 0x62, 0x75,
+0x64, 0x61, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x6e, 0x20, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68,
+0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x41, 0x75, 0x73, 0x74, 0x72, 0x69, 0x61, 0x42, 0x61, 0x68, 0x61,
+0x6d, 0x61, 0x73, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x6f, 0x73, 0x42, 0x65, 0x6c, 0x67, 0x69, 0x75, 0x6d, 0x42, 0x65,
+0x6c, 0x69, 0x7a, 0x65, 0x42, 0x65, 0x72, 0x6d, 0x75, 0x64, 0x61, 0x42, 0x6f, 0x74, 0x73, 0x77, 0x61, 0x6e, 0x61, 0x42,
+0x72, 0x69, 0x74, 0x69, 0x73, 0x68, 0x20, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x4f, 0x63, 0x65, 0x61, 0x6e, 0x20,
+0x54, 0x65, 0x72, 0x72, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x42, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x43, 0x61, 0x6d, 0x65,
+0x72, 0x6f, 0x6f, 0x6e, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68,
+0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x43, 0x61, 0x79, 0x6d, 0x61, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73,
+0x43, 0x68, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x43, 0x6f, 0x63, 0x6f,
+0x73, 0x20, 0x28, 0x4b, 0x65, 0x65, 0x6c, 0x69, 0x6e, 0x67, 0x29, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x43,
+0x6f, 0x6f, 0x6b, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x43, 0x79, 0x70, 0x72, 0x75, 0x73, 0x44, 0x65, 0x6e,
+0x6d, 0x61, 0x72, 0x6b, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61, 0x45, 0x72, 0x69, 0x74, 0x72, 0x65, 0x61, 0x46,
+0x61, 0x6c, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x46, 0x69, 0x6a, 0x69, 0x46,
+0x69, 0x6e, 0x6c, 0x61, 0x6e, 0x64, 0x47, 0x75, 0x65, 0x72, 0x6e, 0x73, 0x65, 0x79, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x61,
+0x47, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x79, 0x47, 0x68, 0x61, 0x6e, 0x61, 0x47, 0x69, 0x62, 0x72, 0x61, 0x6c, 0x74, 0x61,
+0x72, 0x47, 0x72, 0x65, 0x6e, 0x61, 0x64, 0x61, 0x47, 0x75, 0x61, 0x6d, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x48, 0x6f,
+0x6e, 0x67, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x20, 0x53, 0x41, 0x52, 0x20, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x49, 0x6e, 0x64,
+0x69, 0x61, 0x49, 0x72, 0x65, 0x6c, 0x61, 0x6e, 0x64, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x4a, 0x61, 0x6d, 0x61, 0x69,
+0x63, 0x61, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x4b, 0x69, 0x72, 0x69, 0x62, 0x61, 0x74, 0x69, 0x4c, 0x65, 0x73, 0x6f, 0x74,
+0x68, 0x6f, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x69, 0x61, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x20, 0x53, 0x41, 0x52, 0x20, 0x43,
+0x68, 0x69, 0x6e, 0x61, 0x4d, 0x61, 0x64, 0x61, 0x67, 0x61, 0x73, 0x63, 0x61, 0x72, 0x4d, 0x61, 0x6c, 0x61, 0x77, 0x69,
+0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x4d, 0x61, 0x6c, 0x74, 0x61, 0x4d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c,
+0x6c, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x4d, 0x69,
+0x63, 0x72, 0x6f, 0x6e, 0x65, 0x73, 0x69, 0x61, 0x4d, 0x6f, 0x6e, 0x74, 0x73, 0x65, 0x72, 0x72, 0x61, 0x74, 0x4e, 0x61,
+0x6d, 0x69, 0x62, 0x69, 0x61, 0x4e, 0x61, 0x75, 0x72, 0x75, 0x4e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64,
+0x73, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c, 0x61, 0x6e, 0x64, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, 0x4e,
+0x69, 0x75, 0x65, 0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x4e, 0x6f, 0x72,
+0x74, 0x68, 0x65, 0x72, 0x6e, 0x20, 0x4d, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x61, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64,
+0x73, 0x50, 0x61, 0x6b, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x50, 0x61, 0x6c, 0x61, 0x75, 0x50, 0x61, 0x70, 0x75, 0x61, 0x20,
+0x4e, 0x65, 0x77, 0x20, 0x47, 0x75, 0x69, 0x6e, 0x65, 0x61, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65,
+0x73, 0x50, 0x69, 0x74, 0x63, 0x61, 0x69, 0x72, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x50, 0x75, 0x65,
+0x72, 0x74, 0x6f, 0x20, 0x52, 0x69, 0x63, 0x6f, 0x52, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x53, 0x74, 0x2e, 0x20, 0x4b, 0x69,
+0x74, 0x74, 0x73, 0x20, 0x26, 0x20, 0x4e, 0x65, 0x76, 0x69, 0x73, 0x53, 0x74, 0x2e, 0x20, 0x4c, 0x75, 0x63, 0x69, 0x61,
+0x53, 0x74, 0x2e, 0x20, 0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e, 0x74, 0x20, 0x26, 0x20, 0x47, 0x72, 0x65, 0x6e, 0x61, 0x64,
+0x69, 0x6e, 0x65, 0x73, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x65, 0x73, 0x53,
+0x69, 0x65, 0x72, 0x72, 0x61, 0x20, 0x4c, 0x65, 0x6f, 0x6e, 0x65, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65,
+0x53, 0x6c, 0x6f, 0x76, 0x65, 0x6e, 0x69, 0x61, 0x53, 0x6f, 0x6c, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61,
+0x6e, 0x64, 0x73, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x53, 0x74, 0x2e, 0x20, 0x48,
+0x65, 0x6c, 0x65, 0x6e, 0x61, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x53, 0x77, 0x61, 0x7a, 0x69, 0x6c, 0x61, 0x6e, 0x64, 0x53,
+0x77, 0x65, 0x64, 0x65, 0x6e, 0x53, 0x77, 0x69, 0x74, 0x7a, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x54, 0x61, 0x6e, 0x7a,
+0x61, 0x6e, 0x69, 0x61, 0x54, 0x6f, 0x6b, 0x65, 0x6c, 0x61, 0x75, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x54, 0x72, 0x69, 0x6e,
+0x69, 0x64, 0x61, 0x64, 0x20, 0x26, 0x20, 0x54, 0x6f, 0x62, 0x61, 0x67, 0x6f, 0x54, 0x75, 0x72, 0x6b, 0x73, 0x20, 0x26,
+0x20, 0x43, 0x61, 0x69, 0x63, 0x6f, 0x73, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x54, 0x75, 0x76, 0x61, 0x6c,
+0x75, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68, 0x20, 0x45, 0x6e, 0x67, 0x6c, 0x69,
+0x73, 0x68, 0x55, 0x6e, 0x69, 0x74, 0x65, 0x64, 0x20, 0x4b, 0x69, 0x6e, 0x67, 0x64, 0x6f, 0x6d, 0x55, 0x2e, 0x53, 0x2e,
+0x20, 0x4f, 0x75, 0x74, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x56, 0x61, 0x6e,
+0x75, 0x61, 0x74, 0x75, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68, 0x20, 0x56, 0x69, 0x72, 0x67, 0x69, 0x6e, 0x20, 0x49,
+0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x55, 0x2e, 0x53, 0x2e, 0x20, 0x56, 0x69, 0x72, 0x67, 0x69, 0x6e, 0x20, 0x49, 0x73,
+0x6c, 0x61, 0x6e, 0x64, 0x73, 0x5a, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x5a, 0x69, 0x6d, 0x62, 0x61, 0x62, 0x77, 0x65, 0x44,
+0x69, 0x65, 0x67, 0x6f, 0x20, 0x47, 0x61, 0x72, 0x63, 0x69, 0x61, 0x49, 0x73, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x4d,
+0x61, 0x6e, 0x4a, 0x65, 0x72, 0x73, 0x65, 0x79, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x53,
+0x69, 0x6e, 0x74, 0x20, 0x4d, 0x61, 0x61, 0x72, 0x74, 0x65, 0x6e, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x45, 0x75, 0x72, 0x6f,
+0x70, 0x65, 0x65, 0x73, 0x70, 0x65, 0x72, 0x61, 0x6e, 0x74, 0x6f, 0x65, 0x65, 0x73, 0x74, 0x69, 0x45, 0x65, 0x73, 0x74,
+0x69, 0x66, 0xf8, 0x72, 0x6f, 0x79, 0x73, 0x6b, 0x74, 0x46, 0xf8, 0x72, 0x6f, 0x79, 0x61, 0x72, 0x73, 0x75, 0x6f, 0x6d,
+0x69, 0x53, 0x75, 0x6f, 0x6d, 0x69, 0x66, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x69, 0x73, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x65,
+0x41, 0x6c, 0x67, 0xe9, 0x72, 0x69, 0x65, 0x42, 0x65, 0x6c, 0x67, 0x69, 0x71, 0x75, 0x65, 0x42, 0xe9, 0x6e, 0x69, 0x6e,
+0x42, 0x75, 0x72, 0x6b, 0x69, 0x6e, 0x61, 0x20, 0x46, 0x61, 0x73, 0x6f, 0x43, 0x61, 0x6d, 0x65, 0x72, 0x6f, 0x75, 0x6e,
+0x66, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x69, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x52, 0xe9, 0x70,
+0x75, 0x62, 0x6c, 0x69, 0x71, 0x75, 0x65, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x66, 0x72, 0x69, 0x63, 0x61, 0x69,
+0x6e, 0x65, 0x54, 0x63, 0x68, 0x61, 0x64, 0x43, 0x6f, 0x6d, 0x6f, 0x72, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x67, 0x6f, 0x2d,
+0x4b, 0x69, 0x6e, 0x73, 0x68, 0x61, 0x73, 0x61, 0x43, 0x6f, 0x6e, 0x67, 0x6f, 0x2d, 0x42, 0x72, 0x61, 0x7a, 0x7a, 0x61,
+0x76, 0x69, 0x6c, 0x6c, 0x65, 0x43, 0xf4, 0x74, 0x65, 0x20, 0x64, 0x2019, 0x49, 0x76, 0x6f, 0x69, 0x72, 0x65, 0x44, 0x6a,
+0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x47, 0x75, 0x69, 0x6e, 0xe9, 0x65, 0x20, 0xe9, 0x71, 0x75, 0x61, 0x74, 0x6f, 0x72,
+0x69, 0x61, 0x6c, 0x65, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x65, 0x20, 0x66, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x69, 0x73, 0x65,
+0x50, 0x6f, 0x6c, 0x79, 0x6e, 0xe9, 0x73, 0x69, 0x65, 0x20, 0x66, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x69, 0x73, 0x65, 0x47,
+0x61, 0x62, 0x6f, 0x6e, 0x47, 0x75, 0x61, 0x64, 0x65, 0x6c, 0x6f, 0x75, 0x70, 0x65, 0x47, 0x75, 0x69, 0x6e, 0xe9, 0x65,
+0x48, 0x61, 0xef, 0x74, 0x69, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x6f, 0x75, 0x72, 0x67, 0x4d, 0x61, 0x6c, 0x69, 0x4d,
+0x61, 0x72, 0x74, 0x69, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x65, 0x4d,
+0x61, 0x75, 0x72, 0x69, 0x63, 0x65, 0x4d, 0x61, 0x79, 0x6f, 0x74, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x61, 0x63, 0x6f, 0x4d,
+0x61, 0x72, 0x6f, 0x63, 0x4e, 0x6f, 0x75, 0x76, 0x65, 0x6c, 0x6c, 0x65, 0x2d, 0x43, 0x61, 0x6c, 0xe9, 0x64, 0x6f, 0x6e,
+0x69, 0x65, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x4c, 0x61, 0x20, 0x52, 0xe9, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x53, 0xe9, 0x6e,
+0xe9, 0x67, 0x61, 0x6c, 0x53, 0x61, 0x69, 0x6e, 0x74, 0x2d, 0x50, 0x69, 0x65, 0x72, 0x72, 0x65, 0x2d, 0x65, 0x74, 0x2d,
+0x4d, 0x69, 0x71, 0x75, 0x65, 0x6c, 0x6f, 0x6e, 0x66, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x69, 0x73, 0x20, 0x73, 0x75, 0x69,
+0x73, 0x73, 0x65, 0x53, 0x75, 0x69, 0x73, 0x73, 0x65, 0x53, 0x79, 0x72, 0x69, 0x65, 0x54, 0x6f, 0x67, 0x6f, 0x54, 0x75,
+0x6e, 0x69, 0x73, 0x69, 0x65, 0x57, 0x61, 0x6c, 0x6c, 0x69, 0x73, 0x2d, 0x65, 0x74, 0x2d, 0x46, 0x75, 0x74, 0x75, 0x6e,
+0x61, 0x53, 0x61, 0x69, 0x6e, 0x74, 0x2d, 0x42, 0x61, 0x72, 0x74, 0x68, 0xe9, 0x6c, 0x65, 0x6d, 0x79, 0x53, 0x61, 0x69,
+0x6e, 0x74, 0x2d, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x46, 0x72, 0x79, 0x73, 0x6b, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c,
+0xe2, 0x6e, 0x47, 0xe0, 0x69, 0x64, 0x68, 0x6c, 0x69, 0x67, 0x41, 0x6e, 0x20, 0x52, 0xec, 0x6f, 0x67, 0x68, 0x61, 0x63,
+0x68, 0x64, 0x20, 0x41, 0x6f, 0x6e, 0x61, 0x69, 0x63, 0x68, 0x74, 0x65, 0x67, 0x61, 0x6c, 0x65, 0x67, 0x6f, 0x45, 0x73,
+0x70, 0x61, 0xf1, 0x61, 0x10e5, 0x10d0, 0x10e0, 0x10d7, 0x10e3, 0x10da, 0x10d8, 0x10e1, 0x10d0, 0x10e5, 0x10d0, 0x10e0, 0x10d7, 0x10d5, 0x10d4, 0x10da,
+0x10dd, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x6c, 0x61, 0x6e, 0x64, 0xd6,
+0x73, 0x74, 0x65, 0x72, 0x72, 0x65, 0x69, 0x63, 0x68, 0x69, 0x73, 0x63, 0x68, 0x65, 0x73, 0x20, 0x44, 0x65, 0x75, 0x74,
+0x73, 0x63, 0x68, 0xd6, 0x73, 0x74, 0x65, 0x72, 0x72, 0x65, 0x69, 0x63, 0x68, 0x42, 0x65, 0x6c, 0x67, 0x69, 0x65, 0x6e,
+0x49, 0x74, 0x61, 0x6c, 0x69, 0x65, 0x6e, 0x4c, 0x69, 0x65, 0x63, 0x68, 0x74, 0x65, 0x6e, 0x73, 0x74, 0x65, 0x69, 0x6e,
+0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x75, 0x72, 0x67, 0x53, 0x63, 0x68, 0x77, 0x65, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x48,
+0x6f, 0x63, 0x68, 0x64, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x53, 0x63, 0x68, 0x77, 0x65, 0x69, 0x7a, 0x395, 0x3bb, 0x3bb,
+0x3b7, 0x3bd, 0x3b9, 0x3ba, 0x3ac, 0x395, 0x3bb, 0x3bb, 0x3ac, 0x3b4, 0x3b1, 0x39a, 0x3cd, 0x3c0, 0x3c1, 0x3bf, 0x3c2, 0x6b, 0x61, 0x6c,
+0x61, 0x61, 0x6c, 0x6c, 0x69, 0x73, 0x75, 0x74, 0x4b, 0x61, 0x6c, 0x61, 0x61, 0x6c, 0x6c, 0x69, 0x74, 0x20, 0x4e, 0x75,
+0x6e, 0x61, 0x61, 0x74, 0xa97, 0xac1, 0xa9c, 0xab0, 0xabe, 0xaa4, 0xac0, 0xaad, 0xabe, 0xab0, 0xaa4, 0x48, 0x61, 0x75, 0x73, 0x61,
+0x4e, 0x61, 0x6a, 0x65, 0x72, 0x69, 0x79, 0x61, 0x47, 0x61, 0x6e, 0x61, 0x4e, 0x69, 0x6a, 0x61, 0x72, 0x5e2, 0x5d1, 0x5e8,
+0x5d9, 0x5ea, 0x5d9, 0x5e9, 0x5e8, 0x5d0, 0x5dc, 0x939, 0x93f, 0x928, 0x94d, 0x926, 0x940, 0x92d, 0x93e, 0x930, 0x924, 0x6d, 0x61, 0x67,
+0x79, 0x61, 0x72, 0x4d, 0x61, 0x67, 0x79, 0x61, 0x72, 0x6f, 0x72, 0x73, 0x7a, 0xe1, 0x67, 0xed, 0x73, 0x6c, 0x65, 0x6e,
+0x73, 0x6b, 0x61, 0xcd, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x49, 0x6e, 0x64, 0x6f, 0x6e, 0x65, 0x73, 0x69, 0x61, 0x69, 0x6e,
+0x74, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x67, 0x75, 0x61, 0x4d, 0x75, 0x6e, 0x64, 0x6f, 0x47, 0x61, 0x65, 0x69, 0x6c, 0x67,
0x65, 0xc9, 0x69, 0x72, 0x65, 0x69, 0x74, 0x61, 0x6c, 0x69, 0x61, 0x6e, 0x6f, 0x49, 0x74, 0x61, 0x6c, 0x69, 0x61, 0x53,
0x61, 0x6e, 0x20, 0x4d, 0x61, 0x72, 0x69, 0x6e, 0x6f, 0x53, 0x76, 0x69, 0x7a, 0x7a, 0x65, 0x72, 0x61, 0x43, 0x69, 0x74,
0x74, 0xe0, 0x20, 0x64, 0x65, 0x6c, 0x20, 0x56, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x65e5, 0x672c, 0x8a9e, 0x65e5, 0x672c,
-0xc95, 0xca8, 0xccd, 0xca8, 0xca1, 0xcad, 0xcbe, 0xcb0, 0xca4, 0x6a9, 0x672, 0x634, 0x64f, 0x631, 0x6c1, 0x650, 0x646, 0x65b, 0x62f, 0x648,
-0x633, 0x62a, 0x627, 0x646, 0x49b, 0x430, 0x437, 0x430, 0x49b, 0x20, 0x442, 0x456, 0x43b, 0x456, 0x49a, 0x430, 0x437, 0x430, 0x49b, 0x441,
-0x442, 0x430, 0x43d, 0x4b, 0x69, 0x6e, 0x79, 0x61, 0x72, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x43a, 0x44b, 0x440, 0x433, 0x44b, 0x437,
-0x447, 0x430, 0x41a, 0x44b, 0x440, 0x433, 0x44b, 0x437, 0x441, 0x442, 0x430, 0x43d, 0xd55c, 0xad6d, 0xc5b4, 0xb300, 0xd55c, 0xbbfc, 0xad6d, 0xc870,
-0xc120, 0xbbfc, 0xc8fc, 0xc8fc, 0xc758, 0xc778, 0xbbfc, 0xacf5, 0xd654, 0xad6d, 0x49, 0x6b, 0x69, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x55, 0x62,
-0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0xea5, 0xeb2, 0xea7, 0x6c, 0x61, 0x74, 0x76, 0x69, 0x65, 0x161, 0x75, 0x4c, 0x61, 0x74,
-0x76, 0x69, 0x6a, 0x61, 0x6c, 0x69, 0x6e, 0x67, 0xe1, 0x6c, 0x61, 0x52, 0x65, 0x70, 0x75, 0x62, 0x6c, 0xed, 0x6b, 0x69,
-0x20, 0x79, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0xf3, 0x20, 0x44, 0x65, 0x6d, 0x6f, 0x6b, 0x72, 0x61, 0x74, 0xed, 0x6b,
-0x69, 0x41, 0x6e, 0x67, 0xf3, 0x6c, 0x61, 0x52, 0x65, 0x70, 0x69, 0x62, 0x69, 0x6b, 0x69, 0x20, 0x79, 0x61, 0x20, 0x41,
-0x66, 0x72, 0xed, 0x6b, 0x61, 0x20, 0x79, 0x61, 0x20, 0x4b, 0xe1, 0x74, 0x69, 0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x69,
-0x65, 0x74, 0x75, 0x76, 0x69, 0x173, 0x4c, 0x69, 0x65, 0x74, 0x75, 0x76, 0x61, 0x43c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d,
-0x441, 0x43a, 0x438, 0x41c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d, 0x438, 0x458, 0x430, 0x4d, 0x61, 0x6c, 0x61, 0x67, 0x61, 0x73,
-0x79, 0x4d, 0x61, 0x64, 0x61, 0x67, 0x61, 0x73, 0x69, 0x6b, 0x61, 0x72, 0x61, 0x42, 0x61, 0x68, 0x61, 0x73, 0x61, 0x20,
-0x4d, 0x65, 0x6c, 0x61, 0x79, 0x75, 0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x75, 0x72,
-0x61, 0xd2e, 0xd32, 0xd2f, 0xd3e, 0xd33, 0xd02, 0xd07, 0xd28, 0xd4d, 0xd24, 0xd4d, 0xd2f, 0x4d, 0x61, 0x6c, 0x74, 0x69, 0x92e, 0x930,
-0x93e, 0x920, 0x940, 0x43c, 0x43e, 0x43d, 0x433, 0x43e, 0x43b, 0x41c, 0x43e, 0x43d, 0x433, 0x43e, 0x43b, 0x928, 0x947, 0x92a, 0x93e, 0x932,
-0x940, 0x928, 0x947, 0x92a, 0x93e, 0x932, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x20, 0x62, 0x6f, 0x6b, 0x6d, 0xe5, 0x6c, 0x4e, 0x6f,
-0x72, 0x67, 0x65, 0x53, 0x76, 0x61, 0x6c, 0x62, 0x61, 0x72, 0x64, 0x20, 0x6f, 0x67, 0x20, 0x4a, 0x61, 0x6e, 0x20, 0x4d,
-0x61, 0x79, 0x65, 0x6e, 0xb13, 0xb21, 0xb3c, 0xb3f, 0xb06, 0xb2d, 0xb3e, 0xb30, 0xb24, 0x67e, 0x69a, 0x62a, 0x648, 0x627, 0x641, 0x63a,
-0x627, 0x646, 0x633, 0x62a, 0x627, 0x646, 0x641, 0x627, 0x631, 0x633, 0x6cc, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x62f, 0x631, 0x6cc, 0x70,
-0x6f, 0x6c, 0x73, 0x6b, 0x69, 0x50, 0x6f, 0x6c, 0x73, 0x6b, 0x61, 0x70, 0x6f, 0x72, 0x74, 0x75, 0x67, 0x75, 0xea, 0x73,
-0x42, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x41, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x43, 0x61, 0x62, 0x6f, 0x20, 0x56, 0x65, 0x72,
-0x64, 0x65, 0x54, 0x69, 0x6d, 0x6f, 0x72, 0x2d, 0x4c, 0x65, 0x73, 0x74, 0x65, 0x47, 0x75, 0x69, 0x6e, 0xe9, 0x20, 0x45,
-0x71, 0x75, 0x61, 0x74, 0x6f, 0x72, 0x69, 0x61, 0x6c, 0x47, 0x75, 0x69, 0x6e, 0xe9, 0x2d, 0x42, 0x69, 0x73, 0x73, 0x61,
-0x75, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x75, 0x72, 0x67, 0x6f, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x2c, 0x20, 0x52, 0x41,
-0x45, 0x20, 0x64, 0x61, 0x20, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x4d, 0x6f, 0xe7, 0x61, 0x6d, 0x62, 0x69, 0x71, 0x75, 0x65,
-0x70, 0x6f, 0x72, 0x74, 0x75, 0x67, 0x75, 0xea, 0x73, 0x20, 0x65, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x75, 0x50, 0x6f, 0x72,
-0x74, 0x75, 0x67, 0x61, 0x6c, 0x53, 0xe3, 0x6f, 0x20, 0x54, 0x6f, 0x6d, 0xe9, 0x20, 0x65, 0x20, 0x50, 0x72, 0xed, 0x6e,
-0x63, 0x69, 0x70, 0x65, 0x53, 0x75, 0xed, 0xe7, 0x61, 0xa2a, 0xa70, 0xa1c, 0xa3e, 0xa2c, 0xa40, 0xa2d, 0xa3e, 0xa30, 0xa24, 0x67e,
-0x646, 0x62c, 0x627, 0x628, 0x6cc, 0x67e, 0x627, 0x6a9, 0x633, 0x62a, 0x627, 0x646, 0x52, 0x75, 0x6e, 0x61, 0x73, 0x69, 0x6d, 0x69,
-0x50, 0x65, 0x72, 0xfa, 0x42, 0x6f, 0x6c, 0x69, 0x76, 0x69, 0x61, 0x45, 0x63, 0x75, 0x61, 0x64, 0x6f, 0x72, 0x72, 0x75,
-0x6d, 0x61, 0x6e, 0x74, 0x73, 0x63, 0x68, 0x53, 0x76, 0x69, 0x7a, 0x72, 0x61, 0x72, 0x6f, 0x6d, 0xe2, 0x6e, 0x103, 0x52,
-0x6f, 0x6d, 0xe2, 0x6e, 0x69, 0x61, 0x6d, 0x6f, 0x6c, 0x64, 0x6f, 0x76, 0x65, 0x6e, 0x65, 0x61, 0x73, 0x63, 0x103, 0x52,
-0x65, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x20, 0x4d, 0x6f, 0x6c, 0x64, 0x6f, 0x76, 0x61, 0x440, 0x443, 0x441, 0x441,
-0x43a, 0x438, 0x439, 0x420, 0x43e, 0x441, 0x441, 0x438, 0x44f, 0x41a, 0x430, 0x437, 0x430, 0x445, 0x441, 0x442, 0x430, 0x43d, 0x41a, 0x438,
-0x440, 0x433, 0x438, 0x437, 0x438, 0x44f, 0x41c, 0x43e, 0x43b, 0x434, 0x43e, 0x432, 0x430, 0x423, 0x43a, 0x440, 0x430, 0x438, 0x43d, 0x430,
-0x53, 0xe4, 0x6e, 0x67, 0xf6, 0x4b, 0xf6, 0x64, 0xf6, 0x72, 0xf6, 0x73, 0xea, 0x73, 0x65, 0x20, 0x74, 0xee, 0x20, 0x42,
-0xea, 0x61, 0x66, 0x72, 0xee, 0x6b, 0x61, 0x441, 0x440, 0x43f, 0x441, 0x43a, 0x438, 0x421, 0x440, 0x431, 0x438, 0x458, 0x430, 0x411,
-0x43e, 0x441, 0x43d, 0x430, 0x20, 0x438, 0x20, 0x425, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x438, 0x43d, 0x430, 0x426, 0x440,
-0x43d, 0x430, 0x20, 0x413, 0x43e, 0x440, 0x430, 0x41a, 0x43e, 0x441, 0x43e, 0x432, 0x43e, 0x73, 0x72, 0x70, 0x73, 0x6b, 0x69, 0x43,
-0x72, 0x6e, 0x61, 0x20, 0x47, 0x6f, 0x72, 0x61, 0x53, 0x72, 0x62, 0x69, 0x6a, 0x61, 0x4b, 0x6f, 0x73, 0x6f, 0x76, 0x6f,
-0x438, 0x440, 0x43e, 0x43d, 0x413, 0x443, 0x44b, 0x440, 0x434, 0x437, 0x44b, 0x441, 0x442, 0x43e, 0x43d, 0x423, 0x4d5, 0x440, 0x4d5, 0x441,
-0x435, 0x63, 0x68, 0x69, 0x53, 0x68, 0x6f, 0x6e, 0x61, 0xdc3, 0xdd2, 0xd82, 0xdc4, 0xdbd, 0xdc1, 0xdca, 0x200d, 0xdbb, 0xdd3, 0x20,
-0xdbd, 0xd82, 0xd9a, 0xdcf, 0xdc0, 0x73, 0x6c, 0x6f, 0x76, 0x65, 0x6e, 0x10d, 0x69, 0x6e, 0x61, 0x53, 0x6c, 0x6f, 0x76, 0x65,
-0x6e, 0x73, 0x6b, 0x6f, 0x73, 0x6c, 0x6f, 0x76, 0x65, 0x6e, 0x161, 0x10d, 0x69, 0x6e, 0x61, 0x53, 0x6c, 0x6f, 0x76, 0x65,
-0x6e, 0x69, 0x6a, 0x61, 0x53, 0x6f, 0x6f, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x53, 0x6f, 0x6f, 0x6d, 0x61, 0x61, 0x6c, 0x69,
-0x79, 0x61, 0x4a, 0x61, 0x62, 0x75, 0x75, 0x74, 0x69, 0x49, 0x74, 0x6f, 0x6f, 0x62, 0x69, 0x79, 0x61, 0x4b, 0x69, 0x69,
-0x6e, 0x69, 0x79, 0x61, 0x65, 0x73, 0x70, 0x61, 0xf1, 0x6f, 0x6c, 0x20, 0x64, 0x65, 0x20, 0x45, 0x73, 0x70, 0x61, 0xf1,
-0x61, 0x65, 0x73, 0x70, 0x61, 0xf1, 0x6f, 0x6c, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x42, 0x65, 0x6c,
-0x69, 0x63, 0x65, 0x43, 0x68, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x69, 0x61, 0x43, 0x6f, 0x73, 0x74,
-0x61, 0x20, 0x52, 0x69, 0x63, 0x61, 0x43, 0x75, 0x62, 0x61, 0x52, 0x65, 0x70, 0xfa, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x20,
-0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61, 0x6e, 0x61, 0x45, 0x6c, 0x20, 0x53, 0x61, 0x6c, 0x76, 0x61, 0x64, 0x6f,
-0x72, 0x47, 0x75, 0x69, 0x6e, 0x65, 0x61, 0x20, 0x45, 0x63, 0x75, 0x61, 0x74, 0x6f, 0x72, 0x69, 0x61, 0x6c, 0x47, 0x75,
-0x61, 0x74, 0x65, 0x6d, 0x61, 0x6c, 0x61, 0x48, 0x6f, 0x6e, 0x64, 0x75, 0x72, 0x61, 0x73, 0x65, 0x73, 0x70, 0x61, 0xf1,
-0x6f, 0x6c, 0x20, 0x64, 0x65, 0x20, 0x4d, 0xe9, 0x78, 0x69, 0x63, 0x6f, 0x4d, 0xe9, 0x78, 0x69, 0x63, 0x6f, 0x4e, 0x69,
-0x63, 0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x50, 0x61, 0x6e, 0x61, 0x6d, 0xe1, 0x50, 0x61, 0x72, 0x61, 0x67, 0x75, 0x61,
-0x79, 0x46, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x61, 0x73, 0x45, 0x45, 0x2e, 0x20, 0x55, 0x55, 0x2e, 0x55, 0x72, 0x75,
-0x67, 0x75, 0x61, 0x79, 0x56, 0x65, 0x6e, 0x65, 0x7a, 0x75, 0x65, 0x6c, 0x61, 0x43, 0x61, 0x6e, 0x61, 0x72, 0x69, 0x61,
-0x73, 0x65, 0x73, 0x70, 0x61, 0xf1, 0x6f, 0x6c, 0x20, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x6f, 0x61, 0x6d, 0x65, 0x72, 0x69,
-0x63, 0x61, 0x6e, 0x6f, 0x4c, 0x61, 0x74, 0x69, 0x6e, 0x6f, 0x61, 0x6d, 0xe9, 0x72, 0x69, 0x63, 0x61, 0x43, 0x65, 0x75,
-0x74, 0x61, 0x20, 0x79, 0x20, 0x4d, 0x65, 0x6c, 0x69, 0x6c, 0x6c, 0x61, 0x4b, 0x69, 0x73, 0x77, 0x61, 0x68, 0x69, 0x6c,
-0x69, 0x4b, 0x69, 0x6e, 0x67, 0x77, 0x61, 0x6e, 0x61, 0x4a, 0x61, 0x6d, 0x68, 0x75, 0x72, 0x69, 0x20, 0x79, 0x61, 0x20,
-0x4b, 0x69, 0x64, 0x65, 0x6d, 0x6f, 0x6b, 0x72, 0x61, 0x73, 0x69, 0x61, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67,
-0x6f, 0x73, 0x76, 0x65, 0x6e, 0x73, 0x6b, 0x61, 0x53, 0x76, 0x65, 0x72, 0x69, 0x67, 0x65, 0xc5, 0x6c, 0x61, 0x6e, 0x64,
-0xba4, 0xbae, 0xbbf, 0xbb4, 0xbcd, 0xb87, 0xba8, 0xbcd, 0xba4, 0xbbf, 0xbaf, 0xbbe, 0xbae, 0xbb2, 0xbc7, 0xb9a, 0xbbf, 0xbaf, 0xbbe, 0xb9a,
-0xbbf, 0xb99, 0xbcd, 0xb95, 0xbaa, 0xbcd, 0xbaa, 0xbc2, 0xbb0, 0xbcd, 0xb87, 0xbb2, 0xb99, 0xbcd, 0xb95, 0xbc8, 0xc24, 0xc46, 0xc32, 0xc41,
-0xc17, 0xc41, 0xc2d, 0xc3e, 0xc30, 0xc24, 0x20, 0xc26, 0xc47, 0xc36, 0xc02, 0xe44, 0xe17, 0xe22, 0xf56, 0xf7c, 0xf51, 0xf0b, 0xf66, 0xf90,
-0xf51, 0xf0b, 0xf62, 0xf92, 0xfb1, 0xf0b, 0xf53, 0xf42, 0xf62, 0xf92, 0xfb1, 0xf0b, 0xf42, 0xf62, 0xf0b, 0x1275, 0x130d, 0x122d, 0x129b, 0x12a4,
-0x122d, 0x1275, 0x122b, 0x6c, 0x65, 0x61, 0x20, 0x66, 0x61, 0x6b, 0x61, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x54, 0xfc, 0x72, 0x6b,
-0xe7, 0x65, 0x54, 0xfc, 0x72, 0x6b, 0x69, 0x79, 0x65, 0x4b, 0x131, 0x62, 0x72, 0x131, 0x73, 0x74, 0xfc, 0x72, 0x6b, 0x6d,
-0x65, 0x6e, 0xe7, 0x65, 0x54, 0xfc, 0x72, 0x6b, 0x6d, 0x65, 0x6e, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x626, 0x6c7, 0x64a, 0x63a,
-0x6c7, 0x631, 0x686, 0x6d5, 0x62c, 0x6c7, 0x6ad, 0x6af, 0x648, 0x443, 0x43a, 0x440, 0x430, 0x457, 0x43d, 0x441, 0x44c, 0x43a, 0x430, 0x423,
-0x43a, 0x440, 0x430, 0x457, 0x43d, 0x430, 0x627, 0x631, 0x62f, 0x648, 0x628, 0x6be, 0x627, 0x631, 0x62a, 0x6f, 0x2018, 0x7a, 0x62, 0x65,
-0x6b, 0x4f, 0x2bb, 0x7a, 0x62, 0x65, 0x6b, 0x69, 0x73, 0x74, 0x6f, 0x6e, 0x627, 0x648, 0x632, 0x628, 0x6cc, 0x6a9, 0x45e, 0x437,
-0x431, 0x435, 0x43a, 0x447, 0x430, 0x40e, 0x437, 0x431, 0x435, 0x43a, 0x438, 0x441, 0x442, 0x43e, 0x43d, 0x54, 0x69, 0x1ebf, 0x6e, 0x67,
-0x20, 0x56, 0x69, 0x1ec7, 0x74, 0x56, 0x69, 0x1ec7, 0x74, 0x20, 0x4e, 0x61, 0x6d, 0x43, 0x79, 0x6d, 0x72, 0x61, 0x65, 0x67,
-0x59, 0x20, 0x44, 0x65, 0x79, 0x72, 0x6e, 0x61, 0x73, 0x20, 0x55, 0x6e, 0x65, 0x64, 0x69, 0x67, 0xc8, 0x64, 0xe8, 0x20,
-0x59, 0x6f, 0x72, 0xf9, 0x62, 0xe1, 0x4f, 0x72, 0xed, 0x6c, 0x1eb9, 0x301, 0xe8, 0x64, 0x65, 0x20, 0x4e, 0xe0, 0xec, 0x6a,
-0xed, 0x72, 0xed, 0xe0, 0x4f, 0x72, 0xed, 0x6c, 0x25b, 0x301, 0xe8, 0x64, 0x65, 0x20, 0x42, 0x25b, 0x300, 0x6e, 0x25b, 0x300,
-0x69, 0x73, 0x69, 0x5a, 0x75, 0x6c, 0x75, 0x69, 0x2d, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63,
-0x61, 0x6e, 0x79, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x4e, 0x6f, 0x72, 0x65, 0x67, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b,
-0x69, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x438, 0x47, 0x61, 0x65, 0x6c, 0x67, 0x45, 0x6c, 0x6c, 0x61, 0x6e, 0x20,
-0x56, 0x61, 0x6e, 0x6e, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x77, 0x65, 0x6b, 0x52, 0x79, 0x77, 0x76, 0x61, 0x6e,
-0x65, 0x74, 0x68, 0x20, 0x55, 0x6e, 0x79, 0x73, 0x41, 0x6b, 0x61, 0x6e, 0x47, 0x61, 0x61, 0x6e, 0x61, 0x915, 0x94b, 0x902,
-0x915, 0x923, 0x940, 0x49, 0x67, 0x62, 0x6f, 0x4b, 0x69, 0x6b, 0x61, 0x6d, 0x62, 0x61, 0x66, 0x75, 0x72, 0x6c, 0x61, 0x6e,
-0x49, 0x74, 0x61, 0x6c, 0x69, 0x65, 0x45, 0x28b, 0x65, 0x67, 0x62, 0x65, 0x47, 0x68, 0x61, 0x6e, 0x61, 0x20, 0x6e, 0x75,
-0x74, 0x6f, 0x6d, 0x65, 0x54, 0x6f, 0x67, 0x6f, 0x20, 0x6e, 0x75, 0x74, 0x6f, 0x6d, 0x65, 0x2bb, 0x14c, 0x6c, 0x65, 0x6c,
-0x6f, 0x20, 0x48, 0x61, 0x77, 0x61, 0x69, 0x2bb, 0x69, 0x2bb, 0x41, 0x6d, 0x65, 0x6c, 0x69, 0x6b, 0x61, 0x20, 0x48, 0x75,
-0x69, 0x20, 0x50, 0x16b, 0x20, 0x2bb, 0x49, 0x61, 0x46, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x6f, 0x50, 0x69, 0x6c, 0x69,
-0x70, 0x69, 0x6e, 0x61, 0x73, 0x53, 0x63, 0x68, 0x77, 0x69, 0x69, 0x7a, 0x65, 0x72, 0x74, 0xfc, 0xfc, 0x74, 0x73, 0x63,
-0x68, 0x53, 0x63, 0x68, 0x77, 0x69, 0x69, 0x7a, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x72, 0x69, 0x69, 0x63, 0x68, 0x4c, 0x69,
-0xe4, 0x63, 0x68, 0x74, 0x65, 0x73, 0x63, 0x68, 0x74, 0xe4, 0x69, 0xa188, 0xa320, 0xa259, 0xa34f, 0xa1e9, 0x4e, 0x65, 0x64, 0x64,
-0x65, 0x72, 0x73, 0x61, 0x73, 0x73, 0x2019, 0x73, 0x63, 0x68, 0x44, 0xfc, 0xfc, 0x74, 0x73, 0x63, 0x68, 0x6c, 0x61, 0x6e,
-0x64, 0x4e, 0x65, 0x64, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x6e, 0x64, 0x61, 0x76, 0x76, 0x69, 0x73, 0xe1,
-0x6d, 0x65, 0x67, 0x69, 0x65, 0x6c, 0x6c, 0x61, 0x4e, 0x6f, 0x72, 0x67, 0x61, 0x53, 0x75, 0x6f, 0x70, 0x6d, 0x61, 0x52,
-0x75, 0x6f, 0x167, 0x167, 0x61, 0x45, 0x6b, 0x65, 0x67, 0x75, 0x73, 0x69, 0x69, 0x4b, 0x69, 0x74, 0x61, 0x69, 0x74, 0x61,
-0x50, 0x75, 0x6c, 0x61, 0x61, 0x72, 0x53, 0x65, 0x6e, 0x65, 0x67, 0x61, 0x61, 0x6c, 0x4b, 0x61, 0x6d, 0x65, 0x72, 0x75,
-0x75, 0x6e, 0x47, 0x69, 0x6e, 0x65, 0x4d, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x47, 0x69, 0x6b, 0x75, 0x79, 0x75,
-0x4b, 0x69, 0x73, 0x61, 0x6d, 0x70, 0x75, 0x72, 0x73, 0x65, 0x6e, 0x61, 0x69, 0x73, 0x69, 0x4e, 0x64, 0x65, 0x62, 0x65,
-0x6c, 0x65, 0x4b, 0x69, 0x68, 0x6f, 0x72, 0x6f, 0x6d, 0x62, 0x6f, 0x2d5c, 0x2d30, 0x2d5b, 0x2d4d, 0x2d43, 0x2d49, 0x2d5c, 0x2d4d, 0x2d4e,
-0x2d56, 0x2d54, 0x2d49, 0x2d31, 0x54, 0x61, 0x73, 0x68, 0x65, 0x6c, 0x1e25, 0x69, 0x79, 0x74, 0x6c, 0x6d, 0x263, 0x72, 0x69, 0x62,
-0x54, 0x61, 0x71, 0x62, 0x61, 0x79, 0x6c, 0x69, 0x74, 0x4c, 0x65, 0x7a, 0x7a, 0x61, 0x79, 0x65, 0x72, 0x52, 0x75, 0x6e,
-0x79, 0x61, 0x6e, 0x6b, 0x6f, 0x72, 0x65, 0x48, 0x69, 0x62, 0x65, 0x6e, 0x61, 0x48, 0x75, 0x74, 0x61, 0x6e, 0x7a, 0x61,
-0x6e, 0x69, 0x61, 0x4b, 0x79, 0x69, 0x76, 0x75, 0x6e, 0x6a, 0x6f, 0x62, 0x61, 0x6d, 0x61, 0x6e, 0x61, 0x6b, 0x61, 0x6e,
-0x4b, 0x129, 0x65, 0x6d, 0x62, 0x75, 0x13e3, 0x13b3, 0x13a9, 0x13cc, 0x13ca, 0x20, 0x13a2, 0x13f3, 0x13be, 0x13b5, 0x13cd, 0x13d4, 0x13c5, 0x20,
-0x13cd, 0x13a6, 0x13da, 0x13a9, 0x6b, 0x72, 0x65, 0x6f, 0x6c, 0x20, 0x6d, 0x6f, 0x72, 0x69, 0x73, 0x69, 0x65, 0x6e, 0x4d, 0x6f,
-0x72, 0x69, 0x73, 0x43, 0x68, 0x69, 0x6d, 0x61, 0x6b, 0x6f, 0x6e, 0x64, 0x65, 0x4b, 0x268, 0x6c, 0x61, 0x61, 0x6e, 0x67,
-0x69, 0x54, 0x61, 0x61, 0x6e, 0x73, 0x61, 0x6e, 0xed, 0x61, 0x4c, 0x75, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x59, 0x75, 0x67,
-0x61, 0x6e, 0x64, 0x61, 0x49, 0x63, 0x68, 0x69, 0x62, 0x65, 0x6d, 0x62, 0x61, 0x6b, 0x61, 0x62, 0x75, 0x76, 0x65, 0x72,
-0x64, 0x69, 0x61, 0x6e, 0x75, 0x4b, 0x61, 0x62, 0x75, 0x20, 0x56, 0x65, 0x72, 0x64, 0x69, 0x4b, 0x129, 0x6d, 0x129, 0x72,
-0x169, 0x4b, 0x61, 0x6c, 0x65, 0x6e, 0x6a, 0x69, 0x6e, 0x45, 0x6d, 0x65, 0x74, 0x61, 0x62, 0x20, 0x4b, 0x65, 0x6e, 0x79,
-0x61, 0x4b, 0x68, 0x6f, 0x65, 0x6b, 0x68, 0x6f, 0x65, 0x67, 0x6f, 0x77, 0x61, 0x62, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69,
-0x61, 0x62, 0x4b, 0x69, 0x6d, 0x61, 0x63, 0x68, 0x61, 0x6d, 0x65, 0x4b, 0xf6, 0x6c, 0x73, 0x63, 0x68, 0x44, 0x6f, 0xfc,
-0x74, 0x73, 0x63, 0x68, 0x6c, 0x61, 0x6e, 0x64, 0x4d, 0x61, 0x61, 0x54, 0x61, 0x6e, 0x73, 0x61, 0x6e, 0x69, 0x61, 0x4f,
-0x6c, 0x75, 0x73, 0x6f, 0x67, 0x61, 0x4c, 0x75, 0x6c, 0x75, 0x68, 0x69, 0x61, 0x4b, 0x69, 0x70, 0x61, 0x72, 0x65, 0x54,
-0x61, 0x64, 0x68, 0x61, 0x6e, 0x69, 0x61, 0x4b, 0x69, 0x74, 0x65, 0x73, 0x6f, 0x4b, 0x65, 0x6e, 0x69, 0x61, 0x4b, 0x6f,
-0x79, 0x72, 0x61, 0x20, 0x63, 0x69, 0x69, 0x6e, 0x69, 0x4d, 0x61, 0x61, 0x6c, 0x69, 0x4b, 0x69, 0x72, 0x75, 0x77, 0x61,
-0x44, 0x68, 0x6f, 0x6c, 0x75, 0x6f, 0x52, 0x75, 0x6b, 0x69, 0x67, 0x61, 0x54, 0x61, 0x6d, 0x61, 0x7a, 0x69, 0x263, 0x74,
-0x20, 0x6e, 0x20, 0x6c, 0x61, 0x1e6d, 0x6c, 0x61, 0x1e63, 0x4d, 0x65, 0x1e5b, 0x1e5b, 0x75, 0x6b, 0x4b, 0x6f, 0x79, 0x72, 0x61,
-0x62, 0x6f, 0x72, 0x6f, 0x20, 0x73, 0x65, 0x6e, 0x6e, 0x69, 0x4b, 0x69, 0x73, 0x68, 0x61, 0x6d, 0x62, 0x61, 0x61, 0x92c,
-0x921, 0x93c, 0x94b, 0x43d, 0x43e, 0x445, 0x447, 0x438, 0x439, 0x43d, 0x420, 0x43e, 0x441, 0x441, 0x438, 0x446, 0x435, 0x440, 0x43a, 0x43e,
-0x432, 0x43d, 0x43e, 0x441, 0x43b, 0x43e, 0x432, 0x435, 0x301, 0x43d, 0x441, 0x43a, 0x457, 0x439, 0x440, 0x461, 0x441, 0x441, 0x456, 0x301,
-0x430, 0x54, 0x73, 0x68, 0x69, 0x6c, 0x75, 0x62, 0x61, 0x44, 0x69, 0x74, 0x75, 0x6e, 0x67, 0x61, 0x20, 0x77, 0x61, 0x20,
-0x4b, 0x6f, 0x6e, 0x67, 0x75, 0x4c, 0xeb, 0x74, 0x7a, 0x65, 0x62, 0x75, 0x65, 0x72, 0x67, 0x65, 0x73, 0x63, 0x68, 0x4c,
-0xeb, 0x74, 0x7a, 0x65, 0x62, 0x75, 0x65, 0x72, 0x67, 0x41, 0x67, 0x68, 0x65, 0x6d, 0x4b, 0xe0, 0x6d, 0xe0, 0x6c, 0xfb,
-0x14b, 0x181, 0xe0, 0x73, 0xe0, 0x61, 0x4b, 0xe0, 0x6d, 0x25b, 0x300, 0x72, 0xfb, 0x6e, 0x5a, 0x61, 0x72, 0x6d, 0x61, 0x63,
-0x69, 0x69, 0x6e, 0x65, 0x4e, 0x69, 0x17e, 0x65, 0x72, 0x64, 0x75, 0xe1, 0x6c, 0xe1, 0x6a, 0x6f, 0x6f, 0x6c, 0x61, 0x53,
-0x65, 0x6e, 0x65, 0x67, 0x61, 0x6c, 0x65, 0x77, 0x6f, 0x6e, 0x64, 0x6f, 0x4b, 0x61, 0x6d, 0x259, 0x72, 0xfa, 0x6e, 0x72,
-0x69, 0x6b, 0x70, 0x61, 0x6b, 0x61, 0x6d, 0x25b, 0x72, 0xfa, 0x6e, 0x4d, 0x61, 0x6b, 0x75, 0x61, 0x55, 0x6d, 0x6f, 0x7a,
-0x61, 0x6d, 0x62, 0x69, 0x6b, 0x69, 0x4d, 0x55, 0x4e, 0x44, 0x41, 0x14a, 0x6b, 0x61, 0x6d, 0x65, 0x72, 0x75, 0x14b, 0x4b,
-0x77, 0x61, 0x73, 0x69, 0x6f, 0x4b, 0x61, 0x6d, 0x65, 0x72, 0x75, 0x6e, 0x54, 0x68, 0x6f, 0x6b, 0x20, 0x4e, 0x61, 0x74,
-0x68, 0x441, 0x430, 0x445, 0x430, 0x20, 0x442, 0x44b, 0x43b, 0x430, 0x410, 0x440, 0x430, 0x441, 0x441, 0x44b, 0x44b, 0x439, 0x430, 0x49,
-0x73, 0x68, 0x69, 0x73, 0x61, 0x6e, 0x67, 0x75, 0x54, 0x61, 0x6e, 0x73, 0x61, 0x6e, 0x69, 0x79, 0x61, 0x54, 0x61, 0x73,
-0x61, 0x77, 0x61, 0x71, 0x20, 0x73, 0x65, 0x6e, 0x6e, 0x69, 0xa559, 0xa524, 0xa55e, 0xa524, 0xa52b, 0xa569, 0x56, 0x61, 0x69, 0x4c,
-0x61, 0x69, 0x62, 0x68, 0x69, 0x79, 0x61, 0x57, 0x61, 0x6c, 0x73, 0x65, 0x72, 0x53, 0x63, 0x68, 0x77, 0x69, 0x7a, 0x6e,
-0x75, 0x61, 0x73, 0x75, 0x65, 0x4b, 0x65, 0x6d, 0x65, 0x6c, 0xfa, 0x6e, 0x61, 0x73, 0x74, 0x75, 0x72, 0x69, 0x61, 0x6e,
-0x75, 0x4e, 0x64, 0x61, 0xa78c, 0x61, 0x4b, 0x61, 0x6d, 0x25b, 0x6c, 0xfb, 0x6e, 0x6b, 0x61, 0x6b, 0x254, 0x4b, 0x61, 0x6d,
-0x25b, 0x72, 0x75, 0x6e, 0x6d, 0x65, 0x74, 0x61, 0x2bc, 0x4b, 0x61, 0x6d, 0x61, 0x6c, 0x75, 0x6e, 0x53, 0x68, 0x77, 0xf3,
-0x14b, 0xf2, 0x20, 0x6e, 0x67, 0x69, 0x65, 0x6d, 0x62, 0x254, 0x254, 0x6e, 0x4b, 0xe0, 0x6d, 0x61, 0x6c, 0xfb, 0x6d, 0x4c,
-0x61, 0x6b, 0x21f, 0xf3, 0x6c, 0x2bc, 0x69, 0x79, 0x61, 0x70, 0x69, 0x4d, 0xed, 0x6c, 0x61, 0x68, 0x61, 0x14b, 0x73, 0x6b,
-0x61, 0x20, 0x54, 0x21f, 0x61, 0x6d, 0xe1, 0x6b, 0x21f, 0x6f, 0x10d, 0x68, 0x65, 0x2d5c, 0x2d30, 0x2d4e, 0x2d30, 0x2d63, 0x2d49, 0x2d56,
-0x2d5c, 0x6a9, 0x648, 0x631, 0x62f, 0x6cc, 0x6cc, 0x20, 0x646, 0x627, 0x648, 0x6d5, 0x646, 0x62f, 0x6cc, 0x639, 0x6ce, 0x631, 0x627, 0x642,
-0x626, 0x6ce, 0x631, 0x627, 0x646, 0x64, 0x6f, 0x6c, 0x6e, 0x6f, 0x73, 0x65, 0x72, 0x62, 0x161, 0x107, 0x69, 0x6e, 0x61, 0x4e,
-0x69, 0x6d, 0x73, 0x6b, 0x61, 0x68, 0x6f, 0x72, 0x6e, 0x6a, 0x6f, 0x73, 0x65, 0x72, 0x62, 0x161, 0x107, 0x69, 0x6e, 0x61,
-0x4e, 0x11b, 0x6d, 0x73, 0x6b, 0x61, 0x61, 0x6e, 0x61, 0x72, 0xe2, 0x161, 0x6b, 0x69, 0x65, 0x6c, 0xe2, 0x53, 0x75, 0x6f,
-0x6d, 0xe2, 0x645, 0x627, 0x632, 0x631, 0x648, 0x646, 0x6cc, 0x644, 0x6ca, 0x631, 0x6cc, 0x20, 0x634, 0x648, 0x645, 0x627, 0x644, 0x6cc,
-0x7cb5, 0x8a9e, 0x4e2d, 0x83ef, 0x4eba, 0x6c11, 0x5171, 0x548c, 0x570b, 0x9999, 0x6e2f, 0x7279, 0x5225, 0x884c, 0x653f, 0x5340
+0x4a, 0x61, 0x77, 0x61, 0x49, 0x6e, 0x64, 0x6f, 0x6e, 0xe9, 0x73, 0x69, 0x61, 0xc95, 0xca8, 0xccd, 0xca8, 0xca1, 0xcad, 0xcbe,
+0xcb0, 0xca4, 0x6a9, 0x672, 0x634, 0x64f, 0x631, 0x6c1, 0x650, 0x646, 0x65b, 0x62f, 0x648, 0x633, 0x62a, 0x627, 0x646, 0x49b, 0x430, 0x437,
+0x430, 0x49b, 0x20, 0x442, 0x456, 0x43b, 0x456, 0x49a, 0x430, 0x437, 0x430, 0x49b, 0x441, 0x442, 0x430, 0x43d, 0x4b, 0x69, 0x6e, 0x79,
+0x61, 0x72, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x55, 0x20, 0x52, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x43a, 0x44b, 0x440, 0x433, 0x44b,
+0x437, 0x447, 0x430, 0x41a, 0x44b, 0x440, 0x433, 0x44b, 0x437, 0x441, 0x442, 0x430, 0x43d, 0xd55c, 0xad6d, 0xc5b4, 0xb300, 0xd55c, 0xbbfc, 0xad6d,
+0xc870, 0xc120, 0xbbfc, 0xc8fc, 0xc8fc, 0xc758, 0xc778, 0xbbfc, 0xacf5, 0xd654, 0xad6d, 0x6b, 0x75, 0x72, 0x64, 0xee, 0x54, 0x69, 0x72, 0x6b,
+0x69, 0x79, 0x65, 0x49, 0x6b, 0x69, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x55, 0x62, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0xea5,
+0xeb2, 0xea7, 0x6c, 0x61, 0x74, 0x76, 0x69, 0x65, 0x161, 0x75, 0x4c, 0x61, 0x74, 0x76, 0x69, 0x6a, 0x61, 0x6c, 0x69, 0x6e,
+0x67, 0xe1, 0x6c, 0x61, 0x52, 0x65, 0x70, 0x75, 0x62, 0x6c, 0xed, 0x6b, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x6f, 0x6e,
+0x67, 0xf3, 0x20, 0x44, 0x65, 0x6d, 0x6f, 0x6b, 0x72, 0x61, 0x74, 0xed, 0x6b, 0x69, 0x41, 0x6e, 0x67, 0xf3, 0x6c, 0x61,
+0x52, 0x65, 0x70, 0x69, 0x62, 0x69, 0x6b, 0x69, 0x20, 0x79, 0x61, 0x20, 0x41, 0x66, 0x72, 0xed, 0x6b, 0x61, 0x20, 0x79,
+0x61, 0x20, 0x4b, 0xe1, 0x74, 0x69, 0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x69, 0x65, 0x74, 0x75, 0x76, 0x69, 0x173, 0x4c,
+0x69, 0x65, 0x74, 0x75, 0x76, 0x61, 0x43c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d, 0x441, 0x43a, 0x438, 0x41c, 0x430, 0x43a, 0x435,
+0x434, 0x43e, 0x43d, 0x438, 0x458, 0x430, 0x4d, 0x61, 0x6c, 0x61, 0x67, 0x61, 0x73, 0x79, 0x4d, 0x61, 0x64, 0x61, 0x67, 0x61,
+0x73, 0x69, 0x6b, 0x61, 0x72, 0x61, 0x4d, 0x65, 0x6c, 0x61, 0x79, 0x75, 0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x53, 0x69,
+0x6e, 0x67, 0x61, 0x70, 0x75, 0x72, 0x61, 0xd2e, 0xd32, 0xd2f, 0xd3e, 0xd33, 0xd02, 0xd07, 0xd28, 0xd4d, 0xd24, 0xd4d, 0xd2f, 0x4d,
+0x61, 0x6c, 0x74, 0x69, 0x4d, 0x101, 0x6f, 0x72, 0x69, 0x41, 0x6f, 0x74, 0x65, 0x61, 0x72, 0x6f, 0x61, 0x92e, 0x930, 0x93e,
+0x920, 0x940, 0x43c, 0x43e, 0x43d, 0x433, 0x43e, 0x43b, 0x41c, 0x43e, 0x43d, 0x433, 0x43e, 0x43b, 0x928, 0x947, 0x92a, 0x93e, 0x932, 0x940,
+0x928, 0x947, 0x92a, 0x93e, 0x932, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x20, 0x62, 0x6f, 0x6b, 0x6d, 0xe5, 0x6c, 0x4e, 0x6f, 0x72,
+0x67, 0x65, 0x53, 0x76, 0x61, 0x6c, 0x62, 0x61, 0x72, 0x64, 0x20, 0x6f, 0x67, 0x20, 0x4a, 0x61, 0x6e, 0x20, 0x4d, 0x61,
+0x79, 0x65, 0x6e, 0xb13, 0xb21, 0xb3c, 0xb3f, 0xb06, 0xb2d, 0xb3e, 0xb30, 0xb24, 0x67e, 0x69a, 0x62a, 0x648, 0x627, 0x641, 0x63a, 0x627,
+0x646, 0x633, 0x62a, 0x627, 0x646, 0x641, 0x627, 0x631, 0x633, 0x6cc, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x62f, 0x631, 0x6cc, 0x70, 0x6f,
+0x6c, 0x73, 0x6b, 0x69, 0x50, 0x6f, 0x6c, 0x73, 0x6b, 0x61, 0x70, 0x6f, 0x72, 0x74, 0x75, 0x67, 0x75, 0xea, 0x73, 0x42,
+0x72, 0x61, 0x73, 0x69, 0x6c, 0x41, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x43, 0x61, 0x62, 0x6f, 0x20, 0x56, 0x65, 0x72, 0x64,
+0x65, 0x54, 0x69, 0x6d, 0x6f, 0x72, 0x2d, 0x4c, 0x65, 0x73, 0x74, 0x65, 0x47, 0x75, 0x69, 0x6e, 0xe9, 0x20, 0x45, 0x71,
+0x75, 0x61, 0x74, 0x6f, 0x72, 0x69, 0x61, 0x6c, 0x47, 0x75, 0x69, 0x6e, 0xe9, 0x2d, 0x42, 0x69, 0x73, 0x73, 0x61, 0x75,
+0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x75, 0x72, 0x67, 0x6f, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x2c, 0x20, 0x52, 0x41, 0x45,
+0x20, 0x64, 0x61, 0x20, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x4d, 0x6f, 0xe7, 0x61, 0x6d, 0x62, 0x69, 0x71, 0x75, 0x65, 0x70,
+0x6f, 0x72, 0x74, 0x75, 0x67, 0x75, 0xea, 0x73, 0x20, 0x65, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x75, 0x50, 0x6f, 0x72, 0x74,
+0x75, 0x67, 0x61, 0x6c, 0x53, 0xe3, 0x6f, 0x20, 0x54, 0x6f, 0x6d, 0xe9, 0x20, 0x65, 0x20, 0x50, 0x72, 0xed, 0x6e, 0x63,
+0x69, 0x70, 0x65, 0x53, 0x75, 0xed, 0xe7, 0x61, 0xa2a, 0xa70, 0xa1c, 0xa3e, 0xa2c, 0xa40, 0xa2d, 0xa3e, 0xa30, 0xa24, 0x67e, 0x646,
+0x62c, 0x627, 0x628, 0x6cc, 0x67e, 0x627, 0x6a9, 0x633, 0x62a, 0x627, 0x646, 0x52, 0x75, 0x6e, 0x61, 0x73, 0x69, 0x6d, 0x69, 0x50,
+0x65, 0x72, 0xfa, 0x42, 0x6f, 0x6c, 0x69, 0x76, 0x69, 0x61, 0x45, 0x63, 0x75, 0x61, 0x64, 0x6f, 0x72, 0x72, 0x75, 0x6d,
+0x61, 0x6e, 0x74, 0x73, 0x63, 0x68, 0x53, 0x76, 0x69, 0x7a, 0x72, 0x61, 0x72, 0x6f, 0x6d, 0xe2, 0x6e, 0x103, 0x52, 0x6f,
+0x6d, 0xe2, 0x6e, 0x69, 0x61, 0x52, 0x65, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x20, 0x4d, 0x6f, 0x6c, 0x64, 0x6f,
+0x76, 0x61, 0x440, 0x443, 0x441, 0x441, 0x43a, 0x438, 0x439, 0x420, 0x43e, 0x441, 0x441, 0x438, 0x44f, 0x41a, 0x430, 0x437, 0x430, 0x445,
+0x441, 0x442, 0x430, 0x43d, 0x41a, 0x438, 0x440, 0x433, 0x438, 0x437, 0x438, 0x44f, 0x41c, 0x43e, 0x43b, 0x434, 0x43e, 0x432, 0x430, 0x423,
+0x43a, 0x440, 0x430, 0x438, 0x43d, 0x430, 0x53, 0xe4, 0x6e, 0x67, 0xf6, 0x4b, 0xf6, 0x64, 0xf6, 0x72, 0xf6, 0x73, 0xea, 0x73,
+0x65, 0x20, 0x74, 0xee, 0x20, 0x42, 0xea, 0x61, 0x66, 0x72, 0xee, 0x6b, 0x61, 0x441, 0x440, 0x43f, 0x441, 0x43a, 0x438, 0x421,
+0x440, 0x431, 0x438, 0x458, 0x430, 0x411, 0x43e, 0x441, 0x43d, 0x430, 0x20, 0x438, 0x20, 0x425, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e,
+0x432, 0x438, 0x43d, 0x430, 0x426, 0x440, 0x43d, 0x430, 0x20, 0x413, 0x43e, 0x440, 0x430, 0x41a, 0x43e, 0x441, 0x43e, 0x432, 0x43e, 0x73,
+0x72, 0x70, 0x73, 0x6b, 0x69, 0x43, 0x72, 0x6e, 0x61, 0x20, 0x47, 0x6f, 0x72, 0x61, 0x53, 0x72, 0x62, 0x69, 0x6a, 0x61,
+0x4b, 0x6f, 0x73, 0x6f, 0x76, 0x6f, 0x438, 0x440, 0x43e, 0x43d, 0x413, 0x443, 0x44b, 0x440, 0x434, 0x437, 0x44b, 0x441, 0x442, 0x43e,
+0x43d, 0x423, 0x4d5, 0x440, 0x4d5, 0x441, 0x435, 0x63, 0x68, 0x69, 0x53, 0x68, 0x6f, 0x6e, 0x61, 0x633, 0x646, 0x68c, 0x64a, 0x67e,
+0x627, 0x6aa, 0x633, 0x62a, 0x627, 0x646, 0xdc3, 0xdd2, 0xd82, 0xdc4, 0xdbd, 0xdc1, 0xdca, 0x200d, 0xdbb, 0xdd3, 0x20, 0xdbd, 0xd82, 0xd9a,
+0xdcf, 0xdc0, 0x73, 0x6c, 0x6f, 0x76, 0x65, 0x6e, 0x10d, 0x69, 0x6e, 0x61, 0x53, 0x6c, 0x6f, 0x76, 0x65, 0x6e, 0x73, 0x6b,
+0x6f, 0x73, 0x6c, 0x6f, 0x76, 0x65, 0x6e, 0x161, 0x10d, 0x69, 0x6e, 0x61, 0x53, 0x6c, 0x6f, 0x76, 0x65, 0x6e, 0x69, 0x6a,
+0x61, 0x53, 0x6f, 0x6f, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x53, 0x6f, 0x6f, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x79, 0x61, 0x4a,
+0x61, 0x62, 0x75, 0x75, 0x74, 0x69, 0x49, 0x74, 0x6f, 0x6f, 0x62, 0x69, 0x79, 0x61, 0x65, 0x73, 0x70, 0x61, 0xf1, 0x6f,
+0x6c, 0x20, 0x64, 0x65, 0x20, 0x45, 0x73, 0x70, 0x61, 0xf1, 0x61, 0x65, 0x73, 0x70, 0x61, 0xf1, 0x6f, 0x6c, 0x41, 0x72,
+0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x42, 0x65, 0x6c, 0x69, 0x63, 0x65, 0x43, 0x68, 0x69, 0x6c, 0x65, 0x43, 0x6f,
+0x6c, 0x6f, 0x6d, 0x62, 0x69, 0x61, 0x43, 0x6f, 0x73, 0x74, 0x61, 0x20, 0x52, 0x69, 0x63, 0x61, 0x43, 0x75, 0x62, 0x61,
+0x52, 0x65, 0x70, 0xfa, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x20, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61, 0x6e, 0x61,
+0x45, 0x6c, 0x20, 0x53, 0x61, 0x6c, 0x76, 0x61, 0x64, 0x6f, 0x72, 0x47, 0x75, 0x69, 0x6e, 0x65, 0x61, 0x20, 0x45, 0x63,
+0x75, 0x61, 0x74, 0x6f, 0x72, 0x69, 0x61, 0x6c, 0x47, 0x75, 0x61, 0x74, 0x65, 0x6d, 0x61, 0x6c, 0x61, 0x48, 0x6f, 0x6e,
+0x64, 0x75, 0x72, 0x61, 0x73, 0x65, 0x73, 0x70, 0x61, 0xf1, 0x6f, 0x6c, 0x20, 0x64, 0x65, 0x20, 0x4d, 0xe9, 0x78, 0x69,
+0x63, 0x6f, 0x4d, 0xe9, 0x78, 0x69, 0x63, 0x6f, 0x4e, 0x69, 0x63, 0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x50, 0x61, 0x6e,
+0x61, 0x6d, 0xe1, 0x50, 0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x79, 0x46, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x61, 0x73,
+0x45, 0x73, 0x74, 0x61, 0x64, 0x6f, 0x73, 0x20, 0x55, 0x6e, 0x69, 0x64, 0x6f, 0x73, 0x55, 0x72, 0x75, 0x67, 0x75, 0x61,
+0x79, 0x56, 0x65, 0x6e, 0x65, 0x7a, 0x75, 0x65, 0x6c, 0x61, 0x43, 0x61, 0x6e, 0x61, 0x72, 0x69, 0x61, 0x73, 0x65, 0x73,
+0x70, 0x61, 0xf1, 0x6f, 0x6c, 0x20, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x6f, 0x61, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x6e,
+0x6f, 0x4c, 0x61, 0x74, 0x69, 0x6e, 0x6f, 0x61, 0x6d, 0xe9, 0x72, 0x69, 0x63, 0x61, 0x43, 0x65, 0x75, 0x74, 0x61, 0x20,
+0x79, 0x20, 0x4d, 0x65, 0x6c, 0x69, 0x6c, 0x6c, 0x61, 0x4b, 0x69, 0x73, 0x77, 0x61, 0x68, 0x69, 0x6c, 0x69, 0x4a, 0x61,
+0x6d, 0x68, 0x75, 0x72, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x69, 0x64, 0x65, 0x6d, 0x6f, 0x6b, 0x72, 0x61, 0x73, 0x69,
+0x61, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x73, 0x76, 0x65, 0x6e, 0x73, 0x6b, 0x61, 0x53, 0x76, 0x65,
+0x72, 0x69, 0x67, 0x65, 0xc5, 0x6c, 0x61, 0x6e, 0x64, 0x442, 0x43e, 0x4b7, 0x438, 0x43a, 0x4e3, 0x422, 0x43e, 0x4b7, 0x438, 0x43a,
+0x438, 0x441, 0x442, 0x43e, 0x43d, 0xba4, 0xbae, 0xbbf, 0xbb4, 0xbcd, 0xb87, 0xba8, 0xbcd, 0xba4, 0xbbf, 0xbaf, 0xbbe, 0xbae, 0xbb2, 0xbc7,
+0xb9a, 0xbbf, 0xbaf, 0xbbe, 0xb9a, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbaa, 0xbcd, 0xbaa, 0xbc2, 0xbb0, 0xbcd, 0xb87, 0xbb2, 0xb99, 0xbcd, 0xb95,
+0xbc8, 0x442, 0x430, 0x442, 0x430, 0x440, 0xc24, 0xc46, 0xc32, 0xc41, 0xc17, 0xc41, 0xc2d, 0xc3e, 0xc30, 0xc24, 0xc26, 0xc47, 0xc36, 0xc02,
+0xe44, 0xe17, 0xe22, 0xf56, 0xf7c, 0xf51, 0xf0b, 0xf66, 0xf90, 0xf51, 0xf0b, 0xf62, 0xf92, 0xfb1, 0xf0b, 0xf53, 0xf42, 0xf62, 0xf92, 0xfb1,
+0xf0b, 0xf42, 0xf62, 0xf0b, 0x1275, 0x130d, 0x122d, 0x129b, 0x12a4, 0x122d, 0x1275, 0x122b, 0x6c, 0x65, 0x61, 0x20, 0x66, 0x61, 0x6b, 0x61,
+0x74, 0x6f, 0x6e, 0x67, 0x61, 0x54, 0xfc, 0x72, 0x6b, 0xe7, 0x65, 0x54, 0xfc, 0x72, 0x6b, 0x69, 0x79, 0x65, 0x4b, 0x131,
+0x62, 0x72, 0x131, 0x73, 0x74, 0xfc, 0x72, 0x6b, 0x6d, 0x65, 0x6e, 0x20, 0x64, 0x69, 0x6c, 0x69, 0x54, 0xfc, 0x72, 0x6b,
+0x6d, 0x65, 0x6e, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x626, 0x6c7, 0x64a, 0x63a, 0x6c7, 0x631, 0x686, 0x6d5, 0x62c, 0x6c7, 0x6ad, 0x6af,
+0x648, 0x443, 0x43a, 0x440, 0x430, 0x457, 0x43d, 0x441, 0x44c, 0x43a, 0x430, 0x423, 0x43a, 0x440, 0x430, 0x457, 0x43d, 0x430, 0x627, 0x631,
+0x62f, 0x648, 0x628, 0x6be, 0x627, 0x631, 0x62a, 0x6f, 0x2018, 0x7a, 0x62, 0x65, 0x6b, 0x4f, 0x2bb, 0x7a, 0x62, 0x65, 0x6b, 0x69,
+0x73, 0x74, 0x6f, 0x6e, 0x627, 0x648, 0x632, 0x628, 0x6cc, 0x6a9, 0x45e, 0x437, 0x431, 0x435, 0x43a, 0x447, 0x430, 0x40e, 0x437, 0x431,
+0x435, 0x43a, 0x438, 0x441, 0x442, 0x43e, 0x43d, 0x54, 0x69, 0x1ebf, 0x6e, 0x67, 0x20, 0x56, 0x69, 0x1ec7, 0x74, 0x56, 0x69, 0x1ec7,
+0x74, 0x20, 0x4e, 0x61, 0x6d, 0x56, 0x6f, 0x6c, 0x61, 0x70, 0xfc, 0x6b, 0x43, 0x79, 0x6d, 0x72, 0x61, 0x65, 0x67, 0x59,
+0x20, 0x44, 0x65, 0x79, 0x72, 0x6e, 0x61, 0x73, 0x20, 0x55, 0x6e, 0x65, 0x64, 0x69, 0x67, 0x57, 0x6f, 0x6c, 0x6f, 0x66,
+0x53, 0x65, 0x6e, 0x65, 0x67, 0x61, 0x61, 0x6c, 0x69, 0x73, 0x69, 0x58, 0x68, 0x6f, 0x73, 0x61, 0x65, 0x4d, 0x7a, 0x61,
+0x6e, 0x74, 0x73, 0x69, 0x20, 0x41, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x5d9, 0x5d9, 0x5b4, 0x5d3, 0x5d9, 0x5e9, 0x5d5, 0x5d5, 0x5e2,
+0x5dc, 0x5d8, 0xc8, 0x64, 0xe8, 0x20, 0x59, 0x6f, 0x72, 0xf9, 0x62, 0xe1, 0x4f, 0x72, 0xed, 0x6c, 0x1eb9, 0x301, 0xe8, 0x64,
+0x65, 0x20, 0x4e, 0xe0, 0xec, 0x6a, 0xed, 0x72, 0xed, 0xe0, 0x4f, 0x72, 0xed, 0x6c, 0x25b, 0x301, 0xe8, 0x64, 0x65, 0x20,
+0x42, 0x25b, 0x300, 0x6e, 0x25b, 0x300, 0x69, 0x73, 0x69, 0x5a, 0x75, 0x6c, 0x75, 0x69, 0x4e, 0x69, 0x6e, 0x67, 0x69, 0x7a,
+0x69, 0x6d, 0x75, 0x20, 0x41, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x6e, 0x79, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x4e, 0x6f, 0x72,
+0x65, 0x67, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x69, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x438, 0x47, 0x61,
+0x65, 0x6c, 0x67, 0x45, 0x6c, 0x6c, 0x61, 0x6e, 0x20, 0x56, 0x61, 0x6e, 0x6e, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x6e, 0x65,
+0x77, 0x65, 0x6b, 0x52, 0x79, 0x77, 0x76, 0x61, 0x6e, 0x65, 0x74, 0x68, 0x20, 0x55, 0x6e, 0x79, 0x73, 0x41, 0x6b, 0x61,
+0x6e, 0x47, 0x61, 0x61, 0x6e, 0x61, 0x915, 0x94b, 0x902, 0x915, 0x923, 0x940, 0x49, 0x67, 0x62, 0x6f, 0x4e, 0x61, 0x1ecb, 0x6a,
+0x1ecb, 0x72, 0x1ecb, 0x61, 0x4b, 0x69, 0x6b, 0x61, 0x6d, 0x62, 0x61, 0x66, 0x75, 0x72, 0x6c, 0x61, 0x6e, 0x49, 0x74, 0x61,
+0x6c, 0x69, 0x65, 0x45, 0x28b, 0x65, 0x67, 0x62, 0x65, 0x47, 0x68, 0x61, 0x6e, 0x61, 0x20, 0x6e, 0x75, 0x74, 0x6f, 0x6d,
+0x65, 0x54, 0x6f, 0x67, 0x6f, 0x20, 0x6e, 0x75, 0x74, 0x6f, 0x6d, 0x65, 0x2bb, 0x14c, 0x6c, 0x65, 0x6c, 0x6f, 0x20, 0x48,
+0x61, 0x77, 0x61, 0x69, 0x2bb, 0x69, 0x2bb, 0x41, 0x6d, 0x65, 0x6c, 0x69, 0x6b, 0x61, 0x20, 0x48, 0x75, 0x69, 0x20, 0x50,
+0x16b, 0x20, 0x2bb, 0x49, 0x61, 0x46, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x6f, 0x50, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e,
+0x61, 0x73, 0x53, 0x63, 0x68, 0x77, 0x69, 0x69, 0x7a, 0x65, 0x72, 0x74, 0xfc, 0xfc, 0x74, 0x73, 0x63, 0x68, 0x53, 0x63,
+0x68, 0x77, 0x69, 0x69, 0x7a, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x72, 0x69, 0x69, 0x63, 0x68, 0x4c, 0x69, 0xe4, 0x63, 0x68,
+0x74, 0x65, 0x73, 0x63, 0x68, 0x74, 0xe4, 0x69, 0xa188, 0xa320, 0xa259, 0xa34f, 0xa1e9, 0x4e, 0x65, 0x64, 0x64, 0x65, 0x72, 0x73,
+0x61, 0x73, 0x73, 0x2019, 0x73, 0x63, 0x68, 0x44, 0xfc, 0xfc, 0x74, 0x73, 0x63, 0x68, 0x6c, 0x61, 0x6e, 0x64, 0x4e, 0x65,
+0x64, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x6e, 0x64, 0x61, 0x76, 0x76, 0x69, 0x73, 0xe1, 0x6d, 0x65, 0x67,
+0x69, 0x65, 0x6c, 0x6c, 0x61, 0x4e, 0x6f, 0x72, 0x67, 0x61, 0x53, 0x75, 0x6f, 0x70, 0x6d, 0x61, 0x52, 0x75, 0x6f, 0x167,
+0x167, 0x61, 0x45, 0x6b, 0x65, 0x67, 0x75, 0x73, 0x69, 0x69, 0x4b, 0x69, 0x74, 0x61, 0x69, 0x74, 0x61, 0x50, 0x75, 0x6c,
+0x61, 0x61, 0x72, 0x42, 0x75, 0x72, 0x6b, 0x69, 0x62, 0x61, 0x61, 0x20, 0x46, 0x61, 0x61, 0x73, 0x6f, 0x4b, 0x61, 0x6d,
+0x65, 0x72, 0x75, 0x75, 0x6e, 0x47, 0x61, 0x6d, 0x6d, 0x62, 0x69, 0x47, 0x61, 0x6e, 0x61, 0x61, 0x47, 0x69, 0x6e, 0x65,
+0x47, 0x69, 0x6e, 0x65, 0x2d, 0x42, 0x69, 0x73, 0x61, 0x61, 0x77, 0x6f, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x69, 0x79, 0x61,
+0x61, 0x4d, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x4e, 0x69, 0x6a, 0x65, 0x65, 0x72, 0x4e, 0x69, 0x6a, 0x65, 0x72,
+0x69, 0x79, 0x61, 0x61, 0x53, 0x65, 0x72, 0x61, 0x61, 0x20, 0x6c, 0x69, 0x79, 0x6f, 0x6e, 0x47, 0x69, 0x6b, 0x75, 0x79,
+0x75, 0x4b, 0x69, 0x73, 0x61, 0x6d, 0x70, 0x75, 0x72, 0x73, 0x65, 0x6e, 0x61, 0x69, 0x73, 0x69, 0x4e, 0x64, 0x65, 0x62,
+0x65, 0x6c, 0x65, 0x4b, 0x69, 0x68, 0x6f, 0x72, 0x6f, 0x6d, 0x62, 0x6f, 0x2d5c, 0x2d30, 0x2d5b, 0x2d4d, 0x2d43, 0x2d49, 0x2d5c, 0x2d4d,
+0x2d4e, 0x2d56, 0x2d54, 0x2d49, 0x2d31, 0x54, 0x61, 0x73, 0x68, 0x65, 0x6c, 0x1e25, 0x69, 0x79, 0x74, 0x6c, 0x6d, 0x263, 0x72, 0x69,
+0x62, 0x54, 0x61, 0x71, 0x62, 0x61, 0x79, 0x6c, 0x69, 0x74, 0x4c, 0x65, 0x7a, 0x7a, 0x61, 0x79, 0x65, 0x72, 0x52, 0x75,
+0x6e, 0x79, 0x61, 0x6e, 0x6b, 0x6f, 0x72, 0x65, 0x48, 0x69, 0x62, 0x65, 0x6e, 0x61, 0x48, 0x75, 0x74, 0x61, 0x6e, 0x7a,
+0x61, 0x6e, 0x69, 0x61, 0x4b, 0x79, 0x69, 0x76, 0x75, 0x6e, 0x6a, 0x6f, 0x62, 0x61, 0x6d, 0x61, 0x6e, 0x61, 0x6b, 0x61,
+0x6e, 0x4b, 0x129, 0x65, 0x6d, 0x62, 0x75, 0x13e3, 0x13b3, 0x13a9, 0x13cc, 0x13ca, 0x20, 0x13a2, 0x13f3, 0x13be, 0x13b5, 0x13cd, 0x13d4, 0x13c5,
+0x20, 0x13cd, 0x13a6, 0x13da, 0x13a9, 0x6b, 0x72, 0x65, 0x6f, 0x6c, 0x20, 0x6d, 0x6f, 0x72, 0x69, 0x73, 0x69, 0x65, 0x6e, 0x4d,
+0x6f, 0x72, 0x69, 0x73, 0x43, 0x68, 0x69, 0x6d, 0x61, 0x6b, 0x6f, 0x6e, 0x64, 0x65, 0x4b, 0x268, 0x6c, 0x61, 0x61, 0x6e,
+0x67, 0x69, 0x54, 0x61, 0x61, 0x6e, 0x73, 0x61, 0x6e, 0xed, 0x61, 0x4c, 0x75, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x59, 0x75,
+0x67, 0x61, 0x6e, 0x64, 0x61, 0x49, 0x63, 0x68, 0x69, 0x62, 0x65, 0x6d, 0x62, 0x61, 0x6b, 0x61, 0x62, 0x75, 0x76, 0x65,
+0x72, 0x64, 0x69, 0x61, 0x6e, 0x75, 0x4b, 0x61, 0x62, 0x75, 0x20, 0x56, 0x65, 0x72, 0x64, 0x69, 0x4b, 0x129, 0x6d, 0x129,
+0x72, 0x169, 0x4b, 0x61, 0x6c, 0x65, 0x6e, 0x6a, 0x69, 0x6e, 0x45, 0x6d, 0x65, 0x74, 0x61, 0x62, 0x20, 0x4b, 0x65, 0x6e,
+0x79, 0x61, 0x4b, 0x68, 0x6f, 0x65, 0x6b, 0x68, 0x6f, 0x65, 0x67, 0x6f, 0x77, 0x61, 0x62, 0x4e, 0x61, 0x6d, 0x69, 0x62,
+0x69, 0x61, 0x62, 0x4b, 0x69, 0x6d, 0x61, 0x63, 0x68, 0x61, 0x6d, 0x65, 0x4b, 0xf6, 0x6c, 0x73, 0x63, 0x68, 0x44, 0x6f,
+0xfc, 0x74, 0x73, 0x63, 0x68, 0x6c, 0x61, 0x6e, 0x64, 0x4d, 0x61, 0x61, 0x54, 0x61, 0x6e, 0x73, 0x61, 0x6e, 0x69, 0x61,
+0x4f, 0x6c, 0x75, 0x73, 0x6f, 0x67, 0x61, 0x4c, 0x75, 0x6c, 0x75, 0x68, 0x69, 0x61, 0x4b, 0x69, 0x70, 0x61, 0x72, 0x65,
+0x54, 0x61, 0x64, 0x68, 0x61, 0x6e, 0x69, 0x61, 0x4b, 0x69, 0x74, 0x65, 0x73, 0x6f, 0x4b, 0x65, 0x6e, 0x69, 0x61, 0x4b,
+0x6f, 0x79, 0x72, 0x61, 0x20, 0x63, 0x69, 0x69, 0x6e, 0x69, 0x4d, 0x61, 0x61, 0x6c, 0x69, 0x4b, 0x69, 0x72, 0x75, 0x77,
+0x61, 0x44, 0x68, 0x6f, 0x6c, 0x75, 0x6f, 0x52, 0x75, 0x6b, 0x69, 0x67, 0x61, 0x54, 0x61, 0x6d, 0x61, 0x7a, 0x69, 0x263,
+0x74, 0x20, 0x6e, 0x20, 0x6c, 0x61, 0x1e6d, 0x6c, 0x61, 0x1e63, 0x4d, 0x65, 0x1e5b, 0x1e5b, 0x75, 0x6b, 0x4b, 0x6f, 0x79, 0x72,
+0x61, 0x62, 0x6f, 0x72, 0x6f, 0x20, 0x73, 0x65, 0x6e, 0x6e, 0x69, 0x4b, 0x69, 0x73, 0x68, 0x61, 0x6d, 0x62, 0x61, 0x61,
+0x92c, 0x921, 0x93c, 0x94b, 0x43d, 0x43e, 0x445, 0x447, 0x438, 0x439, 0x43d, 0x420, 0x43e, 0x441, 0x441, 0x438, 0x446, 0x435, 0x440, 0x43a,
+0x43e, 0x432, 0x43d, 0x43e, 0x441, 0x43b, 0x43e, 0x432, 0x435, 0x301, 0x43d, 0x441, 0x43a, 0x457, 0x439, 0x440, 0x461, 0x441, 0x441, 0x456,
+0x301, 0x430, 0x54, 0x73, 0x68, 0x69, 0x6c, 0x75, 0x62, 0x61, 0x44, 0x69, 0x74, 0x75, 0x6e, 0x67, 0x61, 0x20, 0x77, 0x61,
+0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x75, 0x4c, 0xeb, 0x74, 0x7a, 0x65, 0x62, 0x75, 0x65, 0x72, 0x67, 0x65, 0x73, 0x63, 0x68,
+0x4c, 0xeb, 0x74, 0x7a, 0x65, 0x62, 0x75, 0x65, 0x72, 0x67, 0x41, 0x67, 0x68, 0x65, 0x6d, 0x4b, 0xe0, 0x6d, 0xe0, 0x6c,
+0xfb, 0x14b, 0x181, 0xe0, 0x73, 0xe0, 0x61, 0x4b, 0xe0, 0x6d, 0x25b, 0x300, 0x72, 0xfb, 0x6e, 0x5a, 0x61, 0x72, 0x6d, 0x61,
+0x63, 0x69, 0x69, 0x6e, 0x65, 0x4e, 0x69, 0x17e, 0x65, 0x72, 0x64, 0x75, 0xe1, 0x6c, 0xe1, 0x6a, 0x6f, 0x6f, 0x6c, 0x61,
+0x53, 0x65, 0x6e, 0x65, 0x67, 0x61, 0x6c, 0x65, 0x77, 0x6f, 0x6e, 0x64, 0x6f, 0x4b, 0x61, 0x6d, 0x259, 0x72, 0xfa, 0x6e,
+0x72, 0x69, 0x6b, 0x70, 0x61, 0x6b, 0x61, 0x6d, 0x25b, 0x72, 0xfa, 0x6e, 0x4d, 0x61, 0x6b, 0x75, 0x61, 0x55, 0x6d, 0x6f,
+0x7a, 0x61, 0x6d, 0x62, 0x69, 0x6b, 0x69, 0x4d, 0x55, 0x4e, 0x44, 0x41, 0x14a, 0x6b, 0x61, 0x6d, 0x65, 0x72, 0x75, 0x14b,
+0x4b, 0x77, 0x61, 0x73, 0x69, 0x6f, 0x4b, 0x61, 0x6d, 0x65, 0x72, 0x75, 0x6e, 0x54, 0x68, 0x6f, 0x6b, 0x20, 0x4e, 0x61,
+0x74, 0x68, 0x441, 0x430, 0x445, 0x430, 0x20, 0x442, 0x44b, 0x43b, 0x430, 0x410, 0x440, 0x430, 0x441, 0x441, 0x44b, 0x44b, 0x439, 0x430,
+0x49, 0x73, 0x68, 0x69, 0x73, 0x61, 0x6e, 0x67, 0x75, 0x54, 0x61, 0x6e, 0x73, 0x61, 0x6e, 0x69, 0x79, 0x61, 0x54, 0x61,
+0x73, 0x61, 0x77, 0x61, 0x71, 0x20, 0x73, 0x65, 0x6e, 0x6e, 0x69, 0xa559, 0xa524, 0xa55e, 0xa524, 0xa52b, 0xa569, 0x56, 0x61, 0x69,
+0x4c, 0x61, 0x69, 0x62, 0x68, 0x69, 0x79, 0x61, 0x57, 0x61, 0x6c, 0x73, 0x65, 0x72, 0x53, 0x63, 0x68, 0x77, 0x69, 0x7a,
+0x6e, 0x75, 0x61, 0x73, 0x75, 0x65, 0x4b, 0x65, 0x6d, 0x65, 0x6c, 0xfa, 0x6e, 0x61, 0x73, 0x74, 0x75, 0x72, 0x69, 0x61,
+0x6e, 0x75, 0x4e, 0x64, 0x61, 0xa78c, 0x61, 0x4b, 0x61, 0x6d, 0x25b, 0x6c, 0xfb, 0x6e, 0x6b, 0x61, 0x6b, 0x254, 0x4b, 0x61,
+0x6d, 0x25b, 0x72, 0x75, 0x6e, 0x6d, 0x65, 0x74, 0x61, 0x2bc, 0x4b, 0x61, 0x6d, 0x61, 0x6c, 0x75, 0x6e, 0x53, 0x68, 0x77,
+0xf3, 0x14b, 0xf2, 0x20, 0x6e, 0x67, 0x69, 0x65, 0x6d, 0x62, 0x254, 0x254, 0x6e, 0x4b, 0xe0, 0x6d, 0x61, 0x6c, 0xfb, 0x6d,
+0x4c, 0x61, 0x6b, 0x21f, 0xf3, 0x6c, 0x2bc, 0x69, 0x79, 0x61, 0x70, 0x69, 0x4d, 0xed, 0x6c, 0x61, 0x68, 0x61, 0x14b, 0x73,
+0x6b, 0x61, 0x20, 0x54, 0x21f, 0x61, 0x6d, 0xe1, 0x6b, 0x21f, 0x6f, 0x10d, 0x68, 0x65, 0x2d5c, 0x2d30, 0x2d4e, 0x2d30, 0x2d63, 0x2d49,
+0x2d56, 0x2d5c, 0x6a9, 0x648, 0x631, 0x62f, 0x6cc, 0x6cc, 0x20, 0x646, 0x627, 0x648, 0x6d5, 0x646, 0x62f, 0x6cc, 0x639, 0x6ce, 0x631, 0x627,
+0x642, 0x626, 0x6ce, 0x631, 0x627, 0x646, 0x64, 0x6f, 0x6c, 0x6e, 0x6f, 0x73, 0x65, 0x72, 0x62, 0x161, 0x107, 0x69, 0x6e, 0x61,
+0x4e, 0x69, 0x6d, 0x73, 0x6b, 0x61, 0x68, 0x6f, 0x72, 0x6e, 0x6a, 0x6f, 0x73, 0x65, 0x72, 0x62, 0x161, 0x107, 0x69, 0x6e,
+0x61, 0x4e, 0x11b, 0x6d, 0x73, 0x6b, 0x61, 0x70, 0x72, 0x16b, 0x73, 0x69, 0x73, 0x6b, 0x61, 0x6e, 0x73, 0x77, 0x12b, 0x74,
+0x61, 0x69, 0x61, 0x6e, 0x61, 0x72, 0xe2, 0x161, 0x6b, 0x69, 0x65, 0x6c, 0xe2, 0x53, 0x75, 0x6f, 0x6d, 0xe2, 0x645, 0x627,
+0x632, 0x631, 0x648, 0x646, 0x6cc, 0x644, 0x6ca, 0x631, 0x6cc, 0x20, 0x634, 0x648, 0x645, 0x627, 0x644, 0x6cc, 0x7cb5, 0x8a9e, 0x4e2d, 0x83ef,
+0x4eba, 0x6c11, 0x5171, 0x548c, 0x570b, 0x9999, 0x6e2f, 0x7279, 0x5225, 0x884c, 0x653f, 0x5340, 0x7ca4, 0x8bed, 0x4e2d, 0x534e, 0x4eba, 0x6c11, 0x5171, 0x548c,
+0x56fd
};
static const char language_name_list[] =
@@ -6217,7 +6498,7 @@ static const char language_name_list[] =
"Mongolian\0"
"Nauru\0"
"Nepali\0"
-"NorwegianBokmal\0"
+"Norwegian Bokmal\0"
"Occitan\0"
"Oriya\0"
"Pashto\0"
@@ -6273,7 +6554,7 @@ static const char language_name_list[] =
"Yoruba\0"
"Zhuang\0"
"Zulu\0"
-"NorwegianNynorsk\0"
+"Norwegian Nynorsk\0"
"Bosnian\0"
"Divehi\0"
"Manx\0"
@@ -6362,7 +6643,7 @@ static const char language_name_list[] =
"Kongo\0"
"Kwanyama\0"
"Limburgish\0"
-"LubaKatanga\0"
+"Luba Katanga\0"
"Luxembourgish\0"
"Navaho\0"
"Ndonga\0"
@@ -6373,10 +6654,10 @@ static const char language_name_list[] =
"Basaa\0"
"Zarma\0"
"Duala\0"
-"JolaFonyi\0"
+"Jola Fonyi\0"
"Ewondo\0"
"Bafia\0"
-"MakhuwaMeetto\0"
+"Makhuwa Meetto\0"
"Mundang\0"
"Kwasio\0"
"Nuer\0"
@@ -6395,26 +6676,26 @@ static const char language_name_list[] =
"Ngiemboon\0"
"Aragonese\0"
"Akkadian\0"
-"AncientEgyptian\0"
-"AncientGreek\0"
+"Ancient Egyptian\0"
+"Ancient Greek\0"
"Aramaic\0"
"Balinese\0"
"Bamun\0"
-"BatakToba\0"
+"Batak Toba\0"
"Buginese\0"
"Buhid\0"
"Carian\0"
"Chakma\0"
-"ClassicalMandaic\0"
+"Classical Mandaic\0"
"Coptic\0"
"Dogri\0"
-"EasternCham\0"
-"EasternKayah\0"
+"Eastern Cham\0"
+"Eastern Kayah\0"
"Etruscan\0"
"Gothic\0"
"Hanunoo\0"
"Ingush\0"
-"LargeFloweryMiao\0"
+"Large Flowery Miao\0"
"Lepcha\0"
"Limbu\0"
"Lisu\0"
@@ -6424,15 +6705,15 @@ static const char language_name_list[] =
"Mandingo\0"
"Manipuri\0"
"Meroitic\0"
-"NorthernThai\0"
-"OldIrish\0"
-"OldNorse\0"
-"OldPersian\0"
-"OldTurkish\0"
+"Northern Thai\0"
+"Old Irish\0"
+"Old Norse\0"
+"Old Persian\0"
+"Old Turkish\0"
"Pahlavi\0"
"Parthian\0"
"Phoenician\0"
-"PrakritLanguage\0"
+"Prakrit Language\0"
"Rejang\0"
"Sabaean\0"
"Samaritan\0"
@@ -6441,16 +6722,16 @@ static const char language_name_list[] =
"Sora\0"
"Sylheti\0"
"Tagbanwa\0"
-"TaiDam\0"
-"TaiNua\0"
+"Tai Dam\0"
+"Tai Nua\0"
"Ugaritic\0"
"Akoose\0"
"Lakota\0"
"Standard Moroccan Tamazight\0"
"Mapuche\0"
"Central Kurdish\0"
-"LowerSorbian\0"
-"UpperSorbian\0"
+"Lower Sorbian\0"
+"Upper Sorbian\0"
"Kenyang\0"
"Mohawk\0"
"Nko\0"
@@ -6488,7 +6769,7 @@ static const char language_name_list[] =
"Tokelau\0"
"Tok Pisin\0"
"Tuvalu\0"
-"UncodedLanguages\0"
+"Uncoded Languages\0"
"Cantonese\0"
"Osage\0"
"Tangut\0"
@@ -6580,281 +6861,281 @@ static const quint16 language_name_index[] = {
680, // Mongolian
690, // Nauru
696, // Nepali
- 703, // NorwegianBokmal
- 719, // Occitan
- 727, // Oriya
- 733, // Pashto
- 740, // Persian
- 748, // Polish
- 755, // Portuguese
- 766, // Punjabi
- 774, // Quechua
- 782, // Romansh
- 790, // Romanian
- 799, // Russian
- 807, // Samoan
- 814, // Sango
- 820, // Sanskrit
- 829, // Serbian
- 837, // Ossetic
- 845, // Southern Sotho
- 860, // Tswana
- 867, // Shona
- 873, // Sindhi
- 880, // Sinhala
- 888, // Swati
- 894, // Slovak
- 901, // Slovenian
- 911, // Somali
- 918, // Spanish
- 926, // Sundanese
- 936, // Swahili
- 944, // Swedish
- 952, // Sardinian
- 962, // Tajik
- 968, // Tamil
- 974, // Tatar
- 980, // Telugu
- 987, // Thai
- 992, // Tibetan
- 1000, // Tigrinya
- 1009, // Tongan
- 1016, // Tsonga
- 1023, // Turkish
- 1031, // Turkmen
- 1039, // Tahitian
- 1048, // Uighur
- 1055, // Ukrainian
- 1065, // Urdu
- 1070, // Uzbek
- 1076, // Vietnamese
- 1087, // Volapuk
- 1095, // Welsh
- 1101, // Wolof
- 1107, // Xhosa
- 1113, // Yiddish
- 1121, // Yoruba
- 1128, // Zhuang
- 1135, // Zulu
- 1140, // NorwegianNynorsk
- 1157, // Bosnian
- 1165, // Divehi
- 1172, // Manx
- 1177, // Cornish
- 1185, // Akan
- 1190, // Konkani
- 1198, // Ga
- 1201, // Igbo
- 1206, // Kamba
- 1212, // Syriac
- 1219, // Blin
- 1224, // Geez
- 1229, // Koro
- 1234, // Sidamo
- 1241, // Atsam
- 1247, // Tigre
- 1253, // Jju
- 1257, // Friulian
- 1266, // Venda
- 1272, // Ewe
- 1276, // Walamo
- 1283, // Hawaiian
- 1292, // Tyap
- 1297, // Nyanja
- 1304, // Filipino
- 1313, // Swiss German
- 1326, // Sichuan Yi
- 1337, // Kpelle
- 1344, // Low German
- 1355, // South Ndebele
- 1369, // Northern Sotho
- 1384, // Northern Sami
- 1398, // Taroko
- 1405, // Gusii
- 1411, // Taita
- 1417, // Fulah
- 1423, // Kikuyu
- 1430, // Samburu
- 1438, // Sena
- 1443, // North Ndebele
- 1457, // Rombo
- 1463, // Tachelhit
- 1473, // Kabyle
- 1480, // Nyankole
- 1489, // Bena
- 1494, // Vunjo
- 1500, // Bambara
- 1508, // Embu
- 1513, // Cherokee
- 1522, // Morisyen
- 1531, // Makonde
- 1539, // Langi
- 1545, // Ganda
- 1551, // Bemba
- 1557, // Kabuverdianu
- 1570, // Meru
- 1575, // Kalenjin
- 1584, // Nama
- 1589, // Machame
- 1597, // Colognian
- 1607, // Masai
- 1613, // Soga
- 1618, // Luyia
- 1624, // Asu
- 1628, // Teso
- 1633, // Saho
- 1638, // Koyra Chiini
- 1651, // Rwa
- 1655, // Luo
- 1659, // Chiga
- 1665, // Central Morocco Tamazight
- 1691, // Koyraboro Senni
- 1707, // Shambala
- 1716, // Bodo
- 1721, // Avaric
- 1728, // Chamorro
- 1737, // Chechen
- 1745, // Church
- 1752, // Chuvash
- 1760, // Cree
- 1765, // Haitian
- 1773, // Herero
- 1780, // Hiri Motu
- 1790, // Kanuri
- 1797, // Komi
- 1802, // Kongo
- 1808, // Kwanyama
- 1817, // Limburgish
- 1828, // LubaKatanga
- 1840, // Luxembourgish
- 1854, // Navaho
- 1861, // Ndonga
- 1868, // Ojibwa
- 1875, // Pali
- 1880, // Walloon
- 1888, // Aghem
- 1894, // Basaa
- 1900, // Zarma
- 1906, // Duala
- 1912, // JolaFonyi
- 1922, // Ewondo
- 1929, // Bafia
- 1935, // MakhuwaMeetto
- 1949, // Mundang
- 1957, // Kwasio
- 1964, // Nuer
- 1969, // Sakha
- 1975, // Sangu
- 1981, // Congo Swahili
- 1995, // Tasawaq
- 2003, // Vai
- 2007, // Walser
- 2014, // Yangben
- 2022, // Avestan
- 2030, // Asturian
- 2039, // Ngomba
- 2046, // Kako
- 2051, // Meta
- 2056, // Ngiemboon
- 2066, // Aragonese
- 2076, // Akkadian
- 2085, // AncientEgyptian
- 2101, // AncientGreek
- 2114, // Aramaic
- 2122, // Balinese
- 2131, // Bamun
- 2137, // BatakToba
- 2147, // Buginese
- 2156, // Buhid
- 2162, // Carian
- 2169, // Chakma
- 2176, // ClassicalMandaic
- 2193, // Coptic
- 2200, // Dogri
- 2206, // EasternCham
- 2218, // EasternKayah
- 2231, // Etruscan
- 2240, // Gothic
- 2247, // Hanunoo
- 2255, // Ingush
- 2262, // LargeFloweryMiao
- 2279, // Lepcha
- 2286, // Limbu
- 2292, // Lisu
- 2297, // Lu
- 2300, // Lycian
- 2307, // Lydian
- 2314, // Mandingo
- 2323, // Manipuri
- 2332, // Meroitic
- 2341, // NorthernThai
- 2354, // OldIrish
- 2363, // OldNorse
- 2372, // OldPersian
- 2383, // OldTurkish
- 2394, // Pahlavi
- 2402, // Parthian
- 2411, // Phoenician
- 2422, // PrakritLanguage
- 2438, // Rejang
- 2445, // Sabaean
- 2453, // Samaritan
- 2463, // Santali
- 2471, // Saurashtra
- 2482, // Sora
- 2487, // Sylheti
- 2495, // Tagbanwa
- 2504, // TaiDam
- 2511, // TaiNua
- 2518, // Ugaritic
- 2527, // Akoose
- 2534, // Lakota
- 2541, // Standard Moroccan Tamazight
- 2569, // Mapuche
- 2577, // Central Kurdish
- 2593, // LowerSorbian
- 2606, // UpperSorbian
- 2619, // Kenyang
- 2627, // Mohawk
- 2634, // Nko
- 2638, // Prussian
- 2647, // Kiche
- 2653, // Southern Sami
- 2667, // Lule Sami
- 2677, // Inari Sami
- 2688, // Skolt Sami
- 2699, // Warlpiri
- 2708, // Manichaean Middle Persian
- 2734, // Mende
- 2740, // Ancient North Arabian
- 2762, // Linear A
- 2771, // Hmong Njua
- 2782, // Ho
- 2785, // Lezghian
- 2794, // Bassa
- 2800, // Mono
- 2805, // Tedim Chin
- 2816, // Maithili
- 2825, // Ahom
- 2830, // American Sign Language
- 2853, // Ardhamagadhi Prakrit
- 2874, // Bhojpuri
- 2883, // Hieroglyphic Luwian
- 2903, // Literary Chinese
- 2920, // Mazanderani
- 2932, // Mru
- 2936, // Newari
- 2943, // Northern Luri
- 2957, // Palauan
- 2965, // Papiamento
- 2976, // Saraiki
- 2984, // Tokelau
- 2992, // Tok Pisin
- 3002, // Tuvalu
- 3009, // UncodedLanguages
- 3026, // Cantonese
- 3036, // Osage
- 3042, // Tangut
+ 703, // Norwegian Bokmal
+ 720, // Occitan
+ 728, // Oriya
+ 734, // Pashto
+ 741, // Persian
+ 749, // Polish
+ 756, // Portuguese
+ 767, // Punjabi
+ 775, // Quechua
+ 783, // Romansh
+ 791, // Romanian
+ 800, // Russian
+ 808, // Samoan
+ 815, // Sango
+ 821, // Sanskrit
+ 830, // Serbian
+ 838, // Ossetic
+ 846, // Southern Sotho
+ 861, // Tswana
+ 868, // Shona
+ 874, // Sindhi
+ 881, // Sinhala
+ 889, // Swati
+ 895, // Slovak
+ 902, // Slovenian
+ 912, // Somali
+ 919, // Spanish
+ 927, // Sundanese
+ 937, // Swahili
+ 945, // Swedish
+ 953, // Sardinian
+ 963, // Tajik
+ 969, // Tamil
+ 975, // Tatar
+ 981, // Telugu
+ 988, // Thai
+ 993, // Tibetan
+ 1001, // Tigrinya
+ 1010, // Tongan
+ 1017, // Tsonga
+ 1024, // Turkish
+ 1032, // Turkmen
+ 1040, // Tahitian
+ 1049, // Uighur
+ 1056, // Ukrainian
+ 1066, // Urdu
+ 1071, // Uzbek
+ 1077, // Vietnamese
+ 1088, // Volapuk
+ 1096, // Welsh
+ 1102, // Wolof
+ 1108, // Xhosa
+ 1114, // Yiddish
+ 1122, // Yoruba
+ 1129, // Zhuang
+ 1136, // Zulu
+ 1141, // Norwegian Nynorsk
+ 1159, // Bosnian
+ 1167, // Divehi
+ 1174, // Manx
+ 1179, // Cornish
+ 1187, // Akan
+ 1192, // Konkani
+ 1200, // Ga
+ 1203, // Igbo
+ 1208, // Kamba
+ 1214, // Syriac
+ 1221, // Blin
+ 1226, // Geez
+ 1231, // Koro
+ 1236, // Sidamo
+ 1243, // Atsam
+ 1249, // Tigre
+ 1255, // Jju
+ 1259, // Friulian
+ 1268, // Venda
+ 1274, // Ewe
+ 1278, // Walamo
+ 1285, // Hawaiian
+ 1294, // Tyap
+ 1299, // Nyanja
+ 1306, // Filipino
+ 1315, // Swiss German
+ 1328, // Sichuan Yi
+ 1339, // Kpelle
+ 1346, // Low German
+ 1357, // South Ndebele
+ 1371, // Northern Sotho
+ 1386, // Northern Sami
+ 1400, // Taroko
+ 1407, // Gusii
+ 1413, // Taita
+ 1419, // Fulah
+ 1425, // Kikuyu
+ 1432, // Samburu
+ 1440, // Sena
+ 1445, // North Ndebele
+ 1459, // Rombo
+ 1465, // Tachelhit
+ 1475, // Kabyle
+ 1482, // Nyankole
+ 1491, // Bena
+ 1496, // Vunjo
+ 1502, // Bambara
+ 1510, // Embu
+ 1515, // Cherokee
+ 1524, // Morisyen
+ 1533, // Makonde
+ 1541, // Langi
+ 1547, // Ganda
+ 1553, // Bemba
+ 1559, // Kabuverdianu
+ 1572, // Meru
+ 1577, // Kalenjin
+ 1586, // Nama
+ 1591, // Machame
+ 1599, // Colognian
+ 1609, // Masai
+ 1615, // Soga
+ 1620, // Luyia
+ 1626, // Asu
+ 1630, // Teso
+ 1635, // Saho
+ 1640, // Koyra Chiini
+ 1653, // Rwa
+ 1657, // Luo
+ 1661, // Chiga
+ 1667, // Central Morocco Tamazight
+ 1693, // Koyraboro Senni
+ 1709, // Shambala
+ 1718, // Bodo
+ 1723, // Avaric
+ 1730, // Chamorro
+ 1739, // Chechen
+ 1747, // Church
+ 1754, // Chuvash
+ 1762, // Cree
+ 1767, // Haitian
+ 1775, // Herero
+ 1782, // Hiri Motu
+ 1792, // Kanuri
+ 1799, // Komi
+ 1804, // Kongo
+ 1810, // Kwanyama
+ 1819, // Limburgish
+ 1830, // Luba Katanga
+ 1843, // Luxembourgish
+ 1857, // Navaho
+ 1864, // Ndonga
+ 1871, // Ojibwa
+ 1878, // Pali
+ 1883, // Walloon
+ 1891, // Aghem
+ 1897, // Basaa
+ 1903, // Zarma
+ 1909, // Duala
+ 1915, // Jola Fonyi
+ 1926, // Ewondo
+ 1933, // Bafia
+ 1939, // Makhuwa Meetto
+ 1954, // Mundang
+ 1962, // Kwasio
+ 1969, // Nuer
+ 1974, // Sakha
+ 1980, // Sangu
+ 1986, // Congo Swahili
+ 2000, // Tasawaq
+ 2008, // Vai
+ 2012, // Walser
+ 2019, // Yangben
+ 2027, // Avestan
+ 2035, // Asturian
+ 2044, // Ngomba
+ 2051, // Kako
+ 2056, // Meta
+ 2061, // Ngiemboon
+ 2071, // Aragonese
+ 2081, // Akkadian
+ 2090, // Ancient Egyptian
+ 2107, // Ancient Greek
+ 2121, // Aramaic
+ 2129, // Balinese
+ 2138, // Bamun
+ 2144, // Batak Toba
+ 2155, // Buginese
+ 2164, // Buhid
+ 2170, // Carian
+ 2177, // Chakma
+ 2184, // Classical Mandaic
+ 2202, // Coptic
+ 2209, // Dogri
+ 2215, // Eastern Cham
+ 2228, // Eastern Kayah
+ 2242, // Etruscan
+ 2251, // Gothic
+ 2258, // Hanunoo
+ 2266, // Ingush
+ 2273, // Large Flowery Miao
+ 2292, // Lepcha
+ 2299, // Limbu
+ 2305, // Lisu
+ 2310, // Lu
+ 2313, // Lycian
+ 2320, // Lydian
+ 2327, // Mandingo
+ 2336, // Manipuri
+ 2345, // Meroitic
+ 2354, // Northern Thai
+ 2368, // Old Irish
+ 2378, // Old Norse
+ 2388, // Old Persian
+ 2400, // Old Turkish
+ 2412, // Pahlavi
+ 2420, // Parthian
+ 2429, // Phoenician
+ 2440, // Prakrit Language
+ 2457, // Rejang
+ 2464, // Sabaean
+ 2472, // Samaritan
+ 2482, // Santali
+ 2490, // Saurashtra
+ 2501, // Sora
+ 2506, // Sylheti
+ 2514, // Tagbanwa
+ 2523, // Tai Dam
+ 2531, // Tai Nua
+ 2539, // Ugaritic
+ 2548, // Akoose
+ 2555, // Lakota
+ 2562, // Standard Moroccan Tamazight
+ 2590, // Mapuche
+ 2598, // Central Kurdish
+ 2614, // Lower Sorbian
+ 2628, // Upper Sorbian
+ 2642, // Kenyang
+ 2650, // Mohawk
+ 2657, // Nko
+ 2661, // Prussian
+ 2670, // Kiche
+ 2676, // Southern Sami
+ 2690, // Lule Sami
+ 2700, // Inari Sami
+ 2711, // Skolt Sami
+ 2722, // Warlpiri
+ 2731, // Manichaean Middle Persian
+ 2757, // Mende
+ 2763, // Ancient North Arabian
+ 2785, // Linear A
+ 2794, // Hmong Njua
+ 2805, // Ho
+ 2808, // Lezghian
+ 2817, // Bassa
+ 2823, // Mono
+ 2828, // Tedim Chin
+ 2839, // Maithili
+ 2848, // Ahom
+ 2853, // American Sign Language
+ 2876, // Ardhamagadhi Prakrit
+ 2897, // Bhojpuri
+ 2906, // Hieroglyphic Luwian
+ 2926, // Literary Chinese
+ 2943, // Mazanderani
+ 2955, // Mru
+ 2959, // Newari
+ 2966, // Northern Luri
+ 2980, // Palauan
+ 2988, // Papiamento
+ 2999, // Saraiki
+ 3007, // Tokelau
+ 3015, // Tok Pisin
+ 3025, // Tuvalu
+ 3032, // Uncoded Languages
+ 3050, // Cantonese
+ 3060, // Osage
+ 3066, // Tangut
};
static const char script_name_list[] =
@@ -6902,7 +7183,7 @@ static const char script_name_list[] =
"Brahmi\0"
"Buginese\0"
"Buhid\0"
-"CanadianAboriginal\0"
+"Canadian Aboriginal\0"
"Carian\0"
"Chakma\0"
"Cham\0"
@@ -6991,7 +7272,7 @@ static const char script_name_list[] =
"Hatran\0"
"Multani\0"
"Old Hungarian\0"
-"SignWriting\0"
+"Sign Writing\0"
"Adlam\0"
"Bhaiksuki\0"
"Marchen\0"
@@ -7047,104 +7328,104 @@ static const quint16 script_name_index[] = {
325, // Brahmi
332, // Buginese
341, // Buhid
- 347, // CanadianAboriginal
- 366, // Carian
- 373, // Chakma
- 380, // Cham
- 385, // Coptic
- 392, // Cypriot
- 400, // Egyptian Hieroglyphs
- 421, // Fraser
- 428, // Glagolitic
- 439, // Gothic
- 446, // Han
- 450, // Hangul
- 457, // Hanunoo
- 465, // Imperial Aramaic
- 482, // Inscriptional Pahlavi
- 504, // Inscriptional Parthian
- 527, // Javanese
- 536, // Kaithi
- 543, // Katakana
- 552, // Kayah Li
- 561, // Kharoshthi
- 572, // Lanna
- 578, // Lepcha
- 585, // Limbu
- 591, // Linear B
- 600, // Lycian
- 607, // Lydian
- 614, // Mandaean
- 623, // Meitei Mayek
- 636, // Meroitic
- 645, // Meroitic Cursive
- 662, // Nko
- 666, // New Tai Lue
- 678, // Ogham
- 684, // Ol Chiki
- 693, // Old Italic
- 704, // Old Persian
- 716, // Old South Arabian
- 734, // Orkhon
- 741, // Osmanya
- 749, // Phags Pa
- 758, // Phoenician
- 769, // Pollard Phonetic
- 786, // Rejang
- 793, // Runic
- 799, // Samaritan
- 809, // Saurashtra
- 820, // Sharada
- 828, // Shavian
- 836, // Sora Sompeng
- 849, // Cuneiform
- 859, // Sundanese
- 869, // Syloti Nagri
- 882, // Tagalog
- 890, // Tagbanwa
- 899, // Tai Le
- 906, // Tai Viet
- 915, // Takri
- 921, // Ugaritic
- 930, // Braille
- 938, // Hiragana
- 947, // Caucasian Albanian
- 966, // Bassa Vah
- 976, // Duployan
- 985, // Elbasan
- 993, // Grantha
- 1001, // Pahawh Hmong
- 1014, // Khojki
- 1021, // Linear A
- 1030, // Mahajani
- 1039, // Manichaean
- 1050, // Mende Kikakui
- 1064, // Modi
- 1069, // Mro
- 1073, // Old North Arabian
- 1091, // Nabataean
- 1101, // Palmyrene
- 1111, // Pau Cin Hau
- 1123, // Old Permic
- 1134, // Psalter Pahlavi
- 1150, // Siddham
- 1158, // Khudawadi
- 1168, // Tirhuta
- 1176, // Varang Kshiti
- 1190, // Ahom
- 1195, // Anatolian Hieroglyphs
- 1217, // Hatran
- 1224, // Multani
- 1232, // Old Hungarian
- 1246, // SignWriting
- 1258, // Adlam
- 1264, // Bhaiksuki
- 1274, // Marchen
- 1282, // Newa
- 1287, // Osage
- 1293, // Tangut
- 1300, // Han with Bopomofo
- 1318, // Jamo
+ 347, // Canadian Aboriginal
+ 367, // Carian
+ 374, // Chakma
+ 381, // Cham
+ 386, // Coptic
+ 393, // Cypriot
+ 401, // Egyptian Hieroglyphs
+ 422, // Fraser
+ 429, // Glagolitic
+ 440, // Gothic
+ 447, // Han
+ 451, // Hangul
+ 458, // Hanunoo
+ 466, // Imperial Aramaic
+ 483, // Inscriptional Pahlavi
+ 505, // Inscriptional Parthian
+ 528, // Javanese
+ 537, // Kaithi
+ 544, // Katakana
+ 553, // Kayah Li
+ 562, // Kharoshthi
+ 573, // Lanna
+ 579, // Lepcha
+ 586, // Limbu
+ 592, // Linear B
+ 601, // Lycian
+ 608, // Lydian
+ 615, // Mandaean
+ 624, // Meitei Mayek
+ 637, // Meroitic
+ 646, // Meroitic Cursive
+ 663, // Nko
+ 667, // New Tai Lue
+ 679, // Ogham
+ 685, // Ol Chiki
+ 694, // Old Italic
+ 705, // Old Persian
+ 717, // Old South Arabian
+ 735, // Orkhon
+ 742, // Osmanya
+ 750, // Phags Pa
+ 759, // Phoenician
+ 770, // Pollard Phonetic
+ 787, // Rejang
+ 794, // Runic
+ 800, // Samaritan
+ 810, // Saurashtra
+ 821, // Sharada
+ 829, // Shavian
+ 837, // Sora Sompeng
+ 850, // Cuneiform
+ 860, // Sundanese
+ 870, // Syloti Nagri
+ 883, // Tagalog
+ 891, // Tagbanwa
+ 900, // Tai Le
+ 907, // Tai Viet
+ 916, // Takri
+ 922, // Ugaritic
+ 931, // Braille
+ 939, // Hiragana
+ 948, // Caucasian Albanian
+ 967, // Bassa Vah
+ 977, // Duployan
+ 986, // Elbasan
+ 994, // Grantha
+ 1002, // Pahawh Hmong
+ 1015, // Khojki
+ 1022, // Linear A
+ 1031, // Mahajani
+ 1040, // Manichaean
+ 1051, // Mende Kikakui
+ 1065, // Modi
+ 1070, // Mro
+ 1074, // Old North Arabian
+ 1092, // Nabataean
+ 1102, // Palmyrene
+ 1112, // Pau Cin Hau
+ 1124, // Old Permic
+ 1135, // Psalter Pahlavi
+ 1151, // Siddham
+ 1159, // Khudawadi
+ 1169, // Tirhuta
+ 1177, // Varang Kshiti
+ 1191, // Ahom
+ 1196, // Anatolian Hieroglyphs
+ 1218, // Hatran
+ 1225, // Multani
+ 1233, // Old Hungarian
+ 1247, // Sign Writing
+ 1260, // Adlam
+ 1266, // Bhaiksuki
+ 1276, // Marchen
+ 1284, // Newa
+ 1289, // Osage
+ 1295, // Tangut
+ 1302, // Han with Bopomofo
+ 1320, // Jamo
};
static const char country_name_list[] =
@@ -7152,12 +7433,12 @@ static const char country_name_list[] =
"Afghanistan\0"
"Albania\0"
"Algeria\0"
-"AmericanSamoa\0"
+"American Samoa\0"
"Andorra\0"
"Angola\0"
"Anguilla\0"
"Antarctica\0"
-"AntiguaAndBarbuda\0"
+"Antigua And Barbuda\0"
"Argentina\0"
"Armenia\0"
"Aruba\0"
@@ -7175,58 +7456,58 @@ static const char country_name_list[] =
"Bermuda\0"
"Bhutan\0"
"Bolivia\0"
-"BosniaAndHerzegowina\0"
+"Bosnia And Herzegowina\0"
"Botswana\0"
-"BouvetIsland\0"
+"Bouvet Island\0"
"Brazil\0"
-"BritishIndianOceanTerritory\0"
+"British Indian Ocean Territory\0"
"Brunei\0"
"Bulgaria\0"
-"BurkinaFaso\0"
+"Burkina Faso\0"
"Burundi\0"
"Cambodia\0"
"Cameroon\0"
"Canada\0"
-"CapeVerde\0"
-"CaymanIslands\0"
-"CentralAfricanRepublic\0"
+"Cape Verde\0"
+"Cayman Islands\0"
+"Central African Republic\0"
"Chad\0"
"Chile\0"
"China\0"
-"ChristmasIsland\0"
-"CocosIslands\0"
+"Christmas Island\0"
+"Cocos Islands\0"
"Colombia\0"
"Comoros\0"
-"CongoKinshasa\0"
-"CongoBrazzaville\0"
-"CookIslands\0"
-"CostaRica\0"
-"IvoryCoast\0"
+"Congo Kinshasa\0"
+"Congo Brazzaville\0"
+"Cook Islands\0"
+"Costa Rica\0"
+"Ivory Coast\0"
"Croatia\0"
"Cuba\0"
"Cyprus\0"
-"CzechRepublic\0"
+"Czech Republic\0"
"Denmark\0"
"Djibouti\0"
"Dominica\0"
-"DominicanRepublic\0"
-"EastTimor\0"
+"Dominican Republic\0"
+"East Timor\0"
"Ecuador\0"
"Egypt\0"
-"ElSalvador\0"
-"EquatorialGuinea\0"
+"El Salvador\0"
+"Equatorial Guinea\0"
"Eritrea\0"
"Estonia\0"
"Ethiopia\0"
-"FalklandIslands\0"
-"FaroeIslands\0"
+"Falkland Islands\0"
+"Faroe Islands\0"
"Fiji\0"
"Finland\0"
"France\0"
"Guernsey\0"
-"FrenchGuiana\0"
-"FrenchPolynesia\0"
-"FrenchSouthernTerritories\0"
+"French Guiana\0"
+"French Polynesia\0"
+"French Southern Territories\0"
"Gabon\0"
"Gambia\0"
"Georgia\0"
@@ -7240,12 +7521,12 @@ static const char country_name_list[] =
"Guam\0"
"Guatemala\0"
"Guinea\0"
-"GuineaBissau\0"
+"Guinea Bissau\0"
"Guyana\0"
"Haiti\0"
-"HeardAndMcDonaldIslands\0"
+"Heard And McDonald Islands\0"
"Honduras\0"
-"HongKong\0"
+"Hong Kong\0"
"Hungary\0"
"Iceland\0"
"India\0"
@@ -7261,8 +7542,8 @@ static const char country_name_list[] =
"Kazakhstan\0"
"Kenya\0"
"Kiribati\0"
-"NorthKorea\0"
-"SouthKorea\0"
+"North Korea\0"
+"South Korea\0"
"Kuwait\0"
"Kyrgyzstan\0"
"Laos\0"
@@ -7282,7 +7563,7 @@ static const char country_name_list[] =
"Maldives\0"
"Mali\0"
"Malta\0"
-"MarshallIslands\0"
+"Marshall Islands\0"
"Martinique\0"
"Mauritania\0"
"Mauritius\0"
@@ -7300,58 +7581,58 @@ static const char country_name_list[] =
"Nauru\0"
"Nepal\0"
"Netherlands\0"
-"CuraSao\0"
-"NewCaledonia\0"
-"NewZealand\0"
+"Cura Sao\0"
+"New Caledonia\0"
+"New Zealand\0"
"Nicaragua\0"
"Niger\0"
"Nigeria\0"
"Niue\0"
-"NorfolkIsland\0"
-"NorthernMarianaIslands\0"
+"Norfolk Island\0"
+"Northern Mariana Islands\0"
"Norway\0"
"Oman\0"
"Pakistan\0"
"Palau\0"
-"PalestinianTerritories\0"
+"Palestinian Territories\0"
"Panama\0"
-"PapuaNewGuinea\0"
+"Papua New Guinea\0"
"Paraguay\0"
"Peru\0"
"Philippines\0"
"Pitcairn\0"
"Poland\0"
"Portugal\0"
-"PuertoRico\0"
+"Puerto Rico\0"
"Qatar\0"
"Reunion\0"
"Romania\0"
"Russia\0"
"Rwanda\0"
-"SaintKittsAndNevis\0"
-"SaintLucia\0"
-"SaintVincentAndTheGrenadines\0"
+"Saint Kitts And Nevis\0"
+"Saint Lucia\0"
+"Saint Vincent And The Grenadines\0"
"Samoa\0"
-"SanMarino\0"
-"SaoTomeAndPrincipe\0"
-"SaudiArabia\0"
+"San Marino\0"
+"Sao Tome And Principe\0"
+"Saudi Arabia\0"
"Senegal\0"
"Seychelles\0"
-"SierraLeone\0"
+"Sierra Leone\0"
"Singapore\0"
"Slovakia\0"
"Slovenia\0"
-"SolomonIslands\0"
+"Solomon Islands\0"
"Somalia\0"
-"SouthAfrica\0"
-"SouthGeorgiaAndTheSouthSandwichIslands\0"
+"South Africa\0"
+"South Georgia And The South Sandwich Islands\0"
"Spain\0"
-"SriLanka\0"
-"SaintHelena\0"
-"SaintPierreAndMiquelon\0"
+"Sri Lanka\0"
+"Saint Helena\0"
+"Saint Pierre And Miquelon\0"
"Sudan\0"
"Suriname\0"
-"SvalbardAndJanMayenIslands\0"
+"Svalbard And Jan Mayen Islands\0"
"Swaziland\0"
"Sweden\0"
"Switzerland\0"
@@ -7363,51 +7644,53 @@ static const char country_name_list[] =
"Togo\0"
"Tokelau\0"
"Tonga\0"
-"TrinidadAndTobago\0"
+"Trinidad And Tobago\0"
"Tunisia\0"
"Turkey\0"
"Turkmenistan\0"
-"TurksAndCaicosIslands\0"
+"Turks And Caicos Islands\0"
"Tuvalu\0"
"Uganda\0"
"Ukraine\0"
-"UnitedArabEmirates\0"
-"UnitedKingdom\0"
-"UnitedStates\0"
-"UnitedStatesMinorOutlyingIslands\0"
+"United Arab Emirates\0"
+"United Kingdom\0"
+"United States\0"
+"United States Minor Outlying Islands\0"
"Uruguay\0"
"Uzbekistan\0"
"Vanuatu\0"
-"VaticanCityState\0"
+"Vatican City State\0"
"Venezuela\0"
"Vietnam\0"
-"BritishVirginIslands\0"
-"UnitedStatesVirginIslands\0"
-"WallisAndFutunaIslands\0"
-"WesternSahara\0"
+"British Virgin Islands\0"
+"United States Virgin Islands\0"
+"Wallis And Futuna Islands\0"
+"Western Sahara\0"
"Yemen\0"
-"CanaryIslands\0"
+"Canary Islands\0"
"Zambia\0"
"Zimbabwe\0"
-"ClippertonIsland\0"
+"Clipperton Island\0"
"Montenegro\0"
"Serbia\0"
"Saint Barthelemy\0"
"Saint Martin\0"
-"LatinAmericaAndTheCaribbean\0"
-"AscensionIsland\0"
-"AlandIslands\0"
-"DiegoGarcia\0"
-"CeutaAndMelilla\0"
-"IsleOfMan\0"
+"Latin America\0"
+"Ascension Island\0"
+"Aland Islands\0"
+"Diego Garcia\0"
+"Ceuta And Melilla\0"
+"Isle Of Man\0"
"Jersey\0"
-"TristanDaCunha\0"
-"SouthSudan\0"
+"Tristan Da Cunha\0"
+"South Sudan\0"
"Bonaire\0"
-"SintMaarten\0"
+"Sint Maarten\0"
"Kosovo\0"
"European Union\0"
"Outlying Oceania\0"
+"World\0"
+"Europe\0"
;
static const quint16 country_name_index[] = {
@@ -7415,262 +7698,264 @@ static const quint16 country_name_index[] = {
8, // Afghanistan
20, // Albania
28, // Algeria
- 36, // AmericanSamoa
- 50, // Andorra
- 58, // Angola
- 65, // Anguilla
- 74, // Antarctica
- 85, // AntiguaAndBarbuda
- 103, // Argentina
- 113, // Armenia
- 121, // Aruba
- 127, // Australia
- 137, // Austria
- 145, // Azerbaijan
- 156, // Bahamas
- 164, // Bahrain
- 172, // Bangladesh
- 183, // Barbados
- 192, // Belarus
- 200, // Belgium
- 208, // Belize
- 215, // Benin
- 221, // Bermuda
- 229, // Bhutan
- 236, // Bolivia
- 244, // BosniaAndHerzegowina
- 265, // Botswana
- 274, // BouvetIsland
- 287, // Brazil
- 294, // BritishIndianOceanTerritory
- 322, // Brunei
- 329, // Bulgaria
- 338, // BurkinaFaso
- 350, // Burundi
- 358, // Cambodia
- 367, // Cameroon
- 376, // Canada
- 383, // CapeVerde
- 393, // CaymanIslands
- 407, // CentralAfricanRepublic
- 430, // Chad
- 435, // Chile
- 441, // China
- 447, // ChristmasIsland
- 463, // CocosIslands
- 476, // Colombia
- 485, // Comoros
- 493, // CongoKinshasa
- 507, // CongoBrazzaville
- 524, // CookIslands
- 536, // CostaRica
- 546, // IvoryCoast
- 557, // Croatia
- 565, // Cuba
- 570, // Cyprus
- 577, // CzechRepublic
- 591, // Denmark
- 599, // Djibouti
- 608, // Dominica
- 617, // DominicanRepublic
- 635, // EastTimor
- 645, // Ecuador
- 653, // Egypt
- 659, // ElSalvador
- 670, // EquatorialGuinea
- 687, // Eritrea
- 695, // Estonia
- 703, // Ethiopia
- 712, // FalklandIslands
- 728, // FaroeIslands
- 741, // Fiji
- 746, // Finland
- 754, // France
- 761, // Guernsey
- 770, // FrenchGuiana
- 783, // FrenchPolynesia
- 799, // FrenchSouthernTerritories
- 825, // Gabon
- 831, // Gambia
- 838, // Georgia
- 846, // Germany
- 854, // Ghana
- 860, // Gibraltar
- 870, // Greece
- 877, // Greenland
- 887, // Grenada
- 895, // Guadeloupe
- 906, // Guam
- 911, // Guatemala
- 921, // Guinea
- 928, // GuineaBissau
- 941, // Guyana
- 948, // Haiti
- 954, // HeardAndMcDonaldIslands
- 978, // Honduras
- 987, // HongKong
- 996, // Hungary
- 1004, // Iceland
- 1012, // India
- 1018, // Indonesia
- 1028, // Iran
- 1033, // Iraq
- 1038, // Ireland
- 1046, // Israel
- 1053, // Italy
- 1059, // Jamaica
- 1067, // Japan
- 1073, // Jordan
- 1080, // Kazakhstan
- 1091, // Kenya
- 1097, // Kiribati
- 1106, // NorthKorea
- 1117, // SouthKorea
- 1128, // Kuwait
- 1135, // Kyrgyzstan
- 1146, // Laos
- 1151, // Latvia
- 1158, // Lebanon
- 1166, // Lesotho
- 1174, // Liberia
- 1182, // Libya
- 1188, // Liechtenstein
- 1202, // Lithuania
- 1212, // Luxembourg
- 1223, // Macau
- 1229, // Macedonia
- 1239, // Madagascar
- 1250, // Malawi
- 1257, // Malaysia
- 1266, // Maldives
- 1275, // Mali
- 1280, // Malta
- 1286, // MarshallIslands
- 1302, // Martinique
- 1313, // Mauritania
- 1324, // Mauritius
- 1334, // Mayotte
- 1342, // Mexico
- 1349, // Micronesia
- 1360, // Moldova
- 1368, // Monaco
- 1375, // Mongolia
- 1384, // Montserrat
- 1395, // Morocco
- 1403, // Mozambique
- 1414, // Myanmar
- 1422, // Namibia
- 1430, // Nauru
- 1436, // Nepal
- 1442, // Netherlands
- 1454, // CuraSao
- 1462, // NewCaledonia
- 1475, // NewZealand
- 1486, // Nicaragua
- 1496, // Niger
- 1502, // Nigeria
- 1510, // Niue
- 1515, // NorfolkIsland
- 1529, // NorthernMarianaIslands
- 1552, // Norway
- 1559, // Oman
- 1564, // Pakistan
- 1573, // Palau
- 1579, // PalestinianTerritories
- 1602, // Panama
- 1609, // PapuaNewGuinea
- 1624, // Paraguay
- 1633, // Peru
- 1638, // Philippines
- 1650, // Pitcairn
- 1659, // Poland
- 1666, // Portugal
- 1675, // PuertoRico
- 1686, // Qatar
- 1692, // Reunion
- 1700, // Romania
- 1708, // Russia
- 1715, // Rwanda
- 1722, // SaintKittsAndNevis
- 1741, // SaintLucia
- 1752, // SaintVincentAndTheGrenadines
- 1781, // Samoa
- 1787, // SanMarino
- 1797, // SaoTomeAndPrincipe
- 1816, // SaudiArabia
- 1828, // Senegal
- 1836, // Seychelles
- 1847, // SierraLeone
- 1859, // Singapore
- 1869, // Slovakia
- 1878, // Slovenia
- 1887, // SolomonIslands
- 1902, // Somalia
- 1910, // SouthAfrica
- 1922, // SouthGeorgiaAndTheSouthSandwichIslands
- 1961, // Spain
- 1967, // SriLanka
- 1976, // SaintHelena
- 1988, // SaintPierreAndMiquelon
- 2011, // Sudan
- 2017, // Suriname
- 2026, // SvalbardAndJanMayenIslands
- 2053, // Swaziland
- 2063, // Sweden
- 2070, // Switzerland
- 2082, // Syria
- 2088, // Taiwan
- 2095, // Tajikistan
- 2106, // Tanzania
- 2115, // Thailand
- 2124, // Togo
- 2129, // Tokelau
- 2137, // Tonga
- 2143, // TrinidadAndTobago
- 2161, // Tunisia
- 2169, // Turkey
- 2176, // Turkmenistan
- 2189, // TurksAndCaicosIslands
- 2211, // Tuvalu
- 2218, // Uganda
- 2225, // Ukraine
- 2233, // UnitedArabEmirates
- 2252, // UnitedKingdom
- 2266, // UnitedStates
- 2279, // UnitedStatesMinorOutlyingIslands
- 2312, // Uruguay
- 2320, // Uzbekistan
- 2331, // Vanuatu
- 2339, // VaticanCityState
- 2356, // Venezuela
- 2366, // Vietnam
- 2374, // BritishVirginIslands
- 2395, // UnitedStatesVirginIslands
- 2421, // WallisAndFutunaIslands
- 2444, // WesternSahara
- 2458, // Yemen
- 2464, // CanaryIslands
- 2478, // Zambia
- 2485, // Zimbabwe
- 2494, // ClippertonIsland
- 2511, // Montenegro
- 2522, // Serbia
- 2529, // Saint Barthelemy
- 2546, // Saint Martin
- 2559, // LatinAmericaAndTheCaribbean
- 2587, // AscensionIsland
- 2603, // AlandIslands
- 2616, // DiegoGarcia
- 2628, // CeutaAndMelilla
- 2644, // IsleOfMan
- 2654, // Jersey
- 2661, // TristanDaCunha
- 2676, // SouthSudan
- 2687, // Bonaire
- 2695, // SintMaarten
- 2707, // Kosovo
- 2714, // European Union
- 2729, // Outlying Oceania
+ 36, // American Samoa
+ 51, // Andorra
+ 59, // Angola
+ 66, // Anguilla
+ 75, // Antarctica
+ 86, // Antigua And Barbuda
+ 106, // Argentina
+ 116, // Armenia
+ 124, // Aruba
+ 130, // Australia
+ 140, // Austria
+ 148, // Azerbaijan
+ 159, // Bahamas
+ 167, // Bahrain
+ 175, // Bangladesh
+ 186, // Barbados
+ 195, // Belarus
+ 203, // Belgium
+ 211, // Belize
+ 218, // Benin
+ 224, // Bermuda
+ 232, // Bhutan
+ 239, // Bolivia
+ 247, // Bosnia And Herzegowina
+ 270, // Botswana
+ 279, // Bouvet Island
+ 293, // Brazil
+ 300, // British Indian Ocean Territory
+ 331, // Brunei
+ 338, // Bulgaria
+ 347, // Burkina Faso
+ 360, // Burundi
+ 368, // Cambodia
+ 377, // Cameroon
+ 386, // Canada
+ 393, // Cape Verde
+ 404, // Cayman Islands
+ 419, // Central African Republic
+ 444, // Chad
+ 449, // Chile
+ 455, // China
+ 461, // Christmas Island
+ 478, // Cocos Islands
+ 492, // Colombia
+ 501, // Comoros
+ 509, // Congo Kinshasa
+ 524, // Congo Brazzaville
+ 542, // Cook Islands
+ 555, // Costa Rica
+ 566, // Ivory Coast
+ 578, // Croatia
+ 586, // Cuba
+ 591, // Cyprus
+ 598, // Czech Republic
+ 613, // Denmark
+ 621, // Djibouti
+ 630, // Dominica
+ 639, // Dominican Republic
+ 658, // East Timor
+ 669, // Ecuador
+ 677, // Egypt
+ 683, // El Salvador
+ 695, // Equatorial Guinea
+ 713, // Eritrea
+ 721, // Estonia
+ 729, // Ethiopia
+ 738, // Falkland Islands
+ 755, // Faroe Islands
+ 769, // Fiji
+ 774, // Finland
+ 782, // France
+ 789, // Guernsey
+ 798, // French Guiana
+ 812, // French Polynesia
+ 829, // French Southern Territories
+ 857, // Gabon
+ 863, // Gambia
+ 870, // Georgia
+ 878, // Germany
+ 886, // Ghana
+ 892, // Gibraltar
+ 902, // Greece
+ 909, // Greenland
+ 919, // Grenada
+ 927, // Guadeloupe
+ 938, // Guam
+ 943, // Guatemala
+ 953, // Guinea
+ 960, // Guinea Bissau
+ 974, // Guyana
+ 981, // Haiti
+ 987, // Heard And McDonald Islands
+ 1014, // Honduras
+ 1023, // Hong Kong
+ 1033, // Hungary
+ 1041, // Iceland
+ 1049, // India
+ 1055, // Indonesia
+ 1065, // Iran
+ 1070, // Iraq
+ 1075, // Ireland
+ 1083, // Israel
+ 1090, // Italy
+ 1096, // Jamaica
+ 1104, // Japan
+ 1110, // Jordan
+ 1117, // Kazakhstan
+ 1128, // Kenya
+ 1134, // Kiribati
+ 1143, // North Korea
+ 1155, // South Korea
+ 1167, // Kuwait
+ 1174, // Kyrgyzstan
+ 1185, // Laos
+ 1190, // Latvia
+ 1197, // Lebanon
+ 1205, // Lesotho
+ 1213, // Liberia
+ 1221, // Libya
+ 1227, // Liechtenstein
+ 1241, // Lithuania
+ 1251, // Luxembourg
+ 1262, // Macau
+ 1268, // Macedonia
+ 1278, // Madagascar
+ 1289, // Malawi
+ 1296, // Malaysia
+ 1305, // Maldives
+ 1314, // Mali
+ 1319, // Malta
+ 1325, // Marshall Islands
+ 1342, // Martinique
+ 1353, // Mauritania
+ 1364, // Mauritius
+ 1374, // Mayotte
+ 1382, // Mexico
+ 1389, // Micronesia
+ 1400, // Moldova
+ 1408, // Monaco
+ 1415, // Mongolia
+ 1424, // Montserrat
+ 1435, // Morocco
+ 1443, // Mozambique
+ 1454, // Myanmar
+ 1462, // Namibia
+ 1470, // Nauru
+ 1476, // Nepal
+ 1482, // Netherlands
+ 1494, // Cura Sao
+ 1503, // New Caledonia
+ 1517, // New Zealand
+ 1529, // Nicaragua
+ 1539, // Niger
+ 1545, // Nigeria
+ 1553, // Niue
+ 1558, // Norfolk Island
+ 1573, // Northern Mariana Islands
+ 1598, // Norway
+ 1605, // Oman
+ 1610, // Pakistan
+ 1619, // Palau
+ 1625, // Palestinian Territories
+ 1649, // Panama
+ 1656, // Papua New Guinea
+ 1673, // Paraguay
+ 1682, // Peru
+ 1687, // Philippines
+ 1699, // Pitcairn
+ 1708, // Poland
+ 1715, // Portugal
+ 1724, // Puerto Rico
+ 1736, // Qatar
+ 1742, // Reunion
+ 1750, // Romania
+ 1758, // Russia
+ 1765, // Rwanda
+ 1772, // Saint Kitts And Nevis
+ 1794, // Saint Lucia
+ 1806, // Saint Vincent And The Grenadines
+ 1839, // Samoa
+ 1845, // San Marino
+ 1856, // Sao Tome And Principe
+ 1878, // Saudi Arabia
+ 1891, // Senegal
+ 1899, // Seychelles
+ 1910, // Sierra Leone
+ 1923, // Singapore
+ 1933, // Slovakia
+ 1942, // Slovenia
+ 1951, // Solomon Islands
+ 1967, // Somalia
+ 1975, // South Africa
+ 1988, // South Georgia And The South Sandwich Islands
+ 2033, // Spain
+ 2039, // Sri Lanka
+ 2049, // Saint Helena
+ 2062, // Saint Pierre And Miquelon
+ 2088, // Sudan
+ 2094, // Suriname
+ 2103, // Svalbard And Jan Mayen Islands
+ 2134, // Swaziland
+ 2144, // Sweden
+ 2151, // Switzerland
+ 2163, // Syria
+ 2169, // Taiwan
+ 2176, // Tajikistan
+ 2187, // Tanzania
+ 2196, // Thailand
+ 2205, // Togo
+ 2210, // Tokelau
+ 2218, // Tonga
+ 2224, // Trinidad And Tobago
+ 2244, // Tunisia
+ 2252, // Turkey
+ 2259, // Turkmenistan
+ 2272, // Turks And Caicos Islands
+ 2297, // Tuvalu
+ 2304, // Uganda
+ 2311, // Ukraine
+ 2319, // United Arab Emirates
+ 2340, // United Kingdom
+ 2355, // United States
+ 2369, // United States Minor Outlying Islands
+ 2406, // Uruguay
+ 2414, // Uzbekistan
+ 2425, // Vanuatu
+ 2433, // Vatican City State
+ 2452, // Venezuela
+ 2462, // Vietnam
+ 2470, // British Virgin Islands
+ 2493, // United States Virgin Islands
+ 2522, // Wallis And Futuna Islands
+ 2548, // Western Sahara
+ 2563, // Yemen
+ 2569, // Canary Islands
+ 2584, // Zambia
+ 2591, // Zimbabwe
+ 2600, // Clipperton Island
+ 2618, // Montenegro
+ 2629, // Serbia
+ 2636, // Saint Barthelemy
+ 2653, // Saint Martin
+ 2666, // Latin America
+ 2680, // Ascension Island
+ 2697, // Aland Islands
+ 2711, // Diego Garcia
+ 2724, // Ceuta And Melilla
+ 2742, // Isle Of Man
+ 2754, // Jersey
+ 2761, // Tristan Da Cunha
+ 2778, // South Sudan
+ 2790, // Bonaire
+ 2798, // Sint Maarten
+ 2811, // Kosovo
+ 2818, // European Union
+ 2833, // Outlying Oceania
+ 2850, // World
+ 2856, // Europe
};
static const unsigned char language_code_list[] =
@@ -7759,7 +8044,7 @@ static const unsigned char language_code_list[] =
"mn\0" // Mongolian
"na\0" // Nauru
"ne\0" // Nepali
-"nb\0" // NorwegianBokmal
+"nb\0" // Norwegian Bokmal
"oc\0" // Occitan
"or\0" // Oriya
"ps\0" // Pashto
@@ -7815,7 +8100,7 @@ static const unsigned char language_code_list[] =
"yo\0" // Yoruba
"za\0" // Zhuang
"zu\0" // Zulu
-"nn\0" // NorwegianNynorsk
+"nn\0" // Norwegian Nynorsk
"bs\0" // Bosnian
"dv\0" // Divehi
"gv\0" // Manx
@@ -7904,7 +8189,7 @@ static const unsigned char language_code_list[] =
"kg\0" // Kongo
"kj\0" // Kwanyama
"li\0" // Limburgish
-"lu\0" // LubaKatanga
+"lu\0" // Luba Katanga
"lb\0" // Luxembourgish
"nv\0" // Navaho
"ng\0" // Ndonga
@@ -7915,10 +8200,10 @@ static const unsigned char language_code_list[] =
"bas" // Basaa
"dje" // Zarma
"dua" // Duala
-"dyo" // JolaFonyi
+"dyo" // Jola Fonyi
"ewo" // Ewondo
"ksf" // Bafia
-"mgh" // MakhuwaMeetto
+"mgh" // Makhuwa Meetto
"mua" // Mundang
"nmg" // Kwasio
"nus" // Nuer
@@ -7937,26 +8222,26 @@ static const unsigned char language_code_list[] =
"nnh" // Ngiemboon
"an\0" // Aragonese
"akk" // Akkadian
-"egy" // AncientEgyptian
-"grc" // AncientGreek
+"egy" // Ancient Egyptian
+"grc" // Ancient Greek
"arc" // Aramaic
"ban" // Balinese
"bax" // Bamun
-"bbc" // BatakToba
+"bbc" // Batak Toba
"bug" // Buginese
"bku" // Buhid
"xcr" // Carian
"ccp" // Chakma
-"myz" // ClassicalMandaic
+"myz" // Classical Mandaic
"cop" // Coptic
"doi" // Dogri
-"cjm" // EasternCham
-"eky" // EasternKayah
+"cjm" // Eastern Cham
+"eky" // Eastern Kayah
"ett" // Etruscan
"got" // Gothic
"hnn" // Hanunoo
"inh" // Ingush
-"hmd" // LargeFloweryMiao
+"hmd" // Large Flowery Miao
"lep" // Lepcha
"lif" // Limbu
"lis" // Lisu
@@ -7966,15 +8251,15 @@ static const unsigned char language_code_list[] =
"man" // Mandingo
"mni" // Manipuri
"xmr" // Meroitic
-"nod" // NorthernThai
-"sga" // OldIrish
-"non" // OldNorse
-"peo" // OldPersian
-"otk" // OldTurkish
+"nod" // Northern Thai
+"sga" // Old Irish
+"non" // Old Norse
+"peo" // Old Persian
+"otk" // Old Turkish
"pal" // Pahlavi
"xpr" // Parthian
"phn" // Phoenician
-"pra" // PrakritLanguage
+"pra" // Prakrit Language
"rej" // Rejang
"xsa" // Sabaean
"smp" // Samaritan
@@ -7983,16 +8268,16 @@ static const unsigned char language_code_list[] =
"srb" // Sora
"syl" // Sylheti
"tbw" // Tagbanwa
-"blt" // TaiDam
-"tdd" // TaiNua
+"blt" // Tai Dam
+"tdd" // Tai Nua
"uga" // Ugaritic
"bss" // Akoose
"lkt" // Lakota
"zgh" // Standard Moroccan Tamazight
"arn" // Mapuche
"ckb" // Central Kurdish
-"dsb" // LowerSorbian
-"hsb" // UpperSorbian
+"dsb" // Lower Sorbian
+"hsb" // Upper Sorbian
"ken" // Kenyang
"moh" // Mohawk
"nqo" // Nko
@@ -8030,7 +8315,7 @@ static const unsigned char language_code_list[] =
"tkl" // Tokelau
"tpi" // Tok Pisin
"tvl" // Tuvalu
-"mis" // UncodedLanguages
+"mis" // Uncoded Languages
"yue" // Cantonese
"osa" // Osage
"txg" // Tangut
@@ -8081,7 +8366,7 @@ static const unsigned char script_code_list[] =
"Brah" // Brahmi
"Bugi" // Buginese
"Buhd" // Buhid
-"Cans" // CanadianAboriginal
+"Cans" // Canadian Aboriginal
"Cari" // Carian
"Cakm" // Chakma
"Cham" // Cham
@@ -8170,7 +8455,7 @@ static const unsigned char script_code_list[] =
"Hatr" // Hatran
"Mult" // Multani
"Hung" // Old Hungarian
-"Sgnw" // SignWriting
+"Sgnw" // Sign Writing
"Adlm" // Adlam
"Bhks" // Bhaiksuki
"Marc" // Marchen
@@ -8185,12 +8470,12 @@ static const unsigned char country_code_list[] =
"AF\0" // Afghanistan
"AL\0" // Albania
"DZ\0" // Algeria
-"AS\0" // AmericanSamoa
+"AS\0" // American Samoa
"AD\0" // Andorra
"AO\0" // Angola
"AI\0" // Anguilla
"AQ\0" // Antarctica
-"AG\0" // AntiguaAndBarbuda
+"AG\0" // Antigua And Barbuda
"AR\0" // Argentina
"AM\0" // Armenia
"AW\0" // Aruba
@@ -8208,58 +8493,58 @@ static const unsigned char country_code_list[] =
"BM\0" // Bermuda
"BT\0" // Bhutan
"BO\0" // Bolivia
-"BA\0" // BosniaAndHerzegowina
+"BA\0" // Bosnia And Herzegowina
"BW\0" // Botswana
-"BV\0" // BouvetIsland
+"BV\0" // Bouvet Island
"BR\0" // Brazil
-"IO\0" // BritishIndianOceanTerritory
+"IO\0" // British Indian Ocean Territory
"BN\0" // Brunei
"BG\0" // Bulgaria
-"BF\0" // BurkinaFaso
+"BF\0" // Burkina Faso
"BI\0" // Burundi
"KH\0" // Cambodia
"CM\0" // Cameroon
"CA\0" // Canada
-"CV\0" // CapeVerde
-"KY\0" // CaymanIslands
-"CF\0" // CentralAfricanRepublic
+"CV\0" // Cape Verde
+"KY\0" // Cayman Islands
+"CF\0" // Central African Republic
"TD\0" // Chad
"CL\0" // Chile
"CN\0" // China
-"CX\0" // ChristmasIsland
-"CC\0" // CocosIslands
+"CX\0" // Christmas Island
+"CC\0" // Cocos Islands
"CO\0" // Colombia
"KM\0" // Comoros
-"CD\0" // CongoKinshasa
-"CG\0" // CongoBrazzaville
-"CK\0" // CookIslands
-"CR\0" // CostaRica
-"CI\0" // IvoryCoast
+"CD\0" // Congo Kinshasa
+"CG\0" // Congo Brazzaville
+"CK\0" // Cook Islands
+"CR\0" // Costa Rica
+"CI\0" // Ivory Coast
"HR\0" // Croatia
"CU\0" // Cuba
"CY\0" // Cyprus
-"CZ\0" // CzechRepublic
+"CZ\0" // Czech Republic
"DK\0" // Denmark
"DJ\0" // Djibouti
"DM\0" // Dominica
-"DO\0" // DominicanRepublic
-"TL\0" // EastTimor
+"DO\0" // Dominican Republic
+"TL\0" // East Timor
"EC\0" // Ecuador
"EG\0" // Egypt
-"SV\0" // ElSalvador
-"GQ\0" // EquatorialGuinea
+"SV\0" // El Salvador
+"GQ\0" // Equatorial Guinea
"ER\0" // Eritrea
"EE\0" // Estonia
"ET\0" // Ethiopia
-"FK\0" // FalklandIslands
-"FO\0" // FaroeIslands
+"FK\0" // Falkland Islands
+"FO\0" // Faroe Islands
"FJ\0" // Fiji
"FI\0" // Finland
"FR\0" // France
"GG\0" // Guernsey
-"GF\0" // FrenchGuiana
-"PF\0" // FrenchPolynesia
-"TF\0" // FrenchSouthernTerritories
+"GF\0" // French Guiana
+"PF\0" // French Polynesia
+"TF\0" // French Southern Territories
"GA\0" // Gabon
"GM\0" // Gambia
"GE\0" // Georgia
@@ -8273,12 +8558,12 @@ static const unsigned char country_code_list[] =
"GU\0" // Guam
"GT\0" // Guatemala
"GN\0" // Guinea
-"GW\0" // GuineaBissau
+"GW\0" // Guinea Bissau
"GY\0" // Guyana
"HT\0" // Haiti
-"HM\0" // HeardAndMcDonaldIslands
+"HM\0" // Heard And McDonald Islands
"HN\0" // Honduras
-"HK\0" // HongKong
+"HK\0" // Hong Kong
"HU\0" // Hungary
"IS\0" // Iceland
"IN\0" // India
@@ -8294,8 +8579,8 @@ static const unsigned char country_code_list[] =
"KZ\0" // Kazakhstan
"KE\0" // Kenya
"KI\0" // Kiribati
-"KP\0" // NorthKorea
-"KR\0" // SouthKorea
+"KP\0" // North Korea
+"KR\0" // South Korea
"KW\0" // Kuwait
"KG\0" // Kyrgyzstan
"LA\0" // Laos
@@ -8315,7 +8600,7 @@ static const unsigned char country_code_list[] =
"MV\0" // Maldives
"ML\0" // Mali
"MT\0" // Malta
-"MH\0" // MarshallIslands
+"MH\0" // Marshall Islands
"MQ\0" // Martinique
"MR\0" // Mauritania
"MU\0" // Mauritius
@@ -8333,58 +8618,58 @@ static const unsigned char country_code_list[] =
"NR\0" // Nauru
"NP\0" // Nepal
"NL\0" // Netherlands
-"CW\0" // CuraSao
-"NC\0" // NewCaledonia
-"NZ\0" // NewZealand
+"CW\0" // Cura Sao
+"NC\0" // New Caledonia
+"NZ\0" // New Zealand
"NI\0" // Nicaragua
"NE\0" // Niger
"NG\0" // Nigeria
"NU\0" // Niue
-"NF\0" // NorfolkIsland
-"MP\0" // NorthernMarianaIslands
+"NF\0" // Norfolk Island
+"MP\0" // Northern Mariana Islands
"NO\0" // Norway
"OM\0" // Oman
"PK\0" // Pakistan
"PW\0" // Palau
-"PS\0" // PalestinianTerritories
+"PS\0" // Palestinian Territories
"PA\0" // Panama
-"PG\0" // PapuaNewGuinea
+"PG\0" // Papua New Guinea
"PY\0" // Paraguay
"PE\0" // Peru
"PH\0" // Philippines
"PN\0" // Pitcairn
"PL\0" // Poland
"PT\0" // Portugal
-"PR\0" // PuertoRico
+"PR\0" // Puerto Rico
"QA\0" // Qatar
"RE\0" // Reunion
"RO\0" // Romania
"RU\0" // Russia
"RW\0" // Rwanda
-"KN\0" // SaintKittsAndNevis
-"LC\0" // SaintLucia
-"VC\0" // SaintVincentAndTheGrenadines
+"KN\0" // Saint Kitts And Nevis
+"LC\0" // Saint Lucia
+"VC\0" // Saint Vincent And The Grenadines
"WS\0" // Samoa
-"SM\0" // SanMarino
-"ST\0" // SaoTomeAndPrincipe
-"SA\0" // SaudiArabia
+"SM\0" // San Marino
+"ST\0" // Sao Tome And Principe
+"SA\0" // Saudi Arabia
"SN\0" // Senegal
"SC\0" // Seychelles
-"SL\0" // SierraLeone
+"SL\0" // Sierra Leone
"SG\0" // Singapore
"SK\0" // Slovakia
"SI\0" // Slovenia
-"SB\0" // SolomonIslands
+"SB\0" // Solomon Islands
"SO\0" // Somalia
-"ZA\0" // SouthAfrica
-"GS\0" // SouthGeorgiaAndTheSouthSandwichIslands
+"ZA\0" // South Africa
+"GS\0" // South Georgia And The South Sandwich Islands
"ES\0" // Spain
-"LK\0" // SriLanka
-"SH\0" // SaintHelena
-"PM\0" // SaintPierreAndMiquelon
+"LK\0" // Sri Lanka
+"SH\0" // Saint Helena
+"PM\0" // Saint Pierre And Miquelon
"SD\0" // Sudan
"SR\0" // Suriname
-"SJ\0" // SvalbardAndJanMayenIslands
+"SJ\0" // Svalbard And Jan Mayen Islands
"SZ\0" // Swaziland
"SE\0" // Sweden
"CH\0" // Switzerland
@@ -8396,51 +8681,53 @@ static const unsigned char country_code_list[] =
"TG\0" // Togo
"TK\0" // Tokelau
"TO\0" // Tonga
-"TT\0" // TrinidadAndTobago
+"TT\0" // Trinidad And Tobago
"TN\0" // Tunisia
"TR\0" // Turkey
"TM\0" // Turkmenistan
-"TC\0" // TurksAndCaicosIslands
+"TC\0" // Turks And Caicos Islands
"TV\0" // Tuvalu
"UG\0" // Uganda
"UA\0" // Ukraine
-"AE\0" // UnitedArabEmirates
-"GB\0" // UnitedKingdom
-"US\0" // UnitedStates
-"UM\0" // UnitedStatesMinorOutlyingIslands
+"AE\0" // United Arab Emirates
+"GB\0" // United Kingdom
+"US\0" // United States
+"UM\0" // United States Minor Outlying Islands
"UY\0" // Uruguay
"UZ\0" // Uzbekistan
"VU\0" // Vanuatu
-"VA\0" // VaticanCityState
+"VA\0" // Vatican City State
"VE\0" // Venezuela
"VN\0" // Vietnam
-"VG\0" // BritishVirginIslands
-"VI\0" // UnitedStatesVirginIslands
-"WF\0" // WallisAndFutunaIslands
-"EH\0" // WesternSahara
+"VG\0" // British Virgin Islands
+"VI\0" // United States Virgin Islands
+"WF\0" // Wallis And Futuna Islands
+"EH\0" // Western Sahara
"YE\0" // Yemen
-"IC\0" // CanaryIslands
+"IC\0" // Canary Islands
"ZM\0" // Zambia
"ZW\0" // Zimbabwe
-"CP\0" // ClippertonIsland
+"CP\0" // Clipperton Island
"ME\0" // Montenegro
"RS\0" // Serbia
"BL\0" // Saint Barthelemy
"MF\0" // Saint Martin
-"419" // LatinAmericaAndTheCaribbean
-"AC\0" // AscensionIsland
-"AX\0" // AlandIslands
-"DG\0" // DiegoGarcia
-"EA\0" // CeutaAndMelilla
-"IM\0" // IsleOfMan
+"419" // Latin America
+"AC\0" // Ascension Island
+"AX\0" // Aland Islands
+"DG\0" // Diego Garcia
+"EA\0" // Ceuta And Melilla
+"IM\0" // Isle Of Man
"JE\0" // Jersey
-"TA\0" // TristanDaCunha
-"SS\0" // SouthSudan
+"TA\0" // Tristan Da Cunha
+"SS\0" // South Sudan
"BQ\0" // Bonaire
-"SX\0" // SintMaarten
+"SX\0" // Sint Maarten
"XK\0" // Kosovo
"EU\0" // European Union
"QO\0" // Outlying Oceania
+"001" // World
+"150" // Europe
;
// GENERATED PART ENDS HERE
diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h
index 6669ae7c8b..a9c23aed61 100644
--- a/src/corelib/tools/qlocale_p.h
+++ b/src/corelib/tools/qlocale_p.h
@@ -274,6 +274,7 @@ public:
public:
quint16 m_language_id, m_script_id, m_country_id;
+ // FIXME QTBUG-69324: not all unicode code-points map to single-token UTF-16 :-(
quint16 m_decimal, m_group, m_list, m_percent, m_zero, m_minus, m_plus, m_exponential;
quint16 m_quotation_start, m_quotation_end;
quint16 m_alternate_quotation_start, m_alternate_quotation_end;
@@ -407,9 +408,10 @@ inline char QLocaleData::digitToCLocale(QChar in) const
if (in == m_exponential || in == QChar::toUpper(m_exponential))
return 'e';
- // In several languages group() is the char 0xA0, which looks like a space.
- // People use a regular space instead of it and complain it doesn't work.
- if (m_group == 0xA0 && in.unicode() == ' ')
+ // In several languages group() is a non-breaking space (U+00A0) or its thin
+ // version (U+202f), which look like spaces. People (and thus some of our
+ // tests) use a regular space instead and complain if it doesn't work.
+ if ((m_group == 0xA0 || m_group == 0x202f) && in.unicode() == ' ')
return ',';
return 0;
diff --git a/src/corelib/tools/qlocale_tools.cpp b/src/corelib/tools/qlocale_tools.cpp
index 4d969a4723..bde52a20b9 100644
--- a/src/corelib/tools/qlocale_tools.cpp
+++ b/src/corelib/tools/qlocale_tools.cpp
@@ -75,8 +75,8 @@ QT_BEGIN_NAMESPACE
QT_CLOCALE_HOLDER
-void doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, char *buf, int bufSize,
- bool &sign, int &length, int &decpt)
+void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, char *buf, int bufSize,
+ bool &sign, int &length, int &decpt)
{
if (bufSize == 0) {
decpt = 0;
@@ -277,8 +277,8 @@ void doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, char *
--length;
}
-double asciiToDouble(const char *num, int numLen, bool &ok, int &processed,
- TrailingJunkMode trailingJunkMode)
+double qt_asciiToDouble(const char *num, int numLen, bool &ok, int &processed,
+ StrayCharacterMode strayCharMode)
{
if (*num == '\0') {
ok = false;
@@ -315,9 +315,13 @@ double asciiToDouble(const char *num, int numLen, bool &ok, int &processed,
double d = 0.0;
#if !defined(QT_NO_DOUBLECONVERSION) && !defined(QT_BOOTSTRAPPED)
- int conv_flags = (trailingJunkMode == TrailingJunkAllowed) ?
- double_conversion::StringToDoubleConverter::ALLOW_TRAILING_JUNK :
- double_conversion::StringToDoubleConverter::NO_FLAGS;
+ int conv_flags = double_conversion::StringToDoubleConverter::NO_FLAGS;
+ if (strayCharMode == TrailingJunkAllowed) {
+ conv_flags = double_conversion::StringToDoubleConverter::ALLOW_TRAILING_JUNK;
+ } else if (strayCharMode == WhitespacesAllowed) {
+ conv_flags = double_conversion::StringToDoubleConverter::ALLOW_LEADING_SPACES
+ | double_conversion::StringToDoubleConverter::ALLOW_TRAILING_SPACES;
+ }
double_conversion::StringToDoubleConverter conv(conv_flags, 0.0, qt_snan(), 0, 0);
d = conv.StringToDouble(num, numLen, &processed);
@@ -336,7 +340,7 @@ double asciiToDouble(const char *num, int numLen, bool &ok, int &processed,
if (qDoubleSscanf(num, QT_CLOCALE, "%lf%n", &d, &processed) < 1)
processed = 0;
- if ((trailingJunkMode == TrailingJunkProhibited && processed != numLen) || qIsNaN(d)) {
+ if ((strayCharMode == TrailingJunkProhibited && processed != numLen) || qIsNaN(d)) {
// Implementation defined nan symbol or garbage found. We don't accept it.
processed = 0;
ok = false;
@@ -361,7 +365,7 @@ double asciiToDouble(const char *num, int numLen, bool &ok, int &processed,
#endif // !defined(QT_NO_DOUBLECONVERSION) && !defined(QT_BOOTSTRAPPED)
// Otherwise we would have gotten NaN or sorted it out above.
- Q_ASSERT(trailingJunkMode == TrailingJunkAllowed || processed == numLen);
+ Q_ASSERT(strayCharMode == TrailingJunkAllowed || processed == numLen);
// Check if underflow has occurred.
if (isZero(d)) {
@@ -544,7 +548,7 @@ double qstrntod(const char *s00, int len, const char **se, bool *ok)
{
int processed = 0;
bool nonNullOk = false;
- double d = asciiToDouble(s00, len, nonNullOk, processed, TrailingJunkAllowed);
+ double d = qt_asciiToDouble(s00, len, nonNullOk, processed, TrailingJunkAllowed);
if (se)
*se = s00 + processed;
if (ok)
@@ -560,8 +564,8 @@ QString qdtoa(qreal d, int *decpt, int *sign)
// Some versions of libdouble-conversion like an extra digit, probably for '\0'
char result[QLocaleData::DoubleMaxSignificant + 1];
- doubleToAscii(d, QLocaleData::DFSignificantDigits, QLocale::FloatingPointShortest, result,
- QLocaleData::DoubleMaxSignificant + 1, nonNullSign, length, nonNullDecpt);
+ qt_doubleToAscii(d, QLocaleData::DFSignificantDigits, QLocale::FloatingPointShortest, result,
+ QLocaleData::DoubleMaxSignificant + 1, nonNullSign, length, nonNullDecpt);
if (sign)
*sign = nonNullSign ? 1 : 0;
diff --git a/src/corelib/tools/qlocale_tools_p.h b/src/corelib/tools/qlocale_tools_p.h
index 742abb4957..594331ae37 100644
--- a/src/corelib/tools/qlocale_tools_p.h
+++ b/src/corelib/tools/qlocale_tools_p.h
@@ -72,15 +72,16 @@
QT_BEGIN_NAMESPACE
-enum TrailingJunkMode {
+enum StrayCharacterMode {
TrailingJunkProhibited,
- TrailingJunkAllowed
+ TrailingJunkAllowed,
+ WhitespacesAllowed
};
-double asciiToDouble(const char *num, int numLen, bool &ok, int &processed,
- TrailingJunkMode trailingJunkMode = TrailingJunkProhibited);
-void doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, char *buf, int bufSize,
- bool &sign, int &length, int &decpt);
+double qt_asciiToDouble(const char *num, int numLen, bool &ok, int &processed,
+ StrayCharacterMode strayCharMode = TrailingJunkProhibited);
+void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, char *buf, int bufSize,
+ bool &sign, int &length, int &decpt);
QString qulltoa(qulonglong l, int base, const QChar _zero);
Q_CORE_EXPORT QString qdtoa(qreal d, int *decpt, int *sign);
diff --git a/src/corelib/tools/qlocale_win.cpp b/src/corelib/tools/qlocale_win.cpp
index 30aefb71c1..ebc4430046 100644
--- a/src/corelib/tools/qlocale_win.cpp
+++ b/src/corelib/tools/qlocale_win.cpp
@@ -274,7 +274,7 @@ QSystemLocalePrivate::SubstitutionType QSystemLocalePrivate::substitution()
QString &QSystemLocalePrivate::substituteDigits(QString &string)
{
ushort zero = zeroDigit().unicode();
- ushort *qch = (ushort *)string.data();
+ ushort *qch = reinterpret_cast<ushort *>(string.data());
for (ushort *end = qch + string.size(); qch != end; ++qch) {
if (*qch >= '0' && *qch <= '9')
*qch = zero + (*qch - '0');
@@ -365,7 +365,7 @@ QVariant QSystemLocalePrivate::dayName(int day, QLocale::FormatType type)
if (type == QLocale::LongFormat)
return getLocaleInfo(long_day_map[day]);
- else if (type == QLocale::NarrowFormat)
+ if (type == QLocale::NarrowFormat)
return getLocaleInfo(narrow_day_map[day]);
return getLocaleInfo(short_day_map[day]);
}
@@ -386,7 +386,7 @@ QVariant QSystemLocalePrivate::monthName(int month, QLocale::FormatType type)
month -= 1;
if (month < 0 || month > 11)
- return QString();
+ return QString();
LCTYPE lctype = (type == QLocale::ShortFormat || type == QLocale::NarrowFormat)
? short_month_map[month] : long_month_map[month];
@@ -988,7 +988,7 @@ LCID qt_inIsoNametoLCID(const char *name)
// handle norwegian manually, the list above will fail
if (!strncmp(name, "nb", 2))
return 0x0414;
- else if (!strncmp(name, "nn", 2))
+ if (!strncmp(name, "nn", 2))
return 0x0814;
char n[64];
@@ -1001,9 +1001,9 @@ LCID qt_inIsoNametoLCID(const char *name)
++c;
}
- for (int i = 0; i < windows_to_iso_count; ++i) {
- if (!strcmp(n, windows_to_iso_list[i].iso_name))
- return windows_to_iso_list[i].windows_code;
+ for (const WindowsToISOListElt &i : windows_to_iso_list) {
+ if (!strcmp(n, i.iso_name))
+ return i.windows_code;
}
return LOCALE_USER_DEFAULT;
}
@@ -1099,8 +1099,7 @@ static QByteArray getWinLocaleName(LPWSTR id)
id = qstrtoll(result.data(), 0, 0, &ok);
if ( !ok || id == 0 || id < INT_MIN || id > INT_MAX )
return result;
- else
- return winLangCodeToIsoName( (int)id );
+ return winLangCodeToIsoName(int(id));
}
}
diff --git a/src/corelib/tools/qmakearray_p.h b/src/corelib/tools/qmakearray_p.h
new file mode 100644
index 0000000000..ae4d7f07c6
--- /dev/null
+++ b/src/corelib/tools/qmakearray_p.h
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 QMAKEARRAY_P_H
+#define QMAKEARRAY_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtCore/qglobal.h"
+
+#include <array>
+#include <type_traits>
+#include <utility>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtPrivate {
+template<typename T>
+constexpr T&& Forward(typename std::remove_reference<T>::type& t) noexcept
+{
+ return static_cast<T&&>(t);
+}
+
+template<typename T>
+constexpr T&& Forward(typename std::remove_reference<T>::type&& t) noexcept
+{
+ static_assert(!std::is_lvalue_reference<T>::value,
+ "template argument substituting T is an lvalue reference type");
+ return static_cast<T&&>(t);
+}
+
+template <typename ManualType, typename ...>
+struct ArrayTypeHelper
+{
+ using type = ManualType;
+};
+
+template <typename ... Types>
+struct ArrayTypeHelper<void, Types...> : std::common_type<Types...> { };
+
+template <typename ManualType, typename... Types>
+using ArrayType = std::array<typename ArrayTypeHelper<ManualType, Types...>::type,
+ sizeof...(Types)>;
+
+template<typename ... Values>
+struct QuickSortData { };
+
+template <template <typename> class Predicate,
+ typename ... Values>
+struct QuickSortFilter;
+
+template <typename ... Right, typename ... Left>
+constexpr QuickSortData<Right..., Left...> quickSortConcat(
+ QuickSortData<Right...>, QuickSortData<Left...>) noexcept;
+
+template<typename ... Right, typename Middle, typename ... Left>
+constexpr QuickSortData<Right..., Middle, Left...> quickSortConcat(
+ QuickSortData<Right...>,
+ QuickSortData<Middle>,
+ QuickSortData<Left...>) noexcept;
+
+template <template <typename> class Predicate,
+ typename Head, typename ... Tail>
+struct QuickSortFilter<Predicate, QuickSortData<Head, Tail...>>
+{
+ using TailFilteredData = typename QuickSortFilter<
+ Predicate, QuickSortData<Tail...>>::Type;
+
+ using Type = typename QConditional<
+ Predicate<Head>::value,
+ decltype(quickSortConcat(QuickSortData<Head> {}, TailFilteredData{})),
+ TailFilteredData>::Type;
+};
+
+template <template <typename> class Predicate>
+struct QuickSortFilter<Predicate, QuickSortData<>>
+{
+ using Type = QuickSortData<>;
+};
+
+template <typename ... Values>
+struct QuickSort;
+
+template <typename Pivot, typename ... Values>
+struct QuickSort<QuickSortData<Pivot, Values...>>
+{
+ template <typename Left>
+ struct LessThan {
+ static constexpr const bool value = Left::data() <= Pivot::data();
+ };
+
+ template <typename Left>
+ struct MoreThan {
+ static constexpr const bool value = !(Left::data() <= Pivot::data());
+ };
+
+ using LeftSide = typename QuickSortFilter<LessThan, QuickSortData<Values...>>::Type;
+ using RightSide = typename QuickSortFilter<MoreThan, QuickSortData<Values...>>::Type;
+
+ using LeftQS = typename QuickSort<LeftSide>::Type;
+ using RightQS = typename QuickSort<RightSide>::Type;
+
+ using Type = decltype(quickSortConcat(LeftQS{}, QuickSortData<Pivot> {}, RightQS{}));
+
+};
+
+template <>
+struct QuickSort<QuickSortData<>>
+{
+ using Type = QuickSortData<>;
+};
+} // namespace QtPrivate
+
+template <typename ManualType = void, typename ... Types>
+constexpr QtPrivate::ArrayType<ManualType, Types...> qMakeArray(Types && ... t) noexcept
+{
+ return {{QtPrivate::Forward<typename QtPrivate::ArrayType<ManualType, Types...>::value_type>(t)...}};
+}
+
+template<typename ... Values>
+struct QSortedData {
+ using Data = typename QtPrivate::QuickSort<typename QtPrivate::QuickSortData<Values...>>::Type;
+};
+
+template<typename ... Values>
+constexpr auto qMakeArray(QtPrivate::QuickSortData<Values...>) noexcept -> decltype(qMakeArray(Values::data()...))
+{
+ return qMakeArray(Values::data() ...);
+}
+
+
+QT_END_NAMESPACE
+
+#endif // QMAKEARRAY_P_H
diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h
index a5b9096835..1cf9299e26 100644
--- a/src/corelib/tools/qmap.h
+++ b/src/corelib/tools/qmap.h
@@ -449,6 +449,7 @@ public:
inline iterator operator-(int j) const { return operator+(-j); }
inline iterator &operator+=(int j) { return *this = *this + j; }
inline iterator &operator-=(int j) { return *this = *this - j; }
+ friend inline iterator operator+(int j, iterator k) { return k + j; }
#ifndef QT_STRICT_ITERATORS
public:
@@ -512,6 +513,7 @@ public:
inline const_iterator operator-(int j) const { return operator+(-j); }
inline const_iterator &operator+=(int j) { return *this = *this + j; }
inline const_iterator &operator-=(int j) { return *this = *this - j; }
+ friend inline const_iterator operator+(int j, const_iterator k) { return k + j; }
#ifdef QT_STRICT_ITERATORS
private:
diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp
index ad1885e8ce..6e51deebea 100644
--- a/src/corelib/tools/qrect.cpp
+++ b/src/corelib/tools/qrect.cpp
@@ -713,10 +713,7 @@ QRect QRect::normalized() const Q_DECL_NOTHROW
Returns a copy of the rectangle that has its width and height
exchanged:
- \code
- QRect r = {15, 51, 42, 24};
- r = r.transposed(); // r == {15, 51, 24, 42}
- \endcode
+ \snippet code/src_corelib_tools_qrect.cpp 2
\sa QSize::transposed()
*/
@@ -1863,10 +1860,7 @@ QRectF QRectF::normalized() const Q_DECL_NOTHROW
Returns a copy of the rectangle that has its width and height
exchanged:
- \code
- QRectF r = {1.5, 5.1, 4.2, 2.4};
- r = r.transposed(); // r == {1.5, 5.1, 2.4, 4.2}
- \endcode
+ \snippet code/src_corelib_tools_qrect.cpp 3
\sa QSizeF::transposed()
*/
diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp
index 96ddca56af..87b30c952e 100644
--- a/src/corelib/tools/qregexp.cpp
+++ b/src/corelib/tools/qregexp.cpp
@@ -3813,50 +3813,57 @@ struct QRegExpPrivate
};
#if !defined(QT_NO_REGEXP_OPTIM)
-typedef QCache<QRegExpEngineKey, QRegExpEngine> EngineCache;
-Q_GLOBAL_STATIC(EngineCache, globalEngineCache)
-static QBasicMutex globalEngineCacheMutex;
+struct QRECache
+{
+ typedef QHash<QRegExpEngineKey, QRegExpEngine *> EngineCache;
+ typedef QCache<QRegExpEngineKey, QRegExpEngine> UnusedEngineCache;
+ EngineCache usedEngines;
+ UnusedEngineCache unusedEngines;
+};
+Q_GLOBAL_STATIC(QRECache, engineCache)
+static QBasicMutex engineCacheMutex;
#endif // QT_NO_REGEXP_OPTIM
static void derefEngine(QRegExpEngine *eng, const QRegExpEngineKey &key)
{
- if (!eng->ref.deref()) {
#if !defined(QT_NO_REGEXP_OPTIM)
- if (globalEngineCache()) {
- QMutexLocker locker(&globalEngineCacheMutex);
- QT_TRY {
- globalEngineCache()->insert(key, eng, 4 + key.pattern.length() / 4);
- } QT_CATCH(const std::bad_alloc &) {
- // in case of an exception (e.g. oom), just delete the engine
- delete eng;
- }
+ QMutexLocker locker(&engineCacheMutex);
+ if (!eng->ref.deref()) {
+ if (QRECache *c = engineCache()) {
+ c->unusedEngines.insert(key, eng, 4 + key.pattern.length() / 4);
+ c->usedEngines.remove(key);
} else {
delete eng;
}
+ }
#else
- Q_UNUSED(key);
+ Q_UNUSED(key);
+ if (!eng->ref.deref())
delete eng;
#endif
- }
}
static void prepareEngine_helper(QRegExpPrivate *priv)
{
- bool initMatchState = !priv->eng;
+ Q_ASSERT(!priv->eng);
+
#if !defined(QT_NO_REGEXP_OPTIM)
- if (!priv->eng && globalEngineCache()) {
- QMutexLocker locker(&globalEngineCacheMutex);
- priv->eng = globalEngineCache()->take(priv->engineKey);
- if (priv->eng != 0)
+ QMutexLocker locker(&engineCacheMutex);
+ if (QRECache *c = engineCache()) {
+ priv->eng = c->unusedEngines.take(priv->engineKey);
+ if (!priv->eng)
+ priv->eng = c->usedEngines.value(priv->engineKey);
+ if (!priv->eng)
+ priv->eng = new QRegExpEngine(priv->engineKey);
+ else
priv->eng->ref.ref();
+
+ c->usedEngines.insert(priv->engineKey, priv->eng);
+ return;
}
#endif // QT_NO_REGEXP_OPTIM
- if (!priv->eng)
- priv->eng = new QRegExpEngine(priv->engineKey);
-
- if (initMatchState)
- priv->matchState.prepareForMatch(priv->eng);
+ priv->eng = new QRegExpEngine(priv->engineKey);
}
inline static void prepareEngine(QRegExpPrivate *priv)
@@ -3864,6 +3871,7 @@ inline static void prepareEngine(QRegExpPrivate *priv)
if (priv->eng)
return;
prepareEngine_helper(priv);
+ priv->matchState.prepareForMatch(priv->eng);
}
static void prepareEngineForMatch(QRegExpPrivate *priv, const QString &str)
diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp
index 13eff07c04..fec5f620fc 100644
--- a/src/corelib/tools/qregularexpression.cpp
+++ b/src/corelib/tools/qregularexpression.cpp
@@ -43,7 +43,7 @@
#include <QtCore/qcoreapplication.h>
#include <QtCore/qhashfunctions.h>
-#include <QtCore/qreadwritelock.h>
+#include <QtCore/qmutex.h>
#include <QtCore/qvector.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qdebug.h>
@@ -483,6 +483,11 @@ QT_BEGIN_NAMESPACE
Note the usage of the non-capturing group in order to preserve the meaning
of the branch operator inside the pattern.
+ The QRegularExpression::anchoredPattern() helper method does exactly that for
+ you.
+
+ \sa anchoredPattern
+
\section3 Porting from QRegExp's Partial Matching
When using QRegExp::exactMatch(), if an exact match was not found, one
@@ -516,10 +521,10 @@ QT_BEGIN_NAMESPACE
\section2 Wildcard matching
- There is no equivalent of wildcard matching in QRegularExpression.
- Nevertheless, rewriting a regular expression in wildcard syntax to a
- Perl-compatible regular expression is a very easy task, given the fact
- that wildcard syntax supported by QRegExp is very simple.
+ There is no direct way to do wildcard matching in QRegularExpression.
+ However, the wildcardToRegularExpression method is provided to translate
+ glob patterns into a Perl-compatible regular expression that can be used
+ for that purpose.
\section2 Other pattern syntaxes
@@ -720,21 +725,14 @@ QT_BEGIN_NAMESPACE
to the \c{/u} modifier in Perl regular expressions.
\value OptimizeOnFirstUsageOption
- The regular expression will be optimized (and possibly
- JIT-compiled) on its first usage, instead of after a certain (undefined)
- number of usages. See also \l{QRegularExpression::}{optimize()}.
- This enum value has been introduced in Qt 5.4.
+ This option is ignored. A regular expression is automatically optimized
+ (including JIT compiling) the first time it is used. This enum value
+ was introduced in Qt 5.4.
\value DontAutomaticallyOptimizeOption
- Regular expressions are automatically optimized after a
- certain number of usages; setting this option prevents such
- optimizations, therefore avoiding possible unpredictable spikes in
- CPU and memory usage. If both this option and the
- \c{OptimizeOnFirstUsageOption} option are set, then this option takes
- precedence. Note: this option will still let the regular expression
- to be optimized by manually calling
- \l{QRegularExpression::}{optimize()}. This enum value has been
- introduced in Qt 5.4.
+ This option is ignored. A regular expression is automatically optimized
+ (including JIT compiling) the first time it is used. This enum value
+ was introduced in Qt 5.4.
*/
/*!
@@ -791,13 +789,6 @@ QT_BEGIN_NAMESPACE
Qt 5.4.
*/
-// after how many usages we optimize the regexp
-#ifdef QT_BUILD_INTERNAL
-Q_AUTOTEST_EXPORT unsigned int qt_qregularexpression_optimize_after_use_count = 10;
-#else
-static const unsigned int qt_qregularexpression_optimize_after_use_count = 10;
-#endif // QT_BUILD_INTERNAL
-
/*!
\internal
*/
@@ -847,13 +838,7 @@ struct QRegularExpressionPrivate : QSharedData
void cleanCompiledPattern();
void compilePattern();
void getPatternInfo();
-
- enum OptimizePatternOption {
- LazyOptimizeOption,
- ImmediateOptimizeOption
- };
-
- void optimizePattern(OptimizePatternOption option);
+ void optimizePattern();
enum CheckSubjectStringOption {
CheckSubjectString,
@@ -878,16 +863,15 @@ struct QRegularExpressionPrivate : QSharedData
// *All* of the following members are managed while holding this mutex,
// except for isDirty which is set to true by QRegularExpression setters
// (right after a detach happened).
- mutable QReadWriteLock mutex;
+ mutable QMutex mutex;
// The PCRE code pointer is reference-counted by the QRegularExpressionPrivate
// objects themselves; when the private is copied (i.e. a detach happened)
- // they are set to 0
+ // it is set to nullptr
pcre2_code_16 *compiledPattern;
int errorCode;
int errorOffset;
int capturingCount;
- unsigned int usedCount;
bool usingCrLfNewlines;
bool isDirty;
};
@@ -952,11 +936,10 @@ QRegularExpressionPrivate::QRegularExpressionPrivate()
patternOptions(0),
pattern(),
mutex(),
- compiledPattern(0),
+ compiledPattern(nullptr),
errorCode(0),
errorOffset(-1),
capturingCount(0),
- usedCount(0),
usingCrLfNewlines(false),
isDirty(true)
{
@@ -974,8 +957,8 @@ QRegularExpressionPrivate::~QRegularExpressionPrivate()
\internal
Copies the private, which means copying only the pattern and the pattern
- options. The compiledPattern and the studyData pointers are NOT copied (we
- do not own them any more), and in general all the members set when
+ options. The compiledPattern pointer is NOT copied (we
+ do not own it any more), and in general all the members set when
compiling a pattern are set to default values. isDirty is set back to true
so that the pattern has to be recompiled again.
*/
@@ -984,11 +967,10 @@ QRegularExpressionPrivate::QRegularExpressionPrivate(const QRegularExpressionPri
patternOptions(other.patternOptions),
pattern(other.pattern),
mutex(),
- compiledPattern(0),
+ compiledPattern(nullptr),
errorCode(0),
errorOffset(-1),
capturingCount(0),
- usedCount(0),
usingCrLfNewlines(false),
isDirty(true)
{
@@ -1000,11 +982,10 @@ QRegularExpressionPrivate::QRegularExpressionPrivate(const QRegularExpressionPri
void QRegularExpressionPrivate::cleanCompiledPattern()
{
pcre2_code_free_16(compiledPattern);
- compiledPattern = 0;
+ compiledPattern = nullptr;
errorCode = 0;
errorOffset = -1;
capturingCount = 0;
- usedCount = 0;
usingCrLfNewlines = false;
}
@@ -1013,7 +994,7 @@ void QRegularExpressionPrivate::cleanCompiledPattern()
*/
void QRegularExpressionPrivate::compilePattern()
{
- const QWriteLocker lock(&mutex);
+ const QMutexLocker lock(&mutex);
if (!isDirty)
return;
@@ -1040,6 +1021,7 @@ void QRegularExpressionPrivate::compilePattern()
errorCode = 0;
}
+ optimizePattern();
getPatternInfo();
}
@@ -1140,15 +1122,10 @@ static bool isJitEnabled()
The purpose of the function is to call pcre2_jit_compile_16, which
JIT-compiles the pattern.
- It gets called by doMatch() every time a match is performed.
-
- As of now, the optimizations on the pattern are performed after a certain
- number of usages (i.e. the qt_qregularexpression_optimize_after_use_count
- constant) unless the DontAutomaticallyOptimizeOption option is set on the
- QRegularExpression object, or anyhow by calling optimize() (which will pass
- ImmediateOptimizeOption).
+ It gets called when a pattern is recompiled by us (in compilePattern()),
+ under mutex protection.
*/
-void QRegularExpressionPrivate::optimizePattern(OptimizePatternOption option)
+void QRegularExpressionPrivate::optimizePattern()
{
Q_ASSERT(compiledPattern);
@@ -1157,11 +1134,6 @@ void QRegularExpressionPrivate::optimizePattern(OptimizePatternOption option)
if (!enableJit)
return;
- const QWriteLocker lock(&mutex);
-
- if ((option == LazyOptimizeOption) && (++usedCount != qt_qregularexpression_optimize_after_use_count))
- return;
-
pcre2_jit_compile_16(compiledPattern, PCRE2_JIT_COMPLETE | PCRE2_JIT_PARTIAL_SOFT | PCRE2_JIT_PARTIAL_HARD);
}
@@ -1267,22 +1239,12 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString
return priv;
}
- // skip optimizing and doing the actual matching if NoMatch type was requested
+ // skip doing the actual matching if NoMatch type was requested
if (matchType == QRegularExpression::NoMatch) {
priv->isValid = true;
return priv;
}
- if (!(patternOptions & QRegularExpression::DontAutomaticallyOptimizeOption)) {
- const OptimizePatternOption optimizePatternOption =
- (patternOptions & QRegularExpression::OptimizeOnFirstUsageOption)
- ? ImmediateOptimizeOption
- : LazyOptimizeOption;
-
- // this is mutex protected
- const_cast<QRegularExpressionPrivate *>(this)->optimizePattern(optimizePatternOption);
- }
-
int pcreOptions = convertToPcreOptions(matchOptions);
if (matchType == QRegularExpression::PartialPreferCompleteMatch)
@@ -1307,8 +1269,6 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString
int result;
- QReadLocker lock(&mutex);
-
if (!previousMatchWasEmpty) {
result = safe_pcre2_match_16(compiledPattern,
subjectUtf16, subjectLength,
@@ -1340,8 +1300,6 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString
}
}
- lock.unlock();
-
#ifdef QREGULAREXPRESSION_DEBUG
qDebug() << "Matching" << pattern << "against" << subject
<< "starting at" << subjectStart << "len" << subjectLength
@@ -1602,15 +1560,11 @@ int QRegularExpression::captureCount() const
For instance, given the regular expression
- \code
- (?<day>\d\d)-(?<month>\d\d)-(?<year>\d\d\d\d) (\w+) (?<name>\w+)
- \endcode
+ \snippet code/src_corelib_tools_qregularexpression.cpp 32
namedCaptureGroups() will return the following list:
- \code
- ("", "day", "month", "year", "", "name")
- \endcode
+ \snippet code/src_corelib_tools_qregularexpression.cpp 33
which corresponds to the fact that the capturing group #0 (corresponding to
the whole match) has no name, the capturing group #1 has name "day", the
@@ -1810,22 +1764,14 @@ QRegularExpressionMatchIterator QRegularExpression::globalMatch(const QStringRef
/*!
\since 5.4
- Forces an immediate optimization of the pattern, including
- JIT-compiling it (if the JIT compiler is enabled).
-
- Patterns are normally optimized only after a certain number of usages.
- If you can predict that this QRegularExpression object is going to be
- used for several matches, it may be convenient to optimize it in
- advance by calling this function.
+ Compiles the pattern immediately, including JIT compiling it (if
+ the JIT is enabled) for optimization.
- \sa QRegularExpression::OptimizeOnFirstUsageOption
+ \sa isValid(), {Debugging Code that Uses QRegularExpression}
*/
void QRegularExpression::optimize() const
{
- if (!isValid()) // will compile the pattern
- return;
-
- d->optimizePattern(QRegularExpressionPrivate::ImmediateOptimizeOption);
+ d.data()->compilePattern();
}
/*!
@@ -1926,6 +1872,141 @@ QString QRegularExpression::escape(const QString &str)
}
/*!
+ \since 5.12
+
+ Returns a regular expression representation of the given glob \a pattern.
+ The transformation is targeting file path globbing, which means in particular
+ that path separators receive special treatment. This implies that it is not
+ just a basic translation from "*" to ".*".
+
+ \snippet code/src_corelib_tools_qregularexpression.cpp 31
+
+ \warning Unlike QRegExp, this implementation follows closely the definition
+ of wildcard for glob patterns:
+ \table
+ \row \li \b{c}
+ \li Any character represents itself apart from those mentioned
+ below. Thus \b{c} matches the character \e c.
+ \row \li \b{?}
+ \li Matches any single character. It is the same as
+ \b{.} in full regexps.
+ \row \li \b{*}
+ \li Matches zero or more of any characters. It is the
+ same as \b{.*} in full regexps.
+ \row \li \b{[abc]}
+ \li Matches one character given in the bracket.
+ \row \li \b{[a-c]}
+ \li Matches one character from the range given in the bracket.
+ \row \li \b{[!abc]}
+ \li Matches one character that is not given in the bracket. It is the
+ same as \b{[^abc]} in full regexp.
+ \row \li \b{[!a-c]}
+ \li Matches one character that is not from the range given in the
+ bracket. It is the same as \b{[^a-c]} in full regexp.
+ \endtable
+
+ \note The backslash (\\) character is \e not an escape char in this context.
+ In order to match one of the special characters, place it in square brackets
+ (for example, "[?]").
+
+ More information about the implementation can be found in:
+ \list
+ \li \l {https://en.wikipedia.org/wiki/Glob_(programming)} {The Wikipedia Glob article}
+ \li \c man 7 glob
+ \endlist
+
+ \sa escape()
+*/
+QString QRegularExpression::wildcardToRegularExpression(const QString &pattern)
+{
+ const int wclen = pattern.length();
+ QString rx;
+ rx.reserve(wclen + wclen / 16);
+ int i = 0;
+ const QChar *wc = pattern.unicode();
+
+#ifdef Q_OS_WIN
+ const QLatin1Char nativePathSeparator('\\');
+ const QLatin1String starEscape("[^/\\\\]*");
+ const QLatin1String questionMarkEscape("[^/\\\\]");
+#else
+ const QLatin1Char nativePathSeparator('/');
+ const QLatin1String starEscape("[^/]*");
+ const QLatin1String questionMarkEscape("[^/]");
+#endif
+
+ while (i < wclen) {
+ const QChar c = wc[i++];
+ switch (c.unicode()) {
+ case '*':
+ rx += starEscape;
+ break;
+ case '?':
+ rx += questionMarkEscape;
+ break;
+ case '\\':
+#ifdef Q_OS_WIN
+ case '/':
+ rx += QLatin1String("[/\\\\]");
+ break;
+#endif
+ case '$':
+ case '(':
+ case ')':
+ case '+':
+ case '.':
+ case '^':
+ case '{':
+ case '|':
+ case '}':
+ rx += QLatin1Char('\\');
+ rx += c;
+ break;
+ case '[':
+ rx += c;
+ // Support for the [!abc] or [!a-c] syntax
+ if (i < wclen) {
+ if (wc[i] == QLatin1Char('!')) {
+ rx += QLatin1Char('^');
+ ++i;
+ }
+
+ if (i < wclen && wc[i] == QLatin1Char(']'))
+ rx += wc[i++];
+
+ while (i < wclen && wc[i] != QLatin1Char(']')) {
+ // The '/' appearing in a character class invalidates the
+ // regular expression parsing. It also concerns '\\' on
+ // Windows OS types.
+ if (wc[i] == QLatin1Char('/') || wc[i] == nativePathSeparator)
+ return rx;
+ if (wc[i] == QLatin1Char('\\'))
+ rx += QLatin1Char('\\');
+ rx += wc[i++];
+ }
+ }
+ break;
+ default:
+ rx += c;
+ break;
+ }
+ }
+
+ return rx;
+}
+
+/*!
+ \fn QRegularExpression::anchoredPattern(const QString &expression)
+
+ \since 5.12
+
+ Returns the expression wrapped between the \c{\A} and \c{\z} anchors to be
+ used for exact matching.
+
+ \sa {Porting from QRegExp's Exact Matching}
+*/
+
+/*!
\since 5.1
Constructs a valid, empty QRegularExpressionMatch object. The regular
@@ -2657,10 +2738,13 @@ QDebug operator<<(QDebug debug, QRegularExpression::PatternOptions patternOption
flags.append("DontCaptureOption|");
if (patternOptions & QRegularExpression::UseUnicodePropertiesOption)
flags.append("UseUnicodePropertiesOption|");
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
if (patternOptions & QRegularExpression::OptimizeOnFirstUsageOption)
flags.append("OptimizeOnFirstUsageOption|");
if (patternOptions & QRegularExpression::DontAutomaticallyOptimizeOption)
flags.append("DontAutomaticallyOptimizeOption|");
+QT_WARNING_POP
flags.chop(1);
}
diff --git a/src/corelib/tools/qregularexpression.h b/src/corelib/tools/qregularexpression.h
index 398fc9ec9c..f9e7029550 100644
--- a/src/corelib/tools/qregularexpression.h
+++ b/src/corelib/tools/qregularexpression.h
@@ -73,8 +73,8 @@ public:
InvertedGreedinessOption = 0x0010,
DontCaptureOption = 0x0020,
UseUnicodePropertiesOption = 0x0040,
- OptimizeOnFirstUsageOption = 0x0080,
- DontAutomaticallyOptimizeOption = 0x0100
+ OptimizeOnFirstUsageOption Q_DECL_ENUMERATOR_DEPRECATED_X("This option does not have any effect since Qt 5.12") = 0x0080,
+ DontAutomaticallyOptimizeOption Q_DECL_ENUMERATOR_DEPRECATED_X("This option does not have any effect since Qt 5.12") = 0x0100,
};
Q_DECLARE_FLAGS(PatternOptions, PatternOption)
@@ -141,6 +141,13 @@ public:
void optimize() const;
static QString escape(const QString &str);
+ static QString wildcardToRegularExpression(const QString &str);
+ static inline QString anchoredPattern(const QString &expression)
+ {
+ return QLatin1String("\\A(?:")
+ + expression
+ + QLatin1String(")\\z");
+ }
bool operator==(const QRegularExpression &re) const;
inline bool operator!=(const QRegularExpression &re) const { return !operator==(re); }
diff --git a/src/corelib/tools/qringbuffer.cpp b/src/corelib/tools/qringbuffer.cpp
index eb7bdfe95c..59650ed2f7 100644
--- a/src/corelib/tools/qringbuffer.cpp
+++ b/src/corelib/tools/qringbuffer.cpp
@@ -312,12 +312,14 @@ qint64 QRingBuffer::peek(char *data, qint64 maxLength, qint64 pos) const
Q_ASSERT(maxLength >= 0 && pos >= 0);
qint64 readSoFar = 0;
- for (int i = 0; readSoFar < maxLength && i < buffers.size(); ++i) {
- qint64 blockLength = buffers[i].size();
+ for (const QRingChunk &chunk : buffers) {
+ if (readSoFar == maxLength)
+ break;
+ qint64 blockLength = chunk.size();
if (pos < blockLength) {
blockLength = qMin(blockLength - pos, maxLength - readSoFar);
- memcpy(data + readSoFar, buffers[i].data() + pos, blockLength);
+ memcpy(data + readSoFar, chunk.data() + pos, blockLength);
readSoFar += blockLength;
pos = 0;
} else {
diff --git a/src/corelib/tools/qscopeguard.h b/src/corelib/tools/qscopeguard.h
new file mode 100644
index 0000000000..31100fcabb
--- /dev/null
+++ b/src/corelib/tools/qscopeguard.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Sérgio Martins <sergio.martins@kdab.com>
+** Contact: https://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 QSCOPEGUARD_H
+#define QSCOPEGUARD_H
+
+#include <QtCore/qglobal.h>
+
+
+QT_BEGIN_NAMESPACE
+
+
+template <typename F> class QScopeGuard;
+template <typename F> QScopeGuard<F> qScopeGuard(F f);
+
+template <typename F>
+class QScopeGuard
+{
+public:
+ QScopeGuard(QScopeGuard &&other) Q_DECL_NOEXCEPT
+ : m_func(std::move(other.m_func))
+ , m_invoke(other.m_invoke)
+ {
+ other.dismiss();
+ }
+
+ ~QScopeGuard()
+ {
+ if (m_invoke)
+ m_func();
+ }
+
+ void dismiss() Q_DECL_NOEXCEPT
+ {
+ m_invoke = false;
+ }
+
+private:
+ explicit QScopeGuard(F f) Q_DECL_NOEXCEPT
+ : m_func(std::move(f))
+ {
+ }
+
+ Q_DISABLE_COPY(QScopeGuard)
+
+ F m_func;
+ bool m_invoke = true;
+ friend QScopeGuard qScopeGuard<F>(F);
+};
+
+
+template <typename F>
+QScopeGuard<F> qScopeGuard(F f)
+{
+ return QScopeGuard<F>(std::move(f));
+}
+
+QT_END_NAMESPACE
+
+#endif // QSCOPEGUARD_H
diff --git a/src/corelib/tools/qscopeguard.qdoc b/src/corelib/tools/qscopeguard.qdoc
new file mode 100644
index 0000000000..7cbc3e9c7b
--- /dev/null
+++ b/src/corelib/tools/qscopeguard.qdoc
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Sérgio Martins <sergio.martins@kdab.com>
+** 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$
+**
+****************************************************************************/
+
+#include "qscopeguard.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \fn const QScopeGuard<F> qScopeGuard(F f)
+ \inmodule QtCore
+ \brief The qScopeGuard function can be used to call a function at the end of the scope.
+ \since 5.12
+ \ingroup misc
+
+ QScopeGuard<F> is a class which sole purpose is to run a function F in its destructor.
+ This is useful for guaranteeing your cleanup code is executed whether the function is exited normally,
+ exited early by a return statement, or exited by an exception.
+
+ If F is a lambda then you cannot instantiate the template directly, therefore the qScopeGuard() helper
+ is provided and QScopeGuard<F> is made a private implementation detail.
+
+ Example usage is as follows:
+
+ \snippet code/src_corelib_tools_qscopeguard.cpp 0
+
+ \note Exceptions are not supported. The callable shouldn't throw when executed, copied or moved.
+
+ \sa QScopedValueRollback
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h
index 7ded120ab7..6640c8486d 100644
--- a/src/corelib/tools/qset.h
+++ b/src/corelib/tools/qset.h
@@ -131,6 +131,7 @@ public:
inline iterator operator--(int) { iterator r = *this; --i; return r; }
inline iterator operator+(int j) const { return i + j; }
inline iterator operator-(int j) const { return i - j; }
+ friend inline iterator operator+(int j, iterator k) { return k + j; }
inline iterator &operator+=(int j) { i += j; return *this; }
inline iterator &operator-=(int j) { i -= j; return *this; }
};
@@ -165,6 +166,7 @@ public:
inline const_iterator operator--(int) { const_iterator r = *this; --i; return r; }
inline const_iterator operator+(int j) const { return i + j; }
inline const_iterator operator-(int j) const { return i - j; }
+ friend inline const_iterator operator+(int j, const_iterator k) { return k + j; }
inline const_iterator &operator+=(int j) { i += j; return *this; }
inline const_iterator &operator-=(int j) { i -= j; return *this; }
};
diff --git a/src/corelib/tools/qshareddata.cpp b/src/corelib/tools/qshareddata.cpp
index f95d75c4a8..bc4291e20f 100644
--- a/src/corelib/tools/qshareddata.cpp
+++ b/src/corelib/tools/qshareddata.cpp
@@ -142,9 +142,7 @@ QT_BEGIN_NAMESPACE
would just predeclare the private subclass \c EmployeeData in \c
{employee.h} this way:
- \code
- class EmployeeData;
- \endcode
+ \snippet code/src_corelib_tools_qshareddata.cpp 0
If we had done it that way here, the copy constructor shown would be
required. Since the copy constructor is trivial, you might as well
@@ -396,13 +394,7 @@ QT_BEGIN_NAMESPACE
a template-specialization of this function for your own type, like
the example below:
- \code
- template<>
- EmployeeData *QSharedDataPointer<EmployeeData>::clone()
- {
- return d->clone();
- }
- \endcode
+ \snippet code/src_corelib_tools_qshareddata.cpp 1
In the example above, the template specialization for the clone()
function calls the \e {EmployeeData::clone()} virtual function. A
@@ -554,10 +546,7 @@ QT_BEGIN_NAMESPACE
\warning relying on such \c{static_cast} is potentially dangerous,
because it allows code like this to compile:
- \code
- QExplicitlySharedDataPointer<Base> base(new Base);
- QExplicitlySharedDataPointer<Derived> derived(base); // !!! DANGER !!!
- \endcode
+ \snippet code/src_corelib_tools_qshareddata.cpp 2
Starting from Qt 5.4 the cast is disabled by default. It is
possible to enable it back by defining the
diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h
index 780f2331a8..6930cb96a5 100644
--- a/src/corelib/tools/qshareddata.h
+++ b/src/corelib/tools/qshareddata.h
@@ -136,6 +136,18 @@ private:
T *d;
};
+template <class T> inline bool operator==(std::nullptr_t p1, const QSharedDataPointer<T> &p2)
+{
+ Q_UNUSED(p1);
+ return !p2;
+}
+
+template <class T> inline bool operator==(const QSharedDataPointer<T> &p1, std::nullptr_t p2)
+{
+ Q_UNUSED(p2);
+ return !p1;
+}
+
template <class T> class QExplicitlySharedDataPointer
{
public:
@@ -147,6 +159,7 @@ public:
inline T *operator->() const { return d; }
inline T *data() const { return d; }
inline const T *constData() const { return d; }
+ inline T *take() { T *x = d; d = nullptr; return x; }
inline void detach() { if (d && d->ref.load() != 1) detach_helper(); }
@@ -271,6 +284,18 @@ Q_INLINE_TEMPLATE QExplicitlySharedDataPointer<T>::QExplicitlySharedDataPointer(
: d(adata)
{ if (d) d->ref.ref(); }
+template <class T> inline bool operator==(std::nullptr_t p1, const QExplicitlySharedDataPointer<T> &p2)
+{
+ Q_UNUSED(p1);
+ return !p2;
+}
+
+template <class T> inline bool operator==(const QExplicitlySharedDataPointer<T> &p1, std::nullptr_t p2)
+{
+ Q_UNUSED(p2);
+ return !p1;
+}
+
template <class T>
Q_INLINE_TEMPLATE void qSwap(QSharedDataPointer<T> &p1, QSharedDataPointer<T> &p2)
{ p1.swap(p2); }
diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp
index 65616e2abb..622b03f42d 100644
--- a/src/corelib/tools/qsharedpointer.cpp
+++ b/src/corelib/tools/qsharedpointer.cpp
@@ -388,44 +388,14 @@
sharedFromThis() that return a QSharedPointer<T> and
QSharedPointer<const T>, depending on constness, to \c this:
- \code
- class Y: public QEnableSharedFromThis<Y>
- {
- public:
- QSharedPointer<Y> f()
- {
- return sharedFromThis();
- }
- };
-
- int main()
- {
- QSharedPointer<Y> p(new Y());
- QSharedPointer<Y> y = p->f();
- Q_ASSERT(p == y); // p and q must share ownership
- }
- \endcode
+ \snippet code/src_corelib_tools_qsharedpointer.cpp 0
It is also possible to get a shared pointer from an object outside of
the class itself. This is especially useful in code that provides an
interface to scripts, where it is currently not possible to use shared
pointers. For example:
- \code
- class ScriptInterface : public QObject
- {
- Q_OBJECT
-
- // ...
-
- public slots:
- void slotCalledByScript(Y *managedBySharedPointer)
- {
- QSharedPointer<Y> yPtr = managedBySharedPointer->sharedFromThis();
- // Some other code unrelated to scripts that expects a QSharedPointer<Y> ...
- }
- };
- \endcode
+ \snippet code/src_corelib_tools_qsharedpointer.cpp 1
*/
/*!
@@ -466,30 +436,13 @@
when the strong reference count drops to 0. This is useful,
for instance, for calling \l {QObject::}{deleteLater()} on a QObject instead:
- \code
- static void doDeleteLater(MyObject *obj)
- {
- obj->deleteLater();
- }
-
- void otherFunction()
- {
- QSharedPointer<MyObject> obj =
- QSharedPointer<MyObject>(new MyObject, doDeleteLater);
-
- // continue using obj
- obj.clear(); // calls obj->deleteLater();
- }
- \endcode
+ \snippet code/src_corelib_tools_qsharedpointer.cpp 2
Note that the custom deleter function will be called with a pointer to type
\c X, even if the QSharedPointer template parameter \c T is not the same.
It is also possible to specify a member function directly, as in:
- \code
- QSharedPointer<MyObject> obj =
- QSharedPointer<MyObject>(new MyObject, &QObject::deleteLater);
- \endcode
+ \snippet code/src_corelib_tools_qsharedpointer.cpp 3
\sa clear()
*/
@@ -618,9 +571,7 @@
Returns \c true if this object is not null. This function is suitable
for use in \tt if-constructs, like:
- \code
- if (sharedptr) { ... }
- \endcode
+ \snippet code/src_corelib_tools_qsharedpointer.cpp 4
\sa isNull()
*/
@@ -631,9 +582,7 @@
Returns \c true if this object is null. This function is suitable
for use in \tt if-constructs, like:
- \code
- if (!sharedptr) { ... }
- \endcode
+ \snippet code/src_corelib_tools_qsharedpointer.cpp 5
\sa isNull()
*/
@@ -766,9 +715,7 @@
Resets this QSharedPointer object to point to \a t
instead. Equivalent to:
- \code
- QSharedPointer<T> other(t); this->swap(other);
- \endcode
+ \snippet code/src_corelib_tools_qsharedpointer.cpp 6
*/
/*!
@@ -777,9 +724,7 @@
Resets this QSharedPointer object to point to \a t
instead, with the Deleter \a deleter. Equivalent to:
- \code
- QSharedPointer<T> other(t, deleter); this->swap(other);
- \endcode
+ \snippet code/src_corelib_tools_qsharedpointer.cpp 7
*/
/*!
@@ -896,9 +841,7 @@
Returns \c true if this object is not null. This function is suitable
for use in \tt if-constructs, like:
- \code
- if (weakref) { ... }
- \endcode
+ \snippet code/src_corelib_tools_qsharedpointer.cpp 8
Note that, due to the nature of weak references, the pointer that
QWeakPointer references can become null at any moment, so
@@ -914,9 +857,7 @@
Returns \c true if this object is null. This function is suitable
for use in \tt if-constructs, like:
- \code
- if (!weakref) { ... }
- \endcode
+ \snippet code/src_corelib_tools_qsharedpointer.cpp 9
Note that, due to the nature of weak references, the pointer that
QWeakPointer references can become null at any moment, so
@@ -939,9 +880,7 @@
It is ok to obtain the value of the pointer and using that value itself,
like for example in debugging statements:
- \code
- qDebug("Tracking %p", weakref.data());
- \endcode
+ \snippet code/src_corelib_tools_qsharedpointer.cpp 10
However, dereferencing the pointer is only allowed if you can guarantee
by external means that the pointer does not get deleted. For example,
@@ -950,18 +889,7 @@
If that is the case, then the following code is valid:
- \code
- // this pointer cannot be used in another thread
- // so other threads cannot delete it
- QWeakPointer<int> weakref = obtainReference();
-
- Object *obj = weakref.data();
- if (obj) {
- // if the pointer wasn't deleted yet, we know it can't get
- // deleted by our own code here nor the functions we call
- otherFunction(obj);
- }
- \endcode
+ \snippet code/src_corelib_tools_qsharedpointer.cpp 11
Use this function with care.
@@ -986,17 +914,7 @@
to a strong reference and, if it succeeded, it prints the value of the
integer that was held:
- \code
- QWeakPointer<int> weakref;
-
- // ...
-
- QSharedPointer<int> strong = weakref.toStrongRef();
- if (strong)
- qDebug() << "The value is:" << *strong;
- else
- qDebug() << "The value has already been deleted";
- \endcode
+ \snippet code/src_corelib_tools_qsharedpointer.cpp 12
\sa QSharedPointer::QSharedPointer()
*/
diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp
index 25340f2d02..07a8b022bc 100644
--- a/src/corelib/tools/qsimd.cpp
+++ b/src/corelib/tools/qsimd.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -80,6 +80,43 @@
QT_BEGIN_NAMESPACE
+/*
+ * Use kdesdk/scripts/generate_string_table.pl to update the table below. Note
+ * we remove the terminating -1 that the script adds.
+ */
+
+// begin generated
+#if defined(Q_PROCESSOR_ARM)
+/* Data:
+ neon
+ crc32
+ */
+static const char features_string[] =
+ " neon\0"
+ " crc32\0"
+ "\0";
+static const int features_indices[] = { 0, 6 };
+#elif defined(Q_PROCESSOR_MIPS)
+/* Data:
+ dsp
+ dspr2
+*/
+static const char features_string[] =
+ " dsp\0"
+ " dspr2\0"
+ "\0";
+
+static const int features_indices[] = {
+ 0, 5
+};
+#elif defined(Q_PROCESSOR_X86)
+# include "qsimd_x86.cpp" // generated by util/x86simdgen
+#else
+static const char features_string[] = "";
+static const int features_indices[] = { };
+#endif
+// end generated
+
#if defined (Q_OS_NACL)
static inline uint detectProcessorFeatures()
{
@@ -153,7 +190,9 @@ static inline quint64 detectProcessorFeatures()
static int maxBasicCpuidSupported()
{
-#if defined(Q_CC_GNU)
+#if defined(Q_CC_EMSCRIPTEN)
+ return 6; // All features supported by Emscripten
+#elif defined(Q_CC_GNU)
qregisterint tmp1;
# if Q_PROCESSOR_X86 < 5
@@ -198,7 +237,7 @@ static int maxBasicCpuidSupported()
static void cpuidFeatures01(uint &ecx, uint &edx)
{
-#if defined(Q_CC_GNU)
+#if defined(Q_CC_GNU) && !defined(Q_CC_EMSCRIPTEN)
qregisterint tmp1;
asm ("xchg " PICreg", %2\n"
"cpuid\n"
@@ -215,6 +254,9 @@ static void cpuidFeatures01(uint &ecx, uint &edx)
__CPUID(1, info);
ecx = info[2];
edx = info[3];
+#else
+ Q_UNUSED(ecx);
+ Q_UNUSED(edx);
#endif
}
@@ -222,29 +264,32 @@ static void cpuidFeatures01(uint &ecx, uint &edx)
inline void __cpuidex(int info[4], int, __int64) { memset(info, 0, 4*sizeof(int));}
#endif
-static void cpuidFeatures07_00(uint &ebx, uint &ecx)
+static void cpuidFeatures07_00(uint &ebx, uint &ecx, uint &edx)
{
-#if defined(Q_CC_GNU)
+#if defined(Q_CC_GNU) && !defined(Q_CC_EMSCRIPTEN)
qregisteruint rbx; // in case it's 64-bit
qregisteruint rcx = 0;
+ qregisteruint rdx = 0;
asm ("xchg " PICreg", %0\n"
"cpuid\n"
"xchg " PICreg", %0\n"
- : "=&r" (rbx), "+&c" (rcx)
- : "a" (7)
- : "%edx");
+ : "=&r" (rbx), "+&c" (rcx), "+&d" (rdx)
+ : "a" (7));
ebx = rbx;
ecx = rcx;
+ edx = rdx;
#elif defined(Q_OS_WIN)
int info[4];
__cpuidex(info, 7, 0);
ebx = info[1];
ecx = info[2];
+ edx = info[3];
#elif defined(Q_CC_GHS)
unsigned int info[4];
__CPUIDEX(7, 0, info);
ebx = info[1];
ecx = info[2];
+ edx = info[3];
#endif
}
@@ -254,7 +299,7 @@ inline quint64 _xgetbv(__int64) { return 0; }
#endif
static void xgetbv(uint in, uint &eax, uint &edx)
{
-#if defined(Q_CC_GNU) || defined(Q_CC_GHS)
+#if (defined(Q_CC_GNU) && !defined(Q_CC_EMSCRIPTEN)) || defined(Q_CC_GHS)
asm (".byte 0x0F, 0x01, 0xD0" // xgetbv instruction
: "=a" (eax), "=d" (edx)
: "c" (in));
@@ -262,6 +307,10 @@ static void xgetbv(uint in, uint &eax, uint &edx)
quint64 result = _xgetbv(in);
eax = result;
edx = result >> 32;
+#else
+ Q_UNUSED(in);
+ Q_UNUSED(eax);
+ Q_UNUSED(edx);
#endif
}
@@ -282,13 +331,8 @@ static quint64 detectProcessorFeatures()
AVXState = XMM0_15 | YMM0_15Hi128,
AVX512State = AVXState | OpMask | ZMM0_15Hi256 | ZMM16_31
};
- static const quint64 AllAVX512 = (Q_UINT64_C(1) << CpuFeatureAVX512F) | (Q_UINT64_C(1) << CpuFeatureAVX512CD) |
- (Q_UINT64_C(1) << CpuFeatureAVX512ER) | (Q_UINT64_C(1) << CpuFeatureAVX512PF) |
- (Q_UINT64_C(1) << CpuFeatureAVX512BW) | (Q_UINT64_C(1) << CpuFeatureAVX512DQ) |
- (Q_UINT64_C(1) << CpuFeatureAVX512VL) |
- (Q_UINT64_C(1) << CpuFeatureAVX512IFMA) | (Q_UINT64_C(1) << CpuFeatureAVX512VBMI);
- static const quint64 AllAVX2 = (Q_UINT64_C(1) << CpuFeatureAVX2) | AllAVX512;
- static const quint64 AllAVX = (Q_UINT64_C(1) << CpuFeatureAVX) | AllAVX2;
+ static const quint64 AllAVX2 = CpuFeatureAVX2 | AllAVX512;
+ static const quint64 AllAVX = CpuFeatureAVX | AllAVX2;
quint64 features = 0;
int cpuidLevel = maxBasicCpuidSupported();
@@ -299,52 +343,33 @@ static quint64 detectProcessorFeatures()
Q_ASSERT(cpuidLevel >= 1);
#endif
- uint cpuid01ECX = 0, cpuid01EDX = 0;
- cpuidFeatures01(cpuid01ECX, cpuid01EDX);
-
- // the low 32-bits of features is cpuid01ECX
- // note: we need to check OS support for saving the AVX register state
- features = cpuid01ECX;
-
-#if defined(Q_PROCESSOR_X86_32)
- // x86 might not have SSE2 support
- if (cpuid01EDX & (1u << 26))
- features |= Q_UINT64_C(1) << CpuFeatureSSE2;
- else
- features &= ~(Q_UINT64_C(1) << CpuFeatureSSE2);
- // we should verify that the OS enabled saving of the SSE state...
-#else
- // x86-64 or x32
- features |= Q_UINT64_C(1) << CpuFeatureSSE2;
-#endif
+ uint results[X86CpuidMaxLeaf] = {};
+ cpuidFeatures01(results[Leaf1ECX], results[Leaf1EDX]);
+ if (cpuidLevel >= 7)
+ cpuidFeatures07_00(results[Leaf7_0EBX], results[Leaf7_0ECX], results[Leaf7_0EDX]);
+
+ // populate our feature list
+ for (uint i = 0; i < sizeof(x86_locators) / sizeof(x86_locators[0]); ++i) {
+ uint word = x86_locators[i] / 32;
+ uint bit = 1U << (x86_locators[i] % 32);
+ quint64 feature = Q_UINT64_C(1) << (i + 1);
+ if (results[word] & bit)
+ features |= feature;
+ }
+ // now check the AVX state
uint xgetbvA = 0, xgetbvD = 0;
- if (cpuid01ECX & (1u << 27)) {
+ if (results[Leaf1ECX] & (1u << 27)) {
// XGETBV enabled
xgetbv(0, xgetbvA, xgetbvD);
}
- uint cpuid0700EBX = 0;
- uint cpuid0700ECX = 0;
- if (cpuidLevel >= 7) {
- cpuidFeatures07_00(cpuid0700EBX, cpuid0700ECX);
-
- // the high 32-bits of features is cpuid0700EBX
- features |= quint64(cpuid0700EBX) << 32;
- }
-
if ((xgetbvA & AVXState) != AVXState) {
// support for YMM registers is disabled, disable all AVX
features &= ~AllAVX;
} else if ((xgetbvA & AVX512State) != AVX512State) {
// support for ZMM registers or mask registers is disabled, disable all AVX512
features &= ~AllAVX512;
- } else {
- // this feature is out of order
- if (cpuid0700ECX & (1u << 1))
- features |= Q_UINT64_C(1) << CpuFeatureAVX512VBMI;
- else
- features &= ~(Q_UINT64_C(1) << CpuFeatureAVX512VBMI);
}
return features;
@@ -493,152 +518,6 @@ static inline uint detectProcessorFeatures()
}
#endif
-/*
- * Use kdesdk/scripts/generate_string_table.pl to update the table below. Note
- * that the x86 version has a lot of blanks that must be kept and that the
- * offset table's type is changed to make the table smaller. We also remove the
- * terminating -1 that the script adds.
- */
-
-// begin generated
-#if defined(Q_PROCESSOR_ARM)
-/* Data:
- neon
- crc32
- */
-static const char features_string[] =
- " neon\0"
- " crc32\0"
- "\0";
-static const int features_indices[] = { 0, 6 };
-#elif defined(Q_PROCESSOR_MIPS)
-/* Data:
- dsp
- dspr2
-*/
-static const char features_string[] =
- " dsp\0"
- " dspr2\0"
- "\0";
-
-static const int features_indices[] = {
- 0, 5
-};
-#elif defined(Q_PROCESSOR_X86)
-/* Data:
- sse3
- sse2
- avx512vbmi
-
-
-
-
-
-
- ssse3
-
-
- fma
- cmpxchg16b
-
-
-
-
-
- sse4.1
- sse4.2
-
- movbe
- popcnt
-
- aes
-
-
- avx
- f16c
- rdrand
-
-
-
-
- bmi
- hle
- avx2
-
-
- bmi2
-
-
- rtm
-
-
-
-
- avx512f
- avx512dq
- rdseed
-
-
- avx512ifma
-
-
-
-
- avx512pf
- avx512er
- avx512cd
- sha
- avx512bw
- avx512vl
- */
-static const char features_string[] =
- " sse3\0"
- " sse2\0"
- " avx512vbmi\0"
- " ssse3\0"
- " fma\0"
- " cmpxchg16b\0"
- " sse4.1\0"
- " sse4.2\0"
- " movbe\0"
- " popcnt\0"
- " aes\0"
- " avx\0"
- " f16c\0"
- " rdrand\0"
- " bmi\0"
- " hle\0"
- " avx2\0"
- " bmi2\0"
- " rtm\0"
- " avx512f\0"
- " avx512dq\0"
- " rdseed\0"
- " avx512ifma\0"
- " avx512pf\0"
- " avx512er\0"
- " avx512cd\0"
- " sha\0"
- " avx512bw\0"
- " avx512vl\0"
- "\0";
-
-static const quint8 features_indices[] = {
- 0, 6, 12, 5, 5, 5, 5, 5,
- 5, 24, 5, 5, 31, 36, 5, 5,
- 5, 5, 5, 48, 56, 5, 64, 71,
- 5, 79, 5, 5, 84, 89, 95, 5,
- 5, 5, 5, 103, 108, 113, 5, 5,
- 119, 5, 5, 125, 5, 5, 5, 5,
- 130, 139, 149, 5, 5, 157, 5, 5,
- 5, 5, 169, 179, 189, 199, 204, 214
-};
-#else
-static const char features_string[] = "";
-static const int features_indices[] = { };
-#endif
-// end generated
-
static const int features_count = (sizeof features_indices) / (sizeof features_indices[0]);
// record what CPU features were enabled by default in this Qt build
diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h
index 18684caefb..9f1321df94 100644
--- a/src/corelib/tools/qsimd_p.h
+++ b/src/corelib/tools/qsimd_p.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -232,32 +232,48 @@
# define __RDRND__ 1
# endif
-#define QT_FUNCTION_TARGET_STRING_SSE2 "sse2"
-#define QT_FUNCTION_TARGET_STRING_SSE3 "sse3"
-#define QT_FUNCTION_TARGET_STRING_SSSE3 "ssse3"
-#define QT_FUNCTION_TARGET_STRING_SSE4_1 "sse4.1"
-#define QT_FUNCTION_TARGET_STRING_SSE4_2 "sse4.2"
-#define QT_FUNCTION_TARGET_STRING_AVX "avx"
-#define QT_FUNCTION_TARGET_STRING_AVX2 "avx2"
-#define QT_FUNCTION_TARGET_STRING_AVX512F "avx512f"
-#define QT_FUNCTION_TARGET_STRING_AVX512CD "avx512cd"
-#define QT_FUNCTION_TARGET_STRING_AVX512ER "avx512er"
-#define QT_FUNCTION_TARGET_STRING_AVX512PF "avx512pf"
-#define QT_FUNCTION_TARGET_STRING_AVX512BW "avx512bw"
-#define QT_FUNCTION_TARGET_STRING_AVX512DQ "avx512dq"
-#define QT_FUNCTION_TARGET_STRING_AVX512VL "avx512vl"
-#define QT_FUNCTION_TARGET_STRING_AVX512IFMA "avx512ifma"
-#define QT_FUNCTION_TARGET_STRING_AVX512VBMI "avx512vbmi"
-
-#define QT_FUNCTION_TARGET_STRING_AES "aes,sse4.2"
-#define QT_FUNCTION_TARGET_STRING_PCLMUL "pclmul,sse4.2"
-#define QT_FUNCTION_TARGET_STRING_POPCNT "popcnt"
-#define QT_FUNCTION_TARGET_STRING_F16C "f16c,avx"
-#define QT_FUNCTION_TARGET_STRING_RDRND "rdrnd"
-#define QT_FUNCTION_TARGET_STRING_BMI "bmi"
-#define QT_FUNCTION_TARGET_STRING_BMI2 "bmi2"
-#define QT_FUNCTION_TARGET_STRING_RDSEED "rdseed"
-#define QT_FUNCTION_TARGET_STRING_SHA "sha"
+# if defined(__BMI__) && !defined(__BMI2__) && defined(Q_CC_INTEL)
+// BMI2 instructions:
+// All processors that support BMI support BMI2 (and AVX2)
+// (but neither MSVC nor the Intel compiler define this macro)
+# define __BMI2__ 1
+# endif
+
+# include "qsimd_x86_p.h"
+
+// Haswell sub-architecture
+//
+// The Intel Core 4th generation was codenamed "Haswell" and introduced AVX2,
+// BMI1, BMI2, FMA, LZCNT, MOVBE, which makes it a good divider for a
+// sub-target for us. The first AMD processor with AVX2 support (Zen) has the
+// same features.
+//
+// macOS's fat binaries support the "x86_64h" sub-architecture and the GNU libc
+// ELF loader also supports a "haswell/" subdir (e.g., /usr/lib/haswell).
+# define QT_FUNCTION_TARGET_STRING_ARCH_HASWELL "arch=haswell"
+# if defined(__AVX2__) && defined(__BMI__) && defined(__BMI2__) && defined(__F16C__) && \
+ defined(__FMA__) && defined(__LZCNT__) && defined(__RDRND__)
+# define __haswell__ 1
+# endif
+
+// This constant does not include all CPU features found in a Haswell, only
+// those that we'd have optimized code for.
+// Note: must use Q_CONSTEXPR here, as this file may be compiled in C mode.
+QT_BEGIN_NAMESPACE
+static const quint64 CpuFeatureArchHaswell = 0
+ | CpuFeatureSSE2
+ | CpuFeatureSSE3
+ | CpuFeatureSSSE3
+ | CpuFeatureSSE4_1
+ | CpuFeatureSSE4_2
+ | CpuFeatureFMA
+ | CpuFeaturePOPCNT
+ | CpuFeatureAVX
+ | CpuFeatureF16C
+ | CpuFeatureAVX2
+ | CpuFeatureBMI
+ | CpuFeatureBMI2;
+QT_END_NAMESPACE
#endif /* Q_PROCESSOR_X86 */
@@ -292,148 +308,36 @@
QT_BEGIN_NAMESPACE
+#ifndef Q_PROCESSOR_X86
enum CPUFeatures {
#if defined(Q_PROCESSOR_ARM)
- CpuFeatureNEON = 0,
+ CpuFeatureNEON = 2,
CpuFeatureARM_NEON = CpuFeatureNEON,
- CpuFeatureCRC32 = 1,
+ CpuFeatureCRC32 = 4,
#elif defined(Q_PROCESSOR_MIPS)
- CpuFeatureDSP = 0,
- CpuFeatureDSPR2 = 1,
-#elif defined(Q_PROCESSOR_X86)
- // The order of the flags is jumbled so it matches most closely the bits in CPUID
- // Out of order:
- CpuFeatureSSE2 = 1, // uses the bit for PCLMULQDQ
- // in level 1, ECX
- CpuFeatureSSE3 = (0 + 0),
- CpuFeatureSSSE3 = (0 + 9),
- CpuFeatureSSE4_1 = (0 + 19),
- CpuFeatureSSE4_2 = (0 + 20),
- CpuFeatureMOVBE = (0 + 22),
- CpuFeaturePOPCNT = (0 + 23),
- CpuFeatureAES = (0 + 25),
- CpuFeatureAVX = (0 + 28),
- CpuFeatureF16C = (0 + 29),
- CpuFeatureRDRND = (0 + 30),
- // 31 is always zero and we've used it for the QSimdInitialized
-
- // in level 7, leaf 0, EBX
- CpuFeatureBMI = (32 + 3),
- CpuFeatureHLE = (32 + 4),
- CpuFeatureAVX2 = (32 + 5),
- CpuFeatureBMI2 = (32 + 8),
- CpuFeatureRTM = (32 + 11),
- CpuFeatureAVX512F = (32 + 16),
- CpuFeatureAVX512DQ = (32 + 17),
- CpuFeatureRDSEED = (32 + 18),
- CpuFeatureAVX512IFMA = (32 + 21),
- CpuFeatureAVX512PF = (32 + 26),
- CpuFeatureAVX512ER = (32 + 27),
- CpuFeatureAVX512CD = (32 + 28),
- CpuFeatureSHA = (32 + 29),
- CpuFeatureAVX512BW = (32 + 30),
- CpuFeatureAVX512VL = (32 + 31),
-
- // in level 7, leaf 0, ECX (out of order, for now)
- CpuFeatureAVX512VBMI = 2, // uses the bit for DTES64
+ CpuFeatureDSP = 2,
+ CpuFeatureDSPR2 = 4,
#endif
// used only to indicate that the CPU detection was initialised
- QSimdInitialized = 0x80000000
+ QSimdInitialized = 1
};
static const quint64 qCompilerCpuFeatures = 0
-#if defined __SHA__
- | (Q_UINT64_C(1) << CpuFeatureSHA)
-#endif
-#if defined __AES__
- | (Q_UINT64_C(1) << CpuFeatureAES)
-#endif
-#if defined __RTM__
- | (Q_UINT64_C(1) << CpuFeatureRTM)
-#endif
-#ifdef __RDRND__
- | (Q_UINT64_C(1) << CpuFeatureRDRND)
-#endif
-#ifdef __RDSEED__
- | (Q_UINT64_C(1) << CpuFeatureRDSEED)
-#endif
-#if defined __BMI__
- | (Q_UINT64_C(1) << CpuFeatureBMI)
-#endif
-#if defined __BMI2__
- | (Q_UINT64_C(1) << CpuFeatureBMI2)
-#endif
-#if defined __F16C__
- | (Q_UINT64_C(1) << CpuFeatureF16C)
-#endif
-#if defined __POPCNT__
- | (Q_UINT64_C(1) << CpuFeaturePOPCNT)
-#endif
-#if defined __MOVBE__ // GCC and Clang don't seem to define this
- | (Q_UINT64_C(1) << CpuFeatureMOVBE)
-#endif
-#if defined __AVX512F__
- | (Q_UINT64_C(1) << CpuFeatureAVX512F)
-#endif
-#if defined __AVX512CD__
- | (Q_UINT64_C(1) << CpuFeatureAVX512CD)
-#endif
-#if defined __AVX512ER__
- | (Q_UINT64_C(1) << CpuFeatureAVX512ER)
-#endif
-#if defined __AVX512PF__
- | (Q_UINT64_C(1) << CpuFeatureAVX512PF)
-#endif
-#if defined __AVX512BW__
- | (Q_UINT64_C(1) << CpuFeatureAVX512BW)
-#endif
-#if defined __AVX512DQ__
- | (Q_UINT64_C(1) << CpuFeatureAVX512DQ)
-#endif
-#if defined __AVX512VL__
- | (Q_UINT64_C(1) << CpuFeatureAVX512VL)
-#endif
-#if defined __AVX512IFMA__
- | (Q_UINT64_C(1) << CpuFeatureAVX512IFMA)
-#endif
-#if defined __AVX512VBMI__
- | (Q_UINT64_C(1) << CpuFeatureAVX512VBMI)
-#endif
-#if defined __AVX2__
- | (Q_UINT64_C(1) << CpuFeatureAVX2)
-#endif
-#if defined __AVX__
- | (Q_UINT64_C(1) << CpuFeatureAVX)
-#endif
-#if defined __SSE4_2__
- | (Q_UINT64_C(1) << CpuFeatureSSE4_2)
-#endif
-#if defined __SSE4_1__
- | (Q_UINT64_C(1) << CpuFeatureSSE4_1)
-#endif
-#if defined __SSSE3__
- | (Q_UINT64_C(1) << CpuFeatureSSSE3)
-#endif
-#if defined __SSE3__
- | (Q_UINT64_C(1) << CpuFeatureSSE3)
-#endif
-#if defined __SSE2__
- | (Q_UINT64_C(1) << CpuFeatureSSE2)
-#endif
#if defined __ARM_NEON__
- | (Q_UINT64_C(1) << CpuFeatureNEON)
+ | CpuFeatureNEON
#endif
#if defined __ARM_FEATURE_CRC32
- | (Q_UINT64_C(1) << CpuFeatureCRC32)
+ | CpuFeatureCRC32
#endif
#if defined __mips_dsp
- | (Q_UINT64_C(1) << CpuFeatureDSP)
+ | CpuFeatureDSP
#endif
#if defined __mips_dspr2
- | (Q_UINT64_C(1) << CpuFeatureDSPR2)
+ | CpuFeatureDSPR2
#endif
;
+#endif
#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
extern Q_CORE_EXPORT QBasicAtomicInteger<quint64> qt_cpu_features[1];
@@ -459,8 +363,8 @@ static inline quint64 qCpuFeatures()
return features;
}
-#define qCpuHasFeature(feature) ((qCompilerCpuFeatures & (Q_UINT64_C(1) << CpuFeature ## feature)) \
- || (qCpuFeatures() & (Q_UINT64_C(1) << CpuFeature ## feature)))
+#define qCpuHasFeature(feature) (((qCompilerCpuFeatures & CpuFeature ## feature) == CpuFeature ## feature) \
+ || ((qCpuFeatures() & CpuFeature ## feature) == CpuFeature ## feature))
#define ALIGNMENT_PROLOGUE_16BYTES(ptr, i, length) \
for (; i < static_cast<int>(qMin(static_cast<quintptr>(length), ((4 - ((reinterpret_cast<quintptr>(ptr) >> 2) & 0x3)) & 0x3))); ++i)
diff --git a/src/corelib/tools/qsimd_x86.cpp b/src/corelib/tools/qsimd_x86.cpp
new file mode 100644
index 0000000000..509af464b2
--- /dev/null
+++ b/src/corelib/tools/qsimd_x86.cpp
@@ -0,0 +1,116 @@
+// This is a generated file. DO NOT EDIT.
+// Please see util/x86simdgen/generate.pl
+#include "qsimd_p.h"
+
+static const char features_string[] =
+ " sse2\0"
+ " sse3\0"
+ " ssse3\0"
+ " fma\0"
+ " sse4.1\0"
+ " sse4.2\0"
+ " movbe\0"
+ " popcnt\0"
+ " aes\0"
+ " avx\0"
+ " f16c\0"
+ " rdrnd\0"
+ " bmi\0"
+ " hle\0"
+ " avx2\0"
+ " bmi2\0"
+ " rtm\0"
+ " avx512f\0"
+ " avx512dq\0"
+ " rdseed\0"
+ " avx512ifma\0"
+ " avx512pf\0"
+ " avx512er\0"
+ " avx512cd\0"
+ " sha\0"
+ " avx512bw\0"
+ " avx512vl\0"
+ " avx512vbmi\0"
+ " avx512vbmi2\0"
+ " gfni\0"
+ " vaes\0"
+ " avx512vnni\0"
+ " avx512bitalg\0"
+ " avx512vpopcntdq\0"
+ " avx5124nniw\0"
+ " avx5124fmaps\0"
+ "\0";
+
+static const quint16 features_indices[] = {
+ 306, 0, 6, 12, 19, 24, 32, 40,
+ 47, 55, 60, 65, 71, 78, 83, 88,
+ 94, 100, 105, 114, 124, 132, 144, 154,
+ 164, 174, 179, 189, 199, 211, 224, 230,
+ 236, 248, 262, 279, 292
+};
+
+enum X86CpuidLeaves {
+ Leaf1ECX,
+ Leaf1EDX,
+ Leaf7_0EBX,
+ Leaf7_0ECX,
+ Leaf7_0EDX,
+ X86CpuidMaxLeaf
+};
+
+static const quint8 x86_locators[] = {
+ Leaf1EDX*32 + 26, // sse2
+ Leaf1ECX*32 + 0, // sse3
+ Leaf1ECX*32 + 9, // ssse3
+ Leaf1ECX*32 + 12, // fma
+ Leaf1ECX*32 + 19, // sse4.1
+ Leaf1ECX*32 + 20, // sse4.2
+ Leaf1ECX*32 + 22, // movbe
+ Leaf1ECX*32 + 23, // popcnt
+ Leaf1ECX*32 + 25, // aes
+ Leaf1ECX*32 + 28, // avx
+ Leaf1ECX*32 + 29, // f16c
+ Leaf1ECX*32 + 30, // rdrnd
+ Leaf7_0EBX*32 + 3, // bmi
+ Leaf7_0EBX*32 + 4, // hle
+ Leaf7_0EBX*32 + 5, // avx2
+ Leaf7_0EBX*32 + 8, // bmi2
+ Leaf7_0EBX*32 + 11, // rtm
+ Leaf7_0EBX*32 + 16, // avx512f
+ Leaf7_0EBX*32 + 17, // avx512dq
+ Leaf7_0EBX*32 + 18, // rdseed
+ Leaf7_0EBX*32 + 21, // avx512ifma
+ Leaf7_0EBX*32 + 26, // avx512pf
+ Leaf7_0EBX*32 + 27, // avx512er
+ Leaf7_0EBX*32 + 28, // avx512cd
+ Leaf7_0EBX*32 + 29, // sha
+ Leaf7_0EBX*32 + 30, // avx512bw
+ Leaf7_0EBX*32 + 31, // avx512vl
+ Leaf7_0ECX*32 + 1, // avx512vbmi
+ Leaf7_0ECX*32 + 6, // avx512vbmi2
+ Leaf7_0ECX*32 + 8, // gfni
+ Leaf7_0ECX*32 + 9, // vaes
+ Leaf7_0ECX*32 + 11, // avx512vnni
+ Leaf7_0ECX*32 + 12, // avx512bitalg
+ Leaf7_0ECX*32 + 14, // avx512vpopcntdq
+ Leaf7_0EDX*32 + 2, // avx5124nniw
+ Leaf7_0EDX*32 + 3 // avx5124fmaps
+};
+
+// List of AVX512 features (see detectProcessorFeatures())
+static const quint64 AllAVX512 = 0
+ | CpuFeatureAVX512F
+ | CpuFeatureAVX512DQ
+ | CpuFeatureAVX512IFMA
+ | CpuFeatureAVX512PF
+ | CpuFeatureAVX512ER
+ | CpuFeatureAVX512CD
+ | CpuFeatureAVX512BW
+ | CpuFeatureAVX512VL
+ | CpuFeatureAVX512VBMI
+ | CpuFeatureAVX512VBMI2
+ | CpuFeatureAVX512VNNI
+ | CpuFeatureAVX512BITALG
+ | CpuFeatureAVX512VPOPCNTDQ
+ | CpuFeatureAVX5124NNIW
+ | CpuFeatureAVX5124FMAPS;
diff --git a/src/corelib/tools/qsimd_x86_p.h b/src/corelib/tools/qsimd_x86_p.h
new file mode 100644
index 0000000000..2434e2b797
--- /dev/null
+++ b/src/corelib/tools/qsimd_x86_p.h
@@ -0,0 +1,222 @@
+// This is a generated file. DO NOT EDIT.
+// Please see util/x86simdgen/generate.pl
+#ifndef QSIMD_P_H
+# error "Please include <private/qsimd_p.h> instead"
+#endif
+#ifndef QSIMD_X86_P_H
+#define QSIMD_X86_P_H
+
+#include "qsimd_p.h"
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+// used only to indicate that the CPU detection was initialized
+#define QSimdInitialized (Q_UINT64_C(1) << 0)
+
+// in CPUID Leaf 1, EDX:
+#define CpuFeatureSSE2 (Q_UINT64_C(1) << 1)
+#define QT_FUNCTION_TARGET_STRING_SSE2 "sse2"
+
+// in CPUID Leaf 1, ECX:
+#define CpuFeatureSSE3 (Q_UINT64_C(1) << 2)
+#define QT_FUNCTION_TARGET_STRING_SSE3 "sse3"
+#define CpuFeatureSSSE3 (Q_UINT64_C(1) << 3)
+#define QT_FUNCTION_TARGET_STRING_SSSE3 "ssse3"
+#define CpuFeatureFMA (Q_UINT64_C(1) << 4)
+#define QT_FUNCTION_TARGET_STRING_FMA "fma"
+#define CpuFeatureSSE4_1 (Q_UINT64_C(1) << 5)
+#define QT_FUNCTION_TARGET_STRING_SSE4_1 "sse4.1"
+#define CpuFeatureSSE4_2 (Q_UINT64_C(1) << 6)
+#define QT_FUNCTION_TARGET_STRING_SSE4_2 "sse4.2"
+#define CpuFeatureMOVBE (Q_UINT64_C(1) << 7)
+#define QT_FUNCTION_TARGET_STRING_MOVBE "movbe"
+#define CpuFeaturePOPCNT (Q_UINT64_C(1) << 8)
+#define QT_FUNCTION_TARGET_STRING_POPCNT "popcnt"
+#define CpuFeatureAES (Q_UINT64_C(1) << 9)
+#define QT_FUNCTION_TARGET_STRING_AES "aes,sse4.2"
+#define CpuFeatureAVX (Q_UINT64_C(1) << 10)
+#define QT_FUNCTION_TARGET_STRING_AVX "avx"
+#define CpuFeatureF16C (Q_UINT64_C(1) << 11)
+#define QT_FUNCTION_TARGET_STRING_F16C "f16c"
+#define CpuFeatureRDRND (Q_UINT64_C(1) << 12)
+#define QT_FUNCTION_TARGET_STRING_RDRND "rdrnd"
+
+// in CPUID Leaf 7, Sub-leaf 0, EBX:
+#define CpuFeatureBMI (Q_UINT64_C(1) << 13)
+#define QT_FUNCTION_TARGET_STRING_BMI "bmi"
+#define CpuFeatureHLE (Q_UINT64_C(1) << 14)
+#define QT_FUNCTION_TARGET_STRING_HLE "hle"
+#define CpuFeatureAVX2 (Q_UINT64_C(1) << 15)
+#define QT_FUNCTION_TARGET_STRING_AVX2 "avx2"
+#define CpuFeatureBMI2 (Q_UINT64_C(1) << 16)
+#define QT_FUNCTION_TARGET_STRING_BMI2 "bmi2"
+#define CpuFeatureRTM (Q_UINT64_C(1) << 17)
+#define QT_FUNCTION_TARGET_STRING_RTM "rtm"
+#define CpuFeatureAVX512F (Q_UINT64_C(1) << 18)
+#define QT_FUNCTION_TARGET_STRING_AVX512F "avx512f"
+#define CpuFeatureAVX512DQ (Q_UINT64_C(1) << 19)
+#define QT_FUNCTION_TARGET_STRING_AVX512DQ "avx512dq"
+#define CpuFeatureRDSEED (Q_UINT64_C(1) << 20)
+#define QT_FUNCTION_TARGET_STRING_RDSEED "rdseed"
+#define CpuFeatureAVX512IFMA (Q_UINT64_C(1) << 21)
+#define QT_FUNCTION_TARGET_STRING_AVX512IFMA "avx512ifma"
+#define CpuFeatureAVX512PF (Q_UINT64_C(1) << 22)
+#define QT_FUNCTION_TARGET_STRING_AVX512PF "avx512pf"
+#define CpuFeatureAVX512ER (Q_UINT64_C(1) << 23)
+#define QT_FUNCTION_TARGET_STRING_AVX512ER "avx512er"
+#define CpuFeatureAVX512CD (Q_UINT64_C(1) << 24)
+#define QT_FUNCTION_TARGET_STRING_AVX512CD "avx512cd"
+#define CpuFeatureSHA (Q_UINT64_C(1) << 25)
+#define QT_FUNCTION_TARGET_STRING_SHA "sha"
+#define CpuFeatureAVX512BW (Q_UINT64_C(1) << 26)
+#define QT_FUNCTION_TARGET_STRING_AVX512BW "avx512bw"
+#define CpuFeatureAVX512VL (Q_UINT64_C(1) << 27)
+#define QT_FUNCTION_TARGET_STRING_AVX512VL "avx512vl"
+
+// in CPUID Leaf 7, Sub-leaf 0, ECX:
+#define CpuFeatureAVX512VBMI (Q_UINT64_C(1) << 28)
+#define QT_FUNCTION_TARGET_STRING_AVX512VBMI "avx512vbmi"
+#define CpuFeatureAVX512VBMI2 (Q_UINT64_C(1) << 29)
+#define QT_FUNCTION_TARGET_STRING_AVX512VBMI2 "avx512vbmi2"
+#define CpuFeatureGFNI (Q_UINT64_C(1) << 30)
+#define QT_FUNCTION_TARGET_STRING_GFNI "gfni"
+#define CpuFeatureVAES (Q_UINT64_C(1) << 31)
+#define QT_FUNCTION_TARGET_STRING_VAES "vaes"
+#define CpuFeatureAVX512VNNI (Q_UINT64_C(1) << 32)
+#define QT_FUNCTION_TARGET_STRING_AVX512VNNI "avx512vnni"
+#define CpuFeatureAVX512BITALG (Q_UINT64_C(1) << 33)
+#define QT_FUNCTION_TARGET_STRING_AVX512BITALG "avx512bitalg"
+#define CpuFeatureAVX512VPOPCNTDQ (Q_UINT64_C(1) << 34)
+#define QT_FUNCTION_TARGET_STRING_AVX512VPOPCNTDQ "avx512vpopcntdq"
+
+// in CPUID Leaf 7, Sub-leaf 0, EDX:
+#define CpuFeatureAVX5124NNIW (Q_UINT64_C(1) << 35)
+#define QT_FUNCTION_TARGET_STRING_AVX5124NNIW "avx5124nniw"
+#define CpuFeatureAVX5124FMAPS (Q_UINT64_C(1) << 36)
+#define QT_FUNCTION_TARGET_STRING_AVX5124FMAPS "avx5124fmaps"
+
+static const quint64 qCompilerCpuFeatures = 0
+#ifdef __SSE2__
+ | CpuFeatureSSE2
+#endif
+#ifdef __SSE3__
+ | CpuFeatureSSE3
+#endif
+#ifdef __SSSE3__
+ | CpuFeatureSSSE3
+#endif
+#ifdef __FMA__
+ | CpuFeatureFMA
+#endif
+#ifdef __SSE4_1__
+ | CpuFeatureSSE4_1
+#endif
+#ifdef __SSE4_2__
+ | CpuFeatureSSE4_2
+#endif
+#ifdef __MOVBE__
+ | CpuFeatureMOVBE
+#endif
+#ifdef __POPCNT__
+ | CpuFeaturePOPCNT
+#endif
+#ifdef __AES__
+ | CpuFeatureAES
+#endif
+#ifdef __AVX__
+ | CpuFeatureAVX
+#endif
+#ifdef __F16C__
+ | CpuFeatureF16C
+#endif
+#ifdef __RDRND__
+ | CpuFeatureRDRND
+#endif
+#ifdef __BMI__
+ | CpuFeatureBMI
+#endif
+#ifdef __HLE__
+ | CpuFeatureHLE
+#endif
+#ifdef __AVX2__
+ | CpuFeatureAVX2
+#endif
+#ifdef __BMI2__
+ | CpuFeatureBMI2
+#endif
+#ifdef __RTM__
+ | CpuFeatureRTM
+#endif
+#ifdef __AVX512F__
+ | CpuFeatureAVX512F
+#endif
+#ifdef __AVX512DQ__
+ | CpuFeatureAVX512DQ
+#endif
+#ifdef __RDSEED__
+ | CpuFeatureRDSEED
+#endif
+#ifdef __AVX512IFMA__
+ | CpuFeatureAVX512IFMA
+#endif
+#ifdef __AVX512PF__
+ | CpuFeatureAVX512PF
+#endif
+#ifdef __AVX512ER__
+ | CpuFeatureAVX512ER
+#endif
+#ifdef __AVX512CD__
+ | CpuFeatureAVX512CD
+#endif
+#ifdef __SHA__
+ | CpuFeatureSHA
+#endif
+#ifdef __AVX512BW__
+ | CpuFeatureAVX512BW
+#endif
+#ifdef __AVX512VL__
+ | CpuFeatureAVX512VL
+#endif
+#ifdef __AVX512VBMI__
+ | CpuFeatureAVX512VBMI
+#endif
+#ifdef __AVX512VBMI2__
+ | CpuFeatureAVX512VBMI2
+#endif
+#ifdef __GFNI__
+ | CpuFeatureGFNI
+#endif
+#ifdef __VAES__
+ | CpuFeatureVAES
+#endif
+#ifdef __AVX512VNNI__
+ | CpuFeatureAVX512VNNI
+#endif
+#ifdef __AVX512BITALG__
+ | CpuFeatureAVX512BITALG
+#endif
+#ifdef __AVX512VPOPCNTDQ__
+ | CpuFeatureAVX512VPOPCNTDQ
+#endif
+#ifdef __AVX5124NNIW__
+ | CpuFeatureAVX5124NNIW
+#endif
+#ifdef __AVX5124FMAPS__
+ | CpuFeatureAVX5124FMAPS
+#endif
+ ;
+
+QT_END_NAMESPACE
+
+#endif // QSIMD_X86_P_H
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 82a065efc0..c89635cfdb 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -227,10 +227,8 @@ template <uint MaxCount> struct UnrollTailLoop
return returnIfExited;
bool check = loopCheck(i);
- if (check) {
- const RetType &retval = returnIfFailed(i);
- return retval;
- }
+ if (check)
+ return returnIfFailed(i);
return UnrollTailLoop<MaxCount - 1>::exec(count - 1, returnIfExited, loopCheck, returnIfFailed, i + 1);
}
@@ -253,119 +251,265 @@ inline RetType UnrollTailLoop<0>::exec(Number, RetType returnIfExited, Functor1,
}
#endif
+/*!
+ * \internal
+ *
+ * Searches for character \a \c in the string \a str and returns a pointer to
+ * it. Unlike strchr() and wcschr() (but like glibc's strchrnul()), if the
+ * character is not found, this function returns a pointer to the end of the
+ * string -- that is, \c{str.end()}.
+ */
+const ushort *QtPrivate::qustrchr(QStringView str, ushort c) noexcept
+{
+ const ushort *n = reinterpret_cast<const ushort *>(str.begin());
+ const ushort *e = reinterpret_cast<const ushort *>(str.end());
+
+#ifdef __SSE2__
+ __m128i mch = _mm_set1_epi32(c | (c << 16));
+
+ // we're going to read n[0..7] (16 bytes)
+ for (const ushort *next = n + 8; next <= e; n = next, next += 8) {
+ __m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(n));
+ __m128i result = _mm_cmpeq_epi16(data, mch);
+ uint mask = _mm_movemask_epi8(result);
+ if (ushort(mask)) {
+ // found a match
+ return n + (qCountTrailingZeroBits(mask) >> 1);
+ }
+ }
+
+# if !defined(__OPTIMIZE_SIZE__)
+ // we're going to read n[0..3] (8 bytes)
+ if (e - n > 3) {
+ __m128i data = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(n));
+ __m128i result = _mm_cmpeq_epi16(data, mch);
+ uint mask = _mm_movemask_epi8(result);
+ if (uchar(mask)) {
+ // found a match
+ return n + (qCountTrailingZeroBits(mask) >> 1);
+ }
+
+ n += 4;
+ }
+
+ return UnrollTailLoop<3>::exec(e - n, e,
+ [=](int i) { return n[i] == c; },
+ [=](int i) { return n + i; });
+# endif
+#elif defined(__ARM_NEON__) && defined(Q_PROCESSOR_ARM_64) // vaddv is only available on Aarch64
+ const uint16x8_t vmask = { 1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7 };
+ const uint16x8_t ch_vec = vdupq_n_u16(c);
+ for (const ushort *next = n + 8; next <= e; n = next, next += 8) {
+ uint16x8_t data = vld1q_u16(n);
+ uint mask = vaddvq_u16(vandq_u16(vceqq_u16(data, ch_vec), vmask));
+ if (ushort(mask)) {
+ // found a match
+ return n + qCountTrailingZeroBits(mask);
+ }
+ }
+#endif // aarch64
+
+ --n;
+ while (++n != e)
+ if (*n == c)
+ return n;
+
+ return n;
+}
+
#ifdef __SSE2__
+// Scans from \a ptr to \a end until \a maskval is non-zero. Returns true if
+// the no non-zero was found. Returns false and updates \a ptr to point to the
+// first 16-bit word that has any bit set (note: if the input is 8-bit, \a ptr
+// may be updated to one byte short).
static bool simdTestMask(const char *&ptr, const char *end, quint32 maskval)
{
-# if defined(__AVX2__)
+ auto updatePtr = [&](uint result) {
+ // found a character matching the mask
+ uint idx = qCountTrailingZeroBits(~result);
+ ptr += idx;
+ return false;
+ };
+
+# if defined(__SSE4_1__)
+ __m128i mask;
+ auto updatePtrSimd = [&](__m128i data) {
+ __m128i masked = _mm_and_si128(mask, data);
+ __m128i comparison = _mm_cmpeq_epi16(masked, _mm_setzero_si128());
+ uint result = _mm_movemask_epi8(comparison);
+ return updatePtr(result);
+ };
+
+# if defined(__AVX2__)
// AVX2 implementation: test 32 bytes at a time
const __m256i mask256 = _mm256_broadcastd_epi32(_mm_cvtsi32_si128(maskval));
while (ptr + 32 <= end) {
__m256i data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(ptr));
- if (!_mm256_testz_si256(mask256, data))
- return false;
+ if (!_mm256_testz_si256(mask256, data)) {
+ // found a character matching the mask
+ __m256i masked256 = _mm256_and_si256(mask256, data);
+ __m256i comparison256 = _mm256_cmpeq_epi16(masked256, _mm256_setzero_si256());
+ return updatePtr(_mm256_movemask_epi8(comparison256));
+ }
ptr += 32;
}
- const __m128i mask = _mm256_castsi256_si128(mask256);
-# elif defined(__SSE4_1__)
+ mask = _mm256_castsi256_si128(mask256);
+# else
// SSE 4.1 implementation: test 32 bytes at a time (two 16-byte
// comparisons, unrolled)
- const __m128i mask = _mm_set1_epi32(maskval);
+ mask = _mm_set1_epi32(maskval);
while (ptr + 32 <= end) {
__m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
__m128i data2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr + 16));
if (!_mm_testz_si128(mask, data1))
- return false;
+ return updatePtrSimd(data1);
+
+ ptr += 16;
if (!_mm_testz_si128(mask, data2))
- return false;
- ptr += 32;
+ return updatePtrSimd(data2);
+ ptr += 16;
}
-# endif
-# if defined(__SSE4_1__)
+# endif
+
// AVX2 and SSE4.1: final 16-byte comparison
if (ptr + 16 <= end) {
__m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
if (!_mm_testz_si128(mask, data1))
- return false;
+ return updatePtrSimd(data1);
ptr += 16;
}
+
+ // and final 8-byte comparison
+ if (ptr + 8 <= end) {
+ __m128i data1 = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(ptr));
+ if (!_mm_testz_si128(mask, data1))
+ return updatePtrSimd(data1);
+ ptr += 8;
+ }
+
# else
// SSE2 implementation: test 16 bytes at a time.
const __m128i mask = _mm_set1_epi32(maskval);
- while (ptr + 16 < end) {
+ while (ptr + 16 <= end) {
__m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
- __m128i masked = _mm_andnot_si128(mask, data);
+ __m128i masked = _mm_and_si128(mask, data);
__m128i comparison = _mm_cmpeq_epi16(masked, _mm_setzero_si128());
- if (quint16(_mm_movemask_epi8(comparison)) != 0xffff)
- return false;
+ quint16 result = _mm_movemask_epi8(comparison);
+ if (result != 0xffff)
+ return updatePtr(result);
ptr += 16;
}
+
+ // and one 8-byte comparison
+ if (ptr + 8 <= end) {
+ __m128i data = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(ptr));
+ __m128i masked = _mm_and_si128(mask, data);
+ __m128i comparison = _mm_cmpeq_epi16(masked, _mm_setzero_si128());
+ quint8 result = _mm_movemask_epi8(comparison);
+ if (result != 0xff)
+ return updatePtr(result);
+ ptr += 8;
+ }
# endif
return true;
}
#endif
-bool QtPrivate::isAscii(QLatin1String s) Q_DECL_NOTHROW
+// Note: ptr on output may be off by one and point to a preceding US-ASCII
+// character. Usually harmless.
+bool qt_is_ascii(const char *&ptr, const char *end) Q_DECL_NOTHROW
{
- const char *ptr = s.begin();
- const char *end = s.end();
-
#if defined(__SSE2__)
// Testing for the high bit can be done efficiently with just PMOVMSKB
# if defined(__AVX2__)
while (ptr + 32 <= end) {
__m256i data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(ptr));
quint32 mask = _mm256_movemask_epi8(data);
- if (mask)
+ if (mask) {
+ uint idx = qCountTrailingZeroBits(mask);
+ ptr += idx;
return false;
+ }
ptr += 32;
}
# endif
-
while (ptr + 16 <= end) {
__m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
quint32 mask = _mm_movemask_epi8(data);
- if (mask)
+ if (mask) {
+ uint idx = qCountTrailingZeroBits(mask);
+ ptr += idx;
return false;
+ }
ptr += 16;
}
+ if (ptr + 8 <= end) {
+ __m128i data = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(ptr));
+ quint8 mask = _mm_movemask_epi8(data);
+ if (mask) {
+ uint idx = qCountTrailingZeroBits(mask);
+ ptr += idx;
+ return false;
+ }
+ ptr += 8;
+ }
#endif
while (ptr + 4 <= end) {
quint32 data = qFromUnaligned<quint32>(ptr);
- if (data & 0x80808080U)
+ if (data &= 0x80808080U) {
+ uint idx = qCountTrailingZeroBits(data);
+ ptr += idx / 8;
return false;
+ }
ptr += 4;
}
while (ptr != end) {
- if (quint8(*ptr++) & 0x80)
+ if (quint8(*ptr) & 0x80)
return false;
+ ++ptr;
}
return true;
}
-bool QtPrivate::isAscii(QStringView s) Q_DECL_NOTHROW
+bool QtPrivate::isAscii(QLatin1String s) Q_DECL_NOTHROW
{
- const QChar *ptr = s.begin();
- const QChar *end = s.end();
+ const char *ptr = s.begin();
+ const char *end = s.end();
+
+ return qt_is_ascii(ptr, end);
+}
+static bool isAscii(const QChar *&ptr, const QChar *end)
+{
#ifdef __SSE2__
const char *ptr8 = reinterpret_cast<const char *>(ptr);
const char *end8 = reinterpret_cast<const char *>(end);
- if (!simdTestMask(ptr8, end8, 0xff80ff80))
- return false;
+ bool ok = simdTestMask(ptr8, end8, 0xff80ff80);
ptr = reinterpret_cast<const QChar *>(ptr8);
+ if (!ok)
+ return false;
#endif
while (ptr != end) {
- if ((*ptr++).unicode() & 0xff80)
+ if (ptr->unicode() & 0xff80)
return false;
+ ++ptr;
}
return true;
}
+bool QtPrivate::isAscii(QStringView s) Q_DECL_NOTHROW
+{
+ const QChar *ptr = s.begin();
+ const QChar *end = s.end();
+
+ return isAscii(ptr, end);
+}
+
bool QtPrivate::isLatin1(QStringView s) Q_DECL_NOTHROW
{
const QChar *ptr = s.begin();
@@ -439,11 +583,19 @@ void qt_from_latin1(ushort *dst, const char *str, size_t size) Q_DECL_NOTHROW
#endif
}
- size = size % 16;
+ // we're going to read str[offset..offset+7] (8 bytes)
+ if (str + offset + 7 < e) {
+ const __m128i chunk = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(str + offset));
+ const __m128i unpacked = _mm_unpacklo_epi8(chunk, _mm_setzero_si128());
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(dst + offset), unpacked);
+ offset += 8;
+ }
+
+ size = size % 8;
dst += offset;
str += offset;
# if defined(Q_COMPILER_LAMBDA) && !defined(__OPTIMIZE_SIZE__)
- return UnrollTailLoop<15>::exec(int(size), [=](int i) { dst[i] = (uchar)str[i]; });
+ return UnrollTailLoop<7>::exec(int(size), [=](int i) { dst[i] = (uchar)str[i]; });
# endif
#endif
#if defined(__mips_dsp)
@@ -457,86 +609,123 @@ void qt_from_latin1(ushort *dst, const char *str, size_t size) Q_DECL_NOTHROW
#endif
}
-#if defined(__SSE2__)
-static inline __m128i mergeQuestionMarks(__m128i chunk)
+template <bool Checked>
+static void qt_to_latin1_internal(uchar *dst, const ushort *src, qsizetype length)
{
+#if defined(__SSE2__)
+ uchar *e = dst + length;
+ qptrdiff offset = 0;
+
+# ifdef __AVX2__
+ const __m256i questionMark256 = _mm256_broadcastw_epi16(_mm_cvtsi32_si128('?'));
+ const __m256i outOfRange256 = _mm256_broadcastw_epi16(_mm_cvtsi32_si128(0x100));
+ const __m128i questionMark = _mm256_castsi256_si128(questionMark256);
+ const __m128i outOfRange = _mm256_castsi256_si128(outOfRange256);
+# else
const __m128i questionMark = _mm_set1_epi16('?');
+ const __m128i outOfRange = _mm_set1_epi16(0x100);
+# endif
-# ifdef __SSE4_2__
- // compare the unsigned shorts for the range 0x0100-0xFFFF
- // note on the use of _mm_cmpestrm:
- // The MSDN documentation online (http://technet.microsoft.com/en-us/library/bb514080.aspx)
- // says for range search the following:
- // For each character c in a, determine whether b0 <= c <= b1 or b2 <= c <= b3
- //
- // However, all examples on the Internet, including from Intel
- // (see http://software.intel.com/en-us/articles/xml-parsing-accelerator-with-intel-streaming-simd-extensions-4-intel-sse4/)
- // put the range to be searched first
- //
- // Disassembly and instruction-level debugging with GCC and ICC show
- // that they are doing the right thing. Inverting the arguments in the
- // instruction does cause a bunch of test failures.
-
- const __m128i rangeMatch = _mm_cvtsi32_si128(0xffff0100);
- const __m128i offLimitMask = _mm_cmpestrm(rangeMatch, 2, chunk, 8,
- _SIDD_UWORD_OPS | _SIDD_CMP_RANGES | _SIDD_UNIT_MASK);
-
- // replace the non-Latin 1 characters in the chunk with question marks
- chunk = _mm_blendv_epi8(chunk, questionMark, offLimitMask);
+ auto mergeQuestionMarks = [=](__m128i chunk) {
+ // SSE has no compare instruction for unsigned comparison.
+# ifdef __SSE4_1__
+ // We use an unsigned uc = qMin(uc, 0x100) and then compare for equality.
+ chunk = _mm_min_epu16(chunk, outOfRange);
+ const __m128i offLimitMask = _mm_cmpeq_epi16(chunk, outOfRange);
+ chunk = _mm_blendv_epi8(chunk, questionMark, offLimitMask);
# else
- // SSE has no compare instruction for unsigned comparison.
- // The variables must be shiffted + 0x8000 to be compared
- const __m128i signedBitOffset = _mm_set1_epi16(short(0x8000));
- const __m128i thresholdMask = _mm_set1_epi16(short(0xff + 0x8000));
+ // The variables must be shiffted + 0x8000 to be compared
+ const __m128i signedBitOffset = _mm_set1_epi16(short(0x8000));
+ const __m128i thresholdMask = _mm_set1_epi16(short(0xff + 0x8000));
- const __m128i signedChunk = _mm_add_epi16(chunk, signedBitOffset);
- const __m128i offLimitMask = _mm_cmpgt_epi16(signedChunk, thresholdMask);
+ const __m128i signedChunk = _mm_add_epi16(chunk, signedBitOffset);
+ const __m128i offLimitMask = _mm_cmpgt_epi16(signedChunk, thresholdMask);
-# ifdef __SSE4_1__
- // replace the non-Latin 1 characters in the chunk with question marks
- chunk = _mm_blendv_epi8(chunk, questionMark, offLimitMask);
-# else
- // offLimitQuestionMark contains '?' for each 16 bits that was off-limit
- // the 16 bits that were correct contains zeros
- const __m128i offLimitQuestionMark = _mm_and_si128(offLimitMask, questionMark);
+ // offLimitQuestionMark contains '?' for each 16 bits that was off-limit
+ // the 16 bits that were correct contains zeros
+ const __m128i offLimitQuestionMark = _mm_and_si128(offLimitMask, questionMark);
- // correctBytes contains the bytes that were in limit
- // the 16 bits that were off limits contains zeros
- const __m128i correctBytes = _mm_andnot_si128(offLimitMask, chunk);
+ // correctBytes contains the bytes that were in limit
+ // the 16 bits that were off limits contains zeros
+ const __m128i correctBytes = _mm_andnot_si128(offLimitMask, chunk);
- // merge offLimitQuestionMark and correctBytes to have the result
- chunk = _mm_or_si128(correctBytes, offLimitQuestionMark);
-# endif
-# endif
- return chunk;
-}
-#endif
+ // merge offLimitQuestionMark and correctBytes to have the result
+ chunk = _mm_or_si128(correctBytes, offLimitQuestionMark);
-static void qt_to_latin1(uchar *dst, const ushort *src, int length)
-{
-#if defined(__SSE2__)
- uchar *e = dst + length;
- qptrdiff offset = 0;
+ Q_UNUSED(outOfRange);
+# endif
+ return chunk;
+ };
// we're going to write to dst[offset..offset+15] (16 bytes)
for ( ; dst + offset + 15 < e; offset += 16) {
+# if defined(__AVX2__)
+ __m256i chunk = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(src + offset));
+ if (Checked) {
+ // See mergeQuestionMarks lambda above for details
+ chunk = _mm256_min_epu16(chunk, outOfRange256);
+ const __m256i offLimitMask = _mm256_cmpeq_epi16(chunk, outOfRange256);
+ chunk = _mm256_blendv_epi8(chunk, questionMark256, offLimitMask);
+ }
+
+ const __m128i chunk2 = _mm256_extracti128_si256(chunk, 1);
+ const __m128i chunk1 = _mm256_castsi256_si128(chunk);
+# else
__m128i chunk1 = _mm_loadu_si128((const __m128i*)(src + offset)); // load
- chunk1 = mergeQuestionMarks(chunk1);
+ if (Checked)
+ chunk1 = mergeQuestionMarks(chunk1);
__m128i chunk2 = _mm_loadu_si128((const __m128i*)(src + offset + 8)); // load
- chunk2 = mergeQuestionMarks(chunk2);
+ if (Checked)
+ chunk2 = mergeQuestionMarks(chunk2);
+# endif
// pack the two vector to 16 x 8bits elements
const __m128i result = _mm_packus_epi16(chunk1, chunk2);
_mm_storeu_si128((__m128i*)(dst + offset), result); // store
}
+# if !defined(__OPTIMIZE_SIZE__)
+ // we're going to write to dst[offset..offset+7] (8 bytes)
+ if (dst + offset + 7 < e) {
+ __m128i chunk = _mm_loadu_si128(reinterpret_cast<const __m128i *>(src + offset));
+ if (Checked)
+ chunk = mergeQuestionMarks(chunk);
+
+ // pack, where the upper half is ignored
+ const __m128i result = _mm_packus_epi16(chunk, chunk);
+ _mm_storel_epi64(reinterpret_cast<__m128i *>(dst + offset), result);
+ offset += 8;
+ }
+
+ // we're going to write to dst[offset..offset+3] (4 bytes)
+ if (dst + offset + 3 < e) {
+ __m128i chunk = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(src + offset));
+ if (Checked)
+ chunk = mergeQuestionMarks(chunk);
+
+ // pack, we'll the upper three quarters
+ const __m128i result = _mm_packus_epi16(chunk, chunk);
+ qToUnaligned(_mm_cvtsi128_si32(result), dst + offset);
+ offset += 4;
+ }
+
+ length = length % 4;
+# else
length = length % 16;
+# endif // optimize size
+
+ // advance dst, src for tail processing
dst += offset;
src += offset;
-# if defined(Q_COMPILER_LAMBDA) && !defined(__OPTIMIZE_SIZE__)
- return UnrollTailLoop<15>::exec(length, [=](int i) { dst[i] = (src[i]>0xff) ? '?' : (uchar) src[i]; });
+# if !defined(__OPTIMIZE_SIZE__)
+ return UnrollTailLoop<3>::exec(length, [=](int i) {
+ if (Checked)
+ dst[i] = (src[i]>0xff) ? '?' : (uchar) src[i];
+ else
+ dst[i] = src[i];
+ });
# endif
#elif defined(__ARM_NEON__)
// Refer to the documentation of the SSE2 implementation
@@ -551,10 +740,12 @@ static void qt_to_latin1(uchar *dst, const ushort *src, int length)
uint16x8_t chunk = vld1q_u16((uint16_t *)src); // load
src += 8;
- const uint16x8_t offLimitMask = vcgtq_u16(chunk, thresholdMask); // chunk > thresholdMask
- const uint16x8_t offLimitQuestionMark = vandq_u16(offLimitMask, questionMark); // offLimitMask & questionMark
- const uint16x8_t correctBytes = vbicq_u16(chunk, offLimitMask); // !offLimitMask & chunk
- chunk = vorrq_u16(correctBytes, offLimitQuestionMark); // correctBytes | offLimitQuestionMark
+ if (Checked) {
+ const uint16x8_t offLimitMask = vcgtq_u16(chunk, thresholdMask); // chunk > thresholdMask
+ const uint16x8_t offLimitQuestionMark = vandq_u16(offLimitMask, questionMark); // offLimitMask & questionMark
+ const uint16x8_t correctBytes = vbicq_u16(chunk, offLimitMask); // !offLimitMask & chunk
+ chunk = vorrq_u16(correctBytes, offLimitQuestionMark); // correctBytes | offLimitQuestionMark
+ }
const uint8x8_t result = vmovn_u16(chunk); // narrowing move->packing
vst1_u8(dst, result); // store
dst += 8;
@@ -566,12 +757,25 @@ static void qt_to_latin1(uchar *dst, const ushort *src, int length)
qt_toLatin1_mips_dsp_asm(dst, src, length);
#else
while (length--) {
- *dst++ = (*src>0xff) ? '?' : (uchar) *src;
+ if (Checked)
+ *dst++ = (*src>0xff) ? '?' : (uchar) *src;
+ else
+ *dst++ = *src;
++src;
}
#endif
}
+static void qt_to_latin1(uchar *dst, const ushort *src, qsizetype length)
+{
+ qt_to_latin1_internal<true>(dst, src, length);
+}
+
+void qt_to_latin1_unchecked(uchar *dst, const ushort *src, qsizetype length)
+{
+ qt_to_latin1_internal<false>(dst, src, length);
+}
+
// Unicode case-insensitive comparison
static int ucstricmp(const QChar *a, const QChar *ae, const QChar *b, const QChar *be)
{
@@ -836,12 +1040,11 @@ static int ucstrncmp(const QChar *a, const uchar *c, size_t l)
}
}
-# ifdef Q_PROCESSOR_X86_64
- enum { MaxTailLength = 7 };
+# if !defined(__OPTIMIZE_SIZE__)
// we'll read uc[offset..offset+7] (16 bytes) and c[offset..offset+7] (8 bytes)
if (uc + offset + 7 < e) {
// same, but we're using an 8-byte load
- __m128i chunk = _mm_cvtsi64_si128(qFromUnaligned<long long>(c + offset));
+ __m128i chunk = _mm_loadl_epi64((const __m128i*)(c + offset));
__m128i secondHalf = _mm_unpacklo_epi8(chunk, nullmask);
__m128i ucdata = _mm_loadu_si128((const __m128i*)(uc + offset));
@@ -856,11 +1059,26 @@ static int ucstrncmp(const QChar *a, const uchar *c, size_t l)
// still matched
offset += 8;
}
-# else
- // 32-bit, we can't do MOVQ to load 8 bytes
- Q_UNUSED(nullmask);
- enum { MaxTailLength = 15 };
-# endif
+
+ enum { MaxTailLength = 3 };
+ // we'll read uc[offset..offset+3] (8 bytes) and c[offset..offset+3] (4 bytes)
+ if (uc + offset + 3 < e) {
+ __m128i chunk = _mm_cvtsi32_si128(qFromUnaligned<int>(c + offset));
+ __m128i secondHalf = _mm_unpacklo_epi8(chunk, nullmask);
+
+ __m128i ucdata = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(uc + offset));
+ __m128i result = _mm_cmpeq_epi8(secondHalf, ucdata);
+ uint mask = ~_mm_movemask_epi8(result);
+ if (uchar(mask)) {
+ // found a different character
+ uint idx = qCountTrailingZeroBits(mask);
+ return uc[offset + idx / 2] - c[offset + idx / 2];
+ }
+
+ // still matched
+ offset += 4;
+ }
+# endif // optimize size
// reset uc and c
uc += offset;
@@ -930,14 +1148,12 @@ static int qt_compare_strings(QLatin1String lhs, QStringView rhs, Qt::CaseSensit
static int qt_compare_strings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
{
+ if (cs == Qt::CaseInsensitive)
+ return qstrnicmp(lhs.data(), lhs.size(), rhs.data(), rhs.size());
if (lhs.isEmpty())
return lencmp(0, rhs.size());
const auto l = std::min(lhs.size(), rhs.size());
- int r;
- if (cs == Qt::CaseSensitive)
- r = qstrncmp(lhs.data(), rhs.data(), l);
- else
- r = qstrnicmp(lhs.data(), rhs.data(), l);
+ int r = qstrncmp(lhs.data(), rhs.data(), l);
return r ? r : lencmp(lhs.size(), rhs.size());
}
@@ -1039,44 +1255,9 @@ static int findChar(const QChar *str, int len, QChar ch, int from,
const ushort *n = s + from;
const ushort *e = s + len;
if (cs == Qt::CaseSensitive) {
-#ifdef __SSE2__
- __m128i mch = _mm_set1_epi32(c | (c << 16));
-
- // we're going to read n[0..7] (16 bytes)
- for (const ushort *next = n + 8; next <= e; n = next, next += 8) {
- __m128i data = _mm_loadu_si128((const __m128i*)n);
- __m128i result = _mm_cmpeq_epi16(data, mch);
- uint mask = _mm_movemask_epi8(result);
- if (ushort(mask)) {
- // found a match
- // same as: return n - s + _bit_scan_forward(mask) / 2
- return (reinterpret_cast<const char *>(n) - reinterpret_cast<const char *>(s)
- + qCountTrailingZeroBits(mask)) >> 1;
- }
- }
-
-# if defined(Q_COMPILER_LAMBDA) && !defined(__OPTIMIZE_SIZE__)
- return UnrollTailLoop<7>::exec(e - n, -1,
- [=](int i) { return n[i] == c; },
- [=](int i) { return n - s + i; });
-# endif
-#endif
-#if defined(__ARM_NEON__) && defined(Q_PROCESSOR_ARM_64) // vaddv is only available on Aarch64
- const uint16x8_t vmask = { 1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7 };
- const uint16x8_t ch_vec = vdupq_n_u16(c);
- for (const ushort *next = n + 8; next <= e; n = next, next += 8) {
- uint16x8_t data = vld1q_u16(n);
- uint mask = vaddvq_u16(vandq_u16(vceqq_u16(data, ch_vec), vmask));
- if (ushort(mask)) {
- // found a match
- return n - s + qCountTrailingZeroBits(mask);
- }
- }
-#endif // aarch64
- --n;
- while (++n != e)
- if (*n == c)
- return n - s;
+ n = QtPrivate::qustrchr(QStringView(n, e), c);
+ if (n != e)
+ return n - s;
} else {
c = foldCase(c);
--n;
@@ -4930,16 +5111,55 @@ bool QString::endsWith(QChar c, Qt::CaseSensitivity cs) const
return qt_ends_with(*this, c, cs);
}
-static QByteArray qt_convert_to_latin1(QStringView string);
+/*!
+ Returns \c true if the string only contains uppercase letters,
+ otherwise returns \c false.
+ \since 5.12
-QByteArray QString::toLatin1_helper(const QString &string)
+ \sa QChar::isUpper(), isLower()
+*/
+bool QString::isUpper() const
{
- return qt_convert_to_latin1(string);
+ if (isEmpty())
+ return false;
+
+ const QChar *d = data();
+
+ for (int i = 0, max = size(); i < max; ++i) {
+ if (!d[i].isUpper())
+ return false;
+ }
+
+ return true;
}
-QByteArray QString::toLatin1_helper(const QChar *data, int length)
+/*!
+ Returns \c true if the string only contains lowercase letters,
+ otherwise returns \c false.
+ \since 5.12
+
+ \sa QChar::isLower(), isUpper()
+ */
+bool QString::isLower() const
+{
+ if (isEmpty())
+ return false;
+
+ const QChar *d = data();
+
+ for (int i = 0, max = size(); i < max; ++i) {
+ if (!d[i].isLower())
+ return false;
+ }
+
+ return true;
+}
+
+static QByteArray qt_convert_to_latin1(QStringView string);
+
+QByteArray QString::toLatin1_helper(const QString &string)
{
- return qt_convert_to_latin1(QStringView(data, length));
+ return qt_convert_to_latin1(string);
}
/*!
@@ -6013,7 +6233,17 @@ QString& QString::fill(QChar ch, int size)
sensitivity setting \a cs.
*/
+/*!
+ \fn int QString::compare(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+
+ \since 5.12
+ \overload compare()
+
+ Performs a comparison of this with \a s, using the case
+ sensitivity setting \a cs.
+*/
+#if QT_STRINGVIEW_LEVEL < 2
/*!
\overload compare()
\since 4.2
@@ -6029,6 +6259,7 @@ int QString::compare(const QString &other, Qt::CaseSensitivity cs) const Q_DECL_
{
return qt_compare_strings(*this, other, cs);
}
+#endif
/*!
\internal
@@ -6055,6 +6286,7 @@ int QString::compare(QLatin1String other, Qt::CaseSensitivity cs) const Q_DECL_N
return qt_compare_strings(*this, other, cs);
}
+#if QT_STRINGVIEW_LEVEL < 2
/*!
\fn int QString::compare(const QStringRef &ref, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
\overload compare()
@@ -6063,6 +6295,7 @@ int QString::compare(QLatin1String other, Qt::CaseSensitivity cs) const Q_DECL_N
an integer less than, equal to, or greater than zero if the string
is less than, equal to, or greater than \a ref.
*/
+#endif
/*!
\internal
@@ -6173,7 +6406,7 @@ int QString::localeAwareCompare(const QString &other) const
return localeAwareCompare_helper(constData(), length(), other.constData(), other.length());
}
-#if QT_CONFIG(icu) && !defined(Q_OS_WIN32) && !defined(Q_OS_DARWIN)
+#if QT_CONFIG(icu)
Q_GLOBAL_STATIC(QThreadStorage<QCollator>, defaultCollator)
#endif
@@ -6194,12 +6427,15 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1,
return qt_compare_strings(QStringView(data1, length1), QStringView(data2, length2),
Qt::CaseSensitive);
-#if defined(Q_OS_WIN)
-# ifndef Q_OS_WINRT
- int res = CompareString(GetUserDefaultLCID(), 0, (wchar_t*)data1, length1, (wchar_t*)data2, length2);
-# else
- int res = CompareStringEx(LOCALE_NAME_USER_DEFAULT, 0, (LPCWSTR)data1, length1, (LPCWSTR)data2, length2, NULL, NULL, 0);
-# endif
+#if QT_CONFIG(icu)
+ if (!defaultCollator()->hasLocalData())
+ defaultCollator()->setLocalData(QCollator());
+ return defaultCollator()->localData().compare(data1, length1, data2, length2);
+#else
+ const QString lhs = QString::fromRawData(data1, length1).normalized(QString::NormalizationForm_C);
+ const QString rhs = QString::fromRawData(data2, length2).normalized(QString::NormalizationForm_C);
+# if defined(Q_OS_WIN)
+ int res = CompareStringEx(LOCALE_NAME_USER_DEFAULT, 0, (LPWSTR)lhs.constData(), lhs.length(), (LPWSTR)rhs.constData(), rhs.length(), NULL, NULL, 0);
switch (res) {
case CSTR_LESS_THAN:
@@ -6209,37 +6445,33 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1,
default:
return 0;
}
-#elif defined (Q_OS_MAC)
+# elif defined (Q_OS_DARWIN)
// Use CFStringCompare for comparing strings on Mac. This makes Qt order
// strings the same way as native applications do, and also respects
// the "Order for sorted lists" setting in the International preferences
// panel.
const CFStringRef thisString =
CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault,
- reinterpret_cast<const UniChar *>(data1), length1, kCFAllocatorNull);
+ reinterpret_cast<const UniChar *>(lhs.constData()), lhs.length(), kCFAllocatorNull);
const CFStringRef otherString =
CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault,
- reinterpret_cast<const UniChar *>(data2), length2, kCFAllocatorNull);
+ reinterpret_cast<const UniChar *>(rhs.constData()), rhs.length(), kCFAllocatorNull);
const int result = CFStringCompare(thisString, otherString, kCFCompareLocalized);
CFRelease(thisString);
CFRelease(otherString);
return result;
-#elif QT_CONFIG(icu)
- if (!defaultCollator()->hasLocalData())
- defaultCollator()->setLocalData(QCollator());
- return defaultCollator()->localData().compare(data1, length1, data2, length2);
-#elif defined(Q_OS_UNIX)
+# elif defined(Q_OS_UNIX)
// declared in <string.h>
- int delta = strcoll(toLocal8Bit_helper(data1, length1).constData(), toLocal8Bit_helper(data2, length2).constData());
+ int delta = strcoll(lhs.toLocal8Bit().constData(), rhs.toLocal8Bit().constData());
if (delta == 0)
- delta = qt_compare_strings(QStringView(data1, length1), QStringView(data2, length2),
- Qt::CaseSensitive);
+ delta = qt_compare_strings(lhs, rhs, Qt::CaseSensitive);
return delta;
-#else
- return qt_compare_strings(QStringView(data1, length1), QStringView(data2, length2),
- Qt::CaseSensitive);
-#endif
+# else
+# error "This case shouldn't happen"
+ return qt_compare_strings(lhs, rhs, Qt::CaseSensitive);
+# endif
+#endif // !QT_CONFIG(icu)
}
@@ -7742,10 +7974,7 @@ QVector<QStringRef> QString::splitRef(const QRegularExpression &re, SplitBehavio
Example:
- \code
- QString str("ab");
- str.repeated(4); // returns "abababab"
- \endcode
+ \snippet code/src_corelib_tools_qstring.cpp 8
*/
QString QString::repeated(int times) const
{
@@ -7784,19 +8013,11 @@ QString QString::repeated(int times) const
void qt_string_normalize(QString *data, QString::NormalizationForm mode, QChar::UnicodeVersion version, int from)
{
- bool simple = true;
- const QChar *p = data->constData();
- int len = data->length();
- for (int i = from; i < len; ++i) {
- if (p[i].unicode() >= 0x80) {
- simple = false;
- if (i > from)
- from = i - 1;
- break;
- }
- }
- if (simple)
+ const QChar *p = data->constData() + from;
+ if (isAscii(p, p + data->length() - from))
return;
+ if (p > data->constData() + from)
+ from = p - data->constData() - 1; // need one before the non-ASCII to perform NFC
if (version == QChar::Unicode_Unassigned) {
version = QChar::currentUnicodeVersion();
@@ -9757,11 +9978,7 @@ QDataStream &operator<<(QDataStream &out, const QString &str)
out.writeBytes(reinterpret_cast<const char *>(str.unicode()), sizeof(QChar) * str.length());
} else {
QVarLengthArray<ushort> buffer(str.length());
- const ushort *data = reinterpret_cast<const ushort *>(str.constData());
- for (int i = 0; i < str.length(); i++) {
- buffer[i] = qbswap(*data);
- ++data;
- }
+ qbswap<sizeof(ushort)>(str.constData(), str.length(), buffer.data());
out.writeBytes(reinterpret_cast<const char *>(buffer.data()), sizeof(ushort) * buffer.size());
}
} else {
@@ -9818,10 +10035,7 @@ QDataStream &operator>>(QDataStream &in, QString &str)
if ((in.byteOrder() == QDataStream::BigEndian)
!= (QSysInfo::ByteOrder == QSysInfo::BigEndian)) {
ushort *data = reinterpret_cast<ushort *>(str.data());
- while (len--) {
- *data = qbswap(*data);
- ++data;
- }
+ qbswap<sizeof(*data)>(data, len, data);
}
} else {
str = QString(QLatin1String(""));
@@ -11887,10 +12101,7 @@ QString QString::toHtmlEscaped() const
If you have code that looks like this:
- \code
- // hasAttribute takes a QString argument
- if (node.hasAttribute("http-contents-length")) //...
- \endcode
+ \snippet code/src_corelib_tools_qstring.cpp 9
then a temporary QString will be created to be passed as the \c{hasAttribute}
function parameter. This can be quite expensive, as it involves a memory
@@ -11899,9 +12110,7 @@ QString QString::toHtmlEscaped() const
This cost can be avoided by using QStringLiteral instead:
- \code
- if (node.hasAttribute(QStringLiteral(u"http-contents-length"))) //...
- \endcode
+ \snippet code/src_corelib_tools_qstring.cpp 10
In this case, QString's internal data will be generated at compile time; no
conversion or allocation will occur at runtime.
@@ -11916,9 +12125,7 @@ QString QString::toHtmlEscaped() const
instance, QString::operator==() can compare to a QLatin1String
directly:
- \code
- if (attribute.name() == QLatin1String("http-contents-length")) //...
- \endcode
+ \snippet code/src_corelib_tools_qstring.cpp 11
\note Some compilers have bugs encoding strings containing characters outside
the US-ASCII character set. Make sure you prefix your string with \c{u} in
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index f27f7efa2b..6be3dcdbe1 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -409,6 +409,9 @@ public:
bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
bool endsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ bool isUpper() const;
+ bool isLower() const;
+
Q_REQUIRED_RESULT QString leftJustified(int width, QChar fill = QLatin1Char(' '), bool trunc = false) const;
Q_REQUIRED_RESULT QString rightJustified(int width, QChar fill = QLatin1Char(' '), bool trunc = false) const;
@@ -605,8 +608,12 @@ public:
QString &setUnicode(const QChar *unicode, int size);
inline QString &setUtf16(const ushort *utf16, int size);
+#if QT_STRINGVIEW_LEVEL < 2
int compare(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW;
+ inline int compare(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW;
+#endif
int compare(QLatin1String other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW;
+ inline int compare(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW;
static inline int compare(const QString &s1, const QString &s2,
Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW
@@ -619,7 +626,6 @@ public:
Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW
{ return -s2.compare(s1, cs); }
- inline int compare(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW;
static int compare(const QString &s1, const QStringRef &s2,
Qt::CaseSensitivity = Qt::CaseSensitive) Q_DECL_NOTHROW;
@@ -875,7 +881,6 @@ private:
static QString fromUtf8_helper(const char *str, int size);
static QString fromLocal8Bit_helper(const char *, int size);
static QByteArray toLatin1_helper(const QString &);
- static QByteArray toLatin1_helper(const QChar *data, int size);
static QByteArray toLatin1_helper_inplace(QString &);
static QByteArray toUtf8_helper(const QString &);
static QByteArray toLocal8Bit_helper(const QChar *data, int size);
@@ -1636,8 +1641,12 @@ inline bool operator> (const QStringRef &lhs, const QString &rhs) Q_DECL_NOTHROW
inline bool operator<=(const QStringRef &lhs, const QString &rhs) Q_DECL_NOTHROW { return rhs >= lhs; }
inline bool operator>=(const QStringRef &lhs, const QString &rhs) Q_DECL_NOTHROW { return rhs <= lhs; }
+#if QT_STRINGVIEW_LEVEL < 2
inline int QString::compare(const QStringRef &s, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
{ return QString::compare_helper(constData(), length(), s.constData(), s.length(), cs); }
+#endif
+inline int QString::compare(QStringView s, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
+{ return -s.compare(*this, cs); }
inline int QString::compare(const QString &s1, const QStringRef &s2, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
{ return QString::compare_helper(s1.constData(), s1.length(), s2.constData(), s2.length(), cs); }
inline int QStringRef::compare(const QString &s, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
diff --git a/src/corelib/tools/qstringalgorithms.h b/src/corelib/tools/qstringalgorithms.h
index 8446d85239..cc0eda71f3 100644
--- a/src/corelib/tools/qstringalgorithms.h
+++ b/src/corelib/tools/qstringalgorithms.h
@@ -56,6 +56,7 @@ template <typename T> class QVector;
namespace QtPrivate {
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype qustrlen(const ushort *str) Q_DECL_NOTHROW;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION const ushort *qustrchr(QStringView str, ushort ch) noexcept;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QStringView lhs, QLatin1String rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp
index e9b7397a74..cf150c2a1b 100644
--- a/src/corelib/tools/qstringlist.cpp
+++ b/src/corelib/tools/qstringlist.cpp
@@ -323,6 +323,7 @@ static bool stringList_contains(const QStringList &stringList, const T &str, Qt:
}
+#if QT_STRINGVIEW_LEVEL < 2
/*!
\fn bool QStringList::contains(const QString &str, Qt::CaseSensitivity cs) const
@@ -332,11 +333,31 @@ static bool stringList_contains(const QStringList &stringList, const T &str, Qt:
\sa indexOf(), lastIndexOf(), QString::contains()
*/
+#endif
+
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+/// Not really needed anymore, but kept for binary compatibility
bool QtPrivate::QStringList_contains(const QStringList *that, const QString &str,
Qt::CaseSensitivity cs)
{
return stringList_contains(*that, str, cs);
}
+#endif
+
+/*!
+ \fn bool QStringList::contains(QStringView str, Qt::CaseSensitivity cs) const
+ \overload
+ \since 5.12
+
+ 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.
+ */
+bool QtPrivate::QStringList_contains(const QStringList *that, QStringView str,
+ Qt::CaseSensitivity cs)
+{
+ return stringList_contains(*that, str, cs);
+}
/*!
\fn bool QStringList::contains(QLatin1String str, Qt::CaseSensitivity cs) const
@@ -692,7 +713,7 @@ int QtPrivate::QStringList_indexOf(const QStringList *that, const QRegularExpres
if (from < 0)
from = qMax(from + that->size(), 0);
- QString exactPattern = QLatin1String("\\A(?:") + re.pattern() + QLatin1String(")\\z");
+ QString exactPattern = QRegularExpression::anchoredPattern(re.pattern());
QRegularExpression exactRe(exactPattern, re.patternOptions());
for (int i = from; i < that->size(); ++i) {
@@ -722,7 +743,7 @@ int QtPrivate::QStringList_lastIndexOf(const QStringList *that, const QRegularEx
else if (from >= that->size())
from = that->size() - 1;
- QString exactPattern = QLatin1String("\\A(?:") + re.pattern() + QLatin1String(")\\z");
+ QString exactPattern = QRegularExpression::anchoredPattern(re.pattern());
QRegularExpression exactRe(exactPattern, re.patternOptions());
for (int i = from; i >= 0; --i) {
diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h
index e58445b8c0..10cbad04d6 100644
--- a/src/corelib/tools/qstringlist.h
+++ b/src/corelib/tools/qstringlist.h
@@ -117,8 +117,11 @@ public:
{ QList<QString>::operator=(std::move(other)); return *this; }
#endif
+#if QT_STRINGVIEW_LEVEL < 2
inline bool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+#endif
inline bool contains(QLatin1String str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ inline bool contains(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
inline QStringList operator+(const QStringList &other) const
{ QStringList n = *this; n += other; return n; }
@@ -161,7 +164,10 @@ namespace QtPrivate {
QStringList Q_CORE_EXPORT QStringList_filter(const QStringList *that, const QString &str,
Qt::CaseSensitivity cs);
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
bool Q_CORE_EXPORT QStringList_contains(const QStringList *that, const QString &str, Qt::CaseSensitivity cs);
+#endif
+ bool Q_CORE_EXPORT QStringList_contains(const QStringList *that, QStringView 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);
@@ -213,16 +219,23 @@ inline QStringList QListSpecialMethods<QString>::filter(const QString &str, Qt::
return QtPrivate::QStringList_filter(self(), str, cs);
}
+#if QT_STRINGVIEW_LEVEL < 2
inline bool QStringList::contains(const QString &str, Qt::CaseSensitivity cs) const
{
return QtPrivate::QStringList_contains(this, str, cs);
}
+#endif
inline bool QStringList::contains(QLatin1String str, Qt::CaseSensitivity cs) const
{
return QtPrivate::QStringList_contains(this, str, cs);
}
+inline bool QStringList::contains(QStringView 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/qstringliteral.h b/src/corelib/tools/qstringliteral.h
index 6a1a74a80e..64296b89fc 100644
--- a/src/corelib/tools/qstringliteral.h
+++ b/src/corelib/tools/qstringliteral.h
@@ -51,33 +51,17 @@ QT_BEGIN_NAMESPACE
typedef QTypedArrayData<ushort> QStringData;
-#if defined(Q_OS_WIN) && !defined(Q_COMPILER_UNICODE_STRINGS)
-// fall back to wchar_t if the a Windows compiler does not
-// support Unicode string literals, assuming wchar_t is 2 bytes
-// on that platform (sanity-checked by static_assert further below)
-
-#if defined(Q_CC_MSVC)
-# define QT_UNICODE_LITERAL_II(str) L##str
-#else
-# define QT_UNICODE_LITERAL_II(str) L"" str
-#endif
-typedef wchar_t qunicodechar;
-
-#else
// all our supported compilers support Unicode string literals,
// even if their Q_COMPILER_UNICODE_STRING has been revoked due
// to lacking stdlib support. But QStringLiteral only needs the
// core language feature, so just use u"" here unconditionally:
-#define QT_UNICODE_LITERAL_II(str) u"" str
typedef char16_t qunicodechar;
-#endif
-
Q_STATIC_ASSERT_X(sizeof(qunicodechar) == 2,
"qunicodechar must typedef an integral type of size 2");
-#define QT_UNICODE_LITERAL(str) QT_UNICODE_LITERAL_II(str)
+#define QT_UNICODE_LITERAL(str) u"" str
#define QStringLiteral(str) \
([]() Q_DECL_NOEXCEPT -> QString { \
enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
diff --git a/src/corelib/tools/qstringview.cpp b/src/corelib/tools/qstringview.cpp
index 0e3246c72c..a7d9426fa6 100644
--- a/src/corelib/tools/qstringview.cpp
+++ b/src/corelib/tools/qstringview.cpp
@@ -74,19 +74,14 @@ QT_BEGIN_NAMESPACE
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
+ \snippet code/src_corelib_tools_qstringview.cpp 0
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
+ \snippet code/src_corelib_tools_qstringview.cpp 1
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
@@ -291,9 +286,7 @@ QT_BEGIN_NAMESPACE
If you need the full array, use the constructor from pointer and
size instead:
- \code
- auto sv = QStringView(array, std::size(array)); // using C++17 std::size()
- \endcode
+ \snippet code/src_corelib_tools_qstringview.cpp 2
\a string must remain valid for the lifetime of this string view
object.
@@ -681,6 +674,20 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \fn int QStringView::compare(QStringView other, Qt::CaseSensitivity cs) const
+ \since 5.12
+
+ Compares this string-view with the \a other string-view and returns an
+ integer less than, equal to, or greater than zero if this string-view
+ is less than, equal to, or greater than the other string-view.
+
+ If \a cs is Qt::CaseSensitive, the comparison is case sensitive;
+ otherwise the comparison is case insensitive.
+
+ \sa operator==(), operator<(), operator>()
+*/
+
+/*!
\fn bool QStringView::startsWith(QStringView str, Qt::CaseSensitivity cs) const
\fn bool QStringView::startsWith(QLatin1String l1, Qt::CaseSensitivity cs) const
\fn bool QStringView::startsWith(QChar ch) const
diff --git a/src/corelib/tools/qstringview.h b/src/corelib/tools/qstringview.h
index 4f7d48fe1d..2e95c2b218 100644
--- a/src/corelib/tools/qstringview.h
+++ b/src/corelib/tools/qstringview.h
@@ -250,6 +250,9 @@ public:
Q_REQUIRED_RESULT QStringView trimmed() const Q_DECL_NOTHROW { return QtPrivate::trimmed(*this); }
+ Q_REQUIRED_RESULT int compare(QStringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
+ { return QtPrivate::compareStrings(*this, other, cs); }
+
Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
{ return QtPrivate::startsWith(*this, s, cs); }
Q_REQUIRED_RESULT inline bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW;
diff --git a/src/corelib/tools/qt_attribution.json b/src/corelib/tools/qt_attribution.json
index 49a76cb8b4..5bb95c9f5b 100644
--- a/src/corelib/tools/qt_attribution.json
+++ b/src/corelib/tools/qt_attribution.json
@@ -20,16 +20,18 @@
"Name": "Unicode Common Locale Data Repository (CLDR)",
"QDocModule": "qtcore",
"QtUsage": "Used in Qt Core (QTimeZone, QLocale).",
+ "Files": "For update, see qtbase/util/local_database/cldr2qlocalexml.py",
"Files": "qlocale_data_p.h qtimezoneprivate_data_p.h",
"Description": "The Unicode CLDR provides key building blocks for software to support the
world's languages, with the largest and most extensive standard repository of locale data
available.",
"Homepage": "http://cldr.unicode.org/",
- "Version": "v31.0.1",
+ "Version": "v34",
+ "License": "// as specified in https://spdx.org/licenses/Unicode-DFS-2016.html",
"License": "Unicode License Agreement - Data Files and Software (2016)",
"LicenseId": "Unicode-DFS-2016",
"LicenseFile": "UNICODE_LICENSE.txt",
- "Copyright": "Copyright (C) 1991-2017 Unicode, Inc."
+ "Copyright": "Copyright (C) 1991-2018 Unicode, Inc."
}
]
diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp
index daa7dc1531..db6be581ec 100644
--- a/src/corelib/tools/qtimezone.cpp
+++ b/src/corelib/tools/qtimezone.cpp
@@ -66,11 +66,10 @@ static QTimeZonePrivate *newBackendTimeZone()
return new QAndroidTimeZonePrivate();
#elif defined(Q_OS_UNIX) || defined(Q_OS_ANDROID_EMBEDDED)
return new QTzTimeZonePrivate();
- // Registry based timezone backend not available on WinRT
-#elif defined Q_OS_WIN
- return new QWinTimeZonePrivate();
#elif QT_CONFIG(icu)
return new QIcuTimeZonePrivate();
+#elif defined Q_OS_WIN
+ return new QWinTimeZonePrivate();
#else
return new QUtcTimeZonePrivate();
#endif // System Locales
@@ -93,11 +92,10 @@ static QTimeZonePrivate *newBackendTimeZone(const QByteArray &ianaId)
return new QAndroidTimeZonePrivate(ianaId);
#elif defined(Q_OS_UNIX) || defined(Q_OS_ANDROID_EMBEDDED)
return new QTzTimeZonePrivate(ianaId);
- // Registry based timezone backend not available on WinRT
-#elif defined Q_OS_WIN
- return new QWinTimeZonePrivate(ianaId);
#elif QT_CONFIG(icu)
return new QIcuTimeZonePrivate(ianaId);
+#elif defined Q_OS_WIN
+ return new QWinTimeZonePrivate(ianaId);
#else
return new QUtcTimeZonePrivate(ianaId);
#endif // System Locales
@@ -822,8 +820,8 @@ bool QTimeZone::isTimeZoneIdAvailable(const QByteArray &ianaId)
// IDs as availableTimeZoneIds() may be slow
if (!QTimeZonePrivate::isValidId(ianaId))
return false;
- const QList<QByteArray> tzIds = availableTimeZoneIds();
- return std::binary_search(tzIds.begin(), tzIds.end(), ianaId);
+ return QUtcTimeZonePrivate().isTimeZoneIdAvailable(ianaId) ||
+ global_tz->backend->isTimeZoneIdAvailable(ianaId);
}
static QList<QByteArray> set_union(const QList<QByteArray> &l1, const QList<QByteArray> &l2)
diff --git a/src/corelib/tools/qtimezoneprivate.cpp b/src/corelib/tools/qtimezoneprivate.cpp
index 54c2f65d94..569b343187 100644
--- a/src/corelib/tools/qtimezoneprivate.cpp
+++ b/src/corelib/tools/qtimezoneprivate.cpp
@@ -260,6 +260,8 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs,
const qint64 sixteenHoursInMSecs(16 * 3600 * 1000);
Q_STATIC_ASSERT(-sixteenHoursInMSecs / 1000 < QTimeZone::MinUtcOffsetSecs
&& sixteenHoursInMSecs / 1000 > QTimeZone::MaxUtcOffsetSecs);
+ const qint64 recent = forLocalMSecs - sixteenHoursInMSecs;
+ const qint64 imminent = forLocalMSecs + sixteenHoursInMSecs;
/*
Offsets are Local - UTC, positive to the east of Greenwich, negative to
the west; DST offset always exceeds standard offset, when DST applies.
@@ -327,7 +329,7 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs,
// Get a transition definitely before the local MSecs; usually all we need.
// Only around the transition times might we need another.
- Data tran = previousTransition(forLocalMSecs - sixteenHoursInMSecs);
+ Data tran = previousTransition(recent);
Q_ASSERT(forLocalMSecs < 0 || // Pre-epoch TZ info may be unavailable
forLocalMSecs - tran.offsetFromUtc * 1000 >= tran.atMSecsSinceEpoch);
Data nextTran = nextTransition(tran.atMSecsSinceEpoch);
@@ -343,8 +345,7 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs,
&& forLocalMSecs > nextTran.atMSecsSinceEpoch + nextTran.offsetFromUtc * 1000) {
Data newTran = nextTransition(nextTran.atMSecsSinceEpoch);
if (newTran.atMSecsSinceEpoch == invalidMSecs()
- || newTran.atMSecsSinceEpoch + newTran.offsetFromUtc * 1000
- > forLocalMSecs + sixteenHoursInMSecs) {
+ || newTran.atMSecsSinceEpoch + newTran.offsetFromUtc * 1000 > imminent) {
// Definitely not a relevant tansition: too far in the future.
break;
}
@@ -357,10 +358,10 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs,
/*
So now tran is definitely before and nextTran is either after or only
- slightly before. The one with the larger offset is in DST; the other in
- standard time. Our hint tells us which of those to use (defaulting to
- standard if no hint): try it first; if that fails, try the other; if both
- fail life's tricky.
+ slightly before. One is standard time; we interpret the other as DST
+ (although the transition might in fact by a change in standard offset). Our
+ hint tells us which of those to use (defaulting to standard if no hint): try
+ it first; if that fails, try the other; if both fail, life's tricky.
*/
Q_ASSERT(forLocalMSecs < 0
|| forLocalMSecs - tran.offsetFromUtc * 1000 > tran.atMSecsSinceEpoch);
@@ -369,7 +370,9 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs,
nextTran.atMSecsSinceEpoch = forLocalMSecs - nextTran.offsetFromUtc * 1000;
tran.atMSecsSinceEpoch = forLocalMSecs - tran.offsetFromUtc * 1000;
- const bool nextIsDst = tran.offsetFromUtc < nextTran.offsetFromUtc;
+ // If both or neither have zero DST, treat the one with lower offset as standard:
+ const bool nextIsDst = !nextTran.daylightTimeOffset == !tran.daylightTimeOffset
+ ? tran.offsetFromUtc < nextTran.offsetFromUtc : nextTran.daylightTimeOffset;
// If that agrees with hint > 0, our first guess is to use nextTran; else tran.
const bool nextFirst = nextIsDst == (hint > 0) && nextStart != invalidMSecs();
for (int i = 0; i < 2; i++) {
@@ -415,8 +418,8 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs,
/* Bracket and refine to discover offset. */
qint64 utcEpochMSecs;
- int early = offsetFromUtc(forLocalMSecs - sixteenHoursInMSecs);
- int late = offsetFromUtc(forLocalMSecs + sixteenHoursInMSecs);
+ int early = offsetFromUtc(recent);
+ int late = offsetFromUtc(imminent);
if (Q_LIKELY(early == late)) { // > 99% of the time
utcEpochMSecs = forLocalMSecs - early * 1000;
} else {
@@ -437,9 +440,7 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs,
utcEpochMSecs = forStd;
} else {
// Invalid forLocalMSecs: in spring-forward gap.
- const int dstStep = daylightTimeOffset(early < late ?
- forLocalMSecs + sixteenHoursInMSecs :
- forLocalMSecs - sixteenHoursInMSecs) * 1000;
+ const int dstStep = daylightTimeOffset(early < late ? imminent : recent) * 1000;
Q_ASSERT(dstStep); // There can't be a transition without it !
utcEpochMSecs = (hint > 0) ? forStd - dstStep : forDst + dstStep;
}
@@ -486,6 +487,13 @@ QByteArray QTimeZonePrivate::systemTimeZoneId() const
return QByteArray();
}
+bool QTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray& ianaId) const
+{
+ // Fall-back implementation, can be made faster in subclasses
+ const QList<QByteArray> tzIds = availableTimeZoneIds();
+ return std::binary_search(tzIds.begin(), tzIds.end(), ianaId);
+}
+
QList<QByteArray> QTimeZonePrivate::availableTimeZoneIds() const
{
return QList<QByteArray>();
@@ -864,6 +872,17 @@ QByteArray QUtcTimeZonePrivate::systemTimeZoneId() const
return utcQByteArray();
}
+bool QUtcTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray &ianaId) const
+{
+ for (int i = 0; i < utcDataTableSize; ++i) {
+ const QUtcData *data = utcData(i);
+ if (utcId(data) == ianaId) {
+ return true;
+ }
+ }
+ return false;
+}
+
QList<QByteArray> QUtcTimeZonePrivate::availableTimeZoneIds() const
{
QList<QByteArray> result;
diff --git a/src/corelib/tools/qtimezoneprivate_p.h b/src/corelib/tools/qtimezoneprivate_p.h
index 4d357111f2..c9a5726216 100644
--- a/src/corelib/tools/qtimezoneprivate_p.h
+++ b/src/corelib/tools/qtimezoneprivate_p.h
@@ -128,6 +128,7 @@ public:
virtual QByteArray systemTimeZoneId() const;
+ virtual bool isTimeZoneIdAvailable(const QByteArray &ianaId) const;
virtual QList<QByteArray> availableTimeZoneIds() const;
virtual QList<QByteArray> availableTimeZoneIds(QLocale::Country country) const;
virtual QList<QByteArray> availableTimeZoneIds(int utcOffset) const;
@@ -204,6 +205,7 @@ public:
QByteArray systemTimeZoneId() const override;
+ bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override;
QList<QByteArray> availableTimeZoneIds() const override;
QList<QByteArray> availableTimeZoneIds(QLocale::Country country) const override;
QList<QByteArray> availableTimeZoneIds(int utcOffset) const override;
@@ -323,6 +325,7 @@ public:
QByteArray systemTimeZoneId() const override;
+ bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override;
QList<QByteArray> availableTimeZoneIds() const override;
QList<QByteArray> availableTimeZoneIds(QLocale::Country country) const override;
diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/tools/qtimezoneprivate_tz.cpp
index 6a5df6272a..bed62a02bd 100644
--- a/src/corelib/tools/qtimezoneprivate_tz.cpp
+++ b/src/corelib/tools/qtimezoneprivate_tz.cpp
@@ -535,7 +535,7 @@ static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArra
// See the section about TZ at http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html
QList<QByteArray> parts = posixRule.split(',');
- PosixZone stdZone, dstZone;
+ PosixZone stdZone, dstZone = PosixZone::invalid();
{
const QByteArray &zoneinfo = parts.at(0);
const char *begin = zoneinfo.constBegin();
@@ -878,14 +878,17 @@ QString QTzTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
}
// Otherwise is strange sequence, so work backwards through trans looking for first match, if any
- for (int i = m_tranTimes.size() - 1; i >= 0; --i) {
- if (m_tranTimes.at(i).atMSecsSinceEpoch <= currentMSecs) {
- tran = dataForTzTransition(m_tranTimes.at(i));
- if ((timeType == QTimeZone::DaylightTime && tran.daylightTimeOffset != 0)
- || (timeType == QTimeZone::StandardTime && tran.daylightTimeOffset == 0)) {
- return tran.abbreviation;
- }
- }
+ auto it = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(),
+ [currentMSecs](const QTzTransitionTime &at) {
+ return at.atMSecsSinceEpoch <= currentMSecs;
+ });
+
+ while (it != m_tranTimes.cbegin()) {
+ --it;
+ tran = dataForTzTransition(*it);
+ int offset = tran.daylightTimeOffset;
+ if ((timeType == QTimeZone::DaylightTime) != (offset == 0))
+ return tran.abbreviation;
}
// Otherwise if no match use current data
@@ -900,7 +903,7 @@ QString QTzTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch) const
int QTzTimeZonePrivate::offsetFromUtc(qint64 atMSecsSinceEpoch) const
{
const QTimeZonePrivate::Data tran = data(atMSecsSinceEpoch);
- return tran.standardTimeOffset + tran.daylightTimeOffset;
+ return tran.offsetFromUtc; // == tran.standardTimeOffset + tran.daylightTimeOffset
}
int QTzTimeZonePrivate::standardTimeOffset(qint64 atMSecsSinceEpoch) const
@@ -942,40 +945,38 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::dataForTzTransition(QTzTransitionTime
QTimeZonePrivate::Data QTzTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
{
+ // If we have no rules (so probably an invalid tz), return invalid data:
+ if (!m_tranTimes.size())
+ return invalidData();
+
// If the required time is after the last transition and we have a POSIX rule then use it
- if (m_tranTimes.size() > 0 && m_tranTimes.last().atMSecsSinceEpoch < forMSecsSinceEpoch
+ if (m_tranTimes.last().atMSecsSinceEpoch < forMSecsSinceEpoch
&& !m_posixRule.isEmpty() && forMSecsSinceEpoch >= 0) {
const int year = QDateTime::fromMSecsSinceEpoch(forMSecsSinceEpoch, Qt::UTC).date().year();
QVector<QTimeZonePrivate::Data> posixTrans =
calculatePosixTransitions(m_posixRule, year - 1, year + 1,
m_tranTimes.last().atMSecsSinceEpoch);
- for (int i = posixTrans.size() - 1; i >= 0; --i) {
- if (posixTrans.at(i).atMSecsSinceEpoch <= forMSecsSinceEpoch) {
- QTimeZonePrivate::Data data = posixTrans.at(i);
- data.atMSecsSinceEpoch = forMSecsSinceEpoch;
- return data;
- }
- }
- }
-
- // Otherwise if we can find a valid tran then use its rule
- for (int i = m_tranTimes.size() - 1; i >= 0; --i) {
- if (m_tranTimes.at(i).atMSecsSinceEpoch <= forMSecsSinceEpoch) {
- Data data = dataForTzTransition(m_tranTimes.at(i));
+ auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
+ [forMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
+ return at.atMSecsSinceEpoch <= forMSecsSinceEpoch;
+ });
+ if (it > posixTrans.cbegin()) {
+ QTimeZonePrivate::Data data = *--it;
data.atMSecsSinceEpoch = forMSecsSinceEpoch;
return data;
}
}
- // Otherwise use the earliest transition we have
- if (m_tranTimes.size() > 0) {
- Data data = dataForTzTransition(m_tranTimes.at(0));
- data.atMSecsSinceEpoch = forMSecsSinceEpoch;
- return data;
- }
-
- // Otherwise we have no rules, so probably an invalid tz, so return invalid data
- return invalidData();
+ // Otherwise, if we can find a valid tran, then use its rule:
+ auto last = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(),
+ [forMSecsSinceEpoch] (const QTzTransitionTime &at) {
+ return at.atMSecsSinceEpoch <= forMSecsSinceEpoch;
+ });
+ if (last > m_tranTimes.cbegin())
+ --last;
+ Data data = dataForTzTransition(*last);
+ data.atMSecsSinceEpoch = forMSecsSinceEpoch;
+ return data;
}
bool QTzTimeZonePrivate::hasTransitions() const
@@ -992,21 +993,20 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::nextTransition(qint64 afterMSecsSince
QVector<QTimeZonePrivate::Data> posixTrans =
calculatePosixTransitions(m_posixRule, year - 1, year + 1,
m_tranTimes.last().atMSecsSinceEpoch);
- for (int i = 0; i < posixTrans.size(); ++i) {
- if (posixTrans.at(i).atMSecsSinceEpoch > afterMSecsSinceEpoch)
- return posixTrans.at(i);
- }
- }
+ auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
+ [afterMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
+ return at.atMSecsSinceEpoch <= afterMSecsSinceEpoch;
+ });
- // Otherwise if we can find a valid tran then use its rule
- for (int i = 0; i < m_tranTimes.size(); ++i) {
- if (m_tranTimes.at(i).atMSecsSinceEpoch > afterMSecsSinceEpoch) {
- return dataForTzTransition(m_tranTimes.at(i));
- }
+ return it == posixTrans.cend() ? invalidData() : *it;
}
- // Otherwise we have no rule, or there is no next transition, so return invalid data
- return invalidData();
+ // Otherwise, if we can find a valid tran, use its rule:
+ auto last = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(),
+ [afterMSecsSinceEpoch] (const QTzTransitionTime &at) {
+ return at.atMSecsSinceEpoch <= afterMSecsSinceEpoch;
+ });
+ return last != m_tranTimes.cend() ? dataForTzTransition(*last) : invalidData();
}
QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
@@ -1018,21 +1018,20 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecs
QVector<QTimeZonePrivate::Data> posixTrans =
calculatePosixTransitions(m_posixRule, year - 1, year + 1,
m_tranTimes.last().atMSecsSinceEpoch);
- for (int i = posixTrans.size() - 1; i >= 0; --i) {
- if (posixTrans.at(i).atMSecsSinceEpoch < beforeMSecsSinceEpoch)
- return posixTrans.at(i);
- }
+ auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
+ [beforeMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
+ return at.atMSecsSinceEpoch < beforeMSecsSinceEpoch;
+ });
+ Q_ASSERT(it > posixTrans.cbegin());
+ return *--it;
}
// Otherwise if we can find a valid tran then use its rule
- for (int i = m_tranTimes.size() - 1; i >= 0; --i) {
- if (m_tranTimes.at(i).atMSecsSinceEpoch < beforeMSecsSinceEpoch) {
- return dataForTzTransition(m_tranTimes.at(i));
- }
- }
-
- // Otherwise we have no rule, so return invalid data
- return invalidData();
+ auto last = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(),
+ [beforeMSecsSinceEpoch] (const QTzTransitionTime &at) {
+ return at.atMSecsSinceEpoch < beforeMSecsSinceEpoch;
+ });
+ return last > m_tranTimes.cbegin() ? dataForTzTransition(*--last) : invalidData();
}
// TODO Could cache the value and monitor the required files for any changes
@@ -1098,6 +1097,11 @@ QByteArray QTzTimeZonePrivate::systemTimeZoneId() const
return ianaId;
}
+bool QTzTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray &ianaId) const
+{
+ return tzZones->contains(ianaId);
+}
+
QList<QByteArray> QTzTimeZonePrivate::availableTimeZoneIds() const
{
QList<QByteArray> result = tzZones->keys();
diff --git a/src/corelib/tools/qtimezoneprivate_win.cpp b/src/corelib/tools/qtimezoneprivate_win.cpp
index 8bde07c710..1bf2366748 100644
--- a/src/corelib/tools/qtimezoneprivate_win.cpp
+++ b/src/corelib/tools/qtimezoneprivate_win.cpp
@@ -49,6 +49,7 @@
QT_BEGIN_NAMESPACE
#ifndef Q_OS_WINRT
+// The registry-based timezone backend is not available on WinRT, which falls back to equivalent APIs.
#define QT_USE_REGISTRY_TIMEZONE 1
#endif
@@ -139,15 +140,15 @@ bool equalTzi(const TIME_ZONE_INFORMATION &tzi1, const TIME_ZONE_INFORMATION &tz
#ifdef QT_USE_REGISTRY_TIMEZONE
bool openRegistryKey(const QString &keyPath, HKEY *key)
{
- return (RegOpenKeyEx(HKEY_LOCAL_MACHINE, (const wchar_t*)keyPath.utf16(), 0, KEY_READ, key)
- == ERROR_SUCCESS);
+ return RegOpenKeyEx(HKEY_LOCAL_MACHINE, reinterpret_cast<const wchar_t*>(keyPath.utf16()),
+ 0, KEY_READ, key) == ERROR_SUCCESS;
}
QString readRegistryString(const HKEY &key, const wchar_t *value)
{
wchar_t buffer[MAX_PATH] = {0};
DWORD size = sizeof(wchar_t) * MAX_PATH;
- RegQueryValueEx(key, (LPCWSTR)value, NULL, NULL, (LPBYTE)buffer, &size);
+ RegQueryValueEx(key, value, nullptr, nullptr, reinterpret_cast<LPBYTE>(buffer), &size);
return QString::fromWCharArray(buffer);
}
@@ -155,7 +156,7 @@ int readRegistryValue(const HKEY &key, const wchar_t *value)
{
DWORD buffer;
DWORD size = sizeof(buffer);
- RegQueryValueEx(key, (LPCWSTR)value, NULL, NULL, (LPBYTE)&buffer, &size);
+ RegQueryValueEx(key, value, nullptr, nullptr, reinterpret_cast<LPBYTE>(&buffer), &size);
return buffer;
}
@@ -166,7 +167,7 @@ QWinTimeZonePrivate::QWinTransitionRule readRegistryRule(const HKEY &key,
QWinTimeZonePrivate::QWinTransitionRule rule;
REG_TZI_FORMAT tzi;
DWORD tziSize = sizeof(tzi);
- if (RegQueryValueEx(key, (LPCWSTR)value, NULL, NULL, (BYTE *)&tzi, &tziSize)
+ if (RegQueryValueEx(key, value, nullptr, nullptr, reinterpret_cast<BYTE *>(&tzi), &tziSize)
== ERROR_SUCCESS) {
rule.startYear = 0;
rule.standardTimeBias = tzi.Bias + tzi.StandardBias;
@@ -191,12 +192,12 @@ TIME_ZONE_INFORMATION getRegistryTzi(const QByteArray &windowsId, bool *ok)
if (openRegistryKey(tziKeyPath, &key)) {
DWORD size = sizeof(tzi.DaylightName);
- RegQueryValueEx(key, L"Dlt", NULL, NULL, (LPBYTE)tzi.DaylightName, &size);
+ RegQueryValueEx(key, L"Dlt", nullptr, nullptr, reinterpret_cast<LPBYTE>(tzi.DaylightName), &size);
size = sizeof(tzi.StandardName);
- RegQueryValueEx(key, L"Std", NULL, NULL, (LPBYTE)tzi.StandardName, &size);
+ RegQueryValueEx(key, L"Std", nullptr, nullptr, reinterpret_cast<LPBYTE>(tzi.StandardName), &size);
- if (RegQueryValueEx(key, L"TZI", NULL, NULL, (BYTE *) &regTzi, &regTziSize)
+ if (RegQueryValueEx(key, L"TZI", nullptr, nullptr, reinterpret_cast<BYTE *>(&regTzi), &regTziSize)
== ERROR_SUCCESS) {
tzi.Bias = regTzi.Bias;
tzi.StandardBias = regTzi.StandardBias;
@@ -589,7 +590,7 @@ void QWinTimeZonePrivate::init(const QByteArray &ianaId)
for (int year = startYear; year <= endYear; ++year) {
bool ruleOk;
QWinTransitionRule rule = readRegistryRule(dynamicKey,
- (LPCWSTR)QString::number(year).utf16(),
+ reinterpret_cast<LPCWSTR>(QString::number(year).utf16()),
&ruleOk);
if (ruleOk
// Don't repeat a recurrent rule:
@@ -687,10 +688,10 @@ QString QWinTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
if (nameType == QTimeZone::OffsetName) {
const QWinTransitionRule &rule =
m_tranRules.at(ruleIndexForYear(m_tranRules, QDate::currentDate().year()));
+ int offset = rule.standardTimeBias;
if (timeType == QTimeZone::DaylightTime)
- return isoOffsetFormat((rule.standardTimeBias + rule.daylightTimeBias) * -60);
- else
- return isoOffsetFormat((rule.standardTimeBias) * -60);
+ offset += rule.daylightTimeBias;
+ return isoOffsetFormat(offset * -60);
}
switch (timeType) {
diff --git a/src/corelib/tools/qunicodetables_p.h b/src/corelib/tools/qunicodetables_p.h
index f3fb6ec1b0..3f2e91a9b2 100644
--- a/src/corelib/tools/qunicodetables_p.h
+++ b/src/corelib/tools/qunicodetables_p.h
@@ -72,6 +72,9 @@ struct Properties {
signed short mirrorDiff : 16;
ushort lowerCaseSpecial : 1;
signed short lowerCaseDiff : 15;
+#ifdef Q_OS_WASM
+ unsigned char : 0; //wasm 64 packing trick
+#endif
ushort upperCaseSpecial : 1;
signed short upperCaseDiff : 15;
ushort titleCaseSpecial : 1;
@@ -80,6 +83,9 @@ struct Properties {
signed short caseFoldDiff : 15;
ushort unicodeVersion : 8; /* 5 used */
ushort nfQuickCheck : 8;
+#ifdef Q_OS_WASM
+ unsigned char : 0; //wasm 64 packing trick
+#endif
ushort graphemeBreakClass : 5; /* 5 used */
ushort wordBreakClass : 5; /* 5 used */
ushort sentenceBreakClass : 8; /* 4 used */
diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h
index b74b1fd123..597e7464cb 100644
--- a/src/corelib/tools/qvarlengtharray.h
+++ b/src/corelib/tools/qvarlengtharray.h
@@ -254,7 +254,8 @@ private:
bool isValidIterator(const const_iterator &i) const
{
- return (i <= constEnd()) && (constBegin() <= i);
+ const std::less<const T*> less = {};
+ return !less(cend(), i) && !less(i, cbegin());
}
};
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index 345ba4b097..30fd7b2865 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -306,7 +306,8 @@ private:
void destruct(T *from, T *to);
bool isValidIterator(const iterator &i) const
{
- return (i <= d->end()) && (d->begin() <= i);
+ const std::less<const T*> less = {};
+ return !less(d->end(), i) && !less(i, d->begin());
}
class AlignmentDummy { Data header; T array[1]; };
};
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index 72224f280d..dc28e0e0a2 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -34,6 +34,7 @@ HEADERS += \
tools/qlocale_p.h \
tools/qlocale_tools_p.h \
tools/qlocale_data_p.h \
+ tools/qmakearray_p.h \
tools/qmap.h \
tools/qmargins.h \
tools/qmessageauthenticationcode.h \
@@ -45,6 +46,7 @@ HEADERS += \
tools/qregexp.h \
tools/qringbuffer_p.h \
tools/qrefcount.h \
+ tools/qscopeguard.h \
tools/qscopedpointer.h \
tools/qscopedpointer_p.h \
tools/qscopedvaluerollback.h \
@@ -126,7 +128,6 @@ else:unix {
}
else:win32 {
SOURCES += tools/qlocale_win.cpp
- winrt-*-msvc2013: LIBS += advapi32.lib
} else:integrity {
SOURCES += tools/qlocale_unix.cpp
}
@@ -159,16 +160,18 @@ qtConfig(timezone) {
SOURCES += \
tools/qtimezone.cpp \
tools/qtimezoneprivate.cpp
- !nacl:darwin: \
+ !nacl:darwin: {
SOURCES += tools/qtimezoneprivate_mac.mm
- else: android:!android-embedded: \
+ } else: android:!android-embedded: {
SOURCES += tools/qtimezoneprivate_android.cpp
- else: unix: \
+ } else: unix: {
SOURCES += tools/qtimezoneprivate_tz.cpp
- else: win32: \
- SOURCES += tools/qtimezoneprivate_win.cpp
- qtConfig(icu): \
+ qtConfig(icu): SOURCES += tools/qtimezoneprivate_icu.cpp
+ } else: qtConfig(icu): {
SOURCES += tools/qtimezoneprivate_icu.cpp
+ } else: win32: {
+ SOURCES += tools/qtimezoneprivate_win.cpp
+ }
}
qtConfig(datetimeparser) {
@@ -179,7 +182,8 @@ qtConfig(datetimeparser) {
qtConfig(regularexpression) {
QMAKE_USE_PRIVATE += pcre2
- HEADERS += tools/qregularexpression.h
+ HEADERS += \
+ tools/qregularexpression.h
SOURCES += tools/qregularexpression.cpp
}
@@ -216,7 +220,7 @@ qtConfig(system-doubleconversion) {
}
# Note: libm should be present by default becaue this is C++
-unix:!macx-icc:!vxworks:!haiku:!integrity: LIBS_PRIVATE += -lm
+unix:!macx-icc:!vxworks:!haiku:!integrity:!wasm: LIBS_PRIVATE += -lm
TR_EXCLUDE += ../3rdparty/*
diff --git a/src/dbus/dbus_minimal_p.h b/src/dbus/dbus_minimal_p.h
index b52b0153e4..869c02b59d 100644
--- a/src/dbus/dbus_minimal_p.h
+++ b/src/dbus/dbus_minimal_p.h
@@ -218,7 +218,7 @@ struct DBusMessageIter
int dummy10; /**< Don't use this */
int dummy11; /**< Don't use this */
int pad1; /**< Don't use this */
- int pad2; /**< Don't use this */
+ void *pad2; /**< Don't use this */ /* Was int; changed to void* at 1.10.8 */
void *pad3; /**< Don't use this */
};
@@ -251,6 +251,7 @@ struct DBusMessageIter
#define DBUS_TYPE_SIGNATURE_AS_STRING "g"
#define DBUS_TYPE_UNIX_FD ((int) 'h')
#define DBUS_TYPE_UNIX_FD_AS_STRING "h"
+
#define DBUS_TYPE_ARRAY ((int) 'a')
#define DBUS_TYPE_ARRAY_AS_STRING "a"
#define DBUS_TYPE_VARIANT ((int) 'v')
@@ -270,14 +271,14 @@ struct DBusMessageIter
#define DBUS_DICT_ENTRY_END_CHAR ((int) '}')
#define DBUS_DICT_ENTRY_END_CHAR_AS_STRING "}"
+#define DBUS_MAXIMUM_NAME_LENGTH 255
+
#define DBUS_MESSAGE_TYPE_INVALID 0
#define DBUS_MESSAGE_TYPE_METHOD_CALL 1
#define DBUS_MESSAGE_TYPE_METHOD_RETURN 2
#define DBUS_MESSAGE_TYPE_ERROR 3
#define DBUS_MESSAGE_TYPE_SIGNAL 4
-#define DBUS_MAXIMUM_NAME_LENGTH 255
-
#define DBUS_INTROSPECT_1_0_XML_NAMESPACE "http://www.freedesktop.org/standards/dbus"
#define DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
#define DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"
diff --git a/src/dbus/qdbus_symbols.cpp b/src/dbus/qdbus_symbols.cpp
index 1e93a46c0c..f22696639d 100644
--- a/src/dbus/qdbus_symbols.cpp
+++ b/src/dbus/qdbus_symbols.cpp
@@ -79,10 +79,8 @@ bool qdbus_loadLibDBus()
#endif
static bool triedToLoadLibrary = false;
-#ifndef QT_NO_THREAD
static QBasicMutex mutex;
QMutexLocker locker(&mutex);
-#endif
QLibrary *&lib = qdbus_libdbus;
if (triedToLoadLibrary)
@@ -126,14 +124,16 @@ bool qdbus_loadLibDBus()
#endif
}
-#if QT_CONFIG(library)
void (*qdbus_resolve_conditionally(const char *name))()
{
+#if QT_CONFIG(library)
if (qdbus_loadLibDBus())
return qdbus_libdbus->resolve(name);
+#else
+ Q_UNUSED(name);
+#endif
return 0;
}
-#endif
void (*qdbus_resolve_me(const char *name))()
{
diff --git a/src/dbus/qdbus_symbols_p.h b/src/dbus/qdbus_symbols_p.h
index 9eaebe6d7e..7cce0d71aa 100644
--- a/src/dbus/qdbus_symbols_p.h
+++ b/src/dbus/qdbus_symbols_p.h
@@ -161,6 +161,19 @@ template <> struct TraceReturn<void> { typedef void Type; };
funcret DEBUGRET(ret) ptr argcall; \
}
+# define DEFINEFUNC_CONDITIONALLY(ret, func, args, argcall, funcret, failret) \
+ typedef ret (* _q_PTR_##func) args; \
+ static inline ret q_##func args \
+ { \
+ static _q_PTR_##func ptr; \
+ DEBUGCALL(#func, argcall); \
+ if (!ptr) \
+ ptr = (_q_PTR_##func) qdbus_resolve_conditionally(#func); \
+ if (!ptr) \
+ failret; \
+ funcret DEBUGRET(ret) ptr argcall; \
+ }
+
#else // defined QT_LINKED_LIBDBUS
inline bool qdbus_loadLibDBus() { return true; }
@@ -300,6 +313,26 @@ DEFINEFUNC(const char* , dbus_message_get_signature, (DBusMessage *message),
(message), return)
DEFINEFUNC(int , dbus_message_get_type, (DBusMessage *message),
(message), return)
+
+#if !defined QT_LINKED_LIBDBUS
+
+DEFINEFUNC_CONDITIONALLY(dbus_bool_t , dbus_message_get_allow_interactive_authorization, (DBusMessage *message),
+ (message), return, return false)
+
+#else // defined QT_LINKED_LIBDBUS
+
+static inline dbus_bool_t q_dbus_message_get_allow_interactive_authorization(DBusMessage *message)
+{
+#ifdef DBUS_HEADER_FLAG_ALLOW_INTERACTIVE_AUTHORIZATION
+ return dbus_message_get_allow_interactive_authorization(message);
+#else
+ Q_UNUSED(message);
+ return false;
+#endif
+}
+
+#endif // defined QT_LINKED_LIBDBUS
+
DEFINEFUNC(dbus_bool_t , dbus_message_iter_append_basic, (DBusMessageIter *iter,
int type,
const void *value),
@@ -378,9 +411,33 @@ DEFINEFUNC(dbus_bool_t , dbus_message_set_sender, (DBusMessage *message,
DEFINEFUNC(void , dbus_message_unref, (DBusMessage *message),
(message), )
+#if !defined QT_LINKED_LIBDBUS
+
+DEFINEFUNC_CONDITIONALLY(void, dbus_message_set_allow_interactive_authorization,
+ (DBusMessage *message, dbus_bool_t allow), (message, allow), return, return)
+
+
+#else // defined QT_LINKED_LIBDBUS
+
+static inline void q_dbus_message_set_allow_interactive_authorization(DBusMessage *message, dbus_bool_t allow)
+{
+#ifdef DBUS_HEADER_FLAG_ALLOW_INTERACTIVE_AUTHORIZATION
+ dbus_message_set_allow_interactive_authorization(message, allow);
+#else
+ Q_UNUSED(message);
+ Q_UNUSED(allow);
+#endif
+}
+
+#endif // defined QT_LINKED_LIBDBUS
+
/* dbus-misc.h */
DEFINEFUNC(char* , dbus_get_local_machine_id , (void), (), return)
+DEFINEFUNC(void , dbus_get_version , (int *major_version, int *minor_version, int *micro_version)
+ , (major_version, minor_version, micro_version)
+ , return)
+
/* dbus-pending-call.h */
DEFINEFUNC(dbus_bool_t , dbus_pending_call_set_notify, (DBusPendingCall *pending,
diff --git a/src/dbus/qdbusmessage.cpp b/src/dbus/qdbusmessage.cpp
index ef827e82b0..3e8f2eaf3f 100644
--- a/src/dbus/qdbusmessage.cpp
+++ b/src/dbus/qdbusmessage.cpp
@@ -70,7 +70,8 @@ static inline const char *data(const QByteArray &arr)
QDBusMessagePrivate::QDBusMessagePrivate()
: msg(0), reply(0), localReply(0), ref(1), type(QDBusMessage::InvalidMessage),
delayedReply(false), localMessage(false),
- parametersValidated(false), autoStartService(true)
+ parametersValidated(false), autoStartService(true),
+ interactiveAuthorizationAllowed(false)
{
}
@@ -138,6 +139,8 @@ DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message, QDB
msg = q_dbus_message_new_method_call(data(d_ptr->service.toUtf8()), d_ptr->path.toUtf8(),
data(d_ptr->interface.toUtf8()), d_ptr->name.toUtf8());
q_dbus_message_set_auto_start( msg, d_ptr->autoStartService );
+ q_dbus_message_set_allow_interactive_authorization(msg, d_ptr->interactiveAuthorizationAllowed);
+
break;
case QDBusMessage::ReplyMessage:
msg = q_dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
@@ -242,6 +245,7 @@ QDBusMessage QDBusMessagePrivate::fromDBusMessage(DBusMessage *dmsg, QDBusConnec
QString::fromUtf8(q_dbus_message_get_member(dmsg));
message.d_ptr->service = QString::fromUtf8(q_dbus_message_get_sender(dmsg));
message.d_ptr->signature = QString::fromUtf8(q_dbus_message_get_signature(dmsg));
+ message.d_ptr->interactiveAuthorizationAllowed = q_dbus_message_get_allow_interactive_authorization(dmsg);
message.d_ptr->msg = q_dbus_message_ref(dmsg);
QDBusDemarshaller demarshaller(capabilities);
@@ -725,6 +729,44 @@ bool QDBusMessage::autoStartService() const
}
/*!
+ Sets the interactive authorization flag to \a enable.
+ This flag only makes sense for method call messages, where it
+ tells the D-Bus server that the caller of the method is prepared
+ to wait for interactive authorization to take place (for instance
+ via Polkit) before the actual method is processed.
+
+ By default this flag is false and the other end is expected to
+ make any authorization decisions non-interactively and promptly.
+
+ The \c org.freedesktop.DBus.Error.InteractiveAuthorizationRequired
+ error indicates that authorization failed, but could have succeeded
+ if this flag had been set.
+
+ \sa isInteractiveAuthorizationAllowed()
+
+ \since 5.12
+*/
+void QDBusMessage::setInteractiveAuthorizationAllowed(bool enable)
+{
+ d_ptr->interactiveAuthorizationAllowed = enable;
+}
+
+/*!
+ Returns the interactive authorization allowed flag, as set by
+ setInteractiveAuthorizationAllowed(). By default this flag
+ is false and the other end is expected to make any authorization
+ decisions non-interactively and promptly.
+
+ \sa setInteractiveAuthorizationAllowed()
+
+ \since 5.12
+*/
+bool QDBusMessage::isInteractiveAuthorizationAllowed() const
+{
+ return d_ptr->interactiveAuthorizationAllowed;
+}
+
+/*!
Sets the arguments that are going to be sent over D-Bus to \a arguments. Those
will be the arguments to a method call or the parameters in the signal.
diff --git a/src/dbus/qdbusmessage.h b/src/dbus/qdbusmessage.h
index 9f4a98b855..23e04045d8 100644
--- a/src/dbus/qdbusmessage.h
+++ b/src/dbus/qdbusmessage.h
@@ -119,6 +119,9 @@ public:
void setAutoStartService(bool enable);
bool autoStartService() const;
+ void setInteractiveAuthorizationAllowed(bool enable);
+ bool isInteractiveAuthorizationAllowed() const;
+
void setArguments(const QList<QVariant> &arguments);
QList<QVariant> arguments() const;
diff --git a/src/dbus/qdbusmessage_p.h b/src/dbus/qdbusmessage_p.h
index 4b84b3f0cc..f921c33832 100644
--- a/src/dbus/qdbusmessage_p.h
+++ b/src/dbus/qdbusmessage_p.h
@@ -87,6 +87,7 @@ public:
uint localMessage : 1;
mutable uint parametersValidated : 1;
uint autoStartService : 1;
+ uint interactiveAuthorizationAllowed : 1;
static void setParametersValidated(QDBusMessage &msg, bool enable)
{ msg.d_ptr->parametersValidated = enable; }
diff --git a/src/dbus/qdbusmetaobject.cpp b/src/dbus/qdbusmetaobject.cpp
index f64e30b49b..c4296f5c55 100644
--- a/src/dbus/qdbusmetaobject.cpp
+++ b/src/dbus/qdbusmetaobject.cpp
@@ -412,7 +412,7 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
- methods.count(); // ditto
QDBusMetaObjectPrivate *header = reinterpret_cast<QDBusMetaObjectPrivate *>(idata.data());
- Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 7, "QtDBus meta-object generator should generate the same version as moc");
+ Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 8, "QtDBus meta-object generator should generate the same version as moc");
header->revision = QMetaObjectPrivate::OutputRevision;
header->className = 0;
header->classInfoCount = 0;
diff --git a/src/dbus/qt_attribution.json b/src/dbus/qt_attribution.json
index 52636ba89b..69d946ba5c 100644
--- a/src/dbus/qt_attribution.json
+++ b/src/dbus/qt_attribution.json
@@ -6,9 +6,12 @@
"Description": "D-Bus is a message bus system, a simple way for applications to talk to one another.",
"Homepage": "https://www.freedesktop.org/wiki/Software/dbus/",
+ "Version": "Minimal supported is 1.2, compatible up to ...",
+ "Version": "1.12",
"LicenseId": "AFL-2.1 OR GPL-2.0-or-later",
"License": "Academic Free License v2.1, or GNU General Public License v2.0 or later",
"LicenseFile": "LIBDBUS-1-LICENSE.txt",
+ "Files": "Fragments from various upstream files, see comments in ...",
"Files": "dbus_minimal_p.h",
"Copyright": "Copyright (C) 2002, 2003 CodeFactory AB
Copyright (C) 2004, 2005 Red Hat, Inc."
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index d60a21606b..a3f53e149b 100644
--- a/src/gui/accessible/qaccessible.cpp
+++ b/src/gui/accessible/qaccessible.cpp
@@ -202,7 +202,7 @@ Q_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core");
This enum type defines accessible event types.
- \omitvalue InvalidEvent Internal: Used when creating subclasses of QAccessibleEvent.
+ \omitvalue InvalidEvent \omit Internal: Used when creating subclasses of QAccessibleEvent. \endomit
\value AcceleratorChanged The keyboard accelerator for an action has been changed.
\value ActionChanged An action has been changed.
\value ActiveDescendantChanged
@@ -273,27 +273,27 @@ Q_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core");
\value SelectionWithin Several changes to a selection has occurred in an item
view.
\value SoundPlayed A sound has been played by an object
- \omitvalue StateChanged The QAccessible::State of an object has changed.
- This value is used internally for the QAccessibleStateChangeEvent.
+ \omitvalue StateChanged \omit The QAccessible::State of an object has changed.
+ This value is used internally for the QAccessibleStateChangeEvent. \endomit
\value TableCaptionChanged A table caption has been changed.
\value TableColumnDescriptionChanged The description of a table column, typically found in
the column's header, has been changed.
\value TableColumnHeaderChanged A table column header has been changed.
- \omitvalue TableModelChanged The model providing data for a table has been changed.
+ \omitvalue TableModelChanged \omit The model providing data for a table has been changed. \endomit
\value TableRowDescriptionChanged The description of a table row, typically found in the
row's header, has been changed.
\value TableRowHeaderChanged A table row header has been changed.
\value TableSummaryChanged The summary of a table has been changed.
\omitvalue TextAttributeChanged
- \omitvalue TextCaretMoved The caret has moved in an editable widget.
+ \omitvalue TextCaretMoved \omit The caret has moved in an editable widget.
The caret represents the cursor position in an editable
- widget with the input focus.
+ widget with the input focus. \endomit
\value TextColumnChanged A text column has been changed.
- \omitvalue TextInserted Text has been inserted into an editable widget.
- \omitvalue TextRemoved Text has been removed from an editable widget.
- \omitvalue TextSelectionChanged The selected text has changed in an editable widget.
- \omitvalue TextUpdated The text has been update in an editable widget.
- \omitvalue ValueChanged The QAccessible::Value of an object has changed.
+ \omitvalue TextInserted \omit Text has been inserted into an editable widget. \endomit
+ \omitvalue TextRemoved \omit Text has been removed from an editable widget. \endomit
+ \omitvalue TextSelectionChanged \omit The selected text has changed in an editable widget. \endomit
+ \omitvalue TextUpdated \omit The text has been update in an editable widget. \endomit
+ \omitvalue ValueChanged \omit The QAccessible::Value of an object has changed. \endomit
\value VisibleDataChanged
The values for this enum are defined to be the same as those defined in the
@@ -441,10 +441,10 @@ Q_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core");
\note When subclassing one of these interfaces, \l QAccessibleInterface::interface_cast() needs to be implemented.
\value TextInterface For text that supports selections or is more than one line. Simple labels do not need to implement this interface.
- \omitvalue EditableTextInterface For text that can be edited by the user.
+ \omitvalue EditableTextInterface \omit For text that can be edited by the user. \endomit
\value ValueInterface For objects that are used to manipulate a value, for example slider or scroll bar.
\value ActionInterface For interactive objects that allow the user to trigger an action. Basically everything that allows for example mouse interaction.
- \omitvalue ImageInterface For objects that represent an image. This interface is generally less important.
+ \omitvalue ImageInterface \omit For objects that represent an image. This interface is generally less important. \endomit
\value TableInterface For lists, tables and trees.
\value TableCellInterface For cells in a TableInterface object.
@@ -1309,14 +1309,7 @@ QColor QAccessibleInterface::backgroundColor() const
For example to notify about a focus change when re-implementing QWidget::setFocus,
the event could be used as follows:
- \code
- void MyWidget::setFocus(Qt::FocusReason reason)
- {
- // handle custom focus setting...
- QAccessibleEvent event(f, QAccessible::Focus);
- QAccessible::updateAccessibility(&event);
- }
- \endcode
+ \snippet code/src_gui_accessible_qaccessible.cpp 2
To enable in process screen readers, all events must be sent after the change has happened.
*/
@@ -1826,14 +1819,7 @@ void QAccessibleInterface::virtual_hook(int /*id*/, void * /*data*/)
Qt's QLineEdit for example has its accessibility support
implemented in QAccessibleLineEdit.
- \code
-void *QAccessibleLineEdit::interface_cast(QAccessible::InterfaceType t)
-{
- if (t == QAccessible::TextInterface)
- return static_cast<QAccessibleTextInterface*>(this);
- return QAccessibleWidget::interface_cast(t);
-}
- \endcode
+ \snippet code/src_gui_accessible_qaccessible.cpp 3
\sa QAccessible::InterfaceType, QAccessibleTextInterface,
QAccessibleValueInterface, QAccessibleActionInterface,
diff --git a/src/gui/accessible/qaccessiblecache.cpp b/src/gui/accessible/qaccessiblecache.cpp
index f4242036ce..20376a54c4 100644
--- a/src/gui/accessible/qaccessiblecache.cpp
+++ b/src/gui/accessible/qaccessiblecache.cpp
@@ -38,11 +38,15 @@
****************************************************************************/
#include "qaccessiblecache_p.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qloggingcategory.h>
#ifndef QT_NO_ACCESSIBILITY
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcAccessibilityCache, "qt.accessibility.cache");
+
/*!
\class QAccessibleCache
\internal
@@ -57,6 +61,12 @@ static void cleanupAccessibleCache()
accessibleCache = nullptr;
}
+QAccessibleCache::~QAccessibleCache()
+{
+ for (QAccessible::Id id: idToInterface.keys())
+ deleteInterface(id);
+}
+
QAccessibleCache *QAccessibleCache::instance()
{
if (!accessibleCache) {
@@ -116,6 +126,7 @@ QAccessible::Id QAccessibleCache::insert(QObject *object, QAccessibleInterface *
}
idToInterface.insert(id, iface);
interfaceToId.insert(iface, id);
+ qCDebug(lcAccessibilityCache) << "insert - id:" << id << " iface:" << iface;
return id;
}
@@ -131,6 +142,9 @@ void QAccessibleCache::objectDestroyed(QObject* obj)
void QAccessibleCache::deleteInterface(QAccessible::Id id, QObject *obj)
{
QAccessibleInterface *iface = idToInterface.take(id);
+ qCDebug(lcAccessibilityCache) << "delete - id:" << id << " iface:" << iface;
+ if (!iface) // the interface may be deleted already
+ return;
interfaceToId.take(iface);
if (!obj)
obj = iface->object();
diff --git a/src/gui/accessible/qaccessiblecache_p.h b/src/gui/accessible/qaccessiblecache_p.h
index f054ee9678..a976277c1d 100644
--- a/src/gui/accessible/qaccessiblecache_p.h
+++ b/src/gui/accessible/qaccessiblecache_p.h
@@ -68,6 +68,7 @@ class Q_GUI_EXPORT QAccessibleCache :public QObject
Q_OBJECT
public:
+ ~QAccessibleCache() override;
static QAccessibleCache *instance();
QAccessibleInterface *interfaceForId(QAccessible::Id id) const;
QAccessible::Id idForInterface(QAccessibleInterface *iface) const;
diff --git a/src/gui/configure.json b/src/gui/configure.json
index 219385a108..0332631ec8 100644
--- a/src/gui/configure.json
+++ b/src/gui/configure.json
@@ -44,7 +44,7 @@
"xcb": { "type": "enum", "values": [ "no", "yes", "qt", "system" ] },
"xcb-native-painting": "boolean",
"xcb-xlib": "boolean",
- "xinput2": "boolean",
+ "xcb-xinput": "boolean",
"xkb": "boolean",
"xkbcommon": { "type": "enum", "values": [ "no", "qt", "system" ] },
"xkbcommon-evdev": "boolean",
@@ -114,11 +114,16 @@
"drm": {
"label": "KMS",
"test": {
- "include": [ "stdlib.h", "stdint.h" ],
+ "head": [
+ "#include <stdlib.h>",
+ "#include <stdint.h>",
+ "extern \"C\" {"
+ ],
+ "include": [
+ "xf86drmMode.h",
+ "xf86drm.h"
+ ],
"tail": [
- "extern \"C\" {",
- "#include <xf86drmMode.h>",
- "#include <xf86drm.h>",
"}"
],
"main": "(void) drmModeGetCrtc(0, 0);"
@@ -146,8 +151,8 @@
"freetype": {
"label": "FreeType",
"test": {
- "head": [
- "#include <ft2build.h>",
+ "include": "ft2build.h",
+ "tail": [
"#include FT_FREETYPE_H",
"#if ((FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) < 20200)",
"# error This version of freetype is too old.",
@@ -159,14 +164,15 @@
},
"sources": [
{ "type": "pkgConfig", "args": "freetype2" },
- { "type": "freetype", "libs": "-lfreetype" }
+ { "type": "freetype", "libs": "-lfreetype", "condition": "!config.wasm" },
+ { "type": "freetype", "libs": "-s USE_FREETYPE=1", "condition": "config.wasm" }
]
},
"fontconfig": {
"label": "Fontconfig",
"test": {
- "head": [
- "#include <fontconfig/fontconfig.h>",
+ "include": "fontconfig/fontconfig.h",
+ "tail": [
"#ifndef FC_RGBA_UNKNOWN",
"# error This version of fontconfig is tool old, it is missing the FC_RGBA_UNKNOWN define",
"#endif"
@@ -184,10 +190,13 @@
"gbm": {
"label": "GBM",
"test": {
- "include": [ "stdlib.h", "stdint.h" ],
+ "head": [
+ "#include <stdlib.h>",
+ "#include <stdint.h>",
+ "extern \"C\" {"
+ ],
+ "include": "gbm.h",
"tail": [
- "extern \"C\" {",
- "#include <gbm.h>",
"}"
],
"main": "gbm_surface *surface = 0;"
@@ -252,7 +261,11 @@
"integrityhid": {
"label": "integrityhid",
"test": {
- "include": [ "stdlib.h", "stdint.h", "device/hiddriver.h" ],
+ "head": [
+ "#include <stdlib.h>",
+ "#include <stdint.h>"
+ ],
+ "include": "device/hiddriver.h",
"main": [
"HIDDriver *driver;",
"uintptr_t devicecontext;",
@@ -267,10 +280,13 @@
"libjpeg": {
"label": "libjpeg",
"test": {
- "include": [ "sys/types.h", "stdio.h" ],
+ "head": [
+ "#include <sys/types.h>",
+ "#include <stdio.h>",
+ "extern \"C\" {"
+ ],
+ "include": "jpeglib.h",
"tail": [
- "extern \"C\" {",
- "#include <jpeglib.h>",
"}",
"",
"j_compress_ptr cinfo;"
@@ -279,7 +295,7 @@
},
"sources": [
{ "libs": "-llibjpeg", "condition": "config.msvc" },
- { "libs": "-ljpeg", "condition": "!config.msvc" }
+ "-ljpeg"
]
},
"libpng": {
@@ -290,8 +306,11 @@
},
"sources": [
{ "type": "pkgConfig", "args": "libpng" },
+ { "libs": "-llibpng16", "condition": "config.msvc" },
{ "libs": "-llibpng", "condition": "config.msvc" },
- { "libs": "-lpng", "condition": "!config.msvc" }
+ { "libs": "-lpng16", "condition": "!config.msvc" },
+ { "libs": "-lpng", "condition": "!config.msvc" },
+ { "libs": "-s USE_LIBPNG=1", "condition": "config.wasm" }
],
"use": [
{ "lib": "zlib", "condition": "features.system-zlib" }
@@ -393,13 +412,15 @@
"v4l2": {
"label": "V4L2",
"test": {
+ "head": [
+ "#include <cstddef>",
+ "extern \"C\" {"
+ ],
"include": [
- "cstddef"
+ "mediactl/mediactl.h",
+ "mediactl/v4l2subdev.h"
],
"tail": [
- "extern \"C\" {",
- "#include <mediactl/mediactl.h>",
- "#include <mediactl/v4l2subdev.h>",
"}"
],
"main": [
@@ -439,18 +460,18 @@
]
},
"xcb": {
- "label": "XCB >= 1.5 (core)",
+ "label": "XCB >= 1.9 (core)",
"test": {
"include": "xcb/xcb.h",
"main": [
"int primaryScreen = 0;",
"(void)xcb_connect(\"\", &primaryScreen);",
- "// This won't compile unless libxcb >= 1.5 which defines XCB_ATOM_PRIMARY.",
- "int xcbAtomPrimary = XCB_ATOM_PRIMARY;"
+ "// This won't compile unless libxcb >= 1.9 which defines XCB_CONN_CLOSED_INVALID_SCREEN.",
+ "int xcbScreenError = XCB_CONN_CLOSED_INVALID_SCREEN;"
]
},
"sources": [
- { "type": "pkgConfig", "args": "xcb >= 1.5" },
+ { "type": "pkgConfig", "args": "xcb >= 1.9" },
"-lxcb"
]
},
@@ -566,33 +587,22 @@
"-lxcb-glx -lxcb"
]
},
- "xinput2": {
- "label": "Xinput2",
+ "xcb_xinput": {
+ "label": "XCB XInput",
"test": {
- "include": [ "X11/Xlib.h", "X11/extensions/XInput2.h", "X11/extensions/Xge.h" ],
- "tail": [
- "#ifndef XInput_2_0",
- "# error Missing XInput_2_0 #define",
- "#endif"
- ],
+ "include": [ "xcb/xcb.h", "xcb/xinput.h" ],
"main": [
- "// need XGenericEventCookie for XInput2 to work",
- "Display *dpy = 0;",
- "XEvent xevent;",
- "XIEvent *xievent = 0;",
- "XIDeviceEvent *xideviceevent = 0;",
- "XIHierarchyEvent *xihierarchyevent = 0;",
- "int deviceid = 0;",
- "int len = 0;",
- "(void) XGetEventData(dpy, &xevent.xcookie);",
- "XFreeEventData(dpy, &xevent.xcookie);",
- "(void) XIListProperties(dpy, deviceid, &len);"
- ],
- "qmake": "CONFIG += x11"
+ "int primaryScreen = 0;",
+ "xcb_connection_t *connection = xcb_connect(\"\", &primaryScreen);",
+ "xcb_generic_error_t *error = 0;",
+ "xcb_input_xi_query_version_cookie_t xinput_query_cookie = xcb_input_xi_query_version(",
+ " connection, XCB_INPUT_MAJOR_VERSION, XCB_INPUT_MINOR_VERSION);",
+ "xcb_input_xi_query_version_reply(connection, xinput_query_cookie, &error);"
+ ]
},
"sources": [
- { "type": "pkgConfig", "args": "xi" },
- "-lXi"
+ { "type": "pkgConfig", "args": "xcb-xinput >= 1.12 xcb" },
+ "-lxcb-xinput -lxcb"
]
},
"xkbcommon": {
@@ -661,6 +671,26 @@
"fxc.exe"
]
},
+ "drm_atomic": {
+ "label": "DRM Atomic API",
+ "type": "compile",
+ "test": {
+ "head": [
+ "#include <stdlib.h>",
+ "#include <stdint.h>",
+ "extern \"C\" {"
+ ],
+ "include": [
+ "xf86drmMode.h",
+ "xf86drm.h"
+ ],
+ "tail": [
+ "}"
+ ],
+ "main": "drmModeAtomicReq *request;"
+ },
+ "use": "drm"
+ },
"egl-x11": {
"label": "EGL on X11",
"type": "compile",
@@ -953,7 +983,7 @@
},
"evdev": {
"label": "evdev",
- "condition": "tests.evdev",
+ "condition": "features.thread && tests.evdev",
"output": [ "privateFeature" ]
},
"freetype": {
@@ -1010,6 +1040,11 @@
"condition": "libs.drm",
"output": [ "publicQtConfig", "privateFeature" ]
},
+ "drm_atomic": {
+ "label": "DRM Atomic API",
+ "condition": "libs.drm && tests.drm_atomic",
+ "output": [ "privateFeature" ]
+ },
"libinput": {
"label": "libinput",
"condition": "features.libudev && libs.libinput",
@@ -1078,7 +1113,7 @@
},
"opengles3": {
"label": "OpenGL ES 3.0",
- "condition": "features.opengles2 && !features.angle && tests.opengles3",
+ "condition": "features.opengles2 && !features.angle && tests.opengles3 && !config.wasm",
"output": [
"publicFeature",
{ "type": "define", "name": "QT_OPENGL_ES_3" }
@@ -1105,7 +1140,7 @@
"enable": "input.opengl == 'desktop'",
"disable": "input.opengl == 'es2' || input.opengl == 'dynamic' || input.opengl == 'no'",
"condition": "(config.win32 && !config.winrt && !features.opengles2 && (config.msvc || libs.opengl))
- || (!config.watchos && !config.win32 && libs.opengl)"
+ || (!config.watchos && !config.win32 && !config.wasm && libs.opengl)"
},
"opengl-dynamic": {
"label": "Dynamic OpenGL",
@@ -1139,7 +1174,7 @@
},
"egl_x11": {
"label": "EGL on X11",
- "condition": "features.egl && tests.egl-x11",
+ "condition": "features.thread && features.egl && tests.egl-x11",
"output": [ "privateFeature" ]
},
"eglfs": {
@@ -1269,7 +1304,7 @@
"section": "Platform plugins",
"autoDetect": "!config.darwin",
"enable": "input.xcb == 'system' || input.xcb == 'qt' || input.xcb == 'yes'",
- "condition": "libs.xcb",
+ "condition": "features.thread && libs.xcb",
"output": [ "privateFeature" ]
},
"system-xcb": {
@@ -1327,10 +1362,10 @@
"condition": "features.sessionmanager && libs.x11sm",
"output": [ "privateFeature" ]
},
- "xinput2": {
- "label": "Xinput2",
+ "xcb-xinput": {
+ "label": "XCB XInput",
"emitIf": "features.xcb",
- "condition": "features.xcb-xlib && libs.xinput2",
+ "condition": "!features.system-xcb || libs.xcb_xinput",
"output": [ "privateFeature" ]
},
"xkbcommon-evdev": {
@@ -1542,7 +1577,7 @@
},
"multiprocess": {
"label": "Multi process",
- "description": "Provides support for detecting the desktop environment, launching external processes and opening URLs.",
+ "purpose": "Provides support for detecting the desktop environment, launching external processes and opening URLs.",
"section": "Utilities",
"condition": "!config.integrity",
"output": [ "privateFeature" ]
@@ -1701,7 +1736,7 @@ QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your pla
"section": "X11",
"condition": "features.xcb",
"entries": [
- "system-xcb", "egl_x11", "xinput2", "xkb", "xlib", "xcb-render", "xcb-glx", "xcb-xlib", "xkbcommon-system", "xcb-native-painting"
+ "system-xcb", "egl_x11", "xkb", "xlib", "xcb-render", "xcb-glx", "xcb-xinput", "xcb-xlib", "xkbcommon-system", "xcb-native-painting"
]
},
{
diff --git a/src/gui/configure.pri b/src/gui/configure.pri
index fcd2d1f73e..2971fd136e 100644
--- a/src/gui/configure.pri
+++ b/src/gui/configure.pri
@@ -7,7 +7,7 @@ defineTest(qtConfLibrary_freetype) {
for (p, TRY_INCLUDEPATHS) {
includedir = $$p/freetype2
exists($$includedir) {
- $${1}.includedir = "$$val_escape(includedir)"
+ $${1}.includedir = $$includedir
export($${1}.includedir)
return(true)
}
@@ -55,6 +55,7 @@ defineTest(qtConfTest_qpaDefaultPlatform) {
else: qnx: name = qnx
else: integrity: name = integrityfb
else: haiku: name = haiku
+ else: wasm: name = webassembly
else: name = xcb
$${1}.value = $$name
diff --git a/src/gui/doc/qtgui.qdocconf b/src/gui/doc/qtgui.qdocconf
index e1afa426ed..e546c817a7 100644
--- a/src/gui/doc/qtgui.qdocconf
+++ b/src/gui/doc/qtgui.qdocconf
@@ -60,3 +60,6 @@ manifestmeta.highlighted.names = "QtGui/Analog Clock Window Example"
navigation.landingpage = "Qt GUI"
navigation.cppclassespage = "Qt GUI C++ Classes"
+
+# Ignore warnings about undocumented enum values for the QGradient presets
+spurious += "Undocumented enum item '.*' in QGradient::Preset"
diff --git a/src/gui/doc/snippets/code/src_gui_accessible_qaccessible.cpp b/src/gui/doc/snippets/code/src_gui_accessible_qaccessible.cpp
index 98d40c94f9..2fd76d08c7 100644
--- a/src/gui/doc/snippets/code/src_gui_accessible_qaccessible.cpp
+++ b/src/gui/doc/snippets/code/src_gui_accessible_qaccessible.cpp
@@ -51,3 +51,21 @@
//! [1]
typedef QAccessibleInterface* myFactoryFunction(const QString &key, QObject *);
//! [1]
+
+//! [2]
+void MyWidget::setFocus(Qt::FocusReason reason)
+{
+ // handle custom focus setting...
+ QAccessibleEvent event(f, QAccessible::Focus);
+ QAccessible::updateAccessibility(&event);
+}
+//! [2]
+
+//! [3]
+void *QAccessibleLineEdit::interface_cast(QAccessible::InterfaceType t)
+{
+ if (t == QAccessible::TextInterface)
+ return static_cast<QAccessibleTextInterface*>(this);
+ return QAccessibleWidget::interface_cast(t);
+}
+//! [3]
diff --git a/src/gui/doc/snippets/code/src_gui_math3d_qquaternion.cpp b/src/gui/doc/snippets/code/src_gui_math3d_qquaternion.cpp
new file mode 100644
index 0000000000..b5cd00d5aa
--- /dev/null
+++ b/src/gui/doc/snippets/code/src_gui_math3d_qquaternion.cpp
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+ QVector3D result = q.rotatedVector(vector);
+//! [0]
+
+//! [1]
+ QVector3D result = (q * QQuaternion(0, vector) * q.conjugated()).vector();
+//! [1]
diff --git a/src/gui/doc/snippets/code/src_gui_opengl_qopenglbuffer.cpp b/src/gui/doc/snippets/code/src_gui_opengl_qopenglbuffer.cpp
new file mode 100644
index 0000000000..4a4a6fe16d
--- /dev/null
+++ b/src/gui/doc/snippets/code/src_gui_opengl_qopenglbuffer.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+ QOpenGLBuffer buffer1(QOpenGLBuffer::IndexBuffer);
+ buffer1.create();
+
+ QOpenGLBuffer buffer2 = buffer1;
+//! [0]
+
+//! [1]
+ QOpenGLBuffer::release(QOpenGLBuffer::VertexBuffer);
+//! [1]
diff --git a/src/gui/doc/snippets/code/src_gui_opengl_qopengldebug.cpp b/src/gui/doc/snippets/code/src_gui_opengl_qopengldebug.cpp
new file mode 100644
index 0000000000..4ab84deb3e
--- /dev/null
+++ b/src/gui/doc/snippets/code/src_gui_opengl_qopengldebug.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWidgets module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+ GLenum error = GL_NO_ERROR;
+ do {
+ error = glGetError();
+ if (error != GL_NO_ERROR)
+ // handle the error
+ } while (error != GL_NO_ERROR);
+//! [0]
+
+//! [1]
+ QSurfaceFormat format;
+ // asks for a OpenGL 3.2 debug context using the Core profile
+ format.setMajorVersion(3);
+ format.setMinorVersion(2);
+ format.setProfile(QSurfaceFormat::CoreProfile);
+ format.setOption(QSurfaceFormat::DebugContext);
+
+ QOpenGLContext *context = new QOpenGLContext;
+ context->setFormat(format);
+ context->create();
+//! [1]
+
+//! [2]
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ QOpenGLDebugLogger *logger = new QOpenGLDebugLogger(this);
+
+ logger->initialize(); // initializes in the current context, i.e. ctx
+//! [2]
+
+//! [3]
+ ctx->hasExtension(QByteArrayLiteral("GL_KHR_debug"))
+//! [3]
+
+//! [4]
+ const QList<QOpenGLDebugMessage> messages = logger->loggedMessages();
+ for (const QOpenGLDebugMessage &message : messages)
+ qDebug() << message;
+//! [4]
+
+//! [5]
+ connect(logger, &QOpenGLDebugLogger::messageLogged, receiver, &LogHandler::handleLoggedMessage);
+ logger->startLogging();
+//! [5]
+
+//! [6]
+ QOpenGLDebugMessage message =
+ QOpenGLDebugMessage::createApplicationMessage(QStringLiteral("Custom message"));
+
+ logger->logMessage(message);
+//! [6]
diff --git a/src/gui/doc/snippets/code/src_gui_opengl_qopenglfunctions.cpp b/src/gui/doc/snippets/code/src_gui_opengl_qopenglfunctions.cpp
new file mode 100644
index 0000000000..68a20dcb7c
--- /dev/null
+++ b/src/gui/doc/snippets/code/src_gui_opengl_qopenglfunctions.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+ class MyGLWindow : public QWindow, protected QOpenGLFunctions
+ {
+ Q_OBJECT
+ public:
+ MyGLWindow(QScreen *screen = 0);
+
+ protected:
+ void initializeGL();
+ void paintGL();
+
+ QOpenGLContext *m_context;
+ };
+
+ MyGLWindow(QScreen *screen)
+ : QWindow(screen), QOpenGLWidget(parent)
+ {
+ setSurfaceType(OpenGLSurface);
+ create();
+
+ // Create an OpenGL context
+ m_context = new QOpenGLContext;
+ m_context->create();
+
+ // Setup scene and render it
+ initializeGL();
+ paintGL();
+ }
+
+ void MyGLWindow::initializeGL()
+ {
+ m_context->makeCurrent(this);
+ initializeOpenGLFunctions();
+ }
+//! [0]
+
+//! [1]
+ void MyGLWindow::paintGL()
+ {
+ m_context->makeCurrent(this);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, textureId);
+ ...
+ m_context->swapBuffers(this);
+ m_context->doneCurrent();
+ }
+//! [1]
+
+//! [2]
+ QOpenGLFunctions glFuncs(QOpenGLContext::currentContext());
+ glFuncs.glActiveTexture(GL_TEXTURE1);
+//! [2]
+
+//! [3]
+ QOpenGLFunctions *glFuncs = QOpenGLContext::currentContext()->functions();
+ glFuncs->glActiveTexture(GL_TEXTURE1);
+//! [3]
+
+//! [4]
+ QOpenGLFunctions funcs(QOpenGLContext::currentContext());
+ bool npot = funcs.hasOpenGLFeature(QOpenGLFunctions::NPOTTextures);
+//! [4]
diff --git a/src/gui/doc/snippets/code/src_gui_util_qdesktopservices.cpp b/src/gui/doc/snippets/code/src_gui_util_qdesktopservices.cpp
index b48e9e8610..b9a8d8d90e 100644
--- a/src/gui/doc/snippets/code/src_gui_util_qdesktopservices.cpp
+++ b/src/gui/doc/snippets/code/src_gui_util_qdesktopservices.cpp
@@ -68,3 +68,31 @@ mailto:user@foo.com?subject=Test&body=Just a test
//! [2]
QDesktopServices::openUrl(QUrl("file:///C:/Documents and Settings/All Users/Desktop", QUrl::TolerantMode));
//! [2]
+
+//! [3]
+<key>LSApplicationQueriesSchemes</key>
+<array>
+ <string>https</string>
+</array>
+//! [3]
+
+//! [4]
+<key>CFBundleURLTypes</key>
+<array>
+ <dict>
+ <key>CFBundleURLSchemes</key>
+ <array>
+ <string>myapp</string>
+ </array>
+ </dict>
+</array>
+//! [4]
+
+//! [5]
+QDesktopServices::storageLocation(QDesktopServices::DataLocation)
+//! [5]
+
+//! [6]
+QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) +
+ "/data/organization/application"
+//! [6]
diff --git a/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanfunctions.cpp b/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanfunctions.cpp
new file mode 100644
index 0000000000..77c5444df5
--- /dev/null
+++ b/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanfunctions.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+ void Window::render()
+ {
+ QVulkanInstance *inst = vulkanInstance();
+ QVulkanFunctions *f = inst->functions();
+ ...
+ VkResult err = f->vkAllocateCommandBuffers(device, &cmdBufInfo, &cmdBuf);
+ ...
+ }
+//! [0]
+
+//! [1]
+ void Window::render()
+ {
+ QVulkanInstance *inst = vulkanInstance();
+ QVulkanDeviceFunctions *df = inst->deviceFunctions(device);
+ VkResult err = df->vkAllocateCommandBuffers(device, &cmdBufInfo, &cmdBuf);
+ ...
+ }
+//! [1]
diff --git a/src/gui/doc/snippets/code/src_gui_vulkan_qvulkaninstance.cpp b/src/gui/doc/snippets/code/src_gui_vulkan_qvulkaninstance.cpp
new file mode 100644
index 0000000000..50afe7c0ff
--- /dev/null
+++ b/src/gui/doc/snippets/code/src_gui_vulkan_qvulkaninstance.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+ int main(int argc, char **argv)
+ {
+ QGuiApplication app(argc, argv);
+
+ QVulkanInstance inst;
+ if (!inst.create())
+ return 1;
+
+ ...
+ window->setVulkanInstance(&inst);
+ window->show();
+
+ return app.exec();
+ }
+//! [0]
+
+//! [1]
+ QVulkanInstance inst;
+
+ // Enable validation layer, if supported. Messages go to qDebug by default.
+ inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+
+ bool ok = inst.create();
+ if (!ok)
+ ... // Vulkan not available
+ if (!inst.layers().contains("VK_LAYER_LUNARG_standard_validation"))
+ ... // validation layer not available
+//! [1]
+
+//! [2]
+ QVulkanInstance inst;
+
+ if (inst.supportedLayers().contains("VK_LAYER_LUNARG_standard_validation"))
+ ...
+
+ bool ok = inst.create();
+ ...
+//! [2]
+
+//! [3]
+ class VulkanWindow : public QWindow
+ {
+ public:
+ VulkanWindow() {
+ setSurfaceType(VulkanSurface);
+ }
+
+ void exposeEvent(QExposeEvent *) {
+ if (isExposed()) {
+ if (!m_initialized) {
+ m_initialized = true;
+ // initialize device, swapchain, etc.
+ QVulkanInstance *inst = vulkanInstance();
+ QVulkanFunctions *f = inst->functions();
+ uint32_t devCount = 0;
+ f->vkEnumeratePhysicalDevices(inst->vkInstance(), &devCount, nullptr);
+ ...
+ // build the first frame
+ render();
+ }
+ }
+ }
+
+ bool event(QEvent *e) {
+ if (e->type == QEvent::UpdateRequest)
+ render();
+ return QWindow::event(e);
+ }
+
+ void render() {
+ ...
+ requestUpdate(); // render continuously
+ }
+
+ private:
+ bool m_initialized = false;
+ };
+
+ int main(int argc, char **argv)
+ {
+ QGuiApplication app(argc, argv);
+
+ QVulkanInstance inst;
+ if (!inst.create()) {
+ qWarning("Vulkan not available");
+ return 1;
+ }
+
+ VulkanWindow window;
+ window.showMaximized();
+
+ return app.exec();
+
+ }
+//! [3]
diff --git a/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanwindow.cpp b/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanwindow.cpp
new file mode 100644
index 0000000000..65eca4a77f
--- /dev/null
+++ b/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanwindow.cpp
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+ class VulkanRenderer : public QVulkanWindowRenderer
+ {
+ public:
+ VulkanRenderer(QVulkanWindow *w) : m_window(w) { }
+
+ void initResources() override
+ {
+ m_devFuncs = m_window->vulkanInstance()->deviceFunctions(m_window->device());
+ ...
+ }
+ void initSwapChainResources() override { ... }
+ void releaseSwapChainResources() override { ... }
+ void releaseResources() override { ... }
+
+ void startNextFrame() override
+ {
+ VkCommandBuffer cmdBuf = m_window->currentCommandBuffer();
+ ...
+ m_devFuncs->vkCmdBeginRenderPass(...);
+ ...
+ m_window->frameReady();
+ }
+
+ private:
+ QVulkanWindow *m_window;
+ QVulkanDeviceFunctions *m_devFuncs;
+ };
+
+ class VulkanWindow : public QVulkanWindow
+ {
+ public:
+ QVulkanWindowRenderer *createRenderer() override {
+ return new VulkanRenderer(this);
+ }
+ };
+
+ int main(int argc, char *argv[])
+ {
+ QGuiApplication app(argc, argv);
+
+ QVulkanInstance inst;
+ // enable the standard validation layers, when available
+ inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+ if (!inst.create())
+ qFatal("Failed to create Vulkan instance: %d", inst.errorCode());
+
+ VulkanWindow w;
+ w.setVulkanInstance(&inst);
+ w.showMaximized();
+
+ return app.exec();
+ }
+//! [0]
+
+//! [1]
+ class Renderer {
+ ...
+ VkDescriptorBufferInfo m_uniformBufInfo[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT];
+ };
+
+ void Renderer::startNextFrame()
+ {
+ VkDescriptorBufferInfo &uniformBufInfo(m_uniformBufInfo[m_window->currentFrame()]);
+ ...
+ }
+//! [1]
+
+//! [2]
+ class Renderer {
+ ...
+ VkDescriptorBufferInfo m_uniformBufInfo[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT];
+ };
+
+ void Renderer::startNextFrame()
+ {
+ const int count = m_window->concurrentFrameCount();
+ for (int i = 0; i < count; ++i)
+ m_uniformBufInfo[i] = ...
+ ...
+ }
+//! [2]
diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri
index 76aba944b2..70fccbc378 100644
--- a/src/gui/image/image.pri
+++ b/src/gui/image/image.pri
@@ -9,6 +9,7 @@ HEADERS += \
image/qimage_p.h \
image/qimageiohandler.h \
image/qimagereader.h \
+ image/qimagereaderwriterhelpers_p.h \
image/qimagewriter.h \
image/qpaintengine_pic_p.h \
image/qpicture.h \
@@ -33,6 +34,7 @@ SOURCES += \
image/qimage_conversions.cpp \
image/qimageiohandler.cpp \
image/qimagereader.cpp \
+ image/qimagereaderwriterhelpers.cpp \
image/qimagewriter.cpp \
image/qpaintengine_pic.cpp \
image/qpicture.cpp \
@@ -80,10 +82,7 @@ qtConfig(png) {
}
# SIMD
-SSE2_SOURCES += image/qimage_sse2.cpp
SSSE3_SOURCES += image/qimage_ssse3.cpp
-SSE4_1_SOURCES += image/qimage_sse4.cpp
-AVX2_SOURCES += image/qimage_avx2.cpp
NEON_SOURCES += image/qimage_neon.cpp
MIPS_DSPR2_SOURCES += image/qimage_mips_dspr2.cpp
MIPS_DSPR2_ASM += image/qimage_mips_dspr2_asm.S
diff --git a/src/gui/image/qbitmap.cpp b/src/gui/image/qbitmap.cpp
index e8405a6d11..2453242fa8 100644
--- a/src/gui/image/qbitmap.cpp
+++ b/src/gui/image/qbitmap.cpp
@@ -189,9 +189,7 @@ QBitmap &QBitmap::operator=(const QPixmap &pixmap)
} else if (pixmap.depth() == 1) { // 1-bit pixmap
QPixmap::operator=(pixmap); // shallow assignment
} else { // n-bit depth pixmap
- QImage image;
- image = pixmap.toImage(); // convert pixmap to image
- *this = fromImage(image); // will dither image
+ *this = fromImage(pixmap.toImage()); // will dither image
}
return *this;
}
@@ -223,6 +221,24 @@ QBitmap::operator QVariant() const
return QVariant(QVariant::Bitmap, this);
}
+static QBitmap makeBitmap(QImage &&image, Qt::ImageConversionFlags flags)
+{
+ // make sure image.color(0) == Qt::color0 (white)
+ // and image.color(1) == Qt::color1 (black)
+ const QRgb c0 = QColor(Qt::black).rgb();
+ const QRgb c1 = QColor(Qt::white).rgb();
+ if (image.color(0) == c0 && image.color(1) == c1) {
+ image.invertPixels();
+ image.setColor(0, c1);
+ image.setColor(1, c0);
+ }
+
+ QScopedPointer<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::BitmapType));
+
+ data->fromImageInPlace(image, flags | Qt::MonoOnly);
+ return QPixmap(data.take());
+}
+
/*!
Returns a copy of the given \a image converted to a bitmap using
the specified image conversion \a flags.
@@ -234,22 +250,24 @@ QBitmap QBitmap::fromImage(const QImage &image, Qt::ImageConversionFlags flags)
if (image.isNull())
return QBitmap();
- QImage img = image.convertToFormat(QImage::Format_MonoLSB, flags);
+ return makeBitmap(image.convertToFormat(QImage::Format_MonoLSB, flags), flags);
+}
- // make sure image.color(0) == Qt::color0 (white)
- // and image.color(1) == Qt::color1 (black)
- const QRgb c0 = QColor(Qt::black).rgb();
- const QRgb c1 = QColor(Qt::white).rgb();
- if (img.color(0) == c0 && img.color(1) == c1) {
- img.invertPixels();
- img.setColor(0, c1);
- img.setColor(1, c0);
- }
+/*!
+ \since 5.12
+ \overload
- QScopedPointer<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::BitmapType));
+ Returns a copy of the given \a image converted to a bitmap using
+ the specified image conversion \a flags.
- data->fromImage(img, flags | Qt::MonoOnly);
- return QPixmap(data.take());
+ \sa fromData()
+*/
+QBitmap QBitmap::fromImage(QImage &&image, Qt::ImageConversionFlags flags)
+{
+ if (image.isNull())
+ return QBitmap();
+
+ return makeBitmap(std::move(image).convertToFormat(QImage::Format_MonoLSB, flags), flags);
}
/*!
@@ -277,7 +295,7 @@ QBitmap QBitmap::fromData(const QSize &size, const uchar *bits, QImage::Format m
int bytesPerLine = (size.width() + 7) / 8;
for (int y = 0; y < size.height(); ++y)
memcpy(image.scanLine(y), bits + bytesPerLine * y, bytesPerLine);
- return QBitmap::fromImage(image);
+ return QBitmap::fromImage(std::move(image));
}
/*!
diff --git a/src/gui/image/qbitmap.h b/src/gui/image/qbitmap.h
index 6a8c8b3457..188064fccf 100644
--- a/src/gui/image/qbitmap.h
+++ b/src/gui/image/qbitmap.h
@@ -72,6 +72,7 @@ public:
inline void clear() { fill(Qt::color0); }
static QBitmap fromImage(const QImage &image, Qt::ImageConversionFlags flags = Qt::AutoColor);
+ static QBitmap fromImage(QImage &&image, Qt::ImageConversionFlags flags = Qt::AutoColor);
static QBitmap fromData(const QSize &size, const uchar *bits,
QImage::Format monoFormat = QImage::Format_MonoLSB);
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index 635fdc3a68..c362d0dc3f 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -1196,7 +1196,7 @@ void QIcon::setFallbackSearchPaths(const QStringList &paths)
The \a name should correspond to a directory name in the
themeSearchPath() containing an index.theme
- file describing it's contents.
+ file describing its contents.
\sa themeSearchPaths(), themeName()
*/
@@ -1222,6 +1222,37 @@ QString QIcon::themeName()
}
/*!
+ \since 5.12
+
+ Returns the name of the fallback icon theme.
+
+ On X11, if not set, the fallback icon theme depends on your desktop
+ settings. On other platforms it is not set by default.
+
+ \sa setFallbackThemeName(), themeName()
+*/
+QString QIcon::fallbackThemeName()
+{
+ return QIconLoader::instance()->fallbackThemeName();
+}
+
+/*!
+ \since 5.12
+
+ Sets the fallback icon theme to \a name.
+
+ The \a name should correspond to a directory name in the
+ themeSearchPath() containing an index.theme
+ file describing its contents.
+
+ \sa fallbackThemeName(), themeSearchPaths(), themeName()
+*/
+void QIcon::setFallbackThemeName(const QString &name)
+{
+ QIconLoader::instance()->setFallbackThemeName(name);
+}
+
+/*!
\since 4.6
Returns the QIcon corresponding to \a name in the current
diff --git a/src/gui/image/qicon.h b/src/gui/image/qicon.h
index 653ba6fda4..6a4fc8927a 100644
--- a/src/gui/image/qicon.h
+++ b/src/gui/image/qicon.h
@@ -124,6 +124,9 @@ public:
static QString themeName();
static void setThemeName(const QString &path);
+ static QString fallbackThemeName();
+ static void setFallbackThemeName(const QString &name);
+
Q_DUMMY_COMPARISON_OPERATOR(QIcon)
private:
diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp
index 1ea4f1340b..228de3adc3 100644
--- a/src/gui/image/qiconloader.cpp
+++ b/src/gui/image/qiconloader.cpp
@@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE
Q_GLOBAL_STATIC(QIconLoader, iconLoaderInstance)
/* Theme to use in last resort, if the theme does not have the icon, neither the parents */
-static QString fallbackTheme()
+static QString systemFallbackThemeName()
{
if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
const QVariant themeHint = theme->themeHint(QPlatformTheme::SystemIconFallbackThemeName);
@@ -117,7 +117,7 @@ void QIconLoader::ensureInitialized()
m_systemTheme = systemThemeName();
if (m_systemTheme.isEmpty())
- m_systemTheme = fallbackTheme();
+ m_systemTheme = systemFallbackThemeName();
if (qt_iconEngineFactoryLoader()->keyMap().key(QLatin1String("svg"), -1) != -1)
m_supportsSvg = true;
}
@@ -137,7 +137,7 @@ void QIconLoader::updateSystemTheme()
if (m_userTheme.isEmpty()) {
QString theme = systemThemeName();
if (theme.isEmpty())
- theme = fallbackTheme();
+ theme = fallbackThemeName();
if (theme != m_systemTheme) {
m_systemTheme = theme;
invalidateKey();
@@ -151,6 +151,16 @@ void QIconLoader::setThemeName(const QString &themeName)
invalidateKey();
}
+QString QIconLoader::fallbackThemeName() const
+{
+ return m_userFallbackTheme.isEmpty() ? systemFallbackThemeName() : m_userFallbackTheme;
+}
+
+void QIconLoader::setFallbackThemeName(const QString &themeName)
+{
+ m_userFallbackTheme = themeName;
+}
+
void QIconLoader::setThemeSearchPath(const QStringList &searchPaths)
{
m_iconDirs = searchPaths;
@@ -388,7 +398,7 @@ QIconTheme::QIconTheme(const QString &themeName)
// Ensure a default platform fallback for all themes
if (m_parents.isEmpty()) {
- const QString fallback = fallbackTheme();
+ const QString fallback = QIconLoader::instance()->fallbackThemeName();
if (!fallback.isEmpty())
m_parents.append(fallback);
}
@@ -414,7 +424,7 @@ QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName,
if (!theme.isValid()) {
theme = QIconTheme(themeName);
if (!theme.isValid())
- theme = QIconTheme(fallbackTheme());
+ theme = QIconTheme(fallbackThemeName());
}
const QStringList contentDirs = theme.contentDirs();
diff --git a/src/gui/image/qiconloader_p.h b/src/gui/image/qiconloader_p.h
index 746e871fb1..fac18b5d79 100644
--- a/src/gui/image/qiconloader_p.h
+++ b/src/gui/image/qiconloader_p.h
@@ -177,6 +177,8 @@ public:
QString themeName() const { return m_userTheme.isEmpty() ? m_systemTheme : m_userTheme; }
void setThemeName(const QString &themeName);
+ QString fallbackThemeName() const;
+ void setFallbackThemeName(const QString &themeName);
QIconTheme theme() { return themeList.value(themeName()); }
void setThemeSearchPath(const QStringList &searchPaths);
QStringList themeSearchPaths() const;
@@ -200,6 +202,7 @@ private:
bool m_initialized;
mutable QString m_userTheme;
+ mutable QString m_userFallbackTheme;
mutable QString m_systemTheme;
mutable QStringList m_iconDirs;
mutable QHash <QString, QIconTheme> themeList;
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 7fcae12cbd..421362dd9e 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -277,6 +277,16 @@ bool QImageData::checkForAlphaPixels() const
bits += bytes_per_line;
}
} break;
+ case QImage::Format_RGBA64:
+ case QImage::Format_RGBA64_Premultiplied: {
+ uchar *bits = data;
+ for (int y=0; y<height && !has_alpha_pixels; ++y) {
+ for (int x=0; x<width; ++x) {
+ has_alpha_pixels |= !(((QRgba64 *)bits)[x].isOpaque());
+ }
+ bits += bytes_per_line;
+ }
+ } break;
case QImage::Format_RGB32:
case QImage::Format_RGB16:
@@ -288,6 +298,7 @@ bool QImageData::checkForAlphaPixels() const
case QImage::Format_BGR30:
case QImage::Format_RGB30:
case QImage::Format_Grayscale8:
+ case QImage::Format_RGBX64:
break;
case QImage::Format_Invalid:
case QImage::NImageFormats:
@@ -651,11 +662,7 @@ bool QImageData::checkForAlphaPixels() const
/*!
\enum QImage::Format
- The following image formats are available in Qt. Values from Format_ARGB8565_Premultiplied
- to Format_ARGB4444_Premultiplied were added in Qt 4.4. Values Format_RGBX8888, Format_RGBA8888
- and Format_RGBA8888_Premultiplied were added in Qt 5.2. Values Format_BGR30, Format_A2BGR30_Premultiplied,
- Format_RGB30, Format_A2RGB30_Premultiplied were added in Qt 5.4. Format_Alpha8 and Format_Grayscale8
- were added in Qt 5.5.
+ The following image formats are available in Qt.
See the notes after the table.
\value Format_Invalid The image is invalid.
@@ -699,29 +706,32 @@ bool QImageData::checkForAlphaPixels() const
\value Format_ARGB4444_Premultiplied The image is stored using a
premultiplied 16-bit ARGB format (4-4-4-4).
\value Format_RGBX8888 The image is stored using a 32-bit byte-ordered RGB(x) format (8-8-8-8).
- This is the same as the Format_RGBA8888 except alpha must always be 255.
+ This is the same as the Format_RGBA8888 except alpha must always be 255. (added in Qt 5.2)
\value Format_RGBA8888 The image is stored using a 32-bit byte-ordered RGBA format (8-8-8-8).
Unlike ARGB32 this is a byte-ordered format, which means the 32bit
encoding differs between big endian and little endian architectures,
being respectively (0xRRGGBBAA) and (0xAABBGGRR). The order of the colors
- is the same on any architecture if read as bytes 0xRR,0xGG,0xBB,0xAA.
+ is the same on any architecture if read as bytes 0xRR,0xGG,0xBB,0xAA. (added in Qt 5.2)
\value Format_RGBA8888_Premultiplied The image is stored using a
- premultiplied 32-bit byte-ordered RGBA format (8-8-8-8).
- \value Format_BGR30 The image is stored using a 32-bit BGR format (x-10-10-10).
- \value Format_A2BGR30_Premultiplied The image is stored using a 32-bit premultiplied ABGR format (2-10-10-10).
- \value Format_RGB30 The image is stored using a 32-bit RGB format (x-10-10-10).
- \value Format_A2RGB30_Premultiplied The image is stored using a 32-bit premultiplied ARGB format (2-10-10-10).
- \value Format_Alpha8 The image is stored using an 8-bit alpha only format.
- \value Format_Grayscale8 The image is stored using an 8-bit grayscale format.
+ premultiplied 32-bit byte-ordered RGBA format (8-8-8-8). (added in Qt 5.2)
+ \value Format_BGR30 The image is stored using a 32-bit BGR format (x-10-10-10). (added in Qt 5.4)
+ \value Format_A2BGR30_Premultiplied The image is stored using a 32-bit premultiplied ABGR format (2-10-10-10). (added in Qt 5.4)
+ \value Format_RGB30 The image is stored using a 32-bit RGB format (x-10-10-10). (added in Qt 5.4)
+ \value Format_A2RGB30_Premultiplied The image is stored using a 32-bit premultiplied ARGB format (2-10-10-10). (added in Qt 5.4)
+ \value Format_Alpha8 The image is stored using an 8-bit alpha only format. (added in Qt 5.5)
+ \value Format_Grayscale8 The image is stored using an 8-bit grayscale format. (added in Qt 5.5)
+ \value Format_RGBX64 The image is stored using a 64-bit halfword-ordered RGB(x) format (16-16-16-16).
+ This is the same as the Format_RGBX64 except alpha must always be 65535. (added in Qt 5.12)
+ \value Format_RGBA64 The image is stored using a 64-bit halfword-ordered RGBA format (16-16-16-16). (added in Qt 5.12)
+ \value Format_RGBA64_Premultiplied The image is stored using a premultiplied 64-bit halfword-ordered
+ RGBA format (16-16-16-16). (added in Qt 5.12)
\note Drawing into a QImage with QImage::Format_Indexed8 is not
supported.
- \note Do not render into ARGB32 images using QPainter. Using
- QImage::Format_ARGB32_Premultiplied is significantly faster.
-
- \note Formats with more than 8 bit per color channel will only be processed by the raster engine using 8 bit
- per color.
+ \note Avoid most rendering directly to most of these formats using QPainter. Rendering
+ is best optimized to the \c Format_RGB32 and \c Format_ARGB32_Premultiplied formats, and secondarily for rendering to the
+ \c Format_RGB16, \c Format_RGBX8888, \c Format_RGBA8888_Premultiplied, \c Format_RGBX64 and \c Format_RGBA64_Premultiplied formats
\sa format(), convertToFormat()
*/
@@ -1444,7 +1454,8 @@ void QImage::setDevicePixelRatio(qreal scaleFactor)
return;
detach();
- d->devicePixelRatio = scaleFactor;
+ if (d)
+ d->devicePixelRatio = scaleFactor;
}
/*!
@@ -1708,6 +1719,10 @@ void QImage::fill(uint pixel)
qt_rectfill<quint24>(reinterpret_cast<quint24*>(d->data), pixel,
0, 0, d->width, d->height, d->bytes_per_line);
return;
+ } else if (d->depth == 64) {
+ qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), QRgba64::fromArgb32(pixel),
+ 0, 0, d->width, d->height, d->bytes_per_line);
+ return;
}
if (d->format == Format_RGB32)
@@ -1815,6 +1830,19 @@ void QImage::fill(const QColor &color)
else
fill((uint) 0);
break;
+ case QImage::Format_RGBX64: {
+ QRgba64 c = color.rgba64();
+ c.setAlpha(65535);
+ qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), c,
+ 0, 0, d->width, d->height, d->bytes_per_line);
+ break;
+
+ }
+ case QImage::Format_RGBA64:
+ case QImage::Format_RGBA64_Premultiplied:
+ qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), color.rgba64(),
+ 0, 0, d->width, d->height, d->bytes_per_line);
+ break;
default: {
QPainter p(this);
p.setCompositionMode(QPainter::CompositionMode_Source);
@@ -1838,7 +1866,8 @@ void QImage::fill(const QColor &color)
changed.
If the image has a premultiplied alpha channel, the image is first
- converted to ARGB32 to be inverted and then converted back.
+ converted to an unpremultiplied image format to be inverted and
+ then converted back.
\sa {QImage#Image Transformations}{Image Transformations}
*/
@@ -1857,8 +1886,13 @@ void QImage::invertPixels(InvertMode mode)
QImage::Format originalFormat = d->format;
// Inverting premultiplied pixels would produce invalid image data.
if (hasAlphaChannel() && qPixelLayouts[d->format].premultiplied) {
- if (!d->convertInPlace(QImage::Format_ARGB32, 0))
- *this = convertToFormat(QImage::Format_ARGB32);
+ if (depth() > 32) {
+ if (!d->convertInPlace(QImage::Format_RGBA64, 0))
+ *this = convertToFormat(QImage::Format_RGBA64);
+ } else {
+ if (!d->convertInPlace(QImage::Format_ARGB32, 0))
+ *this = convertToFormat(QImage::Format_ARGB32);
+ }
}
if (depth() < 32) {
@@ -1871,6 +1905,20 @@ void QImage::invertPixels(InvertMode mode)
*sl++ ^= 0xff;
sl += pad;
}
+ }
+ else if (depth() == 64) {
+ quint16 *p = (quint16*)d->data;
+ quint16 *end = (quint16*)(d->data + d->nbytes);
+ quint16 xorbits = 0xffff;
+ while (p < end) {
+ *p++ ^= xorbits;
+ *p++ ^= xorbits;
+ *p++ ^= xorbits;
+ if (mode == InvertRgba)
+ *p++ ^= xorbits;
+ else
+ p++;
+ }
} else {
quint32 *p = (quint32*)d->data;
quint32 *end = (quint32*)(d->data + d->nbytes);
@@ -1987,6 +2035,26 @@ QImage::Format QImage::format() const
\sa {Image Formats}
*/
+static bool highColorPrecision(QImage::Format format)
+{
+ // Formats with higher color precision than ARGB32_Premultiplied.
+ switch (format) {
+ case QImage::Format_ARGB32:
+ case QImage::Format_RGBA8888:
+ case QImage::Format_BGR30:
+ case QImage::Format_RGB30:
+ case QImage::Format_A2BGR30_Premultiplied:
+ case QImage::Format_A2RGB30_Premultiplied:
+ case QImage::Format_RGBX64:
+ case QImage::Format_RGBA64:
+ case QImage::Format_RGBA64_Premultiplied:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
/*!
\internal
*/
@@ -1999,8 +2067,18 @@ QImage QImage::convertToFormat_helper(Format format, Qt::ImageConversionFlags fl
return QImage();
Image_Converter converter = qimage_converter_map[d->format][format];
- if (!converter && format > QImage::Format_Indexed8 && d->format > QImage::Format_Indexed8)
- converter = convert_generic;
+ if (!converter && format > QImage::Format_Indexed8 && d->format > QImage::Format_Indexed8) {
+ if (highColorPrecision(format) && highColorPrecision(d->format)) {
+ // Convert over RGBA64_Premultiplied
+ if (format == QImage::Format_RGBA64_Premultiplied)
+ converter = convert_generic_to_rgb64;
+ else {
+ Q_ASSERT(d->format != QImage::Format_RGBA64_Premultiplied);
+ return convertToFormat(Format_RGBA64_Premultiplied, flags).convertToFormat(format, flags);
+ }
+ } else
+ converter = convert_generic;
+ }
if (converter) {
QImage image(d->width, d->height, format);
@@ -2163,8 +2241,15 @@ bool QImage::reinterpretAsFormat(Format format)
return true;
if (qt_depthForFormat(format) != qt_depthForFormat(d->format))
return false;
- if (!isDetached()) // Detach only if shared, not for read-only data.
+ if (!isDetached()) { // Detach only if shared, not for read-only data.
+ QImageData *oldD = d;
detach();
+ // In case detach() ran out of memory
+ if (!d) {
+ d = oldD;
+ return false;
+ }
+ }
d->format = format;
return true;
@@ -2298,13 +2383,16 @@ QRgb QImage::pixel(int x, int y) const
return qConvertA2rgb30ToArgb32<PixelOrderRGB>(reinterpret_cast<const quint32 *>(s)[x]);
case Format_RGB16:
return qConvertRgb16To32(reinterpret_cast<const quint16 *>(s)[x]);
+ case Format_RGBX64:
+ case Format_RGBA64: // Match ARGB32 behavior.
+ case Format_RGBA64_Premultiplied:
+ return reinterpret_cast<const QRgba64 *>(s)[x].toArgb32();
default:
break;
}
const QPixelLayout *layout = &qPixelLayouts[d->format];
uint result;
- const uint *ptr = qFetchPixels[layout->bpp](&result, s, x, 1);
- return *layout->convertToARGB32PM(&result, ptr, 1, 0, 0);
+ return *layout->fetchToARGB32PM(&result, s, x, 1, nullptr, nullptr);
}
/*!
@@ -2405,9 +2493,7 @@ void QImage::setPixel(int x, int y, uint index_or_rgb)
}
const QPixelLayout *layout = &qPixelLayouts[d->format];
- uint result;
- const uint *ptr = layout->convertFromARGB32PM(&result, &index_or_rgb, 1, 0, 0);
- qStorePixels[layout->bpp](s, ptr, x, 1);
+ layout->storeFromARGB32PM(s, &index_or_rgb, x, 1, nullptr, nullptr);
}
/*!
@@ -2450,6 +2536,11 @@ QColor QImage::pixelColor(int x, int y) const
case Format_A2RGB30_Premultiplied:
c = qConvertA2rgb30ToRgb64<PixelOrderRGB>(reinterpret_cast<const quint32 *>(s)[x]);
break;
+ case Format_RGBX64:
+ case Format_RGBA64:
+ case Format_RGBA64_Premultiplied:
+ c = reinterpret_cast<const QRgba64 *>(s)[x];
+ break;
default:
c = QRgba64::fromArgb32(pixel(x, y));
break;
@@ -2520,6 +2611,14 @@ void QImage::setPixelColor(int x, int y, const QColor &color)
case Format_A2RGB30_Premultiplied:
((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderRGB>(c);
return;
+ case Format_RGBX64:
+ ((QRgba64 *)s)[x] = color.rgba64();
+ ((QRgba64 *)s)[x].setAlpha(65535);
+ return;
+ case Format_RGBA64:
+ case Format_RGBA64_Premultiplied:
+ ((QRgba64 *)s)[x] = color.rgba64();
+ return;
default:
setPixel(x, y, c.toArgb32());
return;
@@ -2582,17 +2681,15 @@ bool QImage::allGray() const
break;
}
- const int buffer_size = 2048;
- uint buffer[buffer_size];
+ uint buffer[BufferSize];
const QPixelLayout *layout = &qPixelLayouts[d->format];
- FetchPixelsFunc fetch = qFetchPixels[layout->bpp];
+ const auto fetch = layout->fetchToARGB32PM;
for (int j = 0; j < d->height; ++j) {
const uchar *b = constScanLine(j);
int x = 0;
while (x < d->width) {
- int l = qMin(d->width - x, buffer_size);
- const uint *ptr = fetch(buffer, b, x, l);
- ptr = layout->convertToARGB32PM(buffer, ptr, l, 0, 0);
+ int l = qMin(d->width - x, BufferSize);
+ const uint *ptr = fetch(buffer, b, x, l, nullptr, nullptr);
for (int i = 0; i < l; ++i) {
if (!qIsGray(ptr[i]))
return false;
@@ -2780,6 +2877,13 @@ QMatrix QImage::trueMatrix(const QMatrix &matrix, int w, int h)
Returns a copy of the image that is transformed using the given
transformation \a matrix and transformation \a mode.
+ The returned image will normally have the same {Image Formats}{format} as
+ the original image. However, a complex transformation may result in an
+ image where not all pixels are covered by the transformed pixels of the
+ original image. In such cases, those background pixels will be assigned a
+ transparent color value, and the transformed image will be given a format
+ with an alpha channel, even if the orginal image did not have that.
+
The transformation \a matrix is internally adjusted to compensate
for unwanted translation; i.e. the image produced is the smallest
image that contains all the transformed points of the original
@@ -3098,6 +3202,9 @@ inline void do_mirror(QImageData *dst, QImageData *src, bool horizontal, bool ve
}
switch (depth) {
+ case 64:
+ do_mirror_data<quint64>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
+ break;
case 32:
do_mirror_data<quint32>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
break;
@@ -3189,6 +3296,8 @@ void QImage::mirrored_inplace(bool horizontal, bool vertical)
return;
detach();
+ if (!d)
+ return;
if (!d->own_data)
*this = copy();
@@ -3210,33 +3319,18 @@ void QImage::mirrored_inplace(bool horizontal, bool vertical)
inline void rgbSwapped_generic(int width, int height, const QImage *src, QImage *dst, const QPixelLayout* layout)
{
- Q_ASSERT(layout->redWidth == layout->blueWidth);
- FetchPixelsFunc fetch = qFetchPixels[layout->bpp];
- StorePixelsFunc store = qStorePixels[layout->bpp];
-
- const uint redBlueMask = (1 << layout->redWidth) - 1;
- const uint alphaGreenMask = (((1 << layout->alphaWidth) - 1) << layout->alphaShift)
- | (((1 << layout->greenWidth) - 1) << layout->greenShift);
+ const RbSwapFunc func = layout->rbSwap;
+ if (!func) {
+ qWarning("Trying to rb-swap an image format where it doesn't make sense");
+ if (src != dst)
+ *dst = *src;
+ return;
+ }
- const int buffer_size = 2048;
- uint buffer[buffer_size];
for (int i = 0; i < height; ++i) {
uchar *q = dst->scanLine(i);
const uchar *p = src->constScanLine(i);
- int x = 0;
- while (x < width) {
- int l = qMin(width - x, buffer_size);
- const uint *ptr = fetch(buffer, p, x, l);
- for (int j = 0; j < l; ++j) {
- uint red = (ptr[j] >> layout->redShift) & redBlueMask;
- uint blue = (ptr[j] >> layout->blueShift) & redBlueMask;
- buffer[j] = (ptr[j] & alphaGreenMask)
- | (red << layout->blueShift)
- | (blue << layout->redShift);
- }
- store(q, buffer, x, l);
- x += l;
- }
+ func(q, p, width);
}
}
@@ -3321,18 +3415,18 @@ QImage QImage::rgbSwapped_helper() const
}
}
break;
- case Format_BGR30:
- case Format_A2BGR30_Premultiplied:
- case Format_RGB30:
- case Format_A2RGB30_Premultiplied:
+ case Format_RGBX64:
+ case Format_RGBA64:
+ case Format_RGBA64_Premultiplied:
res = QImage(d->width, d->height, d->format);
QIMAGE_SANITYCHECK_MEMORY(res);
for (int i = 0; i < d->height; i++) {
- uint *q = (uint*)res.scanLine(i);
- const uint *p = (const uint*)constScanLine(i);
- const uint *end = p + d->width;
+ QRgba64 *q = reinterpret_cast<QRgba64 *>(res.scanLine(i));
+ const QRgba64 *p = reinterpret_cast<const QRgba64 *>(constScanLine(i));
+ const QRgba64 *end = p + d->width;
while (p < end) {
- *q = qRgbSwapRgb30(*p);
+ QRgba64 c = *p;
+ *q = QRgba64::fromRgba64(c.blue(), c.green(), c.red(), c.alpha());
p++;
q++;
}
@@ -3356,6 +3450,8 @@ void QImage::rgbSwapped_inplace()
return;
detach();
+ if (!d)
+ return;
if (!d->own_data)
*this = copy();
@@ -3430,6 +3526,19 @@ void QImage::rgbSwapped_inplace()
}
}
break;
+ case Format_RGBX64:
+ case Format_RGBA64:
+ case Format_RGBA64_Premultiplied:
+ for (int i = 0; i < d->height; i++) {
+ QRgba64 *p = reinterpret_cast<QRgba64 *>(scanLine(i));
+ QRgba64 *end = p + d->width;
+ while (p < end) {
+ QRgba64 c = *p;
+ *p = QRgba64::fromRgba64(c.blue(), c.green(), c.red(), c.alpha());
+ p++;
+ }
+ }
+ break;
default:
rgbSwapped_generic(d->width, d->height, this, this, &qPixelLayouts[d->format]);
break;
@@ -3457,8 +3566,7 @@ void QImage::rgbSwapped_inplace()
bool QImage::load(const QString &fileName, const char* format)
{
- QImage image = QImageReader(fileName, format).read();
- operator=(image);
+ *this = QImageReader(fileName, format).read();
return !isNull();
}
@@ -3471,8 +3579,7 @@ bool QImage::load(const QString &fileName, const char* format)
bool QImage::load(QIODevice* device, const char* format)
{
- QImage image = QImageReader(device, format).read();
- operator=(image);
+ *this = QImageReader(device, format).read();
return !isNull();
}
@@ -3492,8 +3599,7 @@ bool QImage::load(QIODevice* device, const char* format)
bool QImage::loadFromData(const uchar *data, int len, const char *format)
{
- QImage image = fromData(data, len, format);
- operator=(image);
+ *this = fromData(data, len, format);
return !isNull();
}
@@ -3644,7 +3750,9 @@ QDataStream &operator>>(QDataStream &s, QImage &image)
return s;
}
}
- image = QImageReader(s.device(), 0).read();
+ image = QImageReader(s.device(), s.version() == 1 ? "bmp" : "png").read();
+ if (image.isNull() && s.version() >= 5)
+ s.setStatus(QDataStream::ReadPastEnd);
return s;
}
#endif // QT_NO_DATASTREAM
@@ -4506,6 +4614,9 @@ int QImage::bitPlaneCount() const
case QImage::Format_RGB444:
bpc = 12;
break;
+ case QImage::Format_RGBX64:
+ bpc = 48;
+ break;
default:
bpc = qt_depthForFormat(d->format);
break;
@@ -4526,6 +4637,11 @@ QImage QImage::smoothScaled(int w, int h) const {
case QImage::Format_RGBX8888:
#endif
case QImage::Format_RGBA8888_Premultiplied:
+ case QImage::Format_RGBX64:
+ case QImage::Format_RGBA64_Premultiplied:
+ break;
+ case QImage::Format_RGBA64:
+ src = src.convertToFormat(QImage::Format_RGBA64_Premultiplied);
break;
default:
if (src.hasAlphaChannel())
@@ -4610,6 +4726,13 @@ static QImage rotated270(const QImage &image)
Returns a copy of the image that is transformed using the given
transformation \a matrix and transformation \a mode.
+ The returned image will normally have the same {Image Formats}{format} as
+ the original image. However, a complex transformation may result in an
+ image where not all pixels are covered by the transformed pixels of the
+ original image. In such cases, those background pixels will be assigned a
+ transparent color value, and the transformed image will be given a format
+ with an alpha channel, even if the orginal image did not have that.
+
The transformation \a matrix is internally adjusted to compensate
for unwanted translation; i.e. the image produced is the smallest
image that contains all the transformed points of the original
@@ -5197,6 +5320,45 @@ static Q_CONSTEXPR QPixelFormat pixelformats[] = {
/*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
/*INTERPRETATION*/ QPixelFormat::UnsignedByte,
/*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGBX64:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 16,
+ /*GREEN*/ 16,
+ /*BLUE*/ 16,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 16,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtEnd,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedShort,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGBA64:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 16,
+ /*GREEN*/ 16,
+ /*BLUE*/ 16,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 16,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtEnd,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedShort,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGBA64_Premultiplied:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 16,
+ /*GREEN*/ 16,
+ /*BLUE*/ 16,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 16,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtEnd,
+ /*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedShort,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
};
Q_STATIC_ASSERT(sizeof(pixelformats) / sizeof(*pixelformats) == QImage::NImageFormats);
diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h
index 9b76b62f24..4b7a3b1ead 100644
--- a/src/gui/image/qimage.h
+++ b/src/gui/image/qimage.h
@@ -96,6 +96,7 @@ typedef void (*QImageCleanupFunction)(void*);
class Q_GUI_EXPORT QImage : public QPaintDevice
{
+ Q_GADGET
public:
enum InvertMode { InvertRgb, InvertRgba };
enum Format {
@@ -124,6 +125,9 @@ public:
Format_A2RGB30_Premultiplied,
Format_Alpha8,
Format_Grayscale8,
+ Format_RGBX64,
+ Format_RGBA64,
+ Format_RGBA64_Premultiplied,
#if 0
// reserved for future use
Format_Grayscale16,
@@ -132,6 +136,7 @@ public:
NImageFormats
#endif
};
+ Q_ENUM(Format)
QImage() Q_DECL_NOEXCEPT;
QImage(const QSize &size, Format format);
@@ -329,7 +334,7 @@ public:
static QPixelFormat toPixelFormat(QImage::Format format) Q_DECL_NOTHROW;
static QImage::Format toImageFormat(QPixelFormat format) Q_DECL_NOTHROW;
- // Platform spesific conversion functions
+ // Platform specific conversion functions
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
CGImageRef toCGImage() const Q_DECL_CF_RETURNS_RETAINED;
#endif
diff --git a/src/gui/image/qimage_avx2.cpp b/src/gui/image/qimage_avx2.cpp
deleted file mode 100644
index 0519f17c5d..0000000000
--- a/src/gui/image/qimage_avx2.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <qimage.h>
-#include <private/qdrawhelper_p.h>
-#include <private/qimage_p.h>
-#include <private/qsimd_p.h>
-
-#ifdef QT_COMPILER_SUPPORTS_AVX2
-
-QT_BEGIN_NAMESPACE
-
-void convert_ARGB_to_ARGB_PM_avx2(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
-{
- Q_ASSERT(src->format == QImage::Format_ARGB32 || src->format == QImage::Format_RGBA8888);
- Q_ASSERT(dest->format == QImage::Format_ARGB32_Premultiplied || dest->format == QImage::Format_RGBA8888_Premultiplied);
- Q_ASSERT(src->width == dest->width);
- Q_ASSERT(src->height == dest->height);
-
- const uint *src_data = (uint *) src->data;
- uint *dest_data = (uint *) dest->data;
- for (int i = 0; i < src->height; ++i) {
- qt_convertARGB32ToARGB32PM(dest_data, src_data, src->width);
- src_data += src->bytes_per_line >> 2;
- dest_data += dest->bytes_per_line >> 2;
- }
-}
-
-QT_END_NAMESPACE
-
-#endif // QT_COMPILER_SUPPORTS_AVX2
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index d981c43711..964dc0d5c6 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -118,26 +118,40 @@ void qGamma_correct_back_to_linear_cs(QImage *image)
Internal routines for converting image depth.
*****************************************************************************/
-// The drawhelper conversions from/to RGB32 are passthroughs which is not always correct for general image conversion.
-static const uint *QT_FASTCALL convertRGB32FromARGB32PM(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+// The drawhelper conversions from/to RGB32 are passthroughs which is not always correct for general image conversion
+#if !defined(__ARM_NEON__)
+static void QT_FASTCALL storeRGB32FromARGB32PM(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
+ uint *d = reinterpret_cast<uint *>(dest) + index;
for (int i = 0; i < count; ++i)
- buffer[i] = 0xff000000 | qUnpremultiply(src[i]);
- return buffer;
+ d[i] = 0xff000000 | qUnpremultiply(src[i]);
+}
+#endif
+
+static void QT_FASTCALL storeRGB32FromARGB32(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ for (int i = 0; i < count; ++i)
+ d[i] = 0xff000000 | src[i];
}
-static const uint *QT_FASTCALL maskRGB32(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+static const uint *QT_FASTCALL fetchRGB32ToARGB32PM(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
+ const uint *s = reinterpret_cast<const uint *>(src) + index;
for (int i = 0; i < count; ++i)
- buffer[i] = 0xff000000 |src[i];
+ buffer[i] = 0xff000000 | s[i];
return buffer;
}
#ifdef QT_COMPILER_SUPPORTS_SSE4_1
-extern const uint *QT_FASTCALL convertRGB32FromARGB32PM_sse4(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *);
+extern void QT_FASTCALL storeRGB32FromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+#elif defined(__ARM_NEON__)
+extern void QT_FASTCALL storeRGB32FromARGB32PM_neon(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
#endif
void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags flags)
@@ -145,42 +159,43 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
// Cannot be used with indexed formats.
Q_ASSERT(dest->format > QImage::Format_Indexed8);
Q_ASSERT(src->format > QImage::Format_Indexed8);
- const int buffer_size = 2048;
- uint buf[buffer_size];
+ uint buf[BufferSize];
uint *buffer = buf;
const QPixelLayout *srcLayout = &qPixelLayouts[src->format];
const QPixelLayout *destLayout = &qPixelLayouts[dest->format];
const uchar *srcData = src->data;
uchar *destData = dest->data;
- const FetchPixelsFunc fetch = qFetchPixels[srcLayout->bpp];
- const StorePixelsFunc store = qStorePixels[destLayout->bpp];
- ConvertFunc convertToARGB32PM = srcLayout->convertToARGB32PM;
- ConvertFunc convertFromARGB32PM = destLayout->convertFromARGB32PM;
- if (srcLayout->alphaWidth == 0 && destLayout->convertFromRGB32) {
- // If the source doesn't have an alpha channel, we can use the faster convertFromRGB32 method.
- convertFromARGB32PM = destLayout->convertFromRGB32;
+ FetchAndConvertPixelsFunc fetch = srcLayout->fetchToARGB32PM;
+ ConvertAndStorePixelsFunc store = destLayout->storeFromARGB32PM;
+ if (!srcLayout->hasAlphaChannel && destLayout->storeFromRGB32) {
+ // If the source doesn't have an alpha channel, we can use the faster storeFromRGB32 method.
+ store = destLayout->storeFromRGB32;
} else {
// The drawhelpers do not mask the alpha value in RGB32, we want to here.
if (src->format == QImage::Format_RGB32)
- convertToARGB32PM = maskRGB32;
+ fetch = fetchRGB32ToARGB32PM;
if (dest->format == QImage::Format_RGB32) {
#ifdef QT_COMPILER_SUPPORTS_SSE4_1
if (qCpuHasFeature(SSE4_1))
- convertFromARGB32PM = convertRGB32FromARGB32PM_sse4;
+ store = storeRGB32FromARGB32PM_sse4;
else
+ store = storeRGB32FromARGB32PM;
+#elif defined(__ARM_NEON__)
+ store = storeRGB32FromARGB32PM_neon;
+#else
+ store = storeRGB32FromARGB32PM;
#endif
- convertFromARGB32PM = convertRGB32FromARGB32PM;
}
}
- if ((src->format == QImage::Format_ARGB32 || src->format == QImage::Format_RGBA8888) &&
- destLayout->alphaWidth == 0 && destLayout->convertFromRGB32) {
+ if (srcLayout->hasAlphaChannel && !srcLayout->premultiplied &&
+ !destLayout->hasAlphaChannel && destLayout->storeFromRGB32) {
// Avoid unnecessary premultiply and unpremultiply when converting from unpremultiplied src format.
- convertToARGB32PM = qPixelLayouts[src->format + 1].convertToARGB32PM;
+ fetch = qPixelLayouts[src->format + 1].fetchToARGB32PM;
if (dest->format == QImage::Format_RGB32)
- convertFromARGB32PM = maskRGB32;
+ store = storeRGB32FromARGB32;
else
- convertFromARGB32PM = destLayout->convertFromRGB32;
+ store = destLayout->storeFromRGB32;
}
QDitherInfo dither;
QDitherInfo *ditherPtr = 0;
@@ -196,12 +211,9 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
if (destLayout->bpp == QPixelLayout::BPP32)
buffer = reinterpret_cast<uint *>(destData) + x;
else
- l = qMin(l, buffer_size);
- const uint *ptr = fetch(buffer, srcData, x, l);
- ptr = convertToARGB32PM(buffer, ptr, l, 0, ditherPtr);
- ptr = convertFromARGB32PM(buffer, ptr, l, 0, ditherPtr);
- if (ptr != reinterpret_cast<uint *>(destData))
- store(destData, ptr, x, l);
+ l = qMin(l, BufferSize);
+ const uint *ptr = fetch(buffer, srcData, x, l, 0, ditherPtr);
+ store(destData, ptr, x, l, 0, ditherPtr);
x += l;
}
srcData += src->bytes_per_line;
@@ -209,6 +221,26 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
}
}
+void convert_generic_to_rgb64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(dest->format == QImage::Format_RGBA64_Premultiplied);
+ Q_ASSERT(src->format > QImage::Format_Indexed8);
+ const QPixelLayout *srcLayout = &qPixelLayouts[src->format];
+ const uchar *srcData = src->data;
+ uchar *destData = dest->data;
+
+ const FetchAndConvertPixelsFunc64 fetch = srcLayout->fetchToRGBA64PM;
+
+ for (int y = 0; y < src->height; ++y) {
+ const QRgba64 *ptr = fetch((QRgba64*)destData, srcData, 0, src->width, nullptr, nullptr);
+ if (ptr != (const QRgba64*)destData) {
+ memcpy(destData, ptr, dest->bytes_per_line);
+ }
+ srcData += src->bytes_per_line;
+ destData += dest->bytes_per_line;
+ }
+}
+
bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags flags)
{
// Cannot be used with indexed formats or between formats with different pixel depths.
@@ -217,39 +249,43 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
if (data->depth != qt_depthForFormat(dst_format))
return false;
- const int buffer_size = 2048;
- uint buffer[buffer_size];
+ uint buf[BufferSize];
+ uint *buffer = buf;
const QPixelLayout *srcLayout = &qPixelLayouts[data->format];
const QPixelLayout *destLayout = &qPixelLayouts[dst_format];
uchar *srcData = data->data;
- const FetchPixelsFunc fetch = qFetchPixels[srcLayout->bpp];
- const StorePixelsFunc store = qStorePixels[destLayout->bpp];
- ConvertFunc convertToARGB32PM = srcLayout->convertToARGB32PM;
- ConvertFunc convertFromARGB32PM = destLayout->convertFromARGB32PM;
- if (srcLayout->alphaWidth == 0 && destLayout->convertFromRGB32) {
- // If the source doesn't have an alpha channel, we can use the faster convertFromRGB32 method.
- convertFromARGB32PM = destLayout->convertFromRGB32;
+ Q_ASSERT(srcLayout->bpp == destLayout->bpp);
+ Q_ASSERT(srcLayout->bpp != QPixelLayout::BPP64);
+ FetchAndConvertPixelsFunc fetch = srcLayout->fetchToARGB32PM;
+ ConvertAndStorePixelsFunc store = destLayout->storeFromARGB32PM;
+ if (!srcLayout->hasAlphaChannel && destLayout->storeFromRGB32) {
+ // If the source doesn't have an alpha channel, we can use the faster storeFromRGB32 method.
+ store = destLayout->storeFromRGB32;
} else {
if (data->format == QImage::Format_RGB32)
- convertToARGB32PM = maskRGB32;
+ fetch = fetchRGB32ToARGB32PM;
if (dst_format == QImage::Format_RGB32) {
#ifdef QT_COMPILER_SUPPORTS_SSE4_1
if (qCpuHasFeature(SSE4_1))
- convertFromARGB32PM = convertRGB32FromARGB32PM_sse4;
+ store = storeRGB32FromARGB32PM_sse4;
else
+ store = storeRGB32FromARGB32PM;
+#elif defined(__ARM_NEON__)
+ store = storeRGB32FromARGB32PM_neon;
+#else
+ store = storeRGB32FromARGB32PM;
#endif
- convertFromARGB32PM = convertRGB32FromARGB32PM;
}
}
- if ((data->format == QImage::Format_ARGB32 || data->format == QImage::Format_RGBA8888) &&
- destLayout->alphaWidth == 0 && destLayout->convertFromRGB32) {
+ if (srcLayout->hasAlphaChannel && !srcLayout->premultiplied &&
+ !destLayout->hasAlphaChannel && destLayout->storeFromRGB32) {
// Avoid unnecessary premultiply and unpremultiply when converting from unpremultiplied src format.
- convertToARGB32PM = qPixelLayouts[data->format + 1].convertToARGB32PM;
- if (dst_format == QImage::Format_RGB32)
- convertFromARGB32PM = maskRGB32;
+ fetch = qPixelLayouts[data->format + 1].fetchToARGB32PM;
+ if (data->format == QImage::Format_RGB32)
+ store = storeRGB32FromARGB32;
else
- convertFromARGB32PM = destLayout->convertFromRGB32;
+ store = destLayout->storeFromRGB32;
}
QDitherInfo dither;
QDitherInfo *ditherPtr = 0;
@@ -261,13 +297,13 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
int x = 0;
while (x < data->width) {
dither.x = x;
- int l = qMin(data->width - x, buffer_size);
- const uint *ptr = fetch(buffer, srcData, x, l);
- ptr = convertToARGB32PM(buffer, ptr, l, 0, ditherPtr);
- ptr = convertFromARGB32PM(buffer, ptr, l, 0, ditherPtr);
- // The conversions might be passthrough and not use the buffer, in that case we are already done.
- if (srcData != (const uchar*)ptr)
- store(srcData, ptr, x, l);
+ int l = data->width - x;
+ if (destLayout->bpp == QPixelLayout::BPP32)
+ buffer = reinterpret_cast<uint *>(srcData) + x;
+ else
+ l = qMin(l, BufferSize);
+ const uint *ptr = fetch(buffer, srcData, x, l, nullptr, ditherPtr);
+ store(srcData, ptr, x, l, nullptr, ditherPtr);
x += l;
}
srcData += data->bytes_per_line;
@@ -281,20 +317,15 @@ static void convert_passthrough(QImageData *dest, const QImageData *src, Qt::Ima
Q_ASSERT(src->width == dest->width);
Q_ASSERT(src->height == dest->height);
- const int src_pad = (src->bytes_per_line >> 2) - src->width;
- const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
- const quint32 *src_data = (quint32 *) src->data;
- quint32 *dest_data = (quint32 *) dest->data;
+ const int src_bpl = src->bytes_per_line;
+ const int dest_bpl = dest->bytes_per_line;
+ const uchar *src_data = src->data;
+ uchar *dest_data = dest->data;
for (int i = 0; i < src->height; ++i) {
- const quint32 *end = src_data + src->width;
- while (src_data < end) {
- *dest_data = *src_data;
- ++src_data;
- ++dest_data;
- }
- src_data += src_pad;
- dest_data += dest_pad;
+ memcpy(dest_data, src_data, src_bpl);
+ src_data += src_bpl;
+ dest_data += dest_bpl;
}
}
@@ -305,30 +336,6 @@ static bool convert_passthrough_inplace(QImageData *data, Qt::ImageConversionFla
return true;
}
-static void convert_ARGB_to_ARGB_PM(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
-{
- Q_ASSERT(src->format == QImage::Format_ARGB32 || src->format == QImage::Format_RGBA8888);
- Q_ASSERT(dest->format == QImage::Format_ARGB32_Premultiplied || dest->format == QImage::Format_RGBA8888_Premultiplied);
- Q_ASSERT(src->width == dest->width);
- Q_ASSERT(src->height == dest->height);
-
- const int src_pad = (src->bytes_per_line >> 2) - src->width;
- const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
- const QRgb *src_data = (QRgb *) src->data;
- QRgb *dest_data = (QRgb *) dest->data;
-
- for (int i = 0; i < src->height; ++i) {
- const QRgb *end = src_data + src->width;
- while (src_data < end) {
- *dest_data = qPremultiply(*src_data);
- ++src_data;
- ++dest_data;
- }
- src_data += src_pad;
- dest_data += dest_pad;
- }
-}
-
Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32(quint32 *dest_data, const uchar *src_data, int len)
{
int pixel = 0;
@@ -431,33 +438,6 @@ static void convert_RGB888_to_RGB(QImageData *dest, const QImageData *src, Qt::I
}
}
-#ifdef __SSE2__
-extern bool convert_ARGB_to_ARGB_PM_inplace_sse2(QImageData *data, Qt::ImageConversionFlags);
-#else
-static bool convert_ARGB_to_ARGB_PM_inplace(QImageData *data,Qt::ImageConversionFlags)
-{
- Q_ASSERT(data->format == QImage::Format_ARGB32 || data->format == QImage::Format_RGBA8888);
-
- const int pad = (data->bytes_per_line >> 2) - data->width;
- QRgb *rgb_data = (QRgb *) data->data;
-
- for (int i = 0; i < data->height; ++i) {
- const QRgb *end = rgb_data + data->width;
- while (rgb_data < end) {
- *rgb_data = qPremultiply(*rgb_data);
- ++rgb_data;
- }
- rgb_data += pad;
- }
-
- if (data->format == QImage::Format_ARGB32)
- data->format = QImage::Format_ARGB32_Premultiplied;
- else
- data->format = QImage::Format_RGBA8888_Premultiplied;
- return true;
-}
-#endif
-
static void convert_ARGB_to_RGBx(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{
Q_ASSERT(src->format == QImage::Format_ARGB32);
@@ -573,11 +553,12 @@ static bool convert_RGBA_to_ARGB_inplace(QImageData *data, Qt::ImageConversionFl
return true;
}
-template<QtPixelOrder PixelOrder>
+template<QtPixelOrder PixelOrder, bool RGBA>
static void convert_RGB_to_RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{
- Q_ASSERT(src->format == QImage::Format_RGB32 || src->format == QImage::Format_ARGB32);
+ Q_ASSERT(RGBA || src->format == QImage::Format_RGB32 || src->format == QImage::Format_ARGB32);
+ Q_ASSERT(!RGBA || src->format == QImage::Format_RGBX8888 || src->format == QImage::Format_RGBA8888);
Q_ASSERT(dest->format == QImage::Format_BGR30 || dest->format == QImage::Format_RGB30);
Q_ASSERT(src->width == dest->width);
Q_ASSERT(src->height == dest->height);
@@ -590,7 +571,10 @@ static void convert_RGB_to_RGB30(QImageData *dest, const QImageData *src, Qt::Im
for (int i = 0; i < src->height; ++i) {
const quint32 *end = src_data + src->width;
while (src_data < end) {
- *dest_data = qConvertRgb32ToRgb30<PixelOrder>(*src_data);
+ QRgb c = *src_data;
+ if (RGBA)
+ c = RGBA2ARGB(c);
+ *dest_data = qConvertRgb32ToRgb30<PixelOrder>(c);
++src_data;
++dest_data;
}
@@ -599,10 +583,11 @@ static void convert_RGB_to_RGB30(QImageData *dest, const QImageData *src, Qt::Im
}
}
-template<QtPixelOrder PixelOrder>
+template<QtPixelOrder PixelOrder, bool RGBA>
static bool convert_RGB_to_RGB30_inplace(QImageData *data, Qt::ImageConversionFlags)
{
- Q_ASSERT(data->format == QImage::Format_RGB32 || data->format == QImage::Format_ARGB32);
+ Q_ASSERT(RGBA || (data->format == QImage::Format_RGB32 || data->format == QImage::Format_ARGB32));
+ Q_ASSERT(!RGBA || (data->format == QImage::Format_RGBX8888 || data->format == QImage::Format_RGBA8888));
const int pad = (data->bytes_per_line >> 2) - data->width;
QRgb *rgb_data = (QRgb *) data->data;
@@ -610,7 +595,10 @@ static bool convert_RGB_to_RGB30_inplace(QImageData *data, Qt::ImageConversionFl
for (int i = 0; i < data->height; ++i) {
const QRgb *end = rgb_data + data->width;
while (rgb_data < end) {
- *rgb_data = qConvertRgb32ToRgb30<PixelOrder>(*rgb_data);
+ QRgb c = *rgb_data;
+ if (RGBA)
+ c = RGBA2ARGB(c);
+ *rgb_data = qConvertRgb32ToRgb30<PixelOrder>(c);
++rgb_data;
}
rgb_data += pad;
@@ -771,11 +759,11 @@ static bool convert_BGR30_to_A2RGB30_inplace(QImageData *data, Qt::ImageConversi
return true;
}
-template<QtPixelOrder PixelOrder>
+template<QtPixelOrder PixelOrder, bool RGBA>
static void convert_A2RGB30_PM_to_ARGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{
Q_ASSERT(src->format == QImage::Format_A2RGB30_Premultiplied || src->format == QImage::Format_A2BGR30_Premultiplied);
- Q_ASSERT(dest->format == QImage::Format_ARGB32);
+ Q_ASSERT(RGBA ? dest->format == QImage::Format_RGBA8888 : dest->format == QImage::Format_ARGB32);
Q_ASSERT(src->width == dest->width);
Q_ASSERT(src->height == dest->height);
@@ -788,6 +776,8 @@ static void convert_A2RGB30_PM_to_ARGB(QImageData *dest, const QImageData *src,
const quint32 *end = src_data + src->width;
while (src_data < end) {
*dest_data = qConvertA2rgb30ToArgb32<PixelOrder>(qUnpremultiplyRgb30(*src_data));
+ if (RGBA)
+ *dest_data = ARGB2RGBA(*dest_data);
++src_data;
++dest_data;
}
@@ -796,7 +786,7 @@ static void convert_A2RGB30_PM_to_ARGB(QImageData *dest, const QImageData *src,
}
}
-template<QtPixelOrder PixelOrder>
+template<QtPixelOrder PixelOrder, bool RGBA>
static bool convert_A2RGB30_PM_to_ARGB_inplace(QImageData *data, Qt::ImageConversionFlags)
{
Q_ASSERT(data->format == QImage::Format_A2RGB30_Premultiplied || data->format == QImage::Format_A2BGR30_Premultiplied);
@@ -808,11 +798,16 @@ static bool convert_A2RGB30_PM_to_ARGB_inplace(QImageData *data, Qt::ImageConver
const uint *end = rgb_data + data->width;
while (rgb_data < end) {
*rgb_data = qConvertA2rgb30ToArgb32<PixelOrder>(qUnpremultiplyRgb30(*rgb_data));
+ if (RGBA)
+ *rgb_data = ARGB2RGBA(*rgb_data);
++rgb_data;
}
rgb_data += pad;
}
- data->format = QImage::Format_ARGB32;
+ if (RGBA)
+ data->format = QImage::Format_RGBA8888;
+ else
+ data->format = QImage::Format_ARGB32;
return true;
}
@@ -1188,6 +1183,270 @@ static bool mask_alpha_converter_rgbx_inplace(QImageData *data, Qt::ImageConvers
#endif
}
+template<bool RGBA>
+static void convert_RGBA64_to_ARGB32(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_RGBA64);
+ Q_ASSERT(RGBA || dest->format == QImage::Format_ARGB32);
+ Q_ASSERT(!RGBA || dest->format == QImage::Format_RGBA8888);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const uchar *srcData = src->data;
+ uchar *destData = dest->data;
+
+ for (int i = 0; i < src->height; ++i) {
+ uint *d = reinterpret_cast<uint *>(destData);
+ const QRgba64 *s = reinterpret_cast<const QRgba64 *>(srcData);
+ qt_convertRGBA64ToARGB32<RGBA>(d, s, src->width);
+ srcData += src->bytes_per_line;
+ destData += dest->bytes_per_line;
+ }
+}
+
+template<bool RGBA>
+static void convert_RGBA64PM_to_ARGB32(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_RGBA64_Premultiplied);
+ Q_ASSERT(RGBA || dest->format == QImage::Format_ARGB32);
+ Q_ASSERT(!RGBA || dest->format == QImage::Format_RGBA8888);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 3) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
+ const QRgba64 *src_data = reinterpret_cast<const QRgba64 *>(src->data);
+ uint *dest_data = reinterpret_cast<uint *>(dest->data);
+
+ for (int i = 0; i < src->height; ++i) {
+ const QRgba64 *end = src_data + src->width;
+ while (src_data < end) {
+ QRgba64 s = src_data->unpremultiplied();
+ *dest_data = RGBA ? ARGB2RGBA(s.toArgb32()) : s.toArgb32();
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+template<bool RGBA>
+static void convert_ARGB32_to_RGBA64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(RGBA || src->format == QImage::Format_ARGB32);
+ Q_ASSERT(!RGBA || src->format == QImage::Format_RGBA8888);
+ Q_ASSERT(dest->format == QImage::Format_RGBA64);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 2) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 3) - dest->width;
+ const uint *src_data = reinterpret_cast<const uint *>(src->data);
+ QRgba64 *dest_data = reinterpret_cast<QRgba64 *>(dest->data);
+
+ for (int i = 0; i < src->height; ++i) {
+ const uint *end = src_data + src->width;
+ while (src_data < end) {
+ if (RGBA)
+ *dest_data = QRgba64::fromArgb32(RGBA2ARGB(*src_data));
+ else
+ *dest_data = QRgba64::fromArgb32(*src_data);
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+template<QtPixelOrder PixelOrder>
+static void convert_RGBA64PM_to_RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_RGBA64_Premultiplied);
+ Q_ASSERT(dest->format == QImage::Format_RGB30 || dest->format == QImage::Format_BGR30);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 3) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
+ const QRgba64 *src_data = reinterpret_cast<const QRgba64 *>(src->data);
+ uint *dest_data = reinterpret_cast<uint *>(dest->data);
+
+ for (int i = 0; i < src->height; ++i) {
+ const QRgba64 *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = 0xc0000000 | qConvertRgb64ToRgb30<PixelOrder>(src_data->unpremultiplied());
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+template<QtPixelOrder PixelOrder>
+static void convert_RGBA64PM_to_A2RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_RGBA64_Premultiplied);
+ Q_ASSERT(dest->format == QImage::Format_A2RGB30_Premultiplied
+ || dest->format == QImage::Format_A2BGR30_Premultiplied);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 3) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 2) - dest->width;
+ const QRgba64 *src_data = reinterpret_cast<const QRgba64 *>(src->data);
+ uint *dest_data = reinterpret_cast<uint *>(dest->data);
+
+ for (int i = 0; i < src->height; ++i) {
+ const QRgba64 *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = qConvertRgb64ToRgb30<PixelOrder>(*src_data);
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+static void convert_RGBA64_to_RGBx64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_RGBA64);
+ Q_ASSERT(dest->format == QImage::Format_RGBX64);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 3) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 3) - dest->width;
+ const QRgba64 *src_data = reinterpret_cast<const QRgba64 *>(src->data);
+ QRgba64 *dest_data = reinterpret_cast<QRgba64 *>(dest->data);
+
+ for (int i = 0; i < src->height; ++i) {
+ const QRgba64 *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = *src_data;
+ dest_data->setAlpha(65535);
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+static bool convert_RGBA64_to_RGBx64_inplace(QImageData *data, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(data->format == QImage::Format_RGBA64);
+
+ const int pad = (data->bytes_per_line >> 3) - data->width;
+ QRgba64 *rgb_data = reinterpret_cast<QRgba64 *>(data->data);
+
+ for (int i = 0; i < data->height; ++i) {
+ const QRgba64 *end = rgb_data + data->width;
+ while (rgb_data < end) {
+ rgb_data->setAlpha(65535);
+ ++rgb_data;
+ }
+ rgb_data += pad;
+ }
+ data->format = QImage::Format_RGBX64;
+ return true;
+}
+
+static void convert_RGBA64_to_RGBA64PM(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_RGBA64);
+ Q_ASSERT(dest->format == QImage::Format_RGBA64_Premultiplied);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 3) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 3) - dest->width;
+ const QRgba64 *src_data = reinterpret_cast<const QRgba64 *>(src->data);
+ QRgba64 *dest_data = reinterpret_cast<QRgba64 *>(dest->data);
+
+ for (int i = 0; i < src->height; ++i) {
+ const QRgba64 *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = src_data->premultiplied();
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+static bool convert_RGBA64_to_RGBA64PM_inplace(QImageData *data, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(data->format == QImage::Format_RGBA64);
+
+ const int pad = (data->bytes_per_line >> 3) - data->width;
+ QRgba64 *rgb_data = reinterpret_cast<QRgba64 *>(data->data);
+
+ for (int i = 0; i < data->height; ++i) {
+ const QRgba64 *end = rgb_data + data->width;
+ while (rgb_data < end) {
+ *rgb_data = rgb_data->premultiplied();
+ ++rgb_data;
+ }
+ rgb_data += pad;
+ }
+ data->format = QImage::Format_RGBA64_Premultiplied;
+ return true;
+}
+
+template<bool MaskAlpha>
+static void convert_RGBA64PM_to_RGBA64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_RGBA64_Premultiplied);
+ Q_ASSERT(dest->format == QImage::Format_RGBA64 || dest->format == QImage::Format_RGBX64);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 3) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 3) - dest->width;
+ const QRgba64 *src_data = reinterpret_cast<const QRgba64 *>(src->data);
+ QRgba64 *dest_data = reinterpret_cast<QRgba64 *>(dest->data);
+
+ for (int i = 0; i < src->height; ++i) {
+ const QRgba64 *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = src_data->unpremultiplied();
+ if (MaskAlpha)
+ dest_data->setAlpha(65535);
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+template<bool MaskAlpha>
+static bool convert_RGBA64PM_to_RGBA64_inplace(QImageData *data, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(data->format == QImage::Format_RGBA64_Premultiplied);
+
+ const int pad = (data->bytes_per_line >> 3) - data->width;
+ QRgba64 *rgb_data = reinterpret_cast<QRgba64 *>(data->data);
+
+ for (int i = 0; i < data->height; ++i) {
+ const QRgba64 *end = rgb_data + data->width;
+ while (rgb_data < end) {
+ *rgb_data = rgb_data->unpremultiplied();
+ if (MaskAlpha)
+ rgb_data->setAlpha(65535);
+ ++rgb_data;
+ }
+ rgb_data += pad;
+ }
+ data->format = MaskAlpha ? QImage::Format_RGBX64 : QImage::Format_RGBA64;
+ return true;
+}
+
static QVector<QRgb> fix_color_table(const QVector<QRgb> &ctbl, QImage::Format format)
{
QVector<QRgb> colorTable = ctbl;
@@ -2032,7 +2291,7 @@ static bool convert_Grayscale8_to_Indexed8_inplace(QImageData *data, Qt::ImageCo
Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormats] =
{
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
},
{
0,
@@ -2053,7 +2312,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_Mono
{
@@ -2075,7 +2334,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_MonoLSB
{
@@ -2100,6 +2359,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0, 0, 0, 0, 0,
convert_Indexed8_to_Alpha8,
convert_Indexed8_to_Grayscale8,
+ 0, 0, 0
}, // Format_Indexed8
{
@@ -2122,11 +2382,12 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- convert_RGB_to_RGB30<PixelOrderBGR>,
+ convert_RGB_to_RGB30<PixelOrderBGR, false>,
0,
- convert_RGB_to_RGB30<PixelOrderRGB>,
+ convert_RGB_to_RGB30<PixelOrderRGB, false>,
0,
- 0, 0
+ 0, 0,
+ 0, 0, 0
}, // Format_RGB32
{
@@ -2136,7 +2397,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_ARGB_to_Indexed8,
mask_alpha_converter,
0,
- convert_ARGB_to_ARGB_PM,
+ 0,
0,
0,
0,
@@ -2149,11 +2410,14 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_ARGB_to_RGBx,
convert_ARGB_to_RGBA,
0,
- convert_RGB_to_RGB30<PixelOrderBGR>,
+ convert_RGB_to_RGB30<PixelOrderBGR, false>,
0,
- convert_RGB_to_RGB30<PixelOrderRGB>,
+ convert_RGB_to_RGB30<PixelOrderRGB, false>,
0,
- 0, 0
+ 0, 0,
+ 0,
+ convert_ARGB32_to_RGBA64<false>,
+ 0
}, // Format_ARGB32
{
@@ -2176,11 +2440,9 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
convert_ARGB_to_RGBA,
- 0,
- 0,
- 0,
- 0,
- 0, 0
+ 0, 0, 0, 0,
+ 0, 0,
+ 0, 0, 0
}, // Format_ARGB32_Premultiplied
{
@@ -2202,7 +2464,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB16
{
@@ -2224,7 +2486,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_ARGB8565_Premultiplied
{
@@ -2246,7 +2508,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB666
{
@@ -2268,7 +2530,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_ARGB6666_Premultiplied
{
@@ -2290,7 +2552,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB555
{
@@ -2312,7 +2574,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_ARGB8555_Premultiplied
{
@@ -2335,7 +2597,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_RGB888_to_RGB<true>,
convert_RGB888_to_RGB<true>,
convert_RGB888_to_RGB<true>,
- 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB888
{
@@ -2357,7 +2619,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB444
{
@@ -2378,7 +2640,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_ARGB4444_Premultiplied
{
0,
@@ -2398,9 +2660,14 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- mask_alpha_converter_RGBx,
- mask_alpha_converter_RGBx,
- 0, 0, 0, 0, 0, 0
+ convert_passthrough,
+ convert_passthrough,
+ convert_RGB_to_RGB30<PixelOrderBGR, true>,
+ 0,
+ convert_RGB_to_RGB30<PixelOrderRGB, true>,
+ 0,
+ 0, 0,
+ 0, 0, 0
}, // Format_RGBX8888
{
0,
@@ -2420,14 +2687,16 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
mask_alpha_converter_RGBx,
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
0,
- convert_ARGB_to_ARGB_PM,
-#else
0,
+ convert_RGB_to_RGB30<PixelOrderBGR, true>,
0,
-#endif
- 0, 0, 0, 0, 0, 0
+ convert_RGB_to_RGB30<PixelOrderRGB, true>,
+ 0,
+ 0, 0,
+ 0,
+ convert_ARGB32_to_RGBA64<true>,
+ 0
}, // Format_RGBA8888
{
@@ -2449,7 +2718,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGBA8888_Premultiplied
{
@@ -2476,7 +2745,8 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_passthrough,
convert_BGR30_to_RGB30,
convert_BGR30_to_RGB30,
- 0, 0
+ 0, 0,
+ 0, 0, 0
}, // Format_BGR30
{
0,
@@ -2484,8 +2754,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- convert_A2RGB30_PM_to_ARGB<PixelOrderBGR>,
- 0,
+ convert_A2RGB30_PM_to_ARGB<PixelOrderBGR, false>,
0,
0,
0,
@@ -2497,12 +2766,14 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
+ convert_A2RGB30_PM_to_ARGB<PixelOrderBGR, true>,
0,
convert_A2RGB30_PM_to_RGB30<false>,
0,
convert_A2RGB30_PM_to_RGB30<true>,
convert_BGR30_to_RGB30,
- 0, 0
+ 0, 0,
+ 0, 0, 0
}, // Format_BGR30A2_Premultiplied
{
0,
@@ -2528,7 +2799,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_BGR30_to_RGB30,
0,
convert_passthrough,
- 0, 0
+ 0, 0, 0, 0, 0
}, // Format_RGB30
{
0,
@@ -2536,8 +2807,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- convert_A2RGB30_PM_to_ARGB<PixelOrderRGB>,
- 0,
+ convert_A2RGB30_PM_to_ARGB<PixelOrderRGB, false>,
0,
0,
0,
@@ -2549,12 +2819,14 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
+ convert_A2RGB30_PM_to_ARGB<PixelOrderRGB, true>,
0,
convert_A2RGB30_PM_to_RGB30<true>,
convert_BGR30_to_RGB30,
convert_A2RGB30_PM_to_RGB30<false>,
0,
- 0, 0
+ 0, 0,
+ 0, 0, 0
}, // Format_RGB30A2_Premultiplied
{
0,
@@ -2574,7 +2846,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_Alpha8
{
0,
@@ -2594,20 +2866,81 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
- 0, 0, 0, 0, 0, 0, 0
- } // Format_Grayscale8
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ }, // Format_Grayscale8
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, // self
+ convert_passthrough,
+ convert_passthrough
+ }, // Format_RGBX64
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_RGBA64_to_ARGB32<false>,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_RGBA64_to_ARGB32<true>,
+ 0,
+ 0, 0, 0, 0,
+ 0, 0,
+ convert_RGBA64_to_RGBx64,
+ 0, // self
+ convert_RGBA64_to_RGBA64PM
+ }, // Format_RGBA64
+ {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_RGBA64PM_to_ARGB32<false>,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ convert_RGBA64PM_to_ARGB32<true>,
+ 0,
+ convert_RGBA64PM_to_RGB30<PixelOrderBGR>,
+ convert_RGBA64PM_to_A2RGB30<PixelOrderBGR>,
+ convert_RGBA64PM_to_RGB30<PixelOrderRGB>,
+ convert_RGBA64PM_to_A2RGB30<PixelOrderRGB>,
+ 0, 0,
+ convert_RGBA64PM_to_RGBA64<true>,
+ convert_RGBA64PM_to_RGBA64<false>,
+ 0 // self
+ } // Format_RGBA64_Premultiplied
};
InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QImage::NImageFormats] =
{
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
},
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_Mono
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_MonoLSB
{
0,
@@ -2631,6 +2964,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0, 0, 0, 0, 0,
convert_Indexed8_to_Alpha8_inplace,
convert_Indexed8_to_Grayscale8_inplace,
+ 0, 0, 0
}, // Format_Indexed8
{
0,
@@ -2652,11 +2986,12 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
- convert_RGB_to_RGB30_inplace<PixelOrderBGR>,
+ convert_RGB_to_RGB30_inplace<PixelOrderBGR, false>,
0,
- convert_RGB_to_RGB30_inplace<PixelOrderRGB>,
+ convert_RGB_to_RGB30_inplace<PixelOrderRGB, false>,
0,
- 0, 0
+ 0, 0,
+ 0, 0, 0
}, // Format_RGB32
{
0,
@@ -2665,11 +3000,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
mask_alpha_converter_inplace<QImage::Format_RGB32>,
0,
-#ifdef __SSE2__
- convert_ARGB_to_ARGB_PM_inplace_sse2,
-#else
- convert_ARGB_to_ARGB_PM_inplace,
-#endif
+ 0,
0,
0,
0,
@@ -2682,11 +3013,12 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
convert_ARGB_to_RGBA_inplace<QImage::Format_RGBX8888>,
convert_ARGB_to_RGBA_inplace<QImage::Format_RGBA8888>,
0,
- convert_RGB_to_RGB30_inplace<PixelOrderBGR>,
+ convert_RGB_to_RGB30_inplace<PixelOrderBGR, false>,
0,
- convert_RGB_to_RGB30_inplace<PixelOrderRGB>,
+ convert_RGB_to_RGB30_inplace<PixelOrderRGB, false>,
0,
- 0, 0
+ 0, 0,
+ 0, 0, 0
}, // Format_ARGB32
{
0,
@@ -2708,38 +3040,36 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
convert_ARGB_to_RGBA_inplace<QImage::Format_RGBA8888_Premultiplied>,
- 0,
- 0,
- 0,
- 0,
- 0, 0
+ 0, 0, 0, 0,
+ 0, 0,
+ 0, 0, 0
}, // Format_ARGB32_Premultiplied
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB16
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_ARGB8565_Premultiplied
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB666
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_ARGB6666_Premultiplied
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB555
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_ARGB8555_Premultiplied
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB888
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB444
{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_ARGB4444_Premultiplied
{
0,
@@ -2761,7 +3091,12 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
convert_passthrough_inplace<QImage::Format_RGBA8888>,
convert_passthrough_inplace<QImage::Format_RGBA8888_Premultiplied>,
- 0, 0, 0, 0, 0, 0
+ convert_RGB_to_RGB30_inplace<PixelOrderBGR, true>,
+ 0,
+ convert_RGB_to_RGB30_inplace<PixelOrderRGB, true>,
+ 0,
+ 0, 0,
+ 0, 0, 0
}, // Format_RGBX8888
{
0,
@@ -2782,14 +3117,13 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
mask_alpha_converter_rgbx_inplace,
0,
-#ifdef __SSE2__
- convert_ARGB_to_ARGB_PM_inplace_sse2,
-#elif Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- convert_ARGB_to_ARGB_PM_inplace,
-#else
0,
-#endif
- 0, 0, 0, 0, 0, 0
+ convert_RGB_to_RGB30_inplace<PixelOrderBGR, true>,
+ 0,
+ convert_RGB_to_RGB30_inplace<PixelOrderRGB, true>,
+ 0,
+ 0, 0,
+ 0, 0, 0
}, // Format_RGBA8888
{
0,
@@ -2811,7 +3145,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
- 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGBA8888_Premultiplied
{
0,
@@ -2837,7 +3171,8 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
convert_passthrough_inplace<QImage::Format_A2BGR30_Premultiplied>,
convert_BGR30_to_RGB30_inplace,
convert_BGR30_to_A2RGB30_inplace,
- 0, 0
+ 0, 0,
+ 0, 0, 0
}, // Format_BGR30
{
0,
@@ -2845,8 +3180,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
- convert_A2RGB30_PM_to_ARGB_inplace<PixelOrderBGR>,
- 0,
+ convert_A2RGB30_PM_to_ARGB_inplace<PixelOrderBGR, false>,
0,
0,
0,
@@ -2858,12 +3192,13 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
+ convert_A2RGB30_PM_to_ARGB_inplace<PixelOrderBGR, true>,
0,
convert_A2RGB30_PM_to_RGB30_inplace<false>,
0, // self
convert_A2RGB30_PM_to_RGB30_inplace<true>,
convert_BGR30_to_RGB30_inplace,
- 0, 0
+ 0, 0, 0, 0, 0
}, // Format_BGR30A2_Premultiplied
{
0,
@@ -2889,7 +3224,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
convert_BGR30_to_A2RGB30_inplace,
0, // self
convert_passthrough_inplace<QImage::Format_A2RGB30_Premultiplied>,
- 0, 0
+ 0, 0, 0, 0, 0
}, // Format_RGB30
{
0,
@@ -2897,8 +3232,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
- convert_A2RGB30_PM_to_ARGB_inplace<PixelOrderRGB>,
- 0,
+ convert_A2RGB30_PM_to_ARGB_inplace<PixelOrderRGB, false>,
0,
0,
0,
@@ -2910,12 +3244,14 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
+ convert_A2RGB30_PM_to_ARGB_inplace<PixelOrderRGB, true>,
0,
convert_A2RGB30_PM_to_RGB30_inplace<true>,
convert_BGR30_to_RGB30_inplace,
convert_A2RGB30_PM_to_RGB30_inplace<false>,
0, // self
- 0, 0
+ 0, 0,
+ 0, 0, 0
}, // Format_RGB30A2_Premultiplied
{
0,
@@ -2937,11 +3273,10 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
+ 0, 0, 0, 0,
+ 0, // self
0,
- 0,
- 0,
- 0,
- 0, 0
+ 0, 0, 0
}, // Format_Alpha8
{
0,
@@ -2963,12 +3298,29 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
+ 0, 0, 0, 0,
0,
- 0,
- 0,
- 0,
- 0, 0
- } // Format_Grayscale8
+ 0, // self
+ 0, 0, 0
+ }, // Format_Grayscale8
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, // self
+ convert_passthrough_inplace<QImage::Format_RGBA64>,
+ convert_passthrough_inplace<QImage::Format_RGBA64_Premultiplied>,
+ }, // Format_RGBX64
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ convert_RGBA64_to_RGBx64_inplace,
+ 0, // self
+ convert_RGBA64_to_RGBA64PM_inplace
+ }, // Format_RGBA64
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ convert_RGBA64PM_to_RGBA64_inplace<true>,
+ convert_RGBA64PM_to_RGBA64_inplace<false>,
+ 0 // self
+ } // Format_RGBA64_Premultiplied
};
static void qInitImageConversions()
@@ -2982,22 +3334,6 @@ static void qInitImageConversions()
}
#endif
-#if defined(QT_COMPILER_SUPPORTS_SSE4_1) && !defined(__SSE4_1__)
- if (qCpuHasFeature(SSE4_1)) {
- extern void convert_ARGB_to_ARGB_PM_sse4(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
- qimage_converter_map[QImage::Format_ARGB32][QImage::Format_ARGB32_Premultiplied] = convert_ARGB_to_ARGB_PM_sse4;
- qimage_converter_map[QImage::Format_RGBA8888][QImage::Format_RGBA8888_Premultiplied] = convert_ARGB_to_ARGB_PM_sse4;
- }
-#endif
-
-#if defined(QT_COMPILER_SUPPORTS_AVX2) && !defined(__AVX2__)
- if (qCpuHasFeature(AVX2)) {
- extern void convert_ARGB_to_ARGB_PM_avx2(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
- qimage_converter_map[QImage::Format_ARGB32][QImage::Format_ARGB32_Premultiplied] = convert_ARGB_to_ARGB_PM_avx2;
- qimage_converter_map[QImage::Format_RGBA8888][QImage::Format_RGBA8888_Premultiplied] = convert_ARGB_to_ARGB_PM_avx2;
- }
-#endif
-
#if defined(__ARM_NEON__)
extern void convert_RGB888_to_RGB32_neon(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
qimage_converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_neon;
diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h
index f5fea2ed00..2fe29a88d3 100644
--- a/src/gui/image/qimage_p.h
+++ b/src/gui/image/qimage_p.h
@@ -113,6 +113,7 @@ extern Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImag
extern InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QImage::NImageFormats];
void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
+void convert_generic_to_rgb64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags);
void dither_to_Mono(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags, bool fromalpha);
@@ -164,6 +165,11 @@ inline int qt_depthForFormat(QImage::Format format)
case QImage::Format_RGB888:
depth = 24;
break;
+ case QImage::Format_RGBX64:
+ case QImage::Format_RGBA64:
+ case QImage::Format_RGBA64_Premultiplied:
+ depth = 64;
+ break;
}
return depth;
}
@@ -190,6 +196,9 @@ inline QImage::Format qt_opaqueVersion(QImage::Format format)
return QImage::Format_BGR30;
case QImage::Format_A2RGB30_Premultiplied:
return QImage::Format_RGB30;
+ case QImage::Format_RGBA64:
+ case QImage::Format_RGBA64_Premultiplied:
+ return QImage::Format_RGBX64;
case QImage::Format_ARGB32_Premultiplied:
case QImage::Format_ARGB32:
default:
@@ -214,6 +223,8 @@ inline QImage::Format qt_alphaVersion(QImage::Format format)
return QImage::Format_A2BGR30_Premultiplied;
case QImage::Format_RGB30:
return QImage::Format_A2RGB30_Premultiplied;
+ case QImage::Format_RGBX64:
+ return QImage::Format_RGBA64_Premultiplied;
default:
break;
}
diff --git a/src/gui/image/qimage_sse2.cpp b/src/gui/image/qimage_sse2.cpp
deleted file mode 100644
index 8f7195e0b5..0000000000
--- a/src/gui/image/qimage_sse2.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qimage.h"
-#include <private/qimage_p.h>
-#include <private/qsimd_p.h>
-#include <private/qdrawhelper_p.h>
-#include <private/qdrawingprimitive_sse2_p.h>
-
-#ifdef QT_COMPILER_SUPPORTS_SSE2
-
-QT_BEGIN_NAMESPACE
-
-bool convert_ARGB_to_ARGB_PM_inplace_sse2(QImageData *data, Qt::ImageConversionFlags)
-{
- Q_ASSERT(data->format == QImage::Format_ARGB32 || data->format == QImage::Format_RGBA8888);
-
- const int width = data->width;
- const int height = data->height;
- const int bpl = data->bytes_per_line;
-
- const __m128i alphaMask = _mm_set1_epi32(0xff000000);
- const __m128i nullVector = _mm_setzero_si128();
- const __m128i half = _mm_set1_epi16(0x80);
- const __m128i colorMask = _mm_set1_epi32(0x00ff00ff);
-
- uchar *d = data->data;
- for (int y = 0; y < height; ++y) {
- int i = 0;
- quint32 *d32 = reinterpret_cast<quint32 *>(d);
- ALIGNMENT_PROLOGUE_16BYTES(d, i, width) {
- const quint32 p = d32[i];
- if (p <= 0x00ffffff)
- d32[i] = 0;
- else if (p < 0xff000000)
- d32[i] = qPremultiply(p);
- }
- __m128i *d128 = reinterpret_cast<__m128i *>(d32 + i);
- for (; i < (width - 3); i += 4) {
- const __m128i srcVector = _mm_load_si128(d128);
-#ifdef __SSE4_1__
- if (_mm_testc_si128(srcVector, alphaMask)) {
- // opaque, data is unchanged
- } else if (_mm_testz_si128(srcVector, alphaMask)) {
- // fully transparent
- _mm_store_si128(d128, nullVector);
- } else {
- const __m128i srcVectorAlpha = _mm_and_si128(srcVector, alphaMask);
-#else
- const __m128i srcVectorAlpha = _mm_and_si128(srcVector, alphaMask);
- if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, alphaMask)) == 0xffff) {
- // opaque, data is unchanged
- } else if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, nullVector)) == 0xffff) {
- // fully transparent
- _mm_store_si128(d128, nullVector);
- } else {
-#endif
- __m128i alphaChannel = _mm_srli_epi32(srcVector, 24);
- alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16));
-
- __m128i result;
- BYTE_MUL_SSE2(result, srcVector, alphaChannel, colorMask, half);
- result = _mm_or_si128(_mm_andnot_si128(alphaMask, result), srcVectorAlpha);
- _mm_store_si128(d128, result);
- }
- d128++;
- }
-
- SIMD_EPILOGUE(i, width, 3) {
- const quint32 p = d32[i];
- if (p <= 0x00ffffff)
- d32[i] = 0;
- else if (p < 0xff000000)
- d32[i] = qPremultiply(p);
- }
-
- d += bpl;
- }
-
- if (data->format == QImage::Format_ARGB32)
- data->format = QImage::Format_ARGB32_Premultiplied;
- else
- data->format = QImage::Format_RGBA8888_Premultiplied;
- return true;
-}
-
-QT_END_NAMESPACE
-
-#endif // QT_COMPILER_SUPPORTS_SSE2
diff --git a/src/gui/image/qimage_sse4.cpp b/src/gui/image/qimage_sse4.cpp
deleted file mode 100644
index 0e2c2f492e..0000000000
--- a/src/gui/image/qimage_sse4.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <qimage.h>
-#include <private/qdrawhelper_p.h>
-#include <private/qdrawingprimitive_sse2_p.h>
-#include <private/qimage_p.h>
-#include <private/qsimd_p.h>
-
-#ifdef QT_COMPILER_SUPPORTS_SSE4_1
-
-QT_BEGIN_NAMESPACE
-
-const uint *QT_FASTCALL convertRGB32FromARGB32PM_sse4(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
-{
- for (int i = 0; i < count; ++i)
- buffer[i] = 0xff000000 | qUnpremultiply_sse4(src[i]);
- return buffer;
-}
-
-void convert_ARGB_to_ARGB_PM_sse4(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
-{
- Q_ASSERT(src->format == QImage::Format_ARGB32 || src->format == QImage::Format_RGBA8888);
- Q_ASSERT(dest->format == QImage::Format_ARGB32_Premultiplied || dest->format == QImage::Format_RGBA8888_Premultiplied);
- Q_ASSERT(src->width == dest->width);
- Q_ASSERT(src->height == dest->height);
-
- const uint *src_data = (uint *) src->data;
- uint *dest_data = (uint *) dest->data;
- for (int i = 0; i < src->height; ++i) {
- qt_convertARGB32ToARGB32PM(dest_data, src_data, src->width);
- src_data += src->bytes_per_line >> 2;
- dest_data += dest->bytes_per_line >> 2;
- }
-}
-
-QT_END_NAMESPACE
-
-#endif // QT_COMPILER_SUPPORTS_SSE4_1
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index 7086e102ea..0fb1d808e5 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -164,73 +164,14 @@
#include <private/qpnghandler_p.h>
#endif
+#include <private/qimagereaderwriterhelpers_p.h>
+#include <qtgui_tracepoints_p.h>
+
#include <algorithm>
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_IMAGEFORMATPLUGIN
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
- (QImageIOHandlerFactoryInterface_iid, QLatin1String("/imageformats")))
-#endif
-
-enum _qt_BuiltInFormatType {
-#ifndef QT_NO_IMAGEFORMAT_PNG
- _qt_PngFormat,
-#endif
-#ifndef QT_NO_IMAGEFORMAT_BMP
- _qt_BmpFormat,
-#endif
-#ifndef QT_NO_IMAGEFORMAT_PPM
- _qt_PpmFormat,
- _qt_PgmFormat,
- _qt_PbmFormat,
-#endif
-#ifndef QT_NO_IMAGEFORMAT_XBM
- _qt_XbmFormat,
-#endif
-#ifndef QT_NO_IMAGEFORMAT_XPM
- _qt_XpmFormat,
-#endif
- _qt_NumFormats,
- _qt_NoFormat = -1
-};
-
-#if !defined(QT_NO_IMAGEFORMAT_PPM)
-# define MAX_MT_SIZE 20
-#elif !defined(QT_NO_IMAGEFORMAT_XBM) || !defined(QT_NO_IMAGEFORMAT_XPM)
-# define MAX_MT_SIZE 10
-#else
-# define MAX_MT_SIZE 4
-#endif
-
-struct _qt_BuiltInFormatStruct
-{
- char extension[4];
- char mimeType[MAX_MT_SIZE];
-};
-
-#undef MAX_MT_SIZE
-
-static const _qt_BuiltInFormatStruct _qt_BuiltInFormats[] = {
-#ifndef QT_NO_IMAGEFORMAT_PNG
- {"png", "png"},
-#endif
-#ifndef QT_NO_IMAGEFORMAT_BMP
- {"bmp", "bmp"},
-#endif
-#ifndef QT_NO_IMAGEFORMAT_PPM
- {"ppm", "x-portable-pixmap"},
- {"pgm", "x-portable-graymap"},
- {"pbm", "x-portable-bitmap"},
-#endif
-#ifndef QT_NO_IMAGEFORMAT_XBM
- {"xbm", "x-xbitmap"},
-#endif
-#ifndef QT_NO_IMAGEFORMAT_XPM
- {"xpm", "x-xpixmap"},
-#endif
-};
-Q_STATIC_ASSERT(_qt_NumFormats == sizeof _qt_BuiltInFormats / sizeof *_qt_BuiltInFormats);
+using namespace QImageReaderWriterHelpers;
static QImageIOHandler *createReadHandlerHelper(QIODevice *device,
const QByteArray &format,
@@ -251,7 +192,7 @@ static QImageIOHandler *createReadHandlerHelper(QIODevice *device,
typedef QMultiMap<int, QString> PluginKeyMap;
// check if we have plugins that support the image format
- QFactoryLoader *l = loader();
+ auto l = QImageReaderWriterHelpers::pluginLoader();
const PluginKeyMap keyMap = l->keyMap();
#ifdef QIMAGEREADER_DEBUG
@@ -1310,7 +1251,18 @@ bool QImageReader::read(QImage *image)
d->handler->setOption(QImageIOHandler::Quality, d->quality);
// read the image
- if (!d->handler->read(image)) {
+ if (Q_TRACE_ENABLED(QImageReader_read_before_reading)) {
+ QString fileName = QStringLiteral("unknown");
+ if (QFile *file = qobject_cast<QFile *>(d->device))
+ fileName = file->fileName();
+ Q_TRACE(QImageReader_read_before_reading, this, fileName);
+ }
+
+ const bool result = d->handler->read(image);
+
+ Q_TRACE(QImageReader_read_after_reading, this, result);
+
+ if (!result) {
d->imageReaderError = InvalidDataError;
d->errorString = QImageReader::tr("Unable to read image data");
return false;
@@ -1565,16 +1517,6 @@ QByteArray QImageReader::imageFormat(QIODevice *device)
return format;
}
-#ifndef QT_NO_IMAGEFORMATPLUGIN
-void supportedImageHandlerFormats(QFactoryLoader *loader,
- QImageIOPlugin::Capability cap,
- QList<QByteArray> *result);
-
-void supportedImageHandlerMimeTypes(QFactoryLoader *loader,
- QImageIOPlugin::Capability cap,
- QList<QByteArray> *result);
-#endif
-
/*!
Returns the list of image formats supported by QImageReader.
@@ -1605,18 +1547,7 @@ void supportedImageHandlerMimeTypes(QFactoryLoader *loader,
QList<QByteArray> QImageReader::supportedImageFormats()
{
- QList<QByteArray> formats;
- formats.reserve(_qt_NumFormats);
- for (int i = 0; i < _qt_NumFormats; ++i)
- formats << _qt_BuiltInFormats[i].extension;
-
-#ifndef QT_NO_IMAGEFORMATPLUGIN
- supportedImageHandlerFormats(loader(), QImageIOPlugin::CanRead, &formats);
-#endif // QT_NO_IMAGEFORMATPLUGIN
-
- std::sort(formats.begin(), formats.end());
- formats.erase(std::unique(formats.begin(), formats.end()), formats.end());
- return formats;
+ return QImageReaderWriterHelpers::supportedImageFormats(QImageReaderWriterHelpers::CanRead);
}
/*!
@@ -1630,18 +1561,24 @@ QList<QByteArray> QImageReader::supportedImageFormats()
QList<QByteArray> QImageReader::supportedMimeTypes()
{
- QList<QByteArray> mimeTypes;
- mimeTypes.reserve(_qt_NumFormats);
- for (const auto &fmt : _qt_BuiltInFormats)
- mimeTypes.append(QByteArrayLiteral("image/") + fmt.mimeType);
+ return QImageReaderWriterHelpers::supportedMimeTypes(QImageReaderWriterHelpers::CanRead);
+}
-#ifndef QT_NO_IMAGEFORMATPLUGIN
- supportedImageHandlerMimeTypes(loader(), QImageIOPlugin::CanRead, &mimeTypes);
-#endif // QT_NO_IMAGEFORMATPLUGIN
+/*!
+ \since 5.12
- std::sort(mimeTypes.begin(), mimeTypes.end());
- mimeTypes.erase(std::unique(mimeTypes.begin(), mimeTypes.end()), mimeTypes.end());
- return mimeTypes;
+ Returns the list of image formats corresponding to \a mimeType.
+
+ Note that the QGuiApplication instance must be created before this function is
+ called.
+
+ \sa supportedImageFormats(), supportedMimeTypes()
+*/
+
+QList<QByteArray> QImageReader::imageFormatsForMimeType(const QByteArray &mimeType)
+{
+ return QImageReaderWriterHelpers::imageFormatsForMimeType(mimeType,
+ QImageReaderWriterHelpers::CanRead);
}
QT_END_NAMESPACE
diff --git a/src/gui/image/qimagereader.h b/src/gui/image/qimagereader.h
index 9d6c1e0b1e..4e9a08b6e6 100644
--- a/src/gui/image/qimagereader.h
+++ b/src/gui/image/qimagereader.h
@@ -144,6 +144,7 @@ public:
static QByteArray imageFormat(QIODevice *device);
static QList<QByteArray> supportedImageFormats();
static QList<QByteArray> supportedMimeTypes();
+ static QList<QByteArray> imageFormatsForMimeType(const QByteArray &mimeType);
private:
Q_DISABLE_COPY(QImageReader)
diff --git a/src/gui/image/qimagereaderwriterhelpers.cpp b/src/gui/image/qimagereaderwriterhelpers.cpp
new file mode 100644
index 0000000000..a5b7fb6449
--- /dev/null
+++ b/src/gui/image/qimagereaderwriterhelpers.cpp
@@ -0,0 +1,180 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qimagereaderwriterhelpers_p.h"
+
+#include <qjsonarray.h>
+#include <qmutex.h>
+#include <private/qfactoryloader_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QImageReaderWriterHelpers {
+
+#ifndef QT_NO_IMAGEFORMATPLUGIN
+
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
+ (QImageIOHandlerFactoryInterface_iid, QLatin1String("/imageformats")))
+Q_GLOBAL_STATIC(QMutex, loaderMutex)
+
+static void appendImagePluginFormats(QFactoryLoader *loader,
+ QImageIOPlugin::Capability cap,
+ QList<QByteArray> *result)
+{
+ typedef QMultiMap<int, QString> PluginKeyMap;
+ typedef PluginKeyMap::const_iterator PluginKeyMapConstIterator;
+
+ const PluginKeyMap keyMap = loader->keyMap();
+ const PluginKeyMapConstIterator cend = keyMap.constEnd();
+ int i = -1;
+ QImageIOPlugin *plugin = 0;
+ result->reserve(result->size() + keyMap.size());
+ for (PluginKeyMapConstIterator it = keyMap.constBegin(); it != cend; ++it) {
+ if (it.key() != i) {
+ i = it.key();
+ plugin = qobject_cast<QImageIOPlugin *>(loader->instance(i));
+ }
+ const QByteArray key = it.value().toLatin1();
+ if (plugin && (plugin->capabilities(0, key) & cap) != 0)
+ result->append(key);
+ }
+}
+
+static void appendImagePluginMimeTypes(QFactoryLoader *loader,
+ QImageIOPlugin::Capability cap,
+ QList<QByteArray> *result,
+ QList<QByteArray> *resultKeys = nullptr)
+{
+ QList<QJsonObject> metaDataList = loader->metaData();
+
+ const int pluginCount = metaDataList.size();
+ for (int i = 0; i < pluginCount; ++i) {
+ const QJsonObject metaData = metaDataList.at(i).value(QLatin1String("MetaData")).toObject();
+ const QJsonArray keys = metaData.value(QLatin1String("Keys")).toArray();
+ const QJsonArray mimeTypes = metaData.value(QLatin1String("MimeTypes")).toArray();
+ QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(loader->instance(i));
+ const int keyCount = keys.size();
+ for (int k = 0; k < keyCount; ++k) {
+ const QByteArray key = keys.at(k).toString().toLatin1();
+ if (plugin && (plugin->capabilities(0, key) & cap) != 0) {
+ result->append(mimeTypes.at(k).toString().toLatin1());
+ if (resultKeys)
+ resultKeys->append(key);
+ }
+ }
+ }
+}
+
+QSharedPointer<QFactoryLoader> pluginLoader()
+{
+ loaderMutex()->lock();
+ return QSharedPointer<QFactoryLoader>(loader(), [](QFactoryLoader *) {
+ loaderMutex()->unlock();
+ });
+}
+
+static inline QImageIOPlugin::Capability pluginCapability(Capability cap)
+{
+ return cap == CanRead ? QImageIOPlugin::CanRead : QImageIOPlugin::CanWrite;
+}
+
+#endif // QT_NO_IMAGEFORMATPLUGIN
+
+QList<QByteArray> supportedImageFormats(Capability cap)
+{
+ QList<QByteArray> formats;
+ formats.reserve(_qt_NumFormats);
+ for (int i = 0; i < _qt_NumFormats; ++i)
+ formats << _qt_BuiltInFormats[i].extension;
+
+#ifndef QT_NO_IMAGEFORMATPLUGIN
+ appendImagePluginFormats(loader(), pluginCapability(cap), &formats);
+#endif // QT_NO_IMAGEFORMATPLUGIN
+
+ std::sort(formats.begin(), formats.end());
+ formats.erase(std::unique(formats.begin(), formats.end()), formats.end());
+ return formats;
+}
+
+QList<QByteArray> supportedMimeTypes(Capability cap)
+{
+ QList<QByteArray> mimeTypes;
+ mimeTypes.reserve(_qt_NumFormats);
+ for (const auto &fmt : _qt_BuiltInFormats)
+ mimeTypes.append(QByteArrayLiteral("image/") + fmt.mimeType);
+
+#ifndef QT_NO_IMAGEFORMATPLUGIN
+ appendImagePluginMimeTypes(loader(), pluginCapability(cap), &mimeTypes);
+#endif // QT_NO_IMAGEFORMATPLUGIN
+
+ std::sort(mimeTypes.begin(), mimeTypes.end());
+ mimeTypes.erase(std::unique(mimeTypes.begin(), mimeTypes.end()), mimeTypes.end());
+ return mimeTypes;
+}
+
+QList<QByteArray> imageFormatsForMimeType(const QByteArray &mimeType, Capability cap)
+{
+ QList<QByteArray> formats;
+ if (mimeType.startsWith("image/")) {
+ const QByteArray type = mimeType.mid(sizeof("image/") - 1);
+ for (const auto &fmt : _qt_BuiltInFormats) {
+ if (fmt.mimeType == type && !formats.contains(fmt.extension))
+ formats << fmt.extension;
+ }
+ }
+
+#ifndef QT_NO_IMAGEFORMATPLUGIN
+ QList<QByteArray> mimeTypes;
+ QList<QByteArray> keys;
+ appendImagePluginMimeTypes(loader(), pluginCapability(cap), &mimeTypes, &keys);
+ for (int i = 0; i < mimeTypes.size(); ++i) {
+ if (mimeTypes.at(i) == mimeType) {
+ const auto &key = keys.at(i);
+ if (!formats.contains(key))
+ formats << key;
+ }
+ }
+#endif // QT_NO_IMAGEFORMATPLUGIN
+
+ return formats;
+}
+
+} // QImageReaderWriterHelpers
+
+QT_END_NAMESPACE
diff --git a/src/gui/image/qimagereaderwriterhelpers_p.h b/src/gui/image/qimagereaderwriterhelpers_p.h
new file mode 100644
index 0000000000..6fe418a8ab
--- /dev/null
+++ b/src/gui/image/qimagereaderwriterhelpers_p.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QIMAGEREADERWRITERHELPERS_P_H
+#define QIMAGEREADERWRITERHELPERS_P_H
+
+#include <QtGui/private/qtguiglobal_p.h>
+#include <qsharedpointer.h>
+#include "qimageiohandler.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.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QFactoryLoader;
+
+namespace QImageReaderWriterHelpers {
+
+enum _qt_BuiltInFormatType {
+#ifndef QT_NO_IMAGEFORMAT_PNG
+ _qt_PngFormat,
+#endif
+#ifndef QT_NO_IMAGEFORMAT_BMP
+ _qt_BmpFormat,
+#endif
+#ifndef QT_NO_IMAGEFORMAT_PPM
+ _qt_PpmFormat,
+ _qt_PgmFormat,
+ _qt_PbmFormat,
+#endif
+#ifndef QT_NO_IMAGEFORMAT_XBM
+ _qt_XbmFormat,
+#endif
+#ifndef QT_NO_IMAGEFORMAT_XPM
+ _qt_XpmFormat,
+#endif
+ _qt_NumFormats,
+ _qt_NoFormat = -1
+};
+
+#if !defined(QT_NO_IMAGEFORMAT_PPM)
+# define MAX_MT_SIZE 20
+#elif !defined(QT_NO_IMAGEFORMAT_XBM) || !defined(QT_NO_IMAGEFORMAT_XPM)
+# define MAX_MT_SIZE 10
+#else
+# define MAX_MT_SIZE 4
+#endif
+
+struct _qt_BuiltInFormatStruct
+{
+ char extension[4];
+ char mimeType[MAX_MT_SIZE];
+};
+
+#undef MAX_MT_SIZE
+
+static const _qt_BuiltInFormatStruct _qt_BuiltInFormats[] = {
+#ifndef QT_NO_IMAGEFORMAT_PNG
+ {"png", "png"},
+#endif
+#ifndef QT_NO_IMAGEFORMAT_BMP
+ {"bmp", "bmp"},
+#endif
+#ifndef QT_NO_IMAGEFORMAT_PPM
+ {"ppm", "x-portable-pixmap"},
+ {"pgm", "x-portable-graymap"},
+ {"pbm", "x-portable-bitmap"},
+#endif
+#ifndef QT_NO_IMAGEFORMAT_XBM
+ {"xbm", "x-xbitmap"},
+#endif
+#ifndef QT_NO_IMAGEFORMAT_XPM
+ {"xpm", "x-xpixmap"},
+#endif
+};
+Q_STATIC_ASSERT(_qt_NumFormats == sizeof _qt_BuiltInFormats / sizeof *_qt_BuiltInFormats);
+
+#ifndef QT_NO_IMAGEFORMATPLUGIN
+QSharedPointer<QFactoryLoader> pluginLoader();
+#endif
+
+enum Capability {
+ CanRead,
+ CanWrite
+};
+QList<QByteArray> supportedImageFormats(Capability cap);
+QList<QByteArray> supportedMimeTypes(Capability cap);
+QList<QByteArray> imageFormatsForMimeType(const QByteArray &mimeType, Capability cap);
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QIMAGEREADERWRITERHELPERS_P_H
diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp
index a39d204677..5ce7e309bb 100644
--- a/src/gui/image/qimagewriter.cpp
+++ b/src/gui/image/qimagewriter.cpp
@@ -102,7 +102,6 @@
#include <qfileinfo.h>
#include <qimage.h>
#include <qimageiohandler.h>
-#include <qjsonarray.h>
#include <qset.h>
#include <qvariant.h>
@@ -119,15 +118,12 @@
#include <private/qpnghandler_p.h>
#endif
+#include <private/qimagereaderwriterhelpers_p.h>
+
#include <algorithm>
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_IMAGEFORMATPLUGIN
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
- (QImageIOHandlerFactoryInterface_iid, QLatin1String("/imageformats")))
-#endif
-
static QImageIOHandler *createWriteHandlerHelper(QIODevice *device,
const QByteArray &format)
{
@@ -139,7 +135,7 @@ static QImageIOHandler *createWriteHandlerHelper(QIODevice *device,
typedef QMultiMap<int, QString> PluginKeyMap;
// check if any plugins can write the image
- QFactoryLoader *l = loader();
+ auto l = QImageReaderWriterHelpers::pluginLoader();
const PluginKeyMap keyMap = l->keyMap();
int suffixPluginIndex = -1;
#endif
@@ -268,7 +264,7 @@ QImageWriterPrivate::QImageWriterPrivate(QImageWriter *qq)
deleteDevice = false;
handler = 0;
quality = -1;
- compression = 0;
+ compression = -1;
gamma = 0.0;
optimizedWrite = false;
progressiveScanWrite = false;
@@ -824,52 +820,6 @@ bool QImageWriter::supportsOption(QImageIOHandler::ImageOption option) const
return d->handler->supportsOption(option);
}
-
-#ifndef QT_NO_IMAGEFORMATPLUGIN
-void supportedImageHandlerFormats(QFactoryLoader *loader,
- QImageIOPlugin::Capability cap,
- QList<QByteArray> *result)
-{
- typedef QMultiMap<int, QString> PluginKeyMap;
- typedef PluginKeyMap::const_iterator PluginKeyMapConstIterator;
-
- const PluginKeyMap keyMap = loader->keyMap();
- const PluginKeyMapConstIterator cend = keyMap.constEnd();
- int i = -1;
- QImageIOPlugin *plugin = 0;
- result->reserve(result->size() + keyMap.size());
- for (PluginKeyMapConstIterator it = keyMap.constBegin(); it != cend; ++it) {
- if (it.key() != i) {
- i = it.key();
- plugin = qobject_cast<QImageIOPlugin *>(loader->instance(i));
- }
- const QByteArray key = it.value().toLatin1();
- if (plugin && (plugin->capabilities(0, key) & cap) != 0)
- result->append(key);
- }
-}
-
-void supportedImageHandlerMimeTypes(QFactoryLoader *loader,
- QImageIOPlugin::Capability cap,
- QList<QByteArray> *result)
-{
- QList<QJsonObject> metaDataList = loader->metaData();
-
- const int pluginCount = metaDataList.size();
- for (int i = 0; i < pluginCount; ++i) {
- const QJsonObject metaData = metaDataList.at(i).value(QLatin1String("MetaData")).toObject();
- const QJsonArray keys = metaData.value(QLatin1String("Keys")).toArray();
- const QJsonArray mimeTypes = metaData.value(QLatin1String("MimeTypes")).toArray();
- QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(loader->instance(i));
- const int keyCount = keys.size();
- for (int k = 0; k < keyCount; ++k) {
- if (plugin && (plugin->capabilities(0, keys.at(k).toString().toLatin1()) & cap) != 0)
- result->append(mimeTypes.at(k).toString().toLatin1());
- }
- }
-}
-#endif // QT_NO_IMAGEFORMATPLUGIN
-
/*!
Returns the list of image formats supported by QImageWriter.
@@ -897,30 +847,7 @@ void supportedImageHandlerMimeTypes(QFactoryLoader *loader,
*/
QList<QByteArray> QImageWriter::supportedImageFormats()
{
- QList<QByteArray> formats;
-#ifndef QT_NO_IMAGEFORMAT_BMP
- formats << "bmp";
-#endif
-#ifndef QT_NO_IMAGEFORMAT_PPM
- formats << "pbm" << "pgm" << "ppm";
-#endif
-#ifndef QT_NO_IMAGEFORMAT_XBM
- formats << "xbm";
-#endif
-#ifndef QT_NO_IMAGEFORMAT_XPM
- formats << "xpm";
-#endif
-#ifndef QT_NO_IMAGEFORMAT_PNG
- formats << "png";
-#endif
-
-#ifndef QT_NO_IMAGEFORMATPLUGIN
- supportedImageHandlerFormats(loader(), QImageIOPlugin::CanWrite, &formats);
-#endif // QT_NO_IMAGEFORMATPLUGIN
-
- std::sort(formats.begin(), formats.end());
- formats.erase(std::unique(formats.begin(), formats.end()), formats.end());
- return formats;
+ return QImageReaderWriterHelpers::supportedImageFormats(QImageReaderWriterHelpers::CanWrite);
}
/*!
@@ -933,32 +860,24 @@ QList<QByteArray> QImageWriter::supportedImageFormats()
*/
QList<QByteArray> QImageWriter::supportedMimeTypes()
{
- QList<QByteArray> mimeTypes;
-#ifndef QT_NO_IMAGEFORMAT_BMP
- mimeTypes << "image/bmp";
-#endif
-#ifndef QT_NO_IMAGEFORMAT_PPM
- mimeTypes << "image/x-portable-bitmap";
- mimeTypes << "image/x-portable-graymap";
- mimeTypes << "image/x-portable-pixmap";
-#endif
-#ifndef QT_NO_IMAGEFORMAT_XBM
- mimeTypes << "image/x-xbitmap";
-#endif
-#ifndef QT_NO_IMAGEFORMAT_XPM
- mimeTypes << "image/x-xpixmap";
-#endif
-#ifndef QT_NO_IMAGEFORMAT_PNG
- mimeTypes << "image/png";
-#endif
+ return QImageReaderWriterHelpers::supportedMimeTypes(QImageReaderWriterHelpers::CanWrite);
+}
-#ifndef QT_NO_IMAGEFORMATPLUGIN
- supportedImageHandlerMimeTypes(loader(), QImageIOPlugin::CanWrite, &mimeTypes);
-#endif // QT_NO_IMAGEFORMATPLUGIN
+/*!
+ \since 5.12
- std::sort(mimeTypes.begin(), mimeTypes.end());
- mimeTypes.erase(std::unique(mimeTypes.begin(), mimeTypes.end()), mimeTypes.end());
- return mimeTypes;
+ Returns the list of image formats corresponding to \a mimeType.
+
+ Note that the QGuiApplication instance must be created before this function is
+ called.
+
+ \sa supportedImageFormats(), supportedMimeTypes()
+*/
+
+QList<QByteArray> QImageWriter::imageFormatsForMimeType(const QByteArray &mimeType)
+{
+ return QImageReaderWriterHelpers::imageFormatsForMimeType(mimeType,
+ QImageReaderWriterHelpers::CanWrite);
}
QT_END_NAMESPACE
diff --git a/src/gui/image/qimagewriter.h b/src/gui/image/qimagewriter.h
index fd1fdd07e8..29c06ccdd2 100644
--- a/src/gui/image/qimagewriter.h
+++ b/src/gui/image/qimagewriter.h
@@ -116,6 +116,7 @@ public:
static QList<QByteArray> supportedImageFormats();
static QList<QByteArray> supportedMimeTypes();
+ static QList<QByteArray> imageFormatsForMimeType(const QByteArray &mimeType);
private:
Q_DISABLE_COPY(QImageWriter)
diff --git a/src/gui/image/qmovie.cpp b/src/gui/image/qmovie.cpp
index 010760de4c..7d17b7d5ef 100644
--- a/src/gui/image/qmovie.cpp
+++ b/src/gui/image/qmovie.cpp
@@ -379,7 +379,7 @@ QFrameInfo QMoviePrivate::infoForFrame(int frameNumber)
}
if (frameNumber > greatestFrameNumber)
greatestFrameNumber = frameNumber;
- QPixmap aPixmap = QPixmap::fromImage(anImage);
+ QPixmap aPixmap = QPixmap::fromImage(std::move(anImage));
int aDelay = reader->nextImageDelay();
return QFrameInfo(aPixmap, aDelay);
} else if (frameNumber != 0) {
@@ -405,7 +405,7 @@ QFrameInfo QMoviePrivate::infoForFrame(int frameNumber)
return QFrameInfo(); // Invalid
}
greatestFrameNumber = i;
- QPixmap aPixmap = QPixmap::fromImage(anImage);
+ QPixmap aPixmap = QPixmap::fromImage(std::move(anImage));
int aDelay = reader->nextImageDelay();
QFrameInfo info(aPixmap, aDelay);
// Cache it!
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index 1ea503a268..4b2334ae52 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -248,9 +248,9 @@ QPixmap::QPixmap(const char * const xpm[])
QImage image(xpm);
if (!image.isNull()) {
if (data && data->pixelType() == QPlatformPixmap::BitmapType)
- *this = QBitmap::fromImage(image);
+ *this = QBitmap::fromImage(std::move(image));
else
- *this = fromImage(image);
+ *this = fromImage(std::move(image));
}
}
#endif
@@ -691,7 +691,7 @@ QBitmap QPixmap::createHeuristicMask(bool clipTight) const
QBitmap QPixmap::createMaskFromColor(const QColor &maskColor, Qt::MaskMode mode) const
{
QImage image = toImage().convertToFormat(QImage::Format_ARGB32);
- return QBitmap::fromImage(image.createMaskFromColor(maskColor.rgba(), mode));
+ return QBitmap::fromImage(std::move(image).createMaskFromColor(maskColor.rgba(), mode));
}
/*!
@@ -1018,9 +1018,9 @@ QDataStream &operator>>(QDataStream &stream, QPixmap &pixmap)
if (image.isNull()) {
pixmap = QPixmap();
} else if (image.depth() == 1) {
- pixmap = QBitmap::fromImage(image);
+ pixmap = QBitmap::fromImage(std::move(image));
} else {
- pixmap = QPixmap::fromImage(image);
+ pixmap = QPixmap::fromImage(std::move(image));
}
return stream;
}
diff --git a/src/gui/image/qpixmap_blitter.cpp b/src/gui/image/qpixmap_blitter.cpp
index 646e737afa..649a25250c 100644
--- a/src/gui/image/qpixmap_blitter.cpp
+++ b/src/gui/image/qpixmap_blitter.cpp
@@ -150,13 +150,7 @@ void QBlittablePlatformPixmap::fill(const QColor &color)
m_alpha = true;
}
- uint pixel = qPremultiply(color.rgba());
- const QPixelLayout *layout = &qPixelLayouts[blittable()->lock()->format()];
- Q_ASSERT(layout->convertFromARGB32PM);
- layout->convertFromARGB32PM(&pixel, &pixel, 1, 0, 0);
-
- //so premultiplied formats are supported and ARGB32 and RGB32
- blittable()->lock()->fill(pixel);
+ blittable()->lock()->fill(color);
}
}
diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp
index 431002d032..13c1c29d5b 100644
--- a/src/gui/image/qpixmap_raster.cpp
+++ b/src/gui/image/qpixmap_raster.cpp
@@ -193,17 +193,12 @@ void QRasterPlatformPixmap::fill(const QColor &color)
if (alpha != 255) {
if (!image.hasAlphaChannel()) {
QImage::Format toFormat = qt_alphaVersionForPainting(image.format());
- if (!image.isNull() && qt_depthForFormat(image.format()) == qt_depthForFormat(toFormat)) {
- image.detach();
- image.d->format = toFormat;
- } else {
+ if (!image.reinterpretAsFormat(toFormat))
image = QImage(image.width(), image.height(), toFormat);
- }
}
}
- pixel = qPremultiply(color.rgba());
- const QPixelLayout *layout = &qPixelLayouts[image.format()];
- layout->convertFromARGB32PM(&pixel, &pixel, 1, 0, 0);
+ image.fill(color);
+ return;
} else if (image.format() == QImage::Format_Alpha8) {
pixel = qAlpha(color.rgba());
} else if (image.format() == QImage::Format_Grayscale8) {
diff --git a/src/gui/image/qpixmap_win.cpp b/src/gui/image/qpixmap_win.cpp
index 92f6964783..b8d13ac092 100644
--- a/src/gui/image/qpixmap_win.cpp
+++ b/src/gui/image/qpixmap_win.cpp
@@ -42,39 +42,76 @@
#include <qpa/qplatformpixmap.h>
#include "qpixmap_raster_p.h"
-#include <qglobal.h>
+#include <qdebug.h>
#include <QScopedArrayPointer>
#include <qt_windows.h>
+#include <algorithm>
+#include <iterator>
+
QT_BEGIN_NAMESPACE
-static inline void initBitMapInfoHeader(int width, int height, bool topToBottom, BITMAPINFOHEADER *bih)
+template <typename Int>
+static inline Int pad4(Int v)
+{
+ return (v + Int(3)) & ~Int(3);
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const BITMAPINFOHEADER &bih)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d << "BITMAPINFOHEADER(" << bih.biWidth << 'x' << qAbs(bih.biHeight)
+ << (bih.biHeight < 0 ? ", top-down" : ", bottom-up")
+ << ", planes=" << bih.biPlanes << ", bitCount=" << bih.biBitCount
+ << ", compression=" << bih.biCompression << ", size="
+ << bih.biSizeImage << ')';
+ return d;
+}
+#endif // !QT_NO_DEBUG_STREAM
+
+static inline void initBitMapInfoHeader(int width, int height, bool topToBottom,
+ DWORD compression, DWORD bitCount,
+ BITMAPINFOHEADER *bih)
{
memset(bih, 0, sizeof(BITMAPINFOHEADER));
bih->biSize = sizeof(BITMAPINFOHEADER);
bih->biWidth = width;
bih->biHeight = topToBottom ? -height : height;
bih->biPlanes = 1;
- bih->biBitCount = 32;
- bih->biCompression = BI_RGB;
- bih->biSizeImage = width * height * 4;
+ bih->biBitCount = WORD(bitCount);
+ bih->biCompression = compression;
+ // scan lines are word-aligned (unless RLE)
+ const DWORD bytesPerLine = pad4(DWORD(width) * bitCount / 8);
+ bih->biSizeImage = bytesPerLine * DWORD(height);
}
-static inline void initBitMapInfo(int width, int height, bool topToBottom, BITMAPINFO *bmi)
+enum { Indexed8ColorTableSize = 256 };
+
+struct BITMAPINFO_COLORTABLE256 { // BITMAPINFO with 256 entry color table for Indexed 8 format
+ BITMAPINFOHEADER bmiHeader;
+ RGBQUAD bmiColors[Indexed8ColorTableSize];
+};
+
+template <class BITMAPINFO_T> // BITMAPINFO, BITMAPINFO_COLORTABLE256
+static inline void initBitMapInfo(int width, int height, bool topToBottom,
+ DWORD compression, DWORD bitCount,
+ BITMAPINFO_T *bmi)
{
- initBitMapInfoHeader(width, height, topToBottom, &bmi->bmiHeader);
- memset(bmi->bmiColors, 0, sizeof(RGBQUAD));
+ initBitMapInfoHeader(width, height, topToBottom, compression, bitCount, &bmi->bmiHeader);
+ memset(bmi->bmiColors, 0, sizeof(bmi->bmiColors));
}
static inline uchar *getDiBits(HDC hdc, HBITMAP bitmap, int width, int height, bool topToBottom = true)
{
BITMAPINFO bmi;
- initBitMapInfo(width, height, topToBottom, &bmi);
+ initBitMapInfo(width, height, topToBottom, BI_RGB, 32u, &bmi);
uchar *result = new uchar[bmi.bmiHeader.biSizeImage];
- if (!GetDIBits(hdc, bitmap, 0, height, result, &bmi, DIB_RGB_COLORS)) {
+ if (!GetDIBits(hdc, bitmap, 0, UINT(height), result, &bmi, DIB_RGB_COLORS)) {
delete [] result;
qErrnoWarning("%s: GetDIBits() failed to get bitmap bits.", __FUNCTION__);
- return 0;
+ return nullptr;
}
return result;
}
@@ -98,18 +135,92 @@ static inline void copyImageDataCreateAlpha(const uchar *data, QImage *target)
}
}
-static inline void copyImageData(const uchar *data, QImage *target)
+// Flip RGB triplets from DIB to QImage formats. Scan lines are padded to 32bit
+// both in QImage and DIB.
+static inline void flipRgb3(uchar *p, int width, int height)
{
- const int height = target->height();
- const int bytesPerLine = target->bytesPerLine();
+ const int lineSize = 3 * width;
+ const int linePad = pad4(lineSize) - lineSize;
for (int y = 0; y < height; ++y) {
- void *dest = static_cast<void *>(target->scanLine(y));
- const void *src = data + y * bytesPerLine;
- memcpy(dest, src, bytesPerLine);
+ uchar *end = p + lineSize;
+ for ( ; p < end; p += 3)
+ std::swap(*p, *(p + 2));
+ p += linePad;
}
+}
+static inline RGBQUAD qRgbToRgbQuad(QRgb qrgb)
+{
+ RGBQUAD result = {BYTE(qBlue(qrgb)), BYTE(qGreen(qrgb)), BYTE(qRed(qrgb)), 0};
+ return result;
+}
+
+static inline QRgb rgbQuadToQRgb(RGBQUAD quad)
+{
+ return QRgb(quad.rgbBlue) + (QRgb(quad.rgbGreen) << 8) + (QRgb(quad.rgbRed) << 16)
+ + 0xff000000;
}
+// Helper for imageFromWinHBITMAP_*(), create image in desired format
+static QImage copyImageData(const BITMAPINFOHEADER &header, const RGBQUAD *colorTableIn,
+ const void *data, QImage::Format format)
+{
+ const QSize size = QSize(header.biWidth, qAbs(header.biHeight));
+ QImage image(size, format);
+
+ int colorTableSize = 0;
+ switch (format) {
+ case QImage::Format_Mono:
+ colorTableSize = 2;
+ break;
+ case QImage::Format_Indexed8:
+ colorTableSize = Indexed8ColorTableSize;
+ break;
+ default:
+ break;
+ }
+ if (colorTableSize) {
+ Q_ASSERT(colorTableIn);
+ QVector<QRgb> colorTable;
+ colorTable.reserve(colorTableSize);
+ std::transform(colorTableIn, colorTableIn + colorTableSize,
+ std::back_inserter(colorTable), rgbQuadToQRgb);
+ image.setColorTable(colorTable);
+ }
+
+ switch (header.biBitCount) {
+ case 32:
+ copyImageDataCreateAlpha(static_cast<const uchar *>(data), &image);
+ break;
+ case 1:
+ case 8:
+ case 16:
+ case 24:
+ Q_ASSERT(DWORD(image.sizeInBytes()) == header.biSizeImage);
+ memcpy(image.bits(), data, header.biSizeImage);
+ if (format == QImage::Format_RGB888)
+ image = image.rgbSwapped();
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ return image;
+}
+
+class DisplayHdc
+{
+ Q_DISABLE_COPY(DisplayHdc)
+public:
+ DisplayHdc() : m_displayDc(GetDC(nullptr)) {}
+ ~DisplayHdc() { ReleaseDC(nullptr, m_displayDc); }
+
+ operator HDC() const { return m_displayDc; }
+
+private:
+ const HDC m_displayDc;
+};
+
enum HBitmapFormat
{
HBitmapNoAlpha,
@@ -123,108 +234,228 @@ Q_GUI_EXPORT HBITMAP qt_createIconMask(const QBitmap &bitmap)
const int w = bm.width();
const int h = bm.height();
const int bpl = ((w+15)/16)*2; // bpl, 16 bit alignment
- QScopedArrayPointer<uchar> bits(new uchar[bpl * h]);
+ QScopedArrayPointer<uchar> bits(new uchar[size_t(bpl * h)]);
bm.invertPixels();
for (int y = 0; y < h; ++y)
- memcpy(bits.data() + y * bpl, bm.constScanLine(y), bpl);
+ memcpy(bits.data() + y * bpl, bm.constScanLine(y), size_t(bpl));
HBITMAP hbm = CreateBitmap(w, h, 1, 1, bits.data());
return hbm;
}
-Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0)
+static inline QImage::Format format32(int hbitmapFormat)
{
- if (p.isNull())
- return 0;
-
- HBITMAP bitmap = 0;
- if (p.handle()->classId() != QPlatformPixmap::RasterClass) {
- QRasterPlatformPixmap *data = new QRasterPlatformPixmap(p.depth() == 1 ?
- QRasterPlatformPixmap::BitmapType : QRasterPlatformPixmap::PixmapType);
- data->fromImage(p.toImage(), Qt::AutoColor);
- return qt_pixmapToWinHBITMAP(QPixmap(data), hbitmapFormat);
+ switch (hbitmapFormat) {
+ case HBitmapNoAlpha:
+ return QImage::Format_RGB32;
+ case HBitmapAlpha:
+ return QImage::Format_ARGB32;
+ default:
+ break;
}
+ return QImage::Format_ARGB32_Premultiplied;
+}
- QRasterPlatformPixmap *d = static_cast<QRasterPlatformPixmap*>(p.handle());
- const QImage *rasterImage = d->buffer();
- const int w = rasterImage->width();
- const int h = rasterImage->height();
-
- HDC display_dc = GetDC(0);
+Q_GUI_EXPORT HBITMAP qt_imageToWinHBITMAP(const QImage &imageIn, int hbitmapFormat = 0)
+{
+ if (imageIn.isNull())
+ return nullptr;
// Define the header
- BITMAPINFO bmi;
- initBitMapInfo(w, h, true, &bmi);
+ DWORD compression = 0;
+ DWORD bitCount = 0;
+
+ // Copy over the data
+ QImage image = imageIn;
+ switch (image.format()) {
+ case QImage::Format_Mono:
+ bitCount = 1u;
+ break;
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied: {
+ compression = BI_RGB;
+ bitCount = 32u;
+ const QImage::Format targetFormat = format32(hbitmapFormat);
+ if (targetFormat != image.format())
+ image = image.convertToFormat(targetFormat);
+ }
+ break;
+ case QImage::Format_RGB888:
+ compression = BI_RGB;
+ bitCount = 24u;
+ break;
+ case QImage::Format_Indexed8:
+ bitCount = 8u;
+ break;
+ case QImage::Format_RGB555:
+ bitCount = 16u;
+ break;
+ default: {
+ QImage::Format fallbackFormat = QImage::Format_ARGB32_Premultiplied;
+ switch (image.format()) { // Convert to a suitable format.
+ case QImage::Format_MonoLSB:
+ fallbackFormat = QImage::Format_Mono;
+ break;
+ case QImage::Format_RGB16:
+ fallbackFormat = QImage::Format_RGB555;
+ break;
+ case QImage::Format_Grayscale8:
+ fallbackFormat = QImage::Format_Indexed8;
+ break;
+ default:
+ break;
+ } // switch conversion format
+ return qt_imageToWinHBITMAP(imageIn.convertToFormat(fallbackFormat), hbitmapFormat);
+ }
+ }
+
+ const int w = image.width();
+ const int h = image.height();
+
+ BITMAPINFO_COLORTABLE256 bmiColorTable256;
+ initBitMapInfo(w, h, true, compression, bitCount, &bmiColorTable256);
+ BITMAPINFO &bmi = reinterpret_cast<BITMAPINFO &>(bmiColorTable256);
+ switch (image.format()) {
+ case QImage::Format_Mono: // Color table with 2 entries
+ case QImage::Format_Indexed8:
+ std::transform(image.colorTable().constBegin(), image.colorTable().constEnd(),
+ bmiColorTable256.bmiColors, qRgbToRgbQuad);
+ break;
+ default:
+ break;
+ }
// Create the pixmap
- uchar *pixels = 0;
- bitmap = CreateDIBSection(display_dc, &bmi, DIB_RGB_COLORS, (void **) &pixels, 0, 0);
- ReleaseDC(0, display_dc);
+ uchar *pixels = nullptr;
+ const HBITMAP bitmap = CreateDIBSection(nullptr, &bmi, DIB_RGB_COLORS,
+ reinterpret_cast<void **>(&pixels), nullptr, 0);
if (!bitmap) {
qErrnoWarning("%s, failed to create dibsection", __FUNCTION__);
- return 0;
+ return nullptr;
}
if (!pixels) {
qErrnoWarning("%s, did not allocate pixel data", __FUNCTION__);
- return 0;
+ return nullptr;
}
-
- // Copy over the data
- QImage::Format imageFormat = QImage::Format_RGB32;
- if (hbitmapFormat == HBitmapAlpha)
- imageFormat = QImage::Format_ARGB32;
- else if (hbitmapFormat == HBitmapPremultipliedAlpha)
- imageFormat = QImage::Format_ARGB32_Premultiplied;
- const QImage image = rasterImage->convertToFormat(imageFormat);
- const int bytes_per_line = w * 4;
- for (int y=0; y < h; ++y)
- memcpy(pixels + y * bytes_per_line, image.scanLine(y), bytes_per_line);
-
+ memcpy(pixels, image.constBits(), bmi.bmiHeader.biSizeImage);
+ if (image.format() == QImage::Format_RGB888)
+ flipRgb3(pixels, w, h);
return bitmap;
}
+Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0)
+{
+ if (p.isNull())
+ return nullptr;
-Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0)
+ QPlatformPixmap *platformPixmap = p.handle();
+ if (platformPixmap->classId() != QPlatformPixmap::RasterClass) {
+ QRasterPlatformPixmap *data = new QRasterPlatformPixmap(p.depth() == 1 ?
+ QRasterPlatformPixmap::BitmapType : QRasterPlatformPixmap::PixmapType);
+ data->fromImage(p.toImage(), Qt::AutoColor);
+ return qt_pixmapToWinHBITMAP(QPixmap(data), hbitmapFormat);
+ }
+
+ return qt_imageToWinHBITMAP(*static_cast<QRasterPlatformPixmap*>(platformPixmap)->buffer(), hbitmapFormat);
+}
+
+static QImage::Format imageFromWinHBITMAP_Format(const BITMAPINFOHEADER &header, int hbitmapFormat)
{
- // Verify size
- BITMAP bitmap_info;
- memset(&bitmap_info, 0, sizeof(BITMAP));
+ QImage::Format result = QImage::Format_Invalid;
+ switch (header.biBitCount) {
+ case 32:
+ result = hbitmapFormat == HBitmapNoAlpha
+ ? QImage::Format_RGB32 : QImage::Format_ARGB32_Premultiplied;
+ break;
+ case 24:
+ result = QImage::Format_RGB888;
+ break;
+ case 16:
+ result = QImage::Format_RGB555;
+ break;
+ case 8:
+ result = QImage::Format_Indexed8;
+ break;
+ case 1:
+ result = QImage::Format_Mono;
+ break;
+ }
+ return result;
+}
- const int res = GetObject(bitmap, sizeof(BITMAP), &bitmap_info);
- if (!res) {
- qErrnoWarning("QPixmap::fromWinHBITMAP(), failed to get bitmap info");
- return QPixmap();
+// Fast path for creating a QImage directly from a HBITMAP created by CreateDIBSection(),
+// not requiring memory allocation.
+static QImage imageFromWinHBITMAP_DibSection(HBITMAP bitmap, int hbitmapFormat)
+{
+ DIBSECTION dibSection;
+ memset(&dibSection, 0, sizeof(dibSection));
+ dibSection.dsBmih.biSize = sizeof(dibSection.dsBmih);
+
+ if (!GetObject(bitmap, sizeof(dibSection), &dibSection)
+ || !dibSection.dsBm.bmBits
+ || dibSection.dsBmih.biBitCount <= 8 // Cannot access the color table for Indexed8, Mono
+ || dibSection.dsBmih.biCompression != BI_RGB) {
+ return QImage();
}
- const int w = bitmap_info.bmWidth;
- const int h = bitmap_info.bmHeight;
-
- // Get bitmap bits
- HDC display_dc = GetDC(0);
- QScopedArrayPointer<uchar> data(getDiBits(display_dc, bitmap, w, h, true));
- if (data.isNull()) {
- ReleaseDC(0, display_dc);
- return QPixmap();
+
+ const QImage::Format imageFormat = imageFromWinHBITMAP_Format(dibSection.dsBmih, hbitmapFormat);
+ if (imageFormat == QImage::Format_Invalid)
+ return QImage();
+
+ return copyImageData(dibSection.dsBmih, nullptr, dibSection.dsBm.bmBits, imageFormat);
+}
+
+// Create QImage from a HBITMAP using GetDIBits(), potentially with conversion.
+static QImage imageFromWinHBITMAP_GetDiBits(HBITMAP bitmap, bool forceQuads, int hbitmapFormat)
+{
+ BITMAPINFO_COLORTABLE256 bmiColorTable256;
+ BITMAPINFO &info = reinterpret_cast<BITMAPINFO &>(bmiColorTable256);
+ memset(&info, 0, sizeof(info));
+ info.bmiHeader.biSize = sizeof(info.bmiHeader);
+
+ DisplayHdc displayDc;
+ if (!GetDIBits(displayDc, bitmap, 0, 1, 0, &info, DIB_RGB_COLORS)) {
+ qErrnoWarning("%s: GetDIBits() failed to query data.", __FUNCTION__);
+ return QImage();
}
- const QImage::Format imageFormat = hbitmapFormat == HBitmapNoAlpha ?
- QImage::Format_RGB32 : QImage::Format_ARGB32_Premultiplied;
+ if (info.bmiHeader.biHeight > 0) // Force top-down
+ info.bmiHeader.biHeight = -info.bmiHeader.biHeight;
+ info.bmiHeader.biCompression = BI_RGB; // Extract using no compression (can be BI_BITFIELD)
+ if (forceQuads)
+ info.bmiHeader.biBitCount = 32;
- // Create image and copy data into image.
- QImage image(w, h, imageFormat);
- if (image.isNull()) { // failed to alloc?
- ReleaseDC(0, display_dc);
- qWarning("%s, failed create image of %dx%d", __FUNCTION__, w, h);
- return QPixmap();
+ const QImage::Format imageFormat = imageFromWinHBITMAP_Format(info.bmiHeader, hbitmapFormat);
+ if (imageFormat == QImage::Format_Invalid) {
+ qWarning().nospace() << __FUNCTION__ << ": unsupported image format:" << info.bmiHeader;
+ return QImage();
}
- copyImageDataCreateAlpha(data.data(), &image);
- ReleaseDC(0, display_dc);
- return QPixmap::fromImage(image);
+
+ QScopedPointer<uchar> data(new uchar[info.bmiHeader.biSizeImage]);
+ if (!GetDIBits(displayDc, bitmap, 0, qAbs(info.bmiHeader.biHeight), data.data(), &info, DIB_RGB_COLORS)) {
+ qErrnoWarning("%s: GetDIBits() failed to get data.", __FUNCTION__);
+ return QImage();
+ }
+ return copyImageData(info.bmiHeader, bmiColorTable256.bmiColors, data.data(), imageFormat);
}
+Q_GUI_EXPORT QImage qt_imageFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0)
+{
+ QImage result = imageFromWinHBITMAP_DibSection(bitmap, hbitmapFormat);
+ if (result.isNull())
+ result = imageFromWinHBITMAP_GetDiBits(bitmap, /* forceQuads */ false, hbitmapFormat);
+ return result;
+}
+
+Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0)
+{
+ return QPixmap::fromImage(imageFromWinHBITMAP_GetDiBits(bitmap, /* forceQuads */ true, hbitmapFormat));
+}
Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &p)
{
if (p.isNull())
- return 0;
+ return nullptr;
QBitmap maskBitmap = p.mask();
if (maskBitmap.isNull()) {
@@ -267,7 +498,7 @@ static QImage qt_imageFromWinIconHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h)
QScopedArrayPointer<uchar> data(getDiBits(hdc, bitmap, w, h, true));
if (data.isNull())
return QImage();
- copyImageData(data.data(), &image);
+ memcpy(image.bits(), data.data(), size_t(image.sizeInBytes()));
return image;
}
@@ -287,9 +518,9 @@ static inline bool hasAlpha(const QImage &image)
Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon)
{
- HDC screenDevice = GetDC(0);
+ HDC screenDevice = GetDC(nullptr);
HDC hdc = CreateCompatibleDC(screenDevice);
- ReleaseDC(0, screenDevice);
+ ReleaseDC(nullptr, screenDevice);
ICONINFO iconinfo;
const bool result = GetIconInfo(icon, &iconinfo); //x and y Hotspot describes the icon center
@@ -299,25 +530,27 @@ Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon)
return QPixmap();
}
- const int w = iconinfo.xHotspot * 2;
- const int h = iconinfo.yHotspot * 2;
+ const int w = int(iconinfo.xHotspot) * 2;
+ const int h = int(iconinfo.yHotspot) * 2;
BITMAPINFOHEADER bitmapInfo;
- initBitMapInfoHeader(w, h, false, &bitmapInfo);
+ initBitMapInfoHeader(w, h, false, BI_RGB, 32u, &bitmapInfo);
DWORD* bits;
- HBITMAP winBitmap = CreateDIBSection(hdc, (BITMAPINFO*)&bitmapInfo, DIB_RGB_COLORS, (VOID**)&bits, NULL, 0);
- HGDIOBJ oldhdc = (HBITMAP)SelectObject(hdc, winBitmap);
- DrawIconEx( hdc, 0, 0, icon, iconinfo.xHotspot * 2, iconinfo.yHotspot * 2, 0, 0, DI_NORMAL);
+ HBITMAP winBitmap = CreateDIBSection(hdc, reinterpret_cast<BITMAPINFO *>(&bitmapInfo),
+ DIB_RGB_COLORS, reinterpret_cast<VOID **>(&bits),
+ nullptr, 0);
+ HGDIOBJ oldhdc = static_cast<HBITMAP>(SelectObject(hdc, winBitmap));
+ DrawIconEx(hdc, 0, 0, icon, w, h, 0, nullptr, DI_NORMAL);
QImage image = qt_imageFromWinIconHBITMAP(hdc, winBitmap, w, h);
if (!image.isNull() && !hasAlpha(image)) { //If no alpha was found, we use the mask to set alpha values
- DrawIconEx( hdc, 0, 0, icon, w, h, 0, 0, DI_MASK);
+ DrawIconEx( hdc, 0, 0, icon, w, h, 0, nullptr, DI_MASK);
const QImage mask = qt_imageFromWinIconHBITMAP(hdc, winBitmap, w, h);
for (int y = 0 ; y < h ; y++){
QRgb *scanlineImage = reinterpret_cast<QRgb *>(image.scanLine(y));
- const QRgb *scanlineMask = mask.isNull() ? 0 : reinterpret_cast<const QRgb *>(mask.scanLine(y));
+ const QRgb *scanlineMask = mask.isNull() ? nullptr : reinterpret_cast<const QRgb *>(mask.scanLine(y));
for (int x = 0; x < w ; x++){
if (scanlineMask && qRed(scanlineMask[x]) != 0)
scanlineImage[x] = 0; //mask out this pixel
@@ -333,7 +566,7 @@ Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon)
SelectObject(hdc, oldhdc); //restore state
DeleteObject(winBitmap);
DeleteDC(hdc);
- return QPixmap::fromImage(image);
+ return QPixmap::fromImage(std::move(image));
}
QT_END_NAMESPACE
diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp
index 4b8b1203d6..3d1652f68b 100644
--- a/src/gui/image/qpixmapcache.cpp
+++ b/src/gui/image/qpixmapcache.cpp
@@ -86,7 +86,17 @@ QT_BEGIN_NAMESPACE
\sa QCache, QPixmap
*/
-static int cache_limit = 10240; // 10 MB cache limit
+static const int cache_limit_default = 10240; // 10 MB cache limit
+
+static inline int cost(const QPixmap &pixmap)
+{
+ // make sure to do a 64bit calculation
+ const qint64 costKb = static_cast<qint64>(pixmap.width()) *
+ pixmap.height() * pixmap.depth() / (8 * 1024);
+ const qint64 costMax = std::numeric_limits<int>::max();
+ // a small pixmap should have at least a cost of 1(kb)
+ return static_cast<int>(qBound(1LL, costKb, costMax));
+}
/*!
\class QPixmapCache::Key
@@ -237,7 +247,7 @@ uint qHash(const QPixmapCache::Key &k)
QPMCache::QPMCache()
: QObject(0),
- QCache<QPixmapCache::Key, QPixmapCacheEntry>(cache_limit * 1024),
+ QCache<QPixmapCache::Key, QPixmapCacheEntry>(cache_limit_default),
keyArray(0), theid(0), ps(0), keyArraySize(0), freeKey(0), t(false)
{
}
@@ -553,7 +563,7 @@ bool QPixmapCache::find(const Key &key, QPixmap* pixmap)
bool QPixmapCache::insert(const QString &key, const QPixmap &pixmap)
{
- return pm_cache()->insert(key, pixmap, pixmap.width() * pixmap.height() * pixmap.depth() / 8);
+ return pm_cache()->insert(key, pixmap, cost(pixmap));
}
/*!
@@ -573,7 +583,7 @@ bool QPixmapCache::insert(const QString &key, const QPixmap &pixmap)
*/
QPixmapCache::Key QPixmapCache::insert(const QPixmap &pixmap)
{
- return pm_cache()->insert(pixmap, pixmap.width() * pixmap.height() * pixmap.depth() / 8);
+ return pm_cache()->insert(pixmap, cost(pixmap));
}
/*!
@@ -590,7 +600,7 @@ bool QPixmapCache::replace(const Key &key, const QPixmap &pixmap)
//The key is not valid anymore, a flush happened before probably
if (!key.d || !key.d->isValid)
return false;
- return pm_cache()->replace(key, pixmap, pixmap.width() * pixmap.height() * pixmap.depth() / 8);
+ return pm_cache()->replace(key, pixmap, cost(pixmap));
}
/*!
@@ -603,7 +613,7 @@ bool QPixmapCache::replace(const Key &key, const QPixmap &pixmap)
int QPixmapCache::cacheLimit()
{
- return cache_limit;
+ return pm_cache()->maxCost();
}
/*!
@@ -616,8 +626,7 @@ int QPixmapCache::cacheLimit()
void QPixmapCache::setCacheLimit(int n)
{
- cache_limit = n;
- pm_cache()->setMaxCost(1024 * cache_limit);
+ pm_cache()->setMaxCost(n);
}
/*!
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index 42b9e71087..13129e214b 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -99,12 +99,13 @@ public:
};
QPngHandlerPrivate(QPngHandler *qq)
- : gamma(0.0), fileGamma(0.0), quality(2), png_ptr(0), info_ptr(0), end_info(0), state(Ready), q(qq)
+ : gamma(0.0), fileGamma(0.0), quality(50), compression(50), png_ptr(0), info_ptr(0), end_info(0), state(Ready), q(qq)
{ }
float gamma;
float fileGamma;
- int quality;
+ int quality; // quality is used for backward compatibility, maps to compression
+ int compression;
QString description;
QSize scaledSize;
QStringList readTexts;
@@ -161,11 +162,11 @@ public:
void setGamma(float);
bool writeImage(const QImage& img, int x, int y);
- bool writeImage(const QImage& img, volatile int quality, const QString &description, int x, int y);
+ bool writeImage(const QImage& img, volatile int compression_in, const QString &description, int x, int y);
bool writeImage(const QImage& img)
{ return writeImage(img, 0, 0); }
- bool writeImage(const QImage& img, int quality, const QString &description)
- { return writeImage(img, quality, description, 0, 0); }
+ bool writeImage(const QImage& img, int compression, const QString &description)
+ { return writeImage(img, compression, description, 0, 0); }
QIODevice* device() { return dev; }
@@ -245,7 +246,7 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scal
png_set_interlace_handling(png_ptr);
if (color_type == PNG_COLOR_TYPE_GRAY) {
- // Black & White or 8-bit grayscale
+ // Black & White or grayscale
if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) {
png_set_invert_mono(png_ptr);
png_read_update_info(png_ptr, info_ptr);
@@ -266,19 +267,22 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scal
else if (g == 1)
image.setColor(0, qRgba(255, 255, 255, 0));
}
- } else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
- png_set_expand(png_ptr);
- png_set_strip_16(png_ptr);
+ } else if (bit_depth == 16) {
+ bool hasMask = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS);
+ if (!hasMask)
+ png_set_filler(png_ptr, 0xffff, PNG_FILLER_AFTER);
+ else
+ png_set_expand(png_ptr);
png_set_gray_to_rgb(png_ptr);
- if (image.size() != QSize(width, height) || image.format() != QImage::Format_ARGB32) {
- image = QImage(width, height, QImage::Format_ARGB32);
+ QImage::Format format = hasMask ? QImage::Format_RGBA64 : QImage::Format_RGBX64;
+ if (image.size() != QSize(width, height) || image.format() != format) {
+ image = QImage(width, height, format);
if (image.isNull())
return;
}
- if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
- png_set_swap_alpha(png_ptr);
-
png_read_update_info(png_ptr, info_ptr);
+ if (QSysInfo::ByteOrder == QSysInfo::LittleEndian)
+ png_set_swap(png_ptr);
} else if (bit_depth == 8 && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
png_set_expand(png_ptr);
if (image.size() != QSize(width, height) || image.format() != QImage::Format_Grayscale8) {
@@ -289,9 +293,7 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scal
png_read_update_info(png_ptr, info_ptr);
} else {
- if (bit_depth == 16)
- png_set_strip_16(png_ptr);
- else if (bit_depth < 8)
+ if (bit_depth < 8)
png_set_packing(png_ptr);
int ncols = bit_depth < 8 ? 1 << bit_depth : 256;
png_read_update_info(png_ptr, info_ptr);
@@ -352,6 +354,26 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scal
);
i++;
}
+ // Qt==ARGB==Big(ARGB)==Little(BGRA)
+ if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
+ png_set_bgr(png_ptr);
+ }
+ } else if (bit_depth == 16 && !(color_type & PNG_COLOR_MASK_PALETTE)) {
+ QImage::Format format = QImage::Format_RGBA64;
+ if (!(color_type & PNG_COLOR_MASK_ALPHA) && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
+ png_set_filler(png_ptr, 0xffff, PNG_FILLER_AFTER);
+ format = QImage::Format_RGBX64;
+ }
+ if (!(color_type & PNG_COLOR_MASK_COLOR))
+ png_set_gray_to_rgb(png_ptr);
+ if (image.size() != QSize(width, height) || image.format() != format) {
+ image = QImage(width, height, format);
+ if (image.isNull())
+ return;
+ }
+ png_read_update_info(png_ptr, info_ptr);
+ if (QSysInfo::ByteOrder == QSysInfo::LittleEndian)
+ png_set_swap(png_ptr);
} else {
// 32-bit
if (bit_depth == 16)
@@ -388,12 +410,12 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scal
if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
png_set_swap_alpha(png_ptr);
- png_read_update_info(png_ptr, info_ptr);
- }
+ // Qt==ARGB==Big(ARGB)==Little(BGRA)
+ if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
+ png_set_bgr(png_ptr);
+ }
- // Qt==ARGB==Big(ARGB)==Little(BGRA)
- if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
- png_set_bgr(png_ptr);
+ png_read_update_info(png_ptr, info_ptr);
}
}
@@ -662,11 +684,11 @@ QImage::Format QPngHandlerPrivate::readImageFormat()
int num_palette;
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
if (color_type == PNG_COLOR_TYPE_GRAY) {
- // Black & White or 8-bit grayscale
+ // Black & White or grayscale
if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) {
format = QImage::Format_Mono;
- } else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
- format = QImage::Format_ARGB32;
+ } else if (bit_depth == 16) {
+ format = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ? QImage::Format_RGBA64 : QImage::Format_RGBX64;
} else if (bit_depth == 8 && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
format = QImage::Format_Grayscale8;
} else {
@@ -678,6 +700,10 @@ QImage::Format QPngHandlerPrivate::readImageFormat()
{
// 1-bit and 8-bit color
format = bit_depth == 1 ? QImage::Format_Mono : QImage::Format_Indexed8;
+ } else if (bit_depth == 16 && !(color_type & PNG_COLOR_MASK_PALETTE)) {
+ format = QImage::Format_RGBA64;
+ if (!(color_type & PNG_COLOR_MASK_ALPHA) && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
+ format = QImage::Format_RGBX64;
} else {
// 32-bit
format = QImage::Format_ARGB32;
@@ -789,7 +815,7 @@ bool QPNGImageWriter::writeImage(const QImage& image, int off_x, int off_y)
return writeImage(image, -1, QString(), off_x, off_y);
}
-bool QPNGImageWriter::writeImage(const QImage& image, volatile int quality_in, const QString &description,
+bool QPNGImageWriter::writeImage(const QImage& image, volatile int compression_in, const QString &description,
int off_x_in, int off_y_in)
{
QPoint offset = image.offset();
@@ -817,13 +843,13 @@ bool QPNGImageWriter::writeImage(const QImage& image, volatile int quality_in, c
return false;
}
- int quality = quality_in;
- if (quality >= 0) {
- if (quality > 9) {
- qWarning("PNG: Quality %d out of range", quality);
- quality = 9;
+ int compression = compression_in;
+ if (compression >= 0) {
+ if (compression > 9) {
+ qWarning("PNG: Compression %d out of range", compression);
+ compression = 9;
}
- png_set_compression_level(png_ptr, quality);
+ png_set_compression_level(png_ptr, compression);
}
png_set_write_fn(png_ptr, (void*)this, qpiw_write_fn, qpiw_flush_fn);
@@ -843,8 +869,24 @@ bool QPNGImageWriter::writeImage(const QImage& image, volatile int quality_in, c
else
color_type = PNG_COLOR_TYPE_RGB;
+ int bpc = 0;
+ switch (image.format()) {
+ case QImage::Format_Mono:
+ case QImage::Format_MonoLSB:
+ bpc = 1;
+ break;
+ case QImage::Format_RGBX64:
+ case QImage::Format_RGBA64:
+ case QImage::Format_RGBA64_Premultiplied:
+ bpc = 16;
+ break;
+ default:
+ bpc = 8;
+ break;
+ }
+
png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(),
- image.depth() == 1 ? 1 : 8, // per channel
+ bpc, // per channel
color_type, 0, 0, 0); // sets #channels
if (gamma != 0.0) {
@@ -880,13 +922,31 @@ bool QPNGImageWriter::writeImage(const QImage& image, volatile int quality_in, c
// Swap ARGB to RGBA (normal PNG format) before saving on
// BigEndian machines
if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
- png_set_swap_alpha(png_ptr);
+ switch (image.format()) {
+ case QImage::Format_RGBX8888:
+ case QImage::Format_RGBA8888:
+ case QImage::Format_RGBX64:
+ case QImage::Format_RGBA64:
+ case QImage::Format_RGBA64_Premultiplied:
+ break;
+ default:
+ png_set_swap_alpha(png_ptr);
+ }
}
// Qt==ARGB==Big(ARGB)==Little(BGRA). But RGB888 is RGB regardless
- if (QSysInfo::ByteOrder == QSysInfo::LittleEndian
- && image.format() != QImage::Format_RGB888) {
- png_set_bgr(png_ptr);
+ if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
+ switch (image.format()) {
+ case QImage::Format_RGB888:
+ case QImage::Format_RGBX8888:
+ case QImage::Format_RGBA8888:
+ case QImage::Format_RGBX64:
+ case QImage::Format_RGBA64:
+ case QImage::Format_RGBA64_Premultiplied:
+ break;
+ default:
+ png_set_bgr(png_ptr);
+ }
}
if (off_x || off_y) {
@@ -909,10 +969,32 @@ bool QPNGImageWriter::writeImage(const QImage& image, volatile int quality_in, c
if (image.depth() != 1)
png_set_packing(png_ptr);
- if (color_type == PNG_COLOR_TYPE_RGB && image.format() != QImage::Format_RGB888)
- png_set_filler(png_ptr, 0,
- QSysInfo::ByteOrder == QSysInfo::BigEndian ?
- PNG_FILLER_BEFORE : PNG_FILLER_AFTER);
+ if (color_type == PNG_COLOR_TYPE_RGB) {
+ switch (image.format()) {
+ case QImage::Format_RGB888:
+ break;
+ case QImage::Format_RGBX8888:
+ case QImage::Format_RGBX64:
+ png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
+ break;
+ default:
+ png_set_filler(png_ptr, 0,
+ QSysInfo::ByteOrder == QSysInfo::BigEndian ?
+ PNG_FILLER_BEFORE : PNG_FILLER_AFTER);
+ }
+ }
+
+ if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
+ switch (image.format()) {
+ case QImage::Format_RGBX64:
+ case QImage::Format_RGBA64:
+ case QImage::Format_RGBA64_Premultiplied:
+ png_set_swap(png_ptr);
+ break;
+ default:
+ break;
+ }
+ }
if (looping >= 0 && frames_written == 0) {
uchar data[13] = "NETSCAPE2.0";
@@ -940,6 +1022,10 @@ bool QPNGImageWriter::writeImage(const QImage& image, volatile int quality_in, c
case QImage::Format_RGB32:
case QImage::Format_ARGB32:
case QImage::Format_RGB888:
+ case QImage::Format_RGBX8888:
+ case QImage::Format_RGBA8888:
+ case QImage::Format_RGBX64:
+ case QImage::Format_RGBA64:
{
png_bytep* row_pointers = new png_bytep[height];
for (int y=0; y<height; y++)
@@ -948,6 +1034,17 @@ bool QPNGImageWriter::writeImage(const QImage& image, volatile int quality_in, c
delete [] row_pointers;
}
break;
+ case QImage::Format_RGBA64_Premultiplied:
+ {
+ QImage row;
+ png_bytep row_pointers[1];
+ for (int y=0; y<height; y++) {
+ row = image.copy(0, y, width, 1).convertToFormat(QImage::Format_RGBA64);
+ row_pointers[0] = const_cast<png_bytep>(row.constScanLine(0));
+ png_write_rows(png_ptr, row_pointers, 1);
+ }
+ }
+ break;
default:
{
QImage::Format fmt = image.hasAlphaChannel() ? QImage::Format_ARGB32 : QImage::Format_RGB32;
@@ -971,15 +1068,21 @@ bool QPNGImageWriter::writeImage(const QImage& image, volatile int quality_in, c
}
static bool write_png_image(const QImage &image, QIODevice *device,
- int quality, float gamma, const QString &description)
+ int compression, int quality, float gamma, const QString &description)
{
+ // quality is used for backward compatibility, maps to compression
+
QPNGImageWriter writer(device);
- if (quality >= 0) {
- quality = qMin(quality, 100);
- quality = (100-quality) * 9 / 91; // map [0,100] -> [9,0]
- }
+ if (compression >= 0)
+ compression = qMin(compression, 100);
+ else if (quality >= 0)
+ compression = 100 - qMin(quality, 100);
+
+ if (compression >= 0)
+ compression = (compression * 9) / 91; // map [0,100] -> [0,9]
+
writer.setGamma(gamma);
- return writer.writeImage(image, quality, description);
+ return writer.writeImage(image, compression, description);
}
QPngHandler::QPngHandler()
@@ -1026,7 +1129,7 @@ bool QPngHandler::read(QImage *image)
bool QPngHandler::write(const QImage &image)
{
- return write_png_image(image, device(), d->quality, d->gamma, d->description);
+ return write_png_image(image, device(), d->compression, d->quality, d->gamma, d->description);
}
bool QPngHandler::supportsOption(ImageOption option) const
@@ -1035,6 +1138,7 @@ bool QPngHandler::supportsOption(ImageOption option) const
|| option == Description
|| option == ImageFormat
|| option == Quality
+ || option == CompressionRatio
|| option == Size
|| option == ScaledSize;
}
@@ -1050,6 +1154,8 @@ QVariant QPngHandler::option(ImageOption option) const
return d->gamma == 0.0 ? d->fileGamma : d->gamma;
else if (option == Quality)
return d->quality;
+ else if (option == CompressionRatio)
+ return d->compression;
else if (option == Description)
return d->description;
else if (option == Size)
@@ -1068,6 +1174,8 @@ void QPngHandler::setOption(ImageOption option, const QVariant &value)
d->gamma = value.toFloat();
else if (option == Quality)
d->quality = value.toInt();
+ else if (option == CompressionRatio)
+ d->compression = value.toInt();
else if (option == Description)
d->description = value.toString();
else if (option == ScaledSize)
diff --git a/src/gui/image/qxbmhandler.cpp b/src/gui/image/qxbmhandler.cpp
index 155a4f88b4..24d86e116d 100644
--- a/src/gui/image/qxbmhandler.cpp
+++ b/src/gui/image/qxbmhandler.cpp
@@ -241,7 +241,7 @@ static bool write_xbm_image(const QImage &sourceImage, QIODevice *device, const
}
}
}
-#if defined(_MSC_VER) && _MSC_VER >= 1400
+#ifdef Q_CC_MSVC
strcpy_s(p, sizeof(" };\n"), " };\n");
#else
strcpy(p, " };\n");
diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp
index 9c54b9ada4..17272ffe69 100644
--- a/src/gui/image/qxpmhandler.cpp
+++ b/src/gui/image/qxpmhandler.cpp
@@ -741,10 +741,6 @@ static const struct XPMRGBData {
{ QRGB(139,139, 0), "yellow4" },
{ QRGB(154,205, 50), "yellowgreen" } };
-#if defined(Q_CC_MSVC) && _MSC_VER < 1600
-inline bool operator<(const XPMRGBData &data1, const XPMRGBData &data2)
-{ return qstrcmp(data1.name, data2.name) < 0; }
-#endif
inline bool operator<(const char *name, const XPMRGBData &data)
{ return qstrcmp(name, data.name) < 0; }
diff --git a/src/gui/itemmodels/qstandarditemmodel.cpp b/src/gui/itemmodels/qstandarditemmodel.cpp
index 235bc5bd7d..8ec88ebc60 100644
--- a/src/gui/itemmodels/qstandarditemmodel.cpp
+++ b/src/gui/itemmodels/qstandarditemmodel.cpp
@@ -306,8 +306,11 @@ const QMap<int, QVariant> QStandardItemPrivate::itemData() const
{
QMap<int, QVariant> result;
QVector<QStandardItemData>::const_iterator it;
- for (it = values.begin(); it != values.end(); ++it)
- result.insert((*it).role, (*it).value);
+ for (it = values.cbegin(); it != values.cend(); ++it){
+ // Qt::UserRole - 1 is used internally to store the flags
+ if (it->role != Qt::UserRole - 1)
+ result.insert(it->role, it->value);
+ }
return result;
}
@@ -931,6 +934,21 @@ void QStandardItem::setData(const QVariant &value, int role)
}
/*!
+ \since 5.12
+ Removes all the data from all roles previously set.
+ \sa data(), setData()
+*/
+void QStandardItem::clearData()
+{
+ Q_D(QStandardItem);
+ if (d->values.isEmpty())
+ return;
+ d->values.clear();
+ if (d->model)
+ d->model->d_func()->itemChanged(this, QVector<int>{});
+}
+
+/*!
Returns the item's data for the given \a role, or an invalid
QVariant if there is no data for the role.
@@ -2924,8 +2942,10 @@ bool QStandardItemModel::insertRows(int row, int count, const QModelIndex &paren
QMap<int, QVariant> QStandardItemModel::itemData(const QModelIndex &index) const
{
Q_D(const QStandardItemModel);
- QStandardItem *item = d->itemFromIndex(index);
- return item ? item->d_func()->itemData() : QMap<int, QVariant>();
+ const QStandardItem *const item = d->itemFromIndex(index);
+ if (!item || item == d->root.data())
+ return QMap<int, QVariant>();
+ return item->d_func()->itemData();
}
/*!
@@ -2991,6 +3011,23 @@ bool QStandardItemModel::setData(const QModelIndex &index, const QVariant &value
}
/*!
+ \since 5.12
+ Removes the data stored in all the roles for the given \a index.
+ \sa setData(), data()
+*/
+bool QStandardItemModel::clearItemData(const QModelIndex &index)
+{
+ if (!checkIndex(index, CheckIndexOption::IndexIsValid))
+ return false;
+ Q_D(QStandardItemModel);
+ QStandardItem *item = d->itemFromIndex(index);
+ if (!item)
+ return false;
+ item->clearData();
+ return true;
+}
+
+/*!
\reimp
*/
bool QStandardItemModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role)
diff --git a/src/gui/itemmodels/qstandarditemmodel.h b/src/gui/itemmodels/qstandarditemmodel.h
index 827179b31d..a9ee25da75 100644
--- a/src/gui/itemmodels/qstandarditemmodel.h
+++ b/src/gui/itemmodels/qstandarditemmodel.h
@@ -69,6 +69,7 @@ public:
virtual QVariant data(int role = Qt::UserRole + 1) const;
virtual void setData(const QVariant &value, int role = Qt::UserRole + 1);
+ void clearData();
inline QString text() const {
return qvariant_cast<QString>(data(Qt::DisplayRole));
@@ -343,6 +344,8 @@ public:
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
+ // Qt 6: add override keyword
+ bool clearItemData(const QModelIndex &index);
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const override;
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri
index 3b9afdfe8b..1f137fc46f 100644
--- a/src/gui/kernel/kernel.pri
+++ b/src/gui/kernel/kernel.pri
@@ -74,8 +74,8 @@ HEADERS += \
kernel/qplatformgraphicsbufferhelper.h \
kernel/qinputdevicemanager_p.h \
kernel/qinputdevicemanager_p_p.h \
- kernel/qhighdpiscaling_p.h
-
+ kernel/qhighdpiscaling_p.h \
+ kernel/qtestsupport_gui.h
SOURCES += \
kernel/qgenericpluginfactory.cpp \
@@ -128,7 +128,8 @@ SOURCES += \
kernel/qplatformgraphicsbuffer.cpp \
kernel/qplatformgraphicsbufferhelper.cpp \
kernel/qinputdevicemanager.cpp \
- kernel/qhighdpiscaling.cpp
+ kernel/qhighdpiscaling.cpp \
+ kernel/qtestsupport_gui.cpp
qtConfig(draganddrop) {
HEADERS += \
diff --git a/src/gui/kernel/qdnd_p.h b/src/gui/kernel/qdnd_p.h
index cc00bc1442..5f6db07987 100644
--- a/src/gui/kernel/qdnd_p.h
+++ b/src/gui/kernel/qdnd_p.h
@@ -63,10 +63,6 @@
#include "private/qobject_p.h"
#include "QtGui/qbackingstore.h"
-// ### Remove the following include, once everybody includes
-// qinternalmimedata_p.h for QInternalMimeData.
-#include "qinternalmimedata_p.h"
-
QT_REQUIRE_CONFIG(draganddrop);
QT_BEGIN_NAMESPACE
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index 94fc342e2a..53d1ac1fc0 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -783,7 +783,7 @@ QWheelEvent::QWheelEvent(const QPointF &pos, int delta,
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
Qt::Orientation orient)
: QInputEvent(Wheel, modifiers), p(pos), qt4D(delta), qt4O(orient), mouseState(buttons),
- ph(Qt::NoScrollPhase), src(Qt::MouseEventNotSynthesized), invertedScrolling(false)
+ src(Qt::MouseEventNotSynthesized), invertedScrolling(false), ph(Qt::NoScrollPhase)
{
g = QCursor::pos();
if (orient == Qt::Vertical)
@@ -818,7 +818,7 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, int delta
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
Qt::Orientation orient)
: QInputEvent(Wheel, modifiers), p(pos), g(globalPos), qt4D(delta), qt4O(orient), mouseState(buttons),
- ph(Qt::NoScrollPhase), src(Qt::MouseEventNotSynthesized), invertedScrolling(false)
+ src(Qt::MouseEventNotSynthesized), invertedScrolling(false), ph(Qt::NoScrollPhase)
{
if (orient == Qt::Vertical)
angleD = QPoint(0, delta);
@@ -959,10 +959,49 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos,
QPoint pixelDelta, QPoint angleDelta, int qt4Delta, Qt::Orientation qt4Orientation,
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::ScrollPhase phase, Qt::MouseEventSource source, bool inverted)
: QInputEvent(Wheel, modifiers), p(pos), g(globalPos), pixelD(pixelDelta),
- angleD(angleDelta), qt4D(qt4Delta), qt4O(qt4Orientation), mouseState(buttons), ph(phase), src(source),
- invertedScrolling(inverted)
+ angleD(angleDelta), qt4D(qt4Delta), qt4O(qt4Orientation), mouseState(buttons), src(source),
+ invertedScrolling(inverted), ph(phase)
{}
+/*!
+ Constructs a wheel event object.
+
+ The \a pos provides the location of the mouse cursor
+ within the window. The position in global coordinates is specified
+ by \a globalPos.
+
+ \a pixelDelta contains the scrolling distance in pixels on screen, while
+ \a angleDelta contains the wheel rotation distance. \a pixelDelta is
+ optional and can be null.
+
+ The mouse and keyboard states at the time of the event are specified by
+ \a buttons and \a modifiers.
+
+ The scrolling phase of the event is specified by \a phase.
+
+ If the wheel event comes from a physical mouse wheel, \a source is set to
+ Qt::MouseEventNotSynthesized. If it comes from a gesture detected by the
+ operating system, or from a non-mouse hardware device, such that \a
+ pixelDelta is directly related to finger movement, \a source is set to
+ Qt::MouseEventSynthesizedBySystem. If it comes from Qt, source would be set
+ to Qt::MouseEventSynthesizedByQt.
+
+ If the system is configured to invert the delta values delivered with the
+ event (such as natural scrolling of the touchpad on macOS), \a inverted
+ should be \c true. Otherwise, \a inverted is \c false
+
+ \sa posF(), globalPosF(), angleDelta(), pixelDelta(), phase()
+*/
+QWheelEvent::QWheelEvent(QPointF pos, QPointF globalPos, QPoint pixelDelta, QPoint angleDelta,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::ScrollPhase phase,
+ bool inverted, Qt::MouseEventSource source)
+ : QInputEvent(Wheel, modifiers), p(pos), g(globalPos), pixelD(pixelDelta), angleD(angleDelta),
+ qt4O(qAbs(angleDelta.x()) > qAbs(angleDelta.y()) ? Qt::Horizontal : Qt::Vertical),
+ mouseState(buttons), src(source), invertedScrolling(inverted), ph(phase)
+{
+ qt4D = (qt4O == Qt::Horizontal ? angleDelta.x() : angleDelta.y());
+}
+
#endif // QT_CONFIG(wheelevent)
/*!
@@ -1536,8 +1575,8 @@ QMoveEvent::~QMoveEvent()
\ingroup events
- Expose events are sent to windows when an area of the window is invalidated
- or window exposure in the windowing system changes.
+ Expose events are sent to windows when an area of the window is invalidated,
+ for example when window exposure in the windowing system changes.
A Window with a client area that is completely covered by another window, or
is otherwise not visible may be considered obscured by Qt and may in such
@@ -4032,7 +4071,12 @@ QDebug operator<<(QDebug dbg, const QEvent *e)
# if QT_CONFIG(wheelevent)
case QEvent::Wheel: {
const QWheelEvent *we = static_cast<const QWheelEvent *>(e);
- dbg << "QWheelEvent(" << "pixelDelta=" << we->pixelDelta() << ", angleDelta=" << we->angleDelta() << ')';
+ dbg << "QWheelEvent(" << we->phase();
+ if (!we->pixelDelta().isNull() || !we->angleDelta().isNull())
+ dbg << ", pixelDelta=" << we->pixelDelta() << ", angleDelta=" << we->angleDelta();
+ else if (int qt4Delta = we->delta())
+ dbg << ", delta=" << qt4Delta << ", orientation=" << we->orientation();
+ dbg << ')';
}
break;
# endif // QT_CONFIG(wheelevent)
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index 033d24d665..2b1c6a6e31 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -193,6 +193,10 @@ public:
QWheelEvent(const QPointF &pos, const QPointF &globalPos, QPoint pixelDelta, QPoint angleDelta,
int qt4Delta, Qt::Orientation qt4Orientation, Qt::MouseButtons buttons,
Qt::KeyboardModifiers modifiers, Qt::ScrollPhase phase, Qt::MouseEventSource source, bool inverted);
+
+ QWheelEvent(QPointF pos, QPointF globalPos, QPoint pixelDelta, QPoint angleDelta,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::ScrollPhase phase,
+ bool inverted, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized);
~QWheelEvent();
@@ -225,13 +229,14 @@ protected:
QPointF g;
QPoint pixelD;
QPoint angleD;
- int qt4D;
- Qt::Orientation qt4O;
+ int qt4D = 0;
+ Qt::Orientation qt4O = Qt::Vertical;
Qt::MouseButtons mouseState;
- uint ph : 2;
+ uint _unused_ : 2; // Kept for binary compatibility
uint src: 2;
bool invertedScrolling : 1;
- int reserved : 27;
+ uint ph : 3;
+ int reserved : 24;
friend class QApplication;
};
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 06d1fcae53..f4e2dda05a 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -84,6 +84,7 @@
#include "private/qcursor_p.h"
#include "private/qopenglcontext_p.h"
#include "private/qinputdevicemanager_p.h"
+#include "private/qinputmethod_p.h"
#include "private/qtouchdevice_p.h"
#include <qpa/qplatformthemefactory_p.h>
@@ -114,6 +115,10 @@
# include <QtCore/QLibraryInfo>
#endif // Q_OS_WIN
+#ifdef Q_OS_WASM
+#include <emscripten.h>
+#endif
+
#include <qtgui_tracepoints_p.h>
#include <ctype.h>
@@ -143,6 +148,8 @@ Qt::ApplicationState QGuiApplicationPrivate::applicationState = Qt::ApplicationI
bool QGuiApplicationPrivate::highDpiScalingUpdated = false;
+QPointer<QWindow> QGuiApplicationPrivate::currentDragWindow;
+
QVector<QGuiApplicationPrivate::TabletPointData> QGuiApplicationPrivate::tabletDevicePoints;
QPlatformIntegration *QGuiApplicationPrivate::platform_integration = 0;
@@ -250,10 +257,10 @@ static inline void clearFontUnlocked()
QGuiApplicationPrivate::app_font = 0;
}
-static bool checkRunningUnderFlatpak()
+static bool checkNeedPortalSupport()
{
#if QT_CONFIG(dbus)
- return !QStandardPaths::locate(QStandardPaths::RuntimeLocation, QLatin1String("flatpak-info")).isEmpty();
+ return !QStandardPaths::locate(QStandardPaths::RuntimeLocation, QLatin1String("flatpak-info")).isEmpty() || qEnvironmentVariableIsSet("SNAP");
#else
return false;
#endif // QT_CONFIG(dbus)
@@ -592,6 +599,9 @@ static QWindowGeometrySpecification windowGeometrySpecification = Q_WINDOW_GEOME
By default, they will be used if the application is not an
instance of QApplication or for Qt Quick Controls 2
applications.
+
+ \li \c {altgr}, detect the key \c {AltGr} found on some keyboards as
+ Qt::GroupSwitchModifier.
\endlist
The following parameter is available for \c {-platform cocoa} (on macOS):
@@ -668,6 +678,7 @@ QGuiApplication::~QGuiApplication()
QGuiApplicationPrivate::currentMousePressWindow = QGuiApplicationPrivate::currentMouseWindow = nullptr;
QGuiApplicationPrivate::applicationState = Qt::ApplicationInactive;
QGuiApplicationPrivate::highDpiScalingUpdated = false;
+ QGuiApplicationPrivate::currentDragWindow = nullptr;
QGuiApplicationPrivate::tabletDevicePoints.clear();
#ifndef QT_NO_SESSIONMANAGER
QGuiApplicationPrivate::is_fallback_session_management_enabled = true;
@@ -1216,9 +1227,9 @@ static void init_platform(const QString &pluginNamesWithArguments, const QString
if (!platformThemeName.isEmpty())
themeNames.append(platformThemeName);
- // 2) Special case - check whether we are in sandbox to use flatpak platform theme for portals support
- if (checkRunningUnderFlatpak()) {
- themeNames.append(QStringLiteral("flatpak"));
+ // 2) Special case - check whether it's a flatpak or snap app to use xdg-desktop-portal platform theme for portals support
+ if (checkNeedPortalSupport()) {
+ themeNames.append(QStringLiteral("xdgdesktopportal"));
}
// 3) Ask the platform integration for a list of theme names
@@ -1410,7 +1421,7 @@ void QGuiApplicationPrivate::eventDispatcherReady()
void QGuiApplicationPrivate::init()
{
- Q_TRACE(qguiapplicationprivate_init_entry);
+ Q_TRACE(QGuiApplicationPrivate_init_entry);
#if defined(Q_OS_MACOS)
QMacAutoReleasePool pool;
@@ -1575,7 +1586,7 @@ void QGuiApplicationPrivate::init()
QObject::connect(q, &QGuiApplication::applicationNameChanged,
q, &QGuiApplication::applicationDisplayNameChanged);
- Q_TRACE(qguiapplicationprivate_init_exit);
+ Q_TRACE(QGuiApplicationPrivate_init_exit);
}
extern void qt_cleanupFontDatabase();
@@ -1615,7 +1626,13 @@ QGuiApplicationPrivate::~QGuiApplicationPrivate()
qt_gl_set_global_share_context(0);
}
#endif
-
+#ifdef Q_OS_WASM
+ EM_ASM(
+ // unmount persistent directory as IDBFS
+ // see QTBUG-70002
+ FS.unmount('/home/web_user');
+ );
+#endif
platform_integration->destroy();
delete platform_theme;
@@ -1691,7 +1708,7 @@ Qt::KeyboardModifiers QGuiApplication::queryKeyboardModifiers()
/*!
Returns the current state of the buttons on the mouse. The current state is
- updated syncronously as the event queue is emptied of events that will
+ updated synchronously as the event queue is emptied of events that will
spontaneously change the mouse state (QEvent::MouseButtonPress and
QEvent::MouseButtonRelease events).
@@ -1766,8 +1783,11 @@ int QGuiApplication::exec()
*/
bool QGuiApplication::notify(QObject *object, QEvent *event)
{
- if (object->isWindowType())
- QGuiApplicationPrivate::sendQWindowEventToQPlatformWindow(static_cast<QWindow *>(object), event);
+ if (object->isWindowType()) {
+ if (QGuiApplicationPrivate::sendQWindowEventToQPlatformWindow(static_cast<QWindow *>(object), event))
+ return true; // Platform plugin ate the event
+ }
+
return QCoreApplication::notify(object, event);
}
@@ -1789,18 +1809,18 @@ bool QGuiApplication::compressEvent(QEvent *event, QObject *receiver, QPostEvent
return QCoreApplication::compressEvent(event, receiver, postedEvents);
}
-void QGuiApplicationPrivate::sendQWindowEventToQPlatformWindow(QWindow *window, QEvent *event)
+bool QGuiApplicationPrivate::sendQWindowEventToQPlatformWindow(QWindow *window, QEvent *event)
{
if (!window)
- return;
+ return false;
QPlatformWindow *platformWindow = window->handle();
if (!platformWindow)
- return;
+ return false;
// spontaneous events come from the platform integration already, we don't need to send the events back
if (event->spontaneous())
- return;
+ return false;
// let the platform window do any handling it needs to as well
- platformWindow->windowEvent(event);
+ return platformWindow->windowEvent(event);
}
bool QGuiApplicationPrivate::processNativeEvent(QWindow *window, const QByteArray &eventType, void *message, long *result)
@@ -1810,7 +1830,7 @@ bool QGuiApplicationPrivate::processNativeEvent(QWindow *window, const QByteArra
void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e)
{
- Q_TRACE(qguiapplicationprivate_processwsevents_entry, e->type);
+ Q_TRACE(QGuiApplicationPrivate_processWindowSystemEvent_entry, e->type);
switch(e->type) {
case QWindowSystemInterfacePrivate::Mouse:
@@ -1921,7 +1941,7 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv
break;
}
- Q_TRACE(qguiapplicationprivate_processwsevents_exit, e->type);
+ Q_TRACE(QGuiApplicationPrivate_processWindowSystemEvent_exit, e->type);
}
/*! \internal
@@ -2333,11 +2353,11 @@ void QGuiApplicationPrivate::processWindowScreenChangedEvent(QWindowSystemInterf
if (QWindow *window = wse->window.data()) {
if (window->screen() == wse->screen.data())
return;
- if (window->isTopLevel()) {
+ if (QWindow *topLevelWindow = window->d_func()->topLevelWindow(QWindow::ExcludeTransients)) {
if (QScreen *screen = wse->screen.data())
- window->d_func()->setTopLevelScreen(screen, false /* recreate */);
+ topLevelWindow->d_func()->setTopLevelScreen(screen, false /* recreate */);
else // Fall back to default behavior, and try to find some appropriate screen
- window->setScreen(0);
+ topLevelWindow->setScreen(0);
}
// we may have changed scaling, so trigger resize event if needed
if (window->handle()) {
@@ -3048,9 +3068,56 @@ void QGuiApplicationPrivate::processExposeEvent(QWindowSystemInterfacePrivate::E
#if QT_CONFIG(draganddrop)
-QPlatformDragQtResponse QGuiApplicationPrivate::processDrag(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions)
+/*! \internal
+
+ This function updates an internal state to keep the source compatibility. Documentation of
+ QGuiApplication::mouseButtons() states - "The current state is updated synchronously as
+ the event queue is emptied of events that will spontaneously change the mouse state
+ (QEvent::MouseButtonPress and QEvent::MouseButtonRelease events)". But internally we have
+ been updating these state variables from various places to keep buttons returned by
+ mouseButtons() in sync with the systems state. This is not the documented behavior.
+
+ ### Qt6 - Remove QGuiApplication::mouseButtons()/keyboardModifiers() API? And here
+ are the reasons:
+
+ - It is an easy to misuse API by:
+
+ a) Application developers: The only place where the values of this API can be trusted is
+ when using within mouse handling callbacks. In these callbacks we work with the state
+ that was provided directly by the windowing system. Anywhere else it might not reflect what
+ user wrongly expects. We might not always receive a matching mouse release for a press event
+ (e.g. When dismissing a popup window on X11. Or when dnd enter Qt application with mouse
+ button down, we update mouse_buttons and then dnd leaves Qt application and does a drop
+ somewhere else) and hence mouseButtons() will be out-of-sync from users perspective, see
+ for example QTBUG-33161. BUT THIS IS NOT HOW THE API IS SUPPOSED TO BE USED. Since the only
+ safe place to use this API is from mouse event handlers, we might as well deprecate it and
+ pass down the button state if we are not already doing that everywhere where it matters.
+
+ b) Qt framework developers:
+
+ We see users complaining, we start adding hacks everywhere just to keep buttons in sync ;)
+ There are corner cases that can not be solved and adding this kind of hacks is never ending
+ task.
+
+ - Real mouse events, tablet mouse events, etc: all go through QGuiApplication::processMouseEvent,
+ and all share mouse_buttons. What if we want to support multiple mice in future? The API must
+ go.
+
+ - Motivation why this API is public is not clear. Could the same be achieved by a user by
+ installing an event filter?
+*/
+static void updateMouseAndModifierButtonState(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
+{
+ QGuiApplicationPrivate::mouse_buttons = buttons;
+ QGuiApplicationPrivate::modifier_buttons = modifiers;
+}
+
+QPlatformDragQtResponse QGuiApplicationPrivate::processDrag(QWindow *w, const QMimeData *dropData,
+ const QPoint &p, Qt::DropActions supportedActions,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
{
- static QPointer<QWindow> currentDragWindow;
+ updateMouseAndModifierButtonState(buttons, modifiers);
+
static Qt::DropAction lastAcceptedDropAction = Qt::IgnoreAction;
QPlatformDrag *platformDrag = platformIntegration()->drag();
if (!platformDrag || (w && w->d_func()->blockedByModalWindow)) {
@@ -3059,15 +3126,13 @@ QPlatformDragQtResponse QGuiApplicationPrivate::processDrag(QWindow *w, const QM
}
if (!dropData) {
- if (currentDragWindow.data() == w)
- currentDragWindow = 0;
+ currentDragWindow = nullptr;
QDragLeaveEvent e;
QGuiApplication::sendEvent(w, &e);
lastAcceptedDropAction = Qt::IgnoreAction;
return QPlatformDragQtResponse(false, lastAcceptedDropAction, QRect());
}
- QDragMoveEvent me(p, supportedActions, dropData,
- QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
+ QDragMoveEvent me(p, supportedActions, dropData, buttons, modifiers);
if (w != currentDragWindow) {
lastAcceptedDropAction = Qt::IgnoreAction;
@@ -3076,8 +3141,7 @@ QPlatformDragQtResponse QGuiApplicationPrivate::processDrag(QWindow *w, const QM
QGuiApplication::sendEvent(currentDragWindow, &e);
}
currentDragWindow = w;
- QDragEnterEvent e(p, supportedActions, dropData,
- QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
+ QDragEnterEvent e(p, supportedActions, dropData, buttons, modifiers);
QGuiApplication::sendEvent(w, &e);
if (e.isAccepted() && e.dropAction() != Qt::IgnoreAction)
lastAcceptedDropAction = e.dropAction();
@@ -3095,10 +3159,15 @@ QPlatformDragQtResponse QGuiApplicationPrivate::processDrag(QWindow *w, const QM
return QPlatformDragQtResponse(me.isAccepted(), lastAcceptedDropAction, me.answerRect());
}
-QPlatformDropQtResponse QGuiApplicationPrivate::processDrop(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions)
+QPlatformDropQtResponse QGuiApplicationPrivate::processDrop(QWindow *w, const QMimeData *dropData,
+ const QPoint &p, Qt::DropActions supportedActions,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
{
- QDropEvent de(p, supportedActions, dropData,
- QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
+ updateMouseAndModifierButtonState(buttons, modifiers);
+
+ currentDragWindow = nullptr;
+
+ QDropEvent de(p, supportedActions, dropData, buttons, modifiers);
QGuiApplication::sendEvent(w, &de);
Qt::DropAction acceptedAction = de.isAccepted() ? de.dropAction() : Qt::IgnoreAction;
@@ -3963,18 +4032,7 @@ void QGuiApplicationPrivate::_q_updateFocusObject(QObject *object)
Q_Q(QGuiApplication);
QPlatformInputContext *inputContext = platformIntegration()->inputContext();
- bool enabled = false;
- if (object && inputContext) {
- QInputMethodQueryEvent query(Qt::ImEnabled | Qt::ImHints);
- QGuiApplication::sendEvent(object, &query);
- enabled = query.value(Qt::ImEnabled).toBool();
- if (enabled) {
- static const bool supportsHiddenText = inputContext->hasCapability(QPlatformInputContext::HiddenTextCapability);
- const Qt::InputMethodHints hints = static_cast<Qt::InputMethodHints>(query.value(Qt::ImHints).toInt());
- if ((hints & Qt::ImhHiddenText) && !supportsHiddenText)
- enabled = false;
- }
- }
+ const bool enabled = inputContext && QInputMethodPrivate::objectAcceptsInputMethod(object);
QPlatformInputContextPrivate::setInputMethodAccepted(enabled);
if (inputContext)
diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h
index f6f7aa7f8c..79c1a1c820 100644
--- a/src/gui/kernel/qguiapplication_p.h
+++ b/src/gui/kernel/qguiapplication_p.h
@@ -163,13 +163,17 @@ public:
#endif
#if QT_CONFIG(draganddrop)
- static QPlatformDragQtResponse processDrag(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions);
- static QPlatformDropQtResponse processDrop(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions);
+ static QPlatformDragQtResponse processDrag(QWindow *w, const QMimeData *dropData,
+ const QPoint &p, Qt::DropActions supportedActions,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers);
+ static QPlatformDropQtResponse processDrop(QWindow *w, const QMimeData *dropData,
+ const QPoint &p, Qt::DropActions supportedActions,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers);
#endif
static bool processNativeEvent(QWindow *window, const QByteArray &eventType, void *message, long *result);
- static void sendQWindowEventToQPlatformWindow(QWindow *window, QEvent *event);
+ static bool sendQWindowEventToQPlatformWindow(QWindow *window, QEvent *event);
static inline Qt::Alignment visualAlignment(Qt::LayoutDirection direction, Qt::Alignment alignment)
{
@@ -213,6 +217,7 @@ public:
static QWindow *currentMousePressWindow;
static Qt::ApplicationState applicationState;
static bool highDpiScalingUpdated;
+ static QPointer<QWindow> currentDragWindow;
struct TabletPointData {
TabletPointData(qint64 devId = 0) : deviceId(devId), state(Qt::NoButton), target(nullptr) {}
diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp
index 8689f9f3b1..a455aa639d 100644
--- a/src/gui/kernel/qhighdpiscaling.cpp
+++ b/src/gui/kernel/qhighdpiscaling.cpp
@@ -244,7 +244,8 @@ static inline bool usePixelDensity()
return false;
return QCoreApplication::testAttribute(Qt::AA_EnableHighDpiScaling)
|| (screenEnvValueOk && screenEnvValue > 0)
- || (qEnvironmentVariableIsSet(legacyDevicePixelEnvVar) && qgetenv(legacyDevicePixelEnvVar).toLower() == "auto");
+ || (qEnvironmentVariableIsSet(legacyDevicePixelEnvVar) &&
+ qgetenv(legacyDevicePixelEnvVar).compare("auto", Qt::CaseInsensitive) == 0);
}
void QHighDpiScaling::initHighDpiScaling()
diff --git a/src/gui/kernel/qinputmethod.cpp b/src/gui/kernel/qinputmethod.cpp
index 365b088840..a319529442 100644
--- a/src/gui/kernel/qinputmethod.cpp
+++ b/src/gui/kernel/qinputmethod.cpp
@@ -390,15 +390,29 @@ void QInputMethod::invokeAction(Action a, int cursorPosition)
ic->invokeAction(a, cursorPosition);
}
+static inline bool platformSupportsHiddenText()
+{
+ const QPlatformInputContext *inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext();
+ return inputContext && inputContext->hasCapability(QPlatformInputContext::HiddenTextCapability);
+}
+
bool QInputMethodPrivate::objectAcceptsInputMethod(QObject *object)
{
bool enabled = false;
if (object) {
- QInputMethodQueryEvent query(Qt::ImEnabled);
+ // If the platform does not support hidden text, query the hints
+ // in addition and disable in case of ImhHiddenText.
+ static const bool supportsHiddenText = platformSupportsHiddenText();
+ QInputMethodQueryEvent query(supportsHiddenText
+ ? Qt::InputMethodQueries(Qt::ImEnabled)
+ : Qt::InputMethodQueries(Qt::ImEnabled | Qt::ImHints));
QGuiApplication::sendEvent(object, &query);
enabled = query.value(Qt::ImEnabled).toBool();
+ if (enabled && !supportsHiddenText
+ && Qt::InputMethodHints(query.value(Qt::ImHints).toInt()).testFlag(Qt::ImhHiddenText)) {
+ enabled = false;
+ }
}
-
return enabled;
}
diff --git a/src/gui/kernel/qinputmethod_p.h b/src/gui/kernel/qinputmethod_p.h
index 81723bbe30..0c2b739d92 100644
--- a/src/gui/kernel/qinputmethod_p.h
+++ b/src/gui/kernel/qinputmethod_p.h
@@ -80,7 +80,7 @@ public:
void _q_connectFocusObject();
void _q_checkFocusObject(QObject *object);
- bool objectAcceptsInputMethod(QObject *object);
+ static bool objectAcceptsInputMethod(QObject *object);
QTransform inputItemTransform;
QRectF inputRectangle;
diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp
index 9a9677b476..a428da8ca4 100644
--- a/src/gui/kernel/qkeysequence.cpp
+++ b/src/gui/kernel/qkeysequence.cpp
@@ -1062,6 +1062,8 @@ int QKeySequence::decodeString(const QString &str)
int QKeySequencePrivate::decodeString(QString accel, QKeySequence::SequenceFormat format)
{
+ Q_ASSERT(!accel.isEmpty());
+
int ret = 0;
accel = std::move(accel).toLower();
bool nativeText = (format == QKeySequence::NativeText);
@@ -1121,7 +1123,10 @@ int QKeySequencePrivate::decodeString(QString accel, QKeySequence::SequenceForma
sl = accel;
}
}
+ if (accel.isEmpty()) // Incomplete, like for "Meta+Shift+"
+ return Qt::Key_unknown;
#endif
+
int i = 0;
int lastI = 0;
while ((i = sl.indexOf(QLatin1Char('+'), i + 1)) != -1) {
diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp
index 4efa5a40f3..c5d5490ea0 100644
--- a/src/gui/kernel/qopenglcontext.cpp
+++ b/src/gui/kernel/qopenglcontext.cpp
@@ -945,7 +945,7 @@ GLuint QOpenGLContext::defaultFramebufferObject() const
Avoid calling this function from a different thread than the one the
QOpenGLContext instance lives in. If you wish to use QOpenGLContext from a
- different thread you should first call make sure it's not current in the
+ different thread you should first make sure it's not current in the
current thread, by calling doneCurrent() if necessary. Then call
moveToThread(otherThread) before using it in the other thread.
@@ -977,67 +977,66 @@ bool QOpenGLContext::makeCurrent(QSurface *surface)
if (!surface->surfaceHandle())
return false;
if (!surface->supportsOpenGL()) {
+#ifndef Q_OS_WASM // ### work around the WASM platform plugin using QOpenGLContext with raster surfaces.
+ // see QTBUG-70076
qWarning() << "QOpenGLContext::makeCurrent() called with non-opengl surface" << surface;
return false;
+#endif
}
- QOpenGLContext *previous = QOpenGLContextPrivate::setCurrentContext(this);
-
- if (d->platformGLContext->makeCurrent(surface->surfaceHandle())) {
- static bool needsWorkaroundSet = false;
- static bool needsWorkaround = false;
+ if (!d->platformGLContext->makeCurrent(surface->surfaceHandle()))
+ return false;
- if (!needsWorkaroundSet) {
- QByteArray env;
-#ifdef Q_OS_ANDROID
- env = qgetenv(QByteArrayLiteral("QT_ANDROID_DISABLE_GLYPH_CACHE_WORKAROUND"));
- needsWorkaround = env.isEmpty() || env == QByteArrayLiteral("0") || env == QByteArrayLiteral("false");
+ QOpenGLContextPrivate::setCurrentContext(this);
+#ifndef QT_NO_DEBUG
+ QOpenGLContextPrivate::toggleMakeCurrentTracker(this, true);
#endif
- env = qgetenv(QByteArrayLiteral("QT_ENABLE_GLYPH_CACHE_WORKAROUND"));
- if (env == QByteArrayLiteral("1") || env == QByteArrayLiteral("true"))
- needsWorkaround = true;
-
- if (!needsWorkaround) {
- const char *rendererString = reinterpret_cast<const char *>(functions()->glGetString(GL_RENDERER));
- if (rendererString)
- needsWorkaround =
- qstrncmp(rendererString, "Mali-4xx", 6) == 0 // Mali-400, Mali-450
- || qstrcmp(rendererString, "Mali-T880") == 0
- || qstrncmp(rendererString, "Adreno (TM) 2xx", 13) == 0 // Adreno 200, 203, 205
- || qstrncmp(rendererString, "Adreno 2xx", 8) == 0 // Same as above but without the '(TM)'
- || qstrncmp(rendererString, "Adreno (TM) 3xx", 13) == 0 // Adreno 302, 305, 320, 330
- || qstrncmp(rendererString, "Adreno 3xx", 8) == 0 // Same as above but without the '(TM)'
- || qstrncmp(rendererString, "Adreno (TM) 4xx", 13) == 0 // Adreno 405, 418, 420, 430
- || qstrncmp(rendererString, "Adreno 4xx", 8) == 0 // Same as above but without the '(TM)'
- || qstrncmp(rendererString, "Adreno (TM) 5xx", 13) == 0 // Adreno 505, 506, 510, 530, 540
- || qstrncmp(rendererString, "Adreno 5xx", 8) == 0 // Same as above but without the '(TM)'
- || qstrncmp(rendererString, "Adreno (TM) 6xx", 13) == 0 // Adreno 610, 620, 630
- || qstrncmp(rendererString, "Adreno 6xx", 8) == 0 // Same as above but without the '(TM)'
- || qstrcmp(rendererString, "GC800 core") == 0
- || qstrcmp(rendererString, "GC1000 core") == 0
- || strstr(rendererString, "GC2000") != 0
- || qstrcmp(rendererString, "Immersion.16") == 0;
- }
- needsWorkaroundSet = true;
- }
-
- if (needsWorkaround)
- d->workaround_brokenFBOReadBack = true;
- d->surface = surface;
+ d->surface = surface;
- d->shareGroup->d_func()->deletePendingResources(this);
+ static bool needsWorkaroundSet = false;
+ static bool needsWorkaround = false;
-#ifndef QT_NO_DEBUG
- QOpenGLContextPrivate::toggleMakeCurrentTracker(this, true);
+ if (!needsWorkaroundSet) {
+ QByteArray env;
+#ifdef Q_OS_ANDROID
+ env = qgetenv(QByteArrayLiteral("QT_ANDROID_DISABLE_GLYPH_CACHE_WORKAROUND"));
+ needsWorkaround = env.isEmpty() || env == QByteArrayLiteral("0") || env == QByteArrayLiteral("false");
#endif
-
- return true;
+ env = qgetenv(QByteArrayLiteral("QT_ENABLE_GLYPH_CACHE_WORKAROUND"));
+ if (env == QByteArrayLiteral("1") || env == QByteArrayLiteral("true"))
+ needsWorkaround = true;
+
+ if (!needsWorkaround) {
+ const char *rendererString = reinterpret_cast<const char *>(functions()->glGetString(GL_RENDERER));
+ if (rendererString)
+ needsWorkaround =
+ qstrncmp(rendererString, "Mali-4xx", 6) == 0 // Mali-400, Mali-450
+ || qstrcmp(rendererString, "Mali-T880") == 0
+ || qstrncmp(rendererString, "Adreno (TM) 2xx", 13) == 0 // Adreno 200, 203, 205
+ || qstrncmp(rendererString, "Adreno 2xx", 8) == 0 // Same as above but without the '(TM)'
+ || qstrncmp(rendererString, "Adreno (TM) 3xx", 13) == 0 // Adreno 302, 305, 320, 330
+ || qstrncmp(rendererString, "Adreno 3xx", 8) == 0 // Same as above but without the '(TM)'
+ || qstrncmp(rendererString, "Adreno (TM) 4xx", 13) == 0 // Adreno 405, 418, 420, 430
+ || qstrncmp(rendererString, "Adreno 4xx", 8) == 0 // Same as above but without the '(TM)'
+ || qstrncmp(rendererString, "Adreno (TM) 5xx", 13) == 0 // Adreno 505, 506, 510, 530, 540
+ || qstrncmp(rendererString, "Adreno 5xx", 8) == 0 // Same as above but without the '(TM)'
+ || qstrncmp(rendererString, "Adreno (TM) 6xx", 13) == 0 // Adreno 610, 620, 630
+ || qstrncmp(rendererString, "Adreno 6xx", 8) == 0 // Same as above but without the '(TM)'
+ || qstrcmp(rendererString, "GC800 core") == 0
+ || qstrcmp(rendererString, "GC1000 core") == 0
+ || strstr(rendererString, "GC2000") != 0
+ || qstrcmp(rendererString, "Immersion.16") == 0;
+ }
+ needsWorkaroundSet = true;
}
- QOpenGLContextPrivate::setCurrentContext(previous);
+ if (needsWorkaround)
+ d->workaround_brokenFBOReadBack = true;
+
+ d->shareGroup->d_func()->deletePendingResources(this);
- return false;
+ return true;
}
/*!
@@ -1078,7 +1077,8 @@ QSurface *QOpenGLContext::surface() const
Swap the back and front buffers of \a surface.
Call this to finish a frame of OpenGL rendering, and make sure to
- call makeCurrent() again before you begin a new frame.
+ call makeCurrent() again before issuing any further OpenGL commands,
+ for example as part of a new frame.
*/
void QOpenGLContext::swapBuffers(QSurface *surface)
{
diff --git a/src/gui/kernel/qopenglwindow.cpp b/src/gui/kernel/qopenglwindow.cpp
index c3a264f1e8..8b052d92ae 100644
--- a/src/gui/kernel/qopenglwindow.cpp
+++ b/src/gui/kernel/qopenglwindow.cpp
@@ -511,7 +511,7 @@ GLuint QOpenGLWindow::defaultFramebufferObject() const
extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
/*!
- Returns a 32-bit RGB image of the framebuffer.
+ Returns a copy of the framebuffer.
\note This is a potentially expensive operation because it relies on
glReadPixels() to read back the pixels. This may be slow and can stall the
@@ -531,7 +531,9 @@ QImage QOpenGLWindow::grabFramebuffer()
return QImage();
makeCurrent();
- QImage img = qt_gl_read_framebuffer(size() * devicePixelRatio(), false, false);
+
+ const bool hasAlpha = format().hasAlpha();
+ QImage img = qt_gl_read_framebuffer(size() * devicePixelRatio(), hasAlpha, hasAlpha);
img.setDevicePixelRatio(devicePixelRatio());
return img;
}
diff --git a/src/gui/kernel/qpalette.cpp b/src/gui/kernel/qpalette.cpp
index 4905e51e01..9ccfb9b819 100644
--- a/src/gui/kernel/qpalette.cpp
+++ b/src/gui/kernel/qpalette.cpp
@@ -316,6 +316,21 @@ static void qt_palette_from_color(QPalette &pal, const QColor &button)
*/
/*!
+ \fn const QBrush & QPalette::placeholderText() const
+ \since 5.12
+
+ Returns the placeholder text brush of the current color group.
+
+ \note Before Qt 5.12, the placeholder text color was hard-coded in the code as
+ QPalette::text().color() where an alpha of 128 was applied.
+ We continue to support this behavior by default, unless you set your own brush.
+ One can get back the original placeholder color setting the special QBrush default
+ constructor as placeholder brush.
+
+ \sa ColorRole, brush()
+*/
+
+/*!
\fn ColorGroup QPalette::currentColorGroup() const
Returns the palette's current color group.
@@ -444,6 +459,9 @@ static void qt_palette_from_color(QPalette &pal, const QColor &button)
of QPalette, because tool tips are not active
windows.
+ \value PlaceholderText Used as the placeholder color for various text input widgets.
+ This enum value has been introduced in Qt 5.12
+
\value Text The foreground color used with \c Base. This is usually
the same as the \c WindowText, in which case it must provide
good contrast with \c Window and \c Base.
@@ -765,11 +783,32 @@ void QPalette::setBrush(ColorGroup cg, ColorRole cr, const QBrush &b)
cg = Active;
}
+ // For placeholder we want to continue to respect the original behavior, which is
+ // derivating the text color, but only if user has not yet set his own brush.
+ // We then use Qt::NoBrush as an inernal way to know if the brush is customized or not.
+
+ // ### Qt 6 - remove this special case
+ // Part 1 - Restore initial color to the given color group
+ if (cr == PlaceholderText && b == QBrush()) {
+ QColor col = brush(Text).color();
+ col.setAlpha(128);
+ setBrush(cg, PlaceholderText, QBrush(col, Qt::NoBrush));
+ return;
+ }
+
if (d->br[cg][cr] != b) {
detach();
d->br[cg][cr] = b;
}
data.resolve_mask |= (1<<cr);
+
+ // ### Qt 6 - remove this special case
+ // Part 2 - Update initial color to the given color group
+ if (cr == Text && d->br[cg][PlaceholderText].style() == Qt::NoBrush) {
+ QColor col = brush(Text).color();
+ col.setAlpha(128);
+ setBrush(cg, PlaceholderText, QBrush(col, Qt::NoBrush));
+ }
}
/*!
@@ -962,7 +1001,7 @@ QDataStream &operator<<(QDataStream &s, const QPalette &p)
for (int i = 0; i < NumOldRoles; ++i)
s << p.d->br[grp][oldRoles[i]].color();
} else {
- int max = QPalette::ToolTipText + 1;
+ int max = (int)QPalette::NColorRoles;
if (s.version() <= QDataStream::Qt_2_1)
max = QPalette::HighlightedText + 1;
else if (s.version() <= QDataStream::Qt_4_3)
@@ -1159,7 +1198,7 @@ QDebug operator<<(QDebug dbg, const QPalette &p)
{"WindowText", "Button", "Light", "Midlight", "Dark", "Mid", "Text",
"BrightText", "ButtonText", "Base", "Window", "Shadow", "Highlight",
"HighlightedText", "Link", "LinkVisited", "AlternateBase", "NoRole",
- "ToolTipBase","ToolTipText" };
+ "ToolTipBase","ToolTipText", "PlaceholderText" };
QDebugStateSaver saver(dbg);
QDebug nospace = dbg.nospace();
const uint mask = p.resolve();
diff --git a/src/gui/kernel/qpalette.h b/src/gui/kernel/qpalette.h
index 71f3d0c3b8..071eddbc4d 100644
--- a/src/gui/kernel/qpalette.h
+++ b/src/gui/kernel/qpalette.h
@@ -96,7 +96,8 @@ public:
AlternateBase,
NoRole,
ToolTipBase, ToolTipText,
- NColorRoles = ToolTipText + 1,
+ PlaceholderText,
+ NColorRoles = PlaceholderText + 1,
Foreground = WindowText, Background = Window
};
Q_ENUM(ColorRole)
@@ -141,6 +142,7 @@ public:
inline const QBrush &highlightedText() const { return brush(HighlightedText); }
inline const QBrush &link() const { return brush(Link); }
inline const QBrush &linkVisited() const { return brush(LinkVisited); }
+ inline const QBrush &placeholderText() const { return brush(PlaceholderText); }
bool operator==(const QPalette &p) const;
inline bool operator!=(const QPalette &p) const { return !(operator==(p)); }
diff --git a/src/gui/kernel/qplatformdialoghelper.cpp b/src/gui/kernel/qplatformdialoghelper.cpp
index b456c1ca31..b787629f6a 100644
--- a/src/gui/kernel/qplatformdialoghelper.cpp
+++ b/src/gui/kernel/qplatformdialoghelper.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -44,6 +44,7 @@
#include <QtCore/QSharedData>
#include <QtCore/QSettings>
#include <QtCore/QUrl>
+#include <QtCore/QVector>
#include <QtGui/QColor>
#include <algorithm>
@@ -786,7 +787,8 @@ class QMessageDialogOptionsPrivate : public QSharedData
public:
QMessageDialogOptionsPrivate() :
icon(QMessageDialogOptions::NoIcon),
- buttons(QPlatformDialogHelper::Ok)
+ buttons(QPlatformDialogHelper::Ok),
+ nextCustomButtonId(QPlatformDialogHelper::LastButton + 1)
{}
QString windowTitle;
@@ -795,6 +797,8 @@ public:
QString informativeText;
QString detailedText;
QPlatformDialogHelper::StandardButtons buttons;
+ QVector<QMessageDialogOptions::CustomButton> customButtons;
+ int nextCustomButtonId;
};
QMessageDialogOptions::QMessageDialogOptions(QMessageDialogOptionsPrivate *dd)
@@ -886,6 +890,35 @@ QPlatformDialogHelper::StandardButtons QMessageDialogOptions::standardButtons()
return d->buttons;
}
+int QMessageDialogOptions::addButton(const QString &label, QPlatformDialogHelper::ButtonRole role,
+ void *buttonImpl)
+{
+ const CustomButton b(d->nextCustomButtonId++, label, role, buttonImpl);
+ d->customButtons.append(b);
+ return b.id;
+}
+
+static inline bool operator==(const QMessageDialogOptions::CustomButton &a,
+ const QMessageDialogOptions::CustomButton &b) {
+ return a.id == b.id;
+}
+
+void QMessageDialogOptions::removeButton(int id)
+{
+ d->customButtons.removeOne(CustomButton(id));
+}
+
+const QVector<QMessageDialogOptions::CustomButton> &QMessageDialogOptions::customButtons()
+{
+ return d->customButtons;
+}
+
+const QMessageDialogOptions::CustomButton *QMessageDialogOptions::customButton(int id)
+{
+ int i = d->customButtons.indexOf(CustomButton(id));
+ return (i < 0 ? nullptr : &d->customButtons.at(i));
+}
+
QPlatformDialogHelper::ButtonRole QPlatformDialogHelper::buttonRole(QPlatformDialogHelper::StandardButton button)
{
switch (button) {
diff --git a/src/gui/kernel/qplatformdialoghelper.h b/src/gui/kernel/qplatformdialoghelper.h
index f58dcf17f0..bfcb658172 100644
--- a/src/gui/kernel/qplatformdialoghelper.h
+++ b/src/gui/kernel/qplatformdialoghelper.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -150,6 +150,7 @@ public:
MacModelessLayout,
AndroidLayout
};
+ Q_ENUM(ButtonLayout)
QPlatformDialogHelper();
virtual ~QPlatformDialogHelper();
@@ -459,6 +460,26 @@ public:
void setStandardButtons(QPlatformDialogHelper::StandardButtons buttons);
QPlatformDialogHelper::StandardButtons standardButtons() const;
+ struct CustomButton {
+ explicit CustomButton(
+ int id = -1, const QString &label = QString(),
+ QPlatformDialogHelper::ButtonRole role = QPlatformDialogHelper::InvalidRole,
+ void *button = nullptr) :
+ label(label), role(role), id(id), button(button)
+ {}
+
+ QString label;
+ QPlatformDialogHelper::ButtonRole role;
+ int id;
+ void *button; // strictly internal use only
+ };
+
+ int addButton(const QString &label, QPlatformDialogHelper::ButtonRole role,
+ void *buttonImpl = nullptr);
+ void removeButton(int id);
+ const QVector<CustomButton> &customButtons();
+ const CustomButton *customButton(int id);
+
private:
QMessageDialogOptionsPrivate *d;
};
diff --git a/src/gui/kernel/qplatformgraphicsbufferhelper.cpp b/src/gui/kernel/qplatformgraphicsbufferhelper.cpp
index 2afb5e6ba5..924266997d 100644
--- a/src/gui/kernel/qplatformgraphicsbufferhelper.cpp
+++ b/src/gui/kernel/qplatformgraphicsbufferhelper.cpp
@@ -57,24 +57,28 @@
QT_BEGIN_NAMESPACE
/*!
- Convenience function to both lock and bind the buffer to a texture. This
- function will first try and lock with texture read and texture write
+ Convenience function to both lock and bind the \a graphicsBuffer to a texture.
+ This function will first try to lock with texture read and texture write
access. If this succeeds it will use the bindToTexture function to bind the
- content to the currently bound texture. If this fail it will try and lock
- with SWReadAccess and then use the bindSWToTexture convenience function.
+ content to the currently bound texture, and if \a premultiplied is provided,
+ it is set to false.
- \a swizzle is suppose to be used by the caller to figure out if the Red and
+ If it fails, it will try to lock with SWReadAccess and then use the
+ bindSWToTexture convenience function. If \a premultiplied is provided, it is
+ passed to the bindSWToTexture() function.
+
+ \a swizzle is meant to be used by the caller to figure out if the Red and
Blue color channels need to be swizzled when rendering.
\a rect is the subrect which is desired to be bounded to the texture. This
- argument has a no less than semantic, meaning more (if not all) of the buffer
+ argument has a not less than semantic, meaning more (if not all) of the buffer
can be bounded to the texture. An empty QRect is interpreted as entire buffer
should be bound.
The user should use the AccessTypes returned by isLocked to figure out what
lock has been obtained.
- returns true if the buffer has successfully been bound to the currently
+ Returns true if the buffer has successfully been bound to the currently
bound texture, otherwise returns false.
*/
bool QPlatformGraphicsBufferHelper::lockAndBindToTexture(QPlatformGraphicsBuffer *graphicsBuffer,
@@ -103,26 +107,29 @@ bool QPlatformGraphicsBufferHelper::lockAndBindToTexture(QPlatformGraphicsBuffer
}
/*!
- Convenience function that uploads the current raster content to the currently bound texture.
+ Convenience function that uploads the current raster content to the currently
+ bound texture.
- \a swizzleRandB is suppose to be used by the caller to figure out if the Red and
+ \a swizzleRandB is meant to be used by the caller to decide if the Red and
Blue color channels need to be swizzled when rendering. This is an
optimization. Qt often renders to software buffers interpreting pixels as
unsigned ints. When these buffers are uploaded to textures and each color
channel per pixel is interpreted as a byte (read sequentially), then the
- Red and Blue channels are swapped. Conveniently the Alpha buffer will be
- correct since Qt historically has had the alpha channel as the first
+ Red and Blue channels are swapped. Conveniently, the Alpha buffer will be
+ correct, since Qt historically has had the alpha channel as the first
channel, while OpenGL typically expects the alpha channel to be the last
channel.
- \a subRect is the subrect which is desired to be bounded to the texture. This
- argument has a no less than semantic, meaning more (if not all) of the buffer
- can be bounded to the texture. An empty QRect is interpreted as entire buffer
- should be bound.
+ \a subRect is the region to be bound to the texture. This argument has a
+ not less than semantic, meaning more (if not all) of the buffer can be
+ bound to the texture. An empty QRect is interpreted as meaning the entire
+ buffer should be bound.
- This function fails for buffers not capable of locking to SWAccess.
+ This function fails if the \a graphicsBuffer is not locked to SWAccess.
- Returns true on success, otherwise false.
+ Returns true on success, otherwise false. If \a premultipliedB is
+ provided, it is set according to what happens, if the function returns
+ true.
*/
bool QPlatformGraphicsBufferHelper::bindSWToTexture(const QPlatformGraphicsBuffer *graphicsBuffer,
bool *swizzleRandB, bool *premultipliedB,
diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp
index dfb8f60915..6e285a8fa5 100644
--- a/src/gui/kernel/qplatformintegration.cpp
+++ b/src/gui/kernel/qplatformintegration.cpp
@@ -99,8 +99,8 @@ QPlatformClipboard *QPlatformIntegration::clipboard() const
/*!
Accessor for the platform integration's drag object.
- Default implementation returns 0, implying no drag and drop support.
-
+ Default implementation returns QSimpleDrag. This class supports only drag
+ and drop operations within the same Qt application.
*/
QPlatformDrag *QPlatformIntegration::drag() const
{
diff --git a/src/gui/kernel/qplatformmenu.h b/src/gui/kernel/qplatformmenu.h
index e3fa5c71b1..28c29a704c 100644
--- a/src/gui/kernel/qplatformmenu.h
+++ b/src/gui/kernel/qplatformmenu.h
@@ -158,6 +158,7 @@ public:
virtual void removeMenu(QPlatformMenu *menu) = 0;
virtual void syncMenu(QPlatformMenu *menuItem) = 0;
virtual void handleReparent(QWindow *newParentWindow) = 0;
+ virtual QWindow *parentWindow() const { return nullptr; }
virtual QPlatformMenu *menuForTag(quintptr tag) const = 0;
virtual QPlatformMenu *createMenu() const;
diff --git a/src/gui/kernel/qplatformscreen.cpp b/src/gui/kernel/qplatformscreen.cpp
index 358ff16930..9614be7f3e 100644
--- a/src/gui/kernel/qplatformscreen.cpp
+++ b/src/gui/kernel/qplatformscreen.cpp
@@ -72,7 +72,7 @@ QPlatformScreen::~QPlatformScreen()
This function is called when Qt needs to be able to grab the content of a window.
- Returnes the content of the window specified with the WId handle within the boundaries of
+ Returns the content of the window specified with the WId handle within the boundaries of
QRect(x,y,width,height).
*/
QPixmap QPlatformScreen::grabWindow(WId window, int x, int y, int width, int height) const
diff --git a/src/gui/kernel/qplatformsurface.cpp b/src/gui/kernel/qplatformsurface.cpp
index f091c04ebb..fdb2cf567d 100644
--- a/src/gui/kernel/qplatformsurface.cpp
+++ b/src/gui/kernel/qplatformsurface.cpp
@@ -38,6 +38,10 @@
****************************************************************************/
#include "qplatformsurface.h"
+#ifndef QT_NO_DEBUG_STREAM
+#include <QtCore/qdebug.h>
+#include <QtGui/qwindow.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -64,5 +68,26 @@ QPlatformSurface::QPlatformSurface(QSurface *surface) : m_surface(surface)
{
}
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QPlatformSurface *surface)
+{
+ QDebugStateSaver saver(debug);
+ debug.nospace();
+ debug << "QPlatformSurface(" << (const void *)surface;
+ if (surface) {
+ QSurface *s = surface->surface();
+ auto surfaceClass = s->surfaceClass();
+ debug << ", class=" << surfaceClass;
+ debug << ", type=" << s->surfaceType();
+ if (surfaceClass == QSurface::Window)
+ debug << ", window=" << static_cast<QWindow *>(s);
+ else
+ debug << ", surface=" << s;
+ }
+ debug << ')';
+ return debug;
+}
+#endif // !QT_NO_DEBUG_STREAM
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformsurface.h b/src/gui/kernel/qplatformsurface.h
index 76e8767a05..4d8854fb40 100644
--- a/src/gui/kernel/qplatformsurface.h
+++ b/src/gui/kernel/qplatformsurface.h
@@ -58,6 +58,10 @@ QT_BEGIN_NAMESPACE
class QPlatformScreen;
+#ifndef QT_NO_DEBUG_STREAM
+class QDebug;
+#endif
+
class Q_GUI_EXPORT QPlatformSurface
{
public:
@@ -76,6 +80,11 @@ private:
friend class QPlatformOffscreenSurface;
};
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QPlatformSurface *surface);
+#endif
+
QT_END_NAMESPACE
#endif //QPLATFORMSURFACE_H
diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp
index a66420c364..50f05721f7 100644
--- a/src/gui/kernel/qplatformwindow.cpp
+++ b/src/gui/kernel/qplatformwindow.cpp
@@ -140,7 +140,7 @@ void QPlatformWindow::setGeometry(const QRect &rect)
}
/*!
- Returnes the current geometry of a window
+ Returns the current geometry of a window
*/
QRect QPlatformWindow::geometry() const
{
@@ -340,6 +340,20 @@ void QPlatformWindow::setWindowFilePath(const QString &filePath) { Q_UNUSED(file
void QPlatformWindow::setWindowIcon(const QIcon &icon) { Q_UNUSED(icon); }
/*!
+ Reimplement to let the platform handle non-spontaneous window close.
+
+ When reimplementing make sure to call the base class implementation
+ or QWindowSystemInterface::handleCloseEvent(), which will prompt the
+ user to accept the window close (if needed) and then close the QWindow.
+*/
+bool QPlatformWindow::close()
+{
+ bool accepted = false;
+ QWindowSystemInterface::handleCloseEvent<QWindowSystemInterface::SynchronousDelivery>(window(), &accepted);
+ return accepted;
+}
+
+/*!
Reimplement to be able to let Qt raise windows to the top of the desktop
*/
void QPlatformWindow::raise() { qWarning("This plugin does not support raise()"); }
@@ -447,14 +461,26 @@ bool QPlatformWindow::setWindowModified(bool modified)
/*!
Reimplement this method to be able to do any platform specific event
- handling. All events for window() are passed to this function before being
- sent to QWindow::event().
+ handling. All non-synthetic events for window() are passed to this
+ function before being sent to QWindow::event().
- The default implementation is empty and does nothing with \a event.
+ Return true if the event should not be passed on to the QWindow.
+
+ Subclasses should always call the base class implementation.
*/
-void QPlatformWindow::windowEvent(QEvent *event)
+bool QPlatformWindow::windowEvent(QEvent *event)
{
- Q_UNUSED(event);
+ Q_D(QPlatformWindow);
+
+ if (event->type() == QEvent::Timer) {
+ if (static_cast<QTimerEvent *>(event)->timerId() == d->updateTimer.timerId()) {
+ d->updateTimer.stop();
+ deliverUpdateRequest();
+ return true;
+ }
+ }
+
+ return false;
}
/*!
@@ -710,7 +736,7 @@ QRect QPlatformWindow::initialGeometry(const QWindow *w,
QPlatformWindow subclasses can re-implement this function to
provide display refresh synchronized updates. The event
- should be delivered using QWindowPrivate::deliverUpdateRequest()
+ should be delivered using QPlatformWindow::deliverUpdateRequest()
to not get out of sync with the the internal state of QWindow.
The default implementation posts an UpdateRequest event to the
@@ -720,18 +746,44 @@ QRect QPlatformWindow::initialGeometry(const QWindow *w,
*/
void QPlatformWindow::requestUpdate()
{
- static int timeout = -1;
- if (timeout == -1) {
+ Q_D(QPlatformWindow);
+
+ static int updateInterval = []() {
bool ok = false;
- timeout = qEnvironmentVariableIntValue("QT_QPA_UPDATE_IDLE_TIME", &ok);
- if (!ok)
- timeout = 5;
- }
+ int customUpdateInterval = qEnvironmentVariableIntValue("QT_QPA_UPDATE_IDLE_TIME", &ok);
+ return ok ? customUpdateInterval : 5;
+ }();
+
+ Q_ASSERT(!d->updateTimer.isActive());
+ d->updateTimer.start(updateInterval, Qt::PreciseTimer, window());
+}
+
+/*!
+ Returns true if the window has a pending update request.
+
+ \sa requestUpdate(), deliverUpdateRequest()
+*/
+bool QPlatformWindow::hasPendingUpdateRequest() const
+{
+ return qt_window_private(window())->updateRequestPending;
+}
+
+/*!
+ Delivers an QEvent::UpdateRequest event to the window.
+
+ QPlatformWindow subclasses can re-implement this function to
+ provide e.g. logging or tracing of the delivery, but should
+ always call the base class function.
+*/
+void QPlatformWindow::deliverUpdateRequest()
+{
+ Q_ASSERT(hasPendingUpdateRequest());
QWindow *w = window();
- QWindowPrivate *wp = (QWindowPrivate *) QObjectPrivate::get(w);
- Q_ASSERT(wp->updateTimer == 0);
- wp->updateTimer = w->startTimer(timeout, Qt::PreciseTimer);
+ QWindowPrivate *wp = qt_window_private(w);
+ wp->updateRequestPending = false;
+ QEvent request(QEvent::UpdateRequest);
+ QCoreApplication::sendEvent(w, &request);
}
/*!
diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h
index 84dff681d5..1590a10554 100644
--- a/src/gui/kernel/qplatformwindow.h
+++ b/src/gui/kernel/qplatformwindow.h
@@ -100,6 +100,7 @@ public:
virtual void setWindowTitle(const QString &title);
virtual void setWindowFilePath(const QString &title);
virtual void setWindowIcon(const QIcon &icon);
+ virtual bool close();
virtual void raise();
virtual void lower();
@@ -126,7 +127,7 @@ public:
virtual bool setWindowModified(bool modified);
- virtual void windowEvent(QEvent *event);
+ virtual bool windowEvent(QEvent *event);
virtual bool startSystemResize(const QPoint &pos, Qt::Corner corner);
virtual bool startSystemMove(const QPoint &pos);
@@ -143,6 +144,8 @@ public:
const QRect &initialGeometry, int defaultWidth, int defaultHeight);
virtual void requestUpdate();
+ bool hasPendingUpdateRequest() const;
+ virtual void deliverUpdateRequest();
// Window property accessors. Platform plugins should use these
// instead of accessing QWindow directly.
diff --git a/src/gui/kernel/qplatformwindow_p.h b/src/gui/kernel/qplatformwindow_p.h
index 62ecd61d9e..00dae9334c 100644
--- a/src/gui/kernel/qplatformwindow_p.h
+++ b/src/gui/kernel/qplatformwindow_p.h
@@ -52,6 +52,7 @@
//
#include <QtGui/private/qtguiglobal_p.h>
+#include <QtCore/qbasictimer.h>
#include <QtCore/qrect.h>
QT_BEGIN_NAMESPACE
@@ -60,6 +61,7 @@ class QPlatformWindowPrivate
{
public:
QRect rect;
+ QBasicTimer updateTimer;
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qshortcutmap.cpp b/src/gui/kernel/qshortcutmap.cpp
index fa1eb6f6bf..3bb42c1c0b 100644
--- a/src/gui/kernel/qshortcutmap.cpp
+++ b/src/gui/kernel/qshortcutmap.cpp
@@ -540,6 +540,19 @@ void QShortcutMap::createNewSequences(QKeyEvent *e, QVector<QKeySequence> &ksl,
{
Q_D(QShortcutMap);
QList<int> possibleKeys = QKeyMapper::possibleKeys(e);
+#if defined(DEBUG_QSHORTCUTMAP)
+ {
+ QDebug debug = qDebug().nospace();
+ debug << __FUNCTION__ << '(' << e << ", ignoredModifiers="
+ << Qt::KeyboardModifiers(ignoredModifiers) << "), possibleKeys=(";
+ for (int i = 0, size = possibleKeys.size(); i < size; ++i) {
+ if (i)
+ debug << ", ";
+ debug << QKeySequence(possibleKeys.at(i));
+ }
+ debug << ')';
+ }
+#endif // DEBUG_QSHORTCUTMAP
int pkTotal = possibleKeys.count();
if (!pkTotal)
return;
diff --git a/src/gui/kernel/qsimpledrag.cpp b/src/gui/kernel/qsimpledrag.cpp
index 12e204a09f..a84f873437 100644
--- a/src/gui/kernel/qsimpledrag.cpp
+++ b/src/gui/kernel/qsimpledrag.cpp
@@ -94,11 +94,7 @@ static QWindow* topLevelAt(const QPoint &pos)
(within the Qt application or outside) accepts the drag and sets the state accordingly.
*/
-QBasicDrag::QBasicDrag() :
- m_current_window(nullptr), m_restoreCursor(false), m_eventLoop(nullptr),
- m_executed_drop_action(Qt::IgnoreAction), m_can_drop(false),
- m_drag(nullptr), m_drag_icon_window(nullptr), m_useCompositing(true),
- m_screen(nullptr)
+QBasicDrag::QBasicDrag()
{
}
@@ -158,7 +154,8 @@ bool QBasicDrag::eventFilter(QObject *o, QEvent *e)
case QEvent::MouseMove:
{
QPoint nativePosition = getNativeMousePos(e, m_drag_icon_window);
- move(nativePosition);
+ auto mouseMove = static_cast<QMouseEvent *>(e);
+ move(nativePosition, mouseMove->buttons(), mouseMove->modifiers());
return true; // Eat all mouse move events
}
case QEvent::MouseButtonRelease:
@@ -166,7 +163,8 @@ bool QBasicDrag::eventFilter(QObject *o, QEvent *e)
disableEventFilter();
if (canDrop()) {
QPoint nativePosition = getNativeMousePos(e, m_drag_icon_window);
- drop(nativePosition);
+ auto mouseRelease = static_cast<QMouseEvent *>(e);
+ drop(nativePosition, mouseRelease->buttons(), mouseRelease->modifiers());
} else {
cancel();
}
@@ -179,9 +177,9 @@ bool QBasicDrag::eventFilter(QObject *o, QEvent *e)
// make the event relative to the window where the drag started. (QTBUG-66103)
const QMouseEvent *release = static_cast<QMouseEvent *>(e);
const QWindow *releaseWindow = topLevelAt(release->globalPos());
- qCDebug(lcDnd) << "mouse released over" << releaseWindow << "after drag from" << m_current_window << "globalPos" << release->globalPos();
+ qCDebug(lcDnd) << "mouse released over" << releaseWindow << "after drag from" << m_sourceWindow << "globalPos" << release->globalPos();
if (!releaseWindow)
- releaseWindow = m_current_window;
+ releaseWindow = m_sourceWindow;
QPoint releaseWindowPos = (releaseWindow ? releaseWindow->mapFromGlobal(release->globalPos()) : release->globalPos());
QMouseEvent *newRelease = new QMouseEvent(release->type(),
releaseWindowPos, releaseWindowPos, release->screenPos(),
@@ -204,18 +202,15 @@ Qt::DropAction QBasicDrag::drag(QDrag *o)
m_drag = o;
m_executed_drop_action = Qt::IgnoreAction;
m_can_drop = false;
- m_restoreCursor = true;
-#ifndef QT_NO_CURSOR
- qApp->setOverrideCursor(Qt::DragCopyCursor);
- updateCursor(m_executed_drop_action);
-#endif
+
startDrag();
m_eventLoop = new QEventLoop;
m_eventLoop->exec();
delete m_eventLoop;
- m_eventLoop = 0;
- m_drag = 0;
+ m_eventLoop = nullptr;
+ m_drag = nullptr;
endDrag();
+
return m_executed_drop_action;
}
@@ -227,16 +222,6 @@ void QBasicDrag::cancelDrag()
}
}
-void QBasicDrag::restoreCursor()
-{
- if (m_restoreCursor) {
-#ifndef QT_NO_CURSOR
- QGuiApplication::restoreOverrideCursor();
-#endif
- m_restoreCursor = false;
- }
-}
-
void QBasicDrag::startDrag()
{
QPoint pos;
@@ -287,7 +272,7 @@ void QBasicDrag::moveShapedPixmapWindow(const QPoint &globalPos)
m_drag_icon_window->updateGeometry(globalPos);
}
-void QBasicDrag::drop(const QPoint &)
+void QBasicDrag::drop(const QPoint &, Qt::MouseButtons, Qt::KeyboardModifiers)
{
disableEventFilter();
restoreCursor();
@@ -318,25 +303,34 @@ void QBasicDrag::updateCursor(Qt::DropAction action)
}
}
- QCursor *cursor = QGuiApplication::overrideCursor();
QPixmap pixmap = m_drag->dragCursor(action);
- if (!cursor) {
- QGuiApplication::changeOverrideCursor((pixmap.isNull()) ? QCursor(cursorShape) : QCursor(pixmap));
+
+ if (!m_dndHasSetOverrideCursor) {
+ QCursor newCursor = !pixmap.isNull() ? QCursor(pixmap) : QCursor(cursorShape);
+ QGuiApplication::setOverrideCursor(newCursor);
+ m_dndHasSetOverrideCursor = true;
} else {
+ QCursor *cursor = QGuiApplication::overrideCursor();
if (!pixmap.isNull()) {
- if ((cursor->pixmap().cacheKey() != pixmap.cacheKey())) {
+ if (cursor->pixmap().cacheKey() != pixmap.cacheKey())
QGuiApplication::changeOverrideCursor(QCursor(pixmap));
- }
- } else {
- if (cursorShape != cursor->shape()) {
- QGuiApplication::changeOverrideCursor(QCursor(cursorShape));
- }
+ } else if (cursorShape != cursor->shape()) {
+ QGuiApplication::changeOverrideCursor(QCursor(cursorShape));
}
}
#endif
updateAction(action);
}
+void QBasicDrag::restoreCursor()
+{
+#ifndef QT_NO_CURSOR
+ if (m_dndHasSetOverrideCursor) {
+ QGuiApplication::restoreOverrideCursor();
+ m_dndHasSetOverrideCursor = false;
+ }
+#endif
+}
static inline QPoint fromNativeGlobalPixels(const QPoint &point)
{
@@ -374,57 +368,83 @@ QSimpleDrag::QSimpleDrag()
void QSimpleDrag::startDrag()
{
+ setExecutedDropAction(Qt::IgnoreAction);
+
QBasicDrag::startDrag();
- m_current_window = topLevelAt(QCursor::pos());
- if (m_current_window) {
- QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_current_window, drag()->mimeData(), QHighDpi::toNativePixels(QCursor::pos(), m_current_window), drag()->supportedActions());
- setCanDrop(response.isAccepted());
- updateCursor(response.acceptedAction());
+ // Here we can be fairly sure that QGuiApplication::mouseButtons/keyboardModifiers() will
+ // contain sensible values as startDrag() normally is called from mouse event handlers
+ // by QDrag::exec(). A better API would be if we could pass something like "input device
+ // pointer" to QDrag::exec(). My guess is that something like that might be required for
+ // QTBUG-52430.
+ m_sourceWindow = topLevelAt(QCursor::pos());
+ m_windowUnderCursor = m_sourceWindow;
+ if (m_sourceWindow) {
+ auto nativePixelPos = QHighDpi::toNativePixels(QCursor::pos(), m_sourceWindow);
+ move(nativePixelPos, QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
} else {
setCanDrop(false);
updateCursor(Qt::IgnoreAction);
}
- setExecutedDropAction(Qt::IgnoreAction);
- qCDebug(lcDnd) << "drag began from" << m_current_window<< "cursor pos" << QCursor::pos() << "can drop?" << canDrop();
+
+ qCDebug(lcDnd) << "drag began from" << m_sourceWindow << "cursor pos" << QCursor::pos() << "can drop?" << canDrop();
+}
+
+static void sendDragLeave(QWindow *window)
+{
+ QWindowSystemInterface::handleDrag(window, nullptr, QPoint(), Qt::IgnoreAction, 0, 0);
}
void QSimpleDrag::cancel()
{
QBasicDrag::cancel();
- if (drag() && m_current_window) {
- QWindowSystemInterface::handleDrag(m_current_window, 0, QPoint(), Qt::IgnoreAction);
- m_current_window = 0;
+ if (drag() && m_sourceWindow) {
+ sendDragLeave(m_sourceWindow);
+ m_sourceWindow = nullptr;
}
}
-void QSimpleDrag::move(const QPoint &nativeGlobalPos)
+void QSimpleDrag::move(const QPoint &nativeGlobalPos, Qt::MouseButtons buttons,
+ Qt::KeyboardModifiers modifiers)
{
QPoint globalPos = fromNativeGlobalPixels(nativeGlobalPos);
moveShapedPixmapWindow(globalPos);
QWindow *window = topLevelAt(globalPos);
- if (!window)
- return;
+
+ if (!window || window != m_windowUnderCursor) {
+ if (m_windowUnderCursor)
+ sendDragLeave(m_windowUnderCursor);
+ m_windowUnderCursor = window;
+ if (!window) {
+ // QSimpleDrag supports only in-process dnd, we can't drop anywhere else.
+ setCanDrop(false);
+ updateCursor(Qt::IgnoreAction);
+ return;
+ }
+ }
const QPoint pos = nativeGlobalPos - window->handle()->geometry().topLeft();
- const QPlatformDragQtResponse qt_response =
- QWindowSystemInterface::handleDrag(window, drag()->mimeData(), pos, drag()->supportedActions());
+ const QPlatformDragQtResponse qt_response = QWindowSystemInterface::handleDrag(
+ window, drag()->mimeData(), pos, drag()->supportedActions(),
+ buttons, modifiers);
- updateCursor(qt_response.acceptedAction());
setCanDrop(qt_response.isAccepted());
+ updateCursor(qt_response.acceptedAction());
}
-void QSimpleDrag::drop(const QPoint &nativeGlobalPos)
+void QSimpleDrag::drop(const QPoint &nativeGlobalPos, Qt::MouseButtons buttons,
+ Qt::KeyboardModifiers modifiers)
{
QPoint globalPos = fromNativeGlobalPixels(nativeGlobalPos);
- QBasicDrag::drop(nativeGlobalPos);
+ QBasicDrag::drop(nativeGlobalPos, buttons, modifiers);
QWindow *window = topLevelAt(globalPos);
if (!window)
return;
const QPoint pos = nativeGlobalPos - window->handle()->geometry().topLeft();
- const QPlatformDropQtResponse response =
- QWindowSystemInterface::handleDrop(window, drag()->mimeData(),pos, drag()->supportedActions());
+ const QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(
+ window, drag()->mimeData(), pos, drag()->supportedActions(),
+ buttons, modifiers);
if (response.isAccepted()) {
setExecutedDropAction(response.acceptedAction());
} else {
diff --git a/src/gui/kernel/qsimpledrag_p.h b/src/gui/kernel/qsimpledrag_p.h
index d980a3c49d..f9e8a83a39 100644
--- a/src/gui/kernel/qsimpledrag_p.h
+++ b/src/gui/kernel/qsimpledrag_p.h
@@ -55,13 +55,14 @@
#include <qpa/qplatformdrag.h>
#include <QtCore/QObject>
+#include <QtCore/QPointer>
+#include <QtGui/QWindow>
QT_REQUIRE_CONFIG(draganddrop);
QT_BEGIN_NAMESPACE
class QMouseEvent;
-class QWindow;
class QEventLoop;
class QDropData;
class QShapedPixmapWindow;
@@ -82,8 +83,8 @@ protected:
virtual void startDrag();
virtual void cancel();
- virtual void move(const QPoint &globalPos) = 0;
- virtual void drop(const QPoint &globalPos) = 0;
+ virtual void move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) = 0;
+ virtual void drop(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) = 0;
virtual void endDrag();
@@ -106,7 +107,8 @@ protected:
QDrag *drag() const { return m_drag; }
protected:
- QWindow *m_current_window;
+ QWindow *m_sourceWindow = nullptr;
+ QPointer<QWindow> m_windowUnderCursor = nullptr;
private:
void enableEventFilter();
@@ -114,14 +116,16 @@ private:
void restoreCursor();
void exitDndEventLoop();
- bool m_restoreCursor;
- QEventLoop *m_eventLoop;
- Qt::DropAction m_executed_drop_action;
- bool m_can_drop;
- QDrag *m_drag;
- QShapedPixmapWindow *m_drag_icon_window;
- bool m_useCompositing;
- QScreen *m_screen;
+#ifndef QT_NO_CURSOR
+ bool m_dndHasSetOverrideCursor = false;
+#endif
+ QEventLoop *m_eventLoop = nullptr;
+ Qt::DropAction m_executed_drop_action = Qt::IgnoreAction;
+ bool m_can_drop = false;
+ QDrag *m_drag = nullptr;
+ QShapedPixmapWindow *m_drag_icon_window = nullptr;
+ bool m_useCompositing = true;
+ QScreen *m_screen = nullptr;
};
class Q_GUI_EXPORT QSimpleDrag : public QBasicDrag
@@ -132,8 +136,8 @@ public:
protected:
virtual void startDrag() override;
virtual void cancel() override;
- virtual void move(const QPoint &globalPos) override;
- virtual void drop(const QPoint &globalPos) override;
+ virtual void move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) override;
+ virtual void drop(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) override;
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qsurface.cpp b/src/gui/kernel/qsurface.cpp
index 63651ee822..415e64b39c 100644
--- a/src/gui/kernel/qsurface.cpp
+++ b/src/gui/kernel/qsurface.cpp
@@ -80,6 +80,10 @@ QT_BEGIN_NAMESPACE
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.
+ \value MetalSurface The surface is a Metal compatible surface and can be used
+ in conjunction with Apple's Metal graphics API. This surface type is supported
+ on macOS only.
+
*/
diff --git a/src/gui/kernel/qsurface.h b/src/gui/kernel/qsurface.h
index 7e09449d12..521593ea5c 100644
--- a/src/gui/kernel/qsurface.h
+++ b/src/gui/kernel/qsurface.h
@@ -55,19 +55,23 @@ class QSurfacePrivate;
class Q_GUI_EXPORT QSurface
{
+ Q_GADGET
public:
enum SurfaceClass {
Window,
Offscreen
};
+ Q_ENUM(SurfaceClass)
enum SurfaceType {
RasterSurface,
OpenGLSurface,
RasterGLSurface,
OpenVGSurface,
- VulkanSurface
+ VulkanSurface,
+ MetalSurface
};
+ Q_ENUM(SurfaceType)
virtual ~QSurface();
diff --git a/src/gui/kernel/qtestsupport_gui.cpp b/src/gui/kernel/qtestsupport_gui.cpp
new file mode 100644
index 0000000000..56e0eb52b3
--- /dev/null
+++ b/src/gui/kernel/qtestsupport_gui.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 "qtestsupport_gui.h"
+#include "qwindow.h"
+
+#include <QtCore/qtestsupport_core.h>
+
+QT_BEGIN_NAMESPACE
+
+/*! \fn bool qWaitForWindowActive(QWindow *window, int timeout)
+ \relates QTest
+ \since 5.0
+
+ Waits for \a timeout milliseconds or until the \a window is active.
+
+ Returns \c true if \c window is active within \a timeout milliseconds, otherwise returns \c false.
+
+ \sa QTest::qWaitForWindowExposed(), QWindow::isActive()
+*/
+Q_GUI_EXPORT bool QTest::qWaitForWindowActive(QWindow *window, int timeout)
+{
+ return QTest::qWaitFor([&]() { return window->isActive(); }, timeout);
+}
+
+/*! \fn bool qWaitForWindowExposed(QWindow *window, int timeout)
+ \relates QTest
+ \since 5.0
+
+ Waits for \a timeout milliseconds or until the \a window is exposed.
+ Returns \c true if \c window is exposed within \a timeout milliseconds, otherwise returns \c false.
+
+ This is mainly useful for asynchronous systems like X11, where a window will be mapped to screen some
+ time after being asked to show itself on the screen.
+
+ Note that a window that is mapped to screen may still not be considered exposed if the window client
+ area is completely covered by other windows, or if the window is otherwise not visible. This function
+ will then time out when waiting for such a window.
+
+ \sa QTest::qWaitForWindowActive(), QWindow::isExposed()
+*/
+Q_GUI_EXPORT bool QTest::qWaitForWindowExposed(QWindow *window, int timeout)
+{
+ return QTest::qWaitFor([&]() { return window->isExposed(); }, timeout);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qtestsupport_gui.h b/src/gui/kernel/qtestsupport_gui.h
new file mode 100644
index 0000000000..82a81e9214
--- /dev/null
+++ b/src/gui/kernel/qtestsupport_gui.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 QTESTSUPPORT_GUI_H
+#define QTESTSUPPORT_GUI_H
+
+#include <QtGui/qtguiglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWindow;
+
+namespace QTest {
+Q_GUI_EXPORT Q_REQUIRED_RESULT bool qWaitForWindowActive(QWindow *window, int timeout = 5000);
+Q_GUI_EXPORT Q_REQUIRED_RESULT bool qWaitForWindowExposed(QWindow *window, int timeout = 5000);
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index 55fe75d220..bc2d6e6a17 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -115,9 +115,10 @@ QT_BEGIN_NAMESPACE
physical area of the screen. On windowing systems that have exposure
notifications, the isExposed() accessor describes whether the window should
be treated as directly visible on screen. The exposeEvent() function is
- called whenever the windows exposure in the windowing system changes. On
- windowing systems that do not make this information visible to the
- application, isExposed() will simply return the same value as isVisible().
+ called whenever an area of the window is invalidated, for example due to the
+ exposure in the windowing system changing. On windowing systems that do not
+ make this information visible to the 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 windowStates().
@@ -545,6 +546,9 @@ void QWindowPrivate::create(bool recursive, WId nativeHandle)
QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceCreated);
QGuiApplication::sendEvent(q, &e);
+
+ if (updateRequestPending)
+ platformWindow->requestUpdate();
}
void QWindowPrivate::clearFocusObject()
@@ -2150,15 +2154,13 @@ bool QWindow::close()
if (!d->platformWindow)
return true;
- bool accepted = false;
- QWindowSystemInterface::handleCloseEvent(this, &accepted);
- QWindowSystemInterface::flushWindowSystemEvents();
- return accepted;
+ return d->platformWindow->close();
}
/*!
- The expose event (\a ev) is sent by the window system whenever the window's
- exposure on screen changes.
+ The expose event (\a ev) is sent by the window system whenever an area of
+ the window is invalidated, for example due to the exposure in the windowing
+ system changing.
The application can start rendering into the window with QBackingStore
and QOpenGLContext as soon as it gets an exposeEvent() such that
@@ -2335,18 +2337,6 @@ bool QWindow::event(QEvent *ev)
break;
#endif
- case QEvent::Timer: {
- Q_D(QWindow);
- if (static_cast<QTimerEvent *>(ev)->timerId() == d->updateTimer) {
- killTimer(d->updateTimer);
- d->updateTimer = 0;
- d->deliverUpdateRequest();
- } else {
- QObject::event(ev);
- }
- break;
- }
-
case QEvent::PlatformSurface: {
if ((static_cast<QPlatformSurfaceEvent *>(ev))->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed) {
#ifndef QT_NO_OPENGL
@@ -2364,14 +2354,6 @@ bool QWindow::event(QEvent *ev)
return true;
}
-void QWindowPrivate::deliverUpdateRequest()
-{
- Q_Q(QWindow);
- updateRequestPending = false;
- QEvent request(QEvent::UpdateRequest);
- QCoreApplication::sendEvent(q, &request);
-}
-
/*!
Schedules a QEvent::UpdateRequest event to be delivered to this window.
@@ -2626,14 +2608,14 @@ void QWindowPrivate::maybeQuitOnLastWindowClosed()
}
}
-QWindow *QWindowPrivate::topLevelWindow() const
+QWindow *QWindowPrivate::topLevelWindow(QWindow::AncestorMode mode) const
{
Q_Q(const QWindow);
QWindow *window = const_cast<QWindow *>(q);
while (window) {
- QWindow *parent = window->parent(QWindow::IncludeTransients);
+ QWindow *parent = window->parent(mode);
if (!parent)
break;
diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h
index 7ef73eb410..bf5e645114 100644
--- a/src/gui/kernel/qwindow_p.h
+++ b/src/gui/kernel/qwindow_p.h
@@ -97,7 +97,6 @@ public:
, modality(Qt::NonModal)
, blockedByModalWindow(false)
, updateRequestPending(false)
- , updateTimer(0)
, transientParent(0)
, topLevelScreen(0)
#ifndef QT_NO_CURSOR
@@ -124,11 +123,9 @@ public:
bool applyCursor();
#endif
- void deliverUpdateRequest();
-
QPoint globalPosition() const;
- QWindow *topLevelWindow() const;
+ QWindow *topLevelWindow(QWindow::AncestorMode mode = QWindow::IncludeTransients) const;
#if QT_CONFIG(opengl)
virtual QOpenGLContext *shareContext() const;
@@ -194,7 +191,6 @@ public:
bool blockedByModalWindow;
bool updateRequestPending;
- int updateTimer;
QPointer<QWindow> transientParent;
QPointer<QScreen> topLevelScreen;
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index 6edcdfc255..67e1283462 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -57,6 +57,7 @@ QT_BEGIN_NAMESPACE
QElapsedTimer QWindowSystemInterfacePrivate::eventTime;
bool QWindowSystemInterfacePrivate::synchronousWindowSystemEvents = false;
+bool QWindowSystemInterfacePrivate::platformFiltersEvents = false;
bool QWindowSystemInterfacePrivate::TabletEvent::platformSynthesizesMouse = true;
QWaitCondition QWindowSystemInterfacePrivate::eventsFlushed;
QMutex QWindowSystemInterfacePrivate::flushEventMutex;
@@ -339,12 +340,12 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleExposeEvent, QWindow *window, const QReg
QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
-void QWindowSystemInterface::handleCloseEvent(QWindow *window, bool *accepted)
+QT_DEFINE_QPA_EVENT_HANDLER(void, handleCloseEvent, QWindow *window, bool *accepted)
{
if (window) {
QWindowSystemInterfacePrivate::CloseEvent *e =
new QWindowSystemInterfacePrivate::CloseEvent(window, accepted);
- QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
}
@@ -795,14 +796,44 @@ void QWindowSystemInterface::handleThemeChange(QWindow *window)
}
#if QT_CONFIG(draganddrop)
-QPlatformDragQtResponse QWindowSystemInterface::handleDrag(QWindow *window, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions)
+#if QT_DEPRECATED_SINCE(5, 11)
+QPlatformDragQtResponse QWindowSystemInterface::handleDrag(QWindow *window, const QMimeData *dropData,
+ const QPoint &p, Qt::DropActions supportedActions)
+{
+ return QGuiApplicationPrivate::processDrag(window, dropData, p, supportedActions,
+ QGuiApplication::mouseButtons(),
+ QGuiApplication::keyboardModifiers());
+}
+
+QPlatformDropQtResponse QWindowSystemInterface::handleDrop(QWindow *window, const QMimeData *dropData,
+ const QPoint &p, Qt::DropActions supportedActions)
+{
+ return QGuiApplicationPrivate::processDrop(window, dropData, p, supportedActions,
+ QGuiApplication::mouseButtons(),
+ QGuiApplication::keyboardModifiers());
+}
+#endif // QT_DEPRECATED_SINCE(5, 11)
+/*!
+ Drag and drop events are sent immediately.
+
+ ### FIXME? Perhaps DnD API should add some convenience APIs that are more
+ intuitive for the possible DND operations. Here passing nullptr as drop data is used to
+ indicate that drop was canceled and QDragLeaveEvent should be sent as a result.
+*/
+QPlatformDragQtResponse QWindowSystemInterface::handleDrag(QWindow *window, const QMimeData *dropData,
+ const QPoint &p, Qt::DropActions supportedActions,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
{
- return QGuiApplicationPrivate::processDrag(window, dropData, QHighDpi::fromNativeLocalPosition(p, window) ,supportedActions);
+ auto pos = QHighDpi::fromNativeLocalPosition(p, window);
+ return QGuiApplicationPrivate::processDrag(window, dropData, pos, supportedActions, buttons, modifiers);
}
-QPlatformDropQtResponse QWindowSystemInterface::handleDrop(QWindow *window, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions)
+QPlatformDropQtResponse QWindowSystemInterface::handleDrop(QWindow *window, const QMimeData *dropData,
+ const QPoint &p, Qt::DropActions supportedActions,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
{
- return QGuiApplicationPrivate::processDrop(window, dropData, QHighDpi::fromNativeLocalPosition(p, window),supportedActions);
+ auto pos = QHighDpi::fromNativeLocalPosition(p, window);
+ return QGuiApplicationPrivate::processDrop(window, dropData, pos, supportedActions, buttons, modifiers);
}
#endif // QT_CONFIG(draganddrop)
@@ -1017,10 +1048,15 @@ bool QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::ProcessEventsFla
int nevents = 0;
while (QWindowSystemInterfacePrivate::windowSystemEventsQueued()) {
- QWindowSystemInterfacePrivate::WindowSystemEvent *event =
- (flags & QEventLoop::ExcludeUserInputEvents) ?
- QWindowSystemInterfacePrivate::getNonUserInputWindowSystemEvent() :
- QWindowSystemInterfacePrivate::getWindowSystemEvent();
+ QWindowSystemInterfacePrivate::WindowSystemEvent *event = nullptr;
+
+ if (QWindowSystemInterfacePrivate::platformFiltersEvents) {
+ event = QWindowSystemInterfacePrivate::getWindowSystemEvent();
+ } else {
+ event = flags & QEventLoop::ExcludeUserInputEvents ?
+ QWindowSystemInterfacePrivate::getNonUserInputWindowSystemEvent() :
+ QWindowSystemInterfacePrivate::getWindowSystemEvent();
+ }
if (!event)
break;
@@ -1059,6 +1095,21 @@ bool QWindowSystemInterface::nonUserInputEventsQueued()
return QWindowSystemInterfacePrivate::nonUserInputEventsQueued();
}
+/*!
+ Platforms that implement UserInputEvent filtering at native event level must
+ set this property to \c true. The default is \c false, which means that event
+ filtering logic is handled by QWindowSystemInterface. Doing the filtering in
+ platform plugins is necessary when supporting AbstractEventDispatcher::filterNativeEvent(),
+ which should respect flags that were passed to event dispatcher's processEvents()
+ call.
+
+ \since 5.12
+*/
+void QWindowSystemInterface::setPlatformFiltersEvents(bool enable)
+{
+ QWindowSystemInterfacePrivate::platformFiltersEvents = enable;
+}
+
// --------------------- QtTestLib support ---------------------
// The following functions are used by testlib, and need to be synchronous to avoid
diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h
index bba0b05c5a..1dde9130ac 100644
--- a/src/gui/kernel/qwindowsysteminterface.h
+++ b/src/gui/kernel/qwindowsysteminterface.h
@@ -193,6 +193,7 @@ public:
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
static void handleExposeEvent(QWindow *window, const QRegion &region);
+ template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
static void handleCloseEvent(QWindow *window, bool *accepted = nullptr);
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
@@ -215,10 +216,19 @@ public:
static void handleApplicationStateChanged(Qt::ApplicationState newState, bool forcePropagate = false);
#if QT_CONFIG(draganddrop)
- // Drag and drop. These events are sent immediately.
- static QPlatformDragQtResponse handleDrag(QWindow *window, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions);
- static QPlatformDropQtResponse handleDrop(QWindow *window, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions);
-#endif
+#if QT_DEPRECATED_SINCE(5, 11)
+ QT_DEPRECATED static QPlatformDragQtResponse handleDrag(QWindow *window, const QMimeData *dropData,
+ const QPoint &p, Qt::DropActions supportedActions);
+ QT_DEPRECATED static QPlatformDropQtResponse handleDrop(QWindow *window, const QMimeData *dropData,
+ const QPoint &p, Qt::DropActions supportedActions);
+#endif // #if QT_DEPRECATED_SINCE(5, 11)
+ static QPlatformDragQtResponse handleDrag(QWindow *window, const QMimeData *dropData,
+ const QPoint &p, Qt::DropActions supportedActions,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers);
+ static QPlatformDropQtResponse handleDrop(QWindow *window, const QMimeData *dropData,
+ const QPoint &p, Qt::DropActions supportedActions,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers);
+#endif // QT_CONFIG(draganddrop)
static bool handleNativeEvent(QWindow *window, const QByteArray &eventType, void *message, long *result);
@@ -282,6 +292,7 @@ public:
static void deferredFlushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags);
static int windowSystemEventsQueued();
static bool nonUserInputEventsQueued();
+ static void setPlatformFiltersEvents(bool enable);
};
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h
index c3fb19d21a..9cb4e191cc 100644
--- a/src/gui/kernel/qwindowsysteminterface_p.h
+++ b/src/gui/kernel/qwindowsysteminterface_p.h
@@ -365,7 +365,7 @@ public:
QUrl url;
};
- class TabletEvent : public InputEvent {
+ class Q_GUI_EXPORT TabletEvent : public InputEvent {
public:
static void handleTabletEvent(QWindow *w, const QPointF &local, const QPointF &global,
int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt,
@@ -525,6 +525,7 @@ public:
public:
static QElapsedTimer eventTime;
static bool synchronousWindowSystemEvents;
+ static bool platformFiltersEvents;
static QWaitCondition eventsFlushed;
static QMutex flushEventMutex;
diff --git a/src/gui/math3d/qquaternion.cpp b/src/gui/math3d/qquaternion.cpp
index fe1b0425a8..899ec12eb3 100644
--- a/src/gui/math3d/qquaternion.cpp
+++ b/src/gui/math3d/qquaternion.cpp
@@ -325,15 +325,11 @@ void QQuaternion::normalize()
Rotates \a vector with this quaternion to produce a new vector
in 3D space. The following code:
- \code
- QVector3D result = q.rotatedVector(vector);
- \endcode
+ \snippet code/src_gui_math3d_qquaternion.cpp 0
is equivalent to the following:
- \code
- QVector3D result = (q * QQuaternion(0, vector) * q.conjugated()).vector();
- \endcode
+ \snippet code/src_gui_math3d_qquaternion.cpp 1
*/
QVector3D QQuaternion::rotatedVector(const QVector3D& vector) const
{
diff --git a/src/gui/math3d/qvector2d.cpp b/src/gui/math3d/qvector2d.cpp
index 7c02b5ad5d..c04f8b1cbf 100644
--- a/src/gui/math3d/qvector2d.cpp
+++ b/src/gui/math3d/qvector2d.cpp
@@ -49,6 +49,39 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_VECTOR2D
+Q_STATIC_ASSERT_X(std::is_standard_layout<QVector2D>::value, "QVector2D is supposed to be standard layout");
+Q_STATIC_ASSERT_X(sizeof(QVector2D) == sizeof(float) * 2, "QVector2D is not supposed to have padding at the end");
+
+// QVector2D used to be defined as class QVector2D { float x, y; };,
+// now instead it is defined as classs QVector2D { float v[2]; };.
+// Check that binary compatibility is preserved.
+// ### Qt 6: remove all of these checks.
+
+namespace {
+
+struct QVector2DOld
+{
+ float x, y;
+};
+
+struct QVector2DNew
+{
+ float v[2];
+};
+
+Q_STATIC_ASSERT_X(std::is_standard_layout<QVector2DOld>::value, "Binary compatibility break in QVector2D");
+Q_STATIC_ASSERT_X(std::is_standard_layout<QVector2DNew>::value, "Binary compatibility break in QVector2D");
+
+Q_STATIC_ASSERT_X(sizeof(QVector2DOld) == sizeof(QVector2DNew), "Binary compatibility break in QVector2D");
+
+// requires a constexpr offsetof
+#if !defined(Q_CC_MSVC) || (_MSC_VER >= 1910)
+Q_STATIC_ASSERT_X(offsetof(QVector2DOld, x) == offsetof(QVector2DNew, v) + sizeof(QVector2DNew::v[0]) * 0, "Binary compatibility break in QVector2D");
+Q_STATIC_ASSERT_X(offsetof(QVector2DOld, y) == offsetof(QVector2DNew, v) + sizeof(QVector2DNew::v[0]) * 1, "Binary compatibility break in QVector2D");
+#endif
+
+} // anonymous namespace
+
/*!
\class QVector2D
\brief The QVector2D class represents a vector or vertex in 2D space.
@@ -105,8 +138,8 @@ QT_BEGIN_NAMESPACE
*/
QVector2D::QVector2D(const QVector3D& vector)
{
- xp = vector.xp;
- yp = vector.yp;
+ v[0] = vector.v[0];
+ v[1] = vector.v[1];
}
#endif
@@ -121,8 +154,8 @@ QVector2D::QVector2D(const QVector3D& vector)
*/
QVector2D::QVector2D(const QVector4D& vector)
{
- xp = vector.xp;
- yp = vector.yp;
+ v[0] = vector.v[0];
+ v[1] = vector.v[1];
}
#endif
@@ -193,8 +226,8 @@ QVector2D::QVector2D(const QVector4D& vector)
float QVector2D::length() const
{
// Need some extra precision if the length is very small.
- double len = double(xp) * double(xp) +
- double(yp) * double(yp);
+ double len = double(v[0]) * double(v[0]) +
+ double(v[1]) * double(v[1]);
return float(std::sqrt(len));
}
@@ -206,7 +239,7 @@ float QVector2D::length() const
*/
float QVector2D::lengthSquared() const
{
- return xp * xp + yp * yp;
+ return v[0] * v[0] + v[1] * v[1];
}
/*!
@@ -221,13 +254,13 @@ float QVector2D::lengthSquared() const
QVector2D QVector2D::normalized() const
{
// Need some extra precision if the length is very small.
- double len = double(xp) * double(xp) +
- double(yp) * double(yp);
+ double len = double(v[0]) * double(v[0]) +
+ double(v[1]) * double(v[1]);
if (qFuzzyIsNull(len - 1.0f)) {
return *this;
} else if (!qFuzzyIsNull(len)) {
double sqrtLen = std::sqrt(len);
- return QVector2D(float(double(xp) / sqrtLen), float(double(yp) / sqrtLen));
+ return QVector2D(float(double(v[0]) / sqrtLen), float(double(v[1]) / sqrtLen));
} else {
return QVector2D();
}
@@ -242,15 +275,15 @@ QVector2D QVector2D::normalized() const
void QVector2D::normalize()
{
// Need some extra precision if the length is very small.
- double len = double(xp) * double(xp) +
- double(yp) * double(yp);
+ double len = double(v[0]) * double(v[0]) +
+ double(v[1]) * double(v[1]);
if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len))
return;
len = std::sqrt(len);
- xp = float(double(xp) / len);
- yp = float(double(yp) / len);
+ v[0] = float(double(v[0]) / len);
+ v[1] = float(double(v[1]) / len);
}
/*!
@@ -344,7 +377,7 @@ float QVector2D::distanceToLine
*/
float QVector2D::dotProduct(const QVector2D& v1, const QVector2D& v2)
{
- return v1.xp * v2.xp + v1.yp * v2.yp;
+ return v1.v[0] * v2.v[0] + v1.v[1] * v2.v[1];
}
/*!
@@ -458,7 +491,7 @@ float QVector2D::dotProduct(const QVector2D& v1, const QVector2D& v2)
*/
QVector3D QVector2D::toVector3D() const
{
- return QVector3D(xp, yp, 0.0f);
+ return QVector3D(v[0], v[1], 0.0f);
}
#endif
@@ -472,7 +505,7 @@ QVector3D QVector2D::toVector3D() const
*/
QVector4D QVector2D::toVector4D() const
{
- return QVector4D(xp, yp, 0.0f, 0.0f);
+ return QVector4D(v[0], v[1], 0.0f, 0.0f);
}
#endif
diff --git a/src/gui/math3d/qvector2d.h b/src/gui/math3d/qvector2d.h
index 2af5132665..88d8bc199e 100644
--- a/src/gui/math3d/qvector2d.h
+++ b/src/gui/math3d/qvector2d.h
@@ -123,7 +123,7 @@ public:
operator QVariant() const;
private:
- float xp, yp;
+ float v[2];
friend class QVector3D;
friend class QVector4D;
@@ -131,76 +131,76 @@ private:
Q_DECLARE_TYPEINFO(QVector2D, Q_PRIMITIVE_TYPE);
-Q_DECL_CONSTEXPR inline QVector2D::QVector2D() : xp(0.0f), yp(0.0f) {}
+Q_DECL_CONSTEXPR inline QVector2D::QVector2D() : v{0.0f, 0.0f} {}
-Q_DECL_CONSTEXPR inline QVector2D::QVector2D(float xpos, float ypos) : xp(xpos), yp(ypos) {}
+Q_DECL_CONSTEXPR inline QVector2D::QVector2D(float xpos, float ypos) : v{xpos, ypos} {}
-Q_DECL_CONSTEXPR inline QVector2D::QVector2D(const QPoint& point) : xp(point.x()), yp(point.y()) {}
+Q_DECL_CONSTEXPR inline QVector2D::QVector2D(const QPoint& point) : v{float(point.x()), float(point.y())} {}
-Q_DECL_CONSTEXPR inline QVector2D::QVector2D(const QPointF& point) : xp(float(point.x())), yp(float(point.y())) {}
+Q_DECL_CONSTEXPR inline QVector2D::QVector2D(const QPointF& point) : v{float(point.x()), float(point.y())} {}
inline bool QVector2D::isNull() const
{
- return qIsNull(xp) && qIsNull(yp);
+ return qIsNull(v[0]) && qIsNull(v[1]);
}
-Q_DECL_CONSTEXPR inline float QVector2D::x() const { return xp; }
-Q_DECL_CONSTEXPR inline float QVector2D::y() const { return yp; }
+Q_DECL_CONSTEXPR inline float QVector2D::x() const { return v[0]; }
+Q_DECL_CONSTEXPR inline float QVector2D::y() const { return v[1]; }
-inline void QVector2D::setX(float aX) { xp = aX; }
-inline void QVector2D::setY(float aY) { yp = aY; }
+inline void QVector2D::setX(float aX) { v[0] = aX; }
+inline void QVector2D::setY(float aY) { v[1] = aY; }
inline float &QVector2D::operator[](int i)
{
Q_ASSERT(uint(i) < 2u);
- return *(&xp + i);
+ return v[i];
}
inline float QVector2D::operator[](int i) const
{
Q_ASSERT(uint(i) < 2u);
- return *(&xp + i);
+ return v[i];
}
inline QVector2D &QVector2D::operator+=(const QVector2D &vector)
{
- xp += vector.xp;
- yp += vector.yp;
+ v[0] += vector.v[0];
+ v[1] += vector.v[1];
return *this;
}
inline QVector2D &QVector2D::operator-=(const QVector2D &vector)
{
- xp -= vector.xp;
- yp -= vector.yp;
+ v[0] -= vector.v[0];
+ v[1] -= vector.v[1];
return *this;
}
inline QVector2D &QVector2D::operator*=(float factor)
{
- xp *= factor;
- yp *= factor;
+ v[0] *= factor;
+ v[1] *= factor;
return *this;
}
inline QVector2D &QVector2D::operator*=(const QVector2D &vector)
{
- xp *= vector.xp;
- yp *= vector.yp;
+ v[0] *= vector.v[0];
+ v[1] *= vector.v[1];
return *this;
}
inline QVector2D &QVector2D::operator/=(float divisor)
{
- xp /= divisor;
- yp /= divisor;
+ v[0] /= divisor;
+ v[1] /= divisor;
return *this;
}
inline QVector2D &QVector2D::operator/=(const QVector2D &vector)
{
- xp /= vector.xp;
- yp /= vector.yp;
+ v[0] /= vector.v[0];
+ v[1] /= vector.v[1];
return *this;
}
@@ -209,68 +209,68 @@ QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
QT_WARNING_DISABLE_GCC("-Wfloat-equal")
Q_DECL_CONSTEXPR inline bool operator==(const QVector2D &v1, const QVector2D &v2)
{
- return v1.xp == v2.xp && v1.yp == v2.yp;
+ return v1.v[0] == v2.v[0] && v1.v[1] == v2.v[1];
}
Q_DECL_CONSTEXPR inline bool operator!=(const QVector2D &v1, const QVector2D &v2)
{
- return v1.xp != v2.xp || v1.yp != v2.yp;
+ return v1.v[0] != v2.v[0] || v1.v[1] != v2.v[1];
}
QT_WARNING_POP
Q_DECL_CONSTEXPR inline const QVector2D operator+(const QVector2D &v1, const QVector2D &v2)
{
- return QVector2D(v1.xp + v2.xp, v1.yp + v2.yp);
+ return QVector2D(v1.v[0] + v2.v[0], v1.v[1] + v2.v[1]);
}
Q_DECL_CONSTEXPR inline const QVector2D operator-(const QVector2D &v1, const QVector2D &v2)
{
- return QVector2D(v1.xp - v2.xp, v1.yp - v2.yp);
+ return QVector2D(v1.v[0] - v2.v[0], v1.v[1] - v2.v[1]);
}
Q_DECL_CONSTEXPR inline const QVector2D operator*(float factor, const QVector2D &vector)
{
- return QVector2D(vector.xp * factor, vector.yp * factor);
+ return QVector2D(vector.v[0] * factor, vector.v[1] * factor);
}
Q_DECL_CONSTEXPR inline const QVector2D operator*(const QVector2D &vector, float factor)
{
- return QVector2D(vector.xp * factor, vector.yp * factor);
+ return QVector2D(vector.v[0] * factor, vector.v[1] * factor);
}
Q_DECL_CONSTEXPR inline const QVector2D operator*(const QVector2D &v1, const QVector2D &v2)
{
- return QVector2D(v1.xp * v2.xp, v1.yp * v2.yp);
+ return QVector2D(v1.v[0] * v2.v[0], v1.v[1] * v2.v[1]);
}
Q_DECL_CONSTEXPR inline const QVector2D operator-(const QVector2D &vector)
{
- return QVector2D(-vector.xp, -vector.yp);
+ return QVector2D(-vector.v[0], -vector.v[1]);
}
Q_DECL_CONSTEXPR inline const QVector2D operator/(const QVector2D &vector, float divisor)
{
- return QVector2D(vector.xp / divisor, vector.yp / divisor);
+ return QVector2D(vector.v[0] / divisor, vector.v[1] / divisor);
}
Q_DECL_CONSTEXPR inline const QVector2D operator/(const QVector2D &vector, const QVector2D &divisor)
{
- return QVector2D(vector.xp / divisor.xp, vector.yp / divisor.yp);
+ return QVector2D(vector.v[0] / divisor.v[0], vector.v[1] / divisor.v[1]);
}
Q_DECL_CONSTEXPR inline bool qFuzzyCompare(const QVector2D& v1, const QVector2D& v2)
{
- return qFuzzyCompare(v1.xp, v2.xp) && qFuzzyCompare(v1.yp, v2.yp);
+ return qFuzzyCompare(v1.v[0], v2.v[0]) && qFuzzyCompare(v1.v[1], v2.v[1]);
}
Q_DECL_CONSTEXPR inline QPoint QVector2D::toPoint() const
{
- return QPoint(qRound(xp), qRound(yp));
+ return QPoint(qRound(v[0]), qRound(v[1]));
}
Q_DECL_CONSTEXPR inline QPointF QVector2D::toPointF() const
{
- return QPointF(qreal(xp), qreal(yp));
+ return QPointF(qreal(v[0]), qreal(v[1]));
}
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/gui/math3d/qvector3d.cpp b/src/gui/math3d/qvector3d.cpp
index 8aaf1b0eaa..12a7902272 100644
--- a/src/gui/math3d/qvector3d.cpp
+++ b/src/gui/math3d/qvector3d.cpp
@@ -51,6 +51,41 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_VECTOR3D
+Q_STATIC_ASSERT_X(std::is_standard_layout<QVector3D>::value, "QVector3D is supposed to be standard layout");
+Q_STATIC_ASSERT_X(sizeof(QVector3D) == sizeof(float) * 3, "QVector3D is not supposed to have padding at the end");
+
+// QVector3D used to be defined as class QVector3D { float x, y, z; };,
+// now instead it is defined as classs QVector3D { float v[3]; };.
+// Check that binary compatibility is preserved.
+// ### Qt 6: remove all of these checks.
+
+namespace {
+
+struct QVector3DOld
+{
+ float x, y, z;
+};
+
+struct QVector3DNew
+{
+ float v[3];
+};
+
+Q_STATIC_ASSERT_X(std::is_standard_layout<QVector3DOld>::value, "Binary compatibility break in QVector3D");
+Q_STATIC_ASSERT_X(std::is_standard_layout<QVector3DNew>::value, "Binary compatibility break in QVector3D");
+
+Q_STATIC_ASSERT_X(sizeof(QVector3DOld) == sizeof(QVector3DNew), "Binary compatibility break in QVector3D");
+
+// requires a constexpr offsetof
+#if !defined(Q_CC_MSVC) || (_MSC_VER >= 1910)
+Q_STATIC_ASSERT_X(offsetof(QVector3DOld, x) == offsetof(QVector3DNew, v) + sizeof(QVector3DNew::v[0]) * 0, "Binary compatibility break in QVector3D");
+Q_STATIC_ASSERT_X(offsetof(QVector3DOld, y) == offsetof(QVector3DNew, v) + sizeof(QVector3DNew::v[0]) * 1, "Binary compatibility break in QVector3D");
+Q_STATIC_ASSERT_X(offsetof(QVector3DOld, z) == offsetof(QVector3DNew, v) + sizeof(QVector3DNew::v[0]) * 2, "Binary compatibility break in QVector3D");
+#endif
+
+
+} // anonymous namespace
+
/*!
\class QVector3D
\brief The QVector3D class represents a vector or vertex in 3D space.
@@ -112,9 +147,9 @@ QT_BEGIN_NAMESPACE
*/
QVector3D::QVector3D(const QVector2D& vector)
{
- xp = vector.xp;
- yp = vector.yp;
- zp = 0.0f;
+ v[0] = vector.v[0];
+ v[1] = vector.v[1];
+ v[2] = 0.0f;
}
/*!
@@ -125,9 +160,9 @@ QVector3D::QVector3D(const QVector2D& vector)
*/
QVector3D::QVector3D(const QVector2D& vector, float zpos)
{
- xp = vector.xp;
- yp = vector.yp;
- zp = zpos;
+ v[0] = vector.v[0];
+ v[1] = vector.v[1];
+ v[2] = zpos;
}
#endif
@@ -142,9 +177,9 @@ QVector3D::QVector3D(const QVector2D& vector, float zpos)
*/
QVector3D::QVector3D(const QVector4D& vector)
{
- xp = vector.xp;
- yp = vector.yp;
- zp = vector.zp;
+ v[0] = vector.v[0];
+ v[1] = vector.v[1];
+ v[2] = vector.v[2];
}
#endif
@@ -235,16 +270,16 @@ QVector3D::QVector3D(const QVector4D& vector)
QVector3D QVector3D::normalized() const
{
// Need some extra precision if the length is very small.
- double len = double(xp) * double(xp) +
- double(yp) * double(yp) +
- double(zp) * double(zp);
+ double len = double(v[0]) * double(v[0]) +
+ double(v[1]) * double(v[1]) +
+ double(v[2]) * double(v[2]);
if (qFuzzyIsNull(len - 1.0f)) {
return *this;
} else if (!qFuzzyIsNull(len)) {
double sqrtLen = std::sqrt(len);
- return QVector3D(float(double(xp) / sqrtLen),
- float(double(yp) / sqrtLen),
- float(double(zp) / sqrtLen));
+ return QVector3D(float(double(v[0]) / sqrtLen),
+ float(double(v[1]) / sqrtLen),
+ float(double(v[2]) / sqrtLen));
} else {
return QVector3D();
}
@@ -259,17 +294,17 @@ QVector3D QVector3D::normalized() const
void QVector3D::normalize()
{
// Need some extra precision if the length is very small.
- double len = double(xp) * double(xp) +
- double(yp) * double(yp) +
- double(zp) * double(zp);
+ double len = double(v[0]) * double(v[0]) +
+ double(v[1]) * double(v[1]) +
+ double(v[2]) * double(v[2]);
if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len))
return;
len = std::sqrt(len);
- xp = float(double(xp) / len);
- yp = float(double(yp) / len);
- zp = float(double(zp) / len);
+ v[0] = float(double(v[0]) / len);
+ v[1] = float(double(v[1]) / len);
+ v[2] = float(double(v[2]) / len);
}
/*!
@@ -336,7 +371,7 @@ void QVector3D::normalize()
*/
float QVector3D::dotProduct(const QVector3D& v1, const QVector3D& v2)
{
- return v1.xp * v2.xp + v1.yp * v2.yp + v1.zp * v2.zp;
+ return v1.v[0] * v2.v[0] + v1.v[1] * v2.v[1] + v1.v[2] * v2.v[2];
}
/*!
@@ -347,9 +382,9 @@ float QVector3D::dotProduct(const QVector3D& v1, const QVector3D& v2)
*/
QVector3D QVector3D::crossProduct(const QVector3D& v1, const QVector3D& v2)
{
- return QVector3D(v1.yp * v2.zp - v1.zp * v2.yp,
- v1.zp * v2.xp - v1.xp * v2.zp,
- v1.xp * v2.yp - v1.yp * v2.xp);
+ return QVector3D(v1.v[1] * v2.v[2] - v1.v[2] * v2.v[1],
+ v1.v[2] * v2.v[0] - v1.v[0] * v2.v[2],
+ v1.v[0] * v2.v[1] - v1.v[1] * v2.v[0]);
}
/*!
@@ -629,7 +664,7 @@ float QVector3D::distanceToLine
*/
QVector2D QVector3D::toVector2D() const
{
- return QVector2D(xp, yp);
+ return QVector2D(v[0], v[1]);
}
#endif
@@ -643,7 +678,7 @@ QVector2D QVector3D::toVector2D() const
*/
QVector4D QVector3D::toVector4D() const
{
- return QVector4D(xp, yp, zp, 0.0f);
+ return QVector4D(v[0], v[1], v[2], 0.0f);
}
#endif
@@ -682,9 +717,9 @@ QVector3D::operator QVariant() const
float QVector3D::length() const
{
// Need some extra precision if the length is very small.
- double len = double(xp) * double(xp) +
- double(yp) * double(yp) +
- double(zp) * double(zp);
+ double len = double(v[0]) * double(v[0]) +
+ double(v[1]) * double(v[1]) +
+ double(v[2]) * double(v[2]);
return float(std::sqrt(len));
}
@@ -696,7 +731,7 @@ float QVector3D::length() const
*/
float QVector3D::lengthSquared() const
{
- return xp * xp + yp * yp + zp * zp;
+ return v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
}
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/gui/math3d/qvector3d.h b/src/gui/math3d/qvector3d.h
index f3e8c976b7..1b49f3e7b9 100644
--- a/src/gui/math3d/qvector3d.h
+++ b/src/gui/math3d/qvector3d.h
@@ -59,7 +59,7 @@ class Q_GUI_EXPORT QVector3D
public:
Q_DECL_CONSTEXPR QVector3D();
explicit QVector3D(Qt::Initialization) {}
- Q_DECL_CONSTEXPR QVector3D(float xpos, float ypos, float zpos) : xp(xpos), yp(ypos), zp(zpos) {}
+ Q_DECL_CONSTEXPR QVector3D(float xpos, float ypos, float zpos) : v{xpos, ypos, zpos} {}
Q_DECL_CONSTEXPR explicit QVector3D(const QPoint& point);
Q_DECL_CONSTEXPR explicit QVector3D(const QPointF& point);
@@ -138,7 +138,7 @@ public:
operator QVariant() const;
private:
- float xp, yp, zp;
+ float v[3];
friend class QVector2D;
friend class QVector4D;
@@ -150,82 +150,82 @@ private:
Q_DECLARE_TYPEINFO(QVector3D, Q_PRIMITIVE_TYPE);
-Q_DECL_CONSTEXPR inline QVector3D::QVector3D() : xp(0.0f), yp(0.0f), zp(0.0f) {}
+Q_DECL_CONSTEXPR inline QVector3D::QVector3D() : v{0.0f, 0.0f, 0.0f} {}
-Q_DECL_CONSTEXPR inline QVector3D::QVector3D(const QPoint& point) : xp(point.x()), yp(point.y()), zp(0.0f) {}
+Q_DECL_CONSTEXPR inline QVector3D::QVector3D(const QPoint& point) : v{float(point.x()), float(point.y()), float(0.0f)} {}
-Q_DECL_CONSTEXPR inline QVector3D::QVector3D(const QPointF& point) : xp(float(point.x())), yp(float(point.y())), zp(0.0f) {}
+Q_DECL_CONSTEXPR inline QVector3D::QVector3D(const QPointF& point) : v{float(point.x()), float(point.y()), 0.0f} {}
inline bool QVector3D::isNull() const
{
- return qIsNull(xp) && qIsNull(yp) && qIsNull(zp);
+ return qIsNull(v[0]) && qIsNull(v[1]) && qIsNull(v[2]);
}
-Q_DECL_CONSTEXPR inline float QVector3D::x() const { return xp; }
-Q_DECL_CONSTEXPR inline float QVector3D::y() const { return yp; }
-Q_DECL_CONSTEXPR inline float QVector3D::z() const { return zp; }
+Q_DECL_CONSTEXPR inline float QVector3D::x() const { return v[0]; }
+Q_DECL_CONSTEXPR inline float QVector3D::y() const { return v[1]; }
+Q_DECL_CONSTEXPR inline float QVector3D::z() const { return v[2]; }
-inline void QVector3D::setX(float aX) { xp = aX; }
-inline void QVector3D::setY(float aY) { yp = aY; }
-inline void QVector3D::setZ(float aZ) { zp = aZ; }
+inline void QVector3D::setX(float aX) { v[0] = aX; }
+inline void QVector3D::setY(float aY) { v[1] = aY; }
+inline void QVector3D::setZ(float aZ) { v[2] = aZ; }
inline float &QVector3D::operator[](int i)
{
Q_ASSERT(uint(i) < 3u);
- return *(&xp + i);
+ return v[i];
}
inline float QVector3D::operator[](int i) const
{
Q_ASSERT(uint(i) < 3u);
- return *(&xp + i);
+ return v[i];
}
inline QVector3D &QVector3D::operator+=(const QVector3D &vector)
{
- xp += vector.xp;
- yp += vector.yp;
- zp += vector.zp;
+ v[0] += vector.v[0];
+ v[1] += vector.v[1];
+ v[2] += vector.v[2];
return *this;
}
inline QVector3D &QVector3D::operator-=(const QVector3D &vector)
{
- xp -= vector.xp;
- yp -= vector.yp;
- zp -= vector.zp;
+ v[0] -= vector.v[0];
+ v[1] -= vector.v[1];
+ v[2] -= vector.v[2];
return *this;
}
inline QVector3D &QVector3D::operator*=(float factor)
{
- xp *= factor;
- yp *= factor;
- zp *= factor;
+ v[0] *= factor;
+ v[1] *= factor;
+ v[2] *= factor;
return *this;
}
inline QVector3D &QVector3D::operator*=(const QVector3D& vector)
{
- xp *= vector.xp;
- yp *= vector.yp;
- zp *= vector.zp;
+ v[0] *= vector.v[0];
+ v[1] *= vector.v[1];
+ v[2] *= vector.v[2];
return *this;
}
inline QVector3D &QVector3D::operator/=(float divisor)
{
- xp /= divisor;
- yp /= divisor;
- zp /= divisor;
+ v[0] /= divisor;
+ v[1] /= divisor;
+ v[2] /= divisor;
return *this;
}
inline QVector3D &QVector3D::operator/=(const QVector3D &vector)
{
- xp /= vector.xp;
- yp /= vector.yp;
- zp /= vector.zp;
+ v[0] /= vector.v[0];
+ v[1] /= vector.v[1];
+ v[2] /= vector.v[2];
return *this;
}
@@ -234,70 +234,70 @@ QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
QT_WARNING_DISABLE_GCC("-Wfloat-equal")
Q_DECL_CONSTEXPR inline bool operator==(const QVector3D &v1, const QVector3D &v2)
{
- return v1.xp == v2.xp && v1.yp == v2.yp && v1.zp == v2.zp;
+ return v1.v[0] == v2.v[0] && v1.v[1] == v2.v[1] && v1.v[2] == v2.v[2];
}
Q_DECL_CONSTEXPR inline bool operator!=(const QVector3D &v1, const QVector3D &v2)
{
- return v1.xp != v2.xp || v1.yp != v2.yp || v1.zp != v2.zp;
+ return v1.v[0] != v2.v[0] || v1.v[1] != v2.v[1] || v1.v[2] != v2.v[2];
}
QT_WARNING_POP
Q_DECL_CONSTEXPR inline const QVector3D operator+(const QVector3D &v1, const QVector3D &v2)
{
- return QVector3D(v1.xp + v2.xp, v1.yp + v2.yp, v1.zp + v2.zp);
+ return QVector3D(v1.v[0] + v2.v[0], v1.v[1] + v2.v[1], v1.v[2] + v2.v[2]);
}
Q_DECL_CONSTEXPR inline const QVector3D operator-(const QVector3D &v1, const QVector3D &v2)
{
- return QVector3D(v1.xp - v2.xp, v1.yp - v2.yp, v1.zp - v2.zp);
+ return QVector3D(v1.v[0] - v2.v[0], v1.v[1] - v2.v[1], v1.v[2] - v2.v[2]);
}
Q_DECL_CONSTEXPR inline const QVector3D operator*(float factor, const QVector3D &vector)
{
- return QVector3D(vector.xp * factor, vector.yp * factor, vector.zp * factor);
+ return QVector3D(vector.v[0] * factor, vector.v[1] * factor, vector.v[2] * factor);
}
Q_DECL_CONSTEXPR inline const QVector3D operator*(const QVector3D &vector, float factor)
{
- return QVector3D(vector.xp * factor, vector.yp * factor, vector.zp * factor);
+ return QVector3D(vector.v[0] * factor, vector.v[1] * factor, vector.v[2] * factor);
}
Q_DECL_CONSTEXPR inline const QVector3D operator*(const QVector3D &v1, const QVector3D& v2)
{
- return QVector3D(v1.xp * v2.xp, v1.yp * v2.yp, v1.zp * v2.zp);
+ return QVector3D(v1.v[0] * v2.v[0], v1.v[1] * v2.v[1], v1.v[2] * v2.v[2]);
}
Q_DECL_CONSTEXPR inline const QVector3D operator-(const QVector3D &vector)
{
- return QVector3D(-vector.xp, -vector.yp, -vector.zp);
+ return QVector3D(-vector.v[0], -vector.v[1], -vector.v[2]);
}
Q_DECL_CONSTEXPR inline const QVector3D operator/(const QVector3D &vector, float divisor)
{
- return QVector3D(vector.xp / divisor, vector.yp / divisor, vector.zp / divisor);
+ return QVector3D(vector.v[0] / divisor, vector.v[1] / divisor, vector.v[2] / divisor);
}
Q_DECL_CONSTEXPR inline const QVector3D operator/(const QVector3D &vector, const QVector3D &divisor)
{
- return QVector3D(vector.xp / divisor.xp, vector.yp / divisor.yp, vector.zp / divisor.zp);
+ return QVector3D(vector.v[0] / divisor.v[0], vector.v[1] / divisor.v[1], vector.v[2] / divisor.v[2]);
}
Q_DECL_CONSTEXPR inline bool qFuzzyCompare(const QVector3D& v1, const QVector3D& v2)
{
- return qFuzzyCompare(v1.xp, v2.xp) &&
- qFuzzyCompare(v1.yp, v2.yp) &&
- qFuzzyCompare(v1.zp, v2.zp);
+ return qFuzzyCompare(v1.v[0], v2.v[0]) &&
+ qFuzzyCompare(v1.v[1], v2.v[1]) &&
+ qFuzzyCompare(v1.v[2], v2.v[2]);
}
Q_DECL_CONSTEXPR inline QPoint QVector3D::toPoint() const
{
- return QPoint(qRound(xp), qRound(yp));
+ return QPoint(qRound(v[0]), qRound(v[1]));
}
Q_DECL_CONSTEXPR inline QPointF QVector3D::toPointF() const
{
- return QPointF(qreal(xp), qreal(yp));
+ return QPointF(qreal(v[0]), qreal(v[1]));
}
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/gui/math3d/qvector4d.cpp b/src/gui/math3d/qvector4d.cpp
index 331144ba33..3a68bd6cb7 100644
--- a/src/gui/math3d/qvector4d.cpp
+++ b/src/gui/math3d/qvector4d.cpp
@@ -49,6 +49,42 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_VECTOR4D
+Q_STATIC_ASSERT_X(std::is_standard_layout<QVector4D>::value, "QVector4D is supposed to be standard layout");
+Q_STATIC_ASSERT_X(sizeof(QVector4D) == sizeof(float) * 4, "QVector4D is not supposed to have padding at the end");
+
+// QVector4D used to be defined as class QVector4D { float x, y, z, w; };,
+// now instead it is defined as classs QVector4D { float v[4]; };.
+// Check that binary compatibility is preserved.
+// ### Qt 6: remove all of these checks.
+
+namespace {
+
+struct QVector4DOld
+{
+ float x, y, z, w;
+};
+
+struct QVector4DNew
+{
+ float v[4];
+};
+
+Q_STATIC_ASSERT_X(std::is_standard_layout<QVector4DOld>::value, "Binary compatibility break in QVector4D");
+Q_STATIC_ASSERT_X(std::is_standard_layout<QVector4DNew>::value, "Binary compatibility break in QVector4D");
+
+Q_STATIC_ASSERT_X(sizeof(QVector4DOld) == sizeof(QVector4DNew), "Binary compatibility break in QVector4D");
+
+// requires a constexpr offsetof
+#if !defined(Q_CC_MSVC) || (_MSC_VER >= 1910)
+Q_STATIC_ASSERT_X(offsetof(QVector4DOld, x) == offsetof(QVector4DNew, v) + sizeof(QVector4DNew::v[0]) * 0, "Binary compatibility break in QVector4D");
+Q_STATIC_ASSERT_X(offsetof(QVector4DOld, y) == offsetof(QVector4DNew, v) + sizeof(QVector4DNew::v[0]) * 1, "Binary compatibility break in QVector4D");
+Q_STATIC_ASSERT_X(offsetof(QVector4DOld, z) == offsetof(QVector4DNew, v) + sizeof(QVector4DNew::v[0]) * 2, "Binary compatibility break in QVector4D");
+Q_STATIC_ASSERT_X(offsetof(QVector4DOld, w) == offsetof(QVector4DNew, v) + sizeof(QVector4DNew::v[0]) * 3, "Binary compatibility break in QVector4D");
+#endif
+
+
+} // anonymous namespace
+
/*!
\class QVector4D
\brief The QVector4D class represents a vector or vertex in 4D space.
@@ -106,10 +142,10 @@ QT_BEGIN_NAMESPACE
*/
QVector4D::QVector4D(const QVector2D& vector)
{
- xp = vector.xp;
- yp = vector.yp;
- zp = 0.0f;
- wp = 0.0f;
+ v[0] = vector.v[0];
+ v[1] = vector.v[1];
+ v[2] = 0.0f;
+ v[3] = 0.0f;
}
/*!
@@ -120,10 +156,10 @@ QVector4D::QVector4D(const QVector2D& vector)
*/
QVector4D::QVector4D(const QVector2D& vector, float zpos, float wpos)
{
- xp = vector.xp;
- yp = vector.yp;
- zp = zpos;
- wp = wpos;
+ v[0] = vector.v[0];
+ v[1] = vector.v[1];
+ v[2] = zpos;
+ v[3] = wpos;
}
#endif
@@ -138,10 +174,10 @@ QVector4D::QVector4D(const QVector2D& vector, float zpos, float wpos)
*/
QVector4D::QVector4D(const QVector3D& vector)
{
- xp = vector.xp;
- yp = vector.yp;
- zp = vector.zp;
- wp = 0.0f;
+ v[0] = vector.v[0];
+ v[1] = vector.v[1];
+ v[2] = vector.v[2];
+ v[3] = 0.0f;
}
/*!
@@ -152,10 +188,10 @@ QVector4D::QVector4D(const QVector3D& vector)
*/
QVector4D::QVector4D(const QVector3D& vector, float wpos)
{
- xp = vector.xp;
- yp = vector.yp;
- zp = vector.zp;
- wp = wpos;
+ v[0] = vector.v[0];
+ v[1] = vector.v[1];
+ v[2] = vector.v[2];
+ v[3] = wpos;
}
#endif
@@ -258,10 +294,10 @@ QVector4D::QVector4D(const QVector3D& vector, float wpos)
float QVector4D::length() const
{
// Need some extra precision if the length is very small.
- double len = double(xp) * double(xp) +
- double(yp) * double(yp) +
- double(zp) * double(zp) +
- double(wp) * double(wp);
+ double len = double(v[0]) * double(v[0]) +
+ double(v[1]) * double(v[1]) +
+ double(v[2]) * double(v[2]) +
+ double(v[3]) * double(v[3]);
return float(std::sqrt(len));
}
@@ -273,7 +309,7 @@ float QVector4D::length() const
*/
float QVector4D::lengthSquared() const
{
- return xp * xp + yp * yp + zp * zp + wp * wp;
+ return v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3];
}
/*!
@@ -288,18 +324,18 @@ float QVector4D::lengthSquared() const
QVector4D QVector4D::normalized() const
{
// Need some extra precision if the length is very small.
- double len = double(xp) * double(xp) +
- double(yp) * double(yp) +
- double(zp) * double(zp) +
- double(wp) * double(wp);
+ double len = double(v[0]) * double(v[0]) +
+ double(v[1]) * double(v[1]) +
+ double(v[2]) * double(v[2]) +
+ double(v[3]) * double(v[3]);
if (qFuzzyIsNull(len - 1.0f)) {
return *this;
} else if (!qFuzzyIsNull(len)) {
double sqrtLen = std::sqrt(len);
- return QVector4D(float(double(xp) / sqrtLen),
- float(double(yp) / sqrtLen),
- float(double(zp) / sqrtLen),
- float(double(wp) / sqrtLen));
+ return QVector4D(float(double(v[0]) / sqrtLen),
+ float(double(v[1]) / sqrtLen),
+ float(double(v[2]) / sqrtLen),
+ float(double(v[3]) / sqrtLen));
} else {
return QVector4D();
}
@@ -314,19 +350,19 @@ QVector4D QVector4D::normalized() const
void QVector4D::normalize()
{
// Need some extra precision if the length is very small.
- double len = double(xp) * double(xp) +
- double(yp) * double(yp) +
- double(zp) * double(zp) +
- double(wp) * double(wp);
+ double len = double(v[0]) * double(v[0]) +
+ double(v[1]) * double(v[1]) +
+ double(v[2]) * double(v[2]) +
+ double(v[3]) * double(v[3]);
if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len))
return;
len = std::sqrt(len);
- xp = float(double(xp) / len);
- yp = float(double(yp) / len);
- zp = float(double(zp) / len);
- wp = float(double(wp) / len);
+ v[0] = float(double(v[0]) / len);
+ v[1] = float(double(v[1]) / len);
+ v[2] = float(double(v[2]) / len);
+ v[3] = float(double(v[3]) / len);
}
/*!
@@ -387,7 +423,7 @@ void QVector4D::normalize()
*/
float QVector4D::dotProduct(const QVector4D& v1, const QVector4D& v2)
{
- return v1.xp * v2.xp + v1.yp * v2.yp + v1.zp * v2.zp + v1.wp * v2.wp;
+ return v1.v[0] * v2.v[0] + v1.v[1] * v2.v[1] + v1.v[2] * v2.v[2] + v1.v[3] * v2.v[3];
}
/*!
@@ -503,7 +539,7 @@ float QVector4D::dotProduct(const QVector4D& v1, const QVector4D& v2)
*/
QVector2D QVector4D::toVector2D() const
{
- return QVector2D(xp, yp);
+ return QVector2D(v[0], v[1]);
}
/*!
@@ -515,9 +551,9 @@ QVector2D QVector4D::toVector2D() const
*/
QVector2D QVector4D::toVector2DAffine() const
{
- if (qIsNull(wp))
+ if (qIsNull(v[3]))
return QVector2D();
- return QVector2D(xp / wp, yp / wp);
+ return QVector2D(v[0] / v[3], v[1] / v[3]);
}
#endif
@@ -531,7 +567,7 @@ QVector2D QVector4D::toVector2DAffine() const
*/
QVector3D QVector4D::toVector3D() const
{
- return QVector3D(xp, yp, zp);
+ return QVector3D(v[0], v[1], v[2]);
}
/*!
@@ -542,9 +578,9 @@ QVector3D QVector4D::toVector3D() const
*/
QVector3D QVector4D::toVector3DAffine() const
{
- if (qIsNull(wp))
+ if (qIsNull(v[3]))
return QVector3D();
- return QVector3D(xp / wp, yp / wp, zp / wp);
+ return QVector3D(v[0] / v[3], v[1] / v[3], v[2] / v[3]);
}
#endif
diff --git a/src/gui/math3d/qvector4d.h b/src/gui/math3d/qvector4d.h
index 3f14b41e8e..08cb423484 100644
--- a/src/gui/math3d/qvector4d.h
+++ b/src/gui/math3d/qvector4d.h
@@ -128,7 +128,7 @@ public:
operator QVariant() const;
private:
- float xp, yp, zp, wp;
+ float v[4];
friend class QVector2D;
friend class QVector3D;
@@ -140,92 +140,92 @@ private:
Q_DECLARE_TYPEINFO(QVector4D, Q_PRIMITIVE_TYPE);
-Q_DECL_CONSTEXPR inline QVector4D::QVector4D() : xp(0.0f), yp(0.0f), zp(0.0f), wp(0.0f) {}
+Q_DECL_CONSTEXPR inline QVector4D::QVector4D() : v{0.0f, 0.0f, 0.0f, 0.0f} {}
-Q_DECL_CONSTEXPR inline QVector4D::QVector4D(float xpos, float ypos, float zpos, float wpos) : xp(xpos), yp(ypos), zp(zpos), wp(wpos) {}
+Q_DECL_CONSTEXPR inline QVector4D::QVector4D(float xpos, float ypos, float zpos, float wpos) : v{xpos, ypos, zpos, wpos} {}
-Q_DECL_CONSTEXPR inline QVector4D::QVector4D(const QPoint& point) : xp(point.x()), yp(point.y()), zp(0.0f), wp(0.0f) {}
+Q_DECL_CONSTEXPR inline QVector4D::QVector4D(const QPoint& point) : v{float(point.x()), float(point.y()), 0.0f, 0.0f} {}
-Q_DECL_CONSTEXPR inline QVector4D::QVector4D(const QPointF& point) : xp(float(point.x())), yp(float(point.y())), zp(0.0f), wp(0.0f) {}
+Q_DECL_CONSTEXPR inline QVector4D::QVector4D(const QPointF& point) : v{float(point.x()), float(point.y()), 0.0f, 0.0f} {}
inline bool QVector4D::isNull() const
{
- return qIsNull(xp) && qIsNull(yp) && qIsNull(zp) && qIsNull(wp);
+ return qIsNull(v[0]) && qIsNull(v[1]) && qIsNull(v[2]) && qIsNull(v[3]);
}
-Q_DECL_CONSTEXPR inline float QVector4D::x() const { return xp; }
-Q_DECL_CONSTEXPR inline float QVector4D::y() const { return yp; }
-Q_DECL_CONSTEXPR inline float QVector4D::z() const { return zp; }
-Q_DECL_CONSTEXPR inline float QVector4D::w() const { return wp; }
+Q_DECL_CONSTEXPR inline float QVector4D::x() const { return v[0]; }
+Q_DECL_CONSTEXPR inline float QVector4D::y() const { return v[1]; }
+Q_DECL_CONSTEXPR inline float QVector4D::z() const { return v[2]; }
+Q_DECL_CONSTEXPR inline float QVector4D::w() const { return v[3]; }
-inline void QVector4D::setX(float aX) { xp = aX; }
-inline void QVector4D::setY(float aY) { yp = aY; }
-inline void QVector4D::setZ(float aZ) { zp = aZ; }
-inline void QVector4D::setW(float aW) { wp = aW; }
+inline void QVector4D::setX(float aX) { v[0] = aX; }
+inline void QVector4D::setY(float aY) { v[1] = aY; }
+inline void QVector4D::setZ(float aZ) { v[2] = aZ; }
+inline void QVector4D::setW(float aW) { v[3] = aW; }
inline float &QVector4D::operator[](int i)
{
Q_ASSERT(uint(i) < 4u);
- return *(&xp + i);
+ return v[i];
}
inline float QVector4D::operator[](int i) const
{
Q_ASSERT(uint(i) < 4u);
- return *(&xp + i);
+ return v[i];
}
inline QVector4D &QVector4D::operator+=(const QVector4D &vector)
{
- xp += vector.xp;
- yp += vector.yp;
- zp += vector.zp;
- wp += vector.wp;
+ v[0] += vector.v[0];
+ v[1] += vector.v[1];
+ v[2] += vector.v[2];
+ v[3] += vector.v[3];
return *this;
}
inline QVector4D &QVector4D::operator-=(const QVector4D &vector)
{
- xp -= vector.xp;
- yp -= vector.yp;
- zp -= vector.zp;
- wp -= vector.wp;
+ v[0] -= vector.v[0];
+ v[1] -= vector.v[1];
+ v[2] -= vector.v[2];
+ v[3] -= vector.v[3];
return *this;
}
inline QVector4D &QVector4D::operator*=(float factor)
{
- xp *= factor;
- yp *= factor;
- zp *= factor;
- wp *= factor;
+ v[0] *= factor;
+ v[1] *= factor;
+ v[2] *= factor;
+ v[3] *= factor;
return *this;
}
inline QVector4D &QVector4D::operator*=(const QVector4D &vector)
{
- xp *= vector.xp;
- yp *= vector.yp;
- zp *= vector.zp;
- wp *= vector.wp;
+ v[0] *= vector.v[0];
+ v[1] *= vector.v[1];
+ v[2] *= vector.v[2];
+ v[3] *= vector.v[3];
return *this;
}
inline QVector4D &QVector4D::operator/=(float divisor)
{
- xp /= divisor;
- yp /= divisor;
- zp /= divisor;
- wp /= divisor;
+ v[0] /= divisor;
+ v[1] /= divisor;
+ v[2] /= divisor;
+ v[3] /= divisor;
return *this;
}
inline QVector4D &QVector4D::operator/=(const QVector4D &vector)
{
- xp /= vector.xp;
- yp /= vector.yp;
- zp /= vector.zp;
- wp /= vector.wp;
+ v[0] /= vector.v[0];
+ v[1] /= vector.v[1];
+ v[2] /= vector.v[2];
+ v[3] /= vector.v[3];
return *this;
}
@@ -234,71 +234,71 @@ QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
QT_WARNING_DISABLE_GCC("-Wfloat-equal")
Q_DECL_CONSTEXPR inline bool operator==(const QVector4D &v1, const QVector4D &v2)
{
- return v1.xp == v2.xp && v1.yp == v2.yp && v1.zp == v2.zp && v1.wp == v2.wp;
+ return v1.v[0] == v2.v[0] && v1.v[1] == v2.v[1] && v1.v[2] == v2.v[2] && v1.v[3] == v2.v[3];
}
Q_DECL_CONSTEXPR inline bool operator!=(const QVector4D &v1, const QVector4D &v2)
{
- return v1.xp != v2.xp || v1.yp != v2.yp || v1.zp != v2.zp || v1.wp != v2.wp;
+ return v1.v[0] != v2.v[0] || v1.v[1] != v2.v[1] || v1.v[2] != v2.v[2] || v1.v[3] != v2.v[3];
}
QT_WARNING_POP
Q_DECL_CONSTEXPR inline const QVector4D operator+(const QVector4D &v1, const QVector4D &v2)
{
- return QVector4D(v1.xp + v2.xp, v1.yp + v2.yp, v1.zp + v2.zp, v1.wp + v2.wp);
+ return QVector4D(v1.v[0] + v2.v[0], v1.v[1] + v2.v[1], v1.v[2] + v2.v[2], v1.v[3] + v2.v[3]);
}
Q_DECL_CONSTEXPR inline const QVector4D operator-(const QVector4D &v1, const QVector4D &v2)
{
- return QVector4D(v1.xp - v2.xp, v1.yp - v2.yp, v1.zp - v2.zp, v1.wp - v2.wp);
+ return QVector4D(v1.v[0] - v2.v[0], v1.v[1] - v2.v[1], v1.v[2] - v2.v[2], v1.v[3] - v2.v[3]);
}
Q_DECL_CONSTEXPR inline const QVector4D operator*(float factor, const QVector4D &vector)
{
- return QVector4D(vector.xp * factor, vector.yp * factor, vector.zp * factor, vector.wp * factor);
+ return QVector4D(vector.v[0] * factor, vector.v[1] * factor, vector.v[2] * factor, vector.v[3] * factor);
}
Q_DECL_CONSTEXPR inline const QVector4D operator*(const QVector4D &vector, float factor)
{
- return QVector4D(vector.xp * factor, vector.yp * factor, vector.zp * factor, vector.wp * factor);
+ return QVector4D(vector.v[0] * factor, vector.v[1] * factor, vector.v[2] * factor, vector.v[3] * factor);
}
Q_DECL_CONSTEXPR inline const QVector4D operator*(const QVector4D &v1, const QVector4D& v2)
{
- return QVector4D(v1.xp * v2.xp, v1.yp * v2.yp, v1.zp * v2.zp, v1.wp * v2.wp);
+ return QVector4D(v1.v[0] * v2.v[0], v1.v[1] * v2.v[1], v1.v[2] * v2.v[2], v1.v[3] * v2.v[3]);
}
Q_DECL_CONSTEXPR inline const QVector4D operator-(const QVector4D &vector)
{
- return QVector4D(-vector.xp, -vector.yp, -vector.zp, -vector.wp);
+ return QVector4D(-vector.v[0], -vector.v[1], -vector.v[2], -vector.v[3]);
}
Q_DECL_CONSTEXPR inline const QVector4D operator/(const QVector4D &vector, float divisor)
{
- return QVector4D(vector.xp / divisor, vector.yp / divisor, vector.zp / divisor, vector.wp / divisor);
+ return QVector4D(vector.v[0] / divisor, vector.v[1] / divisor, vector.v[2] / divisor, vector.v[3] / divisor);
}
Q_DECL_CONSTEXPR inline const QVector4D operator/(const QVector4D &vector, const QVector4D &divisor)
{
- return QVector4D(vector.xp / divisor.xp, vector.yp / divisor.yp, vector.zp / divisor.zp, vector.wp / divisor.wp);
+ return QVector4D(vector.v[0] / divisor.v[0], vector.v[1] / divisor.v[1], vector.v[2] / divisor.v[2], vector.v[3] / divisor.v[3]);
}
Q_DECL_CONSTEXPR inline bool qFuzzyCompare(const QVector4D& v1, const QVector4D& v2)
{
- return qFuzzyCompare(v1.xp, v2.xp) &&
- qFuzzyCompare(v1.yp, v2.yp) &&
- qFuzzyCompare(v1.zp, v2.zp) &&
- qFuzzyCompare(v1.wp, v2.wp);
+ return qFuzzyCompare(v1.v[0], v2.v[0]) &&
+ qFuzzyCompare(v1.v[1], v2.v[1]) &&
+ qFuzzyCompare(v1.v[2], v2.v[2]) &&
+ qFuzzyCompare(v1.v[3], v2.v[3]);
}
Q_DECL_CONSTEXPR inline QPoint QVector4D::toPoint() const
{
- return QPoint(qRound(xp), qRound(yp));
+ return QPoint(qRound(v[0]), qRound(v[1]));
}
Q_DECL_CONSTEXPR inline QPointF QVector4D::toPointF() const
{
- return QPointF(qreal(xp), qreal(yp));
+ return QPointF(qreal(v[0]), qreal(v[1]));
}
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/gui/opengl/opengl.pri b/src/gui/opengl/opengl.pri
index 4c778b184e..24758afdeb 100644
--- a/src/gui/opengl/opengl.pri
+++ b/src/gui/opengl/opengl.pri
@@ -32,6 +32,7 @@ qtConfig(opengl) {
opengl/qopengltexture.h \
opengl/qopengltexture_p.h \
opengl/qopengltexturehelper_p.h \
+ opengl/qopengltextureuploader_p.h \
opengl/qopenglpixeltransferoptions.h \
opengl/qopenglextrafunctions.h \
opengl/qopenglprogrambinarycache_p.h
@@ -56,6 +57,7 @@ qtConfig(opengl) {
opengl/qopengltextureblitter.cpp \
opengl/qopengltexture.cpp \
opengl/qopengltexturehelper.cpp \
+ opengl/qopengltextureuploader.cpp \
opengl/qopenglpixeltransferoptions.cpp \
opengl/qopenglprogrambinarycache.cpp
diff --git a/src/gui/opengl/qopengl.h b/src/gui/opengl/qopengl.h
index b4657fa118..3a2393ea58 100644
--- a/src/gui/opengl/qopengl.h
+++ b/src/gui/opengl/qopengl.h
@@ -239,7 +239,7 @@ typedef unsigned long long int uint64_t;
typedef long int int32_t;
typedef long long int int64_t;
typedef unsigned long long int uint64_t;
-#elif defined(_WIN32) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1600))
+#elif defined(_WIN32) && (defined(__GNUC__) || defined(_MSC_VER))
#include <stdint.h>
#elif defined(_WIN32)
typedef __int32 int32_t;
diff --git a/src/gui/opengl/qopenglbuffer.cpp b/src/gui/opengl/qopenglbuffer.cpp
index 69c2baa8d9..537097c09f 100644
--- a/src/gui/opengl/qopenglbuffer.cpp
+++ b/src/gui/opengl/qopenglbuffer.cpp
@@ -43,6 +43,10 @@
#include "qopenglbuffer.h"
#include <private/qopenglextensions_p.h>
+#ifndef GL_CONTEXT_LOST
+#define GL_CONTEXT_LOST 0x0507
+#endif
+
QT_BEGIN_NAMESPACE
/*!
@@ -59,12 +63,7 @@ QT_BEGIN_NAMESPACE
QOpenGLBuffer objects can be copied around as a reference to the
underlying OpenGL buffer object:
- \code
- QOpenGLBuffer buffer1(QOpenGLBuffer::IndexBuffer);
- buffer1.create();
-
- QOpenGLBuffer buffer2 = buffer1;
- \endcode
+ \snippet code/src_gui_opengl_qopenglbuffer.cpp 0
QOpenGLBuffer performs a shallow copy when objects are copied in this
manner, but does not implement copy-on-write semantics. The original
@@ -346,7 +345,14 @@ bool QOpenGLBuffer::read(int offset, void *data, int count)
Q_D(QOpenGLBuffer);
if (!d->funcs->hasOpenGLFeature(QOpenGLFunctions::Buffers) || !d->guard->id())
return false;
- while (d->funcs->glGetError() != GL_NO_ERROR) ; // Clear error state.
+
+ while (true) { // Clear error state.
+ GLenum error = d->funcs->glGetError();
+ if (error == GL_NO_ERROR)
+ break;
+ if (error == GL_CONTEXT_LOST)
+ return false;
+ };
d->funcs->glGetBufferSubData(d->type, offset, count, data);
return d->funcs->glGetError() == GL_NO_ERROR;
#else
@@ -473,9 +479,7 @@ void QOpenGLBuffer::release()
been bound to the context but wants to make sure that it
is released.
- \code
- QOpenGLBuffer::release(QOpenGLBuffer::VertexBuffer);
- \endcode
+ \snippet code/src_gui_opengl_qopenglbuffer.cpp 1
*/
void QOpenGLBuffer::release(QOpenGLBuffer::Type type)
{
diff --git a/src/gui/opengl/qopengldebug.cpp b/src/gui/opengl/qopengldebug.cpp
index f6c3af37dd..2e628a2bd5 100644
--- a/src/gui/opengl/qopengldebug.cpp
+++ b/src/gui/opengl/qopengldebug.cpp
@@ -89,16 +89,11 @@ QT_BEGIN_NAMESPACE
call. Moreover, OpenGL errors stack up, therefore glGetError should always
be used in a loop like this:
- \code
+ \snippet code/src_gui_opengl_qopengldebug.cpp 0
- GLenum error = GL_NO_ERROR;
- do {
- error = glGetError();
- if (error != GL_NO_ERROR)
- // handle the error
- } while (error != GL_NO_ERROR);
-
- \endcode
+ If you try to clear the error stack, make sure not just keep going until
+ GL_NO_ERROR is returned but also break on GL_CONTEXT_LOST as that error
+ value will keep repeating.
There are also many other information we are interested in (as application
developers), for instance performance issues, or warnings about using
@@ -121,20 +116,7 @@ QT_BEGIN_NAMESPACE
to create a debug context from Qt, you must set the QSurfaceFormat::DebugContext
format option on the QSurfaceFormat used to create the QOpenGLContext object:
- \code
-
- QSurfaceFormat format;
- // asks for a OpenGL 3.2 debug context using the Core profile
- format.setMajorVersion(3);
- format.setMinorVersion(2);
- format.setProfile(QSurfaceFormat::CoreProfile);
- format.setOption(QSurfaceFormat::DebugContext);
-
- QOpenGLContext *context = new QOpenGLContext;
- context->setFormat(format);
- context->create();
-
- \endcode
+ \snippet code/src_gui_opengl_qopengldebug.cpp 1
Note that requesting a 3.2 OpenGL Core Profile is just for the example's
purposes; this class is not tied to any specific OpenGL or OpenGL ES
@@ -148,24 +130,13 @@ QT_BEGIN_NAMESPACE
object), and like the other OpenGL functions in Qt you \e{must} initialize
it before usage by calling initialize() whilst there is a current OpenGL context:
- \code
-
- QOpenGLContext *ctx = QOpenGLContext::currentContext();
- QOpenGLDebugLogger *logger = new QOpenGLDebugLogger(this);
-
- logger->initialize(); // initializes in the current context, i.e. ctx
-
- \endcode
+ \snippet code/src_gui_opengl_qopengldebug.cpp 2
Note that the \c{GL_KHR_debug} extension \e{must} be available in the context
in order to access the messages logged by OpenGL. You can check the
presence of this extension by calling:
- \code
-
- ctx->hasExtension(QByteArrayLiteral("GL_KHR_debug"))
-
- \endcode
+ \snippet code/src_gui_opengl_qopengldebug.cpp 3
where \c{ctx} is a valid QOpenGLContext. If the extension is not available,
initialize() will return false.
@@ -175,13 +146,7 @@ QT_BEGIN_NAMESPACE
OpenGL implementations keep an internal log of debug messages. Messages
stored in this log can be retrieved by using the loggedMessages() function:
- \code
-
- const QList<QOpenGLDebugMessage> messages = logger->loggedMessages();
- for (const QOpenGLDebugMessage &message : messages)
- qDebug() << message;
-
- \endcode
+ \snippet code/src_gui_opengl_qopengldebug.cpp 4
The internal log has a limited size; when it fills up, older messages will
get discarded to make room for the new incoming messages. When you call
@@ -199,12 +164,7 @@ QT_BEGIN_NAMESPACE
you need to connect a suitable slot to the messageLogged() signal, and
start logging by calling startLogging():
- \code
-
- connect(logger, &QOpenGLDebugLogger::messageLogged, receiver, &LogHandler::handleLoggedMessage);
- logger->startLogging();
-
- \endcode
+ \snippet code/src_gui_opengl_qopengldebug.cpp 5
Similarly, logging can be disabled at any time by calling the stopLogging()
function.
@@ -255,14 +215,7 @@ QT_BEGIN_NAMESPACE
\l{QOpenGLDebugMessage::}{createThirdPartyMessage()}, and then inserting it
into the log by calling logMessage():
- \code
-
- QOpenGLDebugMessage message =
- QOpenGLDebugMessage::createApplicationMessage(QStringLiteral("Custom message"));
-
- logger->logMessage(message);
-
- \endcode
+ \snippet code/src_gui_opengl_qopengldebug.cpp 6
Note that OpenGL implementations have a vendor-specific limit to the length
of the messages that can be inserted in the debug log. You can retrieve
diff --git a/src/gui/opengl/qopenglengineshadermanager.cpp b/src/gui/opengl/qopenglengineshadermanager.cpp
index 2f7afa4a66..1e5a10c99c 100644
--- a/src/gui/opengl/qopenglengineshadermanager.cpp
+++ b/src/gui/opengl/qopenglengineshadermanager.cpp
@@ -153,12 +153,8 @@ QOpenGLEngineSharedShaders::QOpenGLEngineSharedShaders(QOpenGLContext* context)
code[AffinePositionWithRadialGradientBrushVertexShader] = qopenglslAffinePositionWithRadialGradientBrushVertexShader_core;
code[AffinePositionWithTextureBrushVertexShader] = qopenglslAffinePositionWithTextureBrushVertexShader_core;
- code[MainFragmentShader_CMO] = qopenglslMainFragmentShader_CMO_core;
- code[MainFragmentShader_CM] = qopenglslMainFragmentShader_CM_core;
code[MainFragmentShader_MO] = qopenglslMainFragmentShader_MO_core;
code[MainFragmentShader_M] = qopenglslMainFragmentShader_M_core;
- code[MainFragmentShader_CO] = qopenglslMainFragmentShader_CO_core;
- code[MainFragmentShader_C] = qopenglslMainFragmentShader_C_core;
code[MainFragmentShader_O] = qopenglslMainFragmentShader_O_core;
code[MainFragmentShader] = qopenglslMainFragmentShader_core;
code[MainFragmentShader_ImageArrays] = qopenglslMainFragmentShader_ImageArrays_core;
@@ -171,7 +167,7 @@ QOpenGLEngineSharedShaders::QOpenGLEngineSharedShaders(QOpenGLContext* context)
code[CustomImageSrcFragmentShader] = qopenglslCustomSrcFragmentShader_core; // Calls "customShader", which must be appended
code[SolidBrushSrcFragmentShader] = qopenglslSolidBrushSrcFragmentShader_core;
- code[TextureBrushSrcFragmentShader] = qopenglslTextureBrushSrcFragmentShader_desktop_core;
+ code[TextureBrushSrcFragmentShader] = qopenglslTextureBrushSrcFragmentShader_core;
code[TextureBrushSrcWithPatternFragmentShader] = qopenglslTextureBrushSrcWithPatternFragmentShader_core;
code[PatternBrushSrcFragmentShader] = qopenglslPatternBrushSrcFragmentShader_core;
code[LinearGradientBrushSrcFragmentShader] = qopenglslLinearGradientBrushSrcFragmentShader_core;
@@ -203,12 +199,8 @@ QOpenGLEngineSharedShaders::QOpenGLEngineSharedShaders(QOpenGLContext* context)
code[AffinePositionWithRadialGradientBrushVertexShader] = qopenglslAffinePositionWithRadialGradientBrushVertexShader;
code[AffinePositionWithTextureBrushVertexShader] = qopenglslAffinePositionWithTextureBrushVertexShader;
- code[MainFragmentShader_CMO] = qopenglslMainFragmentShader_CMO;
- code[MainFragmentShader_CM] = qopenglslMainFragmentShader_CM;
code[MainFragmentShader_MO] = qopenglslMainFragmentShader_MO;
code[MainFragmentShader_M] = qopenglslMainFragmentShader_M;
- code[MainFragmentShader_CO] = qopenglslMainFragmentShader_CO;
- code[MainFragmentShader_C] = qopenglslMainFragmentShader_C;
code[MainFragmentShader_O] = qopenglslMainFragmentShader_O;
code[MainFragmentShader] = qopenglslMainFragmentShader;
code[MainFragmentShader_ImageArrays] = qopenglslMainFragmentShader_ImageArrays;
@@ -220,10 +212,7 @@ QOpenGLEngineSharedShaders::QOpenGLEngineSharedShaders(QOpenGLContext* context)
code[AlphaImageSrcFragmentShader] = qopenglslAlphaImageSrcFragmentShader;
code[CustomImageSrcFragmentShader] = qopenglslCustomSrcFragmentShader; // Calls "customShader", which must be appended
code[SolidBrushSrcFragmentShader] = qopenglslSolidBrushSrcFragmentShader;
- if (context->isOpenGLES())
- code[TextureBrushSrcFragmentShader] = qopenglslTextureBrushSrcFragmentShader_ES;
- else
- code[TextureBrushSrcFragmentShader] = qopenglslTextureBrushSrcFragmentShader_desktop;
+ code[TextureBrushSrcFragmentShader] = qopenglslTextureBrushSrcFragmentShader;
code[TextureBrushSrcWithPatternFragmentShader] = qopenglslTextureBrushSrcWithPatternFragmentShader;
code[PatternBrushSrcFragmentShader] = qopenglslPatternBrushSrcFragmentShader;
code[LinearGradientBrushSrcFragmentShader] = qopenglslLinearGradientBrushSrcFragmentShader;
@@ -238,21 +227,20 @@ QOpenGLEngineSharedShaders::QOpenGLEngineSharedShaders(QOpenGLContext* context)
code[RgbMaskWithGammaFragmentShader] = ""; //###
}
- // These shaders are not implemented yet and therefore are the same
- // for all profiles. Implementations should make a version for both
- // profiles and put the appropriate lines in the if-statement above.
+ // The composition shaders are just layout qualifiers and the same
+ // for all profiles that support them.
code[NoCompositionModeFragmentShader] = "";
- code[MultiplyCompositionModeFragmentShader] = ""; //###
- code[ScreenCompositionModeFragmentShader] = ""; //###
- code[OverlayCompositionModeFragmentShader] = ""; //###
- code[DarkenCompositionModeFragmentShader] = ""; //###
- code[LightenCompositionModeFragmentShader] = ""; //###
- code[ColorDodgeCompositionModeFragmentShader] = ""; //###
- code[ColorBurnCompositionModeFragmentShader] = ""; //###
- code[HardLightCompositionModeFragmentShader] = ""; //###
- code[SoftLightCompositionModeFragmentShader] = ""; //###
- code[DifferenceCompositionModeFragmentShader] = ""; //###
- code[ExclusionCompositionModeFragmentShader] = ""; //###
+ code[MultiplyCompositionModeFragmentShader] = qopenglslMultiplyCompositionModeFragmentShader;
+ code[ScreenCompositionModeFragmentShader] = qopenglslScreenCompositionModeFragmentShader;
+ code[OverlayCompositionModeFragmentShader] = qopenglslOverlayCompositionModeFragmentShader;
+ code[DarkenCompositionModeFragmentShader] = qopenglslDarkenCompositionModeFragmentShader;
+ code[LightenCompositionModeFragmentShader] = qopenglslLightenCompositionModeFragmentShader;
+ code[ColorDodgeCompositionModeFragmentShader] = qopenglslColorDodgeCompositionModeFragmentShader;
+ code[ColorBurnCompositionModeFragmentShader] = qopenglslColorBurnCompositionModeFragmentShader;
+ code[HardLightCompositionModeFragmentShader] = qopenglslHardLightCompositionModeFragmentShader;
+ code[SoftLightCompositionModeFragmentShader] = qopenglslSoftLightCompositionModeFragmentShader;
+ code[DifferenceCompositionModeFragmentShader] = qopenglslDifferenceCompositionModeFragmentShader;
+ code[ExclusionCompositionModeFragmentShader] = qopenglslExclusionCompositionModeFragmentShader;
#if defined(QT_DEBUG)
// Check that all the elements have been filled:
@@ -268,9 +256,13 @@ QOpenGLEngineSharedShaders::QOpenGLEngineSharedShaders(QOpenGLContext* context)
QByteArray fragSource;
// Compile up the simple shader:
+#ifdef Q_OS_WASM
+ vertexSource.append(qShaderSnippets[PositionOnlyVertexShader]);
+ vertexSource.append(qShaderSnippets[MainVertexShader]);
+#else
vertexSource.append(qShaderSnippets[MainVertexShader]);
vertexSource.append(qShaderSnippets[PositionOnlyVertexShader]);
-
+#endif
fragSource.append(qShaderSnippets[MainFragmentShader]);
fragSource.append(qShaderSnippets[ShockingPinkSrcFragmentShader]);
@@ -396,9 +388,13 @@ QOpenGLEngineShaderProg *QOpenGLEngineSharedShaders::findProgramInCache(const QO
fragSource.append(qShaderSnippets[prog.maskFragShader]);
QByteArray vertexSource;
+#ifdef Q_OS_WASM
+ vertexSource.append(qShaderSnippets[prog.positionVertexShader]);
+ vertexSource.append(qShaderSnippets[prog.mainVertexShader]);
+#else
vertexSource.append(qShaderSnippets[prog.mainVertexShader]);
vertexSource.append(qShaderSnippets[prog.positionVertexShader]);
-
+#endif
QScopedPointer<QOpenGLShaderProgram> shaderProgram(new QOpenGLShaderProgram);
CachedShader shaderCache(fragSource, vertexSource);
@@ -612,8 +608,11 @@ void QOpenGLEngineShaderManager::setCompositionMode(QPainter::CompositionMode mo
if (compositionMode == mode)
return;
+ bool wasAdvanced = compositionMode > QPainter::CompositionMode_Plus;
+ bool isAdvanced = mode > QPainter::CompositionMode_Plus;
+
compositionMode = mode;
- shaderProgNeedsChanging = true; //###
+ shaderProgNeedsChanging = shaderProgNeedsChanging || wasAdvanced || isAdvanced;
}
void QOpenGLEngineShaderManager::setCustomStage(QOpenGLCustomShaderStage* stage)
@@ -783,21 +782,13 @@ bool QOpenGLEngineShaderManager::useCorrectShaderProg()
requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_ImageArrays;
} else {
bool useGlobalOpacity = (opacityMode == UniformOpacity);
- if (hasCompose && hasMask && useGlobalOpacity)
- requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_CMO;
- if (hasCompose && hasMask && !useGlobalOpacity)
- requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_CM;
- if (!hasCompose && hasMask && useGlobalOpacity)
+ if (hasMask && useGlobalOpacity)
requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_MO;
- if (!hasCompose && hasMask && !useGlobalOpacity)
+ if (hasMask && !useGlobalOpacity)
requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_M;
- if (hasCompose && !hasMask && useGlobalOpacity)
- requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_CO;
- if (hasCompose && !hasMask && !useGlobalOpacity)
- requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_C;
- if (!hasCompose && !hasMask && useGlobalOpacity)
+ if (!hasMask && useGlobalOpacity)
requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_O;
- if (!hasCompose && !hasMask && !useGlobalOpacity)
+ if (!hasMask && !useGlobalOpacity)
requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader;
}
diff --git a/src/gui/opengl/qopenglengineshadermanager_p.h b/src/gui/opengl/qopenglengineshadermanager_p.h
index 377501457d..d43788d777 100644
--- a/src/gui/opengl/qopenglengineshadermanager_p.h
+++ b/src/gui/opengl/qopenglengineshadermanager_p.h
@@ -281,12 +281,8 @@ public:
AffinePositionWithTextureBrushVertexShader,
// MainFragmentShader_CMO must be first in the list:
- MainFragmentShader_CMO,
- MainFragmentShader_CM,
MainFragmentShader_MO,
MainFragmentShader_M,
- MainFragmentShader_CO,
- MainFragmentShader_C,
MainFragmentShader_O,
MainFragmentShader,
MainFragmentShader_ImageArrays,
diff --git a/src/gui/opengl/qopenglengineshadersource_p.h b/src/gui/opengl/qopenglengineshadersource_p.h
index a165643839..3ac599b6c2 100644
--- a/src/gui/opengl/qopenglengineshadersource_p.h
+++ b/src/gui/opengl/qopenglengineshadersource_p.h
@@ -303,17 +303,7 @@ static const char* const qopenglslPositionWithTextureBrushVertexShader = "\n\
static const char* const qopenglslAffinePositionWithTextureBrushVertexShader
= qopenglslPositionWithTextureBrushVertexShader;
-// OpenGL ES does not support GL_REPEAT wrap modes for NPOT textures. So instead,
-// we emulate GL_REPEAT by only taking the fractional part of the texture coords.
-// TODO: Special case POT textures which don't need this emulation
-static const char* const qopenglslTextureBrushSrcFragmentShader_ES = "\n\
- varying highp vec2 brushTextureCoords; \n\
- uniform sampler2D brushTexture; \n\
- lowp vec4 srcPixel() { \n\
- return texture2D(brushTexture, fract(brushTextureCoords)); \n\
- }\n";
-
-static const char* const qopenglslTextureBrushSrcFragmentShader_desktop = "\n\
+static const char* const qopenglslTextureBrushSrcFragmentShader = "\n\
varying highp vec2 brushTextureCoords; \n\
uniform sampler2D brushTexture; \n\
lowp vec4 srcPixel() \n\
@@ -403,25 +393,6 @@ static const char* const qopenglslMainFragmentShader_ImageArrays = "\n\
gl_FragColor = srcPixel() * opacity; \n\
}\n";
-static const char* const qopenglslMainFragmentShader_CMO = "\n\
- uniform lowp float globalOpacity; \n\
- lowp vec4 srcPixel(); \n\
- lowp vec4 applyMask(lowp vec4); \n\
- lowp vec4 compose(lowp vec4); \n\
- void main() \n\
- { \n\
- gl_FragColor = applyMask(compose(srcPixel()*globalOpacity))); \n\
- }\n";
-
-static const char* const qopenglslMainFragmentShader_CM = "\n\
- lowp vec4 srcPixel(); \n\
- lowp vec4 applyMask(lowp vec4); \n\
- lowp vec4 compose(lowp vec4); \n\
- void main() \n\
- { \n\
- gl_FragColor = applyMask(compose(srcPixel())); \n\
- }\n";
-
static const char* const qopenglslMainFragmentShader_MO = "\n\
uniform lowp float globalOpacity; \n\
lowp vec4 srcPixel(); \n\
@@ -439,23 +410,6 @@ static const char* const qopenglslMainFragmentShader_M = "\n\
gl_FragColor = applyMask(srcPixel()); \n\
}\n";
-static const char* const qopenglslMainFragmentShader_CO = "\n\
- uniform lowp float globalOpacity; \n\
- lowp vec4 srcPixel(); \n\
- lowp vec4 compose(lowp vec4); \n\
- void main() \n\
- { \n\
- gl_FragColor = compose(srcPixel()*globalOpacity); \n\
- }\n";
-
-static const char* const qopenglslMainFragmentShader_C = "\n\
- lowp vec4 srcPixel(); \n\
- lowp vec4 compose(lowp vec4); \n\
- void main() \n\
- { \n\
- gl_FragColor = compose(srcPixel()); \n\
- }\n";
-
static const char* const qopenglslMainFragmentShader_O = "\n\
uniform lowp float globalOpacity; \n\
lowp vec4 srcPixel(); \n\
@@ -513,22 +467,65 @@ static const char* const qopenglslRgbMaskFragmentShaderPass2 = "\n\
return src * mask; \n\
}\n";
+static const char* const qopenglslMultiplyCompositionModeFragmentShader = "\n\
+ #ifdef GL_KHR_blend_equation_advanced\n\
+ layout(blend_support_multiply) out;\n\
+ #endif\n";
+
+static const char* const qopenglslScreenCompositionModeFragmentShader = "\n\
+ #ifdef GL_KHR_blend_equation_advanced\n\
+ layout(blend_support_screen) out;\n\
+ #endif\n";
+
+static const char* const qopenglslOverlayCompositionModeFragmentShader = "\n\
+ #ifdef GL_KHR_blend_equation_advanced\n\
+ layout(blend_support_overlay) out;\n\
+ #endif\n";
+
+static const char* const qopenglslDarkenCompositionModeFragmentShader = "\n\
+ #ifdef GL_KHR_blend_equation_advanced\n\
+ layout(blend_support_darken) out;\n\
+ #endif\n";
+
+static const char* const qopenglslLightenCompositionModeFragmentShader = "\n\
+ #ifdef GL_KHR_blend_equation_advanced\n\
+ layout(blend_support_lighten) out;\n\
+ #endif\n";
+
+static const char* const qopenglslColorDodgeCompositionModeFragmentShader = "\n\
+ #ifdef GL_KHR_blend_equation_advanced\n\
+ layout(blend_support_colordodge) out;\n\
+ #endif\n";
+
+static const char* const qopenglslColorBurnCompositionModeFragmentShader = "\n\
+ #ifdef GL_KHR_blend_equation_advanced\n\
+ layout(blend_support_colorburn) out;\n\
+ #endif\n";
+
+static const char* const qopenglslHardLightCompositionModeFragmentShader = "\n\
+ #ifdef GL_KHR_blend_equation_advanced\n\
+ layout(blend_support_hardlight) out;\n\
+ #endif\n";
+
+static const char* const qopenglslSoftLightCompositionModeFragmentShader = "\n\
+ #ifdef GL_KHR_blend_equation_advanced\n\
+ layout(blend_support_softlight) out;\n\
+ #endif\n";
+
+static const char* const qopenglslDifferenceCompositionModeFragmentShader = "\n\
+ #ifdef GL_KHR_blend_equation_advanced\n\
+ layout(blend_support_difference) out;\n\
+ #endif\n";
+
+static const char* const qopenglslExclusionCompositionModeFragmentShader = "\n\
+ #ifdef GL_KHR_blend_equation_advanced\n\
+ layout(blend_support_exclusion) out;\n\
+ #endif\n";
+
/*
Left to implement:
RgbMaskFragmentShader,
RgbMaskWithGammaFragmentShader,
-
- MultiplyCompositionModeFragmentShader,
- ScreenCompositionModeFragmentShader,
- OverlayCompositionModeFragmentShader,
- DarkenCompositionModeFragmentShader,
- LightenCompositionModeFragmentShader,
- ColorDodgeCompositionModeFragmentShader,
- ColorBurnCompositionModeFragmentShader,
- HardLightCompositionModeFragmentShader,
- SoftLightCompositionModeFragmentShader,
- DifferenceCompositionModeFragmentShader,
- ExclusionCompositionModeFragmentShader,
*/
/*
@@ -788,7 +785,7 @@ static const char* const qopenglslPositionWithTextureBrushVertexShader_core = "\
static const char* const qopenglslAffinePositionWithTextureBrushVertexShader_core
= qopenglslPositionWithTextureBrushVertexShader_core;
-static const char* const qopenglslTextureBrushSrcFragmentShader_desktop_core = "\n\
+static const char* const qopenglslTextureBrushSrcFragmentShader_core = "\n\
in vec2 brushTextureCoords; \n\
uniform sampler2D brushTexture; \n\
vec4 srcPixel() \n\
@@ -880,29 +877,6 @@ static const char* const qopenglslMainFragmentShader_ImageArrays_core =
fragColor = srcPixel() * opacity; \n\
}\n";
-static const char* const qopenglslMainFragmentShader_CMO_core =
- "#version 150 core\n\
- out vec4 fragColor; \n\
- uniform float globalOpacity; \n\
- vec4 srcPixel(); \n\
- vec4 applyMask(vec4); \n\
- vec4 compose(vec4); \n\
- void main() \n\
- { \n\
- fragColor = applyMask(compose(srcPixel()*globalOpacity))); \n\
- }\n";
-
-static const char* const qopenglslMainFragmentShader_CM_core =
- "#version 150 core\n\
- out vec4 fragColor; \n\
- vec4 srcPixel(); \n\
- vec4 applyMask(vec4); \n\
- vec4 compose(vec4); \n\
- void main() \n\
- { \n\
- fragColor = applyMask(compose(srcPixel())); \n\
- }\n";
-
static const char* const qopenglslMainFragmentShader_MO_core =
"#version 150 core\n\
out vec4 fragColor; \n\
@@ -924,27 +898,6 @@ static const char* const qopenglslMainFragmentShader_M_core =
fragColor = applyMask(srcPixel()); \n\
}\n";
-static const char* const qopenglslMainFragmentShader_CO_core =
- "#version 150 core\n\
- out vec4 fragColor; \n\
- uniform float globalOpacity; \n\
- vec4 srcPixel(); \n\
- vec4 compose(vec4); \n\
- void main() \n\
- { \n\
- fragColor = compose(srcPixel()*globalOpacity); \n\
- }\n";
-
-static const char* const qopenglslMainFragmentShader_C_core =
- "#version 150 core\n\
- out vec4 fragColor; \n\
- vec4 srcPixel(); \n\
- vec4 compose(vec4); \n\
- void main() \n\
- { \n\
- fragColor = compose(srcPixel()); \n\
- }\n";
-
static const char* const qopenglslMainFragmentShader_O_core =
"#version 150 core\n\
out vec4 fragColor; \n\
@@ -1010,18 +963,6 @@ static const char* const qopenglslRgbMaskFragmentShaderPass2_core = "\n\
Left to implement:
RgbMaskFragmentShader_core,
RgbMaskWithGammaFragmentShader_core,
-
- MultiplyCompositionModeFragmentShader_core,
- ScreenCompositionModeFragmentShader_core,
- OverlayCompositionModeFragmentShader_core,
- DarkenCompositionModeFragmentShader_core,
- LightenCompositionModeFragmentShader_core,
- ColorDodgeCompositionModeFragmentShader_core,
- ColorBurnCompositionModeFragmentShader_core,
- HardLightCompositionModeFragmentShader_core,
- SoftLightCompositionModeFragmentShader_core,
- DifferenceCompositionModeFragmentShader_core,
- ExclusionCompositionModeFragmentShader_core,
*/
QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopenglextensions_p.h b/src/gui/opengl/qopenglextensions_p.h
index a5f1a2cc88..af8ee8201d 100644
--- a/src/gui/opengl/qopenglextensions_p.h
+++ b/src/gui/opengl/qopenglextensions_p.h
@@ -90,7 +90,8 @@ public:
MapBufferRange = 0x00100000,
Sized8Formats = 0x00200000,
DiscardFramebuffer = 0x00400000,
- Sized16Formats = 0x00800000
+ Sized16Formats = 0x00800000,
+ TextureSwizzle = 0x01000000,
};
Q_DECLARE_FLAGS(OpenGLExtensions, OpenGLExtension)
diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp
index 83bc568ba7..cae3d516c4 100644
--- a/src/gui/opengl/qopenglframebufferobject.cpp
+++ b/src/gui/opengl/qopenglframebufferobject.cpp
@@ -110,6 +110,10 @@ QT_BEGIN_NAMESPACE
#define GL_RGB10 0x8052
#endif
+#ifndef GL_RGB16
+#define GL_RGB16 0x8054
+#endif
+
#ifndef GL_RGBA8
#define GL_RGBA8 0x8058
#endif
@@ -118,6 +122,10 @@ QT_BEGIN_NAMESPACE
#define GL_RGB10_A2 0x8059
#endif
+#ifndef GL_RGBA16
+#define GL_RGBA16 0x805B
+#endif
+
#ifndef GL_BGRA
#define GL_BGRA 0x80E1
#endif
@@ -134,6 +142,15 @@ QT_BEGIN_NAMESPACE
#define GL_CONTEXT_LOST 0x0507
#endif
+#ifndef GL_DEPTH_STENCIL_ATTACHMENT
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#endif
+
+#ifndef GL_DEPTH_STENCIL
+#define GL_DEPTH_STENCIL 0x84F9
+#endif
+
+
/*!
\class QOpenGLFramebufferObjectFormat
@@ -530,6 +547,8 @@ void QOpenGLFramebufferObjectPrivate::initTexture(int idx)
GLuint pixelType = GL_UNSIGNED_BYTE;
if (color.internalFormat == GL_RGB10_A2 || color.internalFormat == GL_RGB10)
pixelType = GL_UNSIGNED_INT_2_10_10_10_REV;
+ else if (color.internalFormat == GL_RGB16 || color.internalFormat == GL_RGBA16)
+ pixelType = GL_UNSIGNED_SHORT;
funcs.glTexImage2D(target, 0, color.internalFormat, color.size.width(), color.size.height(), 0,
GL_RGBA, pixelType, NULL);
@@ -567,11 +586,16 @@ void QOpenGLFramebufferObjectPrivate::initColorBuffer(int idx, GLint *samples)
GLenum storageFormat = color.internalFormat;
// ES requires a sized format. The older desktop extension does not. Correct the format on ES.
- if (ctx->isOpenGLES() && color.internalFormat == GL_RGBA) {
- if (funcs.hasOpenGLExtension(QOpenGLExtensions::Sized8Formats))
- storageFormat = GL_RGBA8;
- else
- storageFormat = GL_RGBA4;
+ if (ctx->isOpenGLES()) {
+ if (color.internalFormat == GL_RGBA) {
+ if (funcs.hasOpenGLExtension(QOpenGLExtensions::Sized8Formats))
+ storageFormat = GL_RGBA8;
+ else
+ storageFormat = GL_RGBA4;
+ } else if (color.internalFormat == GL_RGB10) {
+ // GL_RGB10 is not allowed in ES for glRenderbufferStorage.
+ storageFormat = GL_RGB10_A2;
+ }
}
funcs.glGenRenderbuffers(1, &color_buffer);
@@ -603,7 +627,11 @@ void QOpenGLFramebufferObjectPrivate::initDepthStencilAttachments(QOpenGLContext
// free existing attachments
if (depth_buffer_guard) {
+#ifdef Q_OS_WASM
+ funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
+#else
funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
+#endif
depth_buffer_guard->free();
}
if (stencil_buffer_guard) {
@@ -621,7 +649,35 @@ void QOpenGLFramebufferObjectPrivate::initDepthStencilAttachments(QOpenGLContext
// In practice, a combined depth-stencil buffer is supported by all desktop platforms, while a
// separate stencil buffer is not. On embedded devices however, a combined depth-stencil buffer
// might not be supported while separate buffers are, according to QTBUG-12861.
+#ifdef Q_OS_WASM
+ // WebGL doesn't allow separately attach buffers to
+ // STENCIL_ATTACHMENT and DEPTH_ATTACHMENT
+ // QTBUG-69913
+ if (attachment == QOpenGLFramebufferObject::CombinedDepthStencil) {
+ funcs.glGenRenderbuffers(1, &depth_buffer);
+ funcs.glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer);
+ Q_ASSERT(funcs.glIsRenderbuffer(depth_buffer));
+ GLenum storageFormat = GL_DEPTH_STENCIL;
+
+ if (samples != 0 ) {
+ funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
+ storageFormat, dsSize.width(), dsSize.height());
+ } else {
+ funcs.glRenderbufferStorage(GL_RENDERBUFFER, storageFormat,
+ dsSize.width(), dsSize.height());
+ }
+
+ funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, depth_buffer);
+
+ valid = checkFramebufferStatus(ctx);
+ if (!valid) {
+ funcs.glDeleteRenderbuffers(1, &depth_buffer);
+ depth_buffer = 0;
+ }
+ }
+#else
if (attachment == QOpenGLFramebufferObject::CombinedDepthStencil
&& funcs.hasOpenGLExtension(QOpenGLExtensions::PackedDepthStencil))
{
@@ -713,11 +769,16 @@ void QOpenGLFramebufferObjectPrivate::initDepthStencilAttachments(QOpenGLContext
stencil_buffer = 0;
}
}
+#endif //Q_OS_WASM
// The FBO might have become valid after removing the depth or stencil buffer.
valid = checkFramebufferStatus(ctx);
+#ifdef Q_OS_WASM
+ if (depth_buffer) {
+#else
if (depth_buffer && stencil_buffer) {
+#endif
fbo_attachment = QOpenGLFramebufferObject::CombinedDepthStencil;
} else if (depth_buffer) {
fbo_attachment = QOpenGLFramebufferObject::Depth;
@@ -1307,6 +1368,14 @@ static inline QImage qt_gl_read_framebuffer_rgb10a2(const QSize &size, bool incl
return img;
}
+static inline QImage qt_gl_read_framebuffer_rgba16(const QSize &size, bool include_alpha, QOpenGLContext *context)
+{
+ // We assume OpenGL 1.2+ or ES 3.0+ here.
+ QImage img(size, include_alpha ? QImage::Format_RGBA64_Premultiplied : QImage::Format_RGBX64);
+ context->functions()->glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_UNSIGNED_SHORT, img.bits());
+ return img;
+}
+
static QImage qt_gl_read_framebuffer(const QSize &size, GLenum internal_format, bool include_alpha, bool flip)
{
QOpenGLContext *ctx = QOpenGLContext::currentContext();
@@ -1324,6 +1393,10 @@ static QImage qt_gl_read_framebuffer(const QSize &size, GLenum internal_format,
return qt_gl_read_framebuffer_rgb10a2(size, false, ctx).mirrored(false, flip);
case GL_RGB10_A2:
return qt_gl_read_framebuffer_rgb10a2(size, include_alpha, ctx).mirrored(false, flip);
+ case GL_RGB16:
+ return qt_gl_read_framebuffer_rgba16(size, false, ctx).mirrored(false, flip);
+ case GL_RGBA16:
+ return qt_gl_read_framebuffer_rgba16(size, include_alpha, ctx).mirrored(false, flip);
case GL_RGBA:
case GL_RGBA8:
default:
@@ -1352,7 +1425,8 @@ Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format,
is used only when internalTextureFormat() is set to \c GL_RGB. Since Qt 5.2
the function will fall back to premultiplied RGBA8888 or RGBx8888 when
reading to (A)RGB32 is not supported, and this includes OpenGL ES. Since Qt
- 5.4 an A2BGR30 image is returned if the internal format is RGB10_A2.
+ 5.4 an A2BGR30 image is returned if the internal format is RGB10_A2, and since
+ Qt 5.12 a RGBA64 image is return if the internal format is RGBA16.
If the rendering in the framebuffer was not done with premultiplied alpha in mind,
create a wrapper QImage with a non-premultiplied format. This is necessary before
diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp
index 977565516f..b4ff21f3fd 100644
--- a/src/gui/opengl/qopenglfunctions.cpp
+++ b/src/gui/opengl/qopenglfunctions.cpp
@@ -45,6 +45,7 @@
#include <QtGui/private/qopengl_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformintegration.h>
+#include <qpa/qplatformnativeinterface.h>
#ifdef Q_OS_INTEGRITY
#include <EGL/egl.h>
@@ -89,65 +90,18 @@ void CLASS::init(QOpenGLContext *context) \
that need it. The recommended way to use QOpenGLFunctions is by
direct inheritance:
- \code
- class MyGLWindow : public QWindow, protected QOpenGLFunctions
- {
- Q_OBJECT
- public:
- MyGLWindow(QScreen *screen = 0);
-
- protected:
- void initializeGL();
- void paintGL();
-
- QOpenGLContext *m_context;
- };
-
- MyGLWindow(QScreen *screen)
- : QWindow(screen), QOpenGLWidget(parent)
- {
- setSurfaceType(OpenGLSurface);
- create();
-
- // Create an OpenGL context
- m_context = new QOpenGLContext;
- m_context->create();
-
- // Setup scene and render it
- initializeGL();
- paintGL();
- }
-
- void MyGLWindow::initializeGL()
- {
- m_context->makeCurrent(this);
- initializeOpenGLFunctions();
- }
- \endcode
+ \snippet code/src_gui_opengl_qopenglfunctions.cpp 0
The \c{paintGL()} function can then use any of the OpenGL ES 2.0
functions without explicit resolution, such as glActiveTexture()
in the following example:
- \code
- void MyGLWindow::paintGL()
- {
- m_context->makeCurrent(this);
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, textureId);
- ...
- m_context->swapBuffers(this);
- m_context->doneCurrent();
- }
- \endcode
+ \snippet code/src_gui_opengl_qopenglfunctions.cpp 1
QOpenGLFunctions can also be used directly for ad-hoc invocation
of OpenGL ES 2.0 functions on all platforms:
- \code
- QOpenGLFunctions glFuncs(QOpenGLContext::currentContext());
- glFuncs.glActiveTexture(GL_TEXTURE1);
- \endcode
+ \snippet code/src_gui_opengl_qopenglfunctions.cpp 2
An alternative approach is to query the context's associated
QOpenGLFunctions instance. This is somewhat faster than the previous
@@ -156,10 +110,7 @@ void CLASS::init(QOpenGLContext *context) \
resolving happens only once for a given context, regardless of the number of
QOpenGLFunctions instances initialized for it.
- \code
- QOpenGLFunctions *glFuncs = QOpenGLContext::currentContext()->functions();
- glFuncs->glActiveTexture(GL_TEXTURE1);
- \endcode
+ \snippet code/src_gui_opengl_qopenglfunctions.cpp 3
QOpenGLFunctions provides wrappers for all OpenGL ES 2.0
functions, including the common subset of OpenGL 1.x and ES
@@ -174,10 +125,7 @@ void CLASS::init(QOpenGLContext *context) \
feature. For example, the following checks if non power of two
textures are available:
- \code
- QOpenGLFunctions funcs(QOpenGLContext::currentContext());
- bool npot = funcs.hasOpenGLFeature(QOpenGLFunctions::NPOTTextures);
- \endcode
+ \snippet code/src_gui_opengl_qopenglfunctions.cpp 4
\sa QOpenGLContext, QSurfaceFormat
*/
@@ -294,9 +242,19 @@ QOpenGLExtensions::QOpenGLExtensions(QOpenGLContext *context)
static int qt_gl_resolve_features()
{
QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ QOpenGLExtensionMatcher extensions;
+ int features = 0;
+ if ((extensions.match("GL_KHR_blend_equation_advanced")
+ || extensions.match("GL_NV_blend_equation_advanced")) &&
+ (extensions.match("GL_KHR_blend_equation_advanced_coherent")
+ || extensions.match("GL_NV_blend_equation_advanced_coherent"))) {
+ // We need both the advanced equations and the coherency for us
+ // to be able to easily use the new blend equations
+ features |= QOpenGLFunctions::BlendEquationAdvanced;
+ }
if (ctx->isOpenGLES()) {
// OpenGL ES
- int features = QOpenGLFunctions::Multitexture |
+ features |= QOpenGLFunctions::Multitexture |
QOpenGLFunctions::Shaders |
QOpenGLFunctions::Buffers |
QOpenGLFunctions::Framebuffers |
@@ -308,7 +266,6 @@ static int qt_gl_resolve_features()
QOpenGLFunctions::CompressedTextures |
QOpenGLFunctions::Multisample |
QOpenGLFunctions::StencilSeparate;
- QOpenGLExtensionMatcher extensions;
if (extensions.match("GL_IMG_texture_npot"))
features |= QOpenGLFunctions::NPOTTextures;
if (extensions.match("GL_OES_texture_npot"))
@@ -320,14 +277,18 @@ static int qt_gl_resolve_features()
if (!(renderer && strstr(renderer, "Mesa")))
features |= QOpenGLFunctions::TextureRGFormats;
}
- if (ctx->format().majorVersion() >= 3)
+ if (ctx->format().majorVersion() >= 3) {
features |= QOpenGLFunctions::MultipleRenderTargets;
+ if (ctx->format().minorVersion() >= 2 && extensions.match("GL_KHR_blend_equation_advanced_coherent")) {
+ // GL_KHR_blend_equation_advanced is included in OpenGL ES/3.2
+ features |= QOpenGLFunctions::BlendEquationAdvanced;
+ }
+ }
return features;
} else {
// OpenGL
- int features = QOpenGLFunctions::TextureRGFormats;
+ features |= QOpenGLFunctions::TextureRGFormats;
QSurfaceFormat format = QOpenGLContext::currentContext()->format();
- QOpenGLExtensionMatcher extensions;
if (format.majorVersion() >= 3)
features |= QOpenGLFunctions::Framebuffers | QOpenGLFunctions::MultipleRenderTargets;
@@ -411,6 +372,8 @@ static int qt_gl_resolve_extensions()
extensions |= QOpenGLExtensions::NVFloatBuffer;
if (extensionMatcher.match("GL_ARB_pixel_buffer_object"))
extensions |= QOpenGLExtensions::PixelBufferObject;
+ if (extensionMatcher.match("GL_ARB_texture_swizzle") || extensionMatcher.match("GL_EXT_texture_swizzle"))
+ extensions |= QOpenGLExtensions::TextureSwizzle;
if (ctx->isOpenGLES()) {
if (format.majorVersion() >= 2)
@@ -423,7 +386,8 @@ static int qt_gl_resolve_extensions()
| QOpenGLExtensions::MapBufferRange
| QOpenGLExtensions::FramebufferBlit
| QOpenGLExtensions::FramebufferMultisample
- | QOpenGLExtensions::Sized8Formats;
+ | QOpenGLExtensions::Sized8Formats
+ | QOpenGLExtensions::TextureSwizzle;
} else {
// Recognize features by extension name.
if (extensionMatcher.match("GL_OES_packed_depth_stencil"))
@@ -449,6 +413,17 @@ static int qt_gl_resolve_extensions()
// We don't match GL_APPLE_texture_format_BGRA8888 here because it has different semantics.
if (extensionMatcher.match("GL_IMG_texture_format_BGRA8888") || extensionMatcher.match("GL_EXT_texture_format_BGRA8888"))
extensions |= QOpenGLExtensions::BGRATextureFormat;
+#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
+ QString *deviceName =
+ static_cast<QString *>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("AndroidDeviceName"));
+ static bool wrongfullyReportsBgra8888Support = deviceName != 0
+ && (deviceName->compare(QLatin1String("samsung SM-T211"), Qt::CaseInsensitive) == 0
+ || deviceName->compare(QLatin1String("samsung SM-T210"), Qt::CaseInsensitive) == 0
+ || deviceName->compare(QLatin1String("samsung SM-T215"), Qt::CaseInsensitive) == 0);
+ if (wrongfullyReportsBgra8888Support)
+ extensions &= ~QOpenGLExtensions::BGRATextureFormat;
+#endif
+
if (extensionMatcher.match("GL_EXT_discard_framebuffer"))
extensions |= QOpenGLExtensions::DiscardFramebuffer;
if (extensionMatcher.match("GL_EXT_texture_norm16"))
@@ -482,6 +457,9 @@ static int qt_gl_resolve_extensions()
if (format.version() >= qMakePair(3, 2) || extensionMatcher.match("GL_ARB_geometry_shader4"))
extensions |= QOpenGLExtensions::GeometryShaders;
+ if (format.version() >= qMakePair(3, 3))
+ extensions |= QOpenGLExtensions::TextureSwizzle;
+
if (extensionMatcher.match("GL_ARB_map_buffer_range"))
extensions |= QOpenGLExtensions::MapBufferRange;
diff --git a/src/gui/opengl/qopenglfunctions.h b/src/gui/opengl/qopenglfunctions.h
index 1a43f13d9b..00287b0665 100644
--- a/src/gui/opengl/qopenglfunctions.h
+++ b/src/gui/opengl/qopenglfunctions.h
@@ -277,7 +277,8 @@ public:
NPOTTextureRepeat = 0x2000,
FixedFunctionPipeline = 0x4000,
TextureRGFormats = 0x8000,
- MultipleRenderTargets = 0x10000
+ MultipleRenderTargets = 0x10000,
+ BlendEquationAdvanced = 0x20000,
};
Q_DECLARE_FLAGS(OpenGLFeatures, OpenGLFeature)
diff --git a/src/gui/opengl/qopenglpaintengine.cpp b/src/gui/opengl/qopenglpaintengine.cpp
index 6a89089f18..001cb839fa 100644
--- a/src/gui/opengl/qopenglpaintengine.cpp
+++ b/src/gui/opengl/qopenglpaintengine.cpp
@@ -87,8 +87,27 @@
#include <QDebug>
-QT_BEGIN_NAMESPACE
+#ifndef GL_KHR_blend_equation_advanced
+#define GL_KHR_blend_equation_advanced 1
+#define GL_MULTIPLY_KHR 0x9294
+#define GL_SCREEN_KHR 0x9295
+#define GL_OVERLAY_KHR 0x9296
+#define GL_DARKEN_KHR 0x9297
+#define GL_LIGHTEN_KHR 0x9298
+#define GL_COLORDODGE_KHR 0x9299
+#define GL_COLORBURN_KHR 0x929A
+#define GL_HARDLIGHT_KHR 0x929B
+#define GL_SOFTLIGHT_KHR 0x929C
+#define GL_DIFFERENCE_KHR 0x929E
+#define GL_EXCLUSION_KHR 0x92A0
+#endif /* GL_KHR_blend_equation_advanced */
+
+#ifndef GL_KHR_blend_equation_advanced_coherent
+#define GL_KHR_blend_equation_advanced_coherent 1
+#define GL_BLEND_ADVANCED_COHERENT_KHR 0x9285
+#endif /* GL_KHR_blend_equation_advanced_coherent */
+QT_BEGIN_NAMESPACE
Q_GUI_EXPORT QImage qt_imageForBrush(int brushStyle, bool invert);
@@ -244,7 +263,7 @@ GLuint QOpenGL2PaintEngineExPrivate::bindTexture(const QGradient &gradient)
struct ImageWithBindOptions
{
const QImage &image;
- QOpenGLTextureCache::BindOptions options;
+ QOpenGLTextureUploader::BindOptions options;
};
template<>
@@ -253,6 +272,12 @@ GLuint QOpenGL2PaintEngineExPrivate::bindTexture(const ImageWithBindOptions &ima
return QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, imageWithOptions.image, imageWithOptions.options);
}
+inline static bool isPowerOfTwo(int x)
+{
+ // Assumption: x >= 1
+ return x == (x & -x);
+}
+
void QOpenGL2PaintEngineExPrivate::updateBrushTexture()
{
Q_Q(QOpenGL2PaintEngineEx);
@@ -285,16 +310,18 @@ void QOpenGL2PaintEngineExPrivate::updateBrushTexture()
currentBrushImage = currentBrush.textureImage();
int max_texture_size = ctx->d_func()->maxTextureSize();
- if (currentBrushImage.width() > max_texture_size || currentBrushImage.height() > max_texture_size)
- currentBrushImage = currentBrushImage.scaled(max_texture_size, max_texture_size, Qt::KeepAspectRatio);
+ QSize newSize = currentBrushImage.size();
+ newSize = newSize.boundedTo(QSize(max_texture_size, max_texture_size));
+ if (!QOpenGLContext::currentContext()->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat)) {
+ if (!isPowerOfTwo(newSize.width()) || !isPowerOfTwo(newSize.height())) {
+ newSize.setHeight(qNextPowerOfTwo(newSize.height() - 1));
+ newSize.setWidth(qNextPowerOfTwo(newSize.width() - 1));
+ }
+ }
+ if (currentBrushImage.size() != newSize)
+ currentBrushImage = currentBrushImage.scaled(newSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
GLuint wrapMode = GL_REPEAT;
- if (QOpenGLContext::currentContext()->isOpenGLES()) {
- // OpenGL ES does not support GL_REPEAT wrap modes for NPOT textures. So instead,
- // we emulate GL_REPEAT by only taking the fractional part of the texture coords
- // in the qopenglslTextureBrushSrcFragmentShader program.
- wrapMode = GL_CLAMP_TO_EDGE;
- }
updateTexture(QT_BRUSH_TEXTURE_UNIT, currentBrushImage, wrapMode, filterMode, ForceUpdate);
}
@@ -498,6 +525,21 @@ void QOpenGL2PaintEngineExPrivate::updateCompositionMode()
// NOTE: The entire paint engine works on pre-multiplied data - which is why some of these
// composition modes look odd.
// qDebug() << "QOpenGL2PaintEngineExPrivate::updateCompositionMode() - Setting GL composition mode for " << q->state()->composition_mode;
+ if (ctx->functions()->hasOpenGLFeature(QOpenGLFunctions::BlendEquationAdvanced)) {
+ if (q->state()->composition_mode <= QPainter::CompositionMode_Plus) {
+ funcs.glDisable(GL_BLEND_ADVANCED_COHERENT_KHR);
+ funcs.glBlendEquation(GL_FUNC_ADD);
+ } else {
+ funcs.glEnable(GL_BLEND_ADVANCED_COHERENT_KHR);
+ }
+ shaderManager->setCompositionMode(q->state()->composition_mode);
+ } else {
+ if (q->state()->composition_mode > QPainter::CompositionMode_Plus) {
+ qWarning("Unsupported composition mode");
+ compositionModeDirty = false;
+ return;
+ }
+ }
switch(q->state()->composition_mode) {
case QPainter::CompositionMode_SourceOver:
funcs.glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
@@ -538,6 +580,39 @@ void QOpenGL2PaintEngineExPrivate::updateCompositionMode()
case QPainter::CompositionMode_Plus:
funcs.glBlendFunc(GL_ONE, GL_ONE);
break;
+ case QPainter::CompositionMode_Multiply:
+ funcs.glBlendEquation(GL_MULTIPLY_KHR);
+ break;
+ case QPainter::CompositionMode_Screen:
+ funcs.glBlendEquation(GL_SCREEN_KHR);
+ break;
+ case QPainter::CompositionMode_Overlay:
+ funcs.glBlendEquation(GL_OVERLAY_KHR);
+ break;
+ case QPainter::CompositionMode_Darken:
+ funcs.glBlendEquation(GL_DARKEN_KHR);
+ break;
+ case QPainter::CompositionMode_Lighten:
+ funcs.glBlendEquation(GL_LIGHTEN_KHR);
+ break;
+ case QPainter::CompositionMode_ColorDodge:
+ funcs.glBlendEquation(GL_COLORDODGE_KHR);
+ break;
+ case QPainter::CompositionMode_ColorBurn:
+ funcs.glBlendEquation(GL_COLORBURN_KHR);
+ break;
+ case QPainter::CompositionMode_HardLight:
+ funcs.glBlendEquation(GL_HARDLIGHT_KHR);
+ break;
+ case QPainter::CompositionMode_SoftLight:
+ funcs.glBlendEquation(GL_SOFTLIGHT_KHR);
+ break;
+ case QPainter::CompositionMode_Difference:
+ funcs.glBlendEquation(GL_DIFFERENCE_KHR);
+ break;
+ case QPainter::CompositionMode_Exclusion:
+ funcs.glBlendEquation(GL_EXCLUSION_KHR);
+ break;
default:
qWarning("Unsupported composition mode");
break;
@@ -1487,25 +1562,26 @@ void QOpenGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, c
ensureActive();
d->transferMode(ImageDrawingMode);
- QOpenGLTextureCache::BindOptions bindOption = QOpenGLTextureCache::PremultipliedAlphaBindOption;
+ QOpenGLTextureUploader::BindOptions bindOption = QOpenGLTextureUploader::PremultipliedAlphaBindOption;
// Use specialized bind for formats we have specialized shaders for.
switch (image.format()) {
case QImage::Format_RGBA8888:
case QImage::Format_ARGB32:
+ case QImage::Format_RGBA64:
d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::NonPremultipliedImageSrc);
bindOption = 0;
break;
case QImage::Format_Alpha8:
if (ctx->functions()->hasOpenGLFeature(QOpenGLFunctions::TextureRGFormats)) {
d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::AlphaImageSrc);
- bindOption = QOpenGLTextureCache::UseRedFor8BitBindOption;
+ bindOption = QOpenGLTextureUploader::UseRedFor8BitBindOption;
} else
d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::ImageSrc);
break;
case QImage::Format_Grayscale8:
if (ctx->functions()->hasOpenGLFeature(QOpenGLFunctions::TextureRGFormats)) {
d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::GrayscaleImageSrc);
- bindOption = QOpenGLTextureCache::UseRedFor8BitBindOption;
+ bindOption = QOpenGLTextureUploader::UseRedFor8BitBindOption;
} else
d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::ImageSrc);
break;
diff --git a/src/gui/opengl/qopenglprogrambinarycache.cpp b/src/gui/opengl/qopenglprogrambinarycache.cpp
index d16173df83..c96021a969 100644
--- a/src/gui/opengl/qopenglprogrambinarycache.cpp
+++ b/src/gui/opengl/qopenglprogrambinarycache.cpp
@@ -54,14 +54,19 @@ QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(DBG_SHADER_CACHE)
+#ifndef GL_CONTEXT_LOST
+#define GL_CONTEXT_LOST 0x0507
+#endif
+
#ifndef GL_PROGRAM_BINARY_LENGTH
#define GL_PROGRAM_BINARY_LENGTH 0x8741
#endif
const quint32 BINSHADER_MAGIC = 0x5174;
-const quint32 BINSHADER_VERSION = 0x2;
+const quint32 BINSHADER_VERSION = 0x3;
const quint32 BINSHADER_QTVERSION = QT_VERSION;
+namespace {
struct GLEnvInfo
{
GLEnvInfo();
@@ -70,6 +75,7 @@ struct GLEnvInfo
QByteArray glrenderer;
QByteArray glversion;
};
+}
GLEnvInfo::GLEnvInfo()
{
@@ -114,7 +120,7 @@ QString QOpenGLProgramBinaryCache::cacheFileName(const QByteArray &cacheKey) con
return m_cacheDir + QString::fromUtf8(cacheKey);
}
-#define BASE_HEADER_SIZE (int(3 * sizeof(quint32)))
+#define BASE_HEADER_SIZE (int(4 * sizeof(quint32)))
#define FULL_HEADER_SIZE(stringsSize) (BASE_HEADER_SIZE + 12 + stringsSize + 8)
#define PADDING_SIZE(fullHeaderSize) (((fullHeaderSize + 3) & ~3) - fullHeaderSize)
@@ -153,13 +159,21 @@ bool QOpenGLProgramBinaryCache::verifyHeader(const QByteArray &buf) const
qCDebug(DBG_SHADER_CACHE, "Qt version does not match");
return false;
}
+ if (readUInt(&p) != sizeof(quintptr)) {
+ qCDebug(DBG_SHADER_CACHE, "Architecture does not match");
+ return false;
+ }
return true;
}
bool QOpenGLProgramBinaryCache::setProgramBinary(uint programId, uint blobFormat, const void *p, uint blobSize)
{
QOpenGLExtraFunctions *funcs = QOpenGLContext::currentContext()->extraFunctions();
- while (funcs->glGetError() != GL_NO_ERROR) { }
+ while (true) {
+ GLenum error = funcs->glGetError();
+ if (error == GL_NO_ERROR || error == GL_CONTEXT_LOST)
+ break;
+ }
funcs->glProgramBinary(programId, blobFormat, p, blobSize);
GLenum err = funcs->glGetError();
@@ -335,7 +349,11 @@ void QOpenGLProgramBinaryCache::save(const QByteArray &cacheKey, uint programId)
QOpenGLExtraFunctions *funcs = QOpenGLContext::currentContext()->extraFunctions();
GLint blobSize = 0;
- while (funcs->glGetError() != GL_NO_ERROR) { }
+ while (true) {
+ GLenum error = funcs->glGetError();
+ if (error == GL_NO_ERROR || error == GL_CONTEXT_LOST)
+ break;
+ }
funcs->glGetProgramiv(programId, GL_PROGRAM_BINARY_LENGTH, &blobSize);
const int headerSize = FULL_HEADER_SIZE(info.glvendor.size() + info.glrenderer.size() + info.glversion.size());
@@ -357,6 +375,7 @@ void QOpenGLProgramBinaryCache::save(const QByteArray &cacheKey, uint programId)
writeUInt(&p, BINSHADER_MAGIC);
writeUInt(&p, BINSHADER_VERSION);
writeUInt(&p, BINSHADER_QTVERSION);
+ writeUInt(&p, sizeof(quintptr));
writeStr(&p, info.glvendor);
writeStr(&p, info.glrenderer);
diff --git a/src/gui/opengl/qopenglshaderprogram.cpp b/src/gui/opengl/qopenglshaderprogram.cpp
index 2ae9c6d327..c39177080d 100644
--- a/src/gui/opengl/qopenglshaderprogram.cpp
+++ b/src/gui/opengl/qopenglshaderprogram.cpp
@@ -39,7 +39,7 @@
#include "qopenglshaderprogram.h"
#include "qopenglprogrambinarycache_p.h"
-#include "qopenglfunctions.h"
+#include "qopenglextrafunctions.h"
#include "private/qopenglcontext_p.h"
#include <QtCore/private/qobject_p.h>
#include <QtCore/qdebug.h>
@@ -170,13 +170,13 @@ QT_BEGIN_NAMESPACE
\value Vertex Vertex shader written in the OpenGL Shading Language (GLSL).
\value Fragment Fragment shader written in the OpenGL Shading Language (GLSL).
\value Geometry Geometry shaders written in the OpenGL Shading Language (GLSL)
- based on the OpenGL core feature (requires OpenGL >= 3.2).
+ (requires OpenGL >= 3.2 or OpenGL ES >= 3.2).
\value TessellationControl Tessellation control shaders written in the OpenGL
- shading language (GLSL), based on the core feature (requires OpenGL >= 4.0).
+ shading language (GLSL) (requires OpenGL >= 4.0 or OpenGL ES >= 3.2).
\value TessellationEvaluation Tessellation evaluation shaders written in the OpenGL
- shading language (GLSL), based on the core feature (requires OpenGL >= 4.0).
- \value Compute Compute shaders written in the OpenGL shading language (GLSL),
- based on the core feature (requires OpenGL >= 4.3).
+ shading language (GLSL) (requires OpenGL >= 4.0 or OpenGL ES >= 3.2).
+ \value Compute Compute shaders written in the OpenGL shading language (GLSL)
+ (requires OpenGL >= 4.3 or OpenGL ES >= 3.1).
*/
Q_LOGGING_CATEGORY(DBG_SHADER_CACHE, "qt.opengl.diskcache")
@@ -223,26 +223,18 @@ static inline bool isFormatGLES(const QSurfaceFormat &f)
static inline bool supportsGeometry(const QSurfaceFormat &f)
{
-#ifndef QT_OPENGL_ES_2
- if (!isFormatGLES(f))
- return (f.version() >= qMakePair<int, int>(3, 2));
- else
- return false;
-#else
- Q_UNUSED(f);
- return false;
-#endif
+ return f.version() >= qMakePair(3, 2);
}
static inline bool supportsCompute(const QSurfaceFormat &f)
{
#ifndef QT_OPENGL_ES_2
if (!isFormatGLES(f))
- return (f.version() >= qMakePair<int, int>(4, 3));
+ return f.version() >= qMakePair(4, 3);
else
- return (f.version() >= qMakePair<int, int>(3, 1));
+ return f.version() >= qMakePair(3, 1);
#else
- return (f.version() >= qMakePair<int, int>(3, 1));
+ return f.version() >= qMakePair(3, 1);
#endif
}
@@ -250,12 +242,11 @@ static inline bool supportsTessellation(const QSurfaceFormat &f)
{
#ifndef QT_OPENGL_ES_2
if (!isFormatGLES(f))
- return (f.version() >= qMakePair<int, int>(4, 0));
+ return f.version() >= qMakePair(4, 0);
else
- return false;
+ return f.version() >= qMakePair(3, 2);
#else
- Q_UNUSED(f);
- return false;
+ return f.version() >= qMakePair(3, 2);
#endif
}
@@ -267,7 +258,7 @@ public:
: shaderGuard(0)
, shaderType(type)
, compiled(false)
- , glfuncs(new QOpenGLFunctions(ctx))
+ , glfuncs(new QOpenGLExtraFunctions(ctx))
, supportsGeometryShaders(false)
, supportsTessellationShaders(false)
, supportsComputeShaders(false)
@@ -286,7 +277,7 @@ public:
bool compiled;
QString log;
- QOpenGLFunctions *glfuncs;
+ QOpenGLExtraFunctions *glfuncs;
// Support for geometry shaders
bool supportsGeometryShaders;
@@ -496,6 +487,13 @@ static const char redefineHighp[] =
"#endif\n";
#endif
+// Boiler-plate header to have the layout attributes available we need later
+static const char blendEquationAdvancedHeader[] =
+ "#ifdef GL_KHR_blend_equation_advanced\n"
+ "#extension GL_ARB_fragment_coord_conventions : enable\n"
+ "#extension GL_KHR_blend_equation_advanced : enable\n"
+ "#endif\n";
+
struct QVersionDirectivePosition
{
Q_DECL_CONSTEXPR QVersionDirectivePosition(int position = 0, int line = -1)
@@ -636,6 +634,10 @@ bool QOpenGLShader::compileSourceCode(const char *source)
}
}
}
+ if (d->shaderType == Fragment) {
+ sourceChunks.append(blendEquationAdvancedHeader);
+ sourceChunkLengths.append(GLint(sizeof(blendEquationAdvancedHeader) - 1));
+ }
// The precision qualifiers are useful on OpenGL/ES systems,
// but usually not present on desktop systems.
@@ -791,7 +793,7 @@ public:
, linked(false)
, inited(false)
, removingShaders(false)
- , glfuncs(new QOpenGLFunctions)
+ , glfuncs(new QOpenGLExtraFunctions)
#ifndef QT_OPENGL_ES_2
, tessellationFuncs(0)
#endif
@@ -809,10 +811,9 @@ public:
QList<QOpenGLShader *> shaders;
QList<QOpenGLShader *> anonShaders;
- QOpenGLFunctions *glfuncs;
-
+ QOpenGLExtraFunctions *glfuncs;
#ifndef QT_OPENGL_ES_2
- // Tessellation shader support
+ // for tessellation features not in GLES 3.2
QOpenGLFunctions_4_0_Core *tessellationFuncs;
#endif
@@ -902,10 +903,7 @@ bool QOpenGLShaderProgram::init()
d->glfuncs->initializeOpenGLFunctions();
#ifndef QT_OPENGL_ES_2
- // Resolve OpenGL 4 functions for tessellation shader support
- QSurfaceFormat format = context->format();
- if (!context->isOpenGLES()
- && format.version() >= qMakePair<int, int>(4, 0)) {
+ if (!context->isOpenGLES() && context->format().version() >= qMakePair(4, 0)) {
d->tessellationFuncs = context->versionFunctions<QOpenGLFunctions_4_0_Core>();
d->tessellationFuncs->initializeOpenGLFunctions();
}
@@ -3497,13 +3495,8 @@ int QOpenGLShaderProgram::maxGeometryOutputVertices() const
*/
void QOpenGLShaderProgram::setPatchVertexCount(int count)
{
-#ifndef QT_OPENGL_ES_2
Q_D(QOpenGLShaderProgram);
- if (d->tessellationFuncs)
- d->tessellationFuncs->glPatchParameteri(GL_PATCH_VERTICES, count);
-#else
- Q_UNUSED(count);
-#endif
+ d->glfuncs->glPatchParameteri(GL_PATCH_VERTICES, count);
}
/*!
@@ -3516,15 +3509,10 @@ void QOpenGLShaderProgram::setPatchVertexCount(int count)
*/
int QOpenGLShaderProgram::patchVertexCount() const
{
-#ifndef QT_OPENGL_ES_2
int patchVertices = 0;
Q_D(const QOpenGLShaderProgram);
- if (d->tessellationFuncs)
- d->tessellationFuncs->glGetIntegerv(GL_PATCH_VERTICES, &patchVertices);
+ d->glfuncs->glGetIntegerv(GL_PATCH_VERTICES, &patchVertices);
return patchVertices;
-#else
- return 0;
-#endif
}
/*!
@@ -3542,6 +3530,9 @@ int QOpenGLShaderProgram::patchVertexCount() const
function when needed, as QOpenGLShaderProgram will not apply this for
you. This is purely a convenience function.
+ \note This function is only available with OpenGL >= 4.0 and is not supported
+ with OpenGL ES 3.2.
+
\sa defaultOuterTessellationLevels(), setDefaultInnerTessellationLevels()
*/
void QOpenGLShaderProgram::setDefaultOuterTessellationLevels(const QVector<float> &levels)
@@ -3579,6 +3570,9 @@ void QOpenGLShaderProgram::setDefaultOuterTessellationLevels(const QVector<float
\note This returns the global OpenGL state value. It is not specific to
this QOpenGLShaderProgram instance.
+ \note This function is only supported with OpenGL >= 4.0 and will not
+ return valid results with OpenGL ES 3.2.
+
\sa setDefaultOuterTessellationLevels(), defaultInnerTessellationLevels()
*/
QVector<float> QOpenGLShaderProgram::defaultOuterTessellationLevels() const
@@ -3609,6 +3603,9 @@ QVector<float> QOpenGLShaderProgram::defaultOuterTessellationLevels() const
function when needed, as QOpenGLShaderProgram will not apply this for
you. This is purely a convenience function.
+ \note This function is only available with OpenGL >= 4.0 and is not supported
+ with OpenGL ES 3.2.
+
\sa defaultInnerTessellationLevels(), setDefaultOuterTessellationLevels()
*/
void QOpenGLShaderProgram::setDefaultInnerTessellationLevels(const QVector<float> &levels)
@@ -3646,6 +3643,9 @@ void QOpenGLShaderProgram::setDefaultInnerTessellationLevels(const QVector<float
\note This returns the global OpenGL state value. It is not specific to
this QOpenGLShaderProgram instance.
+ \note This function is only supported with OpenGL >= 4.0 and will not
+ return valid results with OpenGL ES 3.2.
+
\sa setDefaultInnerTessellationLevels(), defaultOuterTessellationLevels()
*/
QVector<float> QOpenGLShaderProgram::defaultInnerTessellationLevels() const
diff --git a/src/gui/opengl/qopengltexturecache.cpp b/src/gui/opengl/qopengltexturecache.cpp
index 27aa8db33a..8de0b25fee 100644
--- a/src/gui/opengl/qopengltexturecache.cpp
+++ b/src/gui/opengl/qopengltexturecache.cpp
@@ -38,39 +38,14 @@
****************************************************************************/
#include "qopengltexturecache_p.h"
+#include "qopengltextureuploader_p.h"
#include <qmath.h>
#include <qopenglfunctions.h>
-#include <private/qopenglcontext_p.h>
-#include <private/qopenglextensions_p.h>
#include <private/qimagepixmapcleanuphooks_p.h>
#include <qpa/qplatformpixmap.h>
QT_BEGIN_NAMESPACE
-#ifndef GL_RED
-#define GL_RED 0x1903
-#endif
-
-#ifndef GL_RGB10_A2
-#define GL_RGB10_A2 0x8059
-#endif
-
-#ifndef GL_BGR
-#define GL_BGR 0x80E0
-#endif
-
-#ifndef GL_BGRA
-#define GL_BGRA 0x80E1
-#endif
-
-#ifndef GL_UNSIGNED_INT_8_8_8_8_REV
-#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
-#endif
-
-#ifndef GL_UNSIGNED_INT_2_10_10_10_REV
-#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
-#endif
-
class QOpenGLTextureCacheWrapper
{
public:
@@ -130,7 +105,7 @@ QOpenGLTextureCache::~QOpenGLTextureCache()
{
}
-GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QPixmap &pixmap, BindOptions options)
+GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QPixmap &pixmap, QOpenGLTextureUploader::BindOptions options)
{
if (pixmap.isNull())
return 0;
@@ -153,7 +128,7 @@ GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QPixmap &
return id;
}
-GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QImage &image, BindOptions options)
+GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QImage &image, QOpenGLTextureUploader::BindOptions options)
{
if (image.isNull())
return 0;
@@ -170,16 +145,8 @@ GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QImage &i
}
QImage img = image;
- if (!context->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextures)) {
- // Scale the pixmap if needed. GL textures needs to have the
- // dimensions 2^n+2(border) x 2^m+2(border), unless we're using GL
- // 2.0 or use the GL_TEXTURE_RECTANGLE texture target
- int tx_w = qNextPowerOfTwo(image.width() - 1);
- int tx_h = qNextPowerOfTwo(image.height() - 1);
- if (tx_w != image.width() || tx_h != image.height()) {
- img = img.scaled(tx_w, tx_h);
- }
- }
+ if (!context->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextures))
+ options |= QOpenGLTextureUploader::PowerOfTwoBindOption;
GLuint id = bindTexture(context, key, img, options);
if (id > 0)
@@ -188,164 +155,16 @@ GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QImage &i
return id;
}
-GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, qint64 key, const QImage &image, BindOptions options)
+GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, qint64 key, const QImage &image, QOpenGLTextureUploader::BindOptions options)
{
GLuint id;
QOpenGLFunctions *funcs = context->functions();
funcs->glGenTextures(1, &id);
funcs->glBindTexture(GL_TEXTURE_2D, id);
- QImage tx;
- GLenum externalFormat;
- GLenum internalFormat;
- GLuint pixelType;
- QImage::Format targetFormat = QImage::Format_Invalid;
- const bool isOpenGL12orBetter = !context->isOpenGLES() && (context->format().majorVersion() >= 2 || context->format().minorVersion() >= 2);
-
- switch (image.format()) {
- case QImage::Format_RGB32:
- case QImage::Format_ARGB32:
- case QImage::Format_ARGB32_Premultiplied:
- if (isOpenGL12orBetter) {
- externalFormat = GL_BGRA;
- internalFormat = GL_RGBA;
- pixelType = GL_UNSIGNED_INT_8_8_8_8_REV;
- } else {
-#if Q_BYTE_ORDER == Q_BIG_ENDIAN
- // Without GL_UNSIGNED_INT_8_8_8_8_REV, BGRA only matches ARGB on little endian.
- break;
-#endif
- if (static_cast<QOpenGLExtensions*>(context->functions())->hasOpenGLExtension(QOpenGLExtensions::BGRATextureFormat)) {
- // GL_EXT_bgra or GL_EXT_texture_format_BGRA8888 extensions.
- if (context->isOpenGLES()) {
- // The GL_EXT_texture_format_BGRA8888 extension requires the internal format to match the external.
- externalFormat = internalFormat = GL_BGRA;
- } else {
- // OpenGL BGRA/BGR format is not allowed as an internal format
- externalFormat = GL_BGRA;
- internalFormat = GL_RGBA;
- }
- pixelType = GL_UNSIGNED_BYTE;
- } else if (context->isOpenGLES() && context->hasExtension(QByteArrayLiteral("GL_APPLE_texture_format_BGRA8888"))) {
- // Is only allowed as an external format like OpenGL.
- externalFormat = GL_BGRA;
- internalFormat = GL_RGBA;
- pixelType = GL_UNSIGNED_BYTE;
- } else {
- // No support for direct ARGB32 upload.
- break;
- }
- }
- targetFormat = image.format();
- break;
- case QImage::Format_BGR30:
- case QImage::Format_A2BGR30_Premultiplied:
- if (isOpenGL12orBetter || (context->isOpenGLES() && context->format().majorVersion() >= 3)) {
- pixelType = GL_UNSIGNED_INT_2_10_10_10_REV;
- externalFormat = GL_RGBA;
- internalFormat = GL_RGB10_A2;
- targetFormat = image.format();
- }
- break;
- case QImage::Format_RGB30:
- case QImage::Format_A2RGB30_Premultiplied:
- if (isOpenGL12orBetter) {
- pixelType = GL_UNSIGNED_INT_2_10_10_10_REV;
- externalFormat = GL_BGRA;
- internalFormat = GL_RGB10_A2;
- targetFormat = image.format();
- } else if (context->isOpenGLES() && context->format().majorVersion() >= 3) {
- pixelType = GL_UNSIGNED_INT_2_10_10_10_REV;
- externalFormat = GL_RGBA;
- internalFormat = GL_RGB10_A2;
- targetFormat = QImage::Format_A2BGR30_Premultiplied;
- }
- break;
- case QImage::Format_RGB444:
- case QImage::Format_RGB555:
- case QImage::Format_RGB16:
- if (isOpenGL12orBetter || context->isOpenGLES()) {
- externalFormat = internalFormat = GL_RGB;
- pixelType = GL_UNSIGNED_SHORT_5_6_5;
- targetFormat = QImage::Format_RGB16;
- }
- break;
- case QImage::Format_RGB666:
- case QImage::Format_RGB888:
- externalFormat = internalFormat = GL_RGB;
- pixelType = GL_UNSIGNED_BYTE;
- targetFormat = QImage::Format_RGB888;
- break;
- case QImage::Format_RGBX8888:
- case QImage::Format_RGBA8888:
- case QImage::Format_RGBA8888_Premultiplied:
- externalFormat = internalFormat = GL_RGBA;
- pixelType = GL_UNSIGNED_BYTE;
- targetFormat = image.format();
- break;
- case QImage::Format_Indexed8:
- if (options & UseRedFor8BitBindOption) {
- externalFormat = internalFormat = GL_RED;
- pixelType = GL_UNSIGNED_BYTE;
- targetFormat = image.format();
- }
- break;
- case QImage::Format_Alpha8:
- if (options & UseRedFor8BitBindOption) {
- externalFormat = internalFormat = GL_RED;
- pixelType = GL_UNSIGNED_BYTE;
- targetFormat = image.format();
- } else if (context->isOpenGLES() || context->format().profile() != QSurfaceFormat::CoreProfile) {
- externalFormat = internalFormat = GL_ALPHA;
- pixelType = GL_UNSIGNED_BYTE;
- targetFormat = image.format();
- }
- break;
- case QImage::Format_Grayscale8:
- if (options & UseRedFor8BitBindOption) {
- externalFormat = internalFormat = GL_RED;
- pixelType = GL_UNSIGNED_BYTE;
- targetFormat = image.format();
- } else if (context->isOpenGLES() || context->format().profile() != QSurfaceFormat::CoreProfile) {
- externalFormat = internalFormat = GL_LUMINANCE;
- pixelType = GL_UNSIGNED_BYTE;
- targetFormat = image.format();
- }
- break;
- default:
- break;
- }
-
- if (targetFormat == QImage::Format_Invalid) {
- externalFormat = internalFormat = GL_RGBA;
- pixelType = GL_UNSIGNED_BYTE;
- if (!image.hasAlphaChannel())
- targetFormat = QImage::Format_RGBX8888;
- else
- targetFormat = QImage::Format_RGBA8888;
- }
-
- if (options & PremultipliedAlphaBindOption) {
- if (targetFormat == QImage::Format_ARGB32)
- targetFormat = QImage::Format_ARGB32_Premultiplied;
- else if (targetFormat == QImage::Format_RGBA8888)
- targetFormat = QImage::Format_RGBA8888_Premultiplied;
- } else {
- if (targetFormat == QImage::Format_ARGB32_Premultiplied)
- targetFormat = QImage::Format_ARGB32;
- else if (targetFormat == QImage::Format_RGBA8888_Premultiplied)
- targetFormat = QImage::Format_RGBA8888;
- }
-
- if (image.format() != targetFormat)
- tx = image.convertToFormat(targetFormat);
- else
- tx = image;
-
- funcs->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, tx.width(), tx.height(), 0, externalFormat, pixelType, const_cast<const QImage &>(tx).bits());
+ int cost = QOpenGLTextureUploader::textureImage(GL_TEXTURE_2D, image, options);
- int cost = tx.width() * tx.height() * tx.depth() / (1024 * 8);
- m_cache.insert(key, new QOpenGLCachedTexture(id, options, context), cost);
+ m_cache.insert(key, new QOpenGLCachedTexture(id, options, context), cost / 1024);
return id;
}
@@ -371,7 +190,7 @@ static void freeTexture(QOpenGLFunctions *funcs, GLuint id)
funcs->glDeleteTextures(1, &id);
}
-QOpenGLCachedTexture::QOpenGLCachedTexture(GLuint id, QOpenGLTextureCache::BindOptions options, QOpenGLContext *context) : m_options(options)
+QOpenGLCachedTexture::QOpenGLCachedTexture(GLuint id, QOpenGLTextureUploader::BindOptions options, QOpenGLContext *context) : m_options(options)
{
m_resource = new QOpenGLSharedResourceGuard(context, id, freeTexture);
}
diff --git a/src/gui/opengl/qopengltexturecache_p.h b/src/gui/opengl/qopengltexturecache_p.h
index b9d7df91e3..88ef06e744 100644
--- a/src/gui/opengl/qopengltexturecache_p.h
+++ b/src/gui/opengl/qopengltexturecache_p.h
@@ -56,6 +56,7 @@
#include <QObject>
#include <QCache>
#include <private/qopenglcontext_p.h>
+#include <private/qopengltextureuploader_p.h>
#include <QtCore/qmutex.h>
QT_BEGIN_NAMESPACE
@@ -70,15 +71,10 @@ public:
QOpenGLTextureCache(QOpenGLContext *);
~QOpenGLTextureCache();
- enum BindOption {
- NoBindOption = 0x0000,
- PremultipliedAlphaBindOption = 0x0001,
- UseRedFor8BitBindOption = 0x0002,
- };
- Q_DECLARE_FLAGS(BindOptions, BindOption)
-
- GLuint bindTexture(QOpenGLContext *context, const QPixmap &pixmap, QOpenGLTextureCache::BindOptions options = PremultipliedAlphaBindOption);
- GLuint bindTexture(QOpenGLContext *context, const QImage &image, QOpenGLTextureCache::BindOptions options = PremultipliedAlphaBindOption);
+ GLuint bindTexture(QOpenGLContext *context, const QPixmap &pixmap,
+ QOpenGLTextureUploader::BindOptions options = QOpenGLTextureUploader::PremultipliedAlphaBindOption);
+ GLuint bindTexture(QOpenGLContext *context, const QImage &image,
+ QOpenGLTextureUploader::BindOptions options = QOpenGLTextureUploader::PremultipliedAlphaBindOption);
void invalidate(qint64 key);
@@ -86,26 +82,24 @@ public:
void freeResource(QOpenGLContext *ctx) override;
private:
- GLuint bindTexture(QOpenGLContext *context, qint64 key, const QImage &image, QOpenGLTextureCache::BindOptions options);
+ GLuint bindTexture(QOpenGLContext *context, qint64 key, const QImage &image, QOpenGLTextureUploader::BindOptions options);
QMutex m_mutex;
QCache<quint64, QOpenGLCachedTexture> m_cache;
};
-Q_DECLARE_OPERATORS_FOR_FLAGS(QOpenGLTextureCache::BindOptions)
-
class QOpenGLCachedTexture
{
public:
- QOpenGLCachedTexture(GLuint id, QOpenGLTextureCache::BindOptions options, QOpenGLContext *context);
+ QOpenGLCachedTexture(GLuint id, QOpenGLTextureUploader::BindOptions options, QOpenGLContext *context);
~QOpenGLCachedTexture() { m_resource->free(); }
GLuint id() const { return m_resource->id(); }
- QOpenGLTextureCache::BindOptions options() const { return m_options; }
+ QOpenGLTextureUploader::BindOptions options() const { return m_options; }
private:
QOpenGLSharedResourceGuard *m_resource;
- QOpenGLTextureCache::BindOptions m_options;
+ QOpenGLTextureUploader::BindOptions m_options;
};
QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopengltextureglyphcache.cpp b/src/gui/opengl/qopengltextureglyphcache.cpp
index 556d52ef99..e3cbba955d 100644
--- a/src/gui/opengl/qopengltextureglyphcache.cpp
+++ b/src/gui/opengl/qopengltextureglyphcache.cpp
@@ -344,15 +344,25 @@ void QOpenGLTextureGlyphCache::resizeTextureData(int width, int height)
{
QString source;
+#ifdef Q_OS_WASM
+ source.append(QLatin1String(isCoreProfile ? qopenglslUntransformedPositionVertexShader_core : qopenglslUntransformedPositionVertexShader));
+ source.append(QLatin1String(isCoreProfile ? qopenglslMainWithTexCoordsVertexShader_core : qopenglslMainWithTexCoordsVertexShader));
+#else
source.append(QLatin1String(isCoreProfile ? qopenglslMainWithTexCoordsVertexShader_core : qopenglslMainWithTexCoordsVertexShader));
source.append(QLatin1String(isCoreProfile ? qopenglslUntransformedPositionVertexShader_core : qopenglslUntransformedPositionVertexShader));
+#endif
m_blitProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, source);
}
{
QString source;
+#ifdef Q_OS_WASM
+ source.append(QLatin1String(isCoreProfile ? qopenglslImageSrcFragmentShader_core : qopenglslImageSrcFragmentShader));
+ source.append(QLatin1String(isCoreProfile ? qopenglslMainFragmentShader_core : qopenglslMainFragmentShader));
+#else
source.append(QLatin1String(isCoreProfile ? qopenglslMainFragmentShader_core : qopenglslMainFragmentShader));
source.append(QLatin1String(isCoreProfile ? qopenglslImageSrcFragmentShader_core : qopenglslImageSrcFragmentShader));
+#endif
m_blitProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, source);
}
diff --git a/src/gui/opengl/qopengltextureuploader.cpp b/src/gui/opengl/qopengltextureuploader.cpp
new file mode 100644
index 0000000000..2428baed93
--- /dev/null
+++ b/src/gui/opengl/qopengltextureuploader.cpp
@@ -0,0 +1,328 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qopengltextureuploader_p.h"
+
+#include <qimage.h>
+#include <qmath.h>
+#include <qopenglfunctions.h>
+#include <private/qopenglcontext_p.h>
+#include <private/qopenglextensions_p.h>
+
+#ifndef GL_RED
+#define GL_RED 0x1903
+#endif
+
+#ifndef GL_GREEN
+#define GL_GREEN 0x1904
+#endif
+
+#ifndef GL_BLUE
+#define GL_BLUE 0x1905
+#endif
+
+#ifndef GL_RGB10_A2
+#define GL_RGB10_A2 0x8059
+#endif
+
+#ifndef GL_RGBA16
+#define GL_RGBA16 0x805B
+#endif
+
+#ifndef GL_BGRA
+#define GL_BGRA 0x80E1
+#endif
+
+#ifndef GL_UNSIGNED_INT_8_8_8_8_REV
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#endif
+
+#ifndef GL_UNSIGNED_INT_2_10_10_10_REV
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#endif
+
+#ifndef GL_TEXTURE_SWIZZLE_RGBA
+#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
+#endif
+
+#ifndef GL_SRGB
+#define GL_SRGB 0x8C40
+#endif
+#ifndef GL_SRGB_ALPHA
+#define GL_SRGB_ALPHA 0x8C42
+#endif
+
+QT_BEGIN_NAMESPACE
+
+qsizetype QOpenGLTextureUploader::textureImage(GLenum target, const QImage &image, QOpenGLTextureUploader::BindOptions options, QSize maxSize)
+{
+ QOpenGLContext *context = QOpenGLContext::currentContext();
+ QOpenGLExtensions *funcs = static_cast<QOpenGLExtensions*>(context->functions());
+
+ QImage tx;
+ GLenum externalFormat;
+ GLenum internalFormat;
+ GLuint pixelType;
+ QImage::Format targetFormat = QImage::Format_Invalid;
+ const bool isOpenGL12orBetter = !context->isOpenGLES() && (context->format().majorVersion() >= 2 || context->format().minorVersion() >= 2);
+ const bool isOpenGLES3orBetter = context->isOpenGLES() && context->format().majorVersion() >= 3;
+ const bool sRgbBinding = (options & SRgbBindOption);
+ Q_ASSERT(isOpenGL12orBetter || context->isOpenGLES());
+ Q_ASSERT((options & (SRgbBindOption | UseRedFor8BitBindOption)) != (SRgbBindOption | UseRedFor8BitBindOption));
+
+ switch (image.format()) {
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ if (isOpenGL12orBetter) {
+ externalFormat = GL_BGRA;
+ internalFormat = GL_RGBA;
+ pixelType = GL_UNSIGNED_INT_8_8_8_8_REV;
+ } else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle) && false) {
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ GLint swizzle[4] = { GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA };
+ funcs->glTexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
+#else
+ GLint swizzle[4] = { GL_GREEN, GL_BLUE, GL_ALPHA, GL_RED };
+ funcs->glTexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
+#endif
+ externalFormat = internalFormat = GL_RGBA;
+ pixelType = GL_UNSIGNED_BYTE;
+ } else {
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ // Without GL_UNSIGNED_INT_8_8_8_8_REV, BGRA only matches ARGB on little endian.
+ if (funcs->hasOpenGLExtension(QOpenGLExtensions::BGRATextureFormat) && !sRgbBinding) {
+ // The GL_EXT_texture_format_BGRA8888 extension requires the internal format to match the external.
+ externalFormat = internalFormat = GL_BGRA;
+ pixelType = GL_UNSIGNED_BYTE;
+ } else if (context->isOpenGLES() && context->hasExtension(QByteArrayLiteral("GL_APPLE_texture_format_BGRA8888"))) {
+ // Is only allowed as an external format like OpenGL.
+ externalFormat = GL_BGRA;
+ internalFormat = GL_RGBA;
+ pixelType = GL_UNSIGNED_BYTE;
+ } else {
+ // No support for direct ARGB32 upload.
+ break;
+ }
+#else
+ // Big endian requires GL_UNSIGNED_INT_8_8_8_8_REV for ARGB to match BGRA
+ break;
+#endif
+ }
+ targetFormat = image.format();
+ break;
+ case QImage::Format_BGR30:
+ case QImage::Format_A2BGR30_Premultiplied:
+ if (sRgbBinding) {
+ // Always needs conversion
+ break;
+ } else if (isOpenGL12orBetter || isOpenGLES3orBetter) {
+ pixelType = GL_UNSIGNED_INT_2_10_10_10_REV;
+ externalFormat = GL_RGBA;
+ internalFormat = GL_RGB10_A2;
+ targetFormat = image.format();
+ }
+ break;
+ case QImage::Format_RGB30:
+ case QImage::Format_A2RGB30_Premultiplied:
+ if (sRgbBinding) {
+ // Always needs conversion
+ break;
+ } else if (isOpenGL12orBetter) {
+ pixelType = GL_UNSIGNED_INT_2_10_10_10_REV;
+ externalFormat = GL_BGRA;
+ internalFormat = GL_RGB10_A2;
+ targetFormat = image.format();
+ } else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle) && (isOpenGL12orBetter || isOpenGLES3orBetter)) {
+ pixelType = GL_UNSIGNED_INT_2_10_10_10_REV;
+ externalFormat = GL_RGBA;
+ internalFormat = GL_RGB10_A2;
+ GLint swizzle[4] = { GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA };
+ funcs->glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
+ targetFormat = image.format();
+ }
+ break;
+ case QImage::Format_RGB444:
+ case QImage::Format_RGB555:
+ case QImage::Format_RGB16:
+ if (isOpenGL12orBetter || context->isOpenGLES()) {
+ externalFormat = internalFormat = GL_RGB;
+ pixelType = GL_UNSIGNED_SHORT_5_6_5;
+ targetFormat = QImage::Format_RGB16;
+ }
+ break;
+ case QImage::Format_RGB666:
+ case QImage::Format_RGB888:
+ externalFormat = internalFormat = GL_RGB;
+ pixelType = GL_UNSIGNED_BYTE;
+ targetFormat = QImage::Format_RGB888;
+ break;
+ case QImage::Format_RGBX8888:
+ case QImage::Format_RGBA8888:
+ case QImage::Format_RGBA8888_Premultiplied:
+ externalFormat = internalFormat = GL_RGBA;
+ pixelType = GL_UNSIGNED_BYTE;
+ targetFormat = image.format();
+ break;
+ case QImage::Format_RGBX64:
+ case QImage::Format_RGBA64:
+ case QImage::Format_RGBA64_Premultiplied:
+ externalFormat = internalFormat = GL_RGBA;
+ if (isOpenGL12orBetter || (context->isOpenGLES() && context->format().majorVersion() >= 3))
+ internalFormat = GL_RGBA16;
+ pixelType = GL_UNSIGNED_SHORT;
+ targetFormat = image.format();
+ break;
+ case QImage::Format_Indexed8:
+ if (sRgbBinding) {
+ // Always needs conversion
+ break;
+ } else if (options & UseRedFor8BitBindOption) {
+ externalFormat = internalFormat = GL_RED;
+ pixelType = GL_UNSIGNED_BYTE;
+ targetFormat = image.format();
+ }
+ break;
+ case QImage::Format_Alpha8:
+ if (sRgbBinding) {
+ // Always needs conversion
+ break;
+ } else if (options & UseRedFor8BitBindOption) {
+ externalFormat = internalFormat = GL_RED;
+ pixelType = GL_UNSIGNED_BYTE;
+ targetFormat = image.format();
+ } else if (context->isOpenGLES() || context->format().profile() != QSurfaceFormat::CoreProfile) {
+ externalFormat = internalFormat = GL_ALPHA;
+ pixelType = GL_UNSIGNED_BYTE;
+ targetFormat = image.format();
+ } else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) {
+ GLint swizzle[4] = { GL_ZERO, GL_ZERO, GL_ZERO, GL_RED };
+ funcs->glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
+ externalFormat = internalFormat = GL_RED;
+ pixelType = GL_UNSIGNED_BYTE;
+ targetFormat = image.format();
+ }
+ break;
+ case QImage::Format_Grayscale8:
+ if (sRgbBinding) {
+ // Always needs conversion
+ break;
+ } else if (options & UseRedFor8BitBindOption) {
+ externalFormat = internalFormat = GL_RED;
+ pixelType = GL_UNSIGNED_BYTE;
+ targetFormat = image.format();
+ } else if (context->isOpenGLES() || context->format().profile() != QSurfaceFormat::CoreProfile) {
+ externalFormat = internalFormat = GL_LUMINANCE;
+ pixelType = GL_UNSIGNED_BYTE;
+ targetFormat = image.format();
+ } else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) {
+ GLint swizzle[4] = { GL_RED, GL_RED, GL_RED, GL_ONE };
+ funcs->glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
+ externalFormat = internalFormat = GL_RED;
+ pixelType = GL_UNSIGNED_BYTE;
+ targetFormat = image.format();
+ }
+ break;
+ default:
+ break;
+ }
+
+ // If no direct upload was detected above, convert to RGBA8888 and upload that
+ if (targetFormat == QImage::Format_Invalid) {
+ externalFormat = internalFormat = GL_RGBA;
+ pixelType = GL_UNSIGNED_BYTE;
+ if (!image.hasAlphaChannel())
+ targetFormat = QImage::Format_RGBX8888;
+ else
+ targetFormat = QImage::Format_RGBA8888;
+ }
+
+ if (options & PremultipliedAlphaBindOption) {
+ if (targetFormat == QImage::Format_ARGB32)
+ targetFormat = QImage::Format_ARGB32_Premultiplied;
+ else if (targetFormat == QImage::Format_RGBA8888)
+ targetFormat = QImage::Format_RGBA8888_Premultiplied;
+ else if (targetFormat == QImage::Format_RGBA64)
+ targetFormat = QImage::Format_RGBA64_Premultiplied;
+ } else {
+ if (targetFormat == QImage::Format_ARGB32_Premultiplied)
+ targetFormat = QImage::Format_ARGB32;
+ else if (targetFormat == QImage::Format_RGBA8888_Premultiplied)
+ targetFormat = QImage::Format_RGBA8888;
+ else if (targetFormat == QImage::Format_RGBA64_Premultiplied)
+ targetFormat = QImage::Format_RGBA64;
+ }
+
+ if (sRgbBinding) {
+ Q_ASSERT(internalFormat == GL_RGBA || internalFormat == GL_RGB);
+ if (image.hasAlphaChannel())
+ internalFormat = GL_SRGB_ALPHA;
+ else
+ internalFormat = GL_SRGB;
+ }
+
+ if (image.format() != targetFormat)
+ tx = image.convertToFormat(targetFormat);
+ else
+ tx = image;
+
+ QSize newSize = tx.size();
+ if (!maxSize.isEmpty())
+ newSize = newSize.boundedTo(maxSize);
+ if (options & PowerOfTwoBindOption) {
+ newSize.setWidth(qNextPowerOfTwo(newSize.width() - 1));
+ newSize.setHeight(qNextPowerOfTwo(newSize.height() - 1));
+ }
+
+ if (newSize != tx.size())
+ tx = tx.scaled(newSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+
+ // Handle cases where the QImage is actually a sub image of its image data:
+ qsizetype naturalBpl = ((qsizetype(tx.width()) * tx.depth() + 31) >> 5) << 2;
+ if (tx.bytesPerLine() != naturalBpl)
+ tx = tx.copy(tx.rect());
+
+ funcs->glTexImage2D(target, 0, internalFormat, tx.width(), tx.height(), 0, externalFormat, pixelType, tx.constBits());
+
+ qsizetype cost = qint64(tx.width()) * tx.height() * tx.depth() / 8;
+
+ return cost;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopengltextureuploader_p.h b/src/gui/opengl/qopengltextureuploader_p.h
new file mode 100644
index 0000000000..d758b3787b
--- /dev/null
+++ b/src/gui/opengl/qopengltextureuploader_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// 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.
+//
+
+#ifndef QOPENGLTEXTUREUPLOADER_P_H
+#define QOPENGLTEXTUREUPLOADER_P_H
+
+#include <QtCore/qsize.h>
+#include <QtGui/private/qtguiglobal_p.h>
+#include <QtGui/private/qopenglcontext_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QImage;
+
+class Q_GUI_EXPORT QOpenGLTextureUploader
+{
+public:
+ enum BindOption {
+ NoBindOption = 0x0000,
+ PremultipliedAlphaBindOption = 0x0001,
+ UseRedFor8BitBindOption = 0x0002,
+ SRgbBindOption = 0x0004,
+ PowerOfTwoBindOption = 0x0008
+ };
+ Q_DECLARE_FLAGS(BindOptions, BindOption)
+ Q_FLAGS(BindOptions)
+
+ static qsizetype textureImage(GLenum target, const QImage &image, BindOptions options, QSize maxSize = QSize());
+
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QOpenGLTextureUploader::BindOptions)
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/gui/painting/WEBGRADIENTS_LICENSE.txt b/src/gui/painting/WEBGRADIENTS_LICENSE.txt
new file mode 100644
index 0000000000..1a4d527a4d
--- /dev/null
+++ b/src/gui/painting/WEBGRADIENTS_LICENSE.txt
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 itmeo
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index 29bef14f0c..c3585a4647 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -99,8 +99,13 @@ SOURCES += \
painting/qplatformbackingstore.cpp \
painting/qpathsimplifier.cpp
+webgradients.files = painting/webgradients.binaryjson
+webgradients.prefix = qgradient
+webgradients.base = painting
+
RESOURCES += \
- painting/qpdf.qrc
+ painting/qpdf.qrc \
+ webgradients
darwin {
HEADERS += painting/qcoregraphics_p.h
@@ -122,7 +127,7 @@ SSE2_SOURCES += painting/qdrawhelper_sse2.cpp
SSSE3_SOURCES += painting/qdrawhelper_ssse3.cpp
SSE4_1_SOURCES += painting/qdrawhelper_sse4.cpp \
painting/qimagescale_sse4.cpp
-AVX2_SOURCES += painting/qdrawhelper_avx2.cpp
+ARCH_HASWELL_SOURCES += painting/qdrawhelper_avx2.cpp
NEON_SOURCES += painting/qdrawhelper_neon.cpp painting/qimagescale_neon.cpp
NEON_HEADERS += painting/qdrawhelper_neon_p.h
diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp
index a4a091a29f..2dd5144e40 100644
--- a/src/gui/painting/qblendfunctions.cpp
+++ b/src/gui/painting/qblendfunctions.cpp
@@ -430,28 +430,28 @@ struct Blend_RGB32_on_RGB32_ConstAlpha {
};
struct Blend_ARGB32_on_ARGB32_SourceAlpha {
- inline void write(quint32 *dst, quint32 src) {
- *dst = src + BYTE_MUL(*dst, qAlpha(~src));
+ inline void write(quint32 *dst, quint32 src)
+ {
+ blend_pixel(*dst, src);
}
inline void flush(void *) {}
};
struct Blend_ARGB32_on_ARGB32_SourceAndConstAlpha {
- inline Blend_ARGB32_on_ARGB32_SourceAndConstAlpha(quint32 alpha) {
+ inline Blend_ARGB32_on_ARGB32_SourceAndConstAlpha(quint32 alpha)
+ {
m_alpha = (alpha * 255) >> 8;
- m_ialpha = 255 - m_alpha;
}
- inline void write(quint32 *dst, quint32 src) {
- src = BYTE_MUL(src, m_alpha);
- *dst = src + BYTE_MUL(*dst, qAlpha(~src));
+ inline void write(quint32 *dst, quint32 src)
+ {
+ blend_pixel(*dst, src, m_alpha);
}
inline void flush(void *) {}
quint32 m_alpha;
- quint32 m_ialpha;
};
void qt_scale_image_rgb32_on_rgb32(uchar *destPixels, int dbpl,
diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp
index 5c13308d94..860653cc4c 100644
--- a/src/gui/painting/qbrush.cpp
+++ b/src/gui/painting/qbrush.cpp
@@ -46,9 +46,13 @@
#include "qvariant.h"
#include "qline.h"
#include "qdebug.h"
+#include <QtCore/qjsondocument.h>
+#include <QtCore/qjsonarray.h>
#include <QtCore/qcoreapplication.h>
#include "private/qhexstring_p.h"
#include <QtCore/qnumeric.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qmutex.h>
QT_BEGIN_NAMESPACE
@@ -1073,7 +1077,10 @@ QDataStream &operator<<(QDataStream &s, const QBrush &b)
s << type_as_int;
if (s.version() >= QDataStream::Qt_4_3) {
s << int(gradient->spread());
- s << int(gradient->coordinateMode());
+ QGradient::CoordinateMode co_mode = gradient->coordinateMode();
+ if (s.version() < QDataStream::Qt_5_12 && co_mode == QGradient::ObjectMode)
+ co_mode = QGradient::ObjectBoundingMode;
+ s << int(co_mode);
}
if (s.version() >= QDataStream::Qt_4_5)
@@ -1330,6 +1337,72 @@ QGradient::QGradient()
{
}
+/*!
+ \enum QGradient::Preset
+ \since 5.12
+
+ This enum specifies a set of predefined presets for QGradient,
+ based on the gradients from https://webgradients.com/.
+*/
+
+/*!
+ \fn QGradient::QGradient(QGradient::Preset preset)
+ \since 5.12
+
+ Constructs a gradient based on a predefined \a preset.
+
+ The coordinate mode of the resulting gradient is
+ QGradient::ObjectMode, allowing the preset
+ to be applied to arbitrary object sizes.
+*/
+QGradient::QGradient(Preset preset)
+ : QGradient()
+{
+ static QHash<int, QGradient> cachedPresets;
+ static QMutex cacheMutex;
+ QMutexLocker locker(&cacheMutex);
+ if (cachedPresets.contains(preset)) {
+ const QGradient &cachedPreset = cachedPresets.value(preset);
+ m_type = cachedPreset.m_type;
+ m_data = cachedPreset.m_data;
+ m_stops = cachedPreset.m_stops;
+ m_spread = cachedPreset.m_spread;
+ dummy = cachedPreset.dummy;
+ } else {
+ static QJsonDocument jsonPresets = []() {
+ QFile webGradients(QLatin1String(":/qgradient/webgradients.binaryjson"));
+ webGradients.open(QFile::ReadOnly);
+ return QJsonDocument::fromBinaryData(webGradients.readAll());
+ }();
+
+ const QJsonValue presetData = jsonPresets[preset - 1];
+ if (!presetData.isObject())
+ return;
+
+ m_type = LinearGradient;
+ setCoordinateMode(ObjectMode);
+ setSpread(PadSpread);
+
+ const QJsonValue start = presetData[QLatin1Literal("start")];
+ const QJsonValue end = presetData[QLatin1Literal("end")];
+ m_data.linear.x1 = start[QLatin1Literal("x")].toDouble();
+ m_data.linear.y1 = start[QLatin1Literal("y")].toDouble();
+ m_data.linear.x2 = end[QLatin1Literal("x")].toDouble();
+ m_data.linear.y2 = end[QLatin1Literal("y")].toDouble();
+
+ for (const QJsonValue &stop : presetData[QLatin1String("stops")].toArray()) {
+ setColorAt(stop[QLatin1Literal("position")].toDouble(),
+ QColor(QRgb(stop[QLatin1Literal("color")].toInt())));
+ }
+
+ cachedPresets.insert(preset, *this);
+ }
+}
+
+QT_END_NAMESPACE
+static void initGradientPresets() { Q_INIT_RESOURCE(qmake_webgradients); }
+Q_CONSTRUCTOR_FUNCTION(initGradientPresets);
+QT_BEGIN_NAMESPACE
/*!
\enum QGradient::Type
@@ -1492,14 +1565,19 @@ QGradientStops QGradient::stops() const
\value LogicalMode This is the default mode. The gradient coordinates
are specified logical space just like the object coordinates.
+ \value ObjectMode In this mode the gradient coordinates are
+ relative to the bounding rectangle of the object being drawn, with
+ (0,0) in the top left corner, and (1,1) in the bottom right corner
+ of the object's bounding rectangle. This value was added in Qt
+ 5.12.
\value StretchToDeviceMode In this mode the gradient coordinates
are relative to the bounding rectangle of the paint device,
with (0,0) in the top left corner, and (1,1) in the bottom right
corner of the paint device.
- \value ObjectBoundingMode In this mode the gradient coordinates are
- relative to the bounding rectangle of the object being drawn, with
- (0,0) in the top left corner, and (1,1) in the bottom right corner
- of the object's bounding rectangle.
+ \value ObjectBoundingMode This mode is the same as ObjectMode, except that
+ the {QBrush::transform()} {brush transform}, if any, is applied relative to
+ the logical space instead of the object space. This enum value is
+ deprecated and should not be used in new code.
*/
/*!
diff --git a/src/gui/painting/qbrush.h b/src/gui/painting/qbrush.h
index e5cff9cc9b..aee51c526d 100644
--- a/src/gui/painting/qbrush.h
+++ b/src/gui/painting/qbrush.h
@@ -194,7 +194,8 @@ public:
enum CoordinateMode {
LogicalMode,
StretchToDeviceMode,
- ObjectBoundingMode
+ ObjectBoundingMode,
+ ObjectMode
};
Q_ENUM(CoordinateMode)
@@ -203,7 +204,180 @@ public:
ComponentInterpolation
};
+ enum Preset {
+ WarmFlame = 1,
+ NightFade = 2,
+ SpringWarmth = 3,
+ JuicyPeach = 4,
+ YoungPassion = 5,
+ LadyLips = 6,
+ SunnyMorning = 7,
+ RainyAshville = 8,
+ FrozenDreams = 9,
+ WinterNeva = 10,
+ DustyGrass = 11,
+ TemptingAzure = 12,
+ HeavyRain = 13,
+ AmyCrisp = 14,
+ MeanFruit = 15,
+ DeepBlue = 16,
+ RipeMalinka = 17,
+ CloudyKnoxville = 18,
+ MalibuBeach = 19,
+ NewLife = 20,
+ TrueSunset = 21,
+ MorpheusDen = 22,
+ RareWind = 23,
+ NearMoon = 24,
+ WildApple = 25,
+ SaintPetersburg = 26,
+ PlumPlate = 28,
+ EverlastingSky = 29,
+ HappyFisher = 30,
+ Blessing = 31,
+ SharpeyeEagle = 32,
+ LadogaBottom = 33,
+ LemonGate = 34,
+ ItmeoBranding = 35,
+ ZeusMiracle = 36,
+ OldHat = 37,
+ StarWine = 38,
+ HappyAcid = 41,
+ AwesomePine = 42,
+ NewYork = 43,
+ ShyRainbow = 44,
+ MixedHopes = 46,
+ FlyHigh = 47,
+ StrongBliss = 48,
+ FreshMilk = 49,
+ SnowAgain = 50,
+ FebruaryInk = 51,
+ KindSteel = 52,
+ SoftGrass = 53,
+ GrownEarly = 54,
+ SharpBlues = 55,
+ ShadyWater = 56,
+ DirtyBeauty = 57,
+ GreatWhale = 58,
+ TeenNotebook = 59,
+ PoliteRumors = 60,
+ SweetPeriod = 61,
+ WideMatrix = 62,
+ SoftCherish = 63,
+ RedSalvation = 64,
+ BurningSpring = 65,
+ NightParty = 66,
+ SkyGlider = 67,
+ HeavenPeach = 68,
+ PurpleDivision = 69,
+ AquaSplash = 70,
+ SpikyNaga = 72,
+ LoveKiss = 73,
+ CleanMirror = 75,
+ PremiumDark = 76,
+ ColdEvening = 77,
+ CochitiLake = 78,
+ SummerGames = 79,
+ PassionateBed = 80,
+ MountainRock = 81,
+ DesertHump = 82,
+ JungleDay = 83,
+ PhoenixStart = 84,
+ OctoberSilence = 85,
+ FarawayRiver = 86,
+ AlchemistLab = 87,
+ OverSun = 88,
+ PremiumWhite = 89,
+ MarsParty = 90,
+ EternalConstance = 91,
+ JapanBlush = 92,
+ SmilingRain = 93,
+ CloudyApple = 94,
+ BigMango = 95,
+ HealthyWater = 96,
+ AmourAmour = 97,
+ RiskyConcrete = 98,
+ StrongStick = 99,
+ ViciousStance = 100,
+ PaloAlto = 101,
+ HappyMemories = 102,
+ MidnightBloom = 103,
+ Crystalline = 104,
+ PartyBliss = 106,
+ ConfidentCloud = 107,
+ LeCocktail = 108,
+ RiverCity = 109,
+ FrozenBerry = 110,
+ ChildCare = 112,
+ FlyingLemon = 113,
+ NewRetrowave = 114,
+ HiddenJaguar = 115,
+ AboveTheSky = 116,
+ Nega = 117,
+ DenseWater = 118,
+ Seashore = 120,
+ MarbleWall = 121,
+ CheerfulCaramel = 122,
+ NightSky = 123,
+ MagicLake = 124,
+ YoungGrass = 125,
+ ColorfulPeach = 126,
+ GentleCare = 127,
+ PlumBath = 128,
+ HappyUnicorn = 129,
+ AfricanField = 131,
+ SolidStone = 132,
+ OrangeJuice = 133,
+ GlassWater = 134,
+ NorthMiracle = 136,
+ FruitBlend = 137,
+ MillenniumPine = 138,
+ HighFlight = 139,
+ MoleHall = 140,
+ SpaceShift = 142,
+ ForestInei = 143,
+ RoyalGarden = 144,
+ RichMetal = 145,
+ JuicyCake = 146,
+ SmartIndigo = 147,
+ SandStrike = 148,
+ NorseBeauty = 149,
+ AquaGuidance = 150,
+ SunVeggie = 151,
+ SeaLord = 152,
+ BlackSea = 153,
+ GrassShampoo = 154,
+ LandingAircraft = 155,
+ WitchDance = 156,
+ SleeplessNight = 157,
+ AngelCare = 158,
+ CrystalRiver = 159,
+ SoftLipstick = 160,
+ SaltMountain = 161,
+ PerfectWhite = 162,
+ FreshOasis = 163,
+ StrictNovember = 164,
+ MorningSalad = 165,
+ DeepRelief = 166,
+ SeaStrike = 167,
+ NightCall = 168,
+ SupremeSky = 169,
+ LightBlue = 170,
+ MindCrawl = 171,
+ LilyMeadow = 172,
+ SugarLollipop = 173,
+ SweetDessert = 174,
+ MagicRay = 175,
+ TeenParty = 176,
+ FrozenHeat = 177,
+ GagarinView = 178,
+ FabledSunset = 179,
+ PerfectBlue = 180,
+ };
+ Q_ENUM(Preset)
+
QGradient();
+ QGradient(Preset);
Type type() const { return m_type; }
diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp
index c55bcb12c9..1d7375d1df 100644
--- a/src/gui/painting/qcolor.cpp
+++ b/src/gui/painting/qcolor.cpp
@@ -304,11 +304,6 @@ static const int rgbTblSize = sizeof(rgbTbl) / sizeof(RGBData);
#undef rgb
-#if defined(Q_CC_MSVC) && _MSC_VER < 1600
-inline bool operator<(const RGBData &data1, const RGBData &data2)
-{ return qstrcmp(data1.name, data2.name) < 0; }
-#endif
-
inline bool operator<(const char *name, const RGBData &data)
{ return qstrcmp(name, data.name) < 0; }
inline bool operator<(const RGBData &data, const char *name)
diff --git a/src/gui/painting/qcolorprofile_p.h b/src/gui/painting/qcolorprofile_p.h
index ca1786ee6d..425e9abace 100644
--- a/src/gui/painting/qcolorprofile_p.h
+++ b/src/gui/painting/qcolorprofile_p.h
@@ -55,6 +55,11 @@
#include <QtGui/qrgb.h>
#include <QtGui/qrgba64.h>
+#if defined(__SSE2__)
+#include <emmintrin.h>
+#elif defined(__ARM_NEON__) || defined(__ARM_NEON)
+#include <arm_neon.h>
+#endif
QT_BEGIN_NAMESPACE
class Q_GUI_EXPORT QColorProfile
@@ -67,82 +72,165 @@ public:
QRgba64 toLinear64(QRgb rgb32) const
{
- ushort r = m_toLinear[qRed(rgb32) << 4];
- ushort g = m_toLinear[qGreen(rgb32) << 4];
- ushort b = m_toLinear[qBlue(rgb32) << 4];
+#if defined(__SSE2__)
+ __m128i v = _mm_cvtsi32_si128(rgb32);
+ v = _mm_unpacklo_epi8(v, _mm_setzero_si128());
+ const __m128i vidx = _mm_slli_epi16(v, 4);
+ const int ridx = _mm_extract_epi16(vidx, 2);
+ const int gidx = _mm_extract_epi16(vidx, 1);
+ const int bidx = _mm_extract_epi16(vidx, 0);
+ v = _mm_slli_epi16(v, 8); // a * 256
+ v = _mm_insert_epi16(v, m_toLinear[ridx], 0);
+ v = _mm_insert_epi16(v, m_toLinear[gidx], 1);
+ v = _mm_insert_epi16(v, m_toLinear[bidx], 2);
+ v = _mm_add_epi16(v, _mm_srli_epi16(v, 8));
+ QRgba64 rgba64;
+ _mm_storel_epi64(reinterpret_cast<__m128i *>(&rgba64), v);
+ return rgba64;
+#elif (defined(__ARM_NEON__) || defined(__ARM_NEON)) && Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ uint8x8_t v8 = vreinterpret_u8_u32(vmov_n_u32(rgb32));
+ uint16x4_t v16 = vget_low_u16(vmovl_u8(v8));
+ const uint16x4_t vidx = vshl_n_u16(v16, 4);
+ const int ridx = vget_lane_u16(vidx, 2);
+ const int gidx = vget_lane_u16(vidx, 1);
+ const int bidx = vget_lane_u16(vidx, 0);
+ v16 = vshl_n_u16(v16, 8); // a * 256
+ v16 = vset_lane_u16(m_toLinear[ridx], v16, 0);
+ v16 = vset_lane_u16(m_toLinear[gidx], v16, 1);
+ v16 = vset_lane_u16(m_toLinear[bidx], v16, 2);
+ v16 = vadd_u16(v16, vshr_n_u16(v16, 8));
+ return QRgba64::fromRgba64(vget_lane_u64(vreinterpret_u64_u16(v16), 0));
+#else
+ uint r = m_toLinear[qRed(rgb32) << 4];
+ uint g = m_toLinear[qGreen(rgb32) << 4];
+ uint b = m_toLinear[qBlue(rgb32) << 4];
r = r + (r >> 8);
g = g + (g >> 8);
b = b + (b >> 8);
return QRgba64::fromRgba64(r, g, b, qAlpha(rgb32) * 257);
+#endif
}
QRgb toLinear(QRgb rgb32) const
{
- uchar r = (m_toLinear[qRed(rgb32) << 4] + 0x80) >> 8;
- uchar g = (m_toLinear[qGreen(rgb32) << 4] + 0x80) >> 8;
- uchar b = (m_toLinear[qBlue(rgb32) << 4] + 0x80) >> 8;
- return qRgba(r, g, b, qAlpha(rgb32));
+ return convertWithTable(rgb32, m_toLinear);
}
QRgba64 toLinear(QRgba64 rgb64) const
{
- ushort r = rgb64.red();
- ushort g = rgb64.green();
- ushort b = rgb64.blue();
- r = r - (r >> 8);
- g = g - (g >> 8);
- b = b - (b >> 8);
- r = m_toLinear[r >> 4];
- g = m_toLinear[g >> 4];
- b = m_toLinear[b >> 4];
- r = r + (r >> 8);
- g = g + (g >> 8);
- b = b + (b >> 8);
- return QRgba64::fromRgba64(r, g, b, rgb64.alpha());
+ return convertWithTable(rgb64, m_toLinear);
}
QRgb fromLinear64(QRgba64 rgb64) const
{
- ushort r = rgb64.red();
- ushort g = rgb64.green();
- ushort b = rgb64.blue();
+#if defined(__SSE2__)
+ __m128i v = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(&rgb64));
+ v = _mm_sub_epi16(v, _mm_srli_epi16(v, 8));
+ const __m128i vidx = _mm_srli_epi16(v, 4);
+ const int ridx = _mm_extract_epi16(vidx, 0);
+ const int gidx = _mm_extract_epi16(vidx, 1);
+ const int bidx = _mm_extract_epi16(vidx, 2);
+ v = _mm_insert_epi16(v, m_fromLinear[ridx], 2);
+ v = _mm_insert_epi16(v, m_fromLinear[gidx], 1);
+ v = _mm_insert_epi16(v, m_fromLinear[bidx], 0);
+ v = _mm_add_epi16(v, _mm_set1_epi16(0x80));
+ v = _mm_srli_epi16(v, 8);
+ v = _mm_packus_epi16(v, v);
+ return _mm_cvtsi128_si32(v);
+#elif (defined(__ARM_NEON__) || defined(__ARM_NEON)) && Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ uint16x4_t v = vreinterpret_u16_u64(vmov_n_u64(rgb64));
+ v = vsub_u16(v, vshr_n_u16(v, 8));
+ const uint16x4_t vidx = vshr_n_u16(v, 4);
+ const int ridx = vget_lane_u16(vidx, 0);
+ const int gidx = vget_lane_u16(vidx, 1);
+ const int bidx = vget_lane_u16(vidx, 2);
+ v = vset_lane_u16(m_fromLinear[ridx], v, 2);
+ v = vset_lane_u16(m_fromLinear[gidx], v, 1);
+ v = vset_lane_u16(m_fromLinear[bidx], v, 0);
+ uint8x8_t v8 = vrshrn_n_u16(vcombine_u16(v, v), 8);
+ return vget_lane_u32(vreinterpret_u32_u8(v8), 0);
+#else
+ uint a = rgb64.alpha();
+ uint r = rgb64.red();
+ uint g = rgb64.green();
+ uint b = rgb64.blue();
+ a = a - (a >> 8);
r = r - (r >> 8);
g = g - (g >> 8);
b = b - (b >> 8);
+ a = (a + 0x80) >> 8;
r = (m_fromLinear[r >> 4] + 0x80) >> 8;
g = (m_fromLinear[g >> 4] + 0x80) >> 8;
b = (m_fromLinear[b >> 4] + 0x80) >> 8;
- return qRgba(r, g, b, rgb64.alpha8());
+ return (a << 24) | (r << 16) | (g << 8) | b;
+#endif
}
QRgb fromLinear(QRgb rgb32) const
{
- uchar r = (m_fromLinear[qRed(rgb32) << 4] + 0x80) >> 8;
- uchar g = (m_fromLinear[qGreen(rgb32) << 4] + 0x80) >> 8;
- uchar b = (m_fromLinear[qBlue(rgb32) << 4] + 0x80) >> 8;
- return qRgba(r, g, b, qAlpha(rgb32));
+ return convertWithTable(rgb32, m_fromLinear);
}
QRgba64 fromLinear(QRgba64 rgb64) const
{
+ return convertWithTable(rgb64, m_fromLinear);
+ }
+
+private:
+ QColorProfile() { }
+
+ Q_ALWAYS_INLINE static QRgb convertWithTable(QRgb rgb32, const ushort *table)
+ {
+ const int r = (table[qRed(rgb32) << 4] + 0x80) >> 8;
+ const int g = (table[qGreen(rgb32) << 4] + 0x80) >> 8;
+ const int b = (table[qBlue(rgb32) << 4] + 0x80) >> 8;
+ return (rgb32 & 0xff000000) | (r << 16) | (g << 8) | b;
+ }
+ Q_ALWAYS_INLINE static QRgba64 convertWithTable(QRgba64 rgb64, const ushort *table)
+ {
+#if defined(__SSE2__)
+ __m128i v = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(&rgb64));
+ v = _mm_sub_epi16(v, _mm_srli_epi16(v, 8));
+ const __m128i vidx = _mm_srli_epi16(v, 4);
+ const int ridx = _mm_extract_epi16(vidx, 2);
+ const int gidx = _mm_extract_epi16(vidx, 1);
+ const int bidx = _mm_extract_epi16(vidx, 0);
+ v = _mm_insert_epi16(v, table[ridx], 2);
+ v = _mm_insert_epi16(v, table[gidx], 1);
+ v = _mm_insert_epi16(v, table[bidx], 0);
+ v = _mm_add_epi16(v, _mm_srli_epi16(v, 8));
+ QRgba64 rgba64;
+ _mm_storel_epi64(reinterpret_cast<__m128i *>(&rgba64), v);
+ return rgba64;
+#elif (defined(__ARM_NEON__) || defined(__ARM_NEON)) && Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ uint16x4_t v = vreinterpret_u16_u64(vmov_n_u64(rgb64));
+ v = vsub_u16(v, vshr_n_u16(v, 8));
+ const uint16x4_t vidx = vshr_n_u16(v, 4);
+ const int ridx = vget_lane_u16(vidx, 2);
+ const int gidx = vget_lane_u16(vidx, 1);
+ const int bidx = vget_lane_u16(vidx, 0);
+ v = vset_lane_u16(table[ridx], v, 2);
+ v = vset_lane_u16(table[gidx], v, 1);
+ v = vset_lane_u16(table[bidx], v, 0);
+ v = vadd_u16(v, vshr_n_u16(v, 8));
+ return QRgba64::fromRgba64(vget_lane_u64(vreinterpret_u64_u16(v), 0));
+#else
ushort r = rgb64.red();
ushort g = rgb64.green();
ushort b = rgb64.blue();
r = r - (r >> 8);
g = g - (g >> 8);
b = b - (b >> 8);
- r = m_fromLinear[r >> 4];
- g = m_fromLinear[g >> 4];
- b = m_fromLinear[b >> 4];
+ r = table[r >> 4];
+ g = table[g >> 4];
+ b = table[b >> 4];
r = r + (r >> 8);
g = g + (g >> 8);
b = b + (b >> 8);
return QRgba64::fromRgba64(r, g, b, rgb64.alpha());
+#endif
}
-private:
- QColorProfile() { }
-
// We translate to 0-65280 (255*256) instead to 0-65535 to make simple
// shifting an accurate conversion.
// We translate from 0-4080 (255*16) for the same speed up, and to keep
diff --git a/src/gui/painting/qcompositionfunctions.cpp b/src/gui/painting/qcompositionfunctions.cpp
index 339a9749b8..027bf23115 100644
--- a/src/gui/painting/qcompositionfunctions.cpp
+++ b/src/gui/painting/qcompositionfunctions.cpp
@@ -64,125 +64,354 @@ QT_BEGIN_NAMESPACE
where the source is an array of pixels.
*/
-#if defined __SSE2__
-# define LOAD(ptr) _mm_loadl_epi64(reinterpret_cast<const __m128i *>(ptr))
+struct Argb32OperationsC
+{
+ typedef QRgb Type;
+ typedef quint8 Scalar;
+ typedef QRgb OptimalType;
+ typedef quint8 OptimalScalar;
+
+ static const Type clear;
+ static bool isOpaque(Type val)
+ { return qAlpha(val) == 255; }
+ static bool isTransparent(Type val)
+ { return qAlpha(val) == 0; }
+ static Scalar scalarFrom8bit(uint8_t a)
+ { return a; }
+ static void memfill(Type *ptr, Type value, qsizetype len)
+ { qt_memfill32(ptr, value, len); }
+ static void memcpy(Type *Q_DECL_RESTRICT dest, const Type *Q_DECL_RESTRICT src, qsizetype len)
+ { ::memcpy(dest, src, len * sizeof(Type)); }
+
+ static OptimalType load(const Type *ptr)
+ { return *ptr; }
+ static OptimalType convert(const Type &val)
+ { return val; }
+ static void store(Type *ptr, OptimalType value)
+ { *ptr = value; }
+ static OptimalType add(OptimalType a, OptimalType b)
+ { return a + b; }
+ static OptimalScalar add(OptimalScalar a, OptimalScalar b)
+ { return a + b; }
+ static OptimalType plus(OptimalType a, OptimalType b)
+ { return comp_func_Plus_one_pixel(a, b); }
+ static OptimalScalar alpha(OptimalType val)
+ { return qAlpha(val); }
+ static OptimalScalar invAlpha(OptimalScalar c)
+ { return 255 - c; }
+ static OptimalScalar invAlpha(OptimalType val)
+ { return alpha(~val); }
+ static OptimalScalar scalar(Scalar v)
+ { return v; }
+ static OptimalType multiplyAlpha8bit(OptimalType val, uint8_t a)
+ { return BYTE_MUL(val, a); }
+ static OptimalType interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2)
+ { return INTERPOLATE_PIXEL_255(x, a1, y, a2); }
+ static OptimalType multiplyAlpha(OptimalType val, OptimalScalar a)
+ { return BYTE_MUL(val, a); }
+ static OptimalScalar multiplyAlpha8bit(OptimalScalar val, uint8_t a)
+ { return qt_div_255(val * a); }
+ static OptimalType interpolate(OptimalType x, OptimalScalar a1, OptimalType y, OptimalScalar a2)
+ { return INTERPOLATE_PIXEL_255(x, a1, y, a2); }
+};
+
+const Argb32OperationsC::Type Argb32OperationsC::clear = 0;
+
+struct Rgba64OperationsBase
+{
+ typedef QRgba64 Type;
+ typedef quint16 Scalar;
+
+ static const Type clear;
+
+ static bool isOpaque(Type val)
+ { return val.isOpaque(); }
+ static bool isTransparent(Type val)
+ { return val.isTransparent(); }
+ static Scalar scalarFrom8bit(uint8_t a)
+ { return a * 257; }
+
+ static void memfill(Type *ptr, Type value, qsizetype len)
+ { qt_memfill64((quint64*)ptr, value, len); }
+ static void memcpy(Type *Q_DECL_RESTRICT dest, const Type *Q_DECL_RESTRICT src, qsizetype len)
+ { ::memcpy(dest, src, len * sizeof(Type)); }
+};
+
+const Rgba64OperationsBase::Type Rgba64OperationsBase::clear = QRgba64::fromRgba64(0);
+
+struct Rgba64OperationsC : public Rgba64OperationsBase
+{
+ typedef QRgba64 OptimalType;
+ typedef quint16 OptimalScalar;
+
+ static OptimalType load(const Type *ptr)
+ { return *ptr; }
+ static OptimalType convert(const Type &val)
+ { return val; }
+ static void store(Type *ptr, OptimalType value)
+ { *ptr = value; }
+ static OptimalType add(OptimalType a, OptimalType b)
+ { return QRgba64::fromRgba64((quint64)a + (quint64)b); }
+ static OptimalScalar add(OptimalScalar a, OptimalScalar b)
+ { return a + b; }
+ static OptimalType plus(OptimalType a, OptimalType b)
+ { return addWithSaturation(a, b); }
+ static OptimalScalar alpha(OptimalType val)
+ { return val.alpha(); }
+ static OptimalScalar invAlpha(Scalar c)
+ { return 65535 - c; }
+ static OptimalScalar invAlpha(OptimalType val)
+ { return 65535 - alpha(val); }
+ static OptimalScalar scalar(Scalar v)
+ { return v; }
+ static OptimalType multiplyAlpha8bit(OptimalType val, uint8_t a)
+ { return multiplyAlpha255(val, a); }
+ static OptimalScalar multiplyAlpha8bit(OptimalScalar val, uint8_t a)
+ { return qt_div_255(val * a); }
+ static OptimalType interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2)
+ { return interpolate255(x, a1, y, a2); }
+ static OptimalType multiplyAlpha(OptimalType val, OptimalScalar a)
+ { return multiplyAlpha65535(val, a); }
+ static OptimalType interpolate(OptimalType x, OptimalScalar a1, OptimalType y, OptimalScalar a2)
+ { return interpolate65535(x, a1, y, a2); }
+};
+
+#if defined(__SSE2__)
+struct Rgba64OperationsSSE2 : public Rgba64OperationsBase
+{
+ typedef __m128i OptimalType;
+ typedef __m128i OptimalScalar;
+
+ static OptimalType load(const Type *ptr)
+ {
+ return _mm_loadl_epi64(reinterpret_cast<const __m128i *>(ptr));
+ }
+ static OptimalType convert(const Type &value)
+ {
#ifdef Q_PROCESSOR_X86_64
-# define CONVERT(value) _mm_cvtsi64_si128(value)
+ return _mm_cvtsi64_si128(value);
#else
-# define CONVERT(value) LOAD(&value)
+ return load(&value);
#endif
-# define STORE(ptr, value) _mm_storel_epi64(reinterpret_cast<__m128i *>(ptr), value)
-# define ADD(p, q) _mm_add_epi32(p, q)
-# define ALPHA(c) _mm_shufflelo_epi16(c, _MM_SHUFFLE(3, 3, 3, 3))
-# define CONST(n) _mm_shufflelo_epi16(_mm_cvtsi32_si128(n), _MM_SHUFFLE(0, 0, 0, 0))
-# define INVALPHA(c) _mm_sub_epi32(CONST(65535), ALPHA(c))
-#elif defined __ARM_NEON__
-# define LOAD(ptr) vreinterpret_u16_u64(vld1_u64(reinterpret_cast<const uint64_t *>(ptr)))
-# define CONVERT(value) vreinterpret_u16_u64(vmov_n_u64(value))
-# define STORE(ptr, value) vst1_u64(reinterpret_cast<uint64_t *>(ptr), vreinterpret_u64_u16(value))
-# define ADD(p, q) vadd_u16(p, q)
-# define ALPHA(c) vdup_lane_u16(c, 3)
-# define CONST(n) vdup_n_u16(n)
-# define INVALPHA(c) vmvn_u16(ALPHA(c))
-#else
-# define LOAD(ptr) *ptr
-# define CONVERT(value) value
-# define STORE(ptr, value) *ptr = value
-# define ADD(p, q) (p + q)
-# define ALPHA(c) (c).alpha()
-# define CONST(n) n
-# define INVALPHA(c) (65535 - ALPHA(c))
+ }
+ static void store(Type *ptr, OptimalType value)
+ {
+ _mm_storel_epi64(reinterpret_cast<__m128i *>(ptr), value);
+ }
+ static OptimalType add(OptimalType a, OptimalType b)
+ {
+ return _mm_add_epi16(a, b);
+ }
+// same as above:
+// static OptimalScalar add(OptimalScalar a, OptimalScalar b)
+ static OptimalType plus(OptimalType a, OptimalType b)
+ {
+ return _mm_adds_epu16(a, b);
+ }
+ static OptimalScalar alpha(OptimalType c)
+ {
+ return _mm_shufflelo_epi16(c, _MM_SHUFFLE(3, 3, 3, 3));
+ }
+ static OptimalScalar invAlpha(Scalar c)
+ {
+ return scalar(65535 - c);
+ }
+ static OptimalScalar invAlpha(OptimalType c)
+ {
+ return _mm_xor_si128(_mm_set1_epi16(-1), alpha(c));
+ }
+ static OptimalScalar scalar(Scalar n)
+ {
+ return _mm_shufflelo_epi16(_mm_cvtsi32_si128(n), _MM_SHUFFLE(0, 0, 0, 0));
+ }
+ static OptimalType multiplyAlpha8bit(OptimalType val, uint8_t a)
+ {
+ return multiplyAlpha255(val, a);
+ }
+// same as above:
+// static OptimalScalar multiplyAlpha8bit(OptimalScalar a, uint8_t a)
+ static OptimalType interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2)
+ {
+ return interpolate255(x, a1, y, a2);
+ }
+ static OptimalType multiplyAlpha(OptimalType val, OptimalScalar a)
+ {
+ return multiplyAlpha65535(val, a);
+ }
+ // a2 is const-ref because otherwise MSVC2015@x86 complains that it can't 16-byte align the argument.
+ static OptimalType interpolate(OptimalType x, OptimalScalar a1, OptimalType y, const OptimalScalar &a2)
+ {
+ return interpolate65535(x, a1, y, a2);
+ }
+};
#endif
+#if defined(__ARM_NEON__)
+struct Rgba64OperationsNEON : public Rgba64OperationsBase
+{
+ typedef uint16x4_t OptimalType;
+ typedef uint16x4_t OptimalScalar;
+
+ static OptimalType load(const Type *ptr)
+ {
+ return vreinterpret_u16_u64(vld1_u64(reinterpret_cast<const uint64_t *>(ptr)));
+ }
+ static OptimalType convert(const Type &val)
+ {
+ return vreinterpret_u16_u64(vmov_n_u64(val));
+ }
+ static void store(Type *ptr, OptimalType value)
+ {
+ vst1_u64(reinterpret_cast<uint64_t *>(ptr), vreinterpret_u64_u16(value));
+ }
+ static OptimalType add(OptimalType a, OptimalType b)
+ {
+ return vadd_u16(a, b);
+ }
+// same as above:
+// static OptimalScalar add(OptimalScalar a, OptimalScalar b)
+ static OptimalType plus(OptimalType a, OptimalType b)
+ {
+ return vqadd_u16(a, b);
+ }
+ static OptimalScalar alpha(OptimalType c)
+ {
+ return vdup_lane_u16(c, 3);
+ }
+ static OptimalScalar invAlpha(Scalar c)
+ {
+ return scalar(65535 - c);
+ }
+ static OptimalScalar invAlpha(OptimalType c)
+ {
+ return vmvn_u16(alpha(c));
+ }
+ static OptimalScalar scalar(Scalar n)
+ {
+ return vdup_n_u16(n);
+ }
+ static OptimalType multiplyAlpha8bit(OptimalType val, uint8_t a)
+ {
+ return multiplyAlpha255(val, a);
+ }
+// same as above:
+// static OptimalScalar multiplyAlpha8bit(OptimalScalar a, uint8_t a)
+ static OptimalType interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2)
+ {
+ return interpolate255(x, a1, y, a2);
+ }
+ static OptimalType multiplyAlpha(OptimalType val, OptimalScalar a)
+ {
+ return multiplyAlpha65535(val, a);
+ }
+ static OptimalType interpolate(OptimalType x, OptimalScalar a1, OptimalType y, OptimalScalar a2)
+ {
+ return interpolate65535(x, a1, y, a2);
+ }
+};
+
+#endif
+
+typedef Argb32OperationsC Argb32Operations;
+#if defined(__SSE2__)
+typedef Rgba64OperationsSSE2 Rgba64Operations;
+#elif defined(__ARM_NEON__)
+typedef Rgba64OperationsNEON Rgba64Operations;
+#else
+typedef Rgba64OperationsC Rgba64Operations;
+#endif
/*
result = 0
d = d * cia
*/
-void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint const_alpha)
+template<class Ops>
+inline static void comp_func_Clear_template(typename Ops::Type *dest, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- qt_memfill32(dest, 0, length);
- } else {
+ if (const_alpha == 255)
+ Ops::memfill(dest, Ops::clear, length);
+ else {
uint ialpha = 255 - const_alpha;
- for (int i = 0; i < length; ++i)
- dest[i] = BYTE_MUL(dest[i], ialpha);
+ for (int i = 0; i < length; ++i) {
+ Ops::store(&dest[i], Ops::multiplyAlpha8bit(Ops::load(&dest[i]), ialpha));
+ }
}
}
+void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint const_alpha)
+{
+ comp_func_Clear_template<Argb32Operations>(dest, length, const_alpha);
+}
+
void QT_FASTCALL comp_func_solid_Clear_rgb64(QRgba64 *dest, int length, QRgba64, uint const_alpha)
{
- if (const_alpha == 255) {
- qt_memfill64((quint64*)dest, 0, length);
- } else {
- uint ialpha = 255 - const_alpha;
- for (int i = 0; i < length; ++i)
- STORE(&dest[i], multiplyAlpha255(LOAD(&dest[i]), ialpha));
- }
+ comp_func_Clear_template<Rgba64Operations>(dest, length, const_alpha);
}
void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, uint const_alpha)
{
- comp_func_solid_Clear(dest, length, 0, const_alpha);
+ comp_func_Clear_template<Argb32Operations>(dest, length, const_alpha);
}
void QT_FASTCALL comp_func_Clear_rgb64(QRgba64 *dest, const QRgba64 *, int length, uint const_alpha)
{
- comp_func_solid_Clear_rgb64(dest, length, QRgba64(), const_alpha);
+ comp_func_Clear_template<Rgba64Operations>(dest, length, const_alpha);
}
/*
result = s
dest = s * ca + d * cia
*/
-void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_solid_Source_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
{
- if (const_alpha == 255) {
- qt_memfill32(dest, color, length);
- } else {
- uint ialpha = 255 - const_alpha;
- color = BYTE_MUL(color, const_alpha);
+ if (const_alpha == 255)
+ Ops::memfill(dest, color, length);
+ else {
+ const uint ialpha = 255 - const_alpha;
+ auto s = Ops::multiplyAlpha8bit(Ops::convert(color), const_alpha);
for (int i = 0; i < length; ++i) {
- dest[i] = color + BYTE_MUL(dest[i], ialpha);
+ auto d = Ops::multiplyAlpha8bit(Ops::load(&dest[i]), ialpha);
+ Ops::store(&dest[i], Ops::add(s, d));
}
}
}
-void QT_FASTCALL comp_func_solid_Source_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_Source_template(typename Ops::Type *Q_DECL_RESTRICT dest,
+ const typename Ops::Type *Q_DECL_RESTRICT src,
+ int length, uint const_alpha)
{
if (const_alpha == 255)
- qt_memfill64((quint64*)dest, color, length);
+ Ops::memcpy(dest, src, length);
else {
- uint ialpha = 255 - const_alpha;
- auto c = multiplyAlpha255(CONVERT(color), const_alpha);
+ const uint ialpha = 255 - const_alpha;
for (int i = 0; i < length; ++i) {
- STORE(&dest[i], ADD(c, multiplyAlpha255(LOAD(&dest[i]), ialpha)));
+ auto s = Ops::load(src + i);
+ auto d = Ops::load(dest + i);
+ Ops::store(&dest[i], Ops::interpolate8bit(s, const_alpha, d, ialpha));
}
}
}
+void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint const_alpha)
+{
+ comp_func_solid_Source_template<Argb32Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_solid_Source_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ comp_func_solid_Source_template<Rgba64Operations>(dest, length, color, const_alpha);
+}
+
void QT_FASTCALL comp_func_Source(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- ::memcpy(dest, src, size_t(length) * sizeof(uint));
- } else {
- uint ialpha = 255 - const_alpha;
- for (int i = 0; i < length; ++i) {
- dest[i] = INTERPOLATE_PIXEL_255(src[i], const_alpha, dest[i], ialpha);
- }
- }
+ comp_func_Source_template<Argb32Operations>(dest, src, length, const_alpha);
}
void QT_FASTCALL comp_func_Source_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255)
- ::memcpy(dest, src, size_t(length) * sizeof(quint64));
- else {
- uint ialpha = 255 - const_alpha;
- for (int i = 0; i < length; ++i) {
- STORE(&dest[i], interpolate255(LOAD(&src[i]), const_alpha, LOAD(&dest[i]), ialpha));
- }
- }
+ comp_func_Source_template<Rgba64Operations>(dest, src, length, const_alpha);
}
void QT_FASTCALL comp_func_solid_Destination(uint *, int, uint, uint)
@@ -207,68 +436,66 @@ void QT_FASTCALL comp_func_Destination_rgb64(QRgba64 *, const QRgba64 *, int, ui
= s * ca + d * (sia * ca + cia)
= s * ca + d * (1 - sa*ca)
*/
-void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_solid_SourceOver_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
{
- if ((const_alpha & qAlpha(color)) == 255) {
- qt_memfill32(dest, color, length);
- } else {
+ if (const_alpha == 255 && Ops::isOpaque(color))
+ Ops::memfill(dest, color, length);
+ else {
+ auto c = Ops::convert(color);
if (const_alpha != 255)
- color = BYTE_MUL(color, const_alpha);
+ c = Ops::multiplyAlpha8bit(c, const_alpha);
+ auto cAlpha = Ops::invAlpha(c);
for (int i = 0; i < length; ++i) {
- dest[i] = color + BYTE_MUL(dest[i], qAlpha(~color));
+ auto d = Ops::multiplyAlpha(Ops::load(&dest[i]), cAlpha);
+ Ops::store(&dest[i], Ops::add(c, d));
}
}
}
-void QT_FASTCALL comp_func_solid_SourceOver_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_SourceOver_template(typename Ops::Type *Q_DECL_RESTRICT dest,
+ const typename Ops::Type *Q_DECL_RESTRICT src,
+ int length, uint const_alpha)
{
- if (const_alpha == 255 && color.isOpaque()) {
- qt_memfill64((quint64*)dest, color, length);
+ if (const_alpha == 255) {
+ for (int i = 0; i < length; ++i) {
+ auto c = src[i];
+ if (Ops::isOpaque(c))
+ Ops::store(&dest[i], Ops::convert(c));
+ else if (!Ops::isTransparent(c)) {
+ auto s = Ops::convert(c);
+ auto d = Ops::multiplyAlpha(Ops::load(&dest[i]), Ops::invAlpha(s));
+ Ops::store(&dest[i], Ops::add(s, d));
+ }
+ }
} else {
- auto c = CONVERT(color);
- if (const_alpha != 255)
- c = multiplyAlpha255(c, const_alpha);
- auto cAlpha = INVALPHA(c);
for (int i = 0; i < length; ++i) {
- STORE(&dest[i], ADD(c, multiplyAlpha65535(LOAD(&dest[i]), cAlpha)));
+ auto s = Ops::multiplyAlpha8bit(Ops::load(&src[i]), const_alpha);
+ auto d = Ops::multiplyAlpha(Ops::load(&dest[i]), Ops::invAlpha(s));
+ Ops::store(&dest[i], Ops::add(s, d));
}
}
}
+void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint color, uint const_alpha)
+{
+ comp_func_solid_SourceOver_template<Argb32Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_solid_SourceOver_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ comp_func_solid_SourceOver_template<Rgba64Operations>(dest, length, color, const_alpha);
+}
+
void QT_FASTCALL comp_func_SourceOver(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- uint s = src[i];
- if (s >= 0xff000000)
- dest[i] = s;
- else if (s != 0)
- dest[i] = s + BYTE_MUL(dest[i], qAlpha(~s));
- }
- } else {
- for (int i = 0; i < length; ++i) {
- uint s = BYTE_MUL(src[i], const_alpha);
- dest[i] = s + BYTE_MUL(dest[i], qAlpha(~s));
- }
- }
+ comp_func_SourceOver_template<Argb32Operations>(dest, src, length, const_alpha);
}
void QT_FASTCALL comp_func_SourceOver_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- QRgba64 s = src[i];
- if (s.isOpaque())
- dest[i] = s;
- else if (!s.isTransparent())
- STORE(&dest[i], ADD(CONVERT(s), multiplyAlpha65535(LOAD(&dest[i]), 65535 - s.alpha())));
- }
- } else {
- for (int i = 0; i < length; ++i) {
- auto s = multiplyAlpha255(LOAD(&src[i]), const_alpha);
- STORE(&dest[i], ADD(s, multiplyAlpha65535(LOAD(&dest[i]), INVALPHA(s))));
- }
- }
+ comp_func_SourceOver_template<Rgba64Operations>(dest, src, length, const_alpha);
}
/*
@@ -276,128 +503,122 @@ void QT_FASTCALL comp_func_SourceOver_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const
dest = (d + s * dia) * ca + d * cia
= d + s * dia * ca
*/
-void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length, uint color, uint const_alpha)
-{
- if (const_alpha != 255)
- color = BYTE_MUL(color, const_alpha);
- for (int i = 0; i < length; ++i) {
- uint d = dest[i];
- dest[i] = d + BYTE_MUL(color, qAlpha(~d));
- }
-}
-
-void QT_FASTCALL comp_func_solid_DestinationOver_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_solid_DestinationOver_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
{
- auto c = CONVERT(color);
+ auto c = Ops::convert(color);
if (const_alpha != 255)
- c = multiplyAlpha255(c, const_alpha);
+ c = Ops::multiplyAlpha8bit(c, const_alpha);
for (int i = 0; i < length; ++i) {
- auto d = LOAD(&dest[i]);
- STORE(&dest[i], ADD(d, multiplyAlpha65535(c, INVALPHA(d))));
+ auto d = Ops::load(&dest[i]);
+ auto s = Ops::multiplyAlpha(c, Ops::invAlpha(d));
+ Ops::store(&dest[i], Ops::add(s, d));
}
}
-void QT_FASTCALL comp_func_DestinationOver(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+template<class Ops>
+inline static void comp_func_DestinationOver_template(typename Ops::Type *Q_DECL_RESTRICT dest,
+ const typename Ops::Type *Q_DECL_RESTRICT src,
+ int length, uint const_alpha)
{
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
- uint d = dest[i];
- dest[i] = d + BYTE_MUL(src[i], qAlpha(~d));
+ auto d = Ops::load(&dest[i]);
+ auto s = Ops::multiplyAlpha(Ops::load(&src[i]), Ops::invAlpha(d));
+ Ops::store(&dest[i], Ops::add(s, d));
}
} else {
for (int i = 0; i < length; ++i) {
- uint d = dest[i];
- uint s = BYTE_MUL(src[i], const_alpha);
- dest[i] = d + BYTE_MUL(s, qAlpha(~d));
+ auto d = Ops::load(&dest[i]);
+ auto s = Ops::multiplyAlpha8bit(Ops::load(&src[i]), const_alpha);
+ s = Ops::multiplyAlpha(s, Ops::invAlpha(d));
+ Ops::store(&dest[i], Ops::add(s, d));
}
}
}
+void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length, uint color, uint const_alpha)
+{
+ comp_func_solid_DestinationOver_template<Argb32Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_solid_DestinationOver_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ comp_func_solid_DestinationOver_template<Rgba64Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_DestinationOver(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ comp_func_DestinationOver_template<Argb32Operations>(dest, src, length, const_alpha);
+}
+
void QT_FASTCALL comp_func_DestinationOver_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- auto d = LOAD(&dest[i]);
- STORE(&dest[i], ADD(d, multiplyAlpha65535(LOAD(&src[i]), INVALPHA(d))));
- }
- } else {
- for (int i = 0; i < length; ++i) {
- auto d = LOAD(&dest[i]);
- auto s = multiplyAlpha255(LOAD(&src[i]), const_alpha);
- STORE(&dest[i], ADD(d, multiplyAlpha65535(s, INVALPHA(d))));
- }
- }
+ comp_func_DestinationOver_template<Rgba64Operations>(dest, src, length, const_alpha);
}
/*
result = s * da
dest = s * da * ca + d * cia
*/
-void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_solid_SourceIn_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
{
if (const_alpha == 255) {
+ auto c = Ops::convert(color);
for (int i = 0; i < length; ++i) {
- dest[i] = BYTE_MUL(color, qAlpha(dest[i]));
+ Ops::store(&dest[i], Ops::multiplyAlpha(c, Ops::alpha(Ops::load(&dest[i]))));
}
} else {
- color = BYTE_MUL(color, const_alpha);
- uint cia = 255 - const_alpha;
+ auto c = Ops::multiplyAlpha8bit(Ops::convert(color), const_alpha);
+ auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
for (int i = 0; i < length; ++i) {
- uint d = dest[i];
- dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(d), d, cia);
+ auto d = Ops::load(&dest[i]);
+ Ops::store(&dest[i], Ops::interpolate(c, Ops::alpha(d), d, cia));
}
}
}
-void QT_FASTCALL comp_func_solid_SourceIn_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_SourceIn_template(typename Ops::Type *Q_DECL_RESTRICT dest,
+ const typename Ops::Type *Q_DECL_RESTRICT src,
+ int length, uint const_alpha)
{
if (const_alpha == 255) {
- auto c = CONVERT(color);
for (int i = 0; i < length; ++i) {
- STORE(&dest[i], multiplyAlpha65535(c, dest[i].alpha()));
+ auto s = Ops::load(&src[i]);
+ Ops::store(&dest[i], Ops::multiplyAlpha(s, Ops::alpha(Ops::load(&dest[i]))));
}
} else {
- uint ca = const_alpha * 257;
- auto cia = CONST(65535 - ca);
- auto c = multiplyAlpha65535(CONVERT(color), ca);
+ auto ca = Ops::scalarFrom8bit(const_alpha);
+ auto cia = Ops::invAlpha(ca);
+ auto cav = Ops::scalar(ca);
for (int i = 0; i < length; ++i) {
- auto d = LOAD(&dest[i]);
- STORE(&dest[i], interpolate65535(c, ALPHA(d), d, cia));
+ auto d = Ops::load(&dest[i]);
+ auto s = Ops::multiplyAlpha(Ops::load(&src[i]), cav);
+ Ops::store(&dest[i], Ops::interpolate(s, Ops::alpha(d), d, cia));
}
}
}
+void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint color, uint const_alpha)
+{
+ comp_func_solid_SourceIn_template<Argb32Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_solid_SourceIn_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ comp_func_solid_SourceIn_template<Rgba64Operations>(dest, length, color, const_alpha);
+}
+
void QT_FASTCALL comp_func_SourceIn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- dest[i] = BYTE_MUL(src[i], qAlpha(dest[i]));
- }
- } else {
- uint cia = 255 - const_alpha;
- for (int i = 0; i < length; ++i) {
- uint d = dest[i];
- uint s = BYTE_MUL(src[i], const_alpha);
- dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, cia);
- }
- }
+ comp_func_SourceIn_template<Argb32Operations>(dest, src, length, const_alpha);
}
void QT_FASTCALL comp_func_SourceIn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- STORE(&dest[i], multiplyAlpha65535(LOAD(&src[i]), dest[i].alpha()));
- }
- } else {
- uint ca = const_alpha * 257;
- auto cia = CONST(65535 - ca);
- for (int i = 0; i < length; ++i) {
- auto d = LOAD(&dest[i]);
- auto s = multiplyAlpha65535(LOAD(&src[i]), ca);
- STORE(&dest[i], interpolate65535(s, ALPHA(d), d, cia));
- }
- }
+ comp_func_SourceIn_template<Rgba64Operations>(dest, src, length, const_alpha);
}
/*
@@ -405,128 +626,120 @@ void QT_FASTCALL comp_func_SourceIn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const Q
dest = d * sa * ca + d * cia
= d * (sa * ca + cia)
*/
-void QT_FASTCALL comp_func_solid_DestinationIn(uint *dest, int length, uint color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_solid_DestinationIn_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
{
- uint a = qAlpha(color);
+ auto sa = Ops::alpha(Ops::convert(color));
if (const_alpha != 255) {
- a = BYTE_MUL(a, const_alpha) + 255 - const_alpha;
- }
- for (int i = 0; i < length; ++i) {
- dest[i] = BYTE_MUL(dest[i], a);
+ sa = Ops::multiplyAlpha8bit(sa, const_alpha);
+ sa = Ops::add(sa, Ops::invAlpha(Ops::scalarFrom8bit(const_alpha)));
}
-}
-void QT_FASTCALL comp_func_solid_DestinationIn_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
-{
- uint a = color.alpha();
- uint ca64k = const_alpha * 257;
- if (const_alpha != 255)
- a = qt_div_65535(a * ca64k) + 65535 - ca64k;
for (int i = 0; i < length; ++i) {
- STORE(&dest[i], multiplyAlpha65535(LOAD(&dest[i]), a));
+ Ops::store(&dest[i], Ops::multiplyAlpha(Ops::load(&dest[i]), sa));
}
}
-void QT_FASTCALL comp_func_DestinationIn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+template<class Ops>
+inline static void comp_func_DestinationIn_template(typename Ops::Type *Q_DECL_RESTRICT dest,
+ const typename Ops::Type *Q_DECL_RESTRICT src,
+ int length, uint const_alpha)
{
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
- dest[i] = BYTE_MUL(dest[i], qAlpha(src[i]));
+ auto a = Ops::alpha(Ops::load(&src[i]));
+ Ops::store(&dest[i], Ops::multiplyAlpha(Ops::load(&dest[i]), a));
}
} else {
- uint cia = 255 - const_alpha;
+ auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
for (int i = 0; i < length; ++i) {
- uint a = BYTE_MUL(qAlpha(src[i]), const_alpha) + cia;
- dest[i] = BYTE_MUL(dest[i], a);
+ auto sa = Ops::multiplyAlpha8bit(Ops::alpha(Ops::load(&src[i])), const_alpha);
+ sa = Ops::add(sa, cia);
+ Ops::store(&dest[i], Ops::multiplyAlpha(Ops::load(&dest[i]), sa));
}
}
}
+void QT_FASTCALL comp_func_solid_DestinationIn(uint *dest, int length, uint color, uint const_alpha)
+{
+ comp_func_solid_DestinationIn_template<Argb32Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_solid_DestinationIn_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ comp_func_solid_DestinationIn_template<Rgba64Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_DestinationIn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ comp_func_DestinationIn_template<Argb32Operations>(dest, src, length, const_alpha);
+}
+
void QT_FASTCALL comp_func_DestinationIn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- STORE(&dest[i], multiplyAlpha65535(LOAD(&dest[i]), src[i].alpha()));
- }
- } else {
- uint ca = const_alpha * 257;
- uint cia = 65535 - ca;
- for (int i = 0; i < length; ++i) {
- uint a = qt_div_65535(src[i].alpha() * ca) + cia;
- STORE(&dest[i], multiplyAlpha65535(LOAD(&dest[i]), a));
- }
- }
+ comp_func_DestinationIn_template<Rgba64Operations>(dest, src, length, const_alpha);
}
/*
result = s * dia
dest = s * dia * ca + d * cia
*/
-
-void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_solid_SourceOut_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
{
+ auto c = Ops::convert(color);
if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- dest[i] = BYTE_MUL(color, qAlpha(~dest[i]));
- }
+ for (int i = 0; i < length; ++i)
+ Ops::store(&dest[i], Ops::multiplyAlpha(c, Ops::invAlpha(Ops::load(&dest[i]))));
} else {
- color = BYTE_MUL(color, const_alpha);
- uint cia = 255 - const_alpha;
+ auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
+ c = Ops::multiplyAlpha8bit(c, const_alpha);
for (int i = 0; i < length; ++i) {
- uint d = dest[i];
- dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(~d), d, cia);
+ auto d = Ops::load(&dest[i]);
+ Ops::store(&dest[i], Ops::interpolate(c, Ops::invAlpha(d), d, cia));
}
}
}
-void QT_FASTCALL comp_func_solid_SourceOut_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_SourceOut_template(typename Ops::Type *Q_DECL_RESTRICT dest,
+ const typename Ops::Type *Q_DECL_RESTRICT src,
+ int length, uint const_alpha)
{
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
- dest[i] = multiplyAlpha65535(color, 65535 - dest[i].alpha());
+ auto s = Ops::load(&src[i]);
+ auto d = Ops::load(&dest[i]);
+ Ops::store(&dest[i], Ops::multiplyAlpha(s, Ops::invAlpha(d)));
}
} else {
- uint ca = const_alpha * 257;
- uint cia = 65535 - ca;
- color = multiplyAlpha65535(color, ca);
+ auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
for (int i = 0; i < length; ++i) {
- QRgba64 d = dest[i];
- dest[i] = interpolate65535(color, 65535 - d.alpha(), d, cia);
+ auto s = Ops::multiplyAlpha8bit(Ops::load(&src[i]), const_alpha);
+ auto d = Ops::load(&dest[i]);
+ Ops::store(&dest[i], Ops::interpolate(s, Ops::invAlpha(d), d, cia));
}
}
}
+void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint color, uint const_alpha)
+{
+ comp_func_solid_SourceOut_template<Argb32Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_solid_SourceOut_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ comp_func_solid_SourceOut_template<Rgba64Operations>(dest, length, color, const_alpha);
+}
+
void QT_FASTCALL comp_func_SourceOut(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- dest[i] = BYTE_MUL(src[i], qAlpha(~dest[i]));
- }
- } else {
- uint cia = 255 - const_alpha;
- for (int i = 0; i < length; ++i) {
- uint s = BYTE_MUL(src[i], const_alpha);
- uint d = dest[i];
- dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, cia);
- }
- }
+ comp_func_SourceOut_template<Argb32Operations>(dest, src, length, const_alpha);
}
void QT_FASTCALL comp_func_SourceOut_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- dest[i] = multiplyAlpha65535(src[i], 65535 - dest[i].alpha());
- }
- } else {
- uint ca = const_alpha * 257;
- uint cia = 65535 - ca;
- for (int i = 0; i < length; ++i) {
- QRgba64 d = dest[i];
- QRgba64 s = multiplyAlpha65535(src[i], ca);
- dest[i] = interpolate65535(s, 65535 - d.alpha(), d, cia);
- }
- }
+ comp_func_SourceOut_template<Rgba64Operations>(dest, src, length, const_alpha);
}
/*
@@ -534,56 +747,58 @@ void QT_FASTCALL comp_func_SourceOut_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const
dest = d * sia * ca + d * cia
= d * (sia * ca + cia)
*/
-void QT_FASTCALL comp_func_solid_DestinationOut(uint *dest, int length, uint color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_solid_DestinationOut_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
{
- uint a = qAlpha(~color);
- if (const_alpha != 255)
- a = BYTE_MUL(a, const_alpha) + 255 - const_alpha;
- for (int i = 0; i < length; ++i) {
- dest[i] = BYTE_MUL(dest[i], a);
+ auto sai = Ops::invAlpha(Ops::convert(color));
+ if (const_alpha != 255) {
+ sai = Ops::multiplyAlpha8bit(sai, const_alpha);
+ sai = Ops::add(sai, Ops::invAlpha(Ops::scalarFrom8bit(const_alpha)));
}
-}
-void QT_FASTCALL comp_func_solid_DestinationOut_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
-{
- uint a = 65535 - color.alpha();
- uint ca64k = const_alpha * 257;
- if (const_alpha != 255)
- a = qt_div_65535(a * ca64k) + 65535 - ca64k;
for (int i = 0; i < length; ++i) {
- dest[i] = multiplyAlpha65535(dest[i], a);
+ Ops::store(&dest[i], Ops::multiplyAlpha(Ops::load(&dest[i]), sai));
}
}
-void QT_FASTCALL comp_func_DestinationOut(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+template<class Ops>
+inline static void comp_func_DestinationOut_template(typename Ops::Type *Q_DECL_RESTRICT dest,
+ const typename Ops::Type *Q_DECL_RESTRICT src,
+ int length, uint const_alpha)
{
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
- dest[i] = BYTE_MUL(dest[i], qAlpha(~src[i]));
+ auto sia = Ops::invAlpha(Ops::load(&src[i]));
+ Ops::store(&dest[i], Ops::multiplyAlpha(Ops::load(&dest[i]), sia));
}
} else {
- uint cia = 255 - const_alpha;
+ auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
for (int i = 0; i < length; ++i) {
- uint sia = BYTE_MUL(qAlpha(~src[i]), const_alpha) + cia;
- dest[i] = BYTE_MUL(dest[i], sia);
+ auto sia = Ops::multiplyAlpha8bit(Ops::invAlpha(Ops::load(&src[i])), const_alpha);
+ sia = Ops::add(sia, cia);
+ Ops::store(&dest[i], Ops::multiplyAlpha(Ops::load(&dest[i]), sia));
}
}
}
+void QT_FASTCALL comp_func_solid_DestinationOut(uint *dest, int length, uint color, uint const_alpha)
+{
+ comp_func_solid_DestinationOut_template<Argb32Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_solid_DestinationOut_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ comp_func_solid_DestinationOut_template<Rgba64Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_DestinationOut(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ comp_func_DestinationOut_template<Argb32Operations>(dest, src, length, const_alpha);
+}
+
void QT_FASTCALL comp_func_DestinationOut_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- dest[i] = multiplyAlpha65535(dest[i], 65535 - src[i].alpha());
- }
- } else {
- uint ca = const_alpha * 257;
- uint cia = 65535 - ca;
- for (int i = 0; i < length; ++i) {
- uint a = qt_div_65535((65535 - src[i].alpha()) * ca) + cia;
- dest[i] = multiplyAlpha65535(dest[i], a);
- }
- }
+ comp_func_DestinationOut_template<Rgba64Operations>(dest, src, length, const_alpha);
}
/*
@@ -592,59 +807,57 @@ void QT_FASTCALL comp_func_DestinationOut_rgb64(QRgba64 *Q_DECL_RESTRICT dest, c
= s*ca * da + d * (sia*ca + cia)
= s*ca * da + d * (1 - sa*ca)
*/
-void QT_FASTCALL comp_func_solid_SourceAtop(uint *dest, int length, uint color, uint const_alpha)
-{
- if (const_alpha != 255) {
- color = BYTE_MUL(color, const_alpha);
- }
- uint sia = qAlpha(~color);
- for (int i = 0; i < length; ++i) {
- dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(dest[i]), dest[i], sia);
- }
-}
-
-void QT_FASTCALL comp_func_solid_SourceAtop_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_solid_SourceAtop_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
{
+ auto c = Ops::convert(color);
if (const_alpha != 255)
- color = multiplyAlpha255(color, const_alpha);
- uint sia = 65535 - color.alpha();
+ c = Ops::multiplyAlpha8bit(c, const_alpha);
+ auto sia = Ops::invAlpha(c);
for (int i = 0; i < length; ++i) {
- dest[i] = interpolate65535(color, dest[i].alpha(), dest[i], sia);
+ auto d = Ops::load(&dest[i]);
+ Ops::store(&dest[i], Ops::interpolate(c, Ops::alpha(d), d, sia));
}
}
-void QT_FASTCALL comp_func_SourceAtop(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+template<class Ops>
+inline static void comp_func_SourceAtop_template(typename Ops::Type *Q_DECL_RESTRICT dest,
+ const typename Ops::Type *Q_DECL_RESTRICT src,
+ int length, uint const_alpha)
{
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
- uint s = src[i];
- uint d = dest[i];
- dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, qAlpha(~s));
+ auto s = Ops::load(&src[i]);
+ auto d = Ops::load(&dest[i]);
+ Ops::store(&dest[i], Ops::interpolate(s, Ops::alpha(d), d, Ops::invAlpha(s)));
}
} else {
for (int i = 0; i < length; ++i) {
- uint s = BYTE_MUL(src[i], const_alpha);
- uint d = dest[i];
- dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, qAlpha(~s));
+ auto s = Ops::multiplyAlpha8bit(Ops::load(&src[i]), const_alpha);
+ auto d = Ops::load(&dest[i]);
+ Ops::store(&dest[i], Ops::interpolate(s, Ops::alpha(d), d, Ops::invAlpha(s)));
}
}
}
+void QT_FASTCALL comp_func_solid_SourceAtop(uint *dest, int length, uint color, uint const_alpha)
+{
+ comp_func_solid_SourceAtop_template<Argb32Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_solid_SourceAtop_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ comp_func_solid_SourceAtop_template<Rgba64Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_SourceAtop(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ comp_func_SourceAtop_template<Argb32Operations>(dest, src, length, const_alpha);
+}
+
void QT_FASTCALL comp_func_SourceAtop_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- QRgba64 s = src[i];
- QRgba64 d = dest[i];
- dest[i] = interpolate65535(s, d.alpha(), d, 65535 - s.alpha());
- }
- } else {
- for (int i = 0; i < length; ++i) {
- QRgba64 s = multiplyAlpha255(src[i], const_alpha);
- QRgba64 d = dest[i];
- dest[i] = interpolate65535(s, d.alpha(), d, 65535 - s.alpha());
- }
- }
+ comp_func_SourceAtop_template<Rgba64Operations>(dest, src, length, const_alpha);
}
/*
@@ -652,69 +865,63 @@ void QT_FASTCALL comp_func_SourceAtop_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const
dest = d*sa*ca + s*dia*ca + d *cia
= s*ca * dia + d * (sa*ca + cia)
*/
-void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length, uint color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_solid_DestinationAtop_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
{
- uint a = qAlpha(color);
+ auto c = Ops::convert(color);
+ auto sa = Ops::alpha(c);
if (const_alpha != 255) {
- color = BYTE_MUL(color, const_alpha);
- a = qAlpha(color) + 255 - const_alpha;
- }
- for (int i = 0; i < length; ++i) {
- uint d = dest[i];
- dest[i] = INTERPOLATE_PIXEL_255(d, a, color, qAlpha(~d));
+ c = Ops::multiplyAlpha8bit(c, const_alpha);
+ auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
+ sa = Ops::add(Ops::alpha(c), cia);
}
-}
-void QT_FASTCALL comp_func_solid_DestinationAtop_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
-{
- uint a = color.alpha();
- if (const_alpha != 255) {
- color = multiplyAlpha255(color, const_alpha);
- a = color.alpha() + 65535 - (const_alpha * 257);
- }
for (int i = 0; i < length; ++i) {
- QRgba64 d = dest[i];
- dest[i] = interpolate65535(d, a, color, 65535 - d.alpha());
+ auto d = Ops::load(&dest[i]);
+ Ops::store(&dest[i], Ops::interpolate(c, Ops::invAlpha(d), d, sa));
}
}
-void QT_FASTCALL comp_func_DestinationAtop(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+template<class Ops>
+inline static void comp_func_DestinationAtop_template(typename Ops::Type *Q_DECL_RESTRICT dest,
+ const typename Ops::Type *Q_DECL_RESTRICT src,
+ int length, uint const_alpha)
{
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
- uint s = src[i];
- uint d = dest[i];
- dest[i] = INTERPOLATE_PIXEL_255(d, qAlpha(s), s, qAlpha(~d));
+ auto s = Ops::load(&src[i]);
+ auto d = Ops::load(&dest[i]);
+ Ops::store(&dest[i], Ops::interpolate(s, Ops::invAlpha(d), d, Ops::alpha(s)));
}
} else {
- uint cia = 255 - const_alpha;
+ auto cia = Ops::invAlpha(Ops::scalarFrom8bit(const_alpha));
for (int i = 0; i < length; ++i) {
- uint s = BYTE_MUL(src[i], const_alpha);
- uint d = dest[i];
- uint a = qAlpha(s) + cia;
- dest[i] = INTERPOLATE_PIXEL_255(d, a, s, qAlpha(~d));
+ auto s = Ops::multiplyAlpha8bit(Ops::load(&src[i]), const_alpha);
+ auto d = Ops::load(&dest[i]);
+ auto sa = Ops::add(Ops::alpha(s), cia);
+ Ops::store(&dest[i], Ops::interpolate(s, Ops::invAlpha(d), d, sa));
}
}
}
+void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length, uint color, uint const_alpha)
+{
+ comp_func_solid_DestinationAtop_template<Argb32Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_solid_DestinationAtop_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ comp_func_solid_DestinationAtop_template<Rgba64Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_DestinationAtop(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ comp_func_DestinationAtop_template<Argb32Operations>(dest, src, length, const_alpha);
+}
+
void QT_FASTCALL comp_func_DestinationAtop_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- QRgba64 s = src[i];
- QRgba64 d = dest[i];
- dest[i] = interpolate65535(d, s.alpha(), s, 65535 - d.alpha());
- }
- } else {
- uint ca = const_alpha * 257;
- uint cia = 65535 - ca;
- for (int i = 0; i < length; ++i) {
- QRgba64 s = multiplyAlpha65535(src[i], ca);
- QRgba64 d = dest[i];
- uint a = s.alpha() + cia;
- dest[i] = interpolate65535(d, a, s, 65535 - d.alpha());
- }
- }
+ comp_func_DestinationAtop_template<Rgba64Operations>(dest, src, length, const_alpha);
}
/*
@@ -723,62 +930,58 @@ void QT_FASTCALL comp_func_DestinationAtop_rgb64(QRgba64 *Q_DECL_RESTRICT dest,
= s*ca * dia + d * (sia*ca + cia)
= s*ca * dia + d * (1 - sa*ca)
*/
-void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_solid_XOR_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
{
+ auto c = Ops::convert(color);
if (const_alpha != 255)
- color = BYTE_MUL(color, const_alpha);
- uint sia = qAlpha(~color);
+ c = Ops::multiplyAlpha8bit(c, const_alpha);
+ auto sia = Ops::invAlpha(c);
for (int i = 0; i < length; ++i) {
- uint d = dest[i];
- dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(~d), d, sia);
+ auto d = Ops::load(&dest[i]);
+ Ops::store(&dest[i], Ops::interpolate(c, Ops::invAlpha(d), d, sia));
}
}
-void QT_FASTCALL comp_func_solid_XOR_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
-{
- if (const_alpha != 255)
- color = multiplyAlpha255(color, const_alpha);
- auto s = CONVERT(color);
- auto sia = CONST(65535 - color.alpha());
- for (int i = 0; i < length; ++i) {
- auto d = LOAD(&dest[i]);
- STORE(&dest[i], interpolate65535(s, INVALPHA(d), d, sia));
- }
-}
-
-void QT_FASTCALL comp_func_XOR(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+template<class Ops>
+inline static void comp_func_XOR_template(typename Ops::Type *Q_DECL_RESTRICT dest,
+ const typename Ops::Type *Q_DECL_RESTRICT src,
+ int length, uint const_alpha)
{
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
- uint d = dest[i];
- uint s = src[i];
- dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, qAlpha(~s));
+ auto d = Ops::load(&dest[i]);
+ auto s = Ops::load(&src[i]);
+ Ops::store(&dest[i], Ops::interpolate(s, Ops::invAlpha(d), d, Ops::invAlpha(s)));
}
} else {
for (int i = 0; i < length; ++i) {
- uint d = dest[i];
- uint s = BYTE_MUL(src[i], const_alpha);
- dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, qAlpha(~s));
+ auto d = Ops::load(&dest[i]);
+ auto s = Ops::multiplyAlpha8bit(Ops::load(&src[i]), const_alpha);
+ Ops::store(&dest[i], Ops::interpolate(s, Ops::invAlpha(d), d, Ops::invAlpha(s)));
}
}
}
+void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color, uint const_alpha)
+{
+ comp_func_solid_XOR_template<Argb32Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_solid_XOR_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ comp_func_solid_XOR_template<Rgba64Operations>(dest, length, color, const_alpha);
+}
+
+void QT_FASTCALL comp_func_XOR(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ comp_func_XOR_template<Argb32Operations>(dest, src, length, const_alpha);
+}
+
void QT_FASTCALL comp_func_XOR_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- auto d = LOAD(&dest[i]);
- auto s = LOAD(&src[i]);
- STORE(&dest[i], interpolate65535(s, INVALPHA(d), d, INVALPHA(s)));
- }
- } else {
- for (int i = 0; i < length; ++i) {
- auto d = LOAD(&dest[i]);
- auto s = multiplyAlpha255(LOAD(&src[i]), const_alpha);
- STORE(&dest[i], interpolate65535(s, INVALPHA(d), d, INVALPHA(s)));
- }
- }
+ comp_func_XOR_template<Rgba64Operations>(dest, src, length, const_alpha);
}
struct QFullCoverage {
@@ -827,84 +1030,67 @@ static inline uint mix_alpha_rgb64(uint da, uint sa)
Dca' = Sca.Da + Dca.Sa + Sca.(1 - Da) + Dca.(1 - Sa)
= Sca + Dca
*/
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Plus_impl(uint *dest, int length, uint color, const T &coverage)
+template<class Ops>
+inline static void comp_func_solid_Plus_template(typename Ops::Type *dest, int length, typename Ops::Type color, uint const_alpha)
{
- uint s = color;
-
- for (int i = 0; i < length; ++i) {
- uint d = dest[i];
- d = comp_func_Plus_one_pixel(d, s);
- coverage.store(&dest[i], d);
+ auto c = Ops::convert(color);
+ if (const_alpha == 255) {
+ for (int i = 0; i < length; ++i) {
+ auto d = Ops::load(&dest[i]);
+ d = Ops::plus(d, c);
+ Ops::store(&dest[i], d);
+ }
+ } else {
+ uint ia = 255 - const_alpha;
+ for (int i = 0; i < length; ++i) {
+ auto d = Ops::load(&dest[i]);
+ d = Ops::interpolate8bit(Ops::plus(d, c), const_alpha, d, ia);
+ Ops::store(&dest[i], d);
+ }
}
}
-void QT_FASTCALL comp_func_solid_Plus(uint *dest, int length, uint color, uint const_alpha)
+template<class Ops>
+inline static void comp_func_Plus_template(typename Ops::Type *Q_DECL_RESTRICT dest,
+ const typename Ops::Type *Q_DECL_RESTRICT src,
+ int length, uint const_alpha)
{
- if (const_alpha == 255)
- comp_func_solid_Plus_impl(dest, length, color, QFullCoverage());
- else
- comp_func_solid_Plus_impl(dest, length, color, QPartialCoverage(const_alpha));
-}
-
-void QT_FASTCALL comp_func_solid_Plus_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
-{
- auto b = CONVERT(color);
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
- auto a = LOAD(&dest[i]);
- a = addWithSaturation(a, b);
- STORE(&dest[i], a);
+ auto d = Ops::load(&dest[i]);
+ auto s = Ops::load(&src[i]);
+ d = Ops::plus(d, s);
+ Ops::store(&dest[i], d);
}
} else {
+ uint ia = 255 - const_alpha;
for (int i = 0; i < length; ++i) {
- auto a = LOAD(&dest[i]);
- auto d = addWithSaturation(a, b);
- a = interpolate255(d, const_alpha, a, 255 - const_alpha);
- STORE(&dest[i], a);
+ auto d = Ops::load(&dest[i]);
+ auto s = Ops::load(&src[i]);
+ d = Ops::interpolate8bit(Ops::plus(d, s), const_alpha, d, ia);
+ Ops::store(&dest[i], d);
}
}
}
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Plus_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
+void QT_FASTCALL comp_func_solid_Plus(uint *dest, int length, uint color, uint const_alpha)
{
- for (int i = 0; i < length; ++i) {
- uint d = dest[i];
- uint s = src[i];
-
- d = comp_func_Plus_one_pixel(d, s);
+ comp_func_solid_Plus_template<Argb32Operations>(dest, length, color, const_alpha);
+}
- coverage.store(&dest[i], d);
- }
+void QT_FASTCALL comp_func_solid_Plus_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ comp_func_solid_Plus_template<Rgba64Operations>(dest, length, color, const_alpha);
}
void QT_FASTCALL comp_func_Plus(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255)
- comp_func_Plus_impl(dest, src, length, QFullCoverage());
- else
- comp_func_Plus_impl(dest, src, length, QPartialCoverage(const_alpha));
+ comp_func_Plus_template<Argb32Operations>(dest, src, length, const_alpha);
}
void QT_FASTCALL comp_func_Plus_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
- if (const_alpha == 255) {
- for (int i = 0; i < length; ++i) {
- auto a = LOAD(&dest[i]);
- auto b = LOAD(&src[i]);
- a = addWithSaturation(a, b);
- STORE(&dest[i], a);
- }
- } else {
- for (int i = 0; i < length; ++i) {
- auto a = LOAD(&dest[i]);
- auto b = LOAD(&src[i]);
- auto d = addWithSaturation(a, b);
- a = interpolate255(d, const_alpha, a, 255 - const_alpha);
- STORE(&dest[i], a);
- }
- }
+ comp_func_Plus_template<Rgba64Operations>(dest, src, length, const_alpha);
}
/*
diff --git a/src/gui/painting/qcosmeticstroker_p.h b/src/gui/painting/qcosmeticstroker_p.h
index 68f4e00cdc..082ddee30f 100644
--- a/src/gui/painting/qcosmeticstroker_p.h
+++ b/src/gui/painting/qcosmeticstroker_p.h
@@ -85,6 +85,7 @@ public:
// used to avoid drop outs or duplicated points
enum Direction {
+ NoDirection = 0,
TopToBottom = 0x1,
BottomToTop = 0x2,
LeftToRight = 0x4,
@@ -104,7 +105,7 @@ public:
patternOffset(0),
legacyRounding(false),
current_span(0),
- lastDir(LeftToRight),
+ lastDir(NoDirection),
lastAxisAligned(false)
{ setup(); }
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 0f2d163840..bbeb9fd9ea 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -73,9 +73,6 @@ enum {
half_point = 1 << 15
};
-// must be multiple of 4 for easier SIMD implementations
-static const int buffer_size = 2048;
-
template<QImage::Format> Q_DECL_CONSTEXPR uint redWidth();
template<QImage::Format> Q_DECL_CONSTEXPR uint redShift();
template<QImage::Format> Q_DECL_CONSTEXPR uint greenWidth();
@@ -94,6 +91,10 @@ template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_ARGB4444_Premultiplied>
template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_ARGB8555_Premultiplied>() { return 5; }
template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_ARGB8565_Premultiplied>() { return 5; }
template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_ARGB6666_Premultiplied>() { return 6; }
+template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_RGBX8888>() { return 8; }
+template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_RGBA8888>() { return 8; }
+template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_RGBA8888_Premultiplied>() { return 8; }
+
template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGB16>() { return 11; }
template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGB444>() { return 8; }
template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGB555>() { return 10; }
@@ -103,6 +104,15 @@ template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_ARGB4444_Premultiplied>
template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_ARGB8555_Premultiplied>() { return 18; }
template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_ARGB8565_Premultiplied>() { return 19; }
template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_ARGB6666_Premultiplied>() { return 12; }
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGBX8888>() { return 24; }
+template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGBA8888>() { return 24; }
+template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGBA8888_Premultiplied>() { return 24; }
+#else
+template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGBX8888>() { return 0; }
+template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGBA8888>() { return 0; }
+template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGBA8888_Premultiplied>() { return 0; }
+#endif
template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_RGB16>() { return 6; }
template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_RGB444>() { return 4; }
template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_RGB555>() { return 5; }
@@ -112,6 +122,10 @@ template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_ARGB4444_Premultiplie
template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_ARGB8555_Premultiplied>() { return 5; }
template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_ARGB8565_Premultiplied>() { return 6; }
template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_ARGB6666_Premultiplied>() { return 6; }
+template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_RGBX8888>() { return 8; }
+template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_RGBA8888>() { return 8; }
+template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_RGBA8888_Premultiplied>() { return 8; }
+
template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGB16>() { return 5; }
template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGB444>() { return 4; }
template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGB555>() { return 5; }
@@ -121,6 +135,15 @@ template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_ARGB4444_Premultiplie
template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_ARGB8555_Premultiplied>() { return 13; }
template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_ARGB8565_Premultiplied>() { return 13; }
template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_ARGB6666_Premultiplied>() { return 6; }
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGBX8888>() { return 16; }
+template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGBA8888>() { return 16; }
+template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGBA8888_Premultiplied>() { return 16; }
+#else
+template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGBX8888>() { return 8; }
+template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGBA8888>() { return 8; }
+template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGBA8888_Premultiplied>() { return 8; }
+#endif
template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_RGB16>() { return 5; }
template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_RGB444>() { return 4; }
template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_RGB555>() { return 5; }
@@ -130,6 +153,10 @@ template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_ARGB4444_Premultiplied
template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_ARGB8555_Premultiplied>() { return 5; }
template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_ARGB8565_Premultiplied>() { return 5; }
template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_ARGB6666_Premultiplied>() { return 6; }
+template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_RGBX8888>() { return 8; }
+template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_RGBA8888>() { return 8; }
+template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_RGBA8888_Premultiplied>() { return 8; }
+
template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGB16>() { return 0; }
template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGB444>() { return 0; }
template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGB555>() { return 0; }
@@ -139,6 +166,15 @@ template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_ARGB4444_Premultiplied
template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_ARGB8555_Premultiplied>() { return 8; }
template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_ARGB8565_Premultiplied>() { return 8; }
template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_ARGB6666_Premultiplied>() { return 0; }
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGBX8888>() { return 8; }
+template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGBA8888>() { return 8; }
+template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGBA8888_Premultiplied>() { return 8; }
+#else
+template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGBX8888>() { return 16; }
+template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGBA8888>() { return 16; }
+template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGBA8888_Premultiplied>() { return 16; }
+#endif
template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_RGB16>() { return 0; }
template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_RGB444>() { return 0; }
template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_RGB555>() { return 0; }
@@ -148,6 +184,10 @@ template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_ARGB4444_Premultiplie
template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_ARGB8555_Premultiplied>() { return 8; }
template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_ARGB8565_Premultiplied>() { return 8; }
template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_ARGB6666_Premultiplied>() { return 6; }
+template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_RGBX8888>() { return 0; }
+template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_RGBA8888>() { return 8; }
+template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_RGBA8888_Premultiplied>() { return 8; }
+
template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGB16>() { return 0; }
template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGB444>() { return 0; }
template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGB555>() { return 0; }
@@ -157,138 +197,200 @@ template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_ARGB4444_Premultiplie
template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_ARGB8555_Premultiplied>() { return 0; }
template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_ARGB8565_Premultiplied>() { return 0; }
template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_ARGB6666_Premultiplied>() { return 18; }
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGBX8888>() { return 0; }
+template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGBA8888>() { return 0; }
+template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGBA8888_Premultiplied>() { return 0; }
+#else
+template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGBX8888>() { return 24; }
+template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGBA8888>() { return 24; }
+template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGBA8888_Premultiplied>() { return 24; }
+#endif
-template<QImage::Format> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel();
-template<> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB16>() { return QPixelLayout::BPP16; }
-template<> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB444>() { return QPixelLayout::BPP16; }
-template<> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB555>() { return QPixelLayout::BPP16; }
-template<> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB666>() { return QPixelLayout::BPP24; }
-template<> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB888>() { return QPixelLayout::BPP24; }
-template<> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel<QImage::Format_ARGB4444_Premultiplied>() { return QPixelLayout::BPP16; }
-template<> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel<QImage::Format_ARGB8555_Premultiplied>() { return QPixelLayout::BPP24; }
-template<> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel<QImage::Format_ARGB8565_Premultiplied>() { return QPixelLayout::BPP24; }
-template<> Q_DECL_CONSTEXPR QPixelLayout::BPP bitsPerPixel<QImage::Format_ARGB6666_Premultiplied>() { return QPixelLayout::BPP24; }
+template<QImage::Format> constexpr QPixelLayout::BPP bitsPerPixel();
+template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB16>() { return QPixelLayout::BPP16; }
+template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB444>() { return QPixelLayout::BPP16; }
+template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB555>() { return QPixelLayout::BPP16; }
+template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB666>() { return QPixelLayout::BPP24; }
+template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB888>() { return QPixelLayout::BPP24; }
+template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_ARGB4444_Premultiplied>() { return QPixelLayout::BPP16; }
+template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_ARGB8555_Premultiplied>() { return QPixelLayout::BPP24; }
+template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_ARGB8565_Premultiplied>() { return QPixelLayout::BPP24; }
+template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_ARGB6666_Premultiplied>() { return QPixelLayout::BPP24; }
+template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_RGBX8888>() { return QPixelLayout::BPP32; }
+template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_RGBA8888>() { return QPixelLayout::BPP32; }
+template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_RGBA8888_Premultiplied>() { return QPixelLayout::BPP32; }
-template<QImage::Format Format>
-static const uint *QT_FASTCALL convertToRGB32(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+typedef const uint *(QT_FASTCALL *FetchPixelsFunc)(uint *buffer, const uchar *src, int index, int count);
+
+template <QPixelLayout::BPP bpp> static
+uint QT_FASTCALL fetchPixel(const uchar *, int)
{
- auto conversion = [](uint s) {
- // MSVC needs these constexpr defined in here otherwise it will create a capture.
- Q_CONSTEXPR uint redMask = ((1 << redWidth<Format>()) - 1);
- Q_CONSTEXPR uint greenMask = ((1 << greenWidth<Format>()) - 1);
- Q_CONSTEXPR uint blueMask = ((1 << blueWidth<Format>()) - 1);
+ Q_UNREACHABLE();
+ return 0;
+}
- Q_CONSTEXPR uchar redLeftShift = 8 - redWidth<Format>();
- Q_CONSTEXPR uchar greenLeftShift = 8 - greenWidth<Format>();
- Q_CONSTEXPR uchar blueLeftShift = 8 - blueWidth<Format>();
+template <>
+inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP1LSB>(const uchar *src, int index)
+{
+ return (src[index >> 3] >> (index & 7)) & 1;
+}
- Q_CONSTEXPR uchar redRightShift = 2 * redWidth<Format>() - 8;
- Q_CONSTEXPR uchar greenRightShift = 2 * greenWidth<Format>() - 8;
- Q_CONSTEXPR uchar blueRightShift = 2 * blueWidth<Format>() - 8;
+template <>
+inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP1MSB>(const uchar *src, int index)
+{
+ return (src[index >> 3] >> (~index & 7)) & 1;
+}
- uint red = (s >> redShift<Format>()) & redMask;
- uint green = (s >> greenShift<Format>()) & greenMask;
- uint blue = (s >> blueShift<Format>()) & blueMask;
+template <>
+inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP8>(const uchar *src, int index)
+{
+ return src[index];
+}
- red = ((red << redLeftShift) | (red >> redRightShift)) << 16;
- green = ((green << greenLeftShift) | (green >> greenRightShift)) << 8;
- blue = (blue << blueLeftShift) | (blue >> blueRightShift);
- return 0xff000000 | red | green | blue;
- };
+template <>
+inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP16>(const uchar *src, int index)
+{
+ return reinterpret_cast<const quint16 *>(src)[index];
+}
- UNALIASED_CONVERSION_LOOP(buffer, src, count, conversion);
- return buffer;
+template <>
+inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP24>(const uchar *src, int index)
+{
+ return reinterpret_cast<const quint24 *>(src)[index];
}
-template<QImage::Format Format>
-static const QRgba64 *QT_FASTCALL convertToRGB64(QRgba64 *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+template <>
+inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP32>(const uchar *src, int index)
{
- Q_CONSTEXPR uint redMask = ((1 << redWidth<Format>()) - 1);
- Q_CONSTEXPR uint greenMask = ((1 << greenWidth<Format>()) - 1);
- Q_CONSTEXPR uint blueMask = ((1 << blueWidth<Format>()) - 1);
+ return reinterpret_cast<const uint *>(src)[index];
+}
- Q_CONSTEXPR uchar redLeftShift = 8 - redWidth<Format>();
- Q_CONSTEXPR uchar greenLeftShift = 8 - greenWidth<Format>();
- Q_CONSTEXPR uchar blueLeftShift = 8 - blueWidth<Format>();
+template <>
+inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP64>(const uchar *src, int index)
+{
+ // We have to do the conversion in fetch to fit into a 32bit uint
+ QRgba64 c = reinterpret_cast<const QRgba64 *>(src)[index];
+ return c.toArgb32();
+}
- Q_CONSTEXPR uchar redRightShift = 2 * redWidth<Format>() - 8;
- Q_CONSTEXPR uchar greenRightShift = 2 * greenWidth<Format>() - 8;
- Q_CONSTEXPR uchar blueRightShift = 2 * blueWidth<Format>() - 8;
+template <QPixelLayout::BPP bpp>
+static quint64 QT_FASTCALL fetchPixel64(const uchar *src, int index)
+{
+ Q_STATIC_ASSERT(bpp != QPixelLayout::BPP64);
+ return fetchPixel<bpp>(src, index);
+}
- for (int i = 0; i < count; ++i) {
- uint red = (src[i] >> redShift<Format>()) & redMask;
- uint green = (src[i] >> greenShift<Format>()) & greenMask;
- uint blue = (src[i] >> blueShift<Format>()) & blueMask;
+template <QPixelLayout::BPP width> static
+void QT_FASTCALL storePixel(uchar *dest, int index, uint pixel);
- red = ((red << redLeftShift) | (red >> redRightShift));
- green = ((green << greenLeftShift) | (green >> greenRightShift));
- blue = (blue << blueLeftShift) | (blue >> blueRightShift);
- buffer[i] = QRgba64::fromRgba(red, green, blue, 255);
- }
+template <>
+inline void QT_FASTCALL storePixel<QPixelLayout::BPP16>(uchar *dest, int index, uint pixel)
+{
+ reinterpret_cast<quint16 *>(dest)[index] = quint16(pixel);
+}
- return buffer;
+template <>
+inline void QT_FASTCALL storePixel<QPixelLayout::BPP24>(uchar *dest, int index, uint pixel)
+{
+ reinterpret_cast<quint24 *>(dest)[index] = quint24(pixel);
}
+typedef uint (QT_FASTCALL *FetchPixelFunc)(const uchar *src, int index);
+
+static const FetchPixelFunc qFetchPixel[QPixelLayout::BPPCount] = {
+ 0, // BPPNone
+ fetchPixel<QPixelLayout::BPP1MSB>, // BPP1MSB
+ fetchPixel<QPixelLayout::BPP1LSB>, // BPP1LSB
+ fetchPixel<QPixelLayout::BPP8>, // BPP8
+ fetchPixel<QPixelLayout::BPP16>, // BPP16
+ fetchPixel<QPixelLayout::BPP24>, // BPP24
+ fetchPixel<QPixelLayout::BPP32>, // BPP32
+ fetchPixel<QPixelLayout::BPP64> // BPP64
+};
+
template<QImage::Format Format>
-static const uint *QT_FASTCALL convertARGBPMToARGB32PM(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+static Q_ALWAYS_INLINE uint convertPixelToRGB32(uint s)
{
- Q_CONSTEXPR uint alphaMask = ((1 << alphaWidth<Format>()) - 1);
Q_CONSTEXPR uint redMask = ((1 << redWidth<Format>()) - 1);
Q_CONSTEXPR uint greenMask = ((1 << greenWidth<Format>()) - 1);
Q_CONSTEXPR uint blueMask = ((1 << blueWidth<Format>()) - 1);
- Q_CONSTEXPR uchar alphaLeftShift = 8 - alphaWidth<Format>();
Q_CONSTEXPR uchar redLeftShift = 8 - redWidth<Format>();
Q_CONSTEXPR uchar greenLeftShift = 8 - greenWidth<Format>();
Q_CONSTEXPR uchar blueLeftShift = 8 - blueWidth<Format>();
- Q_CONSTEXPR uchar alphaRightShift = 2 * alphaWidth<Format>() - 8;
Q_CONSTEXPR uchar redRightShift = 2 * redWidth<Format>() - 8;
Q_CONSTEXPR uchar greenRightShift = 2 * greenWidth<Format>() - 8;
Q_CONSTEXPR uchar blueRightShift = 2 * blueWidth<Format>() - 8;
- Q_CONSTEXPR bool mustMin = (alphaWidth<Format>() != redWidth<Format>()) ||
- (alphaWidth<Format>() != greenWidth<Format>()) ||
- (alphaWidth<Format>() != blueWidth<Format>());
+ uint red = (s >> redShift<Format>()) & redMask;
+ uint green = (s >> greenShift<Format>()) & greenMask;
+ uint blue = (s >> blueShift<Format>()) & blueMask;
- if (mustMin) {
- for (int i = 0; i < count; ++i) {
- uint alpha = (src[i] >> alphaShift<Format>()) & alphaMask;
- uint red = (src[i] >> redShift<Format>()) & redMask;
- uint green = (src[i] >> greenShift<Format>()) & greenMask;
- uint blue = (src[i] >> blueShift<Format>()) & blueMask;
-
- alpha = (alpha << alphaLeftShift) | (alpha >> alphaRightShift);
- red = qMin(alpha, (red << redLeftShift) | (red >> redRightShift));
- green = qMin(alpha, (green << greenLeftShift) | (green >> greenRightShift));
- blue = qMin(alpha, (blue << blueLeftShift) | (blue >> blueRightShift));
- buffer[i] = (alpha << 24) | (red << 16) | (green << 8) | blue;
- }
- } else {
- for (int i = 0; i < count; ++i) {
- uint alpha = (src[i] >> alphaShift<Format>()) & alphaMask;
- uint red = (src[i] >> redShift<Format>()) & redMask;
- uint green = (src[i] >> greenShift<Format>()) & greenMask;
- uint blue = (src[i] >> blueShift<Format>()) & blueMask;
-
- alpha = ((alpha << alphaLeftShift) | (alpha >> alphaRightShift)) << 24;
- red = ((red << redLeftShift) | (red >> redRightShift)) << 16;
- green = ((green << greenLeftShift) | (green >> greenRightShift)) << 8;
- blue = (blue << blueLeftShift) | (blue >> blueRightShift);
- buffer[i] = alpha | red | green | blue;
- }
+ red = ((red << redLeftShift) | (red >> redRightShift)) << 16;
+ green = ((green << greenLeftShift) | (green >> greenRightShift)) << 8;
+ blue = (blue << blueLeftShift) | (blue >> blueRightShift);
+ return 0xff000000 | red | green | blue;
+}
+
+template<QImage::Format Format>
+static void QT_FASTCALL convertToRGB32(uint *buffer, int count, const QVector<QRgb> *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = convertPixelToRGB32<Format>(buffer[i]);
+}
+
+#if defined(__SSE2__) && !defined(__SSSE3__) && QT_COMPILER_SUPPORTS_SSSE3
+extern const uint * QT_FASTCALL fetchPixelsBPP24_ssse3(uint *dest, const uchar*src, int index, int count);
+#endif
+
+template<QImage::Format Format>
+static const uint *QT_FASTCALL fetchRGBToRGB32(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ constexpr QPixelLayout::BPP BPP = bitsPerPixel<Format>();
+#if defined(__SSE2__) && !defined(__SSSE3__) && QT_COMPILER_SUPPORTS_SSSE3
+ if (BPP == QPixelLayout::BPP24 && qCpuHasFeature(SSSE3)) {
+ // With SSE2 can convertToRGB32 be vectorized, but it takes SSSE3
+ // to vectorize the deforested version below.
+ fetchPixelsBPP24_ssse3(buffer, src, index, count);
+ convertToRGB32<Format>(buffer, count, nullptr);
+ return buffer;
}
+#endif
+ for (int i = 0; i < count; ++i)
+ buffer[i] = convertPixelToRGB32<Format>(fetchPixel<BPP>(src, index + i));
+ return buffer;
+}
+template<QImage::Format Format>
+static Q_ALWAYS_INLINE QRgba64 convertPixelToRGB64(uint s)
+{
+ return QRgba64::fromArgb32(convertPixelToRGB32<Format>(s));
+}
+
+template<QImage::Format Format>
+static const QRgba64 *QT_FASTCALL convertToRGB64(QRgba64 *buffer, const uint *src, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = convertPixelToRGB64<Format>(src[i]);
return buffer;
}
template<QImage::Format Format>
-static const QRgba64 *QT_FASTCALL convertARGBPMToARGB64PM(QRgba64 *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+static const QRgba64 *QT_FASTCALL fetchRGBToRGB64(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = convertPixelToRGB64<Format>(fetchPixel<bitsPerPixel<Format>()>(src, index + i));
+ return buffer;
+}
+
+template<QImage::Format Format>
+static Q_ALWAYS_INLINE uint convertPixelToARGB32PM(uint s)
{
Q_CONSTEXPR uint alphaMask = ((1 << alphaWidth<Format>()) - 1);
Q_CONSTEXPR uint redMask = ((1 << redWidth<Format>()) - 1);
@@ -309,62 +411,101 @@ static const QRgba64 *QT_FASTCALL convertARGBPMToARGB64PM(QRgba64 *buffer, const
(alphaWidth<Format>() != greenWidth<Format>()) ||
(alphaWidth<Format>() != blueWidth<Format>());
+ uint alpha = (s >> alphaShift<Format>()) & alphaMask;
+ uint red = (s >> redShift<Format>()) & redMask;
+ uint green = (s >> greenShift<Format>()) & greenMask;
+ uint blue = (s >> blueShift<Format>()) & blueMask;
+
+ alpha = (alpha << alphaLeftShift) | (alpha >> alphaRightShift);
+ red = (red << redLeftShift) | (red >> redRightShift);
+ green = (green << greenLeftShift) | (green >> greenRightShift);
+ blue = (blue << blueLeftShift) | (blue >> blueRightShift);
+
if (mustMin) {
- for (int i = 0; i < count; ++i) {
- uint alpha = (src[i] >> alphaShift<Format>()) & alphaMask;
- uint red = (src[i] >> redShift<Format>()) & redMask;
- uint green = (src[i] >> greenShift<Format>()) & greenMask;
- uint blue = (src[i] >> blueShift<Format>()) & blueMask;
-
- alpha = (alpha << alphaLeftShift) | (alpha >> alphaRightShift);
- red = qMin(alpha, (red << redLeftShift) | (red >> redRightShift));
- green = qMin(alpha, (green << greenLeftShift) | (green >> greenRightShift));
- blue = qMin(alpha, (blue << blueLeftShift) | (blue >> blueRightShift));
- buffer[i] = QRgba64::fromRgba(red, green, blue, alpha);
- }
- } else {
- for (int i = 0; i < count; ++i) {
- uint alpha = (src[i] >> alphaShift<Format>()) & alphaMask;
- uint red = (src[i] >> redShift<Format>()) & redMask;
- uint green = (src[i] >> greenShift<Format>()) & greenMask;
- uint blue = (src[i] >> blueShift<Format>()) & blueMask;
-
- alpha = (alpha << alphaLeftShift) | (alpha >> alphaRightShift);
- red = (red << redLeftShift) | (red >> redRightShift);
- green = (green << greenLeftShift) | (green >> greenRightShift);
- blue = (blue << blueLeftShift) | (blue >> blueRightShift);
- buffer[i] = QRgba64::fromRgba(red, green, blue, alpha);
- }
+ red = qMin(alpha, red);
+ green = qMin(alpha, green);
+ blue = qMin(alpha, blue);
}
+ return (alpha << 24) | (red << 16) | (green << 8) | blue;
+}
+
+template<QImage::Format Format>
+static void QT_FASTCALL convertARGBPMToARGB32PM(uint *buffer, int count, const QVector<QRgb> *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = convertPixelToARGB32PM<Format>(buffer[i]);
+}
+
+template<QImage::Format Format>
+static const uint *QT_FASTCALL fetchARGBPMToARGB32PM(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ constexpr QPixelLayout::BPP BPP = bitsPerPixel<Format>();
+#if defined(__SSE2__) && !defined(__SSSE3__) && QT_COMPILER_SUPPORTS_SSSE3
+ if (BPP == QPixelLayout::BPP24 && qCpuHasFeature(SSSE3)) {
+ // With SSE2 can convertToRGB32 be vectorized, but it takes SSSE3
+ // to vectorize the deforested version below.
+ fetchPixelsBPP24_ssse3(buffer, src, index, count);
+ convertARGBPMToARGB32PM<Format>(buffer, count, nullptr);
+ return buffer;
+ }
+#endif
+ for (int i = 0; i < count; ++i)
+ buffer[i] = convertPixelToARGB32PM<Format>(fetchPixel<BPP>(src, index + i));
+ return buffer;
+}
+
+template<QImage::Format Format>
+static Q_ALWAYS_INLINE QRgba64 convertPixelToRGBA64PM(uint s)
+{
+ return QRgba64::fromArgb32(convertPixelToARGB32PM<Format>(s));
+}
+
+template<QImage::Format Format>
+static const QRgba64 *QT_FASTCALL convertARGBPMToRGBA64PM(QRgba64 *buffer, const uint *src, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = convertPixelToRGB64<Format>(src[i]);
+ return buffer;
+}
+
+template<QImage::Format Format>
+static const QRgba64 *QT_FASTCALL fetchARGBPMToRGBA64PM(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ constexpr QPixelLayout::BPP bpp = bitsPerPixel<Format>();
+ for (int i = 0; i < count; ++i)
+ buffer[i] = convertPixelToRGBA64PM<Format>(fetchPixel<bpp>(src, index + i));
return buffer;
}
template<QImage::Format Format, bool fromRGB>
-static const uint *QT_FASTCALL convertRGBFromARGB32PM(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *dither)
+static void QT_FASTCALL storeRGBFromARGB32PM(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *dither)
{
Q_CONSTEXPR uchar rWidth = redWidth<Format>();
Q_CONSTEXPR uchar gWidth = greenWidth<Format>();
Q_CONSTEXPR uchar bWidth = blueWidth<Format>();
+ constexpr QPixelLayout::BPP BPP = bitsPerPixel<Format>();
// RGB32 -> RGB888 is not a precision loss.
if (!dither || (rWidth == 8 && gWidth == 8 && bWidth == 8)) {
- auto conversion = [](uint s) {
- const uint c = fromRGB ? s : qUnpremultiply(s);
- Q_CONSTEXPR uint rMask = (1 << redWidth<Format>()) - 1;
- Q_CONSTEXPR uint gMask = (1 << greenWidth<Format>()) - 1;
- Q_CONSTEXPR uint bMask = (1 << blueWidth<Format>()) - 1;
- Q_CONSTEXPR uchar rRightShift = 24 - redWidth<Format>();
- Q_CONSTEXPR uchar gRightShift = 16 - greenWidth<Format>();
- Q_CONSTEXPR uchar bRightShift = 8 - blueWidth<Format>();
+ Q_CONSTEXPR uint rMask = (1 << redWidth<Format>()) - 1;
+ Q_CONSTEXPR uint gMask = (1 << greenWidth<Format>()) - 1;
+ Q_CONSTEXPR uint bMask = (1 << blueWidth<Format>()) - 1;
+ Q_CONSTEXPR uchar rRightShift = 24 - redWidth<Format>();
+ Q_CONSTEXPR uchar gRightShift = 16 - greenWidth<Format>();
+ Q_CONSTEXPR uchar bRightShift = 8 - blueWidth<Format>();
+ for (int i = 0; i < count; ++i) {
+ const uint c = fromRGB ? src[i] : qUnpremultiply(src[i]);
const uint r = ((c >> rRightShift) & rMask) << redShift<Format>();
const uint g = ((c >> gRightShift) & gMask) << greenShift<Format>();
const uint b = ((c >> bRightShift) & bMask) << blueShift<Format>();
- return r | g | b;
+ storePixel<BPP>(dest, index + i, r | g | b);
};
- UNALIASED_CONVERSION_LOOP(buffer, src, count, conversion);
} else {
// We do ordered dither by using a rounding conversion, but instead of
// adding half of input precision, we add the adjusted result from the
@@ -384,38 +525,39 @@ static const uint *QT_FASTCALL convertRGBFromARGB32PM(uint *buffer, const uint *
r = (r + ((dr - r) >> rWidth) + 1) >> (8 - rWidth);
g = (g + ((dg - g) >> gWidth) + 1) >> (8 - gWidth);
b = (b + ((db - b) >> bWidth) + 1) >> (8 - bWidth);
- buffer[i] = (r << redShift<Format>())
- | (g << greenShift<Format>())
- | (b << blueShift<Format>());
+ const uint s = (r << redShift<Format>())
+ | (g << greenShift<Format>())
+ | (b << blueShift<Format>());
+ storePixel<BPP>(dest, index + i, s);
}
}
- return buffer;
}
template<QImage::Format Format, bool fromRGB>
-static const uint *QT_FASTCALL convertARGBPMFromARGB32PM(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *dither)
+static void QT_FASTCALL storeARGBPMFromARGB32PM(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *dither)
{
+ constexpr QPixelLayout::BPP BPP = bitsPerPixel<Format>();
if (!dither) {
- auto conversion = [](uint c) {
- Q_CONSTEXPR uint aMask = (1 << alphaWidth<Format>()) - 1;
- Q_CONSTEXPR uint rMask = (1 << redWidth<Format>()) - 1;
- Q_CONSTEXPR uint gMask = (1 << greenWidth<Format>()) - 1;
- Q_CONSTEXPR uint bMask = (1 << blueWidth<Format>()) - 1;
-
- Q_CONSTEXPR uchar aRightShift = 32 - alphaWidth<Format>();
- Q_CONSTEXPR uchar rRightShift = 24 - redWidth<Format>();
- Q_CONSTEXPR uchar gRightShift = 16 - greenWidth<Format>();
- Q_CONSTEXPR uchar bRightShift = 8 - blueWidth<Format>();
-
- Q_CONSTEXPR uint aOpaque = aMask << alphaShift<Format>();
+ Q_CONSTEXPR uint aMask = (1 << alphaWidth<Format>()) - 1;
+ Q_CONSTEXPR uint rMask = (1 << redWidth<Format>()) - 1;
+ Q_CONSTEXPR uint gMask = (1 << greenWidth<Format>()) - 1;
+ Q_CONSTEXPR uint bMask = (1 << blueWidth<Format>()) - 1;
+
+ Q_CONSTEXPR uchar aRightShift = 32 - alphaWidth<Format>();
+ Q_CONSTEXPR uchar rRightShift = 24 - redWidth<Format>();
+ Q_CONSTEXPR uchar gRightShift = 16 - greenWidth<Format>();
+ Q_CONSTEXPR uchar bRightShift = 8 - blueWidth<Format>();
+
+ Q_CONSTEXPR uint aOpaque = aMask << alphaShift<Format>();
+ for (int i = 0; i < count; ++i) {
+ const uint c = src[i];
const uint a = fromRGB ? aOpaque : (((c >> aRightShift) & aMask) << alphaShift<Format>());
const uint r = ((c >> rRightShift) & rMask) << redShift<Format>();
const uint g = ((c >> gRightShift) & gMask) << greenShift<Format>();
const uint b = ((c >> bRightShift) & bMask) << blueShift<Format>();
- return a | r | g | b;
+ storePixel<BPP>(dest, index + i, a | r | g | b);
};
- UNALIASED_CONVERSION_LOOP(buffer, src, count, conversion);
} else {
Q_CONSTEXPR uchar aWidth = alphaWidth<Format>();
Q_CONSTEXPR uchar rWidth = redWidth<Format>();
@@ -441,59 +583,147 @@ static const uint *QT_FASTCALL convertARGBPMFromARGB32PM(uint *buffer, const uin
r = (r + ((dr - r) >> rWidth) + 1) >> (8 - rWidth);
g = (g + ((dg - g) >> gWidth) + 1) >> (8 - gWidth);
b = (b + ((db - b) >> bWidth) + 1) >> (8 - bWidth);
- buffer[i] = (a << alphaShift<Format>())
- | (r << redShift<Format>())
- | (g << greenShift<Format>())
- | (b << blueShift<Format>());
+ uint s = (a << alphaShift<Format>())
+ | (r << redShift<Format>())
+ | (g << greenShift<Format>())
+ | (b << blueShift<Format>());
+ storePixel<BPP>(dest, index + i, s);
}
}
- return buffer;
}
+template<QImage::Format Format>
+static void QT_FASTCALL rbSwap(uchar *dst, const uchar *src, int count)
+{
+ Q_CONSTEXPR uchar aWidth = alphaWidth<Format>();
+ Q_CONSTEXPR uchar aShift = alphaShift<Format>();
+ Q_CONSTEXPR uchar rWidth = redWidth<Format>();
+ Q_CONSTEXPR uchar rShift = redShift<Format>();
+ Q_CONSTEXPR uchar gWidth = greenWidth<Format>();
+ Q_CONSTEXPR uchar gShift = greenShift<Format>();
+ Q_CONSTEXPR uchar bWidth = blueWidth<Format>();
+ Q_CONSTEXPR uchar bShift = blueShift<Format>();
#ifdef Q_COMPILER_CONSTEXPR
+ Q_STATIC_ASSERT(rWidth == bWidth);
+#endif
+ Q_CONSTEXPR uint redBlueMask = (1 << rWidth) - 1;
+ Q_CONSTEXPR uint alphaGreenMask = (((1 << aWidth) - 1) << aShift)
+ | (((1 << gWidth) - 1) << gShift);
+ constexpr QPixelLayout::BPP bpp = bitsPerPixel<Format>();
+
+ for (int i = 0; i < count; ++i) {
+ const uint c = fetchPixel<bpp>(src, i);
+ const uint r = (c >> rShift) & redBlueMask;
+ const uint b = (c >> bShift) & redBlueMask;
+ const uint t = (c & alphaGreenMask)
+ | (r << bShift)
+ | (b << rShift);
+ storePixel<bpp>(dst, i, t);
+ }
+}
+
+static void QT_FASTCALL rbSwap_rgb32(uchar *d, const uchar *s, int count)
+{
+ const uint *src = reinterpret_cast<const uint *>(s);
+ uint *dest = reinterpret_cast<uint *>(d);
+ for (int i = 0; i < count; ++i) {
+ const uint c = src[i];
+ const uint ag = c & 0xff00ff00;
+ const uint rb = c & 0x00ff00ff;
+ dest[i] = ag | (rb << 16) | (rb >> 16);
+ }
+}
+
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+template<>
+void QT_FASTCALL rbSwap<QImage::Format_RGBA8888>(uchar *d, const uchar *s, int count)
+{
+ return rbSwap_rgb32(d, s, count);
+}
+#else
+template<>
+void QT_FASTCALL rbSwap<QImage::Format_RGBA8888>(uchar *d, const uchar *s, int count)
+{
+ const uint *src = reinterpret_cast<const uint *>(s);
+ uint *dest = reinterpret_cast<uint *>(d);
+ for (int i = 0; i < count; ++i) {
+ const uint c = src[i];
+ const uint rb = c & 0xff00ff00;
+ const uint ga = c & 0x00ff00ff;
+ dest[i] = ga | (rb << 16) | (rb >> 16);
+ }
+}
+#endif
+
+static void QT_FASTCALL rbSwap_rgb30(uchar *d, const uchar *s, int count)
+{
+ const uint *src = reinterpret_cast<const uint *>(s);
+ uint *dest = reinterpret_cast<uint *>(d);
+ for (int i = 0; i < count; ++i)
+ dest[i] = qRgbSwapRgb30(src[i]);
+}
template<QImage::Format Format> Q_DECL_CONSTEXPR static inline QPixelLayout pixelLayoutRGB()
{
return QPixelLayout{
- uchar(redWidth<Format>()), uchar(redShift<Format>()),
- uchar(greenWidth<Format>()), uchar(greenShift<Format>()),
- uchar(blueWidth<Format>()), uchar(blueShift<Format>()),
- 0, 0,
- false, bitsPerPixel<Format>(),
+ false,
+ false,
+ bitsPerPixel<Format>(),
+ rbSwap<Format>,
convertToRGB32<Format>,
- convertRGBFromARGB32PM<Format, false>,
- convertRGBFromARGB32PM<Format, true>,
- convertToRGB64<Format>
+ convertToRGB64<Format>,
+ fetchRGBToRGB32<Format>,
+ fetchRGBToRGB64<Format>,
+ storeRGBFromARGB32PM<Format, false>,
+ storeRGBFromARGB32PM<Format, true>
};
}
template<QImage::Format Format> Q_DECL_CONSTEXPR static inline QPixelLayout pixelLayoutARGBPM()
{
return QPixelLayout{
- uchar(redWidth<Format>()), uchar(redShift<Format>()),
- uchar(greenWidth<Format>()), uchar(greenShift<Format>()),
- uchar(blueWidth<Format>()), uchar(blueShift<Format>()),
- uchar(alphaWidth<Format>()), uchar(alphaShift<Format>()),
- true, bitsPerPixel<Format>(),
+ true,
+ true,
+ bitsPerPixel<Format>(),
+ rbSwap<Format>,
convertARGBPMToARGB32PM<Format>,
- convertARGBPMFromARGB32PM<Format, false>,
- convertARGBPMFromARGB32PM<Format, true>,
- convertARGBPMToARGB64PM<Format>
+ convertARGBPMToRGBA64PM<Format>,
+ fetchARGBPMToARGB32PM<Format>,
+ fetchARGBPMToRGBA64PM<Format>,
+ storeARGBPMFromARGB32PM<Format, false>,
+ storeARGBPMFromARGB32PM<Format, true>
};
}
-#endif
-
-// To convert in place, let 'dest' and 'src' be the same.
-static const uint *QT_FASTCALL convertIndexedToARGB32PM(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *clut, QDitherInfo *)
+static void QT_FASTCALL convertIndexedToARGB32PM(uint *buffer, int count, const QVector<QRgb> *clut)
{
for (int i = 0; i < count; ++i)
- buffer[i] = qPremultiply(clut->at(src[i]));
+ buffer[i] = qPremultiply(clut->at(buffer[i]));
+}
+
+template<QPixelLayout::BPP BPP>
+static const uint *QT_FASTCALL fetchIndexedToARGB32PM(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *clut, QDitherInfo *)
+{
+ for (int i = 0; i < count; ++i) {
+ const uint s = fetchPixel<BPP>(src, index + i);
+ buffer[i] = qPremultiply(clut->at(s));
+ }
+ return buffer;
+}
+
+template<QPixelLayout::BPP BPP>
+static const QRgba64 *QT_FASTCALL fetchIndexedToRGBA64PM(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *clut, QDitherInfo *)
+{
+ for (int i = 0; i < count; ++i) {
+ const uint s = fetchPixel<BPP>(src, index + i);
+ buffer[i] = QRgba64::fromArgb32(clut->at(s)).premultiplied();
+ }
return buffer;
}
-static const QRgba64 *QT_FASTCALL convertIndexedToARGB64PM(QRgba64 *buffer, const uint *src, int count,
+static const QRgba64 *QT_FASTCALL convertIndexedToRGBA64PM(QRgba64 *buffer, const uint *src, int count,
const QVector<QRgb> *clut, QDitherInfo *)
{
for (int i = 0; i < count; ++i)
@@ -501,44 +731,77 @@ static const QRgba64 *QT_FASTCALL convertIndexedToARGB64PM(QRgba64 *buffer, cons
return buffer;
}
-static const uint *QT_FASTCALL convertPassThrough(uint *, const uint *src, int,
- const QVector<QRgb> *, QDitherInfo *)
+static void QT_FASTCALL convertPassThrough(uint *, int, const QVector<QRgb> *)
{
- return src;
}
-static const uint *QT_FASTCALL convertARGB32ToARGB32PM(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+static const uint *QT_FASTCALL fetchPassThrough(uint *, const uchar *src, int index, int,
+ const QVector<QRgb> *, QDitherInfo *)
{
- return qt_convertARGB32ToARGB32PM(buffer, src, count);
+ return reinterpret_cast<const uint *>(src) + index;
}
-static const uint *QT_FASTCALL convertRGBA8888PMToARGB32PM(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+static const QRgba64 *QT_FASTCALL fetchPassThrough64(QRgba64 *, const uchar *src, int index, int,
+ const QVector<QRgb> *, QDitherInfo *)
{
- UNALIASED_CONVERSION_LOOP(buffer, src, count, RGBA2ARGB);
- return buffer;
+ return reinterpret_cast<const QRgba64 *>(src) + index;
}
-static const uint *QT_FASTCALL convertRGBA8888ToARGB32PM(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+static void QT_FASTCALL storePassThrough(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
- return qt_convertRGBA8888ToARGB32PM(buffer, src, count);
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ if (d != src)
+ memcpy(d, src, count * sizeof(uint));
}
-static const uint *QT_FASTCALL convertAlpha8ToRGB32(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+static void QT_FASTCALL convertARGB32ToARGB32PM(uint *buffer, int count, const QVector<QRgb> *)
+{
+ qt_convertARGB32ToARGB32PM(buffer, buffer, count);
+}
+
+static const uint *QT_FASTCALL fetchARGB32ToARGB32PM(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ return qt_convertARGB32ToARGB32PM(buffer, reinterpret_cast<const uint *>(src) + index, count);
+}
+
+static void QT_FASTCALL convertRGBA8888PMToARGB32PM(uint *buffer, int count, const QVector<QRgb> *)
{
for (int i = 0; i < count; ++i)
- buffer[i] = qRgba(0, 0, 0, src[i]);
+ buffer[i] = RGBA2ARGB(buffer[i]);
+}
+
+static const uint *QT_FASTCALL fetchRGBA8888PMToARGB32PM(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ const uint *s = reinterpret_cast<const uint *>(src) + index;
+ UNALIASED_CONVERSION_LOOP(buffer, s, count, RGBA2ARGB);
return buffer;
}
-static const uint *QT_FASTCALL convertGrayscale8ToRGB32(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+static void QT_FASTCALL convertRGBA8888ToARGB32PM(uint *buffer, int count, const QVector<QRgb> *)
+{
+ qt_convertRGBA8888ToARGB32PM(buffer, buffer, count);
+}
+
+static const uint *QT_FASTCALL fetchRGBA8888ToARGB32PM(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ return qt_convertRGBA8888ToARGB32PM(buffer, reinterpret_cast<const uint *>(src) + index, count);
+}
+
+static void QT_FASTCALL convertAlpha8ToRGB32(uint *buffer, int count, const QVector<QRgb> *)
{
for (int i = 0; i < count; ++i)
- buffer[i] = qRgb(src[i], src[i], src[i]);
+ buffer[i] = qRgba(0, 0, 0, buffer[i]);
+}
+
+static const uint *QT_FASTCALL fetchAlpha8ToRGB32(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = qRgba(0, 0, 0, src[index + i]);
return buffer;
}
@@ -549,6 +812,31 @@ static const QRgba64 *QT_FASTCALL convertAlpha8ToRGB64(QRgba64 *buffer, const ui
buffer[i] = QRgba64::fromRgba(0, 0, 0, src[i]);
return buffer;
}
+static const QRgba64 *QT_FASTCALL fetchAlpha8ToRGB64(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = QRgba64::fromRgba(0, 0, 0, src[index + i]);
+ return buffer;
+}
+
+static void QT_FASTCALL convertGrayscale8ToRGB32(uint *buffer, int count, const QVector<QRgb> *)
+{
+ for (int i = 0; i < count; ++i) {
+ const uint s = buffer[i];
+ buffer[i] = qRgb(s, s, s);
+ }
+}
+
+static const uint *QT_FASTCALL fetchGrayscale8ToRGB32(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ for (int i = 0; i < count; ++i) {
+ const uint s = src[index + i];
+ buffer[i] = qRgb(s, s, s);
+ }
+ return buffer;
+}
static const QRgba64 *QT_FASTCALL convertGrayscale8ToRGB64(QRgba64 *buffer, const uint *src, int count,
const QVector<QRgb> *, QDitherInfo *)
@@ -558,24 +846,33 @@ static const QRgba64 *QT_FASTCALL convertGrayscale8ToRGB64(QRgba64 *buffer, cons
return buffer;
}
-static const uint *QT_FASTCALL convertARGB32FromARGB32PM(uint *buffer, const uint *src, int count,
+static const QRgba64 *QT_FASTCALL fetchGrayscale8ToRGB64(QRgba64 *buffer, const uchar *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *)
{
- for (int i = 0; i < count; ++i)
- buffer[i] = qUnpremultiply(src[i]);
+ for (int i = 0; i < count; ++i) {
+ const uint s = src[index + i];
+ buffer[i] = QRgba64::fromRgba(s, s, s, 255);
+ }
return buffer;
}
-static const uint *QT_FASTCALL convertRGBA8888PMFromARGB32PM(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+static void QT_FASTCALL storeARGB32FromARGB32PM(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
- UNALIASED_CONVERSION_LOOP(buffer, src, count, ARGB2RGBA);
- return buffer;
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ UNALIASED_CONVERSION_LOOP(d, src, count, [](uint c) { return qUnpremultiply(c); });
+}
+
+static void QT_FASTCALL storeRGBA8888PMFromARGB32PM(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ UNALIASED_CONVERSION_LOOP(d, src, count, ARGB2RGBA);
}
#ifdef __SSE2__
template<bool RGBA, bool maskAlpha>
-static inline void qConvertARGB32PMToARGB64PM_sse2(QRgba64 *buffer, const uint *src, int count)
+static inline void qConvertARGB32PMToRGBA64PM_sse2(QRgba64 *buffer, const uint *src, int count)
{
if (count <= 0)
return;
@@ -618,6 +915,66 @@ static inline void qConvertARGB32PMToARGB64PM_sse2(QRgba64 *buffer, const uint *
*buffer++ = QRgba64::fromArgb32(s);
}
}
+
+template<QtPixelOrder PixelOrder>
+static inline void qConvertRGBA64PMToA2RGB30PM_sse2(uint *dest, const QRgba64 *buffer, int count)
+{
+ const __m128i gmask = _mm_set1_epi32(0x000ffc00);
+ const __m128i cmask = _mm_set1_epi32(0x000003ff);
+ int i = 0;
+ __m128i vr, vg, vb, va;
+ for (; i < count && uintptr_t(buffer) & 0xF; ++i) {
+ *dest++ = qConvertRgb64ToRgb30<PixelOrder>(*buffer++);
+ }
+
+ for (; i < count-15; i += 16) {
+ // Repremultiplying is really expensive and hard to do in SIMD without AVX2,
+ // so we try to avoid it by checking if it is needed 16 samples at a time.
+ __m128i vOr = _mm_set1_epi32(0);
+ __m128i vAnd = _mm_set1_epi32(0xffffffff);
+ for (int j = 0; j < 16; j += 2) {
+ __m128i vs = _mm_load_si128((const __m128i*)(buffer + j));
+ vOr = _mm_or_si128(vOr, vs);
+ vAnd = _mm_and_si128(vAnd, vs);
+ }
+ const quint16 orAlpha = ((uint)_mm_extract_epi16(vOr, 3)) | ((uint)_mm_extract_epi16(vOr, 7));
+ const quint16 andAlpha = ((uint)_mm_extract_epi16(vAnd, 3)) & ((uint)_mm_extract_epi16(vAnd, 7));
+
+ if (andAlpha == 0xffff) {
+ for (int j = 0; j < 16; j += 2) {
+ __m128i vs = _mm_load_si128((const __m128i*)buffer);
+ buffer += 2;
+ vr = _mm_srli_epi64(vs, 6);
+ vg = _mm_srli_epi64(vs, 16 + 6 - 10);
+ vb = _mm_srli_epi64(vs, 32 + 6);
+ vr = _mm_and_si128(vr, cmask);
+ vg = _mm_and_si128(vg, gmask);
+ vb = _mm_and_si128(vb, cmask);
+ va = _mm_srli_epi64(vs, 48 + 14);
+ if (PixelOrder == PixelOrderRGB)
+ vr = _mm_slli_epi32(vr, 20);
+ else
+ vb = _mm_slli_epi32(vb, 20);
+ va = _mm_slli_epi32(va, 30);
+ __m128i vd = _mm_or_si128(_mm_or_si128(vr, vg), _mm_or_si128(vb, va));
+ vd = _mm_shuffle_epi32(vd, _MM_SHUFFLE(3, 1, 2, 0));
+ _mm_storel_epi64((__m128i*)dest, vd);
+ dest += 2;
+ }
+ } else if (orAlpha == 0) {
+ for (int j = 0; j < 16; ++j) {
+ *dest++ = 0;
+ buffer++;
+ }
+ } else {
+ for (int j = 0; j < 16; ++j)
+ *dest++ = qConvertRgb64ToRgb30<PixelOrder>(*buffer++);
+ }
+ }
+
+ SIMD_EPILOGUE(i, count, 15)
+ *dest++ = qConvertRgb64ToRgb30<PixelOrder>(*buffer++);
+}
#elif defined(__ARM_NEON__)
template<bool RGBA, bool maskAlpha>
static inline void qConvertARGB32PMToRGBA64PM_neon(QRgba64 *buffer, const uint *src, int count)
@@ -671,7 +1028,7 @@ static const QRgba64 *QT_FASTCALL convertRGB32ToRGB64(QRgba64 *buffer, const uin
const QVector<QRgb> *, QDitherInfo *)
{
#ifdef __SSE2__
- qConvertARGB32PMToARGB64PM_sse2<false, true>(buffer, src, count);
+ qConvertARGB32PMToRGBA64PM_sse2<false, true>(buffer, src, count);
#elif defined(__ARM_NEON__)
qConvertARGB32PMToRGBA64PM_neon<false, true>(buffer, src, count);
#else
@@ -681,11 +1038,17 @@ static const QRgba64 *QT_FASTCALL convertRGB32ToRGB64(QRgba64 *buffer, const uin
return buffer;
}
-static const QRgba64 *QT_FASTCALL convertARGB32ToARGB64PM(QRgba64 *buffer, const uint *src, int count,
+static const QRgba64 *QT_FASTCALL fetchRGB32ToRGB64(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ return convertRGB32ToRGB64(buffer, reinterpret_cast<const uint *>(src) + index, count, nullptr, nullptr);
+}
+
+static const QRgba64 *QT_FASTCALL convertARGB32ToRGBA64PM(QRgba64 *buffer, const uint *src, int count,
const QVector<QRgb> *, QDitherInfo *)
{
#ifdef __SSE2__
- qConvertARGB32PMToARGB64PM_sse2<false, false>(buffer, src, count);
+ qConvertARGB32PMToRGBA64PM_sse2<false, false>(buffer, src, count);
for (int i = 0; i < count; ++i)
buffer[i] = buffer[i].premultiplied();
#elif defined(__ARM_NEON__)
@@ -699,11 +1062,17 @@ static const QRgba64 *QT_FASTCALL convertARGB32ToARGB64PM(QRgba64 *buffer, const
return buffer;
}
-static const QRgba64 *QT_FASTCALL convertARGB32PMToARGB64PM(QRgba64 *buffer, const uint *src, int count,
+static const QRgba64 *QT_FASTCALL fetchARGB32ToRGBA64PM(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ return convertARGB32ToRGBA64PM(buffer, reinterpret_cast<const uint *>(src) + index, count, nullptr, nullptr);
+}
+
+static const QRgba64 *QT_FASTCALL convertARGB32PMToRGBA64PM(QRgba64 *buffer, const uint *src, int count,
const QVector<QRgb> *, QDitherInfo *)
{
#ifdef __SSE2__
- qConvertARGB32PMToARGB64PM_sse2<false, false>(buffer, src, count);
+ qConvertARGB32PMToRGBA64PM_sse2<false, false>(buffer, src, count);
#elif defined(__ARM_NEON__)
qConvertARGB32PMToRGBA64PM_neon<false, false>(buffer, src, count);
#else
@@ -713,11 +1082,36 @@ static const QRgba64 *QT_FASTCALL convertARGB32PMToARGB64PM(QRgba64 *buffer, con
return buffer;
}
-static const QRgba64 *QT_FASTCALL convertRGBA8888ToARGB64PM(QRgba64 *buffer, const uint *src, int count,
+static const QRgba64 *QT_FASTCALL fetchARGB32PMToRGBA64PM(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ return convertARGB32PMToRGBA64PM(buffer, reinterpret_cast<const uint *>(src) + index, count, nullptr, nullptr);
+}
+
+static void convertRGBA64ToRGBA64PM(QRgba64 *buffer, int count)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = buffer[i].premultiplied();
+}
+
+static void convertRGBA64PMToRGBA64PM(QRgba64 *, int)
+{
+}
+
+static const QRgba64 *QT_FASTCALL fetchRGBA64ToRGBA64PM(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ const QRgba64 *s = reinterpret_cast<const QRgba64 *>(src) + index;
+ for (int i = 0; i < count; ++i)
+ buffer[i] = QRgba64::fromRgba64(s[i]).premultiplied();
+ return buffer;
+}
+
+static const QRgba64 *QT_FASTCALL convertRGBA8888ToRGBA64PM(QRgba64 *buffer, const uint *src, int count,
const QVector<QRgb> *, QDitherInfo *)
{
#ifdef __SSE2__
- qConvertARGB32PMToARGB64PM_sse2<true, false>(buffer, src, count);
+ qConvertARGB32PMToRGBA64PM_sse2<true, false>(buffer, src, count);
for (int i = 0; i < count; ++i)
buffer[i] = buffer[i].premultiplied();
#elif defined(__ARM_NEON__)
@@ -731,11 +1125,17 @@ static const QRgba64 *QT_FASTCALL convertRGBA8888ToARGB64PM(QRgba64 *buffer, con
return buffer;
}
-static const QRgba64 *QT_FASTCALL convertRGBA8888PMToARGB64PM(QRgba64 *buffer, const uint *src, int count,
+static const QRgba64 *QT_FASTCALL fetchRGBA8888ToRGBA64PM(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ return convertRGBA8888ToRGBA64PM(buffer, reinterpret_cast<const uint *>(src) + index, count, nullptr, nullptr);
+}
+
+static const QRgba64 *QT_FASTCALL convertRGBA8888PMToRGBA64PM(QRgba64 *buffer, const uint *src, int count,
const QVector<QRgb> *, QDitherInfo *)
{
#ifdef __SSE2__
- qConvertARGB32PMToARGB64PM_sse2<true, false>(buffer, src, count);
+ qConvertARGB32PMToRGBA64PM_sse2<true, false>(buffer, src, count);
#elif defined(__ARM_NEON__)
qConvertARGB32PMToRGBA64PM_neon<true, false>(buffer, src, count);
#else
@@ -745,33 +1145,45 @@ static const QRgba64 *QT_FASTCALL convertRGBA8888PMToARGB64PM(QRgba64 *buffer, c
return buffer;
}
-static const uint *QT_FASTCALL convertRGBA8888FromARGB32PM(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+static const QRgba64 *QT_FASTCALL fetchRGBA8888PMToRGBA64PM(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
- for (int i = 0; i < count; ++i)
- buffer[i] = ARGB2RGBA(qUnpremultiply(src[i]));
- return buffer;
+ return convertRGBA8888PMToRGBA64PM(buffer, reinterpret_cast<const uint *>(src) + index, count, nullptr, nullptr);
}
-static const uint *QT_FASTCALL convertRGBXFromRGB32(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+static void QT_FASTCALL storeRGBA8888FromARGB32PM(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
- UNALIASED_CONVERSION_LOOP(buffer, src, count, [](uint c) { return ARGB2RGBA(0xff000000 | c); });
- return buffer;
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ UNALIASED_CONVERSION_LOOP(d, src, count, [](uint c) { return ARGB2RGBA(qUnpremultiply(c)); });
}
-static const uint *QT_FASTCALL convertRGBXFromARGB32PM(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+static void QT_FASTCALL storeRGBXFromRGB32(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ UNALIASED_CONVERSION_LOOP(d, src, count, [](uint c) { return ARGB2RGBA(0xff000000 | c); });
+}
+
+static void QT_FASTCALL storeRGBXFromARGB32PM(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ UNALIASED_CONVERSION_LOOP(d, src, count, [](uint c) { return ARGB2RGBA(0xff000000 | qUnpremultiply(c)); });
+}
+
+template<QtPixelOrder PixelOrder>
+static void QT_FASTCALL convertA2RGB30PMToARGB32PM(uint *buffer, int count, const QVector<QRgb> *)
{
for (int i = 0; i < count; ++i)
- buffer[i] = ARGB2RGBA(0xff000000 | qUnpremultiply(src[i]));
- return buffer;
+ buffer[i] = qConvertA2rgb30ToArgb32<PixelOrder>(buffer[i]);
}
template<QtPixelOrder PixelOrder>
-static const uint *QT_FASTCALL convertA2RGB30PMToARGB32PM(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *dither)
+static const uint *QT_FASTCALL fetchA2RGB30PMToARGB32PM(uint *buffer, const uchar *s, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *dither)
{
+ const uint *src = reinterpret_cast<const uint *>(s) + index;
if (!dither) {
UNALIASED_CONVERSION_LOOP(buffer, src, count, qConvertA2rgb30ToArgb32<PixelOrder>);
} else {
@@ -796,7 +1208,7 @@ static const uint *QT_FASTCALL convertA2RGB30PMToARGB32PM(uint *buffer, const ui
#ifdef __SSE2__
template<QtPixelOrder PixelOrder>
-static inline void qConvertA2RGB30PMToARGB64PM_sse2(QRgba64 *buffer, const uint *src, int count)
+static inline void qConvertA2RGB30PMToRGBA64PM_sse2(QRgba64 *buffer, const uint *src, int count)
{
if (count <= 0)
return;
@@ -839,11 +1251,11 @@ static inline void qConvertA2RGB30PMToARGB64PM_sse2(QRgba64 *buffer, const uint
#endif
template<QtPixelOrder PixelOrder>
-static const QRgba64 *QT_FASTCALL convertA2RGB30PMToARGB64PM(QRgba64 *buffer, const uint *src, int count,
+static const QRgba64 *QT_FASTCALL convertA2RGB30PMToRGBA64PM(QRgba64 *buffer, const uint *src, int count,
const QVector<QRgb> *, QDitherInfo *)
{
#ifdef __SSE2__
- qConvertA2RGB30PMToARGB64PM_sse2<PixelOrder>(buffer, src, count);
+ qConvertA2RGB30PMToRGBA64PM_sse2<PixelOrder>(buffer, src, count);
#else
for (int i = 0; i < count; ++i)
buffer[i] = qConvertA2rgb30ToRgb64<PixelOrder>(src[i]);
@@ -852,290 +1264,334 @@ static const QRgba64 *QT_FASTCALL convertA2RGB30PMToARGB64PM(QRgba64 *buffer, co
}
template<QtPixelOrder PixelOrder>
-static const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+static const QRgba64 *QT_FASTCALL fetchA2RGB30PMToRGBA64PM(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
- UNALIASED_CONVERSION_LOOP(buffer, src, count, qConvertArgb32ToA2rgb30<PixelOrder>);
- return buffer;
+ return convertA2RGB30PMToRGBA64PM<PixelOrder>(buffer, reinterpret_cast<const uint *>(src) + index, count, nullptr, nullptr);
}
template<QtPixelOrder PixelOrder>
-static const uint *QT_FASTCALL convertRGB30FromRGB32(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+static void QT_FASTCALL storeA2RGB30PMFromARGB32PM(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
- for (int i = 0; i < count; ++i)
- buffer[i] = qConvertRgb32ToRgb30<PixelOrder>(src[i]);
- return buffer;
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ UNALIASED_CONVERSION_LOOP(d, src, count, qConvertArgb32ToA2rgb30<PixelOrder>);
}
template<QtPixelOrder PixelOrder>
-static const uint *QT_FASTCALL convertRGB30FromARGB32PM(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+static void QT_FASTCALL storeRGB30FromRGB32(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
- UNALIASED_CONVERSION_LOOP(buffer, src, count, qConvertRgb32ToRgb30<PixelOrder>);
- return buffer;
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ UNALIASED_CONVERSION_LOOP(d, src, count, qConvertRgb32ToRgb30<PixelOrder>);
}
-static const uint *QT_FASTCALL convertAlpha8FromARGB32PM(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+template<QtPixelOrder PixelOrder>
+static void QT_FASTCALL storeRGB30FromARGB32PM(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
- for (int i = 0; i < count; ++i)
- buffer[i] = qAlpha(src[i]);
- return buffer;
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ UNALIASED_CONVERSION_LOOP(d, src, count, qConvertRgb32ToRgb30<PixelOrder>);
}
-static const uint *QT_FASTCALL convertGrayscale8FromRGB32(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+template<bool RGBA>
+void qt_convertRGBA64ToARGB32(uint *dst, const QRgba64 *src, int count)
{
- for (int i = 0; i < count; ++i)
- buffer[i] = qGray(src[i]);
- return buffer;
+ int i = 0;
+#ifdef __SSE2__
+ if (((uintptr_t)dst & 0x7) && count > 0) {
+ uint s = (*src++).toArgb32();
+ if (RGBA)
+ s = ARGB2RGBA(s);
+ *dst++ = s;
+ i++;
+ }
+ const __m128i vhalf = _mm_set1_epi32(0x80);
+ const __m128i vzero = _mm_setzero_si128();
+ for (; i < count-1; i += 2) {
+ __m128i vs = _mm_loadu_si128((const __m128i*)src);
+ src += 2;
+ if (!RGBA) {
+ vs = _mm_shufflelo_epi16(vs, _MM_SHUFFLE(3, 0, 1, 2));
+ vs = _mm_shufflehi_epi16(vs, _MM_SHUFFLE(3, 0, 1, 2));
+ }
+ __m128i v1 = _mm_unpacklo_epi16(vs, vzero);
+ __m128i v2 = _mm_unpackhi_epi16(vs, vzero);
+ v1 = _mm_add_epi32(v1, vhalf);
+ v2 = _mm_add_epi32(v2, vhalf);
+ v1 = _mm_sub_epi32(v1, _mm_srli_epi32(v1, 8));
+ v2 = _mm_sub_epi32(v2, _mm_srli_epi32(v2, 8));
+ v1 = _mm_srli_epi32(v1, 8);
+ v2 = _mm_srli_epi32(v2, 8);
+ v1 = _mm_packs_epi32(v1, v2);
+ v1 = _mm_packus_epi16(v1, vzero);
+ _mm_storel_epi64((__m128i*)(dst), v1);
+ dst += 2;
+ }
+#endif
+ for (; i < count; i++) {
+ uint s = (*src++).toArgb32();
+ if (RGBA)
+ s = ARGB2RGBA(s);
+ *dst++ = s;
+ }
}
+template void qt_convertRGBA64ToARGB32<false>(uint *dst, const QRgba64 *src, int count);
+template void qt_convertRGBA64ToARGB32<true>(uint *dst, const QRgba64 *src, int count);
-static const uint *QT_FASTCALL convertGrayscale8FromARGB32PM(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+
+static void QT_FASTCALL storeAlpha8FromARGB32PM(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
for (int i = 0; i < count; ++i)
- buffer[i] = qGray(qUnpremultiply(src[i]));
- return buffer;
+ dest[index + i] = qAlpha(src[i]);
}
-template <QPixelLayout::BPP bpp> static
-uint QT_FASTCALL fetchPixel(const uchar *, int)
+static void QT_FASTCALL storeGrayscale8FromRGB32(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
- Q_UNREACHABLE();
- return 0;
+ for (int i = 0; i < count; ++i)
+ dest[index + i] = qGray(src[i]);
}
-template <>
-inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP1LSB>(const uchar *src, int index)
+static void QT_FASTCALL storeGrayscale8FromARGB32PM(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
- return (src[index >> 3] >> (index & 7)) & 1;
+ for (int i = 0; i < count; ++i)
+ dest[index + i] = qGray(qUnpremultiply(src[i]));
}
-template <>
-inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP1MSB>(const uchar *src, int index)
+static const uint *QT_FASTCALL fetchRGB64ToRGB32(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
- return (src[index >> 3] >> (~index & 7)) & 1;
+ const QRgba64 *s = reinterpret_cast<const QRgba64 *>(src) + index;
+ for (int i = 0; i < count; ++i)
+ buffer[i] = toArgb32(s[i]);
+ return buffer;
}
-template <>
-inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP8>(const uchar *src, int index)
+static void QT_FASTCALL storeRGB64FromRGB32(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
- return src[index];
+ QRgba64 *d = reinterpret_cast<QRgba64 *>(dest) + index;
+ for (int i = 0; i < count; ++i)
+ d[i] = QRgba64::fromArgb32(src[i]);
}
-template <>
-inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP16>(const uchar *src, int index)
+static const uint *QT_FASTCALL fetchRGBA64ToARGB32PM(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
- return reinterpret_cast<const quint16 *>(src)[index];
+ const QRgba64 *s = reinterpret_cast<const QRgba64 *>(src) + index;
+ for (int i = 0; i < count; ++i)
+ buffer[i] = toArgb32(s[i].premultiplied());
+ return buffer;
}
-template <>
-inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP24>(const uchar *src, int index)
+static void QT_FASTCALL storeRGBA64FromARGB32PM(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
- return reinterpret_cast<const quint24 *>(src)[index];
+ QRgba64 *d = reinterpret_cast<QRgba64 *>(dest) + index;
+ for (int i = 0; i < count; ++i)
+ d[i] = QRgba64::fromArgb32(src[i]).unpremultiplied();
}
-template <>
-inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP32>(const uchar *src, int index)
-{
- return reinterpret_cast<const uint *>(src)[index];
-}
+// Note:
+// convertToArgb32() assumes that no color channel is less than 4 bits.
+// storeRGBFromARGB32PM() assumes that no color channel is more than 8 bits.
+// QImage::rgbSwapped() assumes that the red and blue color channels have the same number of bits.
+QPixelLayout qPixelLayouts[QImage::NImageFormats] = {
+ { false, false, QPixelLayout::BPPNone, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }, // Format_Invalid
+ { false, false, QPixelLayout::BPP1MSB, nullptr,
+ convertIndexedToARGB32PM, convertIndexedToRGBA64PM,
+ fetchIndexedToARGB32PM<QPixelLayout::BPP1MSB>, fetchIndexedToRGBA64PM<QPixelLayout::BPP1MSB>,
+ nullptr, nullptr }, // Format_Mono
+ { false, false, QPixelLayout::BPP1LSB, nullptr,
+ convertIndexedToARGB32PM, convertIndexedToRGBA64PM,
+ fetchIndexedToARGB32PM<QPixelLayout::BPP1LSB>, fetchIndexedToRGBA64PM<QPixelLayout::BPP1LSB>,
+ nullptr, nullptr }, // Format_MonoLSB
+ { false, false, QPixelLayout::BPP8, nullptr,
+ convertIndexedToARGB32PM, convertIndexedToRGBA64PM,
+ fetchIndexedToARGB32PM<QPixelLayout::BPP8>, fetchIndexedToRGBA64PM<QPixelLayout::BPP8>,
+ nullptr, nullptr }, // Format_Indexed8
+ // Technically using convertPassThrough to convert from ARGB32PM to RGB32 is wrong,
+ // but everywhere this generic conversion would be wrong is currently overloaded.
+ { false, false, QPixelLayout::BPP32, rbSwap_rgb32, convertPassThrough,
+ convertRGB32ToRGB64, fetchPassThrough, fetchRGB32ToRGB64, storePassThrough, storePassThrough }, // Format_RGB32
+ { true, false, QPixelLayout::BPP32, rbSwap_rgb32, convertARGB32ToARGB32PM,
+ convertARGB32ToRGBA64PM, fetchARGB32ToARGB32PM, fetchARGB32ToRGBA64PM, storeARGB32FromARGB32PM, storePassThrough }, // Format_ARGB32
+ { true, true, QPixelLayout::BPP32, rbSwap_rgb32, convertPassThrough,
+ convertARGB32PMToRGBA64PM, fetchPassThrough, fetchARGB32PMToRGBA64PM, storePassThrough, storePassThrough }, // Format_ARGB32_Premultiplied
+ pixelLayoutRGB<QImage::Format_RGB16>(),
+ pixelLayoutARGBPM<QImage::Format_ARGB8565_Premultiplied>(),
+ pixelLayoutRGB<QImage::Format_RGB666>(),
+ pixelLayoutARGBPM<QImage::Format_ARGB6666_Premultiplied>(),
+ pixelLayoutRGB<QImage::Format_RGB555>(),
+ pixelLayoutARGBPM<QImage::Format_ARGB8555_Premultiplied>(),
+ pixelLayoutRGB<QImage::Format_RGB888>(),
+ pixelLayoutRGB<QImage::Format_RGB444>(),
+ pixelLayoutARGBPM<QImage::Format_ARGB4444_Premultiplied>(),
+ { false, false, QPixelLayout::BPP32, rbSwap<QImage::Format_RGBA8888>, convertRGBA8888PMToARGB32PM,
+ convertRGBA8888PMToRGBA64PM, fetchRGBA8888PMToARGB32PM, fetchRGBA8888PMToRGBA64PM, storeRGBXFromARGB32PM, storeRGBXFromRGB32 }, // Format_RGBX8888
+ { true, false, QPixelLayout::BPP32, rbSwap<QImage::Format_RGBA8888>, convertRGBA8888ToARGB32PM,
+ convertRGBA8888ToRGBA64PM, fetchRGBA8888ToARGB32PM, fetchRGBA8888ToRGBA64PM, storeRGBA8888FromARGB32PM, storeRGBXFromRGB32 }, // Format_RGBA8888
+ { true, true, QPixelLayout::BPP32, rbSwap<QImage::Format_RGBA8888>, convertRGBA8888PMToARGB32PM,
+ convertRGBA8888PMToRGBA64PM, fetchRGBA8888PMToARGB32PM, fetchRGBA8888PMToRGBA64PM, storeRGBA8888PMFromARGB32PM, storeRGBXFromRGB32 }, // Format_RGBA8888_Premultiplied
+ { false, false, QPixelLayout::BPP32, rbSwap_rgb30,
+ convertA2RGB30PMToARGB32PM<PixelOrderBGR>,
+ convertA2RGB30PMToRGBA64PM<PixelOrderBGR>,
+ fetchA2RGB30PMToARGB32PM<PixelOrderBGR>,
+ fetchA2RGB30PMToRGBA64PM<PixelOrderBGR>,
+ storeRGB30FromARGB32PM<PixelOrderBGR>,
+ storeRGB30FromRGB32<PixelOrderBGR>
+ }, // Format_BGR30
+ { true, true, QPixelLayout::BPP32, rbSwap_rgb30,
+ convertA2RGB30PMToARGB32PM<PixelOrderBGR>,
+ convertA2RGB30PMToRGBA64PM<PixelOrderBGR>,
+ fetchA2RGB30PMToARGB32PM<PixelOrderBGR>,
+ fetchA2RGB30PMToRGBA64PM<PixelOrderBGR>,
+ storeA2RGB30PMFromARGB32PM<PixelOrderBGR>,
+ storeRGB30FromRGB32<PixelOrderBGR>
+ }, // Format_A2BGR30_Premultiplied
+ { false, false, QPixelLayout::BPP32, rbSwap_rgb30,
+ convertA2RGB30PMToARGB32PM<PixelOrderRGB>,
+ convertA2RGB30PMToRGBA64PM<PixelOrderRGB>,
+ fetchA2RGB30PMToARGB32PM<PixelOrderRGB>,
+ fetchA2RGB30PMToRGBA64PM<PixelOrderRGB>,
+ storeRGB30FromARGB32PM<PixelOrderRGB>,
+ storeRGB30FromRGB32<PixelOrderRGB>
+ }, // Format_RGB30
+ { true, true, QPixelLayout::BPP32, rbSwap_rgb30,
+ convertA2RGB30PMToARGB32PM<PixelOrderRGB>,
+ convertA2RGB30PMToRGBA64PM<PixelOrderRGB>,
+ fetchA2RGB30PMToARGB32PM<PixelOrderRGB>,
+ fetchA2RGB30PMToRGBA64PM<PixelOrderRGB>,
+ storeA2RGB30PMFromARGB32PM<PixelOrderRGB>,
+ storeRGB30FromRGB32<PixelOrderRGB>
+ }, // Format_A2RGB30_Premultiplied
+ { true, true, QPixelLayout::BPP8, nullptr,
+ convertAlpha8ToRGB32, convertAlpha8ToRGB64,
+ fetchAlpha8ToRGB32, fetchAlpha8ToRGB64,
+ storeAlpha8FromARGB32PM, nullptr }, // Format_Alpha8
+ { false, false, QPixelLayout::BPP8, nullptr,
+ convertGrayscale8ToRGB32, convertGrayscale8ToRGB64,
+ fetchGrayscale8ToRGB32, fetchGrayscale8ToRGB64,
+ storeGrayscale8FromARGB32PM, storeGrayscale8FromRGB32 }, // Format_Grayscale8
+ { false, false, QPixelLayout::BPP64, nullptr,
+ convertPassThrough, nullptr,
+ fetchRGB64ToRGB32, fetchPassThrough64,
+ storeRGB64FromRGB32, storeRGB64FromRGB32 }, // Format_RGBX64
+ { true, false, QPixelLayout::BPP64, nullptr,
+ convertARGB32ToARGB32PM, nullptr,
+ fetchRGBA64ToARGB32PM, fetchRGBA64ToRGBA64PM,
+ storeRGBA64FromARGB32PM, storeRGB64FromRGB32 }, // Format_RGBA64
+ { true, true, QPixelLayout::BPP64, nullptr,
+ convertPassThrough, nullptr,
+ fetchRGB64ToRGB32, fetchPassThrough64,
+ storeRGB64FromRGB32, storeRGB64FromRGB32 } // Format_RGBA64_Premultiplied
+};
-template <QPixelLayout::BPP bpp>
-inline const uint *QT_FASTCALL fetchPixels(uint *buffer, const uchar *src, int index, int count)
-{
- for (int i = 0; i < count; ++i)
- buffer[i] = fetchPixel<bpp>(src, index + i);
- return buffer;
-}
+Q_STATIC_ASSERT(sizeof(qPixelLayouts) / sizeof(*qPixelLayouts) == QImage::NImageFormats);
-template <>
-inline const uint *QT_FASTCALL fetchPixels<QPixelLayout::BPP32>(uint *, const uchar *src, int index, int)
+static void QT_FASTCALL convertFromRgb64(uint *dest, const QRgba64 *src, int length)
{
- return reinterpret_cast<const uint *>(src) + index;
+ for (int i = 0; i < length; ++i) {
+ dest[i] = toArgb32(src[i]);
+ }
}
-template <QPixelLayout::BPP width> static
-void QT_FASTCALL storePixel(uchar *dest, int index, uint pixel);
-
-template <>
-inline void QT_FASTCALL storePixel<QPixelLayout::BPP1LSB>(uchar *dest, int index, uint pixel)
+template<QImage::Format format>
+static void QT_FASTCALL storeGenericFromRGBA64PM(uchar *dest, const QRgba64 *src, int index, int count,
+ const QVector<QRgb> *clut, QDitherInfo *dither)
{
- if (pixel)
- dest[index >> 3] |= 1 << (index & 7);
- else
- dest[index >> 3] &= ~(1 << (index & 7));
+ uint buffer[BufferSize];
+ convertFromRgb64(buffer, src, count);
+ qPixelLayouts[format].storeFromARGB32PM(dest, buffer, index, count, clut, dither);
}
-template <>
-inline void QT_FASTCALL storePixel<QPixelLayout::BPP1MSB>(uchar *dest, int index, uint pixel)
+static void QT_FASTCALL storeARGB32FromRGBA64PM(uchar *dest, const QRgba64 *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
- if (pixel)
- dest[index >> 3] |= 1 << (~index & 7);
- else
- dest[index >> 3] &= ~(1 << (~index & 7));
+ uint *d = (uint*)dest + index;
+ for (int i = 0; i < count; ++i)
+ d[i] = toArgb32(src[i].unpremultiplied());
}
-template <>
-inline void QT_FASTCALL storePixel<QPixelLayout::BPP8>(uchar *dest, int index, uint pixel)
+static void QT_FASTCALL storeRGBA8888FromRGBA64PM(uchar *dest, const QRgba64 *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
- dest[index] = uchar(pixel);
+ uint *d = (uint*)dest + index;
+ for (int i = 0; i < count; ++i)
+ d[i] = toRgba8888(src[i].unpremultiplied());
}
-template <>
-inline void QT_FASTCALL storePixel<QPixelLayout::BPP16>(uchar *dest, int index, uint pixel)
+template<QtPixelOrder PixelOrder>
+static void QT_FASTCALL storeRGB30FromRGBA64PM(uchar *dest, const QRgba64 *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
- reinterpret_cast<quint16 *>(dest)[index] = quint16(pixel);
+ uint *d = (uint*)dest + index;
+#ifdef __SSE2__
+ qConvertRGBA64PMToA2RGB30PM_sse2<PixelOrder>(d, src, count);
+#else
+ for (int i = 0; i < count; ++i)
+ d[i] = qConvertRgb64ToRgb30<PixelOrder>(src[i]);
+#endif
}
-template <>
-inline void QT_FASTCALL storePixel<QPixelLayout::BPP24>(uchar *dest, int index, uint pixel)
+static void QT_FASTCALL storeRGBX64FromRGBA64PM(uchar *dest, const QRgba64 *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
- reinterpret_cast<quint24 *>(dest)[index] = quint24(pixel);
+ QRgba64 *d = reinterpret_cast<QRgba64*>(dest) + index;
+ for (int i = 0; i < count; ++i) {
+ d[i] = src[i].unpremultiplied();
+ d[i].setAlpha(65535);
+ }
}
-template <QPixelLayout::BPP width>
-inline void QT_FASTCALL storePixels(uchar *dest, const uint *src, int index, int count)
+static void QT_FASTCALL storeRGBA64FromRGBA64PM(uchar *dest, const QRgba64 *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
+ QRgba64 *d = reinterpret_cast<QRgba64*>(dest) + index;
for (int i = 0; i < count; ++i)
- storePixel<width>(dest, index + i, src[i]);
+ d[i] = src[i].unpremultiplied();
}
-template <>
-inline void QT_FASTCALL storePixels<QPixelLayout::BPP32>(uchar *dest, const uint *src, int index, int count)
+static void QT_FASTCALL storeRGBA64PMFromRGBA64PM(uchar *dest, const QRgba64 *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
- memcpy(reinterpret_cast<uint *>(dest) + index, src, count * sizeof(uint));
-}
-
-// Note:
-// convertToArgb32() assumes that no color channel is less than 4 bits.
-// convertFromArgb32() assumes that no color channel is more than 8 bits.
-// QImage::rgbSwapped() assumes that the red and blue color channels have the same number of bits.
-QPixelLayout qPixelLayouts[QImage::NImageFormats] = {
- { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPPNone, 0, 0, 0, 0 }, // Format_Invalid
- { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP1MSB, convertIndexedToARGB32PM, 0, 0, convertIndexedToARGB64PM }, // Format_Mono
- { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP1LSB, convertIndexedToARGB32PM, 0, 0, convertIndexedToARGB64PM }, // Format_MonoLSB
- { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP8, convertIndexedToARGB32PM, 0, 0, convertIndexedToARGB64PM }, // Format_Indexed8
- // Technically using convertPassThrough to convert from ARGB32PM to RGB32 is wrong,
- // but everywhere this generic conversion would be wrong is currently overloaded.
- { 8, 16, 8, 8, 8, 0, 0, 0, false, QPixelLayout::BPP32, convertPassThrough, convertPassThrough, convertPassThrough, convertRGB32ToRGB64 }, // Format_RGB32
- { 8, 16, 8, 8, 8, 0, 8, 24, false, QPixelLayout::BPP32, convertARGB32ToARGB32PM, convertARGB32FromARGB32PM, convertPassThrough, convertARGB32ToARGB64PM }, // Format_ARGB32
- { 8, 16, 8, 8, 8, 0, 8, 24, true, QPixelLayout::BPP32, convertPassThrough, convertPassThrough, convertPassThrough, convertARGB32PMToARGB64PM }, // Format_ARGB32_Premultiplied
-#ifdef Q_COMPILER_CONSTEXPR
- pixelLayoutRGB<QImage::Format_RGB16>(),
- pixelLayoutARGBPM<QImage::Format_ARGB8565_Premultiplied>(),
- pixelLayoutRGB<QImage::Format_RGB666>(),
- pixelLayoutARGBPM<QImage::Format_ARGB6666_Premultiplied>(),
- pixelLayoutRGB<QImage::Format_RGB555>(),
- pixelLayoutARGBPM<QImage::Format_ARGB8555_Premultiplied>(),
- pixelLayoutRGB<QImage::Format_RGB888>(),
- pixelLayoutRGB<QImage::Format_RGB444>(),
- pixelLayoutARGBPM<QImage::Format_ARGB4444_Premultiplied>(),
-#else
- { 5, 11, 6, 5, 5, 0, 0, 0, false, QPixelLayout::BPP16,
- convertToRGB32<QImage::Format_RGB16>,
- convertRGBFromARGB32PM<QImage::Format_RGB16, false>,
- convertRGBFromARGB32PM<QImage::Format_RGB16, true>,
- convertToRGB64<QImage::Format_RGB16>,
- },
- { 5, 19, 6, 13, 5, 8, 8, 0, true, QPixelLayout::BPP24,
- convertARGBPMToARGB32PM<QImage::Format_ARGB8565_Premultiplied>,
- convertARGBPMFromARGB32PM<QImage::Format_ARGB8565_Premultiplied, false>,
- convertARGBPMFromARGB32PM<QImage::Format_ARGB8565_Premultiplied, true>,
- convertARGBPMToARGB64PM<QImage::Format_ARGB8565_Premultiplied>,
- },
- { 6, 12, 6, 6, 6, 0, 0, 0, false, QPixelLayout::BPP24,
- convertToRGB32<QImage::Format_RGB666>,
- convertRGBFromARGB32PM<QImage::Format_RGB666, false>,
- convertRGBFromARGB32PM<QImage::Format_RGB666, true>,
- convertToRGB64<QImage::Format_RGB666>,
- },
- { 6, 12, 6, 6, 6, 0, 6, 18, true, QPixelLayout::BPP24,
- convertARGBPMToARGB32PM<QImage::Format_ARGB6666_Premultiplied>,
- convertARGBPMFromARGB32PM<QImage::Format_ARGB6666_Premultiplied, false>,
- convertARGBPMFromARGB32PM<QImage::Format_ARGB6666_Premultiplied, true>,
- convertARGBPMToARGB64PM<QImage::Format_ARGB6666_Premultiplied>,
- },
- { 5, 10, 5, 5, 5, 0, 0, 0, false, QPixelLayout::BPP16,
- convertToRGB32<QImage::Format_RGB555>,
- convertRGBFromARGB32PM<QImage::Format_RGB555, false>,
- convertRGBFromARGB32PM<QImage::Format_RGB555, true>,
- convertToRGB64<QImage::Format_RGB555>,
- },
- { 5, 18, 5, 13, 5, 8, 8, 0, true, QPixelLayout::BPP24,
- convertARGBPMToARGB32PM<QImage::Format_ARGB8555_Premultiplied>,
- convertARGBPMFromARGB32PM<QImage::Format_ARGB8555_Premultiplied, false>,
- convertARGBPMFromARGB32PM<QImage::Format_ARGB8555_Premultiplied, true>,
- convertARGBPMToARGB64PM<QImage::Format_ARGB8555_Premultiplied>,
- },
- { 8, 16, 8, 8, 8, 0, 0, 0, false, QPixelLayout::BPP24,
- convertToRGB32<QImage::Format_RGB888>,
- convertRGBFromARGB32PM<QImage::Format_RGB888, false>,
- convertRGBFromARGB32PM<QImage::Format_RGB888, true>,
- convertToRGB64<QImage::Format_RGB888>,
- },
- { 4, 8, 4, 4, 4, 0, 0, 0, false, QPixelLayout::BPP16,
- convertToRGB32<QImage::Format_RGB444>,
- convertRGBFromARGB32PM<QImage::Format_RGB444, false>,
- convertRGBFromARGB32PM<QImage::Format_RGB444, true>,
- convertToRGB64<QImage::Format_RGB444>,
- },
- { 4, 8, 4, 4, 4, 0, 4, 12, true, QPixelLayout::BPP16,
- convertARGBPMToARGB32PM<QImage::Format_ARGB4444_Premultiplied>,
- convertARGBPMFromARGB32PM<QImage::Format_ARGB4444_Premultiplied, false>,
- convertARGBPMFromARGB32PM<QImage::Format_ARGB4444_Premultiplied, true>,
- convertARGBPMToARGB64PM<QImage::Format_ARGB4444_Premultiplied>,
- },
-#endif
-#if Q_BYTE_ORDER == Q_BIG_ENDIAN
- { 8, 24, 8, 16, 8, 8, 0, 0, false, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBXFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToARGB64PM }, // Format_RGBX8888
- { 8, 24, 8, 16, 8, 8, 8, 0, false, QPixelLayout::BPP32, convertRGBA8888ToARGB32PM, convertRGBA8888FromARGB32PM, convertRGBXFromRGB32, convertRGBA8888ToARGB64PM }, // Format_RGBA8888
- { 8, 24, 8, 16, 8, 8, 8, 0, true, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBA8888PMFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToARGB64PM}, // Format_RGBA8888_Premultiplied
-#else
- { 8, 0, 8, 8, 8, 16, 0, 24, false, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBXFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToARGB64PM }, // Format_RGBX8888
- { 8, 0, 8, 8, 8, 16, 8, 24, false, QPixelLayout::BPP32, convertRGBA8888ToARGB32PM, convertRGBA8888FromARGB32PM, convertRGBXFromRGB32, convertRGBA8888ToARGB64PM }, // Format_RGBA8888 (ABGR32)
- { 8, 0, 8, 8, 8, 16, 8, 24, true, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBA8888PMFromARGB32PM, convertRGBXFromRGB32, convertRGBA8888PMToARGB64PM }, // Format_RGBA8888_Premultiplied
-#endif
- { 10, 20, 10, 10, 10, 0, 0, 30, false, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderBGR>, convertRGB30FromARGB32PM<PixelOrderBGR>, convertRGB30FromRGB32<PixelOrderBGR>, convertA2RGB30PMToARGB64PM<PixelOrderBGR> }, // Format_BGR30
- { 10, 20, 10, 10, 10, 0, 2, 30, true, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderBGR>, convertA2RGB30PMFromARGB32PM<PixelOrderBGR>, convertRGB30FromRGB32<PixelOrderBGR>, convertA2RGB30PMToARGB64PM<PixelOrderBGR> }, // Format_A2BGR30_Premultiplied
- { 10, 0, 10, 10, 10, 20, 0, 30, false, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderRGB>, convertRGB30FromARGB32PM<PixelOrderRGB>, convertRGB30FromRGB32<PixelOrderRGB>, convertA2RGB30PMToARGB64PM<PixelOrderRGB> }, // Format_RGB30
- { 10, 0, 10, 10, 10, 20, 2, 30, true, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderRGB>, convertA2RGB30PMFromARGB32PM<PixelOrderRGB>, convertRGB30FromRGB32<PixelOrderRGB>, convertA2RGB30PMToARGB64PM<PixelOrderRGB> }, // Format_A2RGB30_Premultiplied
- { 0, 0, 0, 0, 0, 0, 8, 0, true, QPixelLayout::BPP8, convertAlpha8ToRGB32, convertAlpha8FromARGB32PM, 0, convertAlpha8ToRGB64 }, // Format_Alpha8
- { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP8, convertGrayscale8ToRGB32, convertGrayscale8FromARGB32PM, convertGrayscale8FromRGB32, convertGrayscale8ToRGB64 } // Format_Grayscale8
-};
-
-const FetchPixelsFunc qFetchPixels[QPixelLayout::BPPCount] = {
- 0, // BPPNone
- fetchPixels<QPixelLayout::BPP1MSB>, // BPP1MSB
- fetchPixels<QPixelLayout::BPP1LSB>, // BPP1LSB
- fetchPixels<QPixelLayout::BPP8>, // BPP8
- fetchPixels<QPixelLayout::BPP16>, // BPP16
- fetchPixels<QPixelLayout::BPP24>, // BPP24
- fetchPixels<QPixelLayout::BPP32> // BPP32
-};
-
-StorePixelsFunc qStorePixels[QPixelLayout::BPPCount] = {
- 0, // BPPNone
- storePixels<QPixelLayout::BPP1MSB>, // BPP1MSB
- storePixels<QPixelLayout::BPP1LSB>, // BPP1LSB
- storePixels<QPixelLayout::BPP8>, // BPP8
- storePixels<QPixelLayout::BPP16>, // BPP16
- storePixels<QPixelLayout::BPP24>, // BPP24
- storePixels<QPixelLayout::BPP32> // BPP32
-};
-
-typedef uint (QT_FASTCALL *FetchPixelFunc)(const uchar *src, int index);
-
-static const FetchPixelFunc qFetchPixel[QPixelLayout::BPPCount] = {
- 0, // BPPNone
- fetchPixel<QPixelLayout::BPP1MSB>, // BPP1MSB
- fetchPixel<QPixelLayout::BPP1LSB>, // BPP1LSB
- fetchPixel<QPixelLayout::BPP8>, // BPP8
- fetchPixel<QPixelLayout::BPP16>, // BPP16
- fetchPixel<QPixelLayout::BPP24>, // BPP24
- fetchPixel<QPixelLayout::BPP32> // BPP32
+ QRgba64 *d = reinterpret_cast<QRgba64*>(dest) + index;
+ if (d != src)
+ memcpy(d, src, count * sizeof(QRgba64));
+}
+
+ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats] = {
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ storeGenericFromRGBA64PM<QImage::Format_RGB32>,
+ storeARGB32FromRGBA64PM,
+ storeGenericFromRGBA64PM<QImage::Format_ARGB32_Premultiplied>,
+ storeGenericFromRGBA64PM<QImage::Format_RGB16>,
+ storeGenericFromRGBA64PM<QImage::Format_ARGB8565_Premultiplied>,
+ storeGenericFromRGBA64PM<QImage::Format_RGB666>,
+ storeGenericFromRGBA64PM<QImage::Format_ARGB6666_Premultiplied>,
+ storeGenericFromRGBA64PM<QImage::Format_RGB555>,
+ storeGenericFromRGBA64PM<QImage::Format_ARGB8555_Premultiplied>,
+ storeGenericFromRGBA64PM<QImage::Format_RGB888>,
+ storeGenericFromRGBA64PM<QImage::Format_RGB444>,
+ storeGenericFromRGBA64PM<QImage::Format_ARGB4444_Premultiplied>,
+ storeGenericFromRGBA64PM<QImage::Format_RGBX8888>,
+ storeRGBA8888FromRGBA64PM,
+ storeGenericFromRGBA64PM<QImage::Format_RGBA8888_Premultiplied>,
+ storeRGB30FromRGBA64PM<PixelOrderBGR>,
+ storeRGB30FromRGBA64PM<PixelOrderBGR>,
+ storeRGB30FromRGBA64PM<PixelOrderRGB>,
+ storeRGB30FromRGBA64PM<PixelOrderRGB>,
+ storeGenericFromRGBA64PM<QImage::Format_Alpha8>,
+ storeGenericFromRGBA64PM<QImage::Format_Grayscale8>,
+ storeRGBX64FromRGBA64PM,
+ storeRGBA64FromRGBA64PM,
+ storeRGBA64PMFromRGBA64PM
};
/*
@@ -1185,23 +1641,23 @@ static uint * QT_FASTCALL destFetchRGB16(uint *buffer, QRasterBuffer *rasterBuff
static uint *QT_FASTCALL destFetch(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length)
{
const QPixelLayout *layout = &qPixelLayouts[rasterBuffer->format];
- const uint *ptr = qFetchPixels[layout->bpp](buffer, rasterBuffer->scanLine(y), x, length);
- return const_cast<uint *>(layout->convertToARGB32PM(buffer, ptr, length, 0, 0));
+ return const_cast<uint *>(layout->fetchToARGB32PM(buffer, rasterBuffer->scanLine(y), x, length, nullptr, nullptr));
+}
+
+static uint *QT_FASTCALL destFetchUndefined(uint *buffer, QRasterBuffer *, int, int, int)
+{
+ return buffer;
}
static QRgba64 *QT_FASTCALL destFetch64(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length)
{
const QPixelLayout *layout = &qPixelLayouts[rasterBuffer->format];
- uint buffer32[buffer_size];
- const uint *ptr = qFetchPixels[layout->bpp](buffer32, rasterBuffer->scanLine(y), x, length);
- return const_cast<QRgba64 *>(layout->convertToARGB64PM(buffer, ptr, length, 0, 0));
+ return const_cast<QRgba64 *>(layout->fetchToRGBA64PM(buffer, rasterBuffer->scanLine(y), x, length, nullptr, nullptr));
}
-static QRgba64 *QT_FASTCALL destFetch64uint32(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length)
+static QRgba64 * QT_FASTCALL destFetchRGB64(QRgba64 *, QRasterBuffer *rasterBuffer, int x, int y, int)
{
- const QPixelLayout *layout = &qPixelLayouts[rasterBuffer->format];
- const uint *src = ((const uint *)rasterBuffer->scanLine(y)) + x;
- return const_cast<QRgba64 *>(layout->convertToARGB64PM(buffer, src, length, 0, 0));
+ return (QRgba64 *)rasterBuffer->scanLine(y) + x;
}
static QRgba64 * QT_FASTCALL destFetch64Undefined(QRgba64 *buffer, QRasterBuffer *, int, int, int)
@@ -1236,6 +1692,9 @@ static DestFetchProc destFetchProc[QImage::NImageFormats] =
destFetch, // Format_A2RGB30_Premultiplied
destFetch, // Format_Alpha8
destFetch, // Format_Grayscale8
+ destFetch, // Format_RGBX64
+ destFetch, // Format_RGBA64
+ destFetch, // Format_RGBA64_Premultiplied
};
static DestFetchProc64 destFetchProc64[QImage::NImageFormats] =
@@ -1244,9 +1703,9 @@ static DestFetchProc64 destFetchProc64[QImage::NImageFormats] =
0, // Format_Mono,
0, // Format_MonoLSB
0, // Format_Indexed8
- destFetch64uint32, // Format_RGB32
- destFetch64uint32, // Format_ARGB32,
- destFetch64uint32, // Format_ARGB32_Premultiplied
+ destFetch64, // Format_RGB32
+ destFetch64, // Format_ARGB32,
+ destFetch64, // Format_ARGB32_Premultiplied
destFetch64, // Format_RGB16
destFetch64, // Format_ARGB8565_Premultiplied
destFetch64, // Format_RGB666
@@ -1256,15 +1715,18 @@ static DestFetchProc64 destFetchProc64[QImage::NImageFormats] =
destFetch64, // Format_RGB888
destFetch64, // Format_RGB444
destFetch64, // Format_ARGB4444_Premultiplied
- destFetch64uint32, // Format_RGBX8888
- destFetch64uint32, // Format_RGBA8888
- destFetch64uint32, // Format_RGBA8888_Premultiplied
- destFetch64uint32, // Format_BGR30
- destFetch64uint32, // Format_A2BGR30_Premultiplied
- destFetch64uint32, // Format_RGB30
- destFetch64uint32, // Format_A2RGB30_Premultiplied
+ destFetch64, // Format_RGBX8888
+ destFetch64, // Format_RGBA8888
+ destFetch64, // Format_RGBA8888_Premultiplied
+ destFetch64, // Format_BGR30
+ destFetch64, // Format_A2BGR30_Premultiplied
+ destFetch64, // Format_RGB30
+ destFetch64, // Format_A2RGB30_Premultiplied
destFetch64, // Format_Alpha8
destFetch64, // Format_Grayscale8
+ destFetchRGB64, // Format_RGBX64
+ destFetch64, // Format_RGBA64
+ destFetchRGB64, // Format_RGBA64_Premultiplied
};
/*
@@ -1365,143 +1827,29 @@ static void QT_FASTCALL destStoreRGB16(QRasterBuffer *rasterBuffer, int x, int y
static void QT_FASTCALL destStore(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length)
{
- uint buf[buffer_size];
const QPixelLayout *layout = &qPixelLayouts[rasterBuffer->format];
- StorePixelsFunc store = qStorePixels[layout->bpp];
+ ConvertAndStorePixelsFunc store = layout->storeFromARGB32PM;
+ if (!layout->premultiplied && !layout->hasAlphaChannel)
+ store = layout->storeFromRGB32;
uchar *dest = rasterBuffer->scanLine(y);
- while (length) {
- int l = qMin(length, buffer_size);
- const uint *ptr = 0;
- if (!layout->premultiplied && !layout->alphaWidth)
- ptr = layout->convertFromRGB32(buf, buffer, l, 0, 0);
- else
- ptr = layout->convertFromARGB32PM(buf, buffer, l, 0, 0);
- store(dest, ptr, x, l);
- length -= l;
- buffer += l;
- x += l;
- }
-}
-
-static void QT_FASTCALL convertFromRgb64(uint *dest, const QRgba64 *src, int length)
-{
- for (int i = 0; i < length; ++i) {
- dest[i] = toArgb32(src[i]);
- }
+ store(dest, buffer, x, length, nullptr, nullptr);
}
static void QT_FASTCALL destStore64(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
{
- uint buf[buffer_size];
- const QPixelLayout *layout = &qPixelLayouts[rasterBuffer->format];
- StorePixelsFunc store = qStorePixels[layout->bpp];
+ auto store = qStoreFromRGBA64PM[rasterBuffer->format];
uchar *dest = rasterBuffer->scanLine(y);
- while (length) {
- int l = qMin(length, buffer_size);
- const uint *ptr = 0;
- convertFromRgb64(buf, buffer, l);
- if (!layout->premultiplied && !layout->alphaWidth)
- ptr = layout->convertFromRGB32(buf, buf, l, 0, 0);
- else
- ptr = layout->convertFromARGB32PM(buf, buf, l, 0, 0);
- store(dest, ptr, x, l);
- length -= l;
- buffer += l;
- x += l;
- }
+ store(dest, buffer, x, length, nullptr, nullptr);
}
-#ifdef __SSE2__
-template<QtPixelOrder PixelOrder>
-static inline void qConvertARGB64PMToA2RGB30PM_sse2(uint *dest, const QRgba64 *buffer, int count)
+static void QT_FASTCALL destStore64RGBA64(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
{
- const __m128i gmask = _mm_set1_epi32(0x000ffc00);
- const __m128i cmask = _mm_set1_epi32(0x000003ff);
- int i = 0;
- __m128i vr, vg, vb, va;
- for (; i < count && uintptr_t(buffer) & 0xF; ++i) {
- *dest++ = qConvertRgb64ToRgb30<PixelOrder>(*buffer++);
- }
-
- for (; i < count-15; i += 16) {
- // Repremultiplying is really expensive and hard to do in SIMD without AVX2,
- // so we try to avoid it by checking if it is needed 16 samples at a time.
- __m128i vOr = _mm_set1_epi32(0);
- __m128i vAnd = _mm_set1_epi32(0xffffffff);
- for (int j = 0; j < 16; j += 2) {
- __m128i vs = _mm_load_si128((const __m128i*)(buffer + j));
- vOr = _mm_or_si128(vOr, vs);
- vAnd = _mm_and_si128(vAnd, vs);
- }
- const quint16 orAlpha = ((uint)_mm_extract_epi16(vOr, 3)) | ((uint)_mm_extract_epi16(vOr, 7));
- const quint16 andAlpha = ((uint)_mm_extract_epi16(vAnd, 3)) & ((uint)_mm_extract_epi16(vAnd, 7));
-
- if (andAlpha == 0xffff) {
- for (int j = 0; j < 16; j += 2) {
- __m128i vs = _mm_load_si128((const __m128i*)buffer);
- buffer += 2;
- vr = _mm_srli_epi64(vs, 6);
- vg = _mm_srli_epi64(vs, 16 + 6 - 10);
- vb = _mm_srli_epi64(vs, 32 + 6);
- vr = _mm_and_si128(vr, cmask);
- vg = _mm_and_si128(vg, gmask);
- vb = _mm_and_si128(vb, cmask);
- va = _mm_srli_epi64(vs, 48 + 14);
- if (PixelOrder == PixelOrderRGB)
- vr = _mm_slli_epi32(vr, 20);
- else
- vb = _mm_slli_epi32(vb, 20);
- va = _mm_slli_epi32(va, 30);
- __m128i vd = _mm_or_si128(_mm_or_si128(vr, vg), _mm_or_si128(vb, va));
- vd = _mm_shuffle_epi32(vd, _MM_SHUFFLE(3, 1, 2, 0));
- _mm_storel_epi64((__m128i*)dest, vd);
- dest += 2;
- }
- } else if (orAlpha == 0) {
- for (int j = 0; j < 16; ++j) {
- *dest++ = 0;
- buffer++;
- }
- } else {
- for (int j = 0; j < 16; ++j)
- *dest++ = qConvertRgb64ToRgb30<PixelOrder>(*buffer++);
- }
- }
-
- SIMD_EPILOGUE(i, count, 15)
- *dest++ = qConvertRgb64ToRgb30<PixelOrder>(*buffer++);
-}
-#endif
-
-static void QT_FASTCALL destStore64ARGB32(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
-{
- uint *dest = (uint*)rasterBuffer->scanLine(y) + x;
+ QRgba64 *dest = reinterpret_cast<QRgba64*>(rasterBuffer->scanLine(y)) + x;
for (int i = 0; i < length; ++i) {
- dest[i] = toArgb32(buffer[i].unpremultiplied());
+ dest[i] = buffer[i].unpremultiplied();
}
}
-static void QT_FASTCALL destStore64RGBA8888(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
-{
- uint *dest = (uint*)rasterBuffer->scanLine(y) + x;
- for (int i = 0; i < length; ++i) {
- dest[i] = toRgba8888(buffer[i].unpremultiplied());
- }
-}
-
-template<QtPixelOrder PixelOrder>
-static void QT_FASTCALL destStore64RGB30(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
-{
- uint *dest = (uint*)rasterBuffer->scanLine(y) + x;
-#ifdef __SSE2__
- qConvertARGB64PMToA2RGB30PM_sse2<PixelOrder>(dest, buffer, length);
-#else
- for (int i = 0; i < length; ++i) {
- dest[i] = qConvertRgb64ToRgb30<PixelOrder>(buffer[i]);
- }
-#endif
-}
-
static DestStoreProc destStoreProc[QImage::NImageFormats] =
{
0, // Format_Invalid
@@ -1529,16 +1877,19 @@ static DestStoreProc destStoreProc[QImage::NImageFormats] =
destStore, // Format_A2RGB30_Premultiplied
destStore, // Format_Alpha8
destStore, // Format_Grayscale8
+ destStore, // Format_RGBX64
+ destStore, // Format_RGBA64
+ destStore, // Format_RGBA64_Premultiplied
};
static DestStoreProc64 destStoreProc64[QImage::NImageFormats] =
{
0, // Format_Invalid
- destStore64, // Format_Mono,
- destStore64, // Format_MonoLSB
+ 0, // Format_Mono,
+ 0, // Format_MonoLSB
0, // Format_Indexed8
destStore64, // Format_RGB32
- destStore64ARGB32, // Format_ARGB32,
+ destStore64, // Format_ARGB32,
destStore64, // Format_ARGB32_Premultiplied
destStore64, // Format_RGB16
destStore64, // Format_ARGB8565_Premultiplied
@@ -1550,14 +1901,17 @@ static DestStoreProc64 destStoreProc64[QImage::NImageFormats] =
destStore64, // Format_RGB444
destStore64, // Format_ARGB4444_Premultiplied
destStore64, // Format_RGBX8888
- destStore64RGBA8888, // Format_RGBA8888
+ destStore64, // Format_RGBA8888
destStore64, // Format_RGBA8888_Premultiplied
- destStore64RGB30<PixelOrderBGR>, // Format_BGR30
- destStore64RGB30<PixelOrderBGR>, // Format_A2BGR30_Premultiplied
- destStore64RGB30<PixelOrderRGB>, // Format_RGB30
- destStore64RGB30<PixelOrderRGB>, // Format_A2RGB30_Premultiplied
+ destStore64, // Format_BGR30
+ destStore64, // Format_A2BGR30_Premultiplied
+ destStore64, // Format_RGB30
+ destStore64, // Format_A2RGB30_Premultiplied
destStore64, // Format_Alpha8
destStore64, // Format_Grayscale8
+ 0, // Format_RGBX64
+ destStore64RGBA64, // Format_RGBA64
+ 0 // Format_RGBA64_Premultiplied
};
/*
@@ -1589,15 +1943,14 @@ static const uint *QT_FASTCALL fetchUntransformed(uint *buffer, const Operator *
const QSpanData *data, int y, int x, int length)
{
const QPixelLayout *layout = &qPixelLayouts[data->texture.format];
- const uint *ptr = qFetchPixels[layout->bpp](buffer, data->texture.scanLine(y), x, length);
- return layout->convertToARGB32PM(buffer, ptr, length, data->texture.colorTable, 0);
+ return layout->fetchToARGB32PM(buffer, data->texture.scanLine(y), x, length, data->texture.colorTable, nullptr);
}
static const uint *QT_FASTCALL fetchUntransformedARGB32PM(uint *, const Operator *,
const QSpanData *data, int y, int x, int)
{
const uchar *scanLine = data->texture.scanLine(y);
- return ((const uint *)scanLine) + x;
+ return reinterpret_cast<const uint *>(scanLine) + x;
}
static const uint *QT_FASTCALL fetchUntransformedRGB16(uint *buffer, const Operator *,
@@ -1614,39 +1967,47 @@ static const QRgba64 *QT_FASTCALL fetchUntransformed64(QRgba64 *buffer, const Op
const QSpanData *data, int y, int x, int length)
{
const QPixelLayout *layout = &qPixelLayouts[data->texture.format];
- if (layout->bpp != QPixelLayout::BPP32) {
- uint buffer32[buffer_size];
- const uint *ptr = qFetchPixels[layout->bpp](buffer32, data->texture.scanLine(y), x, length);
- return layout->convertToARGB64PM(buffer, ptr, length, data->texture.colorTable, 0);
+ return layout->fetchToRGBA64PM(buffer, data->texture.scanLine(y), x, length, data->texture.colorTable, nullptr);
+}
+
+static const QRgba64 *QT_FASTCALL fetchUntransformedRGBA64PM(QRgba64 *, const Operator *,
+ const QSpanData *data, int y, int x, int)
+{
+ const uchar *scanLine = data->texture.scanLine(y);
+ return reinterpret_cast<const QRgba64 *>(scanLine) + x;
+}
+
+template<TextureBlendType blendType>
+inline void fetchTransformed_pixelBounds(int max, int l1, int l2, int &v)
+{
+ Q_STATIC_ASSERT(blendType == BlendTransformed || blendType == BlendTransformedTiled);
+ if (blendType == BlendTransformedTiled) {
+ if (v < 0 || v >= max) {
+ v %= max;
+ if (v < 0) v += max;
+ }
} else {
- const uint *src = (const uint *)data->texture.scanLine(y) + x;
- return layout->convertToARGB64PM(buffer, src, length, data->texture.colorTable, 0);
+ v = qBound(l1, v, l2);
}
}
-template<TextureBlendType blendType, QPixelLayout::BPP bpp>
-static const uint *QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, const QSpanData *data,
- int y, int x, int length)
+template<TextureBlendType blendType, QPixelLayout::BPP bpp, typename T>
+static void QT_FASTCALL fetchTransformed_fetcher(T *buffer, const QSpanData *data,
+ int y, int x, int length)
{
Q_STATIC_ASSERT(blendType == BlendTransformed || blendType == BlendTransformedTiled);
- const int image_width = data->texture.width;
- const int image_height = data->texture.height;
- const int image_x1 = data->texture.x1;
- const int image_y1 = data->texture.y1;
- const int image_x2 = data->texture.x2 - 1;
- const int image_y2 = data->texture.y2 - 1;
+ const QTextureData &image = data->texture;
const qreal cx = x + qreal(0.5);
const qreal cy = y + qreal(0.5);
+ constexpr bool useFetch = (bpp < QPixelLayout::BPP32) && sizeof(T) == sizeof(uint);
const QPixelLayout *layout = &qPixelLayouts[data->texture.format];
- if (bpp != QPixelLayout::BPPNone) // Like this to not ICE on GCC 5.3.1
+ if (!useFetch)
Q_ASSERT(layout->bpp == bpp);
// When templated 'fetch' should be inlined at compile time:
const FetchPixelFunc fetch = (bpp == QPixelLayout::BPPNone) ? qFetchPixel[layout->bpp] : FetchPixelFunc(fetchPixel<bpp>);
- uint *const end = buffer + length;
- uint *b = buffer;
if (data->fast_matrix) {
// The increment pr x in the scanline
int fdx = (int)(data->m11 * fixed_scale);
@@ -1657,24 +2018,105 @@ static const uint *QT_FASTCALL fetchTransformed(uint *buffer, const Operator *,
int fy = int((data->m22 * cy
+ data->m12 * cx + data->dy) * fixed_scale);
- while (b < end) {
- int px = fx >> 16;
- int py = fy >> 16;
-
- if (blendType == BlendTransformedTiled) {
- px %= image_width;
- py %= image_height;
- if (px < 0) px += image_width;
- if (py < 0) py += image_height;
- } else {
- px = qBound(image_x1, px, image_x2);
- py = qBound(image_y1, py, image_y2);
+ if (fdy == 0) { // simple scale, no rotation or shear
+ int py = (fy >> 16);
+ fetchTransformed_pixelBounds<blendType>(image.height, image.y1, image.y2 - 1, py);
+ const uchar *src = image.scanLine(py);
+
+ int i = 0;
+ if (blendType == BlendTransformed) {
+ int fastLen = length;
+ 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 x1 = (fx >> 16);
+ int x2 = x1;
+ fetchTransformed_pixelBounds<blendType>(image.width, image.x1, image.x2 - 1, x1);
+ if (x1 == x2)
+ break;
+ if (useFetch)
+ buffer[i] = fetch(src, x1);
+ else
+ buffer[i] = reinterpret_cast<const T*>(src)[x1];
+ fx += fdx;
+ }
+
+ for (; i < fastLen; ++i) {
+ int px = (fx >> 16);
+ if (useFetch)
+ buffer[i] = fetch(src, px);
+ else
+ buffer[i] = reinterpret_cast<const T*>(src)[px];
+ fx += fdx;
+ }
}
- *b = fetch(data->texture.scanLine(py), px);
- fx += fdx;
- fy += fdy;
- ++b;
+ for (; i < length; ++i) {
+ int px = (fx >> 16);
+ fetchTransformed_pixelBounds<blendType>(image.width, image.x1, image.x2 - 1, px);
+ if (useFetch)
+ buffer[i] = fetch(src, px);
+ else
+ buffer[i] = reinterpret_cast<const T*>(src)[px];
+ fx += fdx;
+ }
+ } else { // rotation or shear
+ int i = 0;
+ if (blendType == BlendTransformed) {
+ int fastLen = length;
+ 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 x1 = (fx >> 16);
+ int y1 = (fy >> 16);
+ int x2 = x1;
+ int y2 = y1;
+ fetchTransformed_pixelBounds<blendType>(image.width, image.x1, image.x2 - 1, x1);
+ fetchTransformed_pixelBounds<blendType>(image.height, image.y1, image.y2 - 1, y1);
+ if (x1 == x2 && y1 == y2)
+ break;
+ if (useFetch)
+ buffer[i] = fetch(image.scanLine(y1), x1);
+ else
+ buffer[i] = reinterpret_cast<const T*>(image.scanLine(y1))[x1];
+ fx += fdx;
+ fy += fdy;
+ }
+
+ for (; i < fastLen; ++i) {
+ int px = (fx >> 16);
+ int py = (fy >> 16);
+ if (useFetch)
+ buffer[i] = fetch(image.scanLine(py), px);
+ else
+ buffer[i] = reinterpret_cast<const T*>(image.scanLine(py))[px];
+ fx += fdx;
+ fy += fdy;
+ }
+ }
+
+ for (; i < length; ++i) {
+ int px = (fx >> 16);
+ int py = (fy >> 16);
+ fetchTransformed_pixelBounds<blendType>(image.width, image.x1, image.x2 - 1, px);
+ fetchTransformed_pixelBounds<blendType>(image.height, image.y1, image.y2 - 1, py);
+ if (useFetch)
+ buffer[i] = fetch(image.scanLine(py), px);
+ else
+ buffer[i] = reinterpret_cast<const T*>(image.scanLine(py))[px];
+ fx += fdx;
+ fy += fdy;
+ }
}
} else {
const qreal fdx = data->m11;
@@ -1685,23 +2127,21 @@ static const uint *QT_FASTCALL fetchTransformed(uint *buffer, const Operator *,
qreal fy = data->m22 * cy + data->m12 * cx + data->dy;
qreal fw = data->m23 * cy + data->m13 * cx + data->m33;
+ T *const end = buffer + length;
+ T *b = buffer;
while (b < end) {
const qreal iw = fw == 0 ? 1 : 1 / fw;
const qreal tx = fx * iw;
const qreal ty = fy * iw;
- int px = int(tx) - (tx < 0);
- int py = int(ty) - (ty < 0);
-
- if (blendType == BlendTransformedTiled) {
- px %= image_width;
- py %= image_height;
- if (px < 0) px += image_width;
- if (py < 0) py += image_height;
- } else {
- px = qBound(image_x1, px, image_x2);
- py = qBound(image_y1, py, image_y2);
- }
- *b = fetch(data->texture.scanLine(py), px);
+ int px = qFloor(tx);
+ int py = qFloor(ty);
+
+ fetchTransformed_pixelBounds<blendType>(image.height, image.y1, image.y2 - 1, py);
+ fetchTransformed_pixelBounds<blendType>(image.width, image.x1, image.x2 - 1, px);
+ if (useFetch)
+ *b = fetch(image.scanLine(py), px);
+ else
+ *b = reinterpret_cast<const T*>(image.scanLine(py))[px];
fx += fdx;
fy += fdy;
@@ -1713,115 +2153,37 @@ static const uint *QT_FASTCALL fetchTransformed(uint *buffer, const Operator *,
++b;
}
}
- return layout->convertToARGB32PM(buffer, buffer, length, data->texture.colorTable, 0);
+}
+
+template<TextureBlendType blendType, QPixelLayout::BPP bpp>
+static const uint *QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, const QSpanData *data,
+ int y, int x, int length)
+{
+ Q_STATIC_ASSERT(blendType == BlendTransformed || blendType == BlendTransformedTiled);
+ const QPixelLayout *layout = &qPixelLayouts[data->texture.format];
+ fetchTransformed_fetcher<blendType, bpp, uint>(buffer, data, y, x, length);
+ layout->convertToARGB32PM(buffer, length, data->texture.colorTable);
+ return buffer;
}
template<TextureBlendType blendType> /* either BlendTransformed or BlendTransformedTiled */
static const QRgba64 *QT_FASTCALL fetchTransformed64(QRgba64 *buffer, const Operator *, const QSpanData *data,
int y, int x, int length)
{
- const int image_width = data->texture.width;
- const int image_height = data->texture.height;
- const int image_x1 = data->texture.x1;
- const int image_y1 = data->texture.y1;
- const int image_x2 = data->texture.x2 - 1;
- const int image_y2 = data->texture.y2 - 1;
-
- const qreal cx = x + qreal(0.5);
- const qreal cy = y + qreal(0.5);
-
const QPixelLayout *layout = &qPixelLayouts[data->texture.format];
- FetchPixelFunc fetch = qFetchPixel[layout->bpp];
- const QVector<QRgb> *clut = data->texture.colorTable;
-
- uint buffer32[buffer_size];
- QRgba64 *b = buffer;
- if (data->fast_matrix) {
- // The increment pr x in the scanline
- int fdx = (int)(data->m11 * fixed_scale);
- int fdy = (int)(data->m12 * fixed_scale);
-
- int fx = int((data->m21 * cy
- + data->m11 * cx + data->dx) * fixed_scale);
- int fy = int((data->m22 * cy
- + data->m12 * cx + data->dy) * fixed_scale);
-
- int i = 0, j = 0;
- while (i < length) {
- if (j == buffer_size) {
- layout->convertToARGB64PM(b, buffer32, buffer_size, clut, 0);
- b += buffer_size;
- j = 0;
- }
- int px = fx >> 16;
- int py = fy >> 16;
-
- if (blendType == BlendTransformedTiled) {
- px %= image_width;
- py %= image_height;
- if (px < 0) px += image_width;
- if (py < 0) py += image_height;
- } else {
- px = qBound(image_x1, px, image_x2);
- py = qBound(image_y1, py, image_y2);
- }
- buffer32[j] = fetch(data->texture.scanLine(py), px);
-
- fx += fdx;
- fy += fdy;
- ++i; ++j;
- }
- if (j > 0) {
- layout->convertToARGB64PM(b, buffer32, j, clut, 0);
- b += j;
- }
- } else {
- 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;
-
- int i = 0, j = 0;
- while (i < length) {
- if (j == buffer_size) {
- layout->convertToARGB64PM(b, buffer32, buffer_size, clut, 0);
- b += buffer_size;
- j = 0;
- }
- const qreal iw = fw == 0 ? 1 : 1 / fw;
- const qreal tx = fx * iw;
- const qreal ty = fy * iw;
- int px = int(tx) - (tx < 0);
- int py = int(ty) - (ty < 0);
-
- if (blendType == BlendTransformedTiled) {
- px %= image_width;
- py %= image_height;
- if (px < 0) px += image_width;
- if (py < 0) py += image_height;
- } else {
- px = qBound(image_x1, px, image_x2);
- py = qBound(image_y1, py, image_y2);
- }
- buffer32[j] = fetch(data->texture.scanLine(py), px);
-
- fx += fdx;
- fy += fdy;
- fw += fdw;
- //force increment to avoid /0
- if (!fw) {
- fw += fdw;
- }
- ++i; ++j;
- }
- if (j > 0) {
- layout->convertToARGB64PM(b, buffer32, j, clut, 0);
- b += j;
- }
+ if (layout->bpp != QPixelLayout::BPP64) {
+ uint buffer32[BufferSize];
+ Q_ASSERT(length <= BufferSize);
+ if (layout->bpp == QPixelLayout::BPP32)
+ fetchTransformed_fetcher<blendType, QPixelLayout::BPP32, uint>(buffer32, data, y, x, length);
+ else
+ fetchTransformed_fetcher<blendType, QPixelLayout::BPPNone, uint>(buffer32, data, y, x, length);
+ return layout->convertToRGBA64PM(buffer, buffer32, length, data->texture.colorTable, nullptr);
}
+
+ fetchTransformed_fetcher<blendType, QPixelLayout::BPP64, QRgba64>(buffer, data, y, x, length);
+ if (data->texture.format == QImage::Format_RGBA64)
+ convertRGBA64ToRGBA64PM(buffer, length);
return buffer;
}
@@ -1915,43 +2277,6 @@ static inline uint interpolate_4_pixels_16(uint tl, uint tr, uint bl, uint br, u
}
#endif
-#if defined(__SSE2__)
-static inline QRgba64 interpolate_4_pixels_rgb64(QRgba64 t[], QRgba64 b[], uint distx, uint disty)
-{
- __m128i vt = _mm_loadu_si128((const __m128i*)t);
- if (disty) {
- __m128i vb = _mm_loadu_si128((const __m128i*)b);
- vt = _mm_mulhi_epu16(vt, _mm_set1_epi16(0x10000 - disty));
- vb = _mm_mulhi_epu16(vb, _mm_set1_epi16(disty));
- vt = _mm_add_epi16(vt, vb);
- }
- if (distx) {
- 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));
- vt = _mm_mulhi_epu16(vt, _mm_unpacklo_epi64(vidistx, vdistx));
- vt = _mm_add_epi16(vt, _mm_srli_si128(vt, 8));
- }
-#ifdef Q_PROCESSOR_X86_64
- return QRgba64::fromRgba64(_mm_cvtsi128_si64(vt));
-#else
- QRgba64 out;
- _mm_storel_epi64((__m128i*)&out, vt);
- return out;
-#endif
-}
-#else
-static inline QRgba64 interpolate_4_pixels_rgb64(QRgba64 t[], QRgba64 b[], uint distx, uint disty)
-{
- const uint dx = distx>>8;
- const uint dy = disty>>8;
- const uint idx = 256 - dx;
- const uint idy = 256 - dy;
- QRgba64 xtop = interpolate256(t[0], idx, t[1], dx);
- QRgba64 xbot = interpolate256(b[0], idx, b[1], dx);
- return interpolate256(xtop, idy, xbot, dy);
-}
-#endif
-
template<TextureBlendType blendType>
void fetchTransformedBilinear_pixelBounds(int max, int l1, int l2, int &v1, int &v2);
@@ -1982,7 +2307,7 @@ inline void fetchTransformedBilinear_pixelBounds<BlendTransformedBilinear>(int,
}
enum FastTransformTypes {
- SimpleUpscaleTransform,
+ SimpleScaleTransform,
UpscaleTransform,
DownscaleTransform,
RotateTransform,
@@ -1990,11 +2315,38 @@ enum FastTransformTypes {
NFastTransformTypes
};
+// Completes the partial interpolation stored in IntermediateBuffer.
+// by performing the x-axis interpolation and joining the RB and AG buffers.
+static void QT_FASTCALL intermediate_adder(uint *b, uint *end, const IntermediateBuffer &intermediate, int offset, int &fx, int fdx)
+{
+#if defined(QT_COMPILER_SUPPORTS_AVX2)
+ extern void QT_FASTCALL intermediate_adder_avx2(uint *b, uint *end, const IntermediateBuffer &intermediate, int offset, int &fx, int fdx);
+ if (qCpuHasFeature(AVX2))
+ return intermediate_adder_avx2(b, end, intermediate, offset, fx, fdx);
+#endif
+
+ // Switch to intermediate buffer coordinates
+ fx -= offset * fixed_scale;
+
+ while (b < end) {
+ const int x = (fx >> 16);
+
+ const uint distx = (fx & 0x0000ffff) >> 8;
+ const uint idistx = 256 - distx;
+ const uint rb = (intermediate.buffer_rb[x] * idistx + intermediate.buffer_rb[x + 1] * distx) & 0xff00ff00;
+ const uint ag = (intermediate.buffer_ag[x] * idistx + intermediate.buffer_ag[x + 1] * distx) & 0xff00ff00;
+ *b = (rb >> 8) | ag;
+ b++;
+ fx += fdx;
+ }
+ fx += offset * fixed_scale;
+}
+
typedef void (QT_FASTCALL *BilinearFastTransformHelper)(uint *b, uint *end, const QTextureData &image, int &fx, int &fy, int fdx, int fdy);
template<TextureBlendType blendType>
-static void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_upscale_helper(uint *b, uint *end, const QTextureData &image,
- int &fx, int &fy, int fdx, int /*fdy*/)
+static void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_scale_helper(uint *b, uint *end, const QTextureData &image,
+ int &fx, int &fy, int fdx, int /*fdy*/)
{
int y1 = (fy >> 16);
int y2;
@@ -2011,16 +2363,12 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_upscale_helper(u
const int offset = (fx + adjust) >> 16;
int x = offset;
- // 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.
-
- // intermediate_buffer[0] is a buffer of red-blue component of the pixel, in the form 0x00RR00BB
- // intermediate_buffer[1] is the alpha-green component of the pixel, in the form 0x00AA00GG
- // +1 for the last pixel to interpolate with, and +1 for rounding errors.
- quint32 intermediate_buffer[2][buffer_size + 2];
- // count is the size used in the intermediate_buffer.
+ IntermediateBuffer intermediate;
+ // count is the size used in the intermediate.buffer.
int count = (qint64(length) * qAbs(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
+ // length is supposed to be <= BufferSize either because data->m11 < 1 or
+ // data->m11 < 2, and any larger buffers split
+ Q_ASSERT(count <= BufferSize + 2);
int f = 0;
int lim = count;
if (blendType == BlendTransformedBilinearTiled) {
@@ -2035,8 +2383,8 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_upscale_helper(u
quint32 rb = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff;
quint32 ag = ((((t>>8) & 0xff00ff) * idisty + ((b>>8) & 0xff00ff) * disty) >> 8) & 0xff00ff;
do {
- intermediate_buffer[0][f] = rb;
- intermediate_buffer[1][f] = ag;
+ intermediate.buffer_rb[f] = rb;
+ intermediate.buffer_ag[f] = ag;
f++;
x++;
} while (x < image.x1 && f < lim);
@@ -2069,10 +2417,10 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_upscale_helper(u
// Add the values, and shift to only keep 8 significant bits per colors
__m128i rAG =_mm_add_epi16(topAG, bottomAG);
rAG = _mm_srli_epi16(rAG, 8);
- _mm_storeu_si128((__m128i*)(&intermediate_buffer[1][f]), rAG);
+ _mm_storeu_si128((__m128i*)(&intermediate.buffer_ag[f]), rAG);
__m128i rRB =_mm_add_epi16(topRB, bottomRB);
rRB = _mm_srli_epi16(rRB, 8);
- _mm_storeu_si128((__m128i*)(&intermediate_buffer[0][f]), rRB);
+ _mm_storeu_si128((__m128i*)(&intermediate.buffer_rb[f]), rRB);
}
#elif defined(__ARM_NEON__)
const int16x8_t disty_ = vdupq_n_s16(disty);
@@ -2099,10 +2447,10 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_upscale_helper(u
// Add the values, and shift to only keep 8 significant bits per colors
int16x8_t rAG = vaddq_s16(topAG, bottomAG);
rAG = vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(rAG), 8));
- vst1q_s16((int16_t*)(&intermediate_buffer[1][f]), rAG);
+ vst1q_s16((int16_t*)(&intermediate.buffer_ag[f]), rAG);
int16x8_t rRB = vaddq_s16(topRB, bottomRB);
rRB = vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(rRB), 8));
- vst1q_s16((int16_t*)(&intermediate_buffer[0][f]), rRB);
+ vst1q_s16((int16_t*)(&intermediate.buffer_rb[f]), rRB);
}
#endif
}
@@ -2116,28 +2464,13 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_upscale_helper(u
uint t = s1[x];
uint b = s2[x];
- intermediate_buffer[0][f] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff;
- intermediate_buffer[1][f] = ((((t>>8) & 0xff00ff) * idisty + ((b>>8) & 0xff00ff) * disty) >> 8) & 0xff00ff;
+ intermediate.buffer_rb[f] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff;
+ intermediate.buffer_ag[f] = ((((t>>8) & 0xff00ff) * idisty + ((b>>8) & 0xff00ff) * disty) >> 8) & 0xff00ff;
x++;
}
- // Now interpolate the values from the intermediate_buffer to get the final result.
- fx -= offset * fixed_scale; // Switch to intermediate buffer coordinates
-
- 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 = ((intermediate_buffer[0][x1] * idistx + intermediate_buffer[0][x2] * distx) >> 8) & 0xff00ff;
- int ag = (intermediate_buffer[1][x1] * idistx + intermediate_buffer[1][x2] * distx) & 0xff00ff00;
- *b = rb | ag;
- b++;
- fx += fdx;
- }
+ // Now interpolate the values from the intermediate.buffer to get the final result.
+ intermediate_adder(b, end, intermediate, offset, fx, fdx);
}
template<TextureBlendType blendType>
@@ -2603,14 +2936,14 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_fast_rotate_helper(uint
static BilinearFastTransformHelper bilinearFastTransformHelperARGB32PM[2][NFastTransformTypes] = {
{
- fetchTransformedBilinearARGB32PM_simple_upscale_helper<BlendTransformedBilinear>,
+ fetchTransformedBilinearARGB32PM_simple_scale_helper<BlendTransformedBilinear>,
fetchTransformedBilinearARGB32PM_upscale_helper<BlendTransformedBilinear>,
fetchTransformedBilinearARGB32PM_downscale_helper<BlendTransformedBilinear>,
fetchTransformedBilinearARGB32PM_rotate_helper<BlendTransformedBilinear>,
fetchTransformedBilinearARGB32PM_fast_rotate_helper<BlendTransformedBilinear>
},
{
- fetchTransformedBilinearARGB32PM_simple_upscale_helper<BlendTransformedBilinearTiled>,
+ fetchTransformedBilinearARGB32PM_simple_scale_helper<BlendTransformedBilinearTiled>,
fetchTransformedBilinearARGB32PM_upscale_helper<BlendTransformedBilinearTiled>,
fetchTransformedBilinearARGB32PM_downscale_helper<BlendTransformedBilinearTiled>,
fetchTransformedBilinearARGB32PM_rotate_helper<BlendTransformedBilinearTiled>,
@@ -2645,7 +2978,13 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c
if (fdy == 0) { // simple scale, no rotation or shear
if (qAbs(fdx) <= fixed_scale) {
// simple scale up on X
- bilinearFastTransformHelperARGB32PM[tiled][SimpleUpscaleTransform](b, end, data->texture, fx, fy, fdx, fdy);
+ bilinearFastTransformHelperARGB32PM[tiled][SimpleScaleTransform](b, end, data->texture, fx, fy, fdx, fdy);
+ } else if (qAbs(fdx) <= 2 * fixed_scale) {
+ // simple scale down on X, less than 2x
+ const int mid = (length * 2 < BufferSize) ? length : ((length + 1) / 2);
+ bilinearFastTransformHelperARGB32PM[tiled][SimpleScaleTransform](buffer, buffer + mid, data->texture, fx, fy, fdx, fdy);
+ if (mid != length)
+ bilinearFastTransformHelperARGB32PM[tiled][SimpleScaleTransform](buffer + mid, buffer + length, data->texture, fx, fy, fdx, fdy);
} else if (qAbs(data->m22) < qreal(1./8.)) {
// scale up more than 8x (on Y)
bilinearFastTransformHelperARGB32PM[tiled][UpscaleTransform](b, end, data->texture, fx, fy, fdx, fdy);
@@ -2713,16 +3052,13 @@ 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*/)
+template<TextureBlendType blendType>
+static void QT_FASTCALL fetchTransformedBilinear_simple_scale_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;
+ const FetchAndConvertPixelsFunc fetch = layout->fetchToARGB32PM;
int y1 = (fy >> 16);
int y2;
@@ -2739,16 +3075,14 @@ static void QT_FASTCALL fetchTransformedBilinear_simple_upscale_helper(uint *b,
const int offset = (fx + adjust) >> 16;
int x = offset;
- // 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];
+ IntermediateBuffer intermediate;
+ uint *buf1 = intermediate.buffer_rb;
+ uint *buf2 = intermediate.buffer_ag;
const uint *ptr1;
const uint *ptr2;
int count = (qint64(length) * qAbs(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
+ Q_ASSERT(count <= BufferSize + 2);
if (blendType == BlendTransformedBilinearTiled) {
x %= image.width;
@@ -2757,10 +3091,8 @@ static void QT_FASTCALL fetchTransformedBilinear_simple_upscale_helper(uint *b,
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);
+ ptr1 = fetch(buf1, s1, x, len1, clut, nullptr);
+ ptr2 = fetch(buf2, s2, x, len1, clut, nullptr);
for (int i = 0; i < len1; ++i) {
uint t = ptr1[i];
uint b = ptr2[i];
@@ -2769,10 +3101,8 @@ static void QT_FASTCALL fetchTransformedBilinear_simple_upscale_helper(uint *b,
}
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);
+ ptr1 = fetch(buf1 + len1, s1, 0, len2, clut, nullptr);
+ ptr2 = fetch(buf2 + len1, s2, 0, len2, clut, nullptr);
for (int i = 0; i < len2; ++i) {
uint t = ptr1[i];
uint b = ptr2[i];
@@ -2780,6 +3110,7 @@ static void QT_FASTCALL fetchTransformedBilinear_simple_upscale_helper(uint *b,
buf2[i + len1] = ((((t >> 8) & 0xff00ff) * idisty + ((b >> 8) & 0xff00ff) * disty) >> 8) & 0xff00ff;
}
}
+ // Generate the rest by repeatedly repeating the previous set of pixels
for (int i = image.width; i < count; ++i) {
buf1[i] = buf1[i - image.width];
buf2[i] = buf2[i - image.width];
@@ -2790,10 +3121,8 @@ static void QT_FASTCALL fetchTransformedBilinear_simple_upscale_helper(uint *b,
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);
+ ptr1 = fetch(buf1 + leading, s1, start, len, clut, nullptr);
+ ptr2 = fetch(buf2 + leading, s2, start, len, clut, nullptr);
for (int i = 0; i < len; ++i) {
uint t = ptr1[i];
@@ -2812,35 +3141,21 @@ static void QT_FASTCALL fetchTransformedBilinear_simple_upscale_helper(uint *b,
}
}
- // Now interpolate the values from the intermediate_buffer to get the final result.
- fx -= offset * fixed_scale; // Switch to intermediate buffer coordinates
-
- 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;
- }
+ // Now interpolate the values from the intermediate.buffer to get the final result.
+ intermediate_adder(b, end, intermediate, offset, 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,
+template<TextureBlendType blendType, QPixelLayout::BPP bpp, typename T>
+static void QT_FASTCALL fetchTransformedBilinear_fetcher(T *buf1, T *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:
+ constexpr bool useFetch = (bpp < QPixelLayout::BPP32);
+ if (useFetch)
+ Q_ASSERT(sizeof(T) == sizeof(uint));
+ else
+ Q_ASSERT(layout.bpp == bpp);
const FetchPixelFunc fetch1 = (bpp == QPixelLayout::BPPNone) ? qFetchPixel[layout.bpp] : fetchPixel<bpp>;
if (fdy == 0) {
int y1 = (fy >> 16);
@@ -2857,8 +3172,13 @@ static void QT_FASTCALL fetchTransformedBilinear_fetcher(uint *buf1, uint *buf2,
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);
+ if (useFetch) {
+ buf1[i * 2 + 0] = buf1[i * 2 + 1] = fetch1(s1, x1);
+ buf2[i * 2 + 0] = buf2[i * 2 + 1] = fetch1(s2, x1);
+ } else {
+ buf1[i * 2 + 0] = buf1[i * 2 + 1] = reinterpret_cast<const T *>(s1)[x1];
+ buf2[i * 2 + 0] = buf2[i * 2 + 1] = reinterpret_cast<const T *>(s2)[x1];
+ }
fx += fdx;
}
int fastLen = len;
@@ -2869,10 +3189,17 @@ static void QT_FASTCALL fetchTransformedBilinear_fetcher(uint *buf1, uint *buf2,
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);
+ if (useFetch) {
+ 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);
+ } else {
+ buf1[i * 2 + 0] = reinterpret_cast<const T *>(s1)[x];
+ buf1[i * 2 + 1] = reinterpret_cast<const T *>(s1)[x + 1];
+ buf2[i * 2 + 0] = reinterpret_cast<const T *>(s2)[x];
+ buf2[i * 2 + 1] = reinterpret_cast<const T *>(s2)[x + 1];
+ }
fx += fdx;
}
}
@@ -2881,10 +3208,17 @@ static void QT_FASTCALL fetchTransformedBilinear_fetcher(uint *buf1, uint *buf2,
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);
+ if (useFetch) {
+ 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);
+ } else {
+ buf1[i * 2 + 0] = reinterpret_cast<const T *>(s1)[x1];
+ buf1[i * 2 + 1] = reinterpret_cast<const T *>(s1)[x2];
+ buf2[i * 2 + 0] = reinterpret_cast<const T *>(s2)[x1];
+ buf2[i * 2 + 1] = reinterpret_cast<const T *>(s2)[x2];
+ }
fx += fdx;
}
} else {
@@ -2901,10 +3235,17 @@ static void QT_FASTCALL fetchTransformedBilinear_fetcher(uint *buf1, uint *buf2,
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);
+ if (useFetch) {
+ 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);
+ } else {
+ buf1[i * 2 + 0] = reinterpret_cast<const T *>(s1)[x1];
+ buf1[i * 2 + 1] = reinterpret_cast<const T *>(s1)[x2];
+ buf2[i * 2 + 0] = reinterpret_cast<const T *>(s2)[x1];
+ buf2[i * 2 + 1] = reinterpret_cast<const T *>(s2)[x2];
+ }
fx += fdx;
fy += fdy;
}
@@ -2923,10 +3264,17 @@ static void QT_FASTCALL fetchTransformedBilinear_fetcher(uint *buf1, uint *buf2,
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);
+ if (useFetch) {
+ 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);
+ } else {
+ buf1[i * 2 + 0] = reinterpret_cast<const T *>(s1)[x];
+ buf1[i * 2 + 1] = reinterpret_cast<const T *>(s1)[x + 1];
+ buf2[i * 2 + 0] = reinterpret_cast<const T *>(s2)[x];
+ buf2[i * 2 + 1] = reinterpret_cast<const T *>(s2)[x + 1];
+ }
fx += fdx;
fy += fdy;
}
@@ -2942,10 +3290,17 @@ static void QT_FASTCALL fetchTransformedBilinear_fetcher(uint *buf1, uint *buf2,
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);
+ if (useFetch) {
+ 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);
+ } else {
+ buf1[i * 2 + 0] = reinterpret_cast<const T *>(s1)[x1];
+ buf1[i * 2 + 1] = reinterpret_cast<const T *>(s1)[x2];
+ buf2[i * 2 + 0] = reinterpret_cast<const T *>(s2)[x1];
+ buf2[i * 2 + 1] = reinterpret_cast<const T *>(s2)[x2];
+ }
fx += fdx;
fy += fdy;
}
@@ -2977,18 +3332,23 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
if (fdy == 0) { // simple scale, no rotation or shear
if (qAbs(fdx) <= fixed_scale) { // scale up on X
- fetchTransformedBilinear_simple_upscale_helper<blendType, bpp>(buffer, buffer + length, data->texture, fx, fy, fdx, fdy);
+ fetchTransformedBilinear_simple_scale_helper<blendType>(buffer, buffer + length, data->texture, fx, fy, fdx, fdy);
+ } else if (qAbs(fdx) <= 2 * fixed_scale) { // scale down on X less than 2x
+ const int mid = (length * 2 < BufferSize) ? length : ((length + 1) / 2);
+ fetchTransformedBilinear_simple_scale_helper<blendType>(buffer, buffer + mid, data->texture, fx, fy, fdx, fdy);
+ if (mid != length)
+ fetchTransformedBilinear_simple_scale_helper<blendType>(buffer + mid, buffer + length, data->texture, fx, fy, fdx, fdy);
} else {
- const BilinearFastTransformFetcher fetcher = fetchTransformedBilinear_fetcher<blendType,bpp>;
+ const auto fetcher = fetchTransformedBilinear_fetcher<blendType,bpp,uint>;
- uint buf1[buffer_size];
- uint buf2[buffer_size];
+ uint buf1[BufferSize];
+ uint buf2[BufferSize];
uint *b = buffer;
while (length) {
- int len = qMin(length, buffer_size / 2);
+ int len = qMin(length, BufferSize / 2);
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);
+ layout->convertToARGB32PM(buf1, len * 2, clut);
+ layout->convertToARGB32PM(buf2, len * 2, clut);
if (hasFastInterpolate4() || qAbs(data->m22) < qreal(1./8.)) { // scale up more than 8x (on Y)
int disty = (fy & 0x0000ffff) >> 8;
@@ -3014,16 +3374,16 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
}
}
} else { // rotation or shear
- const BilinearFastTransformFetcher fetcher = fetchTransformedBilinear_fetcher<blendType,bpp>;
+ const auto fetcher = fetchTransformedBilinear_fetcher<blendType,bpp,uint>;
- uint buf1[buffer_size];
- uint buf2[buffer_size];
+ uint buf1[BufferSize];
+ uint buf2[BufferSize];
uint *b = buffer;
while (length) {
- int len = qMin(length, buffer_size / 2);
+ int len = qMin(length, BufferSize / 2);
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);
+ layout->convertToARGB32PM(buf1, len * 2, clut);
+ layout->convertToARGB32PM(buf2, len * 2, clut);
if (hasFastInterpolate4() || 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.
@@ -3070,15 +3430,15 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
qreal fy = data->m22 * cy + data->m12 * cx + data->dy;
qreal fw = data->m23 * cy + data->m13 * cx + data->m33;
- uint buf1[buffer_size];
- uint buf2[buffer_size];
+ uint buf1[BufferSize];
+ uint buf2[BufferSize];
uint *b = buffer;
- int distxs[buffer_size / 2];
- int distys[buffer_size / 2];
+ int distxs[BufferSize / 2];
+ int distys[BufferSize / 2];
while (length) {
- int len = qMin(length, buffer_size / 2);
+ int len = qMin(length, BufferSize / 2);
for (int i = 0; i < len; ++i) {
const qreal iw = fw == 0 ? 1 : 1 / fw;
const qreal px = fx * iw - qreal(0.5);
@@ -3110,8 +3470,8 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
fw += fdw;
}
- layout->convertToARGB32PM(buf1, buf1, len * 2, clut, 0);
- layout->convertToARGB32PM(buf2, buf2, len * 2, clut, 0);
+ layout->convertToARGB32PM(buf1, len * 2, clut);
+ layout->convertToARGB32PM(buf2, len * 2, clut);
for (int i = 0; i < len; ++i) {
int distx = distxs[i];
@@ -3128,19 +3488,27 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
}
template<TextureBlendType blendType>
-static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, const Operator *,
- const QSpanData *data, int y, int x, int length)
+static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64_uint32(QRgba64 *buffer, const QSpanData *data,
+ int y, int x, int length)
{
- const QPixelLayout *layout = &qPixelLayouts[data->texture.format];
+ const QTextureData &texture = data->texture;
+ const QPixelLayout *layout = &qPixelLayouts[texture.format];
const QVector<QRgb> *clut = data->texture.colorTable;
const qreal cx = x + qreal(0.5);
const qreal cy = y + qreal(0.5);
+ uint sbuf1[BufferSize];
+ uint sbuf2[BufferSize];
+ QRgba64 buf1[BufferSize];
+ QRgba64 buf2[BufferSize];
+ QRgba64 *end = buffer + length;
+ QRgba64 *b = buffer;
+
if (data->fast_matrix) {
// The increment pr x in the scanline
- int fdx = (int)(data->m11 * fixed_scale);
- int fdy = (int)(data->m12 * fixed_scale);
+ const int fdx = (int)(data->m11 * fixed_scale);
+ const int fdy = (int)(data->m12 * fixed_scale);
int fx = int((data->m21 * cy + data->m11 * cx + data->dx) * fixed_scale);
int fy = int((data->m22 * cy + data->m12 * cx + data->dy) * fixed_scale);
@@ -3148,20 +3516,14 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
fx -= half_point;
fy -= half_point;
- const BilinearFastTransformFetcher fetcher =
+ const auto fetcher =
(layout->bpp == QPixelLayout::BPP32)
- ? fetchTransformedBilinear_fetcher<blendType, QPixelLayout::BPP32>
- : fetchTransformedBilinear_fetcher<blendType, QPixelLayout::BPPNone>;
+ ? fetchTransformedBilinear_fetcher<blendType, QPixelLayout::BPP32, uint>
+ : fetchTransformedBilinear_fetcher<blendType, QPixelLayout::BPPNone, uint>;
if (fdy == 0) { //simple scale, no rotation
-
- uint sbuf1[buffer_size];
- uint sbuf2[buffer_size];
- quint64 buf1[buffer_size];
- quint64 buf2[buffer_size];
- QRgba64 *b = buffer;
while (length) {
- int len = qMin(length, buffer_size / 2);
+ int len = qMin(length, BufferSize / 2);
int disty = (fy & 0x0000ffff);
#if defined(__SSE2__)
const __m128i vdy = _mm_set1_epi16(disty);
@@ -3169,9 +3531,9 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
#endif
fetcher(sbuf1, sbuf2, len, data->texture, fx, fy, fdx, fdy);
- layout->convertToARGB64PM((QRgba64 *)buf1, sbuf1, len * 2, clut, 0);
+ layout->convertToRGBA64PM(buf1, sbuf1, len * 2, clut, 0);
if (disty)
- layout->convertToARGB64PM((QRgba64 *)buf2, sbuf2, len * 2, clut, 0);
+ layout->convertToRGBA64PM(buf2, sbuf2, len * 2, clut, 0);
for (int i = 0; i < len; ++i) {
int distx = (fx & 0x0000ffff);
@@ -3191,33 +3553,26 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
}
_mm_storel_epi64((__m128i*)(b+i), vt);
#else
- b[i] = interpolate_4_pixels_rgb64((QRgba64 *)buf1 + i*2, (QRgba64 *)buf2 + i*2, distx, disty);
+ b[i] = interpolate_4_pixels_rgb64(buf1 + i*2, buf2 + i*2, distx, disty);
#endif
fx += fdx;
}
length -= len;
b += len;
}
- } else { //rotation
- uint sbuf1[buffer_size];
- uint sbuf2[buffer_size];
- quint64 buf1[buffer_size];
- quint64 buf2[buffer_size];
- QRgba64 *end = buffer + length;
- QRgba64 *b = buffer;
-
+ } else { // rotation or shear
while (b < end) {
- int len = qMin(length, buffer_size / 2);
+ int len = qMin(length, BufferSize / 2);
fetcher(sbuf1, sbuf2, len, data->texture, fx, fy, fdx, fdy);
- layout->convertToARGB64PM((QRgba64 *)buf1, sbuf1, len * 2, clut, 0);
- layout->convertToARGB64PM((QRgba64 *)buf2, sbuf2, len * 2, clut, 0);
+ layout->convertToRGBA64PM(buf1, sbuf1, len * 2, clut, 0);
+ layout->convertToRGBA64PM(buf2, sbuf2, len * 2, clut, 0);
for (int i = 0; i < len; ++i) {
int distx = (fx & 0x0000ffff);
int disty = (fy & 0x0000ffff);
- b[i] = interpolate_4_pixels_rgb64((QRgba64 *)buf1 + i*2, (QRgba64 *)buf2 + i*2, distx, disty);
+ b[i] = interpolate_4_pixels_rgb64(buf1 + i*2, buf2 + i*2, distx, disty);
fx += fdx;
fy += fdy;
}
@@ -3226,7 +3581,7 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
b += len;
}
}
- } else {
+ } else { // !(data->fast_matrix)
const QTextureData &image = data->texture;
const qreal fdx = data->m11;
@@ -3238,17 +3593,12 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
qreal fw = data->m23 * cy + data->m13 * cx + data->m33;
FetchPixelFunc fetch = qFetchPixel[layout->bpp];
- uint sbuf1[buffer_size];
- uint sbuf2[buffer_size];
- quint64 buf1[buffer_size];
- quint64 buf2[buffer_size];
- QRgba64 *b = buffer;
- int distxs[buffer_size / 2];
- int distys[buffer_size / 2];
+ int distxs[BufferSize / 2];
+ int distys[BufferSize / 2];
- while (length) {
- int len = qMin(length, buffer_size / 2);
+ while (b < end) {
+ int len = qMin(length, BufferSize / 2);
for (int i = 0; i < len; ++i) {
const qreal iw = fw == 0 ? 1 : 1 / fw;
const qreal px = fx * iw - qreal(0.5);
@@ -3265,21 +3615,165 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
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);
+ const uchar *s1 = texture.scanLine(y1);
+ const uchar *s2 = 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];
+ 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);
- } 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);
+ fx += fdx;
+ fy += fdy;
+ fw += fdw;
+ //force increment to avoid /0
+ if (!fw)
+ fw += fdw;
+ }
+
+ layout->convertToRGBA64PM(buf1, sbuf1, len * 2, clut, 0);
+ layout->convertToRGBA64PM(buf2, sbuf2, len * 2, clut, 0);
+
+ for (int i = 0; i < len; ++i) {
+ int distx = distxs[i];
+ int disty = distys[i];
+ b[i] = interpolate_4_pixels_rgb64(buf1 + i*2, buf2 + i*2, distx, disty);
+ }
+
+ length -= len;
+ b += len;
+ }
+ }
+ return buffer;
+}
+
+template<TextureBlendType blendType>
+static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64_uint64(QRgba64 *buffer, const QSpanData *data,
+ int y, int x, int length)
+{
+ const QTextureData &texture = data->texture;
+ Q_ASSERT(qPixelLayouts[texture.format].bpp == QPixelLayout::BPP64);
+ const auto convert = (data->texture.format == QImage::Format_RGBA64) ? convertRGBA64ToRGBA64PM : convertRGBA64PMToRGBA64PM;
+
+ const qreal cx = x + qreal(0.5);
+ const qreal cy = y + qreal(0.5);
+
+ QRgba64 buf1[BufferSize];
+ QRgba64 buf2[BufferSize];
+ QRgba64 *end = buffer + length;
+ QRgba64 *b = buffer;
+
+ if (data->fast_matrix) {
+ // The increment pr x in the scanline
+ const int fdx = (int)(data->m11 * fixed_scale);
+ const int fdy = (int)(data->m12 * fixed_scale);
+
+ int fx = int((data->m21 * cy + data->m11 * cx + data->dx) * fixed_scale);
+ int fy = int((data->m22 * cy + data->m12 * cx + data->dy) * fixed_scale);
+
+ fx -= half_point;
+ fy -= half_point;
+ const auto fetcher = fetchTransformedBilinear_fetcher<blendType, QPixelLayout::BPP64, QRgba64>;
+
+ if (fdy == 0) { //simple scale, no rotation
+ while (length) {
+ int len = qMin(length, BufferSize / 2);
+ int disty = (fy & 0x0000ffff);
+#if defined(__SSE2__)
+ const __m128i vdy = _mm_set1_epi16(disty);
+ const __m128i vidy = _mm_set1_epi16(0x10000 - disty);
+#endif
+ fetcher(buf1, buf2, len, data->texture, fx, fy, fdx, fdy);
+
+ convert(buf1, len * 2);
+ if (disty)
+ convert(buf2, len * 2);
+
+ for (int i = 0; i < len; ++i) {
+ int distx = (fx & 0x0000ffff);
+#if defined(__SSE2__)
+ __m128i vt = _mm_loadu_si128((const __m128i*)(buf1 + i*2));
+ if (disty) {
+ __m128i vb = _mm_loadu_si128((const __m128i*)(buf2 + i*2));
+ vt = _mm_mulhi_epu16(vt, vidy);
+ vb = _mm_mulhi_epu16(vb, vdy);
+ vt = _mm_add_epi16(vt, vb);
+ }
+ if (distx) {
+ 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));
+ vt = _mm_mulhi_epu16(vt, _mm_unpacklo_epi64(vidistx, vdistx));
+ vt = _mm_add_epi16(vt, _mm_srli_si128(vt, 8));
+ }
+ _mm_storel_epi64((__m128i*)(b+i), vt);
+#else
+ b[i] = interpolate_4_pixels_rgb64(buf1 + i*2, buf2 + i*2, distx, disty);
+#endif
+ fx += fdx;
}
+ length -= len;
+ b += len;
+ }
+ } else { // rotation or shear
+ while (b < end) {
+ int len = qMin(length, BufferSize / 2);
+
+ fetcher(buf1, buf2, len, data->texture, fx, fy, fdx, fdy);
+
+ convert(buf1, len * 2);
+ convert(buf2, len * 2);
+
+ for (int i = 0; i < len; ++i) {
+ int distx = (fx & 0x0000ffff);
+ int disty = (fy & 0x0000ffff);
+ b[i] = interpolate_4_pixels_rgb64(buf1 + i*2, buf2 + i*2, distx, disty);
+ fx += fdx;
+ fy += fdy;
+ }
+
+ length -= len;
+ b += len;
+ }
+ }
+ } else { // !(data->fast_matrix)
+ 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;
+
+ int distxs[BufferSize / 2];
+ int distys[BufferSize / 2];
+
+ while (b < end) {
+ int len = qMin(length, BufferSize / 2);
+ for (int i = 0; i < len; ++i) {
+ const qreal iw = fw == 0 ? 1 : 1 / fw;
+ const qreal px = fx * iw - qreal(0.5);
+ const qreal py = fy * iw - qreal(0.5);
+
+ int x1 = int(px) - (px < 0);
+ int x2;
+ int y1 = int(py) - (py < 0);
+ int y2;
+
+ distxs[i] = int((px - x1) * (1<<16));
+ distys[i] = int((py - y1) * (1<<16));
+
+ 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 = texture.scanLine(y1);
+ const uchar *s2 = texture.scanLine(y2);
+
+ buf1[i * 2 + 0] = reinterpret_cast<const QRgba64 *>(s1)[x1];
+ buf1[i * 2 + 1] = reinterpret_cast<const QRgba64 *>(s1)[x2];
+ buf2[i * 2 + 0] = reinterpret_cast<const QRgba64 *>(s2)[x1];
+ buf2[i * 2 + 1] = reinterpret_cast<const QRgba64 *>(s2)[x2];
fx += fdx;
fy += fdy;
@@ -3289,23 +3783,31 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
fw += fdw;
}
- layout->convertToARGB64PM((QRgba64 *)buf1, sbuf1, len * 2, clut, 0);
- layout->convertToARGB64PM((QRgba64 *)buf2, sbuf2, len * 2, clut, 0);
+ convert(buf1, len * 2);
+ convert(buf2, len * 2);
for (int i = 0; i < len; ++i) {
int distx = distxs[i];
int disty = distys[i];
- b[i] = interpolate_4_pixels_rgb64((QRgba64 *)buf1 + i*2, (QRgba64 *)buf2 + i*2, distx, disty);
+ b[i] = interpolate_4_pixels_rgb64(buf1 + i*2, buf2 + i*2, distx, disty);
}
length -= len;
b += len;
}
}
-
return buffer;
}
+template<TextureBlendType blendType>
+static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, const Operator *,
+ const QSpanData *data, int y, int x, int length)
+{
+ if (qPixelLayouts[data->texture.format].bpp == QPixelLayout::BPP64)
+ return fetchTransformedBilinear64_uint64<blendType>(buffer, data, y, x, length);
+ return fetchTransformedBilinear64_uint32<blendType>(buffer, data, y, x, length);
+}
+
// FetchUntransformed can have more specialized methods added depending on SIMD features.
static SourceFetchProc sourceFetchUntransformed[QImage::NImageFormats] = {
0, // Invalid
@@ -3333,6 +3835,9 @@ static SourceFetchProc sourceFetchUntransformed[QImage::NImageFormats] = {
fetchUntransformed, // Format_A2RGB30_Premultiplied
fetchUntransformed, // Alpha8
fetchUntransformed, // Grayscale8
+ fetchUntransformed, // RGBX64
+ fetchUntransformed, // RGBA64
+ fetchUntransformed, // RGBA64_Premultiplied
};
static const SourceFetchProc sourceFetchGeneric[NBlendTypes] = {
@@ -3353,6 +3858,15 @@ static SourceFetchProc sourceFetchARGB32PM[NBlendTypes] = {
fetchTransformedBilinearARGB32PM<BlendTransformedBilinearTiled> // BilinearTiled
};
+static SourceFetchProc sourceFetchAny16[NBlendTypes] = {
+ fetchUntransformed, // Untransformed
+ fetchUntransformed, // Tiled
+ fetchTransformed<BlendTransformed, QPixelLayout::BPP16>, // Transformed
+ fetchTransformed<BlendTransformedTiled, QPixelLayout::BPP16>, // TransformedTiled
+ fetchTransformedBilinear<BlendTransformedBilinear, QPixelLayout::BPP16>, // TransformedBilinear
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QPixelLayout::BPP16> // TransformedBilinearTiled
+};
+
static SourceFetchProc sourceFetchAny32[NBlendTypes] = {
fetchUntransformed, // Untransformed
fetchUntransformed, // Tiled
@@ -3371,17 +3885,35 @@ static const SourceFetchProc64 sourceFetchGeneric64[NBlendTypes] = {
fetchTransformedBilinear64<BlendTransformedBilinearTiled> // BilinearTiled
};
+static const SourceFetchProc64 sourceFetchRGBA64PM[NBlendTypes] = {
+ fetchUntransformedRGBA64PM, // Untransformed
+ fetchUntransformedRGBA64PM, // Tiled
+ fetchTransformed64<BlendTransformed>, // Transformed
+ fetchTransformed64<BlendTransformedTiled>, // TransformedTiled
+ fetchTransformedBilinear64<BlendTransformedBilinear>, // Bilinear
+ fetchTransformedBilinear64<BlendTransformedBilinearTiled> // BilinearTiled
+};
+
static inline SourceFetchProc getSourceFetch(TextureBlendType blendType, QImage::Format format)
{
if (format == QImage::Format_RGB32 || format == QImage::Format_ARGB32_Premultiplied)
return sourceFetchARGB32PM[blendType];
if (blendType == BlendUntransformed || blendType == BlendTiled)
return sourceFetchUntransformed[format];
+ if (qPixelLayouts[format].bpp == QPixelLayout::BPP16)
+ return sourceFetchAny16[blendType];
if (qPixelLayouts[format].bpp == QPixelLayout::BPP32)
return sourceFetchAny32[blendType];
return sourceFetchGeneric[blendType];
}
+static inline SourceFetchProc64 getSourceFetch64(TextureBlendType blendType, QImage::Format format)
+{
+ if (format == QImage::Format_RGBX64 || format == QImage::Format_RGBA64_Premultiplied)
+ return sourceFetchRGBA64PM[blendType];
+ return sourceFetchGeneric64[blendType];
+}
+
#define FIXPT_BITS 8
#define FIXPT_SIZE (1<<FIXPT_BITS)
@@ -3724,7 +4256,7 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
case QSpanData::Texture:
solidSource = !data->texture.hasAlpha;
op.srcFetch = getSourceFetch(getBlendType(data), data->texture.format);
- op.srcFetch64 = sourceFetchGeneric64[getBlendType(data)];
+ op.srcFetch64 = getSourceFetch64(getBlendType(data), data->texture.format);;
break;
default:
Q_UNREACHABLE();
@@ -3752,8 +4284,9 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
// If all spans are opaque we do not need to fetch dest.
// But don't clear passthrough destFetch as they are just as fast and save destStore.
if (op.destFetch != destFetchARGB32P)
- op.destFetch = 0;
- op.destFetch64 = destFetch64Undefined;
+ op.destFetch = destFetchUndefined;
+ if (op.destFetch64 != destFetchRGB64)
+ op.destFetch64 = destFetch64Undefined;
}
}
@@ -3778,7 +4311,7 @@ static
void blend_color_generic(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
- uint buffer[buffer_size];
+ uint buffer[BufferSize];
Operator op = getOperator(data, spans, count);
const uint color = data->solid.color.toArgb32();
@@ -3786,8 +4319,8 @@ void blend_color_generic(int count, const QSpan *spans, void *userData)
int x = spans->x;
int length = spans->len;
while (length) {
- int l = qMin(buffer_size, length);
- uint *dest = op.destFetch ? op.destFetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer;
+ int l = qMin(BufferSize, length);
+ uint *dest = op.destFetch(buffer, data->rasterBuffer, x, spans->y, l);
op.funcSolid(dest, l, color, spans->coverage);
if (op.destStore)
op.destStore(data->rasterBuffer, x, spans->y, dest, l);
@@ -3802,7 +4335,7 @@ static void blend_color_argb(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
- Operator op = getOperator(data, spans, count);
+ const Operator op = getOperator(data, spans, count);
const uint color = data->solid.color.toArgb32();
if (op.mode == QPainter::CompositionMode_Source) {
@@ -3838,17 +4371,31 @@ void blend_color_generic_rgb64(int count, const QSpan *spans, void *userData)
return blend_color_generic(count, spans, userData);
}
- quint64 buffer[buffer_size];
+ quint64 buffer[BufferSize];
const QRgba64 color = data->solid.color;
+ bool solidFill = data->rasterBuffer->compositionMode == QPainter::CompositionMode_Source
+ || (data->rasterBuffer->compositionMode == QPainter::CompositionMode_SourceOver && color.isOpaque());
+ bool isBpp32 = qPixelLayouts[data->rasterBuffer->format].bpp == QPixelLayout::BPP32;
while (count--) {
int x = spans->x;
int length = spans->len;
+ if (solidFill && isBpp32 && spans->coverage == 255) {
+ // If dest doesn't matter we don't need to bother with blending or converting all the identical pixels
+ if (length > 0) {
+ op.destStore64(data->rasterBuffer, x, spans->y, &color, 1);
+ uint *dest = (uint*)data->rasterBuffer->scanLine(spans->y) + x;
+ qt_memfill32(dest + 1, dest[0], length - 1);
+ length = 0;
+ }
+ }
+
while (length) {
- int l = qMin(buffer_size, length);
+ int l = qMin(BufferSize, length);
QRgba64 *dest = op.destFetch64((QRgba64 *)buffer, data->rasterBuffer, x, spans->y, l);
op.funcSolid64(dest, l, color, spans->coverage);
- op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
+ if (op.destStore64)
+ op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
length -= l;
x += l;
}
@@ -3950,7 +4497,7 @@ void handleSpans(int count, const QSpan *spans, const QSpanData *data, T &handle
int length = right - x;
while (length) {
- int l = qMin(buffer_size, length);
+ int l = qMin(BufferSize, length);
length -= l;
int process_length = l;
@@ -3997,8 +4544,8 @@ struct QBlendBase
BlendType *dest;
- BlendType buffer[buffer_size];
- BlendType src_buffer[buffer_size];
+ BlendType buffer[BufferSize];
+ BlendType src_buffer[BufferSize];
};
class BlendSrcGeneric : public QBlendBase<uint>
@@ -4011,7 +4558,7 @@ public:
const uint *fetch(int x, int y, int len)
{
- dest = op.destFetch ? op.destFetch(buffer, data->rasterBuffer, x, y, len) : buffer;
+ dest = op.destFetch(buffer, data->rasterBuffer, x, y, len);
return op.srcFetch(src_buffer, &op, data, y, x, len);
}
@@ -4037,7 +4584,7 @@ public:
bool isSupported() const
{
- return op.func64 && op.destFetch64 && op.destStore64;
+ return op.func64 && op.destFetch64;
}
const quint64 *fetch(int x, int y, int len)
@@ -4053,7 +4600,8 @@ public:
void store(int x, int y, int len)
{
- op.destStore64(data->rasterBuffer, x, y, (QRgba64 *)dest, len);
+ if (op.destStore64)
+ op.destStore64(data->rasterBuffer, x, y, (QRgba64 *)dest, len);
}
};
@@ -4082,8 +4630,8 @@ static void blend_untransformed_generic(int count, const QSpan *spans, void *use
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
- uint buffer[buffer_size];
- uint src_buffer[buffer_size];
+ uint buffer[BufferSize];
+ uint src_buffer[BufferSize];
Operator op = getOperator(data, spans, count);
const int image_width = data->texture.width;
@@ -4107,9 +4655,9 @@ static void blend_untransformed_generic(int count, const QSpan *spans, void *use
if (length > 0) {
const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
while (length) {
- int l = qMin(buffer_size, length);
+ int l = qMin(BufferSize, length);
const uint *src = op.srcFetch(src_buffer, &op, data, sy, sx, l);
- uint *dest = op.destFetch ? op.destFetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer;
+ uint *dest = op.destFetch(buffer, data->rasterBuffer, x, spans->y, l);
op.func(dest, src, l, coverage);
if (op.destStore)
op.destStore(data->rasterBuffer, x, spans->y, dest, l);
@@ -4132,8 +4680,8 @@ static void blend_untransformed_generic_rgb64(int count, const QSpan *spans, voi
qCDebug(lcQtGuiDrawHelper, "blend_untransformed_generic_rgb64: unsupported 64-bit blend attempted, falling back to 32-bit");
return blend_untransformed_generic(count, spans, userData);
}
- quint64 buffer[buffer_size];
- quint64 src_buffer[buffer_size];
+ quint64 buffer[BufferSize];
+ quint64 src_buffer[BufferSize];
const int image_width = data->texture.width;
const int image_height = data->texture.height;
@@ -4156,11 +4704,12 @@ static void blend_untransformed_generic_rgb64(int count, const QSpan *spans, voi
if (length > 0) {
const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
while (length) {
- int l = qMin(buffer_size, length);
+ int l = qMin(BufferSize, length);
const QRgba64 *src = op.srcFetch64((QRgba64 *)src_buffer, &op, data, sy, sx, l);
QRgba64 *dest = op.destFetch64((QRgba64 *)buffer, data->rasterBuffer, x, spans->y, l);
op.func64(dest, src, l, coverage);
- op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
+ if (op.destStore64)
+ op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
x += l;
sx += l;
length -= l;
@@ -4320,8 +4869,8 @@ static void blend_tiled_generic(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
- uint buffer[buffer_size];
- uint src_buffer[buffer_size];
+ uint buffer[BufferSize];
+ uint src_buffer[BufferSize];
Operator op = getOperator(data, spans, count);
const int image_width = data->texture.width;
@@ -4347,10 +4896,10 @@ static void blend_tiled_generic(int count, const QSpan *spans, void *userData)
const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
while (length) {
int l = qMin(image_width - sx, length);
- if (buffer_size < l)
- l = buffer_size;
+ if (BufferSize < l)
+ l = BufferSize;
const uint *src = op.srcFetch(src_buffer, &op, data, sy, sx, l);
- uint *dest = op.destFetch ? op.destFetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer;
+ uint *dest = op.destFetch(buffer, data->rasterBuffer, x, spans->y, l);
op.func(dest, src, l, coverage);
if (op.destStore)
op.destStore(data->rasterBuffer, x, spans->y, dest, l);
@@ -4373,8 +4922,8 @@ static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userD
qCDebug(lcQtGuiDrawHelper, "blend_tiled_generic_rgb64: unsupported 64-bit blend attempted, falling back to 32-bit");
return blend_tiled_generic(count, spans, userData);
}
- quint64 buffer[buffer_size];
- quint64 src_buffer[buffer_size];
+ quint64 buffer[BufferSize];
+ quint64 src_buffer[BufferSize];
const int image_width = data->texture.width;
const int image_height = data->texture.height;
@@ -4386,6 +4935,50 @@ static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userD
if (yoff < 0)
yoff += image_height;
+ bool isBpp32 = qPixelLayouts[data->rasterBuffer->format].bpp == QPixelLayout::BPP32;
+ if (op.destFetch64 == destFetch64Undefined && image_width <= BufferSize && isBpp32) {
+ // If destination isn't blended into the result, we can do the tiling directly on destination pixels.
+ while (count--) {
+ int x = spans->x;
+ int y = spans->y;
+ int length = spans->len;
+ int sx = (xoff + spans->x) % image_width;
+ int sy = (spans->y + yoff) % image_height;
+ if (sx < 0)
+ sx += image_width;
+ if (sy < 0)
+ sy += image_height;
+
+ int sl = qMin(image_width, length);
+ if (sx > 0 && sl > 0) {
+ int l = qMin(image_width - sx, sl);
+ const QRgba64 *src = op.srcFetch64((QRgba64 *)src_buffer, &op, data, sy, sx, l);
+ op.destStore64(data->rasterBuffer, x, y, src, l);
+ x += l;
+ sx += l;
+ sl -= l;
+ if (sx >= image_width)
+ sx = 0;
+ }
+ if (sl > 0) {
+ Q_ASSERT(sx == 0);
+ const QRgba64 *src = op.srcFetch64((QRgba64 *)src_buffer, &op, data, sy, sx, sl);
+ op.destStore64(data->rasterBuffer, x, y, src, sl);
+ x += sl;
+ sx += sl;
+ sl -= sl;
+ if (sx >= image_width)
+ sx = 0;
+ }
+ uint *dest = (uint*)data->rasterBuffer->scanLine(y) + x - image_width;
+ for (int i = image_width; i < length; ++i) {
+ dest[i] = dest[i - image_width];
+ }
+ ++spans;
+ }
+ return;
+ }
+
while (count--) {
int x = spans->x;
int length = spans->len;
@@ -4399,12 +4992,13 @@ static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userD
const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
while (length) {
int l = qMin(image_width - sx, length);
- if (buffer_size < l)
- l = buffer_size;
+ if (BufferSize < l)
+ l = BufferSize;
const QRgba64 *src = op.srcFetch64((QRgba64 *)src_buffer, &op, data, sy, sx, l);
QRgba64 *dest = op.destFetch64((QRgba64 *)buffer, data->rasterBuffer, x, spans->y, l);
op.func64(dest, src, l, coverage);
- op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
+ if (op.destStore64)
+ op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
x += l;
sx += l;
length -= l;
@@ -4449,8 +5043,8 @@ static void blend_tiled_argb(int count, const QSpan *spans, void *userData)
const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
while (length) {
int l = qMin(image_width - sx, length);
- if (buffer_size < l)
- l = buffer_size;
+ if (BufferSize < l)
+ l = BufferSize;
const uint *src = (const uint *)data->texture.scanLine(sy) + sx;
uint *dest = ((uint *)data->rasterBuffer->scanLine(spans->y)) + x;
op.func(dest, src, l, coverage);
@@ -4509,8 +5103,8 @@ static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData)
int tx = x;
while (length) {
int l = qMin(image_width - sx, length);
- if (buffer_size < l)
- l = buffer_size;
+ if (BufferSize < l)
+ l = BufferSize;
quint16 *dest = ((quint16 *)data->rasterBuffer->scanLine(spans->y)) + tx;
const quint16 *src = (const quint16 *)data->texture.scanLine(sy) + sx;
memcpy(dest, src, l * sizeof(quint16));
@@ -4545,8 +5139,8 @@ static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData)
if (alpha > 0) {
while (length) {
int l = qMin(image_width - sx, length);
- if (buffer_size < l)
- l = buffer_size;
+ if (BufferSize < l)
+ l = BufferSize;
quint16 *dest = ((quint16 *)data->rasterBuffer->scanLine(spans->y)) + x;
const quint16 *src = (const quint16 *)data->texture.scanLine(sy) + sx;
blend_sourceOver_rgb16_rgb16(dest, src, l, alpha, ialpha);
@@ -4562,723 +5156,12 @@ static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData)
}
}
-static void blend_transformed_bilinear_rgb565(int count, const QSpan *spans, void *userData)
-{
- QSpanData *data = reinterpret_cast<QSpanData*>(userData);
- QPainter::CompositionMode mode = data->rasterBuffer->compositionMode;
-
- if (data->texture.format != QImage::Format_RGB16
- || (mode != QPainter::CompositionMode_SourceOver
- && mode != QPainter::CompositionMode_Source))
- {
- blend_src_generic(count, spans, userData);
- return;
- }
-
- quint16 buffer[buffer_size];
-
- const int src_minx = data->texture.x1;
- const int src_miny = data->texture.y1;
- const int src_maxx = data->texture.x2 - 1;
- const int src_maxy = data->texture.y2 - 1;
-
- if (data->fast_matrix) {
- // The increment pr x in the scanline
- const int fdx = (int)(data->m11 * fixed_scale);
- const int fdy = (int)(data->m12 * fixed_scale);
-
- while (count--) {
- const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8;
- const quint8 alpha = (coverage + 1) >> 3;
- const quint8 ialpha = 0x20 - alpha;
- if (alpha == 0) {
- ++spans;
- continue;
- }
-
- quint16 *dest = (quint16 *)data->rasterBuffer->scanLine(spans->y) + spans->x;
- const qreal cx = spans->x + qreal(0.5);
- const qreal cy = spans->y + qreal(0.5);
- int x = int((data->m21 * cy
- + data->m11 * cx + data->dx) * fixed_scale) - half_point;
- int y = int((data->m22 * cy
- + data->m12 * cx + data->dy) * fixed_scale) - half_point;
- int length = spans->len;
-
- while (length) {
- int l;
- quint16 *b;
- if (ialpha == 0) {
- l = length;
- b = dest;
- } else {
- l = qMin(length, buffer_size);
- b = buffer;
- }
- const quint16 *end = b + l;
-
- while (b < end) {
- int x1 = (x >> 16);
- int x2;
- int y1 = (y >> 16);
- int y2;
-
- fetchTransformedBilinear_pixelBounds<BlendTransformedBilinear>(0, src_minx, src_maxx, x1, x2);
- fetchTransformedBilinear_pixelBounds<BlendTransformedBilinear>(0, src_miny, src_maxy, y1, y2);
-
- const quint16 *src1 = (const quint16*)data->texture.scanLine(y1);
- const quint16 *src2 = (const quint16*)data->texture.scanLine(y2);
- quint16 tl = src1[x1];
- const quint16 tr = src1[x2];
- quint16 bl = src2[x1];
- const quint16 br = src2[x2];
-
- const uint distxsl8 = x & 0xff00;
- const uint distysl8 = y & 0xff00;
- const uint distx = distxsl8 >> 8;
- const uint disty = distysl8 >> 8;
- const uint distxy = distx * disty;
-
- const uint tlw = 0x10000 - distxsl8 - distysl8 + distxy; // (256 - distx) * (256 - disty)
- const uint trw = distxsl8 - distxy; // distx * (256 - disty)
- const uint blw = distysl8 - distxy; // (256 - distx) * disty
- const uint brw = distxy; // distx * disty
- uint red = ((tl & 0xf800) * tlw + (tr & 0xf800) * trw
- + (bl & 0xf800) * blw + (br & 0xf800) * brw) & 0xf8000000;
- uint green = ((tl & 0x07e0) * tlw + (tr & 0x07e0) * trw
- + (bl & 0x07e0) * blw + (br & 0x07e0) * brw) & 0x07e00000;
- uint blue = ((tl & 0x001f) * tlw + (tr & 0x001f) * trw
- + (bl & 0x001f) * blw + (br & 0x001f) * brw);
- *b = quint16((red | green | blue) >> 16);
-
- ++b;
- x += fdx;
- y += fdy;
- }
-
- if (ialpha != 0)
- blend_sourceOver_rgb16_rgb16(dest, buffer, l, alpha, ialpha);
-
- dest += l;
- length -= l;
- }
- ++spans;
- }
- } else {
- const qreal fdx = data->m11;
- const qreal fdy = data->m12;
- const qreal fdw = data->m13;
-
- while (count--) {
- const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8;
- const quint8 alpha = (coverage + 1) >> 3;
- const quint8 ialpha = 0x20 - alpha;
- if (alpha == 0) {
- ++spans;
- continue;
- }
-
- quint16 *dest = (quint16 *)data->rasterBuffer->scanLine(spans->y) + spans->x;
-
- const qreal cx = spans->x + qreal(0.5);
- const qreal cy = spans->y + qreal(0.5);
-
- qreal x = data->m21 * cy + data->m11 * cx + data->dx;
- qreal y = data->m22 * cy + data->m12 * cx + data->dy;
- qreal w = data->m23 * cy + data->m13 * cx + data->m33;
-
- int length = spans->len;
- while (length) {
- int l;
- quint16 *b;
- if (ialpha == 0) {
- l = length;
- b = dest;
- } else {
- l = qMin(length, buffer_size);
- b = buffer;
- }
- const quint16 *end = b + l;
-
- while (b < end) {
- const qreal iw = w == 0 ? 1 : 1 / w;
- const qreal px = x * iw - qreal(0.5);
- const qreal py = y * iw - qreal(0.5);
-
- int x1 = int(px) - (px < 0);
- int x2;
- int y1 = int(py) - (py < 0);
- int y2;
-
- fetchTransformedBilinear_pixelBounds<BlendTransformedBilinear>(0, src_minx, src_maxx, x1, x2);
- fetchTransformedBilinear_pixelBounds<BlendTransformedBilinear>(0, src_miny, src_maxy, y1, y2);
-
- const quint16 *src1 = (const quint16 *)data->texture.scanLine(y1);
- const quint16 *src2 = (const quint16 *)data->texture.scanLine(y2);
- quint16 tl = src1[x1];
- const quint16 tr = src1[x2];
- quint16 bl = src2[x1];
- const quint16 br = src2[x2];
-
- const uint distx = uint((px - x1) * 256);
- const uint disty = uint((py - y1) * 256);
- const uint distxsl8 = distx << 8;
- const uint distysl8 = disty << 8;
- const uint distxy = distx * disty;
-
- const uint tlw = 0x10000 - distxsl8 - distysl8 + distxy; // (256 - distx) * (256 - disty)
- const uint trw = distxsl8 - distxy; // distx * (256 - disty)
- const uint blw = distysl8 - distxy; // (256 - distx) * disty
- const uint brw = distxy; // distx * disty
- uint red = ((tl & 0xf800) * tlw + (tr & 0xf800) * trw
- + (bl & 0xf800) * blw + (br & 0xf800) * brw) & 0xf8000000;
- uint green = ((tl & 0x07e0) * tlw + (tr & 0x07e0) * trw
- + (bl & 0x07e0) * blw + (br & 0x07e0) * brw) & 0x07e00000;
- uint blue = ((tl & 0x001f) * tlw + (tr & 0x001f) * trw
- + (bl & 0x001f) * blw + (br & 0x001f) * brw);
- *b = quint16((red | green | blue) >> 16);
-
- ++b;
- x += fdx;
- y += fdy;
- w += fdw;
- }
-
- if (ialpha != 0)
- blend_sourceOver_rgb16_rgb16(dest, buffer, l, alpha, ialpha);
-
- dest += l;
- length -= l;
- }
- ++spans;
- }
- }
-}
-
-static void blend_transformed_argb(int count, const QSpan *spans, void *userData)
-{
- QSpanData *data = reinterpret_cast<QSpanData *>(userData);
- if (data->texture.format != QImage::Format_ARGB32_Premultiplied
- && data->texture.format != QImage::Format_RGB32) {
- blend_src_generic(count, spans, userData);
- return;
- }
-
- CompositionFunction func = functionForMode[data->rasterBuffer->compositionMode];
- uint buffer[buffer_size];
- quint32 mask = (data->texture.format == QImage::Format_RGB32) ? 0xff000000 : 0;
-
- const int image_x1 = data->texture.x1;
- const int image_y1 = data->texture.y1;
- const int image_x2 = data->texture.x2 - 1;
- const int image_y2 = data->texture.y2 - 1;
-
- if (data->fast_matrix) {
- // The increment pr x in the scanline
- int fdx = (int)(data->m11 * fixed_scale);
- int fdy = (int)(data->m12 * fixed_scale);
-
- while (count--) {
- void *t = data->rasterBuffer->scanLine(spans->y);
-
- uint *target = ((uint *)t) + spans->x;
-
- const qreal cx = spans->x + qreal(0.5);
- const qreal cy = spans->y + qreal(0.5);
-
- int x = int((data->m21 * cy
- + data->m11 * cx + data->dx) * fixed_scale);
- int y = int((data->m22 * cy
- + data->m12 * cx + data->dy) * fixed_scale);
-
- int length = spans->len;
- const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
- while (length) {
- int l = qMin(length, buffer_size);
- const uint *end = buffer + l;
- uint *b = buffer;
- while (b < end) {
- int px = qBound(image_x1, x >> 16, image_x2);
- int py = qBound(image_y1, y >> 16, image_y2);
- *b = reinterpret_cast<const uint *>(data->texture.scanLine(py))[px] | mask;
-
- x += fdx;
- y += fdy;
- ++b;
- }
- func(target, buffer, l, coverage);
- target += l;
- length -= l;
- }
- ++spans;
- }
- } else {
- const qreal fdx = data->m11;
- const qreal fdy = data->m12;
- const qreal fdw = data->m13;
- while (count--) {
- void *t = data->rasterBuffer->scanLine(spans->y);
-
- uint *target = ((uint *)t) + spans->x;
-
- const qreal cx = spans->x + qreal(0.5);
- const qreal cy = spans->y + qreal(0.5);
-
- qreal x = data->m21 * cy + data->m11 * cx + data->dx;
- qreal y = data->m22 * cy + data->m12 * cx + data->dy;
- qreal w = data->m23 * cy + data->m13 * cx + data->m33;
-
- int length = spans->len;
- const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
- while (length) {
- int l = qMin(length, buffer_size);
- const uint *end = buffer + l;
- uint *b = buffer;
- while (b < end) {
- const qreal iw = w == 0 ? 1 : 1 / w;
- const qreal tx = x * iw;
- const qreal ty = y * iw;
- const int px = qBound(image_x1, int(tx) - (tx < 0), image_x2);
- const int py = qBound(image_y1, int(ty) - (ty < 0), image_y2);
-
- *b = reinterpret_cast<const uint *>(data->texture.scanLine(py))[px] | mask;
- x += fdx;
- y += fdy;
- w += fdw;
-
- ++b;
- }
- func(target, buffer, l, coverage);
- target += l;
- length -= l;
- }
- ++spans;
- }
- }
-}
-
-static void blend_transformed_rgb565(int count, const QSpan *spans, void *userData)
-{
- QSpanData *data = reinterpret_cast<QSpanData*>(userData);
- QPainter::CompositionMode mode = data->rasterBuffer->compositionMode;
-
- if (data->texture.format != QImage::Format_RGB16
- || (mode != QPainter::CompositionMode_SourceOver
- && mode != QPainter::CompositionMode_Source))
- {
- blend_src_generic(count, spans, userData);
- return;
- }
-
- quint16 buffer[buffer_size];
- const int image_x1 = data->texture.x1;
- const int image_y1 = data->texture.y1;
- const int image_x2 = data->texture.x2 - 1;
- const int image_y2 = data->texture.y2 - 1;
-
- if (data->fast_matrix) {
- // The increment pr x in the scanline
- const int fdx = (int)(data->m11 * fixed_scale);
- const int fdy = (int)(data->m12 * fixed_scale);
-
- while (count--) {
- const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8;
- const quint8 alpha = (coverage + 1) >> 3;
- const quint8 ialpha = 0x20 - alpha;
- if (alpha == 0) {
- ++spans;
- continue;
- }
-
- quint16 *dest = (quint16 *)data->rasterBuffer->scanLine(spans->y) + spans->x;
- const qreal cx = spans->x + qreal(0.5);
- const qreal cy = spans->y + qreal(0.5);
- int x = int((data->m21 * cy
- + data->m11 * cx + data->dx) * fixed_scale);
- int y = int((data->m22 * cy
- + data->m12 * cx + data->dy) * fixed_scale);
- int length = spans->len;
-
- while (length) {
- int l;
- quint16 *b;
- if (ialpha == 0) {
- l = length;
- b = dest;
- } else {
- l = qMin(length, buffer_size);
- b = buffer;
- }
- const quint16 *end = b + l;
-
- while (b < end) {
- const int px = qBound(image_x1, x >> 16, image_x2);
- const int py = qBound(image_y1, y >> 16, image_y2);
-
- *b = ((const quint16 *)data->texture.scanLine(py))[px];
- ++b;
-
- x += fdx;
- y += fdy;
- }
-
- if (ialpha != 0)
- blend_sourceOver_rgb16_rgb16(dest, buffer, l, alpha, ialpha);
-
- dest += l;
- length -= l;
- }
- ++spans;
- }
- } else {
- const qreal fdx = data->m11;
- const qreal fdy = data->m12;
- const qreal fdw = data->m13;
-
- while (count--) {
- const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8;
- const quint8 alpha = (coverage + 1) >> 3;
- const quint8 ialpha = 0x20 - alpha;
- if (alpha == 0) {
- ++spans;
- continue;
- }
-
- quint16 *dest = (quint16 *)data->rasterBuffer->scanLine(spans->y) + spans->x;
-
- const qreal cx = spans->x + qreal(0.5);
- const qreal cy = spans->y + qreal(0.5);
-
- qreal x = data->m21 * cy + data->m11 * cx + data->dx;
- qreal y = data->m22 * cy + data->m12 * cx + data->dy;
- qreal w = data->m23 * cy + data->m13 * cx + data->m33;
-
- int length = spans->len;
- while (length) {
- int l;
- quint16 *b;
- if (ialpha == 0) {
- l = length;
- b = dest;
- } else {
- l = qMin(length, buffer_size);
- b = buffer;
- }
- const quint16 *end = b + l;
-
- while (b < end) {
- const qreal iw = w == 0 ? 1 : 1 / w;
- const qreal tx = x * iw;
- const qreal ty = y * iw;
-
- const int px = qBound(image_x1, int(tx) - (tx < 0), image_x2);
- const int py = qBound(image_y1, int(ty) - (ty < 0), image_y2);
-
- *b = ((const quint16 *)data->texture.scanLine(py))[px];
- ++b;
-
- x += fdx;
- y += fdy;
- w += fdw;
- }
-
- if (ialpha != 0)
- blend_sourceOver_rgb16_rgb16(dest, buffer, l, alpha, ialpha);
-
- dest += l;
- length -= l;
- }
- ++spans;
- }
- }
-}
-
-static void blend_transformed_tiled_argb(int count, const QSpan *spans, void *userData)
-{
- QSpanData *data = reinterpret_cast<QSpanData *>(userData);
- if (data->texture.format != QImage::Format_ARGB32_Premultiplied
- && data->texture.format != QImage::Format_RGB32) {
- blend_src_generic(count, spans, userData);
- return;
- }
-
- CompositionFunction func = functionForMode[data->rasterBuffer->compositionMode];
- uint buffer[buffer_size];
-
- int image_width = data->texture.width;
- int image_height = data->texture.height;
- const qsizetype scanline_offset = data->texture.bytesPerLine / 4;
-
- if (data->fast_matrix) {
- // The increment pr x in the scanline
- int fdx = (int)(data->m11 * fixed_scale);
- int fdy = (int)(data->m12 * fixed_scale);
-
- while (count--) {
- void *t = data->rasterBuffer->scanLine(spans->y);
-
- uint *target = ((uint *)t) + spans->x;
- const uint *image_bits = (const uint *)data->texture.imageData;
-
- const qreal cx = spans->x + qreal(0.5);
- const qreal cy = spans->y + qreal(0.5);
-
- int x = int((data->m21 * cy
- + data->m11 * cx + data->dx) * fixed_scale);
- int y = int((data->m22 * cy
- + data->m12 * cx + data->dy) * fixed_scale);
-
- const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
- int length = spans->len;
- while (length) {
- int l = qMin(length, buffer_size);
- const uint *end = buffer + l;
- uint *b = buffer;
- int px16 = x % (image_width << 16);
- int py16 = y % (image_height << 16);
- int px_delta = fdx % (image_width << 16);
- int py_delta = fdy % (image_height << 16);
- while (b < end) {
- if (px16 < 0) px16 += image_width << 16;
- if (py16 < 0) py16 += image_height << 16;
- int px = px16 >> 16;
- int py = py16 >> 16;
- int y_offset = py * scanline_offset;
-
- Q_ASSERT(px >= 0 && px < image_width);
- Q_ASSERT(py >= 0 && py < image_height);
-
- *b = image_bits[y_offset + px];
- x += fdx;
- y += fdy;
- px16 += px_delta;
- if (px16 >= image_width << 16)
- px16 -= image_width << 16;
- py16 += py_delta;
- if (py16 >= image_height << 16)
- py16 -= image_height << 16;
- ++b;
- }
- func(target, buffer, l, coverage);
- target += l;
- length -= l;
- }
- ++spans;
- }
- } else {
- const qreal fdx = data->m11;
- const qreal fdy = data->m12;
- const qreal fdw = data->m13;
- while (count--) {
- void *t = data->rasterBuffer->scanLine(spans->y);
-
- uint *target = ((uint *)t) + spans->x;
- const uint *image_bits = (const uint *)data->texture.imageData;
-
- const qreal cx = spans->x + qreal(0.5);
- const qreal cy = spans->y + qreal(0.5);
-
- qreal x = data->m21 * cy + data->m11 * cx + data->dx;
- qreal y = data->m22 * cy + data->m12 * cx + data->dy;
- qreal w = data->m23 * cy + data->m13 * cx + data->m33;
-
- const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
- int length = spans->len;
- while (length) {
- int l = qMin(length, buffer_size);
- const uint *end = buffer + l;
- uint *b = buffer;
- while (b < end) {
- const qreal iw = w == 0 ? 1 : 1 / w;
- const qreal tx = x * iw;
- const qreal ty = y * iw;
- int px = int(tx) - (tx < 0);
- int py = int(ty) - (ty < 0);
-
- px %= image_width;
- py %= image_height;
- if (px < 0) px += image_width;
- if (py < 0) py += image_height;
- int y_offset = py * scanline_offset;
-
- Q_ASSERT(px >= 0 && px < image_width);
- Q_ASSERT(py >= 0 && py < image_height);
-
- *b = image_bits[y_offset + px];
- x += fdx;
- y += fdy;
- w += fdw;
- //force increment to avoid /0
- if (!w) {
- w += fdw;
- }
- ++b;
- }
- func(target, buffer, l, coverage);
- target += l;
- length -= l;
- }
- ++spans;
- }
- }
-}
-
-static void blend_transformed_tiled_rgb565(int count, const QSpan *spans, void *userData)
-{
- QSpanData *data = reinterpret_cast<QSpanData*>(userData);
- QPainter::CompositionMode mode = data->rasterBuffer->compositionMode;
-
- if (data->texture.format != QImage::Format_RGB16
- || (mode != QPainter::CompositionMode_SourceOver
- && mode != QPainter::CompositionMode_Source))
- {
- blend_src_generic(count, spans, userData);
- return;
- }
-
- quint16 buffer[buffer_size];
- const int image_width = data->texture.width;
- const int image_height = data->texture.height;
-
- if (data->fast_matrix) {
- // The increment pr x in the scanline
- const int fdx = (int)(data->m11 * fixed_scale);
- const int fdy = (int)(data->m12 * fixed_scale);
-
- while (count--) {
- const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8;
- const quint8 alpha = (coverage + 1) >> 3;
- const quint8 ialpha = 0x20 - alpha;
- if (alpha == 0) {
- ++spans;
- continue;
- }
-
- quint16 *dest = (quint16 *)data->rasterBuffer->scanLine(spans->y) + spans->x;
- const qreal cx = spans->x + qreal(0.5);
- const qreal cy = spans->y + qreal(0.5);
- int x = int((data->m21 * cy
- + data->m11 * cx + data->dx) * fixed_scale);
- int y = int((data->m22 * cy
- + data->m12 * cx + data->dy) * fixed_scale);
- int length = spans->len;
-
- while (length) {
- int l;
- quint16 *b;
- if (ialpha == 0) {
- l = length;
- b = dest;
- } else {
- l = qMin(length, buffer_size);
- b = buffer;
- }
- const quint16 *end = b + l;
-
- while (b < end) {
- int px = (x >> 16) % image_width;
- int py = (y >> 16) % image_height;
-
- if (px < 0)
- px += image_width;
- if (py < 0)
- py += image_height;
-
- *b = ((const quint16 *)data->texture.scanLine(py))[px];
- ++b;
-
- x += fdx;
- y += fdy;
- }
-
- if (ialpha != 0)
- blend_sourceOver_rgb16_rgb16(dest, buffer, l, alpha, ialpha);
-
- dest += l;
- length -= l;
- }
- ++spans;
- }
- } else {
- const qreal fdx = data->m11;
- const qreal fdy = data->m12;
- const qreal fdw = data->m13;
-
- while (count--) {
- const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8;
- const quint8 alpha = (coverage + 1) >> 3;
- const quint8 ialpha = 0x20 - alpha;
- if (alpha == 0) {
- ++spans;
- continue;
- }
-
- quint16 *dest = (quint16 *)data->rasterBuffer->scanLine(spans->y) + spans->x;
-
- const qreal cx = spans->x + qreal(0.5);
- const qreal cy = spans->y + qreal(0.5);
-
- qreal x = data->m21 * cy + data->m11 * cx + data->dx;
- qreal y = data->m22 * cy + data->m12 * cx + data->dy;
- qreal w = data->m23 * cy + data->m13 * cx + data->m33;
-
- int length = spans->len;
- while (length) {
- int l;
- quint16 *b;
- if (ialpha == 0) {
- l = length;
- b = dest;
- } else {
- l = qMin(length, buffer_size);
- b = buffer;
- }
- const quint16 *end = b + l;
-
- while (b < end) {
- const qreal iw = w == 0 ? 1 : 1 / w;
- const qreal tx = x * iw;
- const qreal ty = y * iw;
-
- int px = int(tx) - (tx < 0);
- int py = int(ty) - (ty < 0);
-
- px %= image_width;
- py %= image_height;
- if (px < 0)
- px += image_width;
- if (py < 0)
- py += image_height;
-
- *b = ((const quint16 *)data->texture.scanLine(py))[px];
- ++b;
-
- x += fdx;
- y += fdy;
- w += fdw;
- // force increment to avoid /0
- if (!w)
- w += fdw;
- }
-
- if (ialpha != 0)
- blend_sourceOver_rgb16_rgb16(dest, buffer, l, alpha, ialpha);
-
- dest += l;
- length -= l;
- }
- ++spans;
- }
- }
-}
-
-
/* Image formats here are target formats */
static const ProcessSpans processTextureSpansARGB32PM[NBlendTypes] = {
blend_untransformed_argb, // Untransformed
blend_tiled_argb, // Tiled
- blend_transformed_argb, // Transformed
- blend_transformed_tiled_argb, // TransformedTiled
+ blend_src_generic, // Transformed
+ blend_src_generic, // TransformedTiled
blend_src_generic, // TransformedBilinear
blend_src_generic // TransformedBilinearTiled
};
@@ -5286,9 +5169,9 @@ static const ProcessSpans processTextureSpansARGB32PM[NBlendTypes] = {
static const ProcessSpans processTextureSpansRGB16[NBlendTypes] = {
blend_untransformed_rgb565, // Untransformed
blend_tiled_rgb565, // Tiled
- blend_transformed_rgb565, // Transformed
- blend_transformed_tiled_rgb565, // TransformedTiled
- blend_transformed_bilinear_rgb565, // TransformedBilinear
+ blend_src_generic, // Transformed
+ blend_src_generic, // TransformedTiled
+ blend_src_generic, // TransformedBilinear
blend_src_generic // TransformedBilinearTiled
};
@@ -5330,6 +5213,9 @@ void qBlendTexture(int count, const QSpan *spans, void *userData)
case QImage::Format_A2BGR30_Premultiplied:
case QImage::Format_RGB30:
case QImage::Format_A2RGB30_Premultiplied:
+ case QImage::Format_RGBX64:
+ case QImage::Format_RGBA64:
+ case QImage::Format_RGBA64_Premultiplied:
proc = processTextureSpansGeneric64[blendType];
break;
case QImage::Format_Invalid:
@@ -5586,7 +5472,7 @@ static void qt_alphamapblit_generic(QRasterBuffer *rasterBuffer,
srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied();
}
- quint64 buffer[buffer_size];
+ quint64 buffer[BufferSize];
const DestFetchProc64 destFetch64 = destFetchProc64[rasterBuffer->format];
const DestStoreProc64 destStore64 = destStoreProc64[rasterBuffer->format];
@@ -5595,13 +5481,14 @@ static void qt_alphamapblit_generic(QRasterBuffer *rasterBuffer,
int i = x;
int length = mapWidth;
while (length > 0) {
- int l = qMin(buffer_size, length);
+ int l = qMin(BufferSize, length);
QRgba64 *dest = destFetch64((QRgba64*)buffer, rasterBuffer, i, y + ly, l);
for (int j=0; j < l; ++j) {
const int coverage = map[j + (i - x)];
alphamapblend_generic(coverage, dest, j, srcColor, color, colorProfile);
}
- destStore64(rasterBuffer, i, y + ly, dest, l);
+ if (destStore64)
+ destStore64(rasterBuffer, i, y + ly, dest, l);
length -= l;
i += l;
}
@@ -5624,14 +5511,15 @@ static void qt_alphamapblit_generic(QRasterBuffer *rasterBuffer,
int end = qMin<int>(x + mapWidth, clip.x + clip.len);
if (end <= start)
continue;
- Q_ASSERT(end - start <= buffer_size);
+ Q_ASSERT(end - start <= BufferSize);
QRgba64 *dest = destFetch64((QRgba64*)buffer, rasterBuffer, start, clip.y, end - start);
for (int xp=start; xp<end; ++xp) {
const int coverage = map[xp - x];
alphamapblend_generic(coverage, dest, xp - start, srcColor, color, colorProfile);
}
- destStore64(rasterBuffer, start, clip.y, dest, end - start);
+ if (destStore64)
+ destStore64(rasterBuffer, start, clip.y, dest, end - start);
} // for (i -> line.count)
map += mapStride;
} // for (yp -> bottom)
@@ -5903,7 +5791,7 @@ static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer,
srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied();
}
- quint64 buffer[buffer_size];
+ quint64 buffer[BufferSize];
const DestFetchProc64 destFetch64 = destFetchProc64[rasterBuffer->format];
const DestStoreProc64 destStore64 = destStoreProc64[rasterBuffer->format];
@@ -5912,13 +5800,14 @@ static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer,
int i = x;
int length = mapWidth;
while (length > 0) {
- int l = qMin(buffer_size, length);
+ int l = qMin(BufferSize, length);
QRgba64 *dest = destFetch64((QRgba64*)buffer, rasterBuffer, i, y + ly, l);
for (int j=0; j < l; ++j) {
const uint coverage = src[j + (i - x)];
alphargbblend_generic(coverage, dest, j, srcColor, color, colorProfile);
}
- destStore64(rasterBuffer, i, y + ly, dest, l);
+ if (destStore64)
+ destStore64(rasterBuffer, i, y + ly, dest, l);
length -= l;
i += l;
}
@@ -5941,14 +5830,15 @@ static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer,
int end = qMin<int>(x + mapWidth, clip.x + clip.len);
if (end <= start)
continue;
- Q_ASSERT(end - start <= buffer_size);
+ Q_ASSERT(end - start <= BufferSize);
QRgba64 *dest = destFetch64((QRgba64*)buffer, rasterBuffer, start, clip.y, end - start);
for (int xp=start; xp<end; ++xp) {
const uint coverage = src[xp - x];
alphargbblend_generic(coverage, dest, xp - start, srcColor, color, colorProfile);
}
- destStore64(rasterBuffer, start, clip.y, dest, end - start);
+ if (destStore64)
+ destStore64(rasterBuffer, start, clip.y, dest, end - start);
} // for (i -> line.count)
src += srcStride;
} // for (yp -> bottom)
@@ -6031,8 +5921,24 @@ static void qt_rectfill_quint16(QRasterBuffer *rasterBuffer,
int x, int y, int width, int height,
const QRgba64 &color)
{
+ const QPixelLayout &layout = qPixelLayouts[rasterBuffer->format];
+ quint32 c32 = color.toArgb32();
+ quint16 c16;
+ layout.storeFromARGB32PM(reinterpret_cast<uchar *>(&c16), &c32, 0, 1, nullptr, nullptr);
qt_rectfill<quint16>(reinterpret_cast<quint16 *>(rasterBuffer->buffer()),
- color.toRgb16(), x, y, width, height, rasterBuffer->bytesPerLine());
+ c16, x, y, width, height, rasterBuffer->bytesPerLine());
+}
+
+static void qt_rectfill_quint24(QRasterBuffer *rasterBuffer,
+ int x, int y, int width, int height,
+ const QRgba64 &color)
+{
+ const QPixelLayout &layout = qPixelLayouts[rasterBuffer->format];
+ quint32 c32 = color.toArgb32();
+ quint24 c24;
+ layout.storeFromARGB32PM(reinterpret_cast<uchar *>(&c24), &c32, 0, 1, nullptr, nullptr);
+ qt_rectfill<quint24>(reinterpret_cast<quint24 *>(rasterBuffer->buffer()),
+ c24, x, y, width, height, rasterBuffer->bytesPerLine());
}
static void qt_rectfill_nonpremul_argb32(QRasterBuffer *rasterBuffer,
@@ -6084,6 +5990,17 @@ static void qt_rectfill_gray(QRasterBuffer *rasterBuffer,
qGray(color.toArgb32()), x, y, width, height, rasterBuffer->bytesPerLine());
}
+static void qt_rectfill_quint64(QRasterBuffer *rasterBuffer,
+ int x, int y, int width, int height,
+ const QRgba64 &color)
+{
+ const auto store = qStoreFromRGBA64PM[rasterBuffer->format];
+ quint64 c64;
+ store(reinterpret_cast<uchar *>(&c64), &color, 0, 1, nullptr, nullptr);
+ qt_rectfill<quint64>(reinterpret_cast<quint64 *>(rasterBuffer->buffer()),
+ c64, x, y, width, height, rasterBuffer->bytesPerLine());
+}
+
// Map table for destination image format. Contains function pointers
// for blends of various types unto the destination
@@ -6152,7 +6069,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
- 0
+ qt_rectfill_quint24
},
// Format_RGB666
{
@@ -6161,7 +6078,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
- 0
+ qt_rectfill_quint24
},
// Format_ARGB6666_Premultiplied
{
@@ -6170,7 +6087,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
- 0
+ qt_rectfill_quint24
},
// Format_RGB555
{
@@ -6179,7 +6096,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
- 0
+ qt_rectfill_quint16
},
// Format_ARGB8555_Premultiplied
{
@@ -6188,7 +6105,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
- 0
+ qt_rectfill_quint24
},
// Format_RGB888
{
@@ -6197,7 +6114,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
- 0
+ qt_rectfill_quint24
},
// Format_RGB444
{
@@ -6206,7 +6123,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
- 0
+ qt_rectfill_quint16
},
// Format_ARGB4444_Premultiplied
{
@@ -6215,7 +6132,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
- 0
+ qt_rectfill_quint16
},
// Format_RGBX8888
{
@@ -6298,6 +6215,33 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
qt_alphargbblit_generic,
qt_rectfill_gray
},
+ // Format_RGBX64
+ {
+ blend_color_generic_rgb64,
+ blend_src_generic_rgb64,
+ 0,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
+ qt_rectfill_quint64
+ },
+ // Format_RGBA64
+ {
+ blend_color_generic_rgb64,
+ blend_src_generic_rgb64,
+ 0,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
+ qt_rectfill_quint64
+ },
+ // Format_RGBA64_Premultiplied
+ {
+ blend_color_generic_rgb64,
+ blend_src_generic_rgb64,
+ 0,
+ qt_alphamapblit_generic,
+ qt_alphargbblit_generic,
+ qt_rectfill_quint64
+ },
};
#if defined(Q_CC_MSVC) && !defined(_MIPS_)
@@ -6370,7 +6314,7 @@ void qt_memfill32(quint32 *dest, quint32 color, int count)
#endif
#ifdef QT_COMPILER_SUPPORTS_SSE4_1
-template<QtPixelOrder> const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM_sse4(uint *buffer, const uint *src, int count, const QVector<QRgb> *, QDitherInfo *);
+template<QtPixelOrder> void QT_FASTCALL storeA2RGB30PMFromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count, const QVector<QRgb> *, QDitherInfo *);
#endif
extern void qInitBlendFunctions();
@@ -6439,42 +6383,54 @@ static void qInitDrawhelperFunctions()
int w, int h,
int const_alpha);
- extern void QT_FASTCALL storePixelsBPP24_ssse3(uchar *dest, const uint *src, int index, int count);
extern const uint * QT_FASTCALL qt_fetchUntransformed_888_ssse3(uint *buffer, const Operator *, const QSpanData *data,
int y, int x, int length);
qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_ssse3;
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_ssse3;
qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_ssse3;
qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_ssse3;
- qStorePixels[QPixelLayout::BPP24] = storePixelsBPP24_ssse3;
sourceFetchUntransformed[QImage::Format_RGB888] = qt_fetchUntransformed_888_ssse3;
}
#endif // SSSE3
#if defined(QT_COMPILER_SUPPORTS_SSE4_1)
if (qCpuHasFeature(SSE4_1)) {
- extern const uint *QT_FASTCALL convertARGB32ToARGB32PM_sse4(uint *buffer, const uint *src, int count,
+ extern void QT_FASTCALL convertARGB32ToARGB32PM_sse4(uint *buffer, int count, const QVector<QRgb> *);
+ extern void QT_FASTCALL convertRGBA8888ToARGB32PM_sse4(uint *buffer, int count, const QVector<QRgb> *);
+ extern const uint *QT_FASTCALL fetchARGB32ToARGB32PM_sse4(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern const uint *QT_FASTCALL fetchRGBA8888ToARGB32PM_sse4(uint *buffer, const uchar *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *);
- extern const uint *QT_FASTCALL convertRGBA8888ToARGB32PM_sse4(uint *buffer, const uint *src, int count,
+ extern void QT_FASTCALL storeARGB32FromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *);
- extern const uint *QT_FASTCALL convertARGB32FromARGB32PM_sse4(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *);
- extern const uint *QT_FASTCALL convertRGBA8888FromARGB32PM_sse4(uint *buffer, const uint *src, int count,
+ extern void QT_FASTCALL storeRGBA8888FromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *);
- extern const uint *QT_FASTCALL convertRGBXFromARGB32PM_sse4(uint *buffer, const uint *src, int count,
+ extern void QT_FASTCALL storeRGBXFromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *);
+ extern void QT_FASTCALL storeARGB32FromRGBA64PM_sse4(uchar *dest, const QRgba64 *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern void QT_FASTCALL storeRGBA8888FromRGBA64PM_sse4(uchar *dest, const QRgba64 *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern void QT_FASTCALL destStore64ARGB32_sse4(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length);
+ extern void QT_FASTCALL destStore64RGBA8888_sse4(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length);
+ qPixelLayouts[QImage::Format_ARGB32].fetchToARGB32PM = fetchARGB32ToARGB32PM_sse4;
qPixelLayouts[QImage::Format_ARGB32].convertToARGB32PM = convertARGB32ToARGB32PM_sse4;
+ qPixelLayouts[QImage::Format_RGBA8888].fetchToARGB32PM = fetchRGBA8888ToARGB32PM_sse4;
qPixelLayouts[QImage::Format_RGBA8888].convertToARGB32PM = convertRGBA8888ToARGB32PM_sse4;
- qPixelLayouts[QImage::Format_ARGB32].convertFromARGB32PM = convertARGB32FromARGB32PM_sse4;
- qPixelLayouts[QImage::Format_RGBA8888].convertFromARGB32PM = convertRGBA8888FromARGB32PM_sse4;
- qPixelLayouts[QImage::Format_RGBX8888].convertFromARGB32PM = convertRGBXFromARGB32PM_sse4;
- qPixelLayouts[QImage::Format_A2BGR30_Premultiplied].convertFromARGB32PM = convertA2RGB30PMFromARGB32PM_sse4<PixelOrderBGR>;
- qPixelLayouts[QImage::Format_A2RGB30_Premultiplied].convertFromARGB32PM = convertA2RGB30PMFromARGB32PM_sse4<PixelOrderRGB>;
+ qPixelLayouts[QImage::Format_ARGB32].storeFromARGB32PM = storeARGB32FromARGB32PM_sse4;
+ qPixelLayouts[QImage::Format_RGBA8888].storeFromARGB32PM = storeRGBA8888FromARGB32PM_sse4;
+ qPixelLayouts[QImage::Format_RGBX8888].storeFromARGB32PM = storeRGBXFromARGB32PM_sse4;
+ qPixelLayouts[QImage::Format_A2BGR30_Premultiplied].storeFromARGB32PM = storeA2RGB30PMFromARGB32PM_sse4<PixelOrderBGR>;
+ qPixelLayouts[QImage::Format_A2RGB30_Premultiplied].storeFromARGB32PM = storeA2RGB30PMFromARGB32PM_sse4<PixelOrderRGB>;
+ qStoreFromRGBA64PM[QImage::Format_ARGB32] = storeARGB32FromRGBA64PM_sse4;
+ qStoreFromRGBA64PM[QImage::Format_RGBA8888] = storeRGBA8888FromRGBA64PM_sse4;
+ destStoreProc64[QImage::Format_ARGB32] = destStore64ARGB32_sse4;
+ destStoreProc64[QImage::Format_RGBA8888] = destStore64RGBA8888_sse4;
}
#endif
#if defined(QT_COMPILER_SUPPORTS_AVX2)
- if (qCpuHasFeature(AVX2)) {
+ if (qCpuHasFeature(ArchHaswell)) {
extern void qt_blend_rgb32_on_rgb32_avx2(uchar *destPixels, int dbpl,
const uchar *srcPixels, int sbpl,
int w, int h, int const_alpha);
@@ -6504,14 +6460,14 @@ static void qInitDrawhelperFunctions()
qt_functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_avx2;
qt_functionForModeSolid64_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_rgb64_avx2;
- extern void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_upscale_helper_avx2(uint *b, uint *end, const QTextureData &image,
- int &fx, int &fy, int fdx, int /*fdy*/);
+ extern void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_scale_helper_avx2(uint *b, uint *end, const QTextureData &image,
+ int &fx, int &fy, int fdx, int /*fdy*/);
extern void QT_FASTCALL fetchTransformedBilinearARGB32PM_downscale_helper_avx2(uint *b, uint *end, const QTextureData &image,
int &fx, int &fy, int fdx, int /*fdy*/);
extern void QT_FASTCALL fetchTransformedBilinearARGB32PM_fast_rotate_helper_avx2(uint *b, uint *end, const QTextureData &image,
int &fx, int &fy, int fdx, int fdy);
- bilinearFastTransformHelperARGB32PM[0][SimpleUpscaleTransform] = fetchTransformedBilinearARGB32PM_simple_upscale_helper_avx2;
+ bilinearFastTransformHelperARGB32PM[0][SimpleScaleTransform] = fetchTransformedBilinearARGB32PM_simple_scale_helper_avx2;
bilinearFastTransformHelperARGB32PM[0][DownscaleTransform] = fetchTransformedBilinearARGB32PM_downscale_helper_avx2;
bilinearFastTransformHelperARGB32PM[0][FastRotateTransform] = fetchTransformedBilinearARGB32PM_fast_rotate_helper_avx2;
}
@@ -6543,12 +6499,25 @@ static void qInitDrawhelperFunctions()
sourceFetchUntransformed[QImage::Format_RGB888] = qt_fetchUntransformed_888_neon;
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- extern const uint *QT_FASTCALL convertARGB32ToARGB32PM_neon(uint *buffer, const uint *src, int count,
+ extern void QT_FASTCALL convertARGB32ToARGB32PM_neon(uint *buffer, int count, const QVector<QRgb> *);
+ extern void QT_FASTCALL convertRGBA8888ToARGB32PM_neon(uint *buffer, int count, const QVector<QRgb> *);
+ extern const uint *QT_FASTCALL fetchARGB32ToARGB32PM_neon(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern const uint *QT_FASTCALL fetchRGBA8888ToARGB32PM_neon(uint *buffer, const uchar *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *);
- extern const uint *QT_FASTCALL convertRGBA8888ToARGB32PM_neon(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *);
+ extern void QT_FASTCALL storeARGB32FromARGB32PM_neon(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern void QT_FASTCALL storeRGBA8888FromARGB32PM_neon(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern void QT_FASTCALL storeRGBXFromARGB32PM_neon(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ qPixelLayouts[QImage::Format_ARGB32].fetchToARGB32PM = fetchARGB32ToARGB32PM_neon;
qPixelLayouts[QImage::Format_ARGB32].convertToARGB32PM = convertARGB32ToARGB32PM_neon;
+ qPixelLayouts[QImage::Format_ARGB32].storeFromARGB32PM = storeARGB32FromARGB32PM_neon;
+ qPixelLayouts[QImage::Format_RGBA8888].fetchToARGB32PM = fetchRGBA8888ToARGB32PM_neon;
qPixelLayouts[QImage::Format_RGBA8888].convertToARGB32PM = convertRGBA8888ToARGB32PM_neon;
+ qPixelLayouts[QImage::Format_RGBA8888].storeFromARGB32PM = storeRGBA8888FromARGB32PM_neon;
+ qPixelLayouts[QImage::Format_RGBX8888].storeFromARGB32PM = storeRGBXFromARGB32PM_neon;
#endif
#if defined(ENABLE_PIXMAN_DRAWHELPERS)
diff --git a/src/gui/painting/qdrawhelper_avx2.cpp b/src/gui/painting/qdrawhelper_avx2.cpp
index 3a70524a9d..ec6643deed 100644
--- a/src/gui/painting/qdrawhelper_avx2.cpp
+++ b/src/gui/painting/qdrawhelper_avx2.cpp
@@ -45,8 +45,6 @@
QT_BEGIN_NAMESPACE
-static Q_CONSTEXPR int BufferSize = 2048;
-
enum {
FixedScale = 1 << 16,
HalfPoint = 1 << 15
@@ -576,8 +574,10 @@ inline void fetchTransformedBilinear_pixelBounds(int, int l1, int l2, int &v1, i
Q_ASSERT(v2 >= l1 && v2 <= l2);
}
-void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_upscale_helper_avx2(uint *b, uint *end, const QTextureData &image,
- int &fx, int &fy, int fdx, int /*fdy*/)
+void QT_FASTCALL intermediate_adder_avx2(uint *b, uint *end, const IntermediateBuffer &intermediate, int offset, int &fx, int fdx);
+
+void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_scale_helper_avx2(uint *b, uint *end, const QTextureData &image,
+ int &fx, int &fy, int fdx, int /*fdy*/)
{
int y1 = (fy >> 16);
int y2;
@@ -594,16 +594,12 @@ void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_upscale_helper_avx2(uin
const int offset = (fx + adjust) >> 16;
int x = offset;
- // 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.
-
- // intermediate_buffer[0] is a buffer of red-blue component of the pixel, in the form 0x00RR00BB
- // intermediate_buffer[1] is the alpha-green component of the pixel, in the form 0x00AA00GG
- // +1 for the last pixel to interpolate with, and +1 for rounding errors.
- quint32 intermediate_buffer[2][BufferSize + 2];
+ IntermediateBuffer intermediate;
// count is the size used in the intermediate_buffer.
int count = (qint64(length) * qAbs(fdx) + FixedScale - 1) / FixedScale + 2;
- Q_ASSERT(count <= BufferSize + 2); //length is supposed to be <= buffer_size and data->m11 < 1 in this case
+ // length is supposed to be <= BufferSize either because data->m11 < 1 or
+ // data->m11 < 2, and any larger buffers split
+ Q_ASSERT(count <= BufferSize + 2);
int f = 0;
int lim = qMin(count, image.x2 - x);
if (x < image.x1) {
@@ -613,8 +609,8 @@ void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_upscale_helper_avx2(uin
quint32 rb = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff;
quint32 ag = ((((t>>8) & 0xff00ff) * idisty + ((b>>8) & 0xff00ff) * disty) >> 8) & 0xff00ff;
do {
- intermediate_buffer[0][f] = rb;
- intermediate_buffer[1][f] = ag;
+ intermediate.buffer_rb[f] = rb;
+ intermediate.buffer_ag[f] = ag;
f++;
x++;
} while (x < image.x1 && f < lim);
@@ -644,10 +640,10 @@ void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_upscale_helper_avx2(uin
// Add the values, and shift to only keep 8 significant bits per colors
__m256i rAG =_mm256_add_epi16(topAG, bottomAG);
rAG = _mm256_srli_epi16(rAG, 8);
- _mm256_storeu_si256((__m256i*)(&intermediate_buffer[1][f]), rAG);
+ _mm256_storeu_si256((__m256i*)(&intermediate.buffer_ag[f]), rAG);
__m256i rRB =_mm256_add_epi16(topRB, bottomRB);
rRB = _mm256_srli_epi16(rRB, 8);
- _mm256_storeu_si256((__m256i*)(&intermediate_buffer[0][f]), rRB);
+ _mm256_storeu_si256((__m256i*)(&intermediate.buffer_rb[f]), rRB);
}
for (; f < count; f++) { // Same as above but without simd
@@ -656,30 +652,37 @@ void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_upscale_helper_avx2(uin
uint t = s1[x];
uint b = s2[x];
- intermediate_buffer[0][f] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff;
- intermediate_buffer[1][f] = ((((t>>8) & 0xff00ff) * idisty + ((b>>8) & 0xff00ff) * disty) >> 8) & 0xff00ff;
+ intermediate.buffer_rb[f] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff;
+ intermediate.buffer_ag[f] = ((((t>>8) & 0xff00ff) * idisty + ((b>>8) & 0xff00ff) * disty) >> 8) & 0xff00ff;
x++;
}
+
// Now interpolate the values from the intermediate_buffer to get the final result.
+ intermediate_adder_avx2(b, end, intermediate, offset, fx, fdx);
+}
+
+void QT_FASTCALL intermediate_adder_avx2(uint *b, uint *end, const IntermediateBuffer &intermediate, int offset, int &fx, int fdx)
+{
fx -= offset * FixedScale;
const __m128i v_fdx = _mm_set1_epi32(fdx * 4);
const __m128i v_blend = _mm_set1_epi32(0x00800080);
+ const __m128i vdx_shuffle = _mm_set_epi8(char(0x80), 13, char(0x80), 13, char(0x80), 9, char(0x80), 9,
+ char(0x80), 5, char(0x80), 5, char(0x80), 1, char(0x80), 1);
__m128i v_fx = _mm_setr_epi32(fx, fx + fdx, fx + fdx + fdx, fx + fdx + fdx + fdx);
while (b < end - 3) {
const __m128i offset = _mm_srli_epi32(v_fx, 16);
- __m256i vrb = _mm256_i32gather_epi64((const long long *)intermediate_buffer[0], offset, 4);
- __m256i vag = _mm256_i32gather_epi64((const long long *)intermediate_buffer[1], offset, 4);
+ __m256i vrb = _mm256_i32gather_epi64((const long long *)intermediate.buffer_rb, offset, 4);
+ __m256i vag = _mm256_i32gather_epi64((const long long *)intermediate.buffer_ag, offset, 4);
- __m128i vdx = _mm_and_si128(v_fx, _mm_set1_epi32(0x0000ffff));
- vdx = _mm_srli_epi16(vdx, 8);
- __m128i vidx = _mm_sub_epi32(_mm_set1_epi32(256), vdx);
+ __m128i vdx = _mm_shuffle_epi8(v_fx, vdx_shuffle);
+ __m128i vidx = _mm_sub_epi16(_mm_set1_epi16(256), vdx);
__m256i vmulx = _mm256_castsi128_si256(_mm_unpacklo_epi32(vidx, vdx));
vmulx = _mm256_inserti128_si256(vmulx, _mm_unpackhi_epi32(vidx, vdx), 1);
- vrb = _mm256_mullo_epi32(vrb, vmulx);
- vag = _mm256_mullo_epi32(vag, vmulx);
+ vrb = _mm256_mullo_epi16(vrb, vmulx);
+ vag = _mm256_mullo_epi16(vag, vmulx);
__m256i vrbag = _mm256_hadd_epi32(vrb, vag);
vrbag = _mm256_permute4x64_epi64(vrbag, _MM_SHUFFLE(3, 1, 2, 0));
@@ -691,21 +694,21 @@ void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_upscale_helper_avx2(uin
_mm_storeu_si128((__m128i*)b, _mm_blendv_epi8(ag, rb, v_blend));
b += 4;
- fx += 4 * fdx;
v_fx = _mm_add_epi32(v_fx, v_fdx);
}
+ fx = _mm_cvtsi128_si32(v_fx);
while (b < end) {
- int x = (fx >> 16);
-
- uint distx = (fx & 0x0000ffff) >> 8;
- uint idistx = 256 - distx;
+ const int x = (fx >> 16);
- uint rb = ((intermediate_buffer[0][x] * idistx + intermediate_buffer[0][x + 1] * distx) >> 8) & 0xff00ff;
- uint ag = (intermediate_buffer[1][x] * idistx + intermediate_buffer[1][x + 1] * distx) & 0xff00ff00;
- *b = rb | ag;
+ const uint distx = (fx & 0x0000ffff) >> 8;
+ const uint idistx = 256 - distx;
+ const uint rb = (intermediate.buffer_rb[x] * idistx + intermediate.buffer_rb[x + 1] * distx) & 0xff00ff00;
+ const uint ag = (intermediate.buffer_ag[x] * idistx + intermediate.buffer_ag[x + 1] * distx) & 0xff00ff00;
+ *b = (rb >> 8) | ag;
b++;
fx += fdx;
}
+ fx += offset * FixedScale;
}
void QT_FASTCALL fetchTransformedBilinearARGB32PM_downscale_helper_avx2(uint *b, uint *end, const QTextureData &image,
diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp
index e126f4b670..629dfe2358 100644
--- a/src/gui/painting/qdrawhelper_neon.cpp
+++ b/src/gui/painting/qdrawhelper_neon.cpp
@@ -1081,15 +1081,28 @@ const uint * QT_FASTCALL qt_fetchUntransformed_888_neon(uint *buffer, const Oper
}
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
-template<bool RGBA>
-static inline void convertARGBToARGB32PM_neon(uint *buffer, const uint *src, int count)
+static inline uint32x4_t vrgba2argb(uint32x4_t srcVector)
{
- int i = 0;
#if defined(Q_PROCESSOR_ARM_64)
const uint8x16_t rgbaMask = { 2, 1, 0, 3, 6, 5, 4, 7, 10, 9, 8, 11, 14, 13, 12, 15};
#else
const uint8x8_t rgbaMask = { 2, 1, 0, 3, 6, 5, 4, 7 };
#endif
+#if defined(Q_PROCESSOR_ARM_64)
+ srcVector = vreinterpretq_u32_u8(vqtbl1q_u8(vreinterpretq_u8_u32(srcVector), rgbaMask));
+#else
+ // no vqtbl1q_u8, so use two vtbl1_u8
+ const uint8x8_t low = vtbl1_u8(vreinterpret_u8_u32(vget_low_u32(srcVector)), rgbaMask);
+ const uint8x8_t high = vtbl1_u8(vreinterpret_u8_u32(vget_high_u32(srcVector)), rgbaMask);
+ srcVector = vcombine_u32(vreinterpret_u32_u8(low), vreinterpret_u32_u8(high));
+#endif
+ return srcVector;
+}
+
+template<bool RGBA>
+static inline void convertARGBToARGB32PM_neon(uint *buffer, const uint *src, int count)
+{
+ int i = 0;
const uint8x8_t shuffleMask = { 3, 3, 3, 3, 7, 7, 7, 7};
const uint32x4_t blendMask = vdupq_n_u32(0xff000000);
@@ -1105,16 +1118,8 @@ static inline void convertARGBToARGB32PM_neon(uint *buffer, const uint *src, int
#endif
if (alphaSum) {
if (alphaSum != 255 * 4) {
- if (RGBA) {
-#if defined(Q_PROCESSOR_ARM_64)
- srcVector = vreinterpretq_u32_u8(vqtbl1q_u8(vreinterpretq_u8_u32(srcVector), rgbaMask));
-#else
- // no vqtbl1q_u8
- const uint8x8_t low = vtbl1_u8(vreinterpret_u8_u32(vget_low_u32(srcVector)), rgbaMask);
- const uint8x8_t high = vtbl1_u8(vreinterpret_u8_u32(vget_high_u32(srcVector)), rgbaMask);
- srcVector = vcombine_u32(vreinterpret_u32_u8(low), vreinterpret_u32_u8(high));
-#endif
- }
+ if (RGBA)
+ srcVector = vrgba2argb(srcVector);
const uint8x8_t s1 = vreinterpret_u8_u32(vget_low_u32(srcVector));
const uint8x8_t s2 = vreinterpret_u8_u32(vget_high_u32(srcVector));
const uint8x8_t alpha1 = vtbl1_u8(s1, shuffleMask);
@@ -1128,19 +1133,10 @@ static inline void convertARGBToARGB32PM_neon(uint *buffer, const uint *src, int
const uint32x4_t d = vbslq_u32(blendMask, srcVector, vreinterpretq_u32_u8(vcombine_u8(d1, d2)));
vst1q_u32(buffer + i, d);
} else {
- if (RGBA) {
-#if defined(Q_PROCESSOR_ARM_64)
- srcVector = vreinterpretq_u32_u8(vqtbl1q_u8(vreinterpretq_u8_u32(srcVector), rgbaMask));
-#else
- // no vqtbl1q_u8
- const uint8x8_t low = vtbl1_u8(vreinterpret_u8_u32(vget_low_u32(srcVector)), rgbaMask);
- const uint8x8_t high = vtbl1_u8(vreinterpret_u8_u32(vget_high_u32(srcVector)), rgbaMask);
- srcVector = vcombine_u32(vreinterpret_u32_u8(low), vreinterpret_u32_u8(high));
-#endif
- vst1q_u32(buffer + i, srcVector);
- } else if (buffer != src) {
+ if (RGBA)
+ vst1q_u32(buffer + i, vrgba2argb(srcVector));
+ else if (buffer != src)
vst1q_u32(buffer + i, srcVector);
- }
}
} else {
vst1q_u32(buffer + i, vdupq_n_u32(0));
@@ -1153,20 +1149,143 @@ static inline void convertARGBToARGB32PM_neon(uint *buffer, const uint *src, int
}
}
-const uint *QT_FASTCALL convertARGB32ToARGB32PM_neon(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+static inline float32x4_t reciprocal_mul_ps(float32x4_t a, float mul)
+{
+ float32x4_t ia = vrecpeq_f32(a); // estimate 1/a
+ ia = vmulq_f32(vrecpsq_f32(a, ia), vmulq_n_f32(ia, mul)); // estimate improvement step * mul
+ return ia;
+}
+
+template<bool RGBA, bool RGBx>
+static inline void convertARGBFromARGB32PM_neon(uint *buffer, const uint *src, int count)
+{
+ int i = 0;
+ const uint32x4_t alphaMask = vdupq_n_u32(0xff000000);
+
+ for (; i < count - 3; i += 4) {
+ uint32x4_t srcVector = vld1q_u32(src + i);
+ uint32x4_t alphaVector = vshrq_n_u32(srcVector, 24);
+#if defined(Q_PROCESSOR_ARM_64)
+ uint32_t alphaSum = vaddvq_u32(alphaVector);
+#else
+ // no vaddvq_u32
+ uint32x2_t tmp = vpadd_u32(vget_low_u32(alphaVector), vget_high_u32(alphaVector));
+ uint32_t alphaSum = vget_lane_u32(vpadd_u32(tmp, tmp), 0);
+#endif
+ if (alphaSum) {
+ if (alphaSum != 255 * 4) {
+ if (RGBA)
+ srcVector = vrgba2argb(srcVector);
+ const float32x4_t a = vcvtq_f32_u32(alphaVector);
+ const float32x4_t ia = reciprocal_mul_ps(a, 255.0f);
+ // Convert 4x(4xU8) to 4x(4xF32)
+ uint16x8_t tmp1 = vmovl_u8(vget_low_u8(vreinterpretq_u8_u32(srcVector)));
+ uint16x8_t tmp3 = vmovl_u8(vget_high_u8(vreinterpretq_u8_u32(srcVector)));
+ float32x4_t src1 = vcvtq_f32_u32(vmovl_u16(vget_low_u16(tmp1)));
+ float32x4_t src2 = vcvtq_f32_u32(vmovl_u16(vget_high_u16(tmp1)));
+ float32x4_t src3 = vcvtq_f32_u32(vmovl_u16(vget_low_u16(tmp3)));
+ float32x4_t src4 = vcvtq_f32_u32(vmovl_u16(vget_high_u16(tmp3)));
+ src1 = vmulq_lane_f32(src1, vget_low_f32(ia), 0);
+ src2 = vmulq_lane_f32(src2, vget_low_f32(ia), 1);
+ src3 = vmulq_lane_f32(src3, vget_high_f32(ia), 0);
+ src4 = vmulq_lane_f32(src4, vget_high_f32(ia), 1);
+ // Convert 4x(4xF32) back to 4x(4xU8) (over a 8.1 fixed point format to get rounding)
+ tmp1 = vcombine_u16(vrshrn_n_u32(vcvtq_n_u32_f32(src1, 1), 1),
+ vrshrn_n_u32(vcvtq_n_u32_f32(src2, 1), 1));
+ tmp3 = vcombine_u16(vrshrn_n_u32(vcvtq_n_u32_f32(src3, 1), 1),
+ vrshrn_n_u32(vcvtq_n_u32_f32(src4, 1), 1));
+ uint32x4_t dstVector = vreinterpretq_u32_u8(vcombine_u8(vmovn_u16(tmp1), vmovn_u16(tmp3)));
+ // Overwrite any undefined results from alpha==0 with zeros:
+#if defined(Q_PROCESSOR_ARM_64)
+ uint32x4_t srcVectorAlphaMask = vceqzq_u32(alphaVector);
+#else
+ uint32x4_t srcVectorAlphaMask = vceqq_u32(alphaVector, vdupq_n_u32(0));
+#endif
+ dstVector = vbicq_u32(dstVector, srcVectorAlphaMask);
+ // Restore or mask alpha values:
+ if (RGBx)
+ dstVector = vorrq_u32(alphaMask, dstVector);
+ else
+ dstVector = vbslq_u32(alphaMask, srcVector, dstVector);
+ vst1q_u32(&buffer[i], dstVector);
+ } else {
+ // 4xAlpha==255, no change except if we are doing RGBA->ARGB:
+ if (RGBA)
+ vst1q_u32(&buffer[i], vrgba2argb(srcVector));
+ else if (buffer != src)
+ vst1q_u32(&buffer[i], srcVector);
+ }
+ } else {
+ // 4xAlpha==0, always zero, except if output is RGBx:
+ if (RGBx)
+ vst1q_u32(&buffer[i], alphaMask);
+ else
+ vst1q_u32(&buffer[i], vdupq_n_u32(0));
+ }
+ }
+
+ SIMD_EPILOGUE(i, count, 3) {
+ uint v = qUnpremultiply(src[i]);
+ if (RGBx)
+ v = 0xff000000 | v;
+ if (RGBA)
+ v = ARGB2RGBA(v);
+ buffer[i] = v;
+ }
+}
+
+void QT_FASTCALL convertARGB32ToARGB32PM_neon(uint *buffer, int count, const QVector<QRgb> *)
+{
+ convertARGBToARGB32PM_neon<false>(buffer, buffer, count);
+}
+
+void QT_FASTCALL convertRGBA8888ToARGB32PM_neon(uint *buffer, int count, const QVector<QRgb> *)
+{
+ convertARGBToARGB32PM_neon<true>(buffer, buffer, count);
+}
+
+const uint *QT_FASTCALL fetchARGB32ToARGB32PM_neon(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
- convertARGBToARGB32PM_neon<false>(buffer, src, count);
+ convertARGBToARGB32PM_neon<false>(buffer, reinterpret_cast<const uint *>(src) + index, count);
return buffer;
}
-const uint *QT_FASTCALL convertRGBA8888ToARGB32PM_neon(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+const uint *QT_FASTCALL fetchRGBA8888ToARGB32PM_neon(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
- convertARGBToARGB32PM_neon<true>(buffer, src, count);
+ convertARGBToARGB32PM_neon<true>(buffer, reinterpret_cast<const uint *>(src) + index, count);
return buffer;
}
+void QT_FASTCALL storeRGB32FromARGB32PM_neon(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ convertARGBFromARGB32PM_neon<false,true>(d, src, count);
+}
+
+void QT_FASTCALL storeARGB32FromARGB32PM_neon(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ convertARGBFromARGB32PM_neon<false,false>(d, src, count);
+}
+
+void QT_FASTCALL storeRGBA8888FromARGB32PM_neon(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ convertARGBFromARGB32PM_neon<true,false>(d, src, count);
+}
+
+void QT_FASTCALL storeRGBXFromARGB32PM_neon(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ convertARGBFromARGB32PM_neon<true,true>(d, src, count);
+}
+
#endif // Q_BYTE_ORDER == Q_LITTLE_ENDIAN
QT_END_NAMESPACE
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index 6f3c92ca64..fb08261205 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -747,6 +747,77 @@ static constexpr inline bool hasFastInterpolate4() { return false; }
#endif
+static inline QRgba64 multiplyAlpha256(QRgba64 rgba64, uint alpha256)
+{
+ return QRgba64::fromRgba64((rgba64.red() * alpha256) >> 8,
+ (rgba64.green() * alpha256) >> 8,
+ (rgba64.blue() * alpha256) >> 8,
+ (rgba64.alpha() * alpha256) >> 8);
+}
+static inline QRgba64 interpolate256(QRgba64 x, uint alpha1, QRgba64 y, uint alpha2)
+{
+ return QRgba64::fromRgba64(multiplyAlpha256(x, alpha1) + multiplyAlpha256(y, alpha2));
+}
+
+#ifdef __SSE2__
+static inline QRgba64 interpolate_4_pixels_rgb64(const QRgba64 t[], const QRgba64 b[], uint distx, uint disty)
+{
+ __m128i vt = _mm_loadu_si128((const __m128i*)t);
+ if (disty) {
+ __m128i vb = _mm_loadu_si128((const __m128i*)b);
+ vt = _mm_mulhi_epu16(vt, _mm_set1_epi16(0x10000 - disty));
+ vb = _mm_mulhi_epu16(vb, _mm_set1_epi16(disty));
+ vt = _mm_add_epi16(vt, vb);
+ }
+ if (distx) {
+ 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));
+ vt = _mm_mulhi_epu16(vt, _mm_unpacklo_epi64(vidistx, vdistx));
+ vt = _mm_add_epi16(vt, _mm_srli_si128(vt, 8));
+ }
+#ifdef Q_PROCESSOR_X86_64
+ return QRgba64::fromRgba64(_mm_cvtsi128_si64(vt));
+#else
+ QRgba64 out;
+ _mm_storel_epi64((__m128i*)&out, vt);
+ return out;
+#endif // Q_PROCESSOR_X86_64
+}
+#elif defined(__ARM_NEON__)
+static inline QRgba64 interpolate_4_pixels_rgb64(const QRgba64 t[], const QRgba64 b[], uint distx, uint disty)
+{
+ uint64x1x2_t vt = vld2_u64(reinterpret_cast<const uint64_t *>(t));
+ if (disty) {
+ uint64x1x2_t vb = vld2_u64(reinterpret_cast<const uint64_t *>(b));
+ uint32x4_t vt0 = vmull_n_u16(vreinterpret_u16_u64(vt.val[0]), 0x10000 - disty);
+ uint32x4_t vt1 = vmull_n_u16(vreinterpret_u16_u64(vt.val[1]), 0x10000 - disty);
+ vt0 = vmlal_n_u16(vt0, vreinterpret_u16_u64(vb.val[0]), disty);
+ vt1 = vmlal_n_u16(vt1, vreinterpret_u16_u64(vb.val[1]), disty);
+ vt.val[0] = vreinterpret_u64_u16(vshrn_n_u32(vt0, 16));
+ vt.val[1] = vreinterpret_u64_u16(vshrn_n_u32(vt1, 16));
+ }
+ if (distx) {
+ uint32x4_t vt0 = vmull_n_u16(vreinterpret_u16_u64(vt.val[0]), 0x10000 - distx);
+ vt0 = vmlal_n_u16(vt0, vreinterpret_u16_u64(vt.val[1]), distx);
+ vt.val[0] = vreinterpret_u64_u16(vshrn_n_u32(vt0, 16));
+ }
+ QRgba64 out;
+ vst1_u64(reinterpret_cast<uint64_t *>(&out), vt.val[0]);
+ return out;
+}
+#else
+static inline QRgba64 interpolate_4_pixels_rgb64(const QRgba64 t[], const QRgba64 b[], uint distx, uint disty)
+{
+ const uint dx = distx>>8;
+ const uint dy = disty>>8;
+ const uint idx = 256 - dx;
+ const uint idy = 256 - dy;
+ QRgba64 xtop = interpolate256(t[0], idx, t[1], dx);
+ QRgba64 xbot = interpolate256(b[0], idx, b[1], dx);
+ return interpolate256(xtop, idy, xbot, dy);
+}
+#endif // __SSE2__
+
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
static Q_ALWAYS_INLINE quint32 RGBA2ARGB(quint32 x) {
quint32 rgb = x >> 8;
@@ -798,6 +869,7 @@ static Q_ALWAYS_INLINE uint qAlphaRgb30(uint c)
}
struct quint24 {
+ quint24() = default;
quint24(uint value);
operator uint() const;
uchar data[3];
@@ -1142,6 +1214,8 @@ static Q_ALWAYS_INLINE const uint *qt_convertRGBA8888ToARGB32PM(uint *buffer, co
return buffer;
}
+template<bool RGBA> void qt_convertRGBA64ToARGB32(uint *dst, const QRgba64 *src, int count);
+
const uint qt_bayer_matrix[16][16] = {
{ 0x1, 0xc0, 0x30, 0xf0, 0xc, 0xcc, 0x3c, 0xfc,
0x3, 0xc3, 0x33, 0xf3, 0xf, 0xcf, 0x3f, 0xff},
@@ -1205,15 +1279,43 @@ inline uint comp_func_Plus_one_pixel(uint d, const uint s)
#undef MIX
#undef AMIX
+// must be multiple of 4 for easier SIMD implementations
+static Q_CONSTEXPR int BufferSize = 2048;
+
+// A buffer of intermediate results used by simple bilinear scaling.
+struct IntermediateBuffer
+{
+ // The idea is first to do the interpolation between the row s1 and the row s2
+ // into this intermediate buffer, then later interpolate between two pixel of this buffer.
+ //
+ // buffer_rb is a buffer of red-blue component of the pixel, in the form 0x00RR00BB
+ // buffer_ag is the alpha-green component of the pixel, in the form 0x00AA00GG
+ // +1 for the last pixel to interpolate with, and +1 for rounding errors.
+ quint32 buffer_rb[BufferSize+2];
+ quint32 buffer_ag[BufferSize+2];
+};
+
struct QDitherInfo {
int x;
int y;
};
-typedef const uint *(QT_FASTCALL *ConvertFunc)(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *clut, QDitherInfo *dither);
-typedef const QRgba64 *(QT_FASTCALL *ConvertFunc64)(QRgba64 *buffer, const uint *src, int count,
- const QVector<QRgb> *clut, QDitherInfo *dither);
+typedef const uint *(QT_FASTCALL *FetchAndConvertPixelsFunc)(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *clut, QDitherInfo *dither);
+typedef void (QT_FASTCALL *ConvertAndStorePixelsFunc)(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *clut, QDitherInfo *dither);
+
+typedef const QRgba64 *(QT_FASTCALL *FetchAndConvertPixelsFunc64)(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *clut, QDitherInfo *dither);
+typedef void (QT_FASTCALL *ConvertAndStorePixelsFunc64)(uchar *dest, const QRgba64 *src, int index, int count,
+ const QVector<QRgb> *clut, QDitherInfo *dither);
+
+typedef void (QT_FASTCALL *ConvertFunc)(uint *buffer, int count, const QVector<QRgb> *clut);
+typedef void (QT_FASTCALL *Convert64Func)(quint64 *buffer, int count, const QVector<QRgb> *clut);
+typedef const QRgba64 *(QT_FASTCALL *ConvertTo64Func)(QRgba64 *buffer, const uint *src, int count,
+ const QVector<QRgb> *clut, QDitherInfo *dither);
+typedef void (QT_FASTCALL *RbSwapFunc)(uchar *dst, const uchar *src, int count);
+
struct QPixelLayout
{
@@ -1226,36 +1328,28 @@ struct QPixelLayout
BPP16,
BPP24,
BPP32,
+ BPP64,
BPPCount
};
- // All numbers in bits.
- uchar redWidth;
- uchar redShift;
- uchar greenWidth;
- uchar greenShift;
- uchar blueWidth;
- uchar blueShift;
- uchar alphaWidth;
- uchar alphaShift;
+ bool hasAlphaChannel;
bool premultiplied;
BPP bpp;
+ RbSwapFunc rbSwap;
ConvertFunc convertToARGB32PM;
- ConvertFunc convertFromARGB32PM;
- ConvertFunc convertFromRGB32;
- ConvertFunc64 convertToARGB64PM;
+ ConvertTo64Func convertToRGBA64PM;
+ FetchAndConvertPixelsFunc fetchToARGB32PM;
+ FetchAndConvertPixelsFunc64 fetchToRGBA64PM;
+ ConvertAndStorePixelsFunc storeFromARGB32PM;
+ ConvertAndStorePixelsFunc storeFromRGB32;
};
-typedef const uint *(QT_FASTCALL *FetchPixelsFunc)(uint *buffer, const uchar *src, int index, int count);
-typedef void (QT_FASTCALL *StorePixelsFunc)(uchar *dest, const uint *src, int index, int count);
+extern ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats];
extern QPixelLayout qPixelLayouts[QImage::NImageFormats];
-extern const FetchPixelsFunc qFetchPixels[QPixelLayout::BPPCount];
-extern StorePixelsFunc qStorePixels[QPixelLayout::BPPCount];
extern MemRotateFunc qMemRotateFunctions[QPixelLayout::BPPCount][3];
-
QT_END_NAMESPACE
#endif // QDRAWHELPER_P_H
diff --git a/src/gui/painting/qdrawhelper_sse4.cpp b/src/gui/painting/qdrawhelper_sse4.cpp
index 14bfaabf09..e3cc1dd43e 100644
--- a/src/gui/painting/qdrawhelper_sse4.cpp
+++ b/src/gui/painting/qdrawhelper_sse4.cpp
@@ -39,13 +39,14 @@
#include <private/qdrawhelper_p.h>
#include <private/qdrawingprimitive_sse2_p.h>
+#include <private/qpaintengine_raster_p.h>
#if defined(QT_COMPILER_SUPPORTS_SSE4_1)
QT_BEGIN_NAMESPACE
template<bool RGBA>
-static inline void convertARGBToARGB32PM_sse4(uint *buffer, const uint *src, int count)
+static void convertARGBToARGB32PM_sse4(uint *buffer, const uint *src, int count)
{
int i = 0;
const __m128i alphaMask = _mm_set1_epi32(0xff000000);
@@ -83,7 +84,7 @@ static inline void convertARGBToARGB32PM_sse4(uint *buffer, const uint *src, int
_mm_storeu_si128((__m128i *)&buffer[i], srcVector);
}
} else {
- _mm_storeu_si128((__m128i *)&buffer[i], _mm_setzero_si128());
+ _mm_storeu_si128((__m128i *)&buffer[i], zero);
}
}
@@ -93,59 +94,264 @@ static inline void convertARGBToARGB32PM_sse4(uint *buffer, const uint *src, int
}
}
-const uint *QT_FASTCALL convertARGB32ToARGB32PM_sse4(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+static inline __m128 reciprocal_mul_ps(__m128 a, float mul)
{
- convertARGBToARGB32PM_sse4<false>(buffer, src, count);
- return buffer;
+ __m128 ia = _mm_rcp_ps(a); // Approximate 1/a
+ // Improve precision of ia using Newton-Raphson
+ ia = _mm_sub_ps(_mm_add_ps(ia, ia), _mm_mul_ps(ia, _mm_mul_ps(ia, a)));
+ ia = _mm_mul_ps(ia, _mm_set1_ps(mul));
+ return ia;
}
-const uint *QT_FASTCALL convertRGBA8888ToARGB32PM_sse4(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+template<bool RGBA, bool RGBx>
+static inline void convertARGBFromARGB32PM_sse4(uint *buffer, const uint *src, int count)
{
- convertARGBToARGB32PM_sse4<true>(buffer, src, count);
- return buffer;
+ int i = 0;
+ const __m128i alphaMask = _mm_set1_epi32(0xff000000);
+ const __m128i rgbaMask = _mm_setr_epi8(2, 1, 0, 3, 6, 5, 4, 7, 10, 9, 8, 11, 14, 13, 12, 15);
+ const __m128i zero = _mm_setzero_si128();
+
+ for (; i < count - 3; i += 4) {
+ __m128i srcVector = _mm_loadu_si128((const __m128i *)&src[i]);
+ if (!_mm_testz_si128(srcVector, alphaMask)) {
+ if (!_mm_testc_si128(srcVector, alphaMask)) {
+ __m128i srcVectorAlpha = _mm_srli_epi32(srcVector, 24);
+ if (RGBA)
+ srcVector = _mm_shuffle_epi8(srcVector, rgbaMask);
+ const __m128 a = _mm_cvtepi32_ps(srcVectorAlpha);
+ const __m128 ia = reciprocal_mul_ps(a, 255.0f);
+ __m128i src1 = _mm_unpacklo_epi8(srcVector, zero);
+ __m128i src3 = _mm_unpackhi_epi8(srcVector, zero);
+ __m128i src2 = _mm_unpackhi_epi16(src1, zero);
+ __m128i src4 = _mm_unpackhi_epi16(src3, zero);
+ src1 = _mm_unpacklo_epi16(src1, zero);
+ src3 = _mm_unpacklo_epi16(src3, zero);
+ __m128 ia1 = _mm_shuffle_ps(ia, ia, _MM_SHUFFLE(0, 0, 0, 0));
+ __m128 ia2 = _mm_shuffle_ps(ia, ia, _MM_SHUFFLE(1, 1, 1, 1));
+ __m128 ia3 = _mm_shuffle_ps(ia, ia, _MM_SHUFFLE(2, 2, 2, 2));
+ __m128 ia4 = _mm_shuffle_ps(ia, ia, _MM_SHUFFLE(3, 3, 3, 3));
+ src1 = _mm_cvtps_epi32(_mm_mul_ps(_mm_cvtepi32_ps(src1), ia1));
+ src2 = _mm_cvtps_epi32(_mm_mul_ps(_mm_cvtepi32_ps(src2), ia2));
+ src3 = _mm_cvtps_epi32(_mm_mul_ps(_mm_cvtepi32_ps(src3), ia3));
+ src4 = _mm_cvtps_epi32(_mm_mul_ps(_mm_cvtepi32_ps(src4), ia4));
+ src1 = _mm_packus_epi32(src1, src2);
+ src3 = _mm_packus_epi32(src3, src4);
+ src1 = _mm_packus_epi16(src1, src3);
+ // Handle potential alpha == 0 values:
+ __m128i srcVectorAlphaMask = _mm_cmpeq_epi32(srcVectorAlpha, zero);
+ src1 = _mm_andnot_si128(srcVectorAlphaMask, src1);
+ // Fixup alpha values:
+ if (RGBx)
+ srcVector = _mm_or_si128(src1, alphaMask);
+ else
+ srcVector = _mm_blendv_epi8(src1, srcVector, alphaMask);
+ _mm_storeu_si128((__m128i *)&buffer[i], srcVector);
+ } else {
+ if (RGBA)
+ _mm_storeu_si128((__m128i *)&buffer[i], _mm_shuffle_epi8(srcVector, rgbaMask));
+ else if (buffer != src)
+ _mm_storeu_si128((__m128i *)&buffer[i], srcVector);
+ }
+ } else {
+ if (RGBx)
+ _mm_storeu_si128((__m128i *)&buffer[i], alphaMask);
+ else
+ _mm_storeu_si128((__m128i *)&buffer[i], zero);
+ }
+ }
+
+ SIMD_EPILOGUE(i, count, 3) {
+ uint v = qUnpremultiply_sse4(src[i]);
+ if (RGBx)
+ v = 0xff000000 | v;
+ if (RGBA)
+ v = ARGB2RGBA(v);
+ buffer[i] = v;
+ }
}
-const uint *QT_FASTCALL convertARGB32FromARGB32PM_sse4(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+template<bool RGBA>
+static inline void convertARGBFromRGBA64PM_sse4(uint *buffer, const QRgba64 *src, int count)
{
- for (int i = 0; i < count; ++i)
- buffer[i] = qUnpremultiply_sse4(src[i]);
- return buffer;
+ int i = 0;
+ const __m128i alphaMask = _mm_set1_epi64x(Q_UINT64_C(0xffff) << 48);
+ const __m128i alphaMask32 = _mm_set1_epi32(0xff000000);
+ const __m128i rgbaMask = _mm_setr_epi8(2, 1, 0, 3, 6, 5, 4, 7, 10, 9, 8, 11, 14, 13, 12, 15);
+ const __m128i zero = _mm_setzero_si128();
+
+ for (; i < count - 3; i += 4) {
+ __m128i srcVector1 = _mm_loadu_si128((const __m128i *)&src[i]);
+ __m128i srcVector2 = _mm_loadu_si128((const __m128i *)&src[i + 2]);
+ bool transparent1 = _mm_testz_si128(srcVector1, alphaMask);
+ bool opaque1 = _mm_testc_si128(srcVector1, alphaMask);
+ bool transparent2 = _mm_testz_si128(srcVector2, alphaMask);
+ bool opaque2 = _mm_testc_si128(srcVector2, alphaMask);
+
+ if (!(transparent1 && transparent2)) {
+ if (!(opaque1 && opaque2)) {
+ __m128i srcVector1Alpha = _mm_srli_epi64(srcVector1, 48);
+ __m128i srcVector2Alpha = _mm_srli_epi64(srcVector2, 48);
+ __m128i srcVectorAlpha = _mm_packus_epi32(srcVector1Alpha, srcVector2Alpha);
+ const __m128 a = _mm_cvtepi32_ps(srcVectorAlpha);
+ // Convert srcVectorAlpha to final 8-bit alpha channel
+ srcVectorAlpha = _mm_add_epi32(srcVectorAlpha, _mm_set1_epi32(128));
+ srcVectorAlpha = _mm_sub_epi32(srcVectorAlpha, _mm_srli_epi32(srcVectorAlpha, 8));
+ srcVectorAlpha = _mm_srli_epi32(srcVectorAlpha, 8);
+ srcVectorAlpha = _mm_slli_epi32(srcVectorAlpha, 24);
+ const __m128 ia = reciprocal_mul_ps(a, 255.0f);
+ __m128i src1 = _mm_unpacklo_epi16(srcVector1, zero);
+ __m128i src2 = _mm_unpackhi_epi16(srcVector1, zero);
+ __m128i src3 = _mm_unpacklo_epi16(srcVector2, zero);
+ __m128i src4 = _mm_unpackhi_epi16(srcVector2, zero);
+ __m128 ia1 = _mm_shuffle_ps(ia, ia, _MM_SHUFFLE(0, 0, 0, 0));
+ __m128 ia2 = _mm_shuffle_ps(ia, ia, _MM_SHUFFLE(1, 1, 1, 1));
+ __m128 ia3 = _mm_shuffle_ps(ia, ia, _MM_SHUFFLE(2, 2, 2, 2));
+ __m128 ia4 = _mm_shuffle_ps(ia, ia, _MM_SHUFFLE(3, 3, 3, 3));
+ src1 = _mm_cvtps_epi32(_mm_mul_ps(_mm_cvtepi32_ps(src1), ia1));
+ src2 = _mm_cvtps_epi32(_mm_mul_ps(_mm_cvtepi32_ps(src2), ia2));
+ src3 = _mm_cvtps_epi32(_mm_mul_ps(_mm_cvtepi32_ps(src3), ia3));
+ src4 = _mm_cvtps_epi32(_mm_mul_ps(_mm_cvtepi32_ps(src4), ia4));
+ src1 = _mm_packus_epi32(src1, src2);
+ src3 = _mm_packus_epi32(src3, src4);
+ // Handle potential alpha == 0 values:
+ __m128i srcVector1AlphaMask = _mm_cmpeq_epi64(srcVector1Alpha, zero);
+ __m128i srcVector2AlphaMask = _mm_cmpeq_epi64(srcVector2Alpha, zero);
+ src1 = _mm_andnot_si128(srcVector1AlphaMask, src1);
+ src3 = _mm_andnot_si128(srcVector2AlphaMask, src3);
+ src1 = _mm_packus_epi16(src1, src3);
+ // Fixup alpha values:
+ src1 = _mm_blendv_epi8(src1, srcVectorAlpha, alphaMask32);
+ // Fix RGB order
+ if (!RGBA)
+ src1 = _mm_shuffle_epi8(src1, rgbaMask);
+ _mm_storeu_si128((__m128i *)&buffer[i], src1);
+ } else {
+ __m128i src1 = _mm_unpacklo_epi16(srcVector1, zero);
+ __m128i src2 = _mm_unpackhi_epi16(srcVector1, zero);
+ __m128i src3 = _mm_unpacklo_epi16(srcVector2, zero);
+ __m128i src4 = _mm_unpackhi_epi16(srcVector2, zero);
+ src1 = _mm_add_epi32(src1, _mm_set1_epi32(128));
+ src2 = _mm_add_epi32(src2, _mm_set1_epi32(128));
+ src3 = _mm_add_epi32(src3, _mm_set1_epi32(128));
+ src4 = _mm_add_epi32(src4, _mm_set1_epi32(128));
+ src1 = _mm_sub_epi32(src1, _mm_srli_epi32(src1, 8));
+ src2 = _mm_sub_epi32(src2, _mm_srli_epi32(src2, 8));
+ src3 = _mm_sub_epi32(src3, _mm_srli_epi32(src3, 8));
+ src4 = _mm_sub_epi32(src4, _mm_srli_epi32(src4, 8));
+ src1 = _mm_srli_epi32(src1, 8);
+ src2 = _mm_srli_epi32(src2, 8);
+ src3 = _mm_srli_epi32(src3, 8);
+ src4 = _mm_srli_epi32(src4, 8);
+ src1 = _mm_packus_epi32(src1, src2);
+ src3 = _mm_packus_epi32(src3, src4);
+ src1 = _mm_packus_epi16(src1, src3);
+ if (!RGBA)
+ src1 = _mm_shuffle_epi8(src1, rgbaMask);
+ _mm_storeu_si128((__m128i *)&buffer[i], src1);
+ }
+ } else {
+ _mm_storeu_si128((__m128i *)&buffer[i], zero);
+ }
+ }
+
+ SIMD_EPILOGUE(i, count, 3) {
+ buffer[i] = qConvertRgba64ToRgb32_sse4<RGBA ? PixelOrderRGB : PixelOrderBGR>(src[i]);
+ }
}
-const uint *QT_FASTCALL convertRGBA8888FromARGB32PM_sse4(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+void QT_FASTCALL convertARGB32ToARGB32PM_sse4(uint *buffer, int count, const QVector<QRgb> *)
{
- for (int i = 0; i < count; ++i)
- buffer[i] = ARGB2RGBA(qUnpremultiply_sse4(src[i]));
+ convertARGBToARGB32PM_sse4<false>(buffer, buffer, count);
+}
+
+void QT_FASTCALL convertRGBA8888ToARGB32PM_sse4(uint *buffer, int count, const QVector<QRgb> *)
+{
+ convertARGBToARGB32PM_sse4<true>(buffer, buffer, count);
+}
+
+const uint *QT_FASTCALL fetchARGB32ToARGB32PM_sse4(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ convertARGBToARGB32PM_sse4<false>(buffer, reinterpret_cast<const uint *>(src) + index, count);
return buffer;
}
-const uint *QT_FASTCALL convertRGBXFromARGB32PM_sse4(uint *buffer, const uint *src, int count,
+const uint *QT_FASTCALL fetchRGBA8888ToARGB32PM_sse4(uint *buffer, const uchar *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *)
{
- for (int i = 0; i < count; ++i)
- buffer[i] = ARGB2RGBA(0xff000000 | qUnpremultiply_sse4(src[i]));
+ convertARGBToARGB32PM_sse4<true>(buffer, reinterpret_cast<const uint *>(src) + index, count);
return buffer;
}
+void QT_FASTCALL storeRGB32FromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ convertARGBFromARGB32PM_sse4<false,true>(d, src, count);
+}
+
+void QT_FASTCALL storeARGB32FromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ convertARGBFromARGB32PM_sse4<false,false>(d, src, count);
+}
+
+void QT_FASTCALL storeRGBA8888FromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ convertARGBFromARGB32PM_sse4<true,false>(d, src, count);
+}
+
+void QT_FASTCALL storeRGBXFromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ convertARGBFromARGB32PM_sse4<true,true>(d, src, count);
+}
+
template<QtPixelOrder PixelOrder>
-const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM_sse4(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+void QT_FASTCALL storeA2RGB30PMFromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
+ uint *d = reinterpret_cast<uint *>(dest) + index;
for (int i = 0; i < count; ++i)
- buffer[i] = qConvertArgb32ToA2rgb30_sse4<PixelOrder>(src[i]);
- return buffer;
+ d[i] = qConvertArgb32ToA2rgb30_sse4<PixelOrder>(src[i]);
+}
+
+void QT_FASTCALL destStore64ARGB32_sse4(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
+{
+ uint *dest = (uint*)rasterBuffer->scanLine(y) + x;
+ convertARGBFromRGBA64PM_sse4<false>(dest, buffer, length);
+}
+
+void QT_FASTCALL destStore64RGBA8888_sse4(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
+{
+ uint *dest = (uint*)rasterBuffer->scanLine(y) + x;
+ convertARGBFromRGBA64PM_sse4<true>(dest, buffer, length);
+}
+
+void QT_FASTCALL storeARGB32FromRGBA64PM_sse4(uchar *dest, const QRgba64 *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ uint *d = (uint*)dest + index;
+ convertARGBFromRGBA64PM_sse4<false>(d, src, count);
+}
+
+void QT_FASTCALL storeRGBA8888FromRGBA64PM_sse4(uchar *dest, const QRgba64 *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *)
+{
+ uint *d = (uint*)dest + index;
+ convertARGBFromRGBA64PM_sse4<true>(d, src, count);
}
template
-const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM_sse4<PixelOrderBGR>(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *);
+void QT_FASTCALL storeA2RGB30PMFromARGB32PM_sse4<PixelOrderBGR>(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
template
-const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM_sse4<PixelOrderRGB>(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *);
+void QT_FASTCALL storeA2RGB30PMFromARGB32PM_sse4<PixelOrderRGB>(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
QT_END_NAMESPACE
diff --git a/src/gui/painting/qdrawhelper_ssse3.cpp b/src/gui/painting/qdrawhelper_ssse3.cpp
index 45ecc8b422..42d760d5cc 100644
--- a/src/gui/painting/qdrawhelper_ssse3.cpp
+++ b/src/gui/painting/qdrawhelper_ssse3.cpp
@@ -167,61 +167,12 @@ void qt_blend_argb32_on_argb32_ssse3(uchar *destPixels, int dbpl,
}
}
-static inline void store_uint24_ssse3(uchar *dst, const uint *src, int len)
+const uint *QT_FASTCALL fetchPixelsBPP24_ssse3(uint *buffer, const uchar *src, int index, int count)
{
- int i = 0;
-
- quint24 *dst24 = reinterpret_cast<quint24*>(dst);
- // Align dst on 16 bytes
- for (; i < len && (reinterpret_cast<quintptr>(dst24) & 0xf); ++i)
- *dst24++ = quint24(*src++);
-
- // Shuffle masks for first and second half of every output, all outputs are aligned so the shuffled ends are not used.
- const __m128i shuffleMask1 = _mm_setr_epi8(char(0x80), char(0x80), char(0x80), char(0x80), 2, 1, 0, 6, 5, 4, 10, 9, 8, 14, 13, 12);
- const __m128i shuffleMask2 = _mm_setr_epi8(2, 1, 0, 6, 5, 4, 10, 9, 8, 14, 13, 12, char(0x80), char(0x80), char(0x80), char(0x80));
-
- const __m128i *inVectorPtr = (const __m128i *)src;
- __m128i *dstVectorPtr = (__m128i *)dst24;
-
- for (; i < (len - 15); i += 16) {
- // Load four vectors, store three.
- // Create each output vector by combining two shuffled input vectors.
- __m128i srcVector1 = _mm_loadu_si128(inVectorPtr);
- ++inVectorPtr;
- __m128i srcVector2 = _mm_loadu_si128(inVectorPtr);
- ++inVectorPtr;
- __m128i outputVector1 = _mm_shuffle_epi8(srcVector1, shuffleMask1);
- __m128i outputVector2 = _mm_shuffle_epi8(srcVector2, shuffleMask2);
- __m128i outputVector = _mm_alignr_epi8(outputVector2, outputVector1, 4);
- _mm_store_si128(dstVectorPtr, outputVector);
- ++dstVectorPtr;
-
- srcVector1 = _mm_loadu_si128(inVectorPtr);
- ++inVectorPtr;
- outputVector1 = _mm_shuffle_epi8(srcVector2, shuffleMask1);
- outputVector2 = _mm_shuffle_epi8(srcVector1, shuffleMask2);
- outputVector = _mm_alignr_epi8(outputVector2, outputVector1, 8);
- _mm_store_si128(dstVectorPtr, outputVector);
- ++dstVectorPtr;
-
- srcVector2 = _mm_loadu_si128(inVectorPtr);
- ++inVectorPtr;
- outputVector1 = _mm_shuffle_epi8(srcVector1, shuffleMask1);
- outputVector2 = _mm_shuffle_epi8(srcVector2, shuffleMask2);
- outputVector = _mm_alignr_epi8(outputVector2, outputVector1, 12);
- _mm_store_si128(dstVectorPtr, outputVector);
- ++dstVectorPtr;
- }
- dst24 = reinterpret_cast<quint24*>(dstVectorPtr);
- src = reinterpret_cast<const uint*>(inVectorPtr);
-
- SIMD_EPILOGUE(i, len, 15)
- *dst24++ = quint24(*src++);
-}
-
-void QT_FASTCALL storePixelsBPP24_ssse3(uchar *dest, const uint *src, int index, int count)
-{
- store_uint24_ssse3(dest + index * 3, src, count);
+ const quint24 *s = reinterpret_cast<const quint24 *>(src);
+ for (int i = 0; i < count; ++i)
+ buffer[i] = s[index + i];
+ return buffer;
}
extern void QT_FASTCALL qt_convert_rgb888_to_rgb32_ssse3(quint32 *dst, const uchar *src, int len);
diff --git a/src/gui/painting/qdrawingprimitive_sse2_p.h b/src/gui/painting/qdrawingprimitive_sse2_p.h
index 93e4b9f572..b237ea1611 100644
--- a/src/gui/painting/qdrawingprimitive_sse2_p.h
+++ b/src/gui/painting/qdrawingprimitive_sse2_p.h
@@ -43,6 +43,7 @@
#include <QtGui/private/qtguiglobal_p.h>
#include <private/qsimd_p.h>
#include "qdrawhelper_p.h"
+#include "qrgba64_p.h"
#ifdef __SSE2__
@@ -230,21 +231,31 @@ QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
#if QT_COMPILER_SUPPORTS_HERE(SSE4_1)
+QT_FUNCTION_TARGET(SSE2)
+Q_ALWAYS_INLINE void reciprocal_mul_ss(__m128 &ia, const __m128 a, float mul)
+{
+ ia = _mm_rcp_ss(a); // Approximate 1/a
+ // Improve precision of ia using Newton-Raphson
+ ia = _mm_sub_ss(_mm_add_ss(ia, ia), _mm_mul_ss(ia, _mm_mul_ss(ia, a)));
+ ia = _mm_mul_ss(ia, _mm_set_ss(mul));
+ ia = _mm_shuffle_ps(ia, ia, _MM_SHUFFLE(0,0,0,0));
+}
+
QT_FUNCTION_TARGET(SSE4_1)
inline QRgb qUnpremultiply_sse4(QRgb p)
{
const uint alpha = qAlpha(p);
- if (alpha == 255 || alpha == 0)
+ if (alpha == 255)
return p;
- const uint invAlpha = qt_inv_premul_factor[alpha];
- const __m128i via = _mm_set1_epi32(invAlpha);
- const __m128i vr = _mm_set1_epi32(0x8000);
+ if (alpha == 0)
+ return 0;
+ const __m128 va = _mm_set1_ps(alpha);
+ __m128 via;
+ reciprocal_mul_ss(via, va, 255.0f); // Approximate 1/a
__m128i vl = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(p));
- vl = _mm_mullo_epi32(vl, via);
- vl = _mm_add_epi32(vl, vr);
- vl = _mm_srai_epi32(vl, 16);
- vl = _mm_insert_epi32(vl, alpha, 3);
+ vl = _mm_cvtps_epi32(_mm_mul_ps(_mm_cvtepi32_ps(vl), via));
vl = _mm_packus_epi32(vl, vl);
+ vl = _mm_insert_epi16(vl, alpha, 3);
vl = _mm_packus_epi16(vl, vl);
return _mm_cvtsi128_si32(vl);
}
@@ -258,21 +269,14 @@ inline uint qConvertArgb32ToA2rgb30_sse4(QRgb p)
return qConvertRgb32ToRgb30<PixelOrder>(p);
if (alpha == 0)
return 0;
- Q_CONSTEXPR uint mult = 255 / (255 >> 6);
- const uint invAlpha = qt_inv_premul_factor[alpha];
+ Q_CONSTEXPR float mult = 1023.0f / (255 >> 6);
const uint newalpha = (alpha >> 6);
- const __m128i via = _mm_set1_epi32(invAlpha);
- const __m128i vna = _mm_set1_epi32(mult * newalpha);
- const __m128i vr1 = _mm_set1_epi32(0x1000);
- const __m128i vr2 = _mm_set1_epi32(0x80);
- __m128i vl = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(p));
- vl = _mm_mullo_epi32(vl, via);
- vl = _mm_add_epi32(vl, vr1);
- vl = _mm_srli_epi32(vl, 14);
- vl = _mm_mullo_epi32(vl, vna);
- vl = _mm_add_epi32(vl, _mm_srli_epi32(vl, 8));
- vl = _mm_add_epi32(vl, vr2);
- vl = _mm_srli_epi32(vl, 8);
+ const __m128 va = _mm_set1_ps(alpha);
+ __m128 via;
+ reciprocal_mul_ss(via, va, mult * newalpha);
+ __m128i vl = _mm_cvtsi32_si128(p);
+ vl = _mm_cvtepu8_epi32(vl);
+ vl = _mm_cvtps_epi32(_mm_mul_ps(_mm_cvtepi32_ps(vl), via));
vl = _mm_packus_epi32(vl, vl);
uint rgb30 = (newalpha << 30);
rgb30 |= ((uint)_mm_extract_epi16(vl, 1)) << 10;
@@ -285,6 +289,27 @@ inline uint qConvertArgb32ToA2rgb30_sse4(QRgb p)
}
return rgb30;
}
+
+template<enum QtPixelOrder PixelOrder>
+QT_FUNCTION_TARGET(SSE4_1)
+inline uint qConvertRgba64ToRgb32_sse4(QRgba64 p)
+{
+ if (p.isTransparent())
+ return 0;
+ __m128i vl = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(&p));
+ if (!p.isOpaque()) {
+ const __m128 va = _mm_set1_ps(p.alpha());
+ __m128 via;
+ reciprocal_mul_ss(via, va, 65535.0f);
+ vl = _mm_unpacklo_epi16(vl, _mm_setzero_si128());
+ vl = _mm_cvtps_epi32(_mm_mul_ps(_mm_cvtepi32_ps(vl) , via));
+ vl = _mm_packus_epi32(vl, vl);
+ vl = _mm_insert_epi16(vl, p.alpha(), 3);
+ }
+ if (PixelOrder == PixelOrderBGR)
+ vl = _mm_shufflelo_epi16(vl, _MM_SHUFFLE(3, 0, 1, 2));
+ return toArgb32(vl);
+}
#endif
QT_END_NAMESPACE
diff --git a/src/gui/painting/qemulationpaintengine.cpp b/src/gui/painting/qemulationpaintengine.cpp
index e6686e3721..0c0df0fb13 100644
--- a/src/gui/painting/qemulationpaintengine.cpp
+++ b/src/gui/painting/qemulationpaintengine.cpp
@@ -74,10 +74,11 @@ QPainterState *QEmulationPaintEngine::createState(QPainterState *orig) const
static inline void combineXForm(QBrush *brush, const QRectF &r)
{
- QTransform t = brush->transform();
- t.translate(r.x(), r.y());
- t.scale(r.width(), r.height());
- brush->setTransform(t);
+ QTransform t(r.width(), 0, 0, r.height(), r.x(), r.y());
+ if (brush->gradient() && brush->gradient()->coordinateMode() != QGradient::ObjectMode)
+ brush->setTransform(t * brush->transform()); // compat mode
+ else
+ brush->setTransform(brush->transform() * t);
}
void QEmulationPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
@@ -96,11 +97,19 @@ void QEmulationPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
if (coMode > QGradient::LogicalMode) {
QBrush copy = brush;
const QPaintDevice *d = real_engine->painter()->device();
- QRectF r = (coMode == QGradient::ObjectBoundingMode) ? path.controlPointRect() : QRectF(0, 0, d->width(), d->height());
+ QRectF r = (coMode == QGradient::StretchToDeviceMode) ? QRectF(0, 0, d->width(), d->height()) : path.controlPointRect();
combineXForm(&copy, r);
real_engine->fill(path, copy);
return;
}
+ } else if (style == Qt::TexturePattern) {
+ qreal dpr = qHasPixmapTexture(brush) ? brush.texture().devicePixelRatioF() : brush.textureImage().devicePixelRatioF();
+ if (!qFuzzyCompare(dpr, 1.0)) {
+ QBrush copy = brush;
+ combineXForm(&copy, QRectF(0, 0, 1.0/dpr, 1.0/dpr));
+ real_engine->fill(path, copy);
+ return;
+ }
}
real_engine->fill(path, brush);
@@ -124,7 +133,7 @@ void QEmulationPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
QGradient::CoordinateMode coMode = brush.gradient()->coordinateMode();
if (coMode > QGradient::LogicalMode) {
const QPaintDevice *d = real_engine->painter()->device();
- QRectF r = (coMode == QGradient::ObjectBoundingMode) ? path.controlPointRect() : QRectF(0, 0, d->width(), d->height());
+ QRectF r = (coMode == QGradient::StretchToDeviceMode) ? QRectF(0, 0, d->width(), d->height()) : path.controlPointRect();
combineXForm(&brush, r);
copy.setBrush(brush);
real_engine->stroke(path, copy);
@@ -166,9 +175,9 @@ void QEmulationPaintEngine::drawTextItem(const QPointF &p, const QTextItem &text
QBrush copy = s->pen.brush();
const QPaintDevice *d = real_engine->painter()->device();
const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
- QRectF r = (g.coordinateMode() == QGradient::ObjectBoundingMode) ?
- QRectF(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal()) :
- QRectF(0, 0, d->width(), d->height());
+ QRectF r = (g.coordinateMode() == QGradient::StretchToDeviceMode) ?
+ QRectF(0, 0, d->width(), d->height()) :
+ QRectF(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
combineXForm(&copy, r);
g.setCoordinateMode(QGradient::LogicalMode);
QBrush brush(g);
diff --git a/src/gui/painting/qimagescale.cpp b/src/gui/painting/qimagescale.cpp
index 22787b91fe..8a5274bd37 100644
--- a/src/gui/painting/qimagescale.cpp
+++ b/src/gui/painting/qimagescale.cpp
@@ -41,6 +41,7 @@
#include "qimage.h"
#include "qcolor.h"
+#include "qrgba64_p.h"
QT_BEGIN_NAMESPACE
@@ -85,7 +86,7 @@ QT_BEGIN_NAMESPACE
* #ifdef'ed code, and removal of unneeded border calculation code.
* Later the code has been refactored, an SSE4.1 optimizated path have been
* added instead of the removed MMX assembler, and scaling of clipped area
- * removed.
+ * removed, and an RGBA64 version written
*
* Imlib2 is (C) Carsten Haitzler and various contributors. The MMX code
* is by Willem Monsuwe <willem@stack.nl>. All other modifications are
@@ -94,12 +95,11 @@ QT_BEGIN_NAMESPACE
namespace QImageScale {
- const unsigned int** qimageCalcYPoints(const unsigned int *src, int sw, int sh, int dh);
- int* qimageCalcXPoints(int sw, int dw);
- int* qimageCalcApoints(int s, int d, int up);
- QImageScaleInfo* qimageFreeScaleInfo(QImageScaleInfo *isi);
- QImageScaleInfo *qimageCalcScaleInfo(const QImage &img, int sw, int sh,
- int dw, int dh, char aa);
+ static const unsigned int** qimageCalcYPoints(const unsigned int *src, int sw, int sh, int dh);
+ static int* qimageCalcXPoints(int sw, int dw);
+ static int* qimageCalcApoints(int s, int d, int up);
+ static QImageScaleInfo* qimageFreeScaleInfo(QImageScaleInfo *isi);
+ static QImageScaleInfo *qimageCalcScaleInfo(const QImage &img, int sw, int sh, int dw, int dh, char aa);
}
using namespace QImageScale;
@@ -108,8 +108,8 @@ using namespace QImageScale;
// Code ported from Imlib...
//
-const unsigned int** QImageScale::qimageCalcYPoints(const unsigned int *src,
- int sw, int sh, int dh)
+static const unsigned int** QImageScale::qimageCalcYPoints(const unsigned int *src,
+ int sw, int sh, int dh)
{
const unsigned int **p;
int j = 0, rv = 0;
@@ -138,7 +138,7 @@ const unsigned int** QImageScale::qimageCalcYPoints(const unsigned int *src,
return(p);
}
-int* QImageScale::qimageCalcXPoints(int sw, int dw)
+static int* QImageScale::qimageCalcXPoints(int sw, int dw)
{
int *p, j = 0, rv = 0;
qint64 val, inc;
@@ -167,7 +167,7 @@ int* QImageScale::qimageCalcXPoints(int sw, int dw)
return p;
}
-int* QImageScale::qimageCalcApoints(int s, int d, int up)
+static int* QImageScale::qimageCalcApoints(int s, int d, int up)
{
int *p, j = 0, rv = 0;
@@ -214,7 +214,7 @@ int* QImageScale::qimageCalcApoints(int s, int d, int up)
return p;
}
-QImageScaleInfo* QImageScale::qimageFreeScaleInfo(QImageScaleInfo *isi)
+static QImageScaleInfo* QImageScale::qimageFreeScaleInfo(QImageScaleInfo *isi)
{
if (isi) {
delete[] isi->xpoints;
@@ -226,9 +226,9 @@ QImageScaleInfo* QImageScale::qimageFreeScaleInfo(QImageScaleInfo *isi)
return 0;
}
-QImageScaleInfo* QImageScale::qimageCalcScaleInfo(const QImage &img,
- int sw, int sh,
- int dw, int dh, char aa)
+static QImageScaleInfo* QImageScale::qimageCalcScaleInfo(const QImage &img,
+ int sw, int sh,
+ int dw, int dh, char aa)
{
QImageScaleInfo *isi;
int scw, sch;
@@ -239,7 +239,6 @@ QImageScaleInfo* QImageScale::qimageCalcScaleInfo(const QImage &img,
isi = new QImageScaleInfo;
if (!isi)
return 0;
- memset(isi, 0, sizeof(QImageScaleInfo));
isi->xup_yup = (qAbs(dw) >= sw) + ((qAbs(dh) >= sh) << 1);
@@ -333,7 +332,7 @@ static void qt_qimageScaleAARGBA_up_xy(QImageScaleInfo *isi, unsigned int *dest,
}
}
-/* scale by area sampling */
+/* scale by area sampling - with alpha */
static void qt_qimageScaleAARGBA(QImageScaleInfo *isi, unsigned int *dest,
int dw, int dh, int dow, int sow)
{
@@ -529,6 +528,207 @@ static void qt_qimageScaleAARGBA_down_xy(QImageScaleInfo *isi, unsigned int *des
}
}
+static void qt_qimageScaleRgba64_up_x_down_y(QImageScaleInfo *isi, QRgba64 *dest,
+ int dw, int dh, int dow, int sow);
+
+static void qt_qimageScaleRgba64_down_x_up_y(QImageScaleInfo *isi, QRgba64 *dest,
+ int dw, int dh, int dow, int sow);
+
+static void qt_qimageScaleRgba64_down_xy(QImageScaleInfo *isi, QRgba64 *dest,
+ int dw, int dh, int dow, int sow);
+
+static void qt_qimageScaleRgba64_up_xy(QImageScaleInfo *isi, QRgba64 *dest,
+ int dw, int dh, int dow, int sow)
+{
+ const QRgba64 **ypoints = (const QRgba64 **)isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ for (int y = 0; y < dh; y++) {
+ const QRgba64 *sptr = ypoints[y];
+ QRgba64 *dptr = dest + (y * dow);
+ const int yap = yapoints[y];
+ if (yap > 0) {
+ for (int x = 0; x < dw; x++) {
+ const QRgba64 *pix = sptr + xpoints[x];
+ const int xap = xapoints[x];
+ if (xap > 0)
+ *dptr = interpolate_4_pixels_rgb64(pix, pix + sow, xap * 256, yap * 256);
+ else
+ *dptr = interpolate256(pix[0], 256 - yap, pix[sow], yap);
+ dptr++;
+ }
+ } else {
+ for (int x = 0; x < dw; x++) {
+ const QRgba64 *pix = sptr + xpoints[x];
+ const int xap = xapoints[x];
+ if (xap > 0)
+ *dptr = interpolate256(pix[0], 256 - xap, pix[1], xap);
+ else
+ *dptr = pix[0];
+ dptr++;
+ }
+ }
+ }
+}
+
+void qt_qimageScaleRgba64(QImageScaleInfo *isi, QRgba64 *dest,
+ int dw, int dh, int dow, int sow)
+{
+ if (isi->xup_yup == 3)
+ qt_qimageScaleRgba64_up_xy(isi, dest, dw, dh, dow, sow);
+ else if (isi->xup_yup == 1)
+ qt_qimageScaleRgba64_up_x_down_y(isi, dest, dw, dh, dow, sow);
+ else if (isi->xup_yup == 2)
+ qt_qimageScaleRgba64_down_x_up_y(isi, dest, dw, dh, dow, sow);
+ else
+ qt_qimageScaleRgba64_down_xy(isi, dest, dw, dh, dow, sow);
+}
+
+inline static void qt_qimageScaleRgba64_helper(const QRgba64 *pix, int xyap, int Cxy, int step, qint64 &r, qint64 &g, qint64 &b, qint64 &a)
+{
+ r = pix->red() * xyap;
+ g = pix->green() * xyap;
+ b = pix->blue() * xyap;
+ a = pix->alpha() * xyap;
+ int j;
+ for (j = (1 << 14) - xyap; j > Cxy; j -= Cxy ){
+ pix += step;
+ r += pix->red() * Cxy;
+ g += pix->green() * Cxy;
+ b += pix->blue() * Cxy;
+ a += pix->alpha() * Cxy;
+ }
+ pix += step;
+ r += pix->red() * j;
+ g += pix->green() * j;
+ b += pix->blue() * j;
+ a += pix->alpha() * j;
+}
+
+static void qt_qimageScaleRgba64_up_x_down_y(QImageScaleInfo *isi, QRgba64 *dest,
+ int dw, int dh, int dow, int sow)
+{
+ const QRgba64 **ypoints = (const QRgba64 **)isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ for (int y = 0; y < dh; y++) {
+ int Cy = (yapoints[y]) >> 16;
+ int yap = (yapoints[y]) & 0xffff;
+
+ QRgba64 *dptr = dest + (y * dow);
+ for (int x = 0; x < dw; x++) {
+ const QRgba64 *sptr = ypoints[y] + xpoints[x];
+ qint64 r, g, b, a;
+ qt_qimageScaleRgba64_helper(sptr, yap, Cy, sow, r, g, b, a);
+
+ int xap = xapoints[x];
+ if (xap > 0) {
+ qint64 rr, gg, bb, aa;
+ qt_qimageScaleRgba64_helper(sptr + 1, yap, Cy, sow, rr, gg, bb, aa);
+
+ r = r * (256 - xap);
+ g = g * (256 - xap);
+ b = b * (256 - xap);
+ a = a * (256 - xap);
+ r = (r + (rr * xap)) >> 8;
+ g = (g + (gg * xap)) >> 8;
+ b = (b + (bb * xap)) >> 8;
+ a = (a + (aa * xap)) >> 8;
+ }
+ *dptr++ = qRgba64(r >> 14, g >> 14, b >> 14, a >> 14);
+ }
+ }
+}
+
+static void qt_qimageScaleRgba64_down_x_up_y(QImageScaleInfo *isi, QRgba64 *dest,
+ int dw, int dh, int dow, int sow)
+{
+ const QRgba64 **ypoints = (const QRgba64 **)isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ for (int y = 0; y < dh; y++) {
+ QRgba64 *dptr = dest + (y * dow);
+ for (int x = 0; x < dw; x++) {
+ int Cx = xapoints[x] >> 16;
+ int xap = xapoints[x] & 0xffff;
+
+ const QRgba64 *sptr = ypoints[y] + xpoints[x];
+ qint64 r, g, b, a;
+ qt_qimageScaleRgba64_helper(sptr, xap, Cx, 1, r, g, b, a);
+
+ int yap = yapoints[y];
+ if (yap > 0) {
+ qint64 rr, gg, bb, aa;
+ qt_qimageScaleRgba64_helper(sptr + sow, xap, Cx, 1, rr, gg, bb, aa);
+
+ r = r * (256 - yap);
+ g = g * (256 - yap);
+ b = b * (256 - yap);
+ a = a * (256 - yap);
+ r = (r + (rr * yap)) >> 8;
+ g = (g + (gg * yap)) >> 8;
+ b = (b + (bb * yap)) >> 8;
+ a = (a + (aa * yap)) >> 8;
+ }
+ *dptr = qRgba64(r >> 14, g >> 14, b >> 14, a >> 14);
+ dptr++;
+ }
+ }
+}
+
+static void qt_qimageScaleRgba64_down_xy(QImageScaleInfo *isi, QRgba64 *dest,
+ int dw, int dh, int dow, int sow)
+{
+ const QRgba64 **ypoints = (const QRgba64 **)isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ for (int y = 0; y < dh; y++) {
+ int Cy = (yapoints[y]) >> 16;
+ int yap = (yapoints[y]) & 0xffff;
+
+ QRgba64 *dptr = dest + (y * dow);
+ for (int x = 0; x < dw; x++) {
+ int Cx = xapoints[x] >> 16;
+ int xap = xapoints[x] & 0xffff;
+
+ const QRgba64 *sptr = ypoints[y] + xpoints[x];
+ qint64 rx, gx, bx, ax;
+ qt_qimageScaleRgba64_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
+
+ qint64 r = rx * yap;
+ qint64 g = gx * yap;
+ qint64 b = bx * yap;
+ qint64 a = ax * yap;
+ int j;
+ for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
+ sptr += sow;
+ qt_qimageScaleRgba64_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
+ r += rx * Cy;
+ g += gx * Cy;
+ b += bx * Cy;
+ a += ax * Cy;
+ }
+ sptr += sow;
+ qt_qimageScaleRgba64_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
+ r += rx * j;
+ g += gx * j;
+ b += bx * j;
+ a += ax * j;
+
+ *dptr = qRgba64(r >> 28, g >> 28, b >> 28, a >> 28);
+ dptr++;
+ }
+ }
+}
+
static void qt_qimageScaleAARGB_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest,
int dw, int dh, int dow, int sow);
@@ -745,7 +945,10 @@ QImage qSmoothScaleImage(const QImage &src, int dw, int dh)
return QImage();
}
- if (src.hasAlphaChannel())
+ if (src.depth() > 32)
+ qt_qimageScaleRgba64(scaleinfo, (QRgba64 *)buffer.scanLine(0),
+ dw, dh, dw, src.bytesPerLine() / 8);
+ else if (src.hasAlphaChannel())
qt_qimageScaleAARGBA(scaleinfo, (unsigned int *)buffer.scanLine(0),
dw, dh, dw, src.bytesPerLine() / 4);
else
diff --git a/src/gui/painting/qimagescale_p.h b/src/gui/painting/qimagescale_p.h
index 415623a575..244d681718 100644
--- a/src/gui/painting/qimagescale_p.h
+++ b/src/gui/painting/qimagescale_p.h
@@ -61,10 +61,11 @@ QImage qSmoothScaleImage(const QImage &img, int w, int h);
namespace QImageScale {
struct QImageScaleInfo {
- int *xpoints;
- const unsigned int **ypoints;
- int *xapoints, *yapoints;
- int xup_yup;
+ int *xpoints{nullptr};
+ const unsigned int **ypoints{nullptr};
+ int *xapoints{nullptr};
+ int *yapoints{nullptr};
+ int xup_yup{0};
};
}
diff --git a/src/gui/painting/qmemrotate.cpp b/src/gui/painting/qmemrotate.cpp
index 25aa6a3122..43aeff3268 100644
--- a/src/gui/painting/qmemrotate.cpp
+++ b/src/gui/painting/qmemrotate.cpp
@@ -239,6 +239,12 @@ inline void qt_memrotate90_template<quint32>(const quint32 *src, int w, int h, i
qt_memrotate90_tiled_unpacked(src, w, h, sstride, dest, dstride);
}
+template <>
+inline void qt_memrotate90_template<quint64>(const quint64 *src, int w, int h, int sstride, quint64 *dest, int dstride)
+{
+ qt_memrotate90_tiled_unpacked(src, w, h, sstride, dest, dstride);
+}
+
template <class T>
Q_STATIC_TEMPLATE_FUNCTION
inline void qt_memrotate180_template(const T *src, int w, int h, int sstride, T *dest, int dstride)
@@ -275,6 +281,12 @@ inline void qt_memrotate270_template<quint32>(const quint32 *src, int w, int h,
qt_memrotate270_tiled_unpacked(src, w, h, sstride, dest, dstride);
}
+template <>
+inline void qt_memrotate270_template<quint64>(const quint64 *src, int w, int h, int sstride, quint64 *dest, int dstride)
+{
+ qt_memrotate270_tiled_unpacked(src, w, h, sstride, dest, dstride);
+}
+
#define QT_IMPL_MEMROTATE(type) \
Q_GUI_EXPORT void qt_memrotate90(const type *src, int w, int h, int sstride, \
type *dest, int dstride) \
@@ -309,9 +321,7 @@ Q_GUI_EXPORT void qt_memrotate270(const type *src, int w, int h, int sstride, \
qt_memrotate270_tiled_unpacked(src, w, h, sstride, dest, dstride); \
}
-
-
-
+QT_IMPL_MEMROTATE(quint64)
QT_IMPL_MEMROTATE(quint32)
QT_IMPL_MEMROTATE(quint16)
QT_IMPL_MEMROTATE(quint24)
@@ -377,6 +387,22 @@ void qt_memrotate270_32(const uchar *srcPixels, int w, int h, int sbpl, uchar *d
qt_memrotate270((const uint *)srcPixels, w, h, sbpl, (uint *)destPixels, dbpl);
}
+
+void qt_memrotate90_64(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
+{
+ qt_memrotate90((const quint64 *)srcPixels, w, h, sbpl, (quint64 *)destPixels, dbpl);
+}
+
+void qt_memrotate180_64(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
+{
+ qt_memrotate180((const quint64 *)srcPixels, w, h, sbpl, (quint64 *)destPixels, dbpl);
+}
+
+void qt_memrotate270_64(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl)
+{
+ qt_memrotate270((const quint64 *)srcPixels, w, h, sbpl, (quint64 *)destPixels, dbpl);
+}
+
MemRotateFunc qMemRotateFunctions[QPixelLayout::BPPCount][3] =
// 90, 180, 270
{
@@ -387,6 +413,7 @@ MemRotateFunc qMemRotateFunctions[QPixelLayout::BPPCount][3] =
{ qt_memrotate90_16, qt_memrotate180_16, qt_memrotate270_16 }, // BPP16,
{ qt_memrotate90_24, qt_memrotate180_24, qt_memrotate270_24 }, // BPP24
{ qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 }, // BPP32
+ { qt_memrotate90_64, qt_memrotate180_64, qt_memrotate270_64 }, // BPP64
};
QT_END_NAMESPACE
diff --git a/src/gui/painting/qmemrotate_p.h b/src/gui/painting/qmemrotate_p.h
index 9bc3fd1010..677fd57af9 100644
--- a/src/gui/painting/qmemrotate_p.h
+++ b/src/gui/painting/qmemrotate_p.h
@@ -65,6 +65,7 @@ QT_DECL_MEMROTATE(quint32);
QT_DECL_MEMROTATE(quint16);
QT_DECL_MEMROTATE(quint24);
QT_DECL_MEMROTATE(quint8);
+QT_DECL_MEMROTATE(quint64);
#undef QT_DECL_MEMROTATE
diff --git a/src/gui/painting/qpagedpaintdevice.cpp b/src/gui/painting/qpagedpaintdevice.cpp
index 1c7d6471b6..72b2834470 100644
--- a/src/gui/painting/qpagedpaintdevice.cpp
+++ b/src/gui/painting/qpagedpaintdevice.cpp
@@ -42,6 +42,41 @@
QT_BEGIN_NAMESPACE
+class QDummyPagedPaintDevicePrivate : public QPagedPaintDevicePrivate
+{
+ bool setPageLayout(const QPageLayout &newPageLayout) override
+ {
+ m_pageLayout = newPageLayout;
+ return m_pageLayout.isEquivalentTo(newPageLayout);
+ }
+
+ bool setPageSize(const QPageSize &pageSize) override
+ {
+ m_pageLayout.setPageSize(pageSize);
+ return m_pageLayout.pageSize().isEquivalentTo(pageSize);
+ }
+
+ bool setPageOrientation(QPageLayout::Orientation orientation) override
+ {
+ m_pageLayout.setOrientation(orientation);
+ return m_pageLayout.orientation() == orientation;
+ }
+
+ bool setPageMargins(const QMarginsF &margins, QPageLayout::Unit units) override
+ {
+ m_pageLayout.setUnits(units);
+ m_pageLayout.setMargins(margins);
+ return m_pageLayout.margins() == margins && m_pageLayout.units() == units;
+ }
+
+ QPageLayout pageLayout() const override
+ {
+ return m_pageLayout;
+ }
+
+ QPageLayout m_pageLayout;
+};
+
QPagedPaintDevicePrivate::~QPagedPaintDevicePrivate()
{
}
@@ -61,9 +96,11 @@ QPagedPaintDevicePrivate::~QPagedPaintDevicePrivate()
/*!
Constructs a new paged paint device.
+
+ \deprecated
*/
QPagedPaintDevice::QPagedPaintDevice()
- : d(new QPagedPaintDevicePrivate)
+ : d(new QDummyPagedPaintDevicePrivate)
{
}
@@ -253,7 +290,8 @@ QPagedPaintDevicePrivate *QPagedPaintDevice::dd()
\value PdfVersion_A1b A PDF/A-1b compatible document is produced.
- \since 5.10
+ \value PdfVersion_1_6 A PDF 1.6 compatible document is produced.
+ This value was added in Qt 5.12.
*/
/*!
@@ -263,7 +301,7 @@ QPagedPaintDevicePrivate *QPagedPaintDevice::dd()
*/
void QPagedPaintDevice::setPageSize(PageSize size)
{
- d->m_pageLayout.setPageSize(QPageSize(QPageSize::PageSizeId(size)));
+ d->setPageSize(QPageSize(QPageSize::PageSizeId(size)));
}
/*!
@@ -271,7 +309,7 @@ void QPagedPaintDevice::setPageSize(PageSize size)
*/
QPagedPaintDevice::PageSize QPagedPaintDevice::pageSize() const
{
- return PageSize(d->m_pageLayout.pageSize().id());
+ return PageSize(d->pageLayout().pageSize().id());
}
/*!
@@ -282,7 +320,7 @@ QPagedPaintDevice::PageSize QPagedPaintDevice::pageSize() const
*/
void QPagedPaintDevice::setPageSizeMM(const QSizeF &size)
{
- d->m_pageLayout.setPageSize(QPageSize(size, QPageSize::Millimeter));
+ d->setPageSize(QPageSize(size, QPageSize::Millimeter));
}
/*!
@@ -290,7 +328,7 @@ void QPagedPaintDevice::setPageSizeMM(const QSizeF &size)
*/
QSizeF QPagedPaintDevice::pageSizeMM() const
{
- return d->m_pageLayout.pageSize().size(QPageSize::Millimeter);
+ return d->pageLayout().pageSize().size(QPageSize::Millimeter);
}
/*!
@@ -305,8 +343,7 @@ QSizeF QPagedPaintDevice::pageSizeMM() const
*/
void QPagedPaintDevice::setMargins(const Margins &margins)
{
- d->m_pageLayout.setUnits(QPageLayout::Millimeter);
- d->m_pageLayout.setMargins(QMarginsF(margins.left, margins.top, margins.right, margins.bottom));
+ d->setPageMargins(QMarginsF(margins.left, margins.top, margins.right, margins.bottom), QPageLayout::Millimeter);
}
/*!
@@ -318,7 +355,7 @@ void QPagedPaintDevice::setMargins(const Margins &margins)
*/
QPagedPaintDevice::Margins QPagedPaintDevice::margins() const
{
- QMarginsF margins = d->m_pageLayout.margins(QPageLayout::Millimeter);
+ QMarginsF margins = d->pageLayout().margins(QPageLayout::Millimeter);
Margins result;
result.left = margins.left();
result.top = margins.top();
@@ -413,7 +450,7 @@ bool QPagedPaintDevice::setPageOrientation(QPageLayout::Orientation orientation)
bool QPagedPaintDevice::setPageMargins(const QMarginsF &margins)
{
- return d->setPageMargins(margins);
+ return setPageMargins(margins, pageLayout().units());
}
/*!
@@ -458,23 +495,30 @@ QPageLayout QPagedPaintDevice::pageLayout() const
/*!
\internal
+ \deprecated
+
Returns the internal device page layout.
*/
QPageLayout QPagedPaintDevice::devicePageLayout() const
{
- return d->m_pageLayout;
+ qWarning("QPagedPaintDevice::devicePageLayout() is deprecated, just use QPagedPaintDevice::pageLayout()");
+ return d->pageLayout();
}
/*!
\internal
+ \deprecated
+
Returns the internal device page layout.
*/
QPageLayout &QPagedPaintDevice::devicePageLayout()
{
- return d->m_pageLayout;
+ qWarning("QPagedPaintDevice::devicePageLayout() is deprecated, you shouldn't be using this at all.");
+ static QPageLayout dummy;
+ return dummy;
}
QT_END_NAMESPACE
diff --git a/src/gui/painting/qpagedpaintdevice.h b/src/gui/painting/qpagedpaintdevice.h
index 66dd6fa8cf..1c37c17fa3 100644
--- a/src/gui/painting/qpagedpaintdevice.h
+++ b/src/gui/painting/qpagedpaintdevice.h
@@ -55,7 +55,7 @@ class QPagedPaintDevicePrivate;
class Q_GUI_EXPORT QPagedPaintDevice : public QPaintDevice
{
public:
- QPagedPaintDevice();
+ QT_DEPRECATED QPagedPaintDevice();
~QPagedPaintDevice();
virtual bool newPage() = 0;
@@ -213,7 +213,7 @@ public:
Envelope10 = Comm10E
};
- enum PdfVersion { PdfVersion_1_4, PdfVersion_A1b };
+ enum PdfVersion { PdfVersion_1_4, PdfVersion_A1b, PdfVersion_1_6 };
// ### Qt6 Make these virtual
bool setPageLayout(const QPageLayout &pageLayout);
@@ -243,8 +243,8 @@ public:
protected:
QPagedPaintDevice(QPagedPaintDevicePrivate *dd);
QPagedPaintDevicePrivate *dd();
- QPageLayout devicePageLayout() const;
- QPageLayout &devicePageLayout();
+ QT_DEPRECATED QPageLayout devicePageLayout() const;
+ QT_DEPRECATED QPageLayout &devicePageLayout();
friend class QPagedPaintDevicePrivate;
QPagedPaintDevicePrivate *d;
};
diff --git a/src/gui/painting/qpagedpaintdevice_p.h b/src/gui/painting/qpagedpaintdevice_p.h
index a993ea4cac..3a43bd7828 100644
--- a/src/gui/painting/qpagedpaintdevice_p.h
+++ b/src/gui/painting/qpagedpaintdevice_p.h
@@ -60,8 +60,7 @@ class Q_GUI_EXPORT QPagedPaintDevicePrivate
{
public:
QPagedPaintDevicePrivate()
- : m_pageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0, 0, 0, 0)),
- fromPage(0),
+ : fromPage(0),
toPage(0),
pageOrderAscending(true),
printSelectionOnly(false)
@@ -70,46 +69,19 @@ public:
virtual ~QPagedPaintDevicePrivate();
- // ### Qt6 Remove these and make public class methods virtual
- virtual bool setPageLayout(const QPageLayout &newPageLayout)
- {
- m_pageLayout = newPageLayout;
- return m_pageLayout.isEquivalentTo(newPageLayout);;
- }
- virtual bool setPageSize(const QPageSize &pageSize)
- {
- m_pageLayout.setPageSize(pageSize);
- return m_pageLayout.pageSize().isEquivalentTo(pageSize);
- }
+ virtual bool setPageLayout(const QPageLayout &newPageLayout) = 0;
- virtual bool setPageOrientation(QPageLayout::Orientation orientation)
- {
- m_pageLayout.setOrientation(orientation);
- return m_pageLayout.orientation() == orientation;
- }
+ virtual bool setPageSize(const QPageSize &pageSize) = 0;
- virtual bool setPageMargins(const QMarginsF &margins)
- {
- return setPageMargins(margins, m_pageLayout.units());
- }
+ virtual bool setPageOrientation(QPageLayout::Orientation orientation) = 0;
- virtual bool setPageMargins(const QMarginsF &margins, QPageLayout::Unit units)
- {
- m_pageLayout.setUnits(units);
- m_pageLayout.setMargins(margins);
- return m_pageLayout.margins() == margins && m_pageLayout.units() == units;
- }
+ virtual bool setPageMargins(const QMarginsF &margins, QPageLayout::Unit units) = 0;
- virtual QPageLayout pageLayout() const
- {
- return m_pageLayout;
- }
+ virtual QPageLayout pageLayout() const = 0;
static inline QPagedPaintDevicePrivate *get(QPagedPaintDevice *pd) { return pd->d; }
- QPageLayout m_pageLayout;
-
// These are currently required to keep QPrinter functionality working in QTextDocument::print()
int fromPage;
int toPage;
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index cade334ea6..7caaf3a8fa 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -2590,10 +2590,13 @@ void QRasterPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap,
if (image.depth() == 1)
image = d->rasterBuffer->colorizeBitmap(image, s->pen.color());
- if (s->matrix.type() > QTransform::TxTranslate) {
+ const qreal pixmapDevicePixelRatio = pixmap.devicePixelRatio();
+ if (s->matrix.type() > QTransform::TxTranslate || pixmapDevicePixelRatio > qreal(1.0)) {
QTransform copy = s->matrix;
copy.translate(r.x(), r.y());
copy.translate(-sr.x(), -sr.y());
+ const qreal inverseDpr = qreal(1.0) / pixmapDevicePixelRatio;
+ copy.scale(inverseDpr, inverseDpr);
d->image_filler_xform.clip = d->clip();
d->image_filler_xform.initTexture(&image, s->intOpacity, QTextureData::Tiled);
if (!d->image_filler_xform.blend)
diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
index 0643a7cbb6..9f07af92e4 100644
--- a/src/gui/painting/qpaintengineex.cpp
+++ b/src/gui/painting/qpaintengineex.cpp
@@ -948,6 +948,8 @@ void QPaintEngineEx::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, con
{
QBrush brush(state()->pen.color(), pixmap);
QTransform xform = QTransform::fromTranslate(r.x() - s.x(), r.y() - s.y());
+ if (!qFuzzyCompare(pixmap.devicePixelRatioF(), 1.0))
+ xform.scale(1.0/pixmap.devicePixelRatioF(), 1.0/pixmap.devicePixelRatioF());
brush.setTransform(xform);
qreal pts[] = { r.x(), r.y(),
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index b992e8f55d..b70b29e54e 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -190,6 +190,13 @@ void QPainterPrivate::checkEmulation()
if (pg && pg->coordinateMode() > QGradient::LogicalMode)
doEmulation = true;
+ if (state->brush.style() == Qt::TexturePattern) {
+ if (qHasPixmapTexture(state->brush))
+ doEmulation |= !qFuzzyCompare(state->brush.texture().devicePixelRatioF(), 1.0);
+ else
+ doEmulation |= !qFuzzyCompare(state->brush.textureImage().devicePixelRatioF(), 1.0);
+ }
+
if (doEmulation && extended->flags() & QPaintEngineEx::DoNotEmulate)
return;
@@ -523,7 +530,10 @@ static inline QBrush stretchGradientToUserSpace(const QBrush &brush, const QRect
g.setCoordinateMode(QGradient::LogicalMode);
QBrush b(g);
- b.setTransform(gradientToUser * b.transform());
+ if (brush.gradient()->coordinateMode() == QGradient::ObjectMode)
+ b.setTransform(b.transform() * gradientToUser);
+ else
+ b.setTransform(gradientToUser * b.transform());
return b;
}
@@ -562,7 +572,7 @@ void QPainterPrivate::drawStretchedGradient(const QPainterPath &path, DrawOperat
} else {
needsFill = true;
- if (brushMode == QGradient::ObjectBoundingMode) {
+ if (brushMode == QGradient::ObjectBoundingMode || brushMode == QGradient::ObjectMode) {
Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
boundingRect = path.boundingRect();
q->setBrush(stretchGradientToUserSpace(brush, boundingRect));
@@ -606,11 +616,11 @@ void QPainterPrivate::drawStretchedGradient(const QPainterPath &path, DrawOperat
changedBrush = true;
}
- if (penMode == QGradient::ObjectBoundingMode) {
+ if (penMode == QGradient::ObjectBoundingMode || penMode == QGradient::ObjectMode) {
Q_ASSERT(engine->hasFeature(QPaintEngine::PatternTransform));
// avoid computing the bounding rect twice
- if (!needsFill || brushMode != QGradient::ObjectBoundingMode)
+ if (!needsFill || (brushMode != QGradient::ObjectBoundingMode && brushMode != QGradient::ObjectMode))
boundingRect = path.boundingRect();
QPen p = pen;
@@ -842,8 +852,8 @@ void QPainterPrivate::updateEmulationSpecifier(QPainterState *s)
gradientStretch |= (brushMode == QGradient::StretchToDeviceMode);
gradientStretch |= (penMode == QGradient::StretchToDeviceMode);
- objectBoundingMode |= (brushMode == QGradient::ObjectBoundingMode);
- objectBoundingMode |= (penMode == QGradient::ObjectBoundingMode);
+ objectBoundingMode |= (brushMode == QGradient::ObjectBoundingMode || brushMode == QGradient::ObjectMode);
+ objectBoundingMode |= (penMode == QGradient::ObjectBoundingMode || penMode == QGradient::ObjectMode);
}
if (gradientStretch)
s->emulationSpecifier |= QGradient_StretchToDevice;
@@ -1287,7 +1297,7 @@ void QPainterPrivate::updateState(QPainterState *newState)
itself and its bounding rectangle: The bounding rect contains
pixels with alpha == 0 (i.e the pixels surrounding the
primitive). These pixels will overwrite the other image's pixels,
- affectively clearing those, while the primitive only overwrites
+ effectively clearing those, while the primitive only overwrites
its own area.
\table 100%
@@ -1377,7 +1387,7 @@ void QPainterPrivate::updateState(QPainterState *newState)
clip.
\li Composition Modes \c QPainter::CompositionMode_Source and
- QPainter::CompositionMode_SourceOver
+ QPainter::CompositionMode_SourceOver.
\li Rounded rectangle filling using solid color and two-color
linear gradients fills.
@@ -6657,6 +6667,16 @@ QRectF QPainter::boundingRect(const QRectF &r, const QString &text, const QTextO
potentially much more efficient depending on the underlying window
system.
+ drawTiledPixmap() will produce the same visual tiling pattern on
+ high-dpi displays (with devicePixelRatio > 1), compared to normal-
+ dpi displays. Set the devicePixelRatio on the \a pixmap to control
+ the tile size. For example, setting it to 2 halves the tile width
+ and height (on both 1x and 2x displays), and produces high-resolution
+ output on 2x displays.
+
+ The \a position offset is always in the painter coordinate system,
+ indepentent of display devicePixelRatio.
+
\sa drawPixmap()
*/
void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &sp)
@@ -6840,7 +6860,8 @@ static inline bool needsResolving(const QBrush &brush)
Qt::BrushStyle s = brush.style();
return ((s == Qt::LinearGradientPattern || s == Qt::RadialGradientPattern ||
s == Qt::ConicalGradientPattern) &&
- brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode);
+ (brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode ||
+ brush.gradient()->coordinateMode() == QGradient::ObjectMode));
}
/*!
@@ -7068,6 +7089,37 @@ void QPainter::fillRect(const QRectF &r, const QColor &color)
*/
/*!
+ \fn void QPainter::fillRect(int x, int y, int width, int height, QGradient::Preset preset)
+
+ \overload
+
+ Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a
+ width and \a height, using the given gradient \a preset.
+
+ \since 5.12
+*/
+
+/*!
+ \fn void QPainter::fillRect(const QRect &rectangle, QGradient::Preset preset);
+
+ \overload
+
+ Fills the given \a rectangle with the specified gradient \a preset.
+
+ \since 5.12
+*/
+
+/*!
+ \fn void QPainter::fillRect(const QRectF &rectangle, QGradient::Preset preset);
+
+ \overload
+
+ Fills the given \a rectangle with the specified gradient \a preset.
+
+ \since 5.12
+*/
+
+/*!
Sets the given render \a hint on the painter if \a on is true;
otherwise clears the render hint.
@@ -8207,6 +8259,7 @@ void QPainter::setTransform(const QTransform &transform, bool combine )
}
/*!
+ Alias for worldTransform().
Returns the world transformation matrix.
\sa worldTransform()
diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h
index 12a9c720a8..482f5fb63d 100644
--- a/src/gui/painting/qpainter.h
+++ b/src/gui/painting/qpainter.h
@@ -448,6 +448,10 @@ public:
inline void fillRect(const QRect &r, Qt::BrushStyle style);
inline void fillRect(const QRectF &r, Qt::BrushStyle style);
+ inline void fillRect(int x, int y, int w, int h, QGradient::Preset preset);
+ inline void fillRect(const QRect &r, QGradient::Preset preset);
+ inline void fillRect(const QRectF &r, QGradient::Preset preset);
+
void eraseRect(const QRectF &);
inline void eraseRect(int x, int y, int w, int h);
inline void eraseRect(const QRect &);
@@ -746,6 +750,20 @@ inline void QPainter::fillRect(const QRectF &r, Qt::BrushStyle style)
fillRect(r, QBrush(style));
}
+inline void QPainter::fillRect(int x, int y, int w, int h, QGradient::Preset p)
+{
+ fillRect(QRect(x, y, w, h), QGradient(p));
+}
+
+inline void QPainter::fillRect(const QRect &r, QGradient::Preset p)
+{
+ fillRect(r, QGradient(p));
+}
+
+inline void QPainter::fillRect(const QRectF &r, QGradient::Preset p)
+{
+ fillRect(r, QGradient(p));
+}
inline void QPainter::setBrushOrigin(int x, int y)
{
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index 2574a00838..c5ccf0003d 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -2476,7 +2476,7 @@ QDataStream &operator>>(QDataStream &s, QPainterPath &p)
s >> p.d_func()->cStart;
int fillRule;
s >> fillRule;
- Q_ASSERT(fillRule == Qt::OddEvenFill || Qt::WindingFill);
+ Q_ASSERT(fillRule == Qt::OddEvenFill || fillRule == Qt::WindingFill);
p.d_func()->fillRule = Qt::FillRule(fillRule);
p.d_func()->dirtyBounds = true;
p.d_func()->dirtyControlBounds = true;
diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp
index 8a0020bd2d..b410e9b900 100644
--- a/src/gui/painting/qpdf.cpp
+++ b/src/gui/painting/qpdf.cpp
@@ -1114,8 +1114,9 @@ void QPdfEngine::updateState(const QPaintEngineState &state)
d->hasPen = d->pen.style() != Qt::NoPen;
d->stroker.setPen(d->pen, state.renderHints());
QBrush penBrush = d->pen.brush();
+ bool cosmeticPen = qt_pen_is_cosmetic(d->pen, state.renderHints());
bool oldSimple = d->simplePen;
- d->simplePen = (d->hasPen && (penBrush.style() == Qt::SolidPattern) && penBrush.isOpaque() && d->opacity == 1.0);
+ d->simplePen = (d->hasPen && !cosmeticPen && (penBrush.style() == Qt::SolidPattern) && penBrush.isOpaque() && d->opacity == 1.0);
if (oldSimple != d->simplePen)
flags |= DirtyTransform;
} else if (flags & DirtyHints) {
@@ -1546,7 +1547,14 @@ void QPdfEnginePrivate::writeHeader()
{
addXrefEntry(0,false);
- xprintf("%%PDF-1.4\n");
+ static const QHash<QPdfEngine::PdfVersion, const char *> mapping {
+ {QPdfEngine::Version_1_4, "1.4"},
+ {QPdfEngine::Version_A1b, "1.4"},
+ {QPdfEngine::Version_1_6, "1.6"}
+ };
+ const char *verStr = mapping.value(pdfVersion, "1.4");
+
+ xprintf("%%PDF-%s\n", verStr);
xprintf("%%\303\242\303\243\n");
writeInfo();
@@ -1879,6 +1887,19 @@ void QPdfEnginePrivate::embedFont(QFontSubset *font)
}
}
+qreal QPdfEnginePrivate::calcUserUnit() const
+{
+ // PDF standards < 1.6 support max 200x200in pages (no UserUnit)
+ if (pdfVersion < QPdfEngine::Version_1_6)
+ return 1.0;
+
+ const int maxLen = qMax(currentPage->pageSize.width(), currentPage->pageSize.height());
+ if (maxLen <= 14400)
+ return 1.0; // for pages up to 200x200in (14400x14400 units) use default scaling
+
+ // for larger pages, rescale units so we can have up to 381x381km
+ return qMin(maxLen / 14400.0, 75000.0);
+}
void QPdfEnginePrivate::writeFonts()
{
@@ -1901,6 +1922,8 @@ void QPdfEnginePrivate::writePage()
uint resources = requestObject();
uint annots = requestObject();
+ qreal userUnit = calcUserUnit();
+
addXrefEntry(pages.constLast());
xprintf("<<\n"
"/Type /Page\n"
@@ -1908,12 +1931,16 @@ void QPdfEnginePrivate::writePage()
"/Contents %d 0 R\n"
"/Resources %d 0 R\n"
"/Annots %d 0 R\n"
- "/MediaBox [0 0 %d %d]\n"
- ">>\n"
- "endobj\n",
+ "/MediaBox [0 0 %f %f]\n",
pageRoot, pageStream, resources, annots,
// make sure we use the pagesize from when we started the page, since the user may have changed it
- currentPage->pageSize.width(), currentPage->pageSize.height());
+ currentPage->pageSize.width() / userUnit, currentPage->pageSize.height() / userUnit);
+
+ if (pdfVersion >= QPdfEngine::Version_1_6)
+ xprintf("/UserUnit %f\n", userUnit);
+
+ xprintf(">>\n"
+ "endobj\n");
addXrefEntry(resources);
xprintf("<<\n"
@@ -2982,8 +3009,9 @@ void QPdfEnginePrivate::drawTextItem(const QPointF &p, const QTextItemInt &ti)
QTransform QPdfEnginePrivate::pageMatrix() const
{
- qreal scale = 72./resolution;
- QTransform tmp(scale, 0.0, 0.0, -scale, 0.0, m_pageLayout.fullRectPoints().height());
+ qreal userUnit = calcUserUnit();
+ qreal scale = 72. / userUnit / resolution;
+ QTransform tmp(scale, 0.0, 0.0, -scale, 0.0, m_pageLayout.fullRectPoints().height() / userUnit);
if (m_pageLayout.mode() != QPageLayout::FullPageMode) {
QRect r = m_pageLayout.paintRectPixels(resolution);
tmp.translate(r.left(), r.top());
diff --git a/src/gui/painting/qpdf_p.h b/src/gui/painting/qpdf_p.h
index 5a909f2ede..e2526de67d 100644
--- a/src/gui/painting/qpdf_p.h
+++ b/src/gui/painting/qpdf_p.h
@@ -171,7 +171,8 @@ public:
enum PdfVersion
{
Version_1_4,
- Version_A1b
+ Version_A1b,
+ Version_1_6
};
QPdfEngine();
@@ -300,6 +301,7 @@ private:
void writePageRoot();
void writeFonts();
void embedFont(QFontSubset *font);
+ qreal calcUserUnit() const;
QVector<int> xrefPositions;
QDataStream* stream;
diff --git a/src/gui/painting/qpdfwriter.cpp b/src/gui/painting/qpdfwriter.cpp
index 2f24c7efcb..6c85d65538 100644
--- a/src/gui/painting/qpdfwriter.cpp
+++ b/src/gui/painting/qpdfwriter.cpp
@@ -83,41 +83,28 @@ public:
{
// Try to set the paint engine page layout
pd->engine->setPageLayout(newPageLayout);
- // Set QPagedPaintDevice layout to match the current paint engine layout
- m_pageLayout = pd->engine->pageLayout();
- return m_pageLayout.isEquivalentTo(newPageLayout);
+ return pageLayout().isEquivalentTo(newPageLayout);
}
bool setPageSize(const QPageSize &pageSize) override
{
// Try to set the paint engine page size
pd->engine->setPageSize(pageSize);
- // Set QPagedPaintDevice layout to match the current paint engine layout
- m_pageLayout = pd->engine->pageLayout();
- return m_pageLayout.pageSize().isEquivalentTo(pageSize);
+ return pageLayout().pageSize().isEquivalentTo(pageSize);
}
bool setPageOrientation(QPageLayout::Orientation orientation) override
{
// Set the print engine value
pd->engine->setPageOrientation(orientation);
- // Set QPagedPaintDevice layout to match the current paint engine layout
- m_pageLayout = pd->engine->pageLayout();
- return m_pageLayout.orientation() == orientation;
- }
-
- bool setPageMargins(const QMarginsF &margins) override
- {
- return setPageMargins(margins, pageLayout().units());
+ return pageLayout().orientation() == orientation;
}
bool setPageMargins(const QMarginsF &margins, QPageLayout::Unit units) override
{
// Try to set engine margins
pd->engine->setPageMargins(margins, units);
- // Set QPagedPaintDevice layout to match the current paint engine layout
- m_pageLayout = pd->engine->pageLayout();
- return m_pageLayout.margins() == margins && m_pageLayout.units() == units;
+ return pageLayout().margins() == margins && pageLayout().units() == units;
}
QPageLayout pageLayout() const override
@@ -150,9 +137,6 @@ QPdfWriter::QPdfWriter(const QString &filename)
Q_D(QPdfWriter);
d->engine->setOutputFilename(filename);
-
- // Set QPagedPaintDevice layout to match the current paint engine layout
- devicePageLayout() = d->engine->pageLayout();
}
/*!
@@ -165,9 +149,6 @@ QPdfWriter::QPdfWriter(QIODevice *device)
Q_D(QPdfWriter);
d->engine->d_func()->outDevice = device;
-
- // Set QPagedPaintDevice layout to match the current paint engine layout
- devicePageLayout() = d->engine->pageLayout();
}
/*!
@@ -189,11 +170,17 @@ void QPdfWriter::setPdfVersion(PdfVersion version)
{
Q_D(QPdfWriter);
+ static const QHash<QPdfWriter::PdfVersion, QPdfEngine::PdfVersion> engineMapping {
+ {QPdfWriter::PdfVersion_1_4, QPdfEngine::Version_1_4},
+ {QPdfWriter::PdfVersion_A1b, QPdfEngine::Version_A1b},
+ {QPdfWriter::PdfVersion_1_6, QPdfEngine::Version_1_6}
+ };
+
if (d->pdfVersion == version)
return;
d->pdfVersion = version;
- d->engine->setPdfVersion(d->pdfVersion == QPdfWriter::PdfVersion_1_4 ? QPdfEngine::Version_1_4 : QPdfEngine::Version_A1b);
+ d->engine->setPdfVersion(engineMapping.value(version, QPdfEngine::Version_1_4));
}
/*!
diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp
index cc8d850689..373722cdb4 100644
--- a/src/gui/painting/qplatformbackingstore.cpp
+++ b/src/gui/painting/qplatformbackingstore.cpp
@@ -80,6 +80,8 @@
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcQpaBackingStore, "qt.qpa.backingstore", QtWarningMsg);
+
class QPlatformBackingStorePrivate
{
public:
@@ -331,16 +333,19 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
d_ptr->context->setScreen(d_ptr->window->screen());
d_ptr->context->setShareContext(qt_window_private(d_ptr->window)->shareContext());
if (!d_ptr->context->create()) {
- qWarning("composeAndFlush: QOpenGLContext creation failed");
+ qCWarning(lcQpaBackingStore, "composeAndFlush: QOpenGLContext creation failed");
return;
}
}
if (!d_ptr->context->makeCurrent(window)) {
- qWarning("composeAndFlush: makeCurrent() failed");
+ qCWarning(lcQpaBackingStore, "composeAndFlush: makeCurrent() failed");
return;
}
+ qCDebug(lcQpaBackingStore) << "Composing and flushing" << region << "of" << window
+ << "at offset" << offset << "with" << textures->count() << "texture(s) in" << textures;
+
QWindowPrivate::get(window)->lastComposeTime.start();
QOpenGLFunctions *funcs = d_ptr->context->functions();
diff --git a/src/gui/painting/qplatformbackingstore.h b/src/gui/painting/qplatformbackingstore.h
index 381c564079..de5ba964dc 100644
--- a/src/gui/painting/qplatformbackingstore.h
+++ b/src/gui/painting/qplatformbackingstore.h
@@ -50,6 +50,7 @@
//
#include <QtGui/qtguiglobal.h>
+#include <QtCore/qloggingcategory.h>
#include <QtCore/qrect.h>
#include <QtCore/qobject.h>
@@ -59,6 +60,7 @@
QT_BEGIN_NAMESPACE
+Q_GUI_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcQpaBackingStore)
class QRegion;
class QRect;
diff --git a/src/gui/painting/qrgba64.h b/src/gui/painting/qrgba64.h
index 2c8f8fa8c4..0e5344cacb 100644
--- a/src/gui/painting/qrgba64.h
+++ b/src/gui/painting/qrgba64.h
@@ -127,6 +127,10 @@ public:
Q_DECL_RELAXED_CONSTEXPR QRgba64 premultiplied() const
{
+ if (isOpaque())
+ return *this;
+ if (isTransparent())
+ return QRgba64::fromRgba64(0);
const quint32 a = alpha();
const quint16 r = div_65535(red() * a);
const quint16 g = div_65535(green() * a);
diff --git a/src/gui/painting/qrgba64_p.h b/src/gui/painting/qrgba64_p.h
index adceda2210..b7e4d4d905 100644
--- a/src/gui/painting/qrgba64_p.h
+++ b/src/gui/painting/qrgba64_p.h
@@ -51,10 +51,11 @@
// We mean it.
//
+#include "qrgba64.h"
+#include "qdrawhelper_p.h"
+
+#include <QtCore/private/qsimd_p.h>
#include <QtGui/private/qtguiglobal_p.h>
-#include <QtGui/qrgba64.h>
-#include <QtGui/private/qdrawhelper_p.h>
-#include <private/qsimd_p.h>
QT_BEGIN_NAMESPACE
@@ -63,14 +64,6 @@ inline QRgba64 combineAlpha256(QRgba64 rgba64, uint alpha256)
return QRgba64::fromRgba64(rgba64.red(), rgba64.green(), rgba64.blue(), (rgba64.alpha() * alpha256) >> 8);
}
-inline QRgba64 multiplyAlpha256(QRgba64 rgba64, uint alpha256)
-{
- return QRgba64::fromRgba64((rgba64.red() * alpha256) >> 8,
- (rgba64.green() * alpha256) >> 8,
- (rgba64.blue() * alpha256) >> 8,
- (rgba64.alpha() * alpha256) >> 8);
-}
-
inline QRgba64 multiplyAlpha65535(QRgba64 rgba64, uint alpha65535)
{
return QRgba64::fromRgba64(qt_div_65535(rgba64.red() * alpha65535),
@@ -125,11 +118,6 @@ inline T multiplyAlpha255(T rgba64, uint alpha255)
#endif
}
-inline QRgba64 interpolate256(QRgba64 x, uint alpha1, QRgba64 y, uint alpha2)
-{
- return QRgba64::fromRgba64(multiplyAlpha256(x, alpha1) + multiplyAlpha256(y, alpha2));
-}
-
inline QRgba64 interpolate255(QRgba64 x, uint alpha1, QRgba64 y, uint alpha2)
{
return QRgba64::fromRgba64(multiplyAlpha255(x, alpha1) + multiplyAlpha255(y, alpha2));
@@ -159,7 +147,7 @@ Q_ALWAYS_INLINE __m128i interpolate65535(__m128i x, uint alpha1, __m128i y, uint
{
return _mm_add_epi32(multiplyAlpha65535(x, alpha1), multiplyAlpha65535(y, alpha2));
}
-// alpha2 below is const-ref because otherwise MSVC2013 complains that it can't 16-byte align the argument.
+// alpha2 below is const-ref because otherwise MSVC2015 complains that it can't 16-byte align the argument.
Q_ALWAYS_INLINE __m128i interpolate65535(__m128i x, __m128i alpha1, __m128i y, const __m128i &alpha2)
{
return _mm_add_epi32(multiplyAlpha65535(x, alpha1), multiplyAlpha65535(y, alpha2));
@@ -185,7 +173,8 @@ inline QRgba64 addWithSaturation(QRgba64 a, QRgba64 b)
qMin(a.alpha() + b.alpha(), 65535));
}
-#if defined __SSE2__
+#if QT_COMPILER_SUPPORTS_HERE(SSE2)
+QT_FUNCTION_TARGET(SSE2)
Q_ALWAYS_INLINE uint toArgb32(__m128i v)
{
v = _mm_unpacklo_epi16(v, _mm_setzero_si128());
@@ -239,20 +228,6 @@ inline uint toRgba8888(QRgba64 rgba64)
#endif
}
-#if defined(__SSE2__)
-Q_ALWAYS_INLINE __m128i addWithSaturation(__m128i a, __m128i b)
-{
- return _mm_adds_epu16(a, b);
-}
-#endif
-
-#if defined(__ARM_NEON__)
-Q_ALWAYS_INLINE uint16x4_t addWithSaturation(uint16x4_t a, uint16x4_t b)
-{
- return vqmovn_u32(vaddl_u16(a, b));
-}
-#endif
-
inline QRgba64 rgbBlend(QRgba64 d, QRgba64 s, uint rgbAlpha)
{
QRgba64 blend;
diff --git a/src/gui/painting/qt_attribution.json b/src/gui/painting/qt_attribution.json
index 7eb7db4876..9d3debc1b9 100644
--- a/src/gui/painting/qt_attribution.json
+++ b/src/gui/painting/qt_attribution.json
@@ -27,5 +27,19 @@
"Copyright": "Copyright (C) 2004, 2005 Daniel M. Duley.
(C) Carsten Haitzler and various contributors.
(C) Willem Monsuwe <willem@stack.nl>"
+ },
+ {
+ "Id": "webgradients",
+ "Name": "WebGradients",
+ "QDocModule": "qtgui",
+ "QtUsage": "Used in Qt GUI to provide presets for QGradient.",
+ "Files": "webgradients.css",
+
+ "Description": "WebGradients is a free collection of 180 linear gradients.",
+ "Homepage": "https://webgradients.com/",
+ "License": "MIT License",
+ "LicenseId": "MIT",
+ "LicenseFile": "WEBGRADIENTS_LICENSE.txt",
+ "Copyright": "Copyright (c) 2017 itmeo"
}
]
diff --git a/src/gui/painting/qtriangulator.cpp b/src/gui/painting/qtriangulator.cpp
index 6d57eba123..9be3eeaffd 100644
--- a/src/gui/painting/qtriangulator.cpp
+++ b/src/gui/painting/qtriangulator.cpp
@@ -472,7 +472,7 @@ class QInt64Set
{
public:
inline QInt64Set(int capacity = 64);
- inline ~QInt64Set() {if (m_array) delete[] m_array;}
+ inline ~QInt64Set() {delete[] m_array;}
inline bool isValid() const {return m_array;}
void insert(quint64 key);
bool contains(quint64 key) const;
@@ -493,10 +493,7 @@ inline QInt64Set::QInt64Set(int capacity)
{
m_capacity = primeForCount(capacity);
m_array = new quint64[m_capacity];
- if (m_array)
- clear();
- else
- m_capacity = 0;
+ clear();
}
bool QInt64Set::rehash(int capacity)
@@ -506,28 +503,19 @@ bool QInt64Set::rehash(int capacity)
m_capacity = capacity;
m_array = new quint64[m_capacity];
- if (m_array) {
- clear();
- if (oldArray) {
- for (int i = 0; i < oldCapacity; ++i) {
- if (oldArray[i] != UNUSED)
- insert(oldArray[i]);
- }
- delete[] oldArray;
- }
- return true;
- } else {
- m_capacity = oldCapacity;
- m_array = oldArray;
- return false;
+ clear();
+ for (int i = 0; i < oldCapacity; ++i) {
+ if (oldArray[i] != UNUSED)
+ insert(oldArray[i]);
}
+ delete[] oldArray;
+ return true;
}
void QInt64Set::insert(quint64 key)
{
if (m_count > 3 * m_capacity / 4)
rehash(primeForCount(2 * m_capacity));
- Q_ASSERT_X(m_array, "QInt64Hash<T>::insert", "Hash set not allocated.");
int index = int(key % m_capacity);
for (int i = 0; i < m_capacity; ++i) {
index += i;
@@ -546,7 +534,6 @@ void QInt64Set::insert(quint64 key)
bool QInt64Set::contains(quint64 key) const
{
- Q_ASSERT_X(m_array, "QInt64Hash<T>::contains", "Hash set not allocated.");
int index = int(key % m_capacity);
for (int i = 0; i < m_capacity; ++i) {
index += i;
@@ -562,7 +549,6 @@ bool QInt64Set::contains(quint64 key) const
inline void QInt64Set::clear()
{
- Q_ASSERT_X(m_array, "QInt64Hash<T>::clear", "Hash set not allocated.");
for (int i = 0; i < m_capacity; ++i)
m_array[i] = UNUSED;
m_count = 0;
diff --git a/src/gui/painting/webgradients.binaryjson b/src/gui/painting/webgradients.binaryjson
new file mode 100644
index 0000000000..75edd487be
--- /dev/null
+++ b/src/gui/painting/webgradients.binaryjson
Binary files differ
diff --git a/src/gui/painting/webgradients.css b/src/gui/painting/webgradients.css
new file mode 100644
index 0000000000..870866bb46
--- /dev/null
+++ b/src/gui/painting/webgradients.css
@@ -0,0 +1,909 @@
+/*001 Warm Flame*/
+.warm_flame{
+ background-image: linear-gradient(45deg, #ff9a9e 0%, #fad0c4 99%, #fad0c4 100%);
+}
+
+/*002 Night Fade*/
+.night_fade{
+ background-image: linear-gradient(to top, #a18cd1 0%, #fbc2eb 100%);
+}
+
+/*003 Spring Warmth*/
+.spring_warmth{
+ background-image: linear-gradient(to top, #fad0c4 0%, #fad0c4 1%, #ffd1ff 100%);
+}
+
+/*004 Juicy Peach*/
+.juicy_peach{
+ background-image: linear-gradient(to right, #ffecd2 0%, #fcb69f 100%);
+}
+
+/*005 Young Passion*/
+.young_passion{
+ background-image: linear-gradient(to right, #ff8177 0%, #ff867a 0%, #ff8c7f 21%, #f99185 52%, #cf556c 78%, #b12a5b 100%);
+}
+
+/*006 Lady Lips*/
+.lady_lips{
+ background-image: linear-gradient(to top, #ff9a9e 0%, #fecfef 99%, #fecfef 100%);
+}
+
+/*007 Sunny Morning*/
+.sunny_morning{
+ background-image: linear-gradient(120deg, #f6d365 0%, #fda085 100%);
+}
+
+/*008 Rainy Ashville*/
+.rainy_ashville{
+ background-image: linear-gradient(to top, #fbc2eb 0%, #a6c1ee 100%);
+}
+
+/*009 Frozen Dreams*/
+.frozen_dreams{
+ background-image: linear-gradient(to top, #fdcbf1 0%, #fdcbf1 1%, #e6dee9 100%);
+}
+
+/*010 Winter Neva*/
+.winter_neva{
+ background-image: linear-gradient(120deg, #a1c4fd 0%, #c2e9fb 100%);
+}
+
+/*011 Dusty Grass*/
+.dusty_grass{
+ background-image: linear-gradient(120deg, #d4fc79 0%, #96e6a1 100%);
+}
+
+/*012 Tempting Azure*/
+.tempting_azure{
+ background-image: linear-gradient(120deg, #84fab0 0%, #8fd3f4 100%);
+}
+
+/*013 Heavy Rain*/
+.heavy_rain{
+ background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%);
+}
+
+/*014 Amy Crisp*/
+.amy_crisp{
+ background-image: linear-gradient(120deg, #a6c0fe 0%, #f68084 100%);
+}
+
+/*015 Mean Fruit*/
+.mean_fruit{
+ background-image: linear-gradient(120deg, #fccb90 0%, #d57eeb 100%);
+}
+
+/*016 Deep Blue*/
+.deep_blue{
+ background-image: linear-gradient(120deg, #e0c3fc 0%, #8ec5fc 100%);
+}
+
+/*017 Ripe Malinka*/
+.ripe_malinka{
+ background-image: linear-gradient(120deg, #f093fb 0%, #f5576c 100%);
+}
+
+/*018 Cloudy Knoxville*/
+.cloudy_knoxville{
+ background-image: linear-gradient(120deg, #fdfbfb 0%, #ebedee 100%);
+}
+
+/*019 Malibu Beach*/
+.malibu_beach{
+ background-image: linear-gradient(to right, #4facfe 0%, #00f2fe 100%);
+}
+
+/*020 New Life*/
+.new_life{
+ background-image: linear-gradient(to right, #43e97b 0%, #38f9d7 100%);
+}
+
+/*021 True Sunset*/
+.true_sunset{
+ background-image: linear-gradient(to right, #fa709a 0%, #fee140 100%);
+}
+
+/*022 Morpheus Den*/
+.morpheus_den{
+ background-image: linear-gradient(to top, #30cfd0 0%, #330867 100%);
+}
+
+/*023 Rare Wind*/
+.rare_wind{
+ background-image: linear-gradient(to top, #a8edea 0%, #fed6e3 100%);
+}
+
+/*024 Near Moon*/
+.near_moon{
+ background-image: linear-gradient(to top, #5ee7df 0%, #b490ca 100%);
+}
+
+/*025 Wild Apple*/
+.wild_apple{
+ background-image: linear-gradient(to top, #d299c2 0%, #fef9d7 100%);
+}
+
+/*026 Saint Petersburg*/
+.saint_petersburg{
+ background-image: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
+}
+
+/*027 Arielle's Smile*/
+.arielles_smile{
+ background-image: radial-gradient(circle 248px at center, #16d9e3 0%, #30c7ec 47%, #46aef7 100%);
+}
+
+/*028 Plum Plate*/
+.plum_plate{
+ background-image: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+}
+
+/*029 Everlasting Sky*/
+.everlasting_sky{
+ background-image: linear-gradient(135deg, #fdfcfb 0%, #e2d1c3 100%);
+}
+
+/*030 Happy Fisher*/
+.happy_fisher{
+ background-image: linear-gradient(120deg, #89f7fe 0%, #66a6ff 100%);
+}
+
+/*031 Blessing*/
+.blessing{
+ background-image: linear-gradient(to top, #fddb92 0%, #d1fdff 100%);
+}
+
+/*032 Sharpeye Eagle*/
+.sharpeye_eagle{
+ background-image: linear-gradient(to top, #9890e3 0%, #b1f4cf 100%);
+}
+
+/*033 Ladoga Bottom*/
+.ladoga_bottom{
+ background-image: linear-gradient(to top, #ebc0fd 0%, #d9ded8 100%);
+}
+
+/*034 Lemon Gate*/
+.lemon_gate{
+ background-image: linear-gradient(to top, #96fbc4 0%, #f9f586 100%);
+}
+
+/*035 Itmeo Branding*/
+.itmeo_branding{
+ background-image: linear-gradient(180deg, #2af598 0%, #009efd 100%);
+}
+
+/*036 Zeus Miracle*/
+.zeus_miracle{
+ background-image: linear-gradient(to top, #cd9cf2 0%, #f6f3ff 100%);
+}
+
+/*037 Old Hat*/
+.old_hat{
+ background-image: linear-gradient(to right, #e4afcb 0%, #b8cbb8 0%, #b8cbb8 0%, #e2c58b 30%, #c2ce9c 64%, #7edbdc 100%);
+}
+
+/*038 Star Wine*/
+.star_wine{
+ background-image: linear-gradient(to right, #b8cbb8 0%, #b8cbb8 0%, #b465da 0%, #cf6cc9 33%, #ee609c 66%, #ee609c 100%);
+}
+
+/*039 Deep Blue*/
+.deep_blue{
+ background-image: linear-gradient(to right, #6a11cb 0%, #2575fc 100%);
+}
+
+/*040 Coup de Grace*/
+.coup_de_grace{
+ background: #DCD9D4 linear-gradient(to bottom, rgba(255, 255, 255, 0.50) 0%, rgba(0, 0, 0, 0.50) 100%), radial-gradient(at 50% 0%, rgba(255, 255, 255, 0.10) 0%, rgba(0, 0, 0, 0.50) 50%);
+ background-blend-mode: soft-light,screen;
+}
+
+/*041 Happy Acid*/
+.happy_acid{
+ background-image: linear-gradient(to top, #37ecba 0%, #72afd3 100%);
+}
+
+/*042 Awesome Pine*/
+.awesome_pine{
+ background-image: linear-gradient(to top, #ebbba7 0%, #cfc7f8 100%);
+}
+
+/*043 New York*/
+.new_york{
+ background-image: linear-gradient(to top, #fff1eb 0%, #ace0f9 100%);
+}
+
+/*044 Shy Rainbow*/
+.shy_rainbow{
+ background-image: linear-gradient(to right, #eea2a2 0%, #bbc1bf 19%, #57c6e1 42%, #b49fda 79%, #7ac5d8 100%);
+}
+
+/*045 Loon Crest*/
+.loon_crest{
+ background: linear-gradient(to bottom, rgba(255,255,255,0.15) 0%, rgba(0,0,0,0.15) 100%), radial-gradient(at top center, rgba(255,255,255,0.40) 0%, rgba(0,0,0,0.40) 120%) #989898;
+ background-blend-mode: multiply,multiply;
+}
+
+/*046 Mixed Hopes*/
+.mixed_hopes{
+ background-image: linear-gradient(to top, #c471f5 0%, #fa71cd 100%);
+}
+
+/*047 Fly High*/
+.fly_high{
+ background-image: linear-gradient(to top, #48c6ef 0%, #6f86d6 100%);
+}
+
+/*048 Strong Bliss*/
+.strong_bliss{
+ background-image: linear-gradient(to right, #f78ca0 0%, #f9748f 19%, #fd868c 60%, #fe9a8b 100%);
+}
+
+/*049 Fresh Milk*/
+.fresh_milk{
+ background-image: linear-gradient(to top, #feada6 0%, #f5efef 100%);
+}
+
+/*050 Snow Again*/
+.snow_again{
+ background-image: linear-gradient(to top, #e6e9f0 0%, #eef1f5 100%);
+}
+
+/*051 February Ink*/
+.february_ink{
+ background-image: linear-gradient(to top, #accbee 0%, #e7f0fd 100%);
+}
+
+/*052 Kind Steel*/
+.kind_steel{
+ background-image: linear-gradient(-20deg, #e9defa 0%, #fbfcdb 100%);
+}
+
+/*053 Soft Grass*/
+.soft_grass{
+ background-image: linear-gradient(to top, #c1dfc4 0%, #deecdd 100%);
+}
+
+/*054 Grown Early*/
+.grown_early{
+ background-image: linear-gradient(to top, #0ba360 0%, #3cba92 100%);
+}
+
+/*055 Sharp Blues*/
+.sharp_blues{
+ background-image: linear-gradient(to top, #00c6fb 0%, #005bea 100%);
+}
+
+/*056 Shady Water*/
+.shady_water{
+ background-image: linear-gradient(to right, #74ebd5 0%, #9face6 100%);
+}
+
+/*057 Dirty Beauty*/
+.dirty_beauty{
+ background-image: linear-gradient(to top, #6a85b6 0%, #bac8e0 100%);
+}
+
+/*058 Great Whale*/
+.great_whale{
+ background-image: linear-gradient(to top, #a3bded 0%, #6991c7 100%);
+}
+
+/*059 Teen Notebook*/
+.teen_notebook{
+ background-image: linear-gradient(to top, #9795f0 0%, #fbc8d4 100%);
+}
+
+/*060 Polite Rumors*/
+.polite_rumors{
+ background-image: linear-gradient(to top, #a7a6cb 0%, #8989ba 52%, #8989ba 100%);
+}
+
+/*061 Sweet Period*/
+.sweet_period{
+ background-image: linear-gradient(to top, #3f51b1 0%, #5a55ae 13%, #7b5fac 25%, #8f6aae 38%, #a86aa4 50%, #cc6b8e 62%, #f18271 75%, #f3a469 87%, #f7c978 100%);
+}
+
+/*062 Wide Matrix*/
+.wide_matrix{
+ background-image: linear-gradient(to top, #fcc5e4 0%, #fda34b 15%, #ff7882 35%, #c8699e 52%, #7046aa 71%, #0c1db8 87%, #020f75 100%);
+}
+
+/*063 Soft Cherish*/
+.soft_cherish{
+ background-image: linear-gradient(to top, #dbdcd7 0%, #dddcd7 24%, #e2c9cc 30%, #e7627d 46%, #b8235a 59%, #801357 71%, #3d1635 84%, #1c1a27 100%);
+}
+
+/*064 Red Salvation*/
+.red_salvation{
+ background-image: linear-gradient(to top, #f43b47 0%, #453a94 100%);
+}
+
+/*065 Burning Spring*/
+.burning_spring{
+ background-image: linear-gradient(to top, #4fb576 0%, #44c489 30%, #28a9ae 46%, #28a2b7 59%, #4c7788 71%, #6c4f63 86%, #432c39 100%);
+}
+
+/*066 Night Party*/
+.night_party{
+ background-image: linear-gradient(to top, #0250c5 0%, #d43f8d 100%);
+}
+
+/*067 Sky Glider*/
+.sky_glider{
+ background-image: linear-gradient(to top, #88d3ce 0%, #6e45e2 100%);
+}
+
+/*068 Heaven Peach*/
+.heaven_peach{
+ background-image: linear-gradient(to top, #d9afd9 0%, #97d9e1 100%);
+}
+
+/*069 Purple Division*/
+.purple_division{
+ background-image: linear-gradient(to top, #7028e4 0%, #e5b2ca 100%);
+}
+
+/*070 Aqua Splash*/
+.aqua_splash{
+ background-image: linear-gradient(15deg, #13547a 0%, #80d0c7 100%);
+}
+
+/*071 Above Clouds*/
+.above_clouds{
+ background-image: linear-gradient(to left, #BDBBBE 0%, #9D9EA3 100%), radial-gradient(88% 271%, rgba(255, 255, 255, 0.25) 0%, rgba(254, 254, 254, 0.25) 1%, rgba(0, 0, 0, 0.25) 100%), radial-gradient(50% 100%, rgba(255, 255, 255, 0.30) 0%, rgba(0, 0, 0, 0.30) 100%);
+ background-blend-mode: normal, lighten, soft-light;
+}
+
+/*072 Spiky Naga*/
+.spiky_naga{
+ background-image: linear-gradient(to top, #505285 0%, #585e92 12%, #65689f 25%, #7474b0 37%, #7e7ebb 50%, #8389c7 62%, #9795d4 75%, #a2a1dc 87%, #b5aee4 100%);
+}
+
+/*073 Love Kiss*/
+.love_kiss{
+ background-image: linear-gradient(to top, #ff0844 0%, #ffb199 100%);
+}
+
+/*074 Sharp Glass*/
+.sharp_glass{
+ background: #C9CCD3 linear-gradient(-180deg, rgba(255, 255, 255, 0.50) 0%, rgba(0, 0, 0, 0.50) 100%);
+ background-blend-mode: lighten;
+}
+
+/*075 Clean Mirror*/
+.clean_mirror{
+ background-image: linear-gradient(45deg, #93a5cf 0%, #e4efe9 100%);
+}
+
+/*076 Premium Dark*/
+.premium_dark{
+ background-image: linear-gradient(to right, #434343 0%, black 100%);
+}
+
+/*077 Cold Evening*/
+.cold_evening{
+ background-image: linear-gradient(to top, #0c3483 0%, #a2b6df 100%, #6b8cce 100%, #a2b6df 100%);
+}
+
+/*078 Cochiti Lake*/
+.cochiti_lake{
+ background-image: linear-gradient(45deg, #93a5cf 0%, #e4efe9 100%);
+}
+
+/*079 Summer Games*/
+.summer_games{
+ background-image: linear-gradient(to right, #92fe9d 0%, #00c9ff 100%);
+}
+
+/*080 Passionate Bed*/
+.passionate_bed{
+ background-image: linear-gradient(to right, #ff758c 0%, #ff7eb3 100%);
+}
+
+/*081 Mountain Rock*/
+.mountain_rock{
+ background-image: linear-gradient(to right, #868f96 0%, #596164 100%);
+}
+
+/*082 Desert Hump*/
+.desert_hump{
+ background-image: linear-gradient(to top, #c79081 0%, #dfa579 100%);
+}
+
+/*083 Jungle Day*/
+.jungle_day{
+ background-image: linear-gradient(45deg, #8baaaa 0%, #ae8b9c 100%);
+}
+
+/*084 Phoenix Start*/
+.phoenix_start{
+ background-image: linear-gradient(to right, #f83600 0%, #f9d423 100%);
+}
+
+/*085 October Silence*/
+.october_silence{
+ background-image: linear-gradient(-20deg, #b721ff 0%, #21d4fd 100%);
+}
+
+/*086 Faraway River*/
+.faraway_river{
+ background-image: linear-gradient(-20deg, #6e45e2 0%, #88d3ce 100%);
+}
+
+/*087 Alchemist Lab*/
+.alchemist_lab{
+ background-image: linear-gradient(-20deg, #d558c8 0%, #24d292 100%);
+}
+
+/*088 Over Sun*/
+.over_sun{
+ background-image: linear-gradient(60deg, #abecd6 0%, #fbed96 100%);
+}
+
+/*089 Premium White*/
+.premium_white{
+ background-image: linear-gradient(to top, #d5d4d0 0%, #d5d4d0 1%, #eeeeec 31%, #efeeec 75%, #e9e9e7 100%);
+}
+
+/*090 Mars Party*/
+.mars_party{
+ background-image: linear-gradient(to top, #5f72bd 0%, #9b23ea 100%);
+}
+
+/*091 Eternal Constance*/
+.eternal_constance{
+ background-image: linear-gradient(to top, #09203f 0%, #537895 100%);
+}
+
+/*092 Japan Blush*/
+.japan_blush{
+ background-image: linear-gradient(-20deg, #ddd6f3 0%, #faaca8 100%, #faaca8 100%);
+}
+
+/*093 Smiling Rain*/
+.smiling_rain{
+ background-image: linear-gradient(-20deg, #dcb0ed 0%, #99c99c 100%);
+}
+
+/*094 Cloudy Apple*/
+.cloudy_apple{
+ background-image: linear-gradient(to top, #f3e7e9 0%, #e3eeff 99%, #e3eeff 100%);
+}
+
+/*095 Big Mango*/
+.big_mango{
+ background-image: linear-gradient(to top, #c71d6f 0%, #d09693 100%);
+}
+
+/*096 Healthy Water*/
+.healthy_water{
+ background-image: linear-gradient(60deg, #96deda 0%, #50c9c3 100%);
+}
+
+/*097 Amour Amour*/
+.amour_amour{
+ background-image: linear-gradient(to top, #f77062 0%, #fe5196 100%);
+}
+
+/*098 Risky Concrete*/
+.risky_concrete{
+ background-image: linear-gradient(to top, #c4c5c7 0%, #dcdddf 52%, #ebebeb 100%);
+}
+
+/*099 Strong Stick*/
+.strong_stick{
+ background-image: linear-gradient(to right, #a8caba 0%, #5d4157 100%);
+}
+
+/*100 Vicious Stance*/
+.vicious_stance{
+ background-image: linear-gradient(60deg, #29323c 0%, #485563 100%);
+}
+
+/*101 Palo Alto*/
+.palo_alto{
+ background-image: linear-gradient(-60deg, #16a085 0%, #f4d03f 100%);
+}
+
+/*102 Happy Memories*/
+.happy_memories{
+ background-image: linear-gradient(-60deg, #ff5858 0%, #f09819 100%);
+}
+
+/*103 Midnight Bloom*/
+.midnight_bloom{
+ background-image: linear-gradient(-20deg, #2b5876 0%, #4e4376 100%);
+}
+
+/*104 Crystalline*/
+.crystalline{
+ background-image: linear-gradient(-20deg, #00cdac 0%, #8ddad5 100%);
+}
+
+/*105 Raccoon Back*/
+.raccoon_back{
+ background: linear-gradient(-180deg, #BCC5CE 0%, #929EAD 98%), radial-gradient(at top left, rgba(255,255,255,0.30) 0%, rgba(0,0,0,0.30) 100%);
+ background-blend-mode: screen;
+}
+
+/*106 Party Bliss*/
+.party_bliss{
+ background-image: linear-gradient(to top, #4481eb 0%, #04befe 100%);
+}
+
+/*107 Confident Cloud*/
+.confident_cloud{
+ background-image: linear-gradient(to top, #dad4ec 0%, #dad4ec 1%, #f3e7e9 100%);
+}
+
+/*108 Le Cocktail*/
+.le_cocktail{
+ background-image: linear-gradient(45deg, #874da2 0%, #c43a30 100%);
+}
+
+/*109 River City*/
+.river_city{
+ background-image: linear-gradient(to top, #4481eb 0%, #04befe 100%);
+}
+
+/*110 Frozen Berry*/
+.frozen_berry{
+ background-image: linear-gradient(to top, #e8198b 0%, #c7eafd 100%);
+}
+
+/*111 Elegance*/
+.elegance{
+ background-image: radial-gradient(73% 147%, #EADFDF 59%, #ECE2DF 100%), radial-gradient(91% 146%, rgba(255,255,255,0.50) 47%, rgba(0,0,0,0.50) 100%);
+ background-blend-mode: screen;
+}
+
+/*112 Child Care*/
+.child_care{
+ background-image: linear-gradient(-20deg, #f794a4 0%, #fdd6bd 100%);
+}
+
+/*113 Flying Lemon*/
+.flying_lemon{
+ background-image: linear-gradient(60deg, #64b3f4 0%, #c2e59c 100%);
+}
+
+/*114 New Retrowave*/
+.new_retrowave{
+ background-image: linear-gradient(to top, #3b41c5 0%, #a981bb 49%, #ffc8a9 100%);
+}
+
+/*115 Hidden Jaguar*/
+.hidden_jaguar{
+ background-image: linear-gradient(to top, #0fd850 0%, #f9f047 100%);
+}
+
+/*116 Above The Sky*/
+.above_the_sky{
+ background-image: linear-gradient(to top, lightgrey 0%, lightgrey 1%, #e0e0e0 26%, #efefef 48%, #d9d9d9 75%, #bcbcbc 100%);
+}
+
+/*117 Nega*/
+.nega{
+ background-image: linear-gradient(45deg, #ee9ca7 0%, #ffdde1 100%);
+}
+
+/*118 Dense Water*/
+.dense_water{
+ background-image: linear-gradient(to right, #3ab5b0 0%, #3d99be 31%, #56317a 100%);
+}
+
+/*119 Chemic Aqua*/
+.chemic_aqua{
+ background: #CDDCDC radial-gradient(at 50% 100%, rgba(255, 255, 255, 0.50) 0%, rgba(0, 0, 0, 0.50) 100%), linear-gradient(to bottom, rgba(255, 255, 255, 0.25) 0%, rgba(0, 0, 0, 0.25) 100%);
+ background-blend-mode: screen, overlay;
+}
+
+/*120 Seashore*/
+.seashore{
+ background-image: linear-gradient(to top, #209cff 0%, #68e0cf 100%);
+}
+
+/*121 Marble Wall*/
+.marble_wall{
+ background-image: linear-gradient(to top, #bdc2e8 0%, #bdc2e8 1%, #e6dee9 100%);
+}
+
+/*122 Cheerful Caramel*/
+.cheerful_caramel{
+ background-image: linear-gradient(to top, #e6b980 0%, #eacda3 100%);
+}
+
+/*123 Night Sky*/
+.night_sky{
+ background-image: linear-gradient(to top, #1e3c72 0%, #1e3c72 1%, #2a5298 100%);
+}
+
+/*124 Magic Lake*/
+.magic_lake{
+ background-image: linear-gradient(to top, #d5dee7 0%, #ffafbd 0%, #c9ffbf 100%);
+}
+
+/*125 Young Grass*/
+.young_grass{
+ background-image: linear-gradient(to top, #9be15d 0%, #00e3ae 100%);
+}
+
+/*126 Colorful Peach*/
+.colorful_peach{
+ background-image: linear-gradient(to right, #ed6ea0 0%, #ec8c69 100%);
+}
+
+/*127 Gentle Care*/
+.gentle_care{
+ background-image: linear-gradient(to right, #ffc3a0 0%, #ffafbd 100%);
+}
+
+/*128 Plum Bath*/
+.plum_bath{
+ background-image: linear-gradient(to top, #cc208e 0%, #6713d2 100%);
+}
+
+/*129 Happy Unicorn*/
+.happy_unicorn{
+ background-image: linear-gradient(to top, #b3ffab 0%, #12fff7 100%);
+}
+
+/*130 Full Metal*/
+.full_metal{
+ background: linear-gradient(to bottom, #D5DEE7 0%, #E8EBF2 50%, #E2E7ED 100%), linear-gradient(to bottom, rgba(0,0,0,0.02) 50%, rgba(255,255,255,0.02) 61%, rgba(0,0,0,0.02) 73%), linear-gradient(33deg, rgba(255,255,255,0.20) 0%, rgba(0,0,0,0.20) 100%);
+ background-blend-mode: normal,color-burn;
+}
+
+/*131 African Field*/
+.african_field{
+ background-image: linear-gradient(to top, #65bd60 0%, #5ac1a8 25%, #3ec6ed 50%, #b7ddb7 75%, #fef381 100%);
+}
+
+/*132 Solid Stone*/
+.solid_stone{
+ background-image: linear-gradient(to right, #243949 0%, #517fa4 100%);
+}
+
+/*133 Orange Juice*/
+.orange_juice{
+ background-image: linear-gradient(-20deg, #fc6076 0%, #ff9a44 100%);
+}
+
+/*134 Glass Water*/
+.glass_water{
+ background-image: linear-gradient(to top, #dfe9f3 0%, white 100%);
+}
+
+/*135 Slick Carbon*/
+.slick_carbon{
+ background: linear-gradient(to bottom, #323232 0%, #3F3F3F 40%, #1C1C1C 150%), linear-gradient(to top, rgba(255,255,255,0.40) 0%, rgba(0,0,0,0.25) 200%);
+ background-blend-mode: multiply;
+}
+
+/*136 North Miracle*/
+.north_miracle{
+ background-image: linear-gradient(to right, #00dbde 0%, #fc00ff 100%);
+}
+
+/*137 Fruit Blend*/
+.fruit_blend{
+ background-image: linear-gradient(to right, #f9d423 0%, #ff4e50 100%);
+}
+
+/*138 Millennium Pine*/
+.millennium_pine{
+ background-image: linear-gradient(to top, #50cc7f 0%, #f5d100 100%);
+}
+
+/*139 High Flight*/
+.high_flight{
+ background-image: linear-gradient(to right, #0acffe 0%, #495aff 100%);
+}
+
+/*140 Mole Hall*/
+.mole_hall{
+ background-image: linear-gradient(-20deg, #616161 0%, #9bc5c3 100%);
+}
+
+/*141 Earl Gray*/
+.earl_gray{
+ background: #E4E4E1 radial-gradient(at top center, rgba(255, 255, 255, 0.03) 0%, rgba(0, 0, 0, 0.03) 100%), linear-gradient(to top, rgba(255, 255, 255, 0.1) 0%, rgba(143, 152, 157, 0.60) 100%);
+ background-blend-mode: normal, multiply;
+}
+
+/*142 Space Shift*/
+.space_shift{
+ background-image: linear-gradient(60deg, #3d3393 0%, #2b76b9 37%, #2cacd1 65%, #35eb93 100%);
+}
+
+/*143 Forest Inei*/
+.forest_inei{
+ background-image: linear-gradient(to top, #df89b5 0%, #bfd9fe 100%);
+}
+
+/*144 Royal Garden*/
+.royal_garden{
+ background-image: linear-gradient(to right, #ed6ea0 0%, #ec8c69 100%);
+}
+
+/*145 Rich Metal*/
+.rich_metal{
+ background-image: linear-gradient(to right, #d7d2cc 0%, #304352 100%);
+}
+
+/*146 Juicy Cake*/
+.juicy_cake{
+ background-image: linear-gradient(to top, #e14fad 0%, #f9d423 100%);
+}
+
+/*147 Smart Indigo*/
+.smart_indigo{
+ background-image: linear-gradient(to top, #b224ef 0%, #7579ff 100%);
+}
+
+/*148 Sand Strike*/
+.sand_strike{
+ background-image: linear-gradient(to right, #c1c161 0%, #c1c161 0%, #d4d4b1 100%);
+}
+
+/*149 Norse Beauty*/
+.norse_beauty{
+ background-image: linear-gradient(to right, #ec77ab 0%, #7873f5 100%);
+}
+
+/*150 Aqua Guidance*/
+.aqua_guidance{
+ background-image: linear-gradient(to top, #007adf 0%, #00ecbc 100%);
+}
+
+/*151 Sun Veggie*/
+.sun_veggie{
+ background-image: linear-gradient(-225deg, #20E2D7 0%, #F9FEA5 100%);
+}
+
+/*152 Sea Lord*/
+.sea_lord{
+ background-image: linear-gradient(-225deg, #2CD8D5 0%, #C5C1FF 56%, #FFBAC3 100%);
+}
+
+/*153 Black Sea*/
+.black_sea{
+ background-image: linear-gradient(-225deg, #2CD8D5 0%, #6B8DD6 48%, #8E37D7 100%);
+}
+
+/*154 Grass Shampoo*/
+.grass_shampoo{
+ background-image: linear-gradient(-225deg, #DFFFCD 0%, #90F9C4 48%, #39F3BB 100%);
+}
+
+/*155 Landing Aircraft*/
+.landing_aircraft{
+ background-image: linear-gradient(-225deg, #5D9FFF 0%, #B8DCFF 48%, #6BBBFF 100%);
+}
+
+/*156 Witch Dance*/
+.witch_dance{
+ background-image: linear-gradient(-225deg, #A8BFFF 0%, #884D80 100%);
+}
+
+/*157 Sleepless Night*/
+.sleepless_night{
+ background-image: linear-gradient(-225deg, #5271C4 0%, #B19FFF 48%, #ECA1FE 100%);
+}
+
+/*158 Angel Care*/
+.angel_care{
+ background-image: linear-gradient(-225deg, #FFE29F 0%, #FFA99F 48%, #FF719A 100%);
+}
+
+/*159 Crystal River*/
+.crystal_river{
+ background-image: linear-gradient(-225deg, #22E1FF 0%, #1D8FE1 48%, #625EB1 100%);
+}
+
+/*160 Soft Lipstick*/
+.soft_lipstick{
+ background-image: linear-gradient(-225deg, #B6CEE8 0%, #F578DC 100%);
+}
+
+/*161 Salt Mountain*/
+.salt_mountain{
+ background-image: linear-gradient(-225deg, #FFFEFF 0%, #D7FFFE 100%);
+}
+
+/*162 Perfect White*/
+.perfect_white{
+ background-image: linear-gradient(-225deg, #E3FDF5 0%, #FFE6FA 100%);
+}
+
+/*163 Fresh Oasis*/
+.fresh_oasis{
+ background-image: linear-gradient(-225deg, #7DE2FC 0%, #B9B6E5 100%);
+}
+
+/*164 Strict November*/
+.strict_november{
+ background-image: linear-gradient(-225deg, #CBBACC 0%, #2580B3 100%);
+}
+
+/*165 Morning Salad*/
+.morning_salad{
+ background-image: linear-gradient(-225deg, #B7F8DB 0%, #50A7C2 100%);
+}
+
+/*166 Deep Relief*/
+.deep_relief{
+ background-image: linear-gradient(-225deg, #7085B6 0%, #87A7D9 50%, #DEF3F8 100%);
+}
+
+/*167 Sea Strike*/
+.sea_strike{
+ background-image: linear-gradient(-225deg, #77FFD2 0%, #6297DB 48%, #1EECFF 100%);
+}
+
+/*168 Night Call*/
+.night_call{
+ background-image: linear-gradient(-225deg, #AC32E4 0%, #7918F2 48%, #4801FF 100%);
+}
+
+/*169 Supreme Sky*/
+.supreme_sky{
+ background-image: linear-gradient(-225deg, #D4FFEC 0%, #57F2CC 48%, #4596FB 100%);
+}
+
+/*170 Light Blue*/
+.light_blue{
+ background-image: linear-gradient(-225deg, #9EFBD3 0%, #57E9F2 48%, #45D4FB 100%);
+}
+
+/*171 Mind Crawl*/
+.mind_crawl{
+ background-image: linear-gradient(-225deg, #473B7B 0%, #3584A7 51%, #30D2BE 100%);
+}
+
+/*172 Lily Meadow*/
+.lily_meadow{
+ background-image: linear-gradient(-225deg, #65379B 0%, #886AEA 53%, #6457C6 100%);
+}
+
+/*173 Sugar Lollipop*/
+.sugar_lollipop{
+ background-image: linear-gradient(-225deg, #A445B2 0%, #D41872 52%, #FF0066 100%);
+}
+
+/*174 Sweet Dessert*/
+.sweet_dessert{
+ background-image: linear-gradient(-225deg, #7742B2 0%, #F180FF 52%, #FD8BD9 100%);
+}
+
+/*175 Magic Ray*/
+.magic_ray{
+ background-image: linear-gradient(-225deg, #FF3CAC 0%, #562B7C 52%, #2B86C5 100%);
+}
+
+/*176 Teen Party*/
+.teen_party{
+ background-image: linear-gradient(-225deg, #FF057C 0%, #8D0B93 50%, #321575 100%);
+}
+
+/*177 Frozen Heat*/
+.frozen_heat{
+ background-image: linear-gradient(-225deg, #FF057C 0%, #7C64D5 48%, #4CC3FF 100%);
+}
+
+/*178 Gagarin View*/
+.gagarin_view{
+ background-image: linear-gradient(-225deg, #69EACB 0%, #EACCF8 48%, #6654F1 100%);
+}
+
+/*179 Fabled Sunset*/
+.fabled_sunset{
+ background-image: linear-gradient(-225deg, #231557 0%, #44107A 29%, #FF1361 67%, #FFF800 100%);
+}
+
+/*180 Perfect Blue*/
+.perfect_blue{
+ background-image: linear-gradient(-225deg, #3D4E81 0%, #5753C9 48%, #6E7FF3 100%);
+}
diff --git a/src/gui/qtgui.tracepoints b/src/gui/qtgui.tracepoints
index aa8a8ede57..aed6c35c03 100644
--- a/src/gui/qtgui.tracepoints
+++ b/src/gui/qtgui.tracepoints
@@ -1,8 +1,13 @@
-qfontdatabase_addapplicationfont(const QString &filename)
-qfontdatabase_load(const QString &family, int pointSize)
-qfontdatabase_loadengine(const QString &family, int pointSize)
-qfontdatabaseprivate_addappfont(const QString &fileName)
-qguiapplicationprivate_init_entry()
-qguiapplicationprivate_init_exit()
-qguiapplicationprivate_processwsevents_entry(int type)
-qguiapplicationprivate_processwsevents_exit(int type)
+QGuiApplicationPrivate_init_entry()
+QGuiApplicationPrivate_init_exit()
+
+QGuiApplicationPrivate_processWindowSystemEvent_entry(int type)
+QGuiApplicationPrivate_processWindowSystemEvent_exit(int type)
+
+QFontDatabase_addApplicationFont(const QString &filename)
+QFontDatabase_load(const QString &family, int pointSize)
+QFontDatabase_loadEngine(const QString &family, int pointSize)
+QFontDatabasePrivate_addAppFont(const QString &fileName)
+
+QImageReader_read_before_reading(QImageReader *reader, const QString &filename)
+QImageReader_read_after_reading(QImageReader *reader, bool result)
diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp
index 64adeaa260..325fd26a31 100644
--- a/src/gui/text/qcssparser.cpp
+++ b/src/gui/text/qcssparser.cpp
@@ -345,13 +345,6 @@ static const QCssKnownValue styleFeatures[NumKnownStyleFeatures - 1] = {
{ "none", StyleFeature_None }
};
-#if defined(Q_CC_MSVC) && _MSC_VER < 1600
-static bool operator<(const QCssKnownValue &prop1, const QCssKnownValue &prop2)
-{
- return QString::compare(QString::fromLatin1(prop1.name), QLatin1String(prop2.name), Qt::CaseInsensitive) < 0;
-}
-#endif
-
static bool operator<(const QString &name, const QCssKnownValue &prop)
{
return QString::compare(name, QLatin1String(prop.name), Qt::CaseInsensitive) < 0;
@@ -2714,8 +2707,10 @@ bool Parser::parseFunction(QString *name, QString *args)
{
*name = lexem();
name->chop(1);
+ // until(RPAREN) needs FUNCTION token at index-1 to work properly
+ int start = index;
skipSpace();
- const int start = index;
+ std::swap(start, index);
if (!until(RPAREN)) return false;
for (int i = start; i < index - 1; ++i)
args->append(symbols.at(i).lexem());
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index f7462b65c8..580a09427c 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -2703,18 +2703,6 @@ static const int slow_timeout = 300000; // 5m
const uint QFontCache::min_cost = 4*1024; // 4mb
-#ifdef QT_NO_THREAD
-Q_GLOBAL_STATIC(QFontCache, theFontCache)
-
-QFontCache *QFontCache::instance()
-{
- return theFontCache();
-}
-
-void QFontCache::cleanup()
-{
-}
-#else
Q_GLOBAL_STATIC(QThreadStorage<QFontCache *>, theFontCache)
QFontCache *QFontCache::instance()
@@ -2736,7 +2724,6 @@ void QFontCache::cleanup()
if (cache && cache->hasLocalData())
cache->setLocalData(0);
}
-#endif // QT_NO_THREAD
QBasicAtomicInt font_cache_id = Q_BASIC_ATOMIC_INITIALIZER(1);
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index a4e5130937..196eebb353 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -689,7 +689,6 @@ static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDe
if (!multi)
fontDef->style = desc.style->key.style;
fontDef->fixedPitch = desc.family->fixedPitch;
- fontDef->stretch = desc.style->key.stretch;
fontDef->ignorePitch = false;
}
@@ -1010,7 +1009,7 @@ QFontEngine *loadEngine(int script, const QFontDef &request,
QFontEngine *engine = loadSingleEngine(script, request, family, foundry, style, size);
if (engine && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol) {
- Q_TRACE(qfontdatabase_loadengine, request.family, request.pointSize);
+ Q_TRACE(QFontDatabase_loadEngine, request.family, request.pointSize);
QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
QFontEngineMulti *pfMultiEngine = pfdb->fontEngineMulti(engine, QChar::Script(script));
@@ -2442,7 +2441,7 @@ int QFontDatabasePrivate::addAppFont(const QByteArray &fontData, const QString &
font.data = fontData;
font.fileName = fileName;
- Q_TRACE(qfontdatabaseprivate_addappfont, fileName);
+ Q_TRACE(QFontDatabasePrivate_addAppFont, fileName);
int i;
for (i = 0; i < applicationFonts.count(); ++i)
@@ -2500,7 +2499,7 @@ int QFontDatabase::addApplicationFont(const QString &fileName)
if (!f.open(QIODevice::ReadOnly))
return -1;
- Q_TRACE(qfontdatabase_addapplicationfont, fileName);
+ Q_TRACE(QFontDatabase_addApplicationFont, fileName);
data = f.readAll();
}
@@ -2800,7 +2799,7 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
QFontEngine *fe = nullptr;
- Q_TRACE(qfontdatabase_load, req.family, req.pointSize);
+ Q_TRACE(QFontDatabase_load, req.family, req.pointSize);
req.fallBackFamilies = fallBackFamilies;
if (!req.fallBackFamilies.isEmpty())
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 80fd288c04..9b0b0ec0d5 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -1327,7 +1327,7 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy
resolveTable:
*isSymbolFont = (symbolTable > -1);
- quint32 unicode_table;
+ quint32 unicode_table = 0;
if (!qSafeFromBigEndian(maps + 8 * tableToUse + 4, endPtr, &unicode_table))
return 0;
diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp
index 2f90754274..0026e3edfb 100644
--- a/src/gui/text/qstatictext.cpp
+++ b/src/gui/text/qstatictext.cpp
@@ -39,6 +39,7 @@
#include "qstatictext.h"
#include "qstatictext_p.h"
+#include <qmath.h>
#include <private/qtextengine_p.h>
#include <private/qfontengine_p.h>
#include <qabstracttextdocumentlayout.h>
@@ -611,22 +612,22 @@ void QStaticTextPrivate::paintText(const QPointF &topLeftPosition, QPainter *p,
textLayout.setTextOption(textOption);
textLayout.setCacheEnabled(true);
- qreal leading = QFontMetricsF(font).leading();
- qreal height = -leading;
-
+ qreal height = 0;
textLayout.beginLayout();
while (1) {
QTextLine line = textLayout.createLine();
if (!line.isValid())
break;
+ line.setLeadingIncluded(true);
if (textWidth >= 0.0)
line.setLineWidth(textWidth);
else
line.setLineWidth(QFIXED_MAX);
- height += leading;
line.setPosition(QPointF(0.0, height));
height += line.height();
+ if (line.leading() < 0)
+ height += qCeil(line.leading());
}
textLayout.endLayout();
diff --git a/src/gui/text/qtextcursor.cpp b/src/gui/text/qtextcursor.cpp
index f32c31d18e..af8fcf369c 100644
--- a/src/gui/text/qtextcursor.cpp
+++ b/src/gui/text/qtextcursor.cpp
@@ -80,7 +80,8 @@ QTextCursorPrivate::QTextCursorPrivate(const QTextCursorPrivate &rhs)
visualNavigation = rhs.visualNavigation;
keepPositionOnInsert = rhs.keepPositionOnInsert;
changed = rhs.changed;
- priv->addCursor(this);
+ if (priv != nullptr)
+ priv->addCursor(this);
}
QTextCursorPrivate::~QTextCursorPrivate()
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index 44d1b2f201..5d88530e65 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -75,6 +75,18 @@ QT_BEGIN_NAMESPACE
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION unsigned int qt_int_sqrt(unsigned int n);
+
+/*!
+ Returns \c true if the string \a text is likely to be rich text;
+ otherwise returns \c false.
+
+ This function uses a fast and therefore simple heuristic. It
+ mainly checks whether there is something that looks like a tag
+ before the first line break. Although the result may be correct
+ for common cases, there is no guarantee.
+
+ This function is defined in the \c <QTextDocument> header file.
+*/
bool Qt::mightBeRichText(const QString& text)
{
if (text.isEmpty())
@@ -133,6 +145,16 @@ bool Qt::mightBeRichText(const QString& text)
return false;
}
+/*!
+ Converts the plain text string \a plain to an HTML-formatted
+ paragraph while preserving most of its look.
+
+ \a mode defines how whitespace is handled.
+
+ This function is defined in the \c <QTextDocument> header file.
+
+ \sa escape(), mightBeRichText()
+*/
QString Qt::convertFromPlainText(const QString &plain, Qt::WhiteSpaceMode mode)
{
int col = 0;
@@ -181,6 +203,12 @@ QString Qt::convertFromPlainText(const QString &plain, Qt::WhiteSpaceMode mode)
return rich;
}
+/*!
+ \fn QTextCodec *Qt::codecForHtml(const QByteArray &ba)
+ \internal
+
+ This function is defined in the \c <QTextDocument> header file.
+*/
#ifndef QT_NO_TEXTCODEC
QTextCodec *Qt::codecForHtml(const QByteArray &ba)
{
@@ -1989,7 +2017,6 @@ void QTextDocument::print(QPagedPaintDevice *printer) const
int fromPage = pd->fromPage;
int toPage = pd->toPage;
- bool ascending = true;
if (fromPage == 0 && toPage == 0) {
fromPage = 1;
@@ -2005,6 +2032,7 @@ void QTextDocument::print(QPagedPaintDevice *printer) const
return;
}
+// bool ascending = true;
// if (printer->pageOrder() == QPrinter::LastPageFirst) {
// int tmp = fromPage;
// fromPage = toPage;
@@ -2018,12 +2046,7 @@ void QTextDocument::print(QPagedPaintDevice *printer) const
if (page == toPage)
break;
-
- if (ascending)
- ++page;
- else
- --page;
-
+ ++page;
if (!printer->newPage())
return;
}
@@ -2908,7 +2931,11 @@ void QTextHtmlExporter::emitBlock(const QTextBlock &block)
html += QLatin1Char('>');
html += QLatin1String("<pre");
} else if (!list) {
- html += QLatin1String("<p");
+ int headingLevel = blockFormat.headingLevel();
+ if (headingLevel > 0 && headingLevel <= 6)
+ html += QLatin1String("<h") + QString::number(headingLevel);
+ else
+ html += QLatin1String("<p");
}
emitBlockAttributes(block);
@@ -2931,8 +2958,13 @@ void QTextHtmlExporter::emitBlock(const QTextBlock &block)
html += QLatin1String("</pre>");
else if (list)
html += QLatin1String("</li>");
- else
- html += QLatin1String("</p>");
+ else {
+ int headingLevel = blockFormat.headingLevel();
+ if (headingLevel > 0 && headingLevel <= 6)
+ html += QLatin1String("</h") + QString::number(headingLevel) + QLatin1Char('>');
+ else
+ html += QLatin1String("</p>");
+ }
if (list) {
if (list->itemNumber(block) == list->count() - 1) { // last item? close list
diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h
index 64e39d4648..33c0b48683 100644
--- a/src/gui/text/qtextdocument.h
+++ b/src/gui/text/qtextdocument.h
@@ -70,17 +70,15 @@ class QTextCursor;
template<typename T> class QVector;
-#ifndef Q_CLANG_QDOC
namespace Qt
{
Q_GUI_EXPORT bool mightBeRichText(const QString&);
Q_GUI_EXPORT QString convertFromPlainText(const QString &plain, WhiteSpaceMode mode = WhiteSpacePre);
-#ifndef QT_NO_TEXTCODEC
+#if !defined(QT_NO_TEXTCODEC) || defined(Q_CLANG_QDOC)
Q_GUI_EXPORT QTextCodec *codecForHtml(const QByteArray &ba);
#endif
}
-#endif
class Q_GUI_EXPORT QAbstractUndoItem
{
diff --git a/src/gui/text/qtextdocumentfragment.cpp b/src/gui/text/qtextdocumentfragment.cpp
index ea37695f4e..f0eff2d4f3 100644
--- a/src/gui/text/qtextdocumentfragment.cpp
+++ b/src/gui/text/qtextdocumentfragment.cpp
@@ -420,7 +420,7 @@ static QTextListFormat::Style nextListStyle(QTextListFormat::Style style)
}
QTextHtmlImporter::QTextHtmlImporter(QTextDocument *_doc, const QString &_html, ImportMode mode, const QTextDocument *resourceProvider)
- : indent(0), compressNextWhitespace(PreserveWhiteSpace), doc(_doc), importMode(mode)
+ : indent(0), headingLevel(0), compressNextWhitespace(PreserveWhiteSpace), doc(_doc), importMode(mode)
{
cursor = QTextCursor(doc);
wsm = QTextHtmlParserNode::WhiteSpaceNormal;
@@ -724,9 +724,9 @@ QTextHtmlImporter::ProcessNodeResult QTextHtmlImporter::processSpecialNodes()
cursor.insertImage(fmt, QTextFrameFormat::Position(currentNode->cssFloat));
- cursor.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor);
+ cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor);
cursor.mergeCharFormat(currentNode->charFormat);
- cursor.movePosition(QTextCursor::Right);
+ cursor.movePosition(QTextCursor::NextCharacter);
compressNextWhitespace = CollapseWhiteSpace;
hasBlock = false;
@@ -747,8 +747,28 @@ QTextHtmlImporter::ProcessNodeResult QTextHtmlImporter::processSpecialNodes()
return ContinueWithNextNode;
}
+ case Html_h1:
+ headingLevel = 1;
+ break;
+ case Html_h2:
+ headingLevel = 2;
+ break;
+ case Html_h3:
+ headingLevel = 3;
+ break;
+ case Html_h4:
+ headingLevel = 4;
+ break;
+ case Html_h5:
+ headingLevel = 5;
+ break;
+ case Html_h6:
+ headingLevel = 6;
+ break;
+
default: break;
}
+
return ContinueWithCurrentNode;
}
@@ -832,6 +852,15 @@ bool QTextHtmlImporter::closeTag()
}
}
break;
+ case Html_h1:
+ case Html_h2:
+ case Html_h3:
+ case Html_h4:
+ case Html_h5:
+ case Html_h6:
+ headingLevel = 0;
+ blockTagClosed = true;
+ break;
default:
if (closedNode->isBlock())
blockTagClosed = true;
@@ -1093,6 +1122,11 @@ QTextHtmlImporter::ProcessNodeResult QTextHtmlImporter::processBlockNode()
modifiedBlockFormat = true;
}
+ if (headingLevel) {
+ block.setHeadingLevel(headingLevel);
+ modifiedBlockFormat = true;
+ }
+
if (currentNode->blockFormat.propertyCount() > 0) {
modifiedBlockFormat = true;
block.merge(currentNode->blockFormat);
diff --git a/src/gui/text/qtextdocumentfragment_p.h b/src/gui/text/qtextdocumentfragment_p.h
index e8699545f7..02a6a429fa 100644
--- a/src/gui/text/qtextdocumentfragment_p.h
+++ b/src/gui/text/qtextdocumentfragment_p.h
@@ -152,6 +152,7 @@ private:
friend class QTypeInfo<List>;
QVector<List> lists;
int indent;
+ int headingLevel;
// insert a named anchor the next time we emit a char format,
// either in a block or in regular text
diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp
index 2957b8d5c0..a9227f0171 100644
--- a/src/gui/text/qtextdocumentlayout.cpp
+++ b/src/gui/text/qtextdocumentlayout.cpp
@@ -399,26 +399,6 @@ static bool operator<(const QCheckPoint &checkPoint, int pos)
return checkPoint.positionInFrame < pos;
}
-#if defined(Q_CC_MSVC) && _MSC_VER < 1600
-//The STL implementation of MSVC 2008 requires the definitions
-
-static bool operator<(const QCheckPoint &checkPoint1, const QCheckPoint &checkPoint2)
-{
- return checkPoint1.y < checkPoint2.y;
-}
-
-static bool operator<(QFixed y, const QCheckPoint &checkPoint)
-{
- return y < checkPoint.y;
-}
-
-static bool operator<(int pos, const QCheckPoint &checkPoint)
-{
- return pos < checkPoint.positionInFrame;
-}
-
-#endif
-
static void fillBackground(QPainter *p, const QRectF &rect, QBrush brush, const QPointF &origin, const QRectF &gradientRect = QRectF())
{
p->save();
@@ -2569,12 +2549,14 @@ void QTextDocumentLayoutPrivate::layoutFlow(QTextFrame::Iterator it, QTextLayout
}
static inline void getLineHeightParams(const QTextBlockFormat &blockFormat, const QTextLine &line, qreal scaling,
- QFixed *lineAdjustment, QFixed *lineBreakHeight, QFixed *lineHeight)
+ QFixed *lineAdjustment, QFixed *lineBreakHeight, QFixed *lineHeight, QFixed *lineBottom)
{
- *lineHeight = QFixed::fromReal(blockFormat.lineHeight(line.height(), scaling));
+ qreal rawHeight = qCeil(line.ascent() + line.descent() + line.leading());
+ *lineHeight = QFixed::fromReal(blockFormat.lineHeight(rawHeight, scaling));
+ *lineBottom = QFixed::fromReal(blockFormat.lineHeight(line.height(), scaling));
if (blockFormat.lineHeightType() == QTextBlockFormat::FixedHeight || blockFormat.lineHeightType() == QTextBlockFormat::MinimumHeight) {
- *lineBreakHeight = *lineHeight;
+ *lineBreakHeight = *lineBottom;
if (blockFormat.lineHeightType() == QTextBlockFormat::FixedHeight)
*lineAdjustment = QFixed::fromReal(line.ascent() + qMax(line.leading(), qreal(0.0))) - ((*lineHeight * 4) / 5);
else
@@ -2652,6 +2634,7 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
const QFixed cy = layoutStruct->y;
const QFixed l = layoutStruct->x_left + totalLeftMargin;
const QFixed r = layoutStruct->x_right - totalRightMargin;
+ QFixed bottom;
tl->beginLayout();
bool firstLine = true;
@@ -2721,10 +2704,10 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
}
- QFixed lineBreakHeight, lineHeight, lineAdjustment;
+ QFixed lineBreakHeight, lineHeight, lineAdjustment, lineBottom;
qreal scaling = (q->paintDevice() && q->paintDevice()->logicalDpiY() != qt_defaultDpi()) ?
qreal(q->paintDevice()->logicalDpiY()) / qreal(qt_defaultDpi()) : 1;
- getLineHeightParams(blockFormat, line, scaling, &lineAdjustment, &lineBreakHeight, &lineHeight);
+ getLineHeightParams(blockFormat, line, scaling, &lineAdjustment, &lineBreakHeight, &lineHeight, &lineBottom);
if (layoutStruct->pageHeight > 0 && layoutStruct->absoluteY() + lineBreakHeight > layoutStruct->pageBottom) {
layoutStruct->newPage();
@@ -2739,6 +2722,7 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
}
line.setPosition(QPointF((left - layoutStruct->x_left).toReal(), (layoutStruct->y - cy - lineAdjustment).toReal()));
+ bottom = layoutStruct->y + lineBottom;
layoutStruct->y += lineHeight;
layoutStruct->contentsWidth
= qMax<QFixed>(layoutStruct->contentsWidth, QFixed::fromReal(line.x() + line.naturalTextWidth()) + totalRightMargin);
@@ -2750,27 +2734,31 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
}
layoutStruct->pendingFloats.clear();
}
+ layoutStruct->y = qMax(layoutStruct->y, bottom);
tl->endLayout();
} else {
const int cnt = tl->lineCount();
+ QFixed bottom;
for (int i = 0; i < cnt; ++i) {
LDEBUG << "going to move text line" << i;
QTextLine line = tl->lineAt(i);
layoutStruct->contentsWidth
= qMax(layoutStruct->contentsWidth, QFixed::fromReal(line.x() + tl->lineAt(i).naturalTextWidth()) + totalRightMargin);
- QFixed lineBreakHeight, lineHeight, lineAdjustment;
+ QFixed lineBreakHeight, lineHeight, lineAdjustment, lineBottom;
qreal scaling = (q->paintDevice() && q->paintDevice()->logicalDpiY() != qt_defaultDpi()) ?
qreal(q->paintDevice()->logicalDpiY()) / qreal(qt_defaultDpi()) : 1;
- getLineHeightParams(blockFormat, line, scaling, &lineAdjustment, &lineBreakHeight, &lineHeight);
+ getLineHeightParams(blockFormat, line, scaling, &lineAdjustment, &lineBreakHeight, &lineHeight, &lineBottom);
if (layoutStruct->pageHeight != QFIXED_MAX) {
if (layoutStruct->absoluteY() + lineBreakHeight > layoutStruct->pageBottom)
layoutStruct->newPage();
line.setPosition(QPointF(line.position().x(), (layoutStruct->y - lineAdjustment).toReal() - tl->position().y()));
}
+ bottom = layoutStruct->y + lineBottom;
layoutStruct->y += lineHeight;
}
+ layoutStruct->y = qMax(layoutStruct->y, bottom);
if (layoutStruct->updateRect.isValid()
&& blockLength > 1) {
if (layoutFrom >= blockPosition + blockLength) {
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 87dc63d59c..4e9b00f9c9 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -597,7 +597,13 @@ struct QBidiAlgorithm {
} else if (current == QChar::DirBN) {
current = last;
} else {
- Q_ASSERT(current != QChar::DirLRE && current != QChar::DirRLE && current != QChar::DirLRO && current != QChar::DirRLO && current != QChar::DirPDF); // there shouldn't be any explicit embedding marks here
+ // there shouldn't be any explicit embedding marks here
+ Q_ASSERT(current != QChar::DirLRE);
+ Q_ASSERT(current != QChar::DirRLE);
+ Q_ASSERT(current != QChar::DirLRO);
+ Q_ASSERT(current != QChar::DirRLO);
+ Q_ASSERT(current != QChar::DirPDF);
+
last = current;
}
@@ -1939,7 +1945,7 @@ const QCharAttributes *QTextEngine::attributes() const
QVarLengthArray<QUnicodeTools::ScriptItem> scriptItems(layoutData->items.size());
for (int i = 0; i < layoutData->items.size(); ++i) {
- const QScriptItem &si = layoutData->items[i];
+ const QScriptItem &si = layoutData->items.at(i);
scriptItems[i].position = si.position;
scriptItems[i].script = si.analysis.script;
}
@@ -1956,14 +1962,14 @@ const QCharAttributes *QTextEngine::attributes() const
void QTextEngine::shape(int item) const
{
- if (layoutData->items[item].analysis.flags == QScriptAnalysis::Object) {
+ if (layoutData->items.at(item).analysis.flags == QScriptAnalysis::Object) {
ensureSpace(1);
if (block.docHandle()) {
docLayout()->resizeInlineObject(QTextInlineObject(item, const_cast<QTextEngine *>(this)),
layoutData->items[item].position + block.position(),
format(&layoutData->items[item]));
}
- } else if (layoutData->items[item].analysis.flags == QScriptAnalysis::Tab) {
+ } else if (layoutData->items.at(item).analysis.flags == QScriptAnalysis::Tab) {
// set up at least the ascent/descent/leading of the script item for the tab
fontEngine(layoutData->items[item],
&layoutData->items[item].ascent,
@@ -2076,7 +2082,7 @@ void QTextEngine::itemize() const
case QChar::Space:
case QChar::Nbsp:
if (option.flags() & QTextOption::ShowTabsAndSpaces) {
- analysis->flags = QScriptAnalysis::Space;
+ analysis->flags = (*uc == QChar::Space) ? QScriptAnalysis::Space : QScriptAnalysis::Nbsp;
break;
}
Q_FALLTHROUGH();
@@ -2204,9 +2210,9 @@ int QTextEngine::findItem(int strPos, int firstItem) const
int right = layoutData->items.size()-1;
while(left <= right) {
int middle = ((right-left)/2)+left;
- if (strPos > layoutData->items[middle].position)
+ if (strPos > layoutData->items.at(middle).position)
left = middle+1;
- else if(strPos < layoutData->items[middle].position)
+ else if (strPos < layoutData->items.at(middle).position)
right = middle-1;
else {
return middle;
@@ -2598,7 +2604,7 @@ void QTextEngine::justify(const QScriptLine &line)
int end = line.from + (int)line.length + line.trailingSpaces;
if (end == layoutData->string.length())
return; // no justification at end of paragraph
- if (end && layoutData->items[findItem(end-1)].analysis.flags == QScriptAnalysis::LineOrParagraphSeparator)
+ if (end && layoutData->items.at(findItem(end - 1)).analysis.flags == QScriptAnalysis::LineOrParagraphSeparator)
return; // no justification at the end of an explicitly separated line
}
@@ -2632,13 +2638,13 @@ void QTextEngine::justify(const QScriptLine &line)
// store pointers to the glyph data that could get reallocated by the shaping
// process.
for (int i = 0; i < nItems; ++i) {
- QScriptItem &si = layoutData->items[firstItem + i];
+ const QScriptItem &si = layoutData->items.at(firstItem + i);
if (!si.num_glyphs)
shape(firstItem + i);
}
for (int i = 0; i < nItems; ++i) {
- QScriptItem &si = layoutData->items[firstItem + i];
+ const QScriptItem &si = layoutData->items.at(firstItem + i);
int kashida_type = Justification_Arabic_Normal;
int kashida_pos = -1;
@@ -2934,7 +2940,7 @@ int QTextEngine::formatIndex(const QScriptItem *si) const
if (specialData && !specialData->resolvedFormats.isEmpty()) {
QTextFormatCollection *collection = formatCollection();
Q_ASSERT(collection);
- return collection->indexForFormat(specialData->resolvedFormats.at(si - &layoutData->items[0]));
+ return collection->indexForFormat(specialData->resolvedFormats.at(si - &layoutData->items.at(0)));
}
QTextDocumentPrivate *p = block.docHandle();
@@ -3140,7 +3146,7 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
if (!attributes)
return QString();
for (int i = 0; i < layoutData->items.size(); ++i) {
- QScriptItem &si = layoutData->items[i];
+ const QScriptItem &si = layoutData->items.at(i);
if (!si.num_glyphs)
shape(i);
@@ -3325,24 +3331,29 @@ QFixed QTextEngine::calculateTabWidth(int item, QFixed x) const
QList<QTextOption::Tab> tabArray = option.tabs();
if (!tabArray.isEmpty()) {
if (isRightToLeft()) { // rebase the tabArray positions.
- QList<QTextOption::Tab> newTabs;
- newTabs.reserve(tabArray.count());
- QList<QTextOption::Tab>::Iterator iter = tabArray.begin();
- while(iter != tabArray.end()) {
- QTextOption::Tab tab = *iter;
- if (tab.type == QTextOption::LeftTab)
- tab.type = QTextOption::RightTab;
- else if (tab.type == QTextOption::RightTab)
- tab.type = QTextOption::LeftTab;
- newTabs << tab;
- ++iter;
+ auto isLeftOrRightTab = [](const QTextOption::Tab &tab) {
+ return tab.type == QTextOption::LeftTab || tab.type == QTextOption::RightTab;
+ };
+ const auto cbegin = tabArray.cbegin();
+ const auto cend = tabArray.cend();
+ const auto cit = std::find_if(cbegin, cend, isLeftOrRightTab);
+ if (cit != cend) {
+ const int index = std::distance(cbegin, cit);
+ auto iter = tabArray.begin() + index;
+ const auto end = tabArray.end();
+ while (iter != end) {
+ QTextOption::Tab &tab = *iter;
+ if (tab.type == QTextOption::LeftTab)
+ tab.type = QTextOption::RightTab;
+ else if (tab.type == QTextOption::RightTab)
+ tab.type = QTextOption::LeftTab;
+ ++iter;
+ }
}
- tabArray = newTabs;
}
- for (int i = 0; i < tabArray.size(); ++i) {
- QFixed tab = QFixed::fromReal(tabArray[i].position) * dpiScale;
+ for (const QTextOption::Tab &tabSpec : qAsConst(tabArray)) {
+ QFixed tab = QFixed::fromReal(tabSpec.position) * dpiScale;
if (tab > x) { // this is the tab we need.
- QTextOption::Tab tabSpec = tabArray[i];
int tabSectionEnd = layoutData->string.count();
if (tabSpec.type == QTextOption::RightTab || tabSpec.type == QTextOption::CenterTab) {
// find next tab to calculate the width required.
@@ -3363,7 +3374,7 @@ QFixed QTextEngine::calculateTabWidth(int item, QFixed x) const
QFixed length;
// Calculate the length of text between this tab and the tabSectionEnd
for (int i=item; i < layoutData->items.count(); i++) {
- QScriptItem &item = layoutData->items[i];
+ const QScriptItem &item = layoutData->items.at(i);
if (item.position > tabSectionEnd || item.position <= si.position)
continue;
shape(i); // first, lets make sure relevant text is already shaped
@@ -3663,11 +3674,12 @@ int QTextEngine::lineNumberForTextPosition(int pos)
return -1;
}
-void QTextEngine::insertionPointsForLine(int lineNum, QVector<int> &insertionPoints)
+std::vector<int> QTextEngine::insertionPointsForLine(int lineNum)
{
QTextLineItemIterator iterator(this, lineNum);
- insertionPoints.reserve(iterator.line.length);
+ std::vector<int> insertionPoints;
+ insertionPoints.reserve(size_t(iterator.line.length));
bool lastLine = lineNum >= lines.size() - 1;
@@ -3685,25 +3697,22 @@ void QTextEngine::insertionPointsForLine(int lineNum, QVector<int> &insertionPoi
insertionPoints.push_back(i);
}
}
+ return insertionPoints;
}
int QTextEngine::endOfLine(int lineNum)
{
- QVector<int> insertionPoints;
- insertionPointsForLine(lineNum, insertionPoints);
-
+ const auto insertionPoints = insertionPointsForLine(lineNum);
if (insertionPoints.size() > 0)
- return insertionPoints.constLast();
+ return insertionPoints.back();
return 0;
}
int QTextEngine::beginningOfLine(int lineNum)
{
- QVector<int> insertionPoints;
- insertionPointsForLine(lineNum, insertionPoints);
-
+ const auto insertionPoints = insertionPointsForLine(lineNum);
if (insertionPoints.size() > 0)
- return insertionPoints.constFirst();
+ return insertionPoints.front();
return 0;
}
@@ -3720,10 +3729,8 @@ int QTextEngine::positionAfterVisualMovement(int pos, QTextCursor::MoveOperation
if (lineNum < 0)
return pos;
- QVector<int> insertionPoints;
- insertionPointsForLine(lineNum, insertionPoints);
- int i, max = insertionPoints.size();
- for (i = 0; i < max; i++)
+ const auto insertionPoints = insertionPointsForLine(lineNum);
+ for (size_t i = 0, max = insertionPoints.size(); i < max; ++i)
if (pos == insertionPoints[i]) {
if (moveRight) {
if (i + 1 < max)
@@ -4001,7 +4008,7 @@ QTextLineItemIterator::QTextLineItemIterator(QTextEngine *_eng, int _lineNum, co
QVarLengthArray<uchar> levels(nItems);
for (int i = 0; i < nItems; ++i)
- levels[i] = eng->layoutData->items[i+firstItem].analysis.bidiLevel;
+ levels[i] = eng->layoutData->items.at(i + firstItem).analysis.bidiLevel;
QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
eng->shapeLine(line);
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index f9eb055478..e9187ea605 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -74,6 +74,7 @@
#include <private/qunicodetools_p.h>
#include <stdlib.h>
+#include <vector>
QT_BEGIN_NAMESPACE
@@ -142,9 +143,10 @@ struct Q_AUTOTEST_EXPORT QScriptAnalysis
LineOrParagraphSeparator = 4,
Space = 5,
SpaceTabOrObject = Space,
- Tab = 6,
+ Nbsp = 6,
+ Tab = 7,
TabOrObject = Tab,
- Object = 7
+ Object = 8
};
enum BidiFlags {
BidiBN = 1,
@@ -632,7 +634,7 @@ public:
int nextLogicalPosition(int oldPos) const;
int lineNumberForTextPosition(int pos);
int positionAfterVisualMovement(int oldPos, QTextCursor::MoveOperation op);
- void insertionPointsForLine(int lineNum, QVector<int> &insertionPoints);
+ std::vector<int> insertionPointsForLine(int lineNum);
void resetFontEngineCache();
void enableDelayDecorations(bool enable = true) { delayDecorations = enable; }
diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
index 08106db6ce..4957da1908 100644
--- a/src/gui/text/qtextformat.cpp
+++ b/src/gui/text/qtextformat.cpp
@@ -514,7 +514,7 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
\value BlockFormat The object formats a text block
\value CharFormat The object formats a single character
\value ListFormat The object formats a list
- \omitvalue TableFormat Unused Value, a table's FormatType is FrameFormat.
+ \omitvalue TableFormat \omit Unused Value, a table's FormatType is FrameFormat. \endomit
\value FrameFormat The object formats a frame
\value UserFormat
@@ -556,6 +556,8 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
\value LineHeightType
\value BlockNonBreakableLines
\value BlockTrailingHorizontalRulerWidth The width of a horizontal ruler element.
+ \value HeadingLevel The level of a heading, for example 1 corresponds to an HTML H1 tag; otherwise 0.
+ This enum value has been added in Qt 5.12.
Character properties
@@ -2246,6 +2248,34 @@ QList<QTextOption::Tab> QTextBlockFormat::tabPositions() const
/*!
+ \fn void QTextBlockFormat::setHeadingLevel(int level)
+ \since 5.12
+
+ Sets the paragraph's heading level, where 1 is the highest-level heading
+ type (usually with the largest possible heading font size), and increasing
+ values are progressively deeper into the document (and usually with smaller
+ font sizes). For example when reading an HTML H1 tag, the heading level is
+ set to 1. Setting the heading level does not automatically change the font
+ size; however QTextDocumentFragment::fromHtml() sets both the heading level
+ and the font size simultaneously.
+
+ If the paragraph is not a heading, the level should be set to 0 (the default).
+
+ \sa headingLevel()
+*/
+
+
+/*!
+ \fn int QTextBlockFormat::headingLevel() const
+ \since 5.12
+
+ Returns the paragraph's heading level if it is a heading, or 0 if not.
+
+ \sa setHeadingLevel()
+*/
+
+
+/*!
\fn void QTextBlockFormat::setLineHeight(qreal height, int heightType)
\since 4.8
@@ -3047,7 +3077,8 @@ QTextTableFormat::QTextTableFormat(const QTextFormat &fmt)
REPLACEMENT CHARACTER) which has an associated QTextImageFormat. The
image format specifies a name with setName() that is used to
locate the image. The size of the rectangle that the image will
- occupy is specified using setWidth() and setHeight().
+ occupy is specified in pixels using setWidth() and setHeight().
+ The desired image quality may be set with setQuality().
Images can be supplied in any format for which Qt has an image
reader, so SVG drawings can be included alongside PNG, TIFF and
@@ -3137,6 +3168,28 @@ QTextImageFormat::QTextImageFormat(const QTextFormat &fmt)
*/
/*!
+ \fn void QTextImageFormat::setQuality(int quality = 100)
+ \since 5.12
+
+ Sets the quality that should be used by exporters when exporting the image. QTextDocumentWriter
+ will export jpg images with the \a quality set here when exporting to ODF files if \a quality is
+ set to a value between 0 and 100. Or it will export png images if \a quality is set to 100
+ (default) or greater.
+
+ \sa quality()
+*/
+
+
+/*!
+ \fn qreal QTextImageFormat::quality() const
+ \since 5.12
+
+ Returns the value set by setQuality().
+
+ \sa setQuality()
+*/
+
+/*!
\fn void QTextCharFormat::setFontCapitalization(QFont::Capitalization capitalization)
\since 4.4
diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h
index 28c3035537..a8e573d5a4 100644
--- a/src/gui/text/qtextformat.h
+++ b/src/gui/text/qtextformat.h
@@ -175,6 +175,7 @@ public:
LineHeightType = 0x1049,
BlockNonBreakableLines = 0x1050,
BlockTrailingHorizontalRulerWidth = 0x1060,
+ HeadingLevel = 0x1070,
// character properties
FirstFontProperty = 0x1FE0,
@@ -249,6 +250,7 @@ public:
ImageName = 0x5000,
ImageWidth = 0x5010,
ImageHeight = 0x5011,
+ ImageQuality = 0x5014,
// internal
/*
@@ -624,6 +626,11 @@ public:
inline int indent() const
{ return intProperty(BlockIndent); }
+ inline void setHeadingLevel(int alevel)
+ { setProperty(HeadingLevel, alevel); }
+ inline int headingLevel() const
+ { return intProperty(HeadingLevel); }
+
inline void setLineHeight(qreal height, int heightType)
{ setProperty(LineHeight, height); setProperty(LineHeightType, heightType); }
inline qreal lineHeight(qreal scriptLineHeight, qreal scaling) const;
@@ -748,6 +755,10 @@ public:
inline qreal height() const
{ return doubleProperty(ImageHeight); }
+ inline void setQuality(int quality = 100);
+ inline int quality() const
+ { return intProperty(ImageQuality); }
+
protected:
explicit QTextImageFormat(const QTextFormat &format);
friend class QTextFormat;
@@ -764,6 +775,9 @@ inline void QTextImageFormat::setWidth(qreal awidth)
inline void QTextImageFormat::setHeight(qreal aheight)
{ setProperty(ImageHeight, aheight); }
+inline void QTextImageFormat::setQuality(int aquality)
+{ setProperty(ImageQuality, aquality); }
+
class Q_GUI_EXPORT QTextFrameFormat : public QTextFormat
{
public:
diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp
index 9154182df1..4be800b251 100644
--- a/src/gui/text/qtexthtmlparser.cpp
+++ b/src/gui/text/qtexthtmlparser.cpp
@@ -448,13 +448,6 @@ static const QTextHtmlElement elements[Html_NumElements]= {
{ "var", Html_var, QTextHtmlElement::DisplayInline },
};
-#if defined(Q_CC_MSVC) && _MSC_VER < 1600
-static bool operator<(const QTextHtmlElement &e1, const QTextHtmlElement &e2)
-{
- return QLatin1String(e1.name) < QLatin1String(e2.name);
-}
-#endif
-
static bool operator<(const QString &str, const QTextHtmlElement &e)
{
return str < QLatin1String(e.name);
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 6e824b2ed1..ca6866d836 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -1006,10 +1006,8 @@ static void addSelectedRegionsToPath(QTextEngine *eng, int lineNumber, const QPo
}
if (lastSelectionWidth > 0) {
- QRectF rect = boundingRect & QRectF(lastSelectionX.toReal(), selectionY, lastSelectionWidth.toReal(), lineHeight);
- rect.moveLeft(qFloor(rect.left()));
- rect.moveTop(qFloor(rect.top()));
- region->addRect(rect);
+ const QRectF rect = boundingRect & QRectF(lastSelectionX.toReal(), selectionY, lastSelectionWidth.toReal(), lineHeight);
+ region->addRect(rect.toAlignedRect());
}
lastSelectionX = selectionX;
@@ -1017,10 +1015,8 @@ static void addSelectedRegionsToPath(QTextEngine *eng, int lineNumber, const QPo
}
}
if (lastSelectionWidth > 0) {
- QRectF rect = boundingRect & QRectF(lastSelectionX.toReal(), selectionY, lastSelectionWidth.toReal(), lineHeight);
- rect.moveLeft(qFloor(rect.left()));
- rect.moveTop(qFloor(rect.top()));
- region->addRect(rect);
+ const QRectF rect = boundingRect & QRectF(lastSelectionX.toReal(), selectionY, lastSelectionWidth.toReal(), lineHeight);
+ region->addRect(rect.toAlignedRect());
}
}
@@ -2135,7 +2131,7 @@ static void setPenAndDrawBackground(QPainter *p, const QPen &defaultPen, const Q
QBrush bg = chf.background();
if (bg.style() != Qt::NoBrush && !chf.property(SuppressBackground).toBool())
- p->fillRect(QRectF(qFloor(r.x()), qFloor(r.y()), r.width(), r.height()), bg);
+ p->fillRect(r.toAlignedRect(), bg);
if (c.style() != Qt::NoBrush) {
p->setPen(QPen(c, 0));
}
@@ -2614,12 +2610,13 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR
QPainterPrivate::get(p)->drawTextItem(pos, gf, eng);
}
- if (si.analysis.flags == QScriptAnalysis::Space
+ if ((si.analysis.flags == QScriptAnalysis::Space
+ || si.analysis.flags == QScriptAnalysis::Nbsp)
&& (eng->option.flags() & QTextOption::ShowTabsAndSpaces)) {
QBrush c = format.foreground();
if (c.style() != Qt::NoBrush)
p->setPen(c.color());
- QChar visualSpace((ushort)0xb7);
+ QChar visualSpace(si.analysis.flags == QScriptAnalysis::Space ? (ushort)0xb7 : (ushort)0xb0);
p->drawText(QPointF(iterator.x.toReal(), itemBaseLine.toReal()), visualSpace);
p->setPen(pen);
}
@@ -2845,9 +2842,7 @@ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const
bool rtl = eng->isRightToLeft();
eng->shapeLine(line);
- QVector<int> insertionPoints;
- if (visual && rtl)
- eng->insertionPointsForLine(lineNum, insertionPoints);
+ const auto insertionPoints = (visual && rtl) ? eng->insertionPointsForLine(lineNum) : std::vector<int>();
int nchars = 0;
for (int i = 0; i < nItems; ++i) {
int item = visualOrder[i]+firstItem;
@@ -2979,7 +2974,7 @@ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const
continue;
}
if (rtl && nchars > 0)
- return insertionPoints[lastLine ? nchars : nchars - 1];
+ return insertionPoints[size_t(lastLine ? nchars : nchars - 1)];
}
return eng->positionInLigature(&si, end, x, pos, -1,
cpos == QTextLine::CursorOnCharacter);
@@ -3007,9 +3002,8 @@ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const
// character between lines is a space and we want
// to position the cursor to the left of that
// character.
- // ###### breaks with japanese for example
if (this->index < eng->lines.count() - 1)
- --maxPos;
+ maxPos = eng->previousLogicalPosition(maxPos);
pos = qMin(pos, maxPos);
return pos;
diff --git a/src/gui/text/qtextodfwriter.cpp b/src/gui/text/qtextodfwriter.cpp
index 30f5bc1051..d8218ab613 100644
--- a/src/gui/text/qtextodfwriter.cpp
+++ b/src/gui/text/qtextodfwriter.cpp
@@ -183,6 +183,35 @@ static QString bulletChar(QTextListFormat::Style style)
}
}
+static QString borderStyleName(QTextFrameFormat::BorderStyle style)
+{
+ switch (style) {
+ case QTextFrameFormat::BorderStyle_None:
+ return QString::fromLatin1("none");
+ case QTextFrameFormat::BorderStyle_Dotted:
+ return QString::fromLatin1("dotted");
+ case QTextFrameFormat::BorderStyle_Dashed:
+ return QString::fromLatin1("dashed");
+ case QTextFrameFormat::BorderStyle_Solid:
+ return QString::fromLatin1("solid");
+ case QTextFrameFormat::BorderStyle_Double:
+ return QString::fromLatin1("double");
+ case QTextFrameFormat::BorderStyle_DotDash:
+ return QString::fromLatin1("dashed");
+ case QTextFrameFormat::BorderStyle_DotDotDash:
+ return QString::fromLatin1("dotted");
+ case QTextFrameFormat::BorderStyle_Groove:
+ return QString::fromLatin1("groove");
+ case QTextFrameFormat::BorderStyle_Ridge:
+ return QString::fromLatin1("ridge");
+ case QTextFrameFormat::BorderStyle_Inset:
+ return QString::fromLatin1("inset");
+ case QTextFrameFormat::BorderStyle_Outset:
+ return QString::fromLatin1("outset");
+ }
+ return QString::fromLatin1("");
+}
+
void QTextOdfWriter::writeFrame(QXmlStreamWriter &writer, const QTextFrame *frame)
{
Q_ASSERT(frame);
@@ -190,8 +219,21 @@ void QTextOdfWriter::writeFrame(QXmlStreamWriter &writer, const QTextFrame *fram
if (table) { // Start a table.
writer.writeStartElement(tableNS, QString::fromLatin1("table"));
- writer.writeEmptyElement(tableNS, QString::fromLatin1("table-column"));
- writer.writeAttribute(tableNS, QString::fromLatin1("number-columns-repeated"), QString::number(table->columns()));
+ writer.writeAttribute(tableNS, QString::fromLatin1("style-name"),
+ QString::fromLatin1("Table%1").arg(table->formatIndex()));
+ // check if column widths are set, if so add TableNS line above for all columns and link to style
+ if (m_tableFormatsWithColWidthConstraints.contains(table->formatIndex())) {
+ for (int colit = 0; colit < table->columns(); ++colit) {
+ writer.writeStartElement(tableNS, QString::fromLatin1("table-column"));
+ writer.writeAttribute(tableNS, QString::fromLatin1("style-name"),
+ QString::fromLatin1("Table%1.%2").arg(table->formatIndex()).arg(colit));
+ writer.writeEndElement();
+ }
+ } else {
+ writer.writeEmptyElement(tableNS, QString::fromLatin1("table-column"));
+ writer.writeAttribute(tableNS, QString::fromLatin1("number-columns-repeated"),
+ QString::number(table->columns()));
+ }
} else if (frame->document() && frame->document()->rootFrame() != frame) { // start a section
writer.writeStartElement(textNS, QString::fromLatin1("section"));
}
@@ -219,7 +261,15 @@ void QTextOdfWriter::writeFrame(QXmlStreamWriter &writer, const QTextFrame *fram
if (cell.rowSpan() > 1)
writer.writeAttribute(tableNS, QString::fromLatin1("number-rows-spanned"), QString::number(cell.rowSpan()));
if (cell.format().isTableCellFormat()) {
- writer.writeAttribute(tableNS, QString::fromLatin1("style-name"), QString::fromLatin1("T%1").arg(cell.tableCellFormatIndex()));
+ if (m_cellFormatsInTablesWithBorders.contains(cell.tableCellFormatIndex()) ) {
+ // writing table:style-name tag in <table:table-cell> element
+ writer.writeAttribute(tableNS, QString::fromLatin1("style-name"),
+ QString::fromLatin1("TB%1.%2").arg(table->formatIndex())
+ .arg(cell.tableCellFormatIndex()));
+ } else {
+ writer.writeAttribute(tableNS, QString::fromLatin1("style-name"),
+ QString::fromLatin1("T%1").arg(cell.tableCellFormatIndex()));
+ }
}
}
writeBlock(writer, block);
@@ -326,7 +376,10 @@ void QTextOdfWriter::writeBlock(QXmlStreamWriter &writer, const QTextBlock &bloc
if (i < fragmentText.count()) {
if (character.unicode() == 0x2028) { // soft-return
//if (exportedIndex < i)
- writer.writeCharacters(fragmentText.mid(exportedIndex, i - exportedIndex));
+ writer.writeCharacters(fragmentText.mid(exportedIndex, i - exportedIndex));
+ // adding tab before line-break, so last line in justified paragraph
+ // will not stretch to the end
+ writer.writeEmptyElement(textNS, QString::fromLatin1("tab"));
writer.writeEmptyElement(textNS, QString::fromLatin1("line-break"));
exportedIndex = i+1;
continue;
@@ -367,7 +420,6 @@ void QTextOdfWriter::writeInlineCharacter(QXmlStreamWriter &writer, const QTextF
QTextImageFormat imageFormat = fragment.charFormat().toImageFormat();
writer.writeAttribute(drawNS, QString::fromLatin1("name"), imageFormat.name());
- // vvv Copy pasted mostly from Qt =================
QImage image;
QString name = imageFormat.name();
if (name.startsWith(QLatin1String(":/"))) // auto-detect resources
@@ -387,26 +439,33 @@ void QTextOdfWriter::writeInlineCharacter(QXmlStreamWriter &writer, const QTextF
}
}
- // ^^^ Copy pasted mostly from Qt =================
if (! image.isNull()) {
QBuffer imageBytes;
- QImageWriter imageWriter(&imageBytes, "png");
- imageWriter.write(image);
QString filename = m_strategy->createUniqueImageName();
- m_strategy->addFile(filename, QString::fromLatin1("image/png"), imageBytes.data());
-
+ int imgQuality = imageFormat.quality();
+ if (imgQuality >= 100 || imgQuality < 0 || image.hasAlphaChannel()) {
+ QImageWriter imageWriter(&imageBytes, "png");
+ imageWriter.write(image);
+ m_strategy->addFile(filename, QString::fromLatin1("image/png"), imageBytes.data());
+ } else {
+ // Write images without alpha channel as jpg with quality set by QTextImageFormat
+ QImageWriter imageWriter(&imageBytes, "jpg");
+ imageWriter.setQuality(imgQuality);
+ imageWriter.write(image);
+ m_strategy->addFile(filename, QString::fromLatin1("image/jpg"), imageBytes.data());
+ }
// get the width/height from the format.
- qreal width = (imageFormat.hasProperty(QTextFormat::ImageWidth)) ? imageFormat.width() : image.width();
+ qreal width = imageFormat.hasProperty(QTextFormat::ImageWidth)
+ ? imageFormat.width() : image.width();
writer.writeAttribute(svgNS, QString::fromLatin1("width"), pixelToPoint(width));
- qreal height = (imageFormat.hasProperty(QTextFormat::ImageHeight)) ? imageFormat.height() : image.height();
+ qreal height = imageFormat.hasProperty(QTextFormat::ImageHeight)
+ ? imageFormat.height() : image.height();
writer.writeAttribute(svgNS, QString::fromLatin1("height"), pixelToPoint(height));
-
writer.writeStartElement(drawNS, QString::fromLatin1("image"));
writer.writeAttribute(xlinkNS, QString::fromLatin1("href"), filename);
writer.writeEndElement(); // image
}
}
-
writer.writeEndElement(); // frame
}
@@ -421,7 +480,7 @@ void QTextOdfWriter::writeFormats(QXmlStreamWriter &writer, const QSet<int> &for
switch (textFormat.type()) {
case QTextFormat::CharFormat:
if (textFormat.isTableCellFormat())
- writeTableCellFormat(writer, textFormat.toTableCellFormat(), formatIndex);
+ writeTableCellFormat(writer, textFormat.toTableCellFormat(), formatIndex, allStyles);
else
writeCharacterFormat(writer, textFormat.toCharFormat(), formatIndex);
break;
@@ -432,10 +491,15 @@ void QTextOdfWriter::writeFormats(QXmlStreamWriter &writer, const QSet<int> &for
writeListFormat(writer, textFormat.toListFormat(), formatIndex);
break;
case QTextFormat::FrameFormat:
- writeFrameFormat(writer, textFormat.toFrameFormat(), formatIndex);
+ if (textFormat.isTableFormat())
+ writeTableFormat(writer, textFormat.toTableFormat(), formatIndex);
+ else
+ writeFrameFormat(writer, textFormat.toFrameFormat(), formatIndex);
break;
case QTextFormat::TableFormat:
- ;break;
+ // this case never happens, because TableFormat is a FrameFormat
+ Q_UNREACHABLE();
+ break;
}
}
@@ -449,6 +513,36 @@ void QTextOdfWriter::writeBlockFormat(QXmlStreamWriter &writer, QTextBlockFormat
writer.writeAttribute(styleNS, QString::fromLatin1("family"), QString::fromLatin1("paragraph"));
writer.writeStartElement(styleNS, QString::fromLatin1("paragraph-properties"));
+ if (format.hasProperty(QTextBlockFormat::LineHeightType)) {
+ const int blockLineHeightType = format.lineHeightType();
+ const qreal blockLineHeight = format.lineHeight();
+ QString type, value;
+ switch (blockLineHeightType) {
+ case QTextBlockFormat::SingleHeight:
+ type = QString::fromLatin1("line-height");
+ value = QString::fromLatin1("100%");
+ break;
+ case QTextBlockFormat::ProportionalHeight:
+ type = QString::fromLatin1("line-height");
+ value = QString::number(blockLineHeight) + QString::fromLatin1("%");
+ break;
+ case QTextBlockFormat::FixedHeight:
+ type = QString::fromLatin1("line-height");
+ value = pixelToPoint(qMax(qreal(0.), blockLineHeight));
+ break;
+ case QTextBlockFormat::MinimumHeight:
+ type = QString::fromLatin1("line-height-at-least");
+ value = pixelToPoint(qMax(qreal(0.), blockLineHeight));
+ break;
+ case QTextBlockFormat::LineDistanceHeight:
+ type = QString::fromLatin1("line-spacing");
+ value = pixelToPoint(qMax(qreal(0.), blockLineHeight));
+ }
+
+ if (!type.isNull())
+ writer.writeAttribute(styleNS, type, value);
+ }
+
if (format.hasProperty(QTextFormat::BlockAlignment)) {
const Qt::Alignment alignment = format.alignment() & Qt::AlignHorizontal_Mask;
QString value;
@@ -693,14 +787,108 @@ void QTextOdfWriter::writeFrameFormat(QXmlStreamWriter &writer, QTextFrameFormat
// PageBreakFlags pageBreakPolicy () const
}
-void QTextOdfWriter::writeTableCellFormat(QXmlStreamWriter &writer, QTextTableCellFormat format, int formatIndex) const
+void QTextOdfWriter::writeTableFormat(QXmlStreamWriter &writer, QTextTableFormat format, int formatIndex) const
{
+ // start writing table style element
writer.writeStartElement(styleNS, QString::fromLatin1("style"));
- writer.writeAttribute(styleNS, QString::fromLatin1("name"), QString::fromLatin1("T%1").arg(formatIndex));
+ writer.writeAttribute(styleNS, QString::fromLatin1("name"),
+ QString::fromLatin1("Table%1").arg(formatIndex));
writer.writeAttribute(styleNS, QString::fromLatin1("family"), QString::fromLatin1("table"));
writer.writeEmptyElement(styleNS, QString::fromLatin1("table-properties"));
+ if (m_tableFormatsWithBorders.contains(formatIndex)) {
+ // write border format collapsing to table style
+ writer.writeAttribute(tableNS, QString::fromLatin1("border-model"),
+ QString::fromLatin1("collapsing"));
+ }
+ const char* align = nullptr;
+ switch (format.alignment()) {
+ case Qt::AlignLeft:
+ align = "left";
+ break;
+ case Qt::AlignRight:
+ align = "right";
+ break;
+ case Qt::AlignHCenter:
+ align = "center";
+ break;
+ case Qt::AlignJustify:
+ align = "margins";
+ break;
+ }
+ if (align)
+ writer.writeAttribute(tableNS, QString::fromLatin1("align"), QString::fromLatin1(align));
+ if (format.width().rawValue()) {
+ writer.writeAttribute(styleNS, QString::fromLatin1("width"),
+ QString::number(format.width().rawValue()) + QLatin1String("pt"));
+ }
+ writer.writeEndElement();
+ // start writing table-column style element
+ if (format.columnWidthConstraints().size()) {
+ // write table-column-properties for columns with constraints
+ m_tableFormatsWithColWidthConstraints.insert(formatIndex); // needed for linking of columns to styles
+ for (int colit = 0; colit < format.columnWidthConstraints().size(); ++colit) {
+ writer.writeStartElement(styleNS, QString::fromLatin1("style"));
+ writer.writeAttribute(styleNS, QString::fromLatin1("name"),
+ QString::fromLatin1("Table%1.%2").arg(formatIndex).arg(colit));
+ writer.writeAttribute(styleNS, QString::fromLatin1("family"), QString::fromLatin1("table-column"));
+ writer.writeEmptyElement(styleNS, QString::fromLatin1("table-column-properties"));
+ QString columnWidth;
+ if (format.columnWidthConstraints().at(colit).type() == QTextLength::PercentageLength) {
+ columnWidth = QString::number(format.columnWidthConstraints().at(colit).rawValue())
+ + QLatin1String("%");
+ } else if (format.columnWidthConstraints().at(colit).type() == QTextLength::FixedLength) {
+ columnWidth = QString::number(format.columnWidthConstraints().at(colit).rawValue())
+ + QLatin1String("pt");
+ } else {
+ //!! HARD-CODING variableWidth Constraints to 100% / nr constraints
+ columnWidth = QString::number(100 / format.columnWidthConstraints().size())
+ + QLatin1String("%");
+ }
+ writer.writeAttribute(styleNS, QString::fromLatin1("column-width"), columnWidth);
+ writer.writeEndElement();
+ }
+ }
+}
+
+void QTextOdfWriter::writeTableCellFormat(QXmlStreamWriter &writer, QTextTableCellFormat format,
+ int formatIndex, QVector<QTextFormat> &styles) const
+{
+ // check for all table cells here if they are in a table with border
+ if (m_cellFormatsInTablesWithBorders.contains(formatIndex)) {
+ const QVector<int> tableIdVector = m_cellFormatsInTablesWithBorders.value(formatIndex);
+ for (const auto &tableId : tableIdVector) {
+ const auto &tmpStyle = styles.at(tableId);
+ if (tmpStyle.isTableFormat()) {
+ QTextTableFormat tableFormatTmp = tmpStyle.toTableFormat();
+ tableCellStyleElement(writer, formatIndex, format, true, tableId, tableFormatTmp);
+ } else {
+ qDebug("QTextOdfWriter::writeTableCellFormat: ERROR writing table border format");
+ }
+ }
+ }
+ tableCellStyleElement(writer, formatIndex, format, false);
+}
+void QTextOdfWriter::tableCellStyleElement(QXmlStreamWriter &writer, const int &formatIndex,
+ const QTextTableCellFormat &format,
+ bool hasBorder, int tableId,
+ const QTextTableFormat tableFormatTmp) const {
+ writer.writeStartElement(styleNS, QString::fromLatin1("style"));
+ if (hasBorder) {
+ writer.writeAttribute(styleNS, QString::fromLatin1("name"),
+ QString::fromLatin1("TB%1.%2").arg(tableId).arg(formatIndex));
+ } else {
+ writer.writeAttribute(styleNS, QString::fromLatin1("name"), QString::fromLatin1("T%1").arg(formatIndex));
+ }
+ writer.writeAttribute(styleNS, QString::fromLatin1("family"), QString::fromLatin1("table-cell"));
+ writer.writeEmptyElement(styleNS, QString::fromLatin1("table-cell-properties"));
+ if (hasBorder) {
+ writer.writeAttribute(foNS, QString::fromLatin1("border"),
+ pixelToPoint(tableFormatTmp.border()) + QLatin1String(" ")
+ + borderStyleName(tableFormatTmp.borderStyle())
+ + QLatin1String(" #000000")); //!! HARD-CODING color black
+ }
qreal padding = format.topPadding();
if (padding > 0 && padding == format.bottomPadding()
&& padding == format.leftPadding() && padding == format.rightPadding()) {
@@ -710,16 +898,19 @@ void QTextOdfWriter::writeTableCellFormat(QXmlStreamWriter &writer, QTextTableCe
if (padding > 0)
writer.writeAttribute(foNS, QString::fromLatin1("padding-top"), pixelToPoint(padding));
if (format.bottomPadding() > 0)
- writer.writeAttribute(foNS, QString::fromLatin1("padding-bottom"), pixelToPoint(format.bottomPadding()));
+ writer.writeAttribute(foNS, QString::fromLatin1("padding-bottom"),
+ pixelToPoint(format.bottomPadding()));
if (format.leftPadding() > 0)
- writer.writeAttribute(foNS, QString::fromLatin1("padding-left"), pixelToPoint(format.leftPadding()));
+ writer.writeAttribute(foNS, QString::fromLatin1("padding-left"),
+ pixelToPoint(format.leftPadding()));
if (format.rightPadding() > 0)
- writer.writeAttribute(foNS, QString::fromLatin1("padding-right"), pixelToPoint(format.rightPadding()));
+ writer.writeAttribute(foNS, QString::fromLatin1("padding-right"),
+ pixelToPoint(format.rightPadding()));
}
if (format.hasProperty(QTextFormat::TextVerticalAlignment)) {
QString pos;
- switch (format.verticalAlignment()) {
+ switch (format.verticalAlignment()) { // TODO - review: doesn't handle all cases
case QTextCharFormat::AlignMiddle:
pos = QString::fromLatin1("middle"); break;
case QTextCharFormat::AlignTop:
@@ -736,8 +927,6 @@ void QTextOdfWriter::writeTableCellFormat(QXmlStreamWriter &writer, QTextTableCe
// ODF just search for style-table-cell-properties-attlist)
// QTextFormat::BackgroundImageUrl
// format.background
- // QTextFormat::FrameBorder
-
writer.writeEndElement(); // style
}
@@ -815,8 +1004,28 @@ bool QTextOdfWriter::writeAll()
const QList<int> copy = formats.toList();
for (auto index : copy) {
QTextObject *object = m_document->objectForFormat(allFormats[index]);
- if (object)
+ if (object) {
formats << object->formatIndex();
+ if (auto *tableobject = qobject_cast<QTextTable *>(object)) {
+ if (tableobject->format().borderStyle()) {
+ int tableID = tableobject->formatIndex();
+ m_tableFormatsWithBorders.insert(tableID);
+ // loop through all rows and cols of table and store cell IDs,
+ // create Hash with cell ID as Key and table IDs as Vector
+ for (int rowindex = 0; rowindex < tableobject->rows(); ++rowindex) {
+ for (int colindex = 0; colindex < tableobject->columns(); ++colindex) {
+ const int cellFormatID = tableobject->cellAt(rowindex, colindex).tableCellFormatIndex();
+ QVector<int> tableIdsTmp;
+ if (m_cellFormatsInTablesWithBorders.contains(cellFormatID))
+ tableIdsTmp = m_cellFormatsInTablesWithBorders.value(cellFormatID);
+ if (!tableIdsTmp.contains(tableID))
+ tableIdsTmp.append(tableID);
+ m_cellFormatsInTablesWithBorders.insert(cellFormatID, tableIdsTmp);
+ }
+ }
+ }
+ }
+ }
}
writeFormats(writer, formats);
diff --git a/src/gui/text/qtextodfwriter_p.h b/src/gui/text/qtextodfwriter_p.h
index d0dd7d2b5c..98a6fdfa96 100644
--- a/src/gui/text/qtextodfwriter_p.h
+++ b/src/gui/text/qtextodfwriter_p.h
@@ -56,8 +56,10 @@
//
#include <QtCore/QXmlStreamWriter>
+#include <QtCore/qhash.h>
#include <QtCore/qset.h>
#include <QtCore/qstack.h>
+#include <QtCore/qvector.h>
#include "qtextdocument_p.h"
#include "qtextdocumentwriter.h"
@@ -94,11 +96,21 @@ public:
void writeCharacterFormat(QXmlStreamWriter &writer, QTextCharFormat format, int formatIndex) const;
void writeListFormat(QXmlStreamWriter &writer, QTextListFormat format, int formatIndex) const;
void writeFrameFormat(QXmlStreamWriter &writer, QTextFrameFormat format, int formatIndex) const;
- void writeTableCellFormat(QXmlStreamWriter &writer, QTextTableCellFormat format, int formatIndex) const;
+ void writeTableFormat(QXmlStreamWriter &writer, QTextTableFormat format, int formatIndex) const;
+ void writeTableCellFormat(QXmlStreamWriter &writer, QTextTableCellFormat format, int formatIndex,
+ QVector<QTextFormat> &styles) const;
void writeFrame(QXmlStreamWriter &writer, const QTextFrame *frame);
void writeInlineCharacter(QXmlStreamWriter &writer, const QTextFragment &fragment) const;
const QString officeNS, textNS, styleNS, foNS, tableNS, drawNS, xlinkNS, svgNS;
+ const int defaultImageResolution = 11811; // 11811 dots per meter = (about) 300 dpi
+
+protected:
+ void tableCellStyleElement(QXmlStreamWriter &writer, const int &formatIndex,
+ const QTextTableCellFormat &format,
+ bool hasBorder, int tableId = 0,
+ const QTextTableFormat tableFormatTmp = QTextTableFormat()) const;
+
private:
const QTextDocument *m_document;
QIODevice *m_device;
@@ -108,6 +120,10 @@ private:
bool m_createArchive;
QStack<QTextList *> m_listStack;
+
+ QHash<int, QVector<int>> m_cellFormatsInTablesWithBorders;
+ QSet<int> m_tableFormatsWithBorders;
+ mutable QSet<int> m_tableFormatsWithColWidthConstraints;
};
QT_END_NAMESPACE
diff --git a/src/gui/text/qtextoption.cpp b/src/gui/text/qtextoption.cpp
index a3fa0e7351..2c2c05567f 100644
--- a/src/gui/text/qtextoption.cpp
+++ b/src/gui/text/qtextoption.cpp
@@ -307,7 +307,8 @@ QList<QTextOption::Tab> QTextOption::tabs() const
\value IncludeTrailingSpaces When this option is set, QTextLine::naturalTextWidth() and naturalTextRect() will
return a value that includes the width of trailing spaces in the text; otherwise
this width is excluded.
- \value ShowTabsAndSpaces Visualize spaces with little dots, and tabs with little arrows.
+ \value ShowTabsAndSpaces Visualize spaces with little dots, and tabs with little arrows. Non-breaking spaces are
+ shown differently to breaking spaces.
\value ShowLineAndParagraphSeparators Visualize line and paragraph separators with appropriate symbol characters.
\value ShowDocumentTerminator Visualize the end of the document with a section sign. This enum value was added
in Qt 5.7.
diff --git a/src/gui/text/qzip.cpp b/src/gui/text/qzip.cpp
index b68c36fd9e..fc7fbcac12 100644
--- a/src/gui/text/qzip.cpp
+++ b/src/gui/text/qzip.cpp
@@ -391,7 +391,6 @@ struct CentralFileHeader
uchar internal_file_attributes[2];
uchar external_file_attributes[4];
uchar offset_local_header[4];
- LocalFileHeader toLocalHeader() const;
};
Q_DECLARE_TYPEINFO(CentralFileHeader, Q_PRIMITIVE_TYPE);
@@ -541,19 +540,19 @@ public:
void addEntry(EntryType type, const QString &fileName, const QByteArray &contents);
};
-LocalFileHeader CentralFileHeader::toLocalHeader() const
+static LocalFileHeader toLocalHeader(const CentralFileHeader &ch)
{
LocalFileHeader h;
writeUInt(h.signature, 0x04034b50);
- copyUShort(h.version_needed, version_needed);
- copyUShort(h.general_purpose_bits, general_purpose_bits);
- copyUShort(h.compression_method, compression_method);
- copyUInt(h.last_mod_file, last_mod_file);
- copyUInt(h.crc_32, crc_32);
- copyUInt(h.compressed_size, compressed_size);
- copyUInt(h.uncompressed_size, uncompressed_size);
- copyUShort(h.file_name_length, file_name_length);
- copyUShort(h.extra_field_length, extra_field_length);
+ copyUShort(h.version_needed, ch.version_needed);
+ copyUShort(h.general_purpose_bits, ch.general_purpose_bits);
+ copyUShort(h.compression_method, ch.compression_method);
+ copyUInt(h.last_mod_file, ch.last_mod_file);
+ copyUInt(h.crc_32, ch.crc_32);
+ copyUInt(h.compressed_size, ch.compressed_size);
+ copyUInt(h.uncompressed_size, ch.uncompressed_size);
+ copyUShort(h.file_name_length, ch.file_name_length);
+ copyUShort(h.extra_field_length, ch.extra_field_length);
return h;
}
@@ -751,7 +750,7 @@ void QZipWriterPrivate::addEntry(EntryType type, const QString &fileName, const
fileHeaders.append(header);
- LocalFileHeader h = header.h.toLocalHeader();
+ LocalFileHeader h = toLocalHeader(header.h);
device->write((const char *)&h, sizeof(LocalFileHeader));
device->write(header.file_name);
device->write(data);
diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp
index dfd190ddd0..b6eac91478 100644
--- a/src/gui/util/qdesktopservices.cpp
+++ b/src/gui/util/qdesktopservices.cpp
@@ -141,6 +141,10 @@ void QOpenUrlHandlerRegistry::handlerDestroyed(QObject *handler)
same argument, and it will try to open the URL using the
appropriate mechanism for the user's desktop environment.
+ Combined with platform specific settings, the schemes registered by the
+ openUrl() function can also be exposed to other applications, opening up
+ for application deep linking or a very basic URL-based IPC mechanism.
+
\note Since Qt 5, storageLocation() and displayName() are replaced by functionality
provided by the QStandardPaths class.
@@ -183,12 +187,7 @@ void QOpenUrlHandlerRegistry::handlerDestroyed(QObject *handler)
\l{https://developer.apple.com/documentation/uikit/uiapplication/1622952-canopenurl}{canOpenURL(_:)}.
For example, the following lines enable URLs with the HTTPS scheme:
- \code
- <key>LSApplicationQueriesSchemes</key>
- <array>
- <string>https</string>
- </array>
- \endcode
+ \snippet code/src_gui_util_qdesktopservices.cpp 3
\sa setUrlHandler()
*/
@@ -245,6 +244,14 @@ bool QDesktopServices::openUrl(const QUrl &url)
The provided method must be implemented as a slot that only accepts a single QUrl
argument.
+ To use this function for receiving data from other apps on iOS you also need to
+ add the custom scheme to the \c CFBundleURLSchemes list in your Info.plist file:
+
+ \snippet code/src_gui_util_qdesktopservices.cpp 4
+
+ For more information, see the Apple Developer Documentation for
+ \l{https://developer.apple.com/documentation/uikit/core_app/allowing_apps_and_websites_to_link_to_your_content/communicating_with_other_apps_using_custom_urls?language=objc}{Communicating with Other Apps Using Custom URLs}.
+
If setUrlHandler() is used to set a new handler for a scheme which already
has a handler, the existing handler is simply replaced with the new one.
Since QDesktopServices does not take ownership of handlers, no objects are
@@ -324,14 +331,9 @@ void QDesktopServices::unsetUrlHandler(const QString &scheme)
wasn't called, while in Qt 5 it defaults to the name of the executable.
Therefore, if you still need to access the Qt 4 path (for example for data migration to Qt 5), replace
- \code
- QDesktopServices::storageLocation(QDesktopServices::DataLocation)
- \endcode
+ \snippet code/src_gui_util_qdesktopservices.cpp 5
with
- \code
- QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) +
- "/data/organization/application"
- \endcode
+ \snippet code/src_gui_util_qdesktopservices.cpp 6
(assuming an organization name and an application name were set).
*/
diff --git a/src/gui/util/qktxhandler.cpp b/src/gui/util/qktxhandler.cpp
new file mode 100644
index 0000000000..7eda4c46fb
--- /dev/null
+++ b/src/gui/util/qktxhandler.cpp
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** 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 "qktxhandler_p.h"
+#include "qtexturefiledata_p.h"
+#include <QtEndian>
+#include <QSize>
+
+//#define KTX_DEBUG
+#ifdef KTX_DEBUG
+#include <QDebug>
+#include <QMetaEnum>
+#include <QOpenGLTexture>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#define KTX_IDENTIFIER_LENGTH 12
+static const char ktxIdentifier[KTX_IDENTIFIER_LENGTH] = { '\xAB', 'K', 'T', 'X', ' ', '1', '1', '\xBB', '\r', '\n', '\x1A', '\n' };
+static const quint32 platformEndianIdentifier = 0x04030201;
+static const quint32 inversePlatformEndianIdentifier = 0x01020304;
+
+struct KTXHeader {
+ quint8 identifier[KTX_IDENTIFIER_LENGTH]; // Must match ktxIdentifier
+ quint32 endianness; // Either platformEndianIdentifier or inversePlatformEndianIdentifier, other values not allowed.
+ quint32 glType;
+ quint32 glTypeSize;
+ quint32 glFormat;
+ quint32 glInternalFormat;
+ quint32 glBaseInternalFormat;
+ quint32 pixelWidth;
+ quint32 pixelHeight;
+ quint32 pixelDepth;
+ quint32 numberOfArrayElements;
+ quint32 numberOfFaces;
+ quint32 numberOfMipmapLevels;
+ quint32 bytesOfKeyValueData;
+};
+
+static const quint32 headerSize = sizeof(KTXHeader);
+
+// Currently unused, declared for future reference
+struct KTXKeyValuePairItem {
+ quint32 keyAndValueByteSize;
+ /*
+ quint8 keyAndValue[keyAndValueByteSize];
+ quint8 valuePadding[3 - ((keyAndValueByteSize + 3) % 4)];
+ */
+};
+
+struct KTXMipmapLevel {
+ quint32 imageSize;
+ /*
+ for each array_element in numberOfArrayElements*
+ for each face in numberOfFaces
+ for each z_slice in pixelDepth*
+ for each row or row_of_blocks in pixelHeight*
+ for each pixel or block_of_pixels in pixelWidth
+ Byte data[format-specific-number-of-bytes]**
+ end
+ end
+ end
+ Byte cubePadding[0-3]
+ end
+ end
+ quint8 mipPadding[3 - ((imageSize + 3) % 4)]
+ */
+};
+
+bool QKtxHandler::canRead(const QByteArray &suffix, const QByteArray &block)
+{
+ Q_UNUSED(suffix)
+
+ return (qstrncmp(block.constData(), ktxIdentifier, KTX_IDENTIFIER_LENGTH) == 0);
+}
+
+QTextureFileData QKtxHandler::read()
+{
+ if (!device())
+ return QTextureFileData();
+
+ QByteArray buf = device()->readAll();
+ const quint32 dataSize = quint32(buf.size());
+ if (dataSize < headerSize || !canRead(QByteArray(), buf)) {
+ qCDebug(lcQtGuiTextureIO, "Invalid KTX file %s", logName().constData());
+ return QTextureFileData();
+ }
+
+ const KTXHeader *header = reinterpret_cast<const KTXHeader *>(buf.constData());
+ if (!checkHeader(*header)) {
+ qCDebug(lcQtGuiTextureIO, "Unsupported KTX file format in %s", logName().constData());
+ return QTextureFileData();
+ }
+
+ QTextureFileData texData;
+ texData.setData(buf);
+
+ texData.setSize(QSize(decode(header->pixelWidth), decode(header->pixelHeight)));
+ texData.setGLFormat(decode(header->glFormat));
+ texData.setGLInternalFormat(decode(header->glInternalFormat));
+ texData.setGLBaseInternalFormat(decode(header->glBaseInternalFormat));
+
+ texData.setNumLevels(decode(header->numberOfMipmapLevels));
+ quint32 offset = headerSize + decode(header->bytesOfKeyValueData);
+ const int maxLevels = qMin(texData.numLevels(), 32); // Cap iterations in case of corrupt file.
+ for (int i = 0; i < maxLevels; i++) {
+ if (offset + sizeof(KTXMipmapLevel) > dataSize) // Corrupt file; avoid oob read
+ break;
+ const KTXMipmapLevel *level = reinterpret_cast<const KTXMipmapLevel *>(buf.constData() + offset);
+ quint32 levelLen = decode(level->imageSize);
+ texData.setDataOffset(offset + sizeof(KTXMipmapLevel::imageSize), i);
+ texData.setDataLength(levelLen, i);
+ offset += sizeof(KTXMipmapLevel::imageSize) + levelLen + (3 - ((levelLen + 3) % 4));
+ }
+
+ if (!texData.isValid()) {
+ qCDebug(lcQtGuiTextureIO, "Invalid values in header of KTX file %s", logName().constData());
+ return QTextureFileData();
+ }
+
+ texData.setLogName(logName());
+
+#ifdef KTX_DEBUG
+ qDebug() << "KTX file handler read" << texData;
+#endif
+
+ return texData;
+}
+
+bool QKtxHandler::checkHeader(const KTXHeader &header)
+{
+ if (header.endianness != platformEndianIdentifier && header.endianness != inversePlatformEndianIdentifier)
+ return false;
+ inverseEndian = (header.endianness == inversePlatformEndianIdentifier);
+#ifdef KTX_DEBUG
+ QMetaEnum tfme = QMetaEnum::fromType<QOpenGLTexture::TextureFormat>();
+ QMetaEnum ptme = QMetaEnum::fromType<QOpenGLTexture::PixelType>();
+ qDebug("Header of %s:", logName().constData());
+ qDebug(" glType: 0x%x (%s)", decode(header.glType), ptme.valueToKey(decode(header.glType)));
+ qDebug(" glTypeSize: %u", decode(header.glTypeSize));
+ qDebug(" glFormat: 0x%x (%s)", decode(header.glFormat), tfme.valueToKey(decode(header.glFormat)));
+ qDebug(" glInternalFormat: 0x%x (%s)", decode(header.glInternalFormat), tfme.valueToKey(decode(header.glInternalFormat)));
+ qDebug(" glBaseInternalFormat: 0x%x (%s)", decode(header.glBaseInternalFormat), tfme.valueToKey(decode(header.glBaseInternalFormat)));
+ qDebug(" pixelWidth: %u", decode(header.pixelWidth));
+ qDebug(" pixelHeight: %u", decode(header.pixelHeight));
+ qDebug(" pixelDepth: %u", decode(header.pixelDepth));
+ qDebug(" numberOfArrayElements: %u", decode(header.numberOfArrayElements));
+ qDebug(" numberOfFaces: %u", decode(header.numberOfFaces));
+ qDebug(" numberOfMipmapLevels: %u", decode(header.numberOfMipmapLevels));
+ qDebug(" bytesOfKeyValueData: %u", decode(header.bytesOfKeyValueData));
+#endif
+ return ((decode(header.glType) == 0) &&
+ (decode(header.glFormat) == 0) &&
+ (decode(header.pixelDepth) == 0) &&
+ (decode(header.numberOfFaces) == 1));
+}
+
+quint32 QKtxHandler::decode(quint32 val)
+{
+ return inverseEndian ? qbswap<quint32>(val) : val;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qktxhandler_p.h b/src/gui/util/qktxhandler_p.h
new file mode 100644
index 0000000000..19f7b0e79a
--- /dev/null
+++ b/src/gui/util/qktxhandler_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QKTXHANDLER_H
+#define QKTXHANDLER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qtexturefilehandler_p.h"
+
+QT_BEGIN_NAMESPACE
+
+struct KTXHeader;
+
+class QKtxHandler : public QTextureFileHandler
+{
+public:
+ using QTextureFileHandler::QTextureFileHandler;
+
+ static bool canRead(const QByteArray &suffix, const QByteArray &block);
+
+ QTextureFileData read() override;
+
+private:
+ bool checkHeader(const KTXHeader &header);
+ quint32 decode(quint32 val);
+
+ bool inverseEndian = false;
+};
+
+QT_END_NAMESPACE
+
+#endif // QKTXHANDLER_H
diff --git a/src/gui/util/qpkmhandler.cpp b/src/gui/util/qpkmhandler.cpp
new file mode 100644
index 0000000000..e0c3b75efe
--- /dev/null
+++ b/src/gui/util/qpkmhandler.cpp
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** 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 "qpkmhandler_p.h"
+#include "qtexturefiledata_p.h"
+
+#include <QFile>
+#include <QDebug>
+#include <QSize>
+#include <qendian.h>
+
+//#define ETC_DEBUG
+
+QT_BEGIN_NAMESPACE
+
+static const int headerSize = 16;
+
+struct PkmType
+{
+ quint32 glFormat;
+ quint32 bytesPerBlock;
+};
+
+static PkmType typeMap[5] = {
+ { 0x8D64, 8 }, // GL_ETC1_RGB8_OES
+ { 0x9274, 8 }, // GL_COMPRESSED_RGB8_ETC2
+ { 0, 0 }, // unused (obsolete)
+ { 0x9278, 16}, // GL_COMPRESSED_RGBA8_ETC2_EAC
+ { 0x9276, 8 } // GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
+};
+
+bool QPkmHandler::canRead(const QByteArray &suffix, const QByteArray &block)
+{
+ Q_UNUSED(suffix)
+
+ return block.startsWith("PKM ");
+}
+
+QTextureFileData QPkmHandler::read()
+{
+ QTextureFileData texData;
+
+ if (!device())
+ return texData;
+
+ QByteArray fileData = device()->readAll();
+ if (fileData.size() < headerSize || !canRead(QByteArray(), fileData)) {
+ qCDebug(lcQtGuiTextureIO, "Invalid PKM file %s", logName().constData());
+ return QTextureFileData();
+ }
+ texData.setData(fileData);
+
+ const char *rawData = fileData.constData();
+
+ // ignore version (rawData + 4 & 5)
+
+ // texture type
+ quint16 type = qFromBigEndian<quint16>(rawData + 6);
+ if (type >= sizeof(typeMap)/sizeof(typeMap[0])) {
+ qCDebug(lcQtGuiTextureIO, "Unknown compression format in PKM file %s", logName().constData());
+ return QTextureFileData();
+ }
+ texData.setGLFormat(0); // 0 for compressed textures
+ texData.setGLInternalFormat(typeMap[type].glFormat);
+ //### setBaseInternalFormat
+
+ // texture size
+ texData.setNumLevels(1);
+ const int bpb = typeMap[type].bytesPerBlock;
+ QSize paddedSize(qFromBigEndian<quint16>(rawData + 8), qFromBigEndian<quint16>(rawData + 10));
+ texData.setDataLength((paddedSize.width() / 4) * (paddedSize.height() / 4) * bpb);
+ QSize texSize(qFromBigEndian<quint16>(rawData + 12), qFromBigEndian<quint16>(rawData + 14));
+ texData.setSize(texSize);
+
+ texData.setDataOffset(headerSize);
+
+ if (!texData.isValid()) {
+ qCDebug(lcQtGuiTextureIO, "Invalid values in header of PKM file %s", logName().constData());
+ return QTextureFileData();
+ }
+
+ texData.setLogName(logName());
+
+#ifdef ETC_DEBUG
+ qDebug() << "PKM file handler read" << texData;
+#endif
+ return texData;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qpkmhandler_p.h b/src/gui/util/qpkmhandler_p.h
new file mode 100644
index 0000000000..2f7618bc53
--- /dev/null
+++ b/src/gui/util/qpkmhandler_p.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPKMHANDLER_H
+#define QPKMHANDLER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qtexturefilehandler_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QPkmHandler : public QTextureFileHandler
+{
+public:
+ using QTextureFileHandler::QTextureFileHandler;
+
+ static bool canRead(const QByteArray &suffix, const QByteArray &block);
+
+ QTextureFileData read() override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QPKMHANDLER_H
diff --git a/src/gui/util/qshadergraphloader.cpp b/src/gui/util/qshadergraphloader.cpp
index 8d92c73a5a..99a9f7869e 100644
--- a/src/gui/util/qshadergraphloader.cpp
+++ b/src/gui/util/qshadergraphloader.cpp
@@ -39,6 +39,8 @@
#include "qshadergraphloader_p.h"
+#include "qshadernodesloader_p.h"
+
#include <QtCore/qdebug.h>
#include <QtCore/qiodevice.h>
#include <QtCore/qjsonarray.h>
@@ -129,6 +131,19 @@ void QShaderGraphLoader::load()
bool hasError = false;
+ const auto prototypesValue = root.value(QStringLiteral("prototypes"));
+ if (!prototypesValue.isUndefined()) {
+ if (prototypesValue.isObject()) {
+ QShaderNodesLoader loader;
+ loader.load(prototypesValue.toObject());
+ m_prototypes.unite(loader.nodes());
+ } else {
+ qWarning() << "Invalid prototypes property, should be an object";
+ m_status = Error;
+ return;
+ }
+ }
+
const auto nodes = nodesValue.toArray();
for (const auto &nodeValue : nodes) {
if (!nodeValue.isObject()) {
diff --git a/src/gui/util/qshadernodesloader.cpp b/src/gui/util/qshadernodesloader.cpp
index db34b6d44d..692653ee44 100644
--- a/src/gui/util/qshadernodesloader.cpp
+++ b/src/gui/util/qshadernodesloader.cpp
@@ -99,11 +99,15 @@ void QShaderNodesLoader::load()
}
const auto root = document.object();
+ load(root);
+}
+void QShaderNodesLoader::load(const QJsonObject &prototypesObject)
+{
bool hasError = false;
- for (const auto &property : root.keys()) {
- const auto nodeValue = root.value(property);
+ for (const auto &property : prototypesObject.keys()) {
+ const auto nodeValue = prototypesObject.value(property);
if (!nodeValue.isObject()) {
qWarning() << "Invalid node found";
hasError = true;
diff --git a/src/gui/util/qshadernodesloader_p.h b/src/gui/util/qshadernodesloader_p.h
index 2696e958b6..0bec871857 100644
--- a/src/gui/util/qshadernodesloader_p.h
+++ b/src/gui/util/qshadernodesloader_p.h
@@ -78,6 +78,7 @@ public:
Q_GUI_EXPORT void setDevice(QIODevice *device) Q_DECL_NOTHROW;
Q_GUI_EXPORT void load();
+ Q_GUI_EXPORT void load(const QJsonObject &prototypesObject);
private:
Status m_status;
diff --git a/src/gui/util/qtexturefiledata.cpp b/src/gui/util/qtexturefiledata.cpp
new file mode 100644
index 0000000000..ebf46f8e4e
--- /dev/null
+++ b/src/gui/util/qtexturefiledata.cpp
@@ -0,0 +1,280 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtexturefiledata_p.h"
+#include <QMetaEnum>
+#include <QSize>
+#if QT_CONFIG(opengl)
+#include <QOpenGLTexture>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcQtGuiTextureIO, "qt.gui.textureio");
+
+class QTextureFileDataPrivate : public QSharedData
+{
+public:
+ QTextureFileDataPrivate()
+ {
+ }
+
+ QTextureFileDataPrivate(const QTextureFileDataPrivate &other)
+ : QSharedData(other),
+ logName(other.logName),
+ data(other.data),
+ offsets(other.offsets),
+ lengths(other.lengths),
+ size(other.size),
+ format(other.format)
+ {
+ }
+
+ ~QTextureFileDataPrivate()
+ {
+ }
+
+ void ensureLevels(int num, bool force = false)
+ {
+ const int newSize = force ? num : qMax(offsets.size(), num);
+ offsets.resize(newSize);
+ lengths.resize(newSize);
+ }
+
+ QByteArray logName;
+ QByteArray data;
+ QVector<int> offsets;
+ QVector<int> lengths;
+ QSize size;
+ quint32 format = 0;
+ quint32 internalFormat = 0;
+ quint32 baseInternalFormat = 0;
+};
+
+
+
+QTextureFileData::QTextureFileData()
+{
+}
+
+QTextureFileData::QTextureFileData(const QTextureFileData &other)
+ : d(other.d)
+{
+}
+
+QTextureFileData &QTextureFileData::operator=(const QTextureFileData &other)
+{
+ d = other.d;
+ return *this;
+}
+
+QTextureFileData::~QTextureFileData()
+{
+}
+
+bool QTextureFileData::isNull() const
+{
+ return !d;
+}
+
+bool QTextureFileData::isValid() const
+{
+ if (!d)
+ return false;
+
+ if (d->data.isEmpty() || d->size.isEmpty() || (!d->format && !d->internalFormat))
+ return false;
+
+ const int numChunks = d->offsets.size();
+ if (numChunks == 0 || (d->lengths.size() != numChunks))
+ return false;
+
+ const qint64 sz = d->data.size();
+ for (int i = 0; i < numChunks; i++) {
+ qint64 offi = d->offsets.at(i);
+ qint64 leni = d->lengths.at(i);
+ if (offi < 0 || offi >= sz || leni <= 0 || (offi + leni > sz))
+ return false;
+ }
+ return true;
+}
+
+void QTextureFileData::clear()
+{
+ d = nullptr;
+}
+
+QByteArray QTextureFileData::data() const
+{
+ return d ? d->data : QByteArray();
+}
+
+void QTextureFileData::setData(const QByteArray &data)
+{
+ if (!d.constData()) //### uh think about this design, this is the only way to create; should be constructor instead at least
+ d = new QTextureFileDataPrivate;
+
+ d->data = data;
+}
+
+int QTextureFileData::dataOffset(int level) const
+{
+ return (d && d->offsets.size() > level) ? d->offsets.at(level) : 0;
+}
+
+void QTextureFileData::setDataOffset(int offset, int level)
+{
+ if (d.constData() && level >= 0) {
+ d->ensureLevels(level + 1);
+ d->offsets[level] = offset;
+ }
+}
+
+int QTextureFileData::dataLength(int level) const
+{
+ return (d && d->lengths.size() > level) ? d->lengths.at(level) : 0;
+}
+
+void QTextureFileData::setDataLength(int length, int level)
+{
+ if (d.constData() && level >= 0) {
+ d->ensureLevels(level + 1);
+ d->lengths[level] = length;
+ }
+}
+
+int QTextureFileData::numLevels() const
+{
+ return d ? d->offsets.size() : 0;
+}
+
+void QTextureFileData::setNumLevels(int num)
+{
+ if (d && num >= 0)
+ d->ensureLevels(num, true);
+}
+
+QSize QTextureFileData::size() const
+{
+ return d ? d->size : QSize();
+}
+
+void QTextureFileData::setSize(const QSize &size)
+{
+ if (d.constData())
+ d->size = size;
+}
+
+quint32 QTextureFileData::glFormat() const
+{
+ return d ? d->format : 0;
+}
+
+void QTextureFileData::setGLFormat(quint32 format)
+{
+ if (d.constData())
+ d->format = format;
+}
+
+quint32 QTextureFileData::glInternalFormat() const
+{
+ return d ? d->internalFormat : 0;
+}
+
+void QTextureFileData::setGLInternalFormat(quint32 format)
+{
+ if (d.constData())
+ d->internalFormat = format;
+}
+
+quint32 QTextureFileData::glBaseInternalFormat() const
+{
+ return d ? d->baseInternalFormat : 0;
+}
+
+void QTextureFileData::setGLBaseInternalFormat(quint32 format)
+{
+ if (d.constData())
+ d->baseInternalFormat = format;
+}
+
+QByteArray QTextureFileData::logName() const
+{
+ return d ? d->logName : QByteArray();
+}
+
+void QTextureFileData::setLogName(const QByteArray &name)
+{
+ if (d.constData())
+ d->logName = name;
+}
+
+static QByteArray glFormatName(quint32 fmt)
+{
+ const char *id = 0;
+#if QT_CONFIG(opengl)
+ id = QMetaEnum::fromType<QOpenGLTexture::TextureFormat>().valueToKey(fmt);
+#endif
+ QByteArray res(id ? id : "(?)");
+ res += " [0x" + QByteArray::number(fmt, 16).rightJustified(4, '0') + ']';
+ return res;
+}
+
+QDebug operator<<(QDebug dbg, const QTextureFileData &d)
+{
+ QDebugStateSaver saver(dbg);
+
+ dbg.nospace() << "QTextureFileData(";
+ if (!d.isNull()) {
+ dbg.space() << d.logName() << d.size();
+ dbg << "glFormat:" << glFormatName(d.glFormat());
+ dbg << "glInternalFormat:" << glFormatName(d.glInternalFormat());
+ dbg << "glBaseInternalFormat:" << glFormatName(d.glBaseInternalFormat());
+ dbg.nospace() << "Levels: " << d.numLevels();
+ if (!d.isValid())
+ dbg << " {Invalid}";
+ dbg << ")";
+ } else {
+ dbg << "null)";
+ }
+
+ return dbg;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qtexturefiledata_p.h b/src/gui/util/qtexturefiledata_p.h
new file mode 100644
index 0000000000..2df23de33c
--- /dev/null
+++ b/src/gui/util/qtexturefiledata_p.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTEXTUREFILEDATA_P_H
+#define QTEXTUREFILEDATA_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/qtguiglobal.h>
+#include <QSharedDataPointer>
+#include <QLoggingCategory>
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(lcQtGuiTextureIO)
+
+class QTextureFileDataPrivate;
+
+class Q_GUI_EXPORT QTextureFileData
+{
+public:
+ QTextureFileData();
+ QTextureFileData(const QTextureFileData &other);
+ QTextureFileData &operator=(const QTextureFileData &other);
+ ~QTextureFileData();
+
+ bool isNull() const;
+ bool isValid() const;
+
+ void clear();
+
+ QByteArray data() const;
+ void setData(const QByteArray &data);
+
+ int dataOffset(int level = 0) const;
+ void setDataOffset(int offset, int level = 0);
+
+ int dataLength(int level = 0) const;
+ void setDataLength(int length, int level = 0);
+
+ int numLevels() const;
+ void setNumLevels(int num);
+
+ QSize size() const;
+ void setSize(const QSize &size);
+
+ quint32 glFormat() const;
+ void setGLFormat(quint32 format);
+
+ quint32 glInternalFormat() const;
+ void setGLInternalFormat(quint32 format);
+
+ quint32 glBaseInternalFormat() const;
+ void setGLBaseInternalFormat(quint32 format);
+
+ QByteArray logName() const;
+ void setLogName(const QByteArray &name);
+
+private:
+ QSharedDataPointer<QTextureFileDataPrivate> d;
+};
+
+Q_DECLARE_TYPEINFO(QTextureFileData, Q_MOVABLE_TYPE);
+
+Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QTextureFileData &d);
+
+QT_END_NAMESPACE
+
+#endif // QABSTRACTLAYOUTSTYLEINFO_P_H
diff --git a/src/gui/util/qtexturefilehandler_p.h b/src/gui/util/qtexturefilehandler_p.h
new file mode 100644
index 0000000000..b808d3e7db
--- /dev/null
+++ b/src/gui/util/qtexturefilehandler_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 QTEXTUREFILEHANDLER_P_H
+#define QTEXTUREFILEHANDLER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qtexturefiledata_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QTextureFileHandler
+{
+public:
+ QTextureFileHandler(QIODevice *device, const QByteArray &logName = QByteArray())
+ : m_device(device)
+ {
+ m_logName = !logName.isEmpty() ? logName : QByteArrayLiteral("(unknown)");
+ }
+ virtual ~QTextureFileHandler() {}
+
+ virtual QTextureFileData read() = 0;
+ QIODevice *device() const { return m_device; }
+ QByteArray logName() const { return m_logName; }
+
+private:
+ QIODevice *m_device = nullptr;
+ QByteArray m_logName;
+};
+
+QT_END_NAMESPACE
+
+#endif // QTEXTUREFILEHANDLER_P_H
diff --git a/src/gui/util/qtexturefilereader.cpp b/src/gui/util/qtexturefilereader.cpp
new file mode 100644
index 0000000000..5d4bd600e0
--- /dev/null
+++ b/src/gui/util/qtexturefilereader.cpp
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtexturefilereader_p.h"
+
+#include "qpkmhandler_p.h"
+#include "qktxhandler_p.h"
+
+#include <QFileInfo>
+
+QT_BEGIN_NAMESPACE
+
+QTextureFileReader::QTextureFileReader(QIODevice *device, const QString &fileName)
+ : m_device(device), m_fileName(fileName)
+{
+}
+
+QTextureFileReader::~QTextureFileReader()
+{
+ delete m_handler;
+}
+
+QTextureFileData QTextureFileReader::read()
+{
+ if (!canRead())
+ return QTextureFileData();
+ return m_handler->read();
+}
+
+bool QTextureFileReader::canRead()
+{
+ if (!checked) {
+ checked = true;
+ if (!init())
+ return false;
+
+ QByteArray headerBlock = m_device->peek(64);
+ QFileInfo fi(m_fileName);
+ QByteArray suffix = fi.suffix().toLower().toLatin1();
+ QByteArray logName = fi.fileName().toUtf8();
+
+ // Currently the handlers are hardcoded; later maybe a list of plugins
+ if (QPkmHandler::canRead(suffix, headerBlock)) {
+ m_handler = new QPkmHandler(m_device, logName);
+ } else if (QKtxHandler::canRead(suffix, headerBlock)) {
+ m_handler = new QKtxHandler(m_device, logName);
+ }
+ // else if OtherHandler::canRead() ...etc.
+ }
+ return (m_handler != nullptr);
+}
+
+QList<QByteArray> QTextureFileReader::supportedFileFormats()
+{
+ // Hardcoded for now
+ return {QByteArrayLiteral("pkm"), QByteArrayLiteral("ktx")};
+}
+
+bool QTextureFileReader::init()
+{
+ if (!m_device)
+ return false;
+ return m_device->isReadable();
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qtexturefilereader_p.h b/src/gui/util/qtexturefilereader_p.h
new file mode 100644
index 0000000000..2ec0b0cc49
--- /dev/null
+++ b/src/gui/util/qtexturefilereader_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTEXTUREFILEREADER_H
+#define QTEXTUREFILEREADER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qtexturefiledata_p.h"
+#include <QString>
+#include <QFileInfo>
+
+QT_BEGIN_NAMESPACE
+
+class QIODevice;
+class QTextureFileHandler;
+
+class Q_GUI_EXPORT QTextureFileReader
+{
+public:
+ QTextureFileReader(QIODevice *device, const QString &fileName = QString()); //### drop this logname thing?
+ ~QTextureFileReader();
+
+ bool canRead();
+ QTextureFileData read();
+
+ // TBD access function to params
+ // TBD ask for identified fmt
+
+ static QList<QByteArray> supportedFileFormats();
+
+private:
+ bool init();
+ QIODevice *m_device = nullptr;
+ QString m_fileName;
+ QTextureFileHandler *m_handler = nullptr;
+ bool checked = false;
+};
+
+QT_END_NAMESPACE
+
+
+#endif // QTEXTUREFILEREADER_H
diff --git a/src/gui/util/qvalidator.cpp b/src/gui/util/qvalidator.cpp
index 7982ad967e..2237b016e9 100644
--- a/src/gui/util/qvalidator.cpp
+++ b/src/gui/util/qvalidator.cpp
@@ -411,13 +411,15 @@ QValidator::State QIntValidator::validate(QString & input, int&) const
if (buff.isEmpty())
return Intermediate;
- if (b >= 0 && buff.startsWith('-'))
+ const bool startsWithMinus(buff[0] == '-');
+ if (b >= 0 && startsWithMinus)
return Invalid;
- if (t < 0 && buff.startsWith('+'))
+ const bool startsWithPlus(buff[0] == '+');
+ if (t < 0 && startsWithPlus)
return Invalid;
- if (buff.size() == 1 && (buff.at(0) == '+' || buff.at(0) == '-'))
+ if (buff.size() == 1 && (startsWithPlus || startsWithMinus))
return Intermediate;
bool ok;
@@ -433,7 +435,15 @@ QValidator::State QIntValidator::validate(QString & input, int&) const
if (entered >= 0) {
// the -entered < b condition is necessary to allow people to type
// the minus last (e.g. for right-to-left languages)
- return (entered > t && -entered < b) ? Invalid : Intermediate;
+ // The buffLength > tLength condition validates values consisting
+ // of a number of digits equal to or less than the max value as intermediate.
+
+ int buffLength = buff.size();
+ if (startsWithPlus)
+ buffLength--;
+ const int tLength = t != 0 ? static_cast<int>(std::log10(qAbs(t))) + 1 : 1;
+
+ return (entered > t && -entered < b && buffLength > tLength) ? Invalid : Intermediate;
} else {
return (entered < b) ? Invalid : Intermediate;
}
@@ -624,10 +634,10 @@ QDoubleValidator::~QDoubleValidator()
that is within the valid range and is in the correct format.
Returns \l Intermediate if \a input contains a double that is
- outside the range or is in the wrong format; e.g. with too many
- digits after the decimal point or is empty.
+ outside the range or is in the wrong format; e.g. is empty.
- Returns \l Invalid if the \a input is not a double.
+ Returns \l Invalid if the \a input is not a double or with too many
+ digits after the decimal point.
Note: If the valid range consists of just positive doubles (e.g. 0.0 to 100.0)
and \a input is a negative double then \l Invalid is returned. If notation()
@@ -690,8 +700,16 @@ QValidator::State QDoubleValidatorPrivate::validateWithLocale(QString &input, QL
if (notation == QDoubleValidator::StandardNotation) {
double max = qMax(qAbs(q->b), qAbs(q->t));
if (max < LLONG_MAX) {
- qlonglong n = pow10(numDigits(qlonglong(max))) - 1;
- if (qAbs(i) > n)
+ qlonglong n = pow10(numDigits(qlonglong(max)));
+ // In order to get the highest possible number in the intermediate
+ // range we need to get 10 to the power of the number of digits
+ // after the decimal's and subtract that from the top number.
+ //
+ // For example, where q->dec == 2 and with a range of 0.0 - 9.0
+ // then the minimum possible number is 0.00 and the maximum
+ // possible is 9.99. Therefore 9.999 and 10.0 should be seen as
+ // invalid.
+ if (qAbs(i) > (n - std::pow(10, -q->dec)))
return QValidator::Invalid;
}
}
@@ -1061,7 +1079,7 @@ void QRegularExpressionValidatorPrivate::setRegularExpression(const QRegularExpr
if (origRe != re) {
usedRe = origRe = re; // copies also the pattern options
- usedRe.setPattern(QLatin1String("\\A(?:") + re.pattern() + QLatin1String(")\\z"));
+ usedRe.setPattern(QRegularExpression::anchoredPattern(re.pattern()));
emit q->regularExpressionChanged(re);
emit q->changed();
}
diff --git a/src/gui/util/util.pri b/src/gui/util/util.pri
index cf3cbee48e..6324642505 100644
--- a/src/gui/util/util.pri
+++ b/src/gui/util/util.pri
@@ -14,7 +14,12 @@ HEADERS += \
util/qshaderlanguage_p.h \
util/qshadernode_p.h \
util/qshadernodeport_p.h \
- util/qshadernodesloader_p.h
+ util/qshadernodesloader_p.h \
+ util/qtexturefiledata_p.h \
+ util/qtexturefilereader_p.h \
+ util/qtexturefilehandler_p.h \
+ util/qpkmhandler_p.h \
+ util/qktxhandler_p.h
SOURCES += \
util/qdesktopservices.cpp \
@@ -29,4 +34,8 @@ SOURCES += \
util/qshaderlanguage.cpp \
util/qshadernode.cpp \
util/qshadernodeport.cpp \
- util/qshadernodesloader.cpp
+ util/qshadernodesloader.cpp \
+ util/qtexturefiledata.cpp \
+ util/qtexturefilereader.cpp \
+ util/qpkmhandler.cpp \
+ util/qktxhandler.cpp
diff --git a/src/gui/vulkan/qvulkanfunctions.cpp b/src/gui/vulkan/qvulkanfunctions.cpp
index c5f9616d20..73dbeb9ab6 100644
--- a/src/gui/vulkan/qvulkanfunctions.cpp
+++ b/src/gui/vulkan/qvulkanfunctions.cpp
@@ -66,16 +66,7 @@ QT_BEGIN_NAMESPACE
The typical usage is the following:
- \code
- void Window::render()
- {
- QVulkanInstance *inst = vulkanInstance();
- QVulkanFunctions *f = inst->functions();
- ...
- VkResult err = f->vkAllocateCommandBuffers(device, &cmdBufInfo, &cmdBuf);
- ...
- }
- \endcode
+ \snippet code/src_gui_vulkan_qvulkanfunctions.cpp 0
\note Windowing system interface (WSI) specifics and extensions are
excluded. This class only covers core Vulkan commands, with the exception
@@ -118,15 +109,7 @@ QT_BEGIN_NAMESPACE
The typical usage is the following:
- \code
- void Window::render()
- {
- QVulkanInstance *inst = vulkanInstance();
- QVulkanDeviceFunctions *df = inst->deviceFunctions(device);
- VkResult err = df->vkAllocateCommandBuffers(device, &cmdBufInfo, &cmdBuf);
- ...
- }
- \endcode
+ \snippet code/src_gui_vulkan_qvulkanfunctions.cpp 1
The QVulkanDeviceFunctions object specific to the provided VkDevice is
created when QVulkanInstance::deviceFunctions() is first called with the
diff --git a/src/gui/vulkan/qvulkaninstance.cpp b/src/gui/vulkan/qvulkaninstance.cpp
index 8236d9625a..000c2b8caa 100644
--- a/src/gui/vulkan/qvulkaninstance.cpp
+++ b/src/gui/vulkan/qvulkaninstance.cpp
@@ -97,22 +97,7 @@ QT_BEGIN_NAMESPACE
calling QWindow::setVulkanInstance(). Thus a typical application pattern is
the following:
- \code
- int main(int argc, char **argv)
- {
- QGuiApplication app(argc, argv);
-
- QVulkanInstance inst;
- if (!inst.create())
- return 1;
-
- ...
- window->setVulkanInstance(&inst);
- window->show();
-
- return app.exec();
- }
- \endcode
+ \snippet code/src_gui_vulkan_qvulkaninstance.cpp 0
\section1 Configuration
@@ -138,31 +123,12 @@ QT_BEGIN_NAMESPACE
For example, to enable the standard validation layers, one could do the
following:
- \code
- QVulkanInstance inst;
-
- // Enable validation layer, if supported. Messages go to qDebug by default.
- inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
-
- bool ok = inst.create();
- if (!ok)
- ... // Vulkan not available
- if (!inst.layers().contains("VK_LAYER_LUNARG_standard_validation"))
- ... // validation layer not available
- \endcode
+ \snippet code/src_gui_vulkan_qvulkaninstance.cpp 1
Or, alternatively, to make decisions before attempting to create a Vulkan
instance:
- \code
- QVulkanInstance inst;
-
- if (inst.supportedLayers().contains("VK_LAYER_LUNARG_standard_validation"))
- ...
-
- bool ok = inst.create();
- ...
- \endcode
+ \snippet code/src_gui_vulkan_qvulkaninstance.cpp 2
\section1 Adopting an Existing Instance
@@ -229,62 +195,7 @@ QT_BEGIN_NAMESPACE
The following is the basic outline of creating a Vulkan-capable QWindow:
- \code
- class VulkanWindow : public QWindow
- {
- public:
- VulkanWindow() {
- setSurfaceType(VulkanSurface);
- }
-
- void exposeEvent(QExposeEvent *) {
- if (isExposed()) {
- if (!m_initialized) {
- m_initialized = true;
- // initialize device, swapchain, etc.
- QVulkanInstance *inst = vulkanInstance();
- QVulkanFunctions *f = inst->functions();
- uint32_t devCount = 0;
- f->vkEnumeratePhysicalDevices(inst->vkInstance(), &devCount, nullptr);
- ...
- // build the first frame
- render();
- }
- }
- }
-
- bool event(QEvent *e) {
- if (e->type == QEvent::UpdateRequest)
- render();
- return QWindow::event(e);
- }
-
- void render() {
- ...
- requestUpdate(); // render continuously
- }
-
- private:
- bool m_initialized = false;
- };
-
- int main(int argc, char **argv)
- {
- QGuiApplication app(argc, argv);
-
- QVulkanInstance inst;
- if (!inst.create()) {
- qWarning("Vulkan not available");
- return 1;
- }
-
- VulkanWindow window;
- window.showMaximized();
-
- return app.exec();
-
- }
- \endcode
+ \snippet code/src_gui_vulkan_qvulkaninstance.cpp 3
\note In addition to expose, a well-behaving window implementation will
also have to take care of additional events like resize and
diff --git a/src/gui/vulkan/qvulkanwindow.cpp b/src/gui/vulkan/qvulkanwindow.cpp
index e45a16170e..6d12377a60 100644
--- a/src/gui/vulkan/qvulkanwindow.cpp
+++ b/src/gui/vulkan/qvulkanwindow.cpp
@@ -74,60 +74,7 @@ Q_LOGGING_CATEGORY(lcGuiVk, "qt.vulkan")
A typical application using QVulkanWindow may look like the following:
- \code
- class VulkanRenderer : public QVulkanWindowRenderer
- {
- public:
- VulkanRenderer(QVulkanWindow *w) : m_window(w) { }
-
- void initResources() override
- {
- m_devFuncs = m_window->vulkanInstance()->deviceFunctions(m_window->device());
- ...
- }
- void initSwapChainResources() override { ... }
- void releaseSwapChainResources() override { ... }
- void releaseResources() override { ... }
-
- void startNextFrame() override
- {
- VkCommandBuffer cmdBuf = m_window->currentCommandBuffer();
- ...
- m_devFuncs->vkCmdBeginRenderPass(...);
- ...
- m_window->frameReady();
- }
-
- private:
- QVulkanWindow *m_window;
- QVulkanDeviceFunctions *m_devFuncs;
- };
-
- class VulkanWindow : public QVulkanWindow
- {
- public:
- QVulkanWindowRenderer *createRenderer() override {
- return new VulkanRenderer(this);
- }
- };
-
- int main(int argc, char *argv[])
- {
- QGuiApplication app(argc, argv);
-
- QVulkanInstance inst;
- // enable the standard validation layers, when available
- inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
- if (!inst.create())
- qFatal("Failed to create Vulkan instance: %d", inst.errorCode());
-
- VulkanWindow w;
- w.setVulkanInstance(&inst);
- w.showMaximized();
-
- return app.exec();
- }
- \endcode
+ \snippet code/src_gui_vulkan_qvulkanwindow.cpp 0
As it can be seen in the example, the main patterns in QVulkanWindow usage are:
@@ -989,7 +936,7 @@ bool QVulkanWindowPrivate::createDefaultRenderPass()
attDesc[1].samples = sampleCount;
attDesc[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attDesc[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- attDesc[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attDesc[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attDesc[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attDesc[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attDesc[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
@@ -999,7 +946,7 @@ bool QVulkanWindowPrivate::createDefaultRenderPass()
attDesc[2].format = colorFormat;
attDesc[2].samples = sampleCount;
attDesc[2].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
- attDesc[2].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ attDesc[2].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attDesc[2].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attDesc[2].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attDesc[2].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
@@ -2164,8 +2111,8 @@ void QVulkanWindowPrivate::addReadback()
barrier.image = frameGrabImage;
devFuncs->vkCmdPipelineBarrier(image.cmdBuf,
- VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_HOST_BIT,
0, 0, nullptr, 0, nullptr,
1, &barrier);
}
@@ -2298,6 +2245,11 @@ uint32_t QVulkanWindow::hostVisibleMemoryIndex() const
\note Calling this function is only valid from the invocation of
QVulkanWindowRenderer::initResources() up until
QVulkanWindowRenderer::releaseResources().
+
+ \note It is not guaranteed that this memory type is always suitable. The
+ correct, cross-implementation solution - especially for device local images
+ - is to manually pick a memory type after checking the mask returned from
+ \c{vkGetImageMemoryRequirements}.
*/
uint32_t QVulkanWindow::deviceLocalMemoryIndex() const
{
@@ -2434,18 +2386,7 @@ VkFramebuffer QVulkanWindow::currentFramebuffer() const
concurrentFrameCount(). Such arrays can then be indexed by the value
returned from this function.
- \code
- class Renderer {
- ...
- VkDescriptorBufferInfo m_uniformBufInfo[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT];
- };
-
- void Renderer::startNextFrame()
- {
- VkDescriptorBufferInfo &uniformBufInfo(m_uniformBufInfo[m_window->currentFrame()]);
- ...
- }
- \endcode
+ \snippet code/src_gui_vulkan_qvulkanwindow.cpp 1
\note This function must only be called from within startNextFrame() and, in
case of asynchronous command generation, up until the call to frameReady().
@@ -2472,20 +2413,7 @@ int QVulkanWindow::currentFrame() const
\note The value is constant for the entire lifetime of the QVulkanWindow.
- \code
- class Renderer {
- ...
- VkDescriptorBufferInfo m_uniformBufInfo[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT];
- };
-
- void Renderer::startNextFrame()
- {
- const int count = m_window->concurrentFrameCount();
- for (int i = 0; i < count; ++i)
- m_uniformBufInfo[i] = ...
- ...
- }
- \endcode
+ \snippet code/src_gui_vulkan_qvulkanwindow.cpp 2
\sa currentFrame()
*/
diff --git a/src/network/access/access.pri b/src/network/access/access.pri
index ec0273377f..8a92308f12 100644
--- a/src/network/access/access.pri
+++ b/src/network/access/access.pri
@@ -74,6 +74,13 @@ qtConfig(settings) {
mac: LIBS_PRIVATE += -framework Security
+wasm {
+ SOURCES += \
+ access/qnetworkreplywasmimpl.cpp
+ HEADERS += \
+ access/qnetworkreplywasmimpl_p.h
+}
+
include($$PWD/../../3rdparty/zlib_dependency.pri)
qtConfig(http) {
diff --git a/src/network/access/http2/http2protocol.cpp b/src/network/access/http2/http2protocol.cpp
index f51af4be5c..0be72042c6 100644
--- a/src/network/access/http2/http2protocol.cpp
+++ b/src/network/access/http2/http2protocol.cpp
@@ -287,7 +287,8 @@ bool is_protocol_upgraded(const QHttpNetworkReply &reply)
// Do some minimal checks here - we expect 'Upgrade: h2c' to be found.
const auto &header = reply.header();
for (const QPair<QByteArray, QByteArray> &field : header) {
- if (field.first.toLower() == "upgrade" && field.second.toLower() == "h2c")
+ if (field.first.compare("upgrade", Qt::CaseInsensitive) == 0 &&
+ field.second.compare("h2c", Qt::CaseInsensitive) == 0)
return true;
}
}
diff --git a/src/network/access/qhsts.cpp b/src/network/access/qhsts.cpp
index af913ca015..ce70b6af90 100644
--- a/src/network/access/qhsts.cpp
+++ b/src/network/access/qhsts.cpp
@@ -470,8 +470,7 @@ bool QHstsHeaderParser::processDirective(const QByteArray &name, const QByteArra
{
Q_ASSERT(name.size());
// RFC6797 6.1/3 Directive names are case-insensitive
- const auto lcName = name.toLower();
- if (lcName == "max-age") {
+ if (name.compare("max-age", Qt::CaseInsensitive) == 0) {
// RFC 6797, 6.1.1
// The syntax of the max-age directive's REQUIRED value (after
// quoted-string unescaping, if necessary) is defined as:
@@ -494,7 +493,7 @@ bool QHstsHeaderParser::processDirective(const QByteArray &name, const QByteArra
maxAge = age;
maxAgeFound = true;
- } else if (lcName == "includesubdomains") {
+ } else if (name.compare("includesubdomains", Qt::CaseInsensitive) == 0) {
// RFC 6797, 6.1.2. The includeSubDomains Directive.
// The OPTIONAL "includeSubDomains" directive is a valueless directive.
diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp
index c207d6e240..df7f87efd4 100644
--- a/src/network/access/qhttp2protocolhandler.cpp
+++ b/src/network/access/qhttp2protocolhandler.cpp
@@ -97,16 +97,18 @@ HPack::HttpHeader build_headers(const QHttpNetworkRequest &request, quint32 maxH
if (size.second > maxHeaderListSize)
break;
- QByteArray key(field.first.toLower());
- if (key == "connection" || key == "host" || key == "keep-alive"
- || key == "proxy-connection" || key == "transfer-encoding")
+ if (field.first.compare("connection", Qt::CaseInsensitive) == 0 ||
+ field.first.compare("host", Qt::CaseInsensitive) == 0 ||
+ field.first.compare("keep-alive", Qt::CaseInsensitive) == 0 ||
+ field.first.compare("proxy-connection", Qt::CaseInsensitive) == 0 ||
+ field.first.compare("transfer-encoding", Qt::CaseInsensitive) == 0)
continue; // Those headers are not valid (section 3.2.1) - from QSpdyProtocolHandler
// TODO: verify with specs, which fields are valid to send ....
// toLower - 8.1.2 .... "header field names MUST be converted to lowercase prior
// to their encoding in HTTP/2.
// A request or response containing uppercase header field names
// MUST be treated as malformed (Section 8.1.2.6)".
- header.push_back(HeaderField(key, field.second));
+ header.push_back(HeaderField(field.first.toLower(), field.second));
}
return header;
@@ -1404,8 +1406,9 @@ bool QHttp2ProtocolHandler::tryReserveStream(const Http2::Frame &pushPromiseFram
return false;
}
- const auto method = pseudoHeaders[":method"].toLower();
- if (method != "get" && method != "head")
+ const QByteArray method = pseudoHeaders[":method"];
+ if (method.compare("get", Qt::CaseInsensitive) != 0 &&
+ method.compare("head", Qt::CaseInsensitive) != 0)
return false;
QUrl url;
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index 0e2c257952..c58fd24a44 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -528,7 +528,7 @@ QUrl QHttpNetworkConnectionPrivate::parseRedirectResponse(QAbstractSocket *socke
QUrl redirectUrl;
const QList<QPair<QByteArray, QByteArray> > fields = reply->header();
for (const QNetworkReply::RawHeaderPair &header : fields) {
- if (header.first.toLower() == "location") {
+ if (header.first.compare("location", Qt::CaseInsensitive) == 0) {
redirectUrl = QUrl::fromEncoded(header.second);
break;
}
diff --git a/src/network/access/qhttpnetworkheader.cpp b/src/network/access/qhttpnetworkheader.cpp
index 3326f89d2f..8ad01174b4 100644
--- a/src/network/access/qhttpnetworkheader.cpp
+++ b/src/network/access/qhttpnetworkheader.cpp
@@ -64,7 +64,7 @@ qint64 QHttpNetworkHeaderPrivate::contentLength() const
QList<QPair<QByteArray, QByteArray> >::ConstIterator it = fields.constBegin(),
end = fields.constEnd();
for ( ; it != end; ++it)
- if (qstricmp("content-length", it->first) == 0) {
+ if (it->first.compare("content-length", Qt::CaseInsensitive) == 0) {
value = it->second;
break;
}
@@ -95,7 +95,7 @@ QList<QByteArray> QHttpNetworkHeaderPrivate::headerFieldValues(const QByteArray
QList<QPair<QByteArray, QByteArray> >::ConstIterator it = fields.constBegin(),
end = fields.constEnd();
for ( ; it != end; ++it)
- if (qstricmp(name.constData(), it->first) == 0)
+ if (name.compare(it->first, Qt::CaseInsensitive) == 0)
result += it->second;
return result;
@@ -104,7 +104,7 @@ QList<QByteArray> QHttpNetworkHeaderPrivate::headerFieldValues(const QByteArray
void QHttpNetworkHeaderPrivate::setHeaderField(const QByteArray &name, const QByteArray &data)
{
auto firstEqualsName = [&name](const QPair<QByteArray, QByteArray> &header) {
- return qstricmp(name.constData(), header.first) == 0;
+ return name.compare(header.first, Qt::CaseInsensitive) == 0;
};
fields.erase(std::remove_if(fields.begin(), fields.end(),
firstEqualsName),
diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp
index a657346958..c9c3172304 100644
--- a/src/network/access/qhttpnetworkreply.cpp
+++ b/src/network/access/qhttpnetworkreply.cpp
@@ -390,7 +390,8 @@ qint64 QHttpNetworkReplyPrivate::bytesAvailable() const
bool QHttpNetworkReplyPrivate::isCompressed()
{
QByteArray encoding = headerField("content-encoding");
- return qstricmp(encoding.constData(), "gzip") == 0 || qstricmp(encoding.constData(), "deflate") == 0;
+ return encoding.compare("gzip", Qt::CaseInsensitive) == 0 ||
+ encoding.compare("deflate", Qt::CaseInsensitive) == 0;
}
void QHttpNetworkReplyPrivate::removeAutoDecompressHeader()
@@ -401,7 +402,7 @@ void QHttpNetworkReplyPrivate::removeAutoDecompressHeader()
QList<QPair<QByteArray, QByteArray> >::Iterator it = fields.begin(),
end = fields.end();
while (it != end) {
- if (qstricmp(name.constData(), it->first.constData()) == 0) {
+ if (name.compare(it->first, Qt::CaseInsensitive) == 0) {
removedContentLength = strtoull(it->second.constData(), nullptr, 0);
fields.erase(it);
break;
diff --git a/src/network/access/qnetworkaccessdebugpipebackend.cpp b/src/network/access/qnetworkaccessdebugpipebackend.cpp
index d7914e4143..67a856506c 100644
--- a/src/network/access/qnetworkaccessdebugpipebackend.cpp
+++ b/src/network/access/qnetworkaccessdebugpipebackend.cpp
@@ -107,8 +107,8 @@ void QNetworkAccessDebugPipeBackend::open()
bareProtocol = QUrlQuery(url()).queryItemValue(QLatin1String("bare")) == QLatin1String("1");
if (operation() == QNetworkAccessManager::PutOperation) {
- uploadByteDevice = createUploadByteDevice();
- QObject::connect(uploadByteDevice, SIGNAL(readyRead()), this, SLOT(uploadReadyReadSlot()));
+ createUploadByteDevice();
+ QObject::connect(uploadByteDevice.data(), SIGNAL(readyRead()), this, SLOT(uploadReadyReadSlot()));
QMetaObject::invokeMethod(this, "uploadReadyReadSlot", Qt::QueuedConnection);
}
}
diff --git a/src/network/access/qnetworkaccessdebugpipebackend_p.h b/src/network/access/qnetworkaccessdebugpipebackend_p.h
index d9a7aabdad..761c7055b8 100644
--- a/src/network/access/qnetworkaccessdebugpipebackend_p.h
+++ b/src/network/access/qnetworkaccessdebugpipebackend_p.h
@@ -77,7 +77,6 @@ protected:
void pushFromSocketToDownstream();
void pushFromUpstreamToSocket();
void possiblyFinish();
- QNonContiguousByteDevice *uploadByteDevice;
private slots:
void uploadReadyReadSlot();
diff --git a/src/network/access/qnetworkaccessfilebackend.cpp b/src/network/access/qnetworkaccessfilebackend.cpp
index d4ca9c22fc..60353cb03e 100644
--- a/src/network/access/qnetworkaccessfilebackend.cpp
+++ b/src/network/access/qnetworkaccessfilebackend.cpp
@@ -99,7 +99,7 @@ QNetworkAccessFileBackendFactory::create(QNetworkAccessManager::Operation op,
}
QNetworkAccessFileBackend::QNetworkAccessFileBackend()
- : uploadByteDevice(0), totalBytes(0), hasUploadFinished(false)
+ : totalBytes(0), hasUploadFinished(false)
{
}
@@ -154,8 +154,8 @@ void QNetworkAccessFileBackend::open()
break;
case QNetworkAccessManager::PutOperation:
mode = QIODevice::WriteOnly | QIODevice::Truncate;
- uploadByteDevice = createUploadByteDevice();
- QObject::connect(uploadByteDevice, SIGNAL(readyRead()), this, SLOT(uploadReadyReadSlot()));
+ createUploadByteDevice();
+ QObject::connect(uploadByteDevice.data(), SIGNAL(readyRead()), this, SLOT(uploadReadyReadSlot()));
QMetaObject::invokeMethod(this, "uploadReadyReadSlot", Qt::QueuedConnection);
break;
default:
diff --git a/src/network/access/qnetworkaccessfilebackend_p.h b/src/network/access/qnetworkaccessfilebackend_p.h
index 2c01fb1121..2204958ee0 100644
--- a/src/network/access/qnetworkaccessfilebackend_p.h
+++ b/src/network/access/qnetworkaccessfilebackend_p.h
@@ -73,8 +73,6 @@ public:
public slots:
void uploadReadyReadSlot();
-protected:
- QNonContiguousByteDevice *uploadByteDevice;
private:
QFile file;
qint64 totalBytes;
diff --git a/src/network/access/qnetworkaccessftpbackend.cpp b/src/network/access/qnetworkaccessftpbackend.cpp
index bc44a78a9a..fd6589b396 100644
--- a/src/network/access/qnetworkaccessftpbackend.cpp
+++ b/src/network/access/qnetworkaccessftpbackend.cpp
@@ -102,8 +102,8 @@ public:
};
QNetworkAccessFtpBackend::QNetworkAccessFtpBackend()
- : ftp(0), uploadDevice(0), totalBytes(0), helpId(-1), sizeId(-1), mdtmId(-1),
- supportsSize(false), supportsMdtm(false), state(Idle)
+ : ftp(0), uploadDevice(0), totalBytes(0), helpId(-1), sizeId(-1), mdtmId(-1), pwdId(-1),
+ supportsSize(false), supportsMdtm(false), supportsPwd(false), state(Idle)
{
}
@@ -302,13 +302,38 @@ void QNetworkAccessFtpBackend::ftpDone()
if (state == LoggingIn) {
state = CheckingFeatures;
- if (operation() == QNetworkAccessManager::GetOperation) {
- // send help command to find out if server supports "SIZE" and "MDTM"
+ // send help command to find out if server supports SIZE, MDTM, and PWD
+ if (operation() == QNetworkAccessManager::GetOperation
+ || operation() == QNetworkAccessManager::PutOperation) {
helpId = ftp->rawCommand(QLatin1String("HELP")); // get supported commands
} else {
ftpDone();
}
} else if (state == CheckingFeatures) {
+ // If a URL path starts with // prefix (/%2F decoded), the resource will
+ // be retrieved by an absolute path starting with the root directory.
+ // For the other URLs, the working directory is retrieved by PWD command
+ // and prepended to the resource path as an absolute path starting with
+ // the working directory.
+ state = ResolvingPath;
+ QString path = url().path();
+ if (path.startsWith(QLatin1String("//")) || supportsPwd == false) {
+ ftpDone(); // no commands sent, move to the next state
+ } else {
+ // If a path starts with /~/ prefix, its prefix will be replaced by
+ // the working directory as an absolute path starting with working
+ // directory.
+ if (path.startsWith(QLatin1String("/~/"))) {
+ // Remove leading /~ symbols
+ QUrl newUrl = url();
+ newUrl.setPath(path.mid(2));
+ setUrl(newUrl);
+ }
+
+ // send PWD command to retrieve the working directory
+ pwdId = ftp->rawCommand(QLatin1String("PWD"));
+ }
+ } else if (state == ResolvingPath) {
state = Statting;
if (operation() == QNetworkAccessManager::GetOperation) {
// logged in successfully, send the stat requests (if supported)
@@ -366,6 +391,34 @@ void QNetworkAccessFtpBackend::ftpRawCommandReply(int code, const QString &text)
supportsSize = true;
if (text.contains(QLatin1String("MDTM"), Qt::CaseSensitive))
supportsMdtm = true;
+ if (text.contains(QLatin1String("PWD"), Qt::CaseSensitive))
+ supportsPwd = true;
+ } else if (id == pwdId && code == 257) {
+ QString pwdPath;
+ int startIndex = text.indexOf('"');
+ int stopIndex = text.lastIndexOf('"');
+ if (stopIndex - startIndex) {
+ // The working directory is a substring between \" symbols.
+ startIndex++; // skip the first \" symbol
+ pwdPath = text.mid(startIndex, stopIndex - startIndex);
+ } else {
+ // If there is no or only one \" symbol, use all the characters of
+ // text.
+ pwdPath = text;
+ }
+
+ // If a URL path starts with the working directory prefix, its resource
+ // will be retrieved from the working directory. Otherwise, the path of
+ // the working directory is prepended to the resource path.
+ QString urlPath = url().path();
+ if (!urlPath.startsWith(pwdPath)) {
+ if (pwdPath.endsWith(QLatin1Char('/')))
+ pwdPath.chop(1);
+ // Prepend working directory to the URL path
+ QUrl newUrl = url();
+ newUrl.setPath(pwdPath % urlPath);
+ setUrl(newUrl);
+ }
} else if (code == 213) { // file status
if (id == sizeId) {
// reply to the size command
diff --git a/src/network/access/qnetworkaccessftpbackend_p.h b/src/network/access/qnetworkaccessftpbackend_p.h
index 4bd082fb67..0b3d35dcd3 100644
--- a/src/network/access/qnetworkaccessftpbackend_p.h
+++ b/src/network/access/qnetworkaccessftpbackend_p.h
@@ -76,6 +76,7 @@ public:
//Connecting,
LoggingIn,
CheckingFeatures,
+ ResolvingPath,
Statting,
Transferring,
Disconnecting
@@ -107,8 +108,8 @@ private:
QPointer<QNetworkAccessCachedFtpConnection> ftp;
QIODevice *uploadDevice;
qint64 totalBytes;
- int helpId, sizeId, mdtmId;
- bool supportsSize, supportsMdtm;
+ int helpId, sizeId, mdtmId, pwdId;
+ bool supportsSize, supportsMdtm, supportsPwd;
State state;
};
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index a2649fe77c..1f0d2f92e2 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -86,6 +86,9 @@
#include <SystemConfiguration/SystemConfiguration.h>
#include <Security/SecKeychain.h>
#endif
+#ifdef Q_OS_WASM
+#include "qnetworkreplywasmimpl_p.h"
+#endif
QT_BEGIN_NAMESPACE
@@ -940,7 +943,7 @@ QNetworkReply *QNetworkAccessManager::put(const QNetworkRequest &request, QHttpM
/*!
Uploads the contents of \a data to the destination \a request and
- returnes a new QNetworkReply object that will be open for reply.
+ returns a new QNetworkReply object that will be open for reply.
\a data must be opened for reading when this function is called
and must remain valid until the finished() signal is emitted for
@@ -1357,6 +1360,16 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
bool isLocalFile = req.url().isLocalFile();
QString scheme = req.url().scheme();
+#ifdef Q_OS_WASM
+ if (scheme == QLatin1String("http") || scheme == QLatin1String("https")) {
+ QNetworkReplyWasmImpl *reply = new QNetworkReplyWasmImpl(this);
+ QNetworkReplyWasmImplPrivate *priv = reply->d_func();
+ priv->manager = this;
+ priv->setup(op, req, outgoingData);
+ return reply;
+ }
+#endif
+
// fast path for GET on file:// URLs
// The QNetworkAccessFileBackend will right now only be used for PUT
if (op == QNetworkAccessManager::GetOperation
@@ -1835,6 +1848,7 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co
if (config.isValid())
newSession = QSharedNetworkSessionManager::getSession(config);
+ QNetworkSession::State oldState = QNetworkSession::Invalid;
if (networkSessionStrongRef) {
//do nothing if new and old session are the same
if (networkSessionStrongRef == newSession)
@@ -1846,6 +1860,7 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co
q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)));
QObject::disconnect(networkSessionStrongRef.data(), SIGNAL(error(QNetworkSession::SessionError)),
q, SLOT(_q_networkSessionFailed(QNetworkSession::SessionError)));
+ oldState = networkSessionStrongRef->state();
}
//switch to new session (null if config was invalid)
@@ -1871,7 +1886,11 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co
QObject::connect(networkSessionStrongRef.data(), SIGNAL(error(QNetworkSession::SessionError)),
q, SLOT(_q_networkSessionFailed(QNetworkSession::SessionError)));
- _q_networkSessionStateChanged(networkSessionStrongRef->state());
+ const QNetworkSession::State newState = networkSessionStrongRef->state();
+ if (newState != oldState) {
+ QMetaObject::invokeMethod(q, "_q_networkSessionStateChanged", Qt::QueuedConnection,
+ Q_ARG(QNetworkSession::State, newState));
+ }
}
void QNetworkAccessManagerPrivate::_q_networkSessionClosed()
diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h
index a0ce3eddcd..67b3a8b71b 100644
--- a/src/network/access/qnetworkaccessmanager.h
+++ b/src/network/access/qnetworkaccessmanager.h
@@ -195,6 +195,9 @@ private:
friend class QNetworkReplyHttpImplPrivate;
friend class QNetworkReplyFileImpl;
+#ifdef Q_OS_WASM
+ friend class QNetworkReplyWasmImpl;
+#endif
Q_DECLARE_PRIVATE(QNetworkAccessManager)
Q_PRIVATE_SLOT(d_func(), void _q_replyFinished())
Q_PRIVATE_SLOT(d_func(), void _q_replyEncrypted())
diff --git a/src/network/access/qnetworkdiskcache.cpp b/src/network/access/qnetworkdiskcache.cpp
index c9d658225e..df2e4902a4 100644
--- a/src/network/access/qnetworkdiskcache.cpp
+++ b/src/network/access/qnetworkdiskcache.cpp
@@ -189,7 +189,7 @@ QIODevice *QNetworkDiskCache::prepare(const QNetworkCacheMetaData &metaData)
const auto headers = metaData.rawHeaders();
for (const auto &header : headers) {
- if (header.first.toLower() == "content-length") {
+ if (header.first.compare("content-length", Qt::CaseInsensitive) == 0) {
const qint64 size = header.second.toLongLong();
if (size > (maximumCacheSize() * 3)/4)
return 0;
@@ -642,7 +642,7 @@ bool QCacheItem::canCompress() const
bool typeOk = false;
const auto headers = metaData.rawHeaders();
for (const auto &header : headers) {
- if (header.first.toLower() == "content-length") {
+ if (header.first.compare("content-length", Qt::CaseInsensitive) == 0) {
qint64 size = header.second.toLongLong();
if (size > MAX_COMPRESSION_SIZE)
return false;
@@ -650,7 +650,7 @@ bool QCacheItem::canCompress() const
sizeOk = true;
}
- if (header.first.toLower() == "content-type") {
+ if (header.first.compare("content-type", Qt::CaseInsensitive) == 0) {
QByteArray type = header.second;
if (type.startsWith("text/")
|| (type.startsWith("application/")
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index 9067dea8e3..8750a841f6 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -1318,7 +1318,7 @@ void QNetworkReplyHttpImplPrivate::replyDownloadMetaData(const QList<QPair<QByte
if (!value.isEmpty()) {
// Why are we appending values for headers which are already
// present?
- if (qstricmp(it->first.constData(), "set-cookie") == 0)
+ if (it->first.compare("set-cookie", Qt::CaseInsensitive) == 0)
value += '\n';
else
value += ", ";
@@ -1584,7 +1584,7 @@ bool QNetworkReplyHttpImplPrivate::sendCacheContents(const QNetworkCacheMetaData
QUrl redirectUrl;
for ( ; it != end; ++it) {
if (httpRequest.isFollowRedirects() &&
- !qstricmp(it->first.toLower().constData(), "location"))
+ !it->first.compare("location", Qt::CaseInsensitive))
redirectUrl = QUrl::fromEncoded(it->second);
setRawHeader(it->first, it->second);
}
diff --git a/src/network/access/qnetworkreplywasmimpl.cpp b/src/network/access/qnetworkreplywasmimpl.cpp
new file mode 100644
index 0000000000..23ca62acd4
--- /dev/null
+++ b/src/network/access/qnetworkreplywasmimpl.cpp
@@ -0,0 +1,618 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 "qnetworkreplywasmimpl_p.h"
+#include "qnetworkrequest.h"
+
+#include <QtCore/qtimer.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qthread.h>
+
+#include <private/qnetworkaccessmanager_p.h>
+#include <private/qnetworkfile_p.h>
+
+#include <emscripten.h>
+#include <emscripten/bind.h>
+#include <emscripten/val.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace emscripten;
+
+static void q_requestErrorCallback(val event)
+{
+ val xhr = event["target"];
+
+ quintptr func = xhr["data-handler"].as<quintptr>();
+ QNetworkReplyWasmImplPrivate *reply = reinterpret_cast<QNetworkReplyWasmImplPrivate*>(func);
+ Q_ASSERT(reply);
+
+ int statusCode = xhr["status"].as<int>();
+
+ QString reasonStr = QString::fromStdString(xhr["statusText"].as<std::string>());
+
+ reply->setReplyAttributes(func, statusCode, reasonStr);
+
+ if (statusCode >= 400 && !reasonStr.isEmpty())
+ reply->emitReplyError(reply->statusCodeFromHttp(statusCode, reply->request.url()), reasonStr);
+}
+
+static void q_progressCallback(val event)
+{
+ val xhr = event["target"];
+
+ QNetworkReplyWasmImplPrivate *reply =
+ reinterpret_cast<QNetworkReplyWasmImplPrivate*>(xhr["data-handler"].as<quintptr>());
+ Q_ASSERT(reply);
+
+ if (xhr["lengthComputable"].as<bool>() && xhr["status"].as<int>() < 400)
+ reply->emitDataReadProgress(xhr["loaded"].as<qint64>(), xhr["total"].as<qint64>());
+
+}
+
+static void q_loadCallback(val event)
+{
+ val xhr = event["target"];
+
+ QNetworkReplyWasmImplPrivate *reply =
+ reinterpret_cast<QNetworkReplyWasmImplPrivate*>(xhr["data-handler"].as<quintptr>());
+ Q_ASSERT(reply);
+
+ int status = xhr["status"].as<int>();
+ if (status >= 300) {
+ q_requestErrorCallback(event);
+ return;
+ }
+ QString statusText = QString::fromStdString(xhr["statusText"].as<std::string>());
+ if (status == 200 || status == 203) {
+ QString responseString;
+ const std::string responseType = xhr["responseType"].as<std::string>();
+ if (responseType.length() == 0 || responseType == "document" || responseType == "text") {
+ responseString = QString::fromStdWString(xhr["responseText"].as<std::wstring>());
+ } else if (responseType == "json") {
+ responseString =
+ QString::fromStdWString(val::global("JSON").call<std::wstring>("stringify", xhr["response"]));
+ } else if (responseType == "arraybuffer" || responseType == "blob") {
+ // handle this data in the FileReader, triggered by the call to readAsArrayBuffer
+ val reader = val::global("FileReader").new_();
+ reader.set("onload", val::module_property("QNetworkReplyWasmImplPrivate_readBinary"));
+ reader.set("data-handler", xhr["data-handler"]);
+ reader.call<void>("readAsArrayBuffer", xhr["response"]);
+ }
+
+ int readyState = xhr["readyState"].as<int>();
+
+ if (readyState == 4) { // done
+ reply->setReplyAttributes(xhr["data-handler"].as<quintptr>(), status, statusText);
+ if (!responseString.isEmpty())
+ reply->dataReceived(responseString.toUtf8(), responseString.size());
+ }
+ }
+ if (status >= 400 && !statusText.isEmpty())
+ reply->emitReplyError(reply->statusCodeFromHttp(status, reply->request.url()), statusText);
+}
+
+static void q_responseHeadersCallback(val event)
+{
+ val xhr = event["target"];
+
+ if (xhr["readyState"].as<int>() == 2) { // HEADERS_RECEIVED
+ std::string responseHeaders = xhr.call<std::string>("getAllResponseHeaders");
+ if (!responseHeaders.empty()) {
+ QNetworkReplyWasmImplPrivate *reply =
+ reinterpret_cast<QNetworkReplyWasmImplPrivate*>(xhr["data-handler"].as<quintptr>());
+ Q_ASSERT(reply);
+
+ reply->headersReceived(QString::fromStdString(responseHeaders));
+ }
+ }
+}
+
+static void q_readBinary(val event)
+{
+ val fileReader = event["target"];
+
+ QNetworkReplyWasmImplPrivate *reply =
+ reinterpret_cast<QNetworkReplyWasmImplPrivate*>(fileReader["data-handler"].as<quintptr>());
+ Q_ASSERT(reply);
+
+ // Set up source typed array
+ val result = fileReader["result"]; // ArrayBuffer
+ val Uint8Array = val::global("Uint8Array");
+ val sourceTypedArray = Uint8Array.new_(result);
+
+ // Allocate and set up destination typed array
+ const quintptr size = result["byteLength"].as<quintptr>();
+ QByteArray buffer(size, Qt::Uninitialized);
+
+ val destinationTypedArray = Uint8Array.new_(val::module_property("HEAPU8")["buffer"],
+ reinterpret_cast<quintptr>(buffer.data()), size);
+ destinationTypedArray.call<void>("set", sourceTypedArray);
+ reply->dataReceived(buffer, buffer.size());
+}
+
+
+EMSCRIPTEN_BINDINGS(network_module) {
+ function("QNetworkReplyWasmImplPrivate_requestErrorCallback", q_requestErrorCallback);
+ function("QNetworkReplyWasmImplPrivate_progressCallback", q_progressCallback);
+ function("QNetworkReplyWasmImplPrivate_loadCallback", q_loadCallback);
+ function("QNetworkReplyWasmImplPrivate_responseHeadersCallback", q_responseHeadersCallback);
+ function("QNetworkReplyWasmImplPrivate_readBinary", q_readBinary);
+}
+
+QNetworkReplyWasmImplPrivate::QNetworkReplyWasmImplPrivate()
+ : QNetworkReplyPrivate()
+ , managerPrivate(0)
+ , downloadBufferReadPosition(0)
+ , downloadBufferCurrentSize(0)
+ , totalDownloadSize(0)
+ , percentFinished(0)
+{
+}
+
+QNetworkReplyWasmImplPrivate::~QNetworkReplyWasmImplPrivate()
+{
+}
+
+QNetworkReplyWasmImpl::~QNetworkReplyWasmImpl()
+{
+}
+
+QNetworkReplyWasmImpl::QNetworkReplyWasmImpl(QObject *parent)
+ : QNetworkReply(*new QNetworkReplyWasmImplPrivate(), parent)
+{
+}
+
+QByteArray QNetworkReplyWasmImpl::methodName() const
+{
+ switch (operation()) {
+ case QNetworkAccessManager::HeadOperation:
+ return "HEAD";
+ case QNetworkAccessManager::GetOperation:
+ return "GET";
+ case QNetworkAccessManager::PutOperation:
+ return "PUT";
+ case QNetworkAccessManager::PostOperation:
+ return "POST";
+ case QNetworkAccessManager::DeleteOperation:
+ return "DELETE";
+ default:
+ break;
+ }
+ return QByteArray();
+}
+
+void QNetworkReplyWasmImpl::close()
+{
+ QNetworkReply::close();
+}
+
+void QNetworkReplyWasmImpl::abort()
+{
+ close();
+}
+
+qint64 QNetworkReplyWasmImpl::bytesAvailable() const
+{
+ Q_D(const QNetworkReplyWasmImpl);
+
+ if (!d->isFinished)
+ return QNetworkReply::bytesAvailable();
+
+ return QNetworkReply::bytesAvailable() + d->downloadBufferCurrentSize - d->downloadBufferReadPosition;
+}
+
+bool QNetworkReplyWasmImpl::isSequential() const
+{
+ return true;
+}
+
+qint64 QNetworkReplyWasmImpl::size() const
+{
+ return QNetworkReply::size();
+}
+
+/*!
+ \internal
+*/
+qint64 QNetworkReplyWasmImpl::readData(char *data, qint64 maxlen)
+{
+ Q_D(QNetworkReplyWasmImpl);
+
+ qint64 howMuch = qMin(maxlen, (d->downloadBuffer.size() - d->downloadBufferReadPosition));
+ memcpy(data, d->downloadBuffer.constData(), howMuch);
+ d->downloadBufferReadPosition += howMuch;
+
+ return howMuch;
+}
+
+void QNetworkReplyWasmImplPrivate::setup(QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice *data)
+{
+ Q_Q(QNetworkReplyWasmImpl);
+
+ outgoingData = data;
+ request = req;
+ url = request.url();
+ operation = op;
+
+ q->QIODevice::open(QIODevice::ReadOnly);
+ if (outgoingData && outgoingData->isSequential()) {
+ bool bufferingDisallowed =
+ request.attribute(QNetworkRequest::DoNotBufferUploadDataAttribute, false).toBool();
+
+ if (bufferingDisallowed) {
+ // if a valid content-length header for the request was supplied, we can disable buffering
+ // if not, we will buffer anyway
+ if (!request.header(QNetworkRequest::ContentLengthHeader).isValid()) {
+ state = Buffering;
+ _q_bufferOutgoingData();
+ return;
+ }
+ } else {
+ // doSendRequest will be called when the buffering has finished.
+ state = Buffering;
+ _q_bufferOutgoingData();
+ return;
+ }
+ }
+ // No outgoing data (POST, ..)
+ doSendRequest();
+}
+
+void QNetworkReplyWasmImplPrivate::setReplyAttributes(quintptr data, int statusCode, const QString &statusReason)
+{
+ QNetworkReplyWasmImplPrivate *handler = reinterpret_cast<QNetworkReplyWasmImplPrivate*>(data);
+ Q_ASSERT(handler);
+
+ handler->q_func()->setAttribute(QNetworkRequest::HttpStatusCodeAttribute, statusCode);
+ if (!statusReason.isEmpty())
+ handler->q_func()->setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, statusReason);
+}
+
+void QNetworkReplyWasmImplPrivate::doSendRequest()
+{
+ Q_Q(QNetworkReplyWasmImpl);
+ totalDownloadSize = 0;
+
+ val xhr = val::global("XMLHttpRequest").new_();
+ std::string verb = q->methodName().toStdString();
+
+ QUrl url;
+ QString extraDataString;
+
+ if (request.url().hasQuery()) { //strip query from url
+ extraDataString = request.url().query(QUrl::FullyEncoded);
+ QString urlStr = request.url().toString();
+ url.setUrl(urlStr.left(urlStr.indexOf("?")));
+ } else {
+ url = request.url();
+ }
+ xhr.call<void>("open", verb, url.toString().toStdString());
+
+ xhr.set("onerror", val::module_property("QNetworkReplyWasmImplPrivate_requestErrorCallback"));
+ xhr.set("onload", val::module_property("QNetworkReplyWasmImplPrivate_loadCallback"));
+ xhr.set("onprogress", val::module_property("QNetworkReplyWasmImplPrivate_progressCallback"));
+ xhr.set("onreadystatechange", val::module_property("QNetworkReplyWasmImplPrivate_responseHeadersCallback"));
+
+ xhr.set("data-handler", val(quintptr(reinterpret_cast<void *>(this))));
+
+ QByteArray contentType = request.rawHeader("Content-Type");
+
+ // handle extra data
+ val dataToSend = val::null();
+ QByteArray extraData;
+
+ if (outgoingData) // data from post request
+ extraData = outgoingData->readAll();
+
+ if (contentType.contains("text") ||
+ contentType.contains("json") ||
+ contentType.contains("form")) {
+ if (extraData.size() > 0)
+ extraDataString.fromUtf8(extraData);
+ }
+ if (contentType.contains("json")) {
+ if (!extraDataString.isEmpty()) {
+ xhr.set("responseType", val("json"));
+ dataToSend = val(extraDataString.toStdString());
+ }
+ }
+ if (contentType.contains("form")) { //construct form data
+ if (!extraDataString.isEmpty()) {
+ val formData = val::global("FormData").new_();
+ QStringList formList = extraDataString.split('&');
+
+ for (auto formEntry : formList) {
+ formData.call<void>("append", formEntry.split('=')[0].toStdString(), formEntry.split('=')[1].toStdString());
+ }
+ dataToSend = formData;
+ }
+ }
+ // set request headers
+ for (auto header : request.rawHeaderList()) {
+ xhr.call<void>("setRequestHeader", header.toStdString(), request.rawHeader(header).toStdString());
+ }
+ xhr.call<void>("send", dataToSend);
+}
+
+void QNetworkReplyWasmImplPrivate::emitReplyError(QNetworkReply::NetworkError errorCode, const QString &errorString)
+{
+ Q_UNUSED(errorCode)
+ Q_Q(QNetworkReplyWasmImpl);
+
+ q->setError(errorCode, errorString);
+ emit q->error(errorCode);
+
+ q->setFinished(true);
+ emit q->finished();
+}
+
+void QNetworkReplyWasmImplPrivate::emitDataReadProgress(qint64 bytesReceived, qint64 bytesTotal)
+{
+ Q_Q(QNetworkReplyWasmImpl);
+
+ totalDownloadSize = bytesTotal;
+
+ percentFinished = (bytesReceived / bytesTotal) * 100;
+
+ emit q->downloadProgress(bytesReceived, bytesTotal);
+}
+
+void QNetworkReplyWasmImplPrivate::dataReceived(const QByteArray &buffer, int bufferSize)
+{
+ Q_Q(QNetworkReplyWasmImpl);
+
+ if (bufferSize > 0)
+ q->setReadBufferSize(bufferSize);
+
+ bytesDownloaded = bufferSize;
+
+ if (percentFinished != 100)
+ downloadBufferCurrentSize += bufferSize;
+ else
+ downloadBufferCurrentSize = bufferSize;
+
+ totalDownloadSize = downloadBufferCurrentSize;
+
+ downloadBuffer.append(buffer, bufferSize);
+
+ if (downloadBufferCurrentSize == totalDownloadSize) {
+ q->setFinished(true);
+ emit q->finished();
+ }
+}
+
+//taken from qnetworkrequest.cpp
+static int parseHeaderName(const QByteArray &headerName)
+{
+ if (headerName.isEmpty())
+ return -1;
+
+ switch (tolower(headerName.at(0))) {
+ case 'c':
+ if (qstricmp(headerName.constData(), "content-type") == 0)
+ return QNetworkRequest::ContentTypeHeader;
+ else if (qstricmp(headerName.constData(), "content-length") == 0)
+ return QNetworkRequest::ContentLengthHeader;
+ else if (qstricmp(headerName.constData(), "cookie") == 0)
+ return QNetworkRequest::CookieHeader;
+ break;
+
+ case 'l':
+ if (qstricmp(headerName.constData(), "location") == 0)
+ return QNetworkRequest::LocationHeader;
+ else if (qstricmp(headerName.constData(), "last-modified") == 0)
+ return QNetworkRequest::LastModifiedHeader;
+ break;
+
+ case 's':
+ if (qstricmp(headerName.constData(), "set-cookie") == 0)
+ return QNetworkRequest::SetCookieHeader;
+ else if (qstricmp(headerName.constData(), "server") == 0)
+ return QNetworkRequest::ServerHeader;
+ break;
+
+ case 'u':
+ if (qstricmp(headerName.constData(), "user-agent") == 0)
+ return QNetworkRequest::UserAgentHeader;
+ break;
+ }
+
+ return -1; // nothing found
+}
+
+
+void QNetworkReplyWasmImplPrivate::headersReceived(const QString &bufferString)
+{
+ Q_Q(QNetworkReplyWasmImpl);
+
+ if (!bufferString.isEmpty()) {
+ QStringList headers = bufferString.split(QString::fromUtf8("\r\n"), QString::SkipEmptyParts);
+
+ for (int i = 0; i < headers.size(); i++) {
+ QString headerName = headers.at(i).split(QString::fromUtf8(": ")).at(0);
+ QString headersValue = headers.at(i).split(QString::fromUtf8(": ")).at(1);
+ if (headerName.isEmpty() || headersValue.isEmpty())
+ continue;
+
+ int headerIndex = parseHeaderName(headerName.toLocal8Bit());
+
+ if (headerIndex == -1)
+ q->setRawHeader(headerName.toLocal8Bit(), headersValue.toLocal8Bit());
+ else
+ q->setHeader(static_cast<QNetworkRequest::KnownHeaders>(headerIndex), (QVariant)headersValue);
+ }
+ }
+ emit q->metaDataChanged();
+}
+
+void QNetworkReplyWasmImplPrivate::_q_bufferOutgoingDataFinished()
+{
+ Q_Q(QNetworkReplyWasmImpl);
+
+ // make sure this is only called once, ever.
+ //_q_bufferOutgoingData may call it or the readChannelFinished emission
+ if (state != Buffering)
+ return;
+
+ // disconnect signals
+ QObject::disconnect(outgoingData, SIGNAL(readyRead()), q, SLOT(_q_bufferOutgoingData()));
+ QObject::disconnect(outgoingData, SIGNAL(readChannelFinished()), q, SLOT(_q_bufferOutgoingDataFinished()));
+
+ // finally, start the request
+ doSendRequest();
+}
+
+void QNetworkReplyWasmImplPrivate::_q_bufferOutgoingData()
+{
+ Q_Q(QNetworkReplyWasmImpl);
+
+ if (!outgoingDataBuffer) {
+ // first call, create our buffer
+ outgoingDataBuffer = QSharedPointer<QRingBuffer>::create();
+
+ QObject::connect(outgoingData, SIGNAL(readyRead()), q, SLOT(_q_bufferOutgoingData()));
+ QObject::connect(outgoingData, SIGNAL(readChannelFinished()), q, SLOT(_q_bufferOutgoingDataFinished()));
+ }
+
+ qint64 bytesBuffered = 0;
+ qint64 bytesToBuffer = 0;
+
+ // read data into our buffer
+ forever {
+ bytesToBuffer = outgoingData->bytesAvailable();
+ // unknown? just try 2 kB, this also ensures we always try to read the EOF
+ if (bytesToBuffer <= 0)
+ bytesToBuffer = 2*1024;
+
+ char *dst = outgoingDataBuffer->reserve(bytesToBuffer);
+ bytesBuffered = outgoingData->read(dst, bytesToBuffer);
+
+ if (bytesBuffered == -1) {
+ // EOF has been reached.
+ outgoingDataBuffer->chop(bytesToBuffer);
+
+ _q_bufferOutgoingDataFinished();
+ break;
+ } else if (bytesBuffered == 0) {
+ // nothing read right now, just wait until we get called again
+ outgoingDataBuffer->chop(bytesToBuffer);
+
+ break;
+ } else {
+ // don't break, try to read() again
+ outgoingDataBuffer->chop(bytesToBuffer - bytesBuffered);
+ }
+ }
+}
+
+//taken from qhttpthreaddelegate.cpp
+QNetworkReply::NetworkError QNetworkReplyWasmImplPrivate::statusCodeFromHttp(int httpStatusCode, const QUrl &url)
+{
+ QNetworkReply::NetworkError code;
+ // we've got an error
+ switch (httpStatusCode) {
+ case 400: // Bad Request
+ code = QNetworkReply::ProtocolInvalidOperationError;
+ break;
+
+ case 401: // Authorization required
+ code = QNetworkReply::AuthenticationRequiredError;
+ break;
+
+ case 403: // Access denied
+ code = QNetworkReply::ContentAccessDenied;
+ break;
+
+ case 404: // Not Found
+ code = QNetworkReply::ContentNotFoundError;
+ break;
+
+ case 405: // Method Not Allowed
+ code = QNetworkReply::ContentOperationNotPermittedError;
+ break;
+
+ case 407:
+ code = QNetworkReply::ProxyAuthenticationRequiredError;
+ break;
+
+ case 409: // Resource Conflict
+ code = QNetworkReply::ContentConflictError;
+ break;
+
+ case 410: // Content no longer available
+ code = QNetworkReply::ContentGoneError;
+ break;
+
+ case 418: // I'm a teapot
+ code = QNetworkReply::ProtocolInvalidOperationError;
+ break;
+
+ case 500: // Internal Server Error
+ code = QNetworkReply::InternalServerError;
+ break;
+
+ case 501: // Server does not support this functionality
+ code = QNetworkReply::OperationNotImplementedError;
+ break;
+
+ case 503: // Service unavailable
+ code = QNetworkReply::ServiceUnavailableError;
+ break;
+
+ default:
+ if (httpStatusCode > 500) {
+ // some kind of server error
+ code = QNetworkReply::UnknownServerError;
+ } else if (httpStatusCode >= 400) {
+ // content error we did not handle above
+ code = QNetworkReply::UnknownContentError;
+ } else {
+ qWarning("QNetworkAccess: got HTTP status code %d which is not expected from url: \"%s\"",
+ httpStatusCode, qPrintable(url.toString()));
+ code = QNetworkReply::ProtocolFailure;
+ }
+ };
+
+ return code;
+}
+
+QT_END_NAMESPACE
diff --git a/src/network/access/qnetworkreplywasmimpl_p.h b/src/network/access/qnetworkreplywasmimpl_p.h
new file mode 100644
index 0000000000..69c90de41a
--- /dev/null
+++ b/src/network/access/qnetworkreplywasmimpl_p.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 QNETWORKREPLYWASMIMPL_H
+#define QNETWORKREPLYWASMIMPL_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the Network Access API. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qnetworkreply.h"
+#include "qnetworkreply_p.h"
+#include "qnetworkaccessmanager.h"
+
+#include <QtCore/qfile.h>
+
+#include <private/qtnetworkglobal_p.h>
+#include <private/qabstractfileengine_p.h>
+
+#include <emscripten.h>
+#include <emscripten/html5.h>
+
+QT_BEGIN_NAMESPACE
+
+class QIODevice;
+
+class QNetworkReplyWasmImplPrivate;
+class QNetworkReplyWasmImpl: public QNetworkReply
+{
+ Q_OBJECT
+public:
+ QNetworkReplyWasmImpl(QObject *parent = nullptr);
+ ~QNetworkReplyWasmImpl();
+ virtual void abort() override;
+
+ // reimplemented from QNetworkReply
+ virtual void close() override;
+ virtual qint64 bytesAvailable() const override;
+ virtual bool isSequential () const override;
+ qint64 size() const override;
+
+ virtual qint64 readData(char *data, qint64 maxlen) override;
+
+ void setup(QNetworkAccessManager::Operation op, const QNetworkRequest &request,
+ QIODevice *outgoingData);
+
+ Q_DECLARE_PRIVATE(QNetworkReplyWasmImpl)
+
+ Q_PRIVATE_SLOT(d_func(), void emitReplyError(QNetworkReply::NetworkError errorCode, const QString &errorString))
+ Q_PRIVATE_SLOT(d_func(), void emitDataReadProgress(qint64 done, qint64 total))
+ Q_PRIVATE_SLOT(d_func(), void dataReceived(char *buffer, int bufferSize))
+
+private:
+ QByteArray methodName() const;
+};
+
+class QNetworkReplyWasmImplPrivate: public QNetworkReplyPrivate
+{
+public:
+ QNetworkReplyWasmImplPrivate();
+ ~QNetworkReplyWasmImplPrivate();
+
+ QNetworkAccessManagerPrivate *managerPrivate;
+ void doSendRequest();
+ static void setReplyAttributes(quintptr data, int statusCode, const QString &statusReason);
+
+ void emitReplyError(QNetworkReply::NetworkError errorCode, const QString &);
+ void emitDataReadProgress(qint64 done, qint64 total);
+ void dataReceived(const QByteArray &buffer, int bufferSize);
+ void headersReceived(const QString &bufferString);
+
+ void setup(QNetworkAccessManager::Operation op, const QNetworkRequest &request,
+ QIODevice *outgoingData);
+
+ State state;
+ void _q_bufferOutgoingData();
+ void _q_bufferOutgoingDataFinished();
+
+ QSharedPointer<QAtomicInt> pendingDownloadData;
+ QSharedPointer<QAtomicInt> pendingDownloadProgress;
+
+ qint64 bytesDownloaded;
+ qint64 bytesBuffered;
+
+ qint64 downloadBufferReadPosition;
+ qint64 downloadBufferCurrentSize;
+ qint64 totalDownloadSize;
+ qint64 percentFinished;
+ QByteArray downloadBuffer;
+
+ QIODevice *outgoingData;
+ QSharedPointer<QRingBuffer> outgoingDataBuffer;
+
+ static QNetworkReply::NetworkError statusCodeFromHttp(int httpStatusCode, const QUrl &url);
+ Q_DECLARE_PUBLIC(QNetworkReplyWasmImpl)
+};
+
+QT_END_NAMESPACE
+
+#endif // QNETWORKREPLYWASMIMPL_H
diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp
index 4cb93805dc..689eecfbb9 100644
--- a/src/network/access/qnetworkrequest.cpp
+++ b/src/network/access/qnetworkrequest.cpp
@@ -98,6 +98,25 @@ QT_BEGIN_NAMESPACE
header and contains a QDateTime representing the last modification
date of the contents.
+ \value IfModifiedSinceHeader Corresponds to the HTTP If-Modified-Since
+ header and contains a QDateTime. It is usually added to a
+ QNetworkRequest. The server shall send a 304 (Not Modified) response
+ if the resource has not changed since this time.
+
+ \value ETagHeader Corresponds to the HTTP ETag
+ header and contains a QString representing the last modification
+ state of the contents.
+
+ \value IfMatchHeader Corresponds to the HTTP If-Match
+ header and contains a QStringList. It is usually added to a
+ QNetworkRequest. The server shall send a 412 (Precondition Failed)
+ response if the resource does not match.
+
+ \value IfNoneMatchHeader Corresponds to the HTTP If-None-Match
+ header and contains a QStringList. It is usually added to a
+ QNetworkRequest. The server shall send a 304 (Not Modified) response
+ if the resource does match.
+
\value CookieHeader Corresponds to the HTTP Cookie header
and contains a QList<QNetworkCookie> representing the cookies to
be sent back to the server.
@@ -785,6 +804,18 @@ static QByteArray headerName(QNetworkRequest::KnownHeaders header)
case QNetworkRequest::LastModifiedHeader:
return "Last-Modified";
+ case QNetworkRequest::IfModifiedSinceHeader:
+ return "If-Modified-Since";
+
+ case QNetworkRequest::ETagHeader:
+ return "ETag";
+
+ case QNetworkRequest::IfMatchHeader:
+ return "If-Match";
+
+ case QNetworkRequest::IfNoneMatchHeader:
+ return "If-None-Match";
+
case QNetworkRequest::CookieHeader:
return "Cookie";
@@ -815,6 +846,9 @@ static QByteArray headerValue(QNetworkRequest::KnownHeaders header, const QVaria
case QNetworkRequest::ContentDispositionHeader:
case QNetworkRequest::UserAgentHeader:
case QNetworkRequest::ServerHeader:
+ case QNetworkRequest::ETagHeader:
+ case QNetworkRequest::IfMatchHeader:
+ case QNetworkRequest::IfNoneMatchHeader:
return value.toByteArray();
case QNetworkRequest::LocationHeader:
@@ -827,6 +861,7 @@ static QByteArray headerValue(QNetworkRequest::KnownHeaders header, const QVaria
}
case QNetworkRequest::LastModifiedHeader:
+ case QNetworkRequest::IfModifiedSinceHeader:
switch (value.userType()) {
case QMetaType::QDate:
case QMetaType::QDateTime:
@@ -880,32 +915,46 @@ static int parseHeaderName(const QByteArray &headerName)
switch (tolower(headerName.at(0))) {
case 'c':
- if (qstricmp(headerName.constData(), "content-type") == 0)
+ if (headerName.compare("content-type", Qt::CaseInsensitive) == 0)
return QNetworkRequest::ContentTypeHeader;
- else if (qstricmp(headerName.constData(), "content-length") == 0)
+ else if (headerName.compare("content-length", Qt::CaseInsensitive) == 0)
return QNetworkRequest::ContentLengthHeader;
- else if (qstricmp(headerName.constData(), "cookie") == 0)
+ else if (headerName.compare("cookie", Qt::CaseInsensitive) == 0)
return QNetworkRequest::CookieHeader;
else if (qstricmp(headerName.constData(), "content-disposition") == 0)
return QNetworkRequest::ContentDispositionHeader;
break;
+ case 'e':
+ if (qstricmp(headerName.constData(), "etag") == 0)
+ return QNetworkRequest::ETagHeader;
+ break;
+
+ case 'i':
+ if (qstricmp(headerName.constData(), "if-modified-since") == 0)
+ return QNetworkRequest::IfModifiedSinceHeader;
+ if (qstricmp(headerName.constData(), "if-match") == 0)
+ return QNetworkRequest::IfMatchHeader;
+ if (qstricmp(headerName.constData(), "if-none-match") == 0)
+ return QNetworkRequest::IfNoneMatchHeader;
+ break;
+
case 'l':
- if (qstricmp(headerName.constData(), "location") == 0)
+ if (headerName.compare("location", Qt::CaseInsensitive) == 0)
return QNetworkRequest::LocationHeader;
- else if (qstricmp(headerName.constData(), "last-modified") == 0)
+ else if (headerName.compare("last-modified", Qt::CaseInsensitive) == 0)
return QNetworkRequest::LastModifiedHeader;
break;
case 's':
- if (qstricmp(headerName.constData(), "set-cookie") == 0)
+ if (headerName.compare("set-cookie", Qt::CaseInsensitive) == 0)
return QNetworkRequest::SetCookieHeader;
- else if (qstricmp(headerName.constData(), "server") == 0)
+ else if (headerName.compare("server", Qt::CaseInsensitive) == 0)
return QNetworkRequest::ServerHeader;
break;
case 'u':
- if (qstricmp(headerName.constData(), "user-agent") == 0)
+ if (headerName.compare("user-agent", Qt::CaseInsensitive) == 0)
return QNetworkRequest::UserAgentHeader;
break;
}
@@ -936,6 +985,61 @@ static QVariant parseCookieHeader(const QByteArray &raw)
return QVariant::fromValue(result);
}
+static QVariant parseETag(const QByteArray &raw)
+{
+ const QByteArray trimmed = raw.trimmed();
+ if (!trimmed.startsWith('"') && !trimmed.startsWith(R"(W/")"))
+ return QVariant();
+
+ if (!trimmed.endsWith('"'))
+ return QVariant();
+
+ return QString::fromLatin1(trimmed);
+}
+
+static QVariant parseIfMatch(const QByteArray &raw)
+{
+ const QByteArray trimmedRaw = raw.trimmed();
+ if (trimmedRaw == "*")
+ return QStringList(QStringLiteral("*"));
+
+ QStringList tags;
+ const QList<QByteArray> split = trimmedRaw.split(',');
+ for (const QByteArray &element : split) {
+ const QByteArray trimmed = element.trimmed();
+ if (!trimmed.startsWith('"'))
+ continue;
+
+ if (!trimmed.endsWith('"'))
+ continue;
+
+ tags += QString::fromLatin1(trimmed);
+ }
+ return tags;
+}
+
+static QVariant parseIfNoneMatch(const QByteArray &raw)
+{
+ const QByteArray trimmedRaw = raw.trimmed();
+ if (trimmedRaw == "*")
+ return QStringList(QStringLiteral("*"));
+
+ QStringList tags;
+ const QList<QByteArray> split = trimmedRaw.split(',');
+ for (const QByteArray &element : split) {
+ const QByteArray trimmed = element.trimmed();
+ if (!trimmed.startsWith('"') && !trimmed.startsWith(R"(W/")"))
+ continue;
+
+ if (!trimmed.endsWith('"'))
+ continue;
+
+ tags += QString::fromLatin1(trimmed);
+ }
+ return tags;
+}
+
+
static QVariant parseHeaderValue(QNetworkRequest::KnownHeaders header, const QByteArray &value)
{
// header is always a valid value
@@ -963,8 +1067,18 @@ static QVariant parseHeaderValue(QNetworkRequest::KnownHeaders header, const QBy
}
case QNetworkRequest::LastModifiedHeader:
+ case QNetworkRequest::IfModifiedSinceHeader:
return parseHttpDate(value);
+ case QNetworkRequest::ETagHeader:
+ return parseETag(value);
+
+ case QNetworkRequest::IfMatchHeader:
+ return parseIfMatch(value);
+
+ case QNetworkRequest::IfNoneMatchHeader:
+ return parseIfNoneMatch(value);
+
case QNetworkRequest::CookieHeader:
return parseCookieHeader(value);
@@ -983,7 +1097,7 @@ QNetworkHeadersPrivate::findRawHeader(const QByteArray &key) const
RawHeadersList::ConstIterator it = rawHeaders.constBegin();
RawHeadersList::ConstIterator end = rawHeaders.constEnd();
for ( ; it != end; ++it)
- if (qstricmp(it->first.constData(), key.constData()) == 0)
+ if (it->first.compare(key, Qt::CaseInsensitive) == 0)
return it;
return end; // not found
@@ -1064,7 +1178,7 @@ void QNetworkHeadersPrivate::setCookedHeader(QNetworkRequest::KnownHeaders heade
void QNetworkHeadersPrivate::setRawHeaderInternal(const QByteArray &key, const QByteArray &value)
{
auto firstEqualsKey = [&key](const RawHeaderPair &header) {
- return qstricmp(header.first.constData(), key.constData()) == 0;
+ return header.first.compare(key, Qt::CaseInsensitive) == 0;
};
rawHeaders.erase(std::remove_if(rawHeaders.begin(), rawHeaders.end(),
firstEqualsKey),
diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h
index e104c139d9..8462eae8c8 100644
--- a/src/network/access/qnetworkrequest.h
+++ b/src/network/access/qnetworkrequest.h
@@ -63,7 +63,11 @@ public:
SetCookieHeader,
ContentDispositionHeader, // added for QMultipartMessage
UserAgentHeader,
- ServerHeader
+ ServerHeader,
+ IfModifiedSinceHeader,
+ ETagHeader,
+ IfMatchHeader,
+ IfNoneMatchHeader
};
enum Attribute {
HttpStatusCodeAttribute,
diff --git a/src/network/bearer/qnetworksession.cpp b/src/network/bearer/qnetworksession.cpp
index e5562e3a0b..471d322998 100644
--- a/src/network/bearer/qnetworksession.cpp
+++ b/src/network/bearer/qnetworksession.cpp
@@ -323,11 +323,7 @@ void QNetworkSession::open()
The following example waits up to one second for the session to be opened:
- \code
- session->open();
- if (session->waitForOpened(1000))
- qDebug("Open!");
- \endcode
+ \snippet code/src_network_bearer_qnetworksession.cpp 0
If \a msecs is -1, this function will not time out.
@@ -491,20 +487,7 @@ QString QNetworkSession::errorString() const
The main purpose of this key is to determine which Internet access point is used
if the session is based on a \l{QNetworkConfiguration::ServiceNetwork}{ServiceNetwork}.
The following code snippet highlights the difference:
- \code
- QNetworkConfigurationManager mgr;
- QNetworkConfiguration ap = mgr.defaultConfiguration();
- QNetworkSession *session = new QNetworkSession(ap);
- ... //code activates session
-
- QString ident = session->sessionProperty("ActiveConfiguration").toString();
- if ( ap.type() == QNetworkConfiguration::ServiceNetwork ) {
- Q_ASSERT( ap.identifier() != ident );
- Q_ASSERT( ap.children().contains( mgr.configurationFromIdentifier(ident) ) );
- } else if ( ap.type() == QNetworkConfiguration::InternetAccessPoint ) {
- Q_ASSERT( ap.identifier() == ident );
- }
- \endcode
+ \snippet code/src_network_bearer_qnetworksession.cpp 1
\row
\li UserChoiceConfiguration
\li If the session \l isOpen() and is bound to a QNetworkConfiguration of type
diff --git a/src/network/configure.json b/src/network/configure.json
index 4cbc476837..327131ba11 100644
--- a/src/network/configure.json
+++ b/src/network/configure.json
@@ -14,6 +14,7 @@
"openssl": { "type": "optionalString", "values": [ "no", "yes", "linked", "runtime" ] },
"openssl-linked": { "type": "void", "name": "openssl", "value": "linked" },
"openssl-runtime": { "type": "void", "name": "openssl", "value": "runtime" },
+ "dtls": "boolean",
"sctp": "boolean",
"securetransport": "boolean",
"ssl": "boolean",
@@ -149,6 +150,19 @@
"type": "compile",
"test": "unix/openssl11",
"use": "openssl"
+ },
+ "dtls": {
+ "label": "DTLS support in OpenSSL",
+ "type": "compile",
+ "test": {
+ "include": "openssl/ssl.h",
+ "tail": [
+ "#if defined(OPENSSL_NO_DTLS) || !defined(DTLS1_2_VERSION)",
+ "# error OpenSSL without DTLS support",
+ "#endif"
+ ]
+ },
+ "use": "openssl"
}
},
@@ -184,7 +198,7 @@
"label": "OpenSSL",
"enable": "input.openssl == 'yes' || input.openssl == 'linked' || input.openssl == 'runtime'",
"disable": "input.openssl == 'no' || input.ssl == 'no'",
- "autoDetect": "!config.winrt",
+ "autoDetect": "!config.winrt && !config.wasm",
"condition": "!features.securetransport && (features.openssl-linked || libs.openssl_headers)",
"output": [
"privateFeature",
@@ -216,6 +230,13 @@
"condition": "config.winrt || features.securetransport || features.openssl",
"output": [ "publicFeature", "feature" ]
},
+ "dtls": {
+ "label": "DTLS",
+ "purpose": "Provides a DTLS implementation",
+ "section": "Networking",
+ "condition": "features.openssl && tests.dtls",
+ "output": [ "publicFeature" ]
+ },
"opensslv11": {
"label": "OpenSSL 1.1",
"condition": "features.openssl && tests.openssl11",
@@ -242,6 +263,7 @@
"label": "HTTP",
"purpose": "Provides support for the Hypertext Transfer Protocol in QNetworkAccessManager.",
"section": "Networking",
+ "condition": "features.thread",
"output": [ "publicFeature", "feature" ]
},
"udpsocket": {
@@ -266,6 +288,7 @@
"networkinterface": {
"label": "QNetworkInterface",
"purpose": "Supports enumerating a host's IP addresses and network interfaces.",
+ "condition": "!config.wasm",
"section": "Networking",
"output": [ "publicFeature", "feature" ]
},
@@ -280,7 +303,7 @@
"label": "Bearer management",
"purpose": "Provides bearer management for the network stack.",
"section": "Networking",
- "condition": "features.library && features.networkinterface && features.properties",
+ "condition": "features.thread && features.library && features.networkinterface && features.properties",
"output": [ "publicFeature", "feature" ]
},
"localserver": {
@@ -346,6 +369,7 @@ For example:
"openssl",
"openssl-linked",
"opensslv11",
+ "dtls",
"sctp",
"system-proxies"
]
diff --git a/src/network/configure.pri b/src/network/configure.pri
index f87b7f635f..fa502db1d1 100644
--- a/src/network/configure.pri
+++ b/src/network/configure.pri
@@ -3,7 +3,7 @@
defineTest(qtConfLibrary_openssl) {
libs = $$getenv("OPENSSL_LIBS")
!isEmpty(libs) {
- $${1}.libs = $$libs
+ eval($${1}.libs = $$libs)
export($${1}.libs)
return(true)
}
diff --git a/src/network/doc/snippets/code/src_network_access_qnetworkaccessmanager.cpp b/src/network/doc/snippets/code/src_network_access_qnetworkaccessmanager.cpp
index 873b74363f..aed74e308e 100644
--- a/src/network/doc/snippets/code/src_network_access_qnetworkaccessmanager.cpp
+++ b/src/network/doc/snippets/code/src_network_access_qnetworkaccessmanager.cpp
@@ -50,8 +50,8 @@
//! [0]
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
-connect(manager, SIGNAL(finished(QNetworkReply*)),
- this, SLOT(replyFinished(QNetworkReply*)));
+connect(manager, &QNetworkAccessManager::finished,
+ this, &MyClass::replyFinished);
manager->get(QNetworkRequest(QUrl("http://qt-project.org")));
//! [0]
@@ -63,11 +63,11 @@ request.setUrl(QUrl("http://qt-project.org"));
request.setRawHeader("User-Agent", "MyOwnBrowser 1.0");
QNetworkReply *reply = manager->get(request);
-connect(reply, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
-connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
- this, SLOT(slotError(QNetworkReply::NetworkError)));
-connect(reply, SIGNAL(sslErrors(QList<QSslError>)),
- this, SLOT(slotSslErrors(QList<QSslError>)));
+connect(reply, &QIODevice::readyRead, this, &MyClass::slotReadyRead);
+connect(reply, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error),
+ this, &MyClass::slotError);
+connect(reply, &QNetworkReply::sslErrors,
+ this, &MyClass::slotSslErrors);
//! [1]
//! [2]
diff --git a/src/network/doc/snippets/code/src_network_bearer_qnetworksession.cpp b/src/network/doc/snippets/code/src_network_bearer_qnetworksession.cpp
new file mode 100644
index 0000000000..b88b6d1768
--- /dev/null
+++ b/src/network/doc/snippets/code/src_network_bearer_qnetworksession.cpp
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+ session->open();
+ if (session->waitForOpened(1000))
+ qDebug("Open!");
+//! [0]
+
+//! [1]
+ QNetworkConfigurationManager mgr;
+ QNetworkConfiguration ap = mgr.defaultConfiguration();
+ QNetworkSession *session = new QNetworkSession(ap);
+ ... //code activates session
+
+ QString ident = session->sessionProperty("ActiveConfiguration").toString();
+ if ( ap.type() == QNetworkConfiguration::ServiceNetwork ) {
+ Q_ASSERT( ap.identifier() != ident );
+ Q_ASSERT( ap.children().contains( mgr.configurationFromIdentifier(ident) ) );
+ } else if ( ap.type() == QNetworkConfiguration::InternetAccessPoint ) {
+ Q_ASSERT( ap.identifier() == ident );
+ }
+ \endcode
+//! [1]
diff --git a/src/network/doc/snippets/code/src_network_kernel_qnetworkdatagram.cpp b/src/network/doc/snippets/code/src_network_kernel_qnetworkdatagram.cpp
new file mode 100644
index 0000000000..f81ca97681
--- /dev/null
+++ b/src/network/doc/snippets/code/src_network_kernel_qnetworkdatagram.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+ void Server::readPendingDatagrams()
+ {
+ while (udpSocket->hasPendingDatagrams()) {
+ QNetworkDatagram datagram = udpSocket->receiveDatagram();
+ QByteArray replyData = processThePayload(datagram.data());
+ udpSocket->writeDatagram(datagram.makeReply(replyData));
+ }
+ }
+//! [0]
+
+//! [1]
+ udpSocket->writeDatagram(std::move(datagram).makeReply(replyData));
+//! [1]
diff --git a/src/network/doc/snippets/code/src_network_kernel_qnetworkinterface.cpp b/src/network/doc/snippets/code/src_network_kernel_qnetworkinterface.cpp
new file mode 100644
index 0000000000..fc7fd7814a
--- /dev/null
+++ b/src/network/doc/snippets/code/src_network_kernel_qnetworkinterface.cpp
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+ QNetworkInterface::interfaceFromName(name).index()
+//! [0]
+
+//! [1]
+ QNetworkInterface::interfaceFromIndex(index).name()
+//! [1]
diff --git a/src/network/doc/snippets/code/src_network_ssl_qdtls.cpp b/src/network/doc/snippets/code/src_network_ssl_qdtls.cpp
new file mode 100644
index 0000000000..2132b48338
--- /dev/null
+++ b/src/network/doc/snippets/code/src_network_ssl_qdtls.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+// A client initiates a handshake:
+QUdpSocket clientSocket;
+QDtls clientDtls;
+clientDtls.setPeer(address, port, peerName);
+clientDtls.doHandshake(&clientSocket);
+
+// A server accepting an incoming connection; address, port, clientHello are
+// read by QUdpSocket::readDatagram():
+QByteArray clientHello(serverSocket.pendingDatagramSize(), Qt::Uninitialized);
+QHostAddress address;
+quin16 port = {};
+serverSocket.readDatagram(clientHello.data(), clientHello.size(), &address, &port);
+
+QDtls serverDtls;
+serverDtls.setPeer(address, port);
+serverDtls.doHandshake(&serverSocket, clientHello);
+
+// Handshake completion, both for server and client:
+void DtlsConnection::continueHandshake(const QByteArray &datagram)
+{
+ if (dtls.doHandshake(&udpSocket, datagram)) {
+ // Check handshake status:
+ if (dtls.handshakeStatus() == QDlts::HandshakeComplete) {
+ // Secure DTLS connection is now established.
+ }
+ } else {
+ // Error handling.
+ }
+}
+
+//! [0]
+
+//! [1]
+DtlsClient::DtlsClient()
+{
+ // Some initialization code here ...
+ connect(&clientDtls, &QDtls::handshakeTimeout, this, &DtlsClient::handleTimeout);
+}
+
+void DtlsClient::handleTimeout()
+{
+ clientDtls.handleTimeout(&clientSocket);
+}
+//! [1]
+
+//! [2]
+// Sending an encrypted datagram:
+dtlsConnection.writeDatagramEncrypted(&clientSocket, "Hello DTLS server!");
+
+// Decryption:
+QByteArray encryptedMessage(dgramSize);
+socket.readDatagram(encryptedMessage.data(), dgramSize);
+const QByteArray plainText = dtlsConnection.decryptDatagram(&socket, encryptedMessage);
+//! [2]
+
+//! [3]
+DtlsClient::~DtlsClient()
+{
+ clientDtls.shutdown(&clientSocket);
+}
+//! [3]
+
+//! [4]
+auto config = QSslConfiguration::defaultDtlsConfiguration();
+config.setDtlsCookieVerificationEnabled(false);
+// Some other customization ...
+dtlsConnection.setDtlsConfiguration(config);
+//! [4]
+
+//! [5]
+if (!dtls.doHandshake(&socket, dgram)) {
+ if (dtls.dtlsError() == QDtlsError::PeerVerificationError)
+ dtls.abortAfterError(&socket);
+}
+//! [5]
+
+//! [6]
+QList<QSslCertificate> cert = QSslCertificate::fromPath(QLatin1String("server-certificate.pem"));
+QSslError error(QSslError::SelfSignedCertificate, cert.at(0));
+QList<QSslError> expectedSslErrors;
+expectedSslErrors.append(error);
+
+QDtls dtls;
+dtls.ignoreVerificationErrors(expectedSslErrors);
+dtls.doHandshake(udpSocket);
+//! [6]
+
diff --git a/src/network/doc/snippets/code/src_network_ssl_qdtlscookie.cpp b/src/network/doc/snippets/code/src_network_ssl_qdtlscookie.cpp
new file mode 100644
index 0000000000..a9e596eca5
--- /dev/null
+++ b/src/network/doc/snippets/code/src_network_ssl_qdtlscookie.cpp
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+class DtlsServer : public QObject
+{
+public:
+ bool listen(const QHostAddress &address, quint16 port);
+ // ...
+
+private:
+ void readyRead();
+ // ...
+
+ QUdpSocket serverSocket;
+ QDtlsClientVerifier verifier;
+ // ...
+};
+
+bool DtlsServer::listen(const QHostAddress &serverAddress, quint16 serverPort)
+{
+ if (serverSocket.bind(serverAddress, serverPort))
+ connect(&serverSocket, &QUdpSocket::readyRead, this, &DtlsServer::readyRead);
+ return serverSocket.state() == QAbstractSocket::BoundState;
+}
+
+void DtlsServer::readyRead()
+{
+ QByteArray dgram(serverSocket.pendingDatagramSize(), Qt::Uninitialized);
+ QHostAddress address;
+ quint16 port = {};
+ serverSocket.readDatagram(dgram.data(), dgram.size(), &address, &port);
+ if (verifiedClients.contains({address, port}) {
+ // This client was verified previously, we either continue the
+ // handshake or decrypt the incoming message.
+ } else if (verifier.verifyClient(&serverSocket, dgram, address, port)) {
+ // Apparently we have a real DTLS client who wants to send us
+ // encrypted datagrams. Remember this client as verified
+ // and proceed with a handshake.
+ } else {
+ // No matching cookie was found in the incoming datagram,
+ // verifyClient() has sent a ClientVerify message.
+ // We'll hear from the client again soon, if they're real.
+ }
+}
+//! [0]
+
+//! [1]
+void DtlsServer::updateServerSecret()
+{
+ const QByteArray newSecret(generateCryptoStrongSecret());
+ if (newSecret.size()) {
+ usedCookies.append(newSecret);
+ verifier.setCookieGeneratorParameters({QCryptographicHash::Sha1, newSecret});
+ }
+}
+//! [1]
+
+//! [2]
+if (!verifier.verifyClient(&socket, message, address, port)) {
+ switch (verifyClient.dtlsError()) {
+ case QDtlsError::NoError:
+ // Not verified yet, but no errors found and we have to wait for the next
+ // message from this client.
+ return;
+ case QDtlsError::TlsInitializationError:
+ // This error is fatal, nothing we can do about it.
+ // Probably, quit the server after reporting the error.
+ return;
+ case QDtlsError::UnderlyingSocketError:
+ // There is some problem in QUdpSocket, handle it (see QUdpSocket::error())
+ return;
+ case QDtlsError::InvalidInputParameters:
+ default:
+ Q_UNREACHABLE();
+ }
+}
+//! [2]
diff --git a/src/network/doc/snippets/code/src_network_ssl_qsslpresharedkeyauthenticator.cpp b/src/network/doc/snippets/code/src_network_ssl_qsslpresharedkeyauthenticator.cpp
new file mode 100644
index 0000000000..22e60840a3
--- /dev/null
+++ b/src/network/doc/snippets/code/src_network_ssl_qsslpresharedkeyauthenticator.cpp
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+ connect(socket, &QSslSocket::preSharedKeyAuthenticationRequired,
+ this, &AuthManager::handlePreSharedKeyAuthentication);
+//! [0]
+
+//! [1]
+ void AuthManager::handlePreSharedKeyAuthentication(QSslPreSharedKeyAuthenticator *authenticator)
+ {
+ authenticator->setIdentity("My Qt App");
+
+ const QByteArray key = deriveKey(authenticator->identityHint(), passphrase);
+ authenticator->setPreSharedKey(key);
+ }
+//! [1]
diff --git a/src/network/doc/src/ssl.qdoc b/src/network/doc/src/ssl.qdoc
index 58589f8479..a3af1d0477 100644
--- a/src/network/doc/src/ssl.qdoc
+++ b/src/network/doc/src/ssl.qdoc
@@ -66,6 +66,15 @@
To disable SSL support in a Qt build, configure Qt with the \c{-no-openssl}
option.
+ \section1 Datagram Transport Layer Security
+
+ Datagram Transport Layer Security (DTLS) is a protocol that enables security
+ for datagram-based applications, providing them with protection against
+ eavesdropping, tampering, or message forgery. The DTLS protocol is based on the
+ stream-oriented Transport Layer Security (TLS) protocol. QtNetwork enables
+ the use of DTLS with User Datagram Protocol (UDP), as defined by
+ \l {https://tools.ietf.org/html/rfc6347}{RFC 6347}.
+
\section1 Import and Export Restrictions
Due to import and export restrictions in some parts of the world, we
diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp
index c995e3fef2..34db5b4b31 100644
--- a/src/network/kernel/qauthenticator.cpp
+++ b/src/network/kernel/qauthenticator.cpp
@@ -412,7 +412,7 @@ void QAuthenticatorPrivate::parseHttpResponse(const QList<QPair<QByteArray, QByt
QByteArray headerVal;
for (int i = 0; i < values.size(); ++i) {
const QPair<QByteArray, QByteArray> &current = values.at(i);
- if (current.first.toLower() != search)
+ if (current.first.compare(search, Qt::CaseInsensitive) != 0)
continue;
QByteArray str = current.second.toLower();
if (method < Basic && str.startsWith("basic")) {
@@ -443,7 +443,7 @@ void QAuthenticatorPrivate::parseHttpResponse(const QList<QPair<QByteArray, QByt
break;
case DigestMd5: {
this->options[QLatin1String("realm")] = realm = QString::fromLatin1(options.value("realm"));
- if (options.value("stale").toLower() == "true")
+ if (options.value("stale").compare("true", Qt::CaseInsensitive) == 0)
phase = Start;
if (user.isEmpty() && password.isEmpty())
phase = Done;
@@ -630,7 +630,7 @@ static QByteArray digestMd5ResponseHelper(
hash.addData(":", 1);
hash.addData(password);
QByteArray ha1 = hash.result();
- if (alg.toLower() == "md5-sess") {
+ if (alg.compare("md5-sess", Qt::CaseInsensitive) == 0) {
hash.reset();
// RFC 2617 contains an error, it was:
// hash.addData(ha1);
@@ -650,7 +650,7 @@ static QByteArray digestMd5ResponseHelper(
hash.addData(method);
hash.addData(":", 1);
hash.addData(digestUri);
- if (qop.toLower() == "auth-int") {
+ if (qop.compare("auth-int", Qt::CaseInsensitive) == 0) {
hash.addData(":", 1);
hash.addData(hEntity);
}
diff --git a/src/network/kernel/qdnslookup.cpp b/src/network/kernel/qdnslookup.cpp
index 10ff35b72c..1b66829070 100644
--- a/src/network/kernel/qdnslookup.cpp
+++ b/src/network/kernel/qdnslookup.cpp
@@ -49,7 +49,9 @@
QT_BEGIN_NAMESPACE
+#if QT_CONFIG(thread)
Q_GLOBAL_STATIC(QDnsLookupThreadPool, theDnsLookupThreadPool);
+#endif
static bool qt_qdnsmailexchangerecord_less_than(const QDnsMailExchangeRecord &r1, const QDnsMailExchangeRecord &r2)
{
@@ -503,7 +505,9 @@ void QDnsLookup::lookup()
connect(d->runnable, SIGNAL(finished(QDnsLookupReply)),
this, SLOT(_q_lookupFinished(QDnsLookupReply)),
Qt::BlockingQueuedConnection);
+#if QT_CONFIG(thread)
theDnsLookupThreadPool()->start(d->runnable);
+#endif
}
/*!
@@ -1016,6 +1020,7 @@ void QDnsLookupRunnable::run()
emit finished(reply);
}
+#if QT_CONFIG(thread)
QDnsLookupThreadPool::QDnsLookupThreadPool()
: signalsConnected(false)
{
@@ -1051,7 +1056,7 @@ void QDnsLookupThreadPool::_q_applicationDestroyed()
waitForDone();
signalsConnected = false;
}
-
+#endif // QT_CONFIG(thread)
QT_END_NAMESPACE
#include "moc_qdnslookup.cpp"
diff --git a/src/network/kernel/qdnslookup_p.h b/src/network/kernel/qdnslookup_p.h
index 4584396efe..2dc98e527a 100644
--- a/src/network/kernel/qdnslookup_p.h
+++ b/src/network/kernel/qdnslookup_p.h
@@ -55,7 +55,9 @@
#include "QtCore/qmutex.h"
#include "QtCore/qrunnable.h"
#include "QtCore/qsharedpointer.h"
+#if QT_CONFIG(thread)
#include "QtCore/qthreadpool.h"
+#endif
#include "QtNetwork/qdnslookup.h"
#include "QtNetwork/qhostaddress.h"
#include "private/qobject_p.h"
@@ -132,6 +134,7 @@ private:
QHostAddress nameserver;
};
+#if QT_CONFIG(thread)
class QDnsLookupThreadPool : public QThreadPool
{
Q_OBJECT
@@ -147,6 +150,7 @@ private:
QMutex signalsMutex;
bool signalsConnected;
};
+#endif // QT_CONFIG(thread)
class QDnsRecordPrivate : public QSharedData
{
diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp
index 4682070712..0973d0dd52 100644
--- a/src/network/kernel/qhostinfo.cpp
+++ b/src/network/kernel/qhostinfo.cpp
@@ -704,6 +704,7 @@ void QHostInfoRunnable::run()
hostInfo.setLookupId(id);
resultEmitter.emitResultsReady(hostInfo);
+#if QT_CONFIG(thread)
// now also iterate through the postponed ones
{
QMutexLocker locker(&manager->mutex);
@@ -720,6 +721,7 @@ void QHostInfoRunnable::run()
manager->postponedLookups.erase(partitionBegin, partitionEnd);
}
+#endif
manager->lookupFinished(this);
// thread goes back to QThreadPool
@@ -728,8 +730,10 @@ void QHostInfoRunnable::run()
QHostInfoLookupManager::QHostInfoLookupManager() : mutex(QMutex::Recursive), wasDeleted(false)
{
moveToThread(QCoreApplicationPrivate::mainThread());
+#if QT_CONFIG(thread)
connect(QCoreApplication::instance(), SIGNAL(destroyed()), SLOT(waitForThreadPoolDone()), Qt::DirectConnection);
threadPool.setMaxThreadCount(20); // do up to 20 DNS lookups in parallel
+#endif
}
QHostInfoLookupManager::~QHostInfoLookupManager()
@@ -744,15 +748,19 @@ void QHostInfoLookupManager::clear()
{
{
QMutexLocker locker(&mutex);
- qDeleteAll(postponedLookups);
qDeleteAll(scheduledLookups);
qDeleteAll(finishedLookups);
+#if QT_CONFIG(thread)
+ qDeleteAll(postponedLookups);
postponedLookups.clear();
+#endif
scheduledLookups.clear();
finishedLookups.clear();
}
+#if QT_CONFIG(thread)
threadPool.waitForDone();
+#endif
cache.clear();
}
@@ -776,6 +784,7 @@ void QHostInfoLookupManager::work()
finishedLookups.clear();
}
+#if QT_CONFIG(thread)
auto isAlreadyRunning = [this](QHostInfoRunnable *lookup) {
return any_of(currentLookups.cbegin(), currentLookups.cend(), ToBeLookedUpEquals(lookup->toBeLookedUp));
};
@@ -808,6 +817,10 @@ void QHostInfoLookupManager::work()
}
scheduledLookups.erase(scheduledLookups.begin(), it);
}
+#else
+ if (!scheduledLookups.isEmpty())
+ scheduledLookups.takeFirst()->run();
+#endif
}
// called by QHostInfo
@@ -829,6 +842,7 @@ void QHostInfoLookupManager::abortLookup(int id)
QMutexLocker locker(&this->mutex);
+#if QT_CONFIG(thread)
// is postponed? delete and return
for (int i = 0; i < postponedLookups.length(); i++) {
if (postponedLookups.at(i)->id == id) {
@@ -836,6 +850,7 @@ void QHostInfoLookupManager::abortLookup(int id)
return;
}
}
+#endif
// is scheduled? delete and return
for (int i = 0; i < scheduledLookups.length(); i++) {
@@ -866,7 +881,9 @@ void QHostInfoLookupManager::lookupFinished(QHostInfoRunnable *r)
return;
QMutexLocker locker(&this->mutex);
+#if QT_CONFIG(thread)
currentLookups.removeOne(r);
+#endif
finishedLookups.append(r);
work();
}
diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h
index 82cf34719f..8cce302166 100644
--- a/src/network/kernel/qhostinfo_p.h
+++ b/src/network/kernel/qhostinfo_p.h
@@ -61,7 +61,9 @@
#include "QtCore/qobject.h"
#include "QtCore/qpointer.h"
#include "QtCore/qthread.h"
+#if QT_CONFIG(thread)
#include "QtCore/qthreadpool.h"
+#endif
#include "QtCore/qrunnable.h"
#include "QtCore/qlist.h"
#include "QtCore/qqueue.h"
@@ -238,20 +240,25 @@ public:
friend class QHostInfoRunnable;
protected:
+#if QT_CONFIG(thread)
QList<QHostInfoRunnable*> currentLookups; // in progress
QList<QHostInfoRunnable*> postponedLookups; // postponed because in progress for same host
+#endif
QQueue<QHostInfoRunnable*> scheduledLookups; // not yet started
QList<QHostInfoRunnable*> finishedLookups; // recently finished
QList<int> abortedLookups; // ids of aborted lookups
+#if QT_CONFIG(thread)
QThreadPool threadPool;
-
+#endif
QMutex mutex;
bool wasDeleted;
private slots:
+#if QT_CONFIG(thread)
void waitForThreadPoolDone() { threadPool.waitForDone(); }
+#endif
};
QT_END_NAMESPACE
diff --git a/src/network/kernel/qhostinfo_win.cpp b/src/network/kernel/qhostinfo_win.cpp
index bea24b0af2..c51e9968f8 100644
--- a/src/network/kernel/qhostinfo_win.cpp
+++ b/src/network/kernel/qhostinfo_win.cpp
@@ -92,13 +92,13 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
sockaddr *sa;
QT_SOCKLEN_T saSize;
if (address.protocol() == QAbstractSocket::IPv4Protocol) {
- sa = (sockaddr *)&sa4;
+ sa = reinterpret_cast<sockaddr *>(&sa4);
saSize = sizeof(sa4);
memset(&sa4, 0, sizeof(sa4));
sa4.sin_family = AF_INET;
sa4.sin_addr.s_addr = htonl(address.toIPv4Address());
} else {
- sa = (sockaddr *)&sa6;
+ sa = reinterpret_cast<sockaddr *>(&sa6);
saSize = sizeof(sa6);
memset(&sa6, 0, sizeof(sa6));
sa6.sin6_family = AF_INET6;
@@ -132,14 +132,14 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
switch (p->ai_family) {
case AF_INET: {
QHostAddress addr;
- addr.setAddress(ntohl(((sockaddr_in *) p->ai_addr)->sin_addr.s_addr));
+ addr.setAddress(ntohl(reinterpret_cast<sockaddr_in *>(p->ai_addr)->sin_addr.s_addr));
if (!addresses.contains(addr))
addresses.append(addr);
}
break;
case AF_INET6: {
QHostAddress addr;
- addr.setAddress(((sockaddr_in6 *) p->ai_addr)->sin6_addr.s6_addr);
+ addr.setAddress(reinterpret_cast<const sockaddr_in6 *>(p->ai_addr)->sin6_addr.s6_addr);
if (!addresses.contains(addr))
addresses.append(addr);
}
diff --git a/src/network/kernel/qnetworkdatagram.cpp b/src/network/kernel/qnetworkdatagram.cpp
index 50421fa7f5..c8c87d4549 100644
--- a/src/network/kernel/qnetworkdatagram.cpp
+++ b/src/network/kernel/qnetworkdatagram.cpp
@@ -450,16 +450,7 @@ void QNetworkDatagram::setData(const QByteArray &data)
way of responding to a datagram back to the original sender.
Example:
- \code
- void Server::readPendingDatagrams()
- {
- while (udpSocket->hasPendingDatagrams()) {
- QNetworkDatagram datagram = udpSocket->receiveDatagram();
- QByteArray replyData = processThePayload(datagram.data());
- udpSocket->writeDatagram(datagram.makeReply(replyData));
- }
- }
- \endcode
+ \snippet code/src_network_kernel_qnetworkdatagram.cpp 0
This function is especially convenient since it will automatically copy
parameters from this datagram to the new datagram as appropriate:
@@ -491,9 +482,7 @@ void QNetworkDatagram::setData(const QByteArray &data)
overloads, so it is a good idea to make sure this object is rvalue, if
possible, before calling makeReply, so as to make better use of move
semantics. To achieve that, the example above would use:
- \code
- udpSocket->writeDatagram(std::move(datagram).makeReply(replyData));
- \endcode
+ \snippet code/src_network_kernel_qnetworkdatagram.cpp 1
*/
diff --git a/src/network/kernel/qnetworkinterface.cpp b/src/network/kernel/qnetworkinterface.cpp
index 75a26848a6..d43dba3e0c 100644
--- a/src/network/kernel/qnetworkinterface.cpp
+++ b/src/network/kernel/qnetworkinterface.cpp
@@ -798,9 +798,7 @@ QList<QNetworkAddressEntry> QNetworkInterface::addressEntries() const
no interface with that name. This function should produce the same result
as the following code, but will probably execute faster.
- \code
- QNetworkInterface::interfaceFromName(name).index()
- \endcode
+ \snippet code/src_network_kernel_qnetworkinterface.cpp 0
\sa interfaceFromName(), interfaceNameFromIndex(), QNetworkDatagram::interfaceIndex()
*/
@@ -858,9 +856,7 @@ QNetworkInterface QNetworkInterface::interfaceFromIndex(int index)
produce the same result as the following code, but will probably execute
faster.
- \code
- QNetworkInterface::interfaceFromIndex(index).name()
- \endcode
+ \snippet code/src_network_kernel_qnetworkinterface.cpp 1
\sa interfaceFromIndex(), interfaceIndexFromName(), QNetworkDatagram::interfaceIndex()
*/
diff --git a/src/network/kernel/qnetworkinterface_win.cpp b/src/network/kernel/qnetworkinterface_win.cpp
index 150553f673..a8d56a9b11 100644
--- a/src/network/kernel/qnetworkinterface_win.cpp
+++ b/src/network/kernel/qnetworkinterface_win.cpp
@@ -74,15 +74,16 @@ static QHostAddress addressFromSockaddr(sockaddr *sa)
if (!sa)
return address;
- if (sa->sa_family == AF_INET)
- address.setAddress(htonl(((sockaddr_in *)sa)->sin_addr.s_addr));
- else if (sa->sa_family == AF_INET6) {
- address.setAddress(((sockaddr_in6 *)sa)->sin6_addr.s6_addr);
- int scope = ((sockaddr_in6 *)sa)->sin6_scope_id;
- if (scope)
- address.setScopeId(QNetworkInterfaceManager::interfaceNameFromIndex(scope));
- } else
+ if (sa->sa_family == AF_INET) {
+ address.setAddress(htonl(reinterpret_cast<const sockaddr_in *>(sa)->sin_addr.s_addr));
+ } else if (sa->sa_family == AF_INET6) {
+ auto sai6 = reinterpret_cast<const sockaddr_in6 *>(sa);
+ address.setAddress(sai6->sin6_addr.s6_addr);
+ if (sai6->sin6_scope_id)
+ address.setScopeId(QNetworkInterfaceManager::interfaceNameFromIndex(sai6->sin6_scope_id));
+ } else {
qWarning("Got unknown socket family %d", sa->sa_family);
+ }
return address;
}
@@ -121,7 +122,7 @@ static QList<QNetworkInterfacePrivate *> interfaceListing()
ULONG retval = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAdapter, &bufSize);
if (retval == ERROR_BUFFER_OVERFLOW) {
// need more memory
- pAdapter = (IP_ADAPTER_ADDRESSES *)malloc(bufSize);
+ pAdapter = reinterpret_cast<IP_ADAPTER_ADDRESSES *>(malloc(bufSize));
if (!pAdapter)
return interfaces;
// try again
@@ -255,7 +256,7 @@ QString QHostInfo::localDomainName()
ULONG bufSize = sizeof info;
pinfo = &info;
if (GetNetworkParams(pinfo, &bufSize) == ERROR_BUFFER_OVERFLOW) {
- pinfo = (FIXED_INFO *)malloc(bufSize);
+ pinfo = reinterpret_cast<FIXED_INFO *>(malloc(bufSize));
if (!pinfo)
return QString();
// try again
diff --git a/src/network/kernel/qnetworkproxy_win.cpp b/src/network/kernel/qnetworkproxy_win.cpp
index 949f9fe12b..db51732bd3 100644
--- a/src/network/kernel/qnetworkproxy_win.cpp
+++ b/src/network/kernel/qnetworkproxy_win.cpp
@@ -370,7 +370,10 @@ static QList<QNetworkProxy> parseServerList(const QNetworkProxyQuery &query, con
#if !defined(Q_OS_WINRT)
namespace {
class QRegistryWatcher {
+ Q_DISABLE_COPY(QRegistryWatcher)
public:
+ QRegistryWatcher() = default;
+
void addLocation(HKEY hive, const QString& path)
{
HKEY openedKey;
@@ -422,6 +425,7 @@ private:
class QWindowsSystemProxy
{
+ Q_DISABLE_COPY(QWindowsSystemProxy)
public:
QWindowsSystemProxy();
~QWindowsSystemProxy();
@@ -566,7 +570,7 @@ void QWindowsSystemProxy::init()
WINHTTP_AUTO_DETECT_TYPE_DNS_A;
} else {
autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
- autoProxyOptions.lpszAutoConfigUrl = (LPCWSTR)autoConfigUrl.utf16();
+ autoProxyOptions.lpszAutoConfigUrl = reinterpret_cast<LPCWSTR>(autoConfigUrl.utf16());
}
}
@@ -608,7 +612,7 @@ QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkPro
}
bool getProxySucceeded = ptrWinHttpGetProxyForUrl(sp->hHttpSession,
- (LPCWSTR)urlQueryString.utf16(),
+ reinterpret_cast<LPCWSTR>(urlQueryString.utf16()),
&sp->autoProxyOptions,
&proxyInfo);
DWORD getProxyError = GetLastError();
@@ -623,9 +627,10 @@ QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkPro
} else {
//pac file URL is specified as well, try using that
sp->autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
- sp->autoProxyOptions.lpszAutoConfigUrl = (LPCWSTR)sp->autoConfigUrl.utf16();
+ sp->autoProxyOptions.lpszAutoConfigUrl =
+ reinterpret_cast<LPCWSTR>(sp->autoConfigUrl.utf16());
getProxySucceeded = ptrWinHttpGetProxyForUrl(sp->hHttpSession,
- (LPCWSTR)urlQueryString.utf16(),
+ reinterpret_cast<LPCWSTR>(urlQueryString.utf16()),
&sp->autoProxyOptions,
&proxyInfo);
getProxyError = GetLastError();
@@ -638,7 +643,7 @@ QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkPro
// But now we've to enable it (http://msdn.microsoft.com/en-us/library/aa383153%28v=VS.85%29.aspx)
sp->autoProxyOptions.fAutoLogonIfChallenged = TRUE;
getProxySucceeded = ptrWinHttpGetProxyForUrl(sp->hHttpSession,
- (LPCWSTR)urlQueryString.utf16(),
+ reinterpret_cast<LPCWSTR>(urlQueryString.utf16()),
&sp->autoProxyOptions,
&proxyInfo);
getProxyError = GetLastError();
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index 13e10e4102..4d9fda00ce 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -1609,7 +1609,10 @@ bool QAbstractSocketPrivate::bind(const QHostAddress &address, quint16 port, QAb
localPort = socketEngine->localPort();
emit q->stateChanged(state);
- if (socketType == QAbstractSocket::UdpSocket)
+ // A slot attached to stateChanged() signal can break our invariant:
+ // by closing the socket it will reset its socket engine - thus we
+ // have additional check (isValid()) ...
+ if (q->isValid() && socketType == QAbstractSocket::UdpSocket)
socketEngine->setReadNotificationEnabled(true);
return true;
}
diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp
index b543ea7981..9427c3b00d 100644
--- a/src/network/socket/qhttpsocketengine.cpp
+++ b/src/network/socket/qhttpsocketengine.cpp
@@ -627,10 +627,9 @@ void QHttpSocketEngine::slotSocketReadNotification()
// from http spec is also allowed.
if (proxyConnectionHeader.isEmpty())
proxyConnectionHeader = d->reply->headerField("Connection");
- proxyConnectionHeader = proxyConnectionHeader.toLower();
- if (proxyConnectionHeader == "close") {
+ if (proxyConnectionHeader.compare("close", Qt::CaseSensitive) == 0) {
willClose = true;
- } else if (proxyConnectionHeader == "keep-alive") {
+ } else if (proxyConnectionHeader.compare("keep-alive", Qt::CaseInsensitive) == 0) {
willClose = false;
} else {
// no Proxy-Connection header, so use the default
diff --git a/src/network/socket/qlocalserver_win.cpp b/src/network/socket/qlocalserver_win.cpp
index ced923ced1..2d71a7e730 100644
--- a/src/network/socket/qlocalserver_win.cpp
+++ b/src/network/socket/qlocalserver_win.cpp
@@ -89,7 +89,7 @@ bool QLocalServerPrivate::addListener()
DWORD dwBufferSize = 0;
GetTokenInformation(hToken, TokenUser, 0, 0, &dwBufferSize);
tokenUserBuffer.fill(0, dwBufferSize);
- PTOKEN_USER pTokenUser = (PTOKEN_USER)tokenUserBuffer.data();
+ auto pTokenUser = reinterpret_cast<PTOKEN_USER>(tokenUserBuffer.data());
if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwBufferSize, &dwBufferSize)) {
setError(QLatin1String("QLocalServerPrivate::addListener"));
CloseHandle(hToken);
@@ -99,7 +99,7 @@ bool QLocalServerPrivate::addListener()
dwBufferSize = 0;
GetTokenInformation(hToken, TokenPrimaryGroup, 0, 0, &dwBufferSize);
tokenGroupBuffer.fill(0, dwBufferSize);
- PTOKEN_PRIMARY_GROUP pTokenGroup = (PTOKEN_PRIMARY_GROUP)tokenGroupBuffer.data();
+ auto pTokenGroup = reinterpret_cast<PTOKEN_PRIMARY_GROUP>(tokenGroupBuffer.data());
if (!GetTokenInformation(hToken, TokenPrimaryGroup, pTokenGroup, dwBufferSize, &dwBufferSize)) {
setError(QLatin1String("QLocalServerPrivate::addListener"));
CloseHandle(hToken);
@@ -140,7 +140,7 @@ bool QLocalServerPrivate::addListener()
aclSize = (aclSize + (sizeof(DWORD) - 1)) & 0xfffffffc;
aclBuffer.fill(0, aclSize);
- PACL acl = (PACL)aclBuffer.data();
+ auto acl = reinterpret_cast<PACL>(aclBuffer.data());
InitializeAcl(acl, aclSize, ACL_REVISION_DS);
if (socketOptions & QLocalServer::UserAccessOption) {
@@ -176,7 +176,7 @@ bool QLocalServerPrivate::addListener()
}
listener.handle = CreateNamedPipe(
- (const wchar_t *)fullServerName.utf16(), // pipe name
+ reinterpret_cast<const wchar_t *>(fullServerName.utf16()), // pipe name
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
PIPE_TYPE_BYTE | // byte type pipe
PIPE_READMODE_BYTE | // byte-read mode
@@ -299,7 +299,7 @@ void QLocalServerPrivate::_q_onNewConnection()
tryAgain = true;
// Make this the last thing so connected slots can wreak the least havoc
- q->incomingConnection((quintptr)handle);
+ q->incomingConnection(reinterpret_cast<quintptr>(handle));
} else {
if (GetLastError() != ERROR_IO_INCOMPLETE) {
q->close();
diff --git a/src/network/socket/qlocalsocket.cpp b/src/network/socket/qlocalsocket.cpp
index 6fec2fdbd2..1c34cd13ee 100644
--- a/src/network/socket/qlocalsocket.cpp
+++ b/src/network/socket/qlocalsocket.cpp
@@ -368,7 +368,7 @@ QLocalSocket::QLocalSocket(QObject * parent)
*/
QLocalSocket::~QLocalSocket()
{
- close();
+ QLocalSocket::close();
#if !defined(Q_OS_WIN) && !defined(QT_LOCALSOCKET_TCP)
Q_D(QLocalSocket);
d->unixSocket.setParent(0);
diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp
index ae94cb9d51..8e20f9efbe 100644
--- a/src/network/socket/qlocalsocket_win.cpp
+++ b/src/network/socket/qlocalsocket_win.cpp
@@ -155,7 +155,7 @@ void QLocalSocket::connectToServer(OpenMode openMode)
forever {
DWORD permissions = (openMode & QIODevice::ReadOnly) ? GENERIC_READ : 0;
permissions |= (openMode & QIODevice::WriteOnly) ? GENERIC_WRITE : 0;
- localSocket = CreateFile((const wchar_t *)d->fullServerName.utf16(), // pipe name
+ localSocket = CreateFile(reinterpret_cast<const wchar_t *>(d->fullServerName.utf16()), // pipe name
permissions,
0, // no sharing
NULL, // default security attributes
@@ -183,7 +183,7 @@ void QLocalSocket::connectToServer(OpenMode openMode)
}
// we have a valid handle
- if (setSocketDescriptor((qintptr)localSocket, ConnectedState, openMode))
+ if (setSocketDescriptor(reinterpret_cast<qintptr>(localSocket), ConnectedState, openMode))
emit connected();
}
@@ -371,7 +371,7 @@ void QLocalSocketPrivate::_q_canWrite()
qintptr QLocalSocket::socketDescriptor() const
{
Q_D(const QLocalSocket);
- return (qintptr)d->handle;
+ return reinterpret_cast<qintptr>(d->handle);
}
qint64 QLocalSocket::readBufferSize() const
diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp
index 1b84b26d83..c999bd2088 100644
--- a/src/network/socket/qnativesocketengine_win.cpp
+++ b/src/network/socket/qnativesocketengine_win.cpp
@@ -294,7 +294,8 @@ static inline QAbstractSocket::SocketType qt_socket_getType(qintptr socketDescri
{
int value = 0;
QT_SOCKLEN_T valueSize = sizeof(value);
- if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_TYPE, (char *) &value, &valueSize) != 0) {
+ if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_TYPE,
+ reinterpret_cast<char *>(&value), &valueSize) != 0) {
WS_ERROR_DEBUG(WSAGetLastError());
} else {
if (value == SOCK_STREAM)
@@ -361,7 +362,7 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc
#ifdef HANDLE_FLAG_INHERIT
if (socket != INVALID_SOCKET) {
// make non inheritable the old way
- BOOL handleFlags = SetHandleInformation((HANDLE)socket, HANDLE_FLAG_INHERIT, 0);
+ BOOL handleFlags = SetHandleInformation(reinterpret_cast<HANDLE>(socket), HANDLE_FLAG_INHERIT, 0);
#ifdef QNATIVESOCKETENGINE_DEBUG
qDebug() << "QNativeSocketEnginePrivate::createNewSocket - set inheritable" << handleFlags;
#else
@@ -1443,7 +1444,7 @@ qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len)
for (;;) {
WSABUF buf;
- buf.buf = (char*)data + ret;
+ buf.buf = const_cast<char*>(data) + ret;
buf.len = bytesToSend;
DWORD flags = 0;
DWORD bytesWritten = 0;
diff --git a/src/network/ssl/qasn1element_p.h b/src/network/ssl/qasn1element_p.h
index 2c5019b4f7..2068254a95 100644
--- a/src/network/ssl/qasn1element_p.h
+++ b/src/network/ssl/qasn1element_p.h
@@ -58,10 +58,62 @@
QT_BEGIN_NAMESPACE
-#define RSA_ENCRYPTION_OID QByteArrayLiteral("1.2.840.113549.1.1.1")
+// General
+#define RSADSI_OID "1.2.840.113549."
+
+#define RSA_ENCRYPTION_OID QByteArrayLiteral(RSADSI_OID "1.1.1")
#define DSA_ENCRYPTION_OID QByteArrayLiteral("1.2.840.10040.4.1")
#define EC_ENCRYPTION_OID QByteArrayLiteral("1.2.840.10045.2.1")
+// These are mostly from the RFC for PKCS#5
+// PKCS#5: https://tools.ietf.org/html/rfc8018#appendix-B
+#define PKCS5_OID RSADSI_OID "1.5."
+// PKCS#12: https://tools.ietf.org/html/rfc7292#appendix-D)
+#define PKCS12_OID RSADSI_OID "1.12."
+
+// -PBES1
+#define PKCS5_MD2_DES_CBC_OID QByteArrayLiteral(PKCS5_OID "1") // Not (yet) implemented
+#define PKCS5_MD2_RC2_CBC_OID QByteArrayLiteral(PKCS5_OID "4") // Not (yet) implemented
+#define PKCS5_MD5_DES_CBC_OID QByteArrayLiteral(PKCS5_OID "3")
+#define PKCS5_MD5_RC2_CBC_OID QByteArrayLiteral(PKCS5_OID "6")
+#define PKCS5_SHA1_DES_CBC_OID QByteArrayLiteral(PKCS5_OID "10")
+#define PKCS5_SHA1_RC2_CBC_OID QByteArrayLiteral(PKCS5_OID "11")
+#define PKCS12_SHA1_RC4_128_OID QByteArrayLiteral(PKCS12_OID "1.1") // Not (yet) implemented
+#define PKCS12_SHA1_RC4_40_OID QByteArrayLiteral(PKCS12_OID "1.2") // Not (yet) implemented
+#define PKCS12_SHA1_3KEY_3DES_CBC_OID QByteArrayLiteral(PKCS12_OID "1.3")
+#define PKCS12_SHA1_2KEY_3DES_CBC_OID QByteArrayLiteral(PKCS12_OID "1.4")
+#define PKCS12_SHA1_RC2_128_CBC_OID QByteArrayLiteral(PKCS12_OID "1.5")
+#define PKCS12_SHA1_RC2_40_CBC_OID QByteArrayLiteral(PKCS12_OID "1.6")
+
+// -PBKDF2
+#define PKCS5_PBKDF2_ENCRYPTION_OID QByteArrayLiteral(PKCS5_OID "12")
+
+// -PBES2
+#define PKCS5_PBES2_ENCRYPTION_OID QByteArrayLiteral(PKCS5_OID "13")
+
+// Digest
+#define DIGEST_ALGORITHM_OID RSADSI_OID "2."
+// -HMAC-SHA-1
+#define HMAC_WITH_SHA1 QByteArrayLiteral(DIGEST_ALGORITHM_OID "7")
+// -HMAC-SHA-2
+#define HMAC_WITH_SHA224 QByteArrayLiteral(DIGEST_ALGORITHM_OID "8")
+#define HMAC_WITH_SHA256 QByteArrayLiteral(DIGEST_ALGORITHM_OID "9")
+#define HMAC_WITH_SHA384 QByteArrayLiteral(DIGEST_ALGORITHM_OID "10")
+#define HMAC_WITH_SHA512 QByteArrayLiteral(DIGEST_ALGORITHM_OID "11")
+#define HMAC_WITH_SHA512_224 QByteArrayLiteral(DIGEST_ALGORITHM_OID "12")
+#define HMAC_WITH_SHA512_256 QByteArrayLiteral(DIGEST_ALGORITHM_OID "13")
+
+// Encryption algorithms
+#define ENCRYPTION_ALGORITHM_OID RSADSI_OID "3."
+#define DES_CBC_ENCRYPTION_OID QByteArrayLiteral("1.3.14.3.2.7")
+#define DES_EDE3_CBC_ENCRYPTION_OID QByteArrayLiteral(ENCRYPTION_ALGORITHM_OID "7")
+#define RC2_CBC_ENCRYPTION_OID QByteArrayLiteral(ENCRYPTION_ALGORITHM_OID "2")
+#define RC5_CBC_ENCRYPTION_OID QByteArrayLiteral(ENCRYPTION_ALGORITHM_OID "9") // Not (yet) implemented
+#define AES_OID "2.16.840.1.101.3.4.1."
+#define AES128_CBC_ENCRYPTION_OID QByteArrayLiteral(AES_OID "2")
+#define AES192_CBC_ENCRYPTION_OID QByteArrayLiteral(AES_OID "22") // Not (yet) implemented
+#define AES256_CBC_ENCRYPTION_OID QByteArrayLiteral(AES_OID "42") // Not (yet) implemented
+
class Q_AUTOTEST_EXPORT QAsn1Element
{
public:
diff --git a/src/network/ssl/qdtls.cpp b/src/network/ssl/qdtls.cpp
new file mode 100644
index 0000000000..bbb22aa527
--- /dev/null
+++ b/src/network/ssl/qdtls.cpp
@@ -0,0 +1,1163 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 "qsslconfiguration.h"
+#include "qdtls_openssl_p.h"
+#include "qudpsocket.h"
+#include "qdtls_p.h"
+#include "qssl_p.h"
+#include "qdtls.h"
+
+#include "qglobal.h"
+
+/*!
+ \class QDtlsClientVerifier
+ \brief This class implements server-side DTLS cookie generation and verification.
+ \since 5.12
+
+ \ingroup network
+ \ingroup ssl
+ \inmodule QtNetwork
+
+ The QDtlsClientVerifier class implements server-side DTLS cookie generation
+ and verification. Datagram security protocols are highly susceptible to a
+ variety of Denial-of-Service attacks. According to \l {https://tools.ietf.org/html/rfc6347#section-4.2.1}{RFC 6347, section 4.2.1},
+ these are two of the more common types of attack:
+
+ \list
+ \li An attacker transmits a series of handshake initiation requests, causing
+ a server to allocate excessive resources and potentially perform expensive
+ cryptographic operations.
+ \li An attacker transmits a series of handshake initiation requests with
+ a forged source of the victim, making the server act as an amplifier.
+ Normally, the server would reply to the victim machine with a Certificate message,
+ which can be quite large, thus flooding the victim machine with datagrams.
+ \endlist
+
+ As a countermeasure to these attacks, \l {https://tools.ietf.org/html/rfc6347#section-4.2.1}{RFC 6347, section 4.2.1}
+ proposes a stateless cookie technique that a server may deploy:
+
+ \list
+ \li In response to the initial ClientHello message, the server sends a HelloVerifyRequest,
+ which contains a cookie. This cookie is a cryptographic hash and is generated using the
+ client's address, port number, and the server's secret (which is a cryptographically strong
+ pseudo-random sequence of bytes).
+ \li A reachable DTLS client is expected to reply with a new ClientHello message
+ containing this cookie.
+ \li When the server receives the ClientHello message with a cookie, it
+ generates a new cookie as described above. This new cookie is compared to the
+ one found in the ClientHello message.
+ \li In the cookies are equal, the client is considered to be real, and the
+ server can continue with a TLS handshake procedure.
+ \endlist
+
+ \note A DTLS server is not required to use DTLS cookies.
+
+ QDtlsClientVerifier is designed to work in pair with QUdpSocket, as shown in
+ the following code-excerpt:
+
+ \snippet code/src_network_ssl_qdtlscookie.cpp 0
+
+ QDtlsClientVerifier does not impose any restrictions on how the application uses
+ QUdpSocket. For example, it is possible to have a server with a single QUdpSocket
+ in state QAbstractSocket::BoundState, handling multiple DTLS clients
+ simultaneously:
+
+ \list
+ \li Testing if new clients are real DTLS-capable clients.
+ \li Completing TLS handshakes with the verified clients (see QDtls).
+ \li Decrypting datagrams coming from the connected clients (see QDtls).
+ \li Sending encrypted datagrams to the connected clients (see QDtls).
+ \endlist
+
+ This implies that QDtlsClientVerifier does not read directly from a socket,
+ instead it expects the application to read an incoming datagram, extract the
+ sender's address, and port, and then pass this data to verifyClient().
+ To send a HelloVerifyRequest message, verifyClient() can write to the QUdpSocket.
+
+ \note QDtlsClientVerifier does not take ownership of the QUdpSocket object.
+
+ By default QDtlsClientVerifier obtains its secret from a cryptographically
+ strong pseudorandom number generator.
+
+ \note The default secret is shared by all objects of the classes QDtlsClientVerifier
+ and QDtls. Since this can impose security risks, RFC 6347 recommends to change
+ the server's secret frequently. Please see \l {https://tools.ietf.org/html/rfc6347}{RFC 6347, section 4.2.1}
+ for hints about possible server implementations. Cookie generator parameters
+ can be set using the class QDtlsClientVerifier::GeneratorParameters and
+ setCookieGeneratorParameters():
+
+ \snippet code/src_network_ssl_qdtlscookie.cpp 1
+
+ The \l{secureudpserver}{DTLS server} example illustrates how to use
+ QDtlsClientVerifier in a server application.
+
+ \sa QUdpSocket, QAbstractSocket::BoundState, QDtls, verifyClient(),
+ GeneratorParameters, setCookieGeneratorParameters(), cookieGeneratorParameters(),
+ QDtls::setCookieGeneratorParameters(),
+ QDtls::cookieGeneratorParameters(),
+ QCryptographicHash::Algorithm,
+ QDtlsError, dtlsError(), dtlsErrorString()
+*/
+
+/*!
+ \class QDtlsClientVerifier::GeneratorParameters
+ \brief This class defines parameters for DTLS cookie generator.
+ \since 5.12
+
+ \ingroup network
+ \ingroup ssl
+ \inmodule QtNetwork
+
+ An object of this class provides the parameters that QDtlsClientVerifier
+ will use to generate DTLS cookies. They include a cryptographic hash
+ algorithm and a secret.
+
+ \note An empty secret is considered to be invalid by
+ QDtlsClientVerifier::setCookieGeneratorParameters().
+
+ \sa QDtlsClientVerifier::setCookieGeneratorParameters(),
+ QDtlsClientVerifier::cookieGeneratorParameters(),
+ QDtls::setCookieGeneratorParameters(),
+ QDtls::cookieGeneratorParameters(),
+ QCryptographicHash::Algorithm
+*/
+
+/*!
+ \enum QDtlsError
+ \brief Describes errors that can be found by QDtls and QDtlsClientVerifier.
+ \relates QDtls
+ \since 5.12
+
+ \ingroup network
+ \ingroup ssl
+ \inmodule QtNetwork
+
+ This enum describes general and TLS-specific errors that can be encountered
+ by objects of the classes QDtlsClientVerifier and QDtls.
+
+ \value NoError No error occurred, the last operation was successful.
+ \value InvalidInputParameters Input parameters provided by a caller were
+ invalid.
+ \value InvalidOperation An operation was attempted in a state that did not
+ permit it.
+ \value UnderlyingSocketError QUdpSocket::writeDatagram() failed, QUdpSocket::error()
+ and QUdpSocket::errorString() can provide more specific information.
+ \value RemoteClosedConnectionError TLS shutdown alert message was received.
+ \value PeerVerificationError Peer's identity could not be verified during the
+ TLS handshake.
+ \value TlsInitializationError An error occurred while initializing an underlying
+ TLS backend.
+ \value TlsFatalError A fatal error occurred during TLS handshake, other
+ than peer verification error or TLS initialization error.
+ \value TlsNonFatalError A failure to encrypt or decrypt a datagram, non-fatal,
+ meaning QDtls can continue working after this error.
+*/
+
+/*!
+ \class QDtls
+ \brief This class provides encryption for UDP sockets.
+ \since 5.12
+
+ \ingroup network
+ \ingroup ssl
+ \inmodule QtNetwork
+
+ The QDtls class can be used to establish a secure connection with a network
+ peer using User Datagram Protocol (UDP). DTLS connection over essentially
+ connectionless UDP means that two peers first have to successfully complete
+ a TLS handshake by calling doHandshake(). After the handshake has completed,
+ encrypted datagrams can be sent to the peer using writeDatagramEncrypted().
+ Encrypted datagrams coming from the peer can be decrypted by decryptDatagram().
+
+ QDtls is designed to work with QUdpSocket. Since QUdpSocket can receive
+ datagrams coming from different peers, an application must implement
+ demultiplexing, forwarding datagrams coming from different peers to their
+ corresponding instances of QDtls. An association between a network peer
+ and its QDtls object can be established using the peer's address and port
+ number. Before starting a handshake, the application must set the peer's
+ address and port number using setPeer().
+
+ QDtls does not read datagrams from QUdpSocket, this is expected to be done by
+ the application, for example, in a slot attached to the QUdpSocket::readyRead()
+ signal. Then, these datagrams must be processed by QDtls.
+
+ \note QDtls does \e not take ownership of the QUdpSocket object.
+
+ Normally, several datagrams are to be received and sent by both peers during
+ the handshake phase. Upon reading datagrams, server and client must pass these
+ datagrams to doHandshake() until some error is found or handshakeState()
+ returns HandshakeComplete:
+
+ \snippet code/src_network_ssl_qdtls.cpp 0
+
+ For a server, the first call to doHandshake() requires a non-empty datagram
+ containing a ClientHello message. If the server also deploys QDtlsClientVerifier,
+ the first ClientHello message is expected to be the one verified by QDtlsClientVerifier.
+
+ In case the peer's identity cannot be validated during the handshake, the application
+ must inspect errors returned by peerVerificationErrors() and then either
+ ignore errors by calling ignoreVerificationErrors() or abort the handshake
+ by calling abortHandshake(). If errors were ignored, the handshake can be
+ resumed by calling resumeHandshake().
+
+ After the handshake has been completed, datagrams can be sent to and received
+ from the network peer securely:
+
+ \snippet code/src_network_ssl_qdtls.cpp 2
+
+ A DTLS connection may be closed using shutdown().
+
+ \snippet code/src_network_ssl_qdtls.cpp 3
+
+ \warning It's recommended to call shutdown() before destroying the client's QDtls
+ object if you are planning to re-use the same port number to connect to the
+ server later. Otherwise, the server may drop incoming ClientHello messages,
+ see \l{https://tools.ietf.org/html/rfc6347#page-25}{RFC 6347, section 4.2.8}
+ for more details and implementation hints.
+
+ If the server does not use QDtlsClientVerifier, it \e must configure its
+ QDtls objects to disable the cookie verification procedure:
+
+ \snippet code/src_network_ssl_qdtls.cpp 4
+
+ A server that uses cookie verification with non-default generator parameters
+ \e must set the same parameters for its QDtls object before starting the handshake.
+
+ \note The DTLS protocol leaves Path Maximum Transmission Unit (PMTU) discovery
+ to the application. The application may provide QDtls with the MTU using
+ setMtuHint(). This hint affects only the handshake phase, since only handshake
+ messages can be fragmented and reassembled by the DTLS. All other messages sent
+ by the application must fit into a single datagram.
+ \note DTLS-specific headers add some overhead to application data further
+ reducing the possible message size.
+ \warning A server configured to reply with HelloVerifyRequest will drop
+ all fragmented ClientHello messages, never starting a handshake.
+
+ The \l{secureudpserver}{DTLS server} and \l{secureudpclient}{DTLS client}
+ examples illustrate how to use QDtls in applications.
+
+ \sa QUdpSocket, QDtlsClientVerifier, HandshakeState, QDtlsError, QSslConfiguration
+*/
+
+/*!
+ \typedef QDtls::GeneratorParameters
+
+ This is a synonym for QDtlsClientVerifier::GeneratorParameters.
+*/
+
+/*!
+ \fn void QDtls::handshakeTimeout()
+
+ Packet loss can result in timeouts during the handshake phase. In this case
+ QDtls emits a handshakeTimeout() signal. Call handleTimeout() to retransmit
+ the handshake messages:
+
+ \snippet code/src_network_ssl_qdtls.cpp 1
+
+ \sa handleTimeout()
+*/
+
+/*!
+ \fn void QDtls::pskRequired(QSslPreSharedKeyAuthenticator *authenticator)
+
+ QDtls emits this signal when it negotiates a PSK ciphersuite, and therefore
+ a PSK authentication is then required.
+
+ When using PSK, the client must send to the server a valid identity and a
+ valid pre shared key, in order for the TLS handshake to continue.
+ Applications can provide this information in a slot connected to this
+ signal, by filling in the passed \a authenticator object according to their
+ needs.
+
+ \note Ignoring this signal, or failing to provide the required credentials,
+ will cause the handshake to fail, and therefore the connection to be aborted.
+
+ \note The \a authenticator object is owned by QDtls and must not be deleted
+ by the application.
+
+ \sa QSslPreSharedKeyAuthenticator
+*/
+
+/*!
+ \enum QDtls::HandshakeState
+ \brief Describes the current state of DTLS handshake.
+ \since 5.12
+
+ \ingroup network
+ \ingroup ssl
+ \inmodule QtNetwork
+
+ This enum describes the current state of DTLS handshake for a QDtls
+ connection.
+
+ \value HandshakeNotStarted Nothing done yet.
+ \value HandshakeInProgress Handshake was initiated and no errors were found so far.
+ \value PeerVerificationFailed The identity of the peer can't be established.
+ \value HandshakeComplete Handshake completed successfully and encrypted connection
+ was established.
+
+ \sa QDtls::doHandshake(), QDtls::handshakeState()
+*/
+
+
+QT_BEGIN_NAMESPACE
+
+QSslConfiguration QDtlsBasePrivate::configuration() const
+{
+ auto copyPrivate = new QSslConfigurationPrivate(dtlsConfiguration);
+ copyPrivate->ref.store(0); // the QSslConfiguration constructor refs up
+ QSslConfiguration copy(copyPrivate);
+ copyPrivate->sessionCipher = sessionCipher;
+ copyPrivate->sessionProtocol = sessionProtocol;
+
+ return copy;
+}
+
+void QDtlsBasePrivate::setConfiguration(const QSslConfiguration &configuration)
+{
+ dtlsConfiguration.localCertificateChain = configuration.localCertificateChain();
+ dtlsConfiguration.privateKey = configuration.privateKey();
+ dtlsConfiguration.ciphers = configuration.ciphers();
+ dtlsConfiguration.ellipticCurves = configuration.ellipticCurves();
+ dtlsConfiguration.preSharedKeyIdentityHint = configuration.preSharedKeyIdentityHint();
+ dtlsConfiguration.dhParams = configuration.diffieHellmanParameters();
+ dtlsConfiguration.caCertificates = configuration.caCertificates();
+ dtlsConfiguration.peerVerifyDepth = configuration.peerVerifyDepth();
+ dtlsConfiguration.peerVerifyMode = configuration.peerVerifyMode();
+ dtlsConfiguration.protocol = configuration.protocol();
+ dtlsConfiguration.sslOptions = configuration.d->sslOptions;
+ dtlsConfiguration.sslSession = configuration.sessionTicket();
+ dtlsConfiguration.sslSessionTicketLifeTimeHint = configuration.sessionTicketLifeTimeHint();
+ dtlsConfiguration.nextAllowedProtocols = configuration.allowedNextProtocols();
+ dtlsConfiguration.nextNegotiatedProtocol = configuration.nextNegotiatedProtocol();
+ dtlsConfiguration.nextProtocolNegotiationStatus = configuration.nextProtocolNegotiationStatus();
+ dtlsConfiguration.dtlsCookieEnabled = configuration.dtlsCookieVerificationEnabled();
+ dtlsConfiguration.allowRootCertOnDemandLoading = configuration.d->allowRootCertOnDemandLoading;
+
+ clearDtlsError();
+}
+
+bool QDtlsBasePrivate::setCookieGeneratorParameters(QCryptographicHash::Algorithm alg,
+ const QByteArray &key)
+{
+ if (!key.size()) {
+ setDtlsError(QDtlsError::InvalidInputParameters,
+ QDtls::tr("Invalid (empty) secret"));
+ return false;
+ }
+
+ clearDtlsError();
+
+ hashAlgorithm = alg;
+ secret = key;
+
+ return true;
+}
+
+bool QDtlsBasePrivate::isDtlsProtocol(QSsl::SslProtocol protocol)
+{
+ switch (protocol) {
+ case QSsl::DtlsV1_0:
+ case QSsl::DtlsV1_0OrLater:
+ case QSsl::DtlsV1_2:
+ case QSsl::DtlsV1_2OrLater:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static QString msgUnsupportedMulticastAddress()
+{
+ return QDtls::tr("Multicast and broadcast addresses are not supported");
+}
+
+/*!
+ Default constructs GeneratorParameters object with QCryptographicHash::Sha1
+ as its algorithm and an empty secret.
+
+ \sa QDtlsClientVerifier::setCookieGeneratorParameters(),
+ QDtlsClientVerifier::cookieGeneratorParameters(),
+ QDtls::setCookieGeneratorParameters(),
+ QDtls::cookieGeneratorParameters()
+ */
+QDtlsClientVerifier::GeneratorParameters::GeneratorParameters()
+{
+}
+
+/*!
+ Constructs GeneratorParameters object from \a algorithm and \a secret.
+
+ \sa QDtlsClientVerifier::setCookieGeneratorParameters(),
+ QDtlsClientVerifier::cookieGeneratorParameters(),
+ QDtls::setCookieGeneratorParameters(),
+ QDtls::cookieGeneratorParameters()
+ */
+QDtlsClientVerifier::GeneratorParameters::GeneratorParameters(QCryptographicHash::Algorithm algorithm, const QByteArray &secret)
+ : hash(algorithm), secret(secret)
+{
+}
+
+/*!
+ Constructs a QDtlsClientVerifier object, \a parent is passed to QObject's
+ constructor.
+*/
+QDtlsClientVerifier::QDtlsClientVerifier(QObject *parent)
+ : QObject(*new QDtlsClientVerifierOpenSSL, parent)
+{
+ Q_D(QDtlsClientVerifier);
+
+ d->mode = QSslSocket::SslServerMode;
+ // The default configuration suffices: verifier never does a full
+ // handshake and upon verifying a cookie in a client hello message,
+ // it reports success.
+ auto conf = QSslConfiguration::defaultDtlsConfiguration();
+ conf.setPeerVerifyMode(QSslSocket::VerifyNone);
+ d->setConfiguration(conf);
+}
+
+/*!
+ Destroys the QDtlsClientVerifier object.
+*/
+QDtlsClientVerifier::~QDtlsClientVerifier()
+{
+}
+
+/*!
+ Sets the secret and the cryptographic hash algorithm from \a params. This
+ QDtlsClientVerifier will use these to generate cookies. If the new secret
+ has size zero, this function returns \c false and does not change the
+ cookie generator parameters.
+
+ \note The secret is supposed to be a cryptographically secure sequence of bytes.
+
+ \sa QDtlsClientVerifier::GeneratorParameters, cookieGeneratorParameters(),
+ QCryptographicHash::Algorithm
+*/
+bool QDtlsClientVerifier::setCookieGeneratorParameters(const GeneratorParameters &params)
+{
+ Q_D(QDtlsClientVerifier);
+
+ return d->setCookieGeneratorParameters(params.hash, params.secret);
+}
+
+/*!
+ Returns the current secret and hash algorithm used to generate cookies.
+ The default hash algorithm is QCryptographicHash::Sha256 if Qt was configured
+ to support it, QCryptographicHash::Sha1 otherwise. The default secret is
+ obtained from the backend-specific cryptographically strong pseudorandom
+ number generator.
+
+ \sa QCryptographicHash::Algorithm, QDtlsClientVerifier::GeneratorParameters,
+ setCookieGeneratorParameters()
+*/
+QDtlsClientVerifier::GeneratorParameters QDtlsClientVerifier::cookieGeneratorParameters() const
+{
+ Q_D(const QDtlsClientVerifier);
+
+ return {d->hashAlgorithm, d->secret};
+}
+
+/*!
+ \a socket must be a valid pointer, \a dgram must be a non-empty
+ datagram, \a address cannot be null, broadcast, or multicast.
+ \a port is the remote peer's port. This function returns \c true
+ if \a dgram contains a ClientHello message with a valid cookie.
+ If no matching cookie is found, verifyClient() will send a
+ HelloVerifyRequest message using \a socket and return \c false.
+
+ The following snippet shows how a server application may check for errors:
+
+ \snippet code/src_network_ssl_qdtlscookie.cpp 2
+
+ \sa QHostAddress::isNull(), QHostAddress::isBroadcast(), QHostAddress::isMulticast(),
+ setCookieGeneratorParameters(), cookieGeneratorParameters()
+*/
+bool QDtlsClientVerifier::verifyClient(QUdpSocket *socket, const QByteArray &dgram,
+ const QHostAddress &address, quint16 port)
+{
+ Q_D(QDtlsClientVerifier);
+
+ if (!socket || address.isNull() || !dgram.size()) {
+ d->setDtlsError(QDtlsError::InvalidInputParameters,
+ tr("A valid UDP socket, non-empty datagram, valid address/port were expected"));
+ return false;
+ }
+
+ if (address.isBroadcast() || address.isMulticast()) {
+ d->setDtlsError(QDtlsError::InvalidInputParameters,
+ msgUnsupportedMulticastAddress());
+ return false;
+ }
+
+ return d->verifyClient(socket, dgram, address, port);
+}
+
+/*!
+ Convenience function. Returns the last ClientHello message that was successfully
+ verified, or an empty QByteArray if no verification has completed.
+
+ \sa verifyClient()
+*/
+QByteArray QDtlsClientVerifier::verifiedHello() const
+{
+ Q_D(const QDtlsClientVerifier);
+
+ return d->verifiedClientHello;
+}
+
+/*!
+ Returns the last error that occurred or QDtlsError::NoError.
+
+ \sa QDtlsError, dtlsErrorString()
+*/
+QDtlsError QDtlsClientVerifier::dtlsError() const
+{
+ Q_D(const QDtlsClientVerifier);
+
+ return d->errorCode;
+}
+
+/*!
+ Returns a textual description of the last error, or an empty string.
+
+ \sa dtlsError()
+ */
+QString QDtlsClientVerifier::dtlsErrorString() const
+{
+ Q_D(const QDtlsBase);
+
+ return d->errorDescription;
+}
+
+/*!
+ Creates a QDtls object, \a parent is passed to the QObject constructor.
+ \a mode is QSslSocket::SslServerMode for a server-side DTLS connection or
+ QSslSocket::SslClientMode for a client.
+
+ \sa sslMode(), QSslSocket::SslMode
+*/
+QDtls::QDtls(QSslSocket::SslMode mode, QObject *parent)
+ : QObject(*new QDtlsPrivateOpenSSL, parent)
+{
+ Q_D(QDtls);
+
+ d->mode = mode;
+ setDtlsConfiguration(QSslConfiguration::defaultDtlsConfiguration());
+}
+
+/*!
+ Destroys the QDtls object.
+*/
+QDtls::~QDtls()
+{
+}
+
+/*!
+ Sets the peer's address, \a port, and host name and returns \c true
+ if successful. \a address must not be null, multicast, or broadcast.
+ \a verificationName is the host name used for the certificate validation.
+
+ \sa peerAddress(), peerPort(), peerVerificationName()
+ */
+bool QDtls::setPeer(const QHostAddress &address, quint16 port,
+ const QString &verificationName)
+{
+ Q_D(QDtls);
+
+ if (d->handshakeState != HandshakeNotStarted) {
+ d->setDtlsError(QDtlsError::InvalidOperation,
+ tr("Cannot set peer after handshake started"));
+ return false;
+ }
+
+ if (address.isNull()) {
+ d->setDtlsError(QDtlsError::InvalidInputParameters,
+ tr("Invalid address"));
+ return false;
+ }
+
+ if (address.isBroadcast() || address.isMulticast()) {
+ d->setDtlsError(QDtlsError::InvalidInputParameters,
+ msgUnsupportedMulticastAddress());
+ return false;
+ }
+
+ d->clearDtlsError();
+
+ d->remoteAddress = address;
+ d->remotePort = port;
+ d->peerVerificationName = verificationName;
+
+ return true;
+}
+
+/*!
+ Sets the host \a name that will be used for the certificate validation
+ and returns \c true if successful.
+
+ \note This function must be called before the handshake starts.
+
+ \sa peerVerificationName(), setPeer()
+*/
+bool QDtls::setPeerVerificationName(const QString &name)
+{
+ Q_D(QDtls);
+
+ if (d->handshakeState != HandshakeNotStarted) {
+ d->setDtlsError(QDtlsError::InvalidOperation,
+ tr("Cannot set verification name after handshake started"));
+ return false;
+ }
+
+ d->clearDtlsError();
+ d->peerVerificationName = name;
+
+ return true;
+}
+
+/*!
+ Returns the peer's address, set by setPeer(), or QHostAddress::Null.
+
+ \sa setPeer()
+*/
+QHostAddress QDtls::peerAddress() const
+{
+ Q_D(const QDtls);
+
+ return d->remoteAddress;
+}
+
+/*!
+ Returns the peer's port number, set by setPeer(), or 0.
+
+ \sa setPeer()
+*/
+quint16 QDtls::peerPort() const
+{
+ Q_D(const QDtlsBase);
+
+ return d->remotePort;
+}
+
+/*!
+ Returns the host name set by setPeer() or setPeerVerificationName().
+ The default value is an empty string.
+
+ \sa setPeerVerificationName(), setPeer()
+*/
+QString QDtls::peerVerificationName() const
+{
+ Q_D(const QDtls);
+
+ return d->peerVerificationName;
+}
+
+/*!
+ Returns QSslSocket::SslServerMode for a server-side connection and
+ QSslSocket::SslClientMode for a client.
+
+ \sa QDtls(), QSslSocket::SslMode
+*/
+QSslSocket::SslMode QDtls::sslMode() const
+{
+ Q_D(const QDtls);
+
+ return d->mode;
+}
+
+/*!
+ \a mtuHint is the maximum transmission unit (MTU), either discovered or guessed
+ by the application. The application is not required to set this value.
+
+ \sa mtuHint(), QAbstractSocket::PathMtuSocketOption
+ */
+void QDtls::setMtuHint(quint16 mtuHint)
+{
+ Q_D(QDtls);
+
+ d->mtuHint = mtuHint;
+}
+
+/*!
+ Returns the value previously set by setMtuHint(). The default value is 0.
+
+ \sa setMtuHint()
+ */
+quint16 QDtls::mtuHint() const
+{
+ Q_D(const QDtls);
+
+ return d->mtuHint;
+}
+
+/*!
+ Sets the cryptographic hash algorithm and the secret from \a params.
+ This function is only needed for a server-side QDtls connection.
+ Returns \c true if successful.
+
+ \note This function must be called before the handshake starts.
+
+ \sa cookieGeneratorParameters(), doHandshake(), QDtlsClientVerifier,
+ QDtlsClientVerifier::cookieGeneratorParameters()
+*/
+bool QDtls::setCookieGeneratorParameters(const GeneratorParameters &params)
+{
+ Q_D(QDtls);
+
+ return d->setCookieGeneratorParameters(params.hash, params.secret);
+}
+
+/*!
+ Returns the current hash algorithm and secret, either default ones or previously
+ set by a call to setCookieGeneratorParameters().
+
+ The default hash algorithm is QCryptographicHash::Sha256 if Qt was
+ configured to support it, QCryptographicHash::Sha1 otherwise. The default
+ secret is obtained from the backend-specific cryptographically strong
+ pseudorandom number generator.
+
+ \sa QDtlsClientVerifier, cookieGeneratorParameters()
+*/
+QDtls::GeneratorParameters QDtls::cookieGeneratorParameters() const
+{
+ Q_D(const QDtls);
+
+ return {d->hashAlgorithm, d->secret};
+}
+
+/*!
+ Sets the connection's TLS configuration from \a configuration
+ and returns \c true if successful.
+
+ \note This function must be called before the handshake starts.
+
+ \sa dtlsConfiguration(), doHandshake()
+*/
+bool QDtls::setDtlsConfiguration(const QSslConfiguration &configuration)
+{
+ Q_D(QDtls);
+
+ if (d->handshakeState != HandshakeNotStarted) {
+ d->setDtlsError(QDtlsError::InvalidOperation,
+ tr("Cannot set configuration after handshake started"));
+ return false;
+ }
+
+ d->setConfiguration(configuration);
+ return true;
+}
+
+/*!
+ Returns either the default DTLS configuration or the configuration set by an
+ earlier call to setDtlsConfiguration().
+
+ \sa setDtlsConfiguration(), QSslConfiguration::defaultDtlsConfiguration()
+*/
+QSslConfiguration QDtls::dtlsConfiguration() const
+{
+ Q_D(const QDtls);
+
+ return d->configuration();
+}
+
+/*!
+ Returns the current handshake state for this QDtls.
+
+ \sa doHandshake(), QDtls::HandshakeState
+ */
+QDtls::HandshakeState QDtls::handshakeState()const
+{
+ Q_D(const QDtls);
+
+ return d->handshakeState;
+}
+
+/*!
+ Starts or continues a DTLS handshake. \a socket must be a valid pointer.
+ When starting a server-side DTLS handshake, \a dgram must contain the initial
+ ClientHello message read from QUdpSocket. This function returns \c true if
+ no error was found. Handshake state can be tested using handshakeState().
+ \c false return means some error occurred, use dtlsError() for more
+ detailed information.
+
+ \note If the identity of the peer can't be established, the error is set to
+ QDtlsError::PeerVerificationError. If you want to ignore verification errors
+ and continue connecting, you must call ignoreVerificationErrors() and then
+ resumeHandshake(). If the errors cannot be ignored, you must call
+ abortHandshake().
+
+ \snippet code/src_network_ssl_qdtls.cpp 5
+
+ \sa handshakeState(), dtlsError(), ignoreVerificationErrors(), resumeHandshake(),
+ abortHandshake()
+*/
+bool QDtls::doHandshake(QUdpSocket *socket, const QByteArray &dgram)
+{
+ Q_D(QDtls);
+
+ if (d->handshakeState == HandshakeNotStarted)
+ return startHandshake(socket, dgram);
+ else if (d->handshakeState == HandshakeInProgress)
+ return continueHandshake(socket, dgram);
+
+ d->setDtlsError(QDtlsError::InvalidOperation,
+ tr("Cannot start/continue handshake, invalid handshake state"));
+ return false;
+}
+
+/*!
+ \internal
+*/
+bool QDtls::startHandshake(QUdpSocket *socket, const QByteArray &datagram)
+{
+ Q_D(QDtls);
+
+ if (!socket) {
+ d->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
+ return false;
+ }
+
+ if (d->remoteAddress.isNull()) {
+ d->setDtlsError(QDtlsError::InvalidOperation,
+ tr("To start a handshake you must set peer's address and port first"));
+ return false;
+ }
+
+ if (sslMode() == QSslSocket::SslServerMode && !datagram.size()) {
+ d->setDtlsError(QDtlsError::InvalidInputParameters,
+ tr("To start a handshake, DTLS server requires non-empty datagram (client hello)"));
+ return false;
+ }
+
+ if (d->handshakeState != HandshakeNotStarted) {
+ d->setDtlsError(QDtlsError::InvalidOperation,
+ tr("Cannot start handshake, already done/in progress"));
+ return false;
+ }
+
+ return d->startHandshake(socket, datagram);
+}
+
+/*!
+ If a timeout occures during the handshake, the handshakeTimeout() signal
+ is emitted. The application must call handleTimeout() to retransmit handshake
+ messages; handleTimeout() returns \c true if a timeout has occurred, false
+ otherwise. \a socket must be a valid pointer.
+
+ \sa handshakeTimeout()
+*/
+bool QDtls::handleTimeout(QUdpSocket *socket)
+{
+ Q_D(QDtls);
+
+ if (!socket) {
+ d->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
+ return false;
+ }
+
+ return d->handleTimeout(socket);
+}
+
+/*!
+ \internal
+*/
+bool QDtls::continueHandshake(QUdpSocket *socket, const QByteArray &datagram)
+{
+ Q_D(QDtls);
+
+ if (!socket || !datagram.size()) {
+ d->setDtlsError(QDtlsError::InvalidInputParameters,
+ tr("A valid QUdpSocket and non-empty datagram are needed to continue the handshake"));
+ return false;
+ }
+
+ if (d->handshakeState != HandshakeInProgress) {
+ d->setDtlsError(QDtlsError::InvalidOperation,
+ tr("Cannot continue handshake, not in InProgress state"));
+ return false;
+ }
+
+ return d->continueHandshake(socket, datagram);
+}
+
+/*!
+ If peer verification errors were ignored during the handshake,
+ resumeHandshake() resumes and completes the handshake and returns
+ \c true. \a socket must be a valid pointer. Returns \c false if
+ the handshake could not be resumed.
+
+ \sa doHandshake(), abortHandshake() peerVerificationErrors(), ignoreVerificationErrors()
+*/
+bool QDtls::resumeHandshake(QUdpSocket *socket)
+{
+ Q_D(QDtls);
+
+ if (!socket) {
+ d->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
+ return false;
+ }
+
+ if (d->handshakeState != PeerVerificationFailed) {
+ d->setDtlsError(QDtlsError::InvalidOperation,
+ tr("Cannot resume, not in VerificationError state"));
+ return false;
+ }
+
+ return d->resumeHandshake(socket);
+}
+
+/*!
+ Aborts the ongoing handshake. Returns true if one was on-going on \a socket;
+ otherwise, sets a suitable error and returns false.
+
+ \sa doHandshake(), resumeHandshake()
+ */
+bool QDtls::abortHandshake(QUdpSocket *socket)
+{
+ Q_D(QDtls);
+
+ if (!socket) {
+ d->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
+ return false;
+ }
+
+ if (d->handshakeState != PeerVerificationFailed && d->handshakeState != HandshakeInProgress) {
+ d->setDtlsError(QDtlsError::InvalidOperation,
+ tr("No handshake in progress, nothing to abort"));
+ return false;
+ }
+
+ d->abortHandshake(socket);
+ return true;
+}
+
+/*!
+ Sends an encrypted shutdown alert message and closes the DTLS connection.
+ Handshake state changes to QDtls::HandshakeNotStarted. \a socket must be a
+ valid pointer. This function returns \c true on success.
+
+ \sa doHandshake()
+ */
+bool QDtls::shutdown(QUdpSocket *socket)
+{
+ Q_D(QDtls);
+
+ if (!socket) {
+ d->setDtlsError(QDtlsError::InvalidInputParameters,
+ tr("Invalid (nullptr) socket"));
+ return false;
+ }
+
+ if (!d->connectionEncrypted) {
+ d->setDtlsError(QDtlsError::InvalidOperation,
+ tr("Cannot send shutdown alert, not encrypted"));
+ return false;
+ }
+
+ d->sendShutdownAlert(socket);
+ return true;
+}
+
+/*!
+ Returns \c true if DTLS handshake completed successfully.
+
+ \sa doHandshake(), handshakeState()
+ */
+bool QDtls::isConnectionEncrypted() const
+{
+ Q_D(const QDtls);
+
+ return d->connectionEncrypted;
+}
+
+/*!
+ Returns the cryptographic \l {QSslCipher} {cipher} used by this connection,
+ or a null cipher if the connection isn't encrypted. The cipher for the
+ session is selected during the handshake phase. The cipher is used to encrypt
+ and decrypt data.
+
+ QSslConfiguration provides functions for setting the ordered list of ciphers
+ from which the handshake phase will eventually select the session cipher.
+ This ordered list must be in place before the handshake phase begins.
+
+ \sa QSslConfiguration, setDtlsConfiguration(), dtlsConfiguration()
+*/
+QSslCipher QDtls::sessionCipher() const
+{
+ Q_D(const QDtls);
+
+ return d->sessionCipher;
+}
+
+/*!
+ Returns the DTLS protocol version used by this connection, or UnknownProtocol
+ if the connection isn't encrypted yet. The protocol for the connection is selected
+ during the handshake phase.
+
+ setDtlsConfiguration() can set the preferred version before the handshake starts.
+
+ \sa setDtlsConfiguration(), QSslConfiguration, QSslConfiguration::defaultDtlsConfiguration(),
+ QSslConfiguration::setProtocol()
+*/
+QSsl::SslProtocol QDtls::sessionProtocol() const
+{
+ Q_D(const QDtls);
+
+ return d->sessionProtocol;
+}
+
+/*!
+ Encrypts \a dgram and writes the encrypted data into \a socket. Returns the
+ number of bytes written, or -1 in case of error. The handshake must be completed
+ before writing encrypted data. \a socket must be a valid
+ pointer.
+
+ \sa doHandshake(), handshakeState(), isConnectionEncrypted(), dtlsError()
+*/
+qint64 QDtls::writeDatagramEncrypted(QUdpSocket *socket, const QByteArray &dgram)
+{
+ Q_D(QDtls);
+
+ if (!socket) {
+ d->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
+ return -1;
+ }
+
+ if (!isConnectionEncrypted()) {
+ d->setDtlsError(QDtlsError::InvalidOperation,
+ tr("Cannot write a datagram, not in encrypted state"));
+ return -1;
+ }
+
+ return d->writeDatagramEncrypted(socket, dgram);
+}
+
+/*!
+ Decrypts \a dgram and returns its contents as plain text. The handshake must
+ be completed before datagrams can be decrypted. Depending on the type of the
+ TLS message the connection may write into \a socket, which must be a valid
+ pointer.
+*/
+QByteArray QDtls::decryptDatagram(QUdpSocket *socket, const QByteArray &dgram)
+{
+ Q_D(QDtls);
+
+ if (!socket) {
+ d->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
+ return {};
+ }
+
+ if (!isConnectionEncrypted()) {
+ d->setDtlsError(QDtlsError::InvalidOperation,
+ tr("Cannot read a datagram, not in encrypted state"));
+ return {};
+ }
+
+ if (!dgram.size())
+ return {};
+
+ return d->decryptDatagram(socket, dgram);
+}
+
+/*!
+ Returns the last error encountered by the connection or QDtlsError::NoError.
+
+ \sa dtlsErrorString(), QDtlsError
+*/
+QDtlsError QDtls::dtlsError() const
+{
+ Q_D(const QDtls);
+
+ return d->errorCode;
+}
+
+/*!
+ Returns a textual description for the last error encountered by the connection
+ or empty string.
+
+ \sa dtlsError()
+*/
+QString QDtls::dtlsErrorString() const
+{
+ Q_D(const QDtls);
+
+ return d->errorDescription;
+}
+
+/*!
+ Returns errors found while establishing the identity of the peer.
+
+ If you want to continue connecting despite the errors that have occurred,
+ you must call ignoreVerificationErrors().
+*/
+QVector<QSslError> QDtls::peerVerificationErrors() const
+{
+ Q_D(const QDtls);
+
+ return d->tlsErrors;
+}
+
+/*!
+ This method tells QDtls to ignore only the errors given in \a errorsToIgnore.
+
+ If, for instance, you want to connect to a server that uses a self-signed
+ certificate, consider the following snippet:
+
+ \snippet code/src_network_ssl_qdtls.cpp 6
+
+ You can also call this function after doHandshake() encountered the
+ QDtlsError::PeerVerificationError error, and then resume the handshake by
+ calling resumeHandshake().
+
+ Later calls to this function will replace the list of errors that were
+ passed in previous calls. You can clear the list of errors you want to ignore
+ by calling this function with an empty list.
+
+ \sa doHandshake(), resumeHandshake(), QSslError
+*/
+void QDtls::ignoreVerificationErrors(const QVector<QSslError> &errorsToIgnore)
+{
+ Q_D(QDtls);
+
+ d->tlsErrorsToIgnore = errorsToIgnore;
+}
+
+QT_END_NAMESPACE
diff --git a/src/network/ssl/qdtls.h b/src/network/ssl/qdtls.h
new file mode 100644
index 0000000000..8505b00d5e
--- /dev/null
+++ b/src/network/ssl/qdtls.h
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 QDTLS_H
+#define QDTLS_H
+
+#include <QtNetwork/qtnetworkglobal.h>
+
+#include <QtNetwork/qsslsocket.h>
+#include <QtNetwork/qssl.h>
+
+#include <QtCore/qcryptographichash.h>
+#include <QtCore/qobject.h>
+
+QT_REQUIRE_CONFIG(dtls);
+
+QT_BEGIN_NAMESPACE
+
+enum class QDtlsError : unsigned char
+{
+ NoError,
+ InvalidInputParameters,
+ InvalidOperation,
+ UnderlyingSocketError,
+ RemoteClosedConnectionError,
+ PeerVerificationError,
+ TlsInitializationError,
+ TlsFatalError,
+ TlsNonFatalError
+};
+
+class QHostAddress;
+class QUdpSocket;
+class QByteArray;
+class QString;
+
+class QDtlsClientVerifierPrivate;
+class Q_NETWORK_EXPORT QDtlsClientVerifier : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ explicit QDtlsClientVerifier(QObject *parent = nullptr);
+ ~QDtlsClientVerifier();
+
+ struct Q_NETWORK_EXPORT GeneratorParameters
+ {
+ GeneratorParameters();
+ GeneratorParameters(QCryptographicHash::Algorithm a, const QByteArray &s);
+ QCryptographicHash::Algorithm hash = QCryptographicHash::Sha1;
+ QByteArray secret;
+ };
+
+ bool setCookieGeneratorParameters(const GeneratorParameters &params);
+ GeneratorParameters cookieGeneratorParameters() const;
+
+ bool verifyClient(QUdpSocket *socket, const QByteArray &dgram,
+ const QHostAddress &address, quint16 port);
+ QByteArray verifiedHello() const;
+
+ QDtlsError dtlsError() const;
+ QString dtlsErrorString() const;
+
+private:
+
+ Q_DECLARE_PRIVATE(QDtlsClientVerifier)
+ Q_DISABLE_COPY(QDtlsClientVerifier)
+};
+
+class QSslPreSharedKeyAuthenticator;
+template<class> class QVector;
+class QSslConfiguration;
+class QSslCipher;
+class QSslError;
+
+class QDtlsPrivate;
+class Q_NETWORK_EXPORT QDtls : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ enum HandshakeState
+ {
+ HandshakeNotStarted,
+ HandshakeInProgress,
+ PeerVerificationFailed,
+ HandshakeComplete
+ };
+
+ explicit QDtls(QSslSocket::SslMode mode, QObject *parent = nullptr);
+ ~QDtls();
+
+ bool setPeer(const QHostAddress &address, quint16 port,
+ const QString &verificationName = {});
+ bool setPeerVerificationName(const QString &name);
+ QHostAddress peerAddress() const;
+ quint16 peerPort() const;
+ QString peerVerificationName() const;
+ QSslSocket::SslMode sslMode() const;
+
+ void setMtuHint(quint16 mtuHint);
+ quint16 mtuHint() const;
+
+ using GeneratorParameters = QDtlsClientVerifier::GeneratorParameters;
+ bool setCookieGeneratorParameters(const GeneratorParameters &params);
+ GeneratorParameters cookieGeneratorParameters() const;
+
+ bool setDtlsConfiguration(const QSslConfiguration &configuration);
+ QSslConfiguration dtlsConfiguration() const;
+
+ HandshakeState handshakeState() const;
+
+ bool doHandshake(QUdpSocket *socket, const QByteArray &dgram = {});
+ bool handleTimeout(QUdpSocket *socket);
+ bool resumeHandshake(QUdpSocket *socket);
+ bool abortHandshake(QUdpSocket *socket);
+ bool shutdown(QUdpSocket *socket);
+
+ bool isConnectionEncrypted() const;
+ QSslCipher sessionCipher() const;
+ QSsl::SslProtocol sessionProtocol() const;
+
+ qint64 writeDatagramEncrypted(QUdpSocket *socket, const QByteArray &dgram);
+ QByteArray decryptDatagram(QUdpSocket *socket, const QByteArray &dgram);
+
+ QDtlsError dtlsError() const;
+ QString dtlsErrorString() const;
+
+ QVector<QSslError> peerVerificationErrors() const;
+ void ignoreVerificationErrors(const QVector<QSslError> &errorsToIgnore);
+
+Q_SIGNALS:
+
+ void pskRequired(QSslPreSharedKeyAuthenticator *authenticator);
+ void handshakeTimeout();
+
+private:
+
+ bool startHandshake(QUdpSocket *socket, const QByteArray &dgram);
+ bool continueHandshake(QUdpSocket *socket, const QByteArray &dgram);
+
+ Q_DECLARE_PRIVATE(QDtls)
+ Q_DISABLE_COPY(QDtls)
+};
+
+QT_END_NAMESPACE
+
+#endif // QDTLS_H
diff --git a/src/network/ssl/qdtls_openssl.cpp b/src/network/ssl/qdtls_openssl.cpp
new file mode 100644
index 0000000000..8be53df24f
--- /dev/null
+++ b/src/network/ssl/qdtls_openssl.cpp
@@ -0,0 +1,1462 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 NOMINMAX
+#define NOMINMAX
+#endif // NOMINMAX
+#include "private/qnativesocketengine_p.h"
+
+#include "qsslpresharedkeyauthenticator_p.h"
+#include "qsslsocket_openssl_symbols_p.h"
+#include "qsslsocket_openssl_p.h"
+#include "qsslcertificate_p.h"
+#include "qdtls_openssl_p.h"
+#include "qudpsocket.h"
+#include "qssl_p.h"
+
+#include "qmessageauthenticationcode.h"
+#include "qcryptographichash.h"
+
+#include "qdebug.h"
+
+#include <cstring>
+#include <cstddef>
+
+QT_BEGIN_NAMESPACE
+
+#define QT_DTLS_VERBOSE 0
+
+#if QT_DTLS_VERBOSE
+
+#define qDtlsWarning(arg) qWarning(arg)
+#define qDtlsDebug(arg) qDebug(arg)
+
+#else
+
+#define qDtlsWarning(arg)
+#define qDtlsDebug(arg)
+
+#endif // QT_DTLS_VERBOSE
+
+namespace dtlsutil
+{
+
+QByteArray cookie_for_peer(SSL *ssl)
+{
+ Q_ASSERT(ssl);
+
+ // SSL_get_rbio does not increment the reference count
+ BIO *readBIO = q_SSL_get_rbio(ssl);
+ if (!readBIO) {
+ qCWarning(lcSsl, "No BIO (dgram) found in SSL object");
+ return {};
+ }
+
+ auto listener = static_cast<dtlsopenssl::DtlsState *>(q_BIO_get_app_data(readBIO));
+ if (!listener) {
+ qCWarning(lcSsl, "BIO_get_app_data returned invalid (nullptr) value");
+ return {};
+ }
+
+ const QHostAddress peerAddress(listener->remoteAddress);
+ const quint16 peerPort(listener->remotePort);
+ QByteArray peerData;
+ if (peerAddress.protocol() == QAbstractSocket::IPv6Protocol) {
+ const Q_IPV6ADDR sin6_addr(peerAddress.toIPv6Address());
+ peerData.resize(int(sizeof sin6_addr + sizeof peerPort));
+ char *dst = peerData.data();
+ std::memcpy(dst, &peerPort, sizeof peerPort);
+ dst += sizeof peerPort;
+ std::memcpy(dst, &sin6_addr, sizeof sin6_addr);
+ } else if (peerAddress.protocol() == QAbstractSocket::IPv4Protocol) {
+ const quint32 sin_addr(peerAddress.toIPv4Address());
+ peerData.resize(int(sizeof sin_addr + sizeof peerPort));
+ char *dst = peerData.data();
+ std::memcpy(dst, &peerPort, sizeof peerPort);
+ dst += sizeof peerPort;
+ std::memcpy(dst, &sin_addr, sizeof sin_addr);
+ } else {
+ Q_UNREACHABLE();
+ }
+
+ return peerData;
+}
+
+struct FallbackCookieSecret
+{
+ FallbackCookieSecret()
+ {
+ key.resize(32);
+ const int status = q_RAND_bytes(reinterpret_cast<unsigned char *>(key.data()),
+ key.size());
+ if (status <= 0)
+ key.clear();
+ }
+
+ QByteArray key;
+
+ Q_DISABLE_COPY(FallbackCookieSecret)
+};
+
+QByteArray fallbackSecret()
+{
+ static const FallbackCookieSecret generator;
+ return generator.key;
+}
+
+int next_timeoutMs(SSL *tlsConnection)
+{
+ Q_ASSERT(tlsConnection);
+ timeval timeLeft = {};
+ q_DTLSv1_get_timeout(tlsConnection, &timeLeft);
+ return timeLeft.tv_sec * 1000;
+}
+
+
+void delete_connection(SSL *ssl)
+{
+ // The 'deleter' for QSharedPointer<SSL>.
+ if (ssl)
+ q_SSL_free(ssl);
+}
+
+#if QT_CONFIG(opensslv11)
+
+void delete_BIO_ADDR(BIO_ADDR *bio)
+{
+ // A deleter for QSharedPointer<BIO_ADDR>
+ if (bio)
+ q_BIO_ADDR_free(bio);
+}
+
+void delete_bio_method(BIO_METHOD *method)
+{
+ // The 'deleter' for QSharedPointer<BIO_METHOD>.
+ if (method)
+ q_BIO_meth_free(method);
+}
+
+#endif // openssl 1.1
+
+// The 'deleter' for QScopedPointer<BIO>.
+struct bio_deleter
+{
+ static void cleanup(BIO *bio)
+ {
+ if (bio)
+ q_BIO_free(bio);
+ }
+};
+
+// The path MTU discovery is non-trivial: it's a mix of getsockopt/setsockopt
+// (IP_MTU/IP6_MTU/IP_MTU_DISCOVER) and fallback MTU values. It's not
+// supported on all platforms, worse so - imposes specific requirements on
+// underlying UDP socket etc. So for now, we either try a user-proposed MTU
+// hint or rely on our own fallback value. As a fallback mtu OpenSSL uses 576
+// for IPv4 and 1280 for IPv6 (RFC 791, RFC 2460). To KIS we use 576. This
+// rather small MTU value does not affect the size that can be read/written
+// by QDtls, only a handshake (which is allowed to fragment).
+enum class MtuGuess : long
+{
+ defaultMtu = 576
+};
+
+} // namespace dtlsutil
+
+namespace dtlscallbacks
+{
+
+extern "C" int q_generate_cookie_callback(SSL *ssl, unsigned char *dst,
+ unsigned *cookieLength)
+{
+ if (!ssl || !dst || !cookieLength) {
+ qCWarning(lcSsl,
+ "Failed to generate cookie - invalid (nullptr) parameter(s)");
+ return 0;
+ }
+
+ void *generic = q_SSL_get_ex_data(ssl, QSslSocketBackendPrivate::s_indexForSSLExtraData);
+ if (!generic) {
+ qCWarning(lcSsl, "SSL_get_ex_data returned nullptr, cannot generate cookie");
+ return 0;
+ }
+
+ *cookieLength = 0;
+
+ auto dtls = static_cast<dtlsopenssl::DtlsState *>(generic);
+ if (!dtls->secret.size())
+ return 0;
+
+ const QByteArray peerData(dtlsutil::cookie_for_peer(ssl));
+ if (!peerData.size())
+ return 0;
+
+ QMessageAuthenticationCode hmac(dtls->hashAlgorithm, dtls->secret);
+ hmac.addData(peerData);
+ const QByteArray cookie = hmac.result();
+ Q_ASSERT(cookie.size() >= 0);
+ // DTLS1_COOKIE_LENGTH is erroneously 256 bytes long, must be 255 - RFC 6347, 4.2.1.
+ *cookieLength = qMin(DTLS1_COOKIE_LENGTH - 1, cookie.size());
+ std::memcpy(dst, cookie.constData(), *cookieLength);
+
+ return 1;
+}
+
+extern "C" int q_verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
+ unsigned cookieLength)
+{
+ if (!ssl || !cookie || !cookieLength) {
+ qCWarning(lcSsl, "Could not verify cookie, invalid (nullptr or zero) parameters");
+ return 0;
+ }
+
+ unsigned char newCookie[DTLS1_COOKIE_LENGTH] = {};
+ unsigned newCookieLength = 0;
+ if (q_generate_cookie_callback(ssl, newCookie, &newCookieLength) != 1)
+ return 0;
+
+ return newCookieLength == cookieLength
+ && !std::memcmp(cookie, newCookie, cookieLength);
+}
+
+extern "C" int q_X509DtlsCallback(int ok, X509_STORE_CTX *ctx)
+{
+ if (!ok) {
+ // Store the error and at which depth the error was detected.
+ SSL *ssl = static_cast<SSL *>(q_X509_STORE_CTX_get_ex_data(ctx, q_SSL_get_ex_data_X509_STORE_CTX_idx()));
+ if (!ssl) {
+ qCWarning(lcSsl, "X509_STORE_CTX_get_ex_data returned nullptr, handshake failure");
+ return 0;
+ }
+
+ void *generic = q_SSL_get_ex_data(ssl, QSslSocketBackendPrivate::s_indexForSSLExtraData);
+ if (!generic) {
+ qCWarning(lcSsl, "SSL_get_ex_data returned nullptr, handshake failure");
+ return 0;
+ }
+
+ auto dtls = static_cast<dtlsopenssl::DtlsState *>(generic);
+ dtls->x509Errors.append(QSslErrorEntry::fromStoreContext(ctx));
+ }
+
+ // Always return 1 (OK) to allow verification to continue. We handle the
+ // errors gracefully after collecting all errors, after verification has
+ // completed.
+ return 1;
+}
+
+extern "C" unsigned q_PSK_client_callback(SSL *ssl, const char *hint, char *identity,
+ unsigned max_identity_len, unsigned char *psk,
+ unsigned max_psk_len)
+{
+ auto *dtls = static_cast<dtlsopenssl::DtlsState *>(q_SSL_get_ex_data(ssl,
+ QSslSocketBackendPrivate::s_indexForSSLExtraData));
+ if (!dtls)
+ return 0;
+
+ Q_ASSERT(dtls->dtlsPrivate);
+ return dtls->dtlsPrivate->pskClientCallback(hint, identity, max_identity_len, psk, max_psk_len);
+}
+
+extern "C" unsigned q_PSK_server_callback(SSL *ssl, const char *identity, unsigned char *psk,
+ unsigned max_psk_len)
+{
+ auto *dtls = static_cast<dtlsopenssl::DtlsState *>(q_SSL_get_ex_data(ssl,
+ QSslSocketBackendPrivate::s_indexForSSLExtraData));
+ if (!dtls)
+ return 0;
+
+ Q_ASSERT(dtls->dtlsPrivate);
+ return dtls->dtlsPrivate->pskServerCallback(identity, psk, max_psk_len);
+}
+
+} // namespace dtlscallbacks
+
+namespace dtlsbio
+{
+
+extern "C" int q_dgram_read(BIO *bio, char *dst, int bytesToRead)
+{
+ if (!bio || !dst || bytesToRead <= 0) {
+ qCWarning(lcSsl, "invalid input parameter(s)");
+ return 0;
+ }
+
+ q_BIO_clear_retry_flags(bio);
+
+ auto dtls = static_cast<dtlsopenssl::DtlsState *>(q_BIO_get_app_data(bio));
+ // It's us who set data, if OpenSSL does too, the logic here is wrong
+ // then and we have to use BIO_set_app_data then!
+ Q_ASSERT(dtls);
+ int bytesRead = 0;
+ if (dtls->dgram.size()) {
+ bytesRead = qMin(dtls->dgram.size(), bytesToRead);
+ std::memcpy(dst, dtls->dgram.constData(), bytesRead);
+
+ if (!dtls->peeking)
+ dtls->dgram = dtls->dgram.mid(bytesRead);
+ } else {
+ bytesRead = -1;
+ }
+
+ if (bytesRead <= 0)
+ q_BIO_set_retry_read(bio);
+
+ return bytesRead;
+}
+
+extern "C" int q_dgram_write(BIO *bio, const char *src, int bytesToWrite)
+{
+ if (!bio || !src || bytesToWrite <= 0) {
+ qCWarning(lcSsl, "invalid input parameter(s)");
+ return 0;
+ }
+
+ q_BIO_clear_retry_flags(bio);
+
+ auto dtls = static_cast<dtlsopenssl::DtlsState *>(q_BIO_get_app_data(bio));
+ Q_ASSERT(dtls);
+ if (dtls->writeSuppressed) {
+ // See the comment in QDtls::startHandshake.
+ return bytesToWrite;
+ }
+
+ QUdpSocket *udpSocket = dtls->udpSocket;
+ Q_ASSERT(udpSocket);
+
+ const QByteArray dgram(QByteArray::fromRawData(src, bytesToWrite));
+ qint64 bytesWritten = -1;
+ if (udpSocket->state() == QAbstractSocket::ConnectedState) {
+ bytesWritten = udpSocket->write(dgram);
+ } else {
+ bytesWritten = udpSocket->writeDatagram(dgram, dtls->remoteAddress,
+ dtls->remotePort);
+ }
+
+ if (bytesWritten <= 0)
+ q_BIO_set_retry_write(bio);
+
+ Q_ASSERT(bytesWritten <= std::numeric_limits<int>::max());
+ return int(bytesWritten);
+}
+
+extern "C" int q_dgram_puts(BIO *bio, const char *src)
+{
+ if (!bio || !src) {
+ qCWarning(lcSsl, "invalid input parameter(s)");
+ return 0;
+ }
+
+ return q_dgram_write(bio, src, int(std::strlen(src)));
+}
+
+extern "C" long q_dgram_ctrl(BIO *bio, int cmd, long num, void *ptr)
+{
+ // This is our custom BIO_ctrl. bio.h defines a lot of BIO_CTRL_*
+ // and BIO_* constants and BIO_somename macros that expands to BIO_ctrl
+ // call with one of those constants as argument. What exactly BIO_ctrl
+ // does - depends on the 'cmd' and the type of BIO (so BIO_ctrl does
+ // not even have a single well-defined value meaning success or failure).
+ // We handle only the most generic commands - the ones documented for
+ // BIO_ctrl - and also DGRAM specific ones. And even for them - in most
+ // cases we do nothing but report a success or some non-error value.
+ // Documents also state: "Source/sink BIOs return an 0 if they do not
+ // recognize the BIO_ctrl() operation." - these are covered by 'default'
+ // label in the switch-statement below. Debug messages in the switch mean:
+ // 1) we got a command that is unexpected for dgram BIO, or:
+ // 2) we do not call any function that would lead to OpenSSL using this
+ // command.
+
+ if (!bio) {
+ qDebug(lcSsl, "invalid 'bio' parameter (nullptr)");
+ return -1;
+ }
+
+ auto dtls = static_cast<dtlsopenssl::DtlsState *>(q_BIO_get_app_data(bio));
+ Q_ASSERT(dtls);
+
+#if !QT_CONFIG(opensslv11)
+ Q_UNUSED(num)
+#endif
+
+ switch (cmd) {
+ // Let's start from the most generic ones, in the order in which they are
+ // documented (as BIO_ctrl):
+ case BIO_CTRL_RESET:
+ // BIO_reset macro.
+ // From documentation:
+ // "BIO_reset() normally returns 1 for success and 0 or -1 for failure.
+ // File BIOs are an exception, they return 0 for success and -1 for
+ // failure."
+ // We have nothing to reset and we are not file BIO.
+ return 1;
+ case BIO_C_FILE_SEEK:
+ case BIO_C_FILE_TELL:
+ qDtlsWarning("Unexpected cmd (BIO_C_FILE_SEEK/BIO_C_FILE_TELL)");
+ // These are for BIO_seek, BIO_tell. We are not a file BIO.
+ // Non-negative return value means success.
+ return 0;
+ case BIO_CTRL_FLUSH:
+ // BIO_flush, nothing to do, we do not buffer any data.
+ // 0 or -1 means error, 1 - success.
+ return 1;
+ case BIO_CTRL_EOF:
+ qDtlsWarning("Unexpected cmd (BIO_CTRL_EOF)");
+ // BIO_eof, 1 means EOF read. Makes no sense for us.
+ return 0;
+ case BIO_CTRL_SET_CLOSE:
+ // BIO_set_close with BIO_CLOSE/BIO_NOCLOSE flags. Documented as
+ // always returning 1.
+ // From the documentation:
+ // "Typically BIO_CLOSE is used in a source/sink BIO to indicate that
+ // the underlying I/O stream should be closed when the BIO is freed."
+ //
+ // QUdpSocket we work with is not BIO's business, ignoring.
+ return 1;
+ case BIO_CTRL_GET_CLOSE:
+ // BIO_get_close. No, never, see the comment above.
+ return 0;
+ case BIO_CTRL_PENDING:
+ qDtlsWarning("Unexpected cmd (BIO_CTRL_PENDING)");
+ // BIO_pending. Not used by DTLS/OpenSSL (we are not buffering).
+ return 0;
+ case BIO_CTRL_WPENDING:
+ // No, we have nothing buffered.
+ return 0;
+ // The constants below are not documented as a part BIO_ctrl documentation,
+ // but they are also not type-specific.
+ case BIO_CTRL_DUP:
+ qDtlsWarning("Unexpected cmd (BIO_CTRL_DUP)");
+ // BIO_dup_state, not used by DTLS (and socket-related BIOs in general).
+ // For some very specific BIO type this 'cmd' would copy some state
+ // from 'bio' to (BIO*)'ptr'. 1 means success.
+ return 0;
+ case BIO_CTRL_SET_CALLBACK:
+ qDtlsWarning("Unexpected cmd (BIO_CTRL_SET_CALLBACK)");
+ // BIO_set_info_callback. We never call this, OpenSSL does not do this
+ // on its own (normally it's used if client code wants to have some
+ // debug information, for example, dumping handshake state via
+ // BIO_printf from SSL info_callback).
+ return 0;
+ case BIO_CTRL_GET_CALLBACK:
+ qDtlsWarning("Unexpected cmd (BIO_CTRL_GET_CALLBACK)");
+ // BIO_get_info_callback. We never call this.
+ if (ptr)
+ *static_cast<bio_info_cb **>(ptr) = nullptr;
+ return 0;
+ case BIO_CTRL_SET:
+ case BIO_CTRL_GET:
+ qDtlsWarning("Unexpected cmd (BIO_CTRL_SET/BIO_CTRL_GET)");
+ // Somewhat 'documented' as setting/getting IO type. Not used anywhere
+ // except BIO_buffer_get_num_lines (which contradics 'get IO type').
+ // Ignoring.
+ return 0;
+ // DGRAM-specific operation, we have to return some reasonable value
+ // (so far, I've encountered only peek mode switching, connect).
+ case BIO_CTRL_DGRAM_CONNECT:
+ // BIO_ctrl_dgram_connect. Not needed. Our 'dtls' already knows
+ // the peer's address/port. Report success though.
+ return 1;
+ case BIO_CTRL_DGRAM_SET_CONNECTED:
+ qDtlsWarning("Unexpected cmd (BIO_CTRL_DGRAM_SET_CONNECTED)");
+ // BIO_ctrl_dgram_set_connected. We never call it, OpenSSL does
+ // not call it on its own (so normally it's done by client code).
+ // Similar to BIO_CTRL_DGRAM_CONNECT, but it also informs the BIO
+ // that its UDP socket is connected. We never need it though.
+ return -1;
+ case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
+ qDtlsWarning("Unexpected cmd (BIO_CTRL_DGRAM_SET_RECV_TIMEOUT)");
+ // Essentially setsockopt with SO_RCVTIMEO, not needed, our sockets
+ // are non-blocking.
+ return -1;
+ case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
+ qDtlsWarning("Unexpected cmd (BIO_CTRL_DGRAM_GET_RECV_TIMEOUT)");
+ // getsockopt with SO_RCVTIMEO, not needed, our sockets are
+ // non-blocking. ptr is timeval *.
+ return -1;
+ case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT:
+ qDtlsWarning("Unexpected cmd (BIO_CTRL_DGRAM_SET_SEND_TIMEOUT)");
+ // setsockopt, SO_SNDTIMEO, cannot happen.
+ return -1;
+ case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT:
+ qDtlsWarning("Unexpected cmd (BIO_CTRL_DGRAM_GET_SEND_TIMEOUT)");
+ // getsockopt, SO_SNDTIMEO, cannot happen.
+ return -1;
+ case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP:
+ // BIO_dgram_recv_timedout. No, we are non-blocking.
+ return 0;
+ case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP:
+ // BIO_dgram_send_timedout. No, we are non-blocking.
+ return 0;
+ case BIO_CTRL_DGRAM_MTU_DISCOVER:
+ qDtlsWarning("Unexpected cmd (BIO_CTRL_DGRAM_MTU_DISCOVER)");
+ // setsockopt, IP_MTU_DISCOVER/IP6_MTU_DISCOVER, to be done
+ // in QUdpSocket instead. OpenSSL never calls it, only client
+ // code.
+ return 1;
+ case BIO_CTRL_DGRAM_QUERY_MTU:
+ qDtlsWarning("Unexpected cmd (BIO_CTRL_DGRAM_QUERY_MTU)");
+ // To be done in QUdpSocket instead.
+ return 1;
+ case BIO_CTRL_DGRAM_GET_FALLBACK_MTU:
+ qDtlsWarning("Unexpected command *BIO_CTRL_DGRAM_GET_FALLBACK_MTU)");
+ // Without SSL_OP_NO_QUERY_MTU set on SSL, OpenSSL can request for
+ // fallback MTU after several re-transmissions.
+ // Should never happen in our case.
+ return long(dtlsutil::MtuGuess::defaultMtu);
+ case BIO_CTRL_DGRAM_GET_MTU:
+ qDtlsWarning("Unexpected cmd (BIO_CTRL_DGRAM_GET_MTU)");
+ return -1;
+ case BIO_CTRL_DGRAM_SET_MTU:
+ qDtlsWarning("Unexpected cmd (BIO_CTRL_DGRAM_SET_MTU)");
+ // Should not happen (we don't call BIO_ctrl with this parameter)
+ // and set MTU on SSL instead.
+ return -1; // num is mtu and it's a return value meaning success.
+ case BIO_CTRL_DGRAM_MTU_EXCEEDED:
+ qDtlsWarning("Unexpected cmd (BIO_CTRL_DGRAM_MTU_EXCEEDED)");
+ return 0;
+ case BIO_CTRL_DGRAM_GET_PEER:
+ qDtlsDebug("BIO_CTRL_DGRAM_GET_PEER");
+ // BIO_dgram_get_peer. We do not return a real address (DTLS is not
+ // using this address), but let's pretend a success.
+ switch (dtls->remoteAddress.protocol()) {
+ case QAbstractSocket::IPv6Protocol:
+ return sizeof(sockaddr_in6);
+ case QAbstractSocket::IPv4Protocol:
+ return sizeof(sockaddr_in);
+ default:
+ return -1;
+ }
+ case BIO_CTRL_DGRAM_SET_PEER:
+ // Similar to BIO_CTRL_DGRAM_CONNECTED.
+ return 1;
+ case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
+ // DTLSTODO: I'm not sure yet, how it's used by OpenSSL.
+ return 1;
+ case BIO_CTRL_DGRAM_SET_DONT_FRAG:
+ qDtlsDebug("BIO_CTRL_DGRAM_SET_DONT_FRAG");
+ // To be done in QUdpSocket, it's about IP_DONTFRAG etc.
+ return 1;
+ case BIO_CTRL_DGRAM_GET_MTU_OVERHEAD:
+ // AFAIK it's 28 for IPv4 and 48 for IPv6, but let's pretend it's 0
+ // so that OpenSSL does not start suddenly fragmenting the first
+ // client hello (which will result in DTLSv1_listen rejecting it).
+ return 0;
+#if QT_CONFIG(opensslv11)
+ case BIO_CTRL_DGRAM_SET_PEEK_MODE:
+ dtls->peeking = num;
+ return 1;
+#endif
+ default:;
+#if QT_DTLS_VERBOSE
+ qWarning() << "Unexpected cmd (" << cmd << ")";
+#endif
+ }
+
+ return 0;
+}
+
+extern "C" int q_dgram_create(BIO *bio)
+{
+#if QT_CONFIG(opensslv11)
+ q_BIO_set_init(bio, 1);
+#else
+ bio->init = 1;
+#endif
+ // With a custom BIO you'd normally allocate some implementation-specific
+ // data and append it to this new BIO: bio->ptr = ... (pre 1.0.2) or
+ // BIO_set_data (1.1). We don't need it and thus q_dgram_destroy below
+ // is a noop.
+ return 1;
+}
+
+extern "C" int q_dgram_destroy(BIO *bio)
+{
+ Q_UNUSED(bio)
+ return 1;
+}
+
+const char * const qdtlsMethodName = "qdtlsbio";
+
+#if !QT_CONFIG(opensslv11)
+
+/*
+typedef struct bio_method_st {
+ int type;
+ const char *name;
+ int (*bwrite) (BIO *, const char *, int);
+ int (*bread) (BIO *, char *, int);
+ int (*bputs) (BIO *, const char *);
+ int (*bgets) (BIO *, char *, int);
+ long (*ctrl) (BIO *, int, long, void *);
+ int (*create) (BIO *);
+ int (*destroy) (BIO *);
+ long (*callback_ctrl) (BIO *, int, bio_info_cb *);
+} BIO_METHOD;
+*/
+
+bio_method_st qdtlsCustomBioMethod =
+{
+ BIO_TYPE_DGRAM,
+ qdtlsMethodName,
+ q_dgram_write,
+ q_dgram_read,
+ q_dgram_puts,
+ nullptr,
+ q_dgram_ctrl,
+ q_dgram_create,
+ q_dgram_destroy,
+ nullptr
+};
+
+#endif // openssl < 1.1
+
+} // namespace dtlsbio
+
+namespace dtlsopenssl
+{
+
+bool DtlsState::init(QDtlsBasePrivate *dtlsBase, QUdpSocket *socket,
+ const QHostAddress &remote, quint16 port,
+ const QByteArray &receivedMessage)
+{
+ Q_ASSERT(dtlsBase);
+ Q_ASSERT(socket);
+
+ if (!tlsContext.data() && !initTls(dtlsBase))
+ return false;
+
+ udpSocket = socket;
+
+ setLinkMtu(dtlsBase);
+
+ dgram = receivedMessage;
+ remoteAddress = remote;
+ remotePort = port;
+
+ // SSL_get_rbio does not increment a reference count.
+ BIO *bio = q_SSL_get_rbio(tlsConnection.data());
+ Q_ASSERT(bio);
+ q_BIO_set_app_data(bio, this);
+
+ return true;
+}
+
+void DtlsState::reset()
+{
+ tlsConnection.reset();
+ tlsContext.reset();
+}
+
+bool DtlsState::initTls(QDtlsBasePrivate *dtlsBase)
+{
+ if (tlsContext.data())
+ return true;
+
+ if (!QSslSocket::supportsSsl())
+ return false;
+
+ if (!initCtxAndConnection(dtlsBase))
+ return false;
+
+ if (!initBIO(dtlsBase)) {
+ tlsConnection.reset();
+ tlsContext.reset();
+ return false;
+ }
+
+ return true;
+}
+
+static QString msgFunctionFailed(const char *function)
+{
+ //: %1: Some function
+ return QDtls::tr("%1 failed").arg(QLatin1String(function));
+}
+
+bool DtlsState::initCtxAndConnection(QDtlsBasePrivate *dtlsBase)
+{
+ Q_ASSERT(dtlsBase);
+ Q_ASSERT(QSslSocket::supportsSsl());
+
+ if (dtlsBase->mode == QSslSocket::UnencryptedMode) {
+ dtlsBase->setDtlsError(QDtlsError::TlsInitializationError,
+ QDtls::tr("Invalid SslMode, SslServerMode or SslClientMode expected"));
+ return false;
+ }
+
+ if (!QDtlsBasePrivate::isDtlsProtocol(dtlsBase->dtlsConfiguration.protocol)) {
+ dtlsBase->setDtlsError(QDtlsError::TlsInitializationError,
+ QDtls::tr("Invalid protocol version, DTLS protocol expected"));
+ return false;
+ }
+
+ // Create a deep copy of our configuration
+ auto configurationCopy = new QSslConfigurationPrivate(dtlsBase->dtlsConfiguration);
+ configurationCopy->ref.store(0); // the QSslConfiguration constructor refs up
+
+ // DTLSTODO: check we do not set something DTLS-incompatible there ...
+ TlsContext newContext(QSslContext::sharedFromConfiguration(dtlsBase->mode,
+ configurationCopy,
+ dtlsBase->dtlsConfiguration.allowRootCertOnDemandLoading));
+
+ if (newContext->error() != QSslError::NoError) {
+ dtlsBase->setDtlsError(QDtlsError::TlsInitializationError, newContext->errorString());
+ return false;
+ }
+
+ TlsConnection newConnection(newContext->createSsl(), dtlsutil::delete_connection);
+ if (!newConnection.data()) {
+ dtlsBase->setDtlsError(QDtlsError::TlsInitializationError,
+ msgFunctionFailed("SSL_new"));
+ return false;
+ }
+
+ const int set = q_SSL_set_ex_data(newConnection.data(),
+ QSslSocketBackendPrivate::s_indexForSSLExtraData,
+ this);
+
+ if (set != 1 && configurationCopy->peerVerifyMode != QSslSocket::VerifyNone) {
+ dtlsBase->setDtlsError(QDtlsError::TlsInitializationError,
+ msgFunctionFailed("SSL_set_ex_data"));
+ return false;
+ }
+
+ if (dtlsBase->mode == QSslSocket::SslServerMode) {
+ if (dtlsBase->dtlsConfiguration.dtlsCookieEnabled)
+ q_SSL_set_options(newConnection.data(), SSL_OP_COOKIE_EXCHANGE);
+ q_SSL_set_psk_server_callback(newConnection.data(), dtlscallbacks::q_PSK_server_callback);
+ } else {
+ q_SSL_set_psk_client_callback(newConnection.data(), dtlscallbacks::q_PSK_client_callback);
+ }
+
+ tlsContext.swap(newContext);
+ tlsConnection.swap(newConnection);
+
+ return true;
+}
+
+bool DtlsState::initBIO(QDtlsBasePrivate *dtlsBase)
+{
+ Q_ASSERT(dtlsBase);
+ Q_ASSERT(tlsContext.data() && tlsConnection.data());
+
+#if QT_CONFIG(opensslv11)
+ BioMethod customMethod(q_BIO_meth_new(BIO_TYPE_DGRAM, dtlsbio::qdtlsMethodName),
+ dtlsutil::delete_bio_method);
+ if (!customMethod.data()) {
+ dtlsBase->setDtlsError(QDtlsError::TlsInitializationError,
+ msgFunctionFailed("BIO_meth_new"));
+ return false;
+ }
+
+ BIO_METHOD *biom = customMethod.data();
+ q_BIO_meth_set_create(biom, dtlsbio::q_dgram_create);
+ q_BIO_meth_set_destroy(biom, dtlsbio::q_dgram_destroy);
+ q_BIO_meth_set_read(biom, dtlsbio::q_dgram_read);
+ q_BIO_meth_set_write(biom, dtlsbio::q_dgram_write);
+ q_BIO_meth_set_puts(biom, dtlsbio::q_dgram_puts);
+ q_BIO_meth_set_ctrl(biom, dtlsbio::q_dgram_ctrl);
+#else
+ BIO_METHOD *biom = &dtlsbio::qdtlsCustomBioMethod;
+#endif // openssl 1.1
+
+ QScopedPointer<BIO, dtlsutil::bio_deleter> newBio(q_BIO_new(biom));
+ BIO *bio = newBio.data();
+ if (!bio) {
+ dtlsBase->setDtlsError(QDtlsError::TlsInitializationError,
+ msgFunctionFailed("BIO_new"));
+ return false;
+ }
+
+ q_SSL_set_bio(tlsConnection.data(), bio, bio);
+ newBio.take();
+
+#if QT_CONFIG(opensslv11)
+ bioMethod.swap(customMethod);
+#endif // openssl 1.1
+
+ return true;
+}
+
+void DtlsState::setLinkMtu(QDtlsBasePrivate *dtlsBase)
+{
+ Q_ASSERT(dtlsBase);
+ Q_ASSERT(udpSocket);
+ Q_ASSERT(tlsConnection.data());
+
+ long mtu = dtlsBase->mtuHint;
+ if (!mtu) {
+ // If the underlying QUdpSocket was connected, getsockopt with
+ // IP_MTU/IP6_MTU can give us some hint:
+ bool optionFound = false;
+ if (udpSocket->state() == QAbstractSocket::ConnectedState) {
+ const QVariant val(udpSocket->socketOption(QAbstractSocket::PathMtuSocketOption));
+ if (val.isValid() && val.canConvert<int>())
+ mtu = val.toInt(&optionFound);
+ }
+
+ if (!optionFound || mtu <= 0) {
+ // OK, our own initial guess.
+ mtu = long(dtlsutil::MtuGuess::defaultMtu);
+ }
+ }
+
+ // For now, we disable this option.
+ q_SSL_set_options(tlsConnection.data(), SSL_OP_NO_QUERY_MTU);
+
+ q_DTLS_set_link_mtu(tlsConnection.data(), mtu);
+}
+
+} // namespace dtlsopenssl
+
+QDtlsClientVerifierOpenSSL::QDtlsClientVerifierOpenSSL()
+{
+ secret = dtlsutil::fallbackSecret();
+}
+
+bool QDtlsClientVerifierOpenSSL::verifyClient(QUdpSocket *socket, const QByteArray &dgram,
+ const QHostAddress &address, quint16 port)
+{
+ Q_ASSERT(socket);
+ Q_ASSERT(dgram.size());
+ Q_ASSERT(!address.isNull());
+ Q_ASSERT(port);
+
+ clearDtlsError();
+ verifiedClientHello.clear();
+
+ if (!dtls.init(this, socket, address, port, dgram))
+ return false;
+
+ dtls.secret = secret;
+ dtls.hashAlgorithm = hashAlgorithm;
+
+ Q_ASSERT(dtls.tlsConnection.data());
+#if QT_CONFIG(opensslv11)
+ QSharedPointer<BIO_ADDR> peer(q_BIO_ADDR_new(), dtlsutil::delete_BIO_ADDR);
+ if (!peer.data()) {
+ setDtlsError(QDtlsError::TlsInitializationError,
+ QDtlsClientVerifier::tr("BIO_ADDR_new failed, ignoring client hello"));
+ return false;
+ }
+
+ const int ret = q_DTLSv1_listen(dtls.tlsConnection.data(), peer.data());
+ if (ret < 0) {
+ // Since 1.1 - it's a fatal error (not so in 1.0.2 for non-blocking socket)
+ setDtlsError(QDtlsError::TlsFatalError, QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+ return false;
+ }
+#else
+ qt_sockaddr peer;
+ const int ret = q_DTLSv1_listen(dtls.tlsConnection.data(), &peer);
+#endif
+ if (ret > 0) {
+ verifiedClientHello = dgram;
+ return true;
+ }
+
+ return false;
+}
+
+void QDtlsPrivateOpenSSL::TimeoutHandler::start(int hintMs)
+{
+ Q_ASSERT(timerId == -1);
+ timerId = startTimer(hintMs > 0 ? hintMs : timeoutMs, Qt::PreciseTimer);
+}
+
+void QDtlsPrivateOpenSSL::TimeoutHandler::doubleTimeout()
+{
+ if (timeoutMs * 2 < 60000)
+ timeoutMs *= 2;
+ else
+ timeoutMs = 60000;
+}
+
+void QDtlsPrivateOpenSSL::TimeoutHandler::stop()
+{
+ if (timerId != -1) {
+ killTimer(timerId);
+ timerId = -1;
+ }
+}
+
+void QDtlsPrivateOpenSSL::TimeoutHandler::timerEvent(QTimerEvent *event)
+{
+ Q_UNUSED(event)
+ Q_ASSERT(timerId != -1);
+
+ killTimer(timerId);
+ timerId = -1;
+
+ Q_ASSERT(dtlsConnection);
+ dtlsConnection->reportTimeout();
+}
+
+QDtlsPrivateOpenSSL::QDtlsPrivateOpenSSL()
+{
+ secret = dtlsutil::fallbackSecret();
+ dtls.dtlsPrivate = this;
+}
+
+bool QDtlsPrivateOpenSSL::startHandshake(QUdpSocket *socket, const QByteArray &dgram)
+{
+ Q_ASSERT(socket);
+ Q_ASSERT(handshakeState == QDtls::HandshakeNotStarted);
+
+ clearDtlsError();
+ connectionEncrypted = false;
+
+ if (!dtls.init(this, socket, remoteAddress, remotePort, dgram))
+ return false;
+
+ if (mode == QSslSocket::SslServerMode && dtlsConfiguration.dtlsCookieEnabled) {
+ dtls.secret = secret;
+ dtls.hashAlgorithm = hashAlgorithm;
+ // Let's prepare the state machine so that message sequence 1 does not
+ // surprise DTLS/OpenSSL (such a message would be disregarded as
+ // 'stale or future' in SSL_accept otherwise):
+ int result = 0;
+#if QT_CONFIG(opensslv11)
+ QSharedPointer<BIO_ADDR> peer(q_BIO_ADDR_new(), dtlsutil::delete_BIO_ADDR);
+ if (!peer.data()) {
+ setDtlsError(QDtlsError::TlsInitializationError,
+ QDtls::tr("BIO_ADD_new failed, cannot start handshake"));
+ return false;
+ }
+
+ // If it's an invalid/unexpected ClientHello, we don't want to send
+ // VerifyClientRequest - it's a job of QDtlsClientVerifier - so we
+ // suppress any attempts to write into socket:
+ dtls.writeSuppressed = true;
+ result = q_DTLSv1_listen(dtls.tlsConnection.data(), peer.data());
+ dtls.writeSuppressed = false;
+#else
+ qt_sockaddr peer;
+ result = q_DTLSv1_listen(dtls.tlsConnection.data(), &peer);
+#endif
+ if (result <= 0) {
+ setDtlsError(QDtlsError::TlsFatalError,
+ QDtls::tr("Cannot start the handshake, verified client hello expected"));
+ dtls.reset();
+ return false;
+ }
+ }
+
+ handshakeState = QDtls::HandshakeInProgress;
+ opensslErrors.clear();
+ tlsErrors.clear();
+
+ return continueHandshake(socket, dgram);
+}
+
+bool QDtlsPrivateOpenSSL::continueHandshake(QUdpSocket *socket, const QByteArray &dgram)
+{
+ Q_ASSERT(socket);
+
+ Q_ASSERT(handshakeState == QDtls::HandshakeInProgress);
+
+ clearDtlsError();
+
+ if (timeoutHandler.data())
+ timeoutHandler->stop();
+
+ if (!dtls.init(this, socket, remoteAddress, remotePort, dgram))
+ return false;
+
+ dtls.x509Errors.clear();
+
+ int result = 0;
+ if (mode == QSslSocket::SslServerMode)
+ result = q_SSL_accept(dtls.tlsConnection.data());
+ else
+ result = q_SSL_connect(dtls.tlsConnection.data());
+
+ // DTLSTODO: Investigate/test if it makes sense - QSslSocket can emit
+ // peerVerifyError at this point (and thus potentially client code
+ // will close the underlying TCP connection immediately), but we are using
+ // QUdpSocket, no connection to close, our verification callback returns 1
+ // (verified OK) and this probably means OpenSSL has already sent a reply
+ // to the server's hello/certificate.
+
+ opensslErrors << dtls.x509Errors;
+
+ if (result <= 0) {
+ const auto code = q_SSL_get_error(dtls.tlsConnection.data(), result);
+ switch (code) {
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ // DTLSTODO: to be tested - in principle, if it was the first call to
+ // continueHandshake and server for some reason discards the client
+ // hello message (even the verified one) - our 'this' will probably
+ // forever stay in this strange InProgress state? (the client
+ // will dully re-transmit the same hello and we discard it again?)
+ // SSL_get_state can provide more information about state
+ // machine and we can switch to NotStarted (since we have not
+ // replied with our hello ...)
+ if (!timeoutHandler.data()) {
+ timeoutHandler.reset(new TimeoutHandler);
+ timeoutHandler->dtlsConnection = this;
+ } else {
+ // Back to 1s.
+ timeoutHandler->resetTimeout();
+ }
+
+ timeoutHandler->start();
+
+ return true; // The handshake is not yet complete.
+ default:
+ storePeerCertificates();
+ setDtlsError(QDtlsError::TlsFatalError,
+ QSslSocketBackendPrivate::msgErrorsDuringHandshake());
+ dtls.reset();
+ handshakeState = QDtls::HandshakeNotStarted;
+ return false;
+ }
+ }
+
+ storePeerCertificates();
+ fetchNegotiatedParameters();
+
+ const bool doVerifyPeer = dtlsConfiguration.peerVerifyMode == QSslSocket::VerifyPeer
+ || (dtlsConfiguration.peerVerifyMode == QSslSocket::AutoVerifyPeer
+ && mode == QSslSocket::SslClientMode);
+
+ if (!doVerifyPeer || verifyPeer() || tlsErrorsWereIgnored()) {
+ connectionEncrypted = true;
+ handshakeState = QDtls::HandshakeComplete;
+ return true;
+ }
+
+ setDtlsError(QDtlsError::PeerVerificationError, QDtls::tr("Peer verification failed"));
+ handshakeState = QDtls::PeerVerificationFailed;
+ return false;
+}
+
+
+bool QDtlsPrivateOpenSSL::handleTimeout(QUdpSocket *socket)
+{
+ Q_ASSERT(socket);
+
+ Q_ASSERT(timeoutHandler.data());
+ Q_ASSERT(dtls.tlsConnection.data());
+
+ clearDtlsError();
+
+ dtls.udpSocket = socket;
+
+ if (q_DTLSv1_handle_timeout(dtls.tlsConnection.data()) > 0) {
+ timeoutHandler->doubleTimeout();
+ timeoutHandler->start();
+ } else {
+ timeoutHandler->start(dtlsutil::next_timeoutMs(dtls.tlsConnection.data()));
+ }
+
+ return true;
+}
+
+bool QDtlsPrivateOpenSSL::resumeHandshake(QUdpSocket *socket)
+{
+ Q_UNUSED(socket);
+ Q_ASSERT(socket);
+ Q_ASSERT(handshakeState == QDtls::PeerVerificationFailed);
+
+ clearDtlsError();
+
+ if (tlsErrorsWereIgnored()) {
+ handshakeState = QDtls::HandshakeComplete;
+ connectionEncrypted = true;
+ tlsErrors.clear();
+ tlsErrorsToIgnore.clear();
+ return true;
+ }
+
+ return false;
+}
+
+void QDtlsPrivateOpenSSL::abortHandshake(QUdpSocket *socket)
+{
+ Q_ASSERT(socket);
+ Q_ASSERT(handshakeState == QDtls::PeerVerificationFailed
+ || handshakeState == QDtls::HandshakeInProgress);
+
+ clearDtlsError();
+
+ if (handshakeState == QDtls::PeerVerificationFailed) {
+ // Yes, while peer verification failed, we were actually encrypted.
+ // Let's play it nice - inform our peer about connection shut down.
+ sendShutdownAlert(socket);
+ } else {
+ resetDtls();
+ }
+}
+
+void QDtlsPrivateOpenSSL::sendShutdownAlert(QUdpSocket *socket)
+{
+ Q_ASSERT(socket);
+
+ clearDtlsError();
+
+ if (connectionEncrypted && !connectionWasShutdown) {
+ dtls.udpSocket = socket;
+ Q_ASSERT(dtls.tlsConnection.data());
+ q_SSL_shutdown(dtls.tlsConnection.data());
+ }
+
+ resetDtls();
+}
+
+qint64 QDtlsPrivateOpenSSL::writeDatagramEncrypted(QUdpSocket *socket,
+ const QByteArray &dgram)
+{
+ Q_ASSERT(socket);
+ Q_ASSERT(dtls.tlsConnection.data());
+ Q_ASSERT(connectionEncrypted);
+
+ clearDtlsError();
+
+ dtls.udpSocket = socket;
+ const int written = q_SSL_write(dtls.tlsConnection.data(),
+ dgram.constData(), dgram.size());
+ if (written > 0)
+ return written;
+
+ const unsigned long errorCode = q_ERR_get_error();
+ if (!dgram.size() && errorCode == SSL_ERROR_NONE) {
+ // With OpenSSL <= 1.1 this can happen. For example, DTLS client
+ // tries to reconnect (while re-using the same address/port) -
+ // DTLS server drops a message with unexpected epoch but says - no
+ // error. We leave to client code to resolve such problems until
+ // OpenSSL provides something better.
+ return 0;
+ }
+
+ switch (errorCode) {
+ case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_WANT_READ:
+ // We do not set any error/description ... a user can probably re-try
+ // sending a datagram.
+ break;
+ case SSL_ERROR_ZERO_RETURN:
+ connectionWasShutdown = true;
+ setDtlsError(QDtlsError::TlsFatalError, QDtls::tr("The DTLS connection has been closed"));
+ handshakeState = QDtls::HandshakeNotStarted;
+ dtls.reset();
+ break;
+ case SSL_ERROR_SYSCALL:
+ case SSL_ERROR_SSL:
+ default:
+ // DTLSTODO: we don't know yet what to do. Tests needed - probably,
+ // some errors can be just ignored (it's UDP, not TCP after all).
+ // Unlike QSslSocket we do not abort though.
+ QString description(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+ if (socket->error() != QAbstractSocket::UnknownSocketError && description.isEmpty()) {
+ setDtlsError(QDtlsError::UnderlyingSocketError, socket->errorString());
+ } else {
+ setDtlsError(QDtlsError::TlsFatalError,
+ QDtls::tr("Error while writing: %1").arg(description));
+ }
+ }
+
+ return -1;
+}
+
+QByteArray QDtlsPrivateOpenSSL::decryptDatagram(QUdpSocket *socket, const QByteArray &tlsdgram)
+{
+ Q_ASSERT(socket);
+ Q_ASSERT(tlsdgram.size());
+
+ Q_ASSERT(dtls.tlsConnection.data());
+ Q_ASSERT(connectionEncrypted);
+
+ dtls.dgram = tlsdgram;
+ dtls.udpSocket = socket;
+
+ clearDtlsError();
+
+ QByteArray dgram;
+ dgram.resize(tlsdgram.size());
+ const int read = q_SSL_read(dtls.tlsConnection.data(), dgram.data(),
+ dgram.size());
+
+ if (read > 0) {
+ dgram.resize(read);
+ return dgram;
+ }
+
+ dgram.clear();
+ unsigned long errorCode = q_ERR_get_error();
+ if (errorCode == SSL_ERROR_NONE) {
+ const int shutdown = q_SSL_get_shutdown(dtls.tlsConnection.data());
+ if (shutdown & SSL_RECEIVED_SHUTDOWN)
+ errorCode = SSL_ERROR_ZERO_RETURN;
+ else
+ return dgram;
+ }
+
+ switch (errorCode) {
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ return dgram;
+ case SSL_ERROR_ZERO_RETURN:
+ // "The connection was shut down cleanly" ... hmm, whatever,
+ // needs testing (DTLSTODO).
+ connectionWasShutdown = true;
+ setDtlsError(QDtlsError::RemoteClosedConnectionError,
+ QDtls::tr("The DTLS connection has been shutdown"));
+ dtls.reset();
+ connectionEncrypted = false;
+ handshakeState = QDtls::HandshakeNotStarted;
+ return dgram;
+ case SSL_ERROR_SYSCALL: // some IO error
+ case SSL_ERROR_SSL: // error in the SSL library
+ // DTLSTODO: Apparently, some errors can be ignored, for example,
+ // ECONNRESET etc. This all needs a lot of testing!!!
+ default:
+ setDtlsError(QDtlsError::TlsNonFatalError,
+ QDtls::tr("Error while reading: %1")
+ .arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()));
+ return dgram;
+ }
+}
+
+unsigned QDtlsPrivateOpenSSL::pskClientCallback(const char *hint, char *identity,
+ unsigned max_identity_len,
+ unsigned char *psk,
+ unsigned max_psk_len)
+{
+ // The code below is taken (with some modifications) from qsslsocket_openssl
+ // - alas, we cannot simply re-use it, it's in QSslSocketPrivate.
+
+ Q_Q(QDtls);
+
+ {
+ QSslPreSharedKeyAuthenticator authenticator;
+ // Fill in some read-only fields (for client code)
+ if (hint) {
+ identityHint.clear();
+ identityHint.append(hint);
+ // From the original code in QSslSocket:
+ // "it's NULL terminated, but do not include the NULL" == this fromRawData(ptr/size).
+ authenticator.d->identityHint = QByteArray::fromRawData(identityHint.constData(),
+ int(std::strlen(hint)));
+ }
+
+ authenticator.d->maximumIdentityLength = int(max_identity_len) - 1; // needs to be NULL terminated
+ authenticator.d->maximumPreSharedKeyLength = int(max_psk_len);
+
+ pskAuthenticator.swap(authenticator);
+ }
+
+ // Let the client provide the remaining bits...
+ emit q->pskRequired(&pskAuthenticator);
+
+ // No PSK set? Return now to make the handshake fail
+ if (pskAuthenticator.preSharedKey().isEmpty())
+ return 0;
+
+ // Copy data back into OpenSSL
+ const int identityLength = qMin(pskAuthenticator.identity().length(),
+ pskAuthenticator.maximumIdentityLength());
+ std::memcpy(identity, pskAuthenticator.identity().constData(), identityLength);
+ identity[identityLength] = 0;
+
+ const int pskLength = qMin(pskAuthenticator.preSharedKey().length(),
+ pskAuthenticator.maximumPreSharedKeyLength());
+ std::memcpy(psk, pskAuthenticator.preSharedKey().constData(), pskLength);
+
+ return pskLength;
+}
+
+unsigned QDtlsPrivateOpenSSL::pskServerCallback(const char *identity, unsigned char *psk,
+ unsigned max_psk_len)
+{
+ Q_Q(QDtls);
+
+ {
+ QSslPreSharedKeyAuthenticator authenticator;
+ // Fill in some read-only fields (for the user)
+ authenticator.d->identityHint = dtlsConfiguration.preSharedKeyIdentityHint;
+ authenticator.d->identity = identity;
+ authenticator.d->maximumIdentityLength = 0; // user cannot set an identity
+ authenticator.d->maximumPreSharedKeyLength = int(max_psk_len);
+
+ pskAuthenticator.swap(authenticator);
+ }
+
+ // Let the client provide the remaining bits...
+ emit q->pskRequired(&pskAuthenticator);
+
+ // No PSK set? Return now to make the handshake fail
+ if (pskAuthenticator.preSharedKey().isEmpty())
+ return 0;
+
+ // Copy data back into OpenSSL
+ const int pskLength = qMin(pskAuthenticator.preSharedKey().length(),
+ pskAuthenticator.maximumPreSharedKeyLength());
+
+ std::memcpy(psk, pskAuthenticator.preSharedKey().constData(), pskLength);
+
+ return pskLength;
+}
+
+// The definition is located in qsslsocket_openssl.cpp.
+QSslError _q_OpenSSL_to_QSslError(int errorCode, const QSslCertificate &cert);
+
+bool QDtlsPrivateOpenSSL::verifyPeer()
+{
+ // DTLSTODO: Windows-specific code for CA fetcher is not here yet.
+ QVector<QSslError> errors;
+
+ // Check the whole chain for blacklisting (including root, as we check for
+ // subjectInfo and issuer)
+ for (const QSslCertificate &cert : qAsConst(dtlsConfiguration.peerCertificateChain)) {
+ if (QSslCertificatePrivate::isBlacklisted(cert))
+ errors << QSslError(QSslError::CertificateBlacklisted, cert);
+ }
+
+ if (dtlsConfiguration.peerCertificate.isNull()) {
+ errors << QSslError(QSslError::NoPeerCertificate);
+ } else if (mode == QSslSocket::SslClientMode) {
+ // Check the peer certificate itself. First try the subject's common name
+ // (CN) as a wildcard, then try all alternate subject name DNS entries the
+ // same way.
+
+ // QSslSocket has a rather twisted logic: if verificationPeerName
+ // is empty, we call QAbstractSocket::peerName(), which returns
+ // either peerName (can be set by setPeerName) or host name
+ // (can be set as a result of connectToHost).
+ QString name = peerVerificationName;
+ if (name.isEmpty()) {
+ Q_ASSERT(dtls.udpSocket);
+ name = dtls.udpSocket->peerName();
+ }
+
+ if (!QSslSocketPrivate::isMatchingHostname(dtlsConfiguration.peerCertificate, name))
+ errors << QSslError(QSslError::HostNameMismatch, dtlsConfiguration.peerCertificate);
+ }
+
+ // Translate errors from the error list into QSslErrors
+ errors.reserve(errors.size() + opensslErrors.size());
+ for (const auto &error : qAsConst(opensslErrors)) {
+ errors << _q_OpenSSL_to_QSslError(error.code,
+ dtlsConfiguration.peerCertificateChain.value(error.depth));
+ }
+
+ tlsErrors = errors;
+ return tlsErrors.isEmpty();
+}
+
+void QDtlsPrivateOpenSSL::storePeerCertificates()
+{
+ Q_ASSERT(dtls.tlsConnection.data());
+ // Store the peer certificate and chain. For clients, the peer certificate
+ // chain includes the peer certificate; for servers, it doesn't. Both the
+ // peer certificate and the chain may be empty if the peer didn't present
+ // any certificate.
+ X509 *x509 = q_SSL_get_peer_certificate(dtls.tlsConnection.data());
+ dtlsConfiguration.peerCertificate = QSslCertificatePrivate::QSslCertificate_from_X509(x509);
+ q_X509_free(x509);
+ if (dtlsConfiguration.peerCertificateChain.isEmpty()) {
+ auto stack = q_SSL_get_peer_cert_chain(dtls.tlsConnection.data());
+ dtlsConfiguration.peerCertificateChain = QSslSocketBackendPrivate::STACKOFX509_to_QSslCertificates(stack);
+ if (!dtlsConfiguration.peerCertificate.isNull() && mode == QSslSocket::SslServerMode)
+ dtlsConfiguration.peerCertificateChain.prepend(dtlsConfiguration.peerCertificate);
+ }
+}
+
+bool QDtlsPrivateOpenSSL::tlsErrorsWereIgnored() const
+{
+ // check whether the errors we got are all in the list of expected errors
+ // (applies only if the method QDtlsConnection::ignoreTlsErrors(const
+ // QVector<QSslError> &errors) was called)
+ for (const QSslError &error : tlsErrors) {
+ if (!tlsErrorsToIgnore.contains(error))
+ return false;
+ }
+
+ return !tlsErrorsToIgnore.empty();
+}
+
+void QDtlsPrivateOpenSSL::fetchNegotiatedParameters()
+{
+ Q_ASSERT(dtls.tlsConnection.data());
+
+ const SSL_CIPHER *cipher = q_SSL_get_current_cipher(dtls.tlsConnection.data());
+ sessionCipher = cipher ? QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(cipher)
+ : QSslCipher();
+
+ // Note: cipher's protocol version will be reported as either TLS 1.0 or
+ // TLS 1.2, that's how it's set by OpenSSL (and that's what they are?).
+
+ switch (q_SSL_version(dtls.tlsConnection.data())) {
+ case DTLS1_VERSION:
+ sessionProtocol = QSsl::DtlsV1_0;
+ break;
+ case DTLS1_2_VERSION:
+ sessionProtocol = QSsl::DtlsV1_2;
+ break;
+ default:
+ qCWarning(lcSsl, "unknown protocol version");
+ sessionProtocol = QSsl::UnknownProtocol;
+ }
+}
+
+void QDtlsPrivateOpenSSL::reportTimeout()
+{
+ Q_Q(QDtls);
+
+ emit q->handshakeTimeout();
+}
+
+void QDtlsPrivateOpenSSL::resetDtls()
+{
+ dtls.reset();
+ connectionEncrypted = false;
+ tlsErrors.clear();
+ tlsErrorsToIgnore.clear();
+ dtlsConfiguration.peerCertificate.clear();
+ dtlsConfiguration.peerCertificateChain.clear();
+ connectionWasShutdown = false;
+ handshakeState = QDtls::HandshakeNotStarted;
+ sessionCipher = {};
+ sessionProtocol = QSsl::UnknownProtocol;
+}
+
+QT_END_NAMESPACE
diff --git a/src/network/ssl/qdtls_openssl_p.h b/src/network/ssl/qdtls_openssl_p.h
new file mode 100644
index 0000000000..9306fa2433
--- /dev/null
+++ b/src/network/ssl/qdtls_openssl_p.h
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 QDTLS_OPENSSL_P_H
+#define QDTLS_OPENSSL_P_H
+
+#include <private/qtnetworkglobal_p.h>
+
+#include <QtCore/qglobal.h>
+
+#include <openssl/ossl_typ.h>
+
+#include "qdtls_p.h"
+
+#include <private/qsslcontext_openssl_p.h>
+#include <private/qsslsocket_openssl_p.h>
+
+#include <QtNetwork/qsslpresharedkeyauthenticator.h>
+#include <QtNetwork/qhostaddress.h>
+
+#include <QtCore/qcryptographichash.h>
+#include <QtCore/qsharedpointer.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qvector.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.
+//
+
+QT_REQUIRE_CONFIG(openssl);
+QT_REQUIRE_CONFIG(dtls);
+
+QT_BEGIN_NAMESPACE
+
+class QDtlsPrivateOpenSSL;
+class QUdpSocket;
+
+namespace dtlsopenssl
+{
+
+class DtlsState
+{
+public:
+ // Note, bioMethod, if allocated (i.e. OpenSSL version >= 1.1) _must_
+ // outlive BIOs it was used to create. Thus the order of declarations
+ // here matters.
+ using BioMethod = QSharedPointer<BIO_METHOD>;
+ BioMethod bioMethod;
+
+ using TlsContext = QSharedPointer<QSslContext>;
+ TlsContext tlsContext;
+
+ using TlsConnection = QSharedPointer<SSL>;
+ TlsConnection tlsConnection;
+
+ QByteArray dgram;
+
+ QHostAddress remoteAddress;
+ quint16 remotePort = 0;
+
+ QVector<QSslErrorEntry> x509Errors;
+
+ long peeking = false;
+ QUdpSocket *udpSocket = nullptr;
+ bool writeSuppressed = false;
+
+ bool init(QDtlsBasePrivate *dtlsBase, QUdpSocket *socket,
+ const QHostAddress &remote, quint16 port,
+ const QByteArray &receivedMessage);
+
+ void reset();
+
+ QDtlsPrivateOpenSSL *dtlsPrivate = nullptr;
+ QByteArray secret;
+
+#ifdef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
+ QCryptographicHash::Algorithm hashAlgorithm = QCryptographicHash::Sha1;
+#else
+ QCryptographicHash::Algorithm hashAlgorithm = QCryptographicHash::Sha256;
+#endif
+
+private:
+
+ bool initTls(QDtlsBasePrivate *dtlsBase);
+ bool initCtxAndConnection(QDtlsBasePrivate *dtlsBase);
+ bool initBIO(QDtlsBasePrivate *dtlsBase);
+ void setLinkMtu(QDtlsBasePrivate *dtlsBase);
+};
+
+} // namespace dtlsopenssl
+
+class QDtlsClientVerifierOpenSSL : public QDtlsClientVerifierPrivate
+{
+public:
+
+ QDtlsClientVerifierOpenSSL();
+
+ bool verifyClient(QUdpSocket *socket, const QByteArray &dgram,
+ const QHostAddress &address, quint16 port) override;
+
+private:
+ dtlsopenssl::DtlsState dtls;
+};
+
+class QDtlsPrivateOpenSSL : public QDtlsPrivate
+{
+public:
+ QDtlsPrivateOpenSSL();
+
+ bool startHandshake(QUdpSocket *socket, const QByteArray &datagram) override;
+ bool continueHandshake(QUdpSocket *socket, const QByteArray &datagram) override;
+ bool resumeHandshake(QUdpSocket *socket) override;
+ void abortHandshake(QUdpSocket *socket) override;
+ bool handleTimeout(QUdpSocket *socket) override;
+ void sendShutdownAlert(QUdpSocket *socket) override;
+
+ qint64 writeDatagramEncrypted(QUdpSocket *socket, const QByteArray &datagram) override;
+ QByteArray decryptDatagram(QUdpSocket *socket, const QByteArray &tlsdgram) override;
+
+ unsigned pskClientCallback(const char *hint, char *identity, unsigned max_identity_len,
+ unsigned char *psk, unsigned max_psk_len);
+ unsigned pskServerCallback(const char *identity, unsigned char *psk,
+ unsigned max_psk_len);
+
+private:
+
+ bool verifyPeer();
+ void storePeerCertificates();
+ bool tlsErrorsWereIgnored() const;
+ void fetchNegotiatedParameters();
+ void reportTimeout();
+ void resetDtls();
+
+ QVector<QSslErrorEntry> opensslErrors;
+ dtlsopenssl::DtlsState dtls;
+
+ // We have to externally handle timeouts since we have non-blocking
+ // sockets and OpenSSL(DTLS) with non-blocking UDP sockets does not
+ // know if a timeout has occurred.
+ struct TimeoutHandler : QObject
+ {
+ TimeoutHandler() = default;
+
+ void start(int hintMs = 0);
+ void doubleTimeout();
+ void resetTimeout() {timeoutMs = 1000;}
+ void stop();
+ void timerEvent(QTimerEvent *event);
+
+ int timerId = -1;
+ int timeoutMs = 1000;
+
+ QDtlsPrivateOpenSSL *dtlsConnection = nullptr;
+ };
+
+ // We will initialize it 'lazily', just in case somebody wants to move
+ // QDtls to another thread.
+ QScopedPointer<TimeoutHandler> timeoutHandler;
+ bool connectionWasShutdown = false;
+ QSslPreSharedKeyAuthenticator pskAuthenticator;
+ QByteArray identityHint;
+
+ Q_DECLARE_PUBLIC(QDtls)
+};
+
+
+
+QT_END_NAMESPACE
+
+#endif // QDTLS_OPENSSL_P_H
diff --git a/src/network/ssl/qdtls_p.h b/src/network/ssl/qdtls_p.h
new file mode 100644
index 0000000000..bdc001502b
--- /dev/null
+++ b/src/network/ssl/qdtls_p.h
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 QDTLS_P_H
+#define QDTLS_P_H
+
+#include <private/qtnetworkglobal_p.h>
+
+#include "qdtls.h"
+
+#include <private/qsslconfiguration_p.h>
+#include <private/qobject_p.h>
+
+#include <QtNetwork/qabstractsocket.h>
+#include <QtNetwork/qhostaddress.h>
+#include <QtNetwork/qsslsocket.h>
+#include <QtNetwork/qsslcipher.h>
+#include <QtNetwork/qssl.h>
+
+#include <QtCore/qcryptographichash.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qstring.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.
+//
+
+QT_REQUIRE_CONFIG(dtls);
+
+QT_BEGIN_NAMESPACE
+
+class QHostAddress;
+
+class QDtlsBasePrivate : public QObjectPrivate
+{
+public:
+
+ void setDtlsError(QDtlsError code, const QString &description)
+ {
+ errorCode = code;
+ errorDescription = description;
+ }
+
+ void clearDtlsError()
+ {
+ errorCode = QDtlsError::NoError;
+ errorDescription.clear();
+ }
+
+ void setConfiguration(const QSslConfiguration &configuration);
+ QSslConfiguration configuration() const;
+
+ bool setCookieGeneratorParameters(QCryptographicHash::Algorithm alg,
+ const QByteArray &secret);
+
+ static bool isDtlsProtocol(QSsl::SslProtocol protocol);
+
+ QHostAddress remoteAddress;
+ quint16 remotePort = 0;
+ quint16 mtuHint = 0;
+
+ QDtlsError errorCode = QDtlsError::NoError;
+ QString errorDescription;
+ QSslConfigurationPrivate dtlsConfiguration;
+ QSslSocket::SslMode mode = QSslSocket::SslClientMode;
+ QSslCipher sessionCipher;
+ QSsl::SslProtocol sessionProtocol = QSsl::UnknownProtocol;
+ QString peerVerificationName;
+ QByteArray secret;
+
+#ifdef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
+ QCryptographicHash::Algorithm hashAlgorithm = QCryptographicHash::Sha1;
+#else
+ QCryptographicHash::Algorithm hashAlgorithm = QCryptographicHash::Sha256;
+#endif
+};
+
+class QDtlsClientVerifierPrivate : public QDtlsBasePrivate
+{
+public:
+
+ QByteArray verifiedClientHello;
+
+ virtual bool verifyClient(QUdpSocket *socket, const QByteArray &dgram,
+ const QHostAddress &address, quint16 port) = 0;
+};
+
+class QDtlsPrivate : public QDtlsBasePrivate
+{
+public:
+
+ virtual bool startHandshake(QUdpSocket *socket, const QByteArray &dgram) = 0;
+ virtual bool handleTimeout(QUdpSocket *socket) = 0;
+ virtual bool continueHandshake(QUdpSocket *socket, const QByteArray &dgram) = 0;
+ virtual bool resumeHandshake(QUdpSocket *socket) = 0;
+ virtual void abortHandshake(QUdpSocket *socket) = 0;
+ virtual void sendShutdownAlert(QUdpSocket *socket) = 0;
+
+ virtual qint64 writeDatagramEncrypted(QUdpSocket *socket, const QByteArray &dgram) = 0;
+ virtual QByteArray decryptDatagram(QUdpSocket *socket, const QByteArray &dgram) = 0;
+
+ QDtls::HandshakeState handshakeState = QDtls::HandshakeNotStarted;
+
+ QVector<QSslError> tlsErrors;
+ QVector<QSslError> tlsErrorsToIgnore;
+
+ bool connectionEncrypted = false;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDTLS_P_H
diff --git a/src/network/ssl/qpassworddigestor.cpp b/src/network/ssl/qpassworddigestor.cpp
new file mode 100644
index 0000000000..127d94e849
--- /dev/null
+++ b/src/network/ssl/qpassworddigestor.cpp
@@ -0,0 +1,187 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 "qpassworddigestor.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QMessageAuthenticationCode>
+#include <QtCore/QtEndian>
+
+#include <limits>
+
+QT_BEGIN_NAMESPACE
+namespace QPasswordDigestor {
+
+/*!
+ \namespace QPasswordDigestor
+ \inmodule QtNetwork
+
+ \brief The QPasswordDigestor namespace contains functions which you can use
+ to generate hashes or keys.
+*/
+
+/*!
+ \since 5.12
+
+ Returns a hash computed using the PBKDF1-algorithm as defined in
+ \l {https://tools.ietf.org/html/rfc8018#section-5.1} {RFC 8018}.
+
+ The function takes the \a data and \a salt, and then hashes it repeatedly
+ for \a iterations iterations using the specified hash \a algorithm. If the
+ resulting hash is longer than \a dkLen then it is truncated before it is
+ returned.
+
+ This function only supports SHA-1 and MD5! The max output size is 160 bits
+ (20 bytes) when using SHA-1, or 128 bits (16 bytes) when using MD5.
+ Specifying a value for \a dkLen which is greater than this results in a
+ warning and an empty QByteArray is returned. To programmatically check this
+ limit you can use \l {QCryptographicHash::hashLength}. Furthermore: the
+ \a salt must always be 8 bytes long!
+
+ \note This function is provided for use with legacy applications and all
+ new applications are recommended to use \l {pbkdf2} {PBKDF2}.
+
+ \sa deriveKeyPbkdf2, QCryptographicHash, QCryptographicHash::hashLength
+*/
+Q_NETWORK_EXPORT QByteArray deriveKeyPbkdf1(QCryptographicHash::Algorithm algorithm,
+ const QByteArray &data, const QByteArray &salt,
+ int iterations, quint64 dkLen)
+{
+ // https://tools.ietf.org/html/rfc8018#section-5.1
+
+ if (algorithm != QCryptographicHash::Sha1
+#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
+ && algorithm != QCryptographicHash::Md5
+#endif
+ ) {
+ qWarning("The only supported algorithms for pbkdf1 are SHA-1 and MD5!");
+ return QByteArray();
+ }
+
+ if (salt.size() != 8) {
+ qWarning("The salt must be 8 bytes long!");
+ return QByteArray();
+ }
+ if (iterations < 1 || dkLen < 1)
+ return QByteArray();
+
+ if (dkLen > quint64(QCryptographicHash::hashLength(algorithm))) {
+ qWarning() << "Derived key too long:\n"
+ << algorithm << "was chosen which produces output of length"
+ << QCryptographicHash::hashLength(algorithm) << "but" << dkLen
+ << "was requested.";
+ return QByteArray();
+ }
+
+ QCryptographicHash hash(algorithm);
+ hash.addData(data);
+ hash.addData(salt);
+ QByteArray key = hash.result();
+
+ for (int i = 1; i < iterations; i++) {
+ hash.reset();
+ hash.addData(key);
+ key = hash.result();
+ }
+ return key.left(dkLen);
+}
+
+/*!
+ \since 5.12
+
+ Derive a key using the PBKDF2-algorithm as defined in
+ \l {https://tools.ietf.org/html/rfc8018#section-5.2} {RFC 8018}.
+
+ This function takes the \a data and \a salt, and then applies HMAC-X, where
+ the X is \a algorithm, repeatedly. It internally concatenates intermediate
+ results to the final output until at least \a dkLen amount of bytes have
+ been computed and it will execute HMAC-X \a iterations times each time a
+ concatenation is required. The total number of times it will execute HMAC-X
+ depends on \a iterations, \a dkLen and \a algorithm and can be calculated
+ as
+ \c{iterations * ceil(dkLen / QCryptographicHash::hashLength(algorithm))}.
+
+ \sa deriveKeyPbkdf1, QMessageAuthenticationCode, QCryptographicHash
+*/
+Q_NETWORK_EXPORT QByteArray deriveKeyPbkdf2(QCryptographicHash::Algorithm algorithm,
+ const QByteArray &data, const QByteArray &salt,
+ int iterations, quint64 dkLen)
+{
+ // https://tools.ietf.org/html/rfc8018#section-5.2
+
+ // The RFC recommends checking that 'dkLen' is not greater than '(2^32 - 1) * hLen'
+ int hashLen = QCryptographicHash::hashLength(algorithm);
+ const quint64 maxLen = quint64(std::numeric_limits<quint32>::max() - 1) * hashLen;
+ if (dkLen > maxLen) {
+ qWarning().nospace() << "Derived key too long:\n"
+ << algorithm << " was chosen which produces output of length "
+ << maxLen << " but " << dkLen << " was requested.";
+ return QByteArray();
+ }
+
+ if (iterations < 1 || dkLen < 1)
+ return QByteArray();
+
+ QByteArray key;
+ quint32 currentIteration = 1;
+ QMessageAuthenticationCode hmac(algorithm, data);
+ QByteArray index(4, Qt::Uninitialized);
+ while (quint64(key.length()) < dkLen) {
+ hmac.addData(salt);
+
+ qToBigEndian(currentIteration, index.data());
+ hmac.addData(index);
+
+ QByteArray u = hmac.result();
+ hmac.reset();
+ QByteArray tkey = u;
+ for (int iter = 1; iter < iterations; iter++) {
+ hmac.addData(u);
+ u = hmac.result();
+ hmac.reset();
+ std::transform(tkey.cbegin(), tkey.cend(), u.cbegin(), tkey.begin(),
+ std::bit_xor<char>());
+ }
+ key += tkey;
+ currentIteration++;
+ }
+ return key.left(dkLen);
+}
+} // namespace QPasswordDigestor
+QT_END_NAMESPACE
diff --git a/src/network/ssl/qpassworddigestor.h b/src/network/ssl/qpassworddigestor.h
new file mode 100644
index 0000000000..0f88643298
--- /dev/null
+++ b/src/network/ssl/qpassworddigestor.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 QPASSWORDDIGESTOR_H
+#define QPASSWORDDIGESTOR_H
+
+#include <QtNetwork/qtnetworkglobal.h>
+#include <QtCore/QByteArray>
+#include <QtCore/QCryptographicHash>
+
+QT_BEGIN_NAMESPACE
+
+namespace QPasswordDigestor {
+Q_NETWORK_EXPORT QByteArray deriveKeyPbkdf1(QCryptographicHash::Algorithm algorithm,
+ const QByteArray &password, const QByteArray &salt,
+ int iterations, quint64 dkLen);
+Q_NETWORK_EXPORT QByteArray deriveKeyPbkdf2(QCryptographicHash::Algorithm algorithm,
+ const QByteArray &password, const QByteArray &salt,
+ int iterations, quint64 dkLen);
+} // namespace QPasswordDigestor
+
+QT_END_NAMESPACE
+
+#endif // QPASSWORDDIGESTOR_H
diff --git a/src/network/ssl/qssl.cpp b/src/network/ssl/qssl.cpp
index 51779dec33..3a0983e8b5 100644
--- a/src/network/ssl/qssl.cpp
+++ b/src/network/ssl/qssl.cpp
@@ -125,6 +125,10 @@ Q_LOGGING_CATEGORY(lcSsl, "qt.network.ssl");
\value TlsV1_1OrLater TLSv1.1 and later versions. This option is not available when using the WinRT backend due to platform limitations.
\value TlsV1_2 TLSv1.2. When using the WinRT backend this option will also enable TLSv1.0 and TLSv1.1.
\value TlsV1_2OrLater TLSv1.2 and later versions. This option is not available when using the WinRT backend due to platform limitations.
+ \value DtlsV1_0 DTLSv1.0
+ \value DtlsV1_0OrLater DTLSv1.0 and later versions.
+ \value DtlsV1_2 DTLSv1.2
+ \value DtlsV1_2OrLater DTLSv1.2 and later versions.
\value UnknownProtocol The cipher's protocol cannot be determined.
\value AnyProtocol The socket understands SSLv2, SSLv3, TLSv1.0 and all
supported later versions of TLS. This value is used by QSslSocket only.
diff --git a/src/network/ssl/qssl.h b/src/network/ssl/qssl.h
index c2a468c97c..dd268cd86d 100644
--- a/src/network/ssl/qssl.h
+++ b/src/network/ssl/qssl.h
@@ -91,6 +91,13 @@ namespace QSsl {
TlsV1_1OrLater,
TlsV1_2OrLater,
+#if QT_CONFIG(dtls) || defined(Q_CLANG_QDOC)
+ DtlsV1_0,
+ DtlsV1_0OrLater,
+ DtlsV1_2,
+ DtlsV1_2OrLater,
+#endif
+
UnknownProtocol = -1
};
diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp
index 9ddcb70b1d..d153e0b929 100644
--- a/src/network/ssl/qsslcertificate.cpp
+++ b/src/network/ssl/qsslcertificate.cpp
@@ -125,7 +125,9 @@
#include "qssl_p.h"
#include "qsslcertificate.h"
#include "qsslcertificate_p.h"
+#ifndef QT_NO_SSL
#include "qsslkey_p.h"
+#endif
#include <QtCore/qdir.h>
#include <QtCore/qdiriterator.h>
@@ -142,8 +144,12 @@ QT_BEGIN_NAMESPACE
QSslCertificate::QSslCertificate(QIODevice *device, QSsl::EncodingFormat format)
: d(new QSslCertificatePrivate)
{
+#ifndef QT_NO_OPENSSL
QSslSocketPrivate::ensureInitialized();
if (device && QSslSocket::supportsSsl())
+#else
+ if (device)
+#endif
d->init(device->readAll(), format);
}
@@ -156,8 +162,10 @@ QSslCertificate::QSslCertificate(QIODevice *device, QSsl::EncodingFormat format)
QSslCertificate::QSslCertificate(const QByteArray &data, QSsl::EncodingFormat format)
: d(new QSslCertificatePrivate)
{
+#ifndef QT_NO_OPENSSL
QSslSocketPrivate::ensureInitialized();
if (QSslSocket::supportsSsl())
+#endif
d->init(data, format);
}
@@ -557,6 +565,8 @@ QList<QSslCertificate> QSslCertificate::fromData(const QByteArray &data, QSsl::E
: QSslCertificatePrivate::certificatesFromDer(data);
}
+#ifndef QT_NO_SSL
+
/*!
Verifies a certificate chain. The chain to be verified is passed in the
\a certificateChain parameter. The first certificate in the list should
@@ -600,6 +610,8 @@ bool QSslCertificate::importPkcs12(QIODevice *device,
return QSslSocketBackendPrivate::importPkcs12(device, key, certificate, caCertificates, passPhrase);
}
+#endif
+
// These certificates are known to be fraudulent and were created during the comodo
// compromise. See http://www.comodo.com/Comodo-Fraud-Incident-2011-03-23.html
static const char *const certificate_blacklist[] = {
@@ -647,12 +659,12 @@ static const char *const certificate_blacklist[] = {
"27:83", "NIC Certifying Authority", // intermediate certificate from NIC India (2007)
"27:92", "NIC CA 2011", // intermediate certificate from NIC India (2011)
"27:b1", "NIC CA 2014", // intermediate certificate from NIC India (2014)
- 0
+ nullptr
};
bool QSslCertificatePrivate::isBlacklisted(const QSslCertificate &certificate)
{
- for (int a = 0; certificate_blacklist[a] != 0; a++) {
+ for (int a = 0; certificate_blacklist[a] != nullptr; a++) {
QString blacklistedCommonName = QString::fromUtf8(certificate_blacklist[(a+1)]);
if (certificate.serialNumber() == certificate_blacklist[a++] &&
(certificate.subjectInfo(QSslCertificate::CommonName).contains(blacklistedCommonName) ||
@@ -680,6 +692,56 @@ QByteArray QSslCertificatePrivate::subjectInfoToString(QSslCertificate::SubjectI
}
/*!
+ \since 5.12
+
+ Returns a name that describes the issuer. It returns the QSslCertificate::CommonName
+ if available, otherwise falls back to the first QSslCertificate::Organization or the
+ first QSslCertificate::OrganizationalUnitName.
+
+ \sa issuerInfo()
+*/
+QString QSslCertificate::issuerDisplayName() const
+{
+ QStringList names;
+ names = issuerInfo(QSslCertificate::CommonName);
+ if (!names.isEmpty())
+ return names.first();
+ names = issuerInfo(QSslCertificate::Organization);
+ if (!names.isEmpty())
+ return names.first();
+ names = issuerInfo(QSslCertificate::OrganizationalUnitName);
+ if (!names.isEmpty())
+ return names.first();
+
+ return QString();
+}
+
+/*!
+ \since 5.12
+
+ Returns a name that describes the subject. It returns the QSslCertificate::CommonName
+ if available, otherwise falls back to the first QSslCertificate::Organization or the
+ first QSslCertificate::OrganizationalUnitName.
+
+ \sa subjectInfo()
+*/
+QString QSslCertificate::subjectDisplayName() const
+{
+ QStringList names;
+ names = subjectInfo(QSslCertificate::CommonName);
+ if (!names.isEmpty())
+ return names.first();
+ names = subjectInfo(QSslCertificate::Organization);
+ if (!names.isEmpty())
+ return names.first();
+ names = subjectInfo(QSslCertificate::OrganizationalUnitName);
+ if (!names.isEmpty())
+ return names.first();
+
+ return QString();
+}
+
+/*!
\fn uint qHash(const QSslCertificate &key, uint seed)
Returns the hash value for the \a key, using \a seed to seed the calculation.
@@ -696,8 +758,8 @@ QDebug operator<<(QDebug debug, const QSslCertificate &certificate)
<< certificate.version()
<< ", " << certificate.serialNumber()
<< ", " << certificate.digest().toBase64()
- << ", " << certificate.issuerInfo(QSslCertificate::Organization)
- << ", " << certificate.subjectInfo(QSslCertificate::Organization)
+ << ", " << certificate.issuerDisplayName()
+ << ", " << certificate.subjectDisplayName()
<< ", " << certificate.subjectAlternativeNames()
#if QT_CONFIG(datestring)
<< ", " << certificate.effectiveDate()
diff --git a/src/network/ssl/qsslcertificate.h b/src/network/ssl/qsslcertificate.h
index 6cd66fd20f..266fcdacb4 100644
--- a/src/network/ssl/qsslcertificate.h
+++ b/src/network/ssl/qsslcertificate.h
@@ -55,8 +55,6 @@
#include <QtCore/qmap.h>
#include <QtNetwork/qssl.h>
-#ifndef QT_NO_SSL
-
QT_BEGIN_NAMESPACE
class QDateTime;
@@ -122,6 +120,9 @@ public:
QStringList issuerInfo(const QByteArray &attribute) const;
QStringList subjectInfo(SubjectInfo info) const;
QStringList subjectInfo(const QByteArray &attribute) const;
+ QString issuerDisplayName() const;
+ QString subjectDisplayName() const;
+
QList<QByteArray> subjectInfoAttributes() const;
QList<QByteArray> issuerInfoAttributes() const;
#if QT_DEPRECATED_SINCE(5,0)
@@ -131,7 +132,9 @@ public:
QMultiMap<QSsl::AlternativeNameEntryType, QString> subjectAlternativeNames() const;
QDateTime effectiveDate() const;
QDateTime expiryDate() const;
+#ifndef QT_NO_SSL
QSslKey publicKey() const;
+#endif
QList<QSslCertificateExtension> extensions() const;
QByteArray toPem() const;
@@ -146,6 +149,7 @@ public:
static QList<QSslCertificate> fromData(
const QByteArray &data, QSsl::EncodingFormat format = QSsl::Pem);
+#ifndef QT_NO_SSL
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
static QList<QSslError> verify(const QList<QSslCertificate> &certificateChain, const QString &hostName = QString());
#else
@@ -156,6 +160,7 @@ public:
QSslKey *key, QSslCertificate *cert,
QList<QSslCertificate> *caCertificates = nullptr,
const QByteArray &passPhrase=QByteArray());
+#endif
Qt::HANDLE handle() const;
@@ -178,6 +183,4 @@ QT_END_NAMESPACE
Q_DECLARE_METATYPE(QSslCertificate)
-#endif // QT_NO_SSL
-
#endif
diff --git a/src/network/ssl/qsslcertificate_openssl.cpp b/src/network/ssl/qsslcertificate_openssl.cpp
index fce150d79d..fa87cfeaaf 100644
--- a/src/network/ssl/qsslcertificate_openssl.cpp
+++ b/src/network/ssl/qsslcertificate_openssl.cpp
@@ -44,8 +44,9 @@
#include "qsslkey_p.h"
#include "qsslcertificateextension_p.h"
+#if QT_CONFIG(thread)
#include <QtCore/private/qmutexpool_p.h>
-
+#endif
QT_BEGIN_NAMESPACE
// forward declaration
@@ -90,7 +91,9 @@ bool QSslCertificate::isSelfSigned() const
QByteArray QSslCertificate::version() const
{
+#if QT_CONFIG(thread)
QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
+#endif
if (d->versionString.isEmpty() && d->x509)
d->versionString = QByteArray::number(qlonglong(q_X509_get_version(d->x509)) + 1);
@@ -99,7 +102,9 @@ QByteArray QSslCertificate::version() const
QByteArray QSslCertificate::serialNumber() const
{
+#if QT_CONFIG(thread)
QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
+#endif
if (d->serialNumberString.isEmpty() && d->x509) {
ASN1_INTEGER *serialNumber = q_X509_get_serialNumber(d->x509);
QByteArray hexString;
@@ -116,7 +121,9 @@ QByteArray QSslCertificate::serialNumber() const
QStringList QSslCertificate::issuerInfo(SubjectInfo info) const
{
+#if QT_CONFIG(thread)
QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
+#endif
// lazy init
if (d->issuerInfo.isEmpty() && d->x509)
d->issuerInfo =
@@ -127,7 +134,9 @@ QStringList QSslCertificate::issuerInfo(SubjectInfo info) const
QStringList QSslCertificate::issuerInfo(const QByteArray &attribute) const
{
+#if QT_CONFIG(thread)
QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
+#endif
// lazy init
if (d->issuerInfo.isEmpty() && d->x509)
d->issuerInfo =
@@ -138,7 +147,9 @@ QStringList QSslCertificate::issuerInfo(const QByteArray &attribute) const
QStringList QSslCertificate::subjectInfo(SubjectInfo info) const
{
+#if QT_CONFIG(thread)
QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
+#endif
// lazy init
if (d->subjectInfo.isEmpty() && d->x509)
d->subjectInfo =
@@ -149,7 +160,9 @@ QStringList QSslCertificate::subjectInfo(SubjectInfo info) const
QStringList QSslCertificate::subjectInfo(const QByteArray &attribute) const
{
+#if QT_CONFIG(thread)
QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
+#endif
// lazy init
if (d->subjectInfo.isEmpty() && d->x509)
d->subjectInfo =
@@ -160,7 +173,9 @@ QStringList QSslCertificate::subjectInfo(const QByteArray &attribute) const
QList<QByteArray> QSslCertificate::subjectInfoAttributes() const
{
+#if QT_CONFIG(thread)
QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
+#endif
// lazy init
if (d->subjectInfo.isEmpty() && d->x509)
d->subjectInfo =
@@ -171,7 +186,9 @@ QList<QByteArray> QSslCertificate::subjectInfoAttributes() const
QList<QByteArray> QSslCertificate::issuerInfoAttributes() const
{
+#if QT_CONFIG(thread)
QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
+#endif
// lazy init
if (d->issuerInfo.isEmpty() && d->x509)
d->issuerInfo =
@@ -187,7 +204,8 @@ QMultiMap<QSsl::AlternativeNameEntryType, QString> QSslCertificate::subjectAlter
if (!d->x509)
return result;
- STACK_OF(GENERAL_NAME) *altNames = (STACK_OF(GENERAL_NAME)*)q_X509_get_ext_d2i(d->x509, NID_subject_alt_name, 0, 0);
+ STACK_OF(GENERAL_NAME) *altNames = (STACK_OF(GENERAL_NAME) *)q_X509_get_ext_d2i(
+ d->x509, NID_subject_alt_name, nullptr, nullptr);
if (altNames) {
for (int i = 0; i < q_sk_GENERAL_NAME_num(altNames); ++i) {
@@ -289,7 +307,7 @@ static QVariant x509UnknownExtensionToValue(X509_EXTENSION *ext)
// If this extension can be converted
if (meth->i2v && ext_internal) {
- STACK_OF(CONF_VALUE) *val = meth->i2v(meth, ext_internal, 0);
+ STACK_OF(CONF_VALUE) *val = meth->i2v(meth, ext_internal, nullptr);
QVariantMap map;
QVariantList list;
@@ -527,7 +545,7 @@ QByteArray QSslCertificatePrivate::QByteArray_from_X509(X509 *x509, QSsl::Encodi
}
// Use i2d_X509 to convert the X509 to an array.
- int length = q_i2d_X509(x509, 0);
+ int length = q_i2d_X509(x509, nullptr);
QByteArray array;
array.resize(length);
char *data = array.data();
@@ -604,11 +622,11 @@ static QMap<QByteArray, QString> _q_mapFromX509Name(X509_NAME *name)
X509_NAME_ENTRY *e = q_X509_NAME_get_entry(name, i);
QByteArray name = QSslCertificatePrivate::asn1ObjectName(q_X509_NAME_ENTRY_get_object(e));
- unsigned char *data = 0;
+ unsigned char *data = nullptr;
int size = q_ASN1_STRING_to_UTF8(&data, q_X509_NAME_ENTRY_get_data(e));
info.insertMulti(name, QString::fromUtf8((char*)data, size));
#if QT_CONFIG(opensslv11)
- q_CRYPTO_free(data, 0, 0);
+ q_CRYPTO_free(data, nullptr, 0);
#else
q_CRYPTO_free(data);
#endif
@@ -679,7 +697,7 @@ QList<QSslCertificate> QSslCertificatePrivate::certificatesFromPem(const QByteAr
QByteArray::fromRawData(pem.data() + startPos, endPos - startPos));
const unsigned char *data = (const unsigned char *)decoded.data();
- if (X509 *x509 = q_d2i_X509(0, &data, decoded.size())) {
+ if (X509 *x509 = q_d2i_X509(nullptr, &data, decoded.size())) {
certificates << QSslCertificate_from_X509(x509);
q_X509_free(x509);
}
@@ -697,7 +715,7 @@ QList<QSslCertificate> QSslCertificatePrivate::certificatesFromDer(const QByteAr
int size = der.size();
while (size > 0 && (count == -1 || certificates.size() < count)) {
- if (X509 *x509 = q_d2i_X509(0, &data, size)) {
+ if (X509 *x509 = q_d2i_X509(nullptr, &data, size)) {
certificates << QSslCertificate_from_X509(x509);
q_X509_free(x509);
} else {
diff --git a/src/network/ssl/qsslcertificate_p.h b/src/network/ssl/qsslcertificate_p.h
index 0397845f8d..dfdceab502 100644
--- a/src/network/ssl/qsslcertificate_p.h
+++ b/src/network/ssl/qsslcertificate_p.h
@@ -55,7 +55,9 @@
// We mean it.
//
+#ifndef QT_NO_SSL
#include "qsslsocket_p.h"
+#endif
#include "qsslcertificateextension.h"
#include <QtCore/qdatetime.h>
#include <QtCore/qmap.h>
@@ -83,7 +85,9 @@ public:
QSslCertificatePrivate()
: null(true), x509(0)
{
+#ifndef QT_NO_SSL
QSslSocketPrivate::ensureInitialized();
+#endif
}
~QSslCertificatePrivate()
diff --git a/src/network/ssl/qsslcertificate_qt.cpp b/src/network/ssl/qsslcertificate_qt.cpp
index 1cc2b1f964..dfdfd529e5 100644
--- a/src/network/ssl/qsslcertificate_qt.cpp
+++ b/src/network/ssl/qsslcertificate_qt.cpp
@@ -41,8 +41,10 @@
#include "qsslcertificate_p.h"
#include "qssl_p.h"
+#ifndef QT_NO_SSL
#include "qsslkey.h"
#include "qsslkey_p.h"
+#endif
#include "qsslcertificateextension.h"
#include "qsslcertificateextension_p.h"
#include "qasn1element_p.h"
@@ -141,10 +143,11 @@ QDateTime QSslCertificate::expiryDate() const
Qt::HANDLE QSslCertificate::handle() const
{
Q_UNIMPLEMENTED();
- return 0;
+ return nullptr;
}
#endif
+#ifndef QT_NO_SSL
QSslKey QSslCertificate::publicKey() const
{
QSslKey key;
@@ -155,6 +158,7 @@ QSslKey QSslCertificate::publicKey() const
}
return key;
}
+#endif
QList<QSslCertificateExtension> QSslCertificate::extensions() const
{
diff --git a/src/network/ssl/qsslcertificate_winrt.cpp b/src/network/ssl/qsslcertificate_winrt.cpp
index eb926d217d..e601307c17 100644
--- a/src/network/ssl/qsslcertificate_winrt.cpp
+++ b/src/network/ssl/qsslcertificate_winrt.cpp
@@ -102,10 +102,11 @@ Qt::HANDLE QSslCertificate::handle() const
HRESULT hr;
ComPtr<IBuffer> buffer;
hr = g->bufferFactory->CreateFromByteArray(d->derData.length(), (BYTE *)d->derData.data(), &buffer);
- RETURN_IF_FAILED("Failed to create the certificate data buffer", return 0);
+ RETURN_IF_FAILED("Failed to create the certificate data buffer", return nullptr);
hr = g->certificateFactory->CreateCertificate(buffer.Get(), &d->certificate);
- RETURN_IF_FAILED("Failed to create the certificate handle from the data buffer", return 0);
+ RETURN_IF_FAILED("Failed to create the certificate handle from the data buffer",
+ return nullptr);
}
return d->certificate.Get();
diff --git a/src/network/ssl/qsslcertificateextension.h b/src/network/ssl/qsslcertificateextension.h
index 2ce2112687..c2910e1707 100644
--- a/src/network/ssl/qsslcertificateextension.h
+++ b/src/network/ssl/qsslcertificateextension.h
@@ -48,9 +48,6 @@
QT_BEGIN_NAMESPACE
-
-#ifndef QT_NO_SSL
-
class QSslCertificateExtensionPrivate;
class Q_NETWORK_EXPORT QSslCertificateExtension
@@ -80,8 +77,6 @@ private:
Q_DECLARE_SHARED(QSslCertificateExtension)
-#endif // QT_NO_SSL
-
QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp
index 52ddf8bb88..3f732b4646 100644
--- a/src/network/ssl/qsslconfiguration.cpp
+++ b/src/network/ssl/qsslconfiguration.cpp
@@ -227,7 +227,8 @@ bool QSslConfiguration::operator==(const QSslConfiguration &other) const
d->sslSessionTicketLifeTimeHint == other.d->sslSessionTicketLifeTimeHint &&
d->nextAllowedProtocols == other.d->nextAllowedProtocols &&
d->nextNegotiatedProtocol == other.d->nextNegotiatedProtocol &&
- d->nextProtocolNegotiationStatus == other.d->nextProtocolNegotiationStatus;
+ d->nextProtocolNegotiationStatus == other.d->nextProtocolNegotiationStatus &&
+ d->dtlsCookieEnabled == other.d->dtlsCookieEnabled;
}
/*!
@@ -1034,6 +1035,65 @@ void QSslConfiguration::setDefaultConfiguration(const QSslConfiguration &configu
QSslConfigurationPrivate::setDefaultConfiguration(configuration);
}
+#if QT_CONFIG(dtls) || defined(Q_CLANG_QDOC)
+
+/*!
+ This function returns true if DTLS cookie verification was enabled on a
+ server-side socket.
+
+ \sa setDtlsCookieVerificationEnabled()
+ */
+bool QSslConfiguration::dtlsCookieVerificationEnabled() const
+{
+ return d->dtlsCookieEnabled;
+}
+
+/*!
+ This function enables DTLS cookie verification when \a enable is true.
+
+ \sa dtlsCookieVerificationEnabled()
+ */
+void QSslConfiguration::setDtlsCookieVerificationEnabled(bool enable)
+{
+ d->dtlsCookieEnabled = enable;
+}
+
+/*!
+ Returns the default DTLS configuration to be used in new DTLS
+ connections.
+
+ The default DTLS configuration consists of:
+
+ \list
+ \li no local certificate and no private key
+ \li protocol DtlsV1_2OrLater
+ \li the system's default CA certificate list
+ \li the cipher list equal to the list of the SSL libraries'
+ supported TLS 1.2 ciphers that use 128 or more secret bits
+ for the cipher.
+ \endlist
+
+ \sa setDefaultDtlsConfiguration()
+*/
+QSslConfiguration QSslConfiguration::defaultDtlsConfiguration()
+{
+ return QSslConfigurationPrivate::defaultDtlsConfiguration();
+}
+
+/*!
+ Sets the default DTLS configuration to be used in new DTLS
+ connections to be \a configuration. Existing connections are not
+ affected by this call.
+
+ \sa defaultDtlsConfiguration()
+*/
+void QSslConfiguration::setDefaultDtlsConfiguration(const QSslConfiguration &configuration)
+{
+ QSslConfigurationPrivate::setDefaultDtlsConfiguration(configuration);
+}
+
+#endif // dtls
+
/*! \internal
*/
bool QSslConfigurationPrivate::peerSessionWasShared(const QSslConfiguration &configuration) {
diff --git a/src/network/ssl/qsslconfiguration.h b/src/network/ssl/qsslconfiguration.h
index fe4181d755..454ac0cee3 100644
--- a/src/network/ssl/qsslconfiguration.h
+++ b/src/network/ssl/qsslconfiguration.h
@@ -73,6 +73,11 @@ class QSslKey;
class QSslEllipticCurve;
class QSslDiffieHellmanParameters;
+namespace dtlsopenssl
+{
+class DtlsState;
+}
+
class QSslConfigurationPrivate;
class Q_NETWORK_EXPORT QSslConfiguration
{
@@ -157,6 +162,14 @@ public:
static QSslConfiguration defaultConfiguration();
static void setDefaultConfiguration(const QSslConfiguration &configuration);
+#if QT_CONFIG(dtls) || defined(Q_CLANG_QDOC)
+ bool dtlsCookieVerificationEnabled() const;
+ void setDtlsCookieVerificationEnabled(bool enable);
+
+ static QSslConfiguration defaultDtlsConfiguration();
+ static void setDefaultDtlsConfiguration(const QSslConfiguration &configuration);
+#endif // dtls
+
enum NextProtocolNegotiationStatus {
NextProtocolNegotiationNone,
NextProtocolNegotiationNegotiated,
@@ -182,6 +195,8 @@ private:
friend class QSslConfigurationPrivate;
friend class QSslSocketBackendPrivate;
friend class QSslContext;
+ friend class QDtlsBasePrivate;
+ friend class dtlsopenssl::DtlsState;
QSslConfiguration(QSslConfigurationPrivate *dd);
QSharedDataPointer<QSslConfigurationPrivate> d;
};
diff --git a/src/network/ssl/qsslconfiguration_p.h b/src/network/ssl/qsslconfiguration_p.h
index 38a98239db..6c23165c6a 100644
--- a/src/network/ssl/qsslconfiguration_p.h
+++ b/src/network/ssl/qsslconfiguration_p.h
@@ -137,10 +137,19 @@ public:
QByteArray nextNegotiatedProtocol;
QSslConfiguration::NextProtocolNegotiationStatus nextProtocolNegotiationStatus;
+#if QT_CONFIG(dtls)
+ bool dtlsCookieEnabled = true;
+#else
+ const bool dtlsCookieEnabled = false;
+#endif // dtls
+
// in qsslsocket.cpp:
static QSslConfiguration defaultConfiguration();
static void setDefaultConfiguration(const QSslConfiguration &configuration);
static void deepCopyDefaultConfiguration(QSslConfigurationPrivate *config);
+
+ static QSslConfiguration defaultDtlsConfiguration();
+ static void setDefaultDtlsConfiguration(const QSslConfiguration &configuration);
};
// implemented here for inlining purposes
diff --git a/src/network/ssl/qsslcontext_openssl.cpp b/src/network/ssl/qsslcontext_openssl.cpp
index 41b759364b..35cca9f01a 100644
--- a/src/network/ssl/qsslcontext_openssl.cpp
+++ b/src/network/ssl/qsslcontext_openssl.cpp
@@ -55,9 +55,9 @@ static inline QString msgErrorSettingBackendConfig(const QString &why)
}
QSslContext::QSslContext()
- : ctx(0),
- pkey(0),
- session(0),
+ : ctx(nullptr),
+ pkey(nullptr),
+ session(nullptr),
m_sessionTicketLifeTimeHint(-1)
{
}
@@ -137,7 +137,8 @@ SSL* QSslContext::createSsl()
if (!session && !sessionASN1().isEmpty()
&& !sslConfiguration.testSslOption(QSsl::SslOptionDisableSessionPersistence)) {
const unsigned char *data = reinterpret_cast<const unsigned char *>(m_sessionASN1.constData());
- session = q_d2i_SSL_SESSION(0, &data, m_sessionASN1.size()); // refcount is 1 already, set by function above
+ session = q_d2i_SSL_SESSION(
+ nullptr, &data, m_sessionASN1.size()); // refcount is 1 already, set by function above
}
if (session) {
@@ -145,7 +146,7 @@ SSL* QSslContext::createSsl()
if (!q_SSL_set_session(ssl, session)) {
qCWarning(lcSsl, "could not set SSL session");
q_SSL_SESSION_free(session);
- session = 0;
+ session = nullptr;
}
}
@@ -204,7 +205,7 @@ bool QSslContext::cacheSession(SSL* ssl)
session = q_SSL_get1_session(ssl);
if (session && !sslConfiguration.testSslOption(QSsl::SslOptionDisableSessionPersistence)) {
- int sessionSize = q_i2d_SSL_SESSION(session, 0);
+ int sessionSize = q_i2d_SSL_SESSION(session, nullptr);
if (sessionSize > 0) {
m_sessionASN1.resize(sessionSize);
unsigned char *data = reinterpret_cast<unsigned char *>(m_sessionASN1.data());
@@ -214,7 +215,7 @@ bool QSslContext::cacheSession(SSL* ssl)
}
}
- return (session != 0);
+ return (session != nullptr);
}
QByteArray QSslContext::sessionASN1() const
diff --git a/src/network/ssl/qsslcontext_openssl11.cpp b/src/network/ssl/qsslcontext_openssl11.cpp
index 4fb33cb0a4..708cb7bb0e 100644
--- a/src/network/ssl/qsslcontext_openssl11.cpp
+++ b/src/network/ssl/qsslcontext_openssl11.cpp
@@ -59,11 +59,26 @@ QT_BEGIN_NAMESPACE
extern int q_X509Callback(int ok, X509_STORE_CTX *ctx);
extern QString getErrorsFromOpenSsl();
+#if QT_CONFIG(dtls)
+// defined in qdtls_openssl.cpp:
+namespace dtlscallbacks
+{
+extern "C" int q_X509DtlsCallback(int ok, X509_STORE_CTX *ctx);
+extern "C" int q_generate_cookie_callback(SSL *ssl, unsigned char *dst,
+ unsigned *cookieLength);
+extern "C" int q_verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
+ unsigned cookieLength);
+}
+#endif // dtls
+
static inline QString msgErrorSettingEllipticCurves(const QString &why)
{
return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why);
}
+// Defined in qsslsocket.cpp
+QList<QSslCipher> q_getDefaultDtlsCiphers();
+
// static
void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
{
@@ -74,14 +89,27 @@ void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mo
bool reinitialized = false;
bool unsupportedProtocol = false;
+ bool isDtls = false;
init_context:
if (sslContext->sslConfiguration.protocol() == QSsl::SslV2) {
// SSL 2 is no longer supported, but chosen deliberately -> error
sslContext->ctx = nullptr;
unsupportedProtocol = true;
} else {
- // The ssl options will actually control the supported methods
- sslContext->ctx = q_SSL_CTX_new(client ? q_TLS_client_method() : q_TLS_server_method());
+ switch (sslContext->sslConfiguration.protocol()) {
+#if QT_CONFIG(dtls)
+ case QSsl::DtlsV1_0:
+ case QSsl::DtlsV1_0OrLater:
+ case QSsl::DtlsV1_2:
+ case QSsl::DtlsV1_2OrLater:
+ isDtls = true;
+ sslContext->ctx = q_SSL_CTX_new(client ? q_DTLS_client_method() : q_DTLS_server_method());
+ break;
+#endif // dtls
+ default:
+ // The ssl options will actually control the supported methods
+ sslContext->ctx = q_SSL_CTX_new(client ? q_TLS_client_method() : q_TLS_server_method());
+ }
}
if (!sslContext->ctx) {
@@ -100,8 +128,15 @@ init_context:
return;
}
- long minVersion = TLS_ANY_VERSION;
- long maxVersion = TLS_ANY_VERSION;
+ const long anyVersion =
+#if QT_CONFIG(dtls)
+ isDtls ? DTLS_ANY_VERSION : TLS_ANY_VERSION;
+#else
+ TLS_ANY_VERSION;
+#endif // dtls
+ long minVersion = anyVersion;
+ long maxVersion = anyVersion;
+
switch (sslContext->sslConfiguration.protocol()) {
// The single-protocol versions first:
case QSsl::SslV3:
@@ -139,6 +174,24 @@ init_context:
minVersion = TLS1_2_VERSION;
maxVersion = 0;
break;
+#if QT_CONFIG(dtls)
+ case QSsl::DtlsV1_0:
+ minVersion = DTLS1_VERSION;
+ maxVersion = DTLS1_VERSION;
+ break;
+ case QSsl::DtlsV1_0OrLater:
+ minVersion = DTLS1_VERSION;
+ maxVersion = DTLS_MAX_VERSION;
+ break;
+ case QSsl::DtlsV1_2:
+ minVersion = DTLS1_2_VERSION;
+ maxVersion = DTLS1_2_VERSION;
+ break;
+ case QSsl::DtlsV1_2OrLater:
+ minVersion = DTLS1_2_VERSION;
+ maxVersion = DTLS_MAX_VERSION;
+ break;
+#endif // dtls
case QSsl::SslV2:
// This protocol is not supported by OpenSSL 1.1 and we handle
// it as an error (see the code above).
@@ -148,14 +201,14 @@ init_context:
break;
}
- if (minVersion != TLS_ANY_VERSION
+ if (minVersion != anyVersion
&& !q_SSL_CTX_set_min_proto_version(sslContext->ctx, minVersion)) {
sslContext->errorStr = QSslSocket::tr("Error while setting the minimal protocol version");
sslContext->errorCode = QSslError::UnspecifiedError;
return;
}
- if (maxVersion != TLS_ANY_VERSION
+ if (maxVersion != anyVersion
&& !q_SSL_CTX_set_max_proto_version(sslContext->ctx, maxVersion)) {
sslContext->errorStr = QSslSocket::tr("Error while setting the maximum protocol version");
sslContext->errorCode = QSslError::UnspecifiedError;
@@ -175,7 +228,8 @@ init_context:
bool first = true;
QList<QSslCipher> ciphers = sslContext->sslConfiguration.ciphers();
if (ciphers.isEmpty())
- ciphers = QSslSocketPrivate::defaultCiphers();
+ ciphers = isDtls ? q_getDefaultDtlsCiphers() : QSslSocketPrivate::defaultCiphers();
+
for (const QSslCipher &cipher : qAsConst(ciphers)) {
if (first)
first = false;
@@ -282,8 +336,19 @@ init_context:
if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) {
q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_NONE, nullptr);
} else {
- q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_PEER, q_X509Callback);
+ q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_PEER,
+#if QT_CONFIG(dtls)
+ isDtls ? dtlscallbacks::q_X509DtlsCallback :
+#endif // dtls
+ q_X509Callback);
+ }
+
+#if QT_CONFIG(dtls)
+ if (mode == QSslSocket::SslServerMode && isDtls && configuration.dtlsCookieVerificationEnabled()) {
+ q_SSL_CTX_set_cookie_generate_cb(sslContext->ctx, dtlscallbacks::q_generate_cookie_callback);
+ q_SSL_CTX_set_cookie_verify_cb(sslContext->ctx, dtlscallbacks::q_verify_cookie_callback);
}
+#endif // dtls
// Set verification depth.
if (sslContext->sslConfiguration.peerVerifyDepth() != 0)
@@ -305,8 +370,9 @@ init_context:
if (!dhparams.isEmpty()) {
const QByteArray &params = dhparams.d->derData;
const char *ptr = params.constData();
- DH *dh = q_d2i_DHparams(NULL, reinterpret_cast<const unsigned char **>(&ptr), params.length());
- if (dh == NULL)
+ DH *dh = q_d2i_DHparams(nullptr, reinterpret_cast<const unsigned char **>(&ptr),
+ params.length());
+ if (dh == nullptr)
qFatal("q_d2i_DHparams failed to convert QSslDiffieHellmanParameters to DER form");
q_SSL_CTX_set_tmp_dh(sslContext->ctx, dh);
q_DH_free(dh);
diff --git a/src/network/ssl/qsslcontext_opensslpre11.cpp b/src/network/ssl/qsslcontext_opensslpre11.cpp
index eea821804f..c8be2ecb31 100644
--- a/src/network/ssl/qsslcontext_opensslpre11.cpp
+++ b/src/network/ssl/qsslcontext_opensslpre11.cpp
@@ -56,11 +56,26 @@ QT_BEGIN_NAMESPACE
extern int q_X509Callback(int ok, X509_STORE_CTX *ctx);
extern QString getErrorsFromOpenSsl();
+#if QT_CONFIG(dtls)
+// defined in qdtls_openssl.cpp:
+namespace dtlscallbacks
+{
+extern "C" int q_X509DtlsCallback(int ok, X509_STORE_CTX *ctx);
+extern "C" int q_generate_cookie_callback(SSL *ssl, unsigned char *dst,
+ unsigned *cookieLength);
+extern "C" int q_verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
+ unsigned cookieLength);
+}
+#endif // dtls
+
static inline QString msgErrorSettingEllipticCurves(const QString &why)
{
return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why);
}
+// Defined in qsslsocket.cpp
+QList<QSslCipher> q_getDefaultDtlsCiphers();
+
// static
void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
{
@@ -68,11 +83,28 @@ void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mo
sslContext->errorCode = QSslError::NoError;
bool client = (mode == QSslSocket::SslClientMode);
-
bool reinitialized = false;
bool unsupportedProtocol = false;
+ bool isDtls = false;
init_context:
switch (sslContext->sslConfiguration.protocol()) {
+#if QT_CONFIG(dtls)
+ case QSsl::DtlsV1_0:
+ isDtls = true;
+ sslContext->ctx = q_SSL_CTX_new(client ? q_DTLSv1_client_method() : q_DTLSv1_server_method());
+ break;
+ case QSsl::DtlsV1_2:
+ case QSsl::DtlsV1_2OrLater:
+ // OpenSSL 1.0.2 and below will probably never receive TLS 1.3, so
+ // technically 1.2 or later is 1.2 and will stay so.
+ isDtls = true;
+ sslContext->ctx = q_SSL_CTX_new(client ? q_DTLSv1_2_client_method() : q_DTLSv1_2_server_method());
+ break;
+ case QSsl::DtlsV1_0OrLater:
+ isDtls = true;
+ sslContext->ctx = q_SSL_CTX_new(client ? q_DTLS_client_method() : q_DTLS_server_method());
+ break;
+#endif // dtls
case QSsl::SslV2:
#ifndef OPENSSL_NO_SSL2
sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv2_client_method() : q_SSLv2_server_method());
@@ -138,6 +170,12 @@ init_context:
break;
}
+ if (!client && isDtls && configuration.peerVerifyMode() != QSslSocket::VerifyNone) {
+ sslContext->errorStr = QSslSocket::tr("DTLS server requires a 'VerifyNone' mode with your version of OpenSSL");
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ return;
+ }
+
if (!sslContext->ctx) {
// After stopping Flash 10 the SSL library loses its ciphers. Try re-adding them
// by re-initializing the library.
@@ -155,6 +193,7 @@ init_context:
}
// Enable bug workarounds.
+ // DTLSTODO: check this setupOpenSslOptions ...
long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
q_SSL_CTX_set_options(sslContext->ctx, options);
@@ -170,7 +209,7 @@ init_context:
bool first = true;
QList<QSslCipher> ciphers = sslContext->sslConfiguration.ciphers();
if (ciphers.isEmpty())
- ciphers = QSslSocketPrivate::defaultCiphers();
+ ciphers = isDtls ? q_getDefaultDtlsCiphers() : QSslSocketPrivate::defaultCiphers();
for (const QSslCipher &cipher : qAsConst(ciphers)) {
if (first)
first = false;
@@ -277,8 +316,19 @@ init_context:
if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) {
q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_NONE, 0);
} else {
- q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_PEER, q_X509Callback);
+ q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_PEER,
+#if QT_CONFIG(dtls)
+ isDtls ? dtlscallbacks::q_X509DtlsCallback :
+#endif // dtls
+ q_X509Callback);
+ }
+
+#if QT_CONFIG(dtls)
+ if (mode == QSslSocket::SslServerMode && isDtls && configuration.dtlsCookieVerificationEnabled()) {
+ q_SSL_CTX_set_cookie_generate_cb(sslContext->ctx, dtlscallbacks::q_generate_cookie_callback);
+ q_SSL_CTX_set_cookie_verify_cb(sslContext->ctx, CookieVerifyCallback(dtlscallbacks::q_verify_cookie_callback));
}
+#endif // dtls
// Set verification depth.
if (sslContext->sslConfiguration.peerVerifyDepth() != 0)
diff --git a/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp b/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
index 00e9be91d8..c36482329a 100644
--- a/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
+++ b/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
@@ -128,7 +128,7 @@ void QSslDiffieHellmanParametersPrivate::decodeDer(const QByteArray &der)
QSslSocketPrivate::ensureInitialized();
- DH *dh = q_d2i_DHparams(NULL, &data, len);
+ DH *dh = q_d2i_DHparams(nullptr, &data, len);
if (dh) {
if (isSafeDH(dh))
derData = der;
@@ -162,7 +162,7 @@ void QSslDiffieHellmanParametersPrivate::decodePem(const QByteArray &pem)
}
DH *dh = nullptr;
- q_PEM_read_bio_DHparams(bio, &dh, 0, 0);
+ q_PEM_read_bio_DHparams(bio, &dh, nullptr, nullptr);
if (dh) {
if (isSafeDH(dh)) {
diff --git a/src/network/ssl/qsslkey_openssl.cpp b/src/network/ssl/qsslkey_openssl.cpp
index 58df544a0e..9a43e67772 100644
--- a/src/network/ssl/qsslkey_openssl.cpp
+++ b/src/network/ssl/qsslkey_openssl.cpp
@@ -62,24 +62,24 @@ void QSslKeyPrivate::clear(bool deep)
if (algorithm == QSsl::Rsa && rsa) {
if (deep)
q_RSA_free(rsa);
- rsa = 0;
+ rsa = nullptr;
}
if (algorithm == QSsl::Dsa && dsa) {
if (deep)
q_DSA_free(dsa);
- dsa = 0;
+ dsa = nullptr;
}
#ifndef OPENSSL_NO_EC
if (algorithm == QSsl::Ec && ec) {
if (deep)
q_EC_KEY_free(ec);
- ec = 0;
+ ec = nullptr;
}
#endif
if (algorithm == QSsl::Opaque && opaque) {
if (deep)
q_EVP_PKEY_free(opaque);
- opaque = 0;
+ opaque = nullptr;
}
}
@@ -125,10 +125,10 @@ bool QSslKeyPrivate::fromEVP_PKEY(EVP_PKEY *pkey)
return false;
}
-void QSslKeyPrivate::decodeDer(const QByteArray &der, bool deepClear)
+void QSslKeyPrivate::decodeDer(const QByteArray &der, const QByteArray &passPhrase, bool deepClear)
{
QMap<QByteArray, QByteArray> headers;
- decodePem(pemFromDer(der, headers), QByteArray(), deepClear);
+ decodePem(pemFromDer(der, headers), passPhrase, deepClear);
}
void QSslKeyPrivate::decodePem(const QByteArray &pem, const QByteArray &passPhrase,
@@ -150,21 +150,21 @@ void QSslKeyPrivate::decodePem(const QByteArray &pem, const QByteArray &passPhra
if (algorithm == QSsl::Rsa) {
RSA *result = (type == QSsl::PublicKey)
- ? q_PEM_read_bio_RSA_PUBKEY(bio, &rsa, 0, phrase)
- : q_PEM_read_bio_RSAPrivateKey(bio, &rsa, 0, phrase);
+ ? q_PEM_read_bio_RSA_PUBKEY(bio, &rsa, nullptr, phrase)
+ : q_PEM_read_bio_RSAPrivateKey(bio, &rsa, nullptr, phrase);
if (rsa && rsa == result)
isNull = false;
} else if (algorithm == QSsl::Dsa) {
DSA *result = (type == QSsl::PublicKey)
- ? q_PEM_read_bio_DSA_PUBKEY(bio, &dsa, 0, phrase)
- : q_PEM_read_bio_DSAPrivateKey(bio, &dsa, 0, phrase);
+ ? q_PEM_read_bio_DSA_PUBKEY(bio, &dsa, nullptr, phrase)
+ : q_PEM_read_bio_DSAPrivateKey(bio, &dsa, nullptr, phrase);
if (dsa && dsa == result)
isNull = false;
#ifndef OPENSSL_NO_EC
} else if (algorithm == QSsl::Ec) {
EC_KEY *result = (type == QSsl::PublicKey)
- ? q_PEM_read_bio_EC_PUBKEY(bio, &ec, 0, phrase)
- : q_PEM_read_bio_ECPrivateKey(bio, &ec, 0, phrase);
+ ? q_PEM_read_bio_EC_PUBKEY(bio, &ec, nullptr, phrase)
+ : q_PEM_read_bio_ECPrivateKey(bio, &ec, nullptr, phrase);
if (ec && ec == result)
isNull = false;
#endif
@@ -215,8 +215,8 @@ QByteArray QSslKeyPrivate::toPem(const QByteArray &passPhrase) const
fail = true;
} else {
if (!q_PEM_write_bio_RSAPrivateKey(
- bio, rsa, cipher,
- const_cast<uchar *>((const uchar *)passPhrase.data()), passPhrase.size(), 0, 0)) {
+ bio, rsa, cipher, const_cast<uchar *>((const uchar *)passPhrase.data()),
+ passPhrase.size(), nullptr, nullptr)) {
fail = true;
}
}
@@ -226,8 +226,8 @@ QByteArray QSslKeyPrivate::toPem(const QByteArray &passPhrase) const
fail = true;
} else {
if (!q_PEM_write_bio_DSAPrivateKey(
- bio, dsa, cipher,
- const_cast<uchar *>((const uchar *)passPhrase.data()), passPhrase.size(), 0, 0)) {
+ bio, dsa, cipher, const_cast<uchar *>((const uchar *)passPhrase.data()),
+ passPhrase.size(), nullptr, nullptr)) {
fail = true;
}
}
@@ -237,9 +237,9 @@ QByteArray QSslKeyPrivate::toPem(const QByteArray &passPhrase) const
if (!q_PEM_write_bio_EC_PUBKEY(bio, ec))
fail = true;
} else {
- if (!q_PEM_write_bio_ECPrivateKey(
- bio, ec, cipher,
- const_cast<uchar *>((const uchar *)passPhrase.data()), passPhrase.size(), 0, 0)) {
+ if (!q_PEM_write_bio_ECPrivateKey(bio, ec, cipher,
+ const_cast<uchar *>((const uchar *)passPhrase.data()),
+ passPhrase.size(), nullptr, nullptr)) {
fail = true;
}
}
@@ -272,13 +272,13 @@ Qt::HANDLE QSslKeyPrivate::handle() const
return Qt::HANDLE(ec);
#endif
default:
- return Qt::HANDLE(NULL);
+ return Qt::HANDLE(nullptr);
}
}
static QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv, int enc)
{
- const EVP_CIPHER* type = 0;
+ const EVP_CIPHER* type = nullptr;
int i = 0, len = 0;
switch (cipher) {
@@ -314,10 +314,10 @@ static QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, const QByteArray &data,
q_EVP_CIPHER_CTX_init(ctx);
#endif
- q_EVP_CipherInit(ctx, type, NULL, NULL, enc);
+ q_EVP_CipherInit(ctx, type, nullptr, nullptr, enc);
q_EVP_CIPHER_CTX_set_key_length(ctx, key.size());
if (cipher == QSslKeyPrivate::Rc2Cbc)
- q_EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS, 8 * key.size(), NULL);
+ q_EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS, 8 * key.size(), nullptr);
#if QT_CONFIG(opensslv11)
// EVP_CipherInit in 1.1 resets the context thus making the calls above useless.
diff --git a/src/network/ssl/qsslkey_p.cpp b/src/network/ssl/qsslkey_p.cpp
index e66ec953a0..28e3e2efd8 100644
--- a/src/network/ssl/qsslkey_p.cpp
+++ b/src/network/ssl/qsslkey_p.cpp
@@ -61,6 +61,7 @@
#endif
#include "qsslsocket.h"
#include "qsslsocket_p.h"
+#include "qasn1element_p.h"
#include <QtCore/qatomic.h>
#include <QtCore/qbytearray.h>
@@ -120,6 +121,13 @@ QByteArray QSslKeyPrivate::pemHeader() const
return QByteArray();
}
+static QByteArray pkcs8Header(bool encrypted)
+{
+ return encrypted
+ ? QByteArrayLiteral("-----BEGIN ENCRYPTED PRIVATE KEY-----")
+ : QByteArrayLiteral("-----BEGIN PRIVATE KEY-----");
+}
+
/*!
\internal
*/
@@ -138,6 +146,13 @@ QByteArray QSslKeyPrivate::pemFooter() const
return QByteArray();
}
+static QByteArray pkcs8Footer(bool encrypted)
+{
+ return encrypted
+ ? QByteArrayLiteral("-----END ENCRYPTED PRIVATE KEY-----")
+ : QByteArrayLiteral("-----END PRIVATE KEY-----");
+}
+
/*!
\internal
@@ -166,8 +181,19 @@ QByteArray QSslKeyPrivate::pemFromDer(const QByteArray &der, const QMap<QByteArr
} while (it != headers.constBegin());
extra += '\n';
}
- pem.prepend(pemHeader() + '\n' + extra);
- pem.append(pemFooter() + '\n');
+
+ if (isEncryptedPkcs8(der)) {
+ pem.prepend(pkcs8Header(true) + '\n' + extra);
+ pem.append(pkcs8Footer(true) + '\n');
+#if !QT_CONFIG(openssl)
+ } else if (isPkcs8) {
+ pem.prepend(pkcs8Header(false) + '\n' + extra);
+ pem.append(pkcs8Footer(false) + '\n');
+#endif
+ } else {
+ pem.prepend(pemHeader() + '\n' + extra);
+ pem.append(pemFooter() + '\n');
+ }
return pem;
}
@@ -179,13 +205,27 @@ QByteArray QSslKeyPrivate::pemFromDer(const QByteArray &der, const QMap<QByteArr
*/
QByteArray QSslKeyPrivate::derFromPem(const QByteArray &pem, QMap<QByteArray, QByteArray> *headers) const
{
- const QByteArray header = pemHeader();
- const QByteArray footer = pemFooter();
+ QByteArray header = pemHeader();
+ QByteArray footer = pemFooter();
QByteArray der(pem);
- const int headerIndex = der.indexOf(header);
- const int footerIndex = der.indexOf(footer);
+ int headerIndex = der.indexOf(header);
+ int footerIndex = der.indexOf(footer, headerIndex + header.length());
+ if (type != QSsl::PublicKey) {
+ if (headerIndex == -1 || footerIndex == -1) {
+ header = pkcs8Header(true);
+ footer = pkcs8Footer(true);
+ headerIndex = der.indexOf(header);
+ footerIndex = der.indexOf(footer, headerIndex + header.length());
+ }
+ if (headerIndex == -1 || footerIndex == -1) {
+ header = pkcs8Header(false);
+ footer = pkcs8Footer(false);
+ headerIndex = der.indexOf(header);
+ footerIndex = der.indexOf(footer, headerIndex + header.length());
+ }
+ }
if (headerIndex == -1 || footerIndex == -1)
return QByteArray();
@@ -225,13 +265,47 @@ QByteArray QSslKeyPrivate::derFromPem(const QByteArray &pem, QMap<QByteArray, QB
return QByteArray::fromBase64(der); // ignores newlines
}
+bool QSslKeyPrivate::isEncryptedPkcs8(const QByteArray &der) const
+{
+ static const QVector<QByteArray> pbes1OIds {
+ // PKCS5
+ {PKCS5_MD2_DES_CBC_OID},
+ {PKCS5_MD2_RC2_CBC_OID},
+ {PKCS5_MD5_DES_CBC_OID},
+ {PKCS5_MD5_RC2_CBC_OID},
+ {PKCS5_SHA1_DES_CBC_OID},
+ {PKCS5_SHA1_RC2_CBC_OID},
+ };
+ QAsn1Element elem;
+ if (!elem.read(der) || elem.type() != QAsn1Element::SequenceType)
+ return false;
+
+ const QVector<QAsn1Element> items = elem.toVector();
+ if (items.size() != 2
+ || items[0].type() != QAsn1Element::SequenceType
+ || items[1].type() != QAsn1Element::OctetStringType) {
+ return false;
+ }
+
+ const QVector<QAsn1Element> encryptionSchemeContainer = items[0].toVector();
+ if (encryptionSchemeContainer.size() != 2
+ || encryptionSchemeContainer[0].type() != QAsn1Element::ObjectIdentifierType
+ || encryptionSchemeContainer[1].type() != QAsn1Element::SequenceType) {
+ return false;
+ }
+
+ const QByteArray encryptionScheme = encryptionSchemeContainer[0].toObjectId();
+ return encryptionScheme == PKCS5_PBES2_ENCRYPTION_OID
+ || pbes1OIds.contains(encryptionScheme)
+ || encryptionScheme.startsWith(PKCS12_OID);
+}
+
/*!
Constructs a QSslKey by decoding the string in the byte array
\a encoded using a specified \a algorithm and \a encoding format.
\a type specifies whether the key is public or private.
- If the key is encoded as PEM and encrypted, \a passPhrase is used
- to decrypt it.
+ If the key is encrypted then \a passPhrase is used to decrypt it.
After construction, use isNull() to check if \a encoded contained
a valid key.
@@ -243,7 +317,7 @@ QSslKey::QSslKey(const QByteArray &encoded, QSsl::KeyAlgorithm algorithm,
d->type = type;
d->algorithm = algorithm;
if (encoding == QSsl::Der)
- d->decodeDer(encoded);
+ d->decodeDer(encoded, passPhrase);
else
d->decodePem(encoded, passPhrase);
}
@@ -253,8 +327,7 @@ QSslKey::QSslKey(const QByteArray &encoded, QSsl::KeyAlgorithm algorithm,
\a device using a specified \a algorithm and \a encoding format.
\a type specifies whether the key is public or private.
- If the key is encoded as PEM and encrypted, \a passPhrase is used
- to decrypt it.
+ If the key is encrypted then \a passPhrase is used to decrypt it.
After construction, use isNull() to check if \a device provided
a valid key.
@@ -269,7 +342,7 @@ QSslKey::QSslKey(QIODevice *device, QSsl::KeyAlgorithm algorithm, QSsl::Encoding
d->type = type;
d->algorithm = algorithm;
if (encoding == QSsl::Der)
- d->decodeDer(encoded);
+ d->decodeDer(encoded, passPhrase);
else
d->decodePem(encoded, passPhrase);
}
diff --git a/src/network/ssl/qsslkey_p.h b/src/network/ssl/qsslkey_p.h
index c93941c198..7ae2cc740b 100644
--- a/src/network/ssl/qsslkey_p.h
+++ b/src/network/ssl/qsslkey_p.h
@@ -81,9 +81,8 @@ public:
#ifndef QT_NO_OPENSSL
bool fromEVP_PKEY(EVP_PKEY *pkey);
#endif
- void decodeDer(const QByteArray &der, bool deepClear = true);
- void decodePem(const QByteArray &pem, const QByteArray &passPhrase,
- bool deepClear = true);
+ void decodeDer(const QByteArray &der, const QByteArray &passPhrase = {}, bool deepClear = true);
+ void decodePem(const QByteArray &pem, const QByteArray &passPhrase, bool deepClear = true);
QByteArray pemHeader() const;
QByteArray pemFooter() const;
QByteArray pemFromDer(const QByteArray &der, const QMap<QByteArray, QByteArray> &headers) const;
@@ -93,6 +92,12 @@ public:
QByteArray toPem(const QByteArray &passPhrase) const;
Qt::HANDLE handle() const;
+ bool isEncryptedPkcs8(const QByteArray &der) const;
+#if !QT_CONFIG(openssl)
+ QByteArray decryptPkcs8(const QByteArray &encrypted, const QByteArray &passPhrase);
+ bool isPkcs8 = false;
+#endif
+
bool isNull;
QSsl::KeyType type;
QSsl::KeyAlgorithm algorithm;
diff --git a/src/network/ssl/qsslkey_qt.cpp b/src/network/ssl/qsslkey_qt.cpp
index a85fed21ed..a13275f3bb 100644
--- a/src/network/ssl/qsslkey_qt.cpp
+++ b/src/network/ssl/qsslkey_qt.cpp
@@ -43,8 +43,11 @@
#include <QtCore/qdatastream.h>
#include <QtCore/qcryptographichash.h>
+#include <QtCore/QMessageAuthenticationCode>
#include <QtCore/qrandom.h>
+#include <QtNetwork/qpassworddigestor.h>
+
QT_USE_NAMESPACE
static const quint8 bits_table[256] = {
@@ -154,15 +157,86 @@ void QSslKeyPrivate::clear(bool deep)
keyLength = -1;
}
-void QSslKeyPrivate::decodeDer(const QByteArray &der, bool deepClear)
+static int extractPkcs8KeyLength(const QVector<QAsn1Element> &items, QSslKeyPrivate *that) {
+ Q_ASSERT(items.size() == 3);
+ int keyLength;
+
+ auto getName = [](QSsl::KeyAlgorithm algorithm) {
+ switch (algorithm){
+ case QSsl::Rsa: return "RSA";
+ case QSsl::Dsa: return "DSA";
+ case QSsl::Ec: return "EC";
+ case QSsl::Opaque: return "Opaque";
+ }
+ Q_UNREACHABLE();
+ };
+
+ const QVector<QAsn1Element> pkcs8Info = items[1].toVector();
+ if (pkcs8Info.size() != 2 || pkcs8Info[0].type() != QAsn1Element::ObjectIdentifierType)
+ return -1;
+ const QByteArray value = pkcs8Info[0].toObjectId();
+ if (value == RSA_ENCRYPTION_OID) {
+ if (Q_UNLIKELY(that->algorithm != QSsl::Rsa)) {
+ // We could change the 'algorithm' of QSslKey here and continue loading, but
+ // this is not supported in the openssl back-end, so we'll fail here and give
+ // the user some feedback.
+ qWarning() << "QSslKey: Found RSA key when asked to use" << getName(that->algorithm)
+ << "\nLoading will fail.";
+ return -1;
+ }
+ // Luckily it contains the 'normal' RSA-key format inside, so we can just recurse
+ // and read the key's info.
+ that->decodeDer(items[2].value());
+ // The real info has been filled out in the call above, so return as if it was invalid
+ // to avoid overwriting the data.
+ return -1;
+ } else if (value == EC_ENCRYPTION_OID) {
+ if (Q_UNLIKELY(that->algorithm != QSsl::Ec)) {
+ // As above for RSA.
+ qWarning() << "QSslKey: Found EC key when asked to use" << getName(that->algorithm)
+ << "\nLoading will fail.";
+ return -1;
+ }
+ // I don't know where this is documented, but the elliptic-curve identifier has been
+ // moved into the "pkcs#8 wrapper", which is what we're interested in.
+ if (pkcs8Info[1].type() != QAsn1Element::ObjectIdentifierType)
+ return -1;
+ keyLength = curveBits(pkcs8Info[1].toObjectId());
+ } else if (value == DSA_ENCRYPTION_OID) {
+ if (Q_UNLIKELY(that->algorithm != QSsl::Dsa)) {
+ // As above for RSA.
+ qWarning() << "QSslKey: Found DSA when asked to use" << getName(that->algorithm)
+ << "\nLoading will fail.";
+ return -1;
+ }
+ // DSA's structure is documented here:
+ // https://www.cryptsoft.com/pkcs11doc/STANDARD/v201-95.pdf in section 11.9.
+ if (pkcs8Info[1].type() != QAsn1Element::SequenceType)
+ return -1;
+ const QVector<QAsn1Element> dsaInfo = pkcs8Info[1].toVector();
+ if (dsaInfo.size() != 3 || dsaInfo[0].type() != QAsn1Element::IntegerType)
+ return -1;
+ keyLength = numberOfBits(dsaInfo[0].value());
+ } else {
+ // in case of unexpected formats:
+ qWarning() << "QSslKey: Unsupported PKCS#8 key algorithm:" << value
+ << "\nFile a bugreport to Qt (include the line above).";
+ return -1;
+ }
+ return keyLength;
+}
+
+void QSslKeyPrivate::decodeDer(const QByteArray &der, const QByteArray &passPhrase, bool deepClear)
{
clear(deepClear);
if (der.isEmpty())
return;
+ // decryptPkcs8 decrypts if necessary or returns 'der' unaltered
+ QByteArray decryptedDer = decryptPkcs8(der, passPhrase);
QAsn1Element elem;
- if (!elem.read(der) || elem.type() != QAsn1Element::SequenceType)
+ if (!elem.read(decryptedDer) || elem.type() != QAsn1Element::SequenceType)
return;
if (type == QSsl::PublicKey) {
@@ -212,7 +286,16 @@ void QSslKeyPrivate::decodeDer(const QByteArray &der, bool deepClear)
return;
const QByteArray versionHex = items[0].value().toHex();
- if (algorithm == QSsl::Rsa) {
+ if (items.size() == 3 && items[1].type() == QAsn1Element::SequenceType
+ && items[2].type() == QAsn1Element::OctetStringType) {
+ if (versionHex != "00" && versionHex != "01")
+ return;
+ int pkcs8KeyLength = extractPkcs8KeyLength(items, this);
+ if (pkcs8KeyLength == -1)
+ return;
+ isPkcs8 = true;
+ keyLength = pkcs8KeyLength;
+ } else if (algorithm == QSsl::Rsa) {
if (versionHex != "00")
return;
if (items.size() != 9 || items[1].type() != QAsn1Element::IntegerType)
@@ -240,7 +323,7 @@ void QSslKeyPrivate::decodeDer(const QByteArray &der, bool deepClear)
}
}
- derData = der;
+ derData = decryptedDer;
isNull = false;
}
@@ -272,7 +355,7 @@ void QSslKeyPrivate::decodePem(const QByteArray &pem, const QByteArray &passPhra
const QByteArray key = deriveKey(cipher, passPhrase, iv);
data = decrypt(cipher, data, key, iv);
}
- decodeDer(data, deepClear);
+ decodeDer(data, passPhrase, deepClear);
}
int QSslKeyPrivate::length() const
@@ -307,3 +390,320 @@ Qt::HANDLE QSslKeyPrivate::handle() const
{
return opaque;
}
+
+// Maps OIDs to the encryption cipher they specify
+static const QMap<QByteArray, QSslKeyPrivate::Cipher> oidCipherMap {
+ {DES_CBC_ENCRYPTION_OID, QSslKeyPrivate::Cipher::DesCbc},
+ {DES_EDE3_CBC_ENCRYPTION_OID, QSslKeyPrivate::Cipher::DesEde3Cbc},
+ // {PKCS5_MD2_DES_CBC_OID, QSslKeyPrivate::Cipher::DesCbc}, // No MD2
+ {PKCS5_MD5_DES_CBC_OID, QSslKeyPrivate::Cipher::DesCbc},
+ {PKCS5_SHA1_DES_CBC_OID, QSslKeyPrivate::Cipher::DesCbc},
+ // {PKCS5_MD2_RC2_CBC_OID, QSslKeyPrivate::Cipher::Rc2Cbc}, // No MD2
+ {PKCS5_MD5_RC2_CBC_OID, QSslKeyPrivate::Cipher::Rc2Cbc},
+ {PKCS5_SHA1_RC2_CBC_OID, QSslKeyPrivate::Cipher::Rc2Cbc},
+ {RC2_CBC_ENCRYPTION_OID, QSslKeyPrivate::Cipher::Rc2Cbc}
+ // {RC5_CBC_ENCRYPTION_OID, QSslKeyPrivate::Cipher::Rc5Cbc}, // No RC5
+ // {AES128_CBC_ENCRYPTION_OID, QSslKeyPrivate::Cipher::Aes128}, // no AES
+ // {AES192_CBC_ENCRYPTION_OID, QSslKeyPrivate::Cipher::Aes192},
+ // {AES256_CBC_ENCRYPTION_OID, QSslKeyPrivate::Cipher::Aes256}
+};
+
+struct EncryptionData
+{
+ EncryptionData() : initialized(false)
+ {}
+ EncryptionData(QSslKeyPrivate::Cipher cipher, QByteArray key, QByteArray iv)
+ : initialized(true), cipher(cipher), key(key), iv(iv)
+ {}
+ bool initialized;
+ QSslKeyPrivate::Cipher cipher;
+ QByteArray key;
+ QByteArray iv;
+};
+
+static EncryptionData readPbes2(const QVector<QAsn1Element> &element, const QByteArray &passPhrase)
+{
+ // RFC 8018: https://tools.ietf.org/html/rfc8018#section-6.2
+ /*** Scheme: ***
+ * Sequence (scheme-specific info..)
+ * Sequence (key derivation info)
+ * Object Identifier (Key derivation algorithm (e.g. PBKDF2))
+ * Sequence (salt)
+ * CHOICE (this entry can be either of the types it contains)
+ * Octet string (actual salt)
+ * Object identifier (Anything using this is deferred to a later version of PKCS #5)
+ * Integer (iteration count)
+ * Sequence (encryption algorithm info)
+ * Object identifier (identifier for the algorithm)
+ * Algorithm dependent, is covered in the switch further down
+ */
+
+ static const QMap<QByteArray, QCryptographicHash::Algorithm> pbes2OidHashFunctionMap {
+ // PBES2/PBKDF2
+ {HMAC_WITH_SHA1, QCryptographicHash::Sha1},
+ {HMAC_WITH_SHA224, QCryptographicHash::Sha224},
+ {HMAC_WITH_SHA256, QCryptographicHash::Sha256},
+ {HMAC_WITH_SHA512, QCryptographicHash::Sha512},
+ {HMAC_WITH_SHA512_224, QCryptographicHash::Sha512},
+ {HMAC_WITH_SHA512_256, QCryptographicHash::Sha512},
+ {HMAC_WITH_SHA384, QCryptographicHash::Sha384}
+ };
+
+ // Values from their respective sections here: https://tools.ietf.org/html/rfc8018#appendix-B.2
+ static const QMap<QSslKeyPrivate::Cipher, int> cipherKeyLengthMap {
+ {QSslKeyPrivate::Cipher::DesCbc, 8},
+ {QSslKeyPrivate::Cipher::DesEde3Cbc, 24},
+ // @note: variable key-length (https://tools.ietf.org/html/rfc8018#appendix-B.2.3)
+ {QSslKeyPrivate::Cipher::Rc2Cbc, 4}
+ // @todo: AES(, rc5?)
+ };
+
+ const QVector<QAsn1Element> keyDerivationContainer = element[0].toVector();
+ if (keyDerivationContainer.size() != 2
+ || keyDerivationContainer[0].type() != QAsn1Element::ObjectIdentifierType
+ || keyDerivationContainer[1].type() != QAsn1Element::SequenceType) {
+ return {};
+ }
+
+ const QByteArray keyDerivationAlgorithm = keyDerivationContainer[0].toObjectId();
+ const QVector<QAsn1Element> keyDerivationParams = keyDerivationContainer[1].toVector();
+
+ const QVector<QAsn1Element> encryptionAlgorithmContainer = element[1].toVector();
+ if (encryptionAlgorithmContainer.size() != 2
+ || encryptionAlgorithmContainer[0].type() != QAsn1Element::ObjectIdentifierType) {
+ return {};
+ }
+
+ auto iterator = oidCipherMap.constFind(encryptionAlgorithmContainer[0].toObjectId());
+ if (iterator == oidCipherMap.cend()) {
+ qWarning()
+ << "QSslKey: Unsupported encryption cipher OID:" << encryptionAlgorithmContainer[0].toObjectId()
+ << "\nFile a bugreport to Qt (include the line above).";
+ return {};
+ }
+
+ QSslKeyPrivate::Cipher cipher = *iterator;
+ QByteArray key;
+ QByteArray iv;
+ switch (cipher) {
+ case QSslKeyPrivate::Cipher::DesCbc:
+ case QSslKeyPrivate::Cipher::DesEde3Cbc:
+ // https://tools.ietf.org/html/rfc8018#appendix-B.2.1 (DES-CBC-PAD)
+ // https://tools.ietf.org/html/rfc8018#appendix-B.2.2 (DES-EDE3-CBC-PAD)
+ // @todo https://tools.ietf.org/html/rfc8018#appendix-B.2.5 (AES-CBC-PAD)
+ /*** Scheme: ***
+ * Octet string (IV)
+ */
+ if (encryptionAlgorithmContainer[1].type() != QAsn1Element::OctetStringType)
+ return {};
+
+ // @note: All AES identifiers should be able to use this branch!!
+ iv = encryptionAlgorithmContainer[1].value();
+
+ if (iv.size() != 8) // @note: AES needs 16 bytes
+ return {};
+ break;
+ case QSslKeyPrivate::Cipher::Rc2Cbc: {
+ // https://tools.ietf.org/html/rfc8018#appendix-B.2.3
+ /*** Scheme: ***
+ * Sequence (rc2 parameters)
+ * Integer (rc2 parameter version)
+ * Octet string (IV)
+ */
+ if (encryptionAlgorithmContainer[1].type() != QAsn1Element::SequenceType)
+ return {};
+ const QVector<QAsn1Element> rc2ParametersContainer = encryptionAlgorithmContainer[1].toVector();
+ if ((rc2ParametersContainer.size() != 1 && rc2ParametersContainer.size() != 2)
+ || rc2ParametersContainer.back().type() != QAsn1Element::OctetStringType) {
+ return {};
+ }
+ iv = rc2ParametersContainer.back().value();
+ if (iv.size() != 8)
+ return {};
+ break;
+ } // @todo(?): case (RC5 , AES)
+ }
+
+ if (Q_LIKELY(keyDerivationAlgorithm == PKCS5_PBKDF2_ENCRYPTION_OID)) {
+ // Definition: https://tools.ietf.org/html/rfc8018#appendix-A.2
+ QByteArray salt;
+ if (keyDerivationParams[0].type() == QAsn1Element::OctetStringType) {
+ salt = keyDerivationParams[0].value();
+ } else if (keyDerivationParams[0].type() == QAsn1Element::ObjectIdentifierType) {
+ Q_UNIMPLEMENTED();
+ /* See paragraph from https://tools.ietf.org/html/rfc8018#appendix-A.2
+ which ends with: "such facilities are deferred to a future version of PKCS #5"
+ */
+ return {};
+ } else {
+ return {};
+ }
+
+ // Iterations needed to derive the key
+ int iterationCount = keyDerivationParams[1].toInteger();
+ // Optional integer
+ int keyLength = -1;
+ int vectorPos = 2;
+ if (keyDerivationParams.size() > vectorPos
+ && keyDerivationParams[vectorPos].type() == QAsn1Element::IntegerType) {
+ keyLength = keyDerivationParams[vectorPos].toInteger(nullptr);
+ ++vectorPos;
+ } else {
+ keyLength = cipherKeyLengthMap[cipher];
+ }
+
+ // Optional algorithm identifier (default: HMAC-SHA-1)
+ QCryptographicHash::Algorithm hashAlgorithm = QCryptographicHash::Sha1;
+ if (keyDerivationParams.size() > vectorPos
+ && keyDerivationParams[vectorPos].type() == QAsn1Element::SequenceType) {
+ QVector<QAsn1Element> hashAlgorithmContainer = keyDerivationParams[vectorPos].toVector();
+ hashAlgorithm = pbes2OidHashFunctionMap[hashAlgorithmContainer.front().toObjectId()];
+ Q_ASSERT(hashAlgorithmContainer[1].type() == QAsn1Element::NullType);
+ ++vectorPos;
+ }
+ Q_ASSERT(keyDerivationParams.size() == vectorPos);
+
+ key = QPasswordDigestor::deriveKeyPbkdf2(hashAlgorithm, passPhrase, salt, iterationCount, keyLength);
+ } else {
+ qWarning()
+ << "QSslKey: Unsupported key derivation algorithm OID:" << keyDerivationAlgorithm
+ << "\nFile a bugreport to Qt (include the line above).";
+ return {};
+ }
+ return {cipher, key, iv};
+}
+
+// Maps OIDs to the hash function it specifies
+static const QMap<QByteArray, QCryptographicHash::Algorithm> pbes1OidHashFunctionMap {
+#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
+ // PKCS5
+ //{PKCS5_MD2_DES_CBC_OID, QCryptographicHash::Md2}, No MD2
+ //{PKCS5_MD2_RC2_CBC_OID, QCryptographicHash::Md2},
+ {PKCS5_MD5_DES_CBC_OID, QCryptographicHash::Md5},
+ {PKCS5_MD5_RC2_CBC_OID, QCryptographicHash::Md5},
+#endif
+ {PKCS5_SHA1_DES_CBC_OID, QCryptographicHash::Sha1},
+ {PKCS5_SHA1_RC2_CBC_OID, QCryptographicHash::Sha1},
+ // PKCS12 (unimplemented)
+ // {PKCS12_SHA1_RC4_128_OID, QCryptographicHash::Sha1}, // No RC4
+ // {PKCS12_SHA1_RC4_40_OID, QCryptographicHash::Sha1},
+ // @todo: lacking support. @note: there might be code to do this inside qsslsocket_mac...
+ // further note that more work may be required for the 3DES variations listed to be available.
+ // {PKCS12_SHA1_3KEY_3DES_CBC_OID, QCryptographicHash::Sha1},
+ // {PKCS12_SHA1_2KEY_3DES_CBC_OID, QCryptographicHash::Sha1},
+ // {PKCS12_SHA1_RC2_128_CBC_OID, QCryptographicHash::Sha1},
+ // {PKCS12_SHA1_RC2_40_CBC_OID, QCryptographicHash::Sha1}
+};
+
+
+static EncryptionData readPbes1(const QVector<QAsn1Element> &element, const QByteArray &encryptionScheme, const QByteArray &passPhrase)
+{
+ // RFC 8018: https://tools.ietf.org/html/rfc8018#section-6.1
+ // Steps refer to this section: https://tools.ietf.org/html/rfc8018#section-6.1.2
+ /*** Scheme: ***
+ * Sequence (PBE Parameter)
+ * Octet string (salt)
+ * Integer (iteration counter)
+ */
+ // Step 1
+ if (element.size() != 2
+ || element[0].type() != QAsn1Element::ElementType::OctetStringType
+ || element[1].type() != QAsn1Element::ElementType::IntegerType) {
+ return {};
+ }
+ QByteArray salt = element[0].value();
+ if (salt.size() != 8)
+ return {};
+
+ int iterationCount = element[1].toInteger();
+ if (iterationCount < 0)
+ return {};
+
+ // Step 2
+ auto iterator = pbes1OidHashFunctionMap.constFind(encryptionScheme);
+ if (iterator == pbes1OidHashFunctionMap.cend()) {
+ // Qt was compiled with ONLY_SHA1 (or it's MD2)
+ return {};
+ }
+ QCryptographicHash::Algorithm hashAlgorithm = *iterator;
+ QByteArray key = QPasswordDigestor::deriveKeyPbkdf1(hashAlgorithm, passPhrase, salt, iterationCount, 16);
+ if (key.size() != 16)
+ return {};
+
+ // Step 3
+ QByteArray iv = key.right(8); // last 8 bytes are used as IV
+ key.truncate(8); // first 8 bytes are used for the key
+
+ QSslKeyPrivate::Cipher cipher = oidCipherMap[encryptionScheme];
+#ifdef Q_OS_WINRT
+ // @todo: document this instead? find some other solution?
+ if (cipher == QSslKeyPrivate::Cipher::Rc2Cbc)
+ qWarning("PBES1 with RC2_CBC doesn't work properly on WinRT.");
+#endif
+ // Steps 4-6 are done after returning
+ return {cipher, key, iv};
+}
+
+QByteArray QSslKeyPrivate::decryptPkcs8(const QByteArray &encrypted, const QByteArray &passPhrase)
+{
+ // RFC 5958: https://tools.ietf.org/html/rfc5958
+ /*** Scheme: ***
+ * Sequence
+ * Sequence
+ * Object Identifier (encryption scheme (currently PBES2, PBES1, @todo PKCS12))
+ * Sequence (scheme parameters)
+ * Octet String (the encrypted data)
+ */
+ QAsn1Element elem;
+ if (!elem.read(encrypted) || elem.type() != QAsn1Element::SequenceType)
+ return encrypted;
+
+ const QVector<QAsn1Element> items = elem.toVector();
+ if (items.size() != 2
+ || items[0].type() != QAsn1Element::SequenceType
+ || items[1].type() != QAsn1Element::OctetStringType) {
+ return encrypted;
+ }
+
+ const QVector<QAsn1Element> encryptionSchemeContainer = items[0].toVector();
+
+ if (encryptionSchemeContainer.size() != 2
+ || encryptionSchemeContainer[0].type() != QAsn1Element::ObjectIdentifierType
+ || encryptionSchemeContainer[1].type() != QAsn1Element::SequenceType) {
+ return encrypted;
+ }
+
+ const QByteArray encryptionScheme = encryptionSchemeContainer[0].toObjectId();
+ const QVector<QAsn1Element> schemeParameterContainer = encryptionSchemeContainer[1].toVector();
+
+ if (schemeParameterContainer.size() != 2
+ && schemeParameterContainer[0].type() != QAsn1Element::SequenceType
+ && schemeParameterContainer[1].type() != QAsn1Element::SequenceType) {
+ return encrypted;
+ }
+
+ EncryptionData data;
+ if (encryptionScheme == PKCS5_PBES2_ENCRYPTION_OID) {
+ data = readPbes2(schemeParameterContainer, passPhrase);
+ } else if (pbes1OidHashFunctionMap.contains(encryptionScheme)) {
+ data = readPbes1(schemeParameterContainer, encryptionScheme, passPhrase);
+ } else if (encryptionScheme.startsWith(PKCS12_OID)) {
+ Q_UNIMPLEMENTED(); // this isn't some 'unknown', I know these aren't implemented
+ return encrypted;
+ } else {
+ qWarning()
+ << "QSslKey: Unsupported encryption scheme OID:" << encryptionScheme
+ << "\nFile a bugreport to Qt (include the line above).";
+ return encrypted;
+ }
+
+ if (!data.initialized) {
+ // something went wrong, return
+ return encrypted;
+ }
+
+ QByteArray decryptedKey = decrypt(data.cipher, items[1].value(), data.key, data.iv);
+ // The data is still wrapped in a octet string, so let's unwrap it
+ QAsn1Element decryptedKeyElement(QAsn1Element::ElementType::OctetStringType, decryptedKey);
+ return decryptedKeyElement.value();
+}
diff --git a/src/network/ssl/qsslpresharedkeyauthenticator.cpp b/src/network/ssl/qsslpresharedkeyauthenticator.cpp
index 8e1313493f..3bb2719026 100644
--- a/src/network/ssl/qsslpresharedkeyauthenticator.cpp
+++ b/src/network/ssl/qsslpresharedkeyauthenticator.cpp
@@ -83,28 +83,13 @@ QSslPreSharedKeyAuthenticatorPrivate::QSslPreSharedKeyAuthenticatorPrivate()
completing the PSK handshake. The client application needs to connect a
slot to the QSslSocket::preSharedKeyAuthenticationRequired() signal:
- \code
-
- connect(socket, &QSslSocket::preSharedKeyAuthenticationRequired,
- this, &AuthManager::handlePreSharedKeyAuthentication);
-
- \endcode
+ \snippet code/src_network_ssl_qsslpresharedkeyauthenticator.cpp 0
The signal carries a QSslPreSharedKeyAuthenticator object containing the
identity hint the server sent to the client, and which must be filled with the
corresponding client identity and the derived key:
- \code
-
- void AuthManager::handlePreSharedKeyAuthentication(QSslPreSharedKeyAuthenticator *authenticator)
- {
- authenticator->setIdentity("My Qt App");
-
- const QByteArray key = deriveKey(authenticator->identityHint(), passphrase);
- authenticator->setPreSharedKey(key);
- }
-
- \endcode
+ \snippet code/src_network_ssl_qsslpresharedkeyauthenticator.cpp 1
\note PSK ciphersuites are supported only when using OpenSSL 1.0.1 (or
greater) as the SSL backend.
diff --git a/src/network/ssl/qsslpresharedkeyauthenticator.h b/src/network/ssl/qsslpresharedkeyauthenticator.h
index 74ab888000..423f7731b4 100644
--- a/src/network/ssl/qsslpresharedkeyauthenticator.h
+++ b/src/network/ssl/qsslpresharedkeyauthenticator.h
@@ -78,6 +78,7 @@ public:
private:
friend Q_NETWORK_EXPORT bool operator==(const QSslPreSharedKeyAuthenticator &lhs, const QSslPreSharedKeyAuthenticator &rhs);
friend class QSslSocketBackendPrivate;
+ friend class QDtlsPrivateOpenSSL;
QSharedDataPointer<QSslPreSharedKeyAuthenticatorPrivate> d;
};
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index ee157082ea..4a9d054c0d 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -336,12 +336,20 @@ QT_BEGIN_NAMESPACE
class QSslSocketGlobalData
{
public:
- QSslSocketGlobalData() : config(new QSslConfigurationPrivate) {}
+ QSslSocketGlobalData()
+ : config(new QSslConfigurationPrivate),
+ dtlsConfig(new QSslConfigurationPrivate)
+ {
+#if QT_CONFIG(dtls)
+ dtlsConfig->protocol = QSsl::DtlsV1_2OrLater;
+#endif // dtls
+ }
QMutex mutex;
QList<QSslCipher> supportedCiphers;
QVector<QSslEllipticCurve> supportedEllipticCurves;
QExplicitlySharedDataPointer<QSslConfigurationPrivate> config;
+ QExplicitlySharedDataPointer<QSslConfigurationPrivate> dtlsConfig;
};
Q_GLOBAL_STATIC(QSslSocketGlobalData, globalData)
@@ -371,7 +379,7 @@ QSslSocket::~QSslSocket()
qCDebug(lcSsl) << "QSslSocket::~QSslSocket(), this =" << (void *)this;
#endif
delete d->plainSocket;
- d->plainSocket = 0;
+ d->plainSocket = nullptr;
}
/*!
@@ -445,6 +453,12 @@ void QSslSocket::connectToHostEncrypted(const QString &hostName, quint16 port, O
return;
}
+ if (!supportsSsl()) {
+ qCWarning(lcSsl, "QSslSocket::connectToHostEncrypted: TLS initialization failed");
+ d->setErrorAndEmit(QAbstractSocket::SslInternalError, tr("TLS initialization failed"));
+ return;
+ }
+
d->init();
d->autoStartHandshake = true;
d->initialized = true;
@@ -476,6 +490,12 @@ void QSslSocket::connectToHostEncrypted(const QString &hostName, quint16 port,
return;
}
+ if (!supportsSsl()) {
+ qCWarning(lcSsl, "QSslSocket::connectToHostEncrypted: TLS initialization failed");
+ d->setErrorAndEmit(QAbstractSocket::SslInternalError, tr("TLS initialization failed"));
+ return;
+ }
+
d->init();
d->autoStartHandshake = true;
d->initialized = true;
@@ -1820,6 +1840,12 @@ void QSslSocket::startClientEncryption()
"QSslSocket::startClientEncryption: cannot start handshake when not connected");
return;
}
+
+ if (!supportsSsl()) {
+ qCWarning(lcSsl, "QSslSocket::startClientEncryption: TLS initialization failed");
+ d->setErrorAndEmit(QAbstractSocket::SslInternalError, tr("TLS initialization failed"));
+ return;
+ }
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << "QSslSocket::startClientEncryption()";
#endif
@@ -1858,6 +1884,11 @@ void QSslSocket::startServerEncryption()
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << "QSslSocket::startServerEncryption()";
#endif
+ if (!supportsSsl()) {
+ qCWarning(lcSsl, "QSslSocket::startServerEncryption: TLS initialization failed");
+ d->setErrorAndEmit(QAbstractSocket::SslInternalError, tr("TLS initialization failed"));
+ return;
+ }
d->mode = SslServerMode;
emit modeChanged(d->mode);
d->startServerEncryption();
@@ -2049,9 +2080,9 @@ QSslSocketPrivate::QSslSocketPrivate()
, connectionEncrypted(false)
, shutdown(false)
, ignoreAllSslErrors(false)
- , readyReadEmittedPointer(0)
+ , readyReadEmittedPointer(nullptr)
, allowRootCertOnDemandLoading(true)
- , plainSocket(0)
+ , plainSocket(nullptr)
, paused(false)
, flushTriggered(false)
{
@@ -2131,6 +2162,26 @@ void QSslSocketPrivate::setDefaultSupportedCiphers(const QList<QSslCipher> &ciph
/*!
\internal
*/
+void q_setDefaultDtlsCiphers(const QList<QSslCipher> &ciphers)
+{
+ QMutexLocker locker(&globalData()->mutex);
+ globalData()->dtlsConfig.detach();
+ globalData()->dtlsConfig->ciphers = ciphers;
+}
+
+/*!
+ \internal
+*/
+QList<QSslCipher> q_getDefaultDtlsCiphers()
+{
+ QSslSocketPrivate::ensureInitialized();
+ QMutexLocker locker(&globalData()->mutex);
+ return globalData()->dtlsConfig->ciphers;
+}
+
+/*!
+ \internal
+*/
QVector<QSslEllipticCurve> QSslSocketPrivate::supportedEllipticCurves()
{
QSslSocketPrivate::ensureInitialized();
@@ -2145,6 +2196,7 @@ void QSslSocketPrivate::setDefaultSupportedEllipticCurves(const QVector<QSslElli
{
const QMutexLocker locker(&globalData()->mutex);
globalData()->config.detach();
+ globalData()->dtlsConfig.detach();
globalData()->supportedEllipticCurves = curves;
}
@@ -2167,6 +2219,8 @@ void QSslSocketPrivate::setDefaultCaCertificates(const QList<QSslCertificate> &c
QMutexLocker locker(&globalData()->mutex);
globalData()->config.detach();
globalData()->config->caCertificates = certs;
+ globalData()->dtlsConfig.detach();
+ globalData()->dtlsConfig->caCertificates = certs;
// when the certificates are set explicitly, we do not want to
// load the system certificates on demand
s_loadRootCertsOnDemand = false;
@@ -2186,6 +2240,8 @@ bool QSslSocketPrivate::addDefaultCaCertificates(const QString &path, QSsl::Enco
QMutexLocker locker(&globalData()->mutex);
globalData()->config.detach();
globalData()->config->caCertificates += certs;
+ globalData()->dtlsConfig.detach();
+ globalData()->dtlsConfig->caCertificates += certs;
return true;
}
@@ -2198,6 +2254,8 @@ void QSslSocketPrivate::addDefaultCaCertificate(const QSslCertificate &cert)
QMutexLocker locker(&globalData()->mutex);
globalData()->config.detach();
globalData()->config->caCertificates += cert;
+ globalData()->dtlsConfig.detach();
+ globalData()->dtlsConfig->caCertificates += cert;
}
/*!
@@ -2209,6 +2267,8 @@ void QSslSocketPrivate::addDefaultCaCertificates(const QList<QSslCertificate> &c
QMutexLocker locker(&globalData()->mutex);
globalData()->config.detach();
globalData()->config->caCertificates += certs;
+ globalData()->dtlsConfig.detach();
+ globalData()->dtlsConfig->caCertificates += certs;
}
/*!
@@ -2261,6 +2321,33 @@ void QSslConfigurationPrivate::deepCopyDefaultConfiguration(QSslConfigurationPri
ptr->sslOptions = global->sslOptions;
ptr->ellipticCurves = global->ellipticCurves;
ptr->backendConfig = global->backendConfig;
+#if QT_CONFIG(dtls)
+ ptr->dtlsCookieEnabled = global->dtlsCookieEnabled;
+#endif
+}
+
+/*!
+ \internal
+*/
+QSslConfiguration QSslConfigurationPrivate::defaultDtlsConfiguration()
+{
+ QSslSocketPrivate::ensureInitialized();
+ QMutexLocker locker(&globalData()->mutex);
+
+ return QSslConfiguration(globalData()->dtlsConfig.data());
+}
+
+/*!
+ \internal
+*/
+void QSslConfigurationPrivate::setDefaultDtlsConfiguration(const QSslConfiguration &configuration)
+{
+ QSslSocketPrivate::ensureInitialized();
+ QMutexLocker locker(&globalData()->mutex);
+ if (globalData()->dtlsConfig == configuration.d)
+ return; // nothing to do
+
+ globalData()->dtlsConfig = const_cast<QSslConfigurationPrivate*>(configuration.d.constData());
}
/*!
diff --git a/src/network/ssl/qsslsocket_mac.cpp b/src/network/ssl/qsslsocket_mac.cpp
index aa0e1b0dd1..9166e0ac29 100644
--- a/src/network/ssl/qsslsocket_mac.cpp
+++ b/src/network/ssl/qsslsocket_mac.cpp
@@ -48,6 +48,7 @@
#include <QtCore/qmessageauthenticationcode.h>
#include <QtCore/qoperatingsystemversion.h>
+#include <QtCore/qscopedvaluerollback.h>
#include <QtCore/qcryptographichash.h>
#include <QtCore/qsystemdetection.h>
#include <QtCore/qdatastream.h>
@@ -242,48 +243,70 @@ static const uint8_t dhparam[] =
"\x90\x0b\x35\x64\xff\xd9\xe3\xac\xf2\xf2\xeb\x3a\x63\x02\x01\x02";
#endif
-// No ioErr on iOS/tvOS/watchOS. (defined in MacErrors.h on macOS)
-#if defined(QT_PLATFORM_UIKIT)
-# define ioErr -36
-#endif
-
-static OSStatus _q_SSLRead(QTcpSocket *plainSocket, char *data, size_t *dataLength)
+OSStatus QSslSocketBackendPrivate::ReadCallback(QSslSocketBackendPrivate *socket,
+ char *data, size_t *dataLength)
{
- Q_ASSERT(plainSocket);
+ Q_ASSERT(socket);
Q_ASSERT(data);
Q_ASSERT(dataLength);
+ QTcpSocket *plainSocket = socket->plainSocket;
+ Q_ASSERT(plainSocket);
+
+ if (socket->isHandshakeComplete()) {
+ // Check if it's a renegotiation attempt, when the handshake is complete, the
+ // session state is 'kSSLConnected':
+ SSLSessionState currentState = kSSLConnected;
+ const OSStatus result = SSLGetSessionState(socket->context, &currentState);
+ if (result != noErr) {
+ *dataLength = 0;
+ return result;
+ }
+
+ if (currentState == kSSLHandshake) {
+ // Renegotiation detected, don't allow read more yet - 'transmit'
+ // will notice this and will call 'startHandshake':
+ *dataLength = 0;
+ socket->renegotiating = true;
+ return errSSLWouldBlock;
+ }
+ }
+
const qint64 bytes = plainSocket->read(data, *dataLength);
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << plainSocket << "read" << bytes;
#endif
if (bytes < 0) {
*dataLength = 0;
- return ioErr;
+ return errSecIO;
}
- const OSStatus err = (size_t(bytes) < *dataLength) ? errSSLWouldBlock : noErr;
+ const OSStatus err = (size_t(bytes) < *dataLength) ? errSSLWouldBlock : errSecSuccess;
*dataLength = bytes;
return err;
}
-static OSStatus _q_SSLWrite(QTcpSocket *plainSocket, const char *data, size_t *dataLength)
+OSStatus QSslSocketBackendPrivate::WriteCallback(QSslSocketBackendPrivate *socket,
+ const char *data, size_t *dataLength)
{
- Q_ASSERT(plainSocket);
+ Q_ASSERT(socket);
Q_ASSERT(data);
Q_ASSERT(dataLength);
+ QTcpSocket *plainSocket = socket->plainSocket;
+ Q_ASSERT(plainSocket);
+
const qint64 bytes = plainSocket->write(data, *dataLength);
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << plainSocket << "write" << bytes;
#endif
if (bytes < 0) {
*dataLength = 0;
- return ioErr;
+ return errSecIO;
}
- const OSStatus err = (size_t(bytes) < *dataLength) ? errSSLWouldBlock : noErr;
+ const OSStatus err = (size_t(bytes) < *dataLength) ? errSSLWouldBlock : errSecSuccess;
*dataLength = bytes;
return err;
@@ -387,12 +410,12 @@ void QSslSocketBackendPrivate::continueHandshake()
Q_Q(QSslSocket);
connectionEncrypted = true;
-#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_NA, __IPHONE_11_0, __TVOS_11_0, __WATCHOS_4_0)
+#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13_4, __IPHONE_11_0, __TVOS_11_0, __WATCHOS_4_0)
// Unlike OpenSSL, Secure Transport does not allow to negotiate protocols via
// a callback during handshake. We can only set our list of preferred protocols
// (and send it during handshake) and then receive what our peer has sent to us.
// And here we can finally try to find a match (if any).
- if (__builtin_available(iOS 11.0, tvOS 11.0, watchOS 4.0, *)) {
+ if (__builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)) {
const auto &requestedProtocols = configuration.nextAllowedProtocols;
if (const int requestedCount = requestedProtocols.size()) {
configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNone;
@@ -423,7 +446,9 @@ void QSslSocketBackendPrivate::continueHandshake()
}
#endif // QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE
- emit q->encrypted();
+ if (!renegotiating)
+ emit q->encrypted();
+
if (autoStartHandshake && pendingClose) {
pendingClose = false;
q->disconnectFromHost();
@@ -452,7 +477,7 @@ void QSslSocketBackendPrivate::disconnectFromHost()
QSslCipher QSslSocketBackendPrivate::sessionCipher() const
{
SSLCipherSuite cipher = 0;
- if (context && SSLGetNegotiatedCipher(context, &cipher) == noErr)
+ if (context && SSLGetNegotiatedCipher(context, &cipher) == errSecSuccess)
return QSslCipher_from_SSLCipherSuite(cipher);
return QSslCipher();
@@ -465,7 +490,7 @@ QSsl::SslProtocol QSslSocketBackendPrivate::sessionProtocol() const
SSLProtocol protocol = kSSLProtocolUnknown;
const OSStatus err = SSLGetNegotiatedProtocolVersion(context, &protocol);
- if (err != noErr) {
+ if (err != errSecSuccess) {
qCWarning(lcSsl) << "SSLGetNegotiatedProtocolVersion failed:" << err;
return QSsl::UnknownProtocol;
}
@@ -521,10 +546,10 @@ void QSslSocketBackendPrivate::transmit()
if (!context || shutdown)
return;
- if (!connectionEncrypted)
+ if (!isHandshakeComplete())
startHandshake();
- if (connectionEncrypted && !writeBuffer.isEmpty()) {
+ if (isHandshakeComplete() && !writeBuffer.isEmpty()) {
qint64 totalBytesWritten = 0;
while (writeBuffer.nextDataBlockSize() > 0 && context) {
const size_t nextDataBlockSize = writeBuffer.nextDataBlockSize();
@@ -533,7 +558,7 @@ void QSslSocketBackendPrivate::transmit()
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << plainSocket << "SSLWrite returned" << err;
#endif
- if (err != noErr && err != errSSLWouldBlock) {
+ if (err != errSecSuccess && err != errSSLWouldBlock) {
setErrorAndEmit(QAbstractSocket::SslInternalError,
QStringLiteral("SSLWrite failed: %1").arg(err));
break;
@@ -559,7 +584,7 @@ void QSslSocketBackendPrivate::transmit()
}
}
- if (connectionEncrypted) {
+ if (isHandshakeComplete()) {
QVarLengthArray<char, 4096> data;
while (context && (!readBufferMaxSize || buffer.size() < readBufferMaxSize)) {
size_t readBytes = 0;
@@ -573,12 +598,17 @@ void QSslSocketBackendPrivate::transmit()
setErrorAndEmit(QAbstractSocket::RemoteHostClosedError,
QSslSocket::tr("The TLS/SSL connection has been closed"));
break;
- } else if (err != noErr && err != errSSLWouldBlock) {
+ } else if (err != errSecSuccess && err != errSSLWouldBlock) {
setErrorAndEmit(QAbstractSocket::SslInternalError,
QStringLiteral("SSLRead failed: %1").arg(err));
break;
}
+ if (err == errSSLWouldBlock && renegotiating) {
+ startHandshake();
+ break;
+ }
+
if (readBytes) {
buffer.append(data.constData(), readBytes);
if (readyReadEmittedPointer)
@@ -861,16 +891,17 @@ bool QSslSocketBackendPrivate::initSslContext()
return false;
}
- const OSStatus err = SSLSetIOFuncs(context, reinterpret_cast<SSLReadFunc>(&_q_SSLRead),
- reinterpret_cast<SSLWriteFunc>(&_q_SSLWrite));
- if (err != noErr) {
+ const OSStatus err = SSLSetIOFuncs(context,
+ reinterpret_cast<SSLReadFunc>(&QSslSocketBackendPrivate::ReadCallback),
+ reinterpret_cast<SSLWriteFunc>(&QSslSocketBackendPrivate::WriteCallback));
+ if (err != errSecSuccess) {
destroySslContext();
setErrorAndEmit(QAbstractSocket::SslInternalError,
QStringLiteral("SSLSetIOFuncs failed: %1").arg(err));
return false;
}
- SSLSetConnection(context, plainSocket);
+ SSLSetConnection(context, this);
if (mode == QSslSocket::SslServerMode
&& !configuration.localCertificateChain.isEmpty()) {
@@ -889,8 +920,8 @@ bool QSslSocketBackendPrivate::initSslContext()
return false;
}
-#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_NA, __IPHONE_11_0, __TVOS_11_0, __WATCHOS_4_0)
- if (__builtin_available(iOS 11.0, tvOS 11.0, watchOS 4.0, *)) {
+#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13_4, __IPHONE_11_0, __TVOS_11_0, __WATCHOS_4_0)
+ if (__builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)) {
const auto protocolNames = configuration.nextAllowedProtocols;
QCFType<CFMutableArrayRef> cfNames(CFArrayCreateMutable(nullptr, 0, &kCFTypeArrayCallBacks));
if (cfNames) {
@@ -922,10 +953,10 @@ bool QSslSocketBackendPrivate::initSslContext()
SSLSetPeerDomainName(context, ace.data(), ace.size());
// tell SecureTransport we handle peer verification ourselves
OSStatus err = SSLSetSessionOption(context, kSSLSessionOptionBreakOnServerAuth, true);
- if (err == noErr)
+ if (err == errSecSuccess)
err = SSLSetSessionOption(context, kSSLSessionOptionBreakOnCertRequested, true);
- if (err != noErr) {
+ if (err != errSecSuccess) {
destroySslContext();
setErrorAndEmit(QSslSocket::SslInternalError,
QStringLiteral("SSLSetSessionOption failed: %1").arg(err));
@@ -936,13 +967,13 @@ bool QSslSocketBackendPrivate::initSslContext()
if (configuration.peerVerifyMode != QSslSocket::VerifyNone) {
// kAlwaysAuthenticate - always fails even if we set break on client auth.
OSStatus err = SSLSetClientSideAuthenticate(context, kTryAuthenticate);
- if (err == noErr) {
+ if (err == errSecSuccess) {
// We'd like to verify peer ourselves, otherwise handshake will
// most probably fail before we can do anything.
err = SSLSetSessionOption(context, kSSLSessionOptionBreakOnClientAuth, true);
}
- if (err != noErr) {
+ if (err != errSecSuccess) {
destroySslContext();
setErrorAndEmit(QAbstractSocket::SslInternalError,
QStringLiteral("failed to set SSL context option in server mode: %1").arg(err));
@@ -1005,7 +1036,7 @@ bool QSslSocketBackendPrivate::setSessionCertificate(QString &errorDescription,
nullptr, nullptr);
QCFType<CFArrayRef> items;
OSStatus err = SecPKCS12Import(pkcs12, options, &items);
- if (err != noErr) {
+ if (err != errSecSuccess) {
#ifdef QSSLSOCKET_DEBUG
qCWarning(lcSsl) << plainSocket
<< QStringLiteral("SecPKCS12Import failed: %1").arg(err);
@@ -1051,7 +1082,7 @@ bool QSslSocketBackendPrivate::setSessionCertificate(QString &errorDescription,
}
err = SSLSetCertificate(context, certs);
- if (err != noErr) {
+ if (err != errSecSuccess) {
#ifdef QSSLSOCKET_DEBUG
qCWarning(lcSsl) << plainSocket
<< QStringLiteral("Cannot set certificate and key: %1").arg(err);
@@ -1079,35 +1110,35 @@ bool QSslSocketBackendPrivate::setSessionProtocol()
return false;
}
- OSStatus err = noErr;
+ OSStatus err = errSecSuccess;
if (configuration.protocol == QSsl::SslV3) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << plainSocket << "requesting : SSLv3";
#endif
err = SSLSetProtocolVersionMin(context, kSSLProtocol3);
- if (err == noErr)
+ if (err == errSecSuccess)
err = SSLSetProtocolVersionMax(context, kSSLProtocol3);
} else if (configuration.protocol == QSsl::TlsV1_0) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.0";
#endif
err = SSLSetProtocolVersionMin(context, kTLSProtocol1);
- if (err == noErr)
+ if (err == errSecSuccess)
err = SSLSetProtocolVersionMax(context, kTLSProtocol1);
} else if (configuration.protocol == QSsl::TlsV1_1) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.1";
#endif
err = SSLSetProtocolVersionMin(context, kTLSProtocol11);
- if (err == noErr)
+ if (err == errSecSuccess)
err = SSLSetProtocolVersionMax(context, kTLSProtocol11);
} else if (configuration.protocol == QSsl::TlsV1_2) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.2";
#endif
err = SSLSetProtocolVersionMin(context, kTLSProtocol12);
- if (err == noErr)
+ if (err == errSecSuccess)
err = SSLSetProtocolVersionMax(context, kTLSProtocol12);
} else if (configuration.protocol == QSsl::AnyProtocol) {
#ifdef QSSLSOCKET_DEBUG
@@ -1115,42 +1146,42 @@ bool QSslSocketBackendPrivate::setSessionProtocol()
#endif
// kSSLProtocol3, since kSSLProtocol2 is disabled:
err = SSLSetProtocolVersionMin(context, kSSLProtocol3);
- if (err == noErr)
+ if (err == errSecSuccess)
err = SSLSetProtocolVersionMax(context, kTLSProtocol12);
} else if (configuration.protocol == QSsl::TlsV1SslV3) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << plainSocket << "requesting : SSLv3 - TLSv1.2";
#endif
err = SSLSetProtocolVersionMin(context, kSSLProtocol3);
- if (err == noErr)
+ if (err == errSecSuccess)
err = SSLSetProtocolVersionMax(context, kTLSProtocol12);
} else if (configuration.protocol == QSsl::SecureProtocols) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << plainSocket << "requesting : TLSv1 - TLSv1.2";
#endif
err = SSLSetProtocolVersionMin(context, kTLSProtocol1);
- if (err == noErr)
+ if (err == errSecSuccess)
err = SSLSetProtocolVersionMax(context, kTLSProtocol12);
} else if (configuration.protocol == QSsl::TlsV1_0OrLater) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << plainSocket << "requesting : TLSv1 - TLSv1.2";
#endif
err = SSLSetProtocolVersionMin(context, kTLSProtocol1);
- if (err == noErr)
+ if (err == errSecSuccess)
err = SSLSetProtocolVersionMax(context, kTLSProtocol12);
} else if (configuration.protocol == QSsl::TlsV1_1OrLater) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.1 - TLSv1.2";
#endif
err = SSLSetProtocolVersionMin(context, kTLSProtocol11);
- if (err == noErr)
+ if (err == errSecSuccess)
err = SSLSetProtocolVersionMax(context, kTLSProtocol12);
} else if (configuration.protocol == QSsl::TlsV1_2OrLater) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.2";
#endif
err = SSLSetProtocolVersionMin(context, kTLSProtocol12);
- if (err == noErr)
+ if (err == errSecSuccess)
err = SSLSetProtocolVersionMax(context, kTLSProtocol12);
} else {
#ifdef QSSLSOCKET_DEBUG
@@ -1159,7 +1190,7 @@ bool QSslSocketBackendPrivate::setSessionProtocol()
return false;
}
- return err == noErr;
+ return err == errSecSuccess;
}
bool QSslSocketBackendPrivate::canIgnoreTrustVerificationFailure() const
@@ -1204,8 +1235,8 @@ bool QSslSocketBackendPrivate::verifyPeerTrust()
QCFType<SecTrustRef> trust;
OSStatus err = SSLCopyPeerTrust(context, &trust);
- // !trust - SSLCopyPeerTrust can return noErr but null trust.
- if (err != noErr || !trust) {
+ // !trust - SSLCopyPeerTrust can return errSecSuccess but null trust.
+ if (err != errSecSuccess || !trust) {
if (!canIgnoreVerify) {
setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
QStringLiteral("Failed to obtain peer trust: %1").arg(err));
@@ -1217,40 +1248,38 @@ bool QSslSocketBackendPrivate::verifyPeerTrust()
}
QList<QSslError> errors;
- // store certificates
- const int certCount = SecTrustGetCertificateCount(trust);
- // TODO: why this test depends on configuration.peerCertificateChain not being empty????
- if (configuration.peerCertificateChain.isEmpty()) {
- // Apple's docs say SetTrustEvaluate must be called before
- // SecTrustGetCertificateAtIndex, but this results
- // in 'kSecTrustResultRecoverableTrustFailure', so
- // here we just ignore 'res' (later we'll use SetAnchor etc.
- // and evaluate again).
- SecTrustResultType res = kSecTrustResultInvalid;
- err = SecTrustEvaluate(trust, &res);
- if (err != noErr) {
- // We can not ignore this, it's not even about trust verification
- // probably ...
- setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
- QStringLiteral("SecTrustEvaluate failed: %1").arg(err));
- plainSocket->disconnectFromHost();
- return false;
- }
- for (int i = 0; i < certCount; ++i) {
- SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, i);
- QCFType<CFDataRef> derData = SecCertificateCopyData(cert);
- configuration.peerCertificateChain << QSslCertificate(QByteArray::fromCFData(derData), QSsl::Der);
- }
+ // Store certificates.
+ // Apple's docs say SetTrustEvaluate must be called before
+ // SecTrustGetCertificateAtIndex, but this results
+ // in 'kSecTrustResultRecoverableTrustFailure', so
+ // here we just ignore 'res' (later we'll use SetAnchor etc.
+ // and evaluate again).
+ SecTrustResultType res = kSecTrustResultInvalid;
+ err = SecTrustEvaluate(trust, &res);
+ if (err != errSecSuccess) {
+ // We can not ignore this, it's not even about trust verification
+ // probably ...
+ setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
+ QStringLiteral("SecTrustEvaluate failed: %1").arg(err));
+ plainSocket->disconnectFromHost();
+ return false;
}
- if (certCount > 0) {
- SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, 0);
+ configuration.peerCertificate.clear();
+ configuration.peerCertificateChain.clear();
+
+ const CFIndex certCount = SecTrustGetCertificateCount(trust);
+ for (CFIndex i = 0; i < certCount; ++i) {
+ SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, i);
QCFType<CFDataRef> derData = SecCertificateCopyData(cert);
- configuration.peerCertificate = QSslCertificate(QByteArray::fromCFData(derData), QSsl::Der);
+ configuration.peerCertificateChain << QSslCertificate(QByteArray::fromCFData(derData), QSsl::Der);
}
- // check the whole chain for blacklisting (including root, as we check for subjectInfo and issuer)
+ if (configuration.peerCertificateChain.size())
+ configuration.peerCertificate = configuration.peerCertificateChain.at(0);
+
+ // Check the whole chain for blacklisting (including root, as we check for subjectInfo and issuer):
for (const QSslCertificate &cert : qAsConst(configuration.peerCertificateChain)) {
if (QSslCertificatePrivate::isBlacklisted(cert) && !canIgnoreVerify) {
const QSslError error(QSslError::CertificateBlacklisted, cert);
@@ -1294,10 +1323,10 @@ bool QSslSocketBackendPrivate::verifyPeerTrust()
}
// verify certificate chain
- QCFType<CFMutableArrayRef> certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ QCFType<CFMutableArrayRef> certArray = CFArrayCreateMutable(nullptr, 0, &kCFTypeArrayCallBacks);
for (const QSslCertificate &cert : qAsConst(configuration.caCertificates)) {
QCFType<CFDataRef> certData = cert.d->derData.toCFData();
- if (QCFType<SecCertificateRef> secRef = SecCertificateCreateWithData(NULL, certData))
+ if (QCFType<SecCertificateRef> secRef = SecCertificateCreateWithData(nullptr, certData))
CFArrayAppendValue(certArray, secRef);
else
qCWarning(lcSsl, "Failed to create SecCertificate from QSslCertificate");
@@ -1422,6 +1451,7 @@ bool QSslSocketBackendPrivate::startHandshake()
// Failure means a real error (invalid certificate, no private key, etc).
if (!setSessionCertificate(errorDescription, errorCode)) {
setErrorAndEmit(errorCode, errorDescription);
+ renegotiating = false;
return false;
} else {
// We try to resume a handshake, even if have no
@@ -1436,6 +1466,7 @@ bool QSslSocketBackendPrivate::startHandshake()
return startHandshake();
}
+ renegotiating = false;
setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
QStringLiteral("SSLHandshake failed: %1").arg(err));
plainSocket->disconnectFromHost();
@@ -1445,6 +1476,7 @@ bool QSslSocketBackendPrivate::startHandshake()
// Connection aborted during handshake phase.
if (q->state() != QAbstractSocket::ConnectedState) {
qCDebug(lcSsl) << "connection aborted";
+ renegotiating = false;
return false;
}
@@ -1453,13 +1485,16 @@ bool QSslSocketBackendPrivate::startHandshake()
if (!verifySessionProtocol()) {
setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, QStringLiteral("Protocol version mismatch"));
plainSocket->disconnectFromHost();
+ renegotiating = false;
return false;
}
if (verifyPeerTrust()) {
continueHandshake();
+ renegotiating = false;
return true;
} else {
+ renegotiating = false;
return false;
}
}
diff --git a/src/network/ssl/qsslsocket_mac_p.h b/src/network/ssl/qsslsocket_mac_p.h
index 34e30ebb16..e37171e56a 100644
--- a/src/network/ssl/qsslsocket_mac_p.h
+++ b/src/network/ssl/qsslsocket_mac_p.h
@@ -120,7 +120,14 @@ private:
bool checkSslErrors();
bool startHandshake();
+ bool isHandshakeComplete() const {return connectionEncrypted && !renegotiating;}
+
+ // IO callbacks:
+ static OSStatus ReadCallback(QSslSocketBackendPrivate *socket, char *data, size_t *dataLength);
+ static OSStatus WriteCallback(QSslSocketBackendPrivate *plainSocket, const char *data, size_t *dataLength);
+
QSecureTransportContext context;
+ bool renegotiating = false;
Q_DISABLE_COPY(QSslSocketBackendPrivate)
};
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index 11f8a40199..64501a75e8 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -66,6 +66,10 @@
#include "qsslpresharedkeyauthenticator.h"
#include "qsslpresharedkeyauthenticator_p.h"
+#ifdef Q_OS_WIN
+#include "qwindowscarootfetcher_p.h"
+#endif
+
#include <QtCore/qdatetime.h>
#include <QtCore/qdebug.h>
#include <QtCore/qdir.h>
@@ -77,15 +81,16 @@
#include <QtCore/qthread.h>
#include <QtCore/qurl.h>
#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qscopedvaluerollback.h>
#include <string.h>
QT_BEGIN_NAMESPACE
#if defined(Q_OS_WIN)
- PtrCertOpenSystemStoreW QSslSocketPrivate::ptrCertOpenSystemStoreW = 0;
- PtrCertFindCertificateInStore QSslSocketPrivate::ptrCertFindCertificateInStore = 0;
- PtrCertCloseStore QSslSocketPrivate::ptrCertCloseStore = 0;
+ PtrCertOpenSystemStoreW QSslSocketPrivate::ptrCertOpenSystemStoreW = nullptr;
+ PtrCertFindCertificateInStore QSslSocketPrivate::ptrCertFindCertificateInStore = nullptr;
+ PtrCertCloseStore QSslSocketPrivate::ptrCertCloseStore = nullptr;
#endif
bool QSslSocketPrivate::s_libraryLoaded = false;
@@ -99,12 +104,13 @@ int QSslSocketBackendPrivate::s_indexForSSLExtraData = -1;
QString QSslSocketBackendPrivate::getErrorsFromOpenSsl()
{
QString errorString;
+ char buf[256] = {}; // OpenSSL docs claim both 120 and 256; use the larger.
unsigned long errNum;
while ((errNum = q_ERR_get_error())) {
- if (! errorString.isEmpty())
+ if (!errorString.isEmpty())
errorString.append(QLatin1String(", "));
- const char *error = q_ERR_error_string(errNum, NULL);
- errorString.append(QString::fromLatin1(error)); // error is ascii according to man ERR_error_string
+ q_ERR_error_string_n(errNum, buf, sizeof buf);
+ errorString.append(QString::fromLatin1(buf)); // error is ascii according to man ERR_error_string
}
return errorString;
}
@@ -134,10 +140,10 @@ static unsigned int q_ssl_psk_server_callback(SSL *ssl,
} // extern "C"
QSslSocketBackendPrivate::QSslSocketBackendPrivate()
- : ssl(0),
- readBio(0),
- writeBio(0),
- session(0)
+ : ssl(nullptr),
+ readBio(nullptr),
+ writeBio(nullptr),
+ session(nullptr)
{
// Calls SSL_library_init().
ensureInitialized();
@@ -188,8 +194,7 @@ QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(const SSL_CIPHER
return ciph;
}
-// static
-inline QSslErrorEntry QSslErrorEntry::fromStoreContext(X509_STORE_CTX *ctx)
+QSslErrorEntry QSslErrorEntry::fromStoreContext(X509_STORE_CTX *ctx)
{
return {
q_X509_STORE_CTX_get_error(ctx),
@@ -242,6 +247,33 @@ int q_X509Callback(int ok, X509_STORE_CTX *ctx)
return 1;
}
+static void q_loadCiphersForConnection(SSL *connection, QList<QSslCipher> &ciphers,
+ QList<QSslCipher> &defaultCiphers)
+{
+ Q_ASSERT(connection);
+
+ STACK_OF(SSL_CIPHER) *supportedCiphers = q_SSL_get_ciphers(connection);
+ for (int i = 0; i < q_sk_SSL_CIPHER_num(supportedCiphers); ++i) {
+ if (SSL_CIPHER *cipher = q_sk_SSL_CIPHER_value(supportedCiphers, i)) {
+ QSslCipher ciph = QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(cipher);
+ if (!ciph.isNull()) {
+ // Unconditionally exclude ADH and AECDH ciphers since they offer no MITM protection
+ if (!ciph.name().toLower().startsWith(QLatin1String("adh")) &&
+ !ciph.name().toLower().startsWith(QLatin1String("exp-adh")) &&
+ !ciph.name().toLower().startsWith(QLatin1String("aecdh"))) {
+ ciphers << ciph;
+
+ if (ciph.usedBits() >= 128)
+ defaultCiphers << ciph;
+ }
+ }
+ }
+ }
+}
+
+// Defined in qsslsocket.cpp
+void q_setDefaultDtlsCiphers(const QList<QSslCipher> &ciphers);
+
long QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions)
{
long options;
@@ -383,7 +415,7 @@ void QSslSocketBackendPrivate::destroySslContext()
{
if (ssl) {
q_SSL_free(ssl);
- ssl = 0;
+ ssl = nullptr;
}
sslContextPointer.clear();
}
@@ -447,29 +479,28 @@ void QSslSocketPrivate::resetDefaultCiphers()
QList<QSslCipher> ciphers;
QList<QSslCipher> defaultCiphers;
- STACK_OF(SSL_CIPHER) *supportedCiphers = q_SSL_get_ciphers(mySsl);
- for (int i = 0; i < q_sk_SSL_CIPHER_num(supportedCiphers); ++i) {
- if (SSL_CIPHER *cipher = q_sk_SSL_CIPHER_value(supportedCiphers, i)) {
- QSslCipher ciph = QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(cipher);
- if (!ciph.isNull()) {
- // Unconditionally exclude ADH and AECDH ciphers since they offer no MITM protection
- if (!ciph.name().toLower().startsWith(QLatin1String("adh")) &&
- !ciph.name().toLower().startsWith(QLatin1String("exp-adh")) &&
- !ciph.name().toLower().startsWith(QLatin1String("aecdh"))) {
- ciphers << ciph;
-
- if (ciph.usedBits() >= 128)
- defaultCiphers << ciph;
- }
- }
- }
- }
+ q_loadCiphersForConnection(mySsl, ciphers, defaultCiphers);
q_SSL_CTX_free(myCtx);
q_SSL_free(mySsl);
setDefaultSupportedCiphers(ciphers);
setDefaultCiphers(defaultCiphers);
+
+#if QT_CONFIG(dtls)
+ ciphers.clear();
+ defaultCiphers.clear();
+ myCtx = q_SSL_CTX_new(q_DTLS_client_method());
+ if (myCtx) {
+ mySsl = q_SSL_new(myCtx);
+ if (mySsl) {
+ q_loadCiphersForConnection(mySsl, ciphers, defaultCiphers);
+ q_setDefaultDtlsCiphers(defaultCiphers);
+ q_SSL_free(mySsl);
+ }
+ q_SSL_CTX_free(myCtx);
+ }
+#endif // dtls
}
void QSslSocketPrivate::resetDefaultEllipticCurves()
@@ -615,6 +646,11 @@ void QSslSocketBackendPrivate::transmit()
{
Q_Q(QSslSocket);
+ using ScopedBool = QScopedValueRollback<bool>;
+
+ if (inSetAndEmitError)
+ return;
+
// If we don't have any SSL context, don't bother transmitting.
if (!ssl)
return;
@@ -642,6 +678,7 @@ void QSslSocketBackendPrivate::transmit()
break;
} else {
// ### Better error handling.
+ const ScopedBool bg(inSetAndEmitError, true);
setErrorAndEmit(QAbstractSocket::SslInternalError,
QSslSocket::tr("Unable to write data: %1").arg(
getErrorsFromOpenSsl()));
@@ -688,6 +725,7 @@ void QSslSocketBackendPrivate::transmit()
#endif
if (actualWritten < 0) {
//plain socket write fails if it was in the pending close state.
+ const ScopedBool bg(inSetAndEmitError, true);
setErrorAndEmit(plainSocket->error(), plainSocket->errorString());
return;
}
@@ -713,6 +751,7 @@ void QSslSocketBackendPrivate::transmit()
plainSocket->skip(writtenToBio);
} else {
// ### Better error handling.
+ const ScopedBool bg(inSetAndEmitError, true);
setErrorAndEmit(QAbstractSocket::SslInternalError,
QSslSocket::tr("Unable to decrypt data: %1").arg(
getErrorsFromOpenSsl()));
@@ -794,15 +833,21 @@ void QSslSocketBackendPrivate::transmit()
qCDebug(lcSsl) << "QSslSocketBackendPrivate::transmit: remote disconnect";
#endif
shutdown = true; // the other side shut down, make sure we do not send shutdown ourselves
- setErrorAndEmit(QAbstractSocket::RemoteHostClosedError,
- QSslSocket::tr("The TLS/SSL connection has been closed"));
+ {
+ const ScopedBool bg(inSetAndEmitError, true);
+ setErrorAndEmit(QAbstractSocket::RemoteHostClosedError,
+ QSslSocket::tr("The TLS/SSL connection has been closed"));
+ }
return;
case SSL_ERROR_SYSCALL: // some IO error
case SSL_ERROR_SSL: // error in the SSL library
// we do not know exactly what the error is, nor whether we can recover from it,
// so just return to prevent an endless loop in the outer "while" statement
- setErrorAndEmit(QAbstractSocket::SslInternalError,
- QSslSocket::tr("Error while reading: %1").arg(getErrorsFromOpenSsl()));
+ {
+ const ScopedBool bg(inSetAndEmitError, true);
+ setErrorAndEmit(QAbstractSocket::SslInternalError,
+ QSslSocket::tr("Error while reading: %1").arg(getErrorsFromOpenSsl()));
+ }
return;
default:
// SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT: can only happen with a
@@ -810,15 +855,18 @@ void QSslSocketBackendPrivate::transmit()
// SSL_ERROR_WANT_X509_LOOKUP: can only happen with a
// SSL_CTX_set_client_cert_cb(), which we do not call.
// So this default case should never be triggered.
- setErrorAndEmit(QAbstractSocket::SslInternalError,
- QSslSocket::tr("Error while reading: %1").arg(getErrorsFromOpenSsl()));
+ {
+ const ScopedBool bg(inSetAndEmitError, true);
+ setErrorAndEmit(QAbstractSocket::SslInternalError,
+ QSslSocket::tr("Error while reading: %1").arg(getErrorsFromOpenSsl()));
+ }
break;
}
} while (ssl && readBytes > 0);
} while (ssl && transmitting);
}
-static QSslError _q_OpenSSL_to_QSslError(int errorCode, const QSslCertificate &cert)
+QSslError _q_OpenSSL_to_QSslError(int errorCode, const QSslCertificate &cert)
{
QSslError error;
switch (errorCode) {
@@ -867,12 +915,24 @@ static QSslError _q_OpenSSL_to_QSslError(int errorCode, const QSslCertificate &c
return error;
}
+QString QSslSocketBackendPrivate::msgErrorsDuringHandshake()
+{
+ return QSslSocket::tr("Error during SSL handshake: %1")
+ .arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+}
+
bool QSslSocketBackendPrivate::startHandshake()
{
Q_Q(QSslSocket);
// Check if the connection has been established. Get all errors from the
// verification stage.
+
+ using ScopedBool = QScopedValueRollback<bool>;
+
+ if (inSetAndEmitError)
+ return false;
+
QMutexLocker locker(&_q_sslErrorList()->mutex);
_q_sslErrorList()->errors.clear();
int result = (mode == QSslSocket::SslClientMode) ? q_SSL_connect(ssl) : q_SSL_accept(ssl);
@@ -902,12 +962,14 @@ bool QSslSocketBackendPrivate::startHandshake()
// The handshake is not yet complete.
break;
default:
- QString errorString
- = QSslSocket::tr("Error during SSL handshake: %1").arg(getErrorsFromOpenSsl());
+ QString errorString = QSslSocketBackendPrivate::msgErrorsDuringHandshake();
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << "QSslSocketBackendPrivate::startHandshake: error!" << errorString;
#endif
- setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, errorString);
+ {
+ const ScopedBool bg(inSetAndEmitError, true);
+ setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, errorString);
+ }
q->abort();
}
return false;
@@ -1177,119 +1239,6 @@ void QSslSocketBackendPrivate::_q_caRootLoaded(QSslCertificate cert, QSslCertifi
}
}
-class QWindowsCaRootFetcherThread : public QThread
-{
-public:
- QWindowsCaRootFetcherThread()
- {
- qRegisterMetaType<QSslCertificate>();
- setObjectName(QStringLiteral("QWindowsCaRootFetcher"));
- start();
- }
- ~QWindowsCaRootFetcherThread()
- {
- quit();
- wait(15500); // worst case, a running request can block for 15 seconds
- }
-};
-
-Q_GLOBAL_STATIC(QWindowsCaRootFetcherThread, windowsCaRootFetcherThread);
-
-QWindowsCaRootFetcher::QWindowsCaRootFetcher(const QSslCertificate &certificate, QSslSocket::SslMode sslMode)
- : cert(certificate), mode(sslMode)
-{
- moveToThread(windowsCaRootFetcherThread());
-}
-
-QWindowsCaRootFetcher::~QWindowsCaRootFetcher()
-{
-}
-
-void QWindowsCaRootFetcher::start()
-{
- QByteArray der = cert.toDer();
- PCCERT_CONTEXT wincert = CertCreateCertificateContext(X509_ASN_ENCODING, (const BYTE *)der.constData(), der.length());
- if (!wincert) {
-#ifdef QSSLSOCKET_DEBUG
- qCDebug(lcSsl, "QWindowsCaRootFetcher failed to convert certificate to windows form");
-#endif
- emit finished(cert, QSslCertificate());
- deleteLater();
- return;
- }
-
- CERT_CHAIN_PARA parameters;
- memset(&parameters, 0, sizeof(parameters));
- parameters.cbSize = sizeof(parameters);
- // set key usage constraint
- parameters.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
- parameters.RequestedUsage.Usage.cUsageIdentifier = 1;
- LPSTR oid = (LPSTR)(mode == QSslSocket::SslClientMode ? szOID_PKIX_KP_SERVER_AUTH : szOID_PKIX_KP_CLIENT_AUTH);
- parameters.RequestedUsage.Usage.rgpszUsageIdentifier = &oid;
-
-#ifdef QSSLSOCKET_DEBUG
- QElapsedTimer stopwatch;
- stopwatch.start();
-#endif
- PCCERT_CHAIN_CONTEXT chain;
- BOOL result = CertGetCertificateChain(
- 0, //default engine
- wincert,
- 0, //current date/time
- 0, //default store
- &parameters,
- 0, //default dwFlags
- 0, //reserved
- &chain);
-#ifdef QSSLSOCKET_DEBUG
- qCDebug(lcSsl) << "QWindowsCaRootFetcher" << stopwatch.elapsed() << "ms to get chain";
-#endif
-
- QSslCertificate trustedRoot;
- if (result) {
-#ifdef QSSLSOCKET_DEBUG
- qCDebug(lcSsl) << "QWindowsCaRootFetcher - examining windows chains";
- if (chain->TrustStatus.dwErrorStatus == CERT_TRUST_NO_ERROR)
- qCDebug(lcSsl) << " - TRUSTED";
- else
- qCDebug(lcSsl) << " - NOT TRUSTED" << chain->TrustStatus.dwErrorStatus;
- if (chain->TrustStatus.dwInfoStatus & CERT_TRUST_IS_SELF_SIGNED)
- qCDebug(lcSsl) << " - SELF SIGNED";
- qCDebug(lcSsl) << "QSslSocketBackendPrivate::fetchCaRootForCert - dumping simple chains";
- for (unsigned int i = 0; i < chain->cChain; i++) {
- if (chain->rgpChain[i]->TrustStatus.dwErrorStatus == CERT_TRUST_NO_ERROR)
- qCDebug(lcSsl) << " - TRUSTED SIMPLE CHAIN" << i;
- else
- qCDebug(lcSsl) << " - UNTRUSTED SIMPLE CHAIN" << i << "reason:" << chain->rgpChain[i]->TrustStatus.dwErrorStatus;
- for (unsigned int j = 0; j < chain->rgpChain[i]->cElement; j++) {
- QSslCertificate foundCert(QByteArray((const char *)chain->rgpChain[i]->rgpElement[j]->pCertContext->pbCertEncoded
- , chain->rgpChain[i]->rgpElement[j]->pCertContext->cbCertEncoded), QSsl::Der);
- qCDebug(lcSsl) << " - " << foundCert;
- }
- }
- qCDebug(lcSsl) << " - and" << chain->cLowerQualityChainContext << "low quality chains"; //expect 0, we haven't asked for them
-#endif
-
- //based on http://msdn.microsoft.com/en-us/library/windows/desktop/aa377182%28v=vs.85%29.aspx
- //about the final chain rgpChain[cChain-1] which must begin with a trusted root to be valid
- if (chain->TrustStatus.dwErrorStatus == CERT_TRUST_NO_ERROR
- && chain->cChain > 0) {
- const PCERT_SIMPLE_CHAIN finalChain = chain->rgpChain[chain->cChain - 1];
- // http://msdn.microsoft.com/en-us/library/windows/desktop/aa377544%28v=vs.85%29.aspx
- // rgpElement[0] is the end certificate chain element. rgpElement[cElement-1] is the self-signed "root" certificate element.
- if (finalChain->TrustStatus.dwErrorStatus == CERT_TRUST_NO_ERROR
- && finalChain->cElement > 0) {
- trustedRoot = QSslCertificate(QByteArray((const char *)finalChain->rgpElement[finalChain->cElement - 1]->pCertContext->pbCertEncoded
- , finalChain->rgpElement[finalChain->cElement - 1]->pCertContext->cbCertEncoded), QSsl::Der);
- }
- }
- CertFreeCertificateChain(chain);
- }
- CertFreeCertificateContext(wincert);
-
- emit finished(cert, trustedRoot);
- deleteLater();
-}
#endif
void QSslSocketBackendPrivate::disconnectFromHost()
@@ -1406,7 +1355,7 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
q_X509_STORE_set_verify_cb(certStore, q_X509Callback);
// Build the chain of intermediate certificates
- STACK_OF(X509) *intermediates = 0;
+ STACK_OF(X509) *intermediates = nullptr;
if (certificateChain.length() > 1) {
intermediates = (STACK_OF(X509) *) q_OPENSSL_sk_new_null();
@@ -1499,9 +1448,10 @@ bool QSslSocketBackendPrivate::importPkcs12(QIODevice *device,
BIO *bio = q_BIO_new_mem_buf(const_cast<char *>(pkcs12data.constData()), pkcs12data.size());
// Create the PKCS#12 object
- PKCS12 *p12 = q_d2i_PKCS12_bio(bio, 0);
+ PKCS12 *p12 = q_d2i_PKCS12_bio(bio, nullptr);
if (!p12) {
- qCWarning(lcSsl, "Unable to read PKCS#12 structure, %s", q_ERR_error_string(q_ERR_get_error(), 0));
+ qCWarning(lcSsl, "Unable to read PKCS#12 structure, %s",
+ q_ERR_error_string(q_ERR_get_error(), nullptr));
q_BIO_free(bio);
return false;
}
@@ -1509,10 +1459,11 @@ bool QSslSocketBackendPrivate::importPkcs12(QIODevice *device,
// Extract the data
EVP_PKEY *pkey = nullptr;
X509 *x509;
- STACK_OF(X509) *ca = 0;
+ STACK_OF(X509) *ca = nullptr;
if (!q_PKCS12_parse(p12, passPhrase.constData(), &pkey, &x509, &ca)) {
- qCWarning(lcSsl, "Unable to parse PKCS#12 structure, %s", q_ERR_error_string(q_ERR_get_error(), 0));
+ qCWarning(lcSsl, "Unable to parse PKCS#12 structure, %s",
+ q_ERR_error_string(q_ERR_get_error(), nullptr));
q_PKCS12_free(p12);
q_BIO_free(bio);
return false;
diff --git a/src/network/ssl/qsslsocket_openssl11.cpp b/src/network/ssl/qsslsocket_openssl11.cpp
index d028f5fc00..cbbf403672 100644
--- a/src/network/ssl/qsslsocket_openssl11.cpp
+++ b/src/network/ssl/qsslsocket_openssl11.cpp
@@ -248,7 +248,7 @@ void QSslSocketBackendPrivate::continueHandshake()
// we could not agree -> be conservative and use HTTP/1.1
configuration.nextNegotiatedProtocol = QByteArrayLiteral("http/1.1");
} else {
- const unsigned char *proto = 0;
+ const unsigned char *proto = nullptr;
unsigned int proto_len = 0;
q_SSL_get0_alpn_selected(ssl, &proto, &proto_len);
diff --git a/src/network/ssl/qsslsocket_openssl11_symbols_p.h b/src/network/ssl/qsslsocket_openssl11_symbols_p.h
index ac8d46ce6d..844c3437be 100644
--- a/src/network/ssl/qsslsocket_openssl11_symbols_p.h
+++ b/src/network/ssl/qsslsocket_openssl11_symbols_p.h
@@ -128,6 +128,45 @@ long q_OpenSSL_version_num();
const char *q_OpenSSL_version(int type);
unsigned long q_SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *session);
+unsigned long q_SSL_set_options(SSL *s, unsigned long op);
+
+#if QT_CONFIG(dtls)
+// Functions and types required for DTLS support:
+extern "C"
+{
+
+typedef int (*CookieVerifyCallback)(SSL *, const unsigned char *, unsigned);
+typedef int (*DgramWriteCallback) (BIO *, const char *, int);
+typedef int (*DgramReadCallback) (BIO *, char *, int);
+typedef int (*DgramPutsCallback) (BIO *, const char *);
+typedef long (*DgramCtrlCallback) (BIO *, int, long, void *);
+typedef int (*DgramCreateCallback) (BIO *);
+typedef int (*DgramDestroyCallback) (BIO *);
+
+}
+
+int q_DTLSv1_listen(SSL *s, BIO_ADDR *client);
+BIO_ADDR *q_BIO_ADDR_new();
+void q_BIO_ADDR_free(BIO_ADDR *ap);
+
+// API we need for a custom dgram BIO:
+
+BIO_METHOD *q_BIO_meth_new(int type, const char *name);
+void q_BIO_meth_free(BIO_METHOD *biom);
+int q_BIO_meth_set_write(BIO_METHOD *biom, DgramWriteCallback);
+int q_BIO_meth_set_read(BIO_METHOD *biom, DgramReadCallback);
+int q_BIO_meth_set_puts(BIO_METHOD *biom, DgramPutsCallback);
+int q_BIO_meth_set_ctrl(BIO_METHOD *biom, DgramCtrlCallback);
+int q_BIO_meth_set_create(BIO_METHOD *biom, DgramCreateCallback);
+int q_BIO_meth_set_destroy(BIO_METHOD *biom, DgramDestroyCallback);
+
+#endif // dtls
+
+void q_BIO_set_data(BIO *a, void *ptr);
+void *q_BIO_get_data(BIO *a);
+void q_BIO_set_init(BIO *a, int init);
+int q_BIO_get_shutdown(BIO *a);
+void q_BIO_set_shutdown(BIO *a, int shut);
#define q_SSL_CTX_set_min_proto_version(ctx, version) \
q_SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, version, nullptr)
diff --git a/src/network/ssl/qsslsocket_openssl_p.h b/src/network/ssl/qsslsocket_openssl_p.h
index 2a800cdc34..c16b9d5f76 100644
--- a/src/network/ssl/qsslsocket_openssl_p.h
+++ b/src/network/ssl/qsslsocket_openssl_p.h
@@ -131,6 +131,8 @@ public:
static int s_indexForSSLExtraData; // index used in SSL_get_ex_data to get the matching QSslSocketBackendPrivate
#endif
+ bool inSetAndEmitError = false;
+
// Platform specific functions
void startClientEncryption() override;
void startServerEncryption() override;
@@ -159,24 +161,9 @@ public:
QSslKey *key, QSslCertificate *cert,
QList<QSslCertificate> *caCertificates,
const QByteArray &passPhrase);
-};
-#ifdef Q_OS_WIN
-class QWindowsCaRootFetcher : public QObject
-{
- Q_OBJECT;
-public:
- QWindowsCaRootFetcher(const QSslCertificate &certificate, QSslSocket::SslMode sslMode);
- ~QWindowsCaRootFetcher();
-public slots:
- void start();
-signals:
- void finished(QSslCertificate brokenChain, QSslCertificate caroot);
-private:
- QSslCertificate cert;
- QSslSocket::SslMode mode;
+ static QString msgErrorsDuringHandshake();
};
-#endif
QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp
index 59c93677dd..5482440b98 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols.cpp
+++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp
@@ -63,7 +63,9 @@
# include <QtCore/qlibrary.h>
#endif
#include <QtCore/qmutex.h>
+#if QT_CONFIG(thread)
#include <private/qmutexpool_p.h>
+#endif
#include <QtCore/qdatetime.h>
#if defined(Q_OS_UNIX)
#include <QtCore/qdir.h>
@@ -141,11 +143,11 @@ void qsslSocketCannotResolveSymbolWarning(const char *functionName)
// Below are the functions first introduced in version 1.1:
-DEFINEFUNC(const unsigned char *, ASN1_STRING_get0_data, const ASN1_STRING *a, a, return 0, return)
+DEFINEFUNC(const unsigned char *, ASN1_STRING_get0_data, const ASN1_STRING *a, a, return nullptr, return)
DEFINEFUNC2(int, OPENSSL_init_ssl, uint64_t opts, opts, const OPENSSL_INIT_SETTINGS *settings, settings, return 0, return)
DEFINEFUNC2(int, OPENSSL_init_crypto, uint64_t opts, opts, const OPENSSL_INIT_SETTINGS *settings, settings, return 0, return)
-DEFINEFUNC(BIO *, BIO_new, const BIO_METHOD *a, a, return 0, return)
-DEFINEFUNC(const BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return 0, return)
+DEFINEFUNC(BIO *, BIO_new, const BIO_METHOD *a, a, return nullptr, return)
+DEFINEFUNC(const BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return nullptr, return)
DEFINEFUNC2(int, BN_is_word, BIGNUM *a, a, BN_ULONG w, w, return 0, return)
DEFINEFUNC(int, EVP_CIPHER_CTX_reset, EVP_CIPHER_CTX *c, c, return 0, return)
DEFINEFUNC(int, EVP_PKEY_base_id, EVP_PKEY *a, a, return NID_undef, return)
@@ -153,45 +155,66 @@ DEFINEFUNC(int, RSA_bits, RSA *a, a, return 0, return)
DEFINEFUNC(int, DSA_bits, DSA *a, a, return 0, return)
DEFINEFUNC(int, OPENSSL_sk_num, OPENSSL_STACK *a, a, return -1, return)
DEFINEFUNC2(void, OPENSSL_sk_pop_free, OPENSSL_STACK *a, a, void (*b)(void*), b, return, DUMMYARG)
-DEFINEFUNC(OPENSSL_STACK *, OPENSSL_sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(OPENSSL_STACK *, OPENSSL_sk_new_null, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC2(void, OPENSSL_sk_push, OPENSSL_STACK *a, a, void *b, b, return, DUMMYARG)
DEFINEFUNC(void, OPENSSL_sk_free, OPENSSL_STACK *a, a, return, DUMMYARG)
-DEFINEFUNC2(void *, OPENSSL_sk_value, OPENSSL_STACK *a, a, int b, b, return 0, return)
+DEFINEFUNC2(void *, OPENSSL_sk_value, OPENSSL_STACK *a, a, int b, b, return nullptr, return)
DEFINEFUNC(int, SSL_session_reused, SSL *a, a, return 0, return)
DEFINEFUNC2(unsigned long, SSL_CTX_set_options, SSL_CTX *ctx, ctx, unsigned long op, op, return 0, return)
DEFINEFUNC3(size_t, SSL_get_client_random, SSL *a, a, unsigned char *out, out, size_t outlen, outlen, return 0, return)
DEFINEFUNC3(size_t, SSL_SESSION_get_master_key, const SSL_SESSION *ses, ses, unsigned char *out, out, size_t outlen, outlen, return 0, return)
DEFINEFUNC6(int, CRYPTO_get_ex_new_index, int class_index, class_index, long argl, argl, void *argp, argp, CRYPTO_EX_new *new_func, new_func, CRYPTO_EX_dup *dup_func, dup_func, CRYPTO_EX_free *free_func, free_func, return -1, return)
+DEFINEFUNC2(unsigned long, SSL_set_options, SSL *ssl, ssl, unsigned long op, op, return 0, return)
-DEFINEFUNC(const SSL_METHOD *, TLS_method, DUMMYARG, DUMMYARG, return 0, return)
-DEFINEFUNC(const SSL_METHOD *, TLS_client_method, DUMMYARG, DUMMYARG, return 0, return)
-DEFINEFUNC(const SSL_METHOD *, TLS_server_method, DUMMYARG, DUMMYARG, return 0, return)
-DEFINEFUNC(ASN1_TIME *, X509_getm_notBefore, X509 *a, a, return 0, return)
-DEFINEFUNC(ASN1_TIME *, X509_getm_notAfter, X509 *a, a, return 0, return)
+DEFINEFUNC(const SSL_METHOD *, TLS_method, DUMMYARG, DUMMYARG, return nullptr, return)
+DEFINEFUNC(const SSL_METHOD *, TLS_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
+DEFINEFUNC(const SSL_METHOD *, TLS_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
+DEFINEFUNC(ASN1_TIME *, X509_getm_notBefore, X509 *a, a, return nullptr, return)
+DEFINEFUNC(ASN1_TIME *, X509_getm_notAfter, X509 *a, a, return nullptr, return)
DEFINEFUNC(long, X509_get_version, X509 *a, a, return -1, return)
-DEFINEFUNC(EVP_PKEY *, X509_get_pubkey, X509 *a, a, return 0, return)
+DEFINEFUNC(EVP_PKEY *, X509_get_pubkey, X509 *a, a, return nullptr, return)
DEFINEFUNC2(void, X509_STORE_set_verify_cb, X509_STORE *a, a, X509_STORE_CTX_verify_cb verify_cb, verify_cb, return, DUMMYARG)
-DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get0_chain, X509_STORE_CTX *a, a, return 0, return)
+DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get0_chain, X509_STORE_CTX *a, a, return nullptr, return)
DEFINEFUNC3(void, CRYPTO_free, void *str, str, const char *file, file, int line, line, return, DUMMYARG)
DEFINEFUNC(long, OpenSSL_version_num, void, DUMMYARG, return 0, return)
-DEFINEFUNC(const char *, OpenSSL_version, int a, a, return 0, return)
+DEFINEFUNC(const char *, OpenSSL_version, int a, a, return nullptr, return)
DEFINEFUNC(unsigned long, SSL_SESSION_get_ticket_lifetime_hint, const SSL_SESSION *session, session, return 0, return)
DEFINEFUNC4(void, DH_get0_pqg, const DH *dh, dh, const BIGNUM **p, p, const BIGNUM **q, q, const BIGNUM **g, g, return, DUMMYARG)
DEFINEFUNC(int, DH_bits, DH *dh, dh, return 0, return)
+#if QT_CONFIG(dtls)
+DEFINEFUNC2(int, DTLSv1_listen, SSL *s, s, BIO_ADDR *c, c, return -1, return)
+DEFINEFUNC(BIO_ADDR *, BIO_ADDR_new, DUMMYARG, DUMMYARG, return nullptr, return)
+DEFINEFUNC(void, BIO_ADDR_free, BIO_ADDR *ap, ap, return, DUMMYARG)
+DEFINEFUNC2(BIO_METHOD *, BIO_meth_new, int type, type, const char *name, name, return nullptr, return)
+DEFINEFUNC(void, BIO_meth_free, BIO_METHOD *biom, biom, return, DUMMYARG)
+DEFINEFUNC2(int, BIO_meth_set_write, BIO_METHOD *biom, biom, DgramWriteCallback write, write, return 0, return)
+DEFINEFUNC2(int, BIO_meth_set_read, BIO_METHOD *biom, biom, DgramReadCallback read, read, return 0, return)
+DEFINEFUNC2(int, BIO_meth_set_puts, BIO_METHOD *biom, biom, DgramPutsCallback puts, puts, return 0, return)
+DEFINEFUNC2(int, BIO_meth_set_ctrl, BIO_METHOD *biom, biom, DgramCtrlCallback ctrl, ctrl, return 0, return)
+DEFINEFUNC2(int, BIO_meth_set_create, BIO_METHOD *biom, biom, DgramCreateCallback crt, crt, return 0, return)
+DEFINEFUNC2(int, BIO_meth_set_destroy, BIO_METHOD *biom, biom, DgramDestroyCallback dtr, dtr, return 0, return)
+#endif // dtls
+
+DEFINEFUNC2(void, BIO_set_data, BIO *a, a, void *ptr, ptr, return, DUMMYARG)
+DEFINEFUNC(void *, BIO_get_data, BIO *a, a, return nullptr, return)
+DEFINEFUNC2(void, BIO_set_init, BIO *a, a, int init, init, return, DUMMYARG)
+DEFINEFUNC(int, BIO_get_shutdown, BIO *a, a, return -1, return)
+DEFINEFUNC2(void, BIO_set_shutdown, BIO *a, a, int shut, shut, return, DUMMYARG)
+
#else // QT_CONFIG(opensslv11)
// Functions below are either deprecated or removed in OpenSSL >= 1.1:
-DEFINEFUNC(unsigned char *, ASN1_STRING_data, ASN1_STRING *a, a, return 0, return)
+DEFINEFUNC(unsigned char *, ASN1_STRING_data, ASN1_STRING *a, a, return nullptr, return)
#ifdef SSLEAY_MACROS
-DEFINEFUNC3(void *, ASN1_dup, i2d_of_void *a, a, d2i_of_void *b, b, char *c, c, return 0, return)
+DEFINEFUNC3(void *, ASN1_dup, i2d_of_void *a, a, d2i_of_void *b, b, char *c, c, return nullptr, return)
#endif
-DEFINEFUNC2(BIO *, BIO_new_file, const char *filename, filename, const char *mode, mode, return 0, return)
+DEFINEFUNC2(BIO *, BIO_new_file, const char *filename, filename, const char *mode, mode, return nullptr, return)
DEFINEFUNC(void, ERR_clear_error, DUMMYARG, DUMMYARG, return, DUMMYARG)
-DEFINEFUNC(BIO *, BIO_new, BIO_METHOD *a, a, return 0, return)
-DEFINEFUNC(BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return 0, return)
+DEFINEFUNC(BIO *, BIO_new, BIO_METHOD *a, a, return nullptr, return)
+DEFINEFUNC(BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return nullptr, return)
DEFINEFUNC(int, CRYPTO_num_locks, DUMMYARG, DUMMYARG, return 0, return)
DEFINEFUNC(void, CRYPTO_set_locking_callback, void (*a)(int, int, const char *, int), a, return, DUMMYARG)
DEFINEFUNC(void, CRYPTO_set_id_callback, unsigned long (*a)(), a, return, DUMMYARG)
@@ -202,23 +225,23 @@ DEFINEFUNC(void, EVP_CIPHER_CTX_cleanup, EVP_CIPHER_CTX *a, a, return, DUMMYARG)
DEFINEFUNC(void, EVP_CIPHER_CTX_init, EVP_CIPHER_CTX *a, a, return, DUMMYARG)
#ifdef SSLEAY_MACROS
-DEFINEFUNC6(void *, PEM_ASN1_read_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return)
-DEFINEFUNC6(void *, PEM_ASN1_write_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return)
+DEFINEFUNC6(void *, PEM_ASN1_read_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return nullptr, return)
+DEFINEFUNC6(void *, PEM_ASN1_write_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return nullptr, return)
#endif // SSLEAY_MACROS
DEFINEFUNC(int, sk_num, STACK *a, a, return -1, return)
DEFINEFUNC2(void, sk_pop_free, STACK *a, a, void (*b)(void*), b, return, DUMMYARG)
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
-DEFINEFUNC(_STACK *, sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(_STACK *, sk_new_null, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC2(void, sk_push, _STACK *a, a, void *b, b, return, DUMMYARG)
DEFINEFUNC(void, sk_free, _STACK *a, a, return, DUMMYARG)
-DEFINEFUNC2(void *, sk_value, STACK *a, a, int b, b, return 0, return)
+DEFINEFUNC2(void *, sk_value, STACK *a, a, int b, b, return nullptr, return)
#else
-DEFINEFUNC(STACK *, sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(STACK *, sk_new_null, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC2(void, sk_push, STACK *a, a, char *b, b, return, DUMMYARG)
DEFINEFUNC(void, sk_free, STACK *a, a, return, DUMMYARG)
-DEFINEFUNC2(char *, sk_value, STACK *a, a, int b, b, return 0, return)
+DEFINEFUNC2(char *, sk_value, STACK *a, a, int b, b, return nullptr, return)
#endif // OPENSSL_VERSION_NUMBER >= 0x10000000L
DEFINEFUNC(int, SSL_library_init, void, DUMMYARG, return -1, return)
@@ -230,49 +253,49 @@ DEFINEFUNC5(int, SSL_get_ex_new_index, long argl, argl, void *argp, argp, CRYPTO
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
#ifndef OPENSSL_NO_SSL2
-DEFINEFUNC(const SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
#ifndef OPENSSL_NO_SSL3_METHOD
-DEFINEFUNC(const SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
-DEFINEFUNC(const SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return)
-DEFINEFUNC(const SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
+DEFINEFUNC(const SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
-DEFINEFUNC(const SSL_METHOD *, TLSv1_1_client_method, DUMMYARG, DUMMYARG, return 0, return)
-DEFINEFUNC(const SSL_METHOD *, TLSv1_2_client_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const SSL_METHOD *, TLSv1_1_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
+DEFINEFUNC(const SSL_METHOD *, TLSv1_2_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
#ifndef OPENSSL_NO_SSL2
-DEFINEFUNC(const SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
#ifndef OPENSSL_NO_SSL3_METHOD
-DEFINEFUNC(const SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
-DEFINEFUNC(const SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return)
-DEFINEFUNC(const SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
+DEFINEFUNC(const SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
-DEFINEFUNC(const SSL_METHOD *, TLSv1_1_server_method, DUMMYARG, DUMMYARG, return 0, return)
-DEFINEFUNC(const SSL_METHOD *, TLSv1_2_server_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const SSL_METHOD *, TLSv1_1_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
+DEFINEFUNC(const SSL_METHOD *, TLSv1_2_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
#else
#ifndef OPENSSL_NO_SSL2
-DEFINEFUNC(SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
#ifndef OPENSSL_NO_SSL3_METHOD
-DEFINEFUNC(SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
-DEFINEFUNC(SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return)
-DEFINEFUNC(SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
+DEFINEFUNC(SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
#ifndef OPENSSL_NO_SSL2
-DEFINEFUNC(SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
#ifndef OPENSSL_NO_SSL3_METHOD
-DEFINEFUNC(SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
-DEFINEFUNC(SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return)
-DEFINEFUNC(SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
+DEFINEFUNC(SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
-DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get_chain, X509_STORE_CTX *a, a, return 0, return)
+DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get_chain, X509_STORE_CTX *a, a, return nullptr, return)
#ifdef SSLEAY_MACROS
DEFINEFUNC2(int, i2d_DSAPrivateKey, const DSA *a, a, unsigned char **b, b, return -1, return)
@@ -280,17 +303,25 @@ DEFINEFUNC2(int, i2d_RSAPrivateKey, const RSA *a, a, unsigned char **b, b, retur
#ifndef OPENSSL_NO_EC
DEFINEFUNC2(int, i2d_ECPrivateKey, const EC_KEY *a, a, unsigned char **b, b, return -1, return)
#endif
-DEFINEFUNC3(RSA *, d2i_RSAPrivateKey, RSA **a, a, unsigned char **b, b, long c, c, return 0, return)
-DEFINEFUNC3(DSA *, d2i_DSAPrivateKey, DSA **a, a, unsigned char **b, b, long c, c, return 0, return)
+DEFINEFUNC3(RSA *, d2i_RSAPrivateKey, RSA **a, a, unsigned char **b, b, long c, c, return nullptr, return)
+DEFINEFUNC3(DSA *, d2i_DSAPrivateKey, DSA **a, a, unsigned char **b, b, long c, c, return nullptr, return)
#ifndef OPENSSL_NO_EC
-DEFINEFUNC3(EC_KEY *, d2i_ECPrivateKey, EC_KEY **a, a, unsigned char **b, b, long c, c, return 0, return)
+DEFINEFUNC3(EC_KEY *, d2i_ECPrivateKey, EC_KEY **a, a, unsigned char **b, b, long c, c, return nullptr, return)
#endif
#endif
-DEFINEFUNC(char *, CONF_get1_default_config_file, DUMMYARG, DUMMYARG, return 0, return)
+
+#if QT_CONFIG(dtls)
+DEFINEFUNC(const SSL_METHOD *, DTLSv1_server_method, void, DUMMYARG, return nullptr, return)
+DEFINEFUNC(const SSL_METHOD *, DTLSv1_client_method, void, DUMMYARG, return nullptr, return)
+DEFINEFUNC(const SSL_METHOD *, DTLSv1_2_server_method, void, DUMMYARG, return nullptr, return)
+DEFINEFUNC(const SSL_METHOD *, DTLSv1_2_client_method, void, DUMMYARG, return nullptr, return)
+#endif // dtls
+
+DEFINEFUNC(char *, CONF_get1_default_config_file, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC(void, OPENSSL_add_all_algorithms_noconf, void, DUMMYARG, return, DUMMYARG)
DEFINEFUNC(void, OPENSSL_add_all_algorithms_conf, void, DUMMYARG, return, DUMMYARG)
DEFINEFUNC(long, SSLeay, void, DUMMYARG, return 0, return)
-DEFINEFUNC(const char *, SSLeay_version, int a, a, return 0, return)
+DEFINEFUNC(const char *, SSLeay_version, int a, a, return nullptr, return)
#endif // QT_CONFIG(opensslv11)
@@ -299,22 +330,23 @@ DEFINEFUNC(int, ASN1_STRING_length, ASN1_STRING *a, a, return 0, return)
DEFINEFUNC2(int, ASN1_STRING_to_UTF8, unsigned char **a, a, ASN1_STRING *b, b, return 0, return)
DEFINEFUNC4(long, BIO_ctrl, BIO *a, a, int b, b, long c, c, void *d, d, return -1, return)
DEFINEFUNC(int, BIO_free, BIO *a, a, return 0, return)
-DEFINEFUNC2(BIO *, BIO_new_mem_buf, void *a, a, int b, b, return 0, return)
+DEFINEFUNC2(BIO *, BIO_new_mem_buf, void *a, a, int b, b, return nullptr, return)
DEFINEFUNC3(int, BIO_read, BIO *a, a, void *b, b, int c, c, return -1, return)
DEFINEFUNC3(int, BIO_write, BIO *a, a, const void *b, b, int c, c, return -1, return)
DEFINEFUNC(int, BN_num_bits, const BIGNUM *a, a, return 0, return)
DEFINEFUNC2(BN_ULONG, BN_mod_word, const BIGNUM *a, a, BN_ULONG w, w, return static_cast<BN_ULONG>(-1), return)
#ifndef OPENSSL_NO_EC
-DEFINEFUNC(const EC_GROUP*, EC_KEY_get0_group, const EC_KEY* k, k, return 0, return)
+DEFINEFUNC(const EC_GROUP*, EC_KEY_get0_group, const EC_KEY* k, k, return nullptr, return)
DEFINEFUNC(int, EC_GROUP_get_degree, const EC_GROUP* g, g, return 0, return)
#endif
-DEFINEFUNC(DSA *, DSA_new, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(DSA *, DSA_new, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC(void, DSA_free, DSA *a, a, return, DUMMYARG)
-DEFINEFUNC3(X509 *, d2i_X509, X509 **a, a, const unsigned char **b, b, long c, c, return 0, return)
-DEFINEFUNC2(char *, ERR_error_string, unsigned long a, a, char *b, b, return 0, return)
+DEFINEFUNC3(X509 *, d2i_X509, X509 **a, a, const unsigned char **b, b, long c, c, return nullptr, return)
+DEFINEFUNC2(char *, ERR_error_string, unsigned long a, a, char *b, b, return nullptr, return)
+DEFINEFUNC3(void, ERR_error_string_n, unsigned long e, e, char *b, b, size_t len, len, return, DUMMYARG)
DEFINEFUNC(unsigned long, ERR_get_error, DUMMYARG, DUMMYARG, return 0, return)
-DEFINEFUNC(EVP_CIPHER_CTX *, EVP_CIPHER_CTX_new, void, DUMMYARG, return 0, return)
+DEFINEFUNC(EVP_CIPHER_CTX *, EVP_CIPHER_CTX_new, void, DUMMYARG, return nullptr, return)
DEFINEFUNC(void, EVP_CIPHER_CTX_free, EVP_CIPHER_CTX *a, a, return, DUMMYARG)
DEFINEFUNC4(int, EVP_CIPHER_CTX_ctrl, EVP_CIPHER_CTX *ctx, ctx, int type, type, int arg, arg, void *ptr, ptr, return 0, return)
DEFINEFUNC2(int, EVP_CIPHER_CTX_set_key_length, EVP_CIPHER_CTX *ctx, ctx, int keylen, keylen, return 0, return)
@@ -323,13 +355,13 @@ DEFINEFUNC6(int, EVP_CipherInit_ex, EVP_CIPHER_CTX *ctx, ctx, const EVP_CIPHER *
DEFINEFUNC5(int, EVP_CipherUpdate, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, const unsigned char *in, in, int inl, inl, return 0, return)
DEFINEFUNC3(int, EVP_CipherFinal, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, return 0, return)
#ifndef OPENSSL_NO_DES
-DEFINEFUNC(const EVP_CIPHER *, EVP_des_cbc, DUMMYARG, DUMMYARG, return 0, return)
-DEFINEFUNC(const EVP_CIPHER *, EVP_des_ede3_cbc, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const EVP_CIPHER *, EVP_des_cbc, DUMMYARG, DUMMYARG, return nullptr, return)
+DEFINEFUNC(const EVP_CIPHER *, EVP_des_ede3_cbc, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
#ifndef OPENSSL_NO_RC2
-DEFINEFUNC(const EVP_CIPHER *, EVP_rc2_cbc, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const EVP_CIPHER *, EVP_rc2_cbc, DUMMYARG, DUMMYARG, return nullptr, return)
#endif
-DEFINEFUNC(const EVP_MD *, EVP_sha1, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const EVP_MD *, EVP_sha1, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC3(int, EVP_PKEY_assign, EVP_PKEY *a, a, int b, b, char *c, c, return -1, return)
DEFINEFUNC2(int, EVP_PKEY_set1_RSA, EVP_PKEY *a, a, RSA *b, b, return -1, return)
DEFINEFUNC2(int, EVP_PKEY_set1_DSA, EVP_PKEY *a, a, DSA *b, b, return -1, return)
@@ -337,16 +369,16 @@ DEFINEFUNC2(int, EVP_PKEY_set1_DSA, EVP_PKEY *a, a, DSA *b, b, return -1, return
DEFINEFUNC2(int, EVP_PKEY_set1_EC_KEY, EVP_PKEY *a, a, EC_KEY *b, b, return -1, return)
#endif
DEFINEFUNC(void, EVP_PKEY_free, EVP_PKEY *a, a, return, DUMMYARG)
-DEFINEFUNC(DSA *, EVP_PKEY_get1_DSA, EVP_PKEY *a, a, return 0, return)
-DEFINEFUNC(RSA *, EVP_PKEY_get1_RSA, EVP_PKEY *a, a, return 0, return)
+DEFINEFUNC(DSA *, EVP_PKEY_get1_DSA, EVP_PKEY *a, a, return nullptr, return)
+DEFINEFUNC(RSA *, EVP_PKEY_get1_RSA, EVP_PKEY *a, a, return nullptr, return)
#ifndef OPENSSL_NO_EC
-DEFINEFUNC(EC_KEY *, EVP_PKEY_get1_EC_KEY, EVP_PKEY *a, a, return 0, return)
+DEFINEFUNC(EC_KEY *, EVP_PKEY_get1_EC_KEY, EVP_PKEY *a, a, return nullptr, return)
#endif
-DEFINEFUNC(EVP_PKEY *, EVP_PKEY_new, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(EVP_PKEY *, EVP_PKEY_new, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC(int, EVP_PKEY_type, int a, a, return NID_undef, return)
DEFINEFUNC2(int, i2d_X509, X509 *a, a, unsigned char **b, b, return -1, return)
-DEFINEFUNC(const char *, OBJ_nid2sn, int a, a, return 0, return)
-DEFINEFUNC(const char *, OBJ_nid2ln, int a, a, return 0, return)
+DEFINEFUNC(const char *, OBJ_nid2sn, int a, a, return nullptr, return)
+DEFINEFUNC(const char *, OBJ_nid2ln, int a, a, return nullptr, return)
DEFINEFUNC(int, OBJ_sn2nid, const char *s, s, return 0, return)
DEFINEFUNC(int, OBJ_ln2nid, const char *s, s, return 0, return)
DEFINEFUNC3(int, i2t_ASN1_OBJECT, char *a, a, int b, b, ASN1_OBJECT *c, c, return -1, return)
@@ -355,24 +387,24 @@ DEFINEFUNC4(int, OBJ_obj2txt, char *a, a, int b, b, ASN1_OBJECT *c, c, int d, d,
DEFINEFUNC(int, OBJ_obj2nid, const ASN1_OBJECT *a, a, return NID_undef, return)
#ifndef SSLEAY_MACROS
-DEFINEFUNC4(EVP_PKEY *, PEM_read_bio_PrivateKey, BIO *a, a, EVP_PKEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
-DEFINEFUNC4(DSA *, PEM_read_bio_DSAPrivateKey, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
-DEFINEFUNC4(RSA *, PEM_read_bio_RSAPrivateKey, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
+DEFINEFUNC4(EVP_PKEY *, PEM_read_bio_PrivateKey, BIO *a, a, EVP_PKEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return)
+DEFINEFUNC4(DSA *, PEM_read_bio_DSAPrivateKey, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return)
+DEFINEFUNC4(RSA *, PEM_read_bio_RSAPrivateKey, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return)
#ifndef OPENSSL_NO_EC
-DEFINEFUNC4(EC_KEY *, PEM_read_bio_ECPrivateKey, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
+DEFINEFUNC4(EC_KEY *, PEM_read_bio_ECPrivateKey, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return)
#endif
-DEFINEFUNC4(DH *, PEM_read_bio_DHparams, BIO *a, a, DH **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
+DEFINEFUNC4(DH *, PEM_read_bio_DHparams, BIO *a, a, DH **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return)
DEFINEFUNC7(int, PEM_write_bio_DSAPrivateKey, BIO *a, a, DSA *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return)
DEFINEFUNC7(int, PEM_write_bio_RSAPrivateKey, BIO *a, a, RSA *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return)
#ifndef OPENSSL_NO_EC
DEFINEFUNC7(int, PEM_write_bio_ECPrivateKey, BIO *a, a, EC_KEY *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return)
#endif
#endif // !SSLEAY_MACROS
-DEFINEFUNC4(EVP_PKEY *, PEM_read_bio_PUBKEY, BIO *a, a, EVP_PKEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
-DEFINEFUNC4(DSA *, PEM_read_bio_DSA_PUBKEY, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
-DEFINEFUNC4(RSA *, PEM_read_bio_RSA_PUBKEY, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
+DEFINEFUNC4(EVP_PKEY *, PEM_read_bio_PUBKEY, BIO *a, a, EVP_PKEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return)
+DEFINEFUNC4(DSA *, PEM_read_bio_DSA_PUBKEY, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return)
+DEFINEFUNC4(RSA *, PEM_read_bio_RSA_PUBKEY, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return)
#ifndef OPENSSL_NO_EC
-DEFINEFUNC4(EC_KEY *, PEM_read_bio_EC_PUBKEY, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
+DEFINEFUNC4(EC_KEY *, PEM_read_bio_EC_PUBKEY, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return)
#endif
DEFINEFUNC2(int, PEM_write_bio_DSA_PUBKEY, BIO *a, a, DSA *b, b, return 0, return)
DEFINEFUNC2(int, PEM_write_bio_RSA_PUBKEY, BIO *a, a, RSA *b, b, return 0, return)
@@ -381,20 +413,22 @@ DEFINEFUNC2(int, PEM_write_bio_EC_PUBKEY, BIO *a, a, EC_KEY *b, b, return 0, ret
#endif
DEFINEFUNC2(void, RAND_seed, const void *a, a, int b, b, return, DUMMYARG)
DEFINEFUNC(int, RAND_status, void, DUMMYARG, return -1, return)
-DEFINEFUNC(RSA *, RSA_new, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC2(int, RAND_bytes, unsigned char *b, b, int n, n, return 0, return)
+DEFINEFUNC(RSA *, RSA_new, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC(void, RSA_free, RSA *a, a, return, DUMMYARG)
DEFINEFUNC(int, SSL_accept, SSL *a, a, return -1, return)
DEFINEFUNC(int, SSL_clear, SSL *a, a, return -1, return)
-DEFINEFUNC3(char *, SSL_CIPHER_description, const SSL_CIPHER *a, a, char *b, b, int c, c, return 0, return)
+DEFINEFUNC3(char *, SSL_CIPHER_description, const SSL_CIPHER *a, a, char *b, b, int c, c, return nullptr, return)
DEFINEFUNC2(int, SSL_CIPHER_get_bits, const SSL_CIPHER *a, a, int *b, b, return 0, return)
+DEFINEFUNC(BIO *, SSL_get_rbio, const SSL *s, s, return nullptr, return)
DEFINEFUNC(int, SSL_connect, SSL *a, a, return -1, return)
DEFINEFUNC(int, SSL_CTX_check_private_key, const SSL_CTX *a, a, return -1, return)
DEFINEFUNC4(long, SSL_CTX_ctrl, SSL_CTX *a, a, int b, b, long c, c, void *d, d, return -1, return)
DEFINEFUNC(void, SSL_CTX_free, SSL_CTX *a, a, return, DUMMYARG)
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
-DEFINEFUNC(SSL_CTX *, SSL_CTX_new, const SSL_METHOD *a, a, return 0, return)
+DEFINEFUNC(SSL_CTX *, SSL_CTX_new, const SSL_METHOD *a, a, return nullptr, return)
#else
-DEFINEFUNC(SSL_CTX *, SSL_CTX_new, SSL_METHOD *a, a, return 0, return)
+DEFINEFUNC(SSL_CTX *, SSL_CTX_new, SSL_METHOD *a, a, return nullptr, return)
#endif
DEFINEFUNC2(int, SSL_CTX_set_cipher_list, SSL_CTX *a, a, const char *b, b, return -1, return)
DEFINEFUNC(int, SSL_CTX_set_default_verify_paths, SSL_CTX *a, a, return -1, return)
@@ -405,9 +439,9 @@ DEFINEFUNC3(int, SSL_CTX_use_certificate_file, SSL_CTX *a, a, const char *b, b,
DEFINEFUNC2(int, SSL_CTX_use_PrivateKey, SSL_CTX *a, a, EVP_PKEY *b, b, return -1, return)
DEFINEFUNC2(int, SSL_CTX_use_RSAPrivateKey, SSL_CTX *a, a, RSA *b, b, return -1, return)
DEFINEFUNC3(int, SSL_CTX_use_PrivateKey_file, SSL_CTX *a, a, const char *b, b, int c, c, return -1, return)
-DEFINEFUNC(X509_STORE *, SSL_CTX_get_cert_store, const SSL_CTX *a, a, return 0, return)
+DEFINEFUNC(X509_STORE *, SSL_CTX_get_cert_store, const SSL_CTX *a, a, return nullptr, return)
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
-DEFINEFUNC(SSL_CONF_CTX *, SSL_CONF_CTX_new, DUMMYARG, DUMMYARG, return 0, return);
+DEFINEFUNC(SSL_CONF_CTX *, SSL_CONF_CTX_new, DUMMYARG, DUMMYARG, return nullptr, return);
DEFINEFUNC(void, SSL_CONF_CTX_free, SSL_CONF_CTX *a, a, return ,return);
DEFINEFUNC2(void, SSL_CONF_CTX_set_ssl_ctx, SSL_CONF_CTX *a, a, SSL_CTX *b, b, return, return);
DEFINEFUNC2(unsigned int, SSL_CONF_CTX_set_flags, SSL_CONF_CTX *a, a, unsigned int b, b, return 0, return);
@@ -415,36 +449,37 @@ DEFINEFUNC(int, SSL_CONF_CTX_finish, SSL_CONF_CTX *a, a, return 0, return);
DEFINEFUNC3(int, SSL_CONF_cmd, SSL_CONF_CTX *a, a, const char *b, b, const char *c, c, return 0, return);
#endif
DEFINEFUNC(void, SSL_free, SSL *a, a, return, DUMMYARG)
-DEFINEFUNC(STACK_OF(SSL_CIPHER) *, SSL_get_ciphers, const SSL *a, a, return 0, return)
+DEFINEFUNC(STACK_OF(SSL_CIPHER) *, SSL_get_ciphers, const SSL *a, a, return nullptr, return)
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
-DEFINEFUNC(const SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return 0, return)
+DEFINEFUNC(const SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return nullptr, return)
#else
-DEFINEFUNC(SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return 0, return)
+DEFINEFUNC(SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return nullptr, return)
#endif
DEFINEFUNC(int, SSL_version, const SSL *a, a, return 0, return)
DEFINEFUNC2(int, SSL_get_error, SSL *a, a, int b, b, return -1, return)
-DEFINEFUNC(STACK_OF(X509) *, SSL_get_peer_cert_chain, SSL *a, a, return 0, return)
-DEFINEFUNC(X509 *, SSL_get_peer_certificate, SSL *a, a, return 0, return)
+DEFINEFUNC(STACK_OF(X509) *, SSL_get_peer_cert_chain, SSL *a, a, return nullptr, return)
+DEFINEFUNC(X509 *, SSL_get_peer_certificate, SSL *a, a, return nullptr, return)
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
// 0.9.8 broke SC and BC by changing this function's signature.
DEFINEFUNC(long, SSL_get_verify_result, const SSL *a, a, return -1, return)
#else
DEFINEFUNC(long, SSL_get_verify_result, SSL *a, a, return -1, return)
#endif
-DEFINEFUNC(SSL *, SSL_new, SSL_CTX *a, a, return 0, return)
+DEFINEFUNC(SSL *, SSL_new, SSL_CTX *a, a, return nullptr, return)
DEFINEFUNC4(long, SSL_ctrl, SSL *a, a, int cmd, cmd, long larg, larg, void *parg, parg, return -1, return)
DEFINEFUNC3(int, SSL_read, SSL *a, a, void *b, b, int c, c, return -1, return)
DEFINEFUNC3(void, SSL_set_bio, SSL *a, a, BIO *b, b, BIO *c, c, return, DUMMYARG)
DEFINEFUNC(void, SSL_set_accept_state, SSL *a, a, return, DUMMYARG)
DEFINEFUNC(void, SSL_set_connect_state, SSL *a, a, return, DUMMYARG)
DEFINEFUNC(int, SSL_shutdown, SSL *a, a, return -1, return)
+DEFINEFUNC(int, SSL_get_shutdown, const SSL *ssl, ssl, return 0, return)
DEFINEFUNC2(int, SSL_set_session, SSL* to, to, SSL_SESSION *session, session, return -1, return)
DEFINEFUNC(void, SSL_SESSION_free, SSL_SESSION *ses, ses, return, DUMMYARG)
-DEFINEFUNC(SSL_SESSION*, SSL_get1_session, SSL *ssl, ssl, return 0, return)
-DEFINEFUNC(SSL_SESSION*, SSL_get_session, const SSL *ssl, ssl, return 0, return)
+DEFINEFUNC(SSL_SESSION*, SSL_get1_session, SSL *ssl, ssl, return nullptr, return)
+DEFINEFUNC(SSL_SESSION*, SSL_get_session, const SSL *ssl, ssl, return nullptr, return)
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
DEFINEFUNC3(int, SSL_set_ex_data, SSL *ssl, ssl, int idx, idx, void *arg, arg, return 0, return)
-DEFINEFUNC2(void *, SSL_get_ex_data, const SSL *ssl, ssl, int idx, idx, return NULL, return)
+DEFINEFUNC2(void *, SSL_get_ex_data, const SSL *ssl, ssl, int idx, idx, return nullptr, return)
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
DEFINEFUNC2(void, SSL_set_psk_client_callback, SSL* ssl, ssl, q_psk_client_callback_t callback, callback, return, DUMMYARG)
@@ -455,18 +490,18 @@ DEFINEFUNC3(int, SSL_write, SSL *a, a, const void *b, b, int c, c, return -1, re
DEFINEFUNC2(int, X509_cmp, X509 *a, a, X509 *b, b, return -1, return)
DEFINEFUNC4(int, X509_digest, const X509 *x509, x509, const EVP_MD *type, type, unsigned char *md, md, unsigned int *len, len, return -1, return)
#ifndef SSLEAY_MACROS
-DEFINEFUNC(X509 *, X509_dup, X509 *a, a, return 0, return)
+DEFINEFUNC(X509 *, X509_dup, X509 *a, a, return nullptr, return)
#endif
DEFINEFUNC2(void, X509_print, BIO *a, a, X509 *b, b, return, DUMMYARG);
-DEFINEFUNC(ASN1_OBJECT *, X509_EXTENSION_get_object, X509_EXTENSION *a, a, return 0, return)
+DEFINEFUNC(ASN1_OBJECT *, X509_EXTENSION_get_object, X509_EXTENSION *a, a, return nullptr, return)
DEFINEFUNC(void, X509_free, X509 *a, a, return, DUMMYARG)
-DEFINEFUNC2(X509_EXTENSION *, X509_get_ext, X509 *a, a, int b, b, return 0, return)
+DEFINEFUNC2(X509_EXTENSION *, X509_get_ext, X509 *a, a, int b, b, return nullptr, return)
DEFINEFUNC(int, X509_get_ext_count, X509 *a, a, return 0, return)
-DEFINEFUNC4(void *, X509_get_ext_d2i, X509 *a, a, int b, b, int *c, c, int *d, d, return 0, return)
-DEFINEFUNC(const X509V3_EXT_METHOD *, X509V3_EXT_get, X509_EXTENSION *a, a, return 0, return)
-DEFINEFUNC(void *, X509V3_EXT_d2i, X509_EXTENSION *a, a, return 0, return)
+DEFINEFUNC4(void *, X509_get_ext_d2i, X509 *a, a, int b, b, int *c, c, int *d, d, return nullptr, return)
+DEFINEFUNC(const X509V3_EXT_METHOD *, X509V3_EXT_get, X509_EXTENSION *a, a, return nullptr, return)
+DEFINEFUNC(void *, X509V3_EXT_d2i, X509_EXTENSION *a, a, return nullptr, return)
DEFINEFUNC(int, X509_EXTENSION_get_critical, X509_EXTENSION *a, a, return 0, return)
-DEFINEFUNC(ASN1_OCTET_STRING *, X509_EXTENSION_get_data, X509_EXTENSION *a, a, return 0, return)
+DEFINEFUNC(ASN1_OCTET_STRING *, X509_EXTENSION_get_data, X509_EXTENSION *a, a, return nullptr, return)
DEFINEFUNC(void, BASIC_CONSTRAINTS_free, BASIC_CONSTRAINTS *a, a, return, DUMMYARG)
DEFINEFUNC(void, AUTHORITY_KEYID_free, AUTHORITY_KEYID *a, a, return, DUMMYARG)
DEFINEFUNC(void, GENERAL_NAME_free, GENERAL_NAME *a, a, return, DUMMYARG)
@@ -476,28 +511,30 @@ DEFINEFUNC2(int, ASN1_STRING_print, BIO *a, a, const ASN1_STRING *b, b, return 0
DEFINEFUNC2(int, ASN1_STRING_print, BIO *a, a, ASN1_STRING *b, b, return 0, return)
#endif
DEFINEFUNC2(int, X509_check_issued, X509 *a, a, X509 *b, b, return -1, return)
-DEFINEFUNC(X509_NAME *, X509_get_issuer_name, X509 *a, a, return 0, return)
-DEFINEFUNC(X509_NAME *, X509_get_subject_name, X509 *a, a, return 0, return)
-DEFINEFUNC(ASN1_INTEGER *, X509_get_serialNumber, X509 *a, a, return 0, return)
+DEFINEFUNC(X509_NAME *, X509_get_issuer_name, X509 *a, a, return nullptr, return)
+DEFINEFUNC(X509_NAME *, X509_get_subject_name, X509 *a, a, return nullptr, return)
+DEFINEFUNC(ASN1_INTEGER *, X509_get_serialNumber, X509 *a, a, return nullptr, return)
DEFINEFUNC(int, X509_verify_cert, X509_STORE_CTX *a, a, return -1, return)
DEFINEFUNC(int, X509_NAME_entry_count, X509_NAME *a, a, return 0, return)
-DEFINEFUNC2(X509_NAME_ENTRY *, X509_NAME_get_entry, X509_NAME *a, a, int b, b, return 0, return)
-DEFINEFUNC(ASN1_STRING *, X509_NAME_ENTRY_get_data, X509_NAME_ENTRY *a, a, return 0, return)
-DEFINEFUNC(ASN1_OBJECT *, X509_NAME_ENTRY_get_object, X509_NAME_ENTRY *a, a, return 0, return)
-DEFINEFUNC(EVP_PKEY *, X509_PUBKEY_get, X509_PUBKEY *a, a, return 0, return)
+DEFINEFUNC2(X509_NAME_ENTRY *, X509_NAME_get_entry, X509_NAME *a, a, int b, b, return nullptr, return)
+DEFINEFUNC(ASN1_STRING *, X509_NAME_ENTRY_get_data, X509_NAME_ENTRY *a, a, return nullptr, return)
+DEFINEFUNC(ASN1_OBJECT *, X509_NAME_ENTRY_get_object, X509_NAME_ENTRY *a, a, return nullptr, return)
+DEFINEFUNC(EVP_PKEY *, X509_PUBKEY_get, X509_PUBKEY *a, a, return nullptr, return)
DEFINEFUNC(void, X509_STORE_free, X509_STORE *a, a, return, DUMMYARG)
-DEFINEFUNC(X509_STORE *, X509_STORE_new, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(X509_STORE *, X509_STORE_new, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC2(int, X509_STORE_add_cert, X509_STORE *a, a, X509 *b, b, return 0, return)
DEFINEFUNC(void, X509_STORE_CTX_free, X509_STORE_CTX *a, a, return, DUMMYARG)
DEFINEFUNC4(int, X509_STORE_CTX_init, X509_STORE_CTX *a, a, X509_STORE *b, b, X509 *c, c, STACK_OF(X509) *d, d, return -1, return)
DEFINEFUNC2(int, X509_STORE_CTX_set_purpose, X509_STORE_CTX *a, a, int b, b, return -1, return)
DEFINEFUNC(int, X509_STORE_CTX_get_error, X509_STORE_CTX *a, a, return -1, return)
DEFINEFUNC(int, X509_STORE_CTX_get_error_depth, X509_STORE_CTX *a, a, return -1, return)
-DEFINEFUNC(X509 *, X509_STORE_CTX_get_current_cert, X509_STORE_CTX *a, a, return 0, return)
-DEFINEFUNC(X509_STORE_CTX *, X509_STORE_CTX_new, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(X509 *, X509_STORE_CTX_get_current_cert, X509_STORE_CTX *a, a, return nullptr, return)
+DEFINEFUNC(X509_STORE_CTX *, X509_STORE_CTX_new, DUMMYARG, DUMMYARG, return nullptr, return)
+DEFINEFUNC2(void *, X509_STORE_CTX_get_ex_data, X509_STORE_CTX *ctx, ctx, int idx, idx, return nullptr, return)
+DEFINEFUNC(int, SSL_get_ex_data_X509_STORE_CTX_idx, DUMMYARG, DUMMYARG, return -1, return)
DEFINEFUNC3(int, SSL_CTX_load_verify_locations, SSL_CTX *ctx, ctx, const char *CAfile, CAfile, const char *CApath, CApath, return 0, return)
DEFINEFUNC2(int, i2d_SSL_SESSION, SSL_SESSION *in, in, unsigned char **pp, pp, return 0, return)
-DEFINEFUNC3(SSL_SESSION *, d2i_SSL_SESSION, SSL_SESSION **a, a, const unsigned char **pp, pp, long length, length, return 0, return)
+DEFINEFUNC3(SSL_SESSION *, d2i_SSL_SESSION, SSL_SESSION **a, a, const unsigned char **pp, pp, long length, length, return nullptr, return)
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG)
DEFINEFUNC6(int, SSL_select_next_proto, unsigned char **out, out, unsigned char *outlen, outlen,
const unsigned char *in, in, unsigned int inlen, inlen,
@@ -524,15 +561,28 @@ DEFINEFUNC3(void, SSL_get0_alpn_selected, const SSL *s, s, const unsigned char *
unsigned *len, len, return, DUMMYARG)
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ...
#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
-DEFINEFUNC(DH *, DH_new, DUMMYARG, DUMMYARG, return 0, return)
+
+// DTLS:
+#if QT_CONFIG(dtls)
+DEFINEFUNC2(void, SSL_CTX_set_cookie_generate_cb, SSL_CTX *ctx, ctx, CookieGenerateCallback cb, cb, return, DUMMYARG)
+DEFINEFUNC2(void, SSL_CTX_set_cookie_verify_cb, SSL_CTX *ctx, ctx, CookieVerifyCallback cb, cb, return, DUMMYARG)
+DEFINEFUNC(const SSL_METHOD *, DTLS_server_method, DUMMYARG, DUMMYARG, return nullptr, return)
+DEFINEFUNC(const SSL_METHOD *, DTLS_client_method, DUMMYARG, DUMMYARG, return nullptr, return)
+#endif // dtls
+DEFINEFUNC2(void, BIO_set_flags, BIO *b, b, int flags, flags, return, DUMMYARG)
+DEFINEFUNC2(void, BIO_clear_flags, BIO *b, b, int flags, flags, return, DUMMYARG)
+DEFINEFUNC2(void *, BIO_get_ex_data, BIO *b, b, int idx, idx, return nullptr, return)
+DEFINEFUNC3(int, BIO_set_ex_data, BIO *b, b, int idx, idx, void *data, data, return -1, return)
+
+DEFINEFUNC(DH *, DH_new, DUMMYARG, DUMMYARG, return nullptr, return)
DEFINEFUNC(void, DH_free, DH *dh, dh, return, DUMMYARG)
-DEFINEFUNC3(DH *, d2i_DHparams, DH**a, a, const unsigned char **pp, pp, long length, length, return 0, return)
+DEFINEFUNC3(DH *, d2i_DHparams, DH**a, a, const unsigned char **pp, pp, long length, length, return nullptr, return)
DEFINEFUNC2(int, i2d_DHparams, DH *a, a, unsigned char **p, p, return -1, return)
DEFINEFUNC2(int, DH_check, DH *dh, dh, int *codes, codes, return 0, return)
-DEFINEFUNC3(BIGNUM *, BN_bin2bn, const unsigned char *s, s, int len, len, BIGNUM *ret, ret, return 0, return)
+DEFINEFUNC3(BIGNUM *, BN_bin2bn, const unsigned char *s, s, int len, len, BIGNUM *ret, ret, return nullptr, return)
#ifndef OPENSSL_NO_EC
-DEFINEFUNC(EC_KEY *, EC_KEY_dup, const EC_KEY *ec, ec, return 0, return)
-DEFINEFUNC(EC_KEY *, EC_KEY_new_by_curve_name, int nid, nid, return 0, return)
+DEFINEFUNC(EC_KEY *, EC_KEY_dup, const EC_KEY *ec, ec, return nullptr, return)
+DEFINEFUNC(EC_KEY *, EC_KEY_new_by_curve_name, int nid, nid, return nullptr, return)
DEFINEFUNC(void, EC_KEY_free, EC_KEY *ecdh, ecdh, return, DUMMYARG)
DEFINEFUNC2(size_t, EC_get_builtin_curves, EC_builtin_curve * r, r, size_t nitems, nitems, return 0, return)
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
@@ -542,7 +592,7 @@ DEFINEFUNC(int, EC_curve_nist2nid, const char *name, name, return 0, return)
DEFINEFUNC5(int, PKCS12_parse, PKCS12 *p12, p12, const char *pass, pass, EVP_PKEY **pkey, pkey, \
X509 **cert, cert, STACK_OF(X509) **ca, ca, return 1, return);
-DEFINEFUNC2(PKCS12 *, d2i_PKCS12_bio, BIO *bio, bio, PKCS12 **pkcs12, pkcs12, return 0, return);
+DEFINEFUNC2(PKCS12 *, d2i_PKCS12_bio, BIO *bio, bio, PKCS12 **pkcs12, pkcs12, return nullptr, return);
DEFINEFUNC(void, PKCS12_free, PKCS12 *pkcs12, pkcs12, return, DUMMYARG)
#define RESOLVEFUNC(func) \
@@ -626,7 +676,7 @@ static QStringList libraryPathList()
// search in .app/Contents/Frameworks
UInt32 packageType;
- CFBundleGetPackageInfo(CFBundleGetMainBundle(), &packageType, NULL);
+ CFBundleGetPackageInfo(CFBundleGetMainBundle(), &packageType, nullptr);
if (packageType == FOUR_CHAR_CODE('APPL')) {
QUrl bundleUrl = QUrl::fromCFURL(QCFType<CFURLRef>(CFBundleCopyBundleURL(CFBundleGetMainBundle())));
QUrl frameworksUrl = QUrl::fromCFURL(QCFType<CFURLRef>(CFBundleCopyPrivateFrameworksURL(CFBundleGetMainBundle())));
@@ -878,7 +928,7 @@ bool q_resolveOpenSslSymbols()
{
static bool symbolsResolved = false;
static bool triedToResolveSymbols = false;
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
#if QT_CONFIG(opensslv11)
QMutexLocker locker(QMutexPool::globalInstanceGet((void *)&q_OPENSSL_init_ssl));
#else
@@ -920,6 +970,7 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(SSL_SESSION_get_master_key)
RESOLVEFUNC(SSL_session_reused)
RESOLVEFUNC(SSL_get_session)
+ RESOLVEFUNC(SSL_set_options)
RESOLVEFUNC(CRYPTO_get_ex_new_index)
RESOLVEFUNC(TLS_method)
RESOLVEFUNC(TLS_client_method)
@@ -946,6 +997,25 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(DH_bits)
RESOLVEFUNC(DSA_bits)
+#if QT_CONFIG(dtls)
+ RESOLVEFUNC(DTLSv1_listen)
+ RESOLVEFUNC(BIO_ADDR_new)
+ RESOLVEFUNC(BIO_ADDR_free)
+ RESOLVEFUNC(BIO_meth_new)
+ RESOLVEFUNC(BIO_meth_free)
+ RESOLVEFUNC(BIO_meth_set_write)
+ RESOLVEFUNC(BIO_meth_set_read)
+ RESOLVEFUNC(BIO_meth_set_puts)
+ RESOLVEFUNC(BIO_meth_set_ctrl)
+ RESOLVEFUNC(BIO_meth_set_create)
+ RESOLVEFUNC(BIO_meth_set_destroy)
+#endif // dtls
+
+ RESOLVEFUNC(BIO_set_data)
+ RESOLVEFUNC(BIO_get_data)
+ RESOLVEFUNC(BIO_set_init)
+ RESOLVEFUNC(BIO_get_shutdown)
+ RESOLVEFUNC(BIO_set_shutdown)
#else // !opensslv11
RESOLVEFUNC(ASN1_STRING_data)
@@ -1010,6 +1080,14 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(d2i_DSAPrivateKey)
RESOLVEFUNC(d2i_RSAPrivateKey)
#endif
+
+#if QT_CONFIG(dtls)
+ RESOLVEFUNC(DTLSv1_server_method)
+ RESOLVEFUNC(DTLSv1_client_method)
+ RESOLVEFUNC(DTLSv1_2_server_method)
+ RESOLVEFUNC(DTLSv1_2_client_method)
+#endif // dtls
+
RESOLVEFUNC(CONF_get1_default_config_file)
RESOLVEFUNC(OPENSSL_add_all_algorithms_noconf)
RESOLVEFUNC(OPENSSL_add_all_algorithms_conf)
@@ -1048,6 +1126,11 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(BIO_read)
RESOLVEFUNC(BIO_s_mem)
RESOLVEFUNC(BIO_write)
+ RESOLVEFUNC(BIO_set_flags)
+ RESOLVEFUNC(BIO_clear_flags)
+ RESOLVEFUNC(BIO_set_ex_data)
+ RESOLVEFUNC(BIO_get_ex_data)
+
#ifndef OPENSSL_NO_EC
RESOLVEFUNC(EC_KEY_get0_group)
RESOLVEFUNC(EC_GROUP_get_degree)
@@ -1060,6 +1143,7 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(DSA_new)
RESOLVEFUNC(DSA_free)
RESOLVEFUNC(ERR_error_string)
+ RESOLVEFUNC(ERR_error_string_n)
RESOLVEFUNC(ERR_get_error)
RESOLVEFUNC(EVP_CIPHER_CTX_new)
RESOLVEFUNC(EVP_CIPHER_CTX_free)
@@ -1127,10 +1211,12 @@ bool q_resolveOpenSslSymbols()
#endif
RESOLVEFUNC(RAND_seed)
RESOLVEFUNC(RAND_status)
+ RESOLVEFUNC(RAND_bytes)
RESOLVEFUNC(RSA_new)
RESOLVEFUNC(RSA_free)
RESOLVEFUNC(SSL_CIPHER_description)
RESOLVEFUNC(SSL_CIPHER_get_bits)
+ RESOLVEFUNC(SSL_get_rbio)
RESOLVEFUNC(SSL_CTX_check_private_key)
RESOLVEFUNC(SSL_CTX_ctrl)
RESOLVEFUNC(SSL_CTX_free)
@@ -1171,6 +1257,7 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(SSL_set_bio)
RESOLVEFUNC(SSL_set_connect_state)
RESOLVEFUNC(SSL_shutdown)
+ RESOLVEFUNC(SSL_get_shutdown)
RESOLVEFUNC(SSL_set_session)
RESOLVEFUNC(SSL_SESSION_free)
RESOLVEFUNC(SSL_get1_session)
@@ -1178,6 +1265,7 @@ bool q_resolveOpenSslSymbols()
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
RESOLVEFUNC(SSL_set_ex_data)
RESOLVEFUNC(SSL_get_ex_data)
+ RESOLVEFUNC(SSL_get_ex_data_X509_STORE_CTX_idx)
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
RESOLVEFUNC(SSL_set_psk_client_callback)
@@ -1201,6 +1289,8 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(X509_STORE_CTX_get_error_depth)
RESOLVEFUNC(X509_STORE_CTX_get_current_cert)
RESOLVEFUNC(X509_cmp)
+ RESOLVEFUNC(X509_STORE_CTX_get_ex_data)
+
#ifndef SSLEAY_MACROS
RESOLVEFUNC(X509_dup)
#endif
@@ -1239,6 +1329,12 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(SSL_CTX_set_alpn_select_cb)
RESOLVEFUNC(SSL_get0_alpn_selected)
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ...
+#if QT_CONFIG(dtls)
+ RESOLVEFUNC(SSL_CTX_set_cookie_generate_cb)
+ RESOLVEFUNC(SSL_CTX_set_cookie_verify_cb)
+ RESOLVEFUNC(DTLS_server_method)
+ RESOLVEFUNC(DTLS_client_method)
+#endif // dtls
RESOLVEFUNC(DH_new)
RESOLVEFUNC(DH_free)
RESOLVEFUNC(d2i_DHparams)
diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h
index 68b519d74e..bfdfbf0efc 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols_p.h
+++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h
@@ -257,6 +257,7 @@ DSA *q_DSA_new();
void q_DSA_free(DSA *a);
X509 *q_d2i_X509(X509 **a, const unsigned char **b, long c);
char *q_ERR_error_string(unsigned long a, char *b);
+void q_ERR_error_string_n(unsigned long e, char *buf, size_t len);
unsigned long q_ERR_get_error();
EVP_CIPHER_CTX *q_EVP_CIPHER_CTX_new();
void q_EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *a);
@@ -331,12 +332,14 @@ int q_PEM_write_bio_EC_PUBKEY(BIO *a, EC_KEY *b);
#endif
void q_RAND_seed(const void *a, int b);
int q_RAND_status();
+int q_RAND_bytes(unsigned char *b, int n);
RSA *q_RSA_new();
void q_RSA_free(RSA *a);
int q_SSL_accept(SSL *a);
int q_SSL_clear(SSL *a);
char *q_SSL_CIPHER_description(const SSL_CIPHER *a, char *b, int c);
int q_SSL_CIPHER_get_bits(const SSL_CIPHER *a, int *b);
+BIO *q_SSL_get_rbio(const SSL *s);
int q_SSL_connect(SSL *a);
int q_SSL_CTX_check_private_key(const SSL_CTX *a);
long q_SSL_CTX_ctrl(SSL_CTX *a, int b, long c, void *d);
@@ -383,6 +386,7 @@ void q_SSL_set_bio(SSL *a, BIO *b, BIO *c);
void q_SSL_set_accept_state(SSL *a);
void q_SSL_set_connect_state(SSL *a);
int q_SSL_shutdown(SSL *a);
+int q_SSL_get_shutdown(const SSL *ssl);
int q_SSL_set_session(SSL *to, SSL_SESSION *session);
void q_SSL_SESSION_free(SSL_SESSION *ses);
SSL_SESSION *q_SSL_get1_session(SSL *ssl);
@@ -529,6 +533,40 @@ void q_SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data,
#endif
#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
+#if QT_CONFIG(dtls)
+
+extern "C"
+{
+typedef int (*CookieGenerateCallback)(SSL *, unsigned char *, unsigned *);
+}
+
+void q_SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, CookieGenerateCallback cb);
+void q_SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, CookieVerifyCallback cb);
+const SSL_METHOD *q_DTLS_server_method();
+const SSL_METHOD *q_DTLS_client_method();
+
+#endif // dtls
+
+void *q_X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx);
+int q_SSL_get_ex_data_X509_STORE_CTX_idx();
+
+#if QT_CONFIG(dtls)
+#define q_DTLS_set_link_mtu(ssl, mtu) q_SSL_ctrl((ssl), DTLS_CTRL_SET_LINK_MTU, (mtu), nullptr)
+#define q_DTLSv1_get_timeout(ssl, arg) q_SSL_ctrl(ssl, DTLS_CTRL_GET_TIMEOUT, 0, arg)
+#define q_DTLSv1_handle_timeout(ssl) q_SSL_ctrl(ssl, DTLS_CTRL_HANDLE_TIMEOUT, 0, nullptr)
+#endif // dtls
+
+void q_BIO_set_flags(BIO *b, int flags);
+void q_BIO_clear_flags(BIO *b, int flags);
+void *q_BIO_get_ex_data(BIO *b, int idx);
+int q_BIO_set_ex_data(BIO *b, int idx, void *data);
+
+#define q_BIO_set_retry_read(b) q_BIO_set_flags(b, (BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY))
+#define q_BIO_set_retry_write(b) q_BIO_set_flags(b, (BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY))
+#define q_BIO_clear_retry_flags(b) q_BIO_clear_flags(b, (BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY))
+#define q_BIO_set_app_data(s,arg) q_BIO_set_ex_data(s,0,arg)
+#define q_BIO_get_app_data(s) q_BIO_get_ex_data(s,0)
+
// Helper function
class QDateTime;
QDateTime q_getTimeFromASN1(const ASN1_TIME *aTime);
diff --git a/src/network/ssl/qsslsocket_opensslpre11_symbols_p.h b/src/network/ssl/qsslsocket_opensslpre11_symbols_p.h
index 9686d22b98..b7bac5d2a2 100644
--- a/src/network/ssl/qsslsocket_opensslpre11_symbols_p.h
+++ b/src/network/ssl/qsslsocket_opensslpre11_symbols_p.h
@@ -204,6 +204,7 @@ DSA *q_d2i_DSAPrivateKey(DSA **a, unsigned char **pp, long length);
#endif // SSLEAY_MACROS
#define q_SSL_CTX_set_options(ctx,op) q_SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL)
+#define q_SSL_set_options(ssl,op) q_SSL_ctrl((ssl),SSL_CTRL_OPTIONS,(op),nullptr)
#define q_SKM_sk_num(type, st) ((int (*)(const STACK_OF(type) *))q_sk_num)(st)
#define q_SKM_sk_value(type, st,i) ((type * (*)(const STACK_OF(type) *, int))q_sk_value)(st, i)
#define q_X509_getm_notAfter(x) X509_get_notAfter(x)
@@ -226,5 +227,19 @@ void q_OPENSSL_add_all_algorithms_conf();
long q_SSLeay();
const char *q_SSLeay_version(int type);
+#if QT_CONFIG(dtls)
+// DTLS:
+extern "C"
+{
+typedef int (*CookieVerifyCallback)(SSL *, unsigned char *, unsigned);
+}
+
+#define q_DTLSv1_listen(ssl, peer) q_SSL_ctrl(ssl, DTLS_CTRL_LISTEN, 0, (void *)peer)
+
+const SSL_METHOD *q_DTLSv1_server_method();
+const SSL_METHOD *q_DTLSv1_client_method();
+const SSL_METHOD *q_DTLSv1_2_server_method();
+const SSL_METHOD *q_DTLSv1_2_client_method();
+#endif // dtls
#endif // QSSLSOCKET_OPENSSL_PRE11_SYMBOLS_P_H
diff --git a/src/network/ssl/qwindowscarootfetcher.cpp b/src/network/ssl/qwindowscarootfetcher.cpp
new file mode 100644
index 0000000000..f83f96886c
--- /dev/null
+++ b/src/network/ssl/qwindowscarootfetcher.cpp
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 "qwindowscarootfetcher_p.h"
+
+#include <QtCore/QThread>
+#include <QtGlobal>
+
+#ifdef QSSLSOCKET_DEBUG
+#include "qssl_p.h" // for debug categories
+#include <QtCore/QElapsedTimer>
+#endif
+
+#include "qsslsocket_p.h" // Transitively includes Wincrypt.h
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsCaRootFetcherThread : public QThread
+{
+public:
+ QWindowsCaRootFetcherThread()
+ {
+ qRegisterMetaType<QSslCertificate>();
+ setObjectName(QStringLiteral("QWindowsCaRootFetcher"));
+ start();
+ }
+ ~QWindowsCaRootFetcherThread()
+ {
+ quit();
+ wait(15500); // worst case, a running request can block for 15 seconds
+ }
+};
+
+Q_GLOBAL_STATIC(QWindowsCaRootFetcherThread, windowsCaRootFetcherThread);
+
+QWindowsCaRootFetcher::QWindowsCaRootFetcher(const QSslCertificate &certificate, QSslSocket::SslMode sslMode)
+ : cert(certificate), mode(sslMode)
+{
+ moveToThread(windowsCaRootFetcherThread());
+}
+
+QWindowsCaRootFetcher::~QWindowsCaRootFetcher()
+{
+}
+
+void QWindowsCaRootFetcher::start()
+{
+ QByteArray der = cert.toDer();
+ PCCERT_CONTEXT wincert = CertCreateCertificateContext(X509_ASN_ENCODING, (const BYTE *)der.constData(), der.length());
+ if (!wincert) {
+#ifdef QSSLSOCKET_DEBUG
+ qCDebug(lcSsl, "QWindowsCaRootFetcher failed to convert certificate to windows form");
+#endif
+ emit finished(cert, QSslCertificate());
+ deleteLater();
+ return;
+ }
+
+ CERT_CHAIN_PARA parameters;
+ memset(&parameters, 0, sizeof(parameters));
+ parameters.cbSize = sizeof(parameters);
+ // set key usage constraint
+ parameters.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
+ parameters.RequestedUsage.Usage.cUsageIdentifier = 1;
+ LPSTR oid = (LPSTR)(mode == QSslSocket::SslClientMode ? szOID_PKIX_KP_SERVER_AUTH : szOID_PKIX_KP_CLIENT_AUTH);
+ parameters.RequestedUsage.Usage.rgpszUsageIdentifier = &oid;
+
+#ifdef QSSLSOCKET_DEBUG
+ QElapsedTimer stopwatch;
+ stopwatch.start();
+#endif
+ PCCERT_CHAIN_CONTEXT chain;
+ BOOL result = CertGetCertificateChain(
+ nullptr, //default engine
+ wincert,
+ nullptr, //current date/time
+ nullptr, //default store
+ &parameters,
+ 0, //default dwFlags
+ nullptr, //reserved
+ &chain);
+#ifdef QSSLSOCKET_DEBUG
+ qCDebug(lcSsl) << "QWindowsCaRootFetcher" << stopwatch.elapsed() << "ms to get chain";
+#endif
+
+ QSslCertificate trustedRoot;
+ if (result) {
+#ifdef QSSLSOCKET_DEBUG
+ qCDebug(lcSsl) << "QWindowsCaRootFetcher - examining windows chains";
+ if (chain->TrustStatus.dwErrorStatus == CERT_TRUST_NO_ERROR)
+ qCDebug(lcSsl) << " - TRUSTED";
+ else
+ qCDebug(lcSsl) << " - NOT TRUSTED" << chain->TrustStatus.dwErrorStatus;
+ if (chain->TrustStatus.dwInfoStatus & CERT_TRUST_IS_SELF_SIGNED)
+ qCDebug(lcSsl) << " - SELF SIGNED";
+ qCDebug(lcSsl) << "QSslSocketBackendPrivate::fetchCaRootForCert - dumping simple chains";
+ for (unsigned int i = 0; i < chain->cChain; i++) {
+ if (chain->rgpChain[i]->TrustStatus.dwErrorStatus == CERT_TRUST_NO_ERROR)
+ qCDebug(lcSsl) << " - TRUSTED SIMPLE CHAIN" << i;
+ else
+ qCDebug(lcSsl) << " - UNTRUSTED SIMPLE CHAIN" << i << "reason:" << chain->rgpChain[i]->TrustStatus.dwErrorStatus;
+ for (unsigned int j = 0; j < chain->rgpChain[i]->cElement; j++) {
+ QSslCertificate foundCert(QByteArray((const char *)chain->rgpChain[i]->rgpElement[j]->pCertContext->pbCertEncoded
+ , chain->rgpChain[i]->rgpElement[j]->pCertContext->cbCertEncoded), QSsl::Der);
+ qCDebug(lcSsl) << " - " << foundCert;
+ }
+ }
+ qCDebug(lcSsl) << " - and" << chain->cLowerQualityChainContext << "low quality chains"; //expect 0, we haven't asked for them
+#endif
+
+ //based on http://msdn.microsoft.com/en-us/library/windows/desktop/aa377182%28v=vs.85%29.aspx
+ //about the final chain rgpChain[cChain-1] which must begin with a trusted root to be valid
+ if (chain->TrustStatus.dwErrorStatus == CERT_TRUST_NO_ERROR
+ && chain->cChain > 0) {
+ const PCERT_SIMPLE_CHAIN finalChain = chain->rgpChain[chain->cChain - 1];
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/aa377544%28v=vs.85%29.aspx
+ // rgpElement[0] is the end certificate chain element. rgpElement[cElement-1] is the self-signed "root" certificate element.
+ if (finalChain->TrustStatus.dwErrorStatus == CERT_TRUST_NO_ERROR
+ && finalChain->cElement > 0) {
+ trustedRoot = QSslCertificate(QByteArray((const char *)finalChain->rgpElement[finalChain->cElement - 1]->pCertContext->pbCertEncoded
+ , finalChain->rgpElement[finalChain->cElement - 1]->pCertContext->cbCertEncoded), QSsl::Der);
+ }
+ }
+ CertFreeCertificateChain(chain);
+ }
+ CertFreeCertificateContext(wincert);
+
+ emit finished(cert, trustedRoot);
+ deleteLater();
+}
+
+QT_END_NAMESPACE
diff --git a/src/network/ssl/qwindowscarootfetcher_p.h b/src/network/ssl/qwindowscarootfetcher_p.h
new file mode 100644
index 0000000000..181c309388
--- /dev/null
+++ b/src/network/ssl/qwindowscarootfetcher_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 QWINDOWSCAROOTFETCHER_P_H
+#define QWINDOWSCAROOTFETCHER_P_H
+
+#include <QtCore/QtGlobal>
+#include <QtCore/QObject>
+
+#include "qsslsocket.h"
+#include "qsslcertificate.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.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsCaRootFetcher : public QObject
+{
+ Q_OBJECT;
+public:
+ QWindowsCaRootFetcher(const QSslCertificate &certificate, QSslSocket::SslMode sslMode);
+ ~QWindowsCaRootFetcher();
+public slots:
+ void start();
+signals:
+ void finished(QSslCertificate brokenChain, QSslCertificate caroot);
+private:
+ QSslCertificate cert;
+ QSslSocket::SslMode mode;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSCAROOTFETCHER_P_H
diff --git a/src/network/ssl/ssl.pri b/src/network/ssl/ssl.pri
index 2783effaf1..6975264038 100644
--- a/src/network/ssl/ssl.pri
+++ b/src/network/ssl/ssl.pri
@@ -1,12 +1,23 @@
# OpenSSL support; compile in QSslSocket.
+
+HEADERS += ssl/qasn1element_p.h \
+ ssl/qssl.h \
+ ssl/qssl_p.h \
+ ssl/qsslcertificate.h \
+ ssl/qsslcertificate_p.h \
+ ssl/qsslcertificateextension.h \
+ ssl/qsslcertificateextension_p.h
+
+SOURCES += ssl/qasn1element.cpp \
+ ssl/qssl.cpp \
+ ssl/qsslcertificate.cpp \
+ ssl/qsslcertificateextension.cpp
+
+!qtConfig(openssl): SOURCES += ssl/qsslcertificate_qt.cpp
+
qtConfig(ssl) {
- HEADERS += ssl/qasn1element_p.h \
- ssl/qssl.h \
- ssl/qssl_p.h \
- ssl/qsslcertificate.h \
- ssl/qsslcertificate_p.h \
- ssl/qsslconfiguration.h \
- ssl/qsslconfiguration_p.h \
+ HEADERS += ssl/qsslconfiguration.h \
+ ssl/qsslconfiguration_p.h \
ssl/qsslcipher.h \
ssl/qsslcipher_p.h \
ssl/qssldiffiehellmanparameters.h \
@@ -18,26 +29,19 @@ qtConfig(ssl) {
ssl/qsslsocket.h \
ssl/qsslsocket_p.h \
ssl/qsslpresharedkeyauthenticator.h \
- ssl/qsslpresharedkeyauthenticator_p.h \
- ssl/qsslcertificateextension.h \
- ssl/qsslcertificateextension_p.h
- SOURCES += ssl/qasn1element.cpp \
- ssl/qssl.cpp \
- ssl/qsslcertificate.cpp \
- ssl/qsslconfiguration.cpp \
+ ssl/qsslpresharedkeyauthenticator_p.h
+ SOURCES += ssl/qsslconfiguration.cpp \
ssl/qsslcipher.cpp \
ssl/qssldiffiehellmanparameters.cpp \
ssl/qsslellipticcurve.cpp \
ssl/qsslkey_p.cpp \
ssl/qsslerror.cpp \
ssl/qsslsocket.cpp \
- ssl/qsslpresharedkeyauthenticator.cpp \
- ssl/qsslcertificateextension.cpp
+ ssl/qsslpresharedkeyauthenticator.cpp
winrt {
HEADERS += ssl/qsslsocket_winrt_p.h
- SOURCES += ssl/qsslcertificate_qt.cpp \
- ssl/qsslcertificate_winrt.cpp \
+ SOURCES += ssl/qsslcertificate_winrt.cpp \
ssl/qssldiffiehellmanparameters_dummy.cpp \
ssl/qsslkey_qt.cpp \
ssl/qsslkey_winrt.cpp \
@@ -47,8 +51,7 @@ qtConfig(ssl) {
qtConfig(securetransport) {
HEADERS += ssl/qsslsocket_mac_p.h
- SOURCES += ssl/qsslcertificate_qt.cpp \
- ssl/qssldiffiehellmanparameters_dummy.cpp \
+ SOURCES += ssl/qssldiffiehellmanparameters_dummy.cpp \
ssl/qsslkey_qt.cpp \
ssl/qsslkey_mac.cpp \
ssl/qsslsocket_mac_shared.cpp \
@@ -56,6 +59,13 @@ qtConfig(ssl) {
ssl/qsslellipticcurve_dummy.cpp
}
+ qtConfig(dtls) {
+ HEADERS += ssl/qdtls.h \
+ ssl/qdtls_p.h
+
+ SOURCES += ssl/qdtls.cpp
+ }
+
qtConfig(openssl) {
HEADERS += ssl/qsslcontext_openssl_p.h \
ssl/qsslsocket_openssl_p.h \
@@ -66,7 +76,12 @@ qtConfig(ssl) {
ssl/qsslellipticcurve_openssl.cpp \
ssl/qsslkey_openssl.cpp \
ssl/qsslsocket_openssl.cpp \
- ssl/qsslcontext_openssl.cpp
+ ssl/qsslcontext_openssl.cpp \
+
+ qtConfig(dtls) {
+ HEADERS += ssl/qdtls_openssl_p.h
+ SOURCES += ssl/qdtls_openssl.cpp
+ }
qtConfig(opensslv11) {
HEADERS += ssl/qsslsocket_openssl11_symbols_p.h
@@ -95,6 +110,13 @@ qtConfig(ssl) {
QMAKE_USE_FOR_PRIVATE += openssl
else: \
QMAKE_USE_FOR_PRIVATE += openssl/nolink
- win32: LIBS_PRIVATE += -lcrypt32
+ win32 {
+ LIBS_PRIVATE += -lcrypt32
+ HEADERS += ssl/qwindowscarootfetcher_p.h
+ SOURCES += ssl/qwindowscarootfetcher.cpp
+ }
}
}
+
+HEADERS += ssl/qpassworddigestor.h
+SOURCES += ssl/qpassworddigestor.cpp
diff --git a/src/opengl/doc/snippets/code/src_opengl_qglbuffer.cpp b/src/opengl/doc/snippets/code/src_opengl_qglbuffer.cpp
new file mode 100644
index 0000000000..c9e49826ae
--- /dev/null
+++ b/src/opengl/doc/snippets/code/src_opengl_qglbuffer.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtOpenGL module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+ QGLBuffer buffer1(QGLBuffer::IndexBuffer);
+ buffer1.create();
+
+ QGLBuffer buffer2 = buffer1;
+//! [0]
+
+//! [1]
+ QGLBuffer::release(QGLBuffer::VertexBuffer);
+//! [1]
diff --git a/src/opengl/doc/snippets/code/src_opengl_qglfunctions.cpp b/src/opengl/doc/snippets/code/src_opengl_qglfunctions.cpp
new file mode 100644
index 0000000000..673186dca9
--- /dev/null
+++ b/src/opengl/doc/snippets/code/src_opengl_qglfunctions.cpp
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtOpenGL module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+ class MyGLWidget : public QGLWidget, protected QGLFunctions
+ {
+ Q_OBJECT
+ public:
+ MyGLWidget(QWidget *parent = 0) : QGLWidget(parent) {}
+
+ protected:
+ void initializeGL();
+ void paintGL();
+ };
+
+ void MyGLWidget::initializeGL()
+ {
+ initializeGLFunctions();
+ }
+//! [0]
+
+//! [1]
+ void MyGLWidget::paintGL()
+ {
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, textureId);
+ ...
+ }
+//! [1]
+
+//! [2]
+ QGLFunctions glFuncs(QGLContext::currentContext());
+ glFuncs.glActiveTexture(GL_TEXTURE1);
+//! [2]
+
+//! [3]
+ QGLFunctions funcs(QGLContext::currentContext());
+ bool npot = funcs.hasOpenGLFeature(QGLFunctions::NPOTTextures);
+//! [3]
diff --git a/src/opengl/doc/snippets/code/src_opengl_qgraphicsshadereffect.cpp b/src/opengl/doc/snippets/code/src_opengl_qgraphicsshadereffect.cpp
new file mode 100644
index 0000000000..d53b73e837
--- /dev/null
+++ b/src/opengl/doc/snippets/code/src_opengl_qgraphicsshadereffect.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtOpenGL module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+ static char const colorizeShaderCode[] =
+ "uniform lowp vec4 effectColor;\n"
+ "lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords) {\n"
+ " vec4 src = texture2D(imageTexture, textureCoords);\n"
+ " float gray = dot(src.rgb, vec3(0.212671, 0.715160, 0.072169));\n"
+ " vec4 colorize = 1.0-((1.0-gray)*(1.0-effectColor));\n"
+ " return vec4(colorize.rgb, src.a);\n"
+ "}";
+//! [0]
+
+//! [1]
+ class ColorizeEffect : public QGraphicsShaderEffect
+ {
+ Q_OBJECT
+ public:
+ ColorizeEffect(QObject *parent = 0)
+ : QGraphicsShaderEffect(parent), color(Qt::black)
+ {
+ setPixelShaderFragment(colorizeShaderCode);
+ }
+
+ QColor effectColor() const { return color; }
+ void setEffectColor(const QColor& c)
+ {
+ color = c;
+ setUniformsDirty();
+ }
+
+ protected:
+ void setUniforms(QGLShaderProgram *program)
+ {
+ program->setUniformValue("effectColor", color);
+ }
+
+ private:
+ QColor color;
+ };
+//! [1]
+
+//! [2]
+ lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords) {
+ return texture2D(imageTexture, textureCoords);
+ }
+//! [2]
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index 6365a7421b..cc97bed3f7 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -2099,9 +2099,8 @@ bool QGL2PaintEngineEx::end()
d->device->endPaint();
ctx->d_ptr->active_engine = 0;
-
+ ctx->makeCurrent();
d->resetOpenGLContextActiveEngine();
-
d->resetGLState();
delete d->shaderManager;
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index d9f2113c14..e136ddcff2 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -2104,17 +2104,17 @@ struct DDSFormat {
would mirror the image and automatically generate mipmaps. This
option helps preserve this default behavior.
- \omitvalue CanFlipNativePixmapBindOption Used by x11 from pixmap to choose
- whether or not it can bind the pixmap upside down or not.
+ \omitvalue CanFlipNativePixmapBindOption \omit Used by x11 from pixmap to choose
+ whether or not it can bind the pixmap upside down or not. \endomit
- \omitvalue MemoryManagedBindOption Used by paint engines to
+ \omitvalue MemoryManagedBindOption \omit Used by paint engines to
indicate that the pixmap should be memory managed along side with
the pixmap/image that it stems from, e.g. installing destruction
- hooks in them.
+ hooks in them. \endomit
- \omitvalue TemporarilyCachedBindOption Used by paint engines on some
+ \omitvalue TemporarilyCachedBindOption \omit Used by paint engines on some
platforms to indicate that the pixmap or image texture is possibly
- cached only temporarily and must be destroyed immediately after the use.
+ cached only temporarily and must be destroyed immediately after the use. \endomit
\omitvalue InternalBindOption
*/
@@ -3603,7 +3603,8 @@ void QGLContext::makeCurrent()
\fn void QGLContext::swapBuffers() const
Call this to finish a frame of OpenGL rendering, and make sure to
- call makeCurrent() again before you begin a new frame.
+ call makeCurrent() again before issuing any further OpenGL commands,
+ for example as part of a new frame.
*/
void QGLContext::swapBuffers() const
{
@@ -4084,7 +4085,13 @@ bool QGLWidget::isSharing() const
void QGLWidget::makeCurrent()
{
Q_D(QGLWidget);
- d->glcx->makeCurrent();
+ d->makeCurrent();
+}
+
+bool QGLWidgetPrivate::makeCurrent()
+{
+ glcx->makeCurrent();
+ return QGLContext::currentContext() == glcx;
}
/*!
@@ -4422,7 +4429,8 @@ void QGLWidget::resizeEvent(QResizeEvent *e)
QWidget::resizeEvent(e);
if (!isValid())
return;
- makeCurrent();
+ if (!d->makeCurrent())
+ return;
if (!d->glcx->initialized())
glInit();
const qreal scaleFactor = (window() && window()->windowHandle()) ?
@@ -4537,7 +4545,8 @@ void QGLWidget::glInit()
Q_D(QGLWidget);
if (!isValid())
return;
- makeCurrent();
+ if (!d->makeCurrent())
+ return;
initializeGL();
d->glcx->setInitialized(true);
}
@@ -4555,7 +4564,8 @@ void QGLWidget::glDraw()
Q_D(QGLWidget);
if (!isValid())
return;
- makeCurrent();
+ if (!d->makeCurrent())
+ return;
#ifndef QT_OPENGL_ES
if (d->glcx->deviceIsPixmap() && !d->glcx->contextHandle()->isOpenGLES())
qgl1_functions()->glDrawBuffer(GL_FRONT);
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
index 6b4d83888f..ed364283cc 100644
--- a/src/opengl/qgl_p.h
+++ b/src/opengl/qgl_p.h
@@ -145,6 +145,8 @@ public:
glcx->reset();
}
+ bool makeCurrent();
+
QGLContext *glcx;
QGLWidgetGLPaintDevice glDevice;
bool autoSwap;
diff --git a/src/opengl/qglbuffer.cpp b/src/opengl/qglbuffer.cpp
index 200ee2499e..bb9c2affbd 100644
--- a/src/opengl/qglbuffer.cpp
+++ b/src/opengl/qglbuffer.cpp
@@ -60,12 +60,7 @@ QT_BEGIN_NAMESPACE
QGLBuffer objects can be copied around as a reference to the
underlying GL buffer object:
- \code
- QGLBuffer buffer1(QGLBuffer::IndexBuffer);
- buffer1.create();
-
- QGLBuffer buffer2 = buffer1;
- \endcode
+ \snippet code/src_opengl_qglbuffer.cpp 0
QGLBuffer performs a shallow copy when objects are copied in this
manner, but does not implement copy-on-write semantics. The original
@@ -474,9 +469,7 @@ void QGLBuffer::release()
been bound to the context but wants to make sure that it
is released.
- \code
- QGLBuffer::release(QGLBuffer::VertexBuffer);
- \endcode
+ \snippet code/src_opengl_qglbuffer.cpp 1
*/
void QGLBuffer::release(QGLBuffer::Type type)
{
diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp
index 0b386ededc..0b2ddf97fe 100644
--- a/src/opengl/qglframebufferobject.cpp
+++ b/src/opengl/qglframebufferobject.cpp
@@ -103,6 +103,14 @@ extern QImage qt_gl_read_frame_buffer(const QSize&, bool, bool);
#define GL_DRAW_FRAMEBUFFER 0x8CA9
#endif
+#ifndef GL_DEPTH_STENCIL_ATTACHMENT
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#endif
+
+#ifndef GL_DEPTH_STENCIL
+#define GL_DEPTH_STENCIL 0x84F9
+#endif
+
/*!
\class QGLFramebufferObjectFormat
\inmodule QtOpenGL
@@ -562,6 +570,7 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,
funcs.glGenRenderbuffers(1, &depth_buffer);
funcs.glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer);
Q_ASSERT(funcs.glIsRenderbuffer(depth_buffer));
+#ifndef Q_OS_WASM
if (samples != 0 && funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample))
funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
GL_DEPTH24_STENCIL8, size.width(), size.height());
@@ -574,6 +583,19 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,
GL_RENDERBUFFER, depth_buffer);
funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, stencil_buffer);
+#else
+ // webgl does not allow separate depth and stencil attachments
+ if (samples != 0) {
+ funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
+ GL_DEPTH_STENCIL, size.width(), size.height());
+ } else {
+ funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL,
+ size.width(), size.height());
+ }
+ stencil_buffer = depth_buffer;
+ funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, depth_buffer);
+#endif
valid = checkFramebufferStatus();
if (!valid) {
diff --git a/src/opengl/qglfunctions.cpp b/src/opengl/qglfunctions.cpp
index 07e1194342..7fe7102510 100644
--- a/src/opengl/qglfunctions.cpp
+++ b/src/opengl/qglfunctions.cpp
@@ -62,44 +62,18 @@ QT_BEGIN_NAMESPACE
that need it. The recommended way to use QGLFunctions is by
direct inheritance:
- \code
- class MyGLWidget : public QGLWidget, protected QGLFunctions
- {
- Q_OBJECT
- public:
- MyGLWidget(QWidget *parent = 0) : QGLWidget(parent) {}
-
- protected:
- void initializeGL();
- void paintGL();
- };
-
- void MyGLWidget::initializeGL()
- {
- initializeGLFunctions();
- }
- \endcode
+ \snippet code/src_opengl_qglfunctions.cpp 0
The \c{paintGL()} function can then use any of the OpenGL ES 2.0
functions without explicit resolution, such as glActiveTexture()
in the following example:
- \code
- void MyGLWidget::paintGL()
- {
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, textureId);
- ...
- }
- \endcode
+ \snippet code/src_opengl_qglfunctions.cpp 1
QGLFunctions can also be used directly for ad-hoc invocation
of OpenGL ES 2.0 functions on all platforms:
- \code
- QGLFunctions glFuncs(QGLContext::currentContext());
- glFuncs.glActiveTexture(GL_TEXTURE1);
- \endcode
+ \snippet code/src_opengl_qglfunctions.cpp 2
QGLFunctions provides wrappers for all OpenGL ES 2.0 functions,
except those like \c{glDrawArrays()}, \c{glViewport()}, and
@@ -114,10 +88,7 @@ QT_BEGIN_NAMESPACE
feature. For example, the following checks if non power of two
textures are available:
- \code
- QGLFunctions funcs(QGLContext::currentContext());
- bool npot = funcs.hasOpenGLFeature(QGLFunctions::NPOTTextures);
- \endcode
+ \snippet code/src_opengl_qglfunctions.cpp 3
\note This class has been deprecated in favor of QOpenGLFunctions.
*/
diff --git a/src/opengl/qglpaintdevice.cpp b/src/opengl/qglpaintdevice.cpp
index b29f71ad2e..c5151f66bb 100644
--- a/src/opengl/qglpaintdevice.cpp
+++ b/src/opengl/qglpaintdevice.cpp
@@ -126,6 +126,7 @@ void QGLPaintDevice::endPaint()
{
// Make sure the FBO bound at beginPaint is re-bound again here:
QGLContext *ctx = context();
+ ctx->makeCurrent();
ctx->d_func()->refreshCurrentFbo();
diff --git a/src/opengl/qgraphicsshadereffect.cpp b/src/opengl/qgraphicsshadereffect.cpp
index cf3d307d71..97b83a6b3d 100644
--- a/src/opengl/qgraphicsshadereffect.cpp
+++ b/src/opengl/qgraphicsshadereffect.cpp
@@ -70,48 +70,12 @@ QT_BEGIN_NAMESPACE
grayscale and then applies a colorize operation using the
\c effectColor value:
- \code
- static char const colorizeShaderCode[] =
- "uniform lowp vec4 effectColor;\n"
- "lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords) {\n"
- " vec4 src = texture2D(imageTexture, textureCoords);\n"
- " float gray = dot(src.rgb, vec3(0.212671, 0.715160, 0.072169));\n"
- " vec4 colorize = 1.0-((1.0-gray)*(1.0-effectColor));\n"
- " return vec4(colorize.rgb, src.a);\n"
- "}";
- \endcode
+ \snippet code/src_opengl_qgraphicsshadereffect.cpp 0
To use this shader code, it is necessary to define a subclass
of QGraphicsShaderEffect as follows:
- \code
- class ColorizeEffect : public QGraphicsShaderEffect
- {
- Q_OBJECT
- public:
- ColorizeEffect(QObject *parent = 0)
- : QGraphicsShaderEffect(parent), color(Qt::black)
- {
- setPixelShaderFragment(colorizeShaderCode);
- }
-
- QColor effectColor() const { return color; }
- void setEffectColor(const QColor& c)
- {
- color = c;
- setUniformsDirty();
- }
-
- protected:
- void setUniforms(QGLShaderProgram *program)
- {
- program->setUniformValue("effectColor", color);
- }
-
- private:
- QColor color;
- };
- \endcode
+ \snippet code/src_opengl_qgraphicsshadereffect.cpp 1
The setUniforms() function is called when the effect is about
to be used for drawing to give the subclass the opportunity to
@@ -216,11 +180,7 @@ QByteArray QGraphicsShaderEffect::pixelShaderFragment() const
shader program. The following is the default pixel shader fragment,
which draws a pixmap with no effect applied:
- \code
- lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords) {
- return texture2D(imageTexture, textureCoords);
- }
- \endcode
+ \snippet code/src_opengl_qgraphicsshadereffect.cpp 2
\sa pixelShaderFragment(), setUniforms()
*/
diff --git a/src/platformheaders/cocoafunctions/qcocoawindowfunctions.qdoc b/src/platformheaders/cocoafunctions/qcocoawindowfunctions.qdoc
index 876096e40f..e164a92e22 100644
--- a/src/platformheaders/cocoafunctions/qcocoawindowfunctions.qdoc
+++ b/src/platformheaders/cocoafunctions/qcocoawindowfunctions.qdoc
@@ -46,7 +46,7 @@
/*!
\fn QByteArray QCocoaWindowFunctions::bottomLeftClippedByNSWindowOffsetIdentifier()
- This function returnes the bytearray that can be used to query
+ This function returns the bytearray that can be used to query
QGuiApplication::platformFunction to retrieve the BottomLeftClippedByNSWindowOffset function.
*/
diff --git a/src/platformheaders/xcbfunctions/qxcbintegrationfunctions.h b/src/platformheaders/xcbfunctions/qxcbintegrationfunctions.h
deleted file mode 100644
index fc24dd0f6e..0000000000
--- a/src/platformheaders/xcbfunctions/qxcbintegrationfunctions.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QXCBINTEGRATIONFUNCTIONS_H
-#define QXCBINTEGRATIONFUNCTIONS_H
-
-#include <QtPlatformHeaders/QPlatformHeaderHelper>
-
-QT_BEGIN_NAMESPACE
-
-class QXcbIntegrationFunctions
-{
-public:
- typedef bool (*XEmbedSystemTrayVisualHasAlphaChannel)();
- static const QByteArray xEmbedSystemTrayVisualHasAlphaChannelIdentifier() { return QByteArrayLiteral("XcbXEmbedSystemTrayVisualHasAlphaChannel"); }
- static bool xEmbedSystemTrayVisualHasAlphaChannel()
- {
- return QPlatformHeaderHelper::callPlatformFunction<bool, XEmbedSystemTrayVisualHasAlphaChannel>(xEmbedSystemTrayVisualHasAlphaChannelIdentifier());
- }
-};
-
-QT_END_NAMESPACE
-
-#endif /*QXCBINTEGRATIONFUNCTIONS_H*/
diff --git a/src/platformheaders/xcbfunctions/qxcbwindowfunctions.h b/src/platformheaders/xcbfunctions/qxcbwindowfunctions.h
index b6c3b1db73..b0e6cb6a1d 100644
--- a/src/platformheaders/xcbfunctions/qxcbwindowfunctions.h
+++ b/src/platformheaders/xcbfunctions/qxcbwindowfunctions.h
@@ -90,27 +90,6 @@ public:
return QPlatformHeaderHelper::callPlatformFunction<void, SetWmWindowIconText, QWindow *, const QString &>(setWmWindowIconTextIdentifier(), window, text);
}
- typedef void (*SetParentRelativeBackPixmap)(const QWindow *window);
- static const QByteArray setParentRelativeBackPixmapIdentifier() { return QByteArrayLiteral("XcbSetParentRelativeBackPixmap"); }
- static void setParentRelativeBackPixmap(const QWindow *window)
- {
- return QPlatformHeaderHelper::callPlatformFunction<void, SetParentRelativeBackPixmap, const QWindow *>(setParentRelativeBackPixmapIdentifier(), window);
- }
-
- typedef bool (*RequestSystemTrayWindowDock)(const QWindow *window);
- static const QByteArray requestSystemTrayWindowDockIdentifier() { return QByteArrayLiteral("XcbRequestSystemTrayWindowDockIdentifier"); }
- static bool requestSystemTrayWindowDock(const QWindow *window)
- {
- return QPlatformHeaderHelper::callPlatformFunction<bool, RequestSystemTrayWindowDock, const QWindow *>(requestSystemTrayWindowDockIdentifier(), window);
- }
-
- typedef QRect (*SystemTrayWindowGlobalGeometry)(const QWindow *window);
- static const QByteArray systemTrayWindowGlobalGeometryIdentifier() { return QByteArrayLiteral("XcbSystemTrayWindowGlobalGeometryIdentifier"); }
- static QRect systemTrayWindowGlobalGeometry(const QWindow *window)
- {
- return QPlatformHeaderHelper::callPlatformFunction<QRect, SystemTrayWindowGlobalGeometry, const QWindow *>(systemTrayWindowGlobalGeometryIdentifier(), window);
- }
-
typedef uint (*VisualId)(QWindow *window);
static const QByteArray visualIdIdentifier() { return QByteArrayLiteral("XcbVisualId"); }
diff --git a/src/platformheaders/xcbfunctions/qxcbwindowfunctions.qdoc b/src/platformheaders/xcbfunctions/qxcbwindowfunctions.qdoc
index fab473b91b..5e2aa2cbf2 100644
--- a/src/platformheaders/xcbfunctions/qxcbwindowfunctions.qdoc
+++ b/src/platformheaders/xcbfunctions/qxcbwindowfunctions.qdoc
@@ -138,81 +138,6 @@
*/
/*!
- \typedef QXcbWindowFunctions::SetParentRelativeBackPixmap
-
- This is the typedef for the function returned by
- QGuiApplication::platformFunction when passed the
- value returned by setParentRelativeBackPixmapIdentifier().
-*/
-
-/*!
- \fn const QByteArray QXcbWindowFunctions::setParentRelativeBackPixmapIdentifier()
-
- This function returns the byte array that can be used to query
- QGuiApplication::platformFunction to retrieve the SetParentRelativeBackPixmap function.
-*/
-
-/*!
- \fn void QXcbWindowFunctions::setParentRelativeBackPixmap(const QWindow *window)
-
- This is a convenience function that can be used directly instead
- of resolving the function pointer. \a window will be
- relayed to the function retrieved by QGuiApplication.
-*/
-
-/*!
- \typedef QXcbWindowFunctions::RequestSystemTrayWindowDock
-
- This is the typedef for the function returned by
- QGuiApplication::platformFunction when passed the
- value returned by requestSystemTrayWindowDockIdentifier().
-*/
-
-/*!
- \fn const QByteArray QXcbWindowFunctions::requestSystemTrayWindowDockIdentifier()
-
- This function returns the byte array that can be used to query
- QGuiApplication::platformFunction to retrieve the RequestSystemTrayWindowDock function.
-*/
-
-/*!
- \fn bool QXcbWindowFunctions::requestSystemTrayWindowDock(const QWindow *window)
-
- This is a convenience function that can be used directly instead
- of resolving the function pointer. \a window will be
- relayed to the function retrieved by QGuiApplication.
-
- Returns the boolean result of calling the function or false if the
- function was not found.
-*/
-
-/*!
- \typedef QXcbWindowFunctions::SystemTrayWindowGlobalGeometry
-
- This is the typedef for the function returned by
- QGuiApplication::platformFunction when passed the
- value returned by systemTrayWindowGlobalGeometryIdentifier().
-*/
-
-/*!
- \fn const QByteArray QXcbWindowFunctions::systemTrayWindowGlobalGeometryIdentifier()
-
- This function returns the byte array that can be used to query
- QGuiApplication::platformFunction to retrieve the SystemTrayWindowGlobalGeometry function.
-*/
-
-/*!
- \fn QRect QXcbWindowFunctions::systemTrayWindowGlobalGeometry(const QWindow *window)
-
- This is a convenience function that can be used directly instead
- of resolving the function pointer. \a window will be
- relayed to the function retrieved by QGuiApplication.
-
- Returns the QRect result of calling the function or an empty
- QRect if the function was not found.
-*/
-
-/*!
\typedef QXcbWindowFunctions::VisualId
This is the typedef for the function returned by
diff --git a/src/platformheaders/xcbfunctions/xcbfunctions.pri b/src/platformheaders/xcbfunctions/xcbfunctions.pri
index 3f2bcb2b34..3fbee53854 100644
--- a/src/platformheaders/xcbfunctions/xcbfunctions.pri
+++ b/src/platformheaders/xcbfunctions/xcbfunctions.pri
@@ -1,4 +1,3 @@
HEADERS += \
$$PWD/qxcbwindowfunctions.h \
- $$PWD/qxcbintegrationfunctions.h \
$$PWD/qxcbscreenfunctions.h
diff --git a/src/platformsupport/clipboard/qmacmime.mm b/src/platformsupport/clipboard/qmacmime.mm
index 09901ba0a5..caa2ccc6e5 100644
--- a/src/platformsupport/clipboard/qmacmime.mm
+++ b/src/platformsupport/clipboard/qmacmime.mm
@@ -536,13 +536,13 @@ QVariant QMacPasteboardMimeRtfText::convertToMime(const QString &mimeType, QList
// Read RTF into to NSAttributedString, then convert the string to HTML
NSAttributedString *string = [[NSAttributedString alloc] initWithData:data.at(0).toNSData()
- options:[NSDictionary dictionaryWithObject:NSRTFTextDocumentType forKey:NSDocumentTypeDocumentAttribute]
+ options:@{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType}
documentAttributes:nil
error:nil];
NSError *error;
NSRange range = NSMakeRange(0, [string length]);
- NSDictionary *dict = [NSDictionary dictionaryWithObject:NSHTMLTextDocumentType forKey:NSDocumentTypeDocumentAttribute];
+ NSDictionary *dict = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType};
NSData *htmlData = [string dataFromRange:range documentAttributes:dict error:&error];
return QByteArray::fromNSData(htmlData);
}
@@ -554,13 +554,13 @@ QList<QByteArray> QMacPasteboardMimeRtfText::convertFromMime(const QString &mime
return ret;
NSAttributedString *string = [[NSAttributedString alloc] initWithData:data.toByteArray().toNSData()
- options:[NSDictionary dictionaryWithObject:NSHTMLTextDocumentType forKey:NSDocumentTypeDocumentAttribute]
+ options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType}
documentAttributes:nil
error:nil];
NSError *error;
NSRange range = NSMakeRange(0, [string length]);
- NSDictionary *dict = [NSDictionary dictionaryWithObject:NSRTFTextDocumentType forKey:NSDocumentTypeDocumentAttribute];
+ NSDictionary *dict = @{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType};
NSData *rtfData = [string dataFromRange:range documentAttributes:dict error:&error];
ret << QByteArray::fromNSData(rtfData);
return ret;
@@ -853,8 +853,8 @@ QList<QByteArray> QMacPasteboardMimeTiff::convertFromMime(const QString &mime, Q
QImage img = qvariant_cast<QImage>(variant);
NSDictionary *props = @{
- static_cast<NSString *>(kCGImagePropertyPixelWidth) : [NSNumber numberWithInt:img.width()],
- static_cast<NSString *>(kCGImagePropertyPixelHeight) : [NSNumber numberWithInt:img.height()]
+ static_cast<NSString *>(kCGImagePropertyPixelWidth): @(img.width()),
+ static_cast<NSString *>(kCGImagePropertyPixelHeight): @(img.height())
};
CGImageDestinationAddImage(imageDestination, qt_mac_toCGImage(img), static_cast<CFDictionaryRef>(props));
diff --git a/src/platformsupport/edid/qedidparser.cpp b/src/platformsupport/edid/qedidparser.cpp
index ccf12e9eb3..06c8852825 100644
--- a/src/platformsupport/edid/qedidparser.cpp
+++ b/src/platformsupport/edid/qedidparser.cpp
@@ -100,11 +100,11 @@ bool QEdidParser::parse(const QByteArray &blob)
* 7654321076543210
* |\---/\---/\---/
* R C1 C2 C3 */
- char id[3];
- id[0] = 'A' + ((data[EDID_OFFSET_PNP_ID] & 0x7c) / 4) - 1;
- id[1] = 'A' + ((data[EDID_OFFSET_PNP_ID] & 0x3) * 8) + ((data[EDID_OFFSET_PNP_ID + 1] & 0xe0) / 32) - 1;
- id[2] = 'A' + (data[EDID_OFFSET_PNP_ID + 1] & 0x1f) - 1;
- identifier = QString::fromLatin1(id, 3);
+ char pnpId[3];
+ pnpId[0] = 'A' + ((data[EDID_OFFSET_PNP_ID] & 0x7c) / 4) - 1;
+ pnpId[1] = 'A' + ((data[EDID_OFFSET_PNP_ID] & 0x3) * 8) + ((data[EDID_OFFSET_PNP_ID + 1] & 0xe0) / 32) - 1;
+ pnpId[2] = 'A' + (data[EDID_OFFSET_PNP_ID + 1] & 0x1f) - 1;
+ QString pnpIdString = QString::fromLatin1(pnpId, 3);
// Clear manufacturer
manufacturer = QString();
@@ -136,12 +136,11 @@ bool QEdidParser::parse(const QByteArray &blob)
}
// Try to use cache first because it is potentially more updated
- if (m_vendorCache.contains(identifier)) {
- manufacturer = m_vendorCache[identifier];
- } else {
+ manufacturer = m_vendorCache.value(pnpIdString);
+ if (manufacturer.isEmpty()) {
// Find the manufacturer from the vendor lookup table
for (size_t i = 0; i < ARRAY_LENGTH(q_edidVendorTable); i++) {
- if (strcmp(q_edidVendorTable[i].id, identifier.toLatin1().constData()) == 0) {
+ if (strncmp(q_edidVendorTable[i].id, pnpId, 3) == 0) {
manufacturer = QString::fromUtf8(q_edidVendorTable[i].name);
break;
}
@@ -150,7 +149,7 @@ bool QEdidParser::parse(const QByteArray &blob)
// If we don't know the manufacturer, fallback to PNP ID
if (manufacturer.isEmpty())
- manufacturer = identifier;
+ manufacturer = pnpIdString;
// Physical size
physicalSize = QSizeF(data[EDID_PHYSICAL_WIDTH], data[EDID_OFFSET_PHYSICAL_HEIGHT]) * 10;
@@ -160,14 +159,14 @@ bool QEdidParser::parse(const QByteArray &blob)
QString QEdidParser::parseEdidString(const quint8 *data)
{
- QByteArray buffer(reinterpret_cast<const char *>(data), 12);
+ QByteArray buffer(reinterpret_cast<const char *>(data), 13);
// Erase carriage return and line feed
buffer = buffer.replace('\r', '\0').replace('\n', '\0');
// Replace non-printable characters with dash
for (int i = 0; i < buffer.count(); ++i) {
- if (buffer[i] < '\040' && buffer[i] > '\176')
+ if (buffer[i] < '\040' || buffer[i] > '\176')
buffer[i] = '-';
}
diff --git a/src/platformsupport/edid/qedidvendortable_p.h b/src/platformsupport/edid/qedidvendortable_p.h
index 6ec399df05..5768dbe992 100644
--- a/src/platformsupport/edid/qedidvendortable_p.h
+++ b/src/platformsupport/edid/qedidvendortable_p.h
@@ -38,9 +38,9 @@
****************************************************************************/
/*
- * This lookup table was generated from https://git.fedorahosted.org/cgit/hwdata.git/plain/pnp.ids
+ * This lookup table was generated from https://github.com/vcrhonek/hwdata/raw/master/pnp.ids
*
- * Do not change directly this file, instead edit the
+ * Do not change this file directly, instead edit the
* qtbase/util/edid/qedidvendortable.py script and regenerate this file.
*/
@@ -66,2240 +66,2240 @@ typedef struct VendorTable {
} VendorTable;
static const struct VendorTable q_edidVendorTable[] = {
- { "LLL", "L-3 Communications" },
- { "GMX", "GMX Inc" },
- { "FOS", "Foss Tecator" },
- { "PHI", "DO NOT USE - PHI" },
- { "DNV", "DiCon" },
- { "KZN", "K-Zone International" },
- { "TIC", "Trigem KinfoComm" },
- { "FNC", "Fanuc LTD" },
- { "ESY", "E-Systems Inc" },
- { "TGM", "TriGem Computer,Inc." },
- { "DBN", "DB Networks Inc" },
- { "GCS", "Grey Cell Systems Ltd" },
- { "AVR", "AVer Information Inc." },
- { "OKI", "OKI Electric Industrial Company Ltd" },
- { "GDI", "G. Diehl ISDN GmbH" },
- { "SPC", "SpinCore Technologies, Inc" },
- { "ICV", "Inside Contactless" },
- { "UNY", "Unicate" },
- { "NMP", "Nokia Mobile Phones" },
- { "HMC", "Hualon Microelectric Corporation" },
- { "OPT", "OPTi Inc" },
- { "TSG", "The Software Group Ltd" },
- { "IMN", "Impossible Production" },
- { "DHQ", "Quadram" },
- { "UFG", "UNIGRAF-USA" },
- { "CLA", "Clarion Company Ltd" },
- { "IOM", "Iomega" },
- { "MTS", "Multi-Tech Systems" },
- { "TXN", "Texas Insturments" },
- { "SDH", "Communications Specialies, Inc." },
- { "DCC", "Dale Computer Corporation" },
- { "PAK", "Many CNC System Co., Ltd." },
- { "TDC", "Teradici" },
- { "XAC", "XAC Automation Corp" },
- { "DRI", "Data Race Inc" },
- { "HAN", "Hanchang System Corporation" },
- { "NTR", "N-trig Innovative Technologies, Inc." },
- { "PDR", "Pure Data Inc" },
- { "BNS", "Boulder Nonlinear Systems" },
- { "EGO", "Ergo Electronics" },
- { "ETS", "Electronic Trade Solutions Ltd" },
- { "CNN", "Canon Inc" },
- { "CSB", "Transtex SA" },
- { "NAK", "Nakano Engineering Co.,Ltd." },
- { "IME", "Imagraph" },
- { "CYT", "Cytechinfo Inc" },
+ { "AAA", "Avolites Ltd" },
+ { "AAE", "Anatek Electronics Inc." },
+ { "AAT", "Ann Arbor Technologies" },
+ { "ABA", "ABBAHOME INC." },
+ { "ABC", "AboCom System Inc" },
+ { "ABD", "Allen Bradley Company" },
+ { "ABE", "Alcatel Bell" },
+ { "ABO", "D-Link Systems Inc" },
+ { "ABT", "Anchor Bay Technologies, Inc." },
+ { "ABV", "Advanced Research Technology" },
+ { "ACA", "Ariel Corporation" },
+ { "ACB", "Aculab Ltd" },
+ { "ACC", "Accton Technology Corporation" },
+ { "ACD", "AWETA BV" },
+ { "ACE", "Actek Engineering Pty Ltd" },
+ { "ACG", "A&R Cambridge Ltd" },
+ { "ACH", "Archtek Telecom Corporation" },
+ { "ACI", "Ancor Communications Inc" },
+ { "ACK", "Acksys" },
+ { "ACL", "Apricot Computers" },
+ { "ACM", "Acroloop Motion Control Systems Inc" },
+ { "ACO", "Allion Computer Inc." },
+ { "ACP", "Aspen Tech Inc" },
+ { "ACR", "Acer Technologies" },
+ { "ACS", "Altos Computer Systems" },
+ { "ACT", "Applied Creative Technology" },
+ { "ACU", "Acculogic" },
+ { "ACV", "ActivCard S.A" },
+ { "ADA", "Addi-Data GmbH" },
+ { "ADB", "Aldebbaron" },
+ { "ADC", "Acnhor Datacomm" },
+ { "ADD", "Advanced Peripheral Devices Inc" },
+ { "ADE", "Arithmos, Inc." },
+ { "ADH", "Aerodata Holdings Ltd" },
+ { "ADI", "ADI Systems Inc" },
+ { "ADK", "Adtek System Science Company Ltd" },
+ { "ADL", "ASTRA Security Products Ltd" },
{ "ADM", "Ad Lib MultiMedia Inc" },
- { "IBC", "Integrated Business Systems" },
- { "TMT", "T-Metrics Inc." },
+ { "ADN", "Analog & Digital Devices Tel. Inc" },
+ { "ADP", "Adaptec Inc" },
+ { "ADR", "Nasa Ames Research Center" },
+ { "ADS", "Analog Devices Inc" },
+ { "ADT", "Aved Display Technologies" },
+ { "ADV", "Advanced Micro Devices Inc" },
+ { "ADX", "Adax Inc" },
+ { "AEC", "Antex Electronics Corporation" },
+ { "AED", "Advanced Electronic Designs, Inc." },
+ { "AEI", "Actiontec Electric Inc" },
+ { "AEJ", "Alpha Electronics Company" },
+ { "AEM", "ASEM S.p.A." },
+ { "AEN", "Avencall" },
+ { "AEP", "Aetas Peripheral International" },
+ { "AET", "Aethra Telecomunicazioni S.r.l." },
+ { "AFA", "Alfa Inc" },
+ { "AGC", "Beijing Aerospace Golden Card Electronic Engineering Co.,Ltd." },
+ { "AGI", "Artish Graphics Inc" },
+ { "AGL", "Argolis" },
+ { "AGM", "Advan Int'l Corporation" },
+ { "AGT", "Agilent Technologies" },
+ { "AHC", "Advantech Co., Ltd." },
+ { "AIC", "Arnos Insturments & Computer Systems" },
+ { "AIE", "Altmann Industrieelektronik" },
+ { "AII", "Amptron International Inc." },
+ { "AIL", "Altos India Ltd" },
+ { "AIM", "AIMS Lab Inc" },
+ { "AIR", "Advanced Integ. Research Inc" },
+ { "AIS", "Alien Internet Services" },
+ { "AIW", "Aiwa Company Ltd" },
+ { "AIX", "ALTINEX, INC." },
+ { "AJA", "AJA Video Systems, Inc." },
+ { "AKB", "Akebia Ltd" },
+ { "AKE", "AKAMI Electric Co.,Ltd" },
+ { "AKI", "AKIA Corporation" },
+ { "AKL", "AMiT Ltd" },
+ { "AKM", "Asahi Kasei Microsystems Company Ltd" },
+ { "AKP", "Atom Komplex Prylad" },
+ { "AKY", "Askey Computer Corporation" },
+ { "ALA", "Alacron Inc" },
+ { "ALC", "Altec Corporation" },
+ { "ALD", "In4S Inc" },
+ { "ALG", "Realtek Semiconductor Corp." },
+ { "ALH", "AL Systems" },
+ { "ALI", "Acer Labs" },
+ { "ALJ", "Altec Lansing" },
+ { "ALK", "Acrolink Inc" },
+ { "ALL", "Alliance Semiconductor Corporation" },
+ { "ALM", "Acutec Ltd." },
+ { "ALN", "Alana Technologies" },
+ { "ALO", "Algolith Inc." },
{ "ALP", "Alps Electric Company Ltd" },
- { "TWX", "TEKWorx Limited" },
- { "CDP", "CalComp" },
- { "KSX", "King Tester Corporation" },
+ { "ALR", "Advanced Logic" },
+ { "ALS", "Texas Advanced optoelectronics Solutions, Inc" },
+ { "ALT", "Altra" },
+ { "ALV", "AlphaView LCD" },
+ { "ALX", "ALEXON Co.,Ltd." },
+ { "AMA", "Asia Microelectronic Development Inc" },
+ { "AMB", "Ambient Technologies, Inc." },
+ { "AMC", "Attachmate Corporation" },
+ { "AMD", "Amdek Corporation" },
{ "AMI", "American Megatrends Inc" },
- { "KBI", "Kidboard Inc" },
- { "COO", "coolux GmbH" },
- { "CBR", "Cebra Tech A/S" },
+ { "AML", "Anderson Multimedia Communications (HK) Limited" },
+ { "AMN", "Amimon LTD." },
+ { "AMO", "Amino Technologies PLC and Amino Communications Limited" },
+ { "AMP", "AMP Inc" },
+ { "AMS", "ARMSTEL, Inc." },
+ { "AMT", "AMT International Industry" },
+ { "AMX", "AMX LLC" },
{ "ANA", "Anakron" },
- { "ACT", "Applied Creative Technology" },
- { "PGS", "Princeton Graphic Systems" },
- { "DCL", "Dynamic Controls Ltd" },
- { "TCH", "Interaction Systems, Inc" },
- { "STP", "StreamPlay Ltd" },
- { "PCG", "First Industrial Computer Inc" },
- { "SSE", "Samsung Electronic Co." },
- { "TXT", "Textron Defense System" },
- { "XRO", "XORO ELECTRONICS (CHENGDU) LIMITED" },
- { "MTU", "Mark of the Unicorn Inc" },
- { "ERG", "Ergo System" },
- { "GFN", "Gefen Inc." },
- { "UNE", "Unisys Corporation" },
- { "DDD", "Danka Data Devices" },
- { "ZGT", "Zenith Data Systems" },
- { "NAL", "Network Alchemy" },
- { "FVX", "C-C-C Group Plc" },
- { "AJA", "AJA Video Systems, Inc." },
+ { "ANC", "Ancot" },
+ { "AND", "Adtran Inc" },
+ { "ANI", "Anigma Inc" },
+ { "ANK", "Anko Electronic Company Ltd" },
+ { "ANL", "Analogix Semiconductor, Inc" },
+ { "ANO", "Anorad Corporation" },
+ { "ANP", "Andrew Network Production" },
+ { "ANR", "ANR Ltd" },
+ { "ANS", "Ansel Communication Company" },
+ { "ANT", "Ace CAD Enterprise Company Ltd" },
+ { "ANX", "Acer Netxus Inc" },
+ { "AOA", "AOpen Inc." },
+ { "AOE", "Advanced Optics Electronics, Inc." },
+ { "AOL", "America OnLine" },
+ { "AOT", "Alcatel" },
+ { "APC", "American Power Conversion" },
+ { "APD", "AppliAdata" },
+ { "APE", "Alpine Electronics, Inc." },
+ { "APG", "Horner Electric Inc" },
+ { "API", "A Plus Info Corporation" },
+ { "APL", "Aplicom Oy" },
+ { "APM", "Applied Memory Tech" },
+ { "APN", "Appian Tech Inc" },
+ { "APP", "Apple Computer Inc" },
+ { "APR", "Aprilia s.p.a." },
+ { "APS", "Autologic Inc" },
+ { "APT", "Audio Processing Technology Ltd" },
+ { "APV", "A+V Link" },
+ { "APX", "AP Designs Ltd" },
+ { "ARC", "Alta Research Corporation" },
+ { "ARE", "ICET S.p.A." },
+ { "ARG", "Argus Electronics Co., LTD" },
+ { "ARI", "Argosy Research Inc" },
+ { "ARK", "Ark Logic Inc" },
+ { "ARL", "Arlotto Comnet Inc" },
+ { "ARM", "Arima" },
+ { "ARO", "Poso International B.V." },
+ { "ARS", "Arescom Inc" },
+ { "ART", "Corion Industrial Corporation" },
+ { "ASC", "Ascom Strategic Technology Unit" },
+ { "ASD", "USC Information Sciences Institute" },
+ { "ASE", "AseV Display Labs" },
+ { "ASI", "Ahead Systems" },
+ { "ASK", "Ask A/S" },
+ { "ASL", "AccuScene Corporation Ltd" },
+ { "ASM", "ASEM S.p.A." },
+ { "ASN", "Asante Tech Inc" },
+ { "ASP", "ASP Microelectronics Ltd" },
+ { "AST", "AST Research Inc" },
+ { "ASU", "Asuscom Network Inc" },
+ { "ASX", "AudioScience" },
+ { "ASY", "Rockwell Collins / Airshow Systems" },
+ { "ATA", "Allied Telesyn International (Asia) Pte Ltd" },
+ { "ATC", "Ably-Tech Corporation" },
+ { "ATD", "Alpha Telecom Inc" },
+ { "ATE", "Innovate Ltd" },
+ { "ATH", "Athena Informatica S.R.L." },
+ { "ATI", "Allied Telesis KK" },
+ { "ATK", "Allied Telesyn Int'l" },
+ { "ATL", "Arcus Technology Ltd" },
+ { "ATM", "ATM Ltd" },
+ { "ATN", "Athena Smartcard Solutions Ltd." },
+ { "ATO", "ASTRO DESIGN, INC." },
+ { "ATP", "Alpha-Top Corporation" },
+ { "ATT", "AT&T" },
+ { "ATV", "Office Depot, Inc." },
+ { "ATX", "Athenix Corporation" },
+ { "AUI", "Alps Electric Inc" },
+ { "AUO", "AU Optronics" },
+ { "AUR", "Aureal Semiconductor" },
+ { "AUT", "Autotime Corporation" },
+ { "AVA", "Avaya Communication" },
+ { "AVC", "Auravision Corporation" },
+ { "AVD", "Avid Electronics Corporation" },
+ { "AVE", "Add Value Enterpises (Asia) Pte Ltd" },
+ { "AVI", "Nippon Avionics Co.,Ltd" },
+ { "AVL", "Avalue Technology Inc." },
+ { "AVM", "AVM GmbH" },
+ { "AVN", "Advance Computer Corporation" },
+ { "AVO", "Avocent Corporation" },
+ { "AVR", "AVer Information Inc." },
+ { "AVT", "Avtek (Electronics) Pty Ltd" },
+ { "AVV", "SBS Technologies (Canada), Inc. (was Avvida Systems, Inc.)" },
+ { "AVX", "AVerMedia Technologies, Inc." },
+ { "AWC", "Access Works Comm Inc" },
+ { "AWL", "Aironet Wireless Communications, Inc" },
+ { "AWS", "Wave Systems" },
+ { "AXB", "Adrienne Electronics Corporation" },
+ { "AXC", "AXIOMTEK CO., LTD." },
+ { "AXE", "D-Link Systems Inc" },
+ { "AXI", "American Magnetics" },
+ { "AXL", "Axel" },
+ { "AXO", "Axonic Labs LLC" },
+ { "AXP", "American Express" },
+ { "AXT", "Axtend Technologies Inc" },
+ { "AXX", "Axxon Computer Corporation" },
+ { "AXY", "AXYZ Automation Services, Inc" },
+ { "AYD", "Aydin Displays" },
+ { "AYR", "Airlib, Inc" },
+ { "AZM", "AZ Middelheim - Radiotherapy" },
{ "AZT", "Aztech Systems Ltd" },
- { "CIS", "Cisco Systems Inc" },
- { "DUA", "Dosch & Amand GmbH & Company KG" },
- { "INP", "Interphase Corporation" },
- { "DMS", "DOME imaging systems" },
- { "COW", "Polycow Productions" },
- { "PTC", "PS Technology Corporation" },
- { "PRD", "Praim S.R.L." },
- { "DEC", "Digital Equipment Corporation" },
- { "SMT", "Silcom Manufacturing Tech Inc" },
- { "MII", "Mitec Inc" },
- { "QLC", "Q-Logic" },
- { "PRG", "The Phoenix Research Group Inc" },
- { "LNV", "Lenovo" },
- { "IND", "ILC" },
- { "MXL", "Hitachi Maxell, Ltd." },
- { "DAU", "Daou Tech Inc" },
- { "SNK", "S&K Electronics" },
- { "SYE", "SY Electronics Ltd" },
+ { "BAC", "Biometric Access Corporation" },
+ { "BAN", "Banyan" },
+ { "BBB", "an-najah university" },
+ { "BBH", "B&Bh" },
+ { "BBL", "Brain Boxes Limited" },
{ "BCC", "Beaver Computer Corporaton" },
- { "LPI", "Design Technology" },
- { "CLO", "Clone Computers" },
- { "CMI", "C-Media Electronics" },
- { "ESK", "ES&S" },
- { "HCW", "Hauppauge Computer Works Inc" },
- { "KPC", "King Phoenix Company" },
- { "DXS", "Signet" },
- { "OLY", "OLYMPUS CORPORATION" },
- { "OOS", "OSRAM" },
- { "NOE", "NordicEye AB" },
- { "DXP", "Data Expert Corporation" },
- { "ITP", "IT-PRO Consulting und Systemhaus GmbH" },
- { "MMS", "MMS Electronics" },
- { "FDC", "Future Domain" },
- { "ASM", "ASEM S.p.A." },
- { "AIC", "Arnos Insturments & Computer Systems" },
- { "ANC", "Ancot" },
- { "SEE", "SeeColor Corporation" },
- { "JAS", "Janz Automationssysteme AG" },
- { "TGV", "Grass Valley Germany GmbH" },
- { "LTI", "Jongshine Tech Inc" },
- { "JVC", "JVC" },
- { "TLV", "S3 Inc" },
- { "MGC", "Mentor Graphics Corporation" },
- { "NBS", "National Key Lab. on ISN" },
- { "GTI", "Goldtouch" },
- { "SPI", "SPACE-I Co., Ltd." },
- { "ZNX", "Znyx Adv. Systems" },
- { "EMC", "eMicro Corporation" },
- { "WDE", "Westinghouse Digital Electronics" },
- { "CEN", "Centurion Technologies P/L" },
+ { "BCD", "Barco GmbH" },
+ { "BCM", "Broadcom" },
+ { "BCQ", "Deutsche Telekom Berkom GmbH" },
+ { "BCS", "Booria CAD/CAM systems" },
+ { "BDO", "Brahler ICS" },
+ { "BDR", "Blonder Tongue Labs, Inc." },
+ { "BDS", "Barco Display Systems" },
+ { "BEC", "Elektro Beckhoff GmbH" },
+ { "BEI", "Beckworth Enterprises Inc" },
+ { "BEK", "Beko Elektronik A.S." },
+ { "BEL", "Beltronic Industrieelektronik GmbH" },
+ { "BEO", "Baug & Olufsen" },
{ "BFE", "B.F. Engineering Corporation" },
- { "DTL", "e-Net Inc" },
- { "FTL", "FUJITSU TEN LIMITED" },
- { "HSC", "Hagiwara Sys-Com Company Ltd" },
- { "ECP", "Elecom Company Ltd" },
- { "LJX", "Datalogic Corporation" },
- { "DRC", "Data Ray Corp." },
- { "STM", "SGS Thomson Microelectronics" },
- { "GDT", "Vortex Computersysteme GmbH" },
- { "JSK", "SANKEN ELECTRIC CO., LTD" },
- { "TMC", "Techmedia Computer Systems Corporation" },
- { "CFG", "Atlantis" },
- { "DCO", "Dialogue Technology Corporation" },
- { "NEC", "NEC Corporation" },
- { "SAE", "Saab Aerotech" },
- { "STA", "ST Electronics Systems Assembly Pte Ltd" },
- { "GEO", "GEO Sense" },
- { "SLH", "Silicon Library Inc." },
- { "SAG", "Sedlbauer" },
- { "VEK", "Vektrex" },
- { "ADA", "Addi-Data GmbH" },
- { "NCT", "NEC CustomTechnica, Ltd." },
- { "STX", "ST-Ericsson" },
- { "PRM", "Prometheus" },
- { "DPA", "DigiTalk Pro AV" },
- { "SLF", "StarLeaf" },
- { "AXY", "AXYZ Automation Services, Inc" },
- { "CPX", "Powermatic Data Systems" },
- { "DLL", "Dell Inc" },
- { "PLF", "Panasonic Avionics Corporation" },
- { "FRI", "Fibernet Research Inc" },
- { "BRM", "Braemar Inc" },
- { "MSK", "Megasoft Inc" },
- { "ECT", "Enciris Technologies" },
- { "TKO", "TouchKo, Inc." },
- { "CYC", "Cylink Corporation" },
- { "SMR", "B.& V. s.r.l." },
- { "SRT", "SeeReal Technologies GmbH" },
- { "GES", "GES Singapore Pte Ltd" },
- { "DHT", "Projectavision Inc" },
- { "ESC", "Eden Sistemas de Computacao S/A" },
- { "BYD", "byd:sign corporation" },
+ { "BGB", "Barco Graphics N.V" },
+ { "BGT", "Budzetron Inc" },
+ { "BHZ", "BitHeadz, Inc." },
+ { "BIC", "Big Island Communications" },
+ { "BII", "Boeckeler Instruments Inc" },
+ { "BIL", "Billion Electric Company Ltd" },
+ { "BIO", "BioLink Technologies International, Inc." },
+ { "BIT", "Bit 3 Computer" },
+ { "BLI", "Busicom" },
+ { "BLN", "BioLink Technologies" },
+ { "BLP", "Bloomberg L.P." },
+ { "BMD", "Blackmagic Design" },
{ "BMI", "Benson Medical Instruments Company" },
- { "XSY", "XSYS" },
- { "MYX", "Micronyx Inc" },
- { "OUK", "OUK Company Ltd" },
- { "MPI", "Mediatrix Peripherals Inc" },
+ { "BML", "BIOMED Lab" },
+ { "BMS", "BIOMEDISYS" },
+ { "BNE", "Bull AB" },
+ { "BNK", "Banksia Tech Pty Ltd" },
+ { "BNO", "Bang & Olufsen" },
+ { "BNS", "Boulder Nonlinear Systems" },
+ { "BOB", "Rainy Orchard" },
+ { "BOE", "BOE" },
+ { "BOI", "NINGBO BOIGLE DIGITAL TECHNOLOGY CO.,LTD" },
+ { "BOS", "BOS" },
+ { "BPD", "Micro Solutions, Inc." },
+ { "BPU", "Best Power" },
+ { "BRA", "Braemac Pty Ltd" },
+ { "BRC", "BARC" },
+ { "BRG", "Bridge Information Co., Ltd" },
+ { "BRI", "Boca Research Inc" },
+ { "BRM", "Braemar Inc" },
+ { "BRO", "BROTHER INDUSTRIES,LTD." },
+ { "BSE", "Bose Corporation" },
+ { "BSL", "Biomedical Systems Laboratory" },
+ { "BSN", "BRIGHTSIGN, LLC" },
+ { "BST", "BodySound Technologies, Inc." },
+ { "BTC", "Bit 3 Computer" },
+ { "BTE", "Brilliant Technology" },
+ { "BTF", "Bitfield Oy" },
+ { "BTI", "BusTech Inc" },
+ { "BTO", "BioTao Ltd" },
+ { "BUF", "Yasuhiko Shirai Melco Inc" },
+ { "BUG", "B.U.G., Inc." },
+ { "BUJ", "ATI Tech Inc" },
+ { "BUL", "Bull" },
+ { "BUR", "Bernecker & Rainer Ind-Eletronik GmbH" },
{ "BUS", "BusTek" },
- { "LCN", "LEXICON" },
- { "ADS", "Analog Devices Inc" },
- { "XTL", "Crystal Computer" },
- { "CEF", "Cefar Digital Vision" },
- { "IPP", "IP Power Technologies GmbH" },
- { "CDV", "Convergent Design Inc." },
- { "OLD", "Olidata S.p.A." },
- { "GNN", "GN Nettest Inc" },
- { "ADH", "Aerodata Holdings Ltd" },
- { "IMM", "Immersion Corporation" },
+ { "BUT", "21ST CENTURY ENTERTAINMENT" },
+ { "BWK", "Bitworks Inc." },
+ { "BXE", "Buxco Electronics" },
+ { "BYD", "byd:sign corporation" },
+ { "CAA", "Castles Automation Co., Ltd" },
+ { "CAC", "CA & F Elettronica" },
+ { "CAG", "CalComp" },
+ { "CAI", "Canon Inc." },
+ { "CAL", "Acon" },
+ { "CAM", "Cambridge Audio" },
+ { "CAN", "CORNEA" },
+ { "CAR", "Cardinal Company Ltd" },
+ { "CAS", "CASIO COMPUTER CO.,LTD" },
+ { "CAT", "Consultancy in Advanced Technology" },
+ { "CAV", "Cavium Networks, Inc" },
+ { "CBI", "ComputerBoards Inc" },
+ { "CBR", "Cebra Tech A/S" },
{ "CBT", "Cabletime Ltd" },
- { "RVI", "Realvision Inc" },
- { "HNS", "Hughes Network Systems" },
- { "HAR", "Harris Corporation" },
- { "ACV", "ActivCard S.A" },
- { "RUN", "RUNCO International" },
- { "WDC", "Western Digital" },
- { "SIG", "Sigma Designs Inc" },
- { "PNR", "Planar Systems, Inc." },
- { "PRS", "Leutron Vision" },
- { "KEM", "Kontron Embedded Modules GmbH" },
- { "LAN", "Sodeman Lancom Inc" },
+ { "CBX", "Cybex Computer Products Corporation" },
+ { "CCC", "C-Cube Microsystems" },
+ { "CCI", "Cache" },
+ { "CCJ", "CONTEC CO.,LTD." },
+ { "CCL", "CCL/ITRI" },
+ { "CCP", "Capetronic USA Inc" },
+ { "CDC", "Core Dynamics Corporation" },
+ { "CDD", "Convergent Data Devices" },
+ { "CDE", "Colin.de" },
+ { "CDG", "Christie Digital Systems Inc" },
+ { "CDI", "Concept Development Inc" },
+ { "CDK", "Cray Communications" },
+ { "CDN", "Codenoll Technical Corporation" },
+ { "CDP", "CalComp" },
+ { "CDS", "Computer Diagnostic Systems" },
+ { "CDT", "IBM Corporation" },
+ { "CDV", "Convergent Design Inc." },
+ { "CEA", "Consumer Electronics Association" },
+ { "CEC", "Chicony Electronics Company Ltd" },
+ { "CED", "Cambridge Electronic Design Ltd" },
+ { "CEF", "Cefar Digital Vision" },
+ { "CEI", "Crestron Electronics, Inc." },
{ "CEM", "MEC Electronics GmbH" },
- { "RHD", "RightHand Technologies" },
+ { "CEN", "Centurion Technologies P/L" },
+ { "CEP", "C-DAC" },
+ { "CER", "Ceronix" },
+ { "CET", "TEC CORPORATION" },
+ { "CFG", "Atlantis" },
+ { "CGA", "Chunghwa Picture Tubes, LTD" },
+ { "CGS", "Chyron Corp" },
+ { "CGT", "congatec AG" },
+ { "CHA", "Chase Research PLC" },
+ { "CHC", "Chic Technology Corp." },
+ { "CHD", "ChangHong Electric Co.,Ltd" },
{ "CHE", "Acer Inc" },
- { "POL", "PolyComp (PTY) Ltd." },
- { "MST", "MS Telematica" },
- { "ALA", "Alacron Inc" },
- { "EDI", "Edimax Tech. Company Ltd" },
- { "EGN", "Egenera, Inc." },
- { "PIX", "Pixie Tech Inc" },
- { "AVN", "Advance Computer Corporation" },
- { "CTN", "Computone Products" },
- { "SFM", "TORNADO Company" },
- { "ATA", "Allied Telesyn International (Asia) Pte Ltd" },
- { "SIA", "SIEMENS AG" },
- { "NAV", "Navigation Corporation" },
- { "PRF", "Digital Electronics Corporation" },
- { "HRE", "Qingdao Haier Electronics Co., Ltd." },
- { "NAC", "Ncast Corporation" },
- { "ELM", "Elmic Systems Inc" },
- { "HYR", "Hypertec Pty Ltd" },
- { "EMB", "Embedded computing inc ltd" },
- { "MWR", "mware" },
- { "KGL", "KEISOKU GIKEN Co.,Ltd." },
- { "NRL", "U.S. Naval Research Lab" },
- { "TNM", "TECNIMAGEN SA" },
- { "GTT", "General Touch Technology Co., Ltd." },
- { "BTE", "Brilliant Technology" },
- { "KDS", "KDS USA" },
- { "EEP", "E.E.P.D. GmbH" },
- { "NCI", "NewCom Inc" },
+ { "CHG", "Sichuan Changhong Electric CO, LTD." },
+ { "CHI", "Chrontel Inc" },
+ { "CHL", "Chloride-R&D" },
+ { "CHM", "CHIC TECHNOLOGY CORP." },
+ { "CHO", "Sichuang Changhong Corporation" },
+ { "CHP", "CH Products" },
+ { "CHS", "Agentur Chairos" },
+ { "CHT", "Chunghwa Picture Tubes,LTD." },
+ { "CHY", "Cherry GmbH" },
+ { "CIC", "Comm. Intelligence Corporation" },
+ { "CII", "Cromack Industries Inc" },
+ { "CIL", "Citicom Infotech Private Limited" },
+ { "CIN", "Citron GmbH" },
{ "CIP", "Ciprico Inc" },
- { "RTL", "Realtek Semiconductor Company Ltd" },
- { "MUK", "mainpine limited" },
- { "SLX", "Specialix" },
- { "HCM", "HCL Peripherals" },
- { "CHA", "Chase Research PLC" },
- { "VOB", "MaxData Computer AG" },
- { "ANK", "Anko Electronic Company Ltd" },
- { "FWR", "Flat Connections Inc" },
- { "DXL", "Dextera Labs Inc" },
- { "QVU", "Quartics" },
- { "MPS", "mps Software GmbH" },
- { "AVM", "AVM GmbH" },
- { "TDY", "Tandy Electronics" },
- { "MJS", "MJS Designs" },
- { "SNC", "Sentronic International Corp." },
- { "IPT", "International Power Technologies" },
- { "API", "A Plus Info Corporation" },
- { "TLT", "Dai Telecom S.p.A." },
- { "PCC", "PowerCom Technology Company Ltd" },
- { "TRM", "Tekram Technology Company Ltd" },
- { "DEL", "Dell Inc." },
- { "CYW", "Cyberware" },
- { "TDS", "Tri-Data Systems Inc" },
- { "FPE", "Fujitsu Peripherals Ltd" },
- { "SPN", "Sapience Corporation" },
+ { "CIR", "Cirrus Logic Inc" },
+ { "CIS", "Cisco Systems Inc" },
+ { "CIT", "Citifax Limited" },
+ { "CKC", "The Concept Keyboard Company Ltd" },
+ { "CKJ", "Carina System Co., Ltd." },
+ { "CLA", "Clarion Company Ltd" },
+ { "CLD", "COMMAT L.t.d." },
+ { "CLE", "Classe Audio" },
+ { "CLG", "CoreLogic" },
+ { "CLI", "Cirrus Logic Inc" },
+ { "CLM", "CrystaLake Multimedia" },
+ { "CLO", "Clone Computers" },
+ { "CLT", "automated computer control systems" },
+ { "CLV", "Clevo Company" },
+ { "CLX", "CardLogix" },
+ { "CMC", "CMC Ltd" },
+ { "CMD", "Colorado MicroDisplay, Inc." },
+ { "CMG", "Chenming Mold Ind. Corp." },
+ { "CMI", "C-Media Electronics" },
+ { "CMM", "Comtime GmbH" },
+ { "CMN", "Chimei Innolux Corporation" },
+ { "CMO", "Chi Mei Optoelectronics corp." },
+ { "CMR", "Cambridge Research Systems Ltd" },
+ { "CMS", "CompuMaster Srl" },
+ { "CMX", "Comex Electronics AB" },
+ { "CNB", "American Power Conversion" },
+ { "CNC", "Alvedon Computers Ltd" },
+ { "CNE", "Cine-tal" },
+ { "CNI", "Connect Int'l A/S" },
+ { "CNN", "Canon Inc" },
+ { "CNT", "COINT Multimedia Systems" },
+ { "COB", "COBY Electronics Co., Ltd" },
+ { "COD", "CODAN Pty. Ltd." },
+ { "COI", "Codec Inc." },
+ { "COL", "Rockwell Collins, Inc." },
+ { "COM", "Comtrol Corporation" },
+ { "CON", "Contec Company Ltd" },
+ { "COO", "coolux GmbH" },
+ { "COR", "Corollary Inc" },
+ { "COS", "CoStar Corporation" },
+ { "COT", "Core Technology Inc" },
+ { "COW", "Polycow Productions" },
{ "COX", "Comrex" },
- { "STE", "SII Ido-Tsushin Inc" },
- { "RVC", "RSI Systems Inc" },
- { "HMK", "hmk Daten-System-Technik BmbH" },
- { "TTA", "Topson Technology Co., Ltd." },
+ { "CPC", "Ciprico Inc" },
+ { "CPD", "CompuAdd" },
+ { "CPI", "Computer Peripherals Inc" },
+ { "CPL", "Compal Electronics Inc" },
+ { "CPM", "Capella Microsystems Inc." },
+ { "CPQ", "Compaq Computer Company" },
+ { "CPT", "cPATH" },
+ { "CPX", "Powermatic Data Systems" },
+ { "CRC", "CONRAC GmbH" },
+ { "CRD", "Cardinal Technical Inc" },
+ { "CRE", "Creative Labs Inc" },
+ { "CRI", "Crio Inc." },
+ { "CRL", "Creative Logic" },
+ { "CRN", "Cornerstone Imaging" },
+ { "CRO", "Extraordinary Technologies PTY Limited" },
+ { "CRQ", "Cirque Corporation" },
+ { "CRS", "Crescendo Communication Inc" },
+ { "CRV", "Cerevo Inc." },
+ { "CRX", "Cyrix Corporation" },
+ { "CSB", "Transtex SA" },
+ { "CSC", "Crystal Semiconductor" },
+ { "CSD", "Cresta Systems Inc" },
+ { "CSE", "Concept Solutions & Engineering" },
+ { "CSI", "Cabletron System Inc" },
{ "CSM", "Cosmic Engineering Inc." },
- { "PTL", "Pantel Inc" },
- { "EQX", "Equinox Systems Inc" },
- { "HEL", "Hitachi Micro Systems Europe Ltd" },
- { "TIX", "Tixi.Com GmbH" },
- { "CMD", "Colorado MicroDisplay, Inc." },
- { "VIS", "Visioneer" },
- { "MTH", "Micro-Tech Hearing Instruments" },
- { "ISR", "INSIS Co., LTD." },
- { "EME", "EMiNE TECHNOLOGY COMPANY, LTD." },
- { "DMT", "Distributed Management Task Force, Inc. (DMTF)" },
- { "JFX", "Jones Futurex Inc" },
- { "SMB", "Schlumberger" },
- { "GTM", "Garnet System Company Ltd" },
+ { "CSO", "California Institute of Technology" },
+ { "CSS", "CSS Laboratories" },
+ { "CST", "CSTI Inc" },
+ { "CTA", "CoSystems Inc" },
+ { "CTC", "CTC Communication Development Company Ltd" },
+ { "CTE", "Chunghwa Telecom Co., Ltd." },
+ { "CTL", "Creative Technology Ltd" },
+ { "CTM", "Computerm Corporation" },
+ { "CTN", "Computone Products" },
+ { "CTP", "Computer Technology Corporation" },
+ { "CTS", "Comtec Systems Co., Ltd." },
+ { "CTX", "Creatix Polymedia GmbH" },
+ { "CUB", "Cubix Corporation" },
+ { "CUK", "Calibre UK Ltd" },
+ { "CVA", "Covia Inc." },
+ { "CVI", "Colorado Video, Inc." },
+ { "CVS", "Clarity Visual Systems" },
+ { "CWR", "Connectware Inc" },
+ { "CXT", "Conexant Systems" },
+ { "CYB", "CyberVision" },
+ { "CYC", "Cylink Corporation" },
+ { "CYD", "Cyclades Corporation" },
+ { "CYL", "Cyberlabs" },
+ { "CYT", "Cytechinfo Inc" },
+ { "CYV", "Cyviz AS" },
+ { "CYW", "Cyberware" },
+ { "CYX", "Cyrix Corporation" },
+ { "CZE", "Carl Zeiss AG" },
+ { "DAC", "Digital Acoustics Corporation" },
+ { "DAE", "Digatron Industrie Elektronik GmbH" },
+ { "DAI", "DAIS SET Ltd." },
+ { "DAK", "Daktronics" },
+ { "DAL", "Digital Audio Labs Inc" },
+ { "DAN", "Danelec Marine A/S" },
+ { "DAS", "DAVIS AS" },
+ { "DAT", "Datel Inc" },
+ { "DAU", "Daou Tech Inc" },
+ { "DAV", "Davicom Semiconductor Inc" },
+ { "DAW", "DA2 Technologies Inc" },
+ { "DAX", "Data Apex Ltd" },
+ { "DBD", "Diebold Inc." },
+ { "DBI", "DigiBoard Inc" },
{ "DBK", "Databook Inc" },
- { "IQT", "IMAGEQUEST Co., Ltd" },
+ { "DBL", "Doble Engineering Company" },
+ { "DBN", "DB Networks Inc" },
+ { "DCA", "Digital Communications Association" },
+ { "DCC", "Dale Computer Corporation" },
+ { "DCD", "Datacast LLC" },
+ { "DCE", "dSPACE GmbH" },
+ { "DCI", "Concepts Inc" },
+ { "DCL", "Dynamic Controls Ltd" },
+ { "DCM", "DCM Data Products" },
+ { "DCO", "Dialogue Technology Corporation" },
+ { "DCR", "Decros Ltd" },
+ { "DCS", "Diamond Computer Systems Inc" },
+ { "DCT", "Dancall Telecom A/S" },
+ { "DCV", "Datatronics Technology Inc" },
+ { "DDA", "DA2 Technologies Corporation" },
+ { "DDD", "Danka Data Devices" },
+ { "DDE", "Datasat Digital Entertainment" },
+ { "DDI", "Data Display AG" },
+ { "DDS", "Barco, n.v." },
+ { "DDT", "Datadesk Technologies Inc" },
+ { "DDV", "Delta Information Systems, Inc" },
+ { "DEC", "Digital Equipment Corporation" },
+ { "DEI", "Deico Electronics" },
+ { "DEL", "Dell Inc." },
+ { "DEN", "Densitron Computers Ltd" },
+ { "DEX", "idex displays" },
+ { "DFI", "DFI" },
+ { "DFK", "SharkTec A/S" },
+ { "DFT", "DEI Holdings dba Definitive Technology" },
+ { "DGA", "Digiital Arts Inc" },
+ { "DGC", "Data General Corporation" },
+ { "DGI", "DIGI International" },
+ { "DGK", "DugoTech Co., LTD" },
+ { "DGP", "Digicorp European sales S.A." },
+ { "DGS", "Diagsoft Inc" },
+ { "DGT", "The Dearborn Group" },
+ { "DHP", "DH Print" },
+ { "DHQ", "Quadram" },
+ { "DHT", "Projectavision Inc" },
+ { "DIA", "Diadem" },
+ { "DIG", "Digicom S.p.A." },
+ { "DII", "Dataq Instruments Inc" },
+ { "DIM", "dPict Imaging, Inc." },
+ { "DIN", "Daintelecom Co., Ltd" },
+ { "DIS", "Diseda S.A." },
+ { "DIT", "Dragon Information Technology" },
+ { "DJE", "Capstone Visual Product Development" },
+ { "DJP", "Maygay Machines, Ltd" },
+ { "DKY", "Datakey Inc" },
+ { "DLB", "Dolby Laboratories Inc." },
+ { "DLC", "Diamond Lane Comm. Corporation" },
+ { "DLG", "Digital-Logic GmbH" },
+ { "DLK", "D-Link Systems Inc" },
+ { "DLL", "Dell Inc" },
+ { "DLT", "Digitelec Informatique Park Cadera" },
+ { "DMB", "Digicom Systems Inc" },
+ { "DMC", "Dune Microsystems Corporation" },
+ { "DMM", "Dimond Multimedia Systems Inc" },
+ { "DMP", "D&M Holdings Inc, Professional Business Company" },
+ { "DMS", "DOME imaging systems" },
+ { "DMT", "Distributed Management Task Force, Inc. (DMTF)" },
+ { "DMV", "NDS Ltd" },
+ { "DNA", "DNA Enterprises, Inc." },
+ { "DNG", "Apache Micro Peripherals Inc" },
+ { "DNI", "Deterministic Networks Inc." },
+ { "DNT", "Dr. Neuhous Telekommunikation GmbH" },
+ { "DNV", "DiCon" },
+ { "DOL", "Dolman Technologies Group Inc" },
+ { "DOM", "Dome Imaging Systems" },
+ { "DON", "DENON, Ltd." },
+ { "DOT", "Dotronic Mikroelektronik GmbH" },
+ { "DPA", "DigiTalk Pro AV" },
+ { "DPC", "Delta Electronics Inc" },
+ { "DPI", "DocuPoint" },
+ { "DPL", "Digital Projection Limited" },
+ { "DPM", "ADPM Synthesis sas" },
+ { "DPS", "Digital Processing Systems" },
+ { "DPT", "DPT" },
+ { "DPX", "DpiX, Inc." },
+ { "DQB", "Datacube Inc" },
+ { "DRB", "Dr. Bott KG" },
+ { "DRC", "Data Ray Corp." },
+ { "DRD", "DIGITAL REFLECTION INC." },
+ { "DRI", "Data Race Inc" },
+ { "DRS", "DRS Defense Solutions, LLC" },
+ { "DSD", "DS Multimedia Pte Ltd" },
+ { "DSI", "Digitan Systems Inc" },
+ { "DSM", "DSM Digital Services GmbH" },
+ { "DSP", "Domain Technology Inc" },
+ { "DTA", "DELTATEC" },
+ { "DTC", "DTC Tech Corporation" },
+ { "DTE", "Dimension Technologies, Inc." },
+ { "DTI", "Diversified Technology, Inc." },
+ { "DTK", "Dynax Electronics (HK) Ltd" },
+ { "DTL", "e-Net Inc" },
+ { "DTN", "Datang Telephone Co" },
+ { "DTO", "Deutsche Thomson OHG" },
+ { "DTT", "Design & Test Technology, Inc." },
{ "DTX", "Data Translation" },
- { "QSI", "Quantum Solutions, Inc." },
- { "BEL", "Beltronic Industrieelektronik GmbH" },
- { "PJT", "Pan Jit International Inc." },
- { "WST", "Wistron Corporation" },
- { "ASN", "Asante Tech Inc" },
- { "ROS", "Rohde & Schwarz" },
- { "NWP", "NovaWeb Technologies Inc" },
- { "CLG", "CoreLogic" },
+ { "DUA", "Dosch & Amand GmbH & Company KG" },
+ { "DUN", "NCR Corporation" },
+ { "DVD", "Dictaphone Corporation" },
+ { "DVL", "Devolo AG" },
+ { "DVS", "Digital Video System" },
+ { "DVT", "Data Video" },
+ { "DWE", "Daewoo Electronics Company Ltd" },
+ { "DXC", "Digipronix Control Systems" },
+ { "DXD", "DECIMATOR DESIGN PTY LTD" },
+ { "DXL", "Dextera Labs Inc" },
+ { "DXP", "Data Expert Corporation" },
+ { "DXS", "Signet" },
+ { "DYC", "Dycam Inc" },
+ { "DYM", "Dymo-CoStar Corporation" },
+ { "DYN", "Askey Computer Corporation" },
+ { "DYX", "Dynax Electronics (HK) Ltd" },
+ { "EAS", "Evans and Sutherland Computer" },
+ { "EBH", "Data Price Informatica" },
+ { "EBT", "HUALONG TECHNOLOGY CO., LTD" },
+ { "ECA", "Electro Cam Corp." },
+ { "ECC", "ESSential Comm. Corporation" },
+ { "ECI", "Enciris Technologies" },
+ { "ECK", "Eugene Chukhlomin Sole Proprietorship, d.b.a." },
+ { "ECL", "Excel Company Ltd" },
+ { "ECM", "E-Cmos Tech Corporation" },
+ { "ECO", "Echo Speech Corporation" },
+ { "ECP", "Elecom Company Ltd" },
{ "ECS", "Elitegroup Computer Systems Company Ltd" },
- { "PER", "Perceptive Signal Technologies" },
- { "SPR", "pmns GmbH" },
- { "DLB", "Dolby Laboratories Inc." },
- { "SRF", "Surf Communication Solutions Ltd" },
- { "ATM", "ATM Ltd" },
- { "MED", "Messeltronik Dresden GmbH" },
- { "SGD", "Sigma Designs, Inc." },
- { "RJA", "Roland Corporation" },
+ { "ECT", "Enciris Technologies" },
{ "EDC", "e.Digital Corporation" },
- { "CON", "Contec Company Ltd" },
- { "CCJ", "CONTEC CO.,LTD." },
- { "GVC", "GVC Corporation" },
- { "TRI", "Tricord Systems" },
- { "SLB", "Shlumberger Ltd" },
- { "PRO", "Proteon" },
- { "DSI", "Digitan Systems Inc" },
- { "SDF", "SODIFF E&T CO., Ltd." },
- { "VDC", "VDC Display Systems" },
- { "PSL", "Perle Systems Limited" },
- { "SCR", "Systran Corporation" },
- { "DEX", "idex displays" },
- { "CDS", "Computer Diagnostic Systems" },
- { "RAY", "Raylar Design, Inc." },
- { "MMF", "Minnesota Mining and Manufacturing" },
- { "MMA", "Micromedia AG" },
- { "FUS", "Fujitsu Siemens Computers GmbH" },
+ { "EDG", "Electronic-Design GmbH" },
+ { "EDI", "Edimax Tech. Company Ltd" },
+ { "EDM", "EDMI" },
+ { "EDT", "Emerging Display Technologies Corp" },
+ { "EEE", "ET&T Technology Company Ltd" },
+ { "EEH", "EEH Datalink GmbH" },
+ { "EEP", "E.E.P.D. GmbH" },
+ { "EES", "EE Solutions, Inc." },
+ { "EGA", "Elgato Systems LLC" },
+ { "EGD", "EIZO GmbH Display Technologies" },
+ { "EGL", "Eagle Technology" },
+ { "EGN", "Egenera, Inc." },
+ { "EGO", "Ergo Electronics" },
+ { "EHJ", "Epson Research" },
+ { "EHN", "Enhansoft" },
+ { "EIC", "Eicon Technology Corporation" },
+ { "EKA", "MagTek Inc." },
+ { "EKC", "Eastman Kodak Company" },
+ { "EKS", "EKSEN YAZILIM" },
+ { "ELA", "ELAD srl" },
+ { "ELC", "Electro Scientific Ind" },
+ { "ELE", "Elecom Company Ltd" },
+ { "ELG", "Elmeg GmbH Kommunikationstechnik" },
+ { "ELI", "Edsun Laboratories" },
+ { "ELL", "Electrosonic Ltd" },
+ { "ELM", "Elmic Systems Inc" },
+ { "ELO", "Tyco Electronics" },
+ { "ELS", "ELSA GmbH" },
+ { "ELT", "Element Labs, Inc." },
+ { "ELX", "Elonex PLC" },
+ { "EMB", "Embedded computing inc ltd" },
+ { "EMC", "eMicro Corporation" },
+ { "EME", "EMiNE TECHNOLOGY COMPANY, LTD." },
+ { "EMG", "EMG Consultants Inc" },
+ { "EMI", "Ex Machina Inc" },
+ { "EMK", "Emcore Corporation" },
+ { "EMO", "ELMO COMPANY, LIMITED" },
+ { "EMU", "Emulex Corporation" },
+ { "ENC", "Eizo Nanao Corporation" },
+ { "END", "ENIDAN Technologies Ltd" },
+ { "ENE", "ENE Technology Inc." },
+ { "ENI", "Efficient Networks" },
+ { "ENS", "Ensoniq Corporation" },
+ { "ENT", "Enterprise Comm. & Computing Inc" },
+ { "EPC", "Empac" },
+ { "EPH", "Epiphan Systems Inc." },
+ { "EPI", "Envision Peripherals, Inc" },
+ { "EPN", "EPiCON Inc." },
+ { "EPS", "KEPS" },
+ { "EQP", "Equipe Electronics Ltd." },
+ { "EQX", "Equinox Systems Inc" },
+ { "ERG", "Ergo System" },
+ { "ERI", "Ericsson Mobile Communications AB" },
+ { "ERN", "Ericsson, Inc." },
+ { "ERP", "Euraplan GmbH" },
+ { "ERT", "Escort Insturments Corporation" },
+ { "ESA", "Elbit Systems of America" },
+ { "ESC", "Eden Sistemas de Computacao S/A" },
+ { "ESD", "Ensemble Designs, Inc" },
+ { "ESG", "ELCON Systemtechnik GmbH" },
+ { "ESI", "Extended Systems, Inc." },
+ { "ESK", "ES&S" },
+ { "ESL", "Esterline Technologies" },
+ { "ESN", "eSATURNUS" },
{ "ESS", "ESS Technology Inc" },
- { "SIX", "Zuniq Data Corporation" },
- { "ISS", "ISS Inc" },
- { "PFT", "Telia ProSoft AB" },
- { "SOL", "Solitron Technologies Inc" },
- { "ZTM", "ZT Group Int'l Inc." },
- { "GZE", "GUNZE Limited" },
- { "CHS", "Agentur Chairos" },
- { "CBI", "ComputerBoards Inc" },
- { "DTA", "DELTATEC" },
- { "CSC", "Crystal Semiconductor" },
- { "MPC", "M-Pact Inc" },
- { "HHI", "Fraunhofer Heinrich-Hertz-Institute" },
- { "BIT", "Bit 3 Computer" },
- { "ICP", "ICP Electronics, Inc./iEi Technology Corp." },
- { "FOA", "FOR-A Company Limited" },
- { "NWC", "NW Computer Engineering" },
- { "MRO", "Medikro Oy" },
- { "IDT", "International Display Technology" },
- { "NMV", "NEC-Mitsubishi Electric Visual Systems Corporation" },
- { "COT", "Core Technology Inc" },
- { "PEL", "Primax Electric Ltd" },
- { "ZMZ", "Z Microsystems" },
- { "TYN", "Tyan Computer Corporation" },
- { "DIN", "Daintelecom Co., Ltd" },
- { "QTH", "Questech Ltd" },
- { "CYL", "Cyberlabs" },
- { "DGC", "Data General Corporation" },
- { "PPM", "Clinton Electronics Corp." },
- { "ITD", "Internet Technology Corporation" },
- { "MMM", "Electronic Measurements" },
- { "CMM", "Comtime GmbH" },
- { "NDC", "National DataComm Corporaiton" },
- { "TAS", "Taskit Rechnertechnik GmbH" },
- { "MFR", "MediaFire Corp." },
- { "HIC", "Hitachi Information Technology Co., Ltd." },
- { "CMC", "CMC Ltd" },
- { "TSE", "Tottori Sanyo Electric" },
- { "TMR", "Taicom International Inc" },
- { "SIE", "Siemens" },
- { "IMD", "ImasDe Canarias S.A." },
- { "SCE", "Sun Corporation" },
- { "PJD", "Projectiondesign AS" },
- { "VML", "Vine Micros Limited" },
+ { "EST", "Embedded Solution Technology" },
+ { "ESY", "E-Systems Inc" },
+ { "ETC", "Everton Technology Company Ltd" },
+ { "ETD", "ELAN MICROELECTRONICS CORPORATION" },
+ { "ETH", "Etherboot Project" },
+ { "ETI", "Eclipse Tech Inc" },
+ { "ETK", "eTEK Labs Inc." },
{ "ETL", "Evertz Microsystems Ltd." },
- { "MAZ", "MAZeT GmbH" },
- { "UNC", "Unisys Corporation" },
- { "MEG", "Abeam Tech Ltd" },
- { "FCS", "Focus Enhancements, Inc." },
- { "MDV", "MET Development Inc" },
- { "GLD", "Goldmund - Digital Audio SA" },
- { "MRC", "Marconi Simulation & Ty-Coch Way Training" },
- { "FEC", "FURUNO ELECTRIC CO., LTD." },
- { "ALR", "Advanced Logic" },
- { "AEJ", "Alpha Electronics Company" },
- { "QCC", "QuakeCom Company Ltd" },
- { "TDK", "TDK USA Corporation" },
- { "TKN", "Teknor Microsystem Inc" },
- { "FMC", "Ford Microelectronics Inc" },
- { "KTI", "Konica Technical Inc" },
- { "AEI", "Actiontec Electric Inc" },
- { "TGI", "TriGem Computer Inc" },
- { "HIL", "Hilevel Technology" },
- { "WNI", "WillNet Inc." },
- { "FTI", "FastPoint Technologies, Inc." },
- { "ASU", "Asuscom Network Inc" },
- { "MEJ", "Mac-Eight Co., LTD." },
- { "SLS", "Schnick-Schnack-Systems GmbH" },
- { "SXG", "SELEX GALILEO" },
+ { "ETS", "Electronic Trade Solutions Ltd" },
+ { "ETT", "E-Tech Inc" },
+ { "EUT", "Ericsson Mobile Networks B.V." },
+ { "EVE", "Advanced Micro Peripherals Ltd" },
+ { "EVI", "eviateg GmbH" },
+ { "EVX", "Everex" },
+ { "EXA", "Exabyte" },
+ { "EXC", "Excession Audio" },
+ { "EXI", "Exide Electronics" },
+ { "EXN", "RGB Systems, Inc. dba Extron Electronics" },
{ "EXP", "Data Export Corporation" },
- { "TPR", "Topro Technology Inc" },
- { "RCE", "Parc d'Activite des Bellevues" },
- { "VIK", "Viking Connectors" },
- { "TGS", "Torus Systems Ltd" },
- { "IDO", "IDEO Product Development" },
- { "MCE", "Metz-Werke GmbH & Co KG" },
- { "PHC", "Pijnenburg Beheer N.V." },
- { "BTF", "Bitfield Oy" },
- { "MCD", "McDATA Corporation" },
+ { "EXT", "Exatech Computadores & Servicos Ltda" },
+ { "EXX", "Exxact GmbH" },
{ "EXY", "Exterity Ltd" },
- { "ZTI", "Zoom Telephonics Inc" },
- { "MTI", "Motorola Inc." },
- { "ONK", "ONKYO Corporation" },
- { "SEC", "Seiko Epson Corporation" },
- { "TTB", "National Semiconductor Japan Ltd" },
- { "SNO", "SINOSUN TECHNOLOGY CO., LTD" },
- { "SHG", "Soft & Hardware development Goldammer GmbH" },
- { "GEM", "Gem Plus" },
- { "BOS", "BOS" },
- { "SAK", "Saitek Ltd" },
- { "CNE", "Cine-tal" },
- { "BOB", "Rainy Orchard" },
- { "UNF", "Unisys Corporation" },
- { "MCG", "Motorola Computer Group" },
- { "RTC", "Relia Technologies" },
- { "ASD", "USC Information Sciences Institute" },
- { "BMS", "BIOMEDISYS" },
- { "LPE", "El-PUSK Co., Ltd." },
- { "CTA", "CoSystems Inc" },
- { "SVI", "Sun Microsystems" },
- { "PCS", "TOSHIBA PERSONAL COMPUTER SYSTEM CORPRATION" },
- { "GEN", "Genesys ATE Inc" },
- { "CRI", "Crio Inc." },
- { "TOG", "The OPEN Group" },
- { "SYT", "Seyeon Tech Company Ltd" },
- { "CRE", "Creative Labs Inc" },
- { "ALK", "Acrolink Inc" },
- { "TNC", "TNC Industrial Company Ltd" },
- { "PLV", "PLUS Vision Corp." },
- { "CCL", "CCL/ITRI" },
- { "PLY", "Polycom Inc." },
- { "RMC", "Raritan Computer, Inc" },
- { "XRC", "Xircom Inc" },
- { "BRC", "BARC" },
- { "CUK", "Calibre UK Ltd" },
- { "KME", "KIMIN Electronics Co., Ltd." },
- { "TBS", "Turtle Beach System" },
- { "ASY", "Rockwell Collins / Airshow Systems" },
- { "ALV", "AlphaView LCD" },
- { "VSD", "3M" },
- { "MTN", "Mtron Storage Technology Co., Ltd." },
- { "LMG", "Lucent Technologies" },
- { "HWP", "Hewlett Packard" },
- { "UEG", "Elitegroup Computer Systems Company Ltd" },
- { "FIC", "Formosa Industrial Computing Inc" },
- { "CRV", "Cerevo Inc." },
- { "AIL", "Altos India Ltd" },
- { "EMI", "Ex Machina Inc" },
- { "DPC", "Delta Electronics Inc" },
- { "ADN", "Analog & Digital Devices Tel. Inc" },
- { "LGC", "Logic Ltd" },
- { "DMP", "D&M Holdings Inc, Professional Business Company" },
- { "CEC", "Chicony Electronics Company Ltd" },
- { "BTC", "Bit 3 Computer" },
- { "IWX", "Intelliworxx, Inc." },
- { "SML", "Sumitomo Metal Industries, Ltd." },
- { "JWY", "Jetway Information Co., Ltd" },
- { "OMC", "OBJIX Multimedia Corporation" },
- { "CIT", "Citifax Limited" },
- { "AOE", "Advanced Optics Electronics, Inc." },
- { "SYC", "Sysmic" },
- { "ZTT", "Z3 Technology" },
- { "LCS", "Longshine Electronics Company" },
- { "NXQ", "Nexiq Technologies, Inc." },
- { "PSY", "Prodea Systems Inc." },
- { "CUB", "Cubix Corporation" },
- { "JWL", "Jewell Instruments, LLC" },
- { "SUB", "Subspace Comm. Inc" },
- { "PTG", "Cipher Systems Inc" },
- { "TON", "TONNA" },
- { "VBR", "VBrick Systems Inc." },
- { "RTI", "Rancho Tech Inc" },
- { "IMG", "IMAGENICS Co., Ltd." },
- { "AEP", "Aetas Peripheral International" },
- { "PTH", "Pathlight Technology Inc" },
- { "ZYX", "Zyxel" },
- { "NXP", "NXP Semiconductors bv." },
- { "OYO", "Shadow Systems" },
- { "PVM", "Penta Studiotechnik GmbH" },
- { "AVC", "Auravision Corporation" },
- { "SYM", "Symicron Computer Communications Ltd." },
- { "AVI", "Nippon Avionics Co.,Ltd" },
{ "EYE", "eyevis GmbH" },
- { "PLM", "PROLINK Microsystems Corp." },
- { "NFC", "BTC Korea Co., Ltd" },
- { "PIE", "Pacific Image Electronics Company Ltd" },
- { "SRC", "Integrated Tech Express Inc" },
- { "CMX", "Comex Electronics AB" },
- { "OPP", "OPPO Digital, Inc." },
- { "GAL", "Galil Motion Control" },
- { "YHW", "Exacom SA" },
- { "SSD", "FlightSafety International" },
- { "FSC", "Future Systems Consulting KK" },
- { "HRI", "Hall Research" },
- { "PSA", "Advanced Signal Processing Technologies" },
- { "MSI", "Microstep" },
- { "IMI", "International Microsystems Inc" },
- { "IDX", "IDEXX Labs" },
- { "SCO", "SORCUS Computer GmbH" },
- { "DIS", "Diseda S.A." },
- { "SVA", "SGEG" },
- { "SMA", "SMART Modular Technologies" },
- { "SXL", "SolutionInside" },
- { "WRC", "WiNRADiO Communications" },
- { "NIT", "Network Info Technology" },
- { "EKS", "EKSEN YAZILIM" },
- { "GEF", "GE Fanuc Embedded Systems" },
- { "DEI", "Deico Electronics" },
- { "DCD", "Datacast LLC" },
- { "MEE", "Mitsubishi Electric Engineering Co., Ltd." },
- { "LSC", "LifeSize Communications" },
- { "PDV", "Prodrive B.V." },
- { "HIB", "Hibino Corporation" },
- { "SKT", "Samsung Electro-Mechanics Company Ltd" },
- { "SAN", "Sanyo Electric Co.,Ltd." },
- { "RCO", "Rockwell Collins" },
- { "SNY", "Sony" },
- { "ANR", "ANR Ltd" },
- { "DKY", "Datakey Inc" },
- { "OPC", "Opcode Inc" },
- { "TBC", "Turbo Communication, Inc" },
- { "CNT", "COINT Multimedia Systems" },
- { "HDC", "HardCom Elektronik & Datateknik" },
- { "UNB", "Unisys Corporation" },
- { "IOD", "I-O Data Device Inc" },
- { "APR", "Aprilia s.p.a." },
- { "AXX", "Axxon Computer Corporation" },
- { "AED", "Advanced Electronic Designs, Inc." },
- { "MTX", "Matrox" },
- { "TAX", "Taxan (Europe) Ltd" },
- { "TVS", "TVS Electronics Limited" },
- { "CZE", "Carl Zeiss AG" },
- { "SMI", "SpaceLabs Medical Inc" },
+ { "EZE", "EzE Technologies" },
+ { "EZP", "Storm Technology" },
+ { "FAR", "Farallon Computing" },
+ { "FBI", "Interface Corporation" },
{ "FCB", "Furukawa Electric Company Ltd" },
- { "AXP", "American Express" },
- { "FST", "Modesto PC Inc" },
- { "PSI", "PSI-Perceptive Solutions Inc" },
- { "MCR", "Marina Communicaitons" },
- { "JCE", "Jace Tech Inc" },
- { "GRE", "GOLD RAIN ENTERPRISES CORP." },
- { "SYN", "Synaptics Inc" },
- { "MBC", "MBC" },
- { "SIB", "Sanyo Electric Company Ltd" },
- { "TCT", "Telecom Technology Centre Co. Ltd." },
- { "BIC", "Big Island Communications" },
- { "UNI", "Unisys Corporation" },
- { "ELX", "Elonex PLC" },
- { "ZDS", "Zenith Data Systems" },
- { "XLX", "Xilinx, Inc." },
- { "MIC", "Micom Communications Inc" },
- { "SEB", "system elektronik GmbH" },
- { "WIN", "Wintop Technology Inc" },
- { "CDG", "Christie Digital Systems Inc" },
- { "HUB", "GAI-Tronics, A Hubbell Company" },
- { "CSE", "Concept Solutions & Engineering" },
- { "SUR", "Surenam Computer Corporation" },
- { "VTM", "Miltope Corporation" },
- { "ATK", "Allied Telesyn Int'l" },
- { "MGT", "Megatech R & D Company" },
- { "SLK", "Silitek Corporation" },
- { "DYN", "Askey Computer Corporation" },
- { "KEY", "Key Tech Inc" },
- { "DVD", "Dictaphone Corporation" },
- { "OTT", "OPTO22, Inc." },
- { "TCI", "Tulip Computers Int'l B.V." },
- { "ACB", "Aculab Ltd" },
- { "PAD", "Promotion and Display Technology Ltd." },
- { "CMG", "Chenming Mold Ind. Corp." },
- { "UJR", "Ueda Japan Radio Co., Ltd." },
- { "LHA", "Lars Haagh ApS" },
- { "SIM", "S3 Inc" },
- { "TPC", "Touch Panel Systems Corporation" },
- { "TVD", "Tecnovision" },
- { "FZI", "FZI Forschungszentrum Informatik" },
- { "AIW", "Aiwa Company Ltd" },
- { "LTW", "Lightware, Inc" },
- { "DSP", "Domain Technology Inc" },
- { "ILS", "Innotech Corporation" },
- { "VDM", "Vadem" },
- { "KYK", "Samsung Electronics America Inc" },
- { "NTW", "Networth Inc" },
- { "SID", "Seiko Instruments Information Devices Inc" },
- { "MRT", "Merging Technologies" },
- { "MGL", "M-G Technology Ltd" },
- { "UBL", "Ubinetics Ltd." },
- { "PSM", "Prosum" },
- { "MDR", "Medar Inc" },
- { "STN", "Samsung Electronics America" },
- { "NCR", "NCR Electronics" },
- { "INU", "Inovatec S.p.A." },
- { "WAL", "Wave Access" },
- { "BLN", "BioLink Technologies" },
- { "RXT", "Tectona SoftSolutions (P) Ltd.," },
- { "MRL", "Miratel" },
- { "ZAZ", "Zazzle Technologies" },
- { "NIC", "National Instruments Corporation" },
- { "FMZ", "Formoza-Altair" },
- { "MDG", "Madge Networks" },
- { "VIA", "VIA Tech Inc" },
- { "KOD", "Eastman Kodak Company" },
- { "SAI", "Sage Inc" },
+ { "FCG", "First International Computer Ltd" },
+ { "FCS", "Focus Enhancements, Inc." },
+ { "FDC", "Future Domain" },
+ { "FDT", "Fujitsu Display Technologies Corp." },
+ { "FEC", "FURUNO ELECTRIC CO., LTD." },
{ "FEL", "Fellowes & Questec" },
- { "SLI", "Symbios Logic Inc" },
- { "ELE", "Elecom Company Ltd" },
- { "FRE", "Forvus Research Inc" },
- { "TTL", "2-Tel B.V." },
- { "PPX", "Perceptive Pixel Inc." },
- { "NAT", "NaturalPoint Inc." },
- { "SLC", "Syslogic Datentechnik AG" },
- { "PAM", "Peter Antesberger Messtechnik" },
- { "JPW", "Wallis Hamilton Industries" },
- { "AVA", "Avaya Communication" },
- { "EEH", "EEH Datalink GmbH" },
- { "WMT", "Winmate Communication Inc" },
- { "LWC", "Labway Corporation" },
- { "HYO", "HYC CO., LTD." },
- { "MCC", "Micro Industries" },
- { "IOA", "CRE Technology Corporation" },
- { "AGI", "Artish Graphics Inc" },
- { "TDT", "TDT" },
- { "UNO", "Unisys Corporation" },
- { "LIN", "Lenovo Beijing Co. Ltd." },
- { "MAG", "MAG InnoVision" },
- { "HCL", "HCL America Inc" },
- { "BWK", "Bitworks Inc." },
- { "BSN", "BRIGHTSIGN, LLC" },
- { "INM", "InnoMedia Inc" },
- { "MIN", "Minicom Digital Signage" },
- { "ARE", "ICET S.p.A." },
- { "TPZ", "Ypoaz Systems Inc" },
- { "BRO", "BROTHER INDUSTRIES,LTD." },
- { "MEX", "MSC Vertriebs GmbH" },
+ { "FEN", "Fen Systems Ltd." },
+ { "FER", "Ferranti Int'L" },
+ { "FFC", "FUJIFILM Corporation" },
+ { "FFI", "Fairfield Industries" },
+ { "FGD", "Lisa Draexlmaier GmbH" },
+ { "FGL", "Fujitsu General Limited." },
+ { "FHL", "FHLP" },
+ { "FIC", "Formosa Industrial Computing Inc" },
+ { "FIL", "Forefront Int'l Ltd" },
+ { "FIN", "Finecom Co., Ltd." },
+ { "FIR", "Chaplet Systems Inc" },
+ { "FIS", "FLY-IT Simulators" },
+ { "FIT", "Feature Integration Technology Inc." },
{ "FJC", "Fujitsu Takamisawa Component Limited" },
- { "HRT", "HERCULES" },
- { "MOM", "Momentum Data Systems" },
- { "RSV", "Ross Video Ltd" },
- { "RAN", "Rancho Tech Inc" },
- { "HOL", "Holoeye Photonics AG" },
- { "SOT", "Sotec Company Ltd" },
- { "AAE", "Anatek Electronics Inc." },
- { "ZYT", "Zytex Computers" },
- { "APP", "Apple Computer Inc" },
- { "MCM", "Metricom Inc" },
- { "NXC", "NextCom K.K." },
- { "CBX", "Cybex Computer Products Corporation" },
{ "FJS", "Fujitsu Spain" },
- { "SNI", "Siemens Microdesign GmbH" },
- { "MPL", "Maple Research Inst. Company Ltd" },
- { "PLX", "Parallax Graphics" },
- { "EAS", "Evans and Sutherland Computer" },
- { "ZBR", "Zebra Technologies International, LLC" },
- { "MSL", "MicroSlate Inc." },
- { "XOC", "DO NOT USE - XOC" },
- { "EMG", "EMG Consultants Inc" },
- { "SMC", "Standard Microsystems Corporation" },
- { "RAD", "Radisys Corporation" },
- { "NMS", "Natural Micro System" },
- { "APT", "Audio Processing Technology Ltd" },
- { "MLI", "McIntosh Laboratory Inc." },
- { "ISI", "Interface Solutions" },
- { "RAT", "Rent-A-Tech" },
- { "BAN", "Banyan" },
- { "PCL", "pentel.co.,ltd" },
- { "CSI", "Cabletron System Inc" },
- { "IVS", "Intevac Photonics Inc." },
- { "MAT", "Matsushita Electric Ind. Company Ltd" },
- { "LWR", "Lightware Visual Engineering" },
+ { "FJT", "F.J. Tieman BV" },
+ { "FLE", "ADTI Media, Inc" },
+ { "FLI", "Faroudja Laboratories" },
+ { "FLY", "Butterfly Communications" },
+ { "FMA", "Fast Multimedia AG" },
+ { "FMC", "Ford Microelectronics Inc" },
+ { "FMI", "Fujitsu Microelect Inc" },
+ { "FML", "Fujitsu Microelect Ltd" },
+ { "FMZ", "Formoza-Altair" },
+ { "FNC", "Fanuc LTD" },
+ { "FNI", "Funai Electric Co., Ltd." },
+ { "FOA", "FOR-A Company Limited" },
+ { "FOS", "Foss Tecator" },
+ { "FOX", "HON HAI PRECISON IND.CO.,LTD." },
+ { "FPE", "Fujitsu Peripherals Ltd" },
+ { "FPS", "Deltec Corporation" },
+ { "FPX", "Cirel Systemes" },
+ { "FRC", "Force Computers" },
+ { "FRD", "Freedom Scientific BLV" },
+ { "FRE", "Forvus Research Inc" },
+ { "FRI", "Fibernet Research Inc" },
+ { "FRO", "FARO Technologies" },
+ { "FRS", "South Mountain Technologies, LTD" },
+ { "FSC", "Future Systems Consulting KK" },
+ { "FSI", "Fore Systems Inc" },
+ { "FST", "Modesto PC Inc" },
+ { "FTC", "Futuretouch Corporation" },
+ { "FTE", "Frontline Test Equipment Inc." },
+ { "FTG", "FTG Data Systems" },
+ { "FTI", "FastPoint Technologies, Inc." },
+ { "FTL", "FUJITSU TEN LIMITED" },
+ { "FTN", "Fountain Technologies Inc" },
+ { "FTR", "Mediasonic" },
+ { "FTW", "MindTribe Product Engineering, Inc." },
+ { "FUJ", "Fujitsu Ltd" },
+ { "FUN", "sisel muhendislik" },
+ { "FUS", "Fujitsu Siemens Computers GmbH" },
+ { "FVC", "First Virtual Corporation" },
+ { "FVX", "C-C-C Group Plc" },
{ "FWA", "Attero Tech, LLC" },
- { "ORI", "OSR Open Systems Resources, Inc." },
- { "ARG", "Argus Electronics Co., LTD" },
- { "CAS", "CASIO COMPUTER CO.,LTD" },
- { "DHP", "DH Print" },
- { "TTS", "TechnoTrend Systemtechnik GmbH" },
- { "HHC", "HIRAKAWA HEWTECH CORP." },
+ { "FWR", "Flat Connections Inc" },
+ { "FXX", "Fuji Xerox" },
+ { "FZC", "Founder Group Shenzhen Co." },
+ { "FZI", "FZI Forschungszentrum Informatik" },
+ { "GAG", "Gage Applied Sciences Inc" },
+ { "GAL", "Galil Motion Control" },
+ { "GAU", "Gaudi Co., Ltd." },
+ { "GCC", "GCC Technologies Inc" },
+ { "GCI", "Gateway Comm. Inc" },
+ { "GCS", "Grey Cell Systems Ltd" },
+ { "GDC", "General Datacom" },
+ { "GDI", "G. Diehl ISDN GmbH" },
+ { "GDS", "GDS" },
+ { "GDT", "Vortex Computersysteme GmbH" },
+ { "GED", "General Dynamics C4 Systems" },
+ { "GEF", "GE Fanuc Embedded Systems" },
+ { "GEH", "GE Intelligent Platforms - Huntsville" },
+ { "GEM", "Gem Plus" },
+ { "GEN", "Genesys ATE Inc" },
+ { "GEO", "GEO Sense" },
+ { "GER", "GERMANEERS GmbH" },
+ { "GES", "GES Singapore Pte Ltd" },
+ { "GET", "Getac Technology Corporation" },
+ { "GFM", "GFMesstechnik GmbH" },
+ { "GFN", "Gefen Inc." },
+ { "GGL", "Google Inc." },
+ { "GIC", "General Inst. Corporation" },
+ { "GIM", "Guillemont International" },
+ { "GIP", "GI Provision Ltd" },
+ { "GIS", "AT&T Global Info Solutions" },
+ { "GJN", "Grand Junction Networks" },
+ { "GLD", "Goldmund - Digital Audio SA" },
+ { "GLE", "AD electronics" },
+ { "GLM", "Genesys Logic" },
+ { "GLS", "Gadget Labs LLC" },
+ { "GMK", "GMK Electronic Design GmbH" },
+ { "GML", "General Information Systems" },
+ { "GMM", "GMM Research Inc" },
+ { "GMN", "GEMINI 2000 Ltd" },
+ { "GMX", "GMX Inc" },
+ { "GND", "Gennum Corporation" },
+ { "GNN", "GN Nettest Inc" },
+ { "GNZ", "Gunze Ltd" },
+ { "GRA", "Graphica Computer" },
+ { "GRE", "GOLD RAIN ENTERPRISES CORP." },
+ { "GRH", "Granch Ltd" },
{ "GRM", "Garmin International" },
- { "BUL", "Bull" },
- { "AFA", "Alfa Inc" },
- { "OVR", "Oculus VR, Inc." },
- { "EPI", "Envision Peripherals, Inc" },
+ { "GRV", "Advanced Gravis" },
+ { "GRY", "Robert Gray Company" },
+ { "GSB", "NIPPONDENCHI CO,.LTD" },
{ "GSC", "General Standards Corporation" },
- { "DNG", "Apache Micro Peripherals Inc" },
- { "VIN", "Vine Micros Ltd" },
- { "PTW", "DO NOT USE - PTW" },
- { "MFI", "Micro Firmware" },
- { "SMP", "Simple Computing" },
- { "HCA", "DAT" },
- { "PHL", "Philips Consumer Electronics Company" },
- { "ADC", "Acnhor Datacomm" },
- { "VBT", "Valley Board Ltda" },
- { "MPX", "Micropix Technologies, Ltd." },
- { "VSP", "Vision Systems GmbH" },
- { "PJA", "Projecta" },
- { "AMT", "AMT International Industry" },
- { "VCI", "VistaCom Inc" },
- { "XIR", "Xirocm Inc" },
- { "MBV", "Moreton Bay" },
- { "NSC", "National Semiconductor Corporation" },
- { "TPV", "Top Victory Electronics ( Fujian ) Company Ltd" },
+ { "GSM", "LG Electronics" },
+ { "GST", "Graphic SystemTechnology" },
+ { "GSY", "Grossenbacher Systeme AG" },
+ { "GTC", "Graphtec Corporation" },
+ { "GTI", "Goldtouch" },
+ { "GTK", "G-Tech Corporation" },
+ { "GTM", "Garnet System Company Ltd" },
+ { "GTS", "Geotest Marvin Test Systems Inc" },
+ { "GTT", "General Touch Technology Co., Ltd." },
+ { "GUD", "Guntermann & Drunck GmbH" },
+ { "GUZ", "Guzik Technical Enterprises" },
+ { "GVC", "GVC Corporation" },
+ { "GVL", "Global Village Communication" },
+ { "GWI", "GW Instruments" },
+ { "GWY", "Gateway 2000" },
+ { "GZE", "GUNZE Limited" },
{ "HAE", "Haider electronics" },
- { "PKA", "Acco UK ltd." },
- { "PXC", "Phoenix Contact" },
- { "BXE", "Buxco Electronics" },
- { "OZC", "OZ Corporation" },
- { "TXL", "Trixel Ltd" },
- { "MXD", "MaxData Computer GmbH & Co.KG" },
- { "ASK", "Ask A/S" },
- { "KSC", "Kinetic Systems Corporation" },
- { "XAD", "Alpha Data" },
- { "MVI", "Media Vision Inc" },
- { "BPU", "Best Power" },
- { "LAF", "Microline" },
- { "SPS", "Synopsys Inc" },
- { "WXT", "Woxter Technology Co. Ltd" },
- { "NIX", "Seanix Technology Inc" },
- { "HPA", "Zytor Communications" },
- { "SPK", "SpeakerCraft" },
- { "CHP", "CH Products" },
- { "SNX", "Sonix Comm. Ltd" },
- { "LZX", "Lightwell Company Ltd" },
- { "ART", "Corion Industrial Corporation" },
- { "IFS", "In Focus Systems Inc" },
- { "DAL", "Digital Audio Labs Inc" },
- { "STR", "Starlight Networks Inc" },
- { "PRT", "Parade Technologies, Ltd." },
- { "VRC", "Virtual Resources Corporation" },
- { "IIC", "ISIC Innoscan Industrial Computers A/S" },
- { "AUR", "Aureal Semiconductor" },
- { "ATC", "Ably-Tech Corporation" },
- { "ODR", "Odrac" },
- { "LIP", "Linked IP GmbH" },
- { "FLI", "Faroudja Laboratories" },
- { "AVV", "SBS Technologies (Canada), Inc. (was Avvida Systems, Inc.)" },
- { "ECM", "E-Cmos Tech Corporation" },
- { "LAG", "Laguna Systems" },
- { "FFC", "FUJIFILM Corporation" },
- { "MAX", "Rogen Tech Distribution Inc" },
- { "HUM", "IMP Electronics Ltd." },
- { "VTX", "Vestax Corporation" },
- { "NST", "Network Security Technology Co" },
- { "FLY", "Butterfly Communications" },
- { "ETT", "E-Tech Inc" },
- { "NXS", "Technology Nexus Secure Open Systems AB" },
- { "VES", "Vestel Elektronik Sanayi ve Ticaret A. S." },
- { "EBT", "HUALONG TECHNOLOGY CO., LTD" },
- { "HPK", "HAMAMATSU PHOTONICS K.K." },
- { "RGB", "RGB Spectrum" },
- { "AUI", "Alps Electric Inc" },
- { "ICI", "Infotek Communication Inc" },
- { "NTS", "Nits Technology Inc." },
- { "EVI", "eviateg GmbH" },
- { "CRD", "Cardinal Technical Inc" },
- { "MOD", "Modular Technology" },
- { "CCP", "Capetronic USA Inc" },
- { "DGS", "Diagsoft Inc" },
- { "IFT", "Informtech" },
- { "LWW", "Lanier Worldwide" },
- { "SDK", "SAIT-Devlonics" },
- { "UWC", "Uniwill Computer Corp." },
- { "MXV", "MaxVision Corporation" },
+ { "HAI", "Haivision Systems Inc." },
+ { "HAL", "Halberthal" },
+ { "HAN", "Hanchang System Corporation" },
+ { "HAR", "Harris Corporation" },
+ { "HAY", "Hayes Microcomputer Products Inc" },
+ { "HCA", "DAT" },
+ { "HCE", "Hitachi Consumer Electronics Co., Ltd" },
+ { "HCL", "HCL America Inc" },
+ { "HCM", "HCL Peripherals" },
+ { "HCP", "Hitachi Computer Products Inc" },
+ { "HCW", "Hauppauge Computer Works Inc" },
+ { "HDC", "HardCom Elektronik & Datateknik" },
+ { "HDI", "HD-INFO d.o.o." },
+ { "HDV", "Holografika kft." },
+ { "HEC", "Hitachi Engineering Company Ltd" },
+ { "HEL", "Hitachi Micro Systems Europe Ltd" },
+ { "HER", "Ascom Business Systems" },
+ { "HET", "HETEC Datensysteme GmbH" },
+ { "HHC", "HIRAKAWA HEWTECH CORP." },
+ { "HHI", "Fraunhofer Heinrich-Hertz-Institute" },
+ { "HIB", "Hibino Corporation" },
+ { "HIC", "Hitachi Information Technology Co., Ltd." },
+ { "HIK", "Hikom Co., Ltd." },
+ { "HIL", "Hilevel Technology" },
+ { "HIQ", "Kaohsiung Opto Electronics Americas, Inc." },
+ { "HIT", "Hitachi America Ltd" },
+ { "HJI", "Harris & Jeffries Inc" },
+ { "HKA", "HONKO MFG. CO., LTD." },
+ { "HKG", "Josef Heim KG" },
+ { "HMC", "Hualon Microelectric Corporation" },
+ { "HMK", "hmk Daten-System-Technik BmbH" },
+ { "HMX", "HUMAX Co., Ltd." },
+ { "HNS", "Hughes Network Systems" },
+ { "HOB", "HOB Electronic GmbH" },
{ "HOE", "Hosiden Corporation" },
- { "SGE", "Kansai Electric Company Ltd" },
- { "URD", "Video Computer S.p.A." },
- { "TSV", "TRANSVIDEO" },
- { "MBM", "Marshall Electronics" },
- { "TLA", "Ferrari Electronic GmbH" },
- { "GLM", "Genesys Logic" },
- { "LEN", "Lenovo Group Limited" },
- { "SAM", "Samsung Electric Company" },
- { "VTL", "Vivid Technology Pte Ltd" },
- { "UTD", "Up to Date Tech" },
- { "ITC", "Intercom Inc" },
- { "ENI", "Efficient Networks" },
- { "GDC", "General Datacom" },
- { "XIT", "Xitel Pty ltd" },
- { "CMN", "Chimei Innolux Corporation" },
- { "AVE", "Add Value Enterpises (Asia) Pte Ltd" },
- { "WEC", "Winbond Electronics Corporation" },
- { "OAK", "Oak Tech Inc" },
- { "DON", "DENON, Ltd." },
- { "ITR", "Infotronic America, Inc." },
- { "CAC", "CA & F Elettronica" },
- { "VIM", "Via Mons Ltd." },
- { "DGP", "Digicorp European sales S.A." },
+ { "HOL", "Holoeye Photonics AG" },
+ { "HON", "Sonitronix" },
+ { "HPA", "Zytor Communications" },
+ { "HPC", "Hewlett Packard Co." },
{ "HPD", "Hewlett Packard" },
- { "USD", "U.S. Digital Corporation" },
- { "TAM", "Tamura Seisakusyo Ltd" },
- { "SGZ", "Systec Computer GmbH" },
- { "NGS", "A D S Exports" },
- { "FSI", "Fore Systems Inc" },
- { "SIL", "Silicon Laboratories, Inc" },
- { "QCP", "Qualcomm Inc" },
- { "SDA", "SAT (Societe Anonyme)" },
- { "SEI", "Seitz & Associates Inc" },
- { "RSI", "Rampage Systems Inc" },
- { "VIZ", "VIZIO, Inc" },
- { "EPN", "EPiCON Inc." },
- { "OIC", "Option Industrial Computers" },
- { "KDE", "KDE" },
- { "CLV", "Clevo Company" },
- { "GRA", "Graphica Computer" },
- { "HIK", "Hikom Co., Ltd." },
- { "LCE", "La Commande Electronique" },
- { "MNP", "Microcom" },
- { "ERI", "Ericsson Mobile Communications AB" },
- { "REX", "RATOC Systems, Inc." },
- { "PPP", "Purup Prepress AS" },
- { "JAT", "Jaton Corporation" },
- { "GLE", "AD electronics" },
- { "VAL", "Valence Computing Corporation" },
- { "CDN", "Codenoll Technical Corporation" },
- { "SDT", "Siemens AG" },
- { "RSC", "PhotoTelesis" },
- { "FFI", "Fairfield Industries" },
- { "VPR", "Best Buy" },
- { "IPM", "IPM Industria Politecnica Meridionale SpA" },
+ { "HPI", "Headplay, Inc." },
+ { "HPK", "HAMAMATSU PHOTONICS K.K." },
+ { "HPQ", "HP" },
+ { "HPR", "H.P.R. Electronics GmbH" },
+ { "HRC", "Hercules" },
+ { "HRE", "Qingdao Haier Electronics Co., Ltd." },
+ { "HRI", "Hall Research" },
+ { "HRL", "Herolab GmbH" },
+ { "HRS", "Harris Semiconductor" },
+ { "HRT", "HERCULES" },
+ { "HSC", "Hagiwara Sys-Com Company Ltd" },
+ { "HSD", "HannStar Display Corp" },
{ "HSM", "AT&T Microelectronics" },
- { "YHQ", "Yokogawa Electric Corporation" },
- { "UEC", "Ultima Electronics Corporation" },
- { "NME", "Navico, Inc." },
- { "GVL", "Global Village Communication" },
- { "TEK", "Tektronix Inc" },
- { "SBD", "Softbed - Consulting & Development Ltd" },
- { "PSD", "Peus-Systems GmbH" },
- { "DCA", "Digital Communications Association" },
+ { "HSP", "HannStar Display Corp" },
+ { "HTC", "Hitachi Ltd" },
+ { "HTI", "Hampshire Company, Inc." },
+ { "HTK", "Holtek Microelectronics Inc" },
+ { "HTX", "Hitex Systementwicklung GmbH" },
+ { "HUB", "GAI-Tronics, A Hubbell Company" },
+ { "HUM", "IMP Electronics Ltd." },
+ { "HWA", "Harris Canada Inc" },
{ "HWC", "DBA Hans Wedemeyer" },
- { "DFK", "SharkTec A/S" },
- { "DMB", "Digicom Systems Inc" },
- { "IPW", "IPWireless, Inc" },
- { "ACC", "Accton Technology Corporation" },
- { "CPM", "Capella Microsystems Inc." },
- { "AAT", "Ann Arbor Technologies" },
- { "LAS", "LASAT Comm. A/S" },
- { "TWI", "Easytel oy" },
- { "HJI", "Harris & Jeffries Inc" },
- { "SGX", "Silicon Graphics Inc" },
- { "TSL", "Tottori SANYO Electric Co., Ltd." },
- { "SVD", "SVD Computer" },
- { "CLT", "automated computer control systems" },
- { "WLD", "Wildfire Communications Inc" },
- { "LCI", "Lite-On Communication Inc" },
- { "AEC", "Antex Electronics Corporation" },
- { "ACA", "Ariel Corporation" },
- { "KML", "Kensington Microware Ltd" },
- { "KDT", "KDDI Technology Corporation" },
- { "BSE", "Bose Corporation" },
- { "WSP", "Wireless And Smart Products Inc." },
- { "GNZ", "Gunze Ltd" },
- { "PMM", "Point Multimedia System" },
- { "ASC", "Ascom Strategic Technology Unit" },
- { "EVX", "Everex" },
- { "WBN", "MicroSoftWare" },
- { "FGL", "Fujitsu General Limited." },
- { "JSI", "Jupiter Systems, Inc." },
- { "SII", "Silicon Image, Inc." },
- { "SMM", "Shark Multimedia Inc" },
- { "XYC", "Xycotec Computer GmbH" },
- { "PEC", "POTRANS Electrical Corp." },
- { "TSD", "TechniSat Digital GmbH" },
- { "ZSE", "Zenith Data Systems" },
- { "ENC", "Eizo Nanao Corporation" },
- { "MWY", "Microway Inc" },
- { "OLI", "Olivetti" },
- { "WIL", "WIPRO Information Technology Ltd" },
- { "LKM", "Likom Technology Sdn. Bhd." },
- { "KOU", "KOUZIRO Co.,Ltd." },
- { "VHI", "Macrocad Development Inc." },
- { "FIT", "Feature Integration Technology Inc." },
- { "MXP", "Maxpeed Corporation" },
- { "SCD", "Sanyo Electric Company Ltd" },
- { "NBL", "N*Able Technologies Inc" },
- { "SPT", "Sceptre Tech Inc" },
- { "IPN", "Performance Technologies" },
- { "BMD", "Blackmagic Design" },
- { "MDK", "Mediatek Corporation" },
- { "DCS", "Diamond Computer Systems Inc" },
- { "ICE", "IC Ensemble" },
- { "LSY", "LSI Systems Inc" },
- { "AMC", "Attachmate Corporation" },
- { "TCO", "Thomas-Conrad Corporation" },
- { "NOK", "Nokia Display Products" },
- { "VFI", "VeriFone Inc" },
- { "OPV", "Optivision Inc" },
- { "LCM", "Latitude Comm." },
- { "LSL", "Logical Solutions" },
- { "TVO", "TV One Ltd" },
- { "KVA", "Kvaser AB" },
- { "PMT", "Promate Electronic Co., Ltd." },
- { "ZZZ", "Boca Research Inc" },
- { "ELC", "Electro Scientific Ind" },
- { "SIR", "Sirius Technologies Pty Ltd" },
- { "DCE", "dSPACE GmbH" },
- { "WAN", "DO NOT USE - WAN" },
- { "PCT", "PC-Tel Inc" },
- { "BEO", "Baug & Olufsen" },
- { "LUM", "Lumagen, Inc." },
- { "DNA", "DNA Enterprises, Inc." },
- { "WEY", "WEY Design AG" },
- { "IAF", "Institut f r angewandte Funksystemtechnik GmbH" },
- { "QFF", "Padix Co., Inc." },
- { "JIC", "Jaeik Information & Communication Co., Ltd." },
- { "VIT", "Visitech AS" },
- { "QUA", "Quatographic AG" },
- { "BNK", "Banksia Tech Pty Ltd" },
- { "TME", "AT&T Microelectronics" },
- { "DRB", "Dr. Bott KG" },
- { "NET", "Mettler Toledo" },
- { "CDE", "Colin.de" },
- { "ATI", "Allied Telesis KK" },
- { "PMD", "TDK USA Corporation" },
- { "SKY", "SKYDATA S.P.A." },
- { "FTN", "Fountain Technologies Inc" },
- { "DBD", "Diebold Inc." },
- { "ECA", "Electro Cam Corp." },
- { "TLI", "TOSHIBA TELI CORPORATION" },
- { "CTC", "CTC Communication Development Company Ltd" },
- { "NVT", "Navatek Engineering Corporation" },
- { "CKC", "The Concept Keyboard Company Ltd" },
- { "FIR", "Chaplet Systems Inc" },
+ { "HWD", "Highwater Designs Ltd" },
+ { "HWP", "Hewlett Packard" },
+ { "HXM", "Hexium Ltd." },
+ { "HYC", "Hypercope Gmbh Aachen" },
{ "HYD", "Hydis Technologies.Co.,LTD" },
- { "TTY", "TRIDELITY Display Solutions GmbH" },
- { "DAE", "Digatron Industrie Elektronik GmbH" },
- { "AUT", "Autotime Corporation" },
- { "GTC", "Graphtec Corporation" },
- { "MYR", "Myriad Solutions Ltd" },
- { "DLT", "Digitelec Informatique Park Cadera" },
- { "SDR", "SDR Systems" },
- { "ACS", "Altos Computer Systems" },
- { "SVC", "Intellix Corp." },
- { "ZTE", "ZTE Corporation" },
- { "ERT", "Escort Insturments Corporation" },
- { "WII", "Innoware Inc" },
- { "DOL", "Dolman Technologies Group Inc" },
- { "RLD", "MEPCO" },
- { "HRL", "Herolab GmbH" },
- { "IRD", "IRdata" },
- { "IVI", "Intervoice Inc" },
- { "ICS", "Integrated Circuit Systems" },
- { "ASE", "AseV Display Labs" },
- { "SYX", "Prime Systems, Inc." },
- { "SOI", "Silicon Optix Corporation" },
- { "OCS", "Open Connect Solutions" },
- { "HON", "Sonitronix" },
- { "TAG", "Teles AG" },
- { "PEP", "Peppercon AG" },
- { "INT", "Interphase Corporation" },
+ { "HYO", "HYC CO., LTD." },
+ { "HYP", "Hyphen Ltd" },
+ { "HYR", "Hypertec Pty Ltd" },
+ { "HYT", "Heng Yu Technology (HK) Limited" },
+ { "HYV", "Hynix Semiconductor" },
+ { "IAF", "Institut f r angewandte Funksystemtechnik GmbH" },
+ { "IAI", "Integration Associates, Inc." },
+ { "IAT", "IAT Germany GmbH" },
+ { "IBC", "Integrated Business Systems" },
+ { "IBI", "INBINE.CO.LTD" },
+ { "IBM", "IBM France" },
+ { "IBP", "IBP Instruments GmbH" },
{ "IBR", "IBR GmbH" },
- { "WYS", "Wyse Technology" },
- { "TRE", "Tremetrics" },
- { "RKC", "Reakin Technolohy Corporation" },
- { "SEG", "DO NOT USE - SEG" },
- { "CAV", "Cavium Networks, Inc" },
- { "ELA", "ELAD srl" },
- { "MMD", "Micromed Biotecnologia Ltd" },
- { "SGL", "Super Gate Technology Company Ltd" },
- { "SIS", "Silicon Integrated Systems Corporation" },
- { "XFO", "EXFO Electro Optical Engineering" },
- { "ING", "Integraph Corporation" },
- { "NEU", "NEUROTEC - EMPRESA DE PESQUISA E DESENVOLVIMENTO EM BIOMEDICINA" },
- { "ZIC", "Nationz Technologies Inc." },
- { "CVI", "Colorado Video, Inc." },
- { "VCC", "Virtual Computer Corporation" },
- { "INZ", "Best Buy" },
- { "ELO", "Tyco Electronics" },
- { "EPH", "Epiphan Systems Inc." },
- { "SYL", "Sylvania Computer Products" },
- { "MXI", "Macronix Inc" },
- { "GEH", "GE Intelligent Platforms - Huntsville" },
- { "BBB", "an-najah university" },
- { "ARK", "Ark Logic Inc" },
- { "IVM", "Iiyama North America" },
- { "XTE", "X2E GmbH" },
- { "DMV", "NDS Ltd" },
- { "CPD", "CompuAdd" },
- { "CYD", "Cyclades Corporation" },
- { "ALX", "ALEXON Co.,Ltd." },
- { "COB", "COBY Electronics Co., Ltd" },
- { "HCE", "Hitachi Consumer Electronics Co., Ltd" },
- { "EXX", "Exxact GmbH" },
- { "TAB", "Todos Data System AB" },
- { "MPN", "Mainpine Limited" },
- { "ATH", "Athena Informatica S.R.L." },
- { "AWL", "Aironet Wireless Communications, Inc" },
- { "FNI", "Funai Electric Co., Ltd." },
- { "PLT", "PT Hartono Istana Teknologi" },
- { "DEN", "Densitron Computers Ltd" },
- { "MIM", "Mimio – A Newell Rubbermaid Company" },
- { "GER", "GERMANEERS GmbH" },
- { "CAI", "Canon Inc." },
- { "DNI", "Deterministic Networks Inc." },
- { "DOT", "Dotronic Mikroelektronik GmbH" },
- { "MVX", "COM 1" },
- { "WTC", "ACC Microelectronics" },
- { "HIT", "Hitachi America Ltd" },
- { "ALM", "Acutec Ltd." },
- { "TIP", "TIPTEL AG" },
- { "END", "ENIDAN Technologies Ltd" },
- { "PAR", "Parallan Comp Inc" },
- { "DVL", "Devolo AG" },
- { "ADV", "Advanced Micro Devices Inc" },
- { "TKS", "TimeKeeping Systems, Inc." },
- { "MLD", "Deep Video Imaging Ltd" },
- { "IUC", "ICSL" },
- { "MNL", "Monorail Inc" },
- { "HRC", "Hercules" },
- { "ANS", "Ansel Communication Company" },
- { "UAS", "Ultima Associates Pte Ltd" },
- { "SBS", "SBS-or Industrial Computers GmbH" },
- { "DVT", "Data Video" },
- { "PTS", "Plain Tree Systems Inc" },
- { "CSD", "Cresta Systems Inc" },
- { "LDT", "LogiDataTech Electronic GmbH" },
- { "AGM", "Advan Int'l Corporation" },
- { "TLD", "Telindus" },
- { "SPU", "SIM2 Multimedia S.P.A." },
- { "BCS", "Booria CAD/CAM systems" },
- { "CRQ", "Cirque Corporation" },
- { "MIL", "Marconi Instruments Ltd" },
- { "FTE", "Frontline Test Equipment Inc." },
- { "RWC", "Red Wing Corporation" },
- { "TLS", "Teleste Educational OY" },
- { "DAT", "Datel Inc" },
- { "SIT", "Sitintel" },
- { "QTI", "Quicknet Technologies Inc" },
- { "EBH", "Data Price Informatica" },
- { "PCK", "PCBANK21" },
- { "VSC", "ViewSonic Corporation" },
- { "BBL", "Brain Boxes Limited" },
- { "UFO", "UFO Systems Inc" },
- { "NTI", "New Tech Int'l Company" },
- { "WAV", "Wavephore" },
- { "NOT", "Not Limited Inc" },
- { "GRH", "Granch Ltd" },
- { "VTC", "VTel Corporation" },
- { "UNA", "Unisys DSD" },
- { "LAB", "ACT Labs Ltd" },
- { "UIC", "Uniform Industrial Corporation" },
+ { "ICA", "ICA Inc" },
+ { "ICC", "BICC Data Networks Ltd" },
+ { "ICD", "ICD Inc" },
+ { "ICE", "IC Ensemble" },
+ { "ICI", "Infotek Communication Inc" },
+ { "ICM", "Intracom SA" },
+ { "ICN", "Sanyo Icon" },
+ { "ICO", "Intel Corp" },
+ { "ICP", "ICP Electronics, Inc./iEi Technology Corp." },
+ { "ICS", "Integrated Circuit Systems" },
+ { "ICV", "Inside Contactless" },
+ { "ICX", "ICCC A/S" },
+ { "IDC", "International Datacasting Corporation" },
+ { "IDE", "IDE Associates" },
{ "IDK", "IDK Corporation" },
- { "CHI", "Chrontel Inc" },
- { "QCH", "Metronics Inc" },
- { "CER", "Ceronix" },
- { "PCB", "OCTAL S.A." },
- { "VTV", "VATIV Technologies" },
- { "BTI", "BusTech Inc" },
- { "RVL", "Reveal Computer Prod" },
- { "CHC", "Chic Technology Corp." },
- { "QDS", "Quanta Display Inc." },
- { "DAW", "DA2 Technologies Inc" },
- { "MTR", "Mitron computer Inc" },
- { "PCP", "Procomp USA Inc" },
- { "AZM", "AZ Middelheim - Radiotherapy" },
- { "NHT", "Vinci Labs" },
- { "ROB", "Robust Electronics GmbH" },
- { "RIC", "RICOH COMPANY, LTD." },
- { "PCI", "Pioneer Computer Inc" },
- { "EKA", "MagTek Inc." },
- { "SWL", "Sharedware Ltd" },
- { "GSM", "Goldstar Company Ltd" },
+ { "IDN", "Idneo Technologies" },
+ { "IDO", "IDEO Product Development" },
{ "IDP", "Integrated Device Technology, Inc." },
- { "BPD", "Micro Solutions, Inc." },
- { "UNS", "Unisys Corporation" },
- { "PBN", "Packard Bell NEC" },
- { "KRM", "Kroma Telecom" },
- { "ENT", "Enterprise Comm. & Computing Inc" },
- { "ATL", "Arcus Technology Ltd" },
- { "VDT", "Viditec, Inc." },
- { "JUK", "Janich & Klass Computertechnik GmbH" },
- { "PVG", "Proview Global Co., Ltd" },
- { "INX", "Communications Supply Corporation (A division of WESCO)" },
- { "GDS", "GDS" },
- { "UHB", "XOCECO" },
- { "MEI", "Panasonic Industry Company" },
- { "OXU", "Oxus Research S.A." },
- { "SGO", "Logos Design A/S" },
- { "STU", "Sentelic Corporation" },
- { "PUL", "Pulse-Eight Ltd" },
- { "BRA", "Braemac Pty Ltd" },
- { "MBD", "Microbus PLC" },
- { "OAS", "Oasys Technology Company" },
- { "MDS", "Micro Display Systems Inc" },
- { "SCS", "Nanomach Anstalt" },
- { "DAS", "DAVIS AS" },
- { "NLC", "Next Level Communications" },
- { "MSU", "motorola" },
- { "MAD", "Xedia Corporation" },
- { "LOE", "Loewe Opta GmbH" },
- { "EEE", "ET&T Technology Company Ltd" },
- { "ANX", "Acer Netxus Inc" },
+ { "IDS", "Interdigital Sistemas de Informacao" },
+ { "IDT", "International Display Technology" },
+ { "IDX", "IDEXX Labs" },
+ { "IEC", "Interlace Engineering Corporation" },
{ "IEE", "IEE" },
- { "ALL", "Alliance Semiconductor Corporation" },
- { "DCT", "Dancall Telecom A/S" },
- { "AII", "Amptron International Inc." },
- { "DPT", "DPT" },
- { "TNJ", "DO NOT USE - TNJ" },
- { "FTC", "Futuretouch Corporation" },
- { "ESG", "ELCON Systemtechnik GmbH" },
- { "SYV", "SYVAX Inc" },
- { "RAC", "Racore Computer Products Inc" },
- { "IBM", "IBM France" },
- { "LTV", "Leitch Technology International Inc." },
- { "AKE", "AKAMI Electric Co.,Ltd" },
- { "VDO", "Video & Display Oriented Corporation" },
- { "MEN", "MEN Mikroelectronik Nueruberg GmbH" },
- { "UNT", "Unisys Corporation" },
- { "TTK", "Totoku Electric Company Ltd" },
- { "DII", "Dataq Instruments Inc" },
- { "AMO", "Amino Technologies PLC and Amino Communications Limited" },
+ { "IEI", "Interlink Electronics" },
+ { "IFS", "In Focus Systems Inc" },
+ { "IFT", "Informtech" },
+ { "IFX", "Infineon Technologies AG" },
+ { "IFZ", "Infinite Z" },
+ { "IGC", "Intergate Pty Ltd" },
+ { "IGM", "IGM Communi" },
+ { "IHE", "InHand Electronics" },
+ { "IIC", "ISIC Innoscan Industrial Computers A/S" },
+ { "III", "Intelligent Instrumentation" },
+ { "IIN", "IINFRA Co., Ltd" },
+ { "IKS", "Ikos Systems Inc" },
+ { "ILC", "Image Logic Corporation" },
+ { "ILS", "Innotech Corporation" },
+ { "IMA", "Imagraph" },
+ { "IMB", "ART s.r.l." },
{ "IMC", "IMC Networks" },
- { "STG", "StereoGraphics Corp." },
- { "RRI", "Radicom Research Inc" },
- { "HTI", "Hampshire Company, Inc." },
- { "SOR", "Sorcus Computer GmbH" },
- { "AXL", "Axel" },
- { "SNS", "Cirtech (UK) Ltd" },
+ { "IMD", "ImasDe Canarias S.A." },
+ { "IME", "Imagraph" },
+ { "IMG", "IMAGENICS Co., Ltd." },
+ { "IMI", "International Microsystems Inc" },
+ { "IMM", "Immersion Corporation" },
+ { "IMN", "Impossible Production" },
+ { "IMP", "Impression Products Incorporated" },
+ { "IMT", "Inmax Technology Corporation" },
+ { "INC", "Home Row Inc" },
+ { "IND", "ILC" },
+ { "INE", "Inventec Electronics (M) Sdn. Bhd." },
+ { "INF", "Inframetrics Inc" },
+ { "ING", "Integraph Corporation" },
+ { "INI", "Initio Corporation" },
+ { "INK", "Indtek Co., Ltd." },
+ { "INL", "InnoLux Display Corporation" },
+ { "INM", "InnoMedia Inc" },
+ { "INN", "Innovent Systems, Inc." },
+ { "INO", "Innolab Pte Ltd" },
+ { "INP", "Interphase Corporation" },
+ { "INS", "Ines GmbH" },
+ { "INT", "Interphase Corporation" },
+ { "INU", "Inovatec S.p.A." },
+ { "INV", "Inviso, Inc." },
+ { "INX", "Communications Supply Corporation (A division of WESCO)" },
+ { "INZ", "Best Buy" },
+ { "IOA", "CRE Technology Corporation" },
+ { "IOD", "I-O Data Device Inc" },
+ { "IOM", "Iomega" },
+ { "ION", "Inside Out Networks" },
+ { "IOS", "i-O Display System" },
+ { "IOT", "I/OTech Inc" },
+ { "IPC", "IPC Corporation" },
{ "IPD", "Industrial Products Design, Inc." },
- { "FMI", "Fujitsu Microelect Inc" },
- { "FMA", "Fast Multimedia AG" },
- { "MIT", "MCM Industrial Technology GmbH" },
- { "RII", "Racal Interlan Inc" },
- { "PDN", "AT&T Paradyne" },
- { "TRU", "Aashima Technology B.V." },
- { "BEI", "Beckworth Enterprises Inc" },
- { "RSS", "Rockwell Semiconductor Systems" },
- { "SHR", "Digital Discovery" },
- { "CDT", "IBM Corporation" },
- { "TKC", "Taiko Electric Works.LTD" },
+ { "IPI", "Intelligent Platform Management Interface (IPMI) forum (Intel, HP, NEC, Dell)" },
+ { "IPM", "IPM Industria Politecnica Meridionale SpA" },
+ { "IPN", "Performance Technologies" },
+ { "IPP", "IP Power Technologies GmbH" },
+ { "IPR", "Ithaca Peripherals" },
+ { "IPS", "IPS, Inc. (Intellectual Property Solutions, Inc.)" },
+ { "IPT", "International Power Technologies" },
+ { "IPW", "IPWireless, Inc" },
+ { "IQI", "IneoQuest Technologies, Inc" },
+ { "IQT", "IMAGEQUEST Co., Ltd" },
+ { "IRD", "IRdata" },
+ { "ISA", "Symbol Technologies" },
+ { "ISC", "Id3 Semiconductors" },
+ { "ISG", "Insignia Solutions Inc" },
+ { "ISI", "Interface Solutions" },
+ { "ISL", "Isolation Systems" },
+ { "ISM", "Image Stream Medical" },
+ { "ISP", "IntreSource Systems Pte Ltd" },
+ { "ISR", "INSIS Co., LTD." },
+ { "ISS", "ISS Inc" },
+ { "IST", "Intersolve Technologies" },
+ { "ISY", "International Integrated Systems,Inc.(IISI)" },
+ { "ITA", "Itausa Export North America" },
+ { "ITC", "Intercom Inc" },
+ { "ITD", "Internet Technology Corporation" },
+ { "ITE", "Integrated Tech Express Inc" },
+ { "ITK", "ITK Telekommunikation AG" },
+ { "ITL", "Inter-Tel" },
{ "ITM", "ITM inc." },
- { "QUE", "Questra Consulting" },
- { "CMR", "Cambridge Research Systems Ltd" },
- { "LCC", "LCI" },
- { "MDO", "Panasonic" },
- { "IEC", "Interlace Engineering Corporation" },
- { "DPL", "Digital Projection Limited" },
- { "INV", "Inviso, Inc." },
+ { "ITN", "The NTI Group" },
+ { "ITP", "IT-PRO Consulting und Systemhaus GmbH" },
+ { "ITR", "Infotronic America, Inc." },
+ { "ITS", "IDTECH" },
+ { "ITT", "I&T Telecom." },
+ { "ITX", "integrated Technology Express Inc" },
+ { "IUC", "ICSL" },
+ { "IVI", "Intervoice Inc" },
+ { "IVM", "Iiyama North America" },
+ { "IVS", "Intevac Photonics Inc." },
+ { "IWR", "Icuiti Corporation" },
+ { "IWX", "Intelliworxx, Inc." },
+ { "IXD", "Intertex Data AB" },
+ { "JAC", "Astec Inc" },
+ { "JAE", "Japan Aviation Electronics Industry, Limited" },
+ { "JAS", "Janz Automationssysteme AG" },
+ { "JAT", "Jaton Corporation" },
+ { "JAZ", "Carrera Computer Inc" },
+ { "JCE", "Jace Tech Inc" },
+ { "JDL", "Japan Digital Laboratory Co.,Ltd." },
+ { "JEN", "N-Vision" },
+ { "JET", "JET POWER TECHNOLOGY CO., LTD." },
+ { "JFX", "Jones Futurex Inc" },
+ { "JGD", "University College" },
+ { "JIC", "Jaeik Information & Communication Co., Ltd." },
+ { "JKC", "JVC KENWOOD Corporation" },
+ { "JMT", "Micro Technical Company Ltd" },
+ { "JPC", "JPC Technology Limited" },
+ { "JPW", "Wallis Hamilton Industries" },
+ { "JQE", "CNet Technical Inc" },
{ "JSD", "JS DigiTech, Inc" },
- { "TOE", "TOEI Electronics Co., Ltd." },
- { "HAY", "Hayes Microcomputer Products Inc" },
- { "SSJ", "Sankyo Seiki Mfg.co., Ltd" },
- { "NNC", "NNC" },
- { "PHE", "Philips Medical Systems Boeblingen GmbH" },
- { "MWI", "Multiwave Innovation Pte Ltd" },
- { "WYT", "Wooyoung Image & Information Co.,Ltd." },
- { "AIM", "AIMS Lab Inc" },
- { "CSS", "CSS Laboratories" },
- { "TRS", "Torus Systems Ltd" },
- { "ROK", "Rockwell International" },
- { "SXD", "Silex technology, Inc." },
- { "PHS", "Philips Communication Systems" },
- { "CLM", "CrystaLake Multimedia" },
- { "ALO", "Algolith Inc." },
- { "SIU", "Seiko Instruments USA Inc" },
- { "TUA", "T+A elektroakustik GmbH" },
- { "CTE", "Chunghwa Telecom Co., Ltd." },
- { "SDD", "Intrada-SDD Ltd" },
- { "RMT", "Roper Mobile" },
- { "SSP", "Spectrum Signal Proecessing Inc" },
- { "VTN", "VIDEOTRON CORP." },
- { "VAD", "Vaddio, LLC" },
- { "SFT", "Mikroforum Ring 3" },
- { "DGK", "DugoTech Co., LTD" },
- { "ACH", "Archtek Telecom Corporation" },
- { "ABT", "Anchor Bay Technologies, Inc." },
- { "STC", "STAC Electronics" },
- { "DRS", "DRS Defense Solutions, LLC" },
- { "OQI", "Oksori Company Ltd" },
- { "IMT", "Inmax Technology Corporation" },
- { "ENE", "ENE Technology Inc." },
- { "WBS", "WB Systemtechnik GmbH" },
- { "PRC", "PerComm" },
- { "PSC", "Philips Semiconductors" },
- { "RJS", "Advanced Engineering" },
- { "STS", "SITECSYSTEM CO., LTD." },
- { "LAV", "Lava Computer MFG Inc" },
- { "RCH", "Reach Technology Inc" },
- { "DWE", "Daewoo Electronics Company Ltd" },
- { "KTC", "Kingston Tech Corporation" },
- { "GLS", "Gadget Labs LLC" },
- { "COS", "CoStar Corporation" },
- { "SBI", "SMART Technologies Inc." },
- { "ATP", "Alpha-Top Corporation" },
- { "DQB", "Datacube Inc" },
- { "INN", "Innovent Systems, Inc." },
- { "DNT", "Dr. Neuhous Telekommunikation GmbH" },
+ { "JSI", "Jupiter Systems, Inc." },
+ { "JSK", "SANKEN ELECTRIC CO., LTD" },
+ { "JTS", "JS Motorsports" },
+ { "JTY", "jetway security micro,inc" },
+ { "JUK", "Janich & Klass Computertechnik GmbH" },
+ { "JUP", "Jupiter Systems" },
+ { "JVC", "JVC" },
+ { "JWD", "Video International Inc." },
+ { "JWL", "Jewell Instruments, LLC" },
+ { "JWS", "JWSpencer & Co." },
+ { "JWY", "Jetway Information Co., Ltd" },
+ { "KAR", "Karna" },
+ { "KBI", "Kidboard Inc" },
+ { "KBL", "Kobil Systems GmbH" },
+ { "KCD", "Chunichi Denshi Co.,LTD." },
+ { "KCL", "Keycorp Ltd" },
+ { "KDE", "KDE" },
+ { "KDK", "Kodiak Tech" },
+ { "KDM", "Korea Data Systems Co., Ltd." },
+ { "KDS", "KDS USA" },
+ { "KDT", "KDDI Technology Corporation" },
+ { "KEC", "Kyushu Electronics Systems Inc" },
+ { "KEM", "Kontron Embedded Modules GmbH" },
+ { "KES", "Kesa Corporation" },
+ { "KEY", "Key Tech Inc" },
+ { "KFC", "SCD Tech" },
+ { "KFE", "Komatsu Forest" },
{ "KFX", "Kofax Image Products" },
- { "APE", "Alpine Electronics, Inc." },
- { "DSM", "DSM Digital Services GmbH" },
- { "RES", "ResMed Pty Ltd" },
- { "HMX", "HUMAX Co., Ltd." },
- { "PCW", "Pacific CommWare Inc" },
+ { "KGL", "KEISOKU GIKEN Co.,Ltd." },
+ { "KIS", "KiSS Technology A/S" },
+ { "KMC", "Mitsumi Company Ltd" },
+ { "KME", "KIMIN Electronics Co., Ltd." },
+ { "KML", "Kensington Microware Ltd" },
+ { "KNC", "Konica corporation" },
+ { "KNX", "Nutech Marketing PTL" },
+ { "KOB", "Kobil Systems GmbH" },
+ { "KOD", "Eastman Kodak Company" },
+ { "KOE", "KOLTER ELECTRONIC" },
+ { "KOL", "Kollmorgen Motion Technologies Group" },
+ { "KOU", "KOUZIRO Co.,Ltd." },
+ { "KOW", "KOWA Company,LTD." },
+ { "KPC", "King Phoenix Company" },
+ { "KRL", "Krell Industries Inc." },
+ { "KRM", "Kroma Telecom" },
+ { "KRY", "Kroy LLC" },
+ { "KSC", "Kinetic Systems Corporation" },
+ { "KSL", "Karn Solutions Ltd." },
+ { "KSX", "King Tester Corporation" },
+ { "KTC", "Kingston Tech Corporation" },
+ { "KTD", "Takahata Electronics Co.,Ltd." },
+ { "KTE", "K-Tech" },
+ { "KTG", "Kayser-Threde GmbH" },
+ { "KTI", "Konica Technical Inc" },
+ { "KTK", "Key Tronic Corporation" },
+ { "KTN", "Katron Tech Inc" },
+ { "KUR", "Kurta Corporation" },
+ { "KVA", "Kvaser AB" },
+ { "KVX", "KeyView" },
+ { "KWD", "Kenwood Corporation" },
{ "KYC", "Kyocera Corporation" },
- { "VSN", "Ingram Macrotron" },
- { "SNT", "SuperNet Inc" },
- { "TEL", "Promotion and Display Technology Ltd." },
- { "IFX", "Infineon Technologies AG" },
- { "PVC", "DO NOT USE - PVC" },
- { "JKC", "JVC KENWOOD Corporation" },
- { "MSV", "Mosgi Corporation" },
- { "BUR", "Bernecker & Rainer Ind-Eletronik GmbH" },
- { "PTA", "PAR Tech Inc." },
- { "GGL", "Google Inc." },
- { "COM", "Comtrol Corporation" },
- { "JEN", "N-Vision" },
- { "AMP", "AMP Inc" },
- { "HDI", "HD-INFO d.o.o." },
- { "BOE", "BOE" },
- { "ICM", "Intracom SA" },
- { "ADD", "Advanced Peripheral Devices Inc" },
- { "PRI", "Priva Hortimation BV" },
- { "ANL", "Analogix Semiconductor, Inc" },
- { "AVO", "Avocent Corporation" },
+ { "KYE", "KYE Syst Corporation" },
+ { "KYK", "Samsung Electronics America Inc" },
+ { "KZI", "K-Zone International co. Ltd." },
+ { "KZN", "K-Zone International" },
+ { "LAB", "ACT Labs Ltd" },
+ { "LAC", "LaCie" },
+ { "LAF", "Microline" },
+ { "LAG", "Laguna Systems" },
+ { "LAN", "Sodeman Lancom Inc" },
+ { "LAS", "LASAT Comm. A/S" },
+ { "LAV", "Lava Computer MFG Inc" },
+ { "LBO", "Lubosoft" },
+ { "LCC", "LCI" },
+ { "LCD", "Toshiba Matsushita Display Technology Co., Ltd" },
+ { "LCE", "La Commande Electronique" },
+ { "LCI", "Lite-On Communication Inc" },
+ { "LCM", "Latitude Comm." },
+ { "LCN", "LEXICON" },
+ { "LCS", "Longshine Electronics Company" },
+ { "LCT", "Labcal Technologies" },
+ { "LDT", "LogiDataTech Electronic GmbH" },
+ { "LEC", "Lectron Company Ltd" },
+ { "LED", "Long Engineering Design Inc" },
{ "LEG", "Legerity, Inc" },
- { "DTE", "Dimension Technologies, Inc." },
- { "WPA", "Matsushita Communication Industrial Co., Ltd." },
- { "OLV", "Olitec S.A." },
- { "RNB", "Rainbow Technologies" },
- { "LVI", "LVI Low Vision International AB" },
- { "LOC", "Locamation B.V." },
- { "TGC", "Toshiba Global Commerce Solutions, Inc." },
- { "STI", "Smart Tech Inc" },
- { "TLF", "Teleforce.,co,ltd" },
- { "PLC", "Pro-Log Corporation" },
- { "HSD", "HannStar Display Corp" },
- { "ONE", "Oneac Corporation" },
- { "CLE", "Classe Audio" },
- { "MCI", "Micronics Computers" },
- { "VTG", "Voice Technologies Group Inc" },
- { "VTI", "VLSI Tech Inc" },
- { "DAI", "DAIS SET Ltd." },
- { "UNM", "Unisys Corporation" },
- { "MCQ", "Mat's Computers" },
- { "IPC", "IPC Corporation" },
- { "ADE", "Arithmos, Inc." },
- { "PON", "Perpetual Technologies, LLC" },
- { "EXA", "Exabyte" },
- { "CHD", "ChangHong Electric Co.,Ltd" },
- { "FDT", "Fujitsu Display Technologies Corp." },
- { "DBL", "Doble Engineering Company" },
- { "CTP", "Computer Technology Corporation" },
- { "CLD", "COMMAT L.t.d." },
- { "BLI", "Busicom" },
- { "FRS", "South Mountain Technologies, LTD" },
- { "CDD", "Convergent Data Devices" },
- { "SHT", "Shin Ho Tech" },
- { "EPC", "Empac" },
- { "RDS", "Radius Inc" },
- { "NEX", "Nexgen Mediatech Inc.," },
- { "AGC", "Beijing Aerospace Golden Card Electronic Engineering Co.,Ltd." },
- { "MCP", "Magni Systems Inc" },
- { "WMO", "Westermo Teleindustri AB" },
- { "NMX", "Neomagic" },
- { "BDS", "Barco Display Systems" },
- { "RIV", "Rivulet Communications" },
- { "TRA", "TriTech Microelectronics International" },
- { "CYX", "Cyrix Corporation" },
- { "TCM", "3Com Corporation" },
- { "ZYP", "Zypcom Inc" },
- { "VIB", "Tatung UK Ltd" },
- { "IEI", "Interlink Electronics" },
- { "BGB", "Barco Graphics N.V" },
- { "ISP", "IntreSource Systems Pte Ltd" },
- { "BGT", "Budzetron Inc" },
- { "DPS", "Digital Processing Systems" },
- { "SSS", "S3 Inc" },
- { "AXB", "Adrienne Electronics Corporation" },
- { "HKA", "HONKO MFG. CO., LTD." },
- { "TPK", "TOPRE CORPORATION" },
- { "NPI", "Network Peripherals Inc" },
+ { "LEN", "Lenovo Group Limited" },
+ { "LEO", "First International Computer Inc" },
+ { "LEX", "Lexical Ltd" },
+ { "LGC", "Logic Ltd" },
+ { "LGI", "Logitech Inc" },
+ { "LGS", "LG Semicom Company Ltd" },
+ { "LGX", "Lasergraphics, Inc." },
+ { "LHA", "Lars Haagh ApS" },
+ { "LHE", "Lung Hwa Electronics Company Ltd" },
+ { "LHT", "Lighthouse Technologies Limited" },
+ { "LIN", "Lenovo Beijing Co. Ltd." },
+ { "LIP", "Linked IP GmbH" },
+ { "LIT", "Lithics Silicon Technology" },
+ { "LJX", "Datalogic Corporation" },
+ { "LKM", "Likom Technology Sdn. Bhd." },
+ { "LLL", "L-3 Communications" },
+ { "LMG", "Lucent Technologies" },
+ { "LMI", "Lexmark Int'l Inc" },
{ "LMP", "Leda Media Products" },
- { "MAI", "Mutoh America Inc" },
- { "ATX", "Athenix Corporation" },
- { "MVM", "SOBO VISION" },
- { "ALI", "Acer Labs" },
- { "HPR", "H.P.R. Electronics GmbH" },
- { "BIL", "Billion Electric Company Ltd" },
- { "CRO", "Extraordinary Technologies PTY Limited" },
- { "KTG", "Kayser-Threde GmbH" },
- { "SCI", "System Craft" },
- { "MVD", "Microvitec PLC" },
- { "IST", "Intersolve Technologies" },
- { "ICD", "ICD Inc" },
- { "PDS", "PD Systems International Ltd" },
- { "CPQ", "Compaq Computer Company" },
- { "QCL", "Quadrant Components Inc" },
- { "PRA", "PRO/AUTOMATION" },
+ { "LMT", "Laser Master" },
+ { "LND", "Land Computer Company Ltd" },
+ { "LNK", "Link Tech Inc" },
+ { "LNR", "Linear Systems Ltd." },
+ { "LNT", "LANETCO International" },
+ { "LNV", "Lenovo" },
+ { "LOC", "Locamation B.V." },
+ { "LOE", "Loewe Opta GmbH" },
+ { "LOG", "Logicode Technology Inc" },
+ { "LOL", "Litelogic Operations Ltd" },
+ { "LPE", "El-PUSK Co., Ltd." },
+ { "LPI", "Design Technology" },
+ { "LPL", "LG Philips" },
+ { "LSC", "LifeSize Communications" },
+ { "LSD", "Intersil Corporation" },
+ { "LSI", "Loughborough Sound Images" },
+ { "LSJ", "LSI Japan Company Ltd" },
+ { "LSL", "Logical Solutions" },
+ { "LSY", "LSI Systems Inc" },
+ { "LTC", "Labtec Inc" },
+ { "LTI", "Jongshine Tech Inc" },
+ { "LTK", "Lucidity Technology Company Ltd" },
+ { "LTN", "Litronic Inc" },
+ { "LTS", "LTS Scale LLC" },
+ { "LTV", "Leitch Technology International Inc." },
+ { "LTW", "Lightware, Inc" },
+ { "LUC", "Lucent Technologies" },
+ { "LUM", "Lumagen, Inc." },
+ { "LUX", "Luxxell Research Inc" },
+ { "LVI", "LVI Low Vision International AB" },
+ { "LWC", "Labway Corporation" },
+ { "LWR", "Lightware Visual Engineering" },
+ { "LWW", "Lanier Worldwide" },
+ { "LXC", "LXCO Technologies AG" },
+ { "LXN", "Luxeon" },
+ { "LXS", "ELEA CardWare" },
+ { "LZX", "Lightwell Company Ltd" },
{ "MAC", "MAC System Company Ltd" },
- { "TOP", "Orion Communications Co., Ltd." },
- { "AGT", "Agilent Technologies" },
- { "SWI", "Sierra Wireless Inc." },
- { "ATT", "AT&T" },
+ { "MAD", "Xedia Corporation" },
+ { "MAE", "Maestro Pty Ltd" },
+ { "MAG", "MAG InnoVision" },
+ { "MAI", "Mutoh America Inc" },
+ { "MAL", "Meridian Audio Ltd" },
+ { "MAN", "LGIC" },
+ { "MAS", "Mass Inc." },
+ { "MAT", "Matsushita Electric Ind. Company Ltd" },
+ { "MAX", "Rogen Tech Distribution Inc" },
+ { "MAY", "Maynard Electronics" },
+ { "MAZ", "MAZeT GmbH" },
+ { "MBC", "MBC" },
+ { "MBD", "Microbus PLC" },
+ { "MBM", "Marshall Electronics" },
+ { "MBV", "Moreton Bay" },
+ { "MCA", "American Nuclear Systems Inc" },
+ { "MCC", "Micro Industries" },
+ { "MCD", "McDATA Corporation" },
+ { "MCE", "Metz-Werke GmbH & Co KG" },
+ { "MCG", "Motorola Computer Group" },
+ { "MCI", "Micronics Computers" },
{ "MCL", "Motorola Communications Israel" },
- { "NCS", "Northgate Computer Systems" },
- { "RSX", "Rapid Tech Corporation" },
- { "ATV", "Office Depot, Inc." },
- { "MRD", "MicroDisplay Corporation" },
- { "SCH", "Schlumberger Cards" },
- { "ONW", "OPEN Networks Ltd" },
- { "DTC", "DTC Tech Corporation" },
- { "HYV", "Hynix Semiconductor" },
- { "WEL", "W-DEV" },
- { "AND", "Adtran Inc" },
- { "AMN", "Amimon LTD." },
- { "PXL", "The Moving Pixel Company" },
- { "ZCT", "ZeitControl cardsystems GmbH" },
- { "ALH", "AL Systems" },
- { "VCJ", "Victor Company of Japan, Limited" },
- { "COD", "CODAN Pty. Ltd." },
- { "TMM", "Time Management, Inc." },
- { "PPR", "PicPro" },
- { "INL", "InnoLux Display Corporation" },
- { "LTC", "Labtec Inc" },
- { "PNP", "Microsoft" },
- { "FIL", "Forefront Int'l Ltd" },
- { "OSR", "Oksori Company Ltd" },
- { "PEI", "PEI Electronics Inc" },
- { "EZP", "Storm Technology" },
- { "TCE", "Century Corporation" },
- { "KAR", "Karna" },
- { "ALS", "Texas Advanced optoelectronics Solutions, Inc" },
- { "COI", "Codec Inc." },
- { "NRT", "Beijing Northern Radiantelecom Co." },
- { "FTR", "Mediasonic" },
- { "SUN", "Sun Electronics Corporation" },
- { "OZO", "Tribe Computer Works Inc" },
+ { "MCM", "Metricom Inc" },
+ { "MCN", "Micron Electronics Inc" },
{ "MCO", "Motion Computing Inc." },
- { "UBI", "Ungermann-Bass Inc" },
- { "ZNI", "Zetinet Inc" },
- { "FUN", "sisel muhendislik" },
- { "RMP", "Research Machines" },
- { "DGT", "The Dearborn Group" },
- { "SPX", "Simplex Time Recorder Co." },
- { "COR", "Corollary Inc" },
- { "AMX", "AMX LLC" },
- { "AKY", "Askey Computer Corporation" },
- { "RAR", "Raritan, Inc." },
- { "VDS", "Vidisys GmbH & Company" },
- { "SCL", "Sigmacom Co., Ltd." },
- { "KSL", "Karn Solutions Ltd." },
- { "ACK", "Acksys" },
- { "NWS", "Newisys, Inc." },
- { "TRX", "Trex Enterprises" },
- { "BOI", "NINGBO BOIGLE DIGITAL TECHNOLOGY CO.,LTD" },
- { "NTT", "NTT Advanced Technology Corporation" },
- { "GUZ", "Guzik Technical Enterprises" },
- { "MDY", "Microdyne Inc" },
- { "EDM", "EDMI" },
- { "DTI", "Diversified Technology, Inc." },
- { "MMI", "Multimax" },
- { "SCB", "SeeCubic B.V." },
- { "UPS", "Systems Enhancement" },
- { "AKB", "Akebia Ltd" },
- { "NBT", "NingBo Bestwinning Technology CO., Ltd" },
- { "TCD", "Taicom Data Systems Co., Ltd." },
- { "XMM", "C3PO S.L." },
- { "OIM", "Option International" },
- { "DAV", "Davicom Semiconductor Inc" },
- { "CKJ", "Carina System Co., Ltd." },
- { "ATD", "Alpha Telecom Inc" },
- { "XQU", "SHANGHAI SVA-DAV ELECTRONICS CO., LTD" },
- { "KOL", "Kollmorgen Motion Technologies Group" },
- { "HWA", "Harris Canada Inc" },
- { "INE", "Inventec Electronics (M) Sdn. Bhd." },
- { "ORN", "ORION ELECTRIC CO., LTD." },
- { "KES", "Kesa Corporation" },
- { "CRC", "CONRAC GmbH" },
- { "AXT", "Axtend Technologies Inc" },
- { "NAX", "Naxos Tecnologia" },
- { "DAN", "Danelec Marine A/S" },
- { "ADP", "Adaptec Inc" },
- { "ICA", "ICA Inc" },
- { "AGL", "Argolis" },
- { "ECC", "ESSential Comm. Corporation" },
- { "AWS", "Wave Systems" },
- { "APN", "Appian Tech Inc" },
- { "DGI", "DIGI International" },
+ { "MCP", "Magni Systems Inc" },
+ { "MCQ", "Mat's Computers" },
+ { "MCR", "Marina Communicaitons" },
{ "MCS", "Micro Computer Systems" },
- { "ITA", "Itausa Export North America" },
- { "CII", "Cromack Industries Inc" },
- { "IPS", "IPS, Inc. (Intellectual Property Solutions, Inc.)" },
- { "KOE", "KOLTER ELECTRONIC" },
+ { "MCT", "Microtec" },
+ { "MDA", "Media4 Inc" },
+ { "MDC", "Midori Electronics" },
+ { "MDD", "MODIS" },
+ { "MDG", "Madge Networks" },
+ { "MDI", "Micro Design Inc" },
+ { "MDK", "Mediatek Corporation" },
+ { "MDO", "Panasonic" },
+ { "MDR", "Medar Inc" },
+ { "MDS", "Micro Display Systems Inc" },
+ { "MDT", "Magus Data Tech" },
+ { "MDV", "MET Development Inc" },
+ { "MDX", "MicroDatec GmbH" },
+ { "MDY", "Microdyne Inc" },
+ { "MEC", "Mega System Technologies Inc" },
+ { "MED", "Messeltronik Dresden GmbH" },
+ { "MEE", "Mitsubishi Electric Engineering Co., Ltd." },
+ { "MEG", "Abeam Tech Ltd" },
+ { "MEI", "Panasonic Industry Company" },
+ { "MEJ", "Mac-Eight Co., LTD." },
+ { "MEL", "Mitsubishi Electric Corporation" },
+ { "MEN", "MEN Mikroelectronik Nueruberg GmbH" },
{ "MEP", "Meld Technology" },
- { "IMA", "Imagraph" },
- { "DDV", "Delta Information Systems, Inc" },
- { "GML", "General Information Systems" },
- { "SSC", "Sierra Semiconductor Inc" },
- { "WNX", "Wincor Nixdorf International GmbH" },
- { "ABD", "Allen Bradley Company" },
- { "CMS", "CompuMaster Srl" },
- { "INK", "Indtek Co., Ltd." },
- { "DTT", "Design & Test Technology, Inc." },
+ { "MEQ", "Matelect Ltd." },
+ { "MET", "Metheus Corporation" },
+ { "MEX", "MSC Vertriebs GmbH" },
+ { "MFG", "MicroField Graphics Inc" },
+ { "MFI", "Micro Firmware" },
+ { "MFR", "MediaFire Corp." },
{ "MGA", "Mega System Technologies, Inc." },
- { "SMO", "STMicroelectronics" },
- { "SSI", "S-S Technology Inc" },
- { "CIR", "Cirrus Logic Inc" },
- { "EKC", "Eastman Kodak Company" },
- { "LNR", "Linear Systems Ltd." },
- { "VCM", "Vector Magnetics, LLC" },
- { "HKG", "Josef Heim KG" },
- { "ORG", "ORGA Kartensysteme GmbH" },
- { "ELG", "Elmeg GmbH Kommunikationstechnik" },
- { "NSI", "NISSEI ELECTRIC CO.,LTD" },
- { "RDM", "Tremon Enterprises Company Ltd" },
- { "HAI", "Haivision Systems Inc." },
- { "CIC", "Comm. Intelligence Corporation" },
- { "LTS", "LTS Scale LLC" },
- { "SAS", "Stores Automated Systems Inc" },
- { "OEC", "ORION ELECTRIC CO.,LTD" },
- { "BRG", "Bridge Information Co., Ltd" },
- { "SQT", "Sequent Computer Systems Inc" },
- { "CCI", "Cache" },
- { "PRX", "Proxima Corporation" },
- { "ADR", "Nasa Ames Research Center" },
- { "SNW", "Snell & Wilcox" },
- { "CDI", "Concept Development Inc" },
- { "SEA", "Seanix Technology Inc." },
- { "STY", "SDS Technologies" },
- { "PCA", "Philips BU Add On Card" },
- { "NYC", "nakayo telecommunications,inc." },
- { "JMT", "Micro Technical Company Ltd" },
+ { "MGC", "Mentor Graphics Corporation" },
+ { "MGE", "Schneider Electric S.A." },
+ { "MGL", "M-G Technology Ltd" },
+ { "MGT", "Megatech R & D Company" },
+ { "MIC", "Micom Communications Inc" },
+ { "MID", "miro Displays" },
+ { "MII", "Mitec Inc" },
+ { "MIL", "Marconi Instruments Ltd" },
+ { "MIM", "Mimio – A Newell Rubbermaid Company" },
+ { "MIN", "Minicom Digital Signage" },
+ { "MIP", "micronpc.com" },
+ { "MIR", "Miro Computer Prod." },
+ { "MIS", "Modular Industrial Solutions Inc" },
+ { "MIT", "MCM Industrial Technology GmbH" },
+ { "MJI", "MARANTZ JAPAN, INC." },
+ { "MJS", "MJS Designs" },
+ { "MKC", "Media Tek Inc." },
+ { "MKT", "MICROTEK Inc." },
+ { "MKV", "Trtheim Technology" },
+ { "MLD", "Deep Video Imaging Ltd" },
+ { "MLG", "Micrologica AG" },
+ { "MLI", "McIntosh Laboratory Inc." },
+ { "MLM", "Millennium Engineering Inc" },
+ { "MLN", "Mark Levinson" },
+ { "MLS", "Milestone EPE" },
+ { "MLX", "Mylex Corporation" },
+ { "MMA", "Micromedia AG" },
+ { "MMD", "Micromed Biotecnologia Ltd" },
+ { "MMF", "Minnesota Mining and Manufacturing" },
+ { "MMI", "Multimax" },
+ { "MMM", "Electronic Measurements" },
+ { "MMN", "MiniMan Inc" },
+ { "MMS", "MMS Electronics" },
+ { "MNC", "Mini Micro Methods Ltd" },
+ { "MNL", "Monorail Inc" },
+ { "MNP", "Microcom" },
+ { "MOD", "Modular Technology" },
+ { "MOM", "Momentum Data Systems" },
+ { "MOS", "Moses Corporation" },
+ { "MOT", "Motorola UDS" },
+ { "MPC", "M-Pact Inc" },
+ { "MPI", "Mediatrix Peripherals Inc" },
+ { "MPJ", "Microlab" },
+ { "MPL", "Maple Research Inst. Company Ltd" },
+ { "MPN", "Mainpine Limited" },
+ { "MPS", "mps Software GmbH" },
+ { "MPX", "Micropix Technologies, Ltd." },
+ { "MQP", "MultiQ Products AB" },
+ { "MRA", "Miranda Technologies Inc" },
+ { "MRC", "Marconi Simulation & Ty-Coch Way Training" },
+ { "MRD", "MicroDisplay Corporation" },
+ { "MRK", "Maruko & Company Ltd" },
+ { "MRL", "Miratel" },
+ { "MRO", "Medikro Oy" },
+ { "MRT", "Merging Technologies" },
+ { "MSA", "Micro Systemation AB" },
+ { "MSC", "Mouse Systems Corporation" },
+ { "MSD", "Datenerfassungs- und Informationssysteme" },
+ { "MSF", "M-Systems Flash Disk Pioneers" },
+ { "MSG", "MSI GmbH" },
+ { "MSH", "Microsoft" },
+ { "MSI", "Microstep" },
+ { "MSK", "Megasoft Inc" },
+ { "MSL", "MicroSlate Inc." },
+ { "MSM", "Advanced Digital Systems" },
+ { "MSP", "Mistral Solutions [P] Ltd." },
+ { "MSR", "MASPRO DENKOH Corp." },
+ { "MST", "MS Telematica" },
+ { "MSU", "motorola" },
+ { "MSV", "Mosgi Corporation" },
+ { "MSX", "Micomsoft Co., Ltd." },
+ { "MSY", "MicroTouch Systems Inc" },
+ { "MTB", "Media Technologies Ltd." },
+ { "MTC", "Mars-Tech Corporation" },
{ "MTD", "MindTech Display Co. Ltd" },
+ { "MTE", "MediaTec GmbH" },
+ { "MTH", "Micro-Tech Hearing Instruments" },
+ { "MTI", "Motorola Inc." },
+ { "MTK", "Microtek International Inc." },
+ { "MTL", "Mitel Corporation" },
+ { "MTM", "Motium" },
+ { "MTN", "Mtron Storage Technology Co., Ltd." },
+ { "MTR", "Mitron computer Inc" },
+ { "MTS", "Multi-Tech Systems" },
+ { "MTU", "Mark of the Unicorn Inc" },
+ { "MTX", "Matrox" },
+ { "MUD", "Multi-Dimension Institute" },
+ { "MUK", "mainpine limited" },
+ { "MVD", "Microvitec PLC" },
+ { "MVI", "Media Vision Inc" },
+ { "MVM", "SOBO VISION" },
+ { "MVS", "Microvision" },
+ { "MVX", "COM 1" },
+ { "MWI", "Multiwave Innovation Pte Ltd" },
+ { "MWR", "mware" },
+ { "MWY", "Microway Inc" },
+ { "MXD", "MaxData Computer GmbH & Co.KG" },
+ { "MXI", "Macronix Inc" },
+ { "MXL", "Hitachi Maxell, Ltd." },
+ { "MXP", "Maxpeed Corporation" },
+ { "MXT", "Maxtech Corporation" },
+ { "MXV", "MaxVision Corporation" },
+ { "MYA", "Monydata" },
+ { "MYR", "Myriad Solutions Ltd" },
+ { "MYX", "Micronyx Inc" },
+ { "NAC", "Ncast Corporation" },
+ { "NAD", "NAD Electronics" },
+ { "NAK", "Nakano Engineering Co.,Ltd." },
+ { "NAL", "Network Alchemy" },
+ { "NAT", "NaturalPoint Inc." },
+ { "NAV", "Navigation Corporation" },
+ { "NAX", "Naxos Tecnologia" },
+ { "NBL", "N*Able Technologies Inc" },
+ { "NBS", "National Key Lab. on ISN" },
+ { "NBT", "NingBo Bestwinning Technology CO., Ltd" },
+ { "NCA", "Nixdorf Company" },
+ { "NCC", "NCR Corporation" },
+ { "NCE", "Norcent Technology, Inc." },
+ { "NCI", "NewCom Inc" },
+ { "NCL", "NetComm Ltd" },
+ { "NCR", "NCR Electronics" },
+ { "NCS", "Northgate Computer Systems" },
+ { "NCT", "NEC CustomTechnica, Ltd." },
+ { "NDC", "National DataComm Corporaiton" },
+ { "NDI", "National Display Systems" },
+ { "NDK", "Naitoh Densei CO., LTD." },
+ { "NDL", "Network Designers" },
+ { "NDS", "Nokia Data" },
+ { "NEC", "NEC Corporation" },
+ { "NEO", "NEO TELECOM CO.,LTD." },
+ { "NET", "Mettler Toledo" },
+ { "NEU", "NEUROTEC - EMPRESA DE PESQUISA E DESENVOLVIMENTO EM BIOMEDICINA" },
+ { "NEX", "Nexgen Mediatech Inc.," },
+ { "NFC", "BTC Korea Co., Ltd" },
+ { "NFS", "Number Five Software" },
+ { "NGC", "Network General" },
+ { "NGS", "A D S Exports" },
+ { "NHT", "Vinci Labs" },
+ { "NIC", "National Instruments Corporation" },
+ { "NIS", "Nissei Electric Company" },
+ { "NIT", "Network Info Technology" },
+ { "NIX", "Seanix Technology Inc" },
+ { "NLC", "Next Level Communications" },
+ { "NME", "Navico, Inc." },
+ { "NMP", "Nokia Mobile Phones" },
+ { "NMS", "Natural Micro System" },
+ { "NMV", "NEC-Mitsubishi Electric Visual Systems Corporation" },
+ { "NMX", "Neomagic" },
+ { "NNC", "NNC" },
+ { "NOE", "NordicEye AB" },
+ { "NOI", "North Invent A/S" },
+ { "NOK", "Nokia Display Products" },
+ { "NOR", "Norand Corporation" },
+ { "NOT", "Not Limited Inc" },
+ { "NPI", "Network Peripherals Inc" },
+ { "NRL", "U.S. Naval Research Lab" },
+ { "NRT", "Beijing Northern Radiantelecom Co." },
+ { "NRV", "Taugagreining hf" },
+ { "NSC", "National Semiconductor Corporation" },
+ { "NSI", "NISSEI ELECTRIC CO.,LTD" },
{ "NSP", "Nspire System Inc." },
- { "DSD", "DS Multimedia Pte Ltd" },
- { "PBI", "Pitney Bowes" },
- { "ARO", "Poso International B.V." },
- { "TTE", "TTE, Inc." },
- { "DDA", "DA2 Technologies Corporation" },
- { "MAS", "Mass Inc." },
- { "LAC", "LaCie" },
- { "CRX", "Cyrix Corporation" },
- { "EMO", "ELMO COMPANY, LIMITED" },
- { "OSP", "OPTI-UPS Corporation" },
- { "GED", "General Dynamics C4 Systems" },
- { "PPI", "Practical Peripherals" },
- { "VPI", "Video Products Inc" },
- { "TOS", "Toshiba Corporation" },
- { "ASL", "AccuScene Corporation Ltd" },
- { "ANT", "Ace CAD Enterprise Company Ltd" },
- { "GRV", "Advanced Gravis" },
- { "ANO", "Anorad Corporation" },
- { "LNK", "Link Tech Inc" },
- { "DIG", "Digicom S.p.A." },
- { "ALC", "Altec Corporation" },
- { "IAI", "Integration Associates, Inc." },
- { "APG", "Horner Electric Inc" },
- { "TWK", "TOWITOKO electronics GmbH" },
- { "BRI", "Boca Research Inc" },
- { "SVS", "SVSI" },
- { "QCI", "Quanta Computer Inc" },
- { "MDD", "MODIS" },
- { "PDT", "PDTS - Prozessdatentechnik und Systeme" },
- { "IMP", "Impression Products Incorporated" },
- { "EXI", "Exide Electronics" },
- { "WNV", "Winnov L.P." },
- { "ALG", "Realtek Semiconductor Corp." },
- { "ESA", "Elbit Systems of America" },
- { "OLC", "Olicom A/S" },
- { "DPX", "DpiX, Inc." },
- { "GSB", "NIPPONDENCHI CO,.LTD" },
- { "MCA", "American Nuclear Systems Inc" },
- { "EST", "Embedded Solution Technology" },
- { "ADX", "Adax Inc" },
- { "MSA", "Micro Systemation AB" },
- { "HDV", "Holografika kft." },
- { "GIP", "GI Provision Ltd" },
- { "XTN", "X-10 (USA) Inc" },
- { "VEC", "Vector Informatik GmbH" },
- { "DTN", "Datang Telephone Co" },
- { "CST", "CSTI Inc" },
- { "ECO", "Echo Speech Corporation" },
- { "TDD", "Tandberg Data Display AS" },
+ { "NSS", "Newport Systems Solutions" },
+ { "NST", "Network Security Technology Co" },
+ { "NTC", "NeoTech S.R.L" },
+ { "NTI", "New Tech Int'l Company" },
+ { "NTL", "National Transcomm. Ltd" },
+ { "NTN", "Nuvoton Technology Corporation" },
+ { "NTR", "N-trig Innovative Technologies, Inc." },
+ { "NTS", "Nits Technology Inc." },
+ { "NTT", "NTT Advanced Technology Corporation" },
+ { "NTW", "Networth Inc" },
+ { "NTX", "Netaccess Inc" },
+ { "NUG", "NU Technology, Inc." },
+ { "NUI", "NU Inc." },
+ { "NVC", "NetVision Corporation" },
+ { "NVD", "Nvidia" },
+ { "NVI", "NuVision US, Inc." },
{ "NVL", "Novell Inc" },
- { "CHT", "Chunghwa Picture Tubes,LTD." },
- { "SCP", "Scriptel Corporation" },
- { "TMS", "Trident Microsystems Ltd" },
- { "ABO", "D-Link Systems Inc" },
- { "JTY", "jetway security micro,inc" },
- { "LSD", "Intersil Corporation" },
- { "SEP", "SEP Eletronica Ltda." },
- { "SHI", "Jiangsu Shinco Electronic Group Co., Ltd" },
- { "FTG", "FTG Data Systems" },
- { "ESN", "eSATURNUS" },
- { "DJE", "Capstone Visual Product Development" },
- { "BEC", "Elektro Beckhoff GmbH" },
- { "FVC", "First Virtual Corporation" },
- { "JUP", "Jupiter Systems" },
- { "XNT", "XN Technologies, Inc." },
- { "RTK", "DO NOT USE - RTK" },
- { "ACL", "Apricot Computers" },
- { "TAA", "Tandberg" },
- { "WIP", "Wipro Infotech" },
- { "KRL", "Krell Industries Inc." },
- { "INO", "Innolab Pte Ltd" },
- { "ELT", "Element Labs, Inc." },
- { "KTE", "K-Tech" },
- { "CVA", "Covia Inc." },
- { "SIC", "Sysmate Corporation" },
- { "STH", "Semtech Corporation" },
- { "ACD", "AWETA BV" },
- { "EHN", "Enhansoft" },
- { "VMI", "Vermont Microsystems" },
- { "TTC", "Telecommunications Techniques Corporation" },
- { "KYE", "KYE Syst Corporation" },
- { "QDI", "Quantum Data Incorporated" },
- { "ELL", "Electrosonic Ltd" },
- { "FLE", "ADTI Media, Inc" },
- { "KTD", "Takahata Electronics Co.,Ltd." },
- { "MAL", "Meridian Audio Ltd" },
- { "TRV", "Trivisio Prototyping GmbH" },
- { "TWH", "Twinhead International Corporation" },
- { "SYP", "SYPRO Co Ltd" },
- { "GCC", "GCC Technologies Inc" },
- { "POR", "Portalis LC" },
- { "PIM", "Prism, LLC" },
- { "MLX", "Mylex Corporation" },
+ { "NVT", "Navatek Engineering Corporation" },
+ { "NWC", "NW Computer Engineering" },
+ { "NWP", "NovaWeb Technologies Inc" },
+ { "NWS", "Newisys, Inc." },
+ { "NXC", "NextCom K.K." },
+ { "NXG", "Nexgen" },
+ { "NXP", "NXP Semiconductors bv." },
+ { "NXQ", "Nexiq Technologies, Inc." },
+ { "NXS", "Technology Nexus Secure Open Systems AB" },
+ { "NYC", "nakayo telecommunications,inc." },
+ { "OAK", "Oak Tech Inc" },
+ { "OAS", "Oasys Technology Company" },
+ { "OBS", "Optibase Technologies" },
+ { "OCD", "Macraigor Systems Inc" },
+ { "OCN", "Olfan" },
+ { "OCS", "Open Connect Solutions" },
+ { "ODM", "ODME Inc." },
+ { "ODR", "Odrac" },
+ { "OEC", "ORION ELECTRIC CO.,LTD" },
+ { "OEI", "Optum Engineering Inc." },
+ { "OIC", "Option Industrial Computers" },
+ { "OIM", "Option International" },
+ { "OIN", "Option International" },
+ { "OKI", "OKI Electric Industrial Company Ltd" },
+ { "OLC", "Olicom A/S" },
+ { "OLD", "Olidata S.p.A." },
+ { "OLI", "Olivetti" },
+ { "OLT", "Olitec S.A." },
+ { "OLV", "Olitec S.A." },
+ { "OLY", "OLYMPUS CORPORATION" },
+ { "OMC", "OBJIX Multimedia Corporation" },
+ { "OMN", "Omnitel" },
+ { "OMR", "Omron Corporation" },
+ { "ONE", "Oneac Corporation" },
+ { "ONK", "ONKYO Corporation" },
{ "ONL", "OnLive, Inc" },
- { "NIS", "Nissei Electric Company" },
- { "ISM", "Image Stream Medical" },
- { "EPS", "KEPS" },
- { "PAC", "Pacific Avionics Corporation" },
- { "AXC", "AXIOMTEK CO., LTD." },
- { "DYX", "Dynax Electronics (HK) Ltd" },
- { "WEB", "WebGear Inc" },
- { "RIT", "Ritech Inc" },
- { "INI", "Initio Corporation" },
- { "LBO", "Lubosoft" },
- { "PGM", "Paradigm Advanced Research Centre" },
+ { "ONS", "On Systems Inc" },
+ { "ONW", "OPEN Networks Ltd" },
+ { "ONX", "SOMELEC Z.I. Du Vert Galanta" },
+ { "OOS", "OSRAM" },
+ { "OPC", "Opcode Inc" },
+ { "OPI", "D.N.S. Corporation" },
+ { "OPP", "OPPO Digital, Inc." },
+ { "OPT", "OPTi Inc" },
+ { "OPV", "Optivision Inc" },
+ { "OQI", "Oksori Company Ltd" },
+ { "ORG", "ORGA Kartensysteme GmbH" },
+ { "ORI", "OSR Open Systems Resources, Inc." },
+ { "ORN", "ORION ELECTRIC CO., LTD." },
{ "OSA", "OSAKA Micro Computer, Inc." },
- { "SIN", "Singular Technology Co., Ltd." },
- { "CIN", "Citron GmbH" },
+ { "OSP", "OPTI-UPS Corporation" },
+ { "OSR", "Oksori Company Ltd" },
{ "OTB", "outsidetheboxstuff.com" },
- { "ARL", "Arlotto Comnet Inc" },
- { "HOB", "HOB Electronic GmbH" },
- { "QQQ", "Chuomusen Co., Ltd." },
- { "AXE", "D-Link Systems Inc" },
- { "CCC", "C-Cube Microsystems" },
- { "CPT", "cPATH" },
- { "SEM", "Samsung Electronics Company Ltd" },
- { "PVI", "Prime view international Co., Ltd" },
- { "TAT", "Teleliaison Inc" },
- { "SON", "Sony" },
- { "ITT", "I&T Telecom." },
- { "SLM", "Solomon Technology Corporation" },
- { "MAN", "LGIC" },
- { "AIX", "ALTINEX, INC." },
- { "ASP", "ASP Microelectronics Ltd" },
- { "VUT", "Vutrix (UK) Ltd" },
- { "MTE", "MediaTec GmbH" },
- { "UPP", "UPPI" },
- { "DCM", "DCM Data Products" },
- { "DYC", "Dycam Inc" },
- { "DAK", "Daktronics" },
- { "JAZ", "Carrera Computer Inc" },
- { "FOX", "HON HAI PRECISON IND.CO.,LTD." },
- { "UEI", "Universal Electronics Inc" },
- { "OPI", "D.N.S. Corporation" },
- { "CXT", "Conexant Systems" },
- { "VTK", "Viewteck Co., Ltd." },
- { "AVL", "Avalue Technology Inc." },
- { "TSI", "TeleVideo Systems" },
+ { "OTI", "Orchid Technology" },
+ { "OTM", "Optoma Corporation" },
+ { "OTT", "OPTO22, Inc." },
+ { "OUK", "OUK Company Ltd" },
+ { "OVR", "Oculus VR, Inc." },
+ { "OWL", "Mediacom Technologies Pte Ltd" },
+ { "OXU", "Oxus Research S.A." },
+ { "OYO", "Shadow Systems" },
+ { "OZC", "OZ Corporation" },
+ { "OZO", "Tribe Computer Works Inc" },
+ { "PAC", "Pacific Avionics Corporation" },
+ { "PAD", "Promotion and Display Technology Ltd." },
+ { "PAK", "Many CNC System Co., Ltd." },
+ { "PAM", "Peter Antesberger Messtechnik" },
{ "PAN", "The Panda Project" },
- { "CED", "Cambridge Electronic Design Ltd" },
- { "RUP", "Ups Manufactoring s.r.l." },
- { "MIP", "micronpc.com" },
- { "REM", "SCI Systems Inc." },
- { "NSS", "Newport Systems Solutions" },
- { "FBI", "Interface Corporation" },
- { "FER", "Ferranti Int'L" },
- { "DLG", "Digital-Logic GmbH" },
- { "TSY", "TouchSystems" },
+ { "PAR", "Parallan Comp Inc" },
+ { "PBI", "Pitney Bowes" },
+ { "PBL", "Packard Bell Electronics" },
+ { "PBN", "Packard Bell NEC" },
+ { "PBV", "Pitney Bowes" },
+ { "PCA", "Philips BU Add On Card" },
+ { "PCB", "OCTAL S.A." },
+ { "PCC", "PowerCom Technology Company Ltd" },
+ { "PCG", "First Industrial Computer Inc" },
+ { "PCI", "Pioneer Computer Inc" },
+ { "PCK", "PCBANK21" },
+ { "PCL", "pentel.co.,ltd" },
+ { "PCM", "PCM Systems Corporation" },
+ { "PCO", "Performance Concepts Inc.," },
+ { "PCP", "Procomp USA Inc" },
+ { "PCS", "TOSHIBA PERSONAL COMPUTER SYSTEM CORPRATION" },
+ { "PCT", "PC-Tel Inc" },
+ { "PCW", "Pacific CommWare Inc" },
+ { "PCX", "PC Xperten" },
+ { "PDM", "Psion Dacom Plc." },
+ { "PDN", "AT&T Paradyne" },
+ { "PDR", "Pure Data Inc" },
+ { "PDS", "PD Systems International Ltd" },
+ { "PDT", "PDTS - Prozessdatentechnik und Systeme" },
+ { "PDV", "Prodrive B.V." },
+ { "PEC", "POTRANS Electrical Corp." },
+ { "PEI", "PEI Electronics Inc" },
+ { "PEL", "Primax Electric Ltd" },
+ { "PEN", "Interactive Computer Products Inc" },
+ { "PEP", "Peppercon AG" },
+ { "PER", "Perceptive Signal Technologies" },
+ { "PET", "Practical Electronic Tools" },
+ { "PFT", "Telia ProSoft AB" },
+ { "PGI", "PACSGEAR, Inc." },
+ { "PGM", "Paradigm Advanced Research Centre" },
+ { "PGP", "propagamma kommunikation" },
+ { "PGS", "Princeton Graphic Systems" },
+ { "PHC", "Pijnenburg Beheer N.V." },
+ { "PHE", "Philips Medical Systems Boeblingen GmbH" },
+ { "PHI", "DO NOT USE - PHI" },
+ { "PHL", "Philips Consumer Electronics Company" },
+ { "PHO", "Photonics Systems Inc." },
+ { "PHS", "Philips Communication Systems" },
+ { "PHY", "Phylon Communications" },
+ { "PIE", "Pacific Image Electronics Company Ltd" },
+ { "PIM", "Prism, LLC" },
{ "PIO", "Pioneer Electronic Corporation" },
+ { "PIX", "Pixie Tech Inc" },
+ { "PJA", "Projecta" },
+ { "PJD", "Projectiondesign AS" },
+ { "PJT", "Pan Jit International Inc." },
+ { "PKA", "Acco UK ltd." },
+ { "PLC", "Pro-Log Corporation" },
+ { "PLF", "Panasonic Avionics Corporation" },
+ { "PLM", "PROLINK Microsystems Corp." },
+ { "PLT", "PT Hartono Istana Teknologi" },
+ { "PLV", "PLUS Vision Corp." },
+ { "PLX", "Parallax Graphics" },
+ { "PLY", "Polycom Inc." },
+ { "PMC", "PMC Consumer Electronics Ltd" },
+ { "PMD", "TDK USA Corporation" },
+ { "PMM", "Point Multimedia System" },
+ { "PMT", "Promate Electronic Co., Ltd." },
+ { "PMX", "Photomatrix" },
{ "PNG", "P.I. Engineering Inc" },
- { "OIN", "Option International" },
- { "RED", "Research Electronics Development Inc" },
- { "NOI", "North Invent A/S" },
- { "MAY", "Maynard Electronics" },
- { "BTO", "BioTao Ltd" },
- { "ZYD", "Zydacron Inc" },
- { "KCD", "Chunichi Denshi Co.,LTD." },
- { "TTI", "Trenton Terminals Inc" },
- { "TRD", "Trident Microsystem Inc" },
- { "TDP", "3D Perception" },
- { "TER", "TerraTec Electronic GmbH" },
- { "AEM", "ASEM S.p.A." },
- { "IBI", "INBINE.CO.LTD" },
- { "ECK", "Eugene Chukhlomin Sole Proprietorship, d.b.a." },
- { "AVT", "Avtek (Electronics) Pty Ltd" },
+ { "PNL", "Panelview, Inc." },
+ { "PNP", "Microsoft" },
+ { "PNR", "Planar Systems, Inc." },
+ { "PNS", "PanaScope" },
+ { "PNX", "Phoenix Technologies, Ltd." },
+ { "POL", "PolyComp (PTY) Ltd." },
+ { "PON", "Perpetual Technologies, LLC" },
+ { "POR", "Portalis LC" },
+ { "PPC", "Phoenixtec Power Company Ltd" },
+ { "PPD", "MEPhI" },
+ { "PPI", "Practical Peripherals" },
+ { "PPM", "Clinton Electronics Corp." },
+ { "PPP", "Purup Prepress AS" },
+ { "PPR", "PicPro" },
+ { "PPX", "Perceptive Pixel Inc." },
+ { "PQI", "Pixel Qi" },
+ { "PRA", "PRO/AUTOMATION" },
+ { "PRC", "PerComm" },
+ { "PRD", "Praim S.R.L." },
+ { "PRF", "Digital Electronics Corporation" },
+ { "PRG", "The Phoenix Research Group Inc" },
+ { "PRI", "Priva Hortimation BV" },
+ { "PRM", "Prometheus" },
+ { "PRO", "Proteon" },
+ { "PRS", "Leutron Vision" },
+ { "PRT", "Parade Technologies, Ltd." },
+ { "PRX", "Proxima Corporation" },
+ { "PSA", "Advanced Signal Processing Technologies" },
+ { "PSC", "Philips Semiconductors" },
+ { "PSD", "Peus-Systems GmbH" },
+ { "PSE", "Practical Solutions Pte., Ltd." },
+ { "PSI", "PSI-Perceptive Solutions Inc" },
+ { "PSL", "Perle Systems Limited" },
+ { "PSM", "Prosum" },
{ "PST", "Global Data SA" },
- { "FPS", "Deltec Corporation" },
- { "SHP", "Sharp Corporation" },
+ { "PSY", "Prodea Systems Inc." },
+ { "PTA", "PAR Tech Inc." },
+ { "PTC", "PS Technology Corporation" },
+ { "PTG", "Cipher Systems Inc" },
+ { "PTH", "Pathlight Technology Inc" },
+ { "PTI", "Promise Technology Inc" },
+ { "PTL", "Pantel Inc" },
+ { "PTS", "Plain Tree Systems Inc" },
+ { "PTW", "DO NOT USE - PTW" },
+ { "PUL", "Pulse-Eight Ltd" },
+ { "PVC", "DO NOT USE - PVC" },
+ { "PVG", "Proview Global Co., Ltd" },
+ { "PVI", "Prime view international Co., Ltd" },
+ { "PVM", "Penta Studiotechnik GmbH" },
+ { "PVN", "Pixel Vision" },
+ { "PVP", "Klos Technologies, Inc." },
+ { "PXC", "Phoenix Contact" },
+ { "PXE", "PIXELA CORPORATION" },
+ { "PXL", "The Moving Pixel Company" },
+ { "PXM", "Proxim Inc" },
+ { "QCC", "QuakeCom Company Ltd" },
+ { "QCH", "Metronics Inc" },
+ { "QCI", "Quanta Computer Inc" },
+ { "QCK", "Quick Corporation" },
+ { "QCL", "Quadrant Components Inc" },
+ { "QCP", "Qualcomm Inc" },
+ { "QDI", "Quantum Data Incorporated" },
+ { "QDM", "Quadram" },
+ { "QDS", "Quanta Display Inc." },
+ { "QFF", "Padix Co., Inc." },
+ { "QFI", "Quickflex, Inc" },
+ { "QLC", "Q-Logic" },
+ { "QQQ", "Chuomusen Co., Ltd." },
+ { "QSI", "Quantum Solutions, Inc." },
+ { "QTD", "Quantum 3D Inc" },
+ { "QTH", "Questech Ltd" },
+ { "QTI", "Quicknet Technologies Inc" },
+ { "QTM", "Quantum" },
+ { "QTR", "Qtronix Corporation" },
+ { "QUA", "Quatographic AG" },
+ { "QUE", "Questra Consulting" },
+ { "QVU", "Quartics" },
+ { "RAC", "Racore Computer Products Inc" },
+ { "RAD", "Radisys Corporation" },
+ { "RAI", "Rockwell Automation/Intecolor" },
+ { "RAN", "Rancho Tech Inc" },
+ { "RAR", "Raritan, Inc." },
+ { "RAS", "RAScom Inc" },
+ { "RAT", "Rent-A-Tech" },
+ { "RAY", "Raylar Design, Inc." },
+ { "RCE", "Parc d'Activite des Bellevues" },
+ { "RCH", "Reach Technology Inc" },
+ { "RCI", "RC International" },
+ { "RCN", "Radio Consult SRL" },
+ { "RCO", "Rockwell Collins" },
+ { "RDI", "Rainbow Displays, Inc." },
+ { "RDM", "Tremon Enterprises Company Ltd" },
{ "RDN", "RADIODATA GmbH" },
- { "TRC", "Trioc AB" },
- { "ABE", "Alcatel Bell" },
- { "VCX", "VCONEX" },
- { "PBL", "Packard Bell Electronics" },
- { "TLK", "Telelink AG" },
- { "DMM", "Dimond Multimedia Systems Inc" },
- { "IGM", "IGM Communi" },
- { "KFC", "SCD Tech" },
- { "GUD", "Guntermann & Drunck GmbH" },
- { "MDA", "Media4 Inc" },
- { "VWB", "Vweb Corp." },
- { "ISG", "Insignia Solutions Inc" },
- { "AMS", "ARMSTEL, Inc." },
- { "NTL", "National Transcomm. Ltd" },
- { "LSJ", "LSI Japan Company Ltd" },
- { "NDL", "Network Designers" },
- { "DIA", "Diadem" },
- { "SDX", "SDX Business Systems Ltd" },
- { "LPL", "LG Philips" },
- { "CAG", "CalComp" },
- { "FZC", "Founder Group Shenzhen Co." },
- { "PCX", "PC Xperten" },
- { "TSF", "Racal-Airtech Software Forge Ltd" },
+ { "RDS", "Radius Inc" },
+ { "REA", "Real D" },
+ { "REC", "ReCom" },
+ { "RED", "Research Electronics Development Inc" },
+ { "REF", "Reflectivity, Inc." },
+ { "REH", "Rehan Electronics Ltd." },
+ { "REL", "Reliance Electric Ind Corporation" },
+ { "REM", "SCI Systems Inc." },
+ { "REN", "Renesas Technology Corp." },
+ { "RES", "ResMed Pty Ltd" },
+ { "RET", "Resonance Technology, Inc." },
+ { "REX", "RATOC Systems, Inc." },
+ { "RGB", "RGB Spectrum" },
{ "RGL", "Robertson Geologging Ltd" },
- { "MSD", "Datenerfassungs- und Informationssysteme" },
- { "NVC", "NetVision Corporation" },
- { "SKD", "Schneider & Koch" },
- { "CRS", "Crescendo Communication Inc" },
- { "AXI", "American Magnetics" },
- { "HRS", "Harris Semiconductor" },
- { "AEN", "Avencall" },
- { "TCL", "Technical Concepts Ltd" },
- { "SST", "SystemSoft Corporation" },
- { "OMN", "Omnitel" },
- { "GCI", "Gateway Comm. Inc" },
- { "SEN", "Sencore" },
- { "MDT", "Magus Data Tech" },
- { "ALN", "Alana Technologies" },
- { "AVD", "Avid Electronics Corporation" },
- { "DOM", "Dome Imaging Systems" },
- { "KBL", "Kobil Systems GmbH" },
- { "ITS", "IDTECH" },
- { "CGS", "Chyron Corp" },
- { "CYV", "Cyviz AS" },
- { "CSO", "California Institute of Technology" },
- { "ADT", "Aved Display Technologies" },
- { "ACP", "Aspen Tech Inc" },
- { "AKI", "AKIA Corporation" },
- { "LCT", "Labcal Technologies" },
- { "NDS", "Nokia Data" },
- { "WCS", "Woodwind Communications Systems Inc" },
- { "XFG", "Jan Strapko - FOTO" },
- { "CPI", "Computer Peripherals Inc" },
- { "FCG", "First International Computer Ltd" },
- { "EVE", "Advanced Micro Peripherals Ltd" },
- { "ATO", "ASTRO DESIGN, INC." },
- { "SGW", "Shanghai Guowei Science and Technology Co., Ltd." },
- { "CNB", "American Power Conversion" },
- { "TCX", "FREEMARS Heavy Industries" },
- { "ITN", "The NTI Group" },
- { "HWD", "Highwater Designs Ltd" },
- { "NUG", "NU Technology, Inc." },
- { "ISL", "Isolation Systems" },
- { "CIL", "Citicom Infotech Private Limited" },
- { "IOT", "I/OTech Inc" },
- { "GET", "Getac Technology Corporation" },
- { "ULT", "Ultra Network Tech" },
- { "TVV", "TV1 GmbH" },
- { "OWL", "Mediacom Technologies Pte Ltd" },
- { "TMX", "Thermotrex Corporation" },
- { "ARC", "Alta Research Corporation" },
- { "SEL", "Way2Call Communications" },
- { "ELS", "ELSA GmbH" },
- { "STD", "STD Computer Inc" },
- { "GST", "Graphic SystemTechnology" },
- { "SME", "Sysmate Company" },
- { "ARS", "Arescom Inc" },
- { "SCN", "Scanport, Inc." },
- { "CTX", "Creatix Polymedia GmbH" },
- { "DIM", "dPict Imaging, Inc." },
- { "MDI", "Micro Design Inc" },
+ { "RHD", "RightHand Technologies" },
+ { "RHM", "Rohm Company Ltd" },
+ { "RHT", "Red Hat, Inc." },
+ { "RIC", "RICOH COMPANY, LTD." },
+ { "RII", "Racal Interlan Inc" },
+ { "RIO", "Rios Systems Company Ltd" },
+ { "RIT", "Ritech Inc" },
+ { "RIV", "Rivulet Communications" },
+ { "RJA", "Roland Corporation" },
+ { "RJS", "Advanced Engineering" },
+ { "RKC", "Reakin Technolohy Corporation" },
+ { "RLD", "MEPCO" },
+ { "RLN", "RadioLAN Inc" },
+ { "RMC", "Raritan Computer, Inc" },
+ { "RMP", "Research Machines" },
+ { "RMT", "Roper Mobile" },
+ { "RNB", "Rainbow Technologies" },
+ { "ROB", "Robust Electronics GmbH" },
+ { "ROH", "Rohm Co., Ltd." },
+ { "ROK", "Rockwell International" },
+ { "ROP", "Roper International Ltd" },
+ { "ROS", "Rohde & Schwarz" },
+ { "RPI", "RoomPro Technologies" },
+ { "RPT", "R.P.T.Intergroups" },
+ { "RRI", "Radicom Research Inc" },
+ { "RSC", "PhotoTelesis" },
+ { "RSH", "ADC-Centre" },
+ { "RSI", "Rampage Systems Inc" },
+ { "RSN", "Radiospire Networks, Inc." },
+ { "RSQ", "R Squared" },
+ { "RSS", "Rockwell Semiconductor Systems" },
+ { "RSV", "Ross Video Ltd" },
+ { "RSX", "Rapid Tech Corporation" },
+ { "RTC", "Relia Technologies" },
+ { "RTI", "Rancho Tech Inc" },
+ { "RTK", "DO NOT USE - RTK" },
+ { "RTL", "Realtek Semiconductor Company Ltd" },
+ { "RTS", "Raintree Systems" },
+ { "RUN", "RUNCO International" },
+ { "RUP", "Ups Manufactoring s.r.l." },
+ { "RVC", "RSI Systems Inc" },
+ { "RVI", "Realvision Inc" },
+ { "RVL", "Reveal Computer Prod" },
+ { "RWC", "Red Wing Corporation" },
+ { "RXT", "Tectona SoftSolutions (P) Ltd.," },
+ { "SAA", "Sanritz Automation Co.,Ltd." },
+ { "SAE", "Saab Aerotech" },
+ { "SAG", "Sedlbauer" },
+ { "SAI", "Sage Inc" },
+ { "SAK", "Saitek Ltd" },
+ { "SAM", "Samsung Electric Company" },
+ { "SAN", "Sanyo Electric Co.,Ltd." },
+ { "SAS", "Stores Automated Systems Inc" },
+ { "SAT", "Shuttle Tech" },
+ { "SBC", "Shanghai Bell Telephone Equip Mfg Co" },
+ { "SBD", "Softbed - Consulting & Development Ltd" },
+ { "SBI", "SMART Technologies Inc." },
+ { "SBS", "SBS-or Industrial Computers GmbH" },
+ { "SBT", "Senseboard Technologies AB" },
+ { "SCB", "SeeCubic B.V." },
+ { "SCC", "SORD Computer Corporation" },
+ { "SCD", "Sanyo Electric Company Ltd" },
+ { "SCE", "Sun Corporation" },
+ { "SCH", "Schlumberger Cards" },
+ { "SCI", "System Craft" },
+ { "SCL", "Sigmacom Co., Ltd." },
{ "SCM", "SCM Microsystems Inc" },
- { "CEA", "Consumer Electronics Association" },
- { "OTI", "Orchid Technology" },
- { "ADK", "Adtek System Science Company Ltd" },
- { "ETC", "Everton Technology Company Ltd" },
- { "PCO", "Performance Concepts Inc.," },
- { "DMC", "Dune Microsystems Corporation" },
- { "SGM", "SAGEM" },
- { "OBS", "Optibase Technologies" },
- { "PMX", "Photomatrix" },
+ { "SCN", "Scanport, Inc." },
+ { "SCO", "SORCUS Computer GmbH" },
+ { "SCP", "Scriptel Corporation" },
+ { "SCR", "Systran Corporation" },
+ { "SCS", "Nanomach Anstalt" },
+ { "SCT", "Smart Card Technology" },
+ { "SDA", "SAT (Societe Anonyme)" },
+ { "SDD", "Intrada-SDD Ltd" },
+ { "SDE", "Sherwood Digital Electronics Corporation" },
+ { "SDF", "SODIFF E&T CO., Ltd." },
+ { "SDH", "Communications Specialies, Inc." },
{ "SDI", "Samtron Displays Inc" },
- { "GMM", "GMM Research Inc" },
- { "DUN", "NCR Corporation" },
- { "CAL", "Acon" },
- { "MIR", "Miro Computer Prod." },
- { "PEN", "Interactive Computer Products Inc" },
- { "CRL", "Creative Logic" },
- { "SBT", "Senseboard Technologies AB" },
- { "AST", "AST Research Inc" },
- { "INS", "Ines GmbH" },
+ { "SDK", "SAIT-Devlonics" },
+ { "SDR", "SDR Systems" },
+ { "SDS", "SunRiver Data System" },
+ { "SDT", "Siemens AG" },
+ { "SDX", "SDX Business Systems Ltd" },
+ { "SEA", "Seanix Technology Inc." },
+ { "SEB", "system elektronik GmbH" },
+ { "SEC", "Seiko Epson Corporation" },
+ { "SEE", "SeeColor Corporation" },
+ { "SEG", "DO NOT USE - SEG" },
+ { "SEI", "Seitz & Associates Inc" },
+ { "SEL", "Way2Call Communications" },
+ { "SEM", "Samsung Electronics Company Ltd" },
+ { "SEN", "Sencore" },
+ { "SEO", "SEOS Ltd" },
+ { "SEP", "SEP Eletronica Ltda." },
+ { "SER", "Sony Ericsson Mobile Communications Inc." },
+ { "SES", "Session Control LLC" },
+ { "SET", "SendTek Corporation" },
+ { "SFM", "TORNADO Company" },
+ { "SFT", "Mikroforum Ring 3" },
{ "SGC", "Spectragraphics Corporation" },
- { "DBI", "DigiBoard Inc" },
- { "LEO", "First International Computer Inc" },
- { "TSP", "U.S. Navy" },
- { "MTK", "Microtek International Inc." },
- { "TCN", "Tecnetics (PTY) Ltd" },
- { "DPM", "ADPM Synthesis sas" },
- { "LGS", "LG Semicom Company Ltd" },
- { "LGI", "Logitech Inc" },
- { "PBV", "Pitney Bowes" },
- { "ELI", "Edsun Laboratories" },
- { "HPQ", "HP" },
- { "RPT", "R.P.T.Intergroups" },
- { "BDO", "Brahler ICS" },
- { "ARM", "Arima" },
- { "JTS", "JS Motorsports" },
- { "TNY", "Tennyson Tech Pty Ltd" },
- { "UDN", "Uniden Corporation" },
- { "KNC", "Konica corporation" },
- { "GND", "Gennum Corporation" },
- { "MSG", "MSI GmbH" },
- { "REH", "Rehan Electronics Ltd." },
- { "COL", "Rockwell Collins, Inc." },
- { "MDC", "Midori Electronics" },
- { "TRN", "Datacommunicatie Tron B.V." },
- { "VDA", "Victor Data Systems" },
- { "TOU", "Touchstone Technology" },
- { "ETD", "ELAN MICROELECTRONICS CORPORATION" },
- { "CYB", "CyberVision" },
- { "SWC", "Software Café" },
- { "EXN", "RGB Systems, Inc. dba Extron Electronics" },
- { "HSP", "HannStar Display Corp" },
- { "WTK", "Wearnes Thakral Pte" },
- { "GFM", "GFMesstechnik GmbH" },
- { "INC", "Home Row Inc" },
- { "LEC", "Lectron Company Ltd" },
- { "WTS", "Restek Electric Company Ltd" },
- { "ACE", "Actek Engineering Pty Ltd" },
- { "MSH", "Microsoft" },
- { "CHL", "Chloride-R&D" },
- { "ALT", "Altra" },
- { "EES", "EE Solutions, Inc." },
- { "ASX", "AudioScience" },
- { "DAC", "Digital Acoustics Corporation" },
- { "HAL", "Halberthal" },
- { "HPC", "Hewlett Packard Co." },
- { "GRY", "Robert Gray Company" },
- { "AXO", "Axonic Labs LLC" },
- { "ALJ", "Altec Lansing" },
+ { "SGD", "Sigma Designs, Inc." },
+ { "SGE", "Kansai Electric Company Ltd" },
+ { "SGI", "Scan Group Ltd" },
+ { "SGL", "Super Gate Technology Company Ltd" },
+ { "SGM", "SAGEM" },
+ { "SGO", "Logos Design A/S" },
+ { "SGT", "Stargate Technology" },
+ { "SGW", "Shanghai Guowei Science and Technology Co., Ltd." },
+ { "SGX", "Silicon Graphics Inc" },
+ { "SGZ", "Systec Computer GmbH" },
+ { "SHC", "ShibaSoku Co., Ltd." },
+ { "SHG", "Soft & Hardware development Goldammer GmbH" },
+ { "SHI", "Jiangsu Shinco Electronic Group Co., Ltd" },
+ { "SHP", "Sharp Corporation" },
+ { "SHR", "Digital Discovery" },
+ { "SHT", "Shin Ho Tech" },
+ { "SIA", "SIEMENS AG" },
+ { "SIB", "Sanyo Electric Company Ltd" },
+ { "SIC", "Sysmate Corporation" },
+ { "SID", "Seiko Instruments Information Devices Inc" },
+ { "SIE", "Siemens" },
+ { "SIG", "Sigma Designs Inc" },
+ { "SII", "Silicon Image, Inc." },
+ { "SIL", "Silicon Laboratories, Inc" },
+ { "SIM", "S3 Inc" },
+ { "SIN", "Singular Technology Co., Ltd." },
+ { "SIR", "Sirius Technologies Pty Ltd" },
+ { "SIS", "Silicon Integrated Systems Corporation" },
+ { "SIT", "Sitintel" },
+ { "SIU", "Seiko Instruments USA Inc" },
+ { "SIX", "Zuniq Data Corporation" },
+ { "SJE", "Sejin Electron Inc" },
+ { "SKD", "Schneider & Koch" },
+ { "SKT", "Samsung Electro-Mechanics Company Ltd" },
+ { "SKY", "SKYDATA S.P.A." },
+ { "SLA", "Systeme Lauer GmbH&Co KG" },
+ { "SLB", "Shlumberger Ltd" },
+ { "SLC", "Syslogic Datentechnik AG" },
+ { "SLF", "StarLeaf" },
+ { "SLH", "Silicon Library Inc." },
+ { "SLI", "Symbios Logic Inc" },
+ { "SLK", "Silitek Corporation" },
+ { "SLM", "Solomon Technology Corporation" },
+ { "SLR", "Schlumberger Technology Corporate" },
+ { "SLS", "Schnick-Schnack-Systems GmbH" },
+ { "SLT", "Salt Internatioinal Corp." },
+ { "SLX", "Specialix" },
+ { "SMA", "SMART Modular Technologies" },
+ { "SMB", "Schlumberger" },
+ { "SMC", "Standard Microsystems Corporation" },
+ { "SME", "Sysmate Company" },
+ { "SMI", "SpaceLabs Medical Inc" },
+ { "SMK", "SMK CORPORATION" },
+ { "SML", "Sumitomo Metal Industries, Ltd." },
+ { "SMM", "Shark Multimedia Inc" },
+ { "SMO", "STMicroelectronics" },
+ { "SMP", "Simple Computing" },
+ { "SMR", "B.& V. s.r.l." },
{ "SMS", "Silicom Multimedia Systems Inc" },
- { "HPI", "Headplay, Inc." },
- { "FRO", "FARO Technologies" },
- { "GAU", "Gaudi Co., Ltd." },
+ { "SMT", "Silcom Manufacturing Tech Inc" },
+ { "SNC", "Sentronic International Corp." },
+ { "SNI", "Siemens Microdesign GmbH" },
+ { "SNK", "S&K Electronics" },
+ { "SNO", "SINOSUN TECHNOLOGY CO., LTD" },
+ { "SNP", "Siemens Nixdorf Info Systems" },
+ { "SNS", "Cirtech (UK) Ltd" },
+ { "SNT", "SuperNet Inc" },
+ { "SNW", "Snell & Wilcox" },
+ { "SNX", "Sonix Comm. Ltd" },
+ { "SNY", "Sony" },
+ { "SOI", "Silicon Optix Corporation" },
+ { "SOL", "Solitron Technologies Inc" },
+ { "SON", "Sony" },
+ { "SOR", "Sorcus Computer GmbH" },
+ { "SOT", "Sotec Company Ltd" },
+ { "SOY", "SOYO Group, Inc" },
+ { "SPC", "SpinCore Technologies, Inc" },
+ { "SPE", "SPEA Software AG" },
+ { "SPH", "G&W Instruments GmbH" },
+ { "SPI", "SPACE-I Co., Ltd." },
+ { "SPK", "SpeakerCraft" },
+ { "SPL", "Smart Silicon Systems Pty Ltd" },
+ { "SPN", "Sapience Corporation" },
+ { "SPR", "pmns GmbH" },
+ { "SPS", "Synopsys Inc" },
+ { "SPT", "Sceptre Tech Inc" },
+ { "SPU", "SIM2 Multimedia S.P.A." },
+ { "SPX", "Simplex Time Recorder Co." },
+ { "SQT", "Sequent Computer Systems Inc" },
+ { "SRC", "Integrated Tech Express Inc" },
+ { "SRD", "Setred" },
+ { "SRF", "Surf Communication Solutions Ltd" },
+ { "SRG", "Intuitive Surgical, Inc." },
{ "SRS", "SR-Systems e.K." },
- { "APL", "Aplicom Oy" },
- { "JGD", "University College" },
- { "NVD", "Nvidia" },
- { "CEP", "C-DAC" },
- { "BDR", "Blonder Tongue Labs, Inc." },
- { "AUO", "AU Optronics" },
- { "DCR", "Decros Ltd" },
- { "DLK", "D-Link Systems Inc" },
- { "SWS", "Static" },
- { "WSC", "CIS Technology Inc" },
- { "ESL", "Esterline Technologies" },
- { "ISC", "Id3 Semiconductors" },
- { "XSN", "Xscreen AS" },
- { "FML", "Fujitsu Microelect Ltd" },
- { "WPI", "Wearnes Peripherals International (Pte) Ltd" },
- { "EGL", "Eagle Technology" },
- { "EGA", "Elgato Systems LLC" },
- { "GAG", "Gage Applied Sciences Inc" },
- { "HCP", "Hitachi Computer Products Inc" },
- { "UET", "Universal Empowering Technologies" },
- { "ITL", "Inter-Tel" },
- { "SDE", "Sherwood Digital Electronics Corporation" },
- { "CAA", "Castles Automation Co., Ltd" },
- { "ZRN", "Zoran Corporation" },
- { "VLT", "VideoLan Technologies" },
- { "EUT", "Ericsson Mobile Networks B.V." },
- { "REA", "Real D" },
- { "BUT", "21ST CENTURY ENTERTAINMENT" },
- { "THN", "Thundercom Holdings Sdn. Bhd." },
- { "CHO", "Sichuang Changhong Corporation" },
- { "SCC", "SORD Computer Corporation" },
- { "MSY", "MicroTouch Systems Inc" },
- { "ERP", "Euraplan GmbH" },
- { "CPL", "Compal Electronics Inc" },
- { "ACM", "Acroloop Motion Control Systems Inc" },
- { "VTS", "VTech Computers Ltd" },
- { "ETH", "Etherboot Project" },
- { "CGT", "congatec AG" },
- { "FEN", "Fen Systems Ltd." },
- { "MLN", "Mark Levinson" },
- { "UMC", "United Microelectr Corporation" },
- { "CAR", "Cardinal Company Ltd" },
- { "LIT", "Lithics Silicon Technology" },
- { "AWC", "Access Works Comm Inc" },
- { "PPC", "Phoenixtec Power Company Ltd" },
- { "SVT", "SEVIT Co., Ltd." },
- { "MDX", "MicroDatec GmbH" },
- { "XIN", "Xinex Networks Inc" },
- { "KTN", "Katron Tech Inc" },
- { "MJI", "MARANTZ JAPAN, INC." },
- { "CTM", "Computerm Corporation" },
- { "PDM", "Psion Dacom Plc." },
- { "AKM", "Asahi Kasei Microsystems Company Ltd" },
- { "GSY", "Grossenbacher Systeme AG" },
- { "OMR", "Omron Corporation" },
- { "RSH", "ADC-Centre" },
- { "MTM", "Motium" },
- { "XDM", "XDM Ltd." },
- { "MSX", "Micomsoft Co., Ltd." },
- { "VNC", "Vinca Corporation" },
+ { "SRT", "SeeReal Technologies GmbH" },
+ { "SSC", "Sierra Semiconductor Inc" },
+ { "SSD", "FlightSafety International" },
+ { "SSE", "Samsung Electronic Co." },
+ { "SSI", "S-S Technology Inc" },
+ { "SSJ", "Sankyo Seiki Mfg.co., Ltd" },
+ { "SSP", "Spectrum Signal Proecessing Inc" },
+ { "SSS", "S3 Inc" },
+ { "SST", "SystemSoft Corporation" },
+ { "STA", "ST Electronics Systems Assembly Pte Ltd" },
+ { "STB", "STB Systems Inc" },
+ { "STC", "STAC Electronics" },
+ { "STD", "STD Computer Inc" },
+ { "STE", "SII Ido-Tsushin Inc" },
+ { "STF", "Starflight Electronics" },
+ { "STG", "StereoGraphics Corp." },
+ { "STH", "Semtech Corporation" },
+ { "STI", "Smart Tech Inc" },
{ "STK", "SANTAK CORP." },
- { "JET", "JET POWER TECHNOLOGY CO., LTD." },
- { "SLR", "Schlumberger Technology Corporate" },
- { "GWI", "GW Instruments" },
- { "TMI", "Texas Microsystem" },
- { "EXT", "Exatech Computadores & Servicos Ltda" },
- { "SXB", "Syntax-Brillian" },
- { "HYT", "Heng Yu Technology (HK) Limited" },
- { "TST", "Transtream Inc" },
- { "FIS", "FLY-IT Simulators" },
- { "VMW", "VMware Inc.," },
- { "PET", "Practical Electronic Tools" },
- { "BLP", "Bloomberg L.P." },
- { "MVS", "Microvision" },
- { "ZMT", "Zalman Tech Co., Ltd." },
- { "QTD", "Quantum 3D Inc" },
- { "ITE", "Integrated Tech Express Inc" },
- { "MIS", "Modular Industrial Solutions Inc" },
- { "KOB", "Kobil Systems GmbH" },
- { "KOW", "KOWA Company,LTD." },
- { "SHC", "ShibaSoku Co., Ltd." },
- { "IKS", "Ikos Systems Inc" },
- { "PGP", "propagamma kommunikation" },
- { "AYD", "Aydin Displays" },
- { "MFG", "MicroField Graphics Inc" },
- { "APS", "Autologic Inc" },
- { "APM", "Applied Memory Tech" },
- { "ACO", "Allion Computer Inc." },
- { "IWR", "Icuiti Corporation" },
- { "RCI", "RC International" },
- { "YMH", "Yamaha Corporation" },
- { "SPE", "SPEA Software AG" },
- { "ADL", "ASTRA Security Products Ltd" },
- { "QFI", "Quickflex, Inc" },
- { "FRD", "Freedom Scientific BLV" },
- { "PCM", "PCM Systems Corporation" },
- { "RHM", "Rohm Company Ltd" },
- { "EQP", "Equipe Electronics Ltd." },
- { "UND", "Unisys Corporation" },
- { "ITX", "integrated Technology Express Inc" },
- { "WML", "Wolfson Microelectronics Ltd" },
- { "IPR", "Ithaca Peripherals" },
- { "NCE", "Norcent Technology, Inc." },
- { "GWY", "Gateway 2000" },
- { "DAX", "Data Apex Ltd" },
- { "MKT", "MICROTEK Inc." },
- { "AOL", "America OnLine" },
- { "BIO", "BioLink Technologies International, Inc." },
- { "DCI", "Concepts Inc" },
- { "LOL", "Litelogic Operations Ltd" },
- { "ADI", "ADI Systems Inc" },
- { "TPJ", "Junnila" },
- { "JDL", "Japan Digital Laboratory Co.,Ltd." },
- { "MMN", "MiniMan Inc" },
- { "MNC", "Mini Micro Methods Ltd" },
- { "SUM", "Summagraphics Corporation" },
- { "SXT", "SHARP TAKAYA ELECTRONIC INDUSTRY CO.,LTD." },
- { "CAT", "Consultancy in Advanced Technology" },
- { "MSM", "Advanced Digital Systems" },
- { "CHY", "Cherry GmbH" },
- { "VLB", "ValleyBoard Ltda." },
- { "DDS", "Barco, n.v." },
{ "STL", "SigmaTel Inc" },
- { "AIE", "Altmann Industrieelektronik" },
- { "CHM", "CHIC TECHNOLOGY CORP." },
- { "KTK", "Key Tronic Corporation" },
- { "LTN", "Litronic Inc" },
- { "IDC", "International Datacasting Corporation" },
- { "TWA", "Tidewater Association" },
- { "ARI", "Argosy Research Inc" },
+ { "STM", "SGS Thomson Microelectronics" },
+ { "STN", "Samsung Electronics America" },
+ { "STO", "Stollmann E+V GmbH" },
+ { "STP", "StreamPlay Ltd" },
+ { "STR", "Starlight Networks Inc" },
+ { "STS", "SITECSYSTEM CO., LTD." },
{ "STT", "Star Paging Telecom Tech (Shenzhen) Co. Ltd." },
- { "MYA", "Monydata" },
- { "JAE", "Japan Aviation Electronics Industry, Limited" },
- { "BBH", "B&Bh" },
- { "GIC", "General Inst. Corporation" },
- { "TIV", "OOO Technoinvest" },
- { "ION", "Inside Out Networks" },
- { "KZI", "K-Zone International co. Ltd." },
- { "IDE", "IDE Associates" },
- { "IQI", "IneoQuest Technologies, Inc" },
- { "NDI", "National Display Systems" },
- { "REL", "Reliance Electric Ind Corporation" },
- { "SPH", "G&W Instruments GmbH" },
- { "RPI", "RoomPro Technologies" },
- { "LUC", "Lucent Technologies" },
- { "CTL", "Creative Technology Ltd" },
- { "SDS", "SunRiver Data System" },
- { "USR", "U.S. Robotics Inc" },
- { "GJN", "Grand Junction Networks" },
- { "YED", "Y-E Data Inc" },
- { "RHT", "Red Hat, Inc." },
- { "AOT", "Alcatel" },
- { "TCR", "Thomson Consumer Electronics" },
- { "ILC", "Image Logic Corporation" },
- { "IGC", "Intergate Pty Ltd" },
- { "HYC", "Hypercope Gmbh Aachen" },
- { "SPL", "Smart Silicon Systems Pty Ltd" },
- { "DLC", "Diamond Lane Comm. Corporation" },
- { "TBB", "Triple S Engineering Inc" },
- { "MLS", "Milestone EPE" },
- { "QDM", "Quadram" },
- { "AIR", "Advanced Integ. Research Inc" },
- { "SLA", "Systeme Lauer GmbH&Co KG" },
- { "IBP", "IBP Instruments GmbH" },
- { "DDI", "Data Display AG" },
- { "LED", "Long Engineering Design Inc" },
- { "MSC", "Mouse Systems Corporation" },
- { "LXS", "ELEA CardWare" },
- { "ATE", "Innovate Ltd" },
- { "APV", "A+V Link" },
- { "FRC", "Force Computers" },
- { "ZTC", "ZyDAS Technology Corporation" },
- { "ANP", "Andrew Network Production" },
- { "LOG", "Logicode Technology Inc" },
- { "RAI", "Rockwell Automation/Intecolor" },
- { "MPJ", "Microlab" },
- { "CMO", "Chi Mei Optoelectronics corp." },
- { "ROH", "Rohm Co., Ltd." },
- { "HYP", "Hyphen Ltd" },
- { "ICO", "Intel Corp" },
- { "ACI", "Ancor Communications Inc" },
- { "SLT", "Salt Internatioinal Corp." },
- { "TSC", "Sanyo Electric Company Ltd" },
- { "APC", "American Power Conversion" },
- { "PSE", "Practical Solutions Pte., Ltd." },
- { "MET", "Metheus Corporation" },
- { "SAT", "Shuttle Tech" },
+ { "STU", "Sentelic Corporation" },
+ { "STW", "Starwin Inc." },
+ { "STX", "ST-Ericsson" },
+ { "STY", "SDS Technologies" },
+ { "SUB", "Subspace Comm. Inc" },
+ { "SUM", "Summagraphics Corporation" },
+ { "SUN", "Sun Electronics Corporation" },
+ { "SUP", "Supra Corporation" },
+ { "SUR", "Surenam Computer Corporation" },
+ { "SVA", "SGEG" },
+ { "SVC", "Intellix Corp." },
+ { "SVD", "SVD Computer" },
+ { "SVI", "Sun Microsystems" },
+ { "SVS", "SVSI" },
+ { "SVT", "SEVIT Co., Ltd." },
+ { "SWC", "Software Café" },
+ { "SWI", "Sierra Wireless Inc." },
+ { "SWL", "Sharedware Ltd" },
+ { "SWS", "Static" },
+ { "SWT", "Software Technologies Group,Inc." },
+ { "SXB", "Syntax-Brillian" },
+ { "SXD", "Silex technology, Inc." },
+ { "SXG", "SELEX GALILEO" },
+ { "SXL", "SolutionInside" },
+ { "SXT", "SHARP TAKAYA ELECTRONIC INDUSTRY CO.,LTD." },
+ { "SYC", "Sysmic" },
+ { "SYE", "SY Electronics Ltd" },
{ "SYK", "Stryker Communications" },
- { "BCQ", "Deutsche Telekom Berkom GmbH" },
- { "DPI", "DocuPoint" },
- { "FAR", "Farallon Computing" },
- { "ROP", "Roper International Ltd" },
- { "STB", "STB Systems Inc" },
- { "CNC", "Alvedon Computers Ltd" },
- { "DGA", "Digiital Arts Inc" },
- { "EDT", "Emerging Display Technologies Corp" },
- { "IPI", "Intelligent Platform Management Interface (IPMI) forum (Intel, HP, NEC, Dell)" },
- { "VQ@", "Vision Quest" },
- { "EMK", "Emcore Corporation" },
- { "XTD", "Icuiti Corporation" },
- { "KNX", "Nutech Marketing PTL" },
- { "WHI", "Whistle Communications" },
- { "KDM", "Korea Data Systems Co., Ltd." },
- { "QCK", "Quick Corporation" },
- { "QTR", "Qtronix Corporation" },
- { "NFS", "Number Five Software" },
- { "HTK", "Holtek Microelectronics Inc" },
- { "TRL", "Royal Information" },
- { "LXN", "Luxeon" },
- { "VLK", "Vislink International Ltd" },
- { "TWE", "Kontron Electronik" },
- { "DFI", "DFI" },
- { "JWS", "JWSpencer & Co." },
- { "FTW", "MindTribe Product Engineering, Inc." },
+ { "SYL", "Sylvania Computer Products" },
+ { "SYM", "Symicron Computer Communications Ltd." },
+ { "SYN", "Synaptics Inc" },
+ { "SYP", "SYPRO Co Ltd" },
+ { "SYS", "Sysgration Ltd" },
+ { "SYT", "Seyeon Tech Company Ltd" },
+ { "SYV", "SYVAX Inc" },
+ { "SYX", "Prime Systems, Inc." },
+ { "TAA", "Tandberg" },
+ { "TAB", "Todos Data System AB" },
+ { "TAG", "Teles AG" },
+ { "TAI", "Toshiba America Info Systems Inc" },
+ { "TAM", "Tamura Seisakusyo Ltd" },
+ { "TAS", "Taskit Rechnertechnik GmbH" },
+ { "TAT", "Teleliaison Inc" },
+ { "TAX", "Taxan (Europe) Ltd" },
+ { "TBB", "Triple S Engineering Inc" },
+ { "TBC", "Turbo Communication, Inc" },
+ { "TBS", "Turtle Beach System" },
+ { "TCC", "Tandon Corporation" },
+ { "TCD", "Taicom Data Systems Co., Ltd." },
+ { "TCE", "Century Corporation" },
+ { "TCH", "Interaction Systems, Inc" },
+ { "TCI", "Tulip Computers Int'l B.V." },
+ { "TCJ", "TEAC America Inc" },
+ { "TCL", "Technical Concepts Ltd" },
+ { "TCM", "3Com Corporation" },
+ { "TCN", "Tecnetics (PTY) Ltd" },
+ { "TCO", "Thomas-Conrad Corporation" },
+ { "TCR", "Thomson Consumer Electronics" },
+ { "TCS", "Tatung Company of America Inc" },
+ { "TCT", "Telecom Technology Centre Co. Ltd." },
+ { "TCX", "FREEMARS Heavy Industries" },
+ { "TDC", "Teradici" },
+ { "TDD", "Tandberg Data Display AS" },
+ { "TDK", "TDK USA Corporation" },
{ "TDM", "Tandem Computer Europe Inc" },
- { "RAS", "RAScom Inc" },
- { "KVX", "KeyView" },
- { "MOS", "Moses Corporation" },
- { "ONX", "SOMELEC Z.I. Du Vert Galanta" },
- { "STF", "Starflight Electronics" },
- { "HER", "Ascom Business Systems" },
- { "GTS", "Geotest Marvin Test Systems Inc" },
- { "KEC", "Kyushu Electronics Systems Inc" },
- { "MQP", "MultiQ Products AB" },
- { "LUX", "Luxxell Research Inc" },
- { "HEC", "Hitachi Engineering Company Ltd" },
- { "NXG", "Nexgen" },
- { "CNI", "Connect Int'l A/S" },
- { "FUJ", "Fujitsu Ltd" },
- { "APD", "AppliAdata" },
- { "LHE", "Lung Hwa Electronics Company Ltd" },
- { "SCT", "Smart Card Technology" },
- { "SOY", "SOYO Group, Inc" },
- { "ICN", "Sanyo Icon" },
+ { "TDP", "3D Perception" },
+ { "TDS", "Tri-Data Systems Inc" },
+ { "TDT", "TDT" },
{ "TDV", "TDVision Systems, Inc." },
- { "AHC", "Advantech Co., Ltd." },
- { "GTK", "G-Tech Corporation" },
- { "BII", "Boeckeler Instruments Inc" },
- { "TCC", "Tandon Corporation" },
- { "BUJ", "ATI Tech Inc" },
- { "SAA", "Sanritz Automation Co.,Ltd." },
- { "DTK", "Dynax Electronics (HK) Ltd" },
- { "HXM", "Hexium Ltd." },
- { "EGD", "EIZO GmbH Display Technologies" },
- { "NDK", "Naitoh Densei CO., LTD." },
- { "TVR", "TV Interactive Corporation" },
- { "PNL", "Panelview, Inc." },
- { "AET", "Aethra Telecomunicazioni S.r.l." },
- { "REC", "ReCom" },
- { "HET", "HETEC Datensysteme GmbH" },
- { "ZOW", "Zowie Intertainment, Inc" },
- { "MEQ", "Matelect Ltd." },
- { "DRD", "DIGITAL REFLECTION INC." },
- { "MRA", "Miranda Technologies Inc" },
- { "QTM", "Quantum" },
- { "REN", "Renesas Technology Corp." },
- { "XIO", "Xiotech Corporation" },
- { "GIS", "AT&T Global Info Solutions" },
+ { "TDY", "Tandy Electronics" },
{ "TEA", "TEAC System Corporation" },
- { "EMU", "Emulex Corporation" },
- { "VIC", "Victron B.V." },
- { "ATN", "Athena Smartcard Solutions Ltd." },
- { "SYS", "Sysgration Ltd" },
- { "CVS", "Clarity Visual Systems" },
- { "CWR", "Connectware Inc" },
- { "TVI", "Truevision" },
- { "AMB", "Ambient Technologies, Inc." },
- { "USA", "Utimaco Safeware AG" },
- { "LNT", "LANETCO International" },
- { "EDG", "Electronic-Design GmbH" },
- { "MKV", "Trtheim Technology" },
- { "SGT", "Stargate Technology" },
- { "RTS", "Raintree Systems" },
- { "PXM", "Proxim Inc" },
- { "ACG", "A&R Cambridge Ltd" },
- { "FJT", "F.J. Tieman BV" },
- { "LCD", "Toshiba Matsushita Display Technology Co., Ltd" },
- { "IDS", "Interdigital Sistemas de Informacao" },
- { "AOA", "AOpen Inc." },
- { "ACR", "Acer Technologies" },
- { "AKL", "AMiT Ltd" },
- { "IOS", "i-O Display System" },
- { "NOR", "Norand Corporation" },
- { "XST", "XS Technologies Inc" },
- { "BUG", "B.U.G., Inc." },
- { "RCN", "Radio Consult SRL" },
- { "ESI", "Extended Systems, Inc." },
- { "TUT", "Tut Systems" },
- { "VAR", "Varian Australia Pty Ltd" },
- { "DIT", "Dragon Information Technology" },
- { "CET", "TEC CORPORATION" },
- { "WKH", "Uni-Take Int'l Inc." },
- { "BHZ", "BitHeadz, Inc." },
- { "PTI", "Promise Technology Inc" },
- { "HIQ", "Kaohsiung Opto Electronics Americas, Inc." },
- { "SET", "SendTek Corporation" },
- { "KCL", "Keycorp Ltd" },
- { "EIC", "Eicon Technology Corporation" },
- { "TRT", "Tritec Electronic AG" },
- { "ZAN", "Zandar Technologies plc" },
- { "NTN", "Nuvoton Technology Corporation" },
- { "MTC", "Mars-Tech Corporation" },
- { "JQE", "CNet Technical Inc" },
- { "SRG", "Intuitive Surgical, Inc." },
- { "VIR", "Visual Interface, Inc" },
- { "HTX", "Hitex Systementwicklung GmbH" },
+ { "TEC", "Tecmar Inc" },
+ { "TEK", "Tektronix Inc" },
+ { "TEL", "Promotion and Display Technology Ltd." },
+ { "TER", "TerraTec Electronic GmbH" },
+ { "TGC", "Toshiba Global Commerce Solutions, Inc." },
+ { "TGI", "TriGem Computer Inc" },
+ { "TGM", "TriGem Computer,Inc." },
+ { "TGS", "Torus Systems Ltd" },
+ { "TGV", "Grass Valley Germany GmbH" },
+ { "THN", "Thundercom Holdings Sdn. Bhd." },
+ { "TIC", "Trigem KinfoComm" },
+ { "TIP", "TIPTEL AG" },
+ { "TIV", "OOO Technoinvest" },
+ { "TIX", "Tixi.Com GmbH" },
+ { "TKC", "Taiko Electric Works.LTD" },
+ { "TKN", "Teknor Microsystem Inc" },
+ { "TKO", "TouchKo, Inc." },
+ { "TKS", "TimeKeeping Systems, Inc." },
+ { "TLA", "Ferrari Electronic GmbH" },
+ { "TLD", "Telindus" },
+ { "TLF", "Teleforce.,co,ltd" },
+ { "TLI", "TOSHIBA TELI CORPORATION" },
+ { "TLK", "Telelink AG" },
+ { "TLS", "Teleste Educational OY" },
+ { "TLT", "Dai Telecom S.p.A." },
+ { "TLV", "S3 Inc" },
{ "TLX", "Telxon Corporation" },
- { "NGC", "Network General" },
+ { "TMC", "Techmedia Computer Systems Corporation" },
+ { "TME", "AT&T Microelectronics" },
+ { "TMI", "Texas Microsystem" },
+ { "TMM", "Time Management, Inc." },
+ { "TMR", "Taicom International Inc" },
+ { "TMS", "Trident Microsystems Ltd" },
+ { "TMT", "T-Metrics Inc." },
+ { "TMX", "Thermotrex Corporation" },
+ { "TNC", "TNC Industrial Company Ltd" },
+ { "TNJ", "DO NOT USE - TNJ" },
+ { "TNM", "TECNIMAGEN SA" },
+ { "TNY", "Tennyson Tech Pty Ltd" },
+ { "TOE", "TOEI Electronics Co., Ltd." },
+ { "TOG", "The OPEN Group" },
+ { "TON", "TONNA" },
+ { "TOP", "Orion Communications Co., Ltd." },
+ { "TOS", "Toshiba Corporation" },
+ { "TOU", "Touchstone Technology" },
+ { "TPC", "Touch Panel Systems Corporation" },
+ { "TPE", "Technology Power Enterprises Inc" },
+ { "TPJ", "Junnila" },
+ { "TPK", "TOPRE CORPORATION" },
+ { "TPR", "Topro Technology Inc" },
+ { "TPS", "Teleprocessing Systeme GmbH" },
+ { "TPT", "Thruput Ltd" },
+ { "TPV", "Top Victory Electronics ( Fujian ) Company Ltd" },
+ { "TPZ", "Ypoaz Systems Inc" },
+ { "TRA", "TriTech Microelectronics International" },
+ { "TRC", "Trioc AB" },
+ { "TRD", "Trident Microsystem Inc" },
+ { "TRE", "Tremetrics" },
+ { "TRI", "Tricord Systems" },
+ { "TRL", "Royal Information" },
+ { "TRM", "Tekram Technology Company Ltd" },
+ { "TRN", "Datacommunicatie Tron B.V." },
+ { "TRS", "Torus Systems Ltd" },
+ { "TRT", "Tritec Electronic AG" },
+ { "TRU", "Aashima Technology B.V." },
+ { "TRV", "Trivisio Prototyping GmbH" },
+ { "TRX", "Trex Enterprises" },
{ "TSB", "Toshiba America Info Systems Inc" },
- { "SGI", "Scan Group Ltd" },
- { "AIS", "Alien Internet Services" },
- { "MUD", "Multi-Dimension Institute" },
- { "PNS", "PanaScope" },
- { "NEO", "NEO TELECOM CO.,LTD." },
- { "IMB", "ART s.r.l." },
- { "SRD", "Setred" },
- { "LEX", "Lexical Ltd" },
- { "LMI", "Lexmark Int'l Inc" },
- { "ECL", "Excel Company Ltd" },
- { "EXC", "Excession Audio" },
- { "ABA", "ABBAHOME INC." },
- { "CLI", "Cirrus Logic Inc" },
- { "DYM", "Dymo-CoStar Corporation" },
- { "MEL", "Mitsubishi Electric Corporation" },
- { "ZAX", "Zefiro Acoustics" },
- { "TEC", "Tecmar Inc" },
- { "WTI", "WorkStation Tech" },
- { "APX", "AP Designs Ltd" },
- { "MLM", "Millennium Engineering Inc" },
- { "BAC", "Biometric Access Corporation" },
- { "DDE", "Datasat Digital Entertainment" },
- { "GIM", "Guillemont International" },
+ { "TSC", "Sanyo Electric Company Ltd" },
+ { "TSD", "TechniSat Digital GmbH" },
+ { "TSE", "Tottori Sanyo Electric" },
+ { "TSF", "Racal-Airtech Software Forge Ltd" },
+ { "TSG", "The Software Group Ltd" },
+ { "TSI", "TeleVideo Systems" },
+ { "TSL", "Tottori SANYO Electric Co., Ltd." },
+ { "TSP", "U.S. Navy" },
+ { "TST", "Transtream Inc" },
+ { "TSV", "TRANSVIDEO" },
+ { "TSY", "TouchSystems" },
+ { "TTA", "Topson Technology Co., Ltd." },
+ { "TTB", "National Semiconductor Japan Ltd" },
+ { "TTC", "Telecommunications Techniques Corporation" },
+ { "TTE", "TTE, Inc." },
+ { "TTI", "Trenton Terminals Inc" },
+ { "TTK", "Totoku Electric Company Ltd" },
+ { "TTL", "2-Tel B.V." },
+ { "TTS", "TechnoTrend Systemtechnik GmbH" },
+ { "TTY", "TRIDELITY Display Solutions GmbH" },
+ { "TUA", "T+A elektroakustik GmbH" },
+ { "TUT", "Tut Systems" },
+ { "TVD", "Tecnovision" },
+ { "TVI", "Truevision" },
{ "TVM", "Taiwan Video & Monitor Corporation" },
- { "KWD", "Kenwood Corporation" },
- { "STW", "Starwin Inc." },
- { "NRV", "Taugagreining hf" },
- { "SUP", "Supra Corporation" },
- { "MTB", "Media Technologies Ltd." },
- { "INF", "Inframetrics Inc" },
- { "OTM", "Optoma Corporation" },
- { "NTX", "Netaccess Inc" },
- { "LXC", "LXCO Technologies AG" },
- { "CRN", "Cornerstone Imaging" },
- { "PVP", "Klos Technologies, Inc." },
- { "TCJ", "TEAC America Inc" },
- { "WVM", "Wave Systems Corporation" },
- { "ERN", "Ericsson, Inc." },
- { "PVN", "Pixel Vision" },
- { "LMT", "Laser Master" },
- { "MID", "miro Displays" },
+ { "TVO", "TV One Ltd" },
+ { "TVR", "TV Interactive Corporation" },
+ { "TVS", "TVS Electronics Limited" },
+ { "TVV", "TV1 GmbH" },
+ { "TWA", "Tidewater Association" },
+ { "TWE", "Kontron Electronik" },
+ { "TWH", "Twinhead International Corporation" },
+ { "TWI", "Easytel oy" },
+ { "TWK", "TOWITOKO electronics GmbH" },
+ { "TWX", "TEKWorx Limited" },
+ { "TXL", "Trixel Ltd" },
+ { "TXN", "Texas Insturments" },
+ { "TXT", "Textron Defense System" },
+ { "TYN", "Tyan Computer Corporation" },
+ { "UAS", "Ultima Associates Pte Ltd" },
+ { "UBI", "Ungermann-Bass Inc" },
+ { "UBL", "Ubinetics Ltd." },
+ { "UDN", "Uniden Corporation" },
+ { "UEC", "Ultima Electronics Corporation" },
+ { "UEG", "Elitegroup Computer Systems Company Ltd" },
+ { "UEI", "Universal Electronics Inc" },
+ { "UET", "Universal Empowering Technologies" },
+ { "UFG", "UNIGRAF-USA" },
+ { "UFO", "UFO Systems Inc" },
+ { "UHB", "XOCECO" },
+ { "UIC", "Uniform Industrial Corporation" },
+ { "UJR", "Ueda Japan Radio Co., Ltd." },
+ { "ULT", "Ultra Network Tech" },
+ { "UMC", "United Microelectr Corporation" },
+ { "UMG", "Umezawa Giken Co.,Ltd" },
+ { "UMM", "Universal Multimedia" },
+ { "UNA", "Unisys DSD" },
+ { "UNB", "Unisys Corporation" },
+ { "UNC", "Unisys Corporation" },
+ { "UND", "Unisys Corporation" },
+ { "UNE", "Unisys Corporation" },
+ { "UNF", "Unisys Corporation" },
+ { "UNI", "Unisys Corporation" },
+ { "UNM", "Unisys Corporation" },
+ { "UNO", "Unisys Corporation" },
+ { "UNP", "Unitop" },
+ { "UNS", "Unisys Corporation" },
+ { "UNT", "Unisys Corporation" },
+ { "UNY", "Unicate" },
+ { "UPP", "UPPI" },
+ { "UPS", "Systems Enhancement" },
+ { "URD", "Video Computer S.p.A." },
+ { "USA", "Utimaco Safeware AG" },
+ { "USD", "U.S. Digital Corporation" },
+ { "USI", "Universal Scientific Industrial Co., Ltd." },
+ { "USR", "U.S. Robotics Inc" },
+ { "UTD", "Up to Date Tech" },
+ { "UWC", "Uniwill Computer Corp." },
+ { "VAD", "Vaddio, LLC" },
+ { "VAL", "Valence Computing Corporation" },
+ { "VAR", "Varian Australia Pty Ltd" },
+ { "VBR", "VBrick Systems Inc." },
+ { "VBT", "Valley Board Ltda" },
+ { "VCC", "Virtual Computer Corporation" },
+ { "VCI", "VistaCom Inc" },
+ { "VCJ", "Victor Company of Japan, Limited" },
+ { "VCM", "Vector Magnetics, LLC" },
+ { "VCX", "VCONEX" },
+ { "VDA", "Victor Data Systems" },
+ { "VDC", "VDC Display Systems" },
+ { "VDM", "Vadem" },
+ { "VDO", "Video & Display Oriented Corporation" },
+ { "VDS", "Vidisys GmbH & Company" },
+ { "VDT", "Viditec, Inc." },
+ { "VEC", "Vector Informatik GmbH" },
+ { "VEK", "Vektrex" },
+ { "VES", "Vestel Elektronik Sanayi ve Ticaret A. S." },
+ { "VFI", "VeriFone Inc" },
+ { "VHI", "Macrocad Development Inc." },
+ { "VIA", "VIA Tech Inc" },
+ { "VIB", "Tatung UK Ltd" },
+ { "VIC", "Victron B.V." },
{ "VID", "Ingram Macrotron Germany" },
- { "IFZ", "Infinite Z" },
- { "ODM", "ODME Inc." },
- { "ASI", "Ahead Systems" },
- { "ISY", "International Integrated Systems,Inc.(IISI)" },
- { "NCL", "NetComm Ltd" },
- { "ITK", "ITK Telekommunikation AG" },
- { "EZE", "EzE Technologies" },
+ { "VIK", "Viking Connectors" },
+ { "VIM", "Via Mons Ltd." },
+ { "VIN", "Vine Micros Ltd" },
+ { "VIR", "Visual Interface, Inc" },
+ { "VIS", "Visioneer" },
+ { "VIT", "Visitech AS" },
+ { "VIZ", "VIZIO, Inc" },
+ { "VLB", "ValleyBoard Ltda." },
+ { "VLK", "Vislink International Ltd" },
+ { "VLT", "VideoLan Technologies" },
+ { "VMI", "Vermont Microsystems" },
+ { "VML", "Vine Micros Limited" },
+ { "VMW", "VMware Inc.," },
+ { "VNC", "Vinca Corporation" },
+ { "VOB", "MaxData Computer AG" },
+ { "VPI", "Video Products Inc" },
+ { "VPR", "Best Buy" },
+ { "VQ@", "Vision Quest" },
+ { "VRC", "Virtual Resources Corporation" },
+ { "VSC", "ViewSonic Corporation" },
+ { "VSD", "3M" },
+ { "VSI", "VideoServer" },
+ { "VSN", "Ingram Macrotron" },
+ { "VSP", "Vision Systems GmbH" },
{ "VSR", "V-Star Electronics Inc." },
- { "CPC", "Ciprico Inc" },
- { "JWD", "Video International Inc." },
- { "MEC", "Mega System Technologies Inc" },
- { "NVI", "NuVision US, Inc." },
- { "MRK", "Maruko & Company Ltd" },
- { "AAA", "Avolites Ltd" },
- { "CHG", "Sichuan Changhong Electric CO, LTD." },
- { "WWV", "World Wide Video, Inc." },
- { "SEO", "SEOS Ltd" },
- { "XER", "DO NOT USE - XER" },
- { "MCN", "Micron Electronics Inc" },
- { "DXC", "Digipronix Control Systems" },
- { "RSN", "Radiospire Networks, Inc." },
- { "FGD", "Lisa Draexlmaier GmbH" },
- { "SES", "Session Control LLC" },
- { "IIN", "IINFRA Co., Ltd" },
- { "ETI", "Eclipse Tech Inc" },
- { "DXD", "DECIMATOR DESIGN PTY LTD" },
- { "BST", "BodySound Technologies, Inc." },
- { "MTL", "Mitel Corporation" },
- { "LGX", "Lasergraphics, Inc." },
- { "MSP", "Mistral Solutions [P] Ltd." },
- { "SER", "Sony Ericsson Mobile Communications Inc." },
- { "IHE", "InHand Electronics" },
- { "STO", "Stollmann E+V GmbH" },
- { "RET", "Resonance Technology, Inc." },
- { "PXE", "PIXELA CORPORATION" },
- { "USI", "Universal Scientific Industrial Co., Ltd." },
- { "JAC", "Astec Inc" },
+ { "VTC", "VTel Corporation" },
+ { "VTG", "Voice Technologies Group Inc" },
+ { "VTI", "VLSI Tech Inc" },
+ { "VTK", "Viewteck Co., Ltd." },
+ { "VTL", "Vivid Technology Pte Ltd" },
+ { "VTM", "Miltope Corporation" },
+ { "VTN", "VIDEOTRON CORP." },
+ { "VTS", "VTech Computers Ltd" },
+ { "VTV", "VATIV Technologies" },
+ { "VTX", "Vestax Corporation" },
+ { "VUT", "Vutrix (UK) Ltd" },
+ { "VWB", "Vweb Corp." },
{ "WAC", "Wacom Tech" },
- { "BUF", "Yasuhiko Shirai Melco Inc" },
- { "LSI", "Loughborough Sound Images" },
- { "AMA", "Asia Microelectronic Development Inc" },
- { "DJP", "Maygay Machines, Ltd" },
- { "CAN", "CORNEA" },
- { "UMM", "Universal Multimedia" },
- { "ECI", "Enciris Technologies" },
- { "DDT", "Datadesk Technologies Inc" },
- { "MLG", "Micrologica AG" },
- { "NCA", "Nixdorf Company" },
- { "ENS", "Ensoniq Corporation" },
- { "MOT", "Motorola UDS" },
+ { "WAL", "Wave Access" },
+ { "WAN", "DO NOT USE - WAN" },
+ { "WAV", "Wavephore" },
+ { "WBN", "MicroSoftWare" },
+ { "WBS", "WB Systemtechnik GmbH" },
{ "WCI", "Wisecom Inc" },
- { "MXT", "Maxtech Corporation" },
- { "EHJ", "Epson Research" },
- { "KUR", "Kurta Corporation" },
- { "DFT", "DEI Holdings dba Definitive Technology" },
- { "NAD", "NAD Electronics" },
- { "GMK", "GMK Electronic Design GmbH" },
- { "TAI", "Toshiba America Info Systems Inc" },
- { "SNP", "Siemens Nixdorf Info Systems" },
- { "KFE", "Komatsu Forest" },
- { "PPD", "MEPhI" },
- { "UMG", "Umezawa Giken Co.,Ltd" },
- { "PMC", "PMC Consumer Electronics Ltd" },
- { "KIS", "KiSS Technology A/S" },
- { "ABV", "Advanced Research Technology" },
- { "ISA", "Symbol Technologies" },
- { "GMN", "GEMINI 2000 Ltd" },
- { "VSI", "VideoServer" },
- { "DTO", "Deutsche Thomson OHG" },
- { "OCN", "Olfan" },
- { "LTK", "Lucidity Technology Company Ltd" },
- { "CLX", "CardLogix" },
- { "TPT", "Thruput Ltd" },
- { "IXD", "Intertex Data AB" },
- { "ICX", "ICCC A/S" },
- { "REF", "Reflectivity, Inc." },
- { "CDK", "Cray Communications" },
- { "PNX", "Phoenix Technologies, Ltd." },
- { "MCT", "Microtec" },
- { "ESD", "Ensemble Designs, Inc" },
- { "CTS", "Comtec Systems Co., Ltd." },
- { "ADB", "Aldebbaron" },
- { "AML", "Anderson Multimedia Communications (HK) Limited" },
- { "FIN", "Finecom Co., Ltd." },
- { "NCC", "NCR Corporation" },
- { "ONS", "On Systems Inc" },
- { "CGA", "Chunghwa Picture Tubes, LTD" },
- { "NTC", "NeoTech S.R.L" },
- { "AMD", "Amdek Corporation" },
+ { "WCS", "Woodwind Communications Systems Inc" },
+ { "WDC", "Western Digital" },
+ { "WDE", "Westinghouse Digital Electronics" },
+ { "WEB", "WebGear Inc" },
+ { "WEC", "Winbond Electronics Corporation" },
+ { "WEL", "W-DEV" },
+ { "WEY", "WEY Design AG" },
+ { "WHI", "Whistle Communications" },
+ { "WII", "Innoware Inc" },
+ { "WIL", "WIPRO Information Technology Ltd" },
+ { "WIN", "Wintop Technology Inc" },
+ { "WIP", "Wipro Infotech" },
+ { "WKH", "Uni-Take Int'l Inc." },
+ { "WLD", "Wildfire Communications Inc" },
+ { "WML", "Wolfson Microelectronics Ltd" },
+ { "WMO", "Westermo Teleindustri AB" },
+ { "WMT", "Winmate Communication Inc" },
+ { "WNI", "WillNet Inc." },
+ { "WNV", "Winnov L.P." },
+ { "WNX", "Wincor Nixdorf International GmbH" },
+ { "WPA", "Matsushita Communication Industrial Co., Ltd." },
+ { "WPI", "Wearnes Peripherals International (Pte) Ltd" },
+ { "WRC", "WiNRADiO Communications" },
+ { "WSC", "CIS Technology Inc" },
+ { "WSP", "Wireless And Smart Products Inc." },
+ { "WST", "Wistron Corporation" },
+ { "WTC", "ACC Microelectronics" },
+ { "WTI", "WorkStation Tech" },
+ { "WTK", "Wearnes Thakral Pte" },
+ { "WTS", "Restek Electric Company Ltd" },
+ { "WVM", "Wave Systems Corporation" },
{ "WVV", "WolfVision GmbH" },
- { "PHO", "Photonics Systems Inc." },
- { "AVX", "AVerMedia Technologies, Inc." },
- { "SJE", "Sejin Electron Inc" },
- { "BCM", "Broadcom" },
- { "RLN", "RadioLAN Inc" },
- { "CAM", "Cambridge Audio" },
- { "TCS", "Tatung Company of America Inc" },
- { "RIO", "Rios Systems Company Ltd" },
- { "SWT", "Software Technologies Group,Inc." },
- { "BSL", "Biomedical Systems Laboratory" },
- { "DCV", "Datatronics Technology Inc" },
- { "JPC", "JPC Technology Limited" },
- { "ICC", "BICC Data Networks Ltd" },
- { "CEI", "Crestron Electronics, Inc." },
- { "NUI", "NU Inc." },
- { "MAE", "Maestro Pty Ltd" },
- { "AYR", "Airlib, Inc" },
- { "TPS", "Teleprocessing Systeme GmbH" },
- { "SMK", "SMK CORPORATION" },
- { "IAT", "IAT Germany GmbH" },
- { "BNO", "Bang & Olufsen" },
- { "KRY", "Kroy LLC" },
- { "OLT", "Olitec S.A." },
- { "ABC", "AboCom System Inc" },
- { "FXX", "Fuji Xerox" },
- { "ANI", "Anigma Inc" },
- { "OEI", "Optum Engineering Inc." },
- { "TPE", "Technology Power Enterprises Inc" },
- { "RDI", "Rainbow Displays, Inc." },
- { "KDK", "Kodiak Tech" },
- { "LHT", "Lighthouse Technologies Limited" },
- { "BEK", "Beko Elektronik A.S." },
- { "LND", "Land Computer Company Ltd" },
- { "CDC", "Core Dynamics Corporation" },
- { "FHL", "FHLP" },
- { "UNP", "Unitop" },
- { "MSR", "MASPRO DENKOH Corp." },
- { "MKC", "Media Tek Inc." },
- { "BCD", "Barco GmbH" },
- { "PQI", "Pixel Qi" },
- { "ALD", "In4S Inc" },
- { "HTC", "Hitachi Ltd" },
- { "OCD", "Macraigor Systems Inc" },
- { "PHY", "Phylon Communications" },
- { "MSF", "M-Systems Flash Disk Pioneers" },
- { "ETK", "eTEK Labs Inc." },
- { "DVS", "Digital Video System" },
- { "ACU", "Acculogic" },
+ { "WWV", "World Wide Video, Inc." },
+ { "WXT", "Woxter Technology Co. Ltd" },
+ { "WYS", "Wyse Technology" },
+ { "WYT", "Wooyoung Image & Information Co.,Ltd." },
+ { "XAC", "XAC Automation Corp" },
+ { "XAD", "Alpha Data" },
+ { "XDM", "XDM Ltd." },
+ { "XER", "DO NOT USE - XER" },
+ { "XFG", "Jan Strapko - FOTO" },
+ { "XFO", "EXFO Electro Optical Engineering" },
+ { "XIN", "Xinex Networks Inc" },
+ { "XIO", "Xiotech Corporation" },
+ { "XIR", "Xirocm Inc" },
+ { "XIT", "Xitel Pty ltd" },
+ { "XLX", "Xilinx, Inc." },
+ { "XMM", "C3PO S.L." },
+ { "XNT", "XN Technologies, Inc." },
+ { "XOC", "DO NOT USE - XOC" },
+ { "XQU", "SHANGHAI SVA-DAV ELECTRONICS CO., LTD" },
+ { "XRC", "Xircom Inc" },
+ { "XRO", "XORO ELECTRONICS (CHENGDU) LIMITED" },
+ { "XSN", "Xscreen AS" },
+ { "XST", "XS Technologies Inc" },
+ { "XSY", "XSYS" },
+ { "XTD", "Icuiti Corporation" },
+ { "XTE", "X2E GmbH" },
+ { "XTL", "Crystal Computer" },
+ { "XTN", "X-10 (USA) Inc" },
+ { "XYC", "Xycotec Computer GmbH" },
+ { "YED", "Y-E Data Inc" },
+ { "YHQ", "Yokogawa Electric Corporation" },
+ { "YHW", "Exacom SA" },
+ { "YMH", "Yamaha Corporation" },
{ "YOW", "American Biometric Company" },
- { "MGE", "Schneider Electric S.A." },
- { "AKP", "Atom Komplex Prylad" },
- { "PGI", "PACSGEAR, Inc." },
- { "III", "Intelligent Instrumentation" },
- { "BML", "BIOMED Lab" },
- { "KMC", "Mitsumi Company Ltd" },
- { "RSQ", "R Squared" },
- { "SBC", "Shanghai Bell Telephone Equip Mfg Co" },
- { "FPX", "Cirel Systemes" },
- { "IDN", "Idneo Technologies" },
- { "BNE", "Bull AB" },
+ { "ZAN", "Zandar Technologies plc" },
+ { "ZAX", "Zefiro Acoustics" },
+ { "ZAZ", "Zazzle Technologies" },
+ { "ZBR", "Zebra Technologies International, LLC" },
+ { "ZCT", "ZeitControl cardsystems GmbH" },
+ { "ZDS", "Zenith Data Systems" },
+ { "ZGT", "Zenith Data Systems" },
+ { "ZIC", "Nationz Technologies Inc." },
+ { "ZMT", "Zalman Tech Co., Ltd." },
+ { "ZMZ", "Z Microsystems" },
+ { "ZNI", "Zetinet Inc" },
+ { "ZNX", "Znyx Adv. Systems" },
+ { "ZOW", "Zowie Intertainment, Inc" },
+ { "ZRN", "Zoran Corporation" },
+ { "ZSE", "Zenith Data Systems" },
+ { "ZTC", "ZyDAS Technology Corporation" },
+ { "ZTE", "ZTE Corporation" },
+ { "ZTI", "Zoom Telephonics Inc" },
+ { "ZTM", "ZT Group Int'l Inc." },
+ { "ZTT", "Z3 Technology" },
+ { "ZYD", "Zydacron Inc" },
+ { "ZYP", "Zypcom Inc" },
+ { "ZYT", "Zytex Computers" },
+ { "ZYX", "Zyxel" },
+ { "ZZZ", "Boca Research Inc" },
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/eglconvenience/qxlibeglintegration.cpp b/src/platformsupport/eglconvenience/qxlibeglintegration.cpp
index 565dbfb11b..ac743e1e38 100644
--- a/src/platformsupport/eglconvenience/qxlibeglintegration.cpp
+++ b/src/platformsupport/eglconvenience/qxlibeglintegration.cpp
@@ -91,21 +91,21 @@ VisualID QXlibEglIntegration::getCompatibleVisualId(Display *display, EGLDisplay
int visualRedSize = qPopulationCount(chosenVisualInfo->red_mask);
int visualGreenSize = qPopulationCount(chosenVisualInfo->green_mask);
int visualBlueSize = qPopulationCount(chosenVisualInfo->blue_mask);
- int visualAlphaSize = chosenVisualInfo->depth == 32 ? 8 : 0;
+ int visualAlphaSize = chosenVisualInfo->depth - visualRedSize - visualBlueSize - visualGreenSize;
- const bool visualMatchesConfig = visualRedSize == configRedSize
- && visualGreenSize == configGreenSize
- && visualBlueSize == configBlueSize
- && visualAlphaSize == configAlphaSize;
+ const bool visualMatchesConfig = visualRedSize >= configRedSize
+ && visualGreenSize >= configGreenSize
+ && visualBlueSize >= configBlueSize
+ && visualAlphaSize >= configAlphaSize;
// In some cases EGL tends to suggest a 24-bit visual for 8888
// configs. In such a case we have to fall back to XGetVisualInfo.
if (!visualMatchesConfig) {
visualId = 0;
qCDebug(lcXlibEglDebug,
- "EGL suggested using X Visual ID %d (%d %d %d depth %d) for EGL config %d"
+ "EGL suggested using X Visual ID %d (%d %d %d %d depth %d) for EGL config %d"
"(%d %d %d %d), but this is incompatible",
- (int)visualId, visualRedSize, visualGreenSize, visualBlueSize, chosenVisualInfo->depth,
+ (int)visualId, visualRedSize, visualGreenSize, visualBlueSize, visualAlphaSize, chosenVisualInfo->depth,
configId, configRedSize, configGreenSize, configBlueSize, configAlphaSize);
}
} else {
diff --git a/src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp b/src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp
index 06f0aa6747..0ccbf01e80 100644
--- a/src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp
+++ b/src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp
@@ -48,26 +48,76 @@
QT_BEGIN_NAMESPACE
+struct GUserEventSource
+{
+ GSource source;
+ QPAEventDispatcherGlib *q;
+ QPAEventDispatcherGlibPrivate *d;
+};
+
+static gboolean userEventSourcePrepare(GSource *source, gint *timeout)
+{
+ Q_UNUSED(timeout)
+ GUserEventSource *userEventSource = reinterpret_cast<GUserEventSource *>(source);
+ return userEventSource->d->wakeUpCalled;
+}
+
+static gboolean userEventSourceCheck(GSource *source)
+{
+ return userEventSourcePrepare(source, 0);
+}
+
+static gboolean userEventSourceDispatch(GSource *source, GSourceFunc, gpointer)
+{
+ GUserEventSource *userEventSource = reinterpret_cast<GUserEventSource *>(source);
+ QPAEventDispatcherGlib *dispatcher = userEventSource->q;
+ QWindowSystemInterface::sendWindowSystemEvents(dispatcher->m_flags);
+ return true;
+}
+
+static GSourceFuncs userEventSourceFuncs = {
+ userEventSourcePrepare,
+ userEventSourceCheck,
+ userEventSourceDispatch,
+ NULL,
+ NULL,
+ NULL
+};
+
QPAEventDispatcherGlibPrivate::QPAEventDispatcherGlibPrivate(GMainContext *context)
: QEventDispatcherGlibPrivate(context)
{
+ Q_Q(QPAEventDispatcherGlib);
+ userEventSource = reinterpret_cast<GUserEventSource *>(g_source_new(&userEventSourceFuncs,
+ sizeof(GUserEventSource)));
+ userEventSource->q = q;
+ userEventSource->d = this;
+ g_source_set_can_recurse(&userEventSource->source, true);
+ g_source_attach(&userEventSource->source, mainContext);
}
+
QPAEventDispatcherGlib::QPAEventDispatcherGlib(QObject *parent)
: QEventDispatcherGlib(*new QPAEventDispatcherGlibPrivate, parent)
, m_flags(QEventLoop::AllEvents)
{
+ Q_D(QPAEventDispatcherGlib);
+ d->userEventSource->q = this;
}
QPAEventDispatcherGlib::~QPAEventDispatcherGlib()
{
+ Q_D(QPAEventDispatcherGlib);
+
+ g_source_destroy(&d->userEventSource->source);
+ g_source_unref(&d->userEventSource->source);
+ d->userEventSource = 0;
}
bool QPAEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags)
{
m_flags = flags;
- const bool didSendEvents = QEventDispatcherGlib::processEvents(m_flags);
- return QWindowSystemInterface::sendWindowSystemEvents(m_flags) || didSendEvents;
+ return QEventDispatcherGlib::processEvents(m_flags);
}
QT_END_NAMESPACE
diff --git a/src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h b/src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h
index 5930dc68e7..085a1c52f3 100644
--- a/src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h
+++ b/src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h
@@ -71,11 +71,14 @@ public:
QEventLoop::ProcessEventsFlags m_flags;
};
+struct GUserEventSource;
+
class QPAEventDispatcherGlibPrivate : public QEventDispatcherGlibPrivate
{
Q_DECLARE_PUBLIC(QPAEventDispatcherGlib)
public:
QPAEventDispatcherGlibPrivate(GMainContext *context = 0);
+ GUserEventSource *userEventSource;
};
diff --git a/src/platformsupport/eventdispatchers/qgenericunixeventdispatcher.cpp b/src/platformsupport/eventdispatchers/qgenericunixeventdispatcher.cpp
index 11d9c259d5..2e1d81a181 100644
--- a/src/platformsupport/eventdispatchers/qgenericunixeventdispatcher.cpp
+++ b/src/platformsupport/eventdispatchers/qgenericunixeventdispatcher.cpp
@@ -43,7 +43,7 @@
QT_BEGIN_NAMESPACE
-class QAbstractEventDispatcher *createUnixEventDispatcher()
+class QAbstractEventDispatcher *QtGenericUnixDispatcher::createUnixEventDispatcher()
{
#if !defined(QT_NO_GLIB) && !defined(Q_OS_WIN)
if (qEnvironmentVariableIsEmpty("QT_NO_GLIB") && QEventDispatcherGlib::versionSupported())
diff --git a/src/platformsupport/eventdispatchers/qgenericunixeventdispatcher_p.h b/src/platformsupport/eventdispatchers/qgenericunixeventdispatcher_p.h
index adf70adc05..61b4d0515c 100644
--- a/src/platformsupport/eventdispatchers/qgenericunixeventdispatcher_p.h
+++ b/src/platformsupport/eventdispatchers/qgenericunixeventdispatcher_p.h
@@ -56,7 +56,10 @@
QT_BEGIN_NAMESPACE
class QAbstractEventDispatcher;
+namespace QtGenericUnixDispatcher {
QAbstractEventDispatcher* createUnixEventDispatcher();
+}
+using QtGenericUnixDispatcher::createUnixEventDispatcher;
QT_END_NAMESPACE
diff --git a/src/platformsupport/eventdispatchers/qunixeventdispatcher.cpp b/src/platformsupport/eventdispatchers/qunixeventdispatcher.cpp
index 7438ab65c1..44258538ec 100644
--- a/src/platformsupport/eventdispatchers/qunixeventdispatcher.cpp
+++ b/src/platformsupport/eventdispatchers/qunixeventdispatcher.cpp
@@ -43,14 +43,9 @@
#include "private/qguiapplication_p.h"
#include <qpa/qwindowsysteminterface.h>
-#include <QtCore/QElapsedTimer>
-#include <QtCore/QAtomicInt>
-#include <QtCore/QSemaphore>
#include <QtCore/QDebug>
-#include <errno.h>
-
QT_BEGIN_NAMESPACE
QT_USE_NAMESPACE
diff --git a/src/platformsupport/eventdispatchers/qunixeventdispatcher_qpa_p.h b/src/platformsupport/eventdispatchers/qunixeventdispatcher_qpa_p.h
index 23be081ba3..7f775b73ee 100644
--- a/src/platformsupport/eventdispatchers/qunixeventdispatcher_qpa_p.h
+++ b/src/platformsupport/eventdispatchers/qunixeventdispatcher_qpa_p.h
@@ -56,12 +56,9 @@
QT_BEGIN_NAMESPACE
-class QUnixEventDispatcherQPAPrivate;
-
class QUnixEventDispatcherQPA : public QEventDispatcherUNIX
{
Q_OBJECT
- Q_DECLARE_PRIVATE(QUnixEventDispatcherQPA)
public:
explicit QUnixEventDispatcherQPA(QObject *parent = 0);
diff --git a/src/platformsupport/eventdispatchers/qwindowsguieventdispatcher.cpp b/src/platformsupport/eventdispatchers/qwindowsguieventdispatcher.cpp
index aa7bb102c6..a37547f513 100644
--- a/src/platformsupport/eventdispatchers/qwindowsguieventdispatcher.cpp
+++ b/src/platformsupport/eventdispatchers/qwindowsguieventdispatcher.cpp
@@ -184,7 +184,33 @@ messageDebugEntries[] = {
{WM_DRAWCLIPBOARD, "WM_DRAWCLIPBOARD", true},
{WM_THEMECHANGED, "WM_THEMECHANGED", true},
{0x90, "WM_UAHDESTROYWINDOW", true},
- {0x272, "WM_UNREGISTER_WINDOW_SERVICES", true}
+ {0x272, "WM_UNREGISTER_WINDOW_SERVICES", true},
+#ifdef WM_POINTERUPDATE
+ {WM_POINTERDEVICECHANGE, "WM_POINTERDEVICECHANGE", true},
+ {WM_POINTERDEVICEINRANGE, "WM_POINTERDEVICEINRANGE", true},
+ {WM_POINTERDEVICEOUTOFRANGE, "WM_POINTERDEVICEOUTOFRANGE", true},
+ {WM_NCPOINTERUPDATE, "WM_NCPOINTERUPDATE", true},
+ {WM_NCPOINTERDOWN, "WM_NCPOINTERDOWN", true},
+ {WM_NCPOINTERUP, "WM_NCPOINTERUP", true},
+ {WM_POINTERUPDATE, "WM_POINTERUPDATE", true},
+ {WM_POINTERDOWN, "WM_POINTERDOWN", true},
+ {WM_POINTERUP, "WM_POINTERUP", true},
+ {WM_POINTERENTER, "WM_POINTERENTER", true},
+ {WM_POINTERLEAVE, "WM_POINTERLEAVE", true},
+ {WM_POINTERACTIVATE, "WM_POINTERACTIVATE", true},
+ {WM_POINTERCAPTURECHANGED, "WM_POINTERCAPTURECHANGED", true},
+ {WM_TOUCHHITTESTING, "WM_TOUCHHITTESTING", true},
+ {WM_POINTERWHEEL, "WM_POINTERWHEEL", true},
+ {WM_POINTERHWHEEL, "WM_POINTERHWHEEL", true},
+#endif // WM_POINTERUPDATE
+#ifdef DM_POINTERHITTEST
+ {DM_POINTERHITTEST, "DM_POINTERHITTEST", true},
+#endif // DM_POINTERHITTEST
+#ifdef WM_POINTERROUTEDTO
+ {WM_POINTERROUTEDTO, "WM_POINTERROUTEDTO", true},
+ {WM_POINTERROUTEDAWAY, "WM_POINTERROUTEDAWAY", true},
+ {WM_POINTERROUTEDRELEASED, "WM_POINTERROUTEDRELEASED", true},
+#endif // WM_POINTERROUTEDTO
};
static inline const MessageDebugEntry *messageDebugEntry(UINT msg)
diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp
index dabe2bc09e..7b4f6aa107 100644
--- a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp
+++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp
@@ -139,14 +139,6 @@ QtFreetypeData::~QtFreetypeData()
library = 0;
}
-#ifdef QT_NO_THREAD
-Q_GLOBAL_STATIC(QtFreetypeData, theFreetypeData)
-
-QtFreetypeData *qt_getFreetypeData()
-{
- return theFreetypeData();
-}
-#else
Q_GLOBAL_STATIC(QThreadStorage<QtFreetypeData *>, theFreetypeData)
QtFreetypeData *qt_getFreetypeData()
@@ -169,7 +161,6 @@ QtFreetypeData *qt_getFreetypeData()
}
return freetypeData;
}
-#endif
FT_Library qt_getFreetype()
{
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
index 91c2dc8cf0..5ac28ce798 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
@@ -101,14 +101,14 @@ enum { LanguageCount = sizeof(languageForWritingSystem) / sizeof(const char *) }
#ifdef Q_OS_OSX
static NSInteger languageMapSort(id obj1, id obj2, void *context)
{
- NSArray *map1 = (NSArray *) obj1;
- NSArray *map2 = (NSArray *) obj2;
- NSArray *languages = (NSArray *) context;
+ NSArray<NSString *> *map1 = reinterpret_cast<NSArray<NSString *> *>(obj1);
+ NSArray<NSString *> *map2 = reinterpret_cast<NSArray<NSString *> *>(obj2);
+ NSArray<NSString *> *languages = reinterpret_cast<NSArray<NSString *> *>(context);
- NSString *lang1 = [map1 objectAtIndex: 0];
- NSString *lang2 = [map2 objectAtIndex: 0];
+ NSString *lang1 = [map1 objectAtIndex:0];
+ NSString *lang2 = [map2 objectAtIndex:0];
- return [languages indexOfObject: lang1] - [languages indexOfObject: lang2];
+ return [languages indexOfObject:lang1] - [languages indexOfObject:lang2];
}
#endif
@@ -184,23 +184,9 @@ QCoreTextFontDatabase::~QCoreTextFontDatabase()
CFRelease(ref);
}
-static CFArrayRef availableFamilyNames()
-{
-#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(1060, 100000, 100000, 30000)
- if (&CTFontManagerCopyAvailableFontFamilyNames)
- return CTFontManagerCopyAvailableFontFamilyNames();
-#endif
-#if defined(QT_PLATFORM_UIKIT)
- CFMutableArrayRef familyNames = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, (CFArrayRef)[UIFont familyNames]);
- CFArrayAppendValue(familyNames, CFSTR(".PhoneFallback"));
- return familyNames;
-#endif
- Q_UNREACHABLE();
-}
-
void QCoreTextFontDatabase::populateFontDatabase()
{
- QCFType<CFArrayRef> familyNames = availableFamilyNames();
+ QCFType<CFArrayRef> familyNames = CTFontManagerCopyAvailableFontFamilyNames();
for (NSString *familyName in familyNames.as<const NSArray *>())
QPlatformFontDatabase::registerFontFamily(QString::fromNSString(familyName));
@@ -220,7 +206,7 @@ bool QCoreTextFontDatabase::populateFamilyAliases()
if (m_hasPopulatedAliases)
return false;
- QCFType<CFArrayRef> familyNames = availableFamilyNames();
+ QCFType<CFArrayRef> familyNames = CTFontManagerCopyAvailableFontFamilyNames();
for (NSString *familyName in familyNames.as<const NSArray *>()) {
NSFontManager *fontManager = [NSFontManager sharedFontManager];
NSString *localizedFamilyName = [fontManager localizedNameForFamily:familyName face:nil];
@@ -331,9 +317,9 @@ static void getFontDescription(CTFontDescriptorRef font, FontDescription *fd)
if (styles) {
if (CFNumberRef weightValue = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontWeightTrait)) {
- float normalizedWeight;
- if (CFNumberGetValue(weightValue, kCFNumberFloatType, &normalizedWeight))
- fd->weight = QCoreTextFontEngine::qtWeightFromCFWeight(normalizedWeight);
+ double normalizedWeight;
+ if (CFNumberGetValue(weightValue, kCFNumberFloat64Type, &normalizedWeight))
+ fd->weight = QCoreTextFontEngine::qtWeightFromCFWeight(float(normalizedWeight));
}
if (CFNumberRef italic = (CFNumberRef) CFDictionaryGetValue(styles, kCTFontSlantTrait)) {
double d;
@@ -571,21 +557,21 @@ QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFo
if (!didPopulateStyleFallbacks) {
#if defined(Q_OS_MACX)
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
- NSArray *languages = [defaults stringArrayForKey: @"AppleLanguages"];
+ NSArray<NSString *> *languages = [defaults stringArrayForKey:@"AppleLanguages"];
- NSDictionary *fallbackDict = [NSDictionary dictionaryWithContentsOfFile: @"/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreText.framework/Resources/DefaultFontFallbacks.plist"];
+ NSDictionary<NSString *, id> *fallbackDict = [NSDictionary<NSString *, id> dictionaryWithContentsOfFile:@"/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreText.framework/Resources/DefaultFontFallbacks.plist"];
for (NSString *style in [fallbackDict allKeys]) {
- NSArray *list = [fallbackDict valueForKey: style];
+ NSArray *list = [fallbackDict valueForKey:style];
QFont::StyleHint fallbackStyleHint = styleHintFromNSString(style);
QStringList fallbackList;
for (id item in list) {
// sort the array based on system language preferences
- if ([item isKindOfClass: [NSArray class]]) {
- NSArray *langs = [(NSArray *) item sortedArrayUsingFunction: languageMapSort
- context: languages];
- for (NSArray *map in langs)
- fallbackList.append(familyNameFromPostScriptName([map objectAtIndex: 1]));
+ if ([item isKindOfClass:[NSArray class]]) {
+ NSArray *langs = [reinterpret_cast<NSArray *>(item)
+ sortedArrayUsingFunction:languageMapSort context:languages];
+ for (NSArray<NSString *> *map in langs)
+ fallbackList.append(familyNameFromPostScriptName([map objectAtIndex:1]));
}
else if ([item isKindOfClass: [NSString class]])
fallbackList.append(familyNameFromPostScriptName(item));
diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
index 98b753eff9..6543759a3d 100644
--- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
+++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
@@ -42,6 +42,7 @@
#include <qpa/qplatformfontdatabase.h>
#include <QtCore/qendian.h>
#include <QtCore/qsettings.h>
+#include <QtCore/qoperatingsystemversion.h>
#include <private/qimage_p.h>
@@ -652,17 +653,36 @@ bool QCoreTextFontEngine::expectsGammaCorrectedBlending() const
QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, bool aa, const QTransform &matrix)
{
-
glyph_metrics_t br = alphaMapBoundingBox(glyph, subPixelPosition, matrix, glyphFormat);
bool isColorGlyph = glyphFormat == QFontEngine::Format_ARGB;
QImage::Format imageFormat = isColorGlyph ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;
QImage im(br.width.ceil().toInt(), br.height.ceil().toInt(), imageFormat);
- im.fill(0);
-
if (!im.width() || !im.height())
return im;
+#if defined(Q_OS_MACOS)
+ CGColorRef glyphColor = CGColorGetConstantColor(kCGColorWhite);
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave) {
+ // macOS 10.14 uses a new font smoothing algorithm that takes the fill color into
+ // account. This means our default approach of drawing white on black to produce
+ // the alpha map will result in non-native looking text when then drawn as black
+ // on white during the final blit. As a workaround we use the application's current
+ // appearance to decide whether to draw with white or black fill, and then invert
+ // the glyph image in the latter case, producing an alpha map. This covers the
+ // most common use-cases, but longer term we should propagate the fill color all
+ // the way from the paint engine, and include it in the key for the glyph cache.
+ if (!qt_mac_applicationIsInDarkMode())
+ glyphColor = CGColorGetConstantColor(kCGColorBlack);
+ }
+ const bool blackOnWhiteGlyphs = !isColorGlyph
+ && CGColorEqualToColor(glyphColor, CGColorGetConstantColor(kCGColorBlack));
+ if (blackOnWhiteGlyphs)
+ im.fill(Qt::white);
+ else
+#endif
+ im.fill(0); // Faster than Qt::black
+
CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
uint cgflags = isColorGlyph ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst;
#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version
@@ -696,7 +716,11 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition
if (!isColorGlyph) {
CGContextSetTextMatrix(ctx, cgMatrix);
+#if defined(Q_OS_MACOS)
+ CGContextSetFillColorWithColor(ctx, glyphColor);
+#else
CGContextSetRGBFillColor(ctx, 1, 1, 1, 1);
+#endif
CGContextSetTextDrawingMode(ctx, kCGTextFill);
CGContextSetTextPosition(ctx, pos_x, pos_y);
@@ -721,6 +745,11 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition
CGContextRelease(ctx);
CGColorSpaceRelease(colorspace);
+#if defined(Q_OS_MACOS)
+ if (blackOnWhiteGlyphs)
+ im.invertPixels();
+#endif
+
return im;
}
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
index 8df8da1a38..c70d507b99 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
@@ -368,6 +368,7 @@ namespace {
class DirectWriteFontFileStream: public IDWriteFontFileStream
{
+ Q_DISABLE_COPY(DirectWriteFontFileStream)
public:
DirectWriteFontFileStream(const QByteArray &fontData)
: m_fontData(fontData)
@@ -799,9 +800,9 @@ enum PlatformFieldValue {
PlatformId_Microsoft = 3
};
-FontNames qt_getCanonicalFontNames(const uchar *table, quint32 bytes)
+QFontNames qt_getCanonicalFontNames(const uchar *table, quint32 bytes)
{
- FontNames out;
+ QFontNames out;
const int NameRecordSize = 12;
const int MS_LangIdEnglish = 0x009;
@@ -947,7 +948,7 @@ QString qt_getEnglishName(const QString &familyName, bool includeStyle)
goto error;
{
- const FontNames names = qt_getCanonicalFontNames(table, bytes);
+ const QFontNames names = qt_getCanonicalFontNames(table, bytes);
i18n_name = names.name;
if (includeStyle)
i18n_name += QLatin1Char(' ') + names.style;
@@ -963,9 +964,9 @@ error:
}
// Note this duplicates parts of qt_getEnglishName, we should try to unify the two functions.
-FontNames qt_getCanonicalFontNames(const LOGFONT &lf)
+QFontNames qt_getCanonicalFontNames(const LOGFONT &lf)
{
- FontNames fontNames;
+ QFontNames fontNames;
HDC hdc = GetDC(0);
HFONT hfont = CreateFontIndirect(&lf);
@@ -1054,7 +1055,7 @@ static bool addFontToDatabase(QString familyName,
QString subFamilyStyle;
if (ttf) {
// Look-up names registered in the font
- FontNames canonicalNames = qt_getCanonicalFontNames(logFont);
+ QFontNames canonicalNames = qt_getCanonicalFontNames(logFont);
if (qt_localizedName(familyName) && !canonicalNames.name.isEmpty())
englishName = canonicalNames.name;
if (!canonicalNames.preferredName.isEmpty()) {
@@ -1231,7 +1232,6 @@ void QWindowsFontDatabase::populateFontDatabase()
typedef QSharedPointer<QWindowsFontEngineData> QWindowsFontEngineDataPtr;
-#ifndef QT_NO_THREAD
typedef QThreadStorage<QWindowsFontEngineDataPtr> FontEngineThreadLocalData;
Q_GLOBAL_STATIC(FontEngineThreadLocalData, fontEngineThreadLocalData)
@@ -1243,17 +1243,6 @@ QSharedPointer<QWindowsFontEngineData> sharedFontData()
data->setLocalData(QSharedPointer<QWindowsFontEngineData>::create());
return data->localData();
}
-#else // !QT_NO_THREAD
-Q_GLOBAL_STATIC(QWindowsFontEngineDataPtr, fontEngineData)
-
-QWindowsFontEngineDataPtr sharedFontData()
-{
- QWindowsFontEngineDataPtr *data = fontEngineData();
- if (data->isNull())
- *data = QWindowsFontEngineDataPtr::create();
- return *data;
-}
-#endif // QT_NO_THREAD
QWindowsFontDatabase::QWindowsFontDatabase()
{
@@ -1500,7 +1489,7 @@ static void getFontTable(const uchar *fileBegin, const uchar *data, quint32 tag,
}
static void getFamiliesAndSignatures(const QByteArray &fontData,
- QList<FontNames> *families,
+ QList<QFontNames> *families,
QVector<FONTSIGNATURE> *signatures)
{
const uchar *data = reinterpret_cast<const uchar *>(fontData.constData());
@@ -1516,7 +1505,7 @@ static void getFamiliesAndSignatures(const QByteArray &fontData,
getFontTable(data, font, MAKE_TAG('n', 'a', 'm', 'e'), &table, &length);
if (!table)
continue;
- FontNames names = qt_getCanonicalFontNames(table, length);
+ QFontNames names = qt_getCanonicalFontNames(table, length);
if (names.name.isEmpty())
continue;
@@ -1547,7 +1536,7 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData,
WinApplicationFont font;
font.fileName = fileName;
QVector<FONTSIGNATURE> signatures;
- QList<FontNames> families;
+ QList<QFontNames> families;
QStringList familyNames;
if (!fontData.isEmpty()) {
@@ -1616,11 +1605,12 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData,
void QWindowsFontDatabase::removeApplicationFonts()
{
- foreach (const WinApplicationFont &font, m_applicationFonts) {
+ for (const WinApplicationFont &font : qAsConst(m_applicationFonts)) {
if (font.handle) {
RemoveFontMemResourceEx(font.handle);
} else {
- RemoveFontResourceExW((LPCWSTR)font.fileName.utf16(), FR_PRIVATE, 0);
+ RemoveFontResourceExW(reinterpret_cast<LPCWSTR>(font.fileName.utf16()),
+ FR_PRIVATE, nullptr);
}
}
m_applicationFonts.clear();
@@ -1664,7 +1654,8 @@ void QWindowsFontDatabase::refUniqueFont(const QString &uniqueFont)
// ### fixme Qt 6 (QTBUG-58610): See comment at QWindowsFontDatabase::systemDefaultFont()
HFONT QWindowsFontDatabase::systemFont()
{
- static const HFONT stock_sysfont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
+ static const auto stock_sysfont =
+ reinterpret_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT));
return stock_sysfont;
}
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp
index 299dfd40cd..f68ea54dcf 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp
@@ -210,7 +210,7 @@ static bool addFontToDatabase(QString familyName,
QString subFamilyStyle;
if (ttf) {
// Look-up names registered in the font
- FontNames canonicalNames = qt_getCanonicalFontNames(logFont);
+ QFontNames canonicalNames = qt_getCanonicalFontNames(logFont);
if (qt_localizedName(familyName) && !canonicalNames.name.isEmpty())
englishName = canonicalNames.name;
if (!canonicalNames.preferredName.isEmpty()) {
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h
index 30f5beefdf..ab6d6307c7 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h
@@ -85,6 +85,7 @@ public:
class QWindowsFontDatabase : public QPlatformFontDatabase
{
+ Q_DISABLE_COPY(QWindowsFontDatabase)
public:
enum FontOptions {
// Relevant bits from QWindowsIntegration::Options
@@ -93,7 +94,7 @@ public:
};
QWindowsFontDatabase();
- ~QWindowsFontDatabase();
+ ~QWindowsFontDatabase() override;
void populateFontDatabase() override;
void populateFamily(const QString &familyName) override;
@@ -168,7 +169,8 @@ inline quint16 qt_getUShort(const unsigned char *p)
return val;
}
-struct FontNames {
+struct QFontNames
+{
QString name; // e.g. "DejaVu Sans Condensed"
QString style; // e.g. "Italic"
QString preferredName; // e.g. "DejaVu Sans"
@@ -177,7 +179,7 @@ struct FontNames {
bool qt_localizedName(const QString &name);
QString qt_getEnglishName(const QString &familyName, bool includeStyle = false);
-FontNames qt_getCanonicalFontNames(const LOGFONT &lf);
+QFontNames qt_getCanonicalFontNames(const LOGFONT &lf);
QT_END_NAMESPACE
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp
index 584e4db05d..2a41209225 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp
@@ -111,9 +111,8 @@ QFixed QWindowsFontEngine::lineThickness() const
static OUTLINETEXTMETRIC *getOutlineTextMetric(HDC hdc)
{
- int size;
- size = GetOutlineTextMetrics(hdc, 0, 0);
- OUTLINETEXTMETRIC *otm = (OUTLINETEXTMETRIC *)malloc(size);
+ const auto size = GetOutlineTextMetrics(hdc, 0, nullptr);
+ auto otm = reinterpret_cast<OUTLINETEXTMETRIC *>(malloc(size));
GetOutlineTextMetrics(hdc, size, otm);
return otm;
}
@@ -1140,7 +1139,7 @@ QImage QWindowsFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed, const QTra
QImage rgbMask(mask->width(), mask->height(), QImage::Format_RGB32);
for (int y=0; y<mask->height(); ++y) {
- uint *dest = (uint *) rgbMask.scanLine(y);
+ auto dest = reinterpret_cast<uint *>(rgbMask.scanLine(y));
const uint *src = reinterpret_cast<const uint *>(source.constScanLine(y));
for (int x=0; x<mask->width(); ++x) {
dest[x] = 0xffffffff - (0x00ffffff & src[x]);
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h
index 2ec391c4da..a151cf7343 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h
@@ -66,13 +66,14 @@ class QWindowsFontEngineData;
class QWindowsFontEngine : public QFontEngine
{
+ Q_DISABLE_COPY(QWindowsFontEngine)
friend class QWindowsMultiFontEngine;
public:
QWindowsFontEngine(const QString &name, LOGFONT lf,
const QSharedPointer<QWindowsFontEngineData> &fontEngineData);
- ~QWindowsFontEngine();
+ ~QWindowsFontEngine() override;
void initFontInfo(const QFontDef &request,
int dpi);
@@ -89,7 +90,7 @@ public:
void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags) const override;
void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) override;
- virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
+ void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
QPainterPath *path, QTextItem::RenderFlags flags) override;
HGDIOBJ selectDesignFont() const;
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp
index 0e017c3b77..57c41938bc 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp
@@ -69,15 +69,14 @@ namespace {
class GeometrySink: public IDWriteGeometrySink
{
+ Q_DISABLE_COPY(GeometrySink)
public:
GeometrySink(QPainterPath *path)
: m_refCount(0), m_path(path)
{
Q_ASSERT(m_path != 0);
}
- virtual ~GeometrySink()
- {
- }
+ virtual ~GeometrySink() = default;
IFACEMETHOD_(void, AddBeziers)(const D2D1_BEZIER_SEGMENT *beziers, UINT bezierCount);
IFACEMETHOD_(void, AddLines)(const D2D1_POINT_2F *points, UINT pointCount);
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite_p.h
index 83fdddfa26..9326f5aece 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite_p.h
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite_p.h
@@ -72,11 +72,12 @@ class QWindowsFontEngineData;
class QWindowsFontEngineDirectWrite : public QFontEngine
{
+ Q_DISABLE_COPY(QWindowsFontEngineDirectWrite)
public:
explicit QWindowsFontEngineDirectWrite(IDWriteFontFace *directWriteFontFace,
qreal pixelSize,
const QSharedPointer<QWindowsFontEngineData> &d);
- ~QWindowsFontEngineDirectWrite();
+ ~QWindowsFontEngineDirectWrite() override;
void initFontInfo(const QFontDef &request, int dpi);
diff --git a/src/platformsupport/glxconvenience/qglxconvenience.cpp b/src/platformsupport/glxconvenience/qglxconvenience.cpp
index 8d2e58b57b..d7cc36627a 100644
--- a/src/platformsupport/glxconvenience/qglxconvenience.cpp
+++ b/src/platformsupport/glxconvenience/qglxconvenience.cpp
@@ -42,13 +42,18 @@
#include <QtCore/QByteArray>
#include <QtCore/QScopedPointer>
+#include <QtCore/qmetatype.h>
+#include <QtCore/qtextstream.h>
#include "qglxconvenience_p.h"
+#include <QtCore/QLoggingCategory>
#include <QtCore/QVector>
#include <QtCore/QVarLengthArray>
#include <GL/glxext.h>
+Q_LOGGING_CATEGORY(lcGlx, "qt.glx")
+
enum {
XFocusOut = FocusOut,
XFocusIn = FocusIn,
@@ -207,6 +212,7 @@ GLXFBConfig qglx_findConfig(Display *display, int screen , QSurfaceFormat format
const int requestedBlue = qMax(0, format.blueBufferSize());
const int requestedAlpha = qMax(0, format.alphaBufferSize());
+ GLXFBConfig compatibleCandidate = nullptr;
for (int i = 0; i < confcount; i++) {
GLXFBConfig candidate = configs[i];
@@ -226,6 +232,16 @@ GLXFBConfig qglx_findConfig(Display *display, int screen , QSurfaceFormat format
const int actualBlue = qPopulationCount(visual->blue_mask);
const int actualAlpha = visual->depth - actualRed - actualGreen - actualBlue;
+ if (requestedRed && actualRed < requestedRed)
+ continue;
+ if (requestedGreen && actualGreen < requestedGreen)
+ continue;
+ if (requestedBlue && actualBlue < requestedBlue)
+ continue;
+ if (requestedAlpha && actualAlpha < requestedAlpha)
+ continue;
+ compatibleCandidate = candidate;
+
if (requestedRed && actualRed != requestedRed)
continue;
if (requestedGreen && actualGreen != requestedGreen)
@@ -237,6 +253,11 @@ GLXFBConfig qglx_findConfig(Display *display, int screen , QSurfaceFormat format
return candidate;
}
+ if (compatibleCandidate) {
+ qCDebug(lcGlx) << "qglx_findConfig: Found non-matching but compatible FBConfig";
+ return compatibleCandidate;
+ }
+ qCWarning(lcGlx, "qglx_findConfig: Failed to finding matching FBConfig (%d %d %d %d)", requestedRed, requestedGreen, requestedBlue, requestedAlpha);
} while (qglx_reduceFormat(&format));
return config;
@@ -352,6 +373,18 @@ void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display,
bool qglx_reduceFormat(QSurfaceFormat *format)
{
Q_ASSERT(format);
+ if (std::max(std::max(format->redBufferSize(), format->greenBufferSize()), format->blueBufferSize()) > 8) {
+ if (format->alphaBufferSize() > 2) {
+ // First try to match 10 10 10 2
+ format->setAlphaBufferSize(2);
+ return true;
+ }
+
+ format->setRedBufferSize(std::min(format->redBufferSize(), 8));
+ format->setGreenBufferSize(std::min(format->greenBufferSize(), 8));
+ format->setBlueBufferSize(std::min(format->blueBufferSize(), 8));
+ return true;
+ }
if (format->redBufferSize() > 1) {
format->setRedBufferSize(1);
diff --git a/src/platformsupport/kmsconvenience/qkmsdevice.cpp b/src/platformsupport/kmsconvenience/qkmsdevice.cpp
index a5895559e6..ef81f6162d 100644
--- a/src/platformsupport/kmsconvenience/qkmsdevice.cpp
+++ b/src/platformsupport/kmsconvenience/qkmsdevice.cpp
@@ -366,6 +366,25 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources,
if (!cloneSource.isEmpty())
qCDebug(qLcKmsDebug) << "Output" << connectorName << " clones output " << cloneSource;
+ const QByteArray fbsize = userConnectorConfig.value(QStringLiteral("size")).toByteArray().toLower();
+ QSize framebufferSize;
+ framebufferSize.setWidth(modes[selected_mode].hdisplay);
+ framebufferSize.setHeight(modes[selected_mode].vdisplay);
+
+#if QT_CONFIG(drm_atomic)
+ if (hasAtomicSupport()) {
+ if (sscanf(fbsize.constData(), "%dx%d", &framebufferSize.rwidth(), &framebufferSize.rheight()) != 2) {
+ qWarning("Framebuffer size format is invalid.");
+ }
+ } else {
+ qWarning("Setting framebuffer size is only available with DRM atomic API");
+ }
+#else
+ if (fbsize.size())
+ qWarning("Setting framebuffer size is only available with DRM atomic API");
+#endif
+ qCDebug(qLcKmsDebug) << "Output" << connectorName << "framebuffer size is " << framebufferSize;
+
QKmsOutput output;
output.name = QString::fromUtf8(connectorName);
output.connector_id = connector->connector_id;
@@ -385,6 +404,17 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources,
output.forced_plane_set = false;
output.drm_format = drmFormat;
output.clone_source = cloneSource;
+ output.size = framebufferSize;
+
+#if QT_CONFIG(drm_atomic)
+ if (drmModeCreatePropertyBlob(m_dri_fd, &modes[selected_mode], sizeof(drmModeModeInfo),
+ &output.mode_blob_id) != 0) {
+ qCDebug(qLcKmsDebug) << "Failed to create mode blob for mode" << selected_mode;
+ }
+
+ parseConnectorProperties(output.connector_id, &output);
+ parseCrtcProperties(output.crtc_id, &output);
+#endif
QString planeListStr;
for (const QKmsPlane &plane : qAsConst(m_planes)) {
@@ -392,6 +422,8 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources,
output.available_planes.append(plane);
planeListStr.append(QString::number(plane.id));
planeListStr.append(QLatin1Char(' '));
+ if (plane.type == QKmsPlane::PrimaryPlane)
+ output.eglfs_plane = (QKmsPlane*)&plane;
}
}
qCDebug(qLcKmsDebug, "Output %s can use %d planes: %s",
@@ -412,6 +444,12 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources,
output.forced_plane_id = plane->plane_id;
qCDebug(qLcKmsDebug, "Forcing plane index %d, plane id %u (belongs to crtc id %u)",
idx, plane->plane_id, plane->crtc_id);
+
+ for (const QKmsPlane &kmsplane : qAsConst(m_planes)) {
+ if (kmsplane.id == output.forced_plane_id)
+ output.eglfs_plane = (QKmsPlane*)&kmsplane;
+ }
+
drmModeFreePlane(plane);
}
} else {
@@ -420,6 +458,9 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources,
}
}
+ if (output.eglfs_plane)
+ qCDebug(qLcKmsDebug, "Output eglfs plane is: %d", output.eglfs_plane->id);
+
m_crtc_allocator |= (1 << output.crtc_index);
vinfo->output = output;
@@ -464,6 +505,11 @@ QKmsDevice::QKmsDevice(QKmsScreenConfig *screenConfig, const QString &path)
: m_screenConfig(screenConfig)
, m_path(path)
, m_dri_fd(-1)
+ , m_has_atomic_support(false)
+#if QT_CONFIG(drm_atomic)
+ , m_atomic_request(nullptr)
+ , m_previous_request(nullptr)
+#endif
, m_crtc_allocator(0)
{
if (m_path.isEmpty()) {
@@ -478,6 +524,9 @@ QKmsDevice::QKmsDevice(QKmsScreenConfig *screenConfig, const QString &path)
QKmsDevice::~QKmsDevice()
{
+#if QT_CONFIG(drm_atomic)
+ atomicReset();
+#endif
}
struct OrderedScreen
@@ -522,6 +571,14 @@ void QKmsDevice::createScreens()
drmSetClientCap(m_dri_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
+#if QT_CONFIG(drm_atomic)
+ // check atomic support
+ m_has_atomic_support = !drmSetClientCap(m_dri_fd, DRM_CLIENT_CAP_ATOMIC, 1)
+ && qEnvironmentVariableIntValue("QT_QPA_EGLFS_KMS_ATOMIC");
+ if (m_has_atomic_support)
+ qCDebug(qLcKmsDebug) << "Atomic Support found";
+#endif
+
drmModeResPtr resources = drmModeGetResources(m_dri_fd);
if (!resources) {
qErrnoWarning(errno, "drmModeGetResources failed");
@@ -747,6 +804,28 @@ void QKmsDevice::discoverPlanes()
plane.availableRotations |= QKmsPlane::Rotation(1 << prop->enums[i].value);
}
plane.rotationPropertyId = prop->prop_id;
+ } else if (!strcasecmp(prop->name, "crtc_id")) {
+ plane.crtcPropertyId = prop->prop_id;
+ } else if (!strcasecmp(prop->name, "fb_id")) {
+ plane.framebufferPropertyId = prop->prop_id;
+ } else if (!strcasecmp(prop->name, "src_w")) {
+ plane.srcwidthPropertyId = prop->prop_id;
+ } else if (!strcasecmp(prop->name, "src_h")) {
+ plane.srcheightPropertyId = prop->prop_id;
+ } else if (!strcasecmp(prop->name, "crtc_w")) {
+ plane.crtcwidthPropertyId = prop->prop_id;
+ } else if (!strcasecmp(prop->name, "crtc_h")) {
+ plane.crtcheightPropertyId = prop->prop_id;
+ } else if (!strcasecmp(prop->name, "src_x")) {
+ plane.srcXPropertyId = prop->prop_id;
+ } else if (!strcasecmp(prop->name, "src_y")) {
+ plane.srcYPropertyId = prop->prop_id;
+ } else if (!strcasecmp(prop->name, "crtc_x")) {
+ plane.crtcXPropertyId = prop->prop_id;
+ } else if (!strcasecmp(prop->name, "crtc_y")) {
+ plane.crtcYPropertyId = prop->prop_id;
+ } else if (!strcasecmp(prop->name, "zpos")) {
+ plane.zposPropertyId = prop->prop_id;
}
});
@@ -773,6 +852,86 @@ void QKmsDevice::setFd(int fd)
m_dri_fd = fd;
}
+
+bool QKmsDevice::hasAtomicSupport()
+{
+ return m_has_atomic_support;
+}
+
+#if QT_CONFIG(drm_atomic)
+drmModeAtomicReq * QKmsDevice::atomic_request()
+{
+ if (!m_atomic_request && m_has_atomic_support)
+ m_atomic_request = drmModeAtomicAlloc();
+
+ return m_atomic_request;
+}
+
+bool QKmsDevice::atomicCommit(void *user_data)
+{
+ if (m_atomic_request) {
+ int ret = drmModeAtomicCommit(m_dri_fd, m_atomic_request,
+ DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_ALLOW_MODESET, user_data);
+
+ if (ret) {
+ qWarning("Failed to commit atomic request (code=%d)", ret);
+ return false;
+ }
+
+ m_previous_request = m_atomic_request;
+ m_atomic_request = nullptr;
+
+ return true;
+ }
+
+ return false;
+}
+
+void QKmsDevice::atomicReset()
+{
+ if (m_previous_request) {
+ drmModeAtomicFree(m_previous_request);
+ m_previous_request = nullptr;
+ }
+}
+#endif
+
+void QKmsDevice::parseConnectorProperties(uint32_t connectorId, QKmsOutput *output)
+{
+ drmModeObjectPropertiesPtr objProps = drmModeObjectGetProperties(m_dri_fd, connectorId, DRM_MODE_OBJECT_CONNECTOR);
+ if (!objProps) {
+ qCDebug(qLcKmsDebug, "Failed to query connector %d object properties", connectorId);
+ return;
+ }
+
+ enumerateProperties(objProps, [output](drmModePropertyPtr prop, quint64 value) {
+ Q_UNUSED(value);
+ if (!strcasecmp(prop->name, "crtc_id"))
+ output->crtcIdPropertyId = prop->prop_id;
+ });
+
+ drmModeFreeObjectProperties(objProps);
+}
+
+void QKmsDevice::parseCrtcProperties(uint32_t crtcId, QKmsOutput *output)
+{
+ drmModeObjectPropertiesPtr objProps = drmModeObjectGetProperties(m_dri_fd, crtcId, DRM_MODE_OBJECT_CRTC);
+ if (!objProps) {
+ qCDebug(qLcKmsDebug, "Failed to query crtc %d object properties", crtcId);
+ return;
+ }
+
+ enumerateProperties(objProps, [output](drmModePropertyPtr prop, quint64 value) {
+ Q_UNUSED(value)
+ if (!strcasecmp(prop->name, "mode_id"))
+ output->modeIdPropertyId = prop->prop_id;
+ else if (!strcasecmp(prop->name, "active"))
+ output->activePropertyId = prop->prop_id;
+ });
+
+ drmModeFreeObjectProperties(objProps);
+}
+
QKmsScreenConfig *QKmsDevice::screenConfig() const
{
return m_screenConfig;
diff --git a/src/platformsupport/kmsconvenience/qkmsdevice_p.h b/src/platformsupport/kmsconvenience/qkmsdevice_p.h
index 5eecedec39..403972fbb8 100644
--- a/src/platformsupport/kmsconvenience/qkmsdevice_p.h
+++ b/src/platformsupport/kmsconvenience/qkmsdevice_p.h
@@ -53,6 +53,7 @@
// We mean it.
//
+#include <QtGui/private/qtguiglobal_p.h>
#include <qpa/qplatformscreen.h>
#include <QtCore/QMap>
#include <QtCore/QVariant>
@@ -166,6 +167,17 @@ struct QKmsPlane
Rotations initialRotation = Rotation0;
Rotations availableRotations = Rotation0;
uint32_t rotationPropertyId = 0;
+ uint32_t crtcPropertyId = 0;
+ uint32_t framebufferPropertyId = 0;
+ uint32_t srcXPropertyId = 0;
+ uint32_t srcYPropertyId = 0;
+ uint32_t crtcXPropertyId = 0;
+ uint32_t crtcYPropertyId = 0;
+ uint32_t srcwidthPropertyId = 0;
+ uint32_t srcheightPropertyId = 0;
+ uint32_t crtcwidthPropertyId = 0;
+ uint32_t crtcheightPropertyId = 0;
+ uint32_t zposPropertyId = 0;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QKmsPlane::Rotations)
@@ -191,6 +203,13 @@ struct QKmsOutput
uint32_t drm_format = DRM_FORMAT_XRGB8888;
QString clone_source;
QVector<QKmsPlane> available_planes;
+ struct QKmsPlane *eglfs_plane = nullptr;
+ QSize size;
+ uint32_t crtcIdPropertyId = 0;
+ uint32_t modeIdPropertyId = 0;
+ uint32_t activePropertyId = 0;
+
+ uint32_t mode_blob_id = 0;
void restoreMode(QKmsDevice *device);
void cleanup(QKmsDevice *device);
@@ -215,6 +234,14 @@ public:
virtual void close() = 0;
virtual void *nativeDisplay() const = 0;
+ bool hasAtomicSupport();
+
+#if QT_CONFIG(drm_atomic)
+ bool atomicCommit(void *user_data);
+ void atomicReset();
+
+ drmModeAtomicReq *atomic_request();
+#endif
void createScreens();
int fd() const;
@@ -243,11 +270,19 @@ protected:
typedef std::function<void(drmModePropertyPtr, quint64)> PropCallback;
void enumerateProperties(drmModeObjectPropertiesPtr objProps, PropCallback callback);
void discoverPlanes();
+ void parseConnectorProperties(uint32_t connectorId, QKmsOutput *output);
+ void parseCrtcProperties(uint32_t crtcId, QKmsOutput *output);
QKmsScreenConfig *m_screenConfig;
QString m_path;
int m_dri_fd;
+ bool m_has_atomic_support;
+
+#if QT_CONFIG(drm_atomic)
+ drmModeAtomicReq *m_atomic_request;
+ drmModeAtomicReq *m_previous_request;
+#endif
quint32 m_crtc_allocator;
QVector<QKmsPlane> m_planes;
diff --git a/src/platformsupport/linuxaccessibility/constant_mappings.cpp b/src/platformsupport/linuxaccessibility/constant_mappings.cpp
index de4a68dc5b..ef2b3429d2 100644
--- a/src/platformsupport/linuxaccessibility/constant_mappings.cpp
+++ b/src/platformsupport/linuxaccessibility/constant_mappings.cpp
@@ -83,6 +83,8 @@ quint64 spiStatesFromQState(QAccessible::State state)
// if (state.HotTracked)
if (state.defaultButton)
setSpiStateBit(&spiState, ATSPI_STATE_IS_DEFAULT);
+ if (state.expandable)
+ setSpiStateBit(&spiState, ATSPI_STATE_EXPANDABLE);
if (state.expanded)
setSpiStateBit(&spiState, ATSPI_STATE_EXPANDED);
if (state.collapsed)
diff --git a/src/platformsupport/services/genericunix/qgenericunixservices.cpp b/src/platformsupport/services/genericunix/qgenericunixservices.cpp
index cb1e367b9f..67884cef92 100644
--- a/src/platformsupport/services/genericunix/qgenericunixservices.cpp
+++ b/src/platformsupport/services/genericunix/qgenericunixservices.cpp
@@ -50,7 +50,7 @@
#include <QtCore/QUrl>
#if QT_CONFIG(dbus)
-// These QtCore includes are needed for flatpak support
+// These QtCore includes are needed for xdg-desktop-portal support
#include <QtCore/private/qcore_unix_p.h>
#include <QtCore/QFileInfo>
@@ -172,12 +172,47 @@ static inline bool launch(const QString &launcher, const QUrl &url)
}
#if QT_CONFIG(dbus)
-static inline bool checkRunningUnderFlatpak()
+static inline bool checkNeedPortalSupport()
{
- return !QStandardPaths::locate(QStandardPaths::RuntimeLocation, QLatin1String("flatpak-info")).isEmpty();
+ return !QStandardPaths::locate(QStandardPaths::RuntimeLocation, QLatin1String("flatpak-info")).isEmpty() || qEnvironmentVariableIsSet("SNAP");
}
-static inline bool flatpakOpenUrl(const QUrl &url)
+static inline bool xdgDesktopPortalOpenFile(const QUrl &url)
+{
+ // DBus signature:
+ // OpenFile (IN s parent_window,
+ // IN h fd,
+ // IN a{sv} options,
+ // OUT o handle)
+ // Options:
+ // handle_token (s) - A string that will be used as the last element of the @handle.
+ // writable (b) - Whether to allow the chosen application to write to the file.
+
+#ifdef O_PATH
+ const int fd = qt_safe_open(QFile::encodeName(url.toLocalFile()), O_PATH);
+ if (fd != -1) {
+ QDBusMessage message = QDBusMessage::createMethodCall(QLatin1String("org.freedesktop.portal.Desktop"),
+ QLatin1String("/org/freedesktop/portal/desktop"),
+ QLatin1String("org.freedesktop.portal.OpenURI"),
+ QLatin1String("OpenFile"));
+
+ QDBusUnixFileDescriptor descriptor(fd);
+ qt_safe_close(fd);
+
+ // FIXME parent_window_id and handle writable option
+ message << QString() << QVariant::fromValue(descriptor) << QVariantMap();
+
+ QDBusPendingReply<QDBusObjectPath> reply = QDBusConnection::sessionBus().call(message);
+ return !reply.isError();
+ }
+#else
+ Q_UNUSED(url)
+#endif
+
+ return false;
+}
+
+static inline bool xdgDesktopPortalOpenUrl(const QUrl &url)
{
// DBus signature:
// OpenURI (IN s parent_window,
@@ -185,6 +220,7 @@ static inline bool flatpakOpenUrl(const QUrl &url)
// IN a{sv} options,
// OUT o handle)
// Options:
+ // handle_token (s) - A string that will be used as the last element of the @handle.
// writable (b) - Whether to allow the chosen application to write to the file.
// This key only takes effect the uri points to a local file that is exported in the document portal,
// and the chosen application is sandboxed itself.
@@ -200,7 +236,7 @@ static inline bool flatpakOpenUrl(const QUrl &url)
return !reply.isError();
}
-static inline bool flatpakSendEmail(const QUrl &url)
+static inline bool xdgDesktopPortalSendEmail(const QUrl &url)
{
// DBus signature:
// ComposeEmail (IN s parent_window,
@@ -258,15 +294,15 @@ bool QGenericUnixServices::openUrl(const QUrl &url)
{
if (url.scheme() == QLatin1String("mailto")) {
#if QT_CONFIG(dbus)
- if (checkRunningUnderFlatpak())
- return flatpakSendEmail(url);
+ if (checkNeedPortalSupport())
+ return xdgDesktopPortalSendEmail(url);
#endif
return openDocument(url);
}
#if QT_CONFIG(dbus)
- if (checkRunningUnderFlatpak())
- return flatpakOpenUrl(url);
+ if (checkNeedPortalSupport())
+ return xdgDesktopPortalOpenUrl(url);
#endif
if (m_webBrowser.isEmpty() && !detectWebBrowser(desktopEnvironment(), true, &m_webBrowser)) {
@@ -278,6 +314,11 @@ bool QGenericUnixServices::openUrl(const QUrl &url)
bool QGenericUnixServices::openDocument(const QUrl &url)
{
+#if QT_CONFIG(dbus)
+ if (checkNeedPortalSupport())
+ return xdgDesktopPortalOpenFile(url);
+#endif
+
if (m_documentLauncher.isEmpty() && !detectWebBrowser(desktopEnvironment(), false, &m_documentLauncher)) {
qWarning("Unable to detect a launcher for '%s'", qPrintable(url.toString()));
return false;
diff --git a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp
index 382d142334..b9c5669b3f 100644
--- a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp
+++ b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp
@@ -82,6 +82,21 @@ QBasicPlatformVulkanInstance::~QBasicPlatformVulkanInstance()
m_vkDestroyInstance(m_vkInst, nullptr);
}
+void QBasicPlatformVulkanInstance::loadVulkanLibrary(const QString &defaultLibraryName)
+{
+ if (qEnvironmentVariableIsSet("QT_VULKAN_LIB"))
+ m_vulkanLib.setFileName(QString::fromUtf8(qgetenv("QT_VULKAN_LIB")));
+ else
+ m_vulkanLib.setFileName(defaultLibraryName);
+
+ if (!m_vulkanLib.load()) {
+ qWarning("Failed to load %s: %s", qPrintable(m_vulkanLib.fileName()), qPrintable(m_vulkanLib.errorString()));
+ return;
+ }
+
+ init(&m_vulkanLib);
+}
+
void QBasicPlatformVulkanInstance::init(QLibrary *lib)
{
if (m_vkGetInstanceProcAddr)
@@ -256,6 +271,11 @@ void QBasicPlatformVulkanInstance::initInstance(QVulkanInstance *instance, const
if (!m_getPhysDevSurfaceSupport)
qWarning("Failed to find vkGetPhysicalDeviceSurfaceSupportKHR");
+ m_destroySurface = reinterpret_cast<PFN_vkDestroySurfaceKHR>(
+ m_vkGetInstanceProcAddr(m_vkInst, "vkDestroySurfaceKHR"));
+ if (!m_destroySurface)
+ qWarning("Failed to find vkDestroySurfaceKHR");
+
if (!flags.testFlag(QVulkanInstance::NoDebugOutputRedirect))
setupDebugOutput();
}
@@ -310,6 +330,12 @@ bool QBasicPlatformVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevi
return supported;
}
+void QBasicPlatformVulkanInstance::destroySurface(VkSurfaceKHR surface) const
+{
+ if (m_destroySurface && surface)
+ m_destroySurface(m_vkInst, surface, nullptr);
+}
+
static VKAPI_ATTR VkBool32 VKAPI_CALL defaultDebugCallbackFunc(VkDebugReportFlagsEXT flags,
VkDebugReportObjectTypeEXT objectType,
uint64_t object,
diff --git a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h
index 748b138f01..566140b032 100644
--- a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h
+++ b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h
@@ -51,6 +51,7 @@
// We mean it.
//
+#include <QtCore/QLibrary>
#include <qpa/qplatformvulkaninstance.h>
QT_BEGIN_NAMESPACE
@@ -72,18 +73,23 @@ public:
QByteArrayList enabledExtensions() const override;
PFN_vkVoidFunction getInstanceProcAddr(const char *name) override;
bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) override;
+ void destroySurface(VkSurfaceKHR surface) const;
protected:
+ void loadVulkanLibrary(const QString &defaultLibraryName);
void init(QLibrary *lib);
void initInstance(QVulkanInstance *instance, const QByteArrayList &extraExts);
VkInstance m_vkInst;
PFN_vkGetInstanceProcAddr m_vkGetInstanceProcAddr;
PFN_vkGetPhysicalDeviceSurfaceSupportKHR m_getPhysDevSurfaceSupport;
+ PFN_vkDestroySurfaceKHR m_destroySurface;
private:
void setupDebugOutput();
+ QLibrary m_vulkanLib;
+
bool m_ownsVkInst;
VkResult m_errorCode;
QVulkanInfoVector<QVulkanLayer> m_supportedLayers;
diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.mm b/src/plugins/bearer/corewlan/qcorewlanengine.mm
index 341d3bccf2..c3dd49ff3e 100644
--- a/src/plugins/bearer/corewlan/qcorewlanengine.mm
+++ b/src/plugins/bearer/corewlan/qcorewlanengine.mm
@@ -62,33 +62,29 @@ extern "C" { // Otherwise it won't find CWKeychain* symbols at link time
#include <ifaddrs.h>
@interface QT_MANGLE_NAMESPACE(QNSListener) : NSObject <CWEventDelegate>
-{
- NSNotificationCenter *notificationCenter;
- CWWiFiClient *client;
- QCoreWlanEngine *engine;
- NSLock *locker;
-}
-- (void)powerStateDidChangeForWiFiInterfaceWithName:(NSString *)interfaceName;
-- (void)remove;
-- (void)setEngine:(QCoreWlanEngine *)coreEngine;
-- (QCoreWlanEngine *)engine;
-- (void)dealloc;
@property (assign) QCoreWlanEngine* engine;
@end
-@implementation QT_MANGLE_NAMESPACE(QNSListener)
+@implementation QT_MANGLE_NAMESPACE(QNSListener) {
+ NSNotificationCenter *notificationCenter;
+ CWWiFiClient *client;
+ QCoreWlanEngine *engine;
+ NSLock *locker;
+}
-- (id) init
+- (instancetype)init
{
- [locker lock];
- QMacAutoReleasePool pool;
- notificationCenter = [NSNotificationCenter defaultCenter];
- client = [CWWiFiClient sharedWiFiClient];
- client.delegate = self;
- [client startMonitoringEventWithType:CWEventTypePowerDidChange error:nil];
- [locker unlock];
+ if ((self = [super init])) {
+ [locker lock];
+ QMacAutoReleasePool pool;
+ notificationCenter = [NSNotificationCenter defaultCenter];
+ client = [CWWiFiClient sharedWiFiClient];
+ client.delegate = self;
+ [client startMonitoringEventWithType:CWEventTypePowerDidChange error:nil];
+ [locker unlock];
+ }
return self;
}
@@ -300,7 +296,7 @@ void QScanThread::getUserConfigurations()
if(airportPlist != nil) {
NSDictionary *prefNetDict = [airportPlist objectForKey:@"PreferredNetworks"];
- NSArray *thisSsidarray = [prefNetDict valueForKey:@"SSID_STR"];
+ NSArray<NSString *> *thisSsidarray = [prefNetDict valueForKey:@"SSID_STR"];
for (NSString *ssidkey in thisSsidarray) {
QString thisSsid = QString::fromNSString(ssidkey);
if(!userProfiles.contains(thisSsid)) {
diff --git a/src/plugins/doc/snippets/code/src_plugins_platforms_qnx_qqnxwindow.cpp b/src/plugins/doc/snippets/code/src_plugins_platforms_qnx_qqnxwindow.cpp
new file mode 100644
index 0000000000..ce82533c3e
--- /dev/null
+++ b/src/plugins/doc/snippets/code/src_plugins_platforms_qnx_qqnxwindow.cpp
@@ -0,0 +1,52 @@
+/***************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+ QQuickView *view = new QQuickView(parent);
+ view->create();
+ QGuiApplication::platformNativeInterface()->setWindowProperty(view->handle(), "qnxWindowGroup",
+ group);
+//! [0]
+
+//! [1]
+ QQuickView *view = new QQuickView(parent);
+ view->create();
+ QGuiApplication::platformNativeInterface()->setWindowProperty(view->handle(), "qnxWindowGroup",
+ QVariant());
+//! [1]
diff --git a/src/plugins/imageformats/jpeg/qjpeghandler.cpp b/src/plugins/imageformats/jpeg/qjpeghandler.cpp
index 1cdc28c077..e52a19703c 100644
--- a/src/plugins/imageformats/jpeg/qjpeghandler.cpp
+++ b/src/plugins/imageformats/jpeg/qjpeghandler.cpp
@@ -493,10 +493,10 @@ static inline void set_text(const QImage &image, j_compress_ptr cinfo, const QSt
{
const QMap<QString, QString> text = qt_getImageText(image, description);
for (auto it = text.begin(), end = text.end(); it != end; ++it) {
- QByteArray comment = it.key().toLatin1();
+ QByteArray comment = it.key().toUtf8();
if (!comment.isEmpty())
comment += ": ";
- comment += it.value().toLatin1();
+ comment += it.value().toUtf8();
if (comment.length() > 65530)
comment.truncate(65530);
jpeg_write_marker(cinfo, JPEG_COM, (const JOCTET *)comment.constData(), comment.size());
@@ -904,7 +904,7 @@ bool QJpegHandlerPrivate::readJpegHeader(QIODevice *device)
for (jpeg_saved_marker_ptr marker = info.marker_list; marker != NULL; marker = marker->next) {
if (marker->marker == JPEG_COM) {
QString key, value;
- QString s = QString::fromLatin1((const char *)marker->data, marker->data_length);
+ QString s = QString::fromUtf8((const char *)marker->data, marker->data_length);
int index = s.indexOf(QLatin1String(": "));
if (index == -1 || s.indexOf(QLatin1Char(' ')) < index) {
key = QLatin1String("Description");
diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp
index dabab553c2..9cdc5de0e1 100644
--- a/src/plugins/platforms/android/androidjniinput.cpp
+++ b/src/plugins/platforms/android/androidjniinput.cpp
@@ -58,7 +58,6 @@ using namespace QtAndroid;
namespace QtAndroidInput
{
-
static bool m_ignoreMouseEvents = false;
static bool m_softwareKeyboardVisible = false;
static QRect m_softwareKeyboardRect;
@@ -124,11 +123,12 @@ namespace QtAndroidInput
return m_softwareKeyboardRect;
}
- void updateHandles(int mode, QPoint cursor, QPoint anchor, bool rtl)
+ void updateHandles(int mode, QPoint editMenuPos, uint32_t editButtons, QPoint cursor, QPoint anchor, bool rtl)
{
- QJNIObjectPrivate::callStaticMethod<void>(applicationClass(), "updateHandles", "(IIIIIZ)V",
- mode, cursor.x(), cursor.y(), anchor.x(),
- anchor.y(), rtl);
+ QJNIObjectPrivate::callStaticMethod<void>(applicationClass(), "updateHandles", "(IIIIIIIIZ)V",
+ mode, editMenuPos.x(), editMenuPos.y(), editButtons,
+ cursor.x(), cursor.y(),
+ anchor.x(), anchor.y(), rtl);
}
static void mouseDown(JNIEnv */*env*/, jobject /*thiz*/, jint /*winId*/, jint x, jint y)
@@ -173,7 +173,7 @@ namespace QtAndroidInput
QWindowSystemInterface::handleMouseEvent(tlw,
localPos,
globalPos,
- Qt::MouseButtons(Qt::LeftButton));
+ Qt::MouseButtons(m_mouseGrabber ? Qt::LeftButton : Qt::NoButton));
}
static void mouseWheel(JNIEnv */*env*/, jobject /*thiz*/, jint /*winId*/, jint x, jint y, jfloat hdelta, jfloat vdelta)
@@ -195,6 +195,20 @@ namespace QtAndroidInput
angleDelta);
}
+ void releaseMouse(int x, int y)
+ {
+ m_ignoreMouseEvents = true;
+ QPoint globalPos(x,y);
+ QWindow *tlw = topLevelWindowAt(globalPos);
+ QPoint localPos = tlw ? (globalPos-tlw->position()) : globalPos;
+
+ // Release left button
+ QWindowSystemInterface::handleMouseEvent(tlw,
+ localPos,
+ globalPos,
+ Qt::MouseButtons(Qt::NoButton));
+ }
+
static void longPress(JNIEnv */*env*/, jobject /*thiz*/, jint /*winId*/, jint x, jint y)
{
QAndroidInputContext *inputContext = QAndroidInputContext::androidInputContext();
@@ -805,8 +819,10 @@ namespace QtAndroidInput
QAndroidInputContext *inputContext = QAndroidInputContext::androidInputContext();
if (inputContext && qGuiApp) {
inputContext->emitInputPanelVisibleChanged();
- if (!visibility)
+ if (!visibility) {
inputContext->emitKeyboardRectChanged();
+ QMetaObject::invokeMethod(inputContext, "hideSelectionHandles", Qt::QueuedConnection);
+ }
}
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ KEYBOARDVISIBILITYCHANGED" << inputContext;
diff --git a/src/plugins/platforms/android/androidjniinput.h b/src/plugins/platforms/android/androidjniinput.h
index c09b426f49..2e2470ae8f 100644
--- a/src/plugins/platforms/android/androidjniinput.h
+++ b/src/plugins/platforms/android/androidjniinput.h
@@ -58,9 +58,11 @@ namespace QtAndroidInput
// Software keyboard support
// cursor/selection handles
- void updateHandles(int handleCount, QPoint cursor = QPoint(), QPoint anchor = QPoint(), bool rtl = false);
+ void updateHandles(int handleCount, QPoint editMenuPos = QPoint(), uint32_t editButtons = 0, QPoint cursor = QPoint(), QPoint anchor = QPoint(), bool rtl = false);
bool registerNatives(JNIEnv *env);
+
+ void releaseMouse(int x, int y);
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp
index c46a435db1..c5cd0b92d9 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.cpp
+++ b/src/plugins/platforms/android/qandroidinputcontext.cpp
@@ -64,6 +64,29 @@
QT_BEGIN_NAMESPACE
+template <typename T>
+class ScopedValueChangeBack
+{
+public:
+ ScopedValueChangeBack(T &variable, T newValue)
+ : m_oldValue(variable),
+ m_variable(variable)
+ {
+ m_variable = newValue;
+ }
+ inline void setOldValue()
+ {
+ m_variable = m_oldValue;
+ }
+ ~ScopedValueChangeBack()
+ {
+ setOldValue();
+ }
+private:
+ T m_oldValue;
+ T &m_variable;
+};
+
static QAndroidInputContext *m_androidInputContext = 0;
static char const *const QtNativeInputConnectionClassName = "org/qtproject/qt5/android/QtNativeInputConnection";
static char const *const QtExtractedTextClassName = "org/qtproject/qt5/android/QtExtractedText";
@@ -76,6 +99,11 @@ static jfieldID m_selectionStartFieldID = 0;
static jfieldID m_startOffsetFieldID = 0;
static jfieldID m_textFieldID = 0;
+static void runOnQtThread(const std::function<void()> &func)
+{
+ QMetaObject::invokeMethod(m_androidInputContext, "safeCall", Qt::BlockingQueuedConnection, Q_ARG(std::function<void()>, func));
+}
+
static jboolean beginBatchEdit(JNIEnv */*env*/, jobject /*thiz*/)
{
if (!m_androidInputContext)
@@ -84,10 +112,9 @@ static jboolean beginBatchEdit(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@ BEGINBATCH");
#endif
-
- return m_androidInputContext->beginBatchEdit();
-
- return JNI_TRUE;
+ jboolean res;
+ runOnQtThread([&res]{res = m_androidInputContext->beginBatchEdit();});
+ return res;
}
static jboolean endBatchEdit(JNIEnv */*env*/, jobject /*thiz*/)
@@ -99,9 +126,9 @@ static jboolean endBatchEdit(JNIEnv */*env*/, jobject /*thiz*/)
qDebug("@@@ ENDBATCH");
#endif
- return m_androidInputContext->endBatchEdit();
-
- return JNI_TRUE;
+ jboolean res;
+ runOnQtThread([&res]{res = m_androidInputContext->endBatchEdit();});
+ return res;
}
@@ -118,7 +145,9 @@ static jboolean commitText(JNIEnv *env, jobject /*thiz*/, jstring text, jint new
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ COMMIT" << str << newCursorPosition;
#endif
- return m_androidInputContext->commitText(str, newCursorPosition);
+ jboolean res;
+ runOnQtThread([&]{res = m_androidInputContext->commitText(str, newCursorPosition);});
+ return res;
}
static jboolean deleteSurroundingText(JNIEnv */*env*/, jobject /*thiz*/, jint leftLength, jint rightLength)
@@ -129,7 +158,9 @@ static jboolean deleteSurroundingText(JNIEnv */*env*/, jobject /*thiz*/, jint le
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ DELETE" << leftLength << rightLength;
#endif
- return m_androidInputContext->deleteSurroundingText(leftLength, rightLength);
+ jboolean res;
+ runOnQtThread([&]{res = m_androidInputContext->deleteSurroundingText(leftLength, rightLength);});
+ return res;
}
static jboolean finishComposingText(JNIEnv */*env*/, jobject /*thiz*/)
@@ -140,7 +171,9 @@ static jboolean finishComposingText(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@ FINISH");
#endif
- return m_androidInputContext->finishComposingText();
+ jboolean res;
+ runOnQtThread([&]{res = m_androidInputContext->finishComposingText();});
+ return res;
}
static jint getCursorCapsMode(JNIEnv */*env*/, jobject /*thiz*/, jint reqModes)
@@ -148,7 +181,9 @@ static jint getCursorCapsMode(JNIEnv */*env*/, jobject /*thiz*/, jint reqModes)
if (!m_androidInputContext)
return 0;
- return m_androidInputContext->getCursorCapsMode(reqModes);
+ jboolean res;
+ runOnQtThread([&]{res = m_androidInputContext->getCursorCapsMode(reqModes);});
+ return res;
}
static jobject getExtractedText(JNIEnv *env, jobject /*thiz*/, int hintMaxChars, int hintMaxLines, jint flags)
@@ -156,8 +191,8 @@ static jobject getExtractedText(JNIEnv *env, jobject /*thiz*/, int hintMaxChars,
if (!m_androidInputContext)
return 0;
- const QAndroidInputContext::ExtractedText &extractedText =
- m_androidInputContext->getExtractedText(hintMaxChars, hintMaxLines, flags);
+ QAndroidInputContext::ExtractedText extractedText;
+ runOnQtThread([&]{extractedText = m_androidInputContext->getExtractedText(hintMaxChars, hintMaxLines, flags);});
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ GETEX" << hintMaxChars << hintMaxLines << QString::fromLatin1("0x") + QString::number(flags,16) << extractedText.text << "partOff:" << extractedText.partialStartOffset << extractedText.partialEndOffset << "sel:" << extractedText.selectionStart << extractedText.selectionEnd << "offset:" << extractedText.startOffset;
@@ -182,7 +217,8 @@ static jstring getSelectedText(JNIEnv *env, jobject /*thiz*/, jint flags)
if (!m_androidInputContext)
return 0;
- const QString &text = m_androidInputContext->getSelectedText(flags);
+ QString text;
+ runOnQtThread([&]{text = m_androidInputContext->getSelectedText(flags);});
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ GETSEL" << text;
#endif
@@ -196,7 +232,8 @@ static jstring getTextAfterCursor(JNIEnv *env, jobject /*thiz*/, jint length, ji
if (!m_androidInputContext)
return 0;
- const QString &text = m_androidInputContext->getTextAfterCursor(length, flags);
+ QString text;
+ runOnQtThread([&]{text = m_androidInputContext->getTextAfterCursor(length, flags);});
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ GETA" << length << text;
#endif
@@ -208,7 +245,8 @@ static jstring getTextBeforeCursor(JNIEnv *env, jobject /*thiz*/, jint length, j
if (!m_androidInputContext)
return 0;
- const QString &text = m_androidInputContext->getTextBeforeCursor(length, flags);
+ QString text;
+ runOnQtThread([&]{text = m_androidInputContext->getTextBeforeCursor(length, flags);});
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ GETB" << length << text;
#endif
@@ -228,7 +266,9 @@ static jboolean setComposingText(JNIEnv *env, jobject /*thiz*/, jstring text, ji
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ SET" << str << newCursorPosition;
#endif
- return m_androidInputContext->setComposingText(str, newCursorPosition);
+ jboolean res;
+ runOnQtThread([&]{res = m_androidInputContext->setComposingText(str, newCursorPosition);});
+ return res;
}
static jboolean setComposingRegion(JNIEnv */*env*/, jobject /*thiz*/, jint start, jint end)
@@ -239,7 +279,9 @@ static jboolean setComposingRegion(JNIEnv */*env*/, jobject /*thiz*/, jint start
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ SETR" << start << end;
#endif
- return m_androidInputContext->setComposingRegion(start, end);
+ jboolean res;
+ runOnQtThread([&]{res = m_androidInputContext->setComposingRegion(start, end);});
+ return res;
}
@@ -251,7 +293,10 @@ static jboolean setSelection(JNIEnv */*env*/, jobject /*thiz*/, jint start, jint
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug() << "@@@ SETSEL" << start << end;
#endif
- return m_androidInputContext->setSelection(start, end);
+ jboolean res;
+ runOnQtThread([&]{res = m_androidInputContext->setSelection(start, end);});
+ return res;
+
}
static jboolean selectAll(JNIEnv */*env*/, jobject /*thiz*/)
@@ -262,7 +307,9 @@ static jboolean selectAll(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@ SELALL");
#endif
- return m_androidInputContext->selectAll();
+ jboolean res;
+ runOnQtThread([&]{res = m_androidInputContext->selectAll();});
+ return res;
}
static jboolean cut(JNIEnv */*env*/, jobject /*thiz*/)
@@ -273,7 +320,9 @@ static jboolean cut(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@");
#endif
- return m_androidInputContext->cut();
+ jboolean res;
+ runOnQtThread([&]{res = m_androidInputContext->cut();});
+ return res;
}
static jboolean copy(JNIEnv */*env*/, jobject /*thiz*/)
@@ -284,7 +333,9 @@ static jboolean copy(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@");
#endif
- return m_androidInputContext->copy();
+ jboolean res;
+ runOnQtThread([&]{res = m_androidInputContext->copy();});
+ return res;
}
static jboolean copyURL(JNIEnv */*env*/, jobject /*thiz*/)
@@ -295,7 +346,9 @@ static jboolean copyURL(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@");
#endif
- return m_androidInputContext->copyURL();
+ jboolean res;
+ runOnQtThread([&]{res = m_androidInputContext->copyURL();});
+ return res;
}
static jboolean paste(JNIEnv */*env*/, jobject /*thiz*/)
@@ -306,7 +359,9 @@ static jboolean paste(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@ PASTE");
#endif
- return m_androidInputContext->paste();
+ jboolean res;
+ runOnQtThread([&]{res = m_androidInputContext->paste();});
+ return res;
}
static jboolean updateCursorPosition(JNIEnv */*env*/, jobject /*thiz*/)
@@ -317,7 +372,8 @@ static jboolean updateCursorPosition(JNIEnv */*env*/, jobject /*thiz*/)
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
qDebug("@@@ UPDATECURSORPOS");
#endif
- m_androidInputContext->updateCursorPosition();
+
+ runOnQtThread([&]{m_androidInputContext->updateCursorPosition();});
return true;
}
@@ -365,7 +421,7 @@ static QRect inputItemRectangle()
QAndroidInputContext::QAndroidInputContext()
: QPlatformInputContext(), m_composingTextStart(-1), m_blockUpdateSelection(false),
- m_cursorHandleShown(CursorHandleNotShown), m_batchEditNestingLevel(0), m_focusObject(0)
+ m_handleMode(Hidden), m_batchEditNestingLevel(0), m_focusObject(0)
{
jclass clazz = QJNIEnvironmentPrivate::findClass(QtNativeInputConnectionClassName);
if (Q_UNLIKELY(!clazz)) {
@@ -445,10 +501,17 @@ QAndroidInputContext::QAndroidInputContext()
auto im = qGuiApp->inputMethod();
if (!im->inputItemClipRectangle().contains(im->anchorRectangle()) ||
!im->inputItemClipRectangle().contains(im->cursorRectangle())) {
- m_cursorHandleShown = CursorHandleNotShown;
+ m_handleMode = Hidden;
updateSelectionHandles();
}
});
+ m_hideCursorHandleTimer.setInterval(4000);
+ m_hideCursorHandleTimer.setSingleShot(true);
+ m_hideCursorHandleTimer.setTimerType(Qt::VeryCoarseTimer);
+ connect(&m_hideCursorHandleTimer, &QTimer::timeout, this, [this]{
+ m_handleMode = Hidden;
+ updateSelectionHandles();
+ });
}
QAndroidInputContext::~QAndroidInputContext()
@@ -486,9 +549,9 @@ void QAndroidInputContext::reset()
{
clear();
m_batchEditNestingLevel = 0;
- m_cursorHandleShown = QAndroidInputContext::CursorHandleNotShown;
+ m_handleMode = Hidden;
if (qGuiApp->focusObject()) {
- QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQueryThreadSafe(Qt::ImEnabled);
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery(Qt::ImEnabled);
if (!query.isNull() && query->value(Qt::ImEnabled).toBool()) {
QtAndroidInput::resetSoftwareKeyboard();
return;
@@ -504,7 +567,7 @@ void QAndroidInputContext::commit()
void QAndroidInputContext::updateCursorPosition()
{
- QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQueryThreadSafe();
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (!query.isNull() && !m_blockUpdateSelection && !m_batchEditNestingLevel) {
const int cursorPos = getAbsoluteCursorPosition(query);
const int composeLength = m_composingText.length();
@@ -542,9 +605,9 @@ void QAndroidInputContext::updateSelectionHandles()
return;
auto im = qGuiApp->inputMethod();
- if (!m_focusObject || (m_cursorHandleShown == CursorHandleNotShown)) {
+ if (!m_focusObject || ((m_handleMode & 0xff) == Hidden)) {
// Hide the handles
- QtAndroidInput::updateHandles(0);
+ QtAndroidInput::updateHandles(Hidden);
return;
}
QWindow *window = qGuiApp->focusWindow();
@@ -552,25 +615,34 @@ void QAndroidInputContext::updateSelectionHandles()
? QHighDpiScaling::factor(window)
: QHighDpiScaling::factor(QtAndroid::androidPlatformIntegration()->screen());
- QInputMethodQueryEvent query(Qt::ImCursorPosition | Qt::ImAnchorPosition | Qt::ImEnabled | Qt::ImCurrentSelection);
+ QInputMethodQueryEvent query(Qt::ImCursorPosition | Qt::ImAnchorPosition | Qt::ImEnabled | Qt::ImCurrentSelection | Qt::ImHints | Qt::ImSurroundingText);
QCoreApplication::sendEvent(m_focusObject, &query);
+
int cpos = query.value(Qt::ImCursorPosition).toInt();
int anchor = query.value(Qt::ImAnchorPosition).toInt();
if (cpos == anchor || im->anchorRectangle().isNull()) {
if (!query.value(Qt::ImEnabled).toBool()) {
- QtAndroidInput::updateHandles(0);
+ QtAndroidInput::updateHandles(Hidden);
return;
}
auto curRect = im->cursorRectangle();
QPoint cursorPoint(curRect.center().x(), curRect.bottom());
- QPoint editMenuPoint(curRect.center().x(), curRect.top());
- QtAndroidInput::updateHandles(m_cursorHandleShown, cursorPoint * pixelDensity,
- editMenuPoint * pixelDensity);
+ QPoint editMenuPoint(curRect.x(), curRect.y());
+ m_handleMode &= ShowEditPopup;
+ m_handleMode |= ShowCursor;
+ uint32_t buttons = EditContext::PasteButton;
+ if (!query.value(Qt::ImSurroundingText).toString().isEmpty())
+ buttons |= EditContext::SelectAllButton;
+ QtAndroidInput::updateHandles(m_handleMode, editMenuPoint * pixelDensity, buttons, cursorPoint * pixelDensity);
+ // The VK is hidden, reset the timer
+ if (m_hideCursorHandleTimer.isActive())
+ m_hideCursorHandleTimer.start();
return;
}
+ m_handleMode = ShowSelection | ShowEditPopup ;
auto leftRect = im->cursorRectangle();
auto rightRect = im->anchorRectangle();
if (cpos > anchor)
@@ -578,13 +650,10 @@ void QAndroidInputContext::updateSelectionHandles()
QPoint leftPoint(leftRect.bottomLeft().toPoint() * pixelDensity);
QPoint righPoint(rightRect.bottomRight().toPoint() * pixelDensity);
- QtAndroidInput::updateHandles(CursorHandleShowSelection, leftPoint, righPoint,
+ QPoint editPoint(leftRect.united(rightRect).topLeft().toPoint() * pixelDensity);
+ QtAndroidInput::updateHandles(m_handleMode, editPoint, EditContext::AllButtons, leftPoint, righPoint,
query.value(Qt::ImCurrentSelection).toString().isRightToLeft());
-
- if (m_cursorHandleShown == CursorHandleShowPopup) {
- // make sure the popup does not reappear when the selection menu closes
- m_cursorHandleShown = QAndroidInputContext::CursorHandleNotShown;
- }
+ m_hideCursorHandleTimer.stop();
}
/*
@@ -594,8 +663,10 @@ void QAndroidInputContext::updateSelectionHandles()
*/
void QAndroidInputContext::handleLocationChanged(int handleId, int x, int y)
{
- if (m_batchEditNestingLevel.load() || m_blockUpdateSelection)
+ if (m_batchEditNestingLevel.load() || m_blockUpdateSelection) {
+ qWarning() << "QAndroidInputContext::handleLocationChanged returned";
return;
+ }
finishComposingText();
@@ -669,34 +740,86 @@ void QAndroidInputContext::handleLocationChanged(int handleId, int x, int y)
void QAndroidInputContext::touchDown(int x, int y)
{
- if (m_focusObject && inputItemRectangle().contains(x, y) && !m_cursorHandleShown) {
+ if (m_focusObject && inputItemRectangle().contains(x, y)) {
// If the user touch the input rectangle, we can show the cursor handle
- m_cursorHandleShown = QAndroidInputContext::CursorHandleShowNormal;
+ m_handleMode = ShowCursor;
+ // The VK will appear in a moment, stop the timer
+ m_hideCursorHandleTimer.stop();
+ finishComposingText();
updateSelectionHandles();
}
}
void QAndroidInputContext::longPress(int x, int y)
{
+ static bool noHandles = qEnvironmentVariableIntValue("QT_QPA_NO_TEXT_HANDLES");
+ if (noHandles)
+ return;
+
if (m_focusObject && inputItemRectangle().contains(x, y)) {
- // Show the paste menu if there is something to paste.
- m_cursorHandleShown = QAndroidInputContext::CursorHandleShowPopup;
+ finishComposingText();
+
+ // Release left button, otherwise the following events will cancel the menu popup
+ QtAndroidInput::releaseMouse(x, y);
+
+ handleLocationChanged(1, x, y);
+ ScopedValueChangeBack<bool> svcb(m_blockUpdateSelection, true);
+
+ QInputMethodQueryEvent query(Qt::ImCursorPosition | Qt::ImAnchorPosition | Qt::ImTextBeforeCursor | Qt::ImTextAfterCursor);
+ QCoreApplication::sendEvent(m_focusObject, &query);
+ int cursor = query.value(Qt::ImCursorPosition).toInt();
+ int anchor = cursor;
+ QString before = query.value(Qt::ImTextBeforeCursor).toString();
+ QString after = query.value(Qt::ImTextAfterCursor).toString();
+ for (const auto &ch : after) {
+ if (!ch.isLetterOrNumber())
+ break;
+ ++anchor;
+ }
+
+ for (auto itch = before.rbegin(); itch != after.rend(); ++itch) {
+ if (!itch->isLetterOrNumber())
+ break;
+ --cursor;
+ }
+ if (cursor == anchor || cursor < 0 || cursor - anchor > 500) {
+ m_handleMode = ShowCursor | ShowEditPopup;
+ updateSelectionHandles();
+ return;
+ }
+ QList<QInputMethodEvent::Attribute> imAttributes;
+ imAttributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, cursor, 0, QVariant()));
+ imAttributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection, anchor, cursor - anchor, QVariant()));
+ QInputMethodEvent event(QString(), imAttributes);
+ QGuiApplication::sendEvent(m_focusObject, &event);
+
+ m_handleMode = ShowSelection | ShowEditPopup;
updateSelectionHandles();
}
}
void QAndroidInputContext::keyDown()
{
- if (m_cursorHandleShown) {
+ if (m_handleMode) {
// When the user enter text on the keyboard, we hide the cursor handle
- m_cursorHandleShown = QAndroidInputContext::CursorHandleNotShown;
+ m_handleMode = Hidden;
+ updateSelectionHandles();
+ }
+}
+
+void QAndroidInputContext::hideSelectionHandles()
+{
+ if (m_handleMode & ShowSelection) {
+ m_handleMode = Hidden;
updateSelectionHandles();
+ } else {
+ m_hideCursorHandleTimer.start();
}
}
void QAndroidInputContext::update(Qt::InputMethodQueries queries)
{
- QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQueryThreadSafe(queries);
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery(queries);
if (query.isNull())
return;
#warning TODO extract the needed data from query
@@ -728,7 +851,7 @@ void QAndroidInputContext::showInputPanel()
connect(qGuiApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(showInputPanelLater(Qt::ApplicationState)));
return;
}
- QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQueryThreadSafe();
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (query.isNull())
return;
@@ -752,6 +875,14 @@ void QAndroidInputContext::showInputPanelLater(Qt::ApplicationState state)
showInputPanel();
}
+void QAndroidInputContext::safeCall(const std::function<void()> &func, Qt::ConnectionType conType)
+{
+ if (qGuiApp->thread() == QThread::currentThread())
+ func();
+ else
+ QMetaObject::invokeMethod(this, "safeCall", conType, Q_ARG(std::function<void()>, func));
+}
+
void QAndroidInputContext::hideInputPanel()
{
QtAndroidInput::hideSoftwareKeyboard();
@@ -810,17 +941,15 @@ jboolean QAndroidInputContext::endBatchEdit()
*/
jboolean QAndroidInputContext::commitText(const QString &text, jint newCursorPosition)
{
- bool updateSelectionWasBlocked = m_blockUpdateSelection;
- m_blockUpdateSelection = true;
-
+ ScopedValueChangeBack<bool> svcb(m_blockUpdateSelection, true);
QInputMethodEvent event;
event.setCommitString(text);
- sendInputMethodEventThreadSafe(&event);
+ sendInputMethodEvent(&event);
clear();
// Qt has now put the cursor at the end of the text, corresponding to newCursorPosition == 1
if (newCursorPosition != 1) {
- QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQueryThreadSafe();
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (!query.isNull()) {
QList<QInputMethodEvent::Attribute> attributes;
const int localPos = query->value(Qt::ImCursorPosition).toInt();
@@ -832,15 +961,14 @@ jboolean QAndroidInputContext::commitText(const QString &text, jint newCursorPos
newLocalPos, 0));
}
}
- m_blockUpdateSelection = updateSelectionWasBlocked;
-
+ svcb.setOldValue();
updateCursorPosition();
return JNI_TRUE;
}
jboolean QAndroidInputContext::deleteSurroundingText(jint leftLength, jint rightLength)
{
- QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQueryThreadSafe();
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (query.isNull())
return JNI_TRUE;
@@ -854,7 +982,7 @@ jboolean QAndroidInputContext::deleteSurroundingText(jint leftLength, jint right
QInputMethodEvent event;
event.setCommitString(QString(), -leftLength, leftLength+rightLength);
- sendInputMethodEventThreadSafe(&event);
+ sendInputMethodEvent(&event);
clear();
return JNI_TRUE;
@@ -866,7 +994,7 @@ jboolean QAndroidInputContext::finishComposingText()
if (m_composingText.isEmpty())
return JNI_TRUE; // not composing
- QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQueryThreadSafe();
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (query.isNull())
return JNI_FALSE;
@@ -879,7 +1007,7 @@ jboolean QAndroidInputContext::finishComposingText()
QInputMethodEvent event(QString(), attributes);
event.setCommitString(m_composingText);
- sendInputMethodEventThreadSafe(&event);
+ sendInputMethodEvent(&event);
clear();
return JNI_TRUE;
@@ -888,7 +1016,7 @@ jboolean QAndroidInputContext::finishComposingText()
jint QAndroidInputContext::getCursorCapsMode(jint /*reqModes*/)
{
jint res = 0;
- QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQueryThreadSafe();
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (query.isNull())
return res;
@@ -922,7 +1050,7 @@ const QAndroidInputContext::ExtractedText &QAndroidInputContext::getExtractedTex
// updateExtractedText(View, int, ExtractedText) whenever you call
// updateSelection(View, int, int, int, int)." QTBUG-37980
- QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQueryThreadSafe();
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (query.isNull())
return m_extractedText;
@@ -967,7 +1095,7 @@ const QAndroidInputContext::ExtractedText &QAndroidInputContext::getExtractedTex
QString QAndroidInputContext::getSelectedText(jint /*flags*/)
{
- QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQueryThreadSafe();
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (query.isNull())
return QString();
@@ -977,13 +1105,13 @@ QString QAndroidInputContext::getSelectedText(jint /*flags*/)
QString QAndroidInputContext::getTextAfterCursor(jint length, jint /*flags*/)
{
//### the preedit text could theoretically be after the cursor
- QVariant textAfter = queryFocusObjectThreadSafe(Qt::ImTextAfterCursor, QVariant(length));
+ QVariant textAfter = QInputMethod::queryFocusObject(Qt::ImTextAfterCursor, QVariant(length));
if (textAfter.isValid()) {
return textAfter.toString().left(length);
}
//compatibility code for old controls that do not implement the new API
- QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQueryThreadSafe();
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (query.isNull())
return QString();
@@ -997,12 +1125,12 @@ QString QAndroidInputContext::getTextAfterCursor(jint length, jint /*flags*/)
QString QAndroidInputContext::getTextBeforeCursor(jint length, jint /*flags*/)
{
- QVariant textBefore = queryFocusObjectThreadSafe(Qt::ImTextBeforeCursor, QVariant(length));
+ QVariant textBefore = QInputMethod::queryFocusObject(Qt::ImTextBeforeCursor, QVariant(length));
if (textBefore.isValid())
return textBefore.toString().rightRef(length) + m_composingText;
//compatibility code for old controls that do not implement the new API
- QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQueryThreadSafe();
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (query.isNull())
return QString();
@@ -1028,7 +1156,7 @@ QString QAndroidInputContext::getTextBeforeCursor(jint length, jint /*flags*/)
jboolean QAndroidInputContext::setComposingText(const QString &text, jint newCursorPosition)
{
- QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQueryThreadSafe();
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (query.isNull())
return JNI_FALSE;
@@ -1050,7 +1178,7 @@ jboolean QAndroidInputContext::setComposingText(const QString &text, jint newCur
QVariant(underlined)));
QInputMethodEvent event(m_composingText, attributes);
- sendInputMethodEventThreadSafe(&event);
+ sendInputMethodEvent(&event);
QMetaObject::invokeMethod(this, "keyDown");
@@ -1074,7 +1202,7 @@ jboolean QAndroidInputContext::setComposingRegion(jint start, jint end)
if (wasComposing)
finishComposingText();
- QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQueryThreadSafe();
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (query.isNull())
return JNI_FALSE;
@@ -1095,8 +1223,7 @@ jboolean QAndroidInputContext::setComposingRegion(jint start, jint end)
int localStart = start - blockPosition; // Qt uses position inside block
int currentCursor = wasComposing ? m_composingCursor : blockPosition + localPos;
- bool updateSelectionWasBlocked = m_blockUpdateSelection;
- m_blockUpdateSelection = true;
+ ScopedValueChangeBack<bool> svcb(m_blockUpdateSelection, true);
QString text = query->value(Qt::ImSurroundingText).toString();
@@ -1120,12 +1247,10 @@ jboolean QAndroidInputContext::setComposingRegion(jint start, jint end)
QInputMethodEvent event(m_composingText, attributes);
event.setCommitString(QString(), relativeStart, length);
- sendInputMethodEventThreadSafe(&event);
-
- m_blockUpdateSelection = updateSelectionWasBlocked;
+ sendInputMethodEvent(&event);
#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
- QSharedPointer<QInputMethodQueryEvent> query2 = focusObjectInputMethodQueryThreadSafe();
+ QSharedPointer<QInputMethodQueryEvent> query2 = focusObjectInputMethodQuery();
if (!query2.isNull()) {
qDebug() << "Setting. Prev local cpos:" << localPos << "block pos:" <<blockPosition << "comp.start:" << m_composingTextStart << "rel.start:" << relativeStart << "len:" << length << "cpos attr:" << localPos - localStart;
qDebug() << "New cursor pos" << getAbsoluteCursorPosition(query2);
@@ -1137,7 +1262,7 @@ jboolean QAndroidInputContext::setComposingRegion(jint start, jint end)
jboolean QAndroidInputContext::setSelection(jint start, jint end)
{
- QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQueryThreadSafe();
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (query.isNull())
return JNI_FALSE;
@@ -1168,26 +1293,31 @@ jboolean QAndroidInputContext::setSelection(jint start, jint end)
end - start));
}
QInputMethodEvent event(m_composingText, attributes);
- sendInputMethodEventThreadSafe(&event);
+ sendInputMethodEvent(&event);
updateCursorPosition();
return JNI_TRUE;
}
jboolean QAndroidInputContext::selectAll()
{
+ finishComposingText();
+ m_handleMode = ShowCursor;
sendShortcut(QKeySequence::SelectAll);
return JNI_TRUE;
}
jboolean QAndroidInputContext::cut()
{
- m_cursorHandleShown = CursorHandleNotShown;
+ finishComposingText();
+ m_handleMode = ShowCursor;
sendShortcut(QKeySequence::Cut);
return JNI_TRUE;
}
jboolean QAndroidInputContext::copy()
{
+ finishComposingText();
+ m_handleMode = ShowCursor;
sendShortcut(QKeySequence::Copy);
return JNI_TRUE;
}
@@ -1201,7 +1331,7 @@ jboolean QAndroidInputContext::copyURL()
jboolean QAndroidInputContext::paste()
{
finishComposingText();
- m_cursorHandleShown = CursorHandleNotShown;
+ m_handleMode = ShowCursor;
sendShortcut(QKeySequence::Paste);
return JNI_TRUE;
}
@@ -1217,65 +1347,24 @@ void QAndroidInputContext::sendShortcut(const QKeySequence &sequence)
}
}
-Q_INVOKABLE QVariant QAndroidInputContext::queryFocusObjectUnsafe(Qt::InputMethodQuery query, QVariant argument)
-{
- return QInputMethod::queryFocusObject(query, argument);
-}
-
-QVariant QAndroidInputContext::queryFocusObjectThreadSafe(Qt::InputMethodQuery query, QVariant argument)
-{
- QVariant retval;
+QSharedPointer<QInputMethodQueryEvent> QAndroidInputContext::focusObjectInputMethodQuery(Qt::InputMethodQueries queries) {
if (!qGuiApp)
- return retval;
- const bool inMainThread = qGuiApp->thread() == QThread::currentThread();
- if (QAndroidEventDispatcherStopper::stopped() && !inMainThread)
- return retval;
- AndroidDeadlockProtector protector;
- if (!inMainThread && !protector.acquire())
- return retval;
-
- QMetaObject::invokeMethod(this, "queryFocusObjectUnsafe",
- inMainThread ? Qt::DirectConnection : Qt::BlockingQueuedConnection,
- Q_RETURN_ARG(QVariant, retval),
- Q_ARG(Qt::InputMethodQuery, query),
- Q_ARG(QVariant, argument));
+ return {};
- return retval;
-}
-
-QSharedPointer<QInputMethodQueryEvent> QAndroidInputContext::focusObjectInputMethodQueryThreadSafe(Qt::InputMethodQueries queries) {
- QSharedPointer<QInputMethodQueryEvent> retval;
- if (!qGuiApp)
- return QSharedPointer<QInputMethodQueryEvent>();
- const bool inMainThread = qGuiApp->thread() == QThread::currentThread();
- if (QAndroidEventDispatcherStopper::stopped() && !inMainThread)
- return QSharedPointer<QInputMethodQueryEvent>();
- AndroidDeadlockProtector protector;
- if (!inMainThread && !protector.acquire())
- return QSharedPointer<QInputMethodQueryEvent>();
-
- QInputMethodQueryEvent *queryEvent = 0;
- QMetaObject::invokeMethod(this, "focusObjectInputMethodQueryUnsafe",
- inMainThread ? Qt::DirectConnection : Qt::BlockingQueuedConnection,
- Q_RETURN_ARG(QInputMethodQueryEvent*, queryEvent),
- Q_ARG(Qt::InputMethodQueries, queries));
-
- return QSharedPointer<QInputMethodQueryEvent>(queryEvent);
-}
-
-QInputMethodQueryEvent *QAndroidInputContext::focusObjectInputMethodQueryUnsafe(Qt::InputMethodQueries queries)
-{
QObject *focusObject = qGuiApp->focusObject();
if (!focusObject)
- return 0;
+ return {};
QInputMethodQueryEvent *ret = new QInputMethodQueryEvent(queries);
QCoreApplication::sendEvent(focusObject, ret);
- return ret;
+ return QSharedPointer<QInputMethodQueryEvent>(ret);
}
-void QAndroidInputContext::sendInputMethodEventUnsafe(QInputMethodEvent *event)
+void QAndroidInputContext::sendInputMethodEvent(QInputMethodEvent *event)
{
+ if (!qGuiApp)
+ return;
+
QObject *focusObject = qGuiApp->focusObject();
if (!focusObject)
return;
@@ -1283,19 +1372,4 @@ void QAndroidInputContext::sendInputMethodEventUnsafe(QInputMethodEvent *event)
QCoreApplication::sendEvent(focusObject, event);
}
-void QAndroidInputContext::sendInputMethodEventThreadSafe(QInputMethodEvent *event)
-{
- if (!qGuiApp)
- return;
- const bool inMainThread = qGuiApp->thread() == QThread::currentThread();
- if (QAndroidEventDispatcherStopper::stopped() && !inMainThread)
- return;
- AndroidDeadlockProtector protector;
- if (!inMainThread && !protector.acquire())
- return;
- QMetaObject::invokeMethod(this, "sendInputMethodEventUnsafe",
- inMainThread ? Qt::DirectConnection : Qt::BlockingQueuedConnection,
- Q_ARG(QInputMethodEvent*, event));
-}
-
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/android/qandroidinputcontext.h b/src/plugins/platforms/android/qandroidinputcontext.h
index e7692bf720..bd3edb30f0 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.h
+++ b/src/plugins/platforms/android/qandroidinputcontext.h
@@ -42,8 +42,10 @@
#define ANDROIDINPUTCONTEXT_H
#include <qpa/qplatforminputcontext.h>
+#include <functional>
#include <jni.h>
#include <qevent.h>
+#include <QTimer>
QT_BEGIN_NAMESPACE
@@ -58,6 +60,22 @@ class QAndroidInputContext: public QPlatformInputContext
};
public:
+ enum EditContext : uint32_t {
+ CutButton = 1 << 0,
+ CopyButton = 1 << 1,
+ PasteButton = 1 << 2,
+ SelectAllButton = 1 << 3,
+ AllButtons = CutButton | CopyButton | PasteButton | SelectAllButton
+ };
+
+ enum HandleMode {
+ Hidden = 0,
+ ShowCursor = 1,
+ ShowSelection = 2,
+ ShowEditPopup = 0x100
+ };
+ Q_DECLARE_FLAGS(HandleModes, HandleMode)
+
struct ExtractedText
{
ExtractedText() { clear(); }
@@ -118,25 +136,21 @@ public:
jboolean paste();
public slots:
+ void safeCall(const std::function<void()> &func, Qt::ConnectionType conType = Qt::BlockingQueuedConnection);
void updateCursorPosition();
void updateSelectionHandles();
void handleLocationChanged(int handleId, int x, int y);
void touchDown(int x, int y);
void longPress(int x, int y);
void keyDown();
+ void hideSelectionHandles();
private slots:
void showInputPanelLater(Qt::ApplicationState);
private:
- void sendInputMethodEventThreadSafe(QInputMethodEvent *event);
- Q_INVOKABLE void sendInputMethodEventUnsafe(QInputMethodEvent *event);
-
- QSharedPointer<QInputMethodQueryEvent> focusObjectInputMethodQueryThreadSafe(Qt::InputMethodQueries queries = Qt::ImQueryAll);
- Q_INVOKABLE QInputMethodQueryEvent *focusObjectInputMethodQueryUnsafe(Qt::InputMethodQueries queries);
-
- Q_INVOKABLE QVariant queryFocusObjectUnsafe(Qt::InputMethodQuery query, QVariant argument);
- QVariant queryFocusObjectThreadSafe(Qt::InputMethodQuery query, QVariant argument);
+ void sendInputMethodEvent(QInputMethodEvent *event);
+ QSharedPointer<QInputMethodQueryEvent> focusObjectInputMethodQuery(Qt::InputMethodQueries queries = Qt::ImQueryAll);
private:
ExtractedText m_extractedText;
@@ -145,17 +159,12 @@ private:
int m_composingCursor;
QMetaObject::Connection m_updateCursorPosConnection;
bool m_blockUpdateSelection;
- enum CursorHandleShowMode {
- CursorHandleNotShown,
- CursorHandleShowNormal = 1,
- CursorHandleShowSelection = 2,
- CursorHandleShowPopup = 3
- };
- CursorHandleShowMode m_cursorHandleShown;
+ HandleModes m_handleMode;
QAtomicInt m_batchEditNestingLevel;
QObject *m_focusObject;
+ QTimer m_hideCursorHandleTimer;
};
-
+Q_DECLARE_OPERATORS_FOR_FLAGS(QAndroidInputContext::HandleModes)
QT_END_NAMESPACE
#endif // ANDROIDINPUTCONTEXT_H
diff --git a/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp b/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp
index ced35c4cfa..9218afa7f5 100644
--- a/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp
+++ b/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2018 The Qt Company Ltd.
** Copyright (C) 2013 BogDan Vatra <bogdan@kde.org>
** Contact: https://www.qt.io/licensing/
**
@@ -117,6 +118,15 @@ bool QAndroidPlatformMessageDialogHelper::show(Qt::WindowFlags windowFlags
void QAndroidPlatformMessageDialogHelper::addButtons(QSharedPointer<QMessageDialogOptions> opt, ButtonRole role)
{
+ for (const QMessageDialogOptions::CustomButton &b : opt->customButtons()) {
+ if (b.role == role) {
+ QString label = b.label;
+ label.remove(QChar('&'));
+ m_javaMessageDialog.callMethod<void>("addButton", "(ILjava/lang/String;)V", b.id,
+ QJNIObjectPrivate::fromString(label).object());
+ }
+ }
+
for (int i = QPlatformDialogHelper::FirstButton; i < QPlatformDialogHelper::LastButton; i<<=1) {
StandardButton b = static_cast<StandardButton>(i);
if (buttonRole(b) == role && (opt->standardButtons() & i)) {
@@ -144,6 +154,12 @@ void QAndroidPlatformMessageDialogHelper::dialogResult(int buttonID)
QPlatformDialogHelper::StandardButton standardButton = static_cast<QPlatformDialogHelper::StandardButton>(buttonID);
QPlatformDialogHelper::ButtonRole role = QPlatformDialogHelper::buttonRole(standardButton);
+ if (buttonID > QPlatformDialogHelper::LastButton) {
+ const QMessageDialogOptions::CustomButton *custom = options()->customButton(buttonID);
+ Q_ASSERT(custom);
+ role = custom->role;
+ }
+
emit clicked(standardButton, role);
}
diff --git a/src/plugins/platforms/android/qandroidplatformmenubar.h b/src/plugins/platforms/android/qandroidplatformmenubar.h
index 0316ea9362..f5935b8177 100644
--- a/src/plugins/platforms/android/qandroidplatformmenubar.h
+++ b/src/plugins/platforms/android/qandroidplatformmenubar.h
@@ -61,7 +61,7 @@ public:
void handleReparent(QWindow *newParentWindow) override;
QPlatformMenu *menuForTag(quintptr tag) const override;
- QWindow *parentWindow() const;
+ QWindow *parentWindow() const override;
PlatformMenusType menus() const;
QMutex *menusListMutex();
diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro
index 2694cb3607..8d65cf328f 100644
--- a/src/plugins/platforms/cocoa/cocoa.pro
+++ b/src/plugins/platforms/cocoa/cocoa.pro
@@ -8,7 +8,6 @@ SOURCES += main.mm \
qcocoawindow.mm \
qnsview.mm \
qnswindow.mm \
- qnsviewaccessibility.mm \
qnswindowdelegate.mm \
qcocoanativeinterface.mm \
qcocoaeventdispatcher.mm \
@@ -72,19 +71,25 @@ HEADERS += qcocoaintegration.h \
qtConfig(opengl.*) {
SOURCES += qcocoaglcontext.mm
-
HEADERS += qcocoaglcontext.h
}
+qtConfig(vulkan) {
+ SOURCES += qcocoavulkaninstance.mm
+ HEADERS += qcocoavulkaninstance.h
+}
+
RESOURCES += qcocoaresources.qrc
-LIBS += -framework AppKit -framework Carbon -framework IOKit -framework QuartzCore -lcups
+LIBS += -framework AppKit -framework CoreServices -framework Carbon -framework IOKit -framework QuartzCore -framework CoreVideo -framework Metal -lcups
QT += \
core-private gui-private \
accessibility_support-private clipboard_support-private theme_support-private \
fontdatabase_support-private graphics_support-private
+qtConfig(vulkan): QT += vulkan_support-private
+
CONFIG += no_app_extension_api_only
qtHaveModule(widgets) {
@@ -122,11 +127,6 @@ qtHaveModule(widgets) {
OTHER_FILES += cocoa.json
-# Acccessibility debug support
-# DEFINES += QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR
-# include ($$PWD/../../../../util/accessibilityinspector/accessibilityinspector.pri)
-
-
PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = QCocoaIntegrationPlugin
!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
diff --git a/src/plugins/platforms/cocoa/main.mm b/src/plugins/platforms/cocoa/main.mm
index f9bfdc7dc7..89ecdf46f9 100644
--- a/src/plugins/platforms/cocoa/main.mm
+++ b/src/plugins/platforms/cocoa/main.mm
@@ -60,7 +60,7 @@ QPlatformIntegration * QCocoaIntegrationPlugin::create(const QString& system, co
if (system.compare(QLatin1String("cocoa"), Qt::CaseInsensitive) == 0)
return new QCocoaIntegration(paramList);
- return 0;
+ return nullptr;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/messages.cpp b/src/plugins/platforms/cocoa/messages.cpp
index 8eea1e654e..06e3dd454e 100644
--- a/src/plugins/platforms/cocoa/messages.cpp
+++ b/src/plugins/platforms/cocoa/messages.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -39,7 +39,8 @@
#include "messages.h"
-#include <QCoreApplication>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qregularexpression.h>
// Translatable messages should go into this .cpp file for them to be picked up by lupdate.
@@ -52,13 +53,13 @@ QString msgAboutQt()
static const char *application_menu_strings[] =
{
+ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","About %1"),
+ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Preferences..."),
QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Services"),
QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Hide %1"),
QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Hide Others"),
QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Show All"),
- QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Preferences..."),
- QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Quit %1"),
- QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","About %1")
+ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU","Quit %1")
};
QString qt_mac_applicationmenu_string(int type)
@@ -77,8 +78,13 @@ QPlatformMenuItem::MenuRole detectMenuRole(const QString &caption)
QString captionNoAmpersand(caption);
captionNoAmpersand.remove(QLatin1Char('&'));
const QString aboutString = QCoreApplication::translate("QCocoaMenuItem", "About");
- if (captionNoAmpersand.startsWith(aboutString, Qt::CaseInsensitive) || caption.endsWith(aboutString, Qt::CaseInsensitive))
+ if (captionNoAmpersand.startsWith(aboutString, Qt::CaseInsensitive)
+ || captionNoAmpersand.endsWith(aboutString, Qt::CaseInsensitive)) {
+ static const QRegularExpression qtRegExp(QLatin1String("qt$"), QRegularExpression::CaseInsensitiveOption);
+ if (captionNoAmpersand.contains(qtRegExp))
+ return QPlatformMenuItem::AboutQtRole;
return QPlatformMenuItem::AboutRole;
+ }
if (captionNoAmpersand.startsWith(QCoreApplication::translate("QCocoaMenuItem", "Config"), Qt::CaseInsensitive)
|| captionNoAmpersand.startsWith(QCoreApplication::translate("QCocoaMenuItem", "Preference"), Qt::CaseInsensitive)
|| captionNoAmpersand.startsWith(QCoreApplication::translate("QCocoaMenuItem", "Options"), Qt::CaseInsensitive)
diff --git a/src/plugins/platforms/cocoa/messages.h b/src/plugins/platforms/cocoa/messages.h
index e41898fe59..3a9eaf604e 100644
--- a/src/plugins/platforms/cocoa/messages.h
+++ b/src/plugins/platforms/cocoa/messages.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -46,13 +46,13 @@
QT_BEGIN_NAMESPACE
enum {
- ServicesAppMenuItem = 0,
+ AboutAppMenuItem = 0,
+ PreferencesAppMenuItem,
+ ServicesAppMenuItem,
HideAppMenuItem,
HideOthersAppMenuItem,
ShowAllAppMenuItem,
- PreferencesAppMenuItem,
- QuitAppMenuItem,
- AboutAppMenuItem
+ QuitAppMenuItem
};
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.h b/src/plugins/platforms/cocoa/qcocoaaccessibility.h
index e456364555..457c158ddc 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibility.h
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.h
@@ -46,6 +46,8 @@
#ifndef QT_NO_ACCESSIBILITY
+@class QT_MANGLE_NAMESPACE(QMacAccessibilityElement);
+
QT_BEGIN_NAMESPACE
class QCocoaAccessibility : public QPlatformAccessibility
@@ -82,9 +84,8 @@ namespace QCocoaAccessible {
NSString *macRole(QAccessibleInterface *interface);
NSString *macSubrole(QAccessibleInterface *interface);
bool shouldBeIgnored(QAccessibleInterface *interface);
-NSArray *unignoredChildren(QAccessibleInterface *interface);
+NSArray<QT_MANGLE_NAMESPACE(QMacAccessibilityElement) *> *unignoredChildren(QAccessibleInterface *interface);
NSString *getTranslatedAction(const QString &qtAction);
-NSMutableArray *createTranslatedActionsList(const QStringList &qtActions);
QString translateAction(NSString *nsAction, QAccessibleInterface *interface);
bool hasValueAttribute(QAccessibleInterface *interface);
id getValueAttribute(QAccessibleInterface *interface);
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
index 654e6210c8..368cf56c80 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
@@ -256,12 +256,12 @@ bool shouldBeIgnored(QAccessibleInterface *interface)
return false;
}
-NSArray *unignoredChildren(QAccessibleInterface *interface)
+NSArray<QMacAccessibilityElement *> *unignoredChildren(QAccessibleInterface *interface)
{
int numKids = interface->childCount();
// qDebug() << "Children for: " << axid << iface << " are: " << numKids;
- NSMutableArray *kids = [NSMutableArray arrayWithCapacity:numKids];
+ NSMutableArray<QMacAccessibilityElement *> *kids = [NSMutableArray<QMacAccessibilityElement *> arrayWithCapacity:numKids];
for (int i = 0; i < numKids; ++i) {
QAccessibleInterface *child = interface->child(i);
if (!child || !child->isValid() || child->state().invalid || child->state().invisible)
@@ -310,7 +310,7 @@ NSString *getTranslatedAction(const QString &qtAction)
// NSAccessibilityCancelAction;
// NSAccessibilityDeleteAction;
- return 0;
+ return nil;
}
@@ -386,7 +386,7 @@ id getValueAttribute(QAccessibleInterface *interface)
}
if (interface->state().checkable) {
- return [NSNumber numberWithInt: (interface->state().checked ? 1 : 0)];
+ return interface->state().checked ? @(1) : @(0);
}
return nil;
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h
index 07f3f3a99e..914aaa2b1b 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.h
@@ -52,13 +52,10 @@
@class QT_MANGLE_NAMESPACE(QMacAccessibilityElement);
-@interface QT_MANGLE_NAMESPACE(QMacAccessibilityElement) : NSObject {
- NSString *role;
- QAccessible::Id axid;
-}
+@interface QT_MANGLE_NAMESPACE(QMacAccessibilityElement) : NSObject
-- (id)initWithId:(QAccessible::Id)anId;
-+ (QT_MANGLE_NAMESPACE(QMacAccessibilityElement) *)elementWithId:(QAccessible::Id)anId;
+- (instancetype)initWithId:(QAccessible::Id)anId;
++ (instancetype)elementWithId:(QAccessible::Id)anId;
@end
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
index df2336d08b..03dc895ffb 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
@@ -99,9 +99,12 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
*end = curEnd;
}
-@implementation QMacAccessibilityElement
+@implementation QMacAccessibilityElement {
+ NSString *role;
+ QAccessible::Id axid;
+}
-- (id)initWithId:(QAccessible::Id)anId
+- (instancetype)initWithId:(QAccessible::Id)anId
{
Q_ASSERT((int)anId < 0);
self = [super init];
@@ -115,7 +118,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
return self;
}
-+ (id)elementWithId:(QAccessible::Id)anId
++ (instancetype)elementWithId:(QAccessible::Id)anId
{
Q_ASSERT(anId);
if (!anId)
@@ -168,22 +171,15 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
{
QStringRef textBefore = QStringRef(&text, 0, index);
int newlines = textBefore.count(QLatin1Char('\n'));
- return [NSNumber numberWithInt: newlines];
+ return @(newlines);
}
- (BOOL) accessibilityNotifiesWhenDestroyed {
return YES;
}
-- (NSArray *)accessibilityAttributeNames {
- static NSArray *defaultAttributes = nil;
-
- QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
- if (!iface || !iface->isValid())
- return defaultAttributes;
-
- if (defaultAttributes == nil) {
- defaultAttributes = [[NSArray alloc] initWithObjects:
+- (NSArray<NSString *> *)accessibilityAttributeNames {
+ static NSArray<NSString *> *defaultAttributes = [@[
NSAccessibilityRoleAttribute,
NSAccessibilityRoleDescriptionAttribute,
NSAccessibilitySubroleAttribute,
@@ -196,35 +192,36 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
NSAccessibilitySizeAttribute,
NSAccessibilityTitleAttribute,
NSAccessibilityDescriptionAttribute,
- NSAccessibilityEnabledAttribute,
- nil];
- }
+ NSAccessibilityEnabledAttribute
+ ] retain];
+
+ QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
+ if (!iface || !iface->isValid())
+ return defaultAttributes;
- NSMutableArray *attributes = [[NSMutableArray alloc] initWithCapacity : [defaultAttributes count]];
- [attributes addObjectsFromArray : defaultAttributes];
+ NSMutableArray<NSString *> *attributes = [[NSMutableArray<NSString *> alloc] initWithCapacity:defaultAttributes.count];
+ [attributes addObjectsFromArray:defaultAttributes];
if (QCocoaAccessible::hasValueAttribute(iface)) {
- [attributes addObject : NSAccessibilityValueAttribute];
+ [attributes addObject:NSAccessibilityValueAttribute];
}
if (iface->textInterface()) {
- [attributes addObjectsFromArray: [[NSArray alloc] initWithObjects:
+ [attributes addObjectsFromArray:@[
NSAccessibilityNumberOfCharactersAttribute,
NSAccessibilitySelectedTextAttribute,
NSAccessibilitySelectedTextRangeAttribute,
NSAccessibilityVisibleCharacterRangeAttribute,
- NSAccessibilityInsertionPointLineNumberAttribute,
- nil
+ NSAccessibilityInsertionPointLineNumberAttribute
]];
// TODO: multi-selection: NSAccessibilitySelectedTextRangesAttribute,
}
if (iface->valueInterface()) {
- [attributes addObjectsFromArray: [[NSArray alloc] initWithObjects:
+ [attributes addObjectsFromArray:@[
NSAccessibilityMinValueAttribute,
- NSAccessibilityMaxValueAttribute,
- nil
+ NSAccessibilityMaxValueAttribute
]];
}
@@ -261,13 +258,13 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
- (id) minValueAttribute:(QAccessibleInterface*)iface {
if (QAccessibleValueInterface *val = iface->valueInterface())
- return [NSNumber numberWithDouble: val->minimumValue().toDouble()];
+ return @(val->minimumValue().toDouble());
return nil;
}
- (id) maxValueAttribute:(QAccessibleInterface*)iface {
if (QAccessibleValueInterface *val = iface->valueInterface())
- return [NSNumber numberWithDouble: val->maximumValue().toDouble()];
+ return @(val->maximumValue().toDouble());
return nil;
}
@@ -289,7 +286,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
} else if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
// Just check if the app thinks we're focused.
id focusedElement = [NSApp accessibilityAttributeValue:NSAccessibilityFocusedUIElementAttribute];
- return [NSNumber numberWithBool:[focusedElement isEqual:self]];
+ return @([focusedElement isEqual:self]);
} else if ([attribute isEqualToString:NSAccessibilityParentAttribute]) {
return NSAccessibilityUnignoredAncestor([self parentElement]);
} else if ([attribute isEqualToString:NSAccessibilityWindowAttribute]) {
@@ -312,7 +309,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
} else if ([attribute isEqualToString:NSAccessibilityDescriptionAttribute]) {
return iface->text(QAccessible::Description).toNSString();
} else if ([attribute isEqualToString:NSAccessibilityEnabledAttribute]) {
- return [NSNumber numberWithBool:!iface->state().disabled];
+ return @(!iface->state().disabled);
} else if ([attribute isEqualToString:NSAccessibilityValueAttribute]) {
// VoiceOver asks for the value attribute for all elements. Return nil
// if we don't want the element to have a value attribute.
@@ -323,7 +320,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
} else if ([attribute isEqualToString:NSAccessibilityNumberOfCharactersAttribute]) {
if (QAccessibleTextInterface *text = iface->textInterface())
- return [NSNumber numberWithInt: text->characterCount()];
+ return @(text->characterCount());
return nil;
} else if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]) {
if (QAccessibleTextInterface *text = iface->textInterface()) {
@@ -357,7 +354,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
int position = text->cursorPosition();
convertLineOffset(text, &line, &position);
}
- return [NSNumber numberWithInt: line];
+ return @(line);
}
return nil;
} else if ([attribute isEqualToString:NSAccessibilityMinValueAttribute]) {
@@ -378,18 +375,17 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
}
if (iface->textInterface()) {
- return [[NSArray alloc] initWithObjects:
- NSAccessibilityStringForRangeParameterizedAttribute,
- NSAccessibilityLineForIndexParameterizedAttribute,
- NSAccessibilityRangeForLineParameterizedAttribute,
- NSAccessibilityRangeForPositionParameterizedAttribute,
-// NSAccessibilityRangeForIndexParameterizedAttribute,
- NSAccessibilityBoundsForRangeParameterizedAttribute,
-// NSAccessibilityRTFForRangeParameterizedAttribute,
- NSAccessibilityStyleRangeForIndexParameterizedAttribute,
- NSAccessibilityAttributedStringForRangeParameterizedAttribute,
- nil
- ];
+ return @[
+ NSAccessibilityStringForRangeParameterizedAttribute,
+ NSAccessibilityLineForIndexParameterizedAttribute,
+ NSAccessibilityRangeForLineParameterizedAttribute,
+ NSAccessibilityRangeForPositionParameterizedAttribute,
+// NSAccessibilityRangeForIndexParameterizedAttribute,
+ NSAccessibilityBoundsForRangeParameterizedAttribute,
+// NSAccessibilityRTFForRangeParameterizedAttribute,
+ NSAccessibilityStyleRangeForIndexParameterizedAttribute,
+ NSAccessibilityAttributedStringForRangeParameterizedAttribute
+ ];
}
return nil;
@@ -416,7 +412,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
return nil;
int line = -1;
convertLineOffset(iface->textInterface(), &line, &index);
- return [NSNumber numberWithInt:line];
+ return @(line);
}
if ([attribute isEqualToString: NSAccessibilityRangeForLineParameterizedAttribute]) {
int line = [parameter intValue];
@@ -573,7 +569,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
return NSAccessibilityUnignoredAncestor(self);
// find the deepest child at the point
- QAccessibleInterface *childOfChildInterface = 0;
+ QAccessibleInterface *childOfChildInterface = nullptr;
do {
childOfChildInterface = childInterface->childAt(screenPoint.x(), screenPoint.y());
if (childOfChildInterface && childOfChildInterface->isValid())
diff --git a/src/plugins/platforms/cocoa/qcocoaapplication.h b/src/plugins/platforms/cocoa/qcocoaapplication.h
index 66a92686bc..15530d8281 100644
--- a/src/plugins/platforms/cocoa/qcocoaapplication.h
+++ b/src/plugins/platforms/cocoa/qcocoaapplication.h
@@ -89,8 +89,7 @@
#import <AppKit/AppKit.h>
-@interface QT_MANGLE_NAMESPACE(QNSApplication) : NSApplication {
-}
+@interface QT_MANGLE_NAMESPACE(QNSApplication) : NSApplication
@end
QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSApplication);
diff --git a/src/plugins/platforms/cocoa/qcocoaapplication.mm b/src/plugins/platforms/cocoa/qcocoaapplication.mm
index d0f27795b6..340191622a 100644
--- a/src/plugins/platforms/cocoa/qcocoaapplication.mm
+++ b/src/plugins/platforms/cocoa/qcocoaapplication.mm
@@ -113,11 +113,11 @@ static const QByteArray q_macLocalEventType = QByteArrayLiteral("mac_generic_NSE
static bool qt_filterEvent(NSEvent *event)
{
if (qApp && qApp->eventDispatcher()->
- filterNativeEvent(q_macLocalEventType, static_cast<void*>(event), 0))
+ filterNativeEvent(q_macLocalEventType, static_cast<void*>(event), nullptr))
return true;
- if ([event type] == NSApplicationDefined) {
- switch (static_cast<short>([event subtype])) {
+ if (event.type == NSEventTypeApplicationDefined) {
+ switch (static_cast<short>(event.subtype)) {
case QtCocoaEventSubTypePostMessage:
qt_sendPostedMessage(event);
return true;
@@ -137,7 +137,7 @@ static void qt_maybeSendKeyEquivalentUpEvent(NSEvent *event)
// and forward the key event to the key (focus) window.
// However, non-Qt windows will not (and should not) get
// any special treatment, only QWindow-owned NSWindows.
- if (event.type == NSKeyUp && (event.modifierFlags & NSCommandKeyMask)) {
+ if (event.type == NSEventTypeKeyUp && (event.modifierFlags & NSEventModifierFlagCommand)) {
NSWindow *targetWindow = event.window;
if ([targetWindow.class conformsToProtocol:@protocol(QNSWindowProtocol)])
[targetWindow sendEvent:event];
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h
index 59c71017e3..0816730c54 100644
--- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h
+++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -90,20 +90,18 @@
#include <qglobal.h>
#include <private/qcore_mac_p.h>
-@class QT_MANGLE_NAMESPACE(QCocoaMenuLoader);
+Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QCocoaNSMenuItem));
-@interface QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) : NSObject <NSApplicationDelegate> {
- bool startedQuit;
- NSMenu *dockMenu;
- NSObject <NSApplicationDelegate> *reflectionDelegate;
- bool inLaunch;
-}
-+ (QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate)*)sharedDelegate;
-- (void)setDockMenu:(NSMenu *)newMenu;
-- (void)setReflectionDelegate:(NSObject <NSApplicationDelegate> *)oldDelegate;
-- (void)getUrl:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
-- (void) removeAppleEventHandlers;
-- (bool) inLaunch;
+@interface QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) : NSObject <NSApplicationDelegate>
+@property (nonatomic, retain) NSMenu *dockMenu;
++ (instancetype)sharedDelegate;
+- (void)setReflectionDelegate:(NSObject<NSApplicationDelegate> *)oldDelegate;
+- (void)removeAppleEventHandlers;
+- (bool)inLaunch;
+@end
+
+@interface QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) (MenuAPI)
+- (void)qt_itemFired:(QT_MANGLE_NAMESPACE(QCocoaNSMenuItem) *)item;
@end
QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaApplicationDelegate);
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
index a94e0dc517..44ab16d300 100644
--- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
+++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -73,9 +73,12 @@
#import "qcocoaapplicationdelegate.h"
-#import "qnswindowdelegate.h"
-#import "qcocoamenuloader.h"
#include "qcocoaintegration.h"
+#include "qcocoamenu.h"
+#include "qcocoamenuloader.h"
+#include "qcocoamenuitem.h"
+#include "qcocoansmenu.h"
+
#include <qevent.h>
#include <qurl.h>
#include <qdebug.h>
@@ -83,10 +86,16 @@
#include <private/qguiapplication_p.h>
#include "qt_mac_p.h"
#include <qpa/qwindowsysteminterface.h>
+#include <qwindowdefs.h>
QT_USE_NAMESPACE
-@implementation QCocoaApplicationDelegate
+@implementation QCocoaApplicationDelegate {
+ bool startedQuit;
+ NSObject <NSApplicationDelegate> *reflectionDelegate;
+ bool inLaunch;
+ QWindowList hiddenWindows;
+}
+ (instancetype)sharedDelegate
{
@@ -102,7 +111,7 @@ QT_USE_NAMESPACE
return shared;
}
-- (id)init
+- (instancetype)init
{
self = [super init];
if (self) {
@@ -125,7 +134,7 @@ QT_USE_NAMESPACE
- (void)dealloc
{
- [dockMenu release];
+ [_dockMenu release];
if (reflectionDelegate) {
[[NSApplication sharedApplication] setDelegate:reflectionDelegate];
[reflectionDelegate release];
@@ -135,23 +144,16 @@ QT_USE_NAMESPACE
[super dealloc];
}
-- (void)setDockMenu:(NSMenu*)newMenu
-{
- [newMenu retain];
- [dockMenu release];
- dockMenu = newMenu;
-}
-
- (NSMenu *)applicationDockMenu:(NSApplication *)sender
{
Q_UNUSED(sender);
// Manually invoke the delegate's -menuWillOpen: method.
// See QTBUG-39604 (and its fix) for details.
- [[dockMenu delegate] menuWillOpen:dockMenu];
- return [[dockMenu retain] autorelease];
+ [self.dockMenu.delegate menuWillOpen:self.dockMenu];
+ return [[self.dockMenu retain] autorelease];
}
-- (BOOL) canQuit
+- (BOOL)canQuit
{
[[NSApp mainMenu] cancelTracking];
@@ -219,7 +221,7 @@ QT_USE_NAMESPACE
return NSTerminateCancel;
}
-- (void) applicationWillFinishLaunching:(NSNotification *)notification
+- (void)applicationWillFinishLaunching:(NSNotification *)notification
{
Q_UNUSED(notification);
@@ -249,14 +251,14 @@ QT_USE_NAMESPACE
}
// called by QCocoaIntegration's destructor before resetting the application delegate to nil
-- (void) removeAppleEventHandlers
+- (void)removeAppleEventHandlers
{
NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager];
[eventManager removeEventHandlerForEventClass:kCoreEventClass andEventID:kAEQuitApplication];
[eventManager removeEventHandlerForEventClass:kInternetEventClass andEventID:kAEGetURL];
}
-- (bool) inLaunch
+- (bool)inLaunch
{
return inLaunch;
}
@@ -267,13 +269,11 @@ QT_USE_NAMESPACE
inLaunch = false;
if (qEnvironmentVariableIsEmpty("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM")) {
- if (__builtin_available(macOS 10.12, *)) {
- // Move the application window to front to avoid launching behind the terminal.
- // Ignoring other apps is necessary (we must ignore the terminal), but makes
- // Qt apps play slightly less nice with other apps when lanching from Finder
- // (See the activateIgnoringOtherApps docs.)
- [[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
- }
+ // Move the application window to front to avoid launching behind the terminal.
+ // Ignoring other apps is necessary (we must ignore the terminal), but makes
+ // Qt apps play slightly less nice with other apps when lanching from Finder
+ // (See the activateIgnoringOtherApps docs.)
+ [[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
}
}
@@ -324,12 +324,28 @@ QT_USE_NAMESPACE
// fact that the application itself is hidden, which will cause a problem when
// the application is made visible again.
const QWindowList topLevelWindows = QGuiApplication::topLevelWindows();
- for (QWindow *topLevelWindow : qAsConst(topLevelWindows)) {
- if ((topLevelWindow->type() & Qt::Popup) == Qt::Popup && topLevelWindow->isVisible())
+ for (QWindow *topLevelWindow : topLevelWindows) {
+ if ((topLevelWindow->type() & Qt::Popup) == Qt::Popup && topLevelWindow->isVisible()) {
topLevelWindow->hide();
+
+ if ((topLevelWindow->type() & Qt::Tool) == Qt::Tool)
+ hiddenWindows << topLevelWindow;
+ }
}
}
+- (void)applicationDidUnhide:(NSNotification *)notification
+{
+ if (reflectionDelegate
+ && [reflectionDelegate respondsToSelector:@selector(applicationDidUnhide:)])
+ [reflectionDelegate applicationDidUnhide:notification];
+
+ for (QWindow *window : qAsConst(hiddenWindows))
+ window->show();
+
+ hiddenWindows.clear();
+}
+
- (void)applicationDidBecomeActive:(NSNotification *)notification
{
if (reflectionDelegate
@@ -440,3 +456,48 @@ QT_USE_NAMESPACE
}
@end
+
+@implementation QCocoaApplicationDelegate (Menus)
+
+- (BOOL)validateMenuItem:(NSMenuItem*)item
+{
+ auto *nativeItem = qt_objc_cast<QCocoaNSMenuItem *>(item);
+ if (!nativeItem)
+ return item.enabled; // FIXME Test with with Qt as plugin or embedded QWindow.
+
+ auto *platformItem = nativeItem.platformMenuItem;
+ if (!platformItem) // Try a bit harder with orphan menu itens
+ return item.hasSubmenu || (item.enabled && (item.action != @selector(qt_itemFired:)));
+
+ // Menu-holding items are always enabled, as it's conventional in Cocoa
+ if (platformItem->menu())
+ return YES;
+
+ return platformItem->isEnabled();
+}
+
+@end
+
+@implementation QCocoaApplicationDelegate (MenuAPI)
+
+- (void)qt_itemFired:(QCocoaNSMenuItem *)item
+{
+ if (item.hasSubmenu)
+ return;
+
+ auto *nativeItem = qt_objc_cast<QCocoaNSMenuItem *>(item);
+ Q_ASSERT_X(nativeItem, qPrintable(__FUNCTION__), "Triggered menu item is not a QCocoaNSMenuItem.");
+ auto *platformItem = nativeItem.platformMenuItem;
+ // Menu-holding items also get a target to play nicely
+ // with NSMenuValidation but should not trigger.
+ if (!platformItem || platformItem->menu())
+ return;
+
+ QScopedScopeLevelCounter scopeLevelCounter(QGuiApplicationPrivate::instance()->threadData);
+ QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers:[NSEvent modifierFlags]];
+
+ static QMetaMethod activatedSignal = QMetaMethod::fromSignal(&QCocoaMenuItem::activated);
+ activatedSignal.invoke(platformItem, Qt::QueuedConnection);
+}
+
+@end
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index 1343fbc45a..81a0a7d040 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -44,8 +44,6 @@
QT_BEGIN_NAMESPACE
-Q_LOGGING_CATEGORY(lcCocoaBackingStore, "qt.qpa.cocoa.backingstore");
-
QCocoaBackingStore::QCocoaBackingStore(QWindow *window)
: QRasterBackingStore(window)
{
@@ -69,11 +67,6 @@ QImage::Format QCocoaBackingStore::format() const
return QRasterBackingStore::format();
}
-#if !QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12)
-static const NSCompositingOperation NSCompositingOperationCopy = NSCompositeCopy;
-static const NSCompositingOperation NSCompositingOperationSourceOver = NSCompositeSourceOver;
-#endif
-
/*!
Flushes the given \a region from the specified \a window onto the
screen.
@@ -101,13 +94,13 @@ void QCocoaBackingStore::flush(QWindow *window, const QRegion &region, const QPo
QNSView *topLevelView = qnsview_cast(static_cast<QCocoaWindow *>(topLevelWindow->handle())->view());
QNSView *view = qnsview_cast(static_cast<QCocoaWindow *>(window->handle())->view());
- if (lcCocoaBackingStore().isDebugEnabled()) {
+ if (lcQpaBackingStore().isDebugEnabled()) {
QString targetViewDescription;
if (view != topLevelView) {
QDebug targetDebug(&targetViewDescription);
targetDebug << "onto" << topLevelView << "at" << offset;
}
- qCDebug(lcCocoaBackingStore) << "Flushing" << region << "of" << view << qPrintable(targetViewDescription);
+ qCDebug(lcQpaBackingStore) << "Flushing" << region << "of" << view << qPrintable(targetViewDescription);
}
// Prevent potentially costly color conversion by assigning the display color space
@@ -127,118 +120,120 @@ void QCocoaBackingStore::flush(QWindow *window, const QRegion &region, const QPo
// FIXME: Figure out if there's a way to do partial updates
view.layer.contents = (__bridge id)static_cast<CGImageRef>(cgImage);
if (view != topLevelView) {
+ const CGSize topLevelSize = topLevelView.bounds.size;
view.layer.contentsRect = CGRectApplyAffineTransform(
[view convertRect:view.bounds toView:topLevelView],
// The contentsRect is in unit coordinate system
- CGAffineTransformMakeScale(1.0 / m_image.width(), 1.0 / m_image.height()));
+ CGAffineTransformMakeScale(1.0 / topLevelSize.width, 1.0 / topLevelSize.height));
+ }
+ } else {
+ // Normally a NSView is drawn via drawRect, as part of the display cycle in the
+ // main runloop, via setNeedsDisplay and friends. AppKit will lock focus on each
+ // individual view, starting with the top level and then traversing any subviews,
+ // calling drawRect for each of them. This pull model results in expose events
+ // sent to Qt, which result in drawing to the backingstore and flushing it.
+ // Qt may also decide to paint and flush the backingstore via e.g. timers,
+ // or other events such as mouse events, in which case we're in a push model.
+ // If there is no focused view, it means we're in the latter case, and need
+ // to manually flush the NSWindow after drawing to its graphic context.
+ const bool drawingOutsideOfDisplayCycle = ![NSView focusView];
+
+ // We also need to ensure the flushed view has focus, so that the graphics
+ // context is set up correctly (coordinate system, clipping, etc). Outside
+ // of the normal display cycle there is no focused view, as explained above,
+ // so we have to handle it manually. There's also a corner case inside the
+ // normal display cycle due to way QWidgetBackingStore composits native child
+ // widgets, where we'll get a flush of a native child during the drawRect of
+ // its parent/ancestor, and the parent/ancestor being the one locked by AppKit.
+ // In this case we also need to lock and unlock focus manually.
+ const bool shouldHandleViewLockManually = [NSView focusView] != view;
+ if (shouldHandleViewLockManually && ![view lockFocusIfCanDraw]) {
+ qWarning() << "failed to lock focus of" << view;
+ return;
}
- return;
- }
-
- // Normally a NSView is drawn via drawRect, as part of the display cycle in the
- // main runloop, via setNeedsDisplay and friends. AppKit will lock focus on each
- // individual view, starting with the top level and then traversing any subviews,
- // calling drawRect for each of them. This pull model results in expose events
- // sent to Qt, which result in drawing to the backingstore and flushing it.
- // Qt may also decide to paint and flush the backingstore via e.g. timers,
- // or other events such as mouse events, in which case we're in a push model.
- // If there is no focused view, it means we're in the latter case, and need
- // to manually flush the NSWindow after drawing to its graphic context.
- const bool drawingOutsideOfDisplayCycle = ![NSView focusView];
-
- // We also need to ensure the flushed view has focus, so that the graphics
- // context is set up correctly (coordinate system, clipping, etc). Outside
- // of the normal display cycle there is no focused view, as explained above,
- // so we have to handle it manually. There's also a corner case inside the
- // normal display cycle due to way QWidgetBackingStore composits native child
- // widgets, where we'll get a flush of a native child during the drawRect of
- // its parent/ancestor, and the parent/ancestor being the one locked by AppKit.
- // In this case we also need to lock and unlock focus manually.
- const bool shouldHandleViewLockManually = [NSView focusView] != view;
- if (shouldHandleViewLockManually && ![view lockFocusIfCanDraw]) {
- qWarning() << "failed to lock focus of" << view;
- return;
- }
- const qreal devicePixelRatio = m_image.devicePixelRatio();
+ const qreal devicePixelRatio = m_image.devicePixelRatio();
- // If the flushed window is a content view, and we're filling the drawn area
- // completely, or it doesn't have a window background we need to preserve,
- // we can get away with copying instead of blending the backing store.
- QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());
- const NSCompositingOperation compositingOperation = cocoaWindow->isContentView()
- && (cocoaWindow->isOpaque() || view.window.backgroundColor == NSColor.clearColor)
- ? NSCompositingOperationCopy : NSCompositingOperationSourceOver;
+ // If the flushed window is a content view, and we're filling the drawn area
+ // completely, or it doesn't have a window background we need to preserve,
+ // we can get away with copying instead of blending the backing store.
+ QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());
+ const NSCompositingOperation compositingOperation = cocoaWindow->isContentView()
+ && (cocoaWindow->isOpaque() || view.window.backgroundColor == NSColor.clearColor)
+ ? NSCompositingOperationCopy : NSCompositingOperationSourceOver;
#ifdef QT_DEBUG
- static bool debugBackingStoreFlush = [[NSUserDefaults standardUserDefaults]
- boolForKey:@"QtCocoaDebugBackingStoreFlush"];
+ static bool debugBackingStoreFlush = [[NSUserDefaults standardUserDefaults]
+ boolForKey:@"QtCocoaDebugBackingStoreFlush"];
#endif
- // -------------------------------------------------------------------------
+ // -------------------------------------------------------------------------
- // The current contexts is typically a NSWindowGraphicsContext, but can be
- // NSBitmapGraphicsContext e.g. when debugging the view hierarchy in Xcode.
- // If we need to distinguish things here in the future, we can use e.g.
- // [NSGraphicsContext drawingToScreen], or the attributes of the context.
- NSGraphicsContext *graphicsContext = [NSGraphicsContext currentContext];
- Q_ASSERT_X(graphicsContext, "QCocoaBackingStore",
- "Focusing the view should give us a current graphics context");
+ // The current contexts is typically a NSWindowGraphicsContext, but can be
+ // NSBitmapGraphicsContext e.g. when debugging the view hierarchy in Xcode.
+ // If we need to distinguish things here in the future, we can use e.g.
+ // [NSGraphicsContext drawingToScreen], or the attributes of the context.
+ NSGraphicsContext *graphicsContext = [NSGraphicsContext currentContext];
+ Q_ASSERT_X(graphicsContext, "QCocoaBackingStore",
+ "Focusing the view should give us a current graphics context");
- // Create temporary image to use for blitting, without copying image data
- NSImage *backingStoreImage = [[[NSImage alloc] initWithCGImage:cgImage size:NSZeroSize] autorelease];
+ // Create temporary image to use for blitting, without copying image data
+ NSImage *backingStoreImage = [[[NSImage alloc] initWithCGImage:cgImage size:NSZeroSize] autorelease];
- QRegion clippedRegion = region;
- for (QWindow *w = window; w; w = w->parent()) {
- if (!w->mask().isEmpty()) {
- clippedRegion &= w == window ? w->mask()
- : w->mask().translated(window->mapFromGlobal(w->mapToGlobal(QPoint(0, 0))));
+ QRegion clippedRegion = region;
+ for (QWindow *w = window; w; w = w->parent()) {
+ if (!w->mask().isEmpty()) {
+ clippedRegion &= w == window ? w->mask()
+ : w->mask().translated(window->mapFromGlobal(w->mapToGlobal(QPoint(0, 0))));
+ }
}
- }
- for (const QRect &viewLocalRect : clippedRegion) {
- QPoint backingStoreOffset = viewLocalRect.topLeft() + offset;
- QRect backingStoreRect(backingStoreOffset * devicePixelRatio, viewLocalRect.size() * devicePixelRatio);
- if (graphicsContext.flipped) // Flip backingStoreRect to match graphics context
- backingStoreRect.moveTop(m_image.height() - (backingStoreRect.y() + backingStoreRect.height()));
+ for (const QRect &viewLocalRect : clippedRegion) {
+ QPoint backingStoreOffset = viewLocalRect.topLeft() + offset;
+ QRect backingStoreRect(backingStoreOffset * devicePixelRatio, viewLocalRect.size() * devicePixelRatio);
+ if (graphicsContext.flipped) // Flip backingStoreRect to match graphics context
+ backingStoreRect.moveTop(m_image.height() - (backingStoreRect.y() + backingStoreRect.height()));
- CGRect viewRect = viewLocalRect.toCGRect();
+ CGRect viewRect = viewLocalRect.toCGRect();
- if (windowHasUnifiedToolbar())
- NSDrawWindowBackground(viewRect);
+ if (windowHasUnifiedToolbar())
+ NSDrawWindowBackground(viewRect);
- [backingStoreImage drawInRect:viewRect fromRect:backingStoreRect.toCGRect()
- operation:compositingOperation fraction:1.0 respectFlipped:YES hints:nil];
+ [backingStoreImage drawInRect:viewRect fromRect:backingStoreRect.toCGRect()
+ operation:compositingOperation fraction:1.0 respectFlipped:YES hints:nil];
#ifdef QT_DEBUG
- if (Q_UNLIKELY(debugBackingStoreFlush)) {
- [[NSColor colorWithCalibratedRed:drand48() green:drand48() blue:drand48() alpha:0.3] set];
- [NSBezierPath fillRect:viewRect];
-
- if (drawingOutsideOfDisplayCycle) {
- [[[NSColor magentaColor] colorWithAlphaComponent:0.5] set];
- [NSBezierPath strokeLineFromPoint:viewLocalRect.topLeft().toCGPoint()
- toPoint:viewLocalRect.bottomRight().toCGPoint()];
+ if (Q_UNLIKELY(debugBackingStoreFlush)) {
+ [[NSColor colorWithCalibratedRed:drand48() green:drand48() blue:drand48() alpha:0.3] set];
+ [NSBezierPath fillRect:viewRect];
+
+ if (drawingOutsideOfDisplayCycle) {
+ [[[NSColor magentaColor] colorWithAlphaComponent:0.5] set];
+ [NSBezierPath strokeLineFromPoint:viewLocalRect.topLeft().toCGPoint()
+ toPoint:viewLocalRect.bottomRight().toCGPoint()];
+ }
}
- }
#endif
+ }
+
+ // -------------------------------------------------------------------------
+
+ if (shouldHandleViewLockManually)
+ [view unlockFocus];
+
+ if (drawingOutsideOfDisplayCycle) {
+ redrawRoundedBottomCorners([view convertRect:region.boundingRect().toCGRect() toView:nil]);
+ [view.window flushWindow];
+ }
}
+ // Done flushing to either CALayer or NSWindow backingstore
+
QCocoaWindow *topLevelCocoaWindow = static_cast<QCocoaWindow *>(topLevelWindow->handle());
if (Q_UNLIKELY(topLevelCocoaWindow->m_needsInvalidateShadow)) {
[topLevelView.window invalidateShadow];
topLevelCocoaWindow->m_needsInvalidateShadow = false;
}
-
- // -------------------------------------------------------------------------
-
- if (shouldHandleViewLockManually)
- [view unlockFocus];
-
- if (drawingOutsideOfDisplayCycle) {
- redrawRoundedBottomCorners([view convertRect:region.boundingRect().toCGRect() toView:nil]);
- [view.window flushWindow];
- }
}
/*
diff --git a/src/plugins/platforms/cocoa/qcocoaclipboard.mm b/src/plugins/platforms/cocoa/qcocoaclipboard.mm
index b4745900dc..a35c153084 100644
--- a/src/plugins/platforms/cocoa/qcocoaclipboard.mm
+++ b/src/plugins/platforms/cocoa/qcocoaclipboard.mm
@@ -56,13 +56,13 @@ QMimeData *QCocoaClipboard::mimeData(QClipboard::Mode mode)
pasteBoard->sync();
return pasteBoard->mimeData();
}
- return 0;
+ return nullptr;
}
void QCocoaClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
{
if (QMacPasteboard *pasteBoard = pasteboardForMode(mode)) {
- if (data == 0) {
+ if (!data) {
pasteBoard->clear();
}
@@ -90,7 +90,7 @@ QMacPasteboard *QCocoaClipboard::pasteboardForMode(QClipboard::Mode mode) const
else if (mode == QClipboard::FindBuffer)
return m_find.data();
else
- return 0;
+ return nullptr;
}
void QCocoaClipboard::handleApplicationStateChanged(Qt::ApplicationState state)
diff --git a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm
index aa6124507d..d7850b1481 100644
--- a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm
@@ -50,7 +50,14 @@
QT_USE_NAMESPACE
@interface QT_MANGLE_NAMESPACE(QNSColorPanelDelegate) : NSObject<NSWindowDelegate, QNSPanelDelegate>
-{
+- (void)restoreOriginalContentView;
+- (void)updateQtColor;
+- (void)finishOffWithCode:(NSInteger)code;
+@end
+
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate);
+
+@implementation QNSColorPanelDelegate {
@public
NSColorPanel *mColorPanel;
QCocoaColorDialogHelper *mHelper;
@@ -61,22 +68,14 @@ QT_USE_NAMESPACE
BOOL mDialogIsExecuting;
BOOL mResultSet;
BOOL mClosingDueToKnownButton;
-};
-- (void)restoreOriginalContentView;
-- (void)updateQtColor;
-- (void)finishOffWithCode:(NSInteger)code;
-@end
-
-QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate);
-
-@implementation QNSColorPanelDelegate
+}
-- (id)init
+- (instancetype)init
{
self = [super init];
mColorPanel = [NSColorPanel sharedColorPanel];
- mHelper = 0;
- mStolenContentView = 0;
+ mHelper = nullptr;
+ mStolenContentView = nil;
mPanelButtons = nil;
mResultCode = NSModalResponseCancel;
mDialogIsExecuting = false;
@@ -116,9 +115,9 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate);
[self restoreOriginalContentView];
} else if (!mStolenContentView) {
// steal the color panel's contents view
- mStolenContentView = [mColorPanel contentView];
+ mStolenContentView = mColorPanel.contentView;
[mStolenContentView retain];
- [mColorPanel setContentView:0];
+ mColorPanel.contentView = nil;
// create a new content view and add the stolen one as a subview
mPanelButtons = [[QNSPanelContentsWrapper alloc] initWithPanelDelegate:self];
@@ -310,7 +309,7 @@ public:
void cleanup(QCocoaColorDialogHelper *helper)
{
if (mDelegate->mHelper == helper)
- mDelegate->mHelper = 0;
+ mDelegate->mHelper = nullptr;
}
bool exec()
diff --git a/src/plugins/platforms/cocoa/qcocoacursor.mm b/src/plugins/platforms/cocoa/qcocoacursor.mm
index 8c98dc69f7..87a57c78c8 100644
--- a/src/plugins/platforms/cocoa/qcocoacursor.mm
+++ b/src/plugins/platforms/cocoa/qcocoacursor.mm
@@ -80,15 +80,15 @@ void QCocoaCursor::setPos(const QPoint &position)
pos.x = position.x();
pos.y = position.y();
- CGEventRef e = CGEventCreateMouseEvent(0, kCGEventMouseMoved, pos, kCGMouseButtonLeft);
+ CGEventRef e = CGEventCreateMouseEvent(nullptr, kCGEventMouseMoved, pos, kCGMouseButtonLeft);
CGEventPost(kCGHIDEventTap, e);
CFRelease(e);
}
NSCursor *QCocoaCursor::convertCursor(QCursor *cursor)
{
- if (cursor == nullptr)
- return 0;
+ if (!cursor)
+ return nil;
const Qt::CursorShape newShape = cursor->shape();
NSCursor *cocoaCursor;
@@ -138,11 +138,11 @@ NSCursor *QCocoaCursor::convertCursor(QCursor *cursor)
cocoaCursor = m_cursors.value(newShape);
if (cocoaCursor && cursor->shape() == Qt::BitmapCursor) {
[cocoaCursor release];
- cocoaCursor = 0;
+ cocoaCursor = nil;
}
- if (cocoaCursor == 0) {
+ if (!cocoaCursor) {
cocoaCursor = createCursorData(cursor);
- if (cocoaCursor == 0)
+ if (!cocoaCursor)
return [NSCursor arrowCursor];
m_cursors.insert(newShape, cocoaCursor);
@@ -211,8 +211,8 @@ NSCursor *QCocoaCursor::createCursorData(QCursor *cursor)
0x07, 0xf0, 0x0f, 0xf8, 0x0f, 0xf8, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0,
0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0 };
#endif
- const uchar *cursorData = 0;
- const uchar *cursorMaskData = 0;
+ const uchar *cursorData = nullptr;
+ const uchar *cursorMaskData = nullptr;
QPoint hotspot = cursor->hotSpot();
switch (cursor->shape()) {
@@ -269,7 +269,7 @@ NSCursor *QCocoaCursor::createCursorData(QCursor *cursor)
#endif
default:
qWarning("Qt: QCursor::update: Invalid cursor shape %d", cursor->shape());
- return 0;
+ return nil;
}
// Create an NSCursor from image data if this a self-provided cursor.
@@ -279,7 +279,7 @@ NSCursor *QCocoaCursor::createCursorData(QCursor *cursor)
return (createCursorFromBitmap(&bitmap, &mask, hotspot));
}
- return 0; // should not happen, all cases covered above
+ return nil; // should not happen, all cases covered above
}
NSCursor *QCocoaCursor::createCursorFromBitmap(const QBitmap *bitmap, const QBitmap *mask, const QPoint hotspot)
diff --git a/src/plugins/platforms/cocoa/qcocoadrag.mm b/src/plugins/platforms/cocoa/qcocoadrag.mm
index e1f36b47a1..09433194a6 100644
--- a/src/plugins/platforms/cocoa/qcocoadrag.mm
+++ b/src/plugins/platforms/cocoa/qcocoadrag.mm
@@ -50,10 +50,10 @@ QT_BEGIN_NAMESPACE
static const int dragImageMaxChars = 26;
QCocoaDrag::QCocoaDrag() :
- m_drag(0)
+ m_drag(nullptr)
{
- m_lastEvent = 0;
- m_lastView = 0;
+ m_lastEvent = nil;
+ m_lastView = nil;
}
QCocoaDrag::~QCocoaDrag()
@@ -73,7 +73,7 @@ QMimeData *QCocoaDrag::dragMimeData()
if (m_drag)
return m_drag->mimeData();
- return 0;
+ return nullptr;
}
Qt::DropAction QCocoaDrag::defaultAction(Qt::DropActions possibleActions,
@@ -140,7 +140,7 @@ Qt::DropAction QCocoaDrag::drag(QDrag *o)
NSPoint event_location = [m_lastEvent locationInWindow];
NSWindow *theWindow = [m_lastEvent window];
- Q_ASSERT(theWindow != nil);
+ Q_ASSERT(theWindow);
event_location.x -= hotSpot.x();
CGFloat flippedY = pmDeviceIndependentSize.height() - hotSpot.y();
event_location.y -= flippedY;
@@ -157,7 +157,7 @@ Qt::DropAction QCocoaDrag::drag(QDrag *o)
[nsimage release];
- m_drag = 0;
+ m_drag = nullptr;
return m_executed_drop_action;
}
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
index 2ffc1395ba..ebf33cf4e2 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
@@ -110,8 +110,8 @@ class QCocoaEventDispatcher : public QAbstractEventDispatcher
Q_DECLARE_PRIVATE(QCocoaEventDispatcher)
public:
- QCocoaEventDispatcher(QAbstractEventDispatcherPrivate &priv, QObject *parent = 0);
- explicit QCocoaEventDispatcher(QObject *parent = 0);
+ QCocoaEventDispatcher(QAbstractEventDispatcherPrivate &priv, QObject *parent = nullptr);
+ explicit QCocoaEventDispatcher(QObject *parent = nullptr);
~QCocoaEventDispatcher();
bool processEvents(QEventLoop::ProcessEventsFlags flags);
@@ -153,6 +153,7 @@ public:
void maybeStopCFRunLoopTimer();
static void runLoopTimerCallback(CFRunLoopTimerRef, void *info);
static void activateTimersSourceCallback(void *info);
+ bool processTimers();
// Set 'blockSendPostedEvents' to true if you _really_ need
// to make sure that qt events are not posted while calling
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
index bf9ba4eccf..b0f2b6d940 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
@@ -120,20 +120,26 @@ void QCocoaEventDispatcherPrivate::runLoopTimerCallback(CFRunLoopTimerRef, void
void QCocoaEventDispatcherPrivate::activateTimersSourceCallback(void *info)
{
QCocoaEventDispatcherPrivate *d = static_cast<QCocoaEventDispatcherPrivate *>(info);
- (void) d->timerInfoList.activateTimers();
- d->maybeStartCFRunLoopTimer();
+ d->processTimers();
d->maybeCancelWaitForMoreEvents();
}
+bool QCocoaEventDispatcherPrivate::processTimers()
+{
+ int activated = timerInfoList.activateTimers();
+ maybeStartCFRunLoopTimer();
+ return activated > 0;
+}
+
void QCocoaEventDispatcherPrivate::maybeStartCFRunLoopTimer()
{
if (timerInfoList.isEmpty()) {
// no active timers, so the CFRunLoopTimerRef should not be active either
- Q_ASSERT(runLoopTimerRef == 0);
+ Q_ASSERT(!runLoopTimerRef);
return;
}
- if (runLoopTimerRef == 0) {
+ if (!runLoopTimerRef) {
// start the CFRunLoopTimer
CFAbsoluteTime ttf = CFAbsoluteTimeGetCurrent();
CFTimeInterval interval;
@@ -150,11 +156,11 @@ void QCocoaEventDispatcherPrivate::maybeStartCFRunLoopTimer()
}
ttf += interval;
- CFRunLoopTimerContext info = { 0, this, 0, 0, 0 };
+ CFRunLoopTimerContext info = { 0, this, nullptr, nullptr, nullptr };
// create the timer with a large interval, as recommended by the CFRunLoopTimerSetNextFireDate()
// documentation, since we will adjust the timer's time-to-fire as needed to keep Qt timers working
- runLoopTimerRef = CFRunLoopTimerCreate(0, ttf, oneyear, 0, 0, QCocoaEventDispatcherPrivate::runLoopTimerCallback, &info);
- Q_ASSERT(runLoopTimerRef != 0);
+ runLoopTimerRef = CFRunLoopTimerCreate(nullptr, ttf, oneyear, 0, 0, QCocoaEventDispatcherPrivate::runLoopTimerCallback, &info);
+ Q_ASSERT(runLoopTimerRef);
CFRunLoopAddTimer(mainRunLoop(), runLoopTimerRef, kCFRunLoopCommonModes);
} else {
@@ -180,12 +186,12 @@ void QCocoaEventDispatcherPrivate::maybeStartCFRunLoopTimer()
void QCocoaEventDispatcherPrivate::maybeStopCFRunLoopTimer()
{
- if (runLoopTimerRef == 0)
+ if (!runLoopTimerRef)
return;
CFRunLoopTimerInvalidate(runLoopTimerRef);
CFRelease(runLoopTimerRef);
- runLoopTimerRef = 0;
+ runLoopTimerRef = nullptr;
}
void QCocoaEventDispatcher::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *obj)
@@ -293,25 +299,25 @@ static bool IsMouseOrKeyEvent( NSEvent* event )
switch( [event type] )
{
- case NSLeftMouseDown:
- case NSLeftMouseUp:
- case NSRightMouseDown:
- case NSRightMouseUp:
- case NSMouseMoved: // ??
- case NSLeftMouseDragged:
- case NSRightMouseDragged:
- case NSMouseEntered:
- case NSMouseExited:
- case NSKeyDown:
- case NSKeyUp:
- case NSFlagsChanged: // key modifiers changed?
- case NSCursorUpdate: // ??
- case NSScrollWheel:
- case NSTabletPoint:
- case NSTabletProximity:
- case NSOtherMouseDown:
- case NSOtherMouseUp:
- case NSOtherMouseDragged:
+ case NSEventTypeLeftMouseDown:
+ case NSEventTypeLeftMouseUp:
+ case NSEventTypeRightMouseDown:
+ case NSEventTypeRightMouseUp:
+ case NSEventTypeMouseMoved: // ??
+ case NSEventTypeLeftMouseDragged:
+ case NSEventTypeRightMouseDragged:
+ case NSEventTypeMouseEntered:
+ case NSEventTypeMouseExited:
+ case NSEventTypeKeyDown:
+ case NSEventTypeKeyUp:
+ case NSEventTypeFlagsChanged: // key modifiers changed?
+ case NSEventTypeCursorUpdate: // ??
+ case NSEventTypeScrollWheel:
+ case NSEventTypeTabletPoint:
+ case NSEventTypeTabletProximity:
+ case NSEventTypeOtherMouseDown:
+ case NSEventTypeOtherMouseUp:
+ case NSEventTypeOtherMouseDragged:
#ifndef QT_NO_GESTURES
case NSEventTypeGesture: // touch events
case NSEventTypeMagnify:
@@ -335,7 +341,7 @@ static inline void qt_mac_waitForMoreEvents(NSString *runLoopMode = NSDefaultRun
// at least one event occur. Setting 'dequeuing' to 'no' in the following call
// causes it to hang under certain circumstances (QTBUG-28283), so we tell it
// to dequeue instead, just to repost the event again:
- NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
+ NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
untilDate:[NSDate distantFuture]
inMode:runLoopMode
dequeue:YES];
@@ -368,13 +374,13 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
break;
QMacAutoReleasePool pool;
- NSEvent* event = 0;
+ NSEvent* event = nil;
// First, send all previously excluded input events, if any:
if (!excludeUserEvents) {
while (!d->queuedUserInputEvents.isEmpty()) {
event = static_cast<NSEvent *>(d->queuedUserInputEvents.takeFirst());
- if (!filterNativeEvent("NSEvent", event, 0)) {
+ if (!filterNativeEvent("NSEvent", event, nullptr)) {
[NSApp sendEvent:event];
retVal = true;
}
@@ -432,7 +438,7 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
retVal = true;
} else {
int lastSerialCopy = d->lastSerial;
- bool hadModalSession = d->currentModalSessionCached != 0;
+ const bool hadModalSession = d->currentModalSessionCached;
// We cannot block the thread (and run in a tight loop).
// Instead we will process all current pending events and return.
d->ensureNSAppInitialized();
@@ -460,7 +466,7 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
// Dispatch all non-user events (but que non-user events up for later). In
// this case, we need more control over which events gets dispatched, and
// cannot use [NSApp runModalSession:session]:
- event = [NSApp nextEventMatchingMask:NSAnyEventMask
+ event = [NSApp nextEventMatchingMask:NSEventMaskAny
untilDate:nil
inMode:NSModalPanelRunLoopMode
dequeue: YES];
@@ -471,15 +477,15 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
d->queuedUserInputEvents.append(event);
continue;
}
- if (!filterNativeEvent("NSEvent", event, 0)) {
+ if (!filterNativeEvent("NSEvent", event, nullptr)) {
[NSApp sendEvent:event];
retVal = true;
}
}
- } while (!d->interrupt && event != nil);
+ } while (!d->interrupt && event);
} else do {
// INVARIANT: No modal window is executing.
- event = [NSApp nextEventMatchingMask:NSAnyEventMask
+ event = [NSApp nextEventMatchingMask:NSEventMaskAny
untilDate:nil
inMode:NSDefaultRunLoopMode
dequeue: YES];
@@ -492,18 +498,17 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
continue;
}
}
- if (!filterNativeEvent("NSEvent", event, 0)) {
+ if (!filterNativeEvent("NSEvent", event, nullptr)) {
[NSApp sendEvent:event];
retVal = true;
}
}
- } while (!d->interrupt && event != nil);
+ } while (!d->interrupt && event);
if ((d->processEventsFlags & QEventLoop::EventLoopExec) == 0) {
- // when called "manually", always send posted events and timers
+ // When called "manually", always process posted events and timers
d->processPostedEvents();
- retVal = d->timerInfoList.activateTimers() > 0 || retVal;
- d->maybeStartCFRunLoopTimer();
+ retVal = d->processTimers() || retVal;
}
// be sure to return true if the posted event source fired
@@ -514,7 +519,7 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
// event recursion to ensure that we spin the correct modal session.
// We do the interruptLater at the end of the function to ensure that we don't
// disturb the 'wait for more events' below (as deleteLater will post an event):
- if (hadModalSession && d->currentModalSessionCached == 0)
+ if (hadModalSession && !d->currentModalSessionCached)
interruptLater = true;
}
bool canWait = (d->threadData->canWait
@@ -611,11 +616,11 @@ void QCocoaEventDispatcherPrivate::temporarilyStopAllModalSessions()
QCocoaModalSessionInfo &info = cocoaModalSessionStack[i];
if (info.session) {
[NSApp endModalSession:info.session];
- info.session = 0;
+ info.session = nullptr;
[(NSWindow*) info.nswindow release];
}
}
- currentModalSessionCached = 0;
+ currentModalSessionCached = nullptr;
}
NSModalSession QCocoaEventDispatcherPrivate::currentModalSession()
@@ -626,7 +631,7 @@ NSModalSession QCocoaEventDispatcherPrivate::currentModalSession()
return currentModalSessionCached;
if (cocoaModalSessionStack.isEmpty())
- return 0;
+ return nullptr;
int sessionCount = cocoaModalSessionStack.size();
for (int i=0; i<sessionCount; ++i) {
@@ -637,6 +642,8 @@ NSModalSession QCocoaEventDispatcherPrivate::currentModalSession()
if (!info.session) {
QMacAutoReleasePool pool;
QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(info.window->handle());
+ if (!cocoaWindow)
+ continue;
NSWindow *nswindow = cocoaWindow->nativeWindow();
if (!nswindow)
continue;
@@ -647,6 +654,15 @@ NSModalSession QCocoaEventDispatcherPrivate::currentModalSession()
[(NSWindow*) info.nswindow retain];
QRect rect = cocoaWindow->geometry();
info.session = [NSApp beginModalSessionForWindow:nswindow];
+
+ // The call to beginModalSessionForWindow above processes events and may
+ // have deleted or destroyed the window. Check if it's still valid.
+ if (!info.window)
+ continue;
+ cocoaWindow = static_cast<QCocoaWindow *>(info.window->handle());
+ if (!cocoaWindow)
+ continue;
+
if (rect != cocoaWindow->geometry())
cocoaWindow->setGeometry(rect);
}
@@ -717,9 +733,9 @@ void QCocoaEventDispatcherPrivate::cleanupModalSessions()
currentModalSessionCached = info.session;
break;
}
- currentModalSessionCached = 0;
+ currentModalSessionCached = nullptr;
if (info.session) {
- Q_ASSERT(info.nswindow != 0);
+ Q_ASSERT(info.nswindow);
[NSApp endModalSession:info.session];
[(NSWindow *)info.nswindow release];
}
@@ -746,10 +762,10 @@ void QCocoaEventDispatcherPrivate::beginModalSession(QWindow *window)
// currentModalSession). A QCocoaModalSessionInfo is considered pending to be stopped if
// the window pointer is zero, and the session pointer is non-zero (it will be fully
// stopped in cleanupModalSessions()).
- QCocoaModalSessionInfo info = {window, 0, 0};
+ QCocoaModalSessionInfo info = {window, nullptr, nullptr};
cocoaModalSessionStack.push(info);
updateChildrenWorksWhenModal();
- currentModalSessionCached = 0;
+ currentModalSessionCached = nullptr;
}
void QCocoaEventDispatcherPrivate::endModalSession(QWindow *window)
@@ -768,12 +784,12 @@ void QCocoaEventDispatcherPrivate::endModalSession(QWindow *window)
if (!info.window)
endedSessions++;
if (info.window == window) {
- info.window = 0;
+ info.window = nullptr;
if (i + endedSessions == stackSize-1) {
// The top sessions ended. Interrupt the event dispatcher to
// start spinning the correct session immediately.
q->interrupt();
- currentModalSessionCached = 0;
+ currentModalSessionCached = nullptr;
cleanupModalSessionsNeeded = true;
}
}
@@ -782,13 +798,13 @@ void QCocoaEventDispatcherPrivate::endModalSession(QWindow *window)
QCocoaEventDispatcherPrivate::QCocoaEventDispatcherPrivate()
: processEventsFlags(0),
- runLoopTimerRef(0),
+ runLoopTimerRef(nullptr),
blockSendPostedEvents(false),
currentExecIsNSAppRun(false),
nsAppRunCalledByQt(false),
cleanupModalSessionsNeeded(false),
processEventsCalled(0),
- currentModalSessionCached(0),
+ currentModalSessionCached(nullptr),
lastSerial(-1),
interrupt(false)
{
@@ -925,8 +941,8 @@ void QCocoaEventDispatcherPrivate::cancelWaitForMoreEvents()
// In case the event dispatcher is waiting for more
// events somewhere, we post a dummy event to wake it up:
QMacAutoReleasePool pool;
- [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint
- modifierFlags:0 timestamp:0. windowNumber:0 context:0
+ [NSApp postEvent:[NSEvent otherEventWithType:NSEventTypeApplicationDefined location:NSZeroPoint
+ modifierFlags:0 timestamp:0. windowNumber:0 context:nil
subtype:QtCocoaEventSubTypeWakeup data1:0 data2:0] atStart:NO];
}
@@ -1008,7 +1024,7 @@ QCocoaEventDispatcher::~QCocoaEventDispatcher()
CFRelease(d->firstTimeObserver);
}
-QtCocoaInterruptDispatcher* QtCocoaInterruptDispatcher::instance = 0;
+QtCocoaInterruptDispatcher* QtCocoaInterruptDispatcher::instance = nullptr;
QtCocoaInterruptDispatcher::QtCocoaInterruptDispatcher() : cancelled(false)
{
@@ -1025,7 +1041,7 @@ QtCocoaInterruptDispatcher::~QtCocoaInterruptDispatcher()
{
if (cancelled)
return;
- instance = 0;
+ instance = nullptr;
QCocoaEventDispatcher::instance()->interrupt();
}
@@ -1035,7 +1051,7 @@ void QtCocoaInterruptDispatcher::cancelInterruptLater()
return;
instance->cancelled = true;
delete instance;
- instance = 0;
+ instance = nullptr;
}
void QtCocoaInterruptDispatcher::interruptLater()
diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
index 94f2125bad..e7243ec250 100644
--- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
@@ -50,7 +50,6 @@
#include <private/qguiapplication_p.h>
#include "qt_mac_p.h"
#include "qcocoahelpers.h"
-#include "qcocoamenubar.h"
#include "qcocoaeventdispatcher.h"
#include <qregexp.h>
#include <qbuffer.h>
@@ -81,23 +80,6 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions;
@interface QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate)
: NSObject<NSOpenSavePanelDelegate>
-{
- @public
- NSOpenPanel *mOpenPanel;
- NSSavePanel *mSavePanel;
- NSView *mAccessoryView;
- NSPopUpButton *mPopUpButton;
- NSTextField *mTextField;
- QCocoaFileDialogHelper *mHelper;
- NSString *mCurrentDir;
-
- int mReturnCode;
-
- SharedPointerFileDialogOptions mOptions;
- QString *mCurrentSelection;
- QStringList *mNameFilterDropDownList;
- QStringList *mSelectedNameFilter;
-}
- (NSString *)strip:(const QString &)label;
- (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url;
@@ -117,12 +99,27 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions;
QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSOpenSavePanelDelegate);
-@implementation QNSOpenSavePanelDelegate
+@implementation QNSOpenSavePanelDelegate {
+ @public
+ NSOpenPanel *mOpenPanel;
+ NSSavePanel *mSavePanel;
+ NSView *mAccessoryView;
+ NSPopUpButton *mPopUpButton;
+ NSTextField *mTextField;
+ QCocoaFileDialogHelper *mHelper;
+ NSString *mCurrentDir;
+
+ int mReturnCode;
+
+ SharedPointerFileDialogOptions mOptions;
+ QString *mCurrentSelection;
+ QStringList *mNameFilterDropDownList;
+ QStringList *mSelectedNameFilter;
+}
-- (id)initWithAcceptMode:
- (const QString &)selectFile
- options:(SharedPointerFileDialogOptions)options
- helper:(QCocoaFileDialogHelper *)helper
+- (instancetype)initWithAcceptMode:(const QString &)selectFile
+ options:(SharedPointerFileDialogOptions)options
+ helper:(QCocoaFileDialogHelper *)helper
{
self = [super init];
mOptions = options;
@@ -132,7 +129,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSOpenSavePanelDelegate);
} else {
mSavePanel = [NSSavePanel savePanel];
[mSavePanel setCanSelectHiddenExtension:YES];
- mOpenPanel = 0;
+ mOpenPanel = nil;
}
if ([mSavePanel respondsToSelector:@selector(setLevel:)])
@@ -222,7 +219,6 @@ static QString strippedText(QString s)
|| [self panel:nil shouldEnableURL:url];
[self updateProperties];
- QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder();
[mSavePanel setNameFieldStringValue:selectable ? info.fileName().toNSString() : @""];
[mOpenPanel beginWithCompletionHandler:^(NSInteger result){
@@ -252,9 +248,7 @@ static QString strippedText(QString s)
// Make sure we don't interrupt the runModal call below.
QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag();
- QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder();
mReturnCode = [mSavePanel runModal];
- QCocoaMenuBar::resetKnownMenuItemsToQt();
QAbstractEventDispatcher::instance()->interrupt();
return (mReturnCode == NSModalResponseOK);
@@ -274,7 +268,6 @@ static QString strippedText(QString s)
|| [self panel:nil shouldEnableURL:url];
[self updateProperties];
- QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder();
[mSavePanel setDirectoryURL: [NSURL fileURLWithPath:mCurrentDir]];
[mSavePanel setNameFieldStringValue:selectable ? info.fileName().toNSString() : @""];
@@ -292,7 +285,7 @@ static QString strippedText(QString s)
BOOL hidden = NO;
if (url) {
CFBooleanRef isHiddenProperty;
- if (CFURLCopyResourcePropertyForKey((__bridge CFURLRef)url, kCFURLIsHiddenKey, &isHiddenProperty, NULL)) {
+ if (CFURLCopyResourcePropertyForKey((__bridge CFURLRef)url, kCFURLIsHiddenKey, &isHiddenProperty, nullptr)) {
hidden = CFBooleanGetValue(isHiddenProperty);
CFRelease(isHiddenProperty);
}
@@ -406,9 +399,9 @@ static QString strippedText(QString s)
{
if (mOpenPanel) {
QList<QUrl> result;
- NSArray* array = [mOpenPanel URLs];
- for (NSUInteger i=0; i<[array count]; ++i) {
- QString path = QString::fromNSString([[array objectAtIndex:i] path]).normalized(QString::NormalizationForm_C);
+ NSArray<NSURL *> *array = [mOpenPanel URLs];
+ for (NSURL *url in array) {
+ QString path = QString::fromNSString(url.path).normalized(QString::NormalizationForm_C);
result << QUrl::fromLocalFile(path);
}
return result;
@@ -522,8 +515,8 @@ static QString strippedText(QString s)
NSRect textRect = { { 0.0, 3.0 }, { 100.0, 25.0 } };
mTextField = [[NSTextField alloc] initWithFrame:textRect];
[[mTextField cell] setFont:[NSFont systemFontOfSize:
- [NSFont systemFontSizeForControlSize:NSRegularControlSize]]];
- [mTextField setAlignment:NSRightTextAlignment];
+ [NSFont systemFontSizeForControlSize:NSControlSizeRegular]]];
+ [mTextField setAlignment:NSTextAlignmentRight];
[mTextField setEditable:false];
[mTextField setSelectable:false];
[mTextField setBordered:false];
@@ -576,7 +569,7 @@ static QString strippedText(QString s)
QT_BEGIN_NAMESPACE
QCocoaFileDialogHelper::QCocoaFileDialogHelper()
- :mDelegate(0)
+ : mDelegate(nil)
{
}
@@ -586,7 +579,7 @@ QCocoaFileDialogHelper::~QCocoaFileDialogHelper()
return;
QMacAutoReleasePool pool;
[mDelegate release];
- mDelegate = 0;
+ mDelegate = nil;
}
void QCocoaFileDialogHelper::QNSOpenSavePanelDelegate_selectionChanged(const QString &newPath)
@@ -596,7 +589,6 @@ void QCocoaFileDialogHelper::QNSOpenSavePanelDelegate_selectionChanged(const QSt
void QCocoaFileDialogHelper::QNSOpenSavePanelDelegate_panelClosed(bool accepted)
{
- QCocoaMenuBar::resetKnownMenuItemsToQt();
if (accepted) {
emit accept();
} else {
diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
index 815882ab06..8c0af97a68 100644
--- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
@@ -74,7 +74,15 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
}
@interface QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) : NSObject<NSWindowDelegate, QNSPanelDelegate>
-{
+- (void)restoreOriginalContentView;
+- (void)updateQtFont;
+- (void)changeFont:(id)sender;
+- (void)finishOffWithCode:(NSInteger)code;
+@end
+
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate);
+
+@implementation QNSFontPanelDelegate {
@public
NSFontPanel *mFontPanel;
QCocoaFontDialogHelper *mHelper;
@@ -84,34 +92,24 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
NSInteger mResultCode;
BOOL mDialogIsExecuting;
BOOL mResultSet;
-};
-- (void)restoreOriginalContentView;
-- (void)updateQtFont;
-- (void)changeFont:(id)sender;
-- (void)finishOffWithCode:(NSInteger)code;
-@end
-
-QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate);
-
-@implementation QNSFontPanelDelegate
+}
-- (id)init
+- (instancetype)init
{
- self = [super init];
- mFontPanel = [NSFontPanel sharedFontPanel];
- mHelper = 0;
- mStolenContentView = 0;
- mPanelButtons = 0;
- mResultCode = NSModalResponseCancel;
- mDialogIsExecuting = false;
- mResultSet = false;
-
- [mFontPanel setRestorable:NO];
- [mFontPanel setDelegate:self];
+ if ((self = [super init])) {
+ mFontPanel = [NSFontPanel sharedFontPanel];
+ mHelper = nullptr;
+ mStolenContentView = nil;
+ mPanelButtons = nil;
+ mResultCode = NSModalResponseCancel;
+ mDialogIsExecuting = false;
+ mResultSet = false;
- [NSFontManager sharedFontManager].target = self; // Action is changeFont:
+ [mFontPanel setRestorable:NO];
+ [mFontPanel setDelegate:self];
- [mFontPanel retain];
+ [mFontPanel retain];
+ }
return self;
}
@@ -119,7 +117,6 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate);
{
[mStolenContentView release];
[mFontPanel setDelegate:nil];
- [NSFontManager sharedFontManager].target = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
@@ -135,9 +132,9 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate);
[self restoreOriginalContentView];
} else if (!mStolenContentView) {
// steal the font panel's contents view
- mStolenContentView = [mFontPanel contentView];
+ mStolenContentView = mFontPanel.contentView;
[mStolenContentView retain];
- [mFontPanel setContentView:0];
+ mFontPanel.contentView = nil;
// create a new content view and add the stolen one as a subview
mPanelButtons = [[QNSPanelContentsWrapper alloc] initWithPanelDelegate:self];
@@ -159,7 +156,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate);
// return stolen stuff to its rightful owner
[mStolenContentView removeFromSuperview];
[mFontPanel setContentView:mStolenContentView];
- mStolenContentView = 0;
+ mStolenContentView = nil;
[mPanelButtons release];
mPanelButtons = nil;
}
@@ -191,7 +188,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate);
// Get selected font
NSFontManager *fontManager = [NSFontManager sharedFontManager];
NSFont *selectedFont = [fontManager selectedFont];
- if (selectedFont == nil) {
+ if (!selectedFont) {
selectedFont = [NSFont systemFontOfSize:[NSFont systemFontSize]];
}
NSFont *panelFont = [fontManager convertFont:selectedFont];
@@ -224,6 +221,13 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate);
return (mResultCode == NSModalResponseOK);
}
+// Future proofing in case _NSTargetForSendAction checks this
+// property before sending us the changeFont: message.
+- (BOOL)worksWhenModal
+{
+ return YES;
+}
+
- (QPlatformDialogHelper::DialogCode)dialogResultCode
{
return (mResultCode == NSModalResponseOK) ? QPlatformDialogHelper::Accepted : QPlatformDialogHelper::Rejected;
@@ -295,7 +299,7 @@ public:
void cleanup(QCocoaFontDialogHelper *helper)
{
if (mDelegate->mHelper == helper)
- mDelegate->mHelper = 0;
+ mDelegate->mHelper = nullptr;
}
bool exec()
@@ -329,7 +333,7 @@ public:
void setCurrentFont(const QFont &font)
{
NSFontManager *mgr = [NSFontManager sharedFontManager];
- const NSFont *nsFont = 0;
+ NSFont *nsFont = nil;
int weight = 5;
NSFontTraitMask mask = 0;
@@ -347,7 +351,7 @@ public:
weight:weight
size:fontInfo.pointSize()];
- [mgr setSelectedFont:const_cast<NSFont *>(nsFont) isMultiple:NO];
+ [mgr setSelectedFont:nsFont isMultiple:NO];
mDelegate->mQtFont = font;
}
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.h b/src/plugins/platforms/cocoa/qcocoaglcontext.h
index 0530aa8201..eefb1cd0fb 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.h
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.h
@@ -41,6 +41,7 @@
#define QCOCOAGLCONTEXT_H
#include <QtCore/QPointer>
+#include <QtCore/private/qcore_mac_p.h>
#include <qpa/qplatformopenglcontext.h>
#include <QtGui/QOpenGLContext>
#include <QtGui/QWindow>
@@ -52,39 +53,35 @@ QT_BEGIN_NAMESPACE
class QCocoaGLContext : public QPlatformOpenGLContext
{
public:
- QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, const QVariant &nativeHandle);
+ QCocoaGLContext(QOpenGLContext *context);
~QCocoaGLContext();
- QSurfaceFormat format() const override;
-
- void swapBuffers(QPlatformSurface *surface) override;
-
bool makeCurrent(QPlatformSurface *surface) override;
+ void swapBuffers(QPlatformSurface *surface) override;
void doneCurrent() override;
- QFunctionPointer getProcAddress(const char *procName) override;
-
void update();
- static NSOpenGLPixelFormat *createNSOpenGLPixelFormat(const QSurfaceFormat &format);
- NSOpenGLContext *nsOpenGLContext() const;
-
+ QSurfaceFormat format() const override;
bool isSharing() const override;
bool isValid() const override;
- void windowWasHidden();
+ NSOpenGLContext *nativeContext() const;
- QVariant nativeHandle() const;
+ QFunctionPointer getProcAddress(const char *procName) override;
private:
- void setActiveWindow(QWindow *window);
+ static NSOpenGLPixelFormat *pixelFormatForSurfaceFormat(const QSurfaceFormat &format);
+
+ bool setDrawable(QPlatformSurface *surface);
void updateSurfaceFormat();
- NSOpenGLContext *m_context;
- NSOpenGLContext *m_shareContext;
+ NSOpenGLContext *m_context = nil;
+ NSOpenGLContext *m_shareContext = nil;
QSurfaceFormat m_format;
- QPointer<QWindow> m_currentWindow;
- bool m_didCheckForSoftwareContext;
+ bool m_didCheckForSoftwareContext = false;
+ QVarLengthArray<QMacScopedObserver, 3> m_updateObservers;
+ QAtomicInt m_needsUpdate = false;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
index 76f8a7bb02..93d95b38ea 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
@@ -41,14 +41,11 @@
#include "qcocoawindow.h"
#include "qcocoahelpers.h"
#include <qdebug.h>
-#include <QtCore/private/qcore_mac_p.h>
#include <QtPlatformHeaders/qcocoanativecontext.h>
#include <dlfcn.h>
#import <AppKit/AppKit.h>
-QT_BEGIN_NAMESPACE
-
static inline QByteArray getGlString(GLenum param)
{
if (const GLubyte *s = glGetString(param))
@@ -56,109 +53,66 @@ static inline QByteArray getGlString(GLenum param)
return QByteArray();
}
-#if !defined(GL_CONTEXT_FLAGS)
-#define GL_CONTEXT_FLAGS 0x821E
-#endif
-
-#if !defined(GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
-#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001
-#endif
-
-#if !defined(GL_CONTEXT_PROFILE_MASK)
-#define GL_CONTEXT_PROFILE_MASK 0x9126
-#endif
-
-#if !defined(GL_CONTEXT_CORE_PROFILE_BIT)
-#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
-#endif
-
-#if !defined(GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
-#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
-#endif
-
-static void updateFormatFromContext(QSurfaceFormat *format)
+@implementation NSOpenGLPixelFormat (QtHelpers)
+- (GLint)qt_getAttribute:(NSOpenGLPixelFormatAttribute)attribute
{
- Q_ASSERT(format);
-
- // Update the version, profile, and context bit of the format
- int major = 0, minor = 0;
- QByteArray versionString(getGlString(GL_VERSION));
- if (QPlatformOpenGLContext::parseOpenGLVersion(versionString, major, minor)) {
- format->setMajorVersion(major);
- format->setMinorVersion(minor);
- }
-
- format->setProfile(QSurfaceFormat::NoProfile);
-
- Q_ASSERT(format->renderableType() == QSurfaceFormat::OpenGL);
- if (format->version() < qMakePair(3, 0)) {
- format->setOption(QSurfaceFormat::DeprecatedFunctions);
- return;
- }
-
- // Version 3.0 onwards - check if it includes deprecated functionality
- GLint value = 0;
- glGetIntegerv(GL_CONTEXT_FLAGS, &value);
- if (!(value & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT))
- format->setOption(QSurfaceFormat::DeprecatedFunctions);
-
- // Debug context option not supported on OS X
-
- if (format->version() < qMakePair(3, 2))
- return;
-
- // Version 3.2 and newer have a profile
- value = 0;
- glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &value);
+ int value = 0;
+ [self getValues:&value forAttribute:attribute forVirtualScreen:0];
+ return value;
+}
+@end
- if (value & GL_CONTEXT_CORE_PROFILE_BIT)
- format->setProfile(QSurfaceFormat::CoreProfile);
- else if (value & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
- format->setProfile(QSurfaceFormat::CompatibilityProfile);
+@implementation NSOpenGLContext (QtHelpers)
+- (GLint)qt_getParameter:(NSOpenGLContextParameter)parameter
+{
+ int value = 0;
+ [self getValues:&value forParameter:parameter];
+ return value;
}
+@end
+
+QT_BEGIN_NAMESPACE
- // NSOpenGLContext is not re-entrant (https://openradar.appspot.com/37064579)
-static QMutex s_contextMutex;
+Q_LOGGING_CATEGORY(lcQpaOpenGLContext, "qt.qpa.openglcontext", QtWarningMsg);
-QCocoaGLContext::QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share,
- const QVariant &nativeHandle)
- : m_context(nil),
- m_shareContext(nil),
- m_format(format),
- m_didCheckForSoftwareContext(false)
+QCocoaGLContext::QCocoaGLContext(QOpenGLContext *context)
+ : QPlatformOpenGLContext(), m_format(context->format())
{
+ QVariant nativeHandle = context->nativeHandle();
if (!nativeHandle.isNull()) {
if (!nativeHandle.canConvert<QCocoaNativeContext>()) {
- qWarning("QCocoaGLContext: Requires a QCocoaNativeContext");
+ qCWarning(lcQpaOpenGLContext, "QOpenGLContext native handle must be a QCocoaNativeContext");
return;
}
- QCocoaNativeContext handle = nativeHandle.value<QCocoaNativeContext>();
- NSOpenGLContext *context = handle.context();
- if (!context) {
- qWarning("QCocoaGLContext: No NSOpenGLContext given");
+ m_context = nativeHandle.value<QCocoaNativeContext>().context();
+ if (!m_context) {
+ qCWarning(lcQpaOpenGLContext, "QCocoaNativeContext's NSOpenGLContext can not be null");
return;
}
- m_context = context;
+
[m_context retain];
- m_shareContext = share ? static_cast<QCocoaGLContext *>(share)->nsOpenGLContext() : nil;
- // OpenGL surfaces can be ordered either above(default) or below the NSWindow.
- const GLint order = qt_mac_resolveOption(1, "QT_MAC_OPENGL_SURFACE_ORDER");
- [m_context setValues:&order forParameter:NSOpenGLCPSurfaceOrder];
+
+ // Note: We have no way of knowing whether the NSOpenGLContext was created with the
+ // share context as reported by the QOpenGLContext, but we just have to trust that
+ // it was. It's okey, as the only thing we're using it for is to report isShared().
+ if (QPlatformOpenGLContext *shareContext = context->shareHandle())
+ m_shareContext = static_cast<QCocoaGLContext *>(shareContext)->nativeContext();
+
updateSurfaceFormat();
return;
}
- // we only support OpenGL contexts under Cocoa
+ // ----------- Default case, we own the NSOpenGLContext -----------
+
+ // We only support OpenGL contexts under Cocoa
if (m_format.renderableType() == QSurfaceFormat::DefaultRenderableType)
m_format.setRenderableType(QSurfaceFormat::OpenGL);
if (m_format.renderableType() != QSurfaceFormat::OpenGL)
return;
- QMacAutoReleasePool pool; // For the SG Canvas render thread
-
- m_shareContext = share ? static_cast<QCocoaGLContext *>(share)->nsOpenGLContext() : nil;
+ if (QPlatformOpenGLContext *shareContext = context->shareHandle()) {
+ m_shareContext = static_cast<QCocoaGLContext *>(shareContext)->nativeContext();
- if (m_shareContext) {
// Allow sharing between 3.2 Core and 4.1 Core profile versions in
// cases where NSOpenGLContext creates a 4.1 context where a 3.2
// context was requested. Due to the semantics of QSurfaceFormat
@@ -167,318 +121,365 @@ QCocoaGLContext::QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLCo
GLint shareContextRequestedProfile;
[m_shareContext.pixelFormat getValues:&shareContextRequestedProfile
forAttribute:NSOpenGLPFAOpenGLProfile forVirtualScreen:0];
- auto shareContextActualProfile = share->format().version();
+ auto shareContextActualProfile = shareContext->format().version();
- if (shareContextRequestedProfile == NSOpenGLProfileVersion3_2Core &&
- shareContextActualProfile >= qMakePair(4, 1)) {
-
- // There is a mismatch, downgrade requested format to make the
- // NSOpenGLPFAOpenGLProfile attributes match. (NSOpenGLContext will
- // fail to create a new context if there is a mismatch).
+ if (shareContextRequestedProfile == NSOpenGLProfileVersion3_2Core
+ && shareContextActualProfile >= qMakePair(4, 1)) {
+ // There is a mismatch. Downgrade requested format to make the
+ // NSOpenGLPFAOpenGLProfile attributes match. (NSOpenGLContext
+ // will fail to create a new context if there is a mismatch).
if (m_format.version() >= qMakePair(4, 1))
m_format.setVersion(3, 2);
}
}
- // create native context for the requested pixel format and share
- NSOpenGLPixelFormat *pixelFormat = createNSOpenGLPixelFormat(m_format);
+ // ------------------------- Create NSOpenGLContext -------------------------
+
+ NSOpenGLPixelFormat *pixelFormat = [pixelFormatForSurfaceFormat(m_format) autorelease];
m_context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:m_shareContext];
- // retry without sharing on context creation failure.
if (!m_context && m_shareContext) {
- m_shareContext = nil;
+ qCWarning(lcQpaOpenGLContext, "Could not create NSOpenGLContext with shared context, "
+ "falling back to unshared context.");
m_context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];
- if (m_context)
- qWarning("QCocoaGLContext: Falling back to unshared context.");
+ m_shareContext = nil;
}
- // give up if we still did not get a native context
- [pixelFormat release];
if (!m_context) {
- qWarning("QCocoaGLContext: Failed to create context.");
+ qCWarning(lcQpaOpenGLContext, "Failed to create NSOpenGLContext");
return;
}
- const GLint interval = format.swapInterval() >= 0 ? format.swapInterval() : 1;
+ // --------------------- Set NSOpenGLContext properties ---------------------
+
+ const GLint interval = m_format.swapInterval() >= 0 ? m_format.swapInterval() : 1;
[m_context setValues:&interval forParameter:NSOpenGLCPSwapInterval];
- if (format.alphaBufferSize() > 0) {
+ if (m_format.alphaBufferSize() > 0) {
int zeroOpacity = 0;
[m_context setValues:&zeroOpacity forParameter:NSOpenGLCPSurfaceOpacity];
}
-
- // OpenGL surfaces can be ordered either above(default) or below the NSWindow.
+ // OpenGL surfaces can be ordered either above(default) or below the NSWindow
+ // FIXME: Promote to QSurfaceFormat option or property
const GLint order = qt_mac_resolveOption(1, "QT_MAC_OPENGL_SURFACE_ORDER");
[m_context setValues:&order forParameter:NSOpenGLCPSurfaceOrder];
updateSurfaceFormat();
}
-QCocoaGLContext::~QCocoaGLContext()
+NSOpenGLPixelFormat *QCocoaGLContext::pixelFormatForSurfaceFormat(const QSurfaceFormat &format)
{
- if (m_currentWindow && m_currentWindow.data()->handle())
- static_cast<QCocoaWindow *>(m_currentWindow.data()->handle())->setCurrentContext(0);
+ QVector<NSOpenGLPixelFormatAttribute> attrs;
- [m_context release];
-}
+ attrs << NSOpenGLPFAOpenGLProfile;
+ if (format.profile() == QSurfaceFormat::CoreProfile) {
+ if (format.version() >= qMakePair(4, 1))
+ attrs << NSOpenGLProfileVersion4_1Core;
+ else if (format.version() >= qMakePair(3, 2))
+ attrs << NSOpenGLProfileVersion3_2Core;
+ else
+ attrs << NSOpenGLProfileVersionLegacy;
+ } else {
+ attrs << NSOpenGLProfileVersionLegacy;
+ }
-QVariant QCocoaGLContext::nativeHandle() const
-{
- return QVariant::fromValue<QCocoaNativeContext>(QCocoaNativeContext(m_context));
-}
+ switch (format.swapBehavior()) {
+ case QSurfaceFormat::SingleBuffer:
+ break; // The NSOpenGLPixelFormat default, no attribute to set
+ case QSurfaceFormat::DefaultSwapBehavior:
+ // Technically this should be single-buffered, but we force double-buffered
+ // FIXME: Why do we force double-buffered?
+ Q_FALLTHROUGH();
+ case QSurfaceFormat::DoubleBuffer:
+ attrs.append(NSOpenGLPFADoubleBuffer);
+ break;
+ case QSurfaceFormat::TripleBuffer:
+ attrs.append(NSOpenGLPFATripleBuffer);
+ break;
+ }
-QSurfaceFormat QCocoaGLContext::format() const
-{
- return m_format;
-}
+ if (format.depthBufferSize() > 0)
+ attrs << NSOpenGLPFADepthSize << format.depthBufferSize();
+ if (format.stencilBufferSize() > 0)
+ attrs << NSOpenGLPFAStencilSize << format.stencilBufferSize();
+ if (format.alphaBufferSize() > 0)
+ attrs << NSOpenGLPFAAlphaSize << format.alphaBufferSize();
+ if (format.redBufferSize() > 0 && format.greenBufferSize() > 0 && format.blueBufferSize() > 0) {
+ const int colorSize = format.redBufferSize() + format.greenBufferSize() + format.blueBufferSize();
+ attrs << NSOpenGLPFAColorSize << colorSize << NSOpenGLPFAMinimumPolicy;
+ }
-void QCocoaGLContext::windowWasHidden()
-{
- // If the window is hidden, we need to unset the m_currentWindow
- // variable so that succeeding makeCurrent's will not abort prematurely
- // because of the optimization in setActiveWindow.
- // Doing a full doneCurrent here is not preferable, because the GL context
- // might be rendering in a different thread at this time.
- m_currentWindow.clear();
-}
+ if (format.samples() > 0) {
+ attrs << NSOpenGLPFAMultisample
+ << NSOpenGLPFASampleBuffers << NSOpenGLPixelFormatAttribute(1)
+ << NSOpenGLPFASamples << NSOpenGLPixelFormatAttribute(format.samples());
+ }
-void QCocoaGLContext::swapBuffers(QPlatformSurface *surface)
-{
- if (surface->surface()->surfaceClass() == QSurface::Offscreen)
- return; // Nothing to do
+ //Workaround for problems with Chromium and offline renderers on the lat 2013 MacPros.
+ //FIXME: Think if this could be solved via QSurfaceFormat in the future.
+ static bool offlineRenderersAllowed = qEnvironmentVariableIsEmpty("QT_MAC_PRO_WEBENGINE_WORKAROUND");
+ if (offlineRenderersAllowed) {
+ // Allow rendering on GPUs without a connected display
+ attrs << NSOpenGLPFAAllowOfflineRenderers;
+ }
- QWindow *window = static_cast<QCocoaWindow *>(surface)->window();
- setActiveWindow(window);
+ // FIXME: Pull this information out of the NSView
+ QByteArray useLayer = qgetenv("QT_MAC_WANTS_LAYER");
+ if (!useLayer.isEmpty() && useLayer.toInt() > 0) {
+ // Disable the software rendering fallback. This makes compositing
+ // OpenGL and raster NSViews using Core Animation layers possible.
+ attrs << NSOpenGLPFANoRecovery;
+ }
- QMutexLocker locker(&s_contextMutex);
- [m_context flushBuffer];
+ attrs << 0; // 0-terminate array
+ return [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs.constData()];
}
-bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface)
+/*!
+ Updates the surface format of this context based on properties of
+ the native context and GL state, so that the result of creating
+ the context is reflected back in QOpenGLContext.
+*/
+void QCocoaGLContext::updateSurfaceFormat()
{
- Q_ASSERT(surface->surface()->supportsOpenGL());
-
- QMacAutoReleasePool pool;
+ NSOpenGLContext *oldContext = [NSOpenGLContext currentContext];
[m_context makeCurrentContext];
- if (surface->surface()->surfaceClass() == QSurface::Offscreen)
- return true;
+ // --------------------- Query GL state ---------------------
- QWindow *window = static_cast<QCocoaWindow *>(surface)->window();
- setActiveWindow(window);
-
- // Disable high-resolution surfaces when using the software renderer, which has the
- // problem that the system silently falls back to a to using a low-resolution buffer
- // when a high-resolution buffer is requested. This is not detectable using the NSWindow
- // convertSizeToBacking and backingScaleFactor APIs. A typical result of this is that Qt
- // will display a quarter of the window content when running in a virtual machine.
- if (!m_didCheckForSoftwareContext) {
- m_didCheckForSoftwareContext = true;
-
- const GLubyte* renderer = glGetString(GL_RENDERER);
- if (qstrcmp((const char *)renderer, "Apple Software Renderer") == 0) {
- NSView *view = static_cast<QCocoaWindow *>(surface)->m_view;
- [view setWantsBestResolutionOpenGLSurface:NO];
- }
+ int major = 0, minor = 0;
+ QByteArray versionString(getGlString(GL_VERSION));
+ if (QPlatformOpenGLContext::parseOpenGLVersion(versionString, major, minor)) {
+ m_format.setMajorVersion(major);
+ m_format.setMinorVersion(minor);
}
- update();
- return true;
-}
+ m_format.setProfile(QSurfaceFormat::NoProfile);
+ if (m_format.version() >= qMakePair(3, 2)) {
+ GLint value = 0;
+ glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &value);
+ if (value & GL_CONTEXT_CORE_PROFILE_BIT)
+ m_format.setProfile(QSurfaceFormat::CoreProfile);
+ else if (value & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
+ m_format.setProfile(QSurfaceFormat::CompatibilityProfile);
+ }
-void QCocoaGLContext::setActiveWindow(QWindow *window)
-{
- if (window == m_currentWindow.data())
- return;
+ m_format.setOption(QSurfaceFormat::DeprecatedFunctions, [&]() {
+ if (m_format.version() < qMakePair(3, 0)) {
+ return true;
+ } else {
+ GLint value = 0;
+ glGetIntegerv(GL_CONTEXT_FLAGS, &value);
+ return !(value & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT);
+ }
+ }());
- if (m_currentWindow && m_currentWindow.data()->handle())
- static_cast<QCocoaWindow *>(m_currentWindow.data()->handle())->setCurrentContext(0);
+ // Debug contexts not supported on macOS
+ m_format.setOption(QSurfaceFormat::DebugContext, false);
- Q_ASSERT(window->handle());
+ // Nor are stereo buffers (deprecated in macOS 10.12)
+ m_format.setOption(QSurfaceFormat::StereoBuffers, false);
- m_currentWindow = window;
+ // ------------------ Query the pixel format ------------------
- QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());
- cocoaWindow->setCurrentContext(this);
+ NSOpenGLPixelFormat *pixelFormat = m_context.pixelFormat;
- Q_ASSERT(!cocoaWindow->isForeignWindow());
- [qnsview_cast(cocoaWindow->view()) setQCocoaGLContext:this];
-}
+ int colorSize = [pixelFormat qt_getAttribute:NSOpenGLPFAColorSize];
+ colorSize /= 4; // The attribute includes the alpha component
+ m_format.setRedBufferSize(colorSize);
+ m_format.setGreenBufferSize(colorSize);
+ m_format.setBlueBufferSize(colorSize);
-void QCocoaGLContext::updateSurfaceFormat()
-{
- // At present it is impossible to turn an option off on a QSurfaceFormat (see
- // https://codereview.qt-project.org/#change,70599). So we have to populate
- // the actual surface format from scratch
- QSurfaceFormat requestedFormat = m_format;
- m_format = QSurfaceFormat();
- m_format.setRenderableType(QSurfaceFormat::OpenGL);
-
- // CoreGL doesn't require a drawable to make the context current
- CGLContextObj oldContext = CGLGetCurrentContext();
- CGLContextObj ctx = static_cast<CGLContextObj>([m_context CGLContextObj]);
- CGLSetCurrentContext(ctx);
-
- // Get the data that OpenGL provides
- updateFormatFromContext(&m_format);
-
- // Get the data contained within the pixel format
- CGLPixelFormatObj cglPixelFormat = static_cast<CGLPixelFormatObj>(CGLGetPixelFormat(ctx));
- NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithCGLPixelFormatObj:cglPixelFormat];
-
- int colorSize = -1;
- [pixelFormat getValues:&colorSize forAttribute:NSOpenGLPFAColorSize forVirtualScreen:0];
- if (colorSize > 0) {
- // This seems to return the total color buffer depth, including alpha
- m_format.setRedBufferSize(colorSize / 4);
- m_format.setGreenBufferSize(colorSize / 4);
- m_format.setBlueBufferSize(colorSize / 4);
- }
+ // Surfaces on macOS always have an alpha channel, but unless the user requested
+ // one via setAlphaBufferSize(), which triggered setting NSOpenGLCPSurfaceOpacity
+ // to make the surface non-opaque, we don't want to report back the actual alpha
+ // size, as that will make the user believe the alpha channel can be used for
+ // something useful, when in reality it can't, due to the surface being opaque.
+ if (m_format.alphaBufferSize() > 0)
+ m_format.setAlphaBufferSize([pixelFormat qt_getAttribute:NSOpenGLPFAAlphaSize]);
- // The pixel format always seems to return 8 for alpha. However, the framebuffer only
- // seems to have alpha enabled if we requested it explicitly. I can't find any other
- // attribute to check explicitly for this so we use our best guess for alpha.
- int alphaSize = -1;
- [pixelFormat getValues:&alphaSize forAttribute:NSOpenGLPFAAlphaSize forVirtualScreen:0];
- if (alphaSize > 0 && requestedFormat.alphaBufferSize() > 0)
- m_format.setAlphaBufferSize(alphaSize);
-
- int depthSize = -1;
- [pixelFormat getValues:&depthSize forAttribute:NSOpenGLPFADepthSize forVirtualScreen:0];
- if (depthSize > 0)
- m_format.setDepthBufferSize(depthSize);
-
- int stencilSize = -1;
- [pixelFormat getValues:&stencilSize forAttribute:NSOpenGLPFAStencilSize forVirtualScreen:0];
- if (stencilSize > 0)
- m_format.setStencilBufferSize(stencilSize);
-
- int samples = -1;
- [pixelFormat getValues:&samples forAttribute:NSOpenGLPFASamples forVirtualScreen:0];
- if (samples > 0)
- m_format.setSamples(samples);
-
- int doubleBuffered = -1;
- int tripleBuffered = -1;
- [pixelFormat getValues:&doubleBuffered forAttribute:NSOpenGLPFADoubleBuffer forVirtualScreen:0];
- [pixelFormat getValues:&tripleBuffered forAttribute:NSOpenGLPFATripleBuffer forVirtualScreen:0];
-
- if (tripleBuffered == 1)
+ m_format.setDepthBufferSize([pixelFormat qt_getAttribute:NSOpenGLPFADepthSize]);
+ m_format.setStencilBufferSize([pixelFormat qt_getAttribute:NSOpenGLPFAStencilSize]);
+ m_format.setSamples([pixelFormat qt_getAttribute:NSOpenGLPFASamples]);
+
+ if ([pixelFormat qt_getAttribute:NSOpenGLPFATripleBuffer])
m_format.setSwapBehavior(QSurfaceFormat::TripleBuffer);
- else if (doubleBuffered == 1)
+ else if ([pixelFormat qt_getAttribute:NSOpenGLPFADoubleBuffer])
m_format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
else
m_format.setSwapBehavior(QSurfaceFormat::SingleBuffer);
- int steroBuffers = -1;
- [pixelFormat getValues:&steroBuffers forAttribute:NSOpenGLPFAStereo forVirtualScreen:0];
- if (steroBuffers == 1)
- m_format.setOption(QSurfaceFormat::StereoBuffers);
+ // ------------------- Query the context -------------------
- [pixelFormat release];
+ m_format.setSwapInterval([m_context qt_getParameter:NSOpenGLCPSwapInterval]);
- GLint swapInterval = -1;
- [m_context getValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
- if (swapInterval >= 0)
- m_format.setSwapInterval(swapInterval);
+ if (oldContext)
+ [oldContext makeCurrentContext];
+ else
+ [NSOpenGLContext clearCurrentContext];
+}
- // Restore the original context
- CGLSetCurrentContext(oldContext);
+QCocoaGLContext::~QCocoaGLContext()
+{
+ [m_context release];
}
-void QCocoaGLContext::doneCurrent()
+bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface)
{
- if (m_currentWindow && m_currentWindow.data()->handle())
- static_cast<QCocoaWindow *>(m_currentWindow.data()->handle())->setCurrentContext(0);
+ qCDebug(lcQpaOpenGLContext) << "Making" << m_context << "current"
+ << "in" << QThread::currentThread() << "for" << surface;
- m_currentWindow.clear();
+ Q_ASSERT(surface->surface()->supportsOpenGL());
- [NSOpenGLContext clearCurrentContext];
-}
+ if (!setDrawable(surface))
+ return false;
-QFunctionPointer QCocoaGLContext::getProcAddress(const char *procName)
-{
- return (QFunctionPointer)dlsym(RTLD_DEFAULT, procName);
-}
+ [m_context makeCurrentContext];
-void QCocoaGLContext::update()
-{
- QMutexLocker locker(&s_contextMutex);
- [m_context update];
+ if (surface->surface()->surfaceClass() == QSurface::Window) {
+ // Disable high-resolution surfaces when using the software renderer, which has the
+ // problem that the system silently falls back to a to using a low-resolution buffer
+ // when a high-resolution buffer is requested. This is not detectable using the NSWindow
+ // convertSizeToBacking and backingScaleFactor APIs. A typical result of this is that Qt
+ // will display a quarter of the window content when running in a virtual machine.
+ if (!m_didCheckForSoftwareContext) {
+ // FIXME: This ensures we check only once per context,
+ // but the context may be used for multiple surfaces.
+ m_didCheckForSoftwareContext = true;
+
+ const GLubyte* renderer = glGetString(GL_RENDERER);
+ if (qstrcmp((const char *)renderer, "Apple Software Renderer") == 0) {
+ NSView *view = static_cast<QCocoaWindow *>(surface)->m_view;
+ [view setWantsBestResolutionOpenGLSurface:NO];
+ }
+ }
+
+ if (m_needsUpdate.fetchAndStoreRelaxed(false))
+ update();
+ }
+
+ return true;
}
-NSOpenGLPixelFormat *QCocoaGLContext::createNSOpenGLPixelFormat(const QSurfaceFormat &format)
+/*!
+ Sets the drawable object of the NSOpenGLContext, which is the
+ frame buffer that is the target of OpenGL drawing operations.
+*/
+bool QCocoaGLContext::setDrawable(QPlatformSurface *surface)
{
- QVector<NSOpenGLPixelFormatAttribute> attrs;
+ // Make sure any surfaces released during this process are deallocated
+ // straight away, otherwise we may run out of surfaces when spinning a
+ // render-loop that doesn't return to one of the outer pools.
+ QMacAutoReleasePool pool;
- if (format.swapBehavior() == QSurfaceFormat::DoubleBuffer
- || format.swapBehavior() == QSurfaceFormat::DefaultSwapBehavior)
- attrs.append(NSOpenGLPFADoubleBuffer);
- else if (format.swapBehavior() == QSurfaceFormat::TripleBuffer)
- attrs.append(NSOpenGLPFATripleBuffer);
+ if (!surface || surface->surface()->surfaceClass() == QSurface::Offscreen) {
+ // Clear the current drawable and reset the active window, so that GL
+ // commands that don't target a specific FBO will not end up stomping
+ // on the previously set drawable.
+ qCDebug(lcQpaOpenGLContext) << "Clearing current drawable" << m_context.view << "for" << m_context;
+ [m_context clearDrawable];
+ return true;
+ }
+ Q_ASSERT(surface->surface()->surfaceClass() == QSurface::Window);
+ QNSView *view = qnsview_cast(static_cast<QCocoaWindow *>(surface)->view());
- // Select OpenGL profile
- attrs << NSOpenGLPFAOpenGLProfile;
- if (format.profile() == QSurfaceFormat::CoreProfile) {
- if (format.version() >= qMakePair(4, 1))
- attrs << NSOpenGLProfileVersion4_1Core;
- else if (format.version() >= qMakePair(3, 2))
- attrs << NSOpenGLProfileVersion3_2Core;
- else
- attrs << NSOpenGLProfileVersionLegacy;
+ if (view == m_context.view)
+ return true;
+
+ // Setting the drawable may happen on a separate thread as a result of
+ // a call to makeCurrent, so we need to set up the observers before we
+ // associate the view with the context. That way we will guarantee that
+ // as long as the view is the drawable of the context we will know about
+ // any updates to the view that require surface invalidation.
+
+ auto updateCallback = [this, view]() {
+ Q_ASSERT(QThread::currentThread() == qApp->thread());
+ if (m_context.view != view)
+ return;
+ m_needsUpdate = true;
+ };
+
+ m_updateObservers.clear();
+
+ if (view.layer) {
+ m_updateObservers.append(QMacScopedObserver(view, NSViewFrameDidChangeNotification, updateCallback));
+ m_updateObservers.append(QMacScopedObserver(view.window, NSWindowDidChangeScreenNotification, updateCallback));
} else {
- attrs << NSOpenGLProfileVersionLegacy;
+ m_updateObservers.append(QMacScopedObserver(view, NSViewGlobalFrameDidChangeNotification, updateCallback));
}
- if (format.depthBufferSize() > 0)
- attrs << NSOpenGLPFADepthSize << format.depthBufferSize();
- if (format.stencilBufferSize() > 0)
- attrs << NSOpenGLPFAStencilSize << format.stencilBufferSize();
- if (format.alphaBufferSize() > 0)
- attrs << NSOpenGLPFAAlphaSize << format.alphaBufferSize();
- if ((format.redBufferSize() > 0) &&
- (format.greenBufferSize() > 0) &&
- (format.blueBufferSize() > 0)) {
- const int colorSize = format.redBufferSize() +
- format.greenBufferSize() +
- format.blueBufferSize();
- attrs << NSOpenGLPFAColorSize << colorSize << NSOpenGLPFAMinimumPolicy;
- }
+ m_updateObservers.append(QMacScopedObserver([NSApplication sharedApplication],
+ NSApplicationDidChangeScreenParametersNotification, updateCallback));
- if (format.samples() > 0) {
- attrs << NSOpenGLPFAMultisample
- << NSOpenGLPFASampleBuffers << (NSOpenGLPixelFormatAttribute) 1
- << NSOpenGLPFASamples << (NSOpenGLPixelFormatAttribute) format.samples();
+ // If any of the observers fire at this point it's fine. We check the
+ // view association (atomically) in the update callback, and skip the
+ // update if we haven't associated yet. Setting the drawable below will
+ // have the same effect as an update.
+
+ // Now we are ready to associate the view with the context
+ m_context.view = view;
+ if (m_context.view != view) {
+ qCInfo(lcQpaOpenGLContext) << "Failed to set" << view << "as drawable for" << m_context;
+ m_updateObservers.clear();
+ return false;
}
- if (format.stereo())
- attrs << NSOpenGLPFAStereo;
+ qCInfo(lcQpaOpenGLContext) << "Set drawable for" << m_context << "to" << m_context.view;
+ return true;
+}
- //Workaround for problems with Chromium and offline renderers on the lat 2013 MacPros.
- //FIXME: Think if this could be solved via QSurfaceFormat in the future.
- static bool offlineRenderersAllowed = qEnvironmentVariableIsEmpty("QT_MAC_PRO_WEBENGINE_WORKAROUND");
- if (offlineRenderersAllowed) {
- // Allow rendering on GPUs without a connected display
- attrs << NSOpenGLPFAAllowOfflineRenderers;
- }
+// NSOpenGLContext is not re-entrant. Even when using separate contexts per thread,
+// view, and window, calls into the API will still deadlock. For more information
+// see https://openradar.appspot.com/37064579
+static QMutex s_reentrancyMutex;
- QByteArray useLayer = qgetenv("QT_MAC_WANTS_LAYER");
- if (!useLayer.isEmpty() && useLayer.toInt() > 0) {
- // Disable the software rendering fallback. This makes compositing
- // OpenGL and raster NSViews using Core Animation layers possible.
- attrs << NSOpenGLPFANoRecovery;
+void QCocoaGLContext::update()
+{
+ // Make sure any surfaces released during this process are deallocated
+ // straight away, otherwise we may run out of surfaces when spinning a
+ // render-loop that doesn't return to one of the outer pools.
+ QMacAutoReleasePool pool;
+
+ QMutexLocker locker(&s_reentrancyMutex);
+ qCInfo(lcQpaOpenGLContext) << "Updating" << m_context << "for" << m_context.view;
+ [m_context update];
+}
+
+void QCocoaGLContext::swapBuffers(QPlatformSurface *surface)
+{
+ qCDebug(lcQpaOpenGLContext) << "Swapping" << m_context
+ << "in" << QThread::currentThread() << "to" << surface;
+
+ if (surface->surface()->surfaceClass() == QSurface::Offscreen)
+ return; // Nothing to do
+
+ if (!setDrawable(surface)) {
+ qCWarning(lcQpaOpenGLContext) << "Can't flush" << m_context
+ << "without" << surface << "as drawable";
+ return;
}
- attrs << 0;
+ QMutexLocker locker(&s_reentrancyMutex);
+ [m_context flushBuffer];
+}
+
+void QCocoaGLContext::doneCurrent()
+{
+ qCDebug(lcQpaOpenGLContext) << "Clearing current context"
+ << [NSOpenGLContext currentContext] << "in" << QThread::currentThread();
- return [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs.constData()];
+ // Note: We do not need to clear the current drawable here.
+ // As long as there is no current context, GL calls will
+ // do nothing.
+
+ [NSOpenGLContext clearCurrentContext];
}
-NSOpenGLContext *QCocoaGLContext::nsOpenGLContext() const
+QSurfaceFormat QCocoaGLContext::format() const
{
- return m_context;
+ return m_format;
}
bool QCocoaGLContext::isValid() const
@@ -491,5 +492,14 @@ bool QCocoaGLContext::isSharing() const
return m_shareContext != nil;
}
-QT_END_NAMESPACE
+NSOpenGLContext *QCocoaGLContext::nativeContext() const
+{
+ return m_context;
+}
+QFunctionPointer QCocoaGLContext::getProcAddress(const char *procName)
+{
+ return (QFunctionPointer)dlsym(RTLD_DEFAULT, procName);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h
index 84632c1487..69aa7937b6 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.h
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.h
@@ -52,6 +52,7 @@
//
#include "qt_mac_p.h"
#include <private/qguiapplication_p.h>
+#include <QtCore/qoperatingsystemversion.h>
#include <QtGui/qpalette.h>
#include <QtGui/qscreen.h>
@@ -60,27 +61,37 @@
Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSView));
+struct mach_header;
+
QT_BEGIN_NAMESPACE
-Q_DECLARE_LOGGING_CATEGORY(lcQpaCocoaWindow)
-Q_DECLARE_LOGGING_CATEGORY(lcQpaCocoaDrawing)
-Q_DECLARE_LOGGING_CATEGORY(lcQpaCocoaMouse)
+Q_DECLARE_LOGGING_CATEGORY(lcQpaWindow)
+Q_DECLARE_LOGGING_CATEGORY(lcQpaDrawing)
+Q_DECLARE_LOGGING_CATEGORY(lcQpaMouse)
+Q_DECLARE_LOGGING_CATEGORY(lcQpaScreen)
class QPixmap;
class QString;
// Conversion functions
-QStringList qt_mac_NSArrayToQStringList(void *nsarray);
-void *qt_mac_QStringListToNSMutableArrayVoid(const QStringList &list);
-
-inline NSMutableArray *qt_mac_QStringListToNSMutableArray(const QStringList &qstrlist)
-{ return reinterpret_cast<NSMutableArray *>(qt_mac_QStringListToNSMutableArrayVoid(qstrlist)); }
+QStringList qt_mac_NSArrayToQStringList(NSArray<NSString *> *nsarray);
+NSMutableArray<NSString *> *qt_mac_QStringListToNSMutableArray(const QStringList &list);
NSDragOperation qt_mac_mapDropAction(Qt::DropAction action);
NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions);
Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions);
Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions);
+template <typename T>
+typename std::enable_if<std::is_pointer<T>::value, T>::type
+qt_objc_cast(id object)
+{
+ if ([object isKindOfClass:[typename std::remove_pointer<T>::type class]])
+ return static_cast<T>(object);
+
+ return nil;
+}
+
QT_MANGLE_NAMESPACE(QNSView) *qnsview_cast(NSView *view);
// Misc
@@ -91,6 +102,12 @@ QPointF qt_mac_flip(const QPointF &pos, const QRectF &reference);
QRectF qt_mac_flip(const QRectF &rect, const QRectF &reference);
Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum);
+Qt::MouseButton cocoaButton2QtButton(NSEvent *event);
+
+QEvent::Type cocoaEvent2QtMouseEvent(NSEvent *event);
+
+Qt::MouseButtons cocoaMouseButtons2QtMouseButtons(NSInteger pressedMouseButtons);
+Qt::MouseButtons currentlyPressedMouseButtons();
// strip out '&' characters, and convert "&&" to a single '&', in menu
// text - since menu text is sometimes decorated with these for Windows
@@ -159,6 +176,34 @@ T qt_mac_resolveOption(const T &fallback, QWindow *window, const QByteArray &pro
return fallback;
}
+// -------------------------------------------------------------------------
+
+#if !defined(Q_PROCESSOR_X86_64)
+#error "32-bit builds are not supported"
+#endif
+
+class QMacVersion
+{
+public:
+ enum VersionTarget {
+ ApplicationBinary,
+ QtLibraries
+ };
+
+ static QOperatingSystemVersion buildSDK(VersionTarget target = ApplicationBinary);
+ static QOperatingSystemVersion deploymentTarget(VersionTarget target = ApplicationBinary);
+ static QOperatingSystemVersion currentRuntime();
+
+private:
+ QMacVersion() = default;
+ using VersionTuple = QPair<QOperatingSystemVersion, QOperatingSystemVersion>;
+ static VersionTuple versionsForImage(const mach_header *machHeader);
+ static VersionTuple applicationVersion();
+ static VersionTuple libraryVersion();
+};
+
+// -------------------------------------------------------------------------
+
QT_END_NAMESPACE
// @compatibility_alias doesn't work with protocols
@@ -170,12 +215,7 @@ QT_END_NAMESPACE
- (void)onCancelClicked;
@end
-@interface QT_MANGLE_NAMESPACE(QNSPanelContentsWrapper) : NSView {
- NSButton *_okButton;
- NSButton *_cancelButton;
- NSView *_panelContents;
- NSEdgeInsets _panelContentsMargins;
-}
+@interface QT_MANGLE_NAMESPACE(QNSPanelContentsWrapper) : NSView
@property (nonatomic, readonly) NSButton *okButton;
@property (nonatomic, readonly) NSButton *cancelButton;
@@ -187,6 +227,7 @@ QT_END_NAMESPACE
- (NSButton *)createButtonWithTitle:(const char *)title;
- (void)layout;
+
@end
QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSPanelContentsWrapper);
@@ -285,26 +326,17 @@ public:
}
private:
- template <std::size_t... Ts>
- struct index {};
-
- template <std::size_t N, std::size_t... Ts>
- struct gen_seq : gen_seq<N - 1, N - 1, Ts...> {};
-
- template <std::size_t... Ts>
- struct gen_seq<0, Ts...> : index<Ts...> {};
-
template <typename ReturnType, bool V>
using if_requires_stret = typename std::enable_if<objc_msgsend_requires_stret<ReturnType>::value == V, ReturnType>::type;
- template <typename ReturnType, std::size_t... Is>
- if_requires_stret<ReturnType, false> msgSendSuper(std::tuple<Args...>& args, index<Is...>)
+ template <typename ReturnType, int... Is>
+ if_requires_stret<ReturnType, false> msgSendSuper(std::tuple<Args...>& args, QtPrivate::IndexesList<Is...>)
{
return qt_msgSendSuper<ReturnType>(m_receiver, m_selector, std::get<Is>(args)...);
}
- template <typename ReturnType, std::size_t... Is>
- if_requires_stret<ReturnType, true> msgSendSuper(std::tuple<Args...>& args, index<Is...>)
+ template <typename ReturnType, int... Is>
+ if_requires_stret<ReturnType, true> msgSendSuper(std::tuple<Args...>& args, QtPrivate::IndexesList<Is...>)
{
return qt_msgSendSuper_stret<ReturnType>(m_receiver, m_selector, std::get<Is>(args)...);
}
@@ -312,7 +344,7 @@ private:
template <typename ReturnType>
ReturnType msgSendSuper(std::tuple<Args...>& args)
{
- return msgSendSuper<ReturnType>(args, gen_seq<sizeof...(Args)>{});
+ return msgSendSuper<ReturnType>(args, QtPrivate::makeIndexSequence<sizeof...(Args)>{});
}
id m_receiver;
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm
index e5954f277c..36841c77ab 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.mm
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm
@@ -55,31 +55,33 @@
#include <algorithm>
+#include <mach-o/dyld.h>
+#include <dlfcn.h>
+
QT_BEGIN_NAMESPACE
-Q_LOGGING_CATEGORY(lcQpaCocoaWindow, "qt.qpa.cocoa.window");
-Q_LOGGING_CATEGORY(lcQpaCocoaDrawing, "qt.qpa.cocoa.drawing");
-Q_LOGGING_CATEGORY(lcQpaCocoaMouse, "qt.qpa.cocoa.mouse");
+Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window");
+Q_LOGGING_CATEGORY(lcQpaDrawing, "qt.qpa.drawing");
+Q_LOGGING_CATEGORY(lcQpaMouse, "qt.qpa.input.mouse");
+Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.screen");
//
// Conversion Functions
//
-QStringList qt_mac_NSArrayToQStringList(void *nsarray)
+QStringList qt_mac_NSArrayToQStringList(NSArray<NSString *> *array)
{
QStringList result;
- NSArray *array = static_cast<NSArray *>(nsarray);
- for (NSUInteger i=0; i<[array count]; ++i)
- result << QString::fromNSString([array objectAtIndex:i]);
+ for (NSString *string in array)
+ result << QString::fromNSString(string);
return result;
}
-void *qt_mac_QStringListToNSMutableArrayVoid(const QStringList &list)
+NSMutableArray<NSString *> *qt_mac_QStringListToNSMutableArray(const QStringList &list)
{
- NSMutableArray *result = [NSMutableArray arrayWithCapacity:list.size()];
- for (int i=0; i<list.size(); ++i){
- [result addObject:list[i].toNSString()];
- }
+ NSMutableArray<NSString *> *result = [NSMutableArray<NSString *> arrayWithCapacity:list.size()];
+ for (const QString &string : list)
+ [result addObject:string.toNSString()];
return result;
}
@@ -93,6 +95,7 @@ struct dndenum_mapper
static dndenum_mapper dnd_enums[] = {
{ NSDragOperationLink, Qt::LinkAction, true },
{ NSDragOperationMove, Qt::MoveAction, true },
+ { NSDragOperationDelete, Qt::MoveAction, true },
{ NSDragOperationCopy, Qt::CopyAction, true },
{ NSDragOperationGeneric, Qt::CopyAction, false },
{ NSDragOperationEvery, Qt::ActionMask, false },
@@ -161,10 +164,7 @@ Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions)
*/
QNSView *qnsview_cast(NSView *view)
{
- if (![view isKindOfClass:[QNSView class]])
- return nil;
-
- return static_cast<QNSView *>(view);
+ return qt_objc_cast<QNSView *>(view);
}
//
@@ -282,11 +282,174 @@ Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum)
return Qt::NoButton;
}
+/*!
+ \fn Qt::MouseButton cocoaButton2QtButton(NSEvent *event)
+
+ Returns the Qt::Button that corresponds to an NSEvent.buttonNumber.
+
+ \note AppKit will use buttonNumber 0 to indicate both "left button"
+ and "no button". Only NSEvents that describes mouse press/release/dragging
+ events (e.g NSEventTypeOtherMouseDown) will contain a valid
+ button number.
+
+ \note Wacom tablet might not return the correct button number for NSEvent buttonNumber
+ on right clicks. Decide here that the button is the "right" button.
+*/
+Qt::MouseButton cocoaButton2QtButton(NSEvent *event)
+{
+ switch (event.type) {
+ case NSEventTypeMouseMoved:
+ return Qt::NoButton;
+
+ case NSEventTypeRightMouseUp:
+ case NSEventTypeRightMouseDown:
+ case NSEventTypeRightMouseDragged:
+ return Qt::RightButton;
+
+ default:
+ break;
+ }
+
+ return cocoaButton2QtButton(event.buttonNumber);
+}
+
+/*!
+ \fn QEvent::Type cocoaEvent2QtMouseEvent(NSEvent *event)
+
+ Returns the QEvent::Type that corresponds to an NSEvent.type.
+*/
+QEvent::Type cocoaEvent2QtMouseEvent(NSEvent *event)
+{
+ switch (event.type) {
+ case NSEventTypeLeftMouseDown:
+ case NSEventTypeRightMouseDown:
+ case NSEventTypeOtherMouseDown:
+ return QEvent::MouseButtonPress;
+
+ case NSEventTypeLeftMouseUp:
+ case NSEventTypeRightMouseUp:
+ case NSEventTypeOtherMouseUp:
+ return QEvent::MouseButtonRelease;
+
+ case NSEventTypeLeftMouseDragged:
+ case NSEventTypeRightMouseDragged:
+ case NSEventTypeOtherMouseDragged:
+ return QEvent::MouseMove;
+
+ case NSEventTypeMouseMoved:
+ return QEvent::MouseMove;
+
+ default:
+ break;
+ }
+
+ return QEvent::None;
+}
+
+/*!
+ \fn Qt::MouseButtons cocoaMouseButtons2QtMouseButtons(NSInteger pressedMouseButtons)
+
+ Returns the Qt::MouseButtons that corresponds to an NSEvent.pressedMouseButtons.
+*/
+Qt::MouseButtons cocoaMouseButtons2QtMouseButtons(NSInteger pressedMouseButtons)
+{
+ return static_cast<Qt::MouseButton>(pressedMouseButtons & Qt::MouseButtonMask);
+}
+
+/*!
+ \fn Qt::MouseButtons currentlyPressedMouseButtons()
+
+ Returns the Qt::MouseButtons that corresponds to an NSEvent.pressedMouseButtons.
+*/
+Qt::MouseButtons currentlyPressedMouseButtons()
+{
+ return cocoaMouseButtons2QtMouseButtons(NSEvent.pressedMouseButtons);
+}
+
QString qt_mac_removeAmpersandEscapes(QString s)
{
return QPlatformTheme::removeMnemonics(s).trimmed();
}
+// -------------------------------------------------------------------------
+
+#if !defined(Q_PROCESSOR_X86_64)
+#error "32-bit builds are not supported"
+#endif
+
+QOperatingSystemVersion QMacVersion::buildSDK(VersionTarget target)
+{
+ switch (target) {
+ case ApplicationBinary: return applicationVersion().second;
+ case QtLibraries: return libraryVersion().second;
+ }
+ Q_UNREACHABLE();
+}
+
+QOperatingSystemVersion QMacVersion::deploymentTarget(VersionTarget target)
+{
+ switch (target) {
+ case ApplicationBinary: return applicationVersion().first;
+ case QtLibraries: return libraryVersion().first;
+ }
+ Q_UNREACHABLE();
+}
+
+QOperatingSystemVersion QMacVersion::currentRuntime()
+{
+ return QOperatingSystemVersion::current();
+}
+
+QMacVersion::VersionTuple QMacVersion::versionsForImage(const mach_header *machHeader)
+{
+ auto commandCursor = uintptr_t(machHeader) + sizeof(mach_header_64);
+ for (uint32_t i = 0; i < machHeader->ncmds; ++i) {
+ load_command *loadCommand = reinterpret_cast<load_command *>(commandCursor);
+ if (loadCommand->cmd == LC_VERSION_MIN_MACOSX) {
+ auto versionCommand = reinterpret_cast<version_min_command *>(loadCommand);
+ uint32_t dt = versionCommand->version; // Deployment target
+ uint32_t sdk = versionCommand->sdk; // Build SDK
+ return qMakePair(
+ QOperatingSystemVersion(QOperatingSystemVersion::MacOS,
+ dt >> 16 & 0xffff, dt >> 8 & 0xff, dt & 0xff),
+ QOperatingSystemVersion(QOperatingSystemVersion::MacOS,
+ sdk >> 16 & 0xffff, sdk >> 8 & 0xff, sdk & 0xff)
+ );
+ }
+ commandCursor += loadCommand->cmdsize;
+ }
+ Q_ASSERT_X(false, "QCocoaIntegration", "Could not find version-min load command");
+ Q_UNREACHABLE();
+}
+
+QMacVersion::VersionTuple QMacVersion::applicationVersion()
+{
+ static VersionTuple version = []() {
+ const mach_header *executableHeader = nullptr;
+ for (uint32_t i = 0; i < _dyld_image_count(); ++i) {
+ auto header = _dyld_get_image_header(i);
+ if (header->filetype == MH_EXECUTE) {
+ executableHeader = header;
+ break;
+ }
+ }
+ Q_ASSERT_X(executableHeader, "QCocoaIntegration", "Failed to resolve Mach-O header of executable");
+ return versionsForImage(executableHeader);
+ }();
+ return version;
+}
+
+QMacVersion::VersionTuple QMacVersion::libraryVersion()
+{
+ static VersionTuple version = []() {
+ Dl_info cocoaPluginImage;
+ dladdr((const void *)&QMacVersion::libraryVersion, &cocoaPluginImage);
+ Q_ASSERT_X(cocoaPluginImage.dli_fbase, "QCocoaIntegration", "Failed to resolve Mach-O header of Cocoa plugin");
+ return versionsForImage(static_cast<mach_header*>(cocoaPluginImage.dli_fbase));
+ }();
+ return version;
+}
+
QT_END_NAMESPACE
/*! \internal
@@ -298,7 +461,12 @@ QT_END_NAMESPACE
the target-action for the OK/Cancel buttons and making
sure the layout is consistent.
*/
-@implementation QNSPanelContentsWrapper
+@implementation QNSPanelContentsWrapper {
+ NSButton *_okButton;
+ NSButton *_cancelButton;
+ NSView *_panelContents;
+ NSEdgeInsets _panelContentsMargins;
+}
@synthesize okButton = _okButton;
@synthesize cancelButton = _cancelButton;
@@ -346,7 +514,7 @@ QT_END_NAMESPACE
// FIXME: Not obvious, from Cocoa's documentation, that QString::toNSString() makes a deep copy
button.title = (NSString *)cleanTitle.toCFString();
((NSButtonCell *)button.cell).font =
- [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]];
+ [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSControlSizeRegular]];
[self addSubview:button];
return button;
}
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h
index 301771fd53..7de7e073de 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.h
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.h
@@ -51,6 +51,9 @@
#include "qcocoadrag.h"
#include "qcocoaservices.h"
#include "qcocoakeymapper.h"
+#if QT_CONFIG(vulkan)
+#include "qcocoavulkaninstance.h"
+#endif
#include <QtCore/QScopedPointer>
#include <qpa/qplatformintegration.h>
@@ -86,6 +89,11 @@ public:
QAbstractEventDispatcher *createEventDispatcher() const override;
+#if QT_CONFIG(vulkan)
+ QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance) const override;
+ QCocoaVulkanInstance *getCocoaVulkanInstance() const;
+#endif
+
QCoreTextFontDatabase *fontDatabase() const override;
QCocoaNativeInterface *nativeInterface() const override;
QPlatformInputContext *inputContext() const override;
@@ -144,6 +152,9 @@ private:
QScopedPointer<QCocoaServices> mServices;
QScopedPointer<QCocoaKeyMapper> mKeyboardMapper;
+#if QT_CONFIG(vulkan)
+ mutable QCocoaVulkanInstance *mCocoaVulkanInstance = nullptr;
+#endif
QHash<QWindow *, NSToolbar *> mToolbars;
QList<QCocoaWindow *> m_popupWindowStack;
};
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index 55b3805df3..936fecf8de 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -59,6 +59,8 @@
#include <qpa/qplatformoffscreensurface.h>
#include <QtCore/qcoreapplication.h>
+#include <QtPlatformHeaders/qcocoanativecontext.h>
+
#include <QtGui/private/qcoregraphics_p.h>
#ifdef QT_WIDGETS_LIB
@@ -77,6 +79,32 @@ static void initResources()
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcQpa, "qt.qpa", QtWarningMsg);
+
+static void logVersionInformation()
+{
+ if (!lcQpa().isInfoEnabled())
+ return;
+
+ auto osVersion = QMacVersion::currentRuntime();
+ auto qtBuildSDK = QMacVersion::buildSDK(QMacVersion::QtLibraries);
+ auto qtDeploymentTarget = QMacVersion::deploymentTarget(QMacVersion::QtLibraries);
+ auto appBuildSDK = QMacVersion::buildSDK(QMacVersion::ApplicationBinary);
+ auto appDeploymentTarget = QMacVersion::deploymentTarget(QMacVersion::ApplicationBinary);
+
+ qCInfo(lcQpa, "Loading macOS (Cocoa) platform plugin for Qt " QT_VERSION_STR ", running on macOS %d.%d.%d\n\n" \
+ " Component SDK version Deployment target \n" \
+ " ------------- ------------- -------------------\n" \
+ " Qt " QT_VERSION_STR " %d.%d.%d %d.%d.%d\n" \
+ " Application %d.%d.%d %d.%d.%d\n",
+ osVersion.majorVersion(), osVersion.minorVersion(), osVersion.microVersion(),
+ qtBuildSDK.majorVersion(), qtBuildSDK.minorVersion(), qtBuildSDK.microVersion(),
+ qtDeploymentTarget.majorVersion(), qtDeploymentTarget.minorVersion(), qtDeploymentTarget.microVersion(),
+ appBuildSDK.majorVersion(), appBuildSDK.minorVersion(), appBuildSDK.microVersion(),
+ appDeploymentTarget.majorVersion(), appDeploymentTarget.minorVersion(), appDeploymentTarget.microVersion());
+}
+
+
class QCoreTextFontEngine;
class QFontEngineFT;
@@ -94,11 +122,11 @@ static QCocoaIntegration::Options parseOptions(const QStringList &paramList)
return options;
}
-QCocoaIntegration *QCocoaIntegration::mInstance = 0;
+QCocoaIntegration *QCocoaIntegration::mInstance = nullptr;
QCocoaIntegration::QCocoaIntegration(const QStringList &paramList)
: mOptions(parseOptions(paramList))
- , mFontDb(0)
+ , mFontDb(nullptr)
#ifndef QT_NO_ACCESSIBILITY
, mAccessibility(new QCocoaAccessibility)
#endif
@@ -110,7 +138,9 @@ QCocoaIntegration::QCocoaIntegration(const QStringList &paramList)
, mServices(new QCocoaServices)
, mKeyboardMapper(new QCocoaKeyMapper)
{
- if (mInstance != 0)
+ logVersionInformation();
+
+ if (mInstance)
qWarning("Creating multiple Cocoa platform integrations is not supported");
mInstance = this;
@@ -186,7 +216,7 @@ QCocoaIntegration::QCocoaIntegration(const QStringList &paramList)
QCocoaIntegration::~QCocoaIntegration()
{
- mInstance = 0;
+ mInstance = nullptr;
qt_resetNSApplicationSendEvent();
@@ -196,7 +226,7 @@ QCocoaIntegration::~QCocoaIntegration()
QCocoaApplicationDelegate *delegate = [QCocoaApplicationDelegate sharedDelegate];
[delegate removeAppleEventHandlers];
// reset the application delegate
- [[NSApplication sharedApplication] setDelegate: 0];
+ [[NSApplication sharedApplication] setDelegate:nil];
}
#ifndef QT_NO_CLIPBOARD
@@ -225,15 +255,13 @@ QCocoaIntegration::Options QCocoaIntegration::options() const
return mOptions;
}
-Q_LOGGING_CATEGORY(lcCocoaScreen, "qt.qpa.cocoa.screens");
-
/*!
\brief Synchronizes the screen list, adds new screens, removes deleted ones
*/
void QCocoaIntegration::updateScreens()
{
- NSArray *scrs = [NSScreen screens];
- NSMutableArray *screens = [NSMutableArray arrayWithArray:scrs];
+ NSArray<NSScreen *> *scrs = [NSScreen screens];
+ NSMutableArray<NSScreen *> *screens = [NSMutableArray<NSScreen *> arrayWithArray:scrs];
if ([screens count] == 0)
if ([NSScreen mainScreen])
[screens addObject:[NSScreen mainScreen]];
@@ -244,7 +272,7 @@ void QCocoaIntegration::updateScreens()
uint screenCount = [screens count];
for (uint i = 0; i < screenCount; i++) {
NSScreen* scr = [screens objectAtIndex:i];
- CGDirectDisplayID dpy = [[[scr deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue];
+ CGDirectDisplayID dpy = scr.qt_displayId;
// If this screen is a mirror and is not the primary one of the mirror set, ignore it.
// Exception: The NSScreen API has been observed to a return a screen list with one
// mirrored, non-primary screen when Qt is running as a startup item. Always use the
@@ -254,8 +282,8 @@ void QCocoaIntegration::updateScreens()
if (primary != kCGNullDirectDisplay && primary != dpy)
continue;
}
- QCocoaScreen* screen = NULL;
- foreach (QCocoaScreen* existingScr, mScreens)
+ QCocoaScreen* screen = nullptr;
+ foreach (QCocoaScreen* existingScr, mScreens) {
// NSScreen documentation says do not cache the array returned from [NSScreen screens].
// However in practice, we can identify a screen by its pointer: if resolution changes,
// the NSScreen object will be the same instance, just with different values.
@@ -263,14 +291,14 @@ void QCocoaIntegration::updateScreens()
screen = existingScr;
break;
}
+ }
if (screen) {
remainingScreens.remove(screen);
- screen->updateGeometry();
- qCDebug(lcCocoaScreen) << "Updated properties of" << screen;
+ screen->updateProperties();
} else {
screen = new QCocoaScreen(i);
mScreens.append(screen);
- qCDebug(lcCocoaScreen) << "Adding" << screen;
+ qCDebug(lcQpaScreen) << "Adding" << screen;
screenAdded(screen);
}
siblings << screen;
@@ -287,7 +315,7 @@ void QCocoaIntegration::updateScreens()
mScreens.removeOne(screen);
// Prevent stale references to NSScreen during destroy
screen->m_screenIndex = -1;
- qCDebug(lcCocoaScreen) << "Removing" << screen;
+ qCDebug(lcQpaScreen) << "Removing" << screen;
destroyScreen(screen);
}
}
@@ -296,7 +324,7 @@ QCocoaScreen *QCocoaIntegration::screenForNSScreen(NSScreen *nsScreen)
{
NSUInteger index = [[NSScreen screens] indexOfObject:nsScreen];
if (index == NSNotFound)
- return 0;
+ return nullptr;
if (index >= unsigned(mScreens.count()))
updateScreens();
@@ -306,7 +334,7 @@ QCocoaScreen *QCocoaIntegration::screenForNSScreen(NSScreen *nsScreen)
return screen;
}
- return 0;
+ return nullptr;
}
bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) const
@@ -361,10 +389,8 @@ QPlatformOffscreenSurface *QCocoaIntegration::createPlatformOffscreenSurface(QOf
#ifndef QT_NO_OPENGL
QPlatformOpenGLContext *QCocoaIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
- QCocoaGLContext *glContext = new QCocoaGLContext(context->format(),
- context->shareHandle(),
- context->nativeHandle());
- context->setNativeHandle(glContext->nativeHandle());
+ QCocoaGLContext *glContext = new QCocoaGLContext(context);
+ context->setNativeHandle(QVariant::fromValue<QCocoaNativeContext>(glContext->nativeContext()));
return glContext;
}
#endif
@@ -379,6 +405,19 @@ QAbstractEventDispatcher *QCocoaIntegration::createEventDispatcher() const
return new QCocoaEventDispatcher;
}
+#if QT_CONFIG(vulkan)
+QPlatformVulkanInstance *QCocoaIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) const
+{
+ mCocoaVulkanInstance = new QCocoaVulkanInstance(instance);
+ return mCocoaVulkanInstance;
+}
+
+QCocoaVulkanInstance *QCocoaIntegration::getCocoaVulkanInstance() const
+{
+ return mCocoaVulkanInstance;
+}
+#endif
+
QCoreTextFontDatabase *QCocoaIntegration::fontDatabase() const
{
return mFontDb.data();
@@ -480,14 +519,14 @@ void QCocoaIntegration::pushPopupWindow(QCocoaWindow *window)
QCocoaWindow *QCocoaIntegration::popPopupWindow()
{
if (m_popupWindowStack.isEmpty())
- return 0;
+ return nullptr;
return m_popupWindowStack.takeLast();
}
QCocoaWindow *QCocoaIntegration::activePopupWindow() const
{
if (m_popupWindowStack.isEmpty())
- return 0;
+ return nullptr;
return m_popupWindowStack.front();
}
diff --git a/src/plugins/platforms/cocoa/qcocoaintrospection.h b/src/plugins/platforms/cocoa/qcocoaintrospection.h
index 1d984b9857..20001ac71d 100644
--- a/src/plugins/platforms/cocoa/qcocoaintrospection.h
+++ b/src/plugins/platforms/cocoa/qcocoaintrospection.h
@@ -76,7 +76,7 @@
QT_BEGIN_NAMESPACE
-void qt_cocoa_change_implementation(Class baseClass, SEL originalSel, Class proxyClass, SEL replacementSel = 0, SEL backupSel = 0);
+void qt_cocoa_change_implementation(Class baseClass, SEL originalSel, Class proxyClass, SEL replacementSel = nil, SEL backupSel = nil);
void qt_cocoa_change_back_implementation(Class baseClass, SEL originalSel, SEL backupSel);
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoakeymapper.h b/src/plugins/platforms/cocoa/qcocoakeymapper.h
index a75e275077..2624f19978 100644
--- a/src/plugins/platforms/cocoa/qcocoakeymapper.h
+++ b/src/plugins/platforms/cocoa/qcocoakeymapper.h
@@ -89,15 +89,12 @@ public:
void clearMappings();
private:
- QCFType<TISInputSourceRef> currentInputSource;
+ QCFType<TISInputSourceRef> currentInputSource = nullptr;
- enum { NullMode, UnicodeMode, OtherMode } keyboard_mode;
- union {
- const UCKeyboardLayout *unicode;
- void *other;
- } keyboard_layout_format;
- KeyboardLayoutKind keyboard_kind;
- UInt32 keyboard_dead;
+ enum { NullMode, UnicodeMode, OtherMode } keyboard_mode = NullMode;
+ const UCKeyboardLayout *keyboard_layout_format = nullptr;
+ KeyboardLayoutKind keyboard_kind = kKLKCHRuchrKind;
+ UInt32 keyboard_dead = 0;
KeyboardLayoutItem *keyLayout[256];
};
diff --git a/src/plugins/platforms/cocoa/qcocoakeymapper.mm b/src/plugins/platforms/cocoa/qcocoakeymapper.mm
index 80140505d1..350ae4b9be 100644
--- a/src/plugins/platforms/cocoa/qcocoakeymapper.mm
+++ b/src/plugins/platforms/cocoa/qcocoakeymapper.mm
@@ -341,8 +341,6 @@ static int qt_mac_get_key(int modif, const QChar &key, int virtualKey)
QCocoaKeyMapper::QCocoaKeyMapper()
{
memset(keyLayout, 0, sizeof(keyLayout));
- keyboard_layout_format.unicode = 0;
- currentInputSource = 0;
}
QCocoaKeyMapper::~QCocoaKeyMapper()
@@ -352,31 +350,38 @@ QCocoaKeyMapper::~QCocoaKeyMapper()
Qt::KeyboardModifiers QCocoaKeyMapper::queryKeyboardModifiers()
{
- return qt_mac_get_modifiers(GetCurrentEventKeyModifiers());
+ return qt_mac_get_modifiers(GetCurrentKeyModifiers());
}
bool QCocoaKeyMapper::updateKeyboard()
{
- const UCKeyboardLayout *uchrData = 0;
+ const UCKeyboardLayout *uchrData = nullptr;
QCFType<TISInputSourceRef> source = TISCopyInputMethodKeyboardLayoutOverride();
if (!source)
source = TISCopyCurrentKeyboardInputSource();
if (keyboard_mode != NullMode && source == currentInputSource) {
return false;
}
- Q_ASSERT(source != 0);
+ Q_ASSERT(source);
CFDataRef data = static_cast<CFDataRef>(TISGetInputSourceProperty(source,
kTISPropertyUnicodeKeyLayoutData));
- uchrData = data ? reinterpret_cast<const UCKeyboardLayout *>(CFDataGetBytePtr(data)) : 0;
+ uchrData = data ? reinterpret_cast<const UCKeyboardLayout *>(CFDataGetBytePtr(data)) : nullptr;
keyboard_kind = LMGetKbdType();
if (uchrData) {
- keyboard_layout_format.unicode = uchrData;
+ keyboard_layout_format = uchrData;
keyboard_mode = UnicodeMode;
+ } else {
+ keyboard_layout_format = nullptr;
+ keyboard_mode = NullMode;
}
currentInputSource = source;
keyboard_dead = 0;
+ const auto newMode = keyboard_mode;
+ deleteLayouts();
+ keyboard_mode = newMode;
+
return true;
}
@@ -386,7 +391,7 @@ void QCocoaKeyMapper::deleteLayouts()
for (int i = 0; i < 255; ++i) {
if (keyLayout[i]) {
delete keyLayout[i];
- keyLayout[i] = 0;
+ keyLayout[i] = nullptr;
}
}
}
@@ -399,10 +404,8 @@ void QCocoaKeyMapper::clearMappings()
void QCocoaKeyMapper::updateKeyMap(unsigned short macVirtualKey, QChar unicodeKey)
{
- if (updateKeyboard()) {
- // ### Qt 4 did this:
- // QKeyMapper::changeKeyboard();
- }
+ updateKeyboard();
+
if (keyLayout[macVirtualKey])
return;
@@ -414,7 +417,7 @@ void QCocoaKeyMapper::updateKeyMap(unsigned short macVirtualKey, QChar unicodeKe
keyLayout[macVirtualKey]->qtKey[i] = 0;
const UInt32 keyModifier = ((qt_mac_get_mac_modifiers(ModsTbl[i]) >> 8) & 0xFF);
- OSStatus err = UCKeyTranslate(keyboard_layout_format.unicode, macVirtualKey, kUCKeyActionDown, keyModifier,
+ OSStatus err = UCKeyTranslate(keyboard_layout_format, macVirtualKey, kUCKeyActionDown, keyModifier,
keyboard_kind, 0, &keyboard_dead, buffer_size, &out_buffer_size, buffer);
if (err == noErr && out_buffer_size) {
const QChar unicode(buffer[0]);
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.h b/src/plugins/platforms/cocoa/qcocoamenu.h
index 6db4e04c61..34d8428188 100644
--- a/src/plugins/platforms/cocoa/qcocoamenu.h
+++ b/src/plugins/platforms/cocoa/qcocoamenu.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author James Turner <james.turner@kdab.com>
** Contact: https://www.qt.io/licensing/
**
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm
index a788ac7d45..7b96fca3f9 100644
--- a/src/plugins/platforms/cocoa/qcocoamenu.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenu.mm
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2018 The Qt Company Ltd.
** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author James Turner <james.turner@kdab.com>
** Contact: https://www.qt.io/licensing/
**
@@ -53,7 +54,7 @@
QT_BEGIN_NAMESPACE
QCocoaMenu::QCocoaMenu() :
- m_attachedItem(0),
+ m_attachedItem(nil),
m_updateTimer(0),
m_enabled(true),
m_parentEnabled(true),
@@ -62,14 +63,14 @@ QCocoaMenu::QCocoaMenu() :
{
QMacAutoReleasePool pool;
- m_nativeMenu = [[QCocoaNSMenu alloc] initWithQPAMenu:this];
+ m_nativeMenu = [[QCocoaNSMenu alloc] initWithPlatformMenu:this];
}
QCocoaMenu::~QCocoaMenu()
{
- foreach (QCocoaMenuItem *item, m_menuItems) {
+ for (auto *item : qAsConst(m_menuItems)) {
if (item->menuParent() == this)
- item->setMenuParent(0);
+ item->setMenuParent(nullptr);
}
[m_nativeMenu release];
@@ -79,7 +80,7 @@ void QCocoaMenu::setText(const QString &text)
{
QMacAutoReleasePool pool;
QString stripped = qt_mac_removeAmpersandEscapes(text);
- [m_nativeMenu setTitle:stripped.toNSString()];
+ m_nativeMenu.title = stripped.toNSString();
}
void QCocoaMenu::setMinimumWidth(int width)
@@ -132,7 +133,7 @@ void QCocoaMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *
void QCocoaMenu::insertNative(QCocoaMenuItem *item, QCocoaMenuItem *beforeItem)
{
- setItemTargetAction(item);
+ item->resolveTargetAction();
NSMenuItem *nativeItem = item->nsItem();
// Someone's adding new items after aboutToShow() was emitted
if (isOpen() && nativeItem && item->menu())
@@ -187,25 +188,25 @@ void QCocoaMenu::removeMenuItem(QPlatformMenuItem *menuItem)
}
if (cocoaItem->menuParent() == this)
- cocoaItem->setMenuParent(0);
+ cocoaItem->setMenuParent(nullptr);
// Ignore any parent enabled state
cocoaItem->setParentEnabled(true);
m_menuItems.removeOne(cocoaItem);
if (!cocoaItem->isMerged()) {
- if (m_nativeMenu != [cocoaItem->nsItem() menu]) {
+ if (m_nativeMenu != cocoaItem->nsItem().menu) {
qWarning("Item to remove does not belong to this menu");
return;
}
- [m_nativeMenu removeItem: cocoaItem->nsItem()];
+ [m_nativeMenu removeItem:cocoaItem->nsItem()];
}
}
QCocoaMenuItem *QCocoaMenu::itemOrNull(int index) const
{
if ((index < 0) || (index >= m_menuItems.size()))
- return 0;
+ return nullptr;
return m_menuItems.at(index);
}
@@ -247,8 +248,8 @@ void QCocoaMenu::syncMenuItem_helper(QPlatformMenuItem *menuItem, bool menubarUp
// native item was changed for some reason
if (oldItem) {
if (wasMerged) {
- [oldItem setEnabled:NO];
- [oldItem setHidden:YES];
+ oldItem.enabled = NO;
+ oldItem.hidden = YES;
} else {
[m_nativeMenu removeItem:oldItem];
}
@@ -278,31 +279,27 @@ void QCocoaMenu::syncSeparatorsCollapsible(bool enable)
bool previousIsSeparator = true; // setting to true kills all the separators placed at the top.
NSMenuItem *previousItem = nil;
- NSArray *itemArray = [m_nativeMenu itemArray];
- for (unsigned int i = 0; i < [itemArray count]; ++i) {
- NSMenuItem *item = reinterpret_cast<NSMenuItem *>([itemArray objectAtIndex:i]);
- if ([item isSeparatorItem]) {
- QCocoaMenuItem *cocoaItem = reinterpret_cast<QCocoaMenuItem *>([item tag]);
- if (cocoaItem)
+ for (NSMenuItem *item in m_nativeMenu.itemArray) {
+ if (item.separatorItem) {
+ if (auto *cocoaItem = qt_objc_cast<QCocoaNSMenuItem *>(item).platformMenuItem)
cocoaItem->setVisible(!previousIsSeparator);
- [item setHidden:previousIsSeparator];
+ item.hidden = previousIsSeparator;
}
- if (![item isHidden]) {
+ if (!item.hidden) {
previousItem = item;
- previousIsSeparator = ([previousItem isSeparatorItem]);
+ previousIsSeparator = previousItem.separatorItem;
}
}
// We now need to check the final item since we don't want any separators at the end of the list.
if (previousItem && previousIsSeparator) {
- QCocoaMenuItem *cocoaItem = reinterpret_cast<QCocoaMenuItem *>([previousItem tag]);
- if (cocoaItem)
+ if (auto *cocoaItem = qt_objc_cast<QCocoaNSMenuItem *>(previousItem).platformMenuItem)
cocoaItem->setVisible(false);
- [previousItem setHidden:YES];
+ previousItem.hidden = YES;
}
} else {
- foreach (QCocoaMenuItem *item, m_menuItems) {
+ for (auto *item : qAsConst(m_menuItems)) {
if (!item->isSeparator())
continue;
@@ -324,7 +321,7 @@ void QCocoaMenu::setEnabled(bool enabled)
bool QCocoaMenu::isEnabled() const
{
- return m_attachedItem ? [m_attachedItem isEnabled] : m_enabled && m_parentEnabled;
+ return m_attachedItem ? m_attachedItem.enabled : m_enabled && m_parentEnabled;
}
void QCocoaMenu::setVisible(bool visible)
@@ -337,11 +334,11 @@ void QCocoaMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect,
QMacAutoReleasePool pool;
QPoint pos = QPoint(targetRect.left(), targetRect.top() + targetRect.height());
- QCocoaWindow *cocoaWindow = parentWindow ? static_cast<QCocoaWindow *>(parentWindow->handle()) : 0;
+ QCocoaWindow *cocoaWindow = parentWindow ? static_cast<QCocoaWindow *>(parentWindow->handle()) : nullptr;
NSView *view = cocoaWindow ? cocoaWindow->view() : nil;
NSMenuItem *nsItem = item ? ((QCocoaMenuItem *)item)->nsItem() : nil;
- QScreen *screen = 0;
+ QScreen *screen = nullptr;
if (parentWindow)
screen = parentWindow->screen();
if (!screen && !QGuiApplication::screens().isEmpty())
@@ -360,9 +357,9 @@ void QCocoaMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect,
// respect the menu's minimum width.
NSPopUpButtonCell *popupCell = [[[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]
autorelease];
- [popupCell setAltersStateOfSelectedItem:NO];
- [popupCell setTransparent:YES];
- [popupCell setMenu:m_nativeMenu];
+ popupCell.altersStateOfSelectedItem = NO;
+ popupCell.transparent = YES;
+ popupCell.menu = m_nativeMenu;
[popupCell selectItem:nsItem];
QCocoaScreen *cocoaScreen = static_cast<QCocoaScreen *>(screen->handle());
@@ -394,7 +391,7 @@ void QCocoaMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect,
if (view) {
// Finally, we need to synthesize an event.
- NSEvent *menuEvent = [NSEvent mouseEventWithType:NSRightMouseDown
+ NSEvent *menuEvent = [NSEvent mouseEventWithType:NSEventTypeRightMouseDown
location:nsPos
modifierFlags:0
timestamp:0
@@ -405,7 +402,7 @@ void QCocoaMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect,
pressure:1.0];
[NSMenu popUpContextMenu:m_nativeMenu withEvent:menuEvent forView:view];
} else {
- [m_nativeMenu popUpMenuPositioningItem:nsItem atLocation:nsPos inView:0];
+ [m_nativeMenu popUpMenuPositioningItem:nsItem atLocation:nsPos inView:nil];
}
}
@@ -425,17 +422,17 @@ QPlatformMenuItem *QCocoaMenu::menuItemAt(int position) const
if (0 <= position && position < m_menuItems.count())
return m_menuItems.at(position);
- return 0;
+ return nullptr;
}
QPlatformMenuItem *QCocoaMenu::menuItemForTag(quintptr tag) const
{
- foreach (QCocoaMenuItem *item, m_menuItems) {
+ for (auto *item : qAsConst(m_menuItems)) {
if (item->tag() == tag)
return item;
}
- return 0;
+ return nullptr;
}
QList<QCocoaMenuItem *> QCocoaMenu::items() const
@@ -446,7 +443,7 @@ QList<QCocoaMenuItem *> QCocoaMenu::items() const
QList<QCocoaMenuItem *> QCocoaMenu::merged() const
{
QList<QCocoaMenuItem *> result;
- foreach (QCocoaMenuItem *item, m_menuItems) {
+ for (auto *item : qAsConst(m_menuItems)) {
if (item->menu()) { // recurse into submenus
result.append(item->menu()->merged());
continue;
@@ -467,7 +464,7 @@ void QCocoaMenu::propagateEnabledState(bool enabled)
if (!m_enabled && enabled) // Some ancestor was enabled, but this menu is not
return;
- foreach (QCocoaMenuItem *item, m_menuItems) {
+ for (auto *item : qAsConst(m_menuItems)) {
if (QCocoaMenu *menu = item->menu())
menu->propagateEnabledState(enabled);
else
@@ -495,11 +492,4 @@ NSMenuItem *QCocoaMenu::attachedItem() const
return m_attachedItem;
}
-void QCocoaMenu::setItemTargetAction(QCocoaMenuItem *item) const
-{
- auto *nsItem = item->nsItem();
- nsItem.target = m_nativeMenu;
- nsItem.action = @selector(qt_itemFired:);
-}
-
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.h b/src/plugins/platforms/cocoa/qcocoamenubar.h
index 6f3aca3a51..50b6e69720 100644
--- a/src/plugins/platforms/cocoa/qcocoamenubar.h
+++ b/src/plugins/platforms/cocoa/qcocoamenubar.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author James Turner <james.turner@kdab.com>
** Contact: https://www.qt.io/licensing/
**
@@ -60,17 +60,16 @@ public:
void removeMenu(QPlatformMenu *menu) override;
void syncMenu(QPlatformMenu *menuItem) override;
void handleReparent(QWindow *newParentWindow) override;
+ QWindow *parentWindow() const override;
QPlatformMenu *menuForTag(quintptr tag) const override;
inline NSMenu *nsMenu() const
{ return m_nativeMenu; }
- static void redirectKnownMenuItemsToFirstResponder();
- static void resetKnownMenuItemsToQt();
static void updateMenuBarImmediately();
QList<QCocoaMenuItem*> merged() const;
- NSMenuItem *itemForRole(QPlatformMenuItem::MenuRole r);
+ NSMenuItem *itemForRole(QPlatformMenuItem::MenuRole role);
QCocoaWindow *cocoaWindow() const;
void syncMenu_helper(QPlatformMenu *menu, bool menubarUpdate);
diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm
index 61ac5eb7f0..30bff78a36 100644
--- a/src/plugins/platforms/cocoa/qcocoamenubar.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2018 The Qt Company Ltd.
** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author James Turner <james.turner@kdab.com>
** Contact: https://www.qt.io/licensing/
**
@@ -67,7 +68,7 @@ QCocoaMenuBar::~QCocoaMenuBar()
#ifdef QT_COCOA_ENABLE_MENU_DEBUG
qDebug() << "~QCocoaMenuBar" << this;
#endif
- foreach (QCocoaMenu *menu, m_menus) {
+ for (auto menu : qAsConst(m_menus)) {
if (!menu)
continue;
NSMenuItem *item = nativeItemForMenu(menu);
@@ -79,14 +80,13 @@ QCocoaMenuBar::~QCocoaMenuBar()
static_menubars.removeOne(this);
if (!m_window.isNull() && m_window->menubar() == this) {
- m_window->setMenubar(0);
+ m_window->setMenubar(nullptr);
// Delete the children first so they do not cause
// the native menu items to be hidden after
// the menu bar was updated
qDeleteAll(children());
updateMenuBarImmediately();
- resetKnownMenuItemsToQt();
}
}
@@ -199,8 +199,8 @@ void QCocoaMenuBar::syncMenu_helper(QPlatformMenu *menu, bool menubarUpdate)
// If the NSMenu has no visble items, or only separators, we should hide it
// on the menubar. This can happen after syncing the menu items since they
// can be moved to other menus.
- for (NSMenuItem *item in [cocoaMenu->nsMenu() itemArray])
- if (![item isSeparatorItem] && ![item isHidden]) {
+ for (NSMenuItem *item in cocoaMenu->nsMenu().itemArray)
+ if (!item.separatorItem && !item.hidden) {
shouldHide = NO;
break;
}
@@ -230,7 +230,7 @@ void QCocoaMenuBar::handleReparent(QWindow *newParentWindow)
if (!m_window.isNull())
m_window->setMenubar(nullptr);
- if (newParentWindow == nullptr) {
+ if (!newParentWindow) {
m_window.clear();
} else {
newParentWindow->create();
@@ -241,82 +241,28 @@ void QCocoaMenuBar::handleReparent(QWindow *newParentWindow)
updateMenuBarImmediately();
}
+QWindow *QCocoaMenuBar::parentWindow() const
+{
+ return m_window ? m_window->window() : nullptr;
+}
+
+
QCocoaWindow *QCocoaMenuBar::findWindowForMenubar()
{
if (qApp->focusWindow())
return static_cast<QCocoaWindow*>(qApp->focusWindow()->handle());
- return NULL;
+ return nullptr;
}
QCocoaMenuBar *QCocoaMenuBar::findGlobalMenubar()
{
- foreach (QCocoaMenuBar *mb, static_menubars) {
- if (mb->m_window.isNull())
- return mb;
+ for (auto *menubar : qAsConst(static_menubars)) {
+ if (menubar->m_window.isNull())
+ return menubar;
}
- return NULL;
-}
-
-void QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder()
-{
- // QTBUG-17291: http://forums.macrumors.com/showthread.php?t=1249452
- // When a dialog is opened, shortcuts for actions inside the dialog (cut, paste, ...)
- // continue to go through the same menu items which claimed those shortcuts.
- // They are not keystrokes which we can intercept in any other way; the OS intercepts them.
- // The menu items had to be created by the application. That's why we need roles
- // to identify those "special" menu items which can be useful even when non-Qt
- // native widgets are in focus. When the native widget is focused it will be the
- // first responder, so the menu item needs to have its target be the first responder;
- // this is done by setting it to nil.
-
- // This function will find all menu items on all menus which have
- // "special" roles, set the target and also set the standard actions which
- // apply to those roles. But afterwards it is necessary to call
- // resetKnownMenuItemsToQt() to put back the target and action so that
- // those menu items will go back to invoking their associated QActions.
- foreach (QCocoaMenuBar *mb, static_menubars)
- foreach (QCocoaMenu *m, mb->m_menus)
- foreach (QCocoaMenuItem *i, m->items()) {
- bool known = true;
- switch (i->effectiveRole()) {
- case QPlatformMenuItem::CutRole:
- [i->nsItem() setAction:@selector(cut:)];
- break;
- case QPlatformMenuItem::CopyRole:
- [i->nsItem() setAction:@selector(copy:)];
- break;
- case QPlatformMenuItem::PasteRole:
- [i->nsItem() setAction:@selector(paste:)];
- break;
- case QPlatformMenuItem::SelectAllRole:
- [i->nsItem() setAction:@selector(selectAll:)];
- break;
- // We may discover later that there are other roles/actions which
- // are meaningful to standard native widgets; they can be added.
- default:
- known = false;
- break;
- }
- if (known)
- [i->nsItem() setTarget:nil];
- }
-}
-
-void QCocoaMenuBar::resetKnownMenuItemsToQt()
-{
- // Undo the effect of redirectKnownMenuItemsToFirstResponder():
- // reset the menu items' target/action.
- foreach (QCocoaMenuBar *mb, static_menubars) {
- foreach (QCocoaMenu *m, mb->m_menus) {
- foreach (QCocoaMenuItem *i, m->items()) {
- if (i->effectiveRole() >= QPlatformMenuItem::ApplicationSpecificRole) {
- m->setItemTargetAction(i);
- }
- }
- }
- }
+ return nullptr;
}
void QCocoaMenuBar::updateMenuBarImmediately()
@@ -325,7 +271,7 @@ void QCocoaMenuBar::updateMenuBarImmediately()
QCocoaMenuBar *mb = findGlobalMenubar();
QCocoaWindow *cw = findWindowForMenubar();
- QWindow *win = cw ? cw->window() : 0;
+ QWindow *win = cw ? cw->window() : nullptr;
if (win && (win->flags() & Qt::Popup) == Qt::Popup) {
// context menus, comboboxes, etc. don't need to update the menubar,
// but if an application has only Qt::Tool window(s) on start,
@@ -353,7 +299,7 @@ void QCocoaMenuBar::updateMenuBarImmediately()
#endif
bool disableForModal = mb->shouldDisable(cw);
- foreach (QCocoaMenu *menu, mb->m_menus) {
+ for (auto menu : qAsConst(mb->m_menus)) {
if (!menu)
continue;
NSMenuItem *item = mb->nativeItemForMenu(menu);
@@ -368,16 +314,16 @@ void QCocoaMenuBar::updateMenuBarImmediately()
[loader ensureAppMenuInMenu:mb->nsMenu()];
NSMutableSet *mergedItems = [[NSMutableSet setWithCapacity:mb->merged().count()] retain];
- foreach (QCocoaMenuItem *m, mb->merged()) {
- [mergedItems addObject:m->nsItem()];
- m->syncMerged();
+ for (auto mergedItem : mb->merged()) {
+ [mergedItems addObject:mergedItem->nsItem()];
+ mergedItem->syncMerged();
}
// hide+disable all mergeable items we're not currently using
for (NSMenuItem *mergeable in [loader mergeable]) {
if (![mergedItems containsObject:mergeable]) {
- [mergeable setHidden:YES];
- [mergeable setEnabled:NO];
+ mergeable.hidden = YES;
+ mergeable.enabled = NO;
}
}
@@ -389,7 +335,7 @@ void QCocoaMenuBar::updateMenuBarImmediately()
QList<QCocoaMenuItem*> QCocoaMenuBar::merged() const
{
QList<QCocoaMenuItem*> r;
- foreach (QCocoaMenu* menu, m_menus)
+ for (auto menu : qAsConst(m_menus))
r.append(menu->merged());
return r;
@@ -409,11 +355,11 @@ bool QCocoaMenuBar::shouldDisable(QCocoaWindow *active) const
// When there is an application modal window on screen, the entries of
// the menubar should be disabled. The exception in Qt is that if the
// modal window is the only window on screen, then we enable the menu bar.
- foreach (QWindow *w, topWindows) {
- if (w->isVisible() && w->modality() == Qt::ApplicationModal) {
+ for (auto *window : qAsConst(topWindows)) {
+ if (window->isVisible() && window->modality() == Qt::ApplicationModal) {
// check for other visible windows
- foreach (QWindow *other, topWindows) {
- if ((w != other) && (other->isVisible())) {
+ for (auto *other : qAsConst(topWindows)) {
+ if ((window != other) && (other->isVisible())) {
// INVARIANT: we found another visible window
// on screen other than our modalWidget. We therefore
// disable the menu bar to follow normal modality logic:
@@ -433,21 +379,21 @@ bool QCocoaMenuBar::shouldDisable(QCocoaWindow *active) const
QPlatformMenu *QCocoaMenuBar::menuForTag(quintptr tag) const
{
- foreach (QCocoaMenu *menu, m_menus) {
+ for (auto menu : qAsConst(m_menus))
if (menu->tag() == tag)
return menu;
- }
- return 0;
+ return nullptr;
}
-NSMenuItem *QCocoaMenuBar::itemForRole(QPlatformMenuItem::MenuRole r)
+NSMenuItem *QCocoaMenuBar::itemForRole(QPlatformMenuItem::MenuRole role)
{
- foreach (QCocoaMenu *m, m_menus)
- foreach (QCocoaMenuItem *i, m->items())
- if (i->effectiveRole() == r)
- return i->nsItem();
- return nullptr;
+ for (auto menu : qAsConst(m_menus))
+ for (auto *item : menu->items())
+ if (item->effectiveRole() == role)
+ return item->nsItem();
+
+ return nil;
}
QCocoaWindow *QCocoaMenuBar::cocoaWindow() const
diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.h b/src/plugins/platforms/cocoa/qcocoamenuitem.h
index 2b598ee3a0..c842b08d52 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuitem.h
+++ b/src/plugins/platforms/cocoa/qcocoamenuitem.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author James Turner <james.turner@kdab.com>
** Contact: https://www.qt.io/licensing/
**
@@ -108,6 +108,7 @@ public:
QCocoaMenu *menu() const { return m_menu; }
MenuRole effectiveRole() const;
+ void resolveTargetAction();
private:
QString mergeText();
@@ -118,7 +119,6 @@ private:
QString m_text;
QIcon m_icon;
QPointer<QCocoaMenu> m_menu;
- QFont m_font;
MenuRole m_role;
MenuRole m_detectedRole;
#ifndef QT_NO_SHORTCUT
diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
index f8f9648822..e54b6284e5 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2018 The Qt Company Ltd.
** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author James Turner <james.turner@kdab.com>
** Contact: https://www.qt.io/licensing/
**
@@ -41,6 +42,7 @@
#include "qcocoamenuitem.h"
+#include "qcocoansmenu.h"
#include "qcocoamenu.h"
#include "qcocoamenubar.h"
#include "messages.h"
@@ -49,7 +51,6 @@
#include "qcocoaapplication.h" // for custom application category
#include "qcocoamenuloader.h"
#include <QtGui/private/qcoregraphics_p.h>
-#include <QtCore/qregularexpression.h>
#include <QtCore/QDebug>
@@ -60,13 +61,13 @@ static quint32 constructModifierMask(quint32 accel_key)
quint32 ret = 0;
const bool dontSwap = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta);
if ((accel_key & Qt::CTRL) == Qt::CTRL)
- ret |= (dontSwap ? NSControlKeyMask : NSCommandKeyMask);
+ ret |= (dontSwap ? NSEventModifierFlagControl : NSEventModifierFlagCommand);
if ((accel_key & Qt::META) == Qt::META)
- ret |= (dontSwap ? NSCommandKeyMask : NSControlKeyMask);
+ ret |= (dontSwap ? NSEventModifierFlagCommand : NSEventModifierFlagControl);
if ((accel_key & Qt::ALT) == Qt::ALT)
- ret |= NSAlternateKeyMask;
+ ret |= NSEventModifierFlagOption;
if ((accel_key & Qt::SHIFT) == Qt::SHIFT)
- ret |= NSShiftKeyMask;
+ ret |= NSEventModifierFlagShift;
return ret;
}
@@ -92,9 +93,9 @@ NSUInteger keySequenceModifierMask(const QKeySequence &accel)
#endif
QCocoaMenuItem::QCocoaMenuItem() :
- m_native(NULL),
+ m_native(nil),
m_itemView(nil),
- m_menu(NULL),
+ m_menu(nullptr),
m_role(NoRole),
m_iconSize(16),
m_textSynced(false),
@@ -112,9 +113,9 @@ QCocoaMenuItem::~QCocoaMenuItem()
QMacAutoReleasePool pool;
if (m_menu && m_menu->menuParent() == this)
- m_menu->setMenuParent(0);
+ m_menu->setMenuParent(nullptr);
if (m_merged) {
- [m_native setHidden:YES];
+ m_native.hidden = YES;
} else {
if (m_menu && m_menu->attachedItem() == m_native)
m_menu->setAttachedItem(nil);
@@ -140,7 +141,7 @@ void QCocoaMenuItem::setMenu(QPlatformMenu *menu)
return;
if (m_menu && m_menu->menuParent() == this) {
- m_menu->setMenuParent(0);
+ m_menu->setMenuParent(nullptr);
// Free the menu from its parent's influence
m_menu->propagateEnabledState(true);
if (m_native && m_menu->attachedItem() == m_native)
@@ -172,7 +173,7 @@ void QCocoaMenuItem::setIsSeparator(bool isSeparator)
void QCocoaMenuItem::setFont(const QFont &font)
{
- m_font = font;
+ Q_UNUSED(font)
}
void QCocoaMenuItem::setRole(MenuRole role)
@@ -210,82 +211,75 @@ void QCocoaMenuItem::setNativeContents(WId item)
return;
[m_itemView release];
m_itemView = [itemView retain];
- [m_itemView setAutoresizesSubviews:YES];
- [m_itemView setAutoresizingMask:NSViewWidthSizable];
- [m_itemView setHidden:NO];
- [m_itemView setNeedsDisplay:YES];
+ m_itemView.autoresizesSubviews = YES;
+ m_itemView.autoresizingMask = NSViewWidthSizable;
+ m_itemView.hidden = NO;
+ m_itemView.needsDisplay = YES;
}
NSMenuItem *QCocoaMenuItem::sync()
{
- if (m_isSeparator != [m_native isSeparatorItem]) {
+ if (m_isSeparator != m_native.separatorItem) {
[m_native release];
- if (m_isSeparator) {
- m_native = [[NSMenuItem separatorItem] retain];
- [m_native setTag:reinterpret_cast<NSInteger>(this)];
- } else
+ if (m_isSeparator)
+ m_native = [[QCocoaNSMenuItem separatorItemWithPlatformMenuItem:this] retain];
+ else
m_native = nil;
}
if ((m_role != NoRole && !m_textSynced) || m_merged) {
- NSMenuItem *mergeItem = nil;
+ QCocoaMenuBar *menubar = nullptr;
+ if (m_role == TextHeuristicRole) {
+ // Recognized menu roles are only found in the first menus below the menubar
+ QObject *p = menuParent();
+ int depth = 1;
+ while (depth < 3 && p && !(menubar = qobject_cast<QCocoaMenuBar *>(p))) {
+ ++depth;
+ QCocoaMenuObject *menuObject = dynamic_cast<QCocoaMenuObject *>(p);
+ Q_ASSERT(menuObject);
+ p = menuObject->menuParent();
+ }
+
+ if (menubar && depth < 3)
+ m_detectedRole = detectMenuRole(m_text);
+ else
+ m_detectedRole = NoRole;
+ }
+
QCocoaMenuLoader *loader = [QCocoaMenuLoader sharedMenuLoader];
- switch (m_role) {
- case ApplicationSpecificRole:
- mergeItem = [loader appSpecificMenuItem:reinterpret_cast<NSInteger>(this)];
- break;
+ NSMenuItem *mergeItem = nil;
+ const auto role = effectiveRole();
+ switch (role) {
case AboutRole:
mergeItem = [loader aboutMenuItem];
break;
case AboutQtRole:
mergeItem = [loader aboutQtMenuItem];
break;
+ case PreferencesRole:
+ mergeItem = [loader preferencesMenuItem];
+ break;
+ case ApplicationSpecificRole:
+ mergeItem = [loader appSpecificMenuItem:this];
+ break;
case QuitRole:
mergeItem = [loader quitMenuItem];
break;
- case PreferencesRole:
- mergeItem = [loader preferencesMenuItem];
+ case CutRole:
+ case CopyRole:
+ case PasteRole:
+ case SelectAllRole:
+ if (menubar)
+ mergeItem = menubar->itemForRole(role);
break;
- case TextHeuristicRole: {
- QObject *p = menuParent();
- int depth = 1;
- QCocoaMenuBar *menubar = 0;
- while (depth < 3 && p && !(menubar = qobject_cast<QCocoaMenuBar *>(p))) {
- ++depth;
- QCocoaMenuObject *menuObject = dynamic_cast<QCocoaMenuObject *>(p);
- Q_ASSERT(menuObject);
- p = menuObject->menuParent();
- }
- if (depth == 3 || !menubar)
- break; // Menu item too deep in the hierarchy, or not connected to any menubar
-
- m_detectedRole = detectMenuRole(m_text);
- switch (m_detectedRole) {
- case QPlatformMenuItem::AboutRole:
- if (m_text.indexOf(QRegularExpression(QString::fromLatin1("qt$"),
- QRegularExpression::CaseInsensitiveOption)) == -1)
- mergeItem = [loader aboutMenuItem];
- else
- mergeItem = [loader aboutQtMenuItem];
- break;
- case QPlatformMenuItem::PreferencesRole:
- mergeItem = [loader preferencesMenuItem];
- break;
- case QPlatformMenuItem::QuitRole:
- mergeItem = [loader quitMenuItem];
- break;
- default:
- if (m_detectedRole >= CutRole && m_detectedRole < RoleCount && menubar)
- mergeItem = menubar->itemForRole(m_detectedRole);
- if (!m_text.isEmpty())
- m_textSynced = true;
- break;
- }
+ case NoRole:
+ // The heuristic couldn't resolve the menu role
+ m_textSynced = false;
break;
- }
-
default:
- qWarning() << "Menu item" << m_text << "has unsupported role" << m_role;
+ if (!m_text.isEmpty())
+ m_textSynced = true;
+ break;
}
if (mergeItem) {
@@ -294,7 +288,8 @@ NSMenuItem *QCocoaMenuItem::sync()
[mergeItem retain];
[m_native release];
m_native = mergeItem;
- [m_native setTag:reinterpret_cast<NSInteger>(this)];
+ if (auto *nativeItem = qt_objc_cast<QCocoaNSMenuItem *>(m_native))
+ nativeItem.platformMenuItem = this;
} else if (m_merged) {
// was previously merged, but no longer
[m_native release];
@@ -306,14 +301,14 @@ NSMenuItem *QCocoaMenuItem::sync()
}
if (!m_native) {
- m_native = [[NSMenuItem alloc] initWithTitle:m_text.toNSString()
- action:nil
- keyEquivalent:@""];
- [m_native setTag:reinterpret_cast<NSInteger>(this)];
+ m_native = [[QCocoaNSMenuItem alloc] initWithPlatformMenuItem:this];
+ m_native.title = m_text.toNSString();
}
- [m_native setHidden: !m_isVisible];
- [m_native setView:m_itemView];
+ resolveTargetAction();
+
+ m_native.hidden = !m_isVisible;
+ m_native.view = m_itemView;
QString text = mergeText();
#ifndef QT_NO_SHORTCUT
@@ -324,46 +319,28 @@ NSMenuItem *QCocoaMenuItem::sync()
text += QLatin1String(" (") + accel.toString(QKeySequence::NativeText) + QLatin1String(")");
#endif
- QString finalString = QPlatformTheme::removeMnemonics(text);
- bool useAttributedTitle = false;
- // Cocoa Font and title
- if (m_font.resolve()) {
- NSFont *customMenuFont = [NSFont fontWithName:m_font.family().toNSString()
- size:m_font.pointSize()];
- if (customMenuFont) {
- NSArray *keys = [NSArray arrayWithObjects:NSFontAttributeName, nil];
- NSArray *objects = [NSArray arrayWithObjects:customMenuFont, nil];
- NSDictionary *attributes = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
- NSAttributedString *str = [[[NSAttributedString alloc] initWithString:finalString.toNSString()
- attributes:attributes] autorelease];
- [m_native setAttributedTitle: str];
- useAttributedTitle = true;
- }
- }
- if (!useAttributedTitle) {
- [m_native setTitle:finalString.toNSString()];
- }
+ m_native.title = QPlatformTheme::removeMnemonics(text).toNSString();
#ifndef QT_NO_SHORTCUT
if (accel.count() == 1) {
- [m_native setKeyEquivalent:keySequenceToKeyEqivalent(accel)];
- [m_native setKeyEquivalentModifierMask:keySequenceModifierMask(accel)];
+ m_native.keyEquivalent = keySequenceToKeyEqivalent(accel);
+ m_native.keyEquivalentModifierMask = keySequenceModifierMask(accel);
} else
#endif
{
- [m_native setKeyEquivalent:@""];
- [m_native setKeyEquivalentModifierMask:NSCommandKeyMask];
+ m_native.keyEquivalent = @"";
+ m_native.keyEquivalentModifierMask = NSEventModifierFlagCommand;
}
NSImage *img = nil;
if (!m_icon.isNull()) {
img = qt_mac_create_nsimage(m_icon, m_iconSize);
- [img setSize:NSMakeSize(m_iconSize, m_iconSize)];
+ img.size = CGSizeMake(m_iconSize, m_iconSize);
}
- [m_native setImage:img];
+ m_native.image = img;
[img release];
- [m_native setState:m_checked ? NSOnState : NSOffState];
+ m_native.state = m_checked ? NSOnState : NSOffState;
return m_native;
}
@@ -408,8 +385,8 @@ void QCocoaMenuItem::syncMerged()
qWarning("Trying to sync a non-merged item");
return;
}
- [m_native setTag:reinterpret_cast<NSInteger>(this)];
- [m_native setHidden: !m_isVisible];
+
+ m_native.hidden = !m_isVisible;
}
void QCocoaMenuItem::setParentEnabled(bool enabled)
@@ -434,4 +411,39 @@ void QCocoaMenuItem::setIconSize(int size)
m_iconSize = size;
}
+void QCocoaMenuItem::resolveTargetAction()
+{
+ if (m_native.separatorItem)
+ return;
+
+ // Some items created by QCocoaMenuLoader are not
+ // instances of QCocoaNSMenuItem and have their
+ // target/action set as Interface Builder would.
+ if (![m_native isMemberOfClass:[QCocoaNSMenuItem class]])
+ return;
+
+ // Use the responder chain and ensure native modal dialogs
+ // continue receiving cut/copy/paste/etc. key equivalents.
+ SEL roleAction;
+ switch (effectiveRole()) {
+ case CutRole:
+ roleAction = @selector(cut:);
+ break;
+ case CopyRole:
+ roleAction = @selector(copy:);
+ break;
+ case PasteRole:
+ roleAction = @selector(paste:);
+ break;
+ case SelectAllRole:
+ roleAction = @selector(selectAll:);
+ break;
+ default:
+ roleAction = @selector(qt_itemFired:);
+ }
+
+ m_native.action = roleAction;
+ m_native.target = nil;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoamenuloader.h b/src/plugins/platforms/cocoa/qcocoamenuloader.h
index 95f347646c..5e83327854 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuloader.h
+++ b/src/plugins/platforms/cocoa/qcocoamenuloader.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -54,42 +54,20 @@
#import <AppKit/AppKit.h>
#include <QtCore/private/qcore_mac_p.h>
-@interface QT_MANGLE_NAMESPACE(QCocoaMenuLoader) : NSResponder
-{
- IBOutlet NSMenu *theMenu;
- IBOutlet NSMenu *appMenu;
- IBOutlet NSMenuItem *quitItem;
- IBOutlet NSMenuItem *preferencesItem;
- IBOutlet NSMenuItem *aboutItem;
- IBOutlet NSMenuItem *aboutQtItem;
- IBOutlet NSMenuItem *hideItem;
- NSMenuItem *lastAppSpecificItem;
- NSMenuItem *servicesItem;
- NSMenuItem *hideAllOthersItem;
- NSMenuItem *showAllItem;
-}
+QT_FORWARD_DECLARE_CLASS(QCocoaMenuItem);
+
+@interface QT_MANGLE_NAMESPACE(QCocoaMenuLoader) : NSObject
+ (instancetype)sharedMenuLoader;
-- (instancetype)init;
-- (void)ensureAppMenuInMenu:(NSMenu *)menu;
-- (void)removeActionsFromAppMenu;
-- (NSMenu *)applicationMenu;
- (NSMenu *)menu;
+- (void)ensureAppMenuInMenu:(NSMenu *)menu;
- (NSMenuItem *)quitMenuItem;
- (NSMenuItem *)preferencesMenuItem;
- (NSMenuItem *)aboutMenuItem;
- (NSMenuItem *)aboutQtMenuItem;
- (NSMenuItem *)hideMenuItem;
-- (NSMenuItem *)appSpecificMenuItem:(NSInteger)tag;
-- (IBAction)terminate:(id)sender;
-- (IBAction)orderFrontStandardAboutPanel:(id)sender;
-- (IBAction)hideOtherApplications:(id)sender;
-- (IBAction)unhideAllApplications:(id)sender;
-- (IBAction)hide:(id)sender;
-- (IBAction)qtDispatcherToQPAMenuItem:(id)sender;
-- (void)orderFrontCharacterPalette:(id)sender;
-- (BOOL)validateMenuItem:(NSMenuItem*)menuItem;
+- (NSMenuItem *)appSpecificMenuItem:(QCocoaMenuItem *)platformItem;
- (void)qtTranslateApplicationMenu;
-- (NSArray *)mergeable;
+- (NSArray<NSMenuItem *> *)mergeable;
@end
QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuLoader);
diff --git a/src/plugins/platforms/cocoa/qcocoamenuloader.mm b/src/plugins/platforms/cocoa/qcocoamenuloader.mm
index 4432d3e27a..da0fc5c6a1 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuloader.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenuloader.mm
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -41,6 +41,7 @@
#include "messages.h"
#include "qcocoahelpers.h"
+#include "qcocoansmenu.h"
#include "qcocoamenubar.h"
#include "qcocoamenuitem.h"
#include "qcocoaintegration.h"
@@ -50,7 +51,19 @@
#include <QtCore/qcoreapplication.h>
#include <QtGui/private/qguiapplication_p.h>
-@implementation QCocoaMenuLoader
+@implementation QCocoaMenuLoader {
+ NSMenu *theMenu;
+ NSMenu *appMenu;
+ NSMenuItem *quitItem;
+ NSMenuItem *preferencesItem;
+ NSMenuItem *aboutItem;
+ NSMenuItem *aboutQtItem;
+ NSMenuItem *hideItem;
+ NSMenuItem *lastAppSpecificItem;
+ NSMenuItem *servicesItem;
+ NSMenuItem *hideAllOthersItem;
+ NSMenuItem *showAllItem;
+}
+ (instancetype)sharedMenuLoader
{
@@ -83,17 +96,19 @@
appItem.submenu = appMenu;
// About Application
- aboutItem = [[NSMenuItem alloc] initWithTitle:[@"About " stringByAppendingString:appName]
- action:@selector(orderFrontStandardAboutPanel:)
- keyEquivalent:@""];
+ aboutItem = [[QCocoaNSMenuItem alloc] init];
+ aboutItem.title = [@"About " stringByAppendingString:appName];
+ // FIXME This seems useless since barely adding a QAction
+ // with AboutRole role will reset the target/action
aboutItem.target = self;
+ aboutItem.action = @selector(orderFrontStandardAboutPanel:);
// Disable until a QAction is associated
aboutItem.enabled = NO;
aboutItem.hidden = YES;
[appMenu addItem:aboutItem];
// About Qt (shameless self-promotion)
- aboutQtItem = [[NSMenuItem alloc] init];
+ aboutQtItem = [[QCocoaNSMenuItem alloc] init];
aboutQtItem.title = @"About Qt";
// Disable until a QAction is associated
aboutQtItem.enabled = NO;
@@ -103,15 +118,19 @@
[appMenu addItem:[NSMenuItem separatorItem]];
// Preferences
- preferencesItem = [[NSMenuItem alloc] initWithTitle:@"Preferences…"
- action:@selector(qtDispatcherToQPAMenuItem:)
- keyEquivalent:@","];
- preferencesItem.target = self;
+ preferencesItem = [[QCocoaNSMenuItem alloc] init];
+ preferencesItem.title = @"Preferences…";
+ preferencesItem.keyEquivalent = @",";
// Disable until a QAction is associated
preferencesItem.enabled = NO;
preferencesItem.hidden = YES;
[appMenu addItem:preferencesItem];
+ // We'll be adding app specific items after this. The macOS HIG state that,
+ // "In general, a Preferences menu item should be the first app-specific menu item."
+ // https://developer.apple.com/macos/human-interface-guidelines/menus/menu-bar-menus/
+ lastAppSpecificItem = preferencesItem;
+
[appMenu addItem:[NSMenuItem separatorItem]];
// Services item and menu
@@ -136,7 +155,7 @@
action:@selector(hideOtherApplications:)
keyEquivalent:@"h"];
hideAllOthersItem.target = self;
- hideAllOthersItem.keyEquivalentModifierMask = NSCommandKeyMask | NSAlternateKeyMask;
+ hideAllOthersItem.keyEquivalentModifierMask = NSEventModifierFlagCommand | NSEventModifierFlagOption;
[appMenu addItem:hideAllOthersItem];
// Show All
@@ -149,10 +168,13 @@
[appMenu addItem:[NSMenuItem separatorItem]];
// Quit Application
- quitItem = [[NSMenuItem alloc] initWithTitle:[@"Quit " stringByAppendingString:appName]
- action:@selector(terminate:)
- keyEquivalent:@"q"];
- quitItem.target = self;
+ quitItem = [[QCocoaNSMenuItem alloc] init];
+ quitItem.title = [@"Quit " stringByAppendingString:appName];
+ quitItem.keyEquivalent = @"q";
+ // This will remain true until synced with a QCocoaMenuItem.
+ // This way, we will always have a functional Quit menu item
+ // even if no QAction is added.
+ quitItem.action = @selector(terminate:);
[appMenu addItem:quitItem];
}
@@ -184,7 +206,7 @@
// windows with different menu bars), we never recreate this menu, but
// instead pull it out the current menu bar and place into the new one:
NSMenu *mainMenu = [NSApp mainMenu];
- if ([NSApp mainMenu] == menu)
+ if (mainMenu == menu)
return; // nothing to do (menu is the current menu bar)!
#ifndef QT_NAMESPACE
@@ -205,17 +227,11 @@
unparentAppMenu(appMenu.supermenu);
NSMenuItem *appMenuItem = [[NSMenuItem alloc] initWithTitle:@"Apple"
- action:nil keyEquivalent:@""];
- [appMenuItem setSubmenu:appMenu];
+ action:nil keyEquivalent:@""];
+ appMenuItem.submenu = appMenu;
[menu insertItem:appMenuItem atIndex:0];
}
-- (void)removeActionsFromAppMenu
-{
- for (NSMenuItem *item in [appMenu itemArray])
- [item setTag:0];
-}
-
- (NSMenu *)menu
{
return [[theMenu retain] autorelease];
@@ -251,41 +267,32 @@
return [[hideItem retain] autorelease];
}
-- (NSMenuItem *)appSpecificMenuItem:(NSInteger)tag
+- (NSMenuItem *)appSpecificMenuItem:(QCocoaMenuItem *)platformItem
{
- NSMenuItem *item = [appMenu itemWithTag:tag];
-
- // No reason to create the item if it already exists. See QTBUG-27202.
- if (item)
- return [[item retain] autorelease];
+ // No reason to create the item if it already exists.
+ for (NSMenuItem *item in appMenu.itemArray)
+ if (qt_objc_cast<QCocoaNSMenuItem *>(item).platformMenuItem == platformItem)
+ return [[item retain] autorelease];
// Create an App-Specific menu item, insert it into the menu and return
// it as an autorelease item.
- item = [[NSMenuItem alloc] init];
+ QCocoaNSMenuItem *item;
+ if (platformItem->isSeparator())
+ item = [[QCocoaNSMenuItem separatorItemWithPlatformMenuItem:platformItem] retain];
+ else
+ item = [[QCocoaNSMenuItem alloc] initWithPlatformMenuItem:platformItem];
+
+ const auto location = [appMenu indexOfItem:lastAppSpecificItem];
- NSInteger location;
- if (lastAppSpecificItem == nil) {
- location = [appMenu indexOfItem:aboutQtItem];
- } else {
- location = [appMenu indexOfItem:lastAppSpecificItem];
+ if (!lastAppSpecificItem.separatorItem)
[lastAppSpecificItem release];
- }
lastAppSpecificItem = item; // Keep track of this for later (i.e., don't release it)
+
[appMenu insertItem:item atIndex:location + 1];
return [[item retain] autorelease];
}
-- (BOOL) acceptsFirstResponder
-{
- return YES;
-}
-
-- (void)terminate:(id)sender
-{
- [NSApp terminate:sender];
-}
-
- (void)orderFrontStandardAboutPanel:(id)sender
{
[NSApp orderFrontStandardAboutPanel:sender];
@@ -308,61 +315,36 @@
- (void)qtTranslateApplicationMenu
{
-
#ifndef QT_NO_TRANSLATION
- [servicesItem setTitle:qt_mac_applicationmenu_string(ServicesAppMenuItem).toNSString()];
- [hideItem setTitle:qt_mac_applicationmenu_string(HideAppMenuItem).arg(qt_mac_applicationName()).toNSString()];
- [hideAllOthersItem setTitle:qt_mac_applicationmenu_string(HideOthersAppMenuItem).toNSString()];
- [showAllItem setTitle:qt_mac_applicationmenu_string(ShowAllAppMenuItem).toNSString()];
- [preferencesItem setTitle:qt_mac_applicationmenu_string(PreferencesAppMenuItem).toNSString()];
- [quitItem setTitle:qt_mac_applicationmenu_string(QuitAppMenuItem).arg(qt_mac_applicationName()).toNSString()];
- [aboutItem setTitle:qt_mac_applicationmenu_string(AboutAppMenuItem).arg(qt_mac_applicationName()).toNSString()];
+ aboutItem.title = qt_mac_applicationmenu_string(AboutAppMenuItem).arg(qt_mac_applicationName()).toNSString();
+ preferencesItem.title = qt_mac_applicationmenu_string(PreferencesAppMenuItem).toNSString();
+ servicesItem.title = qt_mac_applicationmenu_string(ServicesAppMenuItem).toNSString();
+ hideItem.title = qt_mac_applicationmenu_string(HideAppMenuItem).arg(qt_mac_applicationName()).toNSString();
+ hideAllOthersItem.title = qt_mac_applicationmenu_string(HideOthersAppMenuItem).toNSString();
+ showAllItem.title = qt_mac_applicationmenu_string(ShowAllAppMenuItem).toNSString();
+ quitItem.title = qt_mac_applicationmenu_string(QuitAppMenuItem).arg(qt_mac_applicationName()).toNSString();
#endif
}
-- (IBAction)qtDispatcherToQPAMenuItem:(id)sender
-{
- NSMenuItem *item = static_cast<NSMenuItem *>(sender);
- if (item == quitItem) {
- // We got here because someone was once the quitItem, but it has been
- // abandoned (e.g., the menubar was deleted). In the meantime, just do
- // normal QApplication::quit().
- qApp->quit();
- return;
- }
-
- if ([item tag]) {
- QCocoaMenuItem *cocoaItem = reinterpret_cast<QCocoaMenuItem *>([item tag]);
- QScopedScopeLevelCounter scopeLevelCounter(QGuiApplicationPrivate::instance()->threadData);
- cocoaItem->activated();
- }
-}
-
-- (void)orderFrontCharacterPalette:(id)sender
-{
- [NSApp orderFrontCharacterPalette:sender];
-}
-
- (BOOL)validateMenuItem:(NSMenuItem*)menuItem
{
- if ([menuItem action] == @selector(hideOtherApplications:)
- || [menuItem action] == @selector(unhideAllApplications:)) {
+ if (menuItem.action == @selector(hideOtherApplications:)
+ || menuItem.action == @selector(unhideAllApplications:))
return [NSApp validateMenuItem:menuItem];
- } else if ([menuItem action] == @selector(hide:)) {
+
+ if (menuItem.action == @selector(hide:)) {
if (QCocoaIntegration::instance()->activePopupWindow())
return NO;
return [NSApp validateMenuItem:menuItem];
- } else if ([menuItem tag]) {
- QCocoaMenuItem *cocoaItem = reinterpret_cast<QCocoaMenuItem *>([menuItem tag]);
- return cocoaItem->isEnabled();
- } else {
- return [menuItem isEnabled];
}
+
+ return menuItem.enabled;
}
-- (NSArray*) mergeable
+- (NSArray<NSMenuItem *> *)mergeable
{
- // don't include the quitItem here, since we want it always visible and enabled regardless
+ // Don't include the quitItem here, since we want it always visible and enabled regardless
+ // Note that lastAppSpecificItem may be nil, so we can't use @[] here.
return [NSArray arrayWithObjects:preferencesItem, aboutItem, aboutQtItem, lastAppSpecificItem, nil];
}
diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
index 955b147bfd..7979e430ac 100644
--- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
+++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
@@ -71,6 +71,10 @@
#include <AppKit/AppKit.h>
+#if QT_CONFIG(vulkan)
+#include <MoltenVK/mvk_vulkan.h>
+#endif
+
QT_BEGIN_NAMESPACE
QCocoaNativeInterface::QCocoaNativeInterface()
@@ -81,31 +85,32 @@ QCocoaNativeInterface::QCocoaNativeInterface()
void *QCocoaNativeInterface::nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context)
{
if (!context)
- return 0;
+ return nullptr;
if (resourceString.toLower() == "nsopenglcontext")
return nsOpenGLContextForContext(context);
if (resourceString.toLower() == "cglcontextobj")
return cglContextForContext(context);
- return 0;
+ return nullptr;
}
#endif
void *QCocoaNativeInterface::nativeResourceForWindow(const QByteArray &resourceString, QWindow *window)
{
if (!window->handle())
- return 0;
+ return nullptr;
if (resourceString == "nsview") {
return static_cast<QCocoaWindow *>(window->handle())->m_view;
-#ifndef QT_NO_OPENGL
- } else if (resourceString == "nsopenglcontext") {
- return static_cast<QCocoaWindow *>(window->handle())->currentContext()->nsOpenGLContext();
-#endif
} else if (resourceString == "nswindow") {
return static_cast<QCocoaWindow *>(window->handle())->nativeWindow();
+#if QT_CONFIG(vulkan)
+ } else if (resourceString == "vkSurface") {
+ if (QVulkanInstance *instance = window->vulkanInstance())
+ return static_cast<QCocoaVulkanInstance *>(instance->handle())->createSurface(window);
+#endif
}
- return 0;
+ return nullptr;
}
QPlatformNativeInterface::NativeResourceForIntegrationFunction QCocoaNativeInterface::nativeResourceFunctionForIntegration(const QByteArray &resource)
@@ -143,7 +148,7 @@ QPlatformNativeInterface::NativeResourceForIntegrationFunction QCocoaNativeInter
if (resource.toLower() == "testcontentborderposition")
return NativeResourceForIntegrationFunction(QCocoaNativeInterface::testContentBorderPosition);
- return 0;
+ return nullptr;
}
QPlatformPrinterSupport *QCocoaNativeInterface::createPlatformPrinterSupport()
@@ -152,7 +157,7 @@ QPlatformPrinterSupport *QCocoaNativeInterface::createPlatformPrinterSupport()
return new QCocoaPrinterSupport();
#else
qFatal("Printing is not supported when Qt is configured with -no-widgets");
- return 0;
+ return nullptr;
#endif
}
@@ -166,7 +171,7 @@ void *QCocoaNativeInterface::NSPrintInfoForPrintEngine(QPrintEngine *printEngine
#else
Q_UNUSED(printEngine);
qFatal("Printing is not supported when Qt is configured with -no-widgets");
- return 0;
+ return nullptr;
#endif
}
@@ -180,10 +185,10 @@ QPixmap QCocoaNativeInterface::defaultBackgroundPixmapForQWizard()
CFURLRef url = (CFURLRef)CFArrayGetValueAtIndex(urls, 0);
QCFType<CFBundleRef> bundle = CFBundleCreate(kCFAllocatorDefault, url);
if (bundle) {
- url = CFBundleCopyResourceURL(bundle, CFSTR("Background"), CFSTR("png"), 0);
+ url = CFBundleCopyResourceURL(bundle, CFSTR("Background"), CFSTR("png"), nullptr);
if (url) {
- QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithURL(url, 0);
- QCFType<CGImageRef> image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0);
+ QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithURL(url, nullptr);
+ QCFType<CGImageRef> image = CGImageSourceCreateImageAtIndex(imageSource, 0, nullptr);
if (image) {
int width = CGImageGetWidth(image);
int height = CGImageGetHeight(image);
@@ -213,18 +218,16 @@ void *QCocoaNativeInterface::cglContextForContext(QOpenGLContext* context)
NSOpenGLContext *nsOpenGLContext = static_cast<NSOpenGLContext*>(nsOpenGLContextForContext(context));
if (nsOpenGLContext)
return [nsOpenGLContext CGLContextObj];
- return 0;
+ return nullptr;
}
void *QCocoaNativeInterface::nsOpenGLContextForContext(QOpenGLContext* context)
{
if (context) {
- QCocoaGLContext *cocoaGLContext = static_cast<QCocoaGLContext *>(context->handle());
- if (cocoaGLContext) {
- return cocoaGLContext->nsOpenGLContext();
- }
+ if (QCocoaGLContext *cocoaGLContext = static_cast<QCocoaGLContext *>(context->handle()))
+ return cocoaGLContext->nativeContext();
}
- return 0;
+ return nullptr;
}
#endif
@@ -256,7 +259,7 @@ void QCocoaNativeInterface::setDockMenu(QPlatformMenu *platformMenu)
QMacAutoReleasePool pool;
QCocoaMenu *cocoaPlatformMenu = static_cast<QCocoaMenu *>(platformMenu);
NSMenu *menu = cocoaPlatformMenu->nsMenu();
- [[QCocoaApplicationDelegate sharedDelegate] setDockMenu:menu];
+ [QCocoaApplicationDelegate sharedDelegate].dockMenu = menu;
}
void *QCocoaNativeInterface::qMenuToNSMenu(QPlatformMenu *platformMenu)
@@ -285,8 +288,9 @@ QImage QCocoaNativeInterface::cgImageToQImage(CGImageRef image)
void QCocoaNativeInterface::setEmbeddedInForeignView(QPlatformWindow *window, bool embedded)
{
+ Q_UNUSED(embedded); // "embedded" state is now automatically detected
QCocoaWindow *cocoaPlatformWindow = static_cast<QCocoaWindow *>(window);
- cocoaPlatformWindow->setEmbeddedInForeignView(embedded);
+ cocoaPlatformWindow->setEmbeddedInForeignView();
}
void QCocoaNativeInterface::registerTouchWindow(QWindow *window, bool enable)
diff --git a/src/plugins/platforms/cocoa/qcocoansmenu.h b/src/plugins/platforms/cocoa/qcocoansmenu.h
index a9c3e4fff9..6cbb6e4a01 100644
--- a/src/plugins/platforms/cocoa/qcocoansmenu.h
+++ b/src/plugins/platforms/cocoa/qcocoansmenu.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -53,12 +53,10 @@
#import <AppKit/AppKit.h>
-#include <QtCore/qpointer.h>
#include <qcocoahelpers.h>
QT_FORWARD_DECLARE_CLASS(QCocoaMenu);
-typedef QPointer<QCocoaMenu> QCocoaMenuPointer;
-
+QT_FORWARD_DECLARE_CLASS(QCocoaMenuItem);
@interface QT_MANGLE_NAMESPACE(QCocoaNSMenuDelegate) : NSObject <NSMenuDelegate>
@@ -72,18 +70,24 @@ typedef QPointer<QCocoaMenu> QCocoaMenuPointer;
@interface QT_MANGLE_NAMESPACE(QCocoaNSMenu) : NSMenu
-@property (readonly, nonatomic) QCocoaMenuPointer qpaMenu;
+@property (readonly, nonatomic) QCocoaMenu *platformMenu;
+
+- (instancetype)initWithPlatformMenu:(QCocoaMenu *)menu;
+
+@end
-- (instancetype)initWithQPAMenu:(QCocoaMenu *)menu;
+@interface QT_MANGLE_NAMESPACE(QCocoaNSMenuItem) : NSMenuItem
-- (void)qt_itemFired:(NSMenuItem *)item;
+@property (nonatomic) QCocoaMenuItem *platformMenuItem;
-- (BOOL)worksWhenModal;
-- (BOOL)validateMenuItem:(NSMenuItem*)item; // NSMenuValidation
++ (instancetype)separatorItemWithPlatformMenuItem:(QCocoaMenuItem *)menuItem;
+- (instancetype)initWithPlatformMenuItem:(QCocoaMenuItem *)menuItem;
+- (instancetype)init;
@end
QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaNSMenu);
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaNSMenuItem);
QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaNSMenuDelegate);
#endif // QCOCOANSMENU_H
diff --git a/src/plugins/platforms/cocoa/qcocoansmenu.mm b/src/plugins/platforms/cocoa/qcocoansmenu.mm
index 19a0f950e4..65b0832d9f 100644
--- a/src/plugins/platforms/cocoa/qcocoansmenu.mm
+++ b/src/plugins/platforms/cocoa/qcocoansmenu.mm
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -44,17 +44,15 @@
#include "qcocoawindow.h"
#import "qnsview.h"
-#include <QtCore/qmetaobject.h>
-#include <QtCore/private/qthread_p.h>
-#include <QtGui/private/qguiapplication_p.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qcoreevent.h>
-static NSString *qt_mac_removePrivateUnicode(NSString* string)
+static NSString *qt_mac_removePrivateUnicode(NSString *string)
{
- int len = [string length];
- if (len) {
- QVarLengthArray <unichar, 10> characters(len);
+ if (const int len = string.length) {
+ QVarLengthArray<unichar, 10> characters(len);
bool changed = false;
- for (int i = 0; i<len; i++) {
+ for (int i = 0; i < len; i++) {
characters[i] = [string characterAtIndex:i];
// check if they belong to key codes in private unicode range
// currently we need to handle only the NSDeleteFunctionKey
@@ -70,11 +68,14 @@ static NSString *qt_mac_removePrivateUnicode(NSString* string)
}
@implementation QCocoaNSMenu
+{
+ QPointer<QCocoaMenu> _platformMenu;
+}
-- (instancetype)initWithQPAMenu:(QCocoaMenu *)menu
+- (instancetype)initWithPlatformMenu:(QCocoaMenu *)menu
{
if ((self = [super initWithTitle:@"Untitled"])) {
- _qpaMenu = menu;
+ _platformMenu = menu;
self.autoenablesItems = YES;
self.delegate = [QCocoaNSMenuDelegate sharedMenuDelegate];
}
@@ -82,46 +83,58 @@ static NSString *qt_mac_removePrivateUnicode(NSString* string)
return self;
}
-// Cocoa will query the menu item's target for the worksWhenModal selector.
-// So we need to implement this to allow the items to be handled correctly
-// when a modal dialog is visible. See documentation for NSMenuItem.target.
-- (BOOL)worksWhenModal
+- (QCocoaMenu *)platformMenu
{
- if (!QGuiApplication::modalWindow())
- return YES;
- if (const auto *mb = qobject_cast<QCocoaMenuBar *>(self.qpaMenu->menuParent()))
- return QGuiApplication::modalWindow()->handle() == mb->cocoaWindow() ? YES : NO;
- return YES;
+ return _platformMenu.data();
}
-- (void)qt_itemFired:(NSMenuItem *)item
+@end
+
+@implementation QCocoaNSMenuItem
{
- auto *qpaItem = reinterpret_cast<QCocoaMenuItem *>(item.tag);
- // Menu-holding items also get a target to play nicely
- // with NSMenuValidation but should not trigger.
- if (!qpaItem || qpaItem->menu())
- return;
+ QPointer<QCocoaMenuItem> _platformMenuItem;
+}
- QScopedScopeLevelCounter scopeLevelCounter(QGuiApplicationPrivate::instance()->threadData);
- QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers:[NSEvent modifierFlags]];
++ (instancetype)separatorItemWithPlatformMenuItem:(QCocoaMenuItem *)menuItem
+{
+ // Safe because +[NSMenuItem separatorItem] invokes [[self alloc] init]
+ auto *item = qt_objc_cast<QCocoaNSMenuItem *>([self separatorItem]);
+ Q_ASSERT_X(item, qPrintable(__FUNCTION__),
+ "Did +[NSMenuItem separatorItem] not invoke [[self alloc] init]?");
+ if (item)
+ item.platformMenuItem = menuItem;
+
+ return item;
+}
- static QMetaMethod activatedSignal = QMetaMethod::fromSignal(&QCocoaMenuItem::activated);
- activatedSignal.invoke(qpaItem, Qt::QueuedConnection);
+- (instancetype)initWithPlatformMenuItem:(QCocoaMenuItem *)menuItem
+{
+ if ((self = [super initWithTitle:@"" action:nil keyEquivalent:@""])) {
+ _platformMenuItem = menuItem;
+ }
+
+ return self;
}
-- (BOOL)validateMenuItem:(NSMenuItem*)item
+- (instancetype)init
{
- auto *qpaItem = reinterpret_cast<QCocoaMenuItem *>(item.tag);
- // Menu-holding items are always enabled, as it's conventional in Cocoa
- if (!qpaItem || qpaItem->menu())
- return YES;
+ return [self initWithPlatformMenuItem:nullptr];
+}
- return qpaItem->isEnabled();
+- (QCocoaMenuItem *)platformMenuItem
+{
+ return _platformMenuItem.data();
+}
+
+- (void)setPlatformMenuItem:(QCocoaMenuItem *)menuItem
+{
+ _platformMenuItem = menuItem;
}
@end
-#define CHECK_MENU_CLASS(menu) Q_ASSERT([menu isMemberOfClass:[QCocoaNSMenu class]])
+#define CHECK_MENU_CLASS(menu) Q_ASSERT_X([menu isMemberOfClass:[QCocoaNSMenu class]], \
+ __FUNCTION__, "Menu is not a QCocoaNSMenu")
@implementation QCocoaNSMenuDelegate
@@ -153,14 +166,15 @@ static NSString *qt_mac_removePrivateUnicode(NSString* string)
if (shouldCancel)
return NO;
- const auto &qpaMenu = static_cast<QCocoaNSMenu *>(menu).qpaMenu;
- if (qpaMenu.isNull())
+ const auto &platformMenu = static_cast<QCocoaNSMenu *>(menu).platformMenu;
+ if (!platformMenu)
return YES;
- auto *menuItem = reinterpret_cast<QCocoaMenuItem *>(item.tag);
- if (qpaMenu->items().contains(menuItem)) {
- if (QCocoaMenu *itemSubmenu = menuItem->menu())
- itemSubmenu->setAttachedItem(item);
+ if (auto *platformItem = qt_objc_cast<QCocoaNSMenuItem *>(item).platformMenuItem) {
+ if (platformMenu->items().contains(platformItem)) {
+ if (auto *itemSubmenu = platformItem->menu())
+ itemSubmenu->setAttachedItem(item);
+ }
}
return YES;
@@ -169,32 +183,31 @@ static NSString *qt_mac_removePrivateUnicode(NSString* string)
- (void)menu:(NSMenu *)menu willHighlightItem:(NSMenuItem *)item
{
CHECK_MENU_CLASS(menu);
- auto *qpaItem = reinterpret_cast<QCocoaMenuItem *>(item.tag);
- if (qpaItem)
- qpaItem->hovered();
+ if (auto *platformItem = qt_objc_cast<QCocoaNSMenuItem *>(item).platformMenuItem)
+ emit platformItem->hovered();
}
- (void)menuWillOpen:(NSMenu *)menu
{
CHECK_MENU_CLASS(menu);
- const auto &qpaMenu = static_cast<QCocoaNSMenu *>(menu).qpaMenu;
- if (qpaMenu.isNull())
+ auto *platformMenu = static_cast<QCocoaNSMenu *>(menu).platformMenu;
+ if (!platformMenu)
return;
- qpaMenu->setIsOpen(true);
- emit qpaMenu->aboutToShow();
+ platformMenu->setIsOpen(true);
+ emit platformMenu->aboutToShow();
}
- (void)menuDidClose:(NSMenu *)menu
{
CHECK_MENU_CLASS(menu);
- const auto &qpaMenu = static_cast<QCocoaNSMenu *>(menu).qpaMenu;
- if (qpaMenu.isNull())
+ auto *platformMenu = static_cast<QCocoaNSMenu *>(menu).platformMenu;
+ if (!platformMenu)
return;
- qpaMenu->setIsOpen(false);
+ platformMenu->setIsOpen(false);
// wrong, but it's the best we can do
- emit qpaMenu->aboutToHide();
+ emit platformMenu->aboutToHide();
}
- (BOOL)menuHasKeyEquivalent:(NSMenu *)menu forEvent:(NSEvent *)event target:(id *)target action:(SEL *)action
@@ -212,7 +225,8 @@ static NSString *qt_mac_removePrivateUnicode(NSString* string)
CHECK_MENU_CLASS(menu);
// Interested only in Shift, Cmd, Ctrl & Alt Keys, so ignoring masks like, Caps lock, Num Lock ...
- static const NSUInteger mask = NSShiftKeyMask | NSControlKeyMask | NSCommandKeyMask | NSAlternateKeyMask;
+ static const NSUInteger mask = NSEventModifierFlagShift | NSEventModifierFlagControl
+ | NSEventModifierFlagCommand | NSEventModifierFlagOption;
// Change the private unicode keys to the ones used in setting the "Key Equivalents"
NSString *characters = qt_mac_removePrivateUnicode(event.charactersIgnoringModifiers);
@@ -229,30 +243,17 @@ static NSString *qt_mac_removePrivateUnicode(NSString* string)
}
if (keyEquivalentItem) {
- if (!keyEquivalentItem.target) {
- // This item was modified by QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder
- // and it looks like we're running a modal session for NSOpenPanel/NSSavePanel.
- // QCocoaFileDialogHelper is actually the only place we use this and we run NSOpenPanel modal
- // (modal sheet, window modal, application modal).
- // Whatever the current first responder is, let's give it a chance
- // and do not touch the Qt's focusObject (which is different from some native view
- // having a focus inside NSSave/OpenPanel.
- *target = nil;
- *action = keyEquivalentItem.action;
- return YES;
- }
-
QObject *object = qApp->focusObject();
if (object) {
QChar ch;
int keyCode;
- ulong nativeModifiers = [event modifierFlags];
- Qt::KeyboardModifiers modifiers = [QNSView convertKeyModifiers: nativeModifiers];
- NSString *charactersIgnoringModifiers = [event charactersIgnoringModifiers];
- NSString *characters = [event characters];
+ ulong nativeModifiers = event.modifierFlags;
+ Qt::KeyboardModifiers modifiers = [QNSView convertKeyModifiers:nativeModifiers];
+ NSString *charactersIgnoringModifiers = event.charactersIgnoringModifiers;
+ NSString *characters = event.characters;
- if ([charactersIgnoringModifiers length] > 0) { // convert the first character into a key code
- if ((modifiers & Qt::ControlModifier) && ([characters length] != 0)) {
+ if (charactersIgnoringModifiers.length > 0) { // convert the first character into a key code
+ if ((modifiers & Qt::ControlModifier) && characters.length > 0) {
ch = QChar([characters characterAtIndex:0]);
} else {
ch = QChar([charactersIgnoringModifiers characterAtIndex:0]);
@@ -269,7 +270,7 @@ static NSString *qt_mac_removePrivateUnicode(NSString* string)
accel_ev.ignore();
QCoreApplication::sendEvent(object, &accel_ev);
if (accel_ev.isAccepted()) {
- [[NSApp keyWindow] sendEvent: event];
+ [[NSApp keyWindow] sendEvent:event];
*target = nil;
*action = nil;
return YES;
diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm
index 0c54a3b771..7605dc9d1a 100644
--- a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm
+++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm
@@ -69,17 +69,17 @@ static QPrint::DuplexMode macToDuplexMode(const PMDuplexMode &mode)
QCocoaPrintDevice::QCocoaPrintDevice()
: QPlatformPrintDevice(),
- m_printer(0),
- m_session(0),
- m_ppd(0)
+ m_printer(nullptr),
+ m_session(nullptr),
+ m_ppd(nullptr)
{
}
QCocoaPrintDevice::QCocoaPrintDevice(const QString &id)
: QPlatformPrintDevice(id),
- m_printer(0),
- m_session(0),
- m_ppd(0)
+ m_printer(nullptr),
+ m_session(nullptr),
+ m_ppd(nullptr)
{
if (!id.isEmpty()) {
m_printer = PMPrinterCreateFromPrinterID(id.toCFString());
@@ -413,7 +413,7 @@ QPrint::ColorMode QCocoaPrintDevice::defaultColorMode() const
ppd_option_t *colorModel = ppdFindOption(m_ppd, "DefaultColorModel");
if (!colorModel)
colorModel = ppdFindOption(m_ppd, "ColorModel");
- if (!colorModel || (colorModel && !qstrcmp(colorModel->defchoice, "Gray")))
+ if (!colorModel || qstrcmp(colorModel->defchoice, "Gray") != 0)
return QPrint::Color;
}
return QPrint::GrayScale;
@@ -447,11 +447,11 @@ bool QCocoaPrintDevice::openPpdFile()
{
if (m_ppd)
ppdClose(m_ppd);
- m_ppd = 0;
- CFURLRef ppdURL = NULL;
+ m_ppd = nullptr;
+ CFURLRef ppdURL = nullptr;
char ppdPath[MAXPATHLEN];
if (PMPrinterCopyDescriptionURL(m_printer, kPMPPDDescriptionType, &ppdURL) == noErr
- && ppdURL != NULL) {
+ && ppdURL) {
if (CFURLGetFileSystemRepresentation(ppdURL, true, (UInt8*)ppdPath, sizeof(ppdPath)))
m_ppd = ppdOpenFile(ppdPath);
CFRelease(ppdURL);
@@ -474,7 +474,7 @@ PMPaper QCocoaPrintDevice::macPaper(const QPageSize &pageSize) const
if (m_macPapers.contains(pageSize.key()))
return m_macPapers.value(pageSize.key());
// For any other page size, whether custom or just unsupported, needs to be a custom PMPaper
- PMPaper paper = 0;
+ PMPaper paper = nullptr;
PMPaperMargins paperMargins;
paperMargins.left = m_customMargins.left();
paperMargins.right = m_customMargins.right();
diff --git a/src/plugins/platforms/cocoa/qcocoascreen.h b/src/plugins/platforms/cocoa/qcocoascreen.h
index 3d59c3de79..9ded98df32 100644
--- a/src/plugins/platforms/cocoa/qcocoascreen.h
+++ b/src/plugins/platforms/cocoa/qcocoascreen.h
@@ -75,7 +75,11 @@ public:
// Additional methods
void setVirtualSiblings(const QList<QPlatformScreen *> &siblings) { m_siblings = siblings; }
NSScreen *nativeScreen() const;
- void updateGeometry();
+ void updateProperties();
+
+ void requestUpdate();
+ void deliverUpdateRequests();
+ bool isRunningDisplayLink() const;
static QCocoaScreen *primaryScreen();
@@ -96,6 +100,10 @@ public:
QSizeF m_physicalSize;
QCocoaCursor *m_cursor;
QList<QPlatformScreen *> m_siblings;
+
+ CVDisplayLinkRef m_displayLink = nullptr;
+ dispatch_source_t m_displayLinkSource = nullptr;
+ QAtomicInt m_pendingUpdates;
};
#ifndef QT_NO_DEBUG_STREAM
@@ -104,5 +112,9 @@ QDebug operator<<(QDebug debug, const QCocoaScreen *screen);
QT_END_NAMESPACE
+@interface NSScreen (QtExtras)
+@property(readonly) CGDirectDisplayID qt_displayId;
+@end
+
#endif
diff --git a/src/plugins/platforms/cocoa/qcocoascreen.mm b/src/plugins/platforms/cocoa/qcocoascreen.mm
index 3e8261dfc2..f82ef202b1 100644
--- a/src/plugins/platforms/cocoa/qcocoascreen.mm
+++ b/src/plugins/platforms/cocoa/qcocoascreen.mm
@@ -47,6 +47,10 @@
#include <IOKit/graphics/IOGraphicsLib.h>
+#include <QtGui/private/qwindow_p.h>
+
+#include <QtCore/private/qeventdispatcher_cf_p.h>
+
QT_BEGIN_NAMESPACE
class QCoreTextFontEngine;
@@ -55,18 +59,22 @@ class QFontEngineFT;
QCocoaScreen::QCocoaScreen(int screenIndex)
: QPlatformScreen(), m_screenIndex(screenIndex), m_refreshRate(60.0)
{
- updateGeometry();
+ updateProperties();
m_cursor = new QCocoaCursor;
}
QCocoaScreen::~QCocoaScreen()
{
delete m_cursor;
+
+ CVDisplayLinkRelease(m_displayLink);
+ if (m_displayLinkSource)
+ dispatch_release(m_displayLinkSource);
}
NSScreen *QCocoaScreen::nativeScreen() const
{
- NSArray *screens = [NSScreen screens];
+ NSArray<NSScreen *> *screens = [NSScreen screens];
// Stale reference, screen configuration has changed
if (m_screenIndex < 0 || (NSUInteger)m_screenIndex >= [screens count])
@@ -107,12 +115,17 @@ static QString displayName(CGDirectDisplayID displayID)
return QString();
}
-void QCocoaScreen::updateGeometry()
+void QCocoaScreen::updateProperties()
{
NSScreen *nsScreen = nativeScreen();
if (!nsScreen)
return;
+ const QRect previousGeometry = m_geometry;
+ const QRect previousAvailableGeometry = m_availableGeometry;
+ const QDpi previousLogicalDpi = m_logicalDpi;
+ const qreal previousRefreshRate = m_refreshRate;
+
// The reference screen for the geometry is always the primary screen
QRectF primaryScreenGeometry = QRectF::fromCGRect([[NSScreen screens] firstObject].frame);
m_geometry = qt_mac_flip(QRectF::fromCGRect(nsScreen.frame), primaryScreenGeometry).toRect();
@@ -121,8 +134,7 @@ void QCocoaScreen::updateGeometry()
m_format = QImage::Format_RGB32;
m_depth = NSBitsPerPixelFromDepth([nsScreen depth]);
- NSDictionary *devDesc = [nsScreen deviceDescription];
- CGDirectDisplayID dpy = [[devDesc objectForKey:@"NSScreenNumber"] unsignedIntValue];
+ CGDirectDisplayID dpy = nsScreen.qt_displayId;
CGSize size = CGDisplayScreenSize(dpy);
m_physicalSize = QSizeF(size.width, size.height);
m_logicalDpi.first = 72;
@@ -135,25 +147,230 @@ void QCocoaScreen::updateGeometry()
m_name = displayName(dpy);
- QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry());
- QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen(), m_logicalDpi.first, m_logicalDpi.second);
- QWindowSystemInterface::handleScreenRefreshRateChange(screen(), m_refreshRate);
-
- // When a screen changes its geometry, AppKit will send us a NSWindowDidMoveNotification
- // for each window, resulting in calls to handleGeometryChange(), but this happens before
- // the NSApplicationDidChangeScreenParametersNotification, so when we map the new geometry
- // (which is correct at that point) to the screen using QCocoaScreen::mapFromNative(), we
- // end up using the stale screen geometry, and the new window geometry we report is wrong.
- // To make sure we finally report the correct window geometry, we need to do another pass
- // of geometry reporting, now that the screen properties have been updates. FIXME: Ideally
- // this would be solved by not caching the screen properties in QCocoaScreen, but that
- // requires more research.
- for (QWindow *window : windows()) {
- if (QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow*>(window->handle()))
- cocoaWindow->handleGeometryChange();
+ const bool didChangeGeometry = m_geometry != previousGeometry || m_availableGeometry != previousAvailableGeometry;
+
+ if (didChangeGeometry)
+ QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry());
+ if (m_logicalDpi != previousLogicalDpi)
+ QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen(), m_logicalDpi.first, m_logicalDpi.second);
+ if (m_refreshRate != previousRefreshRate)
+ QWindowSystemInterface::handleScreenRefreshRateChange(screen(), m_refreshRate);
+
+ qCDebug(lcQpaScreen) << "Updated properties for" << this;
+
+ if (didChangeGeometry) {
+ // When a screen changes its geometry, AppKit will send us a NSWindowDidMoveNotification
+ // for each window, resulting in calls to handleGeometryChange(), but this happens before
+ // the NSApplicationDidChangeScreenParametersNotification, so when we map the new geometry
+ // (which is correct at that point) to the screen using QCocoaScreen::mapFromNative(), we
+ // end up using the stale screen geometry, and the new window geometry we report is wrong.
+ // To make sure we finally report the correct window geometry, we need to do another pass
+ // of geometry reporting, now that the screen properties have been updates. FIXME: Ideally
+ // this would be solved by not caching the screen properties in QCocoaScreen, but that
+ // requires more research.
+ for (QWindow *window : windows()) {
+ if (QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow*>(window->handle()))
+ cocoaWindow->handleGeometryChange();
+ }
+ }
+}
+
+// ----------------------- Display link -----------------------
+
+Q_LOGGING_CATEGORY(lcQpaScreenUpdates, "qt.qpa.screen.updates", QtCriticalMsg);
+
+void QCocoaScreen::requestUpdate()
+{
+ if (!m_displayLink) {
+ CVDisplayLinkCreateWithCGDisplay(nativeScreen().qt_displayId, &m_displayLink);
+ CVDisplayLinkSetOutputCallback(m_displayLink, [](CVDisplayLinkRef, const CVTimeStamp*,
+ const CVTimeStamp*, CVOptionFlags, CVOptionFlags*, void* displayLinkContext) -> int {
+ // FIXME: It would be nice if update requests would include timing info
+ static_cast<QCocoaScreen*>(displayLinkContext)->deliverUpdateRequests();
+ return kCVReturnSuccess;
+ }, this);
+ qCDebug(lcQpaScreenUpdates) << "Display link created for" << this;
+
+ // During live window resizing -[NSWindow _resizeWithEvent:] will spin a local event loop
+ // in event-tracking mode, dequeuing only the mouse drag events needed to update the window's
+ // frame. It will repeatedly spin this loop until no longer receiving any mouse drag events,
+ // and will then update the frame (effectively coalescing/compressing the events). Unfortunately
+ // the events are pulled out using -[NSApplication nextEventMatchingEventMask:untilDate:inMode:dequeue:]
+ // which internally uses CFRunLoopRunSpecific, so the event loop will also process GCD queues and other
+ // runloop sources that have been added to the tracking mode. This includes the GCD display-link
+ // source that we use to marshal the display-link callback over to the main thread. If the
+ // subsequent delivery of the update-request on the main thread stalls due to inefficient
+ // user code, the NSEventThread will have had time to deliver additional mouse drag events,
+ // and the logic in -[NSWindow _resizeWithEvent:] will keep on compressing events and never
+ // get to the point of actually updating the window frame, making it seem like the window
+ // is stuck in its original size. Only when the user stops moving their mouse, and the event
+ // queue is completely drained of drag events, will the window frame be updated.
+
+ // By keeping an event tap listening for drag events, registered as a version 1 runloop source,
+ // we prevent the GCD source from being prioritized, giving the resize logic enough time
+ // to finish coalescing the events. This is incidental, but conveniently gives us the behavior
+ // we are looking for, interleaving display-link updates and resize events.
+ static CFMachPortRef eventTap = []() {
+ CFMachPortRef eventTap = CGEventTapCreateForPid(getpid(), kCGTailAppendEventTap,
+ kCGEventTapOptionListenOnly, NSEventMaskLeftMouseDragged,
+ [](CGEventTapProxy, CGEventType type, CGEventRef event, void *) -> CGEventRef {
+ if (type == kCGEventTapDisabledByTimeout)
+ qCWarning(lcQpaScreenUpdates) << "Event tap disabled due to timeout!";
+ return event; // Listen only tap, so what we return doesn't really matter
+ }, nullptr);
+ CGEventTapEnable(eventTap, false); // Event taps are normally enabled when created
+ static CFRunLoopSourceRef runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
+
+ NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+ [center addObserverForName:NSWindowWillStartLiveResizeNotification object:nil queue:nil
+ usingBlock:^(NSNotification *notification) {
+ qCDebug(lcQpaScreenUpdates) << "Live resize of" << notification.object
+ << "started. Enabling event tap";
+ CGEventTapEnable(eventTap, true);
+ }];
+ [center addObserverForName:NSWindowDidEndLiveResizeNotification object:nil queue:nil
+ usingBlock:^(NSNotification *notification) {
+ qCDebug(lcQpaScreenUpdates) << "Live resize of" << notification.object
+ << "ended. Disabling event tap";
+ CGEventTapEnable(eventTap, false);
+ }];
+ return eventTap;
+ }();
+ Q_UNUSED(eventTap);
+ }
+
+ if (!CVDisplayLinkIsRunning(m_displayLink)) {
+ qCDebug(lcQpaScreenUpdates) << "Starting display link for" << this;
+ CVDisplayLinkStart(m_displayLink);
+ }
+}
+
+// Helper to allow building up debug output in multiple steps
+struct DeferredDebugHelper
+{
+ DeferredDebugHelper(const QLoggingCategory &cat) {
+ if (cat.isDebugEnabled())
+ debug = new QDebug(QMessageLogger().debug(cat).nospace());
+ }
+ ~DeferredDebugHelper() {
+ flushOutput();
+ }
+ void flushOutput() {
+ if (debug) {
+ delete debug;
+ debug = nullptr;
+ }
+ }
+ QDebug *debug = nullptr;
+};
+
+#define qDeferredDebug(helper) if (Q_UNLIKELY(helper.debug)) *helper.debug
+
+void QCocoaScreen::deliverUpdateRequests()
+{
+ if (!QGuiApplication::instance())
+ return;
+
+ // The CVDisplayLink callback is a notification that it's a good time to produce a new frame.
+ // Since the callback is delivered on a separate thread we have to marshal it over to the
+ // main thread, as Qt requires update requests to be delivered there. This needs to happen
+ // asynchronously, as otherwise we may end up deadlocking if the main thread calls back
+ // into any of the CVDisplayLink APIs.
+ if (QThread::currentThread() != QGuiApplication::instance()->thread()) {
+ // We're explicitly not using the data of the GCD source to track the pending updates,
+ // as the data isn't reset to 0 until after the event handler, and also doesn't update
+ // during the event handler, both of which we need to track late frames.
+ const int pendingUpdates = ++m_pendingUpdates;
+
+ DeferredDebugHelper screenUpdates(lcQpaScreenUpdates());
+ qDeferredDebug(screenUpdates) << "display link callback for screen " << m_screenIndex;
+
+ if (const int framesAheadOfDelivery = pendingUpdates - 1) {
+ // If we have more than one update pending it means that a previous display link callback
+ // has not been fully processed on the main thread, either because GCD hasn't delivered
+ // it on the main thread yet, because the processing of the update request is taking
+ // too long, or because the update request was deferred due to window live resizing.
+ qDeferredDebug(screenUpdates) << ", " << framesAheadOfDelivery << " frame(s) ahead";
+
+ // We skip the frame completely if we're live-resizing, to not put any extra
+ // strain on the main thread runloop. Otherwise we assume we should push frames
+ // as fast as possible, and hopefully the callback will be delivered on the
+ // main thread just when the previous finished.
+ if (qt_apple_sharedApplication().keyWindow.inLiveResize) {
+ qDeferredDebug(screenUpdates) << "; waiting for main thread to catch up";
+ return;
+ }
+ }
+
+ qDeferredDebug(screenUpdates) << "; signaling dispatch source";
+
+ if (!m_displayLinkSource) {
+ m_displayLinkSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_main_queue());
+ dispatch_source_set_event_handler(m_displayLinkSource, ^{
+ deliverUpdateRequests();
+ });
+ dispatch_resume(m_displayLinkSource);
+ }
+
+ dispatch_source_merge_data(m_displayLinkSource, 1);
+
+ } else {
+ DeferredDebugHelper screenUpdates(lcQpaScreenUpdates());
+ qDeferredDebug(screenUpdates) << "gcd event handler on main thread";
+
+ const int pendingUpdates = m_pendingUpdates;
+ if (pendingUpdates > 1)
+ qDeferredDebug(screenUpdates) << ", " << (pendingUpdates - 1) << " frame(s) behind display link";
+
+ screenUpdates.flushOutput();
+
+ bool pauseUpdates = true;
+
+ auto windows = QGuiApplication::allWindows();
+ for (int i = 0; i < windows.size(); ++i) {
+ QWindow *window = windows.at(i);
+ QPlatformWindow *platformWindow = window->handle();
+ if (!platformWindow)
+ continue;
+
+ if (!platformWindow->hasPendingUpdateRequest())
+ continue;
+
+ if (window->screen() != screen())
+ continue;
+
+ // Skip windows that are not doing update requests via display link
+ if (!(window->format().swapInterval() > 0))
+ continue;
+
+ platformWindow->deliverUpdateRequest();
+
+ // Another update request was triggered, keep the display link running
+ if (platformWindow->hasPendingUpdateRequest())
+ pauseUpdates = false;
+ }
+
+ if (pauseUpdates) {
+ // Pause the display link if there are no pending update requests
+ qCDebug(lcQpaScreenUpdates) << "Stopping display link for" << this;
+ CVDisplayLinkStop(m_displayLink);
+ }
+
+ if (const int missedUpdates = m_pendingUpdates.fetchAndStoreRelaxed(0) - pendingUpdates) {
+ qCWarning(lcQpaScreenUpdates) << "main thread missed" << missedUpdates
+ << "update(s) from display link during update request delivery";
+ }
}
}
+bool QCocoaScreen::isRunningDisplayLink() const
+{
+ return m_displayLink && CVDisplayLinkIsRunning(m_displayLink);
+}
+
+// -----------------------------------------------------------
+
qreal QCocoaScreen::devicePixelRatio() const
{
QMacAutoReleasePool pool;
@@ -179,7 +396,7 @@ QWindow *QCocoaScreen::topLevelAt(const QPoint &point) const
// belowWindowWithWindowNumber] may return windows that are not interesting
// to Qt. The search iterates until a suitable window or no window is found.
NSInteger topWindowNumber = 0;
- QWindow *window = 0;
+ QWindow *window = nullptr;
do {
// Get the top-most window, below any previously rejected window.
topWindowNumber = [NSWindow windowNumberAtPoint:screenPoint
@@ -187,7 +404,7 @@ QWindow *QCocoaScreen::topLevelAt(const QPoint &point) const
// Continue the search if the window does not belong to this process.
NSWindow *nsWindow = [NSApp windowWithWindowNumber:topWindowNumber];
- if (nsWindow == 0)
+ if (!nsWindow)
continue;
// Continue the search if the window does not belong to Qt.
@@ -324,3 +541,12 @@ QDebug operator<<(QDebug debug, const QCocoaScreen *screen)
#endif // !QT_NO_DEBUG_STREAM
QT_END_NAMESPACE
+
+@implementation NSScreen (QtExtras)
+
+- (CGDirectDisplayID)qt_displayId
+{
+ return [self.deviceDescription[@"NSScreenNumber"] unsignedIntValue];
+}
+
+@end
diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
index bad91a2d5d..aef2c6cf48 100644
--- a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
+++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
@@ -45,6 +45,16 @@
#include <QtGui/qfont.h>
#include <QtGui/private/qcoregraphics_p.h>
+#if !QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
+@interface NSColor (MojaveForwardDeclarations)
+@property (class, strong, readonly) NSColor *selectedContentBackgroundColor NS_AVAILABLE_MAC(10_14);
+@property (class, strong, readonly) NSColor *unemphasizedSelectedTextBackgroundColor NS_AVAILABLE_MAC(10_14);
+@property (class, strong, readonly) NSColor *unemphasizedSelectedTextColor NS_AVAILABLE_MAC(10_14);
+@property (class, strong, readonly) NSColor *unemphasizedSelectedContentBackgroundColor NS_AVAILABLE_MAC(10_14);
+@property (class, strong, readonly) NSArray<NSColor *> *alternatingContentBackgroundColors NS_AVAILABLE_MAC(10_14);
+@end
+#endif
+
QT_BEGIN_NAMESPACE
QPalette * qt_mac_createSystemPalette()
@@ -65,18 +75,26 @@ QPalette * qt_mac_createSystemPalette()
palette->setBrush(QPalette::Disabled, QPalette::Text, dark);
palette->setBrush(QPalette::Disabled, QPalette::ButtonText, dark);
palette->setBrush(QPalette::Disabled, QPalette::Base, backgroundBrush);
+ QBrush textBackgroundBrush = qt_mac_toQBrush([NSColor textBackgroundColor]);
+ palette->setBrush(QPalette::Active, QPalette::Base, textBackgroundBrush);
+ palette->setBrush(QPalette::Inactive, QPalette::Base, textBackgroundBrush);
palette->setColor(QPalette::Disabled, QPalette::Dark, QColor(191, 191, 191));
palette->setColor(QPalette::Active, QPalette::Dark, QColor(191, 191, 191));
palette->setColor(QPalette::Inactive, QPalette::Dark, QColor(191, 191, 191));
// System palette initialization:
- palette->setBrush(QPalette::Active, QPalette::Highlight,
- qt_mac_toQBrush([NSColor selectedControlColor]));
- QBrush br = qt_mac_toQBrush([NSColor secondarySelectedControlColor]);
- palette->setBrush(QPalette::Inactive, QPalette::Highlight, br);
- palette->setBrush(QPalette::Disabled, QPalette::Highlight, br);
+ QBrush br = qt_mac_toQBrush([NSColor selectedControlColor]);
+ palette->setBrush(QPalette::Active, QPalette::Highlight, br);
+ if (__builtin_available(macOS 10.14, *)) {
+ const auto inactiveHighlight = qt_mac_toQBrush([NSColor unemphasizedSelectedContentBackgroundColor]);
+ palette->setBrush(QPalette::Inactive, QPalette::Highlight, inactiveHighlight);
+ palette->setBrush(QPalette::Disabled, QPalette::Highlight, inactiveHighlight);
+ } else {
+ palette->setBrush(QPalette::Inactive, QPalette::Highlight, br);
+ palette->setBrush(QPalette::Disabled, QPalette::Highlight, br);
+ }
- palette->setBrush(QPalette::Shadow, background.darker(170));
+ palette->setBrush(QPalette::Shadow, qt_mac_toQColor([NSColor shadowColor]));
qc = qt_mac_toQColor([NSColor controlTextColor]);
palette->setColor(QPalette::Active, QPalette::Text, qc);
@@ -98,10 +116,11 @@ QPalette * qt_mac_createSystemPalette()
struct QMacPaletteMap {
inline QMacPaletteMap(QPlatformTheme::Palette p, NSColor *a, NSColor *i) :
- paletteRole(p), active(a), inactive(i) { }
+ active(a), inactive(i), paletteRole(p) { }
+ NSColor *active;
+ NSColor *inactive;
QPlatformTheme::Palette paletteRole;
- NSColor *active, *inactive;
};
#define MAC_PALETTE_ENTRY(pal, active, inactive) \
@@ -131,7 +150,7 @@ QHash<QPlatformTheme::Palette, QPalette*> qt_mac_createRolePalettes()
QColor qc;
for (int i = 0; i < mac_widget_colors_count; i++) {
QPalette &pal = *qt_mac_createSystemPalette();
- if (mac_widget_colors[i].active != 0) {
+ if (mac_widget_colors[i].active) {
qc = qt_mac_toQColor(mac_widget_colors[i].active);
pal.setColor(QPalette::Active, QPalette::Text, qc);
pal.setColor(QPalette::Inactive, QPalette::Text, qc);
@@ -146,7 +165,18 @@ QHash<QPlatformTheme::Palette, QPalette*> qt_mac_createRolePalettes()
}
if (mac_widget_colors[i].paletteRole == QPlatformTheme::MenuPalette
|| mac_widget_colors[i].paletteRole == QPlatformTheme::MenuBarPalette) {
- pal.setBrush(QPalette::Highlight, qt_mac_toQColor([NSColor selectedMenuItemColor]));
+ NSColor *selectedMenuItemColor = nil;
+ if (__builtin_available(macOS 10.14, *)) {
+ // Cheap approximation for NSVisualEffectView (see deprecation note for selectedMenuItemTextColor)
+ selectedMenuItemColor = [[NSColor selectedContentBackgroundColor] highlightWithLevel:0.4];
+ } else {
+ // selectedMenuItemColor would presumably be the correct color to use as the background
+ // for selected menu items. But that color is always blue, and doesn't follow the
+ // appearance color in system preferences. So we therefore deliberatly choose to use
+ // keyboardFocusIndicatorColor instead, which appears to have the same color value.
+ selectedMenuItemColor = [NSColor keyboardFocusIndicatorColor];
+ }
+ pal.setBrush(QPalette::Highlight, qt_mac_toQColor(selectedMenuItemColor));
qc = qt_mac_toQColor([NSColor labelColor]);
pal.setBrush(QPalette::ButtonText, qc);
pal.setBrush(QPalette::Text, qc);
@@ -164,22 +194,41 @@ QHash<QPlatformTheme::Palette, QPalette*> qt_mac_createRolePalettes()
pal.setColor(QPalette::Active, QPalette::ButtonText,
pal.color(QPalette::Active, QPalette::Text));
} else if (mac_widget_colors[i].paletteRole == QPlatformTheme::ItemViewPalette) {
+ NSArray<NSColor *> *baseColors = nil;
+ NSColor *activeHighlightColor = nil;
+ if (__builtin_available(macOS 10.14, *)) {
+ baseColors = [NSColor alternatingContentBackgroundColors];
+ activeHighlightColor = [NSColor selectedContentBackgroundColor];
+ pal.setBrush(QPalette::Inactive, QPalette::HighlightedText,
+ qt_mac_toQBrush([NSColor unemphasizedSelectedTextColor]));
+ } else {
+ baseColors = [NSColor controlAlternatingRowBackgroundColors];
+ activeHighlightColor = [NSColor alternateSelectedControlColor];
+ pal.setBrush(QPalette::Inactive, QPalette::HighlightedText,
+ pal.brush(QPalette::Active, QPalette::Text));
+ }
+ pal.setBrush(QPalette::Base, qt_mac_toQBrush(baseColors[0]));
+ pal.setBrush(QPalette::AlternateBase, qt_mac_toQBrush(baseColors[1]));
pal.setBrush(QPalette::Active, QPalette::Highlight,
- qt_mac_toQBrush([NSColor alternateSelectedControlColor]));
+ qt_mac_toQBrush(activeHighlightColor));
pal.setBrush(QPalette::Active, QPalette::HighlightedText,
qt_mac_toQBrush([NSColor alternateSelectedControlTextColor]));
pal.setBrush(QPalette::Inactive, QPalette::Text,
- pal.brush(QPalette::Active, QPalette::Text));
- pal.setBrush(QPalette::Inactive, QPalette::HighlightedText,
- pal.brush(QPalette::Active, QPalette::Text));
+ pal.brush(QPalette::Active, QPalette::Text));
} else if (mac_widget_colors[i].paletteRole == QPlatformTheme::TextEditPalette) {
+ pal.setBrush(QPalette::Active, QPalette::Base, qt_mac_toQColor([NSColor textBackgroundColor]));
pal.setBrush(QPalette::Inactive, QPalette::Text,
pal.brush(QPalette::Active, QPalette::Text));
pal.setBrush(QPalette::Inactive, QPalette::HighlightedText,
pal.brush(QPalette::Active, QPalette::Text));
- } else if (mac_widget_colors[i].paletteRole == QPlatformTheme::TextLineEditPalette) {
+ } else if (mac_widget_colors[i].paletteRole == QPlatformTheme::TextLineEditPalette
+ || mac_widget_colors[i].paletteRole == QPlatformTheme::ComboBoxPalette) {
+ pal.setBrush(QPalette::Active, QPalette::Base, qt_mac_toQColor([NSColor textBackgroundColor]));
pal.setBrush(QPalette::Disabled, QPalette::Base,
pal.brush(QPalette::Active, QPalette::Base));
+ } else if (mac_widget_colors[i].paletteRole == QPlatformTheme::LabelPalette) {
+ qc = qt_mac_toQColor([NSColor labelColor]);
+ pal.setBrush(QPalette::Inactive, QPalette::ToolTipText, qc);
}
palettes.insert(mac_widget_colors[i].paletteRole, &pal);
}
diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h
index 2f1a1e42a9..d831612c22 100644
--- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h
+++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h
@@ -55,7 +55,7 @@ class QSystemTrayIconSys;
class Q_GUI_EXPORT QCocoaSystemTrayIcon : public QPlatformSystemTrayIcon
{
public:
- QCocoaSystemTrayIcon() : m_sys(0) {}
+ QCocoaSystemTrayIcon() : m_sys(nullptr) {}
void init() override;
void cleanup() override;
diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
index 5e6913a89a..0158895441 100644
--- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
+++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
@@ -95,31 +95,16 @@ QT_USE_NAMESPACE
@class QT_MANGLE_NAMESPACE(QNSImageView);
@interface QT_MANGLE_NAMESPACE(QNSStatusItem) : NSObject <NSUserNotificationCenterDelegate>
-{
-@public
- QCocoaSystemTrayIcon *systray;
- NSStatusItem *item;
- QCocoaMenu *menu;
- QIcon icon;
- QT_MANGLE_NAMESPACE(QNSImageView) *imageCell;
-}
--(id)initWithSysTray:(QCocoaSystemTrayIcon *)systray;
--(void)dealloc;
--(NSStatusItem*)item;
--(QRectF)geometry;
+@property (nonatomic, assign) QCocoaMenu *menu;
+@property (nonatomic, assign) QIcon icon;
+@property (nonatomic, readonly) NSStatusItem *item;
+@property (nonatomic, readonly) QRectF geometry;
+- (instancetype)initWithSysTray:(QCocoaSystemTrayIcon *)systray;
- (void)triggerSelector:(id)sender button:(Qt::MouseButton)mouseButton;
- (void)doubleClickSelector:(id)sender;
-- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification;
-- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification;
@end
-@interface QT_MANGLE_NAMESPACE(QNSImageView) : NSImageView {
- BOOL down;
- QT_MANGLE_NAMESPACE(QNSStatusItem) *parent;
-}
--(id)initWithParent:(QT_MANGLE_NAMESPACE(QNSStatusItem)*)myParent;
--(void)menuTrackingDone:(NSNotification*)notification;
--(void)mousePressed:(NSEvent *)mouseEvent button:(Qt::MouseButton)mouseButton;
+@interface QT_MANGLE_NAMESPACE(QNSImageView) : NSImageView
@end
QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSStatusItem);
@@ -162,7 +147,7 @@ QRect QCocoaSystemTrayIcon::geometry() const
void QCocoaSystemTrayIcon::cleanup()
{
delete m_sys;
- m_sys = 0;
+ m_sys = nullptr;
}
static bool heightCompareFunction (QSize a, QSize b) { return (a.height() < b.height()); }
@@ -178,7 +163,7 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon)
if (!m_sys)
return;
- m_sys->item->icon = icon;
+ m_sys->item.icon = icon;
// The reccomended maximum title bar icon height is 18 points
// (device independent pixels). The menu height on past and
@@ -249,8 +234,8 @@ void QCocoaSystemTrayIcon::updateMenu(QPlatformMenu *menu)
if (!m_sys)
return;
- m_sys->item->menu = static_cast<QCocoaMenu *>(menu);
- if (menu && [m_sys->item->menu->nsMenu() numberOfItems] > 0) {
+ m_sys->item.menu = static_cast<QCocoaMenu *>(menu);
+ if (menu && [m_sys->item.menu->nsMenu() numberOfItems] > 0) {
[[m_sys->item item] setHighlightMode:YES];
} else {
[[m_sys->item item] setHighlightMode:NO];
@@ -289,23 +274,29 @@ void QCocoaSystemTrayIcon::showMessage(const QString &title, const QString &mess
}
QT_END_NAMESPACE
-@implementation QNSImageView
--(id)initWithParent:(QNSStatusItem*)myParent {
+@implementation NSStatusItem (Qt)
+@end
+
+@implementation QNSImageView {
+ BOOL down;
+ QT_MANGLE_NAMESPACE(QNSStatusItem) *parent;
+}
+
+- (instancetype)initWithParent:(QNSStatusItem *)myParent {
self = [super init];
parent = myParent;
down = NO;
return self;
}
--(void)menuTrackingDone:(NSNotification*)notification
+- (void)menuTrackingDone:(NSNotification *)__unused notification
{
- Q_UNUSED(notification);
down = NO;
[self setNeedsDisplay:YES];
}
--(void)mousePressed:(NSEvent *)mouseEvent button:(Qt::MouseButton)mouseButton
+- (void)mousePressed:(NSEvent *)mouseEvent
{
down = YES;
int clickCount = [mouseEvent clickCount];
@@ -315,16 +306,16 @@ QT_END_NAMESPACE
[self menuTrackingDone:nil];
[parent doubleClickSelector:self];
} else {
- [parent triggerSelector:self button:mouseButton];
+ [parent triggerSelector:self button:cocoaButton2QtButton(mouseEvent)];
}
}
--(void)mouseDown:(NSEvent *)mouseEvent
+- (void)mouseDown:(NSEvent *)mouseEvent
{
- [self mousePressed:mouseEvent button:Qt::LeftButton];
+ [self mousePressed:mouseEvent];
}
--(void)mouseUp:(NSEvent *)mouseEvent
+- (void)mouseUp:(NSEvent *)mouseEvent
{
Q_UNUSED(mouseEvent);
[self menuTrackingDone:nil];
@@ -332,10 +323,10 @@ QT_END_NAMESPACE
- (void)rightMouseDown:(NSEvent *)mouseEvent
{
- [self mousePressed:mouseEvent button:Qt::RightButton];
+ [self mousePressed:mouseEvent];
}
--(void)rightMouseUp:(NSEvent *)mouseEvent
+- (void)rightMouseUp:(NSEvent *)mouseEvent
{
Q_UNUSED(mouseEvent);
[self menuTrackingDone:nil];
@@ -343,29 +334,36 @@ QT_END_NAMESPACE
- (void)otherMouseDown:(NSEvent *)mouseEvent
{
- [self mousePressed:mouseEvent button:cocoaButton2QtButton([mouseEvent buttonNumber])];
+ [self mousePressed:mouseEvent];
}
--(void)otherMouseUp:(NSEvent *)mouseEvent
+- (void)otherMouseUp:(NSEvent *)mouseEvent
{
Q_UNUSED(mouseEvent);
[self menuTrackingDone:nil];
}
--(void)drawRect:(NSRect)rect {
+- (void)drawRect:(NSRect)rect {
[[parent item] drawStatusBarBackgroundInRect:rect withHighlight:down];
[super drawRect:rect];
}
@end
-@implementation QNSStatusItem
+@implementation QNSStatusItem {
+ QCocoaSystemTrayIcon *systray;
+ NSStatusItem *item;
+ QT_MANGLE_NAMESPACE(QNSImageView) *imageCell;
+}
+
+@synthesize menu = menu;
+@synthesize icon = icon;
--(id)initWithSysTray:(QCocoaSystemTrayIcon *)sys
+- (instancetype)initWithSysTray:(QCocoaSystemTrayIcon *)sys
{
self = [super init];
if (self) {
item = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];
- menu = 0;
+ menu = nullptr;
systray = sys;
imageCell = [[QNSImageView alloc] initWithParent:self];
[item setView: imageCell];
@@ -373,19 +371,19 @@ QT_END_NAMESPACE
return self;
}
--(void)dealloc {
+- (void)dealloc {
[[NSStatusBar systemStatusBar] removeStatusItem:item];
[[NSNotificationCenter defaultCenter] removeObserver:imageCell];
[imageCell release];
[item release];
[super dealloc];
-
}
--(NSStatusItem*)item {
+- (NSStatusItem *)item {
return item;
}
--(QRectF)geometry {
+
+- (QRectF)geometry {
if (NSWindow *window = [[item view] window]) {
if (QCocoaScreen *screen = QCocoaIntegration::instance()->screenForNSScreen([window screen]))
return screen->mapFromNative([window frame]);
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.h b/src/plugins/platforms/cocoa/qcocoatheme.h
index 69eaf8db56..c42fa7d2e8 100644
--- a/src/plugins/platforms/cocoa/qcocoatheme.h
+++ b/src/plugins/platforms/cocoa/qcocoatheme.h
@@ -43,7 +43,7 @@
#include <QtCore/QHash>
#include <qpa/qplatformtheme.h>
-Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QCocoaThemeNotificationReceiver));
+Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QCocoaThemeAppAppearanceObserver));
QT_BEGIN_NAMESPACE
@@ -78,11 +78,13 @@ public:
static const char *name;
+ void handleSystemThemeChange();
+
private:
mutable QPalette *m_systemPalette;
mutable QHash<QPlatformTheme::Palette, QPalette*> m_palettes;
mutable QHash<QPlatformTheme::Font, QFont*> m_fonts;
- mutable QT_MANGLE_NAMESPACE(QCocoaThemeNotificationReceiver) *m_notificationReceiver;
+ QT_MANGLE_NAMESPACE(QCocoaThemeAppAppearanceObserver) *m_appearanceObserver;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm
index 93f0400916..a2229159b5 100644
--- a/src/plugins/platforms/cocoa/qcocoatheme.mm
+++ b/src/plugins/platforms/cocoa/qcocoatheme.mm
@@ -42,6 +42,7 @@
#include "qcocoatheme.h"
#include "messages.h"
+#include <QtCore/QOperatingSystemVersion>
#include <QtCore/QVariant>
#include "qcocoasystemsettings.h"
@@ -75,30 +76,50 @@
#endif
#endif
-#include <Carbon/Carbon.h>
+#include <CoreServices/CoreServices.h>
-@interface QT_MANGLE_NAMESPACE(QCocoaThemeNotificationReceiver) : NSObject {
-QCocoaTheme *mPrivate;
-}
-- (id)initWithPrivate:(QCocoaTheme *)priv;
-- (void)systemColorsDidChange:(NSNotification *)notification;
+#if !QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
+@interface NSApplication (MojaveForwardDeclarations)
+@property (readonly, strong) NSAppearance *effectiveAppearance NS_AVAILABLE_MAC(10_14);
@end
+#endif
-QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaThemeNotificationReceiver);
+@interface QT_MANGLE_NAMESPACE(QCocoaThemeAppAppearanceObserver) : NSObject
+@property (readonly, nonatomic) QCocoaTheme *theme;
+- (instancetype)initWithTheme:(QCocoaTheme *)theme;
+@end
-@implementation QCocoaThemeNotificationReceiver
-- (id)initWithPrivate:(QCocoaTheme *)priv
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaThemeAppAppearanceObserver);
+
+@implementation QCocoaThemeAppAppearanceObserver
+- (instancetype)initWithTheme:(QCocoaTheme *)theme
{
- self = [super init];
- mPrivate = priv;
+ if ((self = [super init])) {
+ _theme = theme;
+ [NSApp addObserver:self forKeyPath:@"effectiveAppearance" options:NSKeyValueObservingOptionNew context:nullptr];
+ }
return self;
}
-- (void)systemColorsDidChange:(NSNotification *)notification
+- (void)dealloc
{
- Q_UNUSED(notification);
- mPrivate->reset();
- QWindowSystemInterface::handleThemeChange(nullptr);
+ [NSApp removeObserver:self forKeyPath:@"effectiveAppearance"];
+ [super dealloc];
+}
+
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
+ change:(NSDictionary<NSKeyValueChangeKey, id> *)change context:(void *)context
+{
+ Q_UNUSED(change);
+ Q_UNUSED(context);
+
+ Q_ASSERT(object == NSApp);
+ Q_ASSERT([keyPath isEqualToString:@"effectiveAppearance"]);
+
+ if (__builtin_available(macOS 10.14, *))
+ NSAppearance.currentAppearance = NSApp.effectiveAppearance;
+
+ self.theme->handleSystemThemeChange();
}
@end
@@ -107,19 +128,22 @@ QT_BEGIN_NAMESPACE
const char *QCocoaTheme::name = "cocoa";
QCocoaTheme::QCocoaTheme()
- :m_systemPalette(0)
+ : m_systemPalette(nullptr), m_appearanceObserver(nil)
{
- m_notificationReceiver = [[QT_MANGLE_NAMESPACE(QCocoaThemeNotificationReceiver) alloc] initWithPrivate:this];
- [[NSNotificationCenter defaultCenter] addObserver:m_notificationReceiver
- selector:@selector(systemColorsDidChange:)
- name:NSSystemColorsDidChangeNotification
- object:nil];
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave)
+ m_appearanceObserver = [[QCocoaThemeAppAppearanceObserver alloc] initWithTheme:this];
+
+ [[NSNotificationCenter defaultCenter] addObserverForName:NSSystemColorsDidChangeNotification
+ object:nil queue:nil usingBlock:^(NSNotification *) {
+ handleSystemThemeChange();
+ }];
}
QCocoaTheme::~QCocoaTheme()
{
- [[NSNotificationCenter defaultCenter] removeObserver:m_notificationReceiver];
- [m_notificationReceiver release];
+ if (m_appearanceObserver)
+ [m_appearanceObserver release];
+
reset();
qDeleteAll(m_fonts);
}
@@ -132,6 +156,15 @@ void QCocoaTheme::reset()
m_palettes.clear();
}
+void QCocoaTheme::handleSystemThemeChange()
+{
+ reset();
+ m_systemPalette = qt_mac_createSystemPalette();
+ m_palettes = qt_mac_createRolePalettes();
+
+ QWindowSystemInterface::handleThemeChange(nullptr);
+}
+
bool QCocoaTheme::usePlatformNativeDialog(DialogType dialogType) const
{
if (dialogType == QPlatformTheme::FileDialog)
@@ -147,7 +180,7 @@ bool QCocoaTheme::usePlatformNativeDialog(DialogType dialogType) const
return false;
}
-QPlatformDialogHelper * QCocoaTheme::createPlatformDialogHelper(DialogType dialogType) const
+QPlatformDialogHelper *QCocoaTheme::createPlatformDialogHelper(DialogType dialogType) const
{
switch (dialogType) {
#if defined(QT_WIDGETS_LIB) && QT_CONFIG(filedialog)
@@ -163,7 +196,7 @@ QPlatformDialogHelper * QCocoaTheme::createPlatformDialogHelper(DialogType dialo
return new QCocoaFontDialogHelper();
#endif
default:
- return 0;
+ return nullptr;
}
}
@@ -183,9 +216,9 @@ const QPalette *QCocoaTheme::palette(Palette type) const
} else {
if (m_palettes.isEmpty())
m_palettes = qt_mac_createRolePalettes();
- return m_palettes.value(type, 0);
+ return m_palettes.value(type, nullptr);
}
- return 0;
+ return nullptr;
}
QHash<QPlatformTheme::Font, QFont *> qt_mac_createRoleFonts()
@@ -199,7 +232,7 @@ const QFont *QCocoaTheme::font(Font type) const
if (m_fonts.isEmpty()) {
m_fonts = qt_mac_createRoleFonts();
}
- return m_fonts.value(type, 0);
+ return m_fonts.value(type, nullptr);
}
//! \internal
diff --git a/src/plugins/platforms/cocoa/qcocoavulkaninstance.h b/src/plugins/platforms/cocoa/qcocoavulkaninstance.h
new file mode 100644
index 0000000000..5fe6a612af
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qcocoavulkaninstance.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOCOAVULKANINSTANCE_H
+#define QCOCOAVULKANINSTANCE_H
+
+// Include mvk_vulkan.h first. The order is important since
+// mvk_vulkan.h just defines VK_USE_PLATFORM_MACOS_MVK (or the IOS
+// variant) and includes vulkan.h. If something else included vulkan.h
+// before this then we wouldn't get the MVK specifics...
+#include <MoltenVK/mvk_vulkan.h>
+
+#include <QtCore/QHash>
+#include <QtVulkanSupport/private/qbasicvulkanplatforminstance_p.h>
+
+#include <AppKit/AppKit.h>
+
+QT_BEGIN_NAMESPACE
+
+class QCocoaVulkanInstance : public QBasicPlatformVulkanInstance
+{
+public:
+ QCocoaVulkanInstance(QVulkanInstance *instance);
+ ~QCocoaVulkanInstance();
+
+ void createOrAdoptInstance() override;
+
+ VkSurfaceKHR *createSurface(QWindow *window);
+ VkSurfaceKHR createSurface(NSView *view);
+private:
+ QVulkanInstance *m_instance = nullptr;
+ QLibrary m_lib;
+ VkSurfaceKHR m_nullSurface = nullptr;
+ PFN_vkCreateMacOSSurfaceMVK m_createSurface = nullptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QXCBVULKANINSTANCE_H
diff --git a/src/plugins/platforms/cocoa/qcocoavulkaninstance.mm b/src/plugins/platforms/cocoa/qcocoavulkaninstance.mm
new file mode 100644
index 0000000000..b00fde6c6f
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qcocoavulkaninstance.mm
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcocoavulkaninstance.h"
+#include "qcocoawindow.h"
+
+QT_BEGIN_NAMESPACE
+
+QCocoaVulkanInstance::QCocoaVulkanInstance(QVulkanInstance *instance)
+ : m_instance(instance)
+{
+ loadVulkanLibrary(QStringLiteral("vulkan"));
+}
+
+QCocoaVulkanInstance::~QCocoaVulkanInstance()
+{
+}
+
+void QCocoaVulkanInstance::createOrAdoptInstance()
+{
+ initInstance(m_instance, QByteArrayList());
+}
+
+VkSurfaceKHR *QCocoaVulkanInstance::createSurface(QWindow *window)
+{
+ QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());
+ if (cocoaWindow->m_vulkanSurface)
+ destroySurface(cocoaWindow->m_vulkanSurface);
+ cocoaWindow->m_vulkanSurface = createSurface(cocoaWindow->m_view);
+ return &cocoaWindow->m_vulkanSurface;
+}
+
+VkSurfaceKHR QCocoaVulkanInstance::createSurface(NSView *view)
+{
+ if (!m_createSurface) {
+ m_createSurface = reinterpret_cast<PFN_vkCreateMacOSSurfaceMVK>(
+ m_vkGetInstanceProcAddr(m_vkInst, "vkCreateMacOSSurfaceMVK"));
+ }
+ if (!m_createSurface) {
+ qWarning("Failed to find vkCreateMacOSSurfaceMVK");
+ return m_nullSurface;
+ }
+
+ VkMacOSSurfaceCreateInfoMVK surfaceInfo;
+ surfaceInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
+ surfaceInfo.pNext = nullptr;
+ surfaceInfo.flags = 0;
+ surfaceInfo.pView = view;
+
+ VkSurfaceKHR surface = nullptr;
+ VkResult err = m_createSurface(m_vkInst, &surfaceInfo, nullptr, &surface);
+ if (err != VK_SUCCESS)
+ qWarning("Failed to create Vulkan surface: %d", err);
+
+ return surface;
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index fb91c53a7a..8f1bdb8af0 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -53,6 +53,10 @@
#include "qnswindow.h"
#include "qt_mac_p.h"
+#if QT_CONFIG(vulkan)
+#include <MoltenVK/mvk_vulkan.h>
+#endif
+
QT_BEGIN_NAMESPACE
#ifndef QT_NO_DEBUG_STREAM
@@ -112,6 +116,7 @@ public:
void raise() override;
void lower() override;
bool isExposed() const override;
+ bool isEmbedded() const override;
bool isOpaque() const;
void propagateSizeHints() override;
void setOpacity(qreal level) override;
@@ -124,6 +129,8 @@ public:
bool isForeignWindow() const override;
void requestUpdate() override;
+ void deliverUpdateRequest() override;
+
void requestActivateWindow() override;
WId winId() const override;
@@ -132,7 +139,7 @@ public:
NSView *view() const;
NSWindow *nativeWindow() const;
- void setEmbeddedInForeignView(bool subwindow);
+ void setEmbeddedInForeignView();
Q_NOTIFICATION_HANDLER(NSViewFrameDidChangeNotification) void viewDidChangeFrame();
Q_NOTIFICATION_HANDLER(NSViewGlobalFrameDidChangeNotification) void viewDidChangeGlobalFrame();
@@ -162,11 +169,6 @@ public:
NSUInteger windowStyleMask(Qt::WindowFlags flags);
void setWindowZoomButton(Qt::WindowFlags flags);
-#ifndef QT_NO_OPENGL
- void setCurrentContext(QCocoaGLContext *context);
- QCocoaGLContext *currentContext() const;
-#endif
-
bool setWindowModified(bool modified) override;
void setFrameStrutEventsEnabled(bool enabled) override;
@@ -237,11 +239,6 @@ public: // for QNSView
NSView *m_view;
QCocoaNSWindow *m_nsWindow;
- // TODO merge to one variable if possible
- bool m_viewIsEmbedded; // true if the m_view is actually embedded in a "foreign" NSView hiearchy
- bool m_viewIsToBeEmbedded; // true if the m_view is intended to be embedded in a "foreign" NSView hiearchy
-
- Qt::WindowFlags m_windowFlags;
Qt::WindowStates m_lastReportedWindowState;
Qt::WindowModality m_windowModality;
QPointer<QWindow> m_enterLeaveTargetWindow;
@@ -251,9 +248,6 @@ public: // for QNSView
bool m_inSetVisible;
bool m_inSetGeometry;
bool m_inSetStyleMask;
-#ifndef QT_NO_OPENGL
- QCocoaGLContext *m_glContext;
-#endif
QCocoaMenuBar *m_menubar;
bool m_needsInvalidateShadow;
@@ -283,6 +277,10 @@ public: // for QNSView
};
QHash<quintptr, BorderRange> m_contentBorderAreas; // identifer -> uppper/lower
QHash<quintptr, bool> m_enabledContentBorderAreas; // identifer -> enabled state (true/false)
+
+#if QT_CONFIG(vulkan)
+ VkSurfaceKHR m_vulkanSurface = nullptr;
+#endif
};
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 00c3f7c22c..1ce671941d 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -117,24 +117,19 @@ static void qRegisterNotificationCallbacks()
return;
}
- if (lcCocoaNotifications().isDebugEnabled()) {
- if (cocoaWindows.isEmpty()) {
- qCDebug(lcCocoaNotifications) << "Could not find forwarding target for" <<
- qPrintable(notificationName) << "from" << notification.object;
- } else {
- QVector<QCocoaWindow *> debugWindows;
- for (QCocoaWindow *cocoaWindow : cocoaWindows)
- debugWindows += cocoaWindow;
- qCDebug(lcCocoaNotifications) << "Forwarding" << qPrintable(notificationName) <<
- "to" << debugWindows;
- }
+ if (lcCocoaNotifications().isDebugEnabled() && !cocoaWindows.isEmpty()) {
+ QVector<QCocoaWindow *> debugWindows;
+ for (QCocoaWindow *cocoaWindow : cocoaWindows)
+ debugWindows += cocoaWindow;
+ qCDebug(lcCocoaNotifications) << "Forwarding" << qPrintable(notificationName) <<
+ "to" << debugWindows;
}
// FIXME: Could be a foreign window, look up by iterating top level QWindows
for (QCocoaWindow *cocoaWindow : cocoaWindows) {
if (!method.invoke(cocoaWindow, Qt::DirectConnection)) {
- qCWarning(lcQpaCocoaWindow) << "Failed to invoke NSNotification callback for"
+ qCWarning(lcQpaWindow) << "Failed to invoke NSNotification callback for"
<< notification.name << "on" << cocoaWindow;
}
}
@@ -148,9 +143,7 @@ const int QCocoaWindow::NoAlertRequest = -1;
QCocoaWindow::QCocoaWindow(QWindow *win, WId nativeHandle)
: QPlatformWindow(win)
, m_view(nil)
- , m_nsWindow(0)
- , m_viewIsEmbedded(false)
- , m_viewIsToBeEmbedded(false)
+ , m_nsWindow(nil)
, m_lastReportedWindowState(Qt::WindowNoState)
, m_windowModality(Qt::NonModal)
, m_windowUnderMouse(false)
@@ -158,10 +151,7 @@ QCocoaWindow::QCocoaWindow(QWindow *win, WId nativeHandle)
, m_inSetVisible(false)
, m_inSetGeometry(false)
, m_inSetStyleMask(false)
-#ifndef QT_NO_OPENGL
- , m_glContext(0)
-#endif
- , m_menubar(0)
+ , m_menubar(nullptr)
, m_needsInvalidateShadow(false)
, m_hasModalSession(false)
, m_frameStrutEventsEnabled(false)
@@ -173,7 +163,7 @@ QCocoaWindow::QCocoaWindow(QWindow *win, WId nativeHandle)
, m_topContentBorderThickness(0)
, m_bottomContentBorderThickness(0)
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::QCocoaWindow" << window();
+ qCDebug(lcQpaWindow) << "QCocoaWindow::QCocoaWindow" << window();
if (nativeHandle) {
m_view = reinterpret_cast<NSView *>(nativeHandle);
@@ -183,41 +173,24 @@ QCocoaWindow::QCocoaWindow(QWindow *win, WId nativeHandle)
void QCocoaWindow::initialize()
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::initialize" << window();
+ qCDebug(lcQpaWindow) << "QCocoaWindow::initialize" << window();
QMacAutoReleasePool pool;
- if (!m_view) {
+ if (!m_view)
m_view = [[QNSView alloc] initWithCocoaWindow:this];
- // Enable high-dpi OpenGL for retina displays. Enabling has the side
- // effect that Cocoa will start calling glViewport(0, 0, width, height),
- // overriding any glViewport calls in application code. This is usually not a
- // problem, except if the appilcation wants to have a "custom" viewport.
- // (like the hellogl example)
- if (window()->supportsOpenGL()) {
- BOOL enable = qt_mac_resolveOption(YES, window(), "_q_mac_wantsBestResolutionOpenGLSurface",
- "QT_MAC_WANTS_BEST_RESOLUTION_OPENGL_SURFACE");
- [m_view setWantsBestResolutionOpenGLSurface:enable];
- // See also QCocoaGLContext::makeCurrent for software renderer workarounds.
- }
- BOOL enable = qt_mac_resolveOption(NO, window(), "_q_mac_wantsLayer",
- "QT_MAC_WANTS_LAYER");
- [m_view setWantsLayer:enable];
- }
setGeometry(initialGeometry(window(), windowGeometry(), defaultWindowWidth, defaultWindowHeight));
recreateWindowIfNeeded();
window()->setGeometry(geometry());
- if (window()->isTopLevel())
- setWindowIcon(window()->icon());
m_initialized = true;
}
QCocoaWindow::~QCocoaWindow()
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::~QCocoaWindow" << window();
+ qCDebug(lcQpaWindow) << "QCocoaWindow::~QCocoaWindow" << window();
QMacAutoReleasePool pool;
[m_nsWindow makeFirstResponder:nil];
@@ -232,10 +205,16 @@ QCocoaWindow::~QCocoaWindow()
if (!isForeignWindow())
[[NSNotificationCenter defaultCenter] removeObserver:m_view];
- // While it is unlikely that this window will be in the popup stack
- // during deletetion we clear any pointers here to make sure.
- if (QCocoaIntegration::instance()) {
- QCocoaIntegration::instance()->popupWindowStack()->removeAll(this);
+ if (QCocoaIntegration *cocoaIntegration = QCocoaIntegration::instance()) {
+ // While it is unlikely that this window will be in the popup stack
+ // during deletetion we clear any pointers here to make sure.
+ cocoaIntegration->popupWindowStack()->removeAll(this);
+
+#if QT_CONFIG(vulkan)
+ auto vulcanInstance = cocoaIntegration->getCocoaVulkanInstance();
+ if (vulcanInstance)
+ vulcanInstance->destroySurface(m_vulkanSurface);
+#endif
}
[m_view release];
@@ -255,7 +234,7 @@ QSurfaceFormat QCocoaWindow::format() const
void QCocoaWindow::setGeometry(const QRect &rectIn)
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setGeometry" << window() << rectIn;
+ qCDebug(lcQpaWindow) << "QCocoaWindow::setGeometry" << window() << rectIn;
QBoolBlocker inSetGeometry(m_inSetGeometry, true);
@@ -283,7 +262,7 @@ QRect QCocoaWindow::geometry() const
// QWindows that are embedded in a NSView hiearchy may be considered
// top-level from Qt's point of view but are not from Cocoa's point
// of view. Embedded QWindows get global (screen) geometry.
- if (m_viewIsEmbedded) {
+ if (isEmbedded()) {
NSPoint windowPoint = [m_view convertPoint:NSMakePoint(0, 0) toView:nil];
NSRect screenRect = [[m_view window] convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 1, 1)];
NSPoint screenPoint = screenRect.origin;
@@ -297,12 +276,12 @@ QRect QCocoaWindow::geometry() const
void QCocoaWindow::setCocoaGeometry(const QRect &rect)
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setCocoaGeometry" << window() << rect;
+ qCDebug(lcQpaWindow) << "QCocoaWindow::setCocoaGeometry" << window() << rect;
QMacAutoReleasePool pool;
QPlatformWindow::setGeometry(rect);
- if (m_viewIsEmbedded) {
+ if (isEmbedded()) {
if (!isForeignWindow()) {
[m_view setFrame:NSMakeRect(0, 0, rect.width(), rect.height())];
}
@@ -321,12 +300,12 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect)
void QCocoaWindow::setVisible(bool visible)
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setVisible" << window() << visible;
+ qCDebug(lcQpaWindow) << "QCocoaWindow::setVisible" << window() << visible;
m_inSetVisible = true;
QMacAutoReleasePool pool;
- QCocoaWindow *parentCocoaWindow = 0;
+ QCocoaWindow *parentCocoaWindow = nullptr;
if (window()->transientParent())
parentCocoaWindow = static_cast<QCocoaWindow *>(window()->transientParent()->handle());
@@ -355,9 +334,9 @@ void QCocoaWindow::setVisible(bool visible)
// Since this isn't a native popup, the window manager doesn't close the popup when you click outside
NSWindow *nativeParentWindow = parentCocoaWindow->nativeWindow();
NSUInteger parentStyleMask = nativeParentWindow.styleMask;
- if ((m_resizableTransientParent = (parentStyleMask & NSResizableWindowMask))
- && !(nativeParentWindow.styleMask & NSFullScreenWindowMask))
- nativeParentWindow.styleMask &= ~NSResizableWindowMask;
+ if ((m_resizableTransientParent = (parentStyleMask & NSWindowStyleMaskResizable))
+ && !(nativeParentWindow.styleMask & NSWindowStyleMaskFullScreen))
+ nativeParentWindow.styleMask &= ~NSWindowStyleMaskResizable;
}
}
@@ -378,13 +357,13 @@ void QCocoaWindow::setVisible(bool visible)
} else if (window()->modality() != Qt::NonModal) {
// show the window as application modal
QCocoaEventDispatcher *cocoaEventDispatcher = qobject_cast<QCocoaEventDispatcher *>(QGuiApplication::instance()->eventDispatcher());
- Q_ASSERT(cocoaEventDispatcher != 0);
+ Q_ASSERT(cocoaEventDispatcher);
QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = static_cast<QCocoaEventDispatcherPrivate *>(QObjectPrivate::get(cocoaEventDispatcher));
cocoaEventDispatcherPrivate->beginModalSession(window());
m_hasModalSession = true;
} else if ([m_view.window canBecomeKeyWindow]) {
QCocoaEventDispatcher *cocoaEventDispatcher = qobject_cast<QCocoaEventDispatcher *>(QGuiApplication::instance()->eventDispatcher());
- QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = 0;
+ QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = nullptr;
if (cocoaEventDispatcher)
cocoaEventDispatcherPrivate = static_cast<QCocoaEventDispatcherPrivate *>(QObjectPrivate::get(cocoaEventDispatcher));
@@ -402,12 +381,15 @@ void QCocoaWindow::setVisible(bool visible)
((NSPanel *)m_view.window).worksWhenModal = YES;
if (!(parentCocoaWindow && window()->transientParent()->isActive()) && window()->type() == Qt::Popup) {
removeMonitor();
- monitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDownMask|NSRightMouseDownMask|NSOtherMouseDownMask|NSMouseMovedMask handler:^(NSEvent *e) {
- QPointF localPoint = QCocoaScreen::mapFromNative([NSEvent mouseLocation]);
- const auto button = e.type == NSEventTypeMouseMoved ? Qt::NoButton : cocoaButton2QtButton([e buttonNumber]);
- const auto eventType = e.type == NSEventTypeMouseMoved ? QEvent::MouseMove : QEvent::MouseButtonPress;
- QWindowSystemInterface::handleMouseEvent(window(), window()->mapFromGlobal(localPoint.toPoint()), localPoint,
- Qt::MouseButtons(uint(NSEvent.pressedMouseButtons & 0xFFFF)), button, eventType);
+ NSEventMask eventMask = NSEventMaskLeftMouseDown | NSEventMaskRightMouseDown
+ | NSEventMaskOtherMouseDown | NSEventMaskMouseMoved;
+ monitor = [NSEvent addGlobalMonitorForEventsMatchingMask:eventMask handler:^(NSEvent *e) {
+ const auto button = cocoaButton2QtButton(e);
+ const auto buttons = currentlyPressedMouseButtons();
+ const auto eventType = cocoaEvent2QtMouseEvent(e);
+ const auto globalPoint = QCocoaScreen::mapFromNative(NSEvent.mouseLocation);
+ const auto localPoint = window()->mapFromGlobal(globalPoint.toPoint());
+ QWindowSystemInterface::handleMouseEvent(window(), localPoint, globalPoint, buttons, button, eventType);
}];
}
}
@@ -420,12 +402,8 @@ void QCocoaWindow::setVisible(bool visible)
[m_view setHidden:NO];
} else {
// qDebug() << "close" << this;
-#ifndef QT_NO_OPENGL
- if (m_glContext)
- m_glContext->windowWasHidden();
-#endif
QCocoaEventDispatcher *cocoaEventDispatcher = qobject_cast<QCocoaEventDispatcher *>(QGuiApplication::instance()->eventDispatcher());
- QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = 0;
+ QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = nullptr;
if (cocoaEventDispatcher)
cocoaEventDispatcherPrivate = static_cast<QCocoaEventDispatcherPrivate *>(QObjectPrivate::get(cocoaEventDispatcher));
if (isContentView()) {
@@ -463,9 +441,9 @@ void QCocoaWindow::setVisible(bool visible)
if (parentCocoaWindow && window()->type() == Qt::Popup) {
NSWindow *nativeParentWindow = parentCocoaWindow->nativeWindow();
if (m_resizableTransientParent
- && !(nativeParentWindow.styleMask & NSFullScreenWindowMask))
+ && !(nativeParentWindow.styleMask & NSWindowStyleMaskFullScreen))
// A window should not be resizable while a transient popup is open
- nativeParentWindow.styleMask |= NSResizableWindowMask;
+ nativeParentWindow.styleMask |= NSWindowStyleMaskResizable;
}
}
@@ -493,7 +471,8 @@ NSInteger QCocoaWindow::windowLevel(Qt::WindowFlags flags)
// Any "special" window should be in at least the same level as its parent.
if (type != Qt::Window) {
const QWindow * const transientParent = window()->transientParent();
- const QCocoaWindow * const transientParentWindow = transientParent ? static_cast<QCocoaWindow *>(transientParent->handle()) : 0;
+ const QCocoaWindow * const transientParentWindow = transientParent ?
+ static_cast<QCocoaWindow *>(transientParent->handle()) : nullptr;
if (transientParentWindow)
windowLevel = qMax([transientParentWindow->nativeWindow() level], windowLevel);
}
@@ -507,39 +486,39 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags)
const bool frameless = (flags & Qt::FramelessWindowHint) || windowIsPopupType(type);
// Remove zoom button by disabling resize for CustomizeWindowHint windows, except for
- // Qt::Tool windows (e.g. dock windows) which should always be resizeable.
- const bool resizeable = !(flags & Qt::CustomizeWindowHint) || (type == Qt::Tool);
+ // Qt::Tool windows (e.g. dock windows) which should always be resizable.
+ const bool resizable = !(flags & Qt::CustomizeWindowHint) || (type == Qt::Tool);
// Select base window type. Note that the value of NSBorderlessWindowMask is 0.
- NSUInteger styleMask = (frameless || !resizeable) ? NSBorderlessWindowMask : NSResizableWindowMask;
+ NSUInteger styleMask = (frameless || !resizable) ? NSWindowStyleMaskBorderless : NSWindowStyleMaskResizable;
if (frameless) {
// No further customizations for frameless since there are no window decorations.
} else if (flags & Qt::CustomizeWindowHint) {
if (flags & Qt::WindowTitleHint)
- styleMask |= NSTitledWindowMask;
+ styleMask |= NSWindowStyleMaskTitled;
if (flags & Qt::WindowCloseButtonHint)
- styleMask |= NSClosableWindowMask;
+ styleMask |= NSWindowStyleMaskClosable;
if (flags & Qt::WindowMinimizeButtonHint)
- styleMask |= NSMiniaturizableWindowMask;
+ styleMask |= NSWindowStyleMaskMiniaturizable;
if (flags & Qt::WindowMaximizeButtonHint)
- styleMask |= NSResizableWindowMask;
+ styleMask |= NSWindowStyleMaskResizable;
} else {
- styleMask |= NSClosableWindowMask | NSTitledWindowMask;
+ styleMask |= NSWindowStyleMaskClosable | NSWindowStyleMaskTitled;
if (type != Qt::Dialog)
- styleMask |= NSMiniaturizableWindowMask;
+ styleMask |= NSWindowStyleMaskMiniaturizable;
}
if (type == Qt::Tool)
- styleMask |= NSUtilityWindowMask;
+ styleMask |= NSWindowStyleMaskUtilityWindow;
if (m_drawContentBorderGradient)
- styleMask |= NSTexturedBackgroundWindowMask;
+ styleMask |= NSWindowStyleMaskTexturedBackground;
// Don't wipe fullscreen state
- if (m_view.window.styleMask & NSFullScreenWindowMask)
- styleMask |= NSFullScreenWindowMask;
+ if (m_view.window.styleMask & NSWindowStyleMaskFullScreen)
+ styleMask |= NSWindowStyleMaskFullScreen;
return styleMask;
}
@@ -562,54 +541,289 @@ void QCocoaWindow::setWindowZoomButton(Qt::WindowFlags flags)
void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags)
{
- if (isContentView()) {
- // While setting style mask we can have handleGeometryChange calls on a content
- // view with null geometry, reporting an invalid coordinates as a result.
- m_inSetStyleMask = true;
- m_view.window.styleMask = windowStyleMask(flags);
- m_inSetStyleMask = false;
- m_view.window.level = this->windowLevel(flags);
-
- m_view.window.hasShadow = !(flags & Qt::NoDropShadowWindowHint);
-
- if (!(flags & Qt::FramelessWindowHint))
- setWindowTitle(window()->title());
-
- Qt::WindowType type = window()->type();
- if ((type & Qt::Popup) != Qt::Popup && (type & Qt::Dialog) != Qt::Dialog) {
- NSWindowCollectionBehavior behavior = m_view.window.collectionBehavior;
- if ((flags & Qt::WindowFullscreenButtonHint) || m_view.window.qt_fullScreen) {
- behavior |= NSWindowCollectionBehaviorFullScreenPrimary;
- behavior &= ~NSWindowCollectionBehaviorFullScreenAuxiliary;
- } else {
- behavior |= NSWindowCollectionBehaviorFullScreenAuxiliary;
- behavior &= ~NSWindowCollectionBehaviorFullScreenPrimary;
- }
- m_view.window.collectionBehavior = behavior;
+ // Updating the window flags may affect the window's theme frame, which
+ // in the process retains and then autoreleases the NSWindow. To make
+ // sure this doesn't leave lingering releases when there is no pool in
+ // place (e.g. during main(), before exec), we add one locally here.
+ QMacAutoReleasePool pool;
+
+ if (!isContentView())
+ return;
+
+ // While setting style mask we can have handleGeometryChange calls on a content
+ // view with null geometry, reporting an invalid coordinates as a result.
+ m_inSetStyleMask = true;
+ m_view.window.styleMask = windowStyleMask(flags);
+ m_inSetStyleMask = false;
+
+ Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
+ if ((type & Qt::Popup) != Qt::Popup && (type & Qt::Dialog) != Qt::Dialog) {
+ NSWindowCollectionBehavior behavior = m_view.window.collectionBehavior;
+ if ((flags & Qt::WindowFullscreenButtonHint) || m_view.window.qt_fullScreen) {
+ behavior |= NSWindowCollectionBehaviorFullScreenPrimary;
+ behavior &= ~NSWindowCollectionBehaviorFullScreenAuxiliary;
+ } else {
+ behavior |= NSWindowCollectionBehaviorFullScreenAuxiliary;
+ behavior &= ~NSWindowCollectionBehaviorFullScreenPrimary;
}
- setWindowZoomButton(flags);
-
- // Make window ignore mouse events if WindowTransparentForInput is set.
- // Note that ignoresMouseEvents has a special initial state where events
- // are ignored (passed through) based on window transparency, and that
- // setting the property to false does not return us to that state. Instead,
- // this makes the window capture all mouse events. Take care to only
- // set the property if needed. FIXME: recreate window if needed or find
- // some other way to implement WindowTransparentForInput.
- bool ignoreMouse = flags & Qt::WindowTransparentForInput;
- if (m_view.window.ignoresMouseEvents != ignoreMouse)
- m_view.window.ignoresMouseEvents = ignoreMouse;
+ m_view.window.collectionBehavior = behavior;
}
- m_windowFlags = flags;
+ // Set styleMask and collectionBehavior before applying window level, as
+ // the window level change will trigger verification of the two properties.
+ m_view.window.level = this->windowLevel(flags);
+
+ m_view.window.hasShadow = !(flags & Qt::NoDropShadowWindowHint);
+
+ if (!(flags & Qt::FramelessWindowHint))
+ setWindowTitle(window()->title());
+
+ setWindowZoomButton(flags);
+
+ // Make window ignore mouse events if WindowTransparentForInput is set.
+ // Note that ignoresMouseEvents has a special initial state where events
+ // are ignored (passed through) based on window transparency, and that
+ // setting the property to false does not return us to that state. Instead,
+ // this makes the window capture all mouse events. Take care to only
+ // set the property if needed. FIXME: recreate window if needed or find
+ // some other way to implement WindowTransparentForInput.
+ bool ignoreMouse = flags & Qt::WindowTransparentForInput;
+ if (m_view.window.ignoresMouseEvents != ignoreMouse)
+ m_view.window.ignoresMouseEvents = ignoreMouse;
}
+// ----------------------- Window state -----------------------
+
+/*!
+ Changes the state of the NSWindow, going in/out of minimize/zoomed/fullscreen
+
+ When this is called from QWindow::setWindowState(), the QWindow state has not been
+ updated yet, so window()->windowState() will reflect the previous state that was
+ reported to QtGui.
+*/
void QCocoaWindow::setWindowState(Qt::WindowStates state)
{
if (window()->isVisible())
applyWindowState(state); // Window state set for hidden windows take effect when show() is called
}
+void QCocoaWindow::applyWindowState(Qt::WindowStates requestedState)
+{
+ if (!isContentView())
+ return;
+
+ const Qt::WindowState currentState = windowState();
+ const Qt::WindowState newState = QWindowPrivate::effectiveState(requestedState);
+
+ if (newState == currentState)
+ return;
+
+ qCDebug(lcQpaWindow) << "Applying" << newState << "to" << window() << "in" << currentState;
+
+ const NSSize contentSize = m_view.frame.size;
+ if (contentSize.width <= 0 || contentSize.height <= 0) {
+ // If content view width or height is 0 then the window animations will crash so
+ // do nothing. We report the current state back to reflect the failed operation.
+ qWarning("invalid window content view size, check your window geometry");
+ handleWindowStateChanged(HandleUnconditionally);
+ return;
+ }
+
+ const NSWindow *nsWindow = m_view.window;
+
+ if (nsWindow.styleMask & NSWindowStyleMaskUtilityWindow
+ && newState & (Qt::WindowMinimized | Qt::WindowFullScreen)) {
+ qWarning() << window()->type() << "windows can not be made" << newState;
+ handleWindowStateChanged(HandleUnconditionally);
+ return;
+ }
+
+ const id sender = nsWindow;
+
+ // First we need to exit states that can't transition directly to other states
+ switch (currentState) {
+ case Qt::WindowMinimized:
+ [nsWindow deminiaturize:sender];
+ Q_ASSERT_X(windowState() != Qt::WindowMinimized, "QCocoaWindow",
+ "[NSWindow deminiaturize:] is synchronous");
+ break;
+ case Qt::WindowFullScreen: {
+ toggleFullScreen();
+ // Exiting fullscreen is not synchronous, so we need to wait for the
+ // NSWindowDidExitFullScreenNotification before continuing to apply
+ // the new state.
+ return;
+ }
+ default:;
+ }
+
+ // Then we apply the new state if needed
+ if (newState == windowState())
+ return;
+
+ switch (newState) {
+ case Qt::WindowFullScreen:
+ toggleFullScreen();
+ break;
+ case Qt::WindowMaximized:
+ toggleMaximized();
+ break;
+ case Qt::WindowMinimized:
+ [nsWindow miniaturize:sender];
+ break;
+ case Qt::WindowNoState:
+ if (windowState() == Qt::WindowMaximized)
+ toggleMaximized();
+ break;
+ default:
+ Q_UNREACHABLE();
+ }
+}
+
+Qt::WindowState QCocoaWindow::windowState() const
+{
+ // FIXME: Support compound states (Qt::WindowStates)
+
+ NSWindow *window = m_view.window;
+ if (window.miniaturized)
+ return Qt::WindowMinimized;
+ if (window.qt_fullScreen)
+ return Qt::WindowFullScreen;
+ if ((window.zoomed && !isTransitioningToFullScreen())
+ || (m_lastReportedWindowState == Qt::WindowMaximized && isTransitioningToFullScreen()))
+ return Qt::WindowMaximized;
+
+ // Note: We do not report Qt::WindowActive, even if isActive()
+ // is true, as QtGui does not expect this window state to be set.
+
+ return Qt::WindowNoState;
+}
+
+void QCocoaWindow::toggleMaximized()
+{
+ const NSWindow *window = m_view.window;
+
+ // The NSWindow needs to be resizable, otherwise the window will
+ // not be possible to zoom back to non-zoomed state.
+ const bool wasResizable = window.styleMask & NSWindowStyleMaskResizable;
+ window.styleMask |= NSWindowStyleMaskResizable;
+
+ const id sender = window;
+ [window zoom:sender];
+
+ if (!wasResizable)
+ window.styleMask &= ~NSWindowStyleMaskResizable;
+}
+
+void QCocoaWindow::toggleFullScreen()
+{
+ const NSWindow *window = m_view.window;
+
+ // The window needs to have the correct collection behavior for the
+ // toggleFullScreen call to have an effect. The collection behavior
+ // will be reset in windowDidEnterFullScreen/windowDidLeaveFullScreen.
+ window.collectionBehavior |= NSWindowCollectionBehaviorFullScreenPrimary;
+
+ const id sender = window;
+ [window toggleFullScreen:sender];
+}
+
+void QCocoaWindow::windowWillEnterFullScreen()
+{
+ if (!isContentView())
+ return;
+
+ // The NSWindow needs to be resizable, otherwise we'll end up with
+ // the normal window geometry, centered in the middle of the screen
+ // on a black background. The styleMask will be reset below.
+ m_view.window.styleMask |= NSWindowStyleMaskResizable;
+}
+
+bool QCocoaWindow::isTransitioningToFullScreen() const
+{
+ NSWindow *window = m_view.window;
+ return window.styleMask & NSWindowStyleMaskFullScreen && !window.qt_fullScreen;
+}
+
+void QCocoaWindow::windowDidEnterFullScreen()
+{
+ if (!isContentView())
+ return;
+
+ Q_ASSERT_X(m_view.window.qt_fullScreen, "QCocoaWindow",
+ "FullScreen category processes window notifications first");
+
+ // Reset to original styleMask
+ setWindowFlags(window()->flags());
+
+ handleWindowStateChanged();
+}
+
+void QCocoaWindow::windowWillExitFullScreen()
+{
+ if (!isContentView())
+ return;
+
+ // The NSWindow needs to be resizable, otherwise we'll end up with
+ // a weird zoom animation. The styleMask will be reset below.
+ m_view.window.styleMask |= NSWindowStyleMaskResizable;
+}
+
+void QCocoaWindow::windowDidExitFullScreen()
+{
+ if (!isContentView())
+ return;
+
+ Q_ASSERT_X(!m_view.window.qt_fullScreen, "QCocoaWindow",
+ "FullScreen category processes window notifications first");
+
+ // Reset to original styleMask
+ setWindowFlags(window()->flags());
+
+ Qt::WindowState requestedState = window()->windowState();
+
+ // Deliver update of QWindow state
+ handleWindowStateChanged();
+
+ if (requestedState != windowState() && requestedState != Qt::WindowFullScreen) {
+ // We were only going out of full screen as an intermediate step before
+ // progressing into the final step, so re-sync the desired state.
+ applyWindowState(requestedState);
+ }
+}
+
+void QCocoaWindow::windowDidMiniaturize()
+{
+ if (!isContentView())
+ return;
+
+ handleWindowStateChanged();
+}
+
+void QCocoaWindow::windowDidDeminiaturize()
+{
+ if (!isContentView())
+ return;
+
+ handleWindowStateChanged();
+}
+
+void QCocoaWindow::handleWindowStateChanged(HandleFlags flags)
+{
+ Qt::WindowState currentState = windowState();
+ if (!(flags & HandleUnconditionally) && currentState == m_lastReportedWindowState)
+ return;
+
+ qCDebug(lcQpaWindow) << "QCocoaWindow::handleWindowStateChanged" <<
+ m_lastReportedWindowState << "-->" << currentState;
+
+ QWindowSystemInterface::handleWindowStateChanged<QWindowSystemInterface::SynchronousDelivery>(
+ window(), currentState, m_lastReportedWindowState);
+ m_lastReportedWindowState = currentState;
+}
+
+// ------------------------------------------------------------
+
void QCocoaWindow::setWindowTitle(const QString &title)
{
if (!isContentView())
@@ -680,7 +894,7 @@ bool QCocoaWindow::isAlertState() const
void QCocoaWindow::raise()
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::raise" << window();
+ qCDebug(lcQpaWindow) << "QCocoaWindow::raise" << window();
// ### handle spaces (see Qt 4 raise_sys in qwidget_mac.mm)
if (!isContentView())
@@ -705,7 +919,7 @@ void QCocoaWindow::raise()
void QCocoaWindow::lower()
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::lower" << window();
+ qCDebug(lcQpaWindow) << "QCocoaWindow::lower" << window();
if (!isContentView())
return;
@@ -718,6 +932,22 @@ bool QCocoaWindow::isExposed() const
return !m_exposedRect.isEmpty();
}
+bool QCocoaWindow::isEmbedded() const
+{
+ // Child QWindows are not embedded
+ if (window()->parent())
+ return false;
+
+ // Top-level QWindows with non-Qt NSWindows are embedded
+ if (m_view.window)
+ return !([m_view.window isKindOfClass:[QNSWindow class]] ||
+ [m_view.window isKindOfClass:[QNSPanel class]]);
+
+ // The window has no QWindow parent but also no NSWindow,
+ // conservatively reuturn false.
+ return false;
+}
+
bool QCocoaWindow::isOpaque() const
{
// OpenGL surfaces can be ordered either above(default) or below the NSWindow.
@@ -737,7 +967,7 @@ void QCocoaWindow::propagateSizeHints()
if (!isContentView())
return;
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::propagateSizeHints" << window()
+ qCDebug(lcQpaWindow) << "QCocoaWindow::propagateSizeHints" << window()
<< "min:" << windowMinimumSize() << "max:" << windowMaximumSize()
<< "increment:" << windowSizeIncrement()
<< "base:" << windowBaseSize();
@@ -754,7 +984,7 @@ void QCocoaWindow::propagateSizeHints()
window.contentMaxSize = NSSizeFromCGSize(windowMaximumSize().toCGSize());
// The window may end up with a fixed size; in this case the zoom button should be disabled.
- setWindowZoomButton(m_windowFlags);
+ setWindowZoomButton(this->window()->flags());
// sizeIncrement is observed to take values of (-1, -1) and (0, 0) for windows that should be
// resizable and that have no specific size increment set. Cocoa expects (1.0, 1.0) in this case.
@@ -771,7 +1001,7 @@ void QCocoaWindow::propagateSizeHints()
void QCocoaWindow::setOpacity(qreal level)
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setOpacity" << level;
+ qCDebug(lcQpaWindow) << "QCocoaWindow::setOpacity" << level;
if (!isContentView())
return;
@@ -780,7 +1010,7 @@ void QCocoaWindow::setOpacity(qreal level)
void QCocoaWindow::setMask(const QRegion &region)
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setMask" << window() << region;
+ qCDebug(lcQpaWindow) << "QCocoaWindow::setMask" << window() << region;
if (m_view.layer) {
if (!region.isEmpty()) {
@@ -803,18 +1033,12 @@ void QCocoaWindow::setMask(const QRegion &region)
// time, and so would not result in an updated backingstore.
m_needsInvalidateShadow = true;
[m_view setNeedsDisplay:YES];
-
- // FIXME: [NSWindow invalidateShadow] has no effect when in layer-backed mode,
- // so if the mask is changed after the initial mask is applied, it will not
- // result in any visual change to the shadow. This is an Apple bug, and there
- // may be ways to work around it, such as calling setFrame on the window to
- // trigger some internal invalidation, but that needs more research.
}
}
bool QCocoaWindow::setKeyboardGrabEnabled(bool grab)
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setKeyboardGrabEnabled" << window() << grab;
+ qCDebug(lcQpaWindow) << "QCocoaWindow::setKeyboardGrabEnabled" << window() << grab;
if (!isContentView())
return false;
@@ -826,7 +1050,7 @@ bool QCocoaWindow::setKeyboardGrabEnabled(bool grab)
bool QCocoaWindow::setMouseGrabEnabled(bool grab)
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setMouseGrabEnabled" << window() << grab;
+ qCDebug(lcQpaWindow) << "QCocoaWindow::setMouseGrabEnabled" << window() << grab;
if (!isContentView())
return false;
@@ -843,10 +1067,10 @@ WId QCocoaWindow::winId() const
void QCocoaWindow::setParent(const QPlatformWindow *parentWindow)
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setParent" << window() << (parentWindow ? parentWindow->window() : 0);
+ qCDebug(lcQpaWindow) << "QCocoaWindow::setParent" << window() << (parentWindow ? parentWindow->window() : 0);
// recreate the window for compatibility
- bool unhideAfterRecreate = parentWindow && !m_viewIsToBeEmbedded && ![m_view isHidden];
+ bool unhideAfterRecreate = parentWindow && !isEmbedded() && ![m_view isHidden];
recreateWindowIfNeeded();
if (unhideAfterRecreate)
[m_view setHidden:NO];
@@ -863,9 +1087,8 @@ NSWindow *QCocoaWindow::nativeWindow() const
return m_view.window;
}
-void QCocoaWindow::setEmbeddedInForeignView(bool embedded)
+void QCocoaWindow::setEmbeddedInForeignView()
{
- m_viewIsToBeEmbedded = embedded;
// Release any previosly created NSWindow.
[m_nsWindow closeAndRelease];
m_nsWindow = 0;
@@ -948,8 +1171,8 @@ void QCocoaWindow::windowDidBecomeKey()
QWindowSystemInterface::handleEnterEvent(m_enterLeaveTargetWindow, windowPoint, screenPoint);
}
- if (!windowIsPopupType() && !qnsview_cast(m_view).isMenuView)
- QWindowSystemInterface::handleWindowActivated(window());
+ if (!windowIsPopupType())
+ QWindowSystemInterface::handleWindowActivated<QWindowSystemInterface::SynchronousDelivery>(window());
}
void QCocoaWindow::windowDidResignKey()
@@ -966,82 +1189,8 @@ void QCocoaWindow::windowDidResignKey()
NSWindow *keyWindow = [NSApp keyWindow];
if (!keyWindow || keyWindow == m_view.window) {
// No new key window, go ahead and set the active window to zero
- if (!windowIsPopupType() && !qnsview_cast(m_view).isMenuView)
- QWindowSystemInterface::handleWindowActivated(0);
- }
-}
-
-void QCocoaWindow::windowDidMiniaturize()
-{
- if (!isContentView())
- return;
-
- handleWindowStateChanged();
-}
-
-void QCocoaWindow::windowDidDeminiaturize()
-{
- if (!isContentView())
- return;
-
- handleWindowStateChanged();
-}
-
-void QCocoaWindow::windowWillEnterFullScreen()
-{
- if (!isContentView())
- return;
-
- // The NSWindow needs to be resizable, otherwise we'll end up with
- // the normal window geometry, centered in the middle of the screen
- // on a black background. The styleMask will be reset below.
- m_view.window.styleMask |= NSResizableWindowMask;
-}
-
-void QCocoaWindow::windowDidEnterFullScreen()
-{
- if (!isContentView())
- return;
-
- Q_ASSERT_X(m_view.window.qt_fullScreen, "QCocoaWindow",
- "FullScreen category processes window notifications first");
-
- // Reset to original styleMask
- setWindowFlags(m_windowFlags);
-
- handleWindowStateChanged();
-}
-
-void QCocoaWindow::windowWillExitFullScreen()
-{
- if (!isContentView())
- return;
-
- // The NSWindow needs to be resizable, otherwise we'll end up with
- // a weird zoom animation. The styleMask will be reset below.
- m_view.window.styleMask |= NSResizableWindowMask;
-}
-
-void QCocoaWindow::windowDidExitFullScreen()
-{
- if (!isContentView())
- return;
-
- Q_ASSERT_X(!m_view.window.qt_fullScreen, "QCocoaWindow",
- "FullScreen category processes window notifications first");
-
- // Reset to original styleMask
- setWindowFlags(m_windowFlags);
-
- Qt::WindowState requestedState = window()->windowState();
-
- // Deliver update of QWindow state
- handleWindowStateChanged();
-
- if (requestedState != windowState() && requestedState != Qt::WindowFullScreen) {
- // We were only going out of full screen as an intermediate step before
- // progressing into the final step, so re-sync the desired state.
- applyWindowState(requestedState);
+ if (!windowIsPopupType())
+ QWindowSystemInterface::handleWindowActivated<QWindowSystemInterface::SynchronousDelivery>(0);
}
}
@@ -1068,8 +1217,24 @@ void QCocoaWindow::windowDidChangeScreen()
if (!window())
return;
- if (QCocoaScreen *cocoaScreen = QCocoaIntegration::instance()->screenForNSScreen(m_view.window.screen))
- QWindowSystemInterface::handleWindowScreenChanged(window(), cocoaScreen->screen());
+ const bool wasRunningDisplayLink = static_cast<QCocoaScreen *>(screen())->isRunningDisplayLink();
+
+ if (QCocoaScreen *newScreen = QCocoaIntegration::instance()->screenForNSScreen(m_view.window.screen)) {
+ if (newScreen == screen()) {
+ // Screen properties have changed. Will be handled by
+ // NSApplicationDidChangeScreenParametersNotification
+ // in QCocoaIntegration::updateScreens().
+ return;
+ }
+
+ qCDebug(lcQpaWindow) << window() << "moved to" << newScreen;
+ QWindowSystemInterface::handleWindowScreenChanged<QWindowSystemInterface::SynchronousDelivery>(window(), newScreen->screen());
+
+ if (hasPendingUpdateRequest() && wasRunningDisplayLink)
+ requestUpdate(); // Restart display-link on new screen
+ } else {
+ qCWarning(lcQpaWindow) << "Failed to get QCocoaScreen for" << m_view.window.screen;
+ }
}
void QCocoaWindow::windowWillClose()
@@ -1083,7 +1248,7 @@ void QCocoaWindow::windowWillClose()
bool QCocoaWindow::windowShouldClose()
{
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::windowShouldClose" << window();
+ qCDebug(lcQpaWindow) << "QCocoaWindow::windowShouldClose" << window();
// This callback should technically only determine if the window
// should (be allowed to) close, but since our QPA API to determine
// that also involves actually closing the window we do both at the
@@ -1104,22 +1269,14 @@ void QCocoaWindow::handleGeometryChange()
if (!m_initialized)
return;
- // Don't send the geometry change if the QWindow is designated to be
- // embedded in a foreign view hierarchy but has not actually been
- // embedded yet - it's too early.
- if (m_viewIsToBeEmbedded && !m_viewIsEmbedded)
- return;
-
// It can happen that the current NSWindow is nil (if we are changing styleMask
// from/to borderless, and the content view is being re-parented), which results
// in invalid coordinates.
if (m_inSetStyleMask && !m_view.window)
return;
- const bool isEmbedded = m_viewIsToBeEmbedded || m_viewIsEmbedded;
-
QRect newGeometry;
- if (isContentView() && !isEmbedded) {
+ if (isContentView() && !isEmbedded()) {
// Content views are positioned at (0, 0) in the window, so we resolve via the window
CGRect contentRect = [m_view.window contentRectForFrameRect:m_view.window.frame];
@@ -1130,7 +1287,7 @@ void QCocoaWindow::handleGeometryChange()
newGeometry = QRectF::fromCGRect(m_view.frame).toRect();
}
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::handleGeometryChange" << window()
+ qCDebug(lcQpaWindow) << "QCocoaWindow::handleGeometryChange" << window()
<< "current" << geometry() << "new" << newGeometry;
QWindowSystemInterface::handleGeometryChange(window(), newGeometry);
@@ -1162,24 +1319,10 @@ void QCocoaWindow::handleExposeEvent(const QRegion &region)
m_exposedRect = QRect();
}
- qCDebug(lcQpaCocoaDrawing) << "QCocoaWindow::handleExposeEvent" << window() << region << "isExposed" << isExposed();
+ qCDebug(lcQpaDrawing) << "QCocoaWindow::handleExposeEvent" << window() << region << "isExposed" << isExposed();
QWindowSystemInterface::handleExposeEvent<QWindowSystemInterface::SynchronousDelivery>(window(), region);
}
-void QCocoaWindow::handleWindowStateChanged(HandleFlags flags)
-{
- Qt::WindowState currentState = windowState();
- if (!(flags & HandleUnconditionally) && currentState == m_lastReportedWindowState)
- return;
-
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::handleWindowStateChanged" <<
- m_lastReportedWindowState << "-->" << currentState;
-
- QWindowSystemInterface::handleWindowStateChanged<QWindowSystemInterface::SynchronousDelivery>(
- window(), currentState, m_lastReportedWindowState);
- m_lastReportedWindowState = currentState;
-}
-
// --------------------------------------------------------------------------
bool QCocoaWindow::windowIsPopupType(Qt::WindowType type) const
@@ -1192,18 +1335,6 @@ bool QCocoaWindow::windowIsPopupType(Qt::WindowType type) const
return ((type & Qt::Popup) == Qt::Popup);
}
-#ifndef QT_NO_OPENGL
-void QCocoaWindow::setCurrentContext(QCocoaGLContext *context)
-{
- m_glContext = context;
-}
-
-QCocoaGLContext *QCocoaWindow::currentContext() const
-{
- return m_glContext;
-}
-#endif
-
/*!
Checks if the window is the content view of its immediate NSWindow.
@@ -1230,6 +1361,7 @@ void QCocoaWindow::recreateWindowIfNeeded()
QPlatformWindow *parentWindow = QPlatformWindow::parent();
+ const bool isEmbeddedView = isEmbedded();
RecreationReasons recreateReason = RecreationNotNeeded;
QCocoaWindow *oldParentCocoaWindow = nullptr;
@@ -1246,11 +1378,14 @@ void QCocoaWindow::recreateWindowIfNeeded()
if (m_windowModality != window()->modality())
recreateReason |= WindowModalityChanged;
- const bool shouldBeContentView = !parentWindow && !(m_viewIsToBeEmbedded || m_viewIsEmbedded);
+ Qt::WindowType type = window()->type();
+
+ const bool shouldBeContentView = !parentWindow
+ && !((type & Qt::SubWindow) == Qt::SubWindow)
+ && !isEmbeddedView;
if (isContentView() != shouldBeContentView)
recreateReason |= ContentViewChanged;
- Qt::WindowType type = window()->type();
const bool isPanel = isContentView() && [m_view.window isKindOfClass:[QNSPanel class]];
const bool shouldBePanel = shouldBeContentView &&
((type & Qt::Popup) == Qt::Popup || (type & Qt::Dialog) == Qt::Dialog);
@@ -1258,7 +1393,7 @@ void QCocoaWindow::recreateWindowIfNeeded()
if (isPanel != shouldBePanel)
recreateReason |= PanelChanged;
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::recreateWindowIfNeeded" << window() << recreateReason;
+ qCDebug(lcQpaWindow) << "QCocoaWindow::recreateWindowIfNeeded" << window() << recreateReason;
if (recreateReason == RecreationNotNeeded)
return;
@@ -1268,33 +1403,28 @@ void QCocoaWindow::recreateWindowIfNeeded()
// Remove current window (if any)
if ((isContentView() && !shouldBeContentView) || (recreateReason & PanelChanged)) {
if (m_nsWindow) {
- qCDebug(lcQpaCocoaWindow) << "Getting rid of existing window" << m_nsWindow;
+ qCDebug(lcQpaWindow) << "Getting rid of existing window" << m_nsWindow;
if (m_nsWindow.observationInfo) {
- qCCritical(lcQpaCocoaWindow) << m_nsWindow << "has active key-value observers (KVO)!"
+ qCCritical(lcQpaWindow) << m_nsWindow << "has active key-value observers (KVO)!"
<< "These will stop working now that the window is recreated, and will result in exceptions"
<< "when the observers are removed. Break in QCocoaWindow::recreateWindowIfNeeded to debug.";
}
[m_nsWindow closeAndRelease];
- if (isContentView()) {
+ if (isContentView() && !isEmbeddedView) {
// We explicitly disassociate m_view from the window's contentView,
// as AppKit does not automatically do this in response to removing
// the view from the NSThemeFrame subview list, so we might end up
// with a NSWindow contentView pointing to a deallocated NSView.
m_view.window.contentView = nil;
}
- m_nsWindow = 0;
+ m_nsWindow = nil;
}
}
- if (shouldBeContentView) {
- bool noPreviousWindow = m_nsWindow == 0;
- QCocoaNSWindow *newWindow = nullptr;
- if (noPreviousWindow)
- newWindow = createNSWindow(shouldBePanel);
-
+ if (shouldBeContentView && !m_nsWindow) {
// Move view to new NSWindow if needed
- if (newWindow) {
- qCDebug(lcQpaCocoaWindow) << "Ensuring that" << m_view << "is content view for" << newWindow;
+ if (auto *newWindow = createNSWindow(shouldBePanel)) {
+ qCDebug(lcQpaWindow) << "Ensuring that" << m_view << "is content view for" << newWindow;
[m_view setPostsFrameChangedNotifications:NO];
[newWindow setContentView:m_view];
[m_view setPostsFrameChangedNotifications:YES];
@@ -1304,14 +1434,14 @@ void QCocoaWindow::recreateWindowIfNeeded()
}
}
- if (m_viewIsToBeEmbedded) {
+ if (isEmbeddedView) {
// An embedded window doesn't have its own NSWindow.
} else if (!parentWindow) {
// QPlatformWindow subclasses must sync up with QWindow on creation:
propagateSizeHints();
setWindowFlags(window()->flags());
setWindowTitle(window()->title());
- setWindowFilePath(window()->filePath());
+ setWindowFilePath(window()->filePath()); // Also sets window icon
setWindowState(window()->windowState());
} else {
// Child windows have no NSWindow, link the NSViews instead.
@@ -1334,14 +1464,28 @@ void QCocoaWindow::recreateWindowIfNeeded()
// top-level QWindows may have an attached NSToolBar, call
// update function which will attach to the NSWindow.
- if (!parentWindow)
+ if (!parentWindow && !isEmbeddedView)
updateNSToolbar();
}
void QCocoaWindow::requestUpdate()
{
- qCDebug(lcQpaCocoaDrawing) << "QCocoaWindow::requestUpdate" << window();
- QPlatformWindow::requestUpdate();
+ const int swapInterval = format().swapInterval();
+ qCDebug(lcQpaDrawing) << "QCocoaWindow::requestUpdate" << window() << "swapInterval" << swapInterval;
+
+ if (swapInterval > 0) {
+ // Vsync is enabled, deliver via CVDisplayLink
+ static_cast<QCocoaScreen *>(screen())->requestUpdate();
+ } else {
+ // Fall back to the un-throttled timer-based callback
+ QPlatformWindow::requestUpdate();
+ }
+}
+
+void QCocoaWindow::deliverUpdateRequest()
+{
+ qCDebug(lcQpaDrawing) << "Delivering update request to" << window();
+ QPlatformWindow::deliverUpdateRequest();
}
void QCocoaWindow::requestActivateWindow()
@@ -1375,7 +1519,7 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel)
}
if (!targetScreen) {
- qCWarning(lcQpaCocoaWindow) << "Window position" << rect << "outside any known screen, using primary screen";
+ qCWarning(lcQpaWindow) << "Window position" << rect << "outside any known screen, using primary screen";
targetScreen = QGuiApplication::primaryScreen();
// AppKit will only reposition a window that's outside the target screen area if
// the window has a title bar. If left out, the window ends up with no screen.
@@ -1399,8 +1543,10 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel)
Q_ASSERT_X(nsWindow.screen == cocoaScreen->nativeScreen(), "QCocoaWindow",
"Resulting NSScreen should match the requested NSScreen");
- if (targetScreen != window()->screen())
- QWindowSystemInterface::handleWindowScreenChanged(window(), targetScreen);
+ if (targetScreen != window()->screen()) {
+ QWindowSystemInterface::handleWindowScreenChanged<
+ QWindowSystemInterface::SynchronousDelivery>(window(), targetScreen);
+ }
nsWindow.delegate = [[QNSWindowDelegate alloc] initWithQCocoaWindow:this];
@@ -1473,138 +1619,6 @@ void QCocoaWindow::removeMonitor()
monitor = nil;
}
-/*!
- Applies the given state to the NSWindow, going in/out of minimize/zoomed/fullscreen
-
- When this is called from QWindow::setWindowState(), the QWindow state has not been
- updated yet, so window()->windowState() will reflect the previous state that was
- reported to QtGui.
-*/
-void QCocoaWindow::applyWindowState(Qt::WindowStates requestedState)
-{
- if (!isContentView())
- return;
-
- const Qt::WindowState currentState = windowState();
- const Qt::WindowState newState = QWindowPrivate::effectiveState(requestedState);
-
- if (newState == currentState)
- return;
-
- const NSSize contentSize = m_view.frame.size;
- if (contentSize.width <= 0 || contentSize.height <= 0) {
- // If content view width or height is 0 then the window animations will crash so
- // do nothing. We report the current state back to reflect the failed operation.
- qWarning("invalid window content view size, check your window geometry");
- handleWindowStateChanged(HandleUnconditionally);
- return;
- }
-
- const NSWindow *nsWindow = m_view.window;
-
- if (nsWindow.styleMask & NSUtilityWindowMask
- && newState & (Qt::WindowMinimized | Qt::WindowFullScreen)) {
- qWarning() << window()->type() << "windows can not be made" << newState;
- handleWindowStateChanged(HandleUnconditionally);
- return;
- }
-
- const id sender = nsWindow;
-
- // First we need to exit states that can't transition directly to other states
- switch (currentState) {
- case Qt::WindowMinimized:
- [nsWindow deminiaturize:sender];
- Q_ASSERT_X(windowState() != Qt::WindowMinimized, "QCocoaWindow",
- "[NSWindow deminiaturize:] is synchronous");
- break;
- case Qt::WindowFullScreen: {
- toggleFullScreen();
- // Exiting fullscreen is not synchronous, so we need to wait for the
- // NSWindowDidExitFullScreenNotification before continuing to apply
- // the new state.
- return;
- }
- default:;
- }
-
- // Then we apply the new state if needed
- if (newState == windowState())
- return;
-
- switch (newState) {
- case Qt::WindowFullScreen:
- toggleFullScreen();
- break;
- case Qt::WindowMaximized:
- toggleMaximized();
- break;
- case Qt::WindowMinimized:
- [nsWindow miniaturize:sender];
- break;
- case Qt::WindowNoState:
- if (windowState() == Qt::WindowMaximized)
- toggleMaximized();
- break;
- default:
- Q_UNREACHABLE();
- }
-}
-
-void QCocoaWindow::toggleMaximized()
-{
- const NSWindow *window = m_view.window;
-
- // The NSWindow needs to be resizable, otherwise the window will
- // not be possible to zoom back to non-zoomed state.
- const bool wasResizable = window.styleMask & NSResizableWindowMask;
- window.styleMask |= NSResizableWindowMask;
-
- const id sender = window;
- [window zoom:sender];
-
- if (!wasResizable)
- window.styleMask &= ~NSResizableWindowMask;
-}
-
-void QCocoaWindow::toggleFullScreen()
-{
- const NSWindow *window = m_view.window;
-
- // The window needs to have the correct collection behavior for the
- // toggleFullScreen call to have an effect. The collection behavior
- // will be reset in windowDidEnterFullScreen/windowDidLeaveFullScreen.
- window.collectionBehavior |= NSWindowCollectionBehaviorFullScreenPrimary;
-
- const id sender = window;
- [window toggleFullScreen:sender];
-}
-
-bool QCocoaWindow::isTransitioningToFullScreen() const
-{
- NSWindow *window = m_view.window;
- return window.styleMask & NSFullScreenWindowMask && !window.qt_fullScreen;
-}
-
-Qt::WindowState QCocoaWindow::windowState() const
-{
- // FIXME: Support compound states (Qt::WindowStates)
-
- NSWindow *window = m_view.window;
- if (window.miniaturized)
- return Qt::WindowMinimized;
- if (window.qt_fullScreen)
- return Qt::WindowFullScreen;
- if ((window.zoomed && !isTransitioningToFullScreen())
- || (m_lastReportedWindowState == Qt::WindowMaximized && isTransitioningToFullScreen()))
- return Qt::WindowMaximized;
-
- // Note: We do not report Qt::WindowActive, even if isActive()
- // is true, as QtGui does not expect this window state to be set.
-
- return Qt::WindowNoState;
-}
-
bool QCocoaWindow::setWindowModified(bool modified)
{
if (!isContentView())
@@ -1685,7 +1699,7 @@ void QCocoaWindow::applyContentBorderThickness(NSWindow *window)
return;
if (!m_drawContentBorderGradient) {
- window.styleMask = window.styleMask & ~NSTexturedBackgroundWindowMask;
+ window.styleMask = window.styleMask & ~NSWindowStyleMaskTexturedBackground;
[window.contentView.superview setNeedsDisplay:YES];
window.titlebarAppearsTransparent = NO;
return;
@@ -1711,7 +1725,7 @@ void QCocoaWindow::applyContentBorderThickness(NSWindow *window)
int effectiveBottomContentBorderThickness = m_bottomContentBorderThickness;
- [window setStyleMask:[window styleMask] | NSTexturedBackgroundWindowMask];
+ [window setStyleMask:[window styleMask] | NSWindowStyleMaskTexturedBackground];
window.titlebarAppearsTransparent = YES;
// Setting titlebarAppearsTransparent to YES means that the border thickness has to account
diff --git a/src/plugins/platforms/cocoa/qmacclipboard.h b/src/plugins/platforms/cocoa/qmacclipboard.h
index 1d229a55d2..f2f460c048 100644
--- a/src/plugins/platforms/cocoa/qmacclipboard.h
+++ b/src/plugins/platforms/cocoa/qmacclipboard.h
@@ -54,7 +54,7 @@ public:
enum DataRequestType { EagerRequest, LazyRequest };
private:
struct Promise {
- Promise() : itemId(0), convertor(0) { }
+ Promise() : itemId(0), convertor(nullptr) { }
static Promise eagerPromise(int itemId, QMacInternalPasteboardMime *c, QString m, QMacMimeData *d, int o = 0);
static Promise lazyPromise(int itemId, QMacInternalPasteboardMime *c, QString m, QMacMimeData *d, int o = 0);
@@ -79,7 +79,7 @@ private:
public:
QMacPasteboard(PasteboardRef p, uchar mime_type=0);
QMacPasteboard(uchar mime_type);
- QMacPasteboard(CFStringRef name=0, uchar mime_type=0);
+ QMacPasteboard(CFStringRef name=nullptr, uchar mime_type=0);
~QMacPasteboard();
bool hasFlavor(QString flavor) const;
diff --git a/src/plugins/platforms/cocoa/qmacclipboard.mm b/src/plugins/platforms/cocoa/qmacclipboard.mm
index f3467fdc73..5939003c64 100644
--- a/src/plugins/platforms/cocoa/qmacclipboard.mm
+++ b/src/plugins/platforms/cocoa/qmacclipboard.mm
@@ -75,7 +75,7 @@ QMacPasteboard::Promise::Promise(int itemId, QMacInternalPasteboardMime *c, QStr
// Request the data from the application immediately for eager requests.
if (dataRequestType == QMacPasteboard::EagerRequest) {
variantData = md->variantData(m);
- mimeData = 0;
+ mimeData = nullptr;
} else {
mimeData = md;
}
@@ -94,8 +94,8 @@ QMacPasteboard::QMacPasteboard(uchar mt)
{
mac_mime_source = false;
mime_type = mt ? mt : uchar(QMacInternalPasteboardMime::MIME_ALL);
- paste = 0;
- OSStatus err = PasteboardCreate(0, &paste);
+ paste = nullptr;
+ OSStatus err = PasteboardCreate(nullptr, &paste);
if (err == noErr) {
PasteboardSetPromiseKeeper(paste, promiseKeeper, this);
} else {
@@ -108,7 +108,7 @@ QMacPasteboard::QMacPasteboard(CFStringRef name, uchar mt)
{
mac_mime_source = false;
mime_type = mt ? mt : uchar(QMacInternalPasteboardMime::MIME_ALL);
- paste = 0;
+ paste = nullptr;
OSStatus err = PasteboardCreate(name, &paste);
if (err == noErr) {
PasteboardSetPromiseKeeper(paste, promiseKeeper, this);
@@ -165,7 +165,7 @@ OSStatus QMacPasteboard::promiseKeeper(PasteboardRef paste, PasteboardItemID id,
// we have promised this data, but won't be able to convert, so return null data.
// This helps in making the application/x-qt-mime-type-name hidden from normal use.
QByteArray ba;
- QCFType<CFDataRef> data = CFDataCreate(0, (UInt8*)ba.constData(), ba.size());
+ QCFType<CFDataRef> data = CFDataCreate(nullptr, (UInt8*)ba.constData(), ba.size());
PasteboardPutItemFlavor(paste, id, flavor, data, kPasteboardFlavorNoFlags);
return noErr;
}
@@ -196,7 +196,7 @@ OSStatus QMacPasteboard::promiseKeeper(PasteboardRef paste, PasteboardItemID id,
if (md.size() <= promise.offset)
return cantGetFlavorErr;
const QByteArray &ba = md[promise.offset];
- QCFType<CFDataRef> data = CFDataCreate(0, (UInt8*)ba.constData(), ba.size());
+ QCFType<CFDataRef> data = CFDataCreate(nullptr, (UInt8*)ba.constData(), ba.size());
PasteboardPutItemFlavor(paste, id, flavor, data, kPasteboardFlavorNoFlags);
return noErr;
}
@@ -553,7 +553,7 @@ QMacPasteboard::sync() const
const bool fromGlobal = PasteboardSynchronize(paste) & kPasteboardModified;
if (fromGlobal)
- const_cast<QMacPasteboard *>(this)->setMimeData(0);
+ const_cast<QMacPasteboard *>(this)->setMimeData(nullptr);
#ifdef DEBUG_PASTEBOARD
if (fromGlobal)
diff --git a/src/plugins/platforms/cocoa/qmultitouch_mac.mm b/src/plugins/platforms/cocoa/qmultitouch_mac.mm
index 9eca4d2d43..10652dc6a1 100644
--- a/src/plugins/platforms/cocoa/qmultitouch_mac.mm
+++ b/src/plugins/platforms/cocoa/qmultitouch_mac.mm
@@ -107,7 +107,7 @@ QCocoaTouch *QCocoaTouch::findQCocoaTouch(NSTouch *nstouch)
qint64 identity = qint64([nstouch identity]);
if (_currentTouches.contains(identity))
return _currentTouches.value(identity);
- return 0;
+ return nullptr;
}
Qt::TouchPointState QCocoaTouch::toTouchPointState(NSTouchPhase nsState)
diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h
index e2ea862cd5..b40dfe0d14 100644
--- a/src/plugins/platforms/cocoa/qnsview.h
+++ b/src/plugins/platforms/cocoa/qnsview.h
@@ -41,111 +41,45 @@
#define QNSVIEW_H
#include <AppKit/AppKit.h>
-
-#include <QtCore/QPointer>
-#include <QtCore/QSet>
-#include <QtGui/QImage>
-#include <QtGui/QAccessible>
+#include <MetalKit/MetalKit.h>
#include "private/qcore_mac_p.h"
QT_BEGIN_NAMESPACE
class QCocoaWindow;
class QCocoaGLContext;
+class QPointF;
QT_END_NAMESPACE
Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
+Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QCocoaNSMenuItem));
-@interface QT_MANGLE_NAMESPACE(QNSView) : NSView <NSTextInputClient> {
- QPointer<QCocoaWindow> m_platformWindow;
- NSTrackingArea *m_trackingArea;
- Qt::MouseButtons m_buttons;
- Qt::MouseButtons m_acceptedMouseDowns;
- Qt::MouseButtons m_frameStrutButtons;
- QString m_composingText;
- QPointer<QObject> m_composingFocusObject;
- bool m_sendKeyEvent;
- QStringList *currentCustomDragTypes;
- bool m_dontOverrideCtrlLMB;
- bool m_sendUpAsRightButton;
- Qt::KeyboardModifiers currentWheelModifiers;
-#ifndef QT_NO_OPENGL
- QCocoaGLContext *m_glContext;
- bool m_shouldSetGLContextinDrawRect;
-#endif
- NSString *m_inputSource;
- QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) *m_mouseMoveHelper;
- bool m_resendKeyEvent;
- bool m_scrolling;
- bool m_updatingDrag;
- NSEvent *m_currentlyInterpretedKeyEvent;
- bool m_isMenuView;
- QSet<quint32> m_acceptedKeyDowns;
- bool m_updateRequested;
-}
+@interface QT_MANGLE_NAMESPACE(QNSView) : NSView
@property (nonatomic, retain) NSCursor *cursor;
-- (id)init;
-- (id)initWithCocoaWindow:(QCocoaWindow *)platformWindow;
-#ifndef QT_NO_OPENGL
-- (void)setQCocoaGLContext:(QCocoaGLContext *)context;
-#endif
-- (void)drawRect:(NSRect)dirtyRect;
-- (void)textInputContextKeyboardSelectionDidChangeNotification : (NSNotification *) textInputContextKeyboardSelectionDidChangeNotification;
-- (void)viewDidHide;
-- (void)removeFromSuperview;
-- (void)cancelComposingText;
-
-- (BOOL)isFlipped;
-- (BOOL)acceptsFirstResponder;
-- (BOOL)becomeFirstResponder;
-- (BOOL)isOpaque;
+- (instancetype)initWithCocoaWindow:(QCocoaWindow *)platformWindow;
- (void)convertFromScreen:(NSPoint)mouseLocation toWindowPoint:(QPointF *)qtWindowPoint andScreenPoint:(QPointF *)qtScreenPoint;
-- (void)resetMouseButtons;
+@end
-- (void)requestUpdate;
-
-- (void)handleMouseEvent:(NSEvent *)theEvent;
-- (bool)handleMouseDownEvent:(NSEvent *)theEvent withButton:(int)buttonNumber;
-- (bool)handleMouseDraggedEvent:(NSEvent *)theEvent withButton:(int)buttonNumber;
-- (bool)handleMouseUpEvent:(NSEvent *)theEvent withButton:(int)buttonNumber;
-- (void)mouseDown:(NSEvent *)theEvent;
-- (void)mouseDragged:(NSEvent *)theEvent;
-- (void)mouseUp:(NSEvent *)theEvent;
-- (void)mouseMovedImpl:(NSEvent *)theEvent;
-- (void)mouseEnteredImpl:(NSEvent *)theEvent;
-- (void)mouseExitedImpl:(NSEvent *)theEvent;
-- (void)rightMouseDown:(NSEvent *)theEvent;
-- (void)rightMouseDragged:(NSEvent *)theEvent;
-- (void)rightMouseUp:(NSEvent *)theEvent;
-- (void)otherMouseDown:(NSEvent *)theEvent;
-- (void)otherMouseDragged:(NSEvent *)theEvent;
-- (void)otherMouseUp:(NSEvent *)theEvent;
+@interface QT_MANGLE_NAMESPACE(QNSView) (MouseAPI)
- (void)handleFrameStrutMouseEvent:(NSEvent *)theEvent;
+- (void)resetMouseButtons;
+@end
-#ifndef QT_NO_TABLETEVENT
-- (bool)handleTabletEvent: (NSEvent *)theEvent;
-- (void)tabletPoint: (NSEvent *)theEvent;
-- (void)tabletProximity: (NSEvent *)theEvent;
-#endif
-
-- (int) convertKeyCode : (QChar)keyCode;
-+ (Qt::KeyboardModifiers) convertKeyModifiers : (ulong)modifierFlags;
-- (bool)handleKeyEvent:(NSEvent *)theEvent eventType:(int)eventType;
-- (void)keyDown:(NSEvent *)theEvent;
-- (void)keyUp:(NSEvent *)theEvent;
-
-- (void)registerDragTypes;
-- (NSDragOperation)handleDrag:(id <NSDraggingInfo>)sender;
+@interface QT_MANGLE_NAMESPACE(QNSView) (KeysAPI)
++ (Qt::KeyboardModifiers)convertKeyModifiers:(ulong)modifierFlags;
+@end
+@interface QT_MANGLE_NAMESPACE(QNSView) (ComplexTextAPI)
+- (void)unmarkText;
+- (void)cancelComposingText;
@end
@interface QT_MANGLE_NAMESPACE(QNSView) (QtExtras)
@property (nonatomic, readonly) QCocoaWindow *platformWindow;
-@property (nonatomic, readonly) BOOL isMenuView;
@end
QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSView);
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 1c400a1ec9..9bd53ed334 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -51,7 +51,11 @@
#include <qpa/qwindowsysteminterface.h>
#include <QtGui/QTextFormat>
#include <QtCore/QDebug>
+#include <QtCore/QPointer>
+#include <QtCore/QSet>
#include <QtCore/qsysinfo.h>
+#include <QtGui/QAccessible>
+#include <QtGui/QImage>
#include <private/qguiapplication_p.h>
#include <private/qcoregraphics_p.h>
#include <private/qwindow_p.h>
@@ -61,94 +65,112 @@
#endif
#include "qcocoaintegration.h"
-#ifdef QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR
-#include <accessibilityinspector.h>
-#endif
+// Private interface
+@interface QT_MANGLE_NAMESPACE(QNSView) ()
+- (BOOL)isTransparentForUserInput;
+@end
-Q_LOGGING_CATEGORY(lcQpaTouch, "qt.qpa.input.touch")
-#ifndef QT_NO_GESTURES
-Q_LOGGING_CATEGORY(lcQpaGestures, "qt.qpa.input.gestures")
-#endif
-Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
+@interface QT_MANGLE_NAMESPACE(QNSView) (Drawing) <CALayerDelegate>
+- (BOOL)wantsLayerHelper;
+@end
@interface QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) : NSObject
-{
- QNSView *view;
-}
-
-- (id)initWithView:(QNSView *)theView;
-
+- (instancetype)initWithView:(QNSView *)theView;
- (void)mouseMoved:(NSEvent *)theEvent;
- (void)mouseEntered:(NSEvent *)theEvent;
- (void)mouseExited:(NSEvent *)theEvent;
- (void)cursorUpdate:(NSEvent *)theEvent;
-
@end
-@implementation QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper)
-
-- (id)initWithView:(QNSView *)theView
-{
- self = [super init];
- if (self) {
- view = theView;
- }
- return self;
-}
-
-- (void)mouseMoved:(NSEvent *)theEvent
-{
- [view mouseMovedImpl:theEvent];
-}
+@interface QT_MANGLE_NAMESPACE(QNSView) (Mouse)
+- (NSPoint)screenMousePoint:(NSEvent *)theEvent;
+- (void)mouseMovedImpl:(NSEvent *)theEvent;
+- (void)mouseEnteredImpl:(NSEvent *)theEvent;
+- (void)mouseExitedImpl:(NSEvent *)theEvent;
+@end
-- (void)mouseEntered:(NSEvent *)theEvent
-{
- [view mouseEnteredImpl:theEvent];
-}
+@interface QT_MANGLE_NAMESPACE(QNSView) (Touch)
+@end
-- (void)mouseExited:(NSEvent *)theEvent
-{
- [view mouseExitedImpl:theEvent];
-}
+@interface QT_MANGLE_NAMESPACE(QNSView) (Tablet)
+- (bool)handleTabletEvent:(NSEvent *)theEvent;
+@end
-- (void)cursorUpdate:(NSEvent *)theEvent
-{
- [view cursorUpdate:theEvent];
-}
+@interface QT_MANGLE_NAMESPACE(QNSView) (Gestures)
+@end
+@interface QT_MANGLE_NAMESPACE(QNSView) (Dragging)
+-(void)registerDragTypes;
@end
-// Private interface
-@interface QT_MANGLE_NAMESPACE(QNSView) ()
-- (BOOL)isTransparentForUserInput;
+@interface QT_MANGLE_NAMESPACE(QNSView) (Keys)
@end
-@implementation QT_MANGLE_NAMESPACE(QNSView)
+@interface QT_MANGLE_NAMESPACE(QNSView) (ComplexText) <NSTextInputClient>
+- (void)textInputContextKeyboardSelectionDidChangeNotification:(NSNotification *)textInputContextKeyboardSelectionDidChangeNotification;
+@end
-- (id) init
-{
- if (self = [super initWithFrame:NSZeroRect]) {
+@implementation QT_MANGLE_NAMESPACE(QNSView) {
+ QPointer<QCocoaWindow> m_platformWindow;
+ NSTrackingArea *m_trackingArea;
+ Qt::MouseButtons m_buttons;
+ Qt::MouseButtons m_acceptedMouseDowns;
+ Qt::MouseButtons m_frameStrutButtons;
+ QString m_composingText;
+ QPointer<QObject> m_composingFocusObject;
+ bool m_sendKeyEvent;
+ bool m_dontOverrideCtrlLMB;
+ bool m_sendUpAsRightButton;
+ Qt::KeyboardModifiers m_currentWheelModifiers;
+ NSString *m_inputSource;
+ QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) *m_mouseMoveHelper;
+ bool m_resendKeyEvent;
+ bool m_scrolling;
+ bool m_updatingDrag;
+ NSEvent *m_currentlyInterpretedKeyEvent;
+ QSet<quint32> m_acceptedKeyDowns;
+}
+
+- (instancetype)initWithCocoaWindow:(QCocoaWindow *)platformWindow
+{
+ if ((self = [super initWithFrame:NSZeroRect])) {
+ m_platformWindow = platformWindow;
m_buttons = Qt::NoButton;
m_acceptedMouseDowns = Qt::NoButton;
m_frameStrutButtons = Qt::NoButton;
m_sendKeyEvent = false;
-#ifndef QT_NO_OPENGL
- m_glContext = 0;
- m_shouldSetGLContextinDrawRect = false;
-#endif
- currentCustomDragTypes = 0;
- m_dontOverrideCtrlLMB = false;
m_sendUpAsRightButton = false;
- m_inputSource = 0;
+ m_inputSource = nil;
m_mouseMoveHelper = [[QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) alloc] initWithView:self];
m_resendKeyEvent = false;
m_scrolling = false;
m_updatingDrag = false;
- m_currentlyInterpretedKeyEvent = 0;
- m_isMenuView = false;
+ m_currentlyInterpretedKeyEvent = nil;
+ m_dontOverrideCtrlLMB = qt_mac_resolveOption(false, platformWindow->window(),
+ "_q_platform_MacDontOverrideCtrlLMB", "QT_MAC_DONT_OVERRIDE_CTRL_LMB");
+ m_trackingArea = nil;
+
self.focusRingType = NSFocusRingTypeNone;
self.cursor = nil;
- m_updateRequested = false;
+ self.wantsLayer = [self wantsLayerHelper];
+
+ // Enable high-DPI OpenGL for retina displays. Enabling has the side
+ // effect that Cocoa will start calling glViewport(0, 0, width, height),
+ // overriding any glViewport calls in application code. This is usually not a
+ // problem, except if the application wants to have a "custom" viewport.
+ // (like the hellogl example)
+ if (m_platformWindow->window()->supportsOpenGL()) {
+ self.wantsBestResolutionOpenGLSurface = qt_mac_resolveOption(YES, m_platformWindow->window(),
+ "_q_mac_wantsBestResolutionOpenGLSurface", "QT_MAC_WANTS_BEST_RESOLUTION_OPENGL_SURFACE");
+ // See also QCocoaGLContext::makeCurrent for software renderer workarounds.
+ }
+
+ [self registerDragTypes];
+
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(textInputContextKeyboardSelectionDidChangeNotification:)
+ name:NSTextInputContextKeyboardSelectionDidChangeNotification
+ object:nil];
}
return self;
}
@@ -163,47 +185,9 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
[[NSNotificationCenter defaultCenter] removeObserver:self];
[m_mouseMoveHelper release];
- delete currentCustomDragTypes;
-
[super dealloc];
}
-- (id)initWithCocoaWindow:(QCocoaWindow *)platformWindow
-{
- self = [self init];
- if (!self)
- return 0;
-
- m_platformWindow = platformWindow;
- m_sendKeyEvent = false;
- m_dontOverrideCtrlLMB = qt_mac_resolveOption(false, platformWindow->window(), "_q_platform_MacDontOverrideCtrlLMB", "QT_MAC_DONT_OVERRIDE_CTRL_LMB");
- m_trackingArea = nil;
-
-#ifdef QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR
- // prevent rift in space-time continuum, disable
- // accessibility for the accessibility inspector's windows.
- static bool skipAccessibilityForInspectorWindows = false;
- if (!skipAccessibilityForInspectorWindows) {
-
- // m_accessibleRoot = window->accessibleRoot();
-
- AccessibilityInspector *inspector = new AccessibilityInspector(window);
- skipAccessibilityForInspectorWindows = true;
- inspector->inspectWindow(window);
- skipAccessibilityForInspectorWindows = false;
- }
-#endif
-
- [self registerDragTypes];
-
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(textInputContextKeyboardSelectionDidChangeNotification:)
- name:NSTextInputContextKeyboardSelectionDidChangeNotification
- object:nil];
-
- return self;
-}
-
- (NSString *)description
{
NSMutableString *description = [NSMutableString stringWithString:[super description]];
@@ -220,33 +204,18 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
return description;
}
-#ifndef QT_NO_OPENGL
-- (void) setQCocoaGLContext:(QCocoaGLContext *)context
-{
- m_glContext = context;
- [m_glContext->nsOpenGLContext() setView:self];
- if (![m_glContext->nsOpenGLContext() view]) {
- //was unable to set view
- m_shouldSetGLContextinDrawRect = true;
- }
-}
-#endif
-
- (void)viewDidMoveToSuperview
{
if (!m_platformWindow)
return;
- if (!(m_platformWindow->m_viewIsToBeEmbedded))
+ if (!m_platformWindow->isEmbedded())
return;
if ([self superview]) {
- m_platformWindow->m_viewIsEmbedded = true;
QWindowSystemInterface::handleGeometryChange(m_platformWindow->window(), m_platformWindow->geometry());
[self setNeedsDisplay:YES];
QWindowSystemInterface::flushWindowSystemEvents();
- } else {
- m_platformWindow->m_viewIsEmbedded = false;
}
}
@@ -268,15 +237,6 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
return focusWindow;
}
-- (void)textInputContextKeyboardSelectionDidChangeNotification : (NSNotification *) textInputContextKeyboardSelectionDidChangeNotification
-{
- Q_UNUSED(textInputContextKeyboardSelectionDidChangeNotification)
- if (([NSApp keyWindow] == [self window]) && [[self window] firstResponder] == self) {
- QCocoaInputContext *ic = qobject_cast<QCocoaInputContext *>(QCocoaIntegration::instance()->inputContext());
- ic->updateLocale();
- }
-}
-
- (void)viewDidHide
{
if (!m_platformWindow->isExposed())
@@ -294,107 +254,6 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
[super removeFromSuperview];
}
-- (BOOL) isOpaque
-{
- if (!m_platformWindow)
- return true;
- return m_platformWindow->isOpaque();
-}
-
-- (void)requestUpdate
-{
- if (self.needsDisplay) {
- // If the view already has needsDisplay set it means that there may be code waiting for
- // a real expose event, so we can't issue setNeedsDisplay now as a way to trigger an
- // update request. We will re-trigger requestUpdate from drawRect.
- return;
- }
-
- [self setNeedsDisplay:YES];
- m_updateRequested = true;
-}
-
-- (void)setNeedsDisplayInRect:(NSRect)rect
-{
- [super setNeedsDisplayInRect:rect];
- m_updateRequested = false;
-}
-
-- (void)drawRect:(NSRect)dirtyRect
-{
- Q_UNUSED(dirtyRect);
-
- if (!m_platformWindow)
- return;
-
- QRegion exposedRegion;
- const NSRect *dirtyRects;
- NSInteger numDirtyRects;
- [self getRectsBeingDrawn:&dirtyRects count:&numDirtyRects];
- for (int i = 0; i < numDirtyRects; ++i)
- exposedRegion += QRectF::fromCGRect(dirtyRects[i]).toRect();
-
- qCDebug(lcQpaCocoaDrawing) << "[QNSView drawRect:]" << m_platformWindow->window() << exposedRegion;
- [self updateRegion:exposedRegion];
-}
-
-- (void)updateRegion:(QRegion)dirtyRegion
-{
-#ifndef QT_NO_OPENGL
- if (m_glContext && m_shouldSetGLContextinDrawRect) {
- [m_glContext->nsOpenGLContext() setView:self];
- m_shouldSetGLContextinDrawRect = false;
- }
-#endif
-
- QWindowPrivate *windowPrivate = qt_window_private(m_platformWindow->window());
-
- if (m_updateRequested) {
- Q_ASSERT(windowPrivate->updateRequestPending);
- qCDebug(lcQpaCocoaWindow) << "Delivering update request to" << m_platformWindow->window();
- windowPrivate->deliverUpdateRequest();
- m_updateRequested = false;
- } else {
- m_platformWindow->handleExposeEvent(dirtyRegion);
- }
-
- if (m_updateRequested && windowPrivate->updateRequestPending) {
- // A call to QWindow::requestUpdate was issued during event delivery above,
- // but AppKit will reset the needsDisplay state of the view after completing
- // the current display cycle, so we need to defer the request to redisplay.
- // FIXME: Perhaps this should be a trigger to enable CADisplayLink?
- qCDebug(lcQpaCocoaDrawing) << "[QNSView drawRect:] issuing deferred setNeedsDisplay due to pending update request";
- dispatch_async(dispatch_get_main_queue (), ^{ [self requestUpdate]; });
- }
-}
-
-- (BOOL)wantsUpdateLayer
-{
- return YES;
-}
-
-- (void)updateLayer
-{
- if (!m_platformWindow)
- return;
-
- qCDebug(lcQpaCocoaDrawing) << "[QNSView updateLayer]" << m_platformWindow->window();
-
- // FIXME: Find out if there's a way to resolve the dirty rect like in drawRect:
- [self updateRegion:QRectF::fromCGRect(self.bounds).toRect()];
-}
-
-- (void)viewDidChangeBackingProperties
-{
- if (self.layer)
- self.layer.contentsScale = self.window.backingScaleFactor;
-}
-
-- (BOOL)isFlipped
-{
- return YES;
-}
-
- (BOOL)isTransparentForUserInput
{
return m_platformWindow->window() &&
@@ -407,7 +266,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
return NO;
if ([self isTransparentForUserInput])
return NO;
- if (!m_platformWindow->windowIsPopupType() && !m_isMenuView)
+ if (!m_platformWindow->windowIsPopupType())
QWindowSystemInterface::handleWindowActivated([self topLevelWindow]);
return YES;
}
@@ -416,8 +275,6 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
{
if (!m_platformWindow)
return NO;
- if (m_isMenuView)
- return NO;
if (m_platformWindow->shouldRefuseKeyWindowAndFirstResponder())
return NO;
if ([self isTransparentForUserInput])
@@ -427,16 +284,6 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
return YES;
}
-- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
-{
- Q_UNUSED(theEvent)
- if (!m_platformWindow)
- return NO;
- if ([self isTransparentForUserInput])
- return NO;
- return YES;
-}
-
- (NSView *)hitTest:(NSPoint)aPoint
{
NSView *candidate = [super hitTest:aPoint];
@@ -476,1611 +323,22 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
*qtScreenPoint = QCocoaScreen::mapFromNative(mouseLocation);
}
-- (void)resetMouseButtons
-{
- m_buttons = Qt::NoButton;
- m_frameStrutButtons = Qt::NoButton;
-}
-
-- (NSPoint) screenMousePoint:(NSEvent *)theEvent
-{
- NSPoint screenPoint;
- if (theEvent) {
- NSPoint windowPoint = [theEvent locationInWindow];
- if (qIsNaN(windowPoint.x) || qIsNaN(windowPoint.y)) {
- screenPoint = [NSEvent mouseLocation];
- } else {
- NSRect screenRect = [[theEvent window] convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 1, 1)];
- screenPoint = screenRect.origin;
- }
- } else {
- screenPoint = [NSEvent mouseLocation];
- }
- return screenPoint;
-}
-
-- (void)handleMouseEvent:(NSEvent *)theEvent
-{
- if (!m_platformWindow)
- return;
-
-#ifndef QT_NO_TABLETEVENT
- // Tablet events may come in via the mouse event handlers,
- // check if this is a valid tablet event first.
- if ([self handleTabletEvent: theEvent])
- return;
-#endif
-
- QPointF qtWindowPoint;
- QPointF qtScreenPoint;
- QNSView *targetView = self;
- if (!targetView.platformWindow)
- return;
-
- // Popups implicitly grap mouse events; forward to the active popup if there is one
- if (QCocoaWindow *popup = QCocoaIntegration::instance()->activePopupWindow()) {
- // Tooltips must be transparent for mouse events
- // The bug reference is QTBUG-46379
- if (!popup->m_windowFlags.testFlag(Qt::ToolTip)) {
- if (QNSView *popupView = qnsview_cast(popup->view()))
- targetView = popupView;
- }
- }
-
- [targetView convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint];
- ulong timestamp = [theEvent timestamp] * 1000;
-
- QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag();
- nativeDrag->setLastMouseEvent(theEvent, self);
-
- Qt::KeyboardModifiers keyboardModifiers = [QNSView convertKeyModifiers:[theEvent modifierFlags]];
- QWindowSystemInterface::handleMouseEvent(targetView->m_platformWindow->window(), timestamp, qtWindowPoint, qtScreenPoint,
- m_buttons, keyboardModifiers, Qt::MouseEventNotSynthesized);
-}
-
-- (void)handleFrameStrutMouseEvent:(NSEvent *)theEvent
-{
- if (!m_platformWindow)
- return;
-
- // get m_buttons in sync
- // Don't send frme strut events if we are in the middle of a mouse drag.
- if (m_buttons != Qt::NoButton)
- return;
-
- NSEventType ty = [theEvent type];
- switch (ty) {
- case NSLeftMouseDown:
- m_frameStrutButtons |= Qt::LeftButton;
- break;
- case NSLeftMouseUp:
- m_frameStrutButtons &= ~Qt::LeftButton;
- break;
- case NSRightMouseDown:
- m_frameStrutButtons |= Qt::RightButton;
- break;
- case NSLeftMouseDragged:
- m_frameStrutButtons |= Qt::LeftButton;
- break;
- case NSRightMouseDragged:
- m_frameStrutButtons |= Qt::RightButton;
- break;
- case NSRightMouseUp:
- m_frameStrutButtons &= ~Qt::RightButton;
- break;
- case NSOtherMouseDown:
- m_frameStrutButtons |= cocoaButton2QtButton([theEvent buttonNumber]);
- break;
- case NSOtherMouseUp:
- m_frameStrutButtons &= ~cocoaButton2QtButton([theEvent buttonNumber]);
- default:
- break;
- }
-
- NSWindow *window = [self window];
- NSPoint windowPoint = [theEvent locationInWindow];
-
- int windowScreenY = [window frame].origin.y + [window frame].size.height;
- NSPoint windowCoord = [self convertPoint:[self frame].origin toView:nil];
- int viewScreenY = [window convertRectToScreen:NSMakeRect(windowCoord.x, windowCoord.y, 0, 0)].origin.y;
- int titleBarHeight = windowScreenY - viewScreenY;
-
- NSPoint nsViewPoint = [self convertPoint: windowPoint fromView: nil];
- QPoint qtWindowPoint = QPoint(nsViewPoint.x, titleBarHeight + nsViewPoint.y);
- NSPoint screenPoint = [window convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 0, 0)].origin;
- QPoint qtScreenPoint = QCocoaScreen::mapFromNative(screenPoint).toPoint();
-
- ulong timestamp = [theEvent timestamp] * 1000;
- QWindowSystemInterface::handleFrameStrutMouseEvent(m_platformWindow->window(), timestamp, qtWindowPoint, qtScreenPoint, m_frameStrutButtons);
-}
-
-- (bool)handleMouseDownEvent:(NSEvent *)theEvent withButton:(int)buttonNumber
-{
- if ([self isTransparentForUserInput])
- return false;
-
- Qt::MouseButton button = cocoaButton2QtButton(buttonNumber);
-
- QPointF qtWindowPoint;
- QPointF qtScreenPoint;
- [self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint];
- Q_UNUSED(qtScreenPoint);
-
- // Maintain masked state for the button for use by MouseDragged and MouseUp.
- QRegion mask = m_platformWindow->window()->mask();
- const bool masked = !mask.isEmpty() && !mask.contains(qtWindowPoint.toPoint());
- if (masked)
- m_acceptedMouseDowns &= ~button;
- else
- m_acceptedMouseDowns |= button;
-
- // Forward masked out events to the next responder
- if (masked)
- return false;
-
- m_buttons |= button;
-
- [self handleMouseEvent:theEvent];
- return true;
-}
-
-- (bool)handleMouseDraggedEvent:(NSEvent *)theEvent withButton:(int)buttonNumber
-{
- if ([self isTransparentForUserInput])
- return false;
-
- Qt::MouseButton button = cocoaButton2QtButton(buttonNumber);
-
- // Forward the event to the next responder if Qt did not accept the
- // corresponding mouse down for this button
- if (!(m_acceptedMouseDowns & button) == button)
- return false;
-
- [self handleMouseEvent:theEvent];
- return true;
-}
-
-- (bool)handleMouseUpEvent:(NSEvent *)theEvent withButton:(int)buttonNumber
-{
- if ([self isTransparentForUserInput])
- return false;
-
- Qt::MouseButton button = cocoaButton2QtButton(buttonNumber);
-
- // Forward the event to the next responder if Qt did not accept the
- // corresponding mouse down for this button
- if (!(m_acceptedMouseDowns & button) == button)
- return false;
-
- if (m_sendUpAsRightButton && button == Qt::LeftButton)
- button = Qt::RightButton;
- if (button == Qt::RightButton)
- m_sendUpAsRightButton = false;
-
- m_buttons &= ~button;
-
- [self handleMouseEvent:theEvent];
- return true;
-}
-
-- (void)mouseDown:(NSEvent *)theEvent
-{
- if ([self isTransparentForUserInput])
- return [super mouseDown:theEvent];
- m_sendUpAsRightButton = false;
-
- // Handle any active poup windows; clicking outisde them should close them
- // all. Don't do anything or clicks inside one of the menus, let Cocoa
- // handle that case. Note that in practice many windows of the Qt::Popup type
- // will actually close themselves in this case using logic implemented in
- // that particular poup type (for example context menus). However, Qt expects
- // that plain popup QWindows will also be closed, so we implement the logic
- // here as well.
- QList<QCocoaWindow *> *popups = QCocoaIntegration::instance()->popupWindowStack();
- if (!popups->isEmpty()) {
- // Check if the click is outside all popups.
- bool inside = false;
- QPointF qtScreenPoint = QCocoaScreen::mapFromNative([self screenMousePoint:theEvent]);
- for (QList<QCocoaWindow *>::const_iterator it = popups->begin(); it != popups->end(); ++it) {
- if ((*it)->geometry().contains(qtScreenPoint.toPoint())) {
- inside = true;
- break;
- }
- }
- // Close the popups if the click was outside.
- if (!inside) {
- Qt::WindowType type = QCocoaIntegration::instance()->activePopupWindow()->window()->type();
- while (QCocoaWindow *popup = QCocoaIntegration::instance()->popPopupWindow()) {
- QWindowSystemInterface::handleCloseEvent(popup->window());
- QWindowSystemInterface::flushWindowSystemEvents();
- }
- // Consume the mouse event when closing the popup, except for tool tips
- // were it's expected that the event is processed normally.
- if (type != Qt::ToolTip)
- return;
- }
- }
-
- QPointF qtWindowPoint;
- QPointF qtScreenPoint;
- [self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint];
- Q_UNUSED(qtScreenPoint);
-
- QRegion mask = m_platformWindow->window()->mask();
- const bool masked = !mask.isEmpty() && !mask.contains(qtWindowPoint.toPoint());
- // Maintain masked state for the button for use by MouseDragged and Up.
- if (masked)
- m_acceptedMouseDowns &= ~Qt::LeftButton;
- else
- m_acceptedMouseDowns |= Qt::LeftButton;
-
- // Forward masked out events to the next responder
- if (masked) {
- [super mouseDown:theEvent];
- return;
- }
-
- if ([self hasMarkedText]) {
- [[NSTextInputContext currentInputContext] handleEvent:theEvent];
- } else {
- auto ctrlOrMetaModifier = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta) ? Qt::ControlModifier : Qt::MetaModifier;
- if (!m_dontOverrideCtrlLMB && [QNSView convertKeyModifiers:[theEvent modifierFlags]] & ctrlOrMetaModifier) {
- m_buttons |= Qt::RightButton;
- m_sendUpAsRightButton = true;
- } else {
- m_buttons |= Qt::LeftButton;
- }
- [self handleMouseEvent:theEvent];
- }
-}
-
-- (void)mouseDragged:(NSEvent *)theEvent
-{
- const bool accepted = [self handleMouseDraggedEvent:theEvent withButton:[theEvent buttonNumber]];
- if (!accepted)
- [super mouseDragged:theEvent];
-}
-
-- (void)mouseUp:(NSEvent *)theEvent
-{
- const bool accepted = [self handleMouseUpEvent:theEvent withButton:[theEvent buttonNumber]];
- if (!accepted)
- [super mouseUp:theEvent];
-}
-
-- (void)rightMouseDown:(NSEvent *)theEvent
-{
- // Wacom tablet might not return the correct button number for NSEvent buttonNumber
- // on right clicks. Decide here that the button is the "right" button and forward
- // the button number to the mouse (and tablet) handler.
- const bool accepted = [self handleMouseDownEvent:theEvent withButton:1];
- if (!accepted)
- [super rightMouseDown:theEvent];
-}
-
-- (void)rightMouseDragged:(NSEvent *)theEvent
-{
- const bool accepted = [self handleMouseDraggedEvent:theEvent withButton:1];
- if (!accepted)
- [super rightMouseDragged:theEvent];
-}
-
-- (void)rightMouseUp:(NSEvent *)theEvent
-{
- const bool accepted = [self handleMouseUpEvent:theEvent withButton:1];
- if (!accepted)
- [super rightMouseUp:theEvent];
-}
-
-- (void)otherMouseDown:(NSEvent *)theEvent
-{
- const bool accepted = [self handleMouseDownEvent:theEvent withButton:[theEvent buttonNumber]];
- if (!accepted)
- [super otherMouseDown:theEvent];
-}
-
-- (void)otherMouseDragged:(NSEvent *)theEvent
-{
- const bool accepted = [self handleMouseDraggedEvent:theEvent withButton:[theEvent buttonNumber]];
- if (!accepted)
- [super otherMouseDragged:theEvent];
-}
-
-- (void)otherMouseUp:(NSEvent *)theEvent
-{
- const bool accepted = [self handleMouseUpEvent:theEvent withButton:[theEvent buttonNumber]];
- if (!accepted)
- [super otherMouseUp:theEvent];
-}
-
-- (void)updateTrackingAreas
-{
- [super updateTrackingAreas];
-
- QMacAutoReleasePool pool;
-
- // NSTrackingInVisibleRect keeps care of updating once the tracking is set up, so bail out early
- if (m_trackingArea && [[self trackingAreas] containsObject:m_trackingArea])
- return;
-
- // Ideally, we shouldn't have NSTrackingMouseMoved events included below, it should
- // only be turned on if mouseTracking, hover is on or a tool tip is set.
- // Unfortunately, Qt will send "tooltip" events on mouse moves, so we need to
- // turn it on in ALL case. That means EVERY QWindow gets to pay the cost of
- // mouse moves delivered to it (Apple recommends keeping it OFF because there
- // is a performance hit). So it goes.
- NSUInteger trackingOptions = NSTrackingMouseEnteredAndExited | NSTrackingActiveInActiveApp
- | NSTrackingInVisibleRect | NSTrackingMouseMoved | NSTrackingCursorUpdate;
- [m_trackingArea release];
- m_trackingArea = [[NSTrackingArea alloc] initWithRect:[self frame]
- options:trackingOptions
- owner:m_mouseMoveHelper
- userInfo:nil];
- [self addTrackingArea:m_trackingArea];
-}
-
-- (void)cursorUpdate:(NSEvent *)theEvent
-{
- qCDebug(lcQpaCocoaMouse) << "[QNSView cursorUpdate:]" << self.cursor;
-
- // Note: We do not get this callback when moving from a subview that
- // uses the legacy cursorRect API, so the cursor is reset to the arrow
- // cursor. See rdar://34183708
-
- if (self.cursor)
- [self.cursor set];
- else
- [super cursorUpdate:theEvent];
-}
-
-- (void)mouseMovedImpl:(NSEvent *)theEvent
-{
- if (!m_platformWindow)
- return;
-
- if ([self isTransparentForUserInput])
- return;
-
- QPointF windowPoint;
- QPointF screenPoint;
- [self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
- QWindow *childWindow = m_platformWindow->childWindowAt(windowPoint.toPoint());
-
- // Top-level windows generate enter-leave events for sub-windows.
- // Qt wants to know which window (if any) will be entered at the
- // the time of the leave. This is dificult to accomplish by
- // handling mouseEnter and mouseLeave envents, since they are sent
- // individually to different views.
- if (m_platformWindow->isContentView() && childWindow) {
- if (childWindow != m_platformWindow->m_enterLeaveTargetWindow) {
- QWindowSystemInterface::handleEnterLeaveEvent(childWindow, m_platformWindow->m_enterLeaveTargetWindow, windowPoint, screenPoint);
- m_platformWindow->m_enterLeaveTargetWindow = childWindow;
- }
- }
-
- // Cocoa keeps firing mouse move events for obscured parent views. Qt should not
- // send those events so filter them out here.
- if (childWindow != m_platformWindow->window())
- return;
-
- [self handleMouseEvent: theEvent];
-}
-
-- (void)mouseEnteredImpl:(NSEvent *)theEvent
-{
- Q_UNUSED(theEvent)
- if (!m_platformWindow)
- return;
-
- m_platformWindow->m_windowUnderMouse = true;
-
- if ([self isTransparentForUserInput])
- return;
-
- // Top-level windows generate enter events for sub-windows.
- if (!m_platformWindow->isContentView())
- return;
-
- QPointF windowPoint;
- QPointF screenPoint;
- [self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
- m_platformWindow->m_enterLeaveTargetWindow = m_platformWindow->childWindowAt(windowPoint.toPoint());
- QWindowSystemInterface::handleEnterEvent(m_platformWindow->m_enterLeaveTargetWindow, windowPoint, screenPoint);
-}
-
-- (void)mouseExitedImpl:(NSEvent *)theEvent
-{
- Q_UNUSED(theEvent);
- if (!m_platformWindow)
- return;
-
- m_platformWindow->m_windowUnderMouse = false;
-
- if ([self isTransparentForUserInput])
- return;
-
- // Top-level windows generate leave events for sub-windows.
- if (!m_platformWindow->isContentView())
- return;
-
- QWindowSystemInterface::handleLeaveEvent(m_platformWindow->m_enterLeaveTargetWindow);
- m_platformWindow->m_enterLeaveTargetWindow = 0;
-}
-
-#ifndef QT_NO_TABLETEVENT
-struct QCocoaTabletDeviceData
-{
- QTabletEvent::TabletDevice device;
- QTabletEvent::PointerType pointerType;
- uint capabilityMask;
- qint64 uid;
-};
-
-typedef QHash<uint, QCocoaTabletDeviceData> QCocoaTabletDeviceDataHash;
-Q_GLOBAL_STATIC(QCocoaTabletDeviceDataHash, tabletDeviceDataHash)
-
-- (bool)handleTabletEvent: (NSEvent *)theEvent
-{
- static bool ignoreButtonMapping = qEnvironmentVariableIsSet("QT_MAC_TABLET_IGNORE_BUTTON_MAPPING");
-
- if (!m_platformWindow)
- return false;
-
- NSEventType eventType = [theEvent type];
- if (eventType != NSTabletPoint && [theEvent subtype] != NSTabletPointEventSubtype)
- return false; // Not a tablet event.
-
- ulong timestamp = [theEvent timestamp] * 1000;
-
- QPointF windowPoint;
- QPointF screenPoint;
- [self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint: &windowPoint andScreenPoint: &screenPoint];
-
- uint deviceId = [theEvent deviceID];
- if (!tabletDeviceDataHash->contains(deviceId)) {
- // Error: Unknown tablet device. Qt also gets into this state
- // when running on a VM. This appears to be harmless; don't
- // print a warning.
- return false;
- }
- const QCocoaTabletDeviceData &deviceData = tabletDeviceDataHash->value(deviceId);
-
- bool down = (eventType != NSMouseMoved);
-
- qreal pressure;
- if (down) {
- pressure = [theEvent pressure];
- } else {
- pressure = 0.0;
- }
-
- NSPoint tilt = [theEvent tilt];
- int xTilt = qRound(tilt.x * 60.0);
- int yTilt = qRound(tilt.y * -60.0);
- qreal tangentialPressure = 0;
- qreal rotation = 0;
- int z = 0;
- if (deviceData.capabilityMask & 0x0200)
- z = [theEvent absoluteZ];
-
- if (deviceData.capabilityMask & 0x0800)
- tangentialPressure = ([theEvent tangentialPressure] * 2.0) - 1.0;
-
- rotation = 360.0 - [theEvent rotation];
- if (rotation > 180.0)
- rotation -= 360.0;
-
- Qt::KeyboardModifiers keyboardModifiers = [QNSView convertKeyModifiers:[theEvent modifierFlags]];
- Qt::MouseButtons buttons = ignoreButtonMapping ? static_cast<Qt::MouseButtons>(static_cast<uint>([theEvent buttonMask])) : m_buttons;
-
- qCDebug(lcQpaTablet, "event on tablet %d with tool %d type %d unique ID %lld pos %6.1f, %6.1f root pos %6.1f, %6.1f buttons 0x%x pressure %4.2lf tilt %d, %d rotation %6.2lf",
- deviceId, deviceData.device, deviceData.pointerType, deviceData.uid,
- windowPoint.x(), windowPoint.y(), screenPoint.x(), screenPoint.y(),
- static_cast<uint>(buttons), pressure, xTilt, yTilt, rotation);
-
- QWindowSystemInterface::handleTabletEvent(m_platformWindow->window(), timestamp, windowPoint, screenPoint,
- deviceData.device, deviceData.pointerType, buttons, pressure, xTilt, yTilt,
- tangentialPressure, rotation, z, deviceData.uid,
- keyboardModifiers);
- return true;
-}
-
-- (void)tabletPoint:(NSEvent *)theEvent
-{
- if ([self isTransparentForUserInput])
- return [super tabletPoint:theEvent];
-
- [self handleTabletEvent: theEvent];
-}
-
-static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
-{
- qint64 uid = [theEvent uniqueID];
- uint bits = [theEvent vendorPointingDeviceType];
- if (bits == 0 && uid != 0) {
- // Fallback. It seems that the driver doesn't always include all the information.
- // High-End Wacom devices store their "type" in the uper bits of the Unique ID.
- // I'm not sure how to handle it for consumer devices, but I'll test that in a bit.
- bits = uid >> 32;
- }
-
- QTabletEvent::TabletDevice device;
- // Defined in the "EN0056-NxtGenImpGuideX"
- // on Wacom's Developer Website (www.wacomeng.com)
- if (((bits & 0x0006) == 0x0002) && ((bits & 0x0F06) != 0x0902)) {
- device = QTabletEvent::Stylus;
- } else {
- switch (bits & 0x0F06) {
- case 0x0802:
- device = QTabletEvent::Stylus;
- break;
- case 0x0902:
- device = QTabletEvent::Airbrush;
- break;
- case 0x0004:
- device = QTabletEvent::FourDMouse;
- break;
- case 0x0006:
- device = QTabletEvent::Puck;
- break;
- case 0x0804:
- device = QTabletEvent::RotationStylus;
- break;
- default:
- device = QTabletEvent::NoDevice;
- }
- }
- return device;
-}
-
-- (void)tabletProximity:(NSEvent *)theEvent
-{
- if ([self isTransparentForUserInput])
- return [super tabletProximity:theEvent];
-
- ulong timestamp = [theEvent timestamp] * 1000;
-
- QCocoaTabletDeviceData deviceData;
- deviceData.uid = [theEvent uniqueID];
- deviceData.capabilityMask = [theEvent capabilityMask];
-
- switch ([theEvent pointingDeviceType]) {
- case NSUnknownPointingDevice:
- default:
- deviceData.pointerType = QTabletEvent::UnknownPointer;
- break;
- case NSPenPointingDevice:
- deviceData.pointerType = QTabletEvent::Pen;
- break;
- case NSCursorPointingDevice:
- deviceData.pointerType = QTabletEvent::Cursor;
- break;
- case NSEraserPointingDevice:
- deviceData.pointerType = QTabletEvent::Eraser;
- break;
- }
-
- deviceData.device = wacomTabletDevice(theEvent);
-
- // The deviceID is "unique" while in the proximity, it's a key that we can use for
- // linking up QCocoaTabletDeviceData to an event (especially if there are two devices in action).
- bool entering = [theEvent isEnteringProximity];
- uint deviceId = [theEvent deviceID];
- if (entering) {
- tabletDeviceDataHash->insert(deviceId, deviceData);
- } else {
- tabletDeviceDataHash->remove(deviceId);
- }
-
- qCDebug(lcQpaTablet, "proximity change on tablet %d: current tool %d type %d unique ID %lld",
- deviceId, deviceData.device, deviceData.pointerType, deviceData.uid);
+@end
- if (entering) {
- QWindowSystemInterface::handleTabletEnterProximityEvent(timestamp, deviceData.device, deviceData.pointerType, deviceData.uid);
- } else {
- QWindowSystemInterface::handleTabletLeaveProximityEvent(timestamp, deviceData.device, deviceData.pointerType, deviceData.uid);
- }
-}
+#include "qnsview_drawing.mm"
+#include "qnsview_mouse.mm"
+#include "qnsview_touch.mm"
+#include "qnsview_gestures.mm"
+#include "qnsview_tablet.mm"
+#include "qnsview_dragging.mm"
+#include "qnsview_keys.mm"
+#include "qnsview_complextext.mm"
+#include "qnsview_menus.mm"
+#ifndef QT_NO_ACCESSIBILITY
+#include "qnsview_accessibility.mm"
#endif
-- (bool)shouldSendSingleTouch
-{
- if (!m_platformWindow)
- return true;
-
- // QtWidgets expects single-point touch events, QtDeclarative does not.
- // Until there is an API we solve this by looking at the window class type.
- return m_platformWindow->window()->inherits("QWidgetWindow");
-}
-
-- (void)touchesBeganWithEvent:(NSEvent *)event
-{
- if (!m_platformWindow)
- return;
-
- const NSTimeInterval timestamp = [event timestamp];
- const QList<QWindowSystemInterface::TouchPoint> points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]);
- qCDebug(lcQpaTouch) << "touchesBeganWithEvent" << points << "from device" << hex << [event deviceID];
- QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), points);
-}
-
-- (void)touchesMovedWithEvent:(NSEvent *)event
-{
- if (!m_platformWindow)
- return;
-
- const NSTimeInterval timestamp = [event timestamp];
- const QList<QWindowSystemInterface::TouchPoint> points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]);
- qCDebug(lcQpaTouch) << "touchesMovedWithEvent" << points << "from device" << hex << [event deviceID];
- QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), points);
-}
-
-- (void)touchesEndedWithEvent:(NSEvent *)event
-{
- if (!m_platformWindow)
- return;
-
- const NSTimeInterval timestamp = [event timestamp];
- const QList<QWindowSystemInterface::TouchPoint> points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]);
- qCDebug(lcQpaTouch) << "touchesEndedWithEvent" << points << "from device" << hex << [event deviceID];
- QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), points);
-}
-
-- (void)touchesCancelledWithEvent:(NSEvent *)event
-{
- if (!m_platformWindow)
- return;
-
- const NSTimeInterval timestamp = [event timestamp];
- const QList<QWindowSystemInterface::TouchPoint> points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]);
- qCDebug(lcQpaTouch) << "touchesCancelledWithEvent" << points << "from device" << hex << [event deviceID];
- QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), points);
-}
-
-#ifndef QT_NO_GESTURES
-
-- (bool)handleGestureAsBeginEnd:(NSEvent *)event
-{
- if (QOperatingSystemVersion::current() < QOperatingSystemVersion::OSXElCapitan)
- return false;
-
- if ([event phase] == NSEventPhaseBegan) {
- [self beginGestureWithEvent:event];
- return true;
- }
-
- if ([event phase] == NSEventPhaseEnded) {
- [self endGestureWithEvent:event];
- return true;
- }
-
- return false;
-}
-- (void)magnifyWithEvent:(NSEvent *)event
-{
- if (!m_platformWindow)
- return;
-
- if ([self handleGestureAsBeginEnd:event])
- return;
-
- qCDebug(lcQpaGestures) << "magnifyWithEvent" << [event magnification] << "from device" << hex << [event deviceID];
- const NSTimeInterval timestamp = [event timestamp];
- QPointF windowPoint;
- QPointF screenPoint;
- [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
- QWindowSystemInterface::handleGestureEventWithRealValue(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), timestamp, Qt::ZoomNativeGesture,
- [event magnification], windowPoint, screenPoint);
-}
-
-- (void)smartMagnifyWithEvent:(NSEvent *)event
-{
- if (!m_platformWindow)
- return;
-
- static bool zoomIn = true;
- qCDebug(lcQpaGestures) << "smartMagnifyWithEvent" << zoomIn << "from device" << hex << [event deviceID];
- const NSTimeInterval timestamp = [event timestamp];
- QPointF windowPoint;
- QPointF screenPoint;
- [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
- QWindowSystemInterface::handleGestureEventWithRealValue(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), timestamp, Qt::SmartZoomNativeGesture,
- zoomIn ? 1.0f : 0.0f, windowPoint, screenPoint);
- zoomIn = !zoomIn;
-}
-
-- (void)rotateWithEvent:(NSEvent *)event
-{
- if (!m_platformWindow)
- return;
-
- if ([self handleGestureAsBeginEnd:event])
- return;
-
- const NSTimeInterval timestamp = [event timestamp];
- QPointF windowPoint;
- QPointF screenPoint;
- [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
- QWindowSystemInterface::handleGestureEventWithRealValue(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), timestamp, Qt::RotateNativeGesture,
- -[event rotation], windowPoint, screenPoint);
-}
-
-- (void)swipeWithEvent:(NSEvent *)event
-{
- if (!m_platformWindow)
- return;
-
- qCDebug(lcQpaGestures) << "swipeWithEvent" << [event deltaX] << [event deltaY] << "from device" << hex << [event deviceID];
- const NSTimeInterval timestamp = [event timestamp];
- QPointF windowPoint;
- QPointF screenPoint;
- [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
-
- qreal angle = 0.0f;
- if ([event deltaX] == 1)
- angle = 180.0f;
- else if ([event deltaX] == -1)
- angle = 0.0f;
- else if ([event deltaY] == 1)
- angle = 90.0f;
- else if ([event deltaY] == -1)
- angle = 270.0f;
-
- QWindowSystemInterface::handleGestureEventWithRealValue(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), timestamp, Qt::SwipeNativeGesture,
- angle, windowPoint, screenPoint);
-}
-
-- (void)beginGestureWithEvent:(NSEvent *)event
-{
- if (!m_platformWindow)
- return;
-
- const NSTimeInterval timestamp = [event timestamp];
- QPointF windowPoint;
- QPointF screenPoint;
- [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
- qCDebug(lcQpaGestures) << "beginGestureWithEvent @" << windowPoint << "from device" << hex << [event deviceID];
- QWindowSystemInterface::handleGestureEvent(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), timestamp, Qt::BeginNativeGesture,
- windowPoint, screenPoint);
-}
-
-- (void)endGestureWithEvent:(NSEvent *)event
-{
- if (!m_platformWindow)
- return;
-
- qCDebug(lcQpaGestures) << "endGestureWithEvent" << "from device" << hex << [event deviceID];
- const NSTimeInterval timestamp = [event timestamp];
- QPointF windowPoint;
- QPointF screenPoint;
- [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
- QWindowSystemInterface::handleGestureEvent(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), timestamp, Qt::EndNativeGesture,
- windowPoint, screenPoint);
-}
-#endif // QT_NO_GESTURES
-
-#if QT_CONFIG(wheelevent)
-- (void)scrollWheel:(NSEvent *)theEvent
-{
- if (!m_platformWindow)
- return;
-
- if ([self isTransparentForUserInput])
- return [super scrollWheel:theEvent];
-
- QPoint angleDelta;
- Qt::MouseEventSource source = Qt::MouseEventNotSynthesized;
- if ([theEvent hasPreciseScrollingDeltas]) {
- // The mouse device contains pixel scroll wheel support (Mighty Mouse, Trackpad).
- // Since deviceDelta is delivered as pixels rather than degrees, we need to
- // convert from pixels to degrees in a sensible manner.
- // It looks like 1/4 degrees per pixel behaves most native.
- // (NB: Qt expects the unit for delta to be 8 per degree):
- const int pixelsToDegrees = 2; // 8 * 1/4
- angleDelta.setX([theEvent scrollingDeltaX] * pixelsToDegrees);
- angleDelta.setY([theEvent scrollingDeltaY] * pixelsToDegrees);
- source = Qt::MouseEventSynthesizedBySystem;
- } else {
- // Remove acceleration, and use either -120 or 120 as delta:
- angleDelta.setX(qBound(-120, int([theEvent deltaX] * 10000), 120));
- angleDelta.setY(qBound(-120, int([theEvent deltaY] * 10000), 120));
- }
-
- QPoint pixelDelta;
- if ([theEvent hasPreciseScrollingDeltas]) {
- pixelDelta.setX([theEvent scrollingDeltaX]);
- pixelDelta.setY([theEvent scrollingDeltaY]);
- } else {
- // docs: "In the case of !hasPreciseScrollingDeltas, multiply the delta with the line width."
- // scrollingDeltaX seems to return a minimum value of 0.1 in this case, map that to two pixels.
- const CGFloat lineWithEstimate = 20.0;
- pixelDelta.setX([theEvent scrollingDeltaX] * lineWithEstimate);
- pixelDelta.setY([theEvent scrollingDeltaY] * lineWithEstimate);
- }
-
- QPointF qt_windowPoint;
- QPointF qt_screenPoint;
- [self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&qt_windowPoint andScreenPoint:&qt_screenPoint];
- NSTimeInterval timestamp = [theEvent timestamp];
- ulong qt_timestamp = timestamp * 1000;
-
- // Prevent keyboard modifier state from changing during scroll event streams.
- // A two-finger trackpad flick generates a stream of scroll events. We want
- // the keyboard modifier state to be the state at the beginning of the
- // flick in order to avoid changing the interpretation of the events
- // mid-stream. One example of this happening would be when pressing cmd
- // after scrolling in Qt Creator: not taking the phase into account causes
- // the end of the event stream to be interpreted as font size changes.
- NSEventPhase momentumPhase = [theEvent momentumPhase];
- if (momentumPhase == NSEventPhaseNone) {
- currentWheelModifiers = [QNSView convertKeyModifiers:[theEvent modifierFlags]];
- }
-
- NSEventPhase phase = [theEvent phase];
- Qt::ScrollPhase ph = Qt::ScrollUpdate;
-
- // MayBegin is likely to happen. We treat it the same as an actual begin.
- if (phase == NSEventPhaseMayBegin) {
- m_scrolling = true;
- ph = Qt::ScrollBegin;
- } else if (phase == NSEventPhaseBegan) {
- // If MayBegin did not happen, Began is the actual beginning.
- if (!m_scrolling)
- ph = Qt::ScrollBegin;
- m_scrolling = true;
- } else if (phase == NSEventPhaseEnded || phase == NSEventPhaseCancelled ||
- momentumPhase == NSEventPhaseEnded || momentumPhase == NSEventPhaseCancelled) {
- ph = Qt::ScrollEnd;
- m_scrolling = false;
- } else if (phase == NSEventPhaseNone && momentumPhase == NSEventPhaseNone) {
- ph = Qt::NoScrollPhase;
- }
- // "isInverted": natural OS X scrolling, inverted from the Qt/other platform/Jens perspective.
- bool isInverted = [theEvent isDirectionInvertedFromDevice];
-
- qCDebug(lcQpaCocoaMouse) << "scroll wheel @ window pos" << qt_windowPoint << "delta px" << pixelDelta << "angle" << angleDelta << "phase" << ph << (isInverted ? "inverted" : "");
- QWindowSystemInterface::handleWheelEvent(m_platformWindow->window(), qt_timestamp, qt_windowPoint, qt_screenPoint, pixelDelta, angleDelta, currentWheelModifiers, ph, source, isInverted);
-}
-#endif // QT_CONFIG(wheelevent)
-
-- (int) convertKeyCode : (QChar)keyChar
-{
- return qt_mac_cocoaKey2QtKey(keyChar);
-}
-
-+ (Qt::KeyboardModifiers) convertKeyModifiers : (ulong)modifierFlags
-{
- const bool dontSwapCtrlAndMeta = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta);
- Qt::KeyboardModifiers qtMods =Qt::NoModifier;
- if (modifierFlags & NSShiftKeyMask)
- qtMods |= Qt::ShiftModifier;
- if (modifierFlags & NSControlKeyMask)
- qtMods |= dontSwapCtrlAndMeta ? Qt::ControlModifier : Qt::MetaModifier;
- if (modifierFlags & NSAlternateKeyMask)
- qtMods |= Qt::AltModifier;
- if (modifierFlags & NSCommandKeyMask)
- qtMods |= dontSwapCtrlAndMeta ? Qt::MetaModifier : Qt::ControlModifier;
- if (modifierFlags & NSNumericPadKeyMask)
- qtMods |= Qt::KeypadModifier;
- return qtMods;
-}
-
-- (bool)handleKeyEvent:(NSEvent *)nsevent eventType:(int)eventType
-{
- ulong timestamp = [nsevent timestamp] * 1000;
- ulong nativeModifiers = [nsevent modifierFlags];
- Qt::KeyboardModifiers modifiers = [QNSView convertKeyModifiers: nativeModifiers];
- NSString *charactersIgnoringModifiers = [nsevent charactersIgnoringModifiers];
- NSString *characters = [nsevent characters];
- if (m_inputSource != characters) {
- [m_inputSource release];
- m_inputSource = [characters retain];
- }
-
- // There is no way to get the scan code from carbon/cocoa. But we cannot
- // use the value 0, since it indicates that the event originates from somewhere
- // else than the keyboard.
- quint32 nativeScanCode = 1;
- quint32 nativeVirtualKey = [nsevent keyCode];
-
- QChar ch = QChar::ReplacementCharacter;
- int keyCode = Qt::Key_unknown;
-
- // If a dead key occurs as a result of pressing a key combination then
- // characters will have 0 length, but charactersIgnoringModifiers will
- // have a valid character in it. This enables key combinations such as
- // ALT+E to be used as a shortcut with an English keyboard even though
- // pressing ALT+E will give a dead key while doing normal text input.
- if ([characters length] != 0 || [charactersIgnoringModifiers length] != 0) {
- auto ctrlOrMetaModifier = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta) ? Qt::ControlModifier : Qt::MetaModifier;
- if (((modifiers & ctrlOrMetaModifier) || (modifiers & Qt::AltModifier)) && ([charactersIgnoringModifiers length] != 0))
- ch = QChar([charactersIgnoringModifiers characterAtIndex:0]);
- else if ([characters length] != 0)
- ch = QChar([characters characterAtIndex:0]);
- keyCode = [self convertKeyCode:ch];
- }
-
- // we will send a key event unless the input method sets m_sendKeyEvent to false
- m_sendKeyEvent = true;
- QString text;
- // ignore text for the U+F700-U+F8FF range. This is used by Cocoa when
- // delivering function keys (e.g. arrow keys, backspace, F1-F35, etc.)
- if (!(modifiers & (Qt::ControlModifier | Qt::MetaModifier)) && (ch.unicode() < 0xf700 || ch.unicode() > 0xf8ff))
- text = QString::fromNSString(characters);
-
- QWindow *window = [self topLevelWindow];
-
- // Popups implicitly grab key events; forward to the active popup if there is one.
- // This allows popups to e.g. intercept shortcuts and close the popup in response.
- if (QCocoaWindow *popup = QCocoaIntegration::instance()->activePopupWindow()) {
- if (!popup->m_windowFlags.testFlag(Qt::ToolTip))
- window = popup->window();
- }
-
- if (eventType == QEvent::KeyPress) {
-
- if (m_composingText.isEmpty()) {
- m_sendKeyEvent = !QWindowSystemInterface::handleShortcutEvent(window, timestamp, keyCode,
- modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, [nsevent isARepeat], 1);
-
- // Handling a shortcut may result in closing the window
- if (!m_platformWindow)
- return true;
- }
-
- QObject *fo = m_platformWindow->window()->focusObject();
- if (m_sendKeyEvent && fo) {
- QInputMethodQueryEvent queryEvent(Qt::ImEnabled | Qt::ImHints);
- if (QCoreApplication::sendEvent(fo, &queryEvent)) {
- bool imEnabled = queryEvent.value(Qt::ImEnabled).toBool();
- Qt::InputMethodHints hints = static_cast<Qt::InputMethodHints>(queryEvent.value(Qt::ImHints).toUInt());
- if (imEnabled && !(hints & Qt::ImhDigitsOnly || hints & Qt::ImhFormattedNumbersOnly || hints & Qt::ImhHiddenText)) {
- // pass the key event to the input method. note that m_sendKeyEvent may be set to false during this call
- m_currentlyInterpretedKeyEvent = nsevent;
- [self interpretKeyEvents:[NSArray arrayWithObject:nsevent]];
- m_currentlyInterpretedKeyEvent = 0;
- }
- }
- }
- if (m_resendKeyEvent)
- m_sendKeyEvent = true;
- }
-
- bool accepted = true;
- if (m_sendKeyEvent && m_composingText.isEmpty()) {
- QWindowSystemInterface::handleExtendedKeyEvent(window, timestamp, QEvent::Type(eventType), keyCode, modifiers,
- nativeScanCode, nativeVirtualKey, nativeModifiers, text, [nsevent isARepeat], 1, false);
- accepted = QWindowSystemInterface::flushWindowSystemEvents();
- }
- m_sendKeyEvent = false;
- m_resendKeyEvent = false;
- return accepted;
-}
-
-- (void)keyDown:(NSEvent *)nsevent
-{
- if ([self isTransparentForUserInput])
- return [super keyDown:nsevent];
-
- const bool accepted = [self handleKeyEvent:nsevent eventType:int(QEvent::KeyPress)];
-
- // When Qt is used to implement a plugin for a native application we
- // want to propagate unhandled events to other native views. However,
- // Qt does not always set the accepted state correctly (in particular
- // for return key events), so do this for plugin applications only
- // to prevent incorrect forwarding in the general case.
- const bool shouldPropagate = QCoreApplication::testAttribute(Qt::AA_PluginApplication) && !accepted;
-
- // Track keyDown acceptance/forward state for later acceptance of the keyUp.
- if (!shouldPropagate)
- m_acceptedKeyDowns.insert([nsevent keyCode]);
-
- if (shouldPropagate)
- [super keyDown:nsevent];
-}
-
-- (void)keyUp:(NSEvent *)nsevent
-{
- if ([self isTransparentForUserInput])
- return [super keyUp:nsevent];
-
- const bool keyUpAccepted = [self handleKeyEvent:nsevent eventType:int(QEvent::KeyRelease)];
-
- // Propagate the keyUp if neither Qt accepted it nor the corresponding KeyDown was
- // accepted. Qt text controls wil often not use and ignore keyUp events, but we
- // want to avoid propagating unmatched keyUps.
- const bool keyDownAccepted = m_acceptedKeyDowns.remove([nsevent keyCode]);
- if (!keyUpAccepted && !keyDownAccepted)
- [super keyUp:nsevent];
-}
-
-- (void)cancelOperation:(id)sender
-{
- Q_UNUSED(sender);
-
- NSEvent *currentEvent = [NSApp currentEvent];
- if (!currentEvent || currentEvent.type != NSKeyDown)
- return;
-
- // Handling the key event may recurse back here through interpretKeyEvents
- // (when IM is enabled), so we need to guard against that.
- if (currentEvent == m_currentlyInterpretedKeyEvent)
- return;
-
- // Send Command+Key_Period and Escape as normal keypresses so that
- // the key sequence is delivered through Qt. That way clients can
- // intercept the shortcut and override its effect.
- [self handleKeyEvent:currentEvent eventType:int(QEvent::KeyPress)];
-}
-
-- (void)flagsChanged:(NSEvent *)nsevent
-{
- ulong timestamp = [nsevent timestamp] * 1000;
- ulong modifiers = [nsevent modifierFlags];
- Qt::KeyboardModifiers qmodifiers = [QNSView convertKeyModifiers:modifiers];
-
- // calculate the delta and remember the current modifiers for next time
- static ulong m_lastKnownModifiers;
- ulong lastKnownModifiers = m_lastKnownModifiers;
- ulong delta = lastKnownModifiers ^ modifiers;
- m_lastKnownModifiers = modifiers;
-
- struct qt_mac_enum_mapper
- {
- ulong mac_mask;
- Qt::Key qt_code;
- };
- static qt_mac_enum_mapper modifier_key_symbols[] = {
- { NSShiftKeyMask, Qt::Key_Shift },
- { NSControlKeyMask, Qt::Key_Meta },
- { NSCommandKeyMask, Qt::Key_Control },
- { NSAlternateKeyMask, Qt::Key_Alt },
- { NSAlphaShiftKeyMask, Qt::Key_CapsLock },
- { 0ul, Qt::Key_unknown } };
- for (int i = 0; modifier_key_symbols[i].mac_mask != 0u; ++i) {
- uint mac_mask = modifier_key_symbols[i].mac_mask;
- if ((delta & mac_mask) == 0u)
- continue;
-
- Qt::Key qtCode = modifier_key_symbols[i].qt_code;
- if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) {
- if (qtCode == Qt::Key_Meta)
- qtCode = Qt::Key_Control;
- else if (qtCode == Qt::Key_Control)
- qtCode = Qt::Key_Meta;
- }
- QWindowSystemInterface::handleKeyEvent(m_platformWindow->window(),
- timestamp,
- (lastKnownModifiers & mac_mask) ? QEvent::KeyRelease : QEvent::KeyPress,
- qtCode,
- qmodifiers ^ [QNSView convertKeyModifiers:mac_mask]);
- }
-}
-
-- (void) insertNewline:(id)sender
-{
- Q_UNUSED(sender);
- m_resendKeyEvent = true;
-}
-
-- (void) doCommandBySelector:(SEL)aSelector
-{
- [self tryToPerform:aSelector with:self];
-}
-
-- (void) insertText:(id)aString replacementRange:(NSRange)replacementRange
-{
- Q_UNUSED(replacementRange)
-
- if (m_sendKeyEvent && m_composingText.isEmpty() && [aString isEqualToString:m_inputSource]) {
- // don't send input method events for simple text input (let handleKeyEvent send key events instead)
- return;
- }
-
- QString commitString;
- if ([aString length]) {
- if ([aString isKindOfClass:[NSAttributedString class]]) {
- commitString = QString::fromCFString(reinterpret_cast<CFStringRef>([aString string]));
- } else {
- commitString = QString::fromCFString(reinterpret_cast<CFStringRef>(aString));
- };
- }
- if (QObject *fo = m_platformWindow->window()->focusObject()) {
- QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
- if (QCoreApplication::sendEvent(fo, &queryEvent)) {
- if (queryEvent.value(Qt::ImEnabled).toBool()) {
- QInputMethodEvent e;
- e.setCommitString(commitString);
- QCoreApplication::sendEvent(fo, &e);
- // prevent handleKeyEvent from sending a key event
- m_sendKeyEvent = false;
- }
- }
- }
-
- m_composingText.clear();
- m_composingFocusObject = nullptr;
-}
-
-- (void) setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange
-{
- Q_UNUSED(replacementRange)
- QString preeditString;
-
- QList<QInputMethodEvent::Attribute> attrs;
- attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, selectedRange.location + selectedRange.length, 1, QVariant());
-
- if ([aString isKindOfClass:[NSAttributedString class]]) {
- // Preedit string has attribution
- preeditString = QString::fromCFString(reinterpret_cast<CFStringRef>([aString string]));
- int composingLength = preeditString.length();
- int index = 0;
- // Create attributes for individual sections of preedit text
- while (index < composingLength) {
- NSRange effectiveRange;
- NSRange range = NSMakeRange(index, composingLength-index);
- NSDictionary *attributes = [aString attributesAtIndex:index
- longestEffectiveRange:&effectiveRange
- inRange:range];
- NSNumber *underlineStyle = [attributes objectForKey:NSUnderlineStyleAttributeName];
- if (underlineStyle) {
- QColor clr (Qt::black);
- NSColor *color = [attributes objectForKey:NSUnderlineColorAttributeName];
- if (color) {
- clr = qt_mac_toQColor(color);
- }
- QTextCharFormat format;
- format.setFontUnderline(true);
- format.setUnderlineColor(clr);
- attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,
- effectiveRange.location,
- effectiveRange.length,
- format);
- }
- index = effectiveRange.location + effectiveRange.length;
- }
- } else {
- // No attributes specified, take only the preedit text.
- preeditString = QString::fromCFString(reinterpret_cast<CFStringRef>(aString));
- }
-
- if (attrs.isEmpty()) {
- QTextCharFormat format;
- format.setFontUnderline(true);
- attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,
- 0, preeditString.length(), format);
- }
-
- m_composingText = preeditString;
-
- if (QObject *fo = m_platformWindow->window()->focusObject()) {
- m_composingFocusObject = fo;
- QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
- if (QCoreApplication::sendEvent(fo, &queryEvent)) {
- if (queryEvent.value(Qt::ImEnabled).toBool()) {
- QInputMethodEvent e(preeditString, attrs);
- QCoreApplication::sendEvent(fo, &e);
- // prevent handleKeyEvent from sending a key event
- m_sendKeyEvent = false;
- }
- }
- }
-}
-
-- (void)cancelComposingText
-{
- if (m_composingText.isEmpty())
- return;
-
- if (m_composingFocusObject) {
- QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
- if (QCoreApplication::sendEvent(m_composingFocusObject, &queryEvent)) {
- if (queryEvent.value(Qt::ImEnabled).toBool()) {
- QInputMethodEvent e;
- QCoreApplication::sendEvent(m_composingFocusObject, &e);
- }
- }
- }
-
- m_composingText.clear();
- m_composingFocusObject = nullptr;
-}
-
-- (void) unmarkText
-{
- if (!m_composingText.isEmpty()) {
- if (QObject *fo = m_platformWindow->window()->focusObject()) {
- QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
- if (QCoreApplication::sendEvent(fo, &queryEvent)) {
- if (queryEvent.value(Qt::ImEnabled).toBool()) {
- QInputMethodEvent e;
- e.setCommitString(m_composingText);
- QCoreApplication::sendEvent(fo, &e);
- }
- }
- }
- }
- m_composingText.clear();
- m_composingFocusObject = nullptr;
-}
-
-- (BOOL) hasMarkedText
-{
- return (m_composingText.isEmpty() ? NO: YES);
-}
-
-- (NSAttributedString *) attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
-{
- Q_UNUSED(actualRange)
- QObject *fo = m_platformWindow->window()->focusObject();
- if (!fo)
- return nil;
- QInputMethodQueryEvent queryEvent(Qt::ImEnabled | Qt::ImCurrentSelection);
- if (!QCoreApplication::sendEvent(fo, &queryEvent))
- return nil;
- if (!queryEvent.value(Qt::ImEnabled).toBool())
- return nil;
-
- QString selectedText = queryEvent.value(Qt::ImCurrentSelection).toString();
- if (selectedText.isEmpty())
- return nil;
-
- QCFString string(selectedText.mid(aRange.location, aRange.length));
- const NSString *tmpString = reinterpret_cast<const NSString *>((CFStringRef)string);
- return [[[NSAttributedString alloc] initWithString:const_cast<NSString *>(tmpString)] autorelease];
-}
-
-- (NSRange) markedRange
-{
- NSRange range;
- if (!m_composingText.isEmpty()) {
- range.location = 0;
- range.length = m_composingText.length();
- } else {
- range.location = NSNotFound;
- range.length = 0;
- }
- return range;
-}
-
-- (NSRange) selectedRange
-{
- NSRange selectedRange = {0, 0};
-
- QObject *fo = m_platformWindow->window()->focusObject();
- if (!fo)
- return selectedRange;
- QInputMethodQueryEvent queryEvent(Qt::ImEnabled | Qt::ImCurrentSelection);
- if (!QCoreApplication::sendEvent(fo, &queryEvent))
- return selectedRange;
- if (!queryEvent.value(Qt::ImEnabled).toBool())
- return selectedRange;
-
- QString selectedText = queryEvent.value(Qt::ImCurrentSelection).toString();
-
- if (!selectedText.isEmpty()) {
- selectedRange.location = 0;
- selectedRange.length = selectedText.length();
- }
- return selectedRange;
-}
-
-- (NSRect) firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
-{
- Q_UNUSED(aRange)
- Q_UNUSED(actualRange)
- QObject *fo = m_platformWindow->window()->focusObject();
- if (!fo)
- return NSZeroRect;
-
- QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
- if (!QCoreApplication::sendEvent(fo, &queryEvent))
- return NSZeroRect;
- if (!queryEvent.value(Qt::ImEnabled).toBool())
- return NSZeroRect;
-
- if (!m_platformWindow->window())
- return NSZeroRect;
-
- // The returned rect is always based on the internal cursor.
- QRect mr = qApp->inputMethod()->cursorRectangle().toRect();
- mr.moveBottomLeft(m_platformWindow->window()->mapToGlobal(mr.bottomLeft()));
- return QCocoaScreen::mapToNative(mr);
-}
-
-- (NSUInteger)characterIndexForPoint:(NSPoint)aPoint
-{
- // We don't support cursor movements using mouse while composing.
- Q_UNUSED(aPoint);
- return NSNotFound;
-}
-
-- (NSArray*)validAttributesForMarkedText
-{
- if (!m_platformWindow)
- return nil;
-
- if (m_platformWindow->window() != QGuiApplication::focusWindow())
- return nil;
-
- QObject *fo = m_platformWindow->window()->focusObject();
- if (!fo)
- return nil;
-
- QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
- if (!QCoreApplication::sendEvent(fo, &queryEvent))
- return nil;
- if (!queryEvent.value(Qt::ImEnabled).toBool())
- return nil;
-
- // Support only underline color/style.
- return [NSArray arrayWithObjects:NSUnderlineColorAttributeName,
- NSUnderlineStyleAttributeName, nil];
-}
-
--(void)registerDragTypes
-{
- QMacAutoReleasePool pool;
- QStringList customTypes = qt_mac_enabledDraggedTypes();
- if (currentCustomDragTypes == 0 || *currentCustomDragTypes != customTypes) {
- if (currentCustomDragTypes == 0)
- currentCustomDragTypes = new QStringList();
- *currentCustomDragTypes = customTypes;
- const NSString* mimeTypeGeneric = @"com.trolltech.qt.MimeTypeName";
- NSMutableArray *supportedTypes = [NSMutableArray arrayWithObjects:NSColorPboardType,
- NSFilenamesPboardType, NSStringPboardType,
- NSFilenamesPboardType, NSPostScriptPboardType, NSTIFFPboardType,
- NSRTFPboardType, NSTabularTextPboardType, NSFontPboardType,
- NSRulerPboardType, NSFileContentsPboardType, NSColorPboardType,
- NSRTFDPboardType, NSHTMLPboardType,
- NSURLPboardType, NSPDFPboardType, NSVCardPboardType,
- NSFilesPromisePboardType, NSInkTextPboardType,
- NSMultipleTextSelectionPboardType, mimeTypeGeneric, nil];
- // Add custom types supported by the application.
- for (int i = 0; i < customTypes.size(); i++) {
- [supportedTypes addObject:customTypes[i].toNSString()];
- }
- [self registerForDraggedTypes:supportedTypes];
- }
-}
-
-static QWindow *findEventTargetWindow(QWindow *candidate)
-{
- while (candidate) {
- if (!(candidate->flags() & Qt::WindowTransparentForInput))
- return candidate;
- candidate = candidate->parent();
- }
- return candidate;
-}
-
-static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint point)
-{
- return target->mapFromGlobal(source->mapToGlobal(point));
-}
-
-- (NSDragOperation)draggingSession:(NSDraggingSession *)session
- sourceOperationMaskForDraggingContext:(NSDraggingContext)context
-{
- Q_UNUSED(session);
- Q_UNUSED(context);
- QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag();
- return qt_mac_mapDropActions(nativeDrag->currentDrag()->supportedActions());
-}
-
-- (BOOL)ignoreModifierKeysForDraggingSession:(NSDraggingSession *)session
-{
- Q_UNUSED(session);
- // According to the "Dragging Sources" chapter on Cocoa DnD Programming
- // (https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/DragandDrop/Concepts/dragsource.html),
- // if the control, option, or command key is pressed, the source’s
- // operation mask is filtered to only contain a reduced set of operations.
- //
- // Since Qt already takes care of tracking the keyboard modifiers, we
- // don't need (or want) Cocoa to filter anything. Instead, we'll let
- // the application do the actual filtering.
- return YES;
-}
-
-- (BOOL)wantsPeriodicDraggingUpdates
-{
- // From the documentation:
- //
- // "If the destination returns NO, these messages are sent only when the mouse moves
- // or a modifier flag changes. Otherwise the destination gets the default behavior,
- // where it receives periodic dragging-updated messages even if nothing changes."
- //
- // We do not want these constant drag update events while mouse is stationary,
- // since we do all animations (autoscroll) with timers.
- return NO;
-}
-
-
-- (BOOL)wantsPeriodicDraggingUpdates:(void *)dummy
-{
- // This method never gets called. It's a workaround for Apple's
- // bug: they first respondsToSelector : @selector(wantsPeriodicDraggingUpdates:)
- // (note ':') and then call -wantsPeriodicDraggingUpdate (without colon).
- // So, let's make them happy.
- Q_UNUSED(dummy);
-
- return NO;
-}
-
-- (void)updateCursorFromDragResponse:(QPlatformDragQtResponse)response drag:(QCocoaDrag *)drag
-{
- const QPixmap pixmapCursor = drag->currentDrag()->dragCursor(response.acceptedAction());
- NSCursor *nativeCursor = nil;
-
- if (pixmapCursor.isNull()) {
- switch (response.acceptedAction()) {
- case Qt::CopyAction:
- nativeCursor = [NSCursor dragCopyCursor];
- break;
- case Qt::LinkAction:
- nativeCursor = [NSCursor dragLinkCursor];
- break;
- case Qt::IgnoreAction:
- // Uncomment the next lines if forbiden cursor wanted on non droppable targets.
- /*nativeCursor = [NSCursor operationNotAllowedCursor];
- break;*/
- case Qt::MoveAction:
- default:
- nativeCursor = [NSCursor arrowCursor];
- break;
- }
- }
- else {
- NSImage *nsimage = qt_mac_create_nsimage(pixmapCursor);
- nsimage.size = NSSizeFromCGSize((pixmapCursor.size() / pixmapCursor.devicePixelRatioF()).toCGSize());
- nativeCursor = [[NSCursor alloc] initWithImage:nsimage hotSpot:NSZeroPoint];
- [nsimage release];
- }
-
- // change the cursor
- [nativeCursor set];
-
- // Make sure the cursor is updated correctly if the mouse does not move and window is under cursor
- // by creating a fake move event, unless on 10.14 and later where doing so will trigger a security
- // warning dialog. FIXME: Find a way to update the cursor without fake mouse events.
- if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave)
- return;
-
- if (m_updatingDrag)
- return;
-
- const QPoint mousePos(QCursor::pos());
- CGEventRef moveEvent(CGEventCreateMouseEvent(
- NULL, kCGEventMouseMoved,
- CGPointMake(mousePos.x(), mousePos.y()),
- kCGMouseButtonLeft // ignored
- ));
- CGEventPost(kCGHIDEventTap, moveEvent);
- CFRelease(moveEvent);
-}
-
-- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
-{
- return [self handleDrag : sender];
-}
-
-- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
-{
- m_updatingDrag = true;
- const NSDragOperation ret([self handleDrag : sender]);
- m_updatingDrag = false;
-
- return ret;
-}
-
-// Sends drag update to Qt, return the action
-- (NSDragOperation)handleDrag:(id <NSDraggingInfo>)sender
-{
- if (!m_platformWindow)
- return NSDragOperationNone;
-
- NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil];
- QPoint qt_windowPoint(windowPoint.x, windowPoint.y);
- Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations([sender draggingSourceOperationMask]);
-
- QWindow *target = findEventTargetWindow(m_platformWindow->window());
- if (!target)
- return NSDragOperationNone;
-
- // update these so selecting move/copy/link works
- QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers: [[NSApp currentEvent] modifierFlags]];
-
- QPlatformDragQtResponse response(false, Qt::IgnoreAction, QRect());
- QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag();
- if (nativeDrag->currentDrag()) {
- // The drag was started from within the application
- response = QWindowSystemInterface::handleDrag(target, nativeDrag->dragMimeData(), mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint), qtAllowed);
- [self updateCursorFromDragResponse:response drag:nativeDrag];
- } else {
- QCocoaDropData mimeData([sender draggingPasteboard]);
- response = QWindowSystemInterface::handleDrag(target, &mimeData, mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint), qtAllowed);
- }
-
- return qt_mac_mapDropAction(response.acceptedAction());
-}
-
-- (void)draggingExited:(id <NSDraggingInfo>)sender
-{
- if (!m_platformWindow)
- return;
-
- QWindow *target = findEventTargetWindow(m_platformWindow->window());
- if (!target)
- return;
-
- NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil];
- QPoint qt_windowPoint(windowPoint.x, windowPoint.y);
-
- // Send 0 mime data to indicate drag exit
- QWindowSystemInterface::handleDrag(target, 0, mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint), Qt::IgnoreAction);
-}
-
-// called on drop, send the drop to Qt and return if it was accepted.
-- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
-{
- if (!m_platformWindow)
- return false;
-
- QWindow *target = findEventTargetWindow(m_platformWindow->window());
- if (!target)
- return false;
-
- NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil];
- QPoint qt_windowPoint(windowPoint.x, windowPoint.y);
- Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations([sender draggingSourceOperationMask]);
-
- QPlatformDropQtResponse response(false, Qt::IgnoreAction);
- QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag();
- if (nativeDrag->currentDrag()) {
- // The drag was started from within the application
- response = QWindowSystemInterface::handleDrop(target, nativeDrag->dragMimeData(), mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint), qtAllowed);
- } else {
- QCocoaDropData mimeData([sender draggingPasteboard]);
- response = QWindowSystemInterface::handleDrop(target, &mimeData, mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint), qtAllowed);
- }
- if (response.isAccepted()) {
- QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag();
- nativeDrag->setAcceptedAction(response.acceptedAction());
- }
- return response.isAccepted();
-}
-
-- (void)draggingSession:(NSDraggingSession *)session
- endedAtPoint:(NSPoint)screenPoint
- operation:(NSDragOperation)operation
-{
- Q_UNUSED(session);
- Q_UNUSED(operation);
-
- if (!m_platformWindow)
- return;
-
- QWindow *target = findEventTargetWindow(m_platformWindow->window());
- if (!target)
- return;
-
- // keep our state, and QGuiApplication state (buttons member) in-sync,
- // or future mouse events will be processed incorrectly
- NSUInteger pmb = [NSEvent pressedMouseButtons];
- for (int buttonNumber = 0; buttonNumber < 32; buttonNumber++) { // see cocoaButton2QtButton() for the 32 value
- if (!(pmb & (1 << buttonNumber)))
- m_buttons &= ~cocoaButton2QtButton(buttonNumber);
- }
-
- NSPoint windowPoint = [self.window convertRectFromScreen:NSMakeRect(screenPoint.x, screenPoint.y, 1, 1)].origin;
- NSPoint nsViewPoint = [self convertPoint: windowPoint fromView: nil]; // NSView/QWindow coordinates
- QPoint qtWindowPoint(nsViewPoint.x, nsViewPoint.y);
- QPoint qtScreenPoint = QCocoaScreen::mapFromNative(screenPoint).toPoint();
-
- QWindowSystemInterface::handleMouseEvent(target, mapWindowCoordinates(m_platformWindow->window(), target, qtWindowPoint), qtScreenPoint, m_buttons);
-}
-
-@end
+// -----------------------------------------------------
@implementation QT_MANGLE_NAMESPACE(QNSView) (QtExtras)
@@ -2089,9 +347,4 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin
return m_platformWindow.data();;
}
-- (BOOL)isMenuView
-{
- return m_isMenuView;
-}
-
@end
diff --git a/src/plugins/platforms/cocoa/qnsview_accessibility.mm b/src/plugins/platforms/cocoa/qnsview_accessibility.mm
new file mode 100644
index 0000000000..32ec0b74d4
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qnsview_accessibility.mm
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// This file is included from qnsview.mm, and only used to organize the code
+
+#include "qcocoaaccessibility.h"
+#include "qcocoaaccessibilityelement.h"
+#include "qcocoaintegration.h"
+
+#include <QtGui/qaccessible.h>
+
+#import <AppKit/NSAccessibility.h>
+
+@implementation QT_MANGLE_NAMESPACE(QNSView) (Accessibility)
+
+- (id)childAccessibleElement
+{
+ QCocoaWindow *platformWindow = self.platformWindow;
+ if (!platformWindow || !platformWindow->window()->accessibleRoot())
+ return nil;
+
+ QAccessible::Id childId = QAccessible::uniqueId(platformWindow->window()->accessibleRoot());
+ return [QMacAccessibilityElement elementWithId:childId];
+}
+
+// The QNSView is a container that the user does not interact directly with:
+// Remove it from the user-visible accessibility tree.
+- (BOOL)accessibilityIsIgnored
+{
+ return YES;
+}
+
+- (id)accessibilityAttributeValue:(NSString *)attribute
+{
+ // activate accessibility updates
+ QCocoaIntegration::instance()->accessibility()->setActive(true);
+
+ if ([attribute isEqualToString:NSAccessibilityChildrenAttribute])
+ return NSAccessibilityUnignoredChildrenForOnlyChild([self childAccessibleElement]);
+ else
+ return [super accessibilityAttributeValue:attribute];
+}
+
+- (id)accessibilityHitTest:(NSPoint)point
+{
+ return [[self childAccessibleElement] accessibilityHitTest:point];
+}
+
+- (id)accessibilityFocusedUIElement
+{
+ return [[self childAccessibleElement] accessibilityFocusedUIElement];
+}
+
+@end
diff --git a/src/plugins/platforms/cocoa/qnsview_complextext.mm b/src/plugins/platforms/cocoa/qnsview_complextext.mm
new file mode 100644
index 0000000000..d357082d33
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qnsview_complextext.mm
@@ -0,0 +1,315 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// This file is included from qnsview.mm, and only used to organize the code
+
+@implementation QT_MANGLE_NAMESPACE(QNSView) (ComplexTextAPI)
+
+- (void)cancelComposingText
+{
+ if (m_composingText.isEmpty())
+ return;
+
+ if (m_composingFocusObject) {
+ QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
+ if (QCoreApplication::sendEvent(m_composingFocusObject, &queryEvent)) {
+ if (queryEvent.value(Qt::ImEnabled).toBool()) {
+ QInputMethodEvent e;
+ QCoreApplication::sendEvent(m_composingFocusObject, &e);
+ }
+ }
+ }
+
+ m_composingText.clear();
+ m_composingFocusObject = nullptr;
+}
+
+- (void)unmarkText
+{
+ if (!m_composingText.isEmpty()) {
+ if (QObject *fo = m_platformWindow->window()->focusObject()) {
+ QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
+ if (QCoreApplication::sendEvent(fo, &queryEvent)) {
+ if (queryEvent.value(Qt::ImEnabled).toBool()) {
+ QInputMethodEvent e;
+ e.setCommitString(m_composingText);
+ QCoreApplication::sendEvent(fo, &e);
+ }
+ }
+ }
+ }
+ m_composingText.clear();
+ m_composingFocusObject = nullptr;
+}
+
+@end
+
+@implementation QT_MANGLE_NAMESPACE(QNSView) (ComplexText)
+
+- (void)insertNewline:(id)sender
+{
+ Q_UNUSED(sender);
+ m_resendKeyEvent = true;
+}
+
+- (void)doCommandBySelector:(SEL)aSelector
+{
+ [self tryToPerform:aSelector with:self];
+}
+
+- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange
+{
+ Q_UNUSED(replacementRange)
+
+ if (m_sendKeyEvent && m_composingText.isEmpty() && [aString isEqualToString:m_inputSource]) {
+ // don't send input method events for simple text input (let handleKeyEvent send key events instead)
+ return;
+ }
+
+ QString commitString;
+ if ([aString length]) {
+ if ([aString isKindOfClass:[NSAttributedString class]]) {
+ commitString = QString::fromCFString(reinterpret_cast<CFStringRef>([aString string]));
+ } else {
+ commitString = QString::fromCFString(reinterpret_cast<CFStringRef>(aString));
+ };
+ }
+ if (QObject *fo = m_platformWindow->window()->focusObject()) {
+ QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
+ if (QCoreApplication::sendEvent(fo, &queryEvent)) {
+ if (queryEvent.value(Qt::ImEnabled).toBool()) {
+ QInputMethodEvent e;
+ e.setCommitString(commitString);
+ QCoreApplication::sendEvent(fo, &e);
+ // prevent handleKeyEvent from sending a key event
+ m_sendKeyEvent = false;
+ }
+ }
+ }
+
+ m_composingText.clear();
+ m_composingFocusObject = nullptr;
+}
+
+- (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange
+{
+ Q_UNUSED(replacementRange)
+ QString preeditString;
+
+ QList<QInputMethodEvent::Attribute> attrs;
+ attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, selectedRange.location + selectedRange.length, 1, QVariant());
+
+ if ([aString isKindOfClass:[NSAttributedString class]]) {
+ // Preedit string has attribution
+ preeditString = QString::fromCFString(reinterpret_cast<CFStringRef>([aString string]));
+ int composingLength = preeditString.length();
+ int index = 0;
+ // Create attributes for individual sections of preedit text
+ while (index < composingLength) {
+ NSRange effectiveRange;
+ NSRange range = NSMakeRange(index, composingLength-index);
+ NSDictionary *attributes = [aString attributesAtIndex:index
+ longestEffectiveRange:&effectiveRange
+ inRange:range];
+ NSNumber *underlineStyle = [attributes objectForKey:NSUnderlineStyleAttributeName];
+ if (underlineStyle) {
+ QColor clr (Qt::black);
+ NSColor *color = [attributes objectForKey:NSUnderlineColorAttributeName];
+ if (color) {
+ clr = qt_mac_toQColor(color);
+ }
+ QTextCharFormat format;
+ format.setFontUnderline(true);
+ format.setUnderlineColor(clr);
+ attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,
+ effectiveRange.location,
+ effectiveRange.length,
+ format);
+ }
+ index = effectiveRange.location + effectiveRange.length;
+ }
+ } else {
+ // No attributes specified, take only the preedit text.
+ preeditString = QString::fromCFString(reinterpret_cast<CFStringRef>(aString));
+ }
+
+ if (attrs.isEmpty()) {
+ QTextCharFormat format;
+ format.setFontUnderline(true);
+ attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,
+ 0, preeditString.length(), format);
+ }
+
+ m_composingText = preeditString;
+
+ if (QObject *fo = m_platformWindow->window()->focusObject()) {
+ m_composingFocusObject = fo;
+ QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
+ if (QCoreApplication::sendEvent(fo, &queryEvent)) {
+ if (queryEvent.value(Qt::ImEnabled).toBool()) {
+ QInputMethodEvent e(preeditString, attrs);
+ QCoreApplication::sendEvent(fo, &e);
+ // prevent handleKeyEvent from sending a key event
+ m_sendKeyEvent = false;
+ }
+ }
+ }
+}
+
+- (BOOL)hasMarkedText
+{
+ return (m_composingText.isEmpty() ? NO: YES);
+}
+
+- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
+{
+ Q_UNUSED(actualRange)
+ QObject *fo = m_platformWindow->window()->focusObject();
+ if (!fo)
+ return nil;
+ QInputMethodQueryEvent queryEvent(Qt::ImEnabled | Qt::ImCurrentSelection);
+ if (!QCoreApplication::sendEvent(fo, &queryEvent))
+ return nil;
+ if (!queryEvent.value(Qt::ImEnabled).toBool())
+ return nil;
+
+ QString selectedText = queryEvent.value(Qt::ImCurrentSelection).toString();
+ if (selectedText.isEmpty())
+ return nil;
+
+ QCFString string(selectedText.mid(aRange.location, aRange.length));
+ const NSString *tmpString = reinterpret_cast<const NSString *>((CFStringRef)string);
+ return [[[NSAttributedString alloc] initWithString:const_cast<NSString *>(tmpString)] autorelease];
+}
+
+- (NSRange)markedRange
+{
+ NSRange range;
+ if (!m_composingText.isEmpty()) {
+ range.location = 0;
+ range.length = m_composingText.length();
+ } else {
+ range.location = NSNotFound;
+ range.length = 0;
+ }
+ return range;
+}
+
+- (NSRange)selectedRange
+{
+ NSRange selectedRange = {0, 0};
+
+ QObject *fo = m_platformWindow->window()->focusObject();
+ if (!fo)
+ return selectedRange;
+ QInputMethodQueryEvent queryEvent(Qt::ImEnabled | Qt::ImCurrentSelection);
+ if (!QCoreApplication::sendEvent(fo, &queryEvent))
+ return selectedRange;
+ if (!queryEvent.value(Qt::ImEnabled).toBool())
+ return selectedRange;
+
+ QString selectedText = queryEvent.value(Qt::ImCurrentSelection).toString();
+
+ if (!selectedText.isEmpty()) {
+ selectedRange.location = 0;
+ selectedRange.length = selectedText.length();
+ }
+ return selectedRange;
+}
+
+- (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
+{
+ Q_UNUSED(aRange)
+ Q_UNUSED(actualRange)
+
+ QObject *fo = m_platformWindow->window()->focusObject();
+ if (!fo)
+ return NSZeroRect;
+
+ QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
+ if (!QCoreApplication::sendEvent(fo, &queryEvent))
+ return NSZeroRect;
+ if (!queryEvent.value(Qt::ImEnabled).toBool())
+ return NSZeroRect;
+
+ // The returned rect is always based on the internal cursor.
+ QRect mr = qApp->inputMethod()->cursorRectangle().toRect();
+ mr.moveBottomLeft(m_platformWindow->window()->mapToGlobal(mr.bottomLeft()));
+ return QCocoaScreen::mapToNative(mr);
+}
+
+- (NSUInteger)characterIndexForPoint:(NSPoint)aPoint
+{
+ // We don't support cursor movements using mouse while composing.
+ Q_UNUSED(aPoint);
+ return NSNotFound;
+}
+
+- (NSArray<NSString *> *)validAttributesForMarkedText
+{
+ if (!m_platformWindow)
+ return nil;
+
+ if (m_platformWindow->window() != QGuiApplication::focusWindow())
+ return nil;
+
+ QObject *fo = m_platformWindow->window()->focusObject();
+ if (!fo)
+ return nil;
+
+ QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
+ if (!QCoreApplication::sendEvent(fo, &queryEvent))
+ return nil;
+ if (!queryEvent.value(Qt::ImEnabled).toBool())
+ return nil;
+
+ // Support only underline color/style.
+ return @[NSUnderlineColorAttributeName, NSUnderlineStyleAttributeName];
+}
+
+- (void)textInputContextKeyboardSelectionDidChangeNotification:(NSNotification *)textInputContextKeyboardSelectionDidChangeNotification
+{
+ Q_UNUSED(textInputContextKeyboardSelectionDidChangeNotification)
+ if (([NSApp keyWindow] == self.window) && self.window.firstResponder == self) {
+ QCocoaInputContext *ic = qobject_cast<QCocoaInputContext *>(QCocoaIntegration::instance()->inputContext());
+ ic->updateLocale();
+ }
+}
+
+@end
diff --git a/src/plugins/platforms/cocoa/qnsview_dragging.mm b/src/plugins/platforms/cocoa/qnsview_dragging.mm
new file mode 100644
index 0000000000..1c38c5326c
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qnsview_dragging.mm
@@ -0,0 +1,300 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// This file is included from qnsview.mm, and only used to organize the code
+
+@implementation QT_MANGLE_NAMESPACE(QNSView) (Dragging)
+
+-(void)registerDragTypes
+{
+ QMacAutoReleasePool pool;
+
+ NSString * const mimeTypeGeneric = @"com.trolltech.qt.MimeTypeName";
+ NSMutableArray<NSString *> *supportedTypes = [NSMutableArray<NSString *> arrayWithArray:@[
+ NSColorPboardType,
+ NSFilenamesPboardType, NSStringPboardType,
+ NSFilenamesPboardType, NSPostScriptPboardType, NSTIFFPboardType,
+ NSRTFPboardType, NSTabularTextPboardType, NSFontPboardType,
+ NSRulerPboardType, NSFileContentsPboardType, NSColorPboardType,
+ NSRTFDPboardType, NSHTMLPboardType,
+ NSURLPboardType, NSPDFPboardType, NSVCardPboardType,
+ NSFilesPromisePboardType, NSInkTextPboardType,
+ NSMultipleTextSelectionPboardType, mimeTypeGeneric]];
+
+ // Add custom types supported by the application.
+ for (const QString &customType : qt_mac_enabledDraggedTypes())
+ [supportedTypes addObject:customType.toNSString()];
+
+ [self registerForDraggedTypes:supportedTypes];
+}
+
+static QWindow *findEventTargetWindow(QWindow *candidate)
+{
+ while (candidate) {
+ if (!(candidate->flags() & Qt::WindowTransparentForInput))
+ return candidate;
+ candidate = candidate->parent();
+ }
+ return candidate;
+}
+
+static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint point)
+{
+ return target->mapFromGlobal(source->mapToGlobal(point));
+}
+
+- (NSDragOperation)draggingSession:(NSDraggingSession *)session
+ sourceOperationMaskForDraggingContext:(NSDraggingContext)context
+{
+ Q_UNUSED(session);
+ Q_UNUSED(context);
+ QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag();
+ return qt_mac_mapDropActions(nativeDrag->currentDrag()->supportedActions());
+}
+
+- (BOOL)ignoreModifierKeysForDraggingSession:(NSDraggingSession *)session
+{
+ Q_UNUSED(session);
+ // According to the "Dragging Sources" chapter on Cocoa DnD Programming
+ // (https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/DragandDrop/Concepts/dragsource.html),
+ // if the control, option, or command key is pressed, the source’s
+ // operation mask is filtered to only contain a reduced set of operations.
+ //
+ // Since Qt already takes care of tracking the keyboard modifiers, we
+ // don't need (or want) Cocoa to filter anything. Instead, we'll let
+ // the application do the actual filtering.
+ return YES;
+}
+
+- (BOOL)wantsPeriodicDraggingUpdates
+{
+ // From the documentation:
+ //
+ // "If the destination returns NO, these messages are sent only when the mouse moves
+ // or a modifier flag changes. Otherwise the destination gets the default behavior,
+ // where it receives periodic dragging-updated messages even if nothing changes."
+ //
+ // We do not want these constant drag update events while mouse is stationary,
+ // since we do all animations (autoscroll) with timers.
+ return NO;
+}
+
+
+- (BOOL)wantsPeriodicDraggingUpdates:(void *)dummy
+{
+ // This method never gets called. It's a workaround for Apple's
+ // bug: they first respondsToSelector : @selector(wantsPeriodicDraggingUpdates:)
+ // (note ':') and then call -wantsPeriodicDraggingUpdate (without colon).
+ // So, let's make them happy.
+ Q_UNUSED(dummy);
+
+ return NO;
+}
+
+- (void)updateCursorFromDragResponse:(QPlatformDragQtResponse)response drag:(QCocoaDrag *)drag
+{
+ const QPixmap pixmapCursor = drag->currentDrag()->dragCursor(response.acceptedAction());
+ NSCursor *nativeCursor = nil;
+
+ if (pixmapCursor.isNull()) {
+ switch (response.acceptedAction()) {
+ case Qt::CopyAction:
+ nativeCursor = [NSCursor dragCopyCursor];
+ break;
+ case Qt::LinkAction:
+ nativeCursor = [NSCursor dragLinkCursor];
+ break;
+ case Qt::IgnoreAction:
+ // Uncomment the next lines if forbiden cursor wanted on non droppable targets.
+ /*nativeCursor = [NSCursor operationNotAllowedCursor];
+ break;*/
+ case Qt::MoveAction:
+ default:
+ nativeCursor = [NSCursor arrowCursor];
+ break;
+ }
+ }
+ else {
+ NSImage *nsimage = qt_mac_create_nsimage(pixmapCursor);
+ nsimage.size = NSSizeFromCGSize((pixmapCursor.size() / pixmapCursor.devicePixelRatioF()).toCGSize());
+ nativeCursor = [[NSCursor alloc] initWithImage:nsimage hotSpot:NSZeroPoint];
+ [nsimage release];
+ }
+
+ // change the cursor
+ [nativeCursor set];
+
+ // Make sure the cursor is updated correctly if the mouse does not move and window is under cursor
+ // by creating a fake move event, unless on 10.14 and later where doing so will trigger a security
+ // warning dialog. FIXME: Find a way to update the cursor without fake mouse events.
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave)
+ return;
+
+ if (m_updatingDrag)
+ return;
+
+ const QPoint mousePos(QCursor::pos());
+ CGEventRef moveEvent(CGEventCreateMouseEvent(
+ NULL, kCGEventMouseMoved,
+ CGPointMake(mousePos.x(), mousePos.y()),
+ kCGMouseButtonLeft // ignored
+ ));
+ CGEventPost(kCGHIDEventTap, moveEvent);
+ CFRelease(moveEvent);
+}
+
+- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
+{
+ return [self handleDrag : sender];
+}
+
+- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
+{
+ m_updatingDrag = true;
+ const NSDragOperation ret([self handleDrag : sender]);
+ m_updatingDrag = false;
+
+ return ret;
+}
+
+// Sends drag update to Qt, return the action
+- (NSDragOperation)handleDrag:(id <NSDraggingInfo>)sender
+{
+ if (!m_platformWindow)
+ return NSDragOperationNone;
+
+ NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil];
+ QPoint qt_windowPoint(windowPoint.x, windowPoint.y);
+ Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations([sender draggingSourceOperationMask]);
+
+ QWindow *target = findEventTargetWindow(m_platformWindow->window());
+ if (!target)
+ return NSDragOperationNone;
+
+ const auto modifiers = [QNSView convertKeyModifiers:NSApp.currentEvent.modifierFlags];
+ const auto buttons = currentlyPressedMouseButtons();
+ const auto point = mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint);
+
+ QPlatformDragQtResponse response(false, Qt::IgnoreAction, QRect());
+ QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag();
+ if (nativeDrag->currentDrag()) {
+ // The drag was started from within the application
+ response = QWindowSystemInterface::handleDrag(target, nativeDrag->dragMimeData(),
+ point, qtAllowed, buttons, modifiers);
+ [self updateCursorFromDragResponse:response drag:nativeDrag];
+ } else {
+ QCocoaDropData mimeData([sender draggingPasteboard]);
+ response = QWindowSystemInterface::handleDrag(target, &mimeData,
+ point, qtAllowed, buttons, modifiers);
+ }
+
+ return qt_mac_mapDropAction(response.acceptedAction());
+}
+
+- (void)draggingExited:(id <NSDraggingInfo>)sender
+{
+ if (!m_platformWindow)
+ return;
+
+ QWindow *target = findEventTargetWindow(m_platformWindow->window());
+ if (!target)
+ return;
+
+ NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil];
+ QPoint qt_windowPoint(windowPoint.x, windowPoint.y);
+
+ // Send 0 mime data to indicate drag exit
+ QWindowSystemInterface::handleDrag(target, nullptr,
+ mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint),
+ Qt::IgnoreAction, Qt::NoButton, Qt::NoModifier);
+}
+
+// called on drop, send the drop to Qt and return if it was accepted.
+- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
+{
+ if (!m_platformWindow)
+ return false;
+
+ QWindow *target = findEventTargetWindow(m_platformWindow->window());
+ if (!target)
+ return false;
+
+ NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil];
+ QPoint qt_windowPoint(windowPoint.x, windowPoint.y);
+ Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations([sender draggingSourceOperationMask]);
+
+ QPlatformDropQtResponse response(false, Qt::IgnoreAction);
+ QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag();
+ const auto modifiers = [QNSView convertKeyModifiers:NSApp.currentEvent.modifierFlags];
+ const auto buttons = currentlyPressedMouseButtons();
+ const auto point = mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint);
+
+ if (nativeDrag->currentDrag()) {
+ // The drag was started from within the application
+ response = QWindowSystemInterface::handleDrop(target, nativeDrag->dragMimeData(),
+ point, qtAllowed, buttons, modifiers);
+ } else {
+ QCocoaDropData mimeData([sender draggingPasteboard]);
+ response = QWindowSystemInterface::handleDrop(target, &mimeData,
+ point, qtAllowed, buttons, modifiers);
+ }
+ return response.isAccepted();
+}
+
+- (void)draggingSession:(NSDraggingSession *)session
+ endedAtPoint:(NSPoint)screenPoint
+ operation:(NSDragOperation)operation
+{
+ Q_UNUSED(session);
+ Q_UNUSED(screenPoint);
+
+ if (!m_platformWindow)
+ return;
+
+ QWindow *target = findEventTargetWindow(m_platformWindow->window());
+ if (!target)
+ return;
+
+ QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag();
+ nativeDrag->setAcceptedAction(qt_mac_mapNSDragOperation(operation));
+
+ m_buttons = currentlyPressedMouseButtons();
+}
+
+@end
diff --git a/src/plugins/platforms/cocoa/qnsview_drawing.mm b/src/plugins/platforms/cocoa/qnsview_drawing.mm
new file mode 100644
index 0000000000..4f9d17504d
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qnsview_drawing.mm
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// This file is included from qnsview.mm, and only used to organize the code
+
+@implementation QT_MANGLE_NAMESPACE(QNSView) (Drawing)
+
+- (BOOL)isOpaque
+{
+ if (!m_platformWindow)
+ return true;
+ return m_platformWindow->isOpaque();
+}
+
+- (BOOL)isFlipped
+{
+ return YES;
+}
+
+- (void)drawRect:(NSRect)dirtyRect
+{
+ Q_UNUSED(dirtyRect);
+
+ if (!m_platformWindow)
+ return;
+
+ QRegion exposedRegion;
+ const NSRect *dirtyRects;
+ NSInteger numDirtyRects;
+ [self getRectsBeingDrawn:&dirtyRects count:&numDirtyRects];
+ for (int i = 0; i < numDirtyRects; ++i)
+ exposedRegion += QRectF::fromCGRect(dirtyRects[i]).toRect();
+
+ qCDebug(lcQpaDrawing) << "[QNSView drawRect:]" << m_platformWindow->window() << exposedRegion;
+ m_platformWindow->handleExposeEvent(exposedRegion);
+}
+
+- (BOOL)shouldUseMetalLayer
+{
+ // MetalSurface needs a layer, and so does VulkanSurface (via MoltenVK)
+ QSurface::SurfaceType surfaceType = m_platformWindow->window()->surfaceType();
+ return surfaceType == QWindow::MetalSurface || surfaceType == QWindow::VulkanSurface;
+}
+
+- (BOOL)wantsLayerHelper
+{
+ Q_ASSERT(m_platformWindow);
+
+ bool wantsLayer = qt_mac_resolveOption(true, m_platformWindow->window(),
+ "_q_mac_wantsLayer", "QT_MAC_WANTS_LAYER");
+
+ bool layerForSurfaceType = [self shouldUseMetalLayer];
+
+ return wantsLayer || layerForSurfaceType;
+}
+
+- (CALayer *)makeBackingLayer
+{
+ if ([self shouldUseMetalLayer]) {
+ // Check if Metal is supported. If it isn't then it's most likely
+ // too late at this point and the QWindow will be non-functional,
+ // but we can at least print a warning.
+ if (![MTLCreateSystemDefaultDevice() autorelease]) {
+ qWarning() << "QWindow initialization error: Metal is not supported";
+ return [super makeBackingLayer];
+ }
+
+ CAMetalLayer *layer = [CAMetalLayer layer];
+
+ // Set the contentsScale for the layer. This is normally done in
+ // viewDidChangeBackingProperties, however on startup that function
+ // is called before the layer is created here. The layer's drawableSize
+ // is updated from layoutSublayersOfLayer as usual.
+ layer.contentsScale = self.window.backingScaleFactor;
+
+ return layer;
+ }
+
+ return [super makeBackingLayer];
+}
+
+- (NSViewLayerContentsRedrawPolicy)layerContentsRedrawPolicy
+{
+ // We need to set this explicitly since the super implementation
+ // returns LayerContentsRedrawNever for custom layers like CAMetalLayer.
+ return NSViewLayerContentsRedrawDuringViewResize;
+}
+
+- (void)updateMetalLayerDrawableSize:(CAMetalLayer *)layer
+{
+ CGSize drawableSize = layer.bounds.size;
+ drawableSize.width *= layer.contentsScale;
+ drawableSize.height *= layer.contentsScale;
+ layer.drawableSize = drawableSize;
+}
+
+- (void)layoutSublayersOfLayer:(CALayer *)layer
+{
+ if ([layer isKindOfClass:CAMetalLayer.class])
+ [self updateMetalLayerDrawableSize:static_cast<CAMetalLayer* >(layer)];
+}
+
+- (void)displayLayer:(CALayer *)layer
+{
+ Q_ASSERT(layer == self.layer);
+
+ if (!m_platformWindow)
+ return;
+
+ qCDebug(lcQpaDrawing) << "[QNSView displayLayer]" << m_platformWindow->window();
+
+ // FIXME: Find out if there's a way to resolve the dirty rect like in drawRect:
+ m_platformWindow->handleExposeEvent(QRectF::fromCGRect(self.bounds).toRect());
+}
+
+- (void)viewDidChangeBackingProperties
+{
+ CALayer *layer = self.layer;
+ if (!layer)
+ return;
+
+ layer.contentsScale = self.window.backingScaleFactor;
+
+ // Metal layers must be manually updated on e.g. screen change
+ if ([layer isKindOfClass:CAMetalLayer.class]) {
+ [self updateMetalLayerDrawableSize:static_cast<CAMetalLayer* >(layer)];
+ [self setNeedsDisplay:YES];
+ }
+}
+
+@end
diff --git a/src/plugins/platforms/cocoa/qnsview_gestures.mm b/src/plugins/platforms/cocoa/qnsview_gestures.mm
new file mode 100644
index 0000000000..61d551ee0e
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qnsview_gestures.mm
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// This file is included from qnsview.mm, and only used to organize the code
+
+#ifndef QT_NO_GESTURES
+
+Q_LOGGING_CATEGORY(lcQpaGestures, "qt.qpa.input.gestures")
+
+@implementation QT_MANGLE_NAMESPACE(QNSView) (Gestures)
+
+- (bool)handleGestureAsBeginEnd:(NSEvent *)event
+{
+ if (QOperatingSystemVersion::current() < QOperatingSystemVersion::OSXElCapitan)
+ return false;
+
+ if ([event phase] == NSEventPhaseBegan) {
+ [self beginGestureWithEvent:event];
+ return true;
+ }
+
+ if ([event phase] == NSEventPhaseEnded) {
+ [self endGestureWithEvent:event];
+ return true;
+ }
+
+ return false;
+}
+- (void)magnifyWithEvent:(NSEvent *)event
+{
+ if (!m_platformWindow)
+ return;
+
+ if ([self handleGestureAsBeginEnd:event])
+ return;
+
+ qCDebug(lcQpaGestures) << "magnifyWithEvent" << [event magnification] << "from device" << hex << [event deviceID];
+ const NSTimeInterval timestamp = [event timestamp];
+ QPointF windowPoint;
+ QPointF screenPoint;
+ [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
+ QWindowSystemInterface::handleGestureEventWithRealValue(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), timestamp, Qt::ZoomNativeGesture,
+ [event magnification], windowPoint, screenPoint);
+}
+
+- (void)smartMagnifyWithEvent:(NSEvent *)event
+{
+ if (!m_platformWindow)
+ return;
+
+ static bool zoomIn = true;
+ qCDebug(lcQpaGestures) << "smartMagnifyWithEvent" << zoomIn << "from device" << hex << [event deviceID];
+ const NSTimeInterval timestamp = [event timestamp];
+ QPointF windowPoint;
+ QPointF screenPoint;
+ [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
+ QWindowSystemInterface::handleGestureEventWithRealValue(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), timestamp, Qt::SmartZoomNativeGesture,
+ zoomIn ? 1.0f : 0.0f, windowPoint, screenPoint);
+ zoomIn = !zoomIn;
+}
+
+- (void)rotateWithEvent:(NSEvent *)event
+{
+ if (!m_platformWindow)
+ return;
+
+ if ([self handleGestureAsBeginEnd:event])
+ return;
+
+ const NSTimeInterval timestamp = [event timestamp];
+ QPointF windowPoint;
+ QPointF screenPoint;
+ [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
+ QWindowSystemInterface::handleGestureEventWithRealValue(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), timestamp, Qt::RotateNativeGesture,
+ -[event rotation], windowPoint, screenPoint);
+}
+
+- (void)swipeWithEvent:(NSEvent *)event
+{
+ if (!m_platformWindow)
+ return;
+
+ qCDebug(lcQpaGestures) << "swipeWithEvent" << [event deltaX] << [event deltaY] << "from device" << hex << [event deviceID];
+ const NSTimeInterval timestamp = [event timestamp];
+ QPointF windowPoint;
+ QPointF screenPoint;
+ [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
+
+ qreal angle = 0.0f;
+ if ([event deltaX] == 1)
+ angle = 180.0f;
+ else if ([event deltaX] == -1)
+ angle = 0.0f;
+ else if ([event deltaY] == 1)
+ angle = 90.0f;
+ else if ([event deltaY] == -1)
+ angle = 270.0f;
+
+ QWindowSystemInterface::handleGestureEventWithRealValue(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), timestamp, Qt::SwipeNativeGesture,
+ angle, windowPoint, screenPoint);
+}
+
+- (void)beginGestureWithEvent:(NSEvent *)event
+{
+ if (!m_platformWindow)
+ return;
+
+ const NSTimeInterval timestamp = [event timestamp];
+ QPointF windowPoint;
+ QPointF screenPoint;
+ [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
+ qCDebug(lcQpaGestures) << "beginGestureWithEvent @" << windowPoint << "from device" << hex << [event deviceID];
+ QWindowSystemInterface::handleGestureEvent(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), timestamp, Qt::BeginNativeGesture,
+ windowPoint, screenPoint);
+}
+
+- (void)endGestureWithEvent:(NSEvent *)event
+{
+ if (!m_platformWindow)
+ return;
+
+ qCDebug(lcQpaGestures) << "endGestureWithEvent" << "from device" << hex << [event deviceID];
+ const NSTimeInterval timestamp = [event timestamp];
+ QPointF windowPoint;
+ QPointF screenPoint;
+ [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
+ QWindowSystemInterface::handleGestureEvent(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), timestamp, Qt::EndNativeGesture,
+ windowPoint, screenPoint);
+}
+
+@end
+
+#endif // QT_NO_GESTURES
diff --git a/src/plugins/platforms/cocoa/qnsview_keys.mm b/src/plugins/platforms/cocoa/qnsview_keys.mm
new file mode 100644
index 0000000000..ad751279bb
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qnsview_keys.mm
@@ -0,0 +1,262 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// This file is included from qnsview.mm, and only used to organize the code
+
+@implementation QT_MANGLE_NAMESPACE(QNSView) (KeysAPI)
+
++ (Qt::KeyboardModifiers)convertKeyModifiers:(ulong)modifierFlags
+{
+ const bool dontSwapCtrlAndMeta = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta);
+ Qt::KeyboardModifiers qtMods =Qt::NoModifier;
+ if (modifierFlags & NSEventModifierFlagShift)
+ qtMods |= Qt::ShiftModifier;
+ if (modifierFlags & NSEventModifierFlagControl)
+ qtMods |= dontSwapCtrlAndMeta ? Qt::ControlModifier : Qt::MetaModifier;
+ if (modifierFlags & NSEventModifierFlagOption)
+ qtMods |= Qt::AltModifier;
+ if (modifierFlags & NSEventModifierFlagCommand)
+ qtMods |= dontSwapCtrlAndMeta ? Qt::MetaModifier : Qt::ControlModifier;
+ if (modifierFlags & NSEventModifierFlagNumericPad)
+ qtMods |= Qt::KeypadModifier;
+ return qtMods;
+}
+
+@end
+
+@implementation QT_MANGLE_NAMESPACE(QNSView) (Keys)
+
+- (int)convertKeyCode:(QChar)keyChar
+{
+ return qt_mac_cocoaKey2QtKey(keyChar);
+}
+
+- (bool)handleKeyEvent:(NSEvent *)nsevent eventType:(int)eventType
+{
+ ulong timestamp = [nsevent timestamp] * 1000;
+ ulong nativeModifiers = [nsevent modifierFlags];
+ Qt::KeyboardModifiers modifiers = [QNSView convertKeyModifiers: nativeModifiers];
+ NSString *charactersIgnoringModifiers = [nsevent charactersIgnoringModifiers];
+ NSString *characters = [nsevent characters];
+ if (m_inputSource != characters) {
+ [m_inputSource release];
+ m_inputSource = [characters retain];
+ }
+
+ // There is no way to get the scan code from carbon/cocoa. But we cannot
+ // use the value 0, since it indicates that the event originates from somewhere
+ // else than the keyboard.
+ quint32 nativeScanCode = 1;
+ quint32 nativeVirtualKey = [nsevent keyCode];
+
+ QChar ch = QChar::ReplacementCharacter;
+ int keyCode = Qt::Key_unknown;
+
+ // If a dead key occurs as a result of pressing a key combination then
+ // characters will have 0 length, but charactersIgnoringModifiers will
+ // have a valid character in it. This enables key combinations such as
+ // ALT+E to be used as a shortcut with an English keyboard even though
+ // pressing ALT+E will give a dead key while doing normal text input.
+ if ([characters length] != 0 || [charactersIgnoringModifiers length] != 0) {
+ auto ctrlOrMetaModifier = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta) ? Qt::ControlModifier : Qt::MetaModifier;
+ if (((modifiers & ctrlOrMetaModifier) || (modifiers & Qt::AltModifier)) && ([charactersIgnoringModifiers length] != 0))
+ ch = QChar([charactersIgnoringModifiers characterAtIndex:0]);
+ else if ([characters length] != 0)
+ ch = QChar([characters characterAtIndex:0]);
+ keyCode = [self convertKeyCode:ch];
+ }
+
+ // we will send a key event unless the input method sets m_sendKeyEvent to false
+ m_sendKeyEvent = true;
+ QString text;
+ // ignore text for the U+F700-U+F8FF range. This is used by Cocoa when
+ // delivering function keys (e.g. arrow keys, backspace, F1-F35, etc.)
+ if (!(modifiers & (Qt::ControlModifier | Qt::MetaModifier)) && (ch.unicode() < 0xf700 || ch.unicode() > 0xf8ff))
+ text = QString::fromNSString(characters);
+
+ QWindow *window = [self topLevelWindow];
+
+ // Popups implicitly grab key events; forward to the active popup if there is one.
+ // This allows popups to e.g. intercept shortcuts and close the popup in response.
+ if (QCocoaWindow *popup = QCocoaIntegration::instance()->activePopupWindow()) {
+ if (!popup->window()->flags().testFlag(Qt::ToolTip))
+ window = popup->window();
+ }
+
+ if (eventType == QEvent::KeyPress) {
+
+ if (m_composingText.isEmpty()) {
+ m_sendKeyEvent = !QWindowSystemInterface::handleShortcutEvent(window, timestamp, keyCode,
+ modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, [nsevent isARepeat], 1);
+
+ // Handling a shortcut may result in closing the window
+ if (!m_platformWindow)
+ return true;
+ }
+
+ QObject *fo = m_platformWindow->window()->focusObject();
+ if (m_sendKeyEvent && fo) {
+ QInputMethodQueryEvent queryEvent(Qt::ImEnabled | Qt::ImHints);
+ if (QCoreApplication::sendEvent(fo, &queryEvent)) {
+ bool imEnabled = queryEvent.value(Qt::ImEnabled).toBool();
+ Qt::InputMethodHints hints = static_cast<Qt::InputMethodHints>(queryEvent.value(Qt::ImHints).toUInt());
+ if (imEnabled && !(hints & Qt::ImhDigitsOnly || hints & Qt::ImhFormattedNumbersOnly || hints & Qt::ImhHiddenText)) {
+ // pass the key event to the input method. note that m_sendKeyEvent may be set to false during this call
+ m_currentlyInterpretedKeyEvent = nsevent;
+ [self interpretKeyEvents:@[nsevent]];
+ m_currentlyInterpretedKeyEvent = 0;
+ }
+ }
+ }
+ if (m_resendKeyEvent)
+ m_sendKeyEvent = true;
+ }
+
+ bool accepted = true;
+ if (m_sendKeyEvent && m_composingText.isEmpty()) {
+ QWindowSystemInterface::handleExtendedKeyEvent(window, timestamp, QEvent::Type(eventType), keyCode, modifiers,
+ nativeScanCode, nativeVirtualKey, nativeModifiers, text, [nsevent isARepeat], 1, false);
+ accepted = QWindowSystemInterface::flushWindowSystemEvents();
+ }
+ m_sendKeyEvent = false;
+ m_resendKeyEvent = false;
+ return accepted;
+}
+
+- (void)keyDown:(NSEvent *)nsevent
+{
+ if ([self isTransparentForUserInput])
+ return [super keyDown:nsevent];
+
+ const bool accepted = [self handleKeyEvent:nsevent eventType:int(QEvent::KeyPress)];
+
+ // When Qt is used to implement a plugin for a native application we
+ // want to propagate unhandled events to other native views. However,
+ // Qt does not always set the accepted state correctly (in particular
+ // for return key events), so do this for plugin applications only
+ // to prevent incorrect forwarding in the general case.
+ const bool shouldPropagate = QCoreApplication::testAttribute(Qt::AA_PluginApplication) && !accepted;
+
+ // Track keyDown acceptance/forward state for later acceptance of the keyUp.
+ if (!shouldPropagate)
+ m_acceptedKeyDowns.insert([nsevent keyCode]);
+
+ if (shouldPropagate)
+ [super keyDown:nsevent];
+}
+
+- (void)keyUp:(NSEvent *)nsevent
+{
+ if ([self isTransparentForUserInput])
+ return [super keyUp:nsevent];
+
+ const bool keyUpAccepted = [self handleKeyEvent:nsevent eventType:int(QEvent::KeyRelease)];
+
+ // Propagate the keyUp if neither Qt accepted it nor the corresponding KeyDown was
+ // accepted. Qt text controls wil often not use and ignore keyUp events, but we
+ // want to avoid propagating unmatched keyUps.
+ const bool keyDownAccepted = m_acceptedKeyDowns.remove([nsevent keyCode]);
+ if (!keyUpAccepted && !keyDownAccepted)
+ [super keyUp:nsevent];
+}
+
+- (void)cancelOperation:(id)sender
+{
+ Q_UNUSED(sender);
+
+ NSEvent *currentEvent = [NSApp currentEvent];
+ if (!currentEvent || currentEvent.type != NSEventTypeKeyDown)
+ return;
+
+ // Handling the key event may recurse back here through interpretKeyEvents
+ // (when IM is enabled), so we need to guard against that.
+ if (currentEvent == m_currentlyInterpretedKeyEvent)
+ return;
+
+ // Send Command+Key_Period and Escape as normal keypresses so that
+ // the key sequence is delivered through Qt. That way clients can
+ // intercept the shortcut and override its effect.
+ [self handleKeyEvent:currentEvent eventType:int(QEvent::KeyPress)];
+}
+
+- (void)flagsChanged:(NSEvent *)nsevent
+{
+ ulong timestamp = [nsevent timestamp] * 1000;
+ ulong modifiers = [nsevent modifierFlags];
+ Qt::KeyboardModifiers qmodifiers = [QNSView convertKeyModifiers:modifiers];
+
+ // calculate the delta and remember the current modifiers for next time
+ static ulong m_lastKnownModifiers;
+ ulong lastKnownModifiers = m_lastKnownModifiers;
+ ulong delta = lastKnownModifiers ^ modifiers;
+ m_lastKnownModifiers = modifiers;
+
+ struct qt_mac_enum_mapper
+ {
+ ulong mac_mask;
+ Qt::Key qt_code;
+ };
+ static qt_mac_enum_mapper modifier_key_symbols[] = {
+ { NSEventModifierFlagShift, Qt::Key_Shift },
+ { NSEventModifierFlagControl, Qt::Key_Meta },
+ { NSEventModifierFlagCommand, Qt::Key_Control },
+ { NSEventModifierFlagOption, Qt::Key_Alt },
+ { NSEventModifierFlagCapsLock, Qt::Key_CapsLock },
+ { 0ul, Qt::Key_unknown } };
+ for (int i = 0; modifier_key_symbols[i].mac_mask != 0u; ++i) {
+ uint mac_mask = modifier_key_symbols[i].mac_mask;
+ if ((delta & mac_mask) == 0u)
+ continue;
+
+ Qt::Key qtCode = modifier_key_symbols[i].qt_code;
+ if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) {
+ if (qtCode == Qt::Key_Meta)
+ qtCode = Qt::Key_Control;
+ else if (qtCode == Qt::Key_Control)
+ qtCode = Qt::Key_Meta;
+ }
+ QWindowSystemInterface::handleKeyEvent(m_platformWindow->window(),
+ timestamp,
+ (lastKnownModifiers & mac_mask) ? QEvent::KeyRelease : QEvent::KeyPress,
+ qtCode,
+ qmodifiers ^ [QNSView convertKeyModifiers:mac_mask]);
+ }
+}
+
+@end
diff --git a/src/plugins/platforms/cocoa/qnsview_menus.mm b/src/plugins/platforms/cocoa/qnsview_menus.mm
new file mode 100644
index 0000000000..f0489552aa
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qnsview_menus.mm
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// This file is included from qnsview.mm, and only used to organize the code
+
+#include <qcocoaapplicationdelegate.h>
+#include <qcocoansmenu.h>
+#include <qcocoamenuitem.h>
+#include <qcocoamenu.h>
+#include <qcocoamenubar.h>
+
+static bool selectorIsCutCopyPaste(SEL selector)
+{
+ return (selector == @selector(cut:)
+ || selector == @selector(copy:)
+ || selector == @selector(paste:)
+ || selector == @selector(selectAll:));
+}
+
+@interface QT_MANGLE_NAMESPACE(QNSView) (Menus)
+- (void)qt_itemFired:(QCocoaNSMenuItem *)item;
+@end
+
+@implementation QT_MANGLE_NAMESPACE(QNSView) (Menus)
+
+- (BOOL)validateMenuItem:(NSMenuItem*)item
+{
+ auto *nativeItem = qt_objc_cast<QCocoaNSMenuItem *>(item);
+ if (!nativeItem)
+ return item.enabled; // FIXME Test with with Qt as plugin or embedded QWindow.
+
+ auto *platformItem = nativeItem.platformMenuItem;
+ if (!platformItem)
+ return NO;
+
+ // Menu-holding items are always enabled, as it's conventional in Cocoa
+ if (platformItem->menu())
+ return YES;
+
+ // Check if a modal dialog is active. Validate only menu
+ // items belonging to this view's window own menu bar.
+ if (QGuiApplication::modalWindow()) {
+ QCocoaMenuBar *menubar = nullptr;
+
+ QObject *menuParent = platformItem->menuParent();
+ while (menuParent && !(menubar = qobject_cast<QCocoaMenuBar *>(menuParent))) {
+ auto *menuObject = dynamic_cast<QCocoaMenuObject *>(menuParent);
+ menuParent = menuObject->menuParent();
+ }
+
+ if (menubar && menubar->cocoaWindow() != self.platformWindow)
+ return NO;
+ }
+
+ return platformItem->isEnabled();
+}
+
+- (BOOL)respondsToSelector:(SEL)selector
+{
+ // Not exactly true. Both copy: and selectAll: can work on non key views.
+ if (selectorIsCutCopyPaste(selector))
+ return ([NSApp keyWindow] == self.window) && (self.window.firstResponder == self);
+
+ return [super respondsToSelector:selector];
+}
+
+- (void)qt_itemFired:(QCocoaNSMenuItem *)item
+{
+ auto *appDelegate = [QCocoaApplicationDelegate sharedDelegate];
+ [appDelegate qt_itemFired:item];
+}
+
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
+{
+ if (selectorIsCutCopyPaste(selector)) {
+ NSMethodSignature *itemFiredSign = [super methodSignatureForSelector:@selector(qt_itemFired:)];
+ return itemFiredSign;
+ }
+
+ return [super methodSignatureForSelector:selector];
+}
+
+- (void)forwardInvocation:(NSInvocation *)invocation
+{
+ if (selectorIsCutCopyPaste(invocation.selector)) {
+ NSObject *sender;
+ [invocation getArgument:&sender atIndex:2];
+ if (auto *nativeItem = qt_objc_cast<QCocoaNSMenuItem *>(sender)) {
+ [self qt_itemFired:nativeItem];
+ return;
+ }
+ }
+
+ [super forwardInvocation:invocation];
+}
+
+@end
diff --git a/src/plugins/platforms/cocoa/qnsview_mouse.mm b/src/plugins/platforms/cocoa/qnsview_mouse.mm
new file mode 100644
index 0000000000..3d6471005d
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qnsview_mouse.mm
@@ -0,0 +1,624 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// This file is included from qnsview.mm, and only used to organize the code
+
+@implementation QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) {
+ QNSView *view;
+}
+
+- (instancetype)initWithView:(QNSView *)theView
+{
+ if ((self = [super init]))
+ view = theView;
+
+ return self;
+}
+
+- (void)mouseMoved:(NSEvent *)theEvent
+{
+ [view mouseMovedImpl:theEvent];
+}
+
+- (void)mouseEntered:(NSEvent *)theEvent
+{
+ [view mouseEnteredImpl:theEvent];
+}
+
+- (void)mouseExited:(NSEvent *)theEvent
+{
+ [view mouseExitedImpl:theEvent];
+}
+
+- (void)cursorUpdate:(NSEvent *)theEvent
+{
+ [view cursorUpdate:theEvent];
+}
+
+@end
+
+@implementation QT_MANGLE_NAMESPACE(QNSView) (MouseAPI)
+
+- (void)resetMouseButtons
+{
+ m_buttons = Qt::NoButton;
+ m_frameStrutButtons = Qt::NoButton;
+}
+
+- (void)handleFrameStrutMouseEvent:(NSEvent *)theEvent
+{
+ if (!m_platformWindow)
+ return;
+
+ // get m_buttons in sync
+ // Don't send frme strut events if we are in the middle of a mouse drag.
+ if (m_buttons != Qt::NoButton)
+ return;
+
+ switch (theEvent.type) {
+ case NSEventTypeLeftMouseDown:
+ case NSEventTypeLeftMouseDragged:
+ m_frameStrutButtons |= Qt::LeftButton;
+ break;
+ case NSEventTypeLeftMouseUp:
+ m_frameStrutButtons &= ~Qt::LeftButton;
+ break;
+ case NSEventTypeRightMouseDown:
+ case NSEventTypeRightMouseDragged:
+ m_frameStrutButtons |= Qt::RightButton;
+ break;
+ case NSEventTypeRightMouseUp:
+ m_frameStrutButtons &= ~Qt::RightButton;
+ break;
+ case NSEventTypeOtherMouseDown:
+ m_frameStrutButtons |= cocoaButton2QtButton(theEvent.buttonNumber);
+ break;
+ case NSEventTypeOtherMouseUp:
+ m_frameStrutButtons &= ~cocoaButton2QtButton(theEvent.buttonNumber);
+ default:
+ break;
+ }
+
+ NSWindow *window = [self window];
+ NSPoint windowPoint = [theEvent locationInWindow];
+
+ int windowScreenY = [window frame].origin.y + [window frame].size.height;
+ NSPoint windowCoord = [self convertPoint:[self frame].origin toView:nil];
+ int viewScreenY = [window convertRectToScreen:NSMakeRect(windowCoord.x, windowCoord.y, 0, 0)].origin.y;
+ int titleBarHeight = windowScreenY - viewScreenY;
+
+ NSPoint nsViewPoint = [self convertPoint: windowPoint fromView: nil];
+ QPoint qtWindowPoint = QPoint(nsViewPoint.x, titleBarHeight + nsViewPoint.y);
+ NSPoint screenPoint = [window convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 0, 0)].origin;
+ QPoint qtScreenPoint = QCocoaScreen::mapFromNative(screenPoint).toPoint();
+
+ ulong timestamp = [theEvent timestamp] * 1000;
+ QWindowSystemInterface::handleFrameStrutMouseEvent(m_platformWindow->window(), timestamp, qtWindowPoint, qtScreenPoint, m_frameStrutButtons);
+}
+@end
+
+@implementation QT_MANGLE_NAMESPACE(QNSView) (Mouse)
+
+- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
+{
+ Q_UNUSED(theEvent)
+ if (!m_platformWindow)
+ return NO;
+ if ([self isTransparentForUserInput])
+ return NO;
+ return YES;
+}
+
+- (NSPoint)screenMousePoint:(NSEvent *)theEvent
+{
+ NSPoint screenPoint;
+ if (theEvent) {
+ NSPoint windowPoint = [theEvent locationInWindow];
+ if (qIsNaN(windowPoint.x) || qIsNaN(windowPoint.y)) {
+ screenPoint = [NSEvent mouseLocation];
+ } else {
+ NSRect screenRect = [[theEvent window] convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 1, 1)];
+ screenPoint = screenRect.origin;
+ }
+ } else {
+ screenPoint = [NSEvent mouseLocation];
+ }
+ return screenPoint;
+}
+
+- (void)handleMouseEvent:(NSEvent *)theEvent
+{
+ if (!m_platformWindow)
+ return;
+
+#ifndef QT_NO_TABLETEVENT
+ // Tablet events may come in via the mouse event handlers,
+ // check if this is a valid tablet event first.
+ if ([self handleTabletEvent: theEvent])
+ return;
+#endif
+
+ QPointF qtWindowPoint;
+ QPointF qtScreenPoint;
+ QNSView *targetView = self;
+ if (!targetView.platformWindow)
+ return;
+
+ // Popups implicitly grap mouse events; forward to the active popup if there is one
+ if (QCocoaWindow *popup = QCocoaIntegration::instance()->activePopupWindow()) {
+ // Tooltips must be transparent for mouse events
+ // The bug reference is QTBUG-46379
+ if (!popup->window()->flags().testFlag(Qt::ToolTip)) {
+ if (QNSView *popupView = qnsview_cast(popup->view()))
+ targetView = popupView;
+ }
+ }
+
+ [targetView convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint];
+ ulong timestamp = [theEvent timestamp] * 1000;
+
+ QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag();
+ nativeDrag->setLastMouseEvent(theEvent, self);
+
+ const auto modifiers = [QNSView convertKeyModifiers:theEvent.modifierFlags];
+ const auto buttons = currentlyPressedMouseButtons();
+ auto button = cocoaButton2QtButton(theEvent);
+ if (button == Qt::LeftButton && m_sendUpAsRightButton)
+ button = Qt::RightButton;
+ const auto eventType = cocoaEvent2QtMouseEvent(theEvent);
+
+ QWindowSystemInterface::handleMouseEvent(targetView->m_platformWindow->window(),
+ timestamp, qtWindowPoint, qtScreenPoint,
+ buttons, button, eventType, modifiers);
+}
+
+- (bool)handleMouseDownEvent:(NSEvent *)theEvent
+{
+ if ([self isTransparentForUserInput])
+ return false;
+
+ const auto button = cocoaButton2QtButton(theEvent);
+
+ QPointF qtWindowPoint;
+ QPointF qtScreenPoint;
+ [self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint];
+ Q_UNUSED(qtScreenPoint);
+
+ // Maintain masked state for the button for use by MouseDragged and MouseUp.
+ QRegion mask = m_platformWindow->window()->mask();
+ const bool masked = !mask.isEmpty() && !mask.contains(qtWindowPoint.toPoint());
+ if (masked)
+ m_acceptedMouseDowns &= ~button;
+ else
+ m_acceptedMouseDowns |= button;
+
+ // Forward masked out events to the next responder
+ if (masked)
+ return false;
+
+ m_buttons |= button;
+
+ [self handleMouseEvent:theEvent];
+ return true;
+}
+
+- (bool)handleMouseDraggedEvent:(NSEvent *)theEvent
+{
+ if ([self isTransparentForUserInput])
+ return false;
+
+ const auto button = cocoaButton2QtButton(theEvent);
+
+ // Forward the event to the next responder if Qt did not accept the
+ // corresponding mouse down for this button
+ if (!(m_acceptedMouseDowns & button) == button)
+ return false;
+
+ [self handleMouseEvent:theEvent];
+ return true;
+}
+
+- (bool)handleMouseUpEvent:(NSEvent *)theEvent
+{
+ if ([self isTransparentForUserInput])
+ return false;
+
+ auto button = cocoaButton2QtButton(theEvent);
+
+ // Forward the event to the next responder if Qt did not accept the
+ // corresponding mouse down for this button
+ if (!(m_acceptedMouseDowns & button) == button)
+ return false;
+
+ if (m_sendUpAsRightButton && button == Qt::LeftButton)
+ button = Qt::RightButton;
+
+ m_buttons &= ~button;
+
+ [self handleMouseEvent:theEvent];
+
+ if (button == Qt::RightButton)
+ m_sendUpAsRightButton = false;
+
+ return true;
+}
+
+- (void)mouseDown:(NSEvent *)theEvent
+{
+ if ([self isTransparentForUserInput])
+ return [super mouseDown:theEvent];
+ m_sendUpAsRightButton = false;
+
+ // Handle any active poup windows; clicking outisde them should close them
+ // all. Don't do anything or clicks inside one of the menus, let Cocoa
+ // handle that case. Note that in practice many windows of the Qt::Popup type
+ // will actually close themselves in this case using logic implemented in
+ // that particular poup type (for example context menus). However, Qt expects
+ // that plain popup QWindows will also be closed, so we implement the logic
+ // here as well.
+ QList<QCocoaWindow *> *popups = QCocoaIntegration::instance()->popupWindowStack();
+ if (!popups->isEmpty()) {
+ // Check if the click is outside all popups.
+ bool inside = false;
+ QPointF qtScreenPoint = QCocoaScreen::mapFromNative([self screenMousePoint:theEvent]);
+ for (QList<QCocoaWindow *>::const_iterator it = popups->begin(); it != popups->end(); ++it) {
+ if ((*it)->geometry().contains(qtScreenPoint.toPoint())) {
+ inside = true;
+ break;
+ }
+ }
+ // Close the popups if the click was outside.
+ if (!inside) {
+ Qt::WindowType type = QCocoaIntegration::instance()->activePopupWindow()->window()->type();
+ while (QCocoaWindow *popup = QCocoaIntegration::instance()->popPopupWindow()) {
+ QWindowSystemInterface::handleCloseEvent(popup->window());
+ QWindowSystemInterface::flushWindowSystemEvents();
+ }
+ // Consume the mouse event when closing the popup, except for tool tips
+ // were it's expected that the event is processed normally.
+ if (type != Qt::ToolTip)
+ return;
+ }
+ }
+
+ QPointF qtWindowPoint;
+ QPointF qtScreenPoint;
+ [self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint];
+ Q_UNUSED(qtScreenPoint);
+
+ QRegion mask = m_platformWindow->window()->mask();
+ const bool masked = !mask.isEmpty() && !mask.contains(qtWindowPoint.toPoint());
+ // Maintain masked state for the button for use by MouseDragged and Up.
+ if (masked)
+ m_acceptedMouseDowns &= ~Qt::LeftButton;
+ else
+ m_acceptedMouseDowns |= Qt::LeftButton;
+
+ // Forward masked out events to the next responder
+ if (masked) {
+ [super mouseDown:theEvent];
+ return;
+ }
+
+ if ([self hasMarkedText]) {
+ [[NSTextInputContext currentInputContext] handleEvent:theEvent];
+ } else {
+ auto ctrlOrMetaModifier = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta) ? Qt::ControlModifier : Qt::MetaModifier;
+ if (!m_dontOverrideCtrlLMB && [QNSView convertKeyModifiers:[theEvent modifierFlags]] & ctrlOrMetaModifier) {
+ m_buttons |= Qt::RightButton;
+ m_sendUpAsRightButton = true;
+ } else {
+ m_buttons |= Qt::LeftButton;
+ }
+ [self handleMouseEvent:theEvent];
+ }
+}
+
+- (void)mouseDragged:(NSEvent *)theEvent
+{
+ const bool accepted = [self handleMouseDraggedEvent:theEvent];
+ if (!accepted)
+ [super mouseDragged:theEvent];
+}
+
+- (void)mouseUp:(NSEvent *)theEvent
+{
+ const bool accepted = [self handleMouseUpEvent:theEvent];
+ if (!accepted)
+ [super mouseUp:theEvent];
+}
+
+- (void)rightMouseDown:(NSEvent *)theEvent
+{
+ const bool accepted = [self handleMouseDownEvent:theEvent];
+ if (!accepted)
+ [super rightMouseDown:theEvent];
+}
+
+- (void)rightMouseDragged:(NSEvent *)theEvent
+{
+ const bool accepted = [self handleMouseDraggedEvent:theEvent];
+ if (!accepted)
+ [super rightMouseDragged:theEvent];
+}
+
+- (void)rightMouseUp:(NSEvent *)theEvent
+{
+ const bool accepted = [self handleMouseUpEvent:theEvent];
+ if (!accepted)
+ [super rightMouseUp:theEvent];
+}
+
+- (void)otherMouseDown:(NSEvent *)theEvent
+{
+ const bool accepted = [self handleMouseDownEvent:theEvent];
+ if (!accepted)
+ [super otherMouseDown:theEvent];
+}
+
+- (void)otherMouseDragged:(NSEvent *)theEvent
+{
+ const bool accepted = [self handleMouseDraggedEvent:theEvent];
+ if (!accepted)
+ [super otherMouseDragged:theEvent];
+}
+
+- (void)otherMouseUp:(NSEvent *)theEvent
+{
+ const bool accepted = [self handleMouseUpEvent:theEvent];
+ if (!accepted)
+ [super otherMouseUp:theEvent];
+}
+
+- (void)updateTrackingAreas
+{
+ [super updateTrackingAreas];
+
+ QMacAutoReleasePool pool;
+
+ // NSTrackingInVisibleRect keeps care of updating once the tracking is set up, so bail out early
+ if (m_trackingArea && [[self trackingAreas] containsObject:m_trackingArea])
+ return;
+
+ // Ideally, we shouldn't have NSTrackingMouseMoved events included below, it should
+ // only be turned on if mouseTracking, hover is on or a tool tip is set.
+ // Unfortunately, Qt will send "tooltip" events on mouse moves, so we need to
+ // turn it on in ALL case. That means EVERY QWindow gets to pay the cost of
+ // mouse moves delivered to it (Apple recommends keeping it OFF because there
+ // is a performance hit). So it goes.
+ NSUInteger trackingOptions = NSTrackingMouseEnteredAndExited | NSTrackingActiveInActiveApp
+ | NSTrackingInVisibleRect | NSTrackingMouseMoved | NSTrackingCursorUpdate;
+ [m_trackingArea release];
+ m_trackingArea = [[NSTrackingArea alloc] initWithRect:[self frame]
+ options:trackingOptions
+ owner:m_mouseMoveHelper
+ userInfo:nil];
+ [self addTrackingArea:m_trackingArea];
+}
+
+- (void)cursorUpdate:(NSEvent *)theEvent
+{
+ qCDebug(lcQpaMouse) << "[QNSView cursorUpdate:]" << self.cursor;
+
+ // Note: We do not get this callback when moving from a subview that
+ // uses the legacy cursorRect API, so the cursor is reset to the arrow
+ // cursor. See rdar://34183708
+
+ if (self.cursor)
+ [self.cursor set];
+ else
+ [super cursorUpdate:theEvent];
+}
+
+- (void)mouseMovedImpl:(NSEvent *)theEvent
+{
+ if (!m_platformWindow)
+ return;
+
+ if ([self isTransparentForUserInput])
+ return;
+
+ QPointF windowPoint;
+ QPointF screenPoint;
+ [self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
+ QWindow *childWindow = m_platformWindow->childWindowAt(windowPoint.toPoint());
+
+ // Top-level windows generate enter-leave events for sub-windows.
+ // Qt wants to know which window (if any) will be entered at the
+ // the time of the leave. This is dificult to accomplish by
+ // handling mouseEnter and mouseLeave envents, since they are sent
+ // individually to different views.
+ if (m_platformWindow->isContentView() && childWindow) {
+ if (childWindow != m_platformWindow->m_enterLeaveTargetWindow) {
+ QWindowSystemInterface::handleEnterLeaveEvent(childWindow, m_platformWindow->m_enterLeaveTargetWindow, windowPoint, screenPoint);
+ m_platformWindow->m_enterLeaveTargetWindow = childWindow;
+ }
+ }
+
+ // Cocoa keeps firing mouse move events for obscured parent views. Qt should not
+ // send those events so filter them out here.
+ if (childWindow != m_platformWindow->window())
+ return;
+
+ [self handleMouseEvent: theEvent];
+}
+
+- (void)mouseEnteredImpl:(NSEvent *)theEvent
+{
+ Q_UNUSED(theEvent)
+ if (!m_platformWindow)
+ return;
+
+ m_platformWindow->m_windowUnderMouse = true;
+
+ if ([self isTransparentForUserInput])
+ return;
+
+ // Top-level windows generate enter events for sub-windows.
+ if (!m_platformWindow->isContentView())
+ return;
+
+ QPointF windowPoint;
+ QPointF screenPoint;
+ [self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
+ m_platformWindow->m_enterLeaveTargetWindow = m_platformWindow->childWindowAt(windowPoint.toPoint());
+ QWindowSystemInterface::handleEnterEvent(m_platformWindow->m_enterLeaveTargetWindow, windowPoint, screenPoint);
+}
+
+- (void)mouseExitedImpl:(NSEvent *)theEvent
+{
+ Q_UNUSED(theEvent);
+ if (!m_platformWindow)
+ return;
+
+ m_platformWindow->m_windowUnderMouse = false;
+
+ if ([self isTransparentForUserInput])
+ return;
+
+ // Top-level windows generate leave events for sub-windows.
+ if (!m_platformWindow->isContentView())
+ return;
+
+ QWindowSystemInterface::handleLeaveEvent(m_platformWindow->m_enterLeaveTargetWindow);
+ m_platformWindow->m_enterLeaveTargetWindow = 0;
+}
+
+#if QT_CONFIG(wheelevent)
+- (void)scrollWheel:(NSEvent *)theEvent
+{
+ if (!m_platformWindow)
+ return;
+
+ if ([self isTransparentForUserInput])
+ return [super scrollWheel:theEvent];
+
+ QPoint angleDelta;
+ Qt::MouseEventSource source = Qt::MouseEventNotSynthesized;
+ if ([theEvent hasPreciseScrollingDeltas]) {
+ // The mouse device contains pixel scroll wheel support (Mighty Mouse, Trackpad).
+ // Since deviceDelta is delivered as pixels rather than degrees, we need to
+ // convert from pixels to degrees in a sensible manner.
+ // It looks like 1/4 degrees per pixel behaves most native.
+ // (NB: Qt expects the unit for delta to be 8 per degree):
+ const int pixelsToDegrees = 2; // 8 * 1/4
+ angleDelta.setX([theEvent scrollingDeltaX] * pixelsToDegrees);
+ angleDelta.setY([theEvent scrollingDeltaY] * pixelsToDegrees);
+ source = Qt::MouseEventSynthesizedBySystem;
+ } else {
+ // Remove acceleration, and use either -120 or 120 as delta:
+ angleDelta.setX(qBound(-120, int([theEvent deltaX] * 10000), 120));
+ angleDelta.setY(qBound(-120, int([theEvent deltaY] * 10000), 120));
+ }
+
+ QPoint pixelDelta;
+ if ([theEvent hasPreciseScrollingDeltas]) {
+ pixelDelta.setX([theEvent scrollingDeltaX]);
+ pixelDelta.setY([theEvent scrollingDeltaY]);
+ } else {
+ // docs: "In the case of !hasPreciseScrollingDeltas, multiply the delta with the line width."
+ // scrollingDeltaX seems to return a minimum value of 0.1 in this case, map that to two pixels.
+ const CGFloat lineWithEstimate = 20.0;
+ pixelDelta.setX([theEvent scrollingDeltaX] * lineWithEstimate);
+ pixelDelta.setY([theEvent scrollingDeltaY] * lineWithEstimate);
+ }
+
+ QPointF qt_windowPoint;
+ QPointF qt_screenPoint;
+ [self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&qt_windowPoint andScreenPoint:&qt_screenPoint];
+ NSTimeInterval timestamp = [theEvent timestamp];
+ ulong qt_timestamp = timestamp * 1000;
+
+ Qt::ScrollPhase phase = Qt::NoScrollPhase;
+ if (theEvent.phase == NSEventPhaseMayBegin || theEvent.phase == NSEventPhaseBegan) {
+ // MayBegin is likely to happen. We treat it the same as an actual begin,
+ // and follow it with an update when the actual begin is delivered.
+ phase = m_scrolling ? Qt::ScrollUpdate : Qt::ScrollBegin;
+ m_scrolling = true;
+ } else if (theEvent.phase == NSEventPhaseStationary || theEvent.phase == NSEventPhaseChanged) {
+ phase = Qt::ScrollUpdate;
+ } else if (theEvent.phase == NSEventPhaseEnded) {
+ // A scroll event phase may be followed by a momentum phase after the user releases
+ // the finger, and in that case we don't want to send a Qt::ScrollEnd until after
+ // the momentum phase has ended. Unfortunately there isn't any guaranteed way of
+ // knowing whether or not a NSEventPhaseEnded will be followed by a momentum phase.
+ // The best we can do is to look at the event queue and hope that the system has
+ // had time to emit a momentum phase event.
+ if ([NSApp nextEventMatchingMask:NSEventMaskScrollWheel untilDate:[NSDate distantPast]
+ inMode:@"QtMomementumEventSearchMode" dequeue:NO].momentumPhase == NSEventPhaseBegan) {
+ Q_ASSERT(pixelDelta.isNull() && angleDelta.isNull());
+ return; // Ignore this event, as it has a delta of 0,0
+ }
+ phase = Qt::ScrollEnd;
+ m_scrolling = false;
+ } else if (theEvent.momentumPhase == NSEventPhaseBegan) {
+ Q_ASSERT(!pixelDelta.isNull() && !angleDelta.isNull());
+ phase = Qt::ScrollUpdate; // Send as update, it has a delta
+ } else if (theEvent.momentumPhase == NSEventPhaseChanged) {
+ phase = Qt::ScrollMomentum;
+ } else if (theEvent.phase == NSEventPhaseCancelled
+ || theEvent.momentumPhase == NSEventPhaseEnded
+ || theEvent.momentumPhase == NSEventPhaseCancelled) {
+ phase = Qt::ScrollEnd;
+ m_scrolling = false;
+ } else {
+ Q_ASSERT(theEvent.momentumPhase != NSEventPhaseStationary);
+ }
+
+ // Prevent keyboard modifier state from changing during scroll event streams.
+ // A two-finger trackpad flick generates a stream of scroll events. We want
+ // the keyboard modifier state to be the state at the beginning of the
+ // flick in order to avoid changing the interpretation of the events
+ // mid-stream. One example of this happening would be when pressing cmd
+ // after scrolling in Qt Creator: not taking the phase into account causes
+ // the end of the event stream to be interpreted as font size changes.
+ if (theEvent.momentumPhase == NSEventPhaseNone)
+ m_currentWheelModifiers = [QNSView convertKeyModifiers:[theEvent modifierFlags]];
+
+ // "isInverted": natural OS X scrolling, inverted from the Qt/other platform/Jens perspective.
+ bool isInverted = [theEvent isDirectionInvertedFromDevice];
+
+ qCDebug(lcQpaMouse) << "scroll wheel @ window pos" << qt_windowPoint << "delta px" << pixelDelta
+ << "angle" << angleDelta << "phase" << phase << (isInverted ? "inverted" : "");
+ QWindowSystemInterface::handleWheelEvent(m_platformWindow->window(), qt_timestamp, qt_windowPoint,
+ qt_screenPoint, pixelDelta, angleDelta, m_currentWheelModifiers, phase, source, isInverted);
+}
+#endif // QT_CONFIG(wheelevent)
+
+@end
diff --git a/src/plugins/platforms/cocoa/qnsview_tablet.mm b/src/plugins/platforms/cocoa/qnsview_tablet.mm
new file mode 100644
index 0000000000..43b0aa0960
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qnsview_tablet.mm
@@ -0,0 +1,223 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// This file is included from qnsview.mm, and only used to organize the code
+
+#ifndef QT_NO_TABLETEVENT
+
+Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
+
+struct QCocoaTabletDeviceData
+{
+ QTabletEvent::TabletDevice device;
+ QTabletEvent::PointerType pointerType;
+ uint capabilityMask;
+ qint64 uid;
+};
+
+typedef QHash<uint, QCocoaTabletDeviceData> QCocoaTabletDeviceDataHash;
+Q_GLOBAL_STATIC(QCocoaTabletDeviceDataHash, tabletDeviceDataHash)
+
+@implementation QT_MANGLE_NAMESPACE(QNSView) (Tablet)
+
+- (bool)handleTabletEvent:(NSEvent *)theEvent
+{
+ static bool ignoreButtonMapping = qEnvironmentVariableIsSet("QT_MAC_TABLET_IGNORE_BUTTON_MAPPING");
+
+ if (!m_platformWindow)
+ return false;
+
+ NSEventType eventType = [theEvent type];
+ if (eventType != NSEventTypeTabletPoint && [theEvent subtype] != NSEventSubtypeTabletPoint)
+ return false; // Not a tablet event.
+
+ ulong timestamp = [theEvent timestamp] * 1000;
+
+ QPointF windowPoint;
+ QPointF screenPoint;
+ [self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint: &windowPoint andScreenPoint: &screenPoint];
+
+ uint deviceId = [theEvent deviceID];
+ if (!tabletDeviceDataHash->contains(deviceId)) {
+ // Error: Unknown tablet device. Qt also gets into this state
+ // when running on a VM. This appears to be harmless; don't
+ // print a warning.
+ return false;
+ }
+ const QCocoaTabletDeviceData &deviceData = tabletDeviceDataHash->value(deviceId);
+
+ bool down = (eventType != NSEventTypeMouseMoved);
+
+ qreal pressure;
+ if (down) {
+ pressure = [theEvent pressure];
+ } else {
+ pressure = 0.0;
+ }
+
+ NSPoint tilt = [theEvent tilt];
+ int xTilt = qRound(tilt.x * 60.0);
+ int yTilt = qRound(tilt.y * -60.0);
+ qreal tangentialPressure = 0;
+ qreal rotation = 0;
+ int z = 0;
+ if (deviceData.capabilityMask & 0x0200)
+ z = [theEvent absoluteZ];
+
+ if (deviceData.capabilityMask & 0x0800)
+ tangentialPressure = ([theEvent tangentialPressure] * 2.0) - 1.0;
+
+ rotation = 360.0 - [theEvent rotation];
+ if (rotation > 180.0)
+ rotation -= 360.0;
+
+ Qt::KeyboardModifiers keyboardModifiers = [QNSView convertKeyModifiers:[theEvent modifierFlags]];
+ Qt::MouseButtons buttons = ignoreButtonMapping ? static_cast<Qt::MouseButtons>(static_cast<uint>([theEvent buttonMask])) : m_buttons;
+
+ qCDebug(lcQpaTablet, "event on tablet %d with tool %d type %d unique ID %lld pos %6.1f, %6.1f root pos %6.1f, %6.1f buttons 0x%x pressure %4.2lf tilt %d, %d rotation %6.2lf",
+ deviceId, deviceData.device, deviceData.pointerType, deviceData.uid,
+ windowPoint.x(), windowPoint.y(), screenPoint.x(), screenPoint.y(),
+ static_cast<uint>(buttons), pressure, xTilt, yTilt, rotation);
+
+ QWindowSystemInterface::handleTabletEvent(m_platformWindow->window(), timestamp, windowPoint, screenPoint,
+ deviceData.device, deviceData.pointerType, buttons, pressure, xTilt, yTilt,
+ tangentialPressure, rotation, z, deviceData.uid,
+ keyboardModifiers);
+ return true;
+}
+
+- (void)tabletPoint:(NSEvent *)theEvent
+{
+ if ([self isTransparentForUserInput])
+ return [super tabletPoint:theEvent];
+
+ [self handleTabletEvent: theEvent];
+}
+
+static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
+{
+ qint64 uid = [theEvent uniqueID];
+ uint bits = [theEvent vendorPointingDeviceType];
+ if (bits == 0 && uid != 0) {
+ // Fallback. It seems that the driver doesn't always include all the information.
+ // High-End Wacom devices store their "type" in the uper bits of the Unique ID.
+ // I'm not sure how to handle it for consumer devices, but I'll test that in a bit.
+ bits = uid >> 32;
+ }
+
+ QTabletEvent::TabletDevice device;
+ // Defined in the "EN0056-NxtGenImpGuideX"
+ // on Wacom's Developer Website (www.wacomeng.com)
+ if (((bits & 0x0006) == 0x0002) && ((bits & 0x0F06) != 0x0902)) {
+ device = QTabletEvent::Stylus;
+ } else {
+ switch (bits & 0x0F06) {
+ case 0x0802:
+ device = QTabletEvent::Stylus;
+ break;
+ case 0x0902:
+ device = QTabletEvent::Airbrush;
+ break;
+ case 0x0004:
+ device = QTabletEvent::FourDMouse;
+ break;
+ case 0x0006:
+ device = QTabletEvent::Puck;
+ break;
+ case 0x0804:
+ device = QTabletEvent::RotationStylus;
+ break;
+ default:
+ device = QTabletEvent::NoDevice;
+ }
+ }
+ return device;
+}
+
+- (void)tabletProximity:(NSEvent *)theEvent
+{
+ if ([self isTransparentForUserInput])
+ return [super tabletProximity:theEvent];
+
+ ulong timestamp = [theEvent timestamp] * 1000;
+
+ QCocoaTabletDeviceData deviceData;
+ deviceData.uid = [theEvent uniqueID];
+ deviceData.capabilityMask = [theEvent capabilityMask];
+
+ switch ([theEvent pointingDeviceType]) {
+ case NSPointingDeviceTypeUnknown:
+ default:
+ deviceData.pointerType = QTabletEvent::UnknownPointer;
+ break;
+ case NSPointingDeviceTypePen:
+ deviceData.pointerType = QTabletEvent::Pen;
+ break;
+ case NSPointingDeviceTypeCursor:
+ deviceData.pointerType = QTabletEvent::Cursor;
+ break;
+ case NSPointingDeviceTypeEraser:
+ deviceData.pointerType = QTabletEvent::Eraser;
+ break;
+ }
+
+ deviceData.device = wacomTabletDevice(theEvent);
+
+ // The deviceID is "unique" while in the proximity, it's a key that we can use for
+ // linking up QCocoaTabletDeviceData to an event (especially if there are two devices in action).
+ bool entering = [theEvent isEnteringProximity];
+ uint deviceId = [theEvent deviceID];
+ if (entering) {
+ tabletDeviceDataHash->insert(deviceId, deviceData);
+ } else {
+ tabletDeviceDataHash->remove(deviceId);
+ }
+
+ qCDebug(lcQpaTablet, "proximity change on tablet %d: current tool %d type %d unique ID %lld",
+ deviceId, deviceData.device, deviceData.pointerType, deviceData.uid);
+
+ if (entering) {
+ QWindowSystemInterface::handleTabletEnterProximityEvent(timestamp, deviceData.device, deviceData.pointerType, deviceData.uid);
+ } else {
+ QWindowSystemInterface::handleTabletLeaveProximityEvent(timestamp, deviceData.device, deviceData.pointerType, deviceData.uid);
+ }
+}
+@end
+
+#endif
diff --git a/src/plugins/platforms/cocoa/qnsview_touch.mm b/src/plugins/platforms/cocoa/qnsview_touch.mm
new file mode 100644
index 0000000000..e789213f70
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qnsview_touch.mm
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// This file is included from qnsview.mm, and only used to organize the code
+
+Q_LOGGING_CATEGORY(lcQpaTouch, "qt.qpa.input.touch")
+
+@implementation QT_MANGLE_NAMESPACE(QNSView) (Touch)
+
+- (bool)shouldSendSingleTouch
+{
+ if (!m_platformWindow)
+ return true;
+
+ // QtWidgets expects single-point touch events, QtDeclarative does not.
+ // Until there is an API we solve this by looking at the window class type.
+ return m_platformWindow->window()->inherits("QWidgetWindow");
+}
+
+- (void)touchesBeganWithEvent:(NSEvent *)event
+{
+ if (!m_platformWindow)
+ return;
+
+ const NSTimeInterval timestamp = [event timestamp];
+ const QList<QWindowSystemInterface::TouchPoint> points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]);
+ qCDebug(lcQpaTouch) << "touchesBeganWithEvent" << points << "from device" << hex << [event deviceID];
+ QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), points);
+}
+
+- (void)touchesMovedWithEvent:(NSEvent *)event
+{
+ if (!m_platformWindow)
+ return;
+
+ const NSTimeInterval timestamp = [event timestamp];
+ const QList<QWindowSystemInterface::TouchPoint> points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]);
+ qCDebug(lcQpaTouch) << "touchesMovedWithEvent" << points << "from device" << hex << [event deviceID];
+ QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), points);
+}
+
+- (void)touchesEndedWithEvent:(NSEvent *)event
+{
+ if (!m_platformWindow)
+ return;
+
+ const NSTimeInterval timestamp = [event timestamp];
+ const QList<QWindowSystemInterface::TouchPoint> points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]);
+ qCDebug(lcQpaTouch) << "touchesEndedWithEvent" << points << "from device" << hex << [event deviceID];
+ QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), points);
+}
+
+- (void)touchesCancelledWithEvent:(NSEvent *)event
+{
+ if (!m_platformWindow)
+ return;
+
+ const NSTimeInterval timestamp = [event timestamp];
+ const QList<QWindowSystemInterface::TouchPoint> points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]);
+ qCDebug(lcQpaTouch) << "touchesCancelledWithEvent" << points << "from device" << hex << [event deviceID];
+ QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), points);
+}
+
+@end
diff --git a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
deleted file mode 100644
index 645a93edf7..0000000000
--- a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
+++ /dev/null
@@ -1,93 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qnsview.h"
-#include "qcocoahelpers.h"
-#include "qcocoaaccessibility.h"
-#include "qcocoaaccessibilityelement.h"
-#include "qcocoaintegration.h"
-
-#include <QtGui/qaccessible.h>
-#include <QtCore/QDebug>
-
-#import <AppKit/NSAccessibility.h>
-
-#ifndef QT_NO_ACCESSIBILITY
-
-@implementation QNSView (QNSViewAccessibility)
-
-- (id)childAccessibleElement {
- if (m_platformWindow.isNull())
- return nil;
-
- if (!m_platformWindow->window()->accessibleRoot())
- return nil;
-
- QAccessible::Id childId = QAccessible::uniqueId(m_platformWindow->window()->accessibleRoot());
- return [QMacAccessibilityElement elementWithId: childId];
-}
-
-// The QNSView is a container that the user does not interact directly with:
-// Remove it from the user-visible accessibility tree.
-- (BOOL)accessibilityIsIgnored {
- return YES;
-}
-
-- (id)accessibilityAttributeValue:(NSString *)attribute {
- // activate accessibility updates
- QCocoaIntegration::instance()->accessibility()->setActive(true);
-
- if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
- return NSAccessibilityUnignoredChildrenForOnlyChild([self childAccessibleElement]);
- } else {
- return [super accessibilityAttributeValue:attribute];
- }
-}
-
-- (id)accessibilityHitTest:(NSPoint)point {
- return [[self childAccessibleElement] accessibilityHitTest: point];
-}
-
-- (id)accessibilityFocusedUIElement {
- return [[self childAccessibleElement] accessibilityFocusedUIElement];
-}
-
-@end
-
-#endif // QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/cocoa/qnswindow.h b/src/plugins/platforms/cocoa/qnswindow.h
index ea690b69e3..64f1ed0802 100644
--- a/src/plugins/platforms/cocoa/qnswindow.h
+++ b/src/plugins/platforms/cocoa/qnswindow.h
@@ -67,6 +67,7 @@ QT_FORWARD_DECLARE_CLASS(QCocoaWindow)
- (void)dealloc;
- (BOOL)isOpaque;
- (NSColor *)backgroundColor;
+- (NSString *)description;
@property (nonatomic, readonly) QCocoaWindow *platformWindow;
@end
diff --git a/src/plugins/platforms/cocoa/qnswindow.mm b/src/plugins/platforms/cocoa/qnswindow.mm
index cb13b7d184..1b9dd95cbc 100644
--- a/src/plugins/platforms/cocoa/qnswindow.mm
+++ b/src/plugins/platforms/cocoa/qnswindow.mm
@@ -38,7 +38,6 @@
****************************************************************************/
#include "qnswindow.h"
-#include "qnswindowdelegate.h"
#include "qcocoawindow.h"
#include "qcocoahelpers.h"
#include "qcocoaeventdispatcher.h"
@@ -46,18 +45,18 @@
#include <qpa/qwindowsysteminterface.h>
#include <qoperatingsystemversion.h>
-Q_LOGGING_CATEGORY(lcCocoaEvents, "qt.qpa.cocoa.events");
+Q_LOGGING_CATEGORY(lcQpaEvents, "qt.qpa.events");
static bool isMouseEvent(NSEvent *ev)
{
switch ([ev type]) {
- case NSLeftMouseDown:
- case NSLeftMouseUp:
- case NSRightMouseDown:
- case NSRightMouseUp:
- case NSMouseMoved:
- case NSLeftMouseDragged:
- case NSRightMouseDragged:
+ case NSEventTypeLeftMouseDown:
+ case NSEventTypeLeftMouseUp:
+ case NSEventTypeRightMouseDown:
+ case NSEventTypeRightMouseUp:
+ case NSEventTypeMouseMoved:
+ case NSEventTypeLeftMouseDragged:
+ case NSEventTypeRightMouseDragged:
return true;
default:
return false;
@@ -72,7 +71,7 @@ static bool isMouseEvent(NSEvent *ev)
[center addObserverForName:NSWindowDidEnterFullScreenNotification object:nil queue:nil
usingBlock:^(NSNotification *notification) {
objc_setAssociatedObject(notification.object, @selector(qt_fullScreen),
- [NSNumber numberWithBool:YES], OBJC_ASSOCIATION_RETAIN);
+ @(YES), OBJC_ASSOCIATION_RETAIN);
}
];
[center addObserverForName:NSWindowDidExitFullScreenNotification object:nil queue:nil
@@ -187,22 +186,22 @@ static bool isMouseEvent(NSEvent *ev)
/*!
Borderless windows need a transparent background
- Technically windows with NSTexturedBackgroundWindowMask (such
- as windows with unified toolbars) need to draw the textured
+ Technically windows with NSWindowStyleMaskTexturedBackground
+ (such as windows with unified toolbars) need to draw the textured
background of the NSWindow, and can't have a transparent
- background, but as NSBorderlessWindowMask is 0, you can't
- have a window with NSTexturedBackgroundWindowMask that is
+ background, but as NSWindowStyleMaskBorderless is 0, you can't
+ have a window with NSWindowStyleMaskTexturedBackground that is
also borderless.
*/
- (NSColor *)backgroundColor
{
- return self.styleMask == NSBorderlessWindowMask
+ return self.styleMask == NSWindowStyleMaskBorderless
? [NSColor clearColor] : qt_objcDynamicSuper();
}
- (void)sendEvent:(NSEvent*)theEvent
{
- qCDebug(lcCocoaEvents) << "Sending" << theEvent << "to" << self;
+ qCDebug(lcQpaEvents) << "Sending" << theEvent << "to" << self;
// We might get events for a NSWindow after the corresponding platform
// window has been deleted, as the NSWindow can outlive the QCocoaWindow
@@ -239,7 +238,7 @@ static bool isMouseEvent(NSEvent *ev)
- (void)closeAndRelease
{
- qCDebug(lcQpaCocoaWindow) << "closeAndRelease" << self;
+ qCDebug(lcQpaWindow) << "closeAndRelease" << self;
[self.delegate release];
self.delegate = nil;
@@ -252,7 +251,7 @@ static bool isMouseEvent(NSEvent *ev)
#pragma clang diagnostic ignored "-Wobjc-missing-super-calls"
- (void)dealloc
{
- qCDebug(lcQpaCocoaWindow) << "dealloc" << self;
+ qCDebug(lcQpaWindow) << "dealloc" << self;
qt_objcDynamicSuper();
}
#pragma clang diagnostic pop
@@ -263,29 +262,20 @@ static bool isMouseEvent(NSEvent *ev)
NSEnumerator<NSWindow*> *windowEnumerator = nullptr;
NSApplication *application = [NSApplication sharedApplication];
-#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12)
- if (__builtin_available(macOS 10.12, *)) {
- // Unfortunately there's no NSWindowListOrderedBackToFront,
- // so we have to manually reverse the order using an array.
- NSMutableArray *windows = [[[NSMutableArray alloc] init] autorelease];
- [application enumerateWindowsWithOptions:NSWindowListOrderedFrontToBack
- usingBlock:^(NSWindow *window, BOOL *) {
- // For some reason AppKit will give us nil-windows, skip those
- if (!window)
- return;
-
- [(NSMutableArray*)windows addObject:window];
- }
- ];
-
- windowEnumerator = windows.reverseObjectEnumerator;
- } else
-#endif
- {
- // No way to get ordered list of windows, so fall back to unordered,
- // list, which typically corresponds to window creation order.
- windowEnumerator = application.windows.objectEnumerator;
- }
+ // Unfortunately there's no NSWindowListOrderedBackToFront,
+ // so we have to manually reverse the order using an array.
+ NSMutableArray<NSWindow *> *windows = [NSMutableArray<NSWindow *> new];
+ [application enumerateWindowsWithOptions:NSWindowListOrderedFrontToBack
+ usingBlock:^(NSWindow *window, BOOL *) {
+ // For some reason AppKit will give us nil-windows, skip those
+ if (!window)
+ return;
+
+ [windows addObject:window];
+ }
+ ];
+
+ windowEnumerator = windows.reverseObjectEnumerator;
for (NSWindow *window in windowEnumerator) {
// We're meddling with normal and floating windows, so leave others alone
diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.h b/src/plugins/platforms/cocoa/qnswindowdelegate.h
index d2078b5786..e71afcbb2a 100644
--- a/src/plugins/platforms/cocoa/qnswindowdelegate.h
+++ b/src/plugins/platforms/cocoa/qnswindowdelegate.h
@@ -41,20 +41,16 @@
#define QNSWINDOWDELEGATE_H
#include <AppKit/AppKit.h>
+#include <QtCore/private/qcore_mac_p.h>
-#include "qcocoawindow.h"
+QT_BEGIN_NAMESPACE
+class QCocoaWindow;
+QT_END_NAMESPACE
@interface QT_MANGLE_NAMESPACE(QNSWindowDelegate) : NSObject <NSWindowDelegate>
-{
- QCocoaWindow *m_cocoaWindow;
-}
-- (id)initWithQCocoaWindow:(QCocoaWindow *)cocoaWindow;
+- (instancetype)initWithQCocoaWindow:(QT_PREPEND_NAMESPACE(QCocoaWindow) *)cocoaWindow;
-- (BOOL)windowShouldClose:(NSNotification *)notification;
-
-- (BOOL)window:(NSWindow *)window shouldPopUpDocumentPathMenu:(NSMenu *)menu;
-- (BOOL)window:(NSWindow *)window shouldDragDocumentWithEvent:(NSEvent *)event from:(NSPoint)dragImageLocation withPasteboard:(NSPasteboard *)pasteboard;
@end
QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSWindowDelegate);
diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.mm b/src/plugins/platforms/cocoa/qnswindowdelegate.mm
index 057a4c2943..97309ea990 100644
--- a/src/plugins/platforms/cocoa/qnswindowdelegate.mm
+++ b/src/plugins/platforms/cocoa/qnswindowdelegate.mm
@@ -39,21 +39,24 @@
#include "qnswindowdelegate.h"
#include "qcocoahelpers.h"
+#include "qcocoawindow.h"
#include "qcocoascreen.h"
#include <QDebug>
+#include <QtCore/private/qcore_mac_p.h>
#include <qpa/qplatformscreen.h>
#include <qpa/qwindowsysteminterface.h>
static QRegExp whitespaceRegex = QRegExp(QStringLiteral("\\s*"));
-@implementation QNSWindowDelegate
+@implementation QNSWindowDelegate {
+ QCocoaWindow *m_cocoaWindow;
+}
-- (id)initWithQCocoaWindow:(QCocoaWindow *)cocoaWindow
+- (instancetype)initWithQCocoaWindow:(QCocoaWindow *)cocoaWindow
{
- if (self = [super init])
+ if ((self = [self init]))
m_cocoaWindow = cocoaWindow;
-
return self;
}
@@ -103,6 +106,36 @@ static QRegExp whitespaceRegex = QRegExp(QStringLiteral("\\s*"));
return QCocoaScreen::mapToNative(maximizedFrame);
}
+#pragma clang diagnostic push
+// NSDisableScreenUpdates and NSEnableScreenUpdates are deprecated, but the
+// NSAnimationContext API that replaces them doesn't handle the use-case of
+// cross-thread screen update synchronization.
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+- (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)frameSize
+{
+ qCDebug(lcQpaWindow) << window << "will resize to" << QSizeF::fromCGSize(frameSize)
+ << "- disabling screen updates temporarily";
+
+ // There may be separate threads rendering to CA layers in this window,
+ // and if any of them do a swap while the resize is still in progress,
+ // the visual bounds of that layer will be updated before the visual
+ // bounds of the window frame, resulting in flickering while resizing.
+
+ // To prevent this we disable screen updates for the whole process until
+ // the resize is complete, which makes the whole thing visually atomic.
+ NSDisableScreenUpdates();
+
+ return frameSize;
+}
+
+- (void)windowDidResize:(NSNotification *)notification
+{
+ NSWindow *window = notification.object;
+ qCDebug(lcQpaWindow) << window << "was resized - re-enabling screen updates";
+ NSEnableScreenUpdates();
+}
+#pragma clang diagnostic pop
+
- (BOOL)window:(NSWindow *)window shouldPopUpDocumentPathMenu:(NSMenu *)menu
{
Q_UNUSED(window);
diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm
index 3f363b62d5..96506c67fa 100644
--- a/src/plugins/platforms/cocoa/qpaintengine_mac.mm
+++ b/src/plugins/platforms/cocoa/qpaintengine_mac.mm
@@ -98,8 +98,8 @@ CGImageRef qt_mac_create_imagemask(const QPixmap &pixmap, const QRectF &sr)
for (int x = sx; x < sw; ++x)
*(dptr+(offset++)) = (*(srow+x) & mask) ? 255 : 0;
}
- QCFType<CGDataProviderRef> provider = CGDataProviderCreateWithData(0, dptr, nbytes, qt_mac_cgimage_data_free);
- return CGImageMaskCreate(sw, sh, 8, 8, nbytes / sh, provider, 0, 0);
+ QCFType<CGDataProviderRef> provider = CGDataProviderCreateWithData(nullptr, dptr, nbytes, qt_mac_cgimage_data_free);
+ return CGImageMaskCreate(sw, sh, 8, 8, nbytes / sh, provider, nullptr, false);
}
//conversion
@@ -287,16 +287,16 @@ static void qt_mac_draw_pattern(void *info, CGContextRef c)
Q_ASSERT(pat->data.bytes);
w = h = 8;
#if (QMACPATTERN_MASK_MULTIPLIER == 1)
- CGDataProviderRef provider = CGDataProviderCreateWithData(0, pat->data.bytes, w*h, 0);
- pat->image = CGImageMaskCreate(w, h, 1, 1, 1, provider, 0, false);
+ CGDataProviderRef provider = CGDataProviderCreateWithData(nullptr, pat->data.bytes, w*h, nullptr);
+ pat->image = CGImageMaskCreate(w, h, 1, 1, 1, provider, nullptr, false);
CGDataProviderRelease(provider);
#else
const int numBytes = (w*h)/sizeof(uchar);
uchar xor_bytes[numBytes];
for (int i = 0; i < numBytes; ++i)
xor_bytes[i] = pat->data.bytes[i] ^ 0xFF;
- CGDataProviderRef provider = CGDataProviderCreateWithData(0, xor_bytes, w*h, 0);
- CGImageRef swatch = CGImageMaskCreate(w, h, 1, 1, 1, provider, 0, false);
+ CGDataProviderRef provider = CGDataProviderCreateWithData(nullptr, xor_bytes, w*h, nullptr);
+ CGImageRef swatch = CGImageMaskCreate(w, h, 1, 1, 1, provider, nullptr, false);
CGDataProviderRelease(provider);
const QColor c0(0, 0, 0, 0), c1(255, 255, 255, 255);
@@ -399,9 +399,9 @@ QCoreGraphicsPaintEngine::begin(QPaintDevice *pdev)
d->orig_xform = CGContextGetCTM(d->hd);
if (d->shading) {
CGShadingRelease(d->shading);
- d->shading = 0;
+ d->shading = nullptr;
}
- d->setClip(0); //clear the context's clipping
+ d->setClip(nullptr); //clear the context's clipping
}
setActive(true);
@@ -445,12 +445,12 @@ QCoreGraphicsPaintEngine::end()
CGShadingRelease(d->shading);
d->shading = 0;
}
- d->pdev = 0;
+ d->pdev = nullptr;
if (d->hd) {
d->restoreGraphicsState();
CGContextSynchronize(d->hd);
CGContextRelease(d->hd);
- d->hd = 0;
+ d->hd = nullptr;
}
return true;
}
@@ -545,7 +545,7 @@ QCoreGraphicsPaintEngine::updateBrush(const QBrush &brush, const QPointF &brushO
if (d->shading) {
CGShadingRelease(d->shading);
- d->shading = 0;
+ d->shading = nullptr;
}
d->setFillBrush(brushOrigin);
}
@@ -592,7 +592,7 @@ QCoreGraphicsPaintEngine::updateClipPath(const QPainterPath &p, Qt::ClipOperatio
if (d->current.clipEnabled) {
d->current.clipEnabled = false;
d->current.clip = QRegion();
- d->setClip(0);
+ d->setClip(nullptr);
}
} else {
if (!d->current.clipEnabled)
@@ -601,7 +601,7 @@ QCoreGraphicsPaintEngine::updateClipPath(const QPainterPath &p, Qt::ClipOperatio
QRegion clipRegion(p.toFillPolygon().toPolygon(), p.fillRule());
if (op == Qt::ReplaceClip) {
d->current.clip = clipRegion;
- d->setClip(0);
+ d->setClip(nullptr);
if (p.isEmpty()) {
CGRect rect = CGRectMake(0, 0, 0, 0);
CGContextClipToRect(d->hd, rect);
@@ -630,7 +630,7 @@ QCoreGraphicsPaintEngine::updateClipRegion(const QRegion &clipRegion, Qt::ClipOp
if (op == Qt::NoClip) {
d->current.clipEnabled = false;
d->current.clip = QRegion();
- d->setClip(0);
+ d->setClip(nullptr);
} else {
if (!d->current.clipEnabled)
op = Qt::ReplaceClip;
@@ -676,7 +676,7 @@ QCoreGraphicsPaintEngine::drawRects(const QRectF *rects, int rectCount)
QRectF r = rects[i];
CGMutablePathRef path = CGPathCreateMutable();
- CGPathAddRect(path, 0, qt_mac_compose_rect(r));
+ CGPathAddRect(path, nullptr, qt_mac_compose_rect(r));
d->drawPath(QCoreGraphicsPaintEnginePrivate::CGFill|QCoreGraphicsPaintEnginePrivate::CGStroke,
path);
CGPathRelease(path);
@@ -698,8 +698,8 @@ QCoreGraphicsPaintEngine::drawPoints(const QPointF *points, int pointCount)
CGMutablePathRef path = CGPathCreateMutable();
for (int i=0; i < pointCount; i++) {
float x = points[i].x(), y = points[i].y();
- CGPathMoveToPoint(path, 0, x, y);
- CGPathAddLineToPoint(path, 0, x+0.001, y);
+ CGPathMoveToPoint(path, nullptr, x, y);
+ CGPathAddLineToPoint(path, nullptr, x+0.001, y);
}
bool doRestore = false;
@@ -745,11 +745,11 @@ QCoreGraphicsPaintEngine::drawPolygon(const QPointF *points, int pointCount, Pol
return;
CGMutablePathRef path = CGPathCreateMutable();
- CGPathMoveToPoint(path, 0, points[0].x(), points[0].y());
+ CGPathMoveToPoint(path, nullptr, points[0].x(), points[0].y());
for (int x = 1; x < pointCount; ++x)
- CGPathAddLineToPoint(path, 0, points[x].x(), points[x].y());
+ CGPathAddLineToPoint(path, nullptr, points[x].x(), points[x].y());
if (mode != PolylineMode && points[0] != points[pointCount-1])
- CGPathAddLineToPoint(path, 0, points[0].x(), points[0].y());
+ CGPathAddLineToPoint(path, nullptr, points[0].x(), points[0].y());
uint op = QCoreGraphicsPaintEnginePrivate::CGStroke;
if (mode != PolylineMode)
op |= mode == OddEvenMode ? QCoreGraphicsPaintEnginePrivate::CGEOFill
@@ -770,8 +770,8 @@ QCoreGraphicsPaintEngine::drawLines(const QLineF *lines, int lineCount)
CGMutablePathRef path = CGPathCreateMutable();
for (int i = 0; i < lineCount; i++) {
const QPointF start = lines[i].p1(), end = lines[i].p2();
- CGPathMoveToPoint(path, 0, start.x(), start.y());
- CGPathAddLineToPoint(path, 0, end.x(), end.y());
+ CGPathMoveToPoint(path, nullptr, start.x(), start.y());
+ CGPathAddLineToPoint(path, nullptr, end.x(), end.y());
}
d->drawPath(QCoreGraphicsPaintEnginePrivate::CGStroke, path);
CGPathRelease(path);
@@ -870,7 +870,7 @@ QCoreGraphicsPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap
CGPatternRef pat = CGPatternCreate(qpattern, CGRectMake(0, 0, width, height),
trans, width, height,
kCGPatternTilingNoDistortion, true, &callbks);
- CGColorSpaceRef cs = CGColorSpaceCreatePattern(0);
+ CGColorSpaceRef cs = CGColorSpaceCreatePattern(nullptr);
CGContextSetFillColorSpace(d->hd, cs);
CGFloat component = 1.0; //just one
CGContextSetFillPattern(d->hd, pat, &component);
@@ -1198,9 +1198,9 @@ void QCoreGraphicsPaintEnginePrivate::setFillBrush(const QPointF &offset)
Q_ASSERT(grad->spread() == QGradient::PadSpread);
static const CGFloat domain[] = { 0.0f, +1.0f };
- static const CGFunctionCallbacks callbacks = { 0, qt_mac_color_gradient_function, 0 };
+ static const CGFunctionCallbacks callbacks = { 0, qt_mac_color_gradient_function, nullptr };
CGFunctionRef fill_func = CGFunctionCreate(reinterpret_cast<void *>(&current.brush),
- 1, domain, 4, 0, &callbacks);
+ 1, domain, 4, nullptr, &callbacks);
CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB)
if (bs == Qt::LinearGradientPattern) {
@@ -1233,7 +1233,7 @@ void QCoreGraphicsPaintEnginePrivate::setFillBrush(const QPointF &offset)
QMacPattern *qpattern = new QMacPattern;
qpattern->pdev = pdev;
CGFloat components[4] = { 1.0, 1.0, 1.0, 1.0 };
- CGColorSpaceRef base_colorspace = 0;
+ CGColorSpaceRef base_colorspace = nullptr;
if (bs == Qt::TexturePattern) {
qpattern->data.pixmap = current.brush.texture();
if (qpattern->data.pixmap.isQBitmap()) {
@@ -1291,7 +1291,7 @@ QCoreGraphicsPaintEnginePrivate::setClip(const QRegion *rgn)
if (!sysClip.isEmpty())
qt_mac_clip_cg(hd, sysClip, &orig_xform);
if (rgn)
- qt_mac_clip_cg(hd, *rgn, 0);
+ qt_mac_clip_cg(hd, *rgn, nullptr);
}
}
@@ -1404,7 +1404,7 @@ void QCoreGraphicsPaintEnginePrivate::drawPath(uchar ops, CGMutablePathRef path)
t.transform = qt_mac_convert_transform_to_cg(current.transform);
t.path = CGPathCreateMutable();
CGPathApply(path, &t, qt_mac_cg_transform_path_apply); //transform the path
- setTransform(0); //unset the context transform
+ setTransform(nullptr); //unset the context transform
CGContextSetLineWidth(hd, cosmeticPenSize);
CGContextAddPath(hd, t.path);
CGPathRelease(t.path);
diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac_p.h b/src/plugins/platforms/cocoa/qpaintengine_mac_p.h
index c9519ac827..1416386745 100644
--- a/src/plugins/platforms/cocoa/qpaintengine_mac_p.h
+++ b/src/plugins/platforms/cocoa/qpaintengine_mac_p.h
@@ -135,7 +135,7 @@ class QCoreGraphicsPaintEnginePrivate : public QPaintEnginePrivate
Q_DECLARE_PUBLIC(QCoreGraphicsPaintEngine)
public:
QCoreGraphicsPaintEnginePrivate()
- : hd(0), shading(0), stackCount(0), complexXForm(false), disabledSmoothFonts(false)
+ : hd(nullptr), shading(nullptr), stackCount(0), complexXForm(false), disabledSmoothFonts(false)
{
}
@@ -164,8 +164,8 @@ public:
//internal functions
enum { CGStroke=0x01, CGEOFill=0x02, CGFill=0x04 };
- void drawPath(uchar ops, CGMutablePathRef path = 0);
- void setClip(const QRegion *rgn=0);
+ void drawPath(uchar ops, CGMutablePathRef path = nullptr);
+ void setClip(const QRegion *rgn = nullptr);
void resetClip();
void setFillBrush(const QPointF &origin=QPoint());
void setStrokePen(const QPen &pen);
@@ -174,7 +174,7 @@ public:
float penOffset();
QPointF devicePixelSize(CGContextRef context);
float adjustPenWidth(float penWidth);
- inline void setTransform(const QTransform *matrix=0)
+ inline void setTransform(const QTransform *matrix = nullptr)
{
CGContextConcatCTM(hd, CGAffineTransformInvert(CGContextGetCTM(hd)));
CGAffineTransform xform = orig_xform;
diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm
index eade407500..f2f29b26ee 100644
--- a/src/plugins/platforms/cocoa/qprintengine_mac.mm
+++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm
@@ -117,7 +117,7 @@ bool QMacPrintEngine::end()
if (d->paintEngine->type() == QPaintEngine::CoreGraphics) {
// We don't need the paint engine to call restoreGraphicsState()
static_cast<QCoreGraphicsPaintEngine*>(d->paintEngine)->d_func()->stackCount = 0;
- static_cast<QCoreGraphicsPaintEngine*>(d->paintEngine)->d_func()->hd = 0;
+ static_cast<QCoreGraphicsPaintEngine*>(d->paintEngine)->d_func()->hd = nullptr;
}
d->paintEngine->end();
if (d->state != QPrinter::Idle)
@@ -271,7 +271,7 @@ void QMacPrintEnginePrivate::releaseSession()
PMSessionEndPageNoDialog(session());
PMSessionEndDocumentNoDialog(session());
[printInfo release];
- printInfo = 0;
+ printInfo = nil;
}
bool QMacPrintEnginePrivate::newPage_helper()
@@ -291,7 +291,7 @@ bool QMacPrintEnginePrivate::newPage_helper()
while (cgEngine->d_func()->stackCount > 0)
cgEngine->d_func()->restoreGraphicsState();
- OSStatus status = PMSessionBeginPageNoDialog(session(), format(), 0);
+ OSStatus status = PMSessionBeginPageNoDialog(session(), format(), nullptr);
if (status != noErr) {
state = QPrinter::Error;
return false;
@@ -318,7 +318,7 @@ bool QMacPrintEnginePrivate::newPage_helper()
if (m_pageLayout.mode() != QPageLayout::FullPageMode)
CGContextTranslateCTM(cgContext, page.x() - paper.x(), page.y() - paper.y());
cgEngine->d_func()->orig_xform = CGContextGetCTM(cgContext);
- cgEngine->d_func()->setClip(0);
+ cgEngine->d_func()->setClip(nullptr);
cgEngine->state->dirtyFlags = QPaintEngine::DirtyFlag(QPaintEngine::AllDirty
& ~(QPaintEngine::DirtyClipEnabled
| QPaintEngine::DirtyClipRegion
@@ -340,7 +340,7 @@ void QMacPrintEnginePrivate::setPageSize(const QPageSize &pageSize)
// Get the PMPaper and check it is valid
PMPaper macPaper = m_printDevice->macPaper(usePageSize);
- if (macPaper == 0) {
+ if (!macPaper) {
qWarning() << "QMacPrintEngine: Invalid PMPaper returned for " << pageSize;
return;
}
diff --git a/src/plugins/platforms/cocoa/qprintengine_mac_p.h b/src/plugins/platforms/cocoa/qprintengine_mac_p.h
index 9514f3e691..3d94227ae4 100644
--- a/src/plugins/platforms/cocoa/qprintengine_mac_p.h
+++ b/src/plugins/platforms/cocoa/qprintengine_mac_p.h
@@ -134,7 +134,7 @@ public:
QMacPrintEnginePrivate() : mode(QPrinter::ScreenResolution), state(QPrinter::Idle),
m_pageLayout(QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0, 0, 0, 0))),
- printInfo(0), paintEngine(0), embedFonts(true) {}
+ printInfo(nullptr), paintEngine(nullptr), embedFonts(true) {}
~QMacPrintEnginePrivate();
void initialize();
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp
index 38f2352934..9689d6a89b 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp
@@ -48,9 +48,9 @@
#include "qwindowscontext.h"
-#include <QtGui/QPainter>
-#include <QtGui/QWindow>
-#include <QtCore/QDebug>
+#include <QtGui/qpainter.h>
+#include <QtGui/qwindow.h>
+#include <QtCore/qdebug.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.cpp
index 38425f8fa1..2151f3ae95 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.cpp
@@ -42,8 +42,8 @@
#include "qwindowsdirect2dhelpers.h"
#include "qwindowsdirect2ddevicecontext.h"
-#include <QtGui/QImage>
-#include <QtGui/QColor>
+#include <QtGui/qimage.h>
+#include <QtGui/qcolor.h>
#include <wrl.h>
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.h b/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.h
index ef39b6a661..d8a8a49aec 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.h
@@ -41,8 +41,8 @@
#define QWINDOWSDIRECT2DBITMAP_H
#include <QtCore/qnamespace.h>
-#include <QtCore/QRect>
-#include <QtCore/QScopedPointer>
+#include <QtCore/qrect.h>
+#include <QtCore/qscopedpointer.h>
struct ID2D1DeviceContext;
struct ID2D1Bitmap1;
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.h b/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.h
index 0d42c65964..5bce056ad1 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.h
@@ -40,7 +40,7 @@
#ifndef QWINDOWSDIRECT2DCONTEXT_H
#define QWINDOWSDIRECT2DCONTEXT_H
-#include <QtCore/QScopedPointer>
+#include <QtCore/qscopedpointer.h>
struct ID3D11Device;
struct ID2D1Device;
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.h b/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.h
index 8544f9448b..aee0eb867d 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.h
@@ -40,7 +40,7 @@
#ifndef QWINDOWSDIRECT2DDEVICECONTEXT_H
#define QWINDOWSDIRECT2DDEVICECONTEXT_H
-#include <QtCore/QScopedPointer>
+#include <QtCore/qscopedpointer.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dhelpers.h b/src/plugins/platforms/direct2d/qwindowsdirect2dhelpers.h
index 34225bba9a..babe646fd8 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dhelpers.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dhelpers.h
@@ -40,11 +40,11 @@
#ifndef QWINDOWSDIRECT2DHELPERS_H
#define QWINDOWSDIRECT2DHELPERS_H
-#include <QtCore/QRectF>
-#include <QtCore/QSizeF>
-#include <QtCore/QPointF>
-#include <QtGui/QColor>
-#include <QtGui/QTransform>
+#include <QtCore/qrect.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qpoint.h>
+#include <QtGui/qcolor.h>
+#include <QtGui/qtransform.h>
#ifdef Q_CC_MINGW
# include <qt_windows.h>
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp
index 6d98da5be5..173d79cf2b 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp
@@ -47,8 +47,8 @@
#include "qwindowscontext.h"
#include <qplatformdefs.h>
-#include <QtCore/QCoreApplication>
-#include <QtCore/QVersionNumber>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qversionnumber.h>
#include <QtGui/private/qpixmap_raster_p.h>
#include <QtGui/qpa/qwindowsysteminterface.h>
#include <QtEventDispatcherSupport/private/qwindowsguieventdispatcher_p.h>
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h
index 39ca1d0dbf..19c7521eb7 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h
@@ -42,7 +42,7 @@
#include "qwindowsintegration.h"
-#include <QtCore/QScopedPointer>
+#include <QtCore/qscopedpointer.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dnativeinterface.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dnativeinterface.cpp
index 711366a0b5..f763c4f7ab 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dnativeinterface.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dnativeinterface.cpp
@@ -39,7 +39,7 @@
#include "qwindowsdirect2dnativeinterface.h"
-#include <QtGui/QBackingStore>
+#include <QtGui/qbackingstore.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h
index 1f23d604f5..013d7a9b79 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintdevice.h
@@ -40,8 +40,8 @@
#ifndef QWINDOWSDIRECT2DPAINTDEVICE_H
#define QWINDOWSDIRECT2DPAINTDEVICE_H
-#include <QtCore/QScopedPointer>
-#include <QtGui/QPaintDevice>
+#include <QtCore/qscopedpointer.h>
+#include <QtGui/qpaintdevice.h>
#include "qwindowsdirect2dpaintengine.h"
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
index 95fbd37247..d3e1d4dd12 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
@@ -49,9 +49,9 @@
#include <QtFontDatabaseSupport/private/qwindowsfontengine_p.h>
#include "qwindowsintegration.h"
-#include <QtCore/QtMath>
-#include <QtCore/QStack>
-#include <QtCore/QSettings>
+#include <QtCore/qmath.h>
+#include <QtCore/qstack.h>
+#include <QtCore/qsettings.h>
#include <QtGui/private/qpaintengine_p.h>
#include <QtGui/private/qtextengine_p.h>
#include <QtGui/private/qfontengine_p.h>
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h
index b9616acd6a..6404c60b13 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h
@@ -40,7 +40,7 @@
#ifndef QWINDOWSDIRECT2DPAINTENGINE_H
#define QWINDOWSDIRECT2DPAINTENGINE_H
-#include <QtCore/QScopedPointer>
+#include <QtCore/qscopedpointer.h>
#include <QtGui/private/qpaintengineex_p.h>
struct ID2D1Geometry;
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp
index 65e056d312..fb50e05b3f 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.cpp
@@ -43,10 +43,10 @@
#include "qwindowsdirect2dbitmap.h"
#include "qwindowsdirect2dhelpers.h"
-#include <QtGui/QPainter>
-#include <QtGui/QImage>
-#include <QtGui/QPaintDevice>
-#include <QtGui/QPaintEngine>
+#include <QtGui/qpainter.h>
+#include <QtGui/qimage.h>
+#include <QtGui/qpaintdevice.h>
+#include <QtGui/qpaintengine.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h
index 0448613a95..6bd7852ae0 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h
@@ -42,7 +42,7 @@
#include "qwindowsdirect2dpaintengine.h"
#include <QtGui/qpa/qplatformpixmap.h>
-#include <QtCore/QScopedPointer>
+#include <QtCore/qscopedpointer.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformplugin.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformplugin.cpp
index 7393c11dda..6c56d356b7 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformplugin.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformplugin.cpp
@@ -40,7 +40,7 @@
#include "qwindowsdirect2dintegration.h"
#include <QtGui/qpa/qplatformintegrationplugin.h>
-#include <QtCore/QStringList>
+#include <QtCore/qstringlist.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/api/qeglfshooks.cpp b/src/plugins/platforms/eglfs/api/qeglfshooks.cpp
index d8332a94cb..ff5c5deee4 100644
--- a/src/plugins/platforms/eglfs/api/qeglfshooks.cpp
+++ b/src/plugins/platforms/eglfs/api/qeglfshooks.cpp
@@ -54,6 +54,7 @@ QEglFSDeviceIntegration *qt_egl_device_integration()
#else
+namespace {
class DeviceIntegration
{
public:
@@ -63,6 +64,7 @@ public:
private:
QEglFSDeviceIntegration *m_integration;
};
+}
Q_GLOBAL_STATIC(DeviceIntegration, deviceIntegration)
diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
index 33878a5f50..43f2e31a49 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
+++ b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
@@ -415,8 +415,7 @@ static void *eglContextForContext(QOpenGLContext *context)
QPlatformNativeInterface::NativeResourceForContextFunction QEglFSIntegration::nativeResourceFunctionForContext(const QByteArray &resource)
{
#ifndef QT_NO_OPENGL
- QByteArray lowerCaseResource = resource.toLower();
- if (lowerCaseResource == "get_egl_context")
+ if (resource.compare("get_egl_context", Qt::CaseInsensitive) == 0)
return NativeResourceForContextFunction(eglContextForContext);
#else
Q_UNUSED(resource);
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.pro
index fee67da2de..aa487be8c0 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.pro
@@ -6,7 +6,6 @@ INCLUDEPATH += $$PWD/../../api
CONFIG += egl
LIBS += -lbcm_host
-QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
# Avoid X11 header collision, use generic EGL native types
DEFINES += QT_EGL_NO_X11
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro
index 43170a3875..f5c2c0ed89 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro
@@ -13,7 +13,6 @@ DEFINES += QT_EGL_NO_X11
QMAKE_USE += gbm drm
CONFIG += egl
-QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
SOURCES += $$PWD/qeglfskmsgbmmain.cpp \
$$PWD/qeglfskmsgbmintegration.cpp \
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
index 1b52bdf3ec..24f82e7843 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
@@ -47,6 +47,7 @@
#include <QtCore/QLoggingCategory>
#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/private/qtguiglobal_p.h>
#include <QtFbSupport/private/qfbvthandler_p.h>
#include <errno.h>
@@ -226,17 +227,29 @@ void QEglFSKmsGbmScreen::ensureModeSet(uint32_t fb)
if (doModeSet) {
qCDebug(qLcEglfsKmsDebug, "Setting mode for screen %s", qPrintable(name()));
- int ret = drmModeSetCrtc(fd,
- op.crtc_id,
- fb,
- 0, 0,
- &op.connector_id, 1,
- &op.modes[op.mode]);
-
- if (ret == 0)
- setPowerState(PowerStateOn);
- else
- qErrnoWarning(errno, "Could not set DRM mode for screen %s", qPrintable(name()));
+
+ if (device()->hasAtomicSupport()) {
+#if QT_CONFIG(drm_atomic)
+ drmModeAtomicReq *request = device()->atomic_request();
+ if (request) {
+ drmModeAtomicAddProperty(request, op.connector_id, op.crtcIdPropertyId, op.crtc_id);
+ drmModeAtomicAddProperty(request, op.crtc_id, op.modeIdPropertyId, op.mode_blob_id);
+ drmModeAtomicAddProperty(request, op.crtc_id, op.activePropertyId, 1);
+ }
+#endif
+ } else {
+ int ret = drmModeSetCrtc(fd,
+ op.crtc_id,
+ fb,
+ 0, 0,
+ &op.connector_id, 1,
+ &op.modes[op.mode]);
+
+ if (ret == 0)
+ setPowerState(PowerStateOn);
+ else
+ qErrnoWarning(errno, "Could not set DRM mode for screen %s", qPrintable(name()));
+ }
}
}
}
@@ -259,6 +272,11 @@ void QEglFSKmsGbmScreen::waitForFlip()
drmEvent.page_flip_handler = pageFlipHandler;
drmHandleEvent(device()->fd(), &drmEvent);
}
+
+#if QT_CONFIG(drm_atomic)
+ if (device()->hasAtomicSupport())
+ device()->atomicReset();
+#endif
}
void QEglFSKmsGbmScreen::flip()
@@ -290,34 +308,79 @@ void QEglFSKmsGbmScreen::flip()
QKmsOutput &op(output());
const int fd = device()->fd();
m_flipPending = true;
- int ret = drmModePageFlip(fd,
+
+ if (device()->hasAtomicSupport()) {
+#if QT_CONFIG(drm_atomic)
+ drmModeAtomicReq *request = device()->atomic_request();
+ if (request) {
+ drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->framebufferPropertyId, fb->fb);
+ drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->crtcPropertyId, op.crtc_id);
+ drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->srcwidthPropertyId,
+ output().size.width() << 16);
+ drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->srcXPropertyId, 0);
+ drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->srcYPropertyId, 0);
+ drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->srcheightPropertyId,
+ output().size.height() << 16);
+ drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->crtcXPropertyId, 0);
+ drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->crtcYPropertyId, 0);
+ drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->crtcwidthPropertyId,
+ m_output.modes[m_output.mode].hdisplay);
+ drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->crtcheightPropertyId,
+ m_output.modes[m_output.mode].vdisplay);
+
+ static int zpos = qEnvironmentVariableIntValue("QT_QPA_EGLFS_KMS_ZPOS");
+ if (zpos)
+ drmModeAtomicAddProperty(request, op.eglfs_plane->id, op.eglfs_plane->zposPropertyId, zpos);
+ }
+#endif
+ } else {
+ int ret = drmModePageFlip(fd,
op.crtc_id,
fb->fb,
DRM_MODE_PAGE_FLIP_EVENT,
this);
- if (ret) {
- qErrnoWarning("Could not queue DRM page flip on screen %s", qPrintable(name()));
- m_flipPending = false;
- gbm_surface_release_buffer(m_gbm_surface, m_gbm_bo_next);
- m_gbm_bo_next = nullptr;
- return;
+ if (ret) {
+ qErrnoWarning("Could not queue DRM page flip on screen %s", qPrintable(name()));
+ m_flipPending = false;
+ gbm_surface_release_buffer(m_gbm_surface, m_gbm_bo_next);
+ m_gbm_bo_next = nullptr;
+ return;
+ }
}
for (CloneDestination &d : m_cloneDests) {
if (d.screen != this) {
d.screen->ensureModeSet(fb->fb);
d.cloneFlipPending = true;
- int ret = drmModePageFlip(fd,
- d.screen->output().crtc_id,
- fb->fb,
- DRM_MODE_PAGE_FLIP_EVENT,
- d.screen);
- if (ret) {
- qErrnoWarning("Could not queue DRM page flip for clone screen %s", qPrintable(name()));
- d.cloneFlipPending = false;
+
+ if (device()->hasAtomicSupport()) {
+#if QT_CONFIG(drm_atomic)
+ drmModeAtomicReq *request = device()->atomic_request();
+ if (request) {
+ drmModeAtomicAddProperty(request, d.screen->output().eglfs_plane->id,
+ d.screen->output().eglfs_plane->framebufferPropertyId, fb->fb);
+ drmModeAtomicAddProperty(request, d.screen->output().eglfs_plane->id,
+ d.screen->output().eglfs_plane->crtcPropertyId, op.crtc_id);
+ }
+#endif
+ } else {
+ int ret = drmModePageFlip(fd,
+ d.screen->output().crtc_id,
+ fb->fb,
+ DRM_MODE_PAGE_FLIP_EVENT,
+ d.screen);
+ if (ret) {
+ qErrnoWarning("Could not queue DRM page flip for clone screen %s", qPrintable(name()));
+ d.cloneFlipPending = false;
+ }
}
}
}
+
+#if QT_CONFIG(drm_atomic)
+ if (device()->hasAtomicSupport())
+ device()->atomicCommit(this);
+#endif
}
void QEglFSKmsGbmScreen::pageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data)
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro
index 36f037ac6c..a6145c07e6 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro
@@ -9,7 +9,6 @@ DEFINES += QT_EGL_NO_X11
QMAKE_USE += drm
CONFIG += egl
-QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
SOURCES += $$PWD/qeglfskmsegldevicemain.cpp \
$$PWD/qeglfskmsegldeviceintegration.cpp \
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp
index 531b73d1dc..1626c86239 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp
@@ -112,7 +112,7 @@ void QEglFSKmsEglDeviceScreen::waitForFlip()
qCDebug(qLcEglfsKmsDebug, "Setting plane %u", op.forced_plane_id);
int ret = drmModeSetPlane(fd, op.forced_plane_id, op.crtc_id, uint32_t(-1), 0,
0, 0, w, h,
- 0 << 16, 0 << 16, w << 16, h << 16);
+ 0 << 16, 0 << 16, op.size.width() << 16, op.size.height() << 16);
if (ret == -1)
qErrnoWarning(errno, "drmModeSetPlane failed");
}
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro
index 4d1321079c..40806b6a9b 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro
@@ -11,7 +11,6 @@ DEFINES += QT_EGL_NO_X11
QMAKE_USE += drm
CONFIG += egl
-QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
SOURCES += $$PWD/qeglfskmsintegration.cpp \
$$PWD/qeglfskmsdevice.cpp \
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp
index 06bc272050..a6aac61506 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp
@@ -138,6 +138,10 @@ void *QEglFSKmsIntegration::nativeResourceForIntegration(const QByteArray &name)
if (name == QByteArrayLiteral("dri_fd") && m_device)
return (void *) (qintptr) m_device->fd();
+#if QT_CONFIG(drm_atomic)
+ if (name == QByteArrayLiteral("dri_atomic_request") && m_device)
+ return (void *) (qintptr) m_device->atomic_request();
+#endif
return nullptr;
}
@@ -147,6 +151,8 @@ void *QEglFSKmsIntegration::nativeResourceForScreen(const QByteArray &resource,
if (s) {
if (resource == QByteArrayLiteral("dri_crtcid"))
return (void *) (qintptr) s->output().crtc_id;
+ if (resource == QByteArrayLiteral("dri_connectorid"))
+ return (void *) (qintptr) s->output().connector_id;
}
return nullptr;
}
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
index 5e45b42abe..e5354d97bd 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
@@ -113,10 +113,9 @@ QRect QEglFSKmsScreen::rawGeometry() const
if (m_headless)
return QRect(QPoint(0, 0), m_device->screenConfig()->headlessSize());
- const int mode = m_output.mode;
return QRect(m_pos.x(), m_pos.y(),
- m_output.modes[mode].hdisplay,
- m_output.modes[mode].vdisplay);
+ m_output.size.width(),
+ m_output.size.height());
}
int QEglFSKmsScreen::depth() const
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/eglfs_kms_vsp2.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/eglfs_kms_vsp2.pro
index 826c2f989f..f63b768a38 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/eglfs_kms_vsp2.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/eglfs_kms_vsp2.pro
@@ -13,7 +13,6 @@ DEFINES += QT_EGL_NO_X11
QMAKE_USE += gbm drm v4l2
CONFIG += egl
-QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
SOURCES += $$PWD/qeglfskmsvsp2main.cpp \
$$PWD/qeglfskmsvsp2integration.cpp \
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/eglfs_mali.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/eglfs_mali.pro
index 5e6f636e2b..3261a6dbba 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/eglfs_mali.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/eglfs_mali.pro
@@ -7,7 +7,6 @@ DEFINES += QT_EGL_NO_X11
INCLUDEPATH += $$PWD/../../api
CONFIG += egl
-QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
SOURCES += $$PWD/qeglfsmalimain.cpp \
$$PWD/qeglfsmaliintegration.cpp
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/eglfs_rcar.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/eglfs_rcar.pro
index 04236449a0..62acd51cea 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/eglfs_rcar.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/eglfs_rcar.pro
@@ -5,7 +5,6 @@ QT += core-private gui-private eglfsdeviceintegration-private
INCLUDEPATH += $$PWD/../../api
CONFIG += egl
DEFINES += LINUX=1 EGL_API_FB=1
-QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
SOURCES += $$PWD/qeglfsrcarmain.cpp \
$$PWD/qeglfsrcarintegration.cpp
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/eglfs_viv.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/eglfs_viv.pro
index f9cce8d48b..8d3be9c2ac 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/eglfs_viv.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/eglfs_viv.pro
@@ -5,7 +5,6 @@ QT += core-private gui-private eglfsdeviceintegration-private
INCLUDEPATH += $$PWD/../../api
CONFIG += egl
DEFINES += LINUX=1 EGL_API_FB=1
-QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
SOURCES += $$PWD/qeglfsvivmain.cpp \
$$PWD/qeglfsvivintegration.cpp
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/eglfs_viv_wl.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/eglfs_viv_wl.pro
index 065a103376..45d73e1eb8 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/eglfs_viv_wl.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv_wl/eglfs_viv_wl.pro
@@ -5,7 +5,6 @@ QT += core-private gui-private eglfsdeviceintegration-private
INCLUDEPATH += $$PWD/../../api
CONFIG += egl
DEFINES += LINUX=1 EGL_API_FB=1
-QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
SOURCES += $$PWD/qeglfsvivwlmain.cpp \
$$PWD/qeglfsvivwlintegration.cpp
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/eglfs_x11.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/eglfs_x11.pro
index 391f63615b..acbd1cc785 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/eglfs_x11.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/eglfs_x11.pro
@@ -9,7 +9,6 @@ INCLUDEPATH += $$PWD/../../api
CONFIG += egl
QMAKE_USE += xcb_xlib
-QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
SOURCES += $$PWD/qeglfsx11main.cpp \
$$PWD/qeglfsx11integration.cpp
diff --git a/src/plugins/platforms/eglfs/eglfsdeviceintegration.pro b/src/plugins/platforms/eglfs/eglfsdeviceintegration.pro
index 187cbc025f..8bb7b614f1 100644
--- a/src/plugins/platforms/eglfs/eglfsdeviceintegration.pro
+++ b/src/plugins/platforms/eglfs/eglfsdeviceintegration.pro
@@ -27,8 +27,6 @@ DEFINES += QT_BUILD_EGL_DEVICE_LIB
include($$PWD/api/api.pri)
-QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
-
!isEmpty(EGLFS_PLATFORM_HOOKS_SOURCES) {
HEADERS += $$EGLFS_PLATFORM_HOOKS_HEADERS
SOURCES += $$EGLFS_PLATFORM_HOOKS_SOURCES
diff --git a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosimagepickercontroller.h b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosimagepickercontroller.h
index c52d498cd4..201b277494 100644
--- a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosimagepickercontroller.h
+++ b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosimagepickercontroller.h
@@ -41,8 +41,6 @@
#include "../../qiosfiledialog.h"
-@interface QIOSImagePickerController : UIImagePickerController <UIImagePickerControllerDelegate, UINavigationControllerDelegate> {
- QIOSFileDialog *m_fileDialog;
-}
-- (id)initWithQIOSFileDialog:(QIOSFileDialog *)fileDialog;
+@interface QIOSImagePickerController : UIImagePickerController <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
+- (instancetype)initWithQIOSFileDialog:(QIOSFileDialog *)fileDialog;
@end
diff --git a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosimagepickercontroller.mm b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosimagepickercontroller.mm
index 78e0f00ab4..79d4ecf83f 100644
--- a/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosimagepickercontroller.mm
+++ b/src/plugins/platforms/ios/optional/nsphotolibrarysupport/qiosimagepickercontroller.mm
@@ -41,15 +41,17 @@
#include "qiosimagepickercontroller.h"
-@implementation QIOSImagePickerController
+@implementation QIOSImagePickerController {
+ QIOSFileDialog *m_fileDialog;
+}
-- (id)initWithQIOSFileDialog:(QIOSFileDialog *)fileDialog
+- (instancetype)initWithQIOSFileDialog:(QIOSFileDialog *)fileDialog
{
self = [super init];
if (self) {
m_fileDialog = fileDialog;
- [self setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
- [self setDelegate:self];
+ self.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
+ self.delegate = self;
}
return self;
}
@@ -57,8 +59,8 @@
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
Q_UNUSED(picker);
- NSURL *url = [info objectForKey:UIImagePickerControllerReferenceURL];
- QUrl fileUrl = QUrl::fromLocalFile(QString::fromNSString([url description]));
+ NSURL *url = info[UIImagePickerControllerReferenceURL];
+ QUrl fileUrl = QUrl::fromLocalFile(QString::fromNSString(url.description));
m_fileDialog->selectedFilesChanged(QList<QUrl>() << fileUrl);
emit m_fileDialog->accept();
}
diff --git a/src/plugins/platforms/ios/qiosclipboard.mm b/src/plugins/platforms/ios/qiosclipboard.mm
index 9a975eadc9..6bdbf94d3f 100644
--- a/src/plugins/platforms/ios/qiosclipboard.mm
+++ b/src/plugins/platforms/ios/qiosclipboard.mm
@@ -46,11 +46,11 @@
#include <QtGui/QGuiApplication>
@interface UIPasteboard (QUIPasteboard)
- + (UIPasteboard *)pasteboardWithQClipboardMode:(QClipboard::Mode)mode;
++ (instancetype)pasteboardWithQClipboardMode:(QClipboard::Mode)mode;
@end
@implementation UIPasteboard (QUIPasteboard)
-+ (UIPasteboard *)pasteboardWithQClipboardMode:(QClipboard::Mode)mode
++ (instancetype)pasteboardWithQClipboardMode:(QClipboard::Mode)mode
{
NSString *name = (mode == QClipboard::Clipboard) ? UIPasteboardNameGeneral : UIPasteboardNameFind;
return [UIPasteboard pasteboardWithName:name create:NO];
@@ -60,17 +60,15 @@
// --------------------------------------------------------------------
@interface QUIClipboard : NSObject
-{
-@public
+@end
+
+@implementation QUIClipboard {
QIOSClipboard *m_qiosClipboard;
NSInteger m_changeCountClipboard;
NSInteger m_changeCountFindBuffer;
}
-@end
-
-@implementation QUIClipboard
-- (id)initWithQIOSClipboard:(QIOSClipboard *)qiosClipboard
+- (instancetype)initWithQIOSClipboard:(QIOSClipboard *)qiosClipboard
{
self = [super init];
if (self) {
@@ -149,7 +147,7 @@ QStringList QIOSMimeData::formats() const
{
QStringList foundMimeTypes;
UIPasteboard *pb = [UIPasteboard pasteboardWithQClipboardMode:m_mode];
- NSArray *pasteboardTypes = [pb pasteboardTypes];
+ NSArray<NSString *> *pasteboardTypes = [pb pasteboardTypes];
for (NSUInteger i = 0; i < [pasteboardTypes count]; ++i) {
QString uti = QString::fromNSString([pasteboardTypes objectAtIndex:i]);
@@ -164,7 +162,7 @@ QStringList QIOSMimeData::formats() const
QVariant QIOSMimeData::retrieveData(const QString &mimeType, QVariant::Type) const
{
UIPasteboard *pb = [UIPasteboard pasteboardWithQClipboardMode:m_mode];
- NSArray *pasteboardTypes = [pb pasteboardTypes];
+ NSArray<NSString *> *pasteboardTypes = [pb pasteboardTypes];
foreach (QMacInternalPasteboardMime *converter,
QMacInternalPasteboardMime::all(QMacInternalPasteboardMime::MIME_ALL)) {
@@ -213,12 +211,12 @@ void QIOSClipboard::setMimeData(QMimeData *mimeData, QClipboard::Mode mode)
UIPasteboard *pb = [UIPasteboard pasteboardWithQClipboardMode:mode];
if (!mimeData) {
- pb.items = [NSArray array];
+ pb.items = [NSArray<NSDictionary<NSString *, id> *> array];
return;
}
mimeData->deleteLater();
- NSMutableDictionary *pbItem = [NSMutableDictionary dictionaryWithCapacity:mimeData->formats().size()];
+ NSMutableDictionary<NSString *, id> *pbItem = [NSMutableDictionary<NSString *, id> dictionaryWithCapacity:mimeData->formats().size()];
foreach (const QString &mimeType, mimeData->formats()) {
foreach (QMacInternalPasteboardMime *converter,
@@ -246,7 +244,7 @@ void QIOSClipboard::setMimeData(QMimeData *mimeData, QClipboard::Mode mode)
}
}
- pb.items = [NSArray arrayWithObject:pbItem];
+ pb.items = @[pbItem];
}
bool QIOSClipboard::supportsMode(QClipboard::Mode mode) const
diff --git a/src/plugins/platforms/ios/qioseventdispatcher.mm b/src/plugins/platforms/ios/qioseventdispatcher.mm
index 06e5e6cb80..776343c5aa 100644
--- a/src/plugins/platforms/ios/qioseventdispatcher.mm
+++ b/src/plugins/platforms/ios/qioseventdispatcher.mm
@@ -204,6 +204,11 @@ namespace
jmp_buf applicationWillTerminateJumpPoint;
bool debugStackUsage = false;
+
+ struct {
+ QAppleLogActivity UIApplicationMain;
+ QAppleLogActivity applicationDidFinishLaunching;
+ } logActivity;
}
extern "C" int qt_main_wrapper(int argc, char *argv[])
@@ -228,6 +233,9 @@ extern "C" int qt_main_wrapper(int argc, char *argv[])
}
}
+ logActivity.UIApplicationMain = QT_APPLE_LOG_ACTIVITY(
+ lcEventDispatcher().isDebugEnabled(), "UIApplicationMain").enter();
+
qCDebug(lcEventDispatcher) << "Running UIApplicationMain";
return UIApplicationMain(argc, argv, nil, NSStringFromClass([QIOSApplicationDelegate class]));
}
@@ -245,7 +253,7 @@ extern "C" int main(int argc, char *argv[]);
static void __attribute__((noinline, noreturn)) user_main_trampoline()
{
- NSArray *arguments = [[NSProcessInfo processInfo] arguments];
+ NSArray<NSString *> *arguments = [[NSProcessInfo processInfo] arguments];
int argc = arguments.count;
char **argv = new char*[argc];
@@ -263,11 +271,14 @@ static void __attribute__((noinline, noreturn)) user_main_trampoline()
int exitCode = main(argc, argv);
delete[] argv;
+ logActivity.applicationDidFinishLaunching.enter();
qCDebug(lcEventDispatcher) << "Returned from main with exit code " << exitCode;
if (Q_UNLIKELY(debugStackUsage))
userMainStack.printUsage();
+ logActivity.applicationDidFinishLaunching.leave();
+
if (applicationAboutToTerminate)
longjmp(applicationWillTerminateJumpPoint, kJumpedFromUserMainTrampoline);
@@ -322,6 +333,9 @@ static bool rootLevelRunLoopIntegration()
+ (void)applicationDidFinishLaunching:(NSNotification *)notification
{
+ logActivity.applicationDidFinishLaunching = QT_APPLE_LOG_ACTIVITY_WITH_PARENT(
+ lcEventDispatcher().isDebugEnabled(), "applicationDidFinishLaunching", logActivity.UIApplicationMain).enter();
+
qCDebug(lcEventDispatcher) << "Application launched with options" << notification.userInfo;
if (!isQtApplication())
@@ -339,10 +353,11 @@ static bool rootLevelRunLoopIntegration()
return;
}
-
switch (setjmp(processEventEnterJumpPoint)) {
- case kJumpPointSetSuccessfully:
+ case kJumpPointSetSuccessfully: {
qCDebug(lcEventDispatcher) << "Running main() on separate stack";
+ QT_APPLE_SCOPED_LOG_ACTIVITY(lcEventDispatcher().isDebugEnabled(), "main()");
+
// Redirect the stack pointer to the start of the reserved stack. This ensures
// that when we longjmp out of the event dispatcher and continue execution, the
// 'Qt main' call-stack will not be smashed, as it lives in a part of the stack
@@ -357,9 +372,11 @@ static bool rootLevelRunLoopIntegration()
Q_UNREACHABLE();
break;
+ }
case kJumpedFromEventDispatcherProcessEvents:
// We've returned from the longjmp in the event dispatcher,
// and the stack has been restored to its old self.
+ logActivity.UIApplicationMain.enter();
qCDebug(lcEventDispatcher) << "↳ Jumped from processEvents due to exec";
if (Q_UNLIKELY(debugStackUsage))
@@ -378,6 +395,10 @@ static const char kApplicationWillTerminateExitCode = char(SIGTERM | 0x80);
+ (void)applicationWillTerminate
{
+ QAppleLogActivity applicationWillTerminateActivity = QT_APPLE_LOG_ACTIVITY_WITH_PARENT(
+ lcEventDispatcher().isDebugEnabled(), "applicationWillTerminate", logActivity.UIApplicationMain).enter();
+ qCDebug(lcEventDispatcher) << "Application about to be terminated by iOS";
+
if (!isQtApplication())
return;
@@ -403,11 +424,14 @@ static const char kApplicationWillTerminateExitCode = char(SIGTERM | 0x80);
// so we'll never see the exit activity and have a chance to return from
// QEventLoop::exec(). We initiate the return manually as a workaround.
qCDebug(lcEventDispatcher) << "Manually triggering return from event loop exec";
+ applicationWillTerminateActivity.leave();
static_cast<QIOSJumpingEventDispatcher *>(qApp->eventDispatcher())->interruptEventLoopExec();
break;
case kJumpedFromUserMainTrampoline:
+ applicationWillTerminateActivity.enter();
// The user's main has returned, so we're ready to let iOS terminate the application
qCDebug(lcEventDispatcher) << "kJumpedFromUserMainTrampoline, allowing iOS to terminate";
+ applicationWillTerminateActivity.leave();
break;
default:
qFatal("Unexpected jump result in event loop integration");
@@ -446,8 +470,10 @@ bool QIOSEventDispatcher::processPostedEvents()
if (!QEventDispatcherCoreFoundation::processPostedEvents())
return false;
- qCDebug(lcEventDispatcher) << "Sending window system events for" << m_processEvents.flags;
- QWindowSystemInterface::sendWindowSystemEvents(m_processEvents.flags);
+ QT_APPLE_SCOPED_LOG_ACTIVITY(lcEventDispatcher().isDebugEnabled(), "sendWindowSystemEvents");
+ QEventLoop::ProcessEventsFlags flags = QEventLoop::ProcessEventsFlags(m_processEvents.flags.load());
+ qCDebug(lcEventDispatcher) << "Sending window system events for" << flags;
+ QWindowSystemInterface::sendWindowSystemEvents(flags);
return true;
}
@@ -469,6 +495,7 @@ bool __attribute__((returns_twice)) QIOSJumpingEventDispatcher::processEvents(QE
}
if (!m_processEventLevel && (flags & QEventLoop::EventLoopExec)) {
+ QT_APPLE_SCOPED_LOG_ACTIVITY(lcEventDispatcher().isDebugEnabled(), "processEvents");
qCDebug(lcEventDispatcher) << "Processing events with flags" << flags;
++m_processEventLevel;
@@ -526,10 +553,12 @@ void QIOSJumpingEventDispatcher::interruptEventLoopExec()
switch (setjmp(processEventEnterJumpPoint)) {
case kJumpPointSetSuccessfully:
qCDebug(lcEventDispatcher) << "Jumping into processEvents due to system runloop exit ⇢";
+ logActivity.UIApplicationMain.leave();
longjmp(processEventExitJumpPoint, kJumpedFromEventLoopExecInterrupt);
break;
case kJumpedFromEventDispatcherProcessEvents:
// QEventLoop was re-executed
+ logActivity.UIApplicationMain.enter();
qCDebug(lcEventDispatcher) << "↳ Jumped from processEvents due to re-exec";
break;
default:
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
index 493c283ec1..d2229df133 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.mm
+++ b/src/plugins/platforms/ios/qiosinputcontext.mm
@@ -69,7 +69,7 @@ static QUIView *focusView()
@implementation QIOSLocaleListener
-- (id)init
+- (instancetype)init
{
if (self = [super init]) {
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
@@ -97,16 +97,15 @@ static QUIView *focusView()
// -------------------------------------------------------------------------
-@interface QIOSKeyboardListener : UIGestureRecognizer <UIGestureRecognizerDelegate> {
- @private
- QT_PREPEND_NAMESPACE(QIOSInputContext) *m_context;
-}
+@interface QIOSKeyboardListener : UIGestureRecognizer <UIGestureRecognizerDelegate>
@property BOOL hasDeferredScrollToCursor;
@end
-@implementation QIOSKeyboardListener
+@implementation QIOSKeyboardListener {
+ QT_PREPEND_NAMESPACE(QIOSInputContext) *m_context;
+}
-- (id)initWithQIOSInputContext:(QT_PREPEND_NAMESPACE(QIOSInputContext) *)context
+- (instancetype)initWithQIOSInputContext:(QT_PREPEND_NAMESPACE(QIOSInputContext) *)context
{
if (self = [super initWithTarget:self action:@selector(gestureStateChanged:)]) {
@@ -581,7 +580,7 @@ void QIOSInputContext::scroll(int y)
// Raise all known windows to above the status-bar if we're scrolling the screen,
// while keeping the relative window level between the windows the same.
- NSArray *applicationWindows = [qt_apple_sharedApplication() windows];
+ NSArray<UIWindow *> *applicationWindows = [qt_apple_sharedApplication() windows];
static QHash<UIWindow *, UIWindowLevel> originalWindowLevels;
for (UIWindow *window in applicationWindows) {
if (keyboardScrollIsActive && !originalWindowLevels.contains(window))
diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm
index ed2bfbc0d8..bec8354fcc 100644
--- a/src/plugins/platforms/ios/qiosintegration.mm
+++ b/src/plugins/platforms/ios/qiosintegration.mm
@@ -100,7 +100,7 @@ QIOSIntegration::QIOSIntegration()
void QIOSIntegration::initialize()
{
UIScreen *mainScreen = [UIScreen mainScreen];
- NSMutableArray *screens = [[[UIScreen screens] mutableCopy] autorelease];
+ NSMutableArray<UIScreen *> *screens = [[[UIScreen screens] mutableCopy] autorelease];
if (![screens containsObject:mainScreen]) {
// Fallback for iOS 7.1 (QTBUG-42345)
[screens insertObject:mainScreen atIndex:0];
@@ -115,10 +115,8 @@ void QIOSIntegration::initialize()
m_touchDevice = new QTouchDevice;
m_touchDevice->setType(QTouchDevice::TouchScreen);
QTouchDevice::Capabilities touchCapabilities = QTouchDevice::Position | QTouchDevice::NormalizedPosition;
- if (__builtin_available(iOS 9, *)) {
- if (mainScreen.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)
- touchCapabilities |= QTouchDevice::Pressure;
- }
+ if (mainScreen.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)
+ touchCapabilities |= QTouchDevice::Pressure;
m_touchDevice->setCapabilities(touchCapabilities);
QWindowSystemInterface::registerTouchDevice(m_touchDevice);
#if QT_CONFIG(tabletevent)
diff --git a/src/plugins/platforms/ios/qiosmenu.mm b/src/plugins/platforms/ios/qiosmenu.mm
index 6c70676a31..74a77de757 100644
--- a/src/plugins/platforms/ios/qiosmenu.mm
+++ b/src/plugins/platforms/ios/qiosmenu.mm
@@ -60,14 +60,14 @@ QIOSMenu *QIOSMenu::m_currentMenu = 0;
static NSString *const kSelectorPrefix = @"_qtMenuItem_";
-@interface QUIMenuController : UIResponder {
- QIOSMenuItemList m_visibleMenuItems;
-}
+@interface QUIMenuController : UIResponder
@end
-@implementation QUIMenuController
+@implementation QUIMenuController {
+ QIOSMenuItemList m_visibleMenuItems;
+}
-- (id)initWithVisibleMenuItems:(const QIOSMenuItemList &)visibleMenuItems
+- (instancetype)initWithVisibleMenuItems:(const QIOSMenuItemList &)visibleMenuItems
{
if (self = [super init]) {
[self setVisibleMenuItems:visibleMenuItems];
@@ -80,7 +80,7 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_";
return self;
}
--(void)dealloc
+- (void)dealloc
{
[[NSNotificationCenter defaultCenter]
removeObserver:self
@@ -91,7 +91,7 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_";
- (void)setVisibleMenuItems:(const QIOSMenuItemList &)visibleMenuItems
{
m_visibleMenuItems = visibleMenuItems;
- NSMutableArray *menuItemArray = [NSMutableArray arrayWithCapacity:m_visibleMenuItems.size()];
+ NSMutableArray<UIMenuItem *> *menuItemArray = [NSMutableArray<UIMenuItem *> arrayWithCapacity:m_visibleMenuItems.size()];
// Create an array of UIMenuItems, one for each visible QIOSMenuItem. Each
// UIMenuItem needs a callback assigned, so we assign one of the placeholder methods
// added to UIWindow (QIOSMenuActionTargets) below. Each method knows its own index, which
@@ -107,7 +107,7 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_";
[[UIMenuController sharedMenuController] setMenuVisible:YES animated:NO];
}
--(void)menuClosed
+- (void)menuClosed
{
QIOSMenu::currentMenu()->dismiss();
}
@@ -141,19 +141,19 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_";
// -------------------------------------------------------------------------
-@interface QUIPickerView : UIPickerView <UIPickerViewDelegate, UIPickerViewDataSource> {
- QIOSMenuItemList m_visibleMenuItems;
- QPointer<QObject> m_focusObjectWithPickerView;
- NSInteger m_selectedRow;
-}
+@interface QUIPickerView : UIPickerView <UIPickerViewDelegate, UIPickerViewDataSource>
@property(retain) UIToolbar *toolbar;
@end
-@implementation QUIPickerView
+@implementation QUIPickerView {
+ QIOSMenuItemList m_visibleMenuItems;
+ QPointer<QObject> m_focusObjectWithPickerView;
+ NSInteger m_selectedRow;
+}
-- (id)initWithVisibleMenuItems:(const QIOSMenuItemList &)visibleMenuItems selectItem:(const QIOSMenuItem *)selectItem
+- (instancetype)initWithVisibleMenuItems:(const QIOSMenuItemList &)visibleMenuItems selectItem:(const QIOSMenuItem *)selectItem
{
if (self = [super init]) {
[self setVisibleMenuItems:visibleMenuItems selectItem:selectItem];
@@ -172,7 +172,7 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_";
UIBarButtonItem *doneButton = [[[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self action:@selector(closeMenu)] autorelease];
- [self.toolbar setItems:[NSArray arrayWithObjects:cancelButton, spaceButton, doneButton, nil]];
+ [self.toolbar setItems:@[cancelButton, spaceButton, doneButton]];
[self setDelegate:self];
[self setDataSource:self];
diff --git a/src/plugins/platforms/ios/qiosmessagedialog.h b/src/plugins/platforms/ios/qiosmessagedialog.h
index 92a4db8319..913fe0c2e9 100644
--- a/src/plugins/platforms/ios/qiosmessagedialog.h
+++ b/src/plugins/platforms/ios/qiosmessagedialog.h
@@ -63,6 +63,7 @@ private:
UIAlertController *m_alertController;
QString messageTextPlain();
UIAlertAction *createAction(StandardButton button);
+ UIAlertAction *createAction(const QMessageDialogOptions::CustomButton &customButton);
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiosmessagedialog.mm b/src/plugins/platforms/ios/qiosmessagedialog.mm
index a7de9b473a..254922701a 100644
--- a/src/plugins/platforms/ios/qiosmessagedialog.mm
+++ b/src/plugins/platforms/ios/qiosmessagedialog.mm
@@ -79,6 +79,18 @@ inline QString QIOSMessageDialog::messageTextPlain()
return text;
}
+inline UIAlertAction *QIOSMessageDialog::createAction(
+ const QMessageDialogOptions::CustomButton &customButton)
+{
+ const QString label = QPlatformTheme::removeMnemonics(customButton.label);
+ const UIAlertActionStyle style = UIAlertActionStyleDefault;
+
+ return [UIAlertAction actionWithTitle:label.toNSString() style:style handler:^(UIAlertAction *) {
+ hide();
+ emit clicked(static_cast<QPlatformDialogHelper::StandardButton>(customButton.id), customButton.role);
+ }];
+}
+
inline UIAlertAction *QIOSMessageDialog::createAction(StandardButton button)
{
const StandardButton labelButton = button == NoButton ? Ok : button;
@@ -118,12 +130,18 @@ bool QIOSMessageDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality win
message:messageTextPlain().toNSString()
preferredStyle:UIAlertControllerStyleAlert] retain];
+ const QVector<QMessageDialogOptions::CustomButton> customButtons = options()->customButtons();
+ for (const QMessageDialogOptions::CustomButton &button : customButtons) {
+ UIAlertAction *act = createAction(button);
+ [m_alertController addAction:act];
+ }
+
if (StandardButtons buttons = options()->standardButtons()) {
for (int i = FirstButton; i < LastButton; i<<=1) {
if (i & buttons)
[m_alertController addAction:createAction(StandardButton(i))];
}
- } else {
+ } else if (customButtons.isEmpty()) {
// We need at least one button to allow the user close the dialog
[m_alertController addAction:createAction(NoButton)];
}
diff --git a/src/plugins/platforms/ios/qiosoptionalplugininterface.h b/src/plugins/platforms/ios/qiosoptionalplugininterface.h
index 660c74e856..bae9e5a0d8 100644
--- a/src/plugins/platforms/ios/qiosoptionalplugininterface.h
+++ b/src/plugins/platforms/ios/qiosoptionalplugininterface.h
@@ -44,10 +44,10 @@
#include "qiosfiledialog.h"
-QT_BEGIN_NAMESPACE
-
Q_FORWARD_DECLARE_OBJC_CLASS(UIViewController);
+QT_BEGIN_NAMESPACE
+
#define QIosOptionalPluginInterface_iid "org.qt-project.Qt.QPA.ios.optional"
class QIosOptionalPluginInterface
diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm
index f367d1e75e..4f753be21a 100644
--- a/src/plugins/platforms/ios/qiosscreen.mm
+++ b/src/plugins/platforms/ios/qiosscreen.mm
@@ -132,16 +132,14 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
// -------------------------------------------------------------------------
-@interface QIOSOrientationListener : NSObject {
- @public
- QIOSScreen *m_screen;
-}
-- (id)initWithQIOSScreen:(QIOSScreen *)screen;
+@interface QIOSOrientationListener : NSObject
@end
-@implementation QIOSOrientationListener
+@implementation QIOSOrientationListener {
+ QIOSScreen *m_screen;
+}
-- (id)initWithQIOSScreen:(QIOSScreen *)screen
+- (instancetype)initWithQIOSScreen:(QIOSScreen *)screen
{
self = [super init];
if (self) {
@@ -195,7 +193,7 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
@implementation QUIWindow
-- (id)initWithFrame:(CGRect)frame
+- (instancetype)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame]))
self->_sendingEvent = NO;
@@ -399,17 +397,21 @@ void QIOSScreen::deliverUpdateRequests() const
QList<QWindow*> windows = QGuiApplication::allWindows();
for (int i = 0; i < windows.size(); ++i) {
- if (platformScreenForWindow(windows.at(i)) != this)
+ QWindow *window = windows.at(i);
+ if (platformScreenForWindow(window) != this)
continue;
- QWindowPrivate *wp = static_cast<QWindowPrivate *>(QObjectPrivate::get(windows.at(i)));
- if (!wp->updateRequestPending)
+ QPlatformWindow *platformWindow = window->handle();
+ if (!platformWindow)
continue;
- wp->deliverUpdateRequest();
+ if (!platformWindow->hasPendingUpdateRequest())
+ continue;
+
+ platformWindow->deliverUpdateRequest();
// Another update request was triggered, keep the display link running
- if (wp->updateRequestPending)
+ if (platformWindow->hasPendingUpdateRequest())
pauseUpdates = false;
}
@@ -454,12 +456,7 @@ qreal QIOSScreen::devicePixelRatio() const
qreal QIOSScreen::refreshRate() const
{
-#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_NA, 100300, 110000, __WATCHOS_NA)
- if (__builtin_available(iOS 10.3, tvOS 11, *))
- return m_uiScreen.maximumFramesPerSecond;
-#endif
-
- return 60.0;
+ return m_uiScreen.maximumFramesPerSecond;
}
Qt::ScreenOrientation QIOSScreen::nativeOrientation() const
diff --git a/src/plugins/platforms/ios/qiostextinputoverlay.mm b/src/plugins/platforms/ios/qiostextinputoverlay.mm
index 87c282e24a..e5419b1766 100644
--- a/src/plugins/platforms/ios/qiostextinputoverlay.mm
+++ b/src/plugins/platforms/ios/qiostextinputoverlay.mm
@@ -97,7 +97,7 @@ static void executeBlockWithoutAnimation(Block block)
@implementation QIOSEditMenu
-- (id)init
+- (instancetype)init
{
if (self = [super init]) {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
@@ -161,7 +161,13 @@ static void executeBlockWithoutAnimation(Block block)
// -------------------------------------------------------------------------
-@interface QIOSLoupeLayer : CALayer {
+@interface QIOSLoupeLayer : CALayer
+@property (nonatomic, retain) UIView *targetView;
+@property (nonatomic, assign) CGPoint focalPoint;
+@property (nonatomic, assign) BOOL visible;
+@end
+
+@implementation QIOSLoupeLayer {
UIView *_snapshotView;
BOOL _pendingSnapshotUpdate;
UIView *_loupeImageView;
@@ -169,14 +175,8 @@ static void executeBlockWithoutAnimation(Block block)
CGFloat _loupeOffset;
QTimer _updateTimer;
}
-@property (nonatomic, retain) UIView *targetView;
-@property (nonatomic, assign) CGPoint focalPoint;
-@property (nonatomic, assign) BOOL visible;
-@end
-@implementation QIOSLoupeLayer
-
-- (id)initWithSize:(CGSize)size cornerRadius:(CGFloat)cornerRadius bottomOffset:(CGFloat)bottomOffset
+- (instancetype)initWithSize:(CGSize)size cornerRadius:(CGFloat)cornerRadius bottomOffset:(CGFloat)bottomOffset
{
if (self = [super init]) {
_loupeOffset = bottomOffset + (size.height / 2);
@@ -302,26 +302,22 @@ static void executeBlockWithoutAnimation(Block block)
// -------------------------------------------------------------------------
-#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0)
-@interface QIOSHandleLayer : CALayer <CAAnimationDelegate> {
-#else
-@interface QIOSHandleLayer : CALayer {
-#endif
- CALayer *_handleCursorLayer;
- CALayer *_handleKnobLayer;
- Qt::Edge _selectionEdge;
-}
+@interface QIOSHandleLayer : CALayer <CAAnimationDelegate>
@property (nonatomic, assign) CGRect cursorRectangle;
@property (nonatomic, assign) CGFloat handleScale;
@property (nonatomic, assign) BOOL visible;
@property (nonatomic, copy) Block onAnimationDidStop;
@end
-@implementation QIOSHandleLayer
+@implementation QIOSHandleLayer {
+ CALayer *_handleCursorLayer;
+ CALayer *_handleKnobLayer;
+ Qt::Edge _selectionEdge;
+}
@dynamic handleScale;
-- (id)initWithKnobAtEdge:(Qt::Edge)selectionEdge
+- (instancetype)initWithKnobAtEdge:(Qt::Edge)selectionEdge
{
if (self = [super init]) {
CGColorRef bgColor = [UIColor colorWithRed:0.1 green:0.4 blue:0.9 alpha:1].CGColor;
@@ -356,16 +352,8 @@ static void executeBlockWithoutAnimation(Block block)
// The handle should "bounce" in when becoming visible
CAKeyframeAnimation * animation = [CAKeyframeAnimation animationWithKeyPath:key];
[animation setDuration:0.5];
- animation.values = [NSArray arrayWithObjects:
- [NSNumber numberWithFloat:0],
- [NSNumber numberWithFloat:1.3],
- [NSNumber numberWithFloat:1.3],
- [NSNumber numberWithFloat:1], nil];
- animation.keyTimes = [NSArray arrayWithObjects:
- [NSNumber numberWithFloat:0],
- [NSNumber numberWithFloat:0.3],
- [NSNumber numberWithFloat:0.9],
- [NSNumber numberWithFloat:1], nil];
+ animation.values = @[@(0.0f), @(1.3f), @(1.3f), @(1.0f)];
+ animation.keyTimes = @[@(0.0f), @(0.3f), @(0.9f), @(1.0f)];
return animation;
} else {
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:key];
@@ -437,8 +425,13 @@ static void executeBlockWithoutAnimation(Block block)
below will inherit. It takes care of creating and showing a magnifier
glass depending on the current gesture state.
*/
-@interface QIOSLoupeRecognizer : UIGestureRecognizer <UIGestureRecognizerDelegate> {
-@public
+@interface QIOSLoupeRecognizer : UIGestureRecognizer <UIGestureRecognizerDelegate>
+@property (nonatomic, assign) QPointF focalPoint;
+@property (nonatomic, assign) BOOL dragTriggersGesture;
+@property (nonatomic, readonly) UIView *focusView;
+@end
+
+@implementation QIOSLoupeRecognizer {
QIOSLoupeLayer *_loupeLayer;
UIView *_desktopView;
CGPoint _firstTouchPoint;
@@ -446,14 +439,8 @@ static void executeBlockWithoutAnimation(Block block)
QTimer _triggerStateBeganTimer;
int _originalCursorFlashTime;
}
-@property (nonatomic, assign) QPointF focalPoint;
-@property (nonatomic, assign) BOOL dragTriggersGesture;
-@property (nonatomic, readonly) UIView *focusView;
-@end
-@implementation QIOSLoupeRecognizer
-
-- (id)init
+- (instancetype)init
{
if (self = [super initWithTarget:self action:@selector(gestureStateChanged)]) {
self.enabled = NO;
@@ -658,7 +645,10 @@ static void executeBlockWithoutAnimation(Block block)
on the sides. If the user starts dragging on a handle (or do a press and
hold), it will show a magnifier glass that follows the handle as it moves.
*/
-@interface QIOSSelectionRecognizer : QIOSLoupeRecognizer {
+@interface QIOSSelectionRecognizer : QIOSLoupeRecognizer
+@end
+
+@implementation QIOSSelectionRecognizer {
CALayer *_clipRectLayer;
QIOSHandleLayer *_cursorLayer;
QIOSHandleLayer *_anchorLayer;
@@ -670,11 +660,8 @@ static void executeBlockWithoutAnimation(Block block)
QMetaObject::Connection _anchorConnection;
QMetaObject::Connection _clipRectConnection;
}
-@end
-
-@implementation QIOSSelectionRecognizer
-- (id)init
+- (instancetype)init
{
if (self = [super init]) {
self.delaysTouchesBegan = YES;
@@ -890,15 +877,15 @@ static void executeBlockWithoutAnimation(Block block)
visibility of the edit menu will be toggled. Otherwise, if there's a selection, a
first tap will close the edit menu (if any), and a second tap will remove the selection.
*/
-@interface QIOSTapRecognizer : UITapGestureRecognizer {
+@interface QIOSTapRecognizer : UITapGestureRecognizer
+@end
+
+@implementation QIOSTapRecognizer {
int _cursorPosOnPress;
UIView *_focusView;
}
-@end
-
-@implementation QIOSTapRecognizer
-- (id)init
+- (instancetype)init
{
if (self = [super initWithTarget:self action:@selector(gestureStateChanged)]) {
self.enabled = NO;
diff --git a/src/plugins/platforms/ios/qiostextresponder.h b/src/plugins/platforms/ios/qiostextresponder.h
index 77be2cf2fe..074598c1c3 100644
--- a/src/plugins/platforms/ios/qiostextresponder.h
+++ b/src/plugins/platforms/ios/qiostextresponder.h
@@ -49,16 +49,8 @@ class QIOSInputContext;
QT_END_NAMESPACE
@interface QIOSTextInputResponder : UIResponder <UITextInputTraits, UIKeyInput, UITextInput>
-{
- @private
- QT_PREPEND_NAMESPACE(QIOSInputContext) *m_inputContext;
- QT_PREPEND_NAMESPACE(QInputMethodQueryEvent) *m_configuredImeState;
- QString m_markedText;
- BOOL m_inSendEventToFocusObject;
- BOOL m_inSelectionChange;
-}
-- (id)initWithInputContext:(QT_PREPEND_NAMESPACE(QIOSInputContext) *)context;
+- (instancetype)initWithInputContext:(QT_PREPEND_NAMESPACE(QIOSInputContext) *)context;
- (BOOL)needsKeyboardReconfigure:(Qt::InputMethodQueries)updatedProperties;
- (void)notifyInputDelegate:(Qt::InputMethodQueries)updatedProperties;
diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm
index b029c49a67..396c769be8 100644
--- a/src/plugins/platforms/ios/qiostextresponder.mm
+++ b/src/plugins/platforms/ios/qiostextresponder.mm
@@ -55,13 +55,13 @@
@interface QUITextPosition : UITextPosition
@property (nonatomic) NSUInteger index;
-+ (QUITextPosition *)positionWithIndex:(NSUInteger)index;
++ (instancetype)positionWithIndex:(NSUInteger)index;
@end
@implementation QUITextPosition
-+ (QUITextPosition *)positionWithIndex:(NSUInteger)index
++ (instancetype)positionWithIndex:(NSUInteger)index
{
QUITextPosition *pos = [[QUITextPosition alloc] init];
pos.index = index;
@@ -75,15 +75,15 @@
@interface QUITextRange : UITextRange
@property (nonatomic) NSRange range;
-+ (QUITextRange *)rangeWithNSRange:(NSRange)range;
++ (instancetype)rangeWithNSRange:(NSRange)range;
@end
@implementation QUITextRange
-+ (QUITextRange *)rangeWithNSRange:(NSRange)nsrange
++ (instancetype)rangeWithNSRange:(NSRange)nsrange
{
- QUITextRange *range = [[QUITextRange alloc] init];
+ QUITextRange *range = [[self alloc] init];
range.range = nsrange;
return [range autorelease];
}
@@ -117,7 +117,7 @@
@implementation WrapperView
-- (id)initWithView:(UIView *)view
+- (instancetype)initWithView:(UIView *)view
{
if (self = [self init]) {
[self addSubview:view];
@@ -132,7 +132,7 @@
- (void)layoutSubviews
{
- UIView* view = [self.subviews firstObject];
+ UIView *view = [self.subviews firstObject];
view.frame = self.bounds;
// FIXME: During orientation changes the size and position
@@ -161,9 +161,15 @@
// -------------------------------------------------------------------------
-@implementation QIOSTextInputResponder
+@implementation QIOSTextInputResponder {
+ QT_PREPEND_NAMESPACE(QIOSInputContext) *m_inputContext;
+ QT_PREPEND_NAMESPACE(QInputMethodQueryEvent) *m_configuredImeState;
+ QString m_markedText;
+ BOOL m_inSendEventToFocusObject;
+ BOOL m_inSelectionChange;
+}
-- (id)initWithInputContext:(QT_PREPEND_NAMESPACE(QIOSInputContext) *)inputContext
+- (instancetype)initWithInputContext:(QT_PREPEND_NAMESPACE(QIOSInputContext) *)inputContext
{
if (!(self = [self init]))
return self;
@@ -238,17 +244,15 @@
self.inputAccessoryView = [[[WrapperView alloc] initWithView:accessoryView] autorelease];
#ifndef Q_OS_TVOS
- if (__builtin_available(iOS 9, *)) {
- if (platformData.value(kImePlatformDataHideShortcutsBar).toBool()) {
- // According to the docs, leadingBarButtonGroups/trailingBarButtonGroups should be set to nil to hide the shortcuts bar.
- // However, starting with iOS 10, the API has been surrounded with NS_ASSUME_NONNULL, which contradicts this and causes
- // compiler warnings. Still it is the way to go to really hide the space reserved for that.
+ if (platformData.value(kImePlatformDataHideShortcutsBar).toBool()) {
+ // According to the docs, leadingBarButtonGroups/trailingBarButtonGroups should be set to nil to hide the shortcuts bar.
+ // However, starting with iOS 10, the API has been surrounded with NS_ASSUME_NONNULL, which contradicts this and causes
+ // compiler warnings. Still it is the way to go to really hide the space reserved for that.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnonnull"
- self.inputAssistantItem.leadingBarButtonGroups = nil;
- self.inputAssistantItem.trailingBarButtonGroups = nil;
+ self.inputAssistantItem.leadingBarButtonGroups = nil;
+ self.inputAssistantItem.trailingBarButtonGroups = nil;
#pragma clang diagnostic pop
- }
}
#endif
@@ -548,7 +552,7 @@
[self sendKeyPressRelease:key modifiers:modifiers];
}
-- (void)addKeyCommandsToArray:(NSMutableArray *)array key:(NSString *)key
+- (void)addKeyCommandsToArray:(NSMutableArray<UIKeyCommand *> *)array key:(NSString *)key
{
SEL s = @selector(keyCommandTriggered:);
[array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:0 action:s]];
@@ -559,19 +563,19 @@
[array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:UIKeyModifierCommand|UIKeyModifierShift action:s]];
}
-- (NSArray *)keyCommands
+- (NSArray<UIKeyCommand *> *)keyCommands
{
// Since keyCommands is called for every key
// press/release, we cache the result
static dispatch_once_t once;
- static NSMutableArray *array;
+ static NSMutableArray<UIKeyCommand *> *array;
dispatch_once(&once, ^{
// We let Qt move the cursor around when the arrow keys are being used. This
// is normally implemented through UITextInput, but since IM in Qt have poor
// support for moving the cursor vertically, and even less support for selecting
// text across multiple paragraphs, we do this through key events.
- array = [NSMutableArray new];
+ array = [NSMutableArray<UIKeyCommand *> new];
[self addKeyCommandsToArray:array key:UIKeyInputUpArrow];
[self addKeyCommandsToArray:array key:UIKeyInputDownArrow];
[self addKeyCommandsToArray:array key:UIKeyInputLeftArrow];
@@ -825,13 +829,13 @@
return startRect.united(endRect).toCGRect();
}
-- (NSArray *)selectionRectsForRange:(UITextRange *)range
+- (NSArray<UITextSelectionRect *> *)selectionRectsForRange:(UITextRange *)range
{
Q_UNUSED(range);
// This method is supposed to return a rectangle for each line with selection. Since we don't
// expose an API in Qt/IM for getting this information, and since we never seems to be getting
// a call from UIKit for this, we return an empty array until a need arise.
- return [[NSArray new] autorelease];
+ return [[NSArray<UITextSelectionRect *> new] autorelease];
}
- (CGRect)caretRectForPosition:(UITextPosition *)position
@@ -916,7 +920,7 @@
QObject *focusObject = QGuiApplication::focusObject();
if (!focusObject)
- return [NSDictionary dictionary];
+ return @{};
// Assume position is the same as the cursor for now. QInputMethodQueryEvent with Qt::ImFont
// needs to be extended to take an extra position argument before this can be fully correct.
@@ -925,8 +929,8 @@
QFont qfont = qvariant_cast<QFont>(e.value(Qt::ImFont));
UIFont *uifont = [UIFont fontWithName:qfont.family().toNSString() size:qfont.pointSize()];
if (!uifont)
- return [NSDictionary dictionary];
- return [NSDictionary dictionaryWithObject:uifont forKey:NSFontAttributeName];
+ return @{};
+ return @{NSFontAttributeName: uifont};
}
#endif
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.h b/src/plugins/platforms/ios/qiosviewcontroller.h
index 07d5535e1a..7af4c83b48 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.h
+++ b/src/plugins/platforms/ios/qiosviewcontroller.h
@@ -48,7 +48,7 @@ QT_END_NAMESPACE
@interface QIOSViewController : UIViewController
-- (id)initWithQIOSScreen:(QT_PREPEND_NAMESPACE(QIOSScreen) *)screen;
+- (instancetype)initWithQIOSScreen:(QT_PREPEND_NAMESPACE(QIOSScreen) *)screen;
- (void)updateProperties;
#ifndef Q_OS_TVOS
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm
index aa909d6f63..ce2aa96ca5 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.mm
+++ b/src/plugins/platforms/ios/qiosviewcontroller.mm
@@ -57,12 +57,8 @@
// -------------------------------------------------------------------------
-@interface QIOSViewController () {
- @public
- QPointer<QT_PREPEND_NAMESPACE(QIOSScreen)> m_screen;
- BOOL m_updatingProperties;
- QMetaObject::Connection m_focusWindowChangeConnection;
-}
+@interface QIOSViewController ()
+@property (nonatomic, assign) QPointer<QT_PREPEND_NAMESPACE(QIOSScreen)> platformScreen;
@property (nonatomic, assign) BOOL changingOrientation;
@end
@@ -73,7 +69,7 @@
@implementation QIOSDesktopManagerView
-- (id)init
+- (instancetype)init
{
if (!(self = [super init]))
return nil;
@@ -126,7 +122,7 @@
{
Q_UNUSED(subview);
- QT_PREPEND_NAMESPACE(QIOSScreen) *screen = self.qtViewController->m_screen;
+ QT_PREPEND_NAMESPACE(QIOSScreen) *screen = self.qtViewController.platformScreen;
// The 'window' property of our view is not valid until the window
// has been shown, so we have to access it through the QIOSScreen.
@@ -171,7 +167,7 @@
// here. iOS will still use the latest rendered frame to create the
// application switcher thumbnail, but it will be based on the last
// active orientation of the application.
- QIOSScreen *screen = self.qtViewController->m_screen;
+ QIOSScreen *screen = self.qtViewController.platformScreen;
qCDebug(lcQpaWindow) << "ignoring layout of subviews while suspended,"
<< "likely system snapshot of" << screen->screen()->primaryOrientation();
return;
@@ -247,7 +243,10 @@
// -------------------------------------------------------------------------
-@implementation QIOSViewController
+@implementation QIOSViewController {
+ BOOL m_updatingProperties;
+ QMetaObject::Connection m_focusWindowChangeConnection;
+}
#ifndef Q_OS_TVOS
@synthesize prefersStatusBarHidden;
@@ -255,11 +254,10 @@
@synthesize preferredStatusBarStyle;
#endif
-- (id)initWithQIOSScreen:(QT_PREPEND_NAMESPACE(QIOSScreen) *)screen
+- (instancetype)initWithQIOSScreen:(QT_PREPEND_NAMESPACE(QIOSScreen) *)screen
{
if (self = [self init]) {
- m_screen = screen;
-
+ self.platformScreen = screen;
self.changingOrientation = NO;
#ifndef Q_OS_TVOS
@@ -333,7 +331,7 @@
- (BOOL)shouldAutorotate
{
#ifndef Q_OS_TVOS
- return m_screen && m_screen->uiScreen() == [UIScreen mainScreen] && !self.lockedOrientation;
+ return self.platformScreen && self.platformScreen->uiScreen() == [UIScreen mainScreen] && !self.lockedOrientation;
#else
return NO;
#endif
@@ -413,8 +411,8 @@
if (!QCoreApplication::instance())
return;
- if (m_screen)
- m_screen->updateProperties();
+ if (self.platformScreen)
+ self.platformScreen->updateProperties();
}
// -------------------------------------------------------------------------
@@ -424,12 +422,12 @@
if (!isQtApplication())
return;
- if (!m_screen || !m_screen->screen())
+ if (!self.platformScreen || !self.platformScreen->screen())
return;
// For now we only care about the main screen, as both the statusbar
// visibility and orientation is only appropriate for the main screen.
- if (m_screen->uiScreen() != [UIScreen mainScreen])
+ if (self.platformScreen->uiScreen() != [UIScreen mainScreen])
return;
// Prevent recursion caused by updating the status bar appearance (position
@@ -451,7 +449,7 @@
return;
// We only care about changes to focusWindow that involves our screen
- if (!focusWindow->screen() || focusWindow->screen()->handle() != m_screen)
+ if (!focusWindow->screen() || focusWindow->screen()->handle() != self.platformScreen)
return;
// All decisions are based on the the top level window
diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm
index 6ee258e363..cdec57de71 100644
--- a/src/plugins/platforms/ios/qioswindow.mm
+++ b/src/plugins/platforms/ios/qioswindow.mm
@@ -96,7 +96,7 @@ QIOSWindow::~QIOSWindow()
[m_view touchesCancelled:[NSSet set] withEvent:0];
clearAccessibleCache();
- m_view->m_qioswindow = 0;
+ m_view.platformWindow = 0;
[m_view removeFromSuperview];
[m_view release];
}
@@ -139,7 +139,7 @@ void QIOSWindow::setVisible(bool visible)
} else if (!visible && [m_view isActiveWindow]) {
// Our window was active/focus window but now hidden, so relinquish
// focus to the next possible window in the stack.
- NSArray *subviews = m_view.viewController.view.subviews;
+ NSArray<UIView *> *subviews = m_view.viewController.view.subviews;
for (int i = int(subviews.count) - 1; i >= 0; --i) {
UIView *view = [subviews objectAtIndex:i];
if (view.hidden)
@@ -301,7 +301,7 @@ void QIOSWindow::raiseOrLower(bool raise)
if (!isQtApplication())
return;
- NSArray *subviews = m_view.superview.subviews;
+ NSArray<UIView *> *subviews = m_view.superview.subviews;
if (subviews.count == 1)
return;
diff --git a/src/plugins/platforms/ios/quiaccessibilityelement.h b/src/plugins/platforms/ios/quiaccessibilityelement.h
index 03abf5407e..6b8efdcede 100644
--- a/src/plugins/platforms/ios/quiaccessibilityelement.h
+++ b/src/plugins/platforms/ios/quiaccessibilityelement.h
@@ -45,13 +45,12 @@
#ifndef QT_NO_ACCESSIBILITY
-@interface QMacAccessibilityElement : UIAccessibilityElement
-{}
+@interface QT_MANGLE_NAMESPACE(QMacAccessibilityElement) : UIAccessibilityElement
@property (readonly) QAccessible::Id axid;
-- (id)initWithId:(QAccessible::Id)anId withAccessibilityContainer:(id)view;
-+ (QMacAccessibilityElement *)elementWithId:(QAccessible::Id)anId withAccessibilityContainer:(id)view;
+- (instancetype)initWithId:(QAccessible::Id)anId withAccessibilityContainer:(id)view;
++ (instancetype)elementWithId:(QAccessible::Id)anId withAccessibilityContainer:(id)view;
@end
diff --git a/src/plugins/platforms/ios/quiaccessibilityelement.mm b/src/plugins/platforms/ios/quiaccessibilityelement.mm
index a26ba61b3c..3154536aad 100644
--- a/src/plugins/platforms/ios/quiaccessibilityelement.mm
+++ b/src/plugins/platforms/ios/quiaccessibilityelement.mm
@@ -42,20 +42,23 @@
#ifndef QT_NO_ACCESSIBILITY
#include "private/qaccessiblecache_p.h"
+#include "private/qcore_mac_p.h"
+
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QMacAccessibilityElement);
@implementation QMacAccessibilityElement
-- (id)initWithId:(QAccessible::Id)anId withAccessibilityContainer:(id)view
+- (instancetype)initWithId:(QAccessible::Id)anId withAccessibilityContainer:(id)view
{
Q_ASSERT((int)anId < 0);
- self = [super initWithAccessibilityContainer: view];
+ self = [super initWithAccessibilityContainer:view];
if (self)
_axid = anId;
return self;
}
-+ (id)elementWithId:(QAccessible::Id)anId withAccessibilityContainer:(id)view
++ (instancetype)elementWithId:(QAccessible::Id)anId withAccessibilityContainer:(id)view
{
Q_ASSERT(anId);
if (!anId)
@@ -63,10 +66,10 @@
QAccessibleCache *cache = QAccessibleCache::instance();
- QT_MANGLE_NAMESPACE(QMacAccessibilityElement) *element = cache->elementForId(anId);
+ QMacAccessibilityElement *element = cache->elementForId(anId);
if (!element) {
Q_ASSERT(QAccessible::accessibleInterface(anId));
- element = [[self alloc] initWithId:anId withAccessibilityContainer: view];
+ element = [[self alloc] initWithId:anId withAccessibilityContainer:view];
cache->insertElement(anId, element);
}
return element;
diff --git a/src/plugins/platforms/ios/quiview.h b/src/plugins/platforms/ios/quiview.h
index 3e3c579075..e1d5d5af0c 100644
--- a/src/plugins/platforms/ios/quiview.h
+++ b/src/plugins/platforms/ios/quiview.h
@@ -53,21 +53,10 @@ QT_END_NAMESPACE
@class QIOSViewController;
@interface QUIView : UIView
-{
- @public
- QT_PREPEND_NAMESPACE(QIOSWindow) *m_qioswindow;
- @private
- QHash<UITouch *, QWindowSystemInterface::TouchPoint> m_activeTouches;
- UITouch *m_activePencilTouch;
- int m_nextTouchId;
-
- @private
- NSMutableArray *m_accessibleElements;
-};
-
-- (id)initWithQIOSWindow:(QT_PREPEND_NAMESPACE(QIOSWindow) *)window;
+- (instancetype)initWithQIOSWindow:(QT_PREPEND_NAMESPACE(QIOSWindow) *)window;
- (void)sendUpdatedExposeEvent;
- (BOOL)isActiveWindow;
+@property (nonatomic, assign) QT_PREPEND_NAMESPACE(QIOSWindow) *platformWindow;
@end
@interface QUIView (Accessibility)
diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm
index 8db36705c0..e64c05d099 100644
--- a/src/plugins/platforms/ios/quiview.mm
+++ b/src/plugins/platforms/ios/quiview.mm
@@ -55,7 +55,12 @@
Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
-@implementation QUIView
+@implementation QUIView {
+ QHash<UITouch *, QWindowSystemInterface::TouchPoint> m_activeTouches;
+ UITouch *m_activePencilTouch;
+ int m_nextTouchId;
+ NSMutableArray<UIAccessibilityElement *> *m_accessibleElements;
+}
+ (void)load
{
@@ -82,25 +87,26 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
return [CAEAGLLayer class];
}
-- (id)initWithQIOSWindow:(QT_PREPEND_NAMESPACE(QIOSWindow) *)window
+- (instancetype)initWithQIOSWindow:(QT_PREPEND_NAMESPACE(QIOSWindow) *)window
{
if (self = [self initWithFrame:window->geometry().toCGRect()]) {
- m_qioswindow = window;
- m_accessibleElements = [[NSMutableArray alloc] init];
+ self.platformWindow = window;
+ m_accessibleElements = [[NSMutableArray<UIAccessibilityElement *> alloc] init];
}
return self;
}
-- (id)initWithFrame:(CGRect)frame
+- (instancetype)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame])) {
// Set up EAGL layer
CAEAGLLayer *eaglLayer = static_cast<CAEAGLLayer *>(self.layer);
eaglLayer.opaque = TRUE;
- eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking,
- kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
+ eaglLayer.drawableProperties = @{
+ kEAGLDrawablePropertyRetainedBacking: @(YES),
+ kEAGLDrawablePropertyColorFormat: kEAGLColorFormatRGBA8
+ };
if (isQtApplication())
self.hidden = YES;
@@ -122,21 +128,17 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
self.layer.borderWidth = 1.0;
}
-#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_NA, 110000, 110000, __WATCHOS_NA)
if (qEnvironmentVariableIsSet("QT_IOS_DEBUG_WINDOW_SAFE_AREAS")) {
- if (__builtin_available(iOS 11, tvOS 11, *)) {
- UIView *safeAreaOverlay = [[UIView alloc] initWithFrame:CGRectZero];
- [safeAreaOverlay setBackgroundColor:[UIColor colorWithRed:0.3 green:0.7 blue:0.9 alpha:0.3]];
- [self addSubview:safeAreaOverlay];
-
- safeAreaOverlay.translatesAutoresizingMaskIntoConstraints = NO;
- [safeAreaOverlay.topAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.topAnchor].active = YES;
- [safeAreaOverlay.leftAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.leftAnchor].active = YES;
- [safeAreaOverlay.rightAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.rightAnchor].active = YES;
- [safeAreaOverlay.bottomAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.bottomAnchor].active = YES;
- }
+ UIView *safeAreaOverlay = [[UIView alloc] initWithFrame:CGRectZero];
+ [safeAreaOverlay setBackgroundColor:[UIColor colorWithRed:0.3 green:0.7 blue:0.9 alpha:0.3]];
+ [self addSubview:safeAreaOverlay];
+
+ safeAreaOverlay.translatesAutoresizingMaskIntoConstraints = NO;
+ [safeAreaOverlay.topAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.topAnchor].active = YES;
+ [safeAreaOverlay.leftAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.leftAnchor].active = YES;
+ [safeAreaOverlay.rightAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.rightAnchor].active = YES;
+ [safeAreaOverlay.bottomAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.bottomAnchor].active = YES;
}
-#endif
}
return self;
@@ -156,7 +158,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
#ifndef QT_NO_DEBUG_STREAM
QString platformWindowDescription;
QDebug debug(&platformWindowDescription);
- debug.nospace() << "; " << m_qioswindow << ">";
+ debug.nospace() << "; " << self.platformWindow << ">";
NSRange lastCharacter = [description rangeOfComposedCharacterSequenceAtIndex:description.length - 1];
[description replaceCharactersInRange:lastCharacter withString:platformWindowDescription.toNSString()];
#endif
@@ -210,10 +212,10 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
if (!CGAffineTransformIsIdentity(self.transform))
qWarning() << self << "has a transform set. This is not supported.";
- QWindow *window = m_qioswindow->window();
+ QWindow *window = self.platformWindow->window();
QRect lastReportedGeometry = qt_window_private(window)->geometry;
QRect currentGeometry = QRectF::fromCGRect(self.frame).toRect();
- qCDebug(lcQpaWindow) << m_qioswindow << "new geometry is" << currentGeometry;
+ qCDebug(lcQpaWindow) << self.platformWindow << "new geometry is" << currentGeometry;
QWindowSystemInterface::handleGeometryChange(window, currentGeometry);
if (currentGeometry.size() != lastReportedGeometry.size()) {
@@ -237,29 +239,29 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
{
QRegion region;
- if (m_qioswindow->isExposed()) {
+ if (self.platformWindow->isExposed()) {
QSize bounds = QRectF::fromCGRect(self.layer.bounds).toRect().size();
- Q_ASSERT(m_qioswindow->geometry().size() == bounds);
- Q_ASSERT(self.hidden == !m_qioswindow->window()->isVisible());
+ Q_ASSERT(self.platformWindow->geometry().size() == bounds);
+ Q_ASSERT(self.hidden == !self.platformWindow->window()->isVisible());
region = QRect(QPoint(), bounds);
}
- qCDebug(lcQpaWindow) << m_qioswindow << region << "isExposed" << m_qioswindow->isExposed();
- QWindowSystemInterface::handleExposeEvent(m_qioswindow->window(), region);
+ qCDebug(lcQpaWindow) << self.platformWindow << region << "isExposed" << self.platformWindow->isExposed();
+ QWindowSystemInterface::handleExposeEvent(self.platformWindow->window(), region);
}
- (void)safeAreaInsetsDidChange
{
- QWindowSystemInterface::handleSafeAreaMarginsChanged(m_qioswindow->window());
+ QWindowSystemInterface::handleSafeAreaMarginsChanged(self.platformWindow->window());
}
// -------------------------------------------------------------------------
- (BOOL)canBecomeFirstResponder
{
- return !(m_qioswindow->window()->flags() & Qt::WindowDoesNotAcceptFocus);
+ return !(self.platformWindow->window()->flags() & Qt::WindowDoesNotAcceptFocus);
}
- (BOOL)becomeFirstResponder
@@ -280,10 +282,10 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
qImDebug() << self << "became first responder";
}
- if (qGuiApp->focusWindow() != m_qioswindow->window())
- QWindowSystemInterface::handleWindowActivated(m_qioswindow->window());
+ if (qGuiApp->focusWindow() != self.platformWindow->window())
+ QWindowSystemInterface::handleWindowActivated(self.platformWindow->window());
else
- qImDebug() << m_qioswindow->window() << "already active, not sending window activation";
+ qImDebug() << self.platformWindow->window() << "already active, not sending window activation";
return YES;
}
@@ -349,19 +351,17 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
QTouchDevice *touchDevice = QIOSIntegration::instance()->touchDevice();
QTouchDevice::Capabilities touchCapabilities = touchDevice->capabilities();
- if (__builtin_available(iOS 9, *)) {
- if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)
- touchCapabilities |= QTouchDevice::Pressure;
- else
- touchCapabilities &= ~QTouchDevice::Pressure;
- }
+ if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)
+ touchCapabilities |= QTouchDevice::Pressure;
+ else
+ touchCapabilities &= ~QTouchDevice::Pressure;
touchDevice->setCapabilities(touchCapabilities);
}
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
- if (m_qioswindow->window()->flags() & Qt::WindowTransparentForInput)
+ if (self.platformWindow->window()->flags() & Qt::WindowTransparentForInput)
return NO;
return [super pointInside:point withEvent:event];
}
@@ -378,7 +378,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
for (UITouch *cTouch in cTouches) {
QPointF localViewPosition = QPointF::fromCGPoint([cTouch preciseLocationInView:self]);
QPoint localViewPositionI = localViewPosition.toPoint();
- QPointF globalScreenPosition = m_qioswindow->mapToGlobal(localViewPositionI) +
+ QPointF globalScreenPosition = self.platformWindow->mapToGlobal(localViewPositionI) +
(localViewPosition - localViewPositionI);
qreal pressure = cTouch.force / cTouch.maximumPossibleForce;
// azimuth unit vector: +x to the right, +y going downwards
@@ -391,7 +391,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
qCDebug(lcQpaTablet) << i << ":" << timeStamp << localViewPosition << pressure << state << "azimuth" << azimuth.dx << azimuth.dy
<< "angle" << azimuthAngle << "altitude" << cTouch.altitudeAngle
<< "xTilt" << qBound(-60.0, altitudeAngle * azimuth.dx, 60.0) << "yTilt" << qBound(-60.0, altitudeAngle * azimuth.dy, 60.0);
- QWindowSystemInterface::handleTabletEvent(m_qioswindow->window(), timeStamp, localViewPosition, globalScreenPosition,
+ QWindowSystemInterface::handleTabletEvent(self.platformWindow->window(), timeStamp, localViewPosition, globalScreenPosition,
// device, pointerType, buttons
QTabletEvent::RotationStylus, QTabletEvent::Pen, state == Qt::TouchPointReleased ? Qt::NoButton : Qt::LeftButton,
// pressure, xTilt, yTilt
@@ -415,12 +415,12 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
// just map from the local view position to global coordinates.
// tvOS: all touches start at the center of the screen and move from there.
QPoint localViewPosition = QPointF::fromCGPoint([uiTouch locationInView:self]).toPoint();
- QPoint globalScreenPosition = m_qioswindow->mapToGlobal(localViewPosition);
+ QPoint globalScreenPosition = self.platformWindow->mapToGlobal(localViewPosition);
touchPoint.area = QRectF(globalScreenPosition, QSize(0, 0));
// FIXME: Do we really need to support QTouchDevice::NormalizedPosition?
- QSize screenSize = m_qioswindow->screen()->geometry().size();
+ QSize screenSize = self.platformWindow->screen()->geometry().size();
touchPoint.normalPosition = QPointF(globalScreenPosition.x() / screenSize.width(),
globalScreenPosition.y() / screenSize.height());
@@ -451,10 +451,10 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
// alert dialog, will fail to recognize. To be on the safe side, we deliver
// the event asynchronously.
QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::AsynchronousDelivery>(
- m_qioswindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values());
+ self.platformWindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values());
} else {
QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::SynchronousDelivery>(
- m_qioswindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values());
+ self.platformWindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values());
}
}
@@ -482,8 +482,8 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
#endif
}
- if (m_qioswindow->shouldAutoActivateWindow() && m_activeTouches.size() == 1) {
- QPlatformWindow *topLevel = m_qioswindow;
+ if (self.platformWindow->shouldAutoActivateWindow() && m_activeTouches.size() == 1) {
+ QPlatformWindow *topLevel = self.platformWindow;
while (QPlatformWindow *p = topLevel->parent())
topLevel = p;
if (topLevel->window() != QGuiApplication::focusWindow())
@@ -553,7 +553,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
NSTimeInterval timestamp = event ? event.timestamp : [[NSProcessInfo processInfo] systemUptime];
QIOSIntegration *iosIntegration = static_cast<QIOSIntegration *>(QGuiApplicationPrivate::platformIntegration());
- QWindowSystemInterface::handleTouchCancelEvent(m_qioswindow->window(), ulong(timestamp * 1000), iosIntegration->touchDevice());
+ QWindowSystemInterface::handleTouchCancelEvent(self.platformWindow->window(), ulong(timestamp * 1000), iosIntegration->touchDevice());
}
- (int)mapPressTypeToKey:(UIPress*)press
@@ -581,7 +581,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
int key = [self mapPressTypeToKey:press];
if (key == Qt::Key_unknown)
continue;
- if (QWindowSystemInterface::handleKeyEvent(m_qioswindow->window(), type, key, Qt::NoModifier))
+ if (QWindowSystemInterface::handleKeyEvent(self.platformWindow->window(), type, key, Qt::NoModifier))
handled = true;
}
@@ -635,7 +635,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
- (QWindow *)qwindow
{
if ([self isKindOfClass:[QUIView class]]) {
- if (QT_PREPEND_NAMESPACE(QIOSWindow) *w = static_cast<QUIView *>(self)->m_qioswindow)
+ if (QT_PREPEND_NAMESPACE(QIOSWindow) *w = static_cast<QUIView *>(self).platformWindow)
return w->window();
}
return nil;
@@ -662,18 +662,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
- (UIEdgeInsets)qt_safeAreaInsets
{
-#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_NA, 110000, 110000, __WATCHOS_NA)
- if (__builtin_available(iOS 11, tvOS 11, *))
- return self.safeAreaInsets;
-#endif
-
- // Fallback for iOS < 11
- UIEdgeInsets safeAreaInsets = UIEdgeInsetsZero;
- CGPoint topInset = [self convertPoint:CGPointMake(0, self.viewController.topLayoutGuide.length) fromView:nil];
- CGPoint bottomInset = [self convertPoint:CGPointMake(0, self.viewController.bottomLayoutGuide.length) fromView:nil];
- safeAreaInsets.top = topInset.y;
- safeAreaInsets.bottom = bottomInset.y;
- return safeAreaInsets;
+ return self.safeAreaInsets;
}
@end
diff --git a/src/plugins/platforms/ios/quiview_accessibility.mm b/src/plugins/platforms/ios/quiview_accessibility.mm
index 69a4d375bd..a3f4156a59 100644
--- a/src/plugins/platforms/ios/quiview_accessibility.mm
+++ b/src/plugins/platforms/ios/quiview_accessibility.mm
@@ -49,8 +49,9 @@
if (!iface || iface->state().invisible || (iface->text(QAccessible::Name).isEmpty() && iface->text(QAccessible::Value).isEmpty() && iface->text(QAccessible::Description).isEmpty()))
return;
QAccessible::Id accessibleId = QAccessible::uniqueId(iface);
- UIAccessibilityElement *elem = [[QMacAccessibilityElement alloc] initWithId: accessibleId withAccessibilityContainer: self];
- [m_accessibleElements addObject:[elem autorelease]];
+ UIAccessibilityElement *elem = [[QT_MANGLE_NAMESPACE(QMacAccessibilityElement) alloc] initWithId:accessibleId withAccessibilityContainer:self];
+ [m_accessibleElements addObject:elem];
+ [elem release];
}
- (void)createAccessibleContainer:(QAccessibleInterface *)iface
@@ -73,7 +74,7 @@
if ([m_accessibleElements count])
return;
- QWindow *win = m_qioswindow->window();
+ QWindow *win = self.platformWindow->window();
QAccessibleInterface *iface = win->accessibleRoot();
if (iface)
[self createAccessibleContainer: iface];
diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro
index e61887618f..5bf2b77421 100644
--- a/src/plugins/platforms/platforms.pro
+++ b/src/plugins/platforms/platforms.pro
@@ -46,6 +46,8 @@ haiku {
SUBDIRS += haiku
}
+wasm: SUBDIRS = wasm
+
qtConfig(mirclient): SUBDIRS += mirclient
qtConfig(integrityfb): SUBDIRS += integrity
diff --git a/src/plugins/platforms/qnx/qqnxglcontext.cpp b/src/plugins/platforms/qnx/qqnxglcontext.cpp
index 2031de308c..1d030ba1aa 100644
--- a/src/plugins/platforms/qnx/qqnxglcontext.cpp
+++ b/src/plugins/platforms/qnx/qqnxglcontext.cpp
@@ -64,7 +64,7 @@ static QEGLPlatformContext::Flags makeFlags()
{
QEGLPlatformContext::Flags result = 0;
- if (!QQnxIntegration::options().testFlag(QQnxIntegration::SurfacelessEGLContext))
+ if (!QQnxIntegration::instance()->options().testFlag(QQnxIntegration::SurfacelessEGLContext))
result |= QEGLPlatformContext::NoSurfaceless;
return result;
diff --git a/src/plugins/platforms/qnx/qqnxglobal.cpp b/src/plugins/platforms/qnx/qqnxglobal.cpp
index 6b3cc6bebf..c17f6a7546 100644
--- a/src/plugins/platforms/qnx/qqnxglobal.cpp
+++ b/src/plugins/platforms/qnx/qqnxglobal.cpp
@@ -45,9 +45,9 @@ QT_BEGIN_NAMESPACE
void qScreenCheckError(int rc, const char *funcInfo, const char *message, bool critical)
{
- if (!rc && (QQnxIntegration::options() & QQnxIntegration::AlwaysFlushScreenContext)
- && QQnxIntegration::screenContext() != 0) {
- rc = screen_flush_context(QQnxIntegration::screenContext(), 0);
+ if (!rc && (QQnxIntegration::instance()->options() & QQnxIntegration::AlwaysFlushScreenContext)
+ && QQnxIntegration::instance()->screenContext() != 0) {
+ rc = screen_flush_context(QQnxIntegration::instance()->screenContext(), 0);
}
if (Q_UNLIKELY(rc)) {
diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp
index dc4ebdf699..8c8521325c 100644
--- a/src/plugins/platforms/qnx/qqnxintegration.cpp
+++ b/src/plugins/platforms/qnx/qqnxintegration.cpp
@@ -99,8 +99,7 @@
QT_BEGIN_NAMESPACE
-QQnxWindowMapper QQnxIntegration::ms_windowMapper;
-QMutex QQnxIntegration::ms_windowMapperMutex;
+QQnxIntegration *QQnxIntegration::ms_instance;
static inline QQnxIntegration::Options parseOptions(const QStringList &paramList)
{
@@ -124,6 +123,22 @@ static inline QQnxIntegration::Options parseOptions(const QStringList &paramList
return options;
}
+static inline int getContextCapabilities(const QStringList &paramList)
+{
+ QString contextCapabilitiesPrefix = QStringLiteral("screen-context-capabilities=");
+ int contextCapabilities = SCREEN_APPLICATION_CONTEXT;
+ for (const QString &param : paramList) {
+ if (param.startsWith(contextCapabilitiesPrefix)) {
+ QStringRef value = param.midRef(contextCapabilitiesPrefix.length());
+ bool ok = false;
+ contextCapabilities = value.toInt(&ok, 0);
+ if (!ok)
+ contextCapabilities = SCREEN_APPLICATION_CONTEXT;
+ }
+ }
+ return contextCapabilities;
+}
+
QQnxIntegration::QQnxIntegration(const QStringList &paramList)
: QPlatformIntegration()
, m_screenEventThread(0)
@@ -147,11 +162,15 @@ QQnxIntegration::QQnxIntegration(const QStringList &paramList)
, m_drag(new QSimpleDrag())
#endif
{
- ms_options = parseOptions(paramList);
+ ms_instance = this;
+ m_options = parseOptions(paramList);
qIntegrationDebug();
+
// Open connection to QNX composition manager
- Q_SCREEN_CRITICALERROR(screen_create_context(&ms_screenContext, SCREEN_APPLICATION_CONTEXT),
- "Failed to create screen context");
+ if (screen_create_context(&m_screenContext, getContextCapabilities(paramList))) {
+ qFatal("%s - Screen: Failed to create screen context - Error: %s (%i)",
+ Q_FUNC_INFO, strerror(errno), errno);
+ }
#if QT_CONFIG(qqnx_pps)
// Create/start navigator event notifier
@@ -168,7 +187,8 @@ QQnxIntegration::QQnxIntegration(const QStringList &paramList)
#endif
// Create/start event thread
- m_screenEventThread = new QQnxScreenEventThread(ms_screenContext, m_screenEventHandler);
+ m_screenEventThread = new QQnxScreenEventThread(m_screenContext);
+ m_screenEventHandler->setScreenEventThread(m_screenEventThread);
m_screenEventThread->start();
#if QT_CONFIG(qqnx_pps)
@@ -244,7 +264,7 @@ QQnxIntegration::~QQnxIntegration()
destroyDisplays();
// Close connection to QNX composition manager
- screen_destroy_context(ms_screenContext);
+ screen_destroy_context(m_screenContext);
#if !defined(QT_NO_OPENGL)
// Cleanup global OpenGL resources
@@ -268,6 +288,8 @@ QQnxIntegration::~QQnxIntegration()
// Destroy navigator interface
delete m_navigator;
+ ms_instance = nullptr;
+
qIntegrationDebug("platform plugin shutdown end");
}
@@ -296,10 +318,10 @@ QPlatformWindow *QQnxIntegration::createPlatformWindow(QWindow *window) const
const bool needRootWindow = options() & RootWindow;
switch (surfaceType) {
case QSurface::RasterSurface:
- return new QQnxRasterWindow(window, ms_screenContext, needRootWindow);
+ return new QQnxRasterWindow(window, m_screenContext, needRootWindow);
#if !defined(QT_NO_OPENGL)
case QSurface::OpenGLSurface:
- return new QQnxEglWindow(window, ms_screenContext, needRootWindow);
+ return new QQnxEglWindow(window, m_screenContext, needRootWindow);
#endif
default:
qFatal("QQnxWindow: unsupported window API");
@@ -433,7 +455,7 @@ QPlatformDrag *QQnxIntegration::drag() const
QVariant QQnxIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
{
qIntegrationDebug();
- if ((hint == ShowIsFullScreen) && (ms_options & FullScreenApplication))
+ if ((hint == ShowIsFullScreen) && (m_options & FullScreenApplication))
return true;
return QPlatformIntegration::styleHint(hint);
@@ -447,25 +469,25 @@ QPlatformServices * QQnxIntegration::services() const
QWindow *QQnxIntegration::window(screen_window_t qnxWindow)
{
qIntegrationDebug();
- QMutexLocker locker(&ms_windowMapperMutex);
+ QMutexLocker locker(&m_windowMapperMutex);
Q_UNUSED(locker);
- return ms_windowMapper.value(qnxWindow, 0);
+ return m_windowMapper.value(qnxWindow, 0);
}
void QQnxIntegration::addWindow(screen_window_t qnxWindow, QWindow *window)
{
qIntegrationDebug();
- QMutexLocker locker(&ms_windowMapperMutex);
+ QMutexLocker locker(&m_windowMapperMutex);
Q_UNUSED(locker);
- ms_windowMapper.insert(qnxWindow, window);
+ m_windowMapper.insert(qnxWindow, window);
}
void QQnxIntegration::removeWindow(screen_window_t qnxWindow)
{
qIntegrationDebug();
- QMutexLocker locker(&ms_windowMapperMutex);
+ QMutexLocker locker(&m_windowMapperMutex);
Q_UNUSED(locker);
- ms_windowMapper.remove(qnxWindow);
+ m_windowMapper.remove(qnxWindow);
}
void QQnxIntegration::createDisplays()
@@ -473,7 +495,7 @@ void QQnxIntegration::createDisplays()
qIntegrationDebug();
// Query number of displays
int displayCount = 0;
- int result = screen_get_context_property_iv(ms_screenContext, SCREEN_PROPERTY_DISPLAY_COUNT,
+ int result = screen_get_context_property_iv(m_screenContext, SCREEN_PROPERTY_DISPLAY_COUNT,
&displayCount);
Q_SCREEN_CRITICALERROR(result, "Failed to query display count");
@@ -484,7 +506,7 @@ void QQnxIntegration::createDisplays()
// Get all displays
screen_display_t *displays = (screen_display_t *)alloca(sizeof(screen_display_t) * displayCount);
- result = screen_get_context_property_pv(ms_screenContext, SCREEN_PROPERTY_DISPLAYS,
+ result = screen_get_context_property_pv(m_screenContext, SCREEN_PROPERTY_DISPLAYS,
(void **)displays);
Q_SCREEN_CRITICALERROR(result, "Failed to query displays");
@@ -510,7 +532,7 @@ void QQnxIntegration::createDisplays()
void QQnxIntegration::createDisplay(screen_display_t display, bool isPrimary)
{
- QQnxScreen *screen = new QQnxScreen(ms_screenContext, display, isPrimary);
+ QQnxScreen *screen = new QQnxScreen(m_screenContext, display, isPrimary);
m_screens.append(screen);
screenAdded(screen);
screen->adjustOrientation();
@@ -559,14 +581,14 @@ QQnxScreen *QQnxIntegration::primaryDisplay() const
return m_screens.first();
}
-QQnxIntegration::Options QQnxIntegration::options()
+QQnxIntegration::Options QQnxIntegration::options() const
{
- return ms_options;
+ return m_options;
}
screen_context_t QQnxIntegration::screenContext()
{
- return ms_screenContext;
+ return m_screenContext;
}
QQnxNavigatorEventHandler *QQnxIntegration::navigatorEventHandler()
@@ -574,10 +596,6 @@ QQnxNavigatorEventHandler *QQnxIntegration::navigatorEventHandler()
return m_navigatorEventHandler;
}
-screen_context_t QQnxIntegration::ms_screenContext = 0;
-
-QQnxIntegration::Options QQnxIntegration::ms_options = 0;
-
bool QQnxIntegration::supportsNavigatorEvents() const
{
// If QQNX_PPS is defined then we have navigator
diff --git a/src/plugins/platforms/qnx/qqnxintegration.h b/src/plugins/platforms/qnx/qqnxintegration.h
index f844a7508c..2993607489 100644
--- a/src/plugins/platforms/qnx/qqnxintegration.h
+++ b/src/plugins/platforms/qnx/qqnxintegration.h
@@ -88,6 +88,8 @@ public:
explicit QQnxIntegration(const QStringList &paramList);
~QQnxIntegration();
+ static QQnxIntegration *instance() { return ms_instance; }
+
bool hasCapability(QPlatformIntegration::Capability cap) const override;
QPlatformWindow *createPlatformWindow(QWindow *window) const override;
@@ -121,15 +123,15 @@ public:
QPlatformServices *services() const override;
- static QWindow *window(screen_window_t qnxWindow);
+ QWindow *window(screen_window_t qnxWindow);
QQnxScreen *screenForNative(screen_display_t qnxScreen) const;
void createDisplay(screen_display_t display, bool isPrimary);
void removeDisplay(QQnxScreen *screen);
QQnxScreen *primaryDisplay() const;
- static Options options();
- static screen_context_t screenContext();
+ Options options() const;
+ screen_context_t screenContext();
QQnxNavigatorEventHandler *navigatorEventHandler();
@@ -137,10 +139,10 @@ private:
void createDisplays();
void destroyDisplays();
- static void addWindow(screen_window_t qnxWindow, QWindow *window);
- static void removeWindow(screen_window_t qnxWindow);
+ void addWindow(screen_window_t qnxWindow, QWindow *window);
+ void removeWindow(screen_window_t qnxWindow);
- static screen_context_t ms_screenContext;
+ screen_context_t m_screenContext;
QQnxScreenEventThread *m_screenEventThread;
QQnxNavigatorEventHandler *m_navigatorEventHandler;
QQnxAbstractVirtualKeyboard *m_virtualKeyboard;
@@ -162,10 +164,12 @@ private:
#if QT_CONFIG(draganddrop)
QSimpleDrag *m_drag;
#endif
- static QQnxWindowMapper ms_windowMapper;
- static QMutex ms_windowMapperMutex;
+ QQnxWindowMapper m_windowMapper;
+ QMutex m_windowMapperMutex;
+
+ Options m_options;
- static Options ms_options;
+ static QQnxIntegration *ms_instance;
friend class QQnxWindow;
};
diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
index ff1133aaa7..e4843cb438 100644
--- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
+++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
@@ -218,36 +218,39 @@ void QQnxScreenEventHandler::injectKeyboardEvent(int flags, int sym, int modifie
void QQnxScreenEventHandler::setScreenEventThread(QQnxScreenEventThread *eventThread)
{
m_eventThread = eventThread;
+ connect(m_eventThread, &QQnxScreenEventThread::eventsPending,
+ this, &QQnxScreenEventHandler::processEvents);
}
-void QQnxScreenEventHandler::processEventsFromScreenThread()
+void QQnxScreenEventHandler::processEvents()
{
if (!m_eventThread)
return;
- QQnxScreenEventArray *events = m_eventThread->lock();
+ screen_event_t event = nullptr;
+ if (screen_create_event(&event) != 0)
+ return;
- for (int i = 0; i < events->size(); ++i) {
- screen_event_t event = events->at(i);
- if (!event)
- continue;
- (*events)[i] = 0;
+ int count = 0;
+ for (;;) {
+ if (screen_get_event(m_eventThread->context(), event, 0) != 0)
+ break;
- m_eventThread->unlock();
+ int type = SCREEN_EVENT_NONE;
+ screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &type);
+ if (type == SCREEN_EVENT_NONE)
+ break;
+ ++count;
long result = 0;
QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance();
bool handled = dispatcher && dispatcher->filterNativeEvent(QByteArrayLiteral("screen_event_t"), event, &result);
if (!handled)
handleEvent(event);
- screen_destroy_event(event);
-
- m_eventThread->lock();
}
- events->clear();
-
- m_eventThread->unlock();
+ m_eventThread->armEventsPending(count);
+ screen_destroy_event(event);
}
void QQnxScreenEventHandler::handleKeyboardEvent(screen_event_t event)
@@ -323,11 +326,11 @@ void QQnxScreenEventHandler::handlePointerEvent(screen_event_t event)
"Failed to query event wheel delta");
// Map window handle to top-level QWindow
- QWindow *w = QQnxIntegration::window(qnxWindow);
+ QWindow *w = QQnxIntegration::instance()->window(qnxWindow);
// Generate enter and leave events as needed.
if (qnxWindow != m_lastMouseWindow) {
- QWindow *wOld = QQnxIntegration::window(m_lastMouseWindow);
+ QWindow *wOld = QQnxIntegration::instance()->window(m_lastMouseWindow);
if (wOld) {
QWindowSystemInterface::handleLeaveEvent(wOld);
@@ -435,11 +438,11 @@ void QQnxScreenEventHandler::handleTouchEvent(screen_event_t event, int qnxType)
if (touchId < MaximumTouchPoints) {
// Map window handle to top-level QWindow
- QWindow *w = QQnxIntegration::window(qnxWindow);
+ QWindow *w = QQnxIntegration::instance()->window(qnxWindow);
// Generate enter and leave events as needed.
if (qnxWindow != m_lastMouseWindow) {
- QWindow *wOld = QQnxIntegration::window(m_lastMouseWindow);
+ QWindow *wOld = QQnxIntegration::instance()->window(m_lastMouseWindow);
if (wOld) {
QWindowSystemInterface::handleLeaveEvent(wOld);
@@ -529,7 +532,7 @@ void QQnxScreenEventHandler::handleCloseEvent(screen_event_t event)
Q_EMIT windowClosed(window);
// Map window handle to top-level QWindow
- QWindow *w = QQnxIntegration::window(window);
+ QWindow *w = QQnxIntegration::instance()->window(window);
if (w != 0)
QWindowSystemInterface::handleCloseEvent(w);
}
@@ -629,7 +632,7 @@ void QQnxScreenEventHandler::handleKeyboardFocusPropertyEvent(screen_window_t wi
if (Q_UNLIKELY(window && screen_get_window_property_iv(window, SCREEN_PROPERTY_FOCUS, &focus) != 0))
qFatal("QQnx: failed to query keyboard focus property, errno=%d", errno);
- QWindow *focusWindow = QQnxIntegration::window(window);
+ QWindow *focusWindow = QQnxIntegration::instance()->window(window);
if (m_focusLostTimer != -1) {
killTimer(m_focusLostTimer);
@@ -655,7 +658,7 @@ void QQnxScreenEventHandler::handleGeometryPropertyEvent(screen_window_t window)
}
QRect rect(pos[0], pos[1], size[0], size[1]);
- QWindow *qtWindow = QQnxIntegration::window(window);
+ QWindow *qtWindow = QQnxIntegration::instance()->window(window);
if (qtWindow) {
qtWindow->setGeometry(rect);
QWindowSystemInterface::handleGeometryChange(qtWindow, rect);
diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.h b/src/plugins/platforms/qnx/qqnxscreeneventhandler.h
index 40697b7a09..b35967610e 100644
--- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.h
+++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.h
@@ -74,7 +74,7 @@ protected:
void timerEvent(QTimerEvent *event) override;
private Q_SLOTS:
- void processEventsFromScreenThread();
+ void processEvents();
private:
void handleKeyboardEvent(screen_event_t event);
diff --git a/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp b/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp
index c56d9a8da4..1b5f3b4954 100644
--- a/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp
+++ b/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp
@@ -1,5 +1,6 @@
/***************************************************************************
**
+** Copyright (C) 2017 QNX Software Systems. All rights reserved.
** Copyright (C) 2011 - 2012 Research In Motion
** Contact: https://www.qt.io/licensing/
**
@@ -55,116 +56,101 @@
#define qScreenEventThreadDebug QT_NO_QDEBUG_MACRO
#endif
-QQnxScreenEventThread::QQnxScreenEventThread(screen_context_t context, QQnxScreenEventHandler *screenEventHandler)
- : QThread(),
- m_screenContext(context),
- m_screenEventHandler(screenEventHandler),
- m_quit(false)
+static const int c_screenCode = _PULSE_CODE_MINAVAIL + 0;
+static const int c_armCode = _PULSE_CODE_MINAVAIL + 1;
+static const int c_quitCode = _PULSE_CODE_MINAVAIL + 2;
+
+QQnxScreenEventThread::QQnxScreenEventThread(screen_context_t context)
+ : QThread()
+ , m_screenContext(context)
{
- screenEventHandler->setScreenEventThread(this);
- connect(this, SIGNAL(eventPending()), screenEventHandler, SLOT(processEventsFromScreenThread()), Qt::QueuedConnection);
- connect(this, SIGNAL(finished()), screenEventHandler, SLOT(processEventsFromScreenThread()), Qt::QueuedConnection);
+ m_channelId = ChannelCreate(_NTO_CHF_DISCONNECT | _NTO_CHF_UNBLOCK | _NTO_CHF_PRIVATE);
+ if (m_channelId == -1) {
+ qFatal("QQnxScreenEventThread: Can't continue without a channel");
+ }
+
+ m_connectionId = ConnectAttach(0, 0, m_channelId, _NTO_SIDE_CHANNEL, 0);
+ if (m_connectionId == -1) {
+ ChannelDestroy(m_channelId);
+ qFatal("QQnxScreenEventThread: Can't continue without a channel connection");
+ }
+
+ struct sigevent screenEvent;
+ SIGEV_PULSE_INIT(&screenEvent, m_connectionId, SIGEV_PULSE_PRIO_INHERIT, c_screenCode, 0);
+
+ screen_notify(m_screenContext, SCREEN_NOTIFY_EVENT, nullptr, &screenEvent);
}
QQnxScreenEventThread::~QQnxScreenEventThread()
{
// block until thread terminates
shutdown();
-}
-void QQnxScreenEventThread::injectKeyboardEvent(int flags, int sym, int mod, int scan, int cap)
-{
- QQnxScreenEventHandler::injectKeyboardEvent(flags, sym, mod, scan, cap);
-}
-
-QQnxScreenEventArray *QQnxScreenEventThread::lock()
-{
- m_mutex.lock();
- return &m_events;
-}
-
-void QQnxScreenEventThread::unlock()
-{
- m_mutex.unlock();
+ ConnectDetach(m_connectionId);
+ ChannelDestroy(m_channelId);
}
void QQnxScreenEventThread::run()
{
qScreenEventThreadDebug("screen event thread started");
- int errorCounter = 0;
- // loop indefinitely
- while (!m_quit) {
- screen_event_t event;
-
- // create screen event
- Q_SCREEN_CHECKERROR(screen_create_event(&event), "Failed to create screen event");
-
- // block until screen event is available
- const int error = screen_get_event(m_screenContext, event, -1);
- Q_SCREEN_CRITICALERROR(error, "Failed to get screen event");
- // Only allow 50 consecutive errors before we exit the thread
- if (error) {
- errorCounter++;
- if (errorCounter > 50)
- m_quit = true;
-
- screen_destroy_event(event);
- continue;
- } else {
- errorCounter = 0;
- }
-
- // process received event
- // get the event type
- int qnxType;
- Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &qnxType),
- "Failed to query screen event type");
-
- if (qnxType == SCREEN_EVENT_USER) {
- // treat all user events as shutdown requests
- qScreenEventThreadDebug("QNX user screen event");
- m_quit = true;
- } else {
- m_mutex.lock();
- m_events << event;
- m_mutex.unlock();
- emit eventPending();
- }
+ while (1) {
+ struct _pulse msg;
+ memset(&msg, 0, sizeof(msg));
+ int receiveId = MsgReceive(m_channelId, &msg, sizeof(msg), nullptr);
+ if (receiveId == 0 && msg.code == c_quitCode)
+ break;
+ else if (receiveId == 0)
+ handlePulse(msg);
+ else if (receiveId > 0)
+ qWarning() << "Unexpected message" << msg.code;
+ else
+ qWarning() << "MsgReceive error" << strerror(errno);
}
qScreenEventThreadDebug("screen event thread stopped");
-
- // cleanup
- m_mutex.lock();
- Q_FOREACH (screen_event_t event, m_events) {
- screen_destroy_event(event);
- }
- m_events.clear();
- m_mutex.unlock();
}
-void QQnxScreenEventThread::shutdown()
+void QQnxScreenEventThread::armEventsPending(int count)
{
- screen_event_t event;
+ MsgSendPulse(m_connectionId, SIGEV_PULSE_PRIO_INHERIT, c_armCode, count);
+}
- // create screen event
- Q_SCREEN_CHECKERROR(screen_create_event(&event),
- "Failed to create screen event");
+void QQnxScreenEventThread::handleScreenPulse(const struct _pulse &msg)
+{
+ Q_UNUSED(msg);
- // set the event type as user
- int type = SCREEN_EVENT_USER;
- Q_SCREEN_CHECKERROR(screen_set_event_property_iv(event, SCREEN_PROPERTY_TYPE, &type),
- "Failed to set screen type");
+ ++m_screenPulsesSinceLastArmPulse;
+ if (m_emitNeededOnNextScreenPulse) {
+ m_emitNeededOnNextScreenPulse = false;
+ Q_EMIT eventsPending();
+ }
+}
- // NOTE: ignore SCREEN_PROPERTY_USER_DATA; treat all user events as shutdown events
+void QQnxScreenEventThread::handleArmPulse(const struct _pulse &msg)
+{
+ if (msg.value.sival_int == 0 && m_screenPulsesSinceLastArmPulse == 0) {
+ m_emitNeededOnNextScreenPulse = true;
+ } else {
+ m_screenPulsesSinceLastArmPulse = 0;
+ m_emitNeededOnNextScreenPulse = false;
+ Q_EMIT eventsPending();
+ }
+}
- // post event to event loop so it will wake up and die
- Q_SCREEN_CHECKERROR(screen_send_event(m_screenContext, event, getpid()),
- "Failed to set screen event type");
+void QQnxScreenEventThread::handlePulse(const struct _pulse &msg)
+{
+ if (msg.code == c_screenCode)
+ handleScreenPulse(msg);
+ else if (msg.code == c_armCode)
+ handleArmPulse(msg);
+ else
+ qWarning() << "Unexpected pulse" << msg.code;
+}
- // cleanup
- screen_destroy_event(event);
+void QQnxScreenEventThread::shutdown()
+{
+ MsgSendPulse(m_connectionId, SIGEV_PULSE_PRIO_INHERIT, c_quitCode, 0);
qScreenEventThreadDebug("screen event thread shutdown begin");
diff --git a/src/plugins/platforms/qnx/qqnxscreeneventthread.h b/src/plugins/platforms/qnx/qqnxscreeneventthread.h
index 140f53aa50..3c8d197545 100644
--- a/src/plugins/platforms/qnx/qqnxscreeneventthread.h
+++ b/src/plugins/platforms/qnx/qqnxscreeneventthread.h
@@ -1,5 +1,6 @@
/***************************************************************************
**
+** Copyright (C) 2017 QNX Software Systems. All rights reserved.
** Copyright (C) 2011 - 2012 Research In Motion
** Contact: https://www.qt.io/licensing/
**
@@ -47,37 +48,34 @@
QT_BEGIN_NAMESPACE
-class QQnxScreenEventHandler;
-
-typedef QVarLengthArray<screen_event_t, 64> QQnxScreenEventArray;
-
class QQnxScreenEventThread : public QThread
{
Q_OBJECT
public:
- QQnxScreenEventThread(screen_context_t context, QQnxScreenEventHandler *screenEventHandler);
+ QQnxScreenEventThread(screen_context_t context);
~QQnxScreenEventThread();
- static void injectKeyboardEvent(int flags, int sym, int mod, int scan, int cap);
-
- QQnxScreenEventArray *lock();
- void unlock();
+ screen_context_t context() const { return m_screenContext; }
+ void armEventsPending(int count);
protected:
void run() override;
Q_SIGNALS:
- void eventPending();
+ void eventsPending();
private:
+ void handleScreenPulse(const struct _pulse &msg);
+ void handleArmPulse(const struct _pulse &msg);
+ void handlePulse(const struct _pulse &msg);
void shutdown();
+ int m_channelId;
+ int m_connectionId;
screen_context_t m_screenContext;
- QMutex m_mutex;
- QQnxScreenEventArray m_events;
- QQnxScreenEventHandler *m_screenEventHandler;
- bool m_quit;
+ bool m_emitNeededOnNextScreenPulse = true;
+ int m_screenPulsesSinceLastArmPulse = 0;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp
index 4a547aa158..2096bc789e 100644
--- a/src/plugins/platforms/qnx/qqnxwindow.cpp
+++ b/src/plugins/platforms/qnx/qqnxwindow.cpp
@@ -132,22 +132,12 @@ DECLARE_DEBUG_VAR(statistics)
setWindowProperty function of the native interface to set the \e qnxWindowGroup property
to the desired value, for example:
- \code
- QQuickView *view = new QQuickView(parent);
- view->create();
- QGuiApplication::platformNativeInterface()->setWindowProperty(view->handle(), "qnxWindowGroup",
- group);
- \endcode
+ \snippet code/src_plugins_platforms_qnx_qqnxwindow.cpp 0
To leave the current window group, one passes a null value for the property value,
for example:
- \code
- QQuickView *view = new QQuickView(parent);
- view->create();
- QGuiApplication::platformNativeInterface()->setWindowProperty(view->handle(), "qnxWindowGroup",
- QVariant());
- \endcode
+ \snippet code/src_plugins_platforms_qnx_qqnxwindow.cpp 1
\section1 Window Id
@@ -174,7 +164,9 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootW
// If a qnxInitialWindowGroup property is set on the window we'll take this as an
// indication that we want to create a child window and join that window group.
- const QVariant windowGroup = window->property("qnxInitialWindowGroup");
+ QVariant windowGroup = window->property("qnxInitialWindowGroup");
+ if (!windowGroup.isValid())
+ windowGroup = window->property("_q_platform_qnxParentGroup");
if (window->type() == Qt::CoverWindow) {
// Cover windows have to be top level to be accessible to window delegate (i.e. navigator)
@@ -194,7 +186,12 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootW
if (window->type() == Qt::Desktop) // A desktop widget does not need a libscreen window
return;
- if (m_isTopLevel) {
+ QVariant type = window->property("_q_platform_qnxWindowType");
+ if (type.isValid() && type.canConvert<int>()) {
+ Q_SCREEN_CHECKERROR(
+ screen_create_window_type(&m_window, m_screenContext, type.value<int>()),
+ "Could not create window");
+ } else if (m_isTopLevel) {
Q_SCREEN_CRITICALERROR(screen_create_window(&m_window, m_screenContext),
"Could not create top level window"); // Creates an application window
if (window->type() != Qt::CoverWindow) {
@@ -212,7 +209,9 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootW
// If the window has a qnxWindowId property, set this as the string id property. This generally
// needs to be done prior to joining any group as it might be used by the owner of the
// group to identify the window.
- const QVariant windowId = window->property("qnxWindowId");
+ QVariant windowId = window->property("qnxWindowId");
+ if (!windowId.isValid())
+ windowId = window->property("_q_platform_qnxWindowId");
if (windowId.isValid() && windowId.canConvert<QByteArray>()) {
QByteArray id = windowId.toByteArray();
Q_SCREEN_CHECKERROR(screen_set_window_property_cv(m_window, SCREEN_PROPERTY_ID_STRING,
@@ -262,7 +261,7 @@ QQnxWindow::~QQnxWindow()
Q_ASSERT(m_childWindows.size() == 0);
// Remove from plugin's window mapper
- QQnxIntegration::removeWindow(m_window);
+ QQnxIntegration::instance()->removeWindow(m_window);
// Remove from parent's Hierarchy.
removeFromParent();
@@ -471,7 +470,7 @@ void QQnxWindow::setScreen(QQnxScreen *platformScreen)
qWindowDebug("Moving window to different screen");
m_screen->removeWindow(this);
- if ((QQnxIntegration::options() & QQnxIntegration::RootWindow)) {
+ if ((QQnxIntegration::instance()->options() & QQnxIntegration::RootWindow)) {
screen_leave_window_group(m_window);
}
}
@@ -726,7 +725,7 @@ void QQnxWindow::initWindow()
m_exposed = false;
// Add window to plugin's window mapper
- QQnxIntegration::addWindow(m_window, window());
+ QQnxIntegration::instance()->addWindow(m_window, window());
// Qt never calls these setters after creating the window, so we need to do that ourselves here
setWindowState(window()->windowState());
@@ -823,7 +822,7 @@ void QQnxWindow::windowPosted()
bool QQnxWindow::shouldMakeFullScreen() const
{
return ((static_cast<QQnxScreen *>(screen())->rootWindow() == this)
- && (QQnxIntegration::options() & QQnxIntegration::FullScreenApplication));
+ && (QQnxIntegration::instance()->options() & QQnxIntegration::FullScreenApplication));
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/main.cpp b/src/plugins/platforms/wasm/main.cpp
new file mode 100644
index 0000000000..a4d23b4e0d
--- /dev/null
+++ b/src/plugins/platforms/wasm/main.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qpa/qplatformintegrationplugin.h>
+#include "qwasmintegration.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWasmIntegrationPlugin : public QPlatformIntegrationPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "wasm.json")
+public:
+ QPlatformIntegration *create(const QString &, const QStringList &) override;
+};
+
+QPlatformIntegration *QWasmIntegrationPlugin::create(const QString& system, const QStringList& paramList)
+{
+ Q_UNUSED(paramList);
+ if (!system.compare(QStringLiteral("wasm"), Qt::CaseInsensitive))
+ return new QWasmIntegration;
+
+ return nullptr;
+}
+
+QT_END_NAMESPACE
+
+#include "main.moc"
diff --git a/src/plugins/platforms/wasm/qtloader.js b/src/plugins/platforms/wasm/qtloader.js
new file mode 100644
index 0000000000..37a5308034
--- /dev/null
+++ b/src/plugins/platforms/wasm/qtloader.js
@@ -0,0 +1,516 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// QtLoader provides javascript API for managing Qt application modules.
+//
+// QtLoader provides API on top of Emscripten which supports common lifecycle
+// tasks such as displaying placeholder content while the module downloads,
+// handing application exits, and checking for browser wasm support.
+//
+// There are two usage modes:
+// * Managed: QtLoader owns and manages the HTML display elements like
+// the loader and canvas.
+// * External: The embedding HTML page owns the display elements. QtLoader
+// provides event callbacks which the page reacts to.
+//
+// Managed mode usage:
+//
+// var config = {
+// containerElements : [$("container-id")];
+// }
+// var qtLoader = QtLoader(config);
+// qtLoader.loadEmscriptenModule("applicationName");
+//
+// External mode.usage:
+//
+// var config = {
+// showLoader: function() {
+// loader.style.display = 'block'
+// canvas.style.display = 'hidden'
+// },
+// showCanvas: function() {
+// loader.style.display = 'hidden'
+// canvas.style.display = 'block'
+// return canvas;
+// }
+// }
+// var qtLoader = QtLoader(config);
+// qtLoader.loadEmscriptenModule("applicationName");
+//
+// Config keys
+//
+// containerElements : [container-element, ...]
+// One or more HTML elements. QtLoader will display loader elements
+// on these while loading the applicaton, and replace the loader with a
+// canvas on load complete.
+// showLoader : function(status, containerElement)
+// Optional loading element constructor function. Implement to create
+// a custom loading screen. This function may be called multiple times,
+// while preparing the application binary. "status" is a string
+// containing the loading sub-status, and may be either "Downloading",
+// or "Compiling". The browser may be using streaming compilation, in
+// which case the wasm module is compiled during downloading and the
+// there is no separate compile step.
+// showCanvas : function(containerElement)
+// Optional canvas constructor function. Implement to create custom
+// canvas elements.
+// showExit : function(crashed, exitCode, containerElement)
+// Optional exited element constructor function.
+// showError : function(crashed, exitCode, containerElement)
+// Optional error element constructor function.
+//
+// path : <string>
+// Prefix path for wasm file, realative to the loading HMTL file.
+// restartMode : "DoNotRestart", "RestartOnExit", "RestartOnCrash"
+// Controls whether the application should be reloaded on exits. The default is "DoNotRestart"
+// restartType : "RestartModule", "ReloadPage"
+// restartLimit : <int>
+// Restart attempts limit. The default is 10.
+// stdoutEnabled : <bool>
+// stderrEnabled : <bool>
+// environment : <object>
+// key-value environment variable pairs.
+//
+// QtLoader object API
+//
+// webAssemblySupported : bool
+// webGLSupported : bool
+// canLoadQt : bool
+// Reports if WebAssembly and WebGL are supported. These are requirements for
+// running Qt applications.
+// loadEmscriptenModule(applicationName)
+// Loads the application from the given emscripten javascript module file and wasm file
+// status
+// One of "Created", "Loading", "Running", "Exited".
+// crashed
+// Set to true if there was an unclean exit.
+// exitCode
+// main()/emscripten_force_exit() return code. Valid on status change to
+// "Exited", iff crashed is false.
+// exitText
+// Abort/exit message.
+
+
+var Module = {}
+
+function QtLoader(config)
+{
+ function webAssemblySupported() {
+ return typeof WebAssembly !== "undefined"
+ }
+
+ function webGLSupported() {
+ // We expect that WebGL is supported if WebAssembly is; however
+ // the GPU may be blacklisted.
+ try {
+ var canvas = document.createElement("canvas");
+ return !!(window.WebGLRenderingContext && (canvas.getContext("webgl") || canvas.getContext("experimental-webgl")));
+ } catch (e) {
+ return false;
+ }
+ }
+
+ function canLoadQt() {
+ // The current Qt implementation requires WebAssembly (asm.js is not in use),
+ // and also WebGL (there is no raster fallback).
+ return webAssemblySupported() && webGLSupported();
+ }
+
+ function removeChildren(element) {
+ while (element.firstChild) element.removeChild(element.firstChild);
+ }
+
+ // Set default state handler functions if needed
+ if (config.containerElements !== undefined) {
+ config.showError = config.showError || function(errorText, container) {
+ removeChildren(container);
+ var errorTextElement = document.createElement("text");
+ errorTextElement.className = "QtError"
+ errorTextElement.innerHTML = errorText;
+ return errorTextElement;
+ }
+
+ config.showLoader = config.showLoader || function(loadingState, container) {
+ removeChildren(container);
+ var loadingText = document.createElement("text");
+ loadingText.className = "QtLoading"
+ loadingText.innerHTML = '<p><center> ${loadingState}...</center><p>';
+ return loadingText;
+ };
+
+ config.showCanvas = config.showCanvas || function(container) {
+ removeChildren(container);
+ var canvas = document.createElement("canvas");
+ canvas.className = "QtCanvas"
+ canvas.style = "height: 100%; width: 100%;"
+ return canvas;
+ }
+
+ config.showExit = config.showExit || function(crashed, exitCode, container) {
+ if (!crashed)
+ return undefined;
+
+ removeChildren(container);
+ var fontSize = 54;
+ var crashSymbols = ["\u{1F615}", "\u{1F614}", "\u{1F644}", "\u{1F928}", "\u{1F62C}",
+ "\u{1F915}", "\u{2639}", "\u{1F62E}", "\u{1F61E}", "\u{1F633}"];
+ var symbolIndex = Math.floor(Math.random() * crashSymbols.length);
+ var errorHtml = `<font size='${fontSize}'> ${crashSymbols[symbolIndex]} </font>`
+ var errorElement = document.createElement("text");
+ errorElement.className = "QtExit"
+ errorElement.innerHTML = errorHtml;
+ return errorElement;
+ }
+ }
+
+ config.restartMode = config.restartMode || "DoNotRestart";
+ config.restartLimit = config.restartLimit || 10;
+
+ if (config.stdoutEnabled === undefined) config.stdoutEnabled = true;
+ if (config.stderrEnabled === undefined) config.stderrEnabled = true;
+
+ // Make sure config.path is defined and ends with "/" if needed
+ if (config.path === undefined)
+ config.path = "";
+ if (config.path.length > 0 && !config.path.endsWith("/"))
+ config.path = config.path.concat("/");
+
+ if (config.environment === undefined)
+ config.environment = {};
+
+ var publicAPI = {};
+ publicAPI.webAssemblySupported = webAssemblySupported();
+ publicAPI.webGLSupported = webGLSupported();
+ publicAPI.canLoadQt = canLoadQt();
+ publicAPI.canLoadApplication = canLoadQt();
+ publicAPI.status = undefined;
+ publicAPI.loadEmscriptenModule = loadEmscriptenModule;
+
+ restartCount = 0;
+
+ function fetchResource(filePath) {
+ var fullPath = config.path + filePath;
+ return fetch(fullPath).then(function(response) {
+ if (!response.ok) {
+ self.error = response.status + " " + response.statusText + " " + response.url;
+ setStatus("Error");
+ return Promise.reject(self.error)
+ } else {
+ return response;
+ }
+ });
+ }
+
+ function fetchText(filePath) {
+ return fetchResource(filePath).then(function(response) {
+ return response.text();
+ });
+ }
+
+ function fetchThenCompileWasm(response) {
+ return response.arrayBuffer().then(function(data) {
+ self.loaderSubState = "Compiling";
+ setStatus("Loading") // trigger loaderSubState udpate
+ return WebAssembly.compile(data);
+ });
+ }
+
+ function fetchCompileWasm(filePath) {
+ return fetchResource(filePath).then(function(response) {
+ if (typeof WebAssembly.compileStreaming !== "undefined") {
+ self.loaderSubState = "Downloading/Compiling";
+ setStatus("Loading");
+ return WebAssembly.compileStreaming(response).catch(function(error) {
+ // compileStreaming may/will fail if the server does not set the correct
+ // mime type (application/wasm) for the wasm file. Fall back to fetch,
+ // then compile in this case.
+ return fetchThenCompileWasm(response);
+ });
+ } else {
+ // Fall back to fetch, then compile if compileStreaming is not supported
+ return fetchThenCompileWasm(response);
+ }
+ });
+ }
+
+ function loadEmscriptenModule(applicationName) {
+
+ // Loading in qtloader.js goes through four steps:
+ // 1) Check prerequisites
+ // 2) Download resources
+ // 3) Configure the emscripten Module object
+ // 4) Start the emcripten runtime, after which emscripten takes over
+
+ // Check for Wasm & WebGL support; set error and return before downloading resources if missing
+ if (!webAssemblySupported()) {
+ self.error = "Error: WebAssembly is not supported"
+ setStatus("Error");
+ return;
+ }
+ if (!webGLSupported()) {
+ self.error = "Error: WebGL is not supported"
+ setStatus("Error");
+ return;
+ }
+
+ // Continue waiting if loadEmscriptenModule() is called again
+ if (publicAPI.status == "Loading")
+ return;
+ self.loaderSubState = "Downloading";
+ setStatus("Loading");
+
+ // Fetch emscripten generated javascript runtime
+ var emscriptenModuleSource = undefined
+ var emscriptenModuleSourcePromise = fetchText(applicationName + ".js").then(function(source) {
+ emscriptenModuleSource = source
+ });
+
+ // Fetch and compile wasm module
+ var wasmModule = undefined;
+ var wasmModulePromise = fetchCompileWasm(applicationName + ".wasm").then(function (module) {
+ wasmModule = module;
+ });
+
+ // Wait for all resources ready
+ Promise.all([emscriptenModuleSourcePromise, wasmModulePromise]).then(function(){
+ completeLoadEmscriptenModule(applicationName, emscriptenModuleSource, wasmModule);
+ }).catch(function(error) {
+ self.error = error;
+ setStatus("Error");
+ });
+ }
+
+ function completeLoadEmscriptenModule(applicationName, emscriptenModuleSource, wasmModule) {
+
+ // The wasm binary has been compiled into a module during resource download,
+ // and is ready to be instantiated. Define the instantiateWasm callback which
+ // emscripten will call to create the instance.
+ Module.instantiateWasm = function(imports, successCallback) {
+ return WebAssembly.instantiate(wasmModule, imports).then(function(instance) {
+ successCallback(instance);
+ return instance;
+ }, function(error) {
+ self.error = error;
+ setStatus("Error");
+ });
+ };
+
+ Module.locateFile = Module.locateFile || function(filename) {
+ return config.path + filename;
+ };
+
+ // Attach status callbacks
+ Module.setStatus = Module.setStatus || function(text) {
+ // Currently the only usable status update from this function
+ // is "Running..."
+ if (text.startsWith("Running"))
+ setStatus("Running");
+ };
+ Module.monitorRunDependencies = Module.monitorRunDependencies || function(left) {
+ // console.log("monitorRunDependencies " + left)
+ };
+
+ // Attach standard out/err callbacks.
+ Module.print = Module.print || function(text) {
+ if (config.stdoutEnabled)
+ console.log(text)
+ };
+ Module.printErr = Module.printErr || function(text) {
+ // Filter out OpenGL getProcAddress warnings. Qt tries to resolve
+ // all possible function/extension names at startup which causes
+ // emscripten to spam the console log with warnings.
+ if (text.startsWith !== undefined && text.startsWith("bad name in getProcAddress:"))
+ return;
+
+ if (config.stderrEnabled)
+ console.log(text)
+ };
+
+ // Error handling: set status to "Exited", update crashed and
+ // exitCode according to exit type.
+ // Emscripten will typically call printErr with the error text
+ // as well. Note that emscripten may also throw exceptions from
+ // async callbacks. These should be handled in window.onerror by user code.
+ Module.onAbort = Module.onAbort || function(text) {
+ publicAPI.crashed = true;
+ publicAPI.exitText = text;
+ setStatus("Exited");
+ };
+ Module.quit = Module.quit || function(code, exception) {
+ if (exception.name == "ExitStatus") {
+ // Clean exit with code
+ publicAPI.exitText = undefined
+ publicAPI.exitCode = code;
+ } else {
+ publicAPI.exitText = exception.toString();
+ publicAPI.crashed = true;
+ }
+ setStatus("Exited");
+ };
+
+ // Set environment variables
+ Module.preRun = Module.preRun || []
+ Module.preRun.push(function() {
+ for (var [key, value] of Object.entries(config.environment)) {
+ Module.ENV[key.toUpperCase()] = value;
+ }
+ });
+
+ config.restart = function() {
+
+ // Restart by reloading the page. This will wipe all state which means
+ // reload loops can't be prevented.
+ if (config.restartType == "ReloadPage") {
+ location.reload();
+ }
+
+ // Restart by readling the emscripten app module.
+ ++self.restartCount;
+ if (self.restartCount > config.restartLimit) {
+ self.error = "Error: This application has crashed too many times and has been disabled. Reload the page to try again."
+ setStatus("Error");
+ return;
+ }
+ loadEmscriptenModule(applicationName);
+ };
+
+ publicAPI.exitCode = undefined;
+ publicAPI.exitText = undefined;
+ publicAPI.crashed = false;
+
+ // Finally evaluate the emscripten application script, which will
+ // reference the global Module object created above.
+ self.eval(emscriptenModuleSource); // ES5 indirect global scope eval
+ }
+
+ function setErrorContent() {
+ if (config.containerElements === undefined) {
+ if (config.showError !== undefined)
+ config.showError(self.error);
+ return;
+ }
+
+ for (container of config.containerElements) {
+ var errorElement = config.showError(self.error, container);
+ container.appendChild(errorElement);
+ }
+ }
+
+ function setLoaderContent() {
+ if (config.containerElements === undefined) {
+ if (config.showLoader !== undefined)
+ config.showLoader(self.loaderSubState);
+ return;
+ }
+
+ for (container of config.containerElements) {
+ var loaderElement = config.showLoader(self.loaderSubState, container);
+ container.appendChild(loaderElement);
+ }
+ }
+
+ function setCanvasContent() {
+ var firstCanvas;
+ if (config.containerElements === undefined) {
+ firstCanvas = config.showCanvas();
+ } else {
+ for (container of config.containerElements) {
+ var canvasElement = config.showCanvas(container);
+ container.appendChild(canvasElement);
+ }
+ firstCanvas = config.containerElements[0].firstChild;
+ }
+
+ if (Module.canvas === undefined) {
+ Module.canvas = firstCanvas;
+ }
+ }
+
+ function setExitContent() {
+
+ // publicAPI.crashed = true;
+
+ if (publicAPI.status != "Exited")
+ return;
+
+ if (config.containerElements === undefined) {
+ if (config.showExit !== undefined)
+ config.showExit(publicAPI.crashed, publicAPI.exitCode);
+ return;
+ }
+
+ if (!publicAPI.crashed)
+ return;
+
+ for (container of config.containerElements) {
+ var loaderElement = config.showExit(publicAPI.crashed, publicAPI.exitCode, container);
+ if (loaderElement !== undefined)
+ container.appendChild(loaderElement);
+ }
+ }
+
+ var committedStatus = undefined;
+ function handleStatusChange() {
+ if (publicAPI.status != "Loading" && committedStatus == publicAPI.status)
+ return;
+ committedStatus = publicAPI.status;
+
+ if (publicAPI.status == "Error") {
+ setErrorContent();
+ } else if (publicAPI.status == "Loading") {
+ setLoaderContent();
+ } else if (publicAPI.status == "Running") {
+ setCanvasContent();
+ } else if (publicAPI.status == "Exited") {
+ if (config.restartMode == "RestartOnExit" ||
+ config.restartMode == "RestartOnCrash" && publicAPI.crashed) {
+ committedStatus = undefined;
+ config.restart();
+ } else {
+ setExitContent();
+ }
+ }
+
+ // Send status change notification
+ if (config.statusChanged)
+ config.statusChanged(publicAPI.status);
+ }
+
+ function setStatus(status) {
+ if (status != "Loading" && publicAPI.status == status)
+ return;
+ publicAPI.status = status;
+
+ window.setTimeout(function() { handleStatusChange(); }, 0);
+ }
+
+ setStatus("Created");
+
+ return publicAPI;
+}
diff --git a/src/plugins/platforms/wasm/qtlogo.svg b/src/plugins/platforms/wasm/qtlogo.svg
new file mode 100644
index 0000000000..cb8989bb79
--- /dev/null
+++ b/src/plugins/platforms/wasm/qtlogo.svg
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="462pt"
+ height="339pt"
+ viewBox="0 0 462 339"
+ version="1.1"
+ id="svg2"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="TheQtCompany_logo_2.svg">
+ <metadata
+ id="metadata20">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs18" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1536"
+ inkscape:window-height="801"
+ id="namedview16"
+ showgrid="false"
+ inkscape:zoom="1.1138643"
+ inkscape:cx="270.58047"
+ inkscape:cy="174.65092"
+ inkscape:window-x="-8"
+ inkscape:window-y="-8"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2" />
+ <path
+ fill="#41cd52"
+ d=" M 63.50 0.00 L 462.00 0.00 L 462.00 274.79 C 440.60 296.26 419.13 317.66 397.61 339.00 L 0.00 339.00 L 0.00 63.39 C 21.08 42.18 42.34 21.13 63.50 0.00 Z"
+ id="path6" />
+ <path
+ d=" M 122.37 71.33 C 137.50 61.32 156.21 58.79 174.00 58.95 C 190.94 59.16 208.72 62.13 222.76 72.24 C 232.96 79.41 239.59 90.48 244.01 101.93 C 251.16 120.73 253.26 141.03 253.50 161.01 C 253.53 181.13 252.62 201.69 245.96 220.86 C 241.50 233.90 233.01 245.48 221.81 253.52 C 229.87 266.58 238.09 279.54 246.15 292.60 C 236.02 297.27 225.92 301.97 215.78 306.62 C 207.15 292.38 198.56 278.11 189.90 263.89 C 178.19 265.81 166.21 265.66 154.44 264.36 C 140.34 262.67 125.97 258.37 115.09 248.88 C 106.73 241.64 101.48 231.51 97.89 221.21 C 92.01 203.79 90.43 185.25 90.16 166.97 C 90.02 147.21 91.28 127.14 97.24 108.18 C 101.85 93.92 109.48 79.69 122.37 71.33 Z"
+ id="path8"
+ fill="#ffffff" />
+ <path
+ d=" M 294.13 70.69 C 304.73 70.68 315.33 70.68 325.93 70.69 C 325.96 84.71 325.92 98.72 325.95 112.74 C 339.50 112.76 353.05 112.74 366.60 112.75 C 366.37 121.85 366.12 130.95 365.86 140.05 C 352.32 140.08 338.79 140.04 325.25 140.07 C 325.28 163.05 325.18 186.03 325.30 209.01 C 325.56 215.30 325.42 221.94 328.19 227.75 C 330.21 232.23 335.65 233.38 340.08 233.53 C 348.43 233.50 356.77 233.01 365.12 232.86 C 365.63 241.22 366.12 249.59 366.60 257.95 C 349.99 260.74 332.56 264.08 316.06 258.86 C 309.11 256.80 302.63 252.19 299.81 245.32 C 294.76 233.63 294.35 220.62 294.13 208.07 C 294.11 185.40 294.13 162.74 294.12 140.07 C 286.73 140.05 279.34 140.08 271.95 140.05 C 271.93 130.96 271.93 121.86 271.95 112.76 C 279.34 112.73 286.72 112.77 294.11 112.74 C 294.14 98.72 294.10 84.71 294.13 70.69 Z"
+ id="path10"
+ fill="#ffffff" />
+ <path
+ fill="#41cd52"
+ d=" M 160.51 87.70 C 170.80 86.36 181.60 86.72 191.34 90.61 C 199.23 93.73 205.93 99.84 209.47 107.58 C 214.90 119.31 216.98 132.26 218.03 145.05 C 219.17 162.07 219.01 179.25 216.66 196.17 C 215.01 206.24 212.66 216.85 205.84 224.79 C 198.92 232.76 188.25 236.18 178.01 236.98 C 167.21 237.77 155.82 236.98 146.07 231.87 C 140.38 228.84 135.55 224.09 132.73 218.27 C 129.31 211.30 127.43 203.69 126.11 196.07 C 122.13 171.91 121.17 146.91 126.61 122.89 C 128.85 113.83 132.11 104.53 138.73 97.70 C 144.49 91.85 152.51 88.83 160.51 87.70 Z"
+ id="path12" />
+</svg>
diff --git a/src/plugins/platforms/wasm/qwasmbackingstore.cpp b/src/plugins/platforms/wasm/qwasmbackingstore.cpp
new file mode 100644
index 0000000000..5b40c44807
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmbackingstore.cpp
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwasmbackingstore.h"
+#include "qwasmwindow.h"
+#include "qwasmcompositor.h"
+
+#include <QtGui/qopengltexture.h>
+#include <QtGui/qmatrix4x4.h>
+#include <QtGui/qpainter.h>
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformscreen.h>
+
+#include <QtGui/qbackingstore.h>
+
+QT_BEGIN_NAMESPACE
+
+QWasmBackingStore::QWasmBackingStore(QWasmCompositor *compositor, QWindow *window)
+ : QPlatformBackingStore(window)
+ , m_compositor(compositor)
+ , m_texture(new QOpenGLTexture(QOpenGLTexture::Target2D))
+{
+ QWasmWindow *wasmWindow = static_cast<QWasmWindow *>(window->handle());
+ if (wasmWindow)
+ wasmWindow->setBackingStore(this);
+}
+
+QWasmBackingStore::~QWasmBackingStore()
+{
+}
+
+QPaintDevice *QWasmBackingStore::paintDevice()
+{
+ return &m_image;
+}
+
+void QWasmBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
+{
+ Q_UNUSED(window);
+ Q_UNUSED(region);
+ Q_UNUSED(offset);
+
+ m_dirty |= region;
+ m_compositor->requestRedraw();
+}
+
+void QWasmBackingStore::updateTexture()
+{
+ if (m_dirty.isNull())
+ return;
+
+ if (!m_texture->isCreated()) {
+ m_texture->setMinificationFilter(QOpenGLTexture::Nearest);
+ m_texture->setMagnificationFilter(QOpenGLTexture::Nearest);
+ m_texture->setWrapMode(QOpenGLTexture::ClampToEdge);
+ m_texture->setData(m_image, QOpenGLTexture::DontGenerateMipMaps);
+ m_texture->create();
+ }
+ m_texture->bind();
+
+ QRegion fixed;
+ QRect imageRect = m_image.rect();
+
+ for (const QRect &rect : m_dirty) {
+
+ // Convert device-independent dirty region to device region
+ qreal dpr = m_image.devicePixelRatio();
+ QRect deviceRect = QRect(rect.topLeft() * dpr, rect.size() * dpr);
+
+ // intersect with image rect to be sure
+ QRect r = imageRect & deviceRect;
+ // if the rect is wide enough it is cheaper to just extend it instead of doing an image copy
+ if (r.width() >= imageRect.width() / 2) {
+ r.setX(0);
+ r.setWidth(imageRect.width());
+ }
+
+ fixed |= r;
+ }
+
+ for (const QRect &rect : fixed) {
+ // if the sub-rect is full-width we can pass the image data directly to
+ // OpenGL instead of copying, since there is no gap between scanlines
+ if (rect.width() == imageRect.width()) {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
+ m_image.constScanLine(rect.y()));
+ } else {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
+ m_image.copy(rect).constBits());
+ }
+ }
+ /* End of code taken from QEGLPlatformBackingStore */
+
+ m_dirty = QRegion();
+}
+
+void QWasmBackingStore::beginPaint(const QRegion &region)
+{
+ m_dirty |= region;
+ // Keep backing store device pixel ratio in sync with window
+ if (m_image.devicePixelRatio() != window()->devicePixelRatio())
+ resize(backingStore()->size(), backingStore()->staticContents());
+
+ QPainter painter(&m_image);
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
+ const QColor blank = Qt::transparent;
+ for (const QRect &rect : region)
+ painter.fillRect(rect, blank);
+}
+
+void QWasmBackingStore::resize(const QSize &size, const QRegion &staticContents)
+{
+ Q_UNUSED(staticContents)
+
+ m_image = QImage(size * window()->devicePixelRatio(), QImage::Format_RGB32);
+ m_image.setDevicePixelRatio(window()->devicePixelRatio());
+
+ if (m_texture->isCreated())
+ m_texture->destroy();
+}
+
+QImage QWasmBackingStore::toImage() const
+{
+ // used by QPlatformBackingStore::composeAndFlush
+ return m_image;
+}
+
+const QImage &QWasmBackingStore::getImageRef() const
+{
+ return m_image;
+}
+
+const QOpenGLTexture *QWasmBackingStore::getUpdatedTexture()
+{
+ updateTexture();
+ return m_texture.data();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmbackingstore.h b/src/plugins/platforms/wasm/qwasmbackingstore.h
new file mode 100644
index 0000000000..6ffa262e3d
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmbackingstore.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWASMBACKINGSTORE_H
+#define QWASMBACKINGSTORE_H
+
+#include <qpa/qplatformbackingstore.h>
+#include <QtGui/qimage.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLTexture;
+class QRegion;
+class QWasmCompositor;
+
+class QWasmBackingStore : public QPlatformBackingStore
+{
+public:
+ QWasmBackingStore(QWasmCompositor *compositor, QWindow *window);
+ ~QWasmBackingStore();
+
+ QPaintDevice *paintDevice() override;
+
+ void beginPaint(const QRegion &) override;
+ void flush(QWindow *window, const QRegion &region, const QPoint &offset) override;
+ void resize(const QSize &size, const QRegion &staticContents) override;
+ QImage toImage() const override;
+ const QImage &getImageRef() const;
+
+ const QOpenGLTexture *getUpdatedTexture();
+
+protected:
+ void updateTexture();
+
+private:
+ QWasmCompositor *m_compositor;
+ QImage m_image;
+ QScopedPointer<QOpenGLTexture> m_texture;
+ QRegion m_dirty;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWASMBACKINGSTORE_H
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp
new file mode 100644
index 0000000000..3dc6b7d2f3
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp
@@ -0,0 +1,721 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwasmcompositor.h"
+#include "qwasmwindow.h"
+#include "qwasmstylepixmaps_p.h"
+
+#include <QtGui/qopengltexture.h>
+
+#include <QtGui/private/qwindow_p.h>
+#include <QtGui/qopenglcontext.h>
+#include <QtGui/qopenglfunctions.h>
+#include <QtGui/qopengltextureblitter.h>
+#include <QtGui/qpainter.h>
+#include <private/qpixmapcache_p.h>
+
+#include <private/qguiapplication_p.h>
+
+#include <qpa/qwindowsysteminterface.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtGui/qguiapplication.h>
+
+Q_GUI_EXPORT int qt_defaultDpiX();
+
+QWasmCompositedWindow::QWasmCompositedWindow()
+ : window(nullptr)
+ , parentWindow(nullptr)
+ , flushPending(false)
+ , visible(false)
+{
+}
+
+QWasmCompositor::QWasmCompositor()
+ : m_frameBuffer(nullptr)
+ , m_blitter(new QOpenGLTextureBlitter)
+ , m_needComposit(false)
+ , m_inFlush(false)
+ , m_inResize(false)
+ , m_isEnabled(true)
+ , m_targetDevicePixelRatio(1)
+{
+}
+
+QWasmCompositor::~QWasmCompositor()
+{
+ delete m_frameBuffer;
+}
+
+void QWasmCompositor::setEnabled(bool enabled)
+{
+ m_isEnabled = enabled;
+}
+
+void QWasmCompositor::addWindow(QWasmWindow *window, QWasmWindow *parentWindow)
+{
+ QWasmCompositedWindow compositedWindow;
+ compositedWindow.window = window;
+ compositedWindow.parentWindow = parentWindow;
+ m_compositedWindows.insert(window, compositedWindow);
+
+ if (parentWindow == 0)
+ m_windowStack.append(window);
+ else
+ m_compositedWindows[parentWindow].childWindows.append(window);
+
+ notifyTopWindowChanged(window);
+}
+
+void QWasmCompositor::removeWindow(QWasmWindow *window)
+{
+ QWasmWindow *platformWindow = m_compositedWindows[window].parentWindow;
+
+ if (platformWindow) {
+ QWasmWindow *parentWindow = window;
+ m_compositedWindows[parentWindow].childWindows.removeAll(window);
+ }
+
+ m_windowStack.removeAll(window);
+ m_compositedWindows.remove(window);
+
+ notifyTopWindowChanged(window);
+}
+
+void QWasmCompositor::setScreen(QWasmScreen *screen)
+{
+ m_screen = screen;
+}
+
+void QWasmCompositor::setVisible(QWasmWindow *window, bool visible)
+{
+ QWasmCompositedWindow &compositedWindow = m_compositedWindows[window];
+ if (compositedWindow.visible == visible)
+ return;
+
+ compositedWindow.visible = visible;
+ compositedWindow.flushPending = true;
+ if (visible)
+ compositedWindow.damage = compositedWindow.window->geometry();
+ else
+ m_globalDamage = compositedWindow.window->geometry(); // repaint previosly covered area.
+
+ requestRedraw();
+}
+
+void QWasmCompositor::raise(QWasmWindow *window)
+{
+ if (m_compositedWindows.size() <= 1)
+ return;
+
+ QWasmCompositedWindow &compositedWindow = m_compositedWindows[window];
+ compositedWindow.damage = compositedWindow.window->geometry();
+ m_windowStack.removeAll(window);
+ m_windowStack.append(window);
+
+ notifyTopWindowChanged(window);
+}
+
+void QWasmCompositor::lower(QWasmWindow *window)
+{
+ if (m_compositedWindows.size() <= 1)
+ return;
+
+ m_windowStack.removeAll(window);
+ m_windowStack.prepend(window);
+ QWasmCompositedWindow &compositedWindow = m_compositedWindows[window];
+ m_globalDamage = compositedWindow.window->geometry(); // repaint previosly covered area.
+
+ notifyTopWindowChanged(window);
+}
+
+void QWasmCompositor::setParent(QWasmWindow *window, QWasmWindow *parent)
+{
+ m_compositedWindows[window].parentWindow = parent;
+
+ requestRedraw();
+}
+
+void QWasmCompositor::flush(QWasmWindow *window, const QRegion &region)
+{
+ QWasmCompositedWindow &compositedWindow = m_compositedWindows[window];
+ compositedWindow.flushPending = true;
+ compositedWindow.damage = region;
+
+ requestRedraw();
+}
+
+int QWasmCompositor::windowCount() const
+{
+ return m_windowStack.count();
+}
+
+
+void QWasmCompositor::redrawWindowContent()
+{
+ // Redraw window content by sending expose events. This redraw
+ // will cause a backing store flush, which will call requestRedraw()
+ // to composit.
+ for (QWasmWindow *platformWindow : m_windowStack) {
+ QWindow *window = platformWindow->window();
+ QWindowSystemInterface::handleExposeEvent<QWindowSystemInterface::SynchronousDelivery>(
+ window, QRect(QPoint(0, 0), window->geometry().size()));
+ }
+}
+
+void QWasmCompositor::requestRedraw()
+{
+ if (m_needComposit)
+ return;
+
+ m_needComposit = true;
+ QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
+}
+
+QWindow *QWasmCompositor::windowAt(QPoint p, int padding) const
+{
+ int index = m_windowStack.count() - 1;
+ // qDebug() << "window at" << "point" << p << "window count" << index;
+
+ while (index >= 0) {
+ const QWasmCompositedWindow &compositedWindow = m_compositedWindows[m_windowStack.at(index)];
+ //qDebug() << "windwAt testing" << compositedWindow.window <<
+
+ QRect geometry = compositedWindow.window->windowFrameGeometry()
+ .adjusted(-padding, -padding, padding, padding);
+
+ if (compositedWindow.visible && geometry.contains(p))
+ return m_windowStack.at(index)->window();
+ --index;
+ }
+
+ return 0;
+}
+
+QWindow *QWasmCompositor::keyWindow() const
+{
+ return m_windowStack.at(m_windowStack.count() - 1)->window();
+}
+
+bool QWasmCompositor::event(QEvent *ev)
+{
+ if (ev->type() == QEvent::UpdateRequest) {
+ if (m_isEnabled)
+ frame();
+ return true;
+ }
+
+ return QObject::event(ev);
+}
+
+void QWasmCompositor::blit(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, const QOpenGLTexture *texture, QRect targetGeometry)
+{
+ QMatrix4x4 m;
+ m.translate(-1.0f, -1.0f);
+
+ m.scale(2.0f / (float)screen->geometry().width(),
+ 2.0f / (float)screen->geometry().height());
+
+ m.translate((float)targetGeometry.width() / 2.0f,
+ (float)-targetGeometry.height() / 2.0f);
+
+ m.translate(targetGeometry.x(), screen->geometry().height() - targetGeometry.y());
+
+ m.scale(0.5f * (float)targetGeometry.width(),
+ 0.5f * (float)targetGeometry.height());
+
+ blitter->blit(texture->textureId(), m, QOpenGLTextureBlitter::OriginTopLeft);
+}
+
+void QWasmCompositor::drawWindowContent(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window)
+{
+ QWasmBackingStore *backingStore = window->backingStore();
+
+ QOpenGLTexture const *texture = backingStore->getUpdatedTexture();
+
+ blit(blitter, screen, texture, window->geometry());
+}
+
+QPalette QWasmCompositor::makeWindowPalette()
+{
+ QPalette palette;
+ palette.setColor(QPalette::Active, QPalette::Highlight,
+ palette.color(QPalette::Active, QPalette::Highlight));
+ palette.setColor(QPalette::Active, QPalette::Base,
+ palette.color(QPalette::Active, QPalette::Highlight));
+ palette.setColor(QPalette::Inactive, QPalette::Highlight,
+ palette.color(QPalette::Inactive, QPalette::Dark));
+ palette.setColor(QPalette::Inactive, QPalette::Base,
+ palette.color(QPalette::Inactive, QPalette::Dark));
+ palette.setColor(QPalette::Inactive, QPalette::HighlightedText,
+ palette.color(QPalette::Inactive, QPalette::Window));
+
+ return palette;
+}
+
+QRect QWasmCompositor::titlebarRect(QWasmTitleBarOptions tb, QWasmCompositor::SubControls subcontrol)
+{
+ QRect ret;
+ const int controlMargin = 2;
+ const int controlHeight = tb.rect.height() - controlMargin *2;
+ const int delta = controlHeight + controlMargin;
+ int offset = 0;
+
+ bool isMinimized = tb.state & Qt::WindowMinimized;
+ bool isMaximized = tb.state & Qt::WindowMaximized;
+
+ ret = tb.rect;
+ switch (subcontrol) {
+ case SC_TitleBarLabel:
+ if (tb.flags & Qt::WindowSystemMenuHint)
+ ret.adjust(delta, 0, -delta, 0);
+ break;
+ case SC_TitleBarCloseButton:
+ if (tb.flags & Qt::WindowSystemMenuHint) {
+ ret.adjust(0, 0, -delta, 0);
+ offset += delta;
+ }
+ break;
+ case SC_TitleBarMaxButton:
+ if (!isMaximized && tb.flags & Qt::WindowMaximizeButtonHint) {
+ ret.adjust(0, 0, -delta*2, 0);
+ offset += (delta +delta);
+ }
+ break;
+ case SC_TitleBarNormalButton:
+ if (isMinimized && (tb.flags & Qt::WindowMinimizeButtonHint))
+ offset += delta;
+ else if (isMaximized && (tb.flags & Qt::WindowMaximizeButtonHint))
+ ret.adjust(0, 0, -delta*2, 0);
+ offset += (delta +delta);
+ break;
+ case SC_TitleBarSysMenu:
+ if (tb.flags & Qt::WindowSystemMenuHint) {
+ ret.setRect(tb.rect.left() + controlMargin, tb.rect.top() + controlMargin,
+ controlHeight, controlHeight);
+ }
+ break;
+ default:
+ break;
+ };
+
+ if (subcontrol != SC_TitleBarLabel && subcontrol != SC_TitleBarSysMenu) {
+ ret.setRect(tb.rect.right() - offset, tb.rect.top() + controlMargin,
+ controlHeight, controlHeight);
+ }
+
+ if (qApp->layoutDirection() == Qt::LeftToRight)
+ return ret;
+
+ QRect rect = ret;
+ rect.translate(2 * (tb.rect.right() - ret.right()) +
+ ret.width() - tb.rect.width(), 0);
+
+ return rect;
+}
+
+int dpiScaled(qreal value)
+{
+ return value * (qreal(qt_defaultDpiX()) / 96.0);
+}
+
+QWasmCompositor::QWasmTitleBarOptions QWasmCompositor::makeTitleBarOptions(const QWasmWindow *window)
+{
+ int width = window->windowFrameGeometry().width();
+ int border = window->borderWidth();
+
+ QWasmTitleBarOptions titleBarOptions;
+
+ titleBarOptions.rect = QRect(border, border, width - 2 * border, window->titleHeight());
+ titleBarOptions.flags = window->window()->flags();
+ titleBarOptions.state = window->window()->windowState();
+
+ bool isMaximized = titleBarOptions.state & Qt::WindowMaximized; // this gets reset when maximized
+
+ if (titleBarOptions.flags & (Qt::WindowTitleHint))
+ titleBarOptions.subControls |= SC_TitleBarLabel;
+ if (titleBarOptions.flags & Qt::WindowMaximizeButtonHint) {
+ if (isMaximized)
+ titleBarOptions.subControls |= SC_TitleBarNormalButton;
+ else
+ titleBarOptions.subControls |= SC_TitleBarMaxButton;
+ }
+ if (titleBarOptions.flags & Qt::WindowSystemMenuHint) {
+ titleBarOptions.subControls |= SC_TitleBarCloseButton;
+ titleBarOptions.subControls |= SC_TitleBarSysMenu;
+ }
+
+
+ titleBarOptions.palette = QWasmCompositor::makeWindowPalette();
+
+ if (window->window()->isActive())
+ titleBarOptions.palette.setCurrentColorGroup(QPalette::Active);
+ else
+ titleBarOptions.palette.setCurrentColorGroup(QPalette::Inactive);
+
+ if (window->activeSubControl() != QWasmCompositor::SC_None)
+ titleBarOptions.subControls = window->activeSubControl();
+
+ if (!window->window()->title().isEmpty())
+ titleBarOptions.titleBarOptionsString = window->window()->title();
+
+ return titleBarOptions;
+}
+
+void QWasmCompositor::drawWindowDecorations(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window)
+{
+ int width = window->windowFrameGeometry().width();
+ int height = window->windowFrameGeometry().height();
+ qreal dpr = window->devicePixelRatio();
+
+ QImage image(QSize(width * dpr, height * dpr), QImage::Format_RGB32);
+ image.setDevicePixelRatio(dpr);
+ QPainter painter(&image);
+ painter.fillRect(QRect(0, 0, width, height), painter.background());
+
+ QWasmTitleBarOptions titleBarOptions = makeTitleBarOptions(window);
+
+ drawTitlebarWindow(titleBarOptions, &painter);
+
+ QWasmFrameOptions frameOptions;
+ frameOptions.rect = QRect(0, 0, width, height);
+ frameOptions.lineWidth = dpiScaled(4.);
+
+ drawFrameWindow(frameOptions, &painter);
+
+ painter.end();
+
+ QOpenGLTexture texture(QOpenGLTexture::Target2D);
+ texture.setMinificationFilter(QOpenGLTexture::Nearest);
+ texture.setMagnificationFilter(QOpenGLTexture::Nearest);
+ texture.setWrapMode(QOpenGLTexture::ClampToEdge);
+ texture.setData(image, QOpenGLTexture::DontGenerateMipMaps);
+ texture.create();
+ texture.bind();
+
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image.width(), image.height(), GL_RGBA, GL_UNSIGNED_BYTE,
+ image.constScanLine(0));
+
+ blit(blitter, screen, &texture, QRect(window->windowFrameGeometry().topLeft(), QSize(width, height)));
+}
+
+void QWasmCompositor::drawFrameWindow(QWasmFrameOptions options, QPainter *painter)
+{
+ int x = options.rect.x();
+ int y = options.rect.y();
+ int w = options.rect.width();
+ int h = options.rect.height();
+ const QColor &c1 = options.palette.light().color();
+ const QColor &c2 = options.palette.shadow().color();
+ const QColor &c3 = options.palette.midlight().color();
+ const QColor &c4 = options.palette.dark().color();
+ const QBrush *fill = 0;
+
+ const qreal devicePixelRatio = painter->device()->devicePixelRatioF();
+ if (!qFuzzyCompare(devicePixelRatio, qreal(1))) {
+ const qreal inverseScale = qreal(1) / devicePixelRatio;
+ painter->scale(inverseScale, inverseScale);
+ x = qRound(devicePixelRatio * x);
+ y = qRound(devicePixelRatio * y);
+ w = qRound(devicePixelRatio * w);
+ h = qRound(devicePixelRatio * h);
+ }
+
+ QPen oldPen = painter->pen();
+ QPoint a[3] = { QPoint(x, y+h-2), QPoint(x, y), QPoint(x+w-2, y) };
+ painter->setPen(c1);
+ painter->drawPolyline(a, 3);
+ QPoint b[3] = { QPoint(x, y+h-1), QPoint(x+w-1, y+h-1), QPoint(x+w-1, y) };
+ painter->setPen(c2);
+ painter->drawPolyline(b, 3);
+ if (w > 4 && h > 4) {
+ QPoint c[3] = { QPoint(x+1, y+h-3), QPoint(x+1, y+1), QPoint(x+w-3, y+1) };
+ painter->setPen(c3);
+ painter->drawPolyline(c, 3);
+ QPoint d[3] = { QPoint(x+1, y+h-2), QPoint(x+w-2, y+h-2), QPoint(x+w-2, y+1) };
+ painter->setPen(c4);
+ painter->drawPolyline(d, 3);
+ if (fill)
+ painter->fillRect(QRect(x+2, y+2, w-4, h-4), *fill);
+ }
+ painter->setPen(oldPen);
+}
+
+//from commonstyle.cpp
+static QPixmap cachedPixmapFromXPM(const char * const *xpm)
+{
+ QPixmap result;
+ const QString tag = QString::asprintf("xpm:0x%p", static_cast<const void*>(xpm));
+ if (!QPixmapCache::find(tag, &result)) {
+ result = QPixmap(xpm);
+ QPixmapCache::insert(tag, result);
+ }
+ return result;
+}
+
+void QWasmCompositor::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
+ const QPixmap &pixmap) const
+{
+ qreal scale = pixmap.devicePixelRatio();
+ QSize size = pixmap.size() / scale;
+ int x = rect.x();
+ int y = rect.y();
+ int w = size.width();
+ int h = size.height();
+ if ((alignment & Qt::AlignVCenter) == Qt::AlignVCenter)
+ y += rect.size().height()/2 - h/2;
+ else if ((alignment & Qt::AlignBottom) == Qt::AlignBottom)
+ y += rect.size().height() - h;
+ if ((alignment & Qt::AlignRight) == Qt::AlignRight)
+ x += rect.size().width() - w;
+ else if ((alignment & Qt::AlignHCenter) == Qt::AlignHCenter)
+ x += rect.size().width()/2 - w/2;
+
+ QRect aligned = QRect(x, y, w, h);
+ QRect inter = aligned.intersected(rect);
+
+ painter->drawPixmap(inter.x(), inter.y(), pixmap, inter.x() - aligned.x(), inter.y() - aligned.y(), inter.width() * scale, inter.height() *scale);
+}
+
+
+void QWasmCompositor::drawTitlebarWindow(QWasmTitleBarOptions tb, QPainter *painter)
+{
+ QRect ir;
+ if (tb.subControls.testFlag(SC_TitleBarLabel)) {
+ QColor left = tb.palette.highlight().color();
+ QColor right = tb.palette.base().color();
+
+ QBrush fillBrush(left);
+ if (left != right) {
+ QPoint p1(tb.rect.x(), tb.rect.top() + tb.rect.height()/2);
+ QPoint p2(tb.rect.right(), tb.rect.top() + tb.rect.height()/2);
+ QLinearGradient lg(p1, p2);
+ lg.setColorAt(0, left);
+ lg.setColorAt(1, right);
+ fillBrush = lg;
+ }
+
+ painter->fillRect(tb.rect, fillBrush);
+ ir = titlebarRect(tb, SC_TitleBarLabel);
+ painter->setPen(tb.palette.highlightedText().color());
+ painter->drawText(ir.x() + 2, ir.y(), ir.width() - 2, ir.height(),
+ Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, tb.titleBarOptionsString);
+ } // SC_TitleBarLabel
+
+ bool down = false;
+ QPixmap pixmap;
+
+ if (tb.subControls.testFlag(SC_TitleBarCloseButton)
+ && tb.flags & Qt::WindowSystemMenuHint) {
+ ir = titlebarRect(tb, SC_TitleBarCloseButton);
+ down = tb.subControls & SC_TitleBarCloseButton && (tb.state & State_Sunken);
+ pixmap = cachedPixmapFromXPM(qt_close_xpm).scaled(QSize(10, 10));
+ drawItemPixmap(painter, ir, Qt::AlignCenter, pixmap);
+ } //SC_TitleBarCloseButton
+
+ if (tb.subControls.testFlag(SC_TitleBarMaxButton)
+ && tb.flags & Qt::WindowMaximizeButtonHint
+ && !(tb.state & Qt::WindowMaximized)) {
+ ir = titlebarRect(tb, SC_TitleBarMaxButton);
+ down = tb.subControls & SC_TitleBarMaxButton && (tb.state & State_Sunken);
+ pixmap = cachedPixmapFromXPM(qt_maximize_xpm).scaled(QSize(10, 10));
+ drawItemPixmap(painter, ir, Qt::AlignCenter, pixmap);
+ } //SC_TitleBarMaxButton
+
+ bool drawNormalButton = (tb.subControls & SC_TitleBarNormalButton)
+ && (((tb.flags & Qt::WindowMinimizeButtonHint)
+ && (tb.flags & Qt::WindowMinimized))
+ || ((tb.flags & Qt::WindowMaximizeButtonHint)
+ && (tb.flags & Qt::WindowMaximized)));
+
+ if (drawNormalButton) {
+ ir = titlebarRect(tb, SC_TitleBarNormalButton);
+ down = tb.subControls & SC_TitleBarNormalButton && (tb.state & State_Sunken);
+ pixmap = cachedPixmapFromXPM(qt_normalizeup_xpm).scaled( QSize(10, 10));
+
+ drawItemPixmap(painter, ir, Qt::AlignCenter, pixmap);
+ } // SC_TitleBarNormalButton
+
+ if (tb.subControls & SC_TitleBarSysMenu && tb.flags & Qt::WindowSystemMenuHint) {
+ ir = titlebarRect(tb, SC_TitleBarSysMenu);
+ pixmap = cachedPixmapFromXPM(qt_menu_xpm).scaled(QSize(10, 10));
+ drawItemPixmap(painter, ir, Qt::AlignCenter, pixmap);
+ }
+}
+
+void QWasmCompositor::drawShadePanel(QWasmTitleBarOptions options, QPainter *painter)
+{
+ int lineWidth = 1;
+ QPalette palette = options.palette;
+ const QBrush *fill = &options.palette.brush(QPalette::Button);
+
+ int x = options.rect.x();
+ int y = options.rect.y();
+ int w = options.rect.width();
+ int h = options.rect.height();
+
+ const qreal devicePixelRatio = painter->device()->devicePixelRatioF();
+ if (!qFuzzyCompare(devicePixelRatio, qreal(1))) {
+ const qreal inverseScale = qreal(1) / devicePixelRatio;
+ painter->scale(inverseScale, inverseScale);
+
+ x = qRound(devicePixelRatio * x);
+ y = qRound(devicePixelRatio * y);
+ w = qRound(devicePixelRatio * w);
+ h = qRound(devicePixelRatio * h);
+ lineWidth = qRound(devicePixelRatio * lineWidth);
+ }
+
+ QColor shade = palette.dark().color();
+ QColor light = palette.light().color();
+
+ if (fill) {
+ if (fill->color() == shade)
+ shade = palette.shadow().color();
+ if (fill->color() == light)
+ light = palette.midlight().color();
+ }
+ QPen oldPen = painter->pen();
+ QVector<QLineF> lines;
+ lines.reserve(2*lineWidth);
+
+ painter->setPen(light);
+ int x1, y1, x2, y2;
+ int i;
+ x1 = x;
+ y1 = y2 = y;
+ x2 = x + w - 2;
+ for (i = 0; i < lineWidth; i++) // top shadow
+ lines << QLineF(x1, y1++, x2--, y2++);
+
+ x2 = x1;
+ y1 = y + h - 2;
+ for (i = 0; i < lineWidth; i++) // left shado
+ lines << QLineF(x1++, y1, x2++, y2--);
+
+ painter->drawLines(lines);
+ lines.clear();
+ painter->setPen(shade);
+ x1 = x;
+ y1 = y2 = y+h-1;
+ x2 = x+w-1;
+ for (i=0; i<lineWidth; i++) { // bottom shadow
+ lines << QLineF(x1++, y1--, x2, y2--);
+ }
+ x1 = x2;
+ y1 = y;
+ y2 = y + h - lineWidth - 1;
+ for (i = 0; i < lineWidth; i++) // right shadow
+ lines << QLineF(x1--, y1++, x2--, y2);
+
+ painter->drawLines(lines);
+ if (fill) // fill with fill color
+ painter->fillRect(x+lineWidth, y+lineWidth, w-lineWidth*2, h-lineWidth*2, *fill);
+ painter->setPen(oldPen); // restore pen
+
+}
+
+void QWasmCompositor::drawWindow(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window)
+{
+ if (window->window()->type() != Qt::Popup && !(window->m_windowState & Qt::WindowFullScreen))
+ drawWindowDecorations(blitter, screen, window);
+ drawWindowContent(blitter, screen, window);
+}
+
+void QWasmCompositor::frame()
+{
+ if (!m_needComposit)
+ return;
+
+ m_needComposit = false;
+
+ if (m_windowStack.empty() || !m_screen)
+ return;
+
+ QWasmWindow *someWindow = nullptr;
+
+ foreach (QWasmWindow *window, m_windowStack) {
+ if (window->window()->surfaceClass() == QSurface::Window
+ && qt_window_private(static_cast<QWindow *>(window->window()))->receivedExpose) {
+ someWindow = window;
+ break;
+ }
+ }
+
+ if (!someWindow)
+ return;
+
+ if (m_context.isNull()) {
+ m_context.reset(new QOpenGLContext());
+ //mContext->setFormat(mScreen->format());
+ m_context->setScreen(m_screen->screen());
+ m_context->create();
+ }
+
+ m_context->makeCurrent(someWindow->window());
+
+ if (!m_blitter->isCreated())
+ m_blitter->create();
+
+ qreal dpr = m_screen->devicePixelRatio();
+ glViewport(0, 0, m_screen->geometry().width() * dpr, m_screen->geometry().height() * dpr);
+
+ m_context->functions()->glClearColor(0.2, 0.2, 0.2, 1.0);
+ m_context->functions()->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+ m_blitter->bind();
+ m_blitter->setRedBlueSwizzle(true);
+
+ foreach (QWasmWindow *window, m_windowStack) {
+ QWasmCompositedWindow &compositedWindow = m_compositedWindows[window];
+
+ if (!compositedWindow.visible)
+ continue;
+
+ drawWindow(m_blitter.data(), m_screen, window);
+ }
+
+ m_blitter->release();
+
+ if (someWindow && someWindow->window()->surfaceType() == QSurface::OpenGLSurface)
+ m_context->swapBuffers(someWindow->window());
+}
+
+void QWasmCompositor::notifyTopWindowChanged(QWasmWindow *window)
+{
+ QWindow *modalWindow;
+ bool blocked = QGuiApplicationPrivate::instance()->isWindowBlocked(window->window(), &modalWindow);
+
+ if (blocked) {
+ raise(static_cast<QWasmWindow*>(modalWindow->handle()));
+ return;
+ }
+
+ requestRedraw();
+ QWindowSystemInterface::handleWindowActivated(window->window());
+}
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.h b/src/plugins/platforms/wasm/qwasmcompositor.h
new file mode 100644
index 0000000000..4e5ed46cec
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmcompositor.h
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWASMCOMPOSITOR_H
+#define QWASMCOMPOSITOR_H
+
+#include <QtGui/qregion.h>
+#include <qpa/qplatformwindow.h>
+
+#include <QtGui/qopengltextureblitter.h>
+#include <QtGui/qopengltexture.h>
+#include <QtGui/qpalette.h>
+#include <QtGui/qpainter.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWasmWindow;
+class QWasmScreen;
+class QOpenGLContext;
+class QOpenGLTextureBlitter;
+
+class QWasmCompositedWindow
+{
+public:
+ QWasmCompositedWindow();
+
+ QWasmWindow *window;
+ QWasmWindow *parentWindow;
+ QRegion damage;
+ bool flushPending;
+ bool visible;
+ QList<QWasmWindow *> childWindows;
+};
+
+class QWasmCompositor : public QObject
+{
+ Q_OBJECT
+public:
+ QWasmCompositor();
+ ~QWasmCompositor();
+
+ enum QWasmSubControl {
+ SC_None = 0x00000000,
+ SC_TitleBarSysMenu = 0x00000001,
+ SC_TitleBarMinButton = 0x00000002,
+ SC_TitleBarMaxButton = 0x00000004,
+ SC_TitleBarCloseButton = 0x00000008,
+ SC_TitleBarNormalButton = 0x00000010,
+ SC_TitleBarLabel = 0x00000100
+ };
+ Q_DECLARE_FLAGS(SubControls, QWasmSubControl)
+
+ enum QWasmStateFlag {
+ State_None = 0x00000000,
+ State_Enabled = 0x00000001,
+ State_Raised = 0x00000002,
+ State_Sunken = 0x00000004
+ };
+ Q_DECLARE_FLAGS(StateFlags, QWasmStateFlag)
+
+ struct QWasmTitleBarOptions {
+ QRect rect;
+ Qt::WindowFlags flags;
+ int state;
+ QPalette palette;
+ QString titleBarOptionsString;
+ QWasmCompositor::SubControls subControls;
+ };
+
+ struct QWasmFrameOptions {
+ QRect rect;
+ int lineWidth;
+ QPalette palette;
+ };
+
+ void setEnabled(bool enabled);
+
+ void addWindow(QWasmWindow *window, QWasmWindow *parentWindow = nullptr);
+ void removeWindow(QWasmWindow *window);
+ void setScreen(QWasmScreen *screen);
+
+ void setVisible(QWasmWindow *window, bool visible);
+ void raise(QWasmWindow *window);
+ void lower(QWasmWindow *window);
+ void setParent(QWasmWindow *window, QWasmWindow *parent);
+
+ void flush(QWasmWindow *surface, const QRegion &region);
+
+ int windowCount() const;
+
+ void redrawWindowContent();
+ void requestRedraw();
+
+ QWindow *windowAt(QPoint p, int padding = 0) const;
+ QWindow *keyWindow() const;
+
+ bool event(QEvent *event);
+
+ static QWasmTitleBarOptions makeTitleBarOptions(const QWasmWindow *window);
+ static QRect titlebarRect(QWasmTitleBarOptions tb, QWasmCompositor::SubControls subcontrol);
+
+private slots:
+ void frame();
+
+private:
+ void createFrameBuffer();
+ void flushCompletedCallback(int32_t);
+ void notifyTopWindowChanged(QWasmWindow *window);
+ void drawWindow(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window);
+ void drawWindowContent(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window);
+ void blit(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, const QOpenGLTexture *texture, QRect targetGeometry);
+
+ void drawWindowDecorations(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window);
+ void drwPanelButton();
+
+ QImage *m_frameBuffer;
+ QScopedPointer<QOpenGLContext> m_context;
+ QScopedPointer<QOpenGLTextureBlitter> m_blitter;
+ QWasmScreen *m_screen;
+
+ QHash<QWasmWindow *, QWasmCompositedWindow> m_compositedWindows;
+ QList<QWasmWindow *> m_windowStack;
+ QRegion m_globalDamage; // damage caused by expose, window close, etc.
+ bool m_needComposit;
+ bool m_inFlush;
+ bool m_inResize;
+ bool m_isEnabled;
+ QSize m_targetSize;
+ qreal m_targetDevicePixelRatio;
+
+ static QPalette makeWindowPalette();
+
+ void drawFrameWindow(QWasmFrameOptions options, QPainter *painter);
+ void drawTitlebarWindow(QWasmTitleBarOptions options, QPainter *painter);
+ void drawShadePanel(QWasmTitleBarOptions options, QPainter *painter);
+ void drawItemPixmap(QPainter *painter, const QRect &rect,
+ int alignment, const QPixmap &pixmap) const;
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QWasmCompositor::SubControls)
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/wasm/qwasmcursor.cpp b/src/plugins/platforms/wasm/qwasmcursor.cpp
new file mode 100644
index 0000000000..54804a55b3
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmcursor.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwasmcursor.h"
+
+#include <QtCore/qdebug.h>
+
+#include <emscripten/emscripten.h>
+
+void QWasmCursor::changeCursor(QCursor *windowCursor, QWindow *window)
+{
+ if (windowCursor == nullptr)
+ return;
+
+ // FIXME: The HTML5 plugin sets the cursor on the native canvas; when using multiple windows
+ // multiple cursors need to be managed taking mouse postion and stacking into account.
+ Q_UNUSED(window);
+
+ // Bitmap and custom cursors are not implemented (will fall back to "auto")
+ if (windowCursor->shape() == Qt::BitmapCursor || windowCursor->shape() >= Qt::CustomCursor)
+ qWarning() << "QWasmCursor: bitmap and custom cursors are not supported";
+
+ QByteArray htmlCursorName = cursorShapeToHtml(windowCursor->shape());
+
+ if (htmlCursorName.isEmpty())
+ htmlCursorName = "auto";
+
+ // Set cursor on the main canvas
+ EM_ASM_ARGS({
+ if (Module['canvas']) {
+ Module['canvas'].style['cursor'] = Pointer_stringify($0);
+ }
+ }, htmlCursorName.constData());
+}
+
+QByteArray QWasmCursor::cursorShapeToHtml(Qt::CursorShape shape)
+{
+ QByteArray cursorName;
+
+ switch (shape) {
+ case Qt::ArrowCursor:
+ cursorName = "default";
+ break;
+ case Qt::UpArrowCursor:
+ break;
+ case Qt::CrossCursor:
+ cursorName = "crosshair";
+ break;
+ case Qt::WaitCursor:
+ cursorName = "wait";
+ break;
+ case Qt::IBeamCursor:
+ cursorName = "text";
+ break;
+ case Qt::SizeVerCursor:
+ cursorName = "ns-resize";
+ break;
+ case Qt::SizeHorCursor:
+ cursorName = "ew-resize";
+ break;
+ case Qt::SizeBDiagCursor:
+ cursorName = "nesw-resize";
+ break;
+ case Qt::SizeFDiagCursor:
+ cursorName = "nwse-resize";
+ break;
+ case Qt::SizeAllCursor:
+ break; // no equivalent?
+ case Qt::BlankCursor:
+ cursorName = "none";
+ break;
+ case Qt::SplitVCursor:
+ cursorName = "row-resize";
+ break;
+ case Qt::SplitHCursor:
+ cursorName = "col-resize";
+ break;
+ case Qt::PointingHandCursor:
+ cursorName = "pointer";
+ break;
+ case Qt::ForbiddenCursor:
+ cursorName = "not-allowed";
+ break;
+ case Qt::WhatsThisCursor:
+ cursorName = "help";
+ break;
+ case Qt::BusyCursor:
+ cursorName = "wait";
+ break;
+ case Qt::OpenHandCursor:
+ break; // no equivalent?
+ case Qt::ClosedHandCursor:
+ break; // no equivalent?
+ case Qt::DragCopyCursor:
+ break; // no equivalent?
+ case Qt::DragMoveCursor:
+ break; // no equivalent?
+ case Qt::DragLinkCursor:
+ break; // no equivalent?
+ default:
+ break;
+ }
+
+ return cursorName;
+}
diff --git a/src/plugins/platforms/wasm/qwasmcursor.h b/src/plugins/platforms/wasm/qwasmcursor.h
new file mode 100644
index 0000000000..516e07aa31
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmcursor.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWASMCURSOR_H
+#define QWASMCURSOR_H
+
+#include <qpa/qplatformcursor.h>
+
+class QWasmCursor : public QPlatformCursor
+{
+public:
+ void changeCursor(QCursor *windowCursor, QWindow *window) override;
+
+ QByteArray cursorShapeToHtml(Qt::CursorShape shape);
+};
+
+#endif
diff --git a/src/plugins/platforms/wasm/qwasmeventdispatcher.cpp b/src/plugins/platforms/wasm/qwasmeventdispatcher.cpp
new file mode 100644
index 0000000000..41355d72ae
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmeventdispatcher.cpp
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwasmeventdispatcher.h"
+
+#include <QtCore/qcoreapplication.h>
+
+#include <emscripten.h>
+
+class QWasmEventDispatcherPrivate : public QEventDispatcherUNIXPrivate
+{
+
+};
+
+QWasmEventDispatcher *g_htmlEventDispatcher;
+
+QWasmEventDispatcher::QWasmEventDispatcher(QObject *parent)
+ : QUnixEventDispatcherQPA(parent)
+{
+
+ g_htmlEventDispatcher = this;
+}
+
+QWasmEventDispatcher::~QWasmEventDispatcher()
+{
+ g_htmlEventDispatcher = nullptr;
+}
+
+bool QWasmEventDispatcher::registerRequestUpdateCallback(std::function<void(void)> callback)
+{
+ if (!g_htmlEventDispatcher || !g_htmlEventDispatcher->m_hasMainLoop)
+ return false;
+
+ g_htmlEventDispatcher->m_requestUpdateCallbacks.append(callback);
+ emscripten_resume_main_loop();
+ return true;
+}
+
+void QWasmEventDispatcher::maintainTimers()
+{
+ if (!g_htmlEventDispatcher || !g_htmlEventDispatcher->m_hasMainLoop)
+ return;
+
+ g_htmlEventDispatcher->doMaintainTimers();
+}
+
+bool QWasmEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ // WaitForMoreEvents is not supported (except for in combination with EventLoopExec below),
+ // and we don't want the unix event dispatcher base class to attempt to wait either.
+ flags &= ~QEventLoop::WaitForMoreEvents;
+
+ // Handle normal processEvents.
+ if (!(flags & QEventLoop::EventLoopExec))
+ return QUnixEventDispatcherQPA::processEvents(flags);
+
+ // Handle processEvents from QEventLoop::exec():
+ //
+ // At this point the application has created its root objects on
+ // the stack and has called app.exec() which has called into this
+ // function via QEventLoop.
+ //
+ // The application now expects that exec() will not return until
+ // app exit time. However, the browser expects that we return
+ // control to it periodically, also after initial setup in main().
+
+ // EventLoopExec for nested event loops is not supported.
+ Q_ASSERT(!m_hasMainLoop);
+ m_hasMainLoop = true;
+
+ // Call emscripten_set_main_loop_arg() with a callback which processes
+ // events. Also set simulateInfiniteLoop to true which makes emscripten
+ // return control to the browser without unwinding the C++ stack.
+ auto callback = [](void *eventDispatcher) {
+ QWasmEventDispatcher *that = static_cast<QWasmEventDispatcher *>(eventDispatcher);
+
+ // Save and clear updateRequest callbacks so we can register new ones
+ auto requestUpdateCallbacksCopy = that->m_requestUpdateCallbacks;
+ that->m_requestUpdateCallbacks.clear();
+
+ // Repaint all windows
+ for (auto callback : qAsConst(requestUpdateCallbacksCopy))
+ callback();
+
+ // Pause main loop if no updates were requested. Updates will be
+ // restarted again by registerRequestUpdateCallback().
+ if (that->m_requestUpdateCallbacks.isEmpty())
+ emscripten_pause_main_loop();
+
+ that->doMaintainTimers();
+ };
+ int fps = 0; // update using requestAnimationFrame
+ int simulateInfiniteLoop = 1;
+ emscripten_set_main_loop_arg(callback, this, fps, simulateInfiniteLoop);
+
+ // Note: the above call never returns, not even at app exit
+ return false;
+}
+
+void QWasmEventDispatcher::doMaintainTimers()
+{
+ Q_D(QWasmEventDispatcher);
+
+ // This functon schedules native timers in order to wake up to
+ // process events and activate Qt timers. This is done using the
+ // emscripten_async_call() API which schedules a new timer.
+ // There is unfortunately no way to cancel or update a current
+ // native timer.
+
+ // Schedule a zero-timer to continue processing any pending events.
+ if (!m_hasZeroTimer && hasPendingEvents()) {
+ auto callback = [](void *eventDispatcher) {
+ QWasmEventDispatcher *that = static_cast<QWasmEventDispatcher *>(eventDispatcher);
+ that->m_hasZeroTimer = false;
+ that->QUnixEventDispatcherQPA::processEvents(QEventLoop::AllEvents);
+
+ // Processing events may have posted new events or created new timers
+ that->doMaintainTimers();
+ };
+
+ emscripten_async_call(callback, this, 0);
+ m_hasZeroTimer = true;
+ return;
+ }
+
+ auto timespecToNanosec = [](timespec ts) -> uint64_t { return ts.tv_sec * 1000 + ts.tv_nsec / (1000 * 1000); };
+
+ // Get current time and time-to-first-Qt-timer. This polls for system
+ // time, and we use this time as the current time for the duration of this call.
+ timespec toWait;
+ bool hasTimers = d->timerList.timerWait(toWait);
+ if (!hasTimers)
+ return; // no timer needed
+
+ uint64_t currentTime = timespecToNanosec(d->timerList.currentTime);
+ uint64_t toWaitDuration = timespecToNanosec(toWait);
+
+ // The currently scheduled timer target is stored in m_currentTargetTime.
+ // We can re-use it if the new target is equivalent or later.
+ uint64_t newTargetTime = currentTime + toWaitDuration;
+ if (newTargetTime >= m_currentTargetTime)
+ return; // existing timer is good
+
+ // Schedule a native timer with a callback which processes events (and timers)
+ auto callback = [](void *eventDispatcher) {
+ QWasmEventDispatcher *that = static_cast<QWasmEventDispatcher *>(eventDispatcher);
+ that->m_currentTargetTime = std::numeric_limits<uint64_t>::max();
+ that->QUnixEventDispatcherQPA::processEvents(QEventLoop::AllEvents);
+
+ // Processing events may have posted new events or created new timers
+ that->doMaintainTimers();
+ };
+ emscripten_async_call(callback, this, toWaitDuration);
+ m_currentTargetTime = newTargetTime;
+}
diff --git a/src/plugins/platforms/wasm/qwasmeventdispatcher.h b/src/plugins/platforms/wasm/qwasmeventdispatcher.h
new file mode 100644
index 0000000000..5300b3de73
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmeventdispatcher.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWASMEVENTDISPATCHER_H
+#define QWASMEVENTDISPATCHER_H
+
+#include <QtCore/qhash.h>
+#include <QtCore/qloggingcategory.h>
+#include <QtEventDispatcherSupport/private/qunixeventdispatcher_qpa_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWasmEventDispatcherPrivate;
+
+class QWasmEventDispatcher : public QUnixEventDispatcherQPA
+{
+ Q_DECLARE_PRIVATE(QWasmEventDispatcher)
+public:
+ explicit QWasmEventDispatcher(QObject *parent = nullptr);
+ ~QWasmEventDispatcher();
+
+ static bool registerRequestUpdateCallback(std::function<void(void)> callback);
+ static void maintainTimers();
+
+protected:
+ bool processEvents(QEventLoop::ProcessEventsFlags flags) override;
+ void doMaintainTimers();
+
+private:
+ bool m_hasMainLoop = false;
+ bool m_hasZeroTimer = false;
+ uint64_t m_currentTargetTime = std::numeric_limits<uint64_t>::max();
+ QVector<std::function<void(void)>> m_requestUpdateCallbacks;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
new file mode 100644
index 0000000000..a3fdcd1025
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
@@ -0,0 +1,558 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwasmeventtranslator.h"
+#include "qwasmeventdispatcher.h"
+#include "qwasmcompositor.h"
+#include "qwasmintegration.h"
+
+#include <QtGui/qevent.h>
+#include <qpa/qwindowsysteminterface.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qglobal.h>
+#include <QtCore/qobject.h>
+
+#include <QtCore/qdeadlinetimer.h>
+#include <emscripten/bind.h>
+
+#include <iostream>
+
+QT_BEGIN_NAMESPACE
+using namespace emscripten;
+
+// macOS CTRL <-> META switching. We most likely want to enable
+// the existing switching code in QtGui, but for now do it here.
+static bool g_usePlatformMacCtrlMetaSwitching = false;
+
+bool g_useNaturalScrolling = true; // natural scrolling is default on linux/windows
+
+void setNaturalScrolling(bool use) {
+ g_useNaturalScrolling = use;
+}
+
+EMSCRIPTEN_BINDINGS(mouse_module) {
+ function("setNaturalScrolling", &setNaturalScrolling);
+}
+
+QWasmEventTranslator::QWasmEventTranslator(QObject *parent)
+ : QObject(parent)
+ , draggedWindow(nullptr)
+ , pressedButtons(Qt::NoButton)
+ , resizeMode(QWasmWindow::ResizeNone)
+{
+ emscripten_set_keydown_callback(0, (void *)this, 1, &keyboard_cb);
+ emscripten_set_keyup_callback(0, (void *)this, 1, &keyboard_cb);
+
+ emscripten_set_mousedown_callback(0, (void *)this, 1, &mouse_cb);
+ emscripten_set_mouseup_callback(0, (void *)this, 1, &mouse_cb);
+ emscripten_set_mousemove_callback(0, (void *)this, 1, &mouse_cb);
+
+ emscripten_set_focus_callback(0, (void *)this, 1, &focus_cb);
+
+ emscripten_set_wheel_callback(0, (void *)this, 1, &wheel_cb);
+
+ touchDevice = new QTouchDevice;
+ touchDevice->setType(QTouchDevice::TouchScreen);
+ touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::NormalizedPosition);
+ QWindowSystemInterface::registerTouchDevice(touchDevice);
+
+ emscripten_set_touchstart_callback("#canvas", (void *)this, 1, &touchCallback);
+ emscripten_set_touchend_callback("#canvas", (void *)this, 1, &touchCallback);
+ emscripten_set_touchmove_callback("#canvas", (void *)this, 1, &touchCallback);
+ emscripten_set_touchcancel_callback("#canvas", (void *)this, 1, &touchCallback);
+
+ // The Platform Detect: expand coverage and move as needed
+ enum Platform {
+ GenericPlatform,
+ MacOSPlatform
+ };
+ Platform platform =
+ Platform(EM_ASM_INT("if (navigator.platform.includes(\"Mac\")) return 1; return 0;"));
+
+ g_usePlatformMacCtrlMetaSwitching = (platform == MacOSPlatform);
+
+ if (platform == MacOSPlatform) {
+ g_useNaturalScrolling = false; // make this !default on macOS
+ EM_ASM(
+ if (window.safari !== undefined) {//this only works on safari
+ Module["canvas"].addEventListener('wheel', mouseWheelEvent);
+ function mouseWheelEvent(e) {
+ if (event.webkitDirectionInvertedFromDevice) {
+ Module.setNaturalScrolling(event.webkitDirectionInvertedFromDevice);
+ }
+ }
+ }
+ );
+ }
+}
+
+template <typename Event>
+QFlags<Qt::KeyboardModifier> QWasmEventTranslator::translatKeyModifier(const Event *event)
+{
+ QFlags<Qt::KeyboardModifier> keyModifier = Qt::NoModifier;
+ if (event->shiftKey)
+ keyModifier |= Qt::ShiftModifier;
+ if (event->ctrlKey) {
+ if (g_usePlatformMacCtrlMetaSwitching)
+ keyModifier |= Qt::MetaModifier;
+ else
+ keyModifier |= Qt::ControlModifier;
+ }
+ if (event->altKey)
+ keyModifier |= Qt::AltModifier;
+ if (event->metaKey) {
+ if (g_usePlatformMacCtrlMetaSwitching)
+ keyModifier |= Qt::ControlModifier;
+ else
+ keyModifier |= Qt::MetaModifier;
+ }
+ return keyModifier;
+}
+
+QFlags<Qt::KeyboardModifier> QWasmEventTranslator::translateKeyboardEventModifier(const EmscriptenKeyboardEvent *keyEvent)
+{
+ QFlags<Qt::KeyboardModifier> keyModifier = translatKeyModifier(keyEvent);
+ if (keyEvent->location == DOM_KEY_LOCATION_NUMPAD) {
+ keyModifier |= Qt::KeypadModifier;
+ }
+
+ return keyModifier;
+}
+
+QFlags<Qt::KeyboardModifier> QWasmEventTranslator::translateMouseEventModifier(const EmscriptenMouseEvent *mouseEvent)
+{
+ return translatKeyModifier(mouseEvent);
+}
+
+int QWasmEventTranslator::keyboard_cb(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData)
+{
+ Q_UNUSED(userData)
+
+ bool alphanumeric;
+ Qt::Key qtKey = translateEmscriptKey(keyEvent, &alphanumeric);
+
+ QEvent::Type keyType = QEvent::None;
+ switch (eventType) {
+ case EMSCRIPTEN_EVENT_KEYPRESS:
+ case EMSCRIPTEN_EVENT_KEYDOWN: //down
+ keyType = QEvent::KeyPress;
+ break;
+ case EMSCRIPTEN_EVENT_KEYUP: //up
+ keyType = QEvent::KeyRelease;
+ break;
+ default:
+ break;
+ };
+
+ if (keyType == QEvent::None)
+ return 0;
+
+ QString keyText = alphanumeric ? QString(keyEvent->key) : QString();
+ bool accepted = QWindowSystemInterface::handleKeyEvent<QWindowSystemInterface::SynchronousDelivery>(
+ 0, keyType, qtKey, translateKeyboardEventModifier(keyEvent), keyText);
+ QWasmEventDispatcher::maintainTimers();
+ return accepted ? 1 : 0;
+}
+
+Qt::Key QWasmEventTranslator::translateEmscriptKey(const EmscriptenKeyboardEvent *emscriptKey, bool *outAlphanumeric)
+{
+ Qt::Key qtKey;
+ if (outAlphanumeric)
+ *outAlphanumeric = false;
+
+ switch (emscriptKey->keyCode) {
+ case KeyMultiply: qtKey = Qt::Key_Asterisk; *outAlphanumeric = true; break;
+ case KeyAdd: qtKey = Qt::Key_Plus; *outAlphanumeric = true; break;
+ case KeyMinus: qtKey = Qt::Key_Minus; *outAlphanumeric = true; break;
+ case KeySubtract: qtKey = Qt::Key_Minus; *outAlphanumeric = true; break;
+ case KeyDecimal: qtKey = Qt::Key_Period; *outAlphanumeric = true; break;
+ case KeyDivide: qtKey = Qt::Key_Slash; *outAlphanumeric = true; break;
+ case KeyNumPad0: qtKey = Qt::Key_0; *outAlphanumeric = true; break;
+ case KeyNumPad1: qtKey = Qt::Key_1; *outAlphanumeric = true; break;
+ case KeyNumPad2: qtKey = Qt::Key_2; *outAlphanumeric = true; break;
+ case KeyNumPad3: qtKey = Qt::Key_3; *outAlphanumeric = true; break;
+ case KeyNumPad4: qtKey = Qt::Key_4; *outAlphanumeric = true; break;
+ case KeyNumPad5: qtKey = Qt::Key_5; *outAlphanumeric = true; break;
+ case KeyNumPad6: qtKey = Qt::Key_6; *outAlphanumeric = true; break;
+ case KeyNumPad7: qtKey = Qt::Key_7; *outAlphanumeric = true; break;
+ case KeyNumPad8: qtKey = Qt::Key_8; *outAlphanumeric = true; break;
+ case KeyNumPad9: qtKey = Qt::Key_9; *outAlphanumeric = true; break;
+ case KeyComma: qtKey = Qt::Key_Comma; *outAlphanumeric = true; break;
+ case KeyPeriod: qtKey = Qt::Key_Period; *outAlphanumeric = true; break;
+ case KeySlash: qtKey = Qt::Key_Slash; *outAlphanumeric = true; break;
+ case KeySemiColon: qtKey = Qt::Key_Semicolon; *outAlphanumeric = true; break;
+ case KeyEquals: qtKey = Qt::Key_Equal; *outAlphanumeric = true; break;
+ case KeyOpenBracket: qtKey = Qt::Key_BracketLeft; *outAlphanumeric = true; break;
+ case KeyCloseBracket: qtKey = Qt::Key_BracketRight; *outAlphanumeric = true; break;
+ case KeyBackSlash: qtKey = Qt::Key_Backslash; *outAlphanumeric = true; break;
+ case KeyMeta:
+ Q_FALLTHROUGH();
+ case KeyMetaRight:
+ qtKey = Qt::Key_Meta;
+ break;
+ case KeyTab: qtKey = Qt::Key_Tab; break;
+ case KeyClear: qtKey = Qt::Key_Clear; break;
+ case KeyBackSpace: qtKey = Qt::Key_Backspace; break;
+ case KeyEnter: qtKey = Qt::Key_Return; break;
+ case KeyShift: qtKey = Qt::Key_Shift; break;
+ case KeyControl: qtKey = Qt::Key_Control; break;
+ case KeyAlt: qtKey = Qt::Key_Alt; break;
+ case KeyCapsLock: qtKey = Qt::Key_CapsLock; break;
+ case KeyEscape: qtKey = Qt::Key_Escape; break;
+ case KeyPageUp: qtKey = Qt::Key_PageUp; break;
+ case KeyPageDown: qtKey = Qt::Key_PageDown; break;
+ case KeyEnd: qtKey = Qt::Key_End; break;
+ case KeyHome: qtKey = Qt::Key_Home; break;
+ case KeyLeft: qtKey = Qt::Key_Left; break;
+ case KeyUp: qtKey = Qt::Key_Up; break;
+ case KeyRight: qtKey = Qt::Key_Right; break;
+ case KeyDown: qtKey = Qt::Key_Down; break;
+ case KeyBrightnessDown: qtKey = Qt::Key_MonBrightnessDown; break;
+ case KeyBrightnessUp: qtKey = Qt::Key_MonBrightnessUp; break;
+ case KeyMediaTrackPrevious: qtKey = Qt::Key_MediaPrevious; break;
+ case KeyMediaPlayPause: qtKey = Qt::Key_MediaTogglePlayPause; break;
+ case KeyMediaTrackNext: qtKey = Qt::Key_MediaNext; break;
+ case KeyAudioVolumeMute: qtKey = Qt::Key_VolumeMute; break;
+ case KeyAudioVolumeDown: qtKey = Qt::Key_VolumeDown; break;
+ case KeyAudioVolumeUp: qtKey = Qt::Key_VolumeUp; break;
+ case KeyDelete: qtKey = Qt::Key_Delete; break;
+
+ case KeyF1: qtKey = Qt::Key_F1; break;
+ case KeyF2: qtKey = Qt::Key_F2; break;
+ case KeyF3: qtKey = Qt::Key_F3; break;
+ case KeyF4: qtKey = Qt::Key_F4; break;
+ case KeyF5: qtKey = Qt::Key_F5; break;
+ case KeyF6: qtKey = Qt::Key_F6; break;
+ case KeyF7: qtKey = Qt::Key_F7; break;
+ case KeyF8: qtKey = Qt::Key_F8; break;
+ case KeyF9: qtKey = Qt::Key_F9; break;
+ case KeyF10: qtKey = Qt::Key_F10; break;
+ case KeyF11: qtKey = Qt::Key_F11; break;
+ case KeyF12: qtKey = Qt::Key_F12; break;
+ case 124: qtKey = Qt::Key_F13; break;
+ case 125: qtKey = Qt::Key_F14; break;
+
+ case KeySpace:
+ default:
+ if (outAlphanumeric)
+ *outAlphanumeric = true;
+ qtKey = static_cast<Qt::Key>(emscriptKey->keyCode);
+ break;
+ }
+
+ // Handle Mac command key. Using event->keyCode as above is
+ // no reliable since the codes differ between browsers.
+ if (qstrncmp(emscriptKey->key, "Meta", 4) == 0) {
+ qtKey = Qt::Key_Meta;
+ *outAlphanumeric = false;
+ }
+
+ if (g_usePlatformMacCtrlMetaSwitching) {
+ if (qtKey == Qt::Key_Meta)
+ qtKey = Qt::Key_Control;
+ else if (qtKey == Qt::Key_Control)
+ qtKey = Qt::Key_Meta;
+ }
+
+ return qtKey;
+}
+
+Qt::MouseButton QWasmEventTranslator::translateMouseButton(unsigned short button)
+{
+ if (button == 0)
+ return Qt::LeftButton;
+ else if (button == 1)
+ return Qt::MiddleButton;
+ else if (button == 2)
+ return Qt::RightButton;
+
+ return Qt::NoButton;
+}
+
+int QWasmEventTranslator::mouse_cb(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
+{
+ QWasmEventTranslator *translator = (QWasmEventTranslator*)userData;
+ translator->processMouse(eventType,mouseEvent);
+ QWasmEventDispatcher::maintainTimers();
+ return 0;
+}
+
+void resizeWindow(QWindow *window, QWasmWindow::ResizeMode mode,
+ QRect startRect, QPoint amount)
+{
+ if (mode == QWasmWindow::ResizeNone)
+ return;
+
+ bool top = mode == QWasmWindow::ResizeTopLeft ||
+ mode == QWasmWindow::ResizeTop ||
+ mode == QWasmWindow::ResizeTopRight;
+
+ bool bottom = mode == QWasmWindow::ResizeBottomLeft ||
+ mode == QWasmWindow::ResizeBottom ||
+ mode == QWasmWindow::ResizeBottomRight;
+
+ bool left = mode == QWasmWindow::ResizeLeft ||
+ mode == QWasmWindow::ResizeTopLeft ||
+ mode == QWasmWindow::ResizeBottomLeft;
+
+ bool right = mode == QWasmWindow::ResizeRight ||
+ mode == QWasmWindow::ResizeTopRight ||
+ mode == QWasmWindow::ResizeBottomRight;
+
+ int x1 = startRect.left();
+ int y1 = startRect.top();
+ int x2 = startRect.right();
+ int y2 = startRect.bottom();
+
+ if (left)
+ x1 += amount.x();
+ if (top)
+ y1 += amount.y();
+ if (right)
+ x2 += amount.x();
+ if (bottom)
+ y2 += amount.y();
+
+ int w = x2-x1;
+ int h = y2-y1;
+
+ if (w < window->minimumWidth()) {
+ if (left)
+ x1 -= window->minimumWidth() - w;
+
+ w = window->minimumWidth();
+ }
+
+ if (h < window->minimumHeight()) {
+ if (top)
+ y1 -= window->minimumHeight() - h;
+
+ h = window->minimumHeight();
+ }
+
+ window->setGeometry(x1, y1, w, h);
+}
+
+void QWasmEventTranslator::processMouse(int eventType, const EmscriptenMouseEvent *mouseEvent)
+{
+ auto timestamp = mouseEvent->timestamp;
+ QPoint point(mouseEvent->canvasX, mouseEvent->canvasY);
+
+ QEvent::Type buttonEventType = QEvent::None;
+
+ Qt::MouseButton button = translateMouseButton(mouseEvent->button);
+ Qt::KeyboardModifiers modifiers = translateMouseEventModifier(mouseEvent);
+
+ QWindow *window2 = QWasmIntegration::get()->compositor()->windowAt(point, 5);
+ QWasmWindow *htmlWindow = static_cast<QWasmWindow*>(window2->handle());
+ bool onFrame = false;
+ if (window2 && !window2->geometry().contains(point))
+ onFrame = true;
+
+ QPoint localPoint(point.x() - window2->geometry().x(), point.y() - window2->geometry().y());
+
+ switch (eventType) {
+ case 5: //down
+ {
+ if (window2)
+ window2->raise();
+
+ pressedButtons.setFlag(button);
+
+ if (mouseEvent->button == 0) {
+ pressedWindow = window2;
+ buttonEventType = QEvent::MouseButtonPress;
+ if (!(htmlWindow->m_windowState & Qt::WindowFullScreen) && !(htmlWindow->m_windowState & Qt::WindowMaximized)) {
+ if (htmlWindow && window2->flags().testFlag(Qt::WindowTitleHint) && htmlWindow->isPointOnTitle(point))
+ draggedWindow = window2;
+ else if (htmlWindow && htmlWindow->isPointOnResizeRegion(point)) {
+ draggedWindow = window2;
+ resizeMode = htmlWindow->resizeModeAtPoint(point);
+ resizePoint = point;
+ resizeStartRect = window2->geometry();
+ }
+ }
+ }
+
+ htmlWindow->injectMousePressed(localPoint, point, button, modifiers);
+ break;
+ }
+ case 6: //up
+ {
+ pressedButtons.setFlag(translateMouseButton(mouseEvent->button), false);
+ buttonEventType = QEvent::MouseButtonRelease;
+ QWasmWindow *oldWindow = nullptr;
+
+ if (mouseEvent->button == 0 && pressedWindow) {
+ oldWindow = static_cast<QWasmWindow*>(pressedWindow->handle());
+ pressedWindow = nullptr;
+ }
+
+
+ if (mouseEvent->button == 0) {
+ draggedWindow = nullptr;
+ resizeMode = QWasmWindow::ResizeNone;
+ }
+
+ if (oldWindow)
+ oldWindow->injectMouseReleased(localPoint, point, button, modifiers);
+ break;
+ }
+ case 8://move //drag event
+ {
+ buttonEventType = QEvent::MouseMove;
+ if (!(htmlWindow->m_windowState & Qt::WindowFullScreen) && !(htmlWindow->m_windowState & Qt::WindowMaximized)) {
+ if (resizeMode == QWasmWindow::ResizeNone && draggedWindow) {
+ draggedWindow->setX(draggedWindow->x() + mouseEvent->movementX);
+ draggedWindow->setY(draggedWindow->y() + mouseEvent->movementY);
+ }
+
+ if (resizeMode != QWasmWindow::ResizeNone && !(htmlWindow->m_windowState & Qt::WindowFullScreen)) {
+ QPoint delta = QPoint(mouseEvent->canvasX, mouseEvent->canvasY) - resizePoint;
+ resizeWindow(draggedWindow, resizeMode, resizeStartRect, delta);
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ };
+
+ if (window2 && !onFrame) {
+ QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>(
+ window2, timestamp, localPoint, point, pressedButtons, button, buttonEventType, modifiers);
+ }
+}
+
+int QWasmEventTranslator::focus_cb(int /*eventType*/, const EmscriptenFocusEvent */*focusEvent*/, void */*userData*/)
+{
+ return 0;
+}
+
+int QWasmEventTranslator::wheel_cb(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData)
+{
+ Q_UNUSED(eventType)
+ Q_UNUSED(userData)
+
+ EmscriptenMouseEvent mouseEvent = wheelEvent->mouse;
+
+ int scrollFactor = 0;
+ switch (wheelEvent->deltaMode) {
+ case DOM_DELTA_PIXEL://chrome safari
+ scrollFactor = 1;
+ break;
+ case DOM_DELTA_LINE: //firefox
+ scrollFactor = 12;
+ break;
+ case DOM_DELTA_PAGE:
+ scrollFactor = 20;
+ break;
+ };
+
+ if (g_useNaturalScrolling) //macOS platform has document oriented scrolling
+ scrollFactor = -scrollFactor;
+
+ Qt::KeyboardModifiers modifiers = translateMouseEventModifier(&mouseEvent);
+ auto timestamp = mouseEvent.timestamp;
+ QPoint globalPoint(mouseEvent.canvasX, mouseEvent.canvasY);
+
+ QWindow *window2 = QWasmIntegration::get()->compositor()->windowAt(globalPoint, 5);
+
+ QPoint localPoint(globalPoint.x() - window2->geometry().x(), globalPoint.y() - window2->geometry().y());
+
+ QPoint pixelDelta;
+
+ if (wheelEvent->deltaY != 0) pixelDelta.setY(wheelEvent->deltaY * scrollFactor);
+ if (wheelEvent->deltaX != 0) pixelDelta.setX(wheelEvent->deltaX * scrollFactor);
+
+ QWindowSystemInterface::handleWheelEvent(window2, timestamp, localPoint, globalPoint, QPoint(), pixelDelta, modifiers);
+
+ QWasmEventDispatcher::maintainTimers();
+
+ return 1;
+}
+
+int QWasmEventTranslator::touchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData)
+{
+ QList<QWindowSystemInterface::TouchPoint> touchPointList;
+ touchPointList.reserve(touchEvent->numTouches);
+ QWindow *window2;
+
+ for (int i = 0; i < touchEvent->numTouches; i++) {
+
+ const EmscriptenTouchPoint *touches = &touchEvent->touches[i];
+
+ QPoint point(touches->canvasX, touches->canvasY);
+ window2 = QWasmIntegration::get()->compositor()->windowAt(point, 5);
+
+ QWindowSystemInterface::TouchPoint touchPoint;
+
+ auto cX = point.x();
+ auto cY = point.y();
+ touchPoint.area = QRect(0, 0, 8, 8);
+ touchPoint.area.moveCenter(QPointF(cX,cY)); // simulate area
+
+ touchPoint.id = touches->identifier;
+ touchPoint.normalPosition = QPointF(cX / window2->width(), cY / window2->height());
+
+ switch (eventType) {
+ case EMSCRIPTEN_EVENT_TOUCHSTART:
+ touchPoint.state = Qt::TouchPointPressed;
+ break;
+ case EMSCRIPTEN_EVENT_TOUCHEND:
+ touchPoint.state = Qt::TouchPointReleased;
+ break;
+ case EMSCRIPTEN_EVENT_TOUCHMOVE:
+ touchPoint.state = Qt::TouchPointMoved;
+ break;
+ default:
+ Q_UNREACHABLE();
+ }
+
+ touchPointList.append(touchPoint);
+ }
+
+ QWasmEventTranslator *wasmEventTranslator = (QWasmEventTranslator*)userData;
+ QFlags<Qt::KeyboardModifier> keyModifier = translatKeyModifier(touchEvent);
+
+ if (eventType != EMSCRIPTEN_EVENT_TOUCHCANCEL)
+ QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::SynchronousDelivery>(window2, wasmEventTranslator->getTimestamp(), wasmEventTranslator->touchDevice, touchPointList, keyModifier);
+ else
+ QWindowSystemInterface::handleTouchCancelEvent(window2, wasmEventTranslator->getTimestamp(), wasmEventTranslator->touchDevice, keyModifier);
+
+ QWasmEventDispatcher::maintainTimers();
+ return 1;
+}
+
+quint64 QWasmEventTranslator::getTimestamp()
+{
+ return QDeadlineTimer::current().deadlineNSecs() / 1000;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.h b/src/plugins/platforms/wasm/qwasmeventtranslator.h
new file mode 100644
index 0000000000..11430a57a2
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmeventtranslator.h
@@ -0,0 +1,210 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWASMEVENTTRANSLATOR_H
+#define QWASMEVENTTRANSLATOR_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qpoint.h>
+#include <emscripten/html5.h>
+#include "qwasmwindow.h"
+#include <QtGui/qtouchdevice.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWindow;
+
+class QWasmEventTranslator : public QObject
+{
+ Q_OBJECT
+
+ enum KeyCode {
+ // numpad
+ KeyNumPad0 = 0x60,
+ KeyNumPad1 = 0x61,
+ KeyNumPad2 = 0x62,
+ KeyNumPad3 = 0x63,
+ KeyNumPad4 = 0x64,
+ KeyNumPad5 = 0x65,
+ KeyNumPad6 = 0x66,
+ KeyNumPad7 = 0x67,
+ KeyNumPad8 = 0x68,
+ KeyNumPad9 = 0x69,
+ KeyMultiply = 0x6A,
+ KeyAdd = 0x6B,
+ KeySeparator = 0x6C,
+ KeySubtract = 0x6D,
+ KeyDecimal = 0x6E,
+ KeyDivide = 0x6F,
+ KeyMeta = 0x5B,
+ KeyMetaRight = 0x5C,
+ ////////
+ KeyClear = 0x90,
+ KeyEnter = 0xD,
+ KeyBackSpace = 0x08,
+ KeyCancel = 0x03,
+ KeyTab = 0x09,
+ KeyShift = 0x10,
+ KeyControl = 0x11,
+ KeyAlt = 0x12,
+ KeyPause = 0x13,
+ KeyCapsLock = 0x14,
+ KeyEscape = 0x1B,
+ KeySpace = 0x20,
+ KeyPageUp = 0x21,
+ KeyPageDown = 0x22,
+ KeyEnd = 0x23,
+ KeyHome = 0x24,
+ KeyLeft = 0x25,
+ KeyUp = 0x26,
+ KeyRight = 0x27,
+ KeyDown = 0x28,
+ KeyComma = 0xBC,
+ KeyPeriod = 0xBE,
+ KeySlash = 0xBF,
+ KeyZero = 0x30,
+ KeyOne = 0x31,
+ KeyTwo = 0x32,
+ KeyThree = 0x33,
+ KeyFour = 0x34,
+ KeyFive = 0x35,
+ KeySix = 0x36,
+ KeySeven = 0x37,
+ KeyEight = 0x38,
+ KeyNine = 0x39,
+ KeyBrightnessDown = 0xD8,
+ KeyBrightnessUp = 0xD9,
+ KeyMediaTrackPrevious = 0xB1,
+ KeyMediaPlayPause = 0xB3,
+ KeyMediaTrackNext = 0xB0,
+ KeyAudioVolumeMute = 0xAD,
+ KeyAudioVolumeDown = 0xAE,
+ KeyAudioVolumeUp = 0xAF,
+ KeySemiColon = 0xBA,
+ KeyEquals = 0xBB,
+ KeyMinus = 0xBD,
+ KeyA = 0x41,
+ KeyB = 0x42,
+ KeyC = 0x43,
+ KeyD = 0x44,
+ KeyE = 0x45,
+ KeyF = 0x46,
+ KeyG = 0x47,
+ KeyH = 0x48,
+ KeyI = 0x49,
+ KeyJ = 0x4A,
+ KeyK = 0x4B,
+ KeyL = 0x4C,
+ KeyM = 0x4D,
+ KeyN = 0x4E,
+ KeyO = 0x4F,
+ KeyP = 0x50,
+ KeyQ = 0x51,
+ KeyR = 0x52,
+ KeyS = 0x53,
+ KeyT = 0x54,
+ KeyU = 0x55,
+ KeyV = 0x56,
+ KeyW = 0x57,
+ KeyX = 0x58,
+ KeyY = 0x59,
+ KeyZ = 0x5A,
+ KeyOpenBracket = 0xDB,
+ KeyBackSlash = 0xDC,
+ KeyCloseBracket = 0xDD,
+ KeyF1 = 0x70,
+ KeyF2 = 0x71,
+ KeyF3 = 0x72,
+ KeyF4 = 0x73,
+ KeyF5 = 0x74,
+ KeyF6 = 0x75,
+ KeyF7 = 0x76,
+ KeyF8 = 0x77,
+ KeyF9 = 0x78,
+ KeyF10 = 0x79,
+ KeyF11 = 0x7A,
+ KeyF12 = 0x7B,
+ KeyDelete = 0x2E,
+ KeyNumLock = 0x90,
+ KeyScrollLock = 0x91,
+ KeyPrintScreen = 0x9A,
+ KeyInsert = 0x9B,
+ KeyHelp = 0x9C,
+ KeyBackQuote = 0xC0,
+ KeyQuote = 0xDE,
+ KeyFinal = 0x18,
+ KeyConvert = 0x1C,
+ KeyNonConvert = 0x1D,
+ KeyAccept = 0x1E,
+ KeyModeChange = 0x1F,
+ KeyKana = 0x15,
+ KeyKanji = 0x19,
+ KeyUndefined = 0x0
+ };
+
+public:
+
+ explicit QWasmEventTranslator(QObject *parent = 0);
+
+ static int keyboard_cb(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData);
+ static int mouse_cb(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);
+ static int focus_cb(int eventType, const EmscriptenFocusEvent *focusEvent, void *userData);
+ static int wheel_cb(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData);
+
+ static int touchCallback(int eventType, const EmscriptenTouchEvent *ev, void *userData);
+
+ void processEvents();
+
+Q_SIGNALS:
+ void getWindowAt(const QPoint &point, QWindow **window);
+private:
+ static Qt::Key translateEmscriptKey(const EmscriptenKeyboardEvent *emscriptKey, bool *outAlphanumretic);
+ template <typename Event>
+ static QFlags<Qt::KeyboardModifier> translatKeyModifier(const Event *event);
+ static QFlags<Qt::KeyboardModifier> translateKeyboardEventModifier(const EmscriptenKeyboardEvent *keyEvent);
+ static QFlags<Qt::KeyboardModifier> translateMouseEventModifier(const EmscriptenMouseEvent *mouseEvent);
+ static Qt::MouseButton translateMouseButton(unsigned short button);
+
+ void processMouse(int eventType, const EmscriptenMouseEvent *mouseEvent);
+
+private:
+ QWindow *draggedWindow;
+ QWindow *pressedWindow;
+ Qt::MouseButtons pressedButtons;
+
+ QWasmWindow::ResizeMode resizeMode;
+ QPoint resizePoint;
+ QRect resizeStartRect;
+ QTouchDevice *touchDevice;
+ quint64 getTimestamp();
+};
+
+QT_END_NAMESPACE
+#endif // QWASMEVENTTRANSLATOR_H
diff --git a/src/plugins/platforms/wasm/qwasmfontdatabase.cpp b/src/plugins/platforms/wasm/qwasmfontdatabase.cpp
new file mode 100644
index 0000000000..0c72dfddc4
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmfontdatabase.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwasmfontdatabase.h"
+
+#include <QtCore/qfile.h>
+
+QT_BEGIN_NAMESPACE
+
+void QWasmFontDatabase::populateFontDatabase()
+{
+ // Load font file from resources. Currently
+ // all fonts needs to be bundled with the nexe
+ // as Qt resources.
+ QStringList fontFileNames = QStringList() << QStringLiteral(":/fonts/Vera.ttf")
+ << QStringLiteral(":/fonts/DejaVuSans.ttf");
+
+ foreach (const QString &fontFileName, fontFileNames) {
+ QFile theFont(fontFileName);
+ if (!theFont.open(QIODevice::ReadOnly))
+ break;
+
+ QFreeTypeFontDatabase::addTTFile(theFont.readAll(), fontFileName.toLatin1());
+ }
+}
+
+QFontEngine *QWasmFontDatabase::fontEngine(const QFontDef &fontDef, void *handle)
+{
+ return QFreeTypeFontDatabase::fontEngine(fontDef, handle);
+}
+
+QStringList QWasmFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style,
+ QFont::StyleHint styleHint,
+ QChar::Script script) const
+{
+ QStringList fallbacks
+ = QFreeTypeFontDatabase::fallbacksForFamily(family, style, styleHint, script);
+
+ // Add the vera.ttf font (loaded in populateFontDatabase above) as a falback font
+ // to all other fonts (except itself).
+ const QString veraFontFamily = QStringLiteral("Bitstream Vera Sans");
+ if (family != veraFontFamily)
+ fallbacks.append(veraFontFamily);
+
+ return fallbacks;
+}
+
+QStringList QWasmFontDatabase::addApplicationFont(const QByteArray &fontData,
+ const QString &fileName)
+{
+ return QFreeTypeFontDatabase::addApplicationFont(fontData, fileName);
+}
+
+void QWasmFontDatabase::releaseHandle(void *handle)
+{
+ QFreeTypeFontDatabase::releaseHandle(handle);
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmfontdatabase.h b/src/plugins/platforms/wasm/qwasmfontdatabase.h
new file mode 100644
index 0000000000..891f12859e
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmfontdatabase.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWASMFONTDATABASE_H
+#define QWASMFONTDATABASE_H
+
+#include <QtFontDatabaseSupport/private/qfreetypefontdatabase_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWasmFontDatabase : public QFreeTypeFontDatabase
+{
+public:
+ void populateFontDatabase() override;
+ QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override;
+ QStringList fallbacksForFamily(const QString &family, QFont::Style style,
+ QFont::StyleHint styleHint,
+ QChar::Script script) const override;
+ QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName) override;
+ void releaseHandle(void *handle) override;
+};
+QT_END_NAMESPACE
+#endif
diff --git a/src/plugins/platforms/wasm/qwasmintegration.cpp b/src/plugins/platforms/wasm/qwasmintegration.cpp
new file mode 100644
index 0000000000..1be909f0a0
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmintegration.cpp
@@ -0,0 +1,219 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwasmintegration.h"
+#include "qwasmeventtranslator.h"
+#include "qwasmeventdispatcher.h"
+#include "qwasmcompositor.h"
+#include "qwasmopenglcontext.h"
+#include "qwasmtheme.h"
+
+#include "qwasmwindow.h"
+#ifndef QT_NO_OPENGL
+# include "qwasmbackingstore.h"
+#endif
+#include "qwasmfontdatabase.h"
+#if defined(Q_OS_UNIX)
+#include <QtEventDispatcherSupport/private/qgenericunixeventdispatcher_p.h>
+#endif
+#include <qpa/qplatformwindow.h>
+#include <QtGui/qscreen.h>
+#include <qpa/qwindowsysteminterface.h>
+#include <QtCore/qcoreapplication.h>
+
+#include <emscripten/bind.h>
+
+// this is where EGL headers are pulled in, make sure it is last
+#include "qwasmscreen.h"
+
+using namespace emscripten;
+QT_BEGIN_NAMESPACE
+
+void browserBeforeUnload()
+{
+ QWasmIntegration::QWasmBrowserExit();
+}
+
+EMSCRIPTEN_BINDINGS(my_module)
+{
+ function("browserBeforeUnload", &browserBeforeUnload);
+}
+
+static QWasmIntegration *globalHtml5Integration;
+QWasmIntegration *QWasmIntegration::get() { return globalHtml5Integration; }
+
+QWasmIntegration::QWasmIntegration()
+ : m_fontDb(nullptr),
+ m_compositor(new QWasmCompositor),
+ m_screen(new QWasmScreen(m_compositor)),
+ m_eventDispatcher(nullptr)
+{
+
+ globalHtml5Integration = this;
+
+ updateQScreenAndCanvasRenderSize();
+ screenAdded(m_screen);
+ emscripten_set_resize_callback(0, (void *)this, 1, uiEvent_cb);
+
+ m_eventTranslator = new QWasmEventTranslator;
+
+ EM_ASM(// exit app if browser closes
+ window.onbeforeunload = function () {
+ Module.browserBeforeUnload();
+ };
+ );
+}
+
+QWasmIntegration::~QWasmIntegration()
+{
+ delete m_compositor;
+ destroyScreen(m_screen);
+ delete m_fontDb;
+ delete m_eventTranslator;
+}
+
+void QWasmIntegration::QWasmBrowserExit()
+{
+ QCoreApplication *app = QCoreApplication::instance();
+ app->quit();
+}
+
+bool QWasmIntegration::hasCapability(QPlatformIntegration::Capability cap) const
+{
+ switch (cap) {
+ case ThreadedPixmaps: return true;
+ case OpenGL: return true;
+ case ThreadedOpenGL: return true;
+ case RasterGLSurface: return false; // to enable this you need to fix qopenglwidget and quickwidget for wasm
+ case MultipleWindows: return true;
+ case WindowManagement: return true;
+ default: return QPlatformIntegration::hasCapability(cap);
+ }
+}
+
+QPlatformWindow *QWasmIntegration::createPlatformWindow(QWindow *window) const
+{
+ return new QWasmWindow(window, m_compositor, m_backingStores.value(window));
+}
+
+QPlatformBackingStore *QWasmIntegration::createPlatformBackingStore(QWindow *window) const
+{
+#ifndef QT_NO_OPENGL
+ QWasmBackingStore *backingStore = new QWasmBackingStore(m_compositor, window);
+ m_backingStores.insert(window, backingStore);
+ return backingStore;
+#else
+ return nullptr;
+#endif
+}
+
+#ifndef QT_NO_OPENGL
+QPlatformOpenGLContext *QWasmIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
+{
+ return new QWasmOpenGLContext(context->format());
+}
+#endif
+
+QPlatformFontDatabase *QWasmIntegration::fontDatabase() const
+{
+ if (m_fontDb == nullptr)
+ m_fontDb = new QWasmFontDatabase;
+
+ return m_fontDb;
+}
+
+QAbstractEventDispatcher *QWasmIntegration::createEventDispatcher() const
+{
+ return new QWasmEventDispatcher;
+}
+
+QVariant QWasmIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
+{
+ return QPlatformIntegration::styleHint(hint);
+}
+
+QStringList QWasmIntegration::themeNames() const
+{
+ return QStringList() << QLatin1String("webassembly");
+}
+
+QPlatformTheme *QWasmIntegration::createPlatformTheme(const QString &name) const
+{
+ if (name == QLatin1String("webassembly"))
+ return new QWasmTheme;
+ return QPlatformIntegration::createPlatformTheme(name);
+}
+
+int QWasmIntegration::uiEvent_cb(int eventType, const EmscriptenUiEvent *e, void *userData)
+{
+ Q_UNUSED(e)
+ Q_UNUSED(userData)
+
+ if (eventType == EMSCRIPTEN_EVENT_RESIZE) {
+ // This resize event is called when the HTML window is resized. Depending
+ // on the page layout the the canvas might also have been resized, so we
+ // update the Qt screen size (and canvas render size).
+ updateQScreenAndCanvasRenderSize();
+ }
+
+ return 0;
+}
+
+static void set_canvas_size(double width, double height)
+{
+ EM_ASM_({
+ var canvas = Module.canvas;
+ canvas.width = $0;
+ canvas.height = $1;
+ }, width, height);
+}
+
+void QWasmIntegration::updateQScreenAndCanvasRenderSize()
+{
+ // The HTML canvas has two sizes: the CSS size and the canvas render size.
+ // The CSS size is determined according to standard CSS rules, while the
+ // render size is set using the "width" and "height" attributes. The render
+ // size must be set manually and is not auto-updated on CSS size change.
+ // Setting the render size to a value larger than the CSS size enables high-dpi
+ // rendering.
+
+ double css_width;
+ double css_height;
+ emscripten_get_element_css_size(0, &css_width, &css_height);
+ QSizeF cssSize(css_width, css_height);
+
+ QWasmScreen *screen = QWasmIntegration::get()->m_screen;
+ QSizeF canvasSize = cssSize * screen->devicePixelRatio();
+
+ set_canvas_size(canvasSize.width(), canvasSize.height());
+ screen->setGeometry(QRect(QPoint(0, 0), cssSize.toSize()));
+ QWasmIntegration::get()->m_compositor->redrawWindowContent();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmintegration.h b/src/plugins/platforms/wasm/qwasmintegration.h
new file mode 100644
index 0000000000..ebc3d9d431
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmintegration.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWASMINTEGRATION_H
+#define QWASMINTEGRATION_H
+
+#include "qwasmwindow.h"
+
+#include <qpa/qplatformintegration.h>
+#include <qpa/qplatformscreen.h>
+
+#include <QtCore/qhash.h>
+
+#include <emscripten.h>
+#include <emscripten/html5.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWasmEventTranslator;
+class QWasmFontDatabase;
+class QWasmWindow;
+class QWasmEventDispatcher;
+class QWasmScreen;
+class QWasmCompositor;
+class QWasmBackingStore;
+
+class QWasmIntegration : public QObject, public QPlatformIntegration
+{
+ Q_OBJECT
+public:
+ QWasmIntegration();
+ ~QWasmIntegration();
+
+ bool hasCapability(QPlatformIntegration::Capability cap) const override;
+ QPlatformWindow *createPlatformWindow(QWindow *window) const override;
+ QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override;
+#ifndef QT_NO_OPENGL
+ QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override;
+#endif
+ QPlatformFontDatabase *fontDatabase() const override;
+ QAbstractEventDispatcher *createEventDispatcher() const override;
+ QVariant styleHint(QPlatformIntegration::StyleHint hint) const override;
+ QStringList themeNames() const override;
+ QPlatformTheme *createPlatformTheme(const QString &name) const override;
+
+ static QWasmIntegration *get();
+ QWasmScreen *screen() { return m_screen; }
+ QWasmCompositor *compositor() { return m_compositor; }
+ QWasmEventTranslator *eventTranslator() { return m_eventTranslator; }
+
+ static void QWasmBrowserExit();
+ static void updateQScreenAndCanvasRenderSize();
+
+private:
+ mutable QWasmFontDatabase *m_fontDb;
+ QWasmCompositor *m_compositor;
+ mutable QWasmScreen *m_screen;
+ mutable QWasmEventTranslator *m_eventTranslator;
+ mutable QWasmEventDispatcher *m_eventDispatcher;
+ static int uiEvent_cb(int eventType, const EmscriptenUiEvent *e, void *userData);
+ mutable QHash<QWindow *, QWasmBackingStore *> m_backingStores;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWASMINTEGRATION_H
diff --git a/src/plugins/platforms/wasm/qwasmopenglcontext.cpp b/src/plugins/platforms/wasm/qwasmopenglcontext.cpp
new file mode 100644
index 0000000000..73af3d1878
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmopenglcontext.cpp
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwasmopenglcontext.h"
+
+#include <EGL/egl.h>
+
+QT_BEGIN_NAMESPACE
+
+QWasmOpenGLContext::QWasmOpenGLContext(const QSurfaceFormat &format)
+ : m_requestedFormat(format)
+{
+ m_requestedFormat.setRenderableType(QSurfaceFormat::OpenGLES);
+}
+
+QWasmOpenGLContext::~QWasmOpenGLContext()
+{
+ if (m_context)
+ emscripten_webgl_destroy_context(m_context);
+}
+
+void QWasmOpenGLContext::maybeRecreateEmscriptenContext(QPlatformSurface *surface)
+{
+ // Native emscripten contexts are tied to a single surface. Recreate
+ // the context if the surface is changed.
+ if (surface != m_surface) {
+ m_surface = surface;
+
+ // Destroy existing context
+ if (m_context)
+ emscripten_webgl_destroy_context(m_context);
+
+ // Create new context
+ const char *canvasId = 0; // (use default canvas) FIXME: get the actual canvas from the surface.
+ m_context = createEmscriptenContext(canvasId, m_requestedFormat);
+
+ // Register context-lost callback.
+ auto callback = [](int eventType, const void *reserved, void *userData) -> EM_BOOL
+ {
+ Q_UNUSED(eventType);
+ Q_UNUSED(reserved);
+ // The application may get contex-lost if e.g. moved to the background. Set
+ // m_contextLost which will make isValid() return false. Application code will
+ // then detect this and recrate the the context, resulting in a new QWasmOpenGLContext
+ // instance.
+ reinterpret_cast<QWasmOpenGLContext *>(userData)->m_contextLost = true;
+ return true;
+ };
+ bool capture = true;
+ emscripten_set_webglcontextlost_callback(canvasId, this, capture, callback);
+ }
+}
+
+EMSCRIPTEN_WEBGL_CONTEXT_HANDLE QWasmOpenGLContext::createEmscriptenContext(const char *canvasId, QSurfaceFormat format)
+{
+ EmscriptenWebGLContextAttributes attributes;
+ emscripten_webgl_init_context_attributes(&attributes); // Populate with default attributes
+
+ attributes.preferLowPowerToHighPerformance = false;
+ attributes.failIfMajorPerformanceCaveat = false;
+ attributes.antialias = true;
+ attributes.enableExtensionsByDefault = true;
+
+ if (format.majorVersion() == 3) {
+ attributes.majorVersion = 2;
+ }
+
+ // WebGL offers enable/disable control but not size control for these
+ attributes.alpha = format.alphaBufferSize() > 0;
+ attributes.depth = format.depthBufferSize() > 0;
+ attributes.stencil = format.stencilBufferSize() > 0;
+
+ EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context = emscripten_webgl_create_context(canvasId, &attributes);
+
+ return context;
+}
+
+QSurfaceFormat QWasmOpenGLContext::format() const
+{
+ return m_requestedFormat;
+}
+
+GLuint QWasmOpenGLContext::defaultFramebufferObject(QPlatformSurface *surface) const
+{
+ return QPlatformOpenGLContext::defaultFramebufferObject(surface);
+}
+
+bool QWasmOpenGLContext::makeCurrent(QPlatformSurface *surface)
+{
+ maybeRecreateEmscriptenContext(surface);
+
+ return emscripten_webgl_make_context_current(m_context) == EMSCRIPTEN_RESULT_SUCCESS;
+}
+
+void QWasmOpenGLContext::swapBuffers(QPlatformSurface *surface)
+{
+ Q_UNUSED(surface);
+ // No swapbuffers on WebGl
+}
+
+void QWasmOpenGLContext::doneCurrent()
+{
+ // No doneCurrent on WebGl
+}
+
+bool QWasmOpenGLContext::isSharing() const
+{
+ return false;
+}
+
+bool QWasmOpenGLContext::isValid() const
+{
+ return (m_contextLost == false);
+}
+
+QFunctionPointer QWasmOpenGLContext::getProcAddress(const char *procName)
+{
+ return reinterpret_cast<QFunctionPointer>(eglGetProcAddress(procName));
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmopenglcontext.h b/src/plugins/platforms/wasm/qwasmopenglcontext.h
new file mode 100644
index 0000000000..9123100479
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmopenglcontext.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qpa/qplatformopenglcontext.h>
+
+#include <emscripten.h>
+#include <emscripten/html5.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWasmOpenGLContext : public QPlatformOpenGLContext
+{
+public:
+ QWasmOpenGLContext(const QSurfaceFormat &format);
+ ~QWasmOpenGLContext();
+
+ QSurfaceFormat format() const override;
+ void swapBuffers(QPlatformSurface *surface) override;
+ GLuint defaultFramebufferObject(QPlatformSurface *surface) const override;
+ bool makeCurrent(QPlatformSurface *surface) override;
+ void doneCurrent() override;
+ bool isSharing() const override;
+ bool isValid() const override;
+ QFunctionPointer getProcAddress(const char *procName) override;
+
+private:
+ void maybeRecreateEmscriptenContext(QPlatformSurface *surface);
+ static EMSCRIPTEN_WEBGL_CONTEXT_HANDLE createEmscriptenContext(const char *canvasId, QSurfaceFormat format);
+
+ bool m_contextLost = false;
+ QSurfaceFormat m_requestedFormat;
+ QPlatformSurface *m_surface = nullptr;
+ EMSCRIPTEN_WEBGL_CONTEXT_HANDLE m_context = 0;
+};
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/wasm/qwasmscreen.cpp b/src/plugins/platforms/wasm/qwasmscreen.cpp
new file mode 100644
index 0000000000..93e9906ffc
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmscreen.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwasmscreen.h"
+#include "qwasmwindow.h"
+#include "qwasmcompositor.h"
+
+#include <QtEglSupport/private/qeglconvenience_p.h>
+#ifndef QT_NO_OPENGL
+# include <QtEglSupport/private/qeglplatformcontext_p.h>
+#endif
+#include <qpa/qwindowsysteminterface.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtGui/qguiapplication.h>
+#include <private/qhighdpiscaling_p.h>
+
+
+QT_BEGIN_NAMESPACE
+
+QWasmScreen::QWasmScreen(QWasmCompositor *compositor)
+ : m_compositor(compositor)
+ , m_depth(32)
+ , m_format(QImage::Format_RGB32)
+{
+ m_compositor->setScreen(this);
+}
+
+QWasmScreen::~QWasmScreen()
+{
+
+}
+
+QRect QWasmScreen::geometry() const
+{
+ return m_geometry;
+}
+
+int QWasmScreen::depth() const
+{
+ return m_depth;
+}
+
+QImage::Format QWasmScreen::format() const
+{
+ return m_format;
+}
+
+qreal QWasmScreen::devicePixelRatio() const
+{
+ // FIXME: The effective device pixel ratio may be different from the
+ // HTML window dpr if the OpenGL driver/GPU allocates a less than
+ // full resolution surface. Use emscripten_webgl_get_drawing_buffer_size()
+ // and compute the dpr instead.
+ double htmlWindowDpr = EM_ASM_DOUBLE({
+ return window.devicePixelRatio;
+ });
+ return qreal(htmlWindowDpr);
+}
+
+QPlatformCursor *QWasmScreen::cursor() const
+{
+ return const_cast<QWasmCursor *>(&m_cursor);
+}
+
+void QWasmScreen::resizeMaximizedWindows()
+{
+ QPlatformScreen::resizeMaximizedWindows();
+}
+
+QWindow *QWasmScreen::topWindow() const
+{
+ return m_compositor->keyWindow();
+}
+
+QWindow *QWasmScreen::topLevelAt(const QPoint &p) const
+{
+ return m_compositor->windowAt(p);
+}
+
+void QWasmScreen::invalidateSize()
+{
+ m_geometry = QRect();
+}
+
+void QWasmScreen::setGeometry(const QRect &rect)
+{
+ m_geometry = rect;
+ QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry());
+ resizeMaximizedWindows();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmscreen.h b/src/plugins/platforms/wasm/qwasmscreen.h
new file mode 100644
index 0000000000..3891db77bb
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmscreen.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWASMSCREEN_H
+#define QWASMSCREEN_H
+
+#include "qwasmcursor.h"
+
+#include <qpa/qplatformscreen.h>
+
+#include <QtCore/qscopedpointer.h>
+#include <QtCore/qtextstream.h>
+
+QT_BEGIN_NAMESPACE
+
+class QPlatformOpenGLContext;
+class QWasmWindow;
+class QWasmBackingStore;
+class QWasmCompositor;
+class QOpenGLContext;
+
+class QWasmScreen : public QObject, public QPlatformScreen
+{
+ Q_OBJECT
+public:
+
+ QWasmScreen(QWasmCompositor *compositor);
+ ~QWasmScreen();
+
+ QRect geometry() const override;
+ int depth() const override;
+ QImage::Format format() const override;
+ qreal devicePixelRatio() const override;
+ QPlatformCursor *cursor() const override;
+
+ void resizeMaximizedWindows();
+ QWindow *topWindow() const;
+ QWindow *topLevelAt(const QPoint &p) const override;
+
+ void invalidateSize();
+
+public slots:
+ void setGeometry(const QRect &rect);
+protected:
+
+private:
+ QWasmCompositor *m_compositor;
+
+ QRect m_geometry = QRect(0, 0, 100, 100);
+ int m_depth;
+ QImage::Format m_format;
+ QWasmCursor m_cursor;
+};
+
+QT_END_NAMESPACE
+#endif // QWASMSCREEN_H
diff --git a/src/plugins/platforms/wasm/qwasmstylepixmaps_p.h b/src/plugins/platforms/wasm/qwasmstylepixmaps_p.h
new file mode 100644
index 0000000000..2b5860f42f
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmstylepixmaps_p.h
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWASMSTYLEPIXMAPS_P_H
+#define QWASMSTYLEPIXMAPS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+/* XPM */
+static const char * const qt_menu_xpm[] = {
+"16 16 72 1",
+" c None",
+". c #65AF36",
+"+ c #66B036",
+"@ c #77B94C",
+"# c #A7D28C",
+"$ c #BADBA4",
+"% c #A4D088",
+"& c #72B646",
+"* c #9ACB7A",
+"= c #7FBD56",
+"- c #85C05F",
+"; c #F4F9F0",
+"> c #FFFFFF",
+", c #E5F1DC",
+"' c #ECF5E7",
+") c #7ABA50",
+"! c #83BF5C",
+"~ c #AED595",
+"{ c #D7EACA",
+"] c #A9D28D",
+"^ c #BCDDA8",
+"/ c #C4E0B1",
+"( c #81BE59",
+"_ c #D0E7C2",
+": c #D4E9C6",
+"< c #6FB542",
+"[ c #6EB440",
+"} c #88C162",
+"| c #98CA78",
+"1 c #F4F9F1",
+"2 c #8FC56C",
+"3 c #F1F8EC",
+"4 c #E8F3E1",
+"5 c #D4E9C7",
+"6 c #74B748",
+"7 c #80BE59",
+"8 c #73B747",
+"9 c #6DB43F",
+"0 c #CBE4BA",
+"a c #80BD58",
+"b c #6DB33F",
+"c c #FEFFFE",
+"d c #68B138",
+"e c #F9FCF7",
+"f c #91C66F",
+"g c #E8F3E0",
+"h c #DCEDD0",
+"i c #91C66E",
+"j c #A3CF86",
+"k c #C9E3B8",
+"l c #B0D697",
+"m c #E3F0DA",
+"n c #95C873",
+"o c #E6F2DE",
+"p c #9ECD80",
+"q c #BEDEAA",
+"r c #C7E2B6",
+"s c #79BA4F",
+"t c #6EB441",
+"u c #BCDCA7",
+"v c #FAFCF8",
+"w c #F6FAF3",
+"x c #84BF5D",
+"y c #EDF6E7",
+"z c #FAFDF9",
+"A c #88C263",
+"B c #98CA77",
+"C c #CDE5BE",
+"D c #67B037",
+"E c #D9EBCD",
+"F c #6AB23C",
+"G c #77B94D",
+" .++++++++++++++",
+".+++++++++++++++",
+"+++@#$%&+++*=+++",
+"++-;>,>')+!>~+++",
+"++{>]+^>/(_>:~<+",
+"+[>>}+|>123>456+",
+"+7>>8+->>90>~+++",
+"+a>>b+a>c[0>~+++",
+"+de>=+f>g+0>~+++",
+"++h>i+j>k+0>~+++",
+"++l>mno>p+q>rst+",
+"++duv>wl++xy>zA+",
+"++++B>Cb++++&D++",
+"+++++0zE++++++++",
+"++++++FG+++++++.",
+"++++++++++++++. "};
+
+static const char * const qt_close_xpm[] = {
+"10 10 2 1",
+"# c #000000",
+". c None",
+"..........",
+".##....##.",
+"..##..##..",
+"...####...",
+"....##....",
+"...####...",
+"..##..##..",
+".##....##.",
+"..........",
+".........."};
+
+static const char * const qt_maximize_xpm[]={
+"10 10 2 1",
+"# c #000000",
+". c None",
+"#########.",
+"#########.",
+"#.......#.",
+"#.......#.",
+"#.......#.",
+"#.......#.",
+"#.......#.",
+"#.......#.",
+"#########.",
+".........."};
+
+
+static const char * const qt_normalizeup_xpm[] = {
+"10 10 2 1",
+"# c #000000",
+". c None",
+"...######.",
+"...######.",
+"...#....#.",
+".######.#.",
+".######.#.",
+".#....###.",
+".#....#...",
+".#....#...",
+".######...",
+".........."};
+
+
+#endif // QWASMSTYLEPIXMAPS_P_H
diff --git a/src/plugins/platforms/wasm/qwasmtheme.cpp b/src/plugins/platforms/wasm/qwasmtheme.cpp
new file mode 100644
index 0000000000..a7f2db3bd3
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmtheme.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwasmtheme.h"
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+QWasmTheme::QWasmTheme()
+{
+}
+
+QWasmTheme::~QWasmTheme()
+{
+}
+
+QVariant QWasmTheme::themeHint(ThemeHint hint) const
+{
+ if (hint == QPlatformTheme::StyleNames)
+ return QVariant(QStringList() << QLatin1String("fusion"));
+ return QPlatformTheme::themeHint(hint);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmtheme.h b/src/plugins/platforms/wasm/qwasmtheme.h
new file mode 100644
index 0000000000..e4cc06e049
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmtheme.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWASMTHEME_H
+#define QWASMTHEME_H
+
+#include <qpa/qplatformtheme.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWasmEventTranslator;
+class QWasmFontDatabase;
+class QWasmWindow;
+class QWasmEventDispatcher;
+class QWasmScreen;
+class QWasmCompositor;
+class QWasmBackingStore;
+
+class QWasmTheme : public QPlatformTheme
+{
+public:
+ QWasmTheme();
+ ~QWasmTheme();
+
+ QVariant themeHint(ThemeHint hint) const override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWASMTHEME_H
diff --git a/src/plugins/platforms/wasm/qwasmwindow.cpp b/src/plugins/platforms/wasm/qwasmwindow.cpp
new file mode 100644
index 0000000000..c4167be71e
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmwindow.cpp
@@ -0,0 +1,401 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qpa/qwindowsysteminterface.h>
+#include <private/qguiapplication_p.h>
+#include <QtGui/private/qopenglcontext_p.h>
+#include <QtGui/private/qwindow_p.h>
+#include <QtGui/qopenglcontext.h>
+
+#include "qwasmwindow.h"
+#include "qwasmscreen.h"
+#include "qwasmcompositor.h"
+#include "qwasmeventdispatcher.h"
+
+#include <iostream>
+
+Q_GUI_EXPORT int qt_defaultDpiX();
+
+QT_BEGIN_NAMESPACE
+
+QWasmWindow::QWasmWindow(QWindow *w, QWasmCompositor *compositor, QWasmBackingStore *backingStore)
+ : QPlatformWindow(w),
+ m_window(w),
+ m_compositor(compositor),
+ m_backingStore(backingStore)
+{
+ m_needsCompositor = w->surfaceType() != QSurface::OpenGLSurface;
+ static int serialNo = 0;
+ m_winid = ++serialNo;
+ qWarning("QWasmWindow %p: %p 0x%x\n", this, w, uint(m_winid));
+
+ m_compositor->addWindow(this);
+
+ // Pure OpenGL windows draw directly using egl, disable the compositor.
+ m_compositor->setEnabled(w->surfaceType() != QSurface::OpenGLSurface);
+}
+
+QWasmWindow::~QWasmWindow()
+{
+ m_compositor->removeWindow(this);
+}
+
+void QWasmWindow::initialize()
+{
+ QRect rect = windowGeometry();
+
+ QPlatformWindow::setGeometry(rect);
+
+ const QSize minimumSize = windowMinimumSize();
+ if (rect.width() > 0 || rect.height() > 0) {
+ rect.setWidth(qBound(1, rect.width(), 2000));
+ rect.setHeight(qBound(1, rect.height(), 2000));
+ } else if (minimumSize.width() > 0 || minimumSize.height() > 0) {
+ rect.setSize(minimumSize);
+ }
+
+ setWindowState(window()->windowStates());
+ setWindowFlags(window()->flags());
+ setWindowTitle(window()->title());
+ if (window()->isTopLevel())
+ setWindowIcon(window()->icon());
+ m_normalGeometry = rect;
+}
+
+QWasmScreen *QWasmWindow::platformScreen() const
+{
+ return static_cast<QWasmScreen *>(window()->screen()->handle());
+}
+
+void QWasmWindow::setGeometry(const QRect &rect)
+{
+ QRect r = rect;
+ if (m_needsCompositor) {
+ int yMin = window()->geometry().top() - window()->frameGeometry().top();
+
+ if (r.y() < yMin)
+ r.moveTop(yMin);
+ }
+ QWindowSystemInterface::handleGeometryChange(window(), r);
+ QPlatformWindow::setGeometry(r);
+
+ QWindowSystemInterface::flushWindowSystemEvents();
+ invalidate();
+}
+
+void QWasmWindow::setVisible(bool visible)
+{
+ QRect newGeom;
+
+ if (visible) {
+ const bool forceFullScreen = !m_needsCompositor;//make gl apps fullscreen for now
+
+ if (forceFullScreen || (m_windowState & Qt::WindowFullScreen))
+ newGeom = platformScreen()->geometry();
+ else if (m_windowState & Qt::WindowMaximized)
+ newGeom = platformScreen()->availableGeometry();
+ }
+ QPlatformWindow::setVisible(visible);
+
+ m_compositor->setVisible(this, visible);
+
+ if (!newGeom.isEmpty())
+ setGeometry(newGeom); // may or may not generate an expose
+
+ invalidate();
+}
+
+QMargins QWasmWindow::frameMargins() const
+{
+ int border = hasTitleBar() ? 4. * (qreal(qt_defaultDpiX()) / 96.0) : 0;
+ int titleBarHeight = hasTitleBar() ? titleHeight() : 0;
+
+ QMargins margins;
+ margins.setLeft(border);
+ margins.setRight(border);
+ margins.setTop(2*border + titleBarHeight);
+ margins.setBottom(border);
+
+ return margins;
+}
+
+void QWasmWindow::raise()
+{
+ m_compositor->raise(this);
+ QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), geometry().size()));
+ invalidate();
+}
+
+void QWasmWindow::lower()
+{
+ m_compositor->lower(this);
+ QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), geometry().size()));
+ invalidate();
+}
+
+WId QWasmWindow::winId() const
+{
+ return m_winid;
+}
+
+void QWasmWindow::propagateSizeHints()
+{
+// get rid of base class warning
+}
+
+void QWasmWindow::injectMousePressed(const QPoint &local, const QPoint &global,
+ Qt::MouseButton button, Qt::KeyboardModifiers mods)
+{
+ Q_UNUSED(local);
+ Q_UNUSED(mods);
+
+ if (!hasTitleBar() || button != Qt::LeftButton)
+ return;
+
+ if (maxButtonRect().contains(global))
+ m_activeControl = QWasmCompositor::SC_TitleBarMaxButton;
+ else if (minButtonRect().contains(global))
+ m_activeControl = QWasmCompositor::SC_TitleBarMinButton;
+ else if (closeButtonRect().contains(global))
+ m_activeControl = QWasmCompositor::SC_TitleBarCloseButton;
+ else if (normButtonRect().contains(global))
+ m_activeControl = QWasmCompositor::SC_TitleBarNormalButton;
+
+ invalidate();
+}
+
+void QWasmWindow::injectMouseReleased(const QPoint &local, const QPoint &global,
+ Qt::MouseButton button, Qt::KeyboardModifiers mods)
+{
+ Q_UNUSED(local);
+ Q_UNUSED(mods);
+
+ if (!hasTitleBar() || button != Qt::LeftButton)
+ return;
+
+ if (closeButtonRect().contains(global) && m_activeControl == QWasmCompositor::SC_TitleBarCloseButton)
+ window()->close();
+
+ if (maxButtonRect().contains(global) && m_activeControl == QWasmCompositor::SC_TitleBarMaxButton) {
+ window()->setWindowState(Qt::WindowMaximized);
+ platformScreen()->resizeMaximizedWindows();
+ }
+
+ if (normButtonRect().contains(global) && m_activeControl == QWasmCompositor::SC_TitleBarNormalButton) {
+ window()->setWindowState(Qt::WindowNoState);
+ setGeometry(normalGeometry());
+ }
+
+ m_activeControl = QWasmCompositor::SC_None;
+
+ invalidate();
+}
+
+int QWasmWindow::titleHeight() const
+{
+ return 18. * (qreal(qt_defaultDpiX()) / 96.0);//dpiScaled(18.);
+}
+
+int QWasmWindow::borderWidth() const
+{
+ return 4. * (qreal(qt_defaultDpiX()) / 96.0);// dpiScaled(4.);
+}
+
+QRegion QWasmWindow::titleGeometry() const
+{
+ int border = borderWidth();
+
+ QRegion result(window()->frameGeometry().x() + border,
+ window()->frameGeometry().y() + border,
+ window()->frameGeometry().width() - 2*border,
+ titleHeight());
+
+ result -= titleControlRegion();
+
+ return result;
+}
+
+QRegion QWasmWindow::resizeRegion() const
+{
+ int border = borderWidth();
+ QRegion result(window()->frameGeometry().adjusted(-border, -border, border, border));
+ result -= window()->frameGeometry().adjusted(border, border, -border, -border);
+
+ return result;
+}
+
+bool QWasmWindow::isPointOnTitle(QPoint point) const
+{
+ bool ok = titleGeometry().contains(point);
+ return ok;
+}
+
+bool QWasmWindow::isPointOnResizeRegion(QPoint point) const
+{
+ return resizeRegion().contains(point);
+}
+
+QWasmWindow::ResizeMode QWasmWindow::resizeModeAtPoint(QPoint point) const
+{
+ QPoint p1 = window()->frameGeometry().topLeft() - QPoint(5, 5);
+ QPoint p2 = window()->frameGeometry().bottomRight() + QPoint(5, 5);
+ int corner = 20;
+
+ QRect top(p1, QPoint(p2.x(), p1.y() + corner));
+ QRect middle(QPoint(p1.x(), p1.y() + corner), QPoint(p2.x(), p2.y() - corner));
+ QRect bottom(QPoint(p1.x(), p2.y() - corner), p2);
+
+ QRect left(p1, QPoint(p1.x() + corner, p2.y()));
+ QRect center(QPoint(p1.x() + corner, p1.y()), QPoint(p2.x() - corner, p2.y()));
+ QRect right(QPoint(p2.x() - corner, p1.y()), p2);
+
+ if (top.contains(point)) {
+ // Top
+ if (left.contains(point))
+ return ResizeTopLeft;
+ if (center.contains(point))
+ return ResizeTop;
+ if (right.contains(point))
+ return ResizeTopRight;
+ } else if (middle.contains(point)) {
+ // Middle
+ if (left.contains(point))
+ return ResizeLeft;
+ if (right.contains(point))
+ return ResizeRight;
+ } else if (bottom.contains(point)) {
+ // Bottom
+ if (left.contains(point))
+ return ResizeBottomLeft;
+ if (center.contains(point))
+ return ResizeBottom;
+ if (right.contains(point))
+ return ResizeBottomRight;
+ }
+
+ return ResizeNone;
+}
+
+QRect getSubControlRect(const QWasmWindow *window, QWasmCompositor::SubControls subControl)
+{
+ QWasmCompositor::QWasmTitleBarOptions options = QWasmCompositor::makeTitleBarOptions(window);
+
+ QRect r = QWasmCompositor::titlebarRect(options, subControl);
+ r.translate(window->window()->frameGeometry().x(), window->window()->frameGeometry().y());
+
+ return r;
+}
+
+QRect QWasmWindow::maxButtonRect() const
+{
+ return getSubControlRect(this, QWasmCompositor::SC_TitleBarMaxButton);
+}
+
+QRect QWasmWindow::minButtonRect() const
+{
+ return getSubControlRect(this, QWasmCompositor::SC_TitleBarMinButton);
+}
+
+QRect QWasmWindow::closeButtonRect() const
+{
+ return getSubControlRect(this, QWasmCompositor::SC_TitleBarCloseButton);
+}
+
+QRect QWasmWindow::normButtonRect() const
+{
+ return getSubControlRect(this, QWasmCompositor::SC_TitleBarNormalButton);
+}
+
+QRect QWasmWindow::sysMenuRect() const
+{
+ return getSubControlRect(this, QWasmCompositor::SC_TitleBarSysMenu);
+}
+
+QRegion QWasmWindow::titleControlRegion() const
+{
+ QRegion result;
+ result += closeButtonRect();
+ result += minButtonRect();
+ result += maxButtonRect();
+ result += sysMenuRect();
+
+ return result;
+}
+
+void QWasmWindow::invalidate()
+{
+ m_compositor->requestRedraw();
+}
+
+QWasmCompositor::SubControls QWasmWindow::activeSubControl() const
+{
+ return m_activeControl;
+}
+
+void QWasmWindow::setWindowState(Qt::WindowStates states)
+{
+ m_windowState = Qt::WindowNoState;
+ if (states & Qt::WindowMinimized)
+ m_windowState = Qt::WindowMinimized;
+ else if (states & Qt::WindowFullScreen)
+ m_windowState = Qt::WindowFullScreen;
+ else if (states & Qt::WindowMaximized)
+ m_windowState = Qt::WindowMaximized;
+}
+
+QRect QWasmWindow::normalGeometry() const
+{
+ return m_normalGeometry;
+}
+
+qreal QWasmWindow::devicePixelRatio() const
+{
+ return screen()->devicePixelRatio();
+}
+
+void QWasmWindow::requestUpdate()
+{
+ QPointer<QWindow> windowPointer(window());
+ bool registered = QWasmEventDispatcher::registerRequestUpdateCallback([=](){
+ if (windowPointer.isNull())
+ return;
+
+ deliverUpdateRequest();
+ });
+
+ if (!registered)
+ QPlatformWindow::requestUpdate();
+}
+
+bool QWasmWindow::hasTitleBar() const
+{
+ return !(m_windowState & Qt::WindowFullScreen) && (window()->flags().testFlag(Qt::WindowTitleHint) && m_needsCompositor);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmwindow.h b/src/plugins/platforms/wasm/qwasmwindow.h
new file mode 100644
index 0000000000..cbbce99aeb
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmwindow.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWASMWINDOW_H
+#define QWASMWINDOW_H
+
+#include "qwasmintegration.h"
+#include <qpa/qplatformwindow.h>
+#include <emscripten/html5.h>
+#include "qwasmbackingstore.h"
+#include "qwasmscreen.h"
+#include "qwasmcompositor.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWasmCompositor;
+
+class QWasmWindow : public QPlatformWindow
+{
+public:
+ enum ResizeMode {
+ ResizeNone,
+ ResizeTopLeft,
+ ResizeTop,
+ ResizeTopRight,
+ ResizeRight,
+ ResizeBottomRight,
+ ResizeBottom,
+ ResizeBottomLeft,
+ ResizeLeft
+ };
+
+ QWasmWindow(QWindow *w, QWasmCompositor *compositor, QWasmBackingStore *backingStore);
+ ~QWasmWindow();
+
+ void initialize() override;
+
+ void setGeometry(const QRect &) override;
+ void setVisible(bool visible) override;
+ QMargins frameMargins() const override;
+
+ WId winId() const override;
+
+ void propagateSizeHints() override;
+ void raise() override;
+ void lower() override;
+ QRect normalGeometry() const override;
+ qreal devicePixelRatio() const override;
+ void requestUpdate() override;
+
+ QWasmScreen *platformScreen() const;
+ void setBackingStore(QWasmBackingStore *store) { m_backingStore = store; }
+ QWasmBackingStore *backingStore() const { return m_backingStore; }
+ QWindow *window() const { return m_window; }
+
+ void injectMousePressed(const QPoint &local, const QPoint &global,
+ Qt::MouseButton button, Qt::KeyboardModifiers mods);
+ void injectMouseReleased(const QPoint &local, const QPoint &global,
+ Qt::MouseButton button, Qt::KeyboardModifiers mods);
+
+ int titleHeight() const;
+ int borderWidth() const;
+ QRegion titleGeometry() const;
+ QRegion resizeRegion() const;
+ bool isPointOnTitle(QPoint point) const;
+ bool isPointOnResizeRegion(QPoint point) const;
+ ResizeMode resizeModeAtPoint(QPoint point) const;
+ QRect maxButtonRect() const;
+ QRect minButtonRect() const;
+ QRect closeButtonRect() const;
+ QRect sysMenuRect() const;
+ QRect normButtonRect() const;
+ QRegion titleControlRegion() const;
+ QWasmCompositor::SubControls activeSubControl() const;
+
+ void setWindowState(Qt::WindowStates state) override;
+ bool setKeyboardGrabEnabled(bool) override { return false; }
+ bool setMouseGrabEnabled(bool) override { return false; }
+
+protected:
+ void invalidate();
+ bool hasTitleBar() const;
+
+protected:
+ friend class QWasmScreen;
+
+ QWindow* m_window = nullptr;
+ QWasmCompositor *m_compositor = nullptr;
+ QWasmBackingStore *m_backingStore = nullptr;
+ QRect m_normalGeometry {0, 0, 0 ,0};
+
+ Qt::WindowState m_windowState = Qt::WindowNoState;
+ QWasmCompositor::SubControls m_activeControl = QWasmCompositor::SC_None;
+ WId m_winid = 0;
+ bool m_hasTitle = false;
+ bool m_needsCompositor = false;
+ friend class QWasmCompositor;
+ friend class QWasmEventTranslator;
+};
+QT_END_NAMESPACE
+#endif // QWASMWINDOW_H
diff --git a/src/plugins/platforms/wasm/wasm.json b/src/plugins/platforms/wasm/wasm.json
new file mode 100644
index 0000000000..6e700e06b9
--- /dev/null
+++ b/src/plugins/platforms/wasm/wasm.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "wasm" ]
+}
diff --git a/src/plugins/platforms/wasm/wasm.pro b/src/plugins/platforms/wasm/wasm.pro
new file mode 100644
index 0000000000..f1205702ef
--- /dev/null
+++ b/src/plugins/platforms/wasm/wasm.pro
@@ -0,0 +1,65 @@
+TARGET = wasm
+CONFIG += static plugin
+QT += \
+ core-private gui-private \
+ eventdispatcher_support-private fontdatabase_support-private egl_support-private
+
+# Avoid X11 header collision, use generic EGL native types
+DEFINES += QT_EGL_NO_X11
+
+SOURCES = \
+ main.cpp \
+ qwasmintegration.cpp \
+ qwasmwindow.cpp \
+ qwasmscreen.cpp \
+ qwasmfontdatabase.cpp \
+ qwasmeventtranslator.cpp \
+ qwasmeventdispatcher.cpp \
+ qwasmcompositor.cpp \
+ qwasmcursor.cpp \
+ qwasmopenglcontext.cpp \
+ qwasmtheme.cpp
+
+HEADERS = \
+ qwasmintegration.h \
+ qwasmwindow.h \
+ qwasmscreen.h \
+ qwasmfontdatabase.h \
+ qwasmeventtranslator.h \
+ qwasmeventdispatcher.h \
+ qwasmcompositor.h \
+ qwasmstylepixmaps_p.h \
+ qwasmcursor.h \
+ qwasmopenglcontext.h \
+ qwasmtheme.h
+
+wasmfonts.files = \
+ ../../../3rdparty/wasm/Vera.ttf \
+ ../../../3rdparty/wasm/DejaVuSans.ttf
+wasmfonts.prefix = /fonts
+wasmfonts.base = ../../../3rdparty/wasm
+RESOURCES += wasmfonts
+
+qtConfig(opengl) {
+ SOURCES += qwasmbackingstore.cpp
+ HEADERS += qwasmbackingstore.h
+}
+CONFIG += egl
+
+OTHER_FILES += \
+ wasm.json \
+ wasm_shell.html \
+ qtloader.js
+
+shell_files.path = $$[QT_INSTALL_PLUGINS]/platforms
+shell_files.files = \
+ wasm_shell.html \
+ qtloader.js \
+ qtlogo.svg
+
+INSTALLS += shell_files
+
+PLUGIN_TYPE = platforms
+PLUGIN_CLASS_NAME = QWasmIntegrationPlugin
+!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
+load(qt_plugin)
diff --git a/src/plugins/platforms/wasm/wasm_shell.html b/src/plugins/platforms/wasm/wasm_shell.html
new file mode 100644
index 0000000000..67bfcdfbdc
--- /dev/null
+++ b/src/plugins/platforms/wasm/wasm_shell.html
@@ -0,0 +1,61 @@
+<!doctype html>
+<html lang="en-us">
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <title>APPNAME</title>
+ <style>
+ html, body { padding: 0; margin : 0; overflow:hidden; height: 100% }
+ /* the canvas *must not* have any border or padding, or mouse coords will be wrong */
+ canvas { border: 0px none; background-color: white; height:100%; width:100%; }
+ </style>
+ </head>
+ <body onload="init()">
+ <figure style="overflow:visible;" id="spinner">
+ <center style="margin-top:1.5em; line-height:150%">
+ <img src="qtlogo.svg"; width=320; height=200; style="display:block"> </img>
+ <strong>Qt for WebAssembly: APPNAME</strong>
+ <div id="status"></div>
+ <noscript>JavaScript is disabled. Please enable JavaScript to use this application.</noscript>
+ </center>
+ </figure>
+ <canvas id="canvas" oncontextmenu="event.preventDefault()"></canvas>
+
+ <script type='text/javascript'>
+ function init() {
+ var spinner = document.getElementById('spinner');
+ var canvas = document.getElementById('canvas');
+ var status = document.getElementById('status')
+
+ var qtLoader = QtLoader({
+ showLoader: function(loaderStatus) {
+ spinner.style.display = 'block';
+ canvas.style.display = 'none';
+ status.innerHTML = loaderStatus + "...";
+ },
+ showError: function(errorText) {
+ status.innerHTML = errorText;
+ spinner.style.display = 'block';
+ canvas.style.display = 'none';
+ },
+ showExit: function() {
+ status.innerHTML = "Application exit";
+ if (qtLoader.exitCode !== undefined)
+ status.innerHTML += " with code " + qtLoader.exitCode;
+ if (qtLoader.exitText !== undefined)
+ status.innerHTML += " (" + qtLoader.exitText + ")";
+ spinner.style.display = 'block';
+ canvas.style.display = 'none';
+ },
+ showCanvas: function() {
+ spinner.style.display = 'none';
+ canvas.style.display = 'block';
+ return canvas;
+ },
+ });
+ qtLoader.loadEmscriptenModule("APPNAME");
+ }
+ </script>
+ <script type="text/javascript" src="qtloader.js"></script>
+ </body>
+</html>
diff --git a/src/plugins/platforms/windows/main.cpp b/src/plugins/platforms/windows/main.cpp
index 980de88e72..8bde87c975 100644
--- a/src/plugins/platforms/windows/main.cpp
+++ b/src/plugins/platforms/windows/main.cpp
@@ -39,7 +39,7 @@
#include <qpa/qplatformintegrationplugin.h>
-#include <QtCore/QStringList>
+#include <QtCore/qstringlist.h>
#include "qwindowsgdiintegration.h"
diff --git a/src/plugins/platforms/windows/openglblacklists/default.json b/src/plugins/platforms/windows/openglblacklists/default.json
index d1e9f85247..3cfa7e3856 100644
--- a/src/plugins/platforms/windows/openglblacklists/default.json
+++ b/src/plugins/platforms/windows/openglblacklists/default.json
@@ -141,6 +141,17 @@
"features": [
"disable_desktopgl", "disable_d3d11", "disable_d3d9"
]
+ },
+ {
+ "id": 12,
+ "description": "Intel HD Graphics crash in conjunction with shader caches (QTBUG-64697) - disable for all Intel GPUs",
+ "vendor_id": "0x8086",
+ "os": {
+ "type": "win"
+ },
+ "features": [
+ "disable_program_cache"
+ ]
}
]
}
diff --git a/src/plugins/platforms/windows/qtwindowsglobal.h b/src/plugins/platforms/windows/qtwindowsglobal.h
index 6c44541314..985f13bdc5 100644
--- a/src/plugins/platforms/windows/qtwindowsglobal.h
+++ b/src/plugins/platforms/windows/qtwindowsglobal.h
@@ -60,6 +60,22 @@
# define WM_DPICHANGED 0x02E0
#endif
+// WM_POINTER support from Windows 8 onwards (WINVER >= 0x0602)
+#ifndef WM_POINTERUPDATE
+# define WM_NCPOINTERUPDATE 0x0241
+# define WM_NCPOINTERDOWN 0x0242
+# define WM_NCPOINTERUP 0x0243
+# define WM_POINTERUPDATE 0x0245
+# define WM_POINTERDOWN 0x0246
+# define WM_POINTERUP 0x0247
+# define WM_POINTERENTER 0x0249
+# define WM_POINTERLEAVE 0x024A
+# define WM_POINTERACTIVATE 0x024B
+# define WM_POINTERCAPTURECHANGED 0x024C
+# define WM_POINTERWHEEL 0x024E
+# define WM_POINTERHWHEEL 0x024F
+#endif // WM_POINTERUPDATE
+
QT_BEGIN_NAMESPACE
namespace QtWindows
@@ -78,6 +94,7 @@ enum
ApplicationEventFlag = 0x1000000,
ThemingEventFlag = 0x2000000,
GenericEventFlag = 0x4000000, // Misc
+ PointerEventFlag = 0x8000000,
};
enum WindowsEventType // Simplify event types
@@ -103,13 +120,16 @@ enum WindowsEventType // Simplify event types
DpiChangedEvent = WindowEventFlag + 21,
EnterSizeMoveEvent = WindowEventFlag + 22,
ExitSizeMoveEvent = WindowEventFlag + 23,
+ PointerActivateWindowEvent = WindowEventFlag + 24,
MouseEvent = MouseEventFlag + 1,
MouseWheelEvent = MouseEventFlag + 2,
CursorEvent = MouseEventFlag + 3,
TouchEvent = TouchEventFlag + 1,
+ PointerEvent = PointerEventFlag + 1,
NonClientMouseEvent = NonClientEventFlag + MouseEventFlag + 1,
NonClientHitTest = NonClientEventFlag + 2,
NonClientCreate = NonClientEventFlag + 3,
+ NonClientPointerEvent = NonClientEventFlag + PointerEventFlag + 4,
KeyEvent = KeyEventFlag + 1,
KeyDownEvent = KeyEventFlag + KeyDownEventFlag + 1,
KeyboardLayoutChangeEvent = KeyEventFlag + 2,
@@ -167,6 +187,8 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI
QtWindows::ActivateApplicationEvent : QtWindows::DeactivateApplicationEvent;
case WM_MOUSEACTIVATE:
return QtWindows::MouseActivateWindowEvent;
+ case WM_POINTERACTIVATE:
+ return QtWindows::PointerActivateWindowEvent;
case WM_ACTIVATE:
return LOWORD(wParamIn) == WA_INACTIVE ?
QtWindows::DeactivateWindowEvent : QtWindows::ActivateWindowEvent;
@@ -297,6 +319,10 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI
if ((message >= WM_MOUSEFIRST && message <= WM_MOUSELAST)
|| (message >= WM_XBUTTONDOWN && message <= WM_XBUTTONDBLCLK))
return QtWindows::MouseEvent;
+ if (message >= WM_NCPOINTERUPDATE && message <= WM_NCPOINTERUP)
+ return QtWindows::NonClientPointerEvent;
+ if (message >= WM_POINTERUPDATE && message <= WM_POINTERHWHEEL)
+ return QtWindows::PointerEvent;
return QtWindows::UnknownEvent;
}
diff --git a/src/plugins/platforms/windows/qwin10helpers.cpp b/src/plugins/platforms/windows/qwin10helpers.cpp
index 5976fd23c0..cc17d8798f 100644
--- a/src/plugins/platforms/windows/qwin10helpers.cpp
+++ b/src/plugins/platforms/windows/qwin10helpers.cpp
@@ -39,8 +39,8 @@
#include "qwin10helpers.h"
-#include <QtCore/QDebug>
-#include <QtCore/QOperatingSystemVersion>
+#include <QtCore/qdebug.h>
+#include <QtCore/qoperatingsystemversion.h>
#include <QtCore/private/qsystemlibrary_p.h>
#if defined(Q_CC_MINGW) || defined(Q_CC_CLANG)
diff --git a/src/plugins/platforms/windows/qwin10helpers.h b/src/plugins/platforms/windows/qwin10helpers.h
index e1485003dd..4f364dfc59 100644
--- a/src/plugins/platforms/windows/qwin10helpers.h
+++ b/src/plugins/platforms/windows/qwin10helpers.h
@@ -40,7 +40,7 @@
#ifndef QWIN10HELPERS_H
#define QWIN10HELPERS_H
-#include <QtCore/QtGlobal>
+#include <QtCore/qglobal.h>
#include <QtCore/qt_windows.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp
index 80872c3ea3..03b44458ac 100644
--- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp
+++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp
@@ -41,13 +41,13 @@
#include "qwindowswindow.h"
#include "qwindowscontext.h"
-#include <QtGui/QWindow>
-#include <QtGui/QPainter>
+#include <QtGui/qwindow.h>
+#include <QtGui/qpainter.h>
#include <QtFontDatabaseSupport/private/qwindowsnativeimage_p.h>
#include <private/qhighdpiscaling_p.h>
#include <private/qimage_p.h>
-#include <QtCore/QDebug>
+#include <QtCore/qdebug.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.h b/src/plugins/platforms/windows/qwindowsbackingstore.h
index 9e62266697..088ab3b257 100644
--- a/src/plugins/platforms/windows/qwindowsbackingstore.h
+++ b/src/plugins/platforms/windows/qwindowsbackingstore.h
@@ -43,7 +43,7 @@
#include <QtCore/qt_windows.h>
#include <qpa/qplatformbackingstore.h>
-#include <QtCore/QScopedPointer>
+#include <QtCore/qscopedpointer.h>
QT_BEGIN_NAMESPACE
@@ -55,7 +55,7 @@ class QWindowsBackingStore : public QPlatformBackingStore
Q_DISABLE_COPY(QWindowsBackingStore)
public:
QWindowsBackingStore(QWindow *window);
- ~QWindowsBackingStore();
+ ~QWindowsBackingStore() override;
QPaintDevice *paintDevice() override;
void flush(QWindow *window, const QRegion &region, const QPoint &offset) override;
diff --git a/src/plugins/platforms/windows/qwindowsclipboard.cpp b/src/plugins/platforms/windows/qwindowsclipboard.cpp
index 01191a7dc1..8b386da9f7 100644
--- a/src/plugins/platforms/windows/qwindowsclipboard.cpp
+++ b/src/plugins/platforms/windows/qwindowsclipboard.cpp
@@ -42,16 +42,17 @@
#include "qwindowsole.h"
#include "qwindowsmime.h"
-#include <QtGui/QGuiApplication>
-#include <QtGui/QClipboard>
-#include <QtGui/QColor>
-#include <QtGui/QImage>
-
-#include <QtCore/QDebug>
-#include <QtCore/QMimeData>
-#include <QtCore/QStringList>
-#include <QtCore/QVariant>
-#include <QtCore/QUrl>
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qclipboard.h>
+#include <QtGui/qcolor.h>
+#include <QtGui/qimage.h>
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qmimedata.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qthread.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qurl.h>
#include <QtEventDispatcherSupport/private/qwindowsguieventdispatcher_p.h>
@@ -318,7 +319,15 @@ void QWindowsClipboard::setMimeData(QMimeData *mimeData, QClipboard::Mode mode)
m_data = new QWindowsOleDataObject(mimeData);
}
- const HRESULT src = OleSetClipboard(m_data);
+ HRESULT src = S_FALSE;
+ int attempts = 0;
+ for (; attempts < 3; ++attempts) {
+ src = OleSetClipboard(m_data);
+ if (src != CLIPBRD_E_CANT_OPEN || QWindowsContext::isSessionLocked())
+ break;
+ QThread::msleep(100);
+ }
+
if (src != S_OK) {
QString mimeDataFormats = mimeData ?
mimeData->formats().join(QLatin1String(", ")) : QString(QStringLiteral("NULL"));
diff --git a/src/plugins/platforms/windows/qwindowsclipboard.h b/src/plugins/platforms/windows/qwindowsclipboard.h
index 4f3e7437f6..469d638b89 100644
--- a/src/plugins/platforms/windows/qwindowsclipboard.h
+++ b/src/plugins/platforms/windows/qwindowsclipboard.h
@@ -58,9 +58,10 @@ protected:
class QWindowsClipboard : public QPlatformClipboard
{
+ Q_DISABLE_COPY(QWindowsClipboard)
public:
QWindowsClipboard();
- ~QWindowsClipboard();
+ ~QWindowsClipboard() override;
void registerViewer(); // Call in initialization, when context is up.
void cleanup();
diff --git a/src/plugins/platforms/windows/qwindowscombase.h b/src/plugins/platforms/windows/qwindowscombase.h
index 5e51b6b7b7..6b25d665dc 100644
--- a/src/plugins/platforms/windows/qwindowscombase.h
+++ b/src/plugins/platforms/windows/qwindowscombase.h
@@ -40,7 +40,7 @@
#ifndef QWINDOWSCOMBASE_H
#define QWINDOWSCOMBASE_H
-#include <QtCore/QtGlobal>
+#include <QtCore/qglobal.h>
#include <unknwn.h>
@@ -83,7 +83,7 @@ template <class ComInterface> class QWindowsComBase : public ComInterface
Q_DISABLE_COPY(QWindowsComBase)
public:
explicit QWindowsComBase(ULONG initialRefCount = 1) : m_ref(initialRefCount) {}
- virtual ~QWindowsComBase() {}
+ virtual ~QWindowsComBase() = default;
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface)
{
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index b0c9349da5..1f80ac5872 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -43,6 +43,7 @@
#include "qwindowswindow.h"
#include "qwindowskeymapper.h"
#include "qwindowsmousehandler.h"
+#include "qwindowspointerhandler.h"
#include "qtwindowsglobal.h"
#include "qwindowsmenu.h"
#include "qwindowsmime.h"
@@ -52,7 +53,7 @@
#endif
#include "qwindowstheme.h"
#include <private/qguiapplication_p.h>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
# include "uiautomation/qwindowsuiaaccessibility.h"
#endif
#if QT_CONFIG(sessionmanager)
@@ -62,20 +63,20 @@
#include "qwindowsscreen.h"
#include "qwindowstheme.h"
-#include <QtGui/qtguiglobal.h>
-#include <QtGui/QWindow>
+#include <QtGui/qwindow.h>
#include <qpa/qwindowsysteminterface.h>
+#include <qpa/qwindowsysteminterface_p.h>
#include <qpa/qplatformnativeinterface.h>
-#include <QtGui/QGuiApplication>
-#include <QtGui/QOpenGLContext>
-
-#include <QtCore/QSet>
-#include <QtCore/QHash>
-#include <QtCore/QStringList>
-#include <QtCore/QDebug>
-#include <QtCore/QOperatingSystemVersion>
-#include <QtCore/QSysInfo>
-#include <QtCore/QScopedArrayPointer>
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qopenglcontext.h>
+
+#include <QtCore/qset.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qoperatingsystemversion.h>
+#include <QtCore/qsysinfo.h>
+#include <QtCore/qscopedpointer.h>
#include <QtCore/private/qsystemlibrary_p.h>
#include <QtEventDispatcherSupport/private/qwindowsguieventdispatcher_p.h>
@@ -85,11 +86,11 @@
#include <windowsx.h>
#include <comdef.h>
#include <dbt.h>
+#include <wtsapi32.h>
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcQpaWindows, "qt.qpa.windows")
-Q_LOGGING_CATEGORY(lcQpaBackingStore, "qt.qpa.backingstore")
Q_LOGGING_CATEGORY(lcQpaEvents, "qt.qpa.events")
Q_LOGGING_CATEGORY(lcQpaGl, "qt.qpa.gl")
Q_LOGGING_CATEGORY(lcQpaMime, "qt.qpa.mime")
@@ -147,7 +148,7 @@ static inline bool sessionManagerInteractionBlocked() { return false; }
static inline int windowDpiAwareness(HWND hwnd)
{
- return QWindowsContext::user32dll.getWindowDpiAwarenessContext && QWindowsContext::user32dll.getWindowDpiAwarenessContext
+ return QWindowsContext::user32dll.getWindowDpiAwarenessContext && QWindowsContext::user32dll.getAwarenessFromDpiAwarenessContext
? QWindowsContext::user32dll.getAwarenessFromDpiAwarenessContext(QWindowsContext::user32dll.getWindowDpiAwarenessContext(hwnd))
: -1;
}
@@ -194,14 +195,35 @@ void QWindowsUser32DLL::init()
getDisplayAutoRotationPreferences = (GetDisplayAutoRotationPreferences)library.resolve("GetDisplayAutoRotationPreferences");
setDisplayAutoRotationPreferences = (SetDisplayAutoRotationPreferences)library.resolve("SetDisplayAutoRotationPreferences");
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8) {
+ enableMouseInPointer = (EnableMouseInPointer)library.resolve("EnableMouseInPointer");
+ getPointerType = (GetPointerType)library.resolve("GetPointerType");
+ getPointerInfo = (GetPointerInfo)library.resolve("GetPointerInfo");
+ getPointerDeviceRects = (GetPointerDeviceRects)library.resolve("GetPointerDeviceRects");
+ getPointerTouchInfo = (GetPointerTouchInfo)library.resolve("GetPointerTouchInfo");
+ getPointerFrameTouchInfo = (GetPointerFrameTouchInfo)library.resolve("GetPointerFrameTouchInfo");
+ getPointerFrameTouchInfoHistory = (GetPointerFrameTouchInfoHistory)library.resolve("GetPointerFrameTouchInfoHistory");
+ getPointerPenInfo = (GetPointerPenInfo)library.resolve("GetPointerPenInfo");
+ getPointerPenInfoHistory = (GetPointerPenInfoHistory)library.resolve("GetPointerPenInfoHistory");
+ skipPointerFrameMessages = (SkipPointerFrameMessages)library.resolve("SkipPointerFrameMessages");
+ }
+
if (QOperatingSystemVersion::current()
>= QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 14393)) {
enableNonClientDpiScaling = (EnableNonClientDpiScaling)library.resolve("EnableNonClientDpiScaling");
getWindowDpiAwarenessContext = (GetWindowDpiAwarenessContext)library.resolve("GetWindowDpiAwarenessContext");
getAwarenessFromDpiAwarenessContext = (GetAwarenessFromDpiAwarenessContext)library.resolve("GetAwarenessFromDpiAwarenessContext");
+ systemParametersInfoForDpi = (SystemParametersInfoForDpi)library.resolve("SystemParametersInfoForDpi");
}
}
+bool QWindowsUser32DLL::supportsPointerApi()
+{
+ return enableMouseInPointer && getPointerType && getPointerInfo && getPointerDeviceRects
+ && getPointerTouchInfo && getPointerFrameTouchInfo && getPointerFrameTouchInfoHistory
+ && getPointerPenInfo && getPointerPenInfoHistory && skipPointerFrameMessages;
+}
+
void QWindowsShcoreDLL::init()
{
if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8_1)
@@ -239,6 +261,7 @@ struct QWindowsContextPrivate {
int m_defaultDPI = 96;
QWindowsKeyMapper m_keyMapper;
QWindowsMouseHandler m_mouseHandler;
+ QWindowsPointerHandler m_pointerHandler;
QWindowsMimeConverter m_mimeConverter;
QWindowsScreenManager m_screenManager;
QSharedPointer<QWindowCreationContext> m_creationContext;
@@ -256,7 +279,7 @@ QWindowsContextPrivate::QWindowsContextPrivate()
QWindowsContext::user32dll.init();
QWindowsContext::shcoredll.init();
- if (m_mouseHandler.touchDevice())
+ if (m_pointerHandler.touchDevice() || m_mouseHandler.touchDevice())
m_systemInfo |= QWindowsContext::SI_SupportsTouch;
m_displayContext = GetDC(0);
m_defaultDPI = GetDeviceCaps(m_displayContext, LOGPIXELSY);
@@ -281,10 +304,6 @@ QWindowsContext::QWindowsContext() :
const QByteArray bv = qgetenv("QT_QPA_VERBOSE");
if (!bv.isEmpty())
QLoggingCategory::setFilterRules(QString::fromLocal8Bit(bv));
-#if QT_CONFIG(tabletevent)
- d->m_tabletSupport.reset(QWindowsTabletSupport::create());
- qCDebug(lcQpaTablet) << "Tablet support: " << (d->m_tabletSupport.isNull() ? QStringLiteral("None") : d->m_tabletSupport->description());
-#endif
}
QWindowsContext::~QWindowsContext()
@@ -310,12 +329,17 @@ bool QWindowsContext::initTouch(unsigned integrationOptions)
if (d->m_systemInfo & QWindowsContext::SI_SupportsTouch)
return true;
- QTouchDevice *touchDevice = d->m_mouseHandler.ensureTouchDevice();
+ QTouchDevice *touchDevice = (d->m_systemInfo & QWindowsContext::SI_SupportsPointer) ?
+ d->m_pointerHandler.ensureTouchDevice() : d->m_mouseHandler.ensureTouchDevice();
if (!touchDevice)
return false;
- if (!(integrationOptions & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch))
- touchDevice->setCapabilities(touchDevice->capabilities() | QTouchDevice::MouseEmulation);
+ if (d->m_systemInfo & QWindowsContext::SI_SupportsPointer) {
+ QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false);
+ } else {
+ if (!(integrationOptions & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch))
+ touchDevice->setCapabilities(touchDevice->capabilities() | QTouchDevice::MouseEmulation);
+ }
QWindowSystemInterface::registerTouchDevice(touchDevice);
@@ -330,6 +354,33 @@ bool QWindowsContext::initTouch(unsigned integrationOptions)
return true;
}
+bool QWindowsContext::initTablet(unsigned integrationOptions)
+{
+ Q_UNUSED(integrationOptions);
+#if QT_CONFIG(tabletevent)
+ d->m_tabletSupport.reset(QWindowsTabletSupport::create());
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool QWindowsContext::initPointer(unsigned integrationOptions)
+{
+ if (integrationOptions & QWindowsIntegration::DontUseWMPointer)
+ return false;
+
+ if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8)
+ return false;
+
+ if (!QWindowsContext::user32dll.supportsPointerApi())
+ return false;
+
+ QWindowsContext::user32dll.enableMouseInPointer(TRUE);
+ d->m_systemInfo |= QWindowsContext::SI_SupportsPointer;
+ return true;
+}
+
void QWindowsContext::setTabletAbsoluteRange(int a)
{
#if QT_CONFIG(tabletevent)
@@ -340,6 +391,11 @@ void QWindowsContext::setTabletAbsoluteRange(int a)
#endif
}
+void QWindowsContext::setDetectAltGrModifier(bool a)
+{
+ d->m_keyMapper.setDetectAltGrModifier(a);
+}
+
int QWindowsContext::processDpiAwareness()
{
int result;
@@ -548,7 +604,7 @@ void QWindowsContext::unregisterWindowClasses()
{
const HINSTANCE appInstance = static_cast<HINSTANCE>(GetModuleHandle(0));
- foreach (const QString &name, d->m_registeredWindowClassNames) {
+ for (const QString &name : qAsConst(d->m_registeredWindowClassNames)) {
if (!UnregisterClass(reinterpret_cast<LPCWSTR>(name.utf16()), appInstance) && QWindowsContext::verbose)
qErrnoWarning("UnregisterClass failed for '%s'", qPrintable(name));
}
@@ -632,12 +688,16 @@ QWindow *QWindowsContext::findWindow(HWND hwnd) const
QWindow *QWindowsContext::windowUnderMouse() const
{
- return d->m_mouseHandler.windowUnderMouse();
+ return (d->m_systemInfo & QWindowsContext::SI_SupportsPointer) ?
+ d->m_pointerHandler.windowUnderMouse() : d->m_mouseHandler.windowUnderMouse();
}
void QWindowsContext::clearWindowUnderMouse()
{
- d->m_mouseHandler.clearWindowUnderMouse();
+ if (d->m_systemInfo & QWindowsContext::SI_SupportsPointer)
+ d->m_pointerHandler.clearWindowUnderMouse();
+ else
+ d->m_mouseHandler.clearWindowUnderMouse();
}
/*!
@@ -696,6 +756,37 @@ QWindowsWindow *QWindowsContext::findPlatformWindowAt(HWND parent,
return result;
}
+bool QWindowsContext::isSessionLocked()
+{
+ bool result = false;
+ const DWORD sessionId = WTSGetActiveConsoleSessionId();
+ if (sessionId != 0xFFFFFFFF) {
+ LPTSTR buffer = nullptr;
+ DWORD size = 0;
+#if !defined(Q_CC_MINGW)
+ if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionId,
+ WTSSessionInfoEx, &buffer, &size) == TRUE
+ && size > 0) {
+ const WTSINFOEXW *info = reinterpret_cast<WTSINFOEXW *>(buffer);
+ result = info->Level == 1 && info->Data.WTSInfoExLevel1.SessionFlags == WTS_SESSIONSTATE_LOCK;
+ WTSFreeMemory(buffer);
+ }
+#else // MinGW as of 7.3 does not have WTSINFOEXW in wtsapi32.h
+ // Retrieve the flags which are at offset 16 due to padding for 32/64bit alike.
+ if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionId,
+ WTS_INFO_CLASS(25), &buffer, &size) == TRUE
+ && size >= 20) {
+ const DWORD *p = reinterpret_cast<DWORD *>(buffer);
+ const DWORD level = *p;
+ const DWORD sessionFlags = *(p + 4);
+ result = level == 1 && sessionFlags == 1;
+ WTSFreeMemory(buffer);
+ }
+#endif // Q_CC_MINGW
+ }
+ return result;
+}
+
QWindowsMimeConverter &QWindowsContext::mimeConverter() const
{
return d->m_mimeConverter;
@@ -826,6 +917,45 @@ QByteArray QWindowsContext::comErrorString(HRESULT hr)
return result;
}
+bool QWindowsContext::systemParametersInfo(unsigned action, unsigned param, void *out,
+ unsigned dpi)
+{
+ const BOOL result = QWindowsContext::user32dll.systemParametersInfoForDpi != nullptr && dpi != 0
+ ? QWindowsContext::user32dll.systemParametersInfoForDpi(action, param, out, 0, dpi)
+ : SystemParametersInfo(action, param, out, 0);
+ return result == TRUE;
+}
+
+bool QWindowsContext::systemParametersInfoForScreen(unsigned action, unsigned param, void *out,
+ const QPlatformScreen *screen)
+{
+ return systemParametersInfo(action, param, out, screen ? screen->logicalDpi().first : 0);
+}
+
+bool QWindowsContext::systemParametersInfoForWindow(unsigned action, unsigned param, void *out,
+ const QPlatformWindow *win)
+{
+ return systemParametersInfoForScreen(action, param, out, win ? win->screen() : nullptr);
+}
+
+bool QWindowsContext::nonClientMetrics(NONCLIENTMETRICS *ncm, unsigned dpi)
+{
+ memset(ncm, 0, sizeof(NONCLIENTMETRICS));
+ ncm->cbSize = sizeof(NONCLIENTMETRICS);
+ return systemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm->cbSize, ncm, dpi);
+}
+
+bool QWindowsContext::nonClientMetricsForScreen(NONCLIENTMETRICS *ncm,
+ const QPlatformScreen *screen)
+{
+ return nonClientMetrics(ncm, screen ? screen->logicalDpi().first : 0);
+}
+
+bool QWindowsContext::nonClientMetricsForWindow(NONCLIENTMETRICS *ncm, const QPlatformWindow *win)
+{
+ return nonClientMetricsForScreen(ncm, win ? win->screen() : nullptr);
+}
+
static inline QWindowsInputContext *windowsInputContext()
{
return qobject_cast<QWindowsInputContext *>(QWindowsIntegration::instance()->inputContext());
@@ -870,6 +1000,7 @@ static inline bool isInputMessage(UINT m)
case WM_IME_STARTCOMPOSITION:
case WM_IME_ENDCOMPOSITION:
case WM_IME_COMPOSITION:
+ case WM_INPUT:
case WM_TOUCH:
case WM_MOUSEHOVER:
case WM_MOUSELEAVE:
@@ -957,7 +1088,9 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
switch (et) {
case QtWindows::GestureEvent:
- return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateGestureEvent(platformWindow->window(), hwnd, et, msg, result);
+ if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer))
+ return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateGestureEvent(platformWindow->window(), hwnd, et, msg, result);
+ break;
case QtWindows::InputMethodOpenCandidateWindowEvent:
case QtWindows::InputMethodCloseCandidateWindowEvent:
// TODO: Release/regrab mouse if a popup has mouse grab.
@@ -974,7 +1107,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
case QtWindows::UnknownEvent:
return false;
case QtWindows::AccessibleObjectFromWindowRequest:
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
return QWindowsUiaAccessibility::handleWmGetObject(hwnd, wParam, lParam, result);
#else
return false;
@@ -1083,18 +1216,25 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
case QtWindows::ExposeEvent:
return platformWindow->handleWmPaint(hwnd, message, wParam, lParam);
case QtWindows::NonClientMouseEvent:
- if (platformWindow->frameStrutEventsEnabled())
+ if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled())
return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
break;
+ case QtWindows::NonClientPointerEvent:
+ if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled())
+ return sessionManagerInteractionBlocked() || d->m_pointerHandler.translatePointerEvent(platformWindow->window(), hwnd, et, msg, result);
+ break;
case QtWindows::EnterSizeMoveEvent:
platformWindow->setFlag(QWindowsWindow::ResizeMoveActive);
return true;
case QtWindows::ExitSizeMoveEvent:
platformWindow->clearFlag(QWindowsWindow::ResizeMoveActive);
platformWindow->checkForScreenChanged();
+ handleExitSizeMove(platformWindow->window());
return true;
case QtWindows::ScrollEvent:
- return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateScrollEvent(platformWindow->window(), hwnd, msg, result);
+ if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer))
+ return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateScrollEvent(platformWindow->window(), hwnd, msg, result);
+ break;
case QtWindows::MouseWheelEvent:
case QtWindows::MouseEvent:
case QtWindows::LeaveEvent:
@@ -1104,10 +1244,20 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
window = window->parent();
if (!window)
return false;
- return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(window, hwnd, et, msg, result);
+ if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer))
+ return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(window, hwnd, et, msg, result);
+ else
+ return sessionManagerInteractionBlocked() || d->m_pointerHandler.translateMouseEvent(window, hwnd, et, msg, result);
}
+ break;
case QtWindows::TouchEvent:
- return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateTouchEvent(platformWindow->window(), hwnd, et, msg, result);
+ if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer))
+ return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateTouchEvent(platformWindow->window(), hwnd, et, msg, result);
+ break;
+ case QtWindows::PointerEvent:
+ if (d->m_systemInfo & QWindowsContext::SI_SupportsPointer)
+ return sessionManagerInteractionBlocked() || d->m_pointerHandler.translatePointerEvent(platformWindow->window(), hwnd, et, msg, result);
+ break;
case QtWindows::FocusInEvent: // see QWindowsWindow::requestActivateWindow().
case QtWindows::FocusOutEvent:
handleFocusEvent(et, platformWindow);
@@ -1150,6 +1300,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
}
break;
case QtWindows::MouseActivateWindowEvent:
+ case QtWindows::PointerActivateWindowEvent:
if (platformWindow->window()->flags() & Qt::WindowDoesNotAcceptFocus) {
*result = LRESULT(MA_NOACTIVATE);
return true;
@@ -1294,6 +1445,37 @@ bool QWindowsContext::handleContextMenuEvent(QWindow *window, const MSG &msg)
}
#endif
+void QWindowsContext::handleExitSizeMove(QWindow *window)
+{
+ // Windows can be moved/resized by:
+ // 1) User moving a window by dragging the title bar: Causes a sequence
+ // of WM_NCLBUTTONDOWN, WM_NCMOUSEMOVE but no WM_NCLBUTTONUP,
+ // leaving the left mouse button 'pressed'
+ // 2) User choosing Resize/Move from System menu and using mouse/cursor keys:
+ // No mouse events are received
+ // 3) Programmatically via QSizeGrip calling QPlatformWindow::startSystemResize/Move():
+ // Mouse is left in pressed state after press on size grip (inside window),
+ // no further mouse events are received
+ // For cases 1,3, intercept WM_EXITSIZEMOVE to sync the buttons.
+ const Qt::MouseButtons currentButtons = QWindowsMouseHandler::queryMouseButtons();
+ const Qt::MouseButtons appButtons = QGuiApplication::mouseButtons();
+ if (currentButtons == appButtons)
+ return;
+ const Qt::KeyboardModifiers keyboardModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
+ const QPoint globalPos = QWindowsCursor::mousePosition();
+ const QPlatformWindow *platWin = window->handle();
+ const QPoint localPos = platWin->mapFromGlobal(globalPos);
+ const QEvent::Type type = platWin->geometry().contains(globalPos)
+ ? QEvent::MouseButtonRelease : QEvent::NonClientAreaMouseButtonRelease;
+ for (Qt::MouseButton button : {Qt::LeftButton, Qt::RightButton, Qt::MiddleButton}) {
+ if (appButtons.testFlag(button) && !currentButtons.testFlag(button)) {
+ QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos,
+ currentButtons, button, type,
+ keyboardModifiers);
+ }
+ }
+}
+
bool QWindowsContext::asyncExpose() const
{
return d->m_asyncExpose;
@@ -1306,7 +1488,8 @@ void QWindowsContext::setAsyncExpose(bool value)
QTouchDevice *QWindowsContext::touchDevice() const
{
- return d->m_mouseHandler.touchDevice();
+ return (d->m_systemInfo & QWindowsContext::SI_SupportsPointer) ?
+ d->m_pointerHandler.touchDevice() : d->m_mouseHandler.touchDevice();
}
static DWORD readDwordRegistrySetting(const wchar_t *regKey, const wchar_t *subKey, DWORD defaultValue)
@@ -1399,7 +1582,7 @@ extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPAR
marginsFromRects(ncCalcSizeFrame, rectFromNcCalcSize(message, wParam, lParam, 0));
if (margins.left() >= 0) {
if (platformWindow) {
- platformWindow->setFrameMargins(margins);
+ platformWindow->setFullFrameMargins(margins);
} else {
const QSharedPointer<QWindowCreationContext> ctx = QWindowsContext::instance()->windowCreationContext();
if (!ctx.isNull())
diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h
index 0a7f20ca83..fd6c72668c 100644
--- a/src/plugins/platforms/windows/qwindowscontext.h
+++ b/src/plugins/platforms/windows/qwindowscontext.h
@@ -43,9 +43,9 @@
#include "qtwindowsglobal.h"
#include <QtCore/qt_windows.h>
-#include <QtCore/QScopedPointer>
-#include <QtCore/QSharedPointer>
-#include <QtCore/QLoggingCategory>
+#include <QtCore/qscopedpointer.h>
+#include <QtCore/qsharedpointer.h>
+#include <QtCore/qloggingcategory.h>
#define STRICT_TYPED_ITEMIDS
#include <shlobj.h>
@@ -57,7 +57,6 @@ struct _SHSTOCKICONINFO;
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcQpaWindows)
-Q_DECLARE_LOGGING_CATEGORY(lcQpaBackingStore)
Q_DECLARE_LOGGING_CATEGORY(lcQpaEvents)
Q_DECLARE_LOGGING_CATEGORY(lcQpaGl)
Q_DECLARE_LOGGING_CATEGORY(lcQpaMime)
@@ -71,6 +70,7 @@ Q_DECLARE_LOGGING_CATEGORY(lcQpaTrayIcon)
class QWindow;
class QPlatformScreen;
+class QPlatformWindow;
class QWindowsMenuBar;
class QWindowsScreenManager;
class QWindowsTabletSupport;
@@ -85,7 +85,18 @@ class QTouchDevice;
struct QWindowsUser32DLL
{
inline void init();
-
+ inline bool supportsPointerApi();
+
+ typedef BOOL (WINAPI *EnableMouseInPointer)(BOOL);
+ typedef BOOL (WINAPI *GetPointerType)(UINT32, PVOID);
+ typedef BOOL (WINAPI *GetPointerInfo)(UINT32, PVOID);
+ typedef BOOL (WINAPI *GetPointerDeviceRects)(HANDLE, RECT *, RECT *);
+ typedef BOOL (WINAPI *GetPointerTouchInfo)(UINT32, PVOID);
+ typedef BOOL (WINAPI *GetPointerFrameTouchInfo)(UINT32, UINT32 *, PVOID);
+ typedef BOOL (WINAPI *GetPointerFrameTouchInfoHistory)(UINT32, UINT32 *, UINT32 *, PVOID);
+ typedef BOOL (WINAPI *GetPointerPenInfo)(UINT32, PVOID);
+ typedef BOOL (WINAPI *GetPointerPenInfoHistory)(UINT32, UINT32 *, PVOID);
+ typedef BOOL (WINAPI *SkipPointerFrameMessages)(UINT32);
typedef BOOL (WINAPI *SetProcessDPIAware)();
typedef BOOL (WINAPI *AddClipboardFormatListener)(HWND);
typedef BOOL (WINAPI *RemoveClipboardFormatListener)(HWND);
@@ -94,6 +105,19 @@ struct QWindowsUser32DLL
typedef BOOL (WINAPI *EnableNonClientDpiScaling)(HWND);
typedef int (WINAPI *GetWindowDpiAwarenessContext)(HWND);
typedef int (WINAPI *GetAwarenessFromDpiAwarenessContext)(int);
+ typedef BOOL (WINAPI *SystemParametersInfoForDpi)(UINT, UINT, PVOID, UINT, UINT);
+
+ // Windows pointer functions (Windows 8 or later).
+ EnableMouseInPointer enableMouseInPointer = nullptr;
+ GetPointerType getPointerType = nullptr;
+ GetPointerInfo getPointerInfo = nullptr;
+ GetPointerDeviceRects getPointerDeviceRects = nullptr;
+ GetPointerTouchInfo getPointerTouchInfo = nullptr;
+ GetPointerFrameTouchInfo getPointerFrameTouchInfo = nullptr;
+ GetPointerFrameTouchInfoHistory getPointerFrameTouchInfoHistory = nullptr;
+ GetPointerPenInfo getPointerPenInfo = nullptr;
+ GetPointerPenInfoHistory getPointerPenInfoHistory = nullptr;
+ SkipPointerFrameMessages skipPointerFrameMessages = nullptr;
// Windows Vista onwards
SetProcessDPIAware setProcessDPIAware = nullptr;
@@ -110,6 +134,7 @@ struct QWindowsUser32DLL
EnableNonClientDpiScaling enableNonClientDpiScaling = nullptr;
GetWindowDpiAwarenessContext getWindowDpiAwarenessContext = nullptr;
GetAwarenessFromDpiAwarenessContext getAwarenessFromDpiAwarenessContext = nullptr;
+ SystemParametersInfoForDpi systemParametersInfoForDpi = nullptr;
};
// Shell scaling library (Windows 8.1 onwards)
@@ -134,7 +159,8 @@ public:
enum SystemInfoFlags
{
SI_RTL_Extensions = 0x1,
- SI_SupportsTouch = 0x2
+ SI_SupportsTouch = 0x2,
+ SI_SupportsPointer = 0x4,
};
// Verbose flag set by environment variable QT_QPA_VERBOSE
@@ -145,6 +171,8 @@ public:
bool initTouch();
bool initTouch(unsigned integrationOptions); // For calls from QWindowsIntegration::QWindowsIntegration() only.
+ bool initTablet(unsigned integrationOptions);
+ bool initPointer(unsigned integrationOptions);
int defaultDPI() const;
@@ -191,12 +219,16 @@ public:
void setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness);
static int processDpiAwareness();
+ void setDetectAltGrModifier(bool a);
+
// Returns a combination of SystemInfoFlags
unsigned systemInfo() const;
bool useRTLExtensions() const;
QList<int> possibleKeys(const QKeyEvent *e) const;
+ static bool isSessionLocked();
+
QWindowsMimeConverter &mimeConverter() const;
QWindowsScreenManager &screenManager();
QWindowsTabletSupport *tabletSupport() const;
@@ -208,6 +240,17 @@ public:
bool asyncExpose() const;
void setAsyncExpose(bool value);
+ static bool systemParametersInfo(unsigned action, unsigned param, void *out, unsigned dpi = 0);
+ static bool systemParametersInfoForScreen(unsigned action, unsigned param, void *out,
+ const QPlatformScreen *screen = nullptr);
+ static bool systemParametersInfoForWindow(unsigned action, unsigned param, void *out,
+ const QPlatformWindow *win = nullptr);
+ static bool nonClientMetrics(NONCLIENTMETRICS *ncm, unsigned dpi = 0);
+ static bool nonClientMetricsForScreen(NONCLIENTMETRICS *ncm,
+ const QPlatformScreen *screen = nullptr);
+ static bool nonClientMetricsForWindow(NONCLIENTMETRICS *ncm,
+ const QPlatformWindow *win = nullptr);
+
static DWORD readAdvancedExplorerSettings(const wchar_t *subKey, DWORD defaultValue);
QTouchDevice *touchDevice() const;
@@ -220,6 +263,7 @@ private:
#ifndef QT_NO_CONTEXTMENU
bool handleContextMenuEvent(QWindow *window, const MSG &msg);
#endif
+ void handleExitSizeMove(QWindow *window);
void unregisterWindowClasses();
QScopedPointer<QWindowsContextPrivate> d;
diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp
index 72155a1d1b..4f669a5509 100644
--- a/src/plugins/platforms/windows/qwindowscursor.cpp
+++ b/src/plugins/platforms/windows/qwindowscursor.cpp
@@ -43,16 +43,16 @@
#include "qwindowswindow.h"
#include "qwindowsscreen.h"
-#include <QtGui/QBitmap>
-#include <QtGui/QImage>
-#include <QtGui/QBitmap>
-#include <QtGui/QGuiApplication>
-#include <QtGui/QScreen>
+#include <QtGui/qbitmap.h>
+#include <QtGui/qimage.h>
+#include <QtGui/qbitmap.h>
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qscreen.h>
#include <QtGui/private/qguiapplication_p.h> // getPixmapCursor()
#include <QtGui/private/qhighdpiscaling_p.h>
-#include <QtCore/QDebug>
-#include <QtCore/QScopedArrayPointer>
+#include <QtCore/qdebug.h>
+#include <QtCore/qscopedpointer.h>
static bool initResources()
{
@@ -524,10 +524,11 @@ HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape, const
}
// Load available standard cursors from resources
- const QWindowsStandardCursorMapping *sEnd = standardCursors + sizeof(standardCursors) / sizeof(standardCursors[0]);
- for (const QWindowsStandardCursorMapping *s = standardCursors; s < sEnd; ++s) {
- if (s->shape == cursorShape)
- return static_cast<HCURSOR>(LoadImage(0, s->resource, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED));
+ for (const QWindowsStandardCursorMapping &s : standardCursors) {
+ if (s.shape == cursorShape) {
+ return static_cast<HCURSOR>(LoadImage(nullptr, s.resource, IMAGE_CURSOR,
+ 0, 0, LR_DEFAULTSIZE | LR_SHARED));
+ }
}
qWarning("%s: Invalid cursor shape %d", __FUNCTION__, cursorShape);
@@ -659,18 +660,18 @@ QPoint QWindowsCursor::mousePosition()
return QPoint(p.x, p.y);
}
-QWindowsCursor::CursorState QWindowsCursor::cursorState()
+QWindowsCursor::State QWindowsCursor::cursorState()
{
enum { cursorShowing = 0x1, cursorSuppressed = 0x2 }; // Windows 8: CURSOR_SUPPRESSED
CURSORINFO cursorInfo;
cursorInfo.cbSize = sizeof(CURSORINFO);
if (GetCursorInfo(&cursorInfo)) {
- if (cursorInfo.flags & CursorShowing)
- return CursorShowing;
+ if (cursorInfo.flags & cursorShowing)
+ return State::Showing;
if (cursorInfo.flags & cursorSuppressed)
- return CursorSuppressed;
+ return State::Suppressed;
}
- return CursorHidden;
+ return State::Hidden;
}
QPoint QWindowsCursor::pos() const
diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h
index 345f47597e..8495b51a5a 100644
--- a/src/plugins/platforms/windows/qwindowscursor.h
+++ b/src/plugins/platforms/windows/qwindowscursor.h
@@ -43,8 +43,8 @@
#include <QtCore/qt_windows.h>
#include <qpa/qplatformcursor.h>
-#include <QtCore/QSharedPointer>
-#include <QtCore/QHash>
+#include <QtCore/qsharedpointer.h>
+#include <QtCore/qhash.h>
QT_BEGIN_NAMESPACE
@@ -89,10 +89,10 @@ typedef QSharedPointer<CursorHandle> CursorHandlePtr;
class QWindowsCursor : public QPlatformCursor
{
public:
- enum CursorState {
- CursorShowing,
- CursorHidden,
- CursorSuppressed // Cursor suppressed by touch interaction (Windows 8).
+ enum class State {
+ Showing,
+ Hidden,
+ Suppressed // Cursor suppressed by touch interaction (Windows 8).
};
struct PixmapCursor {
@@ -119,7 +119,7 @@ public:
static HCURSOR createCursorFromShape(Qt::CursorShape cursorShape, const QPlatformScreen *screen = nullptr);
static QPoint mousePosition();
- static CursorState cursorState();
+ static State cursorState();
CursorHandlePtr standardWindowCursor(Qt::CursorShape s = Qt::ArrowCursor);
CursorHandlePtr pixmapWindowCursor(const QCursor &c);
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
index 80ee7b2287..681b35eb7c 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
@@ -51,24 +51,23 @@
#include "qwindowsintegration.h"
#include "qwindowstheme.h" // Color conversion helpers
-#include <QtGui/QGuiApplication>
-#include <QtGui/QColor>
-
-#include <QtCore/QDebug>
-#include <QtCore/QRegularExpression>
-#include <QtCore/QTimer>
-#include <QtCore/QDir>
-#include <QtCore/QScopedArrayPointer>
-#include <QtCore/QSharedPointer>
-#include <QtCore/QObject>
-#include <QtCore/QThread>
-#include <QtCore/QSysInfo>
-#include <QtCore/QSharedData>
-#include <QtCore/QExplicitlySharedDataPointer>
-#include <QtCore/QMutex>
-#include <QtCore/QMutexLocker>
-#include <QtCore/QUuid>
-#include <QtCore/QTemporaryFile>
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qcolor.h>
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qregularexpression.h>
+#include <QtCore/qtimer.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qscopedpointer.h>
+#include <QtCore/qsharedpointer.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qthread.h>
+#include <QtCore/qsysinfo.h>
+#include <QtCore/qshareddata.h>
+#include <QtCore/qshareddata.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/quuid.h>
+#include <QtCore/qtemporaryfile.h>
#include <QtCore/private/qsystemlibrary_p.h>
#include <algorithm>
@@ -365,7 +364,7 @@ static BOOL QT_WIN_CALLBACK findDialogEnumWindowsProc(HWND hwnd, LPARAM lParam)
wchar_t buf[256];
if (!RealGetWindowClass(hwnd, buf, sizeof(buf)/sizeof(wchar_t)) || buf[0] != L'#')
return TRUE;
- if (!GetWindowTextW(hwnd, buf, sizeof(buf)/sizeof(wchar_t)) || wcscmp(buf, context->title.data()))
+ if (!GetWindowTextW(hwnd, buf, sizeof(buf)/sizeof(wchar_t)) || wcscmp(buf, context->title.data()) != 0)
return TRUE;
context->hwnd = hwnd;
return FALSE;
@@ -508,6 +507,7 @@ class QWindowsNativeFileDialogBase;
class QWindowsNativeFileDialogEventHandler : public QWindowsComBase<IFileDialogEvents>
{
+ Q_DISABLE_COPY(QWindowsNativeFileDialogEventHandler)
public:
static IFileDialogEvents *create(QWindowsNativeFileDialogBase *nativeFileDialog);
@@ -523,7 +523,6 @@ public:
QWindowsNativeFileDialogEventHandler(QWindowsNativeFileDialogBase *nativeFileDialog) :
m_nativeFileDialog(nativeFileDialog) {}
- virtual ~QWindowsNativeFileDialogEventHandler() {}
private:
QWindowsNativeFileDialogBase *m_nativeFileDialog;
@@ -787,7 +786,7 @@ class QWindowsNativeFileDialogBase : public QWindowsNativeDialogBase
Q_OBJECT
Q_PROPERTY(bool hideFiltersDetails READ hideFiltersDetails WRITE setHideFiltersDetails)
public:
- ~QWindowsNativeFileDialogBase();
+ ~QWindowsNativeFileDialogBase() override;
inline static QWindowsNativeFileDialogBase *create(QFileDialogOptions::AcceptMode am, const QWindowsFileDialogSharedData &data);
@@ -1027,7 +1026,7 @@ static QList<FilterSpec> filterSpecs(const QStringList &filters,
Q_ASSERT(filterSeparatorRE.isValid());
// Split filter specification as 'Texts (*.txt[;] *.doc)', '*.txt[;] *.doc'
// into description and filters specification as '*.txt;*.doc'
- foreach (const QString &filterString, filters) {
+ for (const QString &filterString : filters) {
const int openingParenPos = filterString.lastIndexOf(QLatin1Char('('));
const int closingParenPos = openingParenPos != -1 ?
filterString.indexOf(QLatin1Char(')'), openingParenPos + 1) : -1;
@@ -1322,7 +1321,7 @@ void QWindowsNativeSaveFileDialog::setNameFilters(const QStringList &f)
// filter only if a default suffix is set (see docs). Set the first available
// suffix unless we have a defaultSuffix.
if (!hasDefaultSuffix()) {
- foreach (const QString &filter, f) {
+ for (const QString &filter : f) {
const QString suffix = suffixFromFilter(filter);
if (!suffix.isEmpty()) {
setDefaultSuffixSys(suffix);
@@ -1546,8 +1545,8 @@ QWindowsNativeDialogBase *QWindowsFileDialogHelper::createNativeDialog()
result->updateDirectory();
result->updateSelectedNameFilter();
const QList<QUrl> initialSelection = opts->initiallySelectedFiles();
- if (initialSelection.size() > 0) {
- const QUrl url = initialSelection.front();
+ if (!initialSelection.empty()) {
+ const QUrl &url = initialSelection.constFirst();
if (url.isLocalFile()) {
QFileInfo info(url.toLocalFile());
if (!info.isDir())
@@ -1699,7 +1698,7 @@ void QWindowsXpNativeFileDialog::doExec(HWND owner)
const QStringList nameFilters = m_options->nameFilters();
if (selectedFilterIndex >= 0 && selectedFilterIndex < nameFilters.size())
m_data.setSelectedNameFilter(nameFilters.at(selectedFilterIndex));
- QUrl firstFile = selectedFiles.front();
+ const QUrl &firstFile = selectedFiles.constFirst();
m_data.setDirectory(firstFile.adjusted(QUrl::RemoveFilename));
m_result = QPlatformDialogHelper::Accepted;
emit accepted();
@@ -1728,7 +1727,7 @@ int QWindowsXpNativeFileDialog::existingDirCallback(HWND hwnd, UINT uMsg, LPARAM
switch (uMsg) {
case BFFM_INITIALIZED: {
if (!m_title.isEmpty())
- SetWindowText(hwnd, (wchar_t *)m_title.utf16());
+ SetWindowText(hwnd, reinterpret_cast<const wchar_t *>(m_title.utf16()));
const QString initialFile = QDir::toNativeSeparators(m_data.directory().toLocalFile());
if (!initialFile.isEmpty())
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, LPARAM(initialFile.utf16()));
@@ -1781,12 +1780,12 @@ void QWindowsXpNativeFileDialog::populateOpenFileName(OPENFILENAME *ofn, HWND ow
// Create a buffer with the filter strings.
int totalStringLength = 0;
- QList<FilterSpec> specs =
+ const QList<FilterSpec> specs =
filterSpecs(m_options->nameFilters(), m_options->options() & QFileDialogOptions::HideNameFilterDetails, &totalStringLength);
const int size = specs.size();
wchar_t *ptr = new wchar_t[totalStringLength + 2 * size + 1];
ofn->lpstrFilter = ptr;
- foreach (const FilterSpec &spec, specs) {
+ for (const FilterSpec &spec : specs) {
ptr += spec.description.toWCharArray(ptr);
*ptr++ = 0;
ptr += spec.filter.toWCharArray(ptr);
@@ -1874,7 +1873,7 @@ QList<QUrl> QWindowsXpNativeFileDialog::execFileNames(HWND owner, int *selectedF
class QWindowsXpFileDialogHelper : public QWindowsDialogHelperBase<QPlatformFileDialogHelper>
{
public:
- QWindowsXpFileDialogHelper() {}
+ QWindowsXpFileDialogHelper() = default;
bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const override { return false; }
bool defaultNameFilterDisables() const override
{ return true; }
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.h b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
index 55f112c57a..6099ea9ac6 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.h
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
@@ -43,8 +43,8 @@
#include <QtCore/qt_windows.h>
#include <qpa/qplatformdialoghelper.h>
#include <qpa/qplatformtheme.h>
-#include <QtCore/QStringList>
-#include <QtCore/QSharedPointer>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qsharedpointer.h>
QT_BEGIN_NAMESPACE
@@ -78,7 +78,7 @@ public:
virtual bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const { return true; }
protected:
- QWindowsDialogHelperBase() {}
+ QWindowsDialogHelperBase() = default;
QWindowsNativeDialogBase *nativeDialog() const;
inline bool hasNativeDialog() const { return m_nativeDialog; }
void timerEvent(QTimerEvent *) override;
diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp
index e427ee162a..ee82b2f022 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.cpp
+++ b/src/plugins/platforms/windows/qwindowsdrag.cpp
@@ -50,19 +50,19 @@
#include "qwindowsmousehandler.h"
#include "qwindowscursor.h"
-#include <QtGui/QMouseEvent>
-#include <QtGui/QPixmap>
-#include <QtGui/QPainter>
-#include <QtGui/QRasterWindow>
-#include <QtGui/QGuiApplication>
+#include <QtGui/qevent.h>
+#include <QtGui/qpixmap.h>
+#include <QtGui/qpainter.h>
+#include <QtGui/qrasterwindow.h>
+#include <QtGui/qguiapplication.h>
#include <qpa/qwindowsysteminterface_p.h>
#include <QtGui/private/qdnd_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/private/qhighdpiscaling_p.h>
-#include <QtCore/QDebug>
-#include <QtCore/QBuffer>
-#include <QtCore/QPoint>
+#include <QtCore/qdebug.h>
+#include <QtCore/qbuffer.h>
+#include <QtCore/qpoint.h>
#include <shlobj.h>
@@ -225,7 +225,7 @@ public:
};
explicit QWindowsOleDropSource(QWindowsDrag *drag);
- virtual ~QWindowsOleDropSource();
+ ~QWindowsOleDropSource() override;
void createCursors();
@@ -260,7 +260,7 @@ private:
};
QWindowsOleDropSource::QWindowsOleDropSource(QWindowsDrag *drag)
- : m_mode(QWindowsCursor::cursorState() != QWindowsCursor::CursorSuppressed ? MouseDrag : TouchDrag)
+ : m_mode(QWindowsCursor::cursorState() != QWindowsCursor::State::Suppressed ? MouseDrag : TouchDrag)
, m_drag(drag)
, m_windowUnderMouse(QWindowsContext::instance()->windowUnderMouse())
, m_currentButtons(Qt::NoButton)
@@ -402,20 +402,16 @@ QWindowsOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
switch (result) {
case DRAGDROP_S_DROP:
case DRAGDROP_S_CANCEL:
- QGuiApplicationPrivate::modifier_buttons = toQtKeyboardModifiers(grfKeyState);
- if (buttons != QGuiApplicationPrivate::mouse_buttons) {
- if (m_windowUnderMouse.isNull() || m_mode == TouchDrag || fEscapePressed == TRUE) {
- QGuiApplicationPrivate::mouse_buttons = buttons;
- } else {
- // QTBUG 66447: Synthesize a mouse release to the window under mouse at
- // start of the DnD operation as Windows does not send any.
- const QPoint globalPos = QWindowsCursor::mousePosition();
- const QPoint localPos = m_windowUnderMouse->handle()->mapFromGlobal(globalPos);
- QWindowSystemInterface::handleMouseEvent(m_windowUnderMouse.data(),
- QPointF(localPos), QPointF(globalPos),
- QWindowsMouseHandler::queryMouseButtons(),
- Qt::LeftButton, QEvent::MouseButtonRelease);
- }
+ if (!m_windowUnderMouse.isNull() && m_mode != TouchDrag && fEscapePressed == FALSE
+ && buttons != QGuiApplicationPrivate::mouse_buttons) {
+ // QTBUG 66447: Synthesize a mouse release to the window under mouse at
+ // start of the DnD operation as Windows does not send any.
+ const QPoint globalPos = QWindowsCursor::mousePosition();
+ const QPoint localPos = m_windowUnderMouse->handle()->mapFromGlobal(globalPos);
+ QWindowSystemInterface::handleMouseEvent(m_windowUnderMouse.data(),
+ QPointF(localPos), QPointF(globalPos),
+ QWindowsMouseHandler::queryMouseButtons(),
+ Qt::LeftButton, QEvent::MouseButtonRelease);
}
m_currentButtons = Qt::NoButton;
break;
@@ -459,7 +455,7 @@ QWindowsOleDropSource::GiveFeedback(DWORD dwEffect)
break;
case TouchDrag:
// "Touch drag" with an unsuppressed cursor may happen with RDP (see createCursors())
- if (QWindowsCursor::cursorState() != QWindowsCursor::CursorSuppressed)
+ if (QWindowsCursor::cursorState() != QWindowsCursor::State::Suppressed)
SetCursor(nullptr);
if (!m_touchDragWindow)
m_touchDragWindow = new QWindowsDragCursorWindow;
@@ -507,11 +503,13 @@ void QWindowsOleDropTarget::handleDrag(QWindow *window, DWORD grfKeyState,
QWindowsDrag *windowsDrag = QWindowsDrag::instance();
const Qt::DropActions actions = translateToQDragDropActions(*pdwEffect);
- QGuiApplicationPrivate::modifier_buttons = toQtKeyboardModifiers(grfKeyState);
- QGuiApplicationPrivate::mouse_buttons = toQtMouseButtons(grfKeyState);
+ const Qt::KeyboardModifiers keyboardModifiers = toQtKeyboardModifiers(grfKeyState);
+ const Qt::MouseButtons mouseButtons = toQtMouseButtons(grfKeyState);
const QPlatformDragQtResponse response =
- QWindowSystemInterface::handleDrag(window, windowsDrag->dropData(), m_lastPoint, actions);
+ QWindowSystemInterface::handleDrag(window, windowsDrag->dropData(),
+ m_lastPoint, actions,
+ mouseButtons, keyboardModifiers);
m_answerRect = response.answerRect();
const Qt::DropAction action = response.acceptedAction();
@@ -523,8 +521,7 @@ void QWindowsOleDropTarget::handleDrag(QWindow *window, DWORD grfKeyState,
*pdwEffect = m_chosenEffect;
qCDebug(lcQpaMime) << __FUNCTION__ << m_window
<< windowsDrag->dropData() << " supported actions=" << actions
- << " mods=" << QGuiApplicationPrivate::modifier_buttons
- << " mouse=" << QGuiApplicationPrivate::mouse_buttons
+ << " mods=" << keyboardModifiers << " mouse=" << mouseButtons
<< " accepted: " << response.isAccepted() << action
<< m_answerRect << " effect" << *pdwEffect;
}
@@ -575,13 +572,11 @@ QWindowsOleDropTarget::DragLeave()
qCDebug(lcQpaMime) << __FUNCTION__ << ' ' << m_window;
- QWindowSystemInterface::handleDrag(m_window, 0, QPoint(), Qt::IgnoreAction);
+ QWindowSystemInterface::handleDrag(m_window, 0, QPoint(), Qt::IgnoreAction,
+ Qt::NoButton, Qt::NoModifier);
- if (!QDragManager::self()->source()) {
- QGuiApplicationPrivate::modifier_buttons = Qt::NoModifier;
- QGuiApplicationPrivate::mouse_buttons = Qt::NoButton;
+ if (!QDragManager::self()->source())
m_lastKeyState = 0;
- }
QWindowsDrag::instance()->releaseDropDataObject();
return NOERROR;
@@ -600,18 +595,16 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState,
<< "keys=" << grfKeyState << "pt=" << pt.x << ',' << pt.y;
m_lastPoint = QWindowsGeometryHint::mapFromGlobal(m_window, QPoint(pt.x,pt.y));
- // grfKeyState does not all ways contain button state in the drop
- QGuiApplicationPrivate::mouse_buttons = toQtMouseButtons(m_lastKeyState);
- QGuiApplicationPrivate::modifier_buttons = toQtKeyboardModifiers(grfKeyState);
QWindowsDrag *windowsDrag = QWindowsDrag::instance();
const QPlatformDropQtResponse response =
QWindowSystemInterface::handleDrop(m_window, windowsDrag->dropData(),
m_lastPoint,
- translateToQDragDropActions(*pdwEffect));
+ translateToQDragDropActions(*pdwEffect),
+ toQtMouseButtons(grfKeyState),
+ toQtKeyboardModifiers(grfKeyState));
- QGuiApplicationPrivate::mouse_buttons = toQtMouseButtons(grfKeyState);
m_lastKeyState = grfKeyState;
if (response.isAccepted()) {
@@ -659,6 +652,7 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState,
*/
bool QWindowsDrag::m_canceled = false;
+bool QWindowsDrag::m_dragging = false;
QWindowsDrag::QWindowsDrag() = default;
@@ -706,7 +700,10 @@ Qt::DropAction QWindowsDrag::drag(QDrag *drag)
const DWORD allowedEffects = translateToWinDragEffects(possibleActions);
qCDebug(lcQpaMime) << '>' << __FUNCTION__ << "possible Actions=0x"
<< hex << int(possibleActions) << "effects=0x" << allowedEffects << dec;
+ // Indicate message handlers we are in DoDragDrop() event loop.
+ QWindowsDrag::m_dragging = true;
const HRESULT r = DoDragDrop(dropDataObject, windowDropSource, allowedEffects, &resultEffect);
+ QWindowsDrag::m_dragging = false;
const DWORD reportedPerformedEffect = dropDataObject->reportedPerformedEffect();
if (r == DRAGDROP_S_DROP) {
if (reportedPerformedEffect == DROPEFFECT_MOVE && resultEffect != DROPEFFECT_MOVE) {
diff --git a/src/plugins/platforms/windows/qwindowsdrag.h b/src/plugins/platforms/windows/qwindowsdrag.h
index d934679488..5f30c59882 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.h
+++ b/src/plugins/platforms/windows/qwindowsdrag.h
@@ -44,8 +44,8 @@
#include "qwindowsinternalmimedata.h"
#include <qpa/qplatformdrag.h>
+#include <QtGui/qpixmap.h>
#include <QtGui/qdrag.h>
-#include <QtGui/QPixmap>
struct IDropTargetHelper;
@@ -55,7 +55,7 @@ class QPlatformScreen;
class QWindowsDropMimeData : public QWindowsInternalMimeData {
public:
- QWindowsDropMimeData() {}
+ QWindowsDropMimeData() = default;
IDataObject *retrieveDataObject() const override;
};
@@ -63,7 +63,7 @@ class QWindowsOleDropTarget : public QWindowsComBase<IDropTarget>
{
public:
explicit QWindowsOleDropTarget(QWindow *w);
- virtual ~QWindowsOleDropTarget();
+ ~QWindowsOleDropTarget() override;
// IDropTarget methods
STDMETHOD(DragEnter)(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect);
@@ -92,6 +92,7 @@ public:
static QWindowsDrag *instance();
void cancelDrag() override { QWindowsDrag::m_canceled = true; }
static bool isCanceled() { return QWindowsDrag::m_canceled; }
+ static bool isDragging() { return QWindowsDrag::m_dragging; }
IDataObject *dropDataObject() const { return m_dropDataObject; }
void setDropDataObject(IDataObject *dataObject) { m_dropDataObject = dataObject; }
@@ -102,6 +103,7 @@ public:
private:
static bool m_canceled;
+ static bool m_dragging;
QWindowsDropMimeData m_dropData;
IDataObject *m_dropDataObject = nullptr;
diff --git a/src/plugins/platforms/windows/qwindowsdropdataobject.cpp b/src/plugins/platforms/windows/qwindowsdropdataobject.cpp
index bd532ab70e..229ff92894 100644
--- a/src/plugins/platforms/windows/qwindowsdropdataobject.cpp
+++ b/src/plugins/platforms/windows/qwindowsdropdataobject.cpp
@@ -39,8 +39,8 @@
#include "qwindowsdropdataobject.h"
-#include <QtCore/QUrl>
-#include <QtCore/QMimeData>
+#include <QtCore/qurl.h>
+#include <QtCore/qmimedata.h>
QT_BEGIN_NAMESPACE
@@ -60,9 +60,7 @@ QWindowsDropDataObject::QWindowsDropDataObject(QMimeData *mimeData) :
{
}
-QWindowsDropDataObject::~QWindowsDropDataObject()
-{
-}
+QWindowsDropDataObject::~QWindowsDropDataObject() = default;
STDMETHODIMP
QWindowsDropDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium)
diff --git a/src/plugins/platforms/windows/qwindowsdropdataobject.h b/src/plugins/platforms/windows/qwindowsdropdataobject.h
index 5ef72c9336..16ba7b036a 100644
--- a/src/plugins/platforms/windows/qwindowsdropdataobject.h
+++ b/src/plugins/platforms/windows/qwindowsdropdataobject.h
@@ -48,7 +48,7 @@ class QWindowsDropDataObject : public QWindowsOleDataObject
{
public:
explicit QWindowsDropDataObject(QMimeData *mimeData);
- virtual ~QWindowsDropDataObject();
+ ~QWindowsDropDataObject() override;
// overridden IDataObject methods
STDMETHOD(GetData)(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium);
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp
index 4632c9c157..52f3c56beb 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp
@@ -41,8 +41,8 @@
#include "qwindowscontext.h"
#include "qwindowswindow.h"
-#include <QtCore/QDebug>
-#include <QtGui/QOpenGLContext>
+#include <QtCore/qdebug.h>
+#include <QtGui/qopenglcontext.h>
#if defined(QT_OPENGL_ES_2_ANGLE) || defined(QT_OPENGL_DYNAMIC)
# include <EGL/eglext.h>
@@ -889,19 +889,19 @@ EGLConfig QWindowsEGLContext::chooseConfig(const QSurfaceFormat &format)
EGLint green = 0;
EGLint blue = 0;
EGLint alpha = 0;
- for (int i = 0; i < configs.size(); ++i) {
+ for (const EGLConfig &config : configs) {
if (confAttrRed)
- QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, configs[i], EGL_RED_SIZE, &red);
+ QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, config, EGL_RED_SIZE, &red);
if (confAttrGreen)
- QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, configs[i], EGL_GREEN_SIZE, &green);
+ QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &green);
if (confAttrBlue)
- QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, configs[i], EGL_BLUE_SIZE, &blue);
+ QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blue);
if (confAttrAlpha)
- QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, configs[i], EGL_ALPHA_SIZE, &alpha);
+ QWindowsEGLStaticContext::libEGL.eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &alpha);
if (red == confAttrRed && green == confAttrGreen
&& blue == confAttrBlue && alpha == confAttrAlpha)
- return configs[i];
+ return config;
}
} while (reduceConfigAttributes(&configureAttributes));
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h
index 3e5f2c81d5..8a1e1ddae8 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.h
+++ b/src/plugins/platforms/windows/qwindowseglcontext.h
@@ -113,7 +113,7 @@ class QWindowsEGLStaticContext : public QWindowsStaticOpenGLContext
public:
static QWindowsEGLStaticContext *create(QWindowsOpenGLTester::Renderers preferredType);
- ~QWindowsEGLStaticContext();
+ ~QWindowsEGLStaticContext() override;
EGLDisplay display() const { return m_display; }
@@ -143,7 +143,7 @@ public:
QWindowsEGLContext(QWindowsEGLStaticContext *staticContext,
const QSurfaceFormat &format,
QPlatformOpenGLContext *share);
- ~QWindowsEGLContext();
+ ~QWindowsEGLContext() override;
bool makeCurrent(QPlatformSurface *surface) override;
void doneCurrent() override;
diff --git a/src/plugins/platforms/windows/qwindowsgdiintegration.cpp b/src/plugins/platforms/windows/qwindowsgdiintegration.cpp
index 51f74518f7..c88f669eb5 100644
--- a/src/plugins/platforms/windows/qwindowsgdiintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsgdiintegration.cpp
@@ -42,7 +42,7 @@
#include "qwindowsbackingstore.h"
#include "qwindowsgdinativeinterface.h"
-#include <QtCore/QDebug>
+#include <QtCore/qdebug.h>
#include <QtGui/private/qpixmap_raster_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsgdiintegration.h b/src/plugins/platforms/windows/qwindowsgdiintegration.h
index ec67a99bc9..74ce3ffd49 100644
--- a/src/plugins/platforms/windows/qwindowsgdiintegration.h
+++ b/src/plugins/platforms/windows/qwindowsgdiintegration.h
@@ -49,7 +49,7 @@ class QWindowsGdiIntegration : public QWindowsIntegration
{
public:
explicit QWindowsGdiIntegration(const QStringList &paramList);
- virtual ~QWindowsGdiIntegration();
+ ~QWindowsGdiIntegration() override;
QPlatformNativeInterface *nativeInterface() const override;
QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const override;
diff --git a/src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp b/src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp
index c7796d959e..4ba7108f45 100644
--- a/src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp
+++ b/src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp
@@ -40,7 +40,7 @@
#include "qwindowsgdinativeinterface.h"
#include "qwindowsbackingstore.h"
-#include <QtGui/QBackingStore>
+#include <QtGui/qbackingstore.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp
index cc8174051a..851a6c961e 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp
@@ -42,11 +42,11 @@
#include "qwindowswindow.h"
#include "qwindowsintegration.h"
-#include <QtCore/QDebug>
-#include <QtCore/QSysInfo>
-#include <QtGui/QGuiApplication>
+#include <QtCore/qdebug.h>
+#include <QtCore/qsysinfo.h>
+#include <QtGui/qguiapplication.h>
#include <qpa/qplatformnativeinterface.h>
-#include <QtPlatformHeaders/QWGLNativeContext>
+#include <QtPlatformHeaders/qwglnativecontext.h>
#include <algorithm>
@@ -206,18 +206,12 @@ bool QWindowsOpengl32DLL::init(bool softwareRendering)
BOOL QWindowsOpengl32DLL::swapBuffers(HDC dc)
{
- if (moduleIsNotOpengl32())
- return wglSwapBuffers(dc);
- else
- return SwapBuffers(dc);
+ return moduleIsNotOpengl32() ? wglSwapBuffers(dc) : SwapBuffers(dc);
}
BOOL QWindowsOpengl32DLL::setPixelFormat(HDC dc, int pf, const PIXELFORMATDESCRIPTOR *pfd)
{
- if (moduleIsNotOpengl32())
- return wglSetPixelFormat(dc, pf, pfd);
- else
- return SetPixelFormat(dc, pf, pfd);
+ return moduleIsNotOpengl32() ? wglSetPixelFormat(dc, pf, pfd) : SetPixelFormat(dc, pf, pfd);
}
QWindowsOpenGLContext *QOpenGLStaticContext::createContext(QOpenGLContext *context)
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.h b/src/plugins/platforms/windows/qwindowsglcontext.h
index 87c3723c26..199f8112e3 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.h
+++ b/src/plugins/platforms/windows/qwindowsglcontext.h
@@ -43,7 +43,7 @@
#include <QtCore/qt_windows.h>
#include "qwindowsopenglcontext.h"
-#include <QtGui/QOpenGLContext>
+#include <QtGui/qopenglcontext.h>
#include <vector>
@@ -170,13 +170,15 @@ public:
static QOpenGLStaticContext *create(bool softwareRendering = false);
static QByteArray getGlString(unsigned int which);
- QWindowsOpenGLContext *createContext(QOpenGLContext *context);
- void *moduleHandle() const { return opengl32.moduleHandle(); }
- QOpenGLContext::OpenGLModuleType moduleType() const { return QOpenGLContext::LibGL; }
+ QWindowsOpenGLContext *createContext(QOpenGLContext *context) override;
+ void *moduleHandle() const override { return opengl32.moduleHandle(); }
+ QOpenGLContext::OpenGLModuleType moduleType() const override
+ { return QOpenGLContext::LibGL; }
// For a regular opengl32.dll report the ThreadedOpenGL capability.
// For others, which are likely to be software-only, don't.
- bool supportsThreadedOpenGL() const { return !opengl32.moduleIsNotOpengl32(); }
+ bool supportsThreadedOpenGL() const override
+ { return !opengl32.moduleIsNotOpengl32(); }
const QByteArray vendor;
const QByteArray renderer;
@@ -198,7 +200,7 @@ class QWindowsGLContext : public QWindowsOpenGLContext
{
public:
explicit QWindowsGLContext(QOpenGLStaticContext *staticContext, QOpenGLContext *context);
- ~QWindowsGLContext();
+ ~QWindowsGLContext() override;
bool isSharing() const override { return m_context->shareHandle(); }
bool isValid() const override { return m_renderingContext && !m_lost; }
QSurfaceFormat format() const override { return m_obtainedFormat; }
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
index 261c931f2b..30da0da1de 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
@@ -43,16 +43,15 @@
#include "qwindowsintegration.h"
#include "qwindowsmousehandler.h"
-#include <QtCore/QDebug>
-#include <QtCore/QObject>
-#include <QtCore/QRect>
-#include <QtCore/QRectF>
-#include <QtCore/QTextBoundaryFinder>
-
-#include <QtGui/QInputMethodEvent>
-#include <QtGui/QTextCharFormat>
-#include <QtGui/QPalette>
-#include <QtGui/QGuiApplication>
+#include <QtCore/qdebug.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qtextboundaryfinder.h>
+
+#include <QtGui/qevent.h>
+#include <QtGui/qtextformat.h>
+#include <QtGui/qpalette.h>
+#include <QtGui/qguiapplication.h>
#include <private/qhighdpiscaling_p.h>
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.h b/src/plugins/platforms/windows/qwindowsinputcontext.h
index d647628ff1..a47585c29e 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.h
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.h
@@ -42,8 +42,8 @@
#include <QtCore/qt_windows.h>
-#include <QtCore/QLocale>
-#include <QtCore/QPointer>
+#include <QtCore/qlocale.h>
+#include <QtCore/qpointer.h>
#include <qpa/qplatforminputcontext.h>
QT_BEGIN_NAMESPACE
@@ -53,6 +53,7 @@ class QWindowsWindow;
class QWindowsInputContext : public QPlatformInputContext
{
+ Q_DISABLE_COPY(QWindowsInputContext)
Q_OBJECT
struct CompositionContext
@@ -65,7 +66,7 @@ class QWindowsInputContext : public QPlatformInputContext
};
public:
explicit QWindowsInputContext();
- ~QWindowsInputContext();
+ ~QWindowsInputContext() override;
static void setWindowsImeEnabled(QWindowsWindow *platformWindow, bool enabled);
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index 0a9e8b9d91..9e03d09607 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -59,7 +59,7 @@
#endif
#include "qwindowsinputcontext.h"
#include "qwindowskeymapper.h"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
# include "uiautomation/qwindowsuiaaccessibility.h"
#endif
@@ -76,8 +76,8 @@
#include <QtEventDispatcherSupport/private/qwindowsguieventdispatcher_p.h>
-#include <QtCore/QDebug>
-#include <QtCore/QVariant>
+#include <QtCore/qdebug.h>
+#include <QtCore/qvariant.h>
#include <limits.h>
@@ -133,6 +133,7 @@ QT_BEGIN_NAMESPACE
struct QWindowsIntegrationPrivate
{
+ Q_DISABLE_COPY(QWindowsIntegrationPrivate)
explicit QWindowsIntegrationPrivate(const QStringList &paramList);
~QWindowsIntegrationPrivate();
@@ -150,7 +151,7 @@ struct QWindowsIntegrationPrivate
QScopedPointer<QWindowsStaticOpenGLContext> m_staticOpenGLContext;
#endif // QT_NO_OPENGL
QScopedPointer<QPlatformInputContext> m_inputContext;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QWindowsUiaAccessibility m_accessibility;
#endif
QWindowsServices m_services;
@@ -184,7 +185,7 @@ static inline unsigned parseOptions(const QStringList &paramList,
QtWindows::ProcessDpiAwareness *dpiAwareness)
{
unsigned options = 0;
- foreach (const QString &param, paramList) {
+ for (const QString &param : paramList) {
if (param.startsWith(QLatin1String("fontengine="))) {
if (param.endsWith(QLatin1String("freetype"))) {
options |= QWindowsIntegration::FontDatabaseFreeType;
@@ -197,6 +198,8 @@ static inline unsigned parseOptions(const QStringList &paramList,
} else if (param.endsWith(QLatin1String("none"))) {
options |= QWindowsIntegration::NoNativeDialogs;
}
+ } else if (param == QLatin1String("altgr")) {
+ options |= QWindowsIntegration::DetectAltGrModifier;
} else if (param == QLatin1String("gl=gdi")) {
options |= QWindowsIntegration::DisableArb;
} else if (param == QLatin1String("nodirectwrite")) {
@@ -212,6 +215,8 @@ static inline unsigned parseOptions(const QStringList &paramList,
options |= QWindowsIntegration::AlwaysUseNativeMenus;
} else if (param == QLatin1String("menus=none")) {
options |= QWindowsIntegration::NoNativeMenus;
+ } else if (param == QLatin1String("nowmpointer")) {
+ options |= QWindowsIntegration::DontUseWMPointer;
} else {
qWarning() << "Unknown option" << param;
}
@@ -230,8 +235,15 @@ QWindowsIntegrationPrivate::QWindowsIntegrationPrivate(const QStringList &paramL
QtWindows::ProcessDpiAwareness dpiAwareness = QtWindows::ProcessPerMonitorDpiAware;
m_options = parseOptions(paramList, &tabletAbsoluteRange, &dpiAwareness);
QWindowsFontDatabase::setFontOptions(m_options);
- if (tabletAbsoluteRange >= 0)
- m_context.setTabletAbsoluteRange(tabletAbsoluteRange);
+
+ if (m_context.initPointer(m_options)) {
+ QCoreApplication::setAttribute(Qt::AA_CompressHighFrequencyEvents);
+ } else {
+ m_context.initTablet(m_options);
+ if (tabletAbsoluteRange >= 0)
+ m_context.setTabletAbsoluteRange(tabletAbsoluteRange);
+ }
+
if (!dpiAwarenessSet) { // Set only once in case of repeated instantiations of QGuiApplication.
if (!QCoreApplication::testAttribute(Qt::AA_PluginApplication)) {
m_context.setProcessDpiAwareness(dpiAwareness);
@@ -248,8 +260,7 @@ QWindowsIntegrationPrivate::QWindowsIntegrationPrivate(const QStringList &paramL
QWindowsIntegrationPrivate::~QWindowsIntegrationPrivate()
{
- if (m_fontDatabase)
- delete m_fontDatabase;
+ delete m_fontDatabase;
}
QWindowsIntegration *QWindowsIntegration::m_instance = nullptr;
@@ -262,6 +273,7 @@ QWindowsIntegration::QWindowsIntegration(const QStringList &paramList) :
d->m_clipboard.registerViewer();
#endif
d->m_context.screenManager().handleScreenChanges();
+ d->m_context.setDetectAltGrModifier((d->m_options & DetectAltGrModifier) != 0);
}
QWindowsIntegration::~QWindowsIntegration()
@@ -332,7 +344,7 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
<< "\n Requested: " << requested.geometry << " frame incl.="
<< QWindowsGeometryHint::positionIncludesFrame(window)
<< ' ' << requested.flags
- << "\n Obtained : " << obtained.geometry << " margins=" << obtained.frame
+ << "\n Obtained : " << obtained.geometry << " margins=" << obtained.fullFrameMargins
<< " handle=" << obtained.hwnd << ' ' << obtained.flags << '\n';
if (Q_UNLIKELY(!obtained.hwnd))
@@ -381,7 +393,7 @@ QWindowsStaticOpenGLContext *QWindowsStaticOpenGLContext::doCreate()
switch (requestedRenderer) {
case QWindowsOpenGLTester::DesktopGl:
if (QWindowsStaticOpenGLContext *glCtx = QOpenGLStaticContext::create()) {
- if ((QWindowsOpenGLTester::supportedRenderers() & QWindowsOpenGLTester::DisableRotationFlag)
+ if ((QWindowsOpenGLTester::supportedRenderers(requestedRenderer) & QWindowsOpenGLTester::DisableRotationFlag)
&& !QWindowsScreen::setOrientationPreference(Qt::LandscapeOrientation)) {
qCWarning(lcQpaGl, "Unable to disable rotation.");
}
@@ -395,19 +407,23 @@ QWindowsStaticOpenGLContext *QWindowsStaticOpenGLContext::doCreate()
case QWindowsOpenGLTester::AngleRendererD3d11Warp:
return QWindowsEGLStaticContext::create(requestedRenderer);
case QWindowsOpenGLTester::Gles:
- return QWindowsEGLStaticContext::create(QWindowsOpenGLTester::supportedGlesRenderers());
+ return QWindowsEGLStaticContext::create(requestedRenderer);
case QWindowsOpenGLTester::SoftwareRasterizer:
if (QWindowsStaticOpenGLContext *swCtx = QOpenGLStaticContext::create(true))
return swCtx;
qCWarning(lcQpaGl, "Software OpenGL failed. Falling back to system OpenGL.");
- if (QWindowsOpenGLTester::supportedRenderers() & QWindowsOpenGLTester::DesktopGl)
+ if (QWindowsOpenGLTester::supportedRenderers(requestedRenderer) & QWindowsOpenGLTester::DesktopGl)
return QOpenGLStaticContext::create();
return nullptr;
default:
break;
}
- const QWindowsOpenGLTester::Renderers supportedRenderers = QWindowsOpenGLTester::supportedRenderers();
+ const QWindowsOpenGLTester::Renderers supportedRenderers = QWindowsOpenGLTester::supportedRenderers(requestedRenderer);
+ if (supportedRenderers.testFlag(QWindowsOpenGLTester::DisableProgramCacheFlag)
+ && !QCoreApplication::testAttribute(Qt::AA_DisableShaderDiskCache)) {
+ QCoreApplication::setAttribute(Qt::AA_DisableShaderDiskCache);
+ }
if (supportedRenderers & QWindowsOpenGLTester::DesktopGl) {
if (QWindowsStaticOpenGLContext *glCtx = QOpenGLStaticContext::create()) {
if ((supportedRenderers & QWindowsOpenGLTester::DisableRotationFlag)
@@ -425,7 +441,7 @@ QWindowsStaticOpenGLContext *QWindowsStaticOpenGLContext::doCreate()
#elif defined(QT_OPENGL_ES_2)
QWindowsOpenGLTester::Renderers glesRenderers = QWindowsOpenGLTester::requestedGlesRenderer();
if (glesRenderers == QWindowsOpenGLTester::InvalidRenderer)
- glesRenderers = QWindowsOpenGLTester::supportedGlesRenderers();
+ glesRenderers = QWindowsOpenGLTester::supportedRenderers(QWindowsOpenGLTester::AngleRendererD3d11);
return QWindowsEGLStaticContext::create(glesRenderers);
#elif !defined(QT_NO_OPENGL)
return QOpenGLStaticContext::create();
@@ -560,7 +576,7 @@ QPlatformInputContext * QWindowsIntegration::inputContext() const
return d->m_inputContext.data();
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QPlatformAccessibility *QWindowsIntegration::accessibility() const
{
return &d->m_accessibility;
diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h
index 23f3d9ef4e..da86852766 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.h
+++ b/src/plugins/platforms/windows/qwindowsintegration.h
@@ -42,7 +42,7 @@
#define QWINDOWSINTEGRATION_H
#include <qpa/qplatformintegration.h>
-#include <QtCore/QScopedPointer>
+#include <QtCore/qscopedpointer.h>
#include <QtFontDatabaseSupport/private/qwindowsfontdatabase_p.h>
QT_BEGIN_NAMESPACE
@@ -54,6 +54,7 @@ class QWindowsStaticOpenGLContext;
class QWindowsIntegration : public QPlatformIntegration
{
+ Q_DISABLE_COPY(QWindowsIntegration)
public:
enum Options { // Options to be passed on command line.
FontDatabaseFreeType = 0x1,
@@ -66,11 +67,13 @@ public:
DontUseDirectWriteFonts = QWindowsFontDatabase::DontUseDirectWriteFonts,
DontUseColorFonts = QWindowsFontDatabase::DontUseColorFonts,
AlwaysUseNativeMenus = 0x100,
- NoNativeMenus = 0x200
+ NoNativeMenus = 0x200,
+ DontUseWMPointer = 0x400,
+ DetectAltGrModifier = 0x800
};
explicit QWindowsIntegration(const QStringList &paramList);
- virtual ~QWindowsIntegration();
+ ~QWindowsIntegration() override;
bool hasCapability(QPlatformIntegration::Capability cap) const override;
@@ -90,7 +93,7 @@ public:
# endif
#endif // !QT_NO_CLIPBOARD
QPlatformInputContext *inputContext() const override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QPlatformAccessibility *accessibility() const override;
#endif
QPlatformFontDatabase *fontDatabase() const override;
diff --git a/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp b/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp
index 21ebee6262..8f1d8f73d9 100644
--- a/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp
+++ b/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp
@@ -40,7 +40,7 @@
#include "qwindowsinternalmimedata.h"
#include "qwindowscontext.h"
#include "qwindowsmime.h"
-#include <QDebug>
+#include <QtCore/qdebug.h>
/*!
\class QWindowsInternalMimeDataBase
\brief Base for implementations of QInternalMimeData using a IDataObject COM object.
diff --git a/src/plugins/platforms/windows/qwindowsinternalmimedata.h b/src/plugins/platforms/windows/qwindowsinternalmimedata.h
index a44f5b509c..dbc1ea3922 100644
--- a/src/plugins/platforms/windows/qwindowsinternalmimedata.h
+++ b/src/plugins/platforms/windows/qwindowsinternalmimedata.h
@@ -43,7 +43,7 @@
#include <QtCore/qt_windows.h>
#include <QtGui/private/qinternalmimedata_p.h>
-#include <QtCore/QVariant>
+#include <QtCore/qvariant.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index 950d8ecd36..9e6101b758 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -43,13 +43,14 @@
#include "qwindowswindow.h"
#include "qwindowsinputcontext.h"
-#include <QtGui/QGuiApplication>
-#include <QtGui/QWindow>
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qwindow.h>
#include <qpa/qwindowsysteminterface.h>
#include <private/qguiapplication_p.h>
#include <private/qhighdpiscaling_p.h>
-#include <QtGui/QKeyEvent>
+#include <QtGui/qevent.h>
#include <QtEventDispatcherSupport/private/qwindowsguieventdispatcher_p.h>
+#include <QtCore/private/qdebug_p.h>
#if defined(WM_APPCOMMAND)
# ifndef FAPPCOMMAND_MOUSE
@@ -105,9 +106,7 @@ QWindowsKeyMapper::QWindowsKeyMapper()
changeKeyboard();
}
-QWindowsKeyMapper::~QWindowsKeyMapper()
-{
-}
+QWindowsKeyMapper::~QWindowsKeyMapper()= default;
#ifndef LANG_PASHTO
#define LANG_PASHTO 0x63
@@ -544,6 +543,59 @@ static const Qt::KeyboardModifiers ModsTbl[] = {
static const size_t NumMods = sizeof ModsTbl / sizeof *ModsTbl;
Q_STATIC_ASSERT((NumMods == KeyboardLayoutItem::NumQtKeys));
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const KeyboardLayoutItem &k)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d << "KeyboardLayoutItem(";
+ if (k.exists) {
+ for (size_t i = 0; i < NumMods; ++i) {
+ if (const quint32 qtKey = k.qtKey[i]) {
+ d << '[' << i << ' ';
+ QtDebugUtils::formatQFlags(d, ModsTbl[i]);
+ d << ' ' << hex << showbase << qtKey << dec << noshowbase << ' ';
+ QtDebugUtils::formatQEnum(d, Qt::Key(qtKey));
+ if (qtKey >= 32 && qtKey < 128)
+ d << " '" << char(qtKey) << '\'';
+ if (k.deadkeys & (1<<i))
+ d << " deadkey";
+ d << "] ";
+ }
+ }
+ }
+ d << ')';
+ return d;
+}
+
+// Helpers to format a list of int as Qt key sequence
+class formatKeys
+{
+public:
+ explicit formatKeys(const QList<int> &keys) : m_keys(keys) {}
+
+private:
+ friend QDebug operator<<(QDebug d, const formatKeys &keys);
+ const QList<int> &m_keys;
+};
+
+QDebug operator<<(QDebug d, const formatKeys &k)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d << '(';
+ for (int i =0, size = k.m_keys.size(); i < size; ++i) {
+ if (i)
+ d << ", ";
+ d << QKeySequence(k.m_keys.at(i));
+ }
+ d << ')';
+ return d;
+}
+#else // !QT_NO_DEBUG_STREAM
+static int formatKeys(const QList<int> &) { return 0; }
+#endif // QT_NO_DEBUG_STREAM
+
/**
Remap return or action key to select key for windows mobile.
*/
@@ -599,8 +651,8 @@ static inline int asciiToKeycode(char a, int state)
void QWindowsKeyMapper::deleteLayouts()
{
- for (size_t i = 0; i < NumKeyboardLayoutItems; ++i)
- keyLayout[i].exists = false;
+ for (KeyboardLayoutItem &k : keyLayout)
+ k.exists = false;
}
void QWindowsKeyMapper::changeKeyboard()
@@ -620,6 +672,7 @@ void QWindowsKeyMapper::changeKeyboard()
bidi = true;
keyboardInputDirection = bidi ? Qt::RightToLeft : Qt::LeftToRight;
+ m_seenAltGr = false;
}
// Helper function that is used when obtaining the list of characters that can be produced by one key and
@@ -722,21 +775,8 @@ void QWindowsKeyMapper::updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32
::ToAscii(VK_SPACE, 0, emptyBuffer, reinterpret_cast<LPWORD>(&buffer), 0);
::ToAscii(vk_key, scancode, kbdBuffer, reinterpret_cast<LPWORD>(&buffer), 0);
}
- if (QWindowsContext::verbose > 1 && lcQpaEvents().isDebugEnabled()) {
- QString message;
- QDebug debug(&message);
- debug <<__FUNCTION__ << " for virtual key = 0x" << hex << vk_key << dec<< '\n';
- for (size_t i = 0; i < NumMods; ++i) {
- const quint32 qtKey = keyLayout[vk_key].qtKey[i];
- debug << " [" << i << "] (" << qtKey << ','
- << hex << showbase << qtKey << noshowbase << dec
- << ",'" << char(qtKey ? qtKey : 0x03) << "')";
- if (keyLayout[vk_key].deadkeys & (1<<i))
- debug << " deadkey";
- debug << '\n';
- }
- qCDebug(lcQpaEvents) << message;
- }
+ qCDebug(lcQpaEvents) << __FUNCTION__ << "for virtual key="
+ << hex << showbase << vk_key << dec << noshowbase << keyLayout[vk_key];
}
static inline QString messageKeyText(const MSG &msg)
@@ -837,10 +877,26 @@ bool QWindowsKeyMapper::translateKeyEvent(QWindow *widget, HWND hwnd,
bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, const MSG &msg)
{
#if defined(WM_APPCOMMAND)
+ const int cmd = GET_APPCOMMAND_LPARAM(msg.lParam);
// QTBUG-57198, do not send mouse-synthesized commands as key events in addition
- if (GET_DEVICE_LPARAM(msg.lParam) == FAPPCOMMAND_MOUSE)
+ switch (GET_DEVICE_LPARAM(msg.lParam)) {
+ case FAPPCOMMAND_MOUSE:
return false;
- const int cmd = GET_APPCOMMAND_LPARAM(msg.lParam);
+ case FAPPCOMMAND_KEY:
+ // QTBUG-62838, swallow WM_KEYDOWN, WM_KEYUP for commands that are
+ // reflected in VK(s) like VK_MEDIA_NEXT_TRACK. Don't do that for
+ // APPCOMMAND_BROWSER_HOME as that one does not trigger two events
+ if (cmd != APPCOMMAND_BROWSER_HOME) {
+ MSG peekedMsg;
+ if (PeekMessage(&peekedMsg, msg.hwnd, 0, 0, PM_NOREMOVE)
+ && peekedMsg.message == WM_KEYDOWN) {
+ PeekMessage(&peekedMsg, msg.hwnd, 0, 0, PM_REMOVE);
+ PeekMessage(&peekedMsg, msg.hwnd, 0, 0, PM_REMOVE);
+ }
+ }
+ break;
+ }
+
const int dwKeys = GET_KEYSTATE_LPARAM(msg.lParam);
int state = 0;
state |= (dwKeys & MK_SHIFT ? int(Qt::ShiftModifier) : 0);
@@ -867,8 +923,34 @@ bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, con
#endif
}
-bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &msg, bool /* grab */, LRESULT *lResult)
+// QTBUG-69317: Check for AltGr found on some keyboards
+// which is a sequence of left Ctrl (SYSKEY) + right Menu (Alt).
+static bool isAltGr(MSG *msg)
+{
+ enum : LONG_PTR { RightFlag = 0x1000000 };
+ if (msg->wParam != VK_CONTROL || (msg->lParam & RightFlag) != 0
+ || (msg->message != WM_KEYDOWN && msg->message != WM_SYSKEYUP)) {
+ return false;
+ }
+ const UINT expectedMessage = msg->message == WM_SYSKEYUP
+ ? WM_KEYUP : msg->message;
+ MSG peekedMsg;
+ if (PeekMessage(&peekedMsg, msg->hwnd, 0, 0, PM_NOREMOVE) == FALSE
+ || peekedMsg.message != expectedMessage || peekedMsg.wParam != VK_MENU
+ || (peekedMsg.lParam & RightFlag) == 0) {
+ return false;
+ }
+ *msg = peekedMsg;
+ PeekMessage(&peekedMsg, msg->hwnd, 0, 0, PM_REMOVE);
+ return true;
+}
+
+bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
+ bool /* grab */, LRESULT *lResult)
{
+ const bool altGr = m_detectAltGrModifier && isAltGr(&msg);
+ if (altGr)
+ m_seenAltGr = true;
const UINT msgType = msg.message;
const quint32 scancode = (msg.lParam >> 16) & scancodeBitmask;
@@ -897,10 +979,12 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms
// Get the modifier states (may be altered later, depending on key code)
int state = 0;
state |= (nModifiers & ShiftAny ? int(Qt::ShiftModifier) : 0);
- state |= (nModifiers & ControlAny ? int(Qt::ControlModifier) : 0);
- state |= (nModifiers & AltAny ? int(Qt::AltModifier) : 0);
+ state |= (nModifiers & AltLeft ? int(Qt::AltModifier) : 0);
+ if ((nModifiers & AltRight) != 0)
+ state |= m_seenAltGr ? Qt::GroupSwitchModifier : Qt::AltModifier;
+ if ((nModifiers & ControlAny) != 0 && (state & Qt::GroupSwitchModifier) == 0)
+ state |= Qt::ControlModifier;
state |= (nModifiers & MetaAny ? int(Qt::MetaModifier) : 0);
-
// A multi-character key or a Input method character
// not found by our look-ahead
if (msgType == WM_CHAR || msgType == WM_IME_CHAR) {
@@ -971,8 +1055,17 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms
modifiersIndex |= (nModifiers & ControlAny ? 0x2 : 0);
modifiersIndex |= (nModifiers & AltAny ? 0x4 : 0);
+ // Note: For the resulting key, AltGr is equivalent to Alt + Ctrl (as
+ // opposed to Linux); hence no entry in KeyboardLayoutItem is required
int code = keyLayout[vk_key].qtKey[modifiersIndex];
+ // If the bit 24 of lParm is set you received a enter,
+ // otherwise a Return. (This is the extended key bit)
+ if ((code == Qt::Key_Return) && (msg.lParam & 0x1000000))
+ code = Qt::Key_Enter;
+ else if (altGr)
+ code = Qt::Key_AltGr;
+
// Invert state logic:
// If the key actually pressed is a modifier key, then we remove its modifier key from the
// state, since a modifier-key can't have itself as a modifier
@@ -982,11 +1075,8 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms
state = state ^ Qt::ShiftModifier;
else if (code == Qt::Key_Alt)
state = state ^ Qt::AltModifier;
-
- // If the bit 24 of lParm is set you received a enter,
- // otherwise a Return. (This is the extended key bit)
- if ((code == Qt::Key_Return) && (msg.lParam & 0x1000000))
- code = Qt::Key_Enter;
+ else if (code == Qt::Key_AltGr)
+ state = state ^ Qt::GroupSwitchModifier;
// All cursor keys without extended bit
if (!(msg.lParam & 0x1000000)) {
@@ -1070,7 +1160,8 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms
if (uch.isHighSurrogate()) {
m_lastHighSurrogate = uch;
return true;
- } else if (uch.isLowSurrogate() && !m_lastHighSurrogate.isNull()) {
+ }
+ if (uch.isLowSurrogate() && !m_lastHighSurrogate.isNull()) {
if (QObject *focusObject = QGuiApplication::focusObject()) {
const QChar chars[2] = {m_lastHighSurrogate, uch};
QInputMethodEvent event;
@@ -1287,7 +1378,9 @@ QList<int> QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const
*it = matchedKey;
}
}
-
+ qCDebug(lcQpaEvents) << __FUNCTION__ << e << "nativeVirtualKey="
+ << showbase << hex << e->nativeVirtualKey() << dec << noshowbase
+ << e->modifiers() << kbItem << "\n returns" << formatKeys(result);
return result;
}
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.h b/src/plugins/platforms/windows/qwindowskeymapper.h
index c6b46b0c30..a454f0f973 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.h
+++ b/src/plugins/platforms/windows/qwindowskeymapper.h
@@ -42,7 +42,7 @@
#include <QtCore/qt_windows.h>
-#include <QtCore/QLocale>
+#include <QtCore/qlocale.h>
QT_BEGIN_NAMESPACE
@@ -81,6 +81,9 @@ public:
void setUseRTLExtensions(bool e) { m_useRTLExtensions = e; }
bool useRTLExtensions() const { return m_useRTLExtensions; }
+ void setDetectAltGrModifier(bool a) { m_detectAltGrModifier = a; }
+ bool detectAltGrModifier() const { return m_detectAltGrModifier; }
+
bool translateKeyEvent(QWindow *widget, HWND hwnd, const MSG &msg, LRESULT *result);
QWindow *keyGrabber() const { return m_keyGrabber; }
@@ -90,7 +93,7 @@ public:
QList<int> possibleKeys(const QKeyEvent *e) const;
private:
- bool translateKeyEventInternal(QWindow *receiver, const MSG &msg, bool grab, LRESULT *lResult);
+ bool translateKeyEventInternal(QWindow *receiver, MSG msg, bool grab, LRESULT *lResult);
bool translateMultimediaKeyEventInternal(QWindow *receiver, const MSG &msg);
void updateKeyMap(const MSG &msg);
@@ -106,6 +109,9 @@ private:
QChar m_lastHighSurrogate;
static const size_t NumKeyboardLayoutItems = 256;
KeyboardLayoutItem keyLayout[NumKeyboardLayoutItems];
+ bool m_detectAltGrModifier = false;
+ bool m_seenAltGr = false;
+
};
enum WindowsNativeModifiers {
diff --git a/src/plugins/platforms/windows/qwindowsmenu.h b/src/plugins/platforms/windows/qwindowsmenu.h
index d51a29676e..6de1553f35 100644
--- a/src/plugins/platforms/windows/qwindowsmenu.h
+++ b/src/plugins/platforms/windows/qwindowsmenu.h
@@ -44,8 +44,8 @@
#include <qpa/qplatformmenu.h>
-#include <QtCore/QVector>
-#include <QtCore/QPair>
+#include <QtCore/qvector.h>
+#include <QtCore/qpair.h>
QT_BEGIN_NAMESPACE
@@ -60,7 +60,7 @@ class QWindowsMenuItem : public QPlatformMenuItem
Q_OBJECT
public:
explicit QWindowsMenuItem(QWindowsMenu *parentMenu = nullptr);
- ~QWindowsMenuItem();
+ ~QWindowsMenuItem() override;
void setText(const QString &text) override;
void setIcon(const QIcon &icon) override;
@@ -199,7 +199,7 @@ public:
typedef QVector<QWindowsMenu *> Menus;
QWindowsMenuBar();
- ~QWindowsMenuBar();
+ ~QWindowsMenuBar() override;
void insertMenu(QPlatformMenu *menu, QPlatformMenu *before) override;
void removeMenu(QPlatformMenu *menu) override;
diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp
index 0439797a7d..ff0dccb0d9 100644
--- a/src/plugins/platforms/windows/qwindowsmime.cpp
+++ b/src/plugins/platforms/windows/qwindowsmime.cpp
@@ -41,15 +41,15 @@
#include "qwindowscontext.h"
#include <QtGui/private/qinternalmimedata_p.h>
-#include <QtCore/QByteArrayMatcher>
-#include <QtCore/QTextCodec>
-#include <QtCore/QMap>
-#include <QtCore/QUrl>
-#include <QtCore/QDir>
-#include <QtCore/QDebug>
-#include <QtCore/QBuffer>
-#include <QtGui/QImageReader>
-#include <QtGui/QImageWriter>
+#include <QtCore/qbytearraymatcher.h>
+#include <QtCore/qtextcodec.h>
+#include <QtCore/qmap.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qbuffer.h>
+#include <QtGui/qimagereader.h>
+#include <QtGui/qimagewriter.h>
#include <shlobj.h>
#include <algorithm>
@@ -107,7 +107,8 @@ static inline QByteArray msgConversionError(const char *func, const char *format
msg += ": Unable to convert DIB image. The image converter plugin for '";
msg += format;
msg += "' is not available. Available formats: ";
- foreach (const QByteArray &af, QImageReader::supportedImageFormats()) {
+ const QList<QByteArray> &formats = QImageReader::supportedImageFormats();
+ for (const QByteArray &af : formats) {
msg += af;
msg += ' ';
}
@@ -487,17 +488,13 @@ QDebug operator<<(QDebug d, IDataObject *dataObj)
Constructs a new conversion object, adding it to the globally accessed
list of available converters.
*/
-QWindowsMime::QWindowsMime()
-{
-}
+QWindowsMime::QWindowsMime() = default;
/*!
Destroys a conversion object, removing it from the global
list of available converters.
*/
-QWindowsMime::~QWindowsMime()
-{
-}
+QWindowsMime::~QWindowsMime() = default;
/*!
Registers the MIME type \a mime, and returns an ID number
@@ -573,12 +570,12 @@ int QWindowsMime::registerMimeType(const QString &mime)
class QWindowsMimeText : public QWindowsMime
{
public:
- bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const;
- QVariant convertToMime(const QString &mime, LPDATAOBJECT pDataObj, QVariant::Type preferredType) const;
- QString mimeForFormat(const FORMATETC &formatetc) const;
- bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const;
- bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM *pmedium) const;
- QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const;
+ bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const override;
+ QVariant convertToMime(const QString &mime, LPDATAOBJECT pDataObj, QVariant::Type preferredType) const override;
+ QString mimeForFormat(const FORMATETC &formatetc) const override;
+ bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const override;
+ bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM *pmedium) const override;
+ QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const override;
};
bool QWindowsMimeText::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const
@@ -627,7 +624,8 @@ bool QWindowsMimeText::convertFromMime(const FORMATETC &formatetc, const QMimeDa
}
o[j]=0;
return setData(r, pmedium);
- } else if (cf == CF_UNICODETEXT) {
+ }
+ if (cf == CF_UNICODETEXT) {
QString str = mimeData->text();
const QChar *u = str.unicode();
QString res;
@@ -729,12 +727,12 @@ class QWindowsMimeURI : public QWindowsMime
{
public:
QWindowsMimeURI();
- bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const;
- QVariant convertToMime(const QString &mime, LPDATAOBJECT pDataObj, QVariant::Type preferredType) const;
- QString mimeForFormat(const FORMATETC &formatetc) const;
- bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const;
- bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM *pmedium) const;
- QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const;
+ bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const override;
+ QVariant convertToMime(const QString &mime, LPDATAOBJECT pDataObj, QVariant::Type preferredType) const override;
+ QString mimeForFormat(const FORMATETC &formatetc) const override;
+ bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const override;
+ bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM *pmedium) const override;
+ QVector<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const override;
private:
int CF_INETURL_W; // wide char version
int CF_INETURL;
@@ -749,9 +747,9 @@ QWindowsMimeURI::QWindowsMimeURI()
bool QWindowsMimeURI::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const
{
if (mimeData->hasUrls() && getCf(formatetc) == CF_HDROP) {
- QList<QUrl> urls = mimeData->urls();
- for (int i=0; i<urls.size(); i++) {
- if (!urls.at(i).toLocalFile().isEmpty())
+ const QList<QUrl> urls = mimeData->urls();
+ for (const QUrl &url : urls) {
+ if (url.isLocalFile())
return true;
}
}
@@ -762,11 +760,11 @@ bool QWindowsMimeURI::convertFromMime(const FORMATETC &formatetc, const QMimeDat
{
if (canConvertFromMime(formatetc, mimeData)) {
if (getCf(formatetc) == CF_HDROP) {
- QList<QUrl> urls = mimeData->urls();
+ const QList<QUrl> &urls = mimeData->urls();
QStringList fileNames;
int size = sizeof(DROPFILES)+2;
- for (int i=0; i<urls.size(); i++) {
- QString fn = QDir::toNativeSeparators(urls.at(i).toLocalFile());
+ for (const QUrl &url : urls) {
+ const QString fn = QDir::toNativeSeparators(url.toLocalFile());
if (!fn.isEmpty()) {
size += sizeof(ushort) * size_t(fn.length() + 1);
fileNames.append(fn);
@@ -791,7 +789,8 @@ bool QWindowsMimeURI::convertFromMime(const FORMATETC &formatetc, const QMimeDat
*f = 0;
return setData(result, pmedium);
- } else if (getCf(formatetc) == CF_INETURL_W) {
+ }
+ if (getCf(formatetc) == CF_INETURL_W) {
QList<QUrl> urls = mimeData->urls();
QByteArray result;
if (!urls.isEmpty()) {
@@ -802,7 +801,8 @@ bool QWindowsMimeURI::convertFromMime(const FORMATETC &formatetc, const QMimeDat
result.append('\0');
result.append('\0');
return setData(result, pmedium);
- } else if (getCf(formatetc) == CF_INETURL) {
+ }
+ if (getCf(formatetc) == CF_INETURL) {
QList<QUrl> urls = mimeData->urls();
QByteArray result;
if (!urls.isEmpty())
@@ -872,7 +872,7 @@ QVariant QWindowsMimeURI::convertToMime(const QString &mimeType, LPDATAOBJECT pD
if (preferredType == QVariant::Url && urls.size() == 1)
return urls.at(0);
- else if (!urls.isEmpty())
+ if (!urls.isEmpty())
return urls;
} else if (canGetData(CF_INETURL_W, pDataObj)) {
QByteArray data = getData(CF_INETURL_W, pDataObj);
@@ -1075,10 +1075,8 @@ QString QWindowsMimeImage::mimeForFormat(const FORMATETC &formatetc) const
bool QWindowsMimeImage::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const
{
- if (mimeType == QLatin1String("application/x-qt-image") &&
- (canGetData(CF_DIB, pDataObj) || canGetData(CF_PNG, pDataObj)))
- return true;
- return false;
+ return mimeType == QLatin1String("application/x-qt-image")
+ && (canGetData(CF_DIB, pDataObj) || canGetData(CF_PNG, pDataObj));
}
bool QWindowsMimeImage::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const
@@ -1134,7 +1132,7 @@ bool QWindowsMimeImage::hasOriginalDIBV5(IDataObject *pDataObj) const
CoTaskMemFree(fc.ptd);
if (fc.cfFormat == CF_DIB)
break;
- else if (fc.cfFormat == CF_DIBV5) {
+ if (fc.cfFormat == CF_DIBV5) {
isSynthesized = false;
break;
}
@@ -1328,7 +1326,7 @@ QStringList QLastResortMimes::excludeList;
QLastResortMimes::QLastResortMimes()
{
//MIME Media-Types
- if (!ianaTypes.size()) {
+ if (ianaTypes.isEmpty()) {
ianaTypes.append(QStringLiteral("application/"));
ianaTypes.append(QStringLiteral("audio/"));
ianaTypes.append(QStringLiteral("example/"));
@@ -1340,7 +1338,7 @@ QLastResortMimes::QLastResortMimes()
ianaTypes.append(QStringLiteral("video/"));
}
//Types handled by other classes
- if (!excludeList.size()) {
+ if (excludeList.isEmpty()) {
excludeList.append(QStringLiteral("HTML Format"));
excludeList.append(QStringLiteral("UniformResourceLocator"));
excludeList.append(QStringLiteral("text/html"));
@@ -1598,7 +1596,7 @@ QVariant QWindowsMimeConverter::convertToMime(const QStringList &mimeTypes,
QVariant::Type preferredType,
QString *formatIn /* = 0 */) const
{
- foreach (const QString &format, mimeTypes) {
+ for (const QString &format : mimeTypes) {
if (const QWindowsMime *converter = converterToMime(format, pDataObj)) {
if (converter->canConvertToMime(format, pDataObj)) {
const QVariant dataV = converter->convertToMime(format, pDataObj, preferredType);
diff --git a/src/plugins/platforms/windows/qwindowsmime.h b/src/plugins/platforms/windows/qwindowsmime.h
index 1ed2aa933f..6bbbae1a0e 100644
--- a/src/plugins/platforms/windows/qwindowsmime.h
+++ b/src/plugins/platforms/windows/qwindowsmime.h
@@ -42,9 +42,9 @@
#include <QtCore/qt_windows.h>
-#include <QtCore/QVector>
-#include <QtCore/QList>
-#include <QtCore/QVariant>
+#include <QtCore/qvector.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qvariant.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
index 17851618b4..fcdd179a31 100644
--- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp
+++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
@@ -45,14 +45,14 @@
#include "qwindowsscreen.h"
#include <qpa/qwindowsysteminterface.h>
-#include <QtGui/QGuiApplication>
-#include <QtGui/QScreen>
-#include <QtGui/QTouchDevice>
-#include <QtGui/QWindow>
-#include <QtGui/QCursor>
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qscreen.h>
+#include <QtGui/qtouchdevice.h>
+#include <QtGui/qwindow.h>
+#include <QtGui/qcursor.h>
-#include <QtCore/QDebug>
-#include <QtCore/QScopedArrayPointer>
+#include <QtCore/qdebug.h>
+#include <QtCore/qscopedpointer.h>
#include <windowsx.h>
@@ -119,20 +119,16 @@ static inline void compressMouseMove(MSG *msg)
static inline QTouchDevice *createTouchDevice()
{
- enum { QT_SM_TABLETPC = 86, QT_SM_DIGITIZER = 94, QT_SM_MAXIMUMTOUCHES = 95,
- QT_NID_INTEGRATED_TOUCH = 0x1, QT_NID_EXTERNAL_TOUCH = 0x02,
- QT_NID_MULTI_INPUT = 0x40, QT_NID_READY = 0x80 };
-
- const int digitizers = GetSystemMetrics(QT_SM_DIGITIZER);
- if (!(digitizers & (QT_NID_INTEGRATED_TOUCH | QT_NID_EXTERNAL_TOUCH)))
+ const int digitizers = GetSystemMetrics(SM_DIGITIZER);
+ if (!(digitizers & (NID_INTEGRATED_TOUCH | NID_EXTERNAL_TOUCH)))
return 0;
- const int tabletPc = GetSystemMetrics(QT_SM_TABLETPC);
- const int maxTouchPoints = GetSystemMetrics(QT_SM_MAXIMUMTOUCHES);
- qCDebug(lcQpaEvents) << "Digitizers:" << hex << showbase << (digitizers & ~QT_NID_READY)
- << "Ready:" << (digitizers & QT_NID_READY) << dec << noshowbase
+ const int tabletPc = GetSystemMetrics(SM_TABLETPC);
+ const int maxTouchPoints = GetSystemMetrics(SM_MAXIMUMTOUCHES);
+ qCDebug(lcQpaEvents) << "Digitizers:" << hex << showbase << (digitizers & ~NID_READY)
+ << "Ready:" << (digitizers & NID_READY) << dec << noshowbase
<< "Tablet PC:" << tabletPc << "Max touch points:" << maxTouchPoints;
QTouchDevice *result = new QTouchDevice;
- result->setType(digitizers & QT_NID_INTEGRATED_TOUCH
+ result->setType(digitizers & NID_INTEGRATED_TOUCH
? QTouchDevice::TouchScreen : QTouchDevice::TouchPad);
QTouchDevice::Capabilities capabilities = QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::NormalizedPosition;
if (result->type() == QTouchDevice::TouchPad)
@@ -178,22 +174,121 @@ Qt::MouseButtons QWindowsMouseHandler::queryMouseButtons()
return result;
}
+static QPoint lastMouseMovePos;
+
+namespace {
+struct MouseEvent {
+ QEvent::Type type;
+ Qt::MouseButton button;
+};
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const MouseEvent &e)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d << "MouseEvent(" << e.type << ", " << e.button << ')';
+ return d;
+}
+#endif // QT_NO_DEBUG_STREAM
+} // namespace
+
+static inline Qt::MouseButton extraButton(WPARAM wParam) // for WM_XBUTTON...
+{
+ return GET_XBUTTON_WPARAM(wParam) == XBUTTON1 ? Qt::BackButton : Qt::ForwardButton;
+}
+
+static inline MouseEvent eventFromMsg(const MSG &msg)
+{
+ switch (msg.message) {
+ case WM_MOUSEMOVE:
+ return {QEvent::MouseMove, Qt::NoButton};
+ case WM_LBUTTONDOWN:
+ return {QEvent::MouseButtonPress, Qt::LeftButton};
+ case WM_LBUTTONUP:
+ return {QEvent::MouseButtonRelease, Qt::LeftButton};
+ case WM_LBUTTONDBLCLK: // Qt QPA does not handle double clicks, send as press
+ return {QEvent::MouseButtonPress, Qt::LeftButton};
+ case WM_MBUTTONDOWN:
+ return {QEvent::MouseButtonPress, Qt::MidButton};
+ case WM_MBUTTONUP:
+ return {QEvent::MouseButtonRelease, Qt::MidButton};
+ case WM_MBUTTONDBLCLK:
+ return {QEvent::MouseButtonPress, Qt::MidButton};
+ case WM_RBUTTONDOWN:
+ return {QEvent::MouseButtonPress, Qt::RightButton};
+ case WM_RBUTTONUP:
+ return {QEvent::MouseButtonRelease, Qt::RightButton};
+ case WM_RBUTTONDBLCLK:
+ return {QEvent::MouseButtonPress, Qt::RightButton};
+ case WM_XBUTTONDOWN:
+ return {QEvent::MouseButtonPress, extraButton(msg.wParam)};
+ case WM_XBUTTONUP:
+ return {QEvent::MouseButtonRelease, extraButton(msg.wParam)};
+ case WM_XBUTTONDBLCLK:
+ return {QEvent::MouseButtonPress, extraButton(msg.wParam)};
+ case WM_NCMOUSEMOVE:
+ return {QEvent::NonClientAreaMouseMove, Qt::NoButton};
+ case WM_NCLBUTTONDOWN:
+ return {QEvent::NonClientAreaMouseButtonPress, Qt::LeftButton};
+ case WM_NCLBUTTONUP:
+ return {QEvent::NonClientAreaMouseButtonRelease, Qt::LeftButton};
+ case WM_NCLBUTTONDBLCLK:
+ return {QEvent::NonClientAreaMouseButtonPress, Qt::LeftButton};
+ case WM_NCMBUTTONDOWN:
+ return {QEvent::NonClientAreaMouseButtonPress, Qt::MidButton};
+ case WM_NCMBUTTONUP:
+ return {QEvent::NonClientAreaMouseButtonRelease, Qt::MidButton};
+ case WM_NCMBUTTONDBLCLK:
+ return {QEvent::NonClientAreaMouseButtonPress, Qt::MidButton};
+ case WM_NCRBUTTONDOWN:
+ return {QEvent::NonClientAreaMouseButtonPress, Qt::RightButton};
+ case WM_NCRBUTTONUP:
+ return {QEvent::NonClientAreaMouseButtonRelease, Qt::RightButton};
+ case WM_NCRBUTTONDBLCLK:
+ return {QEvent::NonClientAreaMouseButtonPress, Qt::RightButton};
+ default: // WM_MOUSELEAVE
+ break;
+ }
+ return {QEvent::None, Qt::NoButton};
+}
+
bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
QtWindows::WindowsEventType et,
MSG msg, LRESULT *result)
{
-#ifdef Q_COMPILER_CLASS_ENUM
enum : quint64 { signatureMask = 0xffffff00, miWpSignature = 0xff515700 };
-#else
- static const quint64 signatureMask = 0xffffff00;
- static const quint64 miWpSignature = 0xff515700;
-#endif // !Q_COMPILER_CLASS_ENUM
if (et == QtWindows::MouseWheelEvent)
return translateMouseWheelEvent(window, hwnd, msg, result);
+ const QPoint winEventPosition(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
+ QPoint clientPosition;
+ QPoint globalPosition;
+ if (et & QtWindows::NonClientEventFlag) {
+ globalPosition = winEventPosition;
+ clientPosition = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPosition);
+ } else {
+ clientPosition = winEventPosition;
+ globalPosition = QWindowsGeometryHint::mapToGlobal(hwnd, winEventPosition);
+ }
+
+ // Windows sends a mouse move with no buttons pressed to signal "Enter"
+ // when a window is shown over the cursor. Discard the event and only use
+ // it for generating QEvent::Enter to be consistent with other platforms -
+ // X11 and macOS.
+ bool discardEvent = false;
+ if (msg.message == WM_MOUSEMOVE) {
+ const bool samePosition = globalPosition == lastMouseMovePos;
+ lastMouseMovePos = globalPosition;
+ if (msg.wParam == 0 && (m_windowUnderMouse.isNull() || samePosition))
+ discardEvent = true;
+ }
+
Qt::MouseEventSource source = Qt::MouseEventNotSynthesized;
+ const MouseEvent mouseEvent = eventFromMsg(msg);
+
// Check for events synthesized from touch. Lower byte is touch index, 0 means pen.
static const bool passSynthesizedMouseEvents =
!(QWindowsIntegration::instance()->options() & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch);
@@ -210,13 +305,11 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
}
}
- const QPoint winEventPosition(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
- if (et & QtWindows::NonClientEventFlag) {
- const QPoint globalPosition = winEventPosition;
- const QPoint clientPosition = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPosition);
+ if (mouseEvent.type >= QEvent::NonClientAreaMouseMove && mouseEvent.type <= QEvent::NonClientAreaMouseButtonDblClick) {
const Qt::MouseButtons buttons = QWindowsMouseHandler::queryMouseButtons();
QWindowSystemInterface::handleFrameStrutMouseEvent(window, clientPosition,
globalPosition, buttons,
+ mouseEvent.button, mouseEvent.type,
QWindowsKeyMapper::queryKeyboardModifiers(),
source);
return false; // Allow further event processing (dragging of windows).
@@ -224,7 +317,8 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
*result = 0;
if (msg.message == WM_MOUSELEAVE) {
- qCDebug(lcQpaEvents) << "WM_MOUSELEAVE for " << window << " previous window under mouse = " << m_windowUnderMouse << " tracked window =" << m_trackedWindow;
+ qCDebug(lcQpaEvents) << mouseEvent << "for" << window << "previous window under mouse="
+ << m_windowUnderMouse << "tracked window=" << m_trackedWindow;
// When moving out of a window, WM_MOUSEMOVE within the moved-to window is received first,
// so if m_trackedWindow is not the window here, it means the cursor has left the
@@ -264,12 +358,11 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
}
m_previousCaptureWindow = window;
return true;
- } else if (m_leftButtonDown && !actualLeftDown) {
- m_leftButtonDown = false;
}
+ if (m_leftButtonDown && !actualLeftDown)
+ m_leftButtonDown = false;
}
- const QPoint globalPosition = QWindowsGeometryHint::mapToGlobal(hwnd, winEventPosition);
// In this context, neither an invisible nor a transparent window (transparent regarding mouse
// events, "click-through") can be considered as the window under mouse.
QWindow *currentWindowUnderMouse = platformWindow->hasMouseCapture() ?
@@ -290,10 +383,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
// Qt expects the platform plugin to capture the mouse on
// any button press until release.
if (!platformWindow->hasMouseCapture()
- && (msg.message == WM_LBUTTONDOWN || msg.message == WM_MBUTTONDOWN
- || msg.message == WM_RBUTTONDOWN || msg.message == WM_XBUTTONDOWN
- || msg.message == WM_LBUTTONDBLCLK || msg.message == WM_MBUTTONDBLCLK
- || msg.message == WM_RBUTTONDBLCLK || msg.message == WM_XBUTTONDBLCLK)) {
+ && (mouseEvent.type == QEvent::MouseButtonPress || mouseEvent.type == QEvent::MouseButtonDblClick)) {
platformWindow->setMouseGrabEnabled(true);
platformWindow->setFlag(QWindowsWindow::AutoMouseCapture);
qCDebug(lcQpaEvents) << "Automatic mouse capture " << window;
@@ -302,8 +392,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
window->requestActivate();
} else if (platformWindow->hasMouseCapture()
&& platformWindow->testFlag(QWindowsWindow::AutoMouseCapture)
- && (msg.message == WM_LBUTTONUP || msg.message == WM_MBUTTONUP
- || msg.message == WM_RBUTTONUP || msg.message == WM_XBUTTONUP)
+ && mouseEvent.type == QEvent::MouseButtonRelease
&& !buttons) {
platformWindow->setMouseGrabEnabled(false);
qCDebug(lcQpaEvents) << "Releasing automatic mouse capture " << window;
@@ -369,9 +458,12 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
m_windowUnderMouse = currentWindowUnderMouse;
}
- QWindowSystemInterface::handleMouseEvent(window, winEventPosition, globalPosition, buttons,
- QWindowsKeyMapper::queryKeyboardModifiers(),
- source);
+ if (!discardEvent && mouseEvent.type != QEvent::None) {
+ QWindowSystemInterface::handleMouseEvent(window, winEventPosition, globalPosition, buttons,
+ mouseEvent.button, mouseEvent.type,
+ QWindowsKeyMapper::queryKeyboardModifiers(),
+ source);
+ }
m_previousCaptureWindow = hasCapture ? window : 0;
// QTBUG-48117, force synchronous handling for the extra buttons so that WM_APPCOMMAND
// is sent for unhandled WM_XBUTTONDOWN.
@@ -411,9 +503,10 @@ static void redirectWheelEvent(QWindow *window, const QPoint &globalPos, int del
}
if (handleEvent) {
+ const QPoint point = (orientation == Qt::Vertical) ? QPoint(0, delta) : QPoint(delta, 0);
QWindowSystemInterface::handleWheelEvent(receiver,
QWindowsGeometryHint::mapFromGlobal(receiver, globalPos),
- globalPos, delta, orientation, mods);
+ globalPos, QPoint(), point, mods);
}
}
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.h b/src/plugins/platforms/windows/qwindowsmousehandler.h
index 86f18a0482..480662c9bf 100644
--- a/src/plugins/platforms/windows/qwindowsmousehandler.h
+++ b/src/plugins/platforms/windows/qwindowsmousehandler.h
@@ -43,8 +43,8 @@
#include "qtwindowsglobal.h"
#include <QtCore/qt_windows.h>
-#include <QtCore/QPointer>
-#include <QtCore/QHash>
+#include <QtCore/qpointer.h>
+#include <QtCore/qhash.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
index ffa100f824..de11356fd4 100644
--- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
+++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
@@ -48,9 +48,9 @@
#include "qwindowsmime.h"
#include "qwin10helpers.h"
-#include <QtGui/QWindow>
-#include <QtGui/QOpenGLContext>
-#include <QtGui/QScreen>
+#include <QtGui/qwindow.h>
+#include <QtGui/qopenglcontext.h>
+#include <QtGui/qscreen.h>
#include <qpa/qplatformscreen.h>
#include <QtFontDatabaseSupport/private/qwindowsfontdatabase_p.h>
@@ -111,15 +111,14 @@ void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resourc
return 0;
}
break;
- case QWindow::OpenGLSurface:
- case QWindow::OpenVGSurface:
- break;
case QWindow::VulkanSurface:
#if QT_CONFIG(vulkan)
if (type == VkSurface)
return bw->surface(nullptr, nullptr); // returns the address of the VkSurfaceKHR, not the value, as expected
#endif
break;
+ default:
+ break;
}
qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
return 0;
@@ -276,11 +275,11 @@ QFunctionPointer QWindowsNativeInterface::platformFunction(const QByteArray &fun
{
if (function == QWindowsWindowFunctions::setTouchWindowTouchTypeIdentifier())
return QFunctionPointer(QWindowsWindow::setTouchWindowTouchTypeStatic);
- else if (function == QWindowsWindowFunctions::setHasBorderInFullScreenIdentifier())
+ if (function == QWindowsWindowFunctions::setHasBorderInFullScreenIdentifier())
return QFunctionPointer(QWindowsWindow::setHasBorderInFullScreenStatic);
- else if (function == QWindowsWindowFunctions::setWindowActivationBehaviorIdentifier())
+ if (function == QWindowsWindowFunctions::setWindowActivationBehaviorIdentifier())
return QFunctionPointer(QWindowsNativeInterface::setWindowActivationBehavior);
- else if (function == QWindowsWindowFunctions::isTabletModeIdentifier())
+ if (function == QWindowsWindowFunctions::isTabletModeIdentifier())
return QFunctionPointer(QWindowsNativeInterface::isTabletMode);
return nullptr;
}
diff --git a/src/plugins/platforms/windows/qwindowsole.cpp b/src/plugins/platforms/windows/qwindowsole.cpp
index 0ceb0d82fa..ad0442c8bd 100644
--- a/src/plugins/platforms/windows/qwindowsole.cpp
+++ b/src/plugins/platforms/windows/qwindowsole.cpp
@@ -41,14 +41,14 @@
#include "qwindowsmime.h"
#include "qwindowscontext.h"
\
-#include <QtGui/QMouseEvent>
-#include <QtGui/QWindow>
-#include <QtGui/QPainter>
-#include <QtGui/QCursor>
-#include <QtGui/QGuiApplication>
+#include <QtGui/qevent.h>
+#include <QtGui/qwindow.h>
+#include <QtGui/qpainter.h>
+#include <QtGui/qcursor.h>
+#include <QtGui/qguiapplication.h>
-#include <QtCore/QMimeData>
-#include <QtCore/QDebug>
+#include <QtCore/qmimedata.h>
+#include <QtCore/qdebug.h>
#include <shlobj.h>
@@ -80,9 +80,7 @@ QWindowsOleDataObject::QWindowsOleDataObject(QMimeData *mimeData) :
qCDebug(lcQpaMime) << __FUNCTION__ << mimeData->formats();
}
-QWindowsOleDataObject::~QWindowsOleDataObject()
-{
-}
+QWindowsOleDataObject::~QWindowsOleDataObject() = default;
void QWindowsOleDataObject::releaseQt()
{
@@ -365,10 +363,9 @@ QWindowsOleEnumFmtEtc::Clone(LPENUMFORMATETC FAR* newEnum)
if (result->isNull()) {
delete result;
return ResultFromScode(E_OUTOFMEMORY);
- } else {
- *newEnum = result;
}
+ *newEnum = result;
return NOERROR;
}
diff --git a/src/plugins/platforms/windows/qwindowsole.h b/src/plugins/platforms/windows/qwindowsole.h
index fc58858f2c..6940657e88 100644
--- a/src/plugins/platforms/windows/qwindowsole.h
+++ b/src/plugins/platforms/windows/qwindowsole.h
@@ -43,9 +43,9 @@
#include "qwindowscombase.h"
#include <QtCore/qt_windows.h>
-#include <QtCore/QMap>
-#include <QtCore/QPointer>
-#include <QtCore/QVector>
+#include <QtCore/qmap.h>
+#include <QtCore/qpointer.h>
+#include <QtCore/qvector.h>
#include <objidl.h>
@@ -58,7 +58,7 @@ class QWindowsOleDataObject : public QWindowsComBase<IDataObject>
{
public:
explicit QWindowsOleDataObject(QMimeData *mimeData);
- virtual ~QWindowsOleDataObject();
+ ~QWindowsOleDataObject() override;
void releaseQt();
QMimeData *mimeData() const;
@@ -88,7 +88,7 @@ class QWindowsOleEnumFmtEtc : public QWindowsComBase<IEnumFORMATETC>
public:
explicit QWindowsOleEnumFmtEtc(const QVector<FORMATETC> &fmtetcs);
explicit QWindowsOleEnumFmtEtc(const QVector<LPFORMATETC> &lpfmtetcs);
- virtual ~QWindowsOleEnumFmtEtc();
+ ~QWindowsOleEnumFmtEtc() override;
bool isNull() const;
diff --git a/src/plugins/platforms/windows/qwindowsopenglcontext.h b/src/plugins/platforms/windows/qwindowsopenglcontext.h
index 85f4f717f5..cc6d93d35e 100644
--- a/src/plugins/platforms/windows/qwindowsopenglcontext.h
+++ b/src/plugins/platforms/windows/qwindowsopenglcontext.h
@@ -40,7 +40,7 @@
#ifndef QWINDOWSOPENGLCONTEXT_H
#define QWINDOWSOPENGLCONTEXT_H
-#include <QtGui/QOpenGLContext>
+#include <QtGui/qopenglcontext.h>
#include <qpa/qplatformopenglcontext.h>
QT_BEGIN_NAMESPACE
@@ -51,9 +51,10 @@ class QWindowsOpenGLContext;
class QWindowsStaticOpenGLContext
{
+ Q_DISABLE_COPY(QWindowsStaticOpenGLContext)
public:
static QWindowsStaticOpenGLContext *create();
- virtual ~QWindowsStaticOpenGLContext() { }
+ virtual ~QWindowsStaticOpenGLContext() = default;
virtual QWindowsOpenGLContext *createContext(QOpenGLContext *context) = 0;
virtual void *moduleHandle() const = 0;
@@ -65,15 +66,17 @@ public:
virtual void *createWindowSurface(void * /*nativeWindow*/, void * /*nativeConfig*/, int * /*err*/) { return 0; }
virtual void destroyWindowSurface(void * /*nativeSurface*/) { }
+protected:
+ QWindowsStaticOpenGLContext() = default;
+
private:
static QWindowsStaticOpenGLContext *doCreate();
};
class QWindowsOpenGLContext : public QPlatformOpenGLContext
{
+ Q_DISABLE_COPY(QWindowsOpenGLContext)
public:
- virtual ~QWindowsOpenGLContext() { }
-
// Returns the native context handle (e.g. HGLRC for WGL, EGLContext for EGL).
virtual void *nativeContext() const = 0;
@@ -81,6 +84,9 @@ public:
// For others, like WGL, they are not relevant.
virtual void *nativeDisplay() const { return 0; }
virtual void *nativeConfig() const { return 0; }
+
+protected:
+ QWindowsOpenGLContext() = default;
};
#endif // QT_NO_OPENGL
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp
index c52e4e612e..3efccf0f32 100644
--- a/src/plugins/platforms/windows/qwindowsopengltester.cpp
+++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp
@@ -40,15 +40,15 @@
#include "qwindowsopengltester.h"
#include "qwindowscontext.h"
-#include <QtCore/QVariantMap>
-#include <QtCore/QDebug>
-#include <QtCore/QTextStream>
-#include <QtCore/QCoreApplication>
-#include <QtCore/QFile>
-#include <QtCore/QFileInfo>
-#include <QtCore/QStandardPaths>
-#include <QtCore/QLibraryInfo>
-#include <QtCore/QHash>
+#include <QtCore/qvariant.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qtextstream.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qstandardpaths.h>
+#include <QtCore/qlibraryinfo.h>
+#include <QtCore/qhash.h>
#ifndef QT_NO_OPENGL
#include <private/qopengl_p.h>
@@ -60,6 +60,8 @@
QT_BEGIN_NAMESPACE
+static const DWORD VENDOR_ID_AMD = 0x1002;
+
GpuDescription GpuDescription::detect()
{
typedef IDirect3D9 * (WINAPI *PtrDirect3DCreate9)(UINT);
@@ -74,9 +76,16 @@ GpuDescription GpuDescription::detect()
IDirect3D9 *direct3D9 = direct3DCreate9(D3D_SDK_VERSION);
if (!direct3D9)
return result;
+
D3DADAPTER_IDENTIFIER9 adapterIdentifier;
- const HRESULT hr = direct3D9->GetAdapterIdentifier(0, 0, &adapterIdentifier);
- direct3D9->Release();
+ bool isAMD = false;
+ // Adapter "0" is D3DADAPTER_DEFAULT which returns the default adapter. In
+ // multi-GPU, multi-screen setups this is the GPU that is associated with
+ // the "main display" in the Display Settings, and this is the GPU OpenGL
+ // and D3D uses by default. Therefore querying any additional adapters is
+ // futile and not useful for our purposes in general, except for
+ // identifying a few special cases later on.
+ HRESULT hr = direct3D9->GetAdapterIdentifier(0, 0, &adapterIdentifier);
if (SUCCEEDED(hr)) {
result.vendorId = adapterIdentifier.VendorId;
result.deviceId = adapterIdentifier.DeviceId;
@@ -90,7 +99,37 @@ GpuDescription GpuDescription::detect()
result.driverVersion = QVersionNumber(version);
result.driverName = adapterIdentifier.Driver;
result.description = adapterIdentifier.Description;
+ isAMD = result.vendorId == VENDOR_ID_AMD;
+ }
+
+ // Detect QTBUG-50371 (having AMD as the default adapter results in a crash
+ // when starting apps on a screen connected to the Intel card) by looking
+ // for a default AMD adapter and an additional non-AMD one.
+ if (isAMD) {
+ const UINT adapterCount = direct3D9->GetAdapterCount();
+ for (UINT adp = 1; adp < adapterCount; ++adp) {
+ hr = direct3D9->GetAdapterIdentifier(adp, 0, &adapterIdentifier);
+ if (SUCCEEDED(hr)) {
+ if (adapterIdentifier.VendorId != VENDOR_ID_AMD) {
+ // Bingo. Now figure out the display for the AMD card.
+ DISPLAY_DEVICE dd;
+ memset(&dd, 0, sizeof(dd));
+ dd.cb = sizeof(dd);
+ for (int dev = 0; EnumDisplayDevices(nullptr, dev, &dd, 0); ++dev) {
+ if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
+ // DeviceName is something like \\.\DISPLAY1 which can be used to
+ // match with the MONITORINFOEX::szDevice queried by QWindowsScreen.
+ result.gpuSuitableScreen = QString::fromWCharArray(dd.DeviceName);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
}
+
+ direct3D9->Release();
return result;
}
@@ -103,7 +142,8 @@ QDebug operator<<(QDebug d, const GpuDescription &gd)
<< ", deviceId=" << gd.deviceId << ", subSysId=" << gd.subSysId
<< dec << noshowbase << ", revision=" << gd.revision
<< ", driver: " << gd.driverName
- << ", version=" << gd.driverVersion << ", " << gd.description << ')';
+ << ", version=" << gd.driverVersion << ", " << gd.description
+ << gd.gpuSuitableScreen << ')';
return d;
}
#endif // !QT_NO_DEBUG_STREAM
@@ -113,15 +153,17 @@ QString GpuDescription::toString() const
{
QString result;
QTextStream str(&result);
- str << " Card name: " << description
- << "\n Driver Name: " << driverName
- << "\n Driver Version: " << driverVersion.toString()
- << "\n Vendor ID: 0x" << qSetPadChar(QLatin1Char('0'))
+ str << " Card name : " << description
+ << "\n Driver Name : " << driverName
+ << "\n Driver Version : " << driverVersion.toString()
+ << "\n Vendor ID : 0x" << qSetPadChar(QLatin1Char('0'))
<< uppercasedigits << hex << qSetFieldWidth(4) << vendorId
- << "\n Device ID: 0x" << qSetFieldWidth(4) << deviceId
- << "\n SubSys ID: 0x" << qSetFieldWidth(8) << subSysId
- << "\n Revision ID: 0x" << qSetFieldWidth(4) << revision
+ << "\n Device ID : 0x" << qSetFieldWidth(4) << deviceId
+ << "\n SubSys ID : 0x" << qSetFieldWidth(8) << subSysId
+ << "\n Revision ID : 0x" << qSetFieldWidth(4) << revision
<< dec;
+ if (!gpuSuitableScreen.isEmpty())
+ str << "\nGL windows forced to screen: " << gpuSuitableScreen;
return result;
}
@@ -205,11 +247,12 @@ typedef QHash<QOpenGLConfig::Gpu, QWindowsOpenGLTester::Renderers> SupportedRend
Q_GLOBAL_STATIC(SupportedRenderersCache, supportedRenderersCache)
#endif
-QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(const GpuDescription &gpu, bool glesOnly)
+QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(const GpuDescription &gpu,
+ Renderer requested)
{
- Q_UNUSED(gpu)
- Q_UNUSED(glesOnly)
#if defined(QT_NO_OPENGL)
+ Q_UNUSED(gpu)
+ Q_UNUSED(requested)
return 0;
#else
QOpenGLConfig::Gpu qgpu = QOpenGLConfig::Gpu::fromDevice(gpu.vendorId, gpu.deviceId, gpu.driverVersion, gpu.description);
@@ -223,8 +266,11 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(c
| QWindowsOpenGLTester::AngleRendererD3d11Warp
| QWindowsOpenGLTester::SoftwareRasterizer);
- if (!glesOnly && testDesktopGL())
- result |= QWindowsOpenGLTester::DesktopGl;
+ // Don't test for GL if explicitly requested or GLES only is requested
+ if (requested == DesktopGl
+ || ((requested & GlesMask) == 0 && testDesktopGL())) {
+ result |= QWindowsOpenGLTester::DesktopGl;
+ }
const char bugListFileVar[] = "QT_OPENGL_BUGLIST";
QString buglistFileName = QStringLiteral(":/qt-project.org/windows/openglblacklists/default.json");
@@ -259,24 +305,20 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(c
qCDebug(lcQpaGl) << "Disabling rotation: " << gpu;
result |= DisableRotationFlag;
}
+ if (features.contains(QStringLiteral("disable_program_cache"))) {
+ qCDebug(lcQpaGl) << "Disabling program cache: " << gpu;
+ result |= DisableProgramCacheFlag;
+ }
srCache->insert(qgpu, result);
return result;
#endif // !QT_NO_OPENGL
}
-QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::supportedGlesRenderers()
-{
- const GpuDescription gpu = GpuDescription::detect();
- const QWindowsOpenGLTester::Renderers result = detectSupportedRenderers(gpu, true);
- qCDebug(lcQpaGl) << __FUNCTION__ << gpu << "renderer: " << result;
- return result;
-}
-
-QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::supportedRenderers()
+QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::supportedRenderers(Renderer requested)
{
const GpuDescription gpu = GpuDescription::detect();
- const QWindowsOpenGLTester::Renderers result = detectSupportedRenderers(gpu, false);
- qCDebug(lcQpaGl) << __FUNCTION__ << gpu << "renderer: " << result;
+ const QWindowsOpenGLTester::Renderers result = detectSupportedRenderers(gpu, requested);
+ qCDebug(lcQpaGl) << __FUNCTION__ << gpu << requested << "renderer: " << result;
return result;
}
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.h b/src/plugins/platforms/windows/qwindowsopengltester.h
index e3fec59dd5..08628c2586 100644
--- a/src/plugins/platforms/windows/qwindowsopengltester.h
+++ b/src/plugins/platforms/windows/qwindowsopengltester.h
@@ -40,8 +40,8 @@
#ifndef QWINDOWSOPENGLTESTER_H
#define QWINDOWSOPENGLTESTER_H
-#include <QtCore/QByteArray>
-#include <QtCore/QFlags>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qflags.h>
#include <QtCore/qversionnumber.h>
QT_BEGIN_NAMESPACE
@@ -62,6 +62,7 @@ struct GpuDescription
QVersionNumber driverVersion;
QByteArray driverName;
QByteArray description;
+ QString gpuSuitableScreen;
};
#ifndef QT_NO_DEBUG_STREAM
@@ -82,18 +83,18 @@ public:
GlesMask = Gles | AngleBackendMask,
SoftwareRasterizer = 0x0020,
RendererMask = 0x00FF,
- DisableRotationFlag = 0x0100
+ DisableRotationFlag = 0x0100,
+ DisableProgramCacheFlag = 0x0200
};
Q_DECLARE_FLAGS(Renderers, Renderer)
static Renderer requestedGlesRenderer();
static Renderer requestedRenderer();
- static Renderers supportedGlesRenderers();
- static Renderers supportedRenderers();
+ static QWindowsOpenGLTester::Renderers supportedRenderers(Renderer requested);
private:
- static QWindowsOpenGLTester::Renderers detectSupportedRenderers(const GpuDescription &gpu, bool glesOnly);
+ static Renderers detectSupportedRenderers(const GpuDescription &gpu, Renderer requested);
static bool testDesktopGL();
};
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
new file mode 100644
index 0000000000..2b6c696979
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
@@ -0,0 +1,799 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#if defined(WINVER) && WINVER < 0x0603
+# undef WINVER
+#endif
+#if !defined(WINVER)
+# define WINVER 0x0603 // Enable pointer functions for MinGW
+#endif
+
+#include "qwindowspointerhandler.h"
+#include "qwindowskeymapper.h"
+#include "qwindowscontext.h"
+#include "qwindowswindow.h"
+#include "qwindowsintegration.h"
+#include "qwindowsscreen.h"
+#if QT_CONFIG(draganddrop)
+# include "qwindowsdrag.h"
+#endif
+
+#include <qpa/qwindowsysteminterface.h>
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qscreen.h>
+#include <QtGui/qtouchdevice.h>
+#include <QtGui/qwindow.h>
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qloggingcategory.h>
+#include <QtCore/qoperatingsystemversion.h>
+#include <QtCore/qqueue.h>
+
+#include <algorithm>
+
+#include <windowsx.h>
+
+QT_BEGIN_NAMESPACE
+
+enum {
+ QT_PT_POINTER = 1,
+ QT_PT_TOUCH = 2,
+ QT_PT_PEN = 3,
+ QT_PT_MOUSE = 4,
+ QT_PT_TOUCHPAD = 5, // MinGW is missing PT_TOUCHPAD
+};
+
+struct PointerTouchEventInfo {
+ QPointer<QWindow> window;
+ QList<QWindowSystemInterface::TouchPoint> points;
+ Qt::KeyboardModifiers modifiers;
+};
+
+struct PointerTabletEventInfo {
+ QPointer<QWindow> window;
+ QPointF local;
+ QPointF global;
+ int device;
+ int pointerType;
+ Qt::MouseButtons buttons;
+ qreal pressure;
+ int xTilt;
+ int yTilt;
+ qreal tangentialPressure;
+ qreal rotation;
+ int z;
+ qint64 uid;
+ Qt::KeyboardModifiers modifiers;
+};
+
+static QQueue<PointerTouchEventInfo> touchEventQueue;
+static QQueue<PointerTabletEventInfo> tabletEventQueue;
+
+static void enqueueTouchEvent(QWindow *window,
+ const QList<QWindowSystemInterface::TouchPoint> &points,
+ Qt::KeyboardModifiers modifiers)
+{
+ PointerTouchEventInfo eventInfo;
+ eventInfo.window = window;
+ eventInfo.points = points;
+ eventInfo.modifiers = modifiers;
+ touchEventQueue.enqueue(eventInfo);
+}
+
+static void enqueueTabletEvent(QWindow *window, const QPointF &local, const QPointF &global,
+ int device, int pointerType, Qt::MouseButtons buttons, qreal pressure,
+ int xTilt, int yTilt, qreal tangentialPressure, qreal rotation,
+ int z, qint64 uid, Qt::KeyboardModifiers modifiers)
+{
+ PointerTabletEventInfo eventInfo;
+ eventInfo.window = window;
+ eventInfo.local = local;
+ eventInfo.global = global;
+ eventInfo.device = device;
+ eventInfo.pointerType = pointerType;
+ eventInfo.buttons = buttons;
+ eventInfo.pressure = pressure;
+ eventInfo.xTilt = xTilt;
+ eventInfo.yTilt = yTilt;
+ eventInfo.tangentialPressure = tangentialPressure;
+ eventInfo.rotation = rotation;
+ eventInfo.z = z;
+ eventInfo.uid = uid;
+ eventInfo.modifiers = modifiers;
+ tabletEventQueue.enqueue(eventInfo);
+}
+
+static void flushTouchEvents(QTouchDevice *touchDevice)
+{
+ while (!touchEventQueue.isEmpty()) {
+ PointerTouchEventInfo eventInfo = touchEventQueue.dequeue();
+ if (eventInfo.window) {
+ QWindowSystemInterface::handleTouchEvent(eventInfo.window,
+ touchDevice,
+ eventInfo.points,
+ eventInfo.modifiers);
+ }
+ }
+}
+
+static void flushTabletEvents()
+{
+ while (!tabletEventQueue.isEmpty()) {
+ PointerTabletEventInfo eventInfo = tabletEventQueue.dequeue();
+ if (eventInfo.window) {
+ QWindowSystemInterface::handleTabletEvent(eventInfo.window,
+ eventInfo.local,
+ eventInfo.global,
+ eventInfo.device,
+ eventInfo.pointerType,
+ eventInfo.buttons,
+ eventInfo.pressure,
+ eventInfo.xTilt,
+ eventInfo.yTilt,
+ eventInfo.tangentialPressure,
+ eventInfo.rotation,
+ eventInfo.z,
+ eventInfo.uid,
+ eventInfo.modifiers);
+ }
+ }
+}
+
+static bool draggingActive()
+{
+#if QT_CONFIG(draganddrop)
+ return QWindowsDrag::isDragging();
+#else
+ return false;
+#endif
+}
+
+bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result)
+{
+ *result = 0;
+ const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
+
+ POINTER_INPUT_TYPE pointerType;
+ if (!QWindowsContext::user32dll.getPointerType(pointerId, &pointerType)) {
+ qWarning() << "GetPointerType() failed:" << qt_error_string();
+ return false;
+ }
+
+ switch (pointerType) {
+ case QT_PT_POINTER:
+ case QT_PT_MOUSE:
+ case QT_PT_TOUCHPAD: {
+ POINTER_INFO pointerInfo;
+ if (!QWindowsContext::user32dll.getPointerInfo(pointerId, &pointerInfo)) {
+ qWarning() << "GetPointerInfo() failed:" << qt_error_string();
+ return false;
+ }
+ return translateMouseTouchPadEvent(window, hwnd, et, msg, &pointerInfo);
+ }
+ case QT_PT_TOUCH: {
+ quint32 pointerCount = 0;
+ if (!QWindowsContext::user32dll.getPointerFrameTouchInfo(pointerId, &pointerCount, nullptr)) {
+ qWarning() << "GetPointerFrameTouchInfo() failed:" << qt_error_string();
+ return false;
+ }
+ QVarLengthArray<POINTER_TOUCH_INFO, 10> touchInfo(pointerCount);
+ if (!QWindowsContext::user32dll.getPointerFrameTouchInfo(pointerId, &pointerCount, touchInfo.data())) {
+ qWarning() << "GetPointerFrameTouchInfo() failed:" << qt_error_string();
+ return false;
+ }
+
+ if (!pointerCount)
+ return false;
+
+ // The history count is the same for all the touchpoints in touchInfo
+ quint32 historyCount = touchInfo[0].pointerInfo.historyCount;
+ // dispatch any skipped frames if event compression is disabled by the app
+ if (historyCount > 1 && !QCoreApplication::testAttribute(Qt::AA_CompressHighFrequencyEvents)) {
+ touchInfo.resize(pointerCount * historyCount);
+ if (!QWindowsContext::user32dll.getPointerFrameTouchInfoHistory(pointerId,
+ &historyCount,
+ &pointerCount,
+ touchInfo.data())) {
+ qWarning() << "GetPointerFrameTouchInfoHistory() failed:" << qt_error_string();
+ return false;
+ }
+
+ // history frames are returned with the most recent frame first so we iterate backwards
+ bool result = true;
+ for (auto it = touchInfo.rbegin(), end = touchInfo.rend(); it != end; it += pointerCount) {
+ result &= translateTouchEvent(window, hwnd, et, msg,
+ &(*(it + (pointerCount - 1))), pointerCount);
+ }
+ return result;
+ }
+
+ return translateTouchEvent(window, hwnd, et, msg, touchInfo.data(), pointerCount);
+ }
+ case QT_PT_PEN: {
+ POINTER_PEN_INFO penInfo;
+ if (!QWindowsContext::user32dll.getPointerPenInfo(pointerId, &penInfo)) {
+ qWarning() << "GetPointerPenInfo() failed:" << qt_error_string();
+ return false;
+ }
+
+ quint32 historyCount = penInfo.pointerInfo.historyCount;
+ // dispatch any skipped frames if generic or tablet event compression is disabled by the app
+ if (historyCount > 1
+ && (!QCoreApplication::testAttribute(Qt::AA_CompressHighFrequencyEvents)
+ || !QCoreApplication::testAttribute(Qt::AA_CompressTabletEvents))) {
+ QVarLengthArray<POINTER_PEN_INFO, 10> penInfoHistory(historyCount);
+
+ if (!QWindowsContext::user32dll.getPointerPenInfoHistory(pointerId,
+ &historyCount,
+ penInfoHistory.data())) {
+ qWarning() << "GetPointerPenInfoHistory() failed:" << qt_error_string();
+ return false;
+ }
+
+ // history frames are returned with the most recent frame first so we iterate backwards
+ bool result = true;
+ for (auto it = penInfoHistory.rbegin(), end = penInfoHistory.rend(); it != end; ++it) {
+ result &= translatePenEvent(window, hwnd, et, msg, &(*(it)));
+ }
+ return result;
+ }
+
+ return translatePenEvent(window, hwnd, et, msg, &penInfo);
+ }
+ }
+ return false;
+}
+
+static void getMouseEventInfo(UINT message, POINTER_BUTTON_CHANGE_TYPE changeType, QEvent::Type *eventType, Qt::MouseButton *mouseButton)
+{
+ static const QHash<POINTER_BUTTON_CHANGE_TYPE, Qt::MouseButton> buttonMapping {
+ {POINTER_CHANGE_FIRSTBUTTON_DOWN, Qt::LeftButton},
+ {POINTER_CHANGE_FIRSTBUTTON_UP, Qt::LeftButton},
+ {POINTER_CHANGE_SECONDBUTTON_DOWN, Qt::RightButton},
+ {POINTER_CHANGE_SECONDBUTTON_UP, Qt::RightButton},
+ {POINTER_CHANGE_THIRDBUTTON_DOWN, Qt::MiddleButton},
+ {POINTER_CHANGE_THIRDBUTTON_UP, Qt::MiddleButton},
+ {POINTER_CHANGE_FOURTHBUTTON_DOWN, Qt::XButton1},
+ {POINTER_CHANGE_FOURTHBUTTON_UP, Qt::XButton1},
+ {POINTER_CHANGE_FIFTHBUTTON_DOWN, Qt::XButton2},
+ {POINTER_CHANGE_FIFTHBUTTON_UP, Qt::XButton2},
+ };
+
+ static const POINTER_BUTTON_CHANGE_TYPE downChanges[] = {
+ POINTER_CHANGE_FIRSTBUTTON_DOWN,
+ POINTER_CHANGE_SECONDBUTTON_DOWN,
+ POINTER_CHANGE_THIRDBUTTON_DOWN,
+ POINTER_CHANGE_FOURTHBUTTON_DOWN,
+ POINTER_CHANGE_FIFTHBUTTON_DOWN,
+ };
+
+ static const POINTER_BUTTON_CHANGE_TYPE upChanges[] = {
+ POINTER_CHANGE_FIRSTBUTTON_UP,
+ POINTER_CHANGE_SECONDBUTTON_UP,
+ POINTER_CHANGE_THIRDBUTTON_UP,
+ POINTER_CHANGE_FOURTHBUTTON_UP,
+ POINTER_CHANGE_FIFTHBUTTON_UP,
+ };
+
+ if (!eventType || !mouseButton)
+ return;
+
+ const bool nonClient = message == WM_NCPOINTERUPDATE ||
+ message == WM_NCPOINTERDOWN ||
+ message == WM_NCPOINTERUP;
+
+ if (std::find(std::begin(downChanges),
+ std::end(downChanges), changeType) < std::end(downChanges)) {
+ *eventType = nonClient ? QEvent::NonClientAreaMouseButtonPress :
+ QEvent::MouseButtonPress;
+ } else if (std::find(std::begin(upChanges),
+ std::end(upChanges), changeType) < std::end(upChanges)) {
+ *eventType = nonClient ? QEvent::NonClientAreaMouseButtonRelease :
+ QEvent::MouseButtonRelease;
+ } else if (message == WM_POINTERWHEEL || message == WM_POINTERHWHEEL) {
+ *eventType = QEvent::Wheel;
+ } else {
+ *eventType = nonClient ? QEvent::NonClientAreaMouseMove :
+ QEvent::MouseMove;
+ }
+
+ *mouseButton = buttonMapping.value(changeType, Qt::NoButton);
+}
+
+static QWindow *getWindowUnderPointer(QWindow *window, QPoint globalPos)
+{
+ QWindow *currentWindowUnderPointer = QWindowsScreen::windowAt(globalPos, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT);
+
+ while (currentWindowUnderPointer && currentWindowUnderPointer->flags() & Qt::WindowTransparentForInput)
+ currentWindowUnderPointer = currentWindowUnderPointer->parent();
+
+ // QTBUG-44332: When Qt is running at low integrity level and
+ // a Qt Window is parented on a Window of a higher integrity process
+ // using QWindow::fromWinId() (for example, Qt running in a browser plugin)
+ // ChildWindowFromPointEx() may not find the Qt window (failing with ERROR_ACCESS_DENIED)
+ if (!currentWindowUnderPointer) {
+ const QRect clientRect(QPoint(0, 0), window->size());
+ if (clientRect.contains(globalPos))
+ currentWindowUnderPointer = window;
+ }
+ return currentWindowUnderPointer;
+}
+
+static bool trackLeave(HWND hwnd)
+{
+ TRACKMOUSEEVENT tme;
+ tme.cbSize = sizeof(TRACKMOUSEEVENT);
+ tme.dwFlags = TME_LEAVE;
+ tme.hwndTrack = hwnd;
+ tme.dwHoverTime = HOVER_DEFAULT;
+ return TrackMouseEvent(&tme);
+}
+
+static bool isValidWheelReceiver(QWindow *candidate)
+{
+ if (candidate) {
+ const QWindow *toplevel = QWindowsWindow::topLevelOf(candidate);
+ if (toplevel->handle() && toplevel->handle()->isForeignWindow())
+ return true;
+ if (const QWindowsWindow *ww = QWindowsWindow::windowsWindowOf(toplevel))
+ return !ww->testFlag(QWindowsWindow::BlockedByModal);
+ }
+ return false;
+}
+
+static QTouchDevice *createTouchDevice()
+{
+ const int digitizers = GetSystemMetrics(SM_DIGITIZER);
+ if (!(digitizers & (NID_INTEGRATED_TOUCH | NID_EXTERNAL_TOUCH)))
+ return nullptr;
+ const int tabletPc = GetSystemMetrics(SM_TABLETPC);
+ const int maxTouchPoints = GetSystemMetrics(SM_MAXIMUMTOUCHES);
+ qCDebug(lcQpaEvents) << "Digitizers:" << hex << showbase << (digitizers & ~NID_READY)
+ << "Ready:" << (digitizers & NID_READY) << dec << noshowbase
+ << "Tablet PC:" << tabletPc << "Max touch points:" << maxTouchPoints;
+ QTouchDevice *result = new QTouchDevice;
+ result->setType(digitizers & NID_INTEGRATED_TOUCH
+ ? QTouchDevice::TouchScreen : QTouchDevice::TouchPad);
+ QTouchDevice::Capabilities capabilities = QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::NormalizedPosition;
+ if (result->type() == QTouchDevice::TouchPad)
+ capabilities |= QTouchDevice::MouseEmulation;
+ result->setCapabilities(capabilities);
+ result->setMaximumTouchPoints(maxTouchPoints);
+ return result;
+}
+
+QTouchDevice *QWindowsPointerHandler::ensureTouchDevice()
+{
+ if (!m_touchDevice)
+ m_touchDevice = createTouchDevice();
+ return m_touchDevice;
+}
+
+Qt::MouseButtons QWindowsPointerHandler::queryMouseButtons()
+{
+ Qt::MouseButtons result = 0;
+ const bool mouseSwapped = GetSystemMetrics(SM_SWAPBUTTON);
+ if (GetAsyncKeyState(VK_LBUTTON) < 0)
+ result |= mouseSwapped ? Qt::RightButton: Qt::LeftButton;
+ if (GetAsyncKeyState(VK_RBUTTON) < 0)
+ result |= mouseSwapped ? Qt::LeftButton : Qt::RightButton;
+ if (GetAsyncKeyState(VK_MBUTTON) < 0)
+ result |= Qt::MidButton;
+ if (GetAsyncKeyState(VK_XBUTTON1) < 0)
+ result |= Qt::XButton1;
+ if (GetAsyncKeyState(VK_XBUTTON2) < 0)
+ result |= Qt::XButton2;
+ return result;
+}
+
+bool QWindowsPointerHandler::translateMouseTouchPadEvent(QWindow *window, HWND hwnd,
+ QtWindows::WindowsEventType et,
+ MSG msg, PVOID vPointerInfo)
+{
+ POINTER_INFO *pointerInfo = static_cast<POINTER_INFO *>(vPointerInfo);
+ const QPoint globalPos = QPoint(pointerInfo->ptPixelLocation.x, pointerInfo->ptPixelLocation.y);
+ const QPoint localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPos);
+ const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
+ const Qt::MouseButtons mouseButtons = queryMouseButtons();
+
+ QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos);
+ QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
+
+ switch (msg.message) {
+ case WM_NCPOINTERDOWN:
+ case WM_NCPOINTERUP:
+ case WM_NCPOINTERUPDATE:
+ case WM_POINTERDOWN:
+ case WM_POINTERUP:
+ case WM_POINTERUPDATE: {
+
+ QEvent::Type eventType;
+ Qt::MouseButton button;
+ getMouseEventInfo(msg.message, pointerInfo->ButtonChangeType, &eventType, &button);
+
+ if (et & QtWindows::NonClientEventFlag) {
+ QWindowSystemInterface::handleFrameStrutMouseEvent(window, localPos, globalPos, mouseButtons, button, eventType,
+ keyModifiers, Qt::MouseEventNotSynthesized);
+ return false; // To allow window dragging, etc.
+ } else {
+ if (currentWindowUnderPointer != m_windowUnderPointer) {
+ if (m_windowUnderPointer && m_windowUnderPointer == m_currentWindow) {
+ QWindowSystemInterface::handleLeaveEvent(m_windowUnderPointer);
+ m_currentWindow = nullptr;
+ }
+
+ if (currentWindowUnderPointer) {
+ if (currentWindowUnderPointer != m_currentWindow) {
+ QWindowSystemInterface::handleEnterEvent(currentWindowUnderPointer, localPos, globalPos);
+ m_currentWindow = currentWindowUnderPointer;
+ if (QWindowsWindow *wumPlatformWindow = QWindowsWindow::windowsWindowOf(currentWindowUnderPointer))
+ wumPlatformWindow->applyCursor();
+ trackLeave(hwnd);
+ }
+ } else {
+ platformWindow->applyCursor();
+ }
+ m_windowUnderPointer = currentWindowUnderPointer;
+ }
+
+ QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, button, eventType,
+ keyModifiers, Qt::MouseEventNotSynthesized);
+
+ // The initial down click over the QSizeGrip area, which posts a resize WM_SYSCOMMAND
+ // has go to through DefWindowProc() for resizing to work, so we return false here,
+ // unless the mouse is captured, as it would mess with menu processing.
+ return msg.message != WM_POINTERDOWN || GetCapture();
+ }
+ }
+ case WM_POINTERHWHEEL:
+ case WM_POINTERWHEEL: {
+
+ if (!isValidWheelReceiver(window))
+ return true;
+
+ int delta = GET_WHEEL_DELTA_WPARAM(msg.wParam);
+
+ // Qt horizontal wheel rotation orientation is opposite to the one in WM_POINTERHWHEEL
+ if (msg.message == WM_POINTERHWHEEL)
+ delta = -delta;
+
+ const QPoint angleDelta = (msg.message == WM_POINTERHWHEEL || (keyModifiers & Qt::AltModifier)) ?
+ QPoint(delta, 0) : QPoint(0, delta);
+
+ QWindowSystemInterface::handleWheelEvent(window, localPos, globalPos, QPoint(), angleDelta, keyModifiers);
+ return true;
+ }
+ case WM_POINTERLEAVE:
+ return true;
+ }
+ return false;
+}
+
+bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
+ QtWindows::WindowsEventType et,
+ MSG msg, PVOID vTouchInfo, quint32 count)
+{
+ Q_UNUSED(hwnd);
+
+ if (et & QtWindows::NonClientEventFlag)
+ return false; // Let DefWindowProc() handle Non Client messages.
+
+ if (draggingActive())
+ return false; // Let DoDragDrop() loop handle it.
+
+ if (count < 1)
+ return false;
+
+ if (msg.message == WM_POINTERCAPTURECHANGED) {
+ QWindowSystemInterface::handleTouchCancelEvent(window, m_touchDevice,
+ QWindowsKeyMapper::queryKeyboardModifiers());
+ m_lastTouchPositions.clear();
+ return true;
+ }
+
+ // Only handle down/up/update, ignore others like WM_POINTERENTER, WM_POINTERLEAVE, etc.
+ if (msg.message > WM_POINTERUP)
+ return false;
+
+ const QScreen *screen = window->screen();
+ if (!screen)
+ screen = QGuiApplication::primaryScreen();
+ if (!screen)
+ return false;
+
+ POINTER_TOUCH_INFO *touchInfo = static_cast<POINTER_TOUCH_INFO *>(vTouchInfo);
+
+ const QRect screenGeometry = screen->geometry();
+
+ QList<QWindowSystemInterface::TouchPoint> touchPoints;
+
+ bool primaryPointer = false;
+
+ if (QWindowsContext::verbose > 1)
+ qCDebug(lcQpaEvents).noquote().nospace() << showbase
+ << __FUNCTION__
+ << " message=" << hex << msg.message
+ << " count=" << dec << count;
+
+ for (quint32 i = 0; i < count; ++i) {
+ if (QWindowsContext::verbose > 1)
+ qCDebug(lcQpaEvents).noquote().nospace() << showbase
+ << " TouchPoint id=" << touchInfo[i].pointerInfo.pointerId
+ << " frame=" << touchInfo[i].pointerInfo.frameId
+ << " flags=" << hex << touchInfo[i].pointerInfo.pointerFlags;
+
+ QWindowSystemInterface::TouchPoint touchPoint;
+ touchPoint.id = touchInfo[i].pointerInfo.pointerId;
+ touchPoint.pressure = (touchInfo[i].touchMask & TOUCH_MASK_PRESSURE) ?
+ touchInfo[i].pressure / 1024.0 : 1.0;
+ if (m_lastTouchPositions.contains(touchPoint.id))
+ touchPoint.normalPosition = m_lastTouchPositions.value(touchPoint.id);
+
+ const QPointF screenPos = QPointF(touchInfo[i].pointerInfo.ptPixelLocation.x,
+ touchInfo[i].pointerInfo.ptPixelLocation.y);
+
+ if (touchInfo[i].touchMask & TOUCH_MASK_CONTACTAREA)
+ touchPoint.area.setSize(QSizeF(touchInfo[i].rcContact.right - touchInfo[i].rcContact.left,
+ touchInfo[i].rcContact.bottom - touchInfo[i].rcContact.top));
+ touchPoint.area.moveCenter(screenPos);
+ QPointF normalPosition = QPointF(screenPos.x() / screenGeometry.width(),
+ screenPos.y() / screenGeometry.height());
+ const bool stationaryTouchPoint = (normalPosition == touchPoint.normalPosition);
+ touchPoint.normalPosition = normalPosition;
+
+ if (touchInfo[i].pointerInfo.pointerFlags & POINTER_FLAG_DOWN) {
+ touchPoint.state = Qt::TouchPointPressed;
+ m_lastTouchPositions.insert(touchPoint.id, touchPoint.normalPosition);
+ } else if (touchInfo[i].pointerInfo.pointerFlags & POINTER_FLAG_UP) {
+ touchPoint.state = Qt::TouchPointReleased;
+ m_lastTouchPositions.remove(touchPoint.id);
+ } else {
+ touchPoint.state = stationaryTouchPoint ? Qt::TouchPointStationary : Qt::TouchPointMoved;
+ m_lastTouchPositions.insert(touchPoint.id, touchPoint.normalPosition);
+ }
+ if (touchInfo[i].pointerInfo.pointerFlags & POINTER_FLAG_PRIMARY)
+ primaryPointer = true;
+
+ touchPoints.append(touchPoint);
+
+ // Avoid getting repeated messages for this frame if there are multiple pointerIds
+ QWindowsContext::user32dll.skipPointerFrameMessages(touchInfo[i].pointerInfo.pointerId);
+ }
+ if (primaryPointer) {
+ // Postpone event delivery to avoid hanging inside DoDragDrop().
+ // Only the primary pointer will generate mouse messages.
+ enqueueTouchEvent(window, touchPoints, QWindowsKeyMapper::queryKeyboardModifiers());
+ } else {
+ QWindowSystemInterface::handleTouchEvent(window, m_touchDevice, touchPoints,
+ QWindowsKeyMapper::queryKeyboardModifiers());
+ }
+ return false; // Allow mouse messages to be generated.
+}
+
+bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et,
+ MSG msg, PVOID vPenInfo)
+{
+ if (et & QtWindows::NonClientEventFlag)
+ return false; // Let DefWindowProc() handle Non Client messages.
+
+ if (draggingActive())
+ return false; // Let DoDragDrop() loop handle it.
+
+ POINTER_PEN_INFO *penInfo = static_cast<POINTER_PEN_INFO *>(vPenInfo);
+
+ RECT pRect, dRect;
+ if (!QWindowsContext::user32dll.getPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect))
+ return false;
+
+ const quint32 pointerId = penInfo->pointerInfo.pointerId;
+ const QPoint globalPos = QPoint(penInfo->pointerInfo.ptPixelLocation.x, penInfo->pointerInfo.ptPixelLocation.y);
+ const QPoint localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPos);
+ const QPointF hiResGlobalPos = QPointF(dRect.left + qreal(penInfo->pointerInfo.ptHimetricLocation.x - pRect.left)
+ / (pRect.right - pRect.left) * (dRect.right - dRect.left),
+ dRect.top + qreal(penInfo->pointerInfo.ptHimetricLocation.y - pRect.top)
+ / (pRect.bottom - pRect.top) * (dRect.bottom - dRect.top));
+ const qreal pressure = (penInfo->penMask & PEN_MASK_PRESSURE) ? qreal(penInfo->pressure) / 1024.0 : 0.5;
+ const qreal rotation = (penInfo->penMask & PEN_MASK_ROTATION) ? qreal(penInfo->rotation) : 0.0;
+ const qreal tangentialPressure = 0.0;
+ const int xTilt = (penInfo->penMask & PEN_MASK_TILT_X) ? penInfo->tiltX : 0;
+ const int yTilt = (penInfo->penMask & PEN_MASK_TILT_Y) ? penInfo->tiltY : 0;
+ const int z = 0;
+
+ if (QWindowsContext::verbose > 1)
+ qCDebug(lcQpaEvents).noquote().nospace() << showbase
+ << __FUNCTION__ << " pointerId=" << pointerId
+ << " globalPos=" << globalPos << " localPos=" << localPos << " hiResGlobalPos=" << hiResGlobalPos
+ << " message=" << hex << msg.message
+ << " flags=" << hex << penInfo->pointerInfo.pointerFlags;
+
+ const QTabletEvent::TabletDevice device = QTabletEvent::Stylus;
+ QTabletEvent::PointerType type;
+ Qt::MouseButtons mouseButtons;
+
+ const bool pointerInContact = IS_POINTER_INCONTACT_WPARAM(msg.wParam);
+ if (pointerInContact)
+ mouseButtons = Qt::LeftButton;
+
+ if (penInfo->penFlags & (PEN_FLAG_ERASER | PEN_FLAG_INVERTED)) {
+ type = QTabletEvent::Eraser;
+ } else {
+ type = QTabletEvent::Pen;
+ if (pointerInContact && penInfo->penFlags & PEN_FLAG_BARREL)
+ mouseButtons = Qt::RightButton; // Either left or right, not both
+ }
+
+ switch (msg.message) {
+ case WM_POINTERENTER: {
+ QWindowSystemInterface::handleTabletEnterProximityEvent(device, type, pointerId);
+ m_windowUnderPointer = window;
+ // The local coordinates may fall outside the window.
+ // Wait until the next update to send the enter event.
+ m_needsEnterOnPointerUpdate = true;
+ break;
+ }
+ case WM_POINTERLEAVE:
+ if (m_windowUnderPointer && m_windowUnderPointer == m_currentWindow) {
+ QWindowSystemInterface::handleLeaveEvent(m_windowUnderPointer);
+ m_windowUnderPointer = nullptr;
+ m_currentWindow = nullptr;
+ }
+ QWindowSystemInterface::handleTabletLeaveProximityEvent(device, type, pointerId);
+ break;
+ case WM_POINTERDOWN:
+ case WM_POINTERUP:
+ case WM_POINTERUPDATE: {
+ QWindow *target = QGuiApplicationPrivate::tabletDevicePoint(pointerId).target; // Pass to window that grabbed it.
+ if (!target && m_windowUnderPointer)
+ target = m_windowUnderPointer;
+ if (!target)
+ target = window;
+
+ if (m_needsEnterOnPointerUpdate) {
+ m_needsEnterOnPointerUpdate = false;
+ if (window != m_currentWindow) {
+ QWindowSystemInterface::handleEnterEvent(window, localPos, globalPos);
+ m_currentWindow = window;
+ if (QWindowsWindow *wumPlatformWindow = QWindowsWindow::windowsWindowOf(target))
+ wumPlatformWindow->applyCursor();
+ }
+ }
+ const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
+
+ // Postpone event delivery to avoid hanging inside DoDragDrop().
+ enqueueTabletEvent(target, localPos, hiResGlobalPos, device, type, mouseButtons,
+ pressure, xTilt, yTilt, tangentialPressure, rotation, z,
+ pointerId, keyModifiers);
+ return false; // Allow mouse messages to be generated.
+ }
+ }
+ return true;
+}
+
+// Process old-style mouse messages here.
+bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result)
+{
+ // Generate enqueued events.
+ flushTouchEvents(m_touchDevice);
+ flushTabletEvents();
+
+ *result = 0;
+ if (et != QtWindows::MouseWheelEvent && msg.message != WM_MOUSELEAVE && msg.message != WM_MOUSEMOVE)
+ return false;
+
+ const QPoint eventPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
+ QPoint localPos;
+ QPoint globalPos;
+ if ((et == QtWindows::MouseWheelEvent) || (et & QtWindows::NonClientEventFlag)) {
+ globalPos = eventPos;
+ localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, eventPos);
+ } else {
+ localPos = eventPos;
+ globalPos = QWindowsGeometryHint::mapToGlobal(hwnd, eventPos);
+ }
+
+ const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
+ QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
+
+ if (et == QtWindows::MouseWheelEvent) {
+
+ if (!isValidWheelReceiver(window))
+ return true;
+
+ int delta = GET_WHEEL_DELTA_WPARAM(msg.wParam);
+
+ // Qt horizontal wheel rotation orientation is opposite to the one in WM_MOUSEHWHEEL
+ if (msg.message == WM_MOUSEHWHEEL)
+ delta = -delta;
+
+ const QPoint angleDelta = (msg.message == WM_MOUSEHWHEEL || (keyModifiers & Qt::AltModifier)) ?
+ QPoint(delta, 0) : QPoint(0, delta);
+
+ QWindowSystemInterface::handleWheelEvent(window, localPos, globalPos, QPoint(), angleDelta, keyModifiers);
+ return true;
+ }
+
+ if (msg.message == WM_MOUSELEAVE) {
+ if (window == m_currentWindow) {
+ QWindowSystemInterface::handleLeaveEvent(window);
+ m_windowUnderPointer = nullptr;
+ m_currentWindow = nullptr;
+ platformWindow->applyCursor();
+ }
+ return false;
+ }
+
+ // Windows sends a mouse move with no buttons pressed to signal "Enter"
+ // when a window is shown over the cursor. Discard the event and only use
+ // it for generating QEvent::Enter to be consistent with other platforms -
+ // X11 and macOS.
+ static QPoint lastMouseMovePos;
+ const bool discardEvent = msg.wParam == 0 && (m_windowUnderPointer.isNull() || globalPos == lastMouseMovePos);
+ lastMouseMovePos = globalPos;
+
+ QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos);
+
+ if (currentWindowUnderPointer != m_windowUnderPointer) {
+ if (m_windowUnderPointer && m_windowUnderPointer == m_currentWindow) {
+ QWindowSystemInterface::handleLeaveEvent(m_windowUnderPointer);
+ m_currentWindow = nullptr;
+ }
+
+ if (currentWindowUnderPointer) {
+ if (currentWindowUnderPointer != m_currentWindow) {
+ QWindowSystemInterface::handleEnterEvent(currentWindowUnderPointer, localPos, globalPos);
+ m_currentWindow = currentWindowUnderPointer;
+ if (QWindowsWindow *wumPlatformWindow = QWindowsWindow::windowsWindowOf(currentWindowUnderPointer))
+ wumPlatformWindow->applyCursor();
+ trackLeave(hwnd);
+ }
+ } else {
+ platformWindow->applyCursor();
+ }
+ m_windowUnderPointer = currentWindowUnderPointer;
+ }
+
+ const Qt::MouseButtons mouseButtons = queryMouseButtons();
+
+ if (!discardEvent)
+ QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, Qt::NoButton, QEvent::MouseMove,
+ keyModifiers, Qt::MouseEventNotSynthesized);
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.h b/src/plugins/platforms/windows/qwindowspointerhandler.h
new file mode 100644
index 0000000000..c4d0e0ce4a
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSPOINTERHANDLER_H
+#define QWINDOWSPOINTERHANDLER_H
+
+#include "qtwindowsglobal.h"
+#include <QtCore/qt_windows.h>
+
+#include <QtCore/qpointer.h>
+#include <QtCore/qscopedpointer.h>
+#include <QtCore/qhash.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWindow;
+class QTouchDevice;
+
+class QWindowsPointerHandler
+{
+ Q_DISABLE_COPY(QWindowsPointerHandler)
+public:
+ QWindowsPointerHandler() = default;
+ bool translatePointerEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result);
+ bool translateMouseEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result);
+ QTouchDevice *touchDevice() const { return m_touchDevice; }
+ QTouchDevice *ensureTouchDevice();
+ Qt::MouseButtons queryMouseButtons();
+ QWindow *windowUnderMouse() const { return m_windowUnderPointer.data(); }
+ void clearWindowUnderMouse() { m_windowUnderPointer = nullptr; }
+
+private:
+ bool translateMouseTouchPadEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPointerInfo);
+ bool translateTouchEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vTouchInfo, unsigned int count);
+ bool translatePenEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPenInfo);
+
+ QTouchDevice *m_touchDevice = nullptr;
+ QHash<int, QPointF> m_lastTouchPositions;
+ QPointer<QWindow> m_windowUnderPointer;
+ QPointer<QWindow> m_currentWindow;
+ bool m_needsEnterOnPointerUpdate = false;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSPOINTERHANDLER_H
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index d56dc870ea..2eaf386d42 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -45,14 +45,14 @@
#include <QtCore/qt_windows.h>
-#include <QtCore/QSettings>
-#include <QtGui/QPixmap>
-#include <QtGui/QGuiApplication>
+#include <QtCore/qsettings.h>
+#include <QtGui/qpixmap.h>
+#include <QtGui/qguiapplication.h>
#include <qpa/qwindowsysteminterface.h>
#include <private/qhighdpiscaling_p.h>
-#include <QtGui/QScreen>
+#include <QtGui/qscreen.h>
-#include <QtCore/QDebug>
+#include <QtCore/qdebug.h>
QT_BEGIN_NAMESPACE
@@ -69,7 +69,7 @@ static inline QDpi monitorDPI(HMONITOR hMonitor)
if (SUCCEEDED(QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, 0, &dpiX, &dpiY)))
return QDpi(dpiX, dpiY);
}
- return QDpi(0, 0);
+ return {0, 0};
}
typedef QList<QWindowsScreenData> WindowsScreenDataList;
@@ -274,9 +274,12 @@ QList<QPlatformScreen *> QWindowsScreen::virtualSiblings() const
{
QList<QPlatformScreen *> result;
if (m_data.flags & QWindowsScreenData::VirtualDesktop) {
- foreach (QWindowsScreen *screen, QWindowsContext::instance()->screenManager().screens())
+ const QWindowsScreenManager::WindowsScreenList screens
+ = QWindowsContext::instance()->screenManager().screens();
+ for (QWindowsScreen *screen : screens) {
if (screen->data().flags & QWindowsScreenData::VirtualDesktop)
result.push_back(screen);
+ }
} else {
result.push_back(const_cast<QWindowsScreen *>(this));
}
@@ -327,10 +330,7 @@ QRect QWindowsScreen::virtualGeometry(const QPlatformScreen *screen) // cf QScre
return result;
}
-enum OrientationPreference // matching Win32 API ORIENTATION_PREFERENCE
-#if defined(Q_COMPILER_CLASS_ENUM) || defined(Q_CC_MSVC)
- : DWORD
-#endif
+enum OrientationPreference : DWORD // matching Win32 API ORIENTATION_PREFERENCE
{
orientationPreferenceNone = 0,
orientationPreferenceLandscape = 0x1,
@@ -398,7 +398,8 @@ QPlatformScreen::SubpixelAntialiasingType QWindowsScreen::subpixelAntialiasingTy
{
QPlatformScreen::SubpixelAntialiasingType type = QPlatformScreen::subpixelAntialiasingTypeHint();
if (type == QPlatformScreen::Subpixel_None) {
- QSettings settings(QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Avalon.Graphics\\DISPLAY1"), QSettings::NativeFormat);
+ QSettings settings(QLatin1String(R"(HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Avalon.Graphics\DISPLAY1)"),
+ QSettings::NativeFormat);
int registryValue = settings.value(QLatin1String("PixelStructure"), -1).toInt();
switch (registryValue) {
case 0:
@@ -505,7 +506,8 @@ void QWindowsScreenManager::removeScreen(int index)
// move those manually.
if (screen != primaryScreen) {
unsigned movedWindowCount = 0;
- foreach (QWindow *w, QGuiApplication::topLevelWindows()) {
+ const QWindowList tlws = QGuiApplication::topLevelWindows();
+ for (QWindow *w : tlws) {
if (w->screen() == screen && w->handle() && w->type() != Qt::Desktop) {
if (w->isVisible() && w->windowState() != Qt::WindowMinimized
&& (QWindowsWindow::baseWindowOf(w)->exStyle() & WS_EX_TOOLWINDOW)) {
@@ -530,9 +532,9 @@ void QWindowsScreenManager::removeScreen(int index)
bool QWindowsScreenManager::handleScreenChanges()
{
// Look for changed monitors, add new ones
- WindowsScreenDataList newDataList = monitorData();
+ const WindowsScreenDataList newDataList = monitorData();
const bool lockScreen = newDataList.size() == 1 && (newDataList.front().flags & QWindowsScreenData::LockScreen);
- foreach (const QWindowsScreenData &newData, newDataList) {
+ for (const QWindowsScreenData &newData : newDataList) {
const int existingIndex = indexOfMonitor(m_screens, newData.name);
if (existingIndex != -1) {
m_screens.at(existingIndex)->handleChanges(newData);
@@ -564,7 +566,7 @@ void QWindowsScreenManager::clearScreens()
const QWindowsScreen *QWindowsScreenManager::screenAtDp(const QPoint &p) const
{
- foreach (QWindowsScreen *scr, m_screens) {
+ for (QWindowsScreen *scr : m_screens) {
if (scr->geometry().contains(p))
return scr;
}
diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h
index 5753e605da..824bcb1ad6 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.h
+++ b/src/plugins/platforms/windows/qwindowsscreen.h
@@ -42,10 +42,10 @@
#include "qtwindowsglobal.h"
-#include <QtCore/QList>
-#include <QtCore/QVector>
-#include <QtCore/QPair>
-#include <QtCore/QScopedPointer>
+#include <QtCore/qlist.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qscopedpointer.h>
#include <qpa/qplatformscreen.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsservices.cpp b/src/plugins/platforms/windows/qwindowsservices.cpp
index 48332b35f8..b6ed27464e 100644
--- a/src/plugins/platforms/windows/qwindowsservices.cpp
+++ b/src/plugins/platforms/windows/qwindowsservices.cpp
@@ -41,9 +41,9 @@
#include "qwindowsservices.h"
#include <QtCore/qt_windows.h>
-#include <QtCore/QUrl>
-#include <QtCore/QDebug>
-#include <QtCore/QDir>
+#include <QtCore/qurl.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qdir.h>
#include <shlobj.h>
#include <intshcut.h>
diff --git a/src/plugins/platforms/windows/qwindowsservices.h b/src/plugins/platforms/windows/qwindowsservices.h
index 7518a52755..5feb7c8490 100644
--- a/src/plugins/platforms/windows/qwindowsservices.h
+++ b/src/plugins/platforms/windows/qwindowsservices.h
@@ -47,8 +47,8 @@ QT_BEGIN_NAMESPACE
class QWindowsServices : public QPlatformServices
{
public:
- bool openUrl(const QUrl &url);
- bool openDocument(const QUrl &url);
+ bool openUrl(const QUrl &url) override;
+ bool openDocument(const QUrl &url) override;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.h b/src/plugins/platforms/windows/qwindowssystemtrayicon.h
index 1f696180cd..a8adb9641f 100644
--- a/src/plugins/platforms/windows/qwindowssystemtrayicon.h
+++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.h
@@ -57,7 +57,7 @@ class QWindowsSystemTrayIcon : public QPlatformSystemTrayIcon
{
public:
QWindowsSystemTrayIcon();
- ~QWindowsSystemTrayIcon();
+ ~QWindowsSystemTrayIcon() override;
void init() override;
void cleanup() override;
diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
index 6acb62ad8f..fa209f09c4 100644
--- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp
+++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
@@ -46,13 +46,13 @@
#include <qpa/qwindowsysteminterface.h>
-#include <QtGui/QTabletEvent>
-#include <QtGui/QScreen>
-#include <QtGui/QGuiApplication>
-#include <QtGui/QWindow>
-#include <QtCore/QDebug>
-#include <QtCore/QVarLengthArray>
-#include <QtCore/QtMath>
+#include <QtGui/qevent.h>
+#include <QtGui/qscreen.h>
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qwindow.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qmath.h>
#include <private/qguiapplication_p.h>
#include <QtCore/private/qsystemlibrary_p.h>
@@ -108,7 +108,7 @@ inline QPointF QWindowsTabletDeviceData::scaleCoordinates(int coordX, int coordY
((coordY - minY) * qAbs(targetHeight) / qAbs(qreal(maxY - minY))) + targetY :
((qAbs(maxY) - (coordY - minY)) * qAbs(targetHeight) / qAbs(qreal(maxY - minY))) + targetY;
- return QPointF(x, y);
+ return {x, y};
}
template <class Stream>
@@ -135,9 +135,9 @@ QDebug operator<<(QDebug d, const QWindowsTabletDeviceData &t)
d.nospace();
d << "TabletDevice id:" << t.uniqueId << " pressure: " << t.minPressure
<< ".." << t.maxPressure << " tan pressure: " << t.minTanPressure << ".."
- << t.maxTanPressure << " area:" << t.minX << t.minY <<t.minZ
- << ".." << t.maxX << t.maxY << t.maxZ << " device " << t.currentDevice
- << " pointer " << t.currentPointerType;
+ << t.maxTanPressure << " area: (" << t.minX << ',' << t.minY << ',' << t.minZ
+ << ")..(" << t.maxX << ',' << t.maxY << ',' << t.maxZ << ") device "
+ << t.currentDevice << " pointer " << t.currentPointerType;
return d;
}
@@ -211,9 +211,6 @@ bool QWindowsWinTab32DLL::init()
QWindowsTabletSupport::QWindowsTabletSupport(HWND window, HCTX context)
: m_window(window)
, m_context(context)
- , m_absoluteRange(20)
- , m_tiltSupport(false)
- , m_currentDevice(-1)
{
AXIS orientation[3];
// Some tablets don't support tilt, check if it is possible,
@@ -230,13 +227,13 @@ QWindowsTabletSupport::~QWindowsTabletSupport()
QWindowsTabletSupport *QWindowsTabletSupport::create()
{
if (!m_winTab32DLL.init())
- return 0;
+ return nullptr;
const HWND window = QWindowsContext::instance()->createDummyWindow(QStringLiteral("TabletDummyWindow"),
L"TabletDummyWindow",
qWindowsTabletSupportWndProc);
if (!window) {
qCWarning(lcQpaTablet) << __FUNCTION__ << "Unable to create window for tablet.";
- return 0;
+ return nullptr;
}
LOGCONTEXT lcMine;
// build our context from the default context
@@ -255,7 +252,7 @@ QWindowsTabletSupport *QWindowsTabletSupport::create()
if (!context) {
qCDebug(lcQpaTablet) << __FUNCTION__ << "Unable to open tablet.";
DestroyWindow(window);
- return 0;
+ return nullptr;
}
// Set the size of the Packet Queue to the correct size
@@ -266,7 +263,7 @@ QWindowsTabletSupport *QWindowsTabletSupport::create()
qWarning("Unable to set queue size on tablet. The tablet will not work.");
QWindowsTabletSupport::m_winTab32DLL.wTClose(context);
DestroyWindow(window);
- return 0;
+ return nullptr;
} // cannot restore old size
} // cannot set
} // mismatch
@@ -285,7 +282,7 @@ unsigned QWindowsTabletSupport::options() const
QString QWindowsTabletSupport::description() const
{
- const unsigned size = m_winTab32DLL.wTInfo(WTI_INTERFACE, IFC_WINTABID, 0);
+ const unsigned size = m_winTab32DLL.wTInfo(WTI_INTERFACE, IFC_WINTABID, nullptr);
if (!size)
return QString();
QVarLengthArray<TCHAR> winTabId(size + 1);
diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.h b/src/plugins/platforms/windows/qwindowstabletsupport.h
index 9379dd72d6..d91701d6a5 100644
--- a/src/plugins/platforms/windows/qwindowstabletsupport.h
+++ b/src/plugins/platforms/windows/qwindowstabletsupport.h
@@ -43,8 +43,8 @@
#include "qtwindowsglobal.h"
#include <QtGui/qtguiglobal.h>
-#include <QtCore/QVector>
-#include <QtCore/QPointF>
+#include <QtCore/qvector.h>
+#include <QtCore/qpoint.h>
#include <wintab.h>
@@ -83,22 +83,23 @@ struct QWindowsWinTab32DLL
struct QWindowsTabletDeviceData
{
- QWindowsTabletDeviceData() : minPressure(0), maxPressure(0), minTanPressure(0),
- maxTanPressure(0), minX(0), maxX(0), minY(0), maxY(0), minZ(0), maxZ(0),
- uniqueId(0), currentDevice(0), currentPointerType(0) {}
-
QPointF scaleCoordinates(int coordX, int coordY,const QRect &targetArea) const;
qreal scalePressure(qreal p) const { return p / qreal(maxPressure - minPressure); }
qreal scaleTangentialPressure(qreal p) const { return p / qreal(maxTanPressure - minTanPressure); }
- int minPressure;
- int maxPressure;
- int minTanPressure;
- int maxTanPressure;
- int minX, maxX, minY, maxY, minZ, maxZ;
- qint64 uniqueId;
- int currentDevice;
- int currentPointerType;
+ int minPressure = 0;
+ int maxPressure = 0;
+ int minTanPressure = 0;
+ int maxTanPressure = 0;
+ int minX = 0;
+ int maxX = 0;
+ int minY = 0;
+ int maxY = 0;
+ int minZ = 0;
+ int maxZ = 0;
+ qint64 uniqueId = 0;
+ int currentDevice = 0;
+ int currentPointerType = 0;
};
#ifndef QT_NO_DEBUG_STREAM
@@ -145,10 +146,10 @@ private:
static QWindowsWinTab32DLL m_winTab32DLL;
const HWND m_window;
const HCTX m_context;
- int m_absoluteRange;
- bool m_tiltSupport;
+ int m_absoluteRange = 20;
+ bool m_tiltSupport = false;
QVector<QWindowsTabletDeviceData> m_devices;
- int m_currentDevice;
+ int m_currentDevice = -1;
Mode m_mode = PenMode;
State m_state = PenUp;
};
diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp
index 651c661d6b..4b70e915a8 100644
--- a/src/plugins/platforms/windows/qwindowstheme.cpp
+++ b/src/plugins/platforms/windows/qwindowstheme.cpp
@@ -59,20 +59,20 @@
#endif
#include <shellapi.h>
-#include <QtCore/QVariant>
-#include <QtCore/QCoreApplication>
-#include <QtCore/QDebug>
-#include <QtCore/QTextStream>
-#include <QtCore/QSysInfo>
-#include <QtCore/QCache>
-#include <QtCore/QThread>
-#include <QtCore/QMutex>
-#include <QtCore/QWaitCondition>
-#include <QtGui/QColor>
-#include <QtGui/QPalette>
-#include <QtGui/QGuiApplication>
-#include <QtGui/QPainter>
-#include <QtGui/QPixmapCache>
+#include <QtCore/qvariant.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qtextstream.h>
+#include <QtCore/qsysinfo.h>
+#include <QtCore/qcache.h>
+#include <QtCore/qthread.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qwaitcondition.h>
+#include <QtGui/qcolor.h>
+#include <QtGui/qpalette.h>
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qpainter.h>
+#include <QtGui/qpixmapcache.h>
#include <qpa/qwindowsysteminterface.h>
#include <QtThemeSupport/private/qabstractfileiconengine_p.h>
#include <QtFontDatabaseSupport/private/qwindowsfontdatabase_p.h>
@@ -107,7 +107,7 @@ static inline bool booleanSystemParametersInfo(UINT what, bool defaultValue)
{
BOOL result;
if (SystemParametersInfo(what, 0, &result, 0))
- return result ? true : false;
+ return result != FALSE;
return defaultValue;
}
@@ -121,9 +121,9 @@ static inline DWORD dWordSystemParametersInfo(UINT what, DWORD defaultValue)
static inline QColor mixColors(const QColor &c1, const QColor &c2)
{
- return QColor ((c1.red() + c2.red()) / 2,
- (c1.green() + c2.green()) / 2,
- (c1.blue() + c2.blue()) / 2);
+ return {(c1.red() + c2.red()) / 2,
+ (c1.green() + c2.green()) / 2,
+ (c1.blue() + c2.blue()) / 2};
}
static inline QColor getSysColor(int index)
@@ -507,9 +507,7 @@ void QWindowsTheme::refreshFonts()
if (!QGuiApplication::desktopSettingsAware())
return;
NONCLIENTMETRICS ncm;
- ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT);
- SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0);
-
+ QWindowsContext::nonClientMetrics(&ncm);
const QFont menuFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfMenuFont);
const QFont messageBoxFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfMessageFont);
const QFont statusFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfStatusFont);
diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h
index 237e8158fa..c132f20167 100644
--- a/src/plugins/platforms/windows/qwindowstheme.h
+++ b/src/plugins/platforms/windows/qwindowstheme.h
@@ -42,8 +42,8 @@
#include <qpa/qplatformtheme.h>
-#include <QtCore/QSharedPointer>
-#include <QtCore/QVariant>
+#include <QtCore/qsharedpointer.h>
+#include <QtCore/qvariant.h>
QT_BEGIN_NAMESPACE
@@ -51,9 +51,10 @@ class QWindow;
class QWindowsTheme : public QPlatformTheme
{
+ Q_DISABLE_COPY(QWindowsTheme)
public:
QWindowsTheme();
- ~QWindowsTheme();
+ ~QWindowsTheme() override;
static QWindowsTheme *instance() { return m_instance; }
diff --git a/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h b/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h
index 5601cc9305..731e4b5432 100644
--- a/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h
+++ b/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h
@@ -40,10 +40,10 @@
#ifndef QWINDOWSTHREADPOOLRUNNER_H
#define QWINDOWSTHREADPOOLRUNNER_H
-#include <QtCore/QMutex>
-#include <QtCore/QRunnable>
-#include <QtCore/QThreadPool>
-#include <QtCore/QWaitCondition>
+#include <QtCore/qmutex.h>
+#include <QtCore/qrunnable.h>
+#include <QtCore/qthreadpool.h>
+#include <QtCore/qwaitcondition.h>
QT_BEGIN_NAMESPACE
@@ -61,7 +61,7 @@ class QWindowsThreadPoolRunner
{
Q_DISABLE_COPY(QWindowsThreadPoolRunner)
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
template <class RunnableFunction> // nested class implementing QRunnable to execute a function.
class Runnable : public QRunnable
{
@@ -104,7 +104,7 @@ public:
private:
QMutex m_mutex;
QWaitCondition m_condition;
-#else // !QT_NO_THREAD
+#else // QT_CONFIG(thread)
public:
QWindowsThreadPoolRunner() {}
@@ -114,7 +114,7 @@ public:
f();
return true;
}
-#endif // QT_NO_THREAD
+#endif // QT_CONFIG(thread)
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp b/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp
index d81ee8ba29..7a01483abd 100644
--- a/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp
+++ b/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp
@@ -44,20 +44,9 @@ QT_BEGIN_NAMESPACE
QWindowsVulkanInstance::QWindowsVulkanInstance(QVulkanInstance *instance)
: m_instance(instance),
m_getPhysDevPresSupport(nullptr),
- m_createSurface(nullptr),
- m_destroySurface(nullptr)
+ m_createSurface(nullptr)
{
- if (qEnvironmentVariableIsSet("QT_VULKAN_LIB"))
- m_lib.setFileName(QString::fromUtf8(qgetenv("QT_VULKAN_LIB")));
- else
- m_lib.setFileName(QStringLiteral("vulkan-1"));
-
- if (!m_lib.load()) {
- qWarning("Failed to load %s: %s", qPrintable(m_lib.fileName()), qPrintable(m_lib.errorString()));
- return;
- }
-
- init(&m_lib);
+ loadVulkanLibrary(QStringLiteral("vulkan-1"));
}
void QWindowsVulkanInstance::createOrAdoptInstance()
@@ -73,10 +62,6 @@ void QWindowsVulkanInstance::createOrAdoptInstance()
qWarning("Failed to find vkGetPhysicalDeviceWin32PresentationSupportKHR");
}
-QWindowsVulkanInstance::~QWindowsVulkanInstance()
-{
-}
-
bool QWindowsVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice,
uint32_t queueFamilyIndex,
QWindow *window)
@@ -106,14 +91,6 @@ VkSurfaceKHR QWindowsVulkanInstance::createSurface(HWND win)
qWarning("Failed to find vkCreateWin32SurfaceKHR");
return surface;
}
- if (!m_destroySurface) {
- m_destroySurface = reinterpret_cast<PFN_vkDestroySurfaceKHR>(
- m_vkGetInstanceProcAddr(m_vkInst, "vkDestroySurfaceKHR"));
- }
- if (!m_destroySurface) {
- qWarning("Failed to find vkDestroySurfaceKHR");
- return surface;
- }
VkWin32SurfaceCreateInfoKHR surfaceInfo;
memset(&surfaceInfo, 0, sizeof(surfaceInfo));
@@ -127,10 +104,4 @@ VkSurfaceKHR QWindowsVulkanInstance::createSurface(HWND win)
return surface;
}
-void QWindowsVulkanInstance::destroySurface(VkSurfaceKHR surface)
-{
- if (m_destroySurface && surface)
- m_destroySurface(m_vkInst, surface, nullptr);
-}
-
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsvulkaninstance.h b/src/plugins/platforms/windows/qwindowsvulkaninstance.h
index ca60ab7627..3292137c39 100644
--- a/src/plugins/platforms/windows/qwindowsvulkaninstance.h
+++ b/src/plugins/platforms/windows/qwindowsvulkaninstance.h
@@ -47,28 +47,25 @@
#define VK_USE_PLATFORM_WIN32_KHR
#include <QtVulkanSupport/private/qbasicvulkanplatforminstance_p.h>
-#include <QLibrary>
+#include <QtCore/qlibrary.h>
QT_BEGIN_NAMESPACE
class QWindowsVulkanInstance : public QBasicPlatformVulkanInstance
{
+ Q_DISABLE_COPY(QWindowsVulkanInstance)
public:
QWindowsVulkanInstance(QVulkanInstance *instance);
- ~QWindowsVulkanInstance();
void createOrAdoptInstance() override;
bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) override;
VkSurfaceKHR createSurface(HWND win);
- void destroySurface(VkSurfaceKHR surface);
private:
QVulkanInstance *m_instance;
- QLibrary m_lib;
PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR m_getPhysDevPresSupport;
PFN_vkCreateWin32SurfaceKHR m_createSurface;
- PFN_vkDestroySurfaceKHR m_destroySurface;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index ca87f1b6a4..f340f16679 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -58,23 +58,25 @@
#else
# include "qwindowsopenglcontext.h"
#endif
+#include "qwindowsopengltester.h"
#ifdef QT_NO_CURSOR
# include "qwindowscursor.h"
#endif
-#include <QtGui/QGuiApplication>
-#include <QtGui/QScreen>
-#include <QtGui/QWindow>
-#include <QtGui/QRegion>
-#include <QtGui/QOpenGLContext>
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qscreen.h>
+#include <QtGui/qwindow.h>
+#include <QtGui/qregion.h>
+#include <QtGui/qopenglcontext.h>
#include <private/qsystemlibrary_p.h>
#include <private/qwindow_p.h> // QWINDOWSIZE_MAX
#include <private/qguiapplication_p.h>
#include <private/qhighdpiscaling_p.h>
#include <qpa/qwindowsysteminterface.h>
-#include <QtCore/QDebug>
-#include <QtCore/QLibraryInfo>
+#include <QtCore/qdebug.h>
+#include <QtCore/qlibraryinfo.h>
+#include <QtCore/qoperatingsystemversion.h>
#include <dwmapi.h>
@@ -422,6 +424,31 @@ static inline void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::Windo
}
/*!
+ Calculates the dimensions of the invisible borders within the
+ window frames in Windows 10, using an empirical expression that
+ reproduces the measured values for standard DPI settings.
+*/
+
+static QMargins invisibleMargins(QPoint screenPoint)
+{
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10) {
+ POINT pt = {screenPoint.x(), screenPoint.y()};
+ if (HMONITOR hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL)) {
+ if (QWindowsContext::shcoredll.isValid()) {
+ UINT dpiX;
+ UINT dpiY;
+ if (SUCCEEDED(QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, 0, &dpiX, &dpiY))) {
+ const qreal sc = (dpiX - 96) / 96.0;
+ const int gap = 7 + qRound(5*sc) - int(sc);
+ return QMargins(gap, 0, gap, gap);
+ }
+ }
+ }
+ }
+ return QMargins();
+}
+
+/*!
\class WindowCreationData
\brief Window creation code.
@@ -515,6 +542,84 @@ static inline void fixTopLevelWindowFlags(Qt::WindowFlags &flags)
flags |= Qt::FramelessWindowHint;
}
+static QScreen *screenForName(const QWindow *w, const QString &name)
+{
+ QScreen *winScreen = w ? w->screen() : QGuiApplication::primaryScreen();
+ if (winScreen && winScreen->name() != name) {
+ const auto screens = winScreen->virtualSiblings();
+ for (QScreen *screen : screens) {
+ if (screen->name() == name)
+ return screen;
+ }
+ }
+ return winScreen;
+}
+
+static QScreen *forcedScreenForGLWindow(const QWindow *w)
+{
+ const QString forceToScreen = GpuDescription::detect().gpuSuitableScreen;
+ return forceToScreen.isEmpty() ? nullptr : screenForName(w, forceToScreen);
+}
+
+static QPoint calcPosition(const QWindow *w, const QWindowCreationContextPtr &context, const QMargins &invMargins)
+{
+ const QPoint orgPos(context->frameX - invMargins.left(), context->frameY - invMargins.top());
+
+ if (!w || (!w->isTopLevel() && w->surfaceType() != QWindow::OpenGLSurface))
+ return orgPos;
+
+ // Workaround for QTBUG-50371
+ const QScreen *screenForGL = forcedScreenForGLWindow(w);
+ if (!screenForGL)
+ return orgPos;
+
+ const QPoint posFrame(context->frameX, context->frameY);
+ const QMargins margins = context->margins;
+ const QRect scrGeo = screenForGL->handle()->availableGeometry();
+
+ // Point is already in the required screen.
+ if (scrGeo.contains(orgPos))
+ return orgPos;
+
+ // If the visible part of the window is already in the
+ // required screen, just ignore the invisible offset.
+ if (scrGeo.contains(posFrame))
+ return posFrame;
+
+ // Find the original screen containing the coordinates.
+ const QList<QScreen *> screens = screenForGL->virtualSiblings();
+ const QScreen *orgScreen = nullptr;
+ for (QScreen *screen : screens) {
+ if (screen->handle()->availableGeometry().contains(posFrame)) {
+ orgScreen = screen;
+ break;
+ }
+ }
+ const QPoint ctPos = QPoint(qMax(scrGeo.left(), scrGeo.center().x()
+ + (margins.right() - margins.left() - context->frameWidth)/2),
+ qMax(scrGeo.top(), scrGeo.center().y()
+ + (margins.bottom() - margins.top() - context->frameHeight)/2));
+
+ // If initial coordinates were outside all screens, center the window on the required screen.
+ if (!orgScreen)
+ return ctPos;
+
+ const QRect orgGeo = orgScreen->handle()->availableGeometry();
+ const QRect orgFrame(QPoint(context->frameX, context->frameY),
+ QSize(context->frameWidth, context->frameHeight));
+
+ // Window would be centered on orgScreen. Center it on the required screen.
+ if (orgGeo.center() == (orgFrame - margins).center())
+ return ctPos;
+
+ // Transform the coordinates to map them into the required screen.
+ const QPoint newPos(scrGeo.left() + ((posFrame.x() - orgGeo.left()) * scrGeo.width()) / orgGeo.width(),
+ scrGeo.top() + ((posFrame.y() - orgGeo.top()) * scrGeo.height()) / orgGeo.height());
+ const QPoint newPosNoMargin(newPos.x() - invMargins.left(), newPos.y() - invMargins.top());
+
+ return scrGeo.contains(newPosNoMargin) ? newPosNoMargin : newPos;
+}
+
void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flagsIn,
unsigned creationFlags)
{
@@ -634,7 +739,7 @@ QWindowsWindowData
WindowData result;
result.flags = flags;
- const HINSTANCE appinst = (HINSTANCE)GetModuleHandle(0);
+ const auto appinst = reinterpret_cast<HINSTANCE>(GetModuleHandle(nullptr));
const QString windowClassName = QWindowsContext::instance()->registerWindowClass(w);
@@ -651,16 +756,23 @@ QWindowsWindowData
const QWindowCreationContextPtr context(new QWindowCreationContext(w, data.geometry, rect, data.customMargins, style, exStyle));
QWindowsContext::instance()->setWindowCreationContext(context);
+ QMargins invMargins = topLevel && !(result.flags & Qt::FramelessWindowHint) && QWindowsGeometryHint::positionIncludesFrame(w)
+ ? invisibleMargins(QPoint(context->frameX, context->frameY)) : QMargins();
+
qCDebug(lcQpaWindows).nospace()
<< "CreateWindowEx: " << w << " class=" << windowClassName << " title=" << title
<< '\n' << *this << "\nrequested: " << rect << ": "
<< context->frameWidth << 'x' << context->frameHeight
<< '+' << context->frameX << '+' << context->frameY
- << " custom margins: " << context->customMargins;
+ << " custom margins: " << context->customMargins
+ << " invisible margins: " << invMargins;
+
+
+ QPoint pos = calcPosition(w, context, invMargins);
result.hwnd = CreateWindowEx(exStyle, classNameUtf16, titleUtf16,
style,
- context->frameX, context->frameY,
+ pos.x(), pos.y(),
context->frameWidth, context->frameHeight,
parentHandle, NULL, appinst, NULL);
qCDebug(lcQpaWindows).nospace()
@@ -673,7 +785,7 @@ QWindowsWindowData
}
result.geometry = context->obtainedGeometry;
- result.frame = context->margins;
+ result.fullFrameMargins = context->margins;
result.embedded = embedded;
result.customMargins = context->customMargins;
@@ -887,7 +999,7 @@ QRect QWindowsBaseWindow::frameGeometry_sys() const
QRect QWindowsBaseWindow::geometry_sys() const
{
- return frameGeometry_sys().marginsRemoved(frameMargins());
+ return frameGeometry_sys().marginsRemoved(fullFrameMargins());
}
QMargins QWindowsBaseWindow::frameMargins_sys() const
@@ -1344,28 +1456,12 @@ bool QWindowsWindow::isEmbedded() const
QPoint QWindowsWindow::mapToGlobal(const QPoint &pos) const
{
- if (m_data.hwnd)
- return QWindowsGeometryHint::mapToGlobal(m_data.hwnd, pos);
- else
- return pos;
+ return m_data.hwnd ? QWindowsGeometryHint::mapToGlobal(m_data.hwnd, pos) : pos;
}
QPoint QWindowsWindow::mapFromGlobal(const QPoint &pos) const
{
- if (m_data.hwnd)
- return QWindowsGeometryHint::mapFromGlobal(m_data.hwnd, pos);
- else
- return pos;
-}
-
-static inline HWND transientParentHwnd(HWND hwnd)
-{
- if (GetAncestor(hwnd, GA_PARENT) == GetDesktopWindow()) {
- const HWND rootOwnerHwnd = GetAncestor(hwnd, GA_ROOTOWNER);
- if (rootOwnerHwnd != hwnd) // May return itself for toplevels.
- return rootOwnerHwnd;
- }
- return 0;
+ return m_data.hwnd ? QWindowsGeometryHint::mapFromGlobal(m_data.hwnd, pos) : pos;
}
// Update the transient parent for a toplevel window. The concept does not
@@ -1382,7 +1478,7 @@ void QWindowsWindow::updateTransientParent() const
if (window()->type() == Qt::Popup)
return; // QTBUG-34503, // a popup stays on top, no parent, see also WindowCreationData::fromWindow().
// Update transient parent.
- const HWND oldTransientParent = transientParentHwnd(m_data.hwnd);
+ const HWND oldTransientParent = GetWindow(m_data.hwnd, GW_OWNER);
HWND newTransientParent = 0;
if (const QWindow *tp = window()->transientParent())
if (const QWindowsWindow *tw = QWindowsWindow::windowsWindowOf(tp))
@@ -1560,7 +1656,7 @@ QRect QWindowsWindow::normalGeometry() const
const bool fakeFullScreen =
m_savedFrameGeometry.isValid() && (window()->windowStates() & Qt::WindowFullScreen);
const QRect frame = fakeFullScreen ? m_savedFrameGeometry : normalFrameGeometry(m_data.hwnd);
- const QMargins margins = fakeFullScreen ? QWindowsGeometryHint::frame(m_savedStyle, 0) : frameMargins();
+ const QMargins margins = fakeFullScreen ? QWindowsGeometryHint::frame(m_savedStyle, 0) : fullFrameMargins();
return frame.isValid() ? frame.marginsRemoved(margins) : frame;
}
@@ -1592,8 +1688,8 @@ void QWindowsWindow::setGeometry(const QRect &rectIn)
window()->metaObject()->className(), qPrintable(window()->objectName()),
m_data.geometry.width(), m_data.geometry.height(),
m_data.geometry.x(), m_data.geometry.y(),
- m_data.frame.left(), m_data.frame.top(),
- m_data.frame.right(), m_data.frame.bottom(),
+ m_data.fullFrameMargins.left(), m_data.fullFrameMargins.top(),
+ m_data.fullFrameMargins.right(), m_data.fullFrameMargins.bottom(),
m_data.customMargins.left(), m_data.customMargins.top(),
m_data.customMargins.right(), m_data.customMargins.bottom(),
window()->minimumWidth(), window()->minimumHeight(),
@@ -1685,7 +1781,7 @@ void QWindowsWindow::handleGeometryChange()
void QWindowsBaseWindow::setGeometry_sys(const QRect &rect) const
{
- const QMargins margins = frameMargins();
+ const QMargins margins = fullFrameMargins();
const QRect frameGeometry = rect + margins;
qCDebug(lcQpaWindows) << '>' << __FUNCTION__ << window()
@@ -1856,7 +1952,8 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state)
fireExpose(QRegion(0, 0, w->width(), w->height()));
exposeEventsSent = true;
}
- foreach (QWindow *child, QGuiApplication::allWindows()) {
+ const QWindowList allWindows = QGuiApplication::allWindows();
+ for (QWindow *child : allWindows) {
if (child != w && child->isVisible() && child->transientParent() == w) {
QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(child);
if (platformWindow && platformWindow->isLayered()) {
@@ -2048,7 +2145,7 @@ void QWindowsWindow::setExStyle(unsigned s) const
SetWindowLongPtr(m_data.hwnd, GWL_EXSTYLE, s);
}
-void QWindowsWindow::windowEvent(QEvent *event)
+bool QWindowsWindow::windowEvent(QEvent *event)
{
switch (event->type()) {
case QEvent::WindowBlocked: // Blocked by another modal window.
@@ -2064,6 +2161,8 @@ void QWindowsWindow::windowEvent(QEvent *event)
default:
break;
}
+
+ return QPlatformWindow::windowEvent(event);
}
void QWindowsWindow::propagateSizeHints()
@@ -2106,21 +2205,29 @@ bool QWindowsWindow::handleGeometryChangingMessage(MSG *message, const QWindow *
bool QWindowsWindow::handleGeometryChanging(MSG *message) const
{
- const QMargins margins = window()->isTopLevel() ? frameMargins() : QMargins();
+ const QMargins margins = window()->isTopLevel() ? fullFrameMargins() : QMargins();
return QWindowsWindow::handleGeometryChangingMessage(message, window(), margins);
}
-void QWindowsWindow::setFrameMargins(const QMargins &newMargins)
+void QWindowsWindow::setFullFrameMargins(const QMargins &newMargins)
{
- if (m_data.frame != newMargins) {
- qCDebug(lcQpaWindows) << __FUNCTION__ << window() << m_data.frame << "->" << newMargins;
- m_data.frame = newMargins;
+ if (m_data.fullFrameMargins != newMargins) {
+ qCDebug(lcQpaWindows) << __FUNCTION__ << window() << m_data.fullFrameMargins << "->" << newMargins;
+ m_data.fullFrameMargins = newMargins;
}
}
QMargins QWindowsWindow::frameMargins() const
{
- return m_data.frame;
+ QMargins result = fullFrameMargins();
+ if (isTopLevel() && !(m_data.flags & Qt::FramelessWindowHint))
+ result -= invisibleMargins(geometry().topLeft());
+ return result;
+}
+
+QMargins QWindowsWindow::fullFrameMargins() const
+{
+ return m_data.fullFrameMargins;
}
void QWindowsWindow::setOpacity(qreal level)
@@ -2174,7 +2281,7 @@ void QWindowsWindow::setMask(const QRegion &region)
// Mask is in client area coordinates, so offset it in case we have a frame
if (window()->isTopLevel()) {
- const QMargins margins = frameMargins();
+ const QMargins margins = fullFrameMargins();
OffsetRgn(winRegion, margins.left(), margins.top());
}
@@ -2309,6 +2416,13 @@ void QWindowsWindow::setFrameStrutEventsEnabled(bool enabled)
}
}
+static int getBorderWidth(const QPlatformScreen *screen)
+{
+ NONCLIENTMETRICS ncm;
+ QWindowsContext::nonClientMetricsForScreen(&ncm, screen);
+ return ncm.iBorderWidth + ncm.iPaddedBorderWidth + 2;
+}
+
void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const
{
// We don't apply the min/max size hint as we change the dpi, because we did not adjust the
@@ -2318,10 +2432,11 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const
hint.applyToMinMaxInfo(m_data.hwnd, mmi);
}
- if ((testFlag(WithinMaximize) || (window()->windowStates() & Qt::WindowMinimized))
- && (m_data.flags & Qt::FramelessWindowHint)) {
- // This block fixes QTBUG-8361: Frameless windows shouldn't cover the
- // taskbar when maximized
+ // This block fixes QTBUG-8361, QTBUG-4362: Frameless/title-less windows shouldn't cover the
+ // taskbar when maximized
+ if ((testFlag(WithinMaximize) || window()->windowStates().testFlag(Qt::WindowMinimized))
+ && (m_data.flags.testFlag(Qt::FramelessWindowHint)
+ || (m_data.flags.testFlag(Qt::CustomizeWindowHint) && !m_data.flags.testFlag(Qt::WindowTitleHint)))) {
const QScreen *screen = window()->screen();
// Documentation of MINMAXINFO states that it will only work for the primary screen
@@ -2335,6 +2450,14 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const
// If you have the taskbar on top, or on the left you don't want it at (0,0):
mmi->ptMaxPosition.x = availableGeometry.x();
mmi->ptMaxPosition.y = availableGeometry.y();
+ if (!m_data.flags.testFlag(Qt::FramelessWindowHint)) {
+ const int borderWidth = getBorderWidth(screen->handle());
+ mmi->ptMaxSize.x += borderWidth * 2;
+ mmi->ptMaxSize.y += borderWidth * 2;
+ mmi->ptMaxTrackSize = mmi->ptMaxSize;
+ mmi->ptMaxPosition.x -= borderWidth;
+ mmi->ptMaxPosition.y -= borderWidth;
+ }
} else if (!screen){
qWarning("window()->screen() returned a null screen");
}
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index 6d439bce1a..e8c30bd44b 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -41,7 +41,7 @@
#define QWINDOWSWINDOW_H
#include <QtCore/qt_windows.h>
-#include <QtCore/QPointer>
+#include <QtCore/qpointer.h>
#include "qwindowscursor.h"
#include <qpa/qplatformwindow.h>
@@ -59,7 +59,7 @@ class QDebug;
struct QWindowsGeometryHint
{
- QWindowsGeometryHint() {}
+ QWindowsGeometryHint() = default;
explicit QWindowsGeometryHint(const QWindow *w, const QMargins &customMargins);
static QMargins frame(DWORD style, DWORD exStyle);
static bool handleCalculateSize(const QMargins &customMargins, const MSG &msg, LRESULT *result);
@@ -108,8 +108,8 @@ struct QWindowsWindowData
{
Qt::WindowFlags flags;
QRect geometry;
- QMargins frame; // Do not use directly for windows, see FrameDirty.
- QMargins customMargins; // User-defined, additional frame for NCCALCSIZE
+ QMargins fullFrameMargins; // Do not use directly for windows, see FrameDirty.
+ QMargins customMargins; // User-defined, additional frame for NCCALCSIZE
HWND hwnd = 0;
bool embedded = false;
@@ -120,14 +120,16 @@ struct QWindowsWindowData
class QWindowsBaseWindow : public QPlatformWindow
{
+ Q_DISABLE_COPY(QWindowsBaseWindow)
public:
explicit QWindowsBaseWindow(QWindow *window) : QPlatformWindow(window) {}
WId winId() const override { return WId(handle()); }
QRect geometry() const override { return geometry_sys(); }
- QMargins frameMargins() const override { return frameMargins_sys(); }
+ QMargins frameMargins() const override { return fullFrameMargins(); }
QPoint mapToGlobal(const QPoint &pos) const override;
QPoint mapFromGlobal(const QPoint &pos) const override;
+ virtual QMargins fullFrameMargins() const { return frameMargins_sys(); }
using QPlatformWindow::screenForGeometry;
@@ -222,7 +224,7 @@ public:
};
QWindowsWindow(QWindow *window, const QWindowsWindowData &data);
- ~QWindowsWindow();
+ ~QWindowsWindow() override;
void initialize() override;
@@ -251,13 +253,14 @@ public:
void raise() override { raise_sys(); }
void lower() override { lower_sys(); }
- void windowEvent(QEvent *event) override;
+ bool windowEvent(QEvent *event) override;
void propagateSizeHints() override;
static bool handleGeometryChangingMessage(MSG *message, const QWindow *qWindow, const QMargins &marginsDp);
bool handleGeometryChanging(MSG *message) const;
QMargins frameMargins() const override;
- void setFrameMargins(const QMargins &newMargins);
+ QMargins fullFrameMargins() const override;
+ void setFullFrameMargins(const QMargins &newMargins);
void setOpacity(qreal level) override;
void setMask(const QRegion &region) override;
@@ -428,7 +431,7 @@ inline QWindowsWindow *QWindowsWindow::windowsWindowOf(const QWindow *w)
void *QWindowsWindow::userDataOf(HWND hwnd)
{
- return (void *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ return reinterpret_cast<void *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
}
void QWindowsWindow::setUserDataOf(HWND hwnd, void *ud)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
index 0f0f42fafe..85a931e015 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
@@ -37,16 +37,16 @@
**
****************************************************************************/
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiaaccessibility.h"
#include "qwindowsuiamainprovider.h"
#include "qwindowsuiautils.h"
-#include <QtGui/QAccessible>
-#include <QtGui/QWindow>
-#include <QtGui/QGuiApplication>
+#include <QtGui/qaccessible.h>
+#include <QtGui/qwindow.h>
+#include <QtGui/qguiapplication.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtCore/qt_windows.h>
#include <qpa/qplatformintegration.h>
@@ -104,19 +104,15 @@ void QWindowsUiaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event
return;
switch (event->type()) {
-
case QAccessible::Focus:
QWindowsUiaMainProvider::notifyFocusChange(event);
break;
-
case QAccessible::StateChanged:
QWindowsUiaMainProvider::notifyStateChange(static_cast<QAccessibleStateChangeEvent *>(event));
break;
-
case QAccessible::ValueChanged:
QWindowsUiaMainProvider::notifyValueChange(static_cast<QAccessibleValueChangeEvent *>(event));
break;
-
case QAccessible::TextAttributeChanged:
case QAccessible::TextColumnChanged:
case QAccessible::TextInserted:
@@ -126,7 +122,6 @@ void QWindowsUiaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event
case QAccessible::TextCaretMoved:
QWindowsUiaMainProvider::notifyTextChange(event);
break;
-
default:
break;
}
@@ -134,4 +129,4 @@ void QWindowsUiaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.h
index bbb81d596b..48b4f9fa6a 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.h
@@ -40,15 +40,15 @@
#ifndef QWINDOWSUIAACCESSIBILITY_H
#define QWINDOWSUIAACCESSIBILITY_H
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowscontext.h"
#include <qpa/qplatformaccessibility.h>
QT_BEGIN_NAMESPACE
-// Windows plataform accessibility implemented over UI Automation.
+// Windows platform accessibility implemented over UI Automation.
class QWindowsUiaAccessibility : public QPlatformAccessibility
{
public:
@@ -60,6 +60,6 @@ public:
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
#endif // QWINDOWSUIAACCESSIBILITY_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.cpp
index 1e1fc49c0f..53c647512a 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.cpp
@@ -37,17 +37,15 @@
**
****************************************************************************/
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiabaseprovider.h"
#include "qwindowsuiautils.h"
#include "qwindowscontext.h"
-#include <QtGui/QAccessible>
-#include <QtGui/QAccessibleInterface>
-#include <QtCore/QDebug>
-#include <QtCore/QString>
+#include <QtGui/qaccessible.h>
+#include <QtCore/qstring.h>
QT_BEGIN_NAMESPACE
@@ -78,4 +76,4 @@ QAccessible::Id QWindowsUiaBaseProvider::id() const
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h
index 3ae403e8c5..9caa7d6898 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h
@@ -40,12 +40,11 @@
#ifndef QWINDOWSUIABASEPROVIDER_H
#define QWINDOWSUIABASEPROVIDER_H
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
-#include <QtGui/QAccessible>
-#include <QtGui/QAccessibleInterface>
-#include <QtCore/QPointer>
+#include <QtGui/qaccessible.h>
+#include <QtCore/qpointer.h>
#include <qwindowscombase.h>
#include <QtWindowsUIAutomationSupport/private/qwindowsuiawrapper_p.h>
@@ -53,7 +52,6 @@
QT_BEGIN_NAMESPACE
class QAccessibleInterface;
-class QDebug;
// Base class for UI Automation providers.
class QWindowsUiaBaseProvider : public QObject
@@ -73,6 +71,6 @@ private:
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
#endif // QWINDOWSUIABASEPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.cpp
index e0502c00f3..93d360c40b 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.cpp
@@ -37,18 +37,17 @@
**
****************************************************************************/
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiagriditemprovider.h"
#include "qwindowsuiamainprovider.h"
#include "qwindowsuiautils.h"
#include "qwindowscontext.h"
-#include <QtGui/QAccessible>
-#include <QtGui/QAccessibleInterface>
-#include <QtCore/QDebug>
-#include <QtCore/QString>
+#include <QtGui/qaccessible.h>
+#include <QtCore/qloggingcategory.h>
+#include <QtCore/qstring.h>
QT_BEGIN_NAMESPACE
@@ -148,7 +147,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaGridItemProvider::get_ColumnSpan(int *pRetV
return S_OK;
}
-// Returns the provider for the cointaining table/tree.
+// Returns the provider for the containing table/tree.
HRESULT STDMETHODCALLTYPE QWindowsUiaGridItemProvider::get_ContainingGrid(IRawElementProviderSimple **pRetVal)
{
qCDebug(lcQpaUiAutomation) << __FUNCTION__;
@@ -173,4 +172,4 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaGridItemProvider::get_ContainingGrid(IRawEl
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h
index a93b50ef97..3d17056d38 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h
@@ -40,8 +40,8 @@
#ifndef QWINDOWSUIAGRIDITEMPROVIDER_H
#define QWINDOWSUIAGRIDITEMPROVIDER_H
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiabaseprovider.h"
@@ -57,15 +57,15 @@ public:
virtual ~QWindowsUiaGridItemProvider();
// IGridItemProvider
- HRESULT STDMETHODCALLTYPE get_Row(int *pRetVal);
- HRESULT STDMETHODCALLTYPE get_Column(int *pRetVal);
- HRESULT STDMETHODCALLTYPE get_RowSpan(int *pRetVal);
- HRESULT STDMETHODCALLTYPE get_ColumnSpan(int *pRetVal);
- HRESULT STDMETHODCALLTYPE get_ContainingGrid(IRawElementProviderSimple **pRetVal);
+ HRESULT STDMETHODCALLTYPE get_Row(int *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_Column(int *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_RowSpan(int *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_ColumnSpan(int *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_ContainingGrid(IRawElementProviderSimple **pRetVal) override;
};
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
#endif // QWINDOWSUIAGRIDITEMPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.cpp
index 65c2df703b..cce9d8143c 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.cpp
@@ -37,18 +37,17 @@
**
****************************************************************************/
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiagridprovider.h"
#include "qwindowsuiamainprovider.h"
#include "qwindowsuiautils.h"
#include "qwindowscontext.h"
-#include <QtGui/QAccessible>
-#include <QtGui/QAccessibleInterface>
-#include <QtCore/QDebug>
-#include <QtCore/QString>
+#include <QtGui/qaccessible.h>
+#include <QtCore/qloggingcategory.h>
+#include <QtCore/qstring.h>
QT_BEGIN_NAMESPACE
@@ -133,4 +132,4 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaGridProvider::get_ColumnCount(int *pRetVal)
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h
index 15521f98b3..b96fc1a93c 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h
@@ -40,8 +40,8 @@
#ifndef QWINDOWSUIAGRIDPROVIDER_H
#define QWINDOWSUIAGRIDPROVIDER_H
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiabaseprovider.h"
@@ -57,13 +57,13 @@ public:
virtual ~QWindowsUiaGridProvider();
// IGridProvider
- HRESULT STDMETHODCALLTYPE GetItem(int row, int column, IRawElementProviderSimple **pRetVal);
- HRESULT STDMETHODCALLTYPE get_RowCount(int *pRetVal);
- HRESULT STDMETHODCALLTYPE get_ColumnCount(int *pRetVal);
+ HRESULT STDMETHODCALLTYPE GetItem(int row, int column, IRawElementProviderSimple **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_RowCount(int *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_ColumnCount(int *pRetVal) override;
};
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
#endif // QWINDOWSUIAGRIDPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.cpp
index 2af883c4f6..d09770bc81 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.cpp
@@ -37,17 +37,16 @@
**
****************************************************************************/
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiainvokeprovider.h"
#include "qwindowsuiautils.h"
#include "qwindowscontext.h"
-#include <QtGui/QAccessible>
-#include <QtGui/QAccessibleInterface>
-#include <QtCore/QDebug>
-#include <QtCore/QString>
+#include <QtGui/qaccessible.h>
+#include <QtCore/qloggingcategory.h>
+#include <QtCore/qstring.h>
QT_BEGIN_NAMESPACE
@@ -81,4 +80,4 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaInvokeProvider::Invoke()
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h
index 2b8a646983..5fb509c5f3 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h
@@ -40,8 +40,8 @@
#ifndef QWINDOWSUIAINVOKEPROVIDER_H
#define QWINDOWSUIAINVOKEPROVIDER_H
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiabaseprovider.h"
@@ -57,11 +57,11 @@ public:
virtual ~QWindowsUiaInvokeProvider();
// IInvokeProvider
- HRESULT STDMETHODCALLTYPE Invoke();
+ HRESULT STDMETHODCALLTYPE Invoke() override;
};
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
#endif // QWINDOWSUIAINVOKEPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
index e36006c103..fad83fb165 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiamainprovider.h"
#include "qwindowsuiavalueprovider.h"
@@ -57,10 +57,10 @@
#include "qwindowsuiautils.h"
#include "qwindowsuiaprovidercache.h"
-#include <QtCore/QDebug>
-#include <QtGui/QAccessible>
-#include <QtGui/QGuiApplication>
-#include <QtGui/QWindow>
+#include <QtCore/qloggingcategory.h>
+#include <QtGui/qaccessible.h>
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qwindow.h>
#if !defined(Q_CC_BOR) && !defined (Q_CC_GNU)
#include <comdef.h>
@@ -391,9 +391,8 @@ HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pR
break;
case UIA_NamePropertyId: {
QString name = accessible->text(QAccessible::Name);
- if (name.isEmpty() && clientTopLevel) {
+ if (name.isEmpty() && clientTopLevel)
name = QCoreApplication::applicationName();
- }
setVariantString(name, pRetVal);
break;
}
@@ -658,4 +657,4 @@ HRESULT QWindowsUiaMainProvider::GetFocus(IRawElementProviderFragment **pRetVal)
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
index 893cbf7f8a..325d5b3de4 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
@@ -40,15 +40,15 @@
#ifndef QWINDOWSUIAMAINPROVIDER_H
#define QWINDOWSUIAMAINPROVIDER_H
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiabaseprovider.h"
-#include <QtCore/QPointer>
-#include <QtCore/QSharedPointer>
+#include <QtCore/qpointer.h>
+#include <QtCore/qsharedpointer.h>
#include <QtCore/qt_windows.h>
-#include <QtGui/QAccessible>
+#include <QtGui/qaccessible.h>
QT_BEGIN_NAMESPACE
@@ -71,27 +71,27 @@ public:
static void notifyTextChange(QAccessibleEvent *event);
// IUnknown
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface);
- ULONG STDMETHODCALLTYPE AddRef();
- ULONG STDMETHODCALLTYPE Release();
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface) override;
+ ULONG STDMETHODCALLTYPE AddRef() override;
+ ULONG STDMETHODCALLTYPE Release() override;
// IRawElementProviderSimple methods
- HRESULT STDMETHODCALLTYPE get_ProviderOptions(ProviderOptions *pRetVal);
- HRESULT STDMETHODCALLTYPE GetPatternProvider(PATTERNID idPattern, IUnknown **pRetVal);
- HRESULT STDMETHODCALLTYPE GetPropertyValue(PROPERTYID idProp, VARIANT *pRetVal);
- HRESULT STDMETHODCALLTYPE get_HostRawElementProvider(IRawElementProviderSimple **pRetVal);
+ HRESULT STDMETHODCALLTYPE get_ProviderOptions(ProviderOptions *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE GetPatternProvider(PATTERNID idPattern, IUnknown **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE GetPropertyValue(PROPERTYID idProp, VARIANT *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_HostRawElementProvider(IRawElementProviderSimple **pRetVal) override;
// IRawElementProviderFragment methods
- HRESULT STDMETHODCALLTYPE Navigate(NavigateDirection direction, IRawElementProviderFragment **pRetVal);
- HRESULT STDMETHODCALLTYPE GetRuntimeId(SAFEARRAY **pRetVal);
- HRESULT STDMETHODCALLTYPE get_BoundingRectangle(UiaRect *pRetVal);
- HRESULT STDMETHODCALLTYPE GetEmbeddedFragmentRoots(SAFEARRAY **pRetVal);
- HRESULT STDMETHODCALLTYPE SetFocus();
- HRESULT STDMETHODCALLTYPE get_FragmentRoot(IRawElementProviderFragmentRoot **pRetVal);
+ HRESULT STDMETHODCALLTYPE Navigate(NavigateDirection direction, IRawElementProviderFragment **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE GetRuntimeId(SAFEARRAY **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_BoundingRectangle(UiaRect *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE GetEmbeddedFragmentRoots(SAFEARRAY **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE SetFocus() override;
+ HRESULT STDMETHODCALLTYPE get_FragmentRoot(IRawElementProviderFragmentRoot **pRetVal) override;
// IRawElementProviderFragmentRoot methods
- HRESULT STDMETHODCALLTYPE ElementProviderFromPoint(double x, double y, IRawElementProviderFragment **pRetVal);
- HRESULT STDMETHODCALLTYPE GetFocus(IRawElementProviderFragment **pRetVal);
+ HRESULT STDMETHODCALLTYPE ElementProviderFromPoint(double x, double y, IRawElementProviderFragment **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE GetFocus(IRawElementProviderFragment **pRetVal) override;
private:
QString automationIdForAccessible(const QAccessibleInterface *accessible);
@@ -100,6 +100,6 @@ private:
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
#endif // QWINDOWSUIAMAINPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.cpp
index 9f0a1e126f..c55e827a46 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.cpp
@@ -37,15 +37,13 @@
**
****************************************************************************/
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiaprovidercache.h"
#include "qwindowsuiautils.h"
#include "qwindowscontext.h"
-#include <QtCore/QDebug>
-
QT_BEGIN_NAMESPACE
using namespace QWindowsUiAutomation;
@@ -66,7 +64,7 @@ QWindowsUiaProviderCache *QWindowsUiaProviderCache::instance()
// Returns the provider instance associated with the ID, or nullptr.
QWindowsUiaBaseProvider *QWindowsUiaProviderCache::providerForId(QAccessible::Id id) const
{
- return providerTable.value(id);
+ return m_providerTable.value(id);
}
// Inserts a provider in the cache and associates it with an accessibility ID.
@@ -74,8 +72,8 @@ void QWindowsUiaProviderCache::insert(QAccessible::Id id, QWindowsUiaBaseProvide
{
remove(id);
if (provider) {
- providerTable[id] = provider;
- inverseTable[provider] = id;
+ m_providerTable[id] = provider;
+ m_inverseTable[provider] = id;
// Connects the destroyed signal to our slot, to remove deleted objects from the cache.
QObject::connect(provider, &QObject::destroyed, this, &QWindowsUiaProviderCache::objectDestroyed);
}
@@ -87,20 +85,20 @@ void QWindowsUiaProviderCache::objectDestroyed(QObject *obj)
// We have to use the inverse table to map the object address back to its ID,
// since at this point (called from QObject destructor), it has already been
// partially destroyed and we cannot treat it as a provider.
- auto it = inverseTable.find(obj);
- if (it != inverseTable.end()) {
- providerTable.remove(*it);
- inverseTable.remove(obj);
+ auto it = m_inverseTable.find(obj);
+ if (it != m_inverseTable.end()) {
+ m_providerTable.remove(*it);
+ m_inverseTable.remove(obj);
}
}
// Removes a provider with a given id from the cache.
void QWindowsUiaProviderCache::remove(QAccessible::Id id)
{
- inverseTable.remove(providerTable.value(id));
- providerTable.remove(id);
+ m_inverseTable.remove(m_providerTable.value(id));
+ m_providerTable.remove(id);
}
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.h
index 7ad30ac39c..f66dc2c170 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.h
@@ -40,14 +40,13 @@
#ifndef QWINDOWSUIAPROVIDERCACHE_H
#define QWINDOWSUIAPROVIDERCACHE_H
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiabaseprovider.h"
-#include <QtCore/QHash>
-#include <QtGui/QAccessible>
-#include <QtGui/QAccessibleInterface>
+#include <QtCore/qhash.h>
+#include <QtGui/qaccessible.h>
QT_BEGIN_NAMESPACE
@@ -66,12 +65,12 @@ private Q_SLOTS:
void objectDestroyed(QObject *obj);
private:
- QHash<QAccessible::Id, QWindowsUiaBaseProvider *> providerTable;
- QHash<QObject *, QAccessible::Id> inverseTable;
+ QHash<QAccessible::Id, QWindowsUiaBaseProvider *> m_providerTable;
+ QHash<QObject *, QAccessible::Id> m_inverseTable;
};
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
#endif // QWINDOWSUIAPROVIDERCACHE_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.cpp
index 0cd09c3f0a..7c1827387a 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.cpp
@@ -37,17 +37,16 @@
**
****************************************************************************/
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiarangevalueprovider.h"
#include "qwindowsuiautils.h"
#include "qwindowscontext.h"
-#include <QtGui/QAccessible>
-#include <QtGui/QAccessibleInterface>
-#include <QtCore/QDebug>
-#include <QtCore/QString>
+#include <QtGui/qaccessible.h>
+#include <QtCore/qloggingcategory.h>
+#include <QtCore/qstring.h>
QT_BEGIN_NAMESPACE
@@ -187,4 +186,4 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaRangeValueProvider::get_SmallChange(double
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h
index f742ef99c2..c5e0a03ee5 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h
@@ -40,8 +40,8 @@
#ifndef QWINDOWSUIARANGEVALUEPROVIDER_H
#define QWINDOWSUIARANGEVALUEPROVIDER_H
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiabaseprovider.h"
@@ -57,17 +57,17 @@ public:
virtual ~QWindowsUiaRangeValueProvider();
// IRangeValueProvider
- HRESULT STDMETHODCALLTYPE SetValue(double val);
- HRESULT STDMETHODCALLTYPE get_Value(double *pRetVal);
- HRESULT STDMETHODCALLTYPE get_IsReadOnly(BOOL *pRetVal);
- HRESULT STDMETHODCALLTYPE get_Maximum(double *pRetVal);
- HRESULT STDMETHODCALLTYPE get_Minimum(double *pRetVal);
- HRESULT STDMETHODCALLTYPE get_LargeChange(double *pRetVal);
- HRESULT STDMETHODCALLTYPE get_SmallChange(double *pRetVal);
+ HRESULT STDMETHODCALLTYPE SetValue(double val) override;
+ HRESULT STDMETHODCALLTYPE get_Value(double *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_IsReadOnly(BOOL *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_Maximum(double *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_Minimum(double *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_LargeChange(double *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_SmallChange(double *pRetVal) override;
};
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
#endif // QWINDOWSUIARANGEVALUEPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp
index 45216a6d1c..a93a05c7bc 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp
@@ -37,18 +37,17 @@
**
****************************************************************************/
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiaselectionitemprovider.h"
#include "qwindowsuiamainprovider.h"
#include "qwindowsuiautils.h"
#include "qwindowscontext.h"
-#include <QtGui/QAccessible>
-#include <QtGui/QAccessibleInterface>
-#include <QtCore/QDebug>
-#include <QtCore/QString>
+#include <QtGui/qaccessible.h>
+#include <QtCore/qloggingcategory.h>
+#include <QtCore/qstring.h>
QT_BEGIN_NAMESPACE
@@ -198,4 +197,4 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::get_SelectionContain
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h
index 6a9b5b1e4b..1f2605188b 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h
@@ -40,8 +40,8 @@
#ifndef QWINDOWSUIASELECTIONITEMPROVIDER_H
#define QWINDOWSUIASELECTIONITEMPROVIDER_H
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiabaseprovider.h"
@@ -57,15 +57,15 @@ public:
virtual ~QWindowsUiaSelectionItemProvider();
// ISelectionItemProvider
- HRESULT STDMETHODCALLTYPE Select();
- HRESULT STDMETHODCALLTYPE AddToSelection();
- HRESULT STDMETHODCALLTYPE RemoveFromSelection();
- HRESULT STDMETHODCALLTYPE get_IsSelected(BOOL *pRetVal);
- HRESULT STDMETHODCALLTYPE get_SelectionContainer(IRawElementProviderSimple **pRetVal);
+ HRESULT STDMETHODCALLTYPE Select() override;
+ HRESULT STDMETHODCALLTYPE AddToSelection() override;
+ HRESULT STDMETHODCALLTYPE RemoveFromSelection() override;
+ HRESULT STDMETHODCALLTYPE get_IsSelected(BOOL *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_SelectionContainer(IRawElementProviderSimple **pRetVal) override;
};
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
#endif // QWINDOWSUIASELECTIONITEMPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp
index 1c06503bfc..3305e9c5c4 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp
@@ -37,19 +37,18 @@
**
****************************************************************************/
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiaselectionprovider.h"
#include "qwindowsuiamainprovider.h"
#include "qwindowsuiautils.h"
#include "qwindowscontext.h"
-#include <QtGui/QAccessible>
-#include <QtGui/QAccessibleInterface>
-#include <QtCore/QDebug>
-#include <QtCore/QString>
-#include <QList>
+#include <QtGui/qaccessible.h>
+#include <QtCore/qloggingcategory.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qlist.h>
QT_BEGIN_NAMESPACE
@@ -144,4 +143,4 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_IsSelectionRequired(
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h
index 5a07a82ac8..0376d25804 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h
@@ -40,8 +40,8 @@
#ifndef QWINDOWSUIASELECTIONPROVIDER_H
#define QWINDOWSUIASELECTIONPROVIDER_H
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiabaseprovider.h"
@@ -57,13 +57,13 @@ public:
virtual ~QWindowsUiaSelectionProvider();
// ISelectionProvider
- HRESULT STDMETHODCALLTYPE GetSelection(SAFEARRAY **pRetVal);
- HRESULT STDMETHODCALLTYPE get_CanSelectMultiple(BOOL *pRetVal);
- HRESULT STDMETHODCALLTYPE get_IsSelectionRequired(BOOL *pRetVal);
+ HRESULT STDMETHODCALLTYPE GetSelection(SAFEARRAY **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_CanSelectMultiple(BOOL *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_IsSelectionRequired(BOOL *pRetVal) override;
};
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
#endif // QWINDOWSUIASELECTIONPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp
index 3ea29fc86c..2a94012590 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp
@@ -37,18 +37,17 @@
**
****************************************************************************/
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiatableitemprovider.h"
#include "qwindowsuiamainprovider.h"
#include "qwindowsuiautils.h"
#include "qwindowscontext.h"
-#include <QtGui/QAccessible>
-#include <QtGui/QAccessibleInterface>
-#include <QtCore/QDebug>
-#include <QtCore/QString>
+#include <QtGui/qaccessible.h>
+#include <QtCore/qloggingcategory.h>
+#include <QtCore/qstring.h>
QT_BEGIN_NAMESPACE
@@ -126,4 +125,4 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTableItemProvider::GetColumnHeaderItems(SAF
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h
index 277884c980..bf4b52ee0b 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h
@@ -40,8 +40,8 @@
#ifndef QWINDOWSUIATABLEITEMPROVIDER_H
#define QWINDOWSUIATABLEITEMPROVIDER_H
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiabaseprovider.h"
@@ -57,12 +57,12 @@ public:
virtual ~QWindowsUiaTableItemProvider();
// ITableItemProvider
- HRESULT STDMETHODCALLTYPE GetRowHeaderItems(SAFEARRAY **pRetVal);
- HRESULT STDMETHODCALLTYPE GetColumnHeaderItems(SAFEARRAY **pRetVal);
+ HRESULT STDMETHODCALLTYPE GetRowHeaderItems(SAFEARRAY **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE GetColumnHeaderItems(SAFEARRAY **pRetVal) override;
};
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
#endif // QWINDOWSUIATABLEITEMPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.cpp
index f79a24536b..80086f1d4f 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.cpp
@@ -37,18 +37,17 @@
**
****************************************************************************/
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiatableprovider.h"
#include "qwindowsuiamainprovider.h"
#include "qwindowsuiautils.h"
#include "qwindowscontext.h"
-#include <QtGui/QAccessible>
-#include <QtGui/QAccessibleInterface>
-#include <QtCore/QDebug>
-#include <QtCore/QString>
+#include <QtGui/qaccessible.h>
+#include <QtCore/qloggingcategory.h>
+#include <QtCore/qstring.h>
QT_BEGIN_NAMESPACE
@@ -151,4 +150,4 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTableProvider::get_RowOrColumnMajor(enum Ro
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h
index 8cd0acda03..94c8ab93a7 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h
@@ -40,8 +40,8 @@
#ifndef QWINDOWSUIATABLEPROVIDER_H
#define QWINDOWSUIATABLEPROVIDER_H
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiabaseprovider.h"
@@ -57,13 +57,13 @@ public:
virtual ~QWindowsUiaTableProvider();
// ITableProvider
- HRESULT STDMETHODCALLTYPE GetRowHeaders(SAFEARRAY **pRetVal);
- HRESULT STDMETHODCALLTYPE GetColumnHeaders(SAFEARRAY **pRetVal);
- HRESULT STDMETHODCALLTYPE get_RowOrColumnMajor(enum RowOrColumnMajor *pRetVal);
+ HRESULT STDMETHODCALLTYPE GetRowHeaders(SAFEARRAY **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE GetColumnHeaders(SAFEARRAY **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_RowOrColumnMajor(enum RowOrColumnMajor *pRetVal) override;
};
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
#endif // QWINDOWSUIATABLEPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp
index e1622933af..9d1e72fb78 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp
@@ -37,17 +37,16 @@
**
****************************************************************************/
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiatextprovider.h"
#include "qwindowsuiautils.h"
#include "qwindowscontext.h"
-#include <QtGui/QAccessible>
-#include <QtGui/QAccessibleInterface>
-#include <QtCore/QDebug>
-#include <QtCore/QString>
+#include <QtGui/qaccessible.h>
+#include <QtCore/qloggingcategory.h>
+#include <QtCore/qstring.h>
QT_BEGIN_NAMESPACE
@@ -258,4 +257,4 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::GetCaretRange(BOOL *isActive,
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h
index a6d10027fa..a9be70fa16 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h
@@ -40,8 +40,8 @@
#ifndef QWINDOWSUIATEXTPROVIDER_H
#define QWINDOWSUIATEXTPROVIDER_H
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiabaseprovider.h"
#include "qwindowsuiatextrangeprovider.h"
@@ -58,23 +58,23 @@ public:
~QWindowsUiaTextProvider();
// IUnknown overrides
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface);
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface) override;
// ITextProvider
- HRESULT STDMETHODCALLTYPE GetSelection(SAFEARRAY **pRetVal);
- HRESULT STDMETHODCALLTYPE GetVisibleRanges(SAFEARRAY **pRetVal);
- HRESULT STDMETHODCALLTYPE RangeFromChild(IRawElementProviderSimple *childElement, ITextRangeProvider **pRetVal);
- HRESULT STDMETHODCALLTYPE RangeFromPoint(UiaPoint point, ITextRangeProvider **pRetVal);
- HRESULT STDMETHODCALLTYPE get_DocumentRange(ITextRangeProvider **pRetVal);
- HRESULT STDMETHODCALLTYPE get_SupportedTextSelection(SupportedTextSelection *pRetVal);
+ HRESULT STDMETHODCALLTYPE GetSelection(SAFEARRAY **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE GetVisibleRanges(SAFEARRAY **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE RangeFromChild(IRawElementProviderSimple *childElement, ITextRangeProvider **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE RangeFromPoint(UiaPoint point, ITextRangeProvider **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_DocumentRange(ITextRangeProvider **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_SupportedTextSelection(SupportedTextSelection *pRetVal) override;
// ITextProvider2
- HRESULT STDMETHODCALLTYPE RangeFromAnnotation(IRawElementProviderSimple *annotationElement, ITextRangeProvider **pRetVal);
- HRESULT STDMETHODCALLTYPE GetCaretRange(BOOL *isActive, ITextRangeProvider **pRetVal);
+ HRESULT STDMETHODCALLTYPE RangeFromAnnotation(IRawElementProviderSimple *annotationElement, ITextRangeProvider **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE GetCaretRange(BOOL *isActive, ITextRangeProvider **pRetVal) override;
};
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
#endif // QWINDOWSUIATEXTPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp
index dae7cbdd5f..1be186f6b3 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp
@@ -37,18 +37,17 @@
**
****************************************************************************/
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiatextrangeprovider.h"
#include "qwindowsuiamainprovider.h"
#include "qwindowsuiautils.h"
#include "qwindowscontext.h"
-#include <QtGui/QAccessible>
-#include <QtGui/QAccessibleInterface>
-#include <QtCore/QDebug>
-#include <QtCore/QString>
+#include <QtGui/qaccessible.h>
+#include <QtCore/qloggingcategory.h>
+#include <QtCore/qstring.h>
QT_BEGIN_NAMESPACE
@@ -238,12 +237,12 @@ HRESULT QWindowsUiaTextRangeProvider::GetBoundingRectangles(SAFEARRAY **pRetVal)
int endRange = qMin(end, m_endOffset);
if (startRange < endRange) {
// Calculates a bounding rectangle for the line and adds it to the list.
- QRect startRect = textInterface->characterRect(startRange);
- QRect endRect = textInterface->characterRect(endRange - 1);
- QRect lineRect(qMin(startRect.x(), endRect.x()),
- qMin(startRect.y(), endRect.y()),
- qMax(startRect.x() + startRect.width(), endRect.x() + endRect.width()) - qMin(startRect.x(), endRect.x()),
- qMax(startRect.y() + startRect.height(), endRect.y() + endRect.height()) - qMin(startRect.y(), endRect.y()));
+ const QRect startRect = textInterface->characterRect(startRange);
+ const QRect endRect = textInterface->characterRect(endRange - 1);
+ const QRect lineRect(qMin(startRect.x(), endRect.x()),
+ qMin(startRect.y(), endRect.y()),
+ qMax(startRect.x() + startRect.width(), endRect.x() + endRect.width()) - qMin(startRect.x(), endRect.x()),
+ qMax(startRect.y() + startRect.height(), endRect.y() + endRect.height()) - qMin(startRect.y(), endRect.y()));
rectList.append(lineRect);
}
if (end >= len) break;
@@ -519,9 +518,9 @@ HRESULT QWindowsUiaTextRangeProvider::Select()
}
// Not supported.
-HRESULT QWindowsUiaTextRangeProvider::FindTextW(BSTR /* text */, BOOL /* backward */,
- BOOL /* ignoreCase */,
- ITextRangeProvider **pRetVal)
+HRESULT QWindowsUiaTextRangeProvider::FindText(BSTR /* text */, BOOL /* backward */,
+ BOOL /* ignoreCase */,
+ ITextRangeProvider **pRetVal)
{
if (!pRetVal)
return E_INVALIDARG;
@@ -551,4 +550,4 @@ HRESULT QWindowsUiaTextRangeProvider::unselect()
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h
index 6fe6502c41..39b9069fc0 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h
@@ -40,8 +40,8 @@
#ifndef QWINDOWSUIATEXTRANGEPROVIDER_H
#define QWINDOWSUIATEXTRANGEPROVIDER_H
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiabaseprovider.h"
@@ -56,24 +56,25 @@ public:
explicit QWindowsUiaTextRangeProvider(QAccessible::Id id, int startOffset, int endOffset);
virtual ~QWindowsUiaTextRangeProvider();
- HRESULT STDMETHODCALLTYPE AddToSelection();
- HRESULT STDMETHODCALLTYPE Clone(ITextRangeProvider **pRetVal);
- HRESULT STDMETHODCALLTYPE Compare(ITextRangeProvider *range, BOOL *pRetVal);
- HRESULT STDMETHODCALLTYPE CompareEndpoints(TextPatternRangeEndpoint endpoint, ITextRangeProvider *targetRange, TextPatternRangeEndpoint targetEndpoint, int *pRetVal);
- HRESULT STDMETHODCALLTYPE ExpandToEnclosingUnit(TextUnit unit);
- HRESULT STDMETHODCALLTYPE FindAttribute(TEXTATTRIBUTEID attributeId, VARIANT val, BOOL backward, ITextRangeProvider **pRetVal);
- HRESULT STDMETHODCALLTYPE FindText(BSTR text, BOOL backward, BOOL ignoreCase, ITextRangeProvider **pRetVal);
- HRESULT STDMETHODCALLTYPE GetAttributeValue(TEXTATTRIBUTEID attributeId, VARIANT *pRetVal);
- HRESULT STDMETHODCALLTYPE GetBoundingRectangles(SAFEARRAY **pRetVal);
- HRESULT STDMETHODCALLTYPE GetChildren(SAFEARRAY **pRetVal);
- HRESULT STDMETHODCALLTYPE GetEnclosingElement(IRawElementProviderSimple **pRetVal);
- HRESULT STDMETHODCALLTYPE GetText(int maxLength, BSTR *pRetVal);
- HRESULT STDMETHODCALLTYPE Move(TextUnit unit, int count, int *pRetVal);
- HRESULT STDMETHODCALLTYPE MoveEndpointByRange(TextPatternRangeEndpoint endpoint, ITextRangeProvider *targetRange, TextPatternRangeEndpoint targetEndpoint);
- HRESULT STDMETHODCALLTYPE MoveEndpointByUnit(TextPatternRangeEndpoint endpoint, TextUnit unit, int count, int *pRetVal);
- HRESULT STDMETHODCALLTYPE RemoveFromSelection();
- HRESULT STDMETHODCALLTYPE ScrollIntoView(BOOL alignToTop);
- HRESULT STDMETHODCALLTYPE Select();
+ // ITextRangeProvider
+ HRESULT STDMETHODCALLTYPE AddToSelection() override;
+ HRESULT STDMETHODCALLTYPE Clone(ITextRangeProvider **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE Compare(ITextRangeProvider *range, BOOL *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE CompareEndpoints(TextPatternRangeEndpoint endpoint, ITextRangeProvider *targetRange, TextPatternRangeEndpoint targetEndpoint, int *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE ExpandToEnclosingUnit(TextUnit unit) override;
+ HRESULT STDMETHODCALLTYPE FindAttribute(TEXTATTRIBUTEID attributeId, VARIANT val, BOOL backward, ITextRangeProvider **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE FindText(BSTR text, BOOL backward, BOOL ignoreCase, ITextRangeProvider **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE GetAttributeValue(TEXTATTRIBUTEID attributeId, VARIANT *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE GetBoundingRectangles(SAFEARRAY **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE GetChildren(SAFEARRAY **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE GetEnclosingElement(IRawElementProviderSimple **pRetVal) override;
+ HRESULT STDMETHODCALLTYPE GetText(int maxLength, BSTR *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE Move(TextUnit unit, int count, int *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE MoveEndpointByRange(TextPatternRangeEndpoint endpoint, ITextRangeProvider *targetRange, TextPatternRangeEndpoint targetEndpoint) override;
+ HRESULT STDMETHODCALLTYPE MoveEndpointByUnit(TextPatternRangeEndpoint endpoint, TextUnit unit, int count, int *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE RemoveFromSelection() override;
+ HRESULT STDMETHODCALLTYPE ScrollIntoView(BOOL alignToTop) override;
+ HRESULT STDMETHODCALLTYPE Select() override;
private:
HRESULT unselect();
@@ -83,6 +84,6 @@ private:
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
#endif // QWINDOWSUIATEXTRANGEPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.cpp
index 01cdfd7e91..32445e4ffb 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.cpp
@@ -37,17 +37,16 @@
**
****************************************************************************/
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiatoggleprovider.h"
#include "qwindowsuiautils.h"
#include "qwindowscontext.h"
-#include <QtGui/QAccessible>
-#include <QtGui/QAccessibleInterface>
-#include <QtCore/QDebug>
-#include <QtCore/QString>
+#include <QtGui/qaccessible.h>
+#include <QtCore/qloggingcategory.h>
+#include <QtCore/qstring.h>
QT_BEGIN_NAMESPACE
@@ -102,4 +101,4 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaToggleProvider::get_ToggleState(ToggleState
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h
index a0df983e40..2bed6f7e36 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h
@@ -40,8 +40,8 @@
#ifndef QWINDOWSUIATOGGLEPROVIDER_H
#define QWINDOWSUIATOGGLEPROVIDER_H
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiabaseprovider.h"
@@ -57,12 +57,12 @@ public:
virtual ~QWindowsUiaToggleProvider();
// IToggleProvider
- HRESULT STDMETHODCALLTYPE Toggle();
- HRESULT STDMETHODCALLTYPE get_ToggleState(ToggleState *pRetVal);
+ HRESULT STDMETHODCALLTYPE Toggle() override;
+ HRESULT STDMETHODCALLTYPE get_ToggleState(ToggleState *pRetVal) override;
};
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
#endif // QWINDOWSUIATOGGLEPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp
index 89e5aad6a6..fbb5c3b9ec 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp
@@ -37,14 +37,14 @@
**
****************************************************************************/
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiautils.h"
#include "qwindowscontext.h"
#include "qwindowswindow.h"
-#include <QtGui/QWindow>
+#include <QtGui/qwindow.h>
#include <QtGui/private/qhighdpiscaling_p.h>
#include <cmath>
@@ -232,4 +232,4 @@ bool isTextUnitSeparator(TextUnit unit, const QChar &ch)
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.h
index 15f4d6e8ba..6a482f6c1c 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.h
@@ -40,16 +40,14 @@
#ifndef QWINDOWSUIAUTILS_H
#define QWINDOWSUIAUTILS_H
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
-#include <QtCore/QString>
+#include <QtCore/qstring.h>
#include <QtCore/qt_windows.h>
-#include <QtGui/QAccessible>
-#include <QtGui/QAccessibleInterface>
-#include <QtGui/QWindow>
-#include <QtCore/QDebug>
-#include <QtCore/QRect>
+#include <QtGui/qaccessible.h>
+#include <QtGui/qwindow.h>
+#include <QtCore/qrect.h>
#include <QtWindowsUIAutomationSupport/private/qwindowsuiawrapper_p.h>
QT_BEGIN_NAMESPACE
@@ -84,6 +82,6 @@ void setVariantString(const QString &value, VARIANT *variant);
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
#endif // QWINDOWSUIAUTILS_H
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.cpp
index ef7d564e22..8651bcff60 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.cpp
@@ -37,17 +37,16 @@
**
****************************************************************************/
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiavalueprovider.h"
#include "qwindowsuiautils.h"
#include "qwindowscontext.h"
-#include <QtGui/QAccessible>
-#include <QtGui/QAccessibleInterface>
-#include <QtCore/QDebug>
-#include <QtCore/QString>
+#include <QtGui/qaccessible.h>
+#include <QtCore/qloggingcategory.h>
+#include <QtCore/qstring.h>
QT_BEGIN_NAMESPACE
@@ -129,4 +128,4 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaValueProvider::get_Value(BSTR *pRetVal)
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h
index db54fc0a46..334a17e51d 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h
@@ -40,8 +40,8 @@
#ifndef QWINDOWSUIAVALUEPROVIDER_H
#define QWINDOWSUIAVALUEPROVIDER_H
-#include <QtCore/QtConfig>
-#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
#include "qwindowsuiabaseprovider.h"
@@ -58,13 +58,13 @@ public:
virtual ~QWindowsUiaValueProvider();
// IValueProvider
- HRESULT STDMETHODCALLTYPE SetValue(LPCWSTR val);
- HRESULT STDMETHODCALLTYPE get_IsReadOnly(BOOL *pRetVal);
- HRESULT STDMETHODCALLTYPE get_Value(BSTR *pRetVal);
+ HRESULT STDMETHODCALLTYPE SetValue(LPCWSTR val) override;
+ HRESULT STDMETHODCALLTYPE get_IsReadOnly(BOOL *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_Value(BSTR *pRetVal) override;
};
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
#endif // QWINDOWSUIAVALUEPROVIDER_H
diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri
index f4c396f7c5..db06a6a2a3 100644
--- a/src/plugins/platforms/windows/windows.pri
+++ b/src/plugins/platforms/windows/windows.pri
@@ -7,9 +7,9 @@ qtConfig(opengl):!qtConfig(opengles2):!qtConfig(dynamicgl): LIBS *= -lopengl32
mingw: LIBS *= -luuid
# For the dialog helpers:
-LIBS += -lshlwapi -lshell32 -ladvapi32
+LIBS += -lshlwapi -lshell32 -ladvapi32 -lwtsapi32
-DEFINES *= QT_NO_CAST_FROM_ASCII
+DEFINES *= QT_NO_CAST_FROM_ASCII QT_NO_FOREACH
SOURCES += \
$$PWD/qwindowswindow.cpp \
@@ -18,6 +18,7 @@ SOURCES += \
$$PWD/qwindowsscreen.cpp \
$$PWD/qwindowskeymapper.cpp \
$$PWD/qwindowsmousehandler.cpp \
+ $$PWD/qwindowspointerhandler.cpp \
$$PWD/qwindowsole.cpp \
$$PWD/qwindowsdropdataobject.cpp \
$$PWD/qwindowsmime.cpp \
@@ -40,6 +41,7 @@ HEADERS += \
$$PWD/qwindowsscreen.h \
$$PWD/qwindowskeymapper.h \
$$PWD/qwindowsmousehandler.h \
+ $$PWD/qwindowspointerhandler.h \
$$PWD/qtwindowsglobal.h \
$$PWD/qwindowsole.h \
$$PWD/qwindowsdropdataobject.h \
diff --git a/src/plugins/platforms/winrt/main.cpp b/src/plugins/platforms/winrt/main.cpp
index 222287b3ef..a37bd1e3d8 100644
--- a/src/plugins/platforms/winrt/main.cpp
+++ b/src/plugins/platforms/winrt/main.cpp
@@ -58,7 +58,7 @@ QPlatformIntegration *QWinRTIntegrationPlugin::create(const QString& system, con
if (!system.compare(QLatin1String("winrt"), Qt::CaseInsensitive))
return QWinRTIntegration::create();
- return 0;
+ return nullptr;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp
index 113886f9b4..c23d48b2dd 100644
--- a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp
+++ b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp
@@ -50,9 +50,6 @@
QT_BEGIN_NAMESPACE
-Q_LOGGING_CATEGORY(lcQpaBackingStore, "qt.qpa.backingstore")
-Q_LOGGING_CATEGORY(lcQpaBackingStoreVerbose, "qt.qpa.backingstore.verbose")
-
class QWinRTBackingStorePrivate
{
public:
@@ -68,7 +65,7 @@ QWinRTBackingStore::QWinRTBackingStore(QWindow *window)
: QPlatformBackingStore(window), d_ptr(new QWinRTBackingStorePrivate)
{
Q_D(QWinRTBackingStore);
- qCDebug(lcQpaBackingStore) << __FUNCTION__ << this << window;
+ qCInfo(lcQpaBackingStore) << __FUNCTION__ << this << window;
d->initialized = false;
d->screen = static_cast<QWinRTScreen*>(window->screen()->handle());
@@ -80,7 +77,7 @@ QWinRTBackingStore::QWinRTBackingStore(QWindow *window)
bool QWinRTBackingStore::initialize()
{
Q_D(QWinRTBackingStore);
- qCDebug(lcQpaBackingStoreVerbose) << __FUNCTION__ << d->initialized;
+ qCDebug(lcQpaBackingStore) << __FUNCTION__ << d->initialized;
if (d->initialized)
return true;
@@ -102,7 +99,7 @@ bool QWinRTBackingStore::initialize()
QWinRTBackingStore::~QWinRTBackingStore()
{
- qCDebug(lcQpaBackingStore) << __FUNCTION__ << this;
+ qCInfo(lcQpaBackingStore) << __FUNCTION__ << this;
}
QPaintDevice *QWinRTBackingStore::paintDevice()
@@ -116,16 +113,19 @@ void QWinRTBackingStore::flush(QWindow *window, const QRegion &region, const QPo
Q_D(QWinRTBackingStore);
Q_UNUSED(offset)
- qCDebug(lcQpaBackingStoreVerbose) << __FUNCTION__ << this << window << region;
+ qCDebug(lcQpaBackingStore) << __FUNCTION__ << this << window << region;
if (d->size.isEmpty())
return;
+ const QRect bounds = region.boundingRect() & d->paintDevice.rect();
+ if (bounds.isEmpty())
+ return;
+
const bool ok = d->context->makeCurrent(window);
if (!ok)
qWarning("unable to flush");
- const QRect bounds = region.boundingRect();
glBindTexture(GL_TEXTURE_2D, d->fbo->texture());
// TODO: when ANGLE GLES3 support is finished, use the glPixelStorei functions to minimize upload
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, bounds.y(), d->size.width(), bounds.height(),
@@ -151,7 +151,7 @@ void QWinRTBackingStore::resize(const QSize &size, const QRegion &staticContents
Q_D(QWinRTBackingStore);
Q_UNUSED(staticContents)
- qCDebug(lcQpaBackingStoreVerbose) << __FUNCTION__ << this << size;
+ qCDebug(lcQpaBackingStore) << __FUNCTION__ << this << size;
if (!initialize())
return;
@@ -182,14 +182,14 @@ QImage QWinRTBackingStore::toImage() const
void QWinRTBackingStore::beginPaint(const QRegion &region)
{
- qCDebug(lcQpaBackingStoreVerbose) << __FUNCTION__ << this << region;
+ qCDebug(lcQpaBackingStore) << __FUNCTION__ << this << region;
resize(window()->size(), region);
}
void QWinRTBackingStore::endPaint()
{
- qCDebug(lcQpaBackingStoreVerbose) << __FUNCTION__ << this;
+ qCDebug(lcQpaBackingStore) << __FUNCTION__ << this;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.h b/src/plugins/platforms/winrt/qwinrtbackingstore.h
index cd05faa63e..b62d340b82 100644
--- a/src/plugins/platforms/winrt/qwinrtbackingstore.h
+++ b/src/plugins/platforms/winrt/qwinrtbackingstore.h
@@ -47,9 +47,6 @@
QT_BEGIN_NAMESPACE
-Q_DECLARE_LOGGING_CATEGORY(lcQpaBackingStore)
-Q_DECLARE_LOGGING_CATEGORY(lcQpaBackingStoreVerbose)
-
class QWinRTScreen;
class QWinRTBackingStorePrivate;
@@ -57,7 +54,7 @@ class QWinRTBackingStore : public QPlatformBackingStore
{
public:
explicit QWinRTBackingStore(QWindow *window);
- ~QWinRTBackingStore();
+ ~QWinRTBackingStore() override;
QPaintDevice *paintDevice() override;
void beginPaint(const QRegion &) override;
void endPaint() override;
diff --git a/src/plugins/platforms/winrt/qwinrtcanvas.cpp b/src/plugins/platforms/winrt/qwinrtcanvas.cpp
new file mode 100644
index 0000000000..dd6b52d9cd
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrtcanvas.cpp
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwinrtcanvas.h"
+#include "uiautomation/qwinrtuiaaccessibility.h"
+#include "uiautomation/qwinrtuiamainprovider.h"
+#include "uiautomation/qwinrtuiametadatacache.h"
+#include "uiautomation/qwinrtuiautils.h"
+
+#include <QtCore/QLoggingCategory>
+#include <QtCore/qfunctions_winrt.h>
+
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::System;
+using namespace ABI::Windows::UI;
+using namespace ABI::Windows::UI::Core;
+using namespace ABI::Windows::UI::Xaml;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
+
+QT_BEGIN_NAMESPACE
+
+QWinRTCanvas::QWinRTCanvas(const std::function<QWindow*()> &delegateWindow)
+{
+ ComPtr<Xaml::Controls::ICanvasFactory> factory;
+ HRESULT hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Controls_Canvas).Get(), IID_PPV_ARGS(&factory));
+ Q_ASSERT_SUCCEEDED(hr);
+
+ hr = factory->CreateInstance(this, &m_base, &m_core);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ delegate = delegateWindow;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTCanvas::QueryInterface(REFIID iid, LPVOID *iface)
+{
+ if (!iface)
+ return E_POINTER;
+ *iface = nullptr;
+
+ if (iid == IID_IUnknown) {
+ *iface = static_cast<Xaml::IUIElementOverrides *>(this);
+ AddRef();
+ return S_OK;
+ } else if (iid == Xaml::IID_IUIElementOverrides) {
+ *iface = static_cast<Xaml::IUIElementOverrides *>(this);
+ AddRef();
+ return S_OK;
+ } else {
+ return m_base.CopyTo(iid, iface);
+ }
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTCanvas::GetIids(ULONG *iidCount, IID **iids)
+{
+ *iidCount = 0;
+ *iids = nullptr;
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTCanvas::GetRuntimeClassName(HSTRING *className)
+{
+ const wchar_t *name = L"QWinRTCanvas";
+ return ::WindowsCreateString(name, static_cast<UINT32>(::wcslen(name)), className);
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTCanvas::GetTrustLevel(TrustLevel *trustLevel)
+{
+ *trustLevel = TrustLevel::BaseTrust;
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTCanvas::OnCreateAutomationPeer(Xaml::Automation::Peers::IAutomationPeer **returnValue)
+{
+ if (!returnValue)
+ return E_INVALIDARG;
+ *returnValue = nullptr;
+
+ if (delegate) {
+ if (QWindow *window = delegate()) {
+ QWinRTUiaAccessibility::activate();
+ if (QAccessibleInterface *accessible = window->accessibleRoot()) {
+ QAccessible::Id accid = QWinRTUiAutomation::idForAccessible(accessible);
+ QWinRTUiaMetadataCache::instance()->load(accid);
+ if (ComPtr<QWinRTUiaMainProvider> provider = QWinRTUiaMainProvider::providerForAccessibleId(accid))
+ return provider.CopyTo(returnValue);
+ }
+ }
+ }
+ return m_base->OnCreateAutomationPeer(returnValue);
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTCanvas::OnDisconnectVisualChildren()
+{
+ return m_base->OnDisconnectVisualChildren();
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTCanvas::FindSubElementsForTouchTargeting(Point point, Rect boundingRect, IIterable<IIterable<ABI::Windows::Foundation::Point>*> **returnValue)
+{
+ return m_base->FindSubElementsForTouchTargeting(point, boundingRect, returnValue);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/winrt/qwinrtcanvas.h b/src/plugins/platforms/winrt/qwinrtcanvas.h
new file mode 100644
index 0000000000..bc3b708ac2
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrtcanvas.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTCANVAS_H
+#define QWINRTCANVAS_H
+
+#include <QtCore/qglobal.h>
+#include <QtGui/QWindow>
+
+#include <wrl.h>
+#include <windows.ui.xaml.h>
+#include <functional>
+
+QT_BEGIN_NAMESPACE
+
+class QWinRTCanvas:
+ public Microsoft::WRL::RuntimeClass<ABI::Windows::UI::Xaml::IUIElementOverrides>
+{
+public:
+ QWinRTCanvas(const std::function<QWindow*()> &delegateWindow);
+ ~QWinRTCanvas() override = default;
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *iface) override;
+ HRESULT STDMETHODCALLTYPE GetIids(ULONG *iidCount, IID **iids) override;
+ HRESULT STDMETHODCALLTYPE GetRuntimeClassName(HSTRING *className) override;
+ HRESULT STDMETHODCALLTYPE GetTrustLevel(TrustLevel *trustLevel) override;
+ HRESULT STDMETHODCALLTYPE OnCreateAutomationPeer(ABI::Windows::UI::Xaml::Automation::Peers::IAutomationPeer **returnValue) override;
+ HRESULT STDMETHODCALLTYPE OnDisconnectVisualChildren() override;
+ HRESULT STDMETHODCALLTYPE FindSubElementsForTouchTargeting(ABI::Windows::Foundation::Point point, ABI::Windows::Foundation::Rect boundingRect, ABI::Windows::Foundation::Collections::IIterable<ABI::Windows::Foundation::Collections::IIterable<ABI::Windows::Foundation::Point>*> **returnValue) override;
+
+private:
+ Microsoft::WRL::ComPtr<ABI::Windows::UI::Xaml::IUIElementOverrides> m_base;
+ Microsoft::WRL::ComPtr<ABI::Windows::UI::Xaml::Controls::ICanvas> m_core;
+ std::function<QWindow*()> delegate;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINRTCANVAS_H
diff --git a/src/plugins/platforms/winrt/qwinrtclipboard.cpp b/src/plugins/platforms/winrt/qwinrtclipboard.cpp
index 05c34b82f8..fd0ed8aed2 100644
--- a/src/plugins/platforms/winrt/qwinrtclipboard.cpp
+++ b/src/plugins/platforms/winrt/qwinrtclipboard.cpp
@@ -99,7 +99,7 @@ QMimeData *QWinRTClipboard::mimeData(QClipboard::Mode mode)
quint32 size;
const wchar_t *textStr = result.GetRawBuffer(&size);
- QString text = QString::fromWCharArray(textStr, size);
+ QString text = QString::fromWCharArray(textStr, int(size));
text.replace(QLatin1String("\r\n"), QLatin1String("\n"));
if (m_mimeData) {
@@ -161,7 +161,8 @@ void QWinRTClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
&package);
const QString nativeString = convertToWindowsLineEnding(text);
- HStringReference textRef(reinterpret_cast<LPCWSTR>(nativeString.utf16()), nativeString.length());
+ HStringReference textRef(reinterpret_cast<LPCWSTR>(nativeString.utf16()),
+ uint(nativeString.length()));
hr = package->SetText(textRef.Get());
RETURN_HR_IF_FAILED("Could not set text to clipboard data package.");
diff --git a/src/plugins/platforms/winrt/qwinrtcursor.cpp b/src/plugins/platforms/winrt/qwinrtcursor.cpp
index 3c918df935..180905945b 100644
--- a/src/plugins/platforms/winrt/qwinrtcursor.cpp
+++ b/src/plugins/platforms/winrt/qwinrtcursor.cpp
@@ -56,6 +56,11 @@ using namespace ABI::Windows::Foundation;
QT_BEGIN_NAMESPACE
+static inline bool qIsPointInRect(const Point &p, const Rect &r)
+{
+ return (p.X >= r.X && p.Y >= r.Y && p.X < r.X + r.Width && p.Y < r.Y + r.Height);
+}
+
class QWinRTCursorPrivate
{
public:
@@ -73,10 +78,6 @@ QWinRTCursor::QWinRTCursor()
Q_ASSERT_SUCCEEDED(hr);
}
-QWinRTCursor::~QWinRTCursor()
-{
-}
-
#ifndef QT_NO_CURSOR
void QWinRTCursor::changeCursor(QCursor *windowCursor, QWindow *window)
{
@@ -169,14 +170,60 @@ QPoint QWinRTCursor::pos() const
ICoreWindow *coreWindow = screen->coreWindow();
Q_ASSERT(coreWindow);
Point point;
- HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([coreWindow, &point]() {
- return coreWindow->get_PointerPosition(&point);
+ Rect bounds;
+ HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([coreWindow, &point, &bounds]() {
+ HRESULT hr = coreWindow->get_PointerPosition(&point);
+ RETURN_HR_IF_FAILED("Failed to obtain pointer position.");
+ hr = coreWindow->get_Bounds(&bounds);
+ RETURN_HR_IF_FAILED("Failed to obtain window bounds.");
+ return hr;
});
Q_ASSERT_SUCCEEDED(hr);
- const QPoint position = QPoint(point.X, point.Y) * screen->scaleFactor();
+ QPointF position(qreal(point.X), qreal(point.Y));
// If no cursor get_PointerPosition returns SHRT_MIN for x and y
- return position.x() == SHRT_MIN && position.y() == SHRT_MIN || FAILED(hr) ? QPointF(Q_INFINITY, Q_INFINITY).toPoint()
- : position;
+ if ((int(position.x()) == SHRT_MIN && int(position.y()) == SHRT_MIN)
+ || FAILED(hr))
+ return QPointF(Q_INFINITY, Q_INFINITY).toPoint();
+ position.rx() -= qreal(bounds.X);
+ position.ry() -= qreal(bounds.Y);
+ position *= screen->scaleFactor();
+ return position.toPoint();
+}
+
+void QWinRTCursor::setPos(const QPoint &pos)
+{
+ QWinRTScreen *screen = static_cast<QWinRTScreen *>(QGuiApplication::primaryScreen()->handle());
+ Q_ASSERT(screen);
+ ComPtr<ICoreWindow> coreWindow = screen->coreWindow();
+ Q_ASSERT(coreWindow);
+ const QPointF scaledPos = QPointF(pos) / screen->scaleFactor();
+ QWinRTScreen::MousePositionTransition t;
+ HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([coreWindow, scaledPos, &t]() {
+ ComPtr<ICoreWindow2> coreWindow2;
+ HRESULT hr = coreWindow.As(&coreWindow2);
+ RETURN_HR_IF_FAILED("Failed to cast core window.");
+ Rect bounds;
+ hr = coreWindow->get_Bounds(&bounds);
+ RETURN_HR_IF_FAILED("Failed to obtain window bounds.");
+ Point mousePos;
+ hr = coreWindow->get_PointerPosition(&mousePos);
+ RETURN_HR_IF_FAILED("Failed to obtain mouse position.");
+ const Point p = { FLOAT(scaledPos.x()) + bounds.X,
+ FLOAT(scaledPos.y()) + bounds.Y };
+ const bool wasInWindow = qIsPointInRect(mousePos, bounds);
+ const bool willBeInWindow = qIsPointInRect(p, bounds);
+ if (wasInWindow && willBeInWindow)
+ t = QWinRTScreen::MousePositionTransition::StayedIn;
+ else if (wasInWindow && !willBeInWindow)
+ t = QWinRTScreen::MousePositionTransition::MovedOut;
+ else if (!wasInWindow && willBeInWindow)
+ t = QWinRTScreen::MousePositionTransition::MovedIn;
+ else
+ t = QWinRTScreen::MousePositionTransition::StayedOut;
+ return coreWindow2->put_PointerPosition(p);
+ });
+ RETURN_VOID_IF_FAILED("Failed to set cursor position");
+ screen->emulateMouseMove(scaledPos, t);
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtcursor.h b/src/plugins/platforms/winrt/qwinrtcursor.h
index 7f579f1531..eca3d8c7ca 100644
--- a/src/plugins/platforms/winrt/qwinrtcursor.h
+++ b/src/plugins/platforms/winrt/qwinrtcursor.h
@@ -49,11 +49,12 @@ class QWinRTCursor : public QPlatformCursor
{
public:
explicit QWinRTCursor();
- ~QWinRTCursor();
+ ~QWinRTCursor() override = default;
#ifndef QT_NO_CURSOR
void changeCursor(QCursor * windowCursor, QWindow *window) override;
#endif
QPoint pos() const override;
+ void setPos(const QPoint &pos) override;
private:
QScopedPointer<QWinRTCursorPrivate> d_ptr;
diff --git a/src/plugins/platforms/winrt/qwinrtdrag.cpp b/src/plugins/platforms/winrt/qwinrtdrag.cpp
index 0c918230b3..3ed4cd692d 100644
--- a/src/plugins/platforms/winrt/qwinrtdrag.cpp
+++ b/src/plugins/platforms/winrt/qwinrtdrag.cpp
@@ -81,7 +81,7 @@ ComPtr<IBuffer> createIBufferFromData(const char *data, qint32 size)
}
ComPtr<IBuffer> buffer;
- const UINT32 length = size;
+ const UINT32 length = UINT32(size);
hr = bufferFactory->Create(length, &buffer);
Q_ASSERT_SUCCEEDED(hr);
hr = buffer->put_Length(length);
@@ -118,13 +118,13 @@ inline QString hStringToQString(const HString &hString)
{
quint32 l;
const wchar_t *raw = hString.GetRawBuffer(&l);
- return (QString::fromWCharArray(raw, l));
+ return (QString::fromWCharArray(raw, int(l)));
}
inline HString qStringToHString(const QString &qString)
{
HString h;
- h.Set(reinterpret_cast<const wchar_t*>(qString.utf16()), qString.size());
+ h.Set(reinterpret_cast<const wchar_t*>(qString.utf16()), uint(qString.size()));
return h;
}
@@ -184,10 +184,6 @@ QWinRTInternalMimeData::QWinRTInternalMimeData()
}
}
-QWinRTInternalMimeData::~QWinRTInternalMimeData()
-{
-}
-
bool QWinRTInternalMimeData::hasFormat_sys(const QString &mimetype) const
{
qCDebug(lcQpaMime) << __FUNCTION__ << mimetype;
@@ -311,7 +307,7 @@ QVariant QWinRTInternalMimeData::retrieveData_sys(const QString &mimetype, QVari
ComPtr<IAsyncOperation<IInspectable*>> op;
ComPtr<IInspectable> res;
HString type;
- type.Set(reinterpret_cast<const wchar_t*>(mimetype.utf16()), mimetype.size());
+ type.Set(reinterpret_cast<const wchar_t*>(mimetype.utf16()), uint(mimetype.size()));
hr = dataView->GetDataAsync(type.Get(), &op);
RETURN_OK_IF_FAILED("Could not query custom drag data.");
hr = QWinRTFunctions::await(op, res.GetAddressOf());
@@ -434,7 +430,7 @@ QVariant QWinRTInternalMimeData::retrieveData_sys(const QString &mimetype, QVari
IID_PPV_ARGS(&bufferFactory));
Q_ASSERT_SUCCEEDED(hr);
- UINT32 length = qBound(quint64(0), quint64(size), quint64(UINT_MAX));
+ UINT32 length = UINT32(qBound(quint64(0), quint64(size), quint64(UINT_MAX)));
ComPtr<IBuffer> buffer;
hr = bufferFactory->Create(length, &buffer);
Q_ASSERT_SUCCEEDED(hr);
@@ -452,7 +448,7 @@ QVariant QWinRTInternalMimeData::retrieveData_sys(const QString &mimetype, QVari
byte *bytes;
hr = byteArrayAccess->Buffer(&bytes);
- QByteArray array((char *)bytes, length);
+ QByteArray array((char *)bytes, int(length));
result.setValue(array);
return S_OK;
}
@@ -559,7 +555,7 @@ extern ComPtr<ABI::Windows::UI::Input::IPointerPoint> qt_winrt_lastPointerPoint;
QWinRTDrag::QWinRTDrag()
: QPlatformDrag()
- , m_dragTarget(0)
+ , m_dragTarget(nullptr)
{
qCDebug(lcQpaMime) << __FUNCTION__;
m_enter = new Q_INST_DRAGHANDLER(Enter);
@@ -612,7 +608,7 @@ Qt::DropAction QWinRTDrag::drag(QDrag *drag)
ComPtr<IAsyncOperation<ABI::Windows::ApplicationModel::DataTransfer::DataPackageOperation>> op;
EventRegistrationToken startingToken;
- hr = QEventDispatcherWinRT::runOnXamlThread([drag, &op, &hr, elem3, &startingToken, this]() {
+ hr = QEventDispatcherWinRT::runOnXamlThread([drag, &op, &hr, elem3, &startingToken]() {
hr = elem3->put_CanDrag(true);
Q_ASSERT_SUCCEEDED(hr);
@@ -660,7 +656,8 @@ Qt::DropAction QWinRTDrag::drag(QDrag *drag)
const QImage image = image2.convertToFormat(QImage::Format_ARGB32);
if (!image.isNull()) {
// Create IBuffer containing image
- ComPtr<IBuffer> imageBuffer = createIBufferFromData(reinterpret_cast<const char*>(image.bits()), image.byteCount());
+ ComPtr<IBuffer> imageBuffer
+ = createIBufferFromData(reinterpret_cast<const char*>(image.bits()), int(image.sizeInBytes()));
ComPtr<ISoftwareBitmapFactory> bitmapFactory;
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Graphics_Imaging_SoftwareBitmap).Get(),
@@ -697,7 +694,7 @@ Qt::DropAction QWinRTDrag::drag(QDrag *drag)
hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_InMemoryRandomAccessStream).Get(), &ras);
Q_ASSERT_SUCCEEDED(hr);
- hr = ras->put_Size(data.size());
+ hr = ras->put_Size(UINT64(data.size()));
ComPtr<IOutputStream> outputStream;
hr = ras->GetOutputStreamAt(0, &outputStream);
Q_ASSERT_SUCCEEDED(hr);
@@ -802,7 +799,7 @@ void QWinRTDrag::handleNativeDragEvent(IInspectable *sender, ABI::Windows::UI::X
Point relativePoint;
hr = e->GetPosition(m_ui.Get(), &relativePoint);
RETURN_VOID_IF_FAILED("Could not query drag position.");
- const QPoint p(relativePoint.X, relativePoint.Y);
+ const QPoint p(int(relativePoint.X), int(relativePoint.Y));
ComPtr<IDragEventArgs2> e2;
hr = e->QueryInterface(IID_PPV_ARGS(&e2));
diff --git a/src/plugins/platforms/winrt/qwinrtdrag.h b/src/plugins/platforms/winrt/qwinrtdrag.h
index 3868c9f015..ab57999bba 100644
--- a/src/plugins/platforms/winrt/qwinrtdrag.h
+++ b/src/plugins/platforms/winrt/qwinrtdrag.h
@@ -77,7 +77,7 @@ class QWinRTInternalMimeData;
class QWinRTInternalMimeData : public QInternalMimeData {
public:
QWinRTInternalMimeData();
- virtual ~QWinRTInternalMimeData();
+ ~QWinRTInternalMimeData() override = default;
bool hasFormat_sys(const QString &mimetype) const override;
QStringList formats_sys() const override;
@@ -92,7 +92,7 @@ private:
class QWinRTDrag : public QPlatformDrag {
public:
QWinRTDrag();
- virtual ~QWinRTDrag();
+ ~QWinRTDrag() override;
static QWinRTDrag *instance();
Qt::DropAction drag(QDrag *) override;
diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.h b/src/plugins/platforms/winrt/qwinrteglcontext.h
index 325dc82c40..8dbd0fc7d0 100644
--- a/src/plugins/platforms/winrt/qwinrteglcontext.h
+++ b/src/plugins/platforms/winrt/qwinrteglcontext.h
@@ -50,7 +50,7 @@ class QWinRTEGLContext : public QPlatformOpenGLContext
{
public:
explicit QWinRTEGLContext(QOpenGLContext *context);
- ~QWinRTEGLContext();
+ ~QWinRTEGLContext() override;
void initialize() override;
diff --git a/src/plugins/platforms/winrt/qwinrteventdispatcher.h b/src/plugins/platforms/winrt/qwinrteventdispatcher.h
index 4c5c19c6b0..61c824f0a9 100644
--- a/src/plugins/platforms/winrt/qwinrteventdispatcher.h
+++ b/src/plugins/platforms/winrt/qwinrteventdispatcher.h
@@ -48,7 +48,7 @@ class QWinRTEventDispatcher : public QEventDispatcherWinRT
{
Q_OBJECT
public:
- explicit QWinRTEventDispatcher(QObject *parent = 0);
+ explicit QWinRTEventDispatcher(QObject *parent = nullptr);
protected:
bool hasPendingEvents() override;
diff --git a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp
index 3c90334c8c..114d6dacd8 100644
--- a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp
+++ b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp
@@ -51,7 +51,7 @@
#include <wrl.h>
#include <windows.foundation.h>
#include <windows.storage.pickers.h>
-#include <Windows.ApplicationModel.activation.h>
+#include <Windows.Applicationmodel.Activation.h>
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
@@ -73,12 +73,12 @@ class WindowsStringVector : public RuntimeClass<IVector<HSTRING>>
public:
HRESULT __stdcall GetAt(quint32 index, HSTRING *item)
{
- *item = impl.at(index);
+ *item = impl.at(int(index));
return S_OK;
}
HRESULT __stdcall get_Size(quint32 *size)
{
- *size = impl.size();
+ *size = quint32(impl.size());
return S_OK;
}
HRESULT __stdcall GetView(IVectorView<HSTRING> **view)
@@ -108,7 +108,7 @@ public:
HRESULT hr = WindowsDuplicateString(item, &newItem);
if (FAILED(hr))
return hr;
- impl[index] = newItem;
+ impl[int(index)] = newItem;
return S_OK;
}
HRESULT __stdcall InsertAt(quint32 index, HSTRING item)
@@ -117,12 +117,12 @@ public:
HRESULT hr = WindowsDuplicateString(item, &newItem);
if (FAILED(hr))
return hr;
- impl.insert(index, newItem);
+ impl.insert(int(index), newItem);
return S_OK;
}
HRESULT __stdcall RemoveAt(quint32 index)
{
- WindowsDeleteString(impl.takeAt(index));
+ WindowsDeleteString(impl.takeAt(int(index)));
return S_OK;
}
HRESULT __stdcall Append(HSTRING item)
@@ -164,7 +164,7 @@ static bool initializePicker(HSTRING runtimeId, T **picker, const QSharedPointer
if (options->isLabelExplicitlySet(QFileDialogOptions::Accept)) {
const QString labelText = options->labelText(QFileDialogOptions::Accept);
HStringReference labelTextRef(reinterpret_cast<const wchar_t *>(labelText.utf16()),
- labelText.length());
+ uint(labelText.length()));
hr = (*picker)->put_CommitButtonText(labelTextRef.Get());
RETURN_FALSE_IF_FAILED("Failed to set commit button text");
}
@@ -188,7 +188,7 @@ static bool initializeOpenPickerOptions(T *picker, const QSharedPointer<QFileDia
// Remove leading star
const int offset = (filter.length() > 1 && filter.startsWith(QLatin1Char('*'))) ? 1 : 0;
HStringReference filterRef(reinterpret_cast<const wchar_t *>(filter.utf16() + offset),
- filter.length() - offset);
+ uint(filter.length() - offset));
hr = filters->Append(filterRef.Get());
if (FAILED(hr)) {
qWarning("Failed to add named file filter \"%s\": %s",
@@ -290,16 +290,12 @@ QWinRTFileDialogHelper::QWinRTFileDialogHelper()
d->shown = false;
}
-QWinRTFileDialogHelper::~QWinRTFileDialogHelper()
-{
-}
-
void QWinRTFileDialogHelper::exec()
{
Q_D(QWinRTFileDialogHelper);
if (!d->shown)
- show(Qt::Dialog, Qt::ApplicationModal, 0);
+ show(Qt::Dialog, Qt::ApplicationModal, nullptr);
d->loop.exec();
}
@@ -369,7 +365,7 @@ bool QWinRTFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModalit
// Remove leading star
const int starOffset = (filter.length() > 1 && filter.startsWith(QLatin1Char('*'))) ? 1 : 0;
HStringReference filterRef(reinterpret_cast<const wchar_t *>(filter.utf16() + starOffset),
- filter.length() - starOffset);
+ uint(filter.length() - starOffset));
hr = entry->Append(filterRef.Get());
if (FAILED(hr)) {
qWarning("Failed to add named file filter \"%s\": %s",
@@ -379,7 +375,7 @@ bool QWinRTFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModalit
const int offset = namedFilter.indexOf(QLatin1String(" ("));
const QString filterTitle = namedFilter.mid(0, offset);
HStringReference namedFilterRef(reinterpret_cast<const wchar_t *>(filterTitle.utf16()),
- filterTitle.length());
+ uint(filterTitle.length()));
boolean replaced;
hr = choices->Insert(namedFilterRef.Get(), entry.Get(), &replaced);
// Only print a warning as * or *.* is not a valid choice on Windows 10
@@ -396,7 +392,7 @@ bool QWinRTFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModalit
if (!suffix.startsWith(QLatin1Char('.')))
suffix.prepend(QLatin1Char('.'));
HStringReference nativeSuffix(reinterpret_cast<const wchar_t *>(suffix.utf16()),
- suffix.length());
+ uint(suffix.length()));
hr = picker->put_DefaultFileExtension(nativeSuffix.Get());
RETURN_FALSE_IF_FAILED_WITH_ARGS("Failed to set default file extension \"%s\"", qPrintable(suffix));
}
@@ -404,7 +400,7 @@ bool QWinRTFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModalit
const QString suggestedName = QFileInfo(d->saveFileName.toLocalFile()).fileName();
if (!suggestedName.isEmpty()) {
HStringReference nativeSuggestedName(reinterpret_cast<const wchar_t *>(suggestedName.utf16()),
- suggestedName.length());
+ uint(suggestedName.length()));
hr = picker->put_SuggestedFileName(nativeSuggestedName.Get());
RETURN_FALSE_IF_FAILED("Failed to set suggested file name");
}
diff --git a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.h b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.h
index 99239aad3a..994d099dcf 100644
--- a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.h
+++ b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.h
@@ -70,7 +70,7 @@ class QWinRTFileDialogHelper : public QPlatformFileDialogHelper
Q_OBJECT
public:
explicit QWinRTFileDialogHelper();
- ~QWinRTFileDialogHelper();
+ ~QWinRTFileDialogHelper() override = default;
void exec() override;
bool show(Qt::WindowFlags, Qt::WindowModality, QWindow *) override;
diff --git a/src/plugins/platforms/winrt/qwinrtfileengine.cpp b/src/plugins/platforms/winrt/qwinrtfileengine.cpp
index 76efdf6cc8..3014b30c38 100644
--- a/src/plugins/platforms/winrt/qwinrtfileengine.cpp
+++ b/src/plugins/platforms/winrt/qwinrtfileengine.cpp
@@ -122,10 +122,6 @@ QWinRTFileEngineHandler::QWinRTFileEngineHandler()
{
}
-QWinRTFileEngineHandler::~QWinRTFileEngineHandler()
-{
-}
-
void QWinRTFileEngineHandler::registerFile(const QString &fileName, IStorageItem *file)
{
handlerInstance->d_func()->files.insert(QDir::cleanPath(fileName), file);
@@ -168,7 +164,7 @@ static HRESULT getDestinationFolder(const QString &fileName, const QString &newF
const QString newFilePath = QDir::toNativeSeparators(newFileInfo.absolutePath());
HStringReference nativeNewFilePath(reinterpret_cast<LPCWSTR>(newFilePath.utf16()),
- newFilePath.length());
+ uint(newFilePath.length()));
hr = folderFactory->GetFolderFromPathAsync(nativeNewFilePath.Get(), &op);
}
if (FAILED(hr))
@@ -181,10 +177,6 @@ QWinRTFileEngine::QWinRTFileEngine(const QString &fileName, IStorageItem *file)
{
}
-QWinRTFileEngine::~QWinRTFileEngine()
-{
-}
-
bool QWinRTFileEngine::open(QIODevice::OpenMode openMode)
{
Q_D(QWinRTFileEngine);
@@ -278,7 +270,7 @@ bool QWinRTFileEngine::seek(qint64 pos)
if (!d->stream)
return false;
- HRESULT hr = d->stream->Seek(pos);
+ HRESULT hr = d->stream->Seek(UINT64(pos));
RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::PositionError, false);
d->pos = pos;
return SUCCEEDED(hr);
@@ -311,7 +303,8 @@ bool QWinRTFileEngine::copy(const QString &newName)
RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::CopyError, false);
const QString destinationName = QFileInfo(newName).fileName();
- HStringReference nativeDestinationName(reinterpret_cast<LPCWSTR>(destinationName.utf16()), destinationName.length());
+ HStringReference nativeDestinationName(reinterpret_cast<LPCWSTR>(destinationName.utf16()),
+ uint(destinationName.length()));
ComPtr<IAsyncOperation<StorageFile *>> op;
hr = file->CopyOverloadDefaultOptions(destinationFolder.Get(), nativeDestinationName.Get(), &op);
RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::CopyError, false);
@@ -332,7 +325,8 @@ bool QWinRTFileEngine::rename(const QString &newName)
RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::RenameError, false);
const QString destinationName = QFileInfo(newName).fileName();
- HStringReference nativeDestinationName(reinterpret_cast<LPCWSTR>(destinationName.utf16()), destinationName.length());
+ HStringReference nativeDestinationName(reinterpret_cast<LPCWSTR>(destinationName.utf16()),
+ uint(destinationName.length()));
ComPtr<IAsyncAction> op;
hr = d->file->RenameAsyncOverloadDefaultOptions(nativeDestinationName.Get(), &op);
RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::RenameError, false);
@@ -349,7 +343,8 @@ bool QWinRTFileEngine::renameOverwrite(const QString &newName)
RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::RenameError, false);
const QString destinationName = QFileInfo(newName).fileName();
- HStringReference nativeDestinationName(reinterpret_cast<LPCWSTR>(destinationName.utf16()), destinationName.length());
+ HStringReference nativeDestinationName(reinterpret_cast<LPCWSTR>(destinationName.utf16()),
+ uint(destinationName.length()));
ComPtr<IAsyncAction> op;
hr = d->file->RenameAsync(nativeDestinationName.Get(), NameCollisionOption_ReplaceExisting, &op);
RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::RenameError, false);
@@ -451,7 +446,7 @@ qint64 QWinRTFileEngine::read(char *data, qint64 maxlen)
HRESULT hr = d->stream.As(&stream);
RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::ReadError, -1);
- UINT32 length = qBound(quint64(0), quint64(maxlen), quint64(UINT_MAX));
+ UINT32 length = UINT32(qBound(quint64(0), quint64(maxlen), quint64(UINT32_MAX)));
ComPtr<IBuffer> buffer;
hr = d->bufferFactory->Create(length, &buffer);
RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::ReadError, -1);
@@ -494,7 +489,7 @@ qint64 QWinRTFileEngine::write(const char *data, qint64 maxlen)
HRESULT hr = d->stream.As(&stream);
RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::WriteError, -1);
- UINT32 length = qBound(quint64(0), quint64(maxlen), quint64(UINT_MAX));
+ UINT32 length = UINT32(qBound(quint64(0), quint64(maxlen), quint64(UINT_MAX)));
ComPtr<IBuffer> buffer;
hr = d->bufferFactory->Create(length, &buffer);
RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::WriteError, -1);
diff --git a/src/plugins/platforms/winrt/qwinrtfileengine.h b/src/plugins/platforms/winrt/qwinrtfileengine.h
index 73ff54b0c8..4485917c9e 100644
--- a/src/plugins/platforms/winrt/qwinrtfileengine.h
+++ b/src/plugins/platforms/winrt/qwinrtfileengine.h
@@ -57,7 +57,7 @@ class QWinRTFileEngineHandler : public QAbstractFileEngineHandler
{
public:
QWinRTFileEngineHandler();
- ~QWinRTFileEngineHandler();
+ ~QWinRTFileEngineHandler() override = default;
QAbstractFileEngine *create(const QString &fileName) const override;
static void registerFile(const QString &fileName, ABI::Windows::Storage::IStorageItem *file);
@@ -73,7 +73,7 @@ class QWinRTFileEngine : public QAbstractFileEngine
{
public:
QWinRTFileEngine(const QString &fileName, ABI::Windows::Storage::IStorageItem *file);
- ~QWinRTFileEngine();
+ ~QWinRTFileEngine() override = default;
bool open(QIODevice::OpenMode openMode) override;
bool close() override;
diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp
index 63e5b0cf27..f7e91bb047 100644
--- a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp
+++ b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp
@@ -64,8 +64,8 @@ inline QRectF getInputPaneRect(ComPtr<IInputPane> pane, qreal scaleFactor)
{
Rect rect;
pane->get_OccludedRect(&rect);
- return QRectF(qRound(rect.X * scaleFactor), qRound(rect.Y * scaleFactor),
- qRound(rect.Width * scaleFactor), qRound(rect.Height * scaleFactor));
+ return QRectF(qRound(qreal(rect.X) * scaleFactor), qRound(qreal(rect.Y) * scaleFactor),
+ qRound(qreal(rect.Width) * scaleFactor), qRound(qreal(rect.Height) * scaleFactor));
}
/*!
@@ -205,6 +205,8 @@ void QWinRTInputContext::showInputPanel()
void QWinRTInputContext::hideInputPanel()
{
qCDebug(lcQpaInputMethods) << __FUNCTION__;
+ if (!m_isInputPanelVisible)
+ return;
QEventDispatcherWinRT::runOnXamlThread([&]() {
ComPtr<IInputPane2> inputPane;
diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp
index c52207d23b..4f37583bed 100644
--- a/src/plugins/platforms/winrt/qwinrtintegration.cpp
+++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp
@@ -50,6 +50,9 @@
#if QT_CONFIG(draganddrop)
#include "qwinrtdrag.h"
#endif
+#if QT_CONFIG(accessibility)
+# include "uiautomation/qwinrtuiaaccessibility.h"
+#endif
#include <QtGui/QOffscreenSurface>
#include <QtGui/QOpenGLContext>
@@ -119,6 +122,9 @@ public:
QPlatformClipboard *clipboard;
QWinRTScreen *mainScreen;
QScopedPointer<QWinRTInputContext> inputContext;
+#if QT_CONFIG(accessibility)
+ QWinRTUiaAccessibility *accessibility;
+#endif
ComPtr<ICoreApplication> application;
QHash<CoreApplicationCallbackRemover, EventRegistrationToken> applicationTokens;
@@ -198,6 +204,9 @@ QWinRTIntegration::QWinRTIntegration() : d_ptr(new QWinRTIntegrationPrivate)
screenAdded(d->mainScreen);
d->platformServices = new QWinRTServices;
d->clipboard = new QWinRTClipboard;
+#if QT_CONFIG(accessibility)
+ d->accessibility = new QWinRTUiaAccessibility;
+#endif
}
QWinRTIntegration::~QWinRTIntegration()
@@ -315,6 +324,14 @@ QPlatformDrag *QWinRTIntegration::drag() const
}
#endif // QT_CONFIG(draganddrop)
+#if QT_CONFIG(accessibility)
+QPlatformAccessibility *QWinRTIntegration::accessibility() const
+{
+ Q_D(const QWinRTIntegration);
+ return d->accessibility;
+}
+#endif // QT_CONFIG(accessibility)
+
Qt::KeyboardModifiers QWinRTIntegration::queryKeyboardModifiers() const
{
Q_D(const QWinRTIntegration);
diff --git a/src/plugins/platforms/winrt/qwinrtintegration.h b/src/plugins/platforms/winrt/qwinrtintegration.h
index d1a9b7edbd..636e594b4b 100644
--- a/src/plugins/platforms/winrt/qwinrtintegration.h
+++ b/src/plugins/platforms/winrt/qwinrtintegration.h
@@ -75,7 +75,7 @@ class QWinRTIntegration : public QPlatformIntegration
private:
explicit QWinRTIntegration();
public:
- ~QWinRTIntegration();
+ ~QWinRTIntegration() override;
static QWinRTIntegration *create()
{
@@ -100,6 +100,9 @@ public:
#if QT_CONFIG(draganddrop)
QPlatformDrag *drag() const override;
#endif
+#if QT_CONFIG(accessibility)
+ QPlatformAccessibility *accessibility() const override;
+#endif
Qt::KeyboardModifiers queryKeyboardModifiers() const override;
diff --git a/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp
index d69c63e9a4..7016b47f7e 100644
--- a/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp
+++ b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp
@@ -99,7 +99,7 @@ void QWinRTMessageDialogHelper::exec()
Q_D(QWinRTMessageDialogHelper);
if (!d->shown)
- show(Qt::Dialog, Qt::ApplicationModal, 0);
+ show(Qt::Dialog, Qt::ApplicationModal, nullptr);
d->loop.exec();
}
@@ -134,9 +134,11 @@ bool QWinRTMessageDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModa
RETURN_FALSE_IF_FAILED("Failed to create command factory");
ComPtr<IMessageDialog> dialog;
- HStringReference nativeText(reinterpret_cast<LPCWSTR>(text.utf16()), text.size());
+ HStringReference nativeText(reinterpret_cast<LPCWSTR>(text.utf16()),
+ uint(text.size()));
if (!title.isEmpty()) {
- HStringReference nativeTitle(reinterpret_cast<LPCWSTR>(title.utf16()), title.size());
+ HStringReference nativeTitle(reinterpret_cast<LPCWSTR>(title.utf16()),
+ uint(title.size()));
hr = dialogFactory->CreateWithTitle(nativeText.Get(), nativeTitle.Get(), &dialog);
RETURN_FALSE_IF_FAILED("Failed to create dialog with title");
} else {
@@ -162,7 +164,8 @@ bool QWinRTMessageDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModa
continue;
// Add native command
const QString label = d->theme->standardButtonText(i);
- HStringReference nativeLabel(reinterpret_cast<LPCWSTR>(label.utf16()), label.size());
+ HStringReference nativeLabel(reinterpret_cast<LPCWSTR>(label.utf16()),
+ uint(label.size()));
ComPtr<IUICommand> command;
hr = commandFactory->Create(nativeLabel.Get(), &command);
RETURN_HR_IF_FAILED("Failed to create message box command");
diff --git a/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.h b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.h
index 14b6d4b715..ab704b1c7d 100644
--- a/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.h
+++ b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.h
@@ -67,7 +67,7 @@ class QWinRTMessageDialogHelper : public QPlatformMessageDialogHelper
Q_OBJECT
public:
explicit QWinRTMessageDialogHelper(const QWinRTTheme *theme);
- ~QWinRTMessageDialogHelper();
+ ~QWinRTMessageDialogHelper() override;
void exec() override;
bool show(Qt::WindowFlags windowFlags,
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp
index e39a87148a..bd2bbcb81c 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.cpp
+++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp
@@ -46,9 +46,11 @@
#include "qwinrtdrag.h"
#endif
#include "qwinrtwindow.h"
+#include "qwinrtcanvas.h"
#include <private/qeventdispatcher_winrt_p.h>
#include <private/qhighdpiscaling_p.h>
+#include <QtCore/qdebug.h>
#include <QtCore/QLoggingCategory>
#include <QtGui/QSurfaceFormat>
#include <QtGui/QGuiApplication>
@@ -99,6 +101,31 @@ typedef ITypedEventHandler<ApplicationView*, IInspectable*> VisibleBoundsChanged
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcQpaEvents, "qt.qpa.events")
+
+#if !defined(QT_NO_DEBUG_STREAM)
+QDebug operator<<(QDebug dbg, QWinRTScreen::MousePositionTransition transition)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QWinRTScreen::MousePositionTransition::";
+ switch (transition) {
+ case QWinRTScreen::MousePositionTransition::MovedOut:
+ dbg << "MovedOut";
+ break;
+ case QWinRTScreen::MousePositionTransition::MovedIn:
+ dbg << "MovedIn";
+ break;
+ case QWinRTScreen::MousePositionTransition::StayedOut:
+ dbg << "StayedOut";
+ break;
+ case QWinRTScreen::MousePositionTransition::StayedIn:
+ dbg << "StayedIn";
+ break;
+ }
+ return dbg;
+}
+#endif
+
struct KeyInfo {
KeyInfo()
{
@@ -463,7 +490,7 @@ public:
QTouchDevice *touchDevice;
ComPtr<ICoreWindow> coreWindow;
ComPtr<ICorePointerRedirector> redirect;
- ComPtr<Xaml::IDependencyObject> canvas;
+ ComPtr<QWinRTCanvas> canvas;
ComPtr<IApplicationView> view;
ComPtr<IDisplayInformation> displayInformation;
@@ -490,6 +517,7 @@ public:
QAtomicPointer<QWinRTWindow> keyboardGrabWindow;
QWindow *currentPressWindow = nullptr;
QWindow *currentTargetWindow = nullptr;
+ bool firstMouseMove = true;
};
// To be called from the XAML thread
@@ -553,27 +581,25 @@ QWinRTScreen::QWinRTScreen()
hr = applicationViewStatics->GetForCurrentView(&d->view);
RETURN_VOID_IF_FAILED("Could not access currentView");
- // Create a canvas and set it as the window content. Eventually, this should have its own method so multiple "screens" can be added
- ComPtr<Xaml::Controls::ICanvas> canvas;
- hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Controls_Canvas).Get(), &canvas);
- Q_ASSERT_SUCCEEDED(hr);
+ d->canvas = Make<QWinRTCanvas>([this]() { return topWindow(); });
+
ComPtr<Xaml::IFrameworkElement> frameworkElement;
- hr = canvas.As(&frameworkElement);
+ hr = d->canvas.As(&frameworkElement);
Q_ASSERT_SUCCEEDED(hr);
hr = frameworkElement->put_Width(d->logicalRect.width());
Q_ASSERT_SUCCEEDED(hr);
hr = frameworkElement->put_Height(d->logicalRect.height());
Q_ASSERT_SUCCEEDED(hr);
+
ComPtr<Xaml::IUIElement> uiElement;
- hr = canvas.As(&uiElement);
+ hr = d->canvas.As(&uiElement);
Q_ASSERT_SUCCEEDED(hr);
+
#if QT_CONFIG(draganddrop)
QWinRTDrag::instance()->setUiElement(uiElement);
#endif
hr = window->put_Content(uiElement.Get());
Q_ASSERT_SUCCEEDED(hr);
- hr = canvas.As(&d->canvas);
- Q_ASSERT_SUCCEEDED(hr);
d->cursor.reset(new QWinRTCursor);
@@ -723,7 +749,10 @@ ICoreWindow *QWinRTScreen::coreWindow() const
Xaml::IDependencyObject *QWinRTScreen::canvas() const
{
Q_D(const QWinRTScreen);
- return d->canvas.Get();
+ Xaml::IDependencyObject *depCanvas;
+ if (SUCCEEDED(d->canvas.CopyTo(&depCanvas)))
+ return depCanvas;
+ return nullptr;
}
void QWinRTScreen::initialize()
@@ -848,6 +877,7 @@ void QWinRTScreen::addWindow(QWindow *window)
}
handleExpose();
+ d->firstMouseMove = true;
QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
#if QT_CONFIG(draganddrop)
@@ -860,6 +890,8 @@ void QWinRTScreen::removeWindow(QWindow *window)
Q_D(QWinRTScreen);
qCDebug(lcQpaWindows) << __FUNCTION__ << window;
+ handleExpose();
+
const bool wasTopWindow = window == topWindow();
if (!d->visibleWindows.removeAll(window))
return;
@@ -867,7 +899,6 @@ void QWinRTScreen::removeWindow(QWindow *window)
const Qt::WindowType type = window->type();
if (wasTopWindow && type != Qt::Popup && type != Qt::ToolTip && type != Qt::Tool)
QWindowSystemInterface::handleWindowActivated(nullptr, Qt::OtherFocusReason);
- handleExpose();
QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
#if QT_CONFIG(draganddrop)
if (wasTopWindow)
@@ -1075,6 +1106,7 @@ HRESULT QWinRTScreen::onCharacterReceived(ICoreWindow *, ICharacterReceivedEvent
HRESULT QWinRTScreen::onPointerEntered(ICoreWindow *, IPointerEventArgs *args)
{
Q_D(QWinRTScreen);
+ qCDebug(lcQpaEvents) << __FUNCTION__;
ComPtr<IPointerPoint> pointerPoint;
if (SUCCEEDED(args->get_CurrentPoint(&pointerPoint))) {
@@ -1087,7 +1119,9 @@ HRESULT QWinRTScreen::onPointerEntered(ICoreWindow *, IPointerEventArgs *args)
if (d->mouseGrabWindow)
d->currentTargetWindow = d->mouseGrabWindow.load()->window();
+ qCDebug(lcQpaEvents) << __FUNCTION__ << "handleEnterEvent" << d->currentTargetWindow << pos;
QWindowSystemInterface::handleEnterEvent(d->currentTargetWindow, pos, pos);
+ d->firstMouseMove = false;
}
return S_OK;
}
@@ -1095,7 +1129,7 @@ HRESULT QWinRTScreen::onPointerEntered(ICoreWindow *, IPointerEventArgs *args)
HRESULT QWinRTScreen::onPointerExited(ICoreWindow *, IPointerEventArgs *args)
{
Q_D(QWinRTScreen);
-
+ qCDebug(lcQpaEvents) << __FUNCTION__;
ComPtr<IPointerPoint> pointerPoint;
if (FAILED(args->get_CurrentPoint(&pointerPoint)))
return E_INVALIDARG;
@@ -1109,6 +1143,7 @@ HRESULT QWinRTScreen::onPointerExited(ICoreWindow *, IPointerEventArgs *args)
if (d->mouseGrabWindow)
d->currentTargetWindow = d->mouseGrabWindow.load()->window();
+ qCDebug(lcQpaEvents) << __FUNCTION__ << "handleLeaveEvent" << d->currentTargetWindow;
QWindowSystemInterface::handleLeaveEvent(d->currentTargetWindow);
d->currentTargetWindow = nullptr;
return S_OK;
@@ -1120,6 +1155,7 @@ ComPtr<IPointerPoint> qt_winrt_lastPointerPoint;
HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
{
Q_D(QWinRTScreen);
+ qCDebug(lcQpaEvents) << __FUNCTION__;
ComPtr<IPointerPoint> pointerPoint;
if (FAILED(args->get_CurrentPoint(&pointerPoint)))
return E_INVALIDARG;
@@ -1175,6 +1211,8 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
boolean isHorizontal;
properties->get_IsHorizontalMouseWheel(&isHorizontal);
QPoint angleDelta(isHorizontal ? delta : 0, isHorizontal ? 0 : delta);
+ qCDebug(lcQpaEvents) << __FUNCTION__ << "handleWheelEvent" << d->currentTargetWindow
+ << localPos << pos << angleDelta << mods;
QWindowSystemInterface::handleWheelEvent(d->currentTargetWindow, localPos, pos, QPoint(), angleDelta, mods);
break;
}
@@ -1213,6 +1251,8 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
const QPointF globalPosDelta = pos - posPoint;
const QPointF localPressPos = d->currentPressWindow->mapFromGlobal(posPoint) + globalPosDelta;
+ qCDebug(lcQpaEvents) << __FUNCTION__ << "handleMouseEvent" << d->currentPressWindow
+ << localPressPos << pos << buttons << mods;
QWindowSystemInterface::handleMouseEvent(d->currentPressWindow, localPressPos, pos, buttons, mods);
d->currentPressWindow = nullptr;
}
@@ -1224,6 +1264,8 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
d->currentPressWindow = nullptr;
}
+ qCDebug(lcQpaEvents) << __FUNCTION__ << "handleMouseEvent" << d->currentTargetWindow
+ << localPos << pos << buttons << mods;
QWindowSystemInterface::handleMouseEvent(d->currentTargetWindow, localPos, pos, buttons, mods);
break;
@@ -1280,6 +1322,8 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
it.value().normalPosition = QPointF(point.X/d->logicalRect.width(), point.Y/d->logicalRect.height());
it.value().pressure = pressure;
+ qCDebug(lcQpaEvents) << __FUNCTION__ << "handleTouchEvent" << d->currentTargetWindow
+ << d->touchDevice << d->touchPoints.values() << mods;
QWindowSystemInterface::handleTouchEvent(d->currentTargetWindow, d->touchDevice, d->touchPoints.values(), mods);
if (wasPressEvent)
it.value().state = Qt::TouchPointStationary;
@@ -1301,6 +1345,9 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
float rotation;
properties->get_Twist(&rotation);
+ qCDebug(lcQpaEvents) << __FUNCTION__ << "handleTabletEvent" << d->currentTargetWindow
+ << isPressed << pos << pointerType << pressure << xTilt << yTilt
+ << rotation << id << mods;
QWindowSystemInterface::handleTabletEvent(d->currentTargetWindow, isPressed, pos, pos, 0,
pointerType, pressure, xTilt, yTilt,
0, rotation, 0, id, mods);
@@ -1312,6 +1359,70 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
return S_OK;
}
+void QWinRTScreen::emulateMouseMove(const QPointF &point, MousePositionTransition transition)
+{
+ Q_D(QWinRTScreen);
+ qCDebug(lcQpaEvents) << __FUNCTION__ << point << transition;
+ if (transition == MousePositionTransition::StayedOut)
+ return;
+ qt_winrt_lastPointerPoint = nullptr;
+ const QPointF pos(point.x() * d->scaleFactor, point.y() * d->scaleFactor);
+ QPointF localPos = pos;
+
+ const QPoint posPoint = pos.toPoint();
+ QWindow *windowUnderPointer = windowAt(QHighDpiScaling::mapPositionFromNative(posPoint, this));
+ d->currentTargetWindow = windowUnderPointer;
+
+ if (d->mouseGrabWindow)
+ d->currentTargetWindow = d->mouseGrabWindow.load()->window();
+
+ if (d->currentTargetWindow) {
+ const QPointF globalPosDelta = pos - posPoint;
+ localPos = d->currentTargetWindow->mapFromGlobal(posPoint) + globalPosDelta;
+ }
+
+ // In case of a mouse grab we have to store the target of a press event
+ // to be able to send one additional release event to this target when the mouse
+ // button is released. This is a similar approach to AutoMouseCapture in the
+ // windows qpa backend. Otherwise the release might not be propagated and the original
+ // press event receiver considers a button to still be pressed, as in Qt Quick Controls 1
+ // menus.
+ if (d->currentPressWindow && d->mouseGrabWindow) {
+ const QPointF globalPosDelta = pos - posPoint;
+ const QPointF localPressPos = d->currentPressWindow->mapFromGlobal(posPoint) + globalPosDelta;
+
+ qCDebug(lcQpaEvents) << __FUNCTION__ << "handleMouseEvent" << d->currentPressWindow
+ << localPressPos << pos << Qt::NoButton << Qt::NoModifier;
+ QWindowSystemInterface::handleMouseEvent(d->currentPressWindow, localPressPos, pos,
+ Qt::NoButton, Qt::NoModifier);
+ d->currentPressWindow = nullptr;
+ }
+ // If the mouse button is released outside of a window, targetWindow is 0, but the event
+ // has to be delivered to the window, that initially received the mouse press. Do not reset
+ // d->currentTargetWindow though, as it is used (and reset) in onPointerExited.
+ if (d->currentPressWindow && !d->currentTargetWindow) {
+ d->currentTargetWindow = d->currentPressWindow;
+ d->currentPressWindow = nullptr;
+ }
+
+ if (transition == MousePositionTransition::MovedOut) {
+ qCDebug(lcQpaEvents) << __FUNCTION__ << "handleLeaveEvent" << d->currentTargetWindow;
+ QWindowSystemInterface::handleLeaveEvent(d->currentTargetWindow);
+ return;
+ }
+
+ if (transition == MousePositionTransition::MovedIn || d->firstMouseMove) {
+ qCDebug(lcQpaEvents) << __FUNCTION__ << "handleEnterEvent" << d->currentTargetWindow
+ << localPos << pos;
+ QWindowSystemInterface::handleEnterEvent(d->currentTargetWindow, localPos, pos);
+ d->firstMouseMove = false;
+ }
+ qCDebug(lcQpaEvents) << __FUNCTION__ << "handleMouseEvent" << d->currentTargetWindow
+ << localPos << pos << Qt::NoButton << Qt::NoModifier;
+ QWindowSystemInterface::handleMouseEvent(d->currentTargetWindow, localPos, pos, Qt::NoButton,
+ Qt::NoModifier);
+}
+
HRESULT QWinRTScreen::onActivated(ICoreWindow *, IWindowActivatedEventArgs *args)
{
Q_D(QWinRTScreen);
@@ -1413,6 +1524,7 @@ HRESULT QWinRTScreen::onRedirectReleased(ICorePointerRedirector *, IPointerEvent
{
// When dragging ends with a non-mouse input device then onRedirectRelease is invoked.
// QTBUG-58781
+ qCDebug(lcQpaEvents) << __FUNCTION__;
return onPointerUpdated(nullptr, args);
}
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h
index fd6499c2b9..cde148a638 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.h
+++ b/src/plugins/platforms/winrt/qwinrtscreen.h
@@ -89,7 +89,7 @@ class QWinRTScreen : public QPlatformScreen
{
public:
explicit QWinRTScreen();
- ~QWinRTScreen();
+ ~QWinRTScreen() override;
QRect geometry() const override;
QRect availableGeometry() const override;
@@ -128,6 +128,15 @@ public:
void setCursorRect(const QRectF &cursorRect);
void setKeyboardRect(const QRectF &keyboardRect);
+ enum class MousePositionTransition {
+ MovedOut,
+ MovedIn,
+ StayedIn,
+ StayedOut
+ };
+
+ void emulateMouseMove(const QPointF &point, MousePositionTransition transition);
+
private:
void handleExpose();
diff --git a/src/plugins/platforms/winrt/qwinrtservices.cpp b/src/plugins/platforms/winrt/qwinrtservices.cpp
index 05620ca4c8..b27c408f40 100644
--- a/src/plugins/platforms/winrt/qwinrtservices.cpp
+++ b/src/plugins/platforms/winrt/qwinrtservices.cpp
@@ -83,17 +83,14 @@ QWinRTServices::QWinRTServices()
Q_ASSERT_X(SUCCEEDED(hr), Q_FUNC_INFO, qPrintable(qt_error_string(hr)));
}
-QWinRTServices::~QWinRTServices()
-{
-}
-
bool QWinRTServices::openUrl(const QUrl &url)
{
Q_D(QWinRTServices);
ComPtr<IUriRuntimeClass> uri;
QString urlString = url.toString();
- HStringReference uriString(reinterpret_cast<LPCWSTR>(urlString.utf16()), urlString.length());
+ HStringReference uriString(reinterpret_cast<LPCWSTR>(urlString.utf16()),
+ uint(urlString.length()));
HRESULT hr = d->uriFactory->CreateUri(uriString.Get(), &uri);
RETURN_FALSE_IF_FAILED("Failed to create URI from QUrl.");
@@ -122,7 +119,8 @@ bool QWinRTServices::openDocument(const QUrl &url)
}
if (!file) {
const QString pathString = QDir::toNativeSeparators(url.toLocalFile());
- HStringReference path(reinterpret_cast<LPCWSTR>(pathString.utf16()), pathString.length());
+ HStringReference path(reinterpret_cast<LPCWSTR>(pathString.utf16()),
+ uint(pathString.length()));
ComPtr<IAsyncOperation<StorageFile *>> op;
hr = d->fileFactory->GetFileFromPathAsync(path.Get(), &op);
RETURN_FALSE_IF_FAILED("Failed to initialize file URI.");
diff --git a/src/plugins/platforms/winrt/qwinrtservices.h b/src/plugins/platforms/winrt/qwinrtservices.h
index 80b9a6c92a..202ce722cf 100644
--- a/src/plugins/platforms/winrt/qwinrtservices.h
+++ b/src/plugins/platforms/winrt/qwinrtservices.h
@@ -50,7 +50,7 @@ class QWinRTServices : public QPlatformServices
{
public:
explicit QWinRTServices();
- ~QWinRTServices();
+ ~QWinRTServices() override = default;
bool openUrl(const QUrl &url) override;
bool openDocument(const QUrl &url) override;
diff --git a/src/plugins/platforms/winrt/qwinrtwindow.cpp b/src/plugins/platforms/winrt/qwinrtwindow.cpp
index cbf0ba36c9..29d234d276 100644
--- a/src/plugins/platforms/winrt/qwinrtwindow.cpp
+++ b/src/plugins/platforms/winrt/qwinrtwindow.cpp
@@ -126,7 +126,7 @@ QWinRTWindow::QWinRTWindow(QWindow *window)
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Controls_Canvas).Get(),
IID_PPV_ARGS(&d->canvas));
Q_ASSERT_SUCCEEDED(hr);
- hr = QEventDispatcherWinRT::runOnXamlThread([this, d]() {
+ hr = QEventDispatcherWinRT::runOnXamlThread([d]() {
// Create a new swapchain and place it inside the canvas
HRESULT hr;
hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Controls_SwapChainPanel).Get(),
diff --git a/src/plugins/platforms/winrt/qwinrtwindow.h b/src/plugins/platforms/winrt/qwinrtwindow.h
index 9604b4bbaa..0445e6bf54 100644
--- a/src/plugins/platforms/winrt/qwinrtwindow.h
+++ b/src/plugins/platforms/winrt/qwinrtwindow.h
@@ -54,7 +54,7 @@ class QWinRTWindow : public QPlatformWindow
{
public:
QWinRTWindow(QWindow *window);
- ~QWinRTWindow();
+ ~QWinRTWindow() override;
QSurfaceFormat format() const override;
bool isActive() const override;
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiaaccessibility.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaaccessibility.cpp
new file mode 100644
index 0000000000..40274fb967
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaaccessibility.cpp
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiaaccessibility.h"
+#include "qwinrtuiamainprovider.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QWindow>
+#include <QtGui/QGuiApplication>
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtCore/qt_windows.h>
+#include <qpa/qplatformintegration.h>
+
+QT_BEGIN_NAMESPACE
+
+QWinRTUiaAccessibility::QWinRTUiaAccessibility()
+{
+}
+
+QWinRTUiaAccessibility::~QWinRTUiaAccessibility()
+{
+}
+
+// Handles UI Automation window messages.
+void QWinRTUiaAccessibility::activate()
+{
+ // Start handling accessibility internally
+ QGuiApplicationPrivate::platformIntegration()->accessibility()->setActive(true);
+}
+
+// Handles accessibility update notifications.
+void QWinRTUiaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
+{
+ if (!event)
+ return;
+
+ QAccessibleInterface *accessible = event->accessibleInterface();
+ if (!isActive() || !accessible || !accessible->isValid())
+ return;
+
+ switch (event->type()) {
+ case QAccessible::Focus:
+ QWinRTUiaMainProvider::notifyFocusChange(event);
+ break;
+ case QAccessible::ObjectCreated:
+ case QAccessible::ObjectDestroyed:
+ case QAccessible::ObjectShow:
+ case QAccessible::ObjectHide:
+ case QAccessible::ObjectReorder:
+ QWinRTUiaMainProvider::notifyVisibilityChange(event);
+ break;
+ case QAccessible::StateChanged:
+ QWinRTUiaMainProvider::notifyStateChange(static_cast<QAccessibleStateChangeEvent *>(event));
+ break;
+ case QAccessible::ValueChanged:
+ QWinRTUiaMainProvider::notifyValueChange(static_cast<QAccessibleValueChangeEvent *>(event));
+ break;
+ case QAccessible::TextAttributeChanged:
+ case QAccessible::TextColumnChanged:
+ case QAccessible::TextInserted:
+ case QAccessible::TextRemoved:
+ case QAccessible::TextUpdated:
+ case QAccessible::TextSelectionChanged:
+ case QAccessible::TextCaretMoved:
+ QWinRTUiaMainProvider::notifyTextChange(event);
+ break;
+ default:
+ break;
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiaaccessibility.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaaccessibility.h
new file mode 100644
index 0000000000..b966271e21
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaaccessibility.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTUIAACCESSIBILITY_H
+#define QWINRTUIAACCESSIBILITY_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include <qpa/qplatformaccessibility.h>
+
+QT_BEGIN_NAMESPACE
+
+// WinRT platform accessibility implemented over UI Automation.
+class QWinRTUiaAccessibility : public QPlatformAccessibility
+{
+public:
+ explicit QWinRTUiaAccessibility();
+ virtual ~QWinRTUiaAccessibility();
+ static void activate();
+ void notifyAccessibilityUpdate(QAccessibleEvent *event) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QWINRTUIAACCESSIBILITY_H
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiabaseprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiabaseprovider.cpp
new file mode 100644
index 0000000000..ee53714caa
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiabaseprovider.cpp
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiabaseprovider.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+QWinRTUiaBaseProvider::QWinRTUiaBaseProvider(QAccessible::Id id) :
+ m_id(id)
+{
+}
+
+QWinRTUiaBaseProvider::~QWinRTUiaBaseProvider()
+{
+}
+
+QAccessibleInterface *QWinRTUiaBaseProvider::accessibleInterface() const
+{
+ QAccessibleInterface *accessible = QAccessible::accessibleInterface(m_id);
+ if (accessible && accessible->isValid())
+ return accessible;
+ return nullptr;
+}
+
+QAccessible::Id QWinRTUiaBaseProvider::id() const
+{
+ return m_id;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiabaseprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiabaseprovider.h
new file mode 100644
index 0000000000..d8837354dc
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiabaseprovider.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTUIABASEPROVIDER_H
+#define QWINRTUIABASEPROVIDER_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+
+// Base class for UI Automation providers.
+class QWinRTUiaBaseProvider : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QWinRTUiaBaseProvider)
+public:
+ explicit QWinRTUiaBaseProvider(QAccessible::Id id);
+ virtual ~QWinRTUiaBaseProvider();
+
+ QAccessibleInterface *accessibleInterface() const;
+ QAccessible::Id id() const;
+
+private:
+ QAccessible::Id m_id;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QWINRTUIABASEPROVIDER_H
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiacontrolmetadata.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiacontrolmetadata.cpp
new file mode 100644
index 0000000000..4e406a3545
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiacontrolmetadata.cpp
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiacontrolmetadata.h"
+#include "qwinrtuiautils.h"
+
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWinRTUiAutomation;
+
+QWinRTUiaControlMetadata::QWinRTUiaControlMetadata()
+{
+}
+
+QWinRTUiaControlMetadata::QWinRTUiaControlMetadata(QAccessible::Id id)
+{
+ update(id);
+}
+
+void QWinRTUiaControlMetadata::update(QAccessible::Id id)
+{
+ if (QAccessibleInterface *accessible = accessibleForId(id)) {
+ m_automationId = generateAutomationId(accessible);
+ m_className = generateClassName(accessible);
+ m_controlName = generateControlName(accessible);
+ m_role = generateRole(accessible);
+ m_state = accessible->state();
+ m_accelerator = accessible->text(QAccessible::Accelerator);
+ m_access = accessible->text(QAccessible::Accelerator);
+ m_help = accessible->text(QAccessible::Help);
+ m_description = accessible->text(QAccessible::Description);
+ m_value = accessible->text(QAccessible::Value);
+ m_boundingRect = accessible->rect();
+ updateValueData(accessible);
+ updateTableData(accessible);
+ updateTextData(accessible);
+ }
+}
+
+QString QWinRTUiaControlMetadata::generateControlName(QAccessibleInterface *accessible)
+{
+ const bool clientTopLevel = (accessible->role() == QAccessible::Client)
+ && accessible->parent() && (accessible->parent()->role() == QAccessible::Application);
+
+ QString name = accessible->text(QAccessible::Name);
+ if (name.isEmpty() && clientTopLevel)
+ name = QCoreApplication::applicationName();
+ return name;
+}
+
+QString QWinRTUiaControlMetadata::generateClassName(QAccessibleInterface *accessible)
+{
+ QString name;
+
+ if (QObject *obj = accessible->object())
+ name = QLatin1String(obj->metaObject()->className());
+ return name;
+}
+
+// Generates an ID based on the name of the controls and their parents.
+QString QWinRTUiaControlMetadata::generateAutomationId(QAccessibleInterface *accessible)
+{
+ QString autid;
+ QObject *obj = accessible->object();
+ while (obj) {
+ QString name = obj->objectName();
+ if (name.isEmpty()) {
+ autid = QStringLiteral("");
+ break;
+ }
+ if (!autid.isEmpty())
+ autid.prepend(QLatin1Char('.'));
+ autid.prepend(name);
+ obj = obj->parent();
+ }
+ return autid;
+}
+
+QAccessible::Role QWinRTUiaControlMetadata::generateRole(QAccessibleInterface *accessible)
+{
+ const bool clientTopLevel = (accessible->role() == QAccessible::Client)
+ && accessible->parent() && (accessible->parent()->role() == QAccessible::Application);
+
+ if (clientTopLevel) {
+ // Reports a top-level widget as a window.
+ return QAccessible::Window;
+ } else {
+ return accessible->role();
+ }
+}
+
+void QWinRTUiaControlMetadata::updateValueData(QAccessibleInterface *accessible)
+{
+ if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
+ m_minimumValue = valueInterface->minimumValue().toDouble();
+ m_maximumValue = valueInterface->maximumValue().toDouble();
+ m_currentValue = valueInterface->currentValue().toDouble();
+ m_minimumStepSize = valueInterface->minimumStepSize().toDouble();
+ } else {
+ m_minimumValue = 0.0;
+ m_maximumValue = 0.0;
+ m_currentValue = 0.0;
+ m_minimumStepSize = 0.0;
+ }
+}
+
+void QWinRTUiaControlMetadata::updateTableData(QAccessibleInterface *accessible)
+{
+ if (QAccessibleTableInterface *tableInterface = accessible->tableInterface()) {
+ m_rowIndex = 0;
+ m_columnIndex = 0;
+ m_rowCount = tableInterface->rowCount();
+ m_columnCount = tableInterface->columnCount();
+ } else if (QAccessibleTableCellInterface *tableCellInterface = accessible->tableCellInterface()) {
+ m_rowIndex = tableCellInterface->rowIndex();
+ m_columnIndex = tableCellInterface->columnIndex();
+ m_rowCount = tableCellInterface->rowExtent();
+ m_columnCount = tableCellInterface->columnExtent();
+ } else {
+ m_rowIndex = 0;
+ m_columnIndex = 0;
+ m_rowCount = 0;
+ m_columnCount = 0;
+ }
+}
+
+void QWinRTUiaControlMetadata::updateTextData(QAccessibleInterface *accessible)
+{
+ if (QAccessibleTextInterface *textInterface = accessible->textInterface()) {
+ m_cursorPosition = textInterface->cursorPosition();
+ m_text = textInterface->text(0, textInterface->characterCount());
+ } else {
+ m_cursorPosition = 0;
+ m_text = QStringLiteral("");
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiacontrolmetadata.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiacontrolmetadata.h
new file mode 100644
index 0000000000..769f073a1b
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiacontrolmetadata.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTUIACONTROLMETADATA_H
+#define QWINRTUIACONTROLMETADATA_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include <QString>
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+
+QT_BEGIN_NAMESPACE
+
+// Cacheable control metadata
+class QWinRTUiaControlMetadata
+{
+public:
+ QWinRTUiaControlMetadata();
+ QWinRTUiaControlMetadata(QAccessible::Id id);
+ void update(QAccessible::Id id);
+ QString automationId() const { return m_automationId; }
+ QString className() const { return m_className; }
+ QString controlName() const { return m_controlName; }
+ QString accelerator() const { return m_accelerator; }
+ QString access() const { return m_access; }
+ QString help() const { return m_help; }
+ QString description() const { return m_description; }
+ QString value() const { return m_value; }
+ QString text() const { return m_text; }
+ QAccessible::Role role() const { return m_role; }
+ QAccessible::State state() const { return m_state; }
+ QRect boundingRect() const { return m_boundingRect; }
+ double minimumValue() const { return m_minimumValue; }
+ double maximumValue() const { return m_maximumValue; }
+ double currentValue() const { return m_currentValue; }
+ double minimumStepSize() const { return m_minimumStepSize; }
+ int rowIndex() const { return m_rowIndex; }
+ int columnIndex() const { return m_columnIndex; }
+ int rowCount() const { return m_rowCount; }
+ int columnCount() const { return m_columnCount; }
+ int characterCount() const { return m_text.length(); }
+ int cursorPosition() const { return m_cursorPosition; }
+
+private:
+ QString generateControlName(QAccessibleInterface *accessible);
+ QString generateClassName(QAccessibleInterface *accessible);
+ QString generateAutomationId(QAccessibleInterface *accessible);
+ QAccessible::Role generateRole(QAccessibleInterface *accessible);
+ void updateValueData(QAccessibleInterface *accessible);
+ void updateTableData(QAccessibleInterface *accessible);
+ void updateTextData(QAccessibleInterface *accessible);
+ QString m_automationId;
+ QString m_className;
+ QString m_controlName;
+ QString m_accelerator;
+ QString m_access;
+ QString m_help;
+ QString m_description;
+ QString m_value;
+ QString m_text;
+ QAccessible::Role m_role = QAccessible::NoRole;
+ QAccessible::State m_state;
+ QRect m_boundingRect;
+ double m_minimumValue = 0.0;
+ double m_maximumValue = 0.0;
+ double m_currentValue = 0.0;
+ double m_minimumStepSize = 0.0;
+ int m_rowIndex = 0;
+ int m_columnIndex = 0;
+ int m_rowCount = 0;
+ int m_columnCount = 0;
+ int m_cursorPosition = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QWINRTUIACONTROLMETADATA_H
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiaemptypropertyvalue.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaemptypropertyvalue.h
new file mode 100644
index 0000000000..35e4df75fc
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaemptypropertyvalue.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTUIAEMPTYPROPERTYVALUE_H
+#define QWINRTUIAEMPTYPROPERTYVALUE_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include <wrl.h>
+#include <windows.ui.xaml.h>
+
+QT_BEGIN_NAMESPACE
+
+// Implements an empty property value.
+class QWinRTUiaEmptyPropertyValue :
+ public Microsoft::WRL::RuntimeClass<ABI::Windows::Foundation::IPropertyValue>
+{
+ InspectableClass(L"QWinRTUiaEmptyPropertyValue", BaseTrust);
+public:
+
+ HRESULT STDMETHODCALLTYPE get_Type(ABI::Windows::Foundation::PropertyType *value)
+ {
+ *value = ABI::Windows::Foundation::PropertyType_Empty;
+ return S_OK;
+ }
+
+ HRESULT STDMETHODCALLTYPE get_IsNumericScalar(boolean*) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetUInt8(BYTE*) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetInt16(INT16*) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetUInt16(UINT16*) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetInt32(INT32*) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetUInt32(UINT32*) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetInt64(INT64*) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetUInt64(UINT64*) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetSingle(FLOAT*) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetDouble(DOUBLE*) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetChar16(WCHAR*) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetBoolean(boolean*) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetString(HSTRING*) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetGuid(GUID*) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetDateTime(ABI::Windows::Foundation::DateTime*) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetTimeSpan(ABI::Windows::Foundation::TimeSpan*) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetPoint(ABI::Windows::Foundation::Point*) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetSize(ABI::Windows::Foundation::Size*) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetRect(ABI::Windows::Foundation::Rect*) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetUInt8Array(UINT32*, BYTE**) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetInt16Array(UINT32*, INT16**) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetUInt16Array(UINT32*, UINT16**) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetInt32Array(UINT32*, INT32**) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetUInt32Array(UINT32*, UINT32**) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetInt64Array(UINT32*, INT64**) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetUInt64Array(UINT32*, UINT64**) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetSingleArray(UINT32*, FLOAT**) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetDoubleArray(UINT32*, DOUBLE**) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetChar16Array(UINT32*, WCHAR**) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetBooleanArray(UINT32*, boolean**) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetStringArray(UINT32*, HSTRING**) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetInspectableArray(UINT32*, IInspectable***) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetGuidArray(UINT32*, GUID**) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetDateTimeArray(UINT32*, ABI::Windows::Foundation::DateTime**) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetTimeSpanArray(UINT32*, ABI::Windows::Foundation::TimeSpan**) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetPointArray(UINT32*, ABI::Windows::Foundation::Point**) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetSizeArray(UINT32*, ABI::Windows::Foundation::Size**) { return E_FAIL; }
+ HRESULT STDMETHODCALLTYPE GetRectArray(UINT32*, ABI::Windows::Foundation::Rect**) { return E_FAIL; }
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QWINRTUIAEMPTYPROPERTYVALUE_H
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiagriditemprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiagriditemprovider.cpp
new file mode 100644
index 0000000000..524000b618
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiagriditemprovider.cpp
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiagriditemprovider.h"
+#include "qwinrtuiamainprovider.h"
+#include "qwinrtuiametadatacache.h"
+#include "qwinrtuiautils.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QString>
+#include <QtCore/private/qeventdispatcher_winrt_p.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWinRTUiAutomation;
+using namespace ABI::Windows::UI::Xaml::Automation;
+using namespace ABI::Windows::UI::Xaml::Automation::Provider;
+using namespace ABI::Windows::UI::Xaml::Automation::Peers;
+
+QWinRTUiaGridItemProvider::QWinRTUiaGridItemProvider(QAccessible::Id id) :
+ QWinRTUiaBaseProvider(id)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+}
+
+QWinRTUiaGridItemProvider::~QWinRTUiaGridItemProvider()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+}
+
+// Returns the column index of the item.
+HRESULT STDMETHODCALLTYPE QWinRTUiaGridItemProvider::get_Column(INT32 *value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!value)
+ return E_INVALIDARG;
+
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ *value = metadata->columnIndex();
+ return S_OK;
+}
+
+// Returns the number of columns occupied by the item.
+HRESULT STDMETHODCALLTYPE QWinRTUiaGridItemProvider::get_ColumnSpan(INT32 *value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!value)
+ return E_INVALIDARG;
+
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ *value = metadata->columnCount();
+ return S_OK;
+}
+
+// Returns the provider for the containing table/tree.
+HRESULT STDMETHODCALLTYPE QWinRTUiaGridItemProvider::get_ContainingGrid(IIRawElementProviderSimple **value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!value)
+ return E_INVALIDARG;
+ *value = nullptr;
+
+ auto accid = id();
+ auto elementId = QSharedPointer<QAccessible::Id>(new QAccessible::Id(0));
+ auto ptrElementId = new QSharedPointer<QAccessible::Id>(elementId);
+
+ if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, ptrElementId]() {
+ if (QAccessibleInterface *accessible = accessibleForId(accid)) {
+ if (QAccessibleTableCellInterface *tableCellInterface = accessible->tableCellInterface()) {
+ if (QAccessibleInterface *table = tableCellInterface->table()) {
+ **ptrElementId = idForAccessible(table);
+ QWinRTUiaMetadataCache::instance()->load(**ptrElementId);
+ }
+ }
+ }
+ delete ptrElementId;
+ return S_OK;
+ }))) {
+ return E_FAIL;
+ }
+
+ if (!*elementId)
+ return S_OK;
+
+ return QWinRTUiaMainProvider::rawProviderForAccessibleId(*elementId, value);
+}
+
+// Returns the row index of the item.
+HRESULT STDMETHODCALLTYPE QWinRTUiaGridItemProvider::get_Row(INT32 *value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!value)
+ return E_INVALIDARG;
+
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ *value = metadata->rowIndex();
+ return S_OK;
+}
+
+// Returns the number of rows occupied by the item.
+HRESULT STDMETHODCALLTYPE QWinRTUiaGridItemProvider::get_RowSpan(INT32 *value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!value)
+ return E_INVALIDARG;
+
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ *value = metadata->rowCount();
+ return S_OK;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiagriditemprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiagriditemprovider.h
new file mode 100644
index 0000000000..70504fc555
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiagriditemprovider.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTUIAGRIDITEMPROVIDER_H
+#define QWINRTUIAGRIDITEMPROVIDER_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiabaseprovider.h"
+
+#include <wrl.h>
+#include <windows.ui.xaml.h>
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Grid Item control pattern provider. Used by items within a table/tree.
+class QWinRTUiaGridItemProvider :
+ public QWinRTUiaBaseProvider,
+ public Microsoft::WRL::RuntimeClass<ABI::Windows::UI::Xaml::Automation::Provider::IGridItemProvider>
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QWinRTUiaGridItemProvider)
+ InspectableClass(L"QWinRTUiaGridItemProvider", BaseTrust);
+
+public:
+ explicit QWinRTUiaGridItemProvider(QAccessible::Id id);
+ virtual ~QWinRTUiaGridItemProvider();
+
+ // IGridItemProvider
+ HRESULT STDMETHODCALLTYPE get_Column(INT32 *value) override;
+ HRESULT STDMETHODCALLTYPE get_ColumnSpan(INT32 *value) override;
+ HRESULT STDMETHODCALLTYPE get_ContainingGrid(ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple **value) override;
+ HRESULT STDMETHODCALLTYPE get_Row(INT32 *value) override;
+ HRESULT STDMETHODCALLTYPE get_RowSpan(INT32 *value) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QWINRTUIAGRIDITEMPROVIDER_H
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiagridprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiagridprovider.cpp
new file mode 100644
index 0000000000..e469991de2
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiagridprovider.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiagridprovider.h"
+#include "qwinrtuiamainprovider.h"
+#include "qwinrtuiametadatacache.h"
+#include "qwinrtuiautils.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QString>
+#include <QtCore/private/qeventdispatcher_winrt_p.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWinRTUiAutomation;
+using namespace ABI::Windows::UI::Xaml::Automation;
+using namespace ABI::Windows::UI::Xaml::Automation::Provider;
+using namespace ABI::Windows::UI::Xaml::Automation::Peers;
+
+QWinRTUiaGridProvider::QWinRTUiaGridProvider(QAccessible::Id id) :
+ QWinRTUiaBaseProvider(id)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+}
+
+QWinRTUiaGridProvider::~QWinRTUiaGridProvider()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+}
+
+// Returns the number of columns.
+HRESULT STDMETHODCALLTYPE QWinRTUiaGridProvider::get_ColumnCount(INT32 *value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!value)
+ return E_INVALIDARG;
+
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ *value = metadata->columnCount();
+ return S_OK;
+}
+
+// Returns the number of rows.
+HRESULT STDMETHODCALLTYPE QWinRTUiaGridProvider::get_RowCount(INT32 *value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!value)
+ return E_INVALIDARG;
+
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ *value = metadata->rowCount();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaGridProvider::GetItem(INT32 row, INT32 column, IIRawElementProviderSimple **returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ *returnValue = nullptr;
+
+ auto accid = id();
+ auto elementId = QSharedPointer<QAccessible::Id>(new QAccessible::Id(0));
+ auto ptrElementId = new QSharedPointer<QAccessible::Id>(elementId);
+
+ if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, row, column, ptrElementId]() {
+ if (QAccessibleInterface *accessible = accessibleForId(accid)) {
+ if (QAccessibleTableInterface *tableInterface = accessible->tableInterface()) {
+ if ((row >= 0) && (row < tableInterface->rowCount()) && (column >= 0) && (column < tableInterface->columnCount())) {
+ if (QAccessibleInterface *cell = tableInterface->cellAt(row, column)) {
+ **ptrElementId = idForAccessible(cell);
+ QWinRTUiaMetadataCache::instance()->load(**ptrElementId);
+ }
+ }
+ }
+ }
+ delete ptrElementId;
+ return S_OK;
+ }))) {
+ return E_FAIL;
+ }
+
+ if (!*elementId)
+ return E_FAIL;
+
+ return QWinRTUiaMainProvider::rawProviderForAccessibleId(*elementId, returnValue);
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiagridprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiagridprovider.h
new file mode 100644
index 0000000000..d6dfaed315
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiagridprovider.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTUIAGRIDPROVIDER_H
+#define QWINRTUIAGRIDPROVIDER_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiabaseprovider.h"
+
+#include <wrl.h>
+#include <windows.ui.xaml.h>
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Grid control pattern provider. Used by tables/trees.
+class QWinRTUiaGridProvider :
+ public QWinRTUiaBaseProvider,
+ public Microsoft::WRL::RuntimeClass<ABI::Windows::UI::Xaml::Automation::Provider::IGridProvider>
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QWinRTUiaGridProvider)
+ InspectableClass(L"QWinRTUiaGridProvider", BaseTrust);
+
+public:
+ explicit QWinRTUiaGridProvider(QAccessible::Id id);
+ virtual ~QWinRTUiaGridProvider();
+
+ // IGridProvider
+ HRESULT STDMETHODCALLTYPE get_ColumnCount(INT32 *value) override;
+ HRESULT STDMETHODCALLTYPE get_RowCount(INT32 *value) override;
+ HRESULT STDMETHODCALLTYPE GetItem(INT32 row, INT32 column, ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple **returnValue) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QWINRTUIAGRIDPROVIDER_H
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiainvokeprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiainvokeprovider.cpp
new file mode 100644
index 0000000000..e2cf7bc107
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiainvokeprovider.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiainvokeprovider.h"
+#include "qwinrtuiametadatacache.h"
+#include "qwinrtuiautils.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QString>
+#include <QtCore/private/qeventdispatcher_winrt_p.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWinRTUiAutomation;
+using namespace ABI::Windows::UI::Xaml::Automation;
+using namespace ABI::Windows::UI::Xaml::Automation::Provider;
+
+QWinRTUiaInvokeProvider::QWinRTUiaInvokeProvider(QAccessible::Id id) :
+ QWinRTUiaBaseProvider(id)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+}
+
+QWinRTUiaInvokeProvider::~QWinRTUiaInvokeProvider()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaInvokeProvider::Invoke()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ auto accid = id();
+
+ QEventDispatcherWinRT::runOnMainThread([accid]() {
+ if (QAccessibleInterface *accessible = accessibleForId(accid))
+ if (QAccessibleActionInterface *actionInterface = accessible->actionInterface())
+ actionInterface->doAction(QAccessibleActionInterface::pressAction());
+ QWinRTUiaMetadataCache::instance()->load(accid);
+ return S_OK;
+ }, 0);
+ return S_OK;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiainvokeprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiainvokeprovider.h
new file mode 100644
index 0000000000..dfe7917a16
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiainvokeprovider.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTUIAINVOKEPROVIDER_H
+#define QWINRTUIAINVOKEPROVIDER_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiabaseprovider.h"
+
+#include <wrl.h>
+#include <windows.ui.xaml.h>
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Invoke control pattern provider.
+class QWinRTUiaInvokeProvider :
+ public QWinRTUiaBaseProvider,
+ public Microsoft::WRL::RuntimeClass<ABI::Windows::UI::Xaml::Automation::Provider::IInvokeProvider>
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QWinRTUiaInvokeProvider)
+ InspectableClass(L"QWinRTUiaInvokeProvider", BaseTrust);
+
+public:
+ explicit QWinRTUiaInvokeProvider(QAccessible::Id id);
+ virtual ~QWinRTUiaInvokeProvider();
+
+ // IInvokeProvider
+ HRESULT STDMETHODCALLTYPE Invoke() override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QWINRTUIAINVOKEPROVIDER_H
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiamainprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiamainprovider.cpp
new file mode 100644
index 0000000000..6f3ad6dcd2
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiamainprovider.cpp
@@ -0,0 +1,789 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiamainprovider.h"
+#include "qwinrtuiaprovidercache.h"
+#include "qwinrtuiavalueprovider.h"
+#include "qwinrtuiarangevalueprovider.h"
+#include "qwinrtuiatextprovider.h"
+#include "qwinrtuiatoggleprovider.h"
+#include "qwinrtuiainvokeprovider.h"
+#include "qwinrtuiaselectionprovider.h"
+#include "qwinrtuiaselectionitemprovider.h"
+#include "qwinrtuiatableprovider.h"
+#include "qwinrtuiatableitemprovider.h"
+#include "qwinrtuiagridprovider.h"
+#include "qwinrtuiagriditemprovider.h"
+#include "qwinrtuiapeervector.h"
+#include "qwinrtuiametadatacache.h"
+#include "qwinrtuiaemptypropertyvalue.h"
+#include "qwinrtuiautils.h"
+
+#include <QCoreApplication>
+#include <QSemaphore>
+#include <QtCore/QLoggingCategory>
+#include <QtCore/qfunctions_winrt.h>
+#include <QtCore/private/qeventdispatcher_winrt_p.h>
+
+using namespace QWinRTUiAutomation;
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::System;
+using namespace ABI::Windows::UI;
+using namespace ABI::Windows::UI::Core;
+using namespace ABI::Windows::UI::Xaml;
+using namespace ABI::Windows::UI::Xaml::Automation;
+using namespace ABI::Windows::UI::Xaml::Automation::Provider;
+using namespace ABI::Windows::UI::Xaml::Automation::Peers;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
+
+QT_BEGIN_NAMESPACE
+
+QWinRTUiaMainProvider::QWinRTUiaMainProvider(QAccessible::Id id)
+ : QWinRTUiaBaseProvider(id)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ ComPtr<IAutomationPeerFactory> factory;
+ HRESULT hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Automation_Peers_AutomationPeer).Get(), IID_PPV_ARGS(&factory));
+ Q_ASSERT_SUCCEEDED(hr);
+
+ hr = factory->CreateInstance(this, &m_base, &m_core);
+ Q_ASSERT_SUCCEEDED(hr);
+}
+
+QWinRTUiaMainProvider::~QWinRTUiaMainProvider()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::QueryInterface(REFIID iid, LPVOID *iface)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!iface)
+ return E_POINTER;
+ *iface = nullptr;
+
+ if (iid == IID_IUnknown) {
+ *iface = static_cast<IAutomationPeerOverrides *>(this);
+ AddRef();
+ return S_OK;
+ } else if (iid == IID_IAutomationPeerOverrides) {
+ *iface = static_cast<IAutomationPeerOverrides *>(this);
+ AddRef();
+ return S_OK;
+ } else {
+ return m_base.CopyTo(iid, iface);
+ }
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetIids(ULONG *iidCount, IID **iids)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ *iidCount = 0;
+ *iids = nullptr;
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetRuntimeClassName(HSTRING *className)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ return qHString(QStringLiteral("QWinRTUiaMainProvider"), className);
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetTrustLevel(TrustLevel *trustLevel)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ *trustLevel = TrustLevel::BaseTrust;
+ return S_OK;
+}
+
+// Returns a cached instance of the provider for a specific accessible interface.
+QWinRTUiaMainProvider *QWinRTUiaMainProvider::providerForAccessibleId(QAccessible::Id id)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ QWinRTUiaProviderCache *providerCache = QWinRTUiaProviderCache::instance();
+ QWinRTUiaMainProvider *provider = qobject_cast<QWinRTUiaMainProvider *>(providerCache->providerForId(id));
+
+ if (provider) {
+ provider->AddRef();
+ } else {
+ ComPtr<QWinRTUiaMainProvider> p = Make<QWinRTUiaMainProvider>(id);
+ provider = p.Get();
+ provider->AddRef();
+ providerCache->insert(id, provider);
+ }
+ return provider;
+}
+
+// Returns an IIRawElementProviderSimple for a specific accessible interface.
+HRESULT QWinRTUiaMainProvider::rawProviderForAccessibleId(QAccessible::Id elementId,
+ IIRawElementProviderSimple **returnValue)
+{
+ if (!returnValue)
+ return E_INVALIDARG;
+ *returnValue = nullptr;
+
+ if (ComPtr<QWinRTUiaMainProvider> provider = providerForAccessibleId(elementId)) {
+ ComPtr<IAutomationPeer> automationPeer;
+ if (SUCCEEDED(provider.As(&automationPeer))) {
+ ComPtr<IAutomationPeerProtected> automationPeerProtected;
+ if (SUCCEEDED(provider.As(&automationPeerProtected))) {
+ return automationPeerProtected->ProviderFromPeer(automationPeer.Get(), returnValue);
+ }
+ }
+ }
+ return E_FAIL;
+}
+
+// Returns an array of IIRawElementProviderSimple instances for a list of accessible interface ids.
+HRESULT QWinRTUiaMainProvider::rawProviderArrayForAccessibleIdList(const QList<QAccessible::Id> &elementIds,
+ UINT32 *returnValueSize,
+ IIRawElementProviderSimple ***returnValue)
+{
+ if (!returnValueSize || !returnValue)
+ return E_INVALIDARG;
+ *returnValueSize = 0;
+ *returnValue = nullptr;
+
+ QList<IIRawElementProviderSimple *> rawProviderList;
+
+ for (auto elementId : qAsConst(elementIds)) {
+ IIRawElementProviderSimple *rawProvider;
+ if (SUCCEEDED(rawProviderForAccessibleId(elementId, &rawProvider)))
+ rawProviderList.append(rawProvider);
+ }
+
+ if (rawProviderList.size() == 0)
+ return S_OK;
+
+ *returnValue = static_cast<IIRawElementProviderSimple **>(CoTaskMemAlloc(rawProviderList.size() * sizeof(IIRawElementProviderSimple *)));
+ if (!*returnValue) {
+ for (auto rawProvider : qAsConst(rawProviderList))
+ rawProvider->Release();
+ return E_OUTOFMEMORY;
+ }
+
+ int index = 0;
+ for (auto rawProvider : qAsConst(rawProviderList))
+ (*returnValue)[index++] = rawProvider;
+ *returnValueSize = rawProviderList.size();
+ return S_OK;
+}
+
+void QWinRTUiaMainProvider::notifyFocusChange(QAccessibleEvent *event)
+{
+ if (QAccessibleInterface *accessible = event->accessibleInterface()) {
+ QAccessible::Id accid = idForAccessible(accessible);
+ QWinRTUiaMetadataCache::instance()->load(accid);
+ QEventDispatcherWinRT::runOnXamlThread([accid]() {
+ if (ComPtr<QWinRTUiaMainProvider> provider = providerForAccessibleId(accid)) {
+ ComPtr<IAutomationPeer> automationPeer;
+ if (SUCCEEDED(provider->QueryInterface(IID_PPV_ARGS(&automationPeer)))) {
+ automationPeer->RaiseAutomationEvent(AutomationEvents_AutomationFocusChanged);
+ }
+ }
+ return S_OK;
+ }, false);
+ }
+}
+
+void QWinRTUiaMainProvider::notifyVisibilityChange(QAccessibleEvent *event)
+{
+ if (QAccessibleInterface *accessible = event->accessibleInterface()) {
+ QAccessible::Id accid = idForAccessible(accessible);
+ QWinRTUiaMetadataCache::instance()->load(accid);
+ }
+}
+
+void QWinRTUiaMainProvider::notifyStateChange(QAccessibleStateChangeEvent *event)
+{
+ if (QAccessibleInterface *accessible = event->accessibleInterface()) {
+ QAccessible::Id accid = idForAccessible(accessible);
+ QWinRTUiaMetadataCache::instance()->load(accid);
+
+ if (event->changedStates().checked || event->changedStates().checkStateMixed) {
+ // Notifies states changes in checkboxes.
+ if (accessible->role() == QAccessible::CheckBox) {
+ QEventDispatcherWinRT::runOnXamlThread([accid]() {
+ if (ComPtr<QWinRTUiaMainProvider> provider = providerForAccessibleId(accid)) {
+ ComPtr<IAutomationPeer> automationPeer;
+ if (SUCCEEDED(provider->QueryInterface(IID_PPV_ARGS(&automationPeer)))) {
+ ComPtr<ITogglePatternIdentifiersStatics> toggleStatics;
+ if (SUCCEEDED(RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Automation_TogglePatternIdentifiers).Get(), IID_PPV_ARGS(&toggleStatics)))) {
+ ComPtr<IAutomationProperty> toggleStateProperty;
+ if (SUCCEEDED(toggleStatics->get_ToggleStateProperty(&toggleStateProperty))) {
+ ComPtr<QWinRTUiaEmptyPropertyValue> emptyValue = Make<QWinRTUiaEmptyPropertyValue>();
+ // by sending an event with an empty value we force ui automation to refresh its state
+ automationPeer->RaisePropertyChangedEvent(toggleStateProperty.Get(), emptyValue.Get(), emptyValue.Get());
+ }
+ }
+ }
+ }
+ return S_OK;
+ }, false);
+ }
+ }
+ if (event->changedStates().active) {
+ if (accessible->role() == QAccessible::Window) {
+ // Notifies window opened/closed.
+ bool active = accessible->state().active;
+ QEventDispatcherWinRT::runOnXamlThread([accid, active]() {
+ if (ComPtr<QWinRTUiaMainProvider> provider = providerForAccessibleId(accid)) {
+ ComPtr<IAutomationPeer> automationPeer;
+ if (SUCCEEDED(provider->QueryInterface(IID_PPV_ARGS(&automationPeer)))) {
+ if (active) {
+ automationPeer->RaiseAutomationEvent(AutomationEvents_WindowOpened);
+ } else {
+ automationPeer->RaiseAutomationEvent(AutomationEvents_WindowClosed);
+ }
+ }
+ }
+ return S_OK;
+ }, false);
+ }
+ }
+ }
+}
+
+void QWinRTUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *event)
+{
+ if (QAccessibleInterface *accessible = event->accessibleInterface()) {
+ QAccessible::Id accid = idForAccessible(accessible);
+ QWinRTUiaMetadataCache::instance()->load(accid);
+ if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
+ // Notifies changes in values of controls supporting the value interface.
+ double value = valueInterface->currentValue().toDouble();
+ QEventDispatcherWinRT::runOnXamlThread([accid, value]() {
+ // For some reason RaisePropertyChangedEvent() does not seem to be
+ // forwarding notifications for any property types except empty,
+ // which would do nothing here. ToDo: find a workaround.
+ return S_OK;
+ }, false);
+ }
+ }
+}
+
+// Notifies changes in text content and selection state of text controls.
+void QWinRTUiaMainProvider::notifyTextChange(QAccessibleEvent *event)
+{
+ if (QAccessibleInterface *accessible = event->accessibleInterface()) {
+ QAccessible::Id accid = idForAccessible(accessible);
+ QWinRTUiaMetadataCache::instance()->load(accid);
+ bool readOnly = accessible->state().readOnly;
+ QAccessible::Event eventType = event->type();
+ if (accessible->textInterface()) {
+ QEventDispatcherWinRT::runOnXamlThread([accid, eventType, readOnly]() {
+ if (ComPtr<QWinRTUiaMainProvider> provider = providerForAccessibleId(accid)) {
+ ComPtr<IAutomationPeer> automationPeer;
+ if (SUCCEEDED(provider->QueryInterface(IID_PPV_ARGS(&automationPeer)))) {
+ if (eventType == QAccessible::TextSelectionChanged) {
+ automationPeer->RaiseAutomationEvent(AutomationEvents_TextPatternOnTextSelectionChanged);
+ } else if (eventType == QAccessible::TextCaretMoved) {
+ if (!readOnly) {
+ automationPeer->RaiseAutomationEvent(AutomationEvents_TextPatternOnTextSelectionChanged);
+ }
+ } else {
+ automationPeer->RaiseAutomationEvent(AutomationEvents_TextPatternOnTextChanged);
+ }
+ }
+ }
+ return S_OK;
+ }, false);
+ }
+ }
+}
+
+// Return providers for specific control patterns
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetPatternCore(PatternInterface patternInterface, IInspectable **returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << patternInterface;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ *returnValue = nullptr;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return E_FAIL;
+
+ switch (patternInterface) {
+ case PatternInterface_Text:
+ case PatternInterface_Text2: {
+ // All text controls.
+ if (accessible->textInterface()) {
+ ComPtr<QWinRTUiaTextProvider> provider = Make<QWinRTUiaTextProvider>(id());
+ return provider.CopyTo(returnValue);
+ }
+ break;
+ }
+ case PatternInterface_Value: {
+ // All accessible controls return text(QAccessible::Value) (which may be empty).
+ ComPtr<QWinRTUiaValueProvider> provider = Make<QWinRTUiaValueProvider>(id());
+ return provider.CopyTo(returnValue);
+ }
+ case PatternInterface_RangeValue: {
+ // Controls providing a numeric value within a range (e.g., sliders, scroll bars, dials).
+ if (accessible->valueInterface()) {
+ ComPtr<QWinRTUiaRangeValueProvider> provider = Make<QWinRTUiaRangeValueProvider>(id());
+ return provider.CopyTo(returnValue);
+ }
+ break;
+ }
+ case PatternInterface_Toggle: {
+ // Checkbox controls.
+ if (accessible->role() == QAccessible::CheckBox) {
+ ComPtr<QWinRTUiaToggleProvider> provider = Make<QWinRTUiaToggleProvider>(id());
+ return provider.CopyTo(returnValue);
+ }
+ break;
+ }
+ case PatternInterface_Selection: {
+ // Lists of items.
+ if (accessible->role() == QAccessible::List) {
+ ComPtr<QWinRTUiaSelectionProvider> provider = Make<QWinRTUiaSelectionProvider>(id());
+ return provider.CopyTo(returnValue);
+ }
+ break;
+ }
+ case PatternInterface_SelectionItem: {
+ // Items within a list and radio buttons.
+ if ((accessible->role() == QAccessible::RadioButton)
+ || (accessible->role() == QAccessible::ListItem)) {
+ ComPtr<QWinRTUiaSelectionItemProvider> provider = Make<QWinRTUiaSelectionItemProvider>(id());
+ return provider.CopyTo(returnValue);
+ }
+ break;
+ }
+ case PatternInterface_Table: {
+ // Table/tree.
+ if (accessible->tableInterface()
+ && ((accessible->role() == QAccessible::Table) || (accessible->role() == QAccessible::Tree))) {
+ ComPtr<QWinRTUiaTableProvider> provider = Make<QWinRTUiaTableProvider>(id());
+ return provider.CopyTo(returnValue);
+ }
+ break;
+ }
+ case PatternInterface_TableItem: {
+ // Item within a table/tree.
+ if (accessible->tableCellInterface()
+ && ((accessible->role() == QAccessible::Cell) || (accessible->role() == QAccessible::TreeItem))) {
+ ComPtr<QWinRTUiaTableItemProvider> provider = Make<QWinRTUiaTableItemProvider>(id());
+ return provider.CopyTo(returnValue);
+ }
+ break;
+ }
+ case PatternInterface_Grid: {
+ // Table/tree.
+ if (accessible->tableInterface()
+ && ((accessible->role() == QAccessible::Table) || (accessible->role() == QAccessible::Tree))) {
+ ComPtr<QWinRTUiaGridProvider> provider = Make<QWinRTUiaGridProvider>(id());
+ return provider.CopyTo(returnValue);
+ }
+ break;
+ }
+ case PatternInterface_GridItem: {
+ // Item within a table/tree.
+ if (accessible->tableCellInterface()
+ && ((accessible->role() == QAccessible::Cell) || (accessible->role() == QAccessible::TreeItem))) {
+ ComPtr<QWinRTUiaGridItemProvider> provider = Make<QWinRTUiaGridItemProvider>(id());
+ return provider.CopyTo(returnValue);
+ }
+ break;
+ }
+ case PatternInterface_Invoke: {
+ // Things that have an invokable action (e.g., simple buttons).
+ if (accessible->actionInterface()) {
+ ComPtr<QWinRTUiaInvokeProvider> provider = Make<QWinRTUiaInvokeProvider>(id());
+ return provider.CopyTo(returnValue);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetAcceleratorKeyCore(HSTRING *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ return qHString(metadata->accelerator(), returnValue);
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetAccessKeyCore(HSTRING *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ return qHString(metadata->access(), returnValue);
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetAutomationControlTypeCore(AutomationControlType *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ *returnValue = roleToControlType(metadata->role());
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetAutomationIdCore(HSTRING *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ return qHString(metadata->automationId(), returnValue);
+}
+
+// Returns the bounding rectangle for the accessible control.
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetBoundingRectangleCore(ABI::Windows::Foundation::Rect *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+
+ QRect rect = metadata->boundingRect();
+ returnValue->X = rect.x();
+ returnValue->Y = rect.y();
+ returnValue->Width = rect.width();
+ returnValue->Height = rect.height();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetChildrenCore(IVector<AutomationPeer *> **returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ *returnValue = nullptr;
+
+ auto accid = id();
+ auto children = QSharedPointer<QList<QAccessible::Id>>(new QList<QAccessible::Id>);
+ auto ptrChildren = new QSharedPointer<QList<QAccessible::Id>>(children);
+
+ if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, ptrChildren]() {
+ if (QAccessibleInterface *accessible = accessibleForId(accid)) {
+ int childCount = accessible->childCount();
+ for (int i = 0; i < childCount; ++i) {
+ if (QAccessibleInterface *childAcc = accessible->child(i)) {
+ QAccessible::Id childId = idForAccessible(childAcc);
+ QWinRTUiaMetadataCache::instance()->load(childId);
+ if (!childAcc->state().invisible)
+ (*ptrChildren)->append(childId);
+ }
+ }
+ }
+ delete ptrChildren;
+ return S_OK;
+ }))) {
+ return E_FAIL;
+ }
+
+ ComPtr<IVector<AutomationPeer *>> peerVector = Make<QWinRTUiaPeerVector>();
+
+ for (auto childId : qAsConst(*children)) {
+ if (ComPtr<QWinRTUiaMainProvider> provider = providerForAccessibleId(childId)) {
+ IAutomationPeer *peer;
+ if (SUCCEEDED(provider.CopyTo(&peer)))
+ peerVector->Append(peer);
+ }
+ }
+ return peerVector.CopyTo(returnValue);
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetClassNameCore(HSTRING *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ return qHString(metadata->className(), returnValue);
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetClickablePointCore(ABI::Windows::Foundation::Point *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetHelpTextCore(HSTRING *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ return qHString(metadata->help(), returnValue);
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetItemStatusCore(HSTRING *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetItemTypeCore(HSTRING *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetLabeledByCore(IAutomationPeer **returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetLocalizedControlTypeCore(HSTRING *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetNameCore(HSTRING *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ return qHString(metadata->controlName(), returnValue);
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetOrientationCore(AutomationOrientation *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ *returnValue = AutomationOrientation_None;
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::HasKeyboardFocusCore(boolean *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ *returnValue = (metadata->state().focused != 0);
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::IsContentElementCore(boolean *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ *returnValue = true;
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::IsControlElementCore(boolean *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ *returnValue = true;
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::IsEnabledCore(boolean *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ *returnValue = (metadata->state().disabled == 0);
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::IsKeyboardFocusableCore(boolean *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ *returnValue = (metadata->state().focusable != 0);
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::IsOffscreenCore(boolean *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ *returnValue = (metadata->state().offscreen != 0);
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::IsPasswordCore(boolean *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ *returnValue = (metadata->role() == QAccessible::EditableText) && (metadata->state().passwordEdit != 0);
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::IsRequiredForFormCore(boolean *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ *returnValue = false;
+ return S_OK;
+}
+
+// Sets focus to the control.
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::SetFocusCore()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible)
+ return E_FAIL;
+
+ QAccessibleActionInterface *actionInterface = accessible->actionInterface();
+ if (!actionInterface)
+ return E_FAIL;
+
+ QEventDispatcherWinRT::runOnMainThread([actionInterface]() {
+ actionInterface->doAction(QAccessibleActionInterface::setFocusAction());
+ return S_OK;
+ });
+ return S_OK;
+}
+
+// Returns a provider for the UI element present at the specified screen coordinates.
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetPeerFromPointCore(ABI::Windows::Foundation::Point point, IAutomationPeer **returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ *returnValue = nullptr;
+
+ // Scale coordinates from High DPI screens?
+
+ auto accid = id();
+ auto elementId = QSharedPointer<QAccessible::Id>(new QAccessible::Id(0));
+ auto ptrElementId = new QSharedPointer<QAccessible::Id>(elementId);
+
+ if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, ptrElementId, point]() {
+ // Controls can be embedded within grouping elements. By default returns the innermost control.
+ QAccessibleInterface *target = accessibleForId(accid);
+ while (QAccessibleInterface *tmpacc = target->childAt(point.X, point.Y)) {
+ target = tmpacc;
+ // For accessibility tools it may be better to return the text element instead of its subcomponents.
+ if (target->textInterface()) break;
+ }
+ **ptrElementId = idForAccessible(target);
+ QWinRTUiaMetadataCache::instance()->load(**ptrElementId);
+ delete ptrElementId;
+ return S_OK;
+ }))) {
+ return E_FAIL;
+ }
+
+ if (ComPtr<QWinRTUiaMainProvider> provider = providerForAccessibleId(*elementId))
+ return provider.CopyTo(returnValue);
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaMainProvider::GetLiveSettingCore(AutomationLiveSetting *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ return E_NOTIMPL;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiamainprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiamainprovider.h
new file mode 100644
index 0000000000..384a166cf7
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiamainprovider.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTUIAMAINPROVIDER_H
+#define QWINRTUIAMAINPROVIDER_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiabaseprovider.h"
+
+#include <QtCore/qglobal.h>
+#include <QtCore/QPointer>
+#include <QtCore/QSharedPointer>
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+
+#include <wrl.h>
+#include <windows.ui.xaml.h>
+
+QT_BEGIN_NAMESPACE
+
+// The main WinRT UI Automation class.
+class QWinRTUiaMainProvider:
+ public QWinRTUiaBaseProvider,
+ public Microsoft::WRL::RuntimeClass<ABI::Windows::UI::Xaml::Automation::Peers::IAutomationPeerOverrides>
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QWinRTUiaMainProvider)
+
+public:
+ explicit QWinRTUiaMainProvider(QAccessible::Id id);
+ virtual ~QWinRTUiaMainProvider();
+ static QWinRTUiaMainProvider *providerForAccessibleId(QAccessible::Id id);
+ static HRESULT rawProviderForAccessibleId(QAccessible::Id elementId, ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple **returnValue);
+ static HRESULT rawProviderArrayForAccessibleIdList(const QList<QAccessible::Id> &elementIds, UINT32 *returnValueSize, ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple ***returnValue);
+ static void notifyFocusChange(QAccessibleEvent *event);
+ static void notifyVisibilityChange(QAccessibleEvent *event);
+ static void notifyStateChange(QAccessibleStateChangeEvent *event);
+ static void notifyValueChange(QAccessibleValueChangeEvent *event);
+ static void notifyTextChange(QAccessibleEvent *event);
+
+ // IUnknown
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface) override;
+
+ // IInspectable
+ HRESULT STDMETHODCALLTYPE GetIids(ULONG *iidCount, IID **iids) override;
+ HRESULT STDMETHODCALLTYPE GetRuntimeClassName(HSTRING *className) override;
+ HRESULT STDMETHODCALLTYPE GetTrustLevel(TrustLevel *trustLevel) override;
+
+ // IAutomationPeerOverrides
+ HRESULT STDMETHODCALLTYPE GetPatternCore(ABI::Windows::UI::Xaml::Automation::Peers::PatternInterface patternInterface, IInspectable **returnValue) override;
+ HRESULT STDMETHODCALLTYPE GetAcceleratorKeyCore(HSTRING *returnValue) override;
+ HRESULT STDMETHODCALLTYPE GetAccessKeyCore(HSTRING *returnValue) override;
+ HRESULT STDMETHODCALLTYPE GetAutomationControlTypeCore(ABI::Windows::UI::Xaml::Automation::Peers::AutomationControlType *returnValue) override;
+ HRESULT STDMETHODCALLTYPE GetAutomationIdCore(HSTRING *returnValue) override;
+ HRESULT STDMETHODCALLTYPE GetBoundingRectangleCore(ABI::Windows::Foundation::Rect *returnValue) override;
+ HRESULT STDMETHODCALLTYPE GetChildrenCore(ABI::Windows::Foundation::Collections::IVector<ABI::Windows::UI::Xaml::Automation::Peers::AutomationPeer*> **returnValue) override;
+ HRESULT STDMETHODCALLTYPE GetClassNameCore(HSTRING *returnValue) override;
+ HRESULT STDMETHODCALLTYPE GetClickablePointCore(ABI::Windows::Foundation::Point *returnValue) override;
+ HRESULT STDMETHODCALLTYPE GetHelpTextCore(HSTRING *returnValue) override;
+ HRESULT STDMETHODCALLTYPE GetItemStatusCore(HSTRING *returnValue) override;
+ HRESULT STDMETHODCALLTYPE GetItemTypeCore(HSTRING *returnValue) override;
+ HRESULT STDMETHODCALLTYPE GetLabeledByCore(ABI::Windows::UI::Xaml::Automation::Peers::IAutomationPeer **returnValue) override;
+ HRESULT STDMETHODCALLTYPE GetLocalizedControlTypeCore(HSTRING *returnValue) override;
+ HRESULT STDMETHODCALLTYPE GetNameCore(HSTRING *returnValue) override;
+ HRESULT STDMETHODCALLTYPE GetOrientationCore(ABI::Windows::UI::Xaml::Automation::Peers::AutomationOrientation *returnValue) override;
+ HRESULT STDMETHODCALLTYPE HasKeyboardFocusCore(boolean *returnValue) override;
+ HRESULT STDMETHODCALLTYPE IsContentElementCore(boolean *returnValue) override;
+ HRESULT STDMETHODCALLTYPE IsControlElementCore(boolean *returnValue) override;
+ HRESULT STDMETHODCALLTYPE IsEnabledCore(boolean *returnValue) override;
+ HRESULT STDMETHODCALLTYPE IsKeyboardFocusableCore(boolean *returnValue) override;
+ HRESULT STDMETHODCALLTYPE IsOffscreenCore(boolean *returnValue) override;
+ HRESULT STDMETHODCALLTYPE IsPasswordCore(boolean *returnValue) override;
+ HRESULT STDMETHODCALLTYPE IsRequiredForFormCore(boolean *returnValue) override;
+ HRESULT STDMETHODCALLTYPE SetFocusCore() override;
+ HRESULT STDMETHODCALLTYPE GetPeerFromPointCore(ABI::Windows::Foundation::Point point, ABI::Windows::UI::Xaml::Automation::Peers::IAutomationPeer **returnValue) override;
+ HRESULT STDMETHODCALLTYPE GetLiveSettingCore(ABI::Windows::UI::Xaml::Automation::Peers::AutomationLiveSetting *returnValue) override;
+
+private:
+ Microsoft::WRL::ComPtr<ABI::Windows::UI::Xaml::Automation::Peers::IAutomationPeerOverrides> m_base;
+ Microsoft::WRL::ComPtr<ABI::Windows::UI::Xaml::Automation::Peers::IAutomationPeer> m_core;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QWINRTUIAMAINPROVIDER_H
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiametadatacache.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiametadatacache.cpp
new file mode 100644
index 0000000000..442ff184a8
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiametadatacache.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiametadatacache.h"
+#include "qwinrtuiautils.h"
+
+#include <QtCore/QLoggingCategory>
+#include <QtCore/private/qeventdispatcher_winrt_p.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWinRTUiAutomation;
+
+// Private constructor
+QWinRTUiaMetadataCache::QWinRTUiaMetadataCache()
+{
+}
+
+// shared instance
+QWinRTUiaMetadataCache *QWinRTUiaMetadataCache::instance()
+{
+ static QWinRTUiaMetadataCache metadataCache;
+ return &metadataCache;
+}
+
+// Returns the cached metadata associated with the ID, or an instance with default values.
+QSharedPointer<QWinRTUiaControlMetadata> QWinRTUiaMetadataCache::metadataForId(QAccessible::Id id)
+{
+ QSharedPointer<QWinRTUiaControlMetadata> metadata;
+
+ m_mutex.lock();
+ if (m_metadataTable.contains(id))
+ metadata = m_metadataTable[id];
+ else
+ metadata = QSharedPointer<QWinRTUiaControlMetadata>(new QWinRTUiaControlMetadata);
+ m_mutex.unlock();
+ return metadata;
+}
+
+// Caches metadata from the accessibility framework within the main thread.
+bool QWinRTUiaMetadataCache::load(QAccessible::Id id)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([id]() {
+ QWinRTUiaMetadataCache::instance()->insert(id, QSharedPointer<QWinRTUiaControlMetadata>(new QWinRTUiaControlMetadata(id)));
+ return S_OK;
+ }))) {
+ return false;
+ }
+ return true;
+}
+
+// Inserts metadata in the cache and associates it with an accessibility ID.
+void QWinRTUiaMetadataCache::insert(QAccessible::Id id, const QSharedPointer<QWinRTUiaControlMetadata> &metadata)
+{
+ m_mutex.lock();
+ m_metadataTable[id] = metadata;
+ m_mutex.unlock();
+}
+
+// Removes metadata with a given id from the cache.
+void QWinRTUiaMetadataCache::remove(QAccessible::Id id)
+{
+ m_mutex.lock();
+ m_metadataTable.remove(id);
+ m_mutex.unlock();
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiametadatacache.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiametadatacache.h
new file mode 100644
index 0000000000..2d68d1b654
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiametadatacache.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTUIAMETADATACACHE_H
+#define QWINRTUIAMETADATACACHE_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiacontrolmetadata.h"
+
+#include <QtCore/QHash>
+#include <QtCore/QMutex>
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+
+QT_BEGIN_NAMESPACE
+
+// Singleton used to cache metadata using the accessibility ID as the key.
+class QWinRTUiaMetadataCache : public QObject
+{
+ QWinRTUiaMetadataCache();
+ Q_OBJECT
+public:
+ static QWinRTUiaMetadataCache *instance();
+ QSharedPointer<QWinRTUiaControlMetadata> metadataForId(QAccessible::Id id);
+ void insert(QAccessible::Id id, const QSharedPointer<QWinRTUiaControlMetadata> &metadata);
+ void remove(QAccessible::Id id);
+ bool load(QAccessible::Id id);
+
+private:
+ QHash<QAccessible::Id, QSharedPointer<QWinRTUiaControlMetadata>> m_metadataTable;
+ QMutex m_mutex;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QWINRTUIAMETADATACACHE_H
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiapeervector.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiapeervector.cpp
new file mode 100644
index 0000000000..e3d6bcae4b
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiapeervector.cpp
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiapeervector.h"
+#include "qwinrtuiautils.h"
+
+using namespace ABI::Windows::UI::Xaml::Automation::Peers;
+using namespace ABI::Windows::Foundation::Collections;
+
+QT_BEGIN_NAMESPACE
+
+HRESULT QWinRTUiaPeerVector::GetAt(quint32 index, IAutomationPeer **item)
+{
+ if (index >= quint32(m_impl.size()))
+ return E_FAIL;
+ if ((*item = m_impl.at(index)))
+ (*item)->AddRef();
+ return S_OK;
+}
+
+HRESULT QWinRTUiaPeerVector::get_Size(quint32 *size)
+{
+ *size = m_impl.size();
+ return S_OK;
+}
+
+HRESULT QWinRTUiaPeerVector::GetView(IVectorView<AutomationPeer *> **view)
+{
+ *view = nullptr;
+ return E_NOTIMPL;
+}
+
+HRESULT QWinRTUiaPeerVector::IndexOf(IAutomationPeer *value, quint32 *index, boolean *found)
+{
+ int idx = m_impl.indexOf(value);
+ if (idx > -1) {
+ *index = quint32(idx);
+ *found = true;
+ } else {
+ *found = false;
+ }
+ return S_OK;
+}
+
+HRESULT QWinRTUiaPeerVector::SetAt(quint32 index, IAutomationPeer *item)
+{
+ if (index >= quint32(m_impl.size()))
+ return E_FAIL;
+ if (IAutomationPeer *elem = m_impl.at(index)) {
+ if (elem == item)
+ return S_OK;
+ else
+ elem->Release();
+ }
+ if (item)
+ item->AddRef();
+ m_impl[index] = item;
+ return S_OK;
+}
+
+HRESULT QWinRTUiaPeerVector::InsertAt(quint32 index, IAutomationPeer *item)
+{
+ if (index >= quint32(m_impl.size()))
+ return E_FAIL;
+ if (item)
+ item->AddRef();
+ m_impl.insert(index, item);
+ return S_OK;
+}
+
+HRESULT QWinRTUiaPeerVector::RemoveAt(quint32 index)
+{
+ if (index >= quint32(m_impl.size()))
+ return E_FAIL;
+ if (IAutomationPeer *elem = m_impl.at(index))
+ elem->Release();
+ m_impl.remove(index);
+ return S_OK;
+}
+
+HRESULT QWinRTUiaPeerVector::Append(IAutomationPeer *item)
+{
+ if (item)
+ item->AddRef();
+ m_impl.append(item);
+ return S_OK;
+}
+
+HRESULT QWinRTUiaPeerVector::RemoveAtEnd()
+{
+ if (m_impl.size() == 0)
+ return E_FAIL;
+ if (IAutomationPeer *elem = m_impl.last())
+ elem->Release();
+ m_impl.removeLast();
+ return S_OK;
+}
+
+HRESULT QWinRTUiaPeerVector::Clear()
+{
+ for (auto elem : qAsConst(m_impl))
+ if (elem)
+ elem->Release();
+ m_impl.clear();
+ return S_OK;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiapeervector.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiapeervector.h
new file mode 100644
index 0000000000..265526de09
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiapeervector.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTUIAPEERVECTOR_H
+#define QWINRTUIAPEERVECTOR_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include <QtCore/QString>
+#include <QtCore/qt_windows.h>
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtGui/QWindow>
+#include <QVector>
+
+#include <wrl.h>
+#include <windows.ui.xaml.h>
+
+QT_BEGIN_NAMESPACE
+
+// Implements IVector<AutomationPeer *>
+class QWinRTUiaPeerVector : public Microsoft::WRL::RuntimeClass<ABI::Windows::Foundation::Collections::IVector<ABI::Windows::UI::Xaml::Automation::Peers::AutomationPeer *>>
+{
+public:
+ HRESULT STDMETHODCALLTYPE GetAt(quint32 index, ABI::Windows::UI::Xaml::Automation::Peers::IAutomationPeer **item) override;
+ HRESULT STDMETHODCALLTYPE get_Size(quint32 *size) override;
+ HRESULT STDMETHODCALLTYPE GetView(ABI::Windows::Foundation::Collections::IVectorView<ABI::Windows::UI::Xaml::Automation::Peers::AutomationPeer *> **view) override;
+ HRESULT STDMETHODCALLTYPE IndexOf(ABI::Windows::UI::Xaml::Automation::Peers::IAutomationPeer *value, quint32 *index, boolean *found) override;
+ HRESULT STDMETHODCALLTYPE SetAt(quint32 index, ABI::Windows::UI::Xaml::Automation::Peers::IAutomationPeer *item) override;
+ HRESULT STDMETHODCALLTYPE InsertAt(quint32 index, ABI::Windows::UI::Xaml::Automation::Peers::IAutomationPeer *item) override;
+ HRESULT STDMETHODCALLTYPE RemoveAt(quint32 index) override;
+ HRESULT STDMETHODCALLTYPE Append(ABI::Windows::UI::Xaml::Automation::Peers::IAutomationPeer *item) override;
+ HRESULT STDMETHODCALLTYPE RemoveAtEnd() override;
+ HRESULT STDMETHODCALLTYPE Clear() override;
+private:
+ QVector<ABI::Windows::UI::Xaml::Automation::Peers::IAutomationPeer *> m_impl;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QWINRTUIAPEERVECTOR_H
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiaprovidercache.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaprovidercache.cpp
new file mode 100644
index 0000000000..06ff094c45
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaprovidercache.cpp
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiaprovidercache.h"
+
+QT_BEGIN_NAMESPACE
+
+// Private constructor
+QWinRTUiaProviderCache::QWinRTUiaProviderCache()
+{
+}
+
+// shared instance
+QWinRTUiaProviderCache *QWinRTUiaProviderCache::instance()
+{
+ static QWinRTUiaProviderCache providerCache;
+ return &providerCache;
+}
+
+// Returns the provider instance associated with the ID, or nullptr.
+QWinRTUiaBaseProvider *QWinRTUiaProviderCache::providerForId(QAccessible::Id id) const
+{
+ return m_providerTable.value(id);
+}
+
+// Inserts a provider in the cache and associates it with an accessibility ID.
+void QWinRTUiaProviderCache::insert(QAccessible::Id id, QWinRTUiaBaseProvider *provider)
+{
+ remove(id);
+ if (provider) {
+ m_providerTable[id] = provider;
+ m_inverseTable[provider] = id;
+ // Connects the destroyed signal to our slot, to remove deleted objects from the cache.
+ QObject::connect(provider, &QObject::destroyed, this, &QWinRTUiaProviderCache::objectDestroyed);
+ }
+}
+
+// Removes deleted provider objects from the cache.
+void QWinRTUiaProviderCache::objectDestroyed(QObject *obj)
+{
+ // We have to use the inverse table to map the object address back to its ID,
+ // since at this point (called from QObject destructor), it has already been
+ // partially destroyed and we cannot treat it as a provider.
+ auto it = m_inverseTable.find(obj);
+ if (it != m_inverseTable.end()) {
+ m_providerTable.remove(*it);
+ m_inverseTable.remove(obj);
+ }
+}
+
+// Removes a provider with a given id from the cache.
+void QWinRTUiaProviderCache::remove(QAccessible::Id id)
+{
+ m_inverseTable.remove(m_providerTable.value(id));
+ m_providerTable.remove(id);
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiaprovidercache.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaprovidercache.h
new file mode 100644
index 0000000000..393ef7d562
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaprovidercache.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTUIAPROVIDERCACHE_H
+#define QWINRTUIAPROVIDERCACHE_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiabaseprovider.h"
+
+#include <QtCore/QHash>
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+
+QT_BEGIN_NAMESPACE
+
+// Singleton used to cache provider instances using the accessibility ID as the key.
+class QWinRTUiaProviderCache : public QObject
+{
+ QWinRTUiaProviderCache();
+ Q_OBJECT
+public:
+ static QWinRTUiaProviderCache *instance();
+ QWinRTUiaBaseProvider *providerForId(QAccessible::Id id) const;
+ void insert(QAccessible::Id id, QWinRTUiaBaseProvider *provider);
+ void remove(QAccessible::Id id);
+
+private Q_SLOTS:
+ void objectDestroyed(QObject *obj);
+
+private:
+ QHash<QAccessible::Id, QWinRTUiaBaseProvider *> m_providerTable;
+ QHash<QObject *, QAccessible::Id> m_inverseTable;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QWINRTUIAPROVIDERCACHE_H
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiarangevalueprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiarangevalueprovider.cpp
new file mode 100644
index 0000000000..4ac59c890a
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiarangevalueprovider.cpp
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiarangevalueprovider.h"
+#include "qwinrtuiametadatacache.h"
+#include "qwinrtuiautils.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QString>
+#include <QtCore/private/qeventdispatcher_winrt_p.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWinRTUiAutomation;
+using namespace ABI::Windows::UI::Xaml::Automation;
+using namespace ABI::Windows::UI::Xaml::Automation::Provider;
+
+QWinRTUiaRangeValueProvider::QWinRTUiaRangeValueProvider(QAccessible::Id id) :
+ QWinRTUiaBaseProvider(id)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+}
+
+QWinRTUiaRangeValueProvider::~QWinRTUiaRangeValueProvider()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaRangeValueProvider::get_IsReadOnly(boolean *value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!value)
+ return E_INVALIDARG;
+
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ *value = (metadata->state().readOnly != 0);
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaRangeValueProvider::get_LargeChange(DOUBLE *value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!value)
+ return E_INVALIDARG;
+
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ *value = metadata->minimumStepSize();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaRangeValueProvider::get_Maximum(DOUBLE *value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!value)
+ return E_INVALIDARG;
+
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ *value = metadata->maximumValue();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaRangeValueProvider::get_Minimum(DOUBLE *value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!value)
+ return E_INVALIDARG;
+
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ *value = metadata->minimumValue();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaRangeValueProvider::get_SmallChange(DOUBLE *value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!value)
+ return E_INVALIDARG;
+
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ *value = metadata->minimumStepSize();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaRangeValueProvider::get_Value(DOUBLE *value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!value)
+ return E_INVALIDARG;
+
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ *value = metadata->currentValue();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaRangeValueProvider::SetValue(DOUBLE value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ auto accid = id();
+
+ QEventDispatcherWinRT::runOnMainThread([accid, value]() {
+ if (QAccessibleInterface *accessible = accessibleForId(accid)) {
+ if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
+ double minimum = valueInterface->minimumValue().toDouble();
+ double maximum = valueInterface->maximumValue().toDouble();
+ if ((value >= minimum) && (value <= maximum)) {
+ valueInterface->setCurrentValue(QVariant(value));
+ }
+ }
+ }
+ QWinRTUiaMetadataCache::instance()->load(accid);
+ return S_OK;
+ }, 0);
+
+ return S_OK;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiarangevalueprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiarangevalueprovider.h
new file mode 100644
index 0000000000..4e98959526
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiarangevalueprovider.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTUIARANGEVALUEPROVIDER_H
+#define QWINRTUIARANGEVALUEPROVIDER_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiabaseprovider.h"
+
+#include <wrl.h>
+#include <windows.ui.xaml.h>
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Range Value control pattern provider.
+class QWinRTUiaRangeValueProvider :
+ public QWinRTUiaBaseProvider,
+ public Microsoft::WRL::RuntimeClass<ABI::Windows::UI::Xaml::Automation::Provider::IRangeValueProvider>
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QWinRTUiaRangeValueProvider)
+ InspectableClass(L"QWinRTUiaRangeValueProvider", BaseTrust);
+
+public:
+ explicit QWinRTUiaRangeValueProvider(QAccessible::Id id);
+ virtual ~QWinRTUiaRangeValueProvider();
+
+ // IRangeValueProvider
+ HRESULT STDMETHODCALLTYPE get_IsReadOnly(boolean *value) override;
+ HRESULT STDMETHODCALLTYPE get_LargeChange(DOUBLE *value) override;
+ HRESULT STDMETHODCALLTYPE get_Maximum(DOUBLE *value) override;
+ HRESULT STDMETHODCALLTYPE get_Minimum(DOUBLE *value) override;
+ HRESULT STDMETHODCALLTYPE get_SmallChange(DOUBLE *value) override;
+ HRESULT STDMETHODCALLTYPE get_Value(DOUBLE *value) override;
+ HRESULT STDMETHODCALLTYPE SetValue(DOUBLE value) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QWINRTUIARANGEVALUEPROVIDER_H
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionitemprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionitemprovider.cpp
new file mode 100644
index 0000000000..9bc88272ba
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionitemprovider.cpp
@@ -0,0 +1,214 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiaselectionitemprovider.h"
+#include "qwinrtuiamainprovider.h"
+#include "qwinrtuiametadatacache.h"
+#include "qwinrtuiautils.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QString>
+#include <QtCore/private/qeventdispatcher_winrt_p.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWinRTUiAutomation;
+using namespace ABI::Windows::UI::Xaml::Automation;
+using namespace ABI::Windows::UI::Xaml::Automation::Provider;
+using namespace ABI::Windows::UI::Xaml::Automation::Peers;
+
+QWinRTUiaSelectionItemProvider::QWinRTUiaSelectionItemProvider(QAccessible::Id id) :
+ QWinRTUiaBaseProvider(id)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+}
+
+QWinRTUiaSelectionItemProvider::~QWinRTUiaSelectionItemProvider()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+}
+
+// Returns true if element is currently selected.
+HRESULT STDMETHODCALLTYPE QWinRTUiaSelectionItemProvider::get_IsSelected(boolean *value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!value)
+ return E_INVALIDARG;
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ if (metadata->role() == QAccessible::RadioButton)
+ *value = metadata->state().checked;
+ else
+ *value = metadata->state().selected;
+ return S_OK;
+}
+
+// Returns the provider for the container element (e.g., the list for the list item).
+HRESULT STDMETHODCALLTYPE QWinRTUiaSelectionItemProvider::get_SelectionContainer(IIRawElementProviderSimple **value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!value)
+ return E_INVALIDARG;
+ *value = nullptr;
+
+ auto accid = id();
+ auto elementId = QSharedPointer<QAccessible::Id>(new QAccessible::Id(0));
+ auto ptrElementId = new QSharedPointer<QAccessible::Id>(elementId);
+
+ if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, ptrElementId]() {
+ if (QAccessibleInterface *accessible = accessibleForId(accid)) {
+ // Radio buttons do not require a container.
+ if (accessible->role() == QAccessible::ListItem) {
+ if (QAccessibleInterface *parent = accessible->parent()) {
+ if (parent->role() == QAccessible::List) {
+ **ptrElementId = idForAccessible(parent);
+ }
+ }
+ }
+ }
+ delete ptrElementId;
+ return S_OK;
+ }))) {
+ return E_FAIL;
+ }
+
+ if (!*elementId)
+ return S_OK;
+
+ return QWinRTUiaMainProvider::rawProviderForAccessibleId(*elementId, value);
+}
+
+// Adds the element to the list of selected elements.
+HRESULT STDMETHODCALLTYPE QWinRTUiaSelectionItemProvider::AddToSelection()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ auto accid = id();
+
+ QEventDispatcherWinRT::runOnMainThread([accid]() {
+ if (QAccessibleInterface *accessible = accessibleForId(accid)) {
+ if (QAccessibleActionInterface *actionInterface = accessible->actionInterface()) {
+ if (accessible->role() == QAccessible::RadioButton) {
+ // For radio buttons we invoke the selection action.
+ actionInterface->doAction(QAccessibleActionInterface::pressAction());
+ } else {
+ // Toggle list item if not already selected.
+ if (!accessible->state().selected) {
+ actionInterface->doAction(QAccessibleActionInterface::toggleAction());
+ }
+ }
+ }
+ }
+ QWinRTUiaMetadataCache::instance()->load(accid);
+ return S_OK;
+ }, 0);
+ return S_OK;
+}
+
+// Removes a list item from selection.
+HRESULT STDMETHODCALLTYPE QWinRTUiaSelectionItemProvider::RemoveFromSelection()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ auto accid = id();
+
+ QEventDispatcherWinRT::runOnMainThread([accid]() {
+ if (QAccessibleInterface *accessible = accessibleForId(accid)) {
+ if (QAccessibleActionInterface *actionInterface = accessible->actionInterface()) {
+ if (accessible->role() != QAccessible::RadioButton) {
+ if (accessible->state().selected) {
+ actionInterface->doAction(QAccessibleActionInterface::toggleAction());
+ }
+ }
+ }
+ }
+ QWinRTUiaMetadataCache::instance()->load(accid);
+ return S_OK;
+ }, 0);
+ return S_OK;
+}
+
+// Selects the element (deselecting all others).
+HRESULT STDMETHODCALLTYPE QWinRTUiaSelectionItemProvider::Select()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ auto accid = id();
+
+ QEventDispatcherWinRT::runOnMainThread([accid]() {
+ if (QAccessibleInterface *accessible = accessibleForId(accid)) {
+ if (QAccessibleActionInterface *actionInterface = accessible->actionInterface()) {
+ if (accessible->role() == QAccessible::RadioButton) {
+ // For radio buttons we just invoke the selection action; others are automatically deselected.
+ actionInterface->doAction(QAccessibleActionInterface::pressAction());
+ } else {
+ // Toggle list item if not already selected. It must be done first to support all selection modes.
+ if (!accessible->state().selected) {
+ actionInterface->doAction(QAccessibleActionInterface::toggleAction());
+ }
+ // Toggle selected siblings.
+ if (QAccessibleInterface *parent = accessible->parent()) {
+ for (int i = 0; i < parent->childCount(); ++i) {
+ if (QAccessibleInterface *sibling = parent->child(i)) {
+ if ((sibling != accessible) && (sibling->state().selected)) {
+ if (QAccessibleActionInterface *siblingAction = sibling->actionInterface()) {
+ siblingAction->doAction(QAccessibleActionInterface::toggleAction());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ QWinRTUiaMetadataCache::instance()->load(accid);
+ return S_OK;
+ }, 0);
+ return S_OK;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionitemprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionitemprovider.h
new file mode 100644
index 0000000000..1b3cce7495
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionitemprovider.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTUIASELECTIONITEMPROVIDER_H
+#define QWINRTUIASELECTIONITEMPROVIDER_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiabaseprovider.h"
+
+#include <wrl.h>
+#include <windows.ui.xaml.h>
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Selection Item control pattern provider. Used for List items and radio buttons.
+class QWinRTUiaSelectionItemProvider :
+ public QWinRTUiaBaseProvider,
+ public Microsoft::WRL::RuntimeClass<ABI::Windows::UI::Xaml::Automation::Provider::ISelectionItemProvider>
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QWinRTUiaSelectionItemProvider)
+ InspectableClass(L"QWinRTUiaSelectionItemProvider", BaseTrust);
+
+public:
+ explicit QWinRTUiaSelectionItemProvider(QAccessible::Id id);
+ virtual ~QWinRTUiaSelectionItemProvider();
+
+ // ISelectionItemProvider
+ HRESULT STDMETHODCALLTYPE get_IsSelected(boolean *value) override;
+ HRESULT STDMETHODCALLTYPE get_SelectionContainer(ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple **value) override;
+ HRESULT STDMETHODCALLTYPE AddToSelection() override;
+ HRESULT STDMETHODCALLTYPE RemoveFromSelection() override;
+ HRESULT STDMETHODCALLTYPE Select() override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QWINRTUIASELECTIONITEMPROVIDER_H
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionprovider.cpp
new file mode 100644
index 0000000000..9e61a8df61
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionprovider.cpp
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiaselectionprovider.h"
+#include "qwinrtuiametadatacache.h"
+#include "qwinrtuiamainprovider.h"
+#include "qwinrtuiautils.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QString>
+#include <QtCore/private/qeventdispatcher_winrt_p.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWinRTUiAutomation;
+using namespace ABI::Windows::UI::Xaml::Automation;
+using namespace ABI::Windows::UI::Xaml::Automation::Provider;
+using namespace ABI::Windows::UI::Xaml::Automation::Peers;
+
+QWinRTUiaSelectionProvider::QWinRTUiaSelectionProvider(QAccessible::Id id) :
+ QWinRTUiaBaseProvider(id)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+}
+
+QWinRTUiaSelectionProvider::~QWinRTUiaSelectionProvider()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaSelectionProvider::get_CanSelectMultiple(boolean *value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!value)
+ return E_INVALIDARG;
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ *value = (metadata->state().multiSelectable != 0);
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaSelectionProvider::get_IsSelectionRequired(boolean *value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!value)
+ return E_INVALIDARG;
+ *value = false;
+
+ auto accid = id();
+ auto selectionRequired = QSharedPointer<bool>(new bool(false));
+ auto ptrSelectionRequired = new QSharedPointer<bool>(selectionRequired);
+
+ if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, ptrSelectionRequired]() {
+ // Initially returns false if none are selected. After the first selection, it may be required.
+ bool anySelected = false;
+ if (QAccessibleInterface *accessible = accessibleForId(accid)) {
+ int childCount = accessible->childCount();
+ for (int i = 0; i < childCount; ++i) {
+ if (QAccessibleInterface *childAcc = accessible->child(i)) {
+ if (childAcc->state().selected) {
+ anySelected = true;
+ break;
+ }
+ }
+ }
+ **ptrSelectionRequired = anySelected && !accessible->state().multiSelectable && !accessible->state().extSelectable;
+ }
+ delete ptrSelectionRequired;
+ return S_OK;
+ }))) {
+ return E_FAIL;
+ }
+
+ *value = *selectionRequired;
+ return S_OK;
+}
+
+// Returns an array of providers with the selected items.
+HRESULT STDMETHODCALLTYPE QWinRTUiaSelectionProvider::GetSelection(UINT32 *returnValueSize, IIRawElementProviderSimple ***returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValueSize || !returnValue)
+ return E_INVALIDARG;
+ *returnValueSize = 0;
+ *returnValue = nullptr;
+
+ auto accid = id();
+ auto elementIds = QSharedPointer<QList<QAccessible::Id>>(new QList<QAccessible::Id>);
+ auto ptrElementIds = new QSharedPointer<QList<QAccessible::Id>>(elementIds);
+
+ if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, ptrElementIds]() {
+ if (QAccessibleInterface *accessible = accessibleForId(accid)) {
+ int childCount = accessible->childCount();
+ for (int i = 0; i < childCount; ++i) {
+ if (QAccessibleInterface *childAcc = accessible->child(i)) {
+ if (childAcc->state().selected) {
+ QAccessible::Id childId = idForAccessible(childAcc);
+ QWinRTUiaMetadataCache::instance()->load(childId);
+ (*ptrElementIds)->append(childId);
+ }
+ }
+ }
+ }
+ delete ptrElementIds;
+ return S_OK;
+ }))) {
+ return E_FAIL;
+ }
+
+ return QWinRTUiaMainProvider::rawProviderArrayForAccessibleIdList(*elementIds, returnValueSize, returnValue);
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionprovider.h
new file mode 100644
index 0000000000..dcd286800f
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiaselectionprovider.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTUIASELECTIONPROVIDER_H
+#define QWINRTUIASELECTIONPROVIDER_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiabaseprovider.h"
+
+#include <wrl.h>
+#include <windows.ui.xaml.h>
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Selection control pattern provider. Used for Lists.
+class QWinRTUiaSelectionProvider :
+ public QWinRTUiaBaseProvider,
+ public Microsoft::WRL::RuntimeClass<ABI::Windows::UI::Xaml::Automation::Provider::ISelectionProvider>
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QWinRTUiaSelectionProvider)
+ InspectableClass(L"QWinRTUiaSelectionProvider", BaseTrust);
+
+public:
+ explicit QWinRTUiaSelectionProvider(QAccessible::Id id);
+ virtual ~QWinRTUiaSelectionProvider();
+
+ // ISelectionProvider
+ HRESULT STDMETHODCALLTYPE get_CanSelectMultiple(boolean *value) override;
+ HRESULT STDMETHODCALLTYPE get_IsSelectionRequired(boolean *value) override;
+ HRESULT STDMETHODCALLTYPE GetSelection(UINT32 *returnValueSize, ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple ***returnValue) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QWINRTUIASELECTIONPROVIDER_H
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiatableitemprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatableitemprovider.cpp
new file mode 100644
index 0000000000..1af74a8b72
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatableitemprovider.cpp
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiatableitemprovider.h"
+#include "qwinrtuiamainprovider.h"
+#include "qwinrtuiametadatacache.h"
+#include "qwinrtuiautils.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QString>
+#include <QtCore/private/qeventdispatcher_winrt_p.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWinRTUiAutomation;
+using namespace ABI::Windows::UI::Xaml::Automation;
+using namespace ABI::Windows::UI::Xaml::Automation::Provider;
+
+QWinRTUiaTableItemProvider::QWinRTUiaTableItemProvider(QAccessible::Id id) :
+ QWinRTUiaBaseProvider(id)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+}
+
+QWinRTUiaTableItemProvider::~QWinRTUiaTableItemProvider()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+}
+
+// Returns the providers for the column headers associated with the item.
+HRESULT STDMETHODCALLTYPE QWinRTUiaTableItemProvider::GetColumnHeaderItems(UINT32 *returnValueSize, IIRawElementProviderSimple ***returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValueSize || !returnValue)
+ return E_INVALIDARG;
+ *returnValueSize = 0;
+ *returnValue = nullptr;
+
+ auto accid = id();
+ auto elementIds = QSharedPointer<QList<QAccessible::Id>>(new QList<QAccessible::Id>);
+ auto ptrElementIds = new QSharedPointer<QList<QAccessible::Id>>(elementIds);
+
+ if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, ptrElementIds]() {
+ if (QAccessibleInterface *accessible = accessibleForId(accid)) {
+ if (QAccessibleTableCellInterface *tableCellInterface = accessible->tableCellInterface()) {
+ QList<QAccessibleInterface *> headers = tableCellInterface->columnHeaderCells();
+ for (auto header : qAsConst(headers)) {
+ QAccessible::Id headerId = idForAccessible(header);
+ QWinRTUiaMetadataCache::instance()->load(headerId);
+ (*ptrElementIds)->append(headerId);
+ }
+ }
+ }
+ delete ptrElementIds;
+ return S_OK;
+ }))) {
+ return E_FAIL;
+ }
+
+ return QWinRTUiaMainProvider::rawProviderArrayForAccessibleIdList(*elementIds, returnValueSize, returnValue);
+}
+
+// Returns the providers for the row headers associated with the item.
+HRESULT STDMETHODCALLTYPE QWinRTUiaTableItemProvider::GetRowHeaderItems(UINT32 *returnValueSize, IIRawElementProviderSimple ***returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValueSize || !returnValue)
+ return E_INVALIDARG;
+ *returnValueSize = 0;
+ *returnValue = nullptr;
+
+ auto accid = id();
+ auto elementIds = QSharedPointer<QList<QAccessible::Id>>(new QList<QAccessible::Id>);
+ auto ptrElementIds = new QSharedPointer<QList<QAccessible::Id>>(elementIds);
+
+ if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, ptrElementIds]() {
+ if (QAccessibleInterface *accessible = accessibleForId(accid)) {
+ if (QAccessibleTableCellInterface *tableCellInterface = accessible->tableCellInterface()) {
+ QList<QAccessibleInterface *> headers = tableCellInterface->rowHeaderCells();
+ for (auto header : qAsConst(headers)) {
+ QAccessible::Id headerId = idForAccessible(header);
+ QWinRTUiaMetadataCache::instance()->load(headerId);
+ (*ptrElementIds)->append(headerId);
+ }
+ }
+ }
+ delete ptrElementIds;
+ return S_OK;
+ }))) {
+ return E_FAIL;
+ }
+
+ return QWinRTUiaMainProvider::rawProviderArrayForAccessibleIdList(*elementIds, returnValueSize, returnValue);
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiatableitemprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatableitemprovider.h
new file mode 100644
index 0000000000..cb759864ae
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatableitemprovider.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTUIATABLEITEMPROVIDER_H
+#define QWINRTUIATABLEITEMPROVIDER_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiabaseprovider.h"
+
+#include <wrl.h>
+#include <windows.ui.xaml.h>
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Table Item control pattern provider. Used by items within a table/tree.
+class QWinRTUiaTableItemProvider :
+ public QWinRTUiaBaseProvider,
+ public Microsoft::WRL::RuntimeClass<ABI::Windows::UI::Xaml::Automation::Provider::ITableItemProvider>
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QWinRTUiaTableItemProvider)
+ InspectableClass(L"QWinRTUiaTableItemProvider", BaseTrust);
+
+public:
+ explicit QWinRTUiaTableItemProvider(QAccessible::Id id);
+ virtual ~QWinRTUiaTableItemProvider();
+
+ // ITableItemProvider
+ HRESULT STDMETHODCALLTYPE GetColumnHeaderItems(UINT32 *returnValueSize, ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple ***returnValue) override;
+ HRESULT STDMETHODCALLTYPE GetRowHeaderItems(UINT32 *returnValueSize, ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple ***returnValue) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QWINRTUIATABLEITEMPROVIDER_H
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiatableprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatableprovider.cpp
new file mode 100644
index 0000000000..e71ade3c1f
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatableprovider.cpp
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiatableprovider.h"
+#include "qwinrtuiamainprovider.h"
+#include "qwinrtuiametadatacache.h"
+#include "qwinrtuiautils.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QString>
+#include <QtCore/private/qeventdispatcher_winrt_p.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWinRTUiAutomation;
+using namespace ABI::Windows::UI::Xaml::Automation;
+using namespace ABI::Windows::UI::Xaml::Automation::Provider;
+using namespace ABI::Windows::UI::Xaml::Automation::Peers;
+
+QWinRTUiaTableProvider::QWinRTUiaTableProvider(QAccessible::Id id) :
+ QWinRTUiaBaseProvider(id)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+}
+
+QWinRTUiaTableProvider::~QWinRTUiaTableProvider()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+}
+
+// Returns the primary direction of traversal for the table.
+HRESULT STDMETHODCALLTYPE QWinRTUiaTableProvider::get_RowOrColumnMajor(RowOrColumnMajor *value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!value)
+ return E_INVALIDARG;
+ *value = RowOrColumnMajor_Indeterminate;
+ return S_OK;
+}
+
+// Gets the providers for all the column headers in the table.
+HRESULT STDMETHODCALLTYPE QWinRTUiaTableProvider::GetColumnHeaders(UINT32 *returnValueSize, IIRawElementProviderSimple ***returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValueSize || !returnValue)
+ return E_INVALIDARG;
+ *returnValueSize = 0;
+ *returnValue = nullptr;
+
+ auto accid = id();
+ auto elementIds = QSharedPointer<QList<QAccessible::Id>>(new QList<QAccessible::Id>);
+ auto ptrElementIds = new QSharedPointer<QList<QAccessible::Id>>(elementIds);
+
+ if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, ptrElementIds]() {
+ if (QAccessibleInterface *accessible = accessibleForId(accid)) {
+ if (QAccessibleTableInterface *tableInterface = accessible->tableInterface()) {
+ for (int i = 0; i < tableInterface->columnCount(); ++i) {
+ if (QAccessibleInterface *cell = tableInterface->cellAt(0, i)) {
+ QWinRTUiaMetadataCache::instance()->load(idForAccessible(cell));
+ if (QAccessibleTableCellInterface *tableCellInterface = cell->tableCellInterface()) {
+ QList<QAccessibleInterface *> headers = tableCellInterface->columnHeaderCells();
+ for (auto header : qAsConst(headers)) {
+ QAccessible::Id headerId = idForAccessible(header);
+ QWinRTUiaMetadataCache::instance()->load(headerId);
+ (*ptrElementIds)->append(headerId);
+ }
+ }
+ }
+ }
+ }
+ }
+ delete ptrElementIds;
+ return S_OK;
+ }))) {
+ return E_FAIL;
+ }
+
+ return QWinRTUiaMainProvider::rawProviderArrayForAccessibleIdList(*elementIds, returnValueSize, returnValue);
+}
+
+// Gets the providers for all the row headers in the table.
+HRESULT STDMETHODCALLTYPE QWinRTUiaTableProvider::GetRowHeaders(UINT32 *returnValueSize, IIRawElementProviderSimple ***returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValueSize || !returnValue)
+ return E_INVALIDARG;
+ *returnValueSize = 0;
+ *returnValue = nullptr;
+
+ auto accid = id();
+ auto elementIds = QSharedPointer<QList<QAccessible::Id>>(new QList<QAccessible::Id>);
+ auto ptrElementIds = new QSharedPointer<QList<QAccessible::Id>>(elementIds);
+
+ if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, ptrElementIds]() {
+ if (QAccessibleInterface *accessible = accessibleForId(accid)) {
+ if (QAccessibleTableInterface *tableInterface = accessible->tableInterface()) {
+ for (int i = 0; i < tableInterface->rowCount(); ++i) {
+ if (QAccessibleInterface *cell = tableInterface->cellAt(i, 0)) {
+ QWinRTUiaMetadataCache::instance()->load(idForAccessible(cell));
+ if (QAccessibleTableCellInterface *tableCellInterface = cell->tableCellInterface()) {
+ QList<QAccessibleInterface *> headers = tableCellInterface->rowHeaderCells();
+ for (auto header : qAsConst(headers)) {
+ QAccessible::Id headerId = idForAccessible(header);
+ QWinRTUiaMetadataCache::instance()->load(headerId);
+ (*ptrElementIds)->append(headerId);
+ }
+ }
+ }
+ }
+ }
+ }
+ delete ptrElementIds;
+ return S_OK;
+ }))) {
+ return E_FAIL;
+ }
+
+ return QWinRTUiaMainProvider::rawProviderArrayForAccessibleIdList(*elementIds, returnValueSize, returnValue);
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiatableprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatableprovider.h
new file mode 100644
index 0000000000..0cd174e401
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatableprovider.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTUIATABLEPROVIDER_H
+#define QWINRTUIATABLEPROVIDER_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiabaseprovider.h"
+
+#include <wrl.h>
+#include <windows.ui.xaml.h>
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Table control pattern provider. Used by tables/trees.
+class QWinRTUiaTableProvider :
+ public QWinRTUiaBaseProvider,
+ public Microsoft::WRL::RuntimeClass<ABI::Windows::UI::Xaml::Automation::Provider::ITableProvider>
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QWinRTUiaTableProvider)
+ InspectableClass(L"QWinRTUiaTableProvider", BaseTrust);
+
+public:
+ explicit QWinRTUiaTableProvider(QAccessible::Id id);
+ virtual ~QWinRTUiaTableProvider();
+
+ // ITableProvider
+ HRESULT STDMETHODCALLTYPE get_RowOrColumnMajor(ABI::Windows::UI::Xaml::Automation::RowOrColumnMajor *value) override;
+ HRESULT STDMETHODCALLTYPE GetColumnHeaders(UINT32 *returnValueSize, ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple ***returnValue) override;
+ HRESULT STDMETHODCALLTYPE GetRowHeaders(UINT32 *returnValueSize, ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple ***returnValue) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QWINRTUIATABLEPROVIDER_H
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiatextprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatextprovider.cpp
new file mode 100644
index 0000000000..aa120377df
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatextprovider.cpp
@@ -0,0 +1,232 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiatextprovider.h"
+#include "qwinrtuiametadatacache.h"
+#include "qwinrtuiatextrangeprovider.h"
+#include "qwinrtuiautils.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QString>
+#include <QtCore/private/qeventdispatcher_winrt_p.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWinRTUiAutomation;
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::UI::Xaml::Automation;
+using namespace ABI::Windows::UI::Xaml::Automation::Provider;
+
+QWinRTUiaTextProvider::QWinRTUiaTextProvider(QAccessible::Id id) :
+ QWinRTUiaBaseProvider(id)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+}
+
+QWinRTUiaTextProvider::~QWinRTUiaTextProvider()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+}
+
+// Returns a text range provider for the entire text.
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextProvider::get_DocumentRange(ITextRangeProvider **value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!value)
+ return E_INVALIDARG;
+
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ ComPtr<QWinRTUiaTextRangeProvider> textRangeProvider = Make<QWinRTUiaTextRangeProvider>(id(), 0, metadata->characterCount());
+ return textRangeProvider.CopyTo(value);
+}
+
+// Currently supporting single selection.
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextProvider::get_SupportedTextSelection(SupportedTextSelection *value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ if (!value)
+ return E_INVALIDARG;
+ *value = SupportedTextSelection_Single;
+ return S_OK;
+
+}
+
+// Returns an array of providers for the selected text ranges.
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextProvider::GetSelection(UINT32 *returnValueSize, ITextRangeProvider ***returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValueSize || !returnValue)
+ return E_INVALIDARG;
+ *returnValueSize = 0;
+ *returnValue = nullptr;
+
+ auto accid = id();
+ auto selections = QSharedPointer<QList<QPair<int,int>>>(new QList<QPair<int,int>>);
+ auto ptrSelections = new QSharedPointer<QList<QPair<int,int>>>(selections);
+
+ if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, ptrSelections]() {
+ if (QAccessibleInterface *accessible = accessibleForId(accid)) {
+ if (QAccessibleTextInterface *textInterface = accessible->textInterface()) {
+ for (int i = 0; i < textInterface->selectionCount(); ++i) {
+ QPair<int,int> sel;
+ textInterface->selection(i, &sel.first, &sel.second);
+ (*ptrSelections)->append(sel);
+ }
+ if ((*ptrSelections)->size() == 0) {
+ // If there is no selection, we return an array with a single degenerate (empty) text range at the cursor position.
+ QPair<int,int> sel(textInterface->cursorPosition(), textInterface->cursorPosition());
+ (*ptrSelections)->append(sel);
+ }
+ }
+ }
+ delete ptrSelections;
+ return S_OK;
+ }))) {
+ return E_FAIL;
+ }
+
+ int selCount = selections->size();
+ if (selCount < 1)
+ return E_FAIL;
+
+ ITextRangeProvider **providerArray = static_cast<ITextRangeProvider **>(CoTaskMemAlloc(selCount * sizeof(ITextRangeProvider *)));
+ if (!providerArray)
+ return E_OUTOFMEMORY;
+
+ for (int i = 0; i < selCount; ++i) {
+ ComPtr<QWinRTUiaTextRangeProvider> textRangeProvider = Make<QWinRTUiaTextRangeProvider>(id(), (*selections)[i].first, (*selections)[i].second);
+ textRangeProvider.CopyTo(&providerArray[i]);
+ }
+ *returnValueSize = selCount;
+ *returnValue = providerArray;
+ return S_OK;
+}
+
+// Returns an array of providers for the visible text ranges.
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextProvider::GetVisibleRanges(UINT32 *returnValueSize, ITextRangeProvider ***returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValueSize || !returnValue)
+ return E_INVALIDARG;
+
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+
+ // Considering the entire text as visible.
+ ComPtr<QWinRTUiaTextRangeProvider> textRangeProvider = Make<QWinRTUiaTextRangeProvider>(id(), 0, metadata->characterCount());
+ textRangeProvider.CopyTo(*returnValue);
+ *returnValueSize = 1;
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextProvider::RangeFromChild(IIRawElementProviderSimple *childElement, ITextRangeProvider **returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ if (!childElement || !returnValue)
+ return E_INVALIDARG;
+ *returnValue = nullptr;
+ // No children supported.
+ return S_OK;
+}
+
+// Returns a degenerate text range at the specified point.
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextProvider::RangeFromPoint(ABI::Windows::Foundation::Point screenLocation, ITextRangeProvider **returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ *returnValue = nullptr;
+
+ const QPoint pt(screenLocation.X, screenLocation.Y);
+ auto accid = id();
+ auto offset = QSharedPointer<int>(new int);
+ auto ptrOffset = new QSharedPointer<int>(offset);
+
+ if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, pt, ptrOffset]() {
+ if (QAccessibleInterface *accessible = accessibleForId(accid))
+ if (QAccessibleTextInterface *textInterface = accessible->textInterface())
+ **ptrOffset = qBound(0, textInterface->offsetAtPoint(pt), textInterface->characterCount() - 1);
+ delete ptrOffset;
+ return S_OK;
+ }))) {
+ return E_FAIL;
+ }
+
+ ComPtr<QWinRTUiaTextRangeProvider> textRangeProvider = Make<QWinRTUiaTextRangeProvider>(id(), *offset, *offset);
+ textRangeProvider.CopyTo(returnValue);
+ return S_OK;
+}
+
+// Not supporting annotations.
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextProvider::RangeFromAnnotation(IIRawElementProviderSimple *annotationElement, ITextRangeProvider **returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ if (!annotationElement || !returnValue)
+ return E_INVALIDARG;
+ *returnValue = nullptr;
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextProvider::GetCaretRange(boolean *isActive, ITextRangeProvider **returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!isActive || !returnValue)
+ return E_INVALIDARG;
+
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ *isActive = metadata->state().focused;
+
+ ComPtr<QWinRTUiaTextRangeProvider> textRangeProvider = Make<QWinRTUiaTextRangeProvider>(id(), metadata->cursorPosition(), metadata->cursorPosition());
+ return textRangeProvider.CopyTo(returnValue);
+}
+
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiatextprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatextprovider.h
new file mode 100644
index 0000000000..80d88e4115
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatextprovider.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTUIATEXTPROVIDER_H
+#define QWINRTUIATEXTPROVIDER_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiabaseprovider.h"
+
+#include <wrl.h>
+#include <windows.ui.xaml.h>
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Text control pattern provider. Used for text controls.
+class QWinRTUiaTextProvider :
+ public QWinRTUiaBaseProvider,
+ public Microsoft::WRL::RuntimeClass<ABI::Windows::UI::Xaml::Automation::Provider::ITextProvider, ABI::Windows::UI::Xaml::Automation::Provider::ITextProvider2>
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QWinRTUiaTextProvider)
+ InspectableClass(L"QWinRTUiaTextProvider", BaseTrust);
+
+public:
+ explicit QWinRTUiaTextProvider(QAccessible::Id id);
+ virtual ~QWinRTUiaTextProvider();
+
+ // ITextProvider
+ HRESULT STDMETHODCALLTYPE get_DocumentRange(ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider **value) override;
+ HRESULT STDMETHODCALLTYPE get_SupportedTextSelection(ABI::Windows::UI::Xaml::Automation::SupportedTextSelection *value) override;
+ HRESULT STDMETHODCALLTYPE GetSelection(UINT32 *returnValueSize, ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider ***returnValue) override;
+ HRESULT STDMETHODCALLTYPE GetVisibleRanges(UINT32 *returnValueSize, ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider ***returnValue) override;
+ HRESULT STDMETHODCALLTYPE RangeFromChild(ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple *childElement, ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider **returnValue) override;
+ HRESULT STDMETHODCALLTYPE RangeFromPoint(ABI::Windows::Foundation::Point screenLocation, ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider **returnValue) override;
+
+ // ITextProvider2
+ HRESULT STDMETHODCALLTYPE RangeFromAnnotation(ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple *annotationElement, ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider **returnValue) override;
+ HRESULT STDMETHODCALLTYPE GetCaretRange(boolean *isActive, ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider **returnValue) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QWINRTUIATEXTPROVIDER_H
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiatextrangeprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatextrangeprovider.cpp
new file mode 100644
index 0000000000..fc3778d652
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatextrangeprovider.cpp
@@ -0,0 +1,497 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiatextrangeprovider.h"
+#include "qwinrtuiametadatacache.h"
+#include "qwinrtuiamainprovider.h"
+#include "qwinrtuiautils.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QString>
+#include <QtCore/private/qeventdispatcher_winrt_p.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWinRTUiAutomation;
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::UI::Xaml;
+using namespace ABI::Windows::UI::Xaml::Automation;
+using namespace ABI::Windows::UI::Xaml::Automation::Provider;
+using namespace ABI::Windows::UI::Xaml::Automation::Text;
+
+QWinRTUiaTextRangeProvider::QWinRTUiaTextRangeProvider(QAccessible::Id id, int startOffset, int endOffset) :
+ QWinRTUiaBaseProvider(id),
+ m_startOffset(startOffset),
+ m_endOffset(endOffset)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << startOffset << endOffset;
+}
+
+QWinRTUiaTextRangeProvider::~QWinRTUiaTextRangeProvider()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::Clone(ITextRangeProvider **returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ if (!returnValue)
+ return E_INVALIDARG;
+
+ ComPtr<QWinRTUiaTextRangeProvider> textRangeProvider = Make<QWinRTUiaTextRangeProvider>(id(), m_startOffset, m_endOffset);
+ textRangeProvider.CopyTo(returnValue);
+ return S_OK;
+}
+
+// Two ranges are considered equal if their start/end points are the same.
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::Compare(ITextRangeProvider *textRangeProvider, boolean *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ if (!textRangeProvider || !returnValue)
+ return E_INVALIDARG;
+
+ QWinRTUiaTextRangeProvider *targetProvider = static_cast<QWinRTUiaTextRangeProvider *>(textRangeProvider);
+ *returnValue = ((targetProvider->m_startOffset == m_startOffset) && (targetProvider->m_endOffset == m_endOffset));
+ return S_OK;
+}
+
+// Compare different endpoinds between two providers.
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::CompareEndpoints(TextPatternRangeEndpoint endpoint, ITextRangeProvider *textRangeProvider, TextPatternRangeEndpoint targetEndpoint, INT32 *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!textRangeProvider || !returnValue)
+ return E_INVALIDARG;
+
+ QWinRTUiaTextRangeProvider *targetProvider = static_cast<QWinRTUiaTextRangeProvider *>(textRangeProvider);
+
+ int point = (endpoint == TextPatternRangeEndpoint_Start) ? m_startOffset : m_endOffset;
+ int targetPoint = (targetEndpoint == TextPatternRangeEndpoint_Start) ?
+ targetProvider->m_startOffset : targetProvider->m_endOffset;
+ *returnValue = point - targetPoint;
+ return S_OK;
+}
+
+// Expands/normalizes the range for a given text unit.
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::ExpandToEnclosingUnit(TextUnit unit)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << "unit=" << unit << "this: " << this;
+
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+
+ int len = metadata->characterCount();
+ if (len < 1) {
+ m_startOffset = 0;
+ m_endOffset = 0;
+ } else {
+ if (unit == TextUnit_Character) {
+ m_startOffset = qBound(0, m_startOffset, len - 1);
+ m_endOffset = m_startOffset + 1;
+ } else {
+ QString text = metadata->text();
+ for (int t = m_startOffset; t >= 0; --t) {
+ if (!isTextUnitSeparator(unit, text[t]) && ((t == 0) || isTextUnitSeparator(unit, text[t - 1]))) {
+ m_startOffset = t;
+ break;
+ }
+ }
+ for (int t = m_startOffset; t < len; ++t) {
+ if ((t == len - 1) || (isTextUnitSeparator(unit, text[t]) && ((unit == TextUnit_Word) || !isTextUnitSeparator(unit, text[t + 1])))) {
+ m_endOffset = t + 1;
+ break;
+ }
+ }
+ }
+ }
+ return S_OK;
+}
+
+// Not supported.
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::FindAttribute(INT32 /*attributeId*/, IInspectable * /*value*/, boolean /*backward*/, ITextRangeProvider **returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ if (!returnValue)
+ return E_INVALIDARG;
+ *returnValue = nullptr;
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::FindText(HSTRING /*text*/, boolean /*backward*/, boolean /*ignoreCase*/, ITextRangeProvider **returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ if (!returnValue)
+ return E_INVALIDARG;
+ *returnValue = nullptr;
+ return S_OK;
+}
+
+// Returns the value of a given attribute.
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::GetAttributeValue(INT32 attributeId, IInspectable **returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__ << "attributeId=" << attributeId;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ *returnValue = nullptr;
+
+ ComPtr<IPropertyValueStatics> propertyValueStatics;
+ if (FAILED(RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Foundation_PropertyValue).Get(), IID_PPV_ARGS(&propertyValueStatics))))
+ return E_FAIL;
+
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+
+ switch (attributeId) {
+ case AutomationTextAttributesEnum_IsReadOnlyAttribute:
+ return propertyValueStatics->CreateBoolean(metadata->state().readOnly, returnValue);
+ case AutomationTextAttributesEnum_CaretPositionAttribute:
+ if (metadata->cursorPosition() == 0)
+ return propertyValueStatics->CreateInt32(AutomationCaretPosition_BeginningOfLine, returnValue);
+ else if (metadata->cursorPosition() == metadata->characterCount())
+ return propertyValueStatics->CreateInt32(AutomationCaretPosition_EndOfLine, returnValue);
+ else
+ return propertyValueStatics->CreateInt32(AutomationCaretPosition_Unknown, returnValue);
+ default:
+ break;
+ }
+ return E_FAIL;
+}
+
+// Returns an array of bounding rectangles for text lines within the range.
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::GetBoundingRectangles(UINT32 *returnValueSize, DOUBLE **returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValueSize || !returnValue)
+ return E_INVALIDARG;
+ *returnValueSize = 0;
+ *returnValue = nullptr;
+
+ auto accid = id();
+ auto startOffset = m_startOffset;
+ auto endOffset = m_endOffset;
+ auto rects = QSharedPointer<QList<QRect>>(new QList<QRect>);
+ auto ptrRects = new QSharedPointer<QList<QRect>>(rects);
+
+ if (!SUCCEEDED(QEventDispatcherWinRT::runOnMainThread([accid, startOffset, endOffset, ptrRects]() {
+ if (QAccessibleInterface *accessible = accessibleForId(accid)) {
+ if (QAccessibleTextInterface *textInterface = accessible->textInterface()) {
+ int len = textInterface->characterCount();
+ if ((startOffset >= 0) && (endOffset <= len) && (startOffset < endOffset)) {
+ int start, end;
+ textInterface->textAtOffset(startOffset, QAccessible::LineBoundary, &start, &end);
+ while ((start >= 0) && (end >= 0)) {
+ int startRange = qMax(start, startOffset);
+ int endRange = qMin(end, endOffset);
+ if (startRange < endRange) {
+ // Calculates a bounding rectangle for the line and adds it to the list.
+ const QRect startRect = textInterface->characterRect(startRange);
+ const QRect endRect = textInterface->characterRect(endRange - 1);
+ const QRect lineRect(qMin(startRect.x(), endRect.x()),
+ qMin(startRect.y(), endRect.y()),
+ qMax(startRect.x() + startRect.width(), endRect.x() + endRect.width()) - qMin(startRect.x(), endRect.x()),
+ qMax(startRect.y() + startRect.height(), endRect.y() + endRect.height()) - qMin(startRect.y(), endRect.y()));
+ (*ptrRects)->append(lineRect);
+ }
+ if (end >= len) break;
+ textInterface->textAfterOffset(end + 1, QAccessible::LineBoundary, &start, &end);
+ }
+ }
+ }
+ }
+ delete ptrRects;
+ return S_OK;
+ }))) {
+ return E_FAIL;
+ }
+
+ DOUBLE *doubleArray = static_cast<DOUBLE *>(CoTaskMemAlloc(4 * rects->size() * sizeof(DOUBLE)));
+ if (!doubleArray)
+ return E_OUTOFMEMORY;
+
+ for (int i = 0; i < rects->size(); ++i) {
+ doubleArray[i*4] = (*rects)[i].left();
+ doubleArray[i*4+1] = (*rects)[i].top();
+ doubleArray[i*4+2] = (*rects)[i].width();
+ doubleArray[i*4+3] = (*rects)[i].height();
+ }
+ *returnValue = doubleArray;
+ *returnValueSize = 4 * rects->size();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::GetEnclosingElement(IIRawElementProviderSimple **returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ if (!returnValue)
+ return E_INVALIDARG;
+ return QWinRTUiaMainProvider::rawProviderForAccessibleId(id(), returnValue);
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::GetText(INT32 maxLength, HSTRING *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ if (!returnValue)
+ return E_INVALIDARG;
+ *returnValue = nullptr;
+
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+
+ QString rangeText = metadata->text().mid(m_startOffset, m_endOffset - m_startOffset);
+
+ if ((maxLength > -1) && (rangeText.size() > maxLength))
+ rangeText.truncate(maxLength);
+ return qHString(rangeText, returnValue);
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::Move(TextUnit unit, INT32 count, INT32 *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ if (!returnValue)
+ return E_INVALIDARG;
+ *returnValue = 0;
+
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+
+ int len = metadata->characterCount();
+ if (len < 1)
+ return S_OK;
+
+ if (unit == TextUnit_Character) {
+ // Moves the start point, ensuring it lies within the bounds.
+ int start = qBound(0, m_startOffset + count, len - 1);
+ // If range was initially empty, leaves it as is; otherwise, normalizes it to one char.
+ m_endOffset = (m_endOffset > m_startOffset) ? start + 1 : start;
+ *returnValue = start - m_startOffset; // Returns the actually moved distance.
+ m_startOffset = start;
+ } else {
+ if (count > 0) {
+ MoveEndpointByUnit(TextPatternRangeEndpoint_End, unit, count, returnValue);
+ MoveEndpointByUnit(TextPatternRangeEndpoint_Start, unit, count, returnValue);
+ } else {
+ MoveEndpointByUnit(TextPatternRangeEndpoint_Start, unit, count, returnValue);
+ MoveEndpointByUnit(TextPatternRangeEndpoint_End, unit, count, returnValue);
+ }
+ }
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::MoveEndpointByUnit(TextPatternRangeEndpoint endpoint, TextUnit unit, INT32 count, INT32 *returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ if (!returnValue)
+ return E_INVALIDARG;
+ *returnValue = 0;
+
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+
+ int len = metadata->characterCount();
+ if (len < 1)
+ return S_OK;
+
+ if (unit == TextUnit_Character) {
+ if (endpoint == TextPatternRangeEndpoint_Start) {
+ int boundedValue = qBound(0, m_startOffset + count, len - 1);
+ *returnValue = boundedValue - m_startOffset;
+ m_startOffset = boundedValue;
+ m_endOffset = qBound(m_startOffset, m_endOffset, len);
+ } else {
+ int boundedValue = qBound(0, m_endOffset + count, len);
+ *returnValue = boundedValue - m_endOffset;
+ m_endOffset = boundedValue;
+ m_startOffset = qBound(0, m_startOffset, m_endOffset);
+ }
+ } else {
+ QString text = metadata->text();
+ int moved = 0;
+
+ if (endpoint == TextPatternRangeEndpoint_Start) {
+ if (count > 0) {
+ for (int t = m_startOffset; (t < len - 1) && (moved < count); ++t) {
+ if (isTextUnitSeparator(unit, text[t]) && !isTextUnitSeparator(unit, text[t + 1])) {
+ m_startOffset = t + 1;
+ ++moved;
+ }
+ }
+ m_endOffset = qBound(m_startOffset, m_endOffset, len);
+ } else {
+ for (int t = m_startOffset - 1; (t >= 0) && (moved > count); --t) {
+ if (!isTextUnitSeparator(unit, text[t]) && ((t == 0) || isTextUnitSeparator(unit, text[t - 1]))) {
+ m_startOffset = t;
+ --moved;
+ }
+ }
+ }
+ } else {
+ if (count > 0) {
+ for (int t = m_endOffset; (t < len) && (moved < count); ++t) {
+ if ((t == len - 1) || (isTextUnitSeparator(unit, text[t]) && ((unit == TextUnit_Word) || !isTextUnitSeparator(unit, text[t + 1])))) {
+ m_endOffset = t + 1;
+ ++moved;
+ }
+ }
+ } else {
+ int end = 0;
+ for (int t = m_endOffset - 2; (t > 0) && (moved > count); --t) {
+ if (isTextUnitSeparator(unit, text[t]) && ((unit == TextUnit_Word) || !isTextUnitSeparator(unit, text[t + 1]))) {
+ end = t + 1;
+ --moved;
+ }
+ }
+ m_endOffset = end;
+ m_startOffset = qBound(0, m_startOffset, m_endOffset);
+ }
+ }
+ *returnValue = moved;
+ }
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::MoveEndpointByRange(TextPatternRangeEndpoint endpoint, ITextRangeProvider *textRangeProvider, TextPatternRangeEndpoint targetEndpoint)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ if (!textRangeProvider)
+ return E_INVALIDARG;
+
+ QWinRTUiaTextRangeProvider *targetProvider = static_cast<QWinRTUiaTextRangeProvider *>(textRangeProvider);
+
+ int targetPoint = (targetEndpoint == TextPatternRangeEndpoint_Start) ?
+ targetProvider->m_startOffset : targetProvider->m_endOffset;
+
+ // If the moved endpoint crosses the other endpoint, that one is moved too.
+ if (endpoint == TextPatternRangeEndpoint_Start) {
+ m_startOffset = targetPoint;
+ if (m_endOffset < m_startOffset)
+ m_endOffset = m_startOffset;
+ } else {
+ m_endOffset = targetPoint;
+ if (m_endOffset < m_startOffset)
+ m_startOffset = m_endOffset;
+ }
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::Select()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ auto accid = id();
+ auto startOffset = m_startOffset;
+ auto endOffset = m_endOffset;
+
+ QEventDispatcherWinRT::runOnMainThread([accid, startOffset, endOffset]() {
+ if (QAccessibleInterface *accessible = accessibleForId(accid))
+ if (QAccessibleTextInterface *textInterface = accessible->textInterface()) {
+ // unselects all and adds a new selection
+ for (int i = textInterface->selectionCount() - 1; i >= 0; --i)
+ textInterface->removeSelection(i);
+ textInterface->addSelection(startOffset, endOffset);
+ }
+ QWinRTUiaMetadataCache::instance()->load(accid);
+ return S_OK;
+ }, 0);
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::AddToSelection()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ return Select();
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::RemoveFromSelection()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ auto accid = id();
+
+ QEventDispatcherWinRT::runOnMainThread([accid]() {
+ if (QAccessibleInterface *accessible = accessibleForId(accid))
+ if (QAccessibleTextInterface *textInterface = accessible->textInterface()) {
+ // unselects all
+ for (int i = textInterface->selectionCount() - 1; i >= 0; --i)
+ textInterface->removeSelection(i);
+ }
+ QWinRTUiaMetadataCache::instance()->load(accid);
+ return S_OK;
+ }, 0);
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::ScrollIntoView(boolean /*alignToTop*/)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ auto accid = id();
+ auto startOffset = m_startOffset;
+ auto endOffset = m_endOffset;
+
+ QEventDispatcherWinRT::runOnMainThread([accid, startOffset, endOffset]() {
+ if (QAccessibleInterface *accessible = accessibleForId(accid))
+ if (QAccessibleTextInterface *textInterface = accessible->textInterface()) {
+ textInterface->scrollToSubstring(startOffset, endOffset);
+ }
+ QWinRTUiaMetadataCache::instance()->load(accid);
+ return S_OK;
+ }, 0);
+ return S_OK;
+}
+
+// Returns an array of children elements embedded within the range.
+HRESULT STDMETHODCALLTYPE QWinRTUiaTextRangeProvider::GetChildren(UINT32 *returnValueSize, IIRawElementProviderSimple ***returnValue)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!returnValue)
+ return E_INVALIDARG;
+ // Not supporting any children.
+ returnValueSize = 0;
+ *returnValue = nullptr;
+ return S_OK;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiatextrangeprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatextrangeprovider.h
new file mode 100644
index 0000000000..81b5f0d400
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatextrangeprovider.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTUIATEXTRANGEPROVIDER_H
+#define QWINRTUIATEXTRANGEPROVIDER_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiabaseprovider.h"
+
+#include <wrl.h>
+#include <windows.ui.xaml.h>
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Text Range control pattern provider. Used for text controls.
+class QWinRTUiaTextRangeProvider :
+ public QWinRTUiaBaseProvider,
+ public Microsoft::WRL::RuntimeClass<ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider>
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QWinRTUiaTextRangeProvider)
+ InspectableClass(L"QWinRTUiaTextRangeProvider", BaseTrust);
+
+public:
+ explicit QWinRTUiaTextRangeProvider(QAccessible::Id id, int startOffset, int endOffset);
+ virtual ~QWinRTUiaTextRangeProvider();
+
+ // ITextRangeProvider
+ HRESULT STDMETHODCALLTYPE Clone(ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider **returnValue) override;
+ HRESULT STDMETHODCALLTYPE Compare(ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider *textRangeProvider, boolean *returnValue) override;
+ HRESULT STDMETHODCALLTYPE CompareEndpoints(ABI::Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint endpoint, ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider *textRangeProvider, ABI::Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint targetEndpoint, INT32 *returnValue) override;
+ HRESULT STDMETHODCALLTYPE ExpandToEnclosingUnit(ABI::Windows::UI::Xaml::Automation::Text::TextUnit unit) override;
+ HRESULT STDMETHODCALLTYPE FindAttribute(INT32 attributeId, IInspectable *value, boolean backward, ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider **returnValue) override;
+ HRESULT STDMETHODCALLTYPE FindText(HSTRING text, boolean backward, boolean ignoreCase, ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider **returnValue) override;
+ HRESULT STDMETHODCALLTYPE GetAttributeValue(INT32 attributeId, IInspectable **returnValue) override;
+ HRESULT STDMETHODCALLTYPE GetBoundingRectangles(UINT32 *returnValueSize, DOUBLE **returnValue) override;
+ HRESULT STDMETHODCALLTYPE GetEnclosingElement(ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple **returnValue) override;
+ HRESULT STDMETHODCALLTYPE GetText(INT32 maxLength, HSTRING *returnValue) override;
+ HRESULT STDMETHODCALLTYPE Move(ABI::Windows::UI::Xaml::Automation::Text::TextUnit unit, INT32 count, INT32 *returnValue) override;
+ HRESULT STDMETHODCALLTYPE MoveEndpointByUnit(ABI::Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint endpoint, ABI::Windows::UI::Xaml::Automation::Text::TextUnit unit, INT32 count, INT32 *returnValue) override;
+ HRESULT STDMETHODCALLTYPE MoveEndpointByRange(ABI::Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint endpoint, ABI::Windows::UI::Xaml::Automation::Provider::ITextRangeProvider *textRangeProvider, ABI::Windows::UI::Xaml::Automation::Text::TextPatternRangeEndpoint targetEndpoint) override;
+ HRESULT STDMETHODCALLTYPE Select() override;
+ HRESULT STDMETHODCALLTYPE AddToSelection() override;
+ HRESULT STDMETHODCALLTYPE RemoveFromSelection() override;
+ HRESULT STDMETHODCALLTYPE ScrollIntoView(boolean alignToTop) override;
+ HRESULT STDMETHODCALLTYPE GetChildren(UINT32 *returnValueSize, ABI::Windows::UI::Xaml::Automation::Provider::IIRawElementProviderSimple ***returnValue) override;
+
+private:
+ int m_startOffset;
+ int m_endOffset;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QWINRTUIATEXTRANGEPROVIDER_H
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiatoggleprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatoggleprovider.cpp
new file mode 100644
index 0000000000..59f55eb422
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatoggleprovider.cpp
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiatoggleprovider.h"
+#include "qwinrtuiametadatacache.h"
+#include "qwinrtuiautils.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QString>
+#include <QtCore/private/qeventdispatcher_winrt_p.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWinRTUiAutomation;
+using namespace ABI::Windows::UI::Xaml::Automation;
+using namespace ABI::Windows::UI::Xaml::Automation::Provider;
+
+QWinRTUiaToggleProvider::QWinRTUiaToggleProvider(QAccessible::Id id) :
+ QWinRTUiaBaseProvider(id)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+}
+
+QWinRTUiaToggleProvider::~QWinRTUiaToggleProvider()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+}
+
+// Gets the current toggle state.
+HRESULT STDMETHODCALLTYPE QWinRTUiaToggleProvider::get_ToggleState(ToggleState *value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!value)
+ return E_INVALIDARG;
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ if (metadata->state().checked)
+ *value = metadata->state().checkStateMixed ? ToggleState_Indeterminate : ToggleState_On;
+ else
+ *value = ToggleState_Off;
+ return S_OK;
+}
+
+// Toggles the state by invoking the toggle action.
+HRESULT STDMETHODCALLTYPE QWinRTUiaToggleProvider::Toggle()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ auto accid = id();
+
+ QEventDispatcherWinRT::runOnMainThread([accid]() {
+ if (QAccessibleInterface *accessible = accessibleForId(accid))
+ if (QAccessibleActionInterface *actionInterface = accessible->actionInterface())
+ actionInterface->doAction(QAccessibleActionInterface::toggleAction());
+ QWinRTUiaMetadataCache::instance()->load(accid);
+ return S_OK;
+ }, 0);
+ return S_OK;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiatoggleprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatoggleprovider.h
new file mode 100644
index 0000000000..3d1740c0a1
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiatoggleprovider.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTUIATOGGLEPROVIDER_H
+#define QWINRTUIATOGGLEPROVIDER_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiabaseprovider.h"
+
+#include <wrl.h>
+#include <windows.ui.xaml.h>
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Toggle control pattern provider. Used for checkboxes.
+class QWinRTUiaToggleProvider :
+ public QWinRTUiaBaseProvider,
+ public Microsoft::WRL::RuntimeClass<ABI::Windows::UI::Xaml::Automation::Provider::IToggleProvider>
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QWinRTUiaToggleProvider)
+ InspectableClass(L"QWinRTUiaToggleProvider", BaseTrust);
+
+public:
+ explicit QWinRTUiaToggleProvider(QAccessible::Id id);
+ virtual ~QWinRTUiaToggleProvider();
+
+ // IToggleProvider
+ HRESULT STDMETHODCALLTYPE get_ToggleState(ABI::Windows::UI::Xaml::Automation::ToggleState *value) override;
+ HRESULT STDMETHODCALLTYPE Toggle() override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QWINRTUIATOGGLEPROVIDER_H
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.cpp
new file mode 100644
index 0000000000..16197c99b9
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.cpp
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiautils.h"
+
+using namespace ABI::Windows::UI::Xaml::Automation::Peers;
+using namespace ABI::Windows::UI::Xaml::Automation::Text;
+using namespace ABI::Windows::Foundation::Collections;
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcQpaUiAutomation, "qt.qpa.uiautomation")
+
+namespace QWinRTUiAutomation {
+
+// Returns the window containing the element (usually the top window),
+QWindow *windowForAccessible(const QAccessibleInterface *accessible)
+{
+ QWindow *window = accessible->window();
+ if (!window) {
+ QAccessibleInterface *acc = accessible->parent();
+ while (acc && acc->isValid() && !window) {
+ window = acc->window();
+ QAccessibleInterface *par = acc->parent();
+ acc = par;
+ }
+ }
+ return window;
+}
+
+QAccessibleInterface *accessibleForId(QAccessible::Id id)
+{
+ QAccessibleInterface *accessible = QAccessible::accessibleInterface(id);
+ if (!accessible || !accessible->isValid())
+ return nullptr;
+ return accessible;
+}
+
+QAccessible::Id idForAccessible(QAccessibleInterface *accessible)
+{
+ if (!accessible)
+ return QAccessible::Id(0);
+ return QAccessible::uniqueId(accessible);
+}
+
+// Maps an accessibility role ID to an UI Automation control type ID.
+AutomationControlType roleToControlType(QAccessible::Role role)
+{
+ static const QHash<QAccessible::Role, AutomationControlType> mapping {
+ {QAccessible::TitleBar, AutomationControlType::AutomationControlType_TitleBar},
+ {QAccessible::MenuBar, AutomationControlType::AutomationControlType_MenuBar},
+ {QAccessible::ScrollBar, AutomationControlType::AutomationControlType_ScrollBar},
+ {QAccessible::Grip, AutomationControlType::AutomationControlType_Thumb},
+ {QAccessible::Sound, AutomationControlType::AutomationControlType_Custom},
+ {QAccessible::Cursor, AutomationControlType::AutomationControlType_Custom},
+ {QAccessible::Caret, AutomationControlType::AutomationControlType_Custom},
+ {QAccessible::AlertMessage, AutomationControlType::AutomationControlType_Custom},
+ {QAccessible::Window, AutomationControlType::AutomationControlType_Window},
+ {QAccessible::Client, AutomationControlType::AutomationControlType_Custom},
+ {QAccessible::PopupMenu, AutomationControlType::AutomationControlType_Menu},
+ {QAccessible::MenuItem, AutomationControlType::AutomationControlType_MenuItem},
+ {QAccessible::ToolTip, AutomationControlType::AutomationControlType_ToolTip},
+ {QAccessible::Application, AutomationControlType::AutomationControlType_Custom},
+ {QAccessible::Document, AutomationControlType::AutomationControlType_Document},
+ {QAccessible::Pane, AutomationControlType::AutomationControlType_Pane},
+ {QAccessible::Chart, AutomationControlType::AutomationControlType_Custom},
+ {QAccessible::Dialog, AutomationControlType::AutomationControlType_Window},
+ {QAccessible::Border, AutomationControlType::AutomationControlType_Custom},
+ {QAccessible::Grouping, AutomationControlType::AutomationControlType_Group},
+ {QAccessible::Separator, AutomationControlType::AutomationControlType_Separator},
+ {QAccessible::ToolBar, AutomationControlType::AutomationControlType_ToolBar},
+ {QAccessible::StatusBar, AutomationControlType::AutomationControlType_StatusBar},
+ {QAccessible::Table, AutomationControlType::AutomationControlType_Table},
+ {QAccessible::ColumnHeader, AutomationControlType::AutomationControlType_Header},
+ {QAccessible::RowHeader, AutomationControlType::AutomationControlType_Header},
+ {QAccessible::Column, AutomationControlType::AutomationControlType_HeaderItem},
+ {QAccessible::Row, AutomationControlType::AutomationControlType_HeaderItem},
+ {QAccessible::Cell, AutomationControlType::AutomationControlType_DataItem},
+ {QAccessible::Link, AutomationControlType::AutomationControlType_Hyperlink},
+ {QAccessible::HelpBalloon, AutomationControlType::AutomationControlType_ToolTip},
+ {QAccessible::Assistant, AutomationControlType::AutomationControlType_Custom},
+ {QAccessible::List, AutomationControlType::AutomationControlType_List},
+ {QAccessible::ListItem, AutomationControlType::AutomationControlType_ListItem},
+ {QAccessible::Tree, AutomationControlType::AutomationControlType_Tree},
+ {QAccessible::TreeItem, AutomationControlType::AutomationControlType_TreeItem},
+ {QAccessible::PageTab, AutomationControlType::AutomationControlType_TabItem},
+ {QAccessible::PropertyPage, AutomationControlType::AutomationControlType_Custom},
+ {QAccessible::Indicator, AutomationControlType::AutomationControlType_Custom},
+ {QAccessible::Graphic, AutomationControlType::AutomationControlType_Image},
+ {QAccessible::StaticText, AutomationControlType::AutomationControlType_Text},
+ {QAccessible::EditableText, AutomationControlType::AutomationControlType_Edit},
+ {QAccessible::Button, AutomationControlType::AutomationControlType_Button},
+ {QAccessible::CheckBox, AutomationControlType::AutomationControlType_CheckBox},
+ {QAccessible::RadioButton, AutomationControlType::AutomationControlType_RadioButton},
+ {QAccessible::ComboBox, AutomationControlType::AutomationControlType_ComboBox},
+ {QAccessible::ProgressBar, AutomationControlType::AutomationControlType_ProgressBar},
+ {QAccessible::Dial, AutomationControlType::AutomationControlType_Custom},
+ {QAccessible::HotkeyField, AutomationControlType::AutomationControlType_Custom},
+ {QAccessible::Slider, AutomationControlType::AutomationControlType_Slider},
+ {QAccessible::SpinBox, AutomationControlType::AutomationControlType_Spinner},
+ {QAccessible::Canvas, AutomationControlType::AutomationControlType_Custom},
+ {QAccessible::Animation, AutomationControlType::AutomationControlType_Custom},
+ {QAccessible::Equation, AutomationControlType::AutomationControlType_Custom},
+ {QAccessible::ButtonDropDown, AutomationControlType::AutomationControlType_Button},
+ {QAccessible::ButtonMenu, AutomationControlType::AutomationControlType_Button},
+ {QAccessible::ButtonDropGrid, AutomationControlType::AutomationControlType_Button},
+ {QAccessible::Whitespace, AutomationControlType::AutomationControlType_Custom},
+ {QAccessible::PageTabList, AutomationControlType::AutomationControlType_Tab},
+ {QAccessible::Clock, AutomationControlType::AutomationControlType_Custom},
+ {QAccessible::Splitter, AutomationControlType::AutomationControlType_Custom},
+ };
+
+ return mapping.value(role, AutomationControlType::AutomationControlType_Custom);
+}
+
+// True if a character can be a separator for a text unit.
+bool isTextUnitSeparator(TextUnit unit, const QChar &ch)
+{
+ return (((unit == TextUnit_Word) || (unit == TextUnit_Format)) && ch.isSpace())
+ || ((unit == TextUnit_Line) && (ch.toLatin1() == '\n'));
+}
+
+HRESULT qHString(const QString &str, HSTRING *returnValue)
+{
+ if (!returnValue)
+ return E_INVALIDARG;
+
+ const wchar_t *wstr = reinterpret_cast<const wchar_t *>(str.utf16());
+ return ::WindowsCreateString(wstr, static_cast<UINT32>(::wcslen(wstr)), returnValue);
+}
+
+QString hStrToQStr(const HSTRING &hStr)
+{
+ quint32 len;
+ const wchar_t *wstr = ::WindowsGetStringRawBuffer(hStr, &len);
+ return QString::fromWCharArray(wstr, len);
+}
+
+} // namespace QWinRTUiAutomation
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.h
new file mode 100644
index 0000000000..9519cb4eb5
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTUIAUTILS_H
+#define QWINRTUIAUTILS_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include <QtCore/QString>
+#include <QtCore/qt_windows.h>
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtGui/QWindow>
+#include <QtCore/QLoggingCategory>
+
+#include <wrl.h>
+#include <windows.ui.xaml.h>
+#include <functional>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(lcQpaUiAutomation)
+
+namespace QWinRTUiAutomation {
+
+QWindow *windowForAccessible(const QAccessibleInterface *accessible);
+
+QAccessibleInterface *accessibleForId(QAccessible::Id id);
+
+QAccessible::Id idForAccessible(QAccessibleInterface *accessible);
+
+ABI::Windows::UI::Xaml::Automation::Peers::AutomationControlType roleToControlType(QAccessible::Role role);
+
+bool isTextUnitSeparator(ABI::Windows::UI::Xaml::Automation::Text::TextUnit unit, const QChar &ch);
+
+HRESULT qHString(const QString &str, HSTRING *returnValue);
+
+QString hStrToQStr(const HSTRING &hStr);
+
+} // namespace QWinRTUiAutomation
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QWINRTUIAUTILS_H
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiavalueprovider.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiavalueprovider.cpp
new file mode 100644
index 0000000000..21389b74d2
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiavalueprovider.cpp
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiavalueprovider.h"
+#include "qwinrtuiametadatacache.h"
+#include "qwinrtuiautils.h"
+
+#include <QtGui/QAccessible>
+#include <QtGui/QAccessibleInterface>
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QString>
+#include <QtCore/private/qeventdispatcher_winrt_p.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWinRTUiAutomation;
+using namespace ABI::Windows::UI::Xaml::Automation;
+using namespace ABI::Windows::UI::Xaml::Automation::Provider;
+
+QWinRTUiaValueProvider::QWinRTUiaValueProvider(QAccessible::Id id) :
+ QWinRTUiaBaseProvider(id)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+}
+
+QWinRTUiaValueProvider::~QWinRTUiaValueProvider()
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+}
+
+// True for read-only controls.
+HRESULT STDMETHODCALLTYPE QWinRTUiaValueProvider::get_IsReadOnly(boolean *value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!value)
+ return E_INVALIDARG;
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ *value = (metadata->state().readOnly != 0);
+ return S_OK;
+}
+
+// Returns the value in text form.
+HRESULT STDMETHODCALLTYPE QWinRTUiaValueProvider::get_Value(HSTRING *value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ if (!value)
+ return E_INVALIDARG;
+ QSharedPointer<QWinRTUiaControlMetadata> metadata = QWinRTUiaMetadataCache::instance()->metadataForId(id());
+ return qHString(metadata->value(), value);
+}
+
+// Sets the value associated with the control.
+HRESULT STDMETHODCALLTYPE QWinRTUiaValueProvider::SetValue(HSTRING value)
+{
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+
+ auto accid = id();
+ auto tmpValue = QSharedPointer<QString>(new QString);
+ auto ptrValue = new QSharedPointer<QString>(tmpValue);
+
+ *tmpValue = hStrToQStr(value);
+
+ QEventDispatcherWinRT::runOnMainThread([accid, ptrValue]() {
+
+ if (QAccessibleInterface *accessible = accessibleForId(accid)) {
+
+ // First sets the value as a text.
+ accessible->setText(QAccessible::Value, **ptrValue);
+
+ // Then, if the control supports the value interface (range value)
+ // and the supplied text can be converted to a number, and that number
+ // lies within the min/max limits, sets it as the control's current (numeric) value.
+ if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
+ bool ok = false;
+ double numval = (*ptrValue)->toDouble(&ok);
+ if (ok) {
+ double minimum = valueInterface->minimumValue().toDouble();
+ double maximum = valueInterface->maximumValue().toDouble();
+ if ((numval >= minimum) && (numval <= maximum)) {
+ valueInterface->setCurrentValue(QVariant(numval));
+ }
+ }
+ }
+ }
+ QWinRTUiaMetadataCache::instance()->load(accid);
+ delete ptrValue;
+ return S_OK;
+ }, 0);
+
+ return S_OK;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiavalueprovider.h b/src/plugins/platforms/winrt/uiautomation/qwinrtuiavalueprovider.h
new file mode 100644
index 0000000000..d9cd5d200d
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiavalueprovider.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINRTUIAVALUEPROVIDER_H
+#define QWINRTUIAVALUEPROVIDER_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwinrtuiabaseprovider.h"
+
+#include <wrl.h>
+#include <windows.ui.xaml.h>
+
+QT_BEGIN_NAMESPACE
+
+// Implements the Value control pattern provider.
+// Supported for all controls that can return text(QAccessible::Value).
+class QWinRTUiaValueProvider :
+ public QWinRTUiaBaseProvider,
+ public Microsoft::WRL::RuntimeClass<ABI::Windows::UI::Xaml::Automation::Provider::IValueProvider>
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QWinRTUiaValueProvider)
+ InspectableClass(L"QWinRTUiaValueProvider", BaseTrust);
+
+public:
+ explicit QWinRTUiaValueProvider(QAccessible::Id id);
+ virtual ~QWinRTUiaValueProvider();
+
+ // IValueProvider
+ HRESULT STDMETHODCALLTYPE get_IsReadOnly(boolean *value) override;
+ HRESULT STDMETHODCALLTYPE get_Value(HSTRING *value) override;
+ HRESULT STDMETHODCALLTYPE SetValue(HSTRING value) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QWINRTUIAVALUEPROVIDER_H
diff --git a/src/plugins/platforms/winrt/uiautomation/uiautomation.pri b/src/plugins/platforms/winrt/uiautomation/uiautomation.pri
new file mode 100644
index 0000000000..ca0dfae53f
--- /dev/null
+++ b/src/plugins/platforms/winrt/uiautomation/uiautomation.pri
@@ -0,0 +1,45 @@
+
+SOURCES += \
+ $$PWD/qwinrtuiaaccessibility.cpp \
+ $$PWD/qwinrtuiabaseprovider.cpp \
+ $$PWD/qwinrtuiacontrolmetadata.cpp \
+ $$PWD/qwinrtuiagriditemprovider.cpp \
+ $$PWD/qwinrtuiagridprovider.cpp \
+ $$PWD/qwinrtuiainvokeprovider.cpp \
+ $$PWD/qwinrtuiamainprovider.cpp \
+ $$PWD/qwinrtuiametadatacache.cpp \
+ $$PWD/qwinrtuiapeervector.cpp \
+ $$PWD/qwinrtuiaprovidercache.cpp \
+ $$PWD/qwinrtuiarangevalueprovider.cpp \
+ $$PWD/qwinrtuiaselectionitemprovider.cpp \
+ $$PWD/qwinrtuiaselectionprovider.cpp \
+ $$PWD/qwinrtuiatableitemprovider.cpp \
+ $$PWD/qwinrtuiatableprovider.cpp \
+ $$PWD/qwinrtuiatextprovider.cpp \
+ $$PWD/qwinrtuiatextrangeprovider.cpp \
+ $$PWD/qwinrtuiatoggleprovider.cpp \
+ $$PWD/qwinrtuiautils.cpp \
+ $$PWD/qwinrtuiavalueprovider.cpp
+
+HEADERS += \
+ $$PWD/qwinrtuiaaccessibility.h \
+ $$PWD/qwinrtuiabaseprovider.h \
+ $$PWD/qwinrtuiacontrolmetadata.h \
+ $$PWD/qwinrtuiaemptypropertyvalue.h \
+ $$PWD/qwinrtuiagriditemprovider.h \
+ $$PWD/qwinrtuiagridprovider.h \
+ $$PWD/qwinrtuiainvokeprovider.h \
+ $$PWD/qwinrtuiamainprovider.h \
+ $$PWD/qwinrtuiametadatacache.h \
+ $$PWD/qwinrtuiapeervector.h \
+ $$PWD/qwinrtuiaprovidercache.h \
+ $$PWD/qwinrtuiarangevalueprovider.h \
+ $$PWD/qwinrtuiaselectionitemprovider.h \
+ $$PWD/qwinrtuiaselectionprovider.h \
+ $$PWD/qwinrtuiatableitemprovider.h \
+ $$PWD/qwinrtuiatableprovider.h \
+ $$PWD/qwinrtuiatextprovider.h \
+ $$PWD/qwinrtuiatextrangeprovider.h \
+ $$PWD/qwinrtuiatoggleprovider.h \
+ $$PWD/qwinrtuiautils.h \
+ $$PWD/qwinrtuiavalueprovider.h
diff --git a/src/plugins/platforms/winrt/winrt.pro b/src/plugins/platforms/winrt/winrt.pro
index 46371b4880..6a847465e4 100644
--- a/src/plugins/platforms/winrt/winrt.pro
+++ b/src/plugins/platforms/winrt/winrt.pro
@@ -13,6 +13,7 @@ LIBS += -lws2_32 -ld3d11
SOURCES = \
main.cpp \
qwinrtbackingstore.cpp \
+ qwinrtcanvas.cpp \
qwinrtclipboard.cpp \
qwinrtcursor.cpp \
qwinrteglcontext.cpp \
@@ -30,6 +31,7 @@ SOURCES = \
HEADERS = \
qwinrtbackingstore.h \
+ qwinrtcanvas.h \
qwinrtclipboard.h \
qwinrtcursor.h \
qwinrteglcontext.h \
@@ -56,6 +58,8 @@ qtConfig(draganddrop) {
HEADERS += qwinrtdrag.h
}
+qtConfig(accessibility): include($$PWD/uiautomation/uiautomation.pri)
+
PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = QWinRTIntegrationPlugin
!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
diff --git a/src/plugins/platforms/xcb/README b/src/plugins/platforms/xcb/README
index 8308db46dc..5f238ab261 100644
--- a/src/plugins/platforms/xcb/README
+++ b/src/plugins/platforms/xcb/README
@@ -1,32 +1,7 @@
-Requires libxcb >= 1.5.
-
-PACKAGE DEPENDENCIES
-
-Required packages:
-libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm1 libxcb-icccm1-dev libxcb-sync0 libxcb-sync0-dev libxcb-render-util0 libxcb-render-util0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-glx0-dev libxcb-xinerama0-dev
-
-On Ubuntu 11.10 icccm1 is replaced by icccm4 and xcb-render-util is not available:
-libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm4 libxcb-icccm4-dev libxcb-sync0 libxcb-sync0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-glx0-dev libxcb-xinerama0-dev
-The packages for xcb-render-util can be installed manually from http://packages.ubuntu.com/natty/libxcb-render-util0 and http://packages.ubuntu.com/natty/libxcb-render-util0-dev
-
-On Ubuntu 12.04 icccm1 is replaced by icccm4 and xcb-render-util can be installed automatically:
-libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm4 libxcb-icccm4-dev libxcb-sync0 libxcb-sync0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-render-util0 libxcb-render-util0-dev libxcb-glx0-dev libxcb-xinerama0-dev
-
-
-On Fedora, the following packages are required:
-libxcb libxcb-devel libXrender libXrender-devel xcb-util-wm xcb-util-wm-devel xcb-util xcb-util-devel xcb-util-image xcb-util-image-devel xcb-util-keysyms xcb-util-keysyms-devel
+Requires libxcb >= 1.9.1.
REDUCING RUNTIME DEPENDENCIES
The '-qt-xcb' configure option can be used to get rid of most xcb- dependencies. Only libxcb will
still be linked dynamically, since it will be most likely be pulled in via other dependencies anyway.
This should allow for binaries that are portable across most modern Linux distributions.
-
-PACKAGE VERSION REQUIREMENTS
-
-When using touch input via XInput 2.2 or higher, there is a potential issue on systems that ship with
-a libXi older than 1.7.5. This is because XIAllowTouchEvents can deadlock with libXi 1.7.4 and earlier.
-When touch events are never received, this is not an issue, so plain mouse/keyboard systems are not affected.
-Qt versions before 5.8 attempted to recognize this scenario based on the pkg-config package version and skip
-the call. This has been removed starting from 5.8 since relying on pkg-config package versions is unsafe given
-that Qt must also support systems with limited or incomplete pkg-config setups.
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp
index a7641baea1..b751aaf8a3 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp
@@ -163,9 +163,9 @@ bool QXcbGlxIntegration::handleXcbEvent(xcb_generic_event_t *event, uint respons
// Unlock the display before calling the native event filter
XUnlockDisplay(xdisplay);
locked = false;
- QByteArray genericEventFilterType = m_connection->nativeInterface()->genericEventFilterType();
+ auto eventType = m_connection->nativeInterface()->nativeEventType();
long result = 0;
- handled = dispatcher->filterNativeEvent(genericEventFilterType, &ev, &result);
+ handled = dispatcher->filterNativeEvent(eventType, &ev, &result);
}
#endif
}
diff --git a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp
index 8b63e5431d..a3e6cedecd 100644
--- a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp
+++ b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp
@@ -226,7 +226,9 @@ public:
QXRenderGlyphCache(QXcbX11Info x, QFontEngine::GlyphFormat format, const QTransform &matrix);
~QXRenderGlyphCache();
- bool addGlyphs(const QTextItemInt &ti, QVarLengthArray<glyph_t> glyphs, QVarLengthArray<QFixedPoint> positions);
+ bool addGlyphs(const QTextItemInt &ti,
+ const QVarLengthArray<glyph_t> &glyphs,
+ const QVarLengthArray<QFixedPoint> &positions);
bool draw(Drawable src, Drawable dst, const QTransform &matrix, const QTextItemInt &ti);
inline GlyphSet glyphSet();
@@ -2608,7 +2610,9 @@ QXRenderGlyphCache::~QXRenderGlyphCache()
XRenderFreeGlyphSet(xinfo.display(), gset);
}
-bool QXRenderGlyphCache::addGlyphs(const QTextItemInt &ti, QVarLengthArray<glyph_t> glyphs, QVarLengthArray<QFixedPoint> positions)
+bool QXRenderGlyphCache::addGlyphs(const QTextItemInt &ti,
+ const QVarLengthArray<glyph_t> &glyphs,
+ const QVarLengthArray<QFixedPoint> &positions)
{
Q_ASSERT(ti.fontEngine->type() == QFontEngine::Freetype);
diff --git a/src/plugins/platforms/xcb/qxcbatom.cpp b/src/plugins/platforms/xcb/qxcbatom.cpp
new file mode 100644
index 0000000000..ecb73cb90b
--- /dev/null
+++ b/src/plugins/platforms/xcb/qxcbatom.cpp
@@ -0,0 +1,277 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 "qxcbatom.h"
+
+#include <QtCore/qglobal.h>
+
+#include <string.h>
+
+#include <algorithm>
+
+static const char *xcb_atomnames = {
+ // window-manager <-> client protocols
+ "WM_PROTOCOLS\0"
+ "WM_DELETE_WINDOW\0"
+ "WM_TAKE_FOCUS\0"
+ "_NET_WM_PING\0"
+ "_NET_WM_CONTEXT_HELP\0"
+ "_NET_WM_SYNC_REQUEST\0"
+ "_NET_WM_SYNC_REQUEST_COUNTER\0"
+ "MANAGER\0"
+ "_NET_SYSTEM_TRAY_OPCODE\0"
+
+ // ICCCM window state
+ "WM_STATE\0"
+ "WM_CHANGE_STATE\0"
+ "WM_CLASS\0"
+ "WM_NAME\0"
+
+ // Session management
+ "WM_CLIENT_LEADER\0"
+ "WM_WINDOW_ROLE\0"
+ "SM_CLIENT_ID\0"
+ "WM_CLIENT_MACHINE\0"
+
+ // Clipboard
+ "CLIPBOARD\0"
+ "INCR\0"
+ "TARGETS\0"
+ "MULTIPLE\0"
+ "TIMESTAMP\0"
+ "SAVE_TARGETS\0"
+ "CLIP_TEMPORARY\0"
+ "_QT_SELECTION\0"
+ "_QT_CLIPBOARD_SENTINEL\0"
+ "_QT_SELECTION_SENTINEL\0"
+ "CLIPBOARD_MANAGER\0"
+
+ "RESOURCE_MANAGER\0"
+
+ "_XSETROOT_ID\0"
+
+ "_QT_SCROLL_DONE\0"
+ "_QT_INPUT_ENCODING\0"
+
+ "_QT_CLOSE_CONNECTION\0"
+
+ "_MOTIF_WM_HINTS\0"
+
+ "DTWM_IS_RUNNING\0"
+ "ENLIGHTENMENT_DESKTOP\0"
+ "_DT_SAVE_MODE\0"
+ "_SGI_DESKS_MANAGER\0"
+
+ // EWMH (aka NETWM)
+ "_NET_SUPPORTED\0"
+ "_NET_VIRTUAL_ROOTS\0"
+ "_NET_WORKAREA\0"
+
+ "_NET_MOVERESIZE_WINDOW\0"
+ "_NET_WM_MOVERESIZE\0"
+
+ "_NET_WM_NAME\0"
+ "_NET_WM_ICON_NAME\0"
+ "_NET_WM_ICON\0"
+
+ "_NET_WM_PID\0"
+
+ "_NET_WM_WINDOW_OPACITY\0"
+
+ "_NET_WM_STATE\0"
+ "_NET_WM_STATE_ABOVE\0"
+ "_NET_WM_STATE_BELOW\0"
+ "_NET_WM_STATE_FULLSCREEN\0"
+ "_NET_WM_STATE_MAXIMIZED_HORZ\0"
+ "_NET_WM_STATE_MAXIMIZED_VERT\0"
+ "_NET_WM_STATE_MODAL\0"
+ "_NET_WM_STATE_STAYS_ON_TOP\0"
+ "_NET_WM_STATE_DEMANDS_ATTENTION\0"
+
+ "_NET_WM_USER_TIME\0"
+ "_NET_WM_USER_TIME_WINDOW\0"
+ "_NET_WM_FULL_PLACEMENT\0"
+
+ "_NET_WM_WINDOW_TYPE\0"
+ "_NET_WM_WINDOW_TYPE_DESKTOP\0"
+ "_NET_WM_WINDOW_TYPE_DOCK\0"
+ "_NET_WM_WINDOW_TYPE_TOOLBAR\0"
+ "_NET_WM_WINDOW_TYPE_MENU\0"
+ "_NET_WM_WINDOW_TYPE_UTILITY\0"
+ "_NET_WM_WINDOW_TYPE_SPLASH\0"
+ "_NET_WM_WINDOW_TYPE_DIALOG\0"
+ "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU\0"
+ "_NET_WM_WINDOW_TYPE_POPUP_MENU\0"
+ "_NET_WM_WINDOW_TYPE_TOOLTIP\0"
+ "_NET_WM_WINDOW_TYPE_NOTIFICATION\0"
+ "_NET_WM_WINDOW_TYPE_COMBO\0"
+ "_NET_WM_WINDOW_TYPE_DND\0"
+ "_NET_WM_WINDOW_TYPE_NORMAL\0"
+ "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE\0"
+
+ "_KDE_NET_WM_FRAME_STRUT\0"
+ "_NET_FRAME_EXTENTS\0"
+
+ "_NET_STARTUP_INFO\0"
+ "_NET_STARTUP_INFO_BEGIN\0"
+
+ "_NET_SUPPORTING_WM_CHECK\0"
+
+ "_NET_WM_CM_S0\0"
+
+ "_NET_SYSTEM_TRAY_VISUAL\0"
+
+ "_NET_ACTIVE_WINDOW\0"
+
+ // Property formats
+ "TEXT\0"
+ "UTF8_STRING\0"
+ "CARDINAL\0"
+
+ // xdnd
+ "XdndEnter\0"
+ "XdndPosition\0"
+ "XdndStatus\0"
+ "XdndLeave\0"
+ "XdndDrop\0"
+ "XdndFinished\0"
+ "XdndTypeList\0"
+ "XdndActionList\0"
+
+ "XdndSelection\0"
+
+ "XdndAware\0"
+ "XdndProxy\0"
+
+ "XdndActionCopy\0"
+ "XdndActionLink\0"
+ "XdndActionMove\0"
+ "XdndActionPrivate\0"
+
+ // Xkb
+ "_XKB_RULES_NAMES\0"
+
+ // XEMBED
+ "_XEMBED\0"
+ "_XEMBED_INFO\0"
+
+ // XInput2
+ "Button Left\0"
+ "Button Middle\0"
+ "Button Right\0"
+ "Button Wheel Up\0"
+ "Button Wheel Down\0"
+ "Button Horiz Wheel Left\0"
+ "Button Horiz Wheel Right\0"
+ "Abs MT Position X\0"
+ "Abs MT Position Y\0"
+ "Abs MT Touch Major\0"
+ "Abs MT Touch Minor\0"
+ "Abs MT Orientation\0"
+ "Abs MT Pressure\0"
+ "Abs MT Tracking ID\0"
+ "Max Contacts\0"
+ "Rel X\0"
+ "Rel Y\0"
+ // XInput2 tablet
+ "Abs X\0"
+ "Abs Y\0"
+ "Abs Pressure\0"
+ "Abs Tilt X\0"
+ "Abs Tilt Y\0"
+ "Abs Wheel\0"
+ "Abs Distance\0"
+ "Wacom Serial IDs\0"
+ "INTEGER\0"
+ "Rel Horiz Wheel\0"
+ "Rel Vert Wheel\0"
+ "Rel Horiz Scroll\0"
+ "Rel Vert Scroll\0"
+ "_XSETTINGS_SETTINGS\0"
+ "_COMPIZ_DECOR_PENDING\0"
+ "_COMPIZ_DECOR_REQUEST\0"
+ "_COMPIZ_DECOR_DELETE_PIXMAP\0"
+ "_COMPIZ_TOOLKIT_ACTION\0"
+ "_GTK_LOAD_ICONTHEMES\0"
+ "AT_SPI_BUS\0"
+ "EDID\0"
+ "EDID_DATA\0"
+ "XFree86_DDC_EDID1_RAWDATA\0"
+ // \0\0 terminates loop.
+};
+
+QXcbAtom::QXcbAtom()
+{
+}
+
+void QXcbAtom::initialize(xcb_connection_t *connection)
+{
+ initializeAllAtoms(connection);
+}
+
+void QXcbAtom::initializeAllAtoms(xcb_connection_t *connection) {
+ const char *names[QXcbAtom::NAtoms];
+ const char *ptr = xcb_atomnames;
+
+ int i = 0;
+ while (*ptr) {
+ names[i++] = ptr;
+ while (*ptr)
+ ++ptr;
+ ++ptr;
+ }
+
+ Q_ASSERT(i == QXcbAtom::NAtoms);
+
+ xcb_intern_atom_cookie_t cookies[QXcbAtom::NAtoms];
+
+ Q_ASSERT(i == QXcbAtom::NAtoms);
+ for (i = 0; i < QXcbAtom::NAtoms; ++i)
+ cookies[i] = xcb_intern_atom(connection, false, strlen(names[i]), names[i]);
+
+ for (i = 0; i < QXcbAtom::NAtoms; ++i) {
+ xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(connection, cookies[i], 0);
+ m_allAtoms[i] = reply->atom;
+ free(reply);
+ }
+}
+
+QXcbAtom::Atom QXcbAtom::qatom(xcb_atom_t xatom) const
+{
+ return static_cast<QXcbAtom::Atom>(std::find(m_allAtoms, m_allAtoms + QXcbAtom::NAtoms, xatom) - m_allAtoms);
+}
diff --git a/src/plugins/platforms/xcb/qxcbatom.h b/src/plugins/platforms/xcb/qxcbatom.h
new file mode 100644
index 0000000000..233d2eadb7
--- /dev/null
+++ b/src/plugins/platforms/xcb/qxcbatom.h
@@ -0,0 +1,257 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 QXCBATOM_H
+#define QXCBATOM_H
+
+#include <xcb/xcb.h>
+
+class QXcbAtom
+{
+public:
+ enum Atom {
+ // window-manager <-> client protocols
+ WM_PROTOCOLS,
+ WM_DELETE_WINDOW,
+ WM_TAKE_FOCUS,
+ _NET_WM_PING,
+ _NET_WM_CONTEXT_HELP,
+ _NET_WM_SYNC_REQUEST,
+ _NET_WM_SYNC_REQUEST_COUNTER,
+ MANAGER, // System tray notification
+ _NET_SYSTEM_TRAY_OPCODE, // System tray operation
+
+ // ICCCM window state
+ WM_STATE,
+ WM_CHANGE_STATE,
+ WM_CLASS,
+ WM_NAME,
+
+ // Session management
+ WM_CLIENT_LEADER,
+ WM_WINDOW_ROLE,
+ SM_CLIENT_ID,
+ WM_CLIENT_MACHINE,
+
+ // Clipboard
+ CLIPBOARD,
+ INCR,
+ TARGETS,
+ MULTIPLE,
+ TIMESTAMP,
+ SAVE_TARGETS,
+ CLIP_TEMPORARY,
+ _QT_SELECTION,
+ _QT_CLIPBOARD_SENTINEL,
+ _QT_SELECTION_SENTINEL,
+ CLIPBOARD_MANAGER,
+
+ RESOURCE_MANAGER,
+
+ _XSETROOT_ID,
+
+ _QT_SCROLL_DONE,
+ _QT_INPUT_ENCODING,
+
+ // Qt/XCB specific
+ _QT_CLOSE_CONNECTION,
+
+ _MOTIF_WM_HINTS,
+
+ DTWM_IS_RUNNING,
+ ENLIGHTENMENT_DESKTOP,
+ _DT_SAVE_MODE,
+ _SGI_DESKS_MANAGER,
+
+ // EWMH (aka NETWM)
+ _NET_SUPPORTED,
+ _NET_VIRTUAL_ROOTS,
+ _NET_WORKAREA,
+
+ _NET_MOVERESIZE_WINDOW,
+ _NET_WM_MOVERESIZE,
+
+ _NET_WM_NAME,
+ _NET_WM_ICON_NAME,
+ _NET_WM_ICON,
+
+ _NET_WM_PID,
+
+ _NET_WM_WINDOW_OPACITY,
+
+ _NET_WM_STATE,
+ _NET_WM_STATE_ABOVE,
+ _NET_WM_STATE_BELOW,
+ _NET_WM_STATE_FULLSCREEN,
+ _NET_WM_STATE_MAXIMIZED_HORZ,
+ _NET_WM_STATE_MAXIMIZED_VERT,
+ _NET_WM_STATE_MODAL,
+ _NET_WM_STATE_STAYS_ON_TOP,
+ _NET_WM_STATE_DEMANDS_ATTENTION,
+
+ _NET_WM_USER_TIME,
+ _NET_WM_USER_TIME_WINDOW,
+ _NET_WM_FULL_PLACEMENT,
+
+ _NET_WM_WINDOW_TYPE,
+ _NET_WM_WINDOW_TYPE_DESKTOP,
+ _NET_WM_WINDOW_TYPE_DOCK,
+ _NET_WM_WINDOW_TYPE_TOOLBAR,
+ _NET_WM_WINDOW_TYPE_MENU,
+ _NET_WM_WINDOW_TYPE_UTILITY,
+ _NET_WM_WINDOW_TYPE_SPLASH,
+ _NET_WM_WINDOW_TYPE_DIALOG,
+ _NET_WM_WINDOW_TYPE_DROPDOWN_MENU,
+ _NET_WM_WINDOW_TYPE_POPUP_MENU,
+ _NET_WM_WINDOW_TYPE_TOOLTIP,
+ _NET_WM_WINDOW_TYPE_NOTIFICATION,
+ _NET_WM_WINDOW_TYPE_COMBO,
+ _NET_WM_WINDOW_TYPE_DND,
+ _NET_WM_WINDOW_TYPE_NORMAL,
+ _KDE_NET_WM_WINDOW_TYPE_OVERRIDE,
+
+ _KDE_NET_WM_FRAME_STRUT,
+ _NET_FRAME_EXTENTS,
+
+ _NET_STARTUP_INFO,
+ _NET_STARTUP_INFO_BEGIN,
+
+ _NET_SUPPORTING_WM_CHECK,
+
+ _NET_WM_CM_S0,
+
+ _NET_SYSTEM_TRAY_VISUAL,
+
+ _NET_ACTIVE_WINDOW,
+
+ // Property formats
+ TEXT,
+ UTF8_STRING,
+ CARDINAL,
+
+ // Xdnd
+ XdndEnter,
+ XdndPosition,
+ XdndStatus,
+ XdndLeave,
+ XdndDrop,
+ XdndFinished,
+ XdndTypelist,
+ XdndActionList,
+
+ XdndSelection,
+
+ XdndAware,
+ XdndProxy,
+
+ XdndActionCopy,
+ XdndActionLink,
+ XdndActionMove,
+ XdndActionPrivate,
+
+ // Xkb
+ _XKB_RULES_NAMES,
+
+ // XEMBED
+ _XEMBED,
+ _XEMBED_INFO,
+
+ // XInput2
+ ButtonLeft,
+ ButtonMiddle,
+ ButtonRight,
+ ButtonWheelUp,
+ ButtonWheelDown,
+ ButtonHorizWheelLeft,
+ ButtonHorizWheelRight,
+ AbsMTPositionX,
+ AbsMTPositionY,
+ AbsMTTouchMajor,
+ AbsMTTouchMinor,
+ AbsMTOrientation,
+ AbsMTPressure,
+ AbsMTTrackingID,
+ MaxContacts,
+ RelX,
+ RelY,
+ // XInput2 tablet
+ AbsX,
+ AbsY,
+ AbsPressure,
+ AbsTiltX,
+ AbsTiltY,
+ AbsWheel,
+ AbsDistance,
+ WacomSerialIDs,
+ INTEGER,
+ RelHorizWheel,
+ RelVertWheel,
+ RelHorizScroll,
+ RelVertScroll,
+
+ _XSETTINGS_SETTINGS,
+
+ _COMPIZ_DECOR_PENDING,
+ _COMPIZ_DECOR_REQUEST,
+ _COMPIZ_DECOR_DELETE_PIXMAP,
+ _COMPIZ_TOOLKIT_ACTION,
+ _GTK_LOAD_ICONTHEMES,
+
+ AT_SPI_BUS,
+
+ EDID,
+ EDID_DATA,
+ XFree86_DDC_EDID1_RAWDATA,
+
+ NAtoms
+ };
+
+ QXcbAtom();
+ void initialize(xcb_connection_t *connection);
+
+ inline xcb_atom_t atom(QXcbAtom::Atom atom) const { return m_allAtoms[atom]; }
+ QXcbAtom::Atom qatom(xcb_atom_t atom) const;
+
+protected:
+ void initializeAllAtoms(xcb_connection_t *connection);
+
+private:
+ xcb_atom_t m_allAtoms[QXcbAtom::NAtoms];
+};
+
+#endif // QXCBATOM_H
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
index 8ae9d9899e..c8c806749f 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
@@ -45,6 +45,16 @@
#include <xcb/shm.h>
#include <xcb/xcb_image.h>
+#if QT_CONFIG(xcb_render)
+#include <xcb/render.h>
+// 'template' is used as a function argument name in xcb_renderutil.h
+#define template template_param
+// extern "C" is missing too
+extern "C" {
+#include <xcb/xcb_renderutil.h>
+}
+#undef template
+#endif
#include <sys/ipc.h>
#include <sys/shm.h>
@@ -76,6 +86,7 @@ class QXcbBackingStoreImage : public QXcbObject
{
public:
QXcbBackingStoreImage(QXcbBackingStore *backingStore, const QSize &size);
+ QXcbBackingStoreImage(QXcbBackingStore *backingStore, const QSize &size, uint depth, QImage::Format format);
~QXcbBackingStoreImage() { destroy(true); }
void resize(const QSize &size);
@@ -95,10 +106,12 @@ public:
void put(xcb_drawable_t dst, const QRegion &region, const QPoint &offset);
void preparePaint(const QRegion &region);
- static bool createSystemVShmSegment(QXcbConnection *c, size_t segmentSize = 1,
+ static bool createSystemVShmSegment(xcb_connection_t *c, size_t segmentSize = 1,
xcb_shm_segment_info_t *shm_info = nullptr);
private:
+ void init(const QSize &size, uint depth, QImage::Format format);
+
void createShmSegment(size_t segmentSize);
void destroyShmSegment();
void destroy(bool destroyShm);
@@ -109,8 +122,8 @@ private:
void setClip(const QRegion &region);
xcb_shm_segment_info_t m_shm_info;
- QXcbBackingStore *m_backingStore = nullptr;
size_t m_segmentSize = 0;
+ QXcbBackingStore *m_backingStore = nullptr;
xcb_image_t *m_xcb_image = nullptr;
@@ -185,10 +198,23 @@ QXcbBackingStoreImage::QXcbBackingStoreImage(QXcbBackingStore *backingStore, con
, m_backingStore(backingStore)
{
auto window = static_cast<QXcbWindow *>(m_backingStore->window()->handle());
- m_xcb_format = connection()->formatForDepth(window->depth());
+ init(size, window->depth(), window->imageFormat());
+}
+
+QXcbBackingStoreImage::QXcbBackingStoreImage(QXcbBackingStore *backingStore, const QSize &size,
+ uint depth, QImage::Format format)
+ : QXcbObject(backingStore->connection())
+ , m_backingStore(backingStore)
+{
+ init(size, depth, format);
+}
+
+void QXcbBackingStoreImage::init(const QSize &size, uint depth, QImage::Format format)
+{
+ m_xcb_format = connection()->formatForDepth(depth);
Q_ASSERT(m_xcb_format);
- m_qimage_format = window->imageFormat();
+ m_qimage_format = format;
m_hasAlpha = QImage::toPixelFormat(m_qimage_format).alphaUsage() == QPixelFormat::UsesAlpha;
if (!m_hasAlpha)
m_qimage_format = qt_maybeAlphaVersionWithSameDepth(m_qimage_format);
@@ -380,12 +406,12 @@ void QXcbBackingStoreImage::createShmSegment(size_t segmentSize)
} else
#endif
{
- if (createSystemVShmSegment(connection(), segmentSize, &m_shm_info))
+ if (createSystemVShmSegment(xcb_connection(), segmentSize, &m_shm_info))
m_segmentSize = segmentSize;
}
}
-bool QXcbBackingStoreImage::createSystemVShmSegment(QXcbConnection *c, size_t segmentSize,
+bool QXcbBackingStoreImage::createSystemVShmSegment(xcb_connection_t *c, size_t segmentSize,
xcb_shm_segment_info_t *shmInfo)
{
const int id = shmget(IPC_PRIVATE, segmentSize, IPC_CREAT | 0600);
@@ -403,17 +429,17 @@ bool QXcbBackingStoreImage::createSystemVShmSegment(QXcbConnection *c, size_t se
if (shmctl(id, IPC_RMID, 0) == -1)
qCWarning(lcQpaXcb, "Error while marking the shared memory segment to be destroyed");
- const auto seg = xcb_generate_id(c->xcb_connection());
- auto cookie = xcb_shm_attach_checked(c->xcb_connection(), seg, id, false);
- auto *error = xcb_request_check(c->xcb_connection(), cookie);
+ const auto seg = xcb_generate_id(c);
+ auto cookie = xcb_shm_attach_checked(c, seg, id, false);
+ auto *error = xcb_request_check(c, cookie);
if (error) {
- c->printXcbError("xcb_shm_attach() failed with error", error);
+ qCWarning(lcQpaXcb(), "xcb_shm_attach() failed");
free(error);
if (shmdt(addr) == -1)
qCWarning(lcQpaXcb, "shmdt() failed (%d: %s) for %p", errno, strerror(errno), addr);
return false;
} else if (!shmInfo) { // this was a test run, free the allocated test segment
- xcb_shm_detach(c->xcb_connection(), seg);
+ xcb_shm_detach(c, seg);
auto shmaddr = static_cast<quint8 *>(addr);
if (shmdt(shmaddr) == -1)
qCWarning(lcQpaXcb, "shmdt() failed (%d: %s) for %p", errno, strerror(errno), shmaddr);
@@ -740,7 +766,7 @@ void QXcbBackingStoreImage::preparePaint(const QRegion &region)
m_pendingFlush |= region;
}
-bool QXcbBackingStore::createSystemVShmSegment(QXcbConnection *c, size_t segmentSize, void *shmInfo)
+bool QXcbBackingStore::createSystemVShmSegment(xcb_connection_t *c, size_t segmentSize, void *shmInfo)
{
auto info = reinterpret_cast<xcb_shm_segment_info_t *>(shmInfo);
return QXcbBackingStoreImage::createSystemVShmSegment(c, segmentSize, info);
@@ -843,7 +869,7 @@ void QXcbBackingStore::flush(QWindow *window, const QRegion &region, const QPoin
return;
}
- m_image->put(platformWindow->xcb_window(), clipped, offset);
+ render(platformWindow->xcb_window(), clipped, offset);
if (platformWindow->needsSync())
platformWindow->updateSyncRequestCounter();
@@ -851,6 +877,11 @@ void QXcbBackingStore::flush(QWindow *window, const QRegion &region, const QPoin
xcb_flush(xcb_connection());
}
+void QXcbBackingStore::render(xcb_window_t window, const QRegion &region, const QPoint &offset)
+{
+ m_image->put(window, region, offset);
+}
+
#ifndef QT_NO_OPENGL
void QXcbBackingStore::composeAndFlush(QWindow *window, const QRegion &region, const QPoint &offset,
QPlatformTextureList *textures,
@@ -884,6 +915,11 @@ void QXcbBackingStore::resize(const QSize &size, const QRegion &)
}
QXcbWindow* win = static_cast<QXcbWindow *>(pw);
+ recreateImage(win, size);
+}
+
+void QXcbBackingStore::recreateImage(QXcbWindow *win, const QSize &size)
+{
if (m_image)
m_image->resize(size);
else
@@ -904,4 +940,167 @@ bool QXcbBackingStore::scroll(const QRegion &area, int dx, int dy)
return false;
}
+QXcbSystemTrayBackingStore::QXcbSystemTrayBackingStore(QWindow *window)
+ : QXcbBackingStore(window)
+{
+ // We need three different behaviors depending on whether the X11 visual
+ // for the system tray supports an alpha channel, i.e. is 32 bits, and
+ // whether XRender can be used:
+ // 1) if the visual has an alpha channel, then render the window's buffer
+ // directly to the X11 window as usual
+ // 2) else if XRender can be used, then render the window's buffer to Pixmap,
+ // then render Pixmap's contents to the cleared X11 window with
+ // xcb_render_composite()
+ // 3) else grab the X11 window's content and paint it first each time as a
+ // background before rendering the window's buffer to the X11 window
+
+ auto *platformWindow = static_cast<QXcbWindow *>(window->handle());
+ quint8 depth = connection()->primaryScreen()->depthOfVisual(platformWindow->visualId());
+
+ if (depth != 32) {
+ platformWindow->setParentRelativeBackPixmap();
+#if QT_CONFIG(xcb_render)
+ initXRenderMode();
+#endif
+ m_useGrabbedBackgound = !m_usingXRenderMode;
+ }
+}
+
+QXcbSystemTrayBackingStore::~QXcbSystemTrayBackingStore()
+{
+#if QT_CONFIG(xcb_render)
+ if (m_xrenderPicture) {
+ xcb_render_free_picture(xcb_connection(), m_xrenderPicture);
+ m_xrenderPicture = XCB_NONE;
+ }
+ if (m_xrenderPixmap) {
+ xcb_free_pixmap(xcb_connection(), m_xrenderPixmap);
+ m_xrenderPixmap = XCB_NONE;
+ }
+ if (m_windowPicture) {
+ xcb_render_free_picture(xcb_connection(), m_windowPicture);
+ m_windowPicture = XCB_NONE;
+ }
+#endif // QT_CONFIG(xcb_render)
+}
+
+void QXcbSystemTrayBackingStore::beginPaint(const QRegion &region)
+{
+ QXcbBackingStore::beginPaint(region);
+
+ if (m_useGrabbedBackgound) {
+ QPainter p(paintDevice());
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ for (const QRect &rect: region)
+ p.drawPixmap(rect, m_grabbedBackground, rect);
+ }
+}
+
+void QXcbSystemTrayBackingStore::render(xcb_window_t window, const QRegion &region, const QPoint &offset)
+{
+ if (!m_usingXRenderMode) {
+ QXcbBackingStore::render(window, region, offset);
+ return;
+ }
+
+#if QT_CONFIG(xcb_render)
+ m_image->put(m_xrenderPixmap, region, offset);
+ const QRect bounds = region.boundingRect();
+ const QPoint target = bounds.topLeft();
+ const QRect source = bounds.translated(offset);
+ xcb_clear_area(xcb_connection(), false, window,
+ target.x(), target.y(), source.width(), source.height());
+ xcb_render_composite(xcb_connection(), XCB_RENDER_PICT_OP_OVER,
+ m_xrenderPicture, 0, m_windowPicture,
+ target.x(), target.y(), 0, 0, target.x(), target.y(),
+ source.width(), source.height());
+#endif // QT_CONFIG(xcb_render)
+}
+
+void QXcbSystemTrayBackingStore::recreateImage(QXcbWindow *win, const QSize &size)
+{
+ if (!m_usingXRenderMode) {
+ QXcbBackingStore::recreateImage(win, size);
+
+ if (m_useGrabbedBackgound) {
+ xcb_clear_area(xcb_connection(), false, win->xcb_window(),
+ 0, 0, size.width(), size.height());
+ m_grabbedBackground = win->xcbScreen()->grabWindow(win->winId(), 0, 0,
+ size.width(), size.height());
+ }
+ return;
+ }
+
+#if QT_CONFIG(xcb_render)
+ if (m_xrenderPicture) {
+ xcb_render_free_picture(xcb_connection(), m_xrenderPicture);
+ m_xrenderPicture = XCB_NONE;
+ }
+ if (m_xrenderPixmap) {
+ xcb_free_pixmap(xcb_connection(), m_xrenderPixmap);
+ m_xrenderPixmap = XCB_NONE;
+ }
+
+ QXcbScreen *screen = win->xcbScreen();
+
+ m_xrenderPixmap = xcb_generate_id(xcb_connection());
+ xcb_create_pixmap(xcb_connection(), 32, m_xrenderPixmap, screen->root(), size.width(), size.height());
+
+ m_xrenderPicture = xcb_generate_id(xcb_connection());
+ xcb_render_create_picture(xcb_connection(), m_xrenderPicture, m_xrenderPixmap, m_xrenderPictFormat, 0, 0);
+
+ // XRender expects premultiplied alpha
+ if (m_image)
+ m_image->resize(size);
+ else
+ m_image = new QXcbBackingStoreImage(this, size, 32, QImage::Format_ARGB32_Premultiplied);
+#endif // QT_CONFIG(xcb_render)
+}
+
+#if QT_CONFIG(xcb_render)
+void QXcbSystemTrayBackingStore::initXRenderMode()
+{
+ if (!connection()->hasXRender())
+ return;
+
+ xcb_connection_t *conn = xcb_connection();
+ auto formatsReply = Q_XCB_REPLY(xcb_render_query_pict_formats, conn);
+
+ if (!formatsReply) {
+ qWarning("QXcbSystemTrayBackingStore: xcb_render_query_pict_formats() failed");
+ return;
+ }
+
+ xcb_render_pictforminfo_t *fmt = xcb_render_util_find_standard_format(formatsReply.get(),
+ XCB_PICT_STANDARD_ARGB_32);
+ if (!fmt) {
+ qWarning("QXcbSystemTrayBackingStore: Failed to find format PICT_STANDARD_ARGB_32");
+ return;
+ }
+
+ m_xrenderPictFormat = fmt->id;
+
+ auto *platformWindow = static_cast<QXcbWindow *>(window()->handle());
+ xcb_render_pictvisual_t *vfmt = xcb_render_util_find_visual_format(formatsReply.get(), platformWindow->visualId());
+
+ if (!vfmt) {
+ qWarning("QXcbSystemTrayBackingStore: Failed to find format for visual %x", platformWindow->visualId());
+ return;
+ }
+
+ m_windowPicture = xcb_generate_id(conn);
+ xcb_void_cookie_t cookie =
+ xcb_render_create_picture_checked(conn, m_windowPicture, platformWindow->xcb_window(), vfmt->format, 0, 0);
+ xcb_generic_error_t *error = xcb_request_check(conn, cookie);
+ if (error) {
+ qWarning("QXcbSystemTrayBackingStore: Failed to create Picture with format %x for window %x, error code %d",
+ vfmt->format, platformWindow->xcb_window(), error->error_code);
+ free(error);
+ return;
+ }
+
+ m_usingXRenderMode = true;
+}
+#endif // QT_CONFIG(xcb_render)
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.h b/src/plugins/platforms/xcb/qxcbbackingstore.h
index 734de1f7d7..b91e5c7dc2 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.h
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.h
@@ -74,15 +74,44 @@ public:
void beginPaint(const QRegion &) override;
void endPaint() override;
- static bool createSystemVShmSegment(QXcbConnection *c, size_t segmentSize = 1,
+ static bool createSystemVShmSegment(xcb_connection_t *c, size_t segmentSize = 1,
void *shmInfo = nullptr);
-private:
+protected:
+ virtual void render(xcb_window_t window, const QRegion &region, const QPoint &offset);
+ virtual void recreateImage(QXcbWindow *win, const QSize &size);
+
QXcbBackingStoreImage *m_image = nullptr;
QStack<QRegion> m_paintRegions;
QImage m_rgbImage;
};
+class QXcbSystemTrayBackingStore : public QXcbBackingStore
+{
+public:
+ QXcbSystemTrayBackingStore(QWindow *window);
+ ~QXcbSystemTrayBackingStore();
+
+ void beginPaint(const QRegion &) override;
+
+protected:
+ void render(xcb_window_t window, const QRegion &region, const QPoint &offset) override;
+ void recreateImage(QXcbWindow *win, const QSize &size) override;
+
+private:
+#if QT_CONFIG(xcb_render)
+ void initXRenderMode();
+
+ xcb_pixmap_t m_xrenderPixmap = XCB_NONE;
+ xcb_render_picture_t m_xrenderPicture = XCB_NONE;
+ xcb_render_pictformat_t m_xrenderPictFormat = XCB_NONE;
+ xcb_render_picture_t m_windowPicture = XCB_NONE;
+#endif
+ bool m_usingXRenderMode = false;
+ bool m_useGrabbedBackgound = false;
+ QPixmap m_grabbedBackground;
+};
+
QT_END_NAMESPACE
#endif
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp
index b091928e8c..3fd14a659e 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp
@@ -42,16 +42,13 @@
#include "qxcbconnection.h"
#include "qxcbscreen.h"
#include "qxcbmime.h"
+#include "qxcbwindow.h"
#include <private/qguiapplication_p.h>
#include <QElapsedTimer>
#include <QtCore/QDebug>
-#define class class_name // Workaround XCB-ICCCM 3.8 breakage
-#include <xcb/xcb_icccm.h>
-#undef class
-
QT_BEGIN_NAMESPACE
#ifndef QT_NO_CLIPBOARD
@@ -156,6 +153,7 @@ private:
QByteArray format_atoms;
};
+namespace {
class INCRTransaction;
typedef QMap<xcb_window_t,INCRTransaction*> TransactionMap;
static TransactionMap *transactions = 0;
@@ -262,6 +260,7 @@ private:
uint offset;
int abort_timer;
};
+} // unnamed namespace
const int QXcbClipboard::clipboard_timeout = 5000;
@@ -276,18 +275,6 @@ QXcbClipboard::QXcbClipboard(QXcbConnection *c)
m_timestamp[QClipboard::Selection] = XCB_CURRENT_TIME;
m_owner = connection()->getQtSelectionOwner();
-#ifndef QT_NO_DEBUG
- QByteArray ba("Qt clipboard window");
- xcb_change_property(xcb_connection(),
- XCB_PROP_MODE_REPLACE,
- m_owner,
- atom(QXcbAtom::_NET_WM_NAME),
- atom(QXcbAtom::UTF8_STRING),
- 8,
- ba.length(),
- ba.constData());
-#endif
-
if (connection()->hasXFixes()) {
const uint32_t mask = XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER |
XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY |
@@ -314,7 +301,7 @@ QXcbClipboard::~QXcbClipboard()
connection()->sync();
// waiting until the clipboard manager fetches the content.
- if (!waitForClipboardEvent(m_owner, XCB_SELECTION_NOTIFY, clipboard_timeout, true)) {
+ if (!waitForClipboardEvent(m_owner, XCB_SELECTION_NOTIFY, true)) {
qWarning("QXcbClipboard: Unable to receive an event from the "
"clipboard manager in a reasonable time");
}
@@ -467,17 +454,9 @@ xcb_window_t QXcbClipboard::requestor() const
platformScreen->screen()->root_visual, // visual
0, // value mask
0); // value list
-#ifndef QT_NO_DEBUG
- QByteArray ba("Qt clipboard requestor window");
- xcb_change_property(xcb_connection(),
- XCB_PROP_MODE_REPLACE,
- window,
- atom(QXcbAtom::_NET_WM_NAME),
- atom(QXcbAtom::UTF8_STRING),
- 8,
- ba.length(),
- ba.constData());
-#endif
+
+ QXcbWindow::setWindowTitle(connection(), window,
+ QStringLiteral("Qt Clipboard Requestor Window"));
uint32_t mask = XCB_EVENT_MASK_PROPERTY_CHANGE;
xcb_change_window_attributes(xcb_connection(), window, XCB_CW_EVENT_MASK, &mask);
@@ -600,7 +579,7 @@ void QXcbClipboard::handleSelectionRequest(xcb_selection_request_event_t *req)
return;
}
- Q_DECLARE_XCB_EVENT(event, xcb_selection_notify_event_t);
+ q_padded_xcb_event<xcb_selection_notify_event_t> event = {};
event.response_type = XCB_SELECTION_NOTIFY;
event.requestor = req->requestor;
event.selection = req->selection;
@@ -824,73 +803,44 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property,
return ok;
}
-
-namespace
+xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t window, int type, bool checkManager)
{
- class Notify {
- public:
- Notify(xcb_window_t win, int t)
- : window(win), type(t) {}
- xcb_window_t window;
- int type;
- bool checkEvent(xcb_generic_event_t *event) const {
- if (!event)
- return false;
- int t = event->response_type & 0x7f;
- if (t != type)
+ QElapsedTimer timer;
+ timer.start();
+ QXcbEventQueue *queue = connection()->eventQueue();
+ do {
+ auto e = queue->peek([window, type](xcb_generic_event_t *event, int eventType) {
+ if (eventType != type)
return false;
- if (t == XCB_PROPERTY_NOTIFY) {
- xcb_property_notify_event_t *pn = (xcb_property_notify_event_t *)event;
- if (pn->window == window)
- return true;
- } else if (t == XCB_SELECTION_NOTIFY) {
- xcb_selection_notify_event_t *sn = (xcb_selection_notify_event_t *)event;
- if (sn->requestor == window)
- return true;
+ if (eventType == XCB_PROPERTY_NOTIFY) {
+ auto propertyNotify = reinterpret_cast<xcb_property_notify_event_t *>(event);
+ return propertyNotify->window == window;
}
- return false;
- }
- };
- class ClipboardEvent {
- public:
- ClipboardEvent(QXcbConnection *c)
- { clipboard = c->internAtom("CLIPBOARD"); }
- xcb_atom_t clipboard;
- bool checkEvent(xcb_generic_event_t *e) const {
- if (!e)
- return false;
- int type = e->response_type & 0x7f;
- if (type == XCB_SELECTION_REQUEST) {
- xcb_selection_request_event_t *sr = (xcb_selection_request_event_t *)e;
- return sr->selection == XCB_ATOM_PRIMARY || sr->selection == clipboard;
- } else if (type == XCB_SELECTION_CLEAR) {
- xcb_selection_clear_event_t *sc = (xcb_selection_clear_event_t *)e;
- return sc->selection == XCB_ATOM_PRIMARY || sc->selection == clipboard;
+ if (eventType == XCB_SELECTION_NOTIFY) {
+ auto selectionNotify = reinterpret_cast<xcb_selection_notify_event_t *>(event);
+ return selectionNotify->requestor == window;
}
return false;
- }
- };
-}
-
-xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t win, int type, int timeout, bool checkManager)
-{
- QElapsedTimer timer;
- timer.start();
- do {
- Notify notify(win, type);
- xcb_generic_event_t *e = connection()->checkEvent(notify);
- if (e)
+ });
+ if (e) // found the waited for event
return e;
if (checkManager) {
auto reply = Q_XCB_REPLY(xcb_get_selection_owner, xcb_connection(), atom(QXcbAtom::CLIPBOARD_MANAGER));
if (!reply || reply->owner == XCB_NONE)
- return 0;
+ return nullptr;
}
// process other clipboard events, since someone is probably requesting data from us
- ClipboardEvent clipboard(connection());
- e = connection()->checkEvent(clipboard);
+ auto clipboardAtom = atom(QXcbAtom::CLIPBOARD);
+ e = queue->peek([clipboardAtom](xcb_generic_event_t *event, int type) {
+ xcb_atom_t selection = XCB_ATOM_NONE;
+ if (type == XCB_SELECTION_REQUEST)
+ selection = reinterpret_cast<xcb_selection_request_event_t *>(event)->selection;
+ else if (type == XCB_SELECTION_CLEAR)
+ selection = reinterpret_cast<xcb_selection_clear_event_t *>(event)->selection;
+ return selection == XCB_ATOM_PRIMARY || selection == clipboardAtom;
+ });
if (e) {
connection()->handleXcbEvent(e);
free(e);
@@ -900,9 +850,9 @@ xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t win, int
// sleep 50 ms, so we don't use up CPU cycles all the time.
QThread::msleep(50);
- } while (timer.elapsed() < timeout);
+ } while (timer.elapsed() < clipboard_timeout);
- return 0;
+ return nullptr;
}
QByteArray QXcbClipboard::clipboardReadIncrementalProperty(xcb_window_t win, xcb_atom_t property, int nbytes, bool nullterm)
@@ -924,7 +874,7 @@ QByteArray QXcbClipboard::clipboardReadIncrementalProperty(xcb_window_t win, xcb
for (;;) {
connection()->flush();
- xcb_generic_event_t *ge = waitForClipboardEvent(win, XCB_PROPERTY_NOTIFY, clipboard_timeout);
+ xcb_generic_event_t *ge = waitForClipboardEvent(win, XCB_PROPERTY_NOTIFY);
if (!ge)
break;
xcb_property_notify_event_t *event = (xcb_property_notify_event_t *)ge;
@@ -987,7 +937,7 @@ QByteArray QXcbClipboard::getSelection(xcb_atom_t selection, xcb_atom_t target,
connection()->sync();
- xcb_generic_event_t *ge = waitForClipboardEvent(win, XCB_SELECTION_NOTIFY, clipboard_timeout);
+ xcb_generic_event_t *ge = waitForClipboardEvent(win, XCB_SELECTION_NOTIFY);
bool no_selection = !ge || ((xcb_selection_notify_event_t *)ge)->property == XCB_NONE;
free(ge);
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.h b/src/plugins/platforms/xcb/qxcbclipboard.h
index bfeae13e10..abab42a613 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.h
+++ b/src/plugins/platforms/xcb/qxcbclipboard.h
@@ -89,7 +89,7 @@ public:
QByteArray getSelection(xcb_atom_t selection, xcb_atom_t target, xcb_atom_t property, xcb_timestamp_t t = 0);
private:
- xcb_generic_event_t *waitForClipboardEvent(xcb_window_t win, int type, int timeout, bool checkManager = false);
+ xcb_generic_event_t *waitForClipboardEvent(xcb_window_t window, int type, bool checkManager = false);
xcb_atom_t sendTargetsSelection(QMimeData *d, xcb_window_t window, xcb_atom_t property);
xcb_atom_t sendSelection(QMimeData *d, xcb_atom_t target, xcb_window_t window, xcb_atom_t property);
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index aca2c347ea..45f096a13a 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -38,12 +38,10 @@
****************************************************************************/
#include <QtGui/private/qguiapplication_p.h>
-#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtCore/QDebug>
#include "qxcbconnection.h"
#include "qxcbkeyboard.h"
-#include "qxcbscreen.h"
#include "qxcbwindow.h"
#include "qxcbclipboard.h"
#if QT_CONFIG(draganddrop)
@@ -55,57 +53,25 @@
#include "qxcbsystemtraytracker.h"
#include "qxcbglintegrationfactory.h"
#include "qxcbglintegration.h"
+#include "qxcbcursor.h"
#include "qxcbbackingstore.h"
+#include "qxcbeventqueue.h"
-#include <QSocketNotifier>
#include <QAbstractEventDispatcher>
-#include <QTimer>
#include <QByteArray>
#include <QScopedPointer>
-#include <algorithm>
-
#include <stdio.h>
#include <errno.h>
-#include <xcb/shm.h>
-#include <xcb/sync.h>
-#include <xcb/xfixes.h>
-#include <xcb/xinerama.h>
-
-#if QT_CONFIG(xcb_xlib)
-#define register /* C++17 deprecated register */
-#include <X11/Xlib.h>
-#include <X11/Xlib-xcb.h>
-#include <X11/Xlibint.h>
-#include <X11/Xutil.h>
-#undef register
-#endif
-
-#if QT_CONFIG(xinput2)
-#include <X11/extensions/XI2proto.h>
-#endif
-
-#if QT_CONFIG(xcb_render)
-#include <xcb/render.h>
-#endif
-
-#if defined(Q_CC_GNU) && defined(Q_OF_ELF)
-static xcb_generic_event_t *local_xcb_poll_for_queued_event(xcb_connection_t *c)
- __attribute__((weakref("xcb_poll_for_queued_event")));
-static inline void checkXcbPollForQueuedEvent()
-{ }
-#else
-#include <dlfcn.h>
-typedef xcb_generic_event_t * (*XcbPollForQueuedEventFunctionPointer)(xcb_connection_t *c);
-static XcbPollForQueuedEventFunctionPointer local_xcb_poll_for_queued_event;
-
-static inline void checkXcbPollForQueuedEvent()
-{
-#ifdef RTLD_DEFAULT
- local_xcb_poll_for_queued_event = (XcbPollForQueuedEventFunctionPointer)dlsym(RTLD_DEFAULT, "xcb_poll_for_queued_event");
+#include <xcb/xfixes.h>
+#if QT_CONFIG(xkb)
+#define explicit dont_use_cxx_explicit
+#include <xcb/xkb.h>
+#undef explicit
#endif
-}
+#if QT_CONFIG(xcb_xinput)
+#include <xcb/xinput.h>
#endif
QT_BEGIN_NAMESPACE
@@ -115,9 +81,10 @@ Q_LOGGING_CATEGORY(lcQpaXInputDevices, "qt.qpa.input.devices")
Q_LOGGING_CATEGORY(lcQpaXInputEvents, "qt.qpa.input.events")
Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.screen")
Q_LOGGING_CATEGORY(lcQpaEvents, "qt.qpa.events")
-Q_LOGGING_CATEGORY(lcQpaXcb, "qt.qpa.xcb") // for general (uncategorized) XCB logging
+Q_LOGGING_CATEGORY(lcQpaEventReader, "qt.qpa.events.reader")
Q_LOGGING_CATEGORY(lcQpaPeeker, "qt.qpa.peeker")
Q_LOGGING_CATEGORY(lcQpaKeyboard, "qt.qpa.xkeyboard")
+Q_LOGGING_CATEGORY(lcQpaXDnd, "qt.qpa.xdnd")
// this event type was added in libxcb 1.10,
// but we support also older version
@@ -125,487 +92,30 @@ Q_LOGGING_CATEGORY(lcQpaKeyboard, "qt.qpa.xkeyboard")
#define XCB_GE_GENERIC 35
#endif
-#if QT_CONFIG(xinput2)
-// Starting from the xcb version 1.9.3 struct xcb_ge_event_t has changed:
-// - "pad0" became "extension"
-// - "pad1" and "pad" became "pad0"
-// New and old version of this struct share the following fields:
-typedef struct qt_xcb_ge_event_t {
- uint8_t response_type;
- uint8_t extension;
- uint16_t sequence;
- uint32_t length;
- uint16_t event_type;
-} qt_xcb_ge_event_t;
-
-static inline bool isXIEvent(xcb_generic_event_t *event, int opCode)
-{
- qt_xcb_ge_event_t *e = reinterpret_cast<qt_xcb_ge_event_t *>(event);
- return e->extension == opCode;
-}
-#endif // QT_CONFIG(xinput2)
-
-#if QT_CONFIG(xcb_xlib)
-static const char * const xcbConnectionErrors[] = {
- "No error", /* Error 0 */
- "I/O error", /* XCB_CONN_ERROR */
- "Unsupported extension used", /* XCB_CONN_CLOSED_EXT_NOTSUPPORTED */
- "Out of memory", /* XCB_CONN_CLOSED_MEM_INSUFFICIENT */
- "Maximum allowed requested length exceeded", /* XCB_CONN_CLOSED_REQ_LEN_EXCEED */
- "Failed to parse display string", /* XCB_CONN_CLOSED_PARSE_ERR */
- "No such screen on display", /* XCB_CONN_CLOSED_INVALID_SCREEN */
- "Error during FD passing" /* XCB_CONN_CLOSED_FDPASSING_FAILED */
-};
-
-static int nullErrorHandler(Display *dpy, XErrorEvent *err)
-{
-#ifndef Q_XCB_DEBUG
- Q_UNUSED(dpy);
- Q_UNUSED(err);
-#else
- const int buflen = 1024;
- char buf[buflen];
-
- XGetErrorText(dpy, err->error_code, buf, buflen);
- fprintf(stderr, "X Error: serial %lu error %d %s\n", err->serial, (int) err->error_code, buf);
-#endif
- return 0;
-}
-
-static int ioErrorHandler(Display *dpy)
-{
- xcb_connection_t *conn = XGetXCBConnection(dpy);
- if (conn != NULL) {
- /* Print a message with a textual description of the error */
- int code = xcb_connection_has_error(conn);
- const char *str = "Unknown error";
- int arrayLength = sizeof(xcbConnectionErrors) / sizeof(xcbConnectionErrors[0]);
- if (code >= 0 && code < arrayLength)
- str = xcbConnectionErrors[code];
-
- qWarning("The X11 connection broke: %s (code %d)", str, code);
- }
- return _XDefaultIOError(dpy);
-}
-#endif
-
-QXcbScreen* QXcbConnection::findScreenForCrtc(xcb_window_t rootWindow, xcb_randr_crtc_t crtc) const
-{
- for (QXcbScreen *screen : m_screens) {
- if (screen->root() == rootWindow && screen->crtc() == crtc)
- return screen;
- }
-
- return 0;
-}
-
-QXcbScreen* QXcbConnection::findScreenForOutput(xcb_window_t rootWindow, xcb_randr_output_t output) const
-{
- for (QXcbScreen *screen : m_screens) {
- if (screen->root() == rootWindow && screen->output() == output)
- return screen;
- }
-
- return 0;
-}
-
-QXcbVirtualDesktop* QXcbConnection::virtualDesktopForRootWindow(xcb_window_t rootWindow) const
-{
- for (QXcbVirtualDesktop *virtualDesktop : m_virtualDesktops) {
- if (virtualDesktop->screen()->root == rootWindow)
- return virtualDesktop;
- }
-
- return 0;
-}
-
-/*!
- \brief Synchronizes the screen list, adds new screens, removes deleted ones
-*/
-void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
-{
- if (event->subCode == XCB_RANDR_NOTIFY_CRTC_CHANGE) {
- xcb_randr_crtc_change_t crtc = event->u.cc;
- QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(crtc.window);
- if (!virtualDesktop)
- // Not for us
- return;
-
- QXcbScreen *screen = findScreenForCrtc(crtc.window, crtc.crtc);
- qCDebug(lcQpaScreen) << "QXcbConnection: XCB_RANDR_NOTIFY_CRTC_CHANGE:" << crtc.crtc
- << "mode" << crtc.mode << "relevant screen" << screen;
- // Only update geometry when there's a valid mode on the CRTC
- // CRTC with node mode could mean that output has been disabled, and we'll
- // get RRNotifyOutputChange notification for that.
- if (screen && crtc.mode) {
- if (crtc.rotation == XCB_RANDR_ROTATION_ROTATE_90 ||
- crtc.rotation == XCB_RANDR_ROTATION_ROTATE_270)
- std::swap(crtc.width, crtc.height);
- screen->updateGeometry(QRect(crtc.x, crtc.y, crtc.width, crtc.height), crtc.rotation);
- if (screen->mode() != crtc.mode)
- screen->updateRefreshRate(crtc.mode);
- }
-
- } else if (event->subCode == XCB_RANDR_NOTIFY_OUTPUT_CHANGE) {
- xcb_randr_output_change_t output = event->u.oc;
- QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(output.window);
- if (!virtualDesktop)
- // Not for us
- return;
-
- QXcbScreen *screen = findScreenForOutput(output.window, output.output);
- qCDebug(lcQpaScreen) << "QXcbConnection: XCB_RANDR_NOTIFY_OUTPUT_CHANGE:" << output.output;
-
- if (screen && output.connection == XCB_RANDR_CONNECTION_DISCONNECTED) {
- qCDebug(lcQpaScreen) << "screen" << screen->name() << "has been disconnected";
- destroyScreen(screen);
- } else if (!screen && output.connection == XCB_RANDR_CONNECTION_CONNECTED) {
- // New XRandR output is available and it's enabled
- if (output.crtc != XCB_NONE && output.mode != XCB_NONE) {
- auto outputInfo = Q_XCB_REPLY(xcb_randr_get_output_info, xcb_connection(),
- output.output, output.config_timestamp);
- // Find a fake screen
- const auto scrs = virtualDesktop->screens();
- for (QPlatformScreen *scr : scrs) {
- QXcbScreen *xcbScreen = static_cast<QXcbScreen *>(scr);
- if (xcbScreen->output() == XCB_NONE) {
- screen = xcbScreen;
- break;
- }
- }
-
- if (screen) {
- QString nameWas = screen->name();
- // Transform the fake screen into a physical screen
- screen->setOutput(output.output, outputInfo.get());
- updateScreen(screen, output);
- qCDebug(lcQpaScreen) << "output" << screen->name()
- << "is connected and enabled; was fake:" << nameWas;
- } else {
- screen = createScreen(virtualDesktop, output, outputInfo.get());
- qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled";
- }
- QHighDpiScaling::updateHighDpiScaling();
- }
- } else if (screen) {
- if (output.crtc == XCB_NONE && output.mode == XCB_NONE) {
- // Screen has been disabled
- auto outputInfo = Q_XCB_REPLY(xcb_randr_get_output_info, xcb_connection(),
- output.output, output.config_timestamp);
- if (outputInfo->crtc == XCB_NONE) {
- qCDebug(lcQpaScreen) << "output" << screen->name() << "has been disabled";
- destroyScreen(screen);
- } else {
- qCDebug(lcQpaScreen) << "output" << screen->name() << "has been temporarily disabled for the mode switch";
- // Reset crtc to skip RRCrtcChangeNotify events,
- // because they may be invalid in the middle of the mode switch
- screen->setCrtc(XCB_NONE);
- }
- } else {
- updateScreen(screen, output);
- qCDebug(lcQpaScreen) << "output has changed" << screen;
- }
- }
-
- qCDebug(lcQpaScreen) << "primary output is" << qAsConst(m_screens).first()->name();
- }
-}
-
-bool QXcbConnection::checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output)
-{
- auto primary = Q_XCB_REPLY(xcb_randr_get_output_primary, xcb_connection(), rootWindow);
- if (!primary)
- qWarning("failed to get the primary output of the screen");
-
- const bool isPrimary = primary ? (primary->output == output) : false;
-
- return isPrimary;
-}
-
-void QXcbConnection::updateScreen(QXcbScreen *screen, const xcb_randr_output_change_t &outputChange)
-{
- screen->setCrtc(outputChange.crtc); // Set the new crtc, because it can be invalid
- screen->updateGeometry(outputChange.config_timestamp);
- if (screen->mode() != outputChange.mode)
- screen->updateRefreshRate(outputChange.mode);
- // Only screen which belongs to the primary virtual desktop can be a primary screen
- if (screen->screenNumber() == m_primaryScreenNumber) {
- if (!screen->isPrimary() && checkOutputIsPrimary(outputChange.window, outputChange.output)) {
- screen->setPrimary(true);
-
- // If the screen became primary, reshuffle the order in QGuiApplicationPrivate
- const int idx = m_screens.indexOf(screen);
- if (idx > 0) {
- qAsConst(m_screens).first()->setPrimary(false);
- m_screens.swap(0, idx);
- }
- screen->virtualDesktop()->setPrimaryScreen(screen);
- QXcbIntegration::instance()->setPrimaryScreen(screen);
- }
- }
-}
-
-QXcbScreen *QXcbConnection::createScreen(QXcbVirtualDesktop *virtualDesktop,
- const xcb_randr_output_change_t &outputChange,
- xcb_randr_get_output_info_reply_t *outputInfo)
-{
- QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, outputChange.output, outputInfo);
- // Only screen which belongs to the primary virtual desktop can be a primary screen
- if (screen->screenNumber() == m_primaryScreenNumber)
- screen->setPrimary(checkOutputIsPrimary(outputChange.window, outputChange.output));
-
- if (screen->isPrimary()) {
- if (!m_screens.isEmpty())
- qAsConst(m_screens).first()->setPrimary(false);
-
- m_screens.prepend(screen);
- } else {
- m_screens.append(screen);
- }
- virtualDesktop->addScreen(screen);
- QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
-
- return screen;
-}
-
-void QXcbConnection::destroyScreen(QXcbScreen *screen)
-{
- QXcbVirtualDesktop *virtualDesktop = screen->virtualDesktop();
- if (virtualDesktop->screens().count() == 1) {
- // If there are no other screens on the same virtual desktop,
- // then transform the physical screen into a fake screen.
- const QString nameWas = screen->name();
- screen->setOutput(XCB_NONE, nullptr);
- qCDebug(lcQpaScreen) << "transformed" << nameWas << "to fake" << screen;
- } else {
- // There is more than one screen on the same virtual desktop, remove the screen
- m_screens.removeOne(screen);
- virtualDesktop->removeScreen(screen);
-
- // When primary screen is removed, set the new primary screen
- // which belongs to the primary virtual desktop.
- if (screen->isPrimary()) {
- QXcbScreen *newPrimary = static_cast<QXcbScreen *>(virtualDesktop->screens().at(0));
- newPrimary->setPrimary(true);
- const int idx = m_screens.indexOf(newPrimary);
- if (idx > 0)
- m_screens.swap(0, idx);
- QXcbIntegration::instance()->setPrimaryScreen(newPrimary);
- }
-
- QXcbIntegration::instance()->destroyScreen(screen);
- }
-}
-
-void QXcbConnection::initializeScreens()
-{
- xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
- int xcbScreenNumber = 0; // screen number in the xcb sense
- QXcbScreen *primaryScreen = nullptr;
- while (it.rem) {
- // Each "screen" in xcb terminology is a virtual desktop,
- // potentially a collection of separate juxtaposed monitors.
- // But we want a separate QScreen for each output (e.g. DVI-I-1, VGA-1, etc.)
- // which will become virtual siblings.
- xcb_screen_t *xcbScreen = it.data;
- QXcbVirtualDesktop *virtualDesktop = new QXcbVirtualDesktop(this, xcbScreen, xcbScreenNumber);
- m_virtualDesktops.append(virtualDesktop);
- QList<QPlatformScreen *> siblings;
- if (has_randr_extension) {
- // RRGetScreenResourcesCurrent is fast but it may return nothing if the
- // configuration is not initialized wrt to the hardware. We should call
- // RRGetScreenResources in this case.
- auto resources_current = Q_XCB_REPLY(xcb_randr_get_screen_resources_current,
- xcb_connection(), xcbScreen->root);
- if (!resources_current) {
- qWarning("failed to get the current screen resources");
- } else {
- xcb_timestamp_t timestamp = 0;
- xcb_randr_output_t *outputs = nullptr;
- int outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources_current.get());
- if (outputCount) {
- timestamp = resources_current->config_timestamp;
- outputs = xcb_randr_get_screen_resources_current_outputs(resources_current.get());
- } else {
- auto resources = Q_XCB_REPLY(xcb_randr_get_screen_resources,
- xcb_connection(), xcbScreen->root);
- if (!resources) {
- qWarning("failed to get the screen resources");
- } else {
- timestamp = resources->config_timestamp;
- outputCount = xcb_randr_get_screen_resources_outputs_length(resources.get());
- outputs = xcb_randr_get_screen_resources_outputs(resources.get());
- }
- }
-
- if (outputCount) {
- auto primary = Q_XCB_REPLY(xcb_randr_get_output_primary, xcb_connection(), xcbScreen->root);
- if (!primary) {
- qWarning("failed to get the primary output of the screen");
- } else {
- for (int i = 0; i < outputCount; i++) {
- auto output = Q_XCB_REPLY_UNCHECKED(xcb_randr_get_output_info,
- xcb_connection(), outputs[i], timestamp);
- // Invalid, disconnected or disabled output
- if (!output)
- continue;
-
- if (output->connection != XCB_RANDR_CONNECTION_CONNECTED) {
- qCDebug(lcQpaScreen, "Output %s is not connected", qPrintable(
- QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.get()),
- xcb_randr_get_output_info_name_length(output.get()))));
- continue;
- }
-
- if (output->crtc == XCB_NONE) {
- qCDebug(lcQpaScreen, "Output %s is not enabled", qPrintable(
- QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.get()),
- xcb_randr_get_output_info_name_length(output.get()))));
- continue;
- }
-
- QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, outputs[i], output.get());
- siblings << screen;
- m_screens << screen;
-
- // There can be multiple outputs per screen, use either
- // the first or an exact match. An exact match isn't
- // always available if primary->output is XCB_NONE
- // or currently disconnected output.
- if (m_primaryScreenNumber == xcbScreenNumber) {
- if (!primaryScreen || (primary && outputs[i] == primary->output)) {
- if (primaryScreen)
- primaryScreen->setPrimary(false);
- primaryScreen = screen;
- primaryScreen->setPrimary(true);
- siblings.prepend(siblings.takeLast());
- }
- }
- }
- }
- }
- }
- } else if (has_xinerama_extension) {
- // Xinerama is available
- auto screens = Q_XCB_REPLY(xcb_xinerama_query_screens, m_connection);
- if (screens) {
- xcb_xinerama_screen_info_iterator_t it = xcb_xinerama_query_screens_screen_info_iterator(screens.get());
- while (it.rem) {
- xcb_xinerama_screen_info_t *screen_info = it.data;
- QXcbScreen *screen = new QXcbScreen(this, virtualDesktop,
- XCB_NONE, nullptr,
- screen_info, it.index);
- siblings << screen;
- m_screens << screen;
- xcb_xinerama_screen_info_next(&it);
- }
- }
- }
- if (siblings.isEmpty()) {
- // If there are no XRandR outputs or XRandR extension is missing,
- // then create a fake/legacy screen.
- QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, XCB_NONE, nullptr);
- qCDebug(lcQpaScreen) << "created fake screen" << screen;
- m_screens << screen;
- if (m_primaryScreenNumber == xcbScreenNumber) {
- primaryScreen = screen;
- primaryScreen->setPrimary(true);
- }
- siblings << screen;
- }
- virtualDesktop->setScreens(siblings);
- xcb_screen_next(&it);
- ++xcbScreenNumber;
- } // for each xcb screen
-
- for (QXcbVirtualDesktop *virtualDesktop : qAsConst(m_virtualDesktops))
- virtualDesktop->subscribeToXFixesSelectionNotify();
-
- if (m_virtualDesktops.isEmpty()) {
- qFatal("QXcbConnection: no screens available");
- } else {
- // Ensure the primary screen is first on the list
- if (primaryScreen) {
- if (qAsConst(m_screens).first() != primaryScreen) {
- m_screens.removeOne(primaryScreen);
- m_screens.prepend(primaryScreen);
- }
- }
-
- // Push the screens to QGuiApplication
- for (QXcbScreen *screen : qAsConst(m_screens)) {
- qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ")";
- QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
- }
-
- qCDebug(lcQpaScreen) << "primary output is" << qAsConst(m_screens).first()->name();
- }
-}
-
QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, xcb_visualid_t defaultVisualId, const char *displayName)
- : m_canGrabServer(canGrabServer)
+ : QXcbBasicConnection(displayName)
+ , m_canGrabServer(canGrabServer)
, m_defaultVisualId(defaultVisualId)
- , m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY"))
, m_nativeInterface(nativeInterface)
{
-#if QT_CONFIG(xcb_xlib)
- Display *dpy = XOpenDisplay(m_displayName.constData());
- if (dpy) {
- m_primaryScreenNumber = DefaultScreen(dpy);
- m_connection = XGetXCBConnection(dpy);
- XSetEventQueueOwner(dpy, XCBOwnsEventQueue);
- XSetErrorHandler(nullErrorHandler);
- XSetIOErrorHandler(ioErrorHandler);
- m_xlib_display = dpy;
- }
-#else
- m_connection = xcb_connect(m_displayName.constData(), &m_primaryScreenNumber);
-#endif // QT_CONFIG(xcb_xlib)
-
- if (Q_UNLIKELY(!m_connection || xcb_connection_has_error(m_connection))) {
- qCWarning(lcQpaScreen, "QXcbConnection: Could not connect to display %s", m_displayName.constData());
+ if (!isConnected())
return;
- }
-
- m_reader = new QXcbEventReader(this);
- m_reader->start();
- xcb_extension_t *extensions[] = {
- &xcb_shm_id, &xcb_xfixes_id, &xcb_randr_id, &xcb_shape_id, &xcb_sync_id,
-#if QT_CONFIG(xkb)
- &xcb_xkb_id,
-#endif
-#if QT_CONFIG(xcb_render)
- &xcb_render_id,
-#endif
- 0
- };
-
- for (xcb_extension_t **ext_it = extensions; *ext_it; ++ext_it)
- xcb_prefetch_extension_data (m_connection, *ext_it);
-
- m_setup = xcb_get_setup(xcb_connection());
+ m_eventQueue = new QXcbEventQueue(this);
m_xdgCurrentDesktop = qgetenv("XDG_CURRENT_DESKTOP").toLower();
- initializeAllAtoms();
+ if (hasXRandr())
+ xrandrSelectEvents();
- if (!qEnvironmentVariableIsSet("QT_XCB_NO_MITSHM"))
- initializeShm();
- if (!qEnvironmentVariableIsSet("QT_XCB_NO_XRANDR"))
- initializeXRandr();
- if (!has_randr_extension)
- initializeXinerama();
- initializeXFixes();
initializeScreens();
- initializeXRender();
-#if QT_CONFIG(xinput2)
- if (!qEnvironmentVariableIsSet("QT_XCB_NO_XI2"))
- initializeXInput2();
+#if QT_CONFIG(xcb_xinput)
+ if (hasXInput2()) {
+ xi2SetupDevices();
+ xi2SelectStateEvents();
+ }
#endif
- initializeXShape();
- initializeXKB();
m_wmSupport.reset(new QXcbWMSupport(this));
m_keyboard = new QXcbKeyboard(this);
@@ -620,34 +130,6 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
if (!m_startupId.isNull())
qunsetenv("DESKTOP_STARTUP_ID");
-
- QStringList glIntegrationNames;
- glIntegrationNames << QStringLiteral("xcb_glx") << QStringLiteral("xcb_egl");
- QString glIntegrationName = QString::fromLocal8Bit(qgetenv("QT_XCB_GL_INTEGRATION"));
- if (!glIntegrationName.isEmpty()) {
- qCDebug(lcQpaGl) << "QT_XCB_GL_INTEGRATION is set to" << glIntegrationName;
- if (glIntegrationName != QLatin1String("none")) {
- glIntegrationNames.removeAll(glIntegrationName);
- glIntegrationNames.prepend(glIntegrationName);
- } else {
- glIntegrationNames.clear();
- }
- }
-
- if (!glIntegrationNames.isEmpty()) {
- qCDebug(lcQpaGl) << "Choosing xcb gl-integration based on following priority\n" << glIntegrationNames;
- for (int i = 0; i < glIntegrationNames.size() && !m_glIntegration; i++) {
- m_glIntegration = QXcbGlIntegrationFactory::create(glIntegrationNames.at(i));
- if (m_glIntegration && !m_glIntegration->initialize(this)) {
- qCDebug(lcQpaGl) << "Failed to initialize xcb gl-integration" << glIntegrationNames.at(i);
- delete m_glIntegration;
- m_glIntegration = nullptr;
- }
- }
- if (!m_glIntegration)
- qCDebug(lcQpaGl) << "Failed to create xcb gl-integration";
- }
-
sync();
}
@@ -659,12 +141,8 @@ QXcbConnection::~QXcbConnection()
#if QT_CONFIG(draganddrop)
delete m_drag;
#endif
- if (m_reader && m_reader->isRunning()) {
- sendConnectionEvent(QXcbAtom::_QT_CLOSE_CONNECTION);
- m_reader->wait();
- }
-
- delete m_reader;
+ if (m_eventQueue)
+ delete m_eventQueue;
QXcbIntegration *integration = QXcbIntegration::instance();
// Delete screens in reverse order to avoid crash in case of multiple screens
@@ -676,22 +154,9 @@ QXcbConnection::~QXcbConnection()
delete m_glIntegration;
- if (isConnected()) {
-#if QT_CONFIG(xcb_xlib)
- XCloseDisplay(static_cast<Display *>(m_xlib_display));
-#else
- xcb_disconnect(xcb_connection());
-#endif
- }
-
delete m_keyboard;
}
-bool QXcbConnection::isConnected() const
-{
- return m_connection && !xcb_connection_has_error(m_connection);
-}
-
QXcbScreen *QXcbConnection::primaryScreen() const
{
if (!m_screens.isEmpty()) {
@@ -727,22 +192,22 @@ QXcbWindow *QXcbConnection::platformWindowFromId(xcb_window_t id)
#define HANDLE_PLATFORM_WINDOW_EVENT(event_t, windowMember, handler) \
{ \
- event_t *e = reinterpret_cast<event_t *>(event); \
+ auto e = reinterpret_cast<event_t *>(event); \
if (QXcbWindowEventListener *eventListener = windowEventListenerFromId(e->windowMember)) { \
- handled = eventListener->handleGenericEvent(event, &result); \
- if (!handled) \
- eventListener->handler(e); \
+ if (eventListener->handleNativeEvent(event)) \
+ return; \
+ eventListener->handler(e); \
} \
} \
break;
#define HANDLE_KEYBOARD_EVENT(event_t, handler) \
{ \
- event_t *e = reinterpret_cast<event_t *>(event); \
+ auto e = reinterpret_cast<event_t *>(event); \
if (QXcbWindowEventListener *eventListener = windowEventListenerFromId(e->event)) { \
- handled = eventListener->handleGenericEvent(event, &result); \
- if (!handled) \
- m_keyboard->handler(e); \
+ if (eventListener->handleNativeEvent(event)) \
+ return; \
+ m_keyboard->handler(e); \
} \
} \
break;
@@ -796,17 +261,17 @@ void QXcbConnection::printXcbEvent(const QLoggingCategory &log, const char *mess
CASE_PRINT_AND_RETURN( XCB_GE_GENERIC );
}
// XFixes
- if (has_xfixes && response_type == xfixes_first_event + XCB_XFIXES_SELECTION_NOTIFY)
+ if (isXFixesType(response_type, XCB_XFIXES_SELECTION_NOTIFY))
PRINT_AND_RETURN("XCB_XFIXES_SELECTION_NOTIFY");
+
// XRandR
- if (has_randr_extension) {
- if (response_type == xrandr_first_event + XCB_RANDR_NOTIFY)
- PRINT_AND_RETURN("XCB_RANDR_NOTIFY");
- if (response_type == xrandr_first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY)
- PRINT_AND_RETURN("XCB_RANDR_SCREEN_CHANGE_NOTIFY");
- }
+ if (isXRandrType(response_type, XCB_RANDR_NOTIFY))
+ PRINT_AND_RETURN("XCB_RANDR_NOTIFY");
+ if (isXRandrType(response_type, XCB_RANDR_SCREEN_CHANGE_NOTIFY))
+ PRINT_AND_RETURN("XCB_RANDR_SCREEN_CHANGE_NOTIFY");
+
// XKB
- if (response_type == xkb_first_event)
+ if (isXkbType(response_type))
PRINT_AND_RETURN("XCB_XKB_* event");
// UNKNOWN
@@ -968,7 +433,7 @@ void QXcbConnection::handleXcbError(xcb_generic_error_t *error)
{
long result = 0;
QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance();
- if (dispatcher && dispatcher->filterNativeEvent(m_nativeInterface->genericEventFilterType(), error, &result))
+ if (dispatcher && dispatcher->filterNativeEvent(m_nativeInterface->nativeEventType(), error, &result))
return;
printXcbError("QXcbConnection: XCB error", error);
@@ -1060,371 +525,210 @@ namespace {
void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
{
- long result = 0;
- QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance();
- bool handled = dispatcher && dispatcher->filterNativeEvent(m_nativeInterface->genericEventFilterType(), event, &result);
+ if (Q_UNLIKELY(lcQpaEvents().isDebugEnabled()))
+ printXcbEvent(lcQpaEvents(), "Event", event);
- uint response_type = event->response_type & ~0x80;
+ long result = 0; // Used only by MS Windows
+ if (QAbstractEventDispatcher *dispatcher = QAbstractEventDispatcher::instance()) {
+ if (dispatcher->filterNativeEvent(m_nativeInterface->nativeEventType(), event, &result))
+ return;
+ }
- if (!handled) {
- switch (response_type) {
- case XCB_EXPOSE:
- HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent);
-
- case XCB_BUTTON_PRESS: {
- xcb_button_press_event_t *ev = (xcb_button_press_event_t *)event;
- m_keyboard->updateXKBStateFromCore(ev->state);
- // the event explicitly contains the state of the three first buttons,
- // the rest we need to manage ourselves
- m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state);
- setButtonState(translateMouseButton(ev->detail), true);
- if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
- qCDebug(lcQpaXInputEvents, "legacy mouse press, button %d state %X", ev->detail, static_cast<unsigned int>(m_buttonState));
- HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent);
- }
- case XCB_BUTTON_RELEASE: {
- xcb_button_release_event_t *ev = (xcb_button_release_event_t *)event;
- m_keyboard->updateXKBStateFromCore(ev->state);
- m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state);
- setButtonState(translateMouseButton(ev->detail), false);
- if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
- qCDebug(lcQpaXInputEvents, "legacy mouse release, button %d state %X", ev->detail, static_cast<unsigned int>(m_buttonState));
- HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent);
- }
- case XCB_MOTION_NOTIFY: {
- xcb_motion_notify_event_t *ev = (xcb_motion_notify_event_t *)event;
- m_keyboard->updateXKBStateFromCore(ev->state);
- m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state);
- if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
- qCDebug(lcQpaXInputEvents, "legacy mouse move %d,%d button %d state %X", ev->event_x, ev->event_y,
- ev->detail, static_cast<unsigned int>(m_buttonState));
- HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent);
- }
+ uint response_type = event->response_type & ~0x80;
- case XCB_CONFIGURE_NOTIFY:
- HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent);
- case XCB_MAP_NOTIFY:
- HANDLE_PLATFORM_WINDOW_EVENT(xcb_map_notify_event_t, event, handleMapNotifyEvent);
- case XCB_UNMAP_NOTIFY:
- HANDLE_PLATFORM_WINDOW_EVENT(xcb_unmap_notify_event_t, event, handleUnmapNotifyEvent);
- case XCB_DESTROY_NOTIFY:
- HANDLE_PLATFORM_WINDOW_EVENT(xcb_destroy_notify_event_t, event, handleDestroyNotifyEvent);
- case XCB_CLIENT_MESSAGE:
- handleClientMessageEvent((xcb_client_message_event_t *)event);
- break;
- case XCB_ENTER_NOTIFY:
-#if QT_CONFIG(xinput2)
- if (hasXInput2() && !xi2MouseEventsDisabled())
- break;
+ bool handled = true;
+ switch (response_type) {
+ case XCB_EXPOSE:
+ HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent);
+ case XCB_BUTTON_PRESS: {
+ auto ev = reinterpret_cast<xcb_button_press_event_t *>(event);
+ m_keyboard->updateXKBStateFromCore(ev->state);
+ // the event explicitly contains the state of the three first buttons,
+ // the rest we need to manage ourselves
+ m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state);
+ setButtonState(translateMouseButton(ev->detail), true);
+ if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
+ qCDebug(lcQpaXInputEvents, "legacy mouse press, button %d state %X",
+ ev->detail, static_cast<unsigned int>(m_buttonState));
+ HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent);
+ }
+ case XCB_BUTTON_RELEASE: {
+ auto ev = reinterpret_cast<xcb_button_release_event_t *>(event);
+ m_keyboard->updateXKBStateFromCore(ev->state);
+ m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state);
+ setButtonState(translateMouseButton(ev->detail), false);
+ if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
+ qCDebug(lcQpaXInputEvents, "legacy mouse release, button %d state %X",
+ ev->detail, static_cast<unsigned int>(m_buttonState));
+ HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent);
+ }
+ case XCB_MOTION_NOTIFY: {
+ auto ev = reinterpret_cast<xcb_motion_notify_event_t *>(event);
+ m_keyboard->updateXKBStateFromCore(ev->state);
+ m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state);
+ if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
+ qCDebug(lcQpaXInputEvents, "legacy mouse move %d,%d button %d state %X",
+ ev->event_x, ev->event_y, ev->detail, static_cast<unsigned int>(m_buttonState));
+ HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent);
+ }
+ case XCB_CONFIGURE_NOTIFY:
+ HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent);
+ case XCB_MAP_NOTIFY:
+ HANDLE_PLATFORM_WINDOW_EVENT(xcb_map_notify_event_t, event, handleMapNotifyEvent);
+ case XCB_UNMAP_NOTIFY:
+ HANDLE_PLATFORM_WINDOW_EVENT(xcb_unmap_notify_event_t, event, handleUnmapNotifyEvent);
+ case XCB_DESTROY_NOTIFY:
+ HANDLE_PLATFORM_WINDOW_EVENT(xcb_destroy_notify_event_t, event, handleDestroyNotifyEvent);
+ case XCB_CLIENT_MESSAGE: {
+ auto clientMessage = reinterpret_cast<xcb_client_message_event_t *>(event);
+ if (clientMessage->format != 32)
+ return;
+#if QT_CONFIG(draganddrop)
+ if (clientMessage->type == atom(QXcbAtom::XdndStatus))
+ drag()->handleStatus(clientMessage);
+ else if (clientMessage->type == atom(QXcbAtom::XdndFinished))
+ drag()->handleFinished(clientMessage);
#endif
- HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent);
- case XCB_LEAVE_NOTIFY:
-#if QT_CONFIG(xinput2)
- if (hasXInput2() && !xi2MouseEventsDisabled())
- break;
+ if (m_systemTrayTracker && clientMessage->type == atom(QXcbAtom::MANAGER))
+ m_systemTrayTracker->notifyManagerClientMessageEvent(clientMessage);
+ HANDLE_PLATFORM_WINDOW_EVENT(xcb_client_message_event_t, window, handleClientMessageEvent);
+ }
+ case XCB_ENTER_NOTIFY:
+#if QT_CONFIG(xcb_xinput)
+ if (hasXInput2() && !xi2MouseEventsDisabled())
+ break;
#endif
- m_keyboard->updateXKBStateFromCore(((xcb_leave_notify_event_t *)event)->state);
- HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, handleLeaveNotifyEvent);
- case XCB_FOCUS_IN:
- HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_in_event_t, event, handleFocusInEvent);
- case XCB_FOCUS_OUT:
- HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent);
- case XCB_KEY_PRESS:
- {
- xcb_key_press_event_t *kp = (xcb_key_press_event_t *)event;
- m_keyboard->updateXKBStateFromCore(kp->state);
- setTime(kp->time);
- HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent);
- }
- case XCB_KEY_RELEASE:
- m_keyboard->updateXKBStateFromCore(((xcb_key_release_event_t *)event)->state);
- HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent);
- case XCB_MAPPING_NOTIFY:
- m_keyboard->updateKeymap(reinterpret_cast<xcb_mapping_notify_event_t *>(event));
+ HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent);
+ case XCB_LEAVE_NOTIFY:
+#if QT_CONFIG(xcb_xinput)
+ if (hasXInput2() && !xi2MouseEventsDisabled())
break;
- case XCB_SELECTION_REQUEST:
- {
+#endif
+ m_keyboard->updateXKBStateFromCore(reinterpret_cast<xcb_leave_notify_event_t *>(event)->state);
+ HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, handleLeaveNotifyEvent);
+ case XCB_FOCUS_IN:
+ HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_in_event_t, event, handleFocusInEvent);
+ case XCB_FOCUS_OUT:
+ HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent);
+ case XCB_KEY_PRESS:
+ {
+ auto keyPress = reinterpret_cast<xcb_key_press_event_t *>(event);
+ m_keyboard->updateXKBStateFromCore(keyPress->state);
+ setTime(keyPress->time);
+ HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent);
+ }
+ case XCB_KEY_RELEASE:
+ m_keyboard->updateXKBStateFromCore(reinterpret_cast<xcb_key_release_event_t *>(event)->state);
+ HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent);
+ case XCB_MAPPING_NOTIFY:
+ m_keyboard->updateKeymap(reinterpret_cast<xcb_mapping_notify_event_t *>(event));
+ break;
+ case XCB_SELECTION_REQUEST:
+ {
#if QT_CONFIG(draganddrop) || QT_CONFIG(clipboard)
- xcb_selection_request_event_t *sr = reinterpret_cast<xcb_selection_request_event_t *>(event);
+ auto selectionRequest = reinterpret_cast<xcb_selection_request_event_t *>(event);
#endif
#if QT_CONFIG(draganddrop)
- if (sr->selection == atom(QXcbAtom::XdndSelection))
- m_drag->handleSelectionRequest(sr);
- else
+ if (selectionRequest->selection == atom(QXcbAtom::XdndSelection))
+ m_drag->handleSelectionRequest(selectionRequest);
+ else
#endif
- {
+ {
#ifndef QT_NO_CLIPBOARD
- m_clipboard->handleSelectionRequest(sr);
+ m_clipboard->handleSelectionRequest(selectionRequest);
#endif
- }
- break;
}
- case XCB_SELECTION_CLEAR:
- setTime((reinterpret_cast<xcb_selection_clear_event_t *>(event))->time);
+ break;
+ }
+ case XCB_SELECTION_CLEAR:
+ setTime((reinterpret_cast<xcb_selection_clear_event_t *>(event))->time);
#ifndef QT_NO_CLIPBOARD
- m_clipboard->handleSelectionClearRequest(reinterpret_cast<xcb_selection_clear_event_t *>(event));
+ m_clipboard->handleSelectionClearRequest(reinterpret_cast<xcb_selection_clear_event_t *>(event));
#endif
- handled = true;
- break;
- case XCB_SELECTION_NOTIFY:
- setTime((reinterpret_cast<xcb_selection_notify_event_t *>(event))->time);
- handled = false;
- break;
- case XCB_PROPERTY_NOTIFY:
- {
- xcb_property_notify_event_t *pn = reinterpret_cast<xcb_property_notify_event_t *>(event);
- if (pn->atom == atom(QXcbAtom::_NET_WORKAREA)) {
- QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(pn->window);
- if (virtualDesktop)
- virtualDesktop->updateWorkArea();
- } else {
- HANDLE_PLATFORM_WINDOW_EVENT(xcb_property_notify_event_t, window, handlePropertyNotifyEvent);
- }
- break;
+ break;
+ case XCB_SELECTION_NOTIFY:
+ setTime((reinterpret_cast<xcb_selection_notify_event_t *>(event))->time);
+ break;
+ case XCB_PROPERTY_NOTIFY:
+ {
+ auto propertyNotify = reinterpret_cast<xcb_property_notify_event_t *>(event);
+ if (propertyNotify->atom == atom(QXcbAtom::_NET_WORKAREA)) {
+ QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(propertyNotify->window);
+ if (virtualDesktop)
+ virtualDesktop->updateWorkArea();
+ } else {
+ HANDLE_PLATFORM_WINDOW_EVENT(xcb_property_notify_event_t, window, handlePropertyNotifyEvent);
}
-#if QT_CONFIG(xinput2)
- case XCB_GE_GENERIC:
- // Here the windowEventListener is invoked from xi2HandleEvent()
- if (hasXInput2() && isXIEvent(event, m_xiOpCode))
- xi2HandleEvent(reinterpret_cast<xcb_ge_event_t *>(event));
- break;
+ break;
+ }
+#if QT_CONFIG(xcb_xinput)
+ case XCB_GE_GENERIC:
+ // Here the windowEventListener is invoked from xi2HandleEvent()
+ if (hasXInput2() && isXIEvent(event))
+ xi2HandleEvent(reinterpret_cast<xcb_ge_event_t *>(event));
+ break;
#endif
- default:
- handled = false;
- break;
- }
+ default:
+ handled = false; // event type not recognized
+ break;
}
- if (!handled) {
- if (has_xfixes && response_type == xfixes_first_event + XCB_XFIXES_SELECTION_NOTIFY) {
- xcb_xfixes_selection_notify_event_t *notify_event = reinterpret_cast<xcb_xfixes_selection_notify_event_t *>(event);
- setTime(notify_event->timestamp);
+ if (handled)
+ return;
+
+ handled = true;
+ if (isXFixesType(response_type, XCB_XFIXES_SELECTION_NOTIFY)) {
+ auto notify_event = reinterpret_cast<xcb_xfixes_selection_notify_event_t *>(event);
+ setTime(notify_event->timestamp);
#ifndef QT_NO_CLIPBOARD
- m_clipboard->handleXFixesSelectionRequest(notify_event);
+ m_clipboard->handleXFixesSelectionRequest(notify_event);
#endif
- for (QXcbVirtualDesktop *virtualDesktop : qAsConst(m_virtualDesktops))
- virtualDesktop->handleXFixesSelectionNotify(notify_event);
-
- handled = true;
- } else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_NOTIFY) {
- updateScreens(reinterpret_cast<xcb_randr_notify_event_t *>(event));
- handled = true;
- } else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY) {
- xcb_randr_screen_change_notify_event_t *change_event = reinterpret_cast<xcb_randr_screen_change_notify_event_t *>(event);
- if (auto *virtualDesktop = virtualDesktopForRootWindow(change_event->root))
- virtualDesktop->handleScreenChange(change_event);
-
- handled = true;
+ for (QXcbVirtualDesktop *virtualDesktop : qAsConst(m_virtualDesktops))
+ virtualDesktop->handleXFixesSelectionNotify(notify_event);
+ } else if (isXRandrType(response_type, XCB_RANDR_NOTIFY)) {
+ updateScreens(reinterpret_cast<xcb_randr_notify_event_t *>(event));
+ } else if (isXRandrType(response_type, XCB_RANDR_SCREEN_CHANGE_NOTIFY)) {
+ auto change_event = reinterpret_cast<xcb_randr_screen_change_notify_event_t *>(event);
+ if (auto virtualDesktop = virtualDesktopForRootWindow(change_event->root))
+ virtualDesktop->handleScreenChange(change_event);
#if QT_CONFIG(xkb)
- } else if (response_type == xkb_first_event) { // https://bugs.freedesktop.org/show_bug.cgi?id=51295
- _xkb_event *xkb_event = reinterpret_cast<_xkb_event *>(event);
- if (xkb_event->any.deviceID == m_keyboard->coreDeviceId()) {
- switch (xkb_event->any.xkbType) {
- // XkbNewKkdNotify and XkbMapNotify together capture all sorts of keymap
- // updates (e.g. xmodmap, xkbcomp, setxkbmap), with minimal redundent recompilations.
- case XCB_XKB_STATE_NOTIFY:
- m_keyboard->updateXKBState(&xkb_event->state_notify);
- handled = true;
- break;
- case XCB_XKB_MAP_NOTIFY:
+ } else if (isXkbType(response_type)) {
+ auto xkb_event = reinterpret_cast<_xkb_event *>(event);
+ if (xkb_event->any.deviceID == m_keyboard->coreDeviceId()) {
+ switch (xkb_event->any.xkbType) {
+ // XkbNewKkdNotify and XkbMapNotify together capture all sorts of keymap
+ // updates (e.g. xmodmap, xkbcomp, setxkbmap), with minimal redundent recompilations.
+ case XCB_XKB_STATE_NOTIFY:
+ m_keyboard->updateXKBState(&xkb_event->state_notify);
+ break;
+ case XCB_XKB_MAP_NOTIFY:
+ m_keyboard->updateKeymap();
+ break;
+ case XCB_XKB_NEW_KEYBOARD_NOTIFY: {
+ xcb_xkb_new_keyboard_notify_event_t *ev = &xkb_event->new_keyboard_notify;
+ if (ev->changed & XCB_XKB_NKN_DETAIL_KEYCODES)
m_keyboard->updateKeymap();
- handled = true;
- break;
- case XCB_XKB_NEW_KEYBOARD_NOTIFY: {
- xcb_xkb_new_keyboard_notify_event_t *ev = &xkb_event->new_keyboard_notify;
- if (ev->changed & XCB_XKB_NKN_DETAIL_KEYCODES)
- m_keyboard->updateKeymap();
- break;
- }
- default:
- break;
+ break;
}
+ default:
+ break;
}
-#endif
}
- }
-
- if (!handled && m_glIntegration)
- handled = m_glIntegration->handleXcbEvent(event, response_type);
-
-#if 0
- if (Q_UNLIKELY(lcQpaEvents().isDebugEnabled()))
- printXcbEvent(lcQpaEvents(), handled ? "Handled" : "Unhandled", event);
#endif
-}
-
-void QXcbConnection::addPeekFunc(PeekFunc f)
-{
- m_peekFuncs.append(f);
-}
-
-qint32 QXcbConnection::generatePeekerId()
-{
- qint32 peekerId = m_peekerIdSource++;
- m_peekerToCachedIndex.insert(peekerId, 0);
- return peekerId;
-}
-
-bool QXcbConnection::removePeekerId(qint32 peekerId)
-{
- if (!m_peekerToCachedIndex.contains(peekerId)) {
- qCWarning(lcQpaXcb, "failed to remove unknown peeker id: %d", peekerId);
- return false;
- }
- m_peekerToCachedIndex.remove(peekerId);
- if (m_peekerToCachedIndex.isEmpty()) {
- m_peekerIdSource = 0; // Once the hash becomes empty, we can start reusing IDs
- m_peekerIndexCacheDirty = false;
- }
- return true;
-}
-
-bool QXcbConnection::peekEventQueue(PeekerCallback peeker, void *peekerData,
- PeekOptions option, qint32 peekerId)
-{
- bool peekerIdProvided = peekerId != -1;
- if (peekerIdProvided && !m_peekerToCachedIndex.contains(peekerId)) {
- qCWarning(lcQpaXcb, "failed to find index for unknown peeker id: %d", peekerId);
- return false;
- }
-
- bool peekFromCachedIndex = option.testFlag(PeekOption::PeekFromCachedIndex);
- if (peekFromCachedIndex && !peekerIdProvided) {
- qCWarning(lcQpaXcb, "PeekOption::PeekFromCachedIndex requires peeker id");
- return false;
- }
-
- if (peekerIdProvided && m_peekerIndexCacheDirty) {
- // When the main event loop has flushed the buffered XCB events into the window
- // system event queue, the cached indices are not valid anymore and need reset.
- auto it = m_peekerToCachedIndex.begin();
- while (it != m_peekerToCachedIndex.constEnd()) {
- (*it) = 0;
- ++it;
- }
- m_peekerIndexCacheDirty = false;
- }
-
- qint32 peekerIndex = peekFromCachedIndex ? m_peekerToCachedIndex.value(peekerId) : 0;
- qint32 startingIndex = peekerIndex;
- bool result = false;
- m_mainEventLoopFlushedQueue = false;
-
- QXcbEventArray *eventqueue = m_reader->lock();
-
- if (Q_UNLIKELY(lcQpaPeeker().isDebugEnabled())) {
- qCDebug(lcQpaPeeker, "[%d] peeker index: %d | mode: %s | queue size: %d", peekerId,
- peekerIndex, peekFromCachedIndex ? "cache" : "start", eventqueue->size());
- }
- while (peekerIndex < eventqueue->size() && !result && !m_mainEventLoopFlushedQueue) {
- xcb_generic_event_t *event = eventqueue->at(peekerIndex++);
- if (!event)
- continue;
- if (Q_UNLIKELY(lcQpaPeeker().isDebugEnabled())) {
- QString debug = QString((QLatin1String("[%1] peeking at index: %2")))
- .arg(peekerId).arg(peekerIndex - 1);
- printXcbEvent(lcQpaPeeker(), debug.toLatin1(), event);
- }
- // A peeker may call QCoreApplication::processEvents(), which has two implications:
- // 1) We need to make the lock available for QXcbConnection::processXcbEvents(),
- // otherwise we will deadlock;
- // 2) QXcbConnection::processXcbEvents() will flush the queue we are currently
- // looping through;
- m_reader->unlock();
- result = peeker(event, peekerData);
- m_reader->lock();
- }
-
- m_reader->unlock();
-
- if (peekerIdProvided && peekerIndex != startingIndex && !m_mainEventLoopFlushedQueue) {
- auto it = m_peekerToCachedIndex.find(peekerId);
- // Make sure that a peeker callback did not remove the peeker id
- if (it != m_peekerToCachedIndex.constEnd())
- (*it) = peekerIndex;
- }
-
- return result;
-}
-
-QXcbEventReader::QXcbEventReader(QXcbConnection *connection)
- : m_connection(connection)
-{
- checkXcbPollForQueuedEvent();
-}
-
-void QXcbEventReader::start()
-{
- if (local_xcb_poll_for_queued_event) {
- connect(this, SIGNAL(eventPending()), m_connection, SLOT(processXcbEvents()), Qt::QueuedConnection);
- connect(this, SIGNAL(finished()), m_connection, SLOT(processXcbEvents()));
- QThread::start();
} else {
- // Must be done after we have an event-dispatcher. By posting a method invocation
- // we are sure that by the time the method is called we have an event-dispatcher.
- QMetaObject::invokeMethod(this, "registerForEvents", Qt::QueuedConnection);
- }
-}
-
-void QXcbEventReader::registerForEvents()
-{
- QSocketNotifier *notifier = new QSocketNotifier(xcb_get_file_descriptor(m_connection->xcb_connection()), QSocketNotifier::Read, this);
- connect(notifier, SIGNAL(activated(int)), m_connection, SLOT(processXcbEvents()));
-
- QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher;
- connect(dispatcher, SIGNAL(aboutToBlock()), m_connection, SLOT(processXcbEvents()));
- connect(dispatcher, SIGNAL(awake()), m_connection, SLOT(processXcbEvents()));
-}
-
-void QXcbEventReader::registerEventDispatcher(QAbstractEventDispatcher *dispatcher)
-{
- // flush the xcb connection before the EventDispatcher is going to block
- // In the non-threaded case processXcbEvents is called before going to block,
- // which flushes the connection.
- if (local_xcb_poll_for_queued_event)
- connect(dispatcher, SIGNAL(aboutToBlock()), m_connection, SLOT(flush()));
-}
-
-void QXcbEventReader::run()
-{
- xcb_generic_event_t *event;
- while (m_connection && (event = xcb_wait_for_event(m_connection->xcb_connection()))) {
- m_mutex.lock();
- addEvent(event);
- while (m_connection && (event = local_xcb_poll_for_queued_event(m_connection->xcb_connection())))
- addEvent(event);
- m_mutex.unlock();
- emit eventPending();
+ handled = false; // event type still not recognized
}
- m_mutex.lock();
- for (int i = 0; i < m_events.size(); ++i)
- free(m_events.at(i));
- m_events.clear();
- m_mutex.unlock();
-}
-
-void QXcbEventReader::addEvent(xcb_generic_event_t *event)
-{
- if ((event->response_type & ~0x80) == XCB_CLIENT_MESSAGE
- && (reinterpret_cast<xcb_client_message_event_t *>(event))->type == m_connection->atom(QXcbAtom::_QT_CLOSE_CONNECTION))
- m_connection = 0;
- m_events << event;
-}
+ if (handled)
+ return;
-QXcbEventArray *QXcbEventReader::lock()
-{
- m_mutex.lock();
- if (!local_xcb_poll_for_queued_event) {
- while (xcb_generic_event_t *event = xcb_poll_for_event(m_connection->xcb_connection()))
- m_events << event;
- }
- return &m_events;
+ if (m_glIntegration)
+ m_glIntegration->handleXcbEvent(event, response_type);
}
-void QXcbEventReader::unlock()
+void QXcbConnection::addPeekFunc(PeekFunc f)
{
- m_mutex.unlock();
+ m_peekFuncs.append(f);
}
void QXcbConnection::setFocusWindow(QWindow *w)
@@ -1444,88 +748,42 @@ void QXcbConnection::setMousePressWindow(QXcbWindow *w)
void QXcbConnection::grabServer()
{
if (m_canGrabServer)
- xcb_grab_server(m_connection);
+ xcb_grab_server(xcb_connection());
}
void QXcbConnection::ungrabServer()
{
if (m_canGrabServer)
- xcb_ungrab_server(m_connection);
-}
-
-void QXcbConnection::sendConnectionEvent(QXcbAtom::Atom a, uint id)
-{
- xcb_client_message_event_t event;
- memset(&event, 0, sizeof(event));
-
- const xcb_window_t eventListener = xcb_generate_id(m_connection);
- xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
- xcb_screen_t *screen = it.data;
- xcb_create_window(m_connection, XCB_COPY_FROM_PARENT,
- eventListener, screen->root,
- 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY,
- screen->root_visual, 0, 0);
-
- event.response_type = XCB_CLIENT_MESSAGE;
- event.format = 32;
- event.sequence = 0;
- event.window = eventListener;
- event.type = atom(a);
- event.data.data32[0] = id;
-
- xcb_send_event(xcb_connection(), false, eventListener, XCB_EVENT_MASK_NO_EVENT, reinterpret_cast<const char *>(&event));
- xcb_destroy_window(m_connection, eventListener);
- xcb_flush(xcb_connection());
-}
-
-namespace
-{
- class PropertyNotifyEvent {
- public:
- PropertyNotifyEvent(xcb_window_t win, xcb_atom_t property)
- : window(win), type(XCB_PROPERTY_NOTIFY), atom(property) {}
- xcb_window_t window;
- int type;
- xcb_atom_t atom;
- bool checkEvent(xcb_generic_event_t *event) const {
- if (!event)
- return false;
- if ((event->response_type & ~0x80) != type) {
- return false;
- } else {
- xcb_property_notify_event_t *pn = reinterpret_cast<xcb_property_notify_event_t *>(event);
- if ((pn->window == window) && (pn->atom == atom))
- return true;
- }
- return false;
- }
- };
+ xcb_ungrab_server(xcb_connection());
}
xcb_timestamp_t QXcbConnection::getTimestamp()
{
// send a dummy event to myself to get the timestamp from X server.
- xcb_window_t root_win = rootWindow();
- xcb_change_property(xcb_connection(), XCB_PROP_MODE_APPEND, root_win, atom(QXcbAtom::CLIP_TEMPORARY),
- XCB_ATOM_INTEGER, 32, 0, NULL);
+ xcb_window_t window = rootWindow();
+ xcb_atom_t dummyAtom = atom(QXcbAtom::CLIP_TEMPORARY);
+ xcb_change_property(xcb_connection(), XCB_PROP_MODE_APPEND, window, dummyAtom,
+ XCB_ATOM_INTEGER, 32, 0, nullptr);
connection()->flush();
- PropertyNotifyEvent checker(root_win, atom(QXcbAtom::CLIP_TEMPORARY));
- xcb_generic_event_t *event = 0;
- // lets keep this inside a loop to avoid a possible race condition, where
- // reader thread has not yet had the time to acquire the mutex in order
- // to add the new set of events to its event queue
+ xcb_generic_event_t *event = nullptr;
+
while (!event) {
connection()->sync();
- event = checkEvent(checker);
+ event = eventQueue()->peek([window, dummyAtom](xcb_generic_event_t *event, int type) {
+ if (type != XCB_PROPERTY_NOTIFY)
+ return false;
+ auto propertyNotify = reinterpret_cast<xcb_property_notify_event_t *>(event);
+ return propertyNotify->window == window && propertyNotify->atom == dummyAtom;
+ });
}
xcb_property_notify_event_t *pn = reinterpret_cast<xcb_property_notify_event_t *>(event);
xcb_timestamp_t timestamp = pn->time;
free(event);
- xcb_delete_property(xcb_connection(), root_win, atom(QXcbAtom::CLIP_TEMPORARY));
+ xcb_delete_property(xcb_connection(), window, dummyAtom);
return timestamp;
}
@@ -1552,6 +810,9 @@ xcb_window_t QXcbConnection::getQtSelectionOwner()
xcbScreen->root_visual, // visual
0, // value mask
0); // value list
+
+ QXcbWindow::setWindowTitle(connection(), m_qtSelectionOwner,
+ QStringLiteral("Qt Selection Window"));
}
return m_qtSelectionOwner;
}
@@ -1576,17 +837,11 @@ xcb_window_t QXcbConnection::clientLeader()
XCB_WINDOW_CLASS_INPUT_OUTPUT,
screen->screen()->root_visual,
0, 0);
-#ifndef QT_NO_DEBUG
- QByteArray ba("Qt client leader window");
- xcb_change_property(xcb_connection(),
- XCB_PROP_MODE_REPLACE,
- m_clientLeader,
- atom(QXcbAtom::_NET_WM_NAME),
- atom(QXcbAtom::UTF8_STRING),
- 8,
- ba.length(),
- ba.constData());
-#endif
+
+
+ QXcbWindow::setWindowTitle(connection(), m_clientLeader,
+ QStringLiteral("Qt Client Leader Window"));
+
xcb_change_property(xcb_connection(),
XCB_PROP_MODE_REPLACE,
m_clientLeader,
@@ -1614,46 +869,6 @@ xcb_window_t QXcbConnection::clientLeader()
return m_clientLeader;
}
-#if QT_CONFIG(xcb_xlib)
-void *QXcbConnection::xlib_display() const
-{
- return m_xlib_display;
-}
-
-void *QXcbConnection::createVisualInfoForDefaultVisualId() const
-{
- if (m_defaultVisualId == UINT_MAX)
- return 0;
- XVisualInfo info;
- memset(&info, 0, sizeof info);
- info.visualid = m_defaultVisualId;
-
- int count = 0;
- Display *dpy = static_cast<Display *>(connection()->xlib_display());
- XVisualInfo *retVisual = XGetVisualInfo(dpy, VisualIDMask, &info, &count);
- Q_ASSERT(count < 2);
- return retVisual;
-}
-
-#endif
-
-#if QT_CONFIG(xinput2)
-// it is safe to cast XI_* events here as long as we are only touching the first 32 bytes,
-// after that position event needs memmove, see xi2PrepareXIGenericDeviceEvent
-static inline bool isXIType(xcb_generic_event_t *event, int opCode, uint16_t type)
-{
- if (!isXIEvent(event, opCode))
- return false;
-
- xXIGenericDeviceEvent *xiEvent = reinterpret_cast<xXIGenericDeviceEvent *>(event);
- return xiEvent->evtype == type;
-}
-#endif
-static inline bool isValid(xcb_generic_event_t *event)
-{
- return event && (event->response_type & ~0x80);
-}
-
/*! \internal
Compresses events of the same type to avoid swamping the event queue.
@@ -1666,85 +881,115 @@ static inline bool isValid(xcb_generic_event_t *event)
3) Or add public API to Qt for disabling event compression QTBUG-44964
*/
-bool QXcbConnection::compressEvent(xcb_generic_event_t *event, int currentIndex, QXcbEventArray *eventqueue) const
+bool QXcbConnection::compressEvent(xcb_generic_event_t *event) const
{
+ if (!QCoreApplication::testAttribute(Qt::AA_CompressHighFrequencyEvents))
+ return false;
+
uint responseType = event->response_type & ~0x80;
- int nextIndex = currentIndex + 1;
if (responseType == XCB_MOTION_NOTIFY) {
// compress XCB_MOTION_NOTIFY notify events
- for (int j = nextIndex; j < eventqueue->size(); ++j) {
- xcb_generic_event_t *next = eventqueue->at(j);
- if (!isValid(next))
- continue;
- if (next->response_type == XCB_MOTION_NOTIFY)
- return true;
- }
- return false;
+ return m_eventQueue->peek(QXcbEventQueue::PeekRetainMatch,
+ [](xcb_generic_event_t *, int type) {
+ return type == XCB_MOTION_NOTIFY;
+ });
}
-#if QT_CONFIG(xinput2)
+
+#if QT_CONFIG(xcb_xinput)
// compress XI_* events
if (responseType == XCB_GE_GENERIC) {
if (!hasXInput2())
return false;
// compress XI_Motion
- if (isXIType(event, m_xiOpCode, XI_Motion)) {
+ if (isXIType(event, XCB_INPUT_MOTION)) {
#if QT_CONFIG(tabletevent)
- xXIDeviceEvent *xdev = reinterpret_cast<xXIDeviceEvent *>(event);
- // Xlib's XI2 events need memmove, see xi2PrepareXIGenericDeviceEvent()
- auto sourceId = *reinterpret_cast<uint16_t *>(reinterpret_cast<char *>(&xdev->sourceid) + 4);
+ auto xdev = reinterpret_cast<xcb_input_motion_event_t *>(event);
if (!QCoreApplication::testAttribute(Qt::AA_CompressTabletEvents) &&
- const_cast<QXcbConnection *>(this)->tabletDataForDevice(sourceId))
+ const_cast<QXcbConnection *>(this)->tabletDataForDevice(xdev->sourceid))
return false;
#endif // QT_CONFIG(tabletevent)
- for (int j = nextIndex; j < eventqueue->size(); ++j) {
- xcb_generic_event_t *next = eventqueue->at(j);
- if (!isValid(next))
- continue;
- if (isXIType(next, m_xiOpCode, XI_Motion))
- return true;
- }
- return false;
+ return m_eventQueue->peek(QXcbEventQueue::PeekRetainMatch,
+ [this](xcb_generic_event_t *next, int) {
+ return isXIType(next, XCB_INPUT_MOTION);
+ });
}
-#ifdef XCB_USE_XINPUT22
+
// compress XI_TouchUpdate for the same touch point id
- if (isXIType(event, m_xiOpCode, XI_TouchUpdate)) {
- xXIDeviceEvent *xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event);
- uint32_t id = xiDeviceEvent->detail % INT_MAX;
- for (int j = nextIndex; j < eventqueue->size(); ++j) {
- xcb_generic_event_t *next = eventqueue->at(j);
- if (!isValid(next))
- continue;
- if (isXIType(next, m_xiOpCode, XI_TouchUpdate)) {
- xXIDeviceEvent *xiDeviceNextEvent = reinterpret_cast<xXIDeviceEvent *>(next);
- if (id == xiDeviceNextEvent->detail % INT_MAX)
- return true;
- }
- }
- return false;
+ if (isXIType(event, XCB_INPUT_TOUCH_UPDATE)) {
+ auto touchUpdateEvent = reinterpret_cast<xcb_input_touch_update_event_t *>(event);
+ uint32_t id = touchUpdateEvent->detail % INT_MAX;
+
+ return m_eventQueue->peek(QXcbEventQueue::PeekRetainMatch,
+ [this, &id](xcb_generic_event_t *next, int) {
+ if (!isXIType(next, XCB_INPUT_TOUCH_UPDATE))
+ return false;
+ auto touchUpdateNextEvent = reinterpret_cast<xcb_input_touch_update_event_t *>(next);
+ return id == touchUpdateNextEvent->detail % INT_MAX;
+ });
}
-#endif
+
return false;
}
#endif
+
if (responseType == XCB_CONFIGURE_NOTIFY) {
// compress multiple configure notify events for the same window
- for (int j = nextIndex; j < eventqueue->size(); ++j) {
- xcb_generic_event_t *next = eventqueue->at(j);
- if (isValid(next) && next->response_type == XCB_CONFIGURE_NOTIFY
- && reinterpret_cast<xcb_configure_notify_event_t *>(next)->event == reinterpret_cast<xcb_configure_notify_event_t *>(event)->event)
- {
- return true;
- }
- }
- return false;
+ return m_eventQueue->peek(QXcbEventQueue::PeekRetainMatch,
+ [event](xcb_generic_event_t *next, int type) {
+ if (type != XCB_CONFIGURE_NOTIFY)
+ return false;
+ auto currentEvent = reinterpret_cast<xcb_configure_notify_event_t *>(event);
+ auto nextEvent = reinterpret_cast<xcb_configure_notify_event_t *>(next);
+ return currentEvent->event == nextEvent->event;
+ });
}
return false;
}
-void QXcbConnection::processXcbEvents()
+bool QXcbConnection::isUserInputEvent(xcb_generic_event_t *event) const
+{
+ auto eventType = event->response_type & ~0x80;
+ bool isInputEvent = eventType == XCB_BUTTON_PRESS ||
+ eventType == XCB_BUTTON_RELEASE ||
+ eventType == XCB_KEY_PRESS ||
+ eventType == XCB_KEY_RELEASE ||
+ eventType == XCB_MOTION_NOTIFY ||
+ eventType == XCB_ENTER_NOTIFY ||
+ eventType == XCB_LEAVE_NOTIFY;
+ if (isInputEvent)
+ return true;
+
+#if QT_CONFIG(xcb_xinput)
+ if (connection()->hasXInput2()) {
+ isInputEvent = isXIType(event, XCB_INPUT_BUTTON_PRESS) ||
+ isXIType(event, XCB_INPUT_BUTTON_RELEASE) ||
+ isXIType(event, XCB_INPUT_MOTION) ||
+ isXIType(event, XCB_INPUT_TOUCH_BEGIN) ||
+ isXIType(event, XCB_INPUT_TOUCH_UPDATE) ||
+ isXIType(event, XCB_INPUT_TOUCH_END) ||
+ isXIType(event, XCB_INPUT_ENTER) ||
+ isXIType(event, XCB_INPUT_LEAVE) ||
+ // wacom driver's way of reporting tool proximity
+ isXIType(event, XCB_INPUT_PROPERTY);
+ }
+ if (isInputEvent)
+ return true;
+#endif
+
+ if (eventType == XCB_CLIENT_MESSAGE) {
+ auto clientMessage = reinterpret_cast<const xcb_client_message_event_t *>(event);
+ if (clientMessage->format == 32 && clientMessage->type == atom(QXcbAtom::WM_PROTOCOLS))
+ if (clientMessage->data.data32[0] == atom(QXcbAtom::WM_DELETE_WINDOW))
+ isInputEvent = true;
+ }
+
+ return isInputEvent;
+}
+
+void QXcbConnection::processXcbEvents(QEventLoop::ProcessEventsFlags flags)
{
int connection_error = xcb_connection_has_error(xcb_connection());
if (connection_error) {
@@ -1752,22 +997,17 @@ void QXcbConnection::processXcbEvents()
exit(1);
}
- QXcbEventArray *eventqueue = m_reader->lock();
+ m_eventQueue->flushBufferedEvents();
- for (int i = 0; i < eventqueue->size(); ++i) {
- xcb_generic_event_t *event = eventqueue->at(i);
- if (!event)
- continue;
+ while (xcb_generic_event_t *event = m_eventQueue->takeFirst(flags)) {
QScopedPointer<xcb_generic_event_t, QScopedPointerPodDeleter> eventGuard(event);
- (*eventqueue)[i] = 0;
if (!(event->response_type & ~0x80)) {
handleXcbError(reinterpret_cast<xcb_generic_error_t *>(event));
continue;
}
- if (Q_LIKELY(QCoreApplication::testAttribute(Qt::AA_CompressHighFrequencyEvents)) &&
- compressEvent(event, i, eventqueue))
+ if (compressEvent(event))
continue;
#ifndef QT_NO_CLIPBOARD
@@ -1786,305 +1026,28 @@ void QXcbConnection::processXcbEvents()
m_peekFuncs.erase(std::remove_if(m_peekFuncs.begin(), m_peekFuncs.end(),
isWaitingFor),
m_peekFuncs.end());
- m_reader->unlock();
- handleXcbEvent(event);
- m_reader->lock();
- }
-
- eventqueue->clear();
- m_reader->unlock();
+ handleXcbEvent(event);
- m_peekerIndexCacheDirty = m_mainEventLoopFlushedQueue = true;
+ // The lock-based solution used to free the lock inside this loop,
+ // hence allowing for more events to arrive. ### Check if we want
+ // this flush here after QTBUG-70095
+ m_eventQueue->flushBufferedEvents();
+ }
// Indicate with a null event that the event the callbacks are waiting for
// is not in the queue currently.
for (PeekFunc f : qAsConst(m_peekFuncs))
- f(this, 0);
+ f(this, nullptr);
m_peekFuncs.clear();
xcb_flush(xcb_connection());
}
-void QXcbConnection::handleClientMessageEvent(const xcb_client_message_event_t *event)
-{
- if (event->format != 32)
- return;
-
-#if QT_CONFIG(draganddrop)
- if (event->type == atom(QXcbAtom::XdndStatus)) {
- drag()->handleStatus(event);
- } else if (event->type == atom(QXcbAtom::XdndFinished)) {
- drag()->handleFinished(event);
- }
-#endif
- if (m_systemTrayTracker && event->type == atom(QXcbAtom::MANAGER))
- m_systemTrayTracker->notifyManagerClientMessageEvent(event);
-
- QXcbWindow *window = platformWindowFromId(event->window);
- if (!window)
- return;
-
- window->handleClientMessageEvent(event);
-}
-
-static const char * xcb_atomnames = {
- // window-manager <-> client protocols
- "WM_PROTOCOLS\0"
- "WM_DELETE_WINDOW\0"
- "WM_TAKE_FOCUS\0"
- "_NET_WM_PING\0"
- "_NET_WM_CONTEXT_HELP\0"
- "_NET_WM_SYNC_REQUEST\0"
- "_NET_WM_SYNC_REQUEST_COUNTER\0"
- "MANAGER\0"
- "_NET_SYSTEM_TRAY_OPCODE\0"
-
- // ICCCM window state
- "WM_STATE\0"
- "WM_CHANGE_STATE\0"
- "WM_CLASS\0"
- "WM_NAME\0"
-
- // Session management
- "WM_CLIENT_LEADER\0"
- "WM_WINDOW_ROLE\0"
- "SM_CLIENT_ID\0"
-
- // Clipboard
- "CLIPBOARD\0"
- "INCR\0"
- "TARGETS\0"
- "MULTIPLE\0"
- "TIMESTAMP\0"
- "SAVE_TARGETS\0"
- "CLIP_TEMPORARY\0"
- "_QT_SELECTION\0"
- "_QT_CLIPBOARD_SENTINEL\0"
- "_QT_SELECTION_SENTINEL\0"
- "CLIPBOARD_MANAGER\0"
-
- "RESOURCE_MANAGER\0"
-
- "_XSETROOT_ID\0"
-
- "_QT_SCROLL_DONE\0"
- "_QT_INPUT_ENCODING\0"
-
- "_QT_CLOSE_CONNECTION\0"
-
- "_MOTIF_WM_HINTS\0"
-
- "DTWM_IS_RUNNING\0"
- "ENLIGHTENMENT_DESKTOP\0"
- "_DT_SAVE_MODE\0"
- "_SGI_DESKS_MANAGER\0"
-
- // EWMH (aka NETWM)
- "_NET_SUPPORTED\0"
- "_NET_VIRTUAL_ROOTS\0"
- "_NET_WORKAREA\0"
-
- "_NET_MOVERESIZE_WINDOW\0"
- "_NET_WM_MOVERESIZE\0"
-
- "_NET_WM_NAME\0"
- "_NET_WM_ICON_NAME\0"
- "_NET_WM_ICON\0"
-
- "_NET_WM_PID\0"
-
- "_NET_WM_WINDOW_OPACITY\0"
-
- "_NET_WM_STATE\0"
- "_NET_WM_STATE_ABOVE\0"
- "_NET_WM_STATE_BELOW\0"
- "_NET_WM_STATE_FULLSCREEN\0"
- "_NET_WM_STATE_MAXIMIZED_HORZ\0"
- "_NET_WM_STATE_MAXIMIZED_VERT\0"
- "_NET_WM_STATE_MODAL\0"
- "_NET_WM_STATE_STAYS_ON_TOP\0"
- "_NET_WM_STATE_DEMANDS_ATTENTION\0"
-
- "_NET_WM_USER_TIME\0"
- "_NET_WM_USER_TIME_WINDOW\0"
- "_NET_WM_FULL_PLACEMENT\0"
-
- "_NET_WM_WINDOW_TYPE\0"
- "_NET_WM_WINDOW_TYPE_DESKTOP\0"
- "_NET_WM_WINDOW_TYPE_DOCK\0"
- "_NET_WM_WINDOW_TYPE_TOOLBAR\0"
- "_NET_WM_WINDOW_TYPE_MENU\0"
- "_NET_WM_WINDOW_TYPE_UTILITY\0"
- "_NET_WM_WINDOW_TYPE_SPLASH\0"
- "_NET_WM_WINDOW_TYPE_DIALOG\0"
- "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU\0"
- "_NET_WM_WINDOW_TYPE_POPUP_MENU\0"
- "_NET_WM_WINDOW_TYPE_TOOLTIP\0"
- "_NET_WM_WINDOW_TYPE_NOTIFICATION\0"
- "_NET_WM_WINDOW_TYPE_COMBO\0"
- "_NET_WM_WINDOW_TYPE_DND\0"
- "_NET_WM_WINDOW_TYPE_NORMAL\0"
- "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE\0"
-
- "_KDE_NET_WM_FRAME_STRUT\0"
- "_NET_FRAME_EXTENTS\0"
-
- "_NET_STARTUP_INFO\0"
- "_NET_STARTUP_INFO_BEGIN\0"
-
- "_NET_SUPPORTING_WM_CHECK\0"
-
- "_NET_WM_CM_S0\0"
-
- "_NET_SYSTEM_TRAY_VISUAL\0"
-
- "_NET_ACTIVE_WINDOW\0"
-
- // Property formats
- "TEXT\0"
- "UTF8_STRING\0"
- "CARDINAL\0"
-
- // xdnd
- "XdndEnter\0"
- "XdndPosition\0"
- "XdndStatus\0"
- "XdndLeave\0"
- "XdndDrop\0"
- "XdndFinished\0"
- "XdndTypeList\0"
- "XdndActionList\0"
-
- "XdndSelection\0"
-
- "XdndAware\0"
- "XdndProxy\0"
-
- "XdndActionCopy\0"
- "XdndActionLink\0"
- "XdndActionMove\0"
- "XdndActionPrivate\0"
-
- // Motif DND
- "_MOTIF_DRAG_AND_DROP_MESSAGE\0"
- "_MOTIF_DRAG_INITIATOR_INFO\0"
- "_MOTIF_DRAG_RECEIVER_INFO\0"
- "_MOTIF_DRAG_WINDOW\0"
- "_MOTIF_DRAG_TARGETS\0"
-
- "XmTRANSFER_SUCCESS\0"
- "XmTRANSFER_FAILURE\0"
-
- // Xkb
- "_XKB_RULES_NAMES\0"
-
- // XEMBED
- "_XEMBED\0"
- "_XEMBED_INFO\0"
-
- // XInput2
- "Button Left\0"
- "Button Middle\0"
- "Button Right\0"
- "Button Wheel Up\0"
- "Button Wheel Down\0"
- "Button Horiz Wheel Left\0"
- "Button Horiz Wheel Right\0"
- "Abs MT Position X\0"
- "Abs MT Position Y\0"
- "Abs MT Touch Major\0"
- "Abs MT Touch Minor\0"
- "Abs MT Orientation\0"
- "Abs MT Pressure\0"
- "Abs MT Tracking ID\0"
- "Max Contacts\0"
- "Rel X\0"
- "Rel Y\0"
- // XInput2 tablet
- "Abs X\0"
- "Abs Y\0"
- "Abs Pressure\0"
- "Abs Tilt X\0"
- "Abs Tilt Y\0"
- "Abs Wheel\0"
- "Abs Distance\0"
- "Wacom Serial IDs\0"
- "INTEGER\0"
- "Rel Horiz Wheel\0"
- "Rel Vert Wheel\0"
- "Rel Horiz Scroll\0"
- "Rel Vert Scroll\0"
- "_XSETTINGS_SETTINGS\0"
- "_COMPIZ_DECOR_PENDING\0"
- "_COMPIZ_DECOR_REQUEST\0"
- "_COMPIZ_DECOR_DELETE_PIXMAP\0"
- "_COMPIZ_TOOLKIT_ACTION\0"
- "_GTK_LOAD_ICONTHEMES\0"
- // \0\0 terminates loop.
-};
-
-QXcbAtom::Atom QXcbConnection::qatom(xcb_atom_t xatom) const
-{
- return static_cast<QXcbAtom::Atom>(std::find(m_allAtoms, m_allAtoms + QXcbAtom::NAtoms, xatom) - m_allAtoms);
-}
-
-void QXcbConnection::initializeAllAtoms() {
- const char *names[QXcbAtom::NAtoms];
- const char *ptr = xcb_atomnames;
-
- int i = 0;
- while (*ptr) {
- names[i++] = ptr;
- while (*ptr)
- ++ptr;
- ++ptr;
- }
-
- Q_ASSERT(i == QXcbAtom::NPredefinedAtoms);
-
- const QByteArray settings_atom_name = "_QT_SETTINGS_TIMESTAMP_" + m_displayName;
- names[i++] = settings_atom_name;
-
- xcb_intern_atom_cookie_t cookies[QXcbAtom::NAtoms];
-
- Q_ASSERT(i == QXcbAtom::NAtoms);
- for (i = 0; i < QXcbAtom::NAtoms; ++i)
- cookies[i] = xcb_intern_atom(xcb_connection(), false, strlen(names[i]), names[i]);
-
- for (i = 0; i < QXcbAtom::NAtoms; ++i) {
- xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xcb_connection(), cookies[i], 0);
- m_allAtoms[i] = reply->atom;
- free(reply);
- }
-}
-
-xcb_atom_t QXcbConnection::internAtom(const char *name)
-{
- if (!name || *name == 0)
- return XCB_NONE;
-
- return Q_XCB_REPLY(xcb_intern_atom, xcb_connection(), false, strlen(name), name)->atom;
-}
-
-QByteArray QXcbConnection::atomName(xcb_atom_t atom)
-{
- if (!atom)
- return QByteArray();
-
- auto reply = Q_XCB_REPLY(xcb_get_atom_name, xcb_connection(), atom);
- if (!reply)
- qWarning() << "QXcbConnection::atomName: bad Atom" << atom;
- else
- return QByteArray(xcb_get_atom_name_name(reply.get()), xcb_get_atom_name_name_length(reply.get()));
-
- return QByteArray();
-}
-
const xcb_format_t *QXcbConnection::formatForDepth(uint8_t depth) const
{
xcb_format_iterator_t iterator =
- xcb_setup_pixmap_formats_iterator(m_setup);
+ xcb_setup_pixmap_formats_iterator(setup());
while (iterator.rem) {
xcb_format_t *format = iterator.data;
@@ -2104,225 +1067,66 @@ void QXcbConnection::sync()
free(xcb_get_input_focus_reply(xcb_connection(), cookie, 0));
}
-void QXcbConnection::initializeShm()
-{
- const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_shm_id);
- if (!reply || !reply->present) {
- qCDebug(lcQpaXcb, "MIT-SHM extension is not present on the X server");
- return;
- }
- has_shm = true;
-
- auto shm_query = Q_XCB_REPLY(xcb_shm_query_version, m_connection);
- if (shm_query) {
- has_shm_fd = (shm_query->major_version == 1 && shm_query->minor_version >= 2) ||
- shm_query->major_version > 1;
- } else {
- qCWarning(lcQpaXcb, "QXcbConnection: Failed to request MIT-SHM version");
- }
-
- qCDebug(lcQpaXcb) << "Has MIT-SHM :" << has_shm;
- qCDebug(lcQpaXcb) << "Has MIT-SHM FD :" << has_shm_fd;
-
- // Temporary disable warnings (unless running in debug mode).
- auto logging = const_cast<QLoggingCategory*>(&lcQpaXcb());
- bool wasEnabled = logging->isEnabled(QtMsgType::QtWarningMsg);
- if (!logging->isEnabled(QtMsgType::QtDebugMsg))
- logging->setEnabled(QtMsgType::QtWarningMsg, false);
- if (!QXcbBackingStore::createSystemVShmSegment(this)) {
- qCDebug(lcQpaXcb, "failed to create System V shared memory segment (remote "
- "X11 connection?), disabling SHM");
- has_shm = has_shm_fd = false;
- }
- if (wasEnabled)
- logging->setEnabled(QtMsgType::QtWarningMsg, true);
-}
-
-void QXcbConnection::initializeXFixes()
-{
- const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_xfixes_id);
- if (!reply || !reply->present)
- return;
-
- auto xfixes_query = Q_XCB_REPLY(xcb_xfixes_query_version, m_connection,
- XCB_XFIXES_MAJOR_VERSION,
- XCB_XFIXES_MINOR_VERSION);
- if (!xfixes_query || xfixes_query->major_version < 2) {
- qWarning("QXcbConnection: Failed to initialize XFixes");
- return;
- }
- xfixes_first_event = reply->first_event;
- has_xfixes = true;
-}
-
-void QXcbConnection::initializeXRender()
-{
-#if QT_CONFIG(xcb_render)
- const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_render_id);
- if (!reply || !reply->present) {
- qCDebug(lcQpaXcb, "XRender extension not present on the X server");
- return;
- }
-
- auto xrender_query = Q_XCB_REPLY(xcb_render_query_version, m_connection,
- XCB_RENDER_MAJOR_VERSION,
- XCB_RENDER_MINOR_VERSION);
- if (!xrender_query) {
- qCWarning(lcQpaXcb, "xcb_render_query_version failed");
- return;
- }
-
- has_render_extension = true;
- m_xrenderVersion.first = xrender_query->major_version;
- m_xrenderVersion.second = xrender_query->minor_version;
-#endif
-}
-
-void QXcbConnection::initializeXRandr()
+QXcbSystemTrayTracker *QXcbConnection::systemTrayTracker() const
{
- const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_randr_id);
- if (!reply || !reply->present)
- return;
-
- xrandr_first_event = reply->first_event;
-
- auto xrandr_query = Q_XCB_REPLY(xcb_randr_query_version, m_connection,
- XCB_RANDR_MAJOR_VERSION,
- XCB_RANDR_MINOR_VERSION);
-
- has_randr_extension = true;
-
- if (!xrandr_query || (xrandr_query->major_version < 1 || (xrandr_query->major_version == 1 && xrandr_query->minor_version < 2))) {
- qWarning("QXcbConnection: Failed to initialize XRandr");
- has_randr_extension = false;
- }
-
- xcb_screen_iterator_t rootIter = xcb_setup_roots_iterator(m_setup);
- for (; rootIter.rem; xcb_screen_next(&rootIter)) {
- xcb_randr_select_input(xcb_connection(),
- rootIter.data->root,
- XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE |
- XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE |
- XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE |
- XCB_RANDR_NOTIFY_MASK_OUTPUT_PROPERTY
- );
+ if (!m_systemTrayTracker) {
+ QXcbConnection *self = const_cast<QXcbConnection *>(this);
+ if ((self->m_systemTrayTracker = QXcbSystemTrayTracker::create(self))) {
+ connect(m_systemTrayTracker, SIGNAL(systemTrayWindowChanged(QScreen*)),
+ QGuiApplication::platformNativeInterface(), SIGNAL(systemTrayWindowChanged(QScreen*)));
+ }
}
+ return m_systemTrayTracker;
}
-void QXcbConnection::initializeXinerama()
+Qt::MouseButtons QXcbConnection::queryMouseButtons() const
{
- const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_xinerama_id);
- if (!reply || !reply->present)
- return;
-
- auto xinerama_is_active = Q_XCB_REPLY(xcb_xinerama_is_active, m_connection);
- has_xinerama_extension = xinerama_is_active && xinerama_is_active->state;
+ int stateMask = 0;
+ QXcbCursor::queryPointer(connection(), 0, 0, &stateMask);
+ return translateMouseButtons(stateMask);
}
-void QXcbConnection::initializeXShape()
+Qt::KeyboardModifiers QXcbConnection::queryKeyboardModifiers() const
{
- const xcb_query_extension_reply_t *xshape_reply = xcb_get_extension_data(m_connection, &xcb_shape_id);
- if (!xshape_reply || !xshape_reply->present)
- return;
-
- has_shape_extension = true;
- auto shape_query = Q_XCB_REPLY(xcb_shape_query_version, m_connection);
- if (!shape_query) {
- qWarning("QXcbConnection: Failed to initialize SHAPE extension");
- } else if (shape_query->major_version > 1 || (shape_query->major_version == 1 && shape_query->minor_version >= 1)) {
- // The input shape is the only thing added in SHAPE 1.1
- has_input_shape = true;
- }
+ int stateMask = 0;
+ QXcbCursor::queryPointer(connection(), 0, 0, &stateMask);
+ return keyboard()->translateModifiers(stateMask);
}
-void QXcbConnection::initializeXKB()
+QXcbGlIntegration *QXcbConnection::glIntegration() const
{
-#if QT_CONFIG(xkb)
- const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_xkb_id);
- if (!reply || !reply->present) {
- qWarning("Qt: XKEYBOARD extension not present on the X server.");
- xkb_first_event = 0;
- return;
- }
- xkb_first_event = reply->first_event;
-
- xcb_connection_t *c = connection()->xcb_connection();
-
- auto xkb_query = Q_XCB_REPLY(xcb_xkb_use_extension, c,
- XKB_X11_MIN_MAJOR_XKB_VERSION,
- XKB_X11_MIN_MINOR_XKB_VERSION);
+ if (m_glIntegrationInitialized)
+ return m_glIntegration;
- if (!xkb_query) {
- qWarning("Qt: Failed to initialize XKB extension");
- return;
- } else if (!xkb_query->supported) {
- qWarning("Qt: Unsupported XKB version (We want %d %d, but X server has %d %d)",
- XCB_XKB_MAJOR_VERSION, XCB_XKB_MINOR_VERSION,
- xkb_query->serverMajor, xkb_query->serverMinor);
- return;
- }
-
- has_xkb = true;
-
- const uint16_t required_map_parts = (XCB_XKB_MAP_PART_KEY_TYPES |
- XCB_XKB_MAP_PART_KEY_SYMS |
- XCB_XKB_MAP_PART_MODIFIER_MAP |
- XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS |
- XCB_XKB_MAP_PART_KEY_ACTIONS |
- XCB_XKB_MAP_PART_KEY_BEHAVIORS |
- XCB_XKB_MAP_PART_VIRTUAL_MODS |
- XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP);
-
- const uint16_t required_events = (XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY |
- XCB_XKB_EVENT_TYPE_MAP_NOTIFY |
- XCB_XKB_EVENT_TYPE_STATE_NOTIFY);
-
- // XKB events are reported to all interested clients without regard
- // to the current keyboard input focus or grab state
- xcb_void_cookie_t select = xcb_xkb_select_events_checked(c,
- XCB_XKB_ID_USE_CORE_KBD,
- required_events,
- 0,
- required_events,
- required_map_parts,
- required_map_parts,
- 0);
-
- xcb_generic_error_t *error = xcb_request_check(c, select);
- if (error) {
- free(error);
- qWarning("Qt: failed to select notify events from xcb-xkb");
- return;
+ QStringList glIntegrationNames;
+ glIntegrationNames << QStringLiteral("xcb_glx") << QStringLiteral("xcb_egl");
+ QString glIntegrationName = QString::fromLocal8Bit(qgetenv("QT_XCB_GL_INTEGRATION"));
+ if (!glIntegrationName.isEmpty()) {
+ qCDebug(lcQpaGl) << "QT_XCB_GL_INTEGRATION is set to" << glIntegrationName;
+ if (glIntegrationName != QLatin1String("none")) {
+ glIntegrationNames.removeAll(glIntegrationName);
+ glIntegrationNames.prepend(glIntegrationName);
+ } else {
+ glIntegrationNames.clear();
+ }
}
-#endif
-}
-QXcbSystemTrayTracker *QXcbConnection::systemTrayTracker() const
-{
- if (!m_systemTrayTracker) {
- QXcbConnection *self = const_cast<QXcbConnection *>(this);
- if ((self->m_systemTrayTracker = QXcbSystemTrayTracker::create(self))) {
- connect(m_systemTrayTracker, SIGNAL(systemTrayWindowChanged(QScreen*)),
- QGuiApplication::platformNativeInterface(), SIGNAL(systemTrayWindowChanged(QScreen*)));
+ if (!glIntegrationNames.isEmpty()) {
+ qCDebug(lcQpaGl) << "Choosing xcb gl-integration based on following priority\n" << glIntegrationNames;
+ for (int i = 0; i < glIntegrationNames.size() && !m_glIntegration; i++) {
+ m_glIntegration = QXcbGlIntegrationFactory::create(glIntegrationNames.at(i));
+ if (m_glIntegration && !m_glIntegration->initialize(const_cast<QXcbConnection *>(this))) {
+ qCDebug(lcQpaGl) << "Failed to initialize xcb gl-integration" << glIntegrationNames.at(i);
+ delete m_glIntegration;
+ m_glIntegration = nullptr;
+ }
}
+ if (!m_glIntegration)
+ qCDebug(lcQpaGl) << "Failed to create xcb gl-integration";
}
- return m_systemTrayTracker;
-}
-bool QXcbConnection::xEmbedSystemTrayAvailable()
-{
- if (!QGuiApplicationPrivate::platformIntegration())
- return false;
- QXcbConnection *connection = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration())->defaultConnection();
- return connection->systemTrayTracker();
-}
-
-bool QXcbConnection::xEmbedSystemTrayVisualHasAlphaChannel()
-{
- if (!QGuiApplicationPrivate::platformIntegration())
- return false;
- QXcbConnection *connection = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration())->defaultConnection();
- return connection->systemTrayTracker() && connection->systemTrayTracker()->visualHasAlphaChannel();
+ m_glIntegrationInitialized = true;
+ return m_glIntegration;
}
bool QXcbConnection::event(QEvent *e)
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index c9dde35558..5d53b97d37 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -47,42 +47,18 @@
#include "qxcbexport.h"
#include <QHash>
#include <QList>
-#include <QMutex>
-#include <QObject>
-#include <QThread>
#include <QVector>
-#include <QVarLengthArray>
#include <qpa/qwindowsysteminterface.h>
#include <QtCore/QLoggingCategory>
#include <QtCore/private/qglobal_p.h>
-#include <cstdlib>
-#include <memory>
-
-// This is needed to make Qt compile together with XKB. xkb.h is using a variable
-// which is called 'explicit', this is a reserved keyword in c++
-#if QT_CONFIG(xkb)
-#define explicit dont_use_cxx_explicit
-#include <xcb/xkb.h>
-#undef explicit
-#endif
+#include "qxcbeventqueue.h"
+#include "qxcbconnection_basic.h"
#if QT_CONFIG(tabletevent)
#include <QTabletEvent>
#endif
-#if QT_CONFIG(xinput2)
-#include <X11/extensions/XI2.h>
-#ifdef XIScrollClass
-#define XCB_USE_XINPUT21 // XI 2.1 adds smooth scrolling support
-#ifdef XI_TouchBeginMask
-#define XCB_USE_XINPUT22 // XI 2.2 adds multi-point touch support
-#endif
-#endif
-#endif // QT_CONFIG(xinput2)
-
-struct xcb_randr_get_output_info_reply_t;
-
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcQpaXInput)
@@ -90,9 +66,10 @@ Q_DECLARE_LOGGING_CATEGORY(lcQpaXInputDevices)
Q_DECLARE_LOGGING_CATEGORY(lcQpaXInputEvents)
Q_DECLARE_LOGGING_CATEGORY(lcQpaScreen)
Q_DECLARE_LOGGING_CATEGORY(lcQpaEvents)
-Q_DECLARE_LOGGING_CATEGORY(lcQpaXcb)
Q_DECLARE_LOGGING_CATEGORY(lcQpaPeeker)
Q_DECLARE_LOGGING_CATEGORY(lcQpaKeyboard)
+Q_DECLARE_LOGGING_CATEGORY(lcQpaXDnd)
+Q_DECLARE_LOGGING_CATEGORY(lcQpaEventReader)
class QXcbVirtualDesktop;
class QXcbScreen;
@@ -105,248 +82,11 @@ class QXcbNativeInterface;
class QXcbSystemTrayTracker;
class QXcbGlIntegration;
-namespace QXcbAtom {
- enum Atom {
- // window-manager <-> client protocols
- WM_PROTOCOLS,
- WM_DELETE_WINDOW,
- WM_TAKE_FOCUS,
- _NET_WM_PING,
- _NET_WM_CONTEXT_HELP,
- _NET_WM_SYNC_REQUEST,
- _NET_WM_SYNC_REQUEST_COUNTER,
- MANAGER, // System tray notification
- _NET_SYSTEM_TRAY_OPCODE, // System tray operation
-
- // ICCCM window state
- WM_STATE,
- WM_CHANGE_STATE,
- WM_CLASS,
- WM_NAME,
-
- // Session management
- WM_CLIENT_LEADER,
- WM_WINDOW_ROLE,
- SM_CLIENT_ID,
-
- // Clipboard
- CLIPBOARD,
- INCR,
- TARGETS,
- MULTIPLE,
- TIMESTAMP,
- SAVE_TARGETS,
- CLIP_TEMPORARY,
- _QT_SELECTION,
- _QT_CLIPBOARD_SENTINEL,
- _QT_SELECTION_SENTINEL,
- CLIPBOARD_MANAGER,
-
- RESOURCE_MANAGER,
-
- _XSETROOT_ID,
-
- _QT_SCROLL_DONE,
- _QT_INPUT_ENCODING,
-
- // Qt/XCB specific
- _QT_CLOSE_CONNECTION,
-
- _MOTIF_WM_HINTS,
-
- DTWM_IS_RUNNING,
- ENLIGHTENMENT_DESKTOP,
- _DT_SAVE_MODE,
- _SGI_DESKS_MANAGER,
-
- // EWMH (aka NETWM)
- _NET_SUPPORTED,
- _NET_VIRTUAL_ROOTS,
- _NET_WORKAREA,
-
- _NET_MOVERESIZE_WINDOW,
- _NET_WM_MOVERESIZE,
-
- _NET_WM_NAME,
- _NET_WM_ICON_NAME,
- _NET_WM_ICON,
-
- _NET_WM_PID,
-
- _NET_WM_WINDOW_OPACITY,
-
- _NET_WM_STATE,
- _NET_WM_STATE_ABOVE,
- _NET_WM_STATE_BELOW,
- _NET_WM_STATE_FULLSCREEN,
- _NET_WM_STATE_MAXIMIZED_HORZ,
- _NET_WM_STATE_MAXIMIZED_VERT,
- _NET_WM_STATE_MODAL,
- _NET_WM_STATE_STAYS_ON_TOP,
- _NET_WM_STATE_DEMANDS_ATTENTION,
-
- _NET_WM_USER_TIME,
- _NET_WM_USER_TIME_WINDOW,
- _NET_WM_FULL_PLACEMENT,
-
- _NET_WM_WINDOW_TYPE,
- _NET_WM_WINDOW_TYPE_DESKTOP,
- _NET_WM_WINDOW_TYPE_DOCK,
- _NET_WM_WINDOW_TYPE_TOOLBAR,
- _NET_WM_WINDOW_TYPE_MENU,
- _NET_WM_WINDOW_TYPE_UTILITY,
- _NET_WM_WINDOW_TYPE_SPLASH,
- _NET_WM_WINDOW_TYPE_DIALOG,
- _NET_WM_WINDOW_TYPE_DROPDOWN_MENU,
- _NET_WM_WINDOW_TYPE_POPUP_MENU,
- _NET_WM_WINDOW_TYPE_TOOLTIP,
- _NET_WM_WINDOW_TYPE_NOTIFICATION,
- _NET_WM_WINDOW_TYPE_COMBO,
- _NET_WM_WINDOW_TYPE_DND,
- _NET_WM_WINDOW_TYPE_NORMAL,
- _KDE_NET_WM_WINDOW_TYPE_OVERRIDE,
-
- _KDE_NET_WM_FRAME_STRUT,
- _NET_FRAME_EXTENTS,
-
- _NET_STARTUP_INFO,
- _NET_STARTUP_INFO_BEGIN,
-
- _NET_SUPPORTING_WM_CHECK,
-
- _NET_WM_CM_S0,
-
- _NET_SYSTEM_TRAY_VISUAL,
-
- _NET_ACTIVE_WINDOW,
-
- // Property formats
- TEXT,
- UTF8_STRING,
- CARDINAL,
-
- // Xdnd
- XdndEnter,
- XdndPosition,
- XdndStatus,
- XdndLeave,
- XdndDrop,
- XdndFinished,
- XdndTypelist,
- XdndActionList,
-
- XdndSelection,
-
- XdndAware,
- XdndProxy,
-
- XdndActionCopy,
- XdndActionLink,
- XdndActionMove,
- XdndActionPrivate,
-
- // Motif DND
- _MOTIF_DRAG_AND_DROP_MESSAGE,
- _MOTIF_DRAG_INITIATOR_INFO,
- _MOTIF_DRAG_RECEIVER_INFO,
- _MOTIF_DRAG_WINDOW,
- _MOTIF_DRAG_TARGETS,
-
- XmTRANSFER_SUCCESS,
- XmTRANSFER_FAILURE,
-
- // Xkb
- _XKB_RULES_NAMES,
-
- // XEMBED
- _XEMBED,
- _XEMBED_INFO,
-
- // XInput2
- ButtonLeft,
- ButtonMiddle,
- ButtonRight,
- ButtonWheelUp,
- ButtonWheelDown,
- ButtonHorizWheelLeft,
- ButtonHorizWheelRight,
- AbsMTPositionX,
- AbsMTPositionY,
- AbsMTTouchMajor,
- AbsMTTouchMinor,
- AbsMTOrientation,
- AbsMTPressure,
- AbsMTTrackingID,
- MaxContacts,
- RelX,
- RelY,
- // XInput2 tablet
- AbsX,
- AbsY,
- AbsPressure,
- AbsTiltX,
- AbsTiltY,
- AbsWheel,
- AbsDistance,
- WacomSerialIDs,
- INTEGER,
- RelHorizWheel,
- RelVertWheel,
- RelHorizScroll,
- RelVertScroll,
-
- _XSETTINGS_SETTINGS,
-
- _COMPIZ_DECOR_PENDING,
- _COMPIZ_DECOR_REQUEST,
- _COMPIZ_DECOR_DELETE_PIXMAP,
- _COMPIZ_TOOLKIT_ACTION,
- _GTK_LOAD_ICONTHEMES,
-
- NPredefinedAtoms,
-
- _QT_SETTINGS_TIMESTAMP = NPredefinedAtoms,
- NAtoms
- };
-}
-
-typedef QVarLengthArray<xcb_generic_event_t *, 64> QXcbEventArray;
-
-class QXcbConnection;
-class QXcbEventReader : public QThread
-{
- Q_OBJECT
-public:
- QXcbEventReader(QXcbConnection *connection);
-
- void run() override;
-
- QXcbEventArray *lock();
- void unlock();
-
- void start();
-
- void registerEventDispatcher(QAbstractEventDispatcher *dispatcher);
-
-signals:
- void eventPending();
-
-private slots:
- void registerForEvents();
-
-private:
- void addEvent(xcb_generic_event_t *event);
-
- QMutex m_mutex;
- QXcbEventArray m_events;
- QXcbConnection *m_connection;
-};
-
class QXcbWindowEventListener
{
public:
virtual ~QXcbWindowEventListener() {}
- virtual bool handleGenericEvent(xcb_generic_event_t *, long *) { return false; }
+ virtual bool handleNativeEvent(xcb_generic_event_t *) { return false; }
virtual void handleExposeEvent(const xcb_expose_event_t *) {}
virtual void handleClientMessageEvent(const xcb_client_message_event_t *) {}
@@ -362,7 +102,7 @@ public:
virtual void handleFocusInEvent(const xcb_focus_in_event_t *) {}
virtual void handleFocusOutEvent(const xcb_focus_out_event_t *) {}
virtual void handlePropertyNotifyEvent(const xcb_property_notify_event_t *) {}
-#if QT_CONFIG(xinput2)
+#if QT_CONFIG(xcb_xinput)
virtual void handleXIMouseEvent(xcb_ge_event_t *, Qt::MouseEventSource = Qt::MouseEventNotSynthesized) {}
virtual void handleXIEnterLeave(xcb_ge_event_t *) {}
#endif
@@ -383,8 +123,7 @@ private:
QXcbWindow *m_window;
};
-class QAbstractEventDispatcher;
-class Q_XCB_EXPORT QXcbConnection : public QObject
+class Q_XCB_EXPORT QXcbConnection : public QXcbBasicConnection
{
Q_OBJECT
public:
@@ -392,22 +131,15 @@ public:
~QXcbConnection();
QXcbConnection *connection() const { return const_cast<QXcbConnection *>(this); }
- bool isConnected() const;
+ QXcbEventQueue *eventQueue() const { return m_eventQueue; }
const QList<QXcbVirtualDesktop *> &virtualDesktops() const { return m_virtualDesktops; }
const QList<QXcbScreen *> &screens() const { return m_screens; }
- int primaryScreenNumber() const { return m_primaryScreenNumber; }
- QXcbVirtualDesktop *primaryVirtualDesktop() const { return m_virtualDesktops.value(m_primaryScreenNumber); }
+ QXcbVirtualDesktop *primaryVirtualDesktop() const {
+ return m_virtualDesktops.value(primaryScreenNumber());
+ }
QXcbScreen *primaryScreen() const;
- inline xcb_atom_t atom(QXcbAtom::Atom atom) const { return m_allAtoms[atom]; }
- QXcbAtom::Atom qatom(xcb_atom_t atom) const;
- xcb_atom_t internAtom(const char *name);
- QByteArray atomName(xcb_atom_t atom);
-
- const char *displayName() const { return m_displayName.constData(); }
- xcb_connection_t *xcb_connection() const { return m_connection; }
- const xcb_setup_t *setup() const { return m_setup; }
const xcb_format_t *formatForDepth(uint8_t depth) const;
bool imageNeedsEndianSwap() const
@@ -415,9 +147,9 @@ public:
if (!hasShm())
return false; // The non-Shm path does its own swapping
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
- return m_setup->image_byte_order != XCB_IMAGE_ORDER_MSB_FIRST;
+ return setup()->image_byte_order != XCB_IMAGE_ORDER_MSB_FIRST;
#else
- return m_setup->image_byte_order != XCB_IMAGE_ORDER_LSB_FIRST;
+ return setup()->image_byte_order != XCB_IMAGE_ORDER_LSB_FIRST;
#endif
}
@@ -437,10 +169,6 @@ public:
bool hasDefaultVisualId() const { return m_defaultVisualId != UINT_MAX; }
xcb_visualid_t defaultVisualId() const { return m_defaultVisualId; }
-#if QT_CONFIG(xcb_xlib)
- void *xlib_display() const;
- void *createVisualInfoForDefaultVisualId() const;
-#endif
void sync();
void handleXcbError(xcb_generic_error_t *error);
@@ -454,45 +182,15 @@ public:
QXcbWindowEventListener *windowEventListenerFromId(xcb_window_t id);
QXcbWindow *platformWindowFromId(xcb_window_t id);
- template<typename T>
- inline xcb_generic_event_t *checkEvent(T &checker);
-
typedef bool (*PeekFunc)(QXcbConnection *, xcb_generic_event_t *);
void addPeekFunc(PeekFunc f);
- // Peek at all queued events
- qint32 generatePeekerId();
- bool removePeekerId(qint32 peekerId);
- enum PeekOption { PeekDefault = 0, PeekFromCachedIndex = 1 }; // see qx11info_x11.h
- Q_DECLARE_FLAGS(PeekOptions, PeekOption)
- typedef bool (*PeekerCallback)(xcb_generic_event_t *event, void *peekerData);
- bool peekEventQueue(PeekerCallback peeker, void *peekerData = nullptr,
- PeekOptions option = PeekDefault, qint32 peekerId = -1);
-
inline xcb_timestamp_t time() const { return m_time; }
inline void setTime(xcb_timestamp_t t) { if (t > m_time) m_time = t; }
inline xcb_timestamp_t netWmUserTime() const { return m_netWmUserTime; }
inline void setNetWmUserTime(xcb_timestamp_t t) { if (t > m_netWmUserTime) m_netWmUserTime = t; }
- bool hasXFixes() const { return has_xfixes; }
- bool hasXShape() const { return has_shape_extension; }
- bool hasXRandr() const { return has_randr_extension; }
- bool hasInputShape() const { return has_input_shape; }
- bool hasXKB() const { return has_xkb; }
- bool hasXRender(int major = -1, int minor = -1) const
- {
- if (has_render_extension && major != -1 && minor != -1)
- return m_xrenderVersion >= qMakePair(major, minor);
-
- return has_render_extension;
- }
- bool hasXInput2() const { return m_xi2Enabled; }
- bool hasShm() const { return has_shm; }
- bool hasShmFd() const { return has_shm_fd; }
-
- bool threadedEventHandling() const { return m_reader->isRunning(); }
-
xcb_timestamp_t getTimestamp();
xcb_window_t getSelectionOwner(xcb_atom_t atom) const;
xcb_window_t getQtSelectionOwner();
@@ -522,53 +220,37 @@ public:
QXcbNativeInterface *nativeInterface() const { return m_nativeInterface; }
QXcbSystemTrayTracker *systemTrayTracker() const;
- static bool xEmbedSystemTrayAvailable();
- static bool xEmbedSystemTrayVisualHasAlphaChannel();
-#if QT_CONFIG(xinput2)
+ Qt::MouseButtons queryMouseButtons() const;
+ Qt::KeyboardModifiers queryKeyboardModifiers() const;
+
+ bool isUserInputEvent(xcb_generic_event_t *event) const;
+
+#if QT_CONFIG(xcb_xinput)
void xi2SelectStateEvents();
void xi2SelectDeviceEvents(xcb_window_t window);
void xi2SelectDeviceEventsCompatibility(xcb_window_t window);
bool xi2SetMouseGrabEnabled(xcb_window_t w, bool grab);
bool xi2MouseEventsDisabled() const;
- bool isAtLeastXI21() const { return m_xi2Enabled && m_xi2Minor >= 1; }
- bool isAtLeastXI22() const { return m_xi2Enabled && m_xi2Minor >= 2; }
Qt::MouseButton xiToQtMouseButton(uint32_t b);
-#ifdef XCB_USE_XINPUT21
void xi2UpdateScrollingDevices();
-#endif
-#ifdef XCB_USE_XINPUT22
bool startSystemMoveResizeForTouchBegin(xcb_window_t window, const QPoint &point, int corner);
void abortSystemMoveResizeForTouch();
bool isTouchScreen(int id);
#endif
-#endif
- QXcbEventReader *eventReader() const { return m_reader; }
bool canGrab() const { return m_canGrabServer; }
- QXcbGlIntegration *glIntegration() const { return m_glIntegration; }
+ QXcbGlIntegration *glIntegration() const;
+
+ void flush() { xcb_flush(xcb_connection()); }
+ void processXcbEvents(QEventLoop::ProcessEventsFlags flags);
protected:
bool event(QEvent *e) override;
-public slots:
- void flush() { xcb_flush(m_connection); }
-
-private slots:
- void processXcbEvents();
-
private:
- void initializeAllAtoms();
- void sendConnectionEvent(QXcbAtom::Atom atom, uint id = 0);
- void initializeShm();
- void initializeXFixes();
- void initializeXRender();
- void initializeXRandr();
- void initializeXinerama();
- void initializeXShape();
- void initializeXKB();
- void handleClientMessageEvent(const xcb_client_message_event_t *event);
+ void xrandrSelectEvents();
QXcbScreen* findScreenForCrtc(xcb_window_t rootWindow, xcb_randr_crtc_t crtc) const;
QXcbScreen* findScreenForOutput(xcb_window_t rootWindow, xcb_randr_output_t output) const;
QXcbVirtualDesktop* virtualDesktopForRootWindow(xcb_window_t rootWindow) const;
@@ -580,12 +262,9 @@ private:
xcb_randr_get_output_info_reply_t *outputInfo);
void destroyScreen(QXcbScreen *screen);
void initializeScreens();
- bool compressEvent(xcb_generic_event_t *event, int currentIndex, QXcbEventArray *eventqueue) const;
+ bool compressEvent(xcb_generic_event_t *event) const;
- bool m_xi2Enabled = false;
-#if QT_CONFIG(xinput2)
- int m_xi2Minor = -1;
- void initializeXInput2();
+#if QT_CONFIG(xcb_xinput)
void xi2SetupDevice(void *info, bool removeExisting = true);
void xi2SetupDevices();
struct TouchDeviceData {
@@ -611,10 +290,7 @@ private:
void xi2HandleEvent(xcb_ge_event_t *event);
void xi2HandleHierarchyEvent(void *event);
void xi2HandleDeviceChangedEvent(void *event);
- int m_xiOpCode, m_xiEventBase, m_xiErrorBase;
-#ifdef XCB_USE_XINPUT22
void xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindow);
-#endif // XCB_USE_XINPUT22
#if QT_CONFIG(tabletevent)
struct TabletData {
int deviceId = 0;
@@ -649,32 +325,30 @@ private:
QPointF lastScrollPosition;
};
QHash<int, ScrollingDevice> m_scrollingDevices;
-#ifdef XCB_USE_XINPUT21
void xi2HandleScrollEvent(void *event, ScrollingDevice &scrollingDevice);
void xi2UpdateScrollingDevice(ScrollingDevice &scrollingDevice);
ScrollingDevice *scrollingDeviceForId(int id);
-#endif
static bool xi2GetValuatorValueIfSet(const void *event, int valuatorNum, double *value);
- static void xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event);
-#endif
- xcb_connection_t *m_connection = nullptr;
- const xcb_setup_t *m_setup = nullptr;
+ QHash<int, TouchDeviceData> m_touchDevices;
+ struct StartSystemMoveResizeInfo {
+ xcb_window_t window = XCB_NONE;
+ uint16_t deviceid;
+ uint32_t pointid;
+ int corner;
+ } m_startSystemMoveResizeInfo;
+#endif // QT_CONFIG(xcb_xinput)
+
const bool m_canGrabServer;
const xcb_visualid_t m_defaultVisualId;
QList<QXcbVirtualDesktop *> m_virtualDesktops;
QList<QXcbScreen *> m_screens;
- int m_primaryScreenNumber = 0;
-
- xcb_atom_t m_allAtoms[QXcbAtom::NAtoms];
xcb_timestamp_t m_time = XCB_CURRENT_TIME;
xcb_timestamp_t m_netWmUserTime = XCB_CURRENT_TIME;
- QByteArray m_displayName;
-
QXcbKeyboard *m_keyboard = nullptr;
#ifndef QT_NO_CLIPBOARD
QXcbClipboard *m_clipboard = nullptr;
@@ -685,42 +359,12 @@ private:
QScopedPointer<QXcbWMSupport> m_wmSupport;
QXcbNativeInterface *m_nativeInterface = nullptr;
-#if QT_CONFIG(xcb_xlib)
- void *m_xlib_display = nullptr;
-#endif
- QXcbEventReader *m_reader = nullptr;
+ QXcbEventQueue *m_eventQueue = nullptr;
-#if QT_CONFIG(xinput2)
- QHash<int, TouchDeviceData> m_touchDevices;
-#ifdef XCB_USE_XINPUT22
- struct StartSystemMoveResizeInfo {
- xcb_window_t window = XCB_NONE;
- uint16_t deviceid;
- uint32_t pointid;
- int corner;
- } m_startSystemMoveResizeInfo;
-#endif
-#endif
WindowMapper m_mapper;
QVector<PeekFunc> m_peekFuncs;
- uint32_t xfixes_first_event = 0;
- uint32_t xrandr_first_event = 0;
- uint32_t xkb_first_event = 0;
-
- bool has_xfixes = false;
- bool has_xinerama_extension = false;
- bool has_shape_extension = false;
- bool has_randr_extension = false;
- bool has_input_shape;
- bool has_xkb = false;
- bool has_render_extension = false;
- bool has_shm = false;
- bool has_shm_fd = false;
-
- QPair<int, int> m_xrenderVersion;
-
Qt::MouseButtons m_buttonState = 0;
Qt::MouseButton m_button = Qt::NoButton;
@@ -731,44 +375,24 @@ private:
xcb_window_t m_clientLeader = 0;
QByteArray m_startupId;
QXcbSystemTrayTracker *m_systemTrayTracker = nullptr;
- QXcbGlIntegration *m_glIntegration = nullptr;
+ mutable QXcbGlIntegration *m_glIntegration = nullptr;
+ mutable bool m_glIntegrationInitialized = false;
bool m_xiGrab = false;
QVector<int> m_xiMasterPointerIds;
xcb_window_t m_qtSelectionOwner = 0;
- bool m_mainEventLoopFlushedQueue = false;
- qint32 m_peekerIdSource = 0;
- bool m_peekerIndexCacheDirty = false;
- QHash<qint32, qint32> m_peekerToCachedIndex;
- friend class QXcbEventReader;
+ friend class QXcbEventQueue;
QByteArray m_xdgCurrentDesktop;
};
-#if QT_CONFIG(xinput2)
+#if QT_CONFIG(xcb_xinput)
#if QT_CONFIG(tabletevent)
Q_DECLARE_TYPEINFO(QXcbConnection::TabletData::ValuatorClassInfo, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(QXcbConnection::TabletData, Q_MOVABLE_TYPE);
#endif
#endif
-template<typename T>
-xcb_generic_event_t *QXcbConnection::checkEvent(T &checker)
-{
- QXcbEventArray *eventqueue = m_reader->lock();
-
- for (int i = 0; i < eventqueue->size(); ++i) {
- xcb_generic_event_t *event = eventqueue->at(i);
- if (checker.checkEvent(event)) {
- (*eventqueue)[i] = 0;
- m_reader->unlock();
- return event;
- }
- }
- m_reader->unlock();
- return 0;
-}
-
class QXcbConnectionGrabber
{
public:
@@ -779,34 +403,11 @@ private:
QXcbConnection *m_connection;
};
-#define Q_XCB_REPLY_CONNECTION_ARG(connection, ...) connection
-
-struct QStdFreeDeleter {
- void operator()(void *p) const Q_DECL_NOTHROW { return std::free(p); }
-};
-
-#define Q_XCB_REPLY(call, ...) \
- std::unique_ptr<call##_reply_t, QStdFreeDeleter>( \
- call##_reply(Q_XCB_REPLY_CONNECTION_ARG(__VA_ARGS__), call(__VA_ARGS__), nullptr) \
- )
-
-#define Q_XCB_REPLY_UNCHECKED(call, ...) \
- std::unique_ptr<call##_reply_t, QStdFreeDeleter>( \
- call##_reply(Q_XCB_REPLY_CONNECTION_ARG(__VA_ARGS__), call##_unchecked(__VA_ARGS__), nullptr) \
- )
-
-template <typename T>
-union q_padded_xcb_event {
- T event;
- char padding[32];
-};
-
// The xcb_send_event() requires all events to have 32 bytes. It calls memcpy() on the
// passed in event. If the passed in event is less than 32 bytes, memcpy() reaches into
// unrelated memory.
-#define Q_DECLARE_XCB_EVENT(event_var, event_type) \
- q_padded_xcb_event<event_type> store = {}; \
- auto &event_var = store.event;
+template <typename T>
+struct alignas(32) q_padded_xcb_event : T { };
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbconnection_basic.cpp b/src/plugins/platforms/xcb/qxcbconnection_basic.cpp
new file mode 100644
index 0000000000..b8335d1240
--- /dev/null
+++ b/src/plugins/platforms/xcb/qxcbconnection_basic.cpp
@@ -0,0 +1,437 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 "qxcbconnection_basic.h"
+#include "qxcbbackingstore.h" // for createSystemVShmSegment()
+
+#include <xcb/randr.h>
+#include <xcb/shm.h>
+#include <xcb/sync.h>
+#include <xcb/xfixes.h>
+#include <xcb/xinerama.h>
+#if QT_CONFIG(xcb_xinput)
+#include <xcb/xinput.h>
+#endif
+#if QT_CONFIG(xcb_render)
+#include <xcb/render.h>
+#endif
+#if QT_CONFIG(xkb)
+#define explicit dont_use_cxx_explicit
+#include <xcb/xkb.h>
+#undef explicit
+#endif
+
+#if QT_CONFIG(xcb_xlib)
+#define register /* C++17 deprecated register */
+#include <X11/Xlib.h>
+#include <X11/Xlib-xcb.h>
+#include <X11/Xlibint.h>
+#include <X11/Xutil.h>
+#undef register
+#endif
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcQpaXcb, "qt.qpa.xcb")
+
+#if QT_CONFIG(xcb_xlib)
+static const char * const xcbConnectionErrors[] = {
+ "No error", /* Error 0 */
+ "I/O error", /* XCB_CONN_ERROR */
+ "Unsupported extension used", /* XCB_CONN_CLOSED_EXT_NOTSUPPORTED */
+ "Out of memory", /* XCB_CONN_CLOSED_MEM_INSUFFICIENT */
+ "Maximum allowed requested length exceeded", /* XCB_CONN_CLOSED_REQ_LEN_EXCEED */
+ "Failed to parse display string", /* XCB_CONN_CLOSED_PARSE_ERR */
+ "No such screen on display", /* XCB_CONN_CLOSED_INVALID_SCREEN */
+ "Error during FD passing" /* XCB_CONN_CLOSED_FDPASSING_FAILED */
+};
+
+static int nullErrorHandler(Display *dpy, XErrorEvent *err)
+{
+#ifndef Q_XCB_DEBUG
+ Q_UNUSED(dpy);
+ Q_UNUSED(err);
+#else
+ const int buflen = 1024;
+ char buf[buflen];
+
+ XGetErrorText(dpy, err->error_code, buf, buflen);
+ fprintf(stderr, "X Error: serial %lu error %d %s\n", err->serial, (int) err->error_code, buf);
+#endif
+ return 0;
+}
+
+static int ioErrorHandler(Display *dpy)
+{
+ xcb_connection_t *conn = XGetXCBConnection(dpy);
+ if (conn != NULL) {
+ /* Print a message with a textual description of the error */
+ int code = xcb_connection_has_error(conn);
+ const char *str = "Unknown error";
+ int arrayLength = sizeof(xcbConnectionErrors) / sizeof(xcbConnectionErrors[0]);
+ if (code >= 0 && code < arrayLength)
+ str = xcbConnectionErrors[code];
+
+ qWarning("The X11 connection broke: %s (code %d)", str, code);
+ }
+ return _XDefaultIOError(dpy);
+}
+#endif
+
+QXcbBasicConnection::QXcbBasicConnection(const char *displayName)
+ : m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY"))
+{
+#if QT_CONFIG(xcb_xlib)
+ Display *dpy = XOpenDisplay(m_displayName.constData());
+ if (dpy) {
+ m_primaryScreenNumber = DefaultScreen(dpy);
+ m_xcbConnection = XGetXCBConnection(dpy);
+ XSetEventQueueOwner(dpy, XCBOwnsEventQueue);
+ XSetErrorHandler(nullErrorHandler);
+ XSetIOErrorHandler(ioErrorHandler);
+ m_xlibDisplay = dpy;
+ }
+#else
+ m_xcbConnection = xcb_connect(m_displayName.constData(), &m_primaryScreenNumber);
+#endif
+ if (Q_UNLIKELY(!isConnected())) {
+ qCWarning(lcQpaXcb, "could not connect to display %s", m_displayName.constData());
+ return;
+ }
+
+ m_setup = xcb_get_setup(m_xcbConnection);
+ m_xcbAtom.initialize(m_xcbConnection);
+
+ xcb_extension_t *extensions[] = {
+ &xcb_shm_id, &xcb_xfixes_id, &xcb_randr_id, &xcb_shape_id, &xcb_sync_id,
+#if QT_CONFIG(xkb)
+ &xcb_xkb_id,
+#endif
+#if QT_CONFIG(xcb_render)
+ &xcb_render_id,
+#endif
+#if QT_CONFIG(xcb_xinput)
+ &xcb_input_id,
+#endif
+ 0
+ };
+
+ for (xcb_extension_t **ext_it = extensions; *ext_it; ++ext_it)
+ xcb_prefetch_extension_data (m_xcbConnection, *ext_it);
+
+ initializeXSync();
+ if (!qEnvironmentVariableIsSet("QT_XCB_NO_MITSHM"))
+ initializeShm();
+ if (!qEnvironmentVariableIsSet("QT_XCB_NO_XRANDR"))
+ initializeXRandr();
+ if (!m_hasXRandr)
+ initializeXinerama();
+ initializeXFixes();
+ initializeXRender();
+#if QT_CONFIG(xcb_xinput)
+ if (!qEnvironmentVariableIsSet("QT_XCB_NO_XI2"))
+ initializeXInput2();
+#endif
+ initializeXShape();
+ initializeXKB();
+}
+
+QXcbBasicConnection::~QXcbBasicConnection()
+{
+ if (isConnected()) {
+#if QT_CONFIG(xcb_xlib)
+ XCloseDisplay(static_cast<Display *>(m_xlibDisplay));
+#else
+ xcb_disconnect(m_xcbConnection);
+#endif
+ }
+}
+
+xcb_atom_t QXcbBasicConnection::internAtom(const char *name)
+{
+ if (!name || *name == 0)
+ return XCB_NONE;
+
+ return Q_XCB_REPLY(xcb_intern_atom, m_xcbConnection, false, strlen(name), name)->atom;
+}
+
+QByteArray QXcbBasicConnection::atomName(xcb_atom_t atom)
+{
+ if (!atom)
+ return QByteArray();
+
+ auto reply = Q_XCB_REPLY(xcb_get_atom_name, m_xcbConnection, atom);
+ if (reply)
+ return QByteArray(xcb_get_atom_name_name(reply.get()), xcb_get_atom_name_name_length(reply.get()));
+
+ qCWarning(lcQpaXcb) << "atomName: bad atom" << atom;
+ return QByteArray();
+}
+
+#if QT_CONFIG(xcb_xinput)
+// Starting from the xcb version 1.9.3 struct xcb_ge_event_t has changed:
+// - "pad0" became "extension"
+// - "pad1" and "pad" became "pad0"
+// New and old version of this struct share the following fields:
+typedef struct qt_xcb_ge_event_t {
+ uint8_t response_type;
+ uint8_t extension;
+ uint16_t sequence;
+ uint32_t length;
+ uint16_t event_type;
+} qt_xcb_ge_event_t;
+
+bool QXcbBasicConnection::isXIEvent(xcb_generic_event_t *event) const
+{
+ qt_xcb_ge_event_t *e = reinterpret_cast<qt_xcb_ge_event_t *>(event);
+ return e->extension == m_xiOpCode;
+}
+
+bool QXcbBasicConnection::isXIType(xcb_generic_event_t *event, uint16_t type) const
+{
+ if (!isXIEvent(event))
+ return false;
+
+ auto *e = reinterpret_cast<qt_xcb_ge_event_t *>(event);
+ return e->event_type == type;
+}
+#endif // QT_CONFIG(xcb_xinput)
+
+bool QXcbBasicConnection::isXFixesType(uint responseType, int eventType) const
+{
+ return m_hasXFixes && responseType == m_xfixesFirstEvent + eventType;
+}
+
+bool QXcbBasicConnection::isXRandrType(uint responseType, int eventType) const
+{
+ return m_hasXRandr && responseType == m_xrandrFirstEvent + eventType;
+}
+
+bool QXcbBasicConnection::isXkbType(uint responseType) const
+{
+ return m_hasXkb && responseType == m_xkbFirstEvent;
+}
+
+void QXcbBasicConnection::initializeXSync()
+{
+ const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_sync_id);
+ if (!reply || !reply->present)
+ return;
+
+ m_hasXSync = true;
+}
+
+void QXcbBasicConnection::initializeShm()
+{
+ const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_shm_id);
+ if (!reply || !reply->present) {
+ qCDebug(lcQpaXcb, "MIT-SHM extension is not present on the X server");
+ return;
+ }
+
+ auto shmQuery = Q_XCB_REPLY(xcb_shm_query_version, m_xcbConnection);
+ if (!shmQuery) {
+ qCWarning(lcQpaXcb, "failed to request MIT-SHM version");
+ return;
+ }
+
+ m_hasShm = true;
+ m_hasShmFd = (shmQuery->major_version == 1 && shmQuery->minor_version >= 2) ||
+ shmQuery->major_version > 1;
+
+ qCDebug(lcQpaXcb) << "Has MIT-SHM :" << m_hasShm;
+ qCDebug(lcQpaXcb) << "Has MIT-SHM FD :" << m_hasShmFd;
+
+ // Temporary disable warnings (unless running in debug mode).
+ auto logging = const_cast<QLoggingCategory*>(&lcQpaXcb());
+ bool wasEnabled = logging->isEnabled(QtMsgType::QtWarningMsg);
+ if (!logging->isEnabled(QtMsgType::QtDebugMsg))
+ logging->setEnabled(QtMsgType::QtWarningMsg, false);
+ if (!QXcbBackingStore::createSystemVShmSegment(m_xcbConnection)) {
+ qCDebug(lcQpaXcb, "failed to create System V shared memory segment (remote "
+ "X11 connection?), disabling SHM");
+ m_hasShm = m_hasShmFd = false;
+ }
+ if (wasEnabled)
+ logging->setEnabled(QtMsgType::QtWarningMsg, true);
+}
+
+void QXcbBasicConnection::initializeXRandr()
+{
+#if QT_CONFIG(xcb_render)
+ const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_render_id);
+ if (!reply || !reply->present) {
+ qCDebug(lcQpaXcb, "XRender extension not present on the X server");
+ return;
+ }
+
+ auto xrenderQuery = Q_XCB_REPLY(xcb_render_query_version, m_xcbConnection,
+ XCB_RENDER_MAJOR_VERSION,
+ XCB_RENDER_MINOR_VERSION);
+ if (!xrenderQuery) {
+ qCWarning(lcQpaXcb, "xcb_render_query_version failed");
+ return;
+ }
+
+ m_hasXRandr = true;
+ m_xrenderVersion.first = xrenderQuery->major_version;
+ m_xrenderVersion.second = xrenderQuery->minor_version;
+#endif
+}
+
+void QXcbBasicConnection::initializeXinerama()
+{
+ const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_xinerama_id);
+ if (!reply || !reply->present)
+ return;
+
+ auto xineramaActive = Q_XCB_REPLY(xcb_xinerama_is_active, m_xcbConnection);
+ if (xineramaActive && xineramaActive->state)
+ m_hasXinerama = true;
+}
+
+void QXcbBasicConnection::initializeXFixes()
+{
+ const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_xfixes_id);
+ if (!reply || !reply->present)
+ return;
+
+ auto xfixesQuery = Q_XCB_REPLY(xcb_xfixes_query_version, m_xcbConnection,
+ XCB_XFIXES_MAJOR_VERSION,
+ XCB_XFIXES_MINOR_VERSION);
+ if (!xfixesQuery || xfixesQuery->major_version < 2) {
+ qCWarning(lcQpaXcb, "failed to initialize XFixes");
+ return;
+ }
+
+ m_hasXFixes = true;
+ m_xfixesFirstEvent = reply->first_event;
+}
+
+void QXcbBasicConnection::initializeXRender()
+{
+ const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_randr_id);
+ if (!reply || !reply->present)
+ return;
+
+ auto xrandrQuery = Q_XCB_REPLY(xcb_randr_query_version, m_xcbConnection,
+ XCB_RANDR_MAJOR_VERSION,
+ XCB_RANDR_MINOR_VERSION);
+ if (!xrandrQuery || (xrandrQuery->major_version < 1 ||
+ (xrandrQuery->major_version == 1 && xrandrQuery->minor_version < 2))) {
+ qCWarning(lcQpaXcb, "failed to initialize XRandr");
+ return;
+ }
+
+ m_hasXRender = true;
+ m_xrandrFirstEvent = reply->first_event;
+}
+
+#if QT_CONFIG(xcb_xinput)
+void QXcbBasicConnection::initializeXInput2()
+{
+ const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_input_id);
+ if (!reply || !reply->present) {
+ qCDebug(lcQpaXcb, "XInput extension is not present on the X server");
+ return;
+ }
+
+ auto xinputQuery = Q_XCB_REPLY(xcb_input_xi_query_version, m_xcbConnection, 2, 2);
+ if (!xinputQuery || xinputQuery->major_version != 2) {
+ qCWarning(lcQpaXcb, "X server does not support XInput 2");
+ return;
+ }
+
+ qCDebug(lcQpaXcb, "Using XInput version %d.%d",
+ xinputQuery->major_version, xinputQuery->minor_version);
+
+ m_xi2Enabled = true;
+ m_xiOpCode = reply->major_opcode;
+ m_xinputFirstEvent = reply->first_event;
+ m_xi2Minor = xinputQuery->minor_version;
+}
+#endif
+
+void QXcbBasicConnection::initializeXShape()
+{
+ const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_shape_id);
+ if (!reply || !reply->present)
+ return;
+
+ m_hasXhape = true;
+
+ auto shapeQuery = Q_XCB_REPLY(xcb_shape_query_version, m_xcbConnection);
+ if (!shapeQuery) {
+ qCWarning(lcQpaXcb, "failed to initialize XShape extension");
+ return;
+ }
+
+ if (shapeQuery->major_version > 1 || (shapeQuery->major_version == 1 && shapeQuery->minor_version >= 1)) {
+ // The input shape is the only thing added in SHAPE 1.1
+ m_hasInputShape = true;
+ }
+}
+
+void QXcbBasicConnection::initializeXKB()
+{
+#if QT_CONFIG(xkb)
+ const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_xcbConnection, &xcb_xkb_id);
+ if (!reply || !reply->present) {
+ qCWarning(lcQpaXcb, "XKeyboard extension not present on the X server");
+ return;
+ }
+
+ int wantMajor = 1;
+ int wantMinor = 0;
+ auto xkbQuery = Q_XCB_REPLY(xcb_xkb_use_extension, m_xcbConnection, wantMajor, wantMinor);
+ if (!xkbQuery) {
+ qCWarning(lcQpaXcb, "failed to initialize XKeyboard extension");
+ return;
+ }
+ if (!xkbQuery->supported) {
+ qCWarning(lcQpaXcb, "unsupported XKB version (we want %d.%d, but X server has %d.%d)",
+ wantMajor, wantMinor, xkbQuery->serverMajor, xkbQuery->serverMinor);
+ return;
+ }
+
+ m_hasXkb = true;
+ m_xkbFirstEvent = reply->first_event;
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbconnection_basic.h b/src/plugins/platforms/xcb/qxcbconnection_basic.h
new file mode 100644
index 0000000000..ca91f7fa45
--- /dev/null
+++ b/src/plugins/platforms/xcb/qxcbconnection_basic.h
@@ -0,0 +1,175 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 QXCBBASICCONNECTION_H
+#define QXCBBASICCONNECTION_H
+
+#include "qxcbatom.h"
+
+#include <QtCore/QPair>
+#include <QtCore/QObject>
+#include <QtCore/QByteArray>
+#include <QtCore/QLoggingCategory>
+#include <QtGui/private/qtguiglobal_p.h>
+
+#include <xcb/xcb.h>
+
+#include <memory>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(lcQpaXcb)
+
+class QXcbBasicConnection : public QObject
+{
+ Q_OBJECT
+public:
+ QXcbBasicConnection(const char *displayName);
+ ~QXcbBasicConnection();
+
+#if QT_CONFIG(xcb_xlib)
+ void *xlib_display() const { return m_xlibDisplay; }
+#endif
+ const char *displayName() const { return m_displayName.constData(); }
+ int primaryScreenNumber() const { return m_primaryScreenNumber; }
+ xcb_connection_t *xcb_connection() const { return m_xcbConnection; }
+ bool isConnected() const {
+ return m_xcbConnection && !xcb_connection_has_error(m_xcbConnection);
+ }
+ const xcb_setup_t *setup() const { return m_setup; }
+
+ inline xcb_atom_t atom(QXcbAtom::Atom qatom) const { return m_xcbAtom.atom(qatom); }
+ QXcbAtom::Atom qatom(xcb_atom_t atom) const { return m_xcbAtom.qatom(atom); }
+ xcb_atom_t internAtom(const char *name);
+ QByteArray atomName(xcb_atom_t atom);
+
+ bool hasXFixes() const { return m_hasXFixes; }
+ bool hasXShape() const { return m_hasXhape; }
+ bool hasXRandr() const { return m_hasXRandr; }
+ bool hasInputShape() const { return m_hasInputShape; }
+ bool hasXKB() const { return m_hasXkb; }
+ bool hasXRender(int major = -1, int minor = -1) const {
+ if (m_hasXRender && major != -1 && minor != -1)
+ return m_xrenderVersion >= qMakePair(major, minor);
+
+ return m_hasXRender;
+ }
+ bool hasXInput2() const { return m_xi2Enabled; }
+ bool hasShm() const { return m_hasShm; }
+ bool hasShmFd() const { return m_hasShmFd; }
+ bool hasXSync() const { return m_hasXSync; }
+ bool hasXinerama() const { return m_hasXinerama; }
+
+#if QT_CONFIG(xcb_xinput)
+ bool isAtLeastXI21() const { return m_xi2Enabled && m_xi2Minor >= 1; }
+ bool isAtLeastXI22() const { return m_xi2Enabled && m_xi2Minor >= 2; }
+ bool isXIEvent(xcb_generic_event_t *event) const;
+ bool isXIType(xcb_generic_event_t *event, uint16_t type) const;
+#endif
+
+ bool isXFixesType(uint responseType, int eventType) const;
+ bool isXRandrType(uint responseType, int eventType) const;
+ bool isXkbType(uint responseType) const; // https://bugs.freedesktop.org/show_bug.cgi?id=51295
+
+protected:
+ void initializeShm();
+ void initializeXFixes();
+ void initializeXRender();
+ void initializeXRandr();
+ void initializeXinerama();
+ void initializeXShape();
+ void initializeXKB();
+ void initializeXSync();
+#if QT_CONFIG(xcb_xinput)
+ void initializeXInput2();
+#endif
+
+private:
+#if QT_CONFIG(xcb_xlib)
+ void *m_xlibDisplay = nullptr;
+#endif
+ QByteArray m_displayName;
+ xcb_connection_t *m_xcbConnection = nullptr;
+ int m_primaryScreenNumber = 0;
+ const xcb_setup_t *m_setup = nullptr;
+ QXcbAtom m_xcbAtom;
+
+ bool m_hasXFixes = false;
+ bool m_hasXinerama = false;
+ bool m_hasXhape = false;
+ bool m_hasInputShape;
+ bool m_hasXRandr = false;
+ bool m_hasXkb = false;
+ bool m_hasXRender = false;
+ bool m_hasShm = false;
+ bool m_hasShmFd = false;
+ bool m_hasXSync = false;
+
+ QPair<int, int> m_xrenderVersion;
+
+ bool m_xi2Enabled = false;
+#if QT_CONFIG(xcb_xinput)
+ int m_xi2Minor = -1;
+ int m_xiOpCode = -1;
+ uint32_t m_xinputFirstEvent = 0;
+#endif
+
+ uint32_t m_xfixesFirstEvent = 0;
+ uint32_t m_xrandrFirstEvent = 0;
+ uint32_t m_xkbFirstEvent = 0;
+};
+
+#define Q_XCB_REPLY_CONNECTION_ARG(connection, ...) connection
+
+struct QStdFreeDeleter {
+ void operator()(void *p) const Q_DECL_NOTHROW { return std::free(p); }
+};
+
+#define Q_XCB_REPLY(call, ...) \
+ std::unique_ptr<call##_reply_t, QStdFreeDeleter>( \
+ call##_reply(Q_XCB_REPLY_CONNECTION_ARG(__VA_ARGS__), call(__VA_ARGS__), nullptr) \
+ )
+
+#define Q_XCB_REPLY_UNCHECKED(call, ...) \
+ std::unique_ptr<call##_reply_t, QStdFreeDeleter>( \
+ call##_reply(Q_XCB_REPLY_CONNECTION_ARG(__VA_ARGS__), call##_unchecked(__VA_ARGS__), nullptr) \
+ )
+
+QT_END_NAMESPACE
+
+#endif // QXCBBASICCONNECTION_H
diff --git a/src/plugins/platforms/xcb/qxcbconnection_screens.cpp b/src/plugins/platforms/xcb/qxcbconnection_screens.cpp
new file mode 100644
index 0000000000..fe9e0be86d
--- /dev/null
+++ b/src/plugins/platforms/xcb/qxcbconnection_screens.cpp
@@ -0,0 +1,414 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 "qxcbconnection.h"
+#include "qxcbscreen.h"
+#include "qxcbintegration.h"
+
+#include <QtGui/private/qhighdpiscaling_p.h>
+#include <QtCore/QString>
+#include <QtCore/QList>
+
+#include <xcb/xinerama.h>
+
+void QXcbConnection::xrandrSelectEvents()
+{
+ xcb_screen_iterator_t rootIter = xcb_setup_roots_iterator(setup());
+ for (; rootIter.rem; xcb_screen_next(&rootIter)) {
+ xcb_randr_select_input(xcb_connection(),
+ rootIter.data->root,
+ XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE |
+ XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE |
+ XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE |
+ XCB_RANDR_NOTIFY_MASK_OUTPUT_PROPERTY
+ );
+ }
+}
+
+QXcbScreen* QXcbConnection::findScreenForCrtc(xcb_window_t rootWindow, xcb_randr_crtc_t crtc) const
+{
+ for (QXcbScreen *screen : m_screens) {
+ if (screen->root() == rootWindow && screen->crtc() == crtc)
+ return screen;
+ }
+
+ return nullptr;
+}
+
+QXcbScreen* QXcbConnection::findScreenForOutput(xcb_window_t rootWindow, xcb_randr_output_t output) const
+{
+ for (QXcbScreen *screen : m_screens) {
+ if (screen->root() == rootWindow && screen->output() == output)
+ return screen;
+ }
+
+ return nullptr;
+}
+
+QXcbVirtualDesktop* QXcbConnection::virtualDesktopForRootWindow(xcb_window_t rootWindow) const
+{
+ for (QXcbVirtualDesktop *virtualDesktop : m_virtualDesktops) {
+ if (virtualDesktop->screen()->root == rootWindow)
+ return virtualDesktop;
+ }
+
+ return nullptr;
+}
+
+/*!
+ \brief Synchronizes the screen list, adds new screens, removes deleted ones
+*/
+void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
+{
+ if (event->subCode == XCB_RANDR_NOTIFY_CRTC_CHANGE) {
+ xcb_randr_crtc_change_t crtc = event->u.cc;
+ QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(crtc.window);
+ if (!virtualDesktop)
+ // Not for us
+ return;
+
+ QXcbScreen *screen = findScreenForCrtc(crtc.window, crtc.crtc);
+ qCDebug(lcQpaScreen) << "QXcbConnection: XCB_RANDR_NOTIFY_CRTC_CHANGE:" << crtc.crtc
+ << "mode" << crtc.mode << "relevant screen" << screen;
+ // Only update geometry when there's a valid mode on the CRTC
+ // CRTC with node mode could mean that output has been disabled, and we'll
+ // get RRNotifyOutputChange notification for that.
+ if (screen && crtc.mode) {
+ if (crtc.rotation == XCB_RANDR_ROTATION_ROTATE_90 ||
+ crtc.rotation == XCB_RANDR_ROTATION_ROTATE_270)
+ std::swap(crtc.width, crtc.height);
+ screen->updateGeometry(QRect(crtc.x, crtc.y, crtc.width, crtc.height), crtc.rotation);
+ if (screen->mode() != crtc.mode)
+ screen->updateRefreshRate(crtc.mode);
+ }
+
+ } else if (event->subCode == XCB_RANDR_NOTIFY_OUTPUT_CHANGE) {
+ xcb_randr_output_change_t output = event->u.oc;
+ QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(output.window);
+ if (!virtualDesktop)
+ // Not for us
+ return;
+
+ QXcbScreen *screen = findScreenForOutput(output.window, output.output);
+ qCDebug(lcQpaScreen) << "QXcbConnection: XCB_RANDR_NOTIFY_OUTPUT_CHANGE:" << output.output;
+
+ if (screen && output.connection == XCB_RANDR_CONNECTION_DISCONNECTED) {
+ qCDebug(lcQpaScreen) << "screen" << screen->name() << "has been disconnected";
+ destroyScreen(screen);
+ } else if (!screen && output.connection == XCB_RANDR_CONNECTION_CONNECTED) {
+ // New XRandR output is available and it's enabled
+ if (output.crtc != XCB_NONE && output.mode != XCB_NONE) {
+ auto outputInfo = Q_XCB_REPLY(xcb_randr_get_output_info, xcb_connection(),
+ output.output, output.config_timestamp);
+ // Find a fake screen
+ const auto scrs = virtualDesktop->screens();
+ for (QPlatformScreen *scr : scrs) {
+ QXcbScreen *xcbScreen = static_cast<QXcbScreen *>(scr);
+ if (xcbScreen->output() == XCB_NONE) {
+ screen = xcbScreen;
+ break;
+ }
+ }
+
+ if (screen) {
+ QString nameWas = screen->name();
+ // Transform the fake screen into a physical screen
+ screen->setOutput(output.output, outputInfo.get());
+ updateScreen(screen, output);
+ qCDebug(lcQpaScreen) << "output" << screen->name()
+ << "is connected and enabled; was fake:" << nameWas;
+ } else {
+ screen = createScreen(virtualDesktop, output, outputInfo.get());
+ qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled";
+ }
+ QHighDpiScaling::updateHighDpiScaling();
+ }
+ } else if (screen) {
+ if (output.crtc == XCB_NONE && output.mode == XCB_NONE) {
+ // Screen has been disabled
+ auto outputInfo = Q_XCB_REPLY(xcb_randr_get_output_info, xcb_connection(),
+ output.output, output.config_timestamp);
+ if (outputInfo->crtc == XCB_NONE) {
+ qCDebug(lcQpaScreen) << "output" << screen->name() << "has been disabled";
+ destroyScreen(screen);
+ } else {
+ qCDebug(lcQpaScreen) << "output" << screen->name() << "has been temporarily disabled for the mode switch";
+ // Reset crtc to skip RRCrtcChangeNotify events,
+ // because they may be invalid in the middle of the mode switch
+ screen->setCrtc(XCB_NONE);
+ }
+ } else {
+ updateScreen(screen, output);
+ qCDebug(lcQpaScreen) << "output has changed" << screen;
+ }
+ }
+
+ qCDebug(lcQpaScreen) << "primary output is" << qAsConst(m_screens).first()->name();
+ }
+}
+
+bool QXcbConnection::checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output)
+{
+ auto primary = Q_XCB_REPLY(xcb_randr_get_output_primary, xcb_connection(), rootWindow);
+ if (!primary)
+ qWarning("failed to get the primary output of the screen");
+
+ const bool isPrimary = primary ? (primary->output == output) : false;
+
+ return isPrimary;
+}
+
+void QXcbConnection::updateScreen(QXcbScreen *screen, const xcb_randr_output_change_t &outputChange)
+{
+ screen->setCrtc(outputChange.crtc); // Set the new crtc, because it can be invalid
+ screen->updateGeometry(outputChange.config_timestamp);
+ if (screen->mode() != outputChange.mode)
+ screen->updateRefreshRate(outputChange.mode);
+ // Only screen which belongs to the primary virtual desktop can be a primary screen
+ if (screen->screenNumber() == primaryScreenNumber()) {
+ if (!screen->isPrimary() && checkOutputIsPrimary(outputChange.window, outputChange.output)) {
+ screen->setPrimary(true);
+
+ // If the screen became primary, reshuffle the order in QGuiApplicationPrivate
+ const int idx = m_screens.indexOf(screen);
+ if (idx > 0) {
+ qAsConst(m_screens).first()->setPrimary(false);
+ m_screens.swap(0, idx);
+ }
+ screen->virtualDesktop()->setPrimaryScreen(screen);
+ QXcbIntegration::instance()->setPrimaryScreen(screen);
+ }
+ }
+}
+
+QXcbScreen *QXcbConnection::createScreen(QXcbVirtualDesktop *virtualDesktop,
+ const xcb_randr_output_change_t &outputChange,
+ xcb_randr_get_output_info_reply_t *outputInfo)
+{
+ QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, outputChange.output, outputInfo);
+ // Only screen which belongs to the primary virtual desktop can be a primary screen
+ if (screen->screenNumber() == primaryScreenNumber())
+ screen->setPrimary(checkOutputIsPrimary(outputChange.window, outputChange.output));
+
+ if (screen->isPrimary()) {
+ if (!m_screens.isEmpty())
+ qAsConst(m_screens).first()->setPrimary(false);
+
+ m_screens.prepend(screen);
+ } else {
+ m_screens.append(screen);
+ }
+ virtualDesktop->addScreen(screen);
+ QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
+
+ return screen;
+}
+
+void QXcbConnection::destroyScreen(QXcbScreen *screen)
+{
+ QXcbVirtualDesktop *virtualDesktop = screen->virtualDesktop();
+ if (virtualDesktop->screens().count() == 1) {
+ // If there are no other screens on the same virtual desktop,
+ // then transform the physical screen into a fake screen.
+ const QString nameWas = screen->name();
+ screen->setOutput(XCB_NONE, nullptr);
+ qCDebug(lcQpaScreen) << "transformed" << nameWas << "to fake" << screen;
+ } else {
+ // There is more than one screen on the same virtual desktop, remove the screen
+ m_screens.removeOne(screen);
+ virtualDesktop->removeScreen(screen);
+
+ // When primary screen is removed, set the new primary screen
+ // which belongs to the primary virtual desktop.
+ if (screen->isPrimary()) {
+ QXcbScreen *newPrimary = static_cast<QXcbScreen *>(virtualDesktop->screens().at(0));
+ newPrimary->setPrimary(true);
+ const int idx = m_screens.indexOf(newPrimary);
+ if (idx > 0)
+ m_screens.swap(0, idx);
+ QXcbIntegration::instance()->setPrimaryScreen(newPrimary);
+ }
+
+ QXcbIntegration::instance()->destroyScreen(screen);
+ }
+}
+
+void QXcbConnection::initializeScreens()
+{
+ xcb_screen_iterator_t it = xcb_setup_roots_iterator(setup());
+ int xcbScreenNumber = 0; // screen number in the xcb sense
+ QXcbScreen *primaryScreen = nullptr;
+ while (it.rem) {
+ // Each "screen" in xcb terminology is a virtual desktop,
+ // potentially a collection of separate juxtaposed monitors.
+ // But we want a separate QScreen for each output (e.g. DVI-I-1, VGA-1, etc.)
+ // which will become virtual siblings.
+ xcb_screen_t *xcbScreen = it.data;
+ QXcbVirtualDesktop *virtualDesktop = new QXcbVirtualDesktop(this, xcbScreen, xcbScreenNumber);
+ m_virtualDesktops.append(virtualDesktop);
+ QList<QPlatformScreen *> siblings;
+ if (hasXRandr()) {
+ // RRGetScreenResourcesCurrent is fast but it may return nothing if the
+ // configuration is not initialized wrt to the hardware. We should call
+ // RRGetScreenResources in this case.
+ auto resources_current = Q_XCB_REPLY(xcb_randr_get_screen_resources_current,
+ xcb_connection(), xcbScreen->root);
+ if (!resources_current) {
+ qWarning("failed to get the current screen resources");
+ } else {
+ xcb_timestamp_t timestamp = 0;
+ xcb_randr_output_t *outputs = nullptr;
+ int outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources_current.get());
+ if (outputCount) {
+ timestamp = resources_current->config_timestamp;
+ outputs = xcb_randr_get_screen_resources_current_outputs(resources_current.get());
+ } else {
+ auto resources = Q_XCB_REPLY(xcb_randr_get_screen_resources,
+ xcb_connection(), xcbScreen->root);
+ if (!resources) {
+ qWarning("failed to get the screen resources");
+ } else {
+ timestamp = resources->config_timestamp;
+ outputCount = xcb_randr_get_screen_resources_outputs_length(resources.get());
+ outputs = xcb_randr_get_screen_resources_outputs(resources.get());
+ }
+ }
+
+ if (outputCount) {
+ auto primary = Q_XCB_REPLY(xcb_randr_get_output_primary, xcb_connection(), xcbScreen->root);
+ if (!primary) {
+ qWarning("failed to get the primary output of the screen");
+ } else {
+ for (int i = 0; i < outputCount; i++) {
+ auto output = Q_XCB_REPLY_UNCHECKED(xcb_randr_get_output_info,
+ xcb_connection(), outputs[i], timestamp);
+ // Invalid, disconnected or disabled output
+ if (!output)
+ continue;
+
+ if (output->connection != XCB_RANDR_CONNECTION_CONNECTED) {
+ qCDebug(lcQpaScreen, "Output %s is not connected", qPrintable(
+ QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.get()),
+ xcb_randr_get_output_info_name_length(output.get()))));
+ continue;
+ }
+
+ if (output->crtc == XCB_NONE) {
+ qCDebug(lcQpaScreen, "Output %s is not enabled", qPrintable(
+ QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.get()),
+ xcb_randr_get_output_info_name_length(output.get()))));
+ continue;
+ }
+
+ QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, outputs[i], output.get());
+ siblings << screen;
+ m_screens << screen;
+
+ // There can be multiple outputs per screen, use either
+ // the first or an exact match. An exact match isn't
+ // always available if primary->output is XCB_NONE
+ // or currently disconnected output.
+ if (primaryScreenNumber() == xcbScreenNumber) {
+ if (!primaryScreen || (primary && outputs[i] == primary->output)) {
+ if (primaryScreen)
+ primaryScreen->setPrimary(false);
+ primaryScreen = screen;
+ primaryScreen->setPrimary(true);
+ siblings.prepend(siblings.takeLast());
+ }
+ }
+ }
+ }
+ }
+ }
+ } else if (hasXinerama()) {
+ // Xinerama is available
+ auto screens = Q_XCB_REPLY(xcb_xinerama_query_screens, xcb_connection());
+ if (screens) {
+ xcb_xinerama_screen_info_iterator_t it = xcb_xinerama_query_screens_screen_info_iterator(screens.get());
+ while (it.rem) {
+ xcb_xinerama_screen_info_t *screen_info = it.data;
+ QXcbScreen *screen = new QXcbScreen(this, virtualDesktop,
+ XCB_NONE, nullptr,
+ screen_info, it.index);
+ siblings << screen;
+ m_screens << screen;
+ xcb_xinerama_screen_info_next(&it);
+ }
+ }
+ }
+ if (siblings.isEmpty()) {
+ // If there are no XRandR outputs or XRandR extension is missing,
+ // then create a fake/legacy screen.
+ QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, XCB_NONE, nullptr);
+ qCDebug(lcQpaScreen) << "created fake screen" << screen;
+ m_screens << screen;
+ if (primaryScreenNumber() == xcbScreenNumber) {
+ primaryScreen = screen;
+ primaryScreen->setPrimary(true);
+ }
+ siblings << screen;
+ }
+ virtualDesktop->setScreens(siblings);
+ xcb_screen_next(&it);
+ ++xcbScreenNumber;
+ } // for each xcb screen
+
+ for (QXcbVirtualDesktop *virtualDesktop : qAsConst(m_virtualDesktops))
+ virtualDesktop->subscribeToXFixesSelectionNotify();
+
+ if (m_virtualDesktops.isEmpty()) {
+ qFatal("QXcbConnection: no screens available");
+ } else {
+ // Ensure the primary screen is first on the list
+ if (primaryScreen) {
+ if (qAsConst(m_screens).first() != primaryScreen) {
+ m_screens.removeOne(primaryScreen);
+ m_screens.prepend(primaryScreen);
+ }
+ }
+
+ // Push the screens to QGuiApplication
+ for (QXcbScreen *screen : qAsConst(m_screens)) {
+ qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ")";
+ QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
+ }
+
+ qCDebug(lcQpaScreen) << "primary output is" << qAsConst(m_screens).first()->name();
+ }
+}
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index 6a5248b8f1..04ddd3c98c 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -47,59 +47,26 @@
#include <QDebug>
#include <cmath>
-#include <X11/extensions/XInput2.h>
-#include <X11/extensions/XI2proto.h>
+#include <xcb/xinput.h>
-void QXcbConnection::initializeXInput2()
-{
- Display *xDisplay = static_cast<Display *>(m_xlib_display);
- if (XQueryExtension(xDisplay, "XInputExtension", &m_xiOpCode, &m_xiEventBase, &m_xiErrorBase)) {
- int xiMajor = 2;
-#if defined(XCB_USE_XINPUT22)
- m_xi2Minor = 2; // for touch support 2.2 is enough
-#elif defined(XCB_USE_XINPUT21)
- m_xi2Minor = 1; // for smooth scrolling 2.1 is enough
-#else
- m_xi2Minor = 0; // for tablet support 2.0 is enough
-#endif
- qCDebug(lcQpaXInput, "Plugin build with support for XInput 2 version up "
- "to %d.%d", xiMajor, m_xi2Minor);
-
- switch (XIQueryVersion(xDisplay, &xiMajor, &m_xi2Minor)) {
- case Success:
- // Server's supported version can be lower than the version we have
- // announced to support. In this case Qt client will be limited by
- // X server's supported version.
- qCDebug(lcQpaXInput, "Using XInput version %d.%d", xiMajor, m_xi2Minor);
- m_xi2Enabled = true;
- xi2SetupDevices();
- xi2SelectStateEvents();
- break;
- case BadRequest: // Must be an X server with XInput 1
- qCDebug(lcQpaXInput, "X server does not support XInput 2");
- break;
- default: // BadValue
- qCDebug(lcQpaXInput, "Internal error");
- break;
- }
- }
-}
+using qt_xcb_input_device_event_t = xcb_input_button_press_event_t;
+
+struct qt_xcb_input_event_mask_t {
+ xcb_input_event_mask_t header;
+ uint32_t mask;
+};
void QXcbConnection::xi2SelectStateEvents()
{
// These state events do not depend on a specific X window, but are global
// for the X client's (application's) state.
- unsigned int bitMask = 0;
- unsigned char *xiBitMask = reinterpret_cast<unsigned char *>(&bitMask);
- XIEventMask xiEventMask;
- bitMask = XI_HierarchyChangedMask;
- bitMask |= XI_DeviceChangedMask;
- bitMask |= XI_PropertyEventMask;
- xiEventMask.deviceid = XIAllDevices;
- xiEventMask.mask_len = sizeof(bitMask);
- xiEventMask.mask = xiBitMask;
- Display *dpy = static_cast<Display *>(m_xlib_display);
- XISelectEvents(dpy, DefaultRootWindow(dpy), &xiEventMask, 1);
+ qt_xcb_input_event_mask_t xiEventMask;
+ xiEventMask.header.deviceid = XCB_INPUT_DEVICE_ALL;
+ xiEventMask.header.mask_len = 1;
+ xiEventMask.mask = XCB_INPUT_XI_EVENT_MASK_HIERARCHY;
+ xiEventMask.mask |= XCB_INPUT_XI_EVENT_MASK_DEVICE_CHANGED;
+ xiEventMask.mask |= XCB_INPUT_XI_EVENT_MASK_PROPERTY;
+ xcb_input_xi_select_events(xcb_connection(), rootWindow(), 1, &xiEventMask.header);
}
void QXcbConnection::xi2SelectDeviceEvents(xcb_window_t window)
@@ -107,38 +74,42 @@ void QXcbConnection::xi2SelectDeviceEvents(xcb_window_t window)
if (window == rootWindow())
return;
- unsigned int bitMask = 0;
- unsigned char *xiBitMask = reinterpret_cast<unsigned char *>(&bitMask);
- bitMask |= XI_ButtonPressMask;
- bitMask |= XI_ButtonReleaseMask;
- bitMask |= XI_MotionMask;
+ uint32_t bitMask = XCB_INPUT_XI_EVENT_MASK_BUTTON_PRESS;
+ bitMask |= XCB_INPUT_XI_EVENT_MASK_BUTTON_RELEASE;
+ bitMask |= XCB_INPUT_XI_EVENT_MASK_MOTION;
// There is a check for enter/leave events in plain xcb enter/leave event handler,
// core enter/leave events will be ignored in this case.
- bitMask |= XI_EnterMask;
- bitMask |= XI_LeaveMask;
-#ifdef XCB_USE_XINPUT22
+ bitMask |= XCB_INPUT_XI_EVENT_MASK_ENTER;
+ bitMask |= XCB_INPUT_XI_EVENT_MASK_LEAVE;
if (isAtLeastXI22()) {
- bitMask |= XI_TouchBeginMask;
- bitMask |= XI_TouchUpdateMask;
- bitMask |= XI_TouchEndMask;
+ bitMask |= XCB_INPUT_XI_EVENT_MASK_TOUCH_BEGIN;
+ bitMask |= XCB_INPUT_XI_EVENT_MASK_TOUCH_UPDATE;
+ bitMask |= XCB_INPUT_XI_EVENT_MASK_TOUCH_END;
}
-#endif
- XIEventMask mask;
- mask.mask_len = sizeof(bitMask);
- mask.mask = xiBitMask;
- mask.deviceid = XIAllMasterDevices;
- Display *dpy = static_cast<Display *>(m_xlib_display);
- Status result = XISelectEvents(dpy, window, &mask, 1);
- if (result == Success)
+ qt_xcb_input_event_mask_t mask;
+ mask.header.deviceid = XCB_INPUT_DEVICE_ALL_MASTER;
+ mask.header.mask_len = 1;
+ mask.mask = bitMask;
+ xcb_void_cookie_t cookie =
+ xcb_input_xi_select_events_checked(xcb_connection(), window, 1, &mask.header);
+ xcb_generic_error_t *error = xcb_request_check(xcb_connection(), cookie);
+ if (error) {
+ qCDebug(lcQpaXInput, "failed to select events, window %x, error code %d", window, error->error_code);
+ free(error);
+ } else {
QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false);
- else
- qCDebug(lcQpaXInput, "failed to select events, window %x, result %d", window, result);
+ }
+}
+
+static inline qreal fixed3232ToReal(xcb_input_fp3232_t val)
+{
+ return qreal(val.integral) + qreal(val.frac) / (1ULL << 32);
}
void QXcbConnection::xi2SetupDevice(void *info, bool removeExisting)
{
- XIDeviceInfo *deviceInfo = reinterpret_cast<XIDeviceInfo *>(info);
+ auto *deviceInfo = reinterpret_cast<xcb_input_xi_device_info_t *>(info);
if (removeExisting) {
#if QT_CONFIG(tabletevent)
for (int i = 0; i < m_tabletData.count(); ++i) {
@@ -152,53 +123,54 @@ void QXcbConnection::xi2SetupDevice(void *info, bool removeExisting)
m_touchDevices.remove(deviceInfo->deviceid);
}
- qCDebug(lcQpaXInputDevices) << "input device " << deviceInfo->name << "ID" << deviceInfo->deviceid;
+ qCDebug(lcQpaXInputDevices) << "input device " << xcb_input_xi_device_info_name(deviceInfo) << "ID" << deviceInfo->deviceid;
#if QT_CONFIG(tabletevent)
TabletData tabletData;
#endif
ScrollingDevice scrollingDevice;
- for (int c = 0; c < deviceInfo->num_classes; ++c) {
- XIAnyClassInfo *classinfo = deviceInfo->classes[c];
+ auto classes_it = xcb_input_xi_device_info_classes_iterator(deviceInfo);
+ for (; classes_it.rem; xcb_input_device_class_next(&classes_it)) {
+ xcb_input_device_class_t *classinfo = classes_it.data;
switch (classinfo->type) {
- case XIValuatorClass: {
- XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo);
+ case XCB_INPUT_DEVICE_CLASS_TYPE_VALUATOR: {
+ auto *vci = reinterpret_cast<xcb_input_valuator_class_t *>(classinfo);
const int valuatorAtom = qatom(vci->label);
qCDebug(lcQpaXInputDevices) << " has valuator" << atomName(vci->label) << "recognized?" << (valuatorAtom < QXcbAtom::NAtoms);
#if QT_CONFIG(tabletevent)
if (valuatorAtom < QXcbAtom::NAtoms) {
TabletData::ValuatorClassInfo info;
- info.minVal = vci->min;
- info.maxVal = vci->max;
+ info.minVal = fixed3232ToReal(vci->min);
+ info.maxVal = fixed3232ToReal(vci->max);
info.number = vci->number;
tabletData.valuatorInfo[valuatorAtom] = info;
}
#endif // QT_CONFIG(tabletevent)
if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel)
- scrollingDevice.lastScrollPosition.setX(vci->value);
+ scrollingDevice.lastScrollPosition.setX(fixed3232ToReal(vci->value));
else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel)
- scrollingDevice.lastScrollPosition.setY(vci->value);
+ scrollingDevice.lastScrollPosition.setY(fixed3232ToReal(vci->value));
break;
}
-#ifdef XCB_USE_XINPUT21
- case XIScrollClass: {
- XIScrollClassInfo *sci = reinterpret_cast<XIScrollClassInfo *>(classinfo);
- if (sci->scroll_type == XIScrollTypeVertical) {
+ case XCB_INPUT_DEVICE_CLASS_TYPE_SCROLL: {
+ auto *sci = reinterpret_cast<xcb_input_scroll_class_t *>(classinfo);
+ if (sci->scroll_type == XCB_INPUT_SCROLL_TYPE_VERTICAL) {
scrollingDevice.orientations |= Qt::Vertical;
scrollingDevice.verticalIndex = sci->number;
- scrollingDevice.verticalIncrement = sci->increment;
- }
- else if (sci->scroll_type == XIScrollTypeHorizontal) {
+ scrollingDevice.verticalIncrement = fixed3232ToReal(sci->increment);
+ } else if (sci->scroll_type == XCB_INPUT_SCROLL_TYPE_HORIZONTAL) {
scrollingDevice.orientations |= Qt::Horizontal;
scrollingDevice.horizontalIndex = sci->number;
- scrollingDevice.horizontalIncrement = sci->increment;
+ scrollingDevice.horizontalIncrement = fixed3232ToReal(sci->increment);
}
break;
}
- case XIButtonClass: {
- XIButtonClassInfo *bci = reinterpret_cast<XIButtonClassInfo *>(classinfo);
+ case XCB_INPUT_DEVICE_CLASS_TYPE_BUTTON: {
+ auto *bci = reinterpret_cast<xcb_input_button_class_t *>(classinfo);
+ xcb_atom_t *labels = 0;
if (bci->num_buttons >= 5) {
- Atom label4 = bci->labels[3];
- Atom label5 = bci->labels[4];
+ labels = xcb_input_button_class_labels(bci);
+ xcb_atom_t label4 = labels[3];
+ xcb_atom_t label5 = labels[4];
// Some drivers have no labels on the wheel buttons, some have no label on just one and some have no label on
// button 4 and the wrong one on button 5. So we just check that they are not labelled with unrelated buttons.
if ((!label4 || qatom(label4) == QXcbAtom::ButtonWheelUp || qatom(label4) == QXcbAtom::ButtonWheelDown) &&
@@ -206,23 +178,20 @@ void QXcbConnection::xi2SetupDevice(void *info, bool removeExisting)
scrollingDevice.legacyOrientations |= Qt::Vertical;
}
if (bci->num_buttons >= 7) {
- Atom label6 = bci->labels[5];
- Atom label7 = bci->labels[6];
+ xcb_atom_t label6 = labels[5];
+ xcb_atom_t label7 = labels[6];
if ((!label6 || qatom(label6) == QXcbAtom::ButtonHorizWheelLeft) && (!label7 || qatom(label7) == QXcbAtom::ButtonHorizWheelRight))
scrollingDevice.legacyOrientations |= Qt::Horizontal;
}
qCDebug(lcQpaXInputDevices, " has %d buttons", bci->num_buttons);
break;
}
-#endif
- case XIKeyClass:
+ case XCB_INPUT_DEVICE_CLASS_TYPE_KEY:
qCDebug(lcQpaXInputDevices) << " it's a keyboard";
break;
-#ifdef XCB_USE_XINPUT22
- case XITouchClass:
+ case XCB_INPUT_DEVICE_CLASS_TYPE_TOUCH:
// will be handled in populateTouchDevices()
break;
-#endif
default:
qCDebug(lcQpaXInputDevices) << " has class" << classinfo->type;
break;
@@ -237,7 +206,8 @@ void QXcbConnection::xi2SetupDevice(void *info, bool removeExisting)
isTablet = true;
// But we need to be careful not to take the touch and tablet-button devices as tablets.
- QByteArray name = QByteArray(deviceInfo->name).toLower();
+ QByteArray name = QByteArray(xcb_input_xi_device_info_name(deviceInfo),
+ xcb_input_xi_device_info_name_length(deviceInfo)).toLower();
QString dbgType = QLatin1String("UNKNOWN");
if (name.contains("eraser")) {
isTablet = true;
@@ -281,7 +251,6 @@ void QXcbConnection::xi2SetupDevice(void *info, bool removeExisting)
}
#endif // QT_CONFIG(tabletevent)
-#ifdef XCB_USE_XINPUT21
if (scrollingDevice.orientations || scrollingDevice.legacyOrientations) {
scrollingDevice.deviceId = deviceInfo->deviceid;
// Only use legacy wheel button events when we don't have real scroll valuators.
@@ -289,7 +258,6 @@ void QXcbConnection::xi2SetupDevice(void *info, bool removeExisting)
m_scrollingDevices.insert(scrollingDevice.deviceId, scrollingDevice);
qCDebug(lcQpaXInputDevices) << " it's a scrolling device";
}
-#endif
if (!isTablet) {
TouchDeviceData *dev = populateTouchDevices(deviceInfo);
@@ -315,23 +283,28 @@ void QXcbConnection::xi2SetupDevices()
#endif
m_scrollingDevices.clear();
m_touchDevices.clear();
-
- Display *xDisplay = static_cast<Display *>(m_xlib_display);
- int deviceCount = 0;
- XIDeviceInfo *devices = XIQueryDevice(xDisplay, XIAllDevices, &deviceCount);
m_xiMasterPointerIds.clear();
- for (int i = 0; i < deviceCount; ++i) {
- XIDeviceInfo deviceInfo = devices[i];
- if (deviceInfo.use == XIMasterPointer) {
- m_xiMasterPointerIds.append(deviceInfo.deviceid);
+
+ auto reply = Q_XCB_REPLY(xcb_input_xi_query_device, xcb_connection(), XCB_INPUT_DEVICE_ALL);
+ if (!reply) {
+ qCDebug(lcQpaXInputDevices) << "failed to query devices";
+ return;
+ }
+
+ auto it = xcb_input_xi_query_device_infos_iterator(reply.get());
+ for (; it.rem; xcb_input_xi_device_info_next(&it)) {
+ xcb_input_xi_device_info_t *deviceInfo = it.data;
+ if (deviceInfo->type == XCB_INPUT_DEVICE_TYPE_MASTER_POINTER) {
+ m_xiMasterPointerIds.append(deviceInfo->deviceid);
continue;
}
- if (deviceInfo.use == XISlavePointer) // only slave pointer devices are relevant here
- xi2SetupDevice(&deviceInfo, false);
+ // only slave pointer devices are relevant here
+ if (deviceInfo->type == XCB_INPUT_DEVICE_TYPE_SLAVE_POINTER)
+ xi2SetupDevice(deviceInfo, false);
}
+
if (m_xiMasterPointerIds.size() > 1)
qCDebug(lcQpaXInputDevices) << "multi-pointer X detected";
- XIFreeDeviceInfo(devices);
}
/*! \internal
@@ -376,70 +349,64 @@ void QXcbConnection::xi2SelectDeviceEventsCompatibility(xcb_window_t window)
if (window == rootWindow())
return;
- unsigned int mask = 0;
- unsigned char *bitMask = reinterpret_cast<unsigned char *>(&mask);
- Display *dpy = static_cast<Display *>(m_xlib_display);
+ uint32_t mask = 0;
-#ifdef XCB_USE_XINPUT22
if (isAtLeastXI22()) {
- mask |= XI_TouchBeginMask;
- mask |= XI_TouchUpdateMask;
- mask |= XI_TouchEndMask;
-
- XIEventMask xiMask;
- xiMask.mask_len = sizeof(mask);
- xiMask.mask = bitMask;
- xiMask.deviceid = XIAllMasterDevices;
- Status result = XISelectEvents(dpy, window, &xiMask, 1);
- if (result == Success)
+ mask |= XCB_INPUT_XI_EVENT_MASK_TOUCH_BEGIN;
+ mask |= XCB_INPUT_XI_EVENT_MASK_TOUCH_UPDATE;
+ mask |= XCB_INPUT_XI_EVENT_MASK_TOUCH_END;
+
+ qt_xcb_input_event_mask_t xiMask;
+ xiMask.header.deviceid = XCB_INPUT_DEVICE_ALL_MASTER;
+ xiMask.header.mask_len = 1;
+ xiMask.mask = mask;
+
+ xcb_void_cookie_t cookie =
+ xcb_input_xi_select_events_checked(xcb_connection(), window, 1, &xiMask.header);
+ xcb_generic_error_t *error = xcb_request_check(xcb_connection(), cookie);
+ if (error) {
+ qCDebug(lcQpaXInput, "failed to select events, window %x, error code %d", window, error->error_code);
+ free(error);
+ } else {
QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false);
- else
- qCDebug(lcQpaXInput, "failed to select events, window %x, result %d", window, result);
+ }
}
-#endif
- mask = XI_ButtonPressMask;
- mask |= XI_ButtonReleaseMask;
- mask |= XI_MotionMask;
+ mask = XCB_INPUT_XI_EVENT_MASK_BUTTON_PRESS;
+ mask |= XCB_INPUT_XI_EVENT_MASK_BUTTON_RELEASE;
+ mask |= XCB_INPUT_XI_EVENT_MASK_MOTION;
#if QT_CONFIG(tabletevent)
QSet<int> tabletDevices;
if (!m_tabletData.isEmpty()) {
const int nrTablets = m_tabletData.count();
- QVector<XIEventMask> xiEventMask(nrTablets);
+ QVector<qt_xcb_input_event_mask_t> xiEventMask(nrTablets);
for (int i = 0; i < nrTablets; ++i) {
int deviceId = m_tabletData.at(i).deviceId;
tabletDevices.insert(deviceId);
- xiEventMask[i].deviceid = deviceId;
- xiEventMask[i].mask_len = sizeof(mask);
- xiEventMask[i].mask = bitMask;
+ xiEventMask[i].header.deviceid = deviceId;
+ xiEventMask[i].header.mask_len = 1;
+ xiEventMask[i].mask = mask;
}
- XISelectEvents(dpy, window, xiEventMask.data(), nrTablets);
+ xcb_input_xi_select_events(xcb_connection(), window, nrTablets, &(xiEventMask.data()->header));
}
#endif
-#ifdef XCB_USE_XINPUT21
if (!m_scrollingDevices.isEmpty()) {
- QVector<XIEventMask> xiEventMask(m_scrollingDevices.size());
+ QVector<qt_xcb_input_event_mask_t> xiEventMask(m_scrollingDevices.size());
int i = 0;
for (const ScrollingDevice& scrollingDevice : qAsConst(m_scrollingDevices)) {
#if QT_CONFIG(tabletevent)
if (tabletDevices.contains(scrollingDevice.deviceId))
continue; // All necessary events are already captured.
#endif
- xiEventMask[i].deviceid = scrollingDevice.deviceId;
- xiEventMask[i].mask_len = sizeof(mask);
- xiEventMask[i].mask = bitMask;
+ xiEventMask[i].header.deviceid = scrollingDevice.deviceId;
+ xiEventMask[i].header.mask_len = 1;
+ xiEventMask[i].mask = mask;
i++;
}
- XISelectEvents(dpy, window, xiEventMask.data(), i);
+ xcb_input_xi_select_events(xcb_connection(), window, i, &(xiEventMask.data()->header));
}
-#endif
-
-#if !QT_CONFIG(tabletevent) && !defined(XCB_USE_XINPUT21)
- Q_UNUSED(bitMask);
- Q_UNUSED(dpy);
-#endif
}
QXcbConnection::TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
@@ -452,39 +419,38 @@ QXcbConnection::TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
QXcbConnection::TouchDeviceData *QXcbConnection::populateTouchDevices(void *info)
{
- XIDeviceInfo *deviceinfo = reinterpret_cast<XIDeviceInfo *>(info);
+ auto *deviceinfo = reinterpret_cast<xcb_input_xi_device_info_t *>(info);
QTouchDevice::Capabilities caps = 0;
int type = -1;
int maxTouchPoints = 1;
bool isTouchDevice = false;
bool hasRelativeCoords = false;
TouchDeviceData dev;
- for (int i = 0; i < deviceinfo->num_classes; ++i) {
- XIAnyClassInfo *classinfo = deviceinfo->classes[i];
+ auto classes_it = xcb_input_xi_device_info_classes_iterator(deviceinfo);
+ for (; classes_it.rem; xcb_input_device_class_next(&classes_it)) {
+ xcb_input_device_class_t *classinfo = classes_it.data;
switch (classinfo->type) {
-#ifdef XCB_USE_XINPUT22
- case XITouchClass: {
- XITouchClassInfo *tci = reinterpret_cast<XITouchClassInfo *>(classinfo);
+ case XCB_INPUT_DEVICE_CLASS_TYPE_TOUCH: {
+ auto *tci = reinterpret_cast<xcb_input_touch_class_t *>(classinfo);
maxTouchPoints = tci->num_touches;
qCDebug(lcQpaXInputDevices, " has touch class with mode %d", tci->mode);
switch (tci->mode) {
- case XIDependentTouch:
+ case XCB_INPUT_TOUCH_MODE_DEPENDENT:
type = QTouchDevice::TouchPad;
break;
- case XIDirectTouch:
+ case XCB_INPUT_TOUCH_MODE_DIRECT:
type = QTouchDevice::TouchScreen;
break;
}
break;
}
-#endif // XCB_USE_XINPUT22
- case XIValuatorClass: {
- XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo);
+ case XCB_INPUT_DEVICE_CLASS_TYPE_VALUATOR: {
+ auto *vci = reinterpret_cast<xcb_input_valuator_class_t *>(classinfo);
const QXcbAtom::Atom valuatorAtom = qatom(vci->label);
if (valuatorAtom < QXcbAtom::NAtoms) {
TouchDeviceData::ValuatorClassInfo info;
- info.min = vci->min;
- info.max = vci->max;
+ info.min = fixed3232ToReal(vci->min);
+ info.max = fixed3232ToReal(vci->max);
info.number = vci->number;
info.label = valuatorAtom;
dev.valuatorInfo.append(info);
@@ -502,16 +468,16 @@ QXcbConnection::TouchDeviceData *QXcbConnection::populateTouchDevices(void *info
caps |= QTouchDevice::Pressure;
else if (valuatorAtom == QXcbAtom::RelX) {
hasRelativeCoords = true;
- dev.size.setWidth((vci->max - vci->min) * 1000.0 / vciResolution);
+ dev.size.setWidth((fixed3232ToReal(vci->max) - fixed3232ToReal(vci->min)) * 1000.0 / vciResolution);
} else if (valuatorAtom == QXcbAtom::RelY) {
hasRelativeCoords = true;
- dev.size.setHeight((vci->max - vci->min) * 1000.0 / vciResolution);
+ dev.size.setHeight((fixed3232ToReal(vci->max) - fixed3232ToReal(vci->min)) * 1000.0 / vciResolution);
} else if (valuatorAtom == QXcbAtom::AbsX) {
caps |= QTouchDevice::Position;
- dev.size.setWidth((vci->max - vci->min) * 1000.0 / vciResolution);
+ dev.size.setWidth((fixed3232ToReal(vci->max) - fixed3232ToReal(vci->min)) * 1000.0 / vciResolution);
} else if (valuatorAtom == QXcbAtom::AbsY) {
caps |= QTouchDevice::Position;
- dev.size.setHeight((vci->max - vci->min) * 1000.0 / vciResolution);
+ dev.size.setHeight((fixed3232ToReal(vci->max) - fixed3232ToReal(vci->min)) * 1000.0 / vciResolution);
}
break;
}
@@ -530,7 +496,8 @@ QXcbConnection::TouchDeviceData *QXcbConnection::populateTouchDevices(void *info
if (type >= QTouchDevice::TouchScreen && type <= QTouchDevice::TouchPad) {
dev.qtTouchDevice = new QTouchDevice;
- dev.qtTouchDevice->setName(QString::fromUtf8(deviceinfo->name));
+ dev.qtTouchDevice->setName(QString::fromUtf8(xcb_input_xi_device_info_name(deviceinfo),
+ xcb_input_xi_device_info_name_length(deviceinfo)));
dev.qtTouchDevice->setType((QTouchDevice::DeviceType)type);
dev.qtTouchDevice->setCapabilities(caps);
dev.qtTouchDevice->setMaximumTouchPoints(maxTouchPoints);
@@ -543,89 +510,83 @@ QXcbConnection::TouchDeviceData *QXcbConnection::populateTouchDevices(void *info
return isTouchDevice ? &m_touchDevices[deviceinfo->deviceid] : nullptr;
}
-#if defined(XCB_USE_XINPUT21) || QT_CONFIG(tabletevent)
-static inline qreal fixed1616ToReal(FP1616 val)
+#if QT_CONFIG(tabletevent)
+static inline qreal fixed1616ToReal(xcb_input_fp1616_t val)
{
return qreal(val) / 0x10000;
}
-#endif // defined(XCB_USE_XINPUT21) || QT_CONFIG(tabletevent)
+#endif // QT_CONFIG(tabletevent)
void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
{
- xi2PrepareXIGenericDeviceEvent(event);
- xXIGenericDeviceEvent *xiEvent = reinterpret_cast<xXIGenericDeviceEvent *>(event);
+ auto *xiEvent = reinterpret_cast<qt_xcb_input_device_event_t *>(event);
int sourceDeviceId = xiEvent->deviceid; // may be the master id
- xXIDeviceEvent *xiDeviceEvent = 0;
- xXIEnterEvent *xiEnterEvent = 0;
+ qt_xcb_input_device_event_t *xiDeviceEvent = nullptr;
+ xcb_input_enter_event_t *xiEnterEvent = nullptr;
QXcbWindowEventListener *eventListener = 0;
- switch (xiEvent->evtype) {
- case XI_ButtonPress:
- case XI_ButtonRelease:
- case XI_Motion:
-#ifdef XCB_USE_XINPUT22
- case XI_TouchBegin:
- case XI_TouchUpdate:
- case XI_TouchEnd:
-#endif
+ switch (xiEvent->event_type) {
+ case XCB_INPUT_BUTTON_PRESS:
+ case XCB_INPUT_BUTTON_RELEASE:
+ case XCB_INPUT_MOTION:
+ case XCB_INPUT_TOUCH_BEGIN:
+ case XCB_INPUT_TOUCH_UPDATE:
+ case XCB_INPUT_TOUCH_END:
{
- xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event);
+ xiDeviceEvent = xiEvent;
eventListener = windowEventListenerFromId(xiDeviceEvent->event);
sourceDeviceId = xiDeviceEvent->sourceid; // use the actual device id instead of the master
break;
}
- case XI_Enter:
- case XI_Leave: {
- xiEnterEvent = reinterpret_cast<xXIEnterEvent *>(event);
+ case XCB_INPUT_ENTER:
+ case XCB_INPUT_LEAVE: {
+ xiEnterEvent = reinterpret_cast<xcb_input_enter_event_t *>(event);
eventListener = windowEventListenerFromId(xiEnterEvent->event);
sourceDeviceId = xiEnterEvent->sourceid; // use the actual device id instead of the master
break;
}
- case XI_HierarchyChanged:
- xi2HandleHierarchyEvent(xiEvent);
+ case XCB_INPUT_HIERARCHY:
+ xi2HandleHierarchyEvent(event);
return;
- case XI_DeviceChanged:
- xi2HandleDeviceChangedEvent(xiEvent);
+ case XCB_INPUT_DEVICE_CHANGED:
+ xi2HandleDeviceChangedEvent(event);
return;
default:
break;
}
if (eventListener) {
- long result = 0;
- if (eventListener->handleGenericEvent(reinterpret_cast<xcb_generic_event_t *>(event), &result))
+ if (eventListener->handleNativeEvent(reinterpret_cast<xcb_generic_event_t *>(event)))
return;
}
#if QT_CONFIG(tabletevent)
if (!xiEnterEvent) {
QXcbConnection::TabletData *tablet = tabletDataForDevice(sourceDeviceId);
- if (tablet && xi2HandleTabletEvent(xiEvent, tablet))
+ if (tablet && xi2HandleTabletEvent(event, tablet))
return;
}
#endif // QT_CONFIG(tabletevent)
-#ifdef XCB_USE_XINPUT21
if (ScrollingDevice *device = scrollingDeviceForId(sourceDeviceId))
- xi2HandleScrollEvent(xiEvent, *device);
-#endif // XCB_USE_XINPUT21
+ xi2HandleScrollEvent(event, *device);
-#ifdef XCB_USE_XINPUT22
if (xiDeviceEvent) {
- switch (xiDeviceEvent->evtype) {
- case XI_ButtonPress:
- case XI_ButtonRelease:
- case XI_Motion:
- if (!xi2MouseEventsDisabled() && eventListener && !(xiDeviceEvent->flags & XIPointerEmulated))
+ switch (xiDeviceEvent->event_type) {
+ case XCB_INPUT_BUTTON_PRESS:
+ case XCB_INPUT_BUTTON_RELEASE:
+ case XCB_INPUT_MOTION:
+ if (!xi2MouseEventsDisabled() && eventListener &&
+ !(xiDeviceEvent->flags & XCB_INPUT_POINTER_EVENT_FLAGS_POINTER_EMULATED))
eventListener->handleXIMouseEvent(event);
break;
- case XI_TouchBegin:
- case XI_TouchUpdate:
- case XI_TouchEnd:
+ case XCB_INPUT_TOUCH_BEGIN:
+ case XCB_INPUT_TOUCH_UPDATE:
+ case XCB_INPUT_TOUCH_END:
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
qCDebug(lcQpaXInputEvents, "XI2 touch event type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f on window %x",
- event->event_type, xiDeviceEvent->sequenceNumber, xiDeviceEvent->detail,
+ event->event_type, xiDeviceEvent->sequence, xiDeviceEvent->detail,
fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y),
fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y),xiDeviceEvent->event);
if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event))
@@ -633,14 +594,13 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
break;
}
} else if (xiEnterEvent && !xi2MouseEventsDisabled() && eventListener) {
- switch (xiEnterEvent->evtype) {
- case XI_Enter:
- case XI_Leave:
+ switch (xiEnterEvent->event_type) {
+ case XCB_INPUT_ENTER:
+ case XCB_INPUT_LEAVE:
eventListener->handleXIEnterLeave(event);
break;
}
}
-#endif // XCB_USE_XINPUT22
}
bool QXcbConnection::xi2MouseEventsDisabled() const
@@ -648,10 +608,9 @@ bool QXcbConnection::xi2MouseEventsDisabled() const
static bool xi2MouseDisabled = qEnvironmentVariableIsSet("QT_XCB_NO_XI2_MOUSE");
// FIXME: Don't use XInput2 mouse events when Xinerama extension
// is enabled, because it causes problems with multi-monitor setup.
- return xi2MouseDisabled || has_xinerama_extension;
+ return xi2MouseDisabled || hasXinerama();
}
-#ifdef XCB_USE_XINPUT22
bool QXcbConnection::isTouchScreen(int id)
{
auto device = touchDeviceForId(id);
@@ -660,11 +619,11 @@ bool QXcbConnection::isTouchScreen(int id)
void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindow)
{
- xXIDeviceEvent *xiDeviceEvent = static_cast<xXIDeviceEvent *>(xiDevEvent);
+ auto *xiDeviceEvent = reinterpret_cast<xcb_input_touch_begin_event_t *>(xiDevEvent);
TouchDeviceData *dev = touchDeviceForId(xiDeviceEvent->sourceid);
Q_ASSERT(dev);
const bool firstTouch = dev->touchPoints.isEmpty();
- if (xiDeviceEvent->evtype == XI_TouchBegin) {
+ if (xiDeviceEvent->event_type == XCB_INPUT_TOUCH_BEGIN) {
QWindowSystemInterface::TouchPoint tp;
tp.id = xiDeviceEvent->detail % INT_MAX;
tp.state = Qt::TouchPointPressed;
@@ -735,7 +694,7 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
y = touchPoint.area.center().y();
ny = y / screen->geometry().height();
}
- if (xiDeviceEvent->evtype != XI_TouchEnd) {
+ if (xiDeviceEvent->event_type != XCB_INPUT_TOUCH_END) {
if (!dev->providesTouchOrientation) {
if (w == 0.0)
w = touchPoint.area.width();
@@ -750,8 +709,8 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
}
}
- switch (xiDeviceEvent->evtype) {
- case XI_TouchBegin:
+ switch (xiDeviceEvent->event_type) {
+ case XCB_INPUT_TOUCH_BEGIN:
if (firstTouch) {
dev->firstPressedPosition = QPointF(x, y);
dev->firstPressedNormalPosition = QPointF(nx, ny);
@@ -761,14 +720,12 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
// Touches must be accepted when we are grabbing touch events. Otherwise the entire sequence
// will get replayed when the grab ends.
if (m_xiGrab) {
- // Note that XIAllowTouchEvents is known to deadlock with older libXi versions,
- // for details see qtbase/src/plugins/platforms/xcb/README. This has nothing to
- // do with the XInput protocol version, but is a bug in libXi implementation instead.
- XIAllowTouchEvents(static_cast<Display *>(m_xlib_display), xiDeviceEvent->deviceid,
- xiDeviceEvent->detail, xiDeviceEvent->event, XIAcceptTouch);
+ xcb_input_xi_allow_events(xcb_connection(), XCB_CURRENT_TIME, xiDeviceEvent->deviceid,
+ XCB_INPUT_EVENT_MODE_ACCEPT_TOUCH,
+ xiDeviceEvent->detail, xiDeviceEvent->event);
}
break;
- case XI_TouchUpdate:
+ case XCB_INPUT_TOUCH_UPDATE:
if (dev->qtTouchDevice->type() == QTouchDevice::TouchPad && dev->pointPressedPosition.value(touchPoint.id) == QPointF(x, y)) {
qreal dx = (nx - dev->firstPressedNormalPosition.x()) *
dev->size.width() * screen->geometry().width() / screen->physicalSize().width();
@@ -789,14 +746,15 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
xiDeviceEvent->detail == m_startSystemMoveResizeInfo.pointid) {
QXcbWindow *window = platformWindowFromId(m_startSystemMoveResizeInfo.window);
if (window) {
- XIAllowTouchEvents(static_cast<Display *>(m_xlib_display), xiDeviceEvent->deviceid,
- xiDeviceEvent->detail, xiDeviceEvent->event, XIRejectTouch);
+ xcb_input_xi_allow_events(xcb_connection(), XCB_CURRENT_TIME, xiDeviceEvent->deviceid,
+ XCB_INPUT_EVENT_MODE_REJECT_TOUCH,
+ xiDeviceEvent->detail, xiDeviceEvent->event);
window->doStartSystemMoveResize(QPoint(x, y), m_startSystemMoveResizeInfo.corner);
m_startSystemMoveResizeInfo.window = XCB_NONE;
}
}
break;
- case XI_TouchEnd:
+ case XCB_INPUT_TOUCH_END:
touchPoint.state = Qt::TouchPointReleased;
if (dev->qtTouchDevice->type() == QTouchDevice::TouchPad && dev->pointPressedPosition.value(touchPoint.id) == QPointF(x, y)) {
qreal dx = (nx - dev->firstPressedNormalPosition.x()) *
@@ -814,7 +772,7 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
qCDebug(lcQpaXInputEvents) << " touchpoint " << touchPoint.id << " state " << touchPoint.state << " pos norm " << touchPoint.normalPosition <<
" area " << touchPoint.area << " pressure " << touchPoint.pressure;
- Qt::KeyboardModifiers modifiers = keyboard()->translateModifiers(xiDeviceEvent->mods.effective_mods);
+ Qt::KeyboardModifiers modifiers = keyboard()->translateModifiers(xiDeviceEvent->mods.effective);
QWindowSystemInterface::handleTouchEvent(platformWindow->window(), xiDeviceEvent->time, dev->qtTouchDevice, dev->touchPoints.values(), modifiers);
if (touchPoint.state == Qt::TouchPointReleased)
// If a touchpoint was released, we can forget it, because the ID won't be reused.
@@ -850,46 +808,46 @@ void QXcbConnection::abortSystemMoveResizeForTouch()
{
m_startSystemMoveResizeInfo.window = XCB_NONE;
}
-#endif // XCB_USE_XINPUT22
bool QXcbConnection::xi2SetMouseGrabEnabled(xcb_window_t w, bool grab)
{
- Display *xDisplay = static_cast<Display *>(xlib_display());
bool ok = false;
if (grab) { // grab
- XIEventMask evmask;
- unsigned char mask[XIMaskLen(XI_LASTEVENT)];
- evmask.mask = mask;
- evmask.mask_len = sizeof(mask);
- memset(mask, 0, sizeof(mask));
- XISetMask(mask, XI_ButtonPress);
- XISetMask(mask, XI_ButtonRelease);
- XISetMask(mask, XI_Motion);
- XISetMask(mask, XI_Enter);
- XISetMask(mask, XI_Leave);
- XISetMask(mask, XI_TouchBegin);
- XISetMask(mask, XI_TouchUpdate);
- XISetMask(mask, XI_TouchEnd);
+ uint32_t mask = XCB_INPUT_XI_EVENT_MASK_BUTTON_PRESS
+ | XCB_INPUT_XI_EVENT_MASK_BUTTON_RELEASE
+ | XCB_INPUT_XI_EVENT_MASK_MOTION
+ | XCB_INPUT_XI_EVENT_MASK_ENTER
+ | XCB_INPUT_XI_EVENT_MASK_LEAVE
+ | XCB_INPUT_XI_EVENT_MASK_TOUCH_BEGIN
+ | XCB_INPUT_XI_EVENT_MASK_TOUCH_UPDATE
+ | XCB_INPUT_XI_EVENT_MASK_TOUCH_END;
for (int id : m_xiMasterPointerIds) {
- evmask.deviceid = id;
- Status result = XIGrabDevice(xDisplay, id, w, CurrentTime, None,
- XIGrabModeAsync, XIGrabModeAsync, False, &evmask);
- if (result != Success) {
+ xcb_generic_error_t *error = nullptr;
+ auto cookie = xcb_input_xi_grab_device(xcb_connection(), w, XCB_CURRENT_TIME, XCB_CURSOR_NONE, id,
+ XCB_INPUT_GRAB_MODE_22_ASYNC, XCB_INPUT_GRAB_MODE_22_ASYNC,
+ false, 1, &mask);
+ auto *reply = xcb_input_xi_grab_device_reply(xcb_connection(), cookie, &error);
+ if (error) {
qCDebug(lcQpaXInput, "failed to grab events for device %d on window %x"
- "(result %d)", id, w, result);
+ "(error code %d)", id, w, error->error_code);
+ free(error);
} else {
// Managed to grab at least one of master pointers, that should be enough
// to properly dismiss windows that rely on mouse grabbing.
ok = true;
}
+ free(reply);
}
} else { // ungrab
for (int id : m_xiMasterPointerIds) {
- Status result = XIUngrabDevice(xDisplay, id, CurrentTime);
- if (result != Success)
- qCDebug(lcQpaXInput, "XIUngrabDevice failed - id: %d (result %d)", id, result);
+ auto cookie = xcb_input_xi_ungrab_device_checked(xcb_connection(), XCB_CURRENT_TIME, id);
+ xcb_generic_error_t *error = xcb_request_check(xcb_connection(), cookie);
+ if (error) {
+ qCDebug(lcQpaXInput, "XIUngrabDevice failed - id: %d (error code %d)", id, error->error_code);
+ free(error);
+ }
}
// XIUngrabDevice does not seem to wait for a reply from X server (similar to
// xcb_ungrab_pointer). Ungrabbing won't fail, unless NoSuchExtension error
@@ -906,9 +864,9 @@ bool QXcbConnection::xi2SetMouseGrabEnabled(xcb_window_t w, bool grab)
void QXcbConnection::xi2HandleHierarchyEvent(void *event)
{
- xXIHierarchyEvent *xiEvent = reinterpret_cast<xXIHierarchyEvent *>(event);
+ auto *xiEvent = reinterpret_cast<xcb_input_hierarchy_event_t *>(event);
// We only care about hotplugged devices
- if (!(xiEvent->flags & (XISlaveRemoved | XISlaveAdded)))
+ if (!(xiEvent->flags & (XCB_INPUT_HIERARCHY_MASK_SLAVE_REMOVED | XCB_INPUT_HIERARCHY_MASK_SLAVE_ADDED)))
return;
xi2SetupDevices();
@@ -925,23 +883,19 @@ void QXcbConnection::xi2HandleHierarchyEvent(void *event)
void QXcbConnection::xi2HandleDeviceChangedEvent(void *event)
{
- xXIDeviceChangedEvent *xiEvent = reinterpret_cast<xXIDeviceChangedEvent *>(event);
+ auto *xiEvent = reinterpret_cast<xcb_input_device_changed_event_t *>(event);
switch (xiEvent->reason) {
- case XIDeviceChange: {
- int nrDevices = 0;
- Display *dpy = static_cast<Display *>(m_xlib_display);
- XIDeviceInfo* deviceInfo = XIQueryDevice(dpy, xiEvent->sourceid, &nrDevices);
- if (nrDevices <= 0)
+ case XCB_INPUT_CHANGE_REASON_DEVICE_CHANGE: {
+ auto reply = Q_XCB_REPLY(xcb_input_xi_query_device, xcb_connection(), xiEvent->sourceid);
+ if (!reply || reply->num_infos <= 0)
return;
- xi2SetupDevice(deviceInfo);
- XIFreeDeviceInfo(deviceInfo);
+ auto it = xcb_input_xi_query_device_infos_iterator(reply.get());
+ xi2SetupDevice(it.data);
break;
}
- case XISlaveSwitch: {
-#ifdef XCB_USE_XINPUT21
+ case XCB_INPUT_CHANGE_REASON_SLAVE_SWITCH: {
if (ScrollingDevice *scrollingDevice = scrollingDeviceForId(xiEvent->sourceid))
xi2UpdateScrollingDevice(*scrollingDevice);
-#endif
break;
}
default:
@@ -950,28 +904,28 @@ void QXcbConnection::xi2HandleDeviceChangedEvent(void *event)
}
}
-#ifdef XCB_USE_XINPUT21
void QXcbConnection::xi2UpdateScrollingDevice(ScrollingDevice &scrollingDevice)
{
- int nrDevices = 0;
- Display *dpy = static_cast<Display *>(m_xlib_display);
- XIDeviceInfo* deviceInfo = XIQueryDevice(dpy, scrollingDevice.deviceId, &nrDevices);
- if (nrDevices <= 0) {
+ auto reply = Q_XCB_REPLY(xcb_input_xi_query_device, xcb_connection(), scrollingDevice.deviceId);
+ if (!reply || reply->num_infos <= 0) {
qCDebug(lcQpaXInputDevices, "scrolling device %d no longer present", scrollingDevice.deviceId);
return;
}
QPointF lastScrollPosition;
if (lcQpaXInputEvents().isDebugEnabled())
lastScrollPosition = scrollingDevice.lastScrollPosition;
- for (int c = 0; c < deviceInfo->num_classes; ++c) {
- XIAnyClassInfo *classInfo = deviceInfo->classes[c];
- if (classInfo->type == XIValuatorClass) {
- XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classInfo);
+
+ xcb_input_xi_device_info_t *deviceInfo = xcb_input_xi_query_device_infos_iterator(reply.get()).data;
+ auto classes_it = xcb_input_xi_device_info_classes_iterator(deviceInfo);
+ for (; classes_it.rem; xcb_input_device_class_next(&classes_it)) {
+ xcb_input_device_class_t *classInfo = classes_it.data;
+ if (classInfo->type == XCB_INPUT_DEVICE_CLASS_TYPE_VALUATOR) {
+ auto *vci = reinterpret_cast<xcb_input_valuator_class_t *>(classInfo);
const int valuatorAtom = qatom(vci->label);
if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel)
- scrollingDevice.lastScrollPosition.setX(vci->value);
+ scrollingDevice.lastScrollPosition.setX(fixed3232ToReal(vci->value));
else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel)
- scrollingDevice.lastScrollPosition.setY(vci->value);
+ scrollingDevice.lastScrollPosition.setY(fixed3232ToReal(vci->value));
}
}
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled() && lastScrollPosition != scrollingDevice.lastScrollPosition))
@@ -979,8 +933,6 @@ void QXcbConnection::xi2UpdateScrollingDevice(ScrollingDevice &scrollingDevice)
lastScrollPosition.x(), lastScrollPosition.y(),
scrollingDevice.lastScrollPosition.x(),
scrollingDevice.lastScrollPosition.y());
-
- XIFreeDeviceInfo(deviceInfo);
}
void QXcbConnection::xi2UpdateScrollingDevices()
@@ -1003,10 +955,9 @@ QXcbConnection::ScrollingDevice *QXcbConnection::scrollingDeviceForId(int id)
void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollingDevice)
{
- xXIGenericDeviceEvent *xiEvent = reinterpret_cast<xXIGenericDeviceEvent *>(event);
+ auto *xiDeviceEvent = reinterpret_cast<qt_xcb_input_device_event_t *>(event);
- if (xiEvent->evtype == XI_Motion && scrollingDevice.orientations) {
- xXIDeviceEvent* xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event);
+ if (xiDeviceEvent->event_type == XCB_INPUT_MOTION && scrollingDevice.orientations) {
if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event)) {
QPoint rawDelta;
QPoint angleDelta;
@@ -1040,17 +991,16 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin
if (!angleDelta.isNull()) {
QPoint local(fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y));
QPoint global(fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y));
- Qt::KeyboardModifiers modifiers = keyboard()->translateModifiers(xiDeviceEvent->mods.effective_mods);
+ Qt::KeyboardModifiers modifiers = keyboard()->translateModifiers(xiDeviceEvent->mods.effective);
if (modifiers & Qt::AltModifier) {
std::swap(angleDelta.rx(), angleDelta.ry());
std::swap(rawDelta.rx(), rawDelta.ry());
}
qCDebug(lcQpaXInputEvents) << "scroll wheel @ window pos" << local << "delta px" << rawDelta << "angle" << angleDelta;
- QWindowSystemInterface::handleWheelEvent(platformWindow->window(), xiEvent->time, local, global, rawDelta, angleDelta, modifiers);
+ QWindowSystemInterface::handleWheelEvent(platformWindow->window(), xiDeviceEvent->time, local, global, rawDelta, angleDelta, modifiers);
}
}
- } else if (xiEvent->evtype == XI_ButtonRelease && scrollingDevice.legacyOrientations) {
- xXIDeviceEvent* xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event);
+ } else if (xiDeviceEvent->event_type == XCB_INPUT_BUTTON_RELEASE && scrollingDevice.legacyOrientations) {
if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event)) {
QPoint angleDelta;
if (scrollingDevice.legacyOrientations & Qt::Vertical) {
@@ -1068,16 +1018,15 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin
if (!angleDelta.isNull()) {
QPoint local(fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y));
QPoint global(fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y));
- Qt::KeyboardModifiers modifiers = keyboard()->translateModifiers(xiDeviceEvent->mods.effective_mods);
+ Qt::KeyboardModifiers modifiers = keyboard()->translateModifiers(xiDeviceEvent->mods.effective);
if (modifiers & Qt::AltModifier)
std::swap(angleDelta.rx(), angleDelta.ry());
qCDebug(lcQpaXInputEvents) << "scroll wheel (button" << xiDeviceEvent->detail << ") @ window pos" << local << "delta angle" << angleDelta;
- QWindowSystemInterface::handleWheelEvent(platformWindow->window(), xiEvent->time, local, global, QPoint(), angleDelta, modifiers);
+ QWindowSystemInterface::handleWheelEvent(platformWindow->window(), xiDeviceEvent->time, local, global, QPoint(), angleDelta, modifiers);
}
}
}
}
-#endif // XCB_USE_XINPUT21
static int xi2ValuatorOffset(const unsigned char *maskPtr, int maskLen, int number)
{
@@ -1100,10 +1049,10 @@ static int xi2ValuatorOffset(const unsigned char *maskPtr, int maskLen, int numb
bool QXcbConnection::xi2GetValuatorValueIfSet(const void *event, int valuatorNum, double *value)
{
- const xXIDeviceEvent *xideviceevent = static_cast<const xXIDeviceEvent *>(event);
- const unsigned char *buttonsMaskAddr = (const unsigned char*)&xideviceevent[1];
- const unsigned char *valuatorsMaskAddr = buttonsMaskAddr + xideviceevent->buttons_len * 4;
- FP3232 *valuatorsValuesAddr = (FP3232*)(valuatorsMaskAddr + xideviceevent->valuators_len * 4);
+ auto *xideviceevent = static_cast<const qt_xcb_input_device_event_t *>(event);
+ auto *buttonsMaskAddr = reinterpret_cast<const unsigned char *>(&xideviceevent[1]);
+ auto *valuatorsMaskAddr = buttonsMaskAddr + xideviceevent->buttons_len * 4;
+ auto *valuatorsValuesAddr = reinterpret_cast<const xcb_input_fp3232_t *>(valuatorsMaskAddr + xideviceevent->valuators_len * 4);
int valuatorOffset = xi2ValuatorOffset(valuatorsMaskAddr, xideviceevent->valuators_len, valuatorNum);
if (valuatorOffset < 0)
@@ -1114,15 +1063,6 @@ bool QXcbConnection::xi2GetValuatorValueIfSet(const void *event, int valuatorNum
return true;
}
-void QXcbConnection::xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event)
-{
- // xcb event structs contain stuff that wasn't on the wire, the full_sequence field
- // adds an extra 4 bytes and generic events cookie data is on the wire right after the standard 32 bytes.
- // Move this data back to have the same layout in memory as it was on the wire
- // and allow casting, overwriting the full_sequence field.
- memmove((char*) event + 32, (char*) event + 36, event->length * 4);
-}
-
Qt::MouseButton QXcbConnection::xiToQtMouseButton(uint32_t b)
{
switch (b) {
@@ -1186,31 +1126,29 @@ static const char *pointerTypeName(QTabletEvent::PointerType ptype) {
bool QXcbConnection::xi2HandleTabletEvent(const void *event, TabletData *tabletData)
{
bool handled = true;
- Display *xDisplay = static_cast<Display *>(m_xlib_display);
- const xXIGenericDeviceEvent *xiEvent = static_cast<const xXIGenericDeviceEvent *>(event);
- const xXIDeviceEvent *xiDeviceEvent = reinterpret_cast<const xXIDeviceEvent *>(xiEvent);
+ const auto *xiDeviceEvent = reinterpret_cast<const qt_xcb_input_device_event_t *>(event);
- switch (xiEvent->evtype) {
- case XI_ButtonPress: {
+ switch (xiDeviceEvent->event_type) {
+ case XCB_INPUT_BUTTON_PRESS: {
Qt::MouseButton b = xiToQtMouseButton(xiDeviceEvent->detail);
tabletData->buttons |= b;
- xi2ReportTabletEvent(xiEvent, tabletData);
+ xi2ReportTabletEvent(event, tabletData);
break;
}
- case XI_ButtonRelease: {
+ case XCB_INPUT_BUTTON_RELEASE: {
Qt::MouseButton b = xiToQtMouseButton(xiDeviceEvent->detail);
tabletData->buttons ^= b;
- xi2ReportTabletEvent(xiEvent, tabletData);
+ xi2ReportTabletEvent(event, tabletData);
break;
}
- case XI_Motion:
- xi2ReportTabletEvent(xiEvent, tabletData);
+ case XCB_INPUT_MOTION:
+ xi2ReportTabletEvent(event, tabletData);
break;
- case XI_PropertyEvent: {
+ case XCB_INPUT_PROPERTY: {
// This is the wacom driver's way of reporting tool proximity.
// The evdev driver doesn't do it this way.
- const xXIPropertyEvent *ev = reinterpret_cast<const xXIPropertyEvent *>(event);
- if (ev->what == XIPropertyModified) {
+ const auto *ev = reinterpret_cast<const xcb_input_property_event_t *>(event);
+ if (ev->what == XCB_INPUT_PROPERTY_FLAG_MODIFIED) {
if (ev->property == atom(QXcbAtom::WacomSerialIDs)) {
enum WacomSerialIndex {
_WACSER_USB_ID = 0,
@@ -1220,15 +1158,12 @@ bool QXcbConnection::xi2HandleTabletEvent(const void *event, TabletData *tabletD
_WACSER_TOOL_ID,
_WACSER_COUNT
};
- Atom propType;
- int propFormat;
- unsigned long numItems, bytesAfter;
- unsigned char *data;
- if (XIGetProperty(xDisplay, tabletData->deviceId, ev->property, 0, 100,
- 0, AnyPropertyType, &propType, &propFormat,
- &numItems, &bytesAfter, &data) == Success) {
- if (propType == atom(QXcbAtom::INTEGER) && propFormat == 32 && numItems == _WACSER_COUNT) {
- quint32 *ptr = reinterpret_cast<quint32 *>(data);
+
+ auto reply = Q_XCB_REPLY(xcb_input_xi_get_property, xcb_connection(), tabletData->deviceId, 0,
+ ev->property, XCB_GET_PROPERTY_TYPE_ANY, 0, 100);
+ if (reply) {
+ if (reply->type == atom(QXcbAtom::INTEGER) && reply->format == 32 && reply->num_items == _WACSER_COUNT) {
+ quint32 *ptr = reinterpret_cast<quint32 *>(xcb_input_xi_get_property_items(reply.get()));
quint32 tool = ptr[_WACSER_TOOL_ID];
// Workaround for http://sourceforge.net/p/linuxwacom/bugs/246/
// e.g. on Thinkpad Helix, tool ID will be 0 and serial will be 1
@@ -1260,7 +1195,6 @@ bool QXcbConnection::xi2HandleTabletEvent(const void *event, TabletData *tabletD
tabletData->deviceId, ptr[_WACSER_USB_ID], ptr[_WACSER_LAST_TOOL_SERIAL], ptr[_WACSER_LAST_TOOL_ID],
ptr[_WACSER_TOOL_SERIAL], ptr[_WACSER_TOOL_ID], toolName(tabletData->tool));
}
- XFree(data);
}
}
}
@@ -1276,12 +1210,12 @@ bool QXcbConnection::xi2HandleTabletEvent(const void *event, TabletData *tabletD
void QXcbConnection::xi2ReportTabletEvent(const void *event, TabletData *tabletData)
{
- const xXIDeviceEvent *ev = reinterpret_cast<const xXIDeviceEvent *>(event);
+ auto *ev = reinterpret_cast<const qt_xcb_input_device_event_t *>(event);
QXcbWindow *xcbWindow = platformWindowFromId(ev->event);
if (!xcbWindow)
return;
QWindow *window = xcbWindow->window();
- const Qt::KeyboardModifiers modifiers = keyboard()->translateModifiers(ev->mods.effective_mods);
+ const Qt::KeyboardModifiers modifiers = keyboard()->translateModifiers(ev->mods.effective);
QPointF local(fixed1616ToReal(ev->event_x), fixed1616ToReal(ev->event_y));
QPointF global(fixed1616ToReal(ev->root_x), fixed1616ToReal(ev->root_y));
double pressure = 0, rotation = 0, tangentialPressure = 0;
@@ -1324,7 +1258,7 @@ void QXcbConnection::xi2ReportTabletEvent(const void *event, TabletData *tabletD
qCDebug(lcQpaXInputEvents, "XI2 event on tablet %d with tool %s type %s seq %d detail %d time %d "
"pos %6.1f, %6.1f root pos %6.1f, %6.1f buttons 0x%x pressure %4.2lf tilt %d, %d rotation %6.2lf modifiers 0x%x",
tabletData->deviceId, toolName(tabletData->tool), pointerTypeName(tabletData->pointerType),
- ev->sequenceNumber, ev->detail, ev->time,
+ ev->sequence, ev->detail, ev->time,
local.x(), local.y(), global.x(), global.y(),
(int)tabletData->buttons, pressure, xTilt, yTilt, rotation, (int)modifiers);
diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp
index b401100dd4..57629ac03a 100644
--- a/src/plugins/platforms/xcb/qxcbcursor.cpp
+++ b/src/plugins/platforms/xcb/qxcbcursor.cpp
@@ -628,6 +628,12 @@ xcb_cursor_t QXcbCursor::createBitmapCursor(QCursor *cursor)
}
#endif
+/*! \internal
+
+ Note that the logical state of a device (as seen by means of the protocol) may
+ lag the physical state if device event processing is frozen. See QueryPointer
+ in X11 protocol specification.
+*/
void QXcbCursor::queryPointer(QXcbConnection *c, QXcbVirtualDesktop **virtualDesktop, QPoint *pos, int *keybMask)
{
if (pos)
diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp
index c8ba33edf5..aa329d8cb7 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.cpp
+++ b/src/plugins/platforms/xcb/qxcbdrag.cpp
@@ -63,19 +63,6 @@
QT_BEGIN_NAMESPACE
-//#define DND_DEBUG
-#ifdef DND_DEBUG
-#define DEBUG qDebug
-#else
-#define DEBUG if(0) qDebug
-#endif
-
-#ifdef DND_DEBUG
-#define DNDDEBUG qDebug()
-#else
-#define DNDDEBUG if(0) qDebug()
-#endif
-
const int xdnd_version = 5;
static inline xcb_window_t xcb_window(QPlatformWindow *w)
@@ -164,8 +151,12 @@ void QXcbDrag::init()
QXcbCursor::queryPointer(connection(), &current_virtual_desktop, 0);
drag_types.clear();
+ //current_embedding_widget = 0;
+
dropped = false;
canceled = false;
+
+ source_sameanswer = QRect();
}
bool QXcbDrag::eventFilter(QObject *o, QEvent *e)
@@ -181,11 +172,10 @@ bool QXcbDrag::eventFilter(QObject *o, QEvent *e)
void QXcbDrag::startDrag()
{
- // #fixme enableEventFilter();
-
init();
#ifndef QT_NO_CLIPBOARD
+ qCDebug(lcQpaXDnd) << "starting drag where source:" << connection()->clipboard()->owner();
xcb_set_selection_owner(xcb_connection(), connection()->clipboard()->owner(),
atom(QXcbAtom::XdndSelection), connection()->time());
#endif
@@ -211,6 +201,9 @@ void QXcbDrag::startDrag()
QBasicDrag::startDrag();
if (connection()->mouseGrabber() == nullptr)
shapedPixmapWindow()->setMouseGrabEnabled(true);
+
+ auto nativePixelPos = QHighDpi::toNativePixels(QCursor::pos(), initiatorWindow);
+ move(nativePixelPos, QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
}
void QXcbDrag::endDrag()
@@ -307,34 +300,13 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md
return 0;
}
-void QXcbDrag::move(const QPoint &globalPos)
+bool QXcbDrag::findXdndAwareTarget(const QPoint &globalPos, xcb_window_t *target_out)
{
-
- if (source_sameanswer.contains(globalPos) && source_sameanswer.isValid())
- return;
-
- QXcbVirtualDesktop *virtualDesktop = nullptr;
- QPoint cursorPos;
- QXcbCursor::queryPointer(connection(), &virtualDesktop, &cursorPos);
- QXcbScreen *screen = virtualDesktop->screenAt(cursorPos);
- QPoint deviceIndependentPos = QHighDpiScaling::mapPositionFromNative(globalPos, screen);
-
- if (virtualDesktop != current_virtual_desktop) {
- setUseCompositing(virtualDesktop->compositingActive());
- recreateShapedPixmapWindow(static_cast<QPlatformScreen*>(screen)->screen(), deviceIndependentPos);
- if (connection()->mouseGrabber() == nullptr)
- shapedPixmapWindow()->setMouseGrabEnabled(true);
-
- current_virtual_desktop = virtualDesktop;
- } else {
- QBasicDrag::moveShapedPixmapWindow(deviceIndependentPos);
- }
-
xcb_window_t rootwin = current_virtual_desktop->root();
- auto translate = Q_XCB_REPLY(xcb_translate_coordinates, connection()->xcb_connection(),
+ auto translate = Q_XCB_REPLY(xcb_translate_coordinates, xcb_connection(),
rootwin, rootwin, globalPos.x(), globalPos.y());
if (!translate)
- return;
+ return false;
xcb_window_t target = translate->child;
int lx = translate->dst_x;
@@ -343,10 +315,9 @@ void QXcbDrag::move(const QPoint &globalPos)
if (target && target != rootwin) {
xcb_window_t src = rootwin;
while (target != 0) {
- DNDDEBUG << "checking target for XdndAware" << target << lx << ly;
+ qCDebug(lcQpaXDnd) << "checking target for XdndAware" << target;
- // translate coordinates
- auto translate = Q_XCB_REPLY(xcb_translate_coordinates, connection()->xcb_connection(),
+ auto translate = Q_XCB_REPLY(xcb_translate_coordinates, xcb_connection(),
src, target, lx, ly);
if (!translate) {
target = 0;
@@ -357,12 +328,11 @@ void QXcbDrag::move(const QPoint &globalPos)
src = target;
xcb_window_t child = translate->child;
- // check if it has XdndAware
auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, target,
atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0);
bool aware = reply && reply->type != XCB_NONE;
if (aware) {
- DNDDEBUG << "Found XdndAware on " << target;
+ qCDebug(lcQpaXDnd) << "found XdndAware on" << target;
break;
}
@@ -370,14 +340,45 @@ void QXcbDrag::move(const QPoint &globalPos)
}
if (!target || target == shapedPixmapWindow()->handle()->winId()) {
- DNDDEBUG << "need to find real window";
+ qCDebug(lcQpaXDnd) << "need to find real window";
target = findRealWindow(globalPos, rootwin, 6, true);
if (target == 0)
target = findRealWindow(globalPos, rootwin, 6, false);
- DNDDEBUG << "real window found" << target;
+ qCDebug(lcQpaXDnd) << "real window found" << target;
}
}
+ *target_out = target;
+ return true;
+}
+
+void QXcbDrag::move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
+{
+ // The source sends XdndEnter and XdndPosition to the target.
+ if (source_sameanswer.contains(globalPos) && source_sameanswer.isValid())
+ return;
+
+ QXcbVirtualDesktop *virtualDesktop = nullptr;
+ QPoint cursorPos;
+ QXcbCursor::queryPointer(connection(), &virtualDesktop, &cursorPos);
+ QXcbScreen *screen = virtualDesktop->screenAt(cursorPos);
+ QPoint deviceIndependentPos = QHighDpiScaling::mapPositionFromNative(globalPos, screen);
+
+ if (virtualDesktop != current_virtual_desktop) {
+ setUseCompositing(virtualDesktop->compositingActive());
+ recreateShapedPixmapWindow(static_cast<QPlatformScreen*>(screen)->screen(), deviceIndependentPos);
+ if (connection()->mouseGrabber() == nullptr)
+ shapedPixmapWindow()->setMouseGrabEnabled(true);
+
+ current_virtual_desktop = virtualDesktop;
+ } else {
+ QBasicDrag::moveShapedPixmapWindow(deviceIndependentPos);
+ }
+
+ xcb_window_t target;
+ if (!findXdndAwareTarget(globalPos, &target))
+ return;
+
QXcbWindow *w = 0;
if (target) {
w = connection()->platformWindowFromId(target);
@@ -385,7 +386,7 @@ void QXcbDrag::move(const QPoint &globalPos)
w = 0;
} else {
w = 0;
- target = rootwin;
+ target = current_virtual_desktop->root();
}
xcb_window_t proxy_target = xdndProxy(connection(), target);
@@ -427,13 +428,14 @@ void QXcbDrag::move(const QPoint &globalPos)
enter.data.data32[0] = 0;
#endif
enter.data.data32[1] = flags;
- enter.data.data32[2] = drag_types.size()>0 ? drag_types.at(0) : 0;
- enter.data.data32[3] = drag_types.size()>1 ? drag_types.at(1) : 0;
- enter.data.data32[4] = drag_types.size()>2 ? drag_types.at(2) : 0;
+ enter.data.data32[2] = drag_types.size() > 0 ? drag_types.at(0) : 0;
+ enter.data.data32[3] = drag_types.size() > 1 ? drag_types.at(1) : 0;
+ enter.data.data32[4] = drag_types.size() > 2 ? drag_types.at(2) : 0;
// provisionally set the rectangle to 5x5 pixels...
- source_sameanswer = QRect(globalPos.x() - 2, globalPos.y() -2 , 5, 5);
+ source_sameanswer = QRect(globalPos.x() - 2, globalPos.y() - 2 , 5, 5);
+
+ qCDebug(lcQpaXDnd) << "sending XdndEnter to target:" << target;
- DEBUG() << "sending Xdnd enter source=" << enter.data.data32[0];
if (w)
handleEnter(w, &enter, current_proxy_target);
else if (target)
@@ -447,7 +449,8 @@ void QXcbDrag::move(const QPoint &globalPos)
if (target) {
waiting_for_status = true;
-
+ // The source sends a ClientMessage of type XdndPosition. This tells the target the
+ // position of the mouse and the action that the user requested.
xcb_client_message_event_t move;
move.response_type = XCB_CLIENT_MESSAGE;
move.sequence = 0;
@@ -462,21 +465,34 @@ void QXcbDrag::move(const QPoint &globalPos)
move.data.data32[1] = 0; // flags
move.data.data32[2] = (globalPos.x() << 16) + globalPos.y();
move.data.data32[3] = connection()->time();
- move.data.data32[4] = toXdndAction(defaultAction(currentDrag()->supportedActions(), QGuiApplication::keyboardModifiers()));
- DEBUG() << "sending Xdnd position source=" << move.data.data32[0] << "target=" << move.window;
+ move.data.data32[4] = toXdndAction(defaultAction(currentDrag()->supportedActions(), mods));
+
+ qCDebug(lcQpaXDnd) << "sending XdndPosition to target:" << target;
source_time = connection()->time();
if (w)
- handle_xdnd_position(w, &move);
+ handle_xdnd_position(w, &move, b, mods);
else
xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&move);
}
+
+ static const bool isUnity = qgetenv("XDG_CURRENT_DESKTOP").toLower() == "unity";
+ if (isUnity && xdndCollectionWindow == XCB_NONE) {
+ QString name = QXcbWindow::windowTitle(connection(), target);
+ if (name == QStringLiteral("XdndCollectionWindowImp"))
+ xdndCollectionWindow = target;
+ }
+ if (target == xdndCollectionWindow) {
+ setCanDrop(false);
+ updateCursor(Qt::IgnoreAction);
+ }
}
-void QXcbDrag::drop(const QPoint &globalPos)
+void QXcbDrag::drop(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
{
- QBasicDrag::drop(globalPos);
+ // XdndDrop is sent from source to target to complete the drop.
+ QBasicDrag::drop(globalPos, b, mods);
if (!current_target)
return;
@@ -500,7 +516,7 @@ void QXcbDrag::drop(const QPoint &globalPos)
QXcbWindow *w = connection()->platformWindowFromId(current_proxy_target);
- if (w && (w->window()->type() == Qt::Desktop) /*&& !w->acceptDrops()*/)
+ if (w && w->window()->type() == Qt::Desktop) // && !w->acceptDrops()
w = 0;
Transaction t = {
@@ -519,16 +535,13 @@ void QXcbDrag::drop(const QPoint &globalPos)
cleanup_timer = startTimer(XdndDropTransactionTimeout);
}
+ qCDebug(lcQpaXDnd) << "sending drop to target:" << current_target;
+
if (w) {
- handleDrop(w, &drop);
+ handleDrop(w, &drop, b, mods);
} else {
xcb_send_event(xcb_connection(), false, current_proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&drop);
}
-
- current_target = 0;
- current_proxy_target = 0;
- source_time = 0;
-// current_embedding_widget = 0;
}
Qt::DropAction QXcbDrag::toDropAction(xcb_atom_t a) const
@@ -586,44 +599,6 @@ int QXcbDrag::findTransactionByTime(xcb_timestamp_t timestamp)
}
#if 0
-
-// find an ancestor with XdndAware on it
-static Window findXdndAwareParent(Window window)
-{
- Window target = 0;
- forever {
- // check if window has XdndAware
- Atom type = 0;
- int f;
- unsigned long n, a;
- unsigned char *data = 0;
- if (XGetWindowProperty(X11->display, window, ATOM(XdndAware), 0, 0, False,
- AnyPropertyType, &type, &f,&n,&a,&data) == Success) {
- if (data)
- XFree(data);
- if (type) {
- target = window;
- break;
- }
- }
-
- // try window's parent
- Window root;
- Window parent;
- Window *children;
- uint unused;
- if (!XQueryTree(X11->display, window, &root, &parent, &children, &unused))
- break;
- if (children)
- XFree(children);
- if (window == root)
- break;
- window = parent;
- }
- return target;
-}
-
-
// for embedding only
static QWidget* current_embedding_widget = 0;
static xcb_client_message_event_t last_enter_event;
@@ -665,11 +640,10 @@ static bool checkEmbedded(QWidget* w, const XEvent* xe)
}
#endif
-
-void QXcbDrag::handleEnter(QPlatformWindow *window, const xcb_client_message_event_t *event, xcb_window_t proxy)
+void QXcbDrag::handleEnter(QPlatformWindow *, const xcb_client_message_event_t *event, xcb_window_t proxy)
{
- Q_UNUSED(window);
- DEBUG() << "handleEnter" << window;
+ // The target receives XdndEnter.
+ qCDebug(lcQpaXDnd) << "target:" << event->window << "received XdndEnter";
xdnd_types.clear();
@@ -705,11 +679,16 @@ void QXcbDrag::handleEnter(QPlatformWindow *window, const xcb_client_message_eve
}
}
for(int i = 0; i < xdnd_types.length(); ++i)
- DEBUG() << " " << connection()->atomName(xdnd_types.at(i));
+ qCDebug(lcQpaXDnd) << " " << connection()->atomName(xdnd_types.at(i));
}
-void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message_event_t *e)
+void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message_event_t *e,
+ Qt::MouseButtons b, Qt::KeyboardModifiers mods)
{
+ // The target receives XdndPosition. The target window must determine which widget the mouse
+ // is in and ask it whether or not it will accept the drop.
+ qCDebug(lcQpaXDnd) << "target:" << e->window << "received XdndPosition";
+
QPoint p((e->data.data32[2] & 0xffff0000) >> 16, e->data.data32[2] & 0x0000ffff);
Q_ASSERT(w);
QRect geometry = w->geometry();
@@ -718,8 +697,9 @@ void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message
if (!w || !w->window() || (w->window()->type() == Qt::Desktop))
return;
- if (e->data.data32[0] != xdnd_dragsource) {
- DEBUG("xdnd drag position from unexpected source (%x not %x)", e->data.data32[0], xdnd_dragsource);
+ if (Q_UNLIKELY(e->data.data32[0] != xdnd_dragsource)) {
+ qCDebug(lcQpaXDnd, "xdnd drag position from unexpected source (%x not %x)",
+ e->data.data32[0], xdnd_dragsource);
return;
}
@@ -741,10 +721,19 @@ void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message
supported_actions = Qt::DropActions(toDropAction(e->data.data32[4]));
}
- QPlatformDragQtResponse qt_response = QWindowSystemInterface::handleDrag(w->window(),dropData,p,supported_actions);
+ auto buttons = currentDrag() ? b : connection()->queryMouseButtons();
+ auto modifiers = currentDrag() ? mods : connection()->queryKeyboardModifiers();
+
+ QPlatformDragQtResponse qt_response = QWindowSystemInterface::handleDrag(
+ w->window(), dropData, p, supported_actions, buttons, modifiers);
+
+ // ### FIXME ? - answerRect appears to be unused.
QRect answerRect(p + geometry.topLeft(), QSize(1,1));
answerRect = qt_response.answerRect().translated(geometry.topLeft()).intersected(geometry);
+ // The target sends a ClientMessage of type XdndStatus. This tells the source whether or not
+ // it will accept the drop, and, if so, what action will be taken. It also includes a rectangle
+ // that means "don't send another XdndPosition message until the mouse moves out of here".
xcb_client_message_event_t response;
response.response_type = XCB_CLIENT_MESSAGE;
response.sequence = 0;
@@ -775,13 +764,15 @@ void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message
// reset
target_time = XCB_CURRENT_TIME;
+ qCDebug(lcQpaXDnd) << "sending XdndStatus to source:" << xdnd_dragsource;
+
#ifndef QT_NO_CLIPBOARD
if (xdnd_dragsource == connection()->clipboard()->owner())
handle_xdnd_status(&response);
else
#endif
- xcb_send_event(xcb_connection(), false, current_proxy_target,
- XCB_EVENT_MASK_NO_EVENT, (const char *)&response);
+ xcb_send_event(xcb_connection(), false, current_proxy_target,
+ XCB_EVENT_MASK_NO_EVENT, (const char *)&response);
}
namespace
@@ -790,12 +781,11 @@ namespace
public:
ClientMessageScanner(xcb_atom_t a) : atom(a) {}
xcb_atom_t atom;
- bool checkEvent(xcb_generic_event_t *event) const {
- if (!event)
+ bool operator() (xcb_generic_event_t *event, int type) const {
+ if (type != XCB_CLIENT_MESSAGE)
return false;
- if ((event->response_type & 0x7f) != XCB_CLIENT_MESSAGE)
- return false;
- return ((xcb_client_message_event_t *)event)->type == atom;
+ auto clientMessage = reinterpret_cast<xcb_client_message_event_t *>(event);
+ return clientMessage->type == atom;
}
};
}
@@ -803,12 +793,11 @@ namespace
void QXcbDrag::handlePosition(QPlatformWindow * w, const xcb_client_message_event_t *event)
{
xcb_client_message_event_t *lastEvent = const_cast<xcb_client_message_event_t *>(event);
- xcb_generic_event_t *nextEvent;
ClientMessageScanner scanner(atom(QXcbAtom::XdndPosition));
- while ((nextEvent = connection()->checkEvent(scanner))) {
+ while (auto nextEvent = connection()->eventQueue()->peek(scanner)) {
if (lastEvent != event)
free(lastEvent);
- lastEvent = (xcb_client_message_event_t *)nextEvent;
+ lastEvent = reinterpret_cast<xcb_client_message_event_t *>(nextEvent);
}
handle_xdnd_position(w, lastEvent);
@@ -818,7 +807,9 @@ void QXcbDrag::handlePosition(QPlatformWindow * w, const xcb_client_message_even
void QXcbDrag::handle_xdnd_status(const xcb_client_message_event_t *event)
{
- DEBUG("xdndHandleStatus");
+ // The source receives XdndStatus. It can use the action to change the cursor to indicate
+ // whether or not the user's requested action will be performed.
+ qCDebug(lcQpaXDnd) << "source:" << event->window << "received XdndStatus";
waiting_for_status = false;
// ignore late status messages
if (event->data.data32[0] && event->data.data32[0] != current_target)
@@ -855,7 +846,7 @@ void QXcbDrag::handleStatus(const xcb_client_message_event_t *event)
xcb_client_message_event_t *lastEvent = const_cast<xcb_client_message_event_t *>(event);
xcb_generic_event_t *nextEvent;
ClientMessageScanner scanner(atom(QXcbAtom::XdndStatus));
- while ((nextEvent = connection()->checkEvent(scanner))) {
+ while ((nextEvent = connection()->eventQueue()->peek(scanner))) {
if (lastEvent != event)
free(lastEvent);
lastEvent = (xcb_client_message_event_t *)nextEvent;
@@ -864,12 +855,13 @@ void QXcbDrag::handleStatus(const xcb_client_message_event_t *event)
handle_xdnd_status(lastEvent);
if (lastEvent != event)
free(lastEvent);
- DEBUG("xdndHandleStatus end");
}
void QXcbDrag::handleLeave(QPlatformWindow *w, const xcb_client_message_event_t *event)
{
- DEBUG("xdnd leave");
+ // If the target receives XdndLeave, it frees any cached data and forgets the whole incident.
+ qCDebug(lcQpaXDnd) << "target:" << event->window << "received XdndLeave";
+
if (!currentWindow || w != currentWindow.data()->handle())
return; // sanity
@@ -882,22 +874,19 @@ void QXcbDrag::handleLeave(QPlatformWindow *w, const xcb_client_message_event_t
if (event->data.data32[0] != xdnd_dragsource) {
// This often happens - leave other-process window quickly
- DEBUG("xdnd drag leave from unexpected source (%x not %x", event->data.data32[0], xdnd_dragsource);
+ qCDebug(lcQpaXDnd, "xdnd drag leave from unexpected source (%x not %x",
+ event->data.data32[0], xdnd_dragsource);
}
- QWindowSystemInterface::handleDrag(w->window(),0,QPoint(),Qt::IgnoreAction);
-
- xdnd_dragsource = 0;
- xdnd_types.clear();
- currentWindow.clear();
+ QWindowSystemInterface::handleDrag(w->window(), nullptr, QPoint(), Qt::IgnoreAction, 0, 0);
}
void QXcbDrag::send_leave()
{
+ // XdndLeave is sent from the source to the target to cancel the drop.
if (!current_target)
return;
-
xcb_client_message_event_t leave;
leave.response_type = XCB_CLIENT_MESSAGE;
leave.sequence = 0;
@@ -919,21 +908,21 @@ void QXcbDrag::send_leave()
if (w && (w->window()->type() == Qt::Desktop) /*&& !w->acceptDrops()*/)
w = 0;
+ qCDebug(lcQpaXDnd) << "sending XdndLeave to target:" << current_target;
+
if (w)
handleLeave(w, (const xcb_client_message_event_t *)&leave);
else
xcb_send_event(xcb_connection(), false,current_proxy_target,
XCB_EVENT_MASK_NO_EVENT, (const char *)&leave);
-
- current_target = 0;
- current_proxy_target = 0;
- source_time = XCB_CURRENT_TIME;
- waiting_for_status = false;
}
-void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *event)
+void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *event,
+ Qt::MouseButtons b, Qt::KeyboardModifiers mods)
{
- DEBUG("xdndHandleDrop");
+ // Target receives XdndDrop. Once it is finished processing the drop, it sends XdndFinished.
+ qCDebug(lcQpaXDnd) << "target:" << event->window << "received XdndDrop";
+
if (!currentWindow) {
xdnd_dragsource = 0;
return; // sanity
@@ -941,16 +930,14 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e
const uint32_t *l = event->data.data32;
- DEBUG("xdnd drop");
-
if (l[0] != xdnd_dragsource) {
- DEBUG("xdnd drop from unexpected source (%x not %x", l[0], xdnd_dragsource);
+ qCDebug(lcQpaXDnd, "xdnd drop from unexpected source (%x not %x", l[0], xdnd_dragsource);
return;
}
// update the "user time" from the timestamp in the event.
if (l[2] != 0)
- target_time = /*X11->userTime =*/ l[2];
+ target_time = l[2];
Qt::DropActions supported_drop_actions;
QMimeData *dropData = 0;
@@ -960,9 +947,6 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e
} else {
dropData = m_dropData;
supported_drop_actions = accepted_drop_action;
-
- // Drop coming from another app? Update keyboard modifiers.
- QGuiApplicationPrivate::modifier_buttons = QGuiApplication::queryKeyboardModifiers();
}
if (!dropData)
@@ -973,7 +957,13 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e
// dropData = QDragManager::dragPrivate(X11->dndDropTransactions.at(at).object)->data;
// if we can't find it, then use the data in the drag manager
- QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(currentWindow.data(),dropData,currentPosition,supported_drop_actions);
+ auto buttons = currentDrag() ? b : connection()->queryMouseButtons();
+ auto modifiers = currentDrag() ? mods : connection()->queryKeyboardModifiers();
+
+ QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(
+ currentWindow.data(), dropData, currentPosition, supported_drop_actions,
+ buttons, modifiers);
+
setExecutedDropAction(response.acceptedAction());
xcb_client_message_event_t finished;
@@ -985,34 +975,26 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e
finished.data.data32[0] = currentWindow ? xcb_window(currentWindow.data()) : XCB_NONE;
finished.data.data32[1] = response.isAccepted(); // flags
finished.data.data32[2] = toXdndAction(response.acceptedAction());
- xcb_send_event(xcb_connection(), false, current_proxy_target,
- XCB_EVENT_MASK_NO_EVENT, (char *)&finished);
- xdnd_dragsource = 0;
- currentWindow.clear();
- waiting_for_status = false;
+ qCDebug(lcQpaXDnd) << "sending XdndFinished to source:" << xdnd_dragsource;
- // reset
- target_time = XCB_CURRENT_TIME;
+ xcb_send_event(xcb_connection(), false, current_proxy_target,
+ XCB_EVENT_MASK_NO_EVENT, (char *)&finished);
dropped = true;
}
-
void QXcbDrag::handleFinished(const xcb_client_message_event_t *event)
{
- DEBUG("xdndHandleFinished");
+ // Source receives XdndFinished when target is done processing the drop data.
+ qCDebug(lcQpaXDnd) << "source:" << event->window << "received XdndFinished";
+
#ifndef QT_NO_CLIPBOARD
if (event->window != connection()->clipboard()->owner())
return;
#endif
const unsigned long *l = (const unsigned long *)event->data.data32;
-
- DNDDEBUG << "xdndHandleFinished, l[0]" << l[0]
- << "current_target" << current_target
- << "qt_xdnd_current_proxy_targe" << current_proxy_target;
-
if (l[0]) {
int at = findTransactionByWindow(l[0]);
if (at != -1) {
@@ -1087,7 +1069,8 @@ void QXcbDrag::timerEvent(QTimerEvent* e)
void QXcbDrag::cancel()
{
- DEBUG("QXcbDrag::cancel");
+ qCDebug(lcQpaXDnd) << "dnd was canceled";
+
QBasicDrag::cancel();
if (current_target)
send_leave();
@@ -1098,7 +1081,6 @@ void QXcbDrag::cancel()
canceled = true;
}
-// find an ancestor with XdndAware on it
static xcb_window_t findXdndAwareParent(QXcbConnection *c, xcb_window_t window)
{
xcb_window_t target = 0;
@@ -1127,7 +1109,8 @@ static xcb_window_t findXdndAwareParent(QXcbConnection *c, xcb_window_t window)
void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event)
{
- Q_DECLARE_XCB_EVENT(notify, xcb_selection_notify_event_t);
+ qCDebug(lcQpaXDnd) << "handle selection request from target:" << event->requestor;
+ q_padded_xcb_event<xcb_selection_notify_event_t> notify = {};
notify.response_type = XCB_SELECTION_NOTIFY;
notify.requestor = event->requestor;
notify.selection = event->selection;
@@ -1194,10 +1177,10 @@ void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event
bool QXcbDrag::dndEnable(QXcbWindow *w, bool on)
{
- DNDDEBUG << "xdndEnable" << w << on;
+ // Windows announce that they support the XDND protocol by creating a window property XdndAware.
if (on) {
- QXcbWindow *xdnd_widget = 0;
- if ((w->window()->type() == Qt::Desktop)) {
+ QXcbWindow *window = nullptr;
+ if (w->window()->type() == Qt::Desktop) {
if (desktop_proxy) // *WE* already have one.
return false;
@@ -1208,8 +1191,8 @@ bool QXcbDrag::dndEnable(QXcbWindow *w, bool on)
if (!proxy_id) {
desktop_proxy = new QWindow;
- xdnd_widget = static_cast<QXcbWindow *>(desktop_proxy->handle());
- proxy_id = xdnd_widget->xcb_window();
+ window = static_cast<QXcbWindow *>(desktop_proxy->handle());
+ proxy_id = window->xcb_window();
xcb_atom_t xdnd_proxy = atom(QXcbAtom::XdndProxy);
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, w->xcb_window(), xdnd_proxy,
XCB_ATOM_WINDOW, 32, 1, &proxy_id);
@@ -1218,24 +1201,24 @@ bool QXcbDrag::dndEnable(QXcbWindow *w, bool on)
}
} else {
- xdnd_widget = w;
+ window = w;
}
- if (xdnd_widget) {
- DNDDEBUG << "setting XdndAware for" << xdnd_widget << xdnd_widget->xcb_window();
+ if (window) {
+ qCDebug(lcQpaXDnd) << "setting XdndAware for" << window->xcb_window();
xcb_atom_t atm = xdnd_version;
- xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, xdnd_widget->xcb_window(),
+ xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, window->xcb_window(),
atom(QXcbAtom::XdndAware), XCB_ATOM_ATOM, 32, 1, &atm);
return true;
} else {
return false;
}
} else {
- if ((w->window()->type() == Qt::Desktop)) {
+ if (w->window()->type() == Qt::Desktop) {
xcb_delete_property(xcb_connection(), w->xcb_window(), atom(QXcbAtom::XdndProxy));
delete desktop_proxy;
desktop_proxy = 0;
} else {
- DNDDEBUG << "not deleting XDndAware";
+ qCDebug(lcQpaXDnd) << "not deleting XDndAware";
}
return true;
}
@@ -1293,7 +1276,6 @@ QVariant QXcbDropData::xdndObtainData(const QByteArray &format, QVariant::Type r
return mimeConvertToFormat(c, a, result, QLatin1String(format), requestedType, encoding);
}
-
bool QXcbDropData::hasFormat_sys(const QString &format) const
{
return formats().contains(format);
diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h
index 60287b717b..c19008c04b 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.h
+++ b/src/plugins/platforms/xcb/qxcbdrag.h
@@ -78,14 +78,15 @@ public:
void startDrag() override;
void cancel() override;
- void move(const QPoint &globalPos) override;
- void drop(const QPoint &globalPos) override;
+ void move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) override;
+ void drop(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) override;
void endDrag() override;
void handleEnter(QPlatformWindow *window, const xcb_client_message_event_t *event, xcb_window_t proxy = 0);
void handlePosition(QPlatformWindow *w, const xcb_client_message_event_t *event);
void handleLeave(QPlatformWindow *w, const xcb_client_message_event_t *event);
- void handleDrop(QPlatformWindow *, const xcb_client_message_event_t *event);
+ void handleDrop(QPlatformWindow *, const xcb_client_message_event_t *event,
+ Qt::MouseButtons b = 0, Qt::KeyboardModifiers mods = 0);
void handleStatus(const xcb_client_message_event_t *event);
void handleSelectionRequest(const xcb_selection_request_event_t *event);
@@ -100,12 +101,15 @@ public:
protected:
void timerEvent(QTimerEvent* e) override;
+ bool findXdndAwareTarget(const QPoint &globalPos, xcb_window_t *target_out);
+
private:
friend class QXcbDropData;
void init();
- void handle_xdnd_position(QPlatformWindow *w, const xcb_client_message_event_t *event);
+ void handle_xdnd_position(QPlatformWindow *w, const xcb_client_message_event_t *event,
+ Qt::MouseButtons b = 0, Qt::KeyboardModifiers mods = 0);
void handle_xdnd_status(const xcb_client_message_event_t *event);
void send_leave();
@@ -139,6 +143,9 @@ private:
bool dropped;
bool canceled;
+ // A window from Unity DnD Manager, which does not respect the XDnD spec
+ xcb_window_t xdndCollectionWindow = XCB_NONE;
+
// top-level window we sent position to last.
xcb_window_t current_target;
// window to send events to (always valid if current_target)
diff --git a/src/plugins/platforms/xcb/qxcbeventdispatcher.cpp b/src/plugins/platforms/xcb/qxcbeventdispatcher.cpp
new file mode 100644
index 0000000000..3cb2a5b5ef
--- /dev/null
+++ b/src/plugins/platforms/xcb/qxcbeventdispatcher.cpp
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 "qxcbeventdispatcher.h"
+#include "qxcbconnection.h"
+
+#include <QtCore/QCoreApplication>
+
+#include <qpa/qwindowsysteminterface.h>
+
+QT_BEGIN_NAMESPACE
+
+QXcbUnixEventDispatcher::QXcbUnixEventDispatcher(QXcbConnection *connection, QObject *parent)
+ : QEventDispatcherUNIX(parent)
+ , m_connection(connection)
+{
+}
+
+QXcbUnixEventDispatcher::~QXcbUnixEventDispatcher()
+{
+}
+
+bool QXcbUnixEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ const bool didSendEvents = QEventDispatcherUNIX::processEvents(flags);
+ m_connection->processXcbEvents(flags);
+ // The following line should not be necessary after QTBUG-70095
+ return QWindowSystemInterface::sendWindowSystemEvents(flags) || didSendEvents;
+}
+
+bool QXcbUnixEventDispatcher::hasPendingEvents()
+{
+ extern uint qGlobalPostedEventsCount();
+ return qGlobalPostedEventsCount() || QWindowSystemInterface::windowSystemEventsQueued();
+}
+
+void QXcbUnixEventDispatcher::flush()
+{
+ if (qApp)
+ qApp->sendPostedEvents();
+}
+
+#if QT_CONFIG(glib)
+struct XcbEventSource
+{
+ GSource source;
+ QXcbGlibEventDispatcher *dispatcher;
+ QXcbGlibEventDispatcherPrivate *dispatcher_p;
+ QXcbConnection *connection = nullptr;
+};
+
+static gboolean xcbSourcePrepare(GSource *source, gint *timeout)
+{
+ Q_UNUSED(timeout)
+ auto xcbEventSource = reinterpret_cast<XcbEventSource *>(source);
+ return xcbEventSource->dispatcher_p->wakeUpCalled;
+}
+
+static gboolean xcbSourceCheck(GSource *source)
+{
+ return xcbSourcePrepare(source, nullptr);
+}
+
+static gboolean xcbSourceDispatch(GSource *source, GSourceFunc, gpointer)
+{
+ auto xcbEventSource = reinterpret_cast<XcbEventSource *>(source);
+ QEventLoop::ProcessEventsFlags flags = xcbEventSource->dispatcher->flags();
+ xcbEventSource->connection->processXcbEvents(flags);
+ // The following line should not be necessary after QTBUG-70095
+ QWindowSystemInterface::sendWindowSystemEvents(flags);
+ return true;
+}
+
+QXcbGlibEventDispatcher::QXcbGlibEventDispatcher(QXcbConnection *connection, QObject *parent)
+ : QEventDispatcherGlib(*new QXcbGlibEventDispatcherPrivate(), parent)
+{
+ Q_D(QXcbGlibEventDispatcher);
+
+ m_xcbEventSourceFuncs.prepare = xcbSourcePrepare;
+ m_xcbEventSourceFuncs.check = xcbSourceCheck;
+ m_xcbEventSourceFuncs.dispatch = xcbSourceDispatch;
+ m_xcbEventSourceFuncs.finalize = nullptr;
+
+ m_xcbEventSource = reinterpret_cast<XcbEventSource *>(
+ g_source_new(&m_xcbEventSourceFuncs, sizeof(XcbEventSource)));
+
+ m_xcbEventSource->dispatcher = this;
+ m_xcbEventSource->dispatcher_p = d_func();
+ m_xcbEventSource->connection = connection;
+
+ g_source_set_can_recurse(&m_xcbEventSource->source, true);
+ g_source_attach(&m_xcbEventSource->source, d->mainContext);
+}
+
+QXcbGlibEventDispatcherPrivate::QXcbGlibEventDispatcherPrivate()
+{
+}
+
+QXcbGlibEventDispatcher::~QXcbGlibEventDispatcher()
+{
+ g_source_destroy(&m_xcbEventSource->source);
+ g_source_unref(&m_xcbEventSource->source);
+}
+
+bool QXcbGlibEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ m_flags = flags;
+ return QEventDispatcherGlib::processEvents(m_flags);
+}
+
+#endif // QT_CONFIG(glib)
+
+QAbstractEventDispatcher *QXcbEventDispatcher::createEventDispatcher(QXcbConnection *connection)
+{
+#if QT_CONFIG(glib)
+ if (qEnvironmentVariableIsEmpty("QT_NO_GLIB") && QEventDispatcherGlib::versionSupported()) {
+ qCDebug(lcQpaXcb, "using glib dispatcher");
+ return new QXcbGlibEventDispatcher(connection);
+ } else
+#endif
+ {
+ qCDebug(lcQpaXcb, "using unix dispatcher");
+ return new QXcbUnixEventDispatcher(connection);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbeventdispatcher.h b/src/plugins/platforms/xcb/qxcbeventdispatcher.h
new file mode 100644
index 0000000000..6aadd63a70
--- /dev/null
+++ b/src/plugins/platforms/xcb/qxcbeventdispatcher.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 QXCBEVENTDISPATCHER_H
+#define QXCBEVENTDISPATCHER_H
+
+#include <QtCore/QObject>
+#include <QtCore/QEventLoop>
+
+#include <QtCore/private/qeventdispatcher_unix_p.h>
+#if QT_CONFIG(glib)
+#include <QtCore/private/qeventdispatcher_glib_p.h>
+#include <glib.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QXcbConnection;
+
+class QXcbUnixEventDispatcher : public QEventDispatcherUNIX
+{
+ Q_OBJECT
+public:
+ explicit QXcbUnixEventDispatcher(QXcbConnection *connection, QObject *parent = nullptr);
+ ~QXcbUnixEventDispatcher();
+ bool processEvents(QEventLoop::ProcessEventsFlags flags) override;
+
+ // Maybe some user code depends on deprecated QUnixEventDispatcherQPA::
+ // hasPendingEvents() / flush() implementation, so keep it around until
+ // Qt 6. These methods are deprecated in QAbstractEventDispatcher.
+ bool hasPendingEvents() override; // ### Qt 6 remove
+ void flush() override; // ### Qt 6 remove
+
+private:
+ QXcbConnection *m_connection;
+};
+
+#if QT_CONFIG(glib)
+
+struct XcbEventSource;
+class QXcbGlibEventDispatcherPrivate;
+
+class QXcbGlibEventDispatcher : public QEventDispatcherGlib
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QXcbGlibEventDispatcher)
+
+public:
+ explicit QXcbGlibEventDispatcher(QXcbConnection *connection, QObject *parent = nullptr);
+ ~QXcbGlibEventDispatcher();
+
+ bool processEvents(QEventLoop::ProcessEventsFlags flags) override;
+ QEventLoop::ProcessEventsFlags flags() const { return m_flags; }
+
+private:
+ XcbEventSource *m_xcbEventSource;
+ GSourceFuncs m_xcbEventSourceFuncs;
+ QEventLoop::ProcessEventsFlags m_flags;
+};
+
+class QXcbGlibEventDispatcherPrivate : public QEventDispatcherGlibPrivate
+{
+ Q_DECLARE_PUBLIC(QXcbGlibEventDispatcher)
+
+public:
+ QXcbGlibEventDispatcherPrivate();
+};
+
+#endif // QT_CONFIG(glib)
+
+class QXcbEventDispatcher
+{
+public:
+ static QAbstractEventDispatcher *createEventDispatcher(QXcbConnection *connection);
+
+private:
+ QXcbConnection *m_connection;
+};
+
+QT_END_NAMESPACE
+
+#endif // QXCBEVENTDISPATCHER_H
diff --git a/src/plugins/platforms/xcb/qxcbeventqueue.cpp b/src/plugins/platforms/xcb/qxcbeventqueue.cpp
new file mode 100644
index 0000000000..862f68764b
--- /dev/null
+++ b/src/plugins/platforms/xcb/qxcbeventqueue.cpp
@@ -0,0 +1,383 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 "qxcbeventqueue.h"
+#include "qxcbconnection.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QAbstractEventDispatcher>
+#include <QtCore/QMutex>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+static QBasicMutex qAppExiting;
+static bool dispatcherOwnerDestructing = false;
+
+/*!
+ \class QXcbEventQueue
+ \internal
+
+ Lock-free event passing:
+
+ The lock-free solution uses a singly-linked list to pass events from the
+ reader thread to the main thread. An atomic operation is used to sync the
+ tail node of the list between threads. The reader thread takes special care
+ when accessing the tail node. It does not dequeue the last node and does not
+ access (read or write) the tail node's 'next' member. This lets the reader
+ add more items at the same time as the main thread is dequeuing nodes from
+ the head. A custom linked list implementation is used, because QLinkedList
+ does not have any thread-safety guarantees and the custom list is more
+ lightweight - no reference counting, back links, etc.
+
+ Memory management:
+
+ In a normally functioning application, XCB plugin won't buffer more than few
+ batches of events, couple events per batch. Instead of constantly calling
+ new / delete, we can create a pool of nodes that we reuse. The main thread
+ uses an atomic operation to sync how many nodes have been restored (available
+ for reuse). If at some point a user application will block the main thread
+ for a long time, we might run out of nodes in the pool. Then we create nodes
+ on a heap. These will be automatically "garbage collected" out of the linked
+ list, once the main thread stops blocking.
+*/
+
+QXcbEventQueue::QXcbEventQueue(QXcbConnection *connection)
+ : m_connection(connection)
+{
+ // When running test cases in auto tests, static variables are preserved
+ // between test function runs, even if Q*Application object is destroyed.
+ // Reset to default value to account for this.
+ dispatcherOwnerDestructing = false;
+ qAddPostRoutine([]() {
+ QMutexLocker locker(&qAppExiting);
+ dispatcherOwnerDestructing = true;
+ });
+
+ // Lets init the list with one node, so we don't have to check for
+ // this special case in various places.
+ m_head = m_flushedTail = qXcbEventNodeFactory(nullptr);
+ m_tail.store(m_head, std::memory_order_release);
+
+ start();
+}
+
+QXcbEventQueue::~QXcbEventQueue()
+{
+ if (isRunning()) {
+ sendCloseConnectionEvent();
+ wait();
+ }
+
+ while (xcb_generic_event_t *event = takeFirst())
+ free(event);
+
+ if (m_head && m_head->fromHeap)
+ delete m_head; // the deferred node
+
+ qCDebug(lcQpaEventReader) << "nodes on heap:" << m_nodesOnHeap;
+}
+
+xcb_generic_event_t *QXcbEventQueue::takeFirst(QEventLoop::ProcessEventsFlags flags)
+{
+ // This is the level at which we were moving excluded user input events into
+ // separate queue in Qt 4 (see qeventdispatcher_x11.cpp). In this case
+ // QXcbEventQueue represents Xlib's internal event queue. In Qt 4, Xlib's
+ // event queue peeking APIs would not see these events anymore, the same way
+ // our peeking functions do not consider m_inputEvents. This design is
+ // intentional to keep the same behavior. We could do filtering directly on
+ // QXcbEventQueue, without the m_inputEvents, but it is not clear if it is
+ // needed by anyone who peeks at the native event queue.
+
+ bool excludeUserInputEvents = flags.testFlag(QEventLoop::ExcludeUserInputEvents);
+ if (excludeUserInputEvents) {
+ xcb_generic_event_t *event = nullptr;
+ while ((event = takeFirst())) {
+ if (m_connection->isUserInputEvent(event)) {
+ m_inputEvents << event;
+ continue;
+ }
+ break;
+ }
+ return event;
+ }
+
+ if (!m_inputEvents.isEmpty())
+ return m_inputEvents.takeFirst();
+ return takeFirst();
+}
+
+xcb_generic_event_t *QXcbEventQueue::takeFirst()
+{
+ if (isEmpty())
+ return nullptr;
+
+ xcb_generic_event_t *event = nullptr;
+ do {
+ event = m_head->event;
+ if (m_head == m_flushedTail) {
+ // defer dequeuing until next successful flush of events
+ if (event) // check if not cleared already by some filter
+ m_head->event = nullptr; // if not, clear it
+ } else {
+ dequeueNode();
+ if (!event)
+ continue; // consumed by filter or deferred node
+ }
+ } while (!isEmpty() && !event);
+
+ m_queueModified = m_peekerIndexCacheDirty = true;
+
+ return event;
+}
+
+void QXcbEventQueue::dequeueNode()
+{
+ QXcbEventNode *node = m_head;
+ m_head = m_head->next;
+ if (node->fromHeap)
+ delete node;
+ else
+ m_nodesRestored.fetch_add(1, std::memory_order_release);
+}
+
+void QXcbEventQueue::flushBufferedEvents()
+{
+ m_flushedTail = m_tail.load(std::memory_order_acquire);
+}
+
+QXcbEventNode *QXcbEventQueue::qXcbEventNodeFactory(xcb_generic_event_t *event)
+{
+ static QXcbEventNode qXcbNodePool[PoolSize];
+
+ if (m_freeNodes == 0) // out of nodes, check if the main thread has released any
+ m_freeNodes = m_nodesRestored.exchange(0, std::memory_order_acquire);
+
+ if (m_freeNodes) {
+ m_freeNodes--;
+ if (m_poolIndex == PoolSize) {
+ // wrap back to the beginning, we always take and restore nodes in-order
+ m_poolIndex = 0;
+ }
+ QXcbEventNode *node = &qXcbNodePool[m_poolIndex++];
+ node->event = event;
+ node->next = nullptr;
+ return node;
+ }
+
+ // the main thread is not flushing events and thus the pool has become empty
+ auto node = new QXcbEventNode(event);
+ node->fromHeap = true;
+ qCDebug(lcQpaEventReader) << "[heap] " << m_nodesOnHeap++;
+ return node;
+}
+
+void QXcbEventQueue::run()
+{
+ xcb_generic_event_t *event = nullptr;
+ xcb_connection_t *connection = m_connection->xcb_connection();
+ QXcbEventNode *tail = m_head;
+
+ auto enqueueEvent = [&tail, this](xcb_generic_event_t *event) {
+ if (!isCloseConnectionEvent(event)) {
+ tail->next = qXcbEventNodeFactory(event);
+ tail = tail->next;
+ m_tail.store(tail, std::memory_order_release);
+ }
+ };
+
+ while (!m_closeConnectionDetected && (event = xcb_wait_for_event(connection))) {
+ enqueueEvent(event);
+ while (!m_closeConnectionDetected && (event = xcb_poll_for_queued_event(connection)))
+ enqueueEvent(event);
+ wakeUpDispatcher();
+ }
+
+ if (!m_closeConnectionDetected) {
+ // Connection was terminated not by us. Wake up dispatcher, which will
+ // call processXcbEvents(), where we handle the connection errors via
+ // xcb_connection_has_error().
+ wakeUpDispatcher();
+ }
+}
+
+void QXcbEventQueue::wakeUpDispatcher()
+{
+ QMutexLocker locker(&qAppExiting);
+ if (!dispatcherOwnerDestructing) {
+ // This thread can run before a dispatcher has been created,
+ // so check if it is ready.
+ if (QCoreApplication::eventDispatcher())
+ QCoreApplication::eventDispatcher()->wakeUp();
+ }
+}
+
+qint32 QXcbEventQueue::generatePeekerId()
+{
+ const qint32 peekerId = m_peekerIdSource++;
+ m_peekerToNode.insert(peekerId, nullptr);
+ return peekerId;
+}
+
+bool QXcbEventQueue::removePeekerId(qint32 peekerId)
+{
+ const auto it = m_peekerToNode.find(peekerId);
+ if (it == m_peekerToNode.constEnd()) {
+ qCWarning(lcQpaXcb, "failed to remove unknown peeker id: %d", peekerId);
+ return false;
+ }
+ m_peekerToNode.erase(it);
+ if (m_peekerToNode.isEmpty()) {
+ m_peekerIdSource = 0; // Once the hash becomes empty, we can start reusing IDs
+ m_peekerIndexCacheDirty = false;
+ }
+ return true;
+}
+
+bool QXcbEventQueue::peekEventQueue(PeekerCallback peeker, void *peekerData,
+ PeekOptions option, qint32 peekerId)
+{
+ const bool peekerIdProvided = peekerId != -1;
+ auto peekerToNodeIt = m_peekerToNode.find(peekerId);
+
+ if (peekerIdProvided && peekerToNodeIt == m_peekerToNode.constEnd()) {
+ qCWarning(lcQpaXcb, "failed to find index for unknown peeker id: %d", peekerId);
+ return false;
+ }
+
+ const bool useCache = option.testFlag(PeekOption::PeekFromCachedIndex);
+ if (useCache && !peekerIdProvided) {
+ qCWarning(lcQpaXcb, "PeekOption::PeekFromCachedIndex requires peeker id");
+ return false;
+ }
+
+ if (peekerIdProvided && m_peekerIndexCacheDirty) {
+ for (auto &node : m_peekerToNode) // reset cache
+ node = nullptr;
+ m_peekerIndexCacheDirty = false;
+ }
+
+ flushBufferedEvents();
+ if (isEmpty())
+ return false;
+
+ const auto startNode = [this, useCache, peekerToNodeIt]() -> QXcbEventNode * {
+ if (useCache) {
+ const QXcbEventNode *cachedNode = peekerToNodeIt.value();
+ if (!cachedNode)
+ return m_head; // cache was reset
+ if (cachedNode == m_flushedTail)
+ return nullptr; // no new events since the last call
+ return cachedNode->next;
+ }
+ return m_head;
+ }();
+
+ if (!startNode)
+ return false;
+
+ // A peeker may call QCoreApplication::processEvents(), which will cause
+ // QXcbConnection::processXcbEvents() to modify the queue we are currently
+ // looping through;
+ m_queueModified = false;
+ bool result = false;
+
+ QXcbEventNode *node = startNode;
+ do {
+ xcb_generic_event_t *event = node->event;
+ if (event && peeker(event, peekerData)) {
+ result = true;
+ break;
+ }
+ if (node == m_flushedTail)
+ break;
+ node = node->next;
+ } while (!m_queueModified);
+
+ // Update the cached index if the queue was not modified, and hence the
+ // cache is still valid.
+ if (peekerIdProvided && node != startNode && !m_queueModified) {
+ // Before updating, make sure that a peeker callback did not remove
+ // the peeker id.
+ peekerToNodeIt = m_peekerToNode.find(peekerId);
+ if (peekerToNodeIt != m_peekerToNode.constEnd())
+ *peekerToNodeIt = node; // id still in the cache, update node
+ }
+
+ return result;
+}
+
+void QXcbEventQueue::sendCloseConnectionEvent() const
+{
+ // A hack to close XCB connection. Apparently XCB does not have any APIs for this?
+ xcb_client_message_event_t event;
+ memset(&event, 0, sizeof(event));
+
+ xcb_connection_t *c = m_connection->xcb_connection();
+ const xcb_window_t window = xcb_generate_id(c);
+ xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_connection->setup());
+ xcb_screen_t *screen = it.data;
+ xcb_create_window(c, XCB_COPY_FROM_PARENT,
+ window, screen->root,
+ 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY,
+ screen->root_visual, 0, nullptr);
+
+ event.response_type = XCB_CLIENT_MESSAGE;
+ event.format = 32;
+ event.sequence = 0;
+ event.window = window;
+ event.type = m_connection->atom(QXcbAtom::_QT_CLOSE_CONNECTION);
+ event.data.data32[0] = 0;
+
+ xcb_send_event(c, false, window, XCB_EVENT_MASK_NO_EVENT, reinterpret_cast<const char *>(&event));
+ xcb_destroy_window(c, window);
+ xcb_flush(c);
+}
+
+bool QXcbEventQueue::isCloseConnectionEvent(const xcb_generic_event_t *event)
+{
+ if (event && (event->response_type & ~0x80) == XCB_CLIENT_MESSAGE) {
+ auto clientMessage = reinterpret_cast<const xcb_client_message_event_t *>(event);
+ if (clientMessage->type == m_connection->atom(QXcbAtom::_QT_CLOSE_CONNECTION))
+ m_closeConnectionDetected = true;
+ }
+ return m_closeConnectionDetected;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbeventqueue.h b/src/plugins/platforms/xcb/qxcbeventqueue.h
new file mode 100644
index 0000000000..235f2824be
--- /dev/null
+++ b/src/plugins/platforms/xcb/qxcbeventqueue.h
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 QXCBEVENTQUEUE_H
+#define QXCBEVENTQUEUE_H
+
+#include <QtCore/QThread>
+#include <QtCore/QHash>
+#include <QtCore/QEventLoop>
+#include <QtCore/QVector>
+
+#include <xcb/xcb.h>
+
+#include <atomic>
+
+QT_BEGIN_NAMESPACE
+
+struct QXcbEventNode {
+ QXcbEventNode(xcb_generic_event_t *e = nullptr)
+ : event(e) { }
+
+ xcb_generic_event_t *event;
+ QXcbEventNode *next = nullptr;
+ bool fromHeap = false;
+};
+
+class QXcbConnection;
+class QAbstractEventDispatcher;
+
+class QXcbEventQueue : public QThread
+{
+ Q_OBJECT
+public:
+ QXcbEventQueue(QXcbConnection *connection);
+ ~QXcbEventQueue();
+
+ enum { PoolSize = 100 }; // 2.4 kB with 100 nodes
+
+ enum PeekOption {
+ PeekDefault = 0, // see qx11info_x11.h for docs
+ PeekFromCachedIndex = 1,
+ PeekRetainMatch = 2,
+ PeekRemoveMatch = 3,
+ PeekRemoveMatchContinue = 4
+ };
+ Q_DECLARE_FLAGS(PeekOptions, PeekOption)
+
+ void run() override;
+
+ bool isEmpty() const { return m_head == m_flushedTail && !m_head->event; }
+ xcb_generic_event_t *takeFirst(QEventLoop::ProcessEventsFlags flags);
+ xcb_generic_event_t *takeFirst();
+ void flushBufferedEvents();
+ void wakeUpDispatcher();
+
+ // ### peek() and peekEventQueue() could be unified. Note that peekEventQueue()
+ // is public API exposed via QX11Extras/QX11Info.
+ template<typename Peeker>
+ xcb_generic_event_t *peek(Peeker &&peeker) {
+ return peek(PeekRemoveMatch, std::forward<Peeker>(peeker));
+ }
+ template<typename Peeker>
+ inline xcb_generic_event_t *peek(PeekOption config, Peeker &&peeker);
+
+ qint32 generatePeekerId();
+ bool removePeekerId(qint32 peekerId);
+
+ using PeekerCallback = bool (*)(xcb_generic_event_t *event, void *peekerData);
+ bool peekEventQueue(PeekerCallback peeker, void *peekerData = nullptr,
+ PeekOptions option = PeekDefault, qint32 peekerId = -1);
+
+private:
+ QXcbEventNode *qXcbEventNodeFactory(xcb_generic_event_t *event);
+ void dequeueNode();
+
+ void sendCloseConnectionEvent() const;
+ bool isCloseConnectionEvent(const xcb_generic_event_t *event);
+
+ QXcbEventNode *m_head = nullptr;
+ QXcbEventNode *m_flushedTail = nullptr;
+ std::atomic<QXcbEventNode *> m_tail { nullptr };
+ std::atomic_uint m_nodesRestored { 0 };
+
+ QXcbConnection *m_connection = nullptr;
+ bool m_closeConnectionDetected = false;
+
+ uint m_freeNodes = PoolSize;
+ uint m_poolIndex = 0;
+
+ qint32 m_peekerIdSource = 0;
+ bool m_queueModified = false;
+ bool m_peekerIndexCacheDirty = false;
+ QHash<qint32, QXcbEventNode *> m_peekerToNode;
+
+ QVector<xcb_generic_event_t *> m_inputEvents;
+
+ // debug stats
+ quint64 m_nodesOnHeap = 0;
+};
+
+template<typename Peeker>
+xcb_generic_event_t *QXcbEventQueue::peek(PeekOption option, Peeker &&peeker)
+{
+ flushBufferedEvents();
+ if (isEmpty())
+ return nullptr;
+
+ QXcbEventNode *node = m_head;
+ do {
+ xcb_generic_event_t *event = node->event;
+ if (event && peeker(event, event->response_type & ~0x80)) {
+ if (option == PeekRemoveMatch || option == PeekRemoveMatchContinue)
+ node->event = nullptr;
+ if (option != PeekRemoveMatchContinue)
+ return event;
+ }
+ if (node == m_flushedTail)
+ break;
+ node = node->next;
+ } while (true);
+
+ return nullptr;
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index bf9eaacbb8..ed9e87a036 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -46,6 +46,8 @@
#include "qxcbbackingstore.h"
#include "qxcbnativeinterface.h"
#include "qxcbclipboard.h"
+#include "qxcbeventqueue.h"
+#include "qxcbeventdispatcher.h"
#if QT_CONFIG(draganddrop)
#include "qxcbdrag.h"
#endif
@@ -57,7 +59,6 @@
#include <xcb/xcb.h>
-#include <QtEventDispatcherSupport/private/qgenericunixeventdispatcher_p.h>
#include <QtFontDatabaseSupport/private/qgenericunixfontdatabase_p.h>
#include <QtServiceSupport/private/qgenericunixservices_p.h>
@@ -69,12 +70,12 @@
#define register /* C++17 deprecated register */
#include <X11/Xlib.h>
#undef register
+#endif
#if QT_CONFIG(xcb_native_painting)
#include "qxcbnativepainting.h"
#include "qpixmap_x11_p.h"
#include "qbackingstore_x11_p.h"
#endif
-#endif
#include <qpa/qplatforminputcontextfactory_p.h>
#include <private/qgenericunixthemes_p.h>
@@ -136,6 +137,8 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters, int &argc, char
m_instance = this;
qApp->setAttribute(Qt::AA_CompressHighFrequencyEvents, true);
+ QWindowSystemInterface::setPlatformFiltersEvents(true);
+
qRegisterMetaType<QXcbWindow*>();
#if QT_CONFIG(xcb_xlib)
XInitThreads();
@@ -192,14 +195,17 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters, int &argc, char
const int numParameters = parameters.size();
m_connections.reserve(1 + numParameters / 2);
+
auto conn = new QXcbConnection(m_nativeInterface.data(), m_canGrab, m_defaultVisualId, displayName);
- if (conn->isConnected())
- m_connections << conn;
- else
+ if (!conn->isConnected()) {
delete conn;
+ return;
+ }
+ m_connections << conn;
+ // ### Qt 6 (QTBUG-52408) remove this multi-connection code path
for (int i = 0; i < numParameters - 1; i += 2) {
- qCDebug(lcQpaScreen) << "connecting to additional display: " << parameters.at(i) << parameters.at(i+1);
+ qCDebug(lcQpaXcb) << "connecting to additional display: " << parameters.at(i) << parameters.at(i+1);
QString display = parameters.at(i) + QLatin1Char(':') + parameters.at(i+1);
conn = new QXcbConnection(m_nativeInterface.data(), m_canGrab, m_defaultVisualId, display.toLatin1().constData());
if (conn->isConnected())
@@ -208,11 +214,6 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters, int &argc, char
delete conn;
}
- if (m_connections.isEmpty()) {
- qCritical("Could not connect to any X display.");
- exit(1);
- }
-
m_fontDatabase.reset(new QGenericUnixFontDatabase());
#if QT_CONFIG(xcb_native_painting)
@@ -241,10 +242,11 @@ QPlatformPixmap *QXcbIntegration::createPlatformPixmap(QPlatformPixmap::PixelTyp
QPlatformWindow *QXcbIntegration::createPlatformWindow(QWindow *window) const
{
- QXcbScreen *screen = static_cast<QXcbScreen *>(window->screen()->handle());
- QXcbGlIntegration *glIntegration = screen->connection()->glIntegration();
- if (window->type() != Qt::Desktop) {
+ QXcbGlIntegration *glIntegration = nullptr;
+ const bool isTrayIconWindow = QXcbWindow::isTrayIconWindow(window);;
+ if (window->type() != Qt::Desktop && !isTrayIconWindow) {
if (window->supportsOpenGL()) {
+ glIntegration = defaultConnection()->glIntegration();
if (glIntegration) {
QXcbWindow *xcbWindow = glIntegration->createWindow(window);
xcbWindow->create();
@@ -259,7 +261,7 @@ QPlatformWindow *QXcbIntegration::createPlatformWindow(QWindow *window) const
}
}
- Q_ASSERT(window->type() == Qt::Desktop || !window->supportsOpenGL()
+ Q_ASSERT(window->type() == Qt::Desktop || isTrayIconWindow || !window->supportsOpenGL()
|| (!glIntegration && window->surfaceType() == QSurface::RasterGLSurface)); // for VNC
QXcbWindow *xcbWindow = new QXcbWindow(window);
xcbWindow->create();
@@ -286,6 +288,10 @@ QPlatformOpenGLContext *QXcbIntegration::createPlatformOpenGLContext(QOpenGLCont
QPlatformBackingStore *QXcbIntegration::createPlatformBackingStore(QWindow *window) const
{
+ const bool isTrayIconWindow = QXcbWindow::isTrayIconWindow(window);
+ if (isTrayIconWindow)
+ return new QXcbSystemTrayBackingStore(window);
+
#if QT_CONFIG(xcb_native_painting)
if (nativePaintingEnabled())
return new QXcbNativeBackingStore(window);
@@ -313,8 +319,7 @@ bool QXcbIntegration::hasCapability(QPlatformIntegration::Capability cap) const
{
const auto *connection = qAsConst(m_connections).first();
if (const auto *integration = connection->glIntegration())
- return cap != ThreadedOpenGL
- || (connection->threadedEventHandling() && integration->supportsThreadedOpenGL());
+ return cap != ThreadedOpenGL || integration->supportsThreadedOpenGL();
return false;
}
@@ -338,10 +343,7 @@ bool QXcbIntegration::hasCapability(QPlatformIntegration::Capability cap) const
QAbstractEventDispatcher *QXcbIntegration::createEventDispatcher() const
{
- QAbstractEventDispatcher *dispatcher = createUnixEventDispatcher();
- for (int i = 0; i < m_connections.size(); i++)
- m_connections[i]->eventReader()->registerEventDispatcher(dispatcher);
- return dispatcher;
+ return QXcbEventDispatcher::createEventDispatcher(defaultConnection());
}
void QXcbIntegration::initialize()
@@ -381,8 +383,17 @@ QPlatformClipboard *QXcbIntegration::clipboard() const
#endif
#if QT_CONFIG(draganddrop)
+#include <private/qsimpledrag_p.h>
QPlatformDrag *QXcbIntegration::drag() const
{
+ static const bool useSimpleDrag = qEnvironmentVariableIsSet("QT_XCB_USE_SIMPLE_DRAG");
+ if (Q_UNLIKELY(useSimpleDrag)) { // This is useful for testing purposes
+ static QSimpleDrag *simpleDrag = nullptr;
+ if (!simpleDrag)
+ simpleDrag = new QSimpleDrag();
+ return simpleDrag;
+ }
+
return m_connections.at(0)->drag();
}
#endif
@@ -414,10 +425,7 @@ QPlatformServices *QXcbIntegration::services() const
Qt::KeyboardModifiers QXcbIntegration::queryKeyboardModifiers() const
{
- int keybMask = 0;
- QXcbConnection *conn = m_connections.at(0);
- QXcbCursor::queryPointer(conn, 0, 0, &keybMask);
- return conn->keyboard()->translateModifiers(keybMask);
+ return m_connections.at(0)->queryKeyboardModifiers();
}
QList<int> QXcbIntegration::possibleKeys(const QKeyEvent *e) const
diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h
index 69e49cb7f6..f13e232291 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.h
+++ b/src/plugins/platforms/xcb/qxcbintegration.h
@@ -53,7 +53,6 @@ QT_BEGIN_NAMESPACE
class QXcbConnection;
class QAbstractEventDispatcher;
class QXcbNativeInterface;
-class QXcbScreen;
class Q_XCB_EXPORT QXcbIntegration : public QPlatformIntegration
{
@@ -103,6 +102,7 @@ public:
QPlatformTheme *createPlatformTheme(const QString &name) const override;
QVariant styleHint(StyleHint hint) const override;
+ bool hasDefaultConnection() const { return !m_connections.isEmpty(); }
QXcbConnection *defaultConnection() const { return m_connections.first(); }
QByteArray wmClass() const;
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index 3733995a0d..c5dc7b21ad 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -49,366 +49,388 @@
#include <QtCore/QMetaEnum>
#include <private/qguiapplication_p.h>
+#include <private/qmakearray_p.h>
#include <xkbcommon/xkbcommon-keysyms.h>
-#if QT_CONFIG(xinput2)
-#include <X11/extensions/XI2proto.h>
-#undef KeyPress
-#undef KeyRelease
+#if QT_CONFIG(xcb_xinput)
+#include <xcb/xinput.h>
#endif
QT_BEGIN_NAMESPACE
-static const unsigned int KeyTbl[] = {
- // misc keys
-
- XKB_KEY_Escape, Qt::Key_Escape,
- XKB_KEY_Tab, Qt::Key_Tab,
- XKB_KEY_ISO_Left_Tab, Qt::Key_Backtab,
- XKB_KEY_BackSpace, Qt::Key_Backspace,
- XKB_KEY_Return, Qt::Key_Return,
- XKB_KEY_Insert, Qt::Key_Insert,
- XKB_KEY_Delete, Qt::Key_Delete,
- XKB_KEY_Clear, Qt::Key_Delete,
- XKB_KEY_Pause, Qt::Key_Pause,
- XKB_KEY_Print, Qt::Key_Print,
- 0x1005FF60, Qt::Key_SysReq, // hardcoded Sun SysReq
- 0x1007ff00, Qt::Key_SysReq, // hardcoded X386 SysReq
-
- // cursor movement
-
- XKB_KEY_Home, Qt::Key_Home,
- XKB_KEY_End, Qt::Key_End,
- XKB_KEY_Left, Qt::Key_Left,
- XKB_KEY_Up, Qt::Key_Up,
- XKB_KEY_Right, Qt::Key_Right,
- XKB_KEY_Down, Qt::Key_Down,
- XKB_KEY_Prior, Qt::Key_PageUp,
- XKB_KEY_Next, Qt::Key_PageDown,
-
- // modifiers
-
- XKB_KEY_Shift_L, Qt::Key_Shift,
- XKB_KEY_Shift_R, Qt::Key_Shift,
- XKB_KEY_Shift_Lock, Qt::Key_Shift,
- XKB_KEY_Control_L, Qt::Key_Control,
- XKB_KEY_Control_R, Qt::Key_Control,
- XKB_KEY_Meta_L, Qt::Key_Meta,
- XKB_KEY_Meta_R, Qt::Key_Meta,
- XKB_KEY_Alt_L, Qt::Key_Alt,
- XKB_KEY_Alt_R, Qt::Key_Alt,
- XKB_KEY_Caps_Lock, Qt::Key_CapsLock,
- XKB_KEY_Num_Lock, Qt::Key_NumLock,
- XKB_KEY_Scroll_Lock, Qt::Key_ScrollLock,
- XKB_KEY_Super_L, Qt::Key_Super_L,
- XKB_KEY_Super_R, Qt::Key_Super_R,
- XKB_KEY_Menu, Qt::Key_Menu,
- XKB_KEY_Hyper_L, Qt::Key_Hyper_L,
- XKB_KEY_Hyper_R, Qt::Key_Hyper_R,
- XKB_KEY_Help, Qt::Key_Help,
- 0x1000FF74, Qt::Key_Backtab, // hardcoded HP backtab
- 0x1005FF10, Qt::Key_F11, // hardcoded Sun F36 (labeled F11)
- 0x1005FF11, Qt::Key_F12, // hardcoded Sun F37 (labeled F12)
-
- // numeric and function keypad keys
-
- XKB_KEY_KP_Space, Qt::Key_Space,
- XKB_KEY_KP_Tab, Qt::Key_Tab,
- XKB_KEY_KP_Enter, Qt::Key_Enter,
- //XKB_KEY_KP_F1, Qt::Key_F1,
- //XKB_KEY_KP_F2, Qt::Key_F2,
- //XKB_KEY_KP_F3, Qt::Key_F3,
- //XKB_KEY_KP_F4, Qt::Key_F4,
- XKB_KEY_KP_Home, Qt::Key_Home,
- XKB_KEY_KP_Left, Qt::Key_Left,
- XKB_KEY_KP_Up, Qt::Key_Up,
- XKB_KEY_KP_Right, Qt::Key_Right,
- XKB_KEY_KP_Down, Qt::Key_Down,
- XKB_KEY_KP_Prior, Qt::Key_PageUp,
- XKB_KEY_KP_Next, Qt::Key_PageDown,
- XKB_KEY_KP_End, Qt::Key_End,
- XKB_KEY_KP_Begin, Qt::Key_Clear,
- XKB_KEY_KP_Insert, Qt::Key_Insert,
- XKB_KEY_KP_Delete, Qt::Key_Delete,
- XKB_KEY_KP_Equal, Qt::Key_Equal,
- XKB_KEY_KP_Multiply, Qt::Key_Asterisk,
- XKB_KEY_KP_Add, Qt::Key_Plus,
- XKB_KEY_KP_Separator, Qt::Key_Comma,
- XKB_KEY_KP_Subtract, Qt::Key_Minus,
- XKB_KEY_KP_Decimal, Qt::Key_Period,
- XKB_KEY_KP_Divide, Qt::Key_Slash,
-
- // special non-XF86 function keys
-
- XKB_KEY_Undo, Qt::Key_Undo,
- XKB_KEY_Redo, Qt::Key_Redo,
- XKB_KEY_Find, Qt::Key_Find,
- XKB_KEY_Cancel, Qt::Key_Cancel,
-
- // International input method support keys
-
- // International & multi-key character composition
- XKB_KEY_ISO_Level3_Shift, Qt::Key_AltGr,
- XKB_KEY_Multi_key, Qt::Key_Multi_key,
- XKB_KEY_Codeinput, Qt::Key_Codeinput,
- XKB_KEY_SingleCandidate, Qt::Key_SingleCandidate,
- XKB_KEY_MultipleCandidate, Qt::Key_MultipleCandidate,
- XKB_KEY_PreviousCandidate, Qt::Key_PreviousCandidate,
-
- // Misc Functions
- XKB_KEY_Mode_switch, Qt::Key_Mode_switch,
- XKB_KEY_script_switch, Qt::Key_Mode_switch,
-
- // Japanese keyboard support
- XKB_KEY_Kanji, Qt::Key_Kanji,
- XKB_KEY_Muhenkan, Qt::Key_Muhenkan,
- //XKB_KEY_Henkan_Mode, Qt::Key_Henkan_Mode,
- XKB_KEY_Henkan_Mode, Qt::Key_Henkan,
- XKB_KEY_Henkan, Qt::Key_Henkan,
- XKB_KEY_Romaji, Qt::Key_Romaji,
- XKB_KEY_Hiragana, Qt::Key_Hiragana,
- XKB_KEY_Katakana, Qt::Key_Katakana,
- XKB_KEY_Hiragana_Katakana, Qt::Key_Hiragana_Katakana,
- XKB_KEY_Zenkaku, Qt::Key_Zenkaku,
- XKB_KEY_Hankaku, Qt::Key_Hankaku,
- XKB_KEY_Zenkaku_Hankaku, Qt::Key_Zenkaku_Hankaku,
- XKB_KEY_Touroku, Qt::Key_Touroku,
- XKB_KEY_Massyo, Qt::Key_Massyo,
- XKB_KEY_Kana_Lock, Qt::Key_Kana_Lock,
- XKB_KEY_Kana_Shift, Qt::Key_Kana_Shift,
- XKB_KEY_Eisu_Shift, Qt::Key_Eisu_Shift,
- XKB_KEY_Eisu_toggle, Qt::Key_Eisu_toggle,
- //XKB_KEY_Kanji_Bangou, Qt::Key_Kanji_Bangou,
- //XKB_KEY_Zen_Koho, Qt::Key_Zen_Koho,
- //XKB_KEY_Mae_Koho, Qt::Key_Mae_Koho,
- XKB_KEY_Kanji_Bangou, Qt::Key_Codeinput,
- XKB_KEY_Zen_Koho, Qt::Key_MultipleCandidate,
- XKB_KEY_Mae_Koho, Qt::Key_PreviousCandidate,
-
- // Korean keyboard support
- XKB_KEY_Hangul, Qt::Key_Hangul,
- XKB_KEY_Hangul_Start, Qt::Key_Hangul_Start,
- XKB_KEY_Hangul_End, Qt::Key_Hangul_End,
- XKB_KEY_Hangul_Hanja, Qt::Key_Hangul_Hanja,
- XKB_KEY_Hangul_Jamo, Qt::Key_Hangul_Jamo,
- XKB_KEY_Hangul_Romaja, Qt::Key_Hangul_Romaja,
- //XKB_KEY_Hangul_Codeinput, Qt::Key_Hangul_Codeinput,
- XKB_KEY_Hangul_Codeinput, Qt::Key_Codeinput,
- XKB_KEY_Hangul_Jeonja, Qt::Key_Hangul_Jeonja,
- XKB_KEY_Hangul_Banja, Qt::Key_Hangul_Banja,
- XKB_KEY_Hangul_PreHanja, Qt::Key_Hangul_PreHanja,
- XKB_KEY_Hangul_PostHanja, Qt::Key_Hangul_PostHanja,
- //XKB_KEY_Hangul_SingleCandidate,Qt::Key_Hangul_SingleCandidate,
- //XKB_KEY_Hangul_MultipleCandidate,Qt::Key_Hangul_MultipleCandidate,
- //XKB_KEY_Hangul_PreviousCandidate,Qt::Key_Hangul_PreviousCandidate,
- XKB_KEY_Hangul_SingleCandidate, Qt::Key_SingleCandidate,
- XKB_KEY_Hangul_MultipleCandidate,Qt::Key_MultipleCandidate,
- XKB_KEY_Hangul_PreviousCandidate,Qt::Key_PreviousCandidate,
- XKB_KEY_Hangul_Special, Qt::Key_Hangul_Special,
- //XKB_KEY_Hangul_switch, Qt::Key_Hangul_switch,
- XKB_KEY_Hangul_switch, Qt::Key_Mode_switch,
-
- // dead keys
- XKB_KEY_dead_grave, Qt::Key_Dead_Grave,
- XKB_KEY_dead_acute, Qt::Key_Dead_Acute,
- XKB_KEY_dead_circumflex, Qt::Key_Dead_Circumflex,
- XKB_KEY_dead_tilde, Qt::Key_Dead_Tilde,
- XKB_KEY_dead_macron, Qt::Key_Dead_Macron,
- XKB_KEY_dead_breve, Qt::Key_Dead_Breve,
- XKB_KEY_dead_abovedot, Qt::Key_Dead_Abovedot,
- XKB_KEY_dead_diaeresis, Qt::Key_Dead_Diaeresis,
- XKB_KEY_dead_abovering, Qt::Key_Dead_Abovering,
- XKB_KEY_dead_doubleacute, Qt::Key_Dead_Doubleacute,
- XKB_KEY_dead_caron, Qt::Key_Dead_Caron,
- XKB_KEY_dead_cedilla, Qt::Key_Dead_Cedilla,
- XKB_KEY_dead_ogonek, Qt::Key_Dead_Ogonek,
- XKB_KEY_dead_iota, Qt::Key_Dead_Iota,
- XKB_KEY_dead_voiced_sound, Qt::Key_Dead_Voiced_Sound,
- XKB_KEY_dead_semivoiced_sound, Qt::Key_Dead_Semivoiced_Sound,
- XKB_KEY_dead_belowdot, Qt::Key_Dead_Belowdot,
- XKB_KEY_dead_hook, Qt::Key_Dead_Hook,
- XKB_KEY_dead_horn, Qt::Key_Dead_Horn,
- XKB_KEY_dead_stroke, Qt::Key_Dead_Stroke,
- XKB_KEY_dead_abovecomma, Qt::Key_Dead_Abovecomma,
- XKB_KEY_dead_abovereversedcomma, Qt::Key_Dead_Abovereversedcomma,
- XKB_KEY_dead_doublegrave, Qt::Key_Dead_Doublegrave,
- XKB_KEY_dead_belowring, Qt::Key_Dead_Belowring,
- XKB_KEY_dead_belowmacron, Qt::Key_Dead_Belowmacron,
- XKB_KEY_dead_belowcircumflex, Qt::Key_Dead_Belowcircumflex,
- XKB_KEY_dead_belowtilde, Qt::Key_Dead_Belowtilde,
- XKB_KEY_dead_belowbreve, Qt::Key_Dead_Belowbreve,
- XKB_KEY_dead_belowdiaeresis, Qt::Key_Dead_Belowdiaeresis,
- XKB_KEY_dead_invertedbreve, Qt::Key_Dead_Invertedbreve,
- XKB_KEY_dead_belowcomma, Qt::Key_Dead_Belowcomma,
- XKB_KEY_dead_currency, Qt::Key_Dead_Currency,
- XKB_KEY_dead_a, Qt::Key_Dead_a,
- XKB_KEY_dead_A, Qt::Key_Dead_A,
- XKB_KEY_dead_e, Qt::Key_Dead_e,
- XKB_KEY_dead_E, Qt::Key_Dead_E,
- XKB_KEY_dead_i, Qt::Key_Dead_i,
- XKB_KEY_dead_I, Qt::Key_Dead_I,
- XKB_KEY_dead_o, Qt::Key_Dead_o,
- XKB_KEY_dead_O, Qt::Key_Dead_O,
- XKB_KEY_dead_u, Qt::Key_Dead_u,
- XKB_KEY_dead_U, Qt::Key_Dead_U,
- XKB_KEY_dead_small_schwa, Qt::Key_Dead_Small_Schwa,
- XKB_KEY_dead_capital_schwa, Qt::Key_Dead_Capital_Schwa,
- XKB_KEY_dead_greek, Qt::Key_Dead_Greek,
- XKB_KEY_dead_lowline, Qt::Key_Dead_Lowline,
- XKB_KEY_dead_aboveverticalline, Qt::Key_Dead_Aboveverticalline,
- XKB_KEY_dead_belowverticalline, Qt::Key_Dead_Belowverticalline,
- XKB_KEY_dead_longsolidusoverlay, Qt::Key_Dead_Longsolidusoverlay,
-
- // Special keys from X.org - This include multimedia keys,
- // wireless/bluetooth/uwb keys, special launcher keys, etc.
- XKB_KEY_XF86Back, Qt::Key_Back,
- XKB_KEY_XF86Forward, Qt::Key_Forward,
- XKB_KEY_XF86Stop, Qt::Key_Stop,
- XKB_KEY_XF86Refresh, Qt::Key_Refresh,
- XKB_KEY_XF86Favorites, Qt::Key_Favorites,
- XKB_KEY_XF86AudioMedia, Qt::Key_LaunchMedia,
- XKB_KEY_XF86OpenURL, Qt::Key_OpenUrl,
- XKB_KEY_XF86HomePage, Qt::Key_HomePage,
- XKB_KEY_XF86Search, Qt::Key_Search,
- XKB_KEY_XF86AudioLowerVolume, Qt::Key_VolumeDown,
- XKB_KEY_XF86AudioMute, Qt::Key_VolumeMute,
- XKB_KEY_XF86AudioRaiseVolume, Qt::Key_VolumeUp,
- XKB_KEY_XF86AudioPlay, Qt::Key_MediaPlay,
- XKB_KEY_XF86AudioStop, Qt::Key_MediaStop,
- XKB_KEY_XF86AudioPrev, Qt::Key_MediaPrevious,
- XKB_KEY_XF86AudioNext, Qt::Key_MediaNext,
- XKB_KEY_XF86AudioRecord, Qt::Key_MediaRecord,
- XKB_KEY_XF86AudioPause, Qt::Key_MediaPause,
- XKB_KEY_XF86Mail, Qt::Key_LaunchMail,
- XKB_KEY_XF86MyComputer, Qt::Key_Launch0, // ### Qt 6: remap properly
- XKB_KEY_XF86Calculator, Qt::Key_Launch1,
- XKB_KEY_XF86Memo, Qt::Key_Memo,
- XKB_KEY_XF86ToDoList, Qt::Key_ToDoList,
- XKB_KEY_XF86Calendar, Qt::Key_Calendar,
- XKB_KEY_XF86PowerDown, Qt::Key_PowerDown,
- XKB_KEY_XF86ContrastAdjust, Qt::Key_ContrastAdjust,
- XKB_KEY_XF86Standby, Qt::Key_Standby,
- XKB_KEY_XF86MonBrightnessUp, Qt::Key_MonBrightnessUp,
- XKB_KEY_XF86MonBrightnessDown, Qt::Key_MonBrightnessDown,
- XKB_KEY_XF86KbdLightOnOff, Qt::Key_KeyboardLightOnOff,
- XKB_KEY_XF86KbdBrightnessUp, Qt::Key_KeyboardBrightnessUp,
- XKB_KEY_XF86KbdBrightnessDown, Qt::Key_KeyboardBrightnessDown,
- XKB_KEY_XF86PowerOff, Qt::Key_PowerOff,
- XKB_KEY_XF86WakeUp, Qt::Key_WakeUp,
- XKB_KEY_XF86Eject, Qt::Key_Eject,
- XKB_KEY_XF86ScreenSaver, Qt::Key_ScreenSaver,
- XKB_KEY_XF86WWW, Qt::Key_WWW,
- XKB_KEY_XF86Sleep, Qt::Key_Sleep,
- XKB_KEY_XF86LightBulb, Qt::Key_LightBulb,
- XKB_KEY_XF86Shop, Qt::Key_Shop,
- XKB_KEY_XF86History, Qt::Key_History,
- XKB_KEY_XF86AddFavorite, Qt::Key_AddFavorite,
- XKB_KEY_XF86HotLinks, Qt::Key_HotLinks,
- XKB_KEY_XF86BrightnessAdjust, Qt::Key_BrightnessAdjust,
- XKB_KEY_XF86Finance, Qt::Key_Finance,
- XKB_KEY_XF86Community, Qt::Key_Community,
- XKB_KEY_XF86AudioRewind, Qt::Key_AudioRewind,
- XKB_KEY_XF86BackForward, Qt::Key_BackForward,
- XKB_KEY_XF86ApplicationLeft, Qt::Key_ApplicationLeft,
- XKB_KEY_XF86ApplicationRight, Qt::Key_ApplicationRight,
- XKB_KEY_XF86Book, Qt::Key_Book,
- XKB_KEY_XF86CD, Qt::Key_CD,
- XKB_KEY_XF86Calculater, Qt::Key_Calculator,
- XKB_KEY_XF86Clear, Qt::Key_Clear,
- XKB_KEY_XF86ClearGrab, Qt::Key_ClearGrab,
- XKB_KEY_XF86Close, Qt::Key_Close,
- XKB_KEY_XF86Copy, Qt::Key_Copy,
- XKB_KEY_XF86Cut, Qt::Key_Cut,
- XKB_KEY_XF86Display, Qt::Key_Display,
- XKB_KEY_XF86DOS, Qt::Key_DOS,
- XKB_KEY_XF86Documents, Qt::Key_Documents,
- XKB_KEY_XF86Excel, Qt::Key_Excel,
- XKB_KEY_XF86Explorer, Qt::Key_Explorer,
- XKB_KEY_XF86Game, Qt::Key_Game,
- XKB_KEY_XF86Go, Qt::Key_Go,
- XKB_KEY_XF86iTouch, Qt::Key_iTouch,
- XKB_KEY_XF86LogOff, Qt::Key_LogOff,
- XKB_KEY_XF86Market, Qt::Key_Market,
- XKB_KEY_XF86Meeting, Qt::Key_Meeting,
- XKB_KEY_XF86MenuKB, Qt::Key_MenuKB,
- XKB_KEY_XF86MenuPB, Qt::Key_MenuPB,
- XKB_KEY_XF86MySites, Qt::Key_MySites,
- XKB_KEY_XF86New, Qt::Key_New,
- XKB_KEY_XF86News, Qt::Key_News,
- XKB_KEY_XF86OfficeHome, Qt::Key_OfficeHome,
- XKB_KEY_XF86Open, Qt::Key_Open,
- XKB_KEY_XF86Option, Qt::Key_Option,
- XKB_KEY_XF86Paste, Qt::Key_Paste,
- XKB_KEY_XF86Phone, Qt::Key_Phone,
- XKB_KEY_XF86Reply, Qt::Key_Reply,
- XKB_KEY_XF86Reload, Qt::Key_Reload,
- XKB_KEY_XF86RotateWindows, Qt::Key_RotateWindows,
- XKB_KEY_XF86RotationPB, Qt::Key_RotationPB,
- XKB_KEY_XF86RotationKB, Qt::Key_RotationKB,
- XKB_KEY_XF86Save, Qt::Key_Save,
- XKB_KEY_XF86Send, Qt::Key_Send,
- XKB_KEY_XF86Spell, Qt::Key_Spell,
- XKB_KEY_XF86SplitScreen, Qt::Key_SplitScreen,
- XKB_KEY_XF86Support, Qt::Key_Support,
- XKB_KEY_XF86TaskPane, Qt::Key_TaskPane,
- XKB_KEY_XF86Terminal, Qt::Key_Terminal,
- XKB_KEY_XF86Tools, Qt::Key_Tools,
- XKB_KEY_XF86Travel, Qt::Key_Travel,
- XKB_KEY_XF86Video, Qt::Key_Video,
- XKB_KEY_XF86Word, Qt::Key_Word,
- XKB_KEY_XF86Xfer, Qt::Key_Xfer,
- XKB_KEY_XF86ZoomIn, Qt::Key_ZoomIn,
- XKB_KEY_XF86ZoomOut, Qt::Key_ZoomOut,
- XKB_KEY_XF86Away, Qt::Key_Away,
- XKB_KEY_XF86Messenger, Qt::Key_Messenger,
- XKB_KEY_XF86WebCam, Qt::Key_WebCam,
- XKB_KEY_XF86MailForward, Qt::Key_MailForward,
- XKB_KEY_XF86Pictures, Qt::Key_Pictures,
- XKB_KEY_XF86Music, Qt::Key_Music,
- XKB_KEY_XF86Battery, Qt::Key_Battery,
- XKB_KEY_XF86Bluetooth, Qt::Key_Bluetooth,
- XKB_KEY_XF86WLAN, Qt::Key_WLAN,
- XKB_KEY_XF86UWB, Qt::Key_UWB,
- XKB_KEY_XF86AudioForward, Qt::Key_AudioForward,
- XKB_KEY_XF86AudioRepeat, Qt::Key_AudioRepeat,
- XKB_KEY_XF86AudioRandomPlay, Qt::Key_AudioRandomPlay,
- XKB_KEY_XF86Subtitle, Qt::Key_Subtitle,
- XKB_KEY_XF86AudioCycleTrack, Qt::Key_AudioCycleTrack,
- XKB_KEY_XF86Time, Qt::Key_Time,
- XKB_KEY_XF86Select, Qt::Key_Select,
- XKB_KEY_XF86View, Qt::Key_View,
- XKB_KEY_XF86TopMenu, Qt::Key_TopMenu,
- XKB_KEY_XF86Red, Qt::Key_Red,
- XKB_KEY_XF86Green, Qt::Key_Green,
- XKB_KEY_XF86Yellow, Qt::Key_Yellow,
- XKB_KEY_XF86Blue, Qt::Key_Blue,
- XKB_KEY_XF86Bluetooth, Qt::Key_Bluetooth,
- XKB_KEY_XF86Suspend, Qt::Key_Suspend,
- XKB_KEY_XF86Hibernate, Qt::Key_Hibernate,
- XKB_KEY_XF86TouchpadToggle, Qt::Key_TouchpadToggle,
- XKB_KEY_XF86TouchpadOn, Qt::Key_TouchpadOn,
- XKB_KEY_XF86TouchpadOff, Qt::Key_TouchpadOff,
- XKB_KEY_XF86AudioMicMute, Qt::Key_MicMute,
- XKB_KEY_XF86Launch0, Qt::Key_Launch2, // ### Qt 6: remap properly
- XKB_KEY_XF86Launch1, Qt::Key_Launch3,
- XKB_KEY_XF86Launch2, Qt::Key_Launch4,
- XKB_KEY_XF86Launch3, Qt::Key_Launch5,
- XKB_KEY_XF86Launch4, Qt::Key_Launch6,
- XKB_KEY_XF86Launch5, Qt::Key_Launch7,
- XKB_KEY_XF86Launch6, Qt::Key_Launch8,
- XKB_KEY_XF86Launch7, Qt::Key_Launch9,
- XKB_KEY_XF86Launch8, Qt::Key_LaunchA,
- XKB_KEY_XF86Launch9, Qt::Key_LaunchB,
- XKB_KEY_XF86LaunchA, Qt::Key_LaunchC,
- XKB_KEY_XF86LaunchB, Qt::Key_LaunchD,
- XKB_KEY_XF86LaunchC, Qt::Key_LaunchE,
- XKB_KEY_XF86LaunchD, Qt::Key_LaunchF,
- XKB_KEY_XF86LaunchE, Qt::Key_LaunchG,
- XKB_KEY_XF86LaunchF, Qt::Key_LaunchH,
-
- 0, 0
+typedef struct xkb2qt
+{
+ unsigned int xkb;
+ unsigned int qt;
+
+ constexpr bool operator <=(const xkb2qt &that) const noexcept
+ {
+ return xkb <= that.xkb;
+ }
+
+ constexpr bool operator <(const xkb2qt &that) const noexcept
+ {
+ return xkb < that.xkb;
+ }
+} xkb2qt_t;
+
+template<std::size_t Xkb, std::size_t Qt>
+struct Xkb2Qt
+{
+ using Type = xkb2qt_t;
+ static constexpr Type data() noexcept { return Type{Xkb, Qt}; }
};
+static constexpr const auto KeyTbl = qMakeArray(
+ QSortedData<
+ // misc keys
+
+ Xkb2Qt<XKB_KEY_Escape, Qt::Key_Escape>,
+ Xkb2Qt<XKB_KEY_Tab, Qt::Key_Tab>,
+ Xkb2Qt<XKB_KEY_ISO_Left_Tab, Qt::Key_Backtab>,
+ Xkb2Qt<XKB_KEY_BackSpace, Qt::Key_Backspace>,
+ Xkb2Qt<XKB_KEY_Return, Qt::Key_Return>,
+ Xkb2Qt<XKB_KEY_Insert, Qt::Key_Insert>,
+ Xkb2Qt<XKB_KEY_Delete, Qt::Key_Delete>,
+ Xkb2Qt<XKB_KEY_Clear, Qt::Key_Delete>,
+ Xkb2Qt<XKB_KEY_Pause, Qt::Key_Pause>,
+ Xkb2Qt<XKB_KEY_Print, Qt::Key_Print>,
+ Xkb2Qt<0x1005FF60, Qt::Key_SysReq>, // hardcoded Sun SysReq
+ Xkb2Qt<0x1007ff00, Qt::Key_SysReq>, // hardcoded X386 SysReq
+
+ // cursor movement
+
+ Xkb2Qt<XKB_KEY_Home, Qt::Key_Home>,
+ Xkb2Qt<XKB_KEY_End, Qt::Key_End>,
+ Xkb2Qt<XKB_KEY_Left, Qt::Key_Left>,
+ Xkb2Qt<XKB_KEY_Up, Qt::Key_Up>,
+ Xkb2Qt<XKB_KEY_Right, Qt::Key_Right>,
+ Xkb2Qt<XKB_KEY_Down, Qt::Key_Down>,
+ Xkb2Qt<XKB_KEY_Prior, Qt::Key_PageUp>,
+ Xkb2Qt<XKB_KEY_Next, Qt::Key_PageDown>,
+
+ // modifiers
+
+ Xkb2Qt<XKB_KEY_Shift_L, Qt::Key_Shift>,
+ Xkb2Qt<XKB_KEY_Shift_R, Qt::Key_Shift>,
+ Xkb2Qt<XKB_KEY_Shift_Lock, Qt::Key_Shift>,
+ Xkb2Qt<XKB_KEY_Control_L, Qt::Key_Control>,
+ Xkb2Qt<XKB_KEY_Control_R, Qt::Key_Control>,
+ Xkb2Qt<XKB_KEY_Meta_L, Qt::Key_Meta>,
+ Xkb2Qt<XKB_KEY_Meta_R, Qt::Key_Meta>,
+ Xkb2Qt<XKB_KEY_Alt_L, Qt::Key_Alt>,
+ Xkb2Qt<XKB_KEY_Alt_R, Qt::Key_Alt>,
+ Xkb2Qt<XKB_KEY_Caps_Lock, Qt::Key_CapsLock>,
+ Xkb2Qt<XKB_KEY_Num_Lock, Qt::Key_NumLock>,
+ Xkb2Qt<XKB_KEY_Scroll_Lock, Qt::Key_ScrollLock>,
+ Xkb2Qt<XKB_KEY_Super_L, Qt::Key_Super_L>,
+ Xkb2Qt<XKB_KEY_Super_R, Qt::Key_Super_R>,
+ Xkb2Qt<XKB_KEY_Menu, Qt::Key_Menu>,
+ Xkb2Qt<XKB_KEY_Hyper_L, Qt::Key_Hyper_L>,
+ Xkb2Qt<XKB_KEY_Hyper_R, Qt::Key_Hyper_R>,
+ Xkb2Qt<XKB_KEY_Help, Qt::Key_Help>,
+ Xkb2Qt<0x1000FF74, Qt::Key_Backtab>, // hardcoded HP backtab
+ Xkb2Qt<0x1005FF10, Qt::Key_F11>, // hardcoded Sun F36 (labeled F11)
+ Xkb2Qt<0x1005FF11, Qt::Key_F12>, // hardcoded Sun F37 (labeled F12)
+
+ // numeric and function keypad keys
+
+ Xkb2Qt<XKB_KEY_KP_Space, Qt::Key_Space>,
+ Xkb2Qt<XKB_KEY_KP_Tab, Qt::Key_Tab>,
+ Xkb2Qt<XKB_KEY_KP_Enter, Qt::Key_Enter>,
+ //Xkb2Qt<XKB_KEY_KP_F1, Qt::Key_F1>,
+ //Xkb2Qt<XKB_KEY_KP_F2, Qt::Key_F2>,
+ //Xkb2Qt<XKB_KEY_KP_F3, Qt::Key_F3>,
+ //Xkb2Qt<XKB_KEY_KP_F4, Qt::Key_F4>,
+ Xkb2Qt<XKB_KEY_KP_Home, Qt::Key_Home>,
+ Xkb2Qt<XKB_KEY_KP_Left, Qt::Key_Left>,
+ Xkb2Qt<XKB_KEY_KP_Up, Qt::Key_Up>,
+ Xkb2Qt<XKB_KEY_KP_Right, Qt::Key_Right>,
+ Xkb2Qt<XKB_KEY_KP_Down, Qt::Key_Down>,
+ Xkb2Qt<XKB_KEY_KP_Prior, Qt::Key_PageUp>,
+ Xkb2Qt<XKB_KEY_KP_Next, Qt::Key_PageDown>,
+ Xkb2Qt<XKB_KEY_KP_End, Qt::Key_End>,
+ Xkb2Qt<XKB_KEY_KP_Begin, Qt::Key_Clear>,
+ Xkb2Qt<XKB_KEY_KP_Insert, Qt::Key_Insert>,
+ Xkb2Qt<XKB_KEY_KP_Delete, Qt::Key_Delete>,
+ Xkb2Qt<XKB_KEY_KP_Equal, Qt::Key_Equal>,
+ Xkb2Qt<XKB_KEY_KP_Multiply, Qt::Key_Asterisk>,
+ Xkb2Qt<XKB_KEY_KP_Add, Qt::Key_Plus>,
+ Xkb2Qt<XKB_KEY_KP_Separator, Qt::Key_Comma>,
+ Xkb2Qt<XKB_KEY_KP_Subtract, Qt::Key_Minus>,
+ Xkb2Qt<XKB_KEY_KP_Decimal, Qt::Key_Period>,
+ Xkb2Qt<XKB_KEY_KP_Divide, Qt::Key_Slash>,
+
+ // special non-XF86 function keys
+
+ Xkb2Qt<XKB_KEY_Undo, Qt::Key_Undo>,
+ Xkb2Qt<XKB_KEY_Redo, Qt::Key_Redo>,
+ Xkb2Qt<XKB_KEY_Find, Qt::Key_Find>,
+ Xkb2Qt<XKB_KEY_Cancel, Qt::Key_Cancel>,
+
+ // International input method support keys
+
+ // International & multi-key character composition
+ Xkb2Qt<XKB_KEY_ISO_Level3_Shift, Qt::Key_AltGr>,
+ Xkb2Qt<XKB_KEY_Multi_key, Qt::Key_Multi_key>,
+ Xkb2Qt<XKB_KEY_Codeinput, Qt::Key_Codeinput>,
+ Xkb2Qt<XKB_KEY_SingleCandidate, Qt::Key_SingleCandidate>,
+ Xkb2Qt<XKB_KEY_MultipleCandidate, Qt::Key_MultipleCandidate>,
+ Xkb2Qt<XKB_KEY_PreviousCandidate, Qt::Key_PreviousCandidate>,
+
+ // Misc Functions
+ Xkb2Qt<XKB_KEY_Mode_switch, Qt::Key_Mode_switch>,
+ Xkb2Qt<XKB_KEY_script_switch, Qt::Key_Mode_switch>,
+
+ // Japanese keyboard support
+ Xkb2Qt<XKB_KEY_Kanji, Qt::Key_Kanji>,
+ Xkb2Qt<XKB_KEY_Muhenkan, Qt::Key_Muhenkan>,
+ //Xkb2Qt<XKB_KEY_Henkan_Mode, Qt::Key_Henkan_Mode>,
+ Xkb2Qt<XKB_KEY_Henkan_Mode, Qt::Key_Henkan>,
+ Xkb2Qt<XKB_KEY_Henkan, Qt::Key_Henkan>,
+ Xkb2Qt<XKB_KEY_Romaji, Qt::Key_Romaji>,
+ Xkb2Qt<XKB_KEY_Hiragana, Qt::Key_Hiragana>,
+ Xkb2Qt<XKB_KEY_Katakana, Qt::Key_Katakana>,
+ Xkb2Qt<XKB_KEY_Hiragana_Katakana, Qt::Key_Hiragana_Katakana>,
+ Xkb2Qt<XKB_KEY_Zenkaku, Qt::Key_Zenkaku>,
+ Xkb2Qt<XKB_KEY_Hankaku, Qt::Key_Hankaku>,
+ Xkb2Qt<XKB_KEY_Zenkaku_Hankaku, Qt::Key_Zenkaku_Hankaku>,
+ Xkb2Qt<XKB_KEY_Touroku, Qt::Key_Touroku>,
+ Xkb2Qt<XKB_KEY_Massyo, Qt::Key_Massyo>,
+ Xkb2Qt<XKB_KEY_Kana_Lock, Qt::Key_Kana_Lock>,
+ Xkb2Qt<XKB_KEY_Kana_Shift, Qt::Key_Kana_Shift>,
+ Xkb2Qt<XKB_KEY_Eisu_Shift, Qt::Key_Eisu_Shift>,
+ Xkb2Qt<XKB_KEY_Eisu_toggle, Qt::Key_Eisu_toggle>,
+ //Xkb2Qt<XKB_KEY_Kanji_Bangou, Qt::Key_Kanji_Bangou>,
+ //Xkb2Qt<XKB_KEY_Zen_Koho, Qt::Key_Zen_Koho>,
+ //Xkb2Qt<XKB_KEY_Mae_Koho, Qt::Key_Mae_Koho>,
+ Xkb2Qt<XKB_KEY_Kanji_Bangou, Qt::Key_Codeinput>,
+ Xkb2Qt<XKB_KEY_Zen_Koho, Qt::Key_MultipleCandidate>,
+ Xkb2Qt<XKB_KEY_Mae_Koho, Qt::Key_PreviousCandidate>,
+
+ // Korean keyboard support
+ Xkb2Qt<XKB_KEY_Hangul, Qt::Key_Hangul>,
+ Xkb2Qt<XKB_KEY_Hangul_Start, Qt::Key_Hangul_Start>,
+ Xkb2Qt<XKB_KEY_Hangul_End, Qt::Key_Hangul_End>,
+ Xkb2Qt<XKB_KEY_Hangul_Hanja, Qt::Key_Hangul_Hanja>,
+ Xkb2Qt<XKB_KEY_Hangul_Jamo, Qt::Key_Hangul_Jamo>,
+ Xkb2Qt<XKB_KEY_Hangul_Romaja, Qt::Key_Hangul_Romaja>,
+ //Xkb2Qt<XKB_KEY_Hangul_Codeinput, Qt::Key_Hangul_Codeinput>,
+ Xkb2Qt<XKB_KEY_Hangul_Codeinput, Qt::Key_Codeinput>,
+ Xkb2Qt<XKB_KEY_Hangul_Jeonja, Qt::Key_Hangul_Jeonja>,
+ Xkb2Qt<XKB_KEY_Hangul_Banja, Qt::Key_Hangul_Banja>,
+ Xkb2Qt<XKB_KEY_Hangul_PreHanja, Qt::Key_Hangul_PreHanja>,
+ Xkb2Qt<XKB_KEY_Hangul_PostHanja, Qt::Key_Hangul_PostHanja>,
+ //Xkb2Qt<XKB_KEY_Hangul_SingleCandidate,Qt::Key_Hangul_SingleCandidate>,
+ //Xkb2Qt<XKB_KEY_Hangul_MultipleCandidate,Qt::Key_Hangul_MultipleCandidate>,
+ //Xkb2Qt<XKB_KEY_Hangul_PreviousCandidate,Qt::Key_Hangul_PreviousCandidate>,
+ Xkb2Qt<XKB_KEY_Hangul_SingleCandidate, Qt::Key_SingleCandidate>,
+ Xkb2Qt<XKB_KEY_Hangul_MultipleCandidate,Qt::Key_MultipleCandidate>,
+ Xkb2Qt<XKB_KEY_Hangul_PreviousCandidate,Qt::Key_PreviousCandidate>,
+ Xkb2Qt<XKB_KEY_Hangul_Special, Qt::Key_Hangul_Special>,
+ //Xkb2Qt<XKB_KEY_Hangul_switch, Qt::Key_Hangul_switch>,
+ Xkb2Qt<XKB_KEY_Hangul_switch, Qt::Key_Mode_switch>,
+
+ // dead keys
+ Xkb2Qt<XKB_KEY_dead_grave, Qt::Key_Dead_Grave>,
+ Xkb2Qt<XKB_KEY_dead_acute, Qt::Key_Dead_Acute>,
+ Xkb2Qt<XKB_KEY_dead_circumflex, Qt::Key_Dead_Circumflex>,
+ Xkb2Qt<XKB_KEY_dead_tilde, Qt::Key_Dead_Tilde>,
+ Xkb2Qt<XKB_KEY_dead_macron, Qt::Key_Dead_Macron>,
+ Xkb2Qt<XKB_KEY_dead_breve, Qt::Key_Dead_Breve>,
+ Xkb2Qt<XKB_KEY_dead_abovedot, Qt::Key_Dead_Abovedot>,
+ Xkb2Qt<XKB_KEY_dead_diaeresis, Qt::Key_Dead_Diaeresis>,
+ Xkb2Qt<XKB_KEY_dead_abovering, Qt::Key_Dead_Abovering>,
+ Xkb2Qt<XKB_KEY_dead_doubleacute, Qt::Key_Dead_Doubleacute>,
+ Xkb2Qt<XKB_KEY_dead_caron, Qt::Key_Dead_Caron>,
+ Xkb2Qt<XKB_KEY_dead_cedilla, Qt::Key_Dead_Cedilla>,
+ Xkb2Qt<XKB_KEY_dead_ogonek, Qt::Key_Dead_Ogonek>,
+ Xkb2Qt<XKB_KEY_dead_iota, Qt::Key_Dead_Iota>,
+ Xkb2Qt<XKB_KEY_dead_voiced_sound, Qt::Key_Dead_Voiced_Sound>,
+ Xkb2Qt<XKB_KEY_dead_semivoiced_sound, Qt::Key_Dead_Semivoiced_Sound>,
+ Xkb2Qt<XKB_KEY_dead_belowdot, Qt::Key_Dead_Belowdot>,
+ Xkb2Qt<XKB_KEY_dead_hook, Qt::Key_Dead_Hook>,
+ Xkb2Qt<XKB_KEY_dead_horn, Qt::Key_Dead_Horn>,
+ Xkb2Qt<XKB_KEY_dead_stroke, Qt::Key_Dead_Stroke>,
+ Xkb2Qt<XKB_KEY_dead_abovecomma, Qt::Key_Dead_Abovecomma>,
+ Xkb2Qt<XKB_KEY_dead_abovereversedcomma, Qt::Key_Dead_Abovereversedcomma>,
+ Xkb2Qt<XKB_KEY_dead_doublegrave, Qt::Key_Dead_Doublegrave>,
+ Xkb2Qt<XKB_KEY_dead_belowring, Qt::Key_Dead_Belowring>,
+ Xkb2Qt<XKB_KEY_dead_belowmacron, Qt::Key_Dead_Belowmacron>,
+ Xkb2Qt<XKB_KEY_dead_belowcircumflex, Qt::Key_Dead_Belowcircumflex>,
+ Xkb2Qt<XKB_KEY_dead_belowtilde, Qt::Key_Dead_Belowtilde>,
+ Xkb2Qt<XKB_KEY_dead_belowbreve, Qt::Key_Dead_Belowbreve>,
+ Xkb2Qt<XKB_KEY_dead_belowdiaeresis, Qt::Key_Dead_Belowdiaeresis>,
+ Xkb2Qt<XKB_KEY_dead_invertedbreve, Qt::Key_Dead_Invertedbreve>,
+ Xkb2Qt<XKB_KEY_dead_belowcomma, Qt::Key_Dead_Belowcomma>,
+ Xkb2Qt<XKB_KEY_dead_currency, Qt::Key_Dead_Currency>,
+ Xkb2Qt<XKB_KEY_dead_a, Qt::Key_Dead_a>,
+ Xkb2Qt<XKB_KEY_dead_A, Qt::Key_Dead_A>,
+ Xkb2Qt<XKB_KEY_dead_e, Qt::Key_Dead_e>,
+ Xkb2Qt<XKB_KEY_dead_E, Qt::Key_Dead_E>,
+ Xkb2Qt<XKB_KEY_dead_i, Qt::Key_Dead_i>,
+ Xkb2Qt<XKB_KEY_dead_I, Qt::Key_Dead_I>,
+ Xkb2Qt<XKB_KEY_dead_o, Qt::Key_Dead_o>,
+ Xkb2Qt<XKB_KEY_dead_O, Qt::Key_Dead_O>,
+ Xkb2Qt<XKB_KEY_dead_u, Qt::Key_Dead_u>,
+ Xkb2Qt<XKB_KEY_dead_U, Qt::Key_Dead_U>,
+ Xkb2Qt<XKB_KEY_dead_small_schwa, Qt::Key_Dead_Small_Schwa>,
+ Xkb2Qt<XKB_KEY_dead_capital_schwa, Qt::Key_Dead_Capital_Schwa>,
+ Xkb2Qt<XKB_KEY_dead_greek, Qt::Key_Dead_Greek>,
+ Xkb2Qt<XKB_KEY_dead_lowline, Qt::Key_Dead_Lowline>,
+ Xkb2Qt<XKB_KEY_dead_aboveverticalline, Qt::Key_Dead_Aboveverticalline>,
+ Xkb2Qt<XKB_KEY_dead_belowverticalline, Qt::Key_Dead_Belowverticalline>,
+ Xkb2Qt<XKB_KEY_dead_longsolidusoverlay, Qt::Key_Dead_Longsolidusoverlay>,
+
+ // Special keys from X.org - This include multimedia keys,
+ // wireless/bluetooth/uwb keys, special launcher keys, etc.
+ Xkb2Qt<XKB_KEY_XF86Back, Qt::Key_Back>,
+ Xkb2Qt<XKB_KEY_XF86Forward, Qt::Key_Forward>,
+ Xkb2Qt<XKB_KEY_XF86Stop, Qt::Key_Stop>,
+ Xkb2Qt<XKB_KEY_XF86Refresh, Qt::Key_Refresh>,
+ Xkb2Qt<XKB_KEY_XF86Favorites, Qt::Key_Favorites>,
+ Xkb2Qt<XKB_KEY_XF86AudioMedia, Qt::Key_LaunchMedia>,
+ Xkb2Qt<XKB_KEY_XF86OpenURL, Qt::Key_OpenUrl>,
+ Xkb2Qt<XKB_KEY_XF86HomePage, Qt::Key_HomePage>,
+ Xkb2Qt<XKB_KEY_XF86Search, Qt::Key_Search>,
+ Xkb2Qt<XKB_KEY_XF86AudioLowerVolume, Qt::Key_VolumeDown>,
+ Xkb2Qt<XKB_KEY_XF86AudioMute, Qt::Key_VolumeMute>,
+ Xkb2Qt<XKB_KEY_XF86AudioRaiseVolume, Qt::Key_VolumeUp>,
+ Xkb2Qt<XKB_KEY_XF86AudioPlay, Qt::Key_MediaPlay>,
+ Xkb2Qt<XKB_KEY_XF86AudioStop, Qt::Key_MediaStop>,
+ Xkb2Qt<XKB_KEY_XF86AudioPrev, Qt::Key_MediaPrevious>,
+ Xkb2Qt<XKB_KEY_XF86AudioNext, Qt::Key_MediaNext>,
+ Xkb2Qt<XKB_KEY_XF86AudioRecord, Qt::Key_MediaRecord>,
+ Xkb2Qt<XKB_KEY_XF86AudioPause, Qt::Key_MediaPause>,
+ Xkb2Qt<XKB_KEY_XF86Mail, Qt::Key_LaunchMail>,
+ Xkb2Qt<XKB_KEY_XF86MyComputer, Qt::Key_Launch0>, // ### Qt 6: remap properly
+ Xkb2Qt<XKB_KEY_XF86Calculator, Qt::Key_Launch1>,
+ Xkb2Qt<XKB_KEY_XF86Memo, Qt::Key_Memo>,
+ Xkb2Qt<XKB_KEY_XF86ToDoList, Qt::Key_ToDoList>,
+ Xkb2Qt<XKB_KEY_XF86Calendar, Qt::Key_Calendar>,
+ Xkb2Qt<XKB_KEY_XF86PowerDown, Qt::Key_PowerDown>,
+ Xkb2Qt<XKB_KEY_XF86ContrastAdjust, Qt::Key_ContrastAdjust>,
+ Xkb2Qt<XKB_KEY_XF86Standby, Qt::Key_Standby>,
+ Xkb2Qt<XKB_KEY_XF86MonBrightnessUp, Qt::Key_MonBrightnessUp>,
+ Xkb2Qt<XKB_KEY_XF86MonBrightnessDown, Qt::Key_MonBrightnessDown>,
+ Xkb2Qt<XKB_KEY_XF86KbdLightOnOff, Qt::Key_KeyboardLightOnOff>,
+ Xkb2Qt<XKB_KEY_XF86KbdBrightnessUp, Qt::Key_KeyboardBrightnessUp>,
+ Xkb2Qt<XKB_KEY_XF86KbdBrightnessDown, Qt::Key_KeyboardBrightnessDown>,
+ Xkb2Qt<XKB_KEY_XF86PowerOff, Qt::Key_PowerOff>,
+ Xkb2Qt<XKB_KEY_XF86WakeUp, Qt::Key_WakeUp>,
+ Xkb2Qt<XKB_KEY_XF86Eject, Qt::Key_Eject>,
+ Xkb2Qt<XKB_KEY_XF86ScreenSaver, Qt::Key_ScreenSaver>,
+ Xkb2Qt<XKB_KEY_XF86WWW, Qt::Key_WWW>,
+ Xkb2Qt<XKB_KEY_XF86Sleep, Qt::Key_Sleep>,
+ Xkb2Qt<XKB_KEY_XF86LightBulb, Qt::Key_LightBulb>,
+ Xkb2Qt<XKB_KEY_XF86Shop, Qt::Key_Shop>,
+ Xkb2Qt<XKB_KEY_XF86History, Qt::Key_History>,
+ Xkb2Qt<XKB_KEY_XF86AddFavorite, Qt::Key_AddFavorite>,
+ Xkb2Qt<XKB_KEY_XF86HotLinks, Qt::Key_HotLinks>,
+ Xkb2Qt<XKB_KEY_XF86BrightnessAdjust, Qt::Key_BrightnessAdjust>,
+ Xkb2Qt<XKB_KEY_XF86Finance, Qt::Key_Finance>,
+ Xkb2Qt<XKB_KEY_XF86Community, Qt::Key_Community>,
+ Xkb2Qt<XKB_KEY_XF86AudioRewind, Qt::Key_AudioRewind>,
+ Xkb2Qt<XKB_KEY_XF86BackForward, Qt::Key_BackForward>,
+ Xkb2Qt<XKB_KEY_XF86ApplicationLeft, Qt::Key_ApplicationLeft>,
+ Xkb2Qt<XKB_KEY_XF86ApplicationRight, Qt::Key_ApplicationRight>,
+ Xkb2Qt<XKB_KEY_XF86Book, Qt::Key_Book>,
+ Xkb2Qt<XKB_KEY_XF86CD, Qt::Key_CD>,
+ Xkb2Qt<XKB_KEY_XF86Calculater, Qt::Key_Calculator>,
+ Xkb2Qt<XKB_KEY_XF86Clear, Qt::Key_Clear>,
+ Xkb2Qt<XKB_KEY_XF86ClearGrab, Qt::Key_ClearGrab>,
+ Xkb2Qt<XKB_KEY_XF86Close, Qt::Key_Close>,
+ Xkb2Qt<XKB_KEY_XF86Copy, Qt::Key_Copy>,
+ Xkb2Qt<XKB_KEY_XF86Cut, Qt::Key_Cut>,
+ Xkb2Qt<XKB_KEY_XF86Display, Qt::Key_Display>,
+ Xkb2Qt<XKB_KEY_XF86DOS, Qt::Key_DOS>,
+ Xkb2Qt<XKB_KEY_XF86Documents, Qt::Key_Documents>,
+ Xkb2Qt<XKB_KEY_XF86Excel, Qt::Key_Excel>,
+ Xkb2Qt<XKB_KEY_XF86Explorer, Qt::Key_Explorer>,
+ Xkb2Qt<XKB_KEY_XF86Game, Qt::Key_Game>,
+ Xkb2Qt<XKB_KEY_XF86Go, Qt::Key_Go>,
+ Xkb2Qt<XKB_KEY_XF86iTouch, Qt::Key_iTouch>,
+ Xkb2Qt<XKB_KEY_XF86LogOff, Qt::Key_LogOff>,
+ Xkb2Qt<XKB_KEY_XF86Market, Qt::Key_Market>,
+ Xkb2Qt<XKB_KEY_XF86Meeting, Qt::Key_Meeting>,
+ Xkb2Qt<XKB_KEY_XF86MenuKB, Qt::Key_MenuKB>,
+ Xkb2Qt<XKB_KEY_XF86MenuPB, Qt::Key_MenuPB>,
+ Xkb2Qt<XKB_KEY_XF86MySites, Qt::Key_MySites>,
+ Xkb2Qt<XKB_KEY_XF86New, Qt::Key_New>,
+ Xkb2Qt<XKB_KEY_XF86News, Qt::Key_News>,
+ Xkb2Qt<XKB_KEY_XF86OfficeHome, Qt::Key_OfficeHome>,
+ Xkb2Qt<XKB_KEY_XF86Open, Qt::Key_Open>,
+ Xkb2Qt<XKB_KEY_XF86Option, Qt::Key_Option>,
+ Xkb2Qt<XKB_KEY_XF86Paste, Qt::Key_Paste>,
+ Xkb2Qt<XKB_KEY_XF86Phone, Qt::Key_Phone>,
+ Xkb2Qt<XKB_KEY_XF86Reply, Qt::Key_Reply>,
+ Xkb2Qt<XKB_KEY_XF86Reload, Qt::Key_Reload>,
+ Xkb2Qt<XKB_KEY_XF86RotateWindows, Qt::Key_RotateWindows>,
+ Xkb2Qt<XKB_KEY_XF86RotationPB, Qt::Key_RotationPB>,
+ Xkb2Qt<XKB_KEY_XF86RotationKB, Qt::Key_RotationKB>,
+ Xkb2Qt<XKB_KEY_XF86Save, Qt::Key_Save>,
+ Xkb2Qt<XKB_KEY_XF86Send, Qt::Key_Send>,
+ Xkb2Qt<XKB_KEY_XF86Spell, Qt::Key_Spell>,
+ Xkb2Qt<XKB_KEY_XF86SplitScreen, Qt::Key_SplitScreen>,
+ Xkb2Qt<XKB_KEY_XF86Support, Qt::Key_Support>,
+ Xkb2Qt<XKB_KEY_XF86TaskPane, Qt::Key_TaskPane>,
+ Xkb2Qt<XKB_KEY_XF86Terminal, Qt::Key_Terminal>,
+ Xkb2Qt<XKB_KEY_XF86Tools, Qt::Key_Tools>,
+ Xkb2Qt<XKB_KEY_XF86Travel, Qt::Key_Travel>,
+ Xkb2Qt<XKB_KEY_XF86Video, Qt::Key_Video>,
+ Xkb2Qt<XKB_KEY_XF86Word, Qt::Key_Word>,
+ Xkb2Qt<XKB_KEY_XF86Xfer, Qt::Key_Xfer>,
+ Xkb2Qt<XKB_KEY_XF86ZoomIn, Qt::Key_ZoomIn>,
+ Xkb2Qt<XKB_KEY_XF86ZoomOut, Qt::Key_ZoomOut>,
+ Xkb2Qt<XKB_KEY_XF86Away, Qt::Key_Away>,
+ Xkb2Qt<XKB_KEY_XF86Messenger, Qt::Key_Messenger>,
+ Xkb2Qt<XKB_KEY_XF86WebCam, Qt::Key_WebCam>,
+ Xkb2Qt<XKB_KEY_XF86MailForward, Qt::Key_MailForward>,
+ Xkb2Qt<XKB_KEY_XF86Pictures, Qt::Key_Pictures>,
+ Xkb2Qt<XKB_KEY_XF86Music, Qt::Key_Music>,
+ Xkb2Qt<XKB_KEY_XF86Battery, Qt::Key_Battery>,
+ Xkb2Qt<XKB_KEY_XF86Bluetooth, Qt::Key_Bluetooth>,
+ Xkb2Qt<XKB_KEY_XF86WLAN, Qt::Key_WLAN>,
+ Xkb2Qt<XKB_KEY_XF86UWB, Qt::Key_UWB>,
+ Xkb2Qt<XKB_KEY_XF86AudioForward, Qt::Key_AudioForward>,
+ Xkb2Qt<XKB_KEY_XF86AudioRepeat, Qt::Key_AudioRepeat>,
+ Xkb2Qt<XKB_KEY_XF86AudioRandomPlay, Qt::Key_AudioRandomPlay>,
+ Xkb2Qt<XKB_KEY_XF86Subtitle, Qt::Key_Subtitle>,
+ Xkb2Qt<XKB_KEY_XF86AudioCycleTrack, Qt::Key_AudioCycleTrack>,
+ Xkb2Qt<XKB_KEY_XF86Time, Qt::Key_Time>,
+ Xkb2Qt<XKB_KEY_XF86Select, Qt::Key_Select>,
+ Xkb2Qt<XKB_KEY_XF86View, Qt::Key_View>,
+ Xkb2Qt<XKB_KEY_XF86TopMenu, Qt::Key_TopMenu>,
+ Xkb2Qt<XKB_KEY_XF86Red, Qt::Key_Red>,
+ Xkb2Qt<XKB_KEY_XF86Green, Qt::Key_Green>,
+ Xkb2Qt<XKB_KEY_XF86Yellow, Qt::Key_Yellow>,
+ Xkb2Qt<XKB_KEY_XF86Blue, Qt::Key_Blue>,
+ Xkb2Qt<XKB_KEY_XF86Bluetooth, Qt::Key_Bluetooth>,
+ Xkb2Qt<XKB_KEY_XF86Suspend, Qt::Key_Suspend>,
+ Xkb2Qt<XKB_KEY_XF86Hibernate, Qt::Key_Hibernate>,
+ Xkb2Qt<XKB_KEY_XF86TouchpadToggle, Qt::Key_TouchpadToggle>,
+ Xkb2Qt<XKB_KEY_XF86TouchpadOn, Qt::Key_TouchpadOn>,
+ Xkb2Qt<XKB_KEY_XF86TouchpadOff, Qt::Key_TouchpadOff>,
+ Xkb2Qt<XKB_KEY_XF86AudioMicMute, Qt::Key_MicMute>,
+ Xkb2Qt<XKB_KEY_XF86Launch0, Qt::Key_Launch2>, // ### Qt 6: remap properly
+ Xkb2Qt<XKB_KEY_XF86Launch1, Qt::Key_Launch3>,
+ Xkb2Qt<XKB_KEY_XF86Launch2, Qt::Key_Launch4>,
+ Xkb2Qt<XKB_KEY_XF86Launch3, Qt::Key_Launch5>,
+ Xkb2Qt<XKB_KEY_XF86Launch4, Qt::Key_Launch6>,
+ Xkb2Qt<XKB_KEY_XF86Launch5, Qt::Key_Launch7>,
+ Xkb2Qt<XKB_KEY_XF86Launch6, Qt::Key_Launch8>,
+ Xkb2Qt<XKB_KEY_XF86Launch7, Qt::Key_Launch9>,
+ Xkb2Qt<XKB_KEY_XF86Launch8, Qt::Key_LaunchA>,
+ Xkb2Qt<XKB_KEY_XF86Launch9, Qt::Key_LaunchB>,
+ Xkb2Qt<XKB_KEY_XF86LaunchA, Qt::Key_LaunchC>,
+ Xkb2Qt<XKB_KEY_XF86LaunchB, Qt::Key_LaunchD>,
+ Xkb2Qt<XKB_KEY_XF86LaunchC, Qt::Key_LaunchE>,
+ Xkb2Qt<XKB_KEY_XF86LaunchD, Qt::Key_LaunchF>,
+ Xkb2Qt<XKB_KEY_XF86LaunchE, Qt::Key_LaunchG>,
+ Xkb2Qt<XKB_KEY_XF86LaunchF, Qt::Key_LaunchH>
+ >::Data{}
+);
+
// Possible modifier states.
static const Qt::KeyboardModifiers ModsTbl[] = {
Qt::NoModifier, // 0
@@ -831,20 +853,20 @@ void QXcbKeyboard::updateXKBStateFromCore(quint16 state)
}
}
-#if QT_CONFIG(xinput2)
+#if QT_CONFIG(xcb_xinput)
void QXcbKeyboard::updateXKBStateFromXI(void *modInfo, void *groupInfo)
{
if (m_config && !connection()->hasXKB()) {
- xXIModifierInfo *mods = static_cast<xXIModifierInfo *>(modInfo);
- xXIGroupInfo *group = static_cast<xXIGroupInfo *>(groupInfo);
+ auto *mods = static_cast<xcb_input_modifier_info_t *>(modInfo);
+ auto *group = static_cast<xcb_input_group_info_t *>(groupInfo);
const xkb_state_component changedComponents
= xkb_state_update_mask(m_xkbState.get(),
- mods->base_mods,
- mods->latched_mods,
- mods->locked_mods,
- group->base_group,
- group->latched_group,
- group->locked_group);
+ mods->base,
+ mods->latched,
+ mods->locked,
+ group->base,
+ group->latched,
+ group->locked);
handleStateChanges(changedComponents);
}
@@ -1105,14 +1127,10 @@ int QXcbKeyboard::keysymToQtKey(xcb_keysym_t keysym, Qt::KeyboardModifiers modif
qtKey = xkbcommon_xkb_keysym_to_upper(keysym);
} else {
// check if we have a direct mapping
- int i = 0;
- while (KeyTbl[i]) {
- if (keysym == KeyTbl[i]) {
- qtKey = KeyTbl[i + 1];
- break;
- }
- i += 2;
- }
+ xkb2qt_t searchKey{keysym, 0};
+ auto it = std::lower_bound(KeyTbl.cbegin(), KeyTbl.cend(), searchKey);
+ if (it != KeyTbl.end() && !(searchKey < *it))
+ qtKey = it->qt;
}
QString text;
@@ -1172,9 +1190,10 @@ QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection)
#if QT_CONFIG(xkb)
core_device_id = 0;
if (connection->hasXKB()) {
+ selectEvents();
core_device_id = xkb_x11_get_core_keyboard_device_id(xcb_connection());
if (core_device_id == -1) {
- qWarning("Qt: couldn't get core keyboard device info");
+ qCWarning(lcQpaXcb, "failed to get core keyboard device info");
return;
}
} else {
@@ -1192,6 +1211,42 @@ QXcbKeyboard::~QXcbKeyboard()
xcb_key_symbols_free(m_key_symbols);
}
+void QXcbKeyboard::selectEvents()
+{
+#if QT_CONFIG(xkb)
+ const uint16_t required_map_parts = (XCB_XKB_MAP_PART_KEY_TYPES |
+ XCB_XKB_MAP_PART_KEY_SYMS |
+ XCB_XKB_MAP_PART_MODIFIER_MAP |
+ XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS |
+ XCB_XKB_MAP_PART_KEY_ACTIONS |
+ XCB_XKB_MAP_PART_KEY_BEHAVIORS |
+ XCB_XKB_MAP_PART_VIRTUAL_MODS |
+ XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP);
+
+ const uint16_t required_events = (XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY |
+ XCB_XKB_EVENT_TYPE_MAP_NOTIFY |
+ XCB_XKB_EVENT_TYPE_STATE_NOTIFY);
+
+ // XKB events are reported to all interested clients without regard
+ // to the current keyboard input focus or grab state
+ xcb_void_cookie_t select = xcb_xkb_select_events_checked(
+ xcb_connection(),
+ XCB_XKB_ID_USE_CORE_KBD,
+ required_events,
+ 0,
+ required_events,
+ required_map_parts,
+ required_map_parts,
+ 0);
+
+ xcb_generic_error_t *error = xcb_request_check(xcb_connection(), select);
+ if (error) {
+ free(error);
+ qCWarning(lcQpaXcb, "failed to select notify events from XKB");
+ }
+#endif
+}
+
void QXcbKeyboard::updateVModMapping()
{
#if QT_CONFIG(xkb)
@@ -1461,64 +1516,6 @@ void QXcbKeyboard::resolveMaskConflicts()
}
}
-class KeyChecker
-{
-public:
- KeyChecker(xcb_window_t window, xcb_keycode_t code, xcb_timestamp_t time, quint16 state)
- : m_window(window)
- , m_code(code)
- , m_time(time)
- , m_state(state)
- , m_error(false)
- , m_release(true)
- {
- }
-
- bool checkEvent(xcb_generic_event_t *ev)
- {
- if (m_error || !ev)
- return false;
-
- int type = ev->response_type & ~0x80;
- if (type != XCB_KEY_PRESS && type != XCB_KEY_RELEASE)
- return false;
-
- xcb_key_press_event_t *event = (xcb_key_press_event_t *)ev;
-
- if (event->event != m_window || event->detail != m_code || event->state != m_state) {
- m_error = true;
- return false;
- }
-
- if (type == XCB_KEY_PRESS) {
- m_error = !m_release || event->time - m_time > 10;
- return !m_error;
- }
-
- if (m_release) {
- m_error = true;
- return false;
- }
-
- m_release = true;
- m_time = event->time;
-
- return false;
- }
-
- bool release() const { return m_release; }
- xcb_timestamp_t time() const { return m_time; }
-
-private:
- xcb_window_t m_window;
- xcb_keycode_t m_code;
- xcb_timestamp_t m_time;
- quint16 m_state;
-
- bool m_error;
- bool m_release;
-};
-
void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type, xcb_keycode_t code,
quint16 state, xcb_timestamp_t time, bool fromSendEvent)
{
@@ -1532,7 +1529,6 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type,
if (type == QEvent::KeyPress)
targetWindow->updateNetWmUserTime(time);
-
ScopedXKBState sendEventState;
if (fromSendEvent) {
// Have a temporary keyboard state filled in from state
@@ -1550,7 +1546,7 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type,
struct xkb_state *xkbState = fromSendEvent ? sendEventState.get() : m_xkbState.get();
xcb_keysym_t sym = xkb_state_key_get_one_sym(xkbState, code);
- QString string = lookupString(xkbState, code);
+ QString text = lookupString(xkbState, code);
Qt::KeyboardModifiers modifiers = translateModifiers(state);
if (sym >= XKB_KEY_KP_Space && sym <= XKB_KEY_KP_9)
@@ -1575,55 +1571,43 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type,
int qtcode = keysymToQtKey(latinKeysym != XKB_KEY_NoSymbol ? latinKeysym : sym,
modifiers, xkbState, code);
- bool isAutoRepeat = false;
if (type == QEvent::KeyPress) {
- if (m_autorepeat_code == code) {
- isAutoRepeat = true;
- m_autorepeat_code = 0;
- }
+ if (m_isAutoRepeat && m_autoRepeatCode != code)
+ // Some other key was pressed while we are auto-repeating on a different key.
+ m_isAutoRepeat = false;
} else {
- // look ahead for auto-repeat
- KeyChecker checker(source->xcb_window(), code, time, state);
- xcb_generic_event_t *event = connection()->checkEvent(checker);
- if (event) {
- isAutoRepeat = true;
- free(event);
- }
- m_autorepeat_code = isAutoRepeat ? code : 0;
+ m_isAutoRepeat = false;
+ // Look at the next event in the queue to see if we are auto-repeating.
+ connection()->eventQueue()->peek(QXcbEventQueue::PeekRetainMatch,
+ [this, time, code](xcb_generic_event_t *event, int type) {
+ if (type == XCB_KEY_PRESS) {
+ auto keyPress = reinterpret_cast<xcb_key_press_event_t *>(event);
+ m_isAutoRepeat = keyPress->time == time && keyPress->detail == code;
+ if (m_isAutoRepeat)
+ m_autoRepeatCode = code;
+ }
+ return true;
+ });
}
bool filtered = false;
- QPlatformInputContext *inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext();
- if (inputContext) {
- QKeyEvent event(type, qtcode, modifiers, code, sym, state, string, isAutoRepeat, string.length());
+ if (auto inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext()) {
+ QKeyEvent event(type, qtcode, modifiers, code, sym, state, text, m_isAutoRepeat, text.size());
event.setTimestamp(time);
filtered = inputContext->filterEvent(&event);
}
- QWindow *window = targetWindow->window();
if (!filtered) {
+ QWindow *window = targetWindow->window();
#ifndef QT_NO_CONTEXTMENU
if (type == QEvent::KeyPress && qtcode == Qt::Key_Menu) {
const QPoint globalPos = window->screen()->handle()->cursor()->pos();
const QPoint pos = window->mapFromGlobal(globalPos);
QWindowSystemInterface::handleContextMenuEvent(window, false, pos, globalPos, modifiers);
}
-#endif // QT_NO_CONTEXTMENU
+#endif
QWindowSystemInterface::handleExtendedKeyEvent(window, time, type, qtcode, modifiers,
- code, sym, state, string, isAutoRepeat);
- }
-
- if (isAutoRepeat && type == QEvent::KeyRelease) {
- // since we removed it from the event queue using checkEvent we need to send the key press here
- filtered = false;
- if (inputContext) {
- QKeyEvent event(QEvent::KeyPress, qtcode, modifiers, code, sym, state, string, isAutoRepeat, string.length());
- event.setTimestamp(time);
- filtered = inputContext->filterEvent(&event);
- }
- if (!filtered)
- QWindowSystemInterface::handleExtendedKeyEvent(window, time, QEvent::KeyPress, qtcode, modifiers,
- code, sym, state, string, isAutoRepeat);
+ code, sym, state, text, m_isAutoRepeat);
}
}
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h
index c131d69267..f8490592b7 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.h
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.h
@@ -43,6 +43,11 @@
#include "qxcbobject.h"
#include <xcb/xcb_keysyms.h>
+#if QT_CONFIG(xkb)
+#define explicit dont_use_cxx_explicit
+#include <xcb/xkb.h>
+#undef explicit
+#endif
#include <xkbcommon/xkbcommon.h>
#if QT_CONFIG(xkb)
@@ -62,6 +67,8 @@ public:
~QXcbKeyboard();
+ void selectEvents();
+
void handleKeyPressEvent(const xcb_key_press_event_t *event);
void handleKeyReleaseEvent(const xcb_key_release_event_t *event);
@@ -74,7 +81,7 @@ public:
void updateXKBMods();
xkb_mod_mask_t xkbModMask(quint16 state);
void updateXKBStateFromCore(quint16 state);
-#if QT_CONFIG(xinput2)
+#if QT_CONFIG(xcb_xinput)
void updateXKBStateFromXI(void *modInfo, void *groupInfo);
#endif
#if QT_CONFIG(xkb)
@@ -109,7 +116,8 @@ protected:
private:
bool m_config = false;
- xcb_keycode_t m_autorepeat_code = 0;
+ bool m_isAutoRepeat = false;
+ xcb_keycode_t m_autoRepeatCode = 0;
struct _mod_masks {
uint alt;
diff --git a/src/plugins/platforms/xcb/qxcbmain.cpp b/src/plugins/platforms/xcb/qxcbmain.cpp
index f8cb9a9269..c1e37f3704 100644
--- a/src/plugins/platforms/xcb/qxcbmain.cpp
+++ b/src/plugins/platforms/xcb/qxcbmain.cpp
@@ -52,10 +52,16 @@ public:
QPlatformIntegration* QXcbIntegrationPlugin::create(const QString& system, const QStringList& parameters, int &argc, char **argv)
{
- if (!system.compare(QLatin1String("xcb"), Qt::CaseInsensitive))
- return new QXcbIntegration(parameters, argc, argv);
+ if (!system.compare(QLatin1String("xcb"), Qt::CaseInsensitive)) {
+ auto xcbIntegration = new QXcbIntegration(parameters, argc, argv);
+ if (!xcbIntegration->hasDefaultConnection()) {
+ delete xcbIntegration;
+ return nullptr;
+ }
+ return xcbIntegration;
+ }
- return 0;
+ return nullptr;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
index db44e58cbb..524af5a2a7 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
@@ -54,7 +54,6 @@
#include <QtGui/qscreen.h>
#include <QtPlatformHeaders/qxcbwindowfunctions.h>
-#include <QtPlatformHeaders/qxcbintegrationfunctions.h>
#include <QtPlatformHeaders/qxcbscreenfunctions.h>
#include <stdio.h>
@@ -93,8 +92,7 @@ static int resourceType(const QByteArray &key)
return int(result - names);
}
-QXcbNativeInterface::QXcbNativeInterface() :
- m_genericEventFilterType(QByteArrayLiteral("xcb_generic_event_t"))
+QXcbNativeInterface::QXcbNativeInterface()
{
}
@@ -106,50 +104,6 @@ static inline QXcbSystemTrayTracker *systemTrayTracker(const QScreen *s)
return static_cast<const QXcbScreen *>(s->handle())->connection()->systemTrayTracker();
}
-bool QXcbNativeInterface::systemTrayAvailable(const QScreen *screen) const
-{
- return systemTrayTracker(screen);
-}
-
-bool QXcbNativeInterface::requestSystemTrayWindowDock(const QWindow *window)
-{
- return QXcbWindow::requestSystemTrayWindowDockStatic(window);
-}
-
-QRect QXcbNativeInterface::systemTrayWindowGlobalGeometry(const QWindow *window)
-{
- return QXcbWindow::systemTrayWindowGlobalGeometryStatic(window);
-}
-
-xcb_window_t QXcbNativeInterface::locateSystemTray(xcb_connection_t *conn, const QXcbScreen *screen)
-{
- if (m_sysTraySelectionAtom == XCB_ATOM_NONE) {
- const QByteArray net_sys_tray = QString::fromLatin1("_NET_SYSTEM_TRAY_S%1").arg(screen->screenNumber()).toLatin1();
- auto intern_r = Q_XCB_REPLY_UNCHECKED(xcb_intern_atom, conn,
- true, net_sys_tray.length(), net_sys_tray);
- if (!intern_r)
- return XCB_WINDOW_NONE;
-
- m_sysTraySelectionAtom = intern_r->atom;
- }
-
- auto sel_owner_r = Q_XCB_REPLY_UNCHECKED(xcb_get_selection_owner, conn, m_sysTraySelectionAtom);
- if (!sel_owner_r)
- return XCB_WINDOW_NONE;
-
- return sel_owner_r->owner;
-}
-
-bool QXcbNativeInterface::systrayVisualHasAlphaChannel()
-{
- return QXcbConnection::xEmbedSystemTrayVisualHasAlphaChannel();
-}
-
-void QXcbNativeInterface::setParentRelativeBackPixmap(QWindow *window)
-{
- QXcbWindow::setParentRelativeBackPixmapStatic(window);
-}
-
void *QXcbNativeInterface::nativeResourceForIntegration(const QByteArray &resourceString)
{
QByteArray lowerCaseResource = resourceString.toLower();
@@ -371,18 +325,6 @@ QFunctionPointer QXcbNativeInterface::platformFunction(const QByteArray &functio
if (function == QXcbWindowFunctions::setWmWindowIconTextIdentifier())
return QFunctionPointer(QXcbWindowFunctions::SetWmWindowIconText(QXcbWindow::setWindowIconTextStatic));
- if (function == QXcbWindowFunctions::setParentRelativeBackPixmapIdentifier())
- return QFunctionPointer(QXcbWindowFunctions::SetParentRelativeBackPixmap(QXcbWindow::setParentRelativeBackPixmapStatic));
-
- if (function == QXcbWindowFunctions::requestSystemTrayWindowDockIdentifier())
- return QFunctionPointer(QXcbWindowFunctions::RequestSystemTrayWindowDock(QXcbWindow::requestSystemTrayWindowDockStatic));
-
- if (function == QXcbWindowFunctions::systemTrayWindowGlobalGeometryIdentifier())
- return QFunctionPointer(QXcbWindowFunctions::SystemTrayWindowGlobalGeometry(QXcbWindow::systemTrayWindowGlobalGeometryStatic));
-
- if (function == QXcbIntegrationFunctions::xEmbedSystemTrayVisualHasAlphaChannelIdentifier())
- return QFunctionPointer(QXcbIntegrationFunctions::XEmbedSystemTrayVisualHasAlphaChannel(QXcbConnection::xEmbedSystemTrayVisualHasAlphaChannel));
-
if (function == QXcbWindowFunctions::visualIdIdentifier()) {
return QFunctionPointer(QXcbWindowFunctions::VisualId(QXcbWindow::visualIdStatic));
}
@@ -466,7 +408,7 @@ void *QXcbNativeInterface::atspiBus()
QXcbIntegration *integration = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration());
QXcbConnection *defaultConnection = integration->defaultConnection();
if (defaultConnection) {
- xcb_atom_t atspiBusAtom = defaultConnection->internAtom("AT_SPI_BUS");
+ auto atspiBusAtom = defaultConnection->atom(QXcbAtom::AT_SPI_BUS);
auto reply = Q_XCB_REPLY(xcb_get_property, defaultConnection->xcb_connection(),
false, defaultConnection->rootWindow(),
atspiBusAtom, XCB_ATOM_STRING, 0, 128);
@@ -495,20 +437,20 @@ void QXcbNativeInterface::setAppUserTime(QScreen* screen, xcb_timestamp_t time)
qint32 QXcbNativeInterface::generatePeekerId()
{
QXcbIntegration *integration = QXcbIntegration::instance();
- return integration->defaultConnection()->generatePeekerId();
+ return integration->defaultConnection()->eventQueue()->generatePeekerId();
}
bool QXcbNativeInterface::removePeekerId(qint32 peekerId)
{
QXcbIntegration *integration = QXcbIntegration::instance();
- return integration->defaultConnection()->removePeekerId(peekerId);
+ return integration->defaultConnection()->eventQueue()->removePeekerId(peekerId);
}
-bool QXcbNativeInterface::peekEventQueue(QXcbConnection::PeekerCallback peeker, void *peekerData,
- QXcbConnection::PeekOptions option, qint32 peekerId)
+bool QXcbNativeInterface::peekEventQueue(QXcbEventQueue::PeekerCallback peeker, void *peekerData,
+ QXcbEventQueue::PeekOptions option, qint32 peekerId)
{
QXcbIntegration *integration = QXcbIntegration::instance();
- return integration->defaultConnection()->peekEventQueue(peeker, peekerData, option, peekerId);
+ return integration->defaultConnection()->eventQueue()->peekEventQueue(peeker, peekerData, option, peekerId);
}
void QXcbNativeInterface::setStartupId(const char *data)
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.h b/src/plugins/platforms/xcb/qxcbnativeinterface.h
index 6a752c68ca..4656f46be5 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.h
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.h
@@ -98,7 +98,7 @@ public:
QFunctionPointer platformFunction(const QByteArray &function) const override;
- inline const QByteArray &genericEventFilterType() const { return m_genericEventFilterType; }
+ inline const QByteArray &nativeEventType() const { return m_nativeEventType; }
void *displayForWindow(QWindow *window);
void *connectionForWindow(QWindow *window);
@@ -118,15 +118,10 @@ public:
static qint32 generatePeekerId();
static bool removePeekerId(qint32 peekerId);
- static bool peekEventQueue(QXcbConnection::PeekerCallback peeker, void *peekerData = nullptr,
- QXcbConnection::PeekOptions option = QXcbConnection::PeekDefault,
+ static bool peekEventQueue(QXcbEventQueue::PeekerCallback peeker, void *peekerData = nullptr,
+ QXcbEventQueue::PeekOptions option = QXcbEventQueue::PeekDefault,
qint32 peekerId = -1);
- Q_INVOKABLE bool systemTrayAvailable(const QScreen *screen) const;
- Q_INVOKABLE void setParentRelativeBackPixmap(QWindow *window);
- Q_INVOKABLE bool systrayVisualHasAlphaChannel();
- Q_INVOKABLE bool requestSystemTrayWindowDock(const QWindow *window);
- Q_INVOKABLE QRect systemTrayWindowGlobalGeometry(const QWindow *window);
Q_INVOKABLE QString dumpConnectionNativeWindows(const QXcbConnection *connection, WId root) const;
Q_INVOKABLE QString dumpNativeWindows(WId root = 0) const;
@@ -136,9 +131,7 @@ signals:
void systemTrayWindowChanged(QScreen *screen);
private:
- xcb_window_t locateSystemTray(xcb_connection_t *conn, const QXcbScreen *screen);
-
- const QByteArray m_genericEventFilterType;
+ const QByteArray m_nativeEventType = QByteArrayLiteral("xcb_generic_event_t");
xcb_atom_t m_sysTraySelectionAtom = XCB_ATOM_NONE;
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index a696e2a311..57dbdc9bec 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -95,12 +95,6 @@ QXcbVirtualDesktop::QXcbVirtualDesktop(QXcbConnection *connection, xcb_screen_t
m_windowManagerName = QXcbWindow::windowTitle(connection, windowManager);
}
- const xcb_query_extension_reply_t *sync_reply = xcb_get_extension_data(xcb_connection(), &xcb_sync_id);
- if (!sync_reply || !sync_reply->present)
- m_syncRequestSupported = false;
- else
- m_syncRequestSupported = true;
-
xcb_depth_iterator_t depth_iterator =
xcb_screen_allowed_depths_iterator(screen);
@@ -746,7 +740,11 @@ void QXcbScreen::updateGeometry(const QRect &geometry, uint8_t rotation)
m_sizeMillimeters = sizeInMillimeters(geometry.size(), m_virtualDesktop->dpi());
qreal dpi = geometry.width() / physicalSize().width() * qreal(25.4);
- m_pixelDensity = qMax(1, qRound(dpi/96));
+
+ // Use 128 as a reference DPI on small screens. This favors "small UI" over "large UI".
+ qreal referenceDpi = physicalSize().width() <= 320 ? 128 : 96;
+
+ m_pixelDensity = qMax(1, qRound(dpi/referenceDpi));
m_geometry = geometry;
m_availableGeometry = geometry & m_virtualDesktop->workArea();
QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), m_geometry, m_availableGeometry);
@@ -905,16 +903,12 @@ QByteArray QXcbScreen::getEdid() const
return result;
// Try a bunch of atoms
- xcb_atom_t atom = connection()->internAtom("EDID");
- result = getOutputProperty(atom);
- if (result.isEmpty()) {
- atom = connection()->internAtom("EDID_DATA");
- result = getOutputProperty(atom);
- }
- if (result.isEmpty()) {
- atom = connection()->internAtom("XFree86_DDC_EDID1_RAWDATA");
- result = getOutputProperty(atom);
- }
+ result = getOutputProperty(atom(QXcbAtom::EDID));
+ if (result.isEmpty())
+ result = getOutputProperty(atom(QXcbAtom::EDID_DATA));
+ if (result.isEmpty())
+ result = getOutputProperty(atom(QXcbAtom::XFree86_DDC_EDID1_RAWDATA));
+
return result;
}
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index 792aca4b06..7f22a8e4db 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -102,7 +102,6 @@ public:
int antialiasingEnabled() const { return m_antialiasingEnabled; }
QString windowManagerName() const { return m_windowManagerName; }
- bool syncRequestSupported() const { return m_syncRequestSupported; }
QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &format) const;
@@ -133,10 +132,9 @@ private:
QFontEngine::SubpixelAntialiasingType m_subpixelType = QFontEngine::SubpixelAntialiasingType(-1);
int m_antialiasingEnabled = -1;
QString m_windowManagerName;
- bool m_syncRequestSupported = false;
QMap<xcb_visualid_t, xcb_visualtype_t> m_visuals;
QMap<xcb_visualid_t, quint8> m_visualDepths;
- uint16_t m_rotation = XCB_RANDR_ROTATION_ROTATE_0;
+ uint16_t m_rotation = 0;
};
class Q_XCB_EXPORT QXcbScreen : public QXcbObject, public QPlatformScreen
@@ -188,7 +186,6 @@ public:
void windowShown(QXcbWindow *window);
QString windowManagerName() const { return m_virtualDesktop->windowManagerName(); }
- bool syncRequestSupported() const { return m_virtualDesktop->syncRequestSupported(); }
QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &format) const;
@@ -220,7 +217,6 @@ private:
xcb_randr_crtc_t m_crtc;
xcb_randr_mode_t m_mode = XCB_NONE;
bool m_primary = false;
- uint8_t m_rotation = 0;
QString m_outputName;
QSizeF m_outputSizeMillimeters;
diff --git a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp
index c98879c7df..684e603fab 100644
--- a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp
+++ b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp
@@ -91,8 +91,7 @@ xcb_window_t QXcbSystemTrayTracker::locateTrayWindow(const QXcbConnection *conne
return reply->owner;
}
-// API for QPlatformNativeInterface/QPlatformSystemTrayIcon: Request a window
-// to be docked on the tray.
+// Request a window to be docked on the tray.
void QXcbSystemTrayTracker::requestSystemTrayWindowDock(xcb_window_t window) const
{
xcb_client_message_event_t trayRequest;
@@ -122,23 +121,6 @@ xcb_window_t QXcbSystemTrayTracker::trayWindow()
return m_trayWindow;
}
-// API for QPlatformNativeInterface/QPlatformSystemTrayIcon: Return the geometry of a
-// a window parented on the tray. Determines the global geometry via XCB since mapToGlobal
-// does not work for the QWindow parented on the tray.
-QRect QXcbSystemTrayTracker::systemTrayWindowGlobalGeometry(xcb_window_t window) const
-{
- xcb_connection_t *conn = m_connection->xcb_connection();
- auto geomReply = Q_XCB_REPLY(xcb_get_geometry, conn, window);
- if (!geomReply)
- return QRect();
-
- auto translateReply = Q_XCB_REPLY(xcb_translate_coordinates, conn, window, m_connection->rootWindow(), 0, 0);
- if (!translateReply)
- return QRect();
-
- return QRect(QPoint(translateReply->dst_x, translateReply->dst_y), QSize(geomReply->width, geomReply->height));
-}
-
inline void QXcbSystemTrayTracker::emitSystemTrayWindowChanged()
{
if (const QPlatformScreen *ps = m_connection->primaryScreen())
@@ -162,10 +144,18 @@ void QXcbSystemTrayTracker::handleDestroyNotifyEvent(const xcb_destroy_notify_ev
}
}
-bool QXcbSystemTrayTracker::visualHasAlphaChannel()
+xcb_visualid_t QXcbSystemTrayTracker::visualId()
+{
+ xcb_visualid_t visual = netSystemTrayVisual();
+ if (visual == XCB_NONE)
+ visual = m_connection->primaryScreen()->screen()->root_visual;
+ return visual;
+}
+
+xcb_visualid_t QXcbSystemTrayTracker::netSystemTrayVisual()
{
if (m_trayWindow == XCB_WINDOW_NONE)
- return false;
+ return XCB_NONE;
xcb_atom_t tray_atom = m_connection->atom(QXcbAtom::_NET_SYSTEM_TRAY_VISUAL);
@@ -174,7 +164,7 @@ bool QXcbSystemTrayTracker::visualHasAlphaChannel()
false, m_trayWindow,
tray_atom, XCB_ATOM_VISUALID, 0, 1);
if (!systray_atom_reply)
- return false;
+ return XCB_NONE;
xcb_visualid_t systrayVisualId = XCB_NONE;
if (systray_atom_reply->value_len > 0 && xcb_get_property_value_length(systray_atom_reply.get()) > 0) {
@@ -182,12 +172,7 @@ bool QXcbSystemTrayTracker::visualHasAlphaChannel()
systrayVisualId = vids[0];
}
- if (systrayVisualId != XCB_NONE) {
- quint8 depth = m_connection->primaryScreen()->depthOfVisual(systrayVisualId);
- return depth == 32;
- }
-
- return false;
+ return systrayVisualId;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbsystemtraytracker.h b/src/plugins/platforms/xcb/qxcbsystemtraytracker.h
index a95b9374e9..d2fc24c957 100644
--- a/src/plugins/platforms/xcb/qxcbsystemtraytracker.h
+++ b/src/plugins/platforms/xcb/qxcbsystemtraytracker.h
@@ -57,13 +57,12 @@ public:
xcb_window_t trayWindow();
void requestSystemTrayWindowDock(xcb_window_t window) const;
- QRect systemTrayWindowGlobalGeometry(xcb_window_t window) const;
void notifyManagerClientMessageEvent(const xcb_client_message_event_t *);
void handleDestroyNotifyEvent(const xcb_destroy_notify_event_t *) override;
- bool visualHasAlphaChannel();
+ xcb_visualid_t visualId();
signals:
void systemTrayWindowChanged(QScreen *screen);
@@ -73,6 +72,7 @@ private:
xcb_atom_t selection);
static xcb_window_t locateTrayWindow(const QXcbConnection *connection, xcb_atom_t selection);
void emitSystemTrayWindowChanged();
+ xcb_visualid_t netSystemTrayVisual();
const xcb_atom_t m_selection;
const xcb_atom_t m_trayAtom;
diff --git a/src/plugins/platforms/xcb/qxcbvulkaninstance.cpp b/src/plugins/platforms/xcb/qxcbvulkaninstance.cpp
index 4d540defa9..b3f8a5832d 100644
--- a/src/plugins/platforms/xcb/qxcbvulkaninstance.cpp
+++ b/src/plugins/platforms/xcb/qxcbvulkaninstance.cpp
@@ -46,20 +46,9 @@ QT_BEGIN_NAMESPACE
QXcbVulkanInstance::QXcbVulkanInstance(QVulkanInstance *instance)
: m_instance(instance),
m_getPhysDevPresSupport(nullptr),
- m_createSurface(nullptr),
- m_destroySurface(nullptr)
+ m_createSurface(nullptr)
{
- if (qEnvironmentVariableIsSet("QT_VULKAN_LIB"))
- m_lib.setFileName(QString::fromUtf8(qgetenv("QT_VULKAN_LIB")));
- else
- m_lib.setFileName(QStringLiteral("vulkan"));
-
- if (!m_lib.load()) {
- qWarning("Failed to load %s: %s", qPrintable(m_lib.fileName()), qPrintable(m_lib.errorString()));
- return;
- }
-
- init(&m_lib);
+ loadVulkanLibrary(QStringLiteral("vulkan"));
}
QXcbVulkanInstance::~QXcbVulkanInstance()
@@ -114,14 +103,6 @@ VkSurfaceKHR QXcbVulkanInstance::createSurface(QXcbWindow *window)
qWarning("Failed to find vkCreateXcbSurfaceKHR");
return surface;
}
- if (!m_destroySurface) {
- m_destroySurface = reinterpret_cast<PFN_vkDestroySurfaceKHR>(
- m_vkGetInstanceProcAddr(m_vkInst, "vkDestroySurfaceKHR"));
- }
- if (!m_destroySurface) {
- qWarning("Failed to find vkDestroySurfaceKHR");
- return surface;
- }
VkXcbSurfaceCreateInfoKHR surfaceInfo;
memset(&surfaceInfo, 0, sizeof(surfaceInfo));
@@ -135,12 +116,6 @@ VkSurfaceKHR QXcbVulkanInstance::createSurface(QXcbWindow *window)
return surface;
}
-void QXcbVulkanInstance::destroySurface(VkSurfaceKHR surface)
-{
- if (m_destroySurface && surface)
- m_destroySurface(m_vkInst, surface, nullptr);
-}
-
void QXcbVulkanInstance::presentQueued(QWindow *window)
{
QXcbWindow *w = static_cast<QXcbWindow *>(window->handle());
diff --git a/src/plugins/platforms/xcb/qxcbvulkaninstance.h b/src/plugins/platforms/xcb/qxcbvulkaninstance.h
index dbe057d944..53f7345254 100644
--- a/src/plugins/platforms/xcb/qxcbvulkaninstance.h
+++ b/src/plugins/platforms/xcb/qxcbvulkaninstance.h
@@ -64,14 +64,11 @@ public:
void presentQueued(QWindow *window) override;
VkSurfaceKHR createSurface(QXcbWindow *window);
- void destroySurface(VkSurfaceKHR surface);
private:
QVulkanInstance *m_instance;
- QLibrary m_lib;
PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR m_getPhysDevPresSupport;
PFN_vkCreateXcbSurfaceKHR m_createSurface;
- PFN_vkDestroySurfaceKHR m_destroySurface;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 59b06d543e..70aab77a51 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -70,6 +70,9 @@
#undef class
#include <xcb/xfixes.h>
#include <xcb/shape.h>
+#if QT_CONFIG(xcb_xinput)
+#include <xcb/xinput.h>
+#endif
// xcb-icccm 3.8 support
#ifdef XCB_ICCCM_NUM_WM_SIZE_HINTS_ELEMENTS
@@ -109,19 +112,12 @@
#undef register
#endif
-#if QT_CONFIG(xinput2)
-#include <X11/extensions/XInput2.h>
-#include <X11/extensions/XI2proto.h>
-#endif
-
#define XCOORD_MAX 16383
enum {
defaultWindowWidth = 160,
defaultWindowHeight = 160
};
-//#ifdef NET_WM_STATE_DEBUG
-
QT_BEGIN_NAMESPACE
Q_DECLARE_TYPEINFO(xcb_rectangle_t, Q_PRIMITIVE_TYPE);
@@ -200,11 +196,6 @@ void QXcbWindow::setImageFormatForVisual(const xcb_visualtype_t *visual)
}
}
-static inline bool positionIncludesFrame(QWindow *w)
-{
- return qt_window_private(w)->positionPolicy == QWindowPrivate::WindowFrameInclusive;
-}
-
#if QT_CONFIG(xcb_xlib)
static inline XTextProperty* qstringToXTP(Display *dpy, const QString& s)
{
@@ -282,11 +273,7 @@ QXcbWindow::QXcbWindow(QWindow *window)
setConnection(xcbScreen()->connection());
}
-#ifdef Q_COMPILER_CLASS_ENUM
enum : quint32 {
-#else
-enum {
-#endif
baseEventMask
= XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY
| XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_FOCUS_CHANGE,
@@ -308,6 +295,7 @@ void QXcbWindow::create()
destroy();
m_windowState = Qt::WindowNoState;
+ m_trayIconWindow = isTrayIconWindow(window());
Qt::WindowType type = window()->type();
@@ -334,9 +322,6 @@ void QXcbWindow::create()
return;
}
- // Parameters to XCreateWindow() are frame corner + inner size.
- // This fits in case position policy is frame inclusive. There is
- // currently no way to implement it for frame-exclusive geometries.
QPlatformWindow::setGeometry(rect);
if (platformScreen != currentScreen)
@@ -368,7 +353,9 @@ void QXcbWindow::create()
const xcb_visualtype_t *visual = nullptr;
- if (connection()->hasDefaultVisualId()) {
+ if (m_trayIconWindow && connection()->systemTrayTracker()) {
+ visual = platformScreen->visualForId(connection()->systemTrayTracker()->visualId());
+ } else if (connection()->hasDefaultVisualId()) {
visual = platformScreen->visualForId(connection()->defaultVisualId());
if (!visual)
qWarning() << "Failed to use requested visual id.";
@@ -408,9 +395,12 @@ void QXcbWindow::create()
| XCB_CW_SAVE_UNDER
| XCB_CW_EVENT_MASK;
- static const bool haveOpenGL = QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL);
+ static auto haveOpenGL = []() {
+ static const bool result = QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL);
+ return result;
+ };
- if ((window()->supportsOpenGL() && haveOpenGL) || m_format.hasAlpha()) {
+ if ((window()->supportsOpenGL() && haveOpenGL()) || m_format.hasAlpha()) {
m_cmap = xcb_generate_id(xcb_connection());
xcb_create_colormap(xcb_connection(),
XCB_COLORMAP_ALLOC_NONE,
@@ -448,8 +438,6 @@ void QXcbWindow::create()
connection()->addWindowEventListener(m_window, this);
- xcb_change_window_attributes(xcb_connection(), m_window, mask, values);
-
propagateSizeHints();
xcb_atom_t properties[5];
@@ -458,9 +446,7 @@ void QXcbWindow::create()
properties[propertyCount++] = atom(QXcbAtom::WM_TAKE_FOCUS);
properties[propertyCount++] = atom(QXcbAtom::_NET_WM_PING);
- m_usingSyncProtocol = platformScreen->syncRequestSupported();
-
- if (m_usingSyncProtocol)
+ if (connection()->hasXSync())
properties[propertyCount++] = atom(QXcbAtom::_NET_WM_SYNC_REQUEST);
if (window()->flags() & Qt::WindowContextHelpButtonHint)
@@ -484,7 +470,7 @@ void QXcbWindow::create()
XCB_ATOM_STRING, 8, wmClass.size(), wmClass.constData());
}
- if (m_usingSyncProtocol) {
+ if (connection()->hasXSync()) {
m_syncCounter = xcb_generate_id(xcb_connection());
xcb_sync_create_counter(xcb_connection(), m_syncCounter, m_syncValue);
@@ -504,12 +490,17 @@ void QXcbWindow::create()
atom(QXcbAtom::_NET_WM_PID), XCB_ATOM_CARDINAL, 32,
1, &pid);
+ const QByteArray clientMachine = QSysInfo::machineHostName().toLocal8Bit();
+ if (!clientMachine.isEmpty()) {
+ xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
+ atom(QXcbAtom::WM_CLIENT_MACHINE), XCB_ATOM_STRING, 8,
+ clientMachine.size(), clientMachine.constData());
+ }
+
+ // Create WM_HINTS property on the window, so we can xcb_get_wm_hints*()
+ // from various setter functions for adjusting the hints.
xcb_wm_hints_t hints;
memset(&hints, 0, sizeof(hints));
- xcb_wm_hints_set_normal(&hints);
-
- xcb_wm_hints_set_input(&hints, !(window()->flags() & Qt::WindowDoesNotAcceptFocus));
-
xcb_set_wm_hints(xcb_connection(), m_window, &hints);
xcb_window_t leader = connection()->clientLeader();
@@ -524,7 +515,7 @@ void QXcbWindow::create()
atom(QXcbAtom::_XEMBED_INFO),
32, 2, (void *)data);
-#if QT_CONFIG(xinput2)
+#if QT_CONFIG(xcb_xinput)
if (connection()->hasXInput2()) {
if (connection()->xi2MouseEventsDisabled())
connection()->xi2SelectDeviceEventsCompatibility(m_window);
@@ -537,9 +528,6 @@ void QXcbWindow::create()
setWindowFlags(window()->flags());
setWindowTitle(window()->title());
- if (window()->flags() & Qt::WindowTransparentForInput)
- setTransparentForMouseEvents(true);
-
#if QT_CONFIG(xcb_xlib)
// force sync to read outstanding requests - see QTBUG-29106
XSync(static_cast<Display*>(platformScreen->connection()->xlib_display()), false);
@@ -562,6 +550,9 @@ void QXcbWindow::create()
QByteArray wmWindowRole = window()->property(wm_window_role_property_id).toByteArray();
setWmWindowRole(wmWindowRole);
}
+
+ if (m_trayIconWindow)
+ m_embedded = requestSystemTrayWindowDock();
}
QXcbWindow::~QXcbWindow()
@@ -587,7 +578,7 @@ void QXcbWindow::destroy()
if (connection()->mouseGrabber() == this)
connection()->setMouseGrabber(nullptr);
- if (m_syncCounter && m_usingSyncProtocol)
+ if (m_syncCounter && connection()->hasXSync())
xcb_sync_destroy_counter(xcb_connection(), m_syncCounter);
if (m_window) {
if (m_netWmUserTimeWindow) {
@@ -623,25 +614,23 @@ void QXcbWindow::setGeometry(const QRect &rect)
if (!newScreen)
newScreen = xcbScreen();
- const QRect wmGeometry = windowToWmGeometry(rect);
-
if (newScreen != currentScreen)
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen());
if (qt_window_private(window())->positionAutomatic) {
const quint32 mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
const qint32 values[] = {
- qBound<qint32>(1, wmGeometry.width(), XCOORD_MAX),
- qBound<qint32>(1, wmGeometry.height(), XCOORD_MAX),
+ qBound<qint32>(1, rect.width(), XCOORD_MAX),
+ qBound<qint32>(1, rect.height(), XCOORD_MAX),
};
xcb_configure_window(xcb_connection(), m_window, mask, reinterpret_cast<const quint32*>(values));
} else {
const quint32 mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
const qint32 values[] = {
- qBound<qint32>(-XCOORD_MAX, wmGeometry.x(), XCOORD_MAX),
- qBound<qint32>(-XCOORD_MAX, wmGeometry.y(), XCOORD_MAX),
- qBound<qint32>(1, wmGeometry.width(), XCOORD_MAX),
- qBound<qint32>(1, wmGeometry.height(), XCOORD_MAX),
+ qBound<qint32>(-XCOORD_MAX, rect.x(), XCOORD_MAX),
+ qBound<qint32>(-XCOORD_MAX, rect.y(), XCOORD_MAX),
+ qBound<qint32>(1, rect.width(), XCOORD_MAX),
+ qBound<qint32>(1, rect.height(), XCOORD_MAX),
};
xcb_configure_window(xcb_connection(), m_window, mask, reinterpret_cast<const quint32*>(values));
if (window()->parent() && !window()->transientParent()) {
@@ -739,34 +728,10 @@ void QXcbWindow::setVisible(bool visible)
hide();
}
-static inline bool testShowWithoutActivating(const QWindow *window)
-{
- // QWidget-attribute Qt::WA_ShowWithoutActivating.
- const QVariant showWithoutActivating = window->property("_q_showWithoutActivating");
- return showWithoutActivating.isValid() && showWithoutActivating.toBool();
-}
-
void QXcbWindow::show()
{
if (window()->isTopLevel()) {
- xcb_get_property_cookie_t cookie = xcb_get_wm_hints_unchecked(xcb_connection(), m_window);
-
- xcb_wm_hints_t hints;
- xcb_get_wm_hints_reply(xcb_connection(), cookie, &hints, NULL);
-
- if (window()->windowStates() & Qt::WindowMinimized)
- xcb_wm_hints_set_iconic(&hints);
- else
- xcb_wm_hints_set_normal(&hints);
-
- xcb_wm_hints_set_input(&hints, !(window()->flags() & Qt::WindowDoesNotAcceptFocus));
-
- xcb_set_wm_hints(xcb_connection(), m_window, &hints);
-
- m_gravity = positionIncludesFrame(window()) ?
- XCB_GRAVITY_NORTH_WEST : XCB_GRAVITY_STATIC;
-
// update WM_NORMAL_HINTS
propagateSizeHints();
@@ -789,19 +754,18 @@ void QXcbWindow::show()
if (!transientXcbParent)
xcb_delete_property(xcb_connection(), m_window, XCB_ATOM_WM_TRANSIENT_FOR);
- // update _MOTIF_WM_HINTS
- updateMotifWmHintsBeforeMap();
-
// update _NET_WM_STATE
updateNetWmStateBeforeMap();
}
- if (testShowWithoutActivating(window()))
+ // QWidget-attribute Qt::WA_ShowWithoutActivating.
+ const auto showWithoutActivating = window()->property("_q_showWithoutActivating");
+ if (showWithoutActivating.isValid() && showWithoutActivating.toBool())
updateNetWmUserTime(0);
else if (connection()->time() != XCB_TIME_CURRENT_TIME)
updateNetWmUserTime(connection()->time());
- if (window()->objectName() == QLatin1String("QSystemTrayIconSysWindow"))
+ if (m_trayIconWindow)
return; // defer showing until XEMBED_EMBEDDED_NOTIFY
xcb_map_window(xcb_connection(), m_window);
@@ -819,7 +783,7 @@ void QXcbWindow::hide()
xcb_unmap_window(xcb_connection(), m_window);
// send synthetic UnmapNotify event according to icccm 4.1.4
- Q_DECLARE_XCB_EVENT(event, xcb_unmap_notify_event_t);
+ q_padded_xcb_event<xcb_unmap_notify_event_t> event = {};
event.response_type = XCB_UNMAP_NOTIFY;
event.event = xcbScreen()->root();
event.window = m_window;
@@ -940,8 +904,8 @@ void QXcbWindow::doFocusOut()
struct QtMotifWmHints {
quint32 flags, functions, decorations;
- qint32 input_mode;
- quint32 status;
+ qint32 input_mode; // unused
+ quint32 status; // unused
};
enum {
@@ -963,50 +927,8 @@ enum {
MWM_DECOR_MENU = (1L << 4),
MWM_DECOR_MINIMIZE = (1L << 5),
MWM_DECOR_MAXIMIZE = (1L << 6),
-
- MWM_HINTS_INPUT_MODE = (1L << 2),
-
- MWM_INPUT_MODELESS = 0L,
- MWM_INPUT_PRIMARY_APPLICATION_MODAL = 1L,
- MWM_INPUT_FULL_APPLICATION_MODAL = 3L
};
-static QtMotifWmHints getMotifWmHints(QXcbConnection *c, xcb_window_t window)
-{
- QtMotifWmHints hints;
-
- auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, c->xcb_connection(), 0, window,
- c->atom(QXcbAtom::_MOTIF_WM_HINTS), c->atom(QXcbAtom::_MOTIF_WM_HINTS), 0, 20);
-
- if (reply && reply->format == 32 && reply->type == c->atom(QXcbAtom::_MOTIF_WM_HINTS)) {
- hints = *((QtMotifWmHints *)xcb_get_property_value(reply.get()));
- } else {
- hints.flags = 0L;
- hints.functions = MWM_FUNC_ALL;
- hints.decorations = MWM_DECOR_ALL;
- hints.input_mode = 0L;
- hints.status = 0L;
- }
-
- return hints;
-}
-
-static void setMotifWmHints(QXcbConnection *c, xcb_window_t window, const QtMotifWmHints &hints)
-{
- if (hints.flags != 0l) {
- xcb_change_property(c->xcb_connection(),
- XCB_PROP_MODE_REPLACE,
- window,
- c->atom(QXcbAtom::_MOTIF_WM_HINTS),
- c->atom(QXcbAtom::_MOTIF_WM_HINTS),
- 32,
- 5,
- &hints);
- } else {
- xcb_delete_property(c->xcb_connection(), window, c->atom(QXcbAtom::_MOTIF_WM_HINTS));
- }
-}
-
QXcbWindow::NetWmStates QXcbWindow::netWmStates()
{
NetWmStates result(0);
@@ -1035,9 +957,7 @@ QXcbWindow::NetWmStates QXcbWindow::netWmStates()
if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION)))
result |= NetWmStateDemandsAttention;
} else {
-#ifdef NET_WM_STATE_DEBUG
- printf("getting net wm state (%x), empty\n", m_window);
-#endif
+ qCDebug(lcQpaXcb, "getting net wm state (%x), empty\n", m_window);
}
return result;
@@ -1110,22 +1030,18 @@ void QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
setWmWindowType(wmWindowTypes, flags);
setNetWmStateWindowFlags(flags);
- setMotifWindowFlags(flags);
+ setMotifWmHints(flags);
setTransparentForMouseEvents(flags & Qt::WindowTransparentForInput);
updateDoesNotAcceptFocus(flags & Qt::WindowDoesNotAcceptFocus);
}
-void QXcbWindow::setMotifWindowFlags(Qt::WindowFlags flags)
+void QXcbWindow::setMotifWmHints(Qt::WindowFlags flags)
{
Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
QtMotifWmHints mwmhints;
- mwmhints.flags = 0L;
- mwmhints.functions = 0L;
- mwmhints.decorations = 0;
- mwmhints.input_mode = 0L;
- mwmhints.status = 0L;
+ memset(&mwmhints, 0, sizeof(mwmhints));
if (type != Qt::SplashScreen) {
mwmhints.flags |= MWM_HINTS_DECORATIONS;
@@ -1183,7 +1099,18 @@ void QXcbWindow::setMotifWindowFlags(Qt::WindowFlags flags)
mwmhints.decorations = 0;
}
- setMotifWmHints(connection(), m_window, mwmhints);
+ if (mwmhints.flags) {
+ xcb_change_property(xcb_connection(),
+ XCB_PROP_MODE_REPLACE,
+ m_window,
+ atom(QXcbAtom::_MOTIF_WM_HINTS),
+ atom(QXcbAtom::_MOTIF_WM_HINTS),
+ 32,
+ 5,
+ &mwmhints);
+ } else {
+ xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_MOTIF_WM_HINTS));
+ }
}
void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two)
@@ -1242,64 +1169,18 @@ void QXcbWindow::setWindowState(Qt::WindowStates state)
changeNetWmState(state & Qt::WindowFullScreen, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
}
- connection()->sync();
- m_windowState = state;
-}
-
-void QXcbWindow::updateMotifWmHintsBeforeMap()
-{
- QtMotifWmHints mwmhints = getMotifWmHints(connection(), m_window);
-
- if (window()->modality() != Qt::NonModal) {
- switch (window()->modality()) {
- case Qt::WindowModal:
- mwmhints.input_mode = MWM_INPUT_PRIMARY_APPLICATION_MODAL;
- break;
- case Qt::ApplicationModal:
- default:
- mwmhints.input_mode = MWM_INPUT_FULL_APPLICATION_MODAL;
- break;
- }
- mwmhints.flags |= MWM_HINTS_INPUT_MODE;
- } else {
- mwmhints.input_mode = MWM_INPUT_MODELESS;
- mwmhints.flags &= ~MWM_HINTS_INPUT_MODE;
- }
-
- if (windowMinimumSize() == windowMaximumSize()) {
- // fixed size, remove the resize handle (since mwm/dtwm
- // isn't smart enough to do it itself)
- mwmhints.flags |= MWM_HINTS_FUNCTIONS;
- if (mwmhints.functions == MWM_FUNC_ALL) {
- mwmhints.functions = MWM_FUNC_MOVE;
- } else {
- mwmhints.functions &= ~MWM_FUNC_RESIZE;
- }
-
- if (mwmhints.decorations == MWM_DECOR_ALL) {
- mwmhints.flags |= MWM_HINTS_DECORATIONS;
- mwmhints.decorations = (MWM_DECOR_BORDER
- | MWM_DECOR_TITLE
- | MWM_DECOR_MENU);
- } else {
- mwmhints.decorations &= ~MWM_DECOR_RESIZEH;
- }
- }
-
- if (window()->flags() & Qt::WindowMinimizeButtonHint) {
- mwmhints.flags |= MWM_HINTS_DECORATIONS;
- mwmhints.decorations |= MWM_DECOR_MINIMIZE;
- mwmhints.functions |= MWM_FUNC_MINIMIZE;
- }
- if (window()->flags() & Qt::WindowMaximizeButtonHint) {
- mwmhints.flags |= MWM_HINTS_DECORATIONS;
- mwmhints.decorations |= MWM_DECOR_MAXIMIZE;
- mwmhints.functions |= MWM_FUNC_MAXIMIZE;
+ xcb_get_property_cookie_t cookie = xcb_get_wm_hints_unchecked(xcb_connection(), m_window);
+ xcb_wm_hints_t hints;
+ if (xcb_get_wm_hints_reply(xcb_connection(), cookie, &hints, nullptr)) {
+ if (state & Qt::WindowMinimized)
+ xcb_wm_hints_set_iconic(&hints);
+ else
+ xcb_wm_hints_set_normal(&hints);
+ xcb_set_wm_hints(xcb_connection(), m_window, &hints);
}
- if (window()->flags() & Qt::WindowCloseButtonHint)
- mwmhints.functions |= MWM_FUNC_CLOSE;
- setMotifWmHints(connection(), m_window, mwmhints);
+ connection()->sync();
+ m_windowState = state;
}
void QXcbWindow::updateNetWmStateBeforeMap()
@@ -1364,17 +1245,10 @@ void QXcbWindow::updateNetWmUserTime(xcb_timestamp_t timestamp)
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, atom(QXcbAtom::_NET_WM_USER_TIME_WINDOW),
XCB_ATOM_WINDOW, 32, 1, &m_netWmUserTimeWindow);
xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_USER_TIME));
-#ifndef QT_NO_DEBUG
- QByteArray ba("Qt NET_WM user time window");
- xcb_change_property(xcb_connection(),
- XCB_PROP_MODE_REPLACE,
- m_netWmUserTimeWindow,
- atom(QXcbAtom::_NET_WM_NAME),
- atom(QXcbAtom::UTF8_STRING),
- 8,
- ba.length(),
- ba.constData());
-#endif
+
+ QXcbWindow::setWindowTitle(connection(), m_netWmUserTimeWindow,
+ QStringLiteral("Qt NET_WM User Time Window"));
+
} else if (!isSupportedByWM) {
// WM no longer supports it, then we should remove the
// _NET_WM_USER_TIME_WINDOW atom.
@@ -1421,9 +1295,8 @@ void QXcbWindow::updateDoesNotAcceptFocus(bool doesNotAcceptFocus)
xcb_get_property_cookie_t cookie = xcb_get_wm_hints_unchecked(xcb_connection(), m_window);
xcb_wm_hints_t hints;
- if (!xcb_get_wm_hints_reply(xcb_connection(), cookie, &hints, NULL)) {
+ if (!xcb_get_wm_hints_reply(xcb_connection(), cookie, &hints, nullptr))
return;
- }
xcb_wm_hints_set_input(&hints, !doesNotAcceptFocus);
xcb_set_wm_hints(xcb_connection(), m_window, &hints);
@@ -1452,24 +1325,7 @@ void QXcbWindow::setParent(const QPlatformWindow *parent)
void QXcbWindow::setWindowTitle(const QString &title)
{
- QString fullTitle = formatWindowTitle(title, QString::fromUtf8(" \xe2\x80\x94 ")); // unicode character U+2014, EM DASH
- const QByteArray ba = std::move(fullTitle).toUtf8();
- xcb_change_property(xcb_connection(),
- XCB_PROP_MODE_REPLACE,
- m_window,
- atom(QXcbAtom::_NET_WM_NAME),
- atom(QXcbAtom::UTF8_STRING),
- 8,
- ba.length(),
- ba.constData());
-
-#if QT_CONFIG(xcb_xlib)
- Display *dpy = static_cast<Display *>(connection()->xlib_display());
- XTextProperty *text = qstringToXTP(dpy, title);
- if (text)
- XSetWMName(dpy, m_window, text);
-#endif
- xcb_flush(xcb_connection());
+ setWindowTitle(connection(), m_window, title);
}
void QXcbWindow::setWindowIconText(const QString &title)
@@ -1541,38 +1397,28 @@ void QXcbWindow::lower()
xcb_configure_window(xcb_connection(), m_window, mask, values);
}
-// Adapt the geometry to match the WM expection with regards
-// to gravity.
-QRect QXcbWindow::windowToWmGeometry(QRect r) const
-{
- if (m_dirtyFrameMargins || m_frameMargins.isNull())
- return r;
- const bool frameInclusive = positionIncludesFrame(window());
- // XCB_GRAVITY_STATIC requires the inner geometry, whereas
- // XCB_GRAVITY_NORTH_WEST requires the frame geometry
- if (frameInclusive && m_gravity == XCB_GRAVITY_STATIC) {
- r.translate(m_frameMargins.left(), m_frameMargins.top());
- } else if (!frameInclusive && m_gravity == XCB_GRAVITY_NORTH_WEST) {
- r.translate(-m_frameMargins.left(), -m_frameMargins.top());
- }
- return r;
-}
-
void QXcbWindow::propagateSizeHints()
{
// update WM_NORMAL_HINTS
xcb_size_hints_t hints;
memset(&hints, 0, sizeof(hints));
- const QRect xRect = windowToWmGeometry(geometry());
+ const QRect rect = geometry();
+ QWindowPrivate *win = qt_window_private(window());
- QWindow *win = window();
+ if (!win->positionAutomatic)
+ xcb_size_hints_set_position(&hints, true, rect.x(), rect.y());
+ if (rect.width() < QWINDOWSIZE_MAX || rect.height() < QWINDOWSIZE_MAX)
+ xcb_size_hints_set_size(&hints, true, rect.width(), rect.height());
- if (!qt_window_private(win)->positionAutomatic)
- xcb_size_hints_set_position(&hints, true, xRect.x(), xRect.y());
- if (xRect.width() < QWINDOWSIZE_MAX || xRect.height() < QWINDOWSIZE_MAX)
- xcb_size_hints_set_size(&hints, true, xRect.width(), xRect.height());
- xcb_size_hints_set_win_gravity(&hints, m_gravity);
+ /* Gravity describes how to interpret x and y values the next time
+ window needs to be positioned on a screen.
+ XCB_GRAVITY_STATIC : the left top corner of the client window
+ XCB_GRAVITY_NORTH_WEST : the left top corner of the frame window */
+ auto gravity = win->positionPolicy == QWindowPrivate::WindowFrameInclusive
+ ? XCB_GRAVITY_NORTH_WEST : XCB_GRAVITY_STATIC;
+
+ xcb_size_hints_set_win_gravity(&hints, gravity);
QSize minimumSize = windowMinimumSize();
QSize maximumSize = windowMaximumSize();
@@ -1836,12 +1682,6 @@ void QXcbWindow::setWmWindowRole(const QByteArray &role)
role.size(), role.constData());
}
-void QXcbWindow::setParentRelativeBackPixmapStatic(QWindow *window)
-{
- if (window->handle())
- static_cast<QXcbWindow *>(window->handle())->setParentRelativeBackPixmap();
-}
-
void QXcbWindow::setParentRelativeBackPixmap()
{
const quint32 mask = XCB_CW_BACK_PIXMAP;
@@ -1849,14 +1689,7 @@ void QXcbWindow::setParentRelativeBackPixmap()
xcb_change_window_attributes(xcb_connection(), m_window, mask, values);
}
-bool QXcbWindow::requestSystemTrayWindowDockStatic(const QWindow *window)
-{
- if (window->handle())
- return static_cast<QXcbWindow *>(window->handle())->requestSystemTrayWindowDock();
- return false;
-}
-
-bool QXcbWindow::requestSystemTrayWindowDock() const
+bool QXcbWindow::requestSystemTrayWindowDock()
{
if (!connection()->systemTrayTracker())
return false;
@@ -1864,81 +1697,33 @@ bool QXcbWindow::requestSystemTrayWindowDock() const
return true;
}
-QRect QXcbWindow::systemTrayWindowGlobalGeometryStatic(const QWindow *window)
+bool QXcbWindow::handleNativeEvent(xcb_generic_event_t *event)
{
- if (window->handle())
- return static_cast<QXcbWindow *>(window->handle())->systemTrayWindowGlobalGeometry();
- return QRect();
+ auto eventType = connection()->nativeInterface()->nativeEventType();
+ long result = 0; // Used only by MS Windows
+ return QWindowSystemInterface::handleNativeEvent(window(), eventType, event, &result);
}
-QRect QXcbWindow::systemTrayWindowGlobalGeometry() const
+void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event)
{
- if (!connection()->systemTrayTracker())
- return QRect();
- return connection()->systemTrayTracker()->systemTrayWindowGlobalGeometry(m_window);
-}
+ QRect rect(event->x, event->y, event->width, event->height);
+ m_exposeRegion |= rect;
-class ExposeCompressor
-{
-public:
- ExposeCompressor(xcb_window_t window, QRegion *region)
- : m_window(window)
- , m_region(region)
- , m_pending(true)
- {
- }
+ bool pending = true;
- bool checkEvent(xcb_generic_event_t *event)
- {
- if (!event)
- return false;
- if ((event->response_type & ~0x80) != XCB_EXPOSE)
+ connection()->eventQueue()->peek(QXcbEventQueue::PeekRemoveMatchContinue,
+ [this, &pending](xcb_generic_event_t *event, int type) {
+ if (type != XCB_EXPOSE)
return false;
- xcb_expose_event_t *expose = (xcb_expose_event_t *)event;
+ auto expose = reinterpret_cast<xcb_expose_event_t *>(event);
if (expose->window != m_window)
return false;
if (expose->count == 0)
- m_pending = false;
- *m_region |= QRect(expose->x, expose->y, expose->width, expose->height);
+ pending = false;
+ m_exposeRegion |= QRect(expose->x, expose->y, expose->width, expose->height);
+ free(expose);
return true;
- }
-
- bool pending() const
- {
- return m_pending;
- }
-
-private:
- xcb_window_t m_window;
- QRegion *m_region;
- bool m_pending;
-};
-
-bool QXcbWindow::compressExposeEvent(QRegion &exposeRegion)
-{
- ExposeCompressor compressor(m_window, &exposeRegion);
- xcb_generic_event_t *filter = 0;
- do {
- filter = connection()->checkEvent(compressor);
- free(filter);
- } while (filter);
- return compressor.pending();
-}
-
-bool QXcbWindow::handleGenericEvent(xcb_generic_event_t *event, long *result)
-{
- return QWindowSystemInterface::handleNativeEvent(window(),
- connection()->nativeInterface()->genericEventFilterType(),
- event,
- result);
-}
-
-void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event)
-{
- QRect rect(event->x, event->y, event->width, event->height);
-
- m_exposeRegion |= rect;
- bool pending = compressExposeEvent(m_exposeRegion);
+ });
// if count is non-zero there are more expose events pending
if (event->count == 0 || !pending) {
@@ -1977,7 +1762,7 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even
connection()->setTime(event->data.data32[1]);
m_syncValue.lo = event->data.data32[2];
m_syncValue.hi = event->data.data32[3];
- if (m_usingSyncProtocol)
+ if (connection()->hasXSync())
m_syncState = SyncReceived;
#ifndef QT_NO_WHATSTHIS
} else if (protocolAtom == atom(QXcbAtom::_NET_WM_CONTEXT_HELP)) {
@@ -2052,7 +1837,7 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
}
m_oldWindowSize = actualGeometry.size();
- if (m_usingSyncProtocol && m_syncState == SyncReceived)
+ if (connection()->hasXSync() && m_syncState == SyncReceived)
m_syncState = SyncAndConfigureReceived;
m_dirtyFrameMargins = true;
@@ -2137,7 +1922,7 @@ void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, in
updateNetWmUserTime(timestamp);
- if (m_embedded) {
+ if (m_embedded && !m_trayIconWindow) {
if (window() != QGuiApplication::focusWindow()) {
const QXcbWindow *container = static_cast<const QXcbWindow *>(parent());
Q_ASSERT(container != 0);
@@ -2149,7 +1934,7 @@ void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, in
QPoint global(root_x, root_y);
if (isWheel) {
-#if QT_CONFIG(xinput2)
+#if QT_CONFIG(xcb_xinput)
if (!connection()->isAtLeastXI21()) {
#endif
QPoint angleDelta;
@@ -2164,7 +1949,7 @@ void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, in
if (modifiers & Qt::AltModifier)
std::swap(angleDelta.rx(), angleDelta.ry());
QWindowSystemInterface::handleWheelEvent(window(), timestamp, local, global, QPoint(), angleDelta, modifiers);
-#if QT_CONFIG(xinput2)
+#if QT_CONFIG(xcb_xinput)
}
#endif
return;
@@ -2204,7 +1989,7 @@ static inline bool doCheckUnGrabAncestor(QXcbConnection *conn)
if (conn) {
const bool mouseButtonsPressed = (conn->buttonState() != Qt::NoButton);
-#if QT_CONFIG(xinput2)
+#if QT_CONFIG(xcb_xinput)
return mouseButtonsPressed || (conn->hasXInput2() && !conn->xi2MouseEventsDisabled());
#else
return mouseButtonsPressed;
@@ -2231,24 +2016,6 @@ static bool ignoreEnterEvent(quint8 mode, quint8 detail, QXcbConnection *conn =
|| detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL);
}
-class EnterEventChecker
-{
-public:
- bool checkEvent(xcb_generic_event_t *event)
- {
- if (!event)
- return false;
- if ((event->response_type & ~0x80) != XCB_ENTER_NOTIFY)
- return false;
-
- xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t *)event;
- if (ignoreEnterEvent(enter->mode, enter->detail))
- return false;
-
- return true;
- }
-};
-
void QXcbWindow::handleEnterNotifyEvent(int event_x, int event_y, int root_x, int root_y,
quint8 mode, quint8 detail, xcb_timestamp_t timestamp)
{
@@ -2258,7 +2025,7 @@ void QXcbWindow::handleEnterNotifyEvent(int event_x, int event_y, int root_x, in
if (ignoreEnterEvent(mode, detail, connection()) || connection()->mousePressWindow())
return;
-#ifdef XCB_USE_XINPUT21
+#if QT_CONFIG(xcb_xinput)
// Updates scroll valuators, as user might have done some scrolling outside our X client.
connection()->xi2UpdateScrollingDevices();
#endif
@@ -2275,9 +2042,15 @@ void QXcbWindow::handleLeaveNotifyEvent(int root_x, int root_y,
if (ignoreLeaveEvent(mode, detail, connection()) || connection()->mousePressWindow())
return;
- EnterEventChecker checker;
- xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t *)connection()->checkEvent(checker);
- QXcbWindow *enterWindow = enter ? connection()->platformWindowFromId(enter->event) : 0;
+ // check if enter event is buffered
+ auto event = connection()->eventQueue()->peek([](xcb_generic_event_t *event, int type) {
+ if (type != XCB_ENTER_NOTIFY)
+ return false;
+ auto enter = reinterpret_cast<xcb_enter_notify_event_t *>(event);
+ return !ignoreEnterEvent(enter->mode, enter->detail);
+ });
+ auto enter = reinterpret_cast<xcb_enter_notify_event_t *>(event);
+ QXcbWindow *enterWindow = enter ? connection()->platformWindowFromId(enter->event) : nullptr;
if (enterWindow) {
QPoint local(enter->event_x, enter->event_y);
@@ -2330,16 +2103,18 @@ void QXcbWindow::handleMotionNotifyEvent(const xcb_motion_notify_event_t *event)
event->time, QEvent::MouseMove);
}
-#if QT_CONFIG(xinput2)
-static inline int fixed1616ToInt(FP1616 val)
+#if QT_CONFIG(xcb_xinput)
+static inline int fixed1616ToInt(xcb_input_fp1616_t val)
{
return int(qreal(val) / 0x10000);
}
+#define qt_xcb_mask_is_set(ptr, event) (((unsigned char*)(ptr))[(event)>>3] & (1 << ((event) & 7)))
+
void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event, Qt::MouseEventSource source)
{
QXcbConnection *conn = connection();
- xXIDeviceEvent *ev = reinterpret_cast<xXIDeviceEvent *>(event);
+ auto *ev = reinterpret_cast<xcb_input_button_press_event_t *>(event);
if (ev->buttons_len > 0) {
unsigned char *buttonMask = (unsigned char *) &ev[1];
@@ -2347,16 +2122,16 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event, Qt::MouseEventSource
// XIPointerEmulated being set: https://bugs.freedesktop.org/show_bug.cgi?id=98188
// Filter them out by other attributes: when their source device is a touch screen
// and the LMB is pressed.
- if (XIMaskIsSet(buttonMask, 1) && conn->isTouchScreen(ev->sourceid)) {
+ if (qt_xcb_mask_is_set(buttonMask, 1) && conn->isTouchScreen(ev->sourceid)) {
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
qCDebug(lcQpaXInput, "XI2 mouse event from touch device %d was ignored", ev->sourceid);
return;
}
for (int i = 1; i <= 15; ++i)
- conn->setButtonState(conn->translateMouseButton(i), XIMaskIsSet(buttonMask, i));
+ conn->setButtonState(conn->translateMouseButton(i), qt_xcb_mask_is_set(buttonMask, i));
}
- const Qt::KeyboardModifiers modifiers = conn->keyboard()->translateModifiers(ev->mods.effective_mods);
+ const Qt::KeyboardModifiers modifiers = conn->keyboard()->translateModifiers(ev->mods.effective);
const int event_x = fixed1616ToInt(ev->event_x);
const int event_y = fixed1616ToInt(ev->event_y);
const int root_x = fixed1616ToInt(ev->root_x);
@@ -2373,47 +2148,47 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event, Qt::MouseEventSource
sourceName = me.valueToKey(source);
}
- switch (ev->evtype) {
- case XI_ButtonPress:
+ switch (ev->event_type) {
+ case XCB_INPUT_BUTTON_PRESS:
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
qCDebug(lcQpaXInputEvents, "XI2 mouse press, button %d, time %d, source %s", button, ev->time, sourceName);
conn->setButtonState(button, true);
handleButtonPressEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time, QEvent::MouseButtonPress, source);
break;
- case XI_ButtonRelease:
+ case XCB_INPUT_BUTTON_RELEASE:
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
qCDebug(lcQpaXInputEvents, "XI2 mouse release, button %d, time %d, source %s", button, ev->time, sourceName);
conn->setButtonState(button, false);
handleButtonReleaseEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time, QEvent::MouseButtonRelease, source);
break;
- case XI_Motion:
+ case XCB_INPUT_MOTION:
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
qCDebug(lcQpaXInputEvents, "XI2 mouse motion %d,%d, time %d, source %s", event_x, event_y, ev->time, sourceName);
handleMotionNotifyEvent(event_x, event_y, root_x, root_y, modifiers, ev->time, QEvent::MouseMove, source);
break;
default:
- qWarning() << "Unrecognized XI2 mouse event" << ev->evtype;
+ qWarning() << "Unrecognized XI2 mouse event" << ev->event_type;
break;
}
}
void QXcbWindow::handleXIEnterLeave(xcb_ge_event_t *event)
{
- xXIEnterEvent *ev = reinterpret_cast<xXIEnterEvent *>(event);
+ auto *ev = reinterpret_cast<xcb_input_enter_event_t *>(event);
// Compare the window with current mouse grabber to prevent deliver events to any other windows.
// If leave event occurs and the window is under mouse - allow to deliver the leave event.
QXcbWindow *mouseGrabber = connection()->mouseGrabber();
if (mouseGrabber && mouseGrabber != this
- && (ev->evtype != XI_Leave || QGuiApplicationPrivate::currentMouseWindow != window())) {
+ && (ev->event_type != XCB_INPUT_LEAVE || QGuiApplicationPrivate::currentMouseWindow != window())) {
return;
}
const int root_x = fixed1616ToInt(ev->root_x);
const int root_y = fixed1616ToInt(ev->root_y);
- switch (ev->evtype) {
- case XI_Enter: {
+ switch (ev->event_type) {
+ case XCB_INPUT_ENTER: {
const int event_x = fixed1616ToInt(ev->event_x);
const int event_y = fixed1616ToInt(ev->event_y);
qCDebug(lcQpaXInputEvents, "XI2 mouse enter %d,%d, mode %d, detail %d, time %d",
@@ -2421,7 +2196,7 @@ void QXcbWindow::handleXIEnterLeave(xcb_ge_event_t *event)
handleEnterNotifyEvent(event_x, event_y, root_x, root_y, ev->mode, ev->detail, ev->time);
break;
}
- case XI_Leave:
+ case XCB_INPUT_LEAVE:
qCDebug(lcQpaXInputEvents, "XI2 mouse leave, mode %d, detail %d, time %d",
ev->mode, ev->detail, ev->time);
connection()->keyboard()->updateXKBStateFromXI(&ev->mods, &ev->group);
@@ -2523,7 +2298,7 @@ void QXcbWindow::updateSyncRequestCounter()
// window manager does not expect a sync event yet.
return;
}
- if (m_usingSyncProtocol && (m_syncValue.lo != 0 || m_syncValue.hi != 0)) {
+ if (connection()->hasXSync() && (m_syncValue.lo != 0 || m_syncValue.hi != 0)) {
xcb_sync_set_counter(xcb_connection(), m_syncCounter, m_syncValue);
xcb_flush(xcb_connection());
@@ -2563,7 +2338,7 @@ bool QXcbWindow::setMouseGrabEnabled(bool grab)
if (grab && !connection()->canGrab())
return false;
-#if QT_CONFIG(xinput2)
+#if QT_CONFIG(xcb_xinput)
if (connection()->hasXInput2() && !connection()->xi2MouseEventsDisabled()) {
bool result = connection()->xi2SetMouseGrabEnabled(m_window, grab);
if (grab && result)
@@ -2591,11 +2366,11 @@ bool QXcbWindow::setMouseGrabEnabled(bool grab)
return result;
}
-void QXcbWindow::windowEvent(QEvent *event)
+bool QXcbWindow::windowEvent(QEvent *event)
{
switch (event->type()) {
case QEvent::FocusIn:
- if (m_embedded && !event->spontaneous()) {
+ if (m_embedded && !m_trayIconWindow && !event->spontaneous()) {
QFocusEvent *focusEvent = static_cast<QFocusEvent *>(event);
switch (focusEvent->reason()) {
case Qt::TabFocusReason:
@@ -2617,7 +2392,7 @@ void QXcbWindow::windowEvent(QEvent *event)
default:
break;
}
- QPlatformWindow::windowEvent(event);
+ return QPlatformWindow::windowEvent(event);
}
bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner)
@@ -2638,7 +2413,7 @@ bool QXcbWindow::startSystemMoveResize(const QPoint &pos, int corner)
return false;
const QPoint globalPos = QHighDpi::toNativePixels(window()->mapToGlobal(pos), window()->screen());
-#ifdef XCB_USE_XINPUT22
+#if QT_CONFIG(xcb_xinput)
// ### FIXME QTBUG-53389
bool startedByTouch = connection()->startSystemMoveResizeForTouchBegin(m_window, globalPos, corner);
if (startedByTouch) {
@@ -2659,6 +2434,7 @@ bool QXcbWindow::startSystemMoveResize(const QPoint &pos, int corner)
return true;
}
+
void QXcbWindow::doStartSystemMoveResize(const QPoint &globalPos, int corner)
{
const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE);
@@ -2728,11 +2504,6 @@ void QXcbWindow::handleXEmbedMessage(const xcb_client_message_event_t *event)
case XEMBED_EMBEDDED_NOTIFY:
xcb_map_window(xcb_connection(), m_window);
xcbScreen()->windowShown(this);
- // Without Qt::WA_TranslucentBackground, we use a ParentRelative BackPixmap.
- // Clear the whole tray icon window to its background color as early as possible
- // so that we can get a clean result from grabWindow() later.
- xcb_clear_area(xcb_connection(), false, m_window, 0, 0, geometry().width(), geometry().height());
- xcb_flush(xcb_connection());
break;
case XEMBED_FOCUS_IN:
Qt::FocusReason reason;
@@ -2846,6 +2617,28 @@ QXcbScreen *QXcbWindow::xcbScreen() const
return static_cast<QXcbScreen *>(screen());
}
+void QXcbWindow::setWindowTitle(const QXcbConnection *conn, xcb_window_t window, const QString &title)
+{
+ QString fullTitle = formatWindowTitle(title, QString::fromUtf8(" \xe2\x80\x94 ")); // unicode character U+2014, EM DASH
+ const QByteArray ba = std::move(fullTitle).toUtf8();
+ xcb_change_property(conn->xcb_connection(),
+ XCB_PROP_MODE_REPLACE,
+ window,
+ conn->atom(QXcbAtom::_NET_WM_NAME),
+ conn->atom(QXcbAtom::UTF8_STRING),
+ 8,
+ ba.length(),
+ ba.constData());
+
+#if QT_CONFIG(xcb_xlib)
+ Display *dpy = static_cast<Display *>(conn->xlib_display());
+ XTextProperty *text = qstringToXTP(dpy, title);
+ if (text)
+ XSetWMName(dpy, window, text);
+#endif
+ xcb_flush(conn->xcb_connection());
+}
+
QString QXcbWindow::windowTitle(const QXcbConnection *conn, xcb_window_t window)
{
const xcb_atom_t utf8Atom = conn->atom(QXcbAtom::UTF8_STRING);
@@ -2856,6 +2649,15 @@ QString QXcbWindow::windowTitle(const QXcbConnection *conn, xcb_window_t window)
const char *name = reinterpret_cast<const char *>(xcb_get_property_value(reply.get()));
return QString::fromUtf8(name, xcb_get_property_value_length(reply.get()));
}
+
+ reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, conn->xcb_connection(),
+ false, window, conn->atom(QXcbAtom::WM_NAME),
+ XCB_ATOM_STRING, 0, 1024);
+ if (reply && reply->format == 8 && reply->type == XCB_ATOM_STRING) {
+ const char *name = reinterpret_cast<const char *>(xcb_get_property_value(reply.get()));
+ return QString::fromLatin1(name, xcb_get_property_value_length(reply.get()));
+ }
+
return QString();
}
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index c4f49c593c..6667f45343 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -105,7 +105,7 @@ public:
QSurfaceFormat format() const override;
- void windowEvent(QEvent *event) override;
+ bool windowEvent(QEvent *event) override;
bool startSystemResize(const QPoint &pos, Qt::Corner corner) override;
bool startSystemMove(const QPoint &pos) override;
@@ -121,7 +121,7 @@ public:
QImage::Format imageFormat() const { return m_imageFormat; }
bool imageNeedsRgbSwap() const { return m_imageRgbSwap; }
- bool handleGenericEvent(xcb_generic_event_t *event, long *result) override;
+ bool handleNativeEvent(xcb_generic_event_t *event) override;
void handleExposeEvent(const xcb_expose_event_t *event) override;
void handleClientMessageEvent(const xcb_client_message_event_t *event) override;
@@ -137,7 +137,7 @@ public:
void handleFocusInEvent(const xcb_focus_in_event_t *event) override;
void handleFocusOutEvent(const xcb_focus_out_event_t *event) override;
void handlePropertyNotifyEvent(const xcb_property_notify_event_t *event) override;
-#if QT_CONFIG(xinput2)
+#if QT_CONFIG(xcb_xinput)
void handleXIMouseEvent(xcb_ge_event_t *, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized) override;
void handleXIEnterLeave(xcb_ge_event_t *) override;
#endif
@@ -159,14 +159,8 @@ public:
static void setWindowIconTextStatic(QWindow *window, const QString &text);
- static void setParentRelativeBackPixmapStatic(QWindow *window);
void setParentRelativeBackPixmap();
-
- static bool requestSystemTrayWindowDockStatic(const QWindow *window);
- bool requestSystemTrayWindowDock() const;
-
- static QRect systemTrayWindowGlobalGeometryStatic(const QWindow *window);
- QRect systemTrayWindowGlobalGeometry() const;
+ bool requestSystemTrayWindowDock();
uint visualId() const;
bool needsSync() const;
@@ -179,9 +173,15 @@ public:
bool startSystemMoveResize(const QPoint &pos, int corner);
void doStartSystemMoveResize(const QPoint &globalPos, int corner);
+ static bool isTrayIconWindow(QWindow *window)
+ {
+ return window->objectName() == QLatin1String("QSystemTrayIconSysWindow");
+ }
+
virtual void create();
virtual void destroy();
+ static void setWindowTitle(const QXcbConnection *conn, xcb_window_t window, const QString &title);
static QString windowTitle(const QXcbConnection *conn, xcb_window_t window);
public Q_SLOTS:
@@ -199,10 +199,9 @@ protected:
NetWmStates netWmStates();
void setNetWmStates(NetWmStates);
- void setMotifWindowFlags(Qt::WindowFlags flags);
- void setNetWmStateWindowFlags(Qt::WindowFlags flags);
+ void setMotifWmHints(Qt::WindowFlags flags);
- void updateMotifWmHintsBeforeMap();
+ void setNetWmStateWindowFlags(Qt::WindowFlags flags);
void updateNetWmStateBeforeMap();
void setTransparentForMouseEvents(bool transparent);
@@ -220,8 +219,6 @@ protected:
void doFocusIn();
void doFocusOut();
- bool compressExposeEvent(QRegion &exposeRegion);
-
void handleButtonPressEvent(int event_x, int event_y, int root_x, int root_y,
int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp,
QEvent::Type type, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized);
@@ -252,15 +249,13 @@ protected:
Qt::WindowStates m_windowState = Qt::WindowNoState;
- xcb_gravity_t m_gravity = XCB_GRAVITY_STATIC;
-
bool m_mapped = false;
bool m_transparent = false;
- bool m_usingSyncProtocol = false;
bool m_deferredActivation = false;
bool m_embedded = false;
bool m_alertState = false;
bool m_minimized = false;
+ bool m_trayIconWindow = false;
xcb_window_t m_netWmUserTimeWindow = XCB_NONE;
QSurfaceFormat m_format;
diff --git a/src/plugins/platforms/xcb/xcb-plugin.pro b/src/plugins/platforms/xcb/xcb-plugin.pro
index a2c56a3dcf..4c646d42c6 100644
--- a/src/plugins/platforms/xcb/xcb-plugin.pro
+++ b/src/plugins/platforms/xcb/xcb-plugin.pro
@@ -8,6 +8,7 @@ macos: CONFIG += no_app_extension_api_only
SOURCES = \
qxcbmain.cpp
+
OTHER_FILES += xcb.json README
PLUGIN_TYPE = platforms
diff --git a/src/plugins/platforms/xcb/xcb-static/xcb-static.pro b/src/plugins/platforms/xcb/xcb-static/xcb-static.pro
index 20d8b83e7c..078b275381 100644
--- a/src/plugins/platforms/xcb/xcb-static/xcb-static.pro
+++ b/src/plugins/platforms/xcb/xcb-static/xcb-static.pro
@@ -2,7 +2,7 @@
# Statically compile in code for
# libxcb-fixes, libxcb-randr, libxcb-shm, libxcb-sync, libxcb-image,
# libxcb-keysyms, libxcb-icccm, libxcb-renderutil, libxcb-xkb,
-# libxcb-xinerama
+# libxcb-xinerama, libxcb-xinput
#
CONFIG += static
@@ -29,7 +29,8 @@ SOURCES += \
$$LIBXCB_DIR/render.c \
$$LIBXCB_DIR/shape.c \
$$LIBXCB_DIR/xkb.c \
- $$LIBXCB_DIR/xinerama.c
+ $$LIBXCB_DIR/xinerama.c \
+ $$LIBXCB_DIR/xinput.c
#
# xcb-util
diff --git a/src/plugins/platforms/xcb/xcb_qpa_lib.pro b/src/plugins/platforms/xcb/xcb_qpa_lib.pro
index 9c4797ac26..c65b145fb6 100644
--- a/src/plugins/platforms/xcb/xcb_qpa_lib.pro
+++ b/src/plugins/platforms/xcb/xcb_qpa_lib.pro
@@ -5,7 +5,7 @@ DEFINES += QT_NO_FOREACH
QT += \
core-private gui-private \
service_support-private theme_support-private \
- eventdispatcher_support-private fontdatabase_support-private \
+ fontdatabase_support-private \
edid_support-private
qtHaveModule(linuxaccessibility_support-private): \
@@ -13,6 +13,8 @@ qtHaveModule(linuxaccessibility_support-private): \
qtConfig(vulkan): QT += vulkan_support-private
+qtConfig(glib) : QMAKE_USE_PRIVATE += glib
+
SOURCES = \
qxcbclipboard.cpp \
qxcbconnection.cpp \
@@ -27,7 +29,12 @@ SOURCES = \
qxcbcursor.cpp \
qxcbimage.cpp \
qxcbxsettings.cpp \
- qxcbsystemtraytracker.cpp
+ qxcbsystemtraytracker.cpp \
+ qxcbeventqueue.cpp \
+ qxcbeventdispatcher.cpp \
+ qxcbconnection_basic.cpp \
+ qxcbconnection_screens.cpp \
+ qxcbatom.cpp
HEADERS = \
qxcbclipboard.h \
@@ -45,7 +52,11 @@ HEADERS = \
qxcbimage.h \
qxcbxsettings.h \
qxcbsystemtraytracker.h \
- qxcbxkbcommon.h
+ qxcbxkbcommon.h \
+ qxcbeventqueue.h \
+ qxcbeventdispatcher.h \
+ qxcbconnection_basic.h \
+ qxcbatom.h
qtConfig(draganddrop) {
SOURCES += qxcbdrag.cpp
@@ -58,11 +69,10 @@ DEFINES += QT_BUILD_XCB_PLUGIN
qtConfig(xcb-xlib) {
QMAKE_USE += xcb_xlib
+}
- qtConfig(xinput2) {
- SOURCES += qxcbconnection_xi2.cpp
- QMAKE_USE += xinput2
- }
+qtConfig(xcb-xinput) {
+ SOURCES += qxcbconnection_xi2.cpp
}
qtConfig(xcb-sm) {
@@ -89,6 +99,7 @@ qtConfig(vulkan) {
} else {
qtConfig(xkb): QMAKE_USE += xcb_xkb
qtConfig(xcb-render): QMAKE_USE += xcb_render
+ qtConfig(xcb-xinput): QMAKE_USE += xcb_xinput
QMAKE_USE += xcb_syslibs
}
diff --git a/src/plugins/platformthemes/flatpak/flatpak.json b/src/plugins/platformthemes/flatpak/flatpak.json
deleted file mode 100644
index 71f834fd08..0000000000
--- a/src/plugins/platformthemes/flatpak/flatpak.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "Keys": [ "flatpak" ]
-}
diff --git a/src/plugins/platformthemes/flatpak/flatpak.pro b/src/plugins/platformthemes/flatpak/flatpak.pro
deleted file mode 100644
index 1e5dbb7a6c..0000000000
--- a/src/plugins/platformthemes/flatpak/flatpak.pro
+++ /dev/null
@@ -1,17 +0,0 @@
-TARGET = qflatpak
-
-PLUGIN_TYPE = platformthemes
-PLUGIN_EXTENDS = -
-PLUGIN_CLASS_NAME = QFlatpakThemePlugin
-load(qt_plugin)
-
-QT += core-private dbus gui-private theme_support-private
-
-HEADERS += \
- qflatpaktheme.h \
- qflatpakfiledialog_p.h
-
-SOURCES += \
- main.cpp \
- qflatpaktheme.cpp \
- qflatpakfiledialog.cpp
diff --git a/src/plugins/platformthemes/flatpak/main.cpp b/src/plugins/platformthemes/flatpak/main.cpp
deleted file mode 100644
index 7888eed8b2..0000000000
--- a/src/plugins/platformthemes/flatpak/main.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Red Hat, Inc
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <qpa/qplatformthemeplugin.h>
-#include "qflatpaktheme.h"
-
-QT_BEGIN_NAMESPACE
-
-class QFlatpakThemePlugin : public QPlatformThemePlugin
-{
- Q_OBJECT
- Q_PLUGIN_METADATA(IID QPlatformThemeFactoryInterface_iid FILE "flatpak.json")
-
-public:
- QPlatformTheme *create(const QString &key, const QStringList &params) override;
-};
-
-QPlatformTheme *QFlatpakThemePlugin::create(const QString &key, const QStringList &params)
-{
- Q_UNUSED(params);
- if (!key.compare(QLatin1String("flatpak"), Qt::CaseInsensitive))
- return new QFlatpakTheme;
-
- return nullptr;
-}
-
-QT_END_NAMESPACE
-
-#include "main.moc"
diff --git a/src/plugins/platformthemes/flatpak/qflatpakfiledialog.cpp b/src/plugins/platformthemes/flatpak/qflatpakfiledialog.cpp
deleted file mode 100644
index c31b326357..0000000000
--- a/src/plugins/platformthemes/flatpak/qflatpakfiledialog.cpp
+++ /dev/null
@@ -1,355 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Red Hat, Inc
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qflatpakfiledialog_p.h"
-
-#include <QtCore/qeventloop.h>
-
-#include <QtDBus/QtDBus>
-#include <QDBusConnection>
-#include <QDBusMessage>
-#include <QDBusPendingCall>
-#include <QDBusPendingCallWatcher>
-#include <QDBusPendingReply>
-
-#include <QMetaType>
-#include <QMimeType>
-#include <QMimeDatabase>
-#include <QRandomGenerator>
-#include <QWindow>
-
-QT_BEGIN_NAMESPACE
-
-QDBusArgument &operator <<(QDBusArgument &arg, const QFlatpakFileDialog::FilterCondition &filterCondition)
-{
- arg.beginStructure();
- arg << filterCondition.type << filterCondition.pattern;
- arg.endStructure();
- return arg;
-}
-
-const QDBusArgument &operator >>(const QDBusArgument &arg, QFlatpakFileDialog::FilterCondition &filterCondition)
-{
- uint type;
- QString filterPattern;
- arg.beginStructure();
- arg >> type >> filterPattern;
- filterCondition.type = (QFlatpakFileDialog::ConditionType)type;
- filterCondition.pattern = filterPattern;
- arg.endStructure();
-
- return arg;
-}
-
-QDBusArgument &operator <<(QDBusArgument &arg, const QFlatpakFileDialog::Filter filter)
-{
- arg.beginStructure();
- arg << filter.name << filter.filterConditions;
- arg.endStructure();
- return arg;
-}
-
-const QDBusArgument &operator >>(const QDBusArgument &arg, QFlatpakFileDialog::Filter &filter)
-{
- QString name;
- QFlatpakFileDialog::FilterConditionList filterConditions;
- arg.beginStructure();
- arg >> name >> filterConditions;
- filter.name = name;
- filter.filterConditions = filterConditions;
- arg.endStructure();
-
- return arg;
-}
-
-class QFlatpakFileDialogPrivate
-{
-public:
- WId winId = 0;
- bool modal = false;
- bool multipleFiles = false;
- bool saveFile = false;
- QString acceptLabel;
- QString directory;
- QString title;
- QStringList nameFilters;
- QStringList mimeTypesFilters;
- QStringList selectedFiles;
-};
-
-QFlatpakFileDialog::QFlatpakFileDialog()
- : QPlatformFileDialogHelper()
- , d_ptr(new QFlatpakFileDialogPrivate)
-{
-}
-
-QFlatpakFileDialog::~QFlatpakFileDialog()
-{
-}
-
-void QFlatpakFileDialog::initializeDialog()
-{
- Q_D(QFlatpakFileDialog);
-
- if (options()->fileMode() == QFileDialogOptions::ExistingFiles)
- d->multipleFiles = true;
-
- if (options()->isLabelExplicitlySet(QFileDialogOptions::Accept))
- d->acceptLabel = options()->labelText(QFileDialogOptions::Accept);
-
- if (!options()->windowTitle().isEmpty())
- d->title = options()->windowTitle();
-
- if (options()->acceptMode() == QFileDialogOptions::AcceptSave)
- d->saveFile = true;
-
- if (!options()->nameFilters().isEmpty())
- d->nameFilters = options()->nameFilters();
-
- if (!options()->mimeTypeFilters().isEmpty())
- d->mimeTypesFilters = options()->mimeTypeFilters();
-
- setDirectory(options()->initialDirectory());
-}
-
-void QFlatpakFileDialog::openPortal()
-{
- Q_D(const QFlatpakFileDialog);
-
- QDBusMessage message = QDBusMessage::createMethodCall(QLatin1String("org.freedesktop.portal.Desktop"),
- QLatin1String("/org/freedesktop/portal/desktop"),
- QLatin1String("org.freedesktop.portal.FileChooser"),
- d->saveFile ? QLatin1String("SaveFile") : QLatin1String("OpenFile"));
- QString parentWindowId = QLatin1String("x11:") + QString::number(d->winId);
-
- QVariantMap options;
- if (!d->acceptLabel.isEmpty())
- options.insert(QLatin1String("accept_label"), d->acceptLabel);
-
- options.insert(QLatin1String("modal"), d->modal);
- options.insert(QLatin1String("multiple"), d->multipleFiles);
-
- if (d->saveFile) {
- if (!d->directory.isEmpty())
- options.insert(QLatin1String("current_folder"), d->directory.toLatin1());
-
- if (!d->selectedFiles.isEmpty())
- options.insert(QLatin1String("current_file"), d->selectedFiles.first().toLatin1());
- }
-
- // Insert filters
- qDBusRegisterMetaType<FilterCondition>();
- qDBusRegisterMetaType<FilterConditionList>();
- qDBusRegisterMetaType<Filter>();
- qDBusRegisterMetaType<FilterList>();
-
- FilterList filterList;
-
- if (!d->mimeTypesFilters.isEmpty()) {
- for (const QString &mimeTypefilter : d->mimeTypesFilters) {
- QMimeDatabase mimeDatabase;
- QMimeType mimeType = mimeDatabase.mimeTypeForName(mimeTypefilter);
-
- // Creates e.g. (1, "image/png")
- FilterCondition filterCondition;
- filterCondition.type = MimeType;
- filterCondition.pattern = mimeTypefilter;
-
- // Creates e.g. [((1, "image/png"))]
- FilterConditionList filterConditions;
- filterConditions << filterCondition;
-
- // Creates e.g. [("Images", [((1, "image/png"))])]
- Filter filter;
- filter.name = mimeType.comment();
- filter.filterConditions = filterConditions;
-
- filterList << filter;
- }
- } else if (!d->nameFilters.isEmpty()) {
- for (const QString &filter : d->nameFilters) {
- // Do parsing:
- // Supported format is ("Images (*.png *.jpg)")
- QRegularExpression regexp(QPlatformFileDialogHelper::filterRegExp);
- QRegularExpressionMatch match = regexp.match(filter);
- if (match.hasMatch()) {
- QString userVisibleName = match.captured(1);
- QStringList filterStrings = match.captured(2).split(QLatin1Char(' '), QString::SkipEmptyParts);
-
- FilterConditionList filterConditions;
- for (const QString &filterString : filterStrings) {
- FilterCondition filterCondition;
- filterCondition.type = GlobalPattern;
- filterCondition.pattern = filterString;
- filterConditions << filterCondition;
- }
-
- Filter filter;
- filter.name = userVisibleName;
- filter.filterConditions = filterConditions;
-
- filterList << filter;
- }
- }
- }
-
- if (!filterList.isEmpty())
- options.insert(QLatin1String("filters"), QVariant::fromValue(filterList));
-
- options.insert(QLatin1String("handle_token"), QStringLiteral("qt%1").arg(QRandomGenerator::global()->generate()));
-
- // TODO choices a(ssa(ss)s)
- // List of serialized combo boxes to add to the file chooser.
-
- message << parentWindowId << d->title << options;
-
- QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message);
- QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall);
- connect(watcher, &QDBusPendingCallWatcher::finished, this, [this] (QDBusPendingCallWatcher *watcher) {
- QDBusPendingReply<QDBusObjectPath> reply = *watcher;
- if (reply.isError()) {
- Q_EMIT reject();
- } else {
- QDBusConnection::sessionBus().connect(nullptr,
- reply.value().path(),
- QLatin1String("org.freedesktop.portal.Request"),
- QLatin1String("Response"),
- this,
- SLOT(gotResponse(uint,QVariantMap)));
- }
- });
-}
-
-bool QFlatpakFileDialog::defaultNameFilterDisables() const
-{
- return false;
-}
-
-void QFlatpakFileDialog::setDirectory(const QUrl &directory)
-{
- Q_D(QFlatpakFileDialog);
-
- d->directory = directory.path();
-}
-
-QUrl QFlatpakFileDialog::directory() const
-{
- Q_D(const QFlatpakFileDialog);
-
- return d->directory;
-}
-
-void QFlatpakFileDialog::selectFile(const QUrl &filename)
-{
- Q_D(QFlatpakFileDialog);
-
- d->selectedFiles << filename.path();
-}
-
-QList<QUrl> QFlatpakFileDialog::selectedFiles() const
-{
- Q_D(const QFlatpakFileDialog);
-
- QList<QUrl> files;
- for (const QString &file : d->selectedFiles) {
- files << QUrl(file);
- }
- return files;
-}
-
-void QFlatpakFileDialog::setFilter()
-{
- // TODO
-}
-
-void QFlatpakFileDialog::selectNameFilter(const QString &filter)
-{
- Q_UNUSED(filter);
- // TODO
-}
-
-QString QFlatpakFileDialog::selectedNameFilter() const
-{
- // TODO
- return QString();
-}
-
-void QFlatpakFileDialog::exec()
-{
- // HACK we have to avoid returning until we emit that the dialog was accepted or rejected
- QEventLoop loop;
- loop.connect(this, SIGNAL(accept()), SLOT(quit()));
- loop.connect(this, SIGNAL(reject()), SLOT(quit()));
- loop.exec();
-}
-
-void QFlatpakFileDialog::hide()
-{
-}
-
-bool QFlatpakFileDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent)
-{
- Q_D(QFlatpakFileDialog);
- Q_UNUSED(windowFlags);
-
- initializeDialog();
-
- d->modal = windowModality != Qt::NonModal;
- d->winId = parent ? parent->winId() : 0;
-
- openPortal();
-
- return true;
-}
-
-void QFlatpakFileDialog::gotResponse(uint response, const QVariantMap &results)
-{
- Q_D(QFlatpakFileDialog);
-
- if (!response) {
- if (results.contains(QLatin1String("uris")))
- d->selectedFiles = results.value(QLatin1String("uris")).toStringList();
-
- Q_EMIT accept();
- } else {
- Q_EMIT reject();
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platformthemes/flatpak/qflatpakfiledialog_p.h b/src/plugins/platformthemes/flatpak/qflatpakfiledialog_p.h
deleted file mode 100644
index f3e195faa0..0000000000
--- a/src/plugins/platformthemes/flatpak/qflatpakfiledialog_p.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Red Hat, Inc
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#ifndef QFLATPAKFILEDIALOG_P_H
-#define QFLATPAKFILEDIALOG_P_H
-
-#include <qpa/qplatformdialoghelper.h>
-#include <QVector>
-
-QT_BEGIN_NAMESPACE
-
-class QFlatpakFileDialogPrivate;
-
-class QFlatpakFileDialog : public QPlatformFileDialogHelper
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QFlatpakFileDialog)
-public:
- enum ConditionType : uint {
- GlobalPattern = 0,
- MimeType = 1
- };
- // Filters a(sa(us))
- // Example: [('Images', [(0, '*.ico'), (1, 'image/png')]), ('Text', [(0, '*.txt')])]
- struct FilterCondition {
- ConditionType type;
- QString pattern; // E.g. '*ico' or 'image/png'
- };
- typedef QVector<FilterCondition> FilterConditionList;
-
- struct Filter {
- QString name; // E.g. 'Images' or 'Text
- FilterConditionList filterConditions;; // E.g. [(0, '*.ico'), (1, 'image/png')] or [(0, '*.txt')]
- };
- typedef QVector<Filter> FilterList;
-
- QFlatpakFileDialog();
- ~QFlatpakFileDialog();
-
- bool defaultNameFilterDisables() const override;
- QUrl directory() const override;
- void setDirectory(const QUrl &directory) override;
- void selectFile(const QUrl &filename) override;
- QList<QUrl> selectedFiles() const override;
- void setFilter() override;
- void selectNameFilter(const QString &filter) override;
- QString selectedNameFilter() const override;
-
- void exec() override;
- bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) override;
- void hide() override;
-
-private Q_SLOTS:
- void gotResponse(uint response, const QVariantMap &results);
-
-private:
- void initializeDialog();
- void openPortal();
-
- QScopedPointer<QFlatpakFileDialogPrivate> d_ptr;
-};
-
-QT_END_NAMESPACE
-
-Q_DECLARE_METATYPE(QFlatpakFileDialog::FilterCondition);
-Q_DECLARE_METATYPE(QFlatpakFileDialog::FilterConditionList);
-Q_DECLARE_METATYPE(QFlatpakFileDialog::Filter);
-Q_DECLARE_METATYPE(QFlatpakFileDialog::FilterList);
-
-#endif // QFLATPAKFILEDIALOG_P_H
-
diff --git a/src/plugins/platformthemes/flatpak/qflatpaktheme.cpp b/src/plugins/platformthemes/flatpak/qflatpaktheme.cpp
deleted file mode 100644
index 6c5e1389cf..0000000000
--- a/src/plugins/platformthemes/flatpak/qflatpaktheme.cpp
+++ /dev/null
@@ -1,196 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qflatpaktheme.h"
-#include "qflatpakfiledialog_p.h"
-
-#include <private/qguiapplication_p.h>
-#include <qpa/qplatformtheme_p.h>
-#include <qpa/qplatformthemefactory_p.h>
-#include <qpa/qplatformintegration.h>
-
-QT_BEGIN_NAMESPACE
-
-class QFlatpakThemePrivate : public QPlatformThemePrivate
-{
-public:
- QFlatpakThemePrivate()
- : QPlatformThemePrivate()
- { }
-
- ~QFlatpakThemePrivate()
- {
- delete baseTheme;
- }
-
- QPlatformTheme *baseTheme;
-};
-
-QFlatpakTheme::QFlatpakTheme()
- : d_ptr(new QFlatpakThemePrivate)
-{
- Q_D(QFlatpakTheme);
-
- QStringList themeNames;
- themeNames += QGuiApplicationPrivate::platform_integration->themeNames();
- // 1) Look for a theme plugin.
- for (const QString &themeName : qAsConst(themeNames)) {
- d->baseTheme = QPlatformThemeFactory::create(themeName, nullptr);
- if (d->baseTheme)
- break;
- }
-
- // 2) If no theme plugin was found ask the platform integration to
- // create a theme
- if (!d->baseTheme) {
- for (const QString &themeName : qAsConst(themeNames)) {
- d->baseTheme = QGuiApplicationPrivate::platform_integration->createPlatformTheme(themeName);
- if (d->baseTheme)
- break;
- }
- // No error message; not having a theme plugin is allowed.
- }
-
- // 3) Fall back on the built-in "null" platform theme.
- if (!d->baseTheme)
- d->baseTheme = new QPlatformTheme;
-}
-
-QPlatformMenuItem* QFlatpakTheme::createPlatformMenuItem() const
-{
- Q_D(const QFlatpakTheme);
- return d->baseTheme->createPlatformMenuItem();
-}
-
-QPlatformMenu* QFlatpakTheme::createPlatformMenu() const
-{
- Q_D(const QFlatpakTheme);
- return d->baseTheme->createPlatformMenu();
-}
-
-QPlatformMenuBar* QFlatpakTheme::createPlatformMenuBar() const
-{
- Q_D(const QFlatpakTheme);
- return d->baseTheme->createPlatformMenuBar();
-}
-
-void QFlatpakTheme::showPlatformMenuBar()
-{
- Q_D(const QFlatpakTheme);
- return d->baseTheme->showPlatformMenuBar();
-}
-
-bool QFlatpakTheme::usePlatformNativeDialog(DialogType type) const
-{
- Q_D(const QFlatpakTheme);
-
- if (type == FileDialog)
- return true;
-
- return d->baseTheme->usePlatformNativeDialog(type);
-}
-
-QPlatformDialogHelper* QFlatpakTheme::createPlatformDialogHelper(DialogType type) const
-{
- Q_D(const QFlatpakTheme);
-
- if (type == FileDialog)
- return new QFlatpakFileDialog;
-
- return d->baseTheme->createPlatformDialogHelper(type);
-}
-
-#ifndef QT_NO_SYSTEMTRAYICON
-QPlatformSystemTrayIcon* QFlatpakTheme::createPlatformSystemTrayIcon() const
-{
- Q_D(const QFlatpakTheme);
- return d->baseTheme->createPlatformSystemTrayIcon();
-}
-#endif
-
-const QPalette *QFlatpakTheme::palette(Palette type) const
-{
- Q_D(const QFlatpakTheme);
- return d->baseTheme->palette(type);
-}
-
-const QFont* QFlatpakTheme::font(Font type) const
-{
- Q_D(const QFlatpakTheme);
- return d->baseTheme->font(type);
-}
-
-QVariant QFlatpakTheme::themeHint(ThemeHint hint) const
-{
- Q_D(const QFlatpakTheme);
- return d->baseTheme->themeHint(hint);
-}
-
-QPixmap QFlatpakTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const
-{
- Q_D(const QFlatpakTheme);
- return d->baseTheme->standardPixmap(sp, size);
-}
-
-QIcon QFlatpakTheme::fileIcon(const QFileInfo &fileInfo,
- QPlatformTheme::IconOptions iconOptions) const
-{
- Q_D(const QFlatpakTheme);
- return d->baseTheme->fileIcon(fileInfo, iconOptions);
-}
-
-QIconEngine * QFlatpakTheme::createIconEngine(const QString &iconName) const
-{
- Q_D(const QFlatpakTheme);
- return d->baseTheme->createIconEngine(iconName);
-}
-
-QList<QKeySequence> QFlatpakTheme::keyBindings(QKeySequence::StandardKey key) const
-{
- Q_D(const QFlatpakTheme);
- return d->baseTheme->keyBindings(key);
-}
-
-QString QFlatpakTheme::standardButtonText(int button) const
-{
- Q_D(const QFlatpakTheme);
- return d->baseTheme->standardButtonText(button);
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platformthemes/flatpak/qflatpaktheme.h b/src/plugins/platformthemes/flatpak/qflatpaktheme.h
deleted file mode 100644
index 87f79a2395..0000000000
--- a/src/plugins/platformthemes/flatpak/qflatpaktheme.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QFLATPAKTHEME_H
-#define QFLATPAKTHEME_H
-
-#include <qpa/qplatformtheme.h>
-
-QT_BEGIN_NAMESPACE
-
-class QFlatpakThemePrivate;
-
-class QFlatpakTheme : public QPlatformTheme
-{
- Q_DECLARE_PRIVATE(QFlatpakTheme)
-public:
- QFlatpakTheme();
-
- QPlatformMenuItem *createPlatformMenuItem() const override;
- QPlatformMenu *createPlatformMenu() const override;
- QPlatformMenuBar *createPlatformMenuBar() const override;
- void showPlatformMenuBar() override;
-
- bool usePlatformNativeDialog(DialogType type) const override;
- QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const override;
-
-#ifndef QT_NO_SYSTEMTRAYICON
- QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const override;
-#endif
-
- const QPalette *palette(Palette type = SystemPalette) const override;
-
- const QFont *font(Font type = SystemFont) const override;
-
- QVariant themeHint(ThemeHint hint) const override;
-
- QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const override;
- QIcon fileIcon(const QFileInfo &fileInfo,
- QPlatformTheme::IconOptions iconOptions = 0) const override;
-
- QIconEngine *createIconEngine(const QString &iconName) const override;
-
- QList<QKeySequence> keyBindings(QKeySequence::StandardKey key) const override;
-
- QString standardButtonText(int button) const override;
-
-private:
- QScopedPointer<QFlatpakThemePrivate> d_ptr;
- Q_DISABLE_COPY(QFlatpakTheme)
-};
-
-QT_END_NAMESPACE
-
-#endif // QFLATPAKTHEME_H
diff --git a/src/plugins/platformthemes/platformthemes.pro b/src/plugins/platformthemes/platformthemes.pro
index 02ed3406e7..3bcc659199 100644
--- a/src/plugins/platformthemes/platformthemes.pro
+++ b/src/plugins/platformthemes/platformthemes.pro
@@ -1,6 +1,6 @@
TEMPLATE = subdirs
QT_FOR_CONFIG += widgets-private
-qtConfig(dbus):qtConfig(regularexpression):qtConfig(mimetype): SUBDIRS += flatpak
+qtConfig(dbus):qtConfig(regularexpression):qtConfig(mimetype): SUBDIRS += xdgdesktopportal
qtHaveModule(widgets):qtConfig(gtk3): SUBDIRS += gtk3
diff --git a/src/plugins/platformthemes/xdgdesktopportal/main.cpp b/src/plugins/platformthemes/xdgdesktopportal/main.cpp
new file mode 100644
index 0000000000..64a03d479f
--- /dev/null
+++ b/src/plugins/platformthemes/xdgdesktopportal/main.cpp
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2017-2018 Red Hat, Inc
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qpa/qplatformthemeplugin.h>
+#include "qxdgdesktopportaltheme.h"
+
+QT_BEGIN_NAMESPACE
+
+class QXdgDesktopPortalThemePlugin : public QPlatformThemePlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QPlatformThemeFactoryInterface_iid FILE "xdgdesktopportal.json")
+
+public:
+ QPlatformTheme *create(const QString &key, const QStringList &params) override;
+};
+
+QPlatformTheme *QXdgDesktopPortalThemePlugin::create(const QString &key, const QStringList &params)
+{
+ Q_UNUSED(params);
+ if (!key.compare(QLatin1String("xdgdesktopportal"), Qt::CaseInsensitive) ||
+ !key.compare(QLatin1String("flatpak"), Qt::CaseInsensitive) ||
+ !key.compare(QLatin1String("snap"), Qt::CaseInsensitive))
+ return new QXdgDesktopPortalTheme;
+
+ return nullptr;
+}
+
+QT_END_NAMESPACE
+
+#include "main.moc"
diff --git a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp
new file mode 100644
index 0000000000..cda267d24b
--- /dev/null
+++ b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog.cpp
@@ -0,0 +1,407 @@
+/****************************************************************************
+**
+** Copyright (C) 2017-2018 Red Hat, Inc
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qxdgdesktopportalfiledialog_p.h"
+
+#include <QtCore/qeventloop.h>
+
+#include <QtDBus/QtDBus>
+#include <QDBusConnection>
+#include <QDBusMessage>
+#include <QDBusPendingCall>
+#include <QDBusPendingCallWatcher>
+#include <QDBusPendingReply>
+
+#include <QMetaType>
+#include <QMimeType>
+#include <QMimeDatabase>
+#include <QRandomGenerator>
+#include <QWindow>
+
+QT_BEGIN_NAMESPACE
+
+QDBusArgument &operator <<(QDBusArgument &arg, const QXdgDesktopPortalFileDialog::FilterCondition &filterCondition)
+{
+ arg.beginStructure();
+ arg << filterCondition.type << filterCondition.pattern;
+ arg.endStructure();
+ return arg;
+}
+
+const QDBusArgument &operator >>(const QDBusArgument &arg, QXdgDesktopPortalFileDialog::FilterCondition &filterCondition)
+{
+ uint type;
+ QString filterPattern;
+ arg.beginStructure();
+ arg >> type >> filterPattern;
+ filterCondition.type = (QXdgDesktopPortalFileDialog::ConditionType)type;
+ filterCondition.pattern = filterPattern;
+ arg.endStructure();
+
+ return arg;
+}
+
+QDBusArgument &operator <<(QDBusArgument &arg, const QXdgDesktopPortalFileDialog::Filter filter)
+{
+ arg.beginStructure();
+ arg << filter.name << filter.filterConditions;
+ arg.endStructure();
+ return arg;
+}
+
+const QDBusArgument &operator >>(const QDBusArgument &arg, QXdgDesktopPortalFileDialog::Filter &filter)
+{
+ QString name;
+ QXdgDesktopPortalFileDialog::FilterConditionList filterConditions;
+ arg.beginStructure();
+ arg >> name >> filterConditions;
+ filter.name = name;
+ filter.filterConditions = filterConditions;
+ arg.endStructure();
+
+ return arg;
+}
+
+class QXdgDesktopPortalFileDialogPrivate
+{
+public:
+ QXdgDesktopPortalFileDialogPrivate(QPlatformFileDialogHelper *nativeFileDialog)
+ : nativeFileDialog(nativeFileDialog)
+ { }
+
+ WId winId = 0;
+ bool modal = false;
+ bool multipleFiles = false;
+ bool saveFile = false;
+ QString acceptLabel;
+ QString directory;
+ QString title;
+ QStringList nameFilters;
+ QStringList mimeTypesFilters;
+ QStringList selectedFiles;
+ QPlatformFileDialogHelper *nativeFileDialog = nullptr;
+};
+
+QXdgDesktopPortalFileDialog::QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog)
+ : QPlatformFileDialogHelper()
+ , d_ptr(new QXdgDesktopPortalFileDialogPrivate(nativeFileDialog))
+{
+ Q_D(QXdgDesktopPortalFileDialog);
+
+ if (d->nativeFileDialog) {
+ connect(d->nativeFileDialog, SIGNAL(accept()), this, SIGNAL(accept()));
+ connect(d->nativeFileDialog, SIGNAL(reject()), this, SIGNAL(reject()));
+ }
+}
+
+QXdgDesktopPortalFileDialog::~QXdgDesktopPortalFileDialog()
+{
+}
+
+void QXdgDesktopPortalFileDialog::initializeDialog()
+{
+ Q_D(QXdgDesktopPortalFileDialog);
+
+ if (d->nativeFileDialog)
+ d->nativeFileDialog->setOptions(options());
+
+ if (options()->fileMode() == QFileDialogOptions::ExistingFiles)
+ d->multipleFiles = true;
+
+ if (options()->isLabelExplicitlySet(QFileDialogOptions::Accept))
+ d->acceptLabel = options()->labelText(QFileDialogOptions::Accept);
+
+ if (!options()->windowTitle().isEmpty())
+ d->title = options()->windowTitle();
+
+ if (options()->acceptMode() == QFileDialogOptions::AcceptSave)
+ d->saveFile = true;
+
+ if (!options()->nameFilters().isEmpty())
+ d->nameFilters = options()->nameFilters();
+
+ if (!options()->mimeTypeFilters().isEmpty())
+ d->mimeTypesFilters = options()->mimeTypeFilters();
+
+ setDirectory(options()->initialDirectory());
+}
+
+void QXdgDesktopPortalFileDialog::openPortal()
+{
+ Q_D(const QXdgDesktopPortalFileDialog);
+
+ QDBusMessage message = QDBusMessage::createMethodCall(QLatin1String("org.freedesktop.portal.Desktop"),
+ QLatin1String("/org/freedesktop/portal/desktop"),
+ QLatin1String("org.freedesktop.portal.FileChooser"),
+ d->saveFile ? QLatin1String("SaveFile") : QLatin1String("OpenFile"));
+ QString parentWindowId = QLatin1String("x11:") + QString::number(d->winId);
+
+ QVariantMap options;
+ if (!d->acceptLabel.isEmpty())
+ options.insert(QLatin1String("accept_label"), d->acceptLabel);
+
+ options.insert(QLatin1String("modal"), d->modal);
+ options.insert(QLatin1String("multiple"), d->multipleFiles);
+
+ if (d->saveFile) {
+ if (!d->directory.isEmpty())
+ options.insert(QLatin1String("current_folder"), d->directory.toLatin1());
+
+ if (!d->selectedFiles.isEmpty())
+ options.insert(QLatin1String("current_file"), d->selectedFiles.first().toLatin1());
+ }
+
+ // Insert filters
+ qDBusRegisterMetaType<FilterCondition>();
+ qDBusRegisterMetaType<FilterConditionList>();
+ qDBusRegisterMetaType<Filter>();
+ qDBusRegisterMetaType<FilterList>();
+
+ FilterList filterList;
+
+ if (!d->mimeTypesFilters.isEmpty()) {
+ for (const QString &mimeTypefilter : d->mimeTypesFilters) {
+ QMimeDatabase mimeDatabase;
+ QMimeType mimeType = mimeDatabase.mimeTypeForName(mimeTypefilter);
+
+ // Creates e.g. (1, "image/png")
+ FilterCondition filterCondition;
+ filterCondition.type = MimeType;
+ filterCondition.pattern = mimeTypefilter;
+
+ // Creates e.g. [((1, "image/png"))]
+ FilterConditionList filterConditions;
+ filterConditions << filterCondition;
+
+ // Creates e.g. [("Images", [((1, "image/png"))])]
+ Filter filter;
+ filter.name = mimeType.comment();
+ filter.filterConditions = filterConditions;
+
+ filterList << filter;
+ }
+ } else if (!d->nameFilters.isEmpty()) {
+ for (const QString &filter : d->nameFilters) {
+ // Do parsing:
+ // Supported format is ("Images (*.png *.jpg)")
+ QRegularExpression regexp(QPlatformFileDialogHelper::filterRegExp);
+ QRegularExpressionMatch match = regexp.match(filter);
+ if (match.hasMatch()) {
+ QString userVisibleName = match.captured(1);
+ QStringList filterStrings = match.captured(2).split(QLatin1Char(' '), QString::SkipEmptyParts);
+
+ FilterConditionList filterConditions;
+ for (const QString &filterString : filterStrings) {
+ FilterCondition filterCondition;
+ filterCondition.type = GlobalPattern;
+ filterCondition.pattern = filterString;
+ filterConditions << filterCondition;
+ }
+
+ Filter filter;
+ filter.name = userVisibleName;
+ filter.filterConditions = filterConditions;
+
+ filterList << filter;
+ }
+ }
+ }
+
+ if (!filterList.isEmpty())
+ options.insert(QLatin1String("filters"), QVariant::fromValue(filterList));
+
+ options.insert(QLatin1String("handle_token"), QStringLiteral("qt%1").arg(QRandomGenerator::global()->generate()));
+
+ // TODO choices a(ssa(ss)s)
+ // List of serialized combo boxes to add to the file chooser.
+
+ message << parentWindowId << d->title << options;
+
+ QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message);
+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall);
+ connect(watcher, &QDBusPendingCallWatcher::finished, this, [this] (QDBusPendingCallWatcher *watcher) {
+ QDBusPendingReply<QDBusObjectPath> reply = *watcher;
+ if (reply.isError()) {
+ Q_EMIT reject();
+ } else {
+ QDBusConnection::sessionBus().connect(nullptr,
+ reply.value().path(),
+ QLatin1String("org.freedesktop.portal.Request"),
+ QLatin1String("Response"),
+ this,
+ SLOT(gotResponse(uint,QVariantMap)));
+ }
+ });
+}
+
+bool QXdgDesktopPortalFileDialog::defaultNameFilterDisables() const
+{
+ return false;
+}
+
+void QXdgDesktopPortalFileDialog::setDirectory(const QUrl &directory)
+{
+ Q_D(QXdgDesktopPortalFileDialog);
+
+ if (d->nativeFileDialog) {
+ d->nativeFileDialog->setOptions(options());
+ d->nativeFileDialog->setDirectory(directory);
+ }
+
+ d->directory = directory.path();
+}
+
+QUrl QXdgDesktopPortalFileDialog::directory() const
+{
+ Q_D(const QXdgDesktopPortalFileDialog);
+
+ if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly))
+ return d->nativeFileDialog->directory();
+
+ return d->directory;
+}
+
+void QXdgDesktopPortalFileDialog::selectFile(const QUrl &filename)
+{
+ Q_D(QXdgDesktopPortalFileDialog);
+
+ if (d->nativeFileDialog) {
+ d->nativeFileDialog->setOptions(options());
+ d->nativeFileDialog->selectFile(filename);
+ }
+
+ d->selectedFiles << filename.path();
+}
+
+QList<QUrl> QXdgDesktopPortalFileDialog::selectedFiles() const
+{
+ Q_D(const QXdgDesktopPortalFileDialog);
+
+ if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly))
+ return d->nativeFileDialog->selectedFiles();
+
+ QList<QUrl> files;
+ for (const QString &file : d->selectedFiles) {
+ files << QUrl(file);
+ }
+ return files;
+}
+
+void QXdgDesktopPortalFileDialog::setFilter()
+{
+ Q_D(QXdgDesktopPortalFileDialog);
+
+ if (d->nativeFileDialog) {
+ d->nativeFileDialog->setOptions(options());
+ d->nativeFileDialog->setFilter();
+ }
+}
+
+void QXdgDesktopPortalFileDialog::selectNameFilter(const QString &filter)
+{
+ Q_D(QXdgDesktopPortalFileDialog);
+
+ if (d->nativeFileDialog) {
+ d->nativeFileDialog->setOptions(options());
+ d->nativeFileDialog->selectNameFilter(filter);
+ }
+}
+
+QString QXdgDesktopPortalFileDialog::selectedNameFilter() const
+{
+ // TODO
+ return QString();
+}
+
+void QXdgDesktopPortalFileDialog::exec()
+{
+ Q_D(QXdgDesktopPortalFileDialog);
+
+ if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly)) {
+ d->nativeFileDialog->exec();
+ return;
+ }
+
+ // HACK we have to avoid returning until we emit that the dialog was accepted or rejected
+ QEventLoop loop;
+ loop.connect(this, SIGNAL(accept()), SLOT(quit()));
+ loop.connect(this, SIGNAL(reject()), SLOT(quit()));
+ loop.exec();
+}
+
+void QXdgDesktopPortalFileDialog::hide()
+{
+ Q_D(QXdgDesktopPortalFileDialog);
+
+ if (d->nativeFileDialog)
+ d->nativeFileDialog->hide();
+}
+
+bool QXdgDesktopPortalFileDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent)
+{
+ Q_D(QXdgDesktopPortalFileDialog);
+
+ initializeDialog();
+
+ d->modal = windowModality != Qt::NonModal;
+ d->winId = parent ? parent->winId() : 0;
+
+ if (d->nativeFileDialog && (options()->fileMode() == QFileDialogOptions::Directory || options()->fileMode() == QFileDialogOptions::DirectoryOnly))
+ return d->nativeFileDialog->show(windowFlags, windowModality, parent);
+
+ openPortal();
+
+ return true;
+}
+
+void QXdgDesktopPortalFileDialog::gotResponse(uint response, const QVariantMap &results)
+{
+ Q_D(QXdgDesktopPortalFileDialog);
+
+ if (!response) {
+ if (results.contains(QLatin1String("uris")))
+ d->selectedFiles = results.value(QLatin1String("uris")).toStringList();
+
+ Q_EMIT accept();
+ } else {
+ Q_EMIT reject();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h
new file mode 100644
index 0000000000..c1f1a2c005
--- /dev/null
+++ b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportalfiledialog_p.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2017-2018 Red Hat, Inc
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QXDGDESKTOPPORTALFILEDIALOG_P_H
+#define QXDGDESKTOPPORTALFILEDIALOG_P_H
+
+#include <qpa/qplatformdialoghelper.h>
+#include <QVector>
+
+QT_BEGIN_NAMESPACE
+
+class QXdgDesktopPortalFileDialogPrivate;
+
+class QXdgDesktopPortalFileDialog : public QPlatformFileDialogHelper
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QXdgDesktopPortalFileDialog)
+public:
+ enum ConditionType : uint {
+ GlobalPattern = 0,
+ MimeType = 1
+ };
+ // Filters a(sa(us))
+ // Example: [('Images', [(0, '*.ico'), (1, 'image/png')]), ('Text', [(0, '*.txt')])]
+ struct FilterCondition {
+ ConditionType type;
+ QString pattern; // E.g. '*ico' or 'image/png'
+ };
+ typedef QVector<FilterCondition> FilterConditionList;
+
+ struct Filter {
+ QString name; // E.g. 'Images' or 'Text
+ FilterConditionList filterConditions;; // E.g. [(0, '*.ico'), (1, 'image/png')] or [(0, '*.txt')]
+ };
+ typedef QVector<Filter> FilterList;
+
+ QXdgDesktopPortalFileDialog(QPlatformFileDialogHelper *nativeFileDialog = nullptr);
+ ~QXdgDesktopPortalFileDialog();
+
+ bool defaultNameFilterDisables() const override;
+ QUrl directory() const override;
+ void setDirectory(const QUrl &directory) override;
+ void selectFile(const QUrl &filename) override;
+ QList<QUrl> selectedFiles() const override;
+ void setFilter() override;
+ void selectNameFilter(const QString &filter) override;
+ QString selectedNameFilter() const override;
+
+ void exec() override;
+ bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) override;
+ void hide() override;
+
+private Q_SLOTS:
+ void gotResponse(uint response, const QVariantMap &results);
+
+private:
+ void initializeDialog();
+ void openPortal();
+
+ QScopedPointer<QXdgDesktopPortalFileDialogPrivate> d_ptr;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QXdgDesktopPortalFileDialog::FilterCondition);
+Q_DECLARE_METATYPE(QXdgDesktopPortalFileDialog::FilterConditionList);
+Q_DECLARE_METATYPE(QXdgDesktopPortalFileDialog::Filter);
+Q_DECLARE_METATYPE(QXdgDesktopPortalFileDialog::FilterList);
+
+#endif // QXDGDESKTOPPORTALFILEDIALOG_P_H
+
diff --git a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp
new file mode 100644
index 0000000000..f07ca3f098
--- /dev/null
+++ b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.cpp
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qxdgdesktopportaltheme.h"
+#include "qxdgdesktopportalfiledialog_p.h"
+
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformtheme_p.h>
+#include <qpa/qplatformthemefactory_p.h>
+#include <qpa/qplatformintegration.h>
+
+QT_BEGIN_NAMESPACE
+
+class QXdgDesktopPortalThemePrivate : public QPlatformThemePrivate
+{
+public:
+ QXdgDesktopPortalThemePrivate()
+ : QPlatformThemePrivate()
+ { }
+
+ ~QXdgDesktopPortalThemePrivate()
+ {
+ delete baseTheme;
+ }
+
+ QPlatformTheme *baseTheme;
+};
+
+QXdgDesktopPortalTheme::QXdgDesktopPortalTheme()
+ : d_ptr(new QXdgDesktopPortalThemePrivate)
+{
+ Q_D(QXdgDesktopPortalTheme);
+
+ QStringList themeNames;
+ themeNames += QGuiApplicationPrivate::platform_integration->themeNames();
+ // 1) Look for a theme plugin.
+ for (const QString &themeName : qAsConst(themeNames)) {
+ d->baseTheme = QPlatformThemeFactory::create(themeName, nullptr);
+ if (d->baseTheme)
+ break;
+ }
+
+ // 2) If no theme plugin was found ask the platform integration to
+ // create a theme
+ if (!d->baseTheme) {
+ for (const QString &themeName : qAsConst(themeNames)) {
+ d->baseTheme = QGuiApplicationPrivate::platform_integration->createPlatformTheme(themeName);
+ if (d->baseTheme)
+ break;
+ }
+ // No error message; not having a theme plugin is allowed.
+ }
+
+ // 3) Fall back on the built-in "null" platform theme.
+ if (!d->baseTheme)
+ d->baseTheme = new QPlatformTheme;
+}
+
+QPlatformMenuItem* QXdgDesktopPortalTheme::createPlatformMenuItem() const
+{
+ Q_D(const QXdgDesktopPortalTheme);
+ return d->baseTheme->createPlatformMenuItem();
+}
+
+QPlatformMenu* QXdgDesktopPortalTheme::createPlatformMenu() const
+{
+ Q_D(const QXdgDesktopPortalTheme);
+ return d->baseTheme->createPlatformMenu();
+}
+
+QPlatformMenuBar* QXdgDesktopPortalTheme::createPlatformMenuBar() const
+{
+ Q_D(const QXdgDesktopPortalTheme);
+ return d->baseTheme->createPlatformMenuBar();
+}
+
+void QXdgDesktopPortalTheme::showPlatformMenuBar()
+{
+ Q_D(const QXdgDesktopPortalTheme);
+ return d->baseTheme->showPlatformMenuBar();
+}
+
+bool QXdgDesktopPortalTheme::usePlatformNativeDialog(DialogType type) const
+{
+ Q_D(const QXdgDesktopPortalTheme);
+
+ if (type == FileDialog)
+ return true;
+
+ return d->baseTheme->usePlatformNativeDialog(type);
+}
+
+QPlatformDialogHelper* QXdgDesktopPortalTheme::createPlatformDialogHelper(DialogType type) const
+{
+ Q_D(const QXdgDesktopPortalTheme);
+
+ if (type == FileDialog) {
+ if (d->baseTheme->usePlatformNativeDialog(type))
+ return new QXdgDesktopPortalFileDialog(static_cast<QPlatformFileDialogHelper*>(d->baseTheme->createPlatformDialogHelper(type)));
+
+ return new QXdgDesktopPortalFileDialog;
+ }
+
+ return d->baseTheme->createPlatformDialogHelper(type);
+}
+
+#ifndef QT_NO_SYSTEMTRAYICON
+QPlatformSystemTrayIcon* QXdgDesktopPortalTheme::createPlatformSystemTrayIcon() const
+{
+ Q_D(const QXdgDesktopPortalTheme);
+ return d->baseTheme->createPlatformSystemTrayIcon();
+}
+#endif
+
+const QPalette *QXdgDesktopPortalTheme::palette(Palette type) const
+{
+ Q_D(const QXdgDesktopPortalTheme);
+ return d->baseTheme->palette(type);
+}
+
+const QFont* QXdgDesktopPortalTheme::font(Font type) const
+{
+ Q_D(const QXdgDesktopPortalTheme);
+ return d->baseTheme->font(type);
+}
+
+QVariant QXdgDesktopPortalTheme::themeHint(ThemeHint hint) const
+{
+ Q_D(const QXdgDesktopPortalTheme);
+ return d->baseTheme->themeHint(hint);
+}
+
+QPixmap QXdgDesktopPortalTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const
+{
+ Q_D(const QXdgDesktopPortalTheme);
+ return d->baseTheme->standardPixmap(sp, size);
+}
+
+QIcon QXdgDesktopPortalTheme::fileIcon(const QFileInfo &fileInfo,
+ QPlatformTheme::IconOptions iconOptions) const
+{
+ Q_D(const QXdgDesktopPortalTheme);
+ return d->baseTheme->fileIcon(fileInfo, iconOptions);
+}
+
+QIconEngine * QXdgDesktopPortalTheme::createIconEngine(const QString &iconName) const
+{
+ Q_D(const QXdgDesktopPortalTheme);
+ return d->baseTheme->createIconEngine(iconName);
+}
+
+QList<QKeySequence> QXdgDesktopPortalTheme::keyBindings(QKeySequence::StandardKey key) const
+{
+ Q_D(const QXdgDesktopPortalTheme);
+ return d->baseTheme->keyBindings(key);
+}
+
+QString QXdgDesktopPortalTheme::standardButtonText(int button) const
+{
+ Q_D(const QXdgDesktopPortalTheme);
+ return d->baseTheme->standardButtonText(button);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.h b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.h
new file mode 100644
index 0000000000..b72e676419
--- /dev/null
+++ b/src/plugins/platformthemes/xdgdesktopportal/qxdgdesktopportaltheme.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXDGDESKTOPPORTALTHEME_H
+#define QXDGDESKTOPPORTALTHEME_H
+
+#include <qpa/qplatformtheme.h>
+
+QT_BEGIN_NAMESPACE
+
+class QXdgDesktopPortalThemePrivate;
+
+class QXdgDesktopPortalTheme : public QPlatformTheme
+{
+ Q_DECLARE_PRIVATE(QXdgDesktopPortalTheme)
+public:
+ QXdgDesktopPortalTheme();
+
+ QPlatformMenuItem *createPlatformMenuItem() const override;
+ QPlatformMenu *createPlatformMenu() const override;
+ QPlatformMenuBar *createPlatformMenuBar() const override;
+ void showPlatformMenuBar() override;
+
+ bool usePlatformNativeDialog(DialogType type) const override;
+ QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const override;
+
+#ifndef QT_NO_SYSTEMTRAYICON
+ QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const override;
+#endif
+
+ const QPalette *palette(Palette type = SystemPalette) const override;
+
+ const QFont *font(Font type = SystemFont) const override;
+
+ QVariant themeHint(ThemeHint hint) const override;
+
+ QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const override;
+ QIcon fileIcon(const QFileInfo &fileInfo,
+ QPlatformTheme::IconOptions iconOptions = 0) const override;
+
+ QIconEngine *createIconEngine(const QString &iconName) const override;
+
+ QList<QKeySequence> keyBindings(QKeySequence::StandardKey key) const override;
+
+ QString standardButtonText(int button) const override;
+
+private:
+ QScopedPointer<QXdgDesktopPortalThemePrivate> d_ptr;
+ Q_DISABLE_COPY(QXdgDesktopPortalTheme)
+};
+
+QT_END_NAMESPACE
+
+#endif // QXDGDESKTOPPORTALTHEME_H
diff --git a/src/plugins/platformthemes/xdgdesktopportal/xdgdesktopportal.json b/src/plugins/platformthemes/xdgdesktopportal/xdgdesktopportal.json
new file mode 100644
index 0000000000..c69062d9a1
--- /dev/null
+++ b/src/plugins/platformthemes/xdgdesktopportal/xdgdesktopportal.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "xdgdesktopportal", "flatpak", "snap" ]
+}
diff --git a/src/plugins/platformthemes/xdgdesktopportal/xdgdesktopportal.pro b/src/plugins/platformthemes/xdgdesktopportal/xdgdesktopportal.pro
new file mode 100644
index 0000000000..0a71484cf9
--- /dev/null
+++ b/src/plugins/platformthemes/xdgdesktopportal/xdgdesktopportal.pro
@@ -0,0 +1,17 @@
+TARGET = qxdgdesktopportal
+
+PLUGIN_TYPE = platformthemes
+PLUGIN_EXTENDS = -
+PLUGIN_CLASS_NAME = QXdgDesktopPortalThemePlugin
+load(qt_plugin)
+
+QT += core-private dbus gui-private theme_support-private
+
+HEADERS += \
+ qxdgdesktopportaltheme.h \
+ qxdgdesktopportalfiledialog_p.h
+
+SOURCES += \
+ main.cpp \
+ qxdgdesktopportaltheme.cpp \
+ qxdgdesktopportalfiledialog.cpp
diff --git a/src/plugins/printsupport/cups/qcupsprintengine.cpp b/src/plugins/printsupport/cups/qcupsprintengine.cpp
index 6c29a99705..c9683eb99d 100644
--- a/src/plugins/printsupport/cups/qcupsprintengine.cpp
+++ b/src/plugins/printsupport/cups/qcupsprintengine.cpp
@@ -104,7 +104,11 @@ void QCupsPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &v
break;
case PPK_QPageLayout: {
QPageLayout pageLayout = value.value<QPageLayout>();
- if (pageLayout.isValid() && (d->m_printDevice.isValidPageLayout(pageLayout, d->resolution) || d->m_printDevice.supportsCustomPageSizes())) {
+ if (pageLayout.isValid() && (d->m_printDevice.isValidPageLayout(pageLayout, d->resolution)
+ || d->m_printDevice.supportsCustomPageSizes()
+ || d->m_printDevice.supportedPageSizes().isEmpty())) {
+ // supportedPageSizes().isEmpty() because QPageSetupWidget::initPageSizes says
+ // "If no available printer page sizes, populate with all page sizes"
d->m_pageLayout = pageLayout;
d->setPageSize(pageLayout.pageSize());
}
@@ -132,6 +136,9 @@ QVariant QCupsPrintEngine::property(PrintEnginePropertyKey key) const
case PPK_CupsOptions:
ret = d->cupsOptions;
break;
+ case PPK_Duplex:
+ ret = d->duplex;
+ break;
default:
ret = QPdfPrintEngine::property(key);
break;
@@ -140,7 +147,9 @@ QVariant QCupsPrintEngine::property(PrintEnginePropertyKey key) const
}
-QCupsPrintEnginePrivate::QCupsPrintEnginePrivate(QPrinter::PrinterMode m) : QPdfPrintEnginePrivate(m)
+QCupsPrintEnginePrivate::QCupsPrintEnginePrivate(QPrinter::PrinterMode m)
+ : QPdfPrintEnginePrivate(m)
+ , duplex(QPrint::DuplexNone)
{
}
diff --git a/src/plugins/printsupport/cups/qcupsprintengine_p.h b/src/plugins/printsupport/cups/qcupsprintengine_p.h
index d5363bb8cc..2a1a83b9d7 100644
--- a/src/plugins/printsupport/cups/qcupsprintengine_p.h
+++ b/src/plugins/printsupport/cups/qcupsprintengine_p.h
@@ -99,6 +99,7 @@ private:
QPrintDevice m_printDevice;
QStringList cupsOptions;
QString cupsTempFile;
+ QPrint::DuplexMode duplex;
};
QT_END_NAMESPACE
diff --git a/src/plugins/printsupport/cups/qcupsprintersupport.cpp b/src/plugins/printsupport/cups/qcupsprintersupport.cpp
index a9c992a2e1..19e1df31f6 100644
--- a/src/plugins/printsupport/cups/qcupsprintersupport.cpp
+++ b/src/plugins/printsupport/cups/qcupsprintersupport.cpp
@@ -47,6 +47,15 @@
#include <QtPrintSupport/QPrinterInfo>
+#if QT_CONFIG(dialogbuttonbox)
+#include <QGuiApplication>
+#include <QDialog>
+#include <QDialogButtonBox>
+#include <QFormLayout>
+#include <QLabel>
+#include <QLineEdit>
+#endif // QT_CONFIG(dialogbuttonbox)
+
#include <cups/ppd.h>
#ifndef QT_LINUXBASE // LSB merges everything into cups.h
# include <cups/language.h>
@@ -54,9 +63,78 @@
QT_BEGIN_NAMESPACE
+#if QT_CONFIG(dialogbuttonbox)
+static const char *getPasswordCB(const char */*prompt*/, http_t *http, const char */*method*/, const char *resource, void */*user_data*/)
+{
+ // cups doesn't free the const char * we return so keep around
+ // the last password so we don't leak memory if called multiple times.
+ static QByteArray password;
+
+ // prompt is always "Password for %s on %s? " but we can't use it since we allow the user to change the user.
+ // That is fine because cups always calls cupsUser after calling this callback.
+ // We build our own prompt with the hostname (if not localhost) and the resource that is being used
+
+ char hostname[HTTP_MAX_HOST];
+ httpGetHostname(http, hostname, HTTP_MAX_HOST);
+
+ const QString username = QString::fromLocal8Bit(cupsUser());
+
+ QDialog dialog;
+ dialog.setWindowTitle(QCoreApplication::translate("QCupsPrinterSupport", "Authentication Needed"));
+
+ QFormLayout *layout = new QFormLayout(&dialog);
+ layout->setSizeConstraint(QLayout::SetFixedSize);
+
+ QLineEdit *usernameLE = new QLineEdit();
+ usernameLE->setText(username);
+
+ QLineEdit *passwordLE = new QLineEdit();
+ passwordLE->setEchoMode(QLineEdit::Password);
+
+ QString resourceString = QString::fromLocal8Bit(resource);
+ if (resourceString.startsWith(QStringLiteral("/printers/")))
+ resourceString = resourceString.mid(QStringLiteral("/printers/").length());
+
+ QLabel *label = new QLabel();
+ if (hostname == QStringLiteral("localhost")) {
+ label->setText(QCoreApplication::translate("QCupsPrinterSupport", "Authentication needed to use %1.").arg(resourceString));
+ } else {
+ label->setText(QCoreApplication::translate("QCupsPrinterSupport", "Authentication needed to use %1 on %2.").arg(resourceString).arg(hostname));
+ label->setWordWrap(true);
+ }
+
+ layout->addRow(label);
+ layout->addRow(new QLabel(QCoreApplication::translate("QCupsPrinterSupport", "Username:")), usernameLE);
+ layout->addRow(new QLabel(QCoreApplication::translate("QCupsPrinterSupport", "Password:")), passwordLE);
+
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+ layout->addRow(buttonBox);
+
+ QObject::connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
+ QObject::connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
+
+ passwordLE->setFocus();
+
+ if (dialog.exec() != QDialog::Accepted)
+ return nullptr;
+
+ if (usernameLE->text() != username)
+ cupsSetUser(usernameLE->text().toLocal8Bit().constData());
+
+ password = passwordLE->text().toLocal8Bit();
+
+ return password.constData();
+}
+#endif // QT_CONFIG(dialogbuttonbox)
+
QCupsPrinterSupport::QCupsPrinterSupport()
: QPlatformPrinterSupport()
{
+#if QT_CONFIG(dialogbuttonbox)
+ // Only show password dialog if GUI application
+ if (qobject_cast<QGuiApplication*>(QCoreApplication::instance()))
+ cupsSetPasswordCB2(getPasswordCB, nullptr /* user_data */ );
+#endif // QT_CONFIG(dialogbuttonbox)
}
QCupsPrinterSupport::~QCupsPrinterSupport()
diff --git a/src/plugins/printsupport/cups/qppdprintdevice.cpp b/src/plugins/printsupport/cups/qppdprintdevice.cpp
index f0a8105d21..51b93a0016 100644
--- a/src/plugins/printsupport/cups/qppdprintdevice.cpp
+++ b/src/plugins/printsupport/cups/qppdprintdevice.cpp
@@ -50,13 +50,6 @@
QT_BEGIN_NAMESPACE
-QPpdPrintDevice::QPpdPrintDevice()
- : QPlatformPrintDevice(),
- m_cupsDest(0),
- m_ppd(0)
-{
-}
-
QPpdPrintDevice::QPpdPrintDevice(const QString &id)
: QPlatformPrintDevice(id),
m_cupsDest(0),
@@ -69,9 +62,26 @@ QPpdPrintDevice::QPpdPrintDevice(const QString &id)
m_cupsName = parts.at(0).toUtf8();
if (parts.size() > 1)
m_cupsInstance = parts.at(1).toUtf8();
- loadPrinter();
- if (m_cupsDest && m_ppd) {
+ // Get the print instance and PPD file
+ m_cupsDest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, m_cupsName, m_cupsInstance.isNull() ? nullptr : m_cupsInstance.constData());
+ if (m_cupsDest) {
+ const char *ppdFile = cupsGetPPD(m_cupsName);
+ if (ppdFile) {
+ m_ppd = ppdOpenFile(ppdFile);
+ unlink(ppdFile);
+ }
+ if (m_ppd) {
+ ppdMarkDefaults(m_ppd);
+ cupsMarkOptions(m_ppd, m_cupsDest->num_options, m_cupsDest->options);
+ ppdLocalize(m_ppd);
+
+ m_minimumPhysicalPageSize = QSize(m_ppd->custom_min[0], m_ppd->custom_min[1]);
+ m_maximumPhysicalPageSize = QSize(m_ppd->custom_max[0], m_ppd->custom_max[1]);
+ m_customMargins = QMarginsF(m_ppd->custom_margins[0], m_ppd->custom_margins[3],
+ m_ppd->custom_margins[2], m_ppd->custom_margins[1]);
+ }
+
m_name = printerOption("printer-info");
m_location = printerOption("printer-location");
m_makeAndModel = printerOption("printer-make-and-model");
@@ -87,10 +97,6 @@ QPpdPrintDevice::QPpdPrintDevice(const QString &id)
// Cups ppd_file_t variable_sizes custom_min custom_max
// PPD MaxMediaWidth MaxMediaHeight
m_supportsCustomPageSizes = type & CUPS_PRINTER_VARIABLE;
- m_minimumPhysicalPageSize = QSize(m_ppd->custom_min[0], m_ppd->custom_min[1]);
- m_maximumPhysicalPageSize = QSize(m_ppd->custom_max[0], m_ppd->custom_max[1]);
- m_customMargins = QMarginsF(m_ppd->custom_margins[0], m_ppd->custom_margins[3],
- m_ppd->custom_margins[2], m_ppd->custom_margins[1]);
}
}
}
@@ -107,7 +113,7 @@ QPpdPrintDevice::~QPpdPrintDevice()
bool QPpdPrintDevice::isValid() const
{
- return m_cupsDest && m_ppd;
+ return m_cupsDest;
}
bool QPpdPrintDevice::isDefault() const
@@ -152,8 +158,8 @@ void QPpdPrintDevice::loadPageSizes() const
}
}
}
- m_havePageSizes = true;
}
+ m_havePageSizes = true;
}
QPageSize QPpdPrintDevice::defaultPageSize() const
@@ -359,14 +365,18 @@ void QPpdPrintDevice::loadDuplexModes() const
ppd_option_t *duplexModes = ppdFindOption(m_ppd, "Duplex");
if (duplexModes) {
m_duplexModes.reserve(duplexModes->num_choices);
- for (int i = 0; i < duplexModes->num_choices; ++i)
- m_duplexModes.append(QPrintUtils::ppdChoiceToDuplexMode(duplexModes->choices[i].choice));
+ for (int i = 0; i < duplexModes->num_choices; ++i) {
+ if (ppdInstallableConflict(m_ppd, duplexModes->keyword, duplexModes->choices[i].choice) == 0) {
+ m_duplexModes.append(QPrintUtils::ppdChoiceToDuplexMode(duplexModes->choices[i].choice));
+ }
+ }
}
// If no result, try just the default
if (m_duplexModes.size() == 0) {
duplexModes = ppdFindOption(m_ppd, "DefaultDuplex");
- if (duplexModes)
+ if (duplexModes && (ppdInstallableConflict(m_ppd, duplexModes->keyword, duplexModes->choices[0].choice) == 0)) {
m_duplexModes.append(QPrintUtils::ppdChoiceToDuplexMode(duplexModes->choices[0].choice));
+ }
}
}
// If still no result, or not added in PPD, then add None
@@ -417,7 +427,7 @@ QPrint::ColorMode QPpdPrintDevice::defaultColorMode() const
ppd_option_t *colorModel = ppdFindOption(m_ppd, "DefaultColorModel");
if (!colorModel)
colorModel = ppdFindOption(m_ppd, "ColorModel");
- if (!colorModel || (colorModel && !qstrcmp(colorModel->defchoice, "Gray")))
+ if (!colorModel || qstrcmp(colorModel->defchoice, "Gray") != 0)
return QPrint::Color;
}
return QPrint::GrayScale;
@@ -481,38 +491,6 @@ void QPpdPrintDevice::loadMimeTypes() const
}
#endif
-void QPpdPrintDevice::loadPrinter()
-{
- // Just to be safe, check if existing printer needs closing
- if (m_ppd) {
- ppdClose(m_ppd);
- m_ppd = 0;
- }
- if (m_cupsDest) {
- cupsFreeDests(1, m_cupsDest);
- m_cupsDest = 0;
- }
-
- // Get the print instance and PPD file
- m_cupsDest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, m_cupsName, m_cupsInstance.isNull() ? nullptr : m_cupsInstance.constData());
- if (m_cupsDest) {
- const char *ppdFile = cupsGetPPD(m_cupsName);
- if (ppdFile) {
- m_ppd = ppdOpenFile(ppdFile);
- unlink(ppdFile);
- }
- if (m_ppd) {
- ppdMarkDefaults(m_ppd);
- cupsMarkOptions(m_ppd, m_cupsDest->num_options, m_cupsDest->options);
- ppdLocalize(m_ppd);
- } else {
- cupsFreeDests(1, m_cupsDest);
- m_cupsDest = 0;
- m_ppd = 0;
- }
- }
-}
-
QString QPpdPrintDevice::printerOption(const QString &key) const
{
return cupsGetOption(key.toUtf8(), m_cupsDest->num_options, m_cupsDest->options);
diff --git a/src/plugins/printsupport/cups/qppdprintdevice.h b/src/plugins/printsupport/cups/qppdprintdevice.h
index 596f9aa3f5..3baf8b771b 100644
--- a/src/plugins/printsupport/cups/qppdprintdevice.h
+++ b/src/plugins/printsupport/cups/qppdprintdevice.h
@@ -65,7 +65,6 @@ QT_BEGIN_NAMESPACE
class QPpdPrintDevice : public QPlatformPrintDevice
{
public:
- QPpdPrintDevice();
explicit QPpdPrintDevice(const QString &id);
virtual ~QPpdPrintDevice();
@@ -105,7 +104,6 @@ protected:
#endif
private:
- void loadPrinter();
QString printerOption(const QString &key) const;
cups_ptype_e printerTypeFlags() const;
diff --git a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp
index b1589c0738..f01e93d611 100644
--- a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp
+++ b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2014 John Layt <jlayt@kde.org>
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -49,6 +49,8 @@
QT_BEGIN_NAMESPACE
QT_WARNING_DISABLE_GCC("-Wsign-compare")
+typedef QVector<QWindowsPrinterInfo> WindowsPrinterLookup;
+Q_GLOBAL_STATIC(WindowsPrinterLookup, windowsDeviceLookup);
extern qreal qt_pointMultiplier(QPageLayout::Unit unit);
@@ -110,7 +112,7 @@ QWindowsPrintDevice::QWindowsPrintDevice(const QString &id)
{
// First do a fast lookup to see if printer exists, if it does then open it
if (!id.isEmpty() && QWindowsPrintDevice::availablePrintDeviceIds().contains(id)) {
- if (OpenPrinter((LPWSTR)m_id.utf16(), &m_hPrinter, NULL)) {
+ if (OpenPrinter(const_cast<LPWSTR>(wcharId()), &m_hPrinter, nullptr)) {
DWORD needed = 0;
GetPrinter(m_hPrinter, 2, 0, 0, &needed);
QScopedArrayPointer<BYTE> buffer(new BYTE[needed]);
@@ -121,15 +123,39 @@ QWindowsPrintDevice::QWindowsPrintDevice(const QString &id)
m_makeAndModel = QString::fromWCharArray(info->pDriverName); // TODO Check is not available elsewhere
m_isRemote = info->Attributes & PRINTER_ATTRIBUTE_NETWORK;
}
- m_supportsMultipleCopies = (DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_COPIES, NULL, NULL) > 1);
- m_supportsCollateCopies = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_COLLATE, NULL, NULL);
- // Min/Max custom size is in tenths of a millimeter
- const qreal multiplier = qt_pointMultiplier(QPageLayout::Millimeter);
- DWORD min = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_MINEXTENT, NULL, NULL);
- m_minimumPhysicalPageSize = QSize((LOWORD(min) / 10.0) * multiplier, (HIWORD(min) / 10.0) * multiplier);
- DWORD max = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_MAXEXTENT, NULL, NULL);
- m_maximumPhysicalPageSize = QSize((LOWORD(max) / 10.0) * multiplier, (HIWORD(max) / 10.0) * multiplier);
- m_supportsCustomPageSizes = (m_maximumPhysicalPageSize.width() > 0 && m_maximumPhysicalPageSize.height() > 0);
+ QWindowsPrinterInfo m_info;
+ m_info.m_id = m_id;
+ m_info.m_name = m_name;
+ m_info.m_location = m_location;
+ m_info.m_makeAndModel = m_makeAndModel;
+ m_info.m_isRemote = m_isRemote;
+ m_infoIndex = windowsDeviceLookup()->indexOf(m_info);
+ if (m_infoIndex != -1) {
+ m_info = windowsDeviceLookup()->at(m_infoIndex);
+ m_havePageSizes = m_info.m_havePageSizes;
+ m_pageSizes = m_info.m_pageSizes;
+ m_haveResolutions = m_info.m_haveResolutions;
+ m_resolutions = m_info.m_resolutions;
+ m_haveCopies = m_info.m_haveCopies;
+ m_supportsMultipleCopies = m_info.m_supportsMultipleCopies;
+ m_supportsCollateCopies = m_info.m_supportsCollateCopies;
+ m_haveMinMaxPageSizes = m_info.m_haveMinMaxPageSizes;
+ m_minimumPhysicalPageSize = m_info.m_minimumPhysicalPageSize;
+ m_maximumPhysicalPageSize = m_info.m_maximumPhysicalPageSize;
+ m_supportsCustomPageSizes = m_info.m_supportsCustomPageSizes;
+ m_haveInputSlots = m_info.m_haveInputSlots;
+ m_inputSlots = m_info.m_inputSlots;
+ m_haveOutputBins = m_info.m_haveOutputBins;
+ m_outputBins = m_info.m_outputBins;
+ m_haveDuplexModes = m_info.m_haveDuplexModes;
+ m_duplexModes = m_info.m_duplexModes;
+ m_haveColorModes = m_info.m_haveColorModes;
+ m_colorModes = m_info.m_colorModes;
+ m_infoIndex = windowsDeviceLookup()->indexOf(m_info);
+ } else {
+ windowsDeviceLookup()->append(m_info);
+ m_infoIndex = windowsDeviceLookup()->count() - 1;
+ }
}
}
}
@@ -184,7 +210,7 @@ void QWindowsPrintDevice::loadPageSizes() const
&& DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_PAPERS, NULL, NULL) == paperCount) {
QScopedArrayPointer<wchar_t> paperNames(new wchar_t[paperCount*64]);
- QScopedArrayPointer<POINT> winSizes(new POINT[paperCount*sizeof(POINT)]);
+ QScopedArrayPointer<POINT> winSizes(new POINT[paperCount]);
QScopedArrayPointer<wchar_t> papers(new wchar_t[paperCount]);
// Get the details and match the default paper size
@@ -205,6 +231,9 @@ void QWindowsPrintDevice::loadPageSizes() const
}
m_havePageSizes = true;
+ QWindowsPrinterInfo *info = windowsDeviceLookup()->data();
+ info[m_infoIndex].m_havePageSizes = true;
+ info[m_infoIndex].m_pageSizes = m_pageSizes;
}
QPageSize QWindowsPrintDevice::defaultPageSize() const
@@ -297,6 +326,9 @@ void QWindowsPrintDevice::loadResolutions() const
}
}
m_haveResolutions = true;
+ QWindowsPrinterInfo *info = windowsDeviceLookup()->data();
+ info[m_infoIndex].m_haveResolutions = true;
+ info[m_infoIndex].m_resolutions = m_resolutions;
}
int QWindowsPrintDevice::defaultResolution() const
@@ -319,16 +351,19 @@ int QWindowsPrintDevice::defaultResolution() const
void QWindowsPrintDevice::loadInputSlots() const
{
- DWORD binCount = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_BINS, NULL, NULL);
+ const auto printerId = wcharId();
+ DWORD binCount = DeviceCapabilities(printerId, nullptr, DC_BINS, nullptr, nullptr);
if (int(binCount) > 0
- && DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_BINNAMES, NULL, NULL) == binCount) {
+ && DeviceCapabilities(printerId, nullptr, DC_BINNAMES, nullptr, nullptr) == binCount) {
- QScopedArrayPointer<WORD> bins(new WORD[binCount*sizeof(WORD)]);
+ QScopedArrayPointer<WORD> bins(new WORD[binCount]);
QScopedArrayPointer<wchar_t> binNames(new wchar_t[binCount*24]);
// Get the details and match the default paper size
- if (DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_BINS, (LPWSTR)bins.data(), NULL) == binCount
- && DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_BINNAMES, binNames.data(), NULL) == binCount) {
+ if (DeviceCapabilities(printerId, nullptr, DC_BINS,
+ reinterpret_cast<LPWSTR>(bins.data()), nullptr) == binCount
+ && DeviceCapabilities(printerId, nullptr, DC_BINNAMES, binNames.data(),
+ nullptr) == binCount) {
for (int i = 0; i < int(binCount); ++i) {
wchar_t *binName = binNames.data() + (i * 24);
@@ -340,6 +375,9 @@ void QWindowsPrintDevice::loadInputSlots() const
}
m_haveInputSlots = true;
+ QWindowsPrinterInfo *info = windowsDeviceLookup()->data();
+ info[m_infoIndex].m_haveInputSlots = true;
+ info[m_infoIndex].m_inputSlots = m_inputSlots;
}
QPrint::InputSlot QWindowsPrintDevice::defaultInputSlot() const
@@ -367,12 +405,15 @@ void QWindowsPrintDevice::loadOutputBins() const
{
m_outputBins.append(QPlatformPrintDevice::defaultOutputBin());
m_haveOutputBins = true;
+ QWindowsPrinterInfo *info = windowsDeviceLookup()->data();
+ info[m_infoIndex].m_haveOutputBins = true;
+ info[m_infoIndex].m_outputBins = m_outputBins;
}
void QWindowsPrintDevice::loadDuplexModes() const
{
m_duplexModes.append(QPrint::DuplexNone);
- DWORD duplex = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_DUPLEX, NULL, NULL);
+ DWORD duplex = DeviceCapabilities(wcharId(), nullptr, DC_DUPLEX, nullptr, nullptr);
if (int(duplex) == 1) {
// TODO Assume if duplex flag supports both modes
m_duplexModes.append(QPrint::DuplexAuto);
@@ -380,6 +421,9 @@ void QWindowsPrintDevice::loadDuplexModes() const
m_duplexModes.append(QPrint::DuplexShortSide);
}
m_haveDuplexModes = true;
+ QWindowsPrinterInfo *info = windowsDeviceLookup()->data();
+ info[m_infoIndex].m_haveDuplexModes = true;
+ info[m_infoIndex].m_duplexModes = m_duplexModes;
}
QPrint::DuplexMode QWindowsPrintDevice::defaultDuplexMode() const
@@ -403,10 +447,13 @@ QPrint::DuplexMode QWindowsPrintDevice::defaultDuplexMode() const
void QWindowsPrintDevice::loadColorModes() const
{
m_colorModes.append(QPrint::GrayScale);
- DWORD color = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_COLORDEVICE, NULL, NULL);
+ DWORD color = DeviceCapabilities(wcharId(), nullptr, DC_COLORDEVICE, nullptr, nullptr);
if (int(color) == 1)
m_colorModes.append(QPrint::Color);
m_haveColorModes = true;
+ QWindowsPrinterInfo *info = windowsDeviceLookup()->data();
+ info[m_infoIndex].m_haveColorModes = true;
+ info[m_infoIndex].m_colorModes = m_colorModes;
}
QPrint::ColorMode QWindowsPrintDevice::defaultColorMode() const
@@ -457,4 +504,68 @@ QString QWindowsPrintDevice::defaultPrintDeviceId()
return QString::fromWCharArray(name.data());
}
+void QWindowsPrintDevice::loadCopiesSupport() const
+{
+ auto printerId = wcharId();
+ m_supportsMultipleCopies = (DeviceCapabilities(printerId, NULL, DC_COPIES, NULL, NULL) > 1);
+ m_supportsCollateCopies = DeviceCapabilities(printerId, NULL, DC_COLLATE, NULL, NULL);
+ m_haveCopies = true;
+ QWindowsPrinterInfo *info = windowsDeviceLookup()->data();
+ info[m_infoIndex].m_haveCopies = true;
+ info[m_infoIndex].m_supportsMultipleCopies = m_supportsMultipleCopies;
+ info[m_infoIndex].m_supportsCollateCopies = m_supportsCollateCopies;
+}
+
+bool QWindowsPrintDevice::supportsCollateCopies() const
+{
+ if (!m_haveCopies)
+ loadCopiesSupport();
+ return m_supportsCollateCopies;
+}
+
+bool QWindowsPrintDevice::supportsMultipleCopies() const
+{
+ if (!m_haveCopies)
+ loadCopiesSupport();
+ return m_supportsMultipleCopies;
+}
+
+bool QWindowsPrintDevice::supportsCustomPageSizes() const
+{
+ if (!m_haveMinMaxPageSizes)
+ loadMinMaxPageSizes();
+ return m_supportsCustomPageSizes;
+}
+
+QSize QWindowsPrintDevice::minimumPhysicalPageSize() const
+{
+ if (!m_haveMinMaxPageSizes)
+ loadMinMaxPageSizes();
+ return m_minimumPhysicalPageSize;
+}
+
+QSize QWindowsPrintDevice::maximumPhysicalPageSize() const
+{
+ if (!m_haveMinMaxPageSizes)
+ loadMinMaxPageSizes();
+ return m_maximumPhysicalPageSize;
+}
+
+void QWindowsPrintDevice::loadMinMaxPageSizes() const
+{
+ // Min/Max custom size is in tenths of a millimeter
+ const qreal multiplier = qt_pointMultiplier(QPageLayout::Millimeter);
+ auto printerId = wcharId();
+ DWORD min = DeviceCapabilities(printerId, NULL, DC_MINEXTENT, NULL, NULL);
+ m_minimumPhysicalPageSize = QSize((LOWORD(min) / 10.0) * multiplier, (HIWORD(min) / 10.0) * multiplier);
+ DWORD max = DeviceCapabilities(printerId, NULL, DC_MAXEXTENT, NULL, NULL);
+ m_maximumPhysicalPageSize = QSize((LOWORD(max) / 10.0) * multiplier, (HIWORD(max) / 10.0) * multiplier);
+ m_supportsCustomPageSizes = (m_maximumPhysicalPageSize.width() > 0 && m_maximumPhysicalPageSize.height() > 0);
+ m_haveMinMaxPageSizes = true;
+ QWindowsPrinterInfo *info = windowsDeviceLookup()->data();
+ info[m_infoIndex].m_haveCopies = true;
+ info[m_infoIndex].m_supportsMultipleCopies = m_supportsMultipleCopies;
+ info[m_infoIndex].m_supportsCollateCopies = m_supportsCollateCopies;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/printsupport/windows/qwindowsprintdevice.h b/src/plugins/printsupport/windows/qwindowsprintdevice.h
index 6b51ee8785..166f0f65b2 100644
--- a/src/plugins/printsupport/windows/qwindowsprintdevice.h
+++ b/src/plugins/printsupport/windows/qwindowsprintdevice.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2014 John Layt <jlayt@kde.org>
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -57,6 +58,43 @@
QT_BEGIN_NAMESPACE
+class QWindowsPrinterInfo
+{
+public:
+ bool operator==(const QWindowsPrinterInfo &other) const
+ {
+ // We only need to check if these are the same for matching up
+ return m_id == other.m_id && m_name == other.m_name &&
+ m_location == other.m_location &&
+ m_makeAndModel == other.m_makeAndModel &&
+ m_isRemote == other.m_isRemote;
+ }
+ QString m_id;
+ QString m_name;
+ QString m_location;
+ QString m_makeAndModel;
+ QList<QPageSize> m_pageSizes;
+ QList<int> m_resolutions;
+ QVector<QPrint::InputSlot> m_inputSlots;
+ QVector<QPrint::OutputBin> m_outputBins;
+ QVector<QPrint::DuplexMode> m_duplexModes;
+ QVector<QPrint::ColorMode> m_colorModes;
+ QSize m_minimumPhysicalPageSize;
+ QSize m_maximumPhysicalPageSize;
+ bool m_isRemote = false;
+ bool m_havePageSizes = false;
+ bool m_haveResolutions = false;
+ bool m_haveCopies = false;
+ bool m_supportsMultipleCopies = false;
+ bool m_supportsCollateCopies = false;
+ bool m_haveMinMaxPageSizes = false;
+ bool m_supportsCustomPageSizes = false;
+ bool m_haveInputSlots = false;
+ bool m_haveOutputBins = false;
+ bool m_haveDuplexModes = false;
+ bool m_haveColorModes = false;
+};
+
class QWindowsPrintDevice : public QPlatformPrintDevice
{
public:
@@ -85,6 +123,12 @@ public:
static QStringList availablePrintDeviceIds();
static QString defaultPrintDeviceId();
+ bool supportsCollateCopies() const override;
+ bool supportsMultipleCopies() const override;
+ bool supportsCustomPageSizes() const override;
+ QSize minimumPhysicalPageSize() const override;
+ QSize maximumPhysicalPageSize() const override;
+
protected:
void loadPageSizes() const override;
void loadResolutions() const override;
@@ -92,9 +136,16 @@ protected:
void loadOutputBins() const override;
void loadDuplexModes() const override;
void loadColorModes() const override;
+ void loadCopiesSupport() const;
+ void loadMinMaxPageSizes() const;
private:
+ LPCWSTR wcharId() const { return reinterpret_cast<LPCWSTR>(m_id.utf16()); }
+
HANDLE m_hPrinter;
+ mutable bool m_haveCopies;
+ mutable bool m_haveMinMaxPageSizes;
+ int m_infoIndex;
};
QT_END_NAMESPACE
diff --git a/src/plugins/printsupport/windows/qwindowsprintersupport.h b/src/plugins/printsupport/windows/qwindowsprintersupport.h
index c42e7aa551..4267701145 100644
--- a/src/plugins/printsupport/windows/qwindowsprintersupport.h
+++ b/src/plugins/printsupport/windows/qwindowsprintersupport.h
@@ -46,9 +46,10 @@ QT_BEGIN_NAMESPACE
class QWindowsPrinterSupport : public QPlatformPrinterSupport
{
+ Q_DISABLE_COPY(QWindowsPrinterSupport)
public:
QWindowsPrinterSupport();
- ~QWindowsPrinterSupport();
+ ~QWindowsPrinterSupport() override;
QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode, const QString &deviceId = QString()) override;
QPaintEngine *createPaintEngine(QPrintEngine *printEngine, QPrinter::PrinterMode) override;
diff --git a/src/plugins/sqldrivers/configure.json b/src/plugins/sqldrivers/configure.json
index 234f880579..4802d3b04d 100644
--- a/src/plugins/sqldrivers/configure.json
+++ b/src/plugins/sqldrivers/configure.json
@@ -229,7 +229,7 @@ Oracle driver, as the current build will most likely fail."
"summary": [
{
- "section": "Qt Sql",
+ "section": "Qt Sql Drivers",
"entries": [
"sql-db2", "sql-ibase", "sql-mysql", "sql-oci", "sql-odbc", "sql-psql",
"sql-sqlite2", "sql-sqlite", "system-sqlite", "sql-tds"
diff --git a/src/plugins/sqldrivers/configure.pri b/src/plugins/sqldrivers/configure.pri
index b69b51b679..24954e9514 100644
--- a/src/plugins/sqldrivers/configure.pri
+++ b/src/plugins/sqldrivers/configure.pri
@@ -19,9 +19,9 @@ defineTest(qtConfLibrary_psqlConfig) {
libs =
!isEmpty(libdir): libs += "-L$$libdir"
libs += "-lpq"
- $${1}.libs = "$$val_escape(libs)"
+ $${1}.libs = $$libs
includedir -= $$QMAKE_DEFAULT_INCDIRS
- $${1}.includedir = "$$val_escape(includedir)"
+ $${1}.includedir = $$includedir
export($${1}.libs)
export($${1}.includedir)
return(true)
@@ -34,7 +34,7 @@ defineTest(qtConfLibrary_psqlEnv) {
# Respect PSQL_LIBS if set
PSQL_LIBS = $$getenv(PSQL_LIBS)
!isEmpty(PSQL_LIBS) {
- $${1}.libs = $$PSQL_LIBS
+ eval($${1}.libs = $$PSQL_LIBS)
export($${1}.libs)
} else {
!qtConfLibrary_inline($$1, $$2): \
@@ -69,14 +69,14 @@ defineTest(qtConfLibrary_mysqlConfig) {
}
libs = $$cleanlibs
}
- $${1}.libs = "$$val_escape(libs)"
+ $${1}.libs = $$libs
eval(rawincludedir = $$includedir)
rawincludedir ~= s/^-I//g
includedir =
for (id, rawincludedir): \
includedir += $$clean_path($$id)
includedir -= $$QMAKE_DEFAULT_INCDIRS
- $${1}.includedir = "$$val_escape(includedir)"
+ $${1}.includedir = $$includedir
export($${1}.libs)
export($${1}.includedir)
return(true)
@@ -90,9 +90,9 @@ defineTest(qtConfLibrary_sybaseEnv) {
sybase = $$getenv(SYBASE)
!isEmpty(sybase): \
libs += "-L$${sybase}/lib"
- libs += $$getenv(SYBASE_LIBS)
+ eval(libs += $$getenv(SYBASE_LIBS))
!isEmpty(libs) {
- $${1}.libs = "$$val_escape(libs)"
+ $${1}.libs = $$libs
export($${1}.libs)
}
return(true)
diff --git a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
index 5a100b8075..58da2a3c51 100644
--- a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
+++ b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
@@ -74,6 +74,10 @@ Q_DECLARE_METATYPE(MYSQL_STMT*)
# define Q_CLIENT_MULTI_STATEMENTS 0
#endif
+// MySQL above version 8 removed my_bool typedef while MariaDB kept it,
+// by redefining it we can regain source compatibility.
+using my_bool = decltype(mysql_stmt_bind_result(nullptr, nullptr));
+
QT_BEGIN_NAMESPACE
class QMYSQLDriverPrivate : public QSqlDriverPrivate
@@ -305,7 +309,9 @@ static QVariant::Type qDecodeMYSQLType(int mysqltype, uint flags)
type = QVariant::Date;
break;
case FIELD_TYPE_TIME :
- type = QVariant::Time;
+ // A time field can be within the range '-838:59:59' to '838:59:59' so
+ // use QString instead of QTime since QTime is limited to 24 hour clock
+ type = QVariant::String;
break;
case FIELD_TYPE_DATETIME :
case FIELD_TYPE_TIMESTAMP :
@@ -1448,7 +1454,7 @@ bool QMYSQLDriver::open(const QString& db,
d->preparedQuerysEnabled = false;
#endif
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
mysql_thread_init();
#endif
@@ -1462,7 +1468,7 @@ void QMYSQLDriver::close()
{
Q_D(QMYSQLDriver);
if (isOpen()) {
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
mysql_thread_end();
#endif
mysql_close(d->mysql);
diff --git a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
index 547eb2043d..1fbbcd0ef1 100644
--- a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
+++ b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
@@ -72,6 +72,7 @@ inline static QString fromSQLTCHAR(const QVarLengthArray<SQLTCHAR>& input, int s
{
QString result;
+ // Remove any trailing \0 as some drivers misguidedly append one
int realsize = qMin(size, input.size());
if(realsize > 0 && input[realsize-1] == 0)
realsize--;
@@ -458,7 +459,6 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool uni
// more data can be fetched, the length indicator does NOT
// contain the number of bytes returned - it contains the
// total number of bytes that CAN be fetched
- // colSize-1: remove 0 termination when there is more data to fetch
int rSize = (r == SQL_SUCCESS_WITH_INFO) ? colSize : int(lengthIndicator / sizeof(SQLTCHAR));
fieldVal += fromSQLTCHAR(buf, rSize);
if (lengthIndicator < SQLLEN(colSize*sizeof(SQLTCHAR))) {
@@ -499,9 +499,12 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool uni
// more data can be fetched, the length indicator does NOT
// contain the number of bytes returned - it contains the
// total number of bytes that CAN be fetched
- // colSize-1: remove 0 termination when there is more data to fetch
int rSize = (r == SQL_SUCCESS_WITH_INFO) ? colSize : lengthIndicator;
- fieldVal += QString::fromUtf8((const char *)buf.constData(), rSize);
+ // Remove any trailing \0 as some drivers misguidedly append one
+ int realsize = qMin(rSize, buf.size());
+ if (realsize > 0 && buf[realsize - 1] == 0)
+ realsize--;
+ fieldVal += QString::fromUtf8(reinterpret_cast<const char *>(buf.constData()), realsize);
if (lengthIndicator < SQLLEN(colSize)) {
// workaround for Drivermanagers that don't return SQL_NO_DATA
break;
@@ -1304,7 +1307,7 @@ QVariant QODBCResult::data(int field)
bool QODBCResult::isNull(int field)
{
Q_D(const QODBCResult);
- if (field < 0 || field > d->fieldCache.size())
+ if (field < 0 || field >= d->fieldCache.size())
return true;
if (field <= d->fieldCacheIdx) {
// since there is no good way to find out whether the value is NULL
diff --git a/src/plugins/sqldrivers/psql/qsql_psql.cpp b/src/plugins/sqldrivers/psql/qsql_psql.cpp
index fe9e098c12..bf0493b0c3 100644
--- a/src/plugins/sqldrivers/psql/qsql_psql.cpp
+++ b/src/plugins/sqldrivers/psql/qsql_psql.cpp
@@ -1465,8 +1465,11 @@ QSqlRecord QPSQLDriver::record(const QString& tablename) const
precision = -1;
}
QString defVal = query.value(5).toString();
- if (!defVal.isEmpty() && defVal.at(0) == QLatin1Char('\''))
- defVal = defVal.mid(1, defVal.length() - 2);
+ if (!defVal.isEmpty() && defVal.at(0) == QLatin1Char('\'')) {
+ const int end = defVal.lastIndexOf(QLatin1Char('\''));
+ if (end > 0)
+ defVal = defVal.mid(1, end - 1);
+ }
QSqlField f(query.value(0).toString(), qDecodePSQLType(query.value(1).toInt()), tablename);
f.setRequired(query.value(2).toBool());
f.setLength(len);
diff --git a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp
index 491d903137..f1a003ddcd 100644
--- a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp
+++ b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp
@@ -55,9 +55,6 @@
#include <qcache.h>
#include <qregularexpression.h>
#endif
-#if QT_CONFIG(timezone)
-#include <QTimeZone>
-#endif
#include <QScopedValueRollback>
#if defined Q_OS_WIN
@@ -421,34 +418,6 @@ bool QSQLiteResult::prepare(const QString &query)
return true;
}
-static QString secondsToOffset(int seconds)
-{
- const QChar sign = ushort(seconds < 0 ? '-' : '+');
- seconds = qAbs(seconds);
- const int hours = seconds / 3600;
- const int minutes = (seconds % 3600) / 60;
-
- return QString(QStringLiteral("%1%2:%3")).arg(sign).arg(hours, 2, 10, QLatin1Char('0')).arg(minutes, 2, 10, QLatin1Char('0'));
-}
-
-static QString timespecToString(const QDateTime &dateTime)
-{
- switch (dateTime.timeSpec()) {
- case Qt::LocalTime:
- return QString();
- case Qt::UTC:
- return QStringLiteral("Z");
- case Qt::OffsetFromUTC:
- return secondsToOffset(dateTime.offsetFromUtc());
-#if QT_CONFIG(timezone)
- case Qt::TimeZone:
- return secondsToOffset(dateTime.timeZone().offsetFromUtc(dateTime));
-#endif
- default:
- return QString();
- }
-}
-
bool QSQLiteResult::execBatch(bool arrayBind)
{
Q_UNUSED(arrayBind);
@@ -555,7 +524,7 @@ bool QSQLiteResult::exec()
break;
case QVariant::DateTime: {
const QDateTime dateTime = value.toDateTime();
- const QString str = dateTime.toString(QLatin1String("yyyy-MM-ddThh:mm:ss.zzz") + timespecToString(dateTime));
+ const QString str = dateTime.toString(Qt::ISODateWithMs);
res = sqlite3_bind_text16(d->stmt, i + 1, str.utf16(),
str.size() * sizeof(ushort), SQLITE_TRANSIENT);
break;
@@ -673,7 +642,7 @@ static void _q_regexp(sqlite3_context* context, int argc, sqlite3_value** argv)
const bool wasCached = regexp;
if (!wasCached)
- regexp = new QRegularExpression(pattern, QRegularExpression::DontCaptureOption | QRegularExpression::OptimizeOnFirstUsageOption);
+ regexp = new QRegularExpression(pattern, QRegularExpression::DontCaptureOption);
const bool found = subject.contains(*regexp);
@@ -953,13 +922,20 @@ static QSqlIndex qGetTableInfo(QSqlQuery &q, const QString &tableName, bool only
if (onlyPIndex && !isPk)
continue;
QString typeName = q.value(2).toString().toLower();
+ QString defVal = q.value(4).toString();
+ if (!defVal.isEmpty() && defVal.at(0) == QLatin1Char('\'')) {
+ const int end = defVal.lastIndexOf(QLatin1Char('\''));
+ if (end > 0)
+ defVal = defVal.mid(1, end - 1);
+ }
+
QSqlField fld(q.value(1).toString(), qGetColumnType(typeName), tableName);
if (isPk && (typeName == QLatin1String("integer")))
// INTEGER PRIMARY KEY fields are auto-generated in sqlite
// INT PRIMARY KEY is not the same as INTEGER PRIMARY KEY!
fld.setAutoValue(true);
fld.setRequired(q.value(3).toInt() != 0);
- fld.setDefaultValue(q.value(4));
+ fld.setDefaultValue(defVal);
ind.append(fld);
}
return ind;
diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm
index 3405f01046..94d048ca7e 100644
--- a/src/plugins/styles/mac/qmacstyle_mac.mm
+++ b/src/plugins/styles/mac/qmacstyle_mac.mm
@@ -143,22 +143,12 @@ static QWindow *qt_getWindow(const QWidget *widget)
return widget ? widget->window()->windowHandle() : 0;
}
-@interface QT_MANGLE_NAMESPACE(NotificationReceiver) : NSObject {
-QMacStylePrivate *mPrivate;
-}
-- (id)initWithPrivate:(QMacStylePrivate *)priv;
-- (void)scrollBarStyleDidChange:(NSNotification *)notification;
+@interface QT_MANGLE_NAMESPACE(NotificationReceiver) : NSObject
@end
QT_NAMESPACE_ALIAS_OBJC_CLASS(NotificationReceiver);
@implementation NotificationReceiver
-- (id)initWithPrivate:(QMacStylePrivate *)priv
-{
- self = [super init];
- mPrivate = priv;
- return self;
-}
- (void)scrollBarStyleDidChange:(NSNotification *)notification
{
@@ -248,6 +238,33 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QVerticalSplitView);
}
@end
+// See render code in drawPrimitive(PE_FrameTabWidget)
+@interface QT_MANGLE_NAMESPACE(QDarkNSBox) : NSBox
+@end
+
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QDarkNSBox);
+
+@implementation QDarkNSBox
+- (instancetype)init
+{
+ if ((self = [super init])) {
+ self.title = @"";
+ self.titlePosition = NSNoTitle;
+ self.boxType = NSBoxCustom;
+ self.cornerRadius = 3;
+ self.borderColor = [NSColor.controlColor colorWithAlphaComponent:0.1];
+ self.fillColor = [NSColor.darkGrayColor colorWithAlphaComponent:0.2];
+ }
+
+ return self;
+}
+
+- (void)drawRect:(NSRect)rect
+{
+ [super drawRect:rect];
+}
+@end
+
QT_BEGIN_NAMESPACE
// The following constants are used for adjusting the size
@@ -263,33 +280,50 @@ QVector<QPointer<QObject> > QMacStylePrivate::scrollBars;
static QLinearGradient titlebarGradientActive()
{
- static QLinearGradient gradient;
- if (gradient == QLinearGradient()) {
+ static QLinearGradient darkGradient = [](){
+ QLinearGradient gradient;
+ // FIXME: colors are chosen somewhat arbitrarily and could be fine-tuned,
+ // or ideally determined by calling a native API.
+ gradient.setColorAt(0, QColor(47, 47, 47));
+ return gradient;
+ }();
+ static QLinearGradient lightGradient = [](){
+ QLinearGradient gradient;
gradient.setColorAt(0, QColor(235, 235, 235));
gradient.setColorAt(0.5, QColor(210, 210, 210));
gradient.setColorAt(0.75, QColor(195, 195, 195));
gradient.setColorAt(1, QColor(180, 180, 180));
- }
- return gradient;
+ return gradient;
+ }();
+ return qt_mac_applicationIsInDarkMode() ? darkGradient : lightGradient;
}
static QLinearGradient titlebarGradientInactive()
{
- static QLinearGradient gradient;
- if (gradient == QLinearGradient()) {
+ static QLinearGradient darkGradient = [](){
+ QLinearGradient gradient;
+ gradient.setColorAt(1, QColor(42, 42, 42));
+ return gradient;
+ }();
+ static QLinearGradient lightGradient = [](){
+ QLinearGradient gradient;
gradient.setColorAt(0, QColor(250, 250, 250));
gradient.setColorAt(1, QColor(225, 225, 225));
- }
- return gradient;
+ return gradient;
+ }();
+ return qt_mac_applicationIsInDarkMode() ? darkGradient : lightGradient;
}
static const QColor titlebarSeparatorLineActive(111, 111, 111);
static const QColor titlebarSeparatorLineInactive(131, 131, 131);
+static const QColor darkModeSeparatorLine(88, 88, 88);
// Gradient colors used for the dock widget title bar and
// non-unifed tool bar bacground.
-static const QColor mainWindowGradientBegin(240, 240, 240);
-static const QColor mainWindowGradientEnd(200, 200, 200);
+static const QColor lightMainWindowGradientBegin(240, 240, 240);
+static const QColor lightMainWindowGradientEnd(200, 200, 200);
+static const QColor darkMainWindowGradientBegin(47, 47, 47);
+static const QColor darkMainWindowGradientEnd(47, 47, 47);
static const int DisclosureOffset = 4;
@@ -404,9 +438,9 @@ static bool setupSlider(NSSlider *slider, const QStyleOptionSlider *sl)
const bool ticksAbove = sl->tickPosition == QSlider::TicksAbove;
if (sl->orientation == Qt::Horizontal)
- slider.tickMarkPosition = ticksAbove ? NSTickMarkAbove : NSTickMarkBelow;
+ slider.tickMarkPosition = ticksAbove ? NSTickMarkPositionAbove : NSTickMarkPositionBelow;
else
- slider.tickMarkPosition = ticksAbove ? NSTickMarkLeft : NSTickMarkRight;
+ slider.tickMarkPosition = ticksAbove ? NSTickMarkPositionLeading : NSTickMarkPositionTrailing;
} else {
slider.numberOfTickMarks = 0;
}
@@ -1461,8 +1495,8 @@ QRectF QMacStylePrivate::CocoaControl::adjustedControlFrame(const QRectF &rect)
QRectF frameRect;
const auto frameSize = defaultFrameSize();
if (type == QMacStylePrivate::Button_SquareButton) {
- frameRect = rect.adjusted(3, 1, -3, -5)
- .adjusted(focusRingWidth, focusRingWidth, -focusRingWidth, -focusRingWidth);
+ frameRect = rect.adjusted(3, 1, -3, -1)
+ .adjusted(focusRingWidth, focusRingWidth, -focusRingWidth, -focusRingWidth);
} else if (type == QMacStylePrivate::Button_PushButton) {
// Start from the style option's top-left corner.
frameRect = QRectF(rect.topLeft(),
@@ -1697,18 +1731,28 @@ NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const
|| widget.size == QStyleHelper::SizeDefault)
return nil;
+ if (widget.type == Box) {
+ if (__builtin_available(macOS 10.14, *)) {
+ if (qt_mac_applicationIsInDarkMode()) {
+ // See render code in drawPrimitive(PE_FrameTabWidget)
+ widget.type = Box_Dark;
+ }
+ }
+ }
+
NSView *bv = cocoaControls.value(widget, nil);
if (!bv) {
switch (widget.type) {
case Box: {
- NSBox *bc = [[NSBox alloc] init];
- bc.title = @"";
- bc.titlePosition = NSNoTitle;
- bc.boxType = NSBoxPrimary;
- bc.borderType = NSBezelBorder;
- bv = bc;
+ NSBox *box = [[NSBox alloc] init];
+ bv = box;
+ box.title = @"";
+ box.titlePosition = NSNoTitle;
break;
}
+ case Box_Dark:
+ bv = [[QDarkNSBox alloc] init];
+ break;
case Button_CheckBox:
case Button_Disclosure:
case Button_PushButton:
@@ -1745,17 +1789,10 @@ NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const
}
Q_UNREACHABLE();
} ();
-#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12)
const auto styleMask = NSWindowStyleMaskTitled
| NSWindowStyleMaskClosable
| NSWindowStyleMaskMiniaturizable
| NSWindowStyleMaskResizable;
-#else
- const auto styleMask = NSTitledWindowMask
- | NSClosableWindowMask
- | NSMiniaturizableWindowMask
- | NSResizableWindowMask;
-#endif
bv = [NSWindow standardWindowButton:button forStyleMask:styleMask];
[bv retain];
break;
@@ -1802,10 +1839,10 @@ NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const
auto *ctrl = static_cast<NSControl *>(bv);
switch (widget.size) {
case QStyleHelper::SizeSmall:
- ctrl.controlSize = NSSmallControlSize;
+ ctrl.controlSize = NSControlSizeSmall;
break;
case QStyleHelper::SizeMini:
- ctrl.controlSize = NSMiniControlSize;
+ ctrl.controlSize = NSControlSizeMini;
break;
default:
break;
@@ -1816,10 +1853,10 @@ NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const
pi.indeterminate = (widget.type == ProgressIndicator_Indeterminate);
switch (widget.size) {
case QStyleHelper::SizeSmall:
- pi.controlSize = NSSmallControlSize;
+ pi.controlSize = NSControlSizeSmall;
break;
case QStyleHelper::SizeMini:
- pi.controlSize = NSMiniControlSize;
+ pi.controlSize = NSControlSizeMini;
break;
default:
break;
@@ -1865,10 +1902,10 @@ NSCell *QMacStylePrivate::cocoaCell(CocoaControl widget) const
switch (widget.size) {
case QStyleHelper::SizeSmall:
- cell.controlSize = NSSmallControlSize;
+ cell.controlSize = NSControlSizeSmall;
break;
case QStyleHelper::SizeMini:
- cell.controlSize = NSMiniControlSize;
+ cell.controlSize = NSControlSizeMini;
break;
default:
break;
@@ -1936,7 +1973,7 @@ QMacStyle::QMacStyle()
Q_D(QMacStyle);
QMacAutoReleasePool pool;
- d->receiver = [[NotificationReceiver alloc] initWithPrivate:d];
+ d->receiver = [[NotificationReceiver alloc] init];
[[NSNotificationCenter defaultCenter] addObserver:d->receiver
selector:@selector(scrollBarStyleDidChange:)
name:NSPreferredScrollerStyleDidChangeNotification
@@ -2208,9 +2245,9 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW
ret = 0;
break;
case PM_TitleBarHeight: {
- NSUInteger style = NSTitledWindowMask;
+ NSUInteger style = NSWindowStyleMaskTitled;
if (widget && ((widget->windowFlags() & Qt::Tool) == Qt::Tool))
- style |= NSUtilityWindowMask;
+ style |= NSWindowStyleMaskUtilityWindow;
ret = int([NSWindow frameRectForContentRect:NSZeroRect
styleMask:style].size.height);
break; }
@@ -2820,8 +2857,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
{
Q_D(const QMacStyle);
QMacCGContext cg(p);
- QWindow *window = w && w->window() ? w->window()->windowHandle() :
- QStyleHelper::styleObjectWindow(opt->styleObject);
+ QWindow *window = w && w->window() ? w->window()->windowHandle() : nullptr;
d->resolveCurrentNSView(window);
switch (pe) {
case PE_IndicatorArrowUp:
@@ -2923,10 +2959,28 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
{
const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Box, QStyleHelper::SizeLarge);
auto *box = static_cast<NSBox *>(d->cocoaControl(cw));
+ // FIXME Since macOS 10.14, simply calling drawRect: won't display anything anymore.
+ // The AppKit team is aware of this and has proposed a couple of solutions.
+ // The first solution was to call displayRectIgnoringOpacity:inContext: instead.
+ // However, it doesn't seem to work on 10.13. More importantly, dark mode on 10.14
+ // is extremely slow. Light mode works fine.
+ // The second solution is to subclass NSBox and reimplement a trivial drawRect: which
+ // would only call super. This works without any issue on 10.13, but a double border
+ // shows on 10.14 in both light and dark modes.
+ // The code below picks what works on each version and mode. On 10.13 and earlier, we
+ // simply call drawRect: on a regular NSBox. On 10.14, we call displayRectIgnoringOpacity:
+ // inContext:, but only in light mode. In dark mode, we use a custom NSBox subclass,
+ // QDarkNSBox, of type NSBoxCustom. Its appearance is close enough to the real thing so
+ // we can use this for now.
d->drawNSViewInRect(box, opt->rect, p, ^(CGContextRef ctx, const CGRect &rect) {
CGContextTranslateCTM(ctx, 0, rect.origin.y + rect.size.height);
CGContextScaleCTM(ctx, 1, -1);
- [box drawRect:rect];
+ if (QOperatingSystemVersion::current() < QOperatingSystemVersion::MacOSMojave
+ || [box isMemberOfClass:QDarkNSBox.class]) {
+ [box drawRect:rect];
+ } else {
+ [box displayRectIgnoringOpacity:box.bounds inContext:NSGraphicsContext.currentContext];
+ }
});
break;
}
@@ -3136,8 +3190,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
tf.bezeled = YES;
static_cast<NSTextFieldCell *>(tf.cell).bezelStyle = isRounded ? NSTextFieldRoundedBezel : NSTextFieldSquareBezel;
tf.frame = opt->rect.toCGRect();
- d->drawNSViewInRect(tf, opt->rect, p, ^(CGContextRef ctx, const CGRect &rect) {
- Q_UNUSED(ctx);
+ d->drawNSViewInRect(tf, opt->rect, p, ^(CGContextRef, const CGRect &rect) {
[tf.cell drawWithFrame:rect inView:tf];
});
} else {
@@ -3266,8 +3319,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
{
Q_D(const QMacStyle);
QMacCGContext cg(p);
- QWindow *window = w && w->window() ? w->window()->windowHandle() :
- QStyleHelper::styleObjectWindow(opt->styleObject);
+ QWindow *window = w && w->window() ? w->window()->windowHandle() : nullptr;
d->resolveCurrentNSView(window);
switch (ce) {
case CE_HeaderSection:
@@ -3468,7 +3520,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
pb.enabled = isEnabled;
[pb highlight:isPressed];
pb.state = isHighlighted && !isPressed ? NSOnState : NSOffState;
- d->drawNSViewInRect(pb, frameRect, p, ^(CGContextRef __unused ctx, const CGRect &r) {
+ d->drawNSViewInRect(pb, frameRect, p, ^(CGContextRef, const CGRect &r) {
[pb.cell drawBezelWithFrame:r inView:pb.superview];
});
[pb highlight:NO];
@@ -4210,7 +4262,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
const auto cw = QMacStylePrivate::CocoaControl(ct, QStyleHelper::SizeLarge);
auto *sv = static_cast<NSSplitView *>(d->cocoaControl(cw));
sv.frame = opt->rect.toCGRect();
- d->drawNSViewInRect(sv, opt->rect, p, ^(CGContextRef __unused ctx, const CGRect &rect) {
+ d->drawNSViewInRect(sv, opt->rect, p, ^(CGContextRef, const CGRect &rect) {
[sv drawDividerInRect:rect];
});
} else {
@@ -4253,12 +4305,13 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
#ifndef QT_NO_TOOLBAR
case CE_ToolBar: {
const QStyleOptionToolBar *toolBar = qstyleoption_cast<const QStyleOptionToolBar *>(opt);
+ const bool isDarkMode = qt_mac_applicationIsInDarkMode();
// Unified title and toolbar drawing. In this mode the cocoa platform plugin will
// fill the top toolbar area part with a background gradient that "unifies" with
// the title bar. The following code fills the toolBar area with transparent pixels
// to make that gradient visible.
- if (w) {
+ if (w) {
#if QT_CONFIG(mainwindow)
if (QMainWindow * mainWindow = qobject_cast<QMainWindow *>(w->window())) {
if (toolBar && toolBar->toolBarArea == Qt::TopToolBarArea && mainWindow->unifiedTitleAndToolBarOnMac()) {
@@ -4268,7 +4321,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
p->fillRect(opt->rect, Qt::transparent);
p->restore();
- // Drow a horizontal separator line at the toolBar bottom if the "unified" area ends here.
+ // Draw a horizontal separator line at the toolBar bottom if the "unified" area ends here.
// There might be additional toolbars or other widgets such as tab bars in document
// mode below. Determine this by making a unified toolbar area test for the row below
// this toolbar.
@@ -4277,7 +4330,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
if (isEndOfUnifiedArea) {
const int margin = qt_mac_aqua_get_metric(SeparatorSize);
const auto separatorRect = QRect(opt->rect.left(), opt->rect.bottom(), opt->rect.width(), margin);
- p->fillRect(separatorRect, opt->palette.dark().color());
+ p->fillRect(separatorRect, isDarkMode ? darkModeSeparatorLine : opt->palette.dark().color());
}
break;
}
@@ -4292,21 +4345,23 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
else
linearGrad = QLinearGradient(opt->rect.left(), 0, opt->rect.right(), 0);
+ QColor mainWindowGradientBegin = isDarkMode ? darkMainWindowGradientBegin : lightMainWindowGradientBegin;
+ QColor mainWindowGradientEnd = isDarkMode ? darkMainWindowGradientEnd : lightMainWindowGradientEnd;
+
linearGrad.setColorAt(0, mainWindowGradientBegin);
linearGrad.setColorAt(1, mainWindowGradientEnd);
p->fillRect(opt->rect, linearGrad);
p->save();
if (opt->state & State_Horizontal) {
- p->setPen(mainWindowGradientBegin.lighter(114));
+ p->setPen(isDarkMode ? darkModeSeparatorLine : mainWindowGradientBegin.lighter(114));
p->drawLine(opt->rect.topLeft(), opt->rect.topRight());
- p->setPen(mainWindowGradientEnd.darker(114));
+ p->setPen(isDarkMode ? darkModeSeparatorLine :mainWindowGradientEnd.darker(114));
p->drawLine(opt->rect.bottomLeft(), opt->rect.bottomRight());
-
} else {
- p->setPen(mainWindowGradientBegin.lighter(114));
+ p->setPen(isDarkMode ? darkModeSeparatorLine : mainWindowGradientBegin.lighter(114));
p->drawLine(opt->rect.topLeft(), opt->rect.bottomLeft());
- p->setPen(mainWindowGradientEnd.darker(114));
+ p->setPen(isDarkMode ? darkModeSeparatorLine : mainWindowGradientEnd.darker(114));
p->drawLine(opt->rect.topRight(), opt->rect.bottomRight());
}
p->restore();
@@ -4841,8 +4896,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
{
Q_D(const QMacStyle);
QMacCGContext cg(p);
- QWindow *window = widget && widget->window() ? widget->window()->windowHandle() :
- QStyleHelper::styleObjectWindow(opt->styleObject);
+ QWindow *window = widget && widget->window() ? widget->window()->windowHandle() : nullptr;
d->resolveCurrentNSView(window);
switch (cc) {
case CC_ScrollBar:
@@ -5217,7 +5271,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
}
pb.frame = frameRect.toCGRect();
[pb highlight:isPressed];
- d->drawNSViewInRect(pb, frameRect, p, ^(CGContextRef __unused ctx, const CGRect &r) {
+ d->drawNSViewInRect(pb, frameRect, p, ^(CGContextRef, const CGRect &r) {
[pb.cell drawBezelWithFrame:r inView:pb.superview];
});
} else if (cw.type == QMacStylePrivate::ComboBox) {
@@ -5233,7 +5287,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
// TODO Render to pixmap and darken the button manually
}
- d->drawNSViewInRect(cb, frameRect, p, ^(CGContextRef __unused ctx, const CGRect &r) {
+ d->drawNSViewInRect(cb, frameRect, p, ^(CGContextRef, const CGRect &r) {
// FIXME This is usually drawn in the control's superview, but we wouldn't get inactive look in this case
[cb.cell drawWithFrame:r inView:cb];
});
@@ -5305,13 +5359,10 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
Q_UNUSED(isHovered); // FIXME No public API for this
const auto buttonRect = proxy()->subControlRect(CC_TitleBar, titlebar, sc, widget);
- const auto drawBlock = ^ (CGContextRef ctx, const CGRect &rect) {
- Q_UNUSED(ctx);
- Q_UNUSED(rect);
+ d->drawNSViewInRect(wb, buttonRect, p, ^(CGContextRef, const CGRect &rect) {
auto *wbCell = static_cast<NSButtonCell *>(wb.cell);
[wbCell drawWithFrame:rect inView:wb];
- };
- d->drawNSViewInRect(wb, buttonRect, p, drawBlock);
+ });
}
}
@@ -5376,12 +5427,6 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
d->drawToolbarButtonArrow(tb, p);
}
if (tb->state & State_On) {
- QWindow *window = 0;
- if (widget && widget->window())
- window = widget->window()->windowHandle();
- else if (opt->styleObject)
- window = opt->styleObject->property("_q_styleObjectWindow").value<QWindow *>();
-
NSView *view = window ? (NSView *)window->winId() : nil;
bool isKey = false;
if (view)
@@ -5420,8 +5465,8 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
pb.enabled = isEnabled;
[pb highlight:isPressed];
pb.state = isHighlighted && !isPressed ? NSOnState : NSOffState;
- const auto buttonRect = proxy()->subControlRect(cc, tb, SC_ToolButton, widget);
- d->drawNSViewInRect(pb, buttonRect, p, ^(CGContextRef __unused ctx, const CGRect &rect) {
+ const auto buttonRect = proxy()->subControlRect(cc, tb, SC_ToolButton, widget);
+ d->drawNSViewInRect(pb, buttonRect, p, ^(CGContextRef, const CGRect &rect) {
[pb.cell drawBezelWithFrame:rect inView:pb];
});
}
@@ -5904,7 +5949,7 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
switch (ct) {
#if QT_CONFIG(spinbox)
case CT_SpinBox:
- if (const QStyleOptionSpinBox *vopt = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
+ if (qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
const int buttonWidth = 20; // FIXME Use subControlRect()
sz += QSize(buttonWidth, 0);
}
diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h
index 8c712e838a..dd99cf4bb5 100644
--- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h
+++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h
@@ -187,6 +187,7 @@ public:
enum CocoaControlType {
NoControl, // For when there's no such a control in Cocoa
Box, // QGroupBox
+ Box_Dark, // FIXME See render code in drawPrimitive(PE_FrameTabWidget)
Button_CheckBox,
Button_Disclosure, // Disclosure triangle, like in QTreeView
Button_PopupButton, // Non-editable QComboBox
diff --git a/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp b/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp
index 6add110249..7b35d1b58c 100644
--- a/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp
+++ b/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp
@@ -179,9 +179,7 @@ QWindowsVistaStyle::QWindowsVistaStyle()
/*!
Destructor.
*/
-QWindowsVistaStyle::~QWindowsVistaStyle()
-{
-}
+QWindowsVistaStyle::~QWindowsVistaStyle() = default;
//convert Qt state flags to uxtheme button states
static int buttonStateId(int flags, int partId)
@@ -2171,12 +2169,12 @@ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOpt
if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(option)) {
if (!buttonVisible(subControl, tb))
return rect;
+ const qreal factor = QWindowsStylePrivate::nativeMetricScaleFactor(widget);
const bool isToolTitle = false;
const int height = tb->rect.height();
const int width = tb->rect.width();
const int buttonWidth =
- qRound(qreal(GetSystemMetrics(SM_CXSIZE)) * QWindowsStylePrivate::nativeMetricScaleFactor(widget)
- - QStyleHelper::dpiScaled(4));
+ qRound(qreal(GetSystemMetrics(SM_CXSIZE)) * factor - QStyleHelper::dpiScaled(4));
const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget);
const bool sysmenuHint = (tb->titleBarFlags & Qt::WindowSystemMenuHint) != 0;
@@ -2190,31 +2188,31 @@ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOpt
rect = QRect(frameWidth, 0, width - (buttonWidth + frameWidth + 10), height);
if (isToolTitle) {
if (sysmenuHint) {
- rect.adjust(0, 0, -buttonWidth - 3, 0);
+ rect.adjust(0, 0, int(-buttonWidth - 3 * factor), 0);
}
if (minimizeHint || maximizeHint)
- rect.adjust(0, 0, -buttonWidth - 2, 0);
+ rect.adjust(0, 0, int(-buttonWidth - 2 * factor), 0);
} else {
if (sysmenuHint) {
- const int leftOffset = height - 8;
- rect.adjust(leftOffset, 0, 0, 4);
+ const int leftOffset = int(height - 8 * factor);
+ rect.adjust(leftOffset, 0, 0, int(4 * factor));
}
if (minimizeHint)
- rect.adjust(0, 0, -buttonWidth - 2, 0);
+ rect.adjust(0, 0, int(-buttonWidth - 2 * factor), 0);
if (maximizeHint)
- rect.adjust(0, 0, -buttonWidth - 2, 0);
+ rect.adjust(0, 0, int(-buttonWidth - 2 * factor), 0);
if (contextHint)
- rect.adjust(0, 0, -buttonWidth - 2, 0);
+ rect.adjust(0, 0, int(-buttonWidth - 2 * factor), 0);
if (shadeHint)
- rect.adjust(0, 0, -buttonWidth - 2, 0);
+ rect.adjust(0, 0, int(-buttonWidth - 2 * factor), 0);
}
- rect.translate(0, 2);
+ rect.translate(0, int(2 * factor));
rect = visualRect(option->direction, option->rect, rect);
break;
case SC_TitleBarSysMenu:
{
- const int controlTop = 6;
- const int controlHeight = height - controlTop - 3;
+ const int controlTop = int(6 * factor);
+ const int controlHeight = int(height - controlTop - 3 * factor);
int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
QSize iconSize = tb->icon.actualSize(QSize(iconExtent, iconExtent));
if (tb->icon.isNull())
@@ -2222,7 +2220,7 @@ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOpt
int hPad = (controlHeight - iconSize.height())/2;
int vPad = (controlHeight - iconSize.width())/2;
rect = QRect(frameWidth + hPad, controlTop + vPad, iconSize.width(), iconSize.height());
- rect.translate(0, 3);
+ rect.translate(0, int(3 * factor));
rect = visualRect(option->direction, option->rect, rect);
}
break;
diff --git a/src/plugins/styles/windowsvista/qwindowsvistastyle_p.h b/src/plugins/styles/windowsvista/qwindowsvistastyle_p.h
index 5ffcbc6aa9..0ebb0eb41a 100644
--- a/src/plugins/styles/windowsvista/qwindowsvistastyle_p.h
+++ b/src/plugins/styles/windowsvista/qwindowsvistastyle_p.h
@@ -62,38 +62,41 @@ class QWindowsVistaStyle : public QWindowsXPStyle
Q_OBJECT
public:
QWindowsVistaStyle();
- ~QWindowsVistaStyle();
+ ~QWindowsVistaStyle() override;
void drawPrimitive(PrimitiveElement element, const QStyleOption *option,
- QPainter *painter, const QWidget *widget = 0) const;
+ QPainter *painter,
+ const QWidget *widget = nullptr) const override;
void drawControl(ControlElement element, const QStyleOption *option,
- QPainter *painter, const QWidget *widget) const;
+ QPainter *painter, const QWidget *widget) const override;
void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option,
- QPainter *painter, const QWidget *widget) const;
+ QPainter *painter, const QWidget *widget) const override;
QSize sizeFromContents(ContentsType type, const QStyleOption *option,
- const QSize &size, const QWidget *widget) const;
+ const QSize &size, const QWidget *widget) const override;
- QRect subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const;
+ QRect subElementRect(SubElement element, const QStyleOption *option,
+ const QWidget *widget) const override;
QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt,
- SubControl sc, const QWidget *widget) const;
+ SubControl sc, const QWidget *widget) const override;
SubControl hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option,
- const QPoint &pos, const QWidget *widget = 0) const;
+ const QPoint &pos, const QWidget *widget = nullptr) const override;
- QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *option = 0,
- const QWidget *widget = 0) const;
+ QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *option = nullptr,
+ const QWidget *widget = nullptr) const override;
QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt,
- const QWidget *widget = 0) const;
- int pixelMetric(PixelMetric metric, const QStyleOption *option = 0, const QWidget *widget = 0) const;
- int styleHint(StyleHint hint, const QStyleOption *opt = 0, const QWidget *widget = 0,
- QStyleHintReturn *returnData = 0) const;
+ const QWidget *widget = nullptr) const override;
+ int pixelMetric(PixelMetric metric, const QStyleOption *option = nullptr,
+ const QWidget *widget = nullptr) const override;
+ int styleHint(StyleHint hint, const QStyleOption *opt = nullptr,
+ const QWidget *widget = nullptr, QStyleHintReturn *returnData = nullptr) const override;
- void polish(QWidget *widget);
- void unpolish(QWidget *widget);
- void polish(QPalette &pal);
- void polish(QApplication *app);
- void unpolish(QApplication *app);
- QPalette standardPalette() const;
+ void polish(QWidget *widget) override;
+ void unpolish(QWidget *widget) override;
+ void polish(QPalette &pal) override;
+ void polish(QApplication *app) override;
+ void unpolish(QApplication *app) override;
+ QPalette standardPalette() const override;
private:
Q_DISABLE_COPY(QWindowsVistaStyle)
diff --git a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
index 36a8afb453..4b583e13d3 100644
--- a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
+++ b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
@@ -494,7 +494,8 @@ bool QWindowsXPStylePrivate::isTransparent(XPThemeData &themeData)
QRegion QWindowsXPStylePrivate::region(XPThemeData &themeData)
{
HRGN hRgn = 0;
- RECT rect = themeData.toRECT(themeData.rect);
+ const qreal factor = QWindowsStylePrivate::nativeMetricScaleFactor(themeData.widget);
+ RECT rect = themeData.toRECT(QRect(themeData.rect.topLeft() / factor, themeData.rect.size() / factor));
if (!SUCCEEDED(GetThemeBackgroundRegion(themeData.handle(), bufferHDC(), themeData.partId,
themeData.stateId, &rect, &hRgn))) {
return QRegion();
@@ -523,7 +524,7 @@ QRegion QWindowsXPStylePrivate::region(XPThemeData &themeData)
RECT *r = reinterpret_cast<RECT*>(rd->Buffer);
for (uint i = 0; i < rd->rdh.nCount; ++i) {
QRect rect;
- rect.setCoords(r->left, r->top, r->right - 1, r->bottom - 1);
+ rect.setCoords(int(r->left * factor), int(r->top * factor), int((r->right - 1) * factor), int((r->bottom - 1) * factor));
++r;
region |= rect;
}
@@ -1756,9 +1757,9 @@ case PE_Frame:
else
stateId = FS_INACTIVE;
- int fwidth = frm->lineWidth + frm->midLineWidth;
+ int fwidth = int((frm->lineWidth + frm->midLineWidth) / QWindowsStylePrivate::nativeMetricScaleFactor(widget));
- XPThemeData theme(0, p, themeNumber, 0, stateId);
+ XPThemeData theme(widget, p, themeNumber, 0, stateId);
if (!theme.isValid())
break;
@@ -2949,6 +2950,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
{
if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(option))
{
+ const qreal factor = QWindowsStylePrivate::nativeMetricScaleFactor(widget);
bool isActive = tb->titleBarState & QStyle::State_Active;
XPThemeData theme(widget, p, QWindowsXPStylePrivate::WindowTheme);
if (sub & SC_TitleBarLabel) {
@@ -2975,13 +2977,15 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
GetThemeColor(theme.handle(), WP_CAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWCOLOR, &textShadowRef);
QColor textShadow = qRgb(GetRValue(textShadowRef), GetGValue(textShadowRef), GetBValue(textShadowRef));
p->setPen(textShadow);
- p->drawText(ir.x() + 3, ir.y() + 2, ir.width() - 1, ir.height(),
+ p->drawText(int(ir.x() + 3 * factor), int(ir.y() + 2 * factor),
+ int(ir.width() - 1 * factor), ir.height(),
Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, tb->text);
}
COLORREF captionText = GetSysColor(isActive ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT);
QColor textColor = qRgb(GetRValue(captionText), GetGValue(captionText), GetBValue(captionText));
p->setPen(textColor);
- p->drawText(ir.x() + 2, ir.y() + 1, ir.width() - 2, ir.height(),
+ p->drawText(int(ir.x() + 2 * factor), int(ir.y() + 1 * factor),
+ int(ir.width() - 2 * factor), ir.height(),
Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, tb->text);
}
if (sub & SC_TitleBarSysMenu && tb->titleBarFlags & Qt::WindowSystemMenuHint) {
diff --git a/src/plugins/styles/windowsvista/qwindowsxpstyle_p.h b/src/plugins/styles/windowsvista/qwindowsxpstyle_p.h
index d00620eefa..7e9f4ddda6 100644
--- a/src/plugins/styles/windowsvista/qwindowsxpstyle_p.h
+++ b/src/plugins/styles/windowsvista/qwindowsxpstyle_p.h
@@ -63,35 +63,37 @@ class QWindowsXPStyle : public QWindowsStyle
public:
QWindowsXPStyle();
QWindowsXPStyle(QWindowsXPStylePrivate &dd);
- ~QWindowsXPStyle();
+ ~QWindowsXPStyle() override;
- void unpolish(QApplication*);
- void polish(QApplication*);
- void polish(QWidget*);
- void polish(QPalette&);
- void unpolish(QWidget*);
+ void unpolish(QApplication*) override;
+ void polish(QApplication*) override;
+ void polish(QWidget*) override;
+ void polish(QPalette&) override;
+ void unpolish(QWidget*) override;
void drawPrimitive(PrimitiveElement pe, const QStyleOption *option, QPainter *p,
- const QWidget *widget = 0) const;
+ const QWidget *widget = nullptr) const override;
void drawControl(ControlElement element, const QStyleOption *option, QPainter *p,
- const QWidget *wwidget = 0) const;
- QRect subElementRect(SubElement r, const QStyleOption *option, const QWidget *widget = 0) const;
+ const QWidget *wwidget = nullptr) const override;
+ QRect subElementRect(SubElement r, const QStyleOption *option,
+ const QWidget *widget = nullptr) const override;
QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *option, SubControl sc,
- const QWidget *widget = 0) const;
+ const QWidget *widget = nullptr) const override;
void drawComplexControl(ComplexControl cc, const QStyleOptionComplex *option, QPainter *p,
- const QWidget *widget = 0) const;
+ const QWidget *widget = nullptr) const override;
QSize sizeFromContents(ContentsType ct, const QStyleOption *option, const QSize &contentsSize,
- const QWidget *widget = 0) const;
- int pixelMetric(PixelMetric pm, const QStyleOption *option = 0,
- const QWidget *widget = 0) const;
- int styleHint(StyleHint hint, const QStyleOption *option = 0, const QWidget *widget = 0,
- QStyleHintReturn *returnData = 0) const;
+ const QWidget *widget = nullptr) const override;
+ int pixelMetric(PixelMetric pm, const QStyleOption *option = nullptr,
+ const QWidget *widget = nullptr) const override;
+ int styleHint(StyleHint hint, const QStyleOption *option = nullptr,
+ const QWidget *widget = nullptr,
+ QStyleHintReturn *returnData = nullptr) const override;
- QPalette standardPalette() const;
+ QPalette standardPalette() const override;
QPixmap standardPixmap(StandardPixmap standardIcon, const QStyleOption *option,
- const QWidget *widget = 0) const;
- QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *option = 0,
- const QWidget *widget = 0) const;
+ const QWidget *widget = nullptr) const override;
+ QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *option = nullptr,
+ const QWidget *widget = nullptr) const override;
private:
Q_DISABLE_COPY(QWindowsXPStyle)
diff --git a/src/printsupport/dialogs/qpagesetupdialog_mac.mm b/src/printsupport/dialogs/qpagesetupdialog_mac.mm
index 1e398452f7..a3511fe7b6 100644
--- a/src/printsupport/dialogs/qpagesetupdialog_mac.mm
+++ b/src/printsupport/dialogs/qpagesetupdialog_mac.mm
@@ -52,16 +52,13 @@ QT_USE_NAMESPACE
@class QT_MANGLE_NAMESPACE(QCocoaPageLayoutDelegate);
@interface QT_MANGLE_NAMESPACE(QCocoaPageLayoutDelegate) : NSObject
-{
+@end
+
+@implementation QT_MANGLE_NAMESPACE(QCocoaPageLayoutDelegate) {
NSPrintInfo *printInfo;
}
-- (id)initWithNSPrintInfo:(NSPrintInfo *)nsPrintInfo;
-- (void)pageLayoutDidEnd:(NSPageLayout *)pageLayout
- returnCode:(int)returnCode contextInfo:(void *)contextInfo;
-@end
-@implementation QT_MANGLE_NAMESPACE(QCocoaPageLayoutDelegate)
-- (id)initWithNSPrintInfo:(NSPrintInfo *)nsPrintInfo
+- (instancetype)initWithNSPrintInfo:(NSPrintInfo *)nsPrintInfo
{
self = [super init];
if (self) {
diff --git a/src/printsupport/dialogs/qpagesetupdialog_unix.cpp b/src/printsupport/dialogs/qpagesetupdialog_unix.cpp
index 7e32f9aa57..d9b4a84aa9 100644
--- a/src/printsupport/dialogs/qpagesetupdialog_unix.cpp
+++ b/src/printsupport/dialogs/qpagesetupdialog_unix.cpp
@@ -49,6 +49,7 @@
#include "qpainter.h"
#include "qprintdialog.h"
+#include "qtextcodec.h"
#include "qdialogbuttonbox.h"
#include <ui_qpagesetupwidget.h>
@@ -235,6 +236,9 @@ QPageSetupWidget::QPageSetupWidget(QWidget *parent)
m_pagePreview(nullptr),
m_printer(nullptr),
m_printDevice(nullptr),
+#if QT_CONFIG(cups)
+ m_pageSizePpdOption(nullptr),
+#endif
m_outputFormat(QPrinter::PdfFormat),
m_units(QPageLayout::Point),
m_savedUnits(QPageLayout::Point),
@@ -391,6 +395,11 @@ void QPageSetupWidget::setPrinter(QPrinter *printer, QPrintDevice *printDevice,
m_printer = printer;
m_printDevice = printDevice;
+#if QT_CONFIG(cups)
+ // find the PageSize cups option
+ m_pageSizePpdOption = m_printDevice ? QCUPSSupport::findPpdOption("PageSize", m_printDevice) : nullptr;
+#endif
+
// Initialize the layout to the current QPrinter layout
m_pageLayout = m_printer->pageLayout();
@@ -415,6 +424,12 @@ void QPageSetupWidget::setPrinter(QPrinter *printer, QPrintDevice *printDevice,
initPageSizes();
updateWidget();
updateSavedValues();
+
+ if (m_ui.pageSizeCombo->currentIndex() == -1) {
+ // This can happen in raw printers that since they don't have a default
+ // page size none will get selected so just default to the first size (A4)
+ m_ui.pageSizeCombo->setCurrentIndex(0);
+ }
}
// Update the widget with the current settings
@@ -547,15 +562,48 @@ void QPageSetupWidget::revertToSavedValues()
m_ui.pagesPerSheetLayoutCombo->setCurrentIndex(m_savedPagesPerSheetLayout);
}
+#if QT_CONFIG(cups)
+bool QPageSetupWidget::hasPpdConflict() const
+{
+ if (m_pageSizePpdOption) {
+ if (m_pageSizePpdOption->conflicted) {
+ const QIcon warning = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning, nullptr, nullptr);
+ const int pixmap_size = m_ui.pageSizeCombo->sizeHint().height() * .75;
+ m_ui.pageSizeWarningLabel->setPixmap(warning.pixmap(pixmap_size, pixmap_size));
+ } else {
+ m_ui.pageSizeWarningLabel->setPixmap(QPixmap());
+ }
+ return m_pageSizePpdOption->conflicted;
+ }
+
+ return false;
+}
+#endif
+
// Updates size/preview after the combobox has been changed.
void QPageSetupWidget::pageSizeChanged()
{
- if (m_blockSignals)
- return;
-
QPageSize pageSize;
if (m_ui.pageSizeCombo->currentIndex() != m_realCustomPageSizeIndex) {
pageSize = m_ui.pageSizeCombo->currentData().value<QPageSize>();
+
+#if QT_CONFIG(cups)
+ if (m_pageSizePpdOption) {
+ ppd_file_t *ppd = m_printDevice->property(PDPK_PpdFile).value<ppd_file_t*>();
+ QTextCodec *cupsCodec = QTextCodec::codecForName(ppd->lang_encoding);
+ for (int i = 0; i < m_pageSizePpdOption->num_choices; ++i) {
+ const ppd_choice_t *choice = &m_pageSizePpdOption->choices[i];
+ if (cupsCodec->toUnicode(choice->text) == m_ui.pageSizeCombo->currentText()) {
+ const auto values = QStringList{} << QString::fromLatin1(m_pageSizePpdOption->keyword)
+ << QString::fromLatin1(choice->choice);
+ m_printDevice->setProperty(PDPK_PpdOption, values);
+ emit ppdOptionChanged();
+ break;
+ }
+ }
+ }
+#endif
+
} else {
QSizeF customSize;
if (m_pageLayout.orientation() == QPageLayout::Landscape)
@@ -563,7 +611,22 @@ void QPageSetupWidget::pageSizeChanged()
else
customSize = QSizeF(m_ui.pageWidth->value(), m_ui.pageHeight->value());
pageSize = QPageSize(customSize, QPageSize::Unit(m_units));
+
+#if QT_CONFIG(cups)
+ if (m_pageSizePpdOption) {
+ const auto values = QStringList{} << QString::fromLatin1(m_pageSizePpdOption->keyword)
+ << QStringLiteral("Custom");
+ m_printDevice->setProperty(PDPK_PpdOption, values);
+ emit ppdOptionChanged();
+ }
+#endif
}
+
+ // We always need to update the m_pageSizePpdOption when the page size changes
+ // even if it's from inside updateWidget, so do not move up
+ if (m_blockSignals)
+ return;
+
const QMarginsF printable = m_printDevice ? m_printDevice->printableMargins(pageSize, m_pageLayout.orientation(), m_printer->resolution())
: QMarginsF();
m_pageLayout.setPageSize(pageSize, qt_convertMargins(printable, QPageLayout::Point, m_pageLayout.units()));
diff --git a/src/printsupport/dialogs/qpagesetupdialog_unix_p.h b/src/printsupport/dialogs/qpagesetupdialog_unix_p.h
index bb33a0f587..7bfdaed740 100644
--- a/src/printsupport/dialogs/qpagesetupdialog_unix_p.h
+++ b/src/printsupport/dialogs/qpagesetupdialog_unix_p.h
@@ -54,6 +54,7 @@
#include <QtPrintSupport/private/qtprintsupportglobal_p.h>
#include "qprinter.h"
+#include "kernel/qprint_p.h"
#include <QtGui/qpagelayout.h>
@@ -78,6 +79,13 @@ public:
void updateSavedValues();
void revertToSavedValues();
+#if QT_CONFIG(cups)
+ bool hasPpdConflict() const;
+
+signals:
+ void ppdOptionChanged();
+#endif
+
private slots:
void pageSizeChanged();
void pageOrientationChanged();
@@ -100,6 +108,9 @@ private:
QPagePreview *m_pagePreview;
QPrinter *m_printer;
QPrintDevice *m_printDevice;
+#if QT_CONFIG(cups)
+ ppd_option_t *m_pageSizePpdOption;
+#endif
QPrinter::OutputFormat m_outputFormat;
QString m_printerName;
QPageLayout m_pageLayout;
diff --git a/src/printsupport/dialogs/qpagesetupwidget.ui b/src/printsupport/dialogs/qpagesetupwidget.ui
index 960a9dac17..3f24553c76 100644
--- a/src/printsupport/dialogs/qpagesetupwidget.ui
+++ b/src/printsupport/dialogs/qpagesetupwidget.ui
@@ -99,6 +99,9 @@
</property>
</spacer>
</item>
+ <item row="0" column="2">
+ <widget class="QLabel" name="pageSizeWarningLabel"/>
+ </item>
</layout>
</widget>
</item>
diff --git a/src/printsupport/dialogs/qprintdialog_mac.mm b/src/printsupport/dialogs/qprintdialog_mac.mm
index 854779977c..ed2d0908c4 100644
--- a/src/printsupport/dialogs/qprintdialog_mac.mm
+++ b/src/printsupport/dialogs/qprintdialog_mac.mm
@@ -77,22 +77,20 @@ QT_USE_NAMESPACE
@class QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate);
@interface QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) : NSObject
-{
+@end
+
+@implementation QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) {
NSPrintInfo *printInfo;
}
-- (id)initWithNSPrintInfo:(NSPrintInfo *)nsPrintInfo;
-- (void)printPanelDidEnd:(NSPrintPanel *)printPanel
- returnCode:(int)returnCode contextInfo:(void *)contextInfo;
-@end
-@implementation QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate)
-- (id)initWithNSPrintInfo:(NSPrintInfo *)nsPrintInfo
+- (instancetype)initWithNSPrintInfo:(NSPrintInfo *)nsPrintInfo
{
- if (self = [super init]) {
+ if ((self = [self init])) {
printInfo = nsPrintInfo;
}
return self;
}
+
- (void)printPanelDidEnd:(NSPrintPanel *)printPanel
returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
@@ -102,8 +100,8 @@ QT_USE_NAMESPACE
QPrinter *printer = dialog->printer();
if (returnCode == NSModalResponseOK) {
- PMPrintSession session = static_cast<PMPrintSession>([printInfo PMPrintSession]);
- PMPrintSettings settings = static_cast<PMPrintSettings>([printInfo PMPrintSettings]);
+ PMPrintSession session = static_cast<PMPrintSession>(printInfo.PMPrintSession);
+ PMPrintSettings settings = static_cast<PMPrintSettings>(printInfo.PMPrintSettings);
UInt32 frompage, topage;
PMGetFirstPage(settings, &frompage);
@@ -192,6 +190,7 @@ QT_USE_NAMESPACE
dialog->done((returnCode == NSModalResponseOK) ? QDialog::Accepted : QDialog::Rejected);
}
+
@end
QT_BEGIN_NAMESPACE
diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp
index 86daea3b02..5390a8b2f2 100644
--- a/src/printsupport/dialogs/qprintdialog_unix.cpp
+++ b/src/printsupport/dialogs/qprintdialog_unix.cpp
@@ -50,12 +50,14 @@
#endif
#include <QtCore/qdebug.h>
#include <QtCore/qdir.h>
+#include <QtCore/qglobal.h>
#include <QtCore/qtextcodec.h>
#include <QtGui/qevent.h>
#if QT_CONFIG(filesystemmodel)
#include <QtWidgets/qfilesystemmodel.h>
#endif
#include <QtWidgets/qstyleditemdelegate.h>
+#include <QtWidgets/qformlayout.h>
#include <QtPrintSupport/qprinter.h>
#include <qpa/qplatformprintplugin.h>
@@ -73,6 +75,7 @@
#include "ui_qprintwidget.h"
#if QT_CONFIG(cups)
+Q_DECLARE_METATYPE(const ppd_option_t *)
#include <private/qcups_p.h>
#if QT_CONFIG(cupsjobwidget)
#include "qcupsjobwidget_p.h"
@@ -110,11 +113,6 @@ Print dialog class declarations
allow editing of Page and Advanced tabs.
Layout in qprintpropertieswidget.ui
-
- QPPDOptionsModel: Holds the PPD Options for the printer.
-
- QPPDOptionsEditor: Edits the PPD Options for the printer.
-
*/
static void initResources()
@@ -124,9 +122,6 @@ static void initResources()
QT_BEGIN_NAMESPACE
-class QOptionTreeItem;
-class QPPDOptionsModel;
-
class QPrintPropertiesDialog : public QDialog
{
Q_OBJECT
@@ -138,13 +133,13 @@ public:
void setupPrinter() const;
- void showEvent(QShowEvent *event) override;
-
private slots:
void reject() override;
void accept() override;
private:
+ void showEvent(QShowEvent *event) override;
+
friend class QUnixPrintWidgetPrivate;
#if QT_CONFIG(cups)
QPrinter *m_printer;
@@ -156,9 +151,16 @@ private:
#endif
#if QT_CONFIG(cups)
- void setCupsOptionsFromItems(QOptionTreeItem *parent) const;
+ bool createAdvancedOptionsWidget();
+ void setPrinterAdvancedCupsOptions() const;
+ void revertAdvancedOptionsToSavedValues() const;
+ void advancedOptionsUpdateSavedValues() const;
+ bool anyPpdOptionConflict() const;
+ bool anyAdvancedOptionConflict() const;
- QPPDOptionsModel *m_cupsOptionsModel;
+ QPrintDevice *m_currentPrintDevice;
+ QTextCodec *m_cupsCodec = nullptr;
+ QVector<QComboBox*> m_advancedOptionsCombos;
#endif
};
@@ -174,6 +176,7 @@ public:
void updatePrinter();
private:
+ friend class QPrintDialog;
friend class QPrintDialogPrivate;
friend class QUnixPrintWidgetPrivate;
QUnixPrintWidgetPrivate *d;
@@ -206,6 +209,11 @@ public:
void updateWidget();
+#if QT_CONFIG(cups)
+ void setPpdDuplex(QPrinter::DuplexMode mode);
+ ppd_option_t *m_duplexPpdOption;
+#endif
+
private:
QPrintDialogPrivate *optionsPane;
bool filePrintersAdded;
@@ -229,6 +237,9 @@ public:
#endif
void _q_collapseOrExpandDialog();
+#if QT_CONFIG(cups)
+ void updatePpdDuplexOption(QRadioButton *radio);
+#endif
void setupPrinter();
void updateWidgets();
@@ -240,103 +251,12 @@ public:
QDialogButtonBox *buttons;
QPushButton *collapseButton;
QPrinter::OutputFormat printerOutputFormat;
-};
-
-#if QT_CONFIG(cups)
-class QOptionTreeItem
-{
-public:
- enum ItemType { Root, Group, Option, Choice };
-
- QOptionTreeItem(ItemType t, int i, const void *p, QOptionTreeItem *pi)
- : type(t),
- index(i),
- ptr(p),
- parentItem(pi) {}
-
- ~QOptionTreeItem() {
- qDeleteAll(childItems);
- }
-
- ItemType type;
- int index;
- const void *ptr;
- QOptionTreeItem *parentItem;
- QList<QOptionTreeItem*> childItems;
-};
-
-class QOptionTreeItemOption : public QOptionTreeItem
-{
-public:
- QOptionTreeItemOption (int i, const void *p, QOptionTreeItem *pi)
- : QOptionTreeItem(Option, i, p, pi)
- {
- }
-
- // These indices are related to ppd_option_t::choices not to childItems
- int selected;
- int originallySelected;
-};
-
-class QPPDOptionsModel : public QAbstractItemModel
-{
- Q_OBJECT
-
-public:
- explicit QPPDOptionsModel(QPrintDevice *currentPrintDevice, QObject *parent);
-
- int columnCount(const QModelIndex &parent = QModelIndex()) const override;
- int rowCount(const QModelIndex &parent = QModelIndex()) const override;
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
- QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
- QModelIndex parent(const QModelIndex &index) const override;
- Qt::ItemFlags flags(const QModelIndex &index) const override;
- QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const override;
-
- void setCupsOptionsFromItems(QPrinter *printer) const;
- void reject();
- void updateSavedValues();
- void revertToSavedValues();
-
- QPrintDevice *currentPrintDevice() const;
- QTextCodec *cupsCodec() const;
-
- void emitConflictsChanged();
- bool hasConflicts() const;
-
-signals:
- void hasConflictsChanged(bool conflicts);
-
private:
- void parseGroups(QOptionTreeItem *parent);
- void parseOptions(QOptionTreeItem *parent);
- void parseChoices(QOptionTreeItemOption *parent);
-
- void setCupsOptionsFromItems(QPrinter *printer, QOptionTreeItem *parent) const;
- void reject(QOptionTreeItem *item);
- void updateSavedValues(QOptionTreeItem *item);
- void revertToSavedValues(QOptionTreeItem *item);
- void emitDataChanged(QOptionTreeItem *item, const QModelIndex &itemIndex, bool *conflictsFound);
- bool hasConflicts(QOptionTreeItem *item) const;
-
- QPrintDevice *m_currentPrintDevice;
- QTextCodec *m_cupsCodec;
- QOptionTreeItem *m_rootItem;
+ void setExplicitDuplexMode(QPrint::DuplexMode duplexMode);
+ // duplex mode explicitly set by user, QPrint::DuplexAuto otherwise
+ QPrint::DuplexMode explicitDuplexMode;
};
-class QPPDOptionsEditor : public QStyledItemDelegate
-{
- Q_OBJECT
-public:
- explicit QPPDOptionsEditor(QObject *parent) : QStyledItemDelegate(parent) {}
-
- QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
- void setEditorData(QWidget *editor, const QModelIndex &index) const override;
- void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
-};
-
-#endif
-
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
@@ -377,24 +297,15 @@ QPrintPropertiesDialog::QPrintPropertiesDialog(QPrinter *printer, QPrintDevice *
const int advancedTabIndex = widget.tabs->indexOf(widget.cupsPropertiesPage);
#if QT_CONFIG(cups)
- m_cupsOptionsModel = new QPPDOptionsModel(currentPrintDevice, this);
-
- widget.treeView->setItemDelegate(new QPPDOptionsEditor(this));
+ m_currentPrintDevice = currentPrintDevice;
+ const bool anyWidgetCreated = createAdvancedOptionsWidget();
- if (m_cupsOptionsModel->rowCount() > 0) {
- widget.treeView->setModel(m_cupsOptionsModel);
+ widget.tabs->setTabEnabled(advancedTabIndex, anyWidgetCreated);
- for (int i = 0; i < m_cupsOptionsModel->rowCount(); ++i)
- widget.treeView->expand(m_cupsOptionsModel->index(i, 0));
+ connect(widget.pageSetup, &QPageSetupWidget::ppdOptionChanged, this, [this] {
+ widget.conflictsLabel->setVisible(anyPpdOptionConflict());
+ });
- widget.tabs->setTabEnabled(advancedTabIndex, true);
- } else {
- widget.treeView->setModel(nullptr);
- widget.tabs->setTabEnabled(advancedTabIndex, false);
- }
-
- widget.conflictsLabel->setVisible(m_cupsOptionsModel->hasConflicts());
- connect(m_cupsOptionsModel, &QPPDOptionsModel::hasConflictsChanged, widget.conflictsLabel, &QLabel::setVisible);
#else
Q_UNUSED(currentPrintDevice)
widget.tabs->setTabEnabled(advancedTabIndex, false);
@@ -420,16 +331,10 @@ void QPrintPropertiesDialog::setupPrinter() const
// Set Color by default, that will change if the "ColorModel" property is available
m_printer->setColorMode(QPrinter::Color);
- m_cupsOptionsModel->setCupsOptionsFromItems(m_printer);
+ setPrinterAdvancedCupsOptions();
#endif
}
-void QPrintPropertiesDialog::showEvent(QShowEvent *event)
-{
- widget.treeView->resizeColumnToContents(0);
- QDialog::showEvent(event);
-}
-
void QPrintPropertiesDialog::reject()
{
widget.pageSetup->revertToSavedValues();
@@ -439,7 +344,7 @@ void QPrintPropertiesDialog::reject()
#endif
#if QT_CONFIG(cups)
- m_cupsOptionsModel->revertToSavedValues();
+ revertAdvancedOptionsToSavedValues();
#endif
QDialog::reject();
}
@@ -447,7 +352,14 @@ void QPrintPropertiesDialog::reject()
void QPrintPropertiesDialog::accept()
{
#if QT_CONFIG(cups)
- if (m_cupsOptionsModel->hasConflicts()) {
+ if (widget.pageSetup->hasPpdConflict()) {
+ widget.tabs->setCurrentWidget(widget.tabPage);
+ const QMessageBox::StandardButton answer = QMessageBox::warning(this, tr("Page Setup Conflicts"),
+ tr("There are conflicts in page setup options. Do you want to fix them?"),
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+ if (answer != QMessageBox::No)
+ return;
+ } else if (anyAdvancedOptionConflict()) {
widget.tabs->setCurrentWidget(widget.cupsPropertiesPage);
const QMessageBox::StandardButton answer = QMessageBox::warning(this, tr("Advanced Option Conflicts"),
tr("There are conflicts in some advanced options. Do you want to fix them?"),
@@ -455,7 +367,7 @@ void QPrintPropertiesDialog::accept()
if (answer != QMessageBox::No)
return;
}
- m_cupsOptionsModel->updateSavedValues();
+ advancedOptionsUpdateSavedValues();
#endif
#if QT_CONFIG(cupsjobwidget)
@@ -467,6 +379,224 @@ void QPrintPropertiesDialog::accept()
QDialog::accept();
}
+void QPrintPropertiesDialog::showEvent(QShowEvent *event)
+{
+#if QT_CONFIG(cups)
+ widget.conflictsLabel->setVisible(anyPpdOptionConflict());
+#endif
+ QDialog::showEvent(event);
+}
+
+#if QT_CONFIG(cups)
+
+// Used to store the ppd_option_t for each QComboBox that represents an advanced option
+static const char *ppdOptionProperty = "_q_ppd_option";
+
+// Used to store the originally selected choice index for each QComboBox that represents an advanced option
+static const char *ppdOriginallySelectedChoiceProperty = "_q_ppd_originally_selected_choice";
+
+// Used to store the warning label pointer for each QComboBox that represents an advanced option
+static const char *warningLabelProperty = "_q_warning_label";
+
+static bool isBlacklistedGroup(const ppd_group_t *group) Q_DECL_NOTHROW
+{
+ return qstrcmp(group->name, "InstallableOptions") == 0;
+};
+
+static bool isBlacklistedOption(const char *keyword) Q_DECL_NOTHROW
+{
+ // We already let the user set these options elsewhere
+ const char *cupsOptionBlacklist[] = {
+ "Collate",
+ "Copies",
+ "OutputOrder",
+ "PageRegion",
+ "PageSize",
+ "Duplex" // handled by the main dialog
+ };
+ auto equals = [](const char *keyword) {
+ return [keyword](const char *candidate) {
+ return qstrcmp(keyword, candidate) == 0;
+ };
+ };
+ return std::any_of(std::begin(cupsOptionBlacklist), std::end(cupsOptionBlacklist), equals(keyword));
+};
+
+bool QPrintPropertiesDialog::createAdvancedOptionsWidget()
+{
+ bool anyWidgetCreated = false;
+
+ ppd_file_t *ppd = m_currentPrintDevice->property(PDPK_PpdFile).value<ppd_file_t*>();
+
+ if (ppd) {
+ m_cupsCodec = QTextCodec::codecForName(ppd->lang_encoding);
+
+ QWidget *holdingWidget = new QWidget();
+ QVBoxLayout *layout = new QVBoxLayout(holdingWidget);
+
+ for (int i = 0; i < ppd->num_groups; ++i) {
+ const ppd_group_t *group = &ppd->groups[i];
+
+ if (!isBlacklistedGroup(group)) {
+ QFormLayout *groupLayout = new QFormLayout();
+
+ for (int i = 0; i < group->num_options; ++i) {
+ const ppd_option_t *option = &group->options[i];
+
+ if (!isBlacklistedOption(option->keyword)) {
+ QComboBox *choicesCb = new QComboBox();
+
+ const auto setPpdOptionFromCombo = [this, choicesCb, option] {
+ // We can't use choicesCb->currentIndex() to know the index of the option in the choices[] array
+ // because some of them may not be present in the list because they conflict with the
+ // installable options so use the index passed on addItem
+ const int selectedChoiceIndex = choicesCb->currentData().toInt();
+ const auto values = QStringList{} << QString::fromLatin1(option->keyword)
+ << QString::fromLatin1(option->choices[selectedChoiceIndex].choice);
+ m_currentPrintDevice->setProperty(PDPK_PpdOption, values);
+ widget.conflictsLabel->setVisible(anyPpdOptionConflict());
+ };
+
+ bool foundMarkedChoice = false;
+ bool markedChoiceNotAvailable = false;
+ for (int i = 0; i < option->num_choices; ++i) {
+ const ppd_choice_t *choice = &option->choices[i];
+ const auto values = QStringList{} << QString::fromLatin1(option->keyword) << QString::fromLatin1(choice->choice);
+ const bool choiceIsInstallableConflict = m_currentPrintDevice->isFeatureAvailable(PDPK_PpdChoiceIsInstallableConflict, values);
+ if (choiceIsInstallableConflict && static_cast<int>(choice->marked) == 1) {
+ markedChoiceNotAvailable = true;
+ } else if (!choiceIsInstallableConflict) {
+ choicesCb->addItem(m_cupsCodec->toUnicode(choice->text), i);
+ if (static_cast<int>(choice->marked) == 1) {
+ choicesCb->setCurrentIndex(choicesCb->count() - 1);
+ choicesCb->setProperty(ppdOriginallySelectedChoiceProperty, QVariant(i));
+ foundMarkedChoice = true;
+ } else if (!foundMarkedChoice && qstrcmp(choice->choice, option->defchoice) == 0) {
+ choicesCb->setCurrentIndex(choicesCb->count() - 1);
+ choicesCb->setProperty(ppdOriginallySelectedChoiceProperty, QVariant(i));
+ }
+ }
+ }
+
+ if (markedChoiceNotAvailable) {
+ // If the user default option is not available because of it conflicting with
+ // the installed options, we need to set the internal ppd value to the value
+ // being shown in the combo
+ setPpdOptionFromCombo();
+ }
+
+ if (choicesCb->count() > 1) {
+
+ connect(choicesCb, QOverload<int>::of(&QComboBox::currentIndexChanged), this, setPpdOptionFromCombo);
+
+ // We need an extra label at the end to show the conflict warning
+ QWidget *choicesCbWithLabel = new QWidget();
+ QHBoxLayout *choicesCbWithLabelLayout = new QHBoxLayout(choicesCbWithLabel);
+ choicesCbWithLabelLayout->setContentsMargins(0, 0, 0, 0);
+ QLabel *warningLabel = new QLabel();
+ choicesCbWithLabelLayout->addWidget(choicesCb);
+ choicesCbWithLabelLayout->addWidget(warningLabel);
+
+ QLabel *optionLabel = new QLabel(m_cupsCodec->toUnicode(option->text));
+ groupLayout->addRow(optionLabel, choicesCbWithLabel);
+ anyWidgetCreated = true;
+ choicesCb->setProperty(ppdOptionProperty, QVariant::fromValue(option));
+ choicesCb->setProperty(warningLabelProperty, QVariant::fromValue(warningLabel));
+ m_advancedOptionsCombos << choicesCb;
+ } else {
+ delete choicesCb;
+ }
+ }
+ }
+
+ if (groupLayout->rowCount() > 0) {
+ QGroupBox *groupBox = new QGroupBox(m_cupsCodec->toUnicode(group->text));
+ groupBox->setLayout(groupLayout);
+ layout->addWidget(groupBox);
+ } else {
+ delete groupLayout;
+ }
+ }
+ }
+
+ layout->addStretch();
+ widget.scrollArea->setWidget(holdingWidget);
+ }
+
+ if (!m_cupsCodec)
+ m_cupsCodec = QTextCodec::codecForLocale();
+
+ return anyWidgetCreated;
+}
+
+void QPrintPropertiesDialog::setPrinterAdvancedCupsOptions() const
+{
+ for (const QComboBox *choicesCb : m_advancedOptionsCombos) {
+ const ppd_option_t *option = choicesCb->property(ppdOptionProperty).value<const ppd_option_t *>();
+
+ // We can't use choicesCb->currentIndex() to know the index of the option in the choices[] array
+ // because some of them may not be present in the list because they conflict with the
+ // installable options so use the index passed on addItem
+ const int selectedChoiceIndex = choicesCb->currentData().toInt();
+ const char *selectedChoice = option->choices[selectedChoiceIndex].choice;
+
+ if (qstrcmp(option->keyword, "ColorModel") == 0)
+ m_printer->setColorMode(qstrcmp(selectedChoice, "Gray") == 0 ? QPrinter::GrayScale : QPrinter::Color);
+
+ if (qstrcmp(option->defchoice, selectedChoice) != 0)
+ QCUPSSupport::setCupsOption(m_printer, QString::fromLatin1(option->keyword), QString::fromLatin1(selectedChoice));
+ }
+}
+
+void QPrintPropertiesDialog::revertAdvancedOptionsToSavedValues() const
+{
+ for (QComboBox *choicesCb : m_advancedOptionsCombos) {
+ const int originallySelectedChoice = choicesCb->property(ppdOriginallySelectedChoiceProperty).value<int>();
+ const int newComboIndexToSelect = choicesCb->findData(originallySelectedChoice);
+ choicesCb->setCurrentIndex(newComboIndexToSelect);
+ // The currentIndexChanged lambda takes care of resetting the ppd option
+ }
+ widget.conflictsLabel->setVisible(anyPpdOptionConflict());
+}
+
+void QPrintPropertiesDialog::advancedOptionsUpdateSavedValues() const
+{
+ for (QComboBox *choicesCb : m_advancedOptionsCombos)
+ choicesCb->setProperty(ppdOriginallySelectedChoiceProperty, choicesCb->currentData());
+}
+
+bool QPrintPropertiesDialog::anyPpdOptionConflict() const
+{
+ // we need to execute both since besides returning true/false they update the warning icons
+ const bool pageSetupConflicts = widget.pageSetup->hasPpdConflict();
+ const bool advancedOptionConflicts = anyAdvancedOptionConflict();
+ return pageSetupConflicts || advancedOptionConflicts;
+}
+
+bool QPrintPropertiesDialog::anyAdvancedOptionConflict() const
+{
+ const QIcon warning = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning, nullptr, nullptr);
+
+ bool anyConflicted = false;
+
+ for (const QComboBox *choicesCb : m_advancedOptionsCombos) {
+ const ppd_option_t *option = choicesCb->property(ppdOptionProperty).value<const ppd_option_t *>();
+ QLabel *warningLabel = choicesCb->property(warningLabelProperty).value<QLabel *>();
+ if (option->conflicted) {
+ anyConflicted = true;
+ const int pixmap_size = choicesCb->sizeHint().height() * .75;
+ warningLabel->setPixmap(warning.pixmap(pixmap_size, pixmap_size));
+ } else {
+ warningLabel->setPixmap(QPixmap());
+ }
+ }
+
+ return anyConflicted;
+}
+
+#endif
+
+
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
@@ -479,7 +609,8 @@ void QPrintPropertiesDialog::accept()
*/
QPrintDialogPrivate::QPrintDialogPrivate()
- : top(nullptr), bottom(nullptr), buttons(nullptr), collapseButton(nullptr)
+ : top(nullptr), bottom(nullptr), buttons(nullptr), collapseButton(nullptr),
+ explicitDuplexMode(QPrint::DuplexAuto)
{
initResources();
}
@@ -540,6 +671,16 @@ void QPrintDialogPrivate::init()
q, SLOT(_q_togglePageSetCombo(bool)));
QObject::connect(collapseButton, SIGNAL(released()), q, SLOT(_q_collapseOrExpandDialog()));
+
+ QObject::connect(options.noDuplex, &QAbstractButton::clicked, q, [this] { setExplicitDuplexMode(QPrint::DuplexNone); });
+ QObject::connect(options.duplexLong, &QAbstractButton::clicked, q, [this] { setExplicitDuplexMode(QPrint::DuplexLongSide); });
+ QObject::connect(options.duplexShort, &QAbstractButton::clicked, q, [this] { setExplicitDuplexMode(QPrint::DuplexShortSide); });
+
+#if QT_CONFIG(cups)
+ QObject::connect(options.noDuplex, &QAbstractButton::toggled, q, [this] { updatePpdDuplexOption(options.noDuplex); });
+ QObject::connect(options.duplexLong, &QAbstractButton::toggled, q, [this] { updatePpdDuplexOption(options.duplexLong); });
+ QObject::connect(options.duplexShort, &QAbstractButton::toggled, q, [this] { updatePpdDuplexOption(options.duplexShort); });
+#endif
}
// initialize printer options
@@ -559,13 +700,20 @@ void QPrintDialogPrivate::selectPrinter(const QPrinter::OutputFormat outputForma
else
options.grayscale->setChecked(true);
- switch (p->duplex()) {
- case QPrinter::DuplexNone:
+ // keep duplex value explicitly set by user, if any, and selected printer supports it;
+ // use device default otherwise
+ QPrint::DuplexMode duplex;
+ if (explicitDuplexMode != QPrint::DuplexAuto && supportedDuplexMode.contains(explicitDuplexMode))
+ duplex = explicitDuplexMode;
+ else
+ duplex = top->d->m_currentPrintDevice.defaultDuplexMode();
+ switch (duplex) {
+ case QPrint::DuplexNone:
options.noDuplex->setChecked(true); break;
- case QPrinter::DuplexLongSide:
- case QPrinter::DuplexAuto:
+ case QPrint::DuplexLongSide:
+ case QPrint::DuplexAuto:
options.duplexLong->setChecked(true); break;
- case QPrinter::DuplexShortSide:
+ case QPrint::DuplexShortSide:
options.duplexShort->setChecked(true); break;
}
options.copies->setValue(p->copyCount());
@@ -665,8 +813,26 @@ static bool isValidPagesString(const QString &pagesString) Q_DECL_NOTHROW
auto pagesRanges = pageRangesFromString(pagesString);
return !pagesRanges.empty();
}
+
+void QPrintDialogPrivate::updatePpdDuplexOption(QRadioButton *radio)
+{
+ const bool checked = radio->isChecked();
+ if (checked) {
+ if (radio == options.noDuplex) top->d->setPpdDuplex(QPrinter::DuplexNone);
+ else if (radio == options.duplexLong) top->d->setPpdDuplex(QPrinter::DuplexLongSide);
+ else if (radio == options.duplexShort) top->d->setPpdDuplex(QPrinter::DuplexShortSide);
+ }
+ const bool conflict = checked && top->d->m_duplexPpdOption && top->d->m_duplexPpdOption->conflicted;
+ radio->setIcon(conflict ? QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning, nullptr, nullptr) : QIcon());
+}
+
#endif
+void QPrintDialogPrivate::setExplicitDuplexMode(const QPrint::DuplexMode duplexMode)
+{
+ explicitDuplexMode = duplexMode;
+}
+
void QPrintDialogPrivate::setupPrinter()
{
// First setup the requested OutputFormat, Printer and Page Size first
@@ -931,6 +1097,13 @@ void QPrintDialog::accept()
QMessageBox::Ok, QMessageBox::Ok);
return;
}
+ if (d->top->d->m_duplexPpdOption && d->top->d->m_duplexPpdOption->conflicted) {
+ const QMessageBox::StandardButton answer = QMessageBox::warning(this, tr("Duplex Settings Conflicts"),
+ tr("There are conflicts in duplex settings. Do you want to fix them?"),
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
+ if (answer != QMessageBox::No)
+ return;
+ }
#endif
d->setupPrinter();
QDialog::accept();
@@ -952,8 +1125,11 @@ void QPrintDialog::accept()
/*! \internal
*/
QUnixPrintWidgetPrivate::QUnixPrintWidgetPrivate(QUnixPrintWidget *p, QPrinter *prn)
- : parent(p), propertiesDialog(nullptr), printer(prn), optionsPane(0),
- filePrintersAdded(false)
+ : parent(p), propertiesDialog(nullptr), printer(prn),
+#if QT_CONFIG(cups)
+ m_duplexPpdOption(nullptr),
+#endif
+ optionsPane(nullptr), filePrintersAdded(false)
{
q = nullptr;
if (parent)
@@ -1043,6 +1219,10 @@ void QUnixPrintWidgetPrivate::_q_printerChanged(int index)
propertiesDialog = nullptr;
}
+#if QT_CONFIG(cups)
+ m_duplexPpdOption = nullptr;
+#endif
+
if (filePrintersAdded) {
Q_ASSERT(index != printerCount - 2); // separator
if (index == printerCount - 1) { // PDF
@@ -1077,6 +1257,10 @@ void QUnixPrintWidgetPrivate::_q_printerChanged(int index)
if (optionsPane)
optionsPane->selectPrinter(QPrinter::NativeFormat);
}
+
+#if QT_CONFIG(cups)
+ m_duplexPpdOption = QCUPSSupport::findPpdOption("Duplex", &m_currentPrintDevice);
+#endif
}
void QUnixPrintWidgetPrivate::setOptionsPane(QPrintDialogPrivate *pane)
@@ -1172,11 +1356,30 @@ void QUnixPrintWidgetPrivate::setupPrinterProperties()
propertiesDialog = new QPrintPropertiesDialog(q->printer(), &m_currentPrintDevice, outputFormat, printerName, q);
}
+#if QT_CONFIG(cups)
+void QUnixPrintWidgetPrivate::setPpdDuplex(QPrinter::DuplexMode mode)
+{
+ auto values = QStringList{} << QStringLiteral("Duplex");
+ if (mode == QPrinter::DuplexNone) values << QStringLiteral("None");
+ else if (mode == QPrinter::DuplexLongSide) values << QStringLiteral("DuplexNoTumble");
+ else if (mode == QPrinter::DuplexShortSide) values << QStringLiteral("DuplexTumble");
+
+ m_currentPrintDevice.setProperty(PDPK_PpdOption, values);
+}
+#endif
+
void QUnixPrintWidgetPrivate::_q_btnPropertiesClicked()
{
if (!propertiesDialog)
setupPrinterProperties();
propertiesDialog->exec();
+
+#if QT_CONFIG(cups)
+ // update the warning icon on the duplex options if needed
+ optionsPane->updatePpdDuplexOption(optionsPane->options.noDuplex);
+ optionsPane->updatePpdDuplexOption(optionsPane->options.duplexLong);
+ optionsPane->updatePpdDuplexOption(optionsPane->options.duplexShort);
+#endif
}
void QUnixPrintWidgetPrivate::setupPrinter()
@@ -1262,436 +1465,8 @@ void QUnixPrintWidget::updatePrinter()
d->setupPrinter();
}
-////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////
-
-/*
-
- QPPDOptionsModel
-
- Holds the PPD Options for the printer.
-
-*/
-
#if QT_CONFIG(cups)
-static bool isBlacklistedGroup(ppd_group_t *group) Q_DECL_NOTHROW
-{
- return qstrcmp(group->name, "InstallableOptions") == 0;
-};
-
-QPPDOptionsModel::QPPDOptionsModel(QPrintDevice *currentPrintDevice, QObject *parent)
- : QAbstractItemModel(parent)
- , m_currentPrintDevice(currentPrintDevice)
- , m_cupsCodec(nullptr)
-{
- ppd_file_t *ppd = m_currentPrintDevice->property(PDPK_PpdFile).value<ppd_file_t*>();
- m_rootItem = new QOptionTreeItem(QOptionTreeItem::Root, 0, ppd, nullptr);
-
- if (ppd) {
- m_cupsCodec = QTextCodec::codecForName(ppd->lang_encoding);
- for (int i = 0; i < ppd->num_groups; ++i) {
- if (!isBlacklistedGroup(&ppd->groups[i])) {
- QOptionTreeItem *group = new QOptionTreeItem(QOptionTreeItem::Group, i, &ppd->groups[i], m_rootItem);
- m_rootItem->childItems.append(group);
- parseGroups(group); // parse possible subgroups
- parseOptions(group); // parse options
- }
- }
- }
-
- if (!m_cupsCodec)
- m_cupsCodec = QTextCodec::codecForLocale();
-}
-
-int QPPDOptionsModel::columnCount(const QModelIndex &) const
-{
- return 2;
-}
-
-int QPPDOptionsModel::rowCount(const QModelIndex &parent) const
-{
- QOptionTreeItem *itm;
- if (!parent.isValid())
- itm = m_rootItem;
- else
- itm = static_cast<QOptionTreeItem*>(parent.internalPointer());
-
- if (itm->type == QOptionTreeItem::Option)
- return 0;
-
- return itm->childItems.count();
-}
-
-QVariant QPPDOptionsModel::data(const QModelIndex &index, int role) const
-{
- if (!index.isValid())
- return QVariant();
-
- QOptionTreeItem *itm = static_cast<QOptionTreeItem*>(index.internalPointer());
-
- switch (role) {
- case Qt::FontRole: {
- if (itm->type == QOptionTreeItem::Group){
- QFont font;
- font.setBold(true);
- return QVariant(font);
- }
- return QVariant();
- }
- break;
-
- case Qt::DisplayRole: {
- if (index.column() == 0) {
- if (itm->type == QOptionTreeItem::Option) {
- const ppd_option_t *option = static_cast<const ppd_option_t*>(itm->ptr);
- return m_cupsCodec->toUnicode(option->text);
- } else if (itm->type == QOptionTreeItem::Group) {
- const ppd_group_t *group = static_cast<const ppd_group_t*>(itm->ptr);
- return m_cupsCodec->toUnicode(group->text);
- }
- } else if (itm->type == QOptionTreeItem::Option) {
- QOptionTreeItemOption *itmOption = static_cast<QOptionTreeItemOption *>(itm);
- const ppd_option_t *option = static_cast<const ppd_option_t*>(itm->ptr);
- if (itmOption->selected > -1)
- return m_cupsCodec->toUnicode(option->choices[itmOption->selected].text);
- }
-
- return QVariant();
- }
- break;
-
- case Qt::DecorationRole: {
- if (itm->type == QOptionTreeItem::Option && index.column() == 1) {
- const ppd_option_t *option = static_cast<const ppd_option_t*>(itm->ptr);
- if (option->conflicted) {
- const QIcon warning = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning, nullptr, nullptr);
- if (!warning.isNull())
- return warning;
-
- qWarning() << "Current application style returned a null icon for SP_MessageBoxWarning.";
- return QColor(Qt::red);
- }
- }
- return QVariant();
- }
- break;
-
- }
-
- return QVariant();
-}
-
-QModelIndex QPPDOptionsModel::index(int row, int column, const QModelIndex &parent) const
-{
- QOptionTreeItem *itm;
- if (!parent.isValid())
- itm = m_rootItem;
- else
- itm = static_cast<QOptionTreeItem*>(parent.internalPointer());
-
- return createIndex(row, column, itm->childItems.at(row));
-}
-
-
-QModelIndex QPPDOptionsModel::parent(const QModelIndex &index) const
-{
- if (!index.isValid())
- return QModelIndex();
-
- QOptionTreeItem *itm = static_cast<QOptionTreeItem*>(index.internalPointer());
-
- if (itm->parentItem && itm->parentItem != m_rootItem)
- return createIndex(itm->parentItem->index, 0, itm->parentItem);
-
- return QModelIndex();
-}
-
-Qt::ItemFlags QPPDOptionsModel::flags(const QModelIndex &index) const
-{
- if (!index.isValid() || static_cast<QOptionTreeItem*>(index.internalPointer())->type == QOptionTreeItem::Group)
- return Qt::ItemIsEnabled;
-
- if (index.column() == 1)
- return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
-
- return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
-}
-
-QPrintDevice *QPPDOptionsModel::currentPrintDevice() const
-{
- return m_currentPrintDevice;
-}
-
-QTextCodec *QPPDOptionsModel::cupsCodec() const
-{
- return m_cupsCodec;
-}
-
-void QPPDOptionsModel::setCupsOptionsFromItems(QPrinter *printer) const
-{
- setCupsOptionsFromItems(printer, m_rootItem);
-}
-
-void QPPDOptionsModel::setCupsOptionsFromItems(QPrinter *printer, QOptionTreeItem *parent) const
-{
- for (QOptionTreeItem *itm : qAsConst(parent->childItems)) {
- if (itm->type == QOptionTreeItem::Option) {
- QOptionTreeItemOption *itmOption = static_cast<QOptionTreeItemOption *>(itm);
- const ppd_option_t *opt = static_cast<const ppd_option_t*>(itm->ptr);
-
- if (qstrcmp(opt->keyword, "ColorModel") == 0)
- printer->setColorMode(qstrcmp(opt->choices[itmOption->selected].choice, "Gray") == 0 ? QPrinter::GrayScale : QPrinter::Color);
-
- if (qstrcmp(opt->defchoice, opt->choices[itmOption->selected].choice) != 0) {
- QCUPSSupport::setCupsOption(printer, QString::fromLatin1(opt->keyword), QString::fromLatin1(opt->choices[itmOption->selected].choice));
- }
- } else {
- setCupsOptionsFromItems(printer, itm);
- }
- }
-}
-
-void QPPDOptionsModel::parseGroups(QOptionTreeItem *parent)
-{
- const ppd_group_t *group = static_cast<const ppd_group_t*>(parent->ptr);
-
- if (group) {
- for (int i = 0; i < group->num_subgroups; ++i) {
- if (!isBlacklistedGroup(&group->subgroups[i])) {
- QOptionTreeItem *subgroup = new QOptionTreeItem(QOptionTreeItem::Group, i, &group->subgroups[i], parent);
- parent->childItems.append(subgroup);
- parseGroups(subgroup); // parse possible subgroups
- parseOptions(subgroup); // parse options
- }
- }
- }
-}
-
-static bool isBlacklistedOption(const char *keyword) Q_DECL_NOTHROW
-{
- // We already let the user set these options elsewhere
- const char *cupsOptionBlacklist[] = {
- "Collate",
- "Copies",
- "OutputOrder",
- "PageRegion",
- "PageSize",
- "Duplex" // handled by the main dialog
- };
- auto equals = [](const char *keyword) {
- return [keyword](const char *candidate) {
- return qstrcmp(keyword, candidate) == 0;
- };
- };
- return std::any_of(std::begin(cupsOptionBlacklist), std::end(cupsOptionBlacklist), equals(keyword));
-};
-
-void QPPDOptionsModel::parseOptions(QOptionTreeItem *parent)
-{
- const ppd_group_t *group = static_cast<const ppd_group_t*>(parent->ptr);
- for (int i = 0; i < group->num_options; ++i) {
- if (!isBlacklistedOption(group->options[i].keyword)) {
- QOptionTreeItemOption *opt = new QOptionTreeItemOption(i, &group->options[i], parent);
- parseChoices(opt);
-
- // Don't show options that are actually not options at all
- // because they don't give the user any choice
- if (opt->childItems.count() > 1)
- parent->childItems.append(opt);
- else
- delete opt;
- }
- }
-}
-
-void QPPDOptionsModel::parseChoices(QOptionTreeItemOption *parent)
-{
- const ppd_option_t *option = static_cast<const ppd_option_t*>(parent->ptr);
- bool marked = false;
- for (int i = 0; i < option->num_choices; ++i) {
- const auto values = QStringList{} << QString::fromLatin1(option->keyword) << QString::fromLatin1(option->choices[i].choice);
- if (!m_currentPrintDevice->isFeatureAvailable(PDPK_PpdChoiceIsInstallableConflict, values)) {
- QOptionTreeItem *choice = new QOptionTreeItem(QOptionTreeItem::Choice, i, &option->choices[i], parent);
- if (static_cast<int>(option->choices[i].marked) == 1) {
- parent->selected = i;
- marked = true;
- } else if (!marked && qstrcmp(option->choices[i].choice, option->defchoice) == 0) {
- parent->selected = i;
- }
- parent->originallySelected = parent->selected;
- parent->childItems.append(choice);
- }
- }
-}
-
-bool QPPDOptionsModel::hasConflicts() const
-{
- return hasConflicts(m_rootItem);
-}
-
-bool QPPDOptionsModel::hasConflicts(QOptionTreeItem *item) const
-{
- if (item->type == QOptionTreeItem::Option) {
- const ppd_option_t *option = static_cast<const ppd_option_t*>(item->ptr);
- return option->conflicted;
- }
-
- for (QOptionTreeItem *child : qAsConst(item->childItems)) {
- if (hasConflicts(child))
- return true;
- }
-
- return false;
-}
-
-void QPPDOptionsModel::emitConflictsChanged()
-{
- bool conflictsFound = false;
- emitDataChanged(m_rootItem, QModelIndex(), &conflictsFound);
-
- emit hasConflictsChanged(conflictsFound);
-}
-
-void QPPDOptionsModel::emitDataChanged(QOptionTreeItem *item, const QModelIndex &itemIndex, bool *conflictsFound)
-{
- if (item->type == QOptionTreeItem::Option) {
- // We just emit DecorationRole dataChanged for all the leaves
- // and let the view requery the value
- const QModelIndex secondColItem = index(itemIndex.row(), 1, itemIndex.parent());
- emit dataChanged(secondColItem, secondColItem, QVector<int>() << Qt::DecorationRole);
-
- if (conflictsFound && *conflictsFound == false) {
- const ppd_option_t *option = static_cast<const ppd_option_t*>(item->ptr);
- if (option->conflicted && conflictsFound)
- *conflictsFound = true;
- }
- }
-
- for (int i = 0; i < item->childItems.count(); ++i) {
- QOptionTreeItem *child = item->childItems.at(i);
- emitDataChanged(child, index(i, 0, itemIndex), conflictsFound);
- }
-}
-
-QVariant QPPDOptionsModel::headerData(int section, Qt::Orientation, int role) const
-{
- if (role != Qt::DisplayRole)
- return QVariant();
-
- switch (section) {
- case 0:
- return QVariant(tr("Name"));
- case 1:
- return QVariant(tr("Value"));
- }
-
- return QVariant();
-}
-
-void QPPDOptionsModel::revertToSavedValues()
-{
- revertToSavedValues(m_rootItem);
- emitConflictsChanged();
-}
-
-void QPPDOptionsModel::revertToSavedValues(QOptionTreeItem *item)
-{
- if (item->type == QOptionTreeItem::Option) {
- QOptionTreeItemOption *itemOption = static_cast<QOptionTreeItemOption *>(item);
-
- const ppd_option_t *option = static_cast<const ppd_option_t*>(item->ptr);
- const char *choice = itemOption->originallySelected != -1 ? option->choices[itemOption->originallySelected].choice
- : option->defchoice;
- const auto values = QStringList{} << QString::fromLatin1(option->keyword) << QString::fromLatin1(choice);
- m_currentPrintDevice->setProperty(PDPK_PpdOption, values);
- itemOption->selected = itemOption->originallySelected;
- }
-
- for (QOptionTreeItem *child : qAsConst(item->childItems))
- revertToSavedValues(child);
-}
-
-void QPPDOptionsModel::updateSavedValues()
-{
- updateSavedValues(m_rootItem);
-}
-
-void QPPDOptionsModel::updateSavedValues(QOptionTreeItem *item)
-{
- if (item->type == QOptionTreeItem::Option) {
- QOptionTreeItemOption *itemOption = static_cast<QOptionTreeItemOption *>(item);
- itemOption->originallySelected = itemOption->selected;
- }
-
- for (QOptionTreeItem *child : qAsConst(item->childItems))
- updateSavedValues(child);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////
-
-/*
-
- QPPDOptionsEditor
-
- Edits the PPD Options for the printer.
-
-*/
-
-QWidget *QPPDOptionsEditor::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
-{
- Q_UNUSED(option)
-
- if (index.column() == 1 && static_cast<QOptionTreeItem*>(index.internalPointer())->type == QOptionTreeItem::Option)
- return new QComboBox(parent);
-
- return nullptr;
-}
-
-void QPPDOptionsEditor::setEditorData(QWidget *editor, const QModelIndex &index) const
-{
- if (index.column() != 1)
- return;
-
- QComboBox *cb = static_cast<QComboBox*>(editor);
- QOptionTreeItemOption *itm = static_cast<QOptionTreeItemOption*>(index.internalPointer());
-
- if (itm->selected == -1)
- cb->addItem(QString());
-
- const QPPDOptionsModel *m = static_cast<const QPPDOptionsModel*>(index.model());
- for (auto *childItem : qAsConst(itm->childItems)) {
- const ppd_choice_t *choice = static_cast<const ppd_choice_t*>(childItem->ptr);
- cb->addItem(m->cupsCodec()->toUnicode(choice->text), childItem->index);
- if (childItem->index == itm->selected)
- cb->setCurrentIndex(cb->count() - 1);
- }
-}
-
-void QPPDOptionsEditor::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
-{
- QComboBox *cb = static_cast<QComboBox*>(editor);
- QOptionTreeItemOption *itm = static_cast<QOptionTreeItemOption*>(index.internalPointer());
-
- // We can't use cb->currentIndex() to know the index of the option in the choices[] array
- // because some of them may not be present in the list because they conflict with the
- // installable options so use the index passed on addItem
- const int selectedChoiceIndex = cb->currentData().toInt();
-
- if (itm->selected == selectedChoiceIndex || selectedChoiceIndex < 0)
- return;
-
- const ppd_option_t *opt = static_cast<const ppd_option_t*>(itm->ptr);
- QPPDOptionsModel *m = static_cast<QPPDOptionsModel*>(model);
-
- const auto values = QStringList{} << QString::fromLatin1(opt->keyword) << QString::fromLatin1(opt->choices[selectedChoiceIndex].choice);
- m->currentPrintDevice()->setProperty(PDPK_PpdOption, values);
- itm->selected = selectedChoiceIndex;
-
- m->emitConflictsChanged();
-}
-
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
diff --git a/src/printsupport/dialogs/qprintpreviewdialog.cpp b/src/printsupport/dialogs/qprintpreviewdialog.cpp
index a4f721fbc8..418bc47a59 100644
--- a/src/printsupport/dialogs/qprintpreviewdialog.cpp
+++ b/src/printsupport/dialogs/qprintpreviewdialog.cpp
@@ -573,8 +573,11 @@ void QPrintPreviewDialogPrivate::_q_print()
if (printer->outputFormat() != QPrinter::NativeFormat) {
QString title = QCoreApplication::translate("QPrintPreviewDialog", "Export to PDF");
QString suffix = QLatin1String(".pdf");
- QString fileName = QFileDialog::getSaveFileName(q, title, printer->outputFileName(),
+ QString fileName;
+#if QT_CONFIG(filedialog)
+ fileName = QFileDialog::getSaveFileName(q, title, printer->outputFileName(),
QLatin1Char('*') + suffix);
+#endif
if (!fileName.isEmpty()) {
if (QFileInfo(fileName).suffix().isEmpty())
fileName.append(suffix);
diff --git a/src/printsupport/dialogs/qprintpropertieswidget.ui b/src/printsupport/dialogs/qprintpropertieswidget.ui
index d8e526139b..c2b4836d26 100644
--- a/src/printsupport/dialogs/qprintpropertieswidget.ui
+++ b/src/printsupport/dialogs/qprintpropertieswidget.ui
@@ -47,60 +47,74 @@
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
- <widget class="QTreeView" name="treeView">
- <property name="alternatingRowColors">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="conflictsLabel">
- <property name="palette">
- <palette>
- <active>
- <colorrole role="WindowText">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>255</red>
- <green>0</green>
- <blue>0</blue>
- </color>
- </brush>
- </colorrole>
- </active>
- <inactive>
- <colorrole role="WindowText">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>255</red>
- <green>0</green>
- <blue>0</blue>
- </color>
- </brush>
- </colorrole>
- </inactive>
- <disabled>
- <colorrole role="WindowText">
- <brush brushstyle="SolidPattern">
- <color alpha="255">
- <red>165</red>
- <green>167</green>
- <blue>169</blue>
- </color>
- </brush>
- </colorrole>
- </disabled>
- </palette>
+ <widget class="QScrollArea" name="scrollArea">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
</property>
- <property name="text">
- <string>There are conflicts in some options. Please fix them.</string>
+ <property name="widgetResizable">
+ <bool>true</bool>
</property>
+ <widget class="QWidget" name="scrollAreaWidgetContents">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>376</width>
+ <height>217</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout"/>
+ </widget>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
+ <item>
+ <widget class="QLabel" name="conflictsLabel">
+ <property name="palette">
+ <palette>
+ <active>
+ <colorrole role="WindowText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </active>
+ <inactive>
+ <colorrole role="WindowText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </inactive>
+ <disabled>
+ <colorrole role="WindowText">
+ <brush brushstyle="SolidPattern">
+ <color alpha="255">
+ <red>165</red>
+ <green>167</green>
+ <blue>169</blue>
+ </color>
+ </brush>
+ </colorrole>
+ </disabled>
+ </palette>
+ </property>
+ <property name="text">
+ <string>There are conflicts in some options. Please fix them.</string>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
<customwidgets>
diff --git a/src/printsupport/kernel/qcups.cpp b/src/printsupport/kernel/qcups.cpp
index 7e8e1707b2..8505e8356c 100644
--- a/src/printsupport/kernel/qcups.cpp
+++ b/src/printsupport/kernel/qcups.cpp
@@ -39,6 +39,7 @@
#include "qcups_p.h"
+#include "qprintdevice_p.h"
#include "qprintengine.h"
QT_BEGIN_NAMESPACE
@@ -146,6 +147,25 @@ QCUPSSupport::JobHoldUntilWithTime QCUPSSupport::parseJobHoldUntil(const QString
return { QCUPSSupport::NoHold, QTime() };
}
+ppd_option_t *QCUPSSupport::findPpdOption(const char *optionName, QPrintDevice *printDevice)
+{
+ ppd_file_t *ppd = printDevice->property(PDPK_PpdFile).value<ppd_file_t*>();
+
+ if (ppd) {
+ for (int i = 0; i < ppd->num_groups; ++i) {
+ ppd_group_t *group = &ppd->groups[i];
+
+ for (int i = 0; i < group->num_options; ++i) {
+ ppd_option_t *option = &group->options[i];
+
+ if (qstrcmp(option->keyword, optionName) == 0)
+ return option;
+ }
+ }
+ }
+
+ return nullptr;
+}
void QCUPSSupport::setJobHold(QPrinter *printer, const JobHoldUntil jobHold, const QTime &holdUntilTime)
{
diff --git a/src/printsupport/kernel/qcups_p.h b/src/printsupport/kernel/qcups_p.h
index 9a71483bb9..57ec281383 100644
--- a/src/printsupport/kernel/qcups_p.h
+++ b/src/printsupport/kernel/qcups_p.h
@@ -52,6 +52,7 @@
//
#include <QtPrintSupport/private/qtprintsupportglobal_p.h>
+#include <QtPrintSupport/private/qprint_p.h>
#include "QtCore/qstring.h"
#include "QtCore/qstringlist.h"
#include "QtPrintSupport/qprinter.h"
@@ -61,6 +62,8 @@ QT_REQUIRE_CONFIG(cups);
QT_BEGIN_NAMESPACE
+class QPrintDevice;
+
// HACK! Define these here temporarily so they can be used in the dialogs
// without a circular reference to QCupsPrintEngine in the plugin.
// Move back to qcupsprintengine_p.h in the plugin once all usage
@@ -163,6 +166,8 @@ public:
QTime time;
};
static JobHoldUntilWithTime parseJobHoldUntil(const QString &jobHoldUntil);
+
+ static ppd_option_t *findPpdOption(const char *optionName, QPrintDevice *printDevice);
};
Q_DECLARE_TYPEINFO(QCUPSSupport::JobHoldUntil, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(QCUPSSupport::BannerPage, Q_PRIMITIVE_TYPE);
diff --git a/src/printsupport/kernel/qplatformprintdevice.cpp b/src/printsupport/kernel/qplatformprintdevice.cpp
index 8c905889db..69d984cb0c 100644
--- a/src/printsupport/kernel/qplatformprintdevice.cpp
+++ b/src/printsupport/kernel/qplatformprintdevice.cpp
@@ -50,23 +50,6 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_PRINTER
-QPlatformPrintDevice::QPlatformPrintDevice()
- : m_isRemote(false),
- m_supportsMultipleCopies(false),
- m_supportsCollateCopies(false),
- m_havePageSizes(false),
- m_supportsCustomPageSizes(false),
- m_haveResolutions(false),
- m_haveInputSlots(false),
- m_haveOutputBins(false),
- m_haveDuplexModes(false),
- m_haveColorModes(false)
-#if QT_CONFIG(mimetype)
- , m_haveMimeTypes(false)
-#endif
-{
-}
-
QPlatformPrintDevice::QPlatformPrintDevice(const QString &id)
: m_id(id),
m_isRemote(false),
@@ -247,6 +230,10 @@ QPageSize QPlatformPrintDevice::supportedPageSize(const QSizeF &size, QPageSize:
QPageSize QPlatformPrintDevice::supportedPageSizeMatch(const QPageSize &pageSize) const
{
+ // If it's a known page size, just return itself
+ if (m_pageSizes.contains(pageSize))
+ return pageSize;
+
// Try to find a supported page size based on point size
for (const QPageSize &ps : m_pageSizes) {
if (ps.sizePoints() == pageSize.sizePoints())
diff --git a/src/printsupport/kernel/qplatformprintdevice.h b/src/printsupport/kernel/qplatformprintdevice.h
index 76f03dea7e..64723db92e 100644
--- a/src/printsupport/kernel/qplatformprintdevice.h
+++ b/src/printsupport/kernel/qplatformprintdevice.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2014 John Layt <jlayt@kde.org>
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtPrintSupport module of the Qt Toolkit.
@@ -71,8 +72,7 @@ class Q_PRINTSUPPORT_EXPORT QPlatformPrintDevice
{
Q_DISABLE_COPY(QPlatformPrintDevice)
public:
- QPlatformPrintDevice();
- explicit QPlatformPrintDevice(const QString &id);
+ explicit QPlatformPrintDevice(const QString &id = QString());
virtual ~QPlatformPrintDevice();
virtual QString id() const;
@@ -154,16 +154,16 @@ protected:
bool m_isRemote;
- bool m_supportsMultipleCopies;
- bool m_supportsCollateCopies;
+ mutable bool m_supportsMultipleCopies;
+ mutable bool m_supportsCollateCopies;
mutable bool m_havePageSizes;
mutable QList<QPageSize> m_pageSizes;
- bool m_supportsCustomPageSizes;
+ mutable bool m_supportsCustomPageSizes;
- QSize m_minimumPhysicalPageSize;
- QSize m_maximumPhysicalPageSize;
+ mutable QSize m_minimumPhysicalPageSize;
+ mutable QSize m_maximumPhysicalPageSize;
mutable bool m_haveResolutions;
mutable QList<int> m_resolutions;
diff --git a/src/printsupport/kernel/qprintengine_pdf.cpp b/src/printsupport/kernel/qprintengine_pdf.cpp
index 0230ebddc8..3c24e5ac69 100644
--- a/src/printsupport/kernel/qprintengine_pdf.cpp
+++ b/src/printsupport/kernel/qprintengine_pdf.cpp
@@ -132,6 +132,8 @@ void QPdfPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va
// The following keys are settings that are unsupported by the PDF PrintEngine
case PPK_CustomBase:
break;
+ case PPK_Duplex:
+ break;
// The following keys are properties and settings that are supported by the PDF PrintEngine
case PPK_CollateCopies:
@@ -203,9 +205,6 @@ void QPdfPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va
case PPK_FontEmbedding:
d->embedFonts = value.toBool();
break;
- case PPK_Duplex:
- d->duplex = static_cast<QPrint::DuplexMode>(value.toInt());
- break;
case PPK_CustomPaperSize:
d->m_pageLayout.setPageSize(QPageSize(value.toSizeF(), QPageSize::Point));
break;
@@ -249,6 +248,7 @@ QVariant QPdfPrintEngine::property(PrintEnginePropertyKey key) const
// The following keys are settings that are unsupported by the PDF PrintEngine
// Return sensible default values to ensure consistent behavior across platforms
case PPK_CustomBase:
+ case PPK_Duplex:
// Special case, leave null
break;
@@ -322,9 +322,6 @@ QVariant QPdfPrintEngine::property(PrintEnginePropertyKey key) const
case PPK_FontEmbedding:
ret = d->embedFonts;
break;
- case PPK_Duplex:
- ret = d->duplex;
- break;
case PPK_CustomPaperSize:
ret = d->m_pageLayout.fullRectPoints().size();
break;
@@ -389,7 +386,6 @@ void QPdfPrintEnginePrivate::closePrintDevice()
QPdfPrintEnginePrivate::QPdfPrintEnginePrivate(QPrinter::PrinterMode m)
: QPdfEnginePrivate(),
- duplex(QPrint::DuplexNone),
collate(true),
copies(1),
pageOrder(QPrinter::FirstPageFirst),
diff --git a/src/printsupport/kernel/qprintengine_pdf_p.h b/src/printsupport/kernel/qprintengine_pdf_p.h
index bb01a2e9e1..e7ae21f260 100644
--- a/src/printsupport/kernel/qprintengine_pdf_p.h
+++ b/src/printsupport/kernel/qprintengine_pdf_p.h
@@ -130,7 +130,6 @@ private:
QString printProgram;
QString selectionOption;
- QPrint::DuplexMode duplex;
bool collate;
int copies;
QPrinter::PageOrder pageOrder;
diff --git a/src/printsupport/kernel/qprintengine_win.cpp b/src/printsupport/kernel/qprintengine_win.cpp
index 6f263e5ea8..e3a5c3d2e8 100644
--- a/src/printsupport/kernel/qprintengine_win.cpp
+++ b/src/printsupport/kernel/qprintengine_win.cpp
@@ -1556,14 +1556,15 @@ HGLOBAL *QWin32PrintEngine::createGlobalDevNames()
Q_D(QWin32PrintEngine);
int size = sizeof(DEVNAMES) + d->m_printDevice.id().length() * 2 + 2;
- HGLOBAL *hGlobal = (HGLOBAL *) GlobalAlloc(GMEM_MOVEABLE, size);
- DEVNAMES *dn = (DEVNAMES*) GlobalLock(hGlobal);
+ auto hGlobal = reinterpret_cast<HGLOBAL *>(GlobalAlloc(GMEM_MOVEABLE, size));
+ auto dn = reinterpret_cast<DEVNAMES*>(GlobalLock(hGlobal));
dn->wDriverOffset = 0;
dn->wDeviceOffset = sizeof(DEVNAMES) / sizeof(wchar_t);
dn->wOutputOffset = 0;
- memcpy((ushort*)dn + dn->wDeviceOffset, d->m_printDevice.id().utf16(), d->m_printDevice.id().length() * 2 + 2);
+ memcpy(reinterpret_cast<ushort*>(dn) + dn->wDeviceOffset,
+ d->m_printDevice.id().utf16(), d->m_printDevice.id().length() * 2 + 2);
dn->wDefault = 0;
GlobalUnlock(hGlobal);
@@ -1574,8 +1575,9 @@ void QWin32PrintEngine::setGlobalDevMode(HGLOBAL globalDevNames, HGLOBAL globalD
{
Q_D(QWin32PrintEngine);
if (globalDevNames) {
- DEVNAMES *dn = (DEVNAMES*) GlobalLock(globalDevNames);
- QString id = QString::fromWCharArray((wchar_t*)(dn) + dn->wDeviceOffset);
+ auto dn = reinterpret_cast<DEVNAMES*>(GlobalLock(globalDevNames));
+ const QString id =
+ QString::fromWCharArray(reinterpret_cast<const wchar_t*>(dn) + dn->wDeviceOffset);
QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();
if (ps)
d->m_printDevice = ps->createPrintDevice(id.isEmpty() ? ps->defaultPrintDeviceId() : id);
@@ -1583,7 +1585,7 @@ void QWin32PrintEngine::setGlobalDevMode(HGLOBAL globalDevNames, HGLOBAL globalD
}
if (globalDevMode) {
- DEVMODE *dm = (DEVMODE*) GlobalLock(globalDevMode);
+ auto dm = reinterpret_cast<DEVMODE*>(GlobalLock(globalDevMode));
d->release();
d->globalDevMode = globalDevMode;
if (d->ownsDevMode) {
@@ -1779,39 +1781,26 @@ static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC h
QTransform matrix = QTransform::fromTranslate(baseline_pos.x(), baseline_pos.y());
ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags,
_glyphs, positions);
- if (_glyphs.size() == 0) {
+ if (_glyphs.isEmpty()) {
SelectObject(hdc, old_font);
return;
}
- bool outputEntireItem = _glyphs.size() > 0;
-
- if (outputEntireItem) {
- options |= ETO_PDY;
- QVarLengthArray<INT> glyphDistances(_glyphs.size() * 2);
- QVarLengthArray<wchar_t> g(_glyphs.size());
- for (int i=0; i<_glyphs.size() - 1; ++i) {
- glyphDistances[i * 2] = qRound(positions[i + 1].x) - qRound(positions[i].x);
- glyphDistances[i * 2 + 1] = qRound(positions[i + 1].y) - qRound(positions[i].y);
- g[i] = _glyphs[i];
- }
- glyphDistances[(_glyphs.size() - 1) * 2] = 0;
- glyphDistances[(_glyphs.size() - 1) * 2 + 1] = 0;
- g[_glyphs.size() - 1] = _glyphs[_glyphs.size() - 1];
- ExtTextOut(hdc, qRound(positions[0].x), qRound(positions[0].y), options, 0,
- g.constData(), _glyphs.size(),
- glyphDistances.data());
- } else {
- int i = 0;
- while(i < _glyphs.size()) {
- wchar_t g = _glyphs[i];
-
- ExtTextOut(hdc, qRound(positions[i].x),
- qRound(positions[i].y), options, 0,
- &g, 1, 0);
- ++i;
- }
+ options |= ETO_PDY;
+ QVarLengthArray<INT> glyphDistances(_glyphs.size() * 2);
+ QVarLengthArray<wchar_t> g(_glyphs.size());
+ const int lastGlyph = _glyphs.size() - 1;
+ for (int i = 0; i < lastGlyph; ++i) {
+ glyphDistances[i * 2] = qRound(positions[i + 1].x) - qRound(positions[i].x);
+ glyphDistances[i * 2 + 1] = qRound(positions[i + 1].y) - qRound(positions[i].y);
+ g[i] = _glyphs[i];
}
+ glyphDistances[lastGlyph * 2] = 0;
+ glyphDistances[lastGlyph * 2 + 1] = 0;
+ g[lastGlyph] = _glyphs[lastGlyph];
+ ExtTextOut(hdc, qRound(positions[0].x), qRound(positions[0].y), options, nullptr,
+ g.constData(), _glyphs.size(),
+ glyphDistances.data());
}
win_xform.eM11 = win_xform.eM22 = 1.0;
diff --git a/src/printsupport/kernel/qprinter.cpp b/src/printsupport/kernel/qprinter.cpp
index 8a2cdcb34f..829a13863b 100644
--- a/src/printsupport/kernel/qprinter.cpp
+++ b/src/printsupport/kernel/qprinter.cpp
@@ -149,7 +149,12 @@ void QPrinterPrivate::initEngines(QPrinter::OutputFormat format, const QPrinterI
printEngine = ps->createNativePrintEngine(printerMode, printerName);
paintEngine = ps->createPaintEngine(printEngine, printerMode);
} else {
- const auto pdfEngineVersion = (pdfVersion == QPrinter::PdfVersion_1_4 ? QPdfEngine::Version_1_4 : QPdfEngine::Version_A1b);
+ static const QHash<QPrinter::PdfVersion, QPdfEngine::PdfVersion> engineMapping {
+ {QPrinter::PdfVersion_1_4, QPdfEngine::Version_1_4},
+ {QPrinter::PdfVersion_A1b, QPdfEngine::Version_A1b},
+ {QPrinter::PdfVersion_1_6, QPdfEngine::Version_1_6}
+ };
+ const auto pdfEngineVersion = engineMapping.value(pdfVersion, QPdfEngine::Version_1_4);
QPdfPrintEngine *pdfEngine = new QPdfPrintEngine(printerMode, pdfEngineVersion);
paintEngine = pdfEngine;
printEngine = pdfEngine;
@@ -224,8 +229,8 @@ void QPrinterPrivate::setProperty(QPrintEngine::PrintEnginePropertyKey key, cons
class QPrinterPagedPaintDevicePrivate : public QPagedPaintDevicePrivate
{
public:
- QPrinterPagedPaintDevicePrivate(QPrinterPrivate *d)
- : QPagedPaintDevicePrivate(), pd(d)
+ QPrinterPagedPaintDevicePrivate(QPrinter *p)
+ : QPagedPaintDevicePrivate(), m_printer(p)
{}
virtual ~QPrinterPagedPaintDevicePrivate()
@@ -233,6 +238,8 @@ public:
bool setPageLayout(const QPageLayout &newPageLayout) override
{
+ QPrinterPrivate *pd = QPrinterPrivate::get(m_printer);
+
if (pd->paintEngine->type() != QPaintEngine::Pdf
&& pd->printEngine->printerState() == QPrinter::Active) {
qWarning("QPrinter::setPageLayout: Cannot be changed while printer is active");
@@ -242,14 +249,13 @@ public:
// Try to set the print engine page layout
pd->setProperty(QPrintEngine::PPK_QPageLayout, QVariant::fromValue(newPageLayout));
- // Set QPagedPaintDevice layout to match the current print engine value
- m_pageLayout = pageLayout();
-
return pageLayout().isEquivalentTo(newPageLayout);
}
bool setPageSize(const QPageSize &pageSize) override
{
+ QPrinterPrivate *pd = QPrinterPrivate::get(m_printer);
+
if (pd->paintEngine->type() != QPaintEngine::Pdf
&& pd->printEngine->printerState() == QPrinter::Active) {
qWarning("QPrinter::setPageLayout: Cannot be changed while printer is active");
@@ -260,46 +266,38 @@ public:
// Try to set the print engine page size
pd->setProperty(QPrintEngine::PPK_QPageSize, QVariant::fromValue(pageSize));
- // Set QPagedPaintDevice layout to match the current print engine value
- m_pageLayout = pageLayout();
-
return pageLayout().pageSize().isEquivalentTo(pageSize);
}
bool setPageOrientation(QPageLayout::Orientation orientation) override
{
+ QPrinterPrivate *pd = QPrinterPrivate::get(m_printer);
+
// Set the print engine value
pd->setProperty(QPrintEngine::PPK_Orientation, orientation);
- // Set QPagedPaintDevice layout to match the current print engine value
- m_pageLayout = pageLayout();
-
return pageLayout().orientation() == orientation;
}
- bool setPageMargins(const QMarginsF &margins) override
- {
- return setPageMargins(margins, pageLayout().units());
- }
-
bool setPageMargins(const QMarginsF &margins, QPageLayout::Unit units) override
{
+ QPrinterPrivate *pd = QPrinterPrivate::get(m_printer);
+
// Try to set print engine margins
QPair<QMarginsF, QPageLayout::Unit> pair = qMakePair(margins, units);
pd->setProperty(QPrintEngine::PPK_QPageMargins, QVariant::fromValue(pair));
- // Set QPagedPaintDevice layout to match the current print engine value
- m_pageLayout = pageLayout();
-
return pageLayout().margins() == margins && pageLayout().units() == units;
}
QPageLayout pageLayout() const override
{
+ QPrinterPrivate *pd = QPrinterPrivate::get(m_printer);
+
return pd->printEngine->property(QPrintEngine::PPK_QPageLayout).value<QPageLayout>();
}
- QPrinterPrivate *pd;
+ QPrinter *m_printer;
};
@@ -554,11 +552,9 @@ public:
Creates a new printer object with the given \a mode.
*/
QPrinter::QPrinter(PrinterMode mode)
- : QPagedPaintDevice(),
+ : QPagedPaintDevice(new QPrinterPagedPaintDevicePrivate(this)),
d_ptr(new QPrinterPrivate(this))
{
- delete d;
- d = new QPrinterPagedPaintDevicePrivate(d_func());
d_ptr->init(QPrinterInfo(), mode);
}
@@ -568,11 +564,9 @@ QPrinter::QPrinter(PrinterMode mode)
Creates a new printer object with the given \a printer and \a mode.
*/
QPrinter::QPrinter(const QPrinterInfo& printer, PrinterMode mode)
- : QPagedPaintDevice(),
+ : QPagedPaintDevice(new QPrinterPagedPaintDevicePrivate(this)),
d_ptr(new QPrinterPrivate(this))
{
- delete d;
- d = new QPrinterPagedPaintDevicePrivate(d_func());
d_ptr->init(printer, mode);
}
@@ -1469,8 +1463,6 @@ void QPrinter::setFullPage(bool fp)
Q_D(QPrinter);
// Set the print engine
d->setProperty(QPrintEngine::PPK_FullPage, fp);
- // Set QPagedPaintDevice layout to match the current print engine value
- devicePageLayout() = pageLayout();
}
diff --git a/src/printsupport/kernel/qprinter_p.h b/src/printsupport/kernel/qprinter_p.h
index 6ced466236..37c9702c17 100644
--- a/src/printsupport/kernel/qprinter_p.h
+++ b/src/printsupport/kernel/qprinter_p.h
@@ -94,6 +94,10 @@ public:
}
+ static QPrinterPrivate *get(QPrinter *printer) {
+ return printer->d_ptr.get();
+ }
+
void init(const QPrinterInfo &printer, QPrinter::PrinterMode mode);
QPrinterInfo findValidPrinter(const QPrinterInfo &printer = QPrinterInfo());
diff --git a/src/sql/configure.json b/src/sql/configure.json
new file mode 100644
index 0000000000..8fdc27e3a2
--- /dev/null
+++ b/src/sql/configure.json
@@ -0,0 +1,22 @@
+{
+ "module": "sql",
+ "depends": [
+ "core"
+ ],
+
+ "features": {
+ "sqlmodel": {
+ "label": "SQL item models",
+ "purpose": "Provides item model classes backed by SQL databases.",
+ "condition": "features.itemmodel",
+ "output": [ "publicFeature" ]
+ }
+ },
+
+ "summary": [
+ {
+ "section": "Qt Sql",
+ "entries": [ "sqlmodel" ]
+ }
+ ]
+}
diff --git a/src/sql/doc/snippets/code/doc_src_sql-driver.cpp b/src/sql/doc/snippets/code/doc_src_sql-driver.cpp
index 2c0e824db3..54576733bf 100644
--- a/src/sql/doc/snippets/code/doc_src_sql-driver.cpp
+++ b/src/sql/doc/snippets/code/doc_src_sql-driver.cpp
@@ -106,7 +106,7 @@ while (query.next()) {
QVariant v = query.result()->handle();
if (qstrcmp(v.typeName(), "PGresult*") == 0) {
PGresult *handle = *static_cast<PGresult **>(v.data());
- if (handle != 0) {
+ if (handle) {
// Do something...
}
}
diff --git a/src/sql/doc/snippets/code/src_sql_kernel_qsqldriver.cpp b/src/sql/doc/snippets/code/src_sql_kernel_qsqldriver.cpp
index ffae690769..a13cf86d3f 100644
--- a/src/sql/doc/snippets/code/src_sql_kernel_qsqldriver.cpp
+++ b/src/sql/doc/snippets/code/src_sql_kernel_qsqldriver.cpp
@@ -51,10 +51,10 @@
//! [0]
QSqlDatabase db = ...;
QVariant v = db.driver()->handle();
-if (v.isValid() && qstrcmp(v.typeName(), "sqlite3*")==0) {
+if (v.isValid() && qstrcmp(v.typeName(), "sqlite3*") == 0) {
// v.data() returns a pointer to the handle
sqlite3 *handle = *static_cast<sqlite3 **>(v.data());
- if (handle != 0) { // check that it is not NULL
+ if (handle) {
...
}
}
@@ -62,13 +62,13 @@ if (v.isValid() && qstrcmp(v.typeName(), "sqlite3*")==0) {
//! [1]
-if (qstrcmp(v.typeName(), "PGconn*")) {
+if (qstrcmp(v.typeName(), "PGconn*") == 0) {
PGconn *handle = *static_cast<PGconn **>(v.data());
- if (handle != 0) ...
+ if (handle) ...
}
-if (qstrcmp(v.typeName(), "MYSQL*")) {
+if (qstrcmp(v.typeName(), "MYSQL*") == 0) {
MYSQL *handle = *static_cast<MYSQL **>(v.data());
- if (handle != 0) ...
+ if (handle) ...
}
//! [1]
diff --git a/src/sql/doc/snippets/code/src_sql_kernel_qsqlresult.cpp b/src/sql/doc/snippets/code/src_sql_kernel_qsqlresult.cpp
index 3424a9140e..8ab2baf2a1 100644
--- a/src/sql/doc/snippets/code/src_sql_kernel_qsqlresult.cpp
+++ b/src/sql/doc/snippets/code/src_sql_kernel_qsqlresult.cpp
@@ -72,10 +72,10 @@ if (!q.execBatch())
//! [1]
QSqlQuery query = ...
QVariant v = query.result()->handle();
-if (v.isValid() && qstrcmp(v.typeName(), "sqlite3_stmt*")) {
+if (v.isValid() && qstrcmp(v.typeName(), "sqlite3_stmt*") == 0) {
// v.data() returns a pointer to the handle
sqlite3_stmt *handle = *static_cast<sqlite3_stmt **>(v.data());
- if (handle != 0) { // check that it is not NULL
+ if (handle) {
...
}
}
@@ -83,13 +83,13 @@ if (v.isValid() && qstrcmp(v.typeName(), "sqlite3_stmt*")) {
//! [2]
-if (v.typeName() == "PGresult*") {
+if (qstrcmp(v.typeName(), "PGresult*") == 0) {
PGresult *handle = *static_cast<PGresult **>(v.data());
- if (handle != 0) ...
+ if (handle) ...
}
-if (v.typeName() == "MYSQL_STMT*") {
+if (qstrcmp(v.typeName(), "MYSQL_STMT*") == 0) {
MYSQL_STMT *handle = *static_cast<MYSQL_STMT **>(v.data());
- if (handle != 0) ...
+ if (handle) ...
}
//! [2]
diff --git a/src/sql/kernel/qsqlquery.cpp b/src/sql/kernel/qsqlquery.cpp
index 628bfa1880..daadcb8a0e 100644
--- a/src/sql/kernel/qsqlquery.cpp
+++ b/src/sql/kernel/qsqlquery.cpp
@@ -942,10 +942,12 @@ void QSqlQuery::clear()
query. See the \l{QSqlQuery examples}{Detailed Description} for
examples.
- Portability note: Some databases choose to delay preparing a query
+ Portability notes: Some databases choose to delay preparing a query
until it is executed the first time. In this case, preparing a
syntactically wrong query succeeds, but every consecutive exec()
will fail.
+ When the database does not support named placeholders directly,
+ the placeholder can only contain characters in the range [a-zA-Z0-9_].
For SQLite, the query string can contain only one statement at a time.
If more than one statement is given, the function returns \c false.
diff --git a/src/sql/kernel/qtsqlglobal.h b/src/sql/kernel/qtsqlglobal.h
index d421adc84b..ec79e8da1e 100644
--- a/src/sql/kernel/qtsqlglobal.h
+++ b/src/sql/kernel/qtsqlglobal.h
@@ -41,6 +41,7 @@
#define QTSQLGLOBAL_H
#include <QtCore/qglobal.h>
+#include <QtSql/qtsql-config.h>
QT_BEGIN_NAMESPACE
diff --git a/src/sql/kernel/qtsqlglobal_p.h b/src/sql/kernel/qtsqlglobal_p.h
index ab45f6cd38..78a2461257 100644
--- a/src/sql/kernel/qtsqlglobal_p.h
+++ b/src/sql/kernel/qtsqlglobal_p.h
@@ -53,5 +53,6 @@
#include <QtSql/qtsqlglobal.h>
#include <QtCore/private/qglobal_p.h>
+#include <QtSql/private/qtsql-config_p.h>
#endif // QTSQLGLOBAL_P_H
diff --git a/src/sql/models/qsqlquerymodel.h b/src/sql/models/qsqlquerymodel.h
index 869a5f030c..427b369ae2 100644
--- a/src/sql/models/qsqlquerymodel.h
+++ b/src/sql/models/qsqlquerymodel.h
@@ -44,8 +44,9 @@
#include <QtCore/qabstractitemmodel.h>
#include <QtSql/qsqldatabase.h>
-QT_BEGIN_NAMESPACE
+QT_REQUIRE_CONFIG(sqlmodel);
+QT_BEGIN_NAMESPACE
class QSqlQueryModelPrivate;
class QSqlError;
diff --git a/src/sql/models/qsqlquerymodel_p.h b/src/sql/models/qsqlquerymodel_p.h
index ffc34b9f95..d5ca2f89cb 100644
--- a/src/sql/models/qsqlquerymodel_p.h
+++ b/src/sql/models/qsqlquerymodel_p.h
@@ -60,6 +60,8 @@
#include "QtCore/qvarlengtharray.h"
#include "QtCore/qvector.h"
+QT_REQUIRE_CONFIG(sqlmodel);
+
QT_BEGIN_NAMESPACE
class QSqlQueryModelPrivate: public QAbstractItemModelPrivate
@@ -73,7 +75,7 @@ public:
void initColOffsets(int size);
int columnInQuery(int modelColumn) const;
- mutable QSqlQuery query;
+ mutable QSqlQuery query = { QSqlQuery(0) };
mutable QSqlError error;
QModelIndex bottom;
QSqlRecord rec;
diff --git a/src/sql/models/qsqlrelationaldelegate.h b/src/sql/models/qsqlrelationaldelegate.h
index 53f43a4acb..e8ae5a229d 100644
--- a/src/sql/models/qsqlrelationaldelegate.h
+++ b/src/sql/models/qsqlrelationaldelegate.h
@@ -42,6 +42,8 @@
#include <QtSql/qtsqlglobal.h>
+QT_REQUIRE_CONFIG(sqlmodel);
+
#ifdef QT_WIDGETS_LIB
#include <QtWidgets/qitemdelegate.h>
@@ -53,7 +55,7 @@
#endif
#include <QtSql/qsqldriver.h>
#include <QtSql/qsqlrelationaltablemodel.h>
-
+#include <QtCore/qmetaobject.h>
QT_BEGIN_NAMESPACE
@@ -97,6 +99,27 @@ QWidget *createEditor(QWidget *aParent,
return combo;
}
+ void setEditorData(QWidget *editor, const QModelIndex &index) const override
+ {
+ if (!index.isValid())
+ return;
+
+ if (qobject_cast<QComboBox *>(editor)) {
+ // Taken from QItemDelegate::setEditorData() as we need
+ // to present the DisplayRole and not the EditRole which
+ // is the id reference to the related model
+ QVariant v = index.data(Qt::DisplayRole);
+ QByteArray n = editor->metaObject()->userProperty().name();
+ if (!n.isEmpty()) {
+ if (!v.isValid())
+ v = QVariant(editor->property(n).userType(), nullptr);
+ editor->setProperty(n, v);
+ return;
+ }
+ }
+ QItemDelegate::setEditorData(editor, index);
+ }
+
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override
{
if (!index.isValid())
diff --git a/src/sql/models/qsqlrelationaltablemodel.h b/src/sql/models/qsqlrelationaltablemodel.h
index 90b7a6481f..555755009c 100644
--- a/src/sql/models/qsqlrelationaltablemodel.h
+++ b/src/sql/models/qsqlrelationaltablemodel.h
@@ -45,6 +45,8 @@
#include <QtCore/qtypeinfo.h>
+QT_REQUIRE_CONFIG(sqlmodel);
+
QT_BEGIN_NAMESPACE
diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp
index 865f76c73a..a33f76838f 100644
--- a/src/sql/models/qsqltablemodel.cpp
+++ b/src/sql/models/qsqltablemodel.cpp
@@ -565,6 +565,10 @@ bool QSqlTableModel::isDirty(const QModelIndex &index) const
Returns \c true if the value could be set or false on error, for
example if \a index is out of bounds.
+ Returns \c false if the role is not Qt::EditRole. To set data
+ for roles other than EditRole, either use a custom proxy model
+ or subclass QSqlTableModel.
+
\sa editStrategy(), data(), submit(), submitAll(), revertRow()
*/
bool QSqlTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
diff --git a/src/sql/models/qsqltablemodel.h b/src/sql/models/qsqltablemodel.h
index 77b0517c74..7acc7dc94d 100644
--- a/src/sql/models/qsqltablemodel.h
+++ b/src/sql/models/qsqltablemodel.h
@@ -44,6 +44,8 @@
#include <QtSql/qsqldatabase.h>
#include <QtSql/qsqlquerymodel.h>
+QT_REQUIRE_CONFIG(sqlmodel);
+
QT_BEGIN_NAMESPACE
diff --git a/src/sql/models/qsqltablemodel_p.h b/src/sql/models/qsqltablemodel_p.h
index 490bb48a24..bb568ab444 100644
--- a/src/sql/models/qsqltablemodel_p.h
+++ b/src/sql/models/qsqltablemodel_p.h
@@ -56,6 +56,8 @@
#include "QtSql/qsqlindex.h"
#include "QtCore/qmap.h"
+QT_REQUIRE_CONFIG(sqlmodel);
+
QT_BEGIN_NAMESPACE
class Q_AUTOTEST_EXPORT QSqlTableModelPrivate: public QSqlQueryModelPrivate
@@ -91,7 +93,7 @@ public:
QSqlTableModel::EditStrategy strategy;
bool busyInsertingRows;
- QSqlQuery editQuery;
+ QSqlQuery editQuery = { QSqlQuery(0) };
QSqlIndex primaryIndex;
QString tableName;
QString filter;
diff --git a/src/sql/sql.pro b/src/sql/sql.pro
index 821ae1c9b9..1cd2a05250 100644
--- a/src/sql/sql.pro
+++ b/src/sql/sql.pro
@@ -11,7 +11,7 @@ PRECOMPILED_HEADER = ../corelib/global/qt_pch.h
SQL_P = sql
include(kernel/kernel.pri)
-include(models/models.pri)
+qtConfig(sqlmodel): include(models/models.pri)
MODULE_PLUGIN_TYPES = \
sqldrivers
diff --git a/src/testlib/3rdparty/VALGRIND_LICENSE.txt b/src/testlib/3rdparty/VALGRIND_LICENSE.txt
index 714b75e6d1..d17836a47d 100644
--- a/src/testlib/3rdparty/VALGRIND_LICENSE.txt
+++ b/src/testlib/3rdparty/VALGRIND_LICENSE.txt
@@ -1,5 +1,5 @@
- Copyright (C) 2000-2007 Julian Seward
- Copyright (C) 2003-2007 Josef Weidendorfer. All rights reserved.
+ Copyright (C) 2000-2017 Julian Seward. All rights reserved.
+ Copyright (C) 2003-2017 Josef Weidendorfer. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
diff --git a/src/testlib/3rdparty/callgrind_p.h b/src/testlib/3rdparty/callgrind_p.h
index 10d79318c4..e971283616 100644
--- a/src/testlib/3rdparty/callgrind_p.h
+++ b/src/testlib/3rdparty/callgrind_p.h
@@ -13,7 +13,7 @@
This file is part of callgrind, a valgrind tool for cache simulation
and call tree tracing.
- Copyright (C) 2003-2007 Josef Weidendorfer. All rights reserved.
+ Copyright (C) 2003-2017 Josef Weidendorfer. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -49,7 +49,7 @@
----------------------------------------------------------------
Notice that the above BSD-style license applies to this one file
- (vgprof.h) only. The entire rest of Valgrind is licensed under
+ (callgrind.h) only. The entire rest of Valgrind is licensed under
the terms of the GNU General Public License, version 2. See the
COPYING file in the source distribution for details.
@@ -82,53 +82,38 @@ typedef
} Vg_CallgrindClientRequest;
/* Dump current state of cost centers, and zero them afterwards */
-#define CALLGRIND_DUMP_STATS \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__DUMP_STATS, \
- 0, 0, 0, 0, 0); \
- }
+#define CALLGRIND_DUMP_STATS \
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DUMP_STATS, \
+ 0, 0, 0, 0, 0)
/* Dump current state of cost centers, and zero them afterwards.
The argument is appended to a string stating the reason which triggered
the dump. This string is written as a description field into the
profile data dump. */
-#define CALLGRIND_DUMP_STATS_AT(pos_str) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__DUMP_STATS_AT, \
- pos_str, 0, 0, 0, 0); \
- }
+#define CALLGRIND_DUMP_STATS_AT(pos_str) \
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DUMP_STATS_AT, \
+ pos_str, 0, 0, 0, 0)
/* Zero cost centers */
-#define CALLGRIND_ZERO_STATS \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__ZERO_STATS, \
- 0, 0, 0, 0, 0); \
- }
+#define CALLGRIND_ZERO_STATS \
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__ZERO_STATS, \
+ 0, 0, 0, 0, 0)
/* Toggles collection state.
The collection state specifies whether the happening of events
should be noted or if they are to be ignored. Events are noted
by increment of counters in a cost center */
-#define CALLGRIND_TOGGLE_COLLECT \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__TOGGLE_COLLECT, \
- 0, 0, 0, 0, 0); \
- }
+#define CALLGRIND_TOGGLE_COLLECT \
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__TOGGLE_COLLECT, \
+ 0, 0, 0, 0, 0)
/* Start full callgrind instrumentation if not already switched on.
When cache simulation is done, it will flush the simulated cache;
- this will lead to an artifical cache warmup phase afterwards with
+ this will lead to an artificial cache warmup phase afterwards with
cache misses which would not have happened in reality. */
-#define CALLGRIND_START_INSTRUMENTATION \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__START_INSTRUMENTATION, \
- 0, 0, 0, 0, 0); \
- }
+#define CALLGRIND_START_INSTRUMENTATION \
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__START_INSTRUMENTATION, \
+ 0, 0, 0, 0, 0)
/* Stop full callgrind instrumentation if not already switched off.
This flushes Valgrinds translation cache, and does no additional
@@ -137,11 +122,8 @@ typedef
Use this to bypass Callgrind aggregation for uninteresting code parts.
To start Callgrind in this mode to ignore the setup phase, use
the option "--instr-atstart=no". */
-#define CALLGRIND_STOP_INSTRUMENTATION \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__STOP_INSTRUMENTATION, \
- 0, 0, 0, 0, 0); \
- }
+#define CALLGRIND_STOP_INSTRUMENTATION \
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STOP_INSTRUMENTATION, \
+ 0, 0, 0, 0, 0)
#endif /* __CALLGRIND_H */
diff --git a/src/testlib/3rdparty/qt_attribution.json b/src/testlib/3rdparty/qt_attribution.json
index 18522b6cd8..4dd844c232 100644
--- a/src/testlib/3rdparty/qt_attribution.json
+++ b/src/testlib/3rdparty/qt_attribution.json
@@ -8,12 +8,12 @@
"Description": "An instrumentation framework for building dynamic analysis tools.",
"Homepage": "http://valgrind.org/",
- "Version": "3.3.0",
+ "Version": "3.14.0",
"License": "BSD 4-clause \"Original\" or \"Old\" License",
"LicenseId": "BSD-4-Clause",
"LicenseFile": "VALGRIND_LICENSE.txt",
- "Copyright": "Copyright (C) 2000-2007 Julian Seward
-Copyright (C) 2003-2007 Josef Weidendorfer."
+ "Copyright": "Copyright (C) 2000-2017 Julian Seward
+Copyright (C) 2003-2017 Josef Weidendorfer."
},
{
"Id": "cycle",
diff --git a/src/testlib/3rdparty/valgrind_p.h b/src/testlib/3rdparty/valgrind_p.h
index 4745371d81..577c8f05e5 100644
--- a/src/testlib/3rdparty/valgrind_p.h
+++ b/src/testlib/3rdparty/valgrind_p.h
@@ -12,7 +12,7 @@
This file is part of Valgrind, a dynamic binary instrumentation
framework.
- Copyright (C) 2000-2007 Julian Seward. All rights reserved.
+ Copyright (C) 2000-2017 Julian Seward. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -73,6 +73,25 @@
#ifndef __VALGRIND_H
#define __VALGRIND_H
+
+/* ------------------------------------------------------------------ */
+/* VERSION NUMBER OF VALGRIND */
+/* ------------------------------------------------------------------ */
+
+/* Specify Valgrind's version number, so that user code can
+ conditionally compile based on our version number. Note that these
+ were introduced at version 3.6 and so do not exist in version 3.5
+ or earlier. The recommended way to use them to check for "version
+ X.Y or later" is (eg)
+
+#if defined(__VALGRIND_MAJOR__) && defined(__VALGRIND_MINOR__) \
+ && (__VALGRIND_MAJOR__ > 3 \
+ || (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6))
+*/
+#define __VALGRIND_MAJOR__ 3
+#define __VALGRIND_MINOR__ 14
+
+
#include <stdarg.h>
/* Nb: this file might be included in a file compiled with -ansi. So
@@ -84,34 +103,69 @@
identifying architectures, which are different to the ones we use
within the rest of Valgrind. Note, __powerpc__ is active for both
32 and 64-bit PPC, whereas __powerpc64__ is only active for the
- latter (on Linux, that is). */
+ latter (on Linux, that is).
+
+ Misc note: how to find out what's predefined in gcc by default:
+ gcc -Wp,-dM somefile.c
+*/
+#undef PLAT_x86_darwin
+#undef PLAT_amd64_darwin
+#undef PLAT_x86_win32
+#undef PLAT_amd64_win64
#undef PLAT_x86_linux
#undef PLAT_amd64_linux
#undef PLAT_ppc32_linux
-#undef PLAT_ppc64_linux
-#undef PLAT_ppc32_aix5
-#undef PLAT_ppc64_aix5
-
-#if !defined(_AIX) && defined(__i386__)
+#undef PLAT_ppc64be_linux
+#undef PLAT_ppc64le_linux
+#undef PLAT_arm_linux
+#undef PLAT_arm64_linux
+#undef PLAT_s390x_linux
+#undef PLAT_mips32_linux
+#undef PLAT_mips64_linux
+#undef PLAT_x86_solaris
+#undef PLAT_amd64_solaris
+
+
+#if defined(__APPLE__) && defined(__i386__)
+# define PLAT_x86_darwin 1
+#elif defined(__APPLE__) && defined(__x86_64__)
+# define PLAT_amd64_darwin 1
+#elif (defined(__MINGW32__) && !defined(__MINGW64__)) \
+ || defined(__CYGWIN32__) \
+ || (defined(_WIN32) && defined(_M_IX86))
+# define PLAT_x86_win32 1
+#elif defined(__MINGW64__) \
+ || (defined(_WIN64) && defined(_M_X64))
+# define PLAT_amd64_win64 1
+#elif defined(__linux__) && defined(__i386__)
# define PLAT_x86_linux 1
-#elif !defined(_AIX) && defined(__x86_64__)
+#elif defined(__linux__) && defined(__x86_64__) && !defined(__ILP32__)
# define PLAT_amd64_linux 1
-#elif !defined(_AIX) && defined(__powerpc__) && !defined(__powerpc64__)
+#elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
# define PLAT_ppc32_linux 1
-#elif !defined(_AIX) && defined(__powerpc__) && defined(__powerpc64__)
-# define PLAT_ppc64_linux 1
-#elif defined(_AIX) && defined(__64BIT__)
-# define PLAT_ppc64_aix5 1
-#elif defined(_AIX) && !defined(__64BIT__)
-# define PLAT_ppc32_aix5 1
-#endif
-
-
+#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) && _CALL_ELF != 2
+/* Big Endian uses ELF version 1 */
+# define PLAT_ppc64be_linux 1
+#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) && _CALL_ELF == 2
+/* Little Endian uses ELF version 2 */
+# define PLAT_ppc64le_linux 1
+#elif defined(__linux__) && defined(__arm__) && !defined(__aarch64__)
+# define PLAT_arm_linux 1
+#elif defined(__linux__) && defined(__aarch64__) && !defined(__arm__)
+# define PLAT_arm64_linux 1
+#elif defined(__linux__) && defined(__s390__) && defined(__s390x__)
+# define PLAT_s390x_linux 1
+#elif defined(__linux__) && defined(__mips__) && (__mips==64)
+# define PLAT_mips64_linux 1
+#elif defined(__linux__) && defined(__mips__) && (__mips!=64)
+# define PLAT_mips32_linux 1
+#elif defined(__sun) && defined(__i386__)
+# define PLAT_x86_solaris 1
+#elif defined(__sun) && defined(__x86_64__)
+# define PLAT_amd64_solaris 1
+#else
/* If we're not compiling for our target platform, don't generate
any inline asms. */
-#if !defined(PLAT_x86_linux) && !defined(PLAT_amd64_linux) \
- && !defined(PLAT_ppc32_linux) && !defined(PLAT_ppc64_linux) \
- && !defined(PLAT_ppc32_aix5) && !defined(PLAT_ppc64_aix5)
# if !defined(NVALGRIND)
# define NVALGRIND 1
# endif
@@ -123,18 +177,41 @@
/* in here of use to end-users -- skip to the next section. */
/* ------------------------------------------------------------------ */
+/*
+ * VALGRIND_DO_CLIENT_REQUEST(): a statement that invokes a Valgrind client
+ * request. Accepts both pointers and integers as arguments.
+ *
+ * VALGRIND_DO_CLIENT_REQUEST_STMT(): a statement that invokes a Valgrind
+ * client request that does not return a value.
+
+ * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind
+ * client request and whose value equals the client request result. Accepts
+ * both pointers and integers as arguments. Note that such calls are not
+ * necessarily pure functions -- they may have side effects.
+ */
+
+#define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, \
+ _zzq_request, _zzq_arg1, _zzq_arg2, \
+ _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ do { (_zzq_rlval) = VALGRIND_DO_CLIENT_REQUEST_EXPR((_zzq_default), \
+ (_zzq_request), (_zzq_arg1), (_zzq_arg2), \
+ (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
+
+#define VALGRIND_DO_CLIENT_REQUEST_STMT(_zzq_request, _zzq_arg1, \
+ _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ do { (void) VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
+ (_zzq_request), (_zzq_arg1), (_zzq_arg2), \
+ (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
+
#if defined(NVALGRIND)
/* Define NVALGRIND to completely remove the Valgrind magic sequence
from the compiled code (analogous to NDEBUG's effects on
assert()) */
-#define VALGRIND_DO_CLIENT_REQUEST( \
- _zzq_rlval, _zzq_default, _zzq_request, \
+#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
+ _zzq_default, _zzq_request, \
_zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
- { \
- (_zzq_rlval) = (_zzq_default); \
- (void)_zzq_rlval; \
- }
+ (_zzq_default)
#else /* ! NVALGRIND */
@@ -173,9 +250,11 @@
inline asm stuff to be useful.
*/
-/* ------------------------- x86-linux ------------------------- */
+/* ----------------- x86-{linux,darwin,solaris} ---------------- */
-#if defined(PLAT_x86_linux)
+#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \
+ || (defined(PLAT_x86_win32) && defined(__GNUC__)) \
+ || defined(PLAT_x86_solaris)
typedef
struct {
@@ -187,10 +266,11 @@ typedef
"roll $3, %%edi ; roll $13, %%edi\n\t" \
"roll $29, %%edi ; roll $19, %%edi\n\t"
-#define VALGRIND_DO_CLIENT_REQUEST( \
- _zzq_rlval, _zzq_default, _zzq_request, \
+#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
+ _zzq_default, _zzq_request, \
_zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
- { volatile unsigned int _zzq_args[6]; \
+ __extension__ \
+ ({volatile unsigned int _zzq_args[6]; \
volatile unsigned int _zzq_result; \
_zzq_args[0] = (unsigned int)(_zzq_request); \
_zzq_args[1] = (unsigned int)(_zzq_arg1); \
@@ -205,9 +285,8 @@ typedef
: "a" (&_zzq_args[0]), "0" (_zzq_default) \
: "cc", "memory" \
); \
- _zzq_rlval = _zzq_result; \
- (void)_zzq_rlval; \
- }
+ _zzq_result; \
+ })
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
{ volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
@@ -226,15 +305,100 @@ typedef
__SPECIAL_INSTRUCTION_PREAMBLE \
/* call-noredir *%EAX */ \
"xchgl %%edx,%%edx\n\t"
-#endif /* PLAT_x86_linux */
-/* ------------------------ amd64-linux ------------------------ */
+#define VALGRIND_VEX_INJECT_IR() \
+ do { \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ "xchgl %%edi,%%edi\n\t" \
+ : : : "cc", "memory" \
+ ); \
+ } while (0)
+
+#endif /* PLAT_x86_linux || PLAT_x86_darwin || (PLAT_x86_win32 && __GNUC__)
+ || PLAT_x86_solaris */
+
+/* ------------------------- x86-Win32 ------------------------- */
+
+#if defined(PLAT_x86_win32) && !defined(__GNUC__)
+
+typedef
+ struct {
+ unsigned int nraddr; /* where's the code? */
+ }
+ OrigFn;
+
+#if defined(_MSC_VER)
+
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ __asm rol edi, 3 __asm rol edi, 13 \
+ __asm rol edi, 29 __asm rol edi, 19
+
+#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
+ _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ valgrind_do_client_request_expr((uintptr_t)(_zzq_default), \
+ (uintptr_t)(_zzq_request), (uintptr_t)(_zzq_arg1), \
+ (uintptr_t)(_zzq_arg2), (uintptr_t)(_zzq_arg3), \
+ (uintptr_t)(_zzq_arg4), (uintptr_t)(_zzq_arg5))
+
+static __inline uintptr_t
+valgrind_do_client_request_expr(uintptr_t _zzq_default, uintptr_t _zzq_request,
+ uintptr_t _zzq_arg1, uintptr_t _zzq_arg2,
+ uintptr_t _zzq_arg3, uintptr_t _zzq_arg4,
+ uintptr_t _zzq_arg5)
+{
+ volatile uintptr_t _zzq_args[6];
+ volatile unsigned int _zzq_result;
+ _zzq_args[0] = (uintptr_t)(_zzq_request);
+ _zzq_args[1] = (uintptr_t)(_zzq_arg1);
+ _zzq_args[2] = (uintptr_t)(_zzq_arg2);
+ _zzq_args[3] = (uintptr_t)(_zzq_arg3);
+ _zzq_args[4] = (uintptr_t)(_zzq_arg4);
+ _zzq_args[5] = (uintptr_t)(_zzq_arg5);
+ __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default
+ __SPECIAL_INSTRUCTION_PREAMBLE
+ /* %EDX = client_request ( %EAX ) */
+ __asm xchg ebx,ebx
+ __asm mov _zzq_result, edx
+ }
+ return _zzq_result;
+}
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ volatile unsigned int __addr; \
+ __asm { __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %EAX = guest_NRADDR */ \
+ __asm xchg ecx,ecx \
+ __asm mov __addr, eax \
+ } \
+ _zzq_orig->nraddr = __addr; \
+ }
+
+#define VALGRIND_CALL_NOREDIR_EAX ERROR
+
+#define VALGRIND_VEX_INJECT_IR() \
+ do { \
+ __asm { __SPECIAL_INSTRUCTION_PREAMBLE \
+ __asm xchg edi,edi \
+ } \
+ } while (0)
+
+#else
+#error Unsupported compiler.
+#endif
-#if defined(PLAT_amd64_linux)
+#endif /* PLAT_x86_win32 */
+
+/* ----------------- amd64-{linux,darwin,solaris} --------------- */
+
+#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) \
+ || defined(PLAT_amd64_solaris) \
+ || (defined(PLAT_amd64_win64) && defined(__GNUC__))
typedef
struct {
- unsigned long long int nraddr; /* where's the code? */
+ unsigned long int nraddr; /* where's the code? */
}
OrigFn;
@@ -242,17 +406,18 @@ typedef
"rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
"rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
-#define VALGRIND_DO_CLIENT_REQUEST( \
- _zzq_rlval, _zzq_default, _zzq_request, \
+#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
+ _zzq_default, _zzq_request, \
_zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
- { volatile unsigned long long int _zzq_args[6]; \
- volatile unsigned long long int _zzq_result; \
- _zzq_args[0] = (unsigned long long int)(_zzq_request); \
- _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
- _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
- _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
- _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
- _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
+ __extension__ \
+ ({ volatile unsigned long int _zzq_args[6]; \
+ volatile unsigned long int _zzq_result; \
+ _zzq_args[0] = (unsigned long int)(_zzq_request); \
+ _zzq_args[1] = (unsigned long int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned long int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned long int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned long int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned long int)(_zzq_arg5); \
__asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
/* %RDX = client_request ( %RAX ) */ \
"xchgq %%rbx,%%rbx" \
@@ -260,13 +425,12 @@ typedef
: "a" (&_zzq_args[0]), "0" (_zzq_default) \
: "cc", "memory" \
); \
- _zzq_rlval = _zzq_result; \
- (void)_zzq_rlval; \
- }
+ _zzq_result; \
+ })
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
{ volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
- volatile unsigned long long int __addr; \
+ volatile unsigned long int __addr; \
__asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
/* %RAX = guest_NRADDR */ \
"xchgq %%rcx,%%rcx" \
@@ -281,7 +445,24 @@ typedef
__SPECIAL_INSTRUCTION_PREAMBLE \
/* call-noredir *%RAX */ \
"xchgq %%rdx,%%rdx\n\t"
-#endif /* PLAT_amd64_linux */
+
+#define VALGRIND_VEX_INJECT_IR() \
+ do { \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ "xchgq %%rdi,%%rdi\n\t" \
+ : : : "cc", "memory" \
+ ); \
+ } while (0)
+
+#endif /* PLAT_amd64_linux || PLAT_amd64_darwin || PLAT_amd64_solaris */
+
+/* ------------------------- amd64-Win64 ------------------------- */
+
+#if defined(PLAT_amd64_win64) && !defined(__GNUC__)
+
+#error Unsupported compiler.
+
+#endif /* PLAT_amd64_win64 */
/* ------------------------ ppc32-linux ------------------------ */
@@ -294,14 +475,15 @@ typedef
OrigFn;
#define __SPECIAL_INSTRUCTION_PREAMBLE \
- "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
- "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
+ "rlwinm 0,0,3,0,31 ; rlwinm 0,0,13,0,31\n\t" \
+ "rlwinm 0,0,29,0,31 ; rlwinm 0,0,19,0,31\n\t"
-#define VALGRIND_DO_CLIENT_REQUEST( \
- _zzq_rlval, _zzq_default, _zzq_request, \
+#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
+ _zzq_default, _zzq_request, \
_zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
\
- { unsigned int _zzq_args[6]; \
+ __extension__ \
+ ({ unsigned int _zzq_args[6]; \
unsigned int _zzq_result; \
unsigned int* _zzq_ptr; \
_zzq_args[0] = (unsigned int)(_zzq_request); \
@@ -320,9 +502,8 @@ typedef
: "=b" (_zzq_result) \
: "b" (_zzq_default), "b" (_zzq_ptr) \
: "cc", "memory", "r3", "r4"); \
- _zzq_rlval = _zzq_result; \
- (void)_zzq_rlval; \
- }
+ _zzq_result; \
+ })
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
{ volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
@@ -342,16 +523,24 @@ typedef
__SPECIAL_INSTRUCTION_PREAMBLE \
/* branch-and-link-to-noredir *%R11 */ \
"or 3,3,3\n\t"
+
+#define VALGRIND_VEX_INJECT_IR() \
+ do { \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ "or 5,5,5\n\t" \
+ ); \
+ } while (0)
+
#endif /* PLAT_ppc32_linux */
/* ------------------------ ppc64-linux ------------------------ */
-#if defined(PLAT_ppc64_linux)
+#if defined(PLAT_ppc64be_linux)
typedef
struct {
- unsigned long long int nraddr; /* where's the code? */
- unsigned long long int r2; /* what tocptr do we need? */
+ unsigned long int nraddr; /* where's the code? */
+ unsigned long int r2; /* what tocptr do we need? */
}
OrigFn;
@@ -359,47 +548,52 @@ typedef
"rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
"rotldi 0,0,61 ; rotldi 0,0,51\n\t"
-#define VALGRIND_DO_CLIENT_REQUEST( \
- _zzq_rlval, _zzq_default, _zzq_request, \
+#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
+ _zzq_default, _zzq_request, \
_zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
\
- { unsigned long long int _zzq_args[6]; \
- register unsigned long long int _zzq_result __asm__("r3"); \
- register unsigned long long int* _zzq_ptr __asm__("r4"); \
- _zzq_args[0] = (unsigned long long int)(_zzq_request); \
- _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
- _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
- _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
- _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
- _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
+ __extension__ \
+ ({ unsigned long int _zzq_args[6]; \
+ unsigned long int _zzq_result; \
+ unsigned long int* _zzq_ptr; \
+ _zzq_args[0] = (unsigned long int)(_zzq_request); \
+ _zzq_args[1] = (unsigned long int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned long int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned long int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned long int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned long int)(_zzq_arg5); \
_zzq_ptr = _zzq_args; \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ __asm__ volatile("mr 3,%1\n\t" /*default*/ \
+ "mr 4,%2\n\t" /*ptr*/ \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
/* %R3 = client_request ( %R4 ) */ \
- "or 1,1,1" \
- : "=r" (_zzq_result) \
- : "0" (_zzq_default), "r" (_zzq_ptr) \
- : "cc", "memory"); \
- _zzq_rlval = _zzq_result; \
- (void)_zzq_rlval; \
- }
+ "or 1,1,1\n\t" \
+ "mr %0,3" /*result*/ \
+ : "=b" (_zzq_result) \
+ : "b" (_zzq_default), "b" (_zzq_ptr) \
+ : "cc", "memory", "r3", "r4"); \
+ _zzq_result; \
+ })
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
{ volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
- register unsigned long long int __addr __asm__("r3"); \
+ unsigned long int __addr; \
__asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
/* %R3 = guest_NRADDR */ \
- "or 2,2,2" \
- : "=r" (__addr) \
+ "or 2,2,2\n\t" \
+ "mr %0,3" \
+ : "=b" (__addr) \
: \
- : "cc", "memory" \
+ : "cc", "memory", "r3" \
); \
_zzq_orig->nraddr = __addr; \
__asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
/* %R3 = guest_NRADDR_GPR2 */ \
- "or 4,4,4" \
- : "=r" (__addr) \
+ "or 4,4,4\n\t" \
+ "mr %0,3" \
+ : "=b" (__addr) \
: \
- : "cc", "memory" \
+ : "cc", "memory", "r3" \
); \
_zzq_orig->r2 = __addr; \
}
@@ -409,61 +603,65 @@ typedef
/* branch-and-link-to-noredir *%R11 */ \
"or 3,3,3\n\t"
-#endif /* PLAT_ppc64_linux */
+#define VALGRIND_VEX_INJECT_IR() \
+ do { \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ "or 5,5,5\n\t" \
+ ); \
+ } while (0)
-/* ------------------------ ppc32-aix5 ------------------------- */
+#endif /* PLAT_ppc64be_linux */
-#if defined(PLAT_ppc32_aix5)
+#if defined(PLAT_ppc64le_linux)
typedef
- struct {
- unsigned int nraddr; /* where's the code? */
- unsigned int r2; /* what tocptr do we need? */
+ struct {
+ unsigned long int nraddr; /* where's the code? */
+ unsigned long int r2; /* what tocptr do we need? */
}
OrigFn;
#define __SPECIAL_INSTRUCTION_PREAMBLE \
- "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
- "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
+ "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
+ "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
-#define VALGRIND_DO_CLIENT_REQUEST( \
- _zzq_rlval, _zzq_default, _zzq_request, \
+#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
+ _zzq_default, _zzq_request, \
_zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
\
- { unsigned int _zzq_args[7]; \
- register unsigned int _zzq_result; \
- register unsigned int* _zzq_ptr; \
- _zzq_args[0] = (unsigned int)(_zzq_request); \
- _zzq_args[1] = (unsigned int)(_zzq_arg1); \
- _zzq_args[2] = (unsigned int)(_zzq_arg2); \
- _zzq_args[3] = (unsigned int)(_zzq_arg3); \
- _zzq_args[4] = (unsigned int)(_zzq_arg4); \
- _zzq_args[5] = (unsigned int)(_zzq_arg5); \
- _zzq_args[6] = (unsigned int)(_zzq_default); \
+ __extension__ \
+ ({ unsigned long int _zzq_args[6]; \
+ unsigned long int _zzq_result; \
+ unsigned long int* _zzq_ptr; \
+ _zzq_args[0] = (unsigned long int)(_zzq_request); \
+ _zzq_args[1] = (unsigned long int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned long int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned long int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned long int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned long int)(_zzq_arg5); \
_zzq_ptr = _zzq_args; \
- __asm__ volatile("mr 4,%1\n\t" \
- "lwz 3, 24(4)\n\t" \
+ __asm__ volatile("mr 3,%1\n\t" /*default*/ \
+ "mr 4,%2\n\t" /*ptr*/ \
__SPECIAL_INSTRUCTION_PREAMBLE \
/* %R3 = client_request ( %R4 ) */ \
"or 1,1,1\n\t" \
- "mr %0,3" \
+ "mr %0,3" /*result*/ \
: "=b" (_zzq_result) \
- : "b" (_zzq_ptr) \
- : "r3", "r4", "cc", "memory"); \
- _zzq_rlval = _zzq_result; \
- (void)_zzq_rlval; \
- }
+ : "b" (_zzq_default), "b" (_zzq_ptr) \
+ : "cc", "memory", "r3", "r4"); \
+ _zzq_result; \
+ })
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
{ volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
- register unsigned int __addr; \
+ unsigned long int __addr; \
__asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
/* %R3 = guest_NRADDR */ \
"or 2,2,2\n\t" \
"mr %0,3" \
: "=b" (__addr) \
: \
- : "r3", "cc", "memory" \
+ : "cc", "memory", "r3" \
); \
_zzq_orig->nraddr = __addr; \
__asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
@@ -472,90 +670,380 @@ typedef
"mr %0,3" \
: "=b" (__addr) \
: \
- : "r3", "cc", "memory" \
+ : "cc", "memory", "r3" \
); \
_zzq_orig->r2 = __addr; \
}
-#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
__SPECIAL_INSTRUCTION_PREAMBLE \
- /* branch-and-link-to-noredir *%R11 */ \
+ /* branch-and-link-to-noredir *%R12 */ \
"or 3,3,3\n\t"
-#endif /* PLAT_ppc32_aix5 */
+#define VALGRIND_VEX_INJECT_IR() \
+ do { \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ "or 5,5,5\n\t" \
+ ); \
+ } while (0)
+
+#endif /* PLAT_ppc64le_linux */
-/* ------------------------ ppc64-aix5 ------------------------- */
+/* ------------------------- arm-linux ------------------------- */
-#if defined(PLAT_ppc64_aix5)
+#if defined(PLAT_arm_linux)
typedef
struct {
- unsigned long long int nraddr; /* where's the code? */
- unsigned long long int r2; /* what tocptr do we need? */
+ unsigned int nraddr; /* where's the code? */
}
OrigFn;
#define __SPECIAL_INSTRUCTION_PREAMBLE \
- "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
- "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
+ "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \
+ "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
-#define VALGRIND_DO_CLIENT_REQUEST( \
- _zzq_rlval, _zzq_default, _zzq_request, \
+#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
+ _zzq_default, _zzq_request, \
_zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
\
- { unsigned long long int _zzq_args[7]; \
- register unsigned long long int _zzq_result; \
- register unsigned long long int* _zzq_ptr; \
- _zzq_args[0] = (unsigned int long long)(_zzq_request); \
- _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \
- _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \
- _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \
- _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \
- _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \
- _zzq_args[6] = (unsigned int long long)(_zzq_default); \
- _zzq_ptr = _zzq_args; \
- __asm__ volatile("mr 4,%1\n\t" \
- "ld 3, 48(4)\n\t" \
+ __extension__ \
+ ({volatile unsigned int _zzq_args[6]; \
+ volatile unsigned int _zzq_result; \
+ _zzq_args[0] = (unsigned int)(_zzq_request); \
+ _zzq_args[1] = (unsigned int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned int)(_zzq_arg5); \
+ __asm__ volatile("mov r3, %1\n\t" /*default*/ \
+ "mov r4, %2\n\t" /*ptr*/ \
__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = client_request ( %R4 ) */ \
- "or 1,1,1\n\t" \
- "mr %0,3" \
- : "=b" (_zzq_result) \
- : "b" (_zzq_ptr) \
- : "r3", "r4", "cc", "memory"); \
- _zzq_rlval = _zzq_result; \
- (void)_zzq_rlval; \
- }
+ /* R3 = client_request ( R4 ) */ \
+ "orr r10, r10, r10\n\t" \
+ "mov %0, r3" /*result*/ \
+ : "=r" (_zzq_result) \
+ : "r" (_zzq_default), "r" (&_zzq_args[0]) \
+ : "cc","memory", "r3", "r4"); \
+ _zzq_result; \
+ })
#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
{ volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
- register unsigned long long int __addr; \
+ unsigned int __addr; \
__asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = guest_NRADDR */ \
- "or 2,2,2\n\t" \
- "mr %0,3" \
- : "=b" (__addr) \
+ /* R3 = guest_NRADDR */ \
+ "orr r11, r11, r11\n\t" \
+ "mov %0, r3" \
+ : "=r" (__addr) \
: \
- : "r3", "cc", "memory" \
+ : "cc", "memory", "r3" \
); \
_zzq_orig->nraddr = __addr; \
+ }
+
+#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* branch-and-link-to-noredir *%R4 */ \
+ "orr r12, r12, r12\n\t"
+
+#define VALGRIND_VEX_INJECT_IR() \
+ do { \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ "orr r9, r9, r9\n\t" \
+ : : : "cc", "memory" \
+ ); \
+ } while (0)
+
+#endif /* PLAT_arm_linux */
+
+/* ------------------------ arm64-linux ------------------------- */
+
+#if defined(PLAT_arm64_linux)
+
+typedef
+ struct {
+ unsigned long int nraddr; /* where's the code? */
+ }
+ OrigFn;
+
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "ror x12, x12, #3 ; ror x12, x12, #13 \n\t" \
+ "ror x12, x12, #51 ; ror x12, x12, #61 \n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
+ _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ \
+ __extension__ \
+ ({volatile unsigned long int _zzq_args[6]; \
+ volatile unsigned long int _zzq_result; \
+ _zzq_args[0] = (unsigned long int)(_zzq_request); \
+ _zzq_args[1] = (unsigned long int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned long int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned long int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned long int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned long int)(_zzq_arg5); \
+ __asm__ volatile("mov x3, %1\n\t" /*default*/ \
+ "mov x4, %2\n\t" /*ptr*/ \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* X3 = client_request ( X4 ) */ \
+ "orr x10, x10, x10\n\t" \
+ "mov %0, x3" /*result*/ \
+ : "=r" (_zzq_result) \
+ : "r" ((unsigned long int)(_zzq_default)), \
+ "r" (&_zzq_args[0]) \
+ : "cc","memory", "x3", "x4"); \
+ _zzq_result; \
+ })
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ unsigned long int __addr; \
__asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = guest_NRADDR_GPR2 */ \
- "or 4,4,4\n\t" \
- "mr %0,3" \
- : "=b" (__addr) \
+ /* X3 = guest_NRADDR */ \
+ "orr x11, x11, x11\n\t" \
+ "mov %0, x3" \
+ : "=r" (__addr) \
: \
- : "r3", "cc", "memory" \
+ : "cc", "memory", "x3" \
); \
- _zzq_orig->r2 = __addr; \
+ _zzq_orig->nraddr = __addr; \
}
-#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
__SPECIAL_INSTRUCTION_PREAMBLE \
- /* branch-and-link-to-noredir *%R11 */ \
- "or 3,3,3\n\t"
+ /* branch-and-link-to-noredir X8 */ \
+ "orr x12, x12, x12\n\t"
+
+#define VALGRIND_VEX_INJECT_IR() \
+ do { \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ "orr x9, x9, x9\n\t" \
+ : : : "cc", "memory" \
+ ); \
+ } while (0)
-#endif /* PLAT_ppc64_aix5 */
+#endif /* PLAT_arm64_linux */
+
+/* ------------------------ s390x-linux ------------------------ */
+
+#if defined(PLAT_s390x_linux)
+
+typedef
+ struct {
+ unsigned long int nraddr; /* where's the code? */
+ }
+ OrigFn;
+
+/* __SPECIAL_INSTRUCTION_PREAMBLE will be used to identify Valgrind specific
+ * code. This detection is implemented in platform specific toIR.c
+ * (e.g. VEX/priv/guest_s390_decoder.c).
+ */
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "lr 15,15\n\t" \
+ "lr 1,1\n\t" \
+ "lr 2,2\n\t" \
+ "lr 3,3\n\t"
+
+#define __CLIENT_REQUEST_CODE "lr 2,2\n\t"
+#define __GET_NR_CONTEXT_CODE "lr 3,3\n\t"
+#define __CALL_NO_REDIR_CODE "lr 4,4\n\t"
+#define __VEX_INJECT_IR_CODE "lr 5,5\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
+ _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ __extension__ \
+ ({volatile unsigned long int _zzq_args[6]; \
+ volatile unsigned long int _zzq_result; \
+ _zzq_args[0] = (unsigned long int)(_zzq_request); \
+ _zzq_args[1] = (unsigned long int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned long int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned long int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned long int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned long int)(_zzq_arg5); \
+ __asm__ volatile(/* r2 = args */ \
+ "lgr 2,%1\n\t" \
+ /* r3 = default */ \
+ "lgr 3,%2\n\t" \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ __CLIENT_REQUEST_CODE \
+ /* results = r3 */ \
+ "lgr %0, 3\n\t" \
+ : "=d" (_zzq_result) \
+ : "a" (&_zzq_args[0]), "0" (_zzq_default) \
+ : "cc", "2", "3", "memory" \
+ ); \
+ _zzq_result; \
+ })
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ volatile unsigned long int __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ __GET_NR_CONTEXT_CODE \
+ "lgr %0, 3\n\t" \
+ : "=a" (__addr) \
+ : \
+ : "cc", "3", "memory" \
+ ); \
+ _zzq_orig->nraddr = __addr; \
+ }
+
+#define VALGRIND_CALL_NOREDIR_R1 \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ __CALL_NO_REDIR_CODE
+
+#define VALGRIND_VEX_INJECT_IR() \
+ do { \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ __VEX_INJECT_IR_CODE); \
+ } while (0)
+
+#endif /* PLAT_s390x_linux */
+
+/* ------------------------- mips32-linux ---------------- */
+
+#if defined(PLAT_mips32_linux)
+
+typedef
+ struct {
+ unsigned int nraddr; /* where's the code? */
+ }
+ OrigFn;
+
+/* .word 0x342
+ * .word 0x742
+ * .word 0xC2
+ * .word 0x4C2*/
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "srl $0, $0, 13\n\t" \
+ "srl $0, $0, 29\n\t" \
+ "srl $0, $0, 3\n\t" \
+ "srl $0, $0, 19\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
+ _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ __extension__ \
+ ({ volatile unsigned int _zzq_args[6]; \
+ volatile unsigned int _zzq_result; \
+ _zzq_args[0] = (unsigned int)(_zzq_request); \
+ _zzq_args[1] = (unsigned int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned int)(_zzq_arg5); \
+ __asm__ volatile("move $11, %1\n\t" /*default*/ \
+ "move $12, %2\n\t" /*ptr*/ \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* T3 = client_request ( T4 ) */ \
+ "or $13, $13, $13\n\t" \
+ "move %0, $11\n\t" /*result*/ \
+ : "=r" (_zzq_result) \
+ : "r" (_zzq_default), "r" (&_zzq_args[0]) \
+ : "$11", "$12", "memory"); \
+ _zzq_result; \
+ })
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ volatile unsigned int __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %t9 = guest_NRADDR */ \
+ "or $14, $14, $14\n\t" \
+ "move %0, $11" /*result*/ \
+ : "=r" (__addr) \
+ : \
+ : "$11" \
+ ); \
+ _zzq_orig->nraddr = __addr; \
+ }
+
+#define VALGRIND_CALL_NOREDIR_T9 \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* call-noredir *%t9 */ \
+ "or $15, $15, $15\n\t"
+
+#define VALGRIND_VEX_INJECT_IR() \
+ do { \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ "or $11, $11, $11\n\t" \
+ ); \
+ } while (0)
+
+
+#endif /* PLAT_mips32_linux */
+
+/* ------------------------- mips64-linux ---------------- */
+
+#if defined(PLAT_mips64_linux)
+
+typedef
+ struct {
+ unsigned long nraddr; /* where's the code? */
+ }
+ OrigFn;
+
+/* dsll $0,$0, 3
+ * dsll $0,$0, 13
+ * dsll $0,$0, 29
+ * dsll $0,$0, 19*/
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "dsll $0,$0, 3 ; dsll $0,$0,13\n\t" \
+ "dsll $0,$0,29 ; dsll $0,$0,19\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
+ _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ __extension__ \
+ ({ volatile unsigned long int _zzq_args[6]; \
+ volatile unsigned long int _zzq_result; \
+ _zzq_args[0] = (unsigned long int)(_zzq_request); \
+ _zzq_args[1] = (unsigned long int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned long int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned long int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned long int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned long int)(_zzq_arg5); \
+ __asm__ volatile("move $11, %1\n\t" /*default*/ \
+ "move $12, %2\n\t" /*ptr*/ \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* $11 = client_request ( $12 ) */ \
+ "or $13, $13, $13\n\t" \
+ "move %0, $11\n\t" /*result*/ \
+ : "=r" (_zzq_result) \
+ : "r" (_zzq_default), "r" (&_zzq_args[0]) \
+ : "$11", "$12", "memory"); \
+ _zzq_result; \
+ })
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ volatile unsigned long int __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* $11 = guest_NRADDR */ \
+ "or $14, $14, $14\n\t" \
+ "move %0, $11" /*result*/ \
+ : "=r" (__addr) \
+ : \
+ : "$11"); \
+ _zzq_orig->nraddr = __addr; \
+ }
+
+#define VALGRIND_CALL_NOREDIR_T9 \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* call-noredir $25 */ \
+ "or $15, $15, $15\n\t"
+
+#define VALGRIND_VEX_INJECT_IR() \
+ do { \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ "or $11, $11, $11\n\t" \
+ ); \
+ } while (0)
+
+#endif /* PLAT_mips64_linux */
/* Insert assembly code for other platforms here... */
@@ -586,13 +1074,20 @@ typedef
*/
/* Use these to write the name of your wrapper. NOTE: duplicates
- VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
+ VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. NOTE also: inserts
+ the default behaviour equivalance class tag "0000" into the name.
+ See pub_tool_redir.h for details -- normally you don't need to
+ think about this, though. */
+
+/* Use an extra level of macroisation so as to ensure the soname/fnname
+ args are fully macro-expanded before pasting them together. */
+#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
- _vgwZU_##soname##_##fnname
+ VG_CONCAT4(_vgw00000ZU_,soname,_,fnname)
#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
- _vgwZZ_##soname##_##fnname
+ VG_CONCAT4(_vgw00000ZZ_,soname,_,fnname)
/* Use this macro from within a wrapper function to collect the
context (address and possibly other info) of the original function.
@@ -600,6 +1095,18 @@ typedef
macros. The type of the argument _lval is OrigFn. */
#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
+/* Also provide end-user facilities for function replacement, rather
+ than wrapping. A replacement function differs from a wrapper in
+ that it has no way to get hold of the original function being
+ called, and hence no way to call onwards to it. In a replacement
+ function, VALGRIND_GET_ORIG_FN always returns zero. */
+
+#define I_REPLACE_SONAME_FNNAME_ZU(soname,fnname) \
+ VG_CONCAT4(_vgr00000ZU_,soname,_,fnname)
+
+#define I_REPLACE_SONAME_FNNAME_ZZ(soname,fnname) \
+ VG_CONCAT4(_vgr00000ZZ_,soname,_,fnname)
+
/* Derivatives of the main macros below, for calling functions
returning void. */
@@ -619,14 +1126,42 @@ typedef
do { volatile unsigned long _junk; \
CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
-/* ------------------------- x86-linux ------------------------- */
+#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
+ do { volatile unsigned long _junk; \
+ CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
+
+#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
+ do { volatile unsigned long _junk; \
+ CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
+
+#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { volatile unsigned long _junk; \
+ CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
-#if defined(PLAT_x86_linux)
+#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
+ do { volatile unsigned long _junk; \
+ CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
+
+/* ----------------- x86-{linux,darwin,solaris} ---------------- */
+
+#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \
+ || defined(PLAT_x86_solaris)
/* These regs are trashed by the hidden call. No need to mention eax
as gcc can already see that, plus causes gcc to bomb. */
#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
+/* Macros to save and align the stack before making a function
+ call and restore it afterwards as gcc may not keep the stack
+ pointer aligned if it doesn't realise calls are being made
+ to other functions. */
+
+#define VALGRIND_ALIGN_STACK \
+ "movl %%esp,%%edi\n\t" \
+ "andl $0xfffffff0,%%esp\n\t"
+#define VALGRIND_RESTORE_STACK \
+ "movl %%edi,%%esp\n\t"
+
/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
long) == 4. */
@@ -637,11 +1172,13 @@ typedef
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -654,13 +1191,15 @@ typedef
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)(arg1); \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
+ "subl $12, %%esp\n\t" \
"pushl 4(%%eax)\n\t" \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
- "addl $4, %%esp\n" \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -674,14 +1213,16 @@ typedef
_argvec[1] = (unsigned long)(arg1); \
_argvec[2] = (unsigned long)(arg2); \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
+ "subl $8, %%esp\n\t" \
"pushl 8(%%eax)\n\t" \
"pushl 4(%%eax)\n\t" \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
- "addl $8, %%esp\n" \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -696,15 +1237,17 @@ typedef
_argvec[2] = (unsigned long)(arg2); \
_argvec[3] = (unsigned long)(arg3); \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
+ "subl $4, %%esp\n\t" \
"pushl 12(%%eax)\n\t" \
"pushl 8(%%eax)\n\t" \
"pushl 4(%%eax)\n\t" \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
- "addl $12, %%esp\n" \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -720,16 +1263,17 @@ typedef
_argvec[3] = (unsigned long)(arg3); \
_argvec[4] = (unsigned long)(arg4); \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"pushl 16(%%eax)\n\t" \
"pushl 12(%%eax)\n\t" \
"pushl 8(%%eax)\n\t" \
"pushl 4(%%eax)\n\t" \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
- "addl $16, %%esp\n" \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -746,6 +1290,8 @@ typedef
_argvec[4] = (unsigned long)(arg4); \
_argvec[5] = (unsigned long)(arg5); \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
+ "subl $12, %%esp\n\t" \
"pushl 20(%%eax)\n\t" \
"pushl 16(%%eax)\n\t" \
"pushl 12(%%eax)\n\t" \
@@ -753,10 +1299,10 @@ typedef
"pushl 4(%%eax)\n\t" \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
- "addl $20, %%esp\n" \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -774,6 +1320,8 @@ typedef
_argvec[5] = (unsigned long)(arg5); \
_argvec[6] = (unsigned long)(arg6); \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
+ "subl $8, %%esp\n\t" \
"pushl 24(%%eax)\n\t" \
"pushl 20(%%eax)\n\t" \
"pushl 16(%%eax)\n\t" \
@@ -782,10 +1330,10 @@ typedef
"pushl 4(%%eax)\n\t" \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
- "addl $24, %%esp\n" \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -805,6 +1353,8 @@ typedef
_argvec[6] = (unsigned long)(arg6); \
_argvec[7] = (unsigned long)(arg7); \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
+ "subl $4, %%esp\n\t" \
"pushl 28(%%eax)\n\t" \
"pushl 24(%%eax)\n\t" \
"pushl 20(%%eax)\n\t" \
@@ -814,10 +1364,10 @@ typedef
"pushl 4(%%eax)\n\t" \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
- "addl $28, %%esp\n" \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -838,6 +1388,7 @@ typedef
_argvec[7] = (unsigned long)(arg7); \
_argvec[8] = (unsigned long)(arg8); \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"pushl 32(%%eax)\n\t" \
"pushl 28(%%eax)\n\t" \
"pushl 24(%%eax)\n\t" \
@@ -848,10 +1399,10 @@ typedef
"pushl 4(%%eax)\n\t" \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
- "addl $32, %%esp\n" \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -873,6 +1424,8 @@ typedef
_argvec[8] = (unsigned long)(arg8); \
_argvec[9] = (unsigned long)(arg9); \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
+ "subl $12, %%esp\n\t" \
"pushl 36(%%eax)\n\t" \
"pushl 32(%%eax)\n\t" \
"pushl 28(%%eax)\n\t" \
@@ -884,10 +1437,10 @@ typedef
"pushl 4(%%eax)\n\t" \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
- "addl $36, %%esp\n" \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -910,6 +1463,8 @@ typedef
_argvec[9] = (unsigned long)(arg9); \
_argvec[10] = (unsigned long)(arg10); \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
+ "subl $8, %%esp\n\t" \
"pushl 40(%%eax)\n\t" \
"pushl 36(%%eax)\n\t" \
"pushl 32(%%eax)\n\t" \
@@ -922,10 +1477,10 @@ typedef
"pushl 4(%%eax)\n\t" \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
- "addl $40, %%esp\n" \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -950,6 +1505,8 @@ typedef
_argvec[10] = (unsigned long)(arg10); \
_argvec[11] = (unsigned long)(arg11); \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
+ "subl $4, %%esp\n\t" \
"pushl 44(%%eax)\n\t" \
"pushl 40(%%eax)\n\t" \
"pushl 36(%%eax)\n\t" \
@@ -963,10 +1520,10 @@ typedef
"pushl 4(%%eax)\n\t" \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
- "addl $44, %%esp\n" \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -992,6 +1549,7 @@ typedef
_argvec[11] = (unsigned long)(arg11); \
_argvec[12] = (unsigned long)(arg12); \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"pushl 48(%%eax)\n\t" \
"pushl 44(%%eax)\n\t" \
"pushl 40(%%eax)\n\t" \
@@ -1006,19 +1564,20 @@ typedef
"pushl 4(%%eax)\n\t" \
"movl (%%eax), %%eax\n\t" /* target->%eax */ \
VALGRIND_CALL_NOREDIR_EAX \
- "addl $48, %%esp\n" \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=a" (_res) \
: /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
-#endif /* PLAT_x86_linux */
+#endif /* PLAT_x86_linux || PLAT_x86_darwin || PLAT_x86_solaris */
-/* ------------------------ amd64-linux ------------------------ */
+/* ---------------- amd64-{linux,darwin,solaris} --------------- */
-#if defined(PLAT_amd64_linux)
+#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) \
+ || defined(PLAT_amd64_solaris)
/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
@@ -1026,6 +1585,88 @@ typedef
#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
"rdi", "r8", "r9", "r10", "r11"
+/* This is all pretty complex. It's so as to make stack unwinding
+ work reliably. See bug 243270. The basic problem is the sub and
+ add of 128 of %rsp in all of the following macros. If gcc believes
+ the CFA is in %rsp, then unwinding may fail, because what's at the
+ CFA is not what gcc "expected" when it constructs the CFIs for the
+ places where the macros are instantiated.
+
+ But we can't just add a CFI annotation to increase the CFA offset
+ by 128, to match the sub of 128 from %rsp, because we don't know
+ whether gcc has chosen %rsp as the CFA at that point, or whether it
+ has chosen some other register (eg, %rbp). In the latter case,
+ adding a CFI annotation to change the CFA offset is simply wrong.
+
+ So the solution is to get hold of the CFA using
+ __builtin_dwarf_cfa(), put it in a known register, and add a
+ CFI annotation to say what the register is. We choose %rbp for
+ this (perhaps perversely), because:
+
+ (1) %rbp is already subject to unwinding. If a new register was
+ chosen then the unwinder would have to unwind it in all stack
+ traces, which is expensive, and
+
+ (2) %rbp is already subject to precise exception updates in the
+ JIT. If a new register was chosen, we'd have to have precise
+ exceptions for it too, which reduces performance of the
+ generated code.
+
+ However .. one extra complication. We can't just whack the result
+ of __builtin_dwarf_cfa() into %rbp and then add %rbp to the
+ list of trashed registers at the end of the inline assembly
+ fragments; gcc won't allow %rbp to appear in that list. Hence
+ instead we need to stash %rbp in %r15 for the duration of the asm,
+ and say that %r15 is trashed instead. gcc seems happy to go with
+ that.
+
+ Oh .. and this all needs to be conditionalised so that it is
+ unchanged from before this commit, when compiled with older gccs
+ that don't support __builtin_dwarf_cfa. Furthermore, since
+ this header file is freestanding, it has to be independent of
+ config.h, and so the following conditionalisation cannot depend on
+ configure time checks.
+
+ Although it's not clear from
+ 'defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)',
+ this expression excludes Darwin.
+ .cfi directives in Darwin assembly appear to be completely
+ different and I haven't investigated how they work.
+
+ For even more entertainment value, note we have to use the
+ completely undocumented __builtin_dwarf_cfa(), which appears to
+ really compute the CFA, whereas __builtin_frame_address(0) claims
+ to but actually doesn't. See
+ https://bugs.kde.org/show_bug.cgi?id=243270#c47
+*/
+#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
+# define __FRAME_POINTER \
+ ,"r"(__builtin_dwarf_cfa())
+# define VALGRIND_CFI_PROLOGUE \
+ "movq %%rbp, %%r15\n\t" \
+ "movq %2, %%rbp\n\t" \
+ ".cfi_remember_state\n\t" \
+ ".cfi_def_cfa rbp, 0\n\t"
+# define VALGRIND_CFI_EPILOGUE \
+ "movq %%r15, %%rbp\n\t" \
+ ".cfi_restore_state\n\t"
+#else
+# define __FRAME_POINTER
+# define VALGRIND_CFI_PROLOGUE
+# define VALGRIND_CFI_EPILOGUE
+#endif
+
+/* Macros to save and align the stack before making a function
+ call and restore it afterwards as gcc may not keep the stack
+ pointer aligned if it doesn't realise calls are being made
+ to other functions. */
+
+#define VALGRIND_ALIGN_STACK \
+ "movq %%rsp,%%r14\n\t" \
+ "andq $0xfffffffffffffff0,%%rsp\n\t"
+#define VALGRIND_RESTORE_STACK \
+ "movq %%r14,%%rsp\n\t"
+
/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
long) == 8. */
@@ -1045,414 +1686,447 @@ typedef
redzone, for the duration of the hidden call, to make it safe.
Probably the same problem afflicts the other redzone-style ABIs too
- (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
+ (ppc64-linux); but for those, the stack is
self describing (none of this CFI nonsense) so at least messing
with the stack pointer doesn't give a danger of non-unwindable
stack. */
-#define CALL_FN_W_v(lval, orig) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[1]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[1]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ VALGRIND_ALIGN_STACK \
+ "subq $128,%%rsp\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ VALGRIND_RESTORE_STACK \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
} while (0)
-#define CALL_FN_W_W(lval, orig, arg1) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[2]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[2]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ VALGRIND_ALIGN_STACK \
+ "subq $128,%%rsp\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ VALGRIND_RESTORE_STACK \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
} while (0)
-#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ VALGRIND_ALIGN_STACK \
+ "subq $128,%%rsp\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ VALGRIND_RESTORE_STACK \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
} while (0)
-#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[4]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[4]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ VALGRIND_ALIGN_STACK \
+ "subq $128,%%rsp\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ VALGRIND_RESTORE_STACK \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
} while (0)
-#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[5]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[5]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ VALGRIND_ALIGN_STACK \
+ "subq $128,%%rsp\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ VALGRIND_RESTORE_STACK \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
} while (0)
-#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[6]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "movq 40(%%rax), %%r8\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[6]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ VALGRIND_ALIGN_STACK \
+ "subq $128,%%rsp\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ VALGRIND_RESTORE_STACK \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
} while (0)
-#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[7]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "movq 48(%%rax), %%r9\n\t" \
- "movq 40(%%rax), %%r8\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- "addq $128,%%rsp\n\t" \
- VALGRIND_CALL_NOREDIR_RAX \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[7]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ VALGRIND_ALIGN_STACK \
+ "subq $128,%%rsp\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ VALGRIND_RESTORE_STACK \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
} while (0)
-#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[8]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "pushq 56(%%rax)\n\t" \
- "movq 48(%%rax), %%r9\n\t" \
- "movq 40(%%rax), %%r8\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $8, %%rsp\n" \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[8]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ VALGRIND_ALIGN_STACK \
+ "subq $136,%%rsp\n\t" \
+ "pushq 56(%%rax)\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ VALGRIND_RESTORE_STACK \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
} while (0)
-#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[9]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "pushq 64(%%rax)\n\t" \
- "pushq 56(%%rax)\n\t" \
- "movq 48(%%rax), %%r9\n\t" \
- "movq 40(%%rax), %%r8\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $16, %%rsp\n" \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[9]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ VALGRIND_ALIGN_STACK \
+ "subq $128,%%rsp\n\t" \
+ "pushq 64(%%rax)\n\t" \
+ "pushq 56(%%rax)\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ VALGRIND_RESTORE_STACK \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
} while (0)
-#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[10]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- _argvec[9] = (unsigned long)(arg9); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "pushq 72(%%rax)\n\t" \
- "pushq 64(%%rax)\n\t" \
- "pushq 56(%%rax)\n\t" \
- "movq 48(%%rax), %%r9\n\t" \
- "movq 40(%%rax), %%r8\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $24, %%rsp\n" \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[10]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ VALGRIND_ALIGN_STACK \
+ "subq $136,%%rsp\n\t" \
+ "pushq 72(%%rax)\n\t" \
+ "pushq 64(%%rax)\n\t" \
+ "pushq 56(%%rax)\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ VALGRIND_RESTORE_STACK \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
} while (0)
-#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[11]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- _argvec[9] = (unsigned long)(arg9); \
- _argvec[10] = (unsigned long)(arg10); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "pushq 80(%%rax)\n\t" \
- "pushq 72(%%rax)\n\t" \
- "pushq 64(%%rax)\n\t" \
- "pushq 56(%%rax)\n\t" \
- "movq 48(%%rax), %%r9\n\t" \
- "movq 40(%%rax), %%r8\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $32, %%rsp\n" \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[11]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ VALGRIND_ALIGN_STACK \
+ "subq $128,%%rsp\n\t" \
+ "pushq 80(%%rax)\n\t" \
+ "pushq 72(%%rax)\n\t" \
+ "pushq 64(%%rax)\n\t" \
+ "pushq 56(%%rax)\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ VALGRIND_RESTORE_STACK \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
} while (0)
-#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10,arg11) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[12]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- _argvec[9] = (unsigned long)(arg9); \
- _argvec[10] = (unsigned long)(arg10); \
- _argvec[11] = (unsigned long)(arg11); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "pushq 88(%%rax)\n\t" \
- "pushq 80(%%rax)\n\t" \
- "pushq 72(%%rax)\n\t" \
- "pushq 64(%%rax)\n\t" \
- "pushq 56(%%rax)\n\t" \
- "movq 48(%%rax), %%r9\n\t" \
- "movq 40(%%rax), %%r8\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $40, %%rsp\n" \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[12]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ _argvec[11] = (unsigned long)(arg11); \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ VALGRIND_ALIGN_STACK \
+ "subq $136,%%rsp\n\t" \
+ "pushq 88(%%rax)\n\t" \
+ "pushq 80(%%rax)\n\t" \
+ "pushq 72(%%rax)\n\t" \
+ "pushq 64(%%rax)\n\t" \
+ "pushq 56(%%rax)\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ VALGRIND_RESTORE_STACK \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
} while (0)
-#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10,arg11,arg12) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[13]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- _argvec[9] = (unsigned long)(arg9); \
- _argvec[10] = (unsigned long)(arg10); \
- _argvec[11] = (unsigned long)(arg11); \
- _argvec[12] = (unsigned long)(arg12); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "pushq 96(%%rax)\n\t" \
- "pushq 88(%%rax)\n\t" \
- "pushq 80(%%rax)\n\t" \
- "pushq 72(%%rax)\n\t" \
- "pushq 64(%%rax)\n\t" \
- "pushq 56(%%rax)\n\t" \
- "movq 48(%%rax), %%r9\n\t" \
- "movq 40(%%rax), %%r8\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $48, %%rsp\n" \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11,arg12) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[13]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ _argvec[11] = (unsigned long)(arg11); \
+ _argvec[12] = (unsigned long)(arg12); \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ VALGRIND_ALIGN_STACK \
+ "subq $128,%%rsp\n\t" \
+ "pushq 96(%%rax)\n\t" \
+ "pushq 88(%%rax)\n\t" \
+ "pushq 80(%%rax)\n\t" \
+ "pushq 72(%%rax)\n\t" \
+ "pushq 64(%%rax)\n\t" \
+ "pushq 56(%%rax)\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ VALGRIND_RESTORE_STACK \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
} while (0)
-#endif /* PLAT_amd64_linux */
+#endif /* PLAT_amd64_linux || PLAT_amd64_darwin || PLAT_amd64_solaris */
/* ------------------------ ppc32-linux ------------------------ */
@@ -1488,6 +2162,17 @@ typedef
"r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
"r11", "r12", "r13"
+/* Macros to save and align the stack before making a function
+ call and restore it afterwards as gcc may not keep the stack
+ pointer aligned if it doesn't realise calls are being made
+ to other functions. */
+
+#define VALGRIND_ALIGN_STACK \
+ "mr 28,1\n\t" \
+ "rlwinm 1,1,0,0,27\n\t"
+#define VALGRIND_RESTORE_STACK \
+ "mr 1,28\n\t"
+
/* These CALL_FN_ macros assume that on ppc32-linux,
sizeof(unsigned long) == 4. */
@@ -1498,13 +2183,15 @@ typedef
volatile unsigned long _res; \
_argvec[0] = (unsigned long)_orig.nraddr; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -1517,14 +2204,16 @@ typedef
_argvec[0] = (unsigned long)_orig.nraddr; \
_argvec[1] = (unsigned long)arg1; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"lwz 3,4(11)\n\t" /* arg1->r3 */ \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -1538,15 +2227,17 @@ typedef
_argvec[1] = (unsigned long)arg1; \
_argvec[2] = (unsigned long)arg2; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"lwz 3,4(11)\n\t" /* arg1->r3 */ \
"lwz 4,8(11)\n\t" \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -1561,16 +2252,18 @@ typedef
_argvec[2] = (unsigned long)arg2; \
_argvec[3] = (unsigned long)arg3; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"lwz 3,4(11)\n\t" /* arg1->r3 */ \
"lwz 4,8(11)\n\t" \
"lwz 5,12(11)\n\t" \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -1586,6 +2279,7 @@ typedef
_argvec[3] = (unsigned long)arg3; \
_argvec[4] = (unsigned long)arg4; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"lwz 3,4(11)\n\t" /* arg1->r3 */ \
"lwz 4,8(11)\n\t" \
@@ -1593,10 +2287,11 @@ typedef
"lwz 6,16(11)\n\t" /* arg4->r6 */ \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -1613,6 +2308,7 @@ typedef
_argvec[4] = (unsigned long)arg4; \
_argvec[5] = (unsigned long)arg5; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"lwz 3,4(11)\n\t" /* arg1->r3 */ \
"lwz 4,8(11)\n\t" \
@@ -1621,10 +2317,11 @@ typedef
"lwz 7,20(11)\n\t" \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -1642,6 +2339,7 @@ typedef
_argvec[5] = (unsigned long)arg5; \
_argvec[6] = (unsigned long)arg6; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"lwz 3,4(11)\n\t" /* arg1->r3 */ \
"lwz 4,8(11)\n\t" \
@@ -1651,10 +2349,11 @@ typedef
"lwz 8,24(11)\n\t" \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -1674,6 +2373,7 @@ typedef
_argvec[6] = (unsigned long)arg6; \
_argvec[7] = (unsigned long)arg7; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"lwz 3,4(11)\n\t" /* arg1->r3 */ \
"lwz 4,8(11)\n\t" \
@@ -1684,10 +2384,11 @@ typedef
"lwz 9,28(11)\n\t" \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -1708,6 +2409,7 @@ typedef
_argvec[7] = (unsigned long)arg7; \
_argvec[8] = (unsigned long)arg8; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"lwz 3,4(11)\n\t" /* arg1->r3 */ \
"lwz 4,8(11)\n\t" \
@@ -1719,10 +2421,11 @@ typedef
"lwz 10,32(11)\n\t" /* arg8->r10 */ \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -1744,6 +2447,7 @@ typedef
_argvec[8] = (unsigned long)arg8; \
_argvec[9] = (unsigned long)arg9; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"addi 1,1,-16\n\t" \
/* arg9 */ \
@@ -1760,11 +2464,11 @@ typedef
"lwz 10,32(11)\n\t" /* arg8->r10 */ \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "addi 1,1,16\n\t" \
+ VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -1787,6 +2491,7 @@ typedef
_argvec[9] = (unsigned long)arg9; \
_argvec[10] = (unsigned long)arg10; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"addi 1,1,-16\n\t" \
/* arg10 */ \
@@ -1806,11 +2511,11 @@ typedef
"lwz 10,32(11)\n\t" /* arg8->r10 */ \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "addi 1,1,16\n\t" \
+ VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -1834,6 +2539,7 @@ typedef
_argvec[10] = (unsigned long)arg10; \
_argvec[11] = (unsigned long)arg11; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"addi 1,1,-32\n\t" \
/* arg11 */ \
@@ -1856,11 +2562,11 @@ typedef
"lwz 10,32(11)\n\t" /* arg8->r10 */ \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "addi 1,1,32\n\t" \
+ VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -1885,6 +2591,7 @@ typedef
_argvec[11] = (unsigned long)arg11; \
_argvec[12] = (unsigned long)arg12; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"addi 1,1,-32\n\t" \
/* arg12 */ \
@@ -1910,11 +2617,11 @@ typedef
"lwz 10,32(11)\n\t" /* arg8->r10 */ \
"lwz 11,0(11)\n\t" /* target->r11 */ \
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "addi 1,1,32\n\t" \
+ VALGRIND_RESTORE_STACK \
"mr %0,3" \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -1923,7 +2630,7 @@ typedef
/* ------------------------ ppc64-linux ------------------------ */
-#if defined(PLAT_ppc64_linux)
+#if defined(PLAT_ppc64be_linux)
/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
@@ -1931,9 +2638,20 @@ typedef
#define __CALLER_SAVED_REGS \
"lr", "ctr", "xer", \
"cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
- "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
+ "r0", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
"r11", "r12", "r13"
+/* Macros to save and align the stack before making a function
+ call and restore it afterwards as gcc may not keep the stack
+ pointer aligned if it doesn't realise calls are being made
+ to other functions. */
+
+#define VALGRIND_ALIGN_STACK \
+ "mr 28,1\n\t" \
+ "rldicr 1,1,0,59\n\t"
+#define VALGRIND_RESTORE_STACK \
+ "mr 1,28\n\t"
+
/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
long) == 8. */
@@ -1946,6 +2664,7 @@ typedef
_argvec[1] = (unsigned long)_orig.r2; \
_argvec[2] = (unsigned long)_orig.nraddr; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
@@ -1953,10 +2672,11 @@ typedef
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -1971,6 +2691,7 @@ typedef
_argvec[2] = (unsigned long)_orig.nraddr; \
_argvec[2+1] = (unsigned long)arg1; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
@@ -1979,10 +2700,11 @@ typedef
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -1998,6 +2720,7 @@ typedef
_argvec[2+1] = (unsigned long)arg1; \
_argvec[2+2] = (unsigned long)arg2; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
@@ -2007,10 +2730,11 @@ typedef
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -2027,6 +2751,7 @@ typedef
_argvec[2+2] = (unsigned long)arg2; \
_argvec[2+3] = (unsigned long)arg3; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
@@ -2037,10 +2762,11 @@ typedef
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -2058,6 +2784,7 @@ typedef
_argvec[2+3] = (unsigned long)arg3; \
_argvec[2+4] = (unsigned long)arg4; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
@@ -2069,10 +2796,11 @@ typedef
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -2091,6 +2819,7 @@ typedef
_argvec[2+4] = (unsigned long)arg4; \
_argvec[2+5] = (unsigned long)arg5; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
@@ -2103,10 +2832,11 @@ typedef
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -2126,6 +2856,7 @@ typedef
_argvec[2+5] = (unsigned long)arg5; \
_argvec[2+6] = (unsigned long)arg6; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
@@ -2139,10 +2870,11 @@ typedef
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -2164,6 +2896,7 @@ typedef
_argvec[2+6] = (unsigned long)arg6; \
_argvec[2+7] = (unsigned long)arg7; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
@@ -2178,10 +2911,11 @@ typedef
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -2204,6 +2938,7 @@ typedef
_argvec[2+7] = (unsigned long)arg7; \
_argvec[2+8] = (unsigned long)arg8; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
@@ -2219,10 +2954,11 @@ typedef
VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -2246,6 +2982,7 @@ typedef
_argvec[2+8] = (unsigned long)arg8; \
_argvec[2+9] = (unsigned long)arg9; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
@@ -2267,10 +3004,10 @@ typedef
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
"ld 2,-16(11)\n\t" /* restore tocptr */ \
- "addi 1,1,128" /* restore frame */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -2295,6 +3032,7 @@ typedef
_argvec[2+9] = (unsigned long)arg9; \
_argvec[2+10] = (unsigned long)arg10; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
@@ -2319,10 +3057,10 @@ typedef
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
"ld 2,-16(11)\n\t" /* restore tocptr */ \
- "addi 1,1,128" /* restore frame */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -2348,6 +3086,7 @@ typedef
_argvec[2+10] = (unsigned long)arg10; \
_argvec[2+11] = (unsigned long)arg11; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
@@ -2375,10 +3114,10 @@ typedef
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
"ld 2,-16(11)\n\t" /* restore tocptr */ \
- "addi 1,1,144" /* restore frame */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -2405,6 +3144,7 @@ typedef
_argvec[2+11] = (unsigned long)arg11; \
_argvec[2+12] = (unsigned long)arg12; \
__asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
"mr 11,%1\n\t" \
"std 2,-16(11)\n\t" /* save tocptr */ \
"ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
@@ -2435,19 +3175,18 @@ typedef
"mr 11,%1\n\t" \
"mr %0,3\n\t" \
"ld 2,-16(11)\n\t" /* restore tocptr */ \
- "addi 1,1,144" /* restore frame */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
-#endif /* PLAT_ppc64_linux */
+#endif /* PLAT_ppc64be_linux */
-/* ------------------------ ppc32-aix5 ------------------------- */
-
-#if defined(PLAT_ppc32_aix5)
+/* ------------------------- ppc64le-linux ----------------------- */
+#if defined(PLAT_ppc64le_linux)
/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
@@ -2455,22 +3194,22 @@ typedef
#define __CALLER_SAVED_REGS \
"lr", "ctr", "xer", \
"cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
- "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
+ "r0", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
"r11", "r12", "r13"
-/* Expand the stack frame, copying enough info that unwinding
- still works. Trashes r3. */
-
-#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
- "addi 1,1,-" #_n_fr "\n\t" \
- "lwz 3," #_n_fr "(1)\n\t" \
- "stw 3,0(1)\n\t"
+/* Macros to save and align the stack before making a function
+ call and restore it afterwards as gcc may not keep the stack
+ pointer aligned if it doesn't realise calls are being made
+ to other functions. */
-#define VG_CONTRACT_FRAME_BY(_n_fr) \
- "addi 1,1," #_n_fr "\n\t"
+#define VALGRIND_ALIGN_STACK \
+ "mr 28,1\n\t" \
+ "rldicr 1,1,0,59\n\t"
+#define VALGRIND_RESTORE_STACK \
+ "mr 1,28\n\t"
-/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
- long) == 4. */
+/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
+ long) == 8. */
#define CALL_FN_W_v(lval, orig) \
do { \
@@ -2481,19 +3220,19 @@ typedef
_argvec[1] = (unsigned long)_orig.r2; \
_argvec[2] = (unsigned long)_orig.nraddr; \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
+ VALGRIND_ALIGN_STACK \
+ "mr 12,%1\n\t" \
+ "std 2,-16(12)\n\t" /* save tocptr */ \
+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
+ "ld 12, 0(12)\n\t" /* target->r12 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
+ "mr 12,%1\n\t" \
"mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
+ "ld 2,-16(12)\n\t" /* restore tocptr */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -2508,20 +3247,20 @@ typedef
_argvec[2] = (unsigned long)_orig.nraddr; \
_argvec[2+1] = (unsigned long)arg1; \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
+ VALGRIND_ALIGN_STACK \
+ "mr 12,%1\n\t" \
+ "std 2,-16(12)\n\t" /* save tocptr */ \
+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(12)\n\t" /* arg1->r3 */ \
+ "ld 12, 0(12)\n\t" /* target->r12 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
+ "mr 12,%1\n\t" \
"mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
+ "ld 2,-16(12)\n\t" /* restore tocptr */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -2537,21 +3276,21 @@ typedef
_argvec[2+1] = (unsigned long)arg1; \
_argvec[2+2] = (unsigned long)arg2; \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
+ VALGRIND_ALIGN_STACK \
+ "mr 12,%1\n\t" \
+ "std 2,-16(12)\n\t" /* save tocptr */ \
+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(12)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(12)\n\t" /* arg2->r4 */ \
+ "ld 12, 0(12)\n\t" /* target->r12 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
+ "mr 12,%1\n\t" \
"mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
+ "ld 2,-16(12)\n\t" /* restore tocptr */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -2568,22 +3307,22 @@ typedef
_argvec[2+2] = (unsigned long)arg2; \
_argvec[2+3] = (unsigned long)arg3; \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
+ VALGRIND_ALIGN_STACK \
+ "mr 12,%1\n\t" \
+ "std 2,-16(12)\n\t" /* save tocptr */ \
+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(12)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(12)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(12)\n\t" /* arg3->r5 */ \
+ "ld 12, 0(12)\n\t" /* target->r12 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
+ "mr 12,%1\n\t" \
"mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
+ "ld 2,-16(12)\n\t" /* restore tocptr */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -2601,23 +3340,23 @@ typedef
_argvec[2+3] = (unsigned long)arg3; \
_argvec[2+4] = (unsigned long)arg4; \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
+ VALGRIND_ALIGN_STACK \
+ "mr 12,%1\n\t" \
+ "std 2,-16(12)\n\t" /* save tocptr */ \
+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(12)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(12)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(12)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(12)\n\t" /* arg4->r6 */ \
+ "ld 12, 0(12)\n\t" /* target->r12 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
+ "mr 12,%1\n\t" \
"mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
+ "ld 2,-16(12)\n\t" /* restore tocptr */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -2636,24 +3375,24 @@ typedef
_argvec[2+4] = (unsigned long)arg4; \
_argvec[2+5] = (unsigned long)arg5; \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
+ VALGRIND_ALIGN_STACK \
+ "mr 12,%1\n\t" \
+ "std 2,-16(12)\n\t" /* save tocptr */ \
+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(12)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(12)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(12)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(12)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(12)\n\t" /* arg5->r7 */ \
+ "ld 12, 0(12)\n\t" /* target->r12 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
+ "mr 12,%1\n\t" \
"mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
+ "ld 2,-16(12)\n\t" /* restore tocptr */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -2673,25 +3412,25 @@ typedef
_argvec[2+5] = (unsigned long)arg5; \
_argvec[2+6] = (unsigned long)arg6; \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
- "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
+ VALGRIND_ALIGN_STACK \
+ "mr 12,%1\n\t" \
+ "std 2,-16(12)\n\t" /* save tocptr */ \
+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(12)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(12)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(12)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(12)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(12)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(12)\n\t" /* arg6->r8 */ \
+ "ld 12, 0(12)\n\t" /* target->r12 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
+ "mr 12,%1\n\t" \
"mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
+ "ld 2,-16(12)\n\t" /* restore tocptr */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -2713,26 +3452,26 @@ typedef
_argvec[2+6] = (unsigned long)arg6; \
_argvec[2+7] = (unsigned long)arg7; \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
- "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
- "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
+ VALGRIND_ALIGN_STACK \
+ "mr 12,%1\n\t" \
+ "std 2,-16(12)\n\t" /* save tocptr */ \
+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(12)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(12)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(12)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(12)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(12)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(12)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(12)\n\t" /* arg7->r9 */ \
+ "ld 12, 0(12)\n\t" /* target->r12 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
+ "mr 12,%1\n\t" \
"mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
+ "ld 2,-16(12)\n\t" /* restore tocptr */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -2755,27 +3494,27 @@ typedef
_argvec[2+7] = (unsigned long)arg7; \
_argvec[2+8] = (unsigned long)arg8; \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
- "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
- "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
- "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
+ VALGRIND_ALIGN_STACK \
+ "mr 12,%1\n\t" \
+ "std 2,-16(12)\n\t" /* save tocptr */ \
+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(12)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(12)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(12)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(12)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(12)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(12)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(12)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(12)\n\t" /* arg8->r10 */ \
+ "ld 12, 0(12)\n\t" /* target->r12 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
+ "mr 12,%1\n\t" \
"mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
+ "ld 2,-16(12)\n\t" /* restore tocptr */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -2799,33 +3538,32 @@ typedef
_argvec[2+8] = (unsigned long)arg8; \
_argvec[2+9] = (unsigned long)arg9; \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- VG_EXPAND_FRAME_BY_trashes_r3(64) \
+ VALGRIND_ALIGN_STACK \
+ "mr 12,%1\n\t" \
+ "std 2,-16(12)\n\t" /* save tocptr */ \
+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
+ "addi 1,1,-128\n\t" /* expand stack frame */ \
/* arg9 */ \
- "lwz 3,36(11)\n\t" \
- "stw 3,56(1)\n\t" \
+ "ld 3,72(12)\n\t" \
+ "std 3,96(1)\n\t" \
/* args1-8 */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
- "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
- "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
- "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
+ "ld 3, 8(12)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(12)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(12)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(12)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(12)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(12)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(12)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(12)\n\t" /* arg8->r10 */ \
+ "ld 12, 0(12)\n\t" /* target->r12 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
+ "mr 12,%1\n\t" \
"mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(64) \
- VG_CONTRACT_FRAME_BY(512) \
+ "ld 2,-16(12)\n\t" /* restore tocptr */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -2850,36 +3588,35 @@ typedef
_argvec[2+9] = (unsigned long)arg9; \
_argvec[2+10] = (unsigned long)arg10; \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- VG_EXPAND_FRAME_BY_trashes_r3(64) \
+ VALGRIND_ALIGN_STACK \
+ "mr 12,%1\n\t" \
+ "std 2,-16(12)\n\t" /* save tocptr */ \
+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
+ "addi 1,1,-128\n\t" /* expand stack frame */ \
/* arg10 */ \
- "lwz 3,40(11)\n\t" \
- "stw 3,60(1)\n\t" \
+ "ld 3,80(12)\n\t" \
+ "std 3,104(1)\n\t" \
/* arg9 */ \
- "lwz 3,36(11)\n\t" \
- "stw 3,56(1)\n\t" \
+ "ld 3,72(12)\n\t" \
+ "std 3,96(1)\n\t" \
/* args1-8 */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
- "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
- "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
- "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
+ "ld 3, 8(12)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(12)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(12)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(12)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(12)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(12)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(12)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(12)\n\t" /* arg8->r10 */ \
+ "ld 12, 0(12)\n\t" /* target->r12 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
+ "mr 12,%1\n\t" \
"mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(64) \
- VG_CONTRACT_FRAME_BY(512) \
+ "ld 2,-16(12)\n\t" /* restore tocptr */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -2905,39 +3642,38 @@ typedef
_argvec[2+10] = (unsigned long)arg10; \
_argvec[2+11] = (unsigned long)arg11; \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- VG_EXPAND_FRAME_BY_trashes_r3(72) \
+ VALGRIND_ALIGN_STACK \
+ "mr 12,%1\n\t" \
+ "std 2,-16(12)\n\t" /* save tocptr */ \
+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
+ "addi 1,1,-144\n\t" /* expand stack frame */ \
/* arg11 */ \
- "lwz 3,44(11)\n\t" \
- "stw 3,64(1)\n\t" \
+ "ld 3,88(12)\n\t" \
+ "std 3,112(1)\n\t" \
/* arg10 */ \
- "lwz 3,40(11)\n\t" \
- "stw 3,60(1)\n\t" \
+ "ld 3,80(12)\n\t" \
+ "std 3,104(1)\n\t" \
/* arg9 */ \
- "lwz 3,36(11)\n\t" \
- "stw 3,56(1)\n\t" \
+ "ld 3,72(12)\n\t" \
+ "std 3,96(1)\n\t" \
/* args1-8 */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
- "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
- "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
- "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
+ "ld 3, 8(12)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(12)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(12)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(12)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(12)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(12)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(12)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(12)\n\t" /* arg8->r10 */ \
+ "ld 12, 0(12)\n\t" /* target->r12 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
+ "mr 12,%1\n\t" \
"mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(72) \
- VG_CONTRACT_FRAME_BY(512) \
+ "ld 2,-16(12)\n\t" /* restore tocptr */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -2964,97 +3700,546 @@ typedef
_argvec[2+11] = (unsigned long)arg11; \
_argvec[2+12] = (unsigned long)arg12; \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- VG_EXPAND_FRAME_BY_trashes_r3(72) \
+ VALGRIND_ALIGN_STACK \
+ "mr 12,%1\n\t" \
+ "std 2,-16(12)\n\t" /* save tocptr */ \
+ "ld 2,-8(12)\n\t" /* use nraddr's tocptr */ \
+ "addi 1,1,-144\n\t" /* expand stack frame */ \
/* arg12 */ \
- "lwz 3,48(11)\n\t" \
- "stw 3,68(1)\n\t" \
+ "ld 3,96(12)\n\t" \
+ "std 3,120(1)\n\t" \
/* arg11 */ \
- "lwz 3,44(11)\n\t" \
- "stw 3,64(1)\n\t" \
+ "ld 3,88(12)\n\t" \
+ "std 3,112(1)\n\t" \
/* arg10 */ \
- "lwz 3,40(11)\n\t" \
- "stw 3,60(1)\n\t" \
+ "ld 3,80(12)\n\t" \
+ "std 3,104(1)\n\t" \
/* arg9 */ \
- "lwz 3,36(11)\n\t" \
- "stw 3,56(1)\n\t" \
+ "ld 3,72(12)\n\t" \
+ "std 3,96(1)\n\t" \
/* args1-8 */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
- "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
- "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
- "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
+ "ld 3, 8(12)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(12)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(12)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(12)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(12)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(12)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(12)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(12)\n\t" /* arg8->r10 */ \
+ "ld 12, 0(12)\n\t" /* target->r12 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R12 \
+ "mr 12,%1\n\t" \
"mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(72) \
- VG_CONTRACT_FRAME_BY(512) \
+ "ld 2,-16(12)\n\t" /* restore tocptr */ \
+ VALGRIND_RESTORE_STACK \
: /*out*/ "=r" (_res) \
: /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
-#endif /* PLAT_ppc32_aix5 */
+#endif /* PLAT_ppc64le_linux */
-/* ------------------------ ppc64-aix5 ------------------------- */
+/* ------------------------- arm-linux ------------------------- */
-#if defined(PLAT_ppc64_aix5)
-
-/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
+#if defined(PLAT_arm_linux)
/* These regs are trashed by the hidden call. */
-#define __CALLER_SAVED_REGS \
- "lr", "ctr", "xer", \
- "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
- "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
- "r11", "r12", "r13"
+#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4", "r12", "r14"
+
+/* Macros to save and align the stack before making a function
+ call and restore it afterwards as gcc may not keep the stack
+ pointer aligned if it doesn't realise calls are being made
+ to other functions. */
+
+/* This is a bit tricky. We store the original stack pointer in r10
+ as it is callee-saves. gcc doesn't allow the use of r11 for some
+ reason. Also, we can't directly "bic" the stack pointer in thumb
+ mode since r13 isn't an allowed register number in that context.
+ So use r4 as a temporary, since that is about to get trashed
+ anyway, just after each use of this macro. Side effect is we need
+ to be very careful about any future changes, since
+ VALGRIND_ALIGN_STACK simply assumes r4 is usable. */
+#define VALGRIND_ALIGN_STACK \
+ "mov r10, sp\n\t" \
+ "mov r4, sp\n\t" \
+ "bic r4, r4, #7\n\t" \
+ "mov sp, r4\n\t"
+#define VALGRIND_RESTORE_STACK \
+ "mov sp, r10\n\t"
+
+/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
+ long) == 4. */
-/* Expand the stack frame, copying enough info that unwinding
- still works. Trashes r3. */
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[1]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, r0\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
-#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
- "addi 1,1,-" #_n_fr "\n\t" \
- "ld 3," #_n_fr "(1)\n\t" \
- "std 3,0(1)\n\t"
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[2]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ __asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
+ "ldr r0, [%1, #4] \n\t" \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, r0\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
-#define VG_CONTRACT_FRAME_BY(_n_fr) \
- "addi 1,1," #_n_fr "\n\t"
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ __asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
+ "ldr r0, [%1, #4] \n\t" \
+ "ldr r1, [%1, #8] \n\t" \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, r0\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
-/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
- long) == 8. */
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[4]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ __asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
+ "ldr r0, [%1, #4] \n\t" \
+ "ldr r1, [%1, #8] \n\t" \
+ "ldr r2, [%1, #12] \n\t" \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, r0\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[5]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ __asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
+ "ldr r0, [%1, #4] \n\t" \
+ "ldr r1, [%1, #8] \n\t" \
+ "ldr r2, [%1, #12] \n\t" \
+ "ldr r3, [%1, #16] \n\t" \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, r0" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[6]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ __asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
+ "sub sp, sp, #4 \n\t" \
+ "ldr r0, [%1, #20] \n\t" \
+ "push {r0} \n\t" \
+ "ldr r0, [%1, #4] \n\t" \
+ "ldr r1, [%1, #8] \n\t" \
+ "ldr r2, [%1, #12] \n\t" \
+ "ldr r3, [%1, #16] \n\t" \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, r0" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[7]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ __asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
+ "ldr r0, [%1, #20] \n\t" \
+ "ldr r1, [%1, #24] \n\t" \
+ "push {r0, r1} \n\t" \
+ "ldr r0, [%1, #4] \n\t" \
+ "ldr r1, [%1, #8] \n\t" \
+ "ldr r2, [%1, #12] \n\t" \
+ "ldr r3, [%1, #16] \n\t" \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, r0" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[8]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ __asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
+ "sub sp, sp, #4 \n\t" \
+ "ldr r0, [%1, #20] \n\t" \
+ "ldr r1, [%1, #24] \n\t" \
+ "ldr r2, [%1, #28] \n\t" \
+ "push {r0, r1, r2} \n\t" \
+ "ldr r0, [%1, #4] \n\t" \
+ "ldr r1, [%1, #8] \n\t" \
+ "ldr r2, [%1, #12] \n\t" \
+ "ldr r3, [%1, #16] \n\t" \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, r0" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[9]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ __asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
+ "ldr r0, [%1, #20] \n\t" \
+ "ldr r1, [%1, #24] \n\t" \
+ "ldr r2, [%1, #28] \n\t" \
+ "ldr r3, [%1, #32] \n\t" \
+ "push {r0, r1, r2, r3} \n\t" \
+ "ldr r0, [%1, #4] \n\t" \
+ "ldr r1, [%1, #8] \n\t" \
+ "ldr r2, [%1, #12] \n\t" \
+ "ldr r3, [%1, #16] \n\t" \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, r0" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[10]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ __asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
+ "sub sp, sp, #4 \n\t" \
+ "ldr r0, [%1, #20] \n\t" \
+ "ldr r1, [%1, #24] \n\t" \
+ "ldr r2, [%1, #28] \n\t" \
+ "ldr r3, [%1, #32] \n\t" \
+ "ldr r4, [%1, #36] \n\t" \
+ "push {r0, r1, r2, r3, r4} \n\t" \
+ "ldr r0, [%1, #4] \n\t" \
+ "ldr r1, [%1, #8] \n\t" \
+ "ldr r2, [%1, #12] \n\t" \
+ "ldr r3, [%1, #16] \n\t" \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, r0" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[11]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ __asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
+ "ldr r0, [%1, #40] \n\t" \
+ "push {r0} \n\t" \
+ "ldr r0, [%1, #20] \n\t" \
+ "ldr r1, [%1, #24] \n\t" \
+ "ldr r2, [%1, #28] \n\t" \
+ "ldr r3, [%1, #32] \n\t" \
+ "ldr r4, [%1, #36] \n\t" \
+ "push {r0, r1, r2, r3, r4} \n\t" \
+ "ldr r0, [%1, #4] \n\t" \
+ "ldr r1, [%1, #8] \n\t" \
+ "ldr r2, [%1, #12] \n\t" \
+ "ldr r3, [%1, #16] \n\t" \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, r0" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
+ arg6,arg7,arg8,arg9,arg10, \
+ arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[12]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ _argvec[11] = (unsigned long)(arg11); \
+ __asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
+ "sub sp, sp, #4 \n\t" \
+ "ldr r0, [%1, #40] \n\t" \
+ "ldr r1, [%1, #44] \n\t" \
+ "push {r0, r1} \n\t" \
+ "ldr r0, [%1, #20] \n\t" \
+ "ldr r1, [%1, #24] \n\t" \
+ "ldr r2, [%1, #28] \n\t" \
+ "ldr r3, [%1, #32] \n\t" \
+ "ldr r4, [%1, #36] \n\t" \
+ "push {r0, r1, r2, r3, r4} \n\t" \
+ "ldr r0, [%1, #4] \n\t" \
+ "ldr r1, [%1, #8] \n\t" \
+ "ldr r2, [%1, #12] \n\t" \
+ "ldr r3, [%1, #16] \n\t" \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, r0" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
+ arg6,arg7,arg8,arg9,arg10, \
+ arg11,arg12) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[13]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ _argvec[11] = (unsigned long)(arg11); \
+ _argvec[12] = (unsigned long)(arg12); \
+ __asm__ volatile( \
+ VALGRIND_ALIGN_STACK \
+ "ldr r0, [%1, #40] \n\t" \
+ "ldr r1, [%1, #44] \n\t" \
+ "ldr r2, [%1, #48] \n\t" \
+ "push {r0, r1, r2} \n\t" \
+ "ldr r0, [%1, #20] \n\t" \
+ "ldr r1, [%1, #24] \n\t" \
+ "ldr r2, [%1, #28] \n\t" \
+ "ldr r3, [%1, #32] \n\t" \
+ "ldr r4, [%1, #36] \n\t" \
+ "push {r0, r1, r2, r3, r4} \n\t" \
+ "ldr r0, [%1, #4] \n\t" \
+ "ldr r1, [%1, #8] \n\t" \
+ "ldr r2, [%1, #12] \n\t" \
+ "ldr r3, [%1, #16] \n\t" \
+ "ldr r4, [%1] \n\t" /* target->r4 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, r0" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#endif /* PLAT_arm_linux */
+
+/* ------------------------ arm64-linux ------------------------ */
+
+#if defined(PLAT_arm64_linux)
+
+/* These regs are trashed by the hidden call. */
+#define __CALLER_SAVED_REGS \
+ "x0", "x1", "x2", "x3","x4", "x5", "x6", "x7", "x8", "x9", \
+ "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", \
+ "x18", "x19", "x20", "x30", \
+ "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \
+ "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", \
+ "v18", "v19", "v20", "v21", "v22", "v23", "v24", "v25", \
+ "v26", "v27", "v28", "v29", "v30", "v31"
+
+/* x21 is callee-saved, so we can use it to save and restore SP around
+ the hidden call. */
+#define VALGRIND_ALIGN_STACK \
+ "mov x21, sp\n\t" \
+ "bic sp, x21, #15\n\t"
+#define VALGRIND_RESTORE_STACK \
+ "mov sp, x21\n\t"
+
+/* These CALL_FN_ macros assume that on arm64-linux,
+ sizeof(unsigned long) == 8. */
#define CALL_FN_W_v(lval, orig) \
do { \
volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+0]; \
+ volatile unsigned long _argvec[1]; \
volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
+ VALGRIND_ALIGN_STACK \
+ "ldr x8, [%1] \n\t" /* target->x8 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, x0\n" \
: /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -3062,27 +4247,20 @@ typedef
#define CALL_FN_W_W(lval, orig, arg1) \
do { \
volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+1]; \
+ volatile unsigned long _argvec[2]; \
volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
+ VALGRIND_ALIGN_STACK \
+ "ldr x0, [%1, #8] \n\t" \
+ "ldr x8, [%1] \n\t" /* target->x8 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, x0\n" \
: /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -3090,29 +4268,22 @@ typedef
#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
do { \
volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+2]; \
+ volatile unsigned long _argvec[3]; \
volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
+ VALGRIND_ALIGN_STACK \
+ "ldr x0, [%1, #8] \n\t" \
+ "ldr x1, [%1, #16] \n\t" \
+ "ldr x8, [%1] \n\t" /* target->x8 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, x0\n" \
: /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -3120,31 +4291,24 @@ typedef
#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
do { \
volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+3]; \
+ volatile unsigned long _argvec[4]; \
volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
+ VALGRIND_ALIGN_STACK \
+ "ldr x0, [%1, #8] \n\t" \
+ "ldr x1, [%1, #16] \n\t" \
+ "ldr x2, [%1, #24] \n\t" \
+ "ldr x8, [%1] \n\t" /* target->x8 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, x0\n" \
: /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -3152,33 +4316,26 @@ typedef
#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
do { \
volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+4]; \
+ volatile unsigned long _argvec[5]; \
volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
+ VALGRIND_ALIGN_STACK \
+ "ldr x0, [%1, #8] \n\t" \
+ "ldr x1, [%1, #16] \n\t" \
+ "ldr x2, [%1, #24] \n\t" \
+ "ldr x3, [%1, #32] \n\t" \
+ "ldr x8, [%1] \n\t" /* target->x8 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, x0" \
: /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -3186,35 +4343,28 @@ typedef
#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
do { \
volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+5]; \
+ volatile unsigned long _argvec[6]; \
volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
+ VALGRIND_ALIGN_STACK \
+ "ldr x0, [%1, #8] \n\t" \
+ "ldr x1, [%1, #16] \n\t" \
+ "ldr x2, [%1, #24] \n\t" \
+ "ldr x3, [%1, #32] \n\t" \
+ "ldr x4, [%1, #40] \n\t" \
+ "ldr x8, [%1] \n\t" /* target->x8 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, x0" \
: /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -3222,37 +4372,30 @@ typedef
#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
do { \
volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+6]; \
+ volatile unsigned long _argvec[7]; \
volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
+ VALGRIND_ALIGN_STACK \
+ "ldr x0, [%1, #8] \n\t" \
+ "ldr x1, [%1, #16] \n\t" \
+ "ldr x2, [%1, #24] \n\t" \
+ "ldr x3, [%1, #32] \n\t" \
+ "ldr x4, [%1, #40] \n\t" \
+ "ldr x5, [%1, #48] \n\t" \
+ "ldr x8, [%1] \n\t" /* target->x8 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, x0" \
: /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -3261,39 +4404,32 @@ typedef
arg7) \
do { \
volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+7]; \
+ volatile unsigned long _argvec[8]; \
volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
+ VALGRIND_ALIGN_STACK \
+ "ldr x0, [%1, #8] \n\t" \
+ "ldr x1, [%1, #16] \n\t" \
+ "ldr x2, [%1, #24] \n\t" \
+ "ldr x3, [%1, #32] \n\t" \
+ "ldr x4, [%1, #40] \n\t" \
+ "ldr x5, [%1, #48] \n\t" \
+ "ldr x6, [%1, #56] \n\t" \
+ "ldr x8, [%1] \n\t" /* target->x8 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, x0" \
: /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -3302,41 +4438,34 @@ typedef
arg7,arg8) \
do { \
volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+8]; \
+ volatile unsigned long _argvec[9]; \
volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
+ VALGRIND_ALIGN_STACK \
+ "ldr x0, [%1, #8] \n\t" \
+ "ldr x1, [%1, #16] \n\t" \
+ "ldr x2, [%1, #24] \n\t" \
+ "ldr x3, [%1, #32] \n\t" \
+ "ldr x4, [%1, #40] \n\t" \
+ "ldr x5, [%1, #48] \n\t" \
+ "ldr x6, [%1, #56] \n\t" \
+ "ldr x7, [%1, #64] \n\t" \
+ "ldr x8, [%1] \n\t" /* target->x8 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, x0" \
: /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -3345,48 +4474,38 @@ typedef
arg7,arg8,arg9) \
do { \
volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+9]; \
+ volatile unsigned long _argvec[10]; \
volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- VG_EXPAND_FRAME_BY_trashes_r3(128) \
- /* arg9 */ \
- "ld 3,72(11)\n\t" \
- "std 3,112(1)\n\t" \
- /* args1-8 */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(128) \
- VG_CONTRACT_FRAME_BY(512) \
+ VALGRIND_ALIGN_STACK \
+ "sub sp, sp, #0x20 \n\t" \
+ "ldr x0, [%1, #8] \n\t" \
+ "ldr x1, [%1, #16] \n\t" \
+ "ldr x2, [%1, #24] \n\t" \
+ "ldr x3, [%1, #32] \n\t" \
+ "ldr x4, [%1, #40] \n\t" \
+ "ldr x5, [%1, #48] \n\t" \
+ "ldr x6, [%1, #56] \n\t" \
+ "ldr x7, [%1, #64] \n\t" \
+ "ldr x8, [%1, #72] \n\t" \
+ "str x8, [sp, #0] \n\t" \
+ "ldr x8, [%1] \n\t" /* target->x8 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, x0" \
: /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -3395,52 +4514,41 @@ typedef
arg7,arg8,arg9,arg10) \
do { \
volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+10]; \
+ volatile unsigned long _argvec[11]; \
volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- _argvec[2+10] = (unsigned long)arg10; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- VG_EXPAND_FRAME_BY_trashes_r3(128) \
- /* arg10 */ \
- "ld 3,80(11)\n\t" \
- "std 3,120(1)\n\t" \
- /* arg9 */ \
- "ld 3,72(11)\n\t" \
- "std 3,112(1)\n\t" \
- /* args1-8 */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(128) \
- VG_CONTRACT_FRAME_BY(512) \
+ VALGRIND_ALIGN_STACK \
+ "sub sp, sp, #0x20 \n\t" \
+ "ldr x0, [%1, #8] \n\t" \
+ "ldr x1, [%1, #16] \n\t" \
+ "ldr x2, [%1, #24] \n\t" \
+ "ldr x3, [%1, #32] \n\t" \
+ "ldr x4, [%1, #40] \n\t" \
+ "ldr x5, [%1, #48] \n\t" \
+ "ldr x6, [%1, #56] \n\t" \
+ "ldr x7, [%1, #64] \n\t" \
+ "ldr x8, [%1, #72] \n\t" \
+ "str x8, [sp, #0] \n\t" \
+ "ldr x8, [%1, #80] \n\t" \
+ "str x8, [sp, #8] \n\t" \
+ "ldr x8, [%1] \n\t" /* target->x8 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, x0" \
: /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
@@ -3449,124 +4557,1546 @@ typedef
arg7,arg8,arg9,arg10,arg11) \
do { \
volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+11]; \
+ volatile unsigned long _argvec[12]; \
volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- _argvec[2+10] = (unsigned long)arg10; \
- _argvec[2+11] = (unsigned long)arg11; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ _argvec[11] = (unsigned long)(arg11); \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- VG_EXPAND_FRAME_BY_trashes_r3(144) \
- /* arg11 */ \
- "ld 3,88(11)\n\t" \
- "std 3,128(1)\n\t" \
- /* arg10 */ \
- "ld 3,80(11)\n\t" \
- "std 3,120(1)\n\t" \
- /* arg9 */ \
- "ld 3,72(11)\n\t" \
- "std 3,112(1)\n\t" \
- /* args1-8 */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(144) \
- VG_CONTRACT_FRAME_BY(512) \
+ VALGRIND_ALIGN_STACK \
+ "sub sp, sp, #0x30 \n\t" \
+ "ldr x0, [%1, #8] \n\t" \
+ "ldr x1, [%1, #16] \n\t" \
+ "ldr x2, [%1, #24] \n\t" \
+ "ldr x3, [%1, #32] \n\t" \
+ "ldr x4, [%1, #40] \n\t" \
+ "ldr x5, [%1, #48] \n\t" \
+ "ldr x6, [%1, #56] \n\t" \
+ "ldr x7, [%1, #64] \n\t" \
+ "ldr x8, [%1, #72] \n\t" \
+ "str x8, [sp, #0] \n\t" \
+ "ldr x8, [%1, #80] \n\t" \
+ "str x8, [sp, #8] \n\t" \
+ "ldr x8, [%1, #88] \n\t" \
+ "str x8, [sp, #16] \n\t" \
+ "ldr x8, [%1] \n\t" /* target->x8 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, x0" \
: /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10,arg11,arg12) \
+ arg7,arg8,arg9,arg10,arg11, \
+ arg12) \
do { \
volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+12]; \
+ volatile unsigned long _argvec[13]; \
volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- _argvec[2+10] = (unsigned long)arg10; \
- _argvec[2+11] = (unsigned long)arg11; \
- _argvec[2+12] = (unsigned long)arg12; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ _argvec[11] = (unsigned long)(arg11); \
+ _argvec[12] = (unsigned long)(arg12); \
__asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- VG_EXPAND_FRAME_BY_trashes_r3(144) \
- /* arg12 */ \
- "ld 3,96(11)\n\t" \
- "std 3,136(1)\n\t" \
- /* arg11 */ \
- "ld 3,88(11)\n\t" \
- "std 3,128(1)\n\t" \
- /* arg10 */ \
- "ld 3,80(11)\n\t" \
- "std 3,120(1)\n\t" \
- /* arg9 */ \
- "ld 3,72(11)\n\t" \
- "std 3,112(1)\n\t" \
- /* args1-8 */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(144) \
- VG_CONTRACT_FRAME_BY(512) \
+ VALGRIND_ALIGN_STACK \
+ "sub sp, sp, #0x30 \n\t" \
+ "ldr x0, [%1, #8] \n\t" \
+ "ldr x1, [%1, #16] \n\t" \
+ "ldr x2, [%1, #24] \n\t" \
+ "ldr x3, [%1, #32] \n\t" \
+ "ldr x4, [%1, #40] \n\t" \
+ "ldr x5, [%1, #48] \n\t" \
+ "ldr x6, [%1, #56] \n\t" \
+ "ldr x7, [%1, #64] \n\t" \
+ "ldr x8, [%1, #72] \n\t" \
+ "str x8, [sp, #0] \n\t" \
+ "ldr x8, [%1, #80] \n\t" \
+ "str x8, [sp, #8] \n\t" \
+ "ldr x8, [%1, #88] \n\t" \
+ "str x8, [sp, #16] \n\t" \
+ "ldr x8, [%1, #96] \n\t" \
+ "str x8, [sp, #24] \n\t" \
+ "ldr x8, [%1] \n\t" /* target->x8 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \
+ VALGRIND_RESTORE_STACK \
+ "mov %0, x0" \
: /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \
); \
lval = (__typeof__(lval)) _res; \
} while (0)
-#endif /* PLAT_ppc64_aix5 */
+#endif /* PLAT_arm64_linux */
+
+/* ------------------------- s390x-linux ------------------------- */
+
+#if defined(PLAT_s390x_linux)
+
+/* Similar workaround as amd64 (see above), but we use r11 as frame
+ pointer and save the old r11 in r7. r11 might be used for
+ argvec, therefore we copy argvec in r1 since r1 is clobbered
+ after the call anyway. */
+#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
+# define __FRAME_POINTER \
+ ,"d"(__builtin_dwarf_cfa())
+# define VALGRIND_CFI_PROLOGUE \
+ ".cfi_remember_state\n\t" \
+ "lgr 1,%1\n\t" /* copy the argvec pointer in r1 */ \
+ "lgr 7,11\n\t" \
+ "lgr 11,%2\n\t" \
+ ".cfi_def_cfa r11, 0\n\t"
+# define VALGRIND_CFI_EPILOGUE \
+ "lgr 11, 7\n\t" \
+ ".cfi_restore_state\n\t"
+#else
+# define __FRAME_POINTER
+# define VALGRIND_CFI_PROLOGUE \
+ "lgr 1,%1\n\t"
+# define VALGRIND_CFI_EPILOGUE
+#endif
+
+/* Nb: On s390 the stack pointer is properly aligned *at all times*
+ according to the s390 GCC maintainer. (The ABI specification is not
+ precise in this regard.) Therefore, VALGRIND_ALIGN_STACK and
+ VALGRIND_RESTORE_STACK are not defined here. */
+
+/* These regs are trashed by the hidden call. Note that we overwrite
+ r14 in s390_irgen_noredir (VEX/priv/guest_s390_irgen.c) to give the
+ function a proper return address. All others are ABI defined call
+ clobbers. */
+#define __CALLER_SAVED_REGS "0","1","2","3","4","5","14", \
+ "f0","f1","f2","f3","f4","f5","f6","f7"
+
+/* Nb: Although r11 is modified in the asm snippets below (inside
+ VALGRIND_CFI_PROLOGUE) it is not listed in the clobber section, for
+ two reasons:
+ (1) r11 is restored in VALGRIND_CFI_EPILOGUE, so effectively it is not
+ modified
+ (2) GCC will complain that r11 cannot appear inside a clobber section,
+ when compiled with -O -fno-omit-frame-pointer
+ */
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[1]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-160\n\t" \
+ "lg 1, 0(1)\n\t" /* target->r1 */ \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,160\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "d" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+/* The call abi has the arguments in r2-r6 and stack */
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[2]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-160\n\t" \
+ "lg 2, 8(1)\n\t" \
+ "lg 1, 0(1)\n\t" \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,160\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1, arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-160\n\t" \
+ "lg 2, 8(1)\n\t" \
+ "lg 3,16(1)\n\t" \
+ "lg 1, 0(1)\n\t" \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,160\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[4]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-160\n\t" \
+ "lg 2, 8(1)\n\t" \
+ "lg 3,16(1)\n\t" \
+ "lg 4,24(1)\n\t" \
+ "lg 1, 0(1)\n\t" \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,160\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[5]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-160\n\t" \
+ "lg 2, 8(1)\n\t" \
+ "lg 3,16(1)\n\t" \
+ "lg 4,24(1)\n\t" \
+ "lg 5,32(1)\n\t" \
+ "lg 1, 0(1)\n\t" \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,160\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[6]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-160\n\t" \
+ "lg 2, 8(1)\n\t" \
+ "lg 3,16(1)\n\t" \
+ "lg 4,24(1)\n\t" \
+ "lg 5,32(1)\n\t" \
+ "lg 6,40(1)\n\t" \
+ "lg 1, 0(1)\n\t" \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,160\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
+ arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[7]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-168\n\t" \
+ "lg 2, 8(1)\n\t" \
+ "lg 3,16(1)\n\t" \
+ "lg 4,24(1)\n\t" \
+ "lg 5,32(1)\n\t" \
+ "lg 6,40(1)\n\t" \
+ "mvc 160(8,15), 48(1)\n\t" \
+ "lg 1, 0(1)\n\t" \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,168\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
+ arg6, arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[8]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-176\n\t" \
+ "lg 2, 8(1)\n\t" \
+ "lg 3,16(1)\n\t" \
+ "lg 4,24(1)\n\t" \
+ "lg 5,32(1)\n\t" \
+ "lg 6,40(1)\n\t" \
+ "mvc 160(8,15), 48(1)\n\t" \
+ "mvc 168(8,15), 56(1)\n\t" \
+ "lg 1, 0(1)\n\t" \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,176\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
+ arg6, arg7 ,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[9]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-184\n\t" \
+ "lg 2, 8(1)\n\t" \
+ "lg 3,16(1)\n\t" \
+ "lg 4,24(1)\n\t" \
+ "lg 5,32(1)\n\t" \
+ "lg 6,40(1)\n\t" \
+ "mvc 160(8,15), 48(1)\n\t" \
+ "mvc 168(8,15), 56(1)\n\t" \
+ "mvc 176(8,15), 64(1)\n\t" \
+ "lg 1, 0(1)\n\t" \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,184\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
+ arg6, arg7 ,arg8, arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[10]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ _argvec[9] = (unsigned long)arg9; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-192\n\t" \
+ "lg 2, 8(1)\n\t" \
+ "lg 3,16(1)\n\t" \
+ "lg 4,24(1)\n\t" \
+ "lg 5,32(1)\n\t" \
+ "lg 6,40(1)\n\t" \
+ "mvc 160(8,15), 48(1)\n\t" \
+ "mvc 168(8,15), 56(1)\n\t" \
+ "mvc 176(8,15), 64(1)\n\t" \
+ "mvc 184(8,15), 72(1)\n\t" \
+ "lg 1, 0(1)\n\t" \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,192\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
+ arg6, arg7 ,arg8, arg9, arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[11]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ _argvec[9] = (unsigned long)arg9; \
+ _argvec[10] = (unsigned long)arg10; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-200\n\t" \
+ "lg 2, 8(1)\n\t" \
+ "lg 3,16(1)\n\t" \
+ "lg 4,24(1)\n\t" \
+ "lg 5,32(1)\n\t" \
+ "lg 6,40(1)\n\t" \
+ "mvc 160(8,15), 48(1)\n\t" \
+ "mvc 168(8,15), 56(1)\n\t" \
+ "mvc 176(8,15), 64(1)\n\t" \
+ "mvc 184(8,15), 72(1)\n\t" \
+ "mvc 192(8,15), 80(1)\n\t" \
+ "lg 1, 0(1)\n\t" \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,200\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
+ arg6, arg7 ,arg8, arg9, arg10, arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[12]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ _argvec[9] = (unsigned long)arg9; \
+ _argvec[10] = (unsigned long)arg10; \
+ _argvec[11] = (unsigned long)arg11; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-208\n\t" \
+ "lg 2, 8(1)\n\t" \
+ "lg 3,16(1)\n\t" \
+ "lg 4,24(1)\n\t" \
+ "lg 5,32(1)\n\t" \
+ "lg 6,40(1)\n\t" \
+ "mvc 160(8,15), 48(1)\n\t" \
+ "mvc 168(8,15), 56(1)\n\t" \
+ "mvc 176(8,15), 64(1)\n\t" \
+ "mvc 184(8,15), 72(1)\n\t" \
+ "mvc 192(8,15), 80(1)\n\t" \
+ "mvc 200(8,15), 88(1)\n\t" \
+ "lg 1, 0(1)\n\t" \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,208\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
+ arg6, arg7 ,arg8, arg9, arg10, arg11, arg12)\
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[13]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ _argvec[9] = (unsigned long)arg9; \
+ _argvec[10] = (unsigned long)arg10; \
+ _argvec[11] = (unsigned long)arg11; \
+ _argvec[12] = (unsigned long)arg12; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-216\n\t" \
+ "lg 2, 8(1)\n\t" \
+ "lg 3,16(1)\n\t" \
+ "lg 4,24(1)\n\t" \
+ "lg 5,32(1)\n\t" \
+ "lg 6,40(1)\n\t" \
+ "mvc 160(8,15), 48(1)\n\t" \
+ "mvc 168(8,15), 56(1)\n\t" \
+ "mvc 176(8,15), 64(1)\n\t" \
+ "mvc 184(8,15), 72(1)\n\t" \
+ "mvc 192(8,15), 80(1)\n\t" \
+ "mvc 200(8,15), 88(1)\n\t" \
+ "mvc 208(8,15), 96(1)\n\t" \
+ "lg 1, 0(1)\n\t" \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,216\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+
+#endif /* PLAT_s390x_linux */
+/* ------------------------- mips32-linux ----------------------- */
+
+#if defined(PLAT_mips32_linux)
+
+/* These regs are trashed by the hidden call. */
+#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \
+"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
+"$25", "$31"
+
+/* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned
+ long) == 4. */
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[1]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ "subu $29, $29, 8 \n\t" \
+ "sw $28, 0($29) \n\t" \
+ "sw $31, 4($29) \n\t" \
+ "subu $29, $29, 16 \n\t" \
+ "lw $25, 0(%1) \n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "addu $29, $29, 16\n\t" \
+ "lw $28, 0($29) \n\t" \
+ "lw $31, 4($29) \n\t" \
+ "addu $29, $29, 8 \n\t" \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[2]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ __asm__ volatile( \
+ "subu $29, $29, 8 \n\t" \
+ "sw $28, 0($29) \n\t" \
+ "sw $31, 4($29) \n\t" \
+ "subu $29, $29, 16 \n\t" \
+ "lw $4, 4(%1) \n\t" /* arg1*/ \
+ "lw $25, 0(%1) \n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "addu $29, $29, 16 \n\t" \
+ "lw $28, 0($29) \n\t" \
+ "lw $31, 4($29) \n\t" \
+ "addu $29, $29, 8 \n\t" \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ __asm__ volatile( \
+ "subu $29, $29, 8 \n\t" \
+ "sw $28, 0($29) \n\t" \
+ "sw $31, 4($29) \n\t" \
+ "subu $29, $29, 16 \n\t" \
+ "lw $4, 4(%1) \n\t" \
+ "lw $5, 8(%1) \n\t" \
+ "lw $25, 0(%1) \n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "addu $29, $29, 16 \n\t" \
+ "lw $28, 0($29) \n\t" \
+ "lw $31, 4($29) \n\t" \
+ "addu $29, $29, 8 \n\t" \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[4]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ __asm__ volatile( \
+ "subu $29, $29, 8 \n\t" \
+ "sw $28, 0($29) \n\t" \
+ "sw $31, 4($29) \n\t" \
+ "subu $29, $29, 16 \n\t" \
+ "lw $4, 4(%1) \n\t" \
+ "lw $5, 8(%1) \n\t" \
+ "lw $6, 12(%1) \n\t" \
+ "lw $25, 0(%1) \n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "addu $29, $29, 16 \n\t" \
+ "lw $28, 0($29) \n\t" \
+ "lw $31, 4($29) \n\t" \
+ "addu $29, $29, 8 \n\t" \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[5]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ __asm__ volatile( \
+ "subu $29, $29, 8 \n\t" \
+ "sw $28, 0($29) \n\t" \
+ "sw $31, 4($29) \n\t" \
+ "subu $29, $29, 16 \n\t" \
+ "lw $4, 4(%1) \n\t" \
+ "lw $5, 8(%1) \n\t" \
+ "lw $6, 12(%1) \n\t" \
+ "lw $7, 16(%1) \n\t" \
+ "lw $25, 0(%1) \n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "addu $29, $29, 16 \n\t" \
+ "lw $28, 0($29) \n\t" \
+ "lw $31, 4($29) \n\t" \
+ "addu $29, $29, 8 \n\t" \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[6]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ __asm__ volatile( \
+ "subu $29, $29, 8 \n\t" \
+ "sw $28, 0($29) \n\t" \
+ "sw $31, 4($29) \n\t" \
+ "lw $4, 20(%1) \n\t" \
+ "subu $29, $29, 24\n\t" \
+ "sw $4, 16($29) \n\t" \
+ "lw $4, 4(%1) \n\t" \
+ "lw $5, 8(%1) \n\t" \
+ "lw $6, 12(%1) \n\t" \
+ "lw $7, 16(%1) \n\t" \
+ "lw $25, 0(%1) \n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "addu $29, $29, 24 \n\t" \
+ "lw $28, 0($29) \n\t" \
+ "lw $31, 4($29) \n\t" \
+ "addu $29, $29, 8 \n\t" \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[7]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ __asm__ volatile( \
+ "subu $29, $29, 8 \n\t" \
+ "sw $28, 0($29) \n\t" \
+ "sw $31, 4($29) \n\t" \
+ "lw $4, 20(%1) \n\t" \
+ "subu $29, $29, 32\n\t" \
+ "sw $4, 16($29) \n\t" \
+ "lw $4, 24(%1) \n\t" \
+ "nop\n\t" \
+ "sw $4, 20($29) \n\t" \
+ "lw $4, 4(%1) \n\t" \
+ "lw $5, 8(%1) \n\t" \
+ "lw $6, 12(%1) \n\t" \
+ "lw $7, 16(%1) \n\t" \
+ "lw $25, 0(%1) \n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "addu $29, $29, 32 \n\t" \
+ "lw $28, 0($29) \n\t" \
+ "lw $31, 4($29) \n\t" \
+ "addu $29, $29, 8 \n\t" \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[8]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ __asm__ volatile( \
+ "subu $29, $29, 8 \n\t" \
+ "sw $28, 0($29) \n\t" \
+ "sw $31, 4($29) \n\t" \
+ "lw $4, 20(%1) \n\t" \
+ "subu $29, $29, 32\n\t" \
+ "sw $4, 16($29) \n\t" \
+ "lw $4, 24(%1) \n\t" \
+ "sw $4, 20($29) \n\t" \
+ "lw $4, 28(%1) \n\t" \
+ "sw $4, 24($29) \n\t" \
+ "lw $4, 4(%1) \n\t" \
+ "lw $5, 8(%1) \n\t" \
+ "lw $6, 12(%1) \n\t" \
+ "lw $7, 16(%1) \n\t" \
+ "lw $25, 0(%1) \n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "addu $29, $29, 32 \n\t" \
+ "lw $28, 0($29) \n\t" \
+ "lw $31, 4($29) \n\t" \
+ "addu $29, $29, 8 \n\t" \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[9]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ __asm__ volatile( \
+ "subu $29, $29, 8 \n\t" \
+ "sw $28, 0($29) \n\t" \
+ "sw $31, 4($29) \n\t" \
+ "lw $4, 20(%1) \n\t" \
+ "subu $29, $29, 40\n\t" \
+ "sw $4, 16($29) \n\t" \
+ "lw $4, 24(%1) \n\t" \
+ "sw $4, 20($29) \n\t" \
+ "lw $4, 28(%1) \n\t" \
+ "sw $4, 24($29) \n\t" \
+ "lw $4, 32(%1) \n\t" \
+ "sw $4, 28($29) \n\t" \
+ "lw $4, 4(%1) \n\t" \
+ "lw $5, 8(%1) \n\t" \
+ "lw $6, 12(%1) \n\t" \
+ "lw $7, 16(%1) \n\t" \
+ "lw $25, 0(%1) \n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "addu $29, $29, 40 \n\t" \
+ "lw $28, 0($29) \n\t" \
+ "lw $31, 4($29) \n\t" \
+ "addu $29, $29, 8 \n\t" \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[10]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ __asm__ volatile( \
+ "subu $29, $29, 8 \n\t" \
+ "sw $28, 0($29) \n\t" \
+ "sw $31, 4($29) \n\t" \
+ "lw $4, 20(%1) \n\t" \
+ "subu $29, $29, 40\n\t" \
+ "sw $4, 16($29) \n\t" \
+ "lw $4, 24(%1) \n\t" \
+ "sw $4, 20($29) \n\t" \
+ "lw $4, 28(%1) \n\t" \
+ "sw $4, 24($29) \n\t" \
+ "lw $4, 32(%1) \n\t" \
+ "sw $4, 28($29) \n\t" \
+ "lw $4, 36(%1) \n\t" \
+ "sw $4, 32($29) \n\t" \
+ "lw $4, 4(%1) \n\t" \
+ "lw $5, 8(%1) \n\t" \
+ "lw $6, 12(%1) \n\t" \
+ "lw $7, 16(%1) \n\t" \
+ "lw $25, 0(%1) \n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "addu $29, $29, 40 \n\t" \
+ "lw $28, 0($29) \n\t" \
+ "lw $31, 4($29) \n\t" \
+ "addu $29, $29, 8 \n\t" \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[11]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ __asm__ volatile( \
+ "subu $29, $29, 8 \n\t" \
+ "sw $28, 0($29) \n\t" \
+ "sw $31, 4($29) \n\t" \
+ "lw $4, 20(%1) \n\t" \
+ "subu $29, $29, 48\n\t" \
+ "sw $4, 16($29) \n\t" \
+ "lw $4, 24(%1) \n\t" \
+ "sw $4, 20($29) \n\t" \
+ "lw $4, 28(%1) \n\t" \
+ "sw $4, 24($29) \n\t" \
+ "lw $4, 32(%1) \n\t" \
+ "sw $4, 28($29) \n\t" \
+ "lw $4, 36(%1) \n\t" \
+ "sw $4, 32($29) \n\t" \
+ "lw $4, 40(%1) \n\t" \
+ "sw $4, 36($29) \n\t" \
+ "lw $4, 4(%1) \n\t" \
+ "lw $5, 8(%1) \n\t" \
+ "lw $6, 12(%1) \n\t" \
+ "lw $7, 16(%1) \n\t" \
+ "lw $25, 0(%1) \n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "addu $29, $29, 48 \n\t" \
+ "lw $28, 0($29) \n\t" \
+ "lw $31, 4($29) \n\t" \
+ "addu $29, $29, 8 \n\t" \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
+ arg6,arg7,arg8,arg9,arg10, \
+ arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[12]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ _argvec[11] = (unsigned long)(arg11); \
+ __asm__ volatile( \
+ "subu $29, $29, 8 \n\t" \
+ "sw $28, 0($29) \n\t" \
+ "sw $31, 4($29) \n\t" \
+ "lw $4, 20(%1) \n\t" \
+ "subu $29, $29, 48\n\t" \
+ "sw $4, 16($29) \n\t" \
+ "lw $4, 24(%1) \n\t" \
+ "sw $4, 20($29) \n\t" \
+ "lw $4, 28(%1) \n\t" \
+ "sw $4, 24($29) \n\t" \
+ "lw $4, 32(%1) \n\t" \
+ "sw $4, 28($29) \n\t" \
+ "lw $4, 36(%1) \n\t" \
+ "sw $4, 32($29) \n\t" \
+ "lw $4, 40(%1) \n\t" \
+ "sw $4, 36($29) \n\t" \
+ "lw $4, 44(%1) \n\t" \
+ "sw $4, 40($29) \n\t" \
+ "lw $4, 4(%1) \n\t" \
+ "lw $5, 8(%1) \n\t" \
+ "lw $6, 12(%1) \n\t" \
+ "lw $7, 16(%1) \n\t" \
+ "lw $25, 0(%1) \n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "addu $29, $29, 48 \n\t" \
+ "lw $28, 0($29) \n\t" \
+ "lw $31, 4($29) \n\t" \
+ "addu $29, $29, 8 \n\t" \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
+ arg6,arg7,arg8,arg9,arg10, \
+ arg11,arg12) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[13]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ _argvec[11] = (unsigned long)(arg11); \
+ _argvec[12] = (unsigned long)(arg12); \
+ __asm__ volatile( \
+ "subu $29, $29, 8 \n\t" \
+ "sw $28, 0($29) \n\t" \
+ "sw $31, 4($29) \n\t" \
+ "lw $4, 20(%1) \n\t" \
+ "subu $29, $29, 56\n\t" \
+ "sw $4, 16($29) \n\t" \
+ "lw $4, 24(%1) \n\t" \
+ "sw $4, 20($29) \n\t" \
+ "lw $4, 28(%1) \n\t" \
+ "sw $4, 24($29) \n\t" \
+ "lw $4, 32(%1) \n\t" \
+ "sw $4, 28($29) \n\t" \
+ "lw $4, 36(%1) \n\t" \
+ "sw $4, 32($29) \n\t" \
+ "lw $4, 40(%1) \n\t" \
+ "sw $4, 36($29) \n\t" \
+ "lw $4, 44(%1) \n\t" \
+ "sw $4, 40($29) \n\t" \
+ "lw $4, 48(%1) \n\t" \
+ "sw $4, 44($29) \n\t" \
+ "lw $4, 4(%1) \n\t" \
+ "lw $5, 8(%1) \n\t" \
+ "lw $6, 12(%1) \n\t" \
+ "lw $7, 16(%1) \n\t" \
+ "lw $25, 0(%1) \n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "addu $29, $29, 56 \n\t" \
+ "lw $28, 0($29) \n\t" \
+ "lw $31, 4($29) \n\t" \
+ "addu $29, $29, 8 \n\t" \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#endif /* PLAT_mips32_linux */
+
+/* ------------------------- mips64-linux ------------------------- */
+
+#if defined(PLAT_mips64_linux)
+
+/* These regs are trashed by the hidden call. */
+#define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \
+"$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \
+"$25", "$31"
+
+/* These CALL_FN_ macros assume that on mips64-linux,
+ sizeof(long long) == 8. */
+
+#define MIPS64_LONG2REG_CAST(x) ((long long)(long)x)
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long long _argvec[1]; \
+ volatile unsigned long long _res; \
+ _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr); \
+ __asm__ volatile( \
+ "ld $25, 0(%1)\n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "0" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) (long)_res; \
+ } while (0)
+
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long long _argvec[2]; \
+ volatile unsigned long long _res; \
+ _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr); \
+ _argvec[1] = MIPS64_LONG2REG_CAST(arg1); \
+ __asm__ volatile( \
+ "ld $4, 8(%1)\n\t" /* arg1*/ \
+ "ld $25, 0(%1)\n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) (long)_res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long long _argvec[3]; \
+ volatile unsigned long long _res; \
+ _argvec[0] = _orig.nraddr; \
+ _argvec[1] = MIPS64_LONG2REG_CAST(arg1); \
+ _argvec[2] = MIPS64_LONG2REG_CAST(arg2); \
+ __asm__ volatile( \
+ "ld $4, 8(%1)\n\t" \
+ "ld $5, 16(%1)\n\t" \
+ "ld $25, 0(%1)\n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) (long)_res; \
+ } while (0)
+
+
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long long _argvec[4]; \
+ volatile unsigned long long _res; \
+ _argvec[0] = _orig.nraddr; \
+ _argvec[1] = MIPS64_LONG2REG_CAST(arg1); \
+ _argvec[2] = MIPS64_LONG2REG_CAST(arg2); \
+ _argvec[3] = MIPS64_LONG2REG_CAST(arg3); \
+ __asm__ volatile( \
+ "ld $4, 8(%1)\n\t" \
+ "ld $5, 16(%1)\n\t" \
+ "ld $6, 24(%1)\n\t" \
+ "ld $25, 0(%1)\n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) (long)_res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long long _argvec[5]; \
+ volatile unsigned long long _res; \
+ _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr); \
+ _argvec[1] = MIPS64_LONG2REG_CAST(arg1); \
+ _argvec[2] = MIPS64_LONG2REG_CAST(arg2); \
+ _argvec[3] = MIPS64_LONG2REG_CAST(arg3); \
+ _argvec[4] = MIPS64_LONG2REG_CAST(arg4); \
+ __asm__ volatile( \
+ "ld $4, 8(%1)\n\t" \
+ "ld $5, 16(%1)\n\t" \
+ "ld $6, 24(%1)\n\t" \
+ "ld $7, 32(%1)\n\t" \
+ "ld $25, 0(%1)\n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) (long)_res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long long _argvec[6]; \
+ volatile unsigned long long _res; \
+ _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr); \
+ _argvec[1] = MIPS64_LONG2REG_CAST(arg1); \
+ _argvec[2] = MIPS64_LONG2REG_CAST(arg2); \
+ _argvec[3] = MIPS64_LONG2REG_CAST(arg3); \
+ _argvec[4] = MIPS64_LONG2REG_CAST(arg4); \
+ _argvec[5] = MIPS64_LONG2REG_CAST(arg5); \
+ __asm__ volatile( \
+ "ld $4, 8(%1)\n\t" \
+ "ld $5, 16(%1)\n\t" \
+ "ld $6, 24(%1)\n\t" \
+ "ld $7, 32(%1)\n\t" \
+ "ld $8, 40(%1)\n\t" \
+ "ld $25, 0(%1)\n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) (long)_res; \
+ } while (0)
+
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long long _argvec[7]; \
+ volatile unsigned long long _res; \
+ _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr); \
+ _argvec[1] = MIPS64_LONG2REG_CAST(arg1); \
+ _argvec[2] = MIPS64_LONG2REG_CAST(arg2); \
+ _argvec[3] = MIPS64_LONG2REG_CAST(arg3); \
+ _argvec[4] = MIPS64_LONG2REG_CAST(arg4); \
+ _argvec[5] = MIPS64_LONG2REG_CAST(arg5); \
+ _argvec[6] = MIPS64_LONG2REG_CAST(arg6); \
+ __asm__ volatile( \
+ "ld $4, 8(%1)\n\t" \
+ "ld $5, 16(%1)\n\t" \
+ "ld $6, 24(%1)\n\t" \
+ "ld $7, 32(%1)\n\t" \
+ "ld $8, 40(%1)\n\t" \
+ "ld $9, 48(%1)\n\t" \
+ "ld $25, 0(%1)\n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) (long)_res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long long _argvec[8]; \
+ volatile unsigned long long _res; \
+ _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr); \
+ _argvec[1] = MIPS64_LONG2REG_CAST(arg1); \
+ _argvec[2] = MIPS64_LONG2REG_CAST(arg2); \
+ _argvec[3] = MIPS64_LONG2REG_CAST(arg3); \
+ _argvec[4] = MIPS64_LONG2REG_CAST(arg4); \
+ _argvec[5] = MIPS64_LONG2REG_CAST(arg5); \
+ _argvec[6] = MIPS64_LONG2REG_CAST(arg6); \
+ _argvec[7] = MIPS64_LONG2REG_CAST(arg7); \
+ __asm__ volatile( \
+ "ld $4, 8(%1)\n\t" \
+ "ld $5, 16(%1)\n\t" \
+ "ld $6, 24(%1)\n\t" \
+ "ld $7, 32(%1)\n\t" \
+ "ld $8, 40(%1)\n\t" \
+ "ld $9, 48(%1)\n\t" \
+ "ld $10, 56(%1)\n\t" \
+ "ld $25, 0(%1) \n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) (long)_res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long long _argvec[9]; \
+ volatile unsigned long long _res; \
+ _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr); \
+ _argvec[1] = MIPS64_LONG2REG_CAST(arg1); \
+ _argvec[2] = MIPS64_LONG2REG_CAST(arg2); \
+ _argvec[3] = MIPS64_LONG2REG_CAST(arg3); \
+ _argvec[4] = MIPS64_LONG2REG_CAST(arg4); \
+ _argvec[5] = MIPS64_LONG2REG_CAST(arg5); \
+ _argvec[6] = MIPS64_LONG2REG_CAST(arg6); \
+ _argvec[7] = MIPS64_LONG2REG_CAST(arg7); \
+ _argvec[8] = MIPS64_LONG2REG_CAST(arg8); \
+ __asm__ volatile( \
+ "ld $4, 8(%1)\n\t" \
+ "ld $5, 16(%1)\n\t" \
+ "ld $6, 24(%1)\n\t" \
+ "ld $7, 32(%1)\n\t" \
+ "ld $8, 40(%1)\n\t" \
+ "ld $9, 48(%1)\n\t" \
+ "ld $10, 56(%1)\n\t" \
+ "ld $11, 64(%1)\n\t" \
+ "ld $25, 0(%1) \n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) (long)_res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long long _argvec[10]; \
+ volatile unsigned long long _res; \
+ _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr); \
+ _argvec[1] = MIPS64_LONG2REG_CAST(arg1); \
+ _argvec[2] = MIPS64_LONG2REG_CAST(arg2); \
+ _argvec[3] = MIPS64_LONG2REG_CAST(arg3); \
+ _argvec[4] = MIPS64_LONG2REG_CAST(arg4); \
+ _argvec[5] = MIPS64_LONG2REG_CAST(arg5); \
+ _argvec[6] = MIPS64_LONG2REG_CAST(arg6); \
+ _argvec[7] = MIPS64_LONG2REG_CAST(arg7); \
+ _argvec[8] = MIPS64_LONG2REG_CAST(arg8); \
+ _argvec[9] = MIPS64_LONG2REG_CAST(arg9); \
+ __asm__ volatile( \
+ "dsubu $29, $29, 8\n\t" \
+ "ld $4, 72(%1)\n\t" \
+ "sd $4, 0($29)\n\t" \
+ "ld $4, 8(%1)\n\t" \
+ "ld $5, 16(%1)\n\t" \
+ "ld $6, 24(%1)\n\t" \
+ "ld $7, 32(%1)\n\t" \
+ "ld $8, 40(%1)\n\t" \
+ "ld $9, 48(%1)\n\t" \
+ "ld $10, 56(%1)\n\t" \
+ "ld $11, 64(%1)\n\t" \
+ "ld $25, 0(%1)\n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "daddu $29, $29, 8\n\t" \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) (long)_res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long long _argvec[11]; \
+ volatile unsigned long long _res; \
+ _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr); \
+ _argvec[1] = MIPS64_LONG2REG_CAST(arg1); \
+ _argvec[2] = MIPS64_LONG2REG_CAST(arg2); \
+ _argvec[3] = MIPS64_LONG2REG_CAST(arg3); \
+ _argvec[4] = MIPS64_LONG2REG_CAST(arg4); \
+ _argvec[5] = MIPS64_LONG2REG_CAST(arg5); \
+ _argvec[6] = MIPS64_LONG2REG_CAST(arg6); \
+ _argvec[7] = MIPS64_LONG2REG_CAST(arg7); \
+ _argvec[8] = MIPS64_LONG2REG_CAST(arg8); \
+ _argvec[9] = MIPS64_LONG2REG_CAST(arg9); \
+ _argvec[10] = MIPS64_LONG2REG_CAST(arg10); \
+ __asm__ volatile( \
+ "dsubu $29, $29, 16\n\t" \
+ "ld $4, 72(%1)\n\t" \
+ "sd $4, 0($29)\n\t" \
+ "ld $4, 80(%1)\n\t" \
+ "sd $4, 8($29)\n\t" \
+ "ld $4, 8(%1)\n\t" \
+ "ld $5, 16(%1)\n\t" \
+ "ld $6, 24(%1)\n\t" \
+ "ld $7, 32(%1)\n\t" \
+ "ld $8, 40(%1)\n\t" \
+ "ld $9, 48(%1)\n\t" \
+ "ld $10, 56(%1)\n\t" \
+ "ld $11, 64(%1)\n\t" \
+ "ld $25, 0(%1)\n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "daddu $29, $29, 16\n\t" \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) (long)_res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
+ arg6,arg7,arg8,arg9,arg10, \
+ arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long long _argvec[12]; \
+ volatile unsigned long long _res; \
+ _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr); \
+ _argvec[1] = MIPS64_LONG2REG_CAST(arg1); \
+ _argvec[2] = MIPS64_LONG2REG_CAST(arg2); \
+ _argvec[3] = MIPS64_LONG2REG_CAST(arg3); \
+ _argvec[4] = MIPS64_LONG2REG_CAST(arg4); \
+ _argvec[5] = MIPS64_LONG2REG_CAST(arg5); \
+ _argvec[6] = MIPS64_LONG2REG_CAST(arg6); \
+ _argvec[7] = MIPS64_LONG2REG_CAST(arg7); \
+ _argvec[8] = MIPS64_LONG2REG_CAST(arg8); \
+ _argvec[9] = MIPS64_LONG2REG_CAST(arg9); \
+ _argvec[10] = MIPS64_LONG2REG_CAST(arg10); \
+ _argvec[11] = MIPS64_LONG2REG_CAST(arg11); \
+ __asm__ volatile( \
+ "dsubu $29, $29, 24\n\t" \
+ "ld $4, 72(%1)\n\t" \
+ "sd $4, 0($29)\n\t" \
+ "ld $4, 80(%1)\n\t" \
+ "sd $4, 8($29)\n\t" \
+ "ld $4, 88(%1)\n\t" \
+ "sd $4, 16($29)\n\t" \
+ "ld $4, 8(%1)\n\t" \
+ "ld $5, 16(%1)\n\t" \
+ "ld $6, 24(%1)\n\t" \
+ "ld $7, 32(%1)\n\t" \
+ "ld $8, 40(%1)\n\t" \
+ "ld $9, 48(%1)\n\t" \
+ "ld $10, 56(%1)\n\t" \
+ "ld $11, 64(%1)\n\t" \
+ "ld $25, 0(%1)\n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "daddu $29, $29, 24\n\t" \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) (long)_res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
+ arg6,arg7,arg8,arg9,arg10, \
+ arg11,arg12) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long long _argvec[13]; \
+ volatile unsigned long long _res; \
+ _argvec[0] = MIPS64_LONG2REG_CAST(_orig.nraddr); \
+ _argvec[1] = MIPS64_LONG2REG_CAST(arg1); \
+ _argvec[2] = MIPS64_LONG2REG_CAST(arg2); \
+ _argvec[3] = MIPS64_LONG2REG_CAST(arg3); \
+ _argvec[4] = MIPS64_LONG2REG_CAST(arg4); \
+ _argvec[5] = MIPS64_LONG2REG_CAST(arg5); \
+ _argvec[6] = MIPS64_LONG2REG_CAST(arg6); \
+ _argvec[7] = MIPS64_LONG2REG_CAST(arg7); \
+ _argvec[8] = MIPS64_LONG2REG_CAST(arg8); \
+ _argvec[9] = MIPS64_LONG2REG_CAST(arg9); \
+ _argvec[10] = MIPS64_LONG2REG_CAST(arg10); \
+ _argvec[11] = MIPS64_LONG2REG_CAST(arg11); \
+ _argvec[12] = MIPS64_LONG2REG_CAST(arg12); \
+ __asm__ volatile( \
+ "dsubu $29, $29, 32\n\t" \
+ "ld $4, 72(%1)\n\t" \
+ "sd $4, 0($29)\n\t" \
+ "ld $4, 80(%1)\n\t" \
+ "sd $4, 8($29)\n\t" \
+ "ld $4, 88(%1)\n\t" \
+ "sd $4, 16($29)\n\t" \
+ "ld $4, 96(%1)\n\t" \
+ "sd $4, 24($29)\n\t" \
+ "ld $4, 8(%1)\n\t" \
+ "ld $5, 16(%1)\n\t" \
+ "ld $6, 24(%1)\n\t" \
+ "ld $7, 32(%1)\n\t" \
+ "ld $8, 40(%1)\n\t" \
+ "ld $9, 48(%1)\n\t" \
+ "ld $10, 56(%1)\n\t" \
+ "ld $11, 64(%1)\n\t" \
+ "ld $25, 0(%1)\n\t" /* target->t9 */ \
+ VALGRIND_CALL_NOREDIR_T9 \
+ "daddu $29, $29, 32\n\t" \
+ "move %0, $2\n" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) (long)_res; \
+ } while (0)
+
+#endif /* PLAT_mips64_linux */
/* ------------------------------------------------------------------ */
/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
@@ -3590,8 +6120,9 @@ typedef
/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
This enum comprises an ABI exported by Valgrind to programs
- which use client requests. DO NOT CHANGE THE ORDER OF THESE
- ENTRIES, NOR DELETE ANY -- add new ones at the end. */
+ which use client requests. DO NOT CHANGE THE NUMERIC VALUES OF THESE
+ ENTRIES, NOR DELETE ANY -- add new ones at the end of the most
+ relevant group. */
typedef
enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
@@ -3611,9 +6142,14 @@ typedef
errors. */
VG_USERREQ__COUNT_ERRORS = 0x1201,
+ /* Allows the client program and/or gdbserver to execute a monitor
+ command. */
+ VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202,
+
/* These are useful and can be interpreted by any tool that
tracks malloc() et al, by using vg_replace_malloc.c. */
VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
+ VG_USERREQ__RESIZEINPLACE_BLOCK = 0x130b,
VG_USERREQ__FREELIKE_BLOCK = 0x1302,
/* Memory pool support. */
VG_USERREQ__CREATE_MEMPOOL = 0x1303,
@@ -3626,91 +6162,161 @@ typedef
VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
/* Allow printfs to valgrind log. */
+ /* The first two pass the va_list argument by value, which
+ assumes it is the same size as or smaller than a UWord,
+ which generally isn't the case. Hence are deprecated.
+ The second two pass the vargs by reference and so are
+ immune to this problem. */
+ /* both :: char* fmt, va_list vargs (DEPRECATED) */
VG_USERREQ__PRINTF = 0x1401,
VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
+ /* both :: char* fmt, va_list* vargs */
+ VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
+ VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
/* Stack support. */
VG_USERREQ__STACK_REGISTER = 0x1501,
VG_USERREQ__STACK_DEREGISTER = 0x1502,
- VG_USERREQ__STACK_CHANGE = 0x1503
+ VG_USERREQ__STACK_CHANGE = 0x1503,
+
+ /* Wine support */
+ VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601,
+
+ /* Querying of debug info. */
+ VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701,
+
+ /* Disable/enable error reporting level. Takes a single
+ Word arg which is the delta to this thread's error
+ disablement indicator. Hence 1 disables or further
+ disables errors, and -1 moves back towards enablement.
+ Other values are not allowed. */
+ VG_USERREQ__CHANGE_ERR_DISABLEMENT = 0x1801,
+
+ /* Some requests used for Valgrind internal, such as
+ self-test or self-hosting. */
+ /* Initialise IR injection */
+ VG_USERREQ__VEX_INIT_FOR_IRI = 0x1901,
+ /* Used by Inner Valgrind to inform Outer Valgrind where to
+ find the list of inner guest threads */
+ VG_USERREQ__INNER_THREADS = 0x1902
} Vg_ClientRequest;
#if !defined(__GNUC__)
# define __extension__ /* */
#endif
+
/* Returns the number of Valgrinds this code is running under. That
is, 0 if running natively, 1 if running under Valgrind, 2 if
running under Valgrind which is running under another Valgrind,
etc. */
-#define RUNNING_ON_VALGRIND __extension__ \
- ({unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \
- VG_USERREQ__RUNNING_ON_VALGRIND, \
- 0, 0, 0, 0, 0); \
- _qzz_res; \
- })
+#define RUNNING_ON_VALGRIND \
+ (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */, \
+ VG_USERREQ__RUNNING_ON_VALGRIND, \
+ 0, 0, 0, 0, 0) \
/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
_qzz_len - 1]. Useful if you are debugging a JITter or some such,
since it provides a way to make sure valgrind will retranslate the
invalidated area. Returns no value. */
-#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__DISCARD_TRANSLATIONS, \
- _qzz_addr, _qzz_len, 0, 0, 0); \
- }
+#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DISCARD_TRANSLATIONS, \
+ _qzz_addr, _qzz_len, 0, 0, 0)
+#define VALGRIND_INNER_THREADS(_qzz_addr) \
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__INNER_THREADS, \
+ _qzz_addr, 0, 0, 0, 0)
-/* These requests are for getting Valgrind itself to print something.
- Possibly with a backtrace. This is a really ugly hack. */
-
-#if defined(NVALGRIND)
-# define VALGRIND_PRINTF(...)
-# define VALGRIND_PRINTF_BACKTRACE(...)
-
-#else /* NVALGRIND */
+/* These requests are for getting Valgrind itself to print something.
+ Possibly with a backtrace. This is a really ugly hack. The return value
+ is the number of characters printed, excluding the "**<pid>** " part at the
+ start and the backtrace (if present). */
+#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
/* Modern GCC will optimize the static routine out if unused,
and unused attribute will shut down warnings about it. */
static int VALGRIND_PRINTF(const char *format, ...)
__attribute__((format(__printf__, 1, 2), __unused__));
+#endif
static int
+#if defined(_MSC_VER)
+__inline
+#endif
VALGRIND_PRINTF(const char *format, ...)
{
+#if defined(NVALGRIND)
+ (void)format;
+ return 0;
+#else /* NVALGRIND */
+#if defined(_MSC_VER) || defined(__MINGW64__)
+ uintptr_t _qzz_res;
+#else
unsigned long _qzz_res;
+#endif
va_list vargs;
va_start(vargs, format);
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF,
- (unsigned long)format, (unsigned long)vargs,
+#if defined(_MSC_VER) || defined(__MINGW64__)
+ _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
+ VG_USERREQ__PRINTF_VALIST_BY_REF,
+ (uintptr_t)format,
+ (uintptr_t)&vargs,
0, 0, 0);
+#else
+ _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
+ VG_USERREQ__PRINTF_VALIST_BY_REF,
+ (unsigned long)format,
+ (unsigned long)&vargs,
+ 0, 0, 0);
+#endif
va_end(vargs);
return (int)_qzz_res;
+#endif /* NVALGRIND */
}
+#if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER)
static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
__attribute__((format(__printf__, 1, 2), __unused__));
+#endif
static int
+#if defined(_MSC_VER)
+__inline
+#endif
VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
{
+#if defined(NVALGRIND)
+ (void)format;
+ return 0;
+#else /* NVALGRIND */
+#if defined(_MSC_VER) || defined(__MINGW64__)
+ uintptr_t _qzz_res;
+#else
unsigned long _qzz_res;
+#endif
va_list vargs;
va_start(vargs, format);
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF_BACKTRACE,
- (unsigned long)format, (unsigned long)vargs,
+#if defined(_MSC_VER) || defined(__MINGW64__)
+ _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
+ VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
+ (uintptr_t)format,
+ (uintptr_t)&vargs,
0, 0, 0);
+#else
+ _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
+ VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
+ (unsigned long)format,
+ (unsigned long)&vargs,
+ 0, 0, 0);
+#endif
va_end(vargs);
return (int)_qzz_res;
-}
-
#endif /* NVALGRIND */
+}
/* These requests allow control to move from the simulated CPU to the
- real CPU, calling an arbitary function.
+ real CPU, calling an arbitrary function.
Note that the current ThreadId is inserted as the first argument.
So this call:
@@ -3733,201 +6339,309 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
with a lot in the past.
*/
#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
- __extension__ \
- ({unsigned long _qyy_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
- VG_USERREQ__CLIENT_CALL0, \
- _qyy_fn, \
- 0, 0, 0, 0); \
- _qyy_res; \
- })
-
-#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
- __extension__ \
- ({unsigned long _qyy_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
- VG_USERREQ__CLIENT_CALL1, \
- _qyy_fn, \
- _qyy_arg1, 0, 0, 0); \
- _qyy_res; \
- })
-
-#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
- __extension__ \
- ({unsigned long _qyy_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
- VG_USERREQ__CLIENT_CALL2, \
- _qyy_fn, \
- _qyy_arg1, _qyy_arg2, 0, 0); \
- _qyy_res; \
- })
+ VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
+ VG_USERREQ__CLIENT_CALL0, \
+ _qyy_fn, \
+ 0, 0, 0, 0)
+
+#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
+ VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
+ VG_USERREQ__CLIENT_CALL1, \
+ _qyy_fn, \
+ _qyy_arg1, 0, 0, 0)
+
+#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
+ VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
+ VG_USERREQ__CLIENT_CALL2, \
+ _qyy_fn, \
+ _qyy_arg1, _qyy_arg2, 0, 0)
#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
- __extension__ \
- ({unsigned long _qyy_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
- VG_USERREQ__CLIENT_CALL3, \
- _qyy_fn, \
- _qyy_arg1, _qyy_arg2, \
- _qyy_arg3, 0); \
- _qyy_res; \
- })
+ VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
+ VG_USERREQ__CLIENT_CALL3, \
+ _qyy_fn, \
+ _qyy_arg1, _qyy_arg2, \
+ _qyy_arg3, 0)
/* Counts the number of errors that have been recorded by a tool. Nb:
the tool must record the errors with VG_(maybe_record_error)() or
VG_(unique_error)() for them to be counted. */
#define VALGRIND_COUNT_ERRORS \
- __extension__ \
- ({unsigned int _qyy_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
+ (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR( \
+ 0 /* default return */, \
VG_USERREQ__COUNT_ERRORS, \
- 0, 0, 0, 0, 0); \
- _qyy_res; \
- })
-
-/* Mark a block of memory as having been allocated by a malloc()-like
- function. `addr' is the start of the usable block (ie. after any
- redzone) `rzB' is redzone size if the allocator can apply redzones;
- use '0' if not. Adding redzones makes it more likely Valgrind will spot
- block overruns. `is_zeroed' indicates if the memory is zeroed, as it is
- for calloc(). Put it immediately after the point where a block is
- allocated.
+ 0, 0, 0, 0, 0)
+
+/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
+ when heap blocks are allocated in order to give accurate results. This
+ happens automatically for the standard allocator functions such as
+ malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
+ delete[], etc.
+
+ But if your program uses a custom allocator, this doesn't automatically
+ happen, and Valgrind will not do as well. For example, if you allocate
+ superblocks with mmap() and then allocates chunks of the superblocks, all
+ Valgrind's observations will be at the mmap() level and it won't know that
+ the chunks should be considered separate entities. In Memcheck's case,
+ that means you probably won't get heap block overrun detection (because
+ there won't be redzones marked as unaddressable) and you definitely won't
+ get any leak detection.
+
+ The following client requests allow a custom allocator to be annotated so
+ that it can be handled accurately by Valgrind.
+
+ VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
+ by a malloc()-like function. For Memcheck (an illustrative case), this
+ does two things:
+
+ - It records that the block has been allocated. This means any addresses
+ within the block mentioned in error messages will be
+ identified as belonging to the block. It also means that if the block
+ isn't freed it will be detected by the leak checker.
+
+ - It marks the block as being addressable and undefined (if 'is_zeroed' is
+ not set), or addressable and defined (if 'is_zeroed' is set). This
+ controls how accesses to the block by the program are handled.
- If you're using Memcheck: If you're allocating memory via superblocks,
- and then handing out small chunks of each superblock, if you don't have
- redzones on your small blocks, it's worth marking the superblock with
- VALGRIND_MAKE_MEM_NOACCESS when it's created, so that block overruns are
- detected. But if you can put redzones on, it's probably better to not do
- this, so that messages for small overruns are described in terms of the
- small block rather than the superblock (but if you have a big overrun
- that skips over a redzone, you could miss an error this way). See
- memcheck/tests/custom_alloc.c for an example.
-
- WARNING: if your allocator uses malloc() or 'new' to allocate
- superblocks, rather than mmap() or brk(), this will not work properly --
- you'll likely get assertion failures during leak detection. This is
- because Valgrind doesn't like seeing overlapping heap blocks. Sorry.
-
- Nb: block must be freed via a free()-like function specified
- with VALGRIND_FREELIKE_BLOCK or mismatch errors will occur. */
-#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__MALLOCLIKE_BLOCK, \
- addr, sizeB, rzB, is_zeroed, 0); \
- }
+ 'addr' is the start of the usable block (ie. after any
+ redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
+ can apply redzones -- these are blocks of padding at the start and end of
+ each block. Adding redzones is recommended as it makes it much more likely
+ Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
+ zeroed (or filled with another predictable value), as is the case for
+ calloc().
+
+ VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
+ heap block -- that will be used by the client program -- is allocated.
+ It's best to put it at the outermost level of the allocator if possible;
+ for example, if you have a function my_alloc() which calls
+ internal_alloc(), and the client request is put inside internal_alloc(),
+ stack traces relating to the heap block will contain entries for both
+ my_alloc() and internal_alloc(), which is probably not what you want.
+
+ For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
+ custom blocks from within a heap block, B, that has been allocated with
+ malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
+ -- the custom blocks will take precedence.
+
+ VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
+ Memcheck, it does two things:
+
+ - It records that the block has been deallocated. This assumes that the
+ block was annotated as having been allocated via
+ VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
+
+ - It marks the block as being unaddressable.
+
+ VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
+ heap block is deallocated.
+
+ VALGRIND_RESIZEINPLACE_BLOCK informs a tool about reallocation. For
+ Memcheck, it does four things:
+
+ - It records that the size of a block has been changed. This assumes that
+ the block was annotated as having been allocated via
+ VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
+
+ - If the block shrunk, it marks the freed memory as being unaddressable.
+
+ - If the block grew, it marks the new area as undefined and defines a red
+ zone past the end of the new block.
+
+ - The V-bits of the overlap between the old and the new block are preserved.
+
+ VALGRIND_RESIZEINPLACE_BLOCK should be put after allocation of the new block
+ and before deallocation of the old block.
+
+ In many cases, these three client requests will not be enough to get your
+ allocator working well with Memcheck. More specifically, if your allocator
+ writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
+ will be necessary to mark the memory as addressable just before the zeroing
+ occurs, otherwise you'll get a lot of invalid write errors. For example,
+ you'll need to do this if your allocator recycles freed blocks, but it
+ zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
+ Alternatively, if your allocator reuses freed blocks for allocator-internal
+ data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
+
+ Really, what's happening is a blurring of the lines between the client
+ program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
+ memory should be considered unaddressable to the client program, but the
+ allocator knows more than the rest of the client program and so may be able
+ to safely access it. Extra client requests are necessary for Valgrind to
+ understand the distinction between the allocator and the rest of the
+ program.
+
+ Ignored if addr == 0.
+*/
+#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MALLOCLIKE_BLOCK, \
+ addr, sizeB, rzB, is_zeroed, 0)
-/* Mark a block of memory as having been freed by a free()-like function.
- `rzB' is redzone size; it must match that given to
- VALGRIND_MALLOCLIKE_BLOCK. Memory not freed will be detected by the leak
- checker. Put it immediately after the point where the block is freed. */
-#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__FREELIKE_BLOCK, \
- addr, rzB, 0, 0, 0); \
- }
+/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
+ Ignored if addr == 0.
+*/
+#define VALGRIND_RESIZEINPLACE_BLOCK(addr, oldSizeB, newSizeB, rzB) \
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__RESIZEINPLACE_BLOCK, \
+ addr, oldSizeB, newSizeB, rzB, 0)
+
+/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
+ Ignored if addr == 0.
+*/
+#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__FREELIKE_BLOCK, \
+ addr, rzB, 0, 0, 0)
/* Create a memory pool. */
#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__CREATE_MEMPOOL, \
- pool, rzB, is_zeroed, 0, 0); \
- }
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL, \
+ pool, rzB, is_zeroed, 0, 0)
+
+/* Create a memory pool with some flags specifying extended behaviour.
+ When flags is zero, the behaviour is identical to VALGRIND_CREATE_MEMPOOL.
+
+ The flag VALGRIND_MEMPOOL_METAPOOL specifies that the pieces of memory
+ associated with the pool using VALGRIND_MEMPOOL_ALLOC will be used
+ by the application as superblocks to dole out MALLOC_LIKE blocks using
+ VALGRIND_MALLOCLIKE_BLOCK. In other words, a meta pool is a "2 levels"
+ pool : first level is the blocks described by VALGRIND_MEMPOOL_ALLOC.
+ The second level blocks are described using VALGRIND_MALLOCLIKE_BLOCK.
+ Note that the association between the pool and the second level blocks
+ is implicit : second level blocks will be located inside first level
+ blocks. It is necessary to use the VALGRIND_MEMPOOL_METAPOOL flag
+ for such 2 levels pools, as otherwise valgrind will detect overlapping
+ memory blocks, and will abort execution (e.g. during leak search).
+
+ Such a meta pool can also be marked as an 'auto free' pool using the flag
+ VALGRIND_MEMPOOL_AUTO_FREE, which must be OR-ed together with the
+ VALGRIND_MEMPOOL_METAPOOL. For an 'auto free' pool, VALGRIND_MEMPOOL_FREE
+ will automatically free the second level blocks that are contained
+ inside the first level block freed with VALGRIND_MEMPOOL_FREE.
+ In other words, calling VALGRIND_MEMPOOL_FREE will cause implicit calls
+ to VALGRIND_FREELIKE_BLOCK for all the second level blocks included
+ in the first level block.
+ Note: it is an error to use the VALGRIND_MEMPOOL_AUTO_FREE flag
+ without the VALGRIND_MEMPOOL_METAPOOL flag.
+*/
+#define VALGRIND_MEMPOOL_AUTO_FREE 1
+#define VALGRIND_MEMPOOL_METAPOOL 2
+#define VALGRIND_CREATE_MEMPOOL_EXT(pool, rzB, is_zeroed, flags) \
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL, \
+ pool, rzB, is_zeroed, flags, 0)
/* Destroy a memory pool. */
#define VALGRIND_DESTROY_MEMPOOL(pool) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__DESTROY_MEMPOOL, \
- pool, 0, 0, 0, 0); \
- }
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DESTROY_MEMPOOL, \
+ pool, 0, 0, 0, 0)
/* Associate a piece of memory with a memory pool. */
#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__MEMPOOL_ALLOC, \
- pool, addr, size, 0, 0); \
- }
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_ALLOC, \
+ pool, addr, size, 0, 0)
/* Disassociate a piece of memory from a memory pool. */
#define VALGRIND_MEMPOOL_FREE(pool, addr) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__MEMPOOL_FREE, \
- pool, addr, 0, 0, 0); \
- }
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_FREE, \
+ pool, addr, 0, 0, 0)
/* Disassociate any pieces outside a particular range. */
#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__MEMPOOL_TRIM, \
- pool, addr, size, 0, 0); \
- }
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_TRIM, \
+ pool, addr, size, 0, 0)
/* Resize and/or move a piece associated with a memory pool. */
#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__MOVE_MEMPOOL, \
- poolA, poolB, 0, 0, 0); \
- }
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MOVE_MEMPOOL, \
+ poolA, poolB, 0, 0, 0)
/* Resize and/or move a piece associated with a memory pool. */
#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__MEMPOOL_CHANGE, \
- pool, addrA, addrB, size, 0); \
- }
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_CHANGE, \
+ pool, addrA, addrB, size, 0)
/* Return 1 if a mempool exists, else 0. */
#define VALGRIND_MEMPOOL_EXISTS(pool) \
- ({unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
VG_USERREQ__MEMPOOL_EXISTS, \
- pool, 0, 0, 0, 0); \
- _qzz_res; \
- })
+ pool, 0, 0, 0, 0)
-/* Mark a piece of memory as being a stack. Returns a stack id. */
+/* Mark a piece of memory as being a stack. Returns a stack id.
+ start is the lowest addressable stack byte, end is the highest
+ addressable stack byte. */
#define VALGRIND_STACK_REGISTER(start, end) \
- ({unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
VG_USERREQ__STACK_REGISTER, \
- start, end, 0, 0, 0); \
- _qzz_res; \
- })
+ start, end, 0, 0, 0)
/* Unmark the piece of memory associated with a stack id as being a
stack. */
#define VALGRIND_STACK_DEREGISTER(id) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__STACK_DEREGISTER, \
- id, 0, 0, 0, 0); \
- }
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_DEREGISTER, \
+ id, 0, 0, 0, 0)
-/* Change the start and end address of the stack id. */
+/* Change the start and end address of the stack id.
+ start is the new lowest addressable stack byte, end is the new highest
+ addressable stack byte. */
#define VALGRIND_STACK_CHANGE(id, start, end) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__STACK_CHANGE, \
- id, start, end, 0, 0); \
- }
-
-
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_CHANGE, \
+ id, start, end, 0, 0)
+
+/* Load PDB debug info for Wine PE image_map. */
+#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__LOAD_PDB_DEBUGINFO, \
+ fd, ptr, total_size, delta, 0)
+
+/* Map a code address to a source file name and line number. buf64
+ must point to a 64-byte buffer in the caller's address space. The
+ result will be dumped in there and is guaranteed to be zero
+ terminated. If no info is found, the first byte is set to zero. */
+#define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \
+ (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
+ VG_USERREQ__MAP_IP_TO_SRCLOC, \
+ addr, buf64, 0, 0, 0)
+
+/* Disable error reporting for this thread. Behaves in a stack like
+ way, so you can safely call this multiple times provided that
+ VALGRIND_ENABLE_ERROR_REPORTING is called the same number of times
+ to re-enable reporting. The first call of this macro disables
+ reporting. Subsequent calls have no effect except to increase the
+ number of VALGRIND_ENABLE_ERROR_REPORTING calls needed to re-enable
+ reporting. Child threads do not inherit this setting from their
+ parents -- they are always created with reporting enabled. */
+#define VALGRIND_DISABLE_ERROR_REPORTING \
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
+ 1, 0, 0, 0, 0)
+
+/* Re-enable error reporting, as per comments on
+ VALGRIND_DISABLE_ERROR_REPORTING. */
+#define VALGRIND_ENABLE_ERROR_REPORTING \
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \
+ -1, 0, 0, 0, 0)
+
+/* Execute a monitor command from the client program.
+ If a connection is opened with GDB, the output will be sent
+ according to the output mode set for vgdb.
+ If no connection is opened, output will go to the log output.
+ Returns 1 if command not recognised, 0 otherwise. */
+#define VALGRIND_MONITOR_COMMAND(command) \
+ VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__GDB_MONITOR_COMMAND, \
+ command, 0, 0, 0, 0)
+
+
+#undef PLAT_x86_darwin
+#undef PLAT_amd64_darwin
+#undef PLAT_x86_win32
+#undef PLAT_amd64_win64
#undef PLAT_x86_linux
#undef PLAT_amd64_linux
#undef PLAT_ppc32_linux
-#undef PLAT_ppc64_linux
-#undef PLAT_ppc32_aix5
-#undef PLAT_ppc64_aix5
+#undef PLAT_ppc64be_linux
+#undef PLAT_ppc64le_linux
+#undef PLAT_arm_linux
+#undef PLAT_s390x_linux
+#undef PLAT_mips32_linux
+#undef PLAT_mips64_linux
+#undef PLAT_x86_solaris
+#undef PLAT_amd64_solaris
#endif /* __VALGRIND_H */
-
-
diff --git a/src/testlib/doc/snippets/code/doc_src_qtestlib.cpp b/src/testlib/doc/snippets/code/doc_src_qtestlib.cpp
index 0dc45bef76..de301b8df9 100644
--- a/src/testlib/doc/snippets/code/doc_src_qtestlib.cpp
+++ b/src/testlib/doc/snippets/code/doc_src_qtestlib.cpp
@@ -48,19 +48,41 @@
**
****************************************************************************/
+#include <QtTest>
+
//! [0]
class MyFirstTest: public QObject
{
Q_OBJECT
+
+private:
+ bool myCondition()
+ {
+ return true;
+ }
+
private slots:
void initTestCase()
- { qDebug("called before everything else"); }
+ {
+ qDebug("Called before everything else.");
+ }
+
void myFirstTest()
- { QVERIFY(1 == 1); }
+ {
+ QVERIFY(true); // check that a condition is satisfied
+ QCOMPARE(1, 1); // compare two values
+ }
+
void mySecondTest()
- { QVERIFY(1 != 2); }
+ {
+ QVERIFY(myCondition());
+ QVERIFY(1 != 2);
+ }
+
void cleanupTestCase()
- { qDebug("called after myFirstTest and mySecondTest"); }
+ {
+ qDebug("Called after myFirstTest and mySecondTest.");
+ }
};
//! [0]
diff --git a/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp b/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp
index 990b7a38d7..202f87af52 100644
--- a/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp
+++ b/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp
@@ -177,13 +177,6 @@ namespace MyNamespace {
}
//! [toString-overload]
-//! [17]
-int i = 0;
-while (myNetworkServerNotResponding() && i++ < 50)
- QTest::qWait(250);
-//! [17]
-
-
//! [18]
MyTestObject test1;
QTest::qExec(&test1);
@@ -245,11 +238,6 @@ void MyTestClass::cleanup()
QTest::qSleep(250);
//! [23]
-//! [24]
-QWidget widget;
-widget.show();
-QTest::qWaitForWindowShown(&widget);
-//! [24]
//! [25]
QTouchDevice *dev = QTest::createTouchDevice();
@@ -306,13 +294,5 @@ QTest::keyClick(myWindow, Qt::Key_Escape);
QTest::keyClick(myWindow, Qt::Key_Escape, Qt::ShiftModifier, 200);
//! [29]
-//! [30]
-MyObject obj;
-obj.startup();
-QTest::qWaitFor([&]() {
- return obj.isReady();
-}, 3000);
-//! [30]
-
}
diff --git a/src/testlib/doc/src/qttest-index.qdoc b/src/testlib/doc/src/qttest-index.qdoc
index 8c817b3653..6e4f954034 100644
--- a/src/testlib/doc/src/qttest-index.qdoc
+++ b/src/testlib/doc/src/qttest-index.qdoc
@@ -35,6 +35,11 @@
and the \l QAbstractItemModelTester allows for non-destructive testing
of item models.
+ \note There is no binary compatibility guarantee for the Qt Test module.
+ This means that an application that uses Qt Test is only guaranteed
+ to work with the Qt version it was developed against. However, source
+ compatibility is guaranteed.
+
\section1 Getting Started
To enable Qt Test in a project, add this directive into the C++ files:
diff --git a/src/testlib/doc/src/qttestlib-manual.qdoc b/src/testlib/doc/src/qttestlib-manual.qdoc
index 363ec17c6c..71b4541313 100644
--- a/src/testlib/doc/src/qttestlib-manual.qdoc
+++ b/src/testlib/doc/src/qttestlib-manual.qdoc
@@ -69,8 +69,8 @@
\li Qt Test supports benchmarking and provides several measurement back-ends.
\row
\li \b {IDE friendly}
- \li Qt Test outputs messages that can be interpreted by Visual
- Studio and KDevelop.
+ \li Qt Test outputs messages that can be interpreted by Qt Creator, Visual
+ Studio, and KDevelop.
\row
\li \b Thread-safety
\li The error reporting is thread safe and atomic.
@@ -177,7 +177,7 @@
\list
\li \c -o \e{filename,format} \br
Writes output to the specified file, in the specified format (one of
- \c txt, \c xml, \c lightxml or \c xunitxml). The special filename \c -
+ \c txt, \c xml, \c lightxml, \c xunitxml or \c tap). The special filename \c -
may be used to log to standard output.
\li \c -o \e filename \br
Writes output to the specified file.
@@ -194,6 +194,8 @@
benchmarks, since it suppresses normal pass/fail messages.
\li \c -teamcity \br
Outputs results in TeamCity format.
+ \li \c -tap \br
+ Outputs results in Test Anything Protocol (TAP) format.
\endlist
The first version of the \c -o option may be repeated in order to log
@@ -201,8 +203,8 @@
option can log test results to standard output.
If the first version of the \c -o option is used, neither the second version
- of the \c -o option nor the \c -txt, \c -xml, \c -lightxml, \c -teamcity
- or \c -xunitxml options should be used.
+ of the \c -o option nor the \c -txt, \c -xml, \c -lightxml, \c -teamcity,
+ \c -xunitxml or \c -tap options should be used.
If neither version of the \c -o option is used, test results will be logged to
standard output. If no format option is used, test results will be logged in
diff --git a/src/testlib/qabstracttestlogger.cpp b/src/testlib/qabstracttestlogger.cpp
index 63c165b9dc..2b54cd410b 100644
--- a/src/testlib/qabstracttestlogger.cpp
+++ b/src/testlib/qabstracttestlogger.cpp
@@ -39,6 +39,7 @@
#include <QtTest/private/qabstracttestlogger_p.h>
#include <QtTest/qtestassert.h>
+#include <qtestresult_p.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qstring.h>
@@ -189,4 +190,26 @@ int qt_asprintf(QTestCharBuffer *str, const char *format, ...)
}
+namespace QTestPrivate
+{
+
+void generateTestIdentifier(QTestCharBuffer *identifier, int parts)
+{
+ const char *testObject = parts & TestObject ? QTestResult::currentTestObjectName() : "";
+ const char *testFunction = parts & TestFunction ? (QTestResult::currentTestFunction() ? QTestResult::currentTestFunction() : "UnknownTestFunc") : "";
+ const char *objectFunctionFiller = parts & TestObject && parts & (TestFunction | TestDataTag) ? "::" : "";
+ const char *testFuctionStart = parts & TestFunction ? "(" : "";
+ const char *testFuctionEnd = parts & TestFunction ? ")" : "";
+
+ const char *dataTag = (parts & TestDataTag) && QTestResult::currentDataTag() ? QTestResult::currentDataTag() : "";
+ const char *globalDataTag = (parts & TestDataTag) && QTestResult::currentGlobalDataTag() ? QTestResult::currentGlobalDataTag() : "";
+ const char *tagFiller = (dataTag[0] && globalDataTag[0]) ? ":" : "";
+
+ QTest::qt_asprintf(identifier, "%s%s%s%s%s%s%s%s",
+ testObject, objectFunctionFiller, testFunction, testFuctionStart,
+ globalDataTag, tagFiller, dataTag, testFuctionEnd);
+}
+
+}
+
QT_END_NAMESPACE
diff --git a/src/testlib/qabstracttestlogger_p.h b/src/testlib/qabstracttestlogger_p.h
index c4083b43f4..018361b81e 100644
--- a/src/testlib/qabstracttestlogger_p.h
+++ b/src/testlib/qabstracttestlogger_p.h
@@ -58,6 +58,7 @@
QT_BEGIN_NAMESPACE
class QBenchmarkResult;
+class QTestData;
class QAbstractTestLogger
{
@@ -91,6 +92,8 @@ public:
virtual void enterTestFunction(const char *function) = 0;
virtual void leaveTestFunction() = 0;
+ virtual void enterTestData(QTestData *) {}
+
virtual void addIncident(IncidentTypes type, const char *description,
const char *file = 0, int line = 0) = 0;
virtual void addBenchmarkResult(const QBenchmarkResult &result) = 0;
@@ -175,6 +178,11 @@ namespace QTest
int qt_asprintf(QTestCharBuffer *buf, const char *format, ...);
}
+namespace QTestPrivate
+{
+ enum IdentifierPart { TestObject = 0x1, TestFunction = 0x2, TestDataTag = 0x4, AllParts = 0xFFFF };
+ void generateTestIdentifier(QTestCharBuffer *identifier, int parts = AllParts);
+}
QT_END_NAMESPACE
diff --git a/src/testlib/qappletestlogger.cpp b/src/testlib/qappletestlogger.cpp
new file mode 100644
index 0000000000..2c1005ad80
--- /dev/null
+++ b/src/testlib/qappletestlogger.cpp
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 "qappletestlogger_p.h"
+
+#include <QPair>
+
+QT_BEGIN_NAMESPACE
+
+#if defined(QT_USE_APPLE_UNIFIED_LOGGING)
+
+using namespace QTestPrivate;
+
+bool QAppleTestLogger::debugLoggingEnabled()
+{
+ // Debug-level messages are only captured in memory when debug logging is
+ // enabled through a configuration change, which can happen automatically
+ // when running inside Xcode, or with the Console application open.
+ return os_log_type_enabled(OS_LOG_DEFAULT, OS_LOG_TYPE_DEBUG);
+}
+
+QAppleTestLogger::QAppleTestLogger(QAbstractTestLogger *logger)
+ : QAbstractTestLogger(nullptr)
+ , m_logger(logger)
+{
+}
+
+static QAppleLogActivity testFunctionActivity;
+
+void QAppleTestLogger::enterTestFunction(const char *function)
+{
+ // Re-create activity each time
+ testFunctionActivity = QT_APPLE_LOG_ACTIVITY("Running test function").enter();
+
+ QTestCharBuffer testIdentifier;
+ QTestPrivate::generateTestIdentifier(&testIdentifier);
+ QString identifier = QString::fromLatin1(testIdentifier.data());
+ QMessageLogContext context(nullptr, 0, nullptr, "qt.test.enter");
+ QString message = identifier;
+ if (AppleUnifiedLogger::messageHandler(QtDebugMsg, context, message, identifier))
+ return; // AUL already printed to stderr
+
+ m_logger->enterTestFunction(function);
+}
+
+void QAppleTestLogger::leaveTestFunction()
+{
+ m_logger->leaveTestFunction();
+ testFunctionActivity.leave();
+}
+
+typedef QPair<QtMsgType, const char *> IncidentClassification;
+static IncidentClassification incidentTypeToClassification(QAbstractTestLogger::IncidentTypes type)
+{
+ switch (type) {
+ case QAbstractTestLogger::Pass:
+ return IncidentClassification(QtInfoMsg, "pass");
+ case QAbstractTestLogger::XFail:
+ return IncidentClassification(QtInfoMsg, "xfail");
+ case QAbstractTestLogger::Fail:
+ return IncidentClassification(QtCriticalMsg, "fail");
+ case QAbstractTestLogger::XPass:
+ return IncidentClassification(QtInfoMsg, "xpass");
+ case QAbstractTestLogger::BlacklistedPass:
+ return IncidentClassification(QtWarningMsg, "bpass");
+ case QAbstractTestLogger::BlacklistedFail:
+ return IncidentClassification(QtInfoMsg, "bfail");
+ }
+ return IncidentClassification(QtFatalMsg, nullptr);
+}
+
+void QAppleTestLogger::addIncident(IncidentTypes type, const char *description,
+ const char *file, int line)
+{
+
+ IncidentClassification incidentClassification = incidentTypeToClassification(type);
+
+ QTestCharBuffer category;
+ QTest::qt_asprintf(&category, "qt.test.%s", incidentClassification.second);
+ QMessageLogContext context(file, line, /* function = */ nullptr, category.data());
+
+ QTestCharBuffer subsystemBuffer;
+ // It would be nice to have the data tag as part of the subsystem too, but that
+ // will for some tests results in hundreds of thousands of log objects being
+ // created, so we limit the subsystem to test functions, which we can hope
+ // are reasonably limited.
+ generateTestIdentifier(&subsystemBuffer, TestObject | TestFunction);
+ QString subsystem = QString::fromLatin1(subsystemBuffer.data());
+
+ // We still want the full identifier as part of the message though
+ QTestCharBuffer testIdentifier;
+ generateTestIdentifier(&testIdentifier);
+ QString message = QString::fromLatin1(testIdentifier.data());
+ if (qstrlen(description))
+ message += QLatin1Char('\n') % QString::fromLatin1(description);
+
+ if (AppleUnifiedLogger::messageHandler(incidentClassification.first, context, message, subsystem))
+ return; // AUL already printed to stderr
+
+ m_logger->addIncident(type, description, file, line);
+}
+
+void QAppleTestLogger::addMessage(QtMsgType type, const QMessageLogContext &context, const QString &message)
+{
+ if (AppleUnifiedLogger::messageHandler(type, context, message))
+ return; // AUL already printed to stderr
+
+ m_logger->addMessage(type, context, message);
+}
+
+#endif // QT_USE_APPLE_UNIFIED_LOGGING
+
+QT_END_NAMESPACE
diff --git a/src/testlib/qappletestlogger_p.h b/src/testlib/qappletestlogger_p.h
new file mode 100644
index 0000000000..5a45fad7a0
--- /dev/null
+++ b/src/testlib/qappletestlogger_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 QAPPLETESTLOGGER_P_H
+#define QAPPLETESTLOGGER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtTest/private/qabstracttestlogger_p.h>
+
+#include <QtCore/private/qcore_mac_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#if defined(QT_USE_APPLE_UNIFIED_LOGGING)
+class QAppleTestLogger : public QAbstractTestLogger
+{
+public:
+ static bool debugLoggingEnabled();
+
+ QAppleTestLogger(QAbstractTestLogger *logger);
+
+ void startLogging() override
+ { m_logger->startLogging(); }
+ void stopLogging() override
+ { m_logger->stopLogging(); }
+
+ void enterTestFunction(const char *function) override;
+ void leaveTestFunction() override;
+
+ void addIncident(IncidentTypes type, const char *description,
+ const char *file = 0, int line = 0) override;
+ void addMessage(QtMsgType, const QMessageLogContext &,
+ const QString &) override;
+
+ void addBenchmarkResult(const QBenchmarkResult &result) override
+ { m_logger->addBenchmarkResult(result); }
+
+ void addMessage(MessageTypes type, const QString &message,
+ const char *file = 0, int line = 0) override
+ { m_logger->addMessage(type, message, file, line); }
+
+private:
+ QScopedPointer<QAbstractTestLogger> m_logger;
+};
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QAPPLETESTLOGGER_P_H
diff --git a/src/testlib/qplaintestlogger.cpp b/src/testlib/qplaintestlogger.cpp
index e5226b7820..853515f2d9 100644
--- a/src/testlib/qplaintestlogger.cpp
+++ b/src/testlib/qplaintestlogger.cpp
@@ -221,18 +221,6 @@ void QPlainTestLogger::outputMessage(const char *str)
outputString(str);
}
-static void testIdentifier(QTestCharBuffer *identifier)
-{
- const char *testObject = QTestResult::currentTestObjectName();
- const char *testFunction = QTestResult::currentTestFunction() ? QTestResult::currentTestFunction() : "UnknownTestFunc";
-
- const char *dataTag = QTestResult::currentDataTag() ? QTestResult::currentDataTag() : "";
- const char *globalDataTag = QTestResult::currentGlobalDataTag() ? QTestResult::currentGlobalDataTag() : "";
- const char *tagFiller = (dataTag[0] && globalDataTag[0]) ? ":" : "";
-
- QTest::qt_asprintf(identifier, "%s::%s(%s%s%s)", testObject, testFunction, globalDataTag, tagFiller, dataTag);
-}
-
void QPlainTestLogger::printMessage(const char *type, const char *msg, const char *file, int line)
{
QTEST_ASSERT(type);
@@ -251,10 +239,10 @@ void QPlainTestLogger::printMessage(const char *type, const char *msg, const cha
}
const char *msgFiller = msg[0] ? " " : "";
- QTestCharBuffer testIdent;
- testIdentifier(&testIdent);
+ QTestCharBuffer testIdentifier;
+ QTestPrivate::generateTestIdentifier(&testIdentifier);
QTest::qt_asprintf(&messagePrefix, "%s: %s%s%s%s\n",
- type, testIdent.data(), msgFiller, msg, failureLocation.data());
+ type, testIdentifier.data(), msgFiller, msg, failureLocation.data());
// In colored mode, printf above stripped our nonprintable control characters.
// Put them back.
diff --git a/src/testlib/qsignalspy.h b/src/testlib/qsignalspy.h
index 824dc6aaed..218a26ec5c 100644
--- a/src/testlib/qsignalspy.h
+++ b/src/testlib/qsignalspy.h
@@ -59,11 +59,7 @@ public:
explicit QSignalSpy(const QObject *obj, const char *aSignal)
: m_waiting(false)
{
-#ifdef Q_CC_BOR
- const int memberOffset = QObject::staticMetaObject.methodCount();
-#else
static const int memberOffset = QObject::staticMetaObject.methodCount();
-#endif
if (!obj) {
qWarning("QSignalSpy: Cannot spy on a null object");
return;
@@ -104,11 +100,7 @@ public:
QSignalSpy(const typename QtPrivate::FunctionPointer<Func>::Object *obj, Func signal0)
: m_waiting(false)
{
-#ifdef Q_CC_BOR
- const int memberOffset = QObject::staticMetaObject.methodCount();
-#else
static const int memberOffset = QObject::staticMetaObject.methodCount();
-#endif
if (!obj) {
qWarning("QSignalSpy: Cannot spy on a null object");
return;
diff --git a/src/testlib/qtaptestlogger.cpp b/src/testlib/qtaptestlogger.cpp
new file mode 100644
index 0000000000..37ab89ac91
--- /dev/null
+++ b/src/testlib/qtaptestlogger.cpp
@@ -0,0 +1,254 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 "qtaptestlogger_p.h"
+
+#include "qtestlog_p.h"
+#include "qtestresult_p.h"
+#include "qtestassert.h"
+
+#include <QtCore/qregularexpression.h>
+
+QT_BEGIN_NAMESPACE
+
+QTapTestLogger::QTapTestLogger(const char *filename)
+ : QAbstractTestLogger(filename)
+ , m_wasExpectedFail(false)
+{
+}
+
+QTapTestLogger::~QTapTestLogger()
+{
+}
+
+void QTapTestLogger::startLogging()
+{
+ QAbstractTestLogger::startLogging();
+
+ QTestCharBuffer preamble;
+ QTest::qt_asprintf(&preamble, "TAP version 13\n"
+ // By convention, test suite names are output as diagnostics lines
+ // This is a pretty poor convention, as consumers will then treat
+ // actual diagnostics, e.g. qDebug, as test suite names o_O
+ "# %s\n", QTestResult::currentTestObjectName());
+ outputString(preamble.data());
+}
+
+void QTapTestLogger::stopLogging()
+{
+ const int total = QTestLog::totalCount();
+
+ QTestCharBuffer testPlanAndStats;
+ QTest::qt_asprintf(&testPlanAndStats,
+ "1..%d\n"
+ "# tests %d\n"
+ "# pass %d\n"
+ "# fail %d\n",
+ total, total, QTestLog::passCount(), QTestLog::failCount());
+ outputString(testPlanAndStats.data());
+
+ QAbstractTestLogger::stopLogging();
+}
+
+void QTapTestLogger::enterTestFunction(const char *function)
+{
+ Q_UNUSED(function);
+ m_wasExpectedFail = false;
+}
+
+void QTapTestLogger::enterTestData(QTestData *data)
+{
+ Q_UNUSED(data);
+ m_wasExpectedFail = false;
+}
+
+using namespace QTestPrivate;
+
+void QTapTestLogger::outputTestLine(bool ok, int testNumber, QTestCharBuffer &directive)
+{
+ QTestCharBuffer testIdentifier;
+ QTestPrivate::generateTestIdentifier(&testIdentifier, TestFunction | TestDataTag);
+
+ QTestCharBuffer testLine;
+ QTest::qt_asprintf(&testLine, "%s %d - %s%s\n",
+ ok ? "ok" : "not ok", testNumber, testIdentifier.data(), directive.data());
+
+ outputString(testLine.data());
+}
+
+void QTapTestLogger::addIncident(IncidentTypes type, const char *description,
+ const char *file, int line)
+{
+ if (m_wasExpectedFail && type == Pass) {
+ // XFail comes with a corresponding Pass incident, but we only want
+ // to emit a single test point for it, so skip the this pass.
+ return;
+ }
+
+ bool ok = type == Pass || type == XPass || type == BlacklistedPass;
+
+ QTestCharBuffer directive;
+ if (type == XFail || type == XPass || type == BlacklistedFail || type == BlacklistedPass)
+ // We treat expected or blacklisted failures/passes as TODO-failures/passes,
+ // which should be treated as soft issues by consumers. Not all do though :/
+ QTest::qt_asprintf(&directive, " # TODO %s", description);
+
+ int testNumber = QTestLog::totalCount();
+ if (type == XFail) {
+ // The global test counter hasn't been updated yet for XFail
+ testNumber += 1;
+ }
+
+ outputTestLine(ok, testNumber, directive);
+
+ if (!ok) {
+ // All failures need a diagnostics sections to not confuse consumers
+
+ // The indent needs to be two spaces for maximum compatibility
+ #define YAML_INDENT " "
+
+ outputString(YAML_INDENT "---\n");
+
+ if (type != XFail) {
+ // This is fragile, but unfortunately testlib doesn't plumb
+ // the expected and actual values to the loggers (yet).
+ static QRegularExpression verifyRegex(
+ QLatin1Literal("^'(?<actualexpression>.*)' returned (?<actual>\\w+).+\\((?<message>.*)\\)$"));
+
+ static QRegularExpression comparRegex(
+ QLatin1Literal("^(?<message>.*)\n"
+ "\\s*Actual\\s+\\((?<actualexpression>.*)\\)\\s*: (?<actual>.*)\n"
+ "\\s*Expected\\s+\\((?<expectedexpresssion>.*)\\)\\s*: (?<expected>.*)$"));
+
+ QString descriptionString = QString::fromUtf8(description);
+ QRegularExpressionMatch match = verifyRegex.match(descriptionString);
+ if (!match.hasMatch())
+ match = comparRegex.match(descriptionString);
+
+ if (match.hasMatch()) {
+ bool isVerify = match.regularExpression() == verifyRegex;
+ QString message = match.captured(QLatin1Literal("message"));
+ QString expected;
+ QString actual;
+
+ if (isVerify) {
+ QString expression = QLatin1Literal(" (")
+ % match.captured(QLatin1Literal("actualexpression")) % QLatin1Char(')') ;
+ actual = match.captured(QLatin1Literal("actual")).toLower() % expression;
+ expected = (actual.startsWith(QLatin1Literal("true")) ? QLatin1Literal("false") : QLatin1Literal("true")) % expression;
+ if (message.isEmpty())
+ message = QLatin1Literal("Verification failed");
+ } else {
+ expected = match.captured(QLatin1Literal("expected"))
+ % QLatin1Literal(" (") % match.captured(QLatin1Literal("expectedexpresssion")) % QLatin1Char(')');
+ actual = match.captured(QLatin1Literal("actual"))
+ % QLatin1Literal(" (") % match.captured(QLatin1Literal("actualexpression")) % QLatin1Char(')');
+ }
+
+ QTestCharBuffer diagnosticsYamlish;
+ QTest::qt_asprintf(&diagnosticsYamlish,
+ YAML_INDENT "type: %s\n"
+ YAML_INDENT "message: %s\n"
+
+ // Some consumers understand 'wanted/found', while others need
+ // 'expected/actual', so we do both for maximum compatibility.
+ YAML_INDENT "wanted: %s\n"
+ YAML_INDENT "found: %s\n"
+ YAML_INDENT "expected: %s\n"
+ YAML_INDENT "actual: %s\n",
+
+ isVerify ? "QVERIFY" : "QCOMPARE",
+ qPrintable(message),
+ qPrintable(expected), qPrintable(actual),
+ qPrintable(expected), qPrintable(actual)
+ );
+
+ outputString(diagnosticsYamlish.data());
+ } else {
+ QTestCharBuffer unparsableDescription;
+ QTest::qt_asprintf(&unparsableDescription,
+ YAML_INDENT "# %s\n", description);
+ outputString(unparsableDescription.data());
+ }
+ }
+
+ if (file) {
+ QTestCharBuffer location;
+ QTest::qt_asprintf(&location,
+ // The generic 'at' key is understood by most consumers.
+ YAML_INDENT "at: %s::%s() (%s:%d)\n"
+
+ // The file and line keys are for consumers that are able
+ // to read more granular location info.
+ YAML_INDENT "file: %s\n"
+ YAML_INDENT "line: %d\n",
+
+ QTestResult::currentTestObjectName(),
+ QTestResult::currentTestFunction(),
+ file, line, file, line
+ );
+ outputString(location.data());
+ }
+
+ outputString(YAML_INDENT "...\n");
+ }
+
+ m_wasExpectedFail = type == XFail;
+}
+
+void QTapTestLogger::addMessage(MessageTypes type, const QString &message,
+ const char *file, int line)
+{
+ Q_UNUSED(file);
+ Q_UNUSED(line);
+
+ if (type == Skip) {
+ QTestCharBuffer directive;
+ QTest::qt_asprintf(&directive, " # SKIP %s", message.toUtf8().constData());
+ outputTestLine(/* ok = */ true, QTestLog::totalCount(), directive);
+ return;
+ }
+
+ QTestCharBuffer diagnostics;
+ QTest::qt_asprintf(&diagnostics, "# %s\n", qPrintable(message));
+ outputString(diagnostics.data());
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/testlib/qtaptestlogger_p.h b/src/testlib/qtaptestlogger_p.h
new file mode 100644
index 0000000000..b51343e4fe
--- /dev/null
+++ b/src/testlib/qtaptestlogger_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 QTAPTESTLOGGER_P_H
+#define QTAPTESTLOGGER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtTest/private/qabstracttestlogger_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QTapTestLogger : public QAbstractTestLogger
+{
+public:
+ QTapTestLogger(const char *filename);
+ ~QTapTestLogger();
+
+ void startLogging() override;
+ void stopLogging() override;
+
+ void enterTestFunction(const char *) override;
+ void leaveTestFunction() override {}
+
+ void enterTestData(QTestData *data) override;
+
+ void addIncident(IncidentTypes type, const char *description,
+ const char *file = 0, int line = 0) override;
+ void addMessage(MessageTypes type, const QString &message,
+ const char *file = 0, int line = 0) override;
+
+ void addBenchmarkResult(const QBenchmarkResult &) override {};
+private:
+ void outputTestLine(bool ok, int testNumber, QTestCharBuffer &directive);
+ bool m_wasExpectedFail;
+};
+
+QT_END_NAMESPACE
+
+#endif // QTAPTESTLOGGER_P_H
diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h
index 5517b8fd73..2578037946 100644
--- a/src/testlib/qtest.h
+++ b/src/testlib/qtest.h
@@ -59,6 +59,8 @@
#include <QtCore/qsize.h>
#include <QtCore/qrect.h>
+#include <memory>
+
QT_BEGIN_NAMESPACE
@@ -215,6 +217,25 @@ inline char *toString(const std::pair<T1, T2> &pair)
return toString(QString::asprintf("std::pair(%s,%s)", first.data(), second.data()));
}
+template <typename Tuple, int... I>
+inline char *toString(const Tuple & tuple, QtPrivate::IndexesList<I...>) {
+ using UP = std::unique_ptr<char[]>;
+ // Generate a table of N + 1 elements where N is the number of
+ // elements in the tuple.
+ // The last element is needed to support the empty tuple use case.
+ const UP data[] = {
+ UP(toString(std::get<I>(tuple)))..., UP{}
+ };
+ return formatString("std::tuple(", ")", sizeof...(I), data[I].get()...);
+}
+
+template <class... Types>
+inline char *toString(const std::tuple<Types...> &tuple)
+{
+ static const std::size_t params_count = sizeof...(Types);
+ return toString(tuple, typename QtPrivate::Indexes<params_count>::Value());
+}
+
inline char *toString(std::nullptr_t)
{
return toString(QLatin1String("nullptr"));
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index f5668c274e..32facaf12b 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -60,6 +60,8 @@
#include <QtCore/qwaitcondition.h>
#include <QtCore/qmutex.h>
+#include <QtCore/qtestsupport_core.h>
+
#include <QtTest/private/qtestlog_p.h>
#include <QtTest/private/qtesttable_p.h>
#include <QtTest/qtestdata.h>
@@ -85,7 +87,6 @@
#if defined(Q_OS_LINUX)
#include <sys/types.h>
-#include <unistd.h>
#include <fcntl.h>
#endif
@@ -99,6 +100,7 @@
#include <errno.h>
#include <signal.h>
#include <time.h>
+#include <unistd.h>
# if !defined(Q_OS_INTEGRITY)
# include <sys/resource.h>
# endif
@@ -344,7 +346,9 @@ namespace QTest
static int keyDelay = -1;
static int mouseDelay = -1;
static int eventDelay = -1;
+#if QT_CONFIG(thread)
static int timeout = -1;
+#endif
static bool noCrashHandler = false;
/*! \internal
@@ -395,7 +399,7 @@ int Q_TESTLIB_EXPORT defaultKeyDelay()
}
return keyDelay;
}
-
+#if QT_CONFIG(thread)
static int defaultTimeout()
{
if (timeout == -1) {
@@ -407,6 +411,7 @@ static int defaultTimeout()
}
return timeout;
}
+#endif
Q_TESTLIB_EXPORT bool printAvailableFunctions = false;
Q_TESTLIB_EXPORT QStringList testFunctions;
@@ -526,6 +531,7 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml)
" xml : XML document\n"
" lightxml : A stream of XML tags\n"
" teamcity : TeamCity format\n"
+ " tap : Test Anything Protocol\n"
"\n"
" *** Multiple loggers can be specified, but at most one can log to stdout.\n"
"\n"
@@ -537,6 +543,7 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml)
" -xml : Output results as XML document\n"
" -lightxml : Output results as stream of XML tags\n"
" -teamcity : Output results in TeamCity format\n"
+ " -tap : Output results in Test Anything Protocol format\n"
"\n"
" *** If no output file is specified, stdout is assumed.\n"
" *** If no output format is specified, -txt is assumed.\n"
@@ -624,6 +631,8 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml)
logFormat = QTestLog::LightXML;
} else if (strcmp(argv[i], "-teamcity") == 0) {
logFormat = QTestLog::TeamCity;
+ } else if (strcmp(argv[i], "-tap") == 0) {
+ logFormat = QTestLog::TAP;
} else if (strcmp(argv[i], "-silent") == 0) {
QTestLog::setVerboseLevel(-1);
} else if (strcmp(argv[i], "-v1") == 0) {
@@ -658,8 +667,10 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml)
logFormat = QTestLog::XunitXML;
else if (strcmp(format, "teamcity") == 0)
logFormat = QTestLog::TeamCity;
+ else if (strcmp(format, "tap") == 0)
+ logFormat = QTestLog::TAP;
else {
- fprintf(stderr, "output format must be one of txt, csv, lightxml, xml, teamcity or xunitxml\n");
+ fprintf(stderr, "output format must be one of txt, csv, lightxml, xml, tap, teamcity or xunitxml\n");
exit(1);
}
if (strcmp(filename, "-") == 0 && QTestLog::loggerUsingStdout()) {
@@ -967,6 +978,8 @@ void TestMethods::invokeTestOnData(int index) const
}
}
+#if QT_CONFIG(thread)
+
class WatchDog : public QThread
{
public:
@@ -1018,6 +1031,17 @@ private:
QWaitCondition waitCondition;
};
+#else // !QT_CONFIG(thread)
+
+class WatchDog : public QObject
+{
+public:
+ void beginTest() {};
+ void testFinished() {};
+};
+
+#endif
+
/*!
\internal
@@ -1141,6 +1165,31 @@ void *fetchData(QTestData *data, const char *tagName, int typeId)
}
/*!
+ * \internal
+ */
+char *formatString(const char *prefix, const char *suffix, size_t numArguments, ...)
+{
+ va_list ap;
+ va_start(ap, numArguments);
+
+ QByteArray arguments;
+ arguments += prefix;
+
+ if (numArguments > 0) {
+ arguments += va_arg(ap, const char *);
+
+ for (size_t i = 1; i < numArguments; ++i) {
+ arguments += ", ";
+ arguments += va_arg(ap, const char *);
+ }
+ }
+
+ va_end(ap);
+ arguments += suffix;
+ return qstrdup(arguments.constData());
+}
+
+/*!
\fn char* QTest::toHexRepresentation(const char *ba, int length)
Returns a pointer to a string that is the string \a ba represented
@@ -1439,8 +1488,13 @@ void FatalSignalHandler::signal(int signum)
{
const int msecsFunctionTime = qRound(QTestLog::msecsFunctionTime());
const int msecsTotalTime = qRound(QTestLog::msecsTotalTime());
- if (signum != SIGINT)
+ if (signum != SIGINT) {
stackTrace();
+ if (qEnvironmentVariableIsSet("QTEST_PAUSE_ON_CRASH")) {
+ fprintf(stderr, "Pausing process %d for debugging\n", getpid());
+ raise(SIGSTOP);
+ }
+ }
qFatal("Received signal %d\n"
" Function time: %dms Total time: %dms",
signum, msecsFunctionTime, msecsTotalTime);
@@ -2380,16 +2434,9 @@ bool QTest::currentTestFailed()
*/
void QTest::qSleep(int ms)
{
+ // ### Qt 6, move to QtCore or remove altogether
QTEST_ASSERT(ms > 0);
-
-#if defined(Q_OS_WINRT)
- WaitForSingleObjectEx(GetCurrentThread(), ms, true);
-#elif defined(Q_OS_WIN)
- Sleep(uint(ms));
-#else
- struct timespec ts = { time_t(ms / 1000), (ms % 1000) * 1000 * 1000 };
- nanosleep(&ts, NULL);
-#endif
+ QTestPrivate::qSleep(ms);
}
/*! \internal
diff --git a/src/testlib/qtestcase.h b/src/testlib/qtestcase.h
index 54669c11de..f6891dc941 100644
--- a/src/testlib/qtestcase.h
+++ b/src/testlib/qtestcase.h
@@ -253,6 +253,22 @@ namespace QTest
return nullptr;
}
+ template<typename F> // Output QFlags of registered enumerations
+ inline typename std::enable_if<QtPrivate::IsQEnumHelper<F>::Value, char*>::type toString(QFlags<F> f)
+ {
+ const QMetaEnum me = QMetaEnum::fromType<F>();
+ return qstrdup(me.valueToKeys(int(f)).constData());
+ }
+
+ template <typename F> // Fallback: Output hex value
+ inline typename std::enable_if<!QtPrivate::IsQEnumHelper<F>::Value, char*>::type toString(QFlags<F> f)
+ {
+ const size_t space = 3 + 2 * sizeof(unsigned); // 2 for 0x, two hex digits per byte, 1 for '\0'
+ char *msg = new char[space];
+ qsnprintf(msg, space, "0x%x", unsigned(f));
+ return msg;
+ }
+
} // namespace Internal
template<typename T>
@@ -267,6 +283,9 @@ namespace QTest
template <typename T1, typename T2>
inline char *toString(const std::pair<T1, T2> &pair);
+ template <class... Types>
+ inline char *toString(const std::tuple<Types...> &tuple);
+
Q_TESTLIB_EXPORT char *toHexRepresentation(const char *ba, int length);
Q_TESTLIB_EXPORT char *toPrettyCString(const char *unicode, int length);
Q_TESTLIB_EXPORT char *toPrettyUnicode(QStringView string);
@@ -372,6 +391,8 @@ namespace QTest
Q_TESTLIB_EXPORT bool compare_string_helper(const char *t1, const char *t2, const char *actual,
const char *expected, const char *file, int line);
+ Q_TESTLIB_EXPORT char *formatString(const char *prefix, const char *suffix, size_t numArguments, ...);
+
#ifndef Q_QDOC
QTEST_COMPARE_DECL(short)
QTEST_COMPARE_DECL(ushort)
diff --git a/src/testlib/qtestcase.qdoc b/src/testlib/qtestcase.qdoc
index 9a3c770e31..ad9776f7ec 100644
--- a/src/testlib/qtestcase.qdoc
+++ b/src/testlib/qtestcase.qdoc
@@ -1112,105 +1112,6 @@
Returns a textual representation of size policy \a sp.
*/
-/*! \fn void QTest::qWait(int ms)
-
- Waits for \a ms milliseconds. While waiting, events will be processed and
- your test will stay responsive to user interface events or network communication.
-
- Example:
- \snippet code/src_qtestlib_qtestcase.cpp 17
-
- The code above will wait until the network server is responding for a
- maximum of about 12.5 seconds.
-
- \sa QTest::qSleep(), QSignalSpy::wait()
-*/
-
-/*! \fn template <typename Functor> bool QTest::qWaitFor(Functor predicate, int timeout)
-
- Waits for \a timeout milliseconds or until the \a predicate returns true.
-
- Returns \c true if the \a predicate returned true at any point, otherwise returns \c false.
-
- Example:
- \snippet code/src_qtestlib_qtestcase.cpp 30
-
- The code above will wait for the object to become ready, for a
- maximum of three seconds.
-
- \since 5.10
-*/
-
-/*! \fn bool QTest::qWaitForWindowExposed(QWindow *window, int timeout)
- \since 5.0
-
- Waits for \a timeout milliseconds or until the \a window is exposed.
- Returns \c true if \c window is exposed within \a timeout milliseconds, otherwise returns \c false.
-
- This is mainly useful for asynchronous systems like X11, where a window will be mapped to screen some
- time after being asked to show itself on the screen.
-
- Note that a window that is mapped to screen may still not be considered exposed if the window client
- area is completely covered by other windows, or if the window is otherwise not visible. This function
- will then time out when waiting for such a window.
-
- \sa QTest::qWaitForWindowActive(), QWindow::isExposed()
-*/
-
-/*! \fn bool QTest::qWaitForWindowActive(QWindow *window, int timeout)
- \since 5.0
-
- Waits for \a timeout milliseconds or until the \a window is active.
-
- Returns \c true if \c window is active within \a timeout milliseconds, otherwise returns \c false.
-
- \sa QTest::qWaitForWindowExposed(), QWindow::isActive()
-*/
-
-/*! \fn bool QTest::qWaitForWindowExposed(QWidget *widget, int timeout)
- \since 5.0
-
- Waits for \a timeout milliseconds or until the \a widget's window is exposed.
- Returns \c true if \c widget's window is exposed within \a timeout milliseconds, otherwise returns \c false.
-
- This is mainly useful for asynchronous systems like X11, where a window will be mapped to screen some
- time after being asked to show itself on the screen.
-
- Note that a window that is mapped to screen may still not be considered exposed if the window client
- area is completely covered by other windows, or if the window is otherwise not visible. This function
- will then time out when waiting for such a window.
-
- A specific configuration where this happens is when using QGLWidget as a viewport widget on macOS:
- The viewport widget gets the expose event, not the parent widget.
-
- \sa QTest::qWaitForWindowActive()
-*/
-
-/*! \fn bool QTest::qWaitForWindowActive(QWidget *widget, int timeout)
- \since 5.0
-
- Waits for \a timeout milliseconds or until the \a widget's window is active.
-
- Returns \c true if \c widget's window is active within \a timeout milliseconds, otherwise returns \c false.
-
- \sa QTest::qWaitForWindowExposed(), QWidget::isActiveWindow()
-*/
-
-/*! \fn bool QTest::qWaitForWindowShown(QWidget *widget, int timeout)
- \since 5.0
- \deprecated
-
- Waits for \a timeout milliseconds or until the \a widget's window is exposed.
- Returns \c true if \c widget's window is exposed within \a timeout milliseconds, otherwise returns \c false.
-
- This function does the same as qWaitForWindowExposed().
-
- Example:
- \snippet code/src_qtestlib_qtestcase.cpp 24
-
- \sa QTest::qWaitForWindowActive(), QTest::qWaitForWindowExposed()
-*/
-
/*!
\fn QTouchDevice *QTest::createTouchDevice(QTouchDevice::DeviceType devType = QTouchDevice::TouchScreen)
\since 5.8
diff --git a/src/testlib/qtesteventloop.h b/src/testlib/qtesteventloop.h
index 19ad22565e..a77b47cd7f 100644
--- a/src/testlib/qtesteventloop.h
+++ b/src/testlib/qtesteventloop.h
@@ -83,7 +83,7 @@ protected:
inline void timerEvent(QTimerEvent *e) override;
private:
- bool inLoop;
+ Q_DECL_UNUSED_MEMBER bool inLoop; // ### Qt 6: remove
bool _timeout;
int timerId;
@@ -96,7 +96,6 @@ inline void QTestEventLoop::enterLoopMSecs(int ms)
QEventLoop l;
- inLoop = true;
_timeout = false;
timerId = startTimer(ms);
@@ -120,8 +119,6 @@ inline void QTestEventLoop::exitLoop()
if (loop)
loop->exit();
-
- inLoop = false;
}
inline void QTestEventLoop::timerEvent(QTimerEvent *e)
diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp
index 6260b9e3fd..1268730cc6 100644
--- a/src/testlib/qtestlog.cpp
+++ b/src/testlib/qtestlog.cpp
@@ -47,10 +47,15 @@
#include <QtTest/private/qxunittestlogger_p.h>
#include <QtTest/private/qxmltestlogger_p.h>
#include <QtTest/private/qteamcitylogger_p.h>
+#include <QtTest/private/qtaptestlogger_p.h>
#if defined(HAVE_XCTEST)
#include <QtTest/private/qxctestlogger_p.h>
#endif
+#if defined(Q_OS_DARWIN)
+#include <QtTest/private/qappletestlogger_p.h>
+#endif
+
#include <QtCore/qatomic.h>
#include <QtCore/qbytearray.h>
#include <QtCore/QElapsedTimer>
@@ -211,6 +216,11 @@ namespace QTest {
FOREACH_LOGGER(logger->leaveTestFunction());
}
+ static void enterTestData(QTestData *data)
+ {
+ FOREACH_LOGGER(logger->enterTestData(data));
+ }
+
static void addIncident(QAbstractTestLogger::IncidentTypes type, const char *description,
const char *file = 0, int line = 0)
{
@@ -339,6 +349,12 @@ void QTestLog::enterTestFunction(const char* function)
QTest::TestLoggers::enterTestFunction(function);
}
+void QTestLog::enterTestData(QTestData *data)
+{
+ QTEST_ASSERT(data);
+ QTest::TestLoggers::enterTestData(data);
+}
+
int QTestLog::unhandledIgnoreMessages()
{
int i = 0;
@@ -498,12 +514,24 @@ void QTestLog::addLogger(LogMode mode, const char *filename)
case QTestLog::TeamCity:
logger = new QTeamCityLogger(filename);
break;
+ case QTestLog::TAP:
+ logger = new QTapTestLogger(filename);
+ break;
#if defined(HAVE_XCTEST)
case QTestLog::XCTest:
logger = new QXcodeTestLogger;
break;
#endif
}
+
+#if defined(QT_USE_APPLE_UNIFIED_LOGGING)
+ // Logger that also feeds messages to AUL. It needs to wrap the existing
+ // logger, as it needs to be able to short circuit the existing logger
+ // in case AUL prints to stderr.
+ if (QAppleTestLogger::debugLoggingEnabled())
+ logger = new QAppleTestLogger(logger);
+#endif
+
QTEST_ASSERT(logger);
QTest::TestLoggers::addLogger(logger);
}
@@ -591,6 +619,11 @@ int QTestLog::blacklistCount()
return QTest::blacklists;
}
+int QTestLog::totalCount()
+{
+ return passCount() + failCount() + skipCount() + blacklistCount();
+}
+
void QTestLog::resetCounters()
{
QTest::passes = 0;
diff --git a/src/testlib/qtestlog_p.h b/src/testlib/qtestlog_p.h
index 3d28795188..600c078ce2 100644
--- a/src/testlib/qtestlog_p.h
+++ b/src/testlib/qtestlog_p.h
@@ -57,12 +57,13 @@ QT_BEGIN_NAMESPACE
class QBenchmarkResult;
class QRegularExpression;
+class QTestData;
class Q_TESTLIB_EXPORT QTestLog
{
public:
enum LogMode {
- Plain = 0, XML, LightXML, XunitXML, CSV, TeamCity,
+ Plain = 0, XML, LightXML, XunitXML, CSV, TeamCity, TAP,
#if defined(HAVE_XCTEST)
XCTest
#endif
@@ -71,6 +72,8 @@ public:
static void enterTestFunction(const char* function);
static void leaveTestFunction();
+ static void enterTestData(QTestData *data);
+
static void addPass(const char *msg);
static void addFail(const char *msg, const char *file, int line);
static void addXFail(const char *msg, const char *file, int line);
@@ -110,6 +113,7 @@ public:
static int failCount();
static int skipCount();
static int blacklistCount();
+ static int totalCount();
static void resetCounters();
diff --git a/src/testlib/qtestresult.cpp b/src/testlib/qtestresult.cpp
index 219190d5da..88e3407c90 100644
--- a/src/testlib/qtestresult.cpp
+++ b/src/testlib/qtestresult.cpp
@@ -110,6 +110,8 @@ void QTestResult::setCurrentTestData(QTestData *data)
{
QTest::currentTestData = data;
QTest::failed = false;
+ if (data)
+ QTestLog::enterTestData(data);
}
void QTestResult::setCurrentTestFunction(const char *func)
diff --git a/src/testlib/qtestsystem.h b/src/testlib/qtestsystem.h
index daa0d7aea0..7a73bbb5d2 100644
--- a/src/testlib/qtestsystem.h
+++ b/src/testlib/qtestsystem.h
@@ -41,113 +41,16 @@
#define QTESTSYSTEM_H
#include <QtTest/qtestcase.h>
-#include <QtCore/qcoreapplication.h>
-#include <QtCore/qdeadlinetimer.h>
-#ifdef QT_GUI_LIB
-# include <QtGui/QWindow>
-#endif
-#ifdef QT_WIDGETS_LIB
-# include <QtWidgets/QWidget>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-namespace QTest
-{
- template <typename Functor>
- Q_REQUIRED_RESULT static bool qWaitFor(Functor predicate, int timeout = 5000)
- {
- // We should not spin the event loop in case the predicate is already true,
- // otherwise we might send new events that invalidate the predicate.
- if (predicate())
- return true;
-
- // qWait() is expected to spin the event loop, even when called with a small
- // timeout like 1ms, so we we can't use a simple while-loop here based on
- // the deadline timer not having timed out. Use do-while instead.
-
- int remaining = timeout;
- QDeadlineTimer deadline(remaining, Qt::PreciseTimer);
-
- do {
- QCoreApplication::processEvents(QEventLoop::AllEvents, remaining);
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
-
- remaining = deadline.remainingTime();
- if (remaining > 0) {
- QTest::qSleep(qMin(10, remaining));
- remaining = deadline.remainingTime();
- }
-
- if (predicate())
- return true;
-
- remaining = deadline.remainingTime();
- } while (remaining > 0);
-
- return predicate(); // Last chance
- }
-
- Q_DECL_UNUSED inline static void qWait(int ms)
- {
- // Ideally this method would be implemented in terms of qWaitFor, with
- // a predicate that always returns false, but due to a compiler bug in
- // GCC 6 we can't do that.
-
- Q_ASSERT(QCoreApplication::instance());
-
- QDeadlineTimer timer(ms, Qt::PreciseTimer);
- int remaining = ms;
- do {
- QCoreApplication::processEvents(QEventLoop::AllEvents, remaining);
- QCoreApplication::sendPostedEvents(Q_NULLPTR, QEvent::DeferredDelete);
- remaining = timer.remainingTime();
- if (remaining <= 0)
- break;
- QTest::qSleep(qMin(10, remaining));
- remaining = timer.remainingTime();
- } while (remaining > 0);
- }
+#include <QtCore/qtestsupport_core.h>
#ifdef QT_GUI_LIB
- Q_REQUIRED_RESULT inline static bool qWaitForWindowActive(QWindow *window, int timeout = 5000)
- {
- return qWaitFor([&]() { return window->isActive(); }, timeout);
- }
-
- Q_REQUIRED_RESULT inline static bool qWaitForWindowExposed(QWindow *window, int timeout = 5000)
- {
- return qWaitFor([&]() { return window->isExposed(); }, timeout);
- }
+# include <QtGui/qtestsupport_gui.h>
#endif
-
#ifdef QT_WIDGETS_LIB
- Q_REQUIRED_RESULT inline static bool qWaitForWindowActive(QWidget *widget, int timeout = 5000)
- {
- if (QWindow *window = widget->window()->windowHandle())
- return qWaitForWindowActive(window, timeout);
- return false;
- }
-
- Q_REQUIRED_RESULT inline static bool qWaitForWindowExposed(QWidget *widget, int timeout = 5000)
- {
- if (QWindow *window = widget->window()->windowHandle())
- return qWaitForWindowExposed(window, timeout);
- return false;
- }
+# include <QtWidgets/qtestsupport_widgets.h>
#endif
-#if QT_DEPRECATED_SINCE(5, 0)
-# ifdef QT_WIDGETS_LIB
-
- QT_DEPRECATED Q_REQUIRED_RESULT inline static bool qWaitForWindowShown(QWidget *widget, int timeout = 5000)
- {
- return qWaitForWindowExposed(widget, timeout);
- }
-# endif // QT_WIDGETS_LIB
-#endif // QT_DEPRECATED_SINCE(5, 0)
-}
-
+QT_BEGIN_NAMESPACE
QT_END_NAMESPACE
#endif
diff --git a/src/testlib/qxctestlogger.mm b/src/testlib/qxctestlogger.mm
index 62fd73070f..9fa9da2fdd 100644
--- a/src/testlib/qxctestlogger.mm
+++ b/src/testlib/qxctestlogger.mm
@@ -200,7 +200,7 @@ private:
[autoreleasepool release];
}
-+ (id)defaultTestSuite
++ (QTestLibTests *)defaultTestSuite
{
return [[QtTestLibTests alloc] initWithName:@"QtTestLib"];
}
@@ -255,7 +255,7 @@ static XCTestSuiteRun *s_qtTestSuiteRun = 0;
@implementation QtTestLibTest
-- (id)initWithInvocation:(NSInvocation *)invocation
+- (instancetype)initWithInvocation:(NSInvocation *)invocation
{
if (self = [super initWithInvocation:invocation]) {
// The test object name and function name are used by XCTest after QtTestLib has
@@ -322,7 +322,7 @@ QXcodeTestLogger *QXcodeTestLogger::s_currentTestLogger = 0;
QXcodeTestLogger::QXcodeTestLogger()
: QAbstractTestLogger(0)
- , m_testRuns([[NSMutableArray arrayWithCapacity:2] retain])
+ , m_testRuns([[NSMutableArray<XCTestRun *> arrayWithCapacity:2] retain])
{
Q_ASSERT(!s_currentTestLogger);
@@ -383,11 +383,11 @@ static bool isTestFunctionInActiveScope(const char *function)
Q_ASSERT(activeScope == Selected);
- static NSArray *forcedTests = [@[ @"initTestCase", @"initTestCase_data", @"cleanupTestCase" ] retain];
+ static NSArray<NSString *> *forcedTests = [@[ @"initTestCase", @"initTestCase_data", @"cleanupTestCase" ] retain];
if ([forcedTests containsObject:[NSString stringWithUTF8String:function]])
return true;
- static NSArray *testsInScope = [[testScope componentsSeparatedByString:@","] retain];
+ static NSArray<NSString *> *testsInScope = [[testScope componentsSeparatedByString:@","] retain];
bool inScope = [testsInScope containsObject:[NSString stringWithFormat:@"%s/%s",
QTestResult::currentTestObjectName(), function]];
diff --git a/src/testlib/qxctestlogger_p.h b/src/testlib/qxctestlogger_p.h
index 1b641f18af..8baa5aa27f 100644
--- a/src/testlib/qxctestlogger_p.h
+++ b/src/testlib/qxctestlogger_p.h
@@ -90,7 +90,7 @@ private:
void pushTestRunForTest(XCTest *test, bool start);
XCTestRun *popTestRun();
- NSMutableArray *m_testRuns;
+ NSMutableArray<XCTestRun *> *m_testRuns;
static QXcodeTestLogger *s_currentTestLogger;
};
diff --git a/src/testlib/testlib.pro b/src/testlib/testlib.pro
index 06a6f8b8e5..46b61dac07 100644
--- a/src/testlib/testlib.pro
+++ b/src/testlib/testlib.pro
@@ -39,7 +39,8 @@ HEADERS = \
qtesttouch.h \
qtestblacklist_p.h \
qtesthelpers_p.h \
- qttestglobal.h
+ qttestglobal.h \
+ qtaptestlogger_p.h
SOURCES = \
qtestcase.cpp \
@@ -65,7 +66,8 @@ SOURCES = \
qtestmouse.cpp \
qtestxunitstreamer.cpp \
qxunittestlogger.cpp \
- qtestblacklist.cpp
+ qtestblacklist.cpp \
+ qtaptestlogger.cpp
qtConfig(itemmodeltester) {
HEADERS += \
@@ -84,6 +86,9 @@ embedded:QMAKE_CXXFLAGS += -fno-rtti
mac {
LIBS += -framework Security
+ SOURCES += qappletestlogger.cpp
+ HEADERS += qappletestlogger_p.h
+
macos {
HEADERS += qtestutil_macos_p.h
OBJECTIVE_SOURCES += qtestutil_macos.mm
diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp
index 57714fc687..3b78d2487f 100644
--- a/src/tools/androiddeployqt/main.cpp
+++ b/src/tools/androiddeployqt/main.cpp
@@ -95,6 +95,7 @@ struct Options
, generateAssetsFileList(true)
, build(true)
, gradle(false)
+ , auxMode(false)
, deploymentMechanism(Bundled)
, releasePackage(false)
, digestAlg(QLatin1String("SHA1"))
@@ -126,6 +127,7 @@ struct Options
bool generateAssetsFileList;
bool build;
bool gradle;
+ bool auxMode;
QTime timer;
// External tools
@@ -137,6 +139,7 @@ struct Options
// Build paths
QString qtInstallDirectory;
+ std::vector<QString> extraPrefixDirs;
QString androidSourceDirectory;
QString outputDirectory;
QString inputFileName;
@@ -431,6 +434,8 @@ Options parseOptions()
options.jarSigner = true;
} else if (argument.compare(QLatin1String("--no-generated-assets-cache"), Qt::CaseInsensitive) == 0) {
options.generateAssetsFileList = false;
+ } else if (argument.compare(QLatin1String("--aux-mode"), Qt::CaseInsensitive) == 0) {
+ options.auxMode = true;
}
}
@@ -516,6 +521,9 @@ void printHelp()
" --verbose: Prints out information during processing.\n"
" --no-generated-assets-cache: Do not pregenerate the entry list for\n"
" the assets file engine.\n"
+ " --aux-mode: Operate in auxiliary mode. This will only copy the\n"
+ " dependencies into the build directory and update the XML templates.\n"
+ " The project will not be built or installed.\n"
" --help: Displays this information.\n\n",
qPrintable(QCoreApplication::arguments().at(0))
);
@@ -730,6 +738,14 @@ bool readInputFile(Options *options)
}
{
+ const auto extraPrefixDirs = jsonObject.value(QLatin1String("extraPrefixDirs")).toArray();
+ options->extraPrefixDirs.reserve(extraPrefixDirs.size());
+ for (const auto &prefix : extraPrefixDirs) {
+ options->extraPrefixDirs.push_back(prefix.toString());
+ }
+ }
+
+ {
const QJsonValue androidSourcesDirectory = jsonObject.value(QStringLiteral("android-package-source-directory"));
if (!androidSourcesDirectory.isUndefined())
options->androidSourceDirectory = androidSourcesDirectory.toString();
@@ -1287,6 +1303,9 @@ bool updateAndroidManifest(Options &options)
}
}
+ options.localJars.removeDuplicates();
+ options.initClasses.removeDuplicates();
+
QHash<QString, QString> replacements;
replacements[QLatin1String("-- %%INSERT_APP_NAME%% --")] = QFileInfo(options.applicationBinary).baseName().mid(sizeof("lib") - 1);
replacements[QLatin1String("-- %%INSERT_APP_LIB_NAME%% --")] = QFileInfo(options.applicationBinary).baseName().mid(sizeof("lib") - 1);
@@ -1380,6 +1399,16 @@ bool updateAndroidFiles(Options &options)
return true;
}
+static QString absoluteFilePath(const Options *options, const QString &relativeFileName)
+{
+ for (const auto &prefix : options->extraPrefixDirs) {
+ const QString path = prefix + QLatin1Char('/') + relativeFileName;
+ if (QFile::exists(path))
+ return path;
+ }
+ return options->qtInstallDirectory + QLatin1Char('/') + relativeFileName;
+}
+
QList<QtDependency> findFilesRecursively(const Options &options, const QFileInfo &info, const QString &rootPath)
{
if (!info.exists())
@@ -1404,6 +1433,11 @@ QList<QtDependency> findFilesRecursively(const Options &options, const QFileInfo
QList<QtDependency> findFilesRecursively(const Options &options, const QString &fileName)
{
+ for (const auto &prefix : options.extraPrefixDirs) {
+ QFileInfo info(prefix + QLatin1Char('/') + fileName);
+ if (info.exists())
+ return findFilesRecursively(options, info, prefix + QLatin1Char('/'));
+ }
QFileInfo info(options.qtInstallDirectory + QLatin1Char('/') + fileName);
return findFilesRecursively(options, info, options.qtInstallDirectory + QLatin1Char('/'));
}
@@ -1413,7 +1447,7 @@ bool readAndroidDependencyXml(Options *options,
QSet<QString> *usedDependencies,
QSet<QString> *remainingDependencies)
{
- QString androidDependencyName = options->qtInstallDirectory + QString::fromLatin1("/lib/%1-android-dependencies.xml").arg(moduleName);
+ QString androidDependencyName = absoluteFilePath(options, QString::fromLatin1("/lib/%1-android-dependencies.xml").arg(moduleName));
QFile androidDependencyFile(androidDependencyName);
if (androidDependencyFile.exists()) {
@@ -1458,7 +1492,7 @@ bool readAndroidDependencyXml(Options *options,
int bundling = reader.attributes().value(QLatin1String("bundling")).toInt();
QString fileName = reader.attributes().value(QLatin1String("file")).toString();
if (bundling == (options->deploymentMechanism == Options::Bundled)) {
- QtDependency dependency(fileName, options->qtInstallDirectory + QLatin1Char('/') + fileName);
+ QtDependency dependency(fileName, absoluteFilePath(options, fileName));
if (!usedDependencies->contains(dependency.absolutePath)) {
options->qtDependencies.append(dependency);
usedDependencies->insert(dependency.absolutePath);
@@ -1545,7 +1579,7 @@ QStringList getQtLibsFromElf(const Options &options, const QString &fileName)
if (line.contains("(NEEDED)") && line.contains("Shared library:") ) {
const int pos = line.lastIndexOf('[') + 1;
QString libraryName = QLatin1String("lib/") + QString::fromLatin1(line.mid(pos, line.length() - pos - 2));
- if (QFile::exists(options.qtInstallDirectory + QLatin1Char('/') + libraryName)) {
+ if (QFile::exists(absoluteFilePath(&options, libraryName))) {
ret += libraryName;
}
@@ -1576,7 +1610,7 @@ bool readDependenciesFromElf(Options *options,
if (usedDependencies->contains(dependency))
continue;
- QString absoluteDependencyPath(options->qtInstallDirectory + QLatin1Char('/') + dependency);
+ QString absoluteDependencyPath = absoluteFilePath(options, dependency);
usedDependencies->insert(dependency);
if (!readDependenciesFromElf(options,
absoluteDependencyPath,
@@ -1763,11 +1797,9 @@ bool readDependencies(Options *options)
if (!readDependenciesFromElf(options, options->qtInstallDirectory + QLatin1String("/plugins/platforms/android/libqtforandroid.so"), &usedDependencies, &remainingDependencies))
return false;
- QString qtDir = options->qtInstallDirectory + QLatin1Char('/');
-
while (!remainingDependencies.isEmpty()) {
QSet<QString>::iterator start = remainingDependencies.begin();
- QString fileName = qtDir + *start;
+ QString fileName = absoluteFilePath(options, *start);
remainingDependencies.erase(start);
QStringList unmetDependencies;
@@ -1785,7 +1817,7 @@ bool readDependencies(Options *options)
QStringList::iterator it = options->localLibs.begin();
while (it != options->localLibs.end()) {
QStringList unmetDependencies;
- if (!goodToCopy(options, qtDir + *it, &unmetDependencies)) {
+ if (!goodToCopy(options, absoluteFilePath(options, *it), &unmetDependencies)) {
fprintf(stdout, "Skipping %s due to unmet dependencies: %s\n",
qPrintable(*it),
qPrintable(unmetDependencies.join(QLatin1Char(','))));
@@ -1922,7 +1954,7 @@ bool goodToCopy(const Options *options, const QString &file, QStringList *unmetD
bool ret = true;
const auto libs = getQtLibsFromElf(*options, file);
for (const QString &lib : libs) {
- if (!options->qtDependencies.contains(QtDependency(lib, options->qtInstallDirectory + QLatin1Char('/') + lib))) {
+ if (!options->qtDependencies.contains(QtDependency(lib, absoluteFilePath(options, lib)))) {
ret = false;
unmetDependencies->append(lib);
}
@@ -2801,6 +2833,22 @@ int main(int argc, char *argv[])
: "No"
);
+ if (options.auxMode) {
+ if (!readDependencies(&options))
+ return CannotReadDependencies;
+ if (!copyQtFiles(&options))
+ return CannotCopyQtFiles;
+ if (!copyAndroidExtraResources(options))
+ return CannotCopyAndroidExtraResources;
+ if (!stripLibraries(options))
+ return CannotStripLibraries;
+ if (!updateAndroidFiles(options))
+ return CannotUpdateAndroidFiles;
+ if (options.generateAssetsFileList && !generateAssetsFileList(options))
+ return CannotGenerateAssetsFileList;
+ return 0;
+ }
+
if (options.build) {
if (options.gradle)
cleanAndroidFiles(options);
diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro
index a45382106a..83e44ff9a4 100644
--- a/src/tools/bootstrap/bootstrap.pro
+++ b/src/tools/bootstrap/bootstrap.pro
@@ -2,7 +2,7 @@ option(host_build)
TARGET = QtBootstrap
QT =
-CONFIG += minimal_syncqt internal_module force_bootstrap
+CONFIG += minimal_syncqt internal_module force_bootstrap gc_binaries
MODULE_INCNAME = QtCore QtXml
MODULE_DEFINES = \
@@ -12,6 +12,7 @@ MODULE_DEFINES = \
QT_VERSION_PATCH=$$QT_PATCH_VERSION \
QT_BOOTSTRAPPED \
QT_NO_CAST_TO_ASCII
+MODULE_CONFIG = gc_binaries
DEFINES += \
$$MODULE_DEFINES \
@@ -24,6 +25,7 @@ SOURCES += \
../../corelib/codecs/qlatincodec.cpp \
../../corelib/codecs/qtextcodec.cpp \
../../corelib/codecs/qutfcodec.cpp \
+ ../../corelib/global/qendian.cpp \
../../corelib/global/qglobal.cpp \
../../corelib/global/qlogging.cpp \
../../corelib/global/qmalloc.cpp \
diff --git a/src/tools/moc/cbordevice.h b/src/tools/moc/cbordevice.h
new file mode 100644
index 0000000000..dbfc537dd2
--- /dev/null
+++ b/src/tools/moc/cbordevice.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CBORDEVICE_H
+#define CBORDEVICE_H
+
+#include <memory>
+#include <stdio.h>
+
+#define CBOR_API inline
+#define CBOR_PRIVATE_API inline
+#define CBOR_NO_PARSER_API 1
+#include <cbor.h>
+
+class CborDevice
+{
+public:
+ CborDevice(FILE *out) : out(out) {}
+
+ void nextItem(const char *comment = nullptr)
+ {
+ i = 0;
+ if (comment)
+ fprintf(out, "\n // %s", comment);
+ }
+
+ static CborError callback(void *self, const void *ptr, size_t len, CborEncoderAppendType t)
+ {
+ auto that = static_cast<CborDevice *>(self);
+ auto data = static_cast<const char *>(ptr);
+ if (t == CborEncoderAppendCborData) {
+ while (len--)
+ that->putByte(*data++);
+ } else {
+ while (len--)
+ that->putChar(*data++);
+ }
+ return CborNoError;
+ }
+
+private:
+ FILE *out;
+ int i = 0;
+
+ void putNewline()
+ {
+ if ((i++ % 8) == 0)
+ fputs("\n ", out);
+ }
+
+ void putByte(uint8_t c)
+ {
+ putNewline();
+ fprintf(out, " 0x%02x, ", c);
+ }
+
+ void putChar(char c)
+ {
+ putNewline();
+ if (uchar(c) < 0x20)
+ fprintf(out, " '\\x%x',", uint8_t(c));
+ else if (uchar(c) >= 0x7f)
+ fprintf(out, " uchar('\\x%x'),", uint8_t(c));
+ else if (c == '\'' || c == '\\')
+ fprintf(out, " '\\%c',", c);
+ else
+ fprintf(out, " '%c', ", c);
+ }
+};
+
+#endif // CBORDEVICE_H
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index d299cdad51..9fb980893f 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -2,6 +2,7 @@
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the tools applications of the Qt Toolkit.
@@ -28,6 +29,7 @@
****************************************************************************/
#include "generator.h"
+#include "cbordevice.h"
#include "outputrevision.h"
#include "utils.h"
#include <QtCore/qmetatype.h>
@@ -36,9 +38,13 @@
#include <QtCore/qjsonvalue.h>
#include <QtCore/qjsonarray.h>
#include <QtCore/qplugin.h>
+#include <QtCore/qstringview.h>
+
+#include <math.h>
#include <stdio.h>
#include <private/qmetaobject_p.h> //for the flags.
+#include <private/qplugin_p.h> //for the flags.
QT_BEGIN_NAMESPACE
@@ -74,7 +80,7 @@ QT_FOR_EACH_STATIC_TYPE(RETURN_METATYPENAME_STRING)
return 0;
}
-Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, const QHash<QByteArray, QByteArray> &knownQObjectClasses, const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile)
+Generator::Generator(ClassDef *classDef, const QVector<QByteArray> &metaTypes, const QHash<QByteArray, QByteArray> &knownQObjectClasses, const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile)
: out(outfile), cdef(classDef), metaTypes(metaTypes), knownQObjectClasses(knownQObjectClasses)
, knownGadgets(knownGadgets)
{
@@ -200,6 +206,7 @@ void Generator::generateCode()
if (cdef->enumDeclarations.contains(def.name)) {
enumList += def;
}
+ def.enumName = def.name;
QByteArray alias = cdef->flagAliases.value(def.name);
if (cdef->enumDeclarations.contains(alias)) {
def.name = alias;
@@ -369,7 +376,7 @@ void Generator::generateCode()
int enumsIndex = index;
for (int i = 0; i < cdef->enumList.count(); ++i)
- index += 4 + (cdef->enumList.at(i).values.count() * 2);
+ index += 5 + (cdef->enumList.at(i).values.count() * 2);
fprintf(out, " %4d, %4d, // constructors\n", isConstructible ? cdef->constructorList.count() : 0,
isConstructible ? index : 0);
@@ -454,7 +461,7 @@ void Generator::generateCode()
//
// Build extra array
//
- QList<QByteArray> extraList;
+ QVector<QByteArray> extraList;
QHash<QByteArray, QByteArray> knownExtraMetaObject = knownGadgets;
knownExtraMetaObject.unite(knownQObjectClasses);
@@ -523,29 +530,29 @@ void Generator::generateCode()
// Finally create and initialize the static meta object
//
if (isQt)
- fprintf(out, "QT_INIT_METAOBJECT const QMetaObject QObject::staticQtMetaObject = {\n");
+ fprintf(out, "QT_INIT_METAOBJECT const QMetaObject QObject::staticQtMetaObject = { {\n");
else
- fprintf(out, "QT_INIT_METAOBJECT const QMetaObject %s::staticMetaObject = {\n", cdef->qualified.constData());
+ fprintf(out, "QT_INIT_METAOBJECT const QMetaObject %s::staticMetaObject = { {\n", cdef->qualified.constData());
if (isQObject)
- fprintf(out, " { nullptr, ");
+ fprintf(out, " nullptr,\n");
else if (cdef->superclassList.size() && (!cdef->hasQGadget || knownGadgets.contains(purestSuperClass)))
- fprintf(out, " { &%s::staticMetaObject, ", purestSuperClass.constData());
+ fprintf(out, " &%s::staticMetaObject,\n", purestSuperClass.constData());
else
- fprintf(out, " { nullptr, ");
- fprintf(out, "qt_meta_stringdata_%s.data,\n"
- " qt_meta_data_%s, ", qualifiedClassNameIdentifier.constData(),
+ fprintf(out, " nullptr,\n");
+ fprintf(out, " qt_meta_stringdata_%s.data,\n"
+ " qt_meta_data_%s,\n", qualifiedClassNameIdentifier.constData(),
qualifiedClassNameIdentifier.constData());
if (hasStaticMetaCall)
- fprintf(out, " qt_static_metacall, ");
+ fprintf(out, " qt_static_metacall,\n");
else
- fprintf(out, " nullptr, ");
+ fprintf(out, " nullptr,\n");
if (extraList.isEmpty())
- fprintf(out, "nullptr, ");
+ fprintf(out, " nullptr,\n");
else
- fprintf(out, "qt_meta_extradata_%s, ", qualifiedClassNameIdentifier.constData());
- fprintf(out, "nullptr}\n};\n\n");
+ fprintf(out, " qt_meta_extradata_%s,\n", qualifiedClassNameIdentifier.constData());
+ fprintf(out, " nullptr\n} };\n\n");
if(isQt)
return;
@@ -887,6 +894,8 @@ void Generator::registerEnumStrings()
for (int i = 0; i < cdef->enumList.count(); ++i) {
const EnumDef &e = cdef->enumList.at(i);
strreg(e.name);
+ if (!e.enumName.isNull())
+ strreg(e.enumName);
for (int j = 0; j < e.values.count(); ++j)
strreg(e.values.at(j));
}
@@ -897,8 +906,8 @@ void Generator::generateEnums(int index)
if (cdef->enumDeclarations.isEmpty())
return;
- fprintf(out, "\n // enums: name, flags, count, data\n");
- index += 4 * cdef->enumList.count();
+ fprintf(out, "\n // enums: name, alias, flags, count, data\n");
+ index += 5 * cdef->enumList.count();
int i;
for (i = 0; i < cdef->enumList.count(); ++i) {
const EnumDef &e = cdef->enumList.at(i);
@@ -907,8 +916,9 @@ void Generator::generateEnums(int index)
flags |= EnumIsFlag;
if (e.isEnumClass)
flags |= EnumIsScoped;
- fprintf(out, " %4d, 0x%.1x, %4d, %4d,\n",
+ fprintf(out, " %4d, %4d, 0x%.1x, %4d, %4d,\n",
stridx(e.name),
+ e.enumName.isNull() ? stridx(e.name) : stridx(e.enumName),
flags,
e.values.count(),
index);
@@ -922,7 +932,7 @@ void Generator::generateEnums(int index)
const QByteArray &val = e.values.at(j);
QByteArray code = cdef->qualified.constData();
if (e.isEnumClass)
- code += "::" + e.name;
+ code += "::" + (e.enumName.isNull() ? e.name : e.enumName);
code += "::" + val;
fprintf(out, " %4d, uint(%s),\n",
stridx(val), code.constData());
@@ -1556,31 +1566,56 @@ void Generator::generateSignal(FunctionDef *def,int index)
fprintf(out, "}\n");
}
-static void writePluginMetaData(FILE *out, const QJsonObject &data)
+static CborError jsonValueToCbor(CborEncoder *parent, const QJsonValue &v);
+static CborError jsonObjectToCbor(CborEncoder *parent, const QJsonObject &o)
{
- const QJsonDocument doc(data);
+ auto it = o.constBegin();
+ auto end = o.constEnd();
+ CborEncoder map;
+ cbor_encoder_create_map(parent, &map, o.size());
+
+ for ( ; it != end; ++it) {
+ QByteArray key = it.key().toUtf8();
+ cbor_encode_text_string(&map, key.constData(), key.size());
+ jsonValueToCbor(&map, it.value());
+ }
+ return cbor_encoder_close_container(parent, &map);
+}
- fputs("\nQT_PLUGIN_METADATA_SECTION\n"
- "static const unsigned char qt_pluginMetaData[] = {\n"
- " 'Q', 'T', 'M', 'E', 'T', 'A', 'D', 'A', 'T', 'A', ' ', ' ',\n ", out);
-#if 0
- fprintf(out, "\"%s\";\n", doc.toJson().constData());
-#else
- const QByteArray binary = doc.toBinaryData();
- const int last = binary.size() - 1;
- for (int i = 0; i < last; ++i) {
- uchar c = (uchar)binary.at(i);
- if (c < 0x20 || c >= 0x7f)
- fprintf(out, " 0x%02x,", c);
- else if (c == '\'' || c == '\\')
- fprintf(out, " '\\%c',", c);
- else
- fprintf(out, " '%c', ", c);
- if (!((i + 1) % 8))
- fputs("\n ", out);
+static CborError jsonArrayToCbor(CborEncoder *parent, const QJsonArray &a)
+{
+ CborEncoder array;
+ cbor_encoder_create_array(parent, &array, a.size());
+ for (const QJsonValue &v : a)
+ jsonValueToCbor(&array, v);
+ return cbor_encoder_close_container(parent, &array);
+}
+
+static CborError jsonValueToCbor(CborEncoder *parent, const QJsonValue &v)
+{
+ switch (v.type()) {
+ case QJsonValue::Null:
+ case QJsonValue::Undefined:
+ return cbor_encode_null(parent);
+ case QJsonValue::Bool:
+ return cbor_encode_boolean(parent, v.toBool());
+ case QJsonValue::Array:
+ return jsonArrayToCbor(parent, v.toArray());
+ case QJsonValue::Object:
+ return jsonObjectToCbor(parent, v.toObject());
+ case QJsonValue::String: {
+ QByteArray s = v.toString().toUtf8();
+ return cbor_encode_text_string(parent, s.constData(), s.size());
}
- fprintf(out, " 0x%02x\n};\n", (uchar)binary.at(last));
-#endif
+ case QJsonValue::Double: {
+ double d = v.toDouble();
+ if (d == floor(d) && fabs(d) <= (Q_INT64_C(1) << std::numeric_limits<double>::digits))
+ return cbor_encode_int(parent, qint64(d));
+ return cbor_encode_double(parent, d);
+ }
+ }
+ Q_UNREACHABLE();
+ return CborUnknownError;
}
void Generator::generatePluginMetaData()
@@ -1588,32 +1623,48 @@ void Generator::generatePluginMetaData()
if (cdef->pluginData.iid.isEmpty())
return;
- // Write plugin meta data #ifdefed QT_NO_DEBUG with debug=false,
- // true, respectively.
+ fputs("\nQT_PLUGIN_METADATA_SECTION\n"
+ "static constexpr unsigned char qt_pluginMetaData[] = {\n"
+ " 'Q', 'T', 'M', 'E', 'T', 'A', 'D', 'A', 'T', 'A', ' ', '!',\n"
+ " // metadata version, Qt version, architectural requirements\n"
+ " 0, QT_VERSION_MAJOR, QT_VERSION_MINOR, qPluginArchRequirements(),", out);
- QJsonObject data;
- const QString debugKey = QStringLiteral("debug");
- data.insert(QStringLiteral("IID"), QLatin1String(cdef->pluginData.iid.constData()));
- data.insert(QStringLiteral("className"), QLatin1String(cdef->classname.constData()));
- data.insert(QStringLiteral("version"), (int)QT_VERSION);
- data.insert(debugKey, QJsonValue(false));
- data.insert(QStringLiteral("MetaData"), cdef->pluginData.metaData.object());
- // Add -M args from the command line:
- for (auto it = cdef->pluginData.metaArgs.cbegin(), end = cdef->pluginData.metaArgs.cend(); it != end; ++it)
- data.insert(it.key(), it.value());
+ CborDevice dev(out);
+ CborEncoder enc;
+ cbor_encoder_init_writer(&enc, CborDevice::callback, &dev);
- fputs("\nQT_PLUGIN_METADATA_SECTION const uint qt_section_alignment_dummy = 42;\n\n"
- "#ifdef QT_NO_DEBUG\n", out);
- writePluginMetaData(out, data);
+ CborEncoder map;
+ cbor_encoder_create_map(&enc, &map, CborIndefiniteLength);
- fputs("\n#else // QT_NO_DEBUG\n", out);
+ dev.nextItem("\"IID\"");
+ cbor_encode_int(&map, int(QtPluginMetaDataKeys::IID));
+ cbor_encode_text_string(&map, cdef->pluginData.iid.constData(), cdef->pluginData.iid.size());
- data.remove(debugKey);
- data.insert(debugKey, QJsonValue(true));
- writePluginMetaData(out, data);
+ dev.nextItem("\"className\"");
+ cbor_encode_int(&map, int(QtPluginMetaDataKeys::ClassName));
+ cbor_encode_text_string(&map, cdef->classname.constData(), cdef->classname.size());
- fputs("#endif // QT_NO_DEBUG\n\n", out);
+ QJsonObject o = cdef->pluginData.metaData.object();
+ if (!o.isEmpty()) {
+ dev.nextItem("\"MetaData\"");
+ cbor_encode_int(&map, int(QtPluginMetaDataKeys::MetaData));
+ jsonObjectToCbor(&map, o);
+ }
+
+ // Add -M args from the command line:
+ for (auto it = cdef->pluginData.metaArgs.cbegin(), end = cdef->pluginData.metaArgs.cend(); it != end; ++it) {
+ const QJsonArray &a = it.value();
+ QByteArray key = it.key().toUtf8();
+ dev.nextItem(QByteArray("command-line \"" + key + "\"").constData());
+ cbor_encode_text_string(&map, key.constData(), key.size());
+ jsonArrayToCbor(&map, a);
+ }
+
+ // Close the CBOR map manually
+ dev.nextItem();
+ cbor_encoder_close_container(&enc, &map);
+ fputs("\n};\n", out);
// 'Use' all namespaces.
int pos = cdef->qualified.indexOf("::");
@@ -1623,4 +1674,14 @@ void Generator::generatePluginMetaData()
cdef->qualified.constData(), cdef->classname.constData());
}
+QT_WARNING_DISABLE_GCC("-Wunused-function")
+QT_WARNING_DISABLE_CLANG("-Wunused-function")
+QT_WARNING_DISABLE_CLANG("-Wundefined-internal")
+QT_WARNING_DISABLE_MSVC(4334) // '<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)
+
+#define CBOR_ENCODER_WRITER_CONTROL 1
+#define CBOR_ENCODER_WRITE_FUNCTION CborDevice::callback
+
QT_END_NAMESPACE
+
+#include "cborencoder.c"
diff --git a/src/tools/moc/generator.h b/src/tools/moc/generator.h
index 8b80138302..134166580b 100644
--- a/src/tools/moc/generator.h
+++ b/src/tools/moc/generator.h
@@ -39,7 +39,7 @@ class Generator
ClassDef *cdef;
QVector<uint> meta_data;
public:
- Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, const QHash<QByteArray, QByteArray> &knownQObjectClasses, const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile = 0);
+ Generator(ClassDef *classDef, const QVector<QByteArray> &metaTypes, const QHash<QByteArray, QByteArray> &knownQObjectClasses, const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile = 0);
void generateCode();
private:
bool registerableMetaType(const QByteArray &propertyType);
@@ -64,9 +64,9 @@ private:
void strreg(const QByteArray &); // registers a string
int stridx(const QByteArray &); // returns a string's id
- QList<QByteArray> strings;
+ QVector<QByteArray> strings;
QByteArray purestSuperClass;
- QList<QByteArray> metaTypes;
+ QVector<QByteArray> metaTypes;
QHash<QByteArray, QByteArray> knownQObjectClasses;
QHash<QByteArray, QByteArray> knownGadgets;
};
diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h
index 5f8cdfcf2c..d98c73e1a0 100644
--- a/src/tools/moc/moc.h
+++ b/src/tools/moc/moc.h
@@ -64,7 +64,8 @@ Q_DECLARE_TYPEINFO(Type, Q_MOVABLE_TYPE);
struct EnumDef
{
QByteArray name;
- QList<QByteArray> values;
+ QByteArray enumName;
+ QVector<QByteArray> values;
bool isEnumClass; // c++11 enum class
EnumDef() : isEnumClass(false) {}
};
@@ -206,10 +207,10 @@ public:
bool noInclude;
bool mustIncludeQPluginH;
QByteArray includePath;
- QList<QByteArray> includeFiles;
+ QVector<QByteArray> includeFiles;
QVector<ClassDef> classList;
QMap<QByteArray, QByteArray> interface2IdMap;
- QList<QByteArray> metaTypes;
+ QVector<QByteArray> metaTypes;
// map from class name to fully qualified name
QHash<QByteArray, QByteArray> knownQObjectClasses;
QHash<QByteArray, QByteArray> knownGadgets;
diff --git a/src/tools/moc/moc.pri b/src/tools/moc/moc.pri
index b689a35478..90839a445b 100644
--- a/src/tools/moc/moc.pri
+++ b/src/tools/moc/moc.pri
@@ -1,5 +1,6 @@
-INCLUDEPATH += $$PWD
+INCLUDEPATH += $$PWD \
+ $$PWD/../../3rdparty/tinycbor/src
HEADERS = $$PWD/moc.h \
$$PWD/preprocessor.h \
@@ -8,7 +9,8 @@ HEADERS = $$PWD/moc.h \
$$PWD/token.h \
$$PWD/utils.h \
$$PWD/generator.h \
- $$PWD/outputrevision.h
+ $$PWD/outputrevision.h \
+ $$PWD/cbordevice.h
SOURCES = $$PWD/moc.cpp \
$$PWD/preprocessor.cpp \
$$PWD/generator.cpp \
diff --git a/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp b/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp
index c76983200e..2115a14adf 100644
--- a/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp
+++ b/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp
@@ -62,7 +62,7 @@ static const char docTypeHeader[] =
#define PROGRAMNAME "qdbuscpp2xml"
#define PROGRAMVERSION "0.2"
-#define PROGRAMCOPYRIGHT "Copyright (C) 2017 The Qt Company Ltd."
+#define PROGRAMCOPYRIGHT "Copyright (C) 2018 The Qt Company Ltd."
static QString outputFile;
static int flags;
diff --git a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp
index bbe738dadb..5b76502c94 100644
--- a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp
+++ b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp
@@ -46,7 +46,7 @@
#define PROGRAMNAME "qdbusxml2cpp"
#define PROGRAMVERSION "0.8"
-#define PROGRAMCOPYRIGHT "Copyright (C) 2017 The Qt Company Ltd."
+#define PROGRAMCOPYRIGHT "Copyright (C) 2018 The Qt Company Ltd."
#define ANNOTATION_NO_WAIT "org.freedesktop.DBus.Method.NoReply"
diff --git a/src/tools/rcc/main.cpp b/src/tools/rcc/main.cpp
index fba47b74c3..12f986b1e2 100644
--- a/src/tools/rcc/main.cpp
+++ b/src/tools/rcc/main.cpp
@@ -151,6 +151,10 @@ int runRcc(int argc, char *argv[])
QCommandLineOption listOption(QStringLiteral("list"), QStringLiteral("Only list .qrc file entries, do not generate code."));
parser.addOption(listOption);
+ QCommandLineOption mapOption(QStringLiteral("list-mapping"),
+ QStringLiteral("Only output a mapping of resource paths to file system paths defined in the .qrc file, do not generate code."));
+ parser.addOption(mapOption);
+
QCommandLineOption projectOption(QStringLiteral("project"), QStringLiteral("Output a resource file containing all files from the current directory."));
parser.addOption(projectOption);
@@ -207,6 +211,7 @@ int runRcc(int argc, char *argv[])
library.setVerbose(true);
const bool list = parser.isSet(listOption);
+ const bool map = parser.isSet(mapOption);
const bool projectRequested = parser.isSet(projectOption);
const QStringList filenamesIn = parser.positionalArguments();
@@ -242,7 +247,7 @@ int runRcc(int argc, char *argv[])
library.setInputFiles(filenamesIn);
- if (!library.readFiles(list, errorDevice))
+ if (!library.readFiles(list || map, errorDevice))
return 1;
QFile out;
@@ -294,6 +299,17 @@ int runRcc(int argc, char *argv[])
return 0;
}
+ if (map) {
+ const RCCResourceLibrary::ResourceDataFileMap data = library.resourceDataFileMap();
+ for (auto it = data.begin(), end = data.end(); it != end; ++it) {
+ out.write(qPrintable(it.key()));
+ out.write("\t");
+ out.write(qPrintable(QDir::cleanPath(it.value())));
+ out.write("\n");
+ }
+ return 0;
+ }
+
QFile temp;
if (!tempFilename.isEmpty()) {
temp.setFileName(tempFilename);
diff --git a/src/tools/rcc/rcc.cpp b/src/tools/rcc/rcc.cpp
index 4c7d095ca3..1a7cab01df 100644
--- a/src/tools/rcc/rcc.cpp
+++ b/src/tools/rcc/rcc.cpp
@@ -377,7 +377,7 @@ enum RCCXmlTag {
Q_DECLARE_TYPEINFO(RCCXmlTag, Q_PRIMITIVE_TYPE);
bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
- const QString &fname, QString currentPath, bool ignoreErrors)
+ const QString &fname, QString currentPath, bool listMode)
{
Q_ASSERT(m_errorDevice);
const QChar slash = QLatin1Char('/');
@@ -527,7 +527,7 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
m_failedResources.push_back(child.fileName());
}
}
- } else if (file.isFile()) {
+ } else if (listMode || file.isFile()) {
const bool arc =
addFile(alias,
RCCFileInfo(alias.section(slash, -1),
@@ -551,8 +551,6 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
const QString msg = QString::fromLatin1("RCC: Error in '%1': Cannot find file '%2'\n")
.arg(fname, fileName);
m_errorDevice->write(msg.toUtf8());
- if (ignoreErrors)
- continue;
return false;
}
}
@@ -564,8 +562,6 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
}
if (reader.hasError()) {
- if (ignoreErrors)
- return true;
int errorLine = reader.lineNumber();
int errorColumn = reader.columnNumber();
QString errorMessage = reader.errorString();
@@ -577,7 +573,7 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice,
if (m_root == 0) {
const QString msg = QString::fromLatin1("RCC: Warning: No resources in '%1'.\n").arg(fname);
m_errorDevice->write(msg.toUtf8());
- if (!ignoreErrors && m_format == Binary) {
+ if (!listMode && m_format == Binary) {
// create dummy entry, otherwise loading with QResource will crash
m_root = new RCCFileInfo(QString(), QFileInfo(),
QLocale::C, QLocale::AnyCountry, RCCFileInfo::Directory);
@@ -645,14 +641,14 @@ void RCCResourceLibrary::reset()
}
-bool RCCResourceLibrary::readFiles(bool ignoreErrors, QIODevice &errorDevice)
+bool RCCResourceLibrary::readFiles(bool listMode, QIODevice &errorDevice)
{
reset();
m_errorDevice = &errorDevice;
//read in data
if (m_verbose) {
- const QString msg = QString::fromLatin1("Processing %1 files [%2]\n")
- .arg(m_fileNames.size()).arg(static_cast<int>(ignoreErrors));
+ const QString msg = QString::fromLatin1("Processing %1 files [listMode=%2]\n")
+ .arg(m_fileNames.size()).arg(static_cast<int>(listMode));
m_errorDevice->write(msg.toUtf8());
}
for (int i = 0; i < m_fileNames.size(); ++i) {
@@ -680,7 +676,7 @@ bool RCCResourceLibrary::readFiles(bool ignoreErrors, QIODevice &errorDevice)
m_errorDevice->write(msg.toUtf8());
}
- if (!interpretResourceFile(&fileIn, fname, pwd, ignoreErrors))
+ if (!interpretResourceFile(&fileIn, fname, pwd, listMode))
return false;
}
return true;
diff --git a/src/tools/rcc/rcc.h b/src/tools/rcc/rcc.h
index 19e04e401d..36984cf38a 100644
--- a/src/tools/rcc/rcc.h
+++ b/src/tools/rcc/rcc.h
@@ -53,7 +53,7 @@ public:
bool output(QIODevice &outDevice, QIODevice &tempDevice, QIODevice &errorDevice);
- bool readFiles(bool ignoreErrors, QIODevice &errorDevice);
+ bool readFiles(bool listMode, QIODevice &errorDevice);
enum Format { Binary, C_Code, Pass1, Pass2 };
void setFormat(Format f) { m_format = f; }
@@ -109,7 +109,7 @@ private:
void reset();
bool addFile(const QString &alias, const RCCFileInfo &file);
bool interpretResourceFile(QIODevice *inputDevice, const QString &file,
- QString currentPath = QString(), bool ignoreErrors = false);
+ QString currentPath = QString(), bool listMode = false);
bool writeHeader();
bool writeDataBlobs();
bool writeDataNames();
diff --git a/src/tools/tracegen/etw.cpp b/src/tools/tracegen/etw.cpp
index 07f2d114b6..8c065f93c9 100644
--- a/src/tools/tracegen/etw.cpp
+++ b/src/tools/tracegen/etw.cpp
@@ -75,6 +75,9 @@ static void writeEtwMacro(QTextStream &stream, const Tracepoint::Field &field)
<< "TraceLoggingValue(" << name << ".width(), \"width\"), "
<< "TraceLoggingValue(" << name << ".height(), \"height\")";
return;
+ case Tracepoint::Field::Pointer:
+ stream << "TraceLoggingPointer(" << name << ", \"" << name << "\")";
+ return;
default:
break;
}
diff --git a/src/tools/tracegen/lttng.cpp b/src/tools/tracegen/lttng.cpp
index 6c0d8cc88b..5d41bf5f1f 100644
--- a/src/tools/tracegen/lttng.cpp
+++ b/src/tools/tracegen/lttng.cpp
@@ -69,6 +69,10 @@ static void writeCtfMacro(QTextStream &stream, const Tracepoint::Field &field)
case Tracepoint::Field::Integer:
stream << "ctf_integer(" << paramType << ", " << name << ", " << name << ")";
return;
+ case Tracepoint::Field::IntegerHex:
+ case Tracepoint::Field::Pointer:
+ stream << "ctf_integer_hex(" << paramType << ", " << name << ", " << name << ")";
+ return;
case Tracepoint::Field::Float:
stream << "ctf_float(" << paramType << ", " << name << ", " << name << ")";
return;
diff --git a/src/tools/tracegen/provider.cpp b/src/tools/tracegen/provider.cpp
index 00e105377e..a6523a2e3d 100644
--- a/src/tools/tracegen/provider.cpp
+++ b/src/tools/tracegen/provider.cpp
@@ -157,10 +157,13 @@ static Tracepoint::Field::BackendType backendType(QString rawType)
{ "signed_long_long_int", Tracepoint::Field::Integer },
{ "unsigned_long_long", Tracepoint::Field::Integer },
{ "char", Tracepoint::Field::Integer },
+ { "intptr_t", Tracepoint::Field::IntegerHex },
+ { "uintptr_t", Tracepoint::Field::IntegerHex },
+ { "std::intptr_t", Tracepoint::Field::IntegerHex },
+ { "std::uintptr_t", Tracepoint::Field::IntegerHex },
{ "float", Tracepoint::Field::Float },
{ "double", Tracepoint::Field::Float },
{ "long_double", Tracepoint::Field::Float },
- { "char_ptr", Tracepoint::Field::String },
{ "QString", Tracepoint::Field::QtString },
{ "QByteArray", Tracepoint::Field::QtByteArray },
{ "QUrl", Tracepoint::Field::QtUrl },
@@ -168,7 +171,6 @@ static Tracepoint::Field::BackendType backendType(QString rawType)
};
auto backendType = [](const QString &rawType) {
-
static const size_t tableSize = sizeof (typeTable) / sizeof (typeTable[0]);
for (size_t i = 0; i < tableSize; ++i) {
@@ -194,7 +196,13 @@ static Tracepoint::Field::BackendType backendType(QString rawType)
rawType = rawType.trimmed();
rawType.replace(QStringLiteral(" "), QStringLiteral("_"));
- return backendType(rawType.trimmed());
+ if (rawType == QLatin1String("char_ptr"))
+ return Tracepoint::Field::String;
+
+ if (rawType.endsWith(QLatin1String("_ptr")))
+ return Tracepoint::Field::Pointer;
+
+ return backendType(rawType);
}
static Tracepoint parseTracepoint(const QString &name, const QStringList &args,
@@ -264,35 +272,28 @@ Provider parseProvider(const QString &filename)
static const QRegExp tracedef(QStringLiteral("([A-Za-z][A-Za-z0-9_]*)\\((.*)\\)"));
- int lineNumber = 0;
-
Provider provider;
provider.name = QFileInfo(filename).baseName();
- for (;;) {
+ for (int lineNumber = 1; !s.atEnd(); ++lineNumber) {
QString line = s.readLine().trimmed();
- if (line.isNull())
- break;
-
- if (line.isEmpty() || line.startsWith(QStringLiteral("#"))) {
- ++lineNumber;
+ if (line.isEmpty() || line.startsWith(QLatin1Char('#')))
continue;
- }
if (tracedef.exactMatch(line)) {
const QString name = tracedef.cap(1);
- QStringList args = tracedef.cap(2).split(QStringLiteral(","), QString::SkipEmptyParts);
-
- if (args.at(0).isNull())
- args.clear();
+ const QString argsString = tracedef.cap(2);
+ const QStringList args = argsString.split(QLatin1Char(','),
+ QString::SkipEmptyParts);
provider.tracepoints << parseTracepoint(name, args, filename, lineNumber);
} else {
- panic("Syntax error whilre processing %s on line %d", qPrintable(filename), lineNumber);
+ panic("Syntax error while processing '%s' line %d:\n"
+ " '%s' does not look like a tracepoint definition",
+ qPrintable(filename), lineNumber,
+ qPrintable(line));
}
-
- ++lineNumber;
}
#ifdef TRACEGEN_DEBUG
diff --git a/src/tools/tracegen/provider.h b/src/tools/tracegen/provider.h
index d8cbd2662d..9771e62f4d 100644
--- a/src/tools/tracegen/provider.h
+++ b/src/tools/tracegen/provider.h
@@ -59,8 +59,10 @@ struct Tracepoint
Array,
Sequence,
Integer,
+ IntegerHex,
Float,
String,
+ Pointer,
QtString,
QtByteArray,
QtUrl,
diff --git a/src/tools/uic/cpp/cppwritedeclaration.cpp b/src/tools/uic/cpp/cppwritedeclaration.cpp
index 9e774ad07b..995b99b692 100644
--- a/src/tools/uic/cpp/cppwritedeclaration.cpp
+++ b/src/tools/uic/cpp/cppwritedeclaration.cpp
@@ -40,10 +40,11 @@
QT_BEGIN_NAMESPACE
namespace {
- void openNameSpaces(const QStringList &namespaceList, QTextStream &output) {
- for (auto it = namespaceList.begin(), end = namespaceList.end(); it != end; ++it) {
- if (!it->isEmpty())
- output << "namespace " << *it << " {\n";
+ void openNameSpaces(const QStringList &namespaceList, QTextStream &output)
+ {
+ for (const QString &n : namespaceList) {
+ if (!n.isEmpty())
+ output << "namespace " << n << " {\n";
}
}
@@ -103,13 +104,9 @@ void WriteDeclaration::acceptUI(DomUI *node)
<< "public:\n";
const QStringList connections = m_uic->databaseInfo()->connections();
- for (int i=0; i<connections.size(); ++i) {
- const QString connection = connections.at(i);
-
- if (connection == QLatin1String("(default)"))
- continue;
-
- m_output << m_option.indent << "QSqlDatabase " << connection << "Connection;\n";
+ for (const QString &connection : connections) {
+ if (connection != QLatin1String("(default)"))
+ m_output << m_option.indent << "QSqlDatabase " << connection << "Connection;\n";
}
TreeWalker::acceptWidget(node->elementWidget());
diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp
index 9ab5fd4eb0..4f6ac1eb97 100644
--- a/src/tools/uic/cpp/cppwriteinitialization.cpp
+++ b/src/tools/uic/cpp/cppwriteinitialization.cpp
@@ -475,21 +475,6 @@ WriteInitialization::WriteInitialization(Uic *uic) :
{
}
-QString WriteInitialization::writeString(const QString &s, const QString &indent) const
-{
- unsigned flags = 0;
- const QString ret = fixString(s, indent, &flags);
- if (flags & Utf8String)
- return QLatin1String("QString::fromUtf8(") + ret + QLatin1Char(')');
- // MSVC cannot concat L"foo" "bar" (C2308: concatenating mismatched strings),
- // use QLatin1String instead (all platforms to avoid cross-compiling issues).
- if (flags & MultiLineString)
- return QLatin1String("QLatin1String(") + ret + QLatin1Char(')');
- const QLatin1String stringWrapper = m_uic->option().stringLiteral ?
- QLatin1String("QStringLiteral(") : QLatin1String("QLatin1String(");
- return stringWrapper + ret + QLatin1Char(')');
-}
-
void WriteInitialization::acceptUI(DomUI *node)
{
m_actionGroupChain.push(0);
@@ -529,16 +514,14 @@ void WriteInitialization::acceptUI(DomUI *node)
continue;
const QString varConn = connection + QLatin1String("Connection");
- m_output << m_indent << varConn << " = QSqlDatabase::database(" << writeString(connection, m_dindent) << ");\n";
+ m_output << m_indent << varConn << " = QSqlDatabase::database(" << fixString(connection, m_dindent) << ");\n";
}
acceptWidget(node->elementWidget());
- if (m_buddies.size() > 0)
+ if (!m_buddies.empty())
openIfndef(m_output, QLatin1String(shortcutDefineC));
- for (int i=0; i<m_buddies.size(); ++i) {
- const Buddy &b = m_buddies.at(i);
-
+ for (const Buddy &b : qAsConst(m_buddies)) {
if (!m_registeredWidgets.contains(b.objName)) {
fprintf(stderr, "%s: Warning: Buddy assignment: '%s' is not a valid widget.\n",
qPrintable(m_option.messagePrefix()),
@@ -553,7 +536,7 @@ void WriteInitialization::acceptUI(DomUI *node)
m_output << m_indent << b.objName << "->setBuddy(" << b.buddy << ");\n";
}
- if (m_buddies.size() > 0)
+ if (!m_buddies.empty())
closeIfndef(m_output, QLatin1String(shortcutDefineC));
if (node->elementTabStops())
@@ -832,9 +815,7 @@ void WriteInitialization::acceptWidget(DomWidget *node)
m_layoutChain.pop();
const QStringList zOrder = node->elementZOrder();
- for (int i = 0; i < zOrder.size(); ++i) {
- const QString name = zOrder.at(i);
-
+ for (const QString &name : zOrder) {
if (!m_registeredWidgets.contains(name)) {
fprintf(stderr, "%s: Warning: Z-order assignment: '%s' is not a valid widget.\n",
qPrintable(m_option.messagePrefix()),
@@ -842,11 +823,8 @@ void WriteInitialization::acceptWidget(DomWidget *node)
continue;
}
- if (name.isEmpty()) {
- continue;
- }
-
- m_output << m_indent << name << "->raise();\n";
+ if (!name.isEmpty())
+ m_output << m_indent << name << "->raise();\n";
}
}
@@ -1141,7 +1119,7 @@ QString WriteInitialization::writeStringListProperty(const DomStringList *list)
str << '\n' << m_indent << " << " << trCall(values.at(i), comment);
} else {
for (int i = 0; i < values.size(); ++i)
- str << " << " << writeString(values.at(i), m_dindent);
+ str << " << QString::fromUtf8(" << fixString(values.at(i), m_dindent) << ')';
}
return propertyValue;
}
@@ -1156,8 +1134,8 @@ void WriteInitialization::writeProperties(const QString &varName,
if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QAxWidget"))) {
DomPropertyMap properties = propertyMap(lst);
if (DomProperty *p = properties.value(QLatin1String("control"))) {
- m_output << m_indent << varName << "->setControl("
- << writeString(toString(p->elementString()), m_dindent) << ");\n";
+ m_output << m_indent << varName << "->setControl(QString::fromUtf8("
+ << fixString(toString(p->elementString()), m_dindent) << "));\n";
}
}
@@ -1168,14 +1146,13 @@ void WriteInitialization::writeProperties(const QString &varName,
}
if (!(flags & WritePropertyIgnoreObjectName))
m_output << m_indent << indent << varName
- << "->setObjectName(" << writeString(varName, m_dindent) << ");\n";
+ << "->setObjectName(QString::fromUtf8(" << fixString(varName, m_dindent) << "));\n";
int leftMargin, topMargin, rightMargin, bottomMargin;
leftMargin = topMargin = rightMargin = bottomMargin = -1;
bool frameShadowEncountered = false;
- for (int i=0; i<lst.size(); ++i) {
- const DomProperty *p = lst.at(i);
+ for (const DomProperty *p : lst) {
if (!checkProperty(m_option.inputFile, p))
continue;
QString propertyName = p->attributeName();
@@ -1187,30 +1164,35 @@ void WriteInitialization::writeProperties(const QString &varName,
const DomRect *r = p->elementRect();
m_output << m_indent << varName << "->resize(" << r->elementWidth() << ", " << r->elementHeight() << ");\n";
continue;
- } else if (propertyName == QLatin1String("currentRow") // QListWidget::currentRow
- && m_uic->customWidgetsInfo()->extends(className, QLatin1String("QListWidget"))) {
+ }
+ if (propertyName == QLatin1String("currentRow") // QListWidget::currentRow
+ && m_uic->customWidgetsInfo()->extends(className, QLatin1String("QListWidget"))) {
m_delayedOut << m_indent << varName << "->setCurrentRow("
<< p->elementNumber() << ");\n";
continue;
- } else if (propertyName == QLatin1String("currentIndex") // set currentIndex later
- && (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QComboBox"))
- || m_uic->customWidgetsInfo()->extends(className, QLatin1String("QStackedWidget"))
- || m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTabWidget"))
- || m_uic->customWidgetsInfo()->extends(className, QLatin1String("QToolBox")))) {
+ }
+ if (propertyName == QLatin1String("currentIndex") // set currentIndex later
+ && (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QComboBox"))
+ || m_uic->customWidgetsInfo()->extends(className, QLatin1String("QStackedWidget"))
+ || m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTabWidget"))
+ || m_uic->customWidgetsInfo()->extends(className, QLatin1String("QToolBox")))) {
m_delayedOut << m_indent << varName << "->setCurrentIndex("
<< p->elementNumber() << ");\n";
continue;
- } else if (propertyName == QLatin1String("tabSpacing")
- && m_uic->customWidgetsInfo()->extends(className, QLatin1String("QToolBox"))) {
+ }
+ if (propertyName == QLatin1String("tabSpacing")
+ && m_uic->customWidgetsInfo()->extends(className, QLatin1String("QToolBox"))) {
m_delayedOut << m_indent << varName << "->layout()->setSpacing("
<< p->elementNumber() << ");\n";
continue;
- } else if (propertyName == QLatin1String("control") // ActiveQt support
- && m_uic->customWidgetsInfo()->extends(className, QLatin1String("QAxWidget"))) {
+ }
+ if (propertyName == QLatin1String("control") // ActiveQt support
+ && m_uic->customWidgetsInfo()->extends(className, QLatin1String("QAxWidget"))) {
// already done ;)
continue;
- } else if (propertyName == QLatin1String("default")
- && m_uic->customWidgetsInfo()->extends(className, QLatin1String("QPushButton"))) {
+ }
+ if (propertyName == QLatin1String("default")
+ && m_uic->customWidgetsInfo()->extends(className, QLatin1String("QPushButton"))) {
// QTBUG-44406: Setting of QPushButton::default needs to be delayed until the parent is set
delayProperty = true;
} else if (propertyName == QLatin1String("database")
@@ -1423,10 +1405,10 @@ void WriteInitialization::writeProperties(const QString &varName,
propertyValue += QLatin1Char(')');
break;
case DomProperty::Float:
- propertyValue = QString::number(p->elementFloat());
+ propertyValue = QString::number(p->elementFloat(), 'f', 8);
break;
case DomProperty::Double:
- propertyValue = QString::number(p->elementDouble());
+ propertyValue = QString::number(p->elementDouble(), 'f', 15);
break;
case DomProperty::Char: {
const DomChar *c = p->elementChar();
@@ -1467,8 +1449,8 @@ void WriteInitialization::writeProperties(const QString &varName,
case DomProperty::Url: {
const DomUrl* u = p->elementUrl();
- propertyValue = QString::fromLatin1("QUrl(%1)")
- .arg(writeString(u->elementString()->text(), m_dindent));
+ propertyValue = QString::fromLatin1("QUrl(QString::fromUtf8(%1))")
+ .arg(fixString(u->elementString()->text(), m_dindent));
break;
}
case DomProperty::Brush:
@@ -1572,8 +1554,8 @@ QString WriteInitialization::writeFontProperties(const DomFont *f)
m_output << m_indent << "QFont " << fontName << ";\n";
if (f->hasElementFamily() && !f->elementFamily().isEmpty()) {
- m_output << m_indent << fontName << ".setFamily(" << writeString(f->elementFamily(), m_dindent)
- << ");\n";
+ m_output << m_indent << fontName << ".setFamily(QString::fromUtf8("
+ << fixString(f->elementFamily(), m_dindent) << "));\n";
}
if (f->hasElementPointSize() && f->elementPointSize() > 0) {
m_output << m_indent << fontName << ".setPointSize(" << f->elementPointSize()
@@ -1616,27 +1598,98 @@ QString WriteInitialization::writeFontProperties(const DomFont *f)
}
// Post 4.4 write resource icon
-void WriteInitialization::writeResourceIcon(QTextStream &output,
- const QString &iconName,
- const QString &indent,
- const DomResourceIcon *i) const
-{
- if (i->hasElementNormalOff())
- output << indent << iconName << ".addFile(" << writeString(i->elementNormalOff()->text(), indent) << ", QSize(), QIcon::Normal, QIcon::Off);\n";
- if (i->hasElementNormalOn())
- output << indent << iconName << ".addFile(" << writeString(i->elementNormalOn()->text(), indent) << ", QSize(), QIcon::Normal, QIcon::On);\n";
- if (i->hasElementDisabledOff())
- output << indent << iconName << ".addFile(" << writeString(i->elementDisabledOff()->text(), indent) << ", QSize(), QIcon::Disabled, QIcon::Off);\n";
- if (i->hasElementDisabledOn())
- output << indent << iconName << ".addFile(" << writeString(i->elementDisabledOn()->text(), indent) << ", QSize(), QIcon::Disabled, QIcon::On);\n";
- if (i->hasElementActiveOff())
- output << indent << iconName << ".addFile(" << writeString(i->elementActiveOff()->text(), indent) << ", QSize(), QIcon::Active, QIcon::Off);\n";
- if (i->hasElementActiveOn())
- output << indent << iconName << ".addFile(" << writeString(i->elementActiveOn()->text(), indent) << ", QSize(), QIcon::Active, QIcon::On);\n";
- if (i->hasElementSelectedOff())
- output << indent << iconName << ".addFile(" << writeString(i->elementSelectedOff()->text(), indent) << ", QSize(), QIcon::Selected, QIcon::Off);\n";
- if (i->hasElementSelectedOn())
- output << indent << iconName << ".addFile(" << writeString(i->elementSelectedOn()->text(), indent) << ", QSize(), QIcon::Selected, QIcon::On);\n";
+static void writeResourceIcon(QTextStream &output,
+ const QString &iconName,
+ const QString &indent,
+ const DomResourceIcon *i)
+{
+ if (i->hasElementNormalOff()) {
+ output << indent << iconName << ".addFile(QString::fromUtf8("
+ << fixString(i->elementNormalOff()->text(), indent)
+ << "), QSize(), QIcon::Normal, QIcon::Off);\n";
+ }
+ if (i->hasElementNormalOn()) {
+ output << indent << iconName << ".addFile(QString::fromUtf8("
+ << fixString(i->elementNormalOn()->text(), indent)
+ << "), QSize(), QIcon::Normal, QIcon::On);\n";
+ }
+ if (i->hasElementDisabledOff()) {
+ output << indent << iconName << ".addFile(QString::fromUtf8("
+ << fixString(i->elementDisabledOff()->text(), indent)
+ << "), QSize(), QIcon::Disabled, QIcon::Off);\n";
+ }
+ if (i->hasElementDisabledOn()) {
+ output << indent << iconName << ".addFile(QString::fromUtf8("
+ << fixString(i->elementDisabledOn()->text(), indent)
+ << "), QSize(), QIcon::Disabled, QIcon::On);\n";
+ }
+ if (i->hasElementActiveOff()) {
+ output << indent << iconName << ".addFile(QString::fromUtf8("
+ << fixString(i->elementActiveOff()->text(), indent)
+ << "), QSize(), QIcon::Active, QIcon::Off);\n";
+ }
+ if (i->hasElementActiveOn()) {
+ output << indent << iconName << ".addFile(QString::fromUtf8("
+ << fixString(i->elementActiveOn()->text(), indent)
+ << "), QSize(), QIcon::Active, QIcon::On);\n";
+ }
+ if (i->hasElementSelectedOff()) {
+ output << indent << iconName << ".addFile(QString::fromUtf8("
+ << fixString(i->elementSelectedOff()->text(), indent)
+ << "), QSize(), QIcon::Selected, QIcon::Off);\n";
+ }
+ if (i->hasElementSelectedOn()) {
+ output << indent << iconName << ".addFile(QString::fromUtf8("
+ << fixString(i->elementSelectedOn()->text(), indent)
+ << "), QSize(), QIcon::Selected, QIcon::On);\n";
+ }
+}
+
+void WriteInitialization::writePixmapFunctionIcon(QTextStream &output,
+ const QString &iconName,
+ const QString &indent,
+ const DomResourceIcon *i) const
+{
+ if (i->hasElementNormalOff()) {
+ output << indent << iconName << ".addPixmap("
+ << pixCall(QLatin1String("QPixmap"), i->elementNormalOff()->text())
+ << ", QIcon::Normal, QIcon::Off);\n";
+ }
+ if (i->hasElementNormalOn()) {
+ output << indent << iconName << ".addPixmap("
+ << pixCall(QLatin1String("QPixmap"), i->elementNormalOn()->text())
+ << ", QIcon::Normal, QIcon::On);\n";
+ }
+ if (i->hasElementDisabledOff()) {
+ output << indent << iconName << ".addPixmap("
+ << pixCall(QLatin1String("QPixmap"), i->elementDisabledOff()->text())
+ << ", QIcon::Disabled, QIcon::Off);\n";
+ }
+ if (i->hasElementDisabledOn()) {
+ output << indent << iconName << ".addPixmap("
+ << pixCall(QLatin1String("QPixmap"), i->elementDisabledOn()->text())
+ << ", QIcon::Disabled, QIcon::On);\n";
+ }
+ if (i->hasElementActiveOff()) {
+ output << indent << iconName << ".addPixmap("
+ << pixCall(QLatin1String("QPixmap"), i->elementActiveOff()->text())
+ << ", QIcon::Active, QIcon::Off);\n";
+ }
+ if (i->hasElementActiveOn()) {
+ output << indent << iconName << ".addPixmap("
+ << pixCall(QLatin1String("QPixmap"), i->elementActiveOn()->text())
+ << ", QIcon::Active, QIcon::On);\n";
+ }
+ if (i->hasElementSelectedOff()) {
+ output << indent << iconName << ".addPixmap("
+ << pixCall(QLatin1String("QPixmap"), i->elementSelectedOff()->text())
+ << ", QIcon::Selected, QIcon::Off);\n";
+ }
+ if (i->hasElementSelectedOn()) {
+ output << indent << iconName << ".addPixmap("
+ << pixCall(QLatin1String("QPixmap"), i->elementSelectedOn()->text())
+ << ", QIcon::Selected, QIcon::On);\n";
+ }
}
QString WriteInitialization::writeIconProperties(const DomResourceIcon *i)
@@ -1655,10 +1708,13 @@ QString WriteInitialization::writeIconProperties(const DomResourceIcon *i)
if (i->attributeTheme().isEmpty()) {
// No theme: Write resource icon as is
m_output << m_indent << "QIcon " << iconName << ";\n";
- writeResourceIcon(m_output, iconName, m_indent, i);
+ if (m_uic->pixmapFunction().isEmpty())
+ writeResourceIcon(m_output, iconName, m_indent, i);
+ else
+ writePixmapFunctionIcon(m_output, iconName, m_indent, i);
} else {
// Theme: Generate code to check the theme and default to resource
- const QString themeIconName = writeString(i->attributeTheme(), QString());
+ const QString themeIconName = fixString(i->attributeTheme(), QString());
if (iconHasStatePixmaps(i)) {
// Theme + default state pixmaps:
// Generate code to check the theme and default to state pixmaps
@@ -1670,20 +1726,23 @@ QString WriteInitialization::writeIconProperties(const DomResourceIcon *i)
m_output << "QString ";
m_firstThemeIcon = false;
}
- m_output << themeNameStringVariableC << " = "
- << themeIconName << ";\n";
+ m_output << themeNameStringVariableC << " = QString::fromUtf8("
+ << themeIconName << ");\n";
m_output << m_indent << "if (QIcon::hasThemeIcon("
<< themeNameStringVariableC
<< ")) {\n"
<< m_dindent << iconName << " = QIcon::fromTheme(" << themeNameStringVariableC << ");\n"
<< m_indent << "} else {\n";
- writeResourceIcon(m_output, iconName, m_dindent, i);
+ if (m_uic->pixmapFunction().isEmpty())
+ writeResourceIcon(m_output, iconName, m_dindent, i);
+ else
+ writePixmapFunctionIcon(m_output, iconName, m_dindent, i);
m_output << m_indent << "}\n";
} else {
// Theme, but no state pixmaps: Construct from theme directly.
m_output << m_indent << "QIcon " << iconName
- << "(QIcon::fromTheme("
- << themeIconName << "));\n";
+ << "(QIcon::fromTheme(QString::fromUtf8("
+ << themeIconName << ")));\n";
} // Theme, but not state
} // >= 4.4
} else { // pre-4.4 legacy
@@ -1841,7 +1900,7 @@ void WriteInitialization::acceptTabStops(DomTabStops *tabStops)
const QStringList l = tabStops->elementTabStop();
for (int i=0; i<l.size(); ++i) {
- const QString name = l.at(i);
+ const QString &name = l.at(i);
if (!m_registeredWidgets.contains(name)) {
fprintf(stderr, "%s: Warning: Tab-stop assignment: '%s' is not a valid widget.\n",
@@ -1853,9 +1912,9 @@ void WriteInitialization::acceptTabStops(DomTabStops *tabStops)
if (i == 0) {
lastName = name;
continue;
- } else if (name.isEmpty() || lastName.isEmpty()) {
- continue;
}
+ if (name.isEmpty() || lastName.isEmpty())
+ continue;
m_output << m_indent << "QWidget::setTabOrder(" << lastName << ", " << name << ");\n";
@@ -2125,7 +2184,7 @@ void WriteInitialization::initializeTreeWidget(DomWidget *w)
if (!itemName.isNull())
m_output << m_indent << varName << "->setHeaderItem(" << itemName << ");\n";
- if (w->elementItem().size() == 0)
+ if (w->elementItem().empty())
return;
QString tempName = disableSorting(w, varName);
@@ -2167,9 +2226,8 @@ QList<WriteInitialization::Item *> WriteInitialization::initializeTreeWidgetItem
int col = -1;
const DomPropertyList properties = domItem->elementProperty();
- for (int j = 0; j < properties.size(); ++j) {
- DomProperty *p = properties.at(j);
- if (p->attributeName() == QLatin1String("text")) {
+ for (DomProperty *p : properties) {
+ if (p->attributeName() == QLatin1String("text")) {
if (!map.isEmpty()) {
addCommonInitializers(item, map, col);
map.clear();
@@ -2196,7 +2254,7 @@ void WriteInitialization::initializeTableWidget(DomWidget *w)
// columns
const auto &columns = w->elementColumn();
- if (columns.size() != 0) {
+ if (!columns.empty()) {
m_output << m_indent << "if (" << varName << "->columnCount() < " << columns.size() << ")\n"
<< m_dindent << varName << "->setColumnCount(" << columns.size() << ");\n";
}
@@ -2218,7 +2276,7 @@ void WriteInitialization::initializeTableWidget(DomWidget *w)
// rows
const auto &rows = w->elementRow();
- if (rows.size() != 0) {
+ if (!rows.isEmpty()) {
m_output << m_indent << "if (" << varName << "->rowCount() < " << rows.size() << ")\n"
<< m_dindent << varName << "->setRowCount(" << rows.size() << ");\n";
}
@@ -2242,8 +2300,7 @@ void WriteInitialization::initializeTableWidget(DomWidget *w)
const auto &items = w->elementItem();
- for (int i = 0; i < items.size(); ++i) {
- const DomItem *cell = items.at(i);
+ for (const DomItem *cell : items) {
if (cell->hasAttributeRow() && cell->hasAttributeColumn() && !cell->elementProperty().isEmpty()) {
const int r = cell->attributeRow();
const int c = cell->attributeColumn();
@@ -2323,7 +2380,10 @@ QString WriteInitialization::noTrCall(DomString *str, const QString &defaultStri
return QString();
if (str)
value = str->text();
- return writeString(value, m_dindent);
+ QString ret = QLatin1String("QString::fromUtf8(");
+ ret += fixString(value, m_dindent);
+ ret += QLatin1Char(')');
+ return ret;
}
QString WriteInitialization::autoTrCall(DomString *str, const QString &defaultString) const
@@ -2448,13 +2508,13 @@ QString WriteInitialization::Item::writeSetupUi(const QString &parent, Item::Emp
return QString();
bool generateMultiDirective = false;
- if (emptyItemPolicy == Item::ConstructItemOnly && m_children.size() == 0) {
+ if (emptyItemPolicy == Item::ConstructItemOnly && m_children.isEmpty()) {
if (m_setupUiData.policy == ItemData::DontGenerate) {
m_setupUiStream << m_indent << "new " << m_itemClassName << '(' << parent << ");\n";
- return QString();
- } else if (m_setupUiData.policy == ItemData::GenerateWithMultiDirective) {
- generateMultiDirective = true;
+ return QString();
}
+ if (m_setupUiData.policy == ItemData::GenerateWithMultiDirective)
+ generateMultiDirective = true;
}
if (generateMultiDirective)
diff --git a/src/tools/uic/cpp/cppwriteinitialization.h b/src/tools/uic/cpp/cppwriteinitialization.h
index 21116057d4..cce83bd677 100644
--- a/src/tools/uic/cpp/cppwriteinitialization.h
+++ b/src/tools/uic/cpp/cppwriteinitialization.h
@@ -139,8 +139,6 @@ struct WriteInitialization : public TreeWalker
private:
static QString domColor2QString(const DomColor *c);
- QString writeString(const QString &s, const QString &indent) const;
-
QString iconCall(const DomProperty *prop);
QString pixCall(const DomProperty *prop) const;
QString pixCall(const QString &type, const QString &text) const;
@@ -163,6 +161,7 @@ private:
// special initialization
//
class Item {
+ Q_DISABLE_COPY(Item)
public:
Item(const QString &itemClassName, const QString &indent, QTextStream &setupUiStream, QTextStream &retranslateUiStream, Driver *driver);
~Item();
@@ -178,15 +177,15 @@ private:
int setupUiCount() const { return m_setupUiData.setters.count(); }
int retranslateUiCount() const { return m_retranslateUiData.setters.count(); }
private:
- struct ItemData {
- ItemData() : policy(DontGenerate) {}
+ struct ItemData
+ {
QMultiMap<QString, QString> setters; // directive to setter
QSet<QString> directives;
enum TemporaryVariableGeneratorPolicy { // policies with priority, number describes the priority
DontGenerate = 1,
GenerateWithMultiDirective = 2,
Generate = 3
- } policy;
+ } policy = DontGenerate;
};
ItemData m_setupUiData;
ItemData m_retranslateUiData;
@@ -230,8 +229,9 @@ private:
private:
QString writeFontProperties(const DomFont *f);
- void writeResourceIcon(QTextStream &output, const QString &iconName, const QString &indent, const DomResourceIcon *i) const;
QString writeIconProperties(const DomResourceIcon *i);
+ void writePixmapFunctionIcon(QTextStream &output, const QString &iconName,
+ const QString &indent, const DomResourceIcon *i) const;
QString writeSizePolicy(const DomSizePolicy *sp);
QString writeBrushInitialization(const DomBrush *brush);
void addButtonGroup(const DomWidget *node, const QString &varName);
diff --git a/src/tools/uic/customwidgetsinfo.cpp b/src/tools/uic/customwidgetsinfo.cpp
index 6883b715ae..0ac0c2b6a3 100644
--- a/src/tools/uic/customwidgetsinfo.cpp
+++ b/src/tools/uic/customwidgetsinfo.cpp
@@ -33,9 +33,7 @@
QT_BEGIN_NAMESPACE
-CustomWidgetsInfo::CustomWidgetsInfo()
-{
-}
+CustomWidgetsInfo::CustomWidgetsInfo() = default;
void CustomWidgetsInfo::acceptUI(DomUI *node)
{
diff --git a/src/tools/uic/driver.cpp b/src/tools/uic/driver.cpp
index 72be667468..6b3a6f8f69 100644
--- a/src/tools/uic/driver.cpp
+++ b/src/tools/uic/driver.cpp
@@ -41,9 +41,7 @@ Driver::Driver()
m_output = &m_stdout;
}
-Driver::~Driver()
-{
-}
+Driver::~Driver() = default;
QString Driver::findOrInsertWidget(DomWidget *ui_widget)
{
diff --git a/src/tools/uic/driver.h b/src/tools/uic/driver.h
index 41c1572860..1563bdbd83 100644
--- a/src/tools/uic/driver.h
+++ b/src/tools/uic/driver.h
@@ -49,6 +49,7 @@ class DomButtonGroup;
class Driver
{
+ Q_DISABLE_COPY(Driver)
public:
Driver();
virtual ~Driver();
diff --git a/src/tools/uic/main.cpp b/src/tools/uic/main.cpp
index 46a1e66bcc..0e30bac28e 100644
--- a/src/tools/uic/main.cpp
+++ b/src/tools/uic/main.cpp
@@ -76,7 +76,7 @@ int runUic(int argc, char *argv[])
parser.addOption(noImplicitIncludesOption);
QCommandLineOption noStringLiteralOption(QStringList() << QStringLiteral("s") << QStringLiteral("no-stringliteral"));
- noStringLiteralOption.setDescription(QStringLiteral("Use QLatin1String instead of QStringLiteral in generated code."));
+ noStringLiteralOption.setDescription(QStringLiteral("Deprecated. The use of this option won't take any effect."));
parser.addOption(noStringLiteralOption);
QCommandLineOption postfixOption(QStringLiteral("postfix"));
@@ -111,13 +111,15 @@ int runUic(int argc, char *argv[])
driver.option().outputFile = parser.value(outputOption);
driver.option().headerProtection = !parser.isSet(noProtOption);
driver.option().implicitIncludes = !parser.isSet(noImplicitIncludesOption);
- driver.option().stringLiteral = !parser.isSet(noStringLiteralOption);
driver.option().idBased = parser.isSet(idBasedOption);
driver.option().postfix = parser.value(postfixOption);
driver.option().translateFunction = parser.value(translateOption);
driver.option().includeFile = parser.value(includeOption);
driver.option().generator = (parser.value(generatorOption).toLower() == QLatin1String("java")) ? Option::JavaGenerator : Option::CppGenerator;
+ if (parser.isSet(noStringLiteralOption))
+ fprintf(stderr, "The -s, --no-stringliteral option is deprecated and it won't take any effect.\n");
+
QString inputFile;
if (!parser.positionalArguments().isEmpty())
inputFile = parser.positionalArguments().at(0);
diff --git a/src/tools/uic/option.h b/src/tools/uic/option.h
index c7278393fb..a5b14abc5f 100644
--- a/src/tools/uic/option.h
+++ b/src/tools/uic/option.h
@@ -51,7 +51,6 @@ struct Option
unsigned int limitXPM_LineLength : 1;
unsigned int implicitIncludes: 1;
unsigned int idBased: 1;
- unsigned int stringLiteral: 1;
Generator generator;
QString inputFile;
@@ -77,7 +76,6 @@ struct Option
limitXPM_LineLength(0),
implicitIncludes(1),
idBased(0),
- stringLiteral(1),
generator(CppGenerator),
prefix(QLatin1String("Ui_"))
{ indent.fill(QLatin1Char(' '), 4); }
diff --git a/src/tools/uic/treewalker.h b/src/tools/uic/treewalker.h
index 78da17d628..43d4633d83 100644
--- a/src/tools/uic/treewalker.h
+++ b/src/tools/uic/treewalker.h
@@ -77,7 +77,7 @@ class DomButtonGroup;
struct TreeWalker
{
- inline virtual ~TreeWalker() {}
+ inline virtual ~TreeWalker() = default;
virtual void acceptUI(DomUI *ui);
virtual void acceptLayoutDefault(DomLayoutDefault *layoutDefault);
diff --git a/src/tools/uic/ui4.cpp b/src/tools/uic/ui4.cpp
index 7a1d755bb4..984ef36274 100644
--- a/src/tools/uic/ui4.cpp
+++ b/src/tools/uic/ui4.cpp
@@ -108,19 +108,19 @@ void DomUI::read(QXmlStreamReader &reader)
continue;
}
if (!tag.compare(QLatin1String("widget"), Qt::CaseInsensitive)) {
- DomWidget *v = new DomWidget();
+ auto *v = new DomWidget();
v->read(reader);
setElementWidget(v);
continue;
}
if (!tag.compare(QLatin1String("layoutdefault"), Qt::CaseInsensitive)) {
- DomLayoutDefault *v = new DomLayoutDefault();
+ auto *v = new DomLayoutDefault();
v->read(reader);
setElementLayoutDefault(v);
continue;
}
if (!tag.compare(QLatin1String("layoutfunction"), Qt::CaseInsensitive)) {
- DomLayoutFunction *v = new DomLayoutFunction();
+ auto *v = new DomLayoutFunction();
v->read(reader);
setElementLayoutFunction(v);
continue;
@@ -130,13 +130,13 @@ void DomUI::read(QXmlStreamReader &reader)
continue;
}
if (!tag.compare(QLatin1String("customwidgets"), Qt::CaseInsensitive)) {
- DomCustomWidgets *v = new DomCustomWidgets();
+ auto *v = new DomCustomWidgets();
v->read(reader);
setElementCustomWidgets(v);
continue;
}
if (!tag.compare(QLatin1String("tabstops"), Qt::CaseInsensitive)) {
- DomTabStops *v = new DomTabStops();
+ auto *v = new DomTabStops();
v->read(reader);
setElementTabStops(v);
continue;
@@ -147,37 +147,37 @@ void DomUI::read(QXmlStreamReader &reader)
continue;
}
if (!tag.compare(QLatin1String("includes"), Qt::CaseInsensitive)) {
- DomIncludes *v = new DomIncludes();
+ auto *v = new DomIncludes();
v->read(reader);
setElementIncludes(v);
continue;
}
if (!tag.compare(QLatin1String("resources"), Qt::CaseInsensitive)) {
- DomResources *v = new DomResources();
+ auto *v = new DomResources();
v->read(reader);
setElementResources(v);
continue;
}
if (!tag.compare(QLatin1String("connections"), Qt::CaseInsensitive)) {
- DomConnections *v = new DomConnections();
+ auto *v = new DomConnections();
v->read(reader);
setElementConnections(v);
continue;
}
if (!tag.compare(QLatin1String("designerdata"), Qt::CaseInsensitive)) {
- DomDesignerData *v = new DomDesignerData();
+ auto *v = new DomDesignerData();
v->read(reader);
setElementDesignerdata(v);
continue;
}
if (!tag.compare(QLatin1String("slots"), Qt::CaseInsensitive)) {
- DomSlots *v = new DomSlots();
+ auto *v = new DomSlots();
v->read(reader);
setElementSlots(v);
continue;
}
if (!tag.compare(QLatin1String("buttongroups"), Qt::CaseInsensitive)) {
- DomButtonGroups *v = new DomButtonGroups();
+ auto *v = new DomButtonGroups();
v->read(reader);
setElementButtonGroups(v);
continue;
@@ -293,7 +293,7 @@ void DomUI::setElementClass(const QString &a)
DomWidget *DomUI::takeElementWidget()
{
DomWidget *a = m_widget;
- m_widget = 0;
+ m_widget = nullptr;
m_children ^= Widget;
return a;
}
@@ -308,7 +308,7 @@ void DomUI::setElementWidget(DomWidget *a)
DomLayoutDefault *DomUI::takeElementLayoutDefault()
{
DomLayoutDefault *a = m_layoutDefault;
- m_layoutDefault = 0;
+ m_layoutDefault = nullptr;
m_children ^= LayoutDefault;
return a;
}
@@ -323,7 +323,7 @@ void DomUI::setElementLayoutDefault(DomLayoutDefault *a)
DomLayoutFunction *DomUI::takeElementLayoutFunction()
{
DomLayoutFunction *a = m_layoutFunction;
- m_layoutFunction = 0;
+ m_layoutFunction = nullptr;
m_children ^= LayoutFunction;
return a;
}
@@ -344,7 +344,7 @@ void DomUI::setElementPixmapFunction(const QString &a)
DomCustomWidgets *DomUI::takeElementCustomWidgets()
{
DomCustomWidgets *a = m_customWidgets;
- m_customWidgets = 0;
+ m_customWidgets = nullptr;
m_children ^= CustomWidgets;
return a;
}
@@ -359,7 +359,7 @@ void DomUI::setElementCustomWidgets(DomCustomWidgets *a)
DomTabStops *DomUI::takeElementTabStops()
{
DomTabStops *a = m_tabStops;
- m_tabStops = 0;
+ m_tabStops = nullptr;
m_children ^= TabStops;
return a;
}
@@ -374,7 +374,7 @@ void DomUI::setElementTabStops(DomTabStops *a)
DomIncludes *DomUI::takeElementIncludes()
{
DomIncludes *a = m_includes;
- m_includes = 0;
+ m_includes = nullptr;
m_children ^= Includes;
return a;
}
@@ -389,7 +389,7 @@ void DomUI::setElementIncludes(DomIncludes *a)
DomResources *DomUI::takeElementResources()
{
DomResources *a = m_resources;
- m_resources = 0;
+ m_resources = nullptr;
m_children ^= Resources;
return a;
}
@@ -404,7 +404,7 @@ void DomUI::setElementResources(DomResources *a)
DomConnections *DomUI::takeElementConnections()
{
DomConnections *a = m_connections;
- m_connections = 0;
+ m_connections = nullptr;
m_children ^= Connections;
return a;
}
@@ -419,7 +419,7 @@ void DomUI::setElementConnections(DomConnections *a)
DomDesignerData *DomUI::takeElementDesignerdata()
{
DomDesignerData *a = m_designerdata;
- m_designerdata = 0;
+ m_designerdata = nullptr;
m_children ^= Designerdata;
return a;
}
@@ -434,7 +434,7 @@ void DomUI::setElementDesignerdata(DomDesignerData *a)
DomSlots *DomUI::takeElementSlots()
{
DomSlots *a = m_slots;
- m_slots = 0;
+ m_slots = nullptr;
m_children ^= Slots;
return a;
}
@@ -449,7 +449,7 @@ void DomUI::setElementSlots(DomSlots *a)
DomButtonGroups *DomUI::takeElementButtonGroups()
{
DomButtonGroups *a = m_buttonGroups;
- m_buttonGroups = 0;
+ m_buttonGroups = nullptr;
m_children ^= ButtonGroups;
return a;
}
@@ -484,21 +484,21 @@ void DomUI::clearElementClass()
void DomUI::clearElementWidget()
{
delete m_widget;
- m_widget = 0;
+ m_widget = nullptr;
m_children &= ~Widget;
}
void DomUI::clearElementLayoutDefault()
{
delete m_layoutDefault;
- m_layoutDefault = 0;
+ m_layoutDefault = nullptr;
m_children &= ~LayoutDefault;
}
void DomUI::clearElementLayoutFunction()
{
delete m_layoutFunction;
- m_layoutFunction = 0;
+ m_layoutFunction = nullptr;
m_children &= ~LayoutFunction;
}
@@ -510,56 +510,56 @@ void DomUI::clearElementPixmapFunction()
void DomUI::clearElementCustomWidgets()
{
delete m_customWidgets;
- m_customWidgets = 0;
+ m_customWidgets = nullptr;
m_children &= ~CustomWidgets;
}
void DomUI::clearElementTabStops()
{
delete m_tabStops;
- m_tabStops = 0;
+ m_tabStops = nullptr;
m_children &= ~TabStops;
}
void DomUI::clearElementIncludes()
{
delete m_includes;
- m_includes = 0;
+ m_includes = nullptr;
m_children &= ~Includes;
}
void DomUI::clearElementResources()
{
delete m_resources;
- m_resources = 0;
+ m_resources = nullptr;
m_children &= ~Resources;
}
void DomUI::clearElementConnections()
{
delete m_connections;
- m_connections = 0;
+ m_connections = nullptr;
m_children &= ~Connections;
}
void DomUI::clearElementDesignerdata()
{
delete m_designerdata;
- m_designerdata = 0;
+ m_designerdata = nullptr;
m_children &= ~Designerdata;
}
void DomUI::clearElementSlots()
{
delete m_slots;
- m_slots = 0;
+ m_slots = nullptr;
m_children &= ~Slots;
}
void DomUI::clearElementButtonGroups()
{
delete m_buttonGroups;
- m_buttonGroups = 0;
+ m_buttonGroups = nullptr;
m_children &= ~ButtonGroups;
}
@@ -576,7 +576,7 @@ void DomIncludes::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("include"), Qt::CaseInsensitive)) {
- DomInclude *v = new DomInclude();
+ auto *v = new DomInclude();
v->read(reader);
m_include.append(v);
continue;
@@ -608,9 +608,7 @@ void DomIncludes::setElementInclude(const QVector<DomInclude *> &a)
m_include = a;
}
-DomInclude::~DomInclude()
-{
-}
+DomInclude::~DomInclude() = default;
void DomInclude::read(QXmlStreamReader &reader)
{
@@ -686,7 +684,7 @@ void DomResources::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("include"), Qt::CaseInsensitive)) {
- DomResource *v = new DomResource();
+ auto *v = new DomResource();
v->read(reader);
m_include.append(v);
continue;
@@ -721,9 +719,7 @@ void DomResources::setElementInclude(const QVector<DomResource *> &a)
m_include = a;
}
-DomResource::~DomResource()
-{
-}
+DomResource::~DomResource() = default;
void DomResource::read(QXmlStreamReader &reader)
{
@@ -791,25 +787,25 @@ void DomActionGroup::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("action"), Qt::CaseInsensitive)) {
- DomAction *v = new DomAction();
+ auto *v = new DomAction();
v->read(reader);
m_action.append(v);
continue;
}
if (!tag.compare(QLatin1String("actiongroup"), Qt::CaseInsensitive)) {
- DomActionGroup *v = new DomActionGroup();
+ auto *v = new DomActionGroup();
v->read(reader);
m_actionGroup.append(v);
continue;
}
if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
- DomProperty *v = new DomProperty();
+ auto *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
}
if (!tag.compare(QLatin1String("attribute"), Qt::CaseInsensitive)) {
- DomProperty *v = new DomProperty();
+ auto *v = new DomProperty();
v->read(reader);
m_attribute.append(v);
continue;
@@ -900,13 +896,13 @@ void DomAction::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
- DomProperty *v = new DomProperty();
+ auto *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
}
if (!tag.compare(QLatin1String("attribute"), Qt::CaseInsensitive)) {
- DomProperty *v = new DomProperty();
+ auto *v = new DomProperty();
v->read(reader);
m_attribute.append(v);
continue;
@@ -953,9 +949,7 @@ void DomAction::setElementAttribute(const QList<DomProperty *> &a)
m_attribute = a;
}
-DomActionRef::~DomActionRef()
-{
-}
+DomActionRef::~DomActionRef() = default;
void DomActionRef::read(QXmlStreamReader &reader)
{
@@ -1019,13 +1013,13 @@ void DomButtonGroup::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
- DomProperty *v = new DomProperty();
+ auto *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
}
if (!tag.compare(QLatin1String("attribute"), Qt::CaseInsensitive)) {
- DomProperty *v = new DomProperty();
+ auto *v = new DomProperty();
v->read(reader);
m_attribute.append(v);
continue;
@@ -1082,7 +1076,7 @@ void DomButtonGroups::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("buttongroup"), Qt::CaseInsensitive)) {
- DomButtonGroup *v = new DomButtonGroup();
+ auto *v = new DomButtonGroup();
v->read(reader);
m_buttonGroup.append(v);
continue;
@@ -1127,7 +1121,7 @@ void DomCustomWidgets::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("customwidget"), Qt::CaseInsensitive)) {
- DomCustomWidget *v = new DomCustomWidget();
+ auto *v = new DomCustomWidget();
v->read(reader);
m_customWidget.append(v);
continue;
@@ -1159,9 +1153,7 @@ void DomCustomWidgets::setElementCustomWidget(const QVector<DomCustomWidget *> &
m_customWidget = a;
}
-DomHeader::~DomHeader()
-{
-}
+DomHeader::~DomHeader() = default;
void DomHeader::read(QXmlStreamReader &reader)
{
@@ -1230,13 +1222,13 @@ void DomCustomWidget::read(QXmlStreamReader &reader)
continue;
}
if (!tag.compare(QLatin1String("header"), Qt::CaseInsensitive)) {
- DomHeader *v = new DomHeader();
+ auto *v = new DomHeader();
v->read(reader);
setElementHeader(v);
continue;
}
if (!tag.compare(QLatin1String("sizehint"), Qt::CaseInsensitive)) {
- DomSize *v = new DomSize();
+ auto *v = new DomSize();
v->read(reader);
setElementSizeHint(v);
continue;
@@ -1269,13 +1261,13 @@ void DomCustomWidget::read(QXmlStreamReader &reader)
continue;
}
if (!tag.compare(QLatin1String("slots"), Qt::CaseInsensitive)) {
- DomSlots *v = new DomSlots();
+ auto *v = new DomSlots();
v->read(reader);
setElementSlots(v);
continue;
}
if (!tag.compare(QLatin1String("propertyspecifications"), Qt::CaseInsensitive)) {
- DomPropertySpecifications *v = new DomPropertySpecifications();
+ auto *v = new DomPropertySpecifications();
v->read(reader);
setElementPropertyspecifications(v);
continue;
@@ -1340,7 +1332,7 @@ void DomCustomWidget::setElementExtends(const QString &a)
DomHeader *DomCustomWidget::takeElementHeader()
{
DomHeader *a = m_header;
- m_header = 0;
+ m_header = nullptr;
m_children ^= Header;
return a;
}
@@ -1355,7 +1347,7 @@ void DomCustomWidget::setElementHeader(DomHeader *a)
DomSize *DomCustomWidget::takeElementSizeHint()
{
DomSize *a = m_sizeHint;
- m_sizeHint = 0;
+ m_sizeHint = nullptr;
m_children ^= SizeHint;
return a;
}
@@ -1388,7 +1380,7 @@ void DomCustomWidget::setElementPixmap(const QString &a)
DomSlots *DomCustomWidget::takeElementSlots()
{
DomSlots *a = m_slots;
- m_slots = 0;
+ m_slots = nullptr;
m_children ^= Slots;
return a;
}
@@ -1403,7 +1395,7 @@ void DomCustomWidget::setElementSlots(DomSlots *a)
DomPropertySpecifications *DomCustomWidget::takeElementPropertyspecifications()
{
DomPropertySpecifications *a = m_propertyspecifications;
- m_propertyspecifications = 0;
+ m_propertyspecifications = nullptr;
m_children ^= Propertyspecifications;
return a;
}
@@ -1428,14 +1420,14 @@ void DomCustomWidget::clearElementExtends()
void DomCustomWidget::clearElementHeader()
{
delete m_header;
- m_header = 0;
+ m_header = nullptr;
m_children &= ~Header;
}
void DomCustomWidget::clearElementSizeHint()
{
delete m_sizeHint;
- m_sizeHint = 0;
+ m_sizeHint = nullptr;
m_children &= ~SizeHint;
}
@@ -1457,20 +1449,18 @@ void DomCustomWidget::clearElementPixmap()
void DomCustomWidget::clearElementSlots()
{
delete m_slots;
- m_slots = 0;
+ m_slots = nullptr;
m_children &= ~Slots;
}
void DomCustomWidget::clearElementPropertyspecifications()
{
delete m_propertyspecifications;
- m_propertyspecifications = 0;
+ m_propertyspecifications = nullptr;
m_children &= ~Propertyspecifications;
}
-DomLayoutDefault::~DomLayoutDefault()
-{
-}
+DomLayoutDefault::~DomLayoutDefault() = default;
void DomLayoutDefault::read(QXmlStreamReader &reader)
{
@@ -1516,9 +1506,7 @@ void DomLayoutDefault::write(QXmlStreamWriter &writer, const QString &tagName) c
writer.writeEndElement();
}
-DomLayoutFunction::~DomLayoutFunction()
-{
-}
+DomLayoutFunction::~DomLayoutFunction() = default;
void DomLayoutFunction::read(QXmlStreamReader &reader)
{
@@ -1657,19 +1645,19 @@ void DomLayout::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
- DomProperty *v = new DomProperty();
+ auto *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
}
if (!tag.compare(QLatin1String("attribute"), Qt::CaseInsensitive)) {
- DomProperty *v = new DomProperty();
+ auto *v = new DomProperty();
v->read(reader);
m_attribute.append(v);
continue;
}
if (!tag.compare(QLatin1String("item"), Qt::CaseInsensitive)) {
- DomLayoutItem *v = new DomLayoutItem();
+ auto *v = new DomLayoutItem();
v->read(reader);
m_item.append(v);
continue;
@@ -1793,19 +1781,19 @@ void DomLayoutItem::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("widget"), Qt::CaseInsensitive)) {
- DomWidget *v = new DomWidget();
+ auto *v = new DomWidget();
v->read(reader);
setElementWidget(v);
continue;
}
if (!tag.compare(QLatin1String("layout"), Qt::CaseInsensitive)) {
- DomLayout *v = new DomLayout();
+ auto *v = new DomLayout();
v->read(reader);
setElementLayout(v);
continue;
}
if (!tag.compare(QLatin1String("spacer"), Qt::CaseInsensitive)) {
- DomSpacer *v = new DomSpacer();
+ auto *v = new DomSpacer();
v->read(reader);
setElementSpacer(v);
continue;
@@ -1841,24 +1829,21 @@ void DomLayoutItem::write(QXmlStreamWriter &writer, const QString &tagName) cons
writer.writeAttribute(QStringLiteral("alignment"), attributeAlignment());
switch (kind()) {
- case Widget: {
- DomWidget *v = elementWidget();
- if (v != 0)
- v->write(writer, QStringLiteral("widget"));
+ case Widget:
+ if (m_widget != nullptr)
+ m_widget->write(writer, QStringLiteral("widget"));
break;
- }
- case Layout: {
- DomLayout *v = elementLayout();
- if (v != 0)
- v->write(writer, QStringLiteral("layout"));
+
+ case Layout:
+ if (m_layout != nullptr)
+ m_layout->write(writer, QStringLiteral("layout"));
break;
- }
- case Spacer: {
- DomSpacer *v = elementSpacer();
- if (v != 0)
- v->write(writer, QStringLiteral("spacer"));
+
+ case Spacer:
+ if (m_spacer != nullptr)
+ m_spacer->write(writer, QStringLiteral("spacer"));
break;
- }
+
default:
break;
}
@@ -1868,7 +1853,7 @@ void DomLayoutItem::write(QXmlStreamWriter &writer, const QString &tagName) cons
DomWidget *DomLayoutItem::takeElementWidget()
{
DomWidget *a = m_widget;
- m_widget = 0;
+ m_widget = nullptr;
return a;
}
@@ -1882,7 +1867,7 @@ void DomLayoutItem::setElementWidget(DomWidget *a)
DomLayout *DomLayoutItem::takeElementLayout()
{
DomLayout *a = m_layout;
- m_layout = 0;
+ m_layout = nullptr;
return a;
}
@@ -1896,7 +1881,7 @@ void DomLayoutItem::setElementLayout(DomLayout *a)
DomSpacer *DomLayoutItem::takeElementSpacer()
{
DomSpacer *a = m_spacer;
- m_spacer = 0;
+ m_spacer = nullptr;
return a;
}
@@ -1920,7 +1905,7 @@ void DomRow::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
- DomProperty *v = new DomProperty();
+ auto *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
@@ -1965,7 +1950,7 @@ void DomColumn::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
- DomProperty *v = new DomProperty();
+ auto *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
@@ -2026,13 +2011,13 @@ void DomItem::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
- DomProperty *v = new DomProperty();
+ auto *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
}
if (!tag.compare(QLatin1String("item"), Qt::CaseInsensitive)) {
- DomItem *v = new DomItem();
+ auto *v = new DomItem();
v->read(reader);
m_item.append(v);
continue;
@@ -2134,7 +2119,7 @@ void DomWidget::read(QXmlStreamReader &reader)
continue;
}
if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
- DomProperty *v = new DomProperty();
+ auto *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
@@ -2150,55 +2135,55 @@ void DomWidget::read(QXmlStreamReader &reader)
continue;
}
if (!tag.compare(QLatin1String("attribute"), Qt::CaseInsensitive)) {
- DomProperty *v = new DomProperty();
+ auto *v = new DomProperty();
v->read(reader);
m_attribute.append(v);
continue;
}
if (!tag.compare(QLatin1String("row"), Qt::CaseInsensitive)) {
- DomRow *v = new DomRow();
+ auto *v = new DomRow();
v->read(reader);
m_row.append(v);
continue;
}
if (!tag.compare(QLatin1String("column"), Qt::CaseInsensitive)) {
- DomColumn *v = new DomColumn();
+ auto *v = new DomColumn();
v->read(reader);
m_column.append(v);
continue;
}
if (!tag.compare(QLatin1String("item"), Qt::CaseInsensitive)) {
- DomItem *v = new DomItem();
+ auto *v = new DomItem();
v->read(reader);
m_item.append(v);
continue;
}
if (!tag.compare(QLatin1String("layout"), Qt::CaseInsensitive)) {
- DomLayout *v = new DomLayout();
+ auto *v = new DomLayout();
v->read(reader);
m_layout.append(v);
continue;
}
if (!tag.compare(QLatin1String("widget"), Qt::CaseInsensitive)) {
- DomWidget *v = new DomWidget();
+ auto *v = new DomWidget();
v->read(reader);
m_widget.append(v);
continue;
}
if (!tag.compare(QLatin1String("action"), Qt::CaseInsensitive)) {
- DomAction *v = new DomAction();
+ auto *v = new DomAction();
v->read(reader);
m_action.append(v);
continue;
}
if (!tag.compare(QLatin1String("actiongroup"), Qt::CaseInsensitive)) {
- DomActionGroup *v = new DomActionGroup();
+ auto *v = new DomActionGroup();
v->read(reader);
m_actionGroup.append(v);
continue;
}
if (!tag.compare(QLatin1String("addaction"), Qt::CaseInsensitive)) {
- DomActionRef *v = new DomActionRef();
+ auto *v = new DomActionRef();
v->read(reader);
m_addAction.append(v);
continue;
@@ -2365,7 +2350,7 @@ void DomSpacer::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
- DomProperty *v = new DomProperty();
+ auto *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
@@ -2400,9 +2385,7 @@ void DomSpacer::setElementProperty(const QList<DomProperty *> &a)
m_property = a;
}
-DomColor::~DomColor()
-{
-}
+DomColor::~DomColor() = default;
void DomColor::read(QXmlStreamReader &reader)
{
@@ -2517,7 +2500,7 @@ void DomGradientStop::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("color"), Qt::CaseInsensitive)) {
- DomColor *v = new DomColor();
+ auto *v = new DomColor();
v->read(reader);
setElementColor(v);
continue;
@@ -2549,7 +2532,7 @@ void DomGradientStop::write(QXmlStreamWriter &writer, const QString &tagName) co
DomColor *DomGradientStop::takeElementColor()
{
DomColor *a = m_color;
- m_color = 0;
+ m_color = nullptr;
m_children ^= Color;
return a;
}
@@ -2564,7 +2547,7 @@ void DomGradientStop::setElementColor(DomColor *a)
void DomGradientStop::clearElementColor()
{
delete m_color;
- m_color = 0;
+ m_color = nullptr;
m_children &= ~Color;
}
@@ -2639,7 +2622,7 @@ void DomGradient::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("gradientstop"), Qt::CaseInsensitive)) {
- DomGradientStop *v = new DomGradientStop();
+ auto *v = new DomGradientStop();
v->read(reader);
m_gradientStop.append(v);
continue;
@@ -2747,19 +2730,19 @@ void DomBrush::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("color"), Qt::CaseInsensitive)) {
- DomColor *v = new DomColor();
+ auto *v = new DomColor();
v->read(reader);
setElementColor(v);
continue;
}
if (!tag.compare(QLatin1String("texture"), Qt::CaseInsensitive)) {
- DomProperty *v = new DomProperty();
+ auto *v = new DomProperty();
v->read(reader);
setElementTexture(v);
continue;
}
if (!tag.compare(QLatin1String("gradient"), Qt::CaseInsensitive)) {
- DomGradient *v = new DomGradient();
+ auto *v = new DomGradient();
v->read(reader);
setElementGradient(v);
continue;
@@ -2783,24 +2766,21 @@ void DomBrush::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeAttribute(QStringLiteral("brushstyle"), attributeBrushStyle());
switch (kind()) {
- case Color: {
- DomColor *v = elementColor();
- if (v != 0)
- v->write(writer, QStringLiteral("color"));
+ case Color:
+ if (m_color != nullptr)
+ m_color->write(writer, QStringLiteral("color"));
break;
- }
- case Texture: {
- DomProperty *v = elementTexture();
- if (v != 0)
- v->write(writer, QStringLiteral("texture"));
+
+ case Texture:
+ if (m_texture != nullptr)
+ m_texture->write(writer, QStringLiteral("texture"));
break;
- }
- case Gradient: {
- DomGradient *v = elementGradient();
- if (v != 0)
- v->write(writer, QStringLiteral("gradient"));
+
+ case Gradient:
+ if (m_gradient != nullptr)
+ m_gradient->write(writer, QStringLiteral("gradient"));
break;
- }
+
default:
break;
}
@@ -2810,7 +2790,7 @@ void DomBrush::write(QXmlStreamWriter &writer, const QString &tagName) const
DomColor *DomBrush::takeElementColor()
{
DomColor *a = m_color;
- m_color = 0;
+ m_color = nullptr;
return a;
}
@@ -2824,7 +2804,7 @@ void DomBrush::setElementColor(DomColor *a)
DomProperty *DomBrush::takeElementTexture()
{
DomProperty *a = m_texture;
- m_texture = 0;
+ m_texture = nullptr;
return a;
}
@@ -2838,7 +2818,7 @@ void DomBrush::setElementTexture(DomProperty *a)
DomGradient *DomBrush::takeElementGradient()
{
DomGradient *a = m_gradient;
- m_gradient = 0;
+ m_gradient = nullptr;
return a;
}
@@ -2871,7 +2851,7 @@ void DomColorRole::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("brush"), Qt::CaseInsensitive)) {
- DomBrush *v = new DomBrush();
+ auto *v = new DomBrush();
v->read(reader);
setElementBrush(v);
continue;
@@ -2903,7 +2883,7 @@ void DomColorRole::write(QXmlStreamWriter &writer, const QString &tagName) const
DomBrush *DomColorRole::takeElementBrush()
{
DomBrush *a = m_brush;
- m_brush = 0;
+ m_brush = nullptr;
m_children ^= Brush;
return a;
}
@@ -2918,7 +2898,7 @@ void DomColorRole::setElementBrush(DomBrush *a)
void DomColorRole::clearElementBrush()
{
delete m_brush;
- m_brush = 0;
+ m_brush = nullptr;
m_children &= ~Brush;
}
@@ -2937,13 +2917,13 @@ void DomColorGroup::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("colorrole"), Qt::CaseInsensitive)) {
- DomColorRole *v = new DomColorRole();
+ auto *v = new DomColorRole();
v->read(reader);
m_colorRole.append(v);
continue;
}
if (!tag.compare(QLatin1String("color"), Qt::CaseInsensitive)) {
- DomColor *v = new DomColor();
+ auto *v = new DomColor();
v->read(reader);
m_color.append(v);
continue;
@@ -2998,19 +2978,19 @@ void DomPalette::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("active"), Qt::CaseInsensitive)) {
- DomColorGroup *v = new DomColorGroup();
+ auto *v = new DomColorGroup();
v->read(reader);
setElementActive(v);
continue;
}
if (!tag.compare(QLatin1String("inactive"), Qt::CaseInsensitive)) {
- DomColorGroup *v = new DomColorGroup();
+ auto *v = new DomColorGroup();
v->read(reader);
setElementInactive(v);
continue;
}
if (!tag.compare(QLatin1String("disabled"), Qt::CaseInsensitive)) {
- DomColorGroup *v = new DomColorGroup();
+ auto *v = new DomColorGroup();
v->read(reader);
setElementDisabled(v);
continue;
@@ -3045,7 +3025,7 @@ void DomPalette::write(QXmlStreamWriter &writer, const QString &tagName) const
DomColorGroup *DomPalette::takeElementActive()
{
DomColorGroup *a = m_active;
- m_active = 0;
+ m_active = nullptr;
m_children ^= Active;
return a;
}
@@ -3060,7 +3040,7 @@ void DomPalette::setElementActive(DomColorGroup *a)
DomColorGroup *DomPalette::takeElementInactive()
{
DomColorGroup *a = m_inactive;
- m_inactive = 0;
+ m_inactive = nullptr;
m_children ^= Inactive;
return a;
}
@@ -3075,7 +3055,7 @@ void DomPalette::setElementInactive(DomColorGroup *a)
DomColorGroup *DomPalette::takeElementDisabled()
{
DomColorGroup *a = m_disabled;
- m_disabled = 0;
+ m_disabled = nullptr;
m_children ^= Disabled;
return a;
}
@@ -3090,27 +3070,25 @@ void DomPalette::setElementDisabled(DomColorGroup *a)
void DomPalette::clearElementActive()
{
delete m_active;
- m_active = 0;
+ m_active = nullptr;
m_children &= ~Active;
}
void DomPalette::clearElementInactive()
{
delete m_inactive;
- m_inactive = 0;
+ m_inactive = nullptr;
m_children &= ~Inactive;
}
void DomPalette::clearElementDisabled()
{
delete m_disabled;
- m_disabled = 0;
+ m_disabled = nullptr;
m_children &= ~Disabled;
}
-DomFont::~DomFont()
-{
-}
+DomFont::~DomFont() = default;
void DomFont::read(QXmlStreamReader &reader)
{
@@ -3316,9 +3294,7 @@ void DomFont::clearElementKerning()
m_children &= ~Kerning;
}
-DomPoint::~DomPoint()
-{
-}
+DomPoint::~DomPoint() = default;
void DomPoint::read(QXmlStreamReader &reader)
{
@@ -3380,9 +3356,7 @@ void DomPoint::clearElementY()
m_children &= ~Y;
}
-DomRect::~DomRect()
-{
-}
+DomRect::~DomRect() = default;
void DomRect::read(QXmlStreamReader &reader)
{
@@ -3480,9 +3454,7 @@ void DomRect::clearElementHeight()
m_children &= ~Height;
}
-DomLocale::~DomLocale()
-{
-}
+DomLocale::~DomLocale() = default;
void DomLocale::read(QXmlStreamReader &reader)
{
@@ -3528,9 +3500,7 @@ void DomLocale::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeEndElement();
}
-DomSizePolicy::~DomSizePolicy()
-{
-}
+DomSizePolicy::~DomSizePolicy() = default;
void DomSizePolicy::read(QXmlStreamReader &reader)
{
@@ -3648,9 +3618,7 @@ void DomSizePolicy::clearElementVerStretch()
m_children &= ~VerStretch;
}
-DomSize::~DomSize()
-{
-}
+DomSize::~DomSize() = default;
void DomSize::read(QXmlStreamReader &reader)
{
@@ -3712,9 +3680,7 @@ void DomSize::clearElementHeight()
m_children &= ~Height;
}
-DomDate::~DomDate()
-{
-}
+DomDate::~DomDate() = default;
void DomDate::read(QXmlStreamReader &reader)
{
@@ -3794,9 +3760,7 @@ void DomDate::clearElementDay()
m_children &= ~Day;
}
-DomTime::~DomTime()
-{
-}
+DomTime::~DomTime() = default;
void DomTime::read(QXmlStreamReader &reader)
{
@@ -3876,9 +3840,7 @@ void DomTime::clearElementSecond()
m_children &= ~Second;
}
-DomDateTime::~DomDateTime()
-{
-}
+DomDateTime::~DomDateTime() = default;
void DomDateTime::read(QXmlStreamReader &reader)
{
@@ -4088,9 +4050,7 @@ void DomStringList::setElementString(const QStringList &a)
m_string = a;
}
-DomResourcePixmap::~DomResourcePixmap()
-{
-}
+DomResourcePixmap::~DomResourcePixmap() = default;
void DomResourcePixmap::read(QXmlStreamReader &reader)
{
@@ -4176,49 +4136,49 @@ void DomResourceIcon::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("normaloff"), Qt::CaseInsensitive)) {
- DomResourcePixmap *v = new DomResourcePixmap();
+ auto *v = new DomResourcePixmap();
v->read(reader);
setElementNormalOff(v);
continue;
}
if (!tag.compare(QLatin1String("normalon"), Qt::CaseInsensitive)) {
- DomResourcePixmap *v = new DomResourcePixmap();
+ auto *v = new DomResourcePixmap();
v->read(reader);
setElementNormalOn(v);
continue;
}
if (!tag.compare(QLatin1String("disabledoff"), Qt::CaseInsensitive)) {
- DomResourcePixmap *v = new DomResourcePixmap();
+ auto *v = new DomResourcePixmap();
v->read(reader);
setElementDisabledOff(v);
continue;
}
if (!tag.compare(QLatin1String("disabledon"), Qt::CaseInsensitive)) {
- DomResourcePixmap *v = new DomResourcePixmap();
+ auto *v = new DomResourcePixmap();
v->read(reader);
setElementDisabledOn(v);
continue;
}
if (!tag.compare(QLatin1String("activeoff"), Qt::CaseInsensitive)) {
- DomResourcePixmap *v = new DomResourcePixmap();
+ auto *v = new DomResourcePixmap();
v->read(reader);
setElementActiveOff(v);
continue;
}
if (!tag.compare(QLatin1String("activeon"), Qt::CaseInsensitive)) {
- DomResourcePixmap *v = new DomResourcePixmap();
+ auto *v = new DomResourcePixmap();
v->read(reader);
setElementActiveOn(v);
continue;
}
if (!tag.compare(QLatin1String("selectedoff"), Qt::CaseInsensitive)) {
- DomResourcePixmap *v = new DomResourcePixmap();
+ auto *v = new DomResourcePixmap();
v->read(reader);
setElementSelectedOff(v);
continue;
}
if (!tag.compare(QLatin1String("selectedon"), Qt::CaseInsensitive)) {
- DomResourcePixmap *v = new DomResourcePixmap();
+ auto *v = new DomResourcePixmap();
v->read(reader);
setElementSelectedOn(v);
continue;
@@ -4281,7 +4241,7 @@ void DomResourceIcon::write(QXmlStreamWriter &writer, const QString &tagName) co
DomResourcePixmap *DomResourceIcon::takeElementNormalOff()
{
DomResourcePixmap *a = m_normalOff;
- m_normalOff = 0;
+ m_normalOff = nullptr;
m_children ^= NormalOff;
return a;
}
@@ -4296,7 +4256,7 @@ void DomResourceIcon::setElementNormalOff(DomResourcePixmap *a)
DomResourcePixmap *DomResourceIcon::takeElementNormalOn()
{
DomResourcePixmap *a = m_normalOn;
- m_normalOn = 0;
+ m_normalOn = nullptr;
m_children ^= NormalOn;
return a;
}
@@ -4311,7 +4271,7 @@ void DomResourceIcon::setElementNormalOn(DomResourcePixmap *a)
DomResourcePixmap *DomResourceIcon::takeElementDisabledOff()
{
DomResourcePixmap *a = m_disabledOff;
- m_disabledOff = 0;
+ m_disabledOff = nullptr;
m_children ^= DisabledOff;
return a;
}
@@ -4326,7 +4286,7 @@ void DomResourceIcon::setElementDisabledOff(DomResourcePixmap *a)
DomResourcePixmap *DomResourceIcon::takeElementDisabledOn()
{
DomResourcePixmap *a = m_disabledOn;
- m_disabledOn = 0;
+ m_disabledOn = nullptr;
m_children ^= DisabledOn;
return a;
}
@@ -4341,7 +4301,7 @@ void DomResourceIcon::setElementDisabledOn(DomResourcePixmap *a)
DomResourcePixmap *DomResourceIcon::takeElementActiveOff()
{
DomResourcePixmap *a = m_activeOff;
- m_activeOff = 0;
+ m_activeOff = nullptr;
m_children ^= ActiveOff;
return a;
}
@@ -4356,7 +4316,7 @@ void DomResourceIcon::setElementActiveOff(DomResourcePixmap *a)
DomResourcePixmap *DomResourceIcon::takeElementActiveOn()
{
DomResourcePixmap *a = m_activeOn;
- m_activeOn = 0;
+ m_activeOn = nullptr;
m_children ^= ActiveOn;
return a;
}
@@ -4371,7 +4331,7 @@ void DomResourceIcon::setElementActiveOn(DomResourcePixmap *a)
DomResourcePixmap *DomResourceIcon::takeElementSelectedOff()
{
DomResourcePixmap *a = m_selectedOff;
- m_selectedOff = 0;
+ m_selectedOff = nullptr;
m_children ^= SelectedOff;
return a;
}
@@ -4386,7 +4346,7 @@ void DomResourceIcon::setElementSelectedOff(DomResourcePixmap *a)
DomResourcePixmap *DomResourceIcon::takeElementSelectedOn()
{
DomResourcePixmap *a = m_selectedOn;
- m_selectedOn = 0;
+ m_selectedOn = nullptr;
m_children ^= SelectedOn;
return a;
}
@@ -4401,62 +4361,60 @@ void DomResourceIcon::setElementSelectedOn(DomResourcePixmap *a)
void DomResourceIcon::clearElementNormalOff()
{
delete m_normalOff;
- m_normalOff = 0;
+ m_normalOff = nullptr;
m_children &= ~NormalOff;
}
void DomResourceIcon::clearElementNormalOn()
{
delete m_normalOn;
- m_normalOn = 0;
+ m_normalOn = nullptr;
m_children &= ~NormalOn;
}
void DomResourceIcon::clearElementDisabledOff()
{
delete m_disabledOff;
- m_disabledOff = 0;
+ m_disabledOff = nullptr;
m_children &= ~DisabledOff;
}
void DomResourceIcon::clearElementDisabledOn()
{
delete m_disabledOn;
- m_disabledOn = 0;
+ m_disabledOn = nullptr;
m_children &= ~DisabledOn;
}
void DomResourceIcon::clearElementActiveOff()
{
delete m_activeOff;
- m_activeOff = 0;
+ m_activeOff = nullptr;
m_children &= ~ActiveOff;
}
void DomResourceIcon::clearElementActiveOn()
{
delete m_activeOn;
- m_activeOn = 0;
+ m_activeOn = nullptr;
m_children &= ~ActiveOn;
}
void DomResourceIcon::clearElementSelectedOff()
{
delete m_selectedOff;
- m_selectedOff = 0;
+ m_selectedOff = nullptr;
m_children &= ~SelectedOff;
}
void DomResourceIcon::clearElementSelectedOn()
{
delete m_selectedOn;
- m_selectedOn = 0;
+ m_selectedOn = nullptr;
m_children &= ~SelectedOn;
}
-DomString::~DomString()
-{
-}
+DomString::~DomString() = default;
void DomString::read(QXmlStreamReader &reader)
{
@@ -4523,9 +4481,7 @@ void DomString::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeEndElement();
}
-DomPointF::~DomPointF()
-{
-}
+DomPointF::~DomPointF() = default;
void DomPointF::read(QXmlStreamReader &reader)
{
@@ -4587,9 +4543,7 @@ void DomPointF::clearElementY()
m_children &= ~Y;
}
-DomRectF::~DomRectF()
-{
-}
+DomRectF::~DomRectF() = default;
void DomRectF::read(QXmlStreamReader &reader)
{
@@ -4687,9 +4641,7 @@ void DomRectF::clearElementHeight()
m_children &= ~Height;
}
-DomSizeF::~DomSizeF()
-{
-}
+DomSizeF::~DomSizeF() = default;
void DomSizeF::read(QXmlStreamReader &reader)
{
@@ -4751,9 +4703,7 @@ void DomSizeF::clearElementHeight()
m_children &= ~Height;
}
-DomChar::~DomChar()
-{
-}
+DomChar::~DomChar() = default;
void DomChar::read(QXmlStreamReader &reader)
{
@@ -4809,7 +4759,7 @@ void DomUrl::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("string"), Qt::CaseInsensitive)) {
- DomString *v = new DomString();
+ auto *v = new DomString();
v->read(reader);
setElementString(v);
continue;
@@ -4838,7 +4788,7 @@ void DomUrl::write(QXmlStreamWriter &writer, const QString &tagName) const
DomString *DomUrl::takeElementString()
{
DomString *a = m_string;
- m_string = 0;
+ m_string = nullptr;
m_children ^= String;
return a;
}
@@ -4853,7 +4803,7 @@ void DomUrl::setElementString(DomString *a)
void DomUrl::clearElementString()
{
delete m_string;
- m_string = 0;
+ m_string = nullptr;
m_children &= ~String;
}
@@ -4963,7 +4913,7 @@ void DomProperty::read(QXmlStreamReader &reader)
continue;
}
if (!tag.compare(QLatin1String("color"), Qt::CaseInsensitive)) {
- DomColor *v = new DomColor();
+ auto *v = new DomColor();
v->read(reader);
setElementColor(v);
continue;
@@ -4985,37 +4935,37 @@ void DomProperty::read(QXmlStreamReader &reader)
continue;
}
if (!tag.compare(QLatin1String("font"), Qt::CaseInsensitive)) {
- DomFont *v = new DomFont();
+ auto *v = new DomFont();
v->read(reader);
setElementFont(v);
continue;
}
if (!tag.compare(QLatin1String("iconset"), Qt::CaseInsensitive)) {
- DomResourceIcon *v = new DomResourceIcon();
+ auto *v = new DomResourceIcon();
v->read(reader);
setElementIconSet(v);
continue;
}
if (!tag.compare(QLatin1String("pixmap"), Qt::CaseInsensitive)) {
- DomResourcePixmap *v = new DomResourcePixmap();
+ auto *v = new DomResourcePixmap();
v->read(reader);
setElementPixmap(v);
continue;
}
if (!tag.compare(QLatin1String("palette"), Qt::CaseInsensitive)) {
- DomPalette *v = new DomPalette();
+ auto *v = new DomPalette();
v->read(reader);
setElementPalette(v);
continue;
}
if (!tag.compare(QLatin1String("point"), Qt::CaseInsensitive)) {
- DomPoint *v = new DomPoint();
+ auto *v = new DomPoint();
v->read(reader);
setElementPoint(v);
continue;
}
if (!tag.compare(QLatin1String("rect"), Qt::CaseInsensitive)) {
- DomRect *v = new DomRect();
+ auto *v = new DomRect();
v->read(reader);
setElementRect(v);
continue;
@@ -5025,31 +4975,31 @@ void DomProperty::read(QXmlStreamReader &reader)
continue;
}
if (!tag.compare(QLatin1String("locale"), Qt::CaseInsensitive)) {
- DomLocale *v = new DomLocale();
+ auto *v = new DomLocale();
v->read(reader);
setElementLocale(v);
continue;
}
if (!tag.compare(QLatin1String("sizepolicy"), Qt::CaseInsensitive)) {
- DomSizePolicy *v = new DomSizePolicy();
+ auto *v = new DomSizePolicy();
v->read(reader);
setElementSizePolicy(v);
continue;
}
if (!tag.compare(QLatin1String("size"), Qt::CaseInsensitive)) {
- DomSize *v = new DomSize();
+ auto *v = new DomSize();
v->read(reader);
setElementSize(v);
continue;
}
if (!tag.compare(QLatin1String("string"), Qt::CaseInsensitive)) {
- DomString *v = new DomString();
+ auto *v = new DomString();
v->read(reader);
setElementString(v);
continue;
}
if (!tag.compare(QLatin1String("stringlist"), Qt::CaseInsensitive)) {
- DomStringList *v = new DomStringList();
+ auto *v = new DomStringList();
v->read(reader);
setElementStringList(v);
continue;
@@ -5067,37 +5017,37 @@ void DomProperty::read(QXmlStreamReader &reader)
continue;
}
if (!tag.compare(QLatin1String("date"), Qt::CaseInsensitive)) {
- DomDate *v = new DomDate();
+ auto *v = new DomDate();
v->read(reader);
setElementDate(v);
continue;
}
if (!tag.compare(QLatin1String("time"), Qt::CaseInsensitive)) {
- DomTime *v = new DomTime();
+ auto *v = new DomTime();
v->read(reader);
setElementTime(v);
continue;
}
if (!tag.compare(QLatin1String("datetime"), Qt::CaseInsensitive)) {
- DomDateTime *v = new DomDateTime();
+ auto *v = new DomDateTime();
v->read(reader);
setElementDateTime(v);
continue;
}
if (!tag.compare(QLatin1String("pointf"), Qt::CaseInsensitive)) {
- DomPointF *v = new DomPointF();
+ auto *v = new DomPointF();
v->read(reader);
setElementPointF(v);
continue;
}
if (!tag.compare(QLatin1String("rectf"), Qt::CaseInsensitive)) {
- DomRectF *v = new DomRectF();
+ auto *v = new DomRectF();
v->read(reader);
setElementRectF(v);
continue;
}
if (!tag.compare(QLatin1String("sizef"), Qt::CaseInsensitive)) {
- DomSizeF *v = new DomSizeF();
+ auto *v = new DomSizeF();
v->read(reader);
setElementSizeF(v);
continue;
@@ -5107,13 +5057,13 @@ void DomProperty::read(QXmlStreamReader &reader)
continue;
}
if (!tag.compare(QLatin1String("char"), Qt::CaseInsensitive)) {
- DomChar *v = new DomChar();
+ auto *v = new DomChar();
v->read(reader);
setElementChar(v);
continue;
}
if (!tag.compare(QLatin1String("url"), Qt::CaseInsensitive)) {
- DomUrl *v = new DomUrl();
+ auto *v = new DomUrl();
v->read(reader);
setElementUrl(v);
continue;
@@ -5127,7 +5077,7 @@ void DomProperty::read(QXmlStreamReader &reader)
continue;
}
if (!tag.compare(QLatin1String("brush"), Qt::CaseInsensitive)) {
- DomBrush *v = new DomBrush();
+ auto *v = new DomBrush();
v->read(reader);
setElementBrush(v);
continue;
@@ -5154,180 +5104,159 @@ void DomProperty::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeAttribute(QStringLiteral("stdset"), QString::number(attributeStdset()));
switch (kind()) {
- case Bool: {
+ case Bool:
writer.writeTextElement(QStringLiteral("bool"), elementBool());
break;
- }
- case Color: {
- DomColor *v = elementColor();
- if (v != 0)
- v->write(writer, QStringLiteral("color"));
+
+ case Color:
+ if (m_color != nullptr)
+ m_color->write(writer, QStringLiteral("color"));
break;
- }
- case Cstring: {
+
+ case Cstring:
writer.writeTextElement(QStringLiteral("cstring"), elementCstring());
break;
- }
- case Cursor: {
+
+ case Cursor:
writer.writeTextElement(QStringLiteral("cursor"), QString::number(elementCursor()));
break;
- }
- case CursorShape: {
+
+ case CursorShape:
writer.writeTextElement(QStringLiteral("cursorShape"), elementCursorShape());
break;
- }
- case Enum: {
+
+ case Enum:
writer.writeTextElement(QStringLiteral("enum"), elementEnum());
break;
- }
- case Font: {
- DomFont *v = elementFont();
- if (v != 0)
- v->write(writer, QStringLiteral("font"));
+
+ case Font:
+ if (m_font != nullptr)
+ m_font->write(writer, QStringLiteral("font"));
break;
- }
- case IconSet: {
- DomResourceIcon *v = elementIconSet();
- if (v != 0)
- v->write(writer, QStringLiteral("iconset"));
+
+ case IconSet:
+ if (m_iconSet != nullptr)
+ m_iconSet->write(writer, QStringLiteral("iconset"));
break;
- }
- case Pixmap: {
- DomResourcePixmap *v = elementPixmap();
- if (v != 0)
- v->write(writer, QStringLiteral("pixmap"));
+
+ case Pixmap:
+ if (m_pixmap != nullptr)
+ m_pixmap->write(writer, QStringLiteral("pixmap"));
break;
- }
- case Palette: {
- DomPalette *v = elementPalette();
- if (v != 0)
- v->write(writer, QStringLiteral("palette"));
+
+ case Palette:
+ if (m_palette != nullptr)
+ m_palette->write(writer, QStringLiteral("palette"));
break;
- }
- case Point: {
- DomPoint *v = elementPoint();
- if (v != 0)
- v->write(writer, QStringLiteral("point"));
+
+ case Point:
+ if (m_point != nullptr)
+ m_point->write(writer, QStringLiteral("point"));
break;
- }
- case Rect: {
- DomRect *v = elementRect();
- if (v != 0)
- v->write(writer, QStringLiteral("rect"));
+
+ case Rect:
+ if (m_rect != nullptr)
+ m_rect->write(writer, QStringLiteral("rect"));
break;
- }
- case Set: {
+
+ case Set:
writer.writeTextElement(QStringLiteral("set"), elementSet());
break;
- }
- case Locale: {
- DomLocale *v = elementLocale();
- if (v != 0)
- v->write(writer, QStringLiteral("locale"));
+
+ case Locale:
+ if (m_locale != nullptr)
+ m_locale->write(writer, QStringLiteral("locale"));
break;
- }
- case SizePolicy: {
- DomSizePolicy *v = elementSizePolicy();
- if (v != 0)
- v->write(writer, QStringLiteral("sizepolicy"));
+
+ case SizePolicy:
+ if (m_sizePolicy != nullptr)
+ m_sizePolicy->write(writer, QStringLiteral("sizepolicy"));
break;
- }
- case Size: {
- DomSize *v = elementSize();
- if (v != 0)
- v->write(writer, QStringLiteral("size"));
+
+ case Size:
+ if (m_size != nullptr)
+ m_size->write(writer, QStringLiteral("size"));
break;
- }
- case String: {
- DomString *v = elementString();
- if (v != 0)
- v->write(writer, QStringLiteral("string"));
+
+ case String:
+ if (m_string != nullptr)
+ m_string->write(writer, QStringLiteral("string"));
break;
- }
- case StringList: {
- DomStringList *v = elementStringList();
- if (v != 0)
- v->write(writer, QStringLiteral("stringlist"));
+
+ case StringList:
+ if (m_stringList != nullptr)
+ m_stringList->write(writer, QStringLiteral("stringlist"));
break;
- }
- case Number: {
+
+ case Number:
writer.writeTextElement(QStringLiteral("number"), QString::number(elementNumber()));
break;
- }
- case Float: {
+
+ case Float:
writer.writeTextElement(QStringLiteral("float"), QString::number(elementFloat(), 'f', 8));
break;
- }
- case Double: {
+
+ case Double:
writer.writeTextElement(QStringLiteral("double"), QString::number(elementDouble(), 'f', 15));
break;
- }
- case Date: {
- DomDate *v = elementDate();
- if (v != 0)
- v->write(writer, QStringLiteral("date"));
+
+ case Date:
+ if (m_date != nullptr)
+ m_date->write(writer, QStringLiteral("date"));
break;
- }
- case Time: {
- DomTime *v = elementTime();
- if (v != 0)
- v->write(writer, QStringLiteral("time"));
+
+ case Time:
+ if (m_time != nullptr)
+ m_time->write(writer, QStringLiteral("time"));
break;
- }
- case DateTime: {
- DomDateTime *v = elementDateTime();
- if (v != 0)
- v->write(writer, QStringLiteral("datetime"));
+
+ case DateTime:
+ if (m_dateTime != nullptr)
+ m_dateTime->write(writer, QStringLiteral("datetime"));
break;
- }
- case PointF: {
- DomPointF *v = elementPointF();
- if (v != 0)
- v->write(writer, QStringLiteral("pointf"));
+
+ case PointF:
+ if (m_pointF != nullptr)
+ m_pointF->write(writer, QStringLiteral("pointf"));
break;
- }
- case RectF: {
- DomRectF *v = elementRectF();
- if (v != 0)
- v->write(writer, QStringLiteral("rectf"));
+
+ case RectF:
+ if (m_rectF != nullptr)
+ m_rectF->write(writer, QStringLiteral("rectf"));
break;
- }
- case SizeF: {
- DomSizeF *v = elementSizeF();
- if (v != 0)
- v->write(writer, QStringLiteral("sizef"));
+
+ case SizeF:
+ if (m_sizeF != nullptr)
+ m_sizeF->write(writer, QStringLiteral("sizef"));
break;
- }
- case LongLong: {
+
+ case LongLong:
writer.writeTextElement(QStringLiteral("longLong"), QString::number(elementLongLong()));
break;
- }
- case Char: {
- DomChar *v = elementChar();
- if (v != 0)
- v->write(writer, QStringLiteral("char"));
+
+ case Char:
+ if (m_char != nullptr)
+ m_char->write(writer, QStringLiteral("char"));
break;
- }
- case Url: {
- DomUrl *v = elementUrl();
- if (v != 0)
- v->write(writer, QStringLiteral("url"));
+
+ case Url:
+ if (m_url != nullptr)
+ m_url->write(writer, QStringLiteral("url"));
break;
- }
- case UInt: {
+
+ case UInt:
writer.writeTextElement(QStringLiteral("UInt"), QString::number(elementUInt()));
break;
- }
- case ULongLong: {
+
+ case ULongLong:
writer.writeTextElement(QStringLiteral("uLongLong"), QString::number(elementULongLong()));
break;
- }
- case Brush: {
- DomBrush *v = elementBrush();
- if (v != 0)
- v->write(writer, QStringLiteral("brush"));
+
+ case Brush:
+ if (m_brush != nullptr)
+ m_brush->write(writer, QStringLiteral("brush"));
break;
- }
+
default:
break;
}
@@ -5344,7 +5273,7 @@ void DomProperty::setElementBool(const QString &a)
DomColor *DomProperty::takeElementColor()
{
DomColor *a = m_color;
- m_color = 0;
+ m_color = nullptr;
return a;
}
@@ -5386,7 +5315,7 @@ void DomProperty::setElementEnum(const QString &a)
DomFont *DomProperty::takeElementFont()
{
DomFont *a = m_font;
- m_font = 0;
+ m_font = nullptr;
return a;
}
@@ -5400,7 +5329,7 @@ void DomProperty::setElementFont(DomFont *a)
DomResourceIcon *DomProperty::takeElementIconSet()
{
DomResourceIcon *a = m_iconSet;
- m_iconSet = 0;
+ m_iconSet = nullptr;
return a;
}
@@ -5414,7 +5343,7 @@ void DomProperty::setElementIconSet(DomResourceIcon *a)
DomResourcePixmap *DomProperty::takeElementPixmap()
{
DomResourcePixmap *a = m_pixmap;
- m_pixmap = 0;
+ m_pixmap = nullptr;
return a;
}
@@ -5428,7 +5357,7 @@ void DomProperty::setElementPixmap(DomResourcePixmap *a)
DomPalette *DomProperty::takeElementPalette()
{
DomPalette *a = m_palette;
- m_palette = 0;
+ m_palette = nullptr;
return a;
}
@@ -5442,7 +5371,7 @@ void DomProperty::setElementPalette(DomPalette *a)
DomPoint *DomProperty::takeElementPoint()
{
DomPoint *a = m_point;
- m_point = 0;
+ m_point = nullptr;
return a;
}
@@ -5456,7 +5385,7 @@ void DomProperty::setElementPoint(DomPoint *a)
DomRect *DomProperty::takeElementRect()
{
DomRect *a = m_rect;
- m_rect = 0;
+ m_rect = nullptr;
return a;
}
@@ -5477,7 +5406,7 @@ void DomProperty::setElementSet(const QString &a)
DomLocale *DomProperty::takeElementLocale()
{
DomLocale *a = m_locale;
- m_locale = 0;
+ m_locale = nullptr;
return a;
}
@@ -5491,7 +5420,7 @@ void DomProperty::setElementLocale(DomLocale *a)
DomSizePolicy *DomProperty::takeElementSizePolicy()
{
DomSizePolicy *a = m_sizePolicy;
- m_sizePolicy = 0;
+ m_sizePolicy = nullptr;
return a;
}
@@ -5505,7 +5434,7 @@ void DomProperty::setElementSizePolicy(DomSizePolicy *a)
DomSize *DomProperty::takeElementSize()
{
DomSize *a = m_size;
- m_size = 0;
+ m_size = nullptr;
return a;
}
@@ -5519,7 +5448,7 @@ void DomProperty::setElementSize(DomSize *a)
DomString *DomProperty::takeElementString()
{
DomString *a = m_string;
- m_string = 0;
+ m_string = nullptr;
return a;
}
@@ -5533,7 +5462,7 @@ void DomProperty::setElementString(DomString *a)
DomStringList *DomProperty::takeElementStringList()
{
DomStringList *a = m_stringList;
- m_stringList = 0;
+ m_stringList = nullptr;
return a;
}
@@ -5568,7 +5497,7 @@ void DomProperty::setElementDouble(double a)
DomDate *DomProperty::takeElementDate()
{
DomDate *a = m_date;
- m_date = 0;
+ m_date = nullptr;
return a;
}
@@ -5582,7 +5511,7 @@ void DomProperty::setElementDate(DomDate *a)
DomTime *DomProperty::takeElementTime()
{
DomTime *a = m_time;
- m_time = 0;
+ m_time = nullptr;
return a;
}
@@ -5596,7 +5525,7 @@ void DomProperty::setElementTime(DomTime *a)
DomDateTime *DomProperty::takeElementDateTime()
{
DomDateTime *a = m_dateTime;
- m_dateTime = 0;
+ m_dateTime = nullptr;
return a;
}
@@ -5610,7 +5539,7 @@ void DomProperty::setElementDateTime(DomDateTime *a)
DomPointF *DomProperty::takeElementPointF()
{
DomPointF *a = m_pointF;
- m_pointF = 0;
+ m_pointF = nullptr;
return a;
}
@@ -5624,7 +5553,7 @@ void DomProperty::setElementPointF(DomPointF *a)
DomRectF *DomProperty::takeElementRectF()
{
DomRectF *a = m_rectF;
- m_rectF = 0;
+ m_rectF = nullptr;
return a;
}
@@ -5638,7 +5567,7 @@ void DomProperty::setElementRectF(DomRectF *a)
DomSizeF *DomProperty::takeElementSizeF()
{
DomSizeF *a = m_sizeF;
- m_sizeF = 0;
+ m_sizeF = nullptr;
return a;
}
@@ -5659,7 +5588,7 @@ void DomProperty::setElementLongLong(qlonglong a)
DomChar *DomProperty::takeElementChar()
{
DomChar *a = m_char;
- m_char = 0;
+ m_char = nullptr;
return a;
}
@@ -5673,7 +5602,7 @@ void DomProperty::setElementChar(DomChar *a)
DomUrl *DomProperty::takeElementUrl()
{
DomUrl *a = m_url;
- m_url = 0;
+ m_url = nullptr;
return a;
}
@@ -5701,7 +5630,7 @@ void DomProperty::setElementULongLong(qulonglong a)
DomBrush *DomProperty::takeElementBrush()
{
DomBrush *a = m_brush;
- m_brush = 0;
+ m_brush = nullptr;
return a;
}
@@ -5725,7 +5654,7 @@ void DomConnections::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("connection"), Qt::CaseInsensitive)) {
- DomConnection *v = new DomConnection();
+ auto *v = new DomConnection();
v->read(reader);
m_connection.append(v);
continue;
@@ -5785,7 +5714,7 @@ void DomConnection::read(QXmlStreamReader &reader)
continue;
}
if (!tag.compare(QLatin1String("hints"), Qt::CaseInsensitive)) {
- DomConnectionHints *v = new DomConnectionHints();
+ auto *v = new DomConnectionHints();
v->read(reader);
setElementHints(v);
continue;
@@ -5850,7 +5779,7 @@ void DomConnection::setElementSlot(const QString &a)
DomConnectionHints *DomConnection::takeElementHints()
{
DomConnectionHints *a = m_hints;
- m_hints = 0;
+ m_hints = nullptr;
m_children ^= Hints;
return a;
}
@@ -5885,7 +5814,7 @@ void DomConnection::clearElementSlot()
void DomConnection::clearElementHints()
{
delete m_hints;
- m_hints = 0;
+ m_hints = nullptr;
m_children &= ~Hints;
}
@@ -5902,7 +5831,7 @@ void DomConnectionHints::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("hint"), Qt::CaseInsensitive)) {
- DomConnectionHint *v = new DomConnectionHint();
+ auto *v = new DomConnectionHint();
v->read(reader);
m_hint.append(v);
continue;
@@ -5934,9 +5863,7 @@ void DomConnectionHints::setElementHint(const QVector<DomConnectionHint *> &a)
m_hint = a;
}
-DomConnectionHint::~DomConnectionHint()
-{
-}
+DomConnectionHint::~DomConnectionHint() = default;
void DomConnectionHint::read(QXmlStreamReader &reader)
{
@@ -6024,7 +5951,7 @@ void DomDesignerData::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
- DomProperty *v = new DomProperty();
+ auto *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
@@ -6127,13 +6054,13 @@ void DomPropertySpecifications::read(QXmlStreamReader &reader)
case QXmlStreamReader::StartElement : {
const QStringRef tag = reader.name();
if (!tag.compare(QLatin1String("tooltip"), Qt::CaseInsensitive)) {
- DomPropertyToolTip *v = new DomPropertyToolTip();
+ auto *v = new DomPropertyToolTip();
v->read(reader);
m_tooltip.append(v);
continue;
}
if (!tag.compare(QLatin1String("stringpropertyspecification"), Qt::CaseInsensitive)) {
- DomStringPropertySpecification *v = new DomStringPropertySpecification();
+ auto *v = new DomStringPropertySpecification();
v->read(reader);
m_stringpropertyspecification.append(v);
continue;
@@ -6174,9 +6101,7 @@ void DomPropertySpecifications::setElementStringpropertyspecification(const QVec
m_stringpropertyspecification = a;
}
-DomPropertyToolTip::~DomPropertyToolTip()
-{
-}
+DomPropertyToolTip::~DomPropertyToolTip() = default;
void DomPropertyToolTip::read(QXmlStreamReader &reader)
{
@@ -6215,9 +6140,7 @@ void DomPropertyToolTip::write(QXmlStreamWriter &writer, const QString &tagName)
writer.writeEndElement();
}
-DomStringPropertySpecification::~DomStringPropertySpecification()
-{
-}
+DomStringPropertySpecification::~DomStringPropertySpecification() = default;
void DomStringPropertySpecification::read(QXmlStreamReader &reader)
{
diff --git a/src/tools/uic/uic.cpp b/src/tools/uic/uic.cpp
index 8e4709c831..f275aaeb29 100644
--- a/src/tools/uic/uic.cpp
+++ b/src/tools/uic/uic.cpp
@@ -56,9 +56,7 @@ Uic::Uic(Driver *d)
{
}
-Uic::~Uic()
-{
-}
+Uic::~Uic() = default;
bool Uic::printDependencies()
{
@@ -249,8 +247,12 @@ bool Uic::write(DomUI *ui)
}
pixFunction = ui->elementPixmapFunction();
- if (pixFunction == QLatin1String("QPixmap::fromMimeSource"))
- pixFunction = QLatin1String("qPixmapFromMimeSource");
+ if (pixFunction == QLatin1String("QPixmap::fromMimeSource")
+ || pixFunction == QLatin1String("qPixmapFromMimeSource")) {
+ fprintf(stderr, "%s: Warning: Obsolete pixmap function '%s' specified in the UI file.\n",
+ qPrintable(opt.messagePrefix()), qPrintable(pixFunction));
+ pixFunction.clear();
+ }
info.acceptUI(ui);
cWidgetsInfo.acceptUI(ui);
diff --git a/src/tools/uic/uic.h b/src/tools/uic/uic.h
index e00dc595bc..1c229bc516 100644
--- a/src/tools/uic/uic.h
+++ b/src/tools/uic/uic.h
@@ -53,6 +53,7 @@ struct Option;
class Uic
{
+ Q_DISABLE_COPY(Uic)
public:
Uic(Driver *driver);
~Uic();
diff --git a/src/tools/uic/utils.h b/src/tools/uic/utils.h
index 18b361fb81..3f32a532ca 100644
--- a/src/tools/uic/utils.h
+++ b/src/tools/uic/utils.h
@@ -42,27 +42,18 @@ inline bool toBool(const QString &str)
inline QString toString(const DomString *str)
{ return str ? str->text() : QString(); }
-enum StringFlags {
- Utf8String = 0x1,
- MultiLineString = 0x2
-};
-
-inline QString fixString(const QString &str, const QString &indent,
- unsigned *stringFlags = 0)
+inline QString fixString(const QString &str, const QString &indent)
{
QString cursegment;
QStringList result;
const QByteArray utf8 = str.toUtf8();
const int utf8Length = utf8.length();
- unsigned flags = 0;
-
for (int i = 0; i < utf8Length; ++i) {
const uchar cbyte = utf8.at(i);
if (cbyte >= 0x80) {
cursegment += QLatin1Char('\\');
cursegment += QString::number(cbyte, 8);
- flags |= Utf8String;
} else {
switch(cbyte) {
case '\\':
@@ -72,7 +63,6 @@ inline QString fixString(const QString &str, const QString &indent,
case '\r':
break;
case '\n':
- flags |= MultiLineString;
cursegment += QLatin1String("\\n\"\n\""); break;
default:
cursegment += QLatin1Char(cbyte);
@@ -98,24 +88,14 @@ inline QString fixString(const QString &str, const QString &indent,
rc += result.join(joinstr);
rc += QLatin1Char('"');
- if (result.size() > 1)
- flags |= MultiLineString;
-
- if (stringFlags)
- *stringFlags = flags;
-
return rc;
}
inline QHash<QString, DomProperty *> propertyMap(const QList<DomProperty *> &properties)
{
QHash<QString, DomProperty *> map;
-
- for (int i=0; i<properties.size(); ++i) {
- DomProperty *p = properties.at(i);
- map.insert(p->attributeName(), p);
- }
-
+ for (DomProperty *p : properties)
+ map.insert(p->attributeName(), p);
return map;
}
diff --git a/src/widgets/accessible/complexwidgets.cpp b/src/widgets/accessible/complexwidgets.cpp
index 6cdc06d702..63c6fbb9bb 100644
--- a/src/widgets/accessible/complexwidgets.cpp
+++ b/src/widgets/accessible/complexwidgets.cpp
@@ -120,7 +120,14 @@ public:
return rec;
}
- bool isValid() const override { return m_parent.data() && m_parent->count() > m_index; }
+ bool isValid() const override {
+ if (m_parent) {
+ if (static_cast<QWidget *>(m_parent.data())->d_func()->data.in_destructor)
+ return false;
+ return m_parent->count() > m_index;
+ }
+ return false;
+ }
QAccessibleInterface *childAt(int, int) const override { return 0; }
int childCount() const override { return 0; }
@@ -199,7 +206,7 @@ QAccessibleTabBar::QAccessibleTabBar(QWidget *w)
QAccessibleTabBar::~QAccessibleTabBar()
{
- foreach (QAccessible::Id id, m_childInterfaces)
+ for (QAccessible::Id id : qAsConst(m_childInterfaces))
QAccessible::deleteAccessibleInterface(id);
}
diff --git a/src/widgets/accessible/complexwidgets_p.h b/src/widgets/accessible/complexwidgets_p.h
index 96db2dab70..e7a32c7264 100644
--- a/src/widgets/accessible/complexwidgets_p.h
+++ b/src/widgets/accessible/complexwidgets_p.h
@@ -90,8 +90,6 @@ public:
int indexOfChild(const QAccessibleInterface *child) const override;
bool isValid() const override;
QAccessibleInterface *childAt(int x, int y) const override;
-
-//protected:
QAbstractScrollArea *abstractScrollArea() const;
private:
diff --git a/src/widgets/accessible/itemviews.cpp b/src/widgets/accessible/itemviews.cpp
index 4d37400dc9..51cfaa7f5e 100644
--- a/src/widgets/accessible/itemviews.cpp
+++ b/src/widgets/accessible/itemviews.cpp
@@ -110,12 +110,12 @@ QAccessibleTable::QAccessibleTable(QWidget *w)
bool QAccessibleTable::isValid() const
{
- return (view() && !qobject_cast<QWidget*>(view())->d_func()->data.in_destructor);
+ return view() && !qt_widget_private(view())->data.in_destructor;
}
QAccessibleTable::~QAccessibleTable()
{
- Q_FOREACH (QAccessible::Id id, childToId)
+ for (QAccessible::Id id : qAsConst(childToId))
QAccessible::deleteAccessibleInterface(id);
}
@@ -221,7 +221,7 @@ QList<QAccessibleInterface *> QAccessibleTable::selectedCells() const
return cells;
const QModelIndexList selectedIndexes = view()->selectionModel()->selectedIndexes();
cells.reserve(selectedIndexes.size());
- Q_FOREACH (const QModelIndex &index, selectedIndexes)
+ for (const QModelIndex &index : selectedIndexes)
cells.append(child(logicalIndex(index)));
return cells;
}
@@ -233,7 +233,7 @@ QList<int> QAccessibleTable::selectedColumns() const
QList<int> columns;
const QModelIndexList selectedColumns = view()->selectionModel()->selectedColumns();
columns.reserve(selectedColumns.size());
- Q_FOREACH (const QModelIndex &index, selectedColumns)
+ for (const QModelIndex &index : selectedColumns)
columns.append(index.column());
return columns;
@@ -246,7 +246,7 @@ QList<int> QAccessibleTable::selectedRows() const
QList<int> rows;
const QModelIndexList selectedRows = view()->selectionModel()->selectedRows();
rows.reserve(selectedRows.size());
- Q_FOREACH (const QModelIndex &index, selectedRows)
+ for (const QModelIndex &index : selectedRows)
rows.append(index.row());
return rows;
@@ -553,7 +553,7 @@ void QAccessibleTable::modelChange(QAccessibleTableModelChangeEvent *event)
switch (event->modelChangeType()) {
case QAccessibleTableModelChangeEvent::ModelReset:
- Q_FOREACH (QAccessible::Id id, childToId)
+ for (QAccessible::Id id : qAsConst(childToId))
QAccessible::deleteAccessibleInterface(id);
childToId.clear();
break;
@@ -973,7 +973,7 @@ void QAccessibleTableCell::unselectCell()
{
QAbstractItemView::SelectionMode selectionMode = view->selectionMode();
- if (!m_index.isValid() || (selectionMode & QAbstractItemView::NoSelection))
+ if (!m_index.isValid() || (selectionMode == QAbstractItemView::NoSelection))
return;
QAccessibleTableInterface *cellTable = table()->tableInterface();
@@ -1091,7 +1091,8 @@ void QAccessibleTableCell::setText(QAccessible::Text /*t*/, const QString &text)
bool QAccessibleTableCell::isValid() const
{
- return view && view->model() && m_index.isValid();
+ return view && !qt_widget_private(view)->data.in_destructor
+ && view->model() && m_index.isValid();
}
QAccessibleInterface *QAccessibleTableCell::parent() const
@@ -1180,7 +1181,8 @@ void QAccessibleTableHeaderCell::setText(QAccessible::Text, const QString &)
bool QAccessibleTableHeaderCell::isValid() const
{
- return view && view->model() && (index >= 0)
+ return view && !qt_widget_private(view)->data.in_destructor
+ && view->model() && (index >= 0)
&& ((orientation == Qt::Horizontal) ? (index < view->model()->columnCount()) : (index < view->model()->rowCount()));
}
diff --git a/src/widgets/accessible/qaccessiblemenu.cpp b/src/widgets/accessible/qaccessiblemenu.cpp
index 8b3353f625..507584eb02 100644
--- a/src/widgets/accessible/qaccessiblemenu.cpp
+++ b/src/widgets/accessible/qaccessiblemenu.cpp
@@ -117,10 +117,9 @@ QAccessibleInterface *QAccessibleMenu::child(int index) const
QAccessibleInterface *QAccessibleMenu::parent() const
{
if (QAction *menuAction = menu()->menuAction()) {
- QList<QWidget *> parentCandidates;
- parentCandidates << menu()->parentWidget();
- parentCandidates << menuAction->associatedWidgets();
- foreach (QWidget *w, parentCandidates) {
+ const QList<QWidget*> parentCandidates =
+ QList<QWidget*>() << menu()->parentWidget() << menuAction->associatedWidgets();
+ for (QWidget *w : parentCandidates) {
if (qobject_cast<QMenu*>(w)
#if QT_CONFIG(menubar)
|| qobject_cast<QMenuBar*>(w)
diff --git a/src/widgets/accessible/qaccessiblewidgets.cpp b/src/widgets/accessible/qaccessiblewidgets.cpp
index 872ddcded5..0d87cc486d 100644
--- a/src/widgets/accessible/qaccessiblewidgets.cpp
+++ b/src/widgets/accessible/qaccessiblewidgets.cpp
@@ -569,7 +569,7 @@ QCalendarWidget *QAccessibleCalendarWidget::calendarWidget() const
QAbstractItemView *QAccessibleCalendarWidget::calendarView() const
{
- foreach (QObject *child, calendarWidget()->children()) {
+ for (QObject *child : calendarWidget()->children()) {
if (child->objectName() == QLatin1String("qt_calendar_calendarview"))
return static_cast<QAbstractItemView *>(child);
}
@@ -578,7 +578,7 @@ QAbstractItemView *QAccessibleCalendarWidget::calendarView() const
QWidget *QAccessibleCalendarWidget::navigationBar() const
{
- foreach (QObject *child, calendarWidget()->children()) {
+ for (QObject *child : calendarWidget()->children()) {
if (child->objectName() == QLatin1String("qt_calendar_navigationbar"))
return static_cast<QWidget *>(child);
}
diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp
index 99946d341d..4aa680af61 100644
--- a/src/widgets/dialogs/qcolordialog.cpp
+++ b/src/widgets/dialogs/qcolordialog.cpp
@@ -2123,7 +2123,6 @@ void QColorDialog::setVisible(bool visible)
}
/*!
- \overload
\since 4.5
Opens the dialog and connects its colorSelected() signal to the slot specified
@@ -2162,6 +2161,7 @@ QColor QColorDialog::getColor(const QColor &initial, QWidget *parent, const QStr
return dlg.selectedColor();
}
+#if QT_DEPRECATED_SINCE(5, 12)
/*!
\obsolete
@@ -2169,7 +2169,7 @@ QColor QColorDialog::getColor(const QColor &initial, QWidget *parent, const QStr
and an alpha channel (transparency) value. The color+alpha is
initially set to \a initial. The dialog is a child of \a parent.
- If \a ok is non-null, \e *\a ok is set to true if the user clicked
+ If \a ok is non-null, \e {*ok} is set to true if the user clicked
\uicontrol{OK}, and to false if the user clicked Cancel.
If the user clicks Cancel, the \a initial value is returned.
@@ -2187,6 +2187,7 @@ QRgb QColorDialog::getRgba(QRgb initial, bool *ok, QWidget *parent)
*ok = color.isValid();
return result;
}
+#endif
/*!
Destroys the color dialog.
diff --git a/src/widgets/dialogs/qcolordialog.h b/src/widgets/dialogs/qcolordialog.h
index 6451ff9bde..cdbe0e7fb4 100644
--- a/src/widgets/dialogs/qcolordialog.h
+++ b/src/widgets/dialogs/qcolordialog.h
@@ -92,8 +92,9 @@ public:
const QString &title = QString(),
ColorDialogOptions options = ColorDialogOptions());
- // obsolete
- static QRgb getRgba(QRgb rgba = 0xffffffff, bool *ok = nullptr, QWidget *parent = nullptr);
+#if QT_DEPRECATED_SINCE(5, 12)
+ QT_DEPRECATED_X("Use getColor()") static QRgb getRgba(QRgb rgba = 0xffffffff, bool *ok = nullptr, QWidget *parent = nullptr);
+#endif
static int customCount();
static QColor customColor(int index);
diff --git a/src/widgets/dialogs/qdialog.cpp b/src/widgets/dialogs/qdialog.cpp
index f5db4481ee..06f0393b4c 100644
--- a/src/widgets/dialogs/qdialog.cpp
+++ b/src/widgets/dialogs/qdialog.cpp
@@ -100,6 +100,10 @@ static inline int themeDialogType(const QDialog *dialog)
if (qobject_cast<const QErrorMessage *>(dialog))
return QPlatformTheme::MessageDialog;
#endif
+#if !QT_CONFIG(filedialog) && !QT_CONFIG(colordialog) && !QT_CONFIG(fontdialog) && \
+ !QT_CONFIG(messagebox) && !QT_CONFIG(errormessage)
+ Q_UNUSED(dialog);
+#endif
return -1;
}
@@ -514,6 +518,13 @@ void QDialog::open()
interaction with the parent window is blocked while the dialog is open.
By default, the dialog is application modal.
+ \note Avoid using this function; instead, use \c{open()}. Unlike exec(),
+ open() is asynchronous, and does not spin an additional event loop. This
+ prevents a series of dangerous bugs from happening (e.g. deleting the
+ dialog's parent while the dialog is open via exec()). When using open() you
+ can connect to the finished() signal of QDialog to be notified when the
+ dialog is closed.
+
\sa open(), show(), result(), setWindowModality()
*/
@@ -560,9 +571,12 @@ int QDialog::exec()
}
/*!
- Closes the dialog and sets its result code to \a r. If this dialog
- is shown with exec(), done() causes the local event loop to finish,
- and exec() to return \a r.
+ Closes the dialog and sets its result code to \a r. The finished() signal
+ will emit \a r; if \a r is QDialog::Accepted or QDialog::Rejected, the
+ accepted() or the rejected() signals will also be emitted, respectively.
+
+ If this dialog is shown with exec(), done() also causes the local event loop
+ to finish, and exec() to return \a r.
As with QWidget::close(), done() deletes the dialog if the
Qt::WA_DeleteOnClose flag is set. If the dialog is the application's
diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp
index 778e8556c7..5c6c03d3aa 100644
--- a/src/widgets/dialogs/qfiledialog.cpp
+++ b/src/widgets/dialogs/qfiledialog.cpp
@@ -519,7 +519,7 @@ void QFileDialog::changeEvent(QEvent *e)
QFileDialogPrivate::QFileDialogPrivate()
:
-#ifndef QT_NO_PROXYMODEL
+#if QT_CONFIG(proxymodel)
proxyModel(0),
#endif
model(0),
@@ -665,7 +665,7 @@ void QFileDialogPrivate::retranslateStrings()
QList<QAction*> actions = qFileDialogUi->treeView->header()->actions();
QAbstractItemModel *abstractModel = model;
-#ifndef QT_NO_PROXYMODEL
+#if QT_CONFIG(proxymodel)
if (proxyModel)
abstractModel = proxyModel;
#endif
@@ -804,8 +804,6 @@ QFileDialog::Options QFileDialog::options() const
}
/*!
- \overload
-
\since 4.5
This function connects one of its signals to the slot specified by \a receiver
@@ -1049,10 +1047,15 @@ void QFileDialog::selectFile(const QString &filename)
return;
if (!d->usingWidgets()) {
- QUrl url = QUrl::fromLocalFile(filename);
+ QUrl url;
if (QFileInfo(filename).isRelative()) {
- QDir dir(d->options->initialDirectory().toLocalFile());
- url = QUrl::fromLocalFile(dir.absoluteFilePath(filename));
+ url = d->options->initialDirectory();
+ QString path = url.path();
+ if (!path.endsWith(QLatin1Char('/')))
+ path += QLatin1Char('/');
+ url.setPath(path + filename);
+ } else {
+ url = QUrl::fromLocalFile(filename);
}
d->selectFile_sys(url);
d->options->setInitiallySelectedFiles(QList<QUrl>() << url);
@@ -1110,7 +1113,7 @@ Q_AUTOTEST_EXPORT QString qt_tildeExpansion(const QString &path)
const QString homePath = QDir::homePath();
#else
const QByteArray userName = path.midRef(1, separatorPosition - 1).toLocal8Bit();
-# if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD)
+# if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_WASM)
passwd pw;
passwd *tmpPw;
char buf[200];
@@ -2108,9 +2111,7 @@ QString QFileDialog::labelText(DialogLabel label) const
strings. If you want multiple filters, separate them with ';;', for
example:
- \code
- "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)"
- \endcode
+ \snippet code/src_gui_dialogs_qfiledialog.cpp 14
The \a options argument holds various options about how to run the dialog,
see the QFileDialog::Option enum for more information on the flags you can
@@ -2223,9 +2224,7 @@ QUrl QFileDialog::getOpenFileUrl(QWidget *parent,
\a selectedFilter and \a filter may be empty strings. If you need multiple
filters, separate them with ';;', for instance:
- \code
- "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)"
- \endcode
+ \snippet code/src_gui_dialogs_qfiledialog.cpp 14
The dialog's caption is set to \a caption. If \a caption is not specified
then a default caption will be used.
@@ -2339,9 +2338,7 @@ QList<QUrl> QFileDialog::getOpenFileUrls(QWidget *parent,
parameters \a dir, \a selectedFilter, and \a filter may be empty strings.
Multiple filters are separated with ';;'. For instance:
- \code
- "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)"
- \endcode
+ \snippet code/src_gui_dialogs_qfiledialog.cpp 14
The \a options argument holds various options about how to run the dialog,
see the QFileDialog::Option enum for more information on the flags you can
@@ -2815,7 +2812,7 @@ bool QFileDialogPrivate::restoreWidgetState(QStringList &history, int splitterPo
QList<QAction*> actions = headerView->actions();
QAbstractItemModel *abstractModel = model;
-#ifndef QT_NO_PROXYMODEL
+#if QT_CONFIG(proxymodel)
if (proxyModel)
abstractModel = proxyModel;
#endif
@@ -2984,7 +2981,7 @@ void QFileDialogPrivate::createWidgets()
q, SLOT(_q_showHeader(QAction*)));;
QAbstractItemModel *abstractModel = model;
-#ifndef QT_NO_PROXYMODEL
+#if QT_CONFIG(proxymodel)
if (proxyModel)
abstractModel = proxyModel;
#endif
@@ -3065,7 +3062,7 @@ void QFileDialogPrivate::_q_showHeader(QAction *action)
qFileDialogUi->treeView->header()->setSectionHidden(actionGroup->actions().indexOf(action) + 1, !action->isChecked());
}
-#ifndef QT_NO_PROXYMODEL
+#if QT_CONFIG(proxymodel)
/*!
\since 4.3
@@ -3143,7 +3140,7 @@ QAbstractProxyModel *QFileDialog::proxyModel() const
Q_D(const QFileDialog);
return d->proxyModel;
}
-#endif // QT_NO_PROXYMODEL
+#endif // QT_CONFIG(proxymodel)
/*!
\internal
diff --git a/src/widgets/dialogs/qfiledialog.h b/src/widgets/dialogs/qfiledialog.h
index b9a49d3d18..a4d289a77a 100644
--- a/src/widgets/dialogs/qfiledialog.h
+++ b/src/widgets/dialogs/qfiledialog.h
@@ -178,7 +178,7 @@ public:
void setSupportedSchemes(const QStringList &schemes);
QStringList supportedSchemes() const;
-#ifndef QT_NO_PROXYMODEL
+#if QT_CONFIG(proxymodel)
void setProxyModel(QAbstractProxyModel *model);
QAbstractProxyModel *proxyModel() const;
#endif
diff --git a/src/widgets/dialogs/qfiledialog_p.h b/src/widgets/dialogs/qfiledialog_p.h
index 17290381d3..3a93a53911 100644
--- a/src/widgets/dialogs/qfiledialog_p.h
+++ b/src/widgets/dialogs/qfiledialog_p.h
@@ -227,7 +227,7 @@ public:
void _q_fileRenamed(const QString &path, const QString &oldName, const QString &newName);
// layout
-#ifndef QT_NO_PROXYMODEL
+#if QT_CONFIG(proxymodel)
QAbstractProxyModel *proxyModel;
#endif
@@ -346,17 +346,17 @@ private:
};
QModelIndex QFileDialogPrivate::mapToSource(const QModelIndex &index) const {
-#ifdef QT_NO_PROXYMODEL
- return index;
-#else
+#if QT_CONFIG(proxymodel)
return proxyModel ? proxyModel->mapToSource(index) : index;
+#else
+ return index;
#endif
}
QModelIndex QFileDialogPrivate::mapFromSource(const QModelIndex &index) const {
-#ifdef QT_NO_PROXYMODEL
- return index;
-#else
+#if QT_CONFIG(proxymodel)
return proxyModel ? proxyModel->mapFromSource(index) : index;
+#else
+ return index;
#endif
}
diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp
index 3a30cb5b2a..8b3549c3f5 100644
--- a/src/widgets/dialogs/qfilesystemmodel.cpp
+++ b/src/widgets/dialogs/qfilesystemmodel.cpp
@@ -48,6 +48,9 @@
#endif
#include <qapplication.h>
#include <QtCore/qcollator.h>
+#if QT_CONFIG(regularexpression)
+# include <QtCore/qregularexpression.h>
+#endif
#include <algorithm>
@@ -1580,7 +1583,7 @@ bool QFileSystemModel::nameFilterDisables() const
void QFileSystemModel::setNameFilters(const QStringList &filters)
{
// Prep the regexp's ahead of time
-#ifndef QT_NO_REGEXP
+#if QT_CONFIG(regularexpression)
Q_D(QFileSystemModel);
if (!d->bypassFilters.isEmpty()) {
@@ -1601,11 +1604,7 @@ void QFileSystemModel::setNameFilters(const QStringList &filters)
}
}
- d->nameFilters.clear();
- const Qt::CaseSensitivity caseSensitive =
- (filter() & QDir::CaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive;
- for (const auto &filter : filters)
- d->nameFilters << QRegExp(filter, caseSensitive, QRegExp::Wildcard);
+ d->nameFilters = filters;
d->forceSort = true;
d->delayedSort();
#endif
@@ -1616,16 +1615,12 @@ void QFileSystemModel::setNameFilters(const QStringList &filters)
*/
QStringList QFileSystemModel::nameFilters() const
{
+#if QT_CONFIG(regularexpression)
Q_D(const QFileSystemModel);
- QStringList filters;
-#ifndef QT_NO_REGEXP
- const int numNameFilters = d->nameFilters.size();
- filters.reserve(numNameFilters);
- for (int i = 0; i < numNameFilters; ++i) {
- filters << d->nameFilters.at(i).pattern();
- }
+ return d->nameFilters;
+#else
+ return QStringList();
#endif
- return filters;
}
/*!
@@ -2026,15 +2021,21 @@ bool QFileSystemModelPrivate::filtersAcceptsNode(const QFileSystemNode *node) co
*/
bool QFileSystemModelPrivate::passNameFilters(const QFileSystemNode *node) const
{
-#ifndef QT_NO_REGEXP
+#if QT_CONFIG(regularexpression)
if (nameFilters.isEmpty())
return true;
// Check the name regularexpression filters
if (!(node->isDir() && (filters & QDir::AllDirs))) {
+ const QRegularExpression::PatternOptions options =
+ (filters & QDir::CaseSensitive) ? QRegularExpression::NoPatternOption
+ : QRegularExpression::CaseInsensitiveOption;
+
for (const auto &nameFilter : nameFilters) {
- QRegExp copy = nameFilter;
- if (copy.exactMatch(node->fileName))
+ const QString wildcard = QRegularExpression::wildcardToRegularExpression(nameFilter);
+ QRegularExpression rx(QRegularExpression::anchoredPattern(wildcard), options);
+ QRegularExpressionMatch match = rx.match(node->fileName);
+ if (match.hasMatch())
return true;
}
return false;
diff --git a/src/widgets/dialogs/qfilesystemmodel_p.h b/src/widgets/dialogs/qfilesystemmodel_p.h
index a2a02e2d41..9c432e1ae6 100644
--- a/src/widgets/dialogs/qfilesystemmodel_p.h
+++ b/src/widgets/dialogs/qfilesystemmodel_p.h
@@ -294,8 +294,6 @@ public:
void _q_fileSystemChanged(const QString &path, const QVector<QPair<QString, QFileInfo> > &);
void _q_resolvedName(const QString &fileName, const QString &resolvedName);
- static int naturalCompare(const QString &s1, const QString &s2, Qt::CaseSensitivity cs);
-
QDir rootDir;
#if QT_CONFIG(filesystemwatcher)
# ifdef Q_OS_WIN
@@ -317,8 +315,8 @@ public:
//It enable a sort which is not recursive, it means
//we sort only what we see.
bool disableRecursiveSort;
-#ifndef QT_NO_REGEXP
- QList<QRegExp> nameFilters;
+#if QT_CONFIG(regularexpression)
+ QStringList nameFilters;
#endif
QHash<QString, QString> resolvedSymLinks;
diff --git a/src/widgets/dialogs/qfontdialog.cpp b/src/widgets/dialogs/qfontdialog.cpp
index 5f912c582f..477c6bd540 100644
--- a/src/widgets/dialogs/qfontdialog.cpp
+++ b/src/widgets/dialogs/qfontdialog.cpp
@@ -931,7 +931,6 @@ QFontDialog::FontDialogOptions QFontDialog::options() const
/*!
\since 4.5
- \overload
Opens the dialog and connects its fontSelected() signal to the slot specified
by \a receiver and \a member.
diff --git a/src/widgets/dialogs/qinputdialog.cpp b/src/widgets/dialogs/qinputdialog.cpp
index 5c6e0f45a5..5a7d6edddf 100644
--- a/src/widgets/dialogs/qinputdialog.cpp
+++ b/src/widgets/dialogs/qinputdialog.cpp
@@ -1070,7 +1070,6 @@ QString QInputDialog::cancelButtonText() const
/*!
\since 4.5
- \overload
This function connects one of its signals to the slot specified by \a receiver
and \a member. The specific signal depends on the arguments that are specified
@@ -1180,7 +1179,7 @@ void QInputDialog::done(int result)
\a inputMethodHints is the input method hints that will be used in the
edit widget if an input method is active.
- If \a ok is nonnull \e *\a ok will be set to true if the user pressed
+ If \a ok is nonnull \e {*ok} will be set to true if the user pressed
\uicontrol OK and to false if the user pressed \uicontrol Cancel. The dialog's parent
is \a parent. The dialog will be modal and uses the specified widget
\a flags.
@@ -1228,7 +1227,7 @@ QString QInputDialog::getText(QWidget *parent, const QString &title, const QStri
\a inputMethodHints is the input method hints that will be used in the
edit widget if an input method is active.
- If \a ok is nonnull \e *\a ok will be set to true if the user pressed
+ If \a ok is nonnull \e {*ok} will be set to true if the user pressed
\uicontrol OK and to false if the user pressed \uicontrol Cancel. The dialog's parent
is \a parent. The dialog will be modal and uses the specified widget
\a flags.
@@ -1436,7 +1435,7 @@ double QInputDialog::getDouble(QWidget *parent, const QString &title, const QStr
If \a editable is true the user can enter their own text; otherwise, the
user may only select one of the existing items.
- If \a ok is nonnull \e *\a ok will be set to true if the user pressed
+ If \a ok is nonnull \e {*ok} will be set to true if the user pressed
\uicontrol OK and to false if the user pressed \uicontrol Cancel. The dialog's parent
is \a parent. The dialog will be modal and uses the widget \a flags.
diff --git a/src/widgets/dialogs/qmessagebox.cpp b/src/widgets/dialogs/qmessagebox.cpp
index 6de952a1d3..99157747dd 100644
--- a/src/widgets/dialogs/qmessagebox.cpp
+++ b/src/widgets/dialogs/qmessagebox.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -64,6 +64,7 @@
#include <QtGui/qfont.h>
#include <QtGui/qfontmetrics.h>
#include <QtGui/qclipboard.h>
+#include "private/qabstractbutton_p.h"
#include <private/qdesktopwidget_p.h>
#ifdef Q_OS_WIN
@@ -492,9 +493,17 @@ void QMessageBoxPrivate::_q_buttonClicked(QAbstractButton *button)
void QMessageBoxPrivate::_q_clicked(QPlatformDialogHelper::StandardButton button, QPlatformDialogHelper::ButtonRole role)
{
- Q_UNUSED(role);
Q_Q(QMessageBox);
- q->done(button);
+ if (button > QPlatformDialogHelper::LastButton) {
+ // It's a custom button, and the QPushButton in options is just a proxy
+ // for the button on the platform dialog. Simulate the user clicking it.
+ clickedButton = static_cast<QAbstractButton *>(options->customButton(button)->button);
+ Q_ASSERT(clickedButton);
+ clickedButton->click();
+ q->done(role);
+ } else {
+ q->done(button);
+ }
}
/*!
@@ -831,6 +840,8 @@ void QMessageBox::addButton(QAbstractButton *button, ButtonRole role)
if (!button)
return;
removeButton(button);
+ d->options->addButton(button->text(), static_cast<QPlatformDialogHelper::ButtonRole>(role),
+ button);
d->buttonBox->addButton(button, (QDialogButtonBox::ButtonRole)role);
d->customButtonList.append(button);
d->autoAddOkButton = false;
@@ -1064,7 +1075,7 @@ void QMessageBoxPrivate::detectEscapeButton()
or 0 if the user hit the \uicontrol Esc key and
no \l{setEscapeButton()}{escape button} was set.
- If exec() hasn't been called yet, returns 0.
+ If exec() hasn't been called yet, returns nullptr.
Example:
@@ -1082,7 +1093,7 @@ QAbstractButton *QMessageBox::clickedButton() const
\since 4.2
Returns the button that should be the message box's
- \l{QPushButton::setDefault()}{default button}. Returns 0
+ \l{QPushButton::setDefault()}{default button}. Returns nullptr
if no default button was set.
\sa addButton(), QPushButton::setDefault()
@@ -1489,8 +1500,6 @@ void QMessageBox::keyPressEvent(QKeyEvent *e)
}
/*!
- \overload
-
Opens the dialog and connects its finished() or buttonClicked() signal to
the slot specified by \a receiver and \a member. If the slot in \a member
has a pointer for its first parameter the connection is to buttonClicked(),
@@ -2678,7 +2687,11 @@ void QMessageBoxPrivate::helperPrepareShow(QPlatformDialogHelper *)
void QMessageBoxPrivate::helperDone(QDialog::DialogCode code, QPlatformDialogHelper *)
{
Q_Q(QMessageBox);
- clickedButton = q->button(QMessageBox::StandardButton(code));
+ QAbstractButton *button = q->button(QMessageBox::StandardButton(code));
+ // If it was a custom button, a custom ID was used, so we won't get a valid pointer here.
+ // In that case, clickedButton has already been set in _q_buttonClicked.
+ if (button)
+ clickedButton = button;
}
/*!
@@ -2730,7 +2743,7 @@ QPixmap QMessageBox::standardIcon(Icon icon)
Shows the message box as a \l{QDialog#Modal Dialogs}{modal dialog},
blocking until the user closes it.
- When using a QMessageBox with standard buttons, this functions returns a
+ When using a QMessageBox with standard buttons, this function returns a
\l StandardButton value indicating the standard button that was clicked.
When using QMessageBox with custom buttons, this function returns an
opaque value; use clickedButton() to determine which button was clicked.
diff --git a/src/widgets/dialogs/qprogressdialog.cpp b/src/widgets/dialogs/qprogressdialog.cpp
index a276e28a0c..4bf78e2115 100644
--- a/src/widgets/dialogs/qprogressdialog.cpp
+++ b/src/widgets/dialogs/qprogressdialog.cpp
@@ -865,7 +865,6 @@ void QProgressDialog::forceShow()
/*!
\since 4.5
- \overload
Opens the dialog and connects its canceled() signal to the slot specified
by \a receiver and \a member.
diff --git a/src/widgets/dialogs/qwizard_win.cpp b/src/widgets/dialogs/qwizard_win.cpp
index 5ef304c9f1..aa9ad7f290 100644
--- a/src/widgets/dialogs/qwizard_win.cpp
+++ b/src/widgets/dialogs/qwizard_win.cpp
@@ -606,8 +606,8 @@ bool QVistaHelper::drawTitleText(QPainter *painter, const QString &text, const Q
// Set up the DC
const LOGFONT captionLogFont = getCaptionLogFont(hTheme);
const HFONT hCaptionFont = CreateFontIndirect(&captionLogFont);
- HBITMAP hOldBmp = (HBITMAP)SelectObject(dcMem, (HGDIOBJ) bmp);
- HFONT hOldFont = (HFONT)SelectObject(dcMem, (HGDIOBJ) hCaptionFont);
+ auto hOldBmp = reinterpret_cast<HBITMAP>(SelectObject(dcMem, (HGDIOBJ) bmp));
+ auto hOldFont = reinterpret_cast<HFONT>(SelectObject(dcMem, (HGDIOBJ) hCaptionFont));
// Draw the text!
DTTOPTS dto;
@@ -654,7 +654,7 @@ bool QVistaHelper::drawBlackRect(const QRect &rect, HDC hdc)
dib.bmiHeader.biCompression = BI_RGB;
bmp = CreateDIBSection(hdc, &dib, DIB_RGB_COLORS, NULL, NULL, 0);
- HBITMAP hOldBmp = (HBITMAP)SelectObject(dcMem, (HGDIOBJ) bmp);
+ auto hOldBmp = reinterpret_cast<HBITMAP>(SelectObject(dcMem, (HGDIOBJ) bmp));
BitBlt(hdc, rectDp.left(), rectDp.top(), rectDp.width(), rectDp.height(), dcMem, 0, 0, SRCCOPY);
SelectObject(dcMem, (HGDIOBJ) hOldBmp);
diff --git a/src/widgets/dialogs/qwizard_win_p.h b/src/widgets/dialogs/qwizard_win_p.h
index 7ca4899a1f..d302dedaa3 100644
--- a/src/widgets/dialogs/qwizard_win_p.h
+++ b/src/widgets/dialogs/qwizard_win_p.h
@@ -71,22 +71,23 @@ class QVistaBackButton : public QAbstractButton
public:
QVistaBackButton(QWidget *widget);
- QSize sizeHint() const;
- inline QSize minimumSizeHint() const
+ QSize sizeHint() const override;
+ inline QSize minimumSizeHint() const override
{ return sizeHint(); }
- void enterEvent(QEvent *event);
- void leaveEvent(QEvent *event);
- void paintEvent(QPaintEvent *event);
+ void enterEvent(QEvent *event) override;
+ void leaveEvent(QEvent *event) override;
+ void paintEvent(QPaintEvent *event) override;
};
class QWizard;
class QVistaHelper : public QObject
{
+ Q_DISABLE_COPY(QVistaHelper)
public:
QVistaHelper(QWizard *wizard);
- ~QVistaHelper();
+ ~QVistaHelper() override;
enum TitleBarChangeType { NormalTitleBar, ExtendedTitleBar };
void updateCustomMargins(bool vistaMargins);
bool setDWMTitleBar(TitleBarChangeType type);
@@ -133,7 +134,7 @@ private:
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
- bool eventFilter(QObject *obj, QEvent *event);
+ bool eventFilter(QObject *obj, QEvent *event) override;
static int instanceCount;
static VistaState cachedVistaState;
diff --git a/src/widgets/doc/images/gridlayout.png b/src/widgets/doc/images/qgridlayout.png
index ae76c0487b..ae76c0487b 100644
--- a/src/widgets/doc/images/gridlayout.png
+++ b/src/widgets/doc/images/qgridlayout.png
Binary files differ
diff --git a/src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp b/src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp
index 58f0ae560f..06cca37111 100644
--- a/src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp
+++ b/src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp
@@ -140,3 +140,7 @@ QFileDialog dialog(this);
dialog.setMimeTypeFilters(mimeTypeFilters);
dialog.exec();
//! [13]
+
+//! [14]
+"Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)"
+//! [14]
diff --git a/src/widgets/doc/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp b/src/widgets/doc/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp
index 8d8c63db9e..ebca9d5368 100644
--- a/src/widgets/doc/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp
+++ b/src/widgets/doc/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp
@@ -271,3 +271,18 @@ QRect deviceRect = xform.mapRect(rect).toAlignedRect();
view->viewport()->scroll(dx, dy, deviceRect);
//! [19]
+//! [20]
+item->setTransform(QTransform().rotate(angle), true);
+//! [20]
+
+//! [21]
+setTransform(QTransform::fromScale(sx, sy), true);
+//! [21]
+
+//! [22]
+setTransform(QTransform().shear(sh, sv), true);
+//! [22]
+
+//! [23]
+setTransform(QTransform::fromTranslate(dx, dy), true);
+//! [23]
diff --git a/src/widgets/doc/snippets/code/src_gui_kernel_qformlayout.cpp b/src/widgets/doc/snippets/code/src_gui_kernel_qformlayout.cpp
index eadf753ded..a2ac780a82 100644
--- a/src/widgets/doc/snippets/code/src_gui_kernel_qformlayout.cpp
+++ b/src/widgets/doc/snippets/code/src_gui_kernel_qformlayout.cpp
@@ -84,3 +84,51 @@ formLayout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint);
formLayout->setFormAlignment(Qt::AlignHCenter | Qt::AlignTop);
formLayout->setLabelAlignment(Qt::AlignLeft);
//! [2]
+
+//! [3]
+QFormLayout *flay = ...;
+QPointer<QLineEdit> le = new QLineEdit;
+flay->insertRow(2, "User:", le);
+// later:
+flay->removeRow(2); // le == nullptr at this point
+//! [3]
+
+//! [4]
+QFormLayout *flay = ...;
+QPointer<QLineEdit> le = new QLineEdit;
+flay->insertRow(2, "User:", le);
+// later:
+flay->removeRow(le); // le == nullptr at this point
+//! [4]
+
+//! [5]
+QFormLayout *flay = ...;
+QPointer<QVBoxLayout> vbl = new QVBoxLayout;
+flay->insertRow(2, "User:", vbl);
+// later:
+flay->removeRow(layout); // vbl == nullptr at this point
+//! [5]
+
+//! [6]
+QFormLayout *flay = ...;
+QPointer<QLineEdit> le = new QLineEdit;
+flay->insertRow(2, "User:", le);
+// later:
+QFormLayout::TakeRowResult result = flay->takeRow(2);
+//! [6]
+
+//! [7]
+QFormLayout *flay = ...;
+QPointer<QLineEdit> le = new QLineEdit;
+flay->insertRow(2, "User:", le);
+// later:
+QFormLayout::TakeRowResult result = flay->takeRow(widget);
+//! [7]
+
+//! [8]
+QFormLayout *flay = ...;
+QPointer<QVBoxLayout> vbl = new QVBoxLayout;
+flay->insertRow(2, "User:", vbl);
+// later:
+QFormLayout::TakeRowResult result = flay->takeRow(widget);
+//! [8]
diff --git a/src/widgets/doc/snippets/code/src_widgets_util_qscroller.cpp b/src/widgets/doc/snippets/code/src_widgets_util_qscroller.cpp
new file mode 100644
index 0000000000..2b3d825266
--- /dev/null
+++ b/src/widgets/doc/snippets/code/src_widgets_util_qscroller.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWidgets module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+ QWidget *w = ...;
+ QScroller::grabGesture(w, QScroller::LeftMouseButtonGesture);
+//! [0]
+
+//! [1]
+ QWidget *w = ...;
+ QScroller *scroller = QScroller::scroller(w);
+ scroller->scrollTo(QPointF(100, 100));
+//! [1]
diff --git a/src/widgets/doc/snippets/code/src_widgets_widgets_qmainwindow.cpp b/src/widgets/doc/snippets/code/src_widgets_widgets_qmainwindow.cpp
new file mode 100644
index 0000000000..8ebaaf3991
--- /dev/null
+++ b/src/widgets/doc/snippets/code/src_widgets_widgets_qmainwindow.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWidgets module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [0]
+ void MainWindow::createMenus()
+ {
+ fileMenu = menuBar()->addMenu(tr("&File"));
+ fileMenu->addAction(newAct);
+ fileMenu->addAction(openAct);
+ fileMenu->addAction(saveAct);
+//! [0]
+
+//! [1]
+ void MainWindow::createToolBars()
+ {
+ fileToolBar = addToolBar(tr("File"));
+ fileToolBar->addAction(newAct);
+//! [1]
+
+//! [2]
+ resizeDocks({blueWidget, yellowWidget}, {20 , 40}, Qt::Horizontal);
+//! [2]
diff --git a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc
index be6a068d65..43f9dda49a 100644
--- a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc
+++ b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc
@@ -520,7 +520,7 @@
user had manually called the corresponding QWidget::setPalette() and
QWidget::setFont() methods on all of the QWidgets targeted by the style
sheet. If this would have caused propagation in C++, it will cause
- propagation in style sheets and visa versa.
+ propagation in style sheets and vice versa.
\section1 Widgets Inside C++ Namespaces
diff --git a/src/widgets/graphicsview/qgraphicsanchorlayout.h b/src/widgets/graphicsview/qgraphicsanchorlayout.h
index e392be1568..9bea43dd8e 100644
--- a/src/widgets/graphicsview/qgraphicsanchorlayout.h
+++ b/src/widgets/graphicsview/qgraphicsanchorlayout.h
@@ -70,7 +70,6 @@ private:
Q_DECLARE_PRIVATE(QGraphicsAnchor)
friend class QGraphicsAnchorLayoutPrivate;
- friend struct AnchorData;
};
class Q_WIDGETS_EXPORT QGraphicsAnchorLayout : public QGraphicsLayout
diff --git a/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp b/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp
index 71027f00a2..008560d856 100644
--- a/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp
+++ b/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp
@@ -167,7 +167,7 @@ AnchorData::~AnchorData()
if (graphicsAnchor) {
// Remove reference to ourself to avoid double removal in
// QGraphicsAnchorPrivate dtor.
- graphicsAnchor->d_func()->data = 0;
+ QGraphicsAnchorPrivate::get(graphicsAnchor)->data = nullptr;
delete graphicsAnchor;
}
@@ -215,7 +215,7 @@ void AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo)
} else {
// It is a user-created anchor, fetch size information from the associated QGraphicsAnchor
Q_ASSERT(graphicsAnchor);
- QGraphicsAnchorPrivate *anchorPrivate = graphicsAnchor->d_func();
+ QGraphicsAnchorPrivate *anchorPrivate = QGraphicsAnchorPrivate::get(graphicsAnchor);
// Policy, min and max sizes are straightforward
policy = anchorPrivate->sizePolicy;
@@ -2526,7 +2526,7 @@ QGraphicsAnchorLayoutPrivate::getGraphParts(Orientation orientation)
// Check if this constraint have some overlap with current
// trunk variables...
- foreach (QSimplexVariable *ad, trunkVariables) {
+ for (QSimplexVariable *ad : qAsConst(trunkVariables)) {
if (c->variables.contains(ad)) {
match = true;
break;
diff --git a/src/widgets/graphicsview/qgraphicsanchorlayout_p.h b/src/widgets/graphicsview/qgraphicsanchorlayout_p.h
index 6b2408b2eb..699ca32bfe 100644
--- a/src/widgets/graphicsview/qgraphicsanchorlayout_p.h
+++ b/src/widgets/graphicsview/qgraphicsanchorlayout_p.h
@@ -73,6 +73,7 @@ QT_BEGIN_NAMESPACE
respectively.
*/
+namespace QtGraphicsAnchorLayout {
/*!
\internal
@@ -326,6 +327,9 @@ public:
QSet<AnchorData *> positives;
QSet<AnchorData *> negatives;
};
+} // namespace QtGraphicsAnchorLayout
+using namespace QtGraphicsAnchorLayout;
+
Q_DECLARE_TYPEINFO(GraphPath, Q_MOVABLE_TYPE);
class QGraphicsAnchorLayoutPrivate;
@@ -346,6 +350,9 @@ public:
void setSizePolicy(QSizePolicy::Policy policy);
+ static QGraphicsAnchorPrivate *get(QGraphicsAnchor *q)
+ { return q->d_func(); }
+
QGraphicsAnchorLayoutPrivate *layoutPrivate;
AnchorData *data;
diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp
index fdf21fb499..e81eab4c46 100644
--- a/src/widgets/graphicsview/qgraphicsitem.cpp
+++ b/src/widgets/graphicsview/qgraphicsitem.cpp
@@ -1598,7 +1598,7 @@ QGraphicsItem::~QGraphicsItem()
#ifndef QT_NO_GESTURES
if (d_ptr->isObject && !d_ptr->gestureContext.isEmpty()) {
QGraphicsObject *o = static_cast<QGraphicsObject *>(this);
- if (QGestureManager *manager = QGestureManager::instance()) {
+ if (QGestureManager *manager = QGestureManager::instance(QGestureManager::DontForceCreation)) {
const auto types = d_ptr->gestureContext.keys(); // FIXME: iterate over the map directly?
for (Qt::GestureType type : types)
manager->cleanupCachedGestures(o, type);
@@ -4666,9 +4666,7 @@ void QGraphicsItem::resetTransform()
Use
- \code
- item->setTransform(QTransform().rotate(angle), true);
- \endcode
+ \snippet code/src_gui_graphicsview_qgraphicsitem.cpp 20
instead.
@@ -4689,9 +4687,7 @@ void QGraphicsItem::resetTransform()
Use
- \code
- setTransform(QTransform::fromScale(sx, sy), true);
- \endcode
+ \snippet code/src_gui_graphicsview_qgraphicsitem.cpp 21
instead.
@@ -4712,9 +4708,7 @@ void QGraphicsItem::resetTransform()
Use
- \code
- setTransform(QTransform().shear(sh, sv), true);
- \endcode
+ \snippet code/src_gui_graphicsview_qgraphicsitem.cpp 22
instead.
@@ -4730,9 +4724,7 @@ void QGraphicsItem::resetTransform()
Use setPos() or setTransformOriginPoint() instead. For identical
behavior, use
- \code
- setTransform(QTransform::fromTranslate(dx, dy), true);
- \endcode
+ \snippet code/src_gui_graphicsview_qgraphicsitem.cpp 23
Translates the current item transformation by (\a dx, \a dy).
@@ -7310,7 +7302,7 @@ void QGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
selectedItems = d_ptr->scene->selectedItems();
initialPositions = d_ptr->scene->d_func()->movingItemsInitialPositions;
if (initialPositions.isEmpty()) {
- foreach (QGraphicsItem *item, selectedItems)
+ for (QGraphicsItem *item : qAsConst(selectedItems))
initialPositions[item] = item->pos();
initialPositions[this] = pos();
}
diff --git a/src/widgets/graphicsview/qgraphicsitem_p.h b/src/widgets/graphicsview/qgraphicsitem_p.h
index 9fc6c0794a..d586a22544 100644
--- a/src/widgets/graphicsview/qgraphicsitem_p.h
+++ b/src/widgets/graphicsview/qgraphicsitem_p.h
@@ -500,7 +500,9 @@ public:
quint32 filtersDescendantEvents : 1;
quint32 sceneTransformTranslateOnly : 1;
quint32 notifyBoundingRectChanged : 1;
-
+#ifdef Q_OS_WASM
+ unsigned char :0; //this aligns 64bit field for wasm see QTBUG-65259
+#endif
// New 32 bits
quint32 notifyInvalidated : 1;
quint32 mouseSetsFocus : 1;
diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp
index 37c631483a..bba992144d 100644
--- a/src/widgets/graphicsview/qgraphicsscene.cpp
+++ b/src/widgets/graphicsview/qgraphicsscene.cpp
@@ -297,6 +297,7 @@ QGraphicsScenePrivate::QGraphicsScenePrivate()
painterStateProtection(true),
sortCacheEnabled(false),
allItemsIgnoreTouchEvents(true),
+ focusOnTouch(true),
minimumRenderSize(0.0),
selectionChanging(0),
rectAdjust(2),
@@ -2393,6 +2394,7 @@ void QGraphicsScene::clear()
d->allItemsIgnoreHoverEvents = true;
d->allItemsUseDefaultCursor = true;
d->allItemsIgnoreTouchEvents = true;
+ d->focusOnTouch = true;
}
/*!
@@ -3215,7 +3217,8 @@ void QGraphicsScene::update(const QRectF &rect)
view->d_func()->updateRectF(rect);
}
} else {
- d->updatedRects << rect;
+ if (!d->updatedRects.contains(rect))
+ d->updatedRects << rect;
}
}
@@ -4331,7 +4334,8 @@ static void _q_paintIntoCache(QPixmap *pix, QGraphicsItem *item, const QRegion &
pix->fill(Qt::transparent);
pixmapPainter.begin(pix);
} else {
- subPix = QPixmap(br.size());
+ subPix = QPixmap(br.size() * pix->devicePixelRatio());
+ subPix.setDevicePixelRatio(pix->devicePixelRatio());
subPix.fill(Qt::transparent);
pixmapPainter.begin(&subPix);
pixmapPainter.translate(-br.topLeft());
@@ -4409,6 +4413,7 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
return;
}
+ const qreal devicePixelRatio = painter->device()->devicePixelRatio();
const qreal oldPainterOpacity = painter->opacity();
qreal newPainterOpacity = oldPainterOpacity;
QGraphicsProxyWidget *proxy = item->isWidget() ? qobject_cast<QGraphicsProxyWidget *>(static_cast<QGraphicsWidget *>(item)) : 0;
@@ -4428,6 +4433,7 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
// Fetch the off-screen transparent buffer and exposed area info.
QPixmapCache::Key pixmapKey;
QPixmap pix;
+
bool pixmapFound;
QGraphicsItemCache *itemCache = itemd->extraItemCache();
if (cacheMode == QGraphicsItem::ItemCoordinateCache) {
@@ -4442,18 +4448,20 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
// Render using item coordinate cache mode.
if (cacheMode == QGraphicsItem::ItemCoordinateCache) {
QSize pixmapSize;
- bool fixedCacheSize = false;
+ bool fixedCacheSize = itemCache->fixedSize.isValid();
QRect br = brect.toAlignedRect();
- if ((fixedCacheSize = itemCache->fixedSize.isValid())) {
+ if (fixedCacheSize) {
pixmapSize = itemCache->fixedSize;
} else {
pixmapSize = br.size();
}
+ pixmapSize *= devicePixelRatio;
+
// Create or recreate the pixmap.
int adjust = itemCache->fixedSize.isValid() ? 0 : 2;
QSize adjustSize(adjust*2, adjust*2);
- br.adjust(-adjust, -adjust, adjust, adjust);
+ br.adjust(-adjust / devicePixelRatio, -adjust / devicePixelRatio, adjust / devicePixelRatio, adjust / devicePixelRatio);
if (pix.isNull() || (!fixedCacheSize && (pixmapSize + adjustSize) != pix.size())) {
pix = QPixmap(pixmapSize + adjustSize);
itemCache->boundingRect = br;
@@ -4476,7 +4484,8 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
// Fit the item's bounding rect into the pixmap's coordinates.
QTransform itemToPixmap;
if (fixedCacheSize) {
- const QPointF scale(pixmapSize.width() / brect.width(), pixmapSize.height() / brect.height());
+ const QPointF scale((pixmapSize.width() / devicePixelRatio) / brect.width(),
+ (pixmapSize.height() / devicePixelRatio) / brect.height());
itemToPixmap.scale(scale.x(), scale.y());
}
itemToPixmap.translate(-br.x(), -br.y());
@@ -4498,6 +4507,7 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
styleOptionTmp.exposedRect = exposedRect;
// Render.
+ pix.setDevicePixelRatio(devicePixelRatio);
_q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(),
&styleOptionTmp, painterStateProtection);
@@ -4595,21 +4605,22 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
// Copy / "scroll" the old pixmap onto the new ole and calculate
// scrolled exposure.
- if (newCacheIndent != deviceData->cacheIndent || deviceRect.size() != pix.size()) {
+ if (newCacheIndent != deviceData->cacheIndent || deviceRect.size() != pix.size() / devicePixelRatio) {
QPoint diff = newCacheIndent - deviceData->cacheIndent;
- QPixmap newPix(deviceRect.size());
+ QPixmap newPix(deviceRect.size() * devicePixelRatio);
// ### Investigate removing this fill (test with Plasma and
// graphicssystem raster).
newPix.fill(Qt::transparent);
if (!pix.isNull()) {
+ newPix.setDevicePixelRatio(devicePixelRatio);
QPainter newPixPainter(&newPix);
newPixPainter.drawPixmap(-diff, pix);
newPixPainter.end();
}
QRegion exposed;
- exposed += newPix.rect();
+ exposed += QRect(QPoint(0,0), newPix.size() / devicePixelRatio);
if (!pix.isNull())
- exposed -= QRect(-diff, pix.size());
+ exposed -= QRect(-diff, pix.size() / devicePixelRatio);
scrollExposure = exposed;
pix = newPix;
@@ -4621,9 +4632,9 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
deviceData->cacheIndent = QPoint();
// Auto-adjust the pixmap size.
- if (deviceRect.size() != pix.size()) {
+ if (deviceRect.size() != pix.size() / devicePixelRatio) {
// exposed needs to cover the whole pixmap
- pix = QPixmap(deviceRect.size());
+ pix = QPixmap(deviceRect.size() * devicePixelRatio);
pixModified = true;
itemCache->allExposed = true;
itemCache->exposed.clear();
@@ -4667,6 +4678,7 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
styleOptionTmp.exposedRect = br.adjusted(-1, -1, 1, 1);
// Render the exposed areas.
+ pix.setDevicePixelRatio(devicePixelRatio);
_q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(),
&styleOptionTmp, painterStateProtection);
@@ -5844,6 +5856,41 @@ void QGraphicsScene::setMinimumRenderSize(qreal minSize)
update();
}
+/*!
+ \property QGraphicsScene::focusOnTouch
+ \since 5.12
+ \brief whether items gain focus when receiving a \e {touch begin} event.
+
+ The usual behavior is to transfer focus only when an item is clicked. Often
+ a tap on a touchpad is interpreted as equivalent to a mouse click by the
+ operating system, generating a synthesized click event in response. However,
+ at least on macOS you can configure this behavior.
+
+ By default, QGraphicsScene also transfers focus when you touch on a trackpad
+ or similar. If the operating system is configured to not generate a
+ synthetic mouse click on tapping the trackpad, this is surprising. If the
+ operating system does generate synthetic mouse clicks on tapping the
+ trackpad, the focus transfer on starting a touch gesture is unnecessary.
+
+ With focusOnTouch switched off, QGraphicsScene behaves as one would expect
+ on macOS.
+
+ The default value is \c true, ensuring that the default behavior is just as
+ in Qt versions prior to 5.12. Set to \c false to prevent touch events from
+ triggering focus changes.
+*/
+bool QGraphicsScene::focusOnTouch() const
+{
+ Q_D(const QGraphicsScene);
+ return d->focusOnTouch;
+}
+
+void QGraphicsScene::setFocusOnTouch(bool enabled)
+{
+ Q_D(QGraphicsScene);
+ d->focusOnTouch = enabled;
+}
+
void QGraphicsScenePrivate::addView(QGraphicsView *view)
{
views << view;
@@ -6023,39 +6070,41 @@ bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEve
{
Q_Q(QGraphicsScene);
- if (cachedItemsUnderMouse.isEmpty() || cachedItemsUnderMouse.constFirst() != origin) {
- const QTouchEvent::TouchPoint &firstTouchPoint = touchEvent->touchPoints().first();
- cachedItemsUnderMouse = itemsAtPosition(firstTouchPoint.screenPos().toPoint(),
- firstTouchPoint.scenePos(),
- static_cast<QWidget *>(touchEvent->target()));
- }
+ if (focusOnTouch) {
+ if (cachedItemsUnderMouse.isEmpty() || cachedItemsUnderMouse.constFirst() != origin) {
+ const QTouchEvent::TouchPoint &firstTouchPoint = touchEvent->touchPoints().first();
+ cachedItemsUnderMouse = itemsAtPosition(firstTouchPoint.screenPos().toPoint(),
+ firstTouchPoint.scenePos(),
+ static_cast<QWidget *>(touchEvent->target()));
+ }
- // Set focus on the topmost enabled item that can take focus.
- bool setFocus = false;
+ // Set focus on the topmost enabled item that can take focus.
+ bool setFocus = false;
- foreach (QGraphicsItem *item, cachedItemsUnderMouse) {
- if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) {
- if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
+ foreach (QGraphicsItem *item, cachedItemsUnderMouse) {
+ if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) {
+ if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
+ setFocus = true;
+ if (item != q->focusItem())
+ q->setFocusItem(item, Qt::MouseFocusReason);
+ break;
+ }
+ }
+ if (item->isPanel())
+ break;
+ if (item->d_ptr->flags & QGraphicsItem::ItemStopsClickFocusPropagation)
+ break;
+ if (item->d_ptr->flags & QGraphicsItem::ItemStopsFocusHandling) {
+ // Make sure we don't clear focus.
setFocus = true;
- if (item != q->focusItem())
- q->setFocusItem(item, Qt::MouseFocusReason);
break;
}
}
- if (item->isPanel())
- break;
- if (item->d_ptr->flags & QGraphicsItem::ItemStopsClickFocusPropagation)
- break;
- if (item->d_ptr->flags & QGraphicsItem::ItemStopsFocusHandling) {
- // Make sure we don't clear focus.
- setFocus = true;
- break;
- }
- }
- // If nobody could take focus, clear it.
- if (!stickyFocus && !setFocus)
- q->setFocusItem(0, Qt::MouseFocusReason);
+ // If nobody could take focus, clear it.
+ if (!stickyFocus && !setFocus)
+ q->setFocusItem(0, Qt::MouseFocusReason);
+ }
bool res = false;
bool eventAccepted = touchEvent->isAccepted();
@@ -6391,7 +6440,7 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event)
ev.setWidget(event->widget());
sendEvent(receiver.data(), &ev);
QSet<QGesture *> ignoredGestures;
- foreach (QGesture *g, gestures) {
+ for (QGesture *g : qAsConst(gestures)) {
if (!ev.isAccepted() && !ev.isAccepted(g)) {
// if the gesture was ignored by its target, we will update the
// targetItems list with a possible target items (items that
diff --git a/src/widgets/graphicsview/qgraphicsscene.h b/src/widgets/graphicsview/qgraphicsscene.h
index 8efbcd273e..287e551db7 100644
--- a/src/widgets/graphicsview/qgraphicsscene.h
+++ b/src/widgets/graphicsview/qgraphicsscene.h
@@ -106,6 +106,7 @@ class Q_WIDGETS_EXPORT QGraphicsScene : public QObject
Q_PROPERTY(bool sortCacheEnabled READ isSortCacheEnabled WRITE setSortCacheEnabled)
Q_PROPERTY(bool stickyFocus READ stickyFocus WRITE setStickyFocus)
Q_PROPERTY(qreal minimumRenderSize READ minimumRenderSize WRITE setMinimumRenderSize)
+ Q_PROPERTY(bool focusOnTouch READ focusOnTouch WRITE setFocusOnTouch)
public:
enum ItemIndexMethod {
@@ -253,6 +254,9 @@ public:
qreal minimumRenderSize() const;
void setMinimumRenderSize(qreal minSize);
+ bool focusOnTouch() const;
+ void setFocusOnTouch(bool enabled);
+
public Q_SLOTS:
void update(const QRectF &rect = QRectF());
void invalidate(const QRectF &rect = QRectF(), SceneLayers layers = AllLayers);
diff --git a/src/widgets/graphicsview/qgraphicsscene_p.h b/src/widgets/graphicsview/qgraphicsscene_p.h
index 2f5d7c54bb..a2d13436fc 100644
--- a/src/widgets/graphicsview/qgraphicsscene_p.h
+++ b/src/widgets/graphicsview/qgraphicsscene_p.h
@@ -114,7 +114,8 @@ public:
quint32 painterStateProtection : 1;
quint32 sortCacheEnabled : 1; // for compatibility
quint32 allItemsIgnoreTouchEvents : 1;
- quint32 padding : 15;
+ quint32 focusOnTouch : 1;
+ quint32 padding : 14;
qreal minimumRenderSize;
diff --git a/src/widgets/graphicsview/qgraphicssceneevent.cpp b/src/widgets/graphicsview/qgraphicssceneevent.cpp
index f7f09486e9..398ef1aaf5 100644
--- a/src/widgets/graphicsview/qgraphicssceneevent.cpp
+++ b/src/widgets/graphicsview/qgraphicssceneevent.cpp
@@ -259,8 +259,9 @@
#include "qgraphicssceneevent.h"
-#ifndef QT_NO_DEBUG
+#ifndef QT_NO_DEBUG_STREAM
#include <QtCore/qdebug.h>
+#include <private/qdebug_p.h>
#endif
#include <QtCore/qmap.h>
#include <QtCore/qpoint.h>
@@ -1730,4 +1731,99 @@ void QGraphicsSceneMoveEvent::setNewPos(const QPointF &pos)
d->newPos = pos;
}
+#ifndef QT_NO_DEBUG_STREAM
+template <class Event>
+static inline void formatPositions(QDebug &debug, const Event *event)
+{
+ debug << ", pos=";
+ QtDebugUtils::formatQPoint(debug, event->pos());
+ debug << ", scenePos=";
+ QtDebugUtils::formatQPoint(debug, event->scenePos());
+ debug << ", screenPos=";
+ QtDebugUtils::formatQPoint(debug, event->screenPos());
+}
+
+QDebug operator<<(QDebug debug, const QGraphicsSceneEvent *event)
+{
+ QDebugStateSaver saver(debug);
+ debug.nospace();
+ if (!event) {
+ debug << "QGraphicsSceneEvent(0)";
+ return debug;
+ }
+
+ const QEvent::Type type = event->type();
+ switch (type) {
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseRelease:
+ case QEvent::GraphicsSceneMouseDoubleClick: {
+ const QGraphicsSceneMouseEvent *me = static_cast<const QGraphicsSceneMouseEvent *>(event);
+ const Qt::MouseButton button = me->button();
+ const Qt::MouseButtons buttons = me->buttons();
+ debug << "QGraphicsSceneMouseEvent(";
+ QtDebugUtils::formatQEnum(debug, type);
+ if (type != QEvent::GraphicsSceneMouseMove) {
+ debug << ", ";
+ QtDebugUtils::formatQEnum(debug, button);
+ }
+ if (buttons && button != buttons) {
+ debug << ", buttons=";
+ QtDebugUtils::formatQFlags(debug, buttons);
+ }
+ QtDebugUtils::formatNonNullQFlags(debug, ", ", me->modifiers());
+ formatPositions(debug, me);
+ QtDebugUtils::formatNonNullQEnum(debug, ", ", me->source());
+ QtDebugUtils::formatNonNullQFlags(debug, ", flags=", me->flags());
+ debug << ')';
+ }
+ break;
+ case QEvent::GraphicsSceneContextMenu: {
+ const QGraphicsSceneContextMenuEvent *ce = static_cast<const QGraphicsSceneContextMenuEvent *>(event);
+ debug << "QGraphicsSceneContextMenuEvent(reason=" << ce->reason();
+ QtDebugUtils::formatNonNullQFlags(debug, ", ", ce->modifiers());
+ formatPositions(debug, ce);
+ debug << ')';
+ }
+ break;
+ case QEvent::GraphicsSceneHoverEnter:
+ case QEvent::GraphicsSceneHoverMove:
+ case QEvent::GraphicsSceneHoverLeave:
+ debug << "QGraphicsSceneHoverEvent(";
+ formatPositions(debug, static_cast<const QGraphicsSceneHoverEvent *>(event));
+ debug << ')';
+ break;
+ case QEvent::GraphicsSceneHelp:
+ break;
+ case QEvent::GraphicsSceneDragEnter:
+ case QEvent::GraphicsSceneDragMove:
+ case QEvent::GraphicsSceneDragLeave:
+ case QEvent::GraphicsSceneDrop: {
+ const QGraphicsSceneDragDropEvent *de = static_cast<const QGraphicsSceneDragDropEvent *>(event);
+ debug << "QGraphicsSceneDragDropEvent(proposedAction=";
+ QtDebugUtils::formatQEnum(debug, de->proposedAction());
+ debug << ", possibleActions=";
+ QtDebugUtils::formatQFlags(debug, de->possibleActions());
+ debug << ", source=" << de->source();
+ QtDebugUtils::formatNonNullQFlags(debug, ", buttons=", de->buttons());
+ QtDebugUtils::formatNonNullQFlags(debug, ", ", de->modifiers());
+ formatPositions(debug, de);
+ }
+ break;
+ case QEvent::GraphicsSceneWheel: {
+ const QGraphicsSceneWheelEvent *we = static_cast<const QGraphicsSceneWheelEvent *>(event);
+ debug << "QGraphicsSceneWheelEvent(";
+ QtDebugUtils::formatNonNullQFlags(debug, ", buttons=", we->buttons());
+ QtDebugUtils::formatNonNullQFlags(debug, ", ", we->modifiers());
+ formatPositions(debug, we);
+ debug << ')';
+ }
+ break;
+ default:
+ break;
+ }
+ return debug;
+}
+#endif // !QT_NO_DEBUG_STREAM
+
QT_END_NAMESPACE
diff --git a/src/widgets/graphicsview/qgraphicssceneevent.h b/src/widgets/graphicsview/qgraphicssceneevent.h
index 77b53e401d..9d940be2c0 100644
--- a/src/widgets/graphicsview/qgraphicssceneevent.h
+++ b/src/widgets/graphicsview/qgraphicssceneevent.h
@@ -320,6 +320,10 @@ public:
void setNewPos(const QPointF &pos);
};
+#ifndef QT_NO_DEBUG_STREAM
+Q_WIDGETS_EXPORT QDebug operator<<(QDebug, const QGraphicsSceneEvent *);
+#endif
+
QT_END_NAMESPACE
#endif
diff --git a/src/widgets/graphicsview/qgraphicsview.cpp b/src/widgets/graphicsview/qgraphicsview.cpp
index f79ee41e10..24647dd74c 100644
--- a/src/widgets/graphicsview/qgraphicsview.cpp
+++ b/src/widgets/graphicsview/qgraphicsview.cpp
@@ -2703,7 +2703,7 @@ void QGraphicsView::updateScene(const QList<QRectF> &rects)
dirtyViewportRects << xrect;
}
- foreach (const QRect &rect, dirtyViewportRects) {
+ for (const QRect &rect : qAsConst(dirtyViewportRects)) {
// Add the exposed rect to the update region. In rect update
// mode, we only count the bounding rect of items.
if (!boundingRectUpdate) {
@@ -3483,7 +3483,9 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
// Recreate the background pixmap, and flag the whole background as
// exposed.
if (d->mustResizeBackgroundPixmap) {
- d->backgroundPixmap = QPixmap(viewport()->size());
+ const qreal dpr = d->viewport->devicePixelRatioF();
+ d->backgroundPixmap = QPixmap(viewport()->size() * dpr);
+ d->backgroundPixmap.setDevicePixelRatio(dpr);
QBrush bgBrush = viewport()->palette().brush(viewport()->backgroundRole());
if (!bgBrush.isOpaque())
d->backgroundPixmap.fill(Qt::transparent);
@@ -3679,14 +3681,20 @@ void QGraphicsView::scrollContentsBy(int dx, int dy)
&& X11->use_xrender
#endif
) {
+ // Below, QPixmap::scroll() works in device pixels, while the delta values
+ // and backgroundPixmapExposed are in device independent pixels.
+ const qreal dpr = d->backgroundPixmap.devicePixelRatio();
+ const qreal inverseDpr = qreal(1) / dpr;
+
// Scroll the background pixmap
QRegion exposed;
if (!d->backgroundPixmap.isNull())
- d->backgroundPixmap.scroll(dx, dy, d->backgroundPixmap.rect(), &exposed);
+ d->backgroundPixmap.scroll(dx * dpr, dy * dpr, d->backgroundPixmap.rect(), &exposed);
// Invalidate the background pixmap
d->backgroundPixmapExposed.translate(dx, dy);
- d->backgroundPixmapExposed += exposed;
+ const QRegion exposedScaled = QTransform::fromScale(inverseDpr, inverseDpr).map(exposed);
+ d->backgroundPixmapExposed += exposedScaled;
}
// Always replay on scroll.
diff --git a/src/widgets/itemviews/qabstractitemdelegate.cpp b/src/widgets/itemviews/qabstractitemdelegate.cpp
index c9f321c3f6..7bc0ece4b3 100644
--- a/src/widgets/itemviews/qabstractitemdelegate.cpp
+++ b/src/widgets/itemviews/qabstractitemdelegate.cpp
@@ -599,18 +599,21 @@ QString QAbstractItemDelegatePrivate::textForRole(Qt::ItemDataRole role, const Q
case QVariant::DateTime:
text = locale.toString(value.toDateTime(), formatType);
break;
- default: {
- if (value.canConvert<QJsonValue>()) {
- const QJsonValue val = value.toJsonValue();
- if (val.isBool())
- text = QVariant(val.toBool()).toString();
- else if (val.isDouble())
- text = locale.toString(val.toDouble(), 'g', precision);
- else if (val.isString())
- text = val.toString();
- } else {
- text = value.toString();
+ case QVariant::Type(QMetaType::QJsonValue): {
+ const QJsonValue val = value.toJsonValue();
+ if (val.isBool()) {
+ text = QVariant(val.toBool()).toString();
+ break;
+ }
+ if (val.isDouble()) {
+ text = locale.toString(val.toDouble(), 'g', precision);
+ break;
}
+ // val is a string (or null) here
+ Q_FALLTHROUGH();
+ }
+ default: {
+ text = value.toString();
if (role == Qt::DisplayRole)
text.replace(QLatin1Char('\n'), QChar::LineSeparator);
break;
diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp
index 2d30b2650a..7bfa51337d 100644
--- a/src/widgets/itemviews/qheaderview.cpp
+++ b/src/widgets/itemviews/qheaderview.cpp
@@ -1853,11 +1853,13 @@ bool QHeaderView::restoreState(const QByteArray &state)
*/
void QHeaderView::reset()
{
+ Q_D(QHeaderView);
QAbstractItemView::reset();
// it would be correct to call clear, but some apps rely
// on the header keeping the sections, even after calling reset
//d->clear();
initializeSections();
+ d->invalidateCachedSizeHint();
}
/*!
@@ -2868,6 +2870,7 @@ bool QHeaderView::viewportEvent(QEvent *e)
}
return true; }
#endif // QT_CONFIG(statustip)
+ case QEvent::Resize:
case QEvent::FontChange:
case QEvent::StyleChange:
d->invalidateCachedSizeHint();
@@ -2962,8 +2965,10 @@ void QHeaderView::paintSection(QPainter *painter, const QRect &rect, int logical
margin += style()->pixelMetric(QStyle::PM_SmallIconSize, 0, this) +
style()->pixelMetric(QStyle::PM_HeaderMargin, 0, this);
- if (d->textElideMode != Qt::ElideNone)
- opt.text = opt.fontMetrics.elidedText(opt.text, d->textElideMode , rect.width() - margin);
+ if (d->textElideMode != Qt::ElideNone) {
+ const QRect textRect = style()->subElementRect(QStyle::SE_HeaderLabel, &opt, this);
+ opt.text = opt.fontMetrics.elidedText(opt.text, d->textElideMode, textRect.width() - margin);
+ }
QVariant foregroundBrush = d->model->headerData(logicalIndex, d->orientation,
Qt::ForegroundRole);
@@ -3363,7 +3368,9 @@ void QHeaderViewPrivate::setupSectionIndicator(int section, int position)
sectionIndicator->resize(w, h);
#endif
- QPixmap pm(w, h);
+ const qreal pixmapDevicePixelRatio = q->devicePixelRatioF();
+ QPixmap pm(QSize(w, h) * pixmapDevicePixelRatio);
+ pm.setDevicePixelRatio(pixmapDevicePixelRatio);
pm.fill(QColor(0, 0, 0, 45));
QRect rect(0, 0, w, h);
@@ -3828,6 +3835,7 @@ void QHeaderViewPrivate::cascadingResize(int visual, int newSize)
void QHeaderViewPrivate::setDefaultSectionSize(int size)
{
Q_Q(QHeaderView);
+ size = qBound(q->minimumSectionSize(), size, q->maximumSectionSize());
executePostedLayout();
invalidateCachedSizeHint();
defaultSectionSize = size;
@@ -4083,7 +4091,7 @@ bool QHeaderViewPrivate::read(QDataStream &in)
}
int sectionItemsLengthTotal = 0;
- foreach (const SectionItem &section, newSectionItems)
+ for (const SectionItem &section : qAsConst(newSectionItems))
sectionItemsLengthTotal += section.size;
if (sectionItemsLengthTotal != lengthIn)
return false;
diff --git a/src/widgets/itemviews/qitemdelegate.cpp b/src/widgets/itemviews/qitemdelegate.cpp
index 91122283a4..dff4cc4593 100644
--- a/src/widgets/itemviews/qitemdelegate.cpp
+++ b/src/widgets/itemviews/qitemdelegate.cpp
@@ -103,7 +103,10 @@ public:
QItemEditorFactory *f;
bool clipPainting;
- QRect textLayoutBounds(const QStyleOptionViewItem &options) const;
+ QRect displayRect(const QModelIndex &index, const QStyleOptionViewItem &option,
+ const QRect &decorationRect, const QRect &checkRect) const;
+ QRect textLayoutBounds(const QStyleOptionViewItem &option,
+ const QRect &decorationRect, const QRect &checkRect) const;
QSizeF doTextLayout(int lineWidth) const;
mutable QTextLayout textLayout;
mutable QTextOption textOption;
@@ -121,21 +124,53 @@ public:
} tmp;
};
-QRect QItemDelegatePrivate::textLayoutBounds(const QStyleOptionViewItem &option) const
+QRect QItemDelegatePrivate::displayRect(const QModelIndex &index, const QStyleOptionViewItem &option,
+ const QRect &decorationRect, const QRect &checkRect) const
+{
+ Q_Q(const QItemDelegate);
+ const QVariant value = index.data(Qt::DisplayRole);
+ if (!value.isValid() || value.isNull())
+ return QRect();
+
+ const QString text = valueToText(value, option);
+ const QVariant fontVal = index.data(Qt::FontRole);
+ const QFont fnt = qvariant_cast<QFont>(fontVal).resolve(option.font);
+ return q->textRectangle(nullptr,
+ textLayoutBounds(option, decorationRect, checkRect),
+ fnt, text);
+}
+
+// similar to QCommonStylePrivate::viewItemSize(Qt::DisplayRole)
+QRect QItemDelegatePrivate::textLayoutBounds(const QStyleOptionViewItem &option,
+ const QRect &decorationRect, const QRect &checkRect) const
{
QRect rect = option.rect;
+ const QWidget *w = widget(option);
+ QStyle *style = w ? w->style() : QApplication::style();
const bool wrapText = option.features & QStyleOptionViewItem::WrapText;
+ // see QItemDelegate::drawDisplay
+ const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, w) + 1;
switch (option.decorationPosition) {
case QStyleOptionViewItem::Left:
case QStyleOptionViewItem::Right:
- rect.setWidth(wrapText && rect.isValid() ? rect.width() : (QFIXED_MAX));
+ rect.setWidth(wrapText && rect.isValid() ? rect.width() - 2 * textMargin : (QFIXED_MAX));
break;
case QStyleOptionViewItem::Top:
case QStyleOptionViewItem::Bottom:
- rect.setWidth(wrapText ? option.decorationSize.width() : (QFIXED_MAX));
+ rect.setWidth(wrapText ? option.decorationSize.width() - 2 * textMargin : (QFIXED_MAX));
break;
}
+ if (wrapText) {
+ if (!decorationRect.isNull())
+ rect.setWidth(rect.width() - decorationRect.width() - 2 * textMargin);
+ if (!checkRect.isNull())
+ rect.setWidth(rect.width() - checkRect.width() - 2 * textMargin);
+ // adjust height to be sure that the text fits
+ const QSizeF size = doTextLayout(rect.width());
+ rect.setHeight(qCeil(size.height()));
+ }
+
return rect;
}
@@ -395,14 +430,6 @@ void QItemDelegate::paint(QPainter *painter,
decorationRect = QRect();
}
- QString text;
- QRect displayRect;
- value = index.data(Qt::DisplayRole);
- if (value.isValid() && !value.isNull()) {
- text = d->valueToText(value, opt);
- displayRect = textRectangle(painter, d->textLayoutBounds(opt), opt.font, text);
- }
-
QRect checkRect;
Qt::CheckState checkState = Qt::Unchecked;
value = index.data(Qt::CheckStateRole);
@@ -411,6 +438,14 @@ void QItemDelegate::paint(QPainter *painter,
checkRect = doCheck(opt, opt.rect, value);
}
+ QString text;
+ QRect displayRect;
+ value = index.data(Qt::DisplayRole);
+ if (value.isValid() && !value.isNull()) {
+ text = d->valueToText(value, opt);
+ displayRect = d->displayRect(index, opt, decorationRect, checkRect);
+ }
+
// do the layout
doLayout(opt, &checkRect, &decorationRect, &displayRect, false);
@@ -440,12 +475,13 @@ void QItemDelegate::paint(QPainter *painter,
QSize QItemDelegate::sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
+ Q_D(const QItemDelegate);
QVariant value = index.data(Qt::SizeHintRole);
if (value.isValid())
return qvariant_cast<QSize>(value);
QRect decorationRect = rect(option, index, Qt::DecorationRole);
- QRect displayRect = rect(option, index, Qt::DisplayRole);
QRect checkRect = rect(option, index, Qt::CheckStateRole);
+ QRect displayRect = d->displayRect(index, option, decorationRect, checkRect);
doLayout(option, &checkRect, &decorationRect, &displayRect, true);
@@ -1000,8 +1036,8 @@ QPixmap *QItemDelegate::selected(const QPixmap &pixmap, const QPalette &palette,
/*!
\internal
+ Only used (and usable) for Qt::DecorationRole and Qt::CheckStateRole
*/
-
QRect QItemDelegate::rect(const QStyleOptionViewItem &option,
const QModelIndex &index, int role) const
{
@@ -1032,7 +1068,9 @@ QRect QItemDelegate::rect(const QStyleOptionViewItem &option,
const QString text = d->valueToText(value, option);
value = index.data(Qt::FontRole);
QFont fnt = qvariant_cast<QFont>(value).resolve(option.font);
- return textRectangle(0, d->textLayoutBounds(option), fnt, text); }
+ return textRectangle(nullptr,
+ d->textLayoutBounds(option, QRect(), QRect()),
+ fnt, text); }
}
}
return QRect();
diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp
index a7174a92e8..e5769940d4 100644
--- a/src/widgets/itemviews/qlistview.cpp
+++ b/src/widgets/itemviews/qlistview.cpp
@@ -1631,6 +1631,32 @@ bool QListView::isSelectionRectVisible() const
}
/*!
+ \property QListView::itemAlignment
+ \brief the alignment of each item in its cell
+ \since 5.12
+
+ This is only supported in ListMode with TopToBottom flow
+ and with wrapping enabled.
+ The default alignment is 0, which means that an item fills
+ its cell entirely.
+*/
+void QListView::setItemAlignment(Qt::Alignment alignment)
+{
+ Q_D(QListView);
+ if (d->itemAlignment == alignment)
+ return;
+ d->itemAlignment = alignment;
+ if (viewMode() == ListMode && flow() == QListView::TopToBottom && isWrapping())
+ d->doDelayedItemsLayout();
+}
+
+Qt::Alignment QListView::itemAlignment() const
+{
+ Q_D(const QListView);
+ return d->itemAlignment;
+}
+
+/*!
\reimp
*/
bool QListView::event(QEvent *e)
@@ -1656,7 +1682,8 @@ QListViewPrivate::QListViewPrivate()
column(0),
uniformItemSizes(false),
batchSize(100),
- showElasticBand(false)
+ showElasticBand(false),
+ itemAlignment(Qt::Alignment())
{
}
@@ -2366,6 +2393,7 @@ QListViewItem QListModeViewBase::indexToListViewItem(const QModelIndex &index) c
options.rect.setSize(contentsSize);
QSize size = (uniformItemSizes() && cachedItemSize().isValid())
? cachedItemSize() : itemSize(options, index);
+ QSize cellSize = size;
QPoint pos;
if (flow() == QListView::LeftToRight) {
@@ -2378,12 +2406,22 @@ QListViewItem QListModeViewBase::indexToListViewItem(const QModelIndex &index) c
int right = (segment + 1 >= segmentPositions.count()
? contentsSize.width()
: segmentPositions.at(segment + 1));
- size.setWidth(right - pos.x());
+ cellSize.setWidth(right - pos.x());
} else { // make the items as wide as the viewport
- size.setWidth(qMax(size.width(), viewport()->width() - 2 * spacing()));
+ cellSize.setWidth(qMax(size.width(), viewport()->width() - 2 * spacing()));
}
}
+ if (dd->itemAlignment & Qt::AlignHorizontal_Mask) {
+ size.setWidth(qMin(size.width(), cellSize.width()));
+ if (dd->itemAlignment & Qt::AlignRight)
+ pos.setX(pos.x() + cellSize.width() - size.width());
+ if (dd->itemAlignment & Qt::AlignHCenter)
+ pos.setX(pos.x() + (cellSize.width() - size.width()) / 2);
+ } else {
+ size.setWidth(cellSize.width());
+ }
+
return QListViewItem(QRect(pos, size), index.row());
}
@@ -2562,8 +2600,18 @@ QVector<QModelIndex> QListModeViewBase::intersectingSet(const QRect &area) const
if (isHidden(row))
continue;
QModelIndex index = modelIndex(row);
- if (index.isValid())
- ret += index;
+ if (index.isValid()) {
+ if (flow() == QListView::LeftToRight || dd->itemAlignment == Qt::Alignment()) {
+ ret += index;
+ } else {
+ const auto viewItem = indexToListViewItem(index);
+ const int iw = viewItem.width();
+ const int startPos = qMax(segStartPosition, segmentPositions.at(seg));
+ const int endPos = qMin(segmentPositions.at(seg + 1), segEndPosition);
+ if (endPos >= viewItem.x && startPos < viewItem.x + iw)
+ ret += index;
+ }
+ }
#if 0 // for debugging
else
qWarning("intersectingSet: row %d was invalid", row);
@@ -2603,7 +2651,7 @@ int QListModeViewBase::perItemScrollingPageSteps(int length, int bounds, bool wr
positions = segmentPositions;
else if (!flowPositions.isEmpty()) {
positions.reserve(scrollValueMap.size());
- foreach (int itemShown, scrollValueMap)
+ for (int itemShown : scrollValueMap)
positions.append(flowPositions.at(itemShown));
}
if (positions.isEmpty() || bounds <= length)
@@ -2767,6 +2815,8 @@ bool QIconModeViewBase::filterStartDrag(Qt::DropActions supportedActions)
drag->setHotSpot(dd->pressedPosition - rect.topLeft());
Qt::DropAction action = drag->exec(supportedActions, dd->defaultDropAction);
draggedItems.clear();
+ // for internal moves the action was set to Qt::CopyAction in
+ // filterDropEvent() to avoid the deletion here
if (action == Qt::MoveAction)
dd->clearOrRemove();
}
@@ -2784,7 +2834,7 @@ bool QIconModeViewBase::filterDropEvent(QDropEvent *e)
if (qq->acceptDrops()) {
const Qt::ItemFlags dropableFlags = Qt::ItemIsDropEnabled|Qt::ItemIsEnabled;
const QVector<QModelIndex> &dropIndices = intersectingSet(QRect(end, QSize(1, 1)));
- foreach (const QModelIndex &index, dropIndices)
+ for (const QModelIndex &index : dropIndices)
if ((index.flags() & dropableFlags) == dropableFlags)
return false;
}
@@ -2803,6 +2853,8 @@ bool QIconModeViewBase::filterDropEvent(QDropEvent *e)
dd->stopAutoScroll();
draggedItems.clear();
dd->emitIndexesMoved(indexes);
+ // do not delete item on internal move, see filterStartDrag()
+ e->setDropAction(Qt::CopyAction);
e->accept(); // we have handled the event
// if the size has not grown, we need to check if it has shrinked
if (contentsSize != contents) {
diff --git a/src/widgets/itemviews/qlistview.h b/src/widgets/itemviews/qlistview.h
index 9fc4035999..8a5d5e02ae 100644
--- a/src/widgets/itemviews/qlistview.h
+++ b/src/widgets/itemviews/qlistview.h
@@ -65,6 +65,7 @@ class Q_WIDGETS_EXPORT QListView : public QAbstractItemView
Q_PROPERTY(int batchSize READ batchSize WRITE setBatchSize)
Q_PROPERTY(bool wordWrap READ wordWrap WRITE setWordWrap)
Q_PROPERTY(bool selectionRectVisible READ isSelectionRectVisible WRITE setSelectionRectVisible)
+ Q_PROPERTY(Qt::Alignment itemAlignment READ itemAlignment WRITE setItemAlignment)
public:
enum Movement { Static, Free, Snap };
@@ -125,6 +126,9 @@ public:
void setSelectionRectVisible(bool show);
bool isSelectionRectVisible() const;
+ void setItemAlignment(Qt::Alignment alignment);
+ Qt::Alignment itemAlignment() const;
+
QRect visualRect(const QModelIndex &index) const override;
void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible) override;
QModelIndex indexAt(const QPoint &p) const override;
diff --git a/src/widgets/itemviews/qlistview_p.h b/src/widgets/itemviews/qlistview_p.h
index ca947292e3..181386d4d0 100644
--- a/src/widgets/itemviews/qlistview_p.h
+++ b/src/widgets/itemviews/qlistview_p.h
@@ -431,6 +431,8 @@ public:
QRect elasticBand;
bool showElasticBand;
+
+ Qt::Alignment itemAlignment;
};
// inline implementations
diff --git a/src/widgets/itemviews/qlistwidget.cpp b/src/widgets/itemviews/qlistwidget.cpp
index 4f1c7fe80a..72e0a67a64 100644
--- a/src/widgets/itemviews/qlistwidget.cpp
+++ b/src/widgets/itemviews/qlistwidget.cpp
@@ -48,9 +48,6 @@
QT_BEGIN_NAMESPACE
-// workaround for VC++ 6.0 linker bug (?)
-typedef bool(*LessThan)(const QPair<QListWidgetItem*,int>&,const QPair<QListWidgetItem*,int>&);
-
class QListWidgetMimeData : public QMimeData
{
Q_OBJECT
@@ -301,7 +298,7 @@ void QListModel::sort(int column, Qt::SortOrder order)
sorting[i].second = i;
}
- LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
+ const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
std::sort(sorting.begin(), sorting.end(), compare);
QModelIndexList fromIndexes;
QModelIndexList toIndexes;
@@ -338,7 +335,7 @@ void QListModel::ensureSorted(int column, Qt::SortOrder order, int start, int en
sorting[i].second = start + i;
}
- LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
+ const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
std::sort(sorting.begin(), sorting.end(), compare);
QModelIndexList oldPersistentIndexes = persistentIndexList();
@@ -1847,7 +1844,7 @@ QMimeData *QListWidget::mimeData(const QList<QListWidgetItem*> items) const
// if non empty, it's called from the model's own mimeData
if (cachedIndexes.isEmpty()) {
cachedIndexes.reserve(items.count());
- foreach (QListWidgetItem *item, items)
+ for (QListWidgetItem *item : items)
cachedIndexes << indexFromItem(item);
QMimeData *result = d->listModel()->internalMimeData();
diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp
index 1938fd8e92..9725a768de 100644
--- a/src/widgets/itemviews/qtableview.cpp
+++ b/src/widgets/itemviews/qtableview.cpp
@@ -74,7 +74,7 @@ void QSpanCollection::addSpan(QSpanCollection::Span *span)
//the previouslist is the list of spans that sarts _before_ the row of the span.
// and which may intersect this row.
const SubIndex previousList = it_y.value();
- foreach(Span *s, previousList) {
+ for (Span *s : previousList) {
//If a subspans intersect the row, we need to split it into subspans
if(s->bottom() >= span->top())
sub_index.insert(-s->left(), s);
@@ -798,6 +798,7 @@ void QTableViewPrivate::drawAndClipSpans(const QRegion &area, QPainter *painter,
const QStyleOptionViewItem &option, QBitArray *drawn,
int firstVisualRow, int lastVisualRow, int firstVisualColumn, int lastVisualColumn)
{
+ Q_Q(const QTableView);
bool alternateBase = false;
QRegion region = viewport->rect();
@@ -816,7 +817,7 @@ void QTableViewPrivate::drawAndClipSpans(const QRegion &area, QPainter *painter,
visibleSpans = set.toList();
}
- foreach (QSpanCollection::Span *span, visibleSpans) {
+ for (QSpanCollection::Span *span : qAsConst(visibleSpans)) {
int row = span->top();
int col = span->left();
QModelIndex index = model->index(row, col, root);
@@ -831,6 +832,18 @@ void QTableViewPrivate::drawAndClipSpans(const QRegion &area, QPainter *painter,
alternateBase = alternatingColors && (span->top() & 1);
opt.features.setFlag(QStyleOptionViewItem::Alternate, alternateBase);
drawCell(painter, opt, index);
+ if (showGrid) {
+ // adjust the clip rect to be able to paint the top & left grid lines
+ // if the headers are not visible, see paintEvent()
+ if (horizontalHeader->visualIndex(row) == 0)
+ rect.setTop(rect.top() + 1);
+ if (verticalHeader->visualIndex(row) == 0) {
+ if (q->isLeftToRight())
+ rect.setLeft(rect.left() + 1);
+ else
+ rect.setRight(rect.right() - 1);
+ }
+ }
region -= rect;
for (int r = span->top(); r <= span->bottom(); ++r) {
const int vr = visualRow(r);
@@ -1163,7 +1176,6 @@ void QTableView::doItemsLayout()
{
Q_D(QTableView);
QAbstractItemView::doItemsLayout();
- d->verticalHeader->d_func()->setScrollOffset(verticalScrollBar(), verticalScrollMode());
if (!d->verticalHeader->updatesEnabled())
d->verticalHeader->setUpdatesEnabled(true);
}
@@ -1321,10 +1333,10 @@ void QTableView::scrollContentsBy(int dx, int dy)
//we need to update the first line of the previous top item in the view
//because it has the grid drawn if the header is invisible.
//It is strictly related to what's done at then end of the paintEvent
- if (dy > 0 && d->horizontalHeader->isHidden() && d->verticalScrollMode == ScrollPerItem) {
+ if (dy > 0 && d->horizontalHeader->isHidden()) {
d->viewport->update(0, dy, d->viewport->width(), dy);
}
- if (dx > 0 && d->verticalHeader->isHidden() && d->horizontalScrollMode == ScrollPerItem) {
+ if (dx > 0 && d->verticalHeader->isHidden()) {
d->viewport->update(dx, 0, dx, d->viewport->height());
}
}
@@ -1504,10 +1516,26 @@ void QTableView::paintEvent(QPaintEvent *event)
//draw the top & left grid lines if the headers are not visible.
//We do update this line when subsequent scroll happen (see scrollContentsBy)
- if (horizontalHeader->isHidden() && verticalScrollMode() == ScrollPerItem)
- painter.drawLine(dirtyArea.left(), 0, dirtyArea.right(), 0);
- if (verticalHeader->isHidden() && horizontalScrollMode() == ScrollPerItem)
- painter.drawLine(0, dirtyArea.top(), 0, dirtyArea.bottom());
+ if (horizontalHeader->isHidden() && top == 0) {
+ const int row = verticalHeader->logicalIndex(top);
+ if (!verticalHeader->isSectionHidden(row)) {
+ const int rowY = rowViewportPosition(row) + offset.y();
+ if (rowY == dirtyArea.top())
+ painter.drawLine(dirtyArea.left(), rowY, dirtyArea.right(), rowY);
+ }
+ }
+ if (verticalHeader->isHidden() && left == 0) {
+ const int col = horizontalHeader->logicalIndex(left);
+ if (!horizontalHeader->isSectionHidden(col)) {
+ int colX = columnViewportPosition(col) + offset.x();
+ if (!isLeftToRight())
+ colX += columnWidth(left) - 1;
+ if (isLeftToRight() && colX == dirtyArea.left())
+ painter.drawLine(colX, dirtyArea.top(), colX, dirtyArea.bottom());
+ if (!isLeftToRight() && colX == dirtyArea.right())
+ painter.drawLine(colX, dirtyArea.top(), colX, dirtyArea.bottom());
+ }
+ }
painter.setPen(old);
}
}
@@ -1788,8 +1816,12 @@ QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifi
break;
case MovePageUp: {
int newRow = rowAt(visualRect(current).bottom() - d->viewport->height());
- if (newRow == -1)
- newRow = d->logicalRow(0);
+ if (newRow == -1) {
+ int visualRow = 0;
+ while (visualRow < bottom && isRowHidden(d->logicalRow(visualRow)))
+ ++visualRow;
+ newRow = d->logicalRow(visualRow);
+ }
return d->model->index(newRow, current.column(), d->root);
}
case MovePageDown: {
@@ -2194,6 +2226,7 @@ void QTableView::updateGeometries()
verticalScrollBar()->setRange(0, verticalLength - vsize.height());
verticalScrollBar()->d_func()->itemviewChangeSingleStep(qMax(vsize.height() / (rowsInViewport + 1), 2));
}
+ d->verticalHeader->d_func()->setScrollOffset(verticalScrollBar(), verticalScrollMode());
d->geometryRecursionBlock = false;
QAbstractItemView::updateGeometries();
diff --git a/src/widgets/itemviews/qtablewidget.cpp b/src/widgets/itemviews/qtablewidget.cpp
index 9d5a2aa1bd..2d539e10ba 100644
--- a/src/widgets/itemviews/qtablewidget.cpp
+++ b/src/widgets/itemviews/qtablewidget.cpp
@@ -225,7 +225,7 @@ QTableWidgetItem *QTableModel::takeItem(int row, int column)
itm->view = 0;
itm->d->id = -1;
tableItems[i] = 0;
- QModelIndex ind = index(itm);
+ const QModelIndex ind = index(row, column);
emit dataChanged(ind, ind);
}
return itm;
@@ -453,17 +453,20 @@ bool QTableModel::setItemData(const QModelIndex &index, const QMap<int, QVariant
QTableWidget *view = qobject_cast<QTableWidget*>(QObject::parent());
QTableWidgetItem *itm = item(index);
if (itm) {
- itm->view = 0; // prohibits item from calling itemChanged()
- bool changed = false;
+ itm->view = nullptr; // prohibits item from calling itemChanged()
+ QVector<int> rolesVec;
for (QMap<int, QVariant>::ConstIterator it = roles.constBegin(); it != roles.constEnd(); ++it) {
- if (itm->data(it.key()) != it.value()) {
- itm->setData(it.key(), it.value());
- changed = true;
+ const int role = (it.key() == Qt::EditRole ? Qt::DisplayRole : it.key());
+ if (itm->data(role) != it.value()) {
+ itm->setData(role, it.value());
+ rolesVec += role;
+ if (role == Qt::DisplayRole)
+ rolesVec += Qt::EditRole;
}
}
itm->view = view;
- if (changed)
- itemChanged(itm);
+ if (!rolesVec.isEmpty())
+ itemChanged(itm, rolesVec);
return true;
}
@@ -506,7 +509,7 @@ void QTableModel::sort(int column, Qt::SortOrder order)
unsortable.append(row);
}
- LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
+ const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
std::stable_sort(sortable.begin(), sortable.end(), compare);
QVector<QTableWidgetItem*> sorted_table(tableItems.count());
@@ -558,7 +561,7 @@ void QTableModel::ensureSorted(int column, Qt::SortOrder order,
sorting.append(QPair<QTableWidgetItem*,int>(itm, row));
}
- LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
+ const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
std::stable_sort(sorting.begin(), sorting.end(), compare);
QModelIndexList oldPersistentIndexes, newPersistentIndexes;
QVector<QTableWidgetItem*> newTable = tableItems;
@@ -771,7 +774,7 @@ void QTableModel::clearContents()
endResetModel();
}
-void QTableModel::itemChanged(QTableWidgetItem *item)
+void QTableModel::itemChanged(QTableWidgetItem *item, const QVector<int> &roles)
{
if (!item)
return;
@@ -787,7 +790,7 @@ void QTableModel::itemChanged(QTableWidgetItem *item)
} else {
QModelIndex idx = index(item);
if (idx.isValid())
- emit dataChanged(idx, idx);
+ emit dataChanged(idx, idx, roles);
}
}
@@ -1386,8 +1389,13 @@ void QTableWidgetItem::setData(int role, const QVariant &value)
}
if (!found)
values.append(QWidgetItemData(role, value));
- if (QTableModel *model = (view ? qobject_cast<QTableModel*>(view->model()) : 0))
- model->itemChanged(this);
+ if (QTableModel *model = (view ? qobject_cast<QTableModel*>(view->model()) : nullptr))
+ {
+ const QVector<int> roles((role == Qt::DisplayRole) ?
+ QVector<int>({Qt::DisplayRole, Qt::EditRole}) :
+ QVector<int>({role}));
+ model->itemChanged(this, roles);
+ }
}
/*!
@@ -2595,7 +2603,7 @@ QMimeData *QTableWidget::mimeData(const QList<QTableWidgetItem*> items) const
// if non empty, it's called from the model's own mimeData
if (cachedIndexes.isEmpty()) {
cachedIndexes.reserve(items.count());
- foreach (QTableWidgetItem *item, items)
+ for (QTableWidgetItem *item : items)
cachedIndexes << indexFromItem(item);
QMimeData *result = d->tableModel()->internalMimeData();
diff --git a/src/widgets/itemviews/qtablewidget.h b/src/widgets/itemviews/qtablewidget.h
index 7322e3aed7..9de27d164f 100644
--- a/src/widgets/itemviews/qtablewidget.h
+++ b/src/widgets/itemviews/qtablewidget.h
@@ -302,6 +302,7 @@ Q_SIGNALS:
void itemActivated(QTableWidgetItem *item);
void itemEntered(QTableWidgetItem *item);
+ // ### Qt 6: add changed roles
void itemChanged(QTableWidgetItem *item);
void currentItemChanged(QTableWidgetItem *current, QTableWidgetItem *previous);
diff --git a/src/widgets/itemviews/qtablewidget_p.h b/src/widgets/itemviews/qtablewidget_p.h
index 6412477be0..9899272fce 100644
--- a/src/widgets/itemviews/qtablewidget_p.h
+++ b/src/widgets/itemviews/qtablewidget_p.h
@@ -62,9 +62,6 @@ QT_REQUIRE_CONFIG(tablewidget);
QT_BEGIN_NAMESPACE
-// workaround for VC++ 6.0 linker bug
-typedef bool(*LessThan)(const QPair<QTableWidgetItem*,int>&,const QPair<QTableWidgetItem*,int>&);
-
class QTableWidgetMimeData : public QMimeData
{
Q_OBJECT
@@ -160,7 +157,7 @@ public:
void clear();
void clearContents();
- void itemChanged(QTableWidgetItem *item);
+ void itemChanged(QTableWidgetItem *item, const QVector<int> &roles = QVector<int>());
QTableWidgetItem *createItem() const;
const QTableWidgetItem *itemPrototype() const;
diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp
index 7f99a2c6cb..f3647f656a 100644
--- a/src/widgets/itemviews/qtreeview.cpp
+++ b/src/widgets/itemviews/qtreeview.cpp
@@ -131,11 +131,12 @@ QT_BEGIN_NAMESPACE
of the sibling that follows the parent.
\row \li Left \li Hides the children of the current item (if present)
by collapsing a branch.
- \row \li Minus \li Same as LeftArrow.
+ \row \li Minus \li Same as Left.
\row \li Right \li Reveals the children of the current item (if present)
by expanding a branch.
- \row \li Plus \li Same as RightArrow.
- \row \li Asterisk \li Expands all children of the current item (if present).
+ \row \li Plus \li Same as Right.
+ \row \li Asterisk \li Expands the current item and all its children
+ (if present).
\row \li PageUp \li Moves the cursor up one page.
\row \li PageDown \li Moves the cursor down one page.
\row \li Home \li Moves the cursor to an item in the same column of the first
@@ -632,11 +633,8 @@ bool QTreeView::isFirstColumnSpanned(int row, const QModelIndex &parent) const
Q_D(const QTreeView);
if (d->spanningIndexes.isEmpty() || !d->model)
return false;
- QModelIndex index = d->model->index(row, 0, parent);
- for (int i = 0; i < d->spanningIndexes.count(); ++i)
- if (d->spanningIndexes.at(i) == index)
- return true;
- return false;
+ const QModelIndex index = d->model->index(row, 0, parent);
+ return d->spanningIndexes.contains(index);
}
/*!
@@ -653,20 +651,14 @@ void QTreeView::setFirstColumnSpanned(int row, const QModelIndex &parent, bool s
Q_D(QTreeView);
if (!d->model)
return;
- QModelIndex index = d->model->index(row, 0, parent);
+ const QModelIndex index = d->model->index(row, 0, parent);
if (!index.isValid())
return;
- if (span) {
- QPersistentModelIndex persistent(index);
- if (!d->spanningIndexes.contains(persistent))
- d->spanningIndexes.append(persistent);
- } else {
- QPersistentModelIndex persistent(index);
- int i = d->spanningIndexes.indexOf(persistent);
- if (i >= 0)
- d->spanningIndexes.remove(i);
- }
+ if (span)
+ d->spanningIndexes.insert(index);
+ else
+ d->spanningIndexes.remove(index);
d->executePostedLayout();
int i = d->viewIndex(index);
@@ -1420,7 +1412,7 @@ QItemViewPaintPairs QTreeViewPrivate::draggablePaintPairs(const QModelIndexList
if (spanningIndexes.isEmpty())
return QAbstractItemViewPrivate::draggablePaintPairs(indexes, r);
QModelIndexList list;
- foreach (const QModelIndex &idx, indexes) {
+ for (const QModelIndex &idx : indexes) {
if (idx.column() > 0 && q->isFirstColumnSpanned(idx.row(), idx.parent()))
continue;
list << idx;
@@ -2000,19 +1992,21 @@ void QTreeView::keyPressEvent(QKeyEvent *event)
if (d->isIndexValid(current) && d->model && d->itemsExpandable) {
switch (event->key()) {
case Qt::Key_Asterisk: {
+ // do layouting only once after expanding is done
+ d->doDelayedItemsLayout();
QStack<QModelIndex> parents;
parents.push(current);
- while (!parents.isEmpty()) {
- QModelIndex parent = parents.pop();
- for (int row = 0; row < d->model->rowCount(parent); ++row) {
- QModelIndex child = d->model->index(row, 0, parent);
- if (!d->isIndexValid(child))
- break;
- parents.push(child);
- expand(child);
- }
+ while (!parents.isEmpty()) {
+ QModelIndex parent = parents.pop();
+ for (int row = 0; row < d->model->rowCount(parent); ++row) {
+ QModelIndex child = d->model->index(row, 0, parent);
+ if (!d->isIndexValid(child))
+ break;
+ parents.push(child);
+ expand(child);
}
- expand(current);
+ }
+ expand(current);
break; }
case Qt::Key_Plus:
expand(current);
@@ -2495,7 +2489,6 @@ void QTreeView::scrollContentsBy(int dx, int dy)
int previousScrollbarValue = currentScrollbarValue + dy; // -(-dy)
int currentViewIndex = currentScrollbarValue; // the first visible item
int previousViewIndex = previousScrollbarValue;
- const QVector<QTreeViewItem> viewItems = d->viewItems;
dy = 0;
if (previousViewIndex < currentViewIndex) { // scrolling down
for (int i = previousViewIndex; i < currentViewIndex; ++i) {
@@ -3732,9 +3725,14 @@ void QTreeViewPrivate::updateScrollBars()
int QTreeViewPrivate::itemDecorationAt(const QPoint &pos) const
{
+ Q_Q(const QTreeView);
executePostedLayout();
- int x = pos.x();
- int column = header->logicalIndexAt(x);
+ bool spanned = false;
+ if (!spanningIndexes.isEmpty()) {
+ const QModelIndex index = q->indexAt(pos);
+ spanned = q->isFirstColumnSpanned(index.row(), index.parent());
+ }
+ const int column = spanned ? 0 : header->logicalIndexAt(pos.x());
if (!isTreePosition(column))
return -1; // no logical index at x
diff --git a/src/widgets/itemviews/qtreeview_p.h b/src/widgets/itemviews/qtreeview_p.h
index 061bd1fc57..0a0e7aae87 100644
--- a/src/widgets/itemviews/qtreeview_p.h
+++ b/src/widgets/itemviews/qtreeview_p.h
@@ -249,7 +249,7 @@ public:
void updateIndentationFromStyle();
// used for spanning rows
- QVector<QPersistentModelIndex> spanningIndexes;
+ QSet<QPersistentModelIndex> spanningIndexes;
// used for updating resized columns
int columnResizeTimerID;
diff --git a/src/widgets/itemviews/qtreewidget.cpp b/src/widgets/itemviews/qtreewidget.cpp
index 654c241079..a0af27115d 100644
--- a/src/widgets/itemviews/qtreewidget.cpp
+++ b/src/widgets/itemviews/qtreewidget.cpp
@@ -52,9 +52,6 @@
QT_BEGIN_NAMESPACE
-// workaround for VC++ 6.0 linker bug (?)
-typedef bool(*LessThan)(const QPair<QTreeWidgetItem*,int>&,const QPair<QTreeWidgetItem*,int>&);
-
class QTreeModelLessThan
{
public:
@@ -610,7 +607,7 @@ void QTreeModel::ensureSorted(int column, Qt::SortOrder order,
sorting[i].second = start + i;
}
- LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
+ const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
std::stable_sort(sorting.begin(), sorting.end(), compare);
QModelIndexList oldPersistentIndexes;
@@ -777,7 +774,7 @@ bool QTreeModel::isChanging() const
if column is -1 then all columns have changed
*/
-void QTreeModel::emitDataChanged(QTreeWidgetItem *item, int column)
+void QTreeModel::emitDataChanged(QTreeWidgetItem *item, int column, const QVector<int> &roles)
{
if (signalsBlocked())
return;
@@ -800,7 +797,7 @@ void QTreeModel::emitDataChanged(QTreeWidgetItem *item, int column)
topLeft = index(item, column);
bottomRight = topLeft;
}
- emit dataChanged(topLeft, bottomRight);
+ emit dataChanged(topLeft, bottomRight, roles);
}
void QTreeModel::beginInsertItems(QTreeWidgetItem *parent, int row, int count)
@@ -850,7 +847,7 @@ void QTreeModel::sortItems(QList<QTreeWidgetItem*> *items, int column, Qt::SortO
}
// do the sorting
- LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
+ const auto compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
std::stable_sort(sorting.begin(), sorting.end(), compare);
QModelIndexList fromList;
@@ -1015,6 +1012,14 @@ void QTreeModel::timerEvent(QTimerEvent *ev)
\sa isHidden()
*/
+void QTreeWidgetItem::setHidden(bool ahide)
+{
+ if (view) {
+ view->setItemHidden(this, ahide);
+ d->hidden = ahide;
+ }
+}
+
/*!
\fn bool QTreeWidgetItem::isHidden() const
\since 4.2
@@ -1024,6 +1029,11 @@ void QTreeModel::timerEvent(QTimerEvent *ev)
\sa setHidden()
*/
+bool QTreeWidgetItem::isHidden() const
+{
+ return (view ? d->hidden : false);
+}
+
/*!
\fn void QTreeWidgetItem::setExpanded(bool expand)
\since 4.2
@@ -1651,6 +1661,25 @@ void QTreeWidgetItem::setFlags(Qt::ItemFlags flags)
itemChanged();
}
+void QTreeWidgetItemPrivate::updateHiddenStatus(QTreeWidgetItem *item, bool inserting)
+{
+ QTreeModel *model = (item->view ? qobject_cast<QTreeModel*>(item->view->model()) : 0);
+ if (!model)
+ return;
+ QStack<QTreeWidgetItem *> parents;
+ parents.push(item);
+ while (!parents.isEmpty()) {
+ QTreeWidgetItem *parent = parents.pop();
+ QModelIndex index = model->index(parent, 0);
+ if (parent->d->hidden)
+ item->view->setRowHidden(index.row(), index.parent(), inserting);
+ for (int i = 0; i < parent->children.count(); ++i) {
+ QTreeWidgetItem *child = parent->children.at(i);
+ parents.push(child);
+ }
+ }
+}
+
void QTreeWidgetItemPrivate::propagateDisabled(QTreeWidgetItem *item)
{
Q_ASSERT(item);
@@ -1766,11 +1795,14 @@ void QTreeWidgetItem::setData(int column, int role, const QVariant &value)
}
if (model) {
- model->emitDataChanged(this, column);
+ const QVector<int> roles((role == Qt::DisplayRole || role == Qt::EditRole) ?
+ QVector<int>({Qt::DisplayRole, Qt::EditRole}) :
+ QVector<int>({role}));
+ model->emitDataChanged(this, column, roles);
if (role == Qt::CheckStateRole) {
QTreeWidgetItem *p;
for (p = par; p && (p->itemFlags & Qt::ItemIsAutoTristate); p = p->par)
- model->emitDataChanged(p, column);
+ model->emitDataChanged(p, column, roles);
}
}
}
@@ -1937,6 +1969,7 @@ void QTreeWidgetItem::insertChild(int index, QTreeWidgetItem *child)
stack.push(i->children.at(c));
}
children.insert(index, child);
+ d->updateHiddenStatus(child, true);
model->endInsertItems();
model->skipPendingSort = wasSkipSort;
} else {
@@ -1974,6 +2007,7 @@ QTreeWidgetItem *QTreeWidgetItem::takeChild(int index)
}
if (index >= 0 && index < children.count()) {
if (model) model->beginRemoveItems(this, index, 1);
+ d->updateHiddenStatus(children.at(index), false);
QTreeWidgetItem *item = children.takeAt(index);
item->par = 0;
QStack<QTreeWidgetItem*> stack;
@@ -2052,6 +2086,7 @@ void QTreeWidgetItem::insertChildren(int index, const QList<QTreeWidgetItem*> &c
this->children.insert(index + n, child);
if (child->par)
d->propagateDisabled(child);
+ d->updateHiddenStatus(child, true);
}
if (model) model->endInsertItems();
}
@@ -3099,6 +3134,8 @@ bool QTreeWidget::isItemHidden(const QTreeWidgetItem *item) const
*/
void QTreeWidget::setItemHidden(const QTreeWidgetItem *item, bool hide)
{
+ if (!item)
+ return;
Q_D(QTreeWidget);
if (item == d->treeModel()->headerItem) {
header()->setHidden(hide);
@@ -3106,6 +3143,7 @@ void QTreeWidget::setItemHidden(const QTreeWidgetItem *item, bool hide)
const QModelIndex index = d->index(item);
setRowHidden(index.row(), index.parent(), hide);
}
+ item->d->hidden = hide;
}
/*!
diff --git a/src/widgets/itemviews/qtreewidget.h b/src/widgets/itemviews/qtreewidget.h
index a31af0428a..975f208702 100644
--- a/src/widgets/itemviews/qtreewidget.h
+++ b/src/widgets/itemviews/qtreewidget.h
@@ -82,8 +82,8 @@ public:
inline void setSelected(bool select);
inline bool isSelected() const;
- inline void setHidden(bool hide);
- inline bool isHidden() const;
+ void setHidden(bool hide);
+ bool isHidden() const;
inline void setExpanded(bool expand);
inline bool isExpanded() const;
@@ -339,6 +339,7 @@ Q_SIGNALS:
void itemDoubleClicked(QTreeWidgetItem *item, int column);
void itemActivated(QTreeWidgetItem *item, int column);
void itemEntered(QTreeWidgetItem *item, int column);
+ // ### Qt 6: add changed roles
void itemChanged(QTreeWidgetItem *item, int column);
void itemExpanded(QTreeWidgetItem *item);
void itemCollapsed(QTreeWidgetItem *item);
@@ -409,12 +410,6 @@ inline void QTreeWidgetItem::setSelected(bool aselect)
inline bool QTreeWidgetItem::isSelected() const
{ return (view ? view->isItemSelected(this) : false); }
-inline void QTreeWidgetItem::setHidden(bool ahide)
-{ if (view) view->setItemHidden(this, ahide); }
-
-inline bool QTreeWidgetItem::isHidden() const
-{ return (view ? view->isItemHidden(this) : false); }
-
inline void QTreeWidgetItem::setExpanded(bool aexpand)
{ if (view) view->setItemExpanded(this, aexpand); }
diff --git a/src/widgets/itemviews/qtreewidget_p.h b/src/widgets/itemviews/qtreewidget_p.h
index f4625842ef..adc2c2c421 100644
--- a/src/widgets/itemviews/qtreewidget_p.h
+++ b/src/widgets/itemviews/qtreewidget_p.h
@@ -139,7 +139,7 @@ public:
protected:
QTreeModel(QTreeModelPrivate &, QTreeWidget *parent = 0);
- void emitDataChanged(QTreeWidgetItem *item, int column);
+ void emitDataChanged(QTreeWidgetItem *item, int column, const QVector<int> &roles);
void beginInsertItems(QTreeWidgetItem *parent, int row, int count);
void endInsertItems();
void beginRemoveItems(QTreeWidgetItem *parent, int row, int count);
@@ -187,13 +187,16 @@ class QTreeWidgetItemPrivate
{
public:
QTreeWidgetItemPrivate(QTreeWidgetItem *item)
- : q(item), disabled(false), selected(false), rowGuess(-1), policy(QTreeWidgetItem::DontShowIndicatorWhenChildless) {}
+ : q(item), disabled(false), selected(false), hidden(false), rowGuess(-1),
+ policy(QTreeWidgetItem::DontShowIndicatorWhenChildless) {}
void propagateDisabled(QTreeWidgetItem *item);
+ void updateHiddenStatus(QTreeWidgetItem *item, bool inserting);
void sortChildren(int column, Qt::SortOrder order, bool climb);
QTreeWidgetItem *q;
QVariantList display;
uint disabled : 1;
uint selected : 1;
+ uint hidden : 1;
int rowGuess;
QTreeWidgetItem::ChildIndicatorPolicy policy;
};
diff --git a/src/widgets/kernel/kernel.pri b/src/widgets/kernel/kernel.pri
index 1bdcecbc81..c2f6e4ce75 100644
--- a/src/widgets/kernel/kernel.pri
+++ b/src/widgets/kernel/kernel.pri
@@ -35,7 +35,8 @@ HEADERS += \
kernel/qgesturemanager_p.h \
kernel/qdesktopwidget_p.h \
kernel/qwidgetwindow_p.h \
- kernel/qwindowcontainer_p.h
+ kernel/qwindowcontainer_p.h \
+ kernel/qtestsupport_widgets.h
SOURCES += \
kernel/qaction.cpp \
@@ -60,7 +61,8 @@ SOURCES += \
kernel/qdesktopwidget.cpp \
kernel/qwidgetsvariant.cpp \
kernel/qwidgetwindow.cpp \
- kernel/qwindowcontainer.cpp
+ kernel/qwindowcontainer.cpp \
+ kernel/qtestsupport_widgets.cpp
macx: {
HEADERS += kernel/qmacgesturerecognizer_p.h
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index ba315d4338..45b98e9475 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -110,6 +110,8 @@
#include <qpa/qplatformwindow.h>
+#include <qtwidgets_tracepoints_p.h>
+
//#define ALIEN_DEBUG
static void initResources()
@@ -1025,17 +1027,17 @@ QString QApplication::styleSheet() const
void QApplication::setStyleSheet(const QString& styleSheet)
{
QApplicationPrivate::styleSheet = styleSheet;
- QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle*>(QApplicationPrivate::app_style);
+ QStyleSheetStyle *styleSheetStyle = qt_styleSheet(QApplicationPrivate::app_style);
if (styleSheet.isEmpty()) { // application style sheet removed
- if (!proxy)
+ if (!styleSheetStyle)
return; // there was no stylesheet before
- setStyle(proxy->base);
- } else if (proxy) { // style sheet update, just repolish
- proxy->repolish(qApp);
+ setStyle(styleSheetStyle->base);
+ } else if (styleSheetStyle) { // style sheet update, just repolish
+ styleSheetStyle->repolish(qApp);
} else { // stylesheet set the first time
- QStyleSheetStyle *newProxy = new QStyleSheetStyle(QApplicationPrivate::app_style);
- QApplicationPrivate::app_style->setParent(newProxy);
- setStyle(newProxy);
+ QStyleSheetStyle *newStyleSheetStyle = new QStyleSheetStyle(QApplicationPrivate::app_style);
+ QApplicationPrivate::app_style->setParent(newStyleSheetStyle);
+ setStyle(newStyleSheetStyle);
}
}
@@ -1145,11 +1147,11 @@ void QApplication::setStyle(QStyle *style)
QStyle *old = QApplicationPrivate::app_style; // save
#ifndef QT_NO_STYLE_STYLESHEET
- if (!QApplicationPrivate::styleSheet.isEmpty() && !qobject_cast<QStyleSheetStyle *>(style)) {
+ if (!QApplicationPrivate::styleSheet.isEmpty() && !qt_styleSheet(style)) {
// we have a stylesheet already and a new style is being set
- QStyleSheetStyle *newProxy = new QStyleSheetStyle(style);
- style->setParent(newProxy);
- QApplicationPrivate::app_style = newProxy;
+ QStyleSheetStyle *newStyleSheetStyle = new QStyleSheetStyle(style);
+ style->setParent(newStyleSheetStyle);
+ QApplicationPrivate::app_style = newStyleSheetStyle;
} else
#endif // QT_NO_STYLE_STYLESHEET
QApplicationPrivate::app_style = style;
@@ -1199,8 +1201,8 @@ void QApplication::setStyle(QStyle *style)
}
#ifndef QT_NO_STYLE_STYLESHEET
- if (QStyleSheetStyle *oldProxy = qobject_cast<QStyleSheetStyle *>(old)) {
- oldProxy->deref();
+ if (QStyleSheetStyle *oldStyleSheetStyle = qt_styleSheet(old)) {
+ oldStyleSheetStyle->deref();
} else
#endif
if (old && old->parent() == qApp) {
@@ -1343,7 +1345,6 @@ void QApplication::setGlobalStrut(const QSize& strut)
/*!
\fn QPalette QApplication::palette(const QWidget* widget)
- \overload
If a \a widget is passed, the default palette for the widget's class is
returned. This may or may not be the application palette. In most cases
@@ -2627,7 +2628,7 @@ QWidget *QApplicationPrivate::pickMouseReceiver(QWidget *candidate, const QPoint
bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
QWidget *alienWidget, QWidget *nativeWidget,
QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver,
- bool spontaneous)
+ bool spontaneous, bool onlyDispatchEnterLeave)
{
Q_ASSERT(receiver);
Q_ASSERT(event);
@@ -2688,11 +2689,17 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
// We need this quard in case someone opens a modal dialog / popup. If that's the case
// leaveAfterRelease is set to null, but we shall not update lastMouseReceiver.
const bool wasLeaveAfterRelease = leaveAfterRelease != 0;
- bool result;
- if (spontaneous)
- result = QApplication::sendSpontaneousEvent(receiver, event);
- else
- result = QApplication::sendEvent(receiver, event);
+ bool result = true;
+ // This code is used for sending the synthetic enter/leave events for cases where it is needed
+ // due to other events causing the widget under the mouse to change. However in those cases
+ // we do not want to send the mouse event associated with this call, so this enables us to
+ // not send the unneeded mouse event
+ if (!onlyDispatchEnterLeave) {
+ if (spontaneous)
+ result = QApplication::sendSpontaneousEvent(receiver, event);
+ else
+ result = QApplication::sendEvent(receiver, event);
+ }
if (!graphicsWidget && leaveAfterRelease && event->type() == QEvent::MouseButtonRelease
&& !event->buttons() && QWidget::mouseGrabber() != leaveAfterRelease) {
@@ -2767,9 +2774,10 @@ void QApplicationPrivate::sendSyntheticEnterLeave(QWidget *widget)
if (widget->data->in_destructor && qt_button_down == widget)
qt_button_down = 0;
- // Send enter/leave events followed by a mouse move on the entered widget.
+ // A mouse move is not actually sent, but we utilize the sendMouseEvent() call to send the
+ // enter/leave events as appropriate
QMouseEvent e(QEvent::MouseMove, pos, windowPos, globalPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier);
- sendMouseEvent(widgetUnderCursor, &e, widgetUnderCursor, tlw, &qt_button_down, qt_last_mouse_receiver);
+ sendMouseEvent(widgetUnderCursor, &e, widgetUnderCursor, tlw, &qt_button_down, qt_last_mouse_receiver, true, true);
#else // !QT_NO_CURSOR
Q_UNUSED(widget);
#endif // QT_NO_CURSOR
@@ -2947,8 +2955,10 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
d->checkReceiverThread(receiver);
#endif
- if (receiver->isWindowType())
- QGuiApplicationPrivate::sendQWindowEventToQPlatformWindow(static_cast<QWindow *>(receiver), e);
+ if (receiver->isWindowType()) {
+ if (QGuiApplicationPrivate::sendQWindowEventToQPlatformWindow(static_cast<QWindow *>(receiver), e))
+ return true; // Platform plugin ate the event
+ }
if(e->spontaneous()) {
// Capture the current mouse and keyboard states. Doing so here is
@@ -3288,6 +3298,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(),
wheel->modifiers(), phase, wheel->source(), wheel->inverted());
+ we.setTimestamp(wheel->timestamp());
bool eventAccepted;
do {
we.spont = spontaneous && w == receiver;
@@ -3324,6 +3335,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
const QPoint &relpos = QApplicationPrivate::wheel_widget->mapFromGlobal(wheel->globalPos());
QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(),
wheel->modifiers(), wheel->phase(), wheel->source());
+ we.setTimestamp(wheel->timestamp());
we.spont = true;
we.ignore();
d->notify_helper(QApplicationPrivate::wheel_widget, &we);
@@ -3375,6 +3387,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
tablet->tangentialPressure(), tablet->rotation(), tablet->z(),
tablet->modifiers(), tablet->uniqueId(), tablet->button(), tablet->buttons());
te.spont = e->spontaneous();
+ te.setAccepted(false);
res = d->notify_helper(w, w == receiver ? tablet : &te);
eventAccepted = ((w == receiver) ? tablet : &te)->isAccepted();
e->spont = false;
@@ -3649,7 +3662,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
break;
w = w->parentWidget();
}
- foreach (QGesture *g, allGestures)
+ for (QGesture *g : qAsConst(allGestures))
gestureEvent->setAccepted(g, false);
gestureEvent->m_accept = false; // to make sure we check individual gestures
} else {
@@ -3696,11 +3709,19 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e)
{
+ // These tracepoints (and the whole function, actually) are very similar
+ // to the ones in QCoreApplicationPrivate::notify_helper; the reason for their
+ // duplication is because tracepoint symbols are not exported by QtCore.
+ // If you adjust the tracepoints here, consider adjusting QCoreApplicationPrivate too.
+ Q_TRACE(QApplication_notify_entry, receiver, e, e->type());
+
// send to all application event filters
if (threadRequiresCoreApplication()
&& receiver->d_func()->threadData->thread == mainThread()
- && sendThroughApplicationEventFilters(receiver, e))
+ && sendThroughApplicationEventFilters(receiver, e)) {
+ Q_TRACE(QApplication_notify_event_filtered, receiver, e, e->type());
return true;
+ }
if (receiver->isWidgetType()) {
QWidget *widget = static_cast<QWidget *>(receiver);
@@ -3720,11 +3741,18 @@ bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e)
}
// send to all receiver event filters
- if (sendThroughObjectEventFilters(receiver, e))
+ if (sendThroughObjectEventFilters(receiver, e)) {
+ Q_TRACE(QApplication_notify_event_filtered, receiver, e, e->type());
return true;
+ }
+
+ Q_TRACE(QApplication_notify_before_delivery, receiver, e, e->type());
// deliver the event
- bool consumed = receiver->event(e);
+ const bool consumed = receiver->event(e);
+
+ Q_TRACE(QApplication_notify_after_delivery, receiver, e, e->type(), consumed);
+
QCoreApplicationPrivate::setEventSpontaneous(e, false);
return consumed;
}
@@ -4493,12 +4521,12 @@ void QApplicationPrivate::notifyDragStarted(const QDrag *drag)
#endif // QT_CONFIG(draganddrop)
#ifndef QT_NO_GESTURES
-QGestureManager* QGestureManager::instance()
+QGestureManager* QGestureManager::instance(InstanceCreation ic)
{
QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
if (!qAppPriv)
return 0;
- if (!qAppPriv->gestureManager)
+ if (!qAppPriv->gestureManager && ic == ForceCreation)
qAppPriv->gestureManager = new QGestureManager(qApp);
return qAppPriv->gestureManager;
}
diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h
index 488ca6cbfd..2d9468cc21 100644
--- a/src/widgets/kernel/qapplication_p.h
+++ b/src/widgets/kernel/qapplication_p.h
@@ -226,7 +226,7 @@ public:
QWidget *buttonDown, QWidget *alienWidget);
static bool sendMouseEvent(QWidget *receiver, QMouseEvent *event, QWidget *alienWidget,
QWidget *native, QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver,
- bool spontaneous = true);
+ bool spontaneous = true, bool onlyDispatchEnterLeave = false);
void sendSyntheticEnterLeave(QWidget *widget);
static QWindow *windowForWidget(const QWidget *widget)
diff --git a/src/widgets/kernel/qformlayout.cpp b/src/widgets/kernel/qformlayout.cpp
index 595ff3eb6e..66e8858e21 100644
--- a/src/widgets/kernel/qformlayout.cpp
+++ b/src/widgets/kernel/qformlayout.cpp
@@ -1435,13 +1435,7 @@ static void clearAndDestroyQLayoutItem(QLayoutItem *item)
up one row and the freed vertical space is redistributed amongst the remaining rows.
You can use this function to undo a previous addRow() or insertRow():
- \code
- QFormLayout *flay = ...;
- QPointer<QLineEdit> le = new QLineEdit;
- flay->insertRow(2, "User:", le);
- // later:
- flay->removeRow(2); // le == nullptr at this point
- \endcode
+ \snippet code/src_gui_kernel_qformlayout.cpp 3
If you want to remove the row from the layout without deleting the widgets, use takeRow() instead.
@@ -1467,13 +1461,7 @@ void QFormLayout::removeRow(int row)
up one row and the freed vertical space is redistributed amongst the remaining rows.
You can use this function to undo a previous addRow() or insertRow():
- \code
- QFormLayout *flay = ...;
- QPointer<QLineEdit> le = new QLineEdit;
- flay->insertRow(2, "User:", le);
- // later:
- flay->removeRow(le); // le == nullptr at this point
- \endcode
+ \snippet code/src_gui_kernel_qformlayout.cpp 4
If you want to remove the row from the layout without deleting the widgets, use takeRow() instead.
@@ -1499,13 +1487,7 @@ void QFormLayout::removeRow(QWidget *widget)
up one row and the freed vertical space is redistributed amongst the remaining rows.
You can use this function to undo a previous addRow() or insertRow():
- \code
- QFormLayout *flay = ...;
- QPointer<QVBoxLayout> vbl = new QVBoxLayout;
- flay->insertRow(2, "User:", vbl);
- // later:
- flay->removeRow(layout); // vbl == nullptr at this point
- \endcode
+ \snippet code/src_gui_kernel_qformlayout.cpp 5
If you want to remove the row from the form layout without deleting the inserted layout,
use takeRow() instead.
@@ -1532,13 +1514,7 @@ void QFormLayout::removeRow(QLayout *layout)
up one row and the freed vertical space is redistributed amongst the remaining rows.
You can use this function to undo a previous addRow() or insertRow():
- \code
- QFormLayout *flay = ...;
- QPointer<QLineEdit> le = new QLineEdit;
- flay->insertRow(2, "User:", le);
- // later:
- QFormLayout::TakeRowResult result = flay->takeRow(2);
- \endcode
+ \snippet code/src_gui_kernel_qformlayout.cpp 6
If you want to remove the row from the layout and delete the widgets, use removeRow() instead.
@@ -1583,13 +1559,7 @@ QFormLayout::TakeRowResult QFormLayout::takeRow(int row)
After this call, rowCount() is decremented by one. All following rows are shifted
up one row and the freed vertical space is redistributed amongst the remaining rows.
- \code
- QFormLayout *flay = ...;
- QPointer<QLineEdit> le = new QLineEdit;
- flay->insertRow(2, "User:", le);
- // later:
- QFormLayout::TakeRowResult result = flay->takeRow(widget);
- \endcode
+ \snippet code/src_gui_kernel_qformlayout.cpp 7
If you want to remove the row from the layout and delete the widgets, use removeRow() instead.
@@ -1628,13 +1598,7 @@ QFormLayout::TakeRowResult QFormLayout::takeRow(QWidget *widget)
After this call, rowCount() is decremented by one. All following rows are shifted
up one row and the freed vertical space is redistributed amongst the remaining rows.
- \code
- QFormLayout *flay = ...;
- QPointer<QVBoxLayout> vbl = new QVBoxLayout;
- flay->insertRow(2, "User:", vbl);
- // later:
- QFormLayout::TakeRowResult result = flay->takeRow(widget);
- \endcode
+ \snippet code/src_gui_kernel_qformlayout.cpp 8
If you want to remove the row from the form layout and delete the inserted layout,
use removeRow() instead.
diff --git a/src/widgets/kernel/qgesture.cpp b/src/widgets/kernel/qgesture.cpp
index 7f8bf18e90..fc715687c6 100644
--- a/src/widgets/kernel/qgesture.cpp
+++ b/src/widgets/kernel/qgesture.cpp
@@ -916,7 +916,7 @@ QGesture *QGestureEvent::gesture(Qt::GestureType type) const
QList<QGesture *> QGestureEvent::activeGestures() const
{
QList<QGesture *> gestures;
- foreach (QGesture *gesture, m_gestures) {
+ for (QGesture *gesture : m_gestures) {
if (gesture->state() != Qt::GestureCanceled)
gestures.append(gesture);
}
@@ -929,7 +929,7 @@ QList<QGesture *> QGestureEvent::activeGestures() const
QList<QGesture *> QGestureEvent::canceledGestures() const
{
QList<QGesture *> gestures;
- foreach (QGesture *gesture, m_gestures) {
+ for (QGesture *gesture : m_gestures) {
if (gesture->state() == Qt::GestureCanceled)
gestures.append(gesture);
}
diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp
index 5bf66d68e3..c4188044cf 100644
--- a/src/widgets/kernel/qgesturemanager.cpp
+++ b/src/widgets/kernel/qgesturemanager.cpp
@@ -773,7 +773,7 @@ void QGestureManager::recycle(QGesture *gesture)
bool QGestureManager::gesturePending(QObject *o)
{
- const QGestureManager *gm = QGestureManager::instance();
+ const QGestureManager *gm = QGestureManager::instance(DontForceCreation);
return gm && gm->m_gestureOwners.key(o);
}
diff --git a/src/widgets/kernel/qgesturemanager_p.h b/src/widgets/kernel/qgesturemanager_p.h
index 3df80bab55..3a5c9822eb 100644
--- a/src/widgets/kernel/qgesturemanager_p.h
+++ b/src/widgets/kernel/qgesturemanager_p.h
@@ -81,7 +81,9 @@ public:
bool filterEvent(QGraphicsObject *receiver, QEvent *event);
#endif // QT_CONFIG(graphicsview)
- static QGestureManager* instance(); // declared in qapplication.cpp
+ enum InstanceCreation { ForceCreation, DontForceCreation };
+
+ static QGestureManager *instance(InstanceCreation ic = ForceCreation); // declared in qapplication.cpp
static bool gesturePending(QObject *o);
void cleanupCachedGestures(QObject *target, Qt::GestureType type);
diff --git a/src/widgets/kernel/qgridlayout.cpp b/src/widgets/kernel/qgridlayout.cpp
index db8ef89477..f1c6c96a6d 100644
--- a/src/widgets/kernel/qgridlayout.cpp
+++ b/src/widgets/kernel/qgridlayout.cpp
@@ -1029,7 +1029,7 @@ QRect QGridLayoutPrivate::cellRect(int row, int col) const
This illustration shows a fragment of a dialog with a five-column,
three-row grid (the grid is shown overlaid in magenta):
- \image gridlayout.png A grid layout
+ \image qgridlayout.png A grid layout
Columns 0, 2 and 4 in this dialog fragment are made up of a
QLabel, a QLineEdit, and a QListBox. Columns 1 and 3 are
diff --git a/src/widgets/kernel/qlayout.cpp b/src/widgets/kernel/qlayout.cpp
index 9ce1c1c2d4..eac5674161 100644
--- a/src/widgets/kernel/qlayout.cpp
+++ b/src/widgets/kernel/qlayout.cpp
@@ -109,10 +109,11 @@ static int menuBarHeightForWidth(QWidget *menubar, int w)
/*!
Constructs a new top-level QLayout, with parent \a parent.
- \a parent may not be 0.
+ \a parent may not be a \c nullptr.
- There can be only one top-level layout for a widget. It is
- returned by QWidget::layout().
+ The layout is set directly as the top-level layout for
+ \a parent. There can be only one top-level layout for a
+ widget. It is returned by QWidget::layout().
*/
QLayout::QLayout(QWidget *parent)
: QObject(*new QLayoutPrivate, parent)
@@ -1246,6 +1247,26 @@ int QLayout::indexOf(QWidget *widget) const
}
/*!
+ \since 5.12
+ Searches for layout item \a layoutItem in this layout (not including child
+ layouts).
+
+ Returns the index of \a layoutItem, or -1 if \a layoutItem is not found.
+*/
+int QLayout::indexOf(QLayoutItem *layoutItem) const
+{
+ int i = 0;
+ QLayoutItem *item = itemAt(i);
+ while (item) {
+ if (item == layoutItem)
+ return i;
+ ++i;
+ item = itemAt(i);
+ }
+ return -1;
+}
+
+/*!
\enum QLayout::SizeConstraint
The possible values are:
diff --git a/src/widgets/kernel/qlayout.h b/src/widgets/kernel/qlayout.h
index bcc33a0811..616f4e7164 100644
--- a/src/widgets/kernel/qlayout.h
+++ b/src/widgets/kernel/qlayout.h
@@ -122,6 +122,7 @@ public:
virtual QLayoutItem *itemAt(int index) const = 0;
virtual QLayoutItem *takeAt(int index) = 0;
virtual int indexOf(QWidget *) const;
+ QT6_VIRTUAL int indexOf(QLayoutItem *) const;
virtual int count() const = 0;
bool isEmpty() const override;
QSizePolicy::ControlTypes controlTypes() const override;
diff --git a/src/widgets/kernel/qmacgesturerecognizer_p.h b/src/widgets/kernel/qmacgesturerecognizer_p.h
index e381a6cc2f..739fc201b7 100644
--- a/src/widgets/kernel/qmacgesturerecognizer_p.h
+++ b/src/widgets/kernel/qmacgesturerecognizer_p.h
@@ -66,9 +66,9 @@ class QMacSwipeGestureRecognizer : public QGestureRecognizer
public:
QMacSwipeGestureRecognizer();
- QGesture *create(QObject *target);
- QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event);
- void reset(QGesture *gesture);
+ QGesture *create(QObject *target) override;
+ QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event) override;
+ void reset(QGesture *gesture) override;
};
class QMacPinchGestureRecognizer : public QGestureRecognizer
@@ -76,9 +76,9 @@ class QMacPinchGestureRecognizer : public QGestureRecognizer
public:
QMacPinchGestureRecognizer();
- QGesture *create(QObject *target);
- QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event);
- void reset(QGesture *gesture);
+ QGesture *create(QObject *target) override;
+ QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event) override;
+ void reset(QGesture *gesture) override;
};
class QMacPanGestureRecognizer : public QObject, public QGestureRecognizer
@@ -86,9 +86,9 @@ class QMacPanGestureRecognizer : public QObject, public QGestureRecognizer
public:
QMacPanGestureRecognizer();
- QGesture *create(QObject *target);
- QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event);
- void reset(QGesture *gesture);
+ QGesture *create(QObject *target) override;
+ QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event) override;
+ void reset(QGesture *gesture) override;
protected:
void timerEvent(QTimerEvent *ev) override;
private:
diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp
index c96b6812c4..ed0fe0ed91 100644
--- a/src/widgets/kernel/qopenglwidget.cpp
+++ b/src/widgets/kernel/qopenglwidget.cpp
@@ -906,9 +906,19 @@ void QOpenGLWidgetPrivate::invalidateFbo()
const int gl_color_attachment0 = 0x8CE0; // GL_COLOR_ATTACHMENT0
const int gl_depth_attachment = 0x8D00; // GL_DEPTH_ATTACHMENT
const int gl_stencil_attachment = 0x8D20; // GL_STENCIL_ATTACHMENT
+#ifdef Q_OS_WASM
+ // webgl does not allow separate depth and stencil attachments
+ // QTBUG-69913
+ const int gl_depth_stencil_attachment = 0x821A; // GL_DEPTH_STENCIL_ATTACHMENT
+
+ const GLenum attachments[] = {
+ gl_color_attachment0, gl_depth_attachment, gl_stencil_attachment, gl_depth_stencil_attachment
+ };
+#else
const GLenum attachments[] = {
gl_color_attachment0, gl_depth_attachment, gl_stencil_attachment
};
+#endif
f->glDiscardFramebufferEXT(GL_FRAMEBUFFER, sizeof attachments / sizeof *attachments, attachments);
} else {
f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
@@ -938,7 +948,8 @@ QImage QOpenGLWidgetPrivate::grabFramebuffer()
q->makeCurrent();
}
- QImage res = qt_gl_read_framebuffer(q->size() * q->devicePixelRatioF(), false, false);
+ const bool hasAlpha = q->format().hasAlpha();
+ QImage res = qt_gl_read_framebuffer(q->size() * q->devicePixelRatioF(), hasAlpha, hasAlpha);
res.setDevicePixelRatio(q->devicePixelRatioF());
// While we give no guarantees of what is going to be left bound, prefer the
diff --git a/src/widgets/kernel/qshortcut.cpp b/src/widgets/kernel/qshortcut.cpp
index fde039c75e..a680ff7913 100644
--- a/src/widgets/kernel/qshortcut.cpp
+++ b/src/widgets/kernel/qshortcut.cpp
@@ -149,8 +149,16 @@ static bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidge
bool visible = w->isVisible();
#if QT_CONFIG(menubar)
if (QMenuBar *menuBar = qobject_cast<QMenuBar *>(w)) {
- if (menuBar->isNativeMenuBar())
- visible = true;
+ if (auto *pmb = menuBar->platformMenuBar()) {
+ if (menuBar->parentWidget()) {
+ visible = true;
+ } else {
+ if (auto *ww = qobject_cast<QWidgetWindow *>(pmb->parentWindow()))
+ w = ww->widget(); // Good enough since we only care about the window
+ else
+ return false; // This is not a QWidget window. We won't deliver
+ }
+ }
}
#endif
diff --git a/src/widgets/kernel/qtestsupport_widgets.cpp b/src/widgets/kernel/qtestsupport_widgets.cpp
new file mode 100644
index 0000000000..b227e6ff5d
--- /dev/null
+++ b/src/widgets/kernel/qtestsupport_widgets.cpp
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 "qtestsupport_widgets.h"
+
+#include "qwidget.h"
+
+#include <QtGui/qwindow.h>
+#include <QtGui/qtestsupport_gui.h>
+
+QT_BEGIN_NAMESPACE
+
+/*! \fn bool qWaitForWindowActive(QWidget *widget, int timeout)
+ \relates QTest
+ \since 5.0
+
+ Waits for \a timeout milliseconds or until the \a widget's window is active.
+
+ Returns \c true if \c widget's window is active within \a timeout milliseconds, otherwise returns \c false.
+
+ \sa QTest::qWaitForWindowExposed(), QWidget::isActiveWindow()
+*/
+Q_WIDGETS_EXPORT Q_REQUIRED_RESULT bool QTest::qWaitForWindowActive(QWidget *widget, int timeout)
+{
+ if (QWindow *window = widget->window()->windowHandle())
+ return QTest::qWaitForWindowActive(window, timeout);
+ return false;
+}
+
+/*! \fn bool qWaitForWindowExposed(QWidget *widget, int timeout)
+ \relates QTest
+ \since 5.0
+
+ Waits for \a timeout milliseconds or until the \a widget's window is exposed.
+ Returns \c true if \c widget's window is exposed within \a timeout milliseconds, otherwise returns \c false.
+
+ This is mainly useful for asynchronous systems like X11, where a window will be mapped to screen some
+ time after being asked to show itself on the screen.
+
+ Note that a window that is mapped to screen may still not be considered exposed if the window client
+ area is completely covered by other windows, or if the window is otherwise not visible. This function
+ will then time out when waiting for such a window.
+
+ A specific configuration where this happens is when using QGLWidget as a viewport widget on macOS:
+ The viewport widget gets the expose event, not the parent widget.
+
+ \sa QTest::qWaitForWindowActive()
+*/
+Q_WIDGETS_EXPORT Q_REQUIRED_RESULT bool QTest::qWaitForWindowExposed(QWidget *widget, int timeout)
+{
+ if (QWindow *window = widget->window()->windowHandle())
+ return QTest::qWaitForWindowExposed(window, timeout);
+ return false;
+}
+
+/*! \fn bool qWaitForWindowShown(QWidget *widget, int timeout)
+ \relates QTest
+ \since 5.0
+ \deprecated
+
+ Waits for \a timeout milliseconds or until the \a widget's window is exposed.
+ Returns \c true if \c widget's window is exposed within \a timeout milliseconds, otherwise returns \c false.
+
+ This function does the same as qWaitForWindowExposed().
+
+ Example:
+
+ \code
+ QWidget widget;
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ \endcode
+
+ \sa QTest::qWaitForWindowActive(), QTest::qWaitForWindowExposed()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qtestsupport_widgets.h b/src/widgets/kernel/qtestsupport_widgets.h
new file mode 100644
index 0000000000..ca1406b0b2
--- /dev/null
+++ b/src/widgets/kernel/qtestsupport_widgets.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 QTESTSUPPORT_WIDGETS_H
+#define QTESTSUPPORT_WIDGETS_H
+
+#include "qtwidgetsglobal.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWidget;
+
+namespace QTest {
+Q_WIDGETS_EXPORT Q_REQUIRED_RESULT bool qWaitForWindowActive(QWidget *widget, int timeout = 5000);
+Q_WIDGETS_EXPORT Q_REQUIRED_RESULT bool qWaitForWindowExposed(QWidget *widget, int timeout = 5000);
+
+#if QT_DEPRECATED_SINCE(5, 0)
+QT_DEPRECATED Q_REQUIRED_RESULT inline static bool qWaitForWindowShown(QWidget *widget, int timeout = 5000)
+{ return QTest::qWaitForWindowExposed(widget, timeout); }
+#endif
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/widgets/kernel/qtooltip.cpp b/src/widgets/kernel/qtooltip.cpp
index ed7184302a..2e6575c163 100644
--- a/src/widgets/kernel/qtooltip.cpp
+++ b/src/widgets/kernel/qtooltip.cpp
@@ -123,11 +123,11 @@ class QTipLabel : public QLabel
{
Q_OBJECT
public:
- QTipLabel(const QString &text, QWidget *w, int msecDisplayTime);
+ QTipLabel(const QString &text, const QPoint &pos, QWidget *w, int msecDisplayTime);
~QTipLabel();
static QTipLabel *instance;
- void updateSize();
+ void updateSize(const QPoint &pos);
bool eventFilter(QObject *, QEvent *) override;
@@ -135,7 +135,7 @@ public:
bool fadingOut;
- void reuseTip(const QString &text, int msecDisplayTime);
+ void reuseTip(const QString &text, int msecDisplayTime, const QPoint &pos);
void hideTip();
void hideTipImmediately();
void setTipRect(QWidget *w, const QRect &r);
@@ -171,7 +171,7 @@ private:
QTipLabel *QTipLabel::instance = 0;
-QTipLabel::QTipLabel(const QString &text, QWidget *w, int msecDisplayTime)
+QTipLabel::QTipLabel(const QString &text, const QPoint &pos, QWidget *w, int msecDisplayTime)
#ifndef QT_NO_STYLE_STYLESHEET
: QLabel(w, Qt::ToolTip | Qt::BypassGraphicsProxyWidget), styleSheetParent(0), widget(0)
#else
@@ -192,7 +192,7 @@ QTipLabel::QTipLabel(const QString &text, QWidget *w, int msecDisplayTime)
setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0, this) / 255.0);
setMouseTracking(true);
fadingOut = false;
- reuseTip(text, msecDisplayTime);
+ reuseTip(text, msecDisplayTime, pos);
}
void QTipLabel::restartExpireTimer(int msecDisplayTime)
@@ -204,7 +204,7 @@ void QTipLabel::restartExpireTimer(int msecDisplayTime)
hideTimer.stop();
}
-void QTipLabel::reuseTip(const QString &text, int msecDisplayTime)
+void QTipLabel::reuseTip(const QString &text, int msecDisplayTime, const QPoint &pos)
{
#ifndef QT_NO_STYLE_STYLESHEET
if (styleSheetParent){
@@ -214,20 +214,35 @@ void QTipLabel::reuseTip(const QString &text, int msecDisplayTime)
}
#endif
- setWordWrap(Qt::mightBeRichText(text));
+ setWordWrap(true);
setText(text);
- updateSize();
+ updateSize(pos);
restartExpireTimer(msecDisplayTime);
}
-void QTipLabel::updateSize()
+void QTipLabel::updateSize(const QPoint &pos)
{
QFontMetrics fm(font());
QSize extra(1, 0);
// Make it look good with the default ToolTip font on Mac, which has a small descent.
if (fm.descent() == 2 && fm.ascent() >= 11)
++extra.rheight();
- resize(sizeHint() + extra);
+ QSize sh = sizeHint();
+ if (wordWrap()) {
+ QScreen *screen = QGuiApplication::screenAt(pos);
+ if (!screen)
+ screen = QGuiApplication::primaryScreen();
+ if (screen) {
+ const qreal screenWidth = screen->geometry().width();
+ if (sh.width() > screenWidth) {
+ // Try to use widely accepted 75chars max length or 80% of the screen width else.
+ // See https://en.wikipedia.org/wiki/Line_length
+ sh.setWidth(qMin(fm.averageCharWidth() * 75, static_cast<int>(screenWidth * .8)));
+ sh.setHeight(heightForWidth(sh.width()));
+ }
+ }
+ }
+ resize(sh + extra);
}
void QTipLabel::paintEvent(QPaintEvent *ev)
@@ -254,13 +269,13 @@ void QTipLabel::resizeEvent(QResizeEvent *e)
void QTipLabel::mouseMoveEvent(QMouseEvent *e)
{
- if (rect.isNull())
- return;
- QPoint pos = e->globalPos();
- if (widget)
- pos = widget->mapFromGlobal(pos);
- if (!rect.contains(pos))
- hideTip();
+ if (!rect.isNull()) {
+ QPoint pos = e->globalPos();
+ if (widget)
+ pos = widget->mapFromGlobal(pos);
+ if (!rect.contains(pos))
+ hideTip();
+ }
QLabel::mouseMoveEvent(e);
}
@@ -381,7 +396,7 @@ int QTipLabel::getTipScreen(const QPoint &pos, QWidget *w)
void QTipLabel::placeTip(const QPoint &pos, QWidget *w)
{
#ifndef QT_NO_STYLE_STYLESHEET
- if (testAttribute(Qt::WA_StyleSheet) || (w && qobject_cast<QStyleSheetStyle *>(w->style()))) {
+ if (testAttribute(Qt::WA_StyleSheet) || (w && qt_styleSheet(w->style()))) {
//the stylesheet need to know the real parent
QTipLabel::instance->setProperty("_q_stylesheet_parent", QVariant::fromValue(w));
//we force the style to be the QStyleSheetStyle, and force to clear the cache as well.
@@ -394,7 +409,7 @@ void QTipLabel::placeTip(const QPoint &pos, QWidget *w)
QTipLabel::instance, SLOT(styleSheetParentDestroyed()));
// QTBUG-64550: A font inherited by the style sheet might change the size,
// particular on Windows, where the tip is not parented on a window.
- QTipLabel::instance->updateSize();
+ QTipLabel::instance->updateSize(pos);
}
}
#endif //QT_NO_STYLE_STYLESHEET
@@ -497,7 +512,7 @@ void QToolTip::showText(const QPoint &pos, const QString &text, QWidget *w, cons
if (w)
localPos = w->mapFromGlobal(pos);
if (QTipLabel::instance->tipChanged(localPos, text, w)){
- QTipLabel::instance->reuseTip(text, msecDisplayTime);
+ QTipLabel::instance->reuseTip(text, msecDisplayTime, pos);
QTipLabel::instance->setTipRect(w, rect);
QTipLabel::instance->placeTip(pos, w);
}
@@ -511,10 +526,10 @@ void QToolTip::showText(const QPoint &pos, const QString &text, QWidget *w, cons
// raised when the tooltip will be shown
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
- new QTipLabel(text, QApplication::desktop()->screen(QTipLabel::getTipScreen(pos, w)), msecDisplayTime);
+ new QTipLabel(text, pos, QApplication::desktop()->screen(QTipLabel::getTipScreen(pos, w)), msecDisplayTime);
QT_WARNING_POP
#else
- new QTipLabel(text, w, msecDisplayTime); // sets QTipLabel::instance to itself
+ new QTipLabel(text, pos, w, msecDisplayTime); // sets QTipLabel::instance to itself
#endif
QTipLabel::instance->setTipRect(w, rect);
QTipLabel::instance->placeTip(pos, w);
diff --git a/src/widgets/kernel/qwhatsthis.cpp b/src/widgets/kernel/qwhatsthis.cpp
index 96d0cf61c4..1fa83d3238 100644
--- a/src/widgets/kernel/qwhatsthis.cpp
+++ b/src/widgets/kernel/qwhatsthis.cpp
@@ -48,7 +48,9 @@
#include "qscreen.h"
#include "qpainter.h"
#include "qtimer.h"
+#if QT_CONFIG(action)
#include "qaction.h"
+#endif // QT_CONFIG(action)
#include "qcursor.h"
#include "qbitmap.h"
#include "qtextdocument.h"
@@ -366,7 +368,9 @@ class QWhatsThisPrivate : public QObject
~QWhatsThisPrivate();
static QWhatsThisPrivate *instance;
bool eventFilter(QObject *, QEvent *) override;
+#if QT_CONFIG(action)
QPointer<QAction> action;
+#endif // QT_CONFIG(action)
static void say(QWidget *, const QString &, int x = 0, int y = 0);
static void notifyToplevels(QEvent *e);
bool leaveOnMouseRelease;
@@ -408,8 +412,10 @@ QWhatsThisPrivate::QWhatsThisPrivate()
QWhatsThisPrivate::~QWhatsThisPrivate()
{
+#if QT_CONFIG(action)
if (action)
action->setChecked(false);
+#endif // QT_CONFIG(action)
#ifndef QT_NO_CURSOR
QApplication::restoreOverrideCursor();
#endif
@@ -485,6 +491,7 @@ bool QWhatsThisPrivate::eventFilter(QObject *o, QEvent *e)
return true;
}
+#if QT_CONFIG(action)
class QWhatsThisAction: public QAction
{
Q_OBJECT
@@ -516,6 +523,7 @@ void QWhatsThisAction::actionTriggered()
QWhatsThisPrivate::instance->action = this;
}
}
+#endif // QT_CONFIG(action)
/*!
This function switches the user interface into "What's This?"
@@ -672,10 +680,12 @@ void QWhatsThis::hideText()
The returned QAction provides a convenient way to let users enter
"What's This?" mode.
*/
+#if QT_CONFIG(action)
QAction *QWhatsThis::createAction(QObject *parent)
{
return new QWhatsThisAction(parent);
}
+#endif // QT_CONFIG(action)
QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qwhatsthis.h b/src/widgets/kernel/qwhatsthis.h
index 1f0f82b2a2..59c0b01c9b 100644
--- a/src/widgets/kernel/qwhatsthis.h
+++ b/src/widgets/kernel/qwhatsthis.h
@@ -48,7 +48,9 @@ QT_REQUIRE_CONFIG(whatsthis);
QT_BEGIN_NAMESPACE
+#if QT_CONFIG(action)
class QAction;
+#endif // QT_CONFIG(action)
class Q_WIDGETS_EXPORT QWhatsThis
{
@@ -62,7 +64,9 @@ public:
static void showText(const QPoint &pos, const QString &text, QWidget *w = nullptr);
static void hideText();
+#if QT_CONFIG(action)
static QAction *createAction(QObject *parent = nullptr);
+#endif // QT_CONFIG(action)
};
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 1e249dc191..8c680560d4 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -1138,7 +1138,7 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
q->data = &data;
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
if (!parent) {
Q_ASSERT_X(q->thread() == qApp->thread(), "QWidget",
"Widgets must be created in the GUI thread.");
@@ -1572,7 +1572,7 @@ QWidget::~QWidget()
#endif
#ifndef QT_NO_GESTURES
- if (QGestureManager *manager = QGestureManager::instance()) {
+ if (QGestureManager *manager = QGestureManager::instance(QGestureManager::DontForceCreation)) {
// \forall Qt::GestureType type : ungrabGesture(type) (inlined)
for (auto it = d->gestureContext.keyBegin(), end = d->gestureContext.keyEnd(); it != end; ++it)
manager->cleanupCachedGestures(this, *it);
@@ -1580,9 +1580,6 @@ QWidget::~QWidget()
d->gestureContext.clear();
#endif
- // force acceptDrops false before winId is destroyed.
- d->registerDropSite(false);
-
#ifndef QT_NO_ACTION
// remove all actions from this widget
for (int i = 0; i < d->actions.size(); ++i) {
@@ -1849,7 +1846,7 @@ void QWidgetPrivate::deleteExtra()
deleteSysExtra();
#ifndef QT_NO_STYLE_STYLESHEET
// dereference the stylesheet style
- if (QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(extra->style))
+ if (QStyleSheetStyle *proxy = qt_styleSheet(extra->style))
proxy->deref();
#endif
if (extra->topextra) {
@@ -1905,19 +1902,21 @@ void QWidgetPrivate::deleteTLSysExtra()
}
/*
- Returns \c true if there are widgets above this which overlap with
+ Returns \c region of widgets above this which overlap with
\a rect, which is in parent's coordinate system (same as crect).
*/
-bool QWidgetPrivate::isOverlapped(const QRect &rect) const
+QRegion QWidgetPrivate::overlappedRegion(const QRect &rect, bool breakAfterFirst) const
{
Q_Q(const QWidget);
const QWidget *w = q;
QRect r = rect;
+ QPoint p;
+ QRegion region;
while (w) {
if (w->isWindow())
- return false;
+ break;
QWidgetPrivate *pd = w->parentWidget()->d_func();
bool above = false;
for (int i = 0; i < pd->children.size(); ++i) {
@@ -1929,19 +1928,23 @@ bool QWidgetPrivate::isOverlapped(const QRect &rect) const
continue;
}
- if (qRectIntersects(sibling->d_func()->effectiveRectFor(sibling->data->crect), r)) {
+ const QRect siblingRect = sibling->d_func()->effectiveRectFor(sibling->data->crect);
+ if (qRectIntersects(siblingRect, r)) {
const QWExtra *siblingExtra = sibling->d_func()->extra;
if (siblingExtra && siblingExtra->hasMask && !sibling->d_func()->graphicsEffect
&& !siblingExtra->mask.translated(sibling->data->crect.topLeft()).intersects(r)) {
continue;
}
- return true;
+ region += siblingRect.translated(-p);
+ if (breakAfterFirst)
+ break;
}
}
w = w->parentWidget();
r.translate(pd->data.crect.topLeft());
+ p += pd->data.crect.topLeft();
}
- return false;
+ return region;
}
void QWidgetPrivate::syncBackingStore()
@@ -2398,7 +2401,8 @@ static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrus
#endif
} else if (brush.gradient()
- && brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode) {
+ && (brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode
+ || brush.gradient()->coordinateMode() == QGradient::ObjectMode)) {
painter->save();
painter->setClipRegion(rgn);
painter->fillRect(0, 0, painter->device()->width(), painter->device()->height(), brush);
@@ -2659,7 +2663,7 @@ void QWidget::setStyleSheet(const QString& styleSheet)
return;
d->createExtra();
- QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(d->extra->style);
+ QStyleSheetStyle *proxy = qt_styleSheet(d->extra->style);
d->extra->styleSheet = styleSheet;
if (styleSheet.isEmpty()) { // stylesheet removed
if (!proxy)
@@ -2724,12 +2728,12 @@ void QWidget::setStyle(QStyle *style)
setAttribute(Qt::WA_SetStyle, style != 0);
d->createExtra();
#ifndef QT_NO_STYLE_STYLESHEET
- if (QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(style)) {
+ if (QStyleSheetStyle *styleSheetStyle = qt_styleSheet(style)) {
//if for some reason someone try to set a QStyleSheetStyle, ref it
//(this may happen for exemple in QButtonDialogBox which propagates its style)
- proxy->ref();
+ styleSheetStyle->ref();
d->setStyle_helper(style, false);
- } else if (qobject_cast<QStyleSheetStyle *>(d->extra->style) || !qApp->styleSheet().isEmpty()) {
+ } else if (qt_styleSheet(d->extra->style) || !qApp->styleSheet().isEmpty()) {
// if we have an application stylesheet or have a proxy already, propagate
d->setStyle_helper(new QStyleSheetStyle(style), true);
} else
@@ -2737,48 +2741,22 @@ void QWidget::setStyle(QStyle *style)
d->setStyle_helper(style, false);
}
-void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate, bool
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
- metalHack
-#endif
- )
+void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate)
{
Q_Q(QWidget);
- QStyle *oldStyle = q->style();
-#ifndef QT_NO_STYLE_STYLESHEET
- QPointer<QStyle> origStyle;
-#endif
+ QStyle *oldStyle = q->style();
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
- // the metalhack boolean allows Qt/Mac to do a proper re-polish depending
- // on how the Qt::WA_MacBrushedMetal attribute is set. It is only ever
- // set when changing that attribute and passes the widget's CURRENT style.
- // therefore no need to do a reassignment.
- if (!metalHack)
-#endif
- {
- createExtra();
+ createExtra();
#ifndef QT_NO_STYLE_STYLESHEET
- origStyle = extra->style.data();
+ QPointer<QStyle> origStyle = extra->style;
#endif
- extra->style = newStyle;
- }
+ extra->style = newStyle;
// repolish
- if (q->windowType() != Qt::Desktop) {
- if (polished) {
- oldStyle->unpolish(q);
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
- if (metalHack)
- macUpdateMetalAttribute();
-#endif
- q->style()->polish(q);
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
- } else if (metalHack) {
- macUpdateMetalAttribute();
-#endif
- }
+ if (polished && q->windowType() != Qt::Desktop) {
+ oldStyle->unpolish(q);
+ q->style()->polish(q);
}
if (propagate) {
@@ -2792,8 +2770,8 @@ void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate, bool
}
#ifndef QT_NO_STYLE_STYLESHEET
- if (!qobject_cast<QStyleSheetStyle*>(newStyle)) {
- if (const QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(origStyle.data())) {
+ if (!qt_styleSheet(newStyle)) {
+ if (const QStyleSheetStyle* cssStyle = qt_styleSheet(origStyle)) {
cssStyle->clearWidgetFont(q);
}
}
@@ -2804,7 +2782,7 @@ void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate, bool
#ifndef QT_NO_STYLE_STYLESHEET
// dereference the old stylesheet style
- if (QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(origStyle.data()))
+ if (QStyleSheetStyle *proxy = qt_styleSheet(origStyle))
proxy->deref();
#endif
}
@@ -2815,7 +2793,9 @@ void QWidgetPrivate::inheritStyle()
#ifndef QT_NO_STYLE_STYLESHEET
Q_Q(QWidget);
- QStyleSheetStyle *proxy = extra ? qobject_cast<QStyleSheetStyle *>(extra->style) : 0;
+ QStyle *extraStyle = extra ? (QStyle*)extra->style : nullptr;
+
+ QStyleSheetStyle *proxy = qt_styleSheet(extraStyle);
if (!q->styleSheet().isEmpty()) {
Q_ASSERT(proxy);
@@ -2823,16 +2803,16 @@ void QWidgetPrivate::inheritStyle()
return;
}
- QStyle *origStyle = proxy ? proxy->base : (extra ? (QStyle*)extra->style : 0);
+ QStyle *origStyle = proxy ? proxy->base : extraStyle;
QWidget *parent = q->parentWidget();
QStyle *parentStyle = (parent && parent->d_func()->extra) ? (QStyle*)parent->d_func()->extra->style : 0;
// If we have stylesheet on app or parent has stylesheet style, we need
// to be running a proxy
- if (!qApp->styleSheet().isEmpty() || qobject_cast<QStyleSheetStyle *>(parentStyle)) {
+ if (!qApp->styleSheet().isEmpty() || qt_styleSheet(parentStyle)) {
QStyle *newStyle = parentStyle;
if (q->testAttribute(Qt::WA_SetStyle))
newStyle = new QStyleSheetStyle(origStyle);
- else if (QStyleSheetStyle *newProxy = qobject_cast<QStyleSheetStyle *>(parentStyle))
+ else if (QStyleSheetStyle *newProxy = qt_styleSheet(parentStyle))
newProxy->ref();
setStyle_helper(newStyle, true);
@@ -2841,7 +2821,7 @@ void QWidgetPrivate::inheritStyle()
// So, we have no stylesheet on parent/app and we have an empty stylesheet
// we just need our original style back
- if (origStyle == (extra ? (QStyle*)extra->style : 0)) // is it any different?
+ if (origStyle == extraStyle) // is it any different?
return;
// We could have inherited the proxy from our parent (which has a custom style)
@@ -3480,11 +3460,6 @@ void QWidget::setAcceptDrops(bool on)
}
-void QWidgetPrivate::registerDropSite(bool on)
-{
- Q_UNUSED(on);
-}
-
/*!
Disables widget input events if \a disable is true; otherwise
enables input events.
@@ -4514,16 +4489,14 @@ void QWidget::setForegroundRole(QPalette::ColorRole role)
and these styles typically do not follow the palette. Because of this,
assigning roles to a widget's palette is not guaranteed to change the
appearance of the widget. Instead, you may choose to apply a \l
- styleSheet. You can refer to our Knowledge Base article
- \l{http://qt.nokia.com/developer/knowledgebase/22}{here} for more
- information.
+ styleSheet.
\warning Do not use this function in conjunction with \l{Qt Style Sheets}.
When using style sheets, the palette of a widget can be customized using
the "color", "background-color", "selection-color",
"selection-background-color" and "alternate-background-color".
- \sa QApplication::palette(), QWidget::font()
+ \sa QApplication::palette(), QWidget::font(), \l {Qt Style Sheets}
*/
const QPalette &QWidget::palette() const
{
@@ -4690,9 +4663,8 @@ void QWidget::setFont(const QFont &font)
#ifndef QT_NO_STYLE_STYLESHEET
const QStyleSheetStyle* style;
- if (d->extra && (style = qobject_cast<const QStyleSheetStyle*>(d->extra->style))) {
+ if (d->extra && (style = qt_styleSheet(d->extra->style)))
style->saveWidgetFont(this, font);
- }
#endif
setAttribute(Qt::WA_SetFont, font.resolve() != 0);
@@ -4788,7 +4760,7 @@ void QWidgetPrivate::updateFont(const QFont &font)
Q_Q(QWidget);
#ifndef QT_NO_STYLE_STYLESHEET
const QStyleSheetStyle* cssStyle;
- cssStyle = extra ? qobject_cast<const QStyleSheetStyle*>(extra->style) : 0;
+ cssStyle = extra ? qt_styleSheet(extra->style) : 0;
const bool useStyleSheetPropagationInWidgetStyles =
QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles);
#endif
@@ -6620,9 +6592,12 @@ QWidget *QWidgetPrivate::deepestFocusProxy() const
void QWidgetPrivate::setFocus_sys()
{
Q_Q(QWidget);
- // Embedded native widget may have taken the focus; get it back to toplevel if that is the case
+ // Embedded native widget may have taken the focus; get it back to toplevel
+ // if that is the case (QTBUG-25852)
const QWidget *topLevel = q->window();
- if (topLevel->windowType() != Qt::Popup) {
+ // Do not activate in case the popup menu opens another application (QTBUG-70810).
+ if (QGuiApplication::applicationState() == Qt::ApplicationActive
+ && topLevel->windowType() != Qt::Popup) {
if (QWindow *nativeWindow = q->window()->windowHandle()) {
if (nativeWindow != QGuiApplication::focusWindow()
&& q->testAttribute(Qt::WA_WState_Created)) {
@@ -6981,8 +6956,10 @@ void QWidget::setTabOrder(QWidget* first, QWidget *second)
determineLastFocusChild(second, lastFocusChildOfSecond);
// If the tab order is already correct, exit early
- if (lastFocusChildOfFirst->d_func()->focus_next == second)
+ if (lastFocusChildOfFirst == second ||
+ lastFocusChildOfFirst->d_func()->focus_next == second) {
return;
+ }
// Note that we need to handle two different sections in the tab chain; The section
// that 'first' belongs to (firstSection), where we are about to insert 'second', and
@@ -7381,7 +7358,8 @@ QByteArray QWidget::saveGeometry() const
// Version history:
// - Qt 4.2 - 4.8.6, 5.0 - 5.3 : Version 1.0
// - Qt 4.8.6 - today, 5.4 - today: Version 2.0, save screen width in addition to check for high DPI scaling.
- quint16 majorVersion = 2;
+ // - Qt 5.12 - today : Version 3.0, save QWidget::geometry()
+ quint16 majorVersion = 3;
quint16 minorVersion = 0;
const int screenNumber = QDesktopWidgetPrivate::screenNumber(this);
stream << magicNumber
@@ -7397,7 +7375,8 @@ QByteArray QWidget::saveGeometry() const
<< qint32(screenNumber)
<< quint8(windowState() & Qt::WindowMaximized)
<< quint8(windowState() & Qt::WindowFullScreen)
- << qint32(QDesktopWidgetPrivate::screenGeometry(screenNumber).width()); // 1.1 onwards
+ << qint32(QDesktopWidgetPrivate::screenGeometry(screenNumber).width()) // added in 2.0
+ << geometry(); // added in 3.0
return array;
}
@@ -7437,7 +7416,7 @@ bool QWidget::restoreGeometry(const QByteArray &geometry)
if (storedMagicNumber != magicNumber)
return false;
- const quint16 currentMajorVersion = 2;
+ const quint16 currentMajorVersion = 3;
quint16 majorVersion = 0;
quint16 minorVersion = 0;
@@ -7448,7 +7427,8 @@ bool QWidget::restoreGeometry(const QByteArray &geometry)
// (Allow all minor versions.)
QRect restoredFrameGeometry;
- QRect restoredNormalGeometry;
+ QRect restoredGeometry;
+ QRect restoredNormalGeometry;
qint32 restoredScreenNumber;
quint8 maximized;
quint8 fullScreen;
@@ -7462,6 +7442,10 @@ bool QWidget::restoreGeometry(const QByteArray &geometry)
if (majorVersion > 1)
stream >> restoredScreenWidth;
+ if (majorVersion > 2)
+ stream >> restoredGeometry;
+
+ // ### Qt 6 - Perhaps it makes sense to dumb down the restoreGeometry() logic, see QTBUG-69104
if (restoredScreenNumber >= QDesktopWidgetPrivate::numScreens())
restoredScreenNumber = QDesktopWidgetPrivate::primaryScreen();
@@ -7548,14 +7532,11 @@ bool QWidget::restoreGeometry(const QByteArray &geometry)
setWindowState(ws);
d_func()->topData()->normalGeometry = restoredNormalGeometry;
} else {
- QPoint offset;
-#if 0 // Used to be included in Qt4 for Q_WS_X11
- if (isFullScreen())
- offset = d_func()->topData()->fullScreenOffset;
-#endif
setWindowState(windowState() & ~(Qt::WindowMaximized | Qt::WindowFullScreen));
- move(restoredFrameGeometry.topLeft() + offset);
- resize(restoredNormalGeometry.size());
+ if (majorVersion > 2)
+ setGeometry(restoredGeometry);
+ else
+ setGeometry(restoredNormalGeometry);
}
return true;
}
@@ -10107,20 +10088,24 @@ void QWidget::hideEvent(QHideEvent *)
which are passed in the \a message parameter.
In your reimplementation of this function, if you want to stop the
- event being handled by Qt, return true and set \a result.
- If you return false, this native event is passed back to Qt,
- which translates the event into a Qt event and sends it to the widget.
+ event being handled by Qt, return true and set \a result. The \a result
+ parameter has meaning only on Windows. If you return false, this native
+ event is passed back to Qt, which translates the event into a Qt event
+ and sends it to the widget.
- \note Events are only delivered to this event handler if the widget is
- has a native Window handle.
+ \note Events are only delivered to this event handler if the widget
+ has a native window handle.
\note This function superseedes the event filter functions
x11Event(), winEvent() and macEvent() of Qt 4.
+ \sa QAbstractNativeEventFilter
+
\table
\header \li Platform \li Event Type Identifier \li Message Type \li Result Type
\row \li Windows \li "windows_generic_MSG" \li MSG * \li LRESULT
\row \li macOS \li "NSEvent" \li NSEvent * \li
+ \row \li XCB \li "xcb_generic_event_t" \li xcb_generic_event_t * \li
\endtable
*/
@@ -11214,7 +11199,6 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
break;
}
case Qt::WA_DropSiteRegistered: {
- d->registerDropSite(on);
for (int i = 0; i < d->children.size(); ++i) {
QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
if (w && !w->isWindow() && !w->testAttribute(Qt::WA_AcceptDrops) && w->testAttribute(Qt::WA_DropSiteRegistered) != on)
diff --git a/src/widgets/kernel/qwidget.h b/src/widgets/kernel/qwidget.h
index 9f9f167002..9d5fe89c70 100644
--- a/src/widgets/kernel/qwidget.h
+++ b/src/widgets/kernel/qwidget.h
@@ -714,6 +714,7 @@ private:
friend class QWidgetWindow;
friend class QAccessibleWidget;
friend class QAccessibleTable;
+ friend class QAccessibleTabButton;
#ifndef QT_NO_GESTURES
friend class QGestureManager;
friend class QWinNativePanGestureRecognizer;
diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h
index e8b550b1cd..c2fc27a9ad 100644
--- a/src/widgets/kernel/qwidget_p.h
+++ b/src/widgets/kernel/qwidget_p.h
@@ -395,7 +395,7 @@ public:
void setLocale_helper(const QLocale &l, bool forceUpdate = false);
void resolveLocale();
- void setStyle_helper(QStyle *newStyle, bool propagate, bool metalHack = false);
+ void setStyle_helper(QStyle *newStyle, bool propagate);
void inheritStyle();
void setUpdatesEnabled_helper(bool );
@@ -453,7 +453,7 @@ public:
// ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).
void invalidateBuffer(const QRegion &);
void invalidateBuffer(const QRect &);
- bool isOverlapped(const QRect&) const;
+ QRegion overlappedRegion(const QRect &rect, bool breakAfterFirst = false) const;
void syncBackingStore();
void syncBackingStore(const QRegion &region);
@@ -483,7 +483,6 @@ public:
void _q_showIfNotHidden();
void setEnabled_helper(bool);
- void registerDropSite(bool);
static void adjustFlags(Qt::WindowFlags &flags, QWidget *w = 0);
void updateFrameStrut();
diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp
index 3b093283cd..53769ef9ed 100644
--- a/src/widgets/kernel/qwidgetbackingstore.cpp
+++ b/src/widgets/kernel/qwidgetbackingstore.cpp
@@ -59,6 +59,7 @@
#include <private/qgraphicseffect_p.h>
#endif
#include <QtGui/private/qwindow_p.h>
+#include <QtGui/private/qhighdpiscaling_p.h>
#include <qpa/qplatformbackingstore.h>
@@ -759,7 +760,7 @@ void QWidgetBackingStore::updateLists(QWidget *cur)
QList<QObject*> children = cur->children();
for (int i = 0; i < children.size(); ++i) {
QWidget *child = qobject_cast<QWidget*>(children.at(i));
- if (!child)
+ if (!child || child->isWindow())
continue;
updateLists(child);
@@ -793,6 +794,25 @@ QWidgetBackingStore::~QWidgetBackingStore()
delete dirtyOnScreenWidgets;
}
+static QVector<QRect> getSortedRectsToScroll(const QRegion &region, int dx, int dy)
+{
+ QVector<QRect> rects;
+ std::copy(region.begin(), region.end(), std::back_inserter(rects));
+ if (rects.count() > 1) {
+ std::sort(rects.begin(), rects.end(), [=](const QRect &r1, const QRect &r2) {
+ if (r1.y() == r2.y()) {
+ if (dx > 0)
+ return r1.x() > r2.x();
+ return r1.x() < r2.x();
+ }
+ if (dy > 0)
+ return r1.y() > r2.y();
+ return r1.y() < r2.y();
+ });
+ }
+ return rects;
+}
+
//parent's coordinates; move whole rect; update parent and widget
//assume the screen blt has already been done, so we don't need to refresh that part
void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy)
@@ -820,12 +840,12 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy)
const QRect parentRect(rect & clipR);
const bool nativeWithTextureChild = textureChildSeen && q->internalWinId();
- bool accelerateMove = accelEnv && isOpaque && !nativeWithTextureChild
+ const bool accelerateMove = accelEnv && isOpaque && !nativeWithTextureChild
#if QT_CONFIG(graphicsview)
// No accelerate move for proxy widgets.
&& !tlw->d_func()->extra->proxyWidget
#endif
- && !isOverlapped(sourceRect) && !isOverlapped(destRect);
+ ;
if (!accelerateMove) {
QRegion parentR(effectiveRectFor(parentRect));
@@ -841,18 +861,39 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy)
QWidgetBackingStore *wbs = x->backingStoreTracker.data();
QRegion childExpose(newRect & clipR);
+ QRegion overlappedExpose;
- if (sourceRect.isValid() && wbs->bltRect(sourceRect, dx, dy, pw))
- childExpose -= destRect;
+ if (sourceRect.isValid()) {
+ overlappedExpose = (overlappedRegion(sourceRect) | overlappedRegion(destRect)) & clipR;
+
+ const qreal factor = QHighDpiScaling::factor(q->windowHandle());
+ if (overlappedExpose.isEmpty() || qFloor(factor) == factor) {
+ const QVector<QRect> rectsToScroll
+ = getSortedRectsToScroll(QRegion(sourceRect) - overlappedExpose, dx, dy);
+ for (QRect rect : rectsToScroll) {
+ if (wbs->bltRect(rect, dx, dy, pw)) {
+ childExpose -= rect.translated(dx, dy);
+ }
+ }
+ }
+
+ childExpose -= overlappedExpose;
+ }
if (!pw->updatesEnabled())
return;
const bool childUpdatesEnabled = q->updatesEnabled();
- if (childUpdatesEnabled && !childExpose.isEmpty()) {
- childExpose.translate(-data.crect.topLeft());
- wbs->markDirty(childExpose, q);
- isMoved = true;
+ if (childUpdatesEnabled) {
+ if (!overlappedExpose.isEmpty()) {
+ overlappedExpose.translate(-data.crect.topLeft());
+ invalidateBuffer(overlappedExpose);
+ }
+ if (!childExpose.isEmpty()) {
+ childExpose.translate(-data.crect.topLeft());
+ wbs->markDirty(childExpose, q);
+ isMoved = true;
+ }
}
QRegion parentExpose(parentRect);
@@ -888,13 +929,12 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy)
static const bool accelEnv = qEnvironmentVariableIntValue("QT_NO_FAST_SCROLL") == 0;
- QRect scrollRect = rect & clipRect();
- bool overlapped = false;
- bool accelerateScroll = accelEnv && isOpaque && !q_func()->testAttribute(Qt::WA_WState_InPaintEvent)
- && !(overlapped = isOverlapped(scrollRect.translated(data.crect.topLeft())));
+ const QRect clipR = clipRect();
+ const QRect scrollRect = rect & clipR;
+ const bool accelerateScroll = accelEnv && isOpaque && !q_func()->testAttribute(Qt::WA_WState_InPaintEvent);
if (!accelerateScroll) {
- if (overlapped) {
+ if (!overlappedRegion(scrollRect.translated(data.crect.topLeft()), true).isEmpty()) {
QRegion region(scrollRect);
subtractOpaqueSiblings(region);
invalidateBuffer(region);
@@ -906,12 +946,23 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy)
const QRect destRect = scrollRect.translated(dx, dy) & scrollRect;
const QRect sourceRect = destRect.translated(-dx, -dy);
+ const QRegion overlappedExpose = (overlappedRegion(scrollRect.translated(data.crect.topLeft())))
+ .translated(-data.crect.topLeft()) & clipR;
QRegion childExpose(scrollRect);
- if (sourceRect.isValid()) {
- if (wbs->bltRect(sourceRect, dx, dy, q))
- childExpose -= destRect;
+
+ const qreal factor = QHighDpiScaling::factor(q->windowHandle());
+ if (overlappedExpose.isEmpty() || qFloor(factor) == factor) {
+ const QVector<QRect> rectsToScroll
+ = getSortedRectsToScroll(QRegion(sourceRect) - overlappedExpose, dx, dy);
+ for (const QRect &rect : rectsToScroll) {
+ if (wbs->bltRect(rect, dx, dy, q)) {
+ childExpose -= rect.translated(dx, dy);
+ }
+ }
}
+ childExpose -= overlappedExpose;
+
if (inDirtyList) {
if (rect == q->rect()) {
dirty.translate(dx, dy);
@@ -928,6 +979,8 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy)
if (!q->updatesEnabled())
return;
+ if (!overlappedExpose.isEmpty())
+ invalidateBuffer(overlappedExpose);
if (!childExpose.isEmpty()) {
wbs->markDirty(childExpose, q);
isScrolled = true;
@@ -991,7 +1044,7 @@ static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget)
}
}
- if (QWidgetPrivate::get(tlw)->textureChildSeen) {
+ if (QWidgetPrivate::get(widget)->textureChildSeen) {
// No render-to-texture widgets in the (sub-)tree due to hidden or native
// children. Returning null results in using the normal backingstore flush path
// without OpenGL-based compositing. This is very desirable normally. However,
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index 1f3057b008..7292c795b8 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -311,8 +311,10 @@ bool QWidgetWindow::event(QEvent *event)
#if QT_CONFIG(draganddrop)
case QEvent::DragEnter:
+ handleDragEnterEvent(static_cast<QDragEnterEvent *>(event));
+ return true;
case QEvent::DragMove:
- handleDragEnterMoveEvent(static_cast<QDragMoveEvent *>(event));
+ handleDragMoveEvent(static_cast<QDragMoveEvent *>(event));
return true;
case QEvent::DragLeave:
handleDragLeaveEvent(static_cast<QDragLeaveEvent *>(event));
@@ -841,6 +843,7 @@ void QWidgetWindow::handleWheelEvent(QWheelEvent *event)
QPoint mapped = widget->mapFrom(rootWidget, pos);
QWheelEvent translated(mapped, event->globalPos(), event->pixelDelta(), event->angleDelta(), event->delta(), event->orientation(), event->buttons(), event->modifiers(), event->phase(), event->source(), event->inverted());
+ translated.setTimestamp(event->timestamp());
QGuiApplication::forwardEvent(widget, &translated, event);
}
@@ -848,62 +851,80 @@ void QWidgetWindow::handleWheelEvent(QWheelEvent *event)
#if QT_CONFIG(draganddrop)
-void QWidgetWindow::handleDragEnterMoveEvent(QDragMoveEvent *event)
+static QWidget *findDnDTarget(QWidget *parent, const QPoint &pos)
{
- Q_ASSERT(event->type() ==QEvent::DragMove || !m_dragTarget);
// Find a target widget under mouse that accepts drops (QTBUG-22987).
- QWidget *widget = m_widget->childAt(event->pos());
+ QWidget *widget = parent->childAt(pos);
if (!widget)
- widget = m_widget;
+ widget = parent;
for ( ; widget && !widget->isWindow() && !widget->acceptDrops(); widget = widget->parentWidget()) ;
if (widget && !widget->acceptDrops())
- widget = 0;
- // Target widget unchanged: DragMove
- if (widget && widget == m_dragTarget.data()) {
- Q_ASSERT(event->type() == QEvent::DragMove);
- const QPoint mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->pos()));
- QDragMoveEvent translated(mapped, event->possibleActions(), event->mimeData(), event->mouseButtons(), event->keyboardModifiers());
- translated.setDropAction(event->dropAction());
- if (event->isAccepted()) { // Handling 'DragEnter' should suffice for the application.
- translated.accept();
- translated.setDropAction(event->dropAction());
- }
- QGuiApplication::forwardEvent(widget, &translated, event);
- if (translated.isAccepted()) {
- event->accept();
- } else {
- event->ignore();
- }
- event->setDropAction(translated.dropAction());
- return;
- }
- // Target widget changed: Send DragLeave to previous, DragEnter to new if there is any
- if (m_dragTarget.data()) {
- QDragLeaveEvent le;
- QGuiApplication::forwardEvent(m_dragTarget.data(), &le, event);
- m_dragTarget = 0;
- }
+ widget = nullptr;
+ return widget;
+}
+
+void QWidgetWindow::handleDragEnterEvent(QDragEnterEvent *event, QWidget *widget)
+{
+ Q_ASSERT(m_dragTarget == nullptr);
+ if (!widget)
+ widget = findDnDTarget(m_widget, event->pos());
if (!widget) {
- event->ignore();
- return;
+ event->ignore();
+ return;
}
m_dragTarget = widget;
+
const QPoint mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->pos()));
- QDragEnterEvent translated(mapped, event->possibleActions(), event->mimeData(), event->mouseButtons(), event->keyboardModifiers());
- QGuiApplication::forwardEvent(widget, &translated, event);
- if (translated.isAccepted()) {
- event->accept();
- } else {
+ QDragEnterEvent translated(mapped, event->possibleActions(), event->mimeData(),
+ event->mouseButtons(), event->keyboardModifiers());
+ translated.setDropAction(event->dropAction());
+ translated.setAccepted(event->isAccepted());
+ QGuiApplication::forwardEvent(m_dragTarget, &translated, event);
+ event->setAccepted(translated.isAccepted());
+ event->setDropAction(translated.dropAction());
+}
+
+void QWidgetWindow::handleDragMoveEvent(QDragMoveEvent *event)
+{
+ auto *widget = findDnDTarget(m_widget, event->pos());
+ if (!widget) {
event->ignore();
+ if (m_dragTarget) { // Send DragLeave to previous
+ QDragLeaveEvent leaveEvent;
+ QGuiApplication::forwardEvent(m_dragTarget, &leaveEvent, event);
+ m_dragTarget = nullptr;
+ }
+ } else {
+ const QPoint mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->pos()));
+ QDragMoveEvent translated(mapped, event->possibleActions(), event->mimeData(),
+ event->mouseButtons(), event->keyboardModifiers());
+ translated.setDropAction(event->dropAction());
+ translated.setAccepted(event->isAccepted());
+
+ if (widget == m_dragTarget) { // Target widget unchanged: Send DragMove
+ QGuiApplication::forwardEvent(m_dragTarget, &translated, event);
+ } else {
+ if (m_dragTarget) { // Send DragLeave to previous
+ QDragLeaveEvent leaveEvent;
+ QGuiApplication::forwardEvent(m_dragTarget, &leaveEvent, event);
+ m_dragTarget = nullptr;
+ }
+ // Send DragEnter to new widget.
+ handleDragEnterEvent(static_cast<QDragEnterEvent*>(event), widget);
+ // The drag enter event is always immediately followed by a drag move event,
+ // see QDragEnterEvent documentation.
+ QGuiApplication::forwardEvent(m_dragTarget, &translated, event);
+ }
+ event->setAccepted(translated.isAccepted());
+ event->setDropAction(translated.dropAction());
}
- event->setDropAction(translated.dropAction());
}
void QWidgetWindow::handleDragLeaveEvent(QDragLeaveEvent *event)
{
if (m_dragTarget)
- QGuiApplication::forwardEvent(m_dragTarget.data(), event);
- m_dragTarget = 0;
+ QGuiApplication::forwardEvent(m_dragTarget, event);
+ m_dragTarget = nullptr;
}
void QWidgetWindow::handleDropEvent(QDropEvent *event)
@@ -913,13 +934,12 @@ void QWidgetWindow::handleDropEvent(QDropEvent *event)
event->ignore();
return;
}
- const QPoint mapped = m_dragTarget.data()->mapFromGlobal(m_widget->mapToGlobal(event->pos()));
+ const QPoint mapped = m_dragTarget->mapFromGlobal(m_widget->mapToGlobal(event->pos()));
QDropEvent translated(mapped, event->possibleActions(), event->mimeData(), event->mouseButtons(), event->keyboardModifiers());
- QGuiApplication::forwardEvent(m_dragTarget.data(), &translated, event);
- if (translated.isAccepted())
- event->accept();
+ QGuiApplication::forwardEvent(m_dragTarget, &translated, event);
+ event->setAccepted(translated.isAccepted());
event->setDropAction(translated.dropAction());
- m_dragTarget = 0;
+ m_dragTarget = nullptr;
}
#endif // QT_CONFIG(draganddrop)
@@ -957,7 +977,10 @@ void QWidgetWindow::handleExposeEvent(QExposeEvent *event)
}
if (exposed) {
+ // QTBUG-39220, QTBUG-58575: set all (potentially fully obscured parent widgets) mapped.
m_widget->setAttribute(Qt::WA_Mapped);
+ for (QWidget *p = m_widget->parentWidget(); p && !p->testAttribute(Qt::WA_Mapped); p = p->parentWidget())
+ p->setAttribute(Qt::WA_Mapped);
if (!event->region().isNull())
wPriv->syncBackingStore(event->region());
} else {
@@ -1021,6 +1044,7 @@ void QWidgetWindow::handleTabletEvent(QTabletEvent *event)
event->pressure(), event->xTilt(), event->yTilt(), event->tangentialPressure(),
event->rotation(), event->z(), event->modifiers(), event->uniqueId(), event->button(), event->buttons());
ev.setTimestamp(event->timestamp());
+ ev.setAccepted(false);
QGuiApplication::forwardEvent(widget, &ev, event);
event->setAccepted(ev.isAccepted());
}
diff --git a/src/widgets/kernel/qwidgetwindow_p.h b/src/widgets/kernel/qwidgetwindow_p.h
index ead099390e..0728135467 100644
--- a/src/widgets/kernel/qwidgetwindow_p.h
+++ b/src/widgets/kernel/qwidgetwindow_p.h
@@ -96,7 +96,8 @@ protected:
void handleWheelEvent(QWheelEvent *);
#endif
#if QT_CONFIG(draganddrop)
- void handleDragEnterMoveEvent(QDragMoveEvent *);
+ void handleDragEnterEvent(QDragEnterEvent *, QWidget *widget = nullptr);
+ void handleDragMoveEvent(QDragMoveEvent *);
void handleDragLeaveEvent(QDragLeaveEvent *);
void handleDropEvent(QDropEvent *);
#endif
diff --git a/src/widgets/qtwidgets.tracepoints b/src/widgets/qtwidgets.tracepoints
new file mode 100644
index 0000000000..01a1383670
--- /dev/null
+++ b/src/widgets/qtwidgets.tracepoints
@@ -0,0 +1,4 @@
+QApplication_notify_entry(QObject *receiver, QEvent *event, int type)
+QApplication_notify_event_filtered(QObject *receiver, QEvent *event, int type)
+QApplication_notify_before_delivery(QObject *receiver, QEvent *event, int type)
+QApplication_notify_after_delivery(QObject *receiver, QEvent *event, int type, bool consumed)
diff --git a/src/widgets/styles/images/titlebar-contexthelp-16.png b/src/widgets/styles/images/titlebar-contexthelp-16.png
new file mode 100644
index 0000000000..2cead19910
--- /dev/null
+++ b/src/widgets/styles/images/titlebar-contexthelp-16.png
Binary files differ
diff --git a/src/widgets/styles/images/titlebar-contexthelp-32.png b/src/widgets/styles/images/titlebar-contexthelp-32.png
new file mode 100644
index 0000000000..1cd4843d5e
--- /dev/null
+++ b/src/widgets/styles/images/titlebar-contexthelp-32.png
Binary files differ
diff --git a/src/widgets/styles/images/titlebar-contexthelp-48.png b/src/widgets/styles/images/titlebar-contexthelp-48.png
new file mode 100644
index 0000000000..9b170687be
--- /dev/null
+++ b/src/widgets/styles/images/titlebar-contexthelp-48.png
Binary files differ
diff --git a/src/widgets/styles/images/titlebar-max-16.png b/src/widgets/styles/images/titlebar-max-16.png
new file mode 100644
index 0000000000..101a7eac2b
--- /dev/null
+++ b/src/widgets/styles/images/titlebar-max-16.png
Binary files differ
diff --git a/src/widgets/styles/images/titlebar-max-32.png b/src/widgets/styles/images/titlebar-max-32.png
new file mode 100644
index 0000000000..529c54f61d
--- /dev/null
+++ b/src/widgets/styles/images/titlebar-max-32.png
Binary files differ
diff --git a/src/widgets/styles/images/titlebar-max-48.png b/src/widgets/styles/images/titlebar-max-48.png
new file mode 100644
index 0000000000..cfa0b67edf
--- /dev/null
+++ b/src/widgets/styles/images/titlebar-max-48.png
Binary files differ
diff --git a/src/widgets/styles/images/titlebar-min-16.png b/src/widgets/styles/images/titlebar-min-16.png
new file mode 100644
index 0000000000..95e714b522
--- /dev/null
+++ b/src/widgets/styles/images/titlebar-min-16.png
Binary files differ
diff --git a/src/widgets/styles/images/titlebar-min-32.png b/src/widgets/styles/images/titlebar-min-32.png
new file mode 100644
index 0000000000..0b9afedecf
--- /dev/null
+++ b/src/widgets/styles/images/titlebar-min-32.png
Binary files differ
diff --git a/src/widgets/styles/images/titlebar-min-48.png b/src/widgets/styles/images/titlebar-min-48.png
new file mode 100644
index 0000000000..b59a336d36
--- /dev/null
+++ b/src/widgets/styles/images/titlebar-min-48.png
Binary files differ
diff --git a/src/widgets/styles/images/titlebar-shade-16.png b/src/widgets/styles/images/titlebar-shade-16.png
new file mode 100644
index 0000000000..cc870a1e5c
--- /dev/null
+++ b/src/widgets/styles/images/titlebar-shade-16.png
Binary files differ
diff --git a/src/widgets/styles/images/titlebar-shade-32.png b/src/widgets/styles/images/titlebar-shade-32.png
new file mode 100644
index 0000000000..b785b8e216
--- /dev/null
+++ b/src/widgets/styles/images/titlebar-shade-32.png
Binary files differ
diff --git a/src/widgets/styles/images/titlebar-shade-48.png b/src/widgets/styles/images/titlebar-shade-48.png
new file mode 100644
index 0000000000..42b75b4a0c
--- /dev/null
+++ b/src/widgets/styles/images/titlebar-shade-48.png
Binary files differ
diff --git a/src/widgets/styles/images/titlebar-unshade-16.png b/src/widgets/styles/images/titlebar-unshade-16.png
new file mode 100644
index 0000000000..ef19de6c2f
--- /dev/null
+++ b/src/widgets/styles/images/titlebar-unshade-16.png
Binary files differ
diff --git a/src/widgets/styles/images/titlebar-unshade-32.png b/src/widgets/styles/images/titlebar-unshade-32.png
new file mode 100644
index 0000000000..9f74bb0ac7
--- /dev/null
+++ b/src/widgets/styles/images/titlebar-unshade-32.png
Binary files differ
diff --git a/src/widgets/styles/images/titlebar-unshade-48.png b/src/widgets/styles/images/titlebar-unshade-48.png
new file mode 100644
index 0000000000..bd17c3cf48
--- /dev/null
+++ b/src/widgets/styles/images/titlebar-unshade-48.png
Binary files differ
diff --git a/src/widgets/styles/images/toolbar-ext-h-16.png b/src/widgets/styles/images/toolbar-ext-h-16.png
new file mode 100644
index 0000000000..c6bd1b1784
--- /dev/null
+++ b/src/widgets/styles/images/toolbar-ext-h-16.png
Binary files differ
diff --git a/src/widgets/styles/images/toolbar-ext-h-32.png b/src/widgets/styles/images/toolbar-ext-h-32.png
new file mode 100644
index 0000000000..99c62698f2
--- /dev/null
+++ b/src/widgets/styles/images/toolbar-ext-h-32.png
Binary files differ
diff --git a/src/widgets/styles/images/toolbar-ext-h-8.png b/src/widgets/styles/images/toolbar-ext-h-8.png
new file mode 100644
index 0000000000..340a374bce
--- /dev/null
+++ b/src/widgets/styles/images/toolbar-ext-h-8.png
Binary files differ
diff --git a/src/widgets/styles/images/toolbar-ext-h-rtl-16.png b/src/widgets/styles/images/toolbar-ext-h-rtl-16.png
new file mode 100644
index 0000000000..31c72892b4
--- /dev/null
+++ b/src/widgets/styles/images/toolbar-ext-h-rtl-16.png
Binary files differ
diff --git a/src/widgets/styles/images/toolbar-ext-h-rtl-32.png b/src/widgets/styles/images/toolbar-ext-h-rtl-32.png
new file mode 100644
index 0000000000..bfc333daac
--- /dev/null
+++ b/src/widgets/styles/images/toolbar-ext-h-rtl-32.png
Binary files differ
diff --git a/src/widgets/styles/images/toolbar-ext-h-rtl-8.png b/src/widgets/styles/images/toolbar-ext-h-rtl-8.png
new file mode 100644
index 0000000000..538e408310
--- /dev/null
+++ b/src/widgets/styles/images/toolbar-ext-h-rtl-8.png
Binary files differ
diff --git a/src/widgets/styles/images/toolbar-ext.png b/src/widgets/styles/images/toolbar-ext-macstyle.png
index 37bd403ff8..37bd403ff8 100644
--- a/src/widgets/styles/images/toolbar-ext.png
+++ b/src/widgets/styles/images/toolbar-ext-macstyle.png
Binary files differ
diff --git a/src/widgets/styles/images/toolbar-ext@2x.png b/src/widgets/styles/images/toolbar-ext-macstyle@2x.png
index 6fc729efb0..6fc729efb0 100644
--- a/src/widgets/styles/images/toolbar-ext@2x.png
+++ b/src/widgets/styles/images/toolbar-ext-macstyle@2x.png
Binary files differ
diff --git a/src/widgets/styles/images/toolbar-ext-v-10.png b/src/widgets/styles/images/toolbar-ext-v-10.png
new file mode 100644
index 0000000000..2a6d0e4c70
--- /dev/null
+++ b/src/widgets/styles/images/toolbar-ext-v-10.png
Binary files differ
diff --git a/src/widgets/styles/images/toolbar-ext-v-20.png b/src/widgets/styles/images/toolbar-ext-v-20.png
new file mode 100644
index 0000000000..adc27f52b5
--- /dev/null
+++ b/src/widgets/styles/images/toolbar-ext-v-20.png
Binary files differ
diff --git a/src/widgets/styles/images/toolbar-ext-v-5.png b/src/widgets/styles/images/toolbar-ext-v-5.png
new file mode 100644
index 0000000000..21c670446c
--- /dev/null
+++ b/src/widgets/styles/images/toolbar-ext-v-5.png
Binary files differ
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp
index 735ae6b080..66f5f4876e 100644
--- a/src/widgets/styles/qcommonstyle.cpp
+++ b/src/widgets/styles/qcommonstyle.cpp
@@ -938,55 +938,53 @@ void QCommonStylePrivate::viewItemDrawText(QPainter *p, const QStyleOptionViewIt
viewItemTextLayout(textLayout, textRect.width());
- QString elidedText;
- qreal height = 0;
- qreal width = 0;
- int elidedIndex = -1;
- const int lineCount = textLayout.lineCount();
- for (int j = 0; j < lineCount; ++j) {
- const QTextLine line = textLayout.lineAt(j);
- if (j + 1 <= lineCount - 1) {
- const QTextLine nextLine = textLayout.lineAt(j + 1);
- if ((nextLine.y() + nextLine.height()) > textRect.height()) {
- int start = line.textStart();
- int length = line.textLength() + nextLine.textLength();
- const QStackTextEngine engine(textLayout.text().mid(start, length), option->font);
- elidedText = engine.elidedText(option->textElideMode, textRect.width());
- height += line.height();
- width = textRect.width();
- elidedIndex = j;
- break;
- }
- }
- if (line.naturalTextWidth() > textRect.width()) {
- int start = line.textStart();
- int length = line.textLength();
- const QStackTextEngine engine(textLayout.text().mid(start, length), option->font);
- elidedText = engine.elidedText(option->textElideMode, textRect.width());
- height += line.height();
- width = textRect.width();
- elidedIndex = j;
- break;
- }
- width = qMax<qreal>(width, line.width());
- height += line.height();
- }
-
+ const QRectF boundingRect = textLayout.boundingRect();
const QRect layoutRect = QStyle::alignedRect(option->direction, option->displayAlignment,
- QSize(int(width), int(height)), textRect);
+ boundingRect.size().toSize(), textRect);
const QPointF position = layoutRect.topLeft();
+ const int lineCount = textLayout.lineCount();
+
+ qreal height = 0;
for (int i = 0; i < lineCount; ++i) {
const QTextLine line = textLayout.lineAt(i);
- if (i == elidedIndex) {
- qreal x = position.x() + line.x();
- qreal y = position.y() + line.y() + line.ascent();
+ height += line.height();
+
+ // above visible rect
+ if (height + layoutRect.top() <= textRect.top())
+ continue;
+
+ const int start = line.textStart();
+ const int length = line.textLength();
+
+ const bool drawElided = line.naturalTextWidth() > textRect.width();
+ bool elideLastVisibleLine = false;
+ if (!drawElided && i + 1 < lineCount) {
+ const QTextLine nextLine = textLayout.lineAt(i + 1);
+ const int nextHeight = height + nextLine.height() / 2;
+ // elide when less than the next half line is visible
+ if (nextHeight + layoutRect.top() > textRect.height() + textRect.top())
+ elideLastVisibleLine = true;
+ }
+
+ if (drawElided || elideLastVisibleLine) {
+ QString text = textLayout.text().mid(start, length);
+ if (elideLastVisibleLine)
+ text += QChar(0x2026);
+ const QStackTextEngine engine(text, option->font);
+ const QString elidedText = engine.elidedText(option->textElideMode, textRect.width());
+ const QPointF pos(position.x() + line.x(),
+ position.y() + line.y() + line.ascent());
p->save();
p->setFont(option->font);
- p->drawText(QPointF(x, y), elidedText);
+ p->drawText(pos, elidedText);
p->restore();
- break;
+ } else {
+ line.draw(p, position);
}
- line.draw(p, position);
+
+ // below visible text, can stop
+ if (height + layoutRect.top() >= textRect.bottom())
+ break;
}
}
@@ -1675,8 +1673,9 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
alignment |= Qt::AlignLeft | Qt::AlignVCenter;
}
tr.translate(shiftX, shiftY);
+ const QString text = toolbutton->fontMetrics.elidedText(toolbutton->text, Qt::ElideMiddle, tr.width());
proxy()->drawItemText(p, QStyle::visualRect(opt->direction, rect, tr), alignment, toolbutton->palette,
- toolbutton->state & State_Enabled, toolbutton->text,
+ toolbutton->state & State_Enabled, text,
QPalette::ButtonText);
} else {
rect.translate(shiftX, shiftY);
@@ -2863,8 +2862,8 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
case SE_TabBarScrollLeftButton: {
const bool vertical = opt->rect.width() < opt->rect.height();
const Qt::LayoutDirection ld = widget->layoutDirection();
- const int buttonWidth = qMax(pixelMetric(QStyle::PM_TabBarScrollButtonWidth, 0, widget), QApplication::globalStrut().width());
- const int buttonOverlap = pixelMetric(QStyle::PM_TabBar_ScrollButtonOverlap, 0, widget);
+ const int buttonWidth = qMax(proxy()->pixelMetric(QStyle::PM_TabBarScrollButtonWidth, 0, widget), QApplication::globalStrut().width());
+ const int buttonOverlap = proxy()->pixelMetric(QStyle::PM_TabBar_ScrollButtonOverlap, 0, widget);
r = vertical ? QRect(0, opt->rect.height() - (buttonWidth * 2) + buttonOverlap, opt->rect.width(), buttonWidth)
: QStyle::visualRect(ld, opt->rect, QRect(opt->rect.width() - (buttonWidth * 2) + buttonOverlap, 0, buttonWidth, opt->rect.height()));
@@ -2872,7 +2871,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
case SE_TabBarScrollRightButton: {
const bool vertical = opt->rect.width() < opt->rect.height();
const Qt::LayoutDirection ld = widget->layoutDirection();
- const int buttonWidth = qMax(pixelMetric(QStyle::PM_TabBarScrollButtonWidth, 0, widget), QApplication::globalStrut().width());
+ const int buttonWidth = qMax(proxy()->pixelMetric(QStyle::PM_TabBarScrollButtonWidth, 0, widget), QApplication::globalStrut().width());
r = vertical ? QRect(0, opt->rect.height() - buttonWidth, opt->rect.width(), buttonWidth)
: QStyle::visualRect(ld, opt->rect, QRect(opt->rect.width() - buttonWidth, 0, buttonWidth, opt->rect.height()));
@@ -3087,7 +3086,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
//have all the information we need (ie. the layout's margin)
const QToolBar *tb = qobject_cast<const QToolBar*>(widget);
const int margin = tb && tb->layout() ? tb->layout()->margin() : 2;
- const int handleExtent = pixelMetric(QStyle::PM_ToolBarHandleExtent, opt, tb);
+ const int handleExtent = proxy()->pixelMetric(QStyle::PM_ToolBarHandleExtent, opt, tb);
if (tbopt->state & QStyle::State_Horizontal) {
r = QRect(margin, margin, handleExtent, tbopt->rect.height() - 2*margin);
r = QStyle::visualRect(tbopt->direction, tbopt->rect, r);
@@ -4942,8 +4941,8 @@ QSize QCommonStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
case CT_SpinBox:
if (const QStyleOptionSpinBox *vopt = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
// Add button + frame widths
- int buttonWidth = 20;
- int fw = vopt->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, vopt, widget) : 0;
+ const int buttonWidth = (vopt->subControls & (QStyle::SC_SpinBoxUp | QStyle::SC_SpinBoxDown)) != 0 ? 20 : 0;
+ const int fw = vopt->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, vopt, widget) : 0;
sz += QSize(buttonWidth + 2*fw, 2*fw);
}
break;
@@ -5312,6 +5311,9 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget
case SH_SpinBox_ButtonsInsideFrame:
ret = true;
break;
+ case SH_SpinBox_StepModifier:
+ ret = Qt::ControlModifier;
+ break;
default:
ret = 0;
break;
@@ -5724,14 +5726,14 @@ static inline QString iconPngSuffix() { return QStringLiteral(".png"); }
static void addIconFiles(const QString &prefix, const int sizes[], size_t count, QIcon &icon)
{
- for (size_t i = 0; i < count; ++i) {
- const int size = sizes[i];
- icon.addFile(prefix + QString::number(size) + iconPngSuffix(), QSize(size, size));
- }
+ for (size_t i = 0; i < count; ++i)
+ icon.addFile(prefix + QString::number(sizes[i]) + iconPngSuffix());
}
static const int dockTitleIconSizes[] = {10, 16, 20, 32, 48, 64};
-
+static const int titleBarSizes[] = {16, 32, 48};
+static const int toolBarExtHSizes[] = {8, 16, 32};
+static const int toolBarExtVSizes[] = {5, 10, 20};
#endif // imageformat_png
/*!
@@ -6046,6 +6048,27 @@ QIcon QCommonStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption
switch (standardIcon) {
#ifndef QT_NO_IMAGEFORMAT_PNG
+ case SP_TitleBarMinButton:
+ addIconFiles(iconResourcePrefix() + QStringLiteral("titlebar-min-"),
+ titleBarSizes, sizeof(titleBarSizes)/sizeof(titleBarSizes[0]), icon);
+ break;
+ case SP_TitleBarMaxButton:
+ addIconFiles(iconResourcePrefix() + QStringLiteral("titlebar-max-"),
+ titleBarSizes, sizeof(titleBarSizes)/sizeof(titleBarSizes[0]), icon);
+ break;
+ case SP_TitleBarShadeButton:
+ addIconFiles(iconResourcePrefix() + QStringLiteral("titlebar-shade-"),
+ titleBarSizes, sizeof(titleBarSizes)/sizeof(titleBarSizes[0]), icon);
+
+ break;
+ case SP_TitleBarUnshadeButton:
+ addIconFiles(iconResourcePrefix() + QStringLiteral("titlebar-unshade-"),
+ titleBarSizes, sizeof(titleBarSizes)/sizeof(titleBarSizes[0]), icon);
+ break;
+ case SP_TitleBarContextHelpButton:
+ addIconFiles(iconResourcePrefix() + QStringLiteral("titlebar-contexthelp-"),
+ titleBarSizes, sizeof(titleBarSizes)/sizeof(titleBarSizes[0]), icon);
+ break;
case SP_FileDialogNewFolder:
icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/newdirectory-16.png"), QSize(16, 16));
icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/newdirectory-32.png"), QSize(32, 32));
@@ -6254,6 +6277,17 @@ QIcon QCommonStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption
addIconFiles(iconResourcePrefix() + QStringLiteral("normalizedockup-"),
dockTitleIconSizes, sizeof(dockTitleIconSizes)/sizeof(dockTitleIconSizes[0]), icon);
break;
+ case SP_ToolBarHorizontalExtensionButton: {
+ QString prefix = iconResourcePrefix() + QStringLiteral("toolbar-ext-h-");
+ if (rtl)
+ prefix += QStringLiteral("rtl-");
+ addIconFiles(prefix, toolBarExtHSizes, sizeof(toolBarExtHSizes)/sizeof(toolBarExtHSizes[0]), icon);
+ }
+ break;
+ case SP_ToolBarVerticalExtensionButton:
+ addIconFiles(iconResourcePrefix() + QStringLiteral("toolbar-ext-v-"),
+ toolBarExtVSizes, sizeof(toolBarExtVSizes)/sizeof(toolBarExtVSizes[0]), icon);
+ break;
#endif // QT_NO_IMAGEFORMAT_PNG
default:
icon.addPixmap(proxy()->standardPixmap(standardIcon, option, widget));
diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp
index 73a6554f1a..8006be8c27 100644
--- a/src/widgets/styles/qstyle.cpp
+++ b/src/widgets/styles/qstyle.cpp
@@ -2001,6 +2001,13 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
Determnines if the spin box buttons are inside the line edit frame.
This enum value has been introduced in Qt 5.11.
+ \value SH_SpinBox_StepModifier
+ Determines which Qt::KeyboardModifier increases the step rate of
+ QAbstractSpinBox. Possible values are Qt::NoModifier,
+ Qt::ControlModifier (default) or Qt::ShiftModifier. Qt::NoModifier
+ disables this feature.
+ This enum value has been introduced in Qt 5.12.
+
\sa styleHint()
*/
diff --git a/src/widgets/styles/qstyle.h b/src/widgets/styles/qstyle.h
index cef569d514..9192dae864 100644
--- a/src/widgets/styles/qstyle.h
+++ b/src/widgets/styles/qstyle.h
@@ -741,6 +741,7 @@ public:
SH_Widget_Animation_Duration,
SH_ComboBox_AllowWheelScrolling,
SH_SpinBox_ButtonsInsideFrame,
+ SH_SpinBox_StepModifier,
// Add new style hint values here
SH_CustomBase = 0xf0000000
diff --git a/src/widgets/styles/qstyle.qrc b/src/widgets/styles/qstyle.qrc
index 2dc3207e6d..d3511ee754 100644
--- a/src/widgets/styles/qstyle.qrc
+++ b/src/widgets/styles/qstyle.qrc
@@ -140,13 +140,37 @@
<file>images/normalizedockup-32.png</file>
<file>images/normalizedockup-48.png</file>
<file>images/normalizedockup-64.png</file>
+ <file>images/toolbar-ext-h-8.png</file>
+ <file>images/toolbar-ext-h-16.png</file>
+ <file>images/toolbar-ext-h-32.png</file>
+ <file>images/toolbar-ext-h-rtl-8.png</file>
+ <file>images/toolbar-ext-h-rtl-16.png</file>
+ <file>images/toolbar-ext-h-rtl-32.png</file>
+ <file>images/toolbar-ext-v-5.png</file>
+ <file>images/toolbar-ext-v-10.png</file>
+ <file>images/toolbar-ext-v-20.png</file>
+ <file>images/titlebar-contexthelp-16.png</file>
+ <file>images/titlebar-contexthelp-32.png</file>
+ <file>images/titlebar-contexthelp-48.png</file>
+ <file>images/titlebar-max-16.png</file>
+ <file>images/titlebar-max-32.png</file>
+ <file>images/titlebar-max-48.png</file>
+ <file>images/titlebar-min-16.png</file>
+ <file>images/titlebar-min-32.png</file>
+ <file>images/titlebar-min-48.png</file>
+ <file>images/titlebar-shade-16.png</file>
+ <file>images/titlebar-shade-32.png</file>
+ <file>images/titlebar-shade-48.png</file>
+ <file>images/titlebar-unshade-16.png</file>
+ <file>images/titlebar-unshade-32.png</file>
+ <file>images/titlebar-unshade-48.png</file>
</qresource>
<qresource prefix="/qt-project.org/styles/macstyle">
<file alias="images/closedock-16.png">images/closedock-macstyle-16.png</file>
<file alias="images/closedock-down-16.png">images/closedock-down-macstyle-16.png</file>
<file alias="images/dockdock-16.png">images/dockdock-macstyle-16.png</file>
<file alias="images/dockdock-down-16.png">images/dockdock-down-macstyle-16.png</file>
- <file>images/toolbar-ext.png</file>
- <file>images/toolbar-ext@2x.png</file>
+ <file alias="images/toolbar-ext.png">images/toolbar-ext-macstyle.png</file>
+ <file alias="images/toolbar-ext@2x.png">images/toolbar-ext-macstyle@2x.png</file>
</qresource>
</RCC>
diff --git a/src/widgets/styles/qstylehelper.cpp b/src/widgets/styles/qstylehelper.cpp
index 8679d96eda..0b910d46df 100644
--- a/src/widgets/styles/qstylehelper.cpp
+++ b/src/widgets/styles/qstylehelper.cpp
@@ -403,14 +403,6 @@ QColor backgroundColor(const QPalette &pal, const QWidget* widget)
return pal.color(QPalette::Base);
}
-QWindow *styleObjectWindow(QObject *so)
-{
- if (so)
- return so->property("_q_styleObjectWindow").value<QWindow *>();
-
- return 0;
-}
-
WidgetSizePolicy widgetSizePolicy(const QWidget *widget, const QStyleOption *opt)
{
while (widget) {
diff --git a/src/widgets/styles/qstylehelper_p.h b/src/widgets/styles/qstylehelper_p.h
index 260860bf4d..d79dfe4288 100644
--- a/src/widgets/styles/qstylehelper_p.h
+++ b/src/widgets/styles/qstylehelper_p.h
@@ -90,7 +90,6 @@ namespace QStyleHelper
Q_WIDGETS_EXPORT bool hasAncestor(QObject *obj, QAccessible::Role role);
#endif
Q_WIDGETS_EXPORT QColor backgroundColor(const QPalette &pal, const QWidget* widget = 0);
- Q_WIDGETS_EXPORT QWindow *styleObjectWindow(QObject *so);
enum WidgetSizePolicy { SizeLarge = 0, SizeSmall = 1, SizeMini = 2, SizeDefault = -1 };
diff --git a/src/widgets/styles/qstyleoption.cpp b/src/widgets/styles/qstyleoption.cpp
index e7fa26e2d4..97631a5841 100644
--- a/src/widgets/styles/qstyleoption.cpp
+++ b/src/widgets/styles/qstyleoption.cpp
@@ -1842,10 +1842,12 @@ QStyleOptionMenuItem::QStyleOptionMenuItem(int version)
/*!
\variable QStyleOptionMenuItem::tabWidth
- \brief the tab width for the menu item
+ \brief the reserved width for the menu item's shortcut
- The tab width is the distance between the text of the menu item
- and the shortcut. The default value is 0.
+ QMenu sets it to the width occupied by the widest shortcut among
+ all visible items within the menu.
+
+ The default value is 0.
*/
diff --git a/src/widgets/styles/qstyleoption.h b/src/widgets/styles/qstyleoption.h
index 9fbaf34a86..8ae07efc81 100644
--- a/src/widgets/styles/qstyleoption.h
+++ b/src/widgets/styles/qstyleoption.h
@@ -366,7 +366,7 @@ public:
QString text;
QIcon icon;
int maxIconWidth;
- int tabWidth;
+ int tabWidth; // ### Qt 6: rename to reservedShortcutWidth
QFont font;
QStyleOptionMenuItem();
diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp
index ceede9e72f..71c7f5449a 100644
--- a/src/widgets/styles/qstylesheetstyle.cpp
+++ b/src/widgets/styles/qstylesheetstyle.cpp
@@ -117,6 +117,8 @@
#include <QtWidgets/qtoolbar.h>
#endif
+#include <QtGui/qscreen.h>
+
QT_BEGIN_NAMESPACE
using namespace QCss;
@@ -532,6 +534,8 @@ public:
const QStyleSheetGeometryData *geometry() const { return geo; }
const QStyleSheetPositionData *position() const { return p; }
+ bool hasModification() const;
+
bool hasPalette() const { return pal != 0; }
bool hasBackground() const { return bg != 0 && (!bg->pixmap.isNull() || bg->brush.style() != Qt::NoBrush); }
bool hasGradientBackground() const { return bg && bg->brush.style() >= Qt::LinearGradientPattern
@@ -952,8 +956,10 @@ QRenderRule::QRenderRule(const QVector<Declaration> &declarations, const QObject
Attachment attachment = Attachment_Scroll;
origin = Origin_Padding;
Origin clip = Origin_Border;
- if (v.extractBackground(&brush, &uri, &repeat, &alignment, &origin, &attachment, &clip))
- bg = new QStyleSheetBackgroundData(brush, QPixmap(uri), repeat, alignment, origin, attachment, clip);
+ if (v.extractBackground(&brush, &uri, &repeat, &alignment, &origin, &attachment, &clip)) {
+ bg = new QStyleSheetBackgroundData(brush, QStyleSheetStyle::loadPixmap(uri, object),
+ repeat, alignment, origin, attachment, clip);
+ }
QBrush sfg, fg;
QBrush sbg, abg;
@@ -992,7 +998,7 @@ QRenderRule::QRenderRule(const QVector<Declaration> &declarations, const QObject
bd->bi = new QStyleSheetBorderImageData;
QStyleSheetBorderImageData *bi = bd->bi;
- bi->pixmap = QPixmap(uri);
+ bi->pixmap = QStyleSheetStyle::loadPixmap(uri, object);
for (int i = 0; i < 4; i++)
bi->cuts[i] = cuts[i];
bi->horizStretch = horizStretch;
@@ -1043,7 +1049,7 @@ QRenderRule::QRenderRule(const QVector<Declaration> &declarations, const QObject
if (const QWidget *widget = qobject_cast<const QWidget *>(object)) {
QStyleSheetStyle *style = const_cast<QStyleSheetStyle *>(globalStyleSheetStyle);
if (!style)
- style = qobject_cast<QStyleSheetStyle *>(widget->style());
+ style = qt_styleSheet(widget->style());
if (style)
fixupBorder(style->nativeFrameWidth(widget));
}
@@ -1215,30 +1221,33 @@ void QRenderRule::drawBackgroundImage(QPainter *p, const QRect &rect, QPoint off
if (background()->attachment == Attachment_Fixed)
off = QPoint(0, 0);
+ QSize bgpSize = bgp.size() / bgp.devicePixelRatio();
+ int bgpHeight = bgpSize.height();
+ int bgpWidth = bgpSize.width();
QRect r = originRect(rect, background()->origin);
- QRect aligned = QStyle::alignedRect(Qt::LeftToRight, background()->position, bgp.size(), r);
+ QRect aligned = QStyle::alignedRect(Qt::LeftToRight, background()->position, bgpSize, r);
QRect inter = aligned.translated(-off).intersected(r);
switch (background()->repeat) {
case Repeat_Y:
p->drawTiledPixmap(inter.x(), r.y(), inter.width(), r.height(), bgp,
inter.x() - aligned.x() + off.x(),
- bgp.height() - int(aligned.y() - r.y()) % bgp.height() + off.y());
+ bgpHeight - int(aligned.y() - r.y()) % bgpHeight + off.y());
break;
case Repeat_X:
p->drawTiledPixmap(r.x(), inter.y(), r.width(), inter.height(), bgp,
- bgp.width() - int(aligned.x() - r.x())%bgp.width() + off.x(),
+ bgpWidth - int(aligned.x() - r.x())%bgpWidth + off.x(),
inter.y() - aligned.y() + off.y());
break;
case Repeat_XY:
p->drawTiledPixmap(r, bgp,
- QPoint(bgp.width() - int(aligned.x() - r.x())% bgp.width() + off.x(),
- bgp.height() - int(aligned.y() - r.y())%bgp.height() + off.y()));
+ QPoint(bgpWidth - int(aligned.x() - r.x())% bgpWidth + off.x(),
+ bgpHeight - int(aligned.y() - r.y())%bgpHeight + off.y()));
break;
case Repeat_None:
default:
p->drawPixmap(inter.x(), inter.y(), bgp, inter.x() - aligned.x() + off.x(),
- inter.y() - aligned.y() + off.y(), inter.width(), inter.height());
+ inter.y() - aligned.y() + off.y(), bgp.width() , bgp.height());
break;
}
@@ -1446,6 +1455,21 @@ void QRenderRule::configurePalette(QPalette *p, QPalette::ColorGroup cg, const Q
p->setBrush(cg, QPalette::AlternateBase, pal->alternateBackground);
}
+bool QRenderRule::hasModification() const
+{
+ return hasPalette() ||
+ hasBackground() ||
+ hasGradientBackground() ||
+ !hasNativeBorder() ||
+ !hasNativeOutline() ||
+ hasBox() ||
+ hasPosition() ||
+ hasGeometry() ||
+ hasImage() ||
+ hasFont ||
+ !styleHints.isEmpty();
+}
+
///////////////////////////////////////////////////////////////////////////////
// Style rules
#define OBJECT_PTR(x) (static_cast<QObject *>(x.ptr))
@@ -1504,7 +1528,7 @@ public:
return className;
} else if (name == QLatin1String("style")) {
QWidget *w = qobject_cast<QWidget *>(obj);
- QStyleSheetStyle *proxy = w ? qobject_cast<QStyleSheetStyle *>(w->style()) : 0;
+ QStyleSheetStyle *proxy = w ? qt_styleSheet(w->style()) : 0;
if (proxy) {
QString styleName = QString::fromLatin1(proxy->baseStyle()->metaObject()->className());
cache[name] = styleName;
@@ -1925,11 +1949,11 @@ QRenderRule QStyleSheetStyle::renderRule(const QObject *obj, const QStyleOption
break;
case QTabBar::RoundedEast:
case QTabBar::TriangularEast:
- extraClass |= PseudoClass_Left;
+ extraClass |= PseudoClass_Right;
break;
case QTabBar::RoundedWest:
case QTabBar::TriangularWest:
- extraClass |= PseudoClass_Right;
+ extraClass |= PseudoClass_Left;
break;
default:
break;
@@ -1962,11 +1986,11 @@ QRenderRule QStyleSheetStyle::renderRule(const QObject *obj, const QStyleOption
break;
case QTabBar::RoundedEast:
case QTabBar::TriangularEast:
- extraClass |= PseudoClass_Left;
+ extraClass |= PseudoClass_Right;
break;
case QTabBar::RoundedWest:
case QTabBar::TriangularWest:
- extraClass |= PseudoClass_Right;
+ extraClass |= PseudoClass_Left;
break;
default:
break;
@@ -2736,7 +2760,7 @@ QStyle *QStyleSheetStyle::baseStyle() const
{
if (base)
return base;
- if (QStyleSheetStyle *me = qobject_cast<QStyleSheetStyle *>(QApplication::style()))
+ if (QStyleSheetStyle *me = qt_styleSheet(QApplication::style()))
return me->base;
return QApplication::style();
}
@@ -2825,6 +2849,9 @@ void QStyleSheetStyle::polish(QWidget *w)
#endif
QRenderRule rule = renderRule(w, PseudoElement_None, PseudoClass_Any);
+
+ w->setAttribute(Qt::WA_StyleSheetTarget, rule.hasModification());
+
if (rule.hasDrawable() || rule.hasBox()) {
if (w->metaObject() == &QWidget::staticMetaObject
#if QT_CONFIG(itemviews)
@@ -2908,6 +2935,7 @@ void QStyleSheetStyle::unpolish(QWidget *w)
styleSheetCaches->styleSheetCache.remove(w);
unsetPalette(w);
setGeometry(w);
+ w->setAttribute(Qt::WA_StyleSheetTarget, false);
w->setAttribute(Qt::WA_StyleSheet, false);
QObject::disconnect(w, 0, this, 0);
#if QT_CONFIG(scrollarea)
@@ -3672,6 +3700,17 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
bool dis = !(opt->state & QStyle::State_Enabled),
act = opt->state & QStyle::State_Selected;
+ int checkableOffset = 0;
+ if (checkable) {
+ QRenderRule subSubRule = renderRule(w, opt, PseudoElement_MenuCheckMark);
+ QStyleOptionMenuItem newMi = mi;
+ newMi.rect = positionRect(w, subRule, subSubRule, PseudoElement_MenuCheckMark, opt->rect, opt->direction);
+ checkableOffset = newMi.rect.width();
+ if (subSubRule.hasDrawable() || checked)
+ drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, w);
+ }
+
+ int iconOffset = 0;
if (!mi.icon.isNull()) {
QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal;
if (act && !dis)
@@ -3691,20 +3730,22 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
iconRule.geo->height = pixh;
}
QRect iconRect = positionRect(w, subRule, iconRule, PseudoElement_MenuIcon, opt->rect, opt->direction);
+ if (opt->direction == Qt::LeftToRight)
+ iconRect.moveLeft(iconRect.left() + checkableOffset);
+ else
+ iconRect.moveRight(iconRect.right() - checkableOffset);
iconRule.drawRule(p, iconRect);
QRect pmr(0, 0, pixw, pixh);
pmr.moveCenter(iconRect.center());
p->drawPixmap(pmr.topLeft(), pixmap);
- } else if (checkable) {
- QRenderRule subSubRule = renderRule(w, opt, PseudoElement_MenuCheckMark);
- if (subSubRule.hasDrawable() || checked) {
- QStyleOptionMenuItem newMi = mi;
- newMi.rect = positionRect(w, subRule, subSubRule, PseudoElement_MenuCheckMark, opt->rect, opt->direction);
- drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, w);
- }
+ iconOffset = iconRule.geo->width;
}
QRect textRect = subRule.contentsRect(opt->rect);
+ if (opt->direction == Qt::LeftToRight)
+ textRect.setLeft(textRect.left() + checkableOffset + iconOffset);
+ else
+ textRect.setRight(textRect.right() - checkableOffset - iconOffset);
textRect.setWidth(textRect.width() - mi.tabWidth);
QStringRef s(&mi.text);
p->setPen(mi.palette.buttonText().color());
@@ -3838,17 +3879,10 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
if(hasStyleRule(w, PseudoElement_HeaderViewSection)) {
QRenderRule subRule = renderRule(w, opt, PseudoElement_HeaderViewSection);
if (!subRule.hasNativeBorder() || !subRule.baseStyleCanDraw()
- || subRule.hasBackground() || subRule.hasPalette() || subRule.hasFont) {
+ || subRule.hasBackground() || subRule.hasPalette() || subRule.hasFont || subRule.hasBorder()) {
ParentStyle::drawControl(ce, opt, p, w);
return;
}
- if (subRule.hasFont) {
- const QFont oldFont = p->font();
- p->setFont(subRule.font.resolve(p->font()));
- baseStyle()->drawControl(ce, opt, p, w);
- p->setFont(oldFont);
- return;
- }
}
break;
case CE_HeaderSection:
@@ -4821,13 +4855,12 @@ int QStyleSheetStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const
return 0;
break;
- case PM_TabBarScrollButtonWidth: {
+ case PM_TabBarScrollButtonWidth:
subRule = renderRule(w, opt, PseudoElement_TabBarScroller);
if (subRule.hasContentsSize()) {
QSize sz = subRule.size();
- return sz.width() != -1 ? sz.width() : sz.height();
+ return (sz.width() != -1 ? sz.width() : sz.height()) / 2;
}
- }
break;
case PM_TabBarTabShiftHorizontal:
@@ -5050,6 +5083,16 @@ QSize QStyleSheetStyle::sizeFromContents(ContentsType ct, const QStyleOption *op
int width = csz.width();
if (mi->text.contains(QLatin1Char('\t')))
width += 12; //as in QCommonStyle
+ bool checkable = mi->checkType != QStyleOptionMenuItem::NotCheckable;
+ if (checkable) {
+ QRenderRule subSubRule = renderRule(w, opt, PseudoElement_MenuCheckMark);
+ QRect checkmarkRect = positionRect(w, subRule, subSubRule, PseudoElement_MenuCheckMark, opt->rect, opt->direction);
+ width += checkmarkRect.width();
+ }
+ if (!mi->icon.isNull()) {
+ QPixmap pixmap = mi->icon.pixmap(pixelMetric(PM_SmallIconSize));
+ width += pixmap.width();
+ }
return subRule.boxSize(subRule.adjustSize(QSize(width, csz.height())));
}
}
@@ -5200,7 +5243,7 @@ static QLatin1String propertyNameForStandardPixmap(QStyle::StandardPixmap sp)
case QStyle::SP_DialogCloseButton: return QLatin1String("dialog-close-icon");
case QStyle::SP_DialogApplyButton: return QLatin1String("dialog-apply-icon");
case QStyle::SP_DialogResetButton: return QLatin1String("dialog-reset-icon");
- case QStyle::SP_DialogDiscardButton: return QLatin1String("discard-icon");
+ case QStyle::SP_DialogDiscardButton: return QLatin1String("dialog-discard-icon");
case QStyle::SP_DialogYesButton: return QLatin1String("dialog-yes-icon");
case QStyle::SP_DialogNoButton: return QLatin1String("dialog-no-icon");
case QStyle::SP_ArrowUp: return QLatin1String("uparrow-icon");
@@ -5876,6 +5919,12 @@ QRect QStyleSheetStyle::subElementRect(SubElement se, const QStyleOption *opt, c
}
break;
+ case SE_TabBarScrollLeftButton:
+ case SE_TabBarScrollRightButton:
+ if (hasStyleRule(w, PseudoElement_TabBarScroller))
+ return ParentStyle::subElementRect(se, opt, w);
+ break;
+
case SE_TabBarTearIndicator: {
QRenderRule subRule = renderRule(w, opt, PseudoElement_TabBarTear);
if (subRule.hasContentsSize()) {
@@ -6067,6 +6116,28 @@ bool QStyleSheetStyle::isNaturalChild(const QObject *obj)
return false;
}
+QPixmap QStyleSheetStyle::loadPixmap(const QString &fileName, const QObject *context)
+{
+ qreal ratio = -1.0;
+ if (const QWidget *widget = qobject_cast<const QWidget *>(context)) {
+ if (QScreen *screen = QApplication::screenAt(widget->mapToGlobal(QPoint(0, 0))))
+ ratio = screen->devicePixelRatio();
+ }
+
+ if (ratio < 0) {
+ if (const QApplication *app = qApp)
+ ratio = app->devicePixelRatio();
+ else
+ ratio = 1.0;
+ }
+
+ qreal sourceDevicePixelRatio = 1.0;
+ QString resolvedFileName = qt_findAtNxFile(fileName, ratio, &sourceDevicePixelRatio);
+ QPixmap pixmap(resolvedFileName);
+ pixmap.setDevicePixelRatio(sourceDevicePixelRatio);
+ return pixmap;
+}
+
QT_END_NAMESPACE
#include "moc_qstylesheetstyle_p.cpp"
diff --git a/src/widgets/styles/qstylesheetstyle_p.h b/src/widgets/styles/qstylesheetstyle_p.h
index 042abf5c22..d4edb83525 100644
--- a/src/widgets/styles/qstylesheetstyle_p.h
+++ b/src/widgets/styles/qstylesheetstyle_p.h
@@ -167,6 +167,7 @@ private:
static Qt::Alignment resolveAlignment(Qt::LayoutDirection, Qt::Alignment);
static bool isNaturalChild(const QObject *obj);
+ static QPixmap loadPixmap(const QString &fileName, const QObject *context);
bool initObject(const QObject *obj) const;
public:
static int numinstances;
@@ -215,6 +216,13 @@ template <typename T>
class QTypeInfo<QStyleSheetStyleCaches::Tampered<T>>
: QTypeInfoMerger<QStyleSheetStyleCaches::Tampered<T>, T> {};
+
+// Returns a QStyleSheet from the given style.
+inline QStyleSheetStyle* qt_styleSheet(QStyle *style)
+{
+ return qobject_cast<QStyleSheetStyle *>(style);
+}
+
QT_END_NAMESPACE
#endif // QT_NO_STYLE_STYLESHEET
#endif // QSTYLESHEETSTYLE_P_H
diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp
index 80ce8419f8..12ca5201c1 100644
--- a/src/widgets/styles/qwindowsstyle.cpp
+++ b/src/widgets/styles/qwindowsstyle.cpp
@@ -842,17 +842,19 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
: opt->palette.text().color());
if (opt->state & State_NoChange)
p->setBrush(opt->palette.brush(QPalette::Button));
- p->drawRect(opt->rect.x() + 1, opt->rect.y() + 1, 11, 11);
+ p->drawRect(opt->rect.x() + 1, opt->rect.y() + 1, opt->rect.width() - 2, opt->rect.height() - 2);
}
#endif // QT_CONFIG(itemviews)
if (!(opt->state & State_Off)) {
QPointF points[6];
- points[0] = { opt->rect.x() + QStyleHelper::dpiScaled(3.5), opt->rect.y() + QStyleHelper::dpiScaled(5.5) };
- points[1] = { points[0].x(), points[0].y() + QStyleHelper::dpiScaled(2) };
- points[2] = { points[1].x() + QStyleHelper::dpiScaled(2), points[1].y() + QStyleHelper::dpiScaled(2) };
- points[3] = { points[2].x() + QStyleHelper::dpiScaled(4), points[2].y() - QStyleHelper::dpiScaled(4) };
- points[4] = { points[3].x(), points[3].y() - QStyleHelper::dpiScaled(2) };
- points[5] = { points[4].x() - QStyleHelper::dpiScaled(4), points[4].y() + QStyleHelper::dpiScaled(4) };
+ qreal scaleh = opt->rect.width() / 12.0;
+ qreal scalev = opt->rect.height() / 12.0;
+ points[0] = { opt->rect.x() + 3.5 * scaleh, opt->rect.y() + 5.5 * scalev };
+ points[1] = { points[0].x(), points[0].y() + 2 * scalev };
+ points[2] = { points[1].x() + 2 * scaleh, points[1].y() + 2 * scalev };
+ points[3] = { points[2].x() + 4 * scaleh, points[2].y() - 4 * scalev };
+ points[4] = { points[3].x(), points[3].y() - 2 * scalev };
+ points[5] = { points[4].x() - 4 * scaleh, points[4].y() + 4 * scalev };
p->setPen(QPen(opt->palette.text().color(), 0));
p->setBrush(opt->palette.text().color());
p->drawPolygon(points, 6);
@@ -1150,9 +1152,6 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, opt, widget), mode);
const int pixw = pixmap.width() / pixmap.devicePixelRatio();
const int pixh = pixmap.height() / pixmap.devicePixelRatio();
- if (act && !dis && !checked)
- qDrawShadePanel(p, vCheckRect, menuitem->palette, false, 1,
- &menuitem->palette.brush(QPalette::Button));
QRect pmr(0, 0, pixw, pixh);
pmr.moveCenter(vCheckRect.center());
p->setPen(menuitem->palette.text().color());
diff --git a/src/widgets/util/qcompleter.cpp b/src/widgets/util/qcompleter.cpp
index 22fb0a511d..0daa4a4b41 100644
--- a/src/widgets/util/qcompleter.cpp
+++ b/src/widgets/util/qcompleter.cpp
@@ -144,6 +144,7 @@
#include "qcompleter_p.h"
#include "QtWidgets/qscrollbar.h"
+#include "QtCore/qdir.h"
#include "QtCore/qstringlistmodel.h"
#if QT_CONFIG(dirmodel)
#include "QtWidgets/qdirmodel.h"
@@ -181,10 +182,10 @@ int QCompletionModel::columnCount(const QModelIndex &) const
void QCompletionModel::setSourceModel(QAbstractItemModel *source)
{
- bool hadModel = (sourceModel() != 0);
+ bool hadModel = (sourceModel() != nullptr);
if (hadModel)
- QObject::disconnect(sourceModel(), 0, this, 0);
+ QObject::disconnect(sourceModel(), nullptr, this, nullptr);
QAbstractProxyModel::setSourceModel(source);
@@ -401,7 +402,7 @@ QVariant QCompletionModel::data(const QModelIndex& index, int role) const
void QCompletionModel::modelDestroyed()
{
- QAbstractProxyModel::setSourceModel(0); // switch to static empty model
+ QAbstractProxyModel::setSourceModel(nullptr); // switch to static empty model
invalidate();
}
@@ -470,13 +471,13 @@ QMatchData QCompletionEngine::filterHistory()
return QMatchData();
#if QT_CONFIG(dirmodel)
- const bool isDirModel = (qobject_cast<QDirModel *>(source) != 0);
+ const bool isDirModel = (qobject_cast<QDirModel *>(source) != nullptr);
#else
const bool isDirModel = false;
#endif
Q_UNUSED(isDirModel)
#if QT_CONFIG(filesystemmodel)
- const bool isFsModel = (qobject_cast<QFileSystemModel *>(source) != 0);
+ const bool isFsModel = (qobject_cast<QFileSystemModel *>(source) != nullptr);
#else
const bool isFsModel = false;
#endif
@@ -827,9 +828,18 @@ QMatchData QUnsortedModelEngine::filter(const QString& part, const QModelIndex&
///////////////////////////////////////////////////////////////////////////////
QCompleterPrivate::QCompleterPrivate()
-: widget(0), proxy(0), popup(0), filterMode(Qt::MatchStartsWith), cs(Qt::CaseSensitive),
- role(Qt::EditRole), column(0), maxVisibleItems(7), sorting(QCompleter::UnsortedModel),
- wrap(true), eatFocusOut(true), hiddenBecauseNoMatch(false)
+ : widget(nullptr),
+ proxy(nullptr),
+ popup(nullptr),
+ filterMode(Qt::MatchStartsWith),
+ cs(Qt::CaseSensitive),
+ role(Qt::EditRole),
+ column(0),
+ maxVisibleItems(7),
+ sorting(QCompleter::UnsortedModel),
+ wrap(true),
+ eatFocusOut(true),
+ hiddenBecauseNoMatch(false)
{
}
@@ -1000,7 +1010,7 @@ QCompleter::QCompleter(QAbstractItemModel *model, QObject *parent)
d->init(model);
}
-#ifndef QT_NO_STRINGLISTMODEL
+#if QT_CONFIG(stringlistmodel)
/*!
Constructs a QCompleter object with the given \a parent that uses the specified
\a list as a source of possible completions.
@@ -1011,7 +1021,7 @@ QCompleter::QCompleter(const QStringList& list, QObject *parent)
Q_D(QCompleter);
d->init(new QStringListModel(list, this));
}
-#endif // QT_NO_STRINGLISTMODEL
+#endif // QT_CONFIG(stringlistmodel)
/*!
Destroys the completer object.
@@ -1145,7 +1155,7 @@ void QCompleter::setCompletionMode(QCompleter::CompletionMode mode)
d->widget->removeEventFilter(this);
if (d->popup) {
d->popup->deleteLater();
- d->popup = 0;
+ d->popup = nullptr;
}
} else {
if (d->widget)
@@ -1221,8 +1231,8 @@ void QCompleter::setPopup(QAbstractItemView *popup)
Q_D(QCompleter);
Q_ASSERT(popup != 0);
if (d->popup) {
- QObject::disconnect(d->popup->selectionModel(), 0, this, 0);
- QObject::disconnect(d->popup, 0, this, 0);
+ QObject::disconnect(d->popup->selectionModel(), nullptr, this, nullptr);
+ QObject::disconnect(d->popup, nullptr, this, nullptr);
}
if (d->popup != popup)
delete d->popup;
@@ -1494,7 +1504,7 @@ void QCompleter::complete(const QRect& rect)
return;
}
- Q_ASSERT(d->widget != 0);
+ Q_ASSERT(d->widget);
if ((d->mode == QCompleter::PopupCompletion && !idx.isValid())
|| (d->mode == QCompleter::UnfilteredPopupCompletion && d->proxy->rowCount() == 0)) {
if (d->popup)
@@ -1804,10 +1814,10 @@ QString QCompleter::pathFromIndex(const QModelIndex& index) const
bool isDirModel = false;
bool isFsModel = false;
#if QT_CONFIG(dirmodel)
- isDirModel = qobject_cast<QDirModel *>(d->proxy->sourceModel()) != 0;
+ isDirModel = qobject_cast<QDirModel *>(d->proxy->sourceModel()) != nullptr;
#endif
#if QT_CONFIG(filesystemmodel)
- isFsModel = qobject_cast<QFileSystemModel *>(d->proxy->sourceModel()) != 0;
+ isFsModel = qobject_cast<QFileSystemModel *>(d->proxy->sourceModel()) != nullptr;
#endif
if (!isDirModel && !isFsModel)
return sourceModel->data(index, d->role).toString();
@@ -1854,13 +1864,13 @@ QStringList QCompleter::splitPath(const QString& path) const
bool isFsModel = false;
#if QT_CONFIG(dirmodel)
Q_D(const QCompleter);
- isDirModel = qobject_cast<QDirModel *>(d->proxy->sourceModel()) != 0;
+ isDirModel = qobject_cast<QDirModel *>(d->proxy->sourceModel()) != nullptr;
#endif
#if QT_CONFIG(filesystemmodel)
#if !QT_CONFIG(dirmodel)
Q_D(const QCompleter);
#endif
- isFsModel = qobject_cast<QFileSystemModel *>(d->proxy->sourceModel()) != 0;
+ isFsModel = qobject_cast<QFileSystemModel *>(d->proxy->sourceModel()) != nullptr;
#endif
if ((!isDirModel && !isFsModel) || path.isEmpty())
diff --git a/src/widgets/util/qcompleter.h b/src/widgets/util/qcompleter.h
index de79302e15..5620b55589 100644
--- a/src/widgets/util/qcompleter.h
+++ b/src/widgets/util/qcompleter.h
@@ -84,10 +84,10 @@ public:
QCompleter(QObject *parent = nullptr);
QCompleter(QAbstractItemModel *model, QObject *parent = nullptr);
-#ifndef QT_NO_STRINGLISTMODEL
+#if QT_CONFIG(stringlistmodel)
QCompleter(const QStringList& completions, QObject *parent = nullptr);
#endif
- ~QCompleter();
+ ~QCompleter() override;
void setWidget(QWidget *widget);
QWidget *widget() const;
diff --git a/src/widgets/util/qscroller.cpp b/src/widgets/util/qscroller.cpp
index ea8168b55c..e229a885a8 100644
--- a/src/widgets/util/qscroller.cpp
+++ b/src/widgets/util/qscroller.cpp
@@ -249,18 +249,11 @@ private:
scrolling speed and takes care of updates.
QScroller can be triggered by a flick gesture
- \code
- QWidget *w = ...;
- QScroller::grabGesture(w, QScroller::LeftMouseButtonGesture);
- \endcode
+ \snippet code/src_widgets_util_qscroller.cpp 0
or directly like this:
- \code
- QWidget *w = ...;
- QScroller *scroller = QScroller::scroller(w);
- scroller->scrollTo(QPointF(100, 100));
- \endcode
+ \snippet code/src_widgets_util_qscroller.cpp 1
The scrolled QObjects receive a QScrollPrepareEvent whenever the scroller needs to
update its geometry information and a QScrollEvent whenever the content of the object should
@@ -1894,7 +1887,7 @@ qreal QScrollerPrivate::nextSnapPos(qreal p, int dir, Qt::Orientation orientatio
if (orientation == Qt::Horizontal) {
// the snap points in the list
- foreach (qreal snapPos, snapPositionsX) {
+ for (qreal snapPos : snapPositionsX) {
qreal snapPosDist = snapPos - p;
if ((dir > 0 && snapPosDist < 0) ||
(dir < 0 && snapPosDist > 0))
@@ -1941,7 +1934,7 @@ qreal QScrollerPrivate::nextSnapPos(qreal p, int dir, Qt::Orientation orientatio
} else { // (orientation == Qt::Vertical)
// the snap points in the list
- foreach (qreal snapPos, snapPositionsY) {
+ for (qreal snapPos : snapPositionsY) {
qreal snapPosDist = snapPos - p;
if ((dir > 0 && snapPosDist < 0) ||
(dir < 0 && snapPosDist > 0))
diff --git a/src/widgets/util/qsystemtrayicon.cpp b/src/widgets/util/qsystemtrayicon.cpp
index 86c824afdb..d15f5e5955 100644
--- a/src/widgets/util/qsystemtrayicon.cpp
+++ b/src/widgets/util/qsystemtrayicon.cpp
@@ -523,6 +523,8 @@ QBalloonTip::QBalloonTip(const QIcon &icon, const QString &title,
closeButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
closeButton->setFixedSize(closeButtonSize, closeButtonSize);
QObject::connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
+#else
+ Q_UNUSED(closeButtonSize);
#endif
#if QT_CONFIG(label)
diff --git a/src/widgets/util/qsystemtrayicon_x11.cpp b/src/widgets/util/qsystemtrayicon_x11.cpp
index df93e15f80..86532456c7 100644
--- a/src/widgets/util/qsystemtrayicon_x11.cpp
+++ b/src/widgets/util/qsystemtrayicon_x11.cpp
@@ -63,8 +63,6 @@
#include <private/qguiapplication_p.h>
#include <qdebug.h>
-#include <QtPlatformHeaders/qxcbwindowfunctions.h>
-#include <QtPlatformHeaders/qxcbintegrationfunctions.h>
#ifndef QT_NO_SYSTEMTRAYICON
QT_BEGIN_NAMESPACE
@@ -98,10 +96,7 @@ private slots:
void systemTrayWindowChanged(QScreen *screen);
private:
- bool addToTray();
-
QSystemTrayIcon *q;
- QPixmap background;
};
QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *qIn)
@@ -117,55 +112,13 @@ QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *qIn)
const QSize size(22, 22); // Gnome, standard size
setGeometry(QRect(QPoint(0, 0), size));
setMinimumSize(size);
-
- // We need two different behaviors depending on whether the X11 visual for the system tray
- // (a) exists and (b) supports an alpha channel, i.e. is 32 bits.
- // If we have a visual that has an alpha channel, we can paint this widget with a transparent
- // background and it will work.
- // However, if there's no alpha channel visual, in order for transparent tray icons to work,
- // we do not have a transparent background on the widget, but set the BackPixmap property of our
- // window to ParentRelative (so that it inherits the background of its X11 parent window), call
- // xcb_clear_region before painting (so that the inherited background is visible) and then grab
- // the just-drawn background from the X11 server.
- bool hasAlphaChannel = QXcbIntegrationFunctions::xEmbedSystemTrayVisualHasAlphaChannel();
- setAttribute(Qt::WA_TranslucentBackground, hasAlphaChannel);
- if (!hasAlphaChannel) {
- createWinId();
- QXcbWindowFunctions::setParentRelativeBackPixmap(windowHandle());
-
- // XXX: This is actually required, but breaks things ("QWidget::paintEngine: Should no
- // longer be called"). Why is this needed? When the widget is drawn, we use tricks to grab
- // the tray icon's background from the server. If the tray icon isn't visible (because
- // another window is on top of it), the trick fails and instead uses the content of that
- // other window as the background.
- // setAttribute(Qt::WA_PaintOnScreen);
- }
-
- addToTray();
-}
-
-bool QSystemTrayIconSys::addToTray()
-{
- if (!locateSystemTray())
- return false;
-
- createWinId();
+ setAttribute(Qt::WA_TranslucentBackground);
setMouseTracking(true);
-
- if (!QXcbWindowFunctions::requestSystemTrayWindowDock(windowHandle()))
- return false;
-
- if (!background.isNull())
- background = QPixmap();
- show();
- return true;
}
void QSystemTrayIconSys::systemTrayWindowChanged(QScreen *)
{
- if (locateSystemTray()) {
- addToTray();
- } else {
+ if (!locateSystemTray()) {
QBalloonTip::hideBalloon();
hide(); // still no luck
destroy();
@@ -174,7 +127,7 @@ void QSystemTrayIconSys::systemTrayWindowChanged(QScreen *)
QRect QSystemTrayIconSys::globalGeometry() const
{
- return QXcbWindowFunctions::systemTrayWindowGlobalGeometry(windowHandle());
+ return QRect(mapToGlobal(QPoint(0, 0)), size());
}
void QSystemTrayIconSys::mousePressEvent(QMouseEvent *ev)
@@ -227,22 +180,6 @@ void QSystemTrayIconSys::paintEvent(QPaintEvent *)
const QRect rect(QPoint(0, 0), geometry().size());
QPainter painter(this);
- // If we have Qt::WA_TranslucentBackground set, during widget creation
- // we detected the systray visual supported an alpha channel
- if (testAttribute(Qt::WA_TranslucentBackground)) {
- painter.setCompositionMode(QPainter::CompositionMode_Source);
- painter.fillRect(rect, Qt::transparent);
- } else {
- // clearRegion() was called on XEMBED_EMBEDDED_NOTIFY, so we hope that got done by now.
- // Grab the tray background pixmap, before rendering the icon for the first time.
- if (background.isNull()) {
- background = QGuiApplication::primaryScreen()->grabWindow(winId(),
- 0, 0, rect.size().width(), rect.size().height());
- }
- // Then paint over the icon area with the background before compositing the icon on top.
- painter.drawPixmap(QPoint(0, 0), background);
- }
- painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
q->icon().paint(&painter, rect);
}
@@ -285,6 +222,7 @@ void QSystemTrayIconPrivate::install_sys()
sys = new QSystemTrayIconSys(q);
QObject::connect(QGuiApplication::platformNativeInterface(), SIGNAL(systemTrayWindowChanged(QScreen*)),
sys, SLOT(systemTrayWindowChanged(QScreen*)));
+ sys->show();
}
}
diff --git a/src/widgets/util/qundostack.cpp b/src/widgets/util/qundostack.cpp
index b371e903a6..e928b9fe37 100644
--- a/src/widgets/util/qundostack.cpp
+++ b/src/widgets/util/qundostack.cpp
@@ -742,6 +742,17 @@ void QUndoStack::resetClean()
}
/*!
+ \since 5.12
+ \property QUndoStack::clean
+ \brief the clean status of this stack.
+
+ This property indicates whether or not the stack is clean. For example, a
+ stack is clean when a document has been saved.
+
+ \sa isClean(), setClean(), resetClean(), cleanIndex()
+*/
+
+/*!
If the stack is in the clean state, returns \c true; otherwise returns \c false.
\sa setClean(), cleanIndex()
@@ -940,6 +951,17 @@ void QUndoStack::setIndex(int idx)
}
/*!
+ \since 5.12
+ \property QUndoStack::canUndo
+ \brief whether this stack can undo.
+
+ This property indicates whether or not there is a command that can be
+ undone.
+
+ \sa canUndo(), index(), canRedo()
+*/
+
+/*!
Returns \c true if there is a command available for undo; otherwise returns \c false.
This function returns \c false if the stack is empty, or if the bottom command
@@ -959,6 +981,17 @@ bool QUndoStack::canUndo() const
}
/*!
+ \since 5.12
+ \property QUndoStack::canRedo
+ \brief whether this stack can redo.
+
+ This property indicates whether or not there is a command that can be
+ redone.
+
+ \sa canRedo(), index(), canUndo()
+*/
+
+/*!
Returns \c true if there is a command available for redo; otherwise returns \c false.
This function returns \c false if the stack is empty or if the top command
@@ -978,6 +1011,17 @@ bool QUndoStack::canRedo() const
}
/*!
+ \since 5.12
+ \property QUndoStack::undoText
+ \brief the undo text of the next command that is undone.
+
+ This property holds the text of the command which will be undone in the
+ next call to undo().
+
+ \sa undoText(), QUndoCommand::actionText(), redoText()
+*/
+
+/*!
Returns the text of the command which will be undone in the next call to undo().
\sa QUndoCommand::actionText(), redoText()
@@ -994,6 +1038,17 @@ QString QUndoStack::undoText() const
}
/*!
+ \since 5.12
+ \property QUndoStack::redoText
+ \brief the redo text of the next command that is redone.
+
+ This property holds the text of the command which will be redone in the
+ next call to redo().
+
+ \sa redoText(), QUndoCommand::actionText(), undoText()
+*/
+
+/*!
Returns the text of the command which will be redone in the next call to redo().
\sa QUndoCommand::actionText(), undoText()
diff --git a/src/widgets/util/qundostack.h b/src/widgets/util/qundostack.h
index 4be24eadab..b5716b2e9b 100644
--- a/src/widgets/util/qundostack.h
+++ b/src/widgets/util/qundostack.h
@@ -90,6 +90,11 @@ class Q_WIDGETS_EXPORT QUndoStack : public QObject
Q_DECLARE_PRIVATE(QUndoStack)
Q_PROPERTY(bool active READ isActive WRITE setActive)
Q_PROPERTY(int undoLimit READ undoLimit WRITE setUndoLimit)
+ Q_PROPERTY(bool canUndo READ canUndo NOTIFY canUndoChanged)
+ Q_PROPERTY(bool canRedo READ canRedo NOTIFY canRedoChanged)
+ Q_PROPERTY(QString undoText READ undoText NOTIFY undoTextChanged)
+ Q_PROPERTY(QString redoText READ redoText NOTIFY redoTextChanged)
+ Q_PROPERTY(bool clean READ isClean NOTIFY cleanChanged)
public:
explicit QUndoStack(QObject *parent = nullptr);
diff --git a/src/widgets/widgets.pro b/src/widgets/widgets.pro
index e028a691c8..e556cb8b10 100644
--- a/src/widgets/widgets.pro
+++ b/src/widgets/widgets.pro
@@ -6,6 +6,9 @@ CONFIG += $$MODULE_CONFIG
DEFINES += QT_NO_USING_NAMESPACE
msvc:equals(QT_ARCH, i386): QMAKE_LFLAGS += /BASE:0x65000000
+TRACEPOINT_PROVIDER = $$PWD/qtwidgets.tracepoints
+CONFIG += qt_tracepoints
+
QMAKE_DOCS = $$PWD/doc/qtwidgets.qdocconf
#platforms
diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp
index f059980c5c..4e1aa51b4b 100644
--- a/src/widgets/widgets/qabstractspinbox.cpp
+++ b/src/widgets/widgets/qabstractspinbox.cpp
@@ -91,7 +91,7 @@ QT_BEGIN_NAMESPACE
\li \l alignment: The alignment of the text in the QAbstractSpinBox.
\li \l wrapping: Whether the QAbstractSpinBox wraps from the
- minimum value to the maximum value and vica versa.
+ minimum value to the maximum value and vice versa.
\endlist
@@ -100,6 +100,16 @@ QT_BEGIN_NAMESPACE
integer value to signify how many steps were taken. E.g. Pressing
Qt::Key_Down will trigger a call to stepBy(-1).
+ When the user triggers a step whilst holding the Qt::ControlModifier,
+ QAbstractSpinBox steps by 10 instead of making a single step. This
+ step modifier affects wheel events, key events and interaction with
+ the spinbox buttons. Note that on macOS, Control corresponds to the
+ Command key.
+
+ Since Qt 5.12, QStyle::SH_SpinBox_StepModifier can be used to select
+ which Qt::KeyboardModifier increases the step rate. Qt::NoModifier
+ disables this feature.
+
QAbstractSpinBox also provide a virtual function stepEnabled() to
determine whether stepping up/down is allowed at any point. This
function returns a bitset of StepEnabled.
@@ -117,6 +127,13 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \enum QAbstractSpinBox::StepType
+
+ \value DefaultStepType
+ \value AdaptiveDecimalStepType
+*/
+
+/*!
\fn void QAbstractSpinBox::editingFinished()
This signal is emitted editing is finished. This happens when the
@@ -268,7 +285,7 @@ void QAbstractSpinBox::setSpecialValueText(const QString &specialValueText)
\brief whether the spin box is circular.
If wrapping is true stepping up from maximum() value will take you
- to the minimum() value and vica versa. Wrapping only make sense if
+ to the minimum() value and vice versa. Wrapping only make sense if
you have minimum() and maximum() values set.
\snippet code/src_gui_widgets_qabstractspinbox.cpp 0
@@ -640,7 +657,15 @@ void QAbstractSpinBox::stepBy(int steps)
e = AlwaysEmit;
}
if (!dontstep) {
- d->setValue(d->bound(d->value + (d->singleStep * steps), old, steps), e);
+ QVariant singleStep;
+ switch (d->stepType) {
+ case QAbstractSpinBox::StepType::AdaptiveDecimalStepType:
+ singleStep = d->calculateAdaptiveDecimalStep(steps);
+ break;
+ default:
+ singleStep = d->singleStep;
+ }
+ d->setValue(d->bound(d->value + (singleStep * steps), old, steps), e);
} else if (e == AlwaysEmit) {
d->emitSignals(e, old);
}
@@ -826,9 +851,13 @@ void QAbstractSpinBox::changeEvent(QEvent *event)
style()->styleHint(QStyle::SH_SpinBox_ClickAutoRepeatThreshold, 0, this);
if (d->edit)
d->edit->setFrame(!style()->styleHint(QStyle::SH_SpinBox_ButtonsInsideFrame, nullptr, this));
+ d->stepModifier = static_cast<Qt::KeyboardModifier>(style()->styleHint(QStyle::SH_SpinBox_StepModifier, nullptr, this));
d->reset();
d->updateEditFieldGeometry();
break;
+ case QEvent::LocaleChange:
+ d->updateEdit();
+ break;
case QEvent::EnabledChange:
if (!isEnabled()) {
d->reset();
@@ -1008,6 +1037,8 @@ void QAbstractSpinBox::keyPressEvent(QKeyEvent *event)
const bool up = (event->key() == Qt::Key_PageUp || event->key() == Qt::Key_Up);
if (!(stepEnabled() & (up ? StepUpEnabled : StepDownEnabled)))
return;
+ if (!isPgUpOrDown && (event->modifiers() & d->stepModifier))
+ steps *= 10;
if (!up)
steps *= -1;
if (style()->styleHint(QStyle::SH_SpinBox_AnimateButton, 0, this)) {
@@ -1134,11 +1165,24 @@ void QAbstractSpinBox::keyReleaseEvent(QKeyEvent *event)
void QAbstractSpinBox::wheelEvent(QWheelEvent *event)
{
Q_D(QAbstractSpinBox);
+#ifdef Q_OS_MACOS
+ // If the event comes from a real mouse wheel, rather than a track pad
+ // (Qt::MouseEventSynthesizedBySystem), the shift modifier changes the
+ // scroll orientation to horizontal.
+ // Convert horizontal events back to vertical whilst shift is held.
+ if ((event->modifiers() & Qt::ShiftModifier)
+ && event->source() == Qt::MouseEventNotSynthesized) {
+ d->wheelDeltaRemainder += event->angleDelta().x();
+ } else {
+ d->wheelDeltaRemainder += event->angleDelta().y();
+ }
+#else
d->wheelDeltaRemainder += event->angleDelta().y();
+#endif
const int steps = d->wheelDeltaRemainder / 120;
d->wheelDeltaRemainder -= steps * 120;
if (stepEnabled() & (steps > 0 ? StepUpEnabled : StepDownEnabled))
- stepBy(event->modifiers() & Qt::ControlModifier ? steps * 10 : steps);
+ stepBy(event->modifiers() & d->stepModifier ? steps * 10 : steps);
event->accept();
}
#endif
@@ -1238,18 +1282,19 @@ void QAbstractSpinBox::timerEvent(QTimerEvent *event)
}
if (doStep) {
+ const bool increaseStepRate = QGuiApplication::keyboardModifiers() & d->stepModifier;
const StepEnabled st = stepEnabled();
if (d->buttonState & Up) {
if (!(st & StepUpEnabled)) {
d->reset();
} else {
- stepBy(1);
+ stepBy(increaseStepRate ? 10 : 1);
}
} else if (d->buttonState & Down) {
if (!(st & StepDownEnabled)) {
d->reset();
} else {
- stepBy(-1);
+ stepBy(increaseStepRate ? -10 : -1);
}
}
return;
@@ -1377,8 +1422,9 @@ QAbstractSpinBoxPrivate::QAbstractSpinBoxPrivate()
cachedState(QValidator::Invalid), pendingEmit(false), readOnly(false), wrapping(false),
ignoreCursorPositionChanged(false), frame(true), accelerate(false), keyboardTracking(true),
cleared(false), ignoreUpdateEdit(false), correctionMode(QAbstractSpinBox::CorrectToPreviousValue),
- acceleration(0), hoverControl(QStyle::SC_None), buttonSymbols(QAbstractSpinBox::UpDownArrows), validator(0),
- showGroupSeparator(0), wheelDeltaRemainder(0)
+ stepModifier(Qt::ControlModifier), acceleration(0), hoverControl(QStyle::SC_None),
+ buttonSymbols(QAbstractSpinBox::UpDownArrows), validator(0), showGroupSeparator(0),
+ wheelDeltaRemainder(0)
{
}
@@ -1629,7 +1675,10 @@ void QAbstractSpinBoxPrivate::updateState(bool up, bool fromKeyboard /* = false
: QAbstractSpinBox::StepDownEnabled))) {
spinClickThresholdTimerId = q->startTimer(spinClickThresholdTimerInterval);
buttonState = (up ? Up : Down) | (fromKeyboard ? Keyboard : Mouse);
- q->stepBy(up ? 1 : -1);
+ int steps = up ? 1 : -1;
+ if (QGuiApplication::keyboardModifiers() & stepModifier)
+ steps *= 10;
+ q->stepBy(steps);
#ifndef QT_NO_ACCESSIBILITY
QAccessibleValueChangeEvent event(q, value);
QAccessible::updateAccessibility(&event);
@@ -1898,6 +1947,11 @@ void QAbstractSpinBoxPrivate::clearCache() const
cachedState = QValidator::Acceptable;
}
+QVariant QAbstractSpinBoxPrivate::calculateAdaptiveDecimalStep(int steps) const
+{
+ Q_UNUSED(steps)
+ return singleStep;
+}
// --- QSpinBoxValidator ---
diff --git a/src/widgets/widgets/qabstractspinbox.h b/src/widgets/widgets/qabstractspinbox.h
index 83bf83d779..87d46c7326 100644
--- a/src/widgets/widgets/qabstractspinbox.h
+++ b/src/widgets/widgets/qabstractspinbox.h
@@ -127,6 +127,13 @@ public:
virtual void fixup(QString &input) const;
virtual void stepBy(int steps);
+
+ enum StepType {
+ DefaultStepType,
+ AdaptiveDecimalStepType
+ };
+ Q_ENUM(StepType)
+
public Q_SLOTS:
void stepUp();
void stepDown();
diff --git a/src/widgets/widgets/qabstractspinbox_p.h b/src/widgets/widgets/qabstractspinbox_p.h
index 8f312fa900..fce88e43f4 100644
--- a/src/widgets/widgets/qabstractspinbox_p.h
+++ b/src/widgets/widgets/qabstractspinbox_p.h
@@ -122,6 +122,8 @@ public:
static int variantCompare(const QVariant &arg1, const QVariant &arg2);
static QVariant variantBound(const QVariant &min, const QVariant &value, const QVariant &max);
+ virtual QVariant calculateAdaptiveDecimalStep(int steps) const;
+
QLineEdit *edit;
QString prefix, suffix, specialValueText;
QVariant value, minimum, maximum, singleStep;
@@ -143,6 +145,8 @@ public:
uint cleared : 1;
uint ignoreUpdateEdit : 1;
QAbstractSpinBox::CorrectionMode correctionMode;
+ QAbstractSpinBox::StepType stepType = QAbstractSpinBox::StepType::DefaultStepType;
+ Qt::KeyboardModifier stepModifier = Qt::ControlModifier;
int acceleration;
QStyle::SubControl hoverControl;
QRect hoverRect;
diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp
index 04a44e1f37..e20a0892b4 100644
--- a/src/widgets/widgets/qcombobox.cpp
+++ b/src/widgets/widgets/qcombobox.cpp
@@ -3160,7 +3160,6 @@ void QComboBoxPrivate::showPopupFromMouseEvent(QMouseEvent *e)
#endif
// We've restricted the next couple of lines, because by not calling
// viewContainer(), we avoid creating the QComboBoxPrivateContainer.
- viewContainer()->blockMouseReleaseTimer.start(QApplication::doubleClickInterval());
viewContainer()->initialClickPosition = q->mapToGlobal(e->pos());
#ifdef QT_KEYPAD_NAVIGATION
}
@@ -3169,8 +3168,10 @@ void QComboBoxPrivate::showPopupFromMouseEvent(QMouseEvent *e)
// The code below ensures that regular mousepress and pick item still works
// If it was not called the viewContainer would ignore event since it didn't have
// a mousePressEvent first.
- if (viewContainer())
+ if (viewContainer()) {
+ viewContainer()->blockMouseReleaseTimer.start(QApplication::doubleClickInterval());
viewContainer()->maybeIgnoreMouseButtonRelease = false;
+ }
} else {
#ifdef QT_KEYPAD_NAVIGATION
if (QApplication::keypadNavigationEnabled() && sc == QStyle::SC_ComboBoxEditField && lineEdit) {
diff --git a/src/widgets/widgets/qdockarealayout.cpp b/src/widgets/widgets/qdockarealayout.cpp
index 75289e9d1f..54504d124b 100644
--- a/src/widgets/widgets/qdockarealayout.cpp
+++ b/src/widgets/widgets/qdockarealayout.cpp
@@ -2629,8 +2629,9 @@ void QDockAreaLayout::removePlaceHolder(const QString &name)
QList<int> index = indexOfPlaceHolder(name);
if (!index.isEmpty())
remove(index);
- foreach (QDockWidgetGroupWindow *dwgw, mainWindow->findChildren<QDockWidgetGroupWindow *>(
- QString(), Qt::FindDirectChildrenOnly)) {
+ const auto groups =
+ mainWindow->findChildren<QDockWidgetGroupWindow *>(QString(), Qt::FindDirectChildrenOnly);
+ for (QDockWidgetGroupWindow *dwgw : groups) {
index = dwgw->layoutInfo()->indexOfPlaceHolder(name);
if (!index.isEmpty()) {
dwgw->layoutInfo()->remove(index);
@@ -3065,8 +3066,9 @@ QRect QDockAreaLayout::constrainedRect(QRect rect, QWidget* widget)
bool QDockAreaLayout::restoreDockWidget(QDockWidget *dockWidget)
{
QDockAreaLayoutItem *item = 0;
- foreach (QDockWidgetGroupWindow *dwgw, mainWindow->findChildren<QDockWidgetGroupWindow *>(
- QString(), Qt::FindDirectChildrenOnly)) {
+ const auto groups =
+ mainWindow->findChildren<QDockWidgetGroupWindow *>(QString(), Qt::FindDirectChildrenOnly);
+ for (QDockWidgetGroupWindow *dwgw : groups) {
QList<int> index = dwgw->layoutInfo()->indexOfPlaceHolder(dockWidget->objectName());
if (!index.isEmpty()) {
dockWidget->setParent(dwgw);
@@ -3175,7 +3177,7 @@ void QDockAreaLayout::resizeDocks(const QList<QDockWidget *> &docks,
if (!info->tabbed && info->o == o) {
info->item_list[path.constLast()].size = size;
int totalSize = 0;
- foreach (const QDockAreaLayoutItem &item, info->item_list) {
+ for (const QDockAreaLayoutItem &item : qAsConst(info->item_list)) {
if (!item.skip()) {
if (totalSize != 0)
totalSize += sep;
@@ -3293,6 +3295,8 @@ int QDockAreaLayout::separatorMove(const QList<int> &separator, const QPoint &or
delta = pick(o, dest - origin);
delta = separatorMoveHelper(list, sep_index, delta, sep);
+ fallbackToSizeHints = false;
+
if (index == QInternal::LeftDock || index == QInternal::RightDock)
setGrid(0, &list);
else
diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp
index 84cb78a474..6c871aae2c 100644
--- a/src/widgets/widgets/qdockwidget.cpp
+++ b/src/widgets/widgets/qdockwidget.cpp
@@ -45,6 +45,7 @@
#include <qdrawutil.h>
#include <qevent.h>
#include <qfontmetrics.h>
+#include <qproxystyle.h>
#include <qwindow.h>
#include <qscreen.h>
#include <qmainwindow.h>
@@ -166,6 +167,10 @@ static inline bool isWindowsStyle(const QStyle *style)
if (style->inherits("QStyleSheetStyle"))
effectiveStyle = static_cast<const QStyleSheetStyle *>(style)->baseStyle();
#endif
+#if !defined(QT_NO_STYLE_PROXY)
+ if (style->inherits("QProxyStyle"))
+ effectiveStyle = static_cast<const QProxyStyle *>(style)->baseStyle();
+#endif
return effectiveStyle->inherits("QWindowsStyle");
}
@@ -691,7 +696,6 @@ void QDockWidget::initStyleOption(QStyleOptionDockWidget *option) const
// If we are in a floating tab, init from the parent because the attributes and the geometry
// of the title bar should be taken from the floating window.
option->initFrom(floatingTab && !isFloating() ? parentWidget() : this);
- option->fontMetrics = QFontMetrics(d->font);
option->rect = dwlayout->titleArea();
option->title = d->fixedWindowTitle;
option->closable = hasFeature(this, QDockWidget::DockWidgetClosable);
@@ -1468,6 +1472,7 @@ void QDockWidget::closeEvent(QCloseEvent *event)
void QDockWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
+ Q_D(QDockWidget);
QDockWidgetLayout *layout
= qobject_cast<QDockWidgetLayout*>(this->layout());
@@ -1488,7 +1493,11 @@ void QDockWidget::paintEvent(QPaintEvent *event)
// the title may wish to extend out to all sides (eg. Vista style)
QStyleOptionDockWidget titleOpt;
initStyleOption(&titleOpt);
- p.setFont(d_func()->font);
+ if (font() == QApplication::font("QDockWidget")) {
+ titleOpt.fontMetrics = QFontMetrics(d->font);
+ p.setFont(d->font);
+ }
+
p.drawControl(QStyle::CE_DockWidgetTitle, titleOpt);
}
}
diff --git a/src/widgets/widgets/qlabel.cpp b/src/widgets/widgets/qlabel.cpp
index 5d09e14073..60f88df9af 100644
--- a/src/widgets/widgets/qlabel.cpp
+++ b/src/widgets/widgets/qlabel.cpp
@@ -288,7 +288,7 @@ void QLabel::setText(const QString &text)
return;
QWidgetTextControl *oldControl = d->control;
- d->control = 0;
+ d->control = nullptr;
d->clearContents();
d->text = text;
@@ -303,7 +303,7 @@ void QLabel::setText(const QString &text)
d->ensureTextControl();
} else {
delete d->control;
- d->control = 0;
+ d->control = nullptr;
}
if (d->isRichText) {
@@ -714,7 +714,7 @@ void QLabel::setTextInteractionFlags(Qt::TextInteractionFlags flags)
d->ensureTextControl();
} else {
delete d->control;
- d->control = 0;
+ d->control = nullptr;
}
if (d->control)
@@ -1021,13 +1021,13 @@ void QLabel::paintEvent(QPaintEvent *)
QStyleOption opt;
opt.initFrom(this);
#ifndef QT_NO_STYLE_STYLESHEET
- if (QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(style)) {
+ if (QStyleSheetStyle* cssStyle = qt_styleSheet(style))
cssStyle->styleSheetPalette(this, &opt, &opt.palette);
- }
#endif
if (d->control) {
#ifndef QT_NO_SHORTCUT
- const bool underline = (bool)style->styleHint(QStyle::SH_UnderlineShortcut, 0, this, 0);
+ const bool underline = static_cast<bool>(style->styleHint(QStyle::SH_UnderlineShortcut,
+ nullptr, this, nullptr));
if (d->shortcutId != 0
&& underline != d->shortcutCursor.charFormat().fontUnderline()) {
QTextCharFormat fmt;
@@ -1294,20 +1294,20 @@ void QLabel::setMovie(QMovie *movie)
void QLabelPrivate::clearContents()
{
delete control;
- control = 0;
+ control = nullptr;
isTextLabel = false;
hasShortcut = false;
#ifndef QT_NO_PICTURE
delete picture;
- picture = 0;
+ picture = nullptr;
#endif
delete scaledpixmap;
- scaledpixmap = 0;
+ scaledpixmap = nullptr;
delete cachedimage;
- cachedimage = 0;
+ cachedimage = nullptr;
delete pixmap;
- pixmap = 0;
+ pixmap = nullptr;
text.clear();
Q_Q(QLabel);
@@ -1321,7 +1321,7 @@ void QLabelPrivate::clearContents()
QObject::disconnect(movie, SIGNAL(resized(QSize)), q, SLOT(_q_movieResized(QSize)));
QObject::disconnect(movie, SIGNAL(updated(QRect)), q, SLOT(_q_movieUpdated(QRect)));
}
- movie = 0;
+ movie = nullptr;
#endif
#ifndef QT_NO_CURSOR
if (onAnchor) {
@@ -1428,9 +1428,9 @@ void QLabel::setScaledContents(bool enable)
d->scaledcontents = enable;
if (!enable) {
delete d->scaledpixmap;
- d->scaledpixmap = 0;
+ d->scaledpixmap = nullptr;
delete d->cachedimage;
- d->cachedimage = 0;
+ d->cachedimage = nullptr;
}
update(contentsRect());
}
@@ -1629,7 +1629,7 @@ QMenu *QLabelPrivate::createStandardContextMenu(const QPoint &pos)
}
if (linkToCopy.isEmpty() && !control)
- return 0;
+ return nullptr;
return control->createStandardContextMenu(p, q_func());
}
diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp
index ca6aacc16c..242a4405ca 100644
--- a/src/widgets/widgets/qlineedit.cpp
+++ b/src/widgets/widgets/qlineedit.cpp
@@ -437,8 +437,6 @@ bool QLineEdit::hasFrame() const
#if QT_CONFIG(action)
/*!
- \overload
-
Adds the \a action to the list of actions at the \a position.
\since 5.2
@@ -497,6 +495,8 @@ void QLineEdit::setClearButtonEnabled(bool enable)
d->removeAction(clearAction);
delete clearAction;
}
+#else
+ Q_UNUSED(enable);
#endif // QT_CONFIG(action)
}
@@ -680,7 +680,8 @@ QSize QLineEdit::sizeHint() const
Q_D(const QLineEdit);
ensurePolished();
QFontMetrics fm(font());
- int h = qMax(fm.height(), 14) + 2*d->verticalMargin
+ const int iconSize = style()->pixelMetric(QStyle::PM_SmallIconSize, 0, this);
+ int h = qMax(fm.height(), iconSize - 2) + 2*d->verticalMargin
+ d->topTextMargin + d->bottomTextMargin
+ d->topmargin + d->bottommargin;
int w = fm.horizontalAdvance(QLatin1Char('x')) * 17 + 2*d->horizontalMargin
@@ -1676,6 +1677,21 @@ void QLineEdit::mouseDoubleClickEvent(QMouseEvent* e)
*/
/*!
+ \fn void QLineEdit::inputRejected()
+
+ This signal is emitted when the user presses a key that is not
+ considered to be acceptable input. For example, if a key press
+ results in a validator's validate() call to return Invalid.
+ Another case is when trying to enter in more characters beyond the
+ maximum length of the line edit.
+
+ Note: This signal will still be emitted in a case where part of
+ the text is accepted but not all of it is. For example, if there
+ is a maximum length set and the clipboard text is longer than the
+ maximum length when it is pasted.
+*/
+
+/*!
Converts the given key press \a event into a line edit action.
If Return or Enter is pressed and the current text is valid (or
@@ -1946,8 +1962,7 @@ void QLineEdit::paintEvent(QPaintEvent *)
if (!d->placeholderText.isEmpty()) {
const Qt::LayoutDirection layoutDir = d->placeholderText.isRightToLeft() ? Qt::RightToLeft : Qt::LeftToRight;
const Qt::Alignment alignPhText = QStyle::visualAlignment(layoutDir, QFlag(d->alignment));
- QColor col = pal.text().color();
- col.setAlpha(128);
+ const QColor col = pal.placeholderText().color();
QPen oldpen = p.pen();
p.setPen(col);
Qt::LayoutDirection oldLayoutDir = p.layoutDirection();
@@ -2002,7 +2017,7 @@ void QLineEdit::paintEvent(QPaintEvent *)
// draw text, selections and cursors
#ifndef QT_NO_STYLE_STYLESHEET
- if (QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(style())) {
+ if (QStyleSheetStyle* cssStyle = qt_styleSheet(style())) {
cssStyle->styleSheetPalette(this, &panel, &pal);
}
#endif
diff --git a/src/widgets/widgets/qlineedit.h b/src/widgets/widgets/qlineedit.h
index 6c70a8f44a..de82927f74 100644
--- a/src/widgets/widgets/qlineedit.h
+++ b/src/widgets/widgets/qlineedit.h
@@ -207,6 +207,7 @@ Q_SIGNALS:
void returnPressed();
void editingFinished();
void selectionChanged();
+ void inputRejected();
protected:
void mousePressEvent(QMouseEvent *) override;
diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp
index cccb44c4ef..df8d534afa 100644
--- a/src/widgets/widgets/qlineedit_p.cpp
+++ b/src/widgets/widgets/qlineedit_p.cpp
@@ -218,6 +218,7 @@ void QLineEditPrivate::init(const QString& txt)
QObject::connect(control, SIGNAL(updateNeeded(QRect)),
q, SLOT(_q_updateNeeded(QRect)));
+ QObject::connect(control, SIGNAL(inputRejected()), q, SIGNAL(inputRejected()));
QStyleOptionFrame opt;
q->initStyleOption(&opt);
@@ -350,11 +351,9 @@ void QLineEditIconButton::paintEvent(QPaintEvent *)
QWindow *window = nullptr;
if (const QWidget *nativeParent = nativeParentWidget())
window = nativeParent->windowHandle();
- // Note isDown should really use the active state but in most styles
- // this has no proper feedback
QIcon::Mode state = QIcon::Disabled;
if (isEnabled())
- state = isDown() ? QIcon::Selected : QIcon::Normal;
+ state = isDown() ? QIcon::Active : QIcon::Normal;
const QLineEditPrivate *lep = lineEditPrivate();
const int iconWidth = lep ? lep->sideWidgetParameters().iconSize : 16;
const QSize iconSize(iconWidth, iconWidth);
@@ -444,7 +443,7 @@ QLineEditPrivate::SideWidgetParameters QLineEditPrivate::sideWidgetParameters()
{
Q_Q(const QLineEdit);
SideWidgetParameters result;
- result.iconSize = q->height() < 34 ? 16 : 32;
+ result.iconSize = q->style()->pixelMetric(QStyle::PM_SmallIconSize, 0, q);
result.margin = result.iconSize / 4;
result.widgetWidth = result.iconSize + 6;
result.widgetHeight = result.iconSize + 2;
@@ -468,6 +467,8 @@ void QLineEditPrivate::setClearButtonEnabled(bool enabled)
break;
}
}
+#else
+ Q_UNUSED(enabled);
#endif
}
@@ -485,6 +486,8 @@ void QLineEditPrivate::positionSideWidgets()
#if QT_CONFIG(action)
if (e.action->isVisible())
widgetGeometry.moveLeft(widgetGeometry.left() + delta);
+#else
+ Q_UNUSED(delta);
#endif
}
widgetGeometry.moveLeft(contentRect.width() - p.widgetWidth - p.margin);
@@ -598,6 +601,8 @@ void QLineEditPrivate::removeAction(QAction *action)
if (!hasSideWidgets()) // Last widget, remove connection
QObject::disconnect(q, SIGNAL(textChanged(QString)), q, SLOT(_q_textChanged(QString)));
q->update();
+#else
+ Q_UNUSED(action);
#endif // QT_CONFIG(action)
}
diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp
index 2014bdabf3..411b482c11 100644
--- a/src/widgets/widgets/qmainwindow.cpp
+++ b/src/widgets/widgets/qmainwindow.cpp
@@ -249,14 +249,7 @@ void QMainWindowPrivate::init()
An example of how to create menus follows:
- \code
- void MainWindow::createMenus()
- {
- fileMenu = menuBar()->addMenu(tr("&File"));
- fileMenu->addAction(newAct);
- fileMenu->addAction(openAct);
- fileMenu->addAction(saveAct);
- \endcode
+ \snippet code/src_widgets_widgets_qmainwindow.cpp 0
The \c createPopupMenu() function creates popup menus when the
main window receives context menu events. The default
@@ -283,12 +276,7 @@ void QMainWindowPrivate::init()
An example of toolbar creation follows:
- \code
- void MainWindow::createToolBars()
- {
- fileToolBar = addToolBar(tr("File"));
- fileToolBar->addAction(newAct);
- \endcode
+ \snippet code/src_widgets_widgets_qmainwindow.cpp 1
\section2 Creating Dock Widgets
@@ -1227,9 +1215,8 @@ Qt::DockWidgetArea QMainWindow::dockWidgetArea(QDockWidget *dockwidget) const
to the relative weight of the sizes.
Example:
- \code
- resizeDocks({blueWidget, yellowWidget}, {20 , 40}, Qt::Horizontal);
- \endcode
+ \snippet code/src_widgets_widgets_qmainwindow.cpp 2
+
If the blue and the yellow widget are nested on the same level they will be
resized such that the yellowWidget is twice as big as the blueWidget
@@ -1312,8 +1299,12 @@ bool QMainWindow::restoreState(const QByteArray &state, int version)
bool QMainWindow::event(QEvent *event)
{
Q_D(QMainWindow);
+
+#if QT_CONFIG(dockwidget)
if (d->layout && d->layout->windowEvent(event))
return true;
+#endif
+
switch (event->type()) {
#if QT_CONFIG(toolbar)
diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp
index 43c22910f9..053bfbf024 100644
--- a/src/widgets/widgets/qmainwindowlayout.cpp
+++ b/src/widgets/widgets/qmainwindowlayout.cpp
@@ -426,7 +426,8 @@ void QDockWidgetGroupWindow::destroyOrHideIfEmpty()
}
// Make sure to reparent the possibly floating or hidden QDockWidgets to the parent
- foreach (QDockWidget *dw, findChildren<QDockWidget *>(QString(), Qt::FindDirectChildrenOnly)) {
+ const auto dockWidgets = findChildren<QDockWidget *>(QString(), Qt::FindDirectChildrenOnly);
+ for (QDockWidget *dw : dockWidgets) {
bool wasFloating = dw->isFloating();
bool wasHidden = dw->isHidden();
dw->setParent(parentWidget());
@@ -445,7 +446,8 @@ void QDockWidgetGroupWindow::destroyOrHideIfEmpty()
dw->show();
}
#if QT_CONFIG(tabbar)
- foreach (QTabBar *tb, findChildren<QTabBar *>(QString(), Qt::FindDirectChildrenOnly))
+ const auto tabBars = findChildren<QTabBar *>(QString(), Qt::FindDirectChildrenOnly);
+ for (QTabBar *tb : tabBars)
tb->setParent(parentWidget());
#endif
deleteLater();
@@ -1037,10 +1039,10 @@ void QMainWindowLayoutState::saveState(QDataStream &stream) const
#if QT_CONFIG(dockwidget)
dockAreaLayout.saveState(stream);
#if QT_CONFIG(tabbar)
- QList<QDockWidgetGroupWindow *> floatingTabs =
+ const QList<QDockWidgetGroupWindow *> floatingTabs =
mainWindow->findChildren<QDockWidgetGroupWindow *>(QString(), Qt::FindDirectChildrenOnly);
- foreach (QDockWidgetGroupWindow *floating, floatingTabs) {
+ for (QDockWidgetGroupWindow *floating : floatingTabs) {
if (floating->layoutInfo()->isEmpty())
continue;
stream << uchar(QDockAreaLayout::FloatingDockWidgetTabMarker) << floating->geometry();
@@ -1528,9 +1530,9 @@ void QMainWindowLayout::setDocumentMode(bool enabled)
_documentMode = enabled;
// Update the document mode for all tab bars
- foreach (QTabBar *bar, usedTabBars)
+ for (QTabBar *bar : qAsConst(usedTabBars))
bar->setDocumentMode(_documentMode);
- foreach (QTabBar *bar, unusedTabBars)
+ for (QTabBar *bar : qAsConst(unusedTabBars))
bar->setDocumentMode(_documentMode);
}
#endif // QT_CONFIG(tabbar)
@@ -1809,8 +1811,9 @@ QDockAreaLayoutInfo *QMainWindowLayout::dockInfo(QWidget *widget)
QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(widget);
if (info)
return info;
- foreach (QDockWidgetGroupWindow *dwgw,
- parent()->findChildren<QDockWidgetGroupWindow*>(QString(), Qt::FindDirectChildrenOnly)) {
+ const auto groups =
+ parent()->findChildren<QDockWidgetGroupWindow*>(QString(), Qt::FindDirectChildrenOnly);
+ for (QDockWidgetGroupWindow *dwgw : groups) {
info = dwgw->layoutInfo()->info(widget);
if (info)
return info;
@@ -2077,8 +2080,9 @@ bool QMainWindowLayout::plug(QLayoutItem *widgetItem)
layoutState.remove(previousPath);
previousPath = currentHoveredFloat->layoutInfo()->indexOf(widget);
// Let's remove the widget from any possible group window
- foreach (QDockWidgetGroupWindow *dwgw,
- parent()->findChildren<QDockWidgetGroupWindow*>(QString(), Qt::FindDirectChildrenOnly)) {
+ const auto groups =
+ parent()->findChildren<QDockWidgetGroupWindow*>(QString(), Qt::FindDirectChildrenOnly);
+ for (QDockWidgetGroupWindow *dwgw : groups) {
if (dwgw == currentHoveredFloat)
continue;
QList<int> path = dwgw->layoutInfo()->indexOf(widget);
@@ -2106,8 +2110,9 @@ bool QMainWindowLayout::plug(QLayoutItem *widgetItem)
#if QT_CONFIG(dockwidget)
// Let's remove the widget from any possible group window
- foreach (QDockWidgetGroupWindow *dwgw,
- parent()->findChildren<QDockWidgetGroupWindow*>(QString(), Qt::FindDirectChildrenOnly)) {
+ const auto groups =
+ parent()->findChildren<QDockWidgetGroupWindow*>(QString(), Qt::FindDirectChildrenOnly);
+ for (QDockWidgetGroupWindow *dwgw : groups) {
QList<int> path = dwgw->layoutInfo()->indexOf(widget);
if (!path.isEmpty())
dwgw->layoutInfo()->remove(path);
@@ -2249,7 +2254,8 @@ void QMainWindowLayout::animationFinished(QWidget *widget)
#if QT_CONFIG(dockwidget)
parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());
#if QT_CONFIG(tabbar)
- foreach (QTabBar *tab_bar, usedTabBars)
+ const auto usedTabBarsCopy = usedTabBars; // list potentially modified by animations
+ for (QTabBar *tab_bar : usedTabBarsCopy)
tab_bar->show();
#endif // QT_CONFIG(tabbar)
#endif // QT_CONFIG(dockwidget)
@@ -2533,7 +2539,8 @@ void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos)
// Check if we are over another floating dock widget
QVarLengthArray<QWidget *, 10> candidates;
- foreach (QObject *c, parentWidget()->children()) {
+ const auto siblings = parentWidget()->children();
+ for (QObject *c : siblings) {
QWidget *w = qobject_cast<QWidget*>(c);
if (!w)
continue;
@@ -2543,7 +2550,8 @@ void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos)
candidates << w;
if (QDockWidgetGroupWindow *group = qobject_cast<QDockWidgetGroupWindow *>(w)) {
// Sometimes, there are floating QDockWidget that have a QDockWidgetGroupWindow as a parent.
- foreach (QObject *c, group->children()) {
+ const auto groupChildren = group->children();
+ for (QObject *c : groupChildren) {
if (QDockWidget *dw = qobject_cast<QDockWidget*>(c)) {
if (dw != widget && dw->isFloating() && dw->isVisible() && !dw->isMinimized())
candidates << dw;
@@ -2671,14 +2679,14 @@ void QMainWindowLayout::applyState(QMainWindowLayoutState &newState, bool animat
{
#if QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget)
QSet<QTabBar*> used = newState.dockAreaLayout.usedTabBars();
- foreach (QDockWidgetGroupWindow *dwgw,
- parent()->findChildren<QDockWidgetGroupWindow*>(QString(), Qt::FindDirectChildrenOnly)) {
+ const auto groups =
+ parent()->findChildren<QDockWidgetGroupWindow*>(QString(), Qt::FindDirectChildrenOnly);
+ for (QDockWidgetGroupWindow *dwgw : groups)
used += dwgw->layoutInfo()->usedTabBars();
- }
- QSet<QTabBar*> retired = usedTabBars - used;
+ const QSet<QTabBar*> retired = usedTabBars - used;
usedTabBars = used;
- foreach (QTabBar *tab_bar, retired) {
+ for (QTabBar *tab_bar : retired) {
tab_bar->hide();
while (tab_bar->count() > 0)
tab_bar->removeTab(0);
@@ -2686,10 +2694,10 @@ void QMainWindowLayout::applyState(QMainWindowLayoutState &newState, bool animat
}
if (sep == 1) {
- QSet<QWidget*> usedSeps = newState.dockAreaLayout.usedSeparatorWidgets();
- QSet<QWidget*> retiredSeps = usedSeparatorWidgets - usedSeps;
+ const QSet<QWidget*> usedSeps = newState.dockAreaLayout.usedSeparatorWidgets();
+ const QSet<QWidget*> retiredSeps = usedSeparatorWidgets - usedSeps;
usedSeparatorWidgets = usedSeps;
- foreach (QWidget *sepWidget, retiredSeps) {
+ for (QWidget *sepWidget : retiredSeps) {
unusedSeparatorWidgets.append(sepWidget);
}
}
@@ -2731,7 +2739,7 @@ bool QMainWindowLayout::restoreState(QDataStream &stream)
#if QT_CONFIG(dockwidget)
if (parentWidget()->isVisible()) {
#if QT_CONFIG(tabbar)
- foreach (QTabBar *tab_bar, usedTabBars)
+ for (QTabBar *tab_bar : qAsConst(usedTabBars))
tab_bar->show();
#endif
diff --git a/src/widgets/widgets/qmainwindowlayout_p.h b/src/widgets/widgets/qmainwindowlayout_p.h
index 4ccfb1786e..72cbec2350 100644
--- a/src/widgets/widgets/qmainwindowlayout_p.h
+++ b/src/widgets/widgets/qmainwindowlayout_p.h
@@ -92,6 +92,7 @@ public:
QPoint hoverPos;
#if QT_CONFIG(dockwidget)
+
#if QT_CONFIG(cursor)
QCursor separatorCursor(const QList<int> &path);
void adjustCursor(const QPoint &pos);
@@ -108,13 +109,15 @@ public:
bool startSeparatorMove(const QPoint &pos);
bool separatorMove(const QPoint &pos);
bool endSeparatorMove(const QPoint &pos);
+ bool windowEvent(QEvent *e);
#endif // QT_CONFIG(dockwidget)
- bool windowEvent(QEvent *e);
};
-#if QT_CONFIG(dockwidget) && QT_CONFIG(cursor)
+#if QT_CONFIG(dockwidget)
+
+#if QT_CONFIG(cursor)
template <typename Layout>
QCursor QMainWindowLayoutSeparatorHelper<Layout>::separatorCursor(const QList<int> &path)
{
@@ -187,14 +190,13 @@ void QMainWindowLayoutSeparatorHelper<Layout>::adjustCursor(const QPoint &pos)
}
}
}
-#endif // QT_CONFIG(cursor) && QT_CONFIG(dockwidget)
+#endif // QT_CONFIG(cursor)
template <typename Layout>
bool QMainWindowLayoutSeparatorHelper<Layout>::windowEvent(QEvent *event)
{
QWidget *w = window();
switch (event->type()) {
-#if QT_CONFIG(dockwidget)
case QEvent::Paint: {
QPainter p(w);
QRegion r = static_cast<QPaintEvent *>(event)->region();
@@ -290,14 +292,12 @@ bool QMainWindowLayoutSeparatorHelper<Layout>::windowEvent(QEvent *event)
return true;
}
break;
-#endif // QT_CONFIG(dockwidget)
default:
break;
}
return false;
}
-#if QT_CONFIG(dockwidget)
template <typename Layout>
bool QMainWindowLayoutSeparatorHelper<Layout>::startSeparatorMove(const QPoint &pos)
{
diff --git a/src/widgets/widgets/qmdiarea.cpp b/src/widgets/widgets/qmdiarea.cpp
index 45c01dec80..f32cd26478 100644
--- a/src/widgets/widgets/qmdiarea.cpp
+++ b/src/widgets/widgets/qmdiarea.cpp
@@ -471,8 +471,8 @@ QVector<QRect> MinOverlapPlacer::getCandidatePlacements(const QSize &size, const
ylist.erase(std::unique(ylist.begin(), ylist.end()), ylist.end());
result.reserve(ylist.size() * xlist.size());
- foreach (int y, ylist)
- foreach (int x, xlist)
+ for (int y : qAsConst(ylist))
+ for (int x : qAsConst(xlist))
result << QRect(QPoint(x, y), size);
return result;
}
@@ -954,7 +954,7 @@ void QMdiAreaPrivate::rearrange(Rearranger *rearranger)
}
}
- if (active && rearranger->type() == Rearranger::RegularTiler) {
+ if (active && rearranger->type() == Rearranger::RegularTiler && !tileCalledFromResizeEvent) {
// Move active window in front if necessary. That's the case if we
// have any windows with staysOnTopHint set.
int indexToActive = widgets.indexOf((QWidget *)active);
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index 363647aee0..c79e88f094 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -1741,8 +1741,6 @@ QMenu::~QMenu()
}
/*!
- \overload
-
This convenience function creates a new action with \a text.
The function adds the newly created action to the menu's
list of actions, and returns it.
@@ -2433,7 +2431,7 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
atAction = d->defaultAction;
// TODO: This works for first level menus, not yet sub menus
} else {
- foreach (QAction *action, d->actions)
+ for (QAction *action : qAsConst(d->actions))
if (action->isEnabled()) {
atAction = action;
break;
diff --git a/src/widgets/widgets/qmenu.h b/src/widgets/widgets/qmenu.h
index 86d927e919..628f818b5e 100644
--- a/src/widgets/widgets/qmenu.h
+++ b/src/widgets/widgets/qmenu.h
@@ -46,7 +46,7 @@
#include <QtGui/qicon.h>
#include <QtWidgets/qaction.h>
-#ifdef Q_OS_OSX
+#if defined(Q_OS_MACOS) || defined(Q_CLANG_QDOC)
Q_FORWARD_DECLARE_OBJC_CLASS(NSMenu);
#endif
@@ -81,7 +81,7 @@ public:
QAction *addAction(const QString &text, const QObject *receiver, const char* member, const QKeySequence &shortcut = 0);
QAction *addAction(const QIcon &icon, const QString &text, const QObject *receiver, const char* member, const QKeySequence &shortcut = 0);
-#ifdef Q_QDOC
+#ifdef Q_CLANG_QDOC
template<typename PointerToMemberFunction>
QAction *addAction(const QString &text, const QObject *receiver, PointerToMemberFunction method, const QKeySequence &shortcut = 0);
template<typename Functor>
@@ -151,7 +151,7 @@ public:
connect(result, &QAction::triggered, std::move(slot));
return result;
}
-#endif // !Q_QDOC
+#endif // !Q_CLANG_QDOC
QAction *addMenu(QMenu *menu);
QMenu *addMenu(const QString &title);
@@ -211,7 +211,7 @@ public:
QPlatformMenu *platformMenu();
void setPlatformMenu(QPlatformMenu *platformMenu);
-#ifdef Q_OS_OSX
+#if defined(Q_OS_MACOS) || defined(Q_CLANG_QDOC)
NSMenu* toNSMenu();
void setAsDockMenu();
#endif
diff --git a/src/widgets/widgets/qmenu_mac.mm b/src/widgets/widgets/qmenu_mac.mm
index 0d680fb4dc..0872da803d 100644
--- a/src/widgets/widgets/qmenu_mac.mm
+++ b/src/widgets/widgets/qmenu_mac.mm
@@ -73,6 +73,7 @@ inline QPlatformNativeInterface::NativeResourceForIntegrationFunction resolvePla
/*!
+ \fn NSMenu *QMenu::toNSMenu()
\since 5.2
Returns the native NSMenu for this menu. Available on \macos only.
@@ -94,6 +95,7 @@ NSMenu *QMenu::toNSMenu()
/*!
+ \fn void QMenu::setAsDockMenu()
\since 5.2
Set this menu to be the dock menu available by option-clicking
@@ -149,6 +151,7 @@ void QMenuPrivate::moveWidgetToPlatformItem(QWidget *widget, QPlatformMenuItem*
#if QT_CONFIG(menubar)
/*!
+ \fn NSMenu *QMenuBar::toNSMenu()
\since 5.2
Returns the native NSMenu for this menu bar. Available on \macos only.
diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp
index 6df53dc4e4..ce74a4c2ff 100644
--- a/src/widgets/widgets/qmenubar.cpp
+++ b/src/widgets/widgets/qmenubar.cpp
@@ -749,8 +749,6 @@ QMenuBar::~QMenuBar()
}
/*!
- \overload
-
This convenience function creates a new action with \a text.
The function adds the newly created action to the menu's
list of actions, and returns it.
diff --git a/src/widgets/widgets/qmenubar.h b/src/widgets/widgets/qmenubar.h
index 2f071e7e3b..cf6663f94a 100644
--- a/src/widgets/widgets/qmenubar.h
+++ b/src/widgets/widgets/qmenubar.h
@@ -67,7 +67,7 @@ public:
QAction *addAction(const QString &text);
QAction *addAction(const QString &text, const QObject *receiver, const char* member);
-#ifdef Q_QDOC
+#ifdef Q_CLANG_QDOC
template<typename Obj, typename PointerToMemberFunctionOrFunctor>
QAction *addAction(const QString &text, const Obj *receiver, PointerToMemberFunctionOrFunctor method);
template<typename Functor>
@@ -91,7 +91,7 @@ public:
connect(result, &QAction::triggered, std::move(slot));
return result;
}
-#endif // !Q_QDOC
+#endif // !Q_CLANG_QDOC
QAction *addMenu(QMenu *menu);
QMenu *addMenu(const QString &title);
@@ -121,7 +121,7 @@ public:
void setCornerWidget(QWidget *w, Qt::Corner corner = Qt::TopRightCorner);
QWidget *cornerWidget(Qt::Corner corner = Qt::TopRightCorner) const;
-#ifdef Q_OS_OSX
+#if defined(Q_OS_MACOS) || defined(Q_CLANG_QDOC)
NSMenu* toNSMenu();
#endif
diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp
index a4c463fb5b..d6f6a364a8 100644
--- a/src/widgets/widgets/qplaintextedit.cpp
+++ b/src/widgets/widgets/qplaintextedit.cpp
@@ -48,6 +48,7 @@
#include <qdrag.h>
#endif
#include <qclipboard.h>
+#include <qmath.h>
#if QT_CONFIG(menu)
#include <qmenu.h>
#endif
@@ -293,6 +294,7 @@ void QPlainTextDocumentLayout::documentChanged(int from, int charsRemoved, int c
QTextBlock changeStartBlock = doc->findBlock(from);
QTextBlock changeEndBlock = doc->findBlock(qMax(0, from + charsChanged - 1));
+ bool blockVisibilityChanged = false;
if (changeStartBlock == changeEndBlock && newBlockCount == d->blockCount) {
QTextBlock block = changeStartBlock;
@@ -310,14 +312,18 @@ void QPlainTextDocumentLayout::documentChanged(int from, int charsRemoved, int c
QTextBlock block = changeStartBlock;
do {
block.clearLayout();
+ const int lineCount = block.isVisible() ? 1 : 0;
+ if (block.lineCount() != lineCount) {
+ blockVisibilityChanged = true;
+ block.setLineCount(lineCount);
+ }
if (block == changeEndBlock)
break;
block = block.next();
} while(block.isValid());
}
- if (newBlockCount != d->blockCount) {
-
+ if (newBlockCount != d->blockCount || blockVisibilityChanged) {
int changeEnd = changeEndBlock.blockNumber();
int blockDiff = newBlockCount - d->blockCount;
int oldChangeEnd = changeEnd - blockDiff;
@@ -382,6 +388,8 @@ void QPlainTextDocumentLayout::layoutBlock(const QTextBlock &block)
line.setLineWidth(availableWidth);
line.setPosition(QPointF(margin, height));
height += line.height();
+ if (line.leading() < 0)
+ height += qCeil(line.leading());
blockMaximumWidth = qMax(blockMaximumWidth, line.naturalTextWidth() + 2*margin);
}
tl->endLayout();
@@ -1927,8 +1935,7 @@ void QPlainTextEdit::paintEvent(QPaintEvent *e)
painter.setClipRect(er);
if (d->placeholderVisible) {
- QColor col = d->control->palette().text().color();
- col.setAlpha(128);
+ const QColor col = d->control->palette().placeholderText().color();
painter.setPen(col);
painter.setClipRect(e->rect());
const int margin = int(document()->documentMargin());
@@ -2336,8 +2343,6 @@ void QPlainTextEdit::wheelEvent(QWheelEvent *e)
#endif
/*!
- \fn QPlainTextEdit::zoomIn(int range)
-
Zooms in on the text by making the base font size \a range
points larger and recalculating all font sizes to be the new size.
This does not change the size of any images.
@@ -2350,10 +2355,6 @@ void QPlainTextEdit::zoomIn(int range)
}
/*!
- \fn QPlainTextEdit::zoomOut(int range)
-
- \overload
-
Zooms out on the text by making the base font size \a range points
smaller and recalculating all font sizes to be the new size. This
does not change the size of any images.
@@ -2631,8 +2632,8 @@ void QPlainTextEdit::setReadOnly(bool ro)
} else {
flags = Qt::TextEditorInteraction;
}
- setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this));
d->control->setTextInteractionFlags(flags);
+ setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this));
QEvent event(QEvent::ReadOnlyChange);
QApplication::sendEvent(this, &event);
}
diff --git a/src/widgets/widgets/qspinbox.cpp b/src/widgets/widgets/qspinbox.cpp
index 561215ec85..dcf3906dd7 100644
--- a/src/widgets/widgets/qspinbox.cpp
+++ b/src/widgets/widgets/qspinbox.cpp
@@ -45,6 +45,8 @@
#include <qvalidator.h>
#include <qdebug.h>
+#include <algorithm>
+#include <cmath>
#include <float.h>
QT_BEGIN_NAMESPACE
@@ -75,6 +77,8 @@ public:
}
int displayIntegerBase;
+
+ QVariant calculateAdaptiveDecimalStep(int steps) const override;
};
class QDoubleSpinBoxPrivate : public QAbstractSpinBoxPrivate
@@ -100,6 +104,8 @@ public:
// When fiddling with the decimals property, we may lose precision in these properties.
double actualMin;
double actualMax;
+
+ QVariant calculateAdaptiveDecimalStep(int steps) const override;
};
@@ -415,6 +421,47 @@ void QSpinBox::setRange(int minimum, int maximum)
}
/*!
+ Sets the step type for the spin box to \a stepType, which is single
+ step or adaptive decimal step.
+
+ Adaptive decimal step means that the step size will continuously be
+ adjusted to one power of ten below the current \l value. So when
+ the value is 1100, the step is set to 100, so stepping up once
+ increases it to 1200. For 1200 stepping up takes it to 1300. For
+ negative values, stepping down from -1100 goes to -1200.
+
+ Step direction is taken into account to handle edges cases, so
+ that stepping down from 100 takes the value to 99 instead of 90.
+ Thus a step up followed by a step down -- or vice versa -- always
+ lands on the starting value; 99 -> 100 -> 99.
+
+ Setting this will cause the spin box to disregard the value of
+ \l singleStep, although it is preserved so that \l singleStep
+ comes into effect if adaptive decimal step is later turned off.
+
+ \since 5.12
+*/
+
+void QSpinBox::setStepType(QAbstractSpinBox::StepType stepType)
+{
+ Q_D(QSpinBox);
+ d->stepType = stepType;
+}
+
+/*!
+ \property QSpinBox::stepType
+ \brief The step type.
+
+ The step type can be single step or adaptive decimal step.
+*/
+
+QAbstractSpinBox::StepType QSpinBox::stepType() const
+{
+ Q_D(const QSpinBox);
+ return d->stepType;
+}
+
+/*!
\property QSpinBox::displayIntegerBase
\brief the base used to display the value of the spin box
@@ -847,6 +894,50 @@ void QDoubleSpinBox::setRange(double minimum, double maximum)
}
/*!
+ Sets the step type for the spin box to \a stepType, which is single
+ step or adaptive decimal step.
+
+ Adaptive decimal step means that the step size will continuously be
+ adjusted to one power of ten below the current \l value. So when
+ the value is 1100, the step is set to 100, so stepping up once
+ increases it to 1200. For 1200 stepping up takes it to 1300. For
+ negative values, stepping down from -1100 goes to -1200.
+
+ It also works for any decimal values, 0.041 is increased to 0.042
+ by stepping once.
+
+ Step direction is taken into account to handle edges cases, so
+ that stepping down from 100 takes the value to 99 instead of 90.
+ Thus a step up followed by a step down -- or vice versa -- always
+ lands on the starting value; 99 -> 100 -> 99.
+
+ Setting this will cause the spin box to disregard the value of
+ \l singleStep, although it is preserved so that \l singleStep
+ comes into effect if adaptive decimal step is later turned off.
+
+ \since 5.12
+*/
+
+void QDoubleSpinBox::setStepType(StepType stepType)
+{
+ Q_D(QDoubleSpinBox);
+ d->stepType = stepType;
+}
+
+/*!
+ \property QDoubleSpinBox::stepType
+ \brief The step type.
+
+ The step type can be single step or adaptive decimal step.
+*/
+
+QAbstractSpinBox::StepType QDoubleSpinBox::stepType() const
+{
+ Q_D(const QDoubleSpinBox);
+ return d->stepType;
+}
+
+/*!
\property QDoubleSpinBox::decimals
\brief the precision of the spin box, in decimals
@@ -1078,6 +1169,22 @@ QVariant QSpinBoxPrivate::validateAndInterpret(QString &input, int &pos,
return cachedValue;
}
+QVariant QSpinBoxPrivate::calculateAdaptiveDecimalStep(int steps) const
+{
+ const int intValue = value.toInt();
+ const int absValue = qAbs(intValue);
+
+ if (absValue < 100)
+ return 1;
+
+ const bool valueNegative = intValue < 0;
+ const bool stepsNegative = steps < 0;
+ const int signCompensation = (valueNegative == stepsNegative) ? 0 : 1;
+
+ const int log = static_cast<int>(std::log10(absValue - signCompensation)) - 1;
+ return static_cast<int>(std::pow(10, log));
+}
+
// --- QDoubleSpinBoxPrivate ---
/*!
@@ -1303,6 +1410,27 @@ QString QDoubleSpinBoxPrivate::textFromValue(const QVariant &f) const
return q->textFromValue(f.toDouble());
}
+QVariant QDoubleSpinBoxPrivate::calculateAdaptiveDecimalStep(int steps) const
+{
+ const double doubleValue = value.toDouble();
+ const double minStep = std::pow(10, -decimals);
+ double absValue = qAbs(doubleValue);
+
+ if (absValue < minStep)
+ return minStep;
+
+ const bool valueNegative = doubleValue < 0;
+ const bool stepsNegative = steps < 0;
+ if (valueNegative != stepsNegative)
+ absValue /= 1.01;
+
+ const double shift = std::pow(10, 1 - std::floor(std::log10(absValue)));
+ const double absRounded = round(absValue * shift) / shift;
+ const double log = floorf(std::log10(absRounded)) - 1;
+
+ return std::max(minStep, std::pow(10, log));
+}
+
/*! \reimp */
bool QSpinBox::event(QEvent *event)
{
diff --git a/src/widgets/widgets/qspinbox.h b/src/widgets/widgets/qspinbox.h
index 73489c9a68..d2eac903fb 100644
--- a/src/widgets/widgets/qspinbox.h
+++ b/src/widgets/widgets/qspinbox.h
@@ -58,6 +58,7 @@ class Q_WIDGETS_EXPORT QSpinBox : public QAbstractSpinBox
Q_PROPERTY(int minimum READ minimum WRITE setMinimum)
Q_PROPERTY(int maximum READ maximum WRITE setMaximum)
Q_PROPERTY(int singleStep READ singleStep WRITE setSingleStep)
+ Q_PROPERTY(StepType stepType READ stepType WRITE setStepType)
Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged USER true)
Q_PROPERTY(int displayIntegerBase READ displayIntegerBase WRITE setDisplayIntegerBase)
@@ -86,6 +87,9 @@ public:
void setRange(int min, int max);
+ StepType stepType() const;
+ void setStepType(StepType stepType);
+
int displayIntegerBase() const;
void setDisplayIntegerBase(int base);
@@ -121,6 +125,7 @@ class Q_WIDGETS_EXPORT QDoubleSpinBox : public QAbstractSpinBox
Q_PROPERTY(double minimum READ minimum WRITE setMinimum)
Q_PROPERTY(double maximum READ maximum WRITE setMaximum)
Q_PROPERTY(double singleStep READ singleStep WRITE setSingleStep)
+ Q_PROPERTY(StepType stepType READ stepType WRITE setStepType)
Q_PROPERTY(double value READ value WRITE setValue NOTIFY valueChanged USER true)
public:
explicit QDoubleSpinBox(QWidget *parent = nullptr);
@@ -147,6 +152,9 @@ public:
void setRange(double min, double max);
+ StepType stepType() const;
+ void setStepType(StepType stepType);
+
int decimals() const;
void setDecimals(int prec);
diff --git a/src/widgets/widgets/qsplashscreen.cpp b/src/widgets/widgets/qsplashscreen.cpp
index 44b9f7d9a1..277d2fd99f 100644
--- a/src/widgets/widgets/qsplashscreen.cpp
+++ b/src/widgets/widgets/qsplashscreen.cpp
@@ -327,7 +327,13 @@ void QSplashScreen::drawContents(QPainter *painter)
cursor.select(QTextCursor::Document);
QTextBlockFormat fmt;
fmt.setAlignment(Qt::Alignment(d->currAlign));
+ fmt.setLayoutDirection(layoutDirection());
cursor.mergeBlockFormat(fmt);
+ const QSizeF txtSize = doc.size();
+ if (d->currAlign & Qt::AlignBottom)
+ r.setTop(r.height() - txtSize.height());
+ else if (d->currAlign & Qt::AlignVCenter)
+ r.setTop(r.height() / 2 - txtSize.height() / 2);
painter->save();
painter->translate(r.topLeft());
doc.drawContents(painter);
diff --git a/src/widgets/widgets/qsplitter.cpp b/src/widgets/widgets/qsplitter.cpp
index 6ee49aa9f0..9e38c8f18a 100644
--- a/src/widgets/widgets/qsplitter.cpp
+++ b/src/widgets/widgets/qsplitter.cpp
@@ -826,7 +826,7 @@ QSplitterLayoutStruct *QSplitterPrivate::findWidget(QWidget *w) const
if (list.at(i)->widget == w)
return list.at(i);
}
- return 0;
+ return nullptr;
}
@@ -855,7 +855,7 @@ void QSplitterPrivate::insertWidget_helper(int index, QWidget *widget, bool show
QSplitterLayoutStruct *QSplitterPrivate::insertWidget(int index, QWidget *w)
{
Q_Q(QSplitter);
- QSplitterLayoutStruct *sls = 0;
+ QSplitterLayoutStruct *sls = nullptr;
int i;
int last = list.count();
for (i = 0; i < list.size(); ++i) {
@@ -872,12 +872,9 @@ QSplitterLayoutStruct *QSplitterPrivate::insertWidget(int index, QWidget *w)
if (sls) {
list.move(i,index);
} else {
- QSplitterHandle *newHandle = 0;
sls = new QSplitterLayoutStruct;
- QString tmp = QLatin1String("qt_splithandle_");
- tmp += w->objectName();
- newHandle = q->createHandle();
- newHandle->setObjectName(tmp);
+ QSplitterHandle *newHandle = q->createHandle();
+ newHandle->setObjectName(QLatin1String("qt_splithandle_") + w->objectName());
sls->handle = newHandle;
sls->widget = w;
w->lower();
@@ -1248,7 +1245,7 @@ QSplitterHandle *QSplitter::handle(int index) const
{
Q_D(const QSplitter);
if (index < 0 || index >= d->list.size())
- return 0;
+ return nullptr;
return d->list.at(index)->handle;
}
@@ -1262,7 +1259,7 @@ QWidget *QSplitter::widget(int index) const
{
Q_D(const QSplitter);
if (index < 0 || index >= d->list.size())
- return 0;
+ return nullptr;
return d->list.at(index)->widget;
}
@@ -1463,7 +1460,7 @@ void QSplitter::moveSplitter(int pos, int index)
void QSplitter::getRange(int index, int *min, int *max) const
{
Q_D(const QSplitter);
- d->getRange(index, min, 0, 0, max);
+ d->getRange(index, min, nullptr, nullptr, max);
}
diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp
index 98e15c8f17..68453e1842 100644
--- a/src/widgets/widgets/qtabbar.cpp
+++ b/src/widgets/widgets/qtabbar.cpp
@@ -74,6 +74,23 @@
QT_BEGIN_NAMESPACE
+namespace {
+class CloseButton : public QAbstractButton
+{
+ Q_OBJECT
+
+public:
+ explicit CloseButton(QWidget *parent = 0);
+
+ QSize sizeHint() const override;
+ QSize minimumSizeHint() const override
+ { return sizeHint(); }
+ void enterEvent(QEvent *event) override;
+ void leaveEvent(QEvent *event) override;
+ void paintEvent(QPaintEvent *event) override;
+};
+}
+
QMovableTabWidget::QMovableTabWidget(QWidget *parent)
: QWidget(parent)
{
@@ -2686,7 +2703,7 @@ void QTabBarPrivate::Tab::TabBarAnimation::updateCurrentValue(const QVariant &cu
priv->moveTab(priv->tabList.indexOf(*tab), current.toInt());
}
-void QTabBarPrivate::Tab::TabBarAnimation::updateState(QAbstractAnimation::State, QAbstractAnimation::State newState)
+void QTabBarPrivate::Tab::TabBarAnimation::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State)
{
if (newState == Stopped) priv->moveTabFinished(priv->tabList.indexOf(*tab));
}
@@ -2695,5 +2712,4 @@ void QTabBarPrivate::Tab::TabBarAnimation::updateState(QAbstractAnimation::State
QT_END_NAMESPACE
#include "moc_qtabbar.cpp"
-
-#include "moc_qtabbar_p.cpp"
+#include "qtabbar.moc"
diff --git a/src/widgets/widgets/qtabbar_p.h b/src/widgets/widgets/qtabbar_p.h
index 04f07c7cec..9b798e89c9 100644
--- a/src/widgets/widgets/qtabbar_p.h
+++ b/src/widgets/widgets/qtabbar_p.h
@@ -146,7 +146,7 @@ public:
void updateCurrentValue(const QVariant &current) override;
- void updateState(State, State newState) override;
+ void updateState(State newState, State) override;
private:
//these are needed for the callbacks
Tab *tab;
@@ -273,21 +273,6 @@ public:
};
-class CloseButton : public QAbstractButton
-{
- Q_OBJECT
-
-public:
- explicit CloseButton(QWidget *parent = 0);
-
- QSize sizeHint() const override;
- QSize minimumSizeHint() const override
- { return sizeHint(); }
- void enterEvent(QEvent *event) override;
- void leaveEvent(QEvent *event) override;
- void paintEvent(QPaintEvent *event) override;
-};
-
QT_END_NAMESPACE
#endif
diff --git a/src/widgets/widgets/qtabwidget.cpp b/src/widgets/widgets/qtabwidget.cpp
index df847e4894..8a848554e3 100644
--- a/src/widgets/widgets/qtabwidget.cpp
+++ b/src/widgets/widgets/qtabwidget.cpp
@@ -511,8 +511,6 @@ QString QTabWidget::tabText(int index) const
}
/*!
- \overload
-
Sets the \a icon for the tab at position \a index.
*/
void QTabWidget::setTabIcon(int index, const QIcon &icon)
diff --git a/src/widgets/widgets/qtextbrowser.cpp b/src/widgets/widgets/qtextbrowser.cpp
index fa4dd14c92..46b973bae7 100644
--- a/src/widgets/widgets/qtextbrowser.cpp
+++ b/src/widgets/widgets/qtextbrowser.cpp
@@ -163,10 +163,13 @@ QString QTextBrowserPrivate::findFile(const QUrl &name) const
fileName = name.toLocalFile();
}
+ if (fileName.isEmpty())
+ return fileName;
+
if (QFileInfo(fileName).isAbsolute())
return fileName;
- foreach (QString path, searchPaths) {
+ for (QString path : qAsConst(searchPaths)) {
if (!path.endsWith(QLatin1Char('/')))
path.append(QLatin1Char('/'));
path.append(fileName);
@@ -1089,6 +1092,8 @@ QVariant QTextBrowser::loadResource(int /*type*/, const QUrl &name)
QByteArray data;
QString fileName = d->findFile(d->resolveUrl(name));
+ if (fileName.isEmpty())
+ return QVariant();
QFile f(fileName);
if (f.open(QFile::ReadOnly)) {
data = f.readAll();
diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp
index 5790b1e32e..e3a45680ef 100644
--- a/src/widgets/widgets/qtextedit.cpp
+++ b/src/widgets/widgets/qtextedit.cpp
@@ -1518,8 +1518,7 @@ void QTextEditPrivate::paint(QPainter *p, QPaintEvent *e)
layout->setViewport(QRect());
if (!placeholderText.isEmpty() && doc->isEmpty() && !control->isPreediting()) {
- QColor col = control->palette().text().color();
- col.setAlpha(128);
+ const QColor col = control->palette().placeholderText().color();
p->setPen(col);
const int margin = int(doc->documentMargin());
p->drawText(viewport->rect().adjusted(margin, margin, -margin, -margin), Qt::AlignTop | Qt::TextWordWrap, placeholderText);
@@ -2311,8 +2310,6 @@ void QTextEdit::scrollToAnchor(const QString &name)
}
/*!
- \fn QTextEdit::zoomIn(int range)
-
Zooms in on the text by making the base font size \a range
points larger and recalculating all font sizes to be the new size.
This does not change the size of any images.
@@ -2325,10 +2322,6 @@ void QTextEdit::zoomIn(int range)
}
/*!
- \fn QTextEdit::zoomOut(int range)
-
- \overload
-
Zooms out on the text by making the base font size \a range points
smaller and recalculating all font sizes to be the new size. This
does not change the size of any images.
diff --git a/src/widgets/widgets/qtoolbar.cpp b/src/widgets/widgets/qtoolbar.cpp
index 4e90bce69d..4af71c126e 100644
--- a/src/widgets/widgets/qtoolbar.cpp
+++ b/src/widgets/widgets/qtoolbar.cpp
@@ -743,8 +743,6 @@ void QToolBar::clear()
}
/*!
- \overload
-
Creates a new action with the given \a text. This action is added to
the end of the toolbar.
*/
diff --git a/src/widgets/widgets/qtoolbarlayout_p.h b/src/widgets/widgets/qtoolbarlayout_p.h
index b813cd5e2c..a788d30450 100644
--- a/src/widgets/widgets/qtoolbarlayout_p.h
+++ b/src/widgets/widgets/qtoolbarlayout_p.h
@@ -97,7 +97,7 @@ public:
void insertAction(int index, QAction *action);
int indexOf(QAction *action) const;
- int indexOf(QWidget *widget) const override { return QLayout::indexOf(widget); }
+ using QLayout::indexOf; // bring back the hidden members
bool layoutActions(const QSize &size);
QSize expandedSize(const QSize &size) const;
diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp
index c4a928410b..cf2d885b52 100644
--- a/src/widgets/widgets/qwidgetlinecontrol.cpp
+++ b/src/widgets/widgets/qwidgetlinecontrol.cpp
@@ -711,10 +711,12 @@ bool QWidgetLineControl::finishChange(int validateFromState, bool update, bool e
m_validInput = (m_validator->validate(textCopy, cursorCopy) != QValidator::Invalid);
if (m_validInput) {
if (m_text != textCopy) {
- internalSetText(textCopy, cursorCopy, false);
+ internalSetText(textCopy, cursorCopy, edited);
return true;
}
m_cursor = cursorCopy;
+ } else {
+ emit inputRejected();
}
}
#endif
@@ -762,6 +764,8 @@ void QWidgetLineControl::internalSetText(const QString &txt, int pos, bool edite
if (m_maskData) {
m_text = maskString(0, txt, true);
m_text += clearString(m_text.length(), m_maxLength - m_text.length());
+ if (edited && oldText == m_text)
+ emit inputRejected();
} else {
m_text = txt.isEmpty() ? txt : txt.left(m_maxLength);
}
@@ -839,6 +843,8 @@ void QWidgetLineControl::internalInsert(const QString &s)
addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend));
if (m_maskData) {
QString ms = maskString(m_cursor, s);
+ if (ms.isEmpty() && !s.isEmpty())
+ emit inputRejected();
#ifndef QT_NO_ACCESSIBILITY
QAccessibleTextInsertEvent insertEvent(accessibleObject(), m_cursor, ms);
QAccessible::updateAccessibility(&insertEvent);
@@ -867,6 +873,8 @@ void QWidgetLineControl::internalInsert(const QString &s)
addCommand(Command(Insert, m_cursor++, s.at(i), -1, -1));
m_textDirty = true;
}
+ if (s.length() > remaining)
+ emit inputRejected();
}
}
diff --git a/src/widgets/widgets/qwidgetlinecontrol_p.h b/src/widgets/widgets/qwidgetlinecontrol_p.h
index ca70e2c02f..3e33bc0605 100644
--- a/src/widgets/widgets/qwidgetlinecontrol_p.h
+++ b/src/widgets/widgets/qwidgetlinecontrol_p.h
@@ -545,6 +545,7 @@ Q_SIGNALS:
void accepted();
void editingFinished();
void updateNeeded(const QRect &);
+ void inputRejected();
#ifdef QT_KEYPAD_NAVIGATION
void editFocusChange(bool);
diff --git a/src/widgets/widgets/qwidgetresizehandler.cpp b/src/widgets/widgets/qwidgetresizehandler.cpp
index 45010d1768..7ed6f6d78d 100644
--- a/src/widgets/widgets/qwidgetresizehandler.cpp
+++ b/src/widgets/widgets/qwidgetresizehandler.cpp
@@ -192,6 +192,7 @@ bool QWidgetResizeHandler::eventFilter(QObject *o, QEvent *ee)
keyPressEvent(static_cast<QKeyEvent *>(ee));
break;
case QEvent::ShortcutOverride:
+ buttonDown &= ((QGuiApplication::mouseButtons() & Qt::LeftButton) != Qt::NoButton);
if (buttonDown) {
ee->accept();
return true;
diff --git a/src/winmain/qtmain_winrt.cpp b/src/winmain/qtmain_winrt.cpp
index 79ecf30b70..7cc57f4d46 100644
--- a/src/winmain/qtmain_winrt.cpp
+++ b/src/winmain/qtmain_winrt.cpp
@@ -69,6 +69,7 @@ extern "C" {
#include <qstandardpaths.h>
#include <qfunctions_winrt.h>
#include <qcoreapplication.h>
+#include <qmutex.h>
#include <wrl.h>
#include <Windows.ApplicationModel.core.h>
@@ -87,27 +88,68 @@ using namespace Microsoft::WRL::Wrappers;
#define CoreApplicationClass RuntimeClass_Windows_ApplicationModel_Core_CoreApplication
typedef ITypedEventHandler<CoreApplicationView *, Activation::IActivatedEventArgs *> ActivatedHandler;
+const quint32 resizeMessageType = QtInfoMsg + 1;
+
+const PCWSTR shmemName = L"qdebug-shmem";
+const PCWSTR eventName = L"qdebug-event";
+const PCWSTR ackEventName = L"qdebug-event-ack";
+
static QtMessageHandler defaultMessageHandler;
static void devMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message)
{
static HANDLE shmem = 0;
static HANDLE event = 0;
+ static HANDLE ackEvent = 0;
+
+ static QMutex messageMutex;
+ QMutexLocker locker(&messageMutex);
+
+ static quint64 mappingSize = 4096;
+ const quint32 copiedMessageLength = message.length() + 1;
+ // Message format is message type + message. We need the message's length + 4 bytes for the type
+ const quint64 copiedMessageSize = copiedMessageLength * sizeof(wchar_t) + sizeof(quint32);
+ if (copiedMessageSize > mappingSize) {
+ if (!shmem)
+ shmem = CreateFileMappingFromApp(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, mappingSize, shmemName);
+ Q_ASSERT_X(shmem, Q_FUNC_INFO, "Could not create file mapping");
+
+ quint32 *data = reinterpret_cast<quint32 *>(MapViewOfFileFromApp(shmem, FILE_MAP_WRITE, 0, mappingSize));
+ Q_ASSERT_X(data, Q_FUNC_INFO, "Could not map size file");
+
+ mappingSize = copiedMessageSize;
+
+ memcpy(data, (void *)&resizeMessageType, sizeof(quint32));
+ memcpy(data + 1, (void *)&mappingSize, sizeof(quint64));
+ UnmapViewOfFile(data);
+ SetEvent(event);
+ WaitForSingleObjectEx(ackEvent, INFINITE, false);
+ if (shmem) {
+ if (!CloseHandle(shmem))
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Could not close shared file handle");
+ shmem = 0;
+ }
+ }
+
if (!shmem)
- shmem = CreateFileMappingFromApp(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 4096, L"qdebug-shmem");
+ shmem = CreateFileMappingFromApp(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, mappingSize, shmemName);
if (!event)
- event = CreateEventEx(NULL, L"qdebug-event", 0, EVENT_ALL_ACCESS);
+ event = CreateEventEx(NULL, eventName, 0, EVENT_ALL_ACCESS);
+ if (!ackEvent)
+ ackEvent = CreateEventEx(NULL, ackEventName, 0, EVENT_ALL_ACCESS);
Q_ASSERT_X(shmem, Q_FUNC_INFO, "Could not create file mapping");
Q_ASSERT_X(event, Q_FUNC_INFO, "Could not create debug event");
- void *data = MapViewOfFileFromApp(shmem, FILE_MAP_WRITE, 0, 4096);
+ void *data = MapViewOfFileFromApp(shmem, FILE_MAP_WRITE, 0, mappingSize);
Q_ASSERT_X(data, Q_FUNC_INFO, "Could not map file");
memset(data, quint32(type), sizeof(quint32));
- memcpy_s(static_cast<quint32 *>(data) + 1, 4096 - sizeof(quint32),
- message.data(), (message.length() + 1) * sizeof(wchar_t));
+ memcpy_s(static_cast<quint32 *>(data) + 1, mappingSize - sizeof(quint32),
+ message.data(), copiedMessageLength * sizeof(wchar_t));
UnmapViewOfFile(data);
SetEvent(event);
+ WaitForSingleObjectEx(ackEvent, INFINITE, false);
+ locker.unlock();
defaultMessageHandler(type, context, message);
}
@@ -149,15 +191,11 @@ public:
{
}
- int exec(int argc, char **argv)
+ int exec()
{
- args.reserve(argc);
- for (int i = 0; i < argc; ++i)
- args.append(argv[i]);
-
mainThread = CreateThread(NULL, 0, [](void *param) -> DWORD {
AppContainer *app = reinterpret_cast<AppContainer *>(param);
- int argc = app->args.count();
+ int argc = app->args.count() - 1;
char **argv = app->args.data();
const int res = main(argc, argv);
if (app->pidFile != INVALID_HANDLE_VALUE) {
@@ -305,6 +343,8 @@ private:
args.remove(i);
}
}
+ args.append(nullptr);
+
if (develMode) {
// Write a PID file to help runner
const QString pidFileName = QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation))
@@ -379,18 +419,9 @@ private:
// Main entry point for Appx containers
int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
- int argc = 0;
- char **argv = 0, **env = 0;
- for (int i = 0; env && env[i]; ++i) {
- QByteArray var(env[i]);
- int split = var.indexOf('=');
- if (split > 0)
- qputenv(var.mid(0, split), var.mid(split + 1));
- }
-
if (FAILED(RoInitialize(RO_INIT_MULTITHREADED)))
return 1;
ComPtr<AppContainer> app = Make<AppContainer>();
- return app->exec(argc, argv);
+ return app->exec();
}
diff --git a/src/xml/doc/src/xml-processing.qdoc b/src/xml/doc/src/xml-processing.qdoc
index 00c73b4465..4dfcbf4722 100644
--- a/src/xml/doc/src/xml-processing.qdoc
+++ b/src/xml/doc/src/xml-processing.qdoc
@@ -376,7 +376,7 @@
reported through the handler.
\endtable
- The \l{SAX Bookmarks example} illustrates how to subclass
+ The \l{SAX Bookmarks Example} illustrates how to subclass
QXmlDefaultHandler to read an XML bookmark file (XBEL) and
how to generate XML by hand.
@@ -606,7 +606,7 @@
DOM implementation.
To get started please refer to the \l QDomDocument documentation.
- You might also want to take a look at the \l{DOM Bookmarks example},
+ You might also want to take a look at the \l{DOM Bookmarks Example},
which illustrates how to read and write an XML bookmark file (XBEL)
using DOM.
*/
diff --git a/sync.profile b/sync.profile
index c674aab2f3..a6d0e2a4a7 100644
--- a/sync.profile
+++ b/sync.profile
@@ -80,7 +80,7 @@
);
@qpa_headers = ( qr/^(?!qplatformheaderhelper)qplatform/, qr/^qwindowsystem/ );
-my @angle_headers = ('egl.h', 'eglext.h', 'eglplatform.h', 'gl2.h', 'gl2ext.h', 'gl2platform.h', 'ShaderLang.h', 'khrplatform.h');
+my @angle_headers = ('egl.h', 'eglext.h', 'eglext_angle.h', 'eglplatform.h', 'gl2.h', 'gl2ext.h', 'gl2ext_angle.h', 'gl2platform.h', 'ShaderLang.h', 'khrplatform.h');
my @internal_zlib_headers = ( "crc32.h", "deflate.h", "gzguts.h", "inffast.h", "inffixed.h", "inflate.h", "inftrees.h", "trees.h", "zutil.h" );
my @zlib_headers = ( "zconf.h", "zlib.h" );
@ignore_headers = ( @internal_zlib_headers );
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index fbd89e4045..9eb741edac 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -23,12 +23,12 @@ uikit: SUBDIRS = corelib gui
cross_compile: SUBDIRS -= tools cmake installed_cmake
else:!qtConfig(process): SUBDIRS -= tools
-!qtHaveModule(opengl): SUBDIRS -= opengl
+winrt|!qtHaveModule(opengl): SUBDIRS -= opengl
!qtHaveModule(gui): SUBDIRS -= gui
!qtHaveModule(widgets): SUBDIRS -= widgets
!qtHaveModule(printsupport): SUBDIRS -= printsupport
!qtHaveModule(concurrent): SUBDIRS -= concurrent
-!qtHaveModule(network): SUBDIRS -= network
+winrt|!qtHaveModule(network): SUBDIRS -= network
!qtHaveModule(dbus): SUBDIRS -= dbus
!qtHaveModule(xml): SUBDIRS -= xml
!qtHaveModule(sql): SUBDIRS -= sql
diff --git a/tests/auto/cmake/CMakeLists.txt b/tests/auto/cmake/CMakeLists.txt
index 7f685b0338..51d0d2879e 100644
--- a/tests/auto/cmake/CMakeLists.txt
+++ b/tests/auto/cmake/CMakeLists.txt
@@ -146,6 +146,7 @@ endif()
expect_pass(test_interface_link_libraries)
expect_pass(test_moc_macro_target)
+expect_pass(test_add_big_resource)
if (NOT CMAKE_VERSION VERSION_LESS 3.8)
# With earlier CMake versions, this test would simply run moc multiple times and lead to:
diff --git a/tests/auto/cmake/test_add_big_resource/CMakeLists.txt b/tests/auto/cmake/test_add_big_resource/CMakeLists.txt
new file mode 100644
index 0000000000..f928b11278
--- /dev/null
+++ b/tests/auto/cmake/test_add_big_resource/CMakeLists.txt
@@ -0,0 +1,13 @@
+
+cmake_minimum_required(VERSION 2.8)
+
+project(test_add_big_resource)
+
+find_package(Qt5Core REQUIRED)
+
+qt5_wrap_cpp(moc_files myobject.h)
+
+qt5_add_big_resources(rcc_files "test_add_big_resource.qrc" "test_add_big_resource2.qrc")
+
+add_executable(myobject myobject.cpp ${moc_files} ${rcc_files})
+target_link_libraries(myobject ${Qt5Core_LIBRARIES})
diff --git a/tests/auto/cmake/test_add_big_resource/myobject.cpp b/tests/auto/cmake/test_add_big_resource/myobject.cpp
new file mode 100644
index 0000000000..5d320b8592
--- /dev/null
+++ b/tests/auto/cmake/test_add_big_resource/myobject.cpp
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "myobject.h"
+
+MyObject::MyObject(QObject *parent)
+ : QObject(parent)
+{
+ emit someSignal();
+}
+
+int main(int argc, char **argv)
+{
+ MyObject myObject;
+ // Compile error if the resource file was not created.
+ Q_INIT_RESOURCE(test_add_big_resource);
+ Q_INIT_RESOURCE(test_add_big_resource2);
+ return 0;
+}
diff --git a/tests/auto/cmake/test_add_big_resource/myobject.h b/tests/auto/cmake/test_add_big_resource/myobject.h
new file mode 100644
index 0000000000..b6fbce32cd
--- /dev/null
+++ b/tests/auto/cmake/test_add_big_resource/myobject.h
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MYOBJECT_H
+#define MYOBJECT_H
+
+#include <QObject>
+
+class MyObject : public QObject
+{
+ Q_OBJECT
+public:
+ MyObject(QObject *parent = 0);
+
+signals:
+ void someSignal();
+};
+
+#endif
diff --git a/tests/auto/cmake/test_add_big_resource/resource_file.txt b/tests/auto/cmake/test_add_big_resource/resource_file.txt
new file mode 100644
index 0000000000..2c604a4f18
--- /dev/null
+++ b/tests/auto/cmake/test_add_big_resource/resource_file.txt
@@ -0,0 +1 @@
+Ken sent me.
diff --git a/tests/auto/cmake/test_add_big_resource/resource_file2.txt b/tests/auto/cmake/test_add_big_resource/resource_file2.txt
new file mode 100644
index 0000000000..2c604a4f18
--- /dev/null
+++ b/tests/auto/cmake/test_add_big_resource/resource_file2.txt
@@ -0,0 +1 @@
+Ken sent me.
diff --git a/tests/auto/cmake/test_add_big_resource/test_add_big_resource.qrc b/tests/auto/cmake/test_add_big_resource/test_add_big_resource.qrc
new file mode 100644
index 0000000000..00a17f541f
--- /dev/null
+++ b/tests/auto/cmake/test_add_big_resource/test_add_big_resource.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/">
+ <file>resource_file.txt</file>
+</qresource>
+</RCC>
+
diff --git a/tests/auto/cmake/test_add_big_resource/test_add_big_resource2.qrc b/tests/auto/cmake/test_add_big_resource/test_add_big_resource2.qrc
new file mode 100644
index 0000000000..e21cc5e138
--- /dev/null
+++ b/tests/auto/cmake/test_add_big_resource/test_add_big_resource2.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/">
+ <file>resource_file2.txt</file>
+</qresource>
+</RCC>
+
diff --git a/tests/auto/cmake/test_opengl_lib/CMakeLists.txt b/tests/auto/cmake/test_opengl_lib/CMakeLists.txt
index d9adb5a980..d2304a4183 100644
--- a/tests/auto/cmake/test_opengl_lib/CMakeLists.txt
+++ b/tests/auto/cmake/test_opengl_lib/CMakeLists.txt
@@ -8,11 +8,25 @@ find_package(Qt5Gui REQUIRED)
include_directories(${Qt5Gui_INCLUDE_DIRS} ${Qt5Gui_OPENGL_INCLUDE_DIRS} )
add_definitions(${Qt5Gui_DEFINITIONS})
+get_property(QtGui_enabled_features TARGET Qt5::Gui PROPERTY INTERFACE_QT_ENABLED_FEATURES)
+list(LENGTH QtGui_enabled_features _QtGui_enabled_featuresSize)
+if (_QtGui_enabled_featuresSize LESS 1)
+ message(SEND_ERROR "The INTERFACE_QT_ENABLED_FEATURES property of Qt5::Gui is empty!")
+endif()
+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Gui_EXECUTABLE_COMPILE_FLAGS}")
if (${Qt5Gui_OPENGL_IMPLEMENTATION} STREQUAL GLESv2)
+ list(FIND QtGui_enabled_features "opengles2" _opengles2Index)
+ if(_opengles2Index EQUAL -1)
+ message(SEND_ERROR "The INTERFACE_QT_ENABLED_FEATURES property of Qt5::Gui does not contain the opengles2 feature!")
+ endif()
add_definitions(-DGL_IMPLEMENTATION_GLES2)
elseif (${Qt5Gui_OPENGL_IMPLEMENTATION} STREQUAL GL)
+ list(FIND QtGui_enabled_features "opengl" _openglIndex)
+ if(_openglIndex EQUAL -1)
+ message(SEND_ERROR "The INTERFACE_QT_ENABLED_FEATURES property of Qt5::Gui does not contain the opengl feature!")
+ endif()
add_definitions(-DGL_IMPLEMENTATION_GL)
else()
message(SEND_ERROR "Qt5Gui_OPENGL_IMPLEMENTATION does not contain valid data.")
diff --git a/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp b/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp
index f539f012df..b864b065e6 100644
--- a/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp
+++ b/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp
@@ -2379,7 +2379,7 @@ void tst_QtConcurrentMap::stlContainers()
InstanceCounter ic_fn(const InstanceCounter & ic)
{
return InstanceCounter(ic);
-};
+}
// Verify that held results are deleted when a future is
// assigned over with operator ==
diff --git a/tests/auto/corelib/animation/qparallelanimationgroup/BLACKLIST b/tests/auto/corelib/animation/qparallelanimationgroup/BLACKLIST
index fe1d5bd968..b5b37b4498 100644
--- a/tests/auto/corelib/animation/qparallelanimationgroup/BLACKLIST
+++ b/tests/auto/corelib/animation/qparallelanimationgroup/BLACKLIST
@@ -1,2 +1,3 @@
[deleteChildrenWithRunningGroup]
osx-10.12
+osx-10.13
diff --git a/tests/auto/corelib/animation/qsequentialanimationgroup/BLACKLIST b/tests/auto/corelib/animation/qsequentialanimationgroup/BLACKLIST
index 2a31afd735..4c999ff88f 100644
--- a/tests/auto/corelib/animation/qsequentialanimationgroup/BLACKLIST
+++ b/tests/auto/corelib/animation/qsequentialanimationgroup/BLACKLIST
@@ -3,5 +3,6 @@ windows
[finishWithUncontrolledAnimation]
windows
osx-10.12
+osx-10.13
[groupWithZeroDurationAnimations]
osx
diff --git a/tests/auto/corelib/codecs/qtextcodec/echo/echo.pro b/tests/auto/corelib/codecs/qtextcodec/echo/echo.pro
index bf791ffc61..512da8939b 100644
--- a/tests/auto/corelib/codecs/qtextcodec/echo/echo.pro
+++ b/tests/auto/corelib/codecs/qtextcodec/echo/echo.pro
@@ -1,6 +1,4 @@
SOURCES += main.cpp
QT = core
-CONFIG -= app_bundle debug_and_release_target
-CONFIG += console
-
+load(qt_test_helper)
diff --git a/tests/auto/corelib/codecs/qtextcodec/qtextcodec.pro b/tests/auto/corelib/codecs/qtextcodec/qtextcodec.pro
index 302d887fc7..15de02a42d 100644
--- a/tests/auto/corelib/codecs/qtextcodec/qtextcodec.pro
+++ b/tests/auto/corelib/codecs/qtextcodec/qtextcodec.pro
@@ -1,2 +1,3 @@
TEMPLATE = subdirs
-SUBDIRS = test echo
+SUBDIRS = test.pro
+unix: SUBDIRS += echo
diff --git a/tests/auto/corelib/codecs/qtextcodec/test.pro b/tests/auto/corelib/codecs/qtextcodec/test.pro
new file mode 100644
index 0000000000..7505c5ad51
--- /dev/null
+++ b/tests/auto/corelib/codecs/qtextcodec/test.pro
@@ -0,0 +1,6 @@
+CONFIG += testcase
+QT = core testlib
+SOURCES = tst_qtextcodec.cpp
+
+TARGET = tst_qtextcodec
+TESTDATA += *.txt
diff --git a/tests/auto/corelib/codecs/qtextcodec/test/test.pro b/tests/auto/corelib/codecs/qtextcodec/test/test.pro
deleted file mode 100644
index e0a1bbd88e..0000000000
--- a/tests/auto/corelib/codecs/qtextcodec/test/test.pro
+++ /dev/null
@@ -1,13 +0,0 @@
-CONFIG += testcase
-QT = core testlib
-SOURCES = ../tst_qtextcodec.cpp
-
-TARGET = ../tst_qtextcodec
-win32 {
- CONFIG(debug, debug|release) {
- TARGET = ../../debug/tst_qtextcodec
- } else {
- TARGET = ../../release/tst_qtextcodec
- }
-}
-TESTDATA += ../*.txt
diff --git a/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp b/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp
index f8f9387abb..6cadebfd7f 100644
--- a/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp
+++ b/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp
@@ -2092,7 +2092,7 @@ void tst_QTextCodec::toLocal8Bit()
QSKIP("No qprocess support", SkipAll);
#else
QProcess process;
- process.start("echo/echo");
+ process.start("echo_helper");
QString string(QChar(0x410));
process.write((const char*)string.utf16(), string.length()*2);
@@ -2429,7 +2429,7 @@ void tst_QTextCodec::userCodec()
QVERIFY(!QTextCodec::availableCodecs().contains("UserCodec"));
QVERIFY(!QTextCodec::codecForName("UserCodec"));
- QTextCodec *codec = new UserCodec;
+ UserCodec *codec = new UserCodec;
executedOnce = true;
QList<QByteArray> availableCodecs = QTextCodec::availableCodecs();
@@ -2448,6 +2448,11 @@ void tst_QTextCodec::userCodec()
pcodec = QTextCodec::codecForMib(5000);
QCOMPARE(pcodec, codec);
+
+ delete codec;
+
+ pcodec = QTextCodec::codecForName("UserCodec");
+ QCOMPARE(pcodec, nullptr);
}
struct DontCrashAtExit {
diff --git a/tests/auto/corelib/codecs/utf8/tst_utf8.cpp b/tests/auto/corelib/codecs/utf8/tst_utf8.cpp
index 8f78aa937c..9ce1748e72 100644
--- a/tests/auto/corelib/codecs/utf8/tst_utf8.cpp
+++ b/tests/auto/corelib/codecs/utf8/tst_utf8.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
+** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -71,7 +71,7 @@ void tst_Utf8::initTestCase()
// is the locale UTF-8?
if (QString(QChar(QChar::ReplacementCharacter)).toLocal8Bit() == "\xEF\xBF\xBD") {
QTest::newRow("localecodec") << true;
- qDebug() << "locale is utf8";
+ qInfo() << "locale is utf8";
}
}
@@ -227,6 +227,15 @@ void tst_Utf8::invalidUtf8()
// GNU libc's iconv is known to accept U+FFFF and U+FFFE encoded as UTF-8
// OS X's iconv is known to accept those, plus surrogates and codepoints above U+10FFFF
if (!useLocale)
+ QVERIFY(decoder->hasFailure() || decoder->needsMoreData());
+ else if (!decoder->hasFailure() && !decoder->needsMoreData())
+ qWarning("System codec does not report failure when it should. Should report bug upstream.");
+
+ // add a continuation character and test that we don't accidentally use it
+ // (buffer overrun)
+ utf8 += char(0x80 | 0x3f);
+ decoder->toUnicode(utf8.constData(), utf8.size() - 1);
+ if (!useLocale)
QVERIFY(decoder->hasFailure());
else if (!decoder->hasFailure())
qWarning("System codec does not report failure when it should. Should report bug upstream.");
diff --git a/tests/auto/corelib/codecs/utf8/utf8data.cpp b/tests/auto/corelib/codecs/utf8/utf8data.cpp
index 2267dc8514..221e1d5579 100644
--- a/tests/auto/corelib/codecs/utf8/utf8data.cpp
+++ b/tests/auto/corelib/codecs/utf8/utf8data.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -29,15 +30,24 @@
void loadInvalidUtf8Rows()
{
- QTest::newRow("1char") << QByteArray("\x80");
- QTest::newRow("2chars-1") << QByteArray("\xC2\xC0");
- QTest::newRow("2chars-2") << QByteArray("\xC3\xDF");
- QTest::newRow("2chars-3") << QByteArray("\xC7\xF0");
- QTest::newRow("3chars-1") << QByteArray("\xE0\xA0\xC0");
- QTest::newRow("3chars-2") << QByteArray("\xE0\xC0\xA0");
- QTest::newRow("4chars-1") << QByteArray("\xF0\x90\x80\xC0");
- QTest::newRow("4chars-2") << QByteArray("\xF0\x90\xC0\x80");
- QTest::newRow("4chars-3") << QByteArray("\xF0\xC0\x80\x80");
+ // Wrong continuations
+ QTest::newRow("bad-continuation-1char") << QByteArray("\x80");
+ QTest::newRow("bad-continuation-2chars-1") << QByteArray("\xC2\xC0");
+ QTest::newRow("bad-continuation-2chars-2") << QByteArray("\xC3\xDF");
+ QTest::newRow("bad-continuation-2chars-3") << QByteArray("\xC7\xF0");
+ QTest::newRow("bad-continuation-3chars-1") << QByteArray("\xE0\xA0\xC0");
+ QTest::newRow("bad-continuation-3chars-2") << QByteArray("\xE0\xC0\xA0");
+ QTest::newRow("bad-continuation-4chars-1") << QByteArray("\xF0\x90\x80\xC0");
+ QTest::newRow("bad-continuation-4chars-2") << QByteArray("\xF0\x90\xC0\x80");
+ QTest::newRow("bad-continuation-4chars-3") << QByteArray("\xF0\xC0\x80\x80");
+
+ // Too short
+ QTest::newRow("too-short-2chars") << QByteArray("\xC2");
+ QTest::newRow("too-short-3chars-1") << QByteArray("\xE0");
+ QTest::newRow("too-short-3chars-2") << QByteArray("\xE0\xA0");
+ QTest::newRow("too-short-4chars-1") << QByteArray("\xF0");
+ QTest::newRow("too-short-4chars-2") << QByteArray("\xF0\x90");
+ QTest::newRow("too-short-4chars-3") << QByteArray("\xF0\x90\x80");
// Surrogate pairs must now be present either
// U+D800: 1101 10 0000 00 0000
diff --git a/tests/auto/corelib/global/qflags/tst_qflags.cpp b/tests/auto/corelib/global/qflags/tst_qflags.cpp
index 2f1b56629a..72b086350e 100644
--- a/tests/auto/corelib/global/qflags/tst_qflags.cpp
+++ b/tests/auto/corelib/global/qflags/tst_qflags.cpp
@@ -39,6 +39,7 @@ private slots:
void classEnum();
void initializerLists();
void testSetFlags();
+ void adl();
};
void tst_QFlags::testFlag() const
@@ -120,7 +121,7 @@ void tst_QFlags::constExpr()
QVERIFY(verifyConstExpr<uint(Qt::MouseButtons(Qt::RightButton) & 0xff)>(Qt::RightButton));
QVERIFY(verifyConstExpr<uint(Qt::MouseButtons(Qt::RightButton) | 0xff)>(0xff));
- QVERIFY(!verifyConstExpr<Qt::RightButton>(!Qt::MouseButtons(Qt::LeftButton)));
+ QVERIFY(!verifyConstExpr<Qt::RightButton>(~Qt::MouseButtons(Qt::LeftButton)));
#if defined(__cpp_constexpr) && __cpp_constexpr-0 >= 201304
QVERIFY(verifyConstExpr<uint(testRelaxedConstExpr())>(Qt::MiddleButton));
@@ -304,6 +305,27 @@ void tst_QFlags::testSetFlags()
QVERIFY(!flags.testFlag(MyStrictEnum::StrictFour));
}
+namespace SomeNS {
+enum Foo { Foo_A = 1 << 0, Foo_B = 1 << 1, Foo_C = 1 << 2 };
+
+Q_DECLARE_FLAGS(Foos, Foo)
+Q_DECLARE_OPERATORS_FOR_FLAGS(Foos);
+
+Qt::Alignment alignment()
+{
+ // Checks that the operator| works, despite there is another operator| in this namespace.
+ return Qt::AlignLeft | Qt::AlignTop;
+}
+}
+
+void tst_QFlags::adl()
+{
+ SomeNS::Foos fl = SomeNS::Foo_B | SomeNS::Foo_C;
+ QVERIFY(fl & SomeNS::Foo_B);
+ QVERIFY(!(fl & SomeNS::Foo_A));
+ QCOMPARE(SomeNS::alignment(), Qt::AlignLeft | Qt::AlignTop);
+}
+
// (statically) check QTypeInfo for QFlags instantiations:
enum MyEnum { Zero, One, Two, Four=4 };
Q_DECLARE_FLAGS( MyFlags, MyEnum )
diff --git a/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp b/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp
index f02e902468..544cb1bf07 100644
--- a/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp
+++ b/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp
@@ -160,8 +160,10 @@ void tst_QGetPutEnv::intValue_data()
// some repetition from what is tested in getSetCheck()
QTest::newRow("empty") << QByteArray() << 0 << false;
- QTest::newRow("spaces-heading") << QByteArray(" 1") << 1 << true;
- QTest::newRow("spaces-trailing") << QByteArray("1 ") << 0 << false;
+ QTest::newRow("spaces-heading") << QByteArray(" \n\r\t1") << 1 << true;
+ QTest::newRow("spaces-trailing") << QByteArray("1 \n\r\t") << 1 << true;
+ QTest::newRow("junk-heading") << QByteArray("x1") << 0 << false;
+ QTest::newRow("junk-trailing") << QByteArray("1x") << 0 << false;
#define ROW(x, i, b) \
QTest::newRow(#x) << QByteArray(#x) << (i) << (b)
diff --git a/tests/auto/corelib/global/qlogging/app/app.pro b/tests/auto/corelib/global/qlogging/app/app.pro
index 30751d89ec..b90b685749 100644
--- a/tests/auto/corelib/global/qlogging/app/app.pro
+++ b/tests/auto/corelib/global/qlogging/app/app.pro
@@ -1,6 +1,15 @@
TEMPLATE = app
-TARGET = app
+debug_and_release {
+ CONFIG(debug, debug|release) {
+ TARGET = ../debug/helper
+ } else {
+ TARGET = ../release/helper
+ }
+} else {
+ TARGET = ../helper
+}
+
QT = core
DESTDIR = ./
diff --git a/tests/auto/corelib/global/qlogging/test/test.pro b/tests/auto/corelib/global/qlogging/test/test.pro
index b48bf82cf9..91896d4494 100644
--- a/tests/auto/corelib/global/qlogging/test/test.pro
+++ b/tests/auto/corelib/global/qlogging/test/test.pro
@@ -1,11 +1,21 @@
CONFIG += testcase
-CONFIG -= debug_and_release_target
qtConfig(c++11): CONFIG += c++11
qtConfig(c++14): CONFIG += c++14
-TARGET = ../tst_qlogging
+debug_and_release {
+ CONFIG(debug, debug|release) {
+ TARGET = ../../debug/tst_qlogging
+ !android:!winrt: TEST_HELPER_INSTALLS = ../debug/helper
+ } else {
+ TARGET = ../../release/tst_qlogging
+ !android:!winrt: TEST_HELPER_INSTALLS = ../release/helper
+ }
+} else {
+ TARGET = ../tst_qlogging
+ !android:!winrt: TEST_HELPER_INSTALLS = ../helper
+}
+
QT = core testlib
SOURCES = ../tst_qlogging.cpp
DEFINES += QT_MESSAGELOGCONTEXT
-!android:!winrt: TEST_HELPER_INSTALLS = ../app/app
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp
index e7a3748c30..d3ed1a6d0d 100644
--- a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp
+++ b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp
@@ -64,7 +64,6 @@ private slots:
void formatLogMessage();
private:
- QString m_appDir;
QStringList m_baseEnvironment;
};
@@ -101,14 +100,6 @@ tst_qmessagehandler::tst_qmessagehandler()
void tst_qmessagehandler::initTestCase()
{
#if QT_CONFIG(process)
-# ifdef Q_OS_ANDROID
- m_appDir = QCoreApplication::applicationDirPath();
-# else // !android
- m_appDir = QFINDTESTDATA("app");
-# endif
- QVERIFY2(!m_appDir.isEmpty(), qPrintable(
- QString::fromLatin1("Couldn't find helper app dir starting from %1.").arg(QDir::currentPath())));
-
m_baseEnvironment = QProcess::systemEnvironment();
for (int i = 0; i < m_baseEnvironment.count(); ++i) {
if (m_baseEnvironment.at(i).startsWith("QT_MESSAGE_PATTERN=")) {
@@ -806,7 +797,7 @@ void tst_qmessagehandler::qMessagePattern_data()
#ifndef QT_NO_DEBUG
QTest::newRow("backtrace") << "[%{backtrace}] %{message}" << true << (QList<QByteArray>()
// MyClass::qt_static_metacall is explicitly marked as hidden in the Q_OBJECT macro
- << "[MyClass::myFunction|MyClass::mySlot1|?app?|" QT_NAMESPACE_STR "QMetaMethod::invoke|" QT_NAMESPACE_STR "QMetaObject::invokeMethod] from_a_function 34");
+ << "[MyClass::myFunction|MyClass::mySlot1|?helper?|" QT_NAMESPACE_STR "QMetaMethod::invoke|" QT_NAMESPACE_STR "QMetaObject::invokeMethod] from_a_function 34");
#endif
QTest::newRow("backtrace depth,separator") << "[%{backtrace depth=2 separator=\"\n\"}] %{message}" << true << (QList<QByteArray>()
@@ -830,10 +821,10 @@ void tst_qmessagehandler::qMessagePattern()
QFETCH(QList<QByteArray>, expected);
QProcess process;
-#ifdef Q_OS_ANDROID
- const QString appExe = m_appDir + "/libapp.so";
-#else // !android
- const QString appExe = m_appDir + "/app";
+#ifndef Q_OS_ANDROID
+ const QString appExe(QLatin1String("helper"));
+#else
+ const QString appExe(QCoreApplication::applicationDirPath() + QLatin1String("/libhelper.so"));
#endif
//
@@ -880,10 +871,10 @@ void tst_qmessagehandler::setMessagePattern()
//
QProcess process;
-#ifdef Q_OS_ANDROID
- const QString appExe = m_appDir + "/libapp.so";
-#else // !android
- const QString appExe = m_appDir + "/app";
+#ifndef Q_OS_ANDROID
+ const QString appExe(QLatin1String("helper"));
+#else
+ const QString appExe(QCoreApplication::applicationDirPath() + QLatin1String("/libhelper.so"));
#endif
// make sure there is no QT_MESSAGE_PATTERN in the environment
diff --git a/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp b/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp
index 7a6842d144..7c04611823 100644
--- a/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp
+++ b/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp
@@ -52,7 +52,7 @@
// values chosen at random
static const quint32 RandomValue32 = 0x4d1169f1U;
static const quint64 RandomValue64 = Q_UINT64_C(0x3ce63161b998aa91);
-static const double RandomValueFP = double(0.3010463714599609f);
+static const double RandomValueFP = double(0.3010463714599609);
static void setRNGControl(uint v)
{
diff --git a/tests/auto/corelib/global/qtendian/tst_qtendian.cpp b/tests/auto/corelib/global/qtendian/tst_qtendian.cpp
index 6934818dcf..2345bb39c1 100644
--- a/tests/auto/corelib/global/qtendian/tst_qtendian.cpp
+++ b/tests/auto/corelib/global/qtendian/tst_qtendian.cpp
@@ -39,9 +39,17 @@ class tst_QtEndian: public QObject
private slots:
void fromBigEndian();
void fromLittleEndian();
+ void fromBigEndianRegion_data();
+ void fromBigEndianRegion();
+ void fromLittleEndianRegion_data() { fromBigEndianRegion_data(); }
+ void fromLittleEndianRegion();
void toBigEndian();
void toLittleEndian();
+ void toBigEndianRegion_data() { fromBigEndianRegion_data(); }
+ void toBigEndianRegion();
+ void toLittleEndianRegion_data() { fromBigEndianRegion_data(); }
+ void toLittleEndianRegion();
void endianIntegers_data();
void endianIntegers();
@@ -56,18 +64,58 @@ struct TestData
quint16 data16;
quint8 data8;
+ float dataFloat;
+ double dataDouble;
+
quint8 reserved;
};
+template <typename T> T getData(const TestData &d);
+template <> quint8 getData(const TestData &d) { return d.data8; }
+template <> quint16 getData(const TestData &d) { return d.data16; }
+template <> quint32 getData(const TestData &d) { return d.data32; }
+template <> quint64 getData(const TestData &d) { return d.data64; }
+template <> float getData(const TestData &d) { return d.dataFloat; }
+
union RawTestData
{
uchar rawData[sizeof(TestData)];
TestData data;
};
-static const TestData inNativeEndian = { Q_UINT64_C(0x0123456789abcdef), 0x00c0ffee, 0xcafe, 0xcf, '\0' };
-static const RawTestData inBigEndian = { "\x01\x23\x45\x67\x89\xab\xcd\xef" "\x00\xc0\xff\xee" "\xca\xfe" "\xcf" };
-static const RawTestData inLittleEndian = { "\xef\xcd\xab\x89\x67\x45\x23\x01" "\xee\xff\xc0\x00" "\xfe\xca" "\xcf" };
+template <typename Float>
+Float int2Float(typename QIntegerForSizeof<Float>::Unsigned i)
+{
+ Float result = 0;
+ memcpy(reinterpret_cast<char *>(&result), reinterpret_cast<const char *>(&i), sizeof (Float));
+ return result;
+}
+
+static const TestData inNativeEndian = {
+ Q_UINT64_C(0x0123456789abcdef),
+ 0x00c0ffee,
+ 0xcafe,
+ 0xcf,
+ int2Float<float>(0x00c0ffeeU),
+ int2Float<double>(Q_UINT64_C(0x0123456789abcdef)),
+ '\0'
+};
+static const RawTestData inBigEndian = {
+ "\x01\x23\x45\x67\x89\xab\xcd\xef"
+ "\x00\xc0\xff\xee"
+ "\xca\xfe"
+ "\xcf"
+ "\x00\xc0\xff\xee"
+ "\x01\x23\x45\x67\x89\xab\xcd\xef"
+};
+static const RawTestData inLittleEndian = {
+ "\xef\xcd\xab\x89\x67\x45\x23\x01"
+ "\xee\xff\xc0\x00"
+ "\xfe\xca"
+ "\xcf"
+ "\xee\xff\xc0\x00"
+ "\xef\xcd\xab\x89\x67\x45\x23\x01"
+};
#define EXPAND_ENDIAN_TEST(endian) \
do { \
@@ -108,6 +156,106 @@ void tst_QtEndian::fromLittleEndian()
#undef ENDIAN_TEST
+template <typename T>
+void transformRegion_template(T (*transformOne)(T), void (*transformRegion)(const void *, qsizetype, void *))
+{
+ enum { Size = 64 };
+ T source[Size];
+ T dest[Size];
+ T expected = transformOne(getData<T>(inNativeEndian));
+ std::fill_n(source, +Size, getData<T>(inNativeEndian));
+ memset(dest, 0, sizeof(dest));
+
+ auto checkBounds = [&](int from) {
+ for ( ; from < Size; ++from)
+ QCOMPARE(dest[from], T(0));
+ };
+
+ transformRegion(source, 1, dest);
+ QCOMPARE(dest[0], expected);
+ checkBounds(1);
+ memset(dest, 0, sizeof(T));
+
+ transformRegion(source, 2, dest);
+ QCOMPARE(dest[0], expected);
+ QCOMPARE(dest[1], expected);
+ checkBounds(2);
+ memset(dest, 0, sizeof(T) * 2);
+
+ transformRegion(source, 3, dest);
+ QCOMPARE(dest[0], expected);
+ QCOMPARE(dest[1], expected);
+ QCOMPARE(dest[2], expected);
+ checkBounds(3);
+ memset(dest, 0, sizeof(T) * 3);
+
+ transformRegion(source, 4, dest);
+ QCOMPARE(dest[0], expected);
+ QCOMPARE(dest[1], expected);
+ QCOMPARE(dest[2], expected);
+ QCOMPARE(dest[3], expected);
+ checkBounds(4);
+ memset(dest, 0, sizeof(T) * 4);
+
+ transformRegion(source, 8, dest);
+ for (int i = 0; i < 8; ++i)
+ QCOMPARE(dest[i], expected);
+ checkBounds(8);
+ memset(dest, 0, sizeof(T) * 8);
+
+ transformRegion(source, 16, dest);
+ for (int i = 0; i < 16; ++i)
+ QCOMPARE(dest[i], expected);
+ checkBounds(16);
+ memset(dest, 0, sizeof(T) * 16);
+
+ transformRegion(source, 32, dest);
+ for (int i = 0; i < 32; ++i)
+ QCOMPARE(dest[i], expected);
+ checkBounds(32);
+ memset(dest, 0, sizeof(T) * 32);
+
+ transformRegion(source, 64, dest);
+ for (int i = 0; i < 64; ++i)
+ QCOMPARE(dest[i], expected);
+
+ // check transforming in-place
+ memcpy(dest, source, sizeof(dest));
+ transformRegion(dest, 64, dest);
+ for (int i = 0; i < 64; ++i)
+ QCOMPARE(dest[i], expected);
+}
+
+void tst_QtEndian::fromBigEndianRegion_data()
+{
+ QTest::addColumn<int>("size");
+ QTest::newRow("1") << 1;
+ QTest::newRow("2") << 2;
+ QTest::newRow("4") << 4;
+ QTest::newRow("8") << 8;
+}
+
+void tst_QtEndian::fromBigEndianRegion()
+{
+ QFETCH(int, size);
+ switch (size) {
+ case 1: return transformRegion_template<quint8>(qFromBigEndian<quint8>, qFromBigEndian<quint8>);
+ case 2: return transformRegion_template<quint16>(qFromBigEndian<quint16>, qFromBigEndian<quint16>);
+ case 4: return transformRegion_template<quint32>(qFromBigEndian<quint32>, qFromBigEndian<quint32>);
+ case 8: return transformRegion_template<quint64>(qFromBigEndian<quint64>, qFromBigEndian<quint64>);
+ }
+}
+
+void tst_QtEndian::fromLittleEndianRegion()
+{
+ QFETCH(int, size);
+ switch (size) {
+ case 1: return transformRegion_template<quint8>(qFromLittleEndian<quint8>, qFromLittleEndian<quint8>);
+ case 2: return transformRegion_template<quint16>(qFromLittleEndian<quint16>, qFromLittleEndian<quint16>);
+ case 4: return transformRegion_template<quint32>(qFromLittleEndian<quint32>, qFromLittleEndian<quint32>);
+ case 8: return transformRegion_template<quint64>(qFromLittleEndian<quint64>, qFromLittleEndian<quint64>);
+ }
+}
#define ENDIAN_TEST(endian, type, size) \
do { \
@@ -135,6 +283,28 @@ void tst_QtEndian::toLittleEndian()
#undef ENDIAN_TEST
+void tst_QtEndian::toBigEndianRegion()
+{
+ QFETCH(int, size);
+ switch (size) {
+ case 1: return transformRegion_template<quint8>(qToBigEndian<quint8>, qToBigEndian<quint8>);
+ case 2: return transformRegion_template<quint16>(qToBigEndian<quint16>, qToBigEndian<quint16>);
+ case 4: return transformRegion_template<quint32>(qToBigEndian<quint32>, qToBigEndian<quint32>);
+ case 8: return transformRegion_template<quint64>(qToBigEndian<quint64>, qToBigEndian<quint64>);
+ }
+}
+
+void tst_QtEndian::toLittleEndianRegion()
+{
+ QFETCH(int, size);
+ switch (size) {
+ case 1: return transformRegion_template<quint8>(qToLittleEndian<quint8>, qToLittleEndian<quint8>);
+ case 2: return transformRegion_template<quint16>(qToLittleEndian<quint16>, qToLittleEndian<quint16>);
+ case 4: return transformRegion_template<quint32>(qToLittleEndian<quint32>, qToLittleEndian<quint32>);
+ case 8: return transformRegion_template<quint64>(qToLittleEndian<quint64>, qToLittleEndian<quint64>);
+ }
+}
+
void tst_QtEndian::endianIntegers_data()
{
QTest::addColumn<int>("val");
diff --git a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
index b43ea7cfa5..7b8b1df166 100644
--- a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
+++ b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
@@ -38,6 +38,13 @@
class tst_QDebug: public QObject
{
Q_OBJECT
+public:
+ enum EnumType { EnumValue1 = 1, EnumValue2 = 2 };
+ enum FlagType { EnumFlag1 = 1, EnumFlag2 = 2 };
+ Q_ENUM(EnumType)
+ Q_DECLARE_FLAGS(Flags, FlagType)
+ Q_FLAG(Flags)
+
private slots:
void assignment() const;
void warningWithoutDebug() const;
@@ -637,6 +644,15 @@ void tst_QDebug::qDebugQFlags() const
QCOMPARE(s_line, line);
QCOMPARE(QString::fromLatin1(s_function), function);
+ // Test the output of QFlags with an enum not declared with Q_DECLARE_FLAGS and Q_FLAGS
+ QFlags<EnumType> flags2(EnumValue2);
+ qDebug() << flags2;
+ QCOMPARE(s_msg, QString::fromLatin1("QFlags<tst_QDebug::EnumType>(EnumValue2)"));
+
+ // A now for one that was fully declared
+ tst_QDebug::Flags flags3(EnumFlag1);
+ qDebug() << flags3;
+ QCOMPARE(s_msg, QString::fromLatin1("QFlags<tst_QDebug::FlagType>(EnumFlag1)"));
}
void tst_QDebug::textStreamModifiers() const
diff --git a/tests/auto/corelib/io/qdir/tst_qdir.cpp b/tests/auto/corelib/io/qdir/tst_qdir.cpp
index afa15fe895..30f0e447ad 100644
--- a/tests/auto/corelib/io/qdir/tst_qdir.cpp
+++ b/tests/auto/corelib/io/qdir/tst_qdir.cpp
@@ -33,7 +33,6 @@
#include <qdebug.h>
#include <qdir.h>
#include <qfileinfo.h>
-#include <qregexp.h>
#include <qstringlist.h>
#if defined(Q_OS_WIN)
diff --git a/tests/auto/corelib/io/qfile/.gitignore b/tests/auto/corelib/io/qfile/.gitignore
index c508239722..615264e4d4 100644
--- a/tests/auto/corelib/io/qfile/.gitignore
+++ b/tests/auto/corelib/io/qfile/.gitignore
@@ -1,6 +1,10 @@
tst_qfile
-stdinprocess/stdinprocess
-stdinprocess/stdinprocess.exe
+stdinprocess_helper
+stdinprocess_helper.exe
+debug/stdinprocess_helper
+debug/stdinprocess_helper.exe
+release/stdinprocess_helper
+release/stdinprocess_helper.exe
readonlyfile
newfile.txt
appendfile.txt
diff --git a/tests/auto/corelib/io/qfile/qfile.pro b/tests/auto/corelib/io/qfile/qfile.pro
index 0735daedb3..91c5c15f66 100644
--- a/tests/auto/corelib/io/qfile/qfile.pro
+++ b/tests/auto/corelib/io/qfile/qfile.pro
@@ -1,2 +1,3 @@
TEMPLATE = subdirs
-SUBDIRS = test stdinprocess
+SUBDIRS = test.pro
+!winrt: SUBDIRS += stdinprocess
diff --git a/tests/auto/corelib/io/qfile/stdinprocess/main.cpp b/tests/auto/corelib/io/qfile/stdinprocess/main.cpp
index 6ff42c2485..77a1932bd5 100644
--- a/tests/auto/corelib/io/qfile/stdinprocess/main.cpp
+++ b/tests/auto/corelib/io/qfile/stdinprocess/main.cpp
@@ -33,7 +33,7 @@
int main(int argc, char *argv[])
{
if (argc < 2) {
- printf("usage: stdinprocess <all|line <0|1>>\n");
+ printf("usage: stdinprocess_helper <all|line <0|1>>\n");
printf("echos all its input to its output.\n");
return 1;
}
diff --git a/tests/auto/corelib/io/qfile/stdinprocess/stdinprocess.pro b/tests/auto/corelib/io/qfile/stdinprocess/stdinprocess.pro
index 8e463e4cef..512da8939b 100644
--- a/tests/auto/corelib/io/qfile/stdinprocess/stdinprocess.pro
+++ b/tests/auto/corelib/io/qfile/stdinprocess/stdinprocess.pro
@@ -1,8 +1,4 @@
SOURCES += main.cpp
QT = core
-CONFIG -= app_bundle debug_and_release_target
-CONFIG += console
-# This app is testdata for tst_qfile
-target.path = $$[QT_INSTALL_TESTS]/tst_qfile/$$TARGET
-INSTALLS += target
+load(qt_test_helper)
diff --git a/tests/auto/corelib/io/qfile/test.pro b/tests/auto/corelib/io/qfile/test.pro
new file mode 100644
index 0000000000..95389ab3e2
--- /dev/null
+++ b/tests/auto/corelib/io/qfile/test.pro
@@ -0,0 +1,26 @@
+CONFIG += testcase
+QT = core-private testlib
+qtHaveModule(network): QT += network
+else: DEFINES += QT_NO_NETWORK
+
+contains(CONFIG, builtin_testdata) {
+ DEFINES += BUILTIN_TESTDATA
+}
+
+TESTDATA += BLACKLIST
+
+TARGET = tst_qfile
+
+SOURCES = tst_qfile.cpp
+INCLUDEPATH += ../../../../shared/
+HEADERS += ../../../../shared/emulationdetector.h
+
+RESOURCES += qfile.qrc rename-fallback.qrc copy-fallback.qrc
+
+TESTDATA += \
+ dosfile.txt noendofline.txt testfile.txt \
+ testlog.txt two.dots.file tst_qfile.cpp \
+ Makefile forCopying.txt forRenaming.txt \
+ resources/file1.ext1
+
+win32:!winrt: LIBS += -lole32 -luuid
diff --git a/tests/auto/corelib/io/qfile/test/test.pro b/tests/auto/corelib/io/qfile/test/test.pro
deleted file mode 100644
index 1472ddbb83..0000000000
--- a/tests/auto/corelib/io/qfile/test/test.pro
+++ /dev/null
@@ -1,25 +0,0 @@
-CONFIG += testcase
-CONFIG -= debug_and_release_target
-QT = core-private core testlib
-qtHaveModule(network): QT += network
-else: DEFINES += QT_NO_NETWORK
-
-contains(CONFIG, builtin_testdata) {
- DEFINES += BUILTIN_TESTDATA
-}
-
-TESTDATA += ../BLACKLIST
-
-TARGET = ../tst_qfile
-SOURCES = ../tst_qfile.cpp
-INCLUDEPATH += ../../../../../shared/
-HEADERS += ../../../../../shared/emulationdetector.h
-
-RESOURCES += ../qfile.qrc ../rename-fallback.qrc ../copy-fallback.qrc
-
-TESTDATA += ../dosfile.txt ../noendofline.txt ../testfile.txt \
- ../testlog.txt ../two.dots.file ../tst_qfile.cpp \
- ../Makefile ../forCopying.txt ../forRenaming.txt \
- ../resources/file1.ext1
-
-win32:!winrt: LIBS+=-lole32 -luuid
diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp
index 6665200585..678a80c3f7 100644
--- a/tests/auto/corelib/io/qfile/tst_qfile.cpp
+++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp
@@ -367,7 +367,7 @@ private:
QTemporaryDir m_temporaryDir;
const QString m_oldDir;
- QString m_stdinProcessDir;
+ QString m_stdinProcess;
QString m_testSourceFile;
QString m_testLogFile;
QString m_dosFile;
@@ -379,12 +379,6 @@ private:
QString m_noEndOfLineFile;
};
-#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
- #define STDINPROCESS_NAME "libstdinprocess.so"
-#else // !android || android_embedded
- #define STDINPROCESS_NAME "stdinprocess"
-#endif // android && !android_embededd
-
static const char noReadFile[] = "noreadfile";
static const char readOnlyFile[] = "readonlyfile";
@@ -455,11 +449,13 @@ void tst_QFile::initTestCase()
QVERIFY2(m_temporaryDir.isValid(), qPrintable(m_temporaryDir.errorString()));
#if QT_CONFIG(process)
#if defined(Q_OS_ANDROID)
- m_stdinProcessDir = QCoreApplication::applicationDirPath();
+ m_stdinProcess = QCoreApplication::applicationDirPath() + QLatin1String("/libstdinprocess_helper.so");
+#elif defined(Q_OS_WIN)
+ m_stdinProcess = QFINDTESTDATA("stdinprocess_helper.exe");
#else
- m_stdinProcessDir = QFINDTESTDATA("stdinprocess");
+ m_stdinProcess = QFINDTESTDATA("stdinprocess_helper");
#endif
- QVERIFY(!m_stdinProcessDir.isEmpty());
+ QVERIFY(!m_stdinProcess.isEmpty());
#endif
m_testLogFile = QFINDTESTDATA("testlog.txt");
QVERIFY(!m_testLogFile.isEmpty());
@@ -981,7 +977,7 @@ void tst_QFile::readAllStdin()
QProcess process;
StdinReaderProcessGuard processGuard(&process);
- process.start(m_stdinProcessDir + QStringLiteral("/" STDINPROCESS_NAME), QStringList(QStringLiteral("all")));
+ process.start(m_stdinProcess, QStringList(QStringLiteral("all")));
QVERIFY2(process.waitForStarted(), qPrintable(process.errorString()));
for (int i = 0; i < 5; ++i) {
QTest::qWait(1000);
@@ -1014,7 +1010,7 @@ void tst_QFile::readLineStdin()
for (int i = 0; i < 2; ++i) {
QProcess process;
StdinReaderProcessGuard processGuard(&process);
- process.start(m_stdinProcessDir + QStringLiteral("/" STDINPROCESS_NAME),
+ process.start(m_stdinProcess,
QStringList() << QStringLiteral("line") << QString::number(i),
QIODevice::Text | QIODevice::ReadWrite);
QVERIFY2(process.waitForStarted(), qPrintable(process.errorString()));
@@ -1050,7 +1046,7 @@ void tst_QFile::readLineStdin_lineByLine()
for (int i = 0; i < 2; ++i) {
QProcess process;
StdinReaderProcessGuard processGuard(&process);
- process.start(m_stdinProcessDir + QStringLiteral("/" STDINPROCESS_NAME),
+ process.start(m_stdinProcess,
QStringList() << QStringLiteral("line") << QString::number(i),
QIODevice::Text | QIODevice::ReadWrite);
QVERIFY2(process.waitForStarted(), qPrintable(process.errorString()));
@@ -1297,6 +1293,12 @@ void tst_QFile::append()
f.putChar('a');
f.close();
QCOMPARE(int(f.size()), 2);
+
+ QVERIFY2(f.open(QIODevice::Append | QIODevice::Truncate), msgOpenFailed(f).constData());
+ QCOMPARE(f.pos(), 0);
+ f.putChar('a');
+ f.close();
+ QCOMPARE(int(f.size()), 1);
}
void tst_QFile::permissions_data()
@@ -1833,13 +1835,14 @@ void tst_QFile::encodeName()
void tst_QFile::truncate()
{
- for (int i = 0; i < 2; ++i) {
+ const QIODevice::OpenModeFlag modes[] = { QFile::ReadWrite, QIODevice::WriteOnly, QIODevice::Append };
+ for (auto mode : modes) {
QFile file("truncate.txt");
QVERIFY2(file.open(QFile::WriteOnly), msgOpenFailed(file).constData());
file.write(QByteArray(200, '@'));
file.close();
- QVERIFY2(file.open((i ? QFile::WriteOnly : QFile::ReadWrite) | QFile::Truncate), msgOpenFailed(file).constData());
+ QVERIFY2(file.open(mode | QFile::Truncate), msgOpenFailed(file).constData());
file.write(QByteArray(100, '$'));
file.close();
@@ -2210,7 +2213,8 @@ public:
uint ownerId(FileOwner) const { return 0; }
QString owner(FileOwner) const { return QString(); }
QDateTime fileTime(FileTime) const { return QDateTime(); }
- bool setFileTime(const QDateTime &newDate, FileTime time) { return false; }
+ bool setFileTime(const QDateTime &newDate, FileTime time)
+ { Q_UNUSED(newDate) Q_UNUSED(time) return false; }
private:
int number;
@@ -2755,19 +2759,20 @@ void tst_QFile::renameMultiple()
void tst_QFile::appendAndRead()
{
- QFile writeFile(QLatin1String("appendfile.txt"));
- QVERIFY2(writeFile.open(QIODevice::WriteOnly | QIODevice::Truncate), msgOpenFailed(writeFile).constData());
+ const QString fileName(QStringLiteral("appendfile.txt"));
+ QFile writeFile(fileName);
+ QVERIFY2(writeFile.open(QIODevice::Append | QIODevice::Truncate), msgOpenFailed(writeFile).constData());
- QFile readFile(QLatin1String("appendfile.txt"));
+ QFile readFile(fileName);
QVERIFY2(readFile.open(QIODevice::ReadOnly), msgOpenFailed(readFile).constData());
// Write to the end of the file, then read that character back, and so on.
for (int i = 0; i < 100; ++i) {
char c = '\0';
- writeFile.putChar(char(i % 256));
+ writeFile.putChar(char(i));
writeFile.flush();
QVERIFY(readFile.getChar(&c));
- QCOMPARE(c, char(i % 256));
+ QCOMPARE(c, char(i));
QCOMPARE(readFile.pos(), writeFile.pos());
}
@@ -2778,8 +2783,6 @@ void tst_QFile::appendAndRead()
writeFile.flush();
QCOMPARE(readFile.read(size).size(), size);
}
-
- readFile.close();
}
void tst_QFile::miscWithUncPathAsCurrentDir()
diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
index 87d5675e7a..017eebe153 100644
--- a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
+++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
@@ -199,7 +199,8 @@ private slots:
void fileTimes_data();
void fileTimes();
- void fileTimes_oldFile();
+ void fakeFileTimes_data();
+ void fakeFileTimes();
void isSymLink_data();
void isSymLink();
@@ -629,6 +630,16 @@ void tst_QFileInfo::canonicalFilePath()
info.canonicalFilePath();
#if defined(Q_OS_UNIX)
+ // If this file exists, you can't log in to run this test ...
+ const QString notExtantPath(QStringLiteral("/etc/nologin"));
+ QFileInfo notExtant(notExtantPath);
+ QCOMPARE(notExtant.canonicalFilePath(), QString());
+
+ // A path with a non-directory as a directory component also doesn't exist:
+ const QString badDirPath(QStringLiteral("/dev/null/sub/dir/n'existe.pas"));
+ QFileInfo badDir(badDirPath);
+ QCOMPARE(badDir.canonicalFilePath(), QString());
+
// This used to crash on Mac
QFileInfo dontCrash(QLatin1String("/"));
QCOMPARE(dontCrash.canonicalFilePath(), QLatin1String("/"));
@@ -1212,12 +1223,23 @@ void tst_QFileInfo::fileTimes()
QVERIFY(writeTime < beforeRead);
}
-void tst_QFileInfo::fileTimes_oldFile()
+void tst_QFileInfo::fakeFileTimes_data()
{
+ QTest::addColumn<QDateTime>("when");
+
// This is 2^{31} seconds before 1970-01-01 15:14:8,
// i.e. shortly after the start of time_t, in any time-zone:
- const QDateTime early(QDate(1901, 12, 14), QTime(12, 0));
- QFile file("ancientfile.txt");
+ QTest::newRow("early") << QDateTime(QDate(1901, 12, 14), QTime(12, 0));
+
+ // QTBUG-12006 claims XP handled this (2010-Mar-26 8:46:10) wrong due to an MS API bug:
+ QTest::newRow("XP-bug") << QDateTime::fromTime_t(1269593170);
+}
+
+void tst_QFileInfo::fakeFileTimes()
+{
+ QFETCH(QDateTime, when);
+
+ QFile file("faketimefile.txt");
file.open(QIODevice::WriteOnly);
file.write("\n", 1);
file.close();
@@ -1228,15 +1250,13 @@ void tst_QFileInfo::fileTimes_oldFile()
modification time, so need to re-open for read in order to setFileTime().
*/
file.open(QIODevice::ReadOnly);
- bool ok = file.setFileTime(early, QFileDevice::FileModificationTime);
+ bool ok = file.setFileTime(when, QFileDevice::FileModificationTime);
file.close();
- if (ok) {
- QFileInfo info(file.fileName());
- QCOMPARE(info.lastModified(), early);
- } else {
- QSKIP("Unable to set file metadata to ancient values");
- }
+ if (ok)
+ QCOMPARE(QFileInfo(file.fileName()).lastModified(), when);
+ else
+ QSKIP("Unable to set file metadata to contrived values");
}
void tst_QFileInfo::isSymLink_data()
diff --git a/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp b/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp
index fed05698fd..da5327594c 100644
--- a/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp
+++ b/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp
@@ -209,9 +209,6 @@ void tst_QIODevice::read_QByteArray()
//--------------------------------------------------------------------
void tst_QIODevice::unget()
{
-#if defined(Q_OS_MAC)
- QSKIP("The unget network test is unstable on Mac. See QTBUG-39983.");
-#endif
QBuffer buffer;
buffer.open(QBuffer::ReadWrite);
buffer.write("ZXCV");
diff --git a/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp b/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp
index 5b61a6007d..a10e706ed7 100644
--- a/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp
+++ b/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp
@@ -187,6 +187,13 @@ private slots:
"default=false");
QCOMPARE(parser.rules().size(), 1);
+ // QSettings escapes * to %2A when writing.
+ parser.setContent("[Rules]\n"
+ "module.%2A=false");
+ QCOMPARE(parser.rules().size(), 1);
+ QCOMPARE(parser.rules().first().category, QString("module."));
+ QCOMPARE(parser.rules().first().flags, QLoggingRule::LeftFilter);
+
parser.setContent("[OtherSection]\n"
"default=false");
QCOMPARE(parser.rules().size(), 0);
diff --git a/tests/auto/corelib/io/qnodebug/tst_qnodebug.cpp b/tests/auto/corelib/io/qnodebug/tst_qnodebug.cpp
index b78fa29fb6..17c51eaaf4 100644
--- a/tests/auto/corelib/io/qnodebug/tst_qnodebug.cpp
+++ b/tests/auto/corelib/io/qnodebug/tst_qnodebug.cpp
@@ -65,7 +65,7 @@ void tst_QNoDebug::streaming() const
{
QDateTime dt(QDate(1,2,3),QTime(4,5,6));
const QByteArray debugString = dt.toString(QStringViewLiteral("yyyy-MM-dd HH:mm:ss.zzz t")).toLatin1();
- const QByteArray message = "QDateTime(" + debugString + " Qt::TimeSpec(LocalTime))";
+ const QByteArray message = "QDateTime(" + debugString + " Qt::LocalTime)";
QTest::ignoreMessage(QtWarningMsg, message.constData());
qWarning() << dt;
}
diff --git a/tests/auto/corelib/io/qresourceengine/qresourceengine.pro b/tests/auto/corelib/io/qresourceengine/qresourceengine.pro
index e8071297b1..1e12a41dea 100644
--- a/tests/auto/corelib/io/qresourceengine/qresourceengine.pro
+++ b/tests/auto/corelib/io/qresourceengine/qresourceengine.pro
@@ -1,25 +1,2 @@
-CONFIG += testcase
-TARGET = tst_qresourceengine
-
-QT = core testlib
-SOURCES = tst_qresourceengine.cpp
-RESOURCES += testqrc/test.qrc
-
-qtPrepareTool(QMAKE_RCC, rcc, _DEP)
-runtime_resource.target = runtime_resource.rcc
-runtime_resource.depends = $$PWD/testqrc/test.qrc $$QMAKE_RCC_EXE
-runtime_resource.commands = $$QMAKE_RCC -root /runtime_resource/ -binary $$PWD/testqrc/test.qrc -o $${runtime_resource.target}
-QMAKE_EXTRA_TARGETS = runtime_resource
-PRE_TARGETDEPS += $${runtime_resource.target}
-QMAKE_DISTCLEAN += $${runtime_resource.target}
-
-TESTDATA += \
- parentdir.txt \
- testqrc/*
-GENERATED_TESTDATA = $${runtime_resource.target}
-
-android:!android-embedded {
- RESOURCES += android_testdata.qrc
-}
-
-builtin_testdata: DEFINES += BUILTIN_TESTDATA
+TEMPLATE = subdirs
+SUBDIRS = staticplugin qresourceengine_test.pro
diff --git a/tests/auto/corelib/io/qresourceengine/qresourceengine_test.pro b/tests/auto/corelib/io/qresourceengine/qresourceengine_test.pro
new file mode 100644
index 0000000000..3838a72c21
--- /dev/null
+++ b/tests/auto/corelib/io/qresourceengine/qresourceengine_test.pro
@@ -0,0 +1,33 @@
+CONFIG += testcase
+TARGET = tst_qresourceengine
+
+QT = core testlib
+SOURCES = tst_qresourceengine.cpp
+RESOURCES += testqrc/test.qrc
+
+qtPrepareTool(QMAKE_RCC, rcc, _DEP)
+runtime_resource.target = runtime_resource.rcc
+runtime_resource.depends = $$PWD/testqrc/test.qrc $$QMAKE_RCC_EXE
+runtime_resource.commands = $$QMAKE_RCC -root /runtime_resource/ -binary $$PWD/testqrc/test.qrc -o $${runtime_resource.target}
+QMAKE_EXTRA_TARGETS = runtime_resource
+PRE_TARGETDEPS += $${runtime_resource.target}
+QMAKE_DISTCLEAN += $${runtime_resource.target}
+
+TESTDATA += \
+ parentdir.txt \
+ testqrc/*
+GENERATED_TESTDATA = $${runtime_resource.target}
+
+android:!android-embedded {
+ RESOURCES += android_testdata.qrc
+}
+
+win32 {
+ CONFIG(debug, debug|release): LIBS += -Lstaticplugin/debug
+ else: LIBS += -Lstaticplugin/release
+} else {
+ LIBS += -Lstaticplugin
+}
+LIBS += -lmoctestplugin
+
+builtin_testdata: DEFINES += BUILTIN_TESTDATA
diff --git a/tests/auto/corelib/io/qresourceengine/staticplugin/.gitignore b/tests/auto/corelib/io/qresourceengine/staticplugin/.gitignore
new file mode 100644
index 0000000000..c397dde6a5
--- /dev/null
+++ b/tests/auto/corelib/io/qresourceengine/staticplugin/.gitignore
@@ -0,0 +1 @@
+moctestplugin_plugin_resources.cpp
diff --git a/tests/auto/corelib/io/qresourceengine/staticplugin/main.cpp b/tests/auto/corelib/io/qresourceengine/staticplugin/main.cpp
new file mode 100644
index 0000000000..39a3a1e012
--- /dev/null
+++ b/tests/auto/corelib/io/qresourceengine/staticplugin/main.cpp
@@ -0,0 +1,9 @@
+#include <QObject>
+
+class PluginClass : public QObject
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.tests.moc" FILE "staticplugin.json")
+};
+
+#include "main.moc"
diff --git a/tests/auto/corelib/io/qresourceengine/staticplugin/staticplugin.json b/tests/auto/corelib/io/qresourceengine/staticplugin/staticplugin.json
new file mode 100644
index 0000000000..4103ecb18c
--- /dev/null
+++ b/tests/auto/corelib/io/qresourceengine/staticplugin/staticplugin.json
@@ -0,0 +1 @@
+{ "Keys": [ "staticplugin" ] }
diff --git a/tests/auto/corelib/io/qresourceengine/staticplugin/staticplugin.pro b/tests/auto/corelib/io/qresourceengine/staticplugin/staticplugin.pro
new file mode 100644
index 0000000000..e19d884548
--- /dev/null
+++ b/tests/auto/corelib/io/qresourceengine/staticplugin/staticplugin.pro
@@ -0,0 +1,8 @@
+TEMPLATE = lib
+TARGET = moctestplugin
+CONFIG += plugin static
+SOURCES = main.cpp
+plugin_resource.files = main.cpp
+plugin_resource.prefix = /staticplugin
+RESOURCES += plugin_resource
+QT = core
diff --git a/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp b/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp
index b7e85e8f05..ab49dea6d8 100644
--- a/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp
+++ b/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp
@@ -57,6 +57,7 @@ private slots:
void doubleSlashInRoot();
void setLocale();
void lastModified();
+ void resourcesInStaticPlugins();
private:
const QString m_runtimeResourceRcc;
@@ -119,6 +120,7 @@ void tst_QResourceEngine::checkStructure_data()
<< QLatin1String("searchpath1")
<< QLatin1String("searchpath2")
<< QLatin1String("secondary_root")
+ << QLatin1String("staticplugin")
<< QLatin1String("test")
<< QLatin1String("withoutslashes");
@@ -127,7 +129,7 @@ void tst_QResourceEngine::checkStructure_data()
#endif
#if defined(BUILTIN_TESTDATA)
- rootContents.insert(8, QLatin1String("testqrc"));
+ rootContents.insert(9, QLatin1String("testqrc"));
#endif
@@ -520,6 +522,16 @@ void tst_QResourceEngine::lastModified()
}
}
+Q_IMPORT_PLUGIN(PluginClass)
+void tst_QResourceEngine::resourcesInStaticPlugins()
+{
+ // We built a separate static plugin and attempted linking against
+ // it. That should successfully register the resources linked into
+ // the plugin via moc generated Q_INIT_RESOURCE calls in a
+ // Q_CONSTRUCTOR_FUNCTION.
+ QVERIFY(QFile::exists(":/staticplugin/main.cpp"));
+}
+
QTEST_MAIN(tst_QResourceEngine)
#include "tst_qresourceengine.moc"
diff --git a/tests/auto/corelib/io/qsettings/qsettings.pro b/tests/auto/corelib/io/qsettings/qsettings.pro
index 5b4cc8a691..79552b62df 100644
--- a/tests/auto/corelib/io/qsettings/qsettings.pro
+++ b/tests/auto/corelib/io/qsettings/qsettings.pro
@@ -6,4 +6,6 @@ RESOURCES += qsettings.qrc
INCLUDEPATH += $$PWD/../../kernel/qmetatype
msvc: LIBS += advapi32.lib
+darwin: LIBS += -framework CoreFoundation
+
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
index db756ada39..5357194406 100644
--- a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
+++ b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
@@ -531,7 +531,7 @@ void tst_QSettings::ctor()
// more details in QMacSettingsPrivate::QMacSettingsPrivate(), organization was comify()-ed
caseSensitive = settings5.fileName().contains("SoftWare.ORG");;
} else {
- caseSensitive = pathconf(QDir::currentPath().toLatin1().constData(), _PC_CASE_SENSITIVE);
+ caseSensitive = pathconf(settings5.fileName().toLatin1().constData(), _PC_CASE_SENSITIVE);
}
#elif defined(Q_OS_WIN32) || defined(Q_OS_WINRT)
caseSensitive = false;
@@ -1186,6 +1186,10 @@ static void testMetaTypesHelper(QSettings::Format format)
F(QJsonArray) \
F(QJsonDocument) \
F(QPersistentModelIndex) \
+ F(QCborSimpleType) \
+ F(QCborValue) \
+ F(QCborArray) \
+ F(QCborMap) \
#define EXCLUDE_NON_SUPPORTED_METATYPES(MetaTypeName) \
template<> void testMetaTypesHelper<QMetaType::MetaTypeName>(QSettings::Format) \
diff --git a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp
index 3de777653e..5cb130f631 100644
--- a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp
+++ b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp
@@ -183,12 +183,14 @@ void tst_qstandardpaths::testDefaultLocations()
#endif
}
+#ifdef Q_XDG_PLATFORM
static void createTestFile(const QString &fileName)
{
QFile file(fileName);
QVERIFY(file.open(QIODevice::WriteOnly));
QVERIFY(file.write("Hello"));
}
+#endif
void tst_qstandardpaths::testCustomLocations()
{
diff --git a/tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp b/tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp
index 8b1aa105de..1317489e2f 100644
--- a/tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp
+++ b/tests/auto/corelib/io/qstorageinfo/tst_qstorageinfo.cpp
@@ -80,7 +80,7 @@ static int qInfoPrinter(const char *format, ...)
// flush
QtMessageHandler qt_message_print = qInstallMessageHandler(0);
qInstallMessageHandler(qt_message_print); // restore the handler
- qt_message_print(QtInfoMsg, QMessageLogContext(), QString::fromLocal8Bit(buf));
+ qt_message_print(QtInfoMsg, QMessageLogContext(), QString::fromLocal8Bit(buf).trimmed());
bufuse = 0;
}
diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp
index 62af907037..84af1c255a 100644
--- a/tests/auto/corelib/io/qurl/tst_qurl.cpp
+++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp
@@ -180,6 +180,8 @@ private slots:
void testThreading();
void matches_data();
void matches();
+ void ipv6_zoneId_data();
+ void ipv6_zoneId();
private:
void testThreadingHelper();
@@ -1876,6 +1878,24 @@ void tst_QUrl::ipv6_data()
QTest::newRow("encoded-digit") << "//[::%31]" << true << "//[::1]";
QTest::newRow("encoded-colon") << "//[%3A%3A]" << true << "//[::]";
+
+ QTest::newRow("full ipv6 with zone id (decoded %)") << QString::fromLatin1("//[56:56:56:56:56:56:56:56%eth0]") << true
+ << "//[56:56:56:56:56:56:56:56%25eth0]";
+
+ QTest::newRow("full ipv6 with zone id (encoded %)") << QString::fromLatin1("//[56:56:56:56:56:56:56:56%25eth0]") << true
+ << "//[56:56:56:56:56:56:56:56%25eth0]";
+
+ QTest::newRow("full ipv6 with invalid zone id") << QString::fromLatin1("//[56:56:56:56:56:56:56:56%]") << false << "";
+
+ QTest::newRow("full ipv6 with invalid zone id (encoded)") << QString::fromLatin1("//[56:56:56:56:56:56:56:56%25]") << false << "";
+
+ QTest::newRow("full ipv6 with zone id 25 (encoded)") << QString::fromLatin1("//[56:56:56:56:56:56:56:56%2525]") << true << "//[56:56:56:56:56:56:56:56%2525]";
+
+ QTest::newRow("case 4 with less and ip4 and port and useinfo and zone id")
+ << QString::fromLatin1("//user:pass@[56::56:56:56:127.0.0.1%ethernet_1]:99") << true
+ << "//user:pass@[56::56:56:56:7f00:1%25ethernet_1]:99";
+
+ QTest::newRow("encoded-digit including zone id") << "//[::%31%25eth0]" << true << "//[::1%25eth0]";
}
void tst_QUrl::ipv6()
@@ -4149,6 +4169,38 @@ void tst_QUrl::matches()
QCOMPARE(urlOne.matches(urlTwo, QUrl::FormattingOptions(options)), matches);
}
+void tst_QUrl::ipv6_zoneId_data()
+{
+ QTest::addColumn<QUrl>("url");
+ QTest::addColumn<QString>("decodedHost");
+ QTest::addColumn<QString>("prettyHost");
+ QTest::addColumn<QString>("encodedHost");
+
+ QTest::newRow("digit") << QUrl("x://[::%251]") << "::%1" << "::%251" << "::%251";
+ QTest::newRow("eth0") << QUrl("x://[::%25eth0]") << "::%eth0" << "::%25eth0" << "::%25eth0";
+ QTest::newRow("space") << QUrl("x://[::%25%20]") << "::% " << "::%25 " << "::%25%20";
+ QTest::newRow("subdelims") << QUrl("x://[::%25eth%2B]") << "::%eth+" << "::%25eth%2B" << "::%25eth%2B";
+ QTest::newRow("other") << QUrl("x://[::%25^]") << "::%^" << "::%25%5E" << "::%25%5E";
+ QTest::newRow("control") << QUrl("x://[::%25%7F]") << "::%\x7f" << "::%25%7F" << "::%25%7F";
+ QTest::newRow("unicode") << QUrl("x://[::%25wlán0]") << "::%wlán0" << "::%25wlán0" << "::%25wl%C3%A1n0";
+ QTest::newRow("non-utf8") << QUrl("x://[::%25%80]") << QString("::%") + QChar(QChar::ReplacementCharacter) << "::%25%80" << "::%25%80";
+ }
+
+void tst_QUrl::ipv6_zoneId()
+{
+ QFETCH(QUrl, url);
+ QFETCH(QString, decodedHost);
+ QFETCH(QString, prettyHost);
+ QFETCH(QString, encodedHost);
+
+ QVERIFY2(url.isValid(), qPrintable(url.errorString()));
+ QCOMPARE(url.host(QUrl::FullyDecoded), decodedHost);
+ QCOMPARE(url.host(), decodedHost);
+ QCOMPARE(url.host(QUrl::FullyEncoded), encodedHost);
+ QCOMPARE(url.toString(), "x://[" + prettyHost + "]");
+ QCOMPARE(url.toString(QUrl::FullyEncoded), "x://[" + encodedHost + "]");
+}
+
QTEST_MAIN(tst_QUrl)
#include "tst_qurl.moc"
diff --git a/tests/auto/corelib/itemmodels/itemmodels.pro b/tests/auto/corelib/itemmodels/itemmodels.pro
index a09f03a7b4..cca350ad43 100644
--- a/tests/auto/corelib/itemmodels/itemmodels.pro
+++ b/tests/auto/corelib/itemmodels/itemmodels.pro
@@ -1,9 +1,9 @@
TEMPLATE=subdirs
-SUBDIRS = qabstractitemmodel \
- qstringlistmodel \
+SUBDIRS = qstringlistmodel
qtHaveModule(gui): SUBDIRS += \
+ qabstractitemmodel \
qabstractproxymodel \
qidentityproxymodel \
qitemselectionmodel \
@@ -11,7 +11,8 @@ qtHaveModule(gui): SUBDIRS += \
qtHaveModule(widgets) {
SUBDIRS += \
- qsortfilterproxymodel
+ qsortfilterproxymodel_regexp \
+ qsortfilterproxymodel_regularexpression
qtHaveModule(sql): SUBDIRS += \
qitemmodel
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/.gitignore b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/.gitignore
deleted file mode 100644
index d3672fe4ae..0000000000
--- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-tst_qsortfilterproxymodel
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/qsortfilterproxymodel.pro b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/qsortfilterproxymodel.pro
deleted file mode 100644
index dfa8b9fa1b..0000000000
--- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/qsortfilterproxymodel.pro
+++ /dev/null
@@ -1,9 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qsortfilterproxymodel
-
-QT += widgets testlib
-mtdir = ../../../other/qabstractitemmodelutils
-
-INCLUDEPATH += $$PWD/$${mtdir}
-SOURCES += tst_qsortfilterproxymodel.cpp $${mtdir}/dynamictreemodel.cpp
-HEADERS += $${mtdir}/dynamictreemodel.h
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
deleted file mode 100644
index bced3f5790..0000000000
--- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
+++ /dev/null
@@ -1,4853 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtTest/QtTest>
-#include "dynamictreemodel.h"
-
-#include <QtCore/QCoreApplication>
-#include <QtGui/QStandardItem>
-#include <QtWidgets/QTreeView>
-#include <QtWidgets/QTableView>
-
-#include <qdebug.h>
-
-typedef QList<int> IntList;
-typedef QPair<int, int> IntPair;
-typedef QList<IntPair> IntPairList;
-
-Q_DECLARE_METATYPE(QList<QPersistentModelIndex>)
-
-class tst_QSortFilterProxyModel : public QObject
-{
- Q_OBJECT
-public:
- tst_QSortFilterProxyModel();
-
-public slots:
- void initTestCase();
- void cleanupTestCase();
- void cleanup();
-
-private slots:
- void getSetCheck();
- void sort_data();
- void sort();
- void sortHierarchy_data();
- void sortHierarchy();
-
- void insertRows_data();
- void insertRows();
- void prependRow();
- void removeRows_data();
- void removeRows();
- void removeColumns_data();
- void removeColumns();
- void insertAfterSelect();
- void removeAfterSelect();
- void filter_data();
- void filter();
- void filterHierarchy_data();
- void filterHierarchy();
- void filterColumns_data();
- void filterColumns();
-
- void filterTable();
- void filterCurrent();
- void filter_qtbug30662();
-
- void changeSourceLayout();
- void changeSourceLayoutFilteredOut();
- void removeSourceRows_data();
- void removeSourceRows();
- void insertSourceRows_data();
- void insertSourceRows();
- void changeFilter_data();
- void changeFilter();
- void changeSourceData_data();
- void changeSourceData();
- void changeSourceDataKeepsStableSorting_qtbug1548();
- void changeSourceDataForwardsRoles_qtbug35440();
- void resortingDoesNotBreakTreeModels();
- void dynamicFilterWithoutSort();
- void sortFilterRole();
- void selectionFilteredOut();
- void match_data();
- void match();
- void insertIntoChildrenlessItem();
- void invalidateMappedChildren();
- void insertRowIntoFilteredParent();
- void filterOutParentAndFilterInChild();
-
- void sourceInsertRows();
- void sourceModelDeletion();
-
- void sortColumnTracking1();
- void sortColumnTracking2();
-
- void sortStable();
-
- void hiddenColumns();
- void insertRowsSort();
- void staticSorting();
- void dynamicSorting();
- void fetchMore();
- void hiddenChildren();
- void mapFromToSource();
- void removeRowsRecursive();
- void doubleProxySelectionSetSourceModel();
- void appearsAndSort();
- void unnecessaryDynamicSorting();
- void unnecessaryMapCreation();
- void resetInvalidate_data();
- void resetInvalidate();
-
- void testMultipleProxiesWithSelection();
- void mapSelectionFromSource();
- void testResetInternalData();
- void filteredColumns();
- void headerDataChanged();
-
- void testParentLayoutChanged();
- void moveSourceRows();
-
- void hierarchyFilterInvalidation();
- void simpleFilterInvalidation();
-
- void chainedProxyModelRoleNames();
-
- void noMapAfterSourceDelete();
- void forwardDropApi();
- void canDropMimeData();
- void filterHint();
-
- void sourceLayoutChangeLeavesValidPersistentIndexes();
- void rowMoveLeavesValidPersistentIndexes();
-
- void emitLayoutChangedOnlyIfSortingChanged_data();
- void emitLayoutChangedOnlyIfSortingChanged();
-
- void checkSetNewModel();
- void filterAndInsertRow_data();
- void filterAndInsertRow();
- void filterAndInsertColumn_data();
- void filterAndInsertColumn();
-
-protected:
- void buildHierarchy(const QStringList &data, QAbstractItemModel *model);
- void checkHierarchy(const QStringList &data, const QAbstractItemModel *model);
-
-private:
- QStandardItemModel *m_model;
- QSortFilterProxyModel *m_proxy;
-};
-
-Q_DECLARE_METATYPE(QAbstractItemModel::LayoutChangeHint)
-
-// Testing get/set functions
-void tst_QSortFilterProxyModel::getSetCheck()
-{
- QSortFilterProxyModel obj1;
- QCOMPARE(obj1.sourceModel(), (QAbstractItemModel *)0);
- // int QSortFilterProxyModel::filterKeyColumn()
- // void QSortFilterProxyModel::setFilterKeyColumn(int)
- obj1.setFilterKeyColumn(0);
- QCOMPARE(0, obj1.filterKeyColumn());
- obj1.setFilterKeyColumn(INT_MIN);
- QCOMPARE(INT_MIN, obj1.filterKeyColumn());
- obj1.setFilterKeyColumn(INT_MAX);
- QCOMPARE(INT_MAX, obj1.filterKeyColumn());
-}
-
-tst_QSortFilterProxyModel::tst_QSortFilterProxyModel()
- : m_model(0), m_proxy(0)
-{
- qRegisterMetaType<QAbstractItemModel::LayoutChangeHint>();
-}
-
-void tst_QSortFilterProxyModel::initTestCase()
-{
- qRegisterMetaType<QList<QPersistentModelIndex> >();
- m_model = new QStandardItemModel(0, 1);
- m_proxy = new QSortFilterProxyModel();
- m_proxy->setSourceModel(m_model);
-}
-
-void tst_QSortFilterProxyModel::cleanupTestCase()
-{
- delete m_proxy;
- delete m_model;
-}
-
-void tst_QSortFilterProxyModel::cleanup()
-{
- m_proxy->setFilterRegExp(QRegExp());
- m_proxy->sort(-1, Qt::AscendingOrder);
- m_model->clear();
- m_model->insertColumns(0, 1);
-}
-
-/*
- tests
-*/
-
-void tst_QSortFilterProxyModel::sort_data()
-{
- QTest::addColumn<int>("sortOrder");
- QTest::addColumn<int>("sortCaseSensitivity");
- QTest::addColumn<QStringList>("initial");
- QTest::addColumn<QStringList>("expected");
-
- QTest::newRow("flat descending") << static_cast<int>(Qt::DescendingOrder)
- << int(Qt::CaseSensitive)
- << (QStringList()
- << "delta"
- << "yankee"
- << "bravo"
- << "lima"
- << "charlie"
- << "juliet"
- << "tango"
- << "hotel"
- << "uniform"
- << "alpha"
- << "echo"
- << "golf"
- << "quebec"
- << "foxtrot"
- << "india"
- << "romeo"
- << "november"
- << "oskar"
- << "zulu"
- << "kilo"
- << "whiskey"
- << "mike"
- << "papa"
- << "sierra"
- << "xray"
- << "viktor")
- << (QStringList()
- << "zulu"
- << "yankee"
- << "xray"
- << "whiskey"
- << "viktor"
- << "uniform"
- << "tango"
- << "sierra"
- << "romeo"
- << "quebec"
- << "papa"
- << "oskar"
- << "november"
- << "mike"
- << "lima"
- << "kilo"
- << "juliet"
- << "india"
- << "hotel"
- << "golf"
- << "foxtrot"
- << "echo"
- << "delta"
- << "charlie"
- << "bravo"
- << "alpha");
- QTest::newRow("flat ascending") << static_cast<int>(Qt::AscendingOrder)
- << int(Qt::CaseSensitive)
- << (QStringList()
- << "delta"
- << "yankee"
- << "bravo"
- << "lima"
- << "charlie"
- << "juliet"
- << "tango"
- << "hotel"
- << "uniform"
- << "alpha"
- << "echo"
- << "golf"
- << "quebec"
- << "foxtrot"
- << "india"
- << "romeo"
- << "november"
- << "oskar"
- << "zulu"
- << "kilo"
- << "whiskey"
- << "mike"
- << "papa"
- << "sierra"
- << "xray"
- << "viktor")
- << (QStringList()
- << "alpha"
- << "bravo"
- << "charlie"
- << "delta"
- << "echo"
- << "foxtrot"
- << "golf"
- << "hotel"
- << "india"
- << "juliet"
- << "kilo"
- << "lima"
- << "mike"
- << "november"
- << "oskar"
- << "papa"
- << "quebec"
- << "romeo"
- << "sierra"
- << "tango"
- << "uniform"
- << "viktor"
- << "whiskey"
- << "xray"
- << "yankee"
- << "zulu");
- QTest::newRow("case insensitive") << static_cast<int>(Qt::AscendingOrder)
- << int(Qt::CaseInsensitive)
- << (QStringList()
- << "alpha" << "BETA" << "Gamma" << "delta")
- << (QStringList()
- << "alpha" << "BETA" << "delta" << "Gamma");
- QTest::newRow("case sensitive") << static_cast<int>(Qt::AscendingOrder)
- << int(Qt::CaseSensitive)
- << (QStringList()
- << "alpha" << "BETA" << "Gamma" << "delta")
- << (QStringList()
- << "BETA" << "Gamma" << "alpha" << "delta");
-
- QStringList list;
- for (int i = 10000; i < 20000; ++i)
- list.append(QStringLiteral("Number: ") + QString::number(i));
- QTest::newRow("large set ascending") << static_cast<int>(Qt::AscendingOrder) << int(Qt::CaseSensitive) << list << list;
-}
-
-void tst_QSortFilterProxyModel::sort()
-{
- QFETCH(int, sortOrder);
- QFETCH(int, sortCaseSensitivity);
- QFETCH(QStringList, initial);
- QFETCH(QStringList, expected);
-
- // prepare model
- QStandardItem *root = m_model->invisibleRootItem ();
- QList<QStandardItem *> items;
- for (int i = 0; i < initial.count(); ++i) {
- items.append(new QStandardItem(initial.at(i)));
- }
- root->insertRows(0, items);
- QCOMPARE(m_model->rowCount(QModelIndex()), initial.count());
- QCOMPARE(m_model->columnCount(QModelIndex()), 1);
-
- // make sure the proxy is unsorted
- QCOMPARE(m_proxy->columnCount(QModelIndex()), 1);
- QCOMPARE(m_proxy->rowCount(QModelIndex()), initial.count());
- for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) {
- QModelIndex index = m_proxy->index(row, 0, QModelIndex());
- QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), initial.at(row));
- }
-
- // sort
- m_proxy->sort(0, static_cast<Qt::SortOrder>(sortOrder));
- m_proxy->setSortCaseSensitivity(static_cast<Qt::CaseSensitivity>(sortCaseSensitivity));
-
- // make sure the model is unchanged
- for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) {
- QModelIndex index = m_model->index(row, 0, QModelIndex());
- QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), initial.at(row));
- }
- // make sure the proxy is sorted
- for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) {
- QModelIndex index = m_proxy->index(row, 0, QModelIndex());
- QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), expected.at(row));
- }
-
- // restore the unsorted order
- m_proxy->sort(-1);
-
- // make sure the proxy is unsorted again
- for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) {
- QModelIndex index = m_proxy->index(row, 0, QModelIndex());
- QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), initial.at(row));
- }
-}
-
-void tst_QSortFilterProxyModel::sortHierarchy_data()
-{
- QTest::addColumn<int>("sortOrder");
- QTest::addColumn<QStringList>("initial");
- QTest::addColumn<QStringList>("expected");
-
- QTest::newRow("flat ascending")
- << static_cast<int>(Qt::AscendingOrder)
- << (QStringList()
- << "c" << "f" << "d" << "e" << "a" << "b")
- << (QStringList()
- << "a" << "b" << "c" << "d" << "e" << "f");
-
- QTest::newRow("simple hierarchy")
- << static_cast<int>(Qt::AscendingOrder)
- << (QStringList() << "a" << "<" << "b" << "<" << "c" << ">" << ">")
- << (QStringList() << "a" << "<" << "b" << "<" << "c" << ">" << ">");
-
- QTest::newRow("hierarchical ascending")
- << static_cast<int>(Qt::AscendingOrder)
- << (QStringList()
- << "c"
- << "<"
- << "h"
- << "<"
- << "2"
- << "0"
- << "1"
- << ">"
- << "g"
- << "i"
- << ">"
- << "b"
- << "<"
- << "l"
- << "k"
- << "<"
- << "8"
- << "7"
- << "9"
- << ">"
- << "m"
- << ">"
- << "a"
- << "<"
- << "z"
- << "y"
- << "x"
- << ">")
- << (QStringList()
- << "a"
- << "<"
- << "x"
- << "y"
- << "z"
- << ">"
- << "b"
- << "<"
- << "k"
- << "<"
- << "7"
- << "8"
- << "9"
- << ">"
- << "l"
- << "m"
- << ">"
- << "c"
- << "<"
- << "g"
- << "h"
- << "<"
- << "0"
- << "1"
- << "2"
- << ">"
- << "i"
- << ">");
-}
-
-void tst_QSortFilterProxyModel::sortHierarchy()
-{
- QFETCH(int, sortOrder);
- QFETCH(QStringList, initial);
- QFETCH(QStringList, expected);
-
- buildHierarchy(initial, m_model);
- checkHierarchy(initial, m_model);
- checkHierarchy(initial, m_proxy);
- m_proxy->sort(0, static_cast<Qt::SortOrder>(sortOrder));
- checkHierarchy(initial, m_model);
- checkHierarchy(expected, m_proxy);
-}
-
-void tst_QSortFilterProxyModel::insertRows_data()
-{
- QTest::addColumn<QStringList>("initial");
- QTest::addColumn<QStringList>("expected");
- QTest::addColumn<QStringList>("insert");
- QTest::addColumn<int>("position");
-
- QTest::newRow("insert one row in the middle")
- << (QStringList()
- << "One"
- << "Two"
- << "Four"
- << "Five")
- << (QStringList()
- << "One"
- << "Two"
- << "Three"
- << "Four"
- << "Five")
- << (QStringList()
- << "Three")
- << 2;
-
- QTest::newRow("insert one row in the beginning")
- << (QStringList()
- << "Two"
- << "Three"
- << "Four"
- << "Five")
- << (QStringList()
- << "One"
- << "Two"
- << "Three"
- << "Four"
- << "Five")
- << (QStringList()
- << "One")
- << 0;
-
- QTest::newRow("insert one row in the end")
- << (QStringList()
- << "One"
- << "Two"
- << "Three"
- << "Four")
- << (QStringList()
- << "One"
- << "Two"
- << "Three"
- << "Four"
- << "Five")
- << (QStringList()
- <<"Five")
- << 4;
-}
-
-void tst_QSortFilterProxyModel::insertRows()
-{
- QFETCH(QStringList, initial);
- QFETCH(QStringList, expected);
- QFETCH(QStringList, insert);
- QFETCH(int, position);
- // prepare model
- m_model->insertRows(0, initial.count(), QModelIndex());
- //m_model->insertColumns(0, 1, QModelIndex());
- QCOMPARE(m_model->columnCount(QModelIndex()), 1);
- QCOMPARE(m_model->rowCount(QModelIndex()), initial.count());
- for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) {
- QModelIndex index = m_model->index(row, 0, QModelIndex());
- m_model->setData(index, initial.at(row), Qt::DisplayRole);
- }
- // make sure the model correct before insert
- for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) {
- QModelIndex index = m_model->index(row, 0, QModelIndex());
- QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), initial.at(row));
- }
- // make sure the proxy is correct before insert
- for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) {
- QModelIndex index = m_proxy->index(row, 0, QModelIndex());
- QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), initial.at(row));
- }
-
- // insert the row
- m_proxy->insertRows(position, insert.count(), QModelIndex());
- QCOMPARE(m_model->rowCount(QModelIndex()), expected.count());
- QCOMPARE(m_proxy->rowCount(QModelIndex()), expected.count());
-
- // set the data for the inserted row
- for (int i = 0; i < insert.count(); ++i) {
- QModelIndex index = m_proxy->index(position + i, 0, QModelIndex());
- m_proxy->setData(index, insert.at(i), Qt::DisplayRole);
- }
-
- // make sure the model correct after insert
- for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) {
- QModelIndex index = m_model->index(row, 0, QModelIndex());
- QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), expected.at(row));
- }
-
- // make sure the proxy is correct after insert
- for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) {
- QModelIndex index = m_proxy->index(row, 0, QModelIndex());
- QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), expected.at(row));
- }
-}
-
-void tst_QSortFilterProxyModel::prependRow()
-{
- //this tests that data is correctly handled by the sort filter when prepending a row
- QStandardItemModel model;
- QSortFilterProxyModel proxy;
- proxy.setSourceModel(&model);
-
- QStandardItem item("root");
- model.appendRow(&item);
-
- QStandardItem sub("sub");
- item.appendRow(&sub);
-
- sub.appendRow(new QStandardItem("test1"));
- sub.appendRow(new QStandardItem("test2"));
-
- QStandardItem sub2("sub2");
- sub2.appendRow(new QStandardItem("sub3"));
- item.insertRow(0, &sub2);
-
- QModelIndex index_sub2 = proxy.mapFromSource(model.indexFromItem(&sub2));
-
- QCOMPARE(sub2.rowCount(), proxy.rowCount(index_sub2));
- QCOMPARE(proxy.rowCount(QModelIndex()), 1); //only the "root" item is there
-}
-
-void tst_QSortFilterProxyModel::removeRows_data()
-{
- QTest::addColumn<QStringList>("initial");
- QTest::addColumn<int>("sortOrder");
- QTest::addColumn<QString>("filter");
- QTest::addColumn<int>("position");
- QTest::addColumn<int>("count");
- QTest::addColumn<bool>("success");
- QTest::addColumn<QStringList>("expectedProxy");
- QTest::addColumn<QStringList>("expectedSource");
-
- QTest::newRow("remove one row in the middle [no sorting/filter]")
- << (QStringList()
- << "One"
- << "Two"
- << "Three"
- << "Four"
- << "Five")
- << -1 // no sorting
- << QString() // no filter
- << 2 // position
- << 1 // count
- << true // success
- << (QStringList() // expectedProxy
- << "One"
- << "Two"
- << "Four"
- << "Five")
- << (QStringList() // expectedSource
- << "One"
- << "Two"
- << "Four"
- << "Five");
-
- QTest::newRow("remove one row in the beginning [no sorting/filter]")
- << (QStringList()
- << "One"
- << "Two"
- << "Three"
- << "Four"
- << "Five")
- << -1 // no sorting
- << QString() // no filter
- << 0 // position
- << 1 // count
- << true // success
- << (QStringList() // expectedProxy
- << "Two"
- << "Three"
- << "Four"
- << "Five")
- << (QStringList() // expectedSource
- << "Two"
- << "Three"
- << "Four"
- << "Five");
-
- QTest::newRow("remove one row in the end [no sorting/filter]")
- << (QStringList()
- << "One"
- << "Two"
- << "Three"
- << "Four"
- << "Five")
- << -1 // no sorting
- << QString() // no filter
- << 4 // position
- << 1 // count
- << true // success
- << (QStringList() // expectedProxy
- << "One"
- << "Two"
- << "Three"
- << "Four")
- << (QStringList() // expectedSource
- << "One"
- << "Two"
- << "Three"
- << "Four");
-
- QTest::newRow("remove all [no sorting/filter]")
- << (QStringList()
- << "One"
- << "Two"
- << "Three"
- << "Four"
- << "Five")
- << -1 // no sorting
- << QString() // no filter
- << 0 // position
- << 5 // count
- << true // success
- << QStringList() // expectedProxy
- << QStringList(); // expectedSource
-
- QTest::newRow("remove one row past the end [no sorting/filter]")
- << (QStringList()
- << "One"
- << "Two"
- << "Three"
- << "Four"
- << "Five")
- << -1 // no sorting
- << QString() // no filter
- << 5 // position
- << 1 // count
- << false // success
- << (QStringList() // expectedProxy
- << "One"
- << "Two"
- << "Three"
- << "Four"
- << "Five")
- << (QStringList() // expectedSource
- << "One"
- << "Two"
- << "Three"
- << "Four"
- << "Five");
-
- QTest::newRow("remove row -1 [no sorting/filter]")
- << (QStringList()
- << "One"
- << "Two"
- << "Three"
- << "Four"
- << "Five")
- << -1 // no sorting
- << QString() // no filter
- << -1 // position
- << 1 // count
- << false // success
- << (QStringList() // expectedProxy
- << "One"
- << "Two"
- << "Three"
- << "Four"
- << "Five")
- << (QStringList() // expectedSource
- << "One"
- << "Two"
- << "Three"
- << "Four"
- << "Five");
-
- QTest::newRow("remove three rows in the middle [no sorting/filter]")
- << (QStringList()
- << "One"
- << "Two"
- << "Three"
- << "Four"
- << "Five")
- << -1 // no sorting
- << QString() // no filter
- << 1 // position
- << 3 // count
- << true // success
- << (QStringList() // expectedProxy
- << "One"
- << "Five")
- << (QStringList() // expectedSource
- << "One"
- << "Five");
-
- QTest::newRow("remove one row in the middle [ascending sorting, no filter]")
- << (QStringList()
- << "1"
- << "5"
- << "2"
- << "4"
- << "3")
- << static_cast<int>(Qt::AscendingOrder)
- << QString() // no filter
- << 2 // position
- << 1 // count
- << true // success
- << (QStringList() // expectedProxy
- << "1"
- << "2"
- << "4"
- << "5")
- << (QStringList() // expectedSource
- << "1"
- << "5"
- << "2"
- << "4");
-
- QTest::newRow("remove two rows in the middle [ascending sorting, no filter]")
- << (QStringList()
- << "1"
- << "5"
- << "2"
- << "4"
- << "3")
- << static_cast<int>(Qt::AscendingOrder)
- << QString() // no filter
- << 2 // position
- << 2 // count
- << true // success
- << (QStringList() // expectedProxy
- << "1"
- << "2"
- << "5")
- << (QStringList() // expectedSource
- << "1"
- << "5"
- << "2");
-
- QTest::newRow("remove two rows in the middle [descending sorting, no filter]")
- << (QStringList()
- << "1"
- << "5"
- << "2"
- << "4"
- << "3")
- << static_cast<int>(Qt::DescendingOrder)
- << QString() // no filter
- << 2 // position
- << 2 // count
- << true // success
- << (QStringList() // expectedProxy
- << "5"
- << "4"
- << "1")
- << (QStringList() // expectedSource
- << "1"
- << "5"
- << "4");
-
- QTest::newRow("remove one row in the middle [no sorting, filter=5|2|3]")
- << (QStringList()
- << "1"
- << "5"
- << "2"
- << "4"
- << "3")
- << -1 // no sorting
- << QString("5|2|3")
- << 1 // position
- << 1 // count
- << true // success
- << (QStringList() // expectedProxy
- << "5"
- << "3")
- << (QStringList() // expectedSource
- << "1"
- << "5"
- << "4"
- << "3");
-
- QTest::newRow("remove all [ascending sorting, no filter]")
- << (QStringList()
- << "1"
- << "5"
- << "2"
- << "4"
- << "3")
- << static_cast<int>(Qt::AscendingOrder)
- << QString() // no filter
- << 0 // position
- << 5 // count
- << true // success
- << QStringList() // expectedProxy
- << QStringList(); // expectedSource
-}
-
-void tst_QSortFilterProxyModel::removeRows()
-{
- QFETCH(QStringList, initial);
- QFETCH(int, sortOrder);
- QFETCH(QString, filter);
- QFETCH(int, position);
- QFETCH(int, count);
- QFETCH(bool, success);
- QFETCH(QStringList, expectedProxy);
- QFETCH(QStringList, expectedSource);
-
- QStandardItemModel model;
- QSortFilterProxyModel proxy;
- proxy.setSourceModel(&model);
-
- // prepare model
- foreach (QString s, initial)
- model.appendRow(new QStandardItem(s));
-
- if (sortOrder != -1)
- proxy.sort(0, static_cast<Qt::SortOrder>(sortOrder));
- if (!filter.isEmpty())
- proxy.setFilterRegExp(QRegExp(filter));
-
- // remove the rows
- QCOMPARE(proxy.removeRows(position, count, QModelIndex()), success);
- QCOMPARE(model.rowCount(QModelIndex()), expectedSource.count());
- QCOMPARE(proxy.rowCount(QModelIndex()), expectedProxy.count());
-
- // make sure the model is correct after remove
- for (int row = 0; row < model.rowCount(QModelIndex()); ++row)
- QCOMPARE(model.item(row)->text(), expectedSource.at(row));
-
- // make sure the proxy is correct after remove
- for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) {
- QModelIndex index = proxy.index(row, 0, QModelIndex());
- QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expectedProxy.at(row));
- }
-}
-
-class MyFilteredColumnProxyModel : public QSortFilterProxyModel
-{
- Q_OBJECT
-public:
- MyFilteredColumnProxyModel(QObject *parent = 0)
- : QSortFilterProxyModel(parent) { }
-protected:
- bool filterAcceptsColumn(int sourceColumn, const QModelIndex &) const
- {
- QString key = sourceModel()->headerData(sourceColumn, Qt::Horizontal).toString();
- return key.contains(filterRegExp());
- }
-};
-
-void tst_QSortFilterProxyModel::removeColumns_data()
-{
- QTest::addColumn<QStringList>("initial");
- QTest::addColumn<QString>("filter");
- QTest::addColumn<int>("position");
- QTest::addColumn<int>("count");
- QTest::addColumn<bool>("success");
- QTest::addColumn<QStringList>("expectedProxy");
- QTest::addColumn<QStringList>("expectedSource");
-
- QTest::newRow("remove one column in the middle [no filter]")
- << (QStringList()
- << "1"
- << "2"
- << "3"
- << "4"
- << "5")
- << QString() // no filter
- << 2 // position
- << 1 // count
- << true // success
- << (QStringList() // expectedProxy
- << "1"
- << "2"
- << "4"
- << "5")
- << (QStringList() // expectedSource
- << "1"
- << "2"
- << "4"
- << "5");
-
- QTest::newRow("remove one column in the end [no filter]")
- << (QStringList()
- << "1"
- << "2"
- << "3"
- << "4"
- << "5")
- << QString() // no filter
- << 4 // position
- << 1 // count
- << true // success
- << (QStringList() // expectedProxy
- << "1"
- << "2"
- << "3"
- << "4")
- << (QStringList() // expectedSource
- << "1"
- << "2"
- << "3"
- << "4");
-
- QTest::newRow("remove one column past the end [no filter]")
- << (QStringList()
- << "1"
- << "2"
- << "3"
- << "4"
- << "5")
- << QString() // no filter
- << 5 // position
- << 1 // count
- << false // success
- << (QStringList() // expectedProxy
- << "1"
- << "2"
- << "3"
- << "4"
- << "5")
- << (QStringList() // expectedSource
- << "1"
- << "2"
- << "3"
- << "4"
- << "5");
-
- QTest::newRow("remove column -1 [no filter]")
- << (QStringList()
- << "1"
- << "2"
- << "3"
- << "4"
- << "5")
- << QString() // no filter
- << -1 // position
- << 1 // count
- << false // success
- << (QStringList() // expectedProxy
- << "1"
- << "2"
- << "3"
- << "4"
- << "5")
- << (QStringList() // expectedSource
- << "1"
- << "2"
- << "3"
- << "4"
- << "5");
-
- QTest::newRow("remove all columns [no filter]")
- << (QStringList()
- << "1"
- << "2"
- << "3"
- << "4"
- << "5")
- << QString() // no filter
- << 0 // position
- << 5 // count
- << true // success
- << QStringList() // expectedProxy
- << QStringList(); // expectedSource
-
- QTest::newRow("remove one column in the middle [filter=1|3|5]")
- << (QStringList()
- << "1"
- << "2"
- << "3"
- << "4"
- << "5")
- << QString("1|3|5")
- << 1 // position
- << 1 // count
- << true // success
- << (QStringList() // expectedProxy
- << "1"
- << "5")
- << (QStringList() // expectedSource
- << "1"
- << "2"
- << "4"
- << "5");
-
- QTest::newRow("remove one column in the end [filter=1|3|5]")
- << (QStringList()
- << "1"
- << "2"
- << "3"
- << "4"
- << "5")
- << QString("1|3|5")
- << 2 // position
- << 1 // count
- << true // success
- << (QStringList() // expectedProxy
- << "1"
- << "3")
- << (QStringList() // expectedSource
- << "1"
- << "2"
- << "3"
- << "4");
-
- QTest::newRow("remove one column past the end [filter=1|3|5]")
- << (QStringList()
- << "1"
- << "2"
- << "3"
- << "4"
- << "5")
- << QString("1|3|5")
- << 3 // position
- << 1 // count
- << false // success
- << (QStringList() // expectedProxy
- << "1"
- << "3"
- << "5")
- << (QStringList() // expectedSource
- << "1"
- << "2"
- << "3"
- << "4"
- << "5");
-
- QTest::newRow("remove all columns [filter=1|3|5]")
- << (QStringList()
- << "1"
- << "2"
- << "3"
- << "4"
- << "5")
- << QString("1|3|5")
- << 0 // position
- << 3 // count
- << true // success
- << QStringList() // expectedProxy
- << (QStringList() // expectedSource
- << "2"
- << "4");
-}
-
-void tst_QSortFilterProxyModel::removeColumns()
-{
- QFETCH(QStringList, initial);
- QFETCH(QString, filter);
- QFETCH(int, position);
- QFETCH(int, count);
- QFETCH(bool, success);
- QFETCH(QStringList, expectedProxy);
- QFETCH(QStringList, expectedSource);
-
- QStandardItemModel model;
- MyFilteredColumnProxyModel proxy;
- proxy.setSourceModel(&model);
- if (!filter.isEmpty())
- proxy.setFilterRegExp(QRegExp(filter));
-
- // prepare model
- model.setHorizontalHeaderLabels(initial);
-
- // remove the columns
- QCOMPARE(proxy.removeColumns(position, count, QModelIndex()), success);
- QCOMPARE(model.columnCount(QModelIndex()), expectedSource.count());
- QCOMPARE(proxy.columnCount(QModelIndex()), expectedProxy.count());
-
- // make sure the model is correct after remove
- for (int col = 0; col < model.columnCount(QModelIndex()); ++col)
- QCOMPARE(model.horizontalHeaderItem(col)->text(), expectedSource.at(col));
-
- // make sure the proxy is correct after remove
- for (int col = 0; col < proxy.columnCount(QModelIndex()); ++col) {
- QCOMPARE(proxy.headerData(col, Qt::Horizontal, Qt::DisplayRole).toString(),
- expectedProxy.at(col));
- }
-}
-
-void tst_QSortFilterProxyModel::filterColumns_data()
-{
- QTest::addColumn<QString>("pattern");
- QTest::addColumn<QStringList>("initial");
- QTest::addColumn<bool>("data");
-
- QTest::newRow("all") << "a"
- << (QStringList()
- << "delta"
- << "yankee"
- << "bravo"
- << "lima")
- << true;
-
- QTest::newRow("some") << "lie"
- << (QStringList()
- << "charlie"
- << "juliet"
- << "tango"
- << "hotel")
- << true;
-
- QTest::newRow("nothing") << "zoo"
- << (QStringList()
- << "foxtrot"
- << "uniform"
- << "alpha"
- << "golf")
- << false;
-}
-
-void tst_QSortFilterProxyModel::filterColumns()
-{
- QFETCH(QString, pattern);
- QFETCH(QStringList, initial);
- QFETCH(bool, data);
- // prepare model
- m_model->setColumnCount(initial.count());
- m_model->setRowCount(1);
- QCOMPARE(m_model->columnCount(QModelIndex()), initial.count());
- QCOMPARE(m_model->rowCount(QModelIndex()), 1);
- // set data
- QCOMPARE(m_model->rowCount(QModelIndex()), 1);
- for (int col = 0; col < m_model->columnCount(QModelIndex()); ++col) {
- QModelIndex index = m_model->index(0, col, QModelIndex());
- m_model->setData(index, initial.at(col), Qt::DisplayRole);
- }
- m_proxy->setFilterRegExp(pattern);
- m_proxy->setFilterKeyColumn(-1);
- // make sure the model is unchanged
- for (int col = 0; col < m_model->columnCount(QModelIndex()); ++col) {
- QModelIndex index = m_model->index(0, col, QModelIndex());
- QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), initial.at(col));
- }
- // make sure the proxy is filtered
- QModelIndex index = m_proxy->index(0, 0, QModelIndex());
- QCOMPARE(index.isValid(), data);
-}
-
-void tst_QSortFilterProxyModel::filter_data()
-{
- QTest::addColumn<QString>("pattern");
- QTest::addColumn<QStringList>("initial");
- QTest::addColumn<QStringList>("expected");
-
- QTest::newRow("flat") << "e"
- << (QStringList()
- << "delta"
- << "yankee"
- << "bravo"
- << "lima"
- << "charlie"
- << "juliet"
- << "tango"
- << "hotel"
- << "uniform"
- << "alpha"
- << "echo"
- << "golf"
- << "quebec"
- << "foxtrot"
- << "india"
- << "romeo"
- << "november"
- << "oskar"
- << "zulu"
- << "kilo"
- << "whiskey"
- << "mike"
- << "papa"
- << "sierra"
- << "xray"
- << "viktor")
- << (QStringList()
- << "delta"
- << "yankee"
- << "charlie"
- << "juliet"
- << "hotel"
- << "echo"
- << "quebec"
- << "romeo"
- << "november"
- << "whiskey"
- << "mike"
- << "sierra");
-}
-
-void tst_QSortFilterProxyModel::filter()
-{
- QFETCH(QString, pattern);
- QFETCH(QStringList, initial);
- QFETCH(QStringList, expected);
- // prepare model
- QVERIFY(m_model->insertRows(0, initial.count(), QModelIndex()));
- QCOMPARE(m_model->rowCount(QModelIndex()), initial.count());
- // set data
- QCOMPARE(m_model->columnCount(QModelIndex()), 1);
- for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) {
- QModelIndex index = m_model->index(row, 0, QModelIndex());
- m_model->setData(index, initial.at(row), Qt::DisplayRole);
- }
- m_proxy->setFilterRegExp(pattern);
- // make sure the proxy is unfiltered
- QCOMPARE(m_proxy->columnCount(QModelIndex()), 1);
- QCOMPARE(m_proxy->rowCount(QModelIndex()), expected.count());
- // make sure the model is unchanged
- for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) {
- QModelIndex index = m_model->index(row, 0, QModelIndex());
- QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), initial.at(row));
- }
- // make sure the proxy is filtered
- for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) {
- QModelIndex index = m_proxy->index(row, 0, QModelIndex());
- QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), expected.at(row));
- }
-}
-
-void tst_QSortFilterProxyModel::filterHierarchy_data()
-{
- QTest::addColumn<QString>("pattern");
- QTest::addColumn<QStringList>("initial");
- QTest::addColumn<QStringList>("expected");
-
- QTest::newRow("flat") << ".*oo"
- << (QStringList()
- << "foo" << "boo" << "baz" << "moo" << "laa" << "haa")
- << (QStringList()
- << "foo" << "boo" << "moo");
-
- QTest::newRow("simple hierarchy") << "b.*z"
- << (QStringList() << "baz" << "<" << "boz" << "<" << "moo" << ">" << ">")
- << (QStringList() << "baz" << "<" << "boz" << ">");
-}
-
-void tst_QSortFilterProxyModel::filterHierarchy()
-{
- QFETCH(QString, pattern);
- QFETCH(QStringList, initial);
- QFETCH(QStringList, expected);
- buildHierarchy(initial, m_model);
- m_proxy->setFilterRegExp(pattern);
- checkHierarchy(initial, m_model);
- checkHierarchy(expected, m_proxy);
-}
-
-void tst_QSortFilterProxyModel::buildHierarchy(const QStringList &l, QAbstractItemModel *m)
-{
- int ind = 0;
- int row = 0;
- QStack<int> row_stack;
- QModelIndex parent;
- QStack<QModelIndex> parent_stack;
- for (int i = 0; i < l.count(); ++i) {
- QString token = l.at(i);
- if (token == QLatin1String("<")) { // start table
- ++ind;
- parent_stack.push(parent);
- row_stack.push(row);
- parent = m->index(row - 1, 0, parent);
- row = 0;
- QVERIFY(m->insertColumns(0, 1, parent)); // add column
- } else if (token == QLatin1String(">")) { // end table
- --ind;
- parent = parent_stack.pop();
- row = row_stack.pop();
- } else { // append row
- QVERIFY(m->insertRows(row, 1, parent));
- QModelIndex index = m->index(row, 0, parent);
- QVERIFY(index.isValid());
- m->setData(index, token, Qt::DisplayRole);
- ++row;
- }
- }
-}
-
-void tst_QSortFilterProxyModel::checkHierarchy(const QStringList &l, const QAbstractItemModel *m)
-{
- int row = 0;
- int indent = 0;
- QStack<int> row_stack;
- QModelIndex parent;
- QStack<QModelIndex> parent_stack;
- for (int i = 0; i < l.count(); ++i) {
- QString token = l.at(i);
- if (token == QLatin1String("<")) { // start table
- ++indent;
- parent_stack.push(parent);
- row_stack.push(row);
- parent = m->index(row - 1, 0, parent);
- QVERIFY(parent.isValid());
- row = 0;
- } else if (token == QLatin1String(">")) { // end table
- --indent;
- parent = parent_stack.pop();
- row = row_stack.pop();
- } else { // compare row
- QModelIndex index = m->index(row, 0, parent);
- QVERIFY(index.isValid());
- QString str = m->data(index, Qt::DisplayRole).toString();
- QCOMPARE(str, token);
- ++row;
- }
- }
-}
-
-class TestModel: public QAbstractTableModel
-{
-public:
- int rowCount(const QModelIndex &) const { return 10000; }
- int columnCount(const QModelIndex &) const { return 1; }
- QVariant data(const QModelIndex &index, int role) const
- {
- if (role != Qt::DisplayRole)
- return QVariant();
- return QString::number(index.row());
- }
-};
-
-void tst_QSortFilterProxyModel::filterTable()
-{
- TestModel model;
- QSortFilterProxyModel filter;
- filter.setSourceModel(&model);
- filter.setFilterRegExp("9");
-
- for (int i = 0; i < filter.rowCount(); ++i)
- QVERIFY(filter.data(filter.index(i, 0)).toString().contains(QLatin1Char('9')));
-}
-
-void tst_QSortFilterProxyModel::insertAfterSelect()
-{
- QStandardItemModel model(10, 2);
- for (int i = 0; i<10;i++)
- model.setData(model.index(i, 0), QVariant(i));
- QSortFilterProxyModel filter;
- filter.setSourceModel(&model);
- QTreeView view;
- view.setModel(&filter);
- view.show();
- QModelIndex firstIndex = filter.mapFromSource(model.index(0, 0, QModelIndex()));
- QCOMPARE(firstIndex.model(), (const QAbstractItemModel *)view.model());
- QVERIFY(firstIndex.isValid());
- int itemOffset = view.visualRect(firstIndex).width() / 2;
- QPoint p(itemOffset, 1);
- QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p);
- QVERIFY(view.selectionModel()->selectedIndexes().size() > 0);
- model.insertRows(5, 1, QModelIndex());
- QVERIFY(view.selectionModel()->selectedIndexes().size() > 0); // Should still have a selection
-}
-
-void tst_QSortFilterProxyModel::removeAfterSelect()
-{
- QStandardItemModel model(10, 2);
- for (int i = 0; i<10;i++)
- model.setData(model.index(i, 0), QVariant(i));
- QSortFilterProxyModel filter;
- filter.setSourceModel(&model);
- QTreeView view;
- view.setModel(&filter);
- view.show();
- QModelIndex firstIndex = filter.mapFromSource(model.index(0, 0, QModelIndex()));
- QCOMPARE(firstIndex.model(), (const QAbstractItemModel *)view.model());
- QVERIFY(firstIndex.isValid());
- int itemOffset = view.visualRect(firstIndex).width() / 2;
- QPoint p(itemOffset, 1);
- QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p);
- QVERIFY(view.selectionModel()->selectedIndexes().size() > 0);
- model.removeRows(5, 1, QModelIndex());
- QVERIFY(view.selectionModel()->selectedIndexes().size() > 0); // Should still have a selection
-}
-
-void tst_QSortFilterProxyModel::filterCurrent()
-{
- QStandardItemModel model(2, 1);
- model.setData(model.index(0, 0), QString("AAA"));
- model.setData(model.index(1, 0), QString("BBB"));
- QSortFilterProxyModel proxy;
- proxy.setSourceModel(&model);
- QTreeView view;
-
- view.show();
- view.setModel(&proxy);
- QSignalSpy spy(view.selectionModel(), &QItemSelectionModel::currentChanged);
- QVERIFY(spy.isValid());
-
- view.setCurrentIndex(proxy.index(0, 0));
- QCOMPARE(spy.count(), 1);
- proxy.setFilterRegExp(QRegExp("^B"));
- QCOMPARE(spy.count(), 2);
-}
-
-void tst_QSortFilterProxyModel::filter_qtbug30662()
-{
- QStringListModel model;
- QSortFilterProxyModel proxy;
- proxy.setSourceModel(&model);
-
- // make sure the filter does not match any entry
- proxy.setFilterRegExp(QRegExp("[0-9]+"));
-
- QStringList slSource;
- slSource << "z" << "x" << "a" << "b";
-
- proxy.setDynamicSortFilter(true);
- proxy.sort(0);
- model.setStringList(slSource);
-
- // without fix for QTBUG-30662 this will make all entries visible - but unsorted
- proxy.setFilterRegExp(QRegExp("[a-z]+"));
-
- QStringList slResult;
- for (int i = 0; i < proxy.rowCount(); ++i)
- slResult.append(proxy.index(i, 0).data().toString());
-
- slSource.sort();
- QCOMPARE(slResult, slSource);
-}
-
-void tst_QSortFilterProxyModel::changeSourceLayout()
-{
- QStandardItemModel model(2, 1);
- model.setData(model.index(0, 0), QString("b"));
- model.setData(model.index(1, 0), QString("a"));
- QSortFilterProxyModel proxy;
- proxy.setSourceModel(&model);
-
- QList<QPersistentModelIndex> persistentSourceIndexes;
- QList<QPersistentModelIndex> persistentProxyIndexes;
- for (int row = 0; row < model.rowCount(); ++row) {
- persistentSourceIndexes.append(model.index(row, 0));
- persistentProxyIndexes.append(proxy.index(row, 0));
- }
-
- // change layout of source model
- model.sort(0, Qt::AscendingOrder);
-
- for (int row = 0; row < model.rowCount(); ++row) {
- QCOMPARE(persistentProxyIndexes.at(row).row(),
- persistentSourceIndexes.at(row).row());
- }
-}
-
-void tst_QSortFilterProxyModel::changeSourceLayoutFilteredOut()
-{
- QStandardItemModel model(2, 1);
- model.setData(model.index(0, 0), QString("b"));
- model.setData(model.index(1, 0), QString("a"));
- QSortFilterProxyModel proxy;
- proxy.setSourceModel(&model);
-
- int beforeSortFilter = proxy.rowCount();
-
- QSignalSpy removeSpy(&proxy, &QSortFilterProxyModel::rowsRemoved);
- // Filter everything out
- proxy.setFilterRegExp(QRegExp("c"));
- QCOMPARE(removeSpy.count(), 1);
- QCOMPARE(0, proxy.rowCount());
-
- // change layout of source model
- model.sort(0, Qt::AscendingOrder);
-
- QSignalSpy insertSpy(&proxy, &QSortFilterProxyModel::rowsInserted);
- // Remove filter; we expect an insert
- proxy.setFilterRegExp(QRegExp(""));
- QCOMPARE(insertSpy.count(), 1);
- QCOMPARE(beforeSortFilter, proxy.rowCount());
-}
-
-void tst_QSortFilterProxyModel::removeSourceRows_data()
-{
- QTest::addColumn<QStringList>("sourceItems");
- QTest::addColumn<int>("start");
- QTest::addColumn<int>("count");
- QTest::addColumn<int>("sortOrder");
- QTest::addColumn<IntPairList>("expectedRemovedProxyIntervals");
- QTest::addColumn<QStringList>("expectedProxyItems");
-
- QTest::newRow("remove one, no sorting")
- << (QStringList() << "a" << "b") // sourceItems
- << 0 // start
- << 1 // count
- << -1 // sortOrder (no sorting)
- << (IntPairList() << IntPair(0, 0)) // expectedRemovedIntervals
- << (QStringList() << "b") // expectedProxyItems
- ;
- QTest::newRow("remove one, ascending sort (same order)")
- << (QStringList() << "a" << "b") // sourceItems
- << 0 // start
- << 1 // count
- << static_cast<int>(Qt::AscendingOrder) // sortOrder
- << (IntPairList() << IntPair(0, 0)) // expectedRemovedIntervals
- << (QStringList() << "b") // expectedProxyItems
- ;
- QTest::newRow("remove one, ascending sort (reverse order)")
- << (QStringList() << "b" << "a") // sourceItems
- << 0 // start
- << 1 // count
- << static_cast<int>(Qt::AscendingOrder) // sortOrder
- << (IntPairList() << IntPair(1, 1)) // expectedRemovedIntervals
- << (QStringList() << "a") // expectedProxyItems
- ;
- QTest::newRow("remove two, multiple proxy intervals")
- << (QStringList() << "c" << "d" << "a" << "b") // sourceItems
- << 1 // start
- << 2 // count
- << static_cast<int>(Qt::AscendingOrder) // sortOrder
- << (IntPairList() << IntPair(3, 3) << IntPair(0, 0)) // expectedRemovedIntervals
- << (QStringList() << "b" << "c") // expectedProxyItems
- ;
- QTest::newRow("remove three, multiple proxy intervals")
- << (QStringList() << "b" << "d" << "f" << "a" << "c" << "e") // sourceItems
- << 3 // start
- << 3 // count
- << static_cast<int>(Qt::AscendingOrder) // sortOrder
- << (IntPairList() << IntPair(4, 4) << IntPair(2, 2) << IntPair(0, 0)) // expectedRemovedIntervals
- << (QStringList() << "b" << "d" << "f") // expectedProxyItems
- ;
- QTest::newRow("remove all, single proxy intervals")
- << (QStringList() << "a" << "b" << "c" << "d" << "e" << "f") // sourceItems
- << 0 // start
- << 6 // count
- << static_cast<int>(Qt::DescendingOrder) // sortOrder
- << (IntPairList() << IntPair(0, 5)) // expectedRemovedIntervals
- << QStringList() // expectedProxyItems
- ;
-}
-
-// Check that correct proxy model rows are removed when rows are removed
-// from the source model
-void tst_QSortFilterProxyModel::removeSourceRows()
-{
- QFETCH(QStringList, sourceItems);
- QFETCH(int, start);
- QFETCH(int, count);
- QFETCH(int, sortOrder);
- QFETCH(IntPairList, expectedRemovedProxyIntervals);
- QFETCH(QStringList, expectedProxyItems);
-
- QStandardItemModel model;
- QSortFilterProxyModel proxy;
-
- proxy.setSourceModel(&model);
- model.insertColumns(0, 1);
- model.insertRows(0, sourceItems.count());
-
- for (int i = 0; i < sourceItems.count(); ++i) {
- QModelIndex sindex = model.index(i, 0, QModelIndex());
- model.setData(sindex, sourceItems.at(i), Qt::DisplayRole);
- QModelIndex pindex = proxy.index(i, 0, QModelIndex());
- QCOMPARE(proxy.data(pindex, Qt::DisplayRole), model.data(sindex, Qt::DisplayRole));
- }
-
- if (sortOrder != -1)
- proxy.sort(0, static_cast<Qt::SortOrder>(sortOrder));
- (void)proxy.rowCount(QModelIndex()); // force mapping
-
- QSignalSpy removeSpy(&proxy, &QSortFilterProxyModel::rowsRemoved);
- QSignalSpy insertSpy(&proxy, &QSortFilterProxyModel::rowsInserted);
- QSignalSpy aboutToRemoveSpy(&proxy, &QSortFilterProxyModel::rowsAboutToBeRemoved);
- QSignalSpy aboutToInsertSpy(&proxy, &QSortFilterProxyModel::rowsAboutToBeInserted);
-
- QVERIFY(removeSpy.isValid());
- QVERIFY(insertSpy.isValid());
- QVERIFY(aboutToRemoveSpy.isValid());
- QVERIFY(aboutToInsertSpy.isValid());
-
- model.removeRows(start, count, QModelIndex());
-
- QCOMPARE(aboutToRemoveSpy.count(), expectedRemovedProxyIntervals.count());
- for (int i = 0; i < aboutToRemoveSpy.count(); ++i) {
- QList<QVariant> args = aboutToRemoveSpy.at(i);
- QCOMPARE(args.at(1).type(), QVariant::Int);
- QCOMPARE(args.at(2).type(), QVariant::Int);
- QCOMPARE(args.at(1).toInt(), expectedRemovedProxyIntervals.at(i).first);
- QCOMPARE(args.at(2).toInt(), expectedRemovedProxyIntervals.at(i).second);
- }
- QCOMPARE(removeSpy.count(), expectedRemovedProxyIntervals.count());
- for (int i = 0; i < removeSpy.count(); ++i) {
- QList<QVariant> args = removeSpy.at(i);
- QCOMPARE(args.at(1).type(), QVariant::Int);
- QCOMPARE(args.at(2).type(), QVariant::Int);
- QCOMPARE(args.at(1).toInt(), expectedRemovedProxyIntervals.at(i).first);
- QCOMPARE(args.at(2).toInt(), expectedRemovedProxyIntervals.at(i).second);
- }
-
- QCOMPARE(insertSpy.count(), 0);
- QCOMPARE(aboutToInsertSpy.count(), 0);
-
- QCOMPARE(proxy.rowCount(QModelIndex()), expectedProxyItems.count());
- for (int i = 0; i < expectedProxyItems.count(); ++i) {
- QModelIndex pindex = proxy.index(i, 0, QModelIndex());
- QCOMPARE(proxy.data(pindex, Qt::DisplayRole).toString(), expectedProxyItems.at(i));
- }
-}
-
-void tst_QSortFilterProxyModel::insertSourceRows_data()
-{
- QTest::addColumn<QStringList>("sourceItems");
- QTest::addColumn<int>("start");
- QTest::addColumn<QStringList>("newItems");
- QTest::addColumn<int>("sortOrder");
- QTest::addColumn<QStringList>("proxyItems");
-
- QTest::newRow("insert (1)")
- << (QStringList() << "c" << "b") // sourceItems
- << 1 // start
- << (QStringList() << "a") // newItems
- << static_cast<int>(Qt::AscendingOrder) // sortOrder
- << (QStringList() << "a" << "b" << "c") // proxyItems
- ;
-
- QTest::newRow("insert (2)")
- << (QStringList() << "d" << "b" << "c") // sourceItems
- << 3 // start
- << (QStringList() << "a") // newItems
- << static_cast<int>(Qt::DescendingOrder) // sortOrder
- << (QStringList() << "d" << "c" << "b" << "a") // proxyItems
- ;
-}
-
-// Check that rows are inserted at correct position in proxy model when
-// rows are inserted into the source model
-void tst_QSortFilterProxyModel::insertSourceRows()
-{
- QFETCH(QStringList, sourceItems);
- QFETCH(int, start);
- QFETCH(QStringList, newItems);
- QFETCH(int, sortOrder);
- QFETCH(QStringList, proxyItems);
-
- QStandardItemModel model;
- QSortFilterProxyModel proxy;
- proxy.setDynamicSortFilter(true);
-
- proxy.setSourceModel(&model);
- model.insertColumns(0, 1);
- model.insertRows(0, sourceItems.count());
-
- for (int i = 0; i < sourceItems.count(); ++i) {
- QModelIndex index = model.index(i, 0, QModelIndex());
- model.setData(index, sourceItems.at(i), Qt::DisplayRole);
- }
-
- proxy.sort(0, static_cast<Qt::SortOrder>(sortOrder));
- (void)proxy.rowCount(QModelIndex()); // force mapping
-
- model.insertRows(start, newItems.size(), QModelIndex());
-
- QCOMPARE(proxy.rowCount(QModelIndex()), proxyItems.count());
- for (int i = 0; i < newItems.count(); ++i) {
- QModelIndex index = model.index(start + i, 0, QModelIndex());
- model.setData(index, newItems.at(i), Qt::DisplayRole);
- }
-
- for (int i = 0; i < proxyItems.count(); ++i) {
- QModelIndex index = proxy.index(i, 0, QModelIndex());
- QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), proxyItems.at(i));
- }
-}
-
-void tst_QSortFilterProxyModel::changeFilter_data()
-{
- QTest::addColumn<QStringList>("sourceItems");
- QTest::addColumn<int>("sortOrder");
- QTest::addColumn<QString>("initialFilter");
- QTest::addColumn<IntPairList>("initialRemoveIntervals");
- QTest::addColumn<QStringList>("initialProxyItems");
- QTest::addColumn<QString>("finalFilter");
- QTest::addColumn<IntPairList>("finalRemoveIntervals");
- QTest::addColumn<IntPairList>("insertIntervals");
- QTest::addColumn<QStringList>("finalProxyItems");
-
- QTest::newRow("filter (1)")
- << (QStringList() << "a" << "b" << "c" << "d" << "e" << "f") // sourceItems
- << static_cast<int>(Qt::AscendingOrder) // sortOrder
- << "a|b|c" // initialFilter
- << (IntPairList() << IntPair(3, 5)) // initialRemoveIntervals
- << (QStringList() << "a" << "b" << "c") // initialProxyItems
- << "b|d|f" // finalFilter
- << (IntPairList() << IntPair(2, 2) << IntPair(0, 0)) // finalRemoveIntervals
- << (IntPairList() << IntPair(1, 2)) // insertIntervals
- << (QStringList() << "b" << "d" << "f") // finalProxyItems
- ;
-
- QTest::newRow("filter (2)")
- << (QStringList() << "a" << "b" << "c" << "d" << "e" << "f") // sourceItems
- << static_cast<int>(Qt::AscendingOrder) // sortOrder
- << "a|c|e" // initialFilter
- << (IntPairList() << IntPair(5, 5) << IntPair(3, 3) << IntPair(1, 1)) // initialRemoveIntervals
- << (QStringList() << "a" << "c" << "e") // initialProxyItems
- << "" // finalFilter
- << IntPairList() // finalRemoveIntervals
- << (IntPairList() << IntPair(3, 3) << IntPair(2, 2) << IntPair(1, 1)) // insertIntervals
- << (QStringList() << "a" << "b" << "c" << "d" << "e" << "f") // finalProxyItems
- ;
-
- QTest::newRow("filter (3)")
- << (QStringList() << "a" << "b" << "c") // sourceItems
- << static_cast<int>(Qt::AscendingOrder) // sortOrder
- << "a" // initialFilter
- << (IntPairList() << IntPair(1, 2)) // initialRemoveIntervals
- << (QStringList() << "a") // initialProxyItems
- << "a" // finalFilter
- << IntPairList() // finalRemoveIntervals
- << IntPairList() // insertIntervals
- << (QStringList() << "a") // finalProxyItems
- ;
-}
-
-// Check that rows are added/removed when filter changes
-void tst_QSortFilterProxyModel::changeFilter()
-{
- QFETCH(QStringList, sourceItems);
- QFETCH(int, sortOrder);
- QFETCH(QString, initialFilter);
- QFETCH(IntPairList, initialRemoveIntervals);
- QFETCH(QStringList, initialProxyItems);
- QFETCH(QString, finalFilter);
- QFETCH(IntPairList, finalRemoveIntervals);
- QFETCH(IntPairList, insertIntervals);
- QFETCH(QStringList, finalProxyItems);
-
- QStandardItemModel model;
- QSortFilterProxyModel proxy;
-
- proxy.setSourceModel(&model);
- model.insertColumns(0, 1);
- model.insertRows(0, sourceItems.count());
-
- for (int i = 0; i < sourceItems.count(); ++i) {
- QModelIndex index = model.index(i, 0, QModelIndex());
- model.setData(index, sourceItems.at(i), Qt::DisplayRole);
- }
-
- proxy.sort(0, static_cast<Qt::SortOrder>(sortOrder));
- (void)proxy.rowCount(QModelIndex()); // force mapping
-
- QSignalSpy initialRemoveSpy(&proxy, &QSortFilterProxyModel::rowsRemoved);
- QSignalSpy initialInsertSpy(&proxy, &QSortFilterProxyModel::rowsInserted);
-
- QVERIFY(initialRemoveSpy.isValid());
- QVERIFY(initialInsertSpy.isValid());
-
- proxy.setFilterRegExp(initialFilter);
-
- QCOMPARE(initialRemoveSpy.count(), initialRemoveIntervals.count());
- QCOMPARE(initialInsertSpy.count(), 0);
- for (int i = 0; i < initialRemoveSpy.count(); ++i) {
- QList<QVariant> args = initialRemoveSpy.at(i);
- QCOMPARE(args.at(1).type(), QVariant::Int);
- QCOMPARE(args.at(2).type(), QVariant::Int);
- QCOMPARE(args.at(1).toInt(), initialRemoveIntervals.at(i).first);
- QCOMPARE(args.at(2).toInt(), initialRemoveIntervals.at(i).second);
- }
-
- QCOMPARE(proxy.rowCount(QModelIndex()), initialProxyItems.count());
- for (int i = 0; i < initialProxyItems.count(); ++i) {
- QModelIndex index = proxy.index(i, 0, QModelIndex());
- QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), initialProxyItems.at(i));
- }
-
- QSignalSpy finalRemoveSpy(&proxy, &QSortFilterProxyModel::rowsRemoved);
- QSignalSpy finalInsertSpy(&proxy, &QSortFilterProxyModel::rowsInserted);
-
- QVERIFY(finalRemoveSpy.isValid());
- QVERIFY(finalInsertSpy.isValid());
-
- proxy.setFilterRegExp(finalFilter);
-
- QCOMPARE(finalRemoveSpy.count(), finalRemoveIntervals.count());
- for (int i = 0; i < finalRemoveSpy.count(); ++i) {
- QList<QVariant> args = finalRemoveSpy.at(i);
- QCOMPARE(args.at(1).type(), QVariant::Int);
- QCOMPARE(args.at(2).type(), QVariant::Int);
- QCOMPARE(args.at(1).toInt(), finalRemoveIntervals.at(i).first);
- QCOMPARE(args.at(2).toInt(), finalRemoveIntervals.at(i).second);
- }
-
- QCOMPARE(finalInsertSpy.count(), insertIntervals.count());
- for (int i = 0; i < finalInsertSpy.count(); ++i) {
- QList<QVariant> args = finalInsertSpy.at(i);
- QCOMPARE(args.at(1).type(), QVariant::Int);
- QCOMPARE(args.at(2).type(), QVariant::Int);
- QCOMPARE(args.at(1).toInt(), insertIntervals.at(i).first);
- QCOMPARE(args.at(2).toInt(), insertIntervals.at(i).second);
- }
-
- QCOMPARE(proxy.rowCount(QModelIndex()), finalProxyItems.count());
- for (int i = 0; i < finalProxyItems.count(); ++i) {
- QModelIndex index = proxy.index(i, 0, QModelIndex());
- QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), finalProxyItems.at(i));
- }
-}
-
-void tst_QSortFilterProxyModel::changeSourceData_data()
-{
- QTest::addColumn<QStringList>("sourceItems");
- QTest::addColumn<int>("sortOrder");
- QTest::addColumn<QString>("filter");
- QTest::addColumn<QStringList>("expectedInitialProxyItems");
- QTest::addColumn<bool>("dynamic");
- QTest::addColumn<int>("row");
- QTest::addColumn<QString>("newValue");
- QTest::addColumn<IntPairList>("removeIntervals");
- QTest::addColumn<IntPairList>("insertIntervals");
- QTest::addColumn<int>("expectedDataChangedRow"); // -1 if no dataChanged signal expected
- QTest::addColumn<bool>("expectedLayoutChanged");
- QTest::addColumn<QStringList>("proxyItems");
-
- QTest::newRow("move_to_end_ascending")
- << (QStringList() << "c" << "b" << "a") // sourceItems
- << static_cast<int>(Qt::AscendingOrder) // sortOrder
- << "" // filter
- << (QStringList() << "a" << "b" << "c") // expectedInitialProxyItems
- << true // dynamic
- << 2 // row
- << "z" // newValue
- << IntPairList() // removeIntervals
- << IntPairList() // insertIntervals
- << 2 // dataChanged(row 2) is emitted, see comment "Make sure we also emit dataChanged for the rows" in the source code (unclear why, though)
- << true // layoutChanged
- << (QStringList() << "b" << "c" << "z") // proxyItems
- ;
-
- QTest::newRow("move_to_end_descending")
- << (QStringList() << "b" << "c" << "z") // sourceItems
- << static_cast<int>(Qt::DescendingOrder) // sortOrder
- << "" // filter
- << (QStringList() << "z" << "c" << "b") // expectedInitialProxyItems
- << true // dynamic
- << 1 // row
- << "a" // newValue
- << IntPairList() // removeIntervals
- << IntPairList() // insertIntervals
- << 2 // dataChanged(row 2) is emitted, see comment "Make sure we also emit dataChanged for the rows" in the source code (unclear why, though)
- << true // layoutChanged
- << (QStringList() << "z" << "b" << "a") // proxyItems
- ;
-
- QTest::newRow("no_op_change")
- << (QStringList() << "a" << "b") // sourceItems
- << static_cast<int>(Qt::DescendingOrder) // sortOrder
- << "" // filter
- << (QStringList() << "b" << "a") // expectedInitialProxyItems
- << true // dynamic
- << 0 // row
- << "a" // newValue
- << IntPairList() // removeIntervals
- << IntPairList() // insertIntervals
- << -1 // no dataChanged signal
- << false // layoutChanged
- << (QStringList() << "b" << "a") // proxyItems
- ;
-
- QTest::newRow("no_effect_on_filtering")
- << (QStringList() << "a" << "b") // sourceItems
- << static_cast<int>(Qt::AscendingOrder) // sortOrder
- << "" // filter
- << (QStringList() << "a" << "b") // expectedInitialProxyItems
- << true // dynamic
- << 1 // row
- << "z" // newValue
- << IntPairList() // removeIntervals
- << IntPairList() // insertIntervals
- << 1 // expectedDataChangedRow
- << false // layoutChanged
- << (QStringList() << "a" << "z") // proxyItems
- ;
-
- QTest::newRow("filtered_out_value_stays_out")
- << (QStringList() << "a" << "b" << "c" << "d") // sourceItems
- << static_cast<int>(Qt::AscendingOrder) // sortOrder
- << "a|c" // filter
- << (QStringList() << "a" << "c") // expectedInitialProxyItems
- << true // dynamic
- << 1 // row
- << "x" // newValue
- << IntPairList() // removeIntervals
- << IntPairList() // insertIntervals
- << -1 // no dataChanged signal
- << false // layoutChanged
- << (QStringList() << "a" << "c") // proxyItems
- ;
-
- QTest::newRow("filtered_out_now_matches")
- << (QStringList() << "a" << "b" << "c" << "d") // sourceItems
- << static_cast<int>(Qt::AscendingOrder) // sortOrder
- << "a|c|x" // filter
- << (QStringList() << "a" << "c") // expectedInitialProxyItems
- << true // dynamic
- << 1 // row
- << "x" // newValue
- << IntPairList() // removeIntervals
- << (IntPairList() << IntPair(2, 2)) // insertIntervals
- << -1 // no dataChanged signal
- << false // layoutChanged
- << (QStringList() << "a" << "c" << "x") // proxyItems
- ;
-
- QTest::newRow("value_is_now_filtered_out")
- << (QStringList() << "a" << "b" << "c" << "d") // sourceItems
- << static_cast<int>(Qt::AscendingOrder) // sortOrder
- << "a|c" // filter
- << (QStringList() << "a" << "c") // expectedInitialProxyItems
- << true // dynamic
- << 2 // row
- << "x" // newValue
- << (IntPairList() << IntPair(1, 1)) // removeIntervals
- << IntPairList() // insertIntervals
- << -1 // no dataChanged signal
- << false // layoutChanged
- << (QStringList() << "a") // proxyItems
- ;
-
- QTest::newRow("non_dynamic_filter_does_not_update_sort")
- << (QStringList() << "c" << "b" << "a") // sourceItems
- << static_cast<int>(Qt::AscendingOrder) // sortOrder
- << "" // filter
- << (QStringList() << "a" << "b" << "c") // expectedInitialProxyItems
- << false // dynamic
- << 2 // row
- << "x" // newValue
- << IntPairList() // removeIntervals
- << IntPairList() // insertIntervals
- << 0 // expectedDataChangedRow
- << false // layoutChanged
- << (QStringList() << "x" << "b" << "c") // proxyItems
- ;
-}
-
-void tst_QSortFilterProxyModel::changeSourceData()
-{
- QFETCH(QStringList, sourceItems);
- QFETCH(int, sortOrder);
- QFETCH(QString, filter);
- QFETCH(QStringList, expectedInitialProxyItems);
- QFETCH(bool, dynamic);
- QFETCH(int, row);
- QFETCH(QString, newValue);
- QFETCH(IntPairList, removeIntervals);
- QFETCH(IntPairList, insertIntervals);
- QFETCH(int, expectedDataChangedRow);
- QFETCH(bool, expectedLayoutChanged);
- QFETCH(QStringList, proxyItems);
-
- QStandardItemModel model;
- QSortFilterProxyModel proxy;
-
- proxy.setDynamicSortFilter(dynamic);
- proxy.setSourceModel(&model);
- model.insertColumns(0, 1);
- model.insertRows(0, sourceItems.count());
-
- for (int i = 0; i < sourceItems.count(); ++i) {
- QModelIndex index = model.index(i, 0, QModelIndex());
- model.setData(index, sourceItems.at(i), Qt::DisplayRole);
- }
-
- proxy.sort(0, static_cast<Qt::SortOrder>(sortOrder));
- (void)proxy.rowCount(QModelIndex()); // force mapping
-
- proxy.setFilterRegExp(filter);
-
- QCOMPARE(proxy.rowCount(), expectedInitialProxyItems.count());
- for (int i = 0; i < expectedInitialProxyItems.count(); ++i) {
- const QModelIndex index = proxy.index(i, 0, QModelIndex());
- QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expectedInitialProxyItems.at(i));
- }
-
- QSignalSpy removeSpy(&proxy, &QSortFilterProxyModel::rowsRemoved);
- QSignalSpy insertSpy(&proxy, &QSortFilterProxyModel::rowsInserted);
- QSignalSpy dataChangedSpy(&proxy, &QSortFilterProxyModel::dataChanged);
- QSignalSpy layoutChangedSpy(&proxy, &QSortFilterProxyModel::layoutChanged);
-
- QVERIFY(removeSpy.isValid());
- QVERIFY(insertSpy.isValid());
- QVERIFY(dataChangedSpy.isValid());
- QVERIFY(layoutChangedSpy.isValid());
-
- {
- QModelIndex index = model.index(row, 0, QModelIndex());
- model.setData(index, newValue, Qt::DisplayRole);
- }
-
- QCOMPARE(removeSpy.count(), removeIntervals.count());
- for (int i = 0; i < removeSpy.count(); ++i) {
- QList<QVariant> args = removeSpy.at(i);
- QCOMPARE(args.at(1).type(), QVariant::Int);
- QCOMPARE(args.at(2).type(), QVariant::Int);
- QCOMPARE(args.at(1).toInt(), removeIntervals.at(i).first);
- QCOMPARE(args.at(2).toInt(), removeIntervals.at(i).second);
- }
-
- QCOMPARE(insertSpy.count(), insertIntervals.count());
- for (int i = 0; i < insertSpy.count(); ++i) {
- QList<QVariant> args = insertSpy.at(i);
- QCOMPARE(args.at(1).type(), QVariant::Int);
- QCOMPARE(args.at(2).type(), QVariant::Int);
- QCOMPARE(args.at(1).toInt(), insertIntervals.at(i).first);
- QCOMPARE(args.at(2).toInt(), insertIntervals.at(i).second);
- }
-
- QCOMPARE(proxy.rowCount(QModelIndex()), proxyItems.count());
- for (int i = 0; i < proxyItems.count(); ++i) {
- QModelIndex index = proxy.index(i, 0, QModelIndex());
- QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), proxyItems.at(i));
- }
-
- if (expectedDataChangedRow == -1) {
- QCOMPARE(dataChangedSpy.count(), 0);
- } else {
- QCOMPARE(dataChangedSpy.count(), 1);
- const QModelIndex idx = dataChangedSpy.at(0).at(0).value<QModelIndex>();
- QCOMPARE(idx.row(), expectedDataChangedRow);
- QCOMPARE(idx.column(), 0);
- }
-
- QCOMPARE(layoutChangedSpy.count(), expectedLayoutChanged ? 1 : 0);
-}
-
-// Checks that the model is a table, and that each and every row is like this:
-// i-th row: ( rows.at(i), i )
-static void checkSortedTableModel(const QAbstractItemModel *model, const QStringList &rows)
-{
- QCOMPARE(model->rowCount(), rows.length());
- QCOMPARE(model->columnCount(), 2);
-
- for (int row = 0; row < model->rowCount(); ++row) {
- const QString column0 = model->index(row, 0).data().toString();
- const int column1 = model->index(row, 1).data().toString().toInt();
-
- QCOMPARE(column0, rows.at(row));
- QCOMPARE(column1, row);
- }
-}
-
-void tst_QSortFilterProxyModel::changeSourceDataKeepsStableSorting_qtbug1548()
-{
- // Check that emitting dataChanged from the source model
- // for a change of a role which is not the sorting role
- // doesn't alter the sorting. In this case, we sort on the DisplayRole,
- // and play with other roles.
-
- static const QStringList rows
- = QStringList() << "a" << "b" << "b" << "b" << "c" << "c" << "x";
-
- // Build a table of pairs (string, #row) in each row
- QStandardItemModel model(0, 2);
-
- for (int rowNumber = 0; rowNumber < rows.length(); ++rowNumber) {
- QStandardItem *column0 = new QStandardItem(rows.at(rowNumber));
- column0->setCheckable(true);
- column0->setCheckState(Qt::Unchecked);
-
- QStandardItem *column1 = new QStandardItem(QString::number(rowNumber));
-
- const QList<QStandardItem *> row
- = QList<QStandardItem *>() << column0 << column1;
-
- model.appendRow(row);
- }
-
- checkSortedTableModel(&model, rows);
-
- // Build the proxy model
- QSortFilterProxyModel proxy;
- proxy.setSourceModel(&model);
- proxy.setDynamicSortFilter(true);
- proxy.sort(0);
-
- // The proxy is now sorted by the first column, check that the sorting
- // * is correct (the input is already sorted, so it must not have changed)
- // * was stable (by looking at the second column)
- checkSortedTableModel(&model, rows);
-
- // Change the check status of an item. That must not break the stable sorting
- // changes the middle "b"
- model.item(2)->setCheckState(Qt::Checked);
- checkSortedTableModel(&model, rows);
-
- // changes the starting "a"
- model.item(0)->setCheckState(Qt::Checked);
- checkSortedTableModel(&model, rows);
-
- // change the background color of the first "c"
- model.item(4)->setBackground(Qt::red);
- checkSortedTableModel(&model, rows);
-
- // change the background color of the second "c"
- model.item(5)->setBackground(Qt::red);
- checkSortedTableModel(&model, rows);
-}
-
-void tst_QSortFilterProxyModel::changeSourceDataForwardsRoles_qtbug35440()
-{
- QStringList strings;
- for (int i = 0; i < 100; ++i)
- strings << QString::number(i);
-
- QStringListModel model(strings);
-
- QSortFilterProxyModel proxy;
- proxy.setSourceModel(&model);
- proxy.sort(0, Qt::AscendingOrder);
-
- QSignalSpy spy(&proxy, &QAbstractItemModel::dataChanged);
- QVERIFY(spy.isValid());
- QCOMPARE(spy.length(), 0);
-
- QModelIndex index;
-
- // QStringListModel doesn't distinguish between edit and display roles,
- // so changing one always changes the other, too.
- QVector<int> expectedChangedRoles;
- expectedChangedRoles.append(Qt::DisplayRole);
- expectedChangedRoles.append(Qt::EditRole);
-
- index = model.index(0, 0);
- QVERIFY(index.isValid());
- model.setData(index, QStringLiteral("teststring"), Qt::DisplayRole);
- QCOMPARE(spy.length(), 1);
- QCOMPARE(spy.at(0).at(2).value<QVector<int> >(), expectedChangedRoles);
-
- index = model.index(1, 0);
- QVERIFY(index.isValid());
- model.setData(index, QStringLiteral("teststring2"), Qt::EditRole);
- QCOMPARE(spy.length(), 2);
- QCOMPARE(spy.at(1).at(2).value<QVector<int> >(), expectedChangedRoles);
-}
-
-void tst_QSortFilterProxyModel::sortFilterRole()
-{
- QStandardItemModel model;
- QSortFilterProxyModel proxy;
- proxy.setSourceModel(&model);
- model.insertColumns(0, 1);
-
- QList<QPair<QVariant, QVariant> > sourceItems;
- sourceItems = QList<QPair<QVariant, QVariant> >()
- << QPair<QVariant, QVariant>("b", 3)
- << QPair<QVariant, QVariant>("c", 2)
- << QPair<QVariant, QVariant>("a", 1);
-
- QList<int> orderedItems;
- orderedItems = QList<int>()
- << 2 << 1;
-
- model.insertRows(0, sourceItems.count());
- for (int i = 0; i < sourceItems.count(); ++i) {
- QModelIndex index = model.index(i, 0, QModelIndex());
- model.setData(index, sourceItems.at(i).first, Qt::DisplayRole);
- model.setData(index, sourceItems.at(i).second, Qt::UserRole);
- }
-
- proxy.setFilterRegExp("2");
- QCOMPARE(proxy.rowCount(), 0); // Qt::DisplayRole is default role
-
- proxy.setFilterRole(Qt::UserRole);
- QCOMPARE(proxy.rowCount(), 1);
-
- proxy.setFilterRole(Qt::DisplayRole);
- QCOMPARE(proxy.rowCount(), 0);
-
- proxy.setFilterRegExp("1|2|3");
- QCOMPARE(proxy.rowCount(), 0);
-
- proxy.setFilterRole(Qt::UserRole);
- QCOMPARE(proxy.rowCount(), 3);
-
- proxy.sort(0, Qt::AscendingOrder);
- QCOMPARE(proxy.rowCount(), 3);
-
- proxy.setSortRole(Qt::UserRole);
- proxy.setFilterRole(Qt::DisplayRole);
- proxy.setFilterRegExp("a|c");
- QCOMPARE(proxy.rowCount(), orderedItems.count());
- for (int i = 0; i < proxy.rowCount(); ++i) {
- QModelIndex index = proxy.index(i, 0, QModelIndex());
- QCOMPARE(proxy.data(index, Qt::DisplayRole), sourceItems.at(orderedItems.at(i)).first);
- }
-}
-
-void tst_QSortFilterProxyModel::selectionFilteredOut()
-{
- QStandardItemModel model(2, 1);
- model.setData(model.index(0, 0), QString("AAA"));
- model.setData(model.index(1, 0), QString("BBB"));
- QSortFilterProxyModel proxy;
- proxy.setSourceModel(&model);
- QTreeView view;
-
- view.show();
- view.setModel(&proxy);
- QSignalSpy spy(view.selectionModel(), &QItemSelectionModel::currentChanged);
- QVERIFY(spy.isValid());
-
- view.setCurrentIndex(proxy.index(0, 0));
- QCOMPARE(spy.count(), 1);
- proxy.setFilterRegExp(QRegExp("^B"));
- QCOMPARE(spy.count(), 2);
-}
-
-void tst_QSortFilterProxyModel::match_data()
-{
- QTest::addColumn<QStringList>("sourceItems");
- QTest::addColumn<int>("sortOrder");
- QTest::addColumn<QString>("filter");
- QTest::addColumn<int>("proxyStartRow");
- QTest::addColumn<QString>("what");
- QTest::addColumn<int>("matchFlags");
- QTest::addColumn<IntList>("expectedProxyItems");
- QTest::newRow("1")
- << (QStringList() << "a") // sourceItems
- << static_cast<int>(Qt::AscendingOrder) // sortOrder
- << "" // filter
- << 0 // proxyStartRow
- << "a" // what
- << static_cast<int>(Qt::MatchExactly) // matchFlags
- << (IntList() << 0); // expectedProxyItems
- QTest::newRow("2")
- << (QStringList() << "a" << "b") // sourceItems
- << static_cast<int>(Qt::AscendingOrder) // sortOrder
- << "" // filter
- << 0 // proxyStartRow
- << "b" // what
- << static_cast<int>(Qt::MatchExactly) // matchFlags
- << (IntList() << 1); // expectedProxyItems
- QTest::newRow("3")
- << (QStringList() << "a" << "b") // sourceItems
- << static_cast<int>(Qt::DescendingOrder) // sortOrder
- << "" // filter
- << 0 // proxyStartRow
- << "a" // what
- << static_cast<int>(Qt::MatchExactly) // matchFlags
- << (IntList() << 1); // expectedProxyItems
- QTest::newRow("4")
- << (QStringList() << "b" << "d" << "a" << "c") // sourceItems
- << static_cast<int>(Qt::AscendingOrder) // sortOrder
- << "" // filter
- << 1 // proxyStartRow
- << "a" // what
- << static_cast<int>(Qt::MatchExactly) // matchFlags
- << IntList(); // expectedProxyItems
- QTest::newRow("5")
- << (QStringList() << "b" << "d" << "a" << "c") // sourceItems
- << static_cast<int>(Qt::AscendingOrder) // sortOrder
- << "a|b" // filter
- << 0 // proxyStartRow
- << "c" // what
- << static_cast<int>(Qt::MatchExactly) // matchFlags
- << IntList(); // expectedProxyItems
- QTest::newRow("6")
- << (QStringList() << "b" << "d" << "a" << "c") // sourceItems
- << static_cast<int>(Qt::DescendingOrder) // sortOrder
- << "a|b" // filter
- << 0 // proxyStartRow
- << "b" // what
- << static_cast<int>(Qt::MatchExactly) // matchFlags
- << (IntList() << 0); // expectedProxyItems
-}
-
-void tst_QSortFilterProxyModel::match()
-{
- QFETCH(QStringList, sourceItems);
- QFETCH(int, sortOrder);
- QFETCH(QString, filter);
- QFETCH(int, proxyStartRow);
- QFETCH(QString, what);
- QFETCH(int, matchFlags);
- QFETCH(IntList, expectedProxyItems);
-
- QStandardItemModel model;
- QSortFilterProxyModel proxy;
-
- proxy.setSourceModel(&model);
- model.insertColumns(0, 1);
- model.insertRows(0, sourceItems.count());
-
- for (int i = 0; i < sourceItems.count(); ++i) {
- QModelIndex index = model.index(i, 0, QModelIndex());
- model.setData(index, sourceItems.at(i), Qt::DisplayRole);
- }
-
- proxy.sort(0, static_cast<Qt::SortOrder>(sortOrder));
- proxy.setFilterRegExp(filter);
-
- QModelIndex startIndex = proxy.index(proxyStartRow, 0);
- QModelIndexList indexes = proxy.match(startIndex, Qt::DisplayRole, what,
- expectedProxyItems.count(),
- Qt::MatchFlags(matchFlags));
- QCOMPARE(indexes.count(), expectedProxyItems.count());
- for (int i = 0; i < indexes.count(); ++i)
- QCOMPARE(indexes.at(i).row(), expectedProxyItems.at(i));
-}
-
-void tst_QSortFilterProxyModel::insertIntoChildrenlessItem()
-{
- QStandardItemModel model;
- QStandardItem *itemA = new QStandardItem("a");
- model.appendRow(itemA);
- QStandardItem *itemB = new QStandardItem("b");
- model.appendRow(itemB);
- QStandardItem *itemC = new QStandardItem("c");
- model.appendRow(itemC);
-
- QSortFilterProxyModel proxy;
- proxy.setSourceModel(&model);
-
- QSignalSpy colsInsertedSpy(&proxy, &QSortFilterProxyModel::columnsInserted);
- QSignalSpy rowsInsertedSpy(&proxy, &QSortFilterProxyModel::rowsInserted);
-
- QVERIFY(colsInsertedSpy.isValid());
- QVERIFY(rowsInsertedSpy.isValid());
-
- (void)proxy.rowCount(QModelIndex()); // force mapping of "a", "b", "c"
- QCOMPARE(colsInsertedSpy.count(), 0);
- QCOMPARE(rowsInsertedSpy.count(), 0);
-
- // now add a child to itemB ==> should get insert notification from the proxy
- itemB->appendRow(new QStandardItem("a.0"));
- QCOMPARE(colsInsertedSpy.count(), 1);
- QCOMPARE(rowsInsertedSpy.count(), 1);
-
- QVariantList args = colsInsertedSpy.takeFirst();
- QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), proxy.mapFromSource(itemB->index()));
- QCOMPARE(qvariant_cast<int>(args.at(1)), 0);
- QCOMPARE(qvariant_cast<int>(args.at(2)), 0);
-
- args = rowsInsertedSpy.takeFirst();
- QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), proxy.mapFromSource(itemB->index()));
- QCOMPARE(qvariant_cast<int>(args.at(1)), 0);
- QCOMPARE(qvariant_cast<int>(args.at(2)), 0);
-}
-
-void tst_QSortFilterProxyModel::invalidateMappedChildren()
-{
- QStandardItemModel model;
-
- QSortFilterProxyModel proxy;
- proxy.setSourceModel(&model);
-
- QStandardItem *itemA = new QStandardItem("a");
- model.appendRow(itemA);
- QStandardItem *itemB = new QStandardItem("b");
- itemA->appendRow(itemB);
-
- QStandardItem *itemC = new QStandardItem("c");
- itemB->appendRow(itemC);
- itemC->appendRow(new QStandardItem("d"));
-
- // force mappings
- (void)proxy.hasChildren(QModelIndex());
- (void)proxy.hasChildren(proxy.mapFromSource(itemA->index()));
- (void)proxy.hasChildren(proxy.mapFromSource(itemB->index()));
- (void)proxy.hasChildren(proxy.mapFromSource(itemC->index()));
-
- itemB->removeRow(0); // should invalidate mapping of itemC
- itemC = new QStandardItem("c");
- itemA->appendRow(itemC);
- itemC->appendRow(new QStandardItem("d"));
-
- itemA->removeRow(1); // should invalidate mapping of itemC
- itemC = new QStandardItem("c");
- itemB->appendRow(itemC);
- itemC->appendRow(new QStandardItem("d"));
-
- QCOMPARE(proxy.rowCount(proxy.mapFromSource(itemA->index())), 1);
- QCOMPARE(proxy.rowCount(proxy.mapFromSource(itemB->index())), 1);
- QCOMPARE(proxy.rowCount(proxy.mapFromSource(itemC->index())), 1);
-}
-
-class EvenOddFilterModel : public QSortFilterProxyModel
-{
-public:
- virtual bool filterAcceptsRow(int srcRow, const QModelIndex& srcParent) const
- {
- if (srcParent.isValid())
- return (srcParent.row() % 2) ^ !(srcRow % 2);
- return (srcRow % 2);
- }
-};
-
-void tst_QSortFilterProxyModel::insertRowIntoFilteredParent()
-{
- QStandardItemModel model;
- EvenOddFilterModel proxy;
- proxy.setSourceModel(&model);
-
- QSignalSpy spy(&proxy, &EvenOddFilterModel::rowsInserted);
- QVERIFY(spy.isValid());
-
- QStandardItem *itemA = new QStandardItem();
- model.appendRow(itemA); // A will be filtered
- QStandardItem *itemB = new QStandardItem();
- itemA->appendRow(itemB);
-
- QCOMPARE(spy.count(), 0);
-
- itemA->removeRow(0);
-
- QCOMPARE(spy.count(), 0);
-}
-
-void tst_QSortFilterProxyModel::filterOutParentAndFilterInChild()
-{
- QStandardItemModel model;
- QSortFilterProxyModel proxy;
- proxy.setSourceModel(&model);
-
- proxy.setFilterRegExp("A|B");
- QStandardItem *itemA = new QStandardItem("A");
- model.appendRow(itemA); // not filtered
- QStandardItem *itemB = new QStandardItem("B");
- itemA->appendRow(itemB); // not filtered
- QStandardItem *itemC = new QStandardItem("C");
- itemA->appendRow(itemC); // filtered
-
- QSignalSpy removedSpy(&proxy, &QSortFilterProxyModel::rowsRemoved);
- QSignalSpy insertedSpy(&proxy, &QSortFilterProxyModel::rowsInserted);
-
- QVERIFY(removedSpy.isValid());
- QVERIFY(insertedSpy.isValid());
-
- proxy.setFilterRegExp("C"); // A and B will be filtered out, C filtered in
-
- // we should now have been notified that the subtree represented by itemA has been removed
- QCOMPARE(removedSpy.count(), 1);
- // we should NOT get any inserts; itemC should be filtered because its parent (itemA) is
- QCOMPARE(insertedSpy.count(), 0);
-}
-
-void tst_QSortFilterProxyModel::sourceInsertRows()
-{
- QStandardItemModel model;
- QSortFilterProxyModel proxyModel;
- proxyModel.setSourceModel(&model);
-
- model.insertColumns(0, 1, QModelIndex());
- model.insertRows(0, 2, QModelIndex());
-
- {
- QModelIndex parent = model.index(0, 0, QModelIndex());
- model.insertColumns(0, 1, parent);
- model.insertRows(0, 1, parent);
- }
-
- {
- QModelIndex parent = model.index(1, 0, QModelIndex());
- model.insertColumns(0, 1, parent);
- model.insertRows(0, 1, parent);
- }
-
- model.insertRows(0, 1, QModelIndex());
- model.insertRows(0, 1, QModelIndex());
-
- QVERIFY(true); // if you got here without asserting, it's all good
-}
-
-void tst_QSortFilterProxyModel::sourceModelDeletion()
-{
- QSortFilterProxyModel proxyModel;
- {
- QStandardItemModel model;
- proxyModel.setSourceModel(&model);
- QCOMPARE(proxyModel.sourceModel(), static_cast<QAbstractItemModel*>(&model));
- }
- QCOMPARE(proxyModel.sourceModel(), static_cast<QAbstractItemModel*>(0));
-}
-
-void tst_QSortFilterProxyModel::sortColumnTracking1()
-{
- QStandardItemModel model;
- QSortFilterProxyModel proxyModel;
- proxyModel.setSourceModel(&model);
-
- model.insertColumns(0, 10);
- model.insertRows(0, 10);
-
- proxyModel.sort(1);
- QCOMPARE(proxyModel.sortColumn(), 1);
-
- model.insertColumn(8);
- QCOMPARE(proxyModel.sortColumn(), 1);
-
- model.removeColumn(8);
- QCOMPARE(proxyModel.sortColumn(), 1);
-
- model.insertColumn(2);
- QCOMPARE(proxyModel.sortColumn(), 1);
-
- model.removeColumn(2);
- QCOMPARE(proxyModel.sortColumn(), 1);
-
- model.insertColumn(1);
- QCOMPARE(proxyModel.sortColumn(), 2);
-
- model.removeColumn(1);
- QCOMPARE(proxyModel.sortColumn(), 1);
-
- model.removeColumn(1);
- QCOMPARE(proxyModel.sortColumn(), -1);
-}
-
-void tst_QSortFilterProxyModel::sortColumnTracking2()
-{
- QStandardItemModel model;
- QSortFilterProxyModel proxyModel;
- proxyModel.setDynamicSortFilter(true);
- proxyModel.setSourceModel(&model);
-
- proxyModel.sort(0);
- QCOMPARE(proxyModel.sortColumn(), 0);
-
- QList<QStandardItem *> items; // Stable sorting: Items with invalid data should move to the end
- items << new QStandardItem << new QStandardItem("foo") << new QStandardItem("bar")
- << new QStandardItem("some") << new QStandardItem("others") << new QStandardItem("item")
- << new QStandardItem("aa") << new QStandardItem("zz") << new QStandardItem;
-
- model.insertColumn(0,items);
- QCOMPARE(proxyModel.sortColumn(), 0);
- QCOMPARE(proxyModel.data(proxyModel.index(0,0)).toString(),QString::fromLatin1("aa"));
- const int zzIndex = items.count() - 3; // 2 invalid at end.
- QCOMPARE(proxyModel.data(proxyModel.index(zzIndex,0)).toString(),QString::fromLatin1("zz"));
-}
-
-void tst_QSortFilterProxyModel::sortStable()
-{
- QStandardItemModel* model = new QStandardItemModel(5, 2);
- for (int r = 0; r < 5; r++) {
- const QString prefix = QLatin1String("Row:") + QString::number(r) + QLatin1String(", Column:");
- for (int c = 0; c < 2; c++) {
- QStandardItem* item = new QStandardItem(prefix + QString::number(c));
- for (int i = 0; i < 3; i++) {
- QStandardItem* child = new QStandardItem(QLatin1String("Item ") + QString::number(i));
- item->appendRow( child );
- }
- model->setItem(r, c, item);
- }
- }
- model->setHorizontalHeaderItem( 0, new QStandardItem( "Name" ));
- model->setHorizontalHeaderItem( 1, new QStandardItem( "Value" ));
-
- QSortFilterProxyModel *filterModel = new QSortFilterProxyModel(model);
- filterModel->setSourceModel(model);
-
- QTreeView *view = new QTreeView;
- view->setModel(filterModel);
- QModelIndex firstRoot = filterModel->index(0,0);
- view->expand(firstRoot);
- view->setSortingEnabled(true);
-
- view->model()->sort(1, Qt::DescendingOrder);
- QVariant lastItemData =filterModel->index(2,0, firstRoot).data();
- view->model()->sort(1, Qt::DescendingOrder);
- QCOMPARE(lastItemData, filterModel->index(2,0, firstRoot).data());
-}
-
-void tst_QSortFilterProxyModel::hiddenColumns()
-{
- class MyStandardItemModel : public QStandardItemModel
- {
- public:
- MyStandardItemModel() : QStandardItemModel(0,5) {}
- void reset()
- { beginResetModel(); endResetModel(); }
- friend class tst_QSortFilterProxyModel;
- } model;
- QSortFilterProxyModel proxy;
- proxy.setSourceModel(&model);
-
- QTableView view;
- view.setModel(&proxy);
-
- view.hideColumn(0);
-
- QVERIFY(view.isColumnHidden(0));
- model.blockSignals(true);
- model.setRowCount(1);
- model.blockSignals(false);
- model.reset();
-
- // In the initial bug report that spawned this test, this would be false
- // because resetting model would also reset the hidden columns.
- QVERIFY(view.isColumnHidden(0));
-}
-
-void tst_QSortFilterProxyModel::insertRowsSort()
-{
- QStandardItemModel model(2,2);
- QSortFilterProxyModel proxyModel;
- proxyModel.setSourceModel(&model);
-
- proxyModel.sort(0);
- QCOMPARE(proxyModel.sortColumn(), 0);
-
- model.insertColumns(0, 3, model.index(0,0));
- QCOMPARE(proxyModel.sortColumn(), 0);
-
- model.removeColumns(0, 3, model.index(0,0));
- QCOMPARE(proxyModel.sortColumn(), 0);
-}
-
-void tst_QSortFilterProxyModel::staticSorting()
-{
- QStandardItemModel model(0, 1);
- QSortFilterProxyModel proxy;
- proxy.setSourceModel(&model);
- proxy.setDynamicSortFilter(false);
- QStringList initial = QString("bateau avion dragon hirondelle flamme camion elephant").split(QLatin1Char(' '));
-
- // prepare model
- QStandardItem *root = model.invisibleRootItem ();
- QList<QStandardItem *> items;
- for (int i = 0; i < initial.count(); ++i) {
- items.append(new QStandardItem(initial.at(i)));
- }
- root->insertRows(0, items);
- QCOMPARE(model.rowCount(QModelIndex()), initial.count());
- QCOMPARE(model.columnCount(QModelIndex()), 1);
-
- // make sure the proxy is unsorted
- QCOMPARE(proxy.columnCount(QModelIndex()), 1);
- QCOMPARE(proxy.rowCount(QModelIndex()), initial.count());
- for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) {
- QModelIndex index = proxy.index(row, 0, QModelIndex());
- QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), initial.at(row));
- }
-
- // sort
- proxy.sort(0);
-
- QStringList expected = initial;
- expected.sort();
- // make sure the proxy is sorted
- for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) {
- QModelIndex index = proxy.index(row, 0, QModelIndex());
- QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expected.at(row));
- }
-
- //update one item.
- items.first()->setData("girafe", Qt::DisplayRole);
-
- // make sure the proxy is updated but not sorted
- expected.replaceInStrings("bateau", "girafe");
- for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) {
- QModelIndex index = proxy.index(row, 0, QModelIndex());
- QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expected.at(row));
- }
-
- // sort again
- proxy.sort(0);
- expected.sort();
-
- // make sure the proxy is sorted
- for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) {
- QModelIndex index = proxy.index(row, 0, QModelIndex());
- QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expected.at(row));
- }
-}
-
-void tst_QSortFilterProxyModel::dynamicSorting()
-{
- QStringListModel model1;
- const QStringList initial = QString("bateau avion dragon hirondelle flamme camion elephant").split(QLatin1Char(' '));
- model1.setStringList(initial);
- QSortFilterProxyModel proxy1;
- proxy1.setDynamicSortFilter(false);
- proxy1.sort(0);
- proxy1.setSourceModel(&model1);
-
- QCOMPARE(proxy1.columnCount(QModelIndex()), 1);
- //the model should not be sorted because sorting has not been set to dynamic yet.
- QCOMPARE(proxy1.rowCount(QModelIndex()), initial.count());
- for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) {
- QModelIndex index = proxy1.index(row, 0, QModelIndex());
- QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), initial.at(row));
- }
-
- proxy1.setDynamicSortFilter(true);
-
- //now the model should be sorted.
- QStringList expected = initial;
- expected.sort();
- for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) {
- QModelIndex index = proxy1.index(row, 0, QModelIndex());
- QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), expected.at(row));
- }
-
- QStringList initial2 = initial;
- initial2.replaceInStrings("bateau", "girafe");
- model1.setStringList(initial2); //this will cause a reset
-
- QStringList expected2 = initial2;
- expected2.sort();
-
- //now the model should still be sorted.
- for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) {
- QModelIndex index = proxy1.index(row, 0, QModelIndex());
- QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), expected2.at(row));
- }
-
- QStringListModel model2(initial);
- proxy1.setSourceModel(&model2);
-
- //the model should again be sorted
- for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) {
- QModelIndex index = proxy1.index(row, 0, QModelIndex());
- QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), expected.at(row));
- }
-
- //set up the sorting before seting the model up
- QSortFilterProxyModel proxy2;
- proxy2.sort(0);
- proxy2.setSourceModel(&model2);
- for (int row = 0; row < proxy2.rowCount(QModelIndex()); ++row) {
- QModelIndex index = proxy2.index(row, 0, QModelIndex());
- QCOMPARE(proxy2.data(index, Qt::DisplayRole).toString(), expected.at(row));
- }
-}
-
-class QtTestModel: public QAbstractItemModel
-{
-public:
- QtTestModel(int _rows, int _cols, QObject *parent = 0)
- : QAbstractItemModel(parent)
- , rows(_rows)
- , cols(_cols)
- , wrongIndex(false)
- {
- }
-
- bool canFetchMore(const QModelIndex &idx) const
- {
- return !fetched.contains(idx);
- }
-
- void fetchMore(const QModelIndex &idx)
- {
- if (fetched.contains(idx))
- return;
- beginInsertRows(idx, 0, rows-1);
- fetched.insert(idx);
- endInsertRows();
- }
-
- bool hasChildren(const QModelIndex & = QModelIndex()) const
- {
- return true;
- }
-
- int rowCount(const QModelIndex& parent = QModelIndex()) const
- {
- return fetched.contains(parent) ? rows : 0;
- }
-
- int columnCount(const QModelIndex& parent = QModelIndex()) const
- {
- Q_UNUSED(parent);
- return cols;
- }
-
- QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const
- {
- if (row < 0 || column < 0 || column >= cols || row >= rows) {
- return QModelIndex();
- }
- QModelIndex i = createIndex(row, column, int(parent.internalId() + 1));
- parentHash[i] = parent;
- return i;
- }
-
- QModelIndex parent(const QModelIndex &index) const
- {
- if (!parentHash.contains(index))
- return QModelIndex();
- return parentHash[index];
- }
-
- QVariant data(const QModelIndex &idx, int role) const
- {
- if (!idx.isValid())
- return QVariant();
-
- if (role == Qt::DisplayRole) {
- if (idx.row() < 0 || idx.column() < 0 || idx.column() >= cols || idx.row() >= rows) {
- wrongIndex = true;
- qWarning("Invalid modelIndex [%d,%d,%p]", idx.row(), idx.column(),
- idx.internalPointer());
- }
- return QLatin1Char('[') + QString::number(idx.row()) + QLatin1Char(',')
- + QString::number(idx.column()) + QLatin1Char(']');
- }
- return QVariant();
- }
-
- QSet<QModelIndex> fetched;
- int rows, cols;
- mutable bool wrongIndex;
- mutable QMap<QModelIndex,QModelIndex> parentHash;
-};
-
-void tst_QSortFilterProxyModel::fetchMore()
-{
- QtTestModel model(10,10);
- QSortFilterProxyModel proxy;
- proxy.setSourceModel(&model);
- QVERIFY(proxy.canFetchMore(QModelIndex()));
- QVERIFY(proxy.hasChildren());
- while (proxy.canFetchMore(QModelIndex()))
- proxy.fetchMore(QModelIndex());
- QCOMPARE(proxy.rowCount(), 10);
- QCOMPARE(proxy.columnCount(), 10);
-
- QModelIndex idx = proxy.index(1,1);
- QVERIFY(idx.isValid());
- QVERIFY(proxy.canFetchMore(idx));
- QVERIFY(proxy.hasChildren(idx));
- while (proxy.canFetchMore(idx))
- proxy.fetchMore(idx);
- QCOMPARE(proxy.rowCount(idx), 10);
- QCOMPARE(proxy.columnCount(idx), 10);
-}
-
-void tst_QSortFilterProxyModel::hiddenChildren()
-{
- QStandardItemModel model;
- QSortFilterProxyModel proxy;
- proxy.setSourceModel(&model);
- proxy.setDynamicSortFilter(true);
-
- QStandardItem *itemA = new QStandardItem("A VISIBLE");
- model.appendRow(itemA);
- QStandardItem *itemB = new QStandardItem("B VISIBLE");
- itemA->appendRow(itemB);
- QStandardItem *itemC = new QStandardItem("C");
- itemA->appendRow(itemC);
- proxy.setFilterRegExp("VISIBLE");
-
- QCOMPARE(proxy.rowCount(QModelIndex()) , 1);
- QPersistentModelIndex indexA = proxy.index(0,0);
- QCOMPARE(proxy.data(indexA).toString(), QString::fromLatin1("A VISIBLE"));
-
- QCOMPARE(proxy.rowCount(indexA) , 1);
- QPersistentModelIndex indexB = proxy.index(0, 0, indexA);
- QCOMPARE(proxy.data(indexB).toString(), QString::fromLatin1("B VISIBLE"));
-
- itemA->setText("A");
- QCOMPARE(proxy.rowCount(QModelIndex()), 0);
- QVERIFY(!indexA.isValid());
- QVERIFY(!indexB.isValid());
-
- itemB->setText("B");
- itemA->setText("A VISIBLE");
- itemC->setText("C VISIBLE");
-
- QCOMPARE(proxy.rowCount(QModelIndex()), 1);
- indexA = proxy.index(0,0);
- QCOMPARE(proxy.data(indexA).toString(), QString::fromLatin1("A VISIBLE"));
-
- QCOMPARE(proxy.rowCount(indexA) , 1);
- QModelIndex indexC = proxy.index(0, 0, indexA);
- QCOMPARE(proxy.data(indexC).toString(), QString::fromLatin1("C VISIBLE"));
-
- proxy.setFilterRegExp("C");
- QCOMPARE(proxy.rowCount(QModelIndex()), 0);
- itemC->setText("invisible");
- itemA->setText("AC");
-
- QCOMPARE(proxy.rowCount(QModelIndex()), 1);
- indexA = proxy.index(0,0);
- QCOMPARE(proxy.data(indexA).toString(), QString::fromLatin1("AC"));
- QCOMPARE(proxy.rowCount(indexA) , 0);
-}
-
-void tst_QSortFilterProxyModel::mapFromToSource()
-{
- QtTestModel source(10,10);
- source.fetchMore(QModelIndex());
- QSortFilterProxyModel proxy;
- proxy.setSourceModel(&source);
- QCOMPARE(proxy.mapFromSource(source.index(5, 4)), proxy.index(5, 4));
- QCOMPARE(proxy.mapToSource(proxy.index(3, 2)), source.index(3, 2));
- QCOMPARE(proxy.mapFromSource(QModelIndex()), QModelIndex());
- QCOMPARE(proxy.mapToSource(QModelIndex()), QModelIndex());
-
-#ifdef QT_NO_DEBUG //if Qt is compiled in debug mode, this will assert
- QTest::ignoreMessage(QtWarningMsg, "QSortFilterProxyModel: index from wrong model passed to mapToSource");
- QCOMPARE(proxy.mapToSource(source.index(2, 3)), QModelIndex());
- QTest::ignoreMessage(QtWarningMsg, "QSortFilterProxyModel: index from wrong model passed to mapFromSource");
- QCOMPARE(proxy.mapFromSource(proxy.index(6, 2)), QModelIndex());
-#endif
-}
-
-static QStandardItem *addEntry(QStandardItem* pParent, const QString &description)
-{
- QStandardItem* pItem = new QStandardItem(description);
- pParent->appendRow(pItem);
- return pItem;
-}
-
-void tst_QSortFilterProxyModel::removeRowsRecursive()
-{
- QStandardItemModel pModel;
- QStandardItem *pItem1 = new QStandardItem("root");
- pModel.appendRow(pItem1);
- QList<QStandardItem *> items;
-
- QStandardItem *pItem11 = addEntry(pItem1,"Sub-heading");
- items << pItem11;
- QStandardItem *pItem111 = addEntry(pItem11,"A");
- items << pItem111;
- items << addEntry(pItem111,"A1");
- items << addEntry(pItem111,"A2");
- QStandardItem *pItem112 = addEntry(pItem11,"B");
- items << pItem112;
- items << addEntry(pItem112,"B1");
- items << addEntry(pItem112,"B2");
- QStandardItem *pItem1123 = addEntry(pItem112,"B3");
- items << pItem1123;
- items << addEntry(pItem1123,"B3-");
-
- QSortFilterProxyModel proxy;
- proxy.setSourceModel(&pModel);
-
- QList<QPersistentModelIndex> sourceIndexes;
- QList<QPersistentModelIndex> proxyIndexes;
- foreach (QStandardItem *item, items) {
- QModelIndex idx = item->index();
- sourceIndexes << idx;
- proxyIndexes << proxy.mapFromSource(idx);
- }
-
- foreach (const QPersistentModelIndex &pidx, sourceIndexes)
- QVERIFY(pidx.isValid());
- foreach (const QPersistentModelIndex &pidx, proxyIndexes)
- QVERIFY(pidx.isValid());
-
- QList<QStandardItem*> itemRow = pItem1->takeRow(0);
-
- QCOMPARE(itemRow.count(), 1);
- QCOMPARE(itemRow.first(), pItem11);
-
- foreach (const QPersistentModelIndex &pidx, sourceIndexes)
- QVERIFY(!pidx.isValid());
- foreach (const QPersistentModelIndex &pidx, proxyIndexes)
- QVERIFY(!pidx.isValid());
-
- delete pItem11;
-}
-
-void tst_QSortFilterProxyModel::doubleProxySelectionSetSourceModel()
-{
- QStandardItemModel *model1 = new QStandardItemModel;
- QStandardItem *parentItem = model1->invisibleRootItem();
- for (int i = 0; i < 4; ++i) {
- QStandardItem *item = new QStandardItem(QLatin1String("model1 item ") + QString::number(i));
- parentItem->appendRow(item);
- parentItem = item;
- }
-
- QStandardItemModel *model2 = new QStandardItemModel;
- QStandardItem *parentItem2 = model2->invisibleRootItem();
- for (int i = 0; i < 4; ++i) {
- QStandardItem *item = new QStandardItem(QLatin1String("model2 item ") + QString::number(i));
- parentItem2->appendRow(item);
- parentItem2 = item;
- }
-
- QSortFilterProxyModel *toggleProxy = new QSortFilterProxyModel;
- toggleProxy->setSourceModel(model1);
-
- QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel;
- proxyModel->setSourceModel(toggleProxy);
-
- QModelIndex mi = proxyModel->index(0, 0, proxyModel->index(0, 0, proxyModel->index(0, 0)));
- QItemSelectionModel ism(proxyModel);
- ism.select(mi, QItemSelectionModel::Select);
- QModelIndexList mil = ism.selectedIndexes();
- QCOMPARE(mil.count(), 1);
- QCOMPARE(mil.first(), mi);
-
- toggleProxy->setSourceModel(model2);
- // No crash, it's good news!
- QVERIFY(ism.selection().isEmpty());
-}
-
-void tst_QSortFilterProxyModel::appearsAndSort()
-{
- class PModel : public QSortFilterProxyModel
- {
- public:
- PModel() : mVisible(false) {};
- protected:
- bool filterAcceptsRow(int, const QModelIndex &) const
- {
- return mVisible;
- }
-
- public:
- void updateXX()
- {
- mVisible = true;
- invalidate();
- }
- private:
- bool mVisible;
- } proxyModel;
-
- QStringListModel sourceModel;
- QStringList list;
- list << "b" << "a" << "c";
- sourceModel.setStringList(list);
-
- proxyModel.setSourceModel(&sourceModel);
- proxyModel.setDynamicSortFilter(true);
- proxyModel.sort(0, Qt::AscendingOrder);
-
- QApplication::processEvents();
- QCOMPARE(sourceModel.rowCount(), 3);
- QCOMPARE(proxyModel.rowCount(), 0); //all rows are hidden at first;
-
- QSignalSpy spyAbout1(&proxyModel, &PModel::layoutAboutToBeChanged);
- QSignalSpy spyChanged1(&proxyModel, &PModel::layoutChanged);
-
- QVERIFY(spyAbout1.isValid());
- QVERIFY(spyChanged1.isValid());
-
- //introducing secondProxyModel to test the layoutChange when many items appears at once
- QSortFilterProxyModel secondProxyModel;
- secondProxyModel.setSourceModel(&proxyModel);
- secondProxyModel.setDynamicSortFilter(true);
- secondProxyModel.sort(0, Qt::DescendingOrder);
- QCOMPARE(secondProxyModel.rowCount(), 0); //all rows are hidden at first;
- QSignalSpy spyAbout2(&secondProxyModel, &QSortFilterProxyModel::layoutAboutToBeChanged);
- QSignalSpy spyChanged2(&secondProxyModel, &QSortFilterProxyModel::layoutChanged);
-
- QVERIFY(spyAbout2.isValid());
- QVERIFY(spyChanged2.isValid());
-
- proxyModel.updateXX();
- QApplication::processEvents();
- //now rows should be visible, and sorted
- QCOMPARE(proxyModel.rowCount(), 3);
- QCOMPARE(proxyModel.data(proxyModel.index(0,0), Qt::DisplayRole).toString(), QString::fromLatin1("a"));
- QCOMPARE(proxyModel.data(proxyModel.index(1,0), Qt::DisplayRole).toString(), QString::fromLatin1("b"));
- QCOMPARE(proxyModel.data(proxyModel.index(2,0), Qt::DisplayRole).toString(), QString::fromLatin1("c"));
-
- //now rows should be visible, and sorted
- QCOMPARE(secondProxyModel.rowCount(), 3);
- QCOMPARE(secondProxyModel.data(secondProxyModel.index(0,0), Qt::DisplayRole).toString(), QString::fromLatin1("c"));
- QCOMPARE(secondProxyModel.data(secondProxyModel.index(1,0), Qt::DisplayRole).toString(), QString::fromLatin1("b"));
- QCOMPARE(secondProxyModel.data(secondProxyModel.index(2,0), Qt::DisplayRole).toString(), QString::fromLatin1("a"));
-
- QCOMPARE(spyAbout1.count(), 1);
- QCOMPARE(spyChanged1.count(), 1);
- QCOMPARE(spyAbout2.count(), 1);
- QCOMPARE(spyChanged2.count(), 1);
-}
-
-void tst_QSortFilterProxyModel::unnecessaryDynamicSorting()
-{
- QStringListModel model;
- const QStringList initial = QString("bravo charlie delta echo").split(QLatin1Char(' '));
- model.setStringList(initial);
- QSortFilterProxyModel proxy;
- proxy.setDynamicSortFilter(false);
- proxy.setSourceModel(&model);
- proxy.sort(Qt::AscendingOrder);
-
- //append two rows
- int maxrows = proxy.rowCount(QModelIndex());
- model.insertRows(maxrows, 2);
- model.setData(model.index(maxrows, 0), QString("alpha"));
- model.setData(model.index(maxrows + 1, 0), QString("fondue"));
-
- //append new items to the initial string list and compare with model
- QStringList expected = initial;
- expected << QString("alpha") << QString("fondue");
-
- //if bug 7716 is present, new rows were prepended, when they should have been appended
- for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) {
- QModelIndex index = proxy.index(row, 0, QModelIndex());
- QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expected.at(row));
- }
-}
-
-class SelectionProxyModel : QAbstractProxyModel
-{
- Q_OBJECT
-public:
- SelectionProxyModel()
- : QAbstractProxyModel(), selectionModel(0)
- {
- }
-
- QModelIndex mapFromSource(QModelIndex const&) const
- { return QModelIndex(); }
-
- QModelIndex mapToSource(QModelIndex const&) const
- { return QModelIndex(); }
-
- QModelIndex index(int, int, const QModelIndex&) const
- { return QModelIndex(); }
-
- QModelIndex parent(const QModelIndex&) const
- { return QModelIndex(); }
-
- int rowCount(const QModelIndex&) const
- { return 0; }
-
- int columnCount(const QModelIndex&) const
- { return 0; }
-
- void setSourceModel( QAbstractItemModel *sourceModel )
- {
- beginResetModel();
- disconnect( sourceModel, SIGNAL(modelAboutToBeReset()), this, SLOT(sourceModelAboutToBeReset()) );
- QAbstractProxyModel::setSourceModel( sourceModel );
- connect( sourceModel, SIGNAL(modelAboutToBeReset()), this, SLOT(sourceModelAboutToBeReset()) );
- endResetModel();
- }
-
- void setSelectionModel( QItemSelectionModel *_selectionModel )
- {
- selectionModel = _selectionModel;
- }
-
-private slots:
- void sourceModelAboutToBeReset()
- {
- QVERIFY( selectionModel->selectedIndexes().size() == 1 );
- beginResetModel();
- }
-
- void sourceModelReset()
- {
- endResetModel();
- }
-
-private:
- QItemSelectionModel *selectionModel;
-};
-
-void tst_QSortFilterProxyModel::testMultipleProxiesWithSelection()
-{
- QStringListModel model;
- const QStringList initial = QString("bravo charlie delta echo").split(QLatin1Char(' '));
- model.setStringList(initial);
-
- QSortFilterProxyModel proxy;
- proxy.setSourceModel( &model );
-
- SelectionProxyModel proxy1;
- QSortFilterProxyModel proxy2;
-
- // Note that the order here matters. The order of the sourceAboutToBeReset
- // exposes the bug in QSortFilterProxyModel.
- proxy2.setSourceModel( &proxy );
- proxy1.setSourceModel( &proxy );
-
- QItemSelectionModel selectionModel(&proxy2);
- proxy1.setSelectionModel( &selectionModel );
-
- selectionModel.select( proxy2.index( 0, 0 ), QItemSelectionModel::Select );
-
- // trick the proxy into emitting begin/end reset signals.
- proxy.setSourceModel(0);
-}
-
-static bool isValid(const QItemSelection &selection)
-{
- foreach (const QItemSelectionRange &range, selection)
- if (!range.isValid())
- return false;
- return true;
-}
-
-void tst_QSortFilterProxyModel::mapSelectionFromSource()
-{
- QStringListModel model;
- const QStringList initial = QString("bravo charlie delta echo").split(QLatin1Char(' '));
- model.setStringList(initial);
-
- QSortFilterProxyModel proxy;
- proxy.setDynamicSortFilter(true);
- proxy.setFilterRegExp("d.*");
- proxy.setSourceModel(&model);
-
- // Only "delta" remains.
- QCOMPARE(proxy.rowCount(), 1);
-
- QItemSelection selection;
- QModelIndex charlie = model.index(1, 0);
- selection.append(QItemSelectionRange(charlie, charlie));
- QModelIndex delta = model.index(2, 0);
- selection.append(QItemSelectionRange(delta, delta));
- QModelIndex echo = model.index(3, 0);
- selection.append(QItemSelectionRange(echo, echo));
-
- QVERIFY(isValid(selection));
-
- QItemSelection proxiedSelection = proxy.mapSelectionFromSource(selection);
-
- // Only "delta" is in the mapped result.
- QCOMPARE(proxiedSelection.size(), 1);
- QVERIFY(isValid(proxiedSelection));
-}
-
-class Model10287 : public QStandardItemModel
-{
- Q_OBJECT
-
-public:
- Model10287(QObject *parent = 0)
- : QStandardItemModel(0, 1, parent)
- {
- parentItem = new QStandardItem("parent");
- parentItem->setData(false, Qt::UserRole);
- appendRow(parentItem);
-
- childItem = new QStandardItem("child");
- childItem->setData(true, Qt::UserRole);
- parentItem->appendRow(childItem);
-
- childItem2 = new QStandardItem("child2");
- childItem2->setData(true, Qt::UserRole);
- parentItem->appendRow(childItem2);
- }
-
- void removeChild()
- {
- childItem2->setData(false, Qt::UserRole);
- parentItem->removeRow(0);
- }
-
-private:
- QStandardItem *parentItem, *childItem, *childItem2;
-};
-
-class Proxy10287 : public QSortFilterProxyModel
-{
- Q_OBJECT
-
-public:
- Proxy10287(QAbstractItemModel *model, QObject *parent = 0)
- : QSortFilterProxyModel(parent)
- {
- setSourceModel(model);
- setDynamicSortFilter(true);
- }
-
-protected:
- virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
- {
- // Filter based on UserRole in model
- QModelIndex i = sourceModel()->index(source_row, 0, source_parent);
- return i.data(Qt::UserRole).toBool();
- }
-};
-
-void tst_QSortFilterProxyModel::unnecessaryMapCreation()
-{
- Model10287 m;
- Proxy10287 p(&m);
- m.removeChild();
- // No assert failure, it passes.
-}
-
-class FilteredColumnProxyModel : public QSortFilterProxyModel
-{
- Q_OBJECT
-public:
- FilteredColumnProxyModel(QObject *parent = 0)
- : QSortFilterProxyModel(parent)
- {
- }
-
-protected:
- bool filterAcceptsColumn(int column, const QModelIndex & /* source_parent */) const
- {
- return column % 2 != 0;
- }
-};
-
-void tst_QSortFilterProxyModel::filteredColumns()
-{
- DynamicTreeModel *model = new DynamicTreeModel(this);
-
- FilteredColumnProxyModel *proxy = new FilteredColumnProxyModel(this);
- proxy->setSourceModel(model);
-
- new QAbstractItemModelTester(proxy, this);
-
- ModelInsertCommand *insertCommand = new ModelInsertCommand(model, this);
- insertCommand->setNumCols(2);
- insertCommand->setStartRow(0);
- insertCommand->setEndRow(0);
- // Parent is QModelIndex()
- insertCommand->doCommand();
-}
-
-class ChangableHeaderData : public QStringListModel
-{
- Q_OBJECT
-public:
- explicit ChangableHeaderData(QObject *parent = 0)
- : QStringListModel(parent)
- {
-
- }
-
- void emitHeaderDataChanged()
- {
- headerDataChanged(Qt::Vertical, 0, rowCount() - 1);
- }
-};
-
-
-void tst_QSortFilterProxyModel::headerDataChanged()
-{
- ChangableHeaderData *model = new ChangableHeaderData(this);
-
- QStringList numbers;
- for (int i = 0; i < 10; ++i)
- numbers.append(QString::number(i));
- model->setStringList(numbers);
-
- QSortFilterProxyModel *proxy = new QSortFilterProxyModel(this);
- proxy->setSourceModel(model);
-
- new QAbstractItemModelTester(proxy, this);
-
- model->emitHeaderDataChanged();
-}
-
-void tst_QSortFilterProxyModel::resetInvalidate_data()
-{
- QTest::addColumn<int>("test");
- QTest::addColumn<bool>("works");
-
- QTest::newRow("nothing") << 0 << false;
- QTest::newRow("reset") << 1 << true;
- QTest::newRow("invalidate") << 2 << true;
- QTest::newRow("invalidate_filter") << 3 << true;
-}
-
-void tst_QSortFilterProxyModel::resetInvalidate()
-{
- QFETCH(int, test);
- QFETCH(bool, works);
-
- struct Proxy : QSortFilterProxyModel {
- QString pattern;
- virtual bool filterAcceptsRow(int source_row, const QModelIndex&) const
- {
- return sourceModel()->data(sourceModel()->index(source_row, 0)).toString().contains(pattern);
- }
- void notifyChange(int test)
- {
- switch (test) {
- case 0: break;
- case 1:
- beginResetModel();
- endResetModel();
- break;
- case 2: invalidate(); break;
- case 3: invalidateFilter(); break;
- }
- }
- };
-
- QStringListModel sourceModel(QStringList() << "Poisson" << "Vache" << "Brebis"
- << "Elephant" << "Cochon" << "Serpent"
- << "Mouton" << "Ecureuil" << "Mouche");
- Proxy proxy;
- proxy.pattern = QString::fromLatin1("n");
- proxy.setSourceModel(&sourceModel);
-
- QCOMPARE(proxy.rowCount(), 5);
- for (int i = 0; i < proxy.rowCount(); i++) {
- QVERIFY(proxy.data(proxy.index(i,0)).toString().contains('n'));
- }
-
- proxy.pattern = QString::fromLatin1("o");
- proxy.notifyChange(test);
-
- QCOMPARE(proxy.rowCount(), works ? 4 : 5);
- bool ok = true;
- for (int i = 0; i < proxy.rowCount(); i++) {
- if (!proxy.data(proxy.index(i,0)).toString().contains('o'))
- ok = false;
- }
- QCOMPARE(ok, works);
-}
-
-/**
- * A proxy which changes the background color for items ending in 'y' or 'r'
- */
-class CustomDataProxy : public QSortFilterProxyModel
-{
- Q_OBJECT
-
-public:
- CustomDataProxy(QObject *parent = 0)
- : QSortFilterProxyModel(parent)
- {
- setDynamicSortFilter(true);
- }
-
- void setSourceModel(QAbstractItemModel *sourceModel)
- {
- // It would be possible to use only the modelReset signal of the source model to clear
- // the data in *this, however, this requires that the slot is connected
- // before QSortFilterProxyModel::setSourceModel is called, and even then depends
- // on the order of invocation of slots being the same as the order of connection.
- // ie, not reliable.
-// connect(sourceModel, SIGNAL(modelReset()), SLOT(resetInternalData()));
- QSortFilterProxyModel::setSourceModel(sourceModel);
- // Making the connect after the setSourceModel call clears the data too late.
-// connect(sourceModel, SIGNAL(modelReset()), SLOT(resetInternalData()));
-
- // This could be done in data(), but the point is to need to cache something in the proxy
- // which needs to be cleared on reset.
- for (int i = 0; i < sourceModel->rowCount(); ++i)
- {
- if (sourceModel->index(i, 0).data().toString().endsWith(QLatin1Char('y')))
- {
- m_backgroundColours.insert(i, Qt::blue);
- } else if (sourceModel->index(i, 0).data().toString().endsWith(QLatin1Char('r')))
- {
- m_backgroundColours.insert(i, Qt::red);
- }
- }
- }
-
- QVariant data(const QModelIndex &index, int role) const
- {
- if (role != Qt::BackgroundRole)
- return QSortFilterProxyModel::data(index, role);
- return m_backgroundColours.value(index.row());
- }
-
-private slots:
- void resetInternalData()
- {
- m_backgroundColours.clear();
- }
-
-private:
- QHash<int, QColor> m_backgroundColours;
-};
-
-class ModelObserver : public QObject
-{
- Q_OBJECT
-public:
- ModelObserver(QAbstractItemModel *model, QObject *parent = 0)
- : QObject(parent), m_model(model)
- {
- connect(m_model, SIGNAL(modelAboutToBeReset()), SLOT(modelAboutToBeReset()));
- connect(m_model, SIGNAL(modelReset()), SLOT(modelReset()));
- }
-
-public slots:
- void modelAboutToBeReset()
- {
- int reds = 0, blues = 0;
- for (int i = 0; i < m_model->rowCount(); ++i)
- {
- QColor color = m_model->index(i, 0).data(Qt::BackgroundRole).value<QColor>();
- if (color == Qt::blue)
- ++blues;
- if (color == Qt::red)
- ++reds;
- }
- QCOMPARE(blues, 11);
- QCOMPARE(reds, 4);
- }
-
- void modelReset()
- {
- int reds = 0, blues = 0;
- for (int i = 0; i < m_model->rowCount(); ++i)
- {
- QColor color = m_model->index(i, 0).data(Qt::BackgroundRole).value<QColor>();
- if (color == Qt::blue)
- ++blues;
- if (color == Qt::red)
- ++reds;
- }
- QCOMPARE(reds, 0);
- QCOMPARE(blues, 0);
- }
-
-private:
- QAbstractItemModel * const m_model;
-
-};
-
-void tst_QSortFilterProxyModel::testResetInternalData()
-{
-
- QStringListModel model(QStringList() << "Monday"
- << "Tuesday"
- << "Wednesday"
- << "Thursday"
- << "Friday"
- << "January"
- << "February"
- << "March"
- << "April"
- << "May"
- << "Saturday"
- << "June"
- << "Sunday"
- << "July"
- << "August"
- << "September"
- << "October"
- << "November"
- << "December");
-
- CustomDataProxy proxy;
- proxy.setSourceModel(&model);
-
- ModelObserver observer(&proxy);
-
- // Cause the source model to reset.
- model.setStringList(QStringList() << "Spam" << "Eggs");
-
-}
-
-void tst_QSortFilterProxyModel::testParentLayoutChanged()
-{
- QStandardItemModel model;
- QStandardItem *parentItem = model.invisibleRootItem();
- for (int i = 0; i < 4; ++i) {
- {
- QStandardItem *item = new QStandardItem(QLatin1String("item ") + QString::number(i));
- parentItem->appendRow(item);
- }
- {
- QStandardItem *item = new QStandardItem(QLatin1String("item 1") + QString::number(i));
- parentItem->appendRow(item);
- parentItem = item;
- }
- }
- // item 0
- // item 10
- // - item 1
- // - item 11
- // - item 2
- // - item 12
- // ...
-
- QSortFilterProxyModel proxy;
- proxy.sort(0, Qt::AscendingOrder);
- proxy.setDynamicSortFilter(true);
-
- proxy.setSourceModel(&model);
- proxy.setObjectName("proxy");
-
- // When Proxy1 emits layoutChanged(QList<QPersistentModelIndex>) this
- // one will too, with mapped indexes.
- QSortFilterProxyModel proxy2;
- proxy2.sort(0, Qt::AscendingOrder);
- proxy2.setDynamicSortFilter(true);
-
- proxy2.setSourceModel(&proxy);
- proxy2.setObjectName("proxy2");
-
- QSignalSpy dataChangedSpy(&model, &QSortFilterProxyModel::dataChanged);
-
- QVERIFY(dataChangedSpy.isValid());
-
- // Verify that the no-arg signal is still emitted.
- QSignalSpy layoutAboutToBeChangedSpy(&proxy, &QSortFilterProxyModel::layoutAboutToBeChanged);
- QSignalSpy layoutChangedSpy(&proxy, &QSortFilterProxyModel::layoutChanged);
-
- QVERIFY(layoutAboutToBeChangedSpy.isValid());
- QVERIFY(layoutChangedSpy.isValid());
-
- QSignalSpy parentsAboutToBeChangedSpy(&proxy, &QSortFilterProxyModel::layoutAboutToBeChanged);
- QSignalSpy parentsChangedSpy(&proxy, &QSortFilterProxyModel::layoutChanged);
-
- QVERIFY(parentsAboutToBeChangedSpy.isValid());
- QVERIFY(parentsChangedSpy.isValid());
-
- QSignalSpy proxy2ParentsAboutToBeChangedSpy(&proxy2, &QSortFilterProxyModel::layoutAboutToBeChanged);
- QSignalSpy proxy2ParentsChangedSpy(&proxy2, &QSortFilterProxyModel::layoutChanged);
-
- QVERIFY(proxy2ParentsAboutToBeChangedSpy.isValid());
- QVERIFY(proxy2ParentsChangedSpy.isValid());
-
- QStandardItem *item = model.invisibleRootItem()->child(1)->child(1);
- QCOMPARE(item->text(), QStringLiteral("item 11"));
-
- // Ensure mapped:
- proxy.mapFromSource(model.indexFromItem(item));
-
- item->setText("Changed");
-
- QCOMPARE(dataChangedSpy.size(), 1);
- QCOMPARE(layoutAboutToBeChangedSpy.size(), 1);
- QCOMPARE(layoutChangedSpy.size(), 1);
- QCOMPARE(parentsAboutToBeChangedSpy.size(), 1);
- QCOMPARE(parentsChangedSpy.size(), 1);
- QCOMPARE(proxy2ParentsAboutToBeChangedSpy.size(), 1);
- QCOMPARE(proxy2ParentsChangedSpy.size(), 1);
-
- QVariantList beforeSignal = parentsAboutToBeChangedSpy.first();
- QVariantList afterSignal = parentsChangedSpy.first();
-
- QCOMPARE(beforeSignal.size(), 2);
- QCOMPARE(afterSignal.size(), 2);
-
- QList<QPersistentModelIndex> beforeParents = beforeSignal.first().value<QList<QPersistentModelIndex> >();
- QList<QPersistentModelIndex> afterParents = afterSignal.first().value<QList<QPersistentModelIndex> >();
-
- QCOMPARE(beforeParents.size(), 1);
- QCOMPARE(afterParents.size(), 1);
-
- QVERIFY(beforeParents.first().isValid());
- QVERIFY(beforeParents.first() == afterParents.first());
-
- QVERIFY(beforeParents.first() == proxy.mapFromSource(model.indexFromItem(model.invisibleRootItem()->child(1))));
-
- QList<QPersistentModelIndex> proxy2BeforeList = proxy2ParentsAboutToBeChangedSpy.first().first().value<QList<QPersistentModelIndex> >();
- QList<QPersistentModelIndex> proxy2AfterList = proxy2ParentsChangedSpy.first().first().value<QList<QPersistentModelIndex> >();
-
- QCOMPARE(proxy2BeforeList.size(), beforeParents.size());
- QCOMPARE(proxy2AfterList.size(), afterParents.size());
- foreach (const QPersistentModelIndex &idx, proxy2BeforeList)
- QVERIFY(beforeParents.contains(proxy2.mapToSource(idx)));
- foreach (const QPersistentModelIndex &idx, proxy2AfterList)
- QVERIFY(afterParents.contains(proxy2.mapToSource(idx)));
-}
-
-class SignalArgumentChecker : public QObject
-{
- Q_OBJECT
-public:
- SignalArgumentChecker(QAbstractItemModel *model, QAbstractProxyModel *proxy, QObject *parent = 0)
- : QObject(parent), m_proxy(proxy)
- {
- connect(model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), SLOT(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
- connect(model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), SLOT(rowsMoved(QModelIndex,int,int,QModelIndex,int)));
- connect(proxy, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>)), SLOT(layoutAboutToBeChanged(QList<QPersistentModelIndex>)));
- connect(proxy, SIGNAL(layoutChanged(QList<QPersistentModelIndex>)), SLOT(layoutChanged(QList<QPersistentModelIndex>)));
- }
-
-private slots:
- void rowsAboutToBeMoved(const QModelIndex &source, int, int, const QModelIndex &destination, int)
- {
- m_p1PersistentBefore = source;
- m_p2PersistentBefore = destination;
- m_p2FirstProxyChild = m_proxy->index(0, 0, m_proxy->mapFromSource(destination));
- }
-
- void rowsMoved(const QModelIndex &source, int, int, const QModelIndex &destination, int)
- {
- m_p1PersistentAfter = source;
- m_p2PersistentAfter = destination;
- }
-
- void layoutAboutToBeChanged(const QList<QPersistentModelIndex> &parents)
- {
- QVERIFY(m_p1PersistentBefore.isValid());
- QVERIFY(m_p2PersistentBefore.isValid());
- QCOMPARE(parents.size(), 2);
- QVERIFY(parents.first() != parents.at(1));
- QVERIFY(parents.contains(m_proxy->mapFromSource(m_p1PersistentBefore)));
- QVERIFY(parents.contains(m_proxy->mapFromSource(m_p2PersistentBefore)));
- }
-
- void layoutChanged(const QList<QPersistentModelIndex> &parents)
- {
- QVERIFY(m_p1PersistentAfter.isValid());
- QVERIFY(m_p2PersistentAfter.isValid());
- QCOMPARE(parents.size(), 2);
- QVERIFY(parents.first() != parents.at(1));
- QVERIFY(parents.contains(m_proxy->mapFromSource(m_p1PersistentAfter)));
- QVERIFY(parents.contains(m_proxy->mapFromSource(m_p2PersistentAfter)));
-
- // In the source model, the rows were moved to row 1 in the parent.
- // m_p2FirstProxyChild was created with row 0 in the proxy.
- // The moved rows in the proxy do not appear at row 1 because of sorting.
- // Sorting causes them to appear at row 0 instead, pushing what used to
- // be row 0 in the proxy down by two rows.
- QCOMPARE(m_p2FirstProxyChild.row(), 2);
- }
-
-private:
- QAbstractProxyModel *m_proxy;
- QPersistentModelIndex m_p1PersistentBefore;
- QPersistentModelIndex m_p2PersistentBefore;
- QPersistentModelIndex m_p1PersistentAfter;
- QPersistentModelIndex m_p2PersistentAfter;
-
- QPersistentModelIndex m_p2FirstProxyChild;
-};
-
-void tst_QSortFilterProxyModel::moveSourceRows()
-{
- DynamicTreeModel model;
-
- {
- ModelInsertCommand insertCommand(&model);
- insertCommand.setStartRow(0);
- insertCommand.setEndRow(9);
- insertCommand.doCommand();
- }
- {
- ModelInsertCommand insertCommand(&model);
- insertCommand.setAncestorRowNumbers(QList<int>() << 2);
- insertCommand.setStartRow(0);
- insertCommand.setEndRow(9);
- insertCommand.doCommand();
- }
- {
- ModelInsertCommand insertCommand(&model);
- insertCommand.setAncestorRowNumbers(QList<int>() << 5);
- insertCommand.setStartRow(0);
- insertCommand.setEndRow(9);
- insertCommand.doCommand();
- }
-
- QSortFilterProxyModel proxy;
- proxy.setDynamicSortFilter(true);
- proxy.sort(0, Qt::AscendingOrder);
-
- // We need to check the arguments at emission time
- SignalArgumentChecker checker(&model, &proxy);
-
- proxy.setSourceModel(&model);
-
- QSortFilterProxyModel filterProxy;
- filterProxy.setDynamicSortFilter(true);
- filterProxy.sort(0, Qt::AscendingOrder);
- filterProxy.setSourceModel(&proxy);
- filterProxy.setFilterRegExp("6"); // One of the parents
-
- QSortFilterProxyModel filterBothProxy;
- filterBothProxy.setDynamicSortFilter(true);
- filterBothProxy.sort(0, Qt::AscendingOrder);
- filterBothProxy.setSourceModel(&proxy);
- filterBothProxy.setFilterRegExp("5"); // The parents are 6 and 3. This filters both out.
-
- QSignalSpy modelBeforeSpy(&model, &DynamicTreeModel::rowsAboutToBeMoved);
- QSignalSpy modelAfterSpy(&model, &DynamicTreeModel::rowsMoved);
- QSignalSpy proxyBeforeMoveSpy(m_proxy, &QSortFilterProxyModel::rowsAboutToBeMoved);
- QSignalSpy proxyAfterMoveSpy(m_proxy, &QSortFilterProxyModel::rowsMoved);
- QSignalSpy proxyBeforeParentLayoutSpy(&proxy, &QSortFilterProxyModel::layoutAboutToBeChanged);
- QSignalSpy proxyAfterParentLayoutSpy(&proxy, &QSortFilterProxyModel::layoutChanged);
- QSignalSpy filterBeforeParentLayoutSpy(&filterProxy, &QSortFilterProxyModel::layoutAboutToBeChanged);
- QSignalSpy filterAfterParentLayoutSpy(&filterProxy, &QSortFilterProxyModel::layoutChanged);
- QSignalSpy filterBothBeforeParentLayoutSpy(&filterBothProxy, &QSortFilterProxyModel::layoutAboutToBeChanged);
- QSignalSpy filterBothAfterParentLayoutSpy(&filterBothProxy, &QSortFilterProxyModel::layoutChanged);
-
- QVERIFY(modelBeforeSpy.isValid());
- QVERIFY(modelAfterSpy.isValid());
- QVERIFY(proxyBeforeMoveSpy.isValid());
- QVERIFY(proxyAfterMoveSpy.isValid());
- QVERIFY(proxyBeforeParentLayoutSpy.isValid());
- QVERIFY(proxyAfterParentLayoutSpy.isValid());
- QVERIFY(filterBeforeParentLayoutSpy.isValid());
- QVERIFY(filterAfterParentLayoutSpy.isValid());
- QVERIFY(filterBothBeforeParentLayoutSpy.isValid());
- QVERIFY(filterBothAfterParentLayoutSpy.isValid());
-
- {
- ModelMoveCommand moveCommand(&model, 0);
- moveCommand.setAncestorRowNumbers(QList<int>() << 2);
- moveCommand.setDestAncestors(QList<int>() << 5);
- moveCommand.setStartRow(3);
- moveCommand.setEndRow(4);
- moveCommand.setDestRow(1);
- moveCommand.doCommand();
- }
-
- // Proxy notifies layout change
- QCOMPARE(modelBeforeSpy.size(), 1);
- QCOMPARE(proxyBeforeParentLayoutSpy.size(), 1);
- QCOMPARE(modelAfterSpy.size(), 1);
- QCOMPARE(proxyAfterParentLayoutSpy.size(), 1);
-
- // But it doesn't notify a move.
- QCOMPARE(proxyBeforeMoveSpy.size(), 0);
- QCOMPARE(proxyAfterMoveSpy.size(), 0);
-
- QCOMPARE(filterBeforeParentLayoutSpy.size(), 1);
- QCOMPARE(filterAfterParentLayoutSpy.size(), 1);
-
- QList<QPersistentModelIndex> filterBeforeParents = filterBeforeParentLayoutSpy.first().first().value<QList<QPersistentModelIndex> >();
- QList<QPersistentModelIndex> filterAfterParents = filterAfterParentLayoutSpy.first().first().value<QList<QPersistentModelIndex> >();
-
- QCOMPARE(filterBeforeParents.size(), 1);
- QCOMPARE(filterAfterParents.size(), 1);
-
- QCOMPARE(
- filterBeforeParentLayoutSpy.first().at(1).value<QAbstractItemModel::LayoutChangeHint>(),
- QAbstractItemModel::NoLayoutChangeHint);
- QCOMPARE(filterAfterParentLayoutSpy.first().at(1).value<QAbstractItemModel::LayoutChangeHint>(),
- QAbstractItemModel::NoLayoutChangeHint);
-
- QCOMPARE(filterBothBeforeParentLayoutSpy.size(), 0);
- QCOMPARE(filterBothAfterParentLayoutSpy.size(), 0);
-}
-
-class FilterProxy : public QSortFilterProxyModel
-{
- Q_OBJECT
-public:
- FilterProxy(QObject *parent = 0)
- : QSortFilterProxyModel(parent),
- mode(false)
- {
-
- }
-
-public slots:
- void setMode(bool on)
- {
- mode = on;
- invalidateFilter();
- }
-
-protected:
- virtual bool filterAcceptsRow ( int source_row, const QModelIndex & source_parent ) const
- {
- if (mode) {
- if (!source_parent.isValid()) {
- return true;
- } else {
- return (source_row % 2) != 0;
- }
- } else {
- if (!source_parent.isValid()) {
- return source_row >= 2 && source_row < 10;
- } else {
- return true;
- }
- }
- }
-
-private:
- bool mode;
-};
-
-void tst_QSortFilterProxyModel::hierarchyFilterInvalidation()
-{
- QStandardItemModel model;
- for (int i = 0; i < 10; ++i) {
- const QString rowText = QLatin1String("Row ") + QString::number(i);
- QStandardItem *child = new QStandardItem(rowText);
- for (int j = 0; j < 1; ++j) {
- child->appendRow(new QStandardItem(rowText + QLatin1Char('/') + QString::number(j)));
- }
- model.appendRow(child);
- }
-
- FilterProxy proxy;
- proxy.setSourceModel(&model);
-
- QTreeView view;
- view.setModel(&proxy);
-
- view.setCurrentIndex(proxy.index(2, 0).child(0, 0));
-
- view.show();
- QVERIFY(QTest::qWaitForWindowExposed(&view));
-
- proxy.setMode(true);
-}
-
-class FilterProxy2 : public QSortFilterProxyModel
-{
- Q_OBJECT
-public:
- FilterProxy2(QObject *parent = 0)
- : QSortFilterProxyModel(parent),
- mode(false)
- {
-
- }
-
-public slots:
- void setMode(bool on)
- {
- mode = on;
- invalidateFilter();
- }
-
-protected:
- virtual bool filterAcceptsRow ( int source_row, const QModelIndex & source_parent ) const
- {
- if (source_parent.isValid()) {
- return true;
- } else {
- if (0 == source_row) {
- return true;
- } else {
- return !mode;
- }
- }
- }
-
-private:
- bool mode;
-};
-
-void tst_QSortFilterProxyModel::simpleFilterInvalidation()
-{
- QStandardItemModel model;
- for (int i = 0; i < 2; ++i) {
- QStandardItem *child = new QStandardItem(QLatin1String("Row ") + QString::number(i));
- child->appendRow(new QStandardItem("child"));
- model.appendRow(child);
- }
-
- FilterProxy2 proxy;
- proxy.setSourceModel(&model);
-
- QTreeView view;
- view.setModel(&proxy);
-
- view.show();
- QVERIFY(QTest::qWaitForWindowExposed(&view));
-
- proxy.setMode(true);
- model.insertRow(0, new QStandardItem("extra"));
-}
-
-class CustomRoleNameModel : public QAbstractListModel
-{
- Q_OBJECT
-public:
- CustomRoleNameModel(QObject *parent = 0) : QAbstractListModel(parent) {}
-
- QVariant data(const QModelIndex &index, int role) const
- {
- Q_UNUSED(index);
- Q_UNUSED(role);
- return QVariant();
- }
-
- int rowCount(const QModelIndex &parent = QModelIndex()) const
- {
- Q_UNUSED(parent);
- return 0;
- }
-
- QHash<int, QByteArray> roleNames() const
- {
- QHash<int, QByteArray> rn = QAbstractListModel::roleNames();
- rn[Qt::UserRole + 1] = "custom";
- return rn;
- }
-};
-
-void tst_QSortFilterProxyModel::chainedProxyModelRoleNames()
-{
- QSortFilterProxyModel proxy1;
- QSortFilterProxyModel proxy2;
- CustomRoleNameModel customModel;
-
- proxy2.setSourceModel(&proxy1);
-
- // changing the sourceModel of proxy1 must also update roleNames of proxy2
- proxy1.setSourceModel(&customModel);
- QVERIFY(proxy2.roleNames().value(Qt::UserRole + 1) == "custom");
-}
-
-// A source model with ABABAB rows, where only A rows accept drops.
-// It will then be sorted by a QSFPM.
-class DropOnOddRows : public QAbstractListModel
-{
- Q_OBJECT
-public:
- DropOnOddRows(QObject *parent = 0) : QAbstractListModel(parent) {}
-
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
- {
- if (role == Qt::DisplayRole)
- return (index.row() % 2 == 0) ? "A" : "B";
- return QVariant();
- }
-
- int rowCount(const QModelIndex &parent = QModelIndex()) const override
- {
- Q_UNUSED(parent);
- return 10;
- }
-
- bool canDropMimeData(const QMimeData *, Qt::DropAction,
- int row, int column, const QModelIndex &parent) const override
- {
- Q_UNUSED(row);
- Q_UNUSED(column);
- return parent.row() % 2 == 0;
- }
-};
-
-class SourceAssertion : public QSortFilterProxyModel
-{
- Q_OBJECT
-public:
- explicit SourceAssertion(QObject *parent = 0)
- : QSortFilterProxyModel(parent)
- {
-
- }
-
- QModelIndex mapToSource(const QModelIndex &proxyIndex) const override
- {
- Q_ASSERT(sourceModel());
- return QSortFilterProxyModel::mapToSource(proxyIndex);
- }
-};
-
-void tst_QSortFilterProxyModel::noMapAfterSourceDelete()
-{
- SourceAssertion proxy;
- QStringListModel *model = new QStringListModel(QStringList() << "Foo" << "Bar");
-
- proxy.setSourceModel(model);
-
- // Create mappings
- QPersistentModelIndex persistent = proxy.index(0, 0);
-
- QVERIFY(persistent.isValid());
-
- delete model;
-
- QVERIFY(!persistent.isValid());
-}
-
-// QTBUG-39549, test whether canDropMimeData(), dropMimeData() are proxied as well
-// by invoking them on a QSortFilterProxyModel proxying a QStandardItemModel that allows drops
-// on row #1, filtering for that row.
-class DropTestModel : public QStandardItemModel {
-public:
- explicit DropTestModel(QObject *parent = 0) : QStandardItemModel(0, 1, parent)
- {
- appendRow(new QStandardItem(QStringLiteral("Row0")));
- appendRow(new QStandardItem(QStringLiteral("Row1")));
- }
-
- bool canDropMimeData(const QMimeData *, Qt::DropAction,
- int row, int /* column */, const QModelIndex & /* parent */) const override
- { return row == 1; }
-
- bool dropMimeData(const QMimeData *, Qt::DropAction,
- int row, int /* column */, const QModelIndex & /* parent */) override
- { return row == 1; }
-};
-
-void tst_QSortFilterProxyModel::forwardDropApi()
-{
- QSortFilterProxyModel model;
- model.setSourceModel(new DropTestModel(&model));
- model.setFilterFixedString(QStringLiteral("Row1"));
- QCOMPARE(model.rowCount(), 1);
- QVERIFY(model.canDropMimeData(0, Qt::CopyAction, 0, 0, QModelIndex()));
- QVERIFY(model.dropMimeData(0, Qt::CopyAction, 0, 0, QModelIndex()));
-}
-
-static QString rowTexts(QAbstractItemModel *model) {
- QString str;
- for (int row = 0 ; row < model->rowCount(); ++row)
- str += model->index(row, 0).data().toString();
- return str;
-}
-
-void tst_QSortFilterProxyModel::canDropMimeData()
-{
- // Given a source model which only supports dropping on even rows
- DropOnOddRows sourceModel;
- QCOMPARE(rowTexts(&sourceModel), QString("ABABABABAB"));
-
- // and a proxy model that sorts the rows
- QSortFilterProxyModel proxy;
- proxy.setSourceModel(&sourceModel);
- proxy.sort(0, Qt::AscendingOrder);
- QCOMPARE(rowTexts(&proxy), QString("AAAAABBBBB"));
-
- // the proxy should correctly map canDropMimeData to the source model,
- // i.e. accept drops on the first 5 rows and refuse drops on the next 5.
- for (int row = 0; row < proxy.rowCount(); ++row)
- QCOMPARE(proxy.canDropMimeData(0, Qt::CopyAction, -1, -1, proxy.index(row, 0)), row < 5);
-}
-
-void tst_QSortFilterProxyModel::resortingDoesNotBreakTreeModels()
-{
- QStandardItemModel *treeModel = new QStandardItemModel(this);
- QStandardItem *e1 = new QStandardItem("Loading...");
- e1->appendRow(new QStandardItem("entry10"));
- treeModel->appendRow(e1);
- QStandardItem *e0 = new QStandardItem("Loading...");
- e0->appendRow(new QStandardItem("entry00"));
- e0->appendRow(new QStandardItem("entry01"));
- treeModel->appendRow(e0);
-
- QSortFilterProxyModel proxy;
- proxy.setDynamicSortFilter(true);
- proxy.sort(0);
- proxy.setSourceModel(treeModel);
-
- QAbstractItemModelTester modelTester(&proxy);
-
- QCOMPARE(proxy.rowCount(), 2);
- e1->setText("entry1");
- e0->setText("entry0");
-
- QModelIndex pi0 = proxy.index(0, 0);
- QCOMPARE(pi0.data().toString(), QString("entry0"));
- QCOMPARE(proxy.rowCount(pi0), 2);
-
- QModelIndex pi01 = proxy.index(1, 0, pi0);
- QCOMPARE(pi01.data().toString(), QString("entry01"));
-
- QModelIndex pi1 = proxy.index(1, 0);
- QCOMPARE(pi1.data().toString(), QString("entry1"));
- QCOMPARE(proxy.rowCount(pi1), 1);
-}
-
-void tst_QSortFilterProxyModel::filterHint()
-{
- // test that a filtering model does not emit layoutChanged with a hint
- QStringListModel model(QStringList() << "one"
- << "two"
- << "three"
- << "four"
- << "five"
- << "six");
- QSortFilterProxyModel proxy1;
- proxy1.setSourceModel(&model);
- proxy1.setSortRole(Qt::DisplayRole);
- proxy1.setDynamicSortFilter(true);
- proxy1.sort(0);
-
- QSortFilterProxyModel proxy2;
- proxy2.setSourceModel(&proxy1);
- proxy2.setFilterRole(Qt::DisplayRole);
- proxy2.setFilterRegExp("^[^ ]*$");
- proxy2.setDynamicSortFilter(true);
-
- QSignalSpy proxy1BeforeSpy(&proxy1, &QSortFilterProxyModel::layoutAboutToBeChanged);
- QSignalSpy proxy1AfterSpy(&proxy1, &QSortFilterProxyModel::layoutChanged);
- QSignalSpy proxy2BeforeSpy(&proxy2, &QSortFilterProxyModel::layoutAboutToBeChanged);
- QSignalSpy proxy2AfterSpy(&proxy2, &QSortFilterProxyModel::layoutChanged);
-
- model.setData(model.index(2), QStringLiteral("modified three"), Qt::DisplayRole);
-
- // The first proxy was re-sorted as one item as changed.
- QCOMPARE(proxy1BeforeSpy.size(), 1);
- QCOMPARE(proxy1BeforeSpy.first().at(1).value<QAbstractItemModel::LayoutChangeHint>(),
- QAbstractItemModel::VerticalSortHint);
- QCOMPARE(proxy1AfterSpy.size(), 1);
- QCOMPARE(proxy1AfterSpy.first().at(1).value<QAbstractItemModel::LayoutChangeHint>(),
- QAbstractItemModel::VerticalSortHint);
-
- // But the second proxy must not have the VerticalSortHint since an item was filtered
- QCOMPARE(proxy2BeforeSpy.size(), 1);
- QCOMPARE(proxy2BeforeSpy.first().at(1).value<QAbstractItemModel::LayoutChangeHint>(),
- QAbstractItemModel::NoLayoutChangeHint);
- QCOMPARE(proxy2AfterSpy.size(), 1);
- QCOMPARE(proxy2AfterSpy.first().at(1).value<QAbstractItemModel::LayoutChangeHint>(),
- QAbstractItemModel::NoLayoutChangeHint);
-}
-
-/**
-
- Creates a model where each item has one child, to a set depth,
- and the last item has no children. For a model created with
- setDepth(4):
-
- - 1
- - - 2
- - - - 3
- - - - - 4
-*/
-class StepTreeModel : public QAbstractItemModel
-{
- Q_OBJECT
-public:
- StepTreeModel(QObject * parent = 0)
- : QAbstractItemModel(parent), m_depth(0) {}
-
- int columnCount(const QModelIndex& = QModelIndex()) const override { return 1; }
-
- int rowCount(const QModelIndex& parent = QModelIndex()) const override
- {
- quintptr parentId = (parent.isValid()) ? parent.internalId() : 0;
- return (parentId < m_depth) ? 1 : 0;
- }
-
- QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override
- {
- if (role != Qt::DisplayRole)
- return QVariant();
-
- return QString::number(index.internalId());
- }
-
- QModelIndex index(int, int, const QModelIndex& parent = QModelIndex()) const override
- {
- // QTBUG-44962: Would we always expect the parent to belong to the model
- qDebug() << parent.model() << this;
- Q_ASSERT(!parent.isValid() || parent.model() == this);
-
- quintptr parentId = (parent.isValid()) ? parent.internalId() : 0;
- if (parentId >= m_depth)
- return QModelIndex();
-
- return createIndex(0, 0, parentId + 1);
- }
-
- QModelIndex parent(const QModelIndex& index) const override
- {
- if (index.internalId() == 0)
- return QModelIndex();
-
- return createIndex(0, 0, index.internalId() - 1);
- }
-
- void setDepth(quintptr depth)
- {
- int parentIdWithLayoutChange = (m_depth < depth) ? m_depth : depth;
-
- QList<QPersistentModelIndex> parentsOfLayoutChange;
- parentsOfLayoutChange.push_back(createIndex(0, 0, parentIdWithLayoutChange));
-
- layoutAboutToBeChanged(parentsOfLayoutChange);
-
- auto existing = persistentIndexList();
-
- QList<QModelIndex> updated;
-
- for (auto idx : existing) {
- if (indexDepth(idx) <= depth)
- updated.push_back(idx);
- else
- updated.push_back({});
- }
-
- m_depth = depth;
-
- changePersistentIndexList(existing, updated);
-
- layoutChanged(parentsOfLayoutChange);
- }
-
-private:
- static quintptr indexDepth(QModelIndex const& index)
- {
- return (index.isValid()) ? 1 + indexDepth(index.parent()) : 0;
- }
-
-private:
- quintptr m_depth;
-};
-
-void tst_QSortFilterProxyModel::sourceLayoutChangeLeavesValidPersistentIndexes()
-{
- StepTreeModel model;
- Q_SET_OBJECT_NAME(model);
- model.setDepth(4);
-
- QSortFilterProxyModel proxy1;
- proxy1.setSourceModel(&model);
- Q_SET_OBJECT_NAME(proxy1);
-
- proxy1.setFilterRegExp("1|2");
-
- // The current state of things:
- // model proxy
- // - 1 - 1
- // - - 2 - - 2
- // - - - 3
- // - - - - 4
-
- // The setDepth call below removes '4' with a layoutChanged call.
- // Because the proxy filters that out anyway, the proxy doesn't need
- // to emit any signals or update persistent indexes.
-
- QPersistentModelIndex persistentIndex = proxy1.index(0, 0, proxy1.index(0, 0));
-
- model.setDepth(3);
-
- // Calling parent() causes the internalPointer to be used.
- // Before fixing QTBUG-47711, that could be a dangling pointer.
- // The use of qDebug here makes sufficient use of the heap to
- // cause corruption at runtime with normal use on linux (before
- // the fix). valgrind confirms the fix.
- qDebug() << persistentIndex.parent();
- QVERIFY(persistentIndex.parent().isValid());
-}
-
-void tst_QSortFilterProxyModel::rowMoveLeavesValidPersistentIndexes()
-{
- DynamicTreeModel model;
- Q_SET_OBJECT_NAME(model);
-
- QList<int> ancestors;
- for (auto i = 0; i < 5; ++i)
- {
- Q_UNUSED(i);
- ModelInsertCommand insertCommand(&model);
- insertCommand.setAncestorRowNumbers(ancestors);
- insertCommand.setStartRow(0);
- insertCommand.setEndRow(0);
- insertCommand.doCommand();
- ancestors.push_back(0);
- }
-
- QSortFilterProxyModel proxy1;
- proxy1.setSourceModel(&model);
- Q_SET_OBJECT_NAME(proxy1);
-
- proxy1.setFilterRegExp("1|2");
-
- auto item5 = model.match(model.index(0, 0), Qt::DisplayRole, "5", 1, Qt::MatchRecursive).first();
- auto item3 = model.match(model.index(0, 0), Qt::DisplayRole, "3", 1, Qt::MatchRecursive).first();
-
- Q_ASSERT(item5.isValid());
- Q_ASSERT(item3.isValid());
-
- QPersistentModelIndex persistentIndex = proxy1.match(proxy1.index(0, 0), Qt::DisplayRole, "2", 1, Qt::MatchRecursive).first();
-
- ModelMoveCommand moveCommand(&model, 0);
- moveCommand.setAncestorRowNumbers(QList<int>{0, 0, 0, 0});
- moveCommand.setStartRow(0);
- moveCommand.setEndRow(0);
- moveCommand.setDestRow(0);
- moveCommand.setDestAncestors(QList<int>{0, 0, 0});
- moveCommand.doCommand();
-
- // Calling parent() causes the internalPointer to be used.
- // Before fixing QTBUG-47711 (moveRows case), that could be
- // a dangling pointer.
- QVERIFY(persistentIndex.parent().isValid());
-}
-
-void tst_QSortFilterProxyModel::emitLayoutChangedOnlyIfSortingChanged_data()
-{
- QTest::addColumn<int>("changedRow");
- QTest::addColumn<Qt::ItemDataRole>("changedRole");
- QTest::addColumn<QString>("newData");
- QTest::addColumn<QString>("expectedSourceRowTexts");
- QTest::addColumn<QString>("expectedProxyRowTexts");
- QTest::addColumn<int>("expectedLayoutChanged");
-
- // Starting point:
- // a source model with 8,7,6,5,4,3,2,1
- // a proxy model keeping only even rows and sorting them, therefore showing 2,4,6,8
-
- // When setData changes ordering, layoutChanged should be emitted
- QTest::newRow("ordering_change") << 0 << Qt::DisplayRole << "0" << "07654321" << "0246" << 1;
-
- // When setData on visible row doesn't change ordering, layoutChanged should not be emitted
- QTest::newRow("no_ordering_change") << 6 << Qt::DisplayRole << "0" << "87654301" << "0468" << 0;
-
- // When setData happens on a filtered out row, layoutChanged should not be emitted
- QTest::newRow("filtered_out") << 1 << Qt::DisplayRole << "9" << "89654321" << "2468" << 0;
-
- // When setData makes a row visible, layoutChanged should not be emitted (rowsInserted is emitted instead)
- QTest::newRow("make_row_visible") << 7 << Qt::DisplayRole << "0" << "87654320" << "02468" << 0;
-
- // When setData makes a row hidden, layoutChanged should not be emitted (rowsRemoved is emitted instead)
- QTest::newRow("make_row_hidden") << 4 << Qt::DisplayRole << "1" << "87651321" << "268" << 0;
-
- // When setData happens on an unrelated role, layoutChanged should not be emitted
- QTest::newRow("unrelated_role") << 0 << Qt::DecorationRole << "" << "87654321" << "2468" << 0;
-
- // When many changes happen together... and trigger removal, insertion, and layoutChanged
- QTest::newRow("many_changes") << -1 << Qt::DisplayRole << "3,4,2,5,6,0,7,9" << "34256079" << "0246" << 1;
-
- // When many changes happen together... and trigger removal, insertion, but no change in ordering of visible rows => no layoutChanged
- QTest::newRow("many_changes_no_layoutChanged") << -1 << Qt::DisplayRole << "7,5,4,3,2,1,0,8" << "75432108" << "0248" << 0;
-}
-
-void tst_QSortFilterProxyModel::emitLayoutChangedOnlyIfSortingChanged()
-{
- QFETCH(int, changedRow);
- QFETCH(QString, newData);
- QFETCH(Qt::ItemDataRole, changedRole);
- QFETCH(QString, expectedSourceRowTexts);
- QFETCH(QString, expectedProxyRowTexts);
- QFETCH(int, expectedLayoutChanged);
-
- // Custom version of QStringListModel which supports emitting dataChanged for many rows at once
- class CustomStringListModel : public QAbstractListModel
- {
- public:
- bool setData(const QModelIndex &index, const QVariant &value, int role) override
- {
- if (index.row() >= 0 && index.row() < lst.size()
- && (role == Qt::EditRole || role == Qt::DisplayRole)) {
- lst.replace(index.row(), value.toString());
- emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole});
- return true;
- }
- return false;
- }
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
- {
- if (role == Qt::DisplayRole || role == Qt::EditRole)
- return lst.at(index.row());
- return QVariant();
- }
- int rowCount(const QModelIndex & = QModelIndex()) const override
- {
- return lst.count();
- }
-
- void replaceData(const QStringList &newData)
- {
- lst = newData;
- emit dataChanged(index(0, 0), index(rowCount()-1, 0), {Qt::DisplayRole, Qt::EditRole});
- }
-
- void emitDecorationChangedSignal()
- {
- const QModelIndex idx = index(0, 0);
- emit dataChanged(idx, idx, {Qt::DecorationRole});
- }
- private:
- QStringList lst;
- };
- CustomStringListModel model;
- QStringList strings;
- for (auto i = 8; i >= 1; --i)
- strings.append(QString::number(i));
- model.replaceData(strings);
- QCOMPARE(rowTexts(&model), QStringLiteral("87654321"));
-
- class FilterEvenRowsProxyModel : public QSortFilterProxyModel
- {
- public:
- bool filterAcceptsRow(int srcRow, const QModelIndex& srcParent) const override
- {
- return sourceModel()->index(srcRow, 0, srcParent).data().toInt() % 2 == 0;
- }
- };
-
- FilterEvenRowsProxyModel proxy;
- proxy.sort(0);
- proxy.setSourceModel(&model);
- QCOMPARE(rowTexts(&proxy), QStringLiteral("2468"));
-
- QSignalSpy modelDataChangedSpy(&model, &QAbstractItemModel::dataChanged);
- QSignalSpy proxyLayoutChangedSpy(&proxy, &QAbstractItemModel::layoutChanged);
-
- if (changedRole == Qt::DecorationRole)
- model.emitDecorationChangedSignal();
- else if (changedRow == -1)
- model.replaceData(newData.split(QLatin1Char(',')));
- else
- model.setData(model.index(changedRow, 0), newData, changedRole);
-
- QCOMPARE(rowTexts(&model), expectedSourceRowTexts);
- QCOMPARE(rowTexts(&proxy), expectedProxyRowTexts);
- QCOMPARE(modelDataChangedSpy.size(), 1);
- QCOMPARE(proxyLayoutChangedSpy.size(), expectedLayoutChanged);
-}
-
-void tst_QSortFilterProxyModel::dynamicFilterWithoutSort()
-{
- QStringListModel model;
- const QStringList initial = QString("bravo charlie delta echo").split(QLatin1Char(' '));
- model.setStringList(initial);
- QSortFilterProxyModel proxy;
- proxy.setDynamicSortFilter(true);
- proxy.setSourceModel(&model);
-
- QSignalSpy layoutChangeSpy(&proxy, &QAbstractItemModel::layoutChanged);
- QSignalSpy resetSpy(&proxy, &QAbstractItemModel::modelReset);
-
- QVERIFY(layoutChangeSpy.isValid());
- QVERIFY(resetSpy.isValid());
-
- model.setStringList(QStringList() << "Monday" << "Tuesday" << "Wednesday" << "Thursday" << "Friday");
-
- QVERIFY(layoutChangeSpy.isEmpty());
-
- QCOMPARE(model.stringList(), QStringList() << "Monday" << "Tuesday" << "Wednesday" << "Thursday" << "Friday");
-
- QCOMPARE(resetSpy.count(), 1);
-}
-
-void tst_QSortFilterProxyModel::checkSetNewModel()
-{
- QTreeView tv;
- StepTreeModel model1;
- model1.setDepth(4);
-
- QSortFilterProxyModel proxy;
- proxy.setSourceModel(&model1);
- tv.setModel(&proxy);
- tv.show();
- QVERIFY(QTest::qWaitForWindowExposed(&tv));
- tv.expandAll();
- {
- StepTreeModel model2;
- model2.setDepth(4);
- proxy.setSourceModel(&model2);
- tv.expandAll();
- proxy.setSourceModel(&model1);
- tv.expandAll();
- // the destruction of model2 here caused a proxy model reset due to
- // missing disconnect in setSourceModel()
- }
- // handle repaint events, will assert when qsortfilterproxymodel is in wrong state
- QCoreApplication::processEvents();
-}
-
-enum ColumnFilterMode {
- FilterNothing,
- FilterOutMiddle,
- FilterOutBeginEnd,
- FilterAll
-};
-Q_DECLARE_METATYPE(ColumnFilterMode)
-
-void tst_QSortFilterProxyModel::filterAndInsertColumn_data()
-{
-
- QTest::addColumn<int>("insertCol");
- QTest::addColumn<ColumnFilterMode>("filterMode");
- QTest::addColumn<QStringList>("expectedModelList");
- QTest::addColumn<QStringList>("expectedProxyModelList");
-
- QTest::newRow("at_beginning_filter_out_middle")
- << 0
- << FilterOutMiddle
- << QStringList{{"", "A1", "B1", "C1", "D1"}}
- << QStringList{{"", "D1"}}
- ;
- QTest::newRow("at_end_filter_out_middle")
- << 2
- << FilterOutMiddle
- << QStringList{{"A1", "B1", "C1", "D1", ""}}
- << QStringList{{"A1", ""}}
- ;
- QTest::newRow("in_the_middle_filter_out_middle")
- << 1
- << FilterOutMiddle
- << QStringList{{"A1", "B1", "C1", "", "D1"}}
- << QStringList{{"A1", "D1"}}
- ;
- QTest::newRow("at_beginning_filter_out_begin_and_end")
- << 0
- << FilterOutBeginEnd
- << QStringList{{"A1", "", "B1", "C1", "D1"}}
- << QStringList{{"", "B1", "C1"}}
- ;
- QTest::newRow("at_end_filter_out_begin_and_end")
- << 2
- << FilterOutBeginEnd
- << QStringList{{"A1", "B1", "C1", "D1", ""}}
- << QStringList{{"B1", "C1", "D1"}}
- ;
- QTest::newRow("in_the_middle_filter_out_begin_and_end")
- << 1
- << FilterOutBeginEnd
- << QStringList{{"A1", "B1", "", "C1", "D1"}}
- << QStringList{{"B1", "", "C1"}}
- ;
-
- QTest::newRow("at_beginning_filter_nothing")
- << 0
- << FilterAll
- << QStringList{{"", "A1", "B1", "C1", "D1"}}
- << QStringList{{"", "A1", "B1", "C1", "D1"}}
- ;
- QTest::newRow("at_end_filter_nothing")
- << 4
- << FilterAll
- << QStringList{{"A1", "B1", "C1", "D1", ""}}
- << QStringList{{"A1", "B1", "C1", "D1", ""}}
- ;
- QTest::newRow("in_the_middle_nothing")
- << 2
- << FilterAll
- << QStringList{{"A1", "B1", "", "C1", "D1"}}
- << QStringList{{"A1", "B1", "", "C1", "D1"}}
- ;
-
- QTest::newRow("filter_all")
- << 0
- << FilterNothing
- << QStringList{{"A1", "B1", "C1", "D1", ""}}
- << QStringList{}
- ;
-}
-void tst_QSortFilterProxyModel::filterAndInsertColumn()
-{
-
- class ColumnFilterProxy : public QSortFilterProxyModel {
- Q_DISABLE_COPY(ColumnFilterProxy)
- ColumnFilterMode filerMode;
- public:
- ColumnFilterProxy(ColumnFilterMode mode)
- : filerMode(mode)
- {}
- bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const override
- {
- Q_UNUSED(source_parent)
- switch (filerMode){
- case FilterAll:
- return true;
- case FilterNothing:
- return false;
- case FilterOutMiddle:
- return source_column == 0 || source_column == sourceModel()->columnCount() - 1;
- case FilterOutBeginEnd:
- return source_column > 0 && source_column< sourceModel()->columnCount() - 1;
- }
- Q_UNREACHABLE();
- }
- };
- QFETCH(int, insertCol);
- QFETCH(ColumnFilterMode, filterMode);
- QFETCH(QStringList, expectedModelList);
- QFETCH(QStringList, expectedProxyModelList);
- QStandardItemModel model;
- model.insertColumns(0, 4);
- model.insertRows(0, 1);
- for (int i = 0; i < model.rowCount(); ++i) {
- for (int j = 0; j < model.columnCount(); ++j)
- model.setData(model.index(i, j), QString('A' + j) + QString::number(i + 1));
- }
- ColumnFilterProxy proxy(filterMode);
- proxy.setSourceModel(&model);
- QVERIFY(proxy.insertColumn(insertCol));
- proxy.invalidate();
- QStringList modelStringList;
- for (int i = 0; i < model.rowCount(); ++i) {
- for (int j = 0; j < model.columnCount(); ++j)
- modelStringList.append(model.index(i, j).data().toString());
- }
- QCOMPARE(expectedModelList, modelStringList);
- modelStringList.clear();
- for (int i = 0; i < proxy.rowCount(); ++i) {
- for (int j = 0; j < proxy.columnCount(); ++j)
- modelStringList.append(proxy.index(i, j).data().toString());
- }
- QCOMPARE(expectedProxyModelList, modelStringList);
-}
-
-void tst_QSortFilterProxyModel::filterAndInsertRow_data()
-{
- QTest::addColumn<QStringList>("initialModelList");
- QTest::addColumn<int>("row");
- QTest::addColumn<QString>("filterRegExp");
- QTest::addColumn<QStringList>("expectedModelList");
- QTest::addColumn<QStringList>("expectedProxyModelList");
-
- QTest::newRow("at_beginning_filter_out_middle")
- << QStringList{{"A5", "B5", "B6", "A7"}}
- << 0
- << "^A"
- << QStringList{{"", "A5", "B5", "B6", "A7"}}
- << QStringList{{"A5", "A7"}};
- QTest::newRow("at_end_filter_out_middle")
- << QStringList{{"A5", "B5", "B6", "A7"}}
- << 2
- << "^A"
- << QStringList{{"A5", "B5", "B6", "A7", ""}}
- << QStringList{{"A5", "A7"}};
- QTest::newRow("in_the_middle_filter_out_middle")
- << QStringList{{"A5", "B5", "B6", "A7"}}
- << 1
- << "^A"
- << QStringList{{"A5", "B5", "B6", "", "A7"}}
- << QStringList{{"A5", "A7"}};
-
- QTest::newRow("at_beginning_filter_out_first_and_last")
- << QStringList{{"A5", "B5", "B6", "A7"}}
- << 0
- << "^B"
- << QStringList{{"A5", "", "B5", "B6", "A7"}}
- << QStringList{{"B5", "B6"}};
- QTest::newRow("at_end_filter_out_first_and_last")
- << QStringList{{"A5", "B5", "B6", "A7"}}
- << 2
- << "^B"
- << QStringList{{"A5", "B5", "B6", "A7", ""}}
- << QStringList{{"B5", "B6"}};
- QTest::newRow("in_the_middle_filter_out_first_and_last")
- << QStringList{{"A5", "B5", "B6", "A7"}}
- << 1
- << "^B"
- << QStringList{{"A5", "B5", "", "B6", "A7"}}
- << QStringList{{"B5", "B6"}};
-
- QTest::newRow("at_beginning_no_filter")
- << QStringList{{"A5", "B5", "B6", "A7"}}
- << 0
- << ".*"
- << QStringList{{"", "A5", "B5", "B6", "A7"}}
- << QStringList{{"", "A5", "B5", "B6", "A7"}};
- QTest::newRow("at_end_no_filter")
- << QStringList{{"A5", "B5", "B6", "A7"}}
- << 4
- << ".*"
- << QStringList{{"A5", "B5", "B6", "A7", ""}}
- << QStringList{{"A5", "B5", "B6", "A7", ""}};
- QTest::newRow("in_the_middle_no_filter")
- << QStringList{{"A5", "B5", "B6", "A7"}}
- << 2
- << ".*"
- << QStringList{{"A5", "B5", "", "B6", "A7"}}
- << QStringList{{"A5", "B5", "", "B6", "A7"}};
-
- QTest::newRow("filter_all")
- << QStringList{{"A5", "B5", "B6", "A7"}}
- << 0
- << "$a"
- << QStringList{{"A5", "B5", "B6", "A7", ""}}
- << QStringList{};
-}
-
-void tst_QSortFilterProxyModel::filterAndInsertRow()
-{
- QFETCH(QStringList, initialModelList);
- QFETCH(int, row);
- QFETCH(QString, filterRegExp);
- QFETCH(QStringList, expectedModelList);
- QFETCH(QStringList, expectedProxyModelList);
- QStringListModel model;
- QSortFilterProxyModel proxyModel;
-
- model.setStringList(initialModelList);
- proxyModel.setSourceModel(&model);
- proxyModel.setDynamicSortFilter(true);
- proxyModel.setFilterRegExp(filterRegExp);
-
- QVERIFY(proxyModel.insertRow(row));
- QCOMPARE(model.stringList(), expectedModelList);
- QCOMPARE(proxyModel.rowCount(), expectedProxyModelList.count());
- for (int r = 0; r < proxyModel.rowCount(); ++r) {
- QModelIndex index = proxyModel.index(r, 0);
- QVERIFY(index.isValid());
- QCOMPARE(proxyModel.data(index).toString(), expectedProxyModelList.at(r));
- }
-}
-
-QTEST_MAIN(tst_QSortFilterProxyModel)
-#include "tst_qsortfilterproxymodel.moc"
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp
new file mode 100644
index 0000000000..82cd26971b
--- /dev/null
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp
@@ -0,0 +1,4950 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include "tst_qsortfilterproxymodel.h"
+#include "dynamictreemodel.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtGui/QStandardItem>
+#include <QtWidgets/QComboBox>
+#include <QtWidgets/QTreeView>
+#include <QtWidgets/QTableView>
+
+#include <qdebug.h>
+
+// Testing get/set functions
+void tst_QSortFilterProxyModel::getSetCheck()
+{
+ QSortFilterProxyModel obj1;
+ QCOMPARE(obj1.sourceModel(), (QAbstractItemModel *)0);
+ // int QSortFilterProxyModel::filterKeyColumn()
+ // void QSortFilterProxyModel::setFilterKeyColumn(int)
+ obj1.setFilterKeyColumn(0);
+ QCOMPARE(0, obj1.filterKeyColumn());
+ obj1.setFilterKeyColumn(INT_MIN);
+ QCOMPARE(INT_MIN, obj1.filterKeyColumn());
+ obj1.setFilterKeyColumn(INT_MAX);
+ QCOMPARE(INT_MAX, obj1.filterKeyColumn());
+}
+
+tst_QSortFilterProxyModel::tst_QSortFilterProxyModel()
+ : m_model(0), m_proxy(0)
+{
+ qRegisterMetaType<QAbstractItemModel::LayoutChangeHint>();
+}
+
+void tst_QSortFilterProxyModel::initTestCase()
+{
+ qRegisterMetaType<QList<QPersistentModelIndex> >();
+ m_model = new QStandardItemModel(0, 1);
+ m_proxy = new QSortFilterProxyModel();
+ m_proxy->setSourceModel(m_model);
+}
+
+void tst_QSortFilterProxyModel::cleanupTestCase()
+{
+ delete m_proxy;
+ delete m_model;
+}
+
+void tst_QSortFilterProxyModel::cleanup()
+{
+ switch (m_filterType) {
+ case FilterType::RegExp:
+ m_proxy->setFilterRegExp(QRegExp());
+ break;
+ case FilterType::RegularExpression:
+ m_proxy->setFilterRegularExpression(QRegularExpression());
+ break;
+ }
+
+ m_proxy->sort(-1, Qt::AscendingOrder);
+ m_model->clear();
+ m_model->insertColumns(0, 1);
+}
+
+/*
+ tests
+*/
+
+void tst_QSortFilterProxyModel::sort_data()
+{
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<int>("sortCaseSensitivity");
+ QTest::addColumn<QStringList>("initial");
+ QTest::addColumn<QStringList>("expected");
+
+ QTest::newRow("flat descending") << static_cast<int>(Qt::DescendingOrder)
+ << int(Qt::CaseSensitive)
+ << (QStringList()
+ << "delta"
+ << "yankee"
+ << "bravo"
+ << "lima"
+ << "charlie"
+ << "juliet"
+ << "tango"
+ << "hotel"
+ << "uniform"
+ << "alpha"
+ << "echo"
+ << "golf"
+ << "quebec"
+ << "foxtrot"
+ << "india"
+ << "romeo"
+ << "november"
+ << "oskar"
+ << "zulu"
+ << "kilo"
+ << "whiskey"
+ << "mike"
+ << "papa"
+ << "sierra"
+ << "xray"
+ << "viktor")
+ << (QStringList()
+ << "zulu"
+ << "yankee"
+ << "xray"
+ << "whiskey"
+ << "viktor"
+ << "uniform"
+ << "tango"
+ << "sierra"
+ << "romeo"
+ << "quebec"
+ << "papa"
+ << "oskar"
+ << "november"
+ << "mike"
+ << "lima"
+ << "kilo"
+ << "juliet"
+ << "india"
+ << "hotel"
+ << "golf"
+ << "foxtrot"
+ << "echo"
+ << "delta"
+ << "charlie"
+ << "bravo"
+ << "alpha");
+ QTest::newRow("flat ascending") << static_cast<int>(Qt::AscendingOrder)
+ << int(Qt::CaseSensitive)
+ << (QStringList()
+ << "delta"
+ << "yankee"
+ << "bravo"
+ << "lima"
+ << "charlie"
+ << "juliet"
+ << "tango"
+ << "hotel"
+ << "uniform"
+ << "alpha"
+ << "echo"
+ << "golf"
+ << "quebec"
+ << "foxtrot"
+ << "india"
+ << "romeo"
+ << "november"
+ << "oskar"
+ << "zulu"
+ << "kilo"
+ << "whiskey"
+ << "mike"
+ << "papa"
+ << "sierra"
+ << "xray"
+ << "viktor")
+ << (QStringList()
+ << "alpha"
+ << "bravo"
+ << "charlie"
+ << "delta"
+ << "echo"
+ << "foxtrot"
+ << "golf"
+ << "hotel"
+ << "india"
+ << "juliet"
+ << "kilo"
+ << "lima"
+ << "mike"
+ << "november"
+ << "oskar"
+ << "papa"
+ << "quebec"
+ << "romeo"
+ << "sierra"
+ << "tango"
+ << "uniform"
+ << "viktor"
+ << "whiskey"
+ << "xray"
+ << "yankee"
+ << "zulu");
+ QTest::newRow("case insensitive") << static_cast<int>(Qt::AscendingOrder)
+ << int(Qt::CaseInsensitive)
+ << (QStringList()
+ << "alpha" << "BETA" << "Gamma" << "delta")
+ << (QStringList()
+ << "alpha" << "BETA" << "delta" << "Gamma");
+ QTest::newRow("case sensitive") << static_cast<int>(Qt::AscendingOrder)
+ << int(Qt::CaseSensitive)
+ << (QStringList()
+ << "alpha" << "BETA" << "Gamma" << "delta")
+ << (QStringList()
+ << "BETA" << "Gamma" << "alpha" << "delta");
+
+ QStringList list;
+ for (int i = 10000; i < 20000; ++i)
+ list.append(QStringLiteral("Number: ") + QString::number(i));
+ QTest::newRow("large set ascending") << static_cast<int>(Qt::AscendingOrder) << int(Qt::CaseSensitive) << list << list;
+}
+
+void tst_QSortFilterProxyModel::sort()
+{
+ QFETCH(int, sortOrder);
+ QFETCH(int, sortCaseSensitivity);
+ QFETCH(QStringList, initial);
+ QFETCH(QStringList, expected);
+
+ // prepare model
+ QStandardItem *root = m_model->invisibleRootItem ();
+ QList<QStandardItem *> items;
+ for (int i = 0; i < initial.count(); ++i) {
+ items.append(new QStandardItem(initial.at(i)));
+ }
+ root->insertRows(0, items);
+ QCOMPARE(m_model->rowCount(QModelIndex()), initial.count());
+ QCOMPARE(m_model->columnCount(QModelIndex()), 1);
+
+ // make sure the proxy is unsorted
+ QCOMPARE(m_proxy->columnCount(QModelIndex()), 1);
+ QCOMPARE(m_proxy->rowCount(QModelIndex()), initial.count());
+ for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) {
+ QModelIndex index = m_proxy->index(row, 0, QModelIndex());
+ QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), initial.at(row));
+ }
+
+ // sort
+ m_proxy->sort(0, static_cast<Qt::SortOrder>(sortOrder));
+ m_proxy->setSortCaseSensitivity(static_cast<Qt::CaseSensitivity>(sortCaseSensitivity));
+
+ // make sure the model is unchanged
+ for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) {
+ QModelIndex index = m_model->index(row, 0, QModelIndex());
+ QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), initial.at(row));
+ }
+ // make sure the proxy is sorted
+ for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) {
+ QModelIndex index = m_proxy->index(row, 0, QModelIndex());
+ QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+
+ // restore the unsorted order
+ m_proxy->sort(-1);
+
+ // make sure the proxy is unsorted again
+ for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) {
+ QModelIndex index = m_proxy->index(row, 0, QModelIndex());
+ QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), initial.at(row));
+ }
+}
+
+void tst_QSortFilterProxyModel::sortHierarchy_data()
+{
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<QStringList>("initial");
+ QTest::addColumn<QStringList>("expected");
+
+ QTest::newRow("flat ascending")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList()
+ << "c" << "f" << "d" << "e" << "a" << "b")
+ << (QStringList()
+ << "a" << "b" << "c" << "d" << "e" << "f");
+
+ QTest::newRow("simple hierarchy")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList() << "a" << "<" << "b" << "<" << "c" << ">" << ">")
+ << (QStringList() << "a" << "<" << "b" << "<" << "c" << ">" << ">");
+
+ QTest::newRow("hierarchical ascending")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QStringList()
+ << "c"
+ << "<"
+ << "h"
+ << "<"
+ << "2"
+ << "0"
+ << "1"
+ << ">"
+ << "g"
+ << "i"
+ << ">"
+ << "b"
+ << "<"
+ << "l"
+ << "k"
+ << "<"
+ << "8"
+ << "7"
+ << "9"
+ << ">"
+ << "m"
+ << ">"
+ << "a"
+ << "<"
+ << "z"
+ << "y"
+ << "x"
+ << ">")
+ << (QStringList()
+ << "a"
+ << "<"
+ << "x"
+ << "y"
+ << "z"
+ << ">"
+ << "b"
+ << "<"
+ << "k"
+ << "<"
+ << "7"
+ << "8"
+ << "9"
+ << ">"
+ << "l"
+ << "m"
+ << ">"
+ << "c"
+ << "<"
+ << "g"
+ << "h"
+ << "<"
+ << "0"
+ << "1"
+ << "2"
+ << ">"
+ << "i"
+ << ">");
+}
+
+void tst_QSortFilterProxyModel::sortHierarchy()
+{
+ QFETCH(int, sortOrder);
+ QFETCH(QStringList, initial);
+ QFETCH(QStringList, expected);
+
+ buildHierarchy(initial, m_model);
+ checkHierarchy(initial, m_model);
+ checkHierarchy(initial, m_proxy);
+ m_proxy->sort(0, static_cast<Qt::SortOrder>(sortOrder));
+ checkHierarchy(initial, m_model);
+ checkHierarchy(expected, m_proxy);
+}
+
+void tst_QSortFilterProxyModel::insertRows_data()
+{
+ QTest::addColumn<QStringList>("initial");
+ QTest::addColumn<QStringList>("expected");
+ QTest::addColumn<QStringList>("insert");
+ QTest::addColumn<int>("position");
+
+ QTest::newRow("insert one row in the middle")
+ << (QStringList()
+ << "One"
+ << "Two"
+ << "Four"
+ << "Five")
+ << (QStringList()
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << (QStringList()
+ << "Three")
+ << 2;
+
+ QTest::newRow("insert one row in the beginning")
+ << (QStringList()
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << (QStringList()
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << (QStringList()
+ << "One")
+ << 0;
+
+ QTest::newRow("insert one row in the end")
+ << (QStringList()
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four")
+ << (QStringList()
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << (QStringList()
+ <<"Five")
+ << 4;
+}
+
+void tst_QSortFilterProxyModel::insertRows()
+{
+ QFETCH(QStringList, initial);
+ QFETCH(QStringList, expected);
+ QFETCH(QStringList, insert);
+ QFETCH(int, position);
+ // prepare model
+ m_model->insertRows(0, initial.count(), QModelIndex());
+ //m_model->insertColumns(0, 1, QModelIndex());
+ QCOMPARE(m_model->columnCount(QModelIndex()), 1);
+ QCOMPARE(m_model->rowCount(QModelIndex()), initial.count());
+ for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) {
+ QModelIndex index = m_model->index(row, 0, QModelIndex());
+ m_model->setData(index, initial.at(row), Qt::DisplayRole);
+ }
+ // make sure the model correct before insert
+ for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) {
+ QModelIndex index = m_model->index(row, 0, QModelIndex());
+ QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), initial.at(row));
+ }
+ // make sure the proxy is correct before insert
+ for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) {
+ QModelIndex index = m_proxy->index(row, 0, QModelIndex());
+ QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), initial.at(row));
+ }
+
+ // insert the row
+ m_proxy->insertRows(position, insert.count(), QModelIndex());
+ QCOMPARE(m_model->rowCount(QModelIndex()), expected.count());
+ QCOMPARE(m_proxy->rowCount(QModelIndex()), expected.count());
+
+ // set the data for the inserted row
+ for (int i = 0; i < insert.count(); ++i) {
+ QModelIndex index = m_proxy->index(position + i, 0, QModelIndex());
+ m_proxy->setData(index, insert.at(i), Qt::DisplayRole);
+ }
+
+ // make sure the model correct after insert
+ for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) {
+ QModelIndex index = m_model->index(row, 0, QModelIndex());
+ QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+
+ // make sure the proxy is correct after insert
+ for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) {
+ QModelIndex index = m_proxy->index(row, 0, QModelIndex());
+ QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+}
+
+void tst_QSortFilterProxyModel::prependRow()
+{
+ //this tests that data is correctly handled by the sort filter when prepending a row
+ QStandardItemModel model;
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+
+ QStandardItem item("root");
+ model.appendRow(&item);
+
+ QStandardItem sub("sub");
+ item.appendRow(&sub);
+
+ sub.appendRow(new QStandardItem("test1"));
+ sub.appendRow(new QStandardItem("test2"));
+
+ QStandardItem sub2("sub2");
+ sub2.appendRow(new QStandardItem("sub3"));
+ item.insertRow(0, &sub2);
+
+ QModelIndex index_sub2 = proxy.mapFromSource(model.indexFromItem(&sub2));
+
+ QCOMPARE(sub2.rowCount(), proxy.rowCount(index_sub2));
+ QCOMPARE(proxy.rowCount(QModelIndex()), 1); //only the "root" item is there
+}
+
+void tst_QSortFilterProxyModel::appendRowFromCombobox_data()
+{
+ QTest::addColumn<QString>("pattern");
+ QTest::addColumn<QStringList>("initial");
+ QTest::addColumn<QString>("newitem");
+ QTest::addColumn<QStringList>("expected");
+
+ QTest::newRow("filter_out_second_last_item")
+ << "^[0-9]*$"
+ << (QStringList() << "a" << "1")
+ << "2"
+ << (QStringList() << "a" << "1" << "2");
+
+ QTest::newRow("filter_out_everything")
+ << "^c*$"
+ << (QStringList() << "a" << "b")
+ << "c"
+ << (QStringList() << "a" << "b" << "c");
+
+ QTest::newRow("no_filter")
+ << ""
+ << (QStringList() << "0" << "1")
+ << "2"
+ << (QStringList() << "0" << "1" << "2");
+
+ QTest::newRow("filter_out_last_item")
+ << "^[a-z]*$"
+ << (QStringList() << "a" << "1")
+ << "b"
+ << (QStringList() << "a" << "1" << "b");
+}
+
+void tst_QSortFilterProxyModel::appendRowFromCombobox()
+{
+ QFETCH(QString, pattern);
+ QFETCH(QStringList, initial);
+ QFETCH(QString, newitem);
+ QFETCH(QStringList, expected);
+
+ QStringListModel model(initial);
+
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+ proxy.setFilterRegExp(pattern);
+
+ QComboBox comboBox;
+ comboBox.setModel(&proxy);
+ comboBox.addItem(newitem);
+
+ QCOMPARE(model.stringList(), expected);
+}
+
+void tst_QSortFilterProxyModel::removeRows_data()
+{
+ QTest::addColumn<QStringList>("initial");
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<QString>("filter");
+ QTest::addColumn<int>("position");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<bool>("success");
+ QTest::addColumn<QStringList>("expectedProxy");
+ QTest::addColumn<QStringList>("expectedSource");
+
+ QTest::newRow("remove one row in the middle [no sorting/filter]")
+ << (QStringList()
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << -1 // no sorting
+ << QString() // no filter
+ << 2 // position
+ << 1 // count
+ << true // success
+ << (QStringList() // expectedProxy
+ << "One"
+ << "Two"
+ << "Four"
+ << "Five")
+ << (QStringList() // expectedSource
+ << "One"
+ << "Two"
+ << "Four"
+ << "Five");
+
+ QTest::newRow("remove one row in the beginning [no sorting/filter]")
+ << (QStringList()
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << -1 // no sorting
+ << QString() // no filter
+ << 0 // position
+ << 1 // count
+ << true // success
+ << (QStringList() // expectedProxy
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << (QStringList() // expectedSource
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five");
+
+ QTest::newRow("remove one row in the end [no sorting/filter]")
+ << (QStringList()
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << -1 // no sorting
+ << QString() // no filter
+ << 4 // position
+ << 1 // count
+ << true // success
+ << (QStringList() // expectedProxy
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four")
+ << (QStringList() // expectedSource
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four");
+
+ QTest::newRow("remove all [no sorting/filter]")
+ << (QStringList()
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << -1 // no sorting
+ << QString() // no filter
+ << 0 // position
+ << 5 // count
+ << true // success
+ << QStringList() // expectedProxy
+ << QStringList(); // expectedSource
+
+ QTest::newRow("remove one row past the end [no sorting/filter]")
+ << (QStringList()
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << -1 // no sorting
+ << QString() // no filter
+ << 5 // position
+ << 1 // count
+ << false // success
+ << (QStringList() // expectedProxy
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << (QStringList() // expectedSource
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five");
+
+ QTest::newRow("remove row -1 [no sorting/filter]")
+ << (QStringList()
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << -1 // no sorting
+ << QString() // no filter
+ << -1 // position
+ << 1 // count
+ << false // success
+ << (QStringList() // expectedProxy
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << (QStringList() // expectedSource
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five");
+
+ QTest::newRow("remove three rows in the middle [no sorting/filter]")
+ << (QStringList()
+ << "One"
+ << "Two"
+ << "Three"
+ << "Four"
+ << "Five")
+ << -1 // no sorting
+ << QString() // no filter
+ << 1 // position
+ << 3 // count
+ << true // success
+ << (QStringList() // expectedProxy
+ << "One"
+ << "Five")
+ << (QStringList() // expectedSource
+ << "One"
+ << "Five");
+
+ QTest::newRow("remove one row in the middle [ascending sorting, no filter]")
+ << (QStringList()
+ << "1"
+ << "5"
+ << "2"
+ << "4"
+ << "3")
+ << static_cast<int>(Qt::AscendingOrder)
+ << QString() // no filter
+ << 2 // position
+ << 1 // count
+ << true // success
+ << (QStringList() // expectedProxy
+ << "1"
+ << "2"
+ << "4"
+ << "5")
+ << (QStringList() // expectedSource
+ << "1"
+ << "5"
+ << "2"
+ << "4");
+
+ QTest::newRow("remove two rows in the middle [ascending sorting, no filter]")
+ << (QStringList()
+ << "1"
+ << "5"
+ << "2"
+ << "4"
+ << "3")
+ << static_cast<int>(Qt::AscendingOrder)
+ << QString() // no filter
+ << 2 // position
+ << 2 // count
+ << true // success
+ << (QStringList() // expectedProxy
+ << "1"
+ << "2"
+ << "5")
+ << (QStringList() // expectedSource
+ << "1"
+ << "5"
+ << "2");
+
+ QTest::newRow("remove two rows in the middle [descending sorting, no filter]")
+ << (QStringList()
+ << "1"
+ << "5"
+ << "2"
+ << "4"
+ << "3")
+ << static_cast<int>(Qt::DescendingOrder)
+ << QString() // no filter
+ << 2 // position
+ << 2 // count
+ << true // success
+ << (QStringList() // expectedProxy
+ << "5"
+ << "4"
+ << "1")
+ << (QStringList() // expectedSource
+ << "1"
+ << "5"
+ << "4");
+
+ QTest::newRow("remove one row in the middle [no sorting, filter=5|2|3]")
+ << (QStringList()
+ << "1"
+ << "5"
+ << "2"
+ << "4"
+ << "3")
+ << -1 // no sorting
+ << QString("5|2|3")
+ << 1 // position
+ << 1 // count
+ << true // success
+ << (QStringList() // expectedProxy
+ << "5"
+ << "3")
+ << (QStringList() // expectedSource
+ << "1"
+ << "5"
+ << "4"
+ << "3");
+
+ QTest::newRow("remove all [ascending sorting, no filter]")
+ << (QStringList()
+ << "1"
+ << "5"
+ << "2"
+ << "4"
+ << "3")
+ << static_cast<int>(Qt::AscendingOrder)
+ << QString() // no filter
+ << 0 // position
+ << 5 // count
+ << true // success
+ << QStringList() // expectedProxy
+ << QStringList(); // expectedSource
+}
+
+void tst_QSortFilterProxyModel::removeRows()
+{
+ QFETCH(QStringList, initial);
+ QFETCH(int, sortOrder);
+ QFETCH(QString, filter);
+ QFETCH(int, position);
+ QFETCH(int, count);
+ QFETCH(bool, success);
+ QFETCH(QStringList, expectedProxy);
+ QFETCH(QStringList, expectedSource);
+
+ QStandardItemModel model;
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+
+ // prepare model
+ foreach (QString s, initial)
+ model.appendRow(new QStandardItem(s));
+
+ if (sortOrder != -1)
+ proxy.sort(0, static_cast<Qt::SortOrder>(sortOrder));
+
+ if (!filter.isEmpty())
+ setupFilter(&proxy, filter);
+
+ // remove the rows
+ QCOMPARE(proxy.removeRows(position, count, QModelIndex()), success);
+ QCOMPARE(model.rowCount(QModelIndex()), expectedSource.count());
+ QCOMPARE(proxy.rowCount(QModelIndex()), expectedProxy.count());
+
+ // make sure the model is correct after remove
+ for (int row = 0; row < model.rowCount(QModelIndex()); ++row)
+ QCOMPARE(model.item(row)->text(), expectedSource.at(row));
+
+ // make sure the proxy is correct after remove
+ for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy.index(row, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expectedProxy.at(row));
+ }
+}
+
+class MyFilteredColumnProxyModel : public QSortFilterProxyModel
+{
+ Q_OBJECT
+public:
+ MyFilteredColumnProxyModel(FilterType filterType, QObject *parent = 0) :
+ QSortFilterProxyModel(parent),
+ m_filterType(filterType)
+ { }
+
+protected:
+ bool filterAcceptsColumn(int sourceColumn, const QModelIndex &) const
+ {
+ QString key = sourceModel()->headerData(sourceColumn, Qt::Horizontal).toString();
+ bool result = false;
+ switch (m_filterType) {
+ case FilterType::RegExp:
+ result = key.contains(filterRegExp());
+ break;
+ case FilterType::RegularExpression:
+ result = key.contains(filterRegularExpression());
+ break;
+ }
+ return result;
+ }
+
+private:
+ FilterType m_filterType;
+};
+
+void tst_QSortFilterProxyModel::removeColumns_data()
+{
+ QTest::addColumn<QStringList>("initial");
+ QTest::addColumn<QString>("filter");
+ QTest::addColumn<int>("position");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<bool>("success");
+ QTest::addColumn<QStringList>("expectedProxy");
+ QTest::addColumn<QStringList>("expectedSource");
+
+ QTest::newRow("remove one column in the middle [no filter]")
+ << (QStringList()
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5")
+ << QString() // no filter
+ << 2 // position
+ << 1 // count
+ << true // success
+ << (QStringList() // expectedProxy
+ << "1"
+ << "2"
+ << "4"
+ << "5")
+ << (QStringList() // expectedSource
+ << "1"
+ << "2"
+ << "4"
+ << "5");
+
+ QTest::newRow("remove one column in the end [no filter]")
+ << (QStringList()
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5")
+ << QString() // no filter
+ << 4 // position
+ << 1 // count
+ << true // success
+ << (QStringList() // expectedProxy
+ << "1"
+ << "2"
+ << "3"
+ << "4")
+ << (QStringList() // expectedSource
+ << "1"
+ << "2"
+ << "3"
+ << "4");
+
+ QTest::newRow("remove one column past the end [no filter]")
+ << (QStringList()
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5")
+ << QString() // no filter
+ << 5 // position
+ << 1 // count
+ << false // success
+ << (QStringList() // expectedProxy
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5")
+ << (QStringList() // expectedSource
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5");
+
+ QTest::newRow("remove column -1 [no filter]")
+ << (QStringList()
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5")
+ << QString() // no filter
+ << -1 // position
+ << 1 // count
+ << false // success
+ << (QStringList() // expectedProxy
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5")
+ << (QStringList() // expectedSource
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5");
+
+ QTest::newRow("remove all columns [no filter]")
+ << (QStringList()
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5")
+ << QString() // no filter
+ << 0 // position
+ << 5 // count
+ << true // success
+ << QStringList() // expectedProxy
+ << QStringList(); // expectedSource
+
+ QTest::newRow("remove one column in the middle [filter=1|3|5]")
+ << (QStringList()
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5")
+ << QString("1|3|5")
+ << 1 // position
+ << 1 // count
+ << true // success
+ << (QStringList() // expectedProxy
+ << "1"
+ << "5")
+ << (QStringList() // expectedSource
+ << "1"
+ << "2"
+ << "4"
+ << "5");
+
+ QTest::newRow("remove one column in the end [filter=1|3|5]")
+ << (QStringList()
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5")
+ << QString("1|3|5")
+ << 2 // position
+ << 1 // count
+ << true // success
+ << (QStringList() // expectedProxy
+ << "1"
+ << "3")
+ << (QStringList() // expectedSource
+ << "1"
+ << "2"
+ << "3"
+ << "4");
+
+ QTest::newRow("remove one column past the end [filter=1|3|5]")
+ << (QStringList()
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5")
+ << QString("1|3|5")
+ << 3 // position
+ << 1 // count
+ << false // success
+ << (QStringList() // expectedProxy
+ << "1"
+ << "3"
+ << "5")
+ << (QStringList() // expectedSource
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5");
+
+ QTest::newRow("remove all columns [filter=1|3|5]")
+ << (QStringList()
+ << "1"
+ << "2"
+ << "3"
+ << "4"
+ << "5")
+ << QString("1|3|5")
+ << 0 // position
+ << 3 // count
+ << true // success
+ << QStringList() // expectedProxy
+ << (QStringList() // expectedSource
+ << "2"
+ << "4");
+}
+
+void tst_QSortFilterProxyModel::removeColumns()
+{
+ QFETCH(QStringList, initial);
+ QFETCH(QString, filter);
+ QFETCH(int, position);
+ QFETCH(int, count);
+ QFETCH(bool, success);
+ QFETCH(QStringList, expectedProxy);
+ QFETCH(QStringList, expectedSource);
+
+ QStandardItemModel model;
+ MyFilteredColumnProxyModel proxy(m_filterType);
+ proxy.setSourceModel(&model);
+ if (!filter.isEmpty())
+ setupFilter(&proxy, filter);
+
+ // prepare model
+ model.setHorizontalHeaderLabels(initial);
+
+ // remove the columns
+ QCOMPARE(proxy.removeColumns(position, count, QModelIndex()), success);
+ QCOMPARE(model.columnCount(QModelIndex()), expectedSource.count());
+ QCOMPARE(proxy.columnCount(QModelIndex()), expectedProxy.count());
+
+ // make sure the model is correct after remove
+ for (int col = 0; col < model.columnCount(QModelIndex()); ++col)
+ QCOMPARE(model.horizontalHeaderItem(col)->text(), expectedSource.at(col));
+
+ // make sure the proxy is correct after remove
+ for (int col = 0; col < proxy.columnCount(QModelIndex()); ++col) {
+ QCOMPARE(proxy.headerData(col, Qt::Horizontal, Qt::DisplayRole).toString(),
+ expectedProxy.at(col));
+ }
+}
+
+void tst_QSortFilterProxyModel::filterColumns_data()
+{
+ QTest::addColumn<QString>("pattern");
+ QTest::addColumn<QStringList>("initial");
+ QTest::addColumn<bool>("data");
+
+ QTest::newRow("all") << "a"
+ << (QStringList()
+ << "delta"
+ << "yankee"
+ << "bravo"
+ << "lima")
+ << true;
+
+ QTest::newRow("some") << "lie"
+ << (QStringList()
+ << "charlie"
+ << "juliet"
+ << "tango"
+ << "hotel")
+ << true;
+
+ QTest::newRow("nothing") << "zoo"
+ << (QStringList()
+ << "foxtrot"
+ << "uniform"
+ << "alpha"
+ << "golf")
+ << false;
+}
+
+void tst_QSortFilterProxyModel::filterColumns()
+{
+ QFETCH(QString, pattern);
+ QFETCH(QStringList, initial);
+ QFETCH(bool, data);
+ // prepare model
+ m_model->setColumnCount(initial.count());
+ m_model->setRowCount(1);
+ QCOMPARE(m_model->columnCount(QModelIndex()), initial.count());
+ QCOMPARE(m_model->rowCount(QModelIndex()), 1);
+ // set data
+ QCOMPARE(m_model->rowCount(QModelIndex()), 1);
+ for (int col = 0; col < m_model->columnCount(QModelIndex()); ++col) {
+ QModelIndex index = m_model->index(0, col, QModelIndex());
+ m_model->setData(index, initial.at(col), Qt::DisplayRole);
+ }
+ setupFilter(m_proxy, pattern);
+
+ m_proxy->setFilterKeyColumn(-1);
+ // make sure the model is unchanged
+ for (int col = 0; col < m_model->columnCount(QModelIndex()); ++col) {
+ QModelIndex index = m_model->index(0, col, QModelIndex());
+ QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), initial.at(col));
+ }
+ // make sure the proxy is filtered
+ QModelIndex index = m_proxy->index(0, 0, QModelIndex());
+ QCOMPARE(index.isValid(), data);
+}
+
+void tst_QSortFilterProxyModel::filter_data()
+{
+ QTest::addColumn<QString>("pattern");
+ QTest::addColumn<QStringList>("initial");
+ QTest::addColumn<QStringList>("expected");
+
+ QTest::newRow("flat") << "e"
+ << (QStringList()
+ << "delta"
+ << "yankee"
+ << "bravo"
+ << "lima"
+ << "charlie"
+ << "juliet"
+ << "tango"
+ << "hotel"
+ << "uniform"
+ << "alpha"
+ << "echo"
+ << "golf"
+ << "quebec"
+ << "foxtrot"
+ << "india"
+ << "romeo"
+ << "november"
+ << "oskar"
+ << "zulu"
+ << "kilo"
+ << "whiskey"
+ << "mike"
+ << "papa"
+ << "sierra"
+ << "xray"
+ << "viktor")
+ << (QStringList()
+ << "delta"
+ << "yankee"
+ << "charlie"
+ << "juliet"
+ << "hotel"
+ << "echo"
+ << "quebec"
+ << "romeo"
+ << "november"
+ << "whiskey"
+ << "mike"
+ << "sierra");
+}
+
+void tst_QSortFilterProxyModel::filter()
+{
+ QFETCH(QString, pattern);
+ QFETCH(QStringList, initial);
+ QFETCH(QStringList, expected);
+
+ // prepare model
+ QVERIFY(m_model->insertRows(0, initial.count(), QModelIndex()));
+ QCOMPARE(m_model->rowCount(QModelIndex()), initial.count());
+ // set data
+ QCOMPARE(m_model->columnCount(QModelIndex()), 1);
+ for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) {
+ QModelIndex index = m_model->index(row, 0, QModelIndex());
+ m_model->setData(index, initial.at(row), Qt::DisplayRole);
+ }
+ setupFilter(m_proxy, pattern);
+ // make sure the proxy is unfiltered
+ QCOMPARE(m_proxy->columnCount(QModelIndex()), 1);
+ QCOMPARE(m_proxy->rowCount(QModelIndex()), expected.count());
+ // make sure the model is unchanged
+ for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) {
+ QModelIndex index = m_model->index(row, 0, QModelIndex());
+ QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), initial.at(row));
+ }
+ // make sure the proxy is filtered
+ for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) {
+ QModelIndex index = m_proxy->index(row, 0, QModelIndex());
+ QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+}
+
+void tst_QSortFilterProxyModel::filterHierarchy_data()
+{
+ QTest::addColumn<QString>("pattern");
+ QTest::addColumn<QStringList>("initial");
+ QTest::addColumn<QStringList>("expected");
+
+ QTest::newRow("flat") << ".*oo"
+ << (QStringList()
+ << "foo" << "boo" << "baz" << "moo" << "laa" << "haa")
+ << (QStringList()
+ << "foo" << "boo" << "moo");
+
+ QTest::newRow("simple hierarchy") << "b.*z"
+ << (QStringList() << "baz" << "<" << "boz" << "<" << "moo" << ">" << ">")
+ << (QStringList() << "baz" << "<" << "boz" << ">");
+}
+
+void tst_QSortFilterProxyModel::filterHierarchy()
+{
+ QFETCH(QString, pattern);
+ QFETCH(QStringList, initial);
+ QFETCH(QStringList, expected);
+ buildHierarchy(initial, m_model);
+ setupFilter(m_proxy, pattern);
+ checkHierarchy(initial, m_model);
+ checkHierarchy(expected, m_proxy);
+}
+
+void tst_QSortFilterProxyModel::buildHierarchy(const QStringList &l, QAbstractItemModel *m)
+{
+ int ind = 0;
+ int row = 0;
+ QStack<int> row_stack;
+ QModelIndex parent;
+ QStack<QModelIndex> parent_stack;
+ for (int i = 0; i < l.count(); ++i) {
+ QString token = l.at(i);
+ if (token == QLatin1String("<")) { // start table
+ ++ind;
+ parent_stack.push(parent);
+ row_stack.push(row);
+ parent = m->index(row - 1, 0, parent);
+ row = 0;
+ QVERIFY(m->insertColumns(0, 1, parent)); // add column
+ } else if (token == QLatin1String(">")) { // end table
+ --ind;
+ parent = parent_stack.pop();
+ row = row_stack.pop();
+ } else { // append row
+ QVERIFY(m->insertRows(row, 1, parent));
+ QModelIndex index = m->index(row, 0, parent);
+ QVERIFY(index.isValid());
+ m->setData(index, token, Qt::DisplayRole);
+ ++row;
+ }
+ }
+}
+
+void tst_QSortFilterProxyModel::checkHierarchy(const QStringList &l, const QAbstractItemModel *m)
+{
+ int row = 0;
+ int indent = 0;
+ QStack<int> row_stack;
+ QModelIndex parent;
+ QStack<QModelIndex> parent_stack;
+ for (int i = 0; i < l.count(); ++i) {
+ QString token = l.at(i);
+ if (token == QLatin1String("<")) { // start table
+ ++indent;
+ parent_stack.push(parent);
+ row_stack.push(row);
+ parent = m->index(row - 1, 0, parent);
+ QVERIFY(parent.isValid());
+ row = 0;
+ } else if (token == QLatin1String(">")) { // end table
+ --indent;
+ parent = parent_stack.pop();
+ row = row_stack.pop();
+ } else { // compare row
+ QModelIndex index = m->index(row, 0, parent);
+ QVERIFY(index.isValid());
+ QString str = m->data(index, Qt::DisplayRole).toString();
+ QCOMPARE(str, token);
+ ++row;
+ }
+ }
+}
+
+void tst_QSortFilterProxyModel::setupFilter(QSortFilterProxyModel *model, const QString& pattern)
+{
+ switch (m_filterType) {
+ case FilterType::RegExp:
+ model->setFilterRegExp(pattern);
+ break;
+ case FilterType::RegularExpression:
+ model->setFilterRegularExpression(pattern);
+ break;
+ }
+}
+
+class TestModel: public QAbstractTableModel
+{
+public:
+ int rowCount(const QModelIndex &) const { return 10000; }
+ int columnCount(const QModelIndex &) const { return 1; }
+ QVariant data(const QModelIndex &index, int role) const
+ {
+ if (role != Qt::DisplayRole)
+ return QVariant();
+ return QString::number(index.row());
+ }
+};
+
+void tst_QSortFilterProxyModel::filterTable()
+{
+ TestModel model;
+ QSortFilterProxyModel filter;
+ filter.setSourceModel(&model);
+ setupFilter(&filter, QLatin1String("9"));
+
+ for (int i = 0; i < filter.rowCount(); ++i)
+ QVERIFY(filter.data(filter.index(i, 0)).toString().contains(QLatin1Char('9')));
+}
+
+void tst_QSortFilterProxyModel::insertAfterSelect()
+{
+ QStandardItemModel model(10, 2);
+ for (int i = 0; i<10;i++)
+ model.setData(model.index(i, 0), QVariant(i));
+ QSortFilterProxyModel filter;
+ filter.setSourceModel(&model);
+ QTreeView view;
+ view.setModel(&filter);
+ view.show();
+ QModelIndex firstIndex = filter.mapFromSource(model.index(0, 0, QModelIndex()));
+ QCOMPARE(firstIndex.model(), (const QAbstractItemModel *)view.model());
+ QVERIFY(firstIndex.isValid());
+ int itemOffset = view.visualRect(firstIndex).width() / 2;
+ QPoint p(itemOffset, 1);
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p);
+ QVERIFY(view.selectionModel()->selectedIndexes().size() > 0);
+ model.insertRows(5, 1, QModelIndex());
+ QVERIFY(view.selectionModel()->selectedIndexes().size() > 0); // Should still have a selection
+}
+
+void tst_QSortFilterProxyModel::removeAfterSelect()
+{
+ QStandardItemModel model(10, 2);
+ for (int i = 0; i<10;i++)
+ model.setData(model.index(i, 0), QVariant(i));
+ QSortFilterProxyModel filter;
+ filter.setSourceModel(&model);
+ QTreeView view;
+ view.setModel(&filter);
+ view.show();
+ QModelIndex firstIndex = filter.mapFromSource(model.index(0, 0, QModelIndex()));
+ QCOMPARE(firstIndex.model(), (const QAbstractItemModel *)view.model());
+ QVERIFY(firstIndex.isValid());
+ int itemOffset = view.visualRect(firstIndex).width() / 2;
+ QPoint p(itemOffset, 1);
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p);
+ QVERIFY(view.selectionModel()->selectedIndexes().size() > 0);
+ model.removeRows(5, 1, QModelIndex());
+ QVERIFY(view.selectionModel()->selectedIndexes().size() > 0); // Should still have a selection
+}
+
+void tst_QSortFilterProxyModel::filterCurrent()
+{
+ QStandardItemModel model(2, 1);
+ model.setData(model.index(0, 0), QString("AAA"));
+ model.setData(model.index(1, 0), QString("BBB"));
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+ QTreeView view;
+
+ view.show();
+ view.setModel(&proxy);
+ QSignalSpy spy(view.selectionModel(), &QItemSelectionModel::currentChanged);
+ QVERIFY(spy.isValid());
+
+ view.setCurrentIndex(proxy.index(0, 0));
+ QCOMPARE(spy.count(), 1);
+ setupFilter(&proxy, QLatin1String("^B"));
+ QCOMPARE(spy.count(), 2);
+}
+
+void tst_QSortFilterProxyModel::filter_qtbug30662()
+{
+ QStringListModel model;
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+
+ // make sure the filter does not match any entry
+ setupFilter(&proxy, QLatin1String("[0-9]+"));
+
+ QStringList slSource;
+ slSource << "z" << "x" << "a" << "b";
+
+ proxy.setDynamicSortFilter(true);
+ proxy.sort(0);
+ model.setStringList(slSource);
+
+ // without fix for QTBUG-30662 this will make all entries visible - but unsorted
+ setupFilter(&proxy, QLatin1String("[a-z]+"));
+
+ QStringList slResult;
+ for (int i = 0; i < proxy.rowCount(); ++i)
+ slResult.append(proxy.index(i, 0).data().toString());
+
+ slSource.sort();
+ QCOMPARE(slResult, slSource);
+}
+
+void tst_QSortFilterProxyModel::changeSourceLayout()
+{
+ QStandardItemModel model(2, 1);
+ model.setData(model.index(0, 0), QString("b"));
+ model.setData(model.index(1, 0), QString("a"));
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+
+ QList<QPersistentModelIndex> persistentSourceIndexes;
+ QList<QPersistentModelIndex> persistentProxyIndexes;
+ for (int row = 0; row < model.rowCount(); ++row) {
+ persistentSourceIndexes.append(model.index(row, 0));
+ persistentProxyIndexes.append(proxy.index(row, 0));
+ }
+
+ // change layout of source model
+ model.sort(0, Qt::AscendingOrder);
+
+ for (int row = 0; row < model.rowCount(); ++row) {
+ QCOMPARE(persistentProxyIndexes.at(row).row(),
+ persistentSourceIndexes.at(row).row());
+ }
+}
+
+void tst_QSortFilterProxyModel::changeSourceLayoutFilteredOut()
+{
+ QStandardItemModel model(2, 1);
+ model.setData(model.index(0, 0), QString("b"));
+ model.setData(model.index(1, 0), QString("a"));
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+
+ int beforeSortFilter = proxy.rowCount();
+
+ QSignalSpy removeSpy(&proxy, &QSortFilterProxyModel::rowsRemoved);
+ // Filter everything out
+ setupFilter(&proxy, QLatin1String("c"));
+
+ QCOMPARE(removeSpy.count(), 1);
+ QCOMPARE(0, proxy.rowCount());
+
+ // change layout of source model
+ model.sort(0, Qt::AscendingOrder);
+
+ QSignalSpy insertSpy(&proxy, &QSortFilterProxyModel::rowsInserted);
+ // Remove filter; we expect an insert
+ setupFilter(&proxy, "");
+
+ QCOMPARE(insertSpy.count(), 1);
+ QCOMPARE(beforeSortFilter, proxy.rowCount());
+}
+
+void tst_QSortFilterProxyModel::removeSourceRows_data()
+{
+ QTest::addColumn<QStringList>("sourceItems");
+ QTest::addColumn<int>("start");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<IntPairList>("expectedRemovedProxyIntervals");
+ QTest::addColumn<QStringList>("expectedProxyItems");
+
+ QTest::newRow("remove one, no sorting")
+ << (QStringList() << "a" << "b") // sourceItems
+ << 0 // start
+ << 1 // count
+ << -1 // sortOrder (no sorting)
+ << (IntPairList() << IntPair(0, 0)) // expectedRemovedIntervals
+ << (QStringList() << "b") // expectedProxyItems
+ ;
+ QTest::newRow("remove one, ascending sort (same order)")
+ << (QStringList() << "a" << "b") // sourceItems
+ << 0 // start
+ << 1 // count
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << (IntPairList() << IntPair(0, 0)) // expectedRemovedIntervals
+ << (QStringList() << "b") // expectedProxyItems
+ ;
+ QTest::newRow("remove one, ascending sort (reverse order)")
+ << (QStringList() << "b" << "a") // sourceItems
+ << 0 // start
+ << 1 // count
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << (IntPairList() << IntPair(1, 1)) // expectedRemovedIntervals
+ << (QStringList() << "a") // expectedProxyItems
+ ;
+ QTest::newRow("remove two, multiple proxy intervals")
+ << (QStringList() << "c" << "d" << "a" << "b") // sourceItems
+ << 1 // start
+ << 2 // count
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << (IntPairList() << IntPair(3, 3) << IntPair(0, 0)) // expectedRemovedIntervals
+ << (QStringList() << "b" << "c") // expectedProxyItems
+ ;
+ QTest::newRow("remove three, multiple proxy intervals")
+ << (QStringList() << "b" << "d" << "f" << "a" << "c" << "e") // sourceItems
+ << 3 // start
+ << 3 // count
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << (IntPairList() << IntPair(4, 4) << IntPair(2, 2) << IntPair(0, 0)) // expectedRemovedIntervals
+ << (QStringList() << "b" << "d" << "f") // expectedProxyItems
+ ;
+ QTest::newRow("remove all, single proxy intervals")
+ << (QStringList() << "a" << "b" << "c" << "d" << "e" << "f") // sourceItems
+ << 0 // start
+ << 6 // count
+ << static_cast<int>(Qt::DescendingOrder) // sortOrder
+ << (IntPairList() << IntPair(0, 5)) // expectedRemovedIntervals
+ << QStringList() // expectedProxyItems
+ ;
+}
+
+// Check that correct proxy model rows are removed when rows are removed
+// from the source model
+void tst_QSortFilterProxyModel::removeSourceRows()
+{
+ QFETCH(QStringList, sourceItems);
+ QFETCH(int, start);
+ QFETCH(int, count);
+ QFETCH(int, sortOrder);
+ QFETCH(IntPairList, expectedRemovedProxyIntervals);
+ QFETCH(QStringList, expectedProxyItems);
+
+ QStandardItemModel model;
+ QSortFilterProxyModel proxy;
+
+ proxy.setSourceModel(&model);
+ model.insertColumns(0, 1);
+ model.insertRows(0, sourceItems.count());
+
+ for (int i = 0; i < sourceItems.count(); ++i) {
+ QModelIndex sindex = model.index(i, 0, QModelIndex());
+ model.setData(sindex, sourceItems.at(i), Qt::DisplayRole);
+ QModelIndex pindex = proxy.index(i, 0, QModelIndex());
+ QCOMPARE(proxy.data(pindex, Qt::DisplayRole), model.data(sindex, Qt::DisplayRole));
+ }
+
+ if (sortOrder != -1)
+ proxy.sort(0, static_cast<Qt::SortOrder>(sortOrder));
+ (void)proxy.rowCount(QModelIndex()); // force mapping
+
+ QSignalSpy removeSpy(&proxy, &QSortFilterProxyModel::rowsRemoved);
+ QSignalSpy insertSpy(&proxy, &QSortFilterProxyModel::rowsInserted);
+ QSignalSpy aboutToRemoveSpy(&proxy, &QSortFilterProxyModel::rowsAboutToBeRemoved);
+ QSignalSpy aboutToInsertSpy(&proxy, &QSortFilterProxyModel::rowsAboutToBeInserted);
+
+ QVERIFY(removeSpy.isValid());
+ QVERIFY(insertSpy.isValid());
+ QVERIFY(aboutToRemoveSpy.isValid());
+ QVERIFY(aboutToInsertSpy.isValid());
+
+ model.removeRows(start, count, QModelIndex());
+
+ QCOMPARE(aboutToRemoveSpy.count(), expectedRemovedProxyIntervals.count());
+ for (int i = 0; i < aboutToRemoveSpy.count(); ++i) {
+ QList<QVariant> args = aboutToRemoveSpy.at(i);
+ QCOMPARE(args.at(1).type(), QVariant::Int);
+ QCOMPARE(args.at(2).type(), QVariant::Int);
+ QCOMPARE(args.at(1).toInt(), expectedRemovedProxyIntervals.at(i).first);
+ QCOMPARE(args.at(2).toInt(), expectedRemovedProxyIntervals.at(i).second);
+ }
+ QCOMPARE(removeSpy.count(), expectedRemovedProxyIntervals.count());
+ for (int i = 0; i < removeSpy.count(); ++i) {
+ QList<QVariant> args = removeSpy.at(i);
+ QCOMPARE(args.at(1).type(), QVariant::Int);
+ QCOMPARE(args.at(2).type(), QVariant::Int);
+ QCOMPARE(args.at(1).toInt(), expectedRemovedProxyIntervals.at(i).first);
+ QCOMPARE(args.at(2).toInt(), expectedRemovedProxyIntervals.at(i).second);
+ }
+
+ QCOMPARE(insertSpy.count(), 0);
+ QCOMPARE(aboutToInsertSpy.count(), 0);
+
+ QCOMPARE(proxy.rowCount(QModelIndex()), expectedProxyItems.count());
+ for (int i = 0; i < expectedProxyItems.count(); ++i) {
+ QModelIndex pindex = proxy.index(i, 0, QModelIndex());
+ QCOMPARE(proxy.data(pindex, Qt::DisplayRole).toString(), expectedProxyItems.at(i));
+ }
+}
+
+void tst_QSortFilterProxyModel::insertSourceRows_data()
+{
+ QTest::addColumn<QStringList>("sourceItems");
+ QTest::addColumn<int>("start");
+ QTest::addColumn<QStringList>("newItems");
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<QStringList>("proxyItems");
+
+ QTest::newRow("insert (1)")
+ << (QStringList() << "c" << "b") // sourceItems
+ << 1 // start
+ << (QStringList() << "a") // newItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << (QStringList() << "a" << "b" << "c") // proxyItems
+ ;
+
+ QTest::newRow("insert (2)")
+ << (QStringList() << "d" << "b" << "c") // sourceItems
+ << 3 // start
+ << (QStringList() << "a") // newItems
+ << static_cast<int>(Qt::DescendingOrder) // sortOrder
+ << (QStringList() << "d" << "c" << "b" << "a") // proxyItems
+ ;
+}
+
+// Check that rows are inserted at correct position in proxy model when
+// rows are inserted into the source model
+void tst_QSortFilterProxyModel::insertSourceRows()
+{
+ QFETCH(QStringList, sourceItems);
+ QFETCH(int, start);
+ QFETCH(QStringList, newItems);
+ QFETCH(int, sortOrder);
+ QFETCH(QStringList, proxyItems);
+
+ QStandardItemModel model;
+ QSortFilterProxyModel proxy;
+ proxy.setDynamicSortFilter(true);
+
+ proxy.setSourceModel(&model);
+ model.insertColumns(0, 1);
+ model.insertRows(0, sourceItems.count());
+
+ for (int i = 0; i < sourceItems.count(); ++i) {
+ QModelIndex index = model.index(i, 0, QModelIndex());
+ model.setData(index, sourceItems.at(i), Qt::DisplayRole);
+ }
+
+ proxy.sort(0, static_cast<Qt::SortOrder>(sortOrder));
+ (void)proxy.rowCount(QModelIndex()); // force mapping
+
+ model.insertRows(start, newItems.size(), QModelIndex());
+
+ QCOMPARE(proxy.rowCount(QModelIndex()), proxyItems.count());
+ for (int i = 0; i < newItems.count(); ++i) {
+ QModelIndex index = model.index(start + i, 0, QModelIndex());
+ model.setData(index, newItems.at(i), Qt::DisplayRole);
+ }
+
+ for (int i = 0; i < proxyItems.count(); ++i) {
+ QModelIndex index = proxy.index(i, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), proxyItems.at(i));
+ }
+}
+
+void tst_QSortFilterProxyModel::changeFilter_data()
+{
+ QTest::addColumn<QStringList>("sourceItems");
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<QString>("initialFilter");
+ QTest::addColumn<IntPairList>("initialRemoveIntervals");
+ QTest::addColumn<QStringList>("initialProxyItems");
+ QTest::addColumn<QString>("finalFilter");
+ QTest::addColumn<IntPairList>("finalRemoveIntervals");
+ QTest::addColumn<IntPairList>("insertIntervals");
+ QTest::addColumn<QStringList>("finalProxyItems");
+
+ QTest::newRow("filter (1)")
+ << (QStringList() << "a" << "b" << "c" << "d" << "e" << "f") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "a|b|c" // initialFilter
+ << (IntPairList() << IntPair(3, 5)) // initialRemoveIntervals
+ << (QStringList() << "a" << "b" << "c") // initialProxyItems
+ << "b|d|f" // finalFilter
+ << (IntPairList() << IntPair(2, 2) << IntPair(0, 0)) // finalRemoveIntervals
+ << (IntPairList() << IntPair(1, 2)) // insertIntervals
+ << (QStringList() << "b" << "d" << "f") // finalProxyItems
+ ;
+
+ QTest::newRow("filter (2)")
+ << (QStringList() << "a" << "b" << "c" << "d" << "e" << "f") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "a|c|e" // initialFilter
+ << (IntPairList() << IntPair(5, 5) << IntPair(3, 3) << IntPair(1, 1)) // initialRemoveIntervals
+ << (QStringList() << "a" << "c" << "e") // initialProxyItems
+ << "" // finalFilter
+ << IntPairList() // finalRemoveIntervals
+ << (IntPairList() << IntPair(3, 3) << IntPair(2, 2) << IntPair(1, 1)) // insertIntervals
+ << (QStringList() << "a" << "b" << "c" << "d" << "e" << "f") // finalProxyItems
+ ;
+
+ QTest::newRow("filter (3)")
+ << (QStringList() << "a" << "b" << "c") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "a" // initialFilter
+ << (IntPairList() << IntPair(1, 2)) // initialRemoveIntervals
+ << (QStringList() << "a") // initialProxyItems
+ << "a" // finalFilter
+ << IntPairList() // finalRemoveIntervals
+ << IntPairList() // insertIntervals
+ << (QStringList() << "a") // finalProxyItems
+ ;
+}
+
+// Check that rows are added/removed when filter changes
+void tst_QSortFilterProxyModel::changeFilter()
+{
+ QFETCH(QStringList, sourceItems);
+ QFETCH(int, sortOrder);
+ QFETCH(QString, initialFilter);
+ QFETCH(IntPairList, initialRemoveIntervals);
+ QFETCH(QStringList, initialProxyItems);
+ QFETCH(QString, finalFilter);
+ QFETCH(IntPairList, finalRemoveIntervals);
+ QFETCH(IntPairList, insertIntervals);
+ QFETCH(QStringList, finalProxyItems);
+
+ QStandardItemModel model;
+ QSortFilterProxyModel proxy;
+
+ proxy.setSourceModel(&model);
+ model.insertColumns(0, 1);
+ model.insertRows(0, sourceItems.count());
+
+ for (int i = 0; i < sourceItems.count(); ++i) {
+ QModelIndex index = model.index(i, 0, QModelIndex());
+ model.setData(index, sourceItems.at(i), Qt::DisplayRole);
+ }
+
+ proxy.sort(0, static_cast<Qt::SortOrder>(sortOrder));
+ (void)proxy.rowCount(QModelIndex()); // force mapping
+
+ QSignalSpy initialRemoveSpy(&proxy, &QSortFilterProxyModel::rowsRemoved);
+ QSignalSpy initialInsertSpy(&proxy, &QSortFilterProxyModel::rowsInserted);
+
+ QVERIFY(initialRemoveSpy.isValid());
+ QVERIFY(initialInsertSpy.isValid());
+
+ setupFilter(&proxy, initialFilter);
+
+ QCOMPARE(initialRemoveSpy.count(), initialRemoveIntervals.count());
+ QCOMPARE(initialInsertSpy.count(), 0);
+ for (int i = 0; i < initialRemoveSpy.count(); ++i) {
+ QList<QVariant> args = initialRemoveSpy.at(i);
+ QCOMPARE(args.at(1).type(), QVariant::Int);
+ QCOMPARE(args.at(2).type(), QVariant::Int);
+ QCOMPARE(args.at(1).toInt(), initialRemoveIntervals.at(i).first);
+ QCOMPARE(args.at(2).toInt(), initialRemoveIntervals.at(i).second);
+ }
+
+ QCOMPARE(proxy.rowCount(QModelIndex()), initialProxyItems.count());
+ for (int i = 0; i < initialProxyItems.count(); ++i) {
+ QModelIndex index = proxy.index(i, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), initialProxyItems.at(i));
+ }
+
+ QSignalSpy finalRemoveSpy(&proxy, &QSortFilterProxyModel::rowsRemoved);
+ QSignalSpy finalInsertSpy(&proxy, &QSortFilterProxyModel::rowsInserted);
+
+ QVERIFY(finalRemoveSpy.isValid());
+ QVERIFY(finalInsertSpy.isValid());
+
+ setupFilter(&proxy, finalFilter);
+
+ QCOMPARE(finalRemoveSpy.count(), finalRemoveIntervals.count());
+ for (int i = 0; i < finalRemoveSpy.count(); ++i) {
+ QList<QVariant> args = finalRemoveSpy.at(i);
+ QCOMPARE(args.at(1).type(), QVariant::Int);
+ QCOMPARE(args.at(2).type(), QVariant::Int);
+ QCOMPARE(args.at(1).toInt(), finalRemoveIntervals.at(i).first);
+ QCOMPARE(args.at(2).toInt(), finalRemoveIntervals.at(i).second);
+ }
+
+ QCOMPARE(finalInsertSpy.count(), insertIntervals.count());
+ for (int i = 0; i < finalInsertSpy.count(); ++i) {
+ QList<QVariant> args = finalInsertSpy.at(i);
+ QCOMPARE(args.at(1).type(), QVariant::Int);
+ QCOMPARE(args.at(2).type(), QVariant::Int);
+ QCOMPARE(args.at(1).toInt(), insertIntervals.at(i).first);
+ QCOMPARE(args.at(2).toInt(), insertIntervals.at(i).second);
+ }
+
+ QCOMPARE(proxy.rowCount(QModelIndex()), finalProxyItems.count());
+ for (int i = 0; i < finalProxyItems.count(); ++i) {
+ QModelIndex index = proxy.index(i, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), finalProxyItems.at(i));
+ }
+}
+
+void tst_QSortFilterProxyModel::changeSourceData_data()
+{
+ QTest::addColumn<QStringList>("sourceItems");
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<QString>("filter");
+ QTest::addColumn<QStringList>("expectedInitialProxyItems");
+ QTest::addColumn<bool>("dynamic");
+ QTest::addColumn<int>("row");
+ QTest::addColumn<QString>("newValue");
+ QTest::addColumn<IntPairList>("removeIntervals");
+ QTest::addColumn<IntPairList>("insertIntervals");
+ QTest::addColumn<int>("expectedDataChangedRow"); // -1 if no dataChanged signal expected
+ QTest::addColumn<bool>("expectedLayoutChanged");
+ QTest::addColumn<QStringList>("proxyItems");
+
+ QTest::newRow("move_to_end_ascending")
+ << (QStringList() << "c" << "b" << "a") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "" // filter
+ << (QStringList() << "a" << "b" << "c") // expectedInitialProxyItems
+ << true // dynamic
+ << 2 // row
+ << "z" // newValue
+ << IntPairList() // removeIntervals
+ << IntPairList() // insertIntervals
+ << 2 // dataChanged(row 2) is emitted, see comment "Make sure we also emit dataChanged for the rows" in the source code (unclear why, though)
+ << true // layoutChanged
+ << (QStringList() << "b" << "c" << "z") // proxyItems
+ ;
+
+ QTest::newRow("move_to_end_descending")
+ << (QStringList() << "b" << "c" << "z") // sourceItems
+ << static_cast<int>(Qt::DescendingOrder) // sortOrder
+ << "" // filter
+ << (QStringList() << "z" << "c" << "b") // expectedInitialProxyItems
+ << true // dynamic
+ << 1 // row
+ << "a" // newValue
+ << IntPairList() // removeIntervals
+ << IntPairList() // insertIntervals
+ << 2 // dataChanged(row 2) is emitted, see comment "Make sure we also emit dataChanged for the rows" in the source code (unclear why, though)
+ << true // layoutChanged
+ << (QStringList() << "z" << "b" << "a") // proxyItems
+ ;
+
+ QTest::newRow("no_op_change")
+ << (QStringList() << "a" << "b") // sourceItems
+ << static_cast<int>(Qt::DescendingOrder) // sortOrder
+ << "" // filter
+ << (QStringList() << "b" << "a") // expectedInitialProxyItems
+ << true // dynamic
+ << 0 // row
+ << "a" // newValue
+ << IntPairList() // removeIntervals
+ << IntPairList() // insertIntervals
+ << -1 // no dataChanged signal
+ << false // layoutChanged
+ << (QStringList() << "b" << "a") // proxyItems
+ ;
+
+ QTest::newRow("no_effect_on_filtering")
+ << (QStringList() << "a" << "b") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "" // filter
+ << (QStringList() << "a" << "b") // expectedInitialProxyItems
+ << true // dynamic
+ << 1 // row
+ << "z" // newValue
+ << IntPairList() // removeIntervals
+ << IntPairList() // insertIntervals
+ << 1 // expectedDataChangedRow
+ << false // layoutChanged
+ << (QStringList() << "a" << "z") // proxyItems
+ ;
+
+ QTest::newRow("filtered_out_value_stays_out")
+ << (QStringList() << "a" << "b" << "c" << "d") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "a|c" // filter
+ << (QStringList() << "a" << "c") // expectedInitialProxyItems
+ << true // dynamic
+ << 1 // row
+ << "x" // newValue
+ << IntPairList() // removeIntervals
+ << IntPairList() // insertIntervals
+ << -1 // no dataChanged signal
+ << false // layoutChanged
+ << (QStringList() << "a" << "c") // proxyItems
+ ;
+
+ QTest::newRow("filtered_out_now_matches")
+ << (QStringList() << "a" << "b" << "c" << "d") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "a|c|x" // filter
+ << (QStringList() << "a" << "c") // expectedInitialProxyItems
+ << true // dynamic
+ << 1 // row
+ << "x" // newValue
+ << IntPairList() // removeIntervals
+ << (IntPairList() << IntPair(2, 2)) // insertIntervals
+ << -1 // no dataChanged signal
+ << false // layoutChanged
+ << (QStringList() << "a" << "c" << "x") // proxyItems
+ ;
+
+ QTest::newRow("value_is_now_filtered_out")
+ << (QStringList() << "a" << "b" << "c" << "d") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "a|c" // filter
+ << (QStringList() << "a" << "c") // expectedInitialProxyItems
+ << true // dynamic
+ << 2 // row
+ << "x" // newValue
+ << (IntPairList() << IntPair(1, 1)) // removeIntervals
+ << IntPairList() // insertIntervals
+ << -1 // no dataChanged signal
+ << false // layoutChanged
+ << (QStringList() << "a") // proxyItems
+ ;
+
+ QTest::newRow("non_dynamic_filter_does_not_update_sort")
+ << (QStringList() << "c" << "b" << "a") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "" // filter
+ << (QStringList() << "a" << "b" << "c") // expectedInitialProxyItems
+ << false // dynamic
+ << 2 // row
+ << "x" // newValue
+ << IntPairList() // removeIntervals
+ << IntPairList() // insertIntervals
+ << 0 // expectedDataChangedRow
+ << false // layoutChanged
+ << (QStringList() << "x" << "b" << "c") // proxyItems
+ ;
+}
+
+void tst_QSortFilterProxyModel::changeSourceData()
+{
+ QFETCH(QStringList, sourceItems);
+ QFETCH(int, sortOrder);
+ QFETCH(QString, filter);
+ QFETCH(QStringList, expectedInitialProxyItems);
+ QFETCH(bool, dynamic);
+ QFETCH(int, row);
+ QFETCH(QString, newValue);
+ QFETCH(IntPairList, removeIntervals);
+ QFETCH(IntPairList, insertIntervals);
+ QFETCH(int, expectedDataChangedRow);
+ QFETCH(bool, expectedLayoutChanged);
+ QFETCH(QStringList, proxyItems);
+
+ QStandardItemModel model;
+ QSortFilterProxyModel proxy;
+
+ proxy.setDynamicSortFilter(dynamic);
+ proxy.setSourceModel(&model);
+ model.insertColumns(0, 1);
+ model.insertRows(0, sourceItems.count());
+
+ for (int i = 0; i < sourceItems.count(); ++i) {
+ QModelIndex index = model.index(i, 0, QModelIndex());
+ model.setData(index, sourceItems.at(i), Qt::DisplayRole);
+ }
+
+ proxy.sort(0, static_cast<Qt::SortOrder>(sortOrder));
+ (void)proxy.rowCount(QModelIndex()); // force mapping
+
+ setupFilter(&proxy, filter);
+
+ QCOMPARE(proxy.rowCount(), expectedInitialProxyItems.count());
+ for (int i = 0; i < expectedInitialProxyItems.count(); ++i) {
+ const QModelIndex index = proxy.index(i, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expectedInitialProxyItems.at(i));
+ }
+
+ QSignalSpy removeSpy(&proxy, &QSortFilterProxyModel::rowsRemoved);
+ QSignalSpy insertSpy(&proxy, &QSortFilterProxyModel::rowsInserted);
+ QSignalSpy dataChangedSpy(&proxy, &QSortFilterProxyModel::dataChanged);
+ QSignalSpy layoutChangedSpy(&proxy, &QSortFilterProxyModel::layoutChanged);
+
+ QVERIFY(removeSpy.isValid());
+ QVERIFY(insertSpy.isValid());
+ QVERIFY(dataChangedSpy.isValid());
+ QVERIFY(layoutChangedSpy.isValid());
+
+ {
+ QModelIndex index = model.index(row, 0, QModelIndex());
+ model.setData(index, newValue, Qt::DisplayRole);
+ }
+
+ QCOMPARE(removeSpy.count(), removeIntervals.count());
+ for (int i = 0; i < removeSpy.count(); ++i) {
+ QList<QVariant> args = removeSpy.at(i);
+ QCOMPARE(args.at(1).type(), QVariant::Int);
+ QCOMPARE(args.at(2).type(), QVariant::Int);
+ QCOMPARE(args.at(1).toInt(), removeIntervals.at(i).first);
+ QCOMPARE(args.at(2).toInt(), removeIntervals.at(i).second);
+ }
+
+ QCOMPARE(insertSpy.count(), insertIntervals.count());
+ for (int i = 0; i < insertSpy.count(); ++i) {
+ QList<QVariant> args = insertSpy.at(i);
+ QCOMPARE(args.at(1).type(), QVariant::Int);
+ QCOMPARE(args.at(2).type(), QVariant::Int);
+ QCOMPARE(args.at(1).toInt(), insertIntervals.at(i).first);
+ QCOMPARE(args.at(2).toInt(), insertIntervals.at(i).second);
+ }
+
+ QCOMPARE(proxy.rowCount(QModelIndex()), proxyItems.count());
+ for (int i = 0; i < proxyItems.count(); ++i) {
+ QModelIndex index = proxy.index(i, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), proxyItems.at(i));
+ }
+
+ if (expectedDataChangedRow == -1) {
+ QCOMPARE(dataChangedSpy.count(), 0);
+ } else {
+ QCOMPARE(dataChangedSpy.count(), 1);
+ const QModelIndex idx = dataChangedSpy.at(0).at(0).value<QModelIndex>();
+ QCOMPARE(idx.row(), expectedDataChangedRow);
+ QCOMPARE(idx.column(), 0);
+ }
+
+ QCOMPARE(layoutChangedSpy.count(), expectedLayoutChanged ? 1 : 0);
+}
+
+// Checks that the model is a table, and that each and every row is like this:
+// i-th row: ( rows.at(i), i )
+static void checkSortedTableModel(const QAbstractItemModel *model, const QStringList &rows)
+{
+ QCOMPARE(model->rowCount(), rows.length());
+ QCOMPARE(model->columnCount(), 2);
+
+ for (int row = 0; row < model->rowCount(); ++row) {
+ const QString column0 = model->index(row, 0).data().toString();
+ const int column1 = model->index(row, 1).data().toString().toInt();
+
+ QCOMPARE(column0, rows.at(row));
+ QCOMPARE(column1, row);
+ }
+}
+
+void tst_QSortFilterProxyModel::changeSourceDataKeepsStableSorting_qtbug1548()
+{
+ // Check that emitting dataChanged from the source model
+ // for a change of a role which is not the sorting role
+ // doesn't alter the sorting. In this case, we sort on the DisplayRole,
+ // and play with other roles.
+
+ static const QStringList rows
+ = QStringList() << "a" << "b" << "b" << "b" << "c" << "c" << "x";
+
+ // Build a table of pairs (string, #row) in each row
+ QStandardItemModel model(0, 2);
+
+ for (int rowNumber = 0; rowNumber < rows.length(); ++rowNumber) {
+ QStandardItem *column0 = new QStandardItem(rows.at(rowNumber));
+ column0->setCheckable(true);
+ column0->setCheckState(Qt::Unchecked);
+
+ QStandardItem *column1 = new QStandardItem(QString::number(rowNumber));
+
+ const QList<QStandardItem *> row
+ = QList<QStandardItem *>() << column0 << column1;
+
+ model.appendRow(row);
+ }
+
+ checkSortedTableModel(&model, rows);
+
+ // Build the proxy model
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+ proxy.setDynamicSortFilter(true);
+ proxy.sort(0);
+
+ // The proxy is now sorted by the first column, check that the sorting
+ // * is correct (the input is already sorted, so it must not have changed)
+ // * was stable (by looking at the second column)
+ checkSortedTableModel(&model, rows);
+
+ // Change the check status of an item. That must not break the stable sorting
+ // changes the middle "b"
+ model.item(2)->setCheckState(Qt::Checked);
+ checkSortedTableModel(&model, rows);
+
+ // changes the starting "a"
+ model.item(0)->setCheckState(Qt::Checked);
+ checkSortedTableModel(&model, rows);
+
+ // change the background color of the first "c"
+ model.item(4)->setBackground(Qt::red);
+ checkSortedTableModel(&model, rows);
+
+ // change the background color of the second "c"
+ model.item(5)->setBackground(Qt::red);
+ checkSortedTableModel(&model, rows);
+}
+
+void tst_QSortFilterProxyModel::changeSourceDataForwardsRoles_qtbug35440()
+{
+ QStringList strings;
+ for (int i = 0; i < 100; ++i)
+ strings << QString::number(i);
+
+ QStringListModel model(strings);
+
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+ proxy.sort(0, Qt::AscendingOrder);
+
+ QSignalSpy spy(&proxy, &QAbstractItemModel::dataChanged);
+ QVERIFY(spy.isValid());
+ QCOMPARE(spy.length(), 0);
+
+ QModelIndex index;
+
+ // QStringListModel doesn't distinguish between edit and display roles,
+ // so changing one always changes the other, too.
+ QVector<int> expectedChangedRoles;
+ expectedChangedRoles.append(Qt::DisplayRole);
+ expectedChangedRoles.append(Qt::EditRole);
+
+ index = model.index(0, 0);
+ QVERIFY(index.isValid());
+ model.setData(index, QStringLiteral("teststring"), Qt::DisplayRole);
+ QCOMPARE(spy.length(), 1);
+ QCOMPARE(spy.at(0).at(2).value<QVector<int> >(), expectedChangedRoles);
+
+ index = model.index(1, 0);
+ QVERIFY(index.isValid());
+ model.setData(index, QStringLiteral("teststring2"), Qt::EditRole);
+ QCOMPARE(spy.length(), 2);
+ QCOMPARE(spy.at(1).at(2).value<QVector<int> >(), expectedChangedRoles);
+}
+
+void tst_QSortFilterProxyModel::sortFilterRole()
+{
+ QStandardItemModel model;
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+ model.insertColumns(0, 1);
+
+ QList<QPair<QVariant, QVariant> > sourceItems;
+ sourceItems = QList<QPair<QVariant, QVariant> >()
+ << QPair<QVariant, QVariant>("b", 3)
+ << QPair<QVariant, QVariant>("c", 2)
+ << QPair<QVariant, QVariant>("a", 1);
+
+ QList<int> orderedItems;
+ orderedItems = QList<int>()
+ << 2 << 1;
+
+ model.insertRows(0, sourceItems.count());
+ for (int i = 0; i < sourceItems.count(); ++i) {
+ QModelIndex index = model.index(i, 0, QModelIndex());
+ model.setData(index, sourceItems.at(i).first, Qt::DisplayRole);
+ model.setData(index, sourceItems.at(i).second, Qt::UserRole);
+ }
+
+ setupFilter(&proxy, QLatin1String("2"));
+
+ QCOMPARE(proxy.rowCount(), 0); // Qt::DisplayRole is default role
+
+ proxy.setFilterRole(Qt::UserRole);
+ QCOMPARE(proxy.rowCount(), 1);
+
+ proxy.setFilterRole(Qt::DisplayRole);
+ QCOMPARE(proxy.rowCount(), 0);
+
+ setupFilter(&proxy, QLatin1String("1|2|3"));
+
+ QCOMPARE(proxy.rowCount(), 0);
+
+ proxy.setFilterRole(Qt::UserRole);
+ QCOMPARE(proxy.rowCount(), 3);
+
+ proxy.sort(0, Qt::AscendingOrder);
+ QCOMPARE(proxy.rowCount(), 3);
+
+ proxy.setSortRole(Qt::UserRole);
+ proxy.setFilterRole(Qt::DisplayRole);
+ setupFilter(&proxy, QLatin1String("a|c"));
+
+ QCOMPARE(proxy.rowCount(), orderedItems.count());
+ for (int i = 0; i < proxy.rowCount(); ++i) {
+ QModelIndex index = proxy.index(i, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole), sourceItems.at(orderedItems.at(i)).first);
+ }
+}
+
+void tst_QSortFilterProxyModel::selectionFilteredOut()
+{
+ QStandardItemModel model(2, 1);
+ model.setData(model.index(0, 0), QString("AAA"));
+ model.setData(model.index(1, 0), QString("BBB"));
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+ QTreeView view;
+
+ view.show();
+ view.setModel(&proxy);
+ QSignalSpy spy(view.selectionModel(), &QItemSelectionModel::currentChanged);
+ QVERIFY(spy.isValid());
+
+ view.setCurrentIndex(proxy.index(0, 0));
+ QCOMPARE(spy.count(), 1);
+
+ setupFilter(&proxy, QLatin1String("^B"));
+ QCOMPARE(spy.count(), 2);
+}
+
+void tst_QSortFilterProxyModel::match_data()
+{
+ QTest::addColumn<QStringList>("sourceItems");
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<QString>("filter");
+ QTest::addColumn<int>("proxyStartRow");
+ QTest::addColumn<QString>("what");
+ QTest::addColumn<int>("matchFlags");
+ QTest::addColumn<IntList>("expectedProxyItems");
+ QTest::newRow("1")
+ << (QStringList() << "a") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "" // filter
+ << 0 // proxyStartRow
+ << "a" // what
+ << static_cast<int>(Qt::MatchExactly) // matchFlags
+ << (IntList() << 0); // expectedProxyItems
+ QTest::newRow("2")
+ << (QStringList() << "a" << "b") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "" // filter
+ << 0 // proxyStartRow
+ << "b" // what
+ << static_cast<int>(Qt::MatchExactly) // matchFlags
+ << (IntList() << 1); // expectedProxyItems
+ QTest::newRow("3")
+ << (QStringList() << "a" << "b") // sourceItems
+ << static_cast<int>(Qt::DescendingOrder) // sortOrder
+ << "" // filter
+ << 0 // proxyStartRow
+ << "a" // what
+ << static_cast<int>(Qt::MatchExactly) // matchFlags
+ << (IntList() << 1); // expectedProxyItems
+ QTest::newRow("4")
+ << (QStringList() << "b" << "d" << "a" << "c") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "" // filter
+ << 1 // proxyStartRow
+ << "a" // what
+ << static_cast<int>(Qt::MatchExactly) // matchFlags
+ << IntList(); // expectedProxyItems
+ QTest::newRow("5")
+ << (QStringList() << "b" << "d" << "a" << "c") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "a|b" // filter
+ << 0 // proxyStartRow
+ << "c" // what
+ << static_cast<int>(Qt::MatchExactly) // matchFlags
+ << IntList(); // expectedProxyItems
+ QTest::newRow("6")
+ << (QStringList() << "b" << "d" << "a" << "c") // sourceItems
+ << static_cast<int>(Qt::DescendingOrder) // sortOrder
+ << "a|b" // filter
+ << 0 // proxyStartRow
+ << "b" // what
+ << static_cast<int>(Qt::MatchExactly) // matchFlags
+ << (IntList() << 0); // expectedProxyItems
+}
+
+void tst_QSortFilterProxyModel::match()
+{
+ QFETCH(QStringList, sourceItems);
+ QFETCH(int, sortOrder);
+ QFETCH(QString, filter);
+ QFETCH(int, proxyStartRow);
+ QFETCH(QString, what);
+ QFETCH(int, matchFlags);
+ QFETCH(IntList, expectedProxyItems);
+
+ QStandardItemModel model;
+ QSortFilterProxyModel proxy;
+
+ proxy.setSourceModel(&model);
+ model.insertColumns(0, 1);
+ model.insertRows(0, sourceItems.count());
+
+ for (int i = 0; i < sourceItems.count(); ++i) {
+ QModelIndex index = model.index(i, 0, QModelIndex());
+ model.setData(index, sourceItems.at(i), Qt::DisplayRole);
+ }
+
+ proxy.sort(0, static_cast<Qt::SortOrder>(sortOrder));
+ setupFilter(&proxy, filter);
+
+ QModelIndex startIndex = proxy.index(proxyStartRow, 0);
+ QModelIndexList indexes = proxy.match(startIndex, Qt::DisplayRole, what,
+ expectedProxyItems.count(),
+ Qt::MatchFlags(matchFlags));
+ QCOMPARE(indexes.count(), expectedProxyItems.count());
+ for (int i = 0; i < indexes.count(); ++i)
+ QCOMPARE(indexes.at(i).row(), expectedProxyItems.at(i));
+}
+
+void tst_QSortFilterProxyModel::insertIntoChildrenlessItem()
+{
+ QStandardItemModel model;
+ QStandardItem *itemA = new QStandardItem("a");
+ model.appendRow(itemA);
+ QStandardItem *itemB = new QStandardItem("b");
+ model.appendRow(itemB);
+ QStandardItem *itemC = new QStandardItem("c");
+ model.appendRow(itemC);
+
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+
+ QSignalSpy colsInsertedSpy(&proxy, &QSortFilterProxyModel::columnsInserted);
+ QSignalSpy rowsInsertedSpy(&proxy, &QSortFilterProxyModel::rowsInserted);
+
+ QVERIFY(colsInsertedSpy.isValid());
+ QVERIFY(rowsInsertedSpy.isValid());
+
+ (void)proxy.rowCount(QModelIndex()); // force mapping of "a", "b", "c"
+ QCOMPARE(colsInsertedSpy.count(), 0);
+ QCOMPARE(rowsInsertedSpy.count(), 0);
+
+ // now add a child to itemB ==> should get insert notification from the proxy
+ itemB->appendRow(new QStandardItem("a.0"));
+ QCOMPARE(colsInsertedSpy.count(), 1);
+ QCOMPARE(rowsInsertedSpy.count(), 1);
+
+ QVariantList args = colsInsertedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), proxy.mapFromSource(itemB->index()));
+ QCOMPARE(qvariant_cast<int>(args.at(1)), 0);
+ QCOMPARE(qvariant_cast<int>(args.at(2)), 0);
+
+ args = rowsInsertedSpy.takeFirst();
+ QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), proxy.mapFromSource(itemB->index()));
+ QCOMPARE(qvariant_cast<int>(args.at(1)), 0);
+ QCOMPARE(qvariant_cast<int>(args.at(2)), 0);
+}
+
+void tst_QSortFilterProxyModel::invalidateMappedChildren()
+{
+ QStandardItemModel model;
+
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+
+ QStandardItem *itemA = new QStandardItem("a");
+ model.appendRow(itemA);
+ QStandardItem *itemB = new QStandardItem("b");
+ itemA->appendRow(itemB);
+
+ QStandardItem *itemC = new QStandardItem("c");
+ itemB->appendRow(itemC);
+ itemC->appendRow(new QStandardItem("d"));
+
+ // force mappings
+ (void)proxy.hasChildren(QModelIndex());
+ (void)proxy.hasChildren(proxy.mapFromSource(itemA->index()));
+ (void)proxy.hasChildren(proxy.mapFromSource(itemB->index()));
+ (void)proxy.hasChildren(proxy.mapFromSource(itemC->index()));
+
+ itemB->removeRow(0); // should invalidate mapping of itemC
+ itemC = new QStandardItem("c");
+ itemA->appendRow(itemC);
+ itemC->appendRow(new QStandardItem("d"));
+
+ itemA->removeRow(1); // should invalidate mapping of itemC
+ itemC = new QStandardItem("c");
+ itemB->appendRow(itemC);
+ itemC->appendRow(new QStandardItem("d"));
+
+ QCOMPARE(proxy.rowCount(proxy.mapFromSource(itemA->index())), 1);
+ QCOMPARE(proxy.rowCount(proxy.mapFromSource(itemB->index())), 1);
+ QCOMPARE(proxy.rowCount(proxy.mapFromSource(itemC->index())), 1);
+}
+
+class EvenOddFilterModel : public QSortFilterProxyModel
+{
+public:
+ virtual bool filterAcceptsRow(int srcRow, const QModelIndex& srcParent) const
+ {
+ if (srcParent.isValid())
+ return (srcParent.row() % 2) ^ !(srcRow % 2);
+ return (srcRow % 2);
+ }
+};
+
+void tst_QSortFilterProxyModel::insertRowIntoFilteredParent()
+{
+ QStandardItemModel model;
+ EvenOddFilterModel proxy;
+ proxy.setSourceModel(&model);
+
+ QSignalSpy spy(&proxy, &EvenOddFilterModel::rowsInserted);
+ QVERIFY(spy.isValid());
+
+ QStandardItem *itemA = new QStandardItem();
+ model.appendRow(itemA); // A will be filtered
+ QStandardItem *itemB = new QStandardItem();
+ itemA->appendRow(itemB);
+
+ QCOMPARE(spy.count(), 0);
+
+ itemA->removeRow(0);
+
+ QCOMPARE(spy.count(), 0);
+}
+
+void tst_QSortFilterProxyModel::filterOutParentAndFilterInChild()
+{
+ QStandardItemModel model;
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+
+ setupFilter(&proxy, QLatin1String("A|B"));
+
+ QStandardItem *itemA = new QStandardItem("A");
+ model.appendRow(itemA); // not filtered
+ QStandardItem *itemB = new QStandardItem("B");
+ itemA->appendRow(itemB); // not filtered
+ QStandardItem *itemC = new QStandardItem("C");
+ itemA->appendRow(itemC); // filtered
+
+ QSignalSpy removedSpy(&proxy, &QSortFilterProxyModel::rowsRemoved);
+ QSignalSpy insertedSpy(&proxy, &QSortFilterProxyModel::rowsInserted);
+
+ QVERIFY(removedSpy.isValid());
+ QVERIFY(insertedSpy.isValid());
+
+ setupFilter(&proxy, QLatin1String("C")); // A and B will be filtered out, C filtered in
+
+ // we should now have been notified that the subtree represented by itemA has been removed
+ QCOMPARE(removedSpy.count(), 1);
+ // we should NOT get any inserts; itemC should be filtered because its parent (itemA) is
+ QCOMPARE(insertedSpy.count(), 0);
+}
+
+void tst_QSortFilterProxyModel::sourceInsertRows()
+{
+ QStandardItemModel model;
+ QSortFilterProxyModel proxyModel;
+ proxyModel.setSourceModel(&model);
+
+ model.insertColumns(0, 1, QModelIndex());
+ model.insertRows(0, 2, QModelIndex());
+
+ {
+ QModelIndex parent = model.index(0, 0, QModelIndex());
+ model.insertColumns(0, 1, parent);
+ model.insertRows(0, 1, parent);
+ }
+
+ {
+ QModelIndex parent = model.index(1, 0, QModelIndex());
+ model.insertColumns(0, 1, parent);
+ model.insertRows(0, 1, parent);
+ }
+
+ model.insertRows(0, 1, QModelIndex());
+ model.insertRows(0, 1, QModelIndex());
+
+ QVERIFY(true); // if you got here without asserting, it's all good
+}
+
+void tst_QSortFilterProxyModel::sourceModelDeletion()
+{
+ QSortFilterProxyModel proxyModel;
+ {
+ QStandardItemModel model;
+ proxyModel.setSourceModel(&model);
+ QCOMPARE(proxyModel.sourceModel(), static_cast<QAbstractItemModel*>(&model));
+ }
+ QCOMPARE(proxyModel.sourceModel(), static_cast<QAbstractItemModel*>(0));
+}
+
+void tst_QSortFilterProxyModel::sortColumnTracking1()
+{
+ QStandardItemModel model;
+ QSortFilterProxyModel proxyModel;
+ proxyModel.setSourceModel(&model);
+
+ model.insertColumns(0, 10);
+ model.insertRows(0, 10);
+
+ proxyModel.sort(1);
+ QCOMPARE(proxyModel.sortColumn(), 1);
+
+ model.insertColumn(8);
+ QCOMPARE(proxyModel.sortColumn(), 1);
+
+ model.removeColumn(8);
+ QCOMPARE(proxyModel.sortColumn(), 1);
+
+ model.insertColumn(2);
+ QCOMPARE(proxyModel.sortColumn(), 1);
+
+ model.removeColumn(2);
+ QCOMPARE(proxyModel.sortColumn(), 1);
+
+ model.insertColumn(1);
+ QCOMPARE(proxyModel.sortColumn(), 2);
+
+ model.removeColumn(1);
+ QCOMPARE(proxyModel.sortColumn(), 1);
+
+ model.removeColumn(1);
+ QCOMPARE(proxyModel.sortColumn(), -1);
+}
+
+void tst_QSortFilterProxyModel::sortColumnTracking2()
+{
+ QStandardItemModel model;
+ QSortFilterProxyModel proxyModel;
+ proxyModel.setDynamicSortFilter(true);
+ proxyModel.setSourceModel(&model);
+
+ proxyModel.sort(0);
+ QCOMPARE(proxyModel.sortColumn(), 0);
+
+ QList<QStandardItem *> items; // Stable sorting: Items with invalid data should move to the end
+ items << new QStandardItem << new QStandardItem("foo") << new QStandardItem("bar")
+ << new QStandardItem("some") << new QStandardItem("others") << new QStandardItem("item")
+ << new QStandardItem("aa") << new QStandardItem("zz") << new QStandardItem;
+
+ model.insertColumn(0,items);
+ QCOMPARE(proxyModel.sortColumn(), 0);
+ QCOMPARE(proxyModel.data(proxyModel.index(0,0)).toString(),QString::fromLatin1("aa"));
+ const int zzIndex = items.count() - 3; // 2 invalid at end.
+ QCOMPARE(proxyModel.data(proxyModel.index(zzIndex,0)).toString(),QString::fromLatin1("zz"));
+}
+
+void tst_QSortFilterProxyModel::sortStable()
+{
+ QStandardItemModel* model = new QStandardItemModel(5, 2);
+ for (int r = 0; r < 5; r++) {
+ const QString prefix = QLatin1String("Row:") + QString::number(r) + QLatin1String(", Column:");
+ for (int c = 0; c < 2; c++) {
+ QStandardItem* item = new QStandardItem(prefix + QString::number(c));
+ for (int i = 0; i < 3; i++) {
+ QStandardItem* child = new QStandardItem(QLatin1String("Item ") + QString::number(i));
+ item->appendRow( child );
+ }
+ model->setItem(r, c, item);
+ }
+ }
+ model->setHorizontalHeaderItem( 0, new QStandardItem( "Name" ));
+ model->setHorizontalHeaderItem( 1, new QStandardItem( "Value" ));
+
+ QSortFilterProxyModel *filterModel = new QSortFilterProxyModel(model);
+ filterModel->setSourceModel(model);
+
+ QTreeView *view = new QTreeView;
+ view->setModel(filterModel);
+ QModelIndex firstRoot = filterModel->index(0,0);
+ view->expand(firstRoot);
+ view->setSortingEnabled(true);
+
+ view->model()->sort(1, Qt::DescendingOrder);
+ QVariant lastItemData =filterModel->index(2,0, firstRoot).data();
+ view->model()->sort(1, Qt::DescendingOrder);
+ QCOMPARE(lastItemData, filterModel->index(2,0, firstRoot).data());
+}
+
+void tst_QSortFilterProxyModel::hiddenColumns()
+{
+ class MyStandardItemModel : public QStandardItemModel
+ {
+ public:
+ MyStandardItemModel() : QStandardItemModel(0,5) {}
+ void reset()
+ { beginResetModel(); endResetModel(); }
+ friend class tst_QSortFilterProxyModel;
+ } model;
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+
+ QTableView view;
+ view.setModel(&proxy);
+
+ view.hideColumn(0);
+
+ QVERIFY(view.isColumnHidden(0));
+ model.blockSignals(true);
+ model.setRowCount(1);
+ model.blockSignals(false);
+ model.reset();
+
+ // In the initial bug report that spawned this test, this would be false
+ // because resetting model would also reset the hidden columns.
+ QVERIFY(view.isColumnHidden(0));
+}
+
+void tst_QSortFilterProxyModel::insertRowsSort()
+{
+ QStandardItemModel model(2,2);
+ QSortFilterProxyModel proxyModel;
+ proxyModel.setSourceModel(&model);
+
+ proxyModel.sort(0);
+ QCOMPARE(proxyModel.sortColumn(), 0);
+
+ model.insertColumns(0, 3, model.index(0,0));
+ QCOMPARE(proxyModel.sortColumn(), 0);
+
+ model.removeColumns(0, 3, model.index(0,0));
+ QCOMPARE(proxyModel.sortColumn(), 0);
+}
+
+void tst_QSortFilterProxyModel::staticSorting()
+{
+ QStandardItemModel model(0, 1);
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+ proxy.setDynamicSortFilter(false);
+ QStringList initial = QString("bateau avion dragon hirondelle flamme camion elephant").split(QLatin1Char(' '));
+
+ // prepare model
+ QStandardItem *root = model.invisibleRootItem ();
+ QList<QStandardItem *> items;
+ for (int i = 0; i < initial.count(); ++i) {
+ items.append(new QStandardItem(initial.at(i)));
+ }
+ root->insertRows(0, items);
+ QCOMPARE(model.rowCount(QModelIndex()), initial.count());
+ QCOMPARE(model.columnCount(QModelIndex()), 1);
+
+ // make sure the proxy is unsorted
+ QCOMPARE(proxy.columnCount(QModelIndex()), 1);
+ QCOMPARE(proxy.rowCount(QModelIndex()), initial.count());
+ for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy.index(row, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), initial.at(row));
+ }
+
+ // sort
+ proxy.sort(0);
+
+ QStringList expected = initial;
+ expected.sort();
+ // make sure the proxy is sorted
+ for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy.index(row, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+
+ //update one item.
+ items.first()->setData("girafe", Qt::DisplayRole);
+
+ // make sure the proxy is updated but not sorted
+ expected.replaceInStrings("bateau", "girafe");
+ for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy.index(row, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+
+ // sort again
+ proxy.sort(0);
+ expected.sort();
+
+ // make sure the proxy is sorted
+ for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy.index(row, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+}
+
+void tst_QSortFilterProxyModel::dynamicSorting()
+{
+ QStringListModel model1;
+ const QStringList initial = QString("bateau avion dragon hirondelle flamme camion elephant").split(QLatin1Char(' '));
+ model1.setStringList(initial);
+ QSortFilterProxyModel proxy1;
+ proxy1.setDynamicSortFilter(false);
+ proxy1.sort(0);
+ proxy1.setSourceModel(&model1);
+
+ QCOMPARE(proxy1.columnCount(QModelIndex()), 1);
+ //the model should not be sorted because sorting has not been set to dynamic yet.
+ QCOMPARE(proxy1.rowCount(QModelIndex()), initial.count());
+ for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy1.index(row, 0, QModelIndex());
+ QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), initial.at(row));
+ }
+
+ proxy1.setDynamicSortFilter(true);
+
+ //now the model should be sorted.
+ QStringList expected = initial;
+ expected.sort();
+ for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy1.index(row, 0, QModelIndex());
+ QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+
+ QStringList initial2 = initial;
+ initial2.replaceInStrings("bateau", "girafe");
+ model1.setStringList(initial2); //this will cause a reset
+
+ QStringList expected2 = initial2;
+ expected2.sort();
+
+ //now the model should still be sorted.
+ for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy1.index(row, 0, QModelIndex());
+ QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), expected2.at(row));
+ }
+
+ QStringListModel model2(initial);
+ proxy1.setSourceModel(&model2);
+
+ //the model should again be sorted
+ for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy1.index(row, 0, QModelIndex());
+ QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+
+ //set up the sorting before seting the model up
+ QSortFilterProxyModel proxy2;
+ proxy2.sort(0);
+ proxy2.setSourceModel(&model2);
+ for (int row = 0; row < proxy2.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy2.index(row, 0, QModelIndex());
+ QCOMPARE(proxy2.data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+}
+
+class QtTestModel: public QAbstractItemModel
+{
+public:
+ QtTestModel(int _rows, int _cols, QObject *parent = 0)
+ : QAbstractItemModel(parent)
+ , rows(_rows)
+ , cols(_cols)
+ , wrongIndex(false)
+ {
+ }
+
+ bool canFetchMore(const QModelIndex &idx) const
+ {
+ return !fetched.contains(idx);
+ }
+
+ void fetchMore(const QModelIndex &idx)
+ {
+ if (fetched.contains(idx))
+ return;
+ beginInsertRows(idx, 0, rows-1);
+ fetched.insert(idx);
+ endInsertRows();
+ }
+
+ bool hasChildren(const QModelIndex & = QModelIndex()) const
+ {
+ return true;
+ }
+
+ int rowCount(const QModelIndex& parent = QModelIndex()) const
+ {
+ return fetched.contains(parent) ? rows : 0;
+ }
+
+ int columnCount(const QModelIndex& parent = QModelIndex()) const
+ {
+ Q_UNUSED(parent);
+ return cols;
+ }
+
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const
+ {
+ if (row < 0 || column < 0 || column >= cols || row >= rows) {
+ return QModelIndex();
+ }
+ QModelIndex i = createIndex(row, column, int(parent.internalId() + 1));
+ parentHash[i] = parent;
+ return i;
+ }
+
+ QModelIndex parent(const QModelIndex &index) const
+ {
+ if (!parentHash.contains(index))
+ return QModelIndex();
+ return parentHash[index];
+ }
+
+ QVariant data(const QModelIndex &idx, int role) const
+ {
+ if (!idx.isValid())
+ return QVariant();
+
+ if (role == Qt::DisplayRole) {
+ if (idx.row() < 0 || idx.column() < 0 || idx.column() >= cols || idx.row() >= rows) {
+ wrongIndex = true;
+ qWarning("Invalid modelIndex [%d,%d,%p]", idx.row(), idx.column(),
+ idx.internalPointer());
+ }
+ return QLatin1Char('[') + QString::number(idx.row()) + QLatin1Char(',')
+ + QString::number(idx.column()) + QLatin1Char(']');
+ }
+ return QVariant();
+ }
+
+ QSet<QModelIndex> fetched;
+ int rows, cols;
+ mutable bool wrongIndex;
+ mutable QMap<QModelIndex,QModelIndex> parentHash;
+};
+
+void tst_QSortFilterProxyModel::fetchMore()
+{
+ QtTestModel model(10,10);
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+ QVERIFY(proxy.canFetchMore(QModelIndex()));
+ QVERIFY(proxy.hasChildren());
+ while (proxy.canFetchMore(QModelIndex()))
+ proxy.fetchMore(QModelIndex());
+ QCOMPARE(proxy.rowCount(), 10);
+ QCOMPARE(proxy.columnCount(), 10);
+
+ QModelIndex idx = proxy.index(1,1);
+ QVERIFY(idx.isValid());
+ QVERIFY(proxy.canFetchMore(idx));
+ QVERIFY(proxy.hasChildren(idx));
+ while (proxy.canFetchMore(idx))
+ proxy.fetchMore(idx);
+ QCOMPARE(proxy.rowCount(idx), 10);
+ QCOMPARE(proxy.columnCount(idx), 10);
+}
+
+void tst_QSortFilterProxyModel::hiddenChildren()
+{
+ QStandardItemModel model;
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+ proxy.setDynamicSortFilter(true);
+
+ QStandardItem *itemA = new QStandardItem("A VISIBLE");
+ model.appendRow(itemA);
+ QStandardItem *itemB = new QStandardItem("B VISIBLE");
+ itemA->appendRow(itemB);
+ QStandardItem *itemC = new QStandardItem("C");
+ itemA->appendRow(itemC);
+ setupFilter(&proxy, QLatin1String("VISIBLE"));
+
+ QCOMPARE(proxy.rowCount(QModelIndex()) , 1);
+ QPersistentModelIndex indexA = proxy.index(0,0);
+ QCOMPARE(proxy.data(indexA).toString(), QString::fromLatin1("A VISIBLE"));
+
+ QCOMPARE(proxy.rowCount(indexA) , 1);
+ QPersistentModelIndex indexB = proxy.index(0, 0, indexA);
+ QCOMPARE(proxy.data(indexB).toString(), QString::fromLatin1("B VISIBLE"));
+
+ itemA->setText("A");
+ QCOMPARE(proxy.rowCount(QModelIndex()), 0);
+ QVERIFY(!indexA.isValid());
+ QVERIFY(!indexB.isValid());
+
+ itemB->setText("B");
+ itemA->setText("A VISIBLE");
+ itemC->setText("C VISIBLE");
+
+ QCOMPARE(proxy.rowCount(QModelIndex()), 1);
+ indexA = proxy.index(0,0);
+ QCOMPARE(proxy.data(indexA).toString(), QString::fromLatin1("A VISIBLE"));
+
+ QCOMPARE(proxy.rowCount(indexA) , 1);
+ QModelIndex indexC = proxy.index(0, 0, indexA);
+ QCOMPARE(proxy.data(indexC).toString(), QString::fromLatin1("C VISIBLE"));
+
+ setupFilter(&proxy, QLatin1String("C"));
+
+ QCOMPARE(proxy.rowCount(QModelIndex()), 0);
+ itemC->setText("invisible");
+ itemA->setText("AC");
+
+ QCOMPARE(proxy.rowCount(QModelIndex()), 1);
+ indexA = proxy.index(0,0);
+ QCOMPARE(proxy.data(indexA).toString(), QString::fromLatin1("AC"));
+ QCOMPARE(proxy.rowCount(indexA) , 0);
+}
+
+void tst_QSortFilterProxyModel::mapFromToSource()
+{
+ QtTestModel source(10,10);
+ source.fetchMore(QModelIndex());
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&source);
+ QCOMPARE(proxy.mapFromSource(source.index(5, 4)), proxy.index(5, 4));
+ QCOMPARE(proxy.mapToSource(proxy.index(3, 2)), source.index(3, 2));
+ QCOMPARE(proxy.mapFromSource(QModelIndex()), QModelIndex());
+ QCOMPARE(proxy.mapToSource(QModelIndex()), QModelIndex());
+
+#ifdef QT_NO_DEBUG //if Qt is compiled in debug mode, this will assert
+ QTest::ignoreMessage(QtWarningMsg, "QSortFilterProxyModel: index from wrong model passed to mapToSource");
+ QCOMPARE(proxy.mapToSource(source.index(2, 3)), QModelIndex());
+ QTest::ignoreMessage(QtWarningMsg, "QSortFilterProxyModel: index from wrong model passed to mapFromSource");
+ QCOMPARE(proxy.mapFromSource(proxy.index(6, 2)), QModelIndex());
+#endif
+}
+
+static QStandardItem *addEntry(QStandardItem* pParent, const QString &description)
+{
+ QStandardItem* pItem = new QStandardItem(description);
+ pParent->appendRow(pItem);
+ return pItem;
+}
+
+void tst_QSortFilterProxyModel::removeRowsRecursive()
+{
+ QStandardItemModel pModel;
+ QStandardItem *pItem1 = new QStandardItem("root");
+ pModel.appendRow(pItem1);
+ QList<QStandardItem *> items;
+
+ QStandardItem *pItem11 = addEntry(pItem1,"Sub-heading");
+ items << pItem11;
+ QStandardItem *pItem111 = addEntry(pItem11,"A");
+ items << pItem111;
+ items << addEntry(pItem111,"A1");
+ items << addEntry(pItem111,"A2");
+ QStandardItem *pItem112 = addEntry(pItem11,"B");
+ items << pItem112;
+ items << addEntry(pItem112,"B1");
+ items << addEntry(pItem112,"B2");
+ QStandardItem *pItem1123 = addEntry(pItem112,"B3");
+ items << pItem1123;
+ items << addEntry(pItem1123,"B3-");
+
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&pModel);
+
+ QList<QPersistentModelIndex> sourceIndexes;
+ QList<QPersistentModelIndex> proxyIndexes;
+ foreach (QStandardItem *item, items) {
+ QModelIndex idx = item->index();
+ sourceIndexes << idx;
+ proxyIndexes << proxy.mapFromSource(idx);
+ }
+
+ foreach (const QPersistentModelIndex &pidx, sourceIndexes)
+ QVERIFY(pidx.isValid());
+ foreach (const QPersistentModelIndex &pidx, proxyIndexes)
+ QVERIFY(pidx.isValid());
+
+ QList<QStandardItem*> itemRow = pItem1->takeRow(0);
+
+ QCOMPARE(itemRow.count(), 1);
+ QCOMPARE(itemRow.first(), pItem11);
+
+ foreach (const QPersistentModelIndex &pidx, sourceIndexes)
+ QVERIFY(!pidx.isValid());
+ foreach (const QPersistentModelIndex &pidx, proxyIndexes)
+ QVERIFY(!pidx.isValid());
+
+ delete pItem11;
+}
+
+void tst_QSortFilterProxyModel::doubleProxySelectionSetSourceModel()
+{
+ QStandardItemModel *model1 = new QStandardItemModel;
+ QStandardItem *parentItem = model1->invisibleRootItem();
+ for (int i = 0; i < 4; ++i) {
+ QStandardItem *item = new QStandardItem(QLatin1String("model1 item ") + QString::number(i));
+ parentItem->appendRow(item);
+ parentItem = item;
+ }
+
+ QStandardItemModel *model2 = new QStandardItemModel;
+ QStandardItem *parentItem2 = model2->invisibleRootItem();
+ for (int i = 0; i < 4; ++i) {
+ QStandardItem *item = new QStandardItem(QLatin1String("model2 item ") + QString::number(i));
+ parentItem2->appendRow(item);
+ parentItem2 = item;
+ }
+
+ QSortFilterProxyModel *toggleProxy = new QSortFilterProxyModel;
+ toggleProxy->setSourceModel(model1);
+
+ QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel;
+ proxyModel->setSourceModel(toggleProxy);
+
+ QModelIndex mi = proxyModel->index(0, 0, proxyModel->index(0, 0, proxyModel->index(0, 0)));
+ QItemSelectionModel ism(proxyModel);
+ ism.select(mi, QItemSelectionModel::Select);
+ QModelIndexList mil = ism.selectedIndexes();
+ QCOMPARE(mil.count(), 1);
+ QCOMPARE(mil.first(), mi);
+
+ toggleProxy->setSourceModel(model2);
+ // No crash, it's good news!
+ QVERIFY(ism.selection().isEmpty());
+}
+
+void tst_QSortFilterProxyModel::appearsAndSort()
+{
+ class PModel : public QSortFilterProxyModel
+ {
+ public:
+ PModel() : mVisible(false) {};
+ protected:
+ bool filterAcceptsRow(int, const QModelIndex &) const
+ {
+ return mVisible;
+ }
+
+ public:
+ void updateXX()
+ {
+ mVisible = true;
+ invalidate();
+ }
+ private:
+ bool mVisible;
+ } proxyModel;
+
+ QStringListModel sourceModel;
+ QStringList list;
+ list << "b" << "a" << "c";
+ sourceModel.setStringList(list);
+
+ proxyModel.setSourceModel(&sourceModel);
+ proxyModel.setDynamicSortFilter(true);
+ proxyModel.sort(0, Qt::AscendingOrder);
+
+ QApplication::processEvents();
+ QCOMPARE(sourceModel.rowCount(), 3);
+ QCOMPARE(proxyModel.rowCount(), 0); //all rows are hidden at first;
+
+ QSignalSpy spyAbout1(&proxyModel, &PModel::layoutAboutToBeChanged);
+ QSignalSpy spyChanged1(&proxyModel, &PModel::layoutChanged);
+
+ QVERIFY(spyAbout1.isValid());
+ QVERIFY(spyChanged1.isValid());
+
+ //introducing secondProxyModel to test the layoutChange when many items appears at once
+ QSortFilterProxyModel secondProxyModel;
+ secondProxyModel.setSourceModel(&proxyModel);
+ secondProxyModel.setDynamicSortFilter(true);
+ secondProxyModel.sort(0, Qt::DescendingOrder);
+ QCOMPARE(secondProxyModel.rowCount(), 0); //all rows are hidden at first;
+ QSignalSpy spyAbout2(&secondProxyModel, &QSortFilterProxyModel::layoutAboutToBeChanged);
+ QSignalSpy spyChanged2(&secondProxyModel, &QSortFilterProxyModel::layoutChanged);
+
+ QVERIFY(spyAbout2.isValid());
+ QVERIFY(spyChanged2.isValid());
+
+ proxyModel.updateXX();
+ QApplication::processEvents();
+ //now rows should be visible, and sorted
+ QCOMPARE(proxyModel.rowCount(), 3);
+ QCOMPARE(proxyModel.data(proxyModel.index(0,0), Qt::DisplayRole).toString(), QString::fromLatin1("a"));
+ QCOMPARE(proxyModel.data(proxyModel.index(1,0), Qt::DisplayRole).toString(), QString::fromLatin1("b"));
+ QCOMPARE(proxyModel.data(proxyModel.index(2,0), Qt::DisplayRole).toString(), QString::fromLatin1("c"));
+
+ //now rows should be visible, and sorted
+ QCOMPARE(secondProxyModel.rowCount(), 3);
+ QCOMPARE(secondProxyModel.data(secondProxyModel.index(0,0), Qt::DisplayRole).toString(), QString::fromLatin1("c"));
+ QCOMPARE(secondProxyModel.data(secondProxyModel.index(1,0), Qt::DisplayRole).toString(), QString::fromLatin1("b"));
+ QCOMPARE(secondProxyModel.data(secondProxyModel.index(2,0), Qt::DisplayRole).toString(), QString::fromLatin1("a"));
+
+ QCOMPARE(spyAbout1.count(), 1);
+ QCOMPARE(spyChanged1.count(), 1);
+ QCOMPARE(spyAbout2.count(), 1);
+ QCOMPARE(spyChanged2.count(), 1);
+}
+
+void tst_QSortFilterProxyModel::unnecessaryDynamicSorting()
+{
+ QStringListModel model;
+ const QStringList initial = QString("bravo charlie delta echo").split(QLatin1Char(' '));
+ model.setStringList(initial);
+ QSortFilterProxyModel proxy;
+ proxy.setDynamicSortFilter(false);
+ proxy.setSourceModel(&model);
+ proxy.sort(Qt::AscendingOrder);
+
+ //append two rows
+ int maxrows = proxy.rowCount(QModelIndex());
+ model.insertRows(maxrows, 2);
+ model.setData(model.index(maxrows, 0), QString("alpha"));
+ model.setData(model.index(maxrows + 1, 0), QString("fondue"));
+
+ //append new items to the initial string list and compare with model
+ QStringList expected = initial;
+ expected << QString("alpha") << QString("fondue");
+
+ //if bug 7716 is present, new rows were prepended, when they should have been appended
+ for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy.index(row, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+}
+
+class SelectionProxyModel : QAbstractProxyModel
+{
+ Q_OBJECT
+public:
+ SelectionProxyModel()
+ : QAbstractProxyModel(), selectionModel(0)
+ {
+ }
+
+ QModelIndex mapFromSource(QModelIndex const&) const
+ { return QModelIndex(); }
+
+ QModelIndex mapToSource(QModelIndex const&) const
+ { return QModelIndex(); }
+
+ QModelIndex index(int, int, const QModelIndex&) const
+ { return QModelIndex(); }
+
+ QModelIndex parent(const QModelIndex&) const
+ { return QModelIndex(); }
+
+ int rowCount(const QModelIndex&) const
+ { return 0; }
+
+ int columnCount(const QModelIndex&) const
+ { return 0; }
+
+ void setSourceModel( QAbstractItemModel *sourceModel )
+ {
+ beginResetModel();
+ disconnect( sourceModel, SIGNAL(modelAboutToBeReset()), this, SLOT(sourceModelAboutToBeReset()) );
+ QAbstractProxyModel::setSourceModel( sourceModel );
+ connect( sourceModel, SIGNAL(modelAboutToBeReset()), this, SLOT(sourceModelAboutToBeReset()) );
+ endResetModel();
+ }
+
+ void setSelectionModel( QItemSelectionModel *_selectionModel )
+ {
+ selectionModel = _selectionModel;
+ }
+
+private slots:
+ void sourceModelAboutToBeReset()
+ {
+ QVERIFY( selectionModel->selectedIndexes().size() == 1 );
+ beginResetModel();
+ }
+
+ void sourceModelReset()
+ {
+ endResetModel();
+ }
+
+private:
+ QItemSelectionModel *selectionModel;
+};
+
+void tst_QSortFilterProxyModel::testMultipleProxiesWithSelection()
+{
+ QStringListModel model;
+ const QStringList initial = QString("bravo charlie delta echo").split(QLatin1Char(' '));
+ model.setStringList(initial);
+
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel( &model );
+
+ SelectionProxyModel proxy1;
+ QSortFilterProxyModel proxy2;
+
+ // Note that the order here matters. The order of the sourceAboutToBeReset
+ // exposes the bug in QSortFilterProxyModel.
+ proxy2.setSourceModel( &proxy );
+ proxy1.setSourceModel( &proxy );
+
+ QItemSelectionModel selectionModel(&proxy2);
+ proxy1.setSelectionModel( &selectionModel );
+
+ selectionModel.select( proxy2.index( 0, 0 ), QItemSelectionModel::Select );
+
+ // trick the proxy into emitting begin/end reset signals.
+ proxy.setSourceModel(0);
+}
+
+static bool isValid(const QItemSelection &selection)
+{
+ foreach (const QItemSelectionRange &range, selection)
+ if (!range.isValid())
+ return false;
+ return true;
+}
+
+void tst_QSortFilterProxyModel::mapSelectionFromSource()
+{
+ QStringListModel model;
+ const QStringList initial = QString("bravo charlie delta echo").split(QLatin1Char(' '));
+ model.setStringList(initial);
+
+ QSortFilterProxyModel proxy;
+ proxy.setDynamicSortFilter(true);
+ setupFilter(&proxy, QLatin1String("d.*"));
+
+ proxy.setSourceModel(&model);
+
+ // Only "delta" remains.
+ QCOMPARE(proxy.rowCount(), 1);
+
+ QItemSelection selection;
+ QModelIndex charlie = model.index(1, 0);
+ selection.append(QItemSelectionRange(charlie, charlie));
+ QModelIndex delta = model.index(2, 0);
+ selection.append(QItemSelectionRange(delta, delta));
+ QModelIndex echo = model.index(3, 0);
+ selection.append(QItemSelectionRange(echo, echo));
+
+ QVERIFY(isValid(selection));
+
+ QItemSelection proxiedSelection = proxy.mapSelectionFromSource(selection);
+
+ // Only "delta" is in the mapped result.
+ QCOMPARE(proxiedSelection.size(), 1);
+ QVERIFY(isValid(proxiedSelection));
+}
+
+class Model10287 : public QStandardItemModel
+{
+ Q_OBJECT
+
+public:
+ Model10287(QObject *parent = 0)
+ : QStandardItemModel(0, 1, parent)
+ {
+ parentItem = new QStandardItem("parent");
+ parentItem->setData(false, Qt::UserRole);
+ appendRow(parentItem);
+
+ childItem = new QStandardItem("child");
+ childItem->setData(true, Qt::UserRole);
+ parentItem->appendRow(childItem);
+
+ childItem2 = new QStandardItem("child2");
+ childItem2->setData(true, Qt::UserRole);
+ parentItem->appendRow(childItem2);
+ }
+
+ void removeChild()
+ {
+ childItem2->setData(false, Qt::UserRole);
+ parentItem->removeRow(0);
+ }
+
+private:
+ QStandardItem *parentItem, *childItem, *childItem2;
+};
+
+class Proxy10287 : public QSortFilterProxyModel
+{
+ Q_OBJECT
+
+public:
+ Proxy10287(QAbstractItemModel *model, QObject *parent = 0)
+ : QSortFilterProxyModel(parent)
+ {
+ setSourceModel(model);
+ setDynamicSortFilter(true);
+ }
+
+protected:
+ virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
+ {
+ // Filter based on UserRole in model
+ QModelIndex i = sourceModel()->index(source_row, 0, source_parent);
+ return i.data(Qt::UserRole).toBool();
+ }
+};
+
+void tst_QSortFilterProxyModel::unnecessaryMapCreation()
+{
+ Model10287 m;
+ Proxy10287 p(&m);
+ m.removeChild();
+ // No assert failure, it passes.
+}
+
+class FilteredColumnProxyModel : public QSortFilterProxyModel
+{
+ Q_OBJECT
+public:
+ FilteredColumnProxyModel(QObject *parent = 0)
+ : QSortFilterProxyModel(parent)
+ {
+ }
+
+protected:
+ bool filterAcceptsColumn(int column, const QModelIndex & /* source_parent */) const
+ {
+ return column % 2 != 0;
+ }
+};
+
+void tst_QSortFilterProxyModel::filteredColumns()
+{
+ DynamicTreeModel *model = new DynamicTreeModel(this);
+
+ FilteredColumnProxyModel *proxy = new FilteredColumnProxyModel(this);
+ proxy->setSourceModel(model);
+
+ new QAbstractItemModelTester(proxy, this);
+
+ ModelInsertCommand *insertCommand = new ModelInsertCommand(model, this);
+ insertCommand->setNumCols(2);
+ insertCommand->setStartRow(0);
+ insertCommand->setEndRow(0);
+ // Parent is QModelIndex()
+ insertCommand->doCommand();
+}
+
+class ChangableHeaderData : public QStringListModel
+{
+ Q_OBJECT
+public:
+ explicit ChangableHeaderData(QObject *parent = 0)
+ : QStringListModel(parent)
+ {
+
+ }
+
+ void emitHeaderDataChanged()
+ {
+ headerDataChanged(Qt::Vertical, 0, rowCount() - 1);
+ }
+};
+
+
+void tst_QSortFilterProxyModel::headerDataChanged()
+{
+ ChangableHeaderData *model = new ChangableHeaderData(this);
+
+ QStringList numbers;
+ for (int i = 0; i < 10; ++i)
+ numbers.append(QString::number(i));
+ model->setStringList(numbers);
+
+ QSortFilterProxyModel *proxy = new QSortFilterProxyModel(this);
+ proxy->setSourceModel(model);
+
+ new QAbstractItemModelTester(proxy, this);
+
+ model->emitHeaderDataChanged();
+}
+
+void tst_QSortFilterProxyModel::resetInvalidate_data()
+{
+ QTest::addColumn<int>("test");
+ QTest::addColumn<bool>("works");
+
+ QTest::newRow("nothing") << 0 << false;
+ QTest::newRow("reset") << 1 << true;
+ QTest::newRow("invalidate") << 2 << true;
+ QTest::newRow("invalidate_filter") << 3 << true;
+}
+
+void tst_QSortFilterProxyModel::resetInvalidate()
+{
+ QFETCH(int, test);
+ QFETCH(bool, works);
+
+ struct Proxy : QSortFilterProxyModel {
+ QString pattern;
+ virtual bool filterAcceptsRow(int source_row, const QModelIndex&) const
+ {
+ return sourceModel()->data(sourceModel()->index(source_row, 0)).toString().contains(pattern);
+ }
+ void notifyChange(int test)
+ {
+ switch (test) {
+ case 0: break;
+ case 1:
+ beginResetModel();
+ endResetModel();
+ break;
+ case 2: invalidate(); break;
+ case 3: invalidateFilter(); break;
+ }
+ }
+ };
+
+ QStringListModel sourceModel(QStringList() << "Poisson" << "Vache" << "Brebis"
+ << "Elephant" << "Cochon" << "Serpent"
+ << "Mouton" << "Ecureuil" << "Mouche");
+ Proxy proxy;
+ proxy.pattern = QString::fromLatin1("n");
+ proxy.setSourceModel(&sourceModel);
+
+ QCOMPARE(proxy.rowCount(), 5);
+ for (int i = 0; i < proxy.rowCount(); i++) {
+ QVERIFY(proxy.data(proxy.index(i,0)).toString().contains('n'));
+ }
+
+ proxy.pattern = QString::fromLatin1("o");
+ proxy.notifyChange(test);
+
+ QCOMPARE(proxy.rowCount(), works ? 4 : 5);
+ bool ok = true;
+ for (int i = 0; i < proxy.rowCount(); i++) {
+ if (!proxy.data(proxy.index(i,0)).toString().contains('o'))
+ ok = false;
+ }
+ QCOMPARE(ok, works);
+}
+
+/**
+ * A proxy which changes the background color for items ending in 'y' or 'r'
+ */
+class CustomDataProxy : public QSortFilterProxyModel
+{
+ Q_OBJECT
+
+public:
+ CustomDataProxy(QObject *parent = 0)
+ : QSortFilterProxyModel(parent)
+ {
+ setDynamicSortFilter(true);
+ }
+
+ void setSourceModel(QAbstractItemModel *sourceModel)
+ {
+ // It would be possible to use only the modelReset signal of the source model to clear
+ // the data in *this, however, this requires that the slot is connected
+ // before QSortFilterProxyModel::setSourceModel is called, and even then depends
+ // on the order of invocation of slots being the same as the order of connection.
+ // ie, not reliable.
+// connect(sourceModel, SIGNAL(modelReset()), SLOT(resetInternalData()));
+ QSortFilterProxyModel::setSourceModel(sourceModel);
+ // Making the connect after the setSourceModel call clears the data too late.
+// connect(sourceModel, SIGNAL(modelReset()), SLOT(resetInternalData()));
+
+ // This could be done in data(), but the point is to need to cache something in the proxy
+ // which needs to be cleared on reset.
+ for (int i = 0; i < sourceModel->rowCount(); ++i)
+ {
+ if (sourceModel->index(i, 0).data().toString().endsWith(QLatin1Char('y')))
+ {
+ m_backgroundColours.insert(i, Qt::blue);
+ } else if (sourceModel->index(i, 0).data().toString().endsWith(QLatin1Char('r')))
+ {
+ m_backgroundColours.insert(i, Qt::red);
+ }
+ }
+ }
+
+ QVariant data(const QModelIndex &index, int role) const
+ {
+ if (role != Qt::BackgroundRole)
+ return QSortFilterProxyModel::data(index, role);
+ return m_backgroundColours.value(index.row());
+ }
+
+private slots:
+ void resetInternalData()
+ {
+ m_backgroundColours.clear();
+ }
+
+private:
+ QHash<int, QColor> m_backgroundColours;
+};
+
+class ModelObserver : public QObject
+{
+ Q_OBJECT
+public:
+ ModelObserver(QAbstractItemModel *model, QObject *parent = 0)
+ : QObject(parent), m_model(model)
+ {
+ connect(m_model, SIGNAL(modelAboutToBeReset()), SLOT(modelAboutToBeReset()));
+ connect(m_model, SIGNAL(modelReset()), SLOT(modelReset()));
+ }
+
+public slots:
+ void modelAboutToBeReset()
+ {
+ int reds = 0, blues = 0;
+ for (int i = 0; i < m_model->rowCount(); ++i)
+ {
+ QColor color = m_model->index(i, 0).data(Qt::BackgroundRole).value<QColor>();
+ if (color == Qt::blue)
+ ++blues;
+ if (color == Qt::red)
+ ++reds;
+ }
+ QCOMPARE(blues, 11);
+ QCOMPARE(reds, 4);
+ }
+
+ void modelReset()
+ {
+ int reds = 0, blues = 0;
+ for (int i = 0; i < m_model->rowCount(); ++i)
+ {
+ QColor color = m_model->index(i, 0).data(Qt::BackgroundRole).value<QColor>();
+ if (color == Qt::blue)
+ ++blues;
+ if (color == Qt::red)
+ ++reds;
+ }
+ QCOMPARE(reds, 0);
+ QCOMPARE(blues, 0);
+ }
+
+private:
+ QAbstractItemModel * const m_model;
+
+};
+
+void tst_QSortFilterProxyModel::testResetInternalData()
+{
+
+ QStringListModel model(QStringList() << "Monday"
+ << "Tuesday"
+ << "Wednesday"
+ << "Thursday"
+ << "Friday"
+ << "January"
+ << "February"
+ << "March"
+ << "April"
+ << "May"
+ << "Saturday"
+ << "June"
+ << "Sunday"
+ << "July"
+ << "August"
+ << "September"
+ << "October"
+ << "November"
+ << "December");
+
+ CustomDataProxy proxy;
+ proxy.setSourceModel(&model);
+
+ ModelObserver observer(&proxy);
+
+ // Cause the source model to reset.
+ model.setStringList(QStringList() << "Spam" << "Eggs");
+
+}
+
+void tst_QSortFilterProxyModel::testParentLayoutChanged()
+{
+ QStandardItemModel model;
+ QStandardItem *parentItem = model.invisibleRootItem();
+ for (int i = 0; i < 4; ++i) {
+ {
+ QStandardItem *item = new QStandardItem(QLatin1String("item ") + QString::number(i));
+ parentItem->appendRow(item);
+ }
+ {
+ QStandardItem *item = new QStandardItem(QLatin1String("item 1") + QString::number(i));
+ parentItem->appendRow(item);
+ parentItem = item;
+ }
+ }
+ // item 0
+ // item 10
+ // - item 1
+ // - item 11
+ // - item 2
+ // - item 12
+ // ...
+
+ QSortFilterProxyModel proxy;
+ proxy.sort(0, Qt::AscendingOrder);
+ proxy.setDynamicSortFilter(true);
+
+ proxy.setSourceModel(&model);
+ proxy.setObjectName("proxy");
+
+ // When Proxy1 emits layoutChanged(QList<QPersistentModelIndex>) this
+ // one will too, with mapped indexes.
+ QSortFilterProxyModel proxy2;
+ proxy2.sort(0, Qt::AscendingOrder);
+ proxy2.setDynamicSortFilter(true);
+
+ proxy2.setSourceModel(&proxy);
+ proxy2.setObjectName("proxy2");
+
+ QSignalSpy dataChangedSpy(&model, &QSortFilterProxyModel::dataChanged);
+
+ QVERIFY(dataChangedSpy.isValid());
+
+ // Verify that the no-arg signal is still emitted.
+ QSignalSpy layoutAboutToBeChangedSpy(&proxy, &QSortFilterProxyModel::layoutAboutToBeChanged);
+ QSignalSpy layoutChangedSpy(&proxy, &QSortFilterProxyModel::layoutChanged);
+
+ QVERIFY(layoutAboutToBeChangedSpy.isValid());
+ QVERIFY(layoutChangedSpy.isValid());
+
+ QSignalSpy parentsAboutToBeChangedSpy(&proxy, &QSortFilterProxyModel::layoutAboutToBeChanged);
+ QSignalSpy parentsChangedSpy(&proxy, &QSortFilterProxyModel::layoutChanged);
+
+ QVERIFY(parentsAboutToBeChangedSpy.isValid());
+ QVERIFY(parentsChangedSpy.isValid());
+
+ QSignalSpy proxy2ParentsAboutToBeChangedSpy(&proxy2, &QSortFilterProxyModel::layoutAboutToBeChanged);
+ QSignalSpy proxy2ParentsChangedSpy(&proxy2, &QSortFilterProxyModel::layoutChanged);
+
+ QVERIFY(proxy2ParentsAboutToBeChangedSpy.isValid());
+ QVERIFY(proxy2ParentsChangedSpy.isValid());
+
+ QStandardItem *item = model.invisibleRootItem()->child(1)->child(1);
+ QCOMPARE(item->text(), QStringLiteral("item 11"));
+
+ // Ensure mapped:
+ proxy.mapFromSource(model.indexFromItem(item));
+
+ item->setText("Changed");
+
+ QCOMPARE(dataChangedSpy.size(), 1);
+ QCOMPARE(layoutAboutToBeChangedSpy.size(), 1);
+ QCOMPARE(layoutChangedSpy.size(), 1);
+ QCOMPARE(parentsAboutToBeChangedSpy.size(), 1);
+ QCOMPARE(parentsChangedSpy.size(), 1);
+ QCOMPARE(proxy2ParentsAboutToBeChangedSpy.size(), 1);
+ QCOMPARE(proxy2ParentsChangedSpy.size(), 1);
+
+ QVariantList beforeSignal = parentsAboutToBeChangedSpy.first();
+ QVariantList afterSignal = parentsChangedSpy.first();
+
+ QCOMPARE(beforeSignal.size(), 2);
+ QCOMPARE(afterSignal.size(), 2);
+
+ QList<QPersistentModelIndex> beforeParents = beforeSignal.first().value<QList<QPersistentModelIndex> >();
+ QList<QPersistentModelIndex> afterParents = afterSignal.first().value<QList<QPersistentModelIndex> >();
+
+ QCOMPARE(beforeParents.size(), 1);
+ QCOMPARE(afterParents.size(), 1);
+
+ QVERIFY(beforeParents.first().isValid());
+ QVERIFY(beforeParents.first() == afterParents.first());
+
+ QVERIFY(beforeParents.first() == proxy.mapFromSource(model.indexFromItem(model.invisibleRootItem()->child(1))));
+
+ QList<QPersistentModelIndex> proxy2BeforeList = proxy2ParentsAboutToBeChangedSpy.first().first().value<QList<QPersistentModelIndex> >();
+ QList<QPersistentModelIndex> proxy2AfterList = proxy2ParentsChangedSpy.first().first().value<QList<QPersistentModelIndex> >();
+
+ QCOMPARE(proxy2BeforeList.size(), beforeParents.size());
+ QCOMPARE(proxy2AfterList.size(), afterParents.size());
+ foreach (const QPersistentModelIndex &idx, proxy2BeforeList)
+ QVERIFY(beforeParents.contains(proxy2.mapToSource(idx)));
+ foreach (const QPersistentModelIndex &idx, proxy2AfterList)
+ QVERIFY(afterParents.contains(proxy2.mapToSource(idx)));
+}
+
+class SignalArgumentChecker : public QObject
+{
+ Q_OBJECT
+public:
+ SignalArgumentChecker(QAbstractItemModel *model, QAbstractProxyModel *proxy, QObject *parent = 0)
+ : QObject(parent), m_proxy(proxy)
+ {
+ connect(model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), SLOT(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
+ connect(model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), SLOT(rowsMoved(QModelIndex,int,int,QModelIndex,int)));
+ connect(proxy, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>)), SLOT(layoutAboutToBeChanged(QList<QPersistentModelIndex>)));
+ connect(proxy, SIGNAL(layoutChanged(QList<QPersistentModelIndex>)), SLOT(layoutChanged(QList<QPersistentModelIndex>)));
+ }
+
+private slots:
+ void rowsAboutToBeMoved(const QModelIndex &source, int, int, const QModelIndex &destination, int)
+ {
+ m_p1PersistentBefore = source;
+ m_p2PersistentBefore = destination;
+ m_p2FirstProxyChild = m_proxy->index(0, 0, m_proxy->mapFromSource(destination));
+ }
+
+ void rowsMoved(const QModelIndex &source, int, int, const QModelIndex &destination, int)
+ {
+ m_p1PersistentAfter = source;
+ m_p2PersistentAfter = destination;
+ }
+
+ void layoutAboutToBeChanged(const QList<QPersistentModelIndex> &parents)
+ {
+ QVERIFY(m_p1PersistentBefore.isValid());
+ QVERIFY(m_p2PersistentBefore.isValid());
+ QCOMPARE(parents.size(), 2);
+ QVERIFY(parents.first() != parents.at(1));
+ QVERIFY(parents.contains(m_proxy->mapFromSource(m_p1PersistentBefore)));
+ QVERIFY(parents.contains(m_proxy->mapFromSource(m_p2PersistentBefore)));
+ }
+
+ void layoutChanged(const QList<QPersistentModelIndex> &parents)
+ {
+ QVERIFY(m_p1PersistentAfter.isValid());
+ QVERIFY(m_p2PersistentAfter.isValid());
+ QCOMPARE(parents.size(), 2);
+ QVERIFY(parents.first() != parents.at(1));
+ QVERIFY(parents.contains(m_proxy->mapFromSource(m_p1PersistentAfter)));
+ QVERIFY(parents.contains(m_proxy->mapFromSource(m_p2PersistentAfter)));
+
+ // In the source model, the rows were moved to row 1 in the parent.
+ // m_p2FirstProxyChild was created with row 0 in the proxy.
+ // The moved rows in the proxy do not appear at row 1 because of sorting.
+ // Sorting causes them to appear at row 0 instead, pushing what used to
+ // be row 0 in the proxy down by two rows.
+ QCOMPARE(m_p2FirstProxyChild.row(), 2);
+ }
+
+private:
+ QAbstractProxyModel *m_proxy;
+ QPersistentModelIndex m_p1PersistentBefore;
+ QPersistentModelIndex m_p2PersistentBefore;
+ QPersistentModelIndex m_p1PersistentAfter;
+ QPersistentModelIndex m_p2PersistentAfter;
+
+ QPersistentModelIndex m_p2FirstProxyChild;
+};
+
+void tst_QSortFilterProxyModel::moveSourceRows()
+{
+ DynamicTreeModel model;
+
+ {
+ ModelInsertCommand insertCommand(&model);
+ insertCommand.setStartRow(0);
+ insertCommand.setEndRow(9);
+ insertCommand.doCommand();
+ }
+ {
+ ModelInsertCommand insertCommand(&model);
+ insertCommand.setAncestorRowNumbers(QList<int>() << 2);
+ insertCommand.setStartRow(0);
+ insertCommand.setEndRow(9);
+ insertCommand.doCommand();
+ }
+ {
+ ModelInsertCommand insertCommand(&model);
+ insertCommand.setAncestorRowNumbers(QList<int>() << 5);
+ insertCommand.setStartRow(0);
+ insertCommand.setEndRow(9);
+ insertCommand.doCommand();
+ }
+
+ QSortFilterProxyModel proxy;
+ proxy.setDynamicSortFilter(true);
+ proxy.sort(0, Qt::AscendingOrder);
+
+ // We need to check the arguments at emission time
+ SignalArgumentChecker checker(&model, &proxy);
+
+ proxy.setSourceModel(&model);
+
+ QSortFilterProxyModel filterProxy;
+ filterProxy.setDynamicSortFilter(true);
+ filterProxy.sort(0, Qt::AscendingOrder);
+ filterProxy.setSourceModel(&proxy);
+ setupFilter(&filterProxy, QLatin1String("6")); // One of the parents
+
+ QSortFilterProxyModel filterBothProxy;
+ filterBothProxy.setDynamicSortFilter(true);
+ filterBothProxy.sort(0, Qt::AscendingOrder);
+ filterBothProxy.setSourceModel(&proxy);
+ setupFilter(&filterBothProxy, QLatin1String("5")); // The parents are 6 and 3. This filters both out.
+
+ QSignalSpy modelBeforeSpy(&model, &DynamicTreeModel::rowsAboutToBeMoved);
+ QSignalSpy modelAfterSpy(&model, &DynamicTreeModel::rowsMoved);
+ QSignalSpy proxyBeforeMoveSpy(m_proxy, &QSortFilterProxyModel::rowsAboutToBeMoved);
+ QSignalSpy proxyAfterMoveSpy(m_proxy, &QSortFilterProxyModel::rowsMoved);
+ QSignalSpy proxyBeforeParentLayoutSpy(&proxy, &QSortFilterProxyModel::layoutAboutToBeChanged);
+ QSignalSpy proxyAfterParentLayoutSpy(&proxy, &QSortFilterProxyModel::layoutChanged);
+ QSignalSpy filterBeforeParentLayoutSpy(&filterProxy, &QSortFilterProxyModel::layoutAboutToBeChanged);
+ QSignalSpy filterAfterParentLayoutSpy(&filterProxy, &QSortFilterProxyModel::layoutChanged);
+ QSignalSpy filterBothBeforeParentLayoutSpy(&filterBothProxy, &QSortFilterProxyModel::layoutAboutToBeChanged);
+ QSignalSpy filterBothAfterParentLayoutSpy(&filterBothProxy, &QSortFilterProxyModel::layoutChanged);
+
+ QVERIFY(modelBeforeSpy.isValid());
+ QVERIFY(modelAfterSpy.isValid());
+ QVERIFY(proxyBeforeMoveSpy.isValid());
+ QVERIFY(proxyAfterMoveSpy.isValid());
+ QVERIFY(proxyBeforeParentLayoutSpy.isValid());
+ QVERIFY(proxyAfterParentLayoutSpy.isValid());
+ QVERIFY(filterBeforeParentLayoutSpy.isValid());
+ QVERIFY(filterAfterParentLayoutSpy.isValid());
+ QVERIFY(filterBothBeforeParentLayoutSpy.isValid());
+ QVERIFY(filterBothAfterParentLayoutSpy.isValid());
+
+ {
+ ModelMoveCommand moveCommand(&model, 0);
+ moveCommand.setAncestorRowNumbers(QList<int>() << 2);
+ moveCommand.setDestAncestors(QList<int>() << 5);
+ moveCommand.setStartRow(3);
+ moveCommand.setEndRow(4);
+ moveCommand.setDestRow(1);
+ moveCommand.doCommand();
+ }
+
+ // Proxy notifies layout change
+ QCOMPARE(modelBeforeSpy.size(), 1);
+ QCOMPARE(proxyBeforeParentLayoutSpy.size(), 1);
+ QCOMPARE(modelAfterSpy.size(), 1);
+ QCOMPARE(proxyAfterParentLayoutSpy.size(), 1);
+
+ // But it doesn't notify a move.
+ QCOMPARE(proxyBeforeMoveSpy.size(), 0);
+ QCOMPARE(proxyAfterMoveSpy.size(), 0);
+
+ QCOMPARE(filterBeforeParentLayoutSpy.size(), 1);
+ QCOMPARE(filterAfterParentLayoutSpy.size(), 1);
+
+ QList<QPersistentModelIndex> filterBeforeParents = filterBeforeParentLayoutSpy.first().first().value<QList<QPersistentModelIndex> >();
+ QList<QPersistentModelIndex> filterAfterParents = filterAfterParentLayoutSpy.first().first().value<QList<QPersistentModelIndex> >();
+
+ QCOMPARE(filterBeforeParents.size(), 1);
+ QCOMPARE(filterAfterParents.size(), 1);
+
+ QCOMPARE(
+ filterBeforeParentLayoutSpy.first().at(1).value<QAbstractItemModel::LayoutChangeHint>(),
+ QAbstractItemModel::NoLayoutChangeHint);
+ QCOMPARE(filterAfterParentLayoutSpy.first().at(1).value<QAbstractItemModel::LayoutChangeHint>(),
+ QAbstractItemModel::NoLayoutChangeHint);
+
+ QCOMPARE(filterBothBeforeParentLayoutSpy.size(), 0);
+ QCOMPARE(filterBothAfterParentLayoutSpy.size(), 0);
+}
+
+class FilterProxy : public QSortFilterProxyModel
+{
+ Q_OBJECT
+public:
+ FilterProxy(QObject *parent = 0)
+ : QSortFilterProxyModel(parent),
+ mode(false)
+ {
+
+ }
+
+public slots:
+ void setMode(bool on)
+ {
+ mode = on;
+ invalidateFilter();
+ }
+
+protected:
+ virtual bool filterAcceptsRow ( int source_row, const QModelIndex & source_parent ) const
+ {
+ if (mode) {
+ if (!source_parent.isValid()) {
+ return true;
+ } else {
+ return (source_row % 2) != 0;
+ }
+ } else {
+ if (!source_parent.isValid()) {
+ return source_row >= 2 && source_row < 10;
+ } else {
+ return true;
+ }
+ }
+ }
+
+private:
+ bool mode;
+};
+
+void tst_QSortFilterProxyModel::hierarchyFilterInvalidation()
+{
+ QStandardItemModel model;
+ for (int i = 0; i < 10; ++i) {
+ const QString rowText = QLatin1String("Row ") + QString::number(i);
+ QStandardItem *child = new QStandardItem(rowText);
+ for (int j = 0; j < 1; ++j) {
+ child->appendRow(new QStandardItem(rowText + QLatin1Char('/') + QString::number(j)));
+ }
+ model.appendRow(child);
+ }
+
+ FilterProxy proxy;
+ proxy.setSourceModel(&model);
+
+ QTreeView view;
+ view.setModel(&proxy);
+
+ view.setCurrentIndex(proxy.index(2, 0).child(0, 0));
+
+ view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+
+ proxy.setMode(true);
+}
+
+class FilterProxy2 : public QSortFilterProxyModel
+{
+ Q_OBJECT
+public:
+ FilterProxy2(QObject *parent = 0)
+ : QSortFilterProxyModel(parent),
+ mode(false)
+ {
+
+ }
+
+public slots:
+ void setMode(bool on)
+ {
+ mode = on;
+ invalidateFilter();
+ }
+
+protected:
+ virtual bool filterAcceptsRow ( int source_row, const QModelIndex & source_parent ) const
+ {
+ if (source_parent.isValid()) {
+ return true;
+ } else {
+ if (0 == source_row) {
+ return true;
+ } else {
+ return !mode;
+ }
+ }
+ }
+
+private:
+ bool mode;
+};
+
+void tst_QSortFilterProxyModel::simpleFilterInvalidation()
+{
+ QStandardItemModel model;
+ for (int i = 0; i < 2; ++i) {
+ QStandardItem *child = new QStandardItem(QLatin1String("Row ") + QString::number(i));
+ child->appendRow(new QStandardItem("child"));
+ model.appendRow(child);
+ }
+
+ FilterProxy2 proxy;
+ proxy.setSourceModel(&model);
+
+ QTreeView view;
+ view.setModel(&proxy);
+
+ view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+
+ proxy.setMode(true);
+ model.insertRow(0, new QStandardItem("extra"));
+}
+
+class CustomRoleNameModel : public QAbstractListModel
+{
+ Q_OBJECT
+public:
+ CustomRoleNameModel(QObject *parent = 0) : QAbstractListModel(parent) {}
+
+ QVariant data(const QModelIndex &index, int role) const
+ {
+ Q_UNUSED(index);
+ Q_UNUSED(role);
+ return QVariant();
+ }
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const
+ {
+ Q_UNUSED(parent);
+ return 0;
+ }
+
+ QHash<int, QByteArray> roleNames() const
+ {
+ QHash<int, QByteArray> rn = QAbstractListModel::roleNames();
+ rn[Qt::UserRole + 1] = "custom";
+ return rn;
+ }
+};
+
+void tst_QSortFilterProxyModel::chainedProxyModelRoleNames()
+{
+ QSortFilterProxyModel proxy1;
+ QSortFilterProxyModel proxy2;
+ CustomRoleNameModel customModel;
+
+ proxy2.setSourceModel(&proxy1);
+
+ // changing the sourceModel of proxy1 must also update roleNames of proxy2
+ proxy1.setSourceModel(&customModel);
+ QVERIFY(proxy2.roleNames().value(Qt::UserRole + 1) == "custom");
+}
+
+// A source model with ABABAB rows, where only A rows accept drops.
+// It will then be sorted by a QSFPM.
+class DropOnOddRows : public QAbstractListModel
+{
+ Q_OBJECT
+public:
+ DropOnOddRows(QObject *parent = 0) : QAbstractListModel(parent) {}
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
+ {
+ if (role == Qt::DisplayRole)
+ return (index.row() % 2 == 0) ? "A" : "B";
+ return QVariant();
+ }
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override
+ {
+ Q_UNUSED(parent);
+ return 10;
+ }
+
+ bool canDropMimeData(const QMimeData *, Qt::DropAction,
+ int row, int column, const QModelIndex &parent) const override
+ {
+ Q_UNUSED(row);
+ Q_UNUSED(column);
+ return parent.row() % 2 == 0;
+ }
+};
+
+class SourceAssertion : public QSortFilterProxyModel
+{
+ Q_OBJECT
+public:
+ explicit SourceAssertion(QObject *parent = 0)
+ : QSortFilterProxyModel(parent)
+ {
+
+ }
+
+ QModelIndex mapToSource(const QModelIndex &proxyIndex) const override
+ {
+ Q_ASSERT(sourceModel());
+ return QSortFilterProxyModel::mapToSource(proxyIndex);
+ }
+};
+
+void tst_QSortFilterProxyModel::noMapAfterSourceDelete()
+{
+ SourceAssertion proxy;
+ QStringListModel *model = new QStringListModel(QStringList() << "Foo" << "Bar");
+
+ proxy.setSourceModel(model);
+
+ // Create mappings
+ QPersistentModelIndex persistent = proxy.index(0, 0);
+
+ QVERIFY(persistent.isValid());
+
+ delete model;
+
+ QVERIFY(!persistent.isValid());
+}
+
+// QTBUG-39549, test whether canDropMimeData(), dropMimeData() are proxied as well
+// by invoking them on a QSortFilterProxyModel proxying a QStandardItemModel that allows drops
+// on row #1, filtering for that row.
+class DropTestModel : public QStandardItemModel {
+public:
+ explicit DropTestModel(QObject *parent = 0) : QStandardItemModel(0, 1, parent)
+ {
+ appendRow(new QStandardItem(QStringLiteral("Row0")));
+ appendRow(new QStandardItem(QStringLiteral("Row1")));
+ }
+
+ bool canDropMimeData(const QMimeData *, Qt::DropAction,
+ int row, int /* column */, const QModelIndex & /* parent */) const override
+ { return row == 1; }
+
+ bool dropMimeData(const QMimeData *, Qt::DropAction,
+ int row, int /* column */, const QModelIndex & /* parent */) override
+ { return row == 1; }
+};
+
+void tst_QSortFilterProxyModel::forwardDropApi()
+{
+ QSortFilterProxyModel model;
+ model.setSourceModel(new DropTestModel(&model));
+ model.setFilterFixedString(QStringLiteral("Row1"));
+ QCOMPARE(model.rowCount(), 1);
+ QVERIFY(model.canDropMimeData(0, Qt::CopyAction, 0, 0, QModelIndex()));
+ QVERIFY(model.dropMimeData(0, Qt::CopyAction, 0, 0, QModelIndex()));
+}
+
+static QString rowTexts(QAbstractItemModel *model) {
+ QString str;
+ for (int row = 0 ; row < model->rowCount(); ++row)
+ str += model->index(row, 0).data().toString();
+ return str;
+}
+
+void tst_QSortFilterProxyModel::canDropMimeData()
+{
+ // Given a source model which only supports dropping on even rows
+ DropOnOddRows sourceModel;
+ QCOMPARE(rowTexts(&sourceModel), QString("ABABABABAB"));
+
+ // and a proxy model that sorts the rows
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&sourceModel);
+ proxy.sort(0, Qt::AscendingOrder);
+ QCOMPARE(rowTexts(&proxy), QString("AAAAABBBBB"));
+
+ // the proxy should correctly map canDropMimeData to the source model,
+ // i.e. accept drops on the first 5 rows and refuse drops on the next 5.
+ for (int row = 0; row < proxy.rowCount(); ++row)
+ QCOMPARE(proxy.canDropMimeData(0, Qt::CopyAction, -1, -1, proxy.index(row, 0)), row < 5);
+}
+
+void tst_QSortFilterProxyModel::resortingDoesNotBreakTreeModels()
+{
+ QStandardItemModel *treeModel = new QStandardItemModel(this);
+ QStandardItem *e1 = new QStandardItem("Loading...");
+ e1->appendRow(new QStandardItem("entry10"));
+ treeModel->appendRow(e1);
+ QStandardItem *e0 = new QStandardItem("Loading...");
+ e0->appendRow(new QStandardItem("entry00"));
+ e0->appendRow(new QStandardItem("entry01"));
+ treeModel->appendRow(e0);
+
+ QSortFilterProxyModel proxy;
+ proxy.setDynamicSortFilter(true);
+ proxy.sort(0);
+ proxy.setSourceModel(treeModel);
+
+ QAbstractItemModelTester modelTester(&proxy);
+
+ QCOMPARE(proxy.rowCount(), 2);
+ e1->setText("entry1");
+ e0->setText("entry0");
+
+ QModelIndex pi0 = proxy.index(0, 0);
+ QCOMPARE(pi0.data().toString(), QString("entry0"));
+ QCOMPARE(proxy.rowCount(pi0), 2);
+
+ QModelIndex pi01 = proxy.index(1, 0, pi0);
+ QCOMPARE(pi01.data().toString(), QString("entry01"));
+
+ QModelIndex pi1 = proxy.index(1, 0);
+ QCOMPARE(pi1.data().toString(), QString("entry1"));
+ QCOMPARE(proxy.rowCount(pi1), 1);
+}
+
+void tst_QSortFilterProxyModel::filterHint()
+{
+ // test that a filtering model does not emit layoutChanged with a hint
+ QStringListModel model(QStringList() << "one"
+ << "two"
+ << "three"
+ << "four"
+ << "five"
+ << "six");
+ QSortFilterProxyModel proxy1;
+ proxy1.setSourceModel(&model);
+ proxy1.setSortRole(Qt::DisplayRole);
+ proxy1.setDynamicSortFilter(true);
+ proxy1.sort(0);
+
+ QSortFilterProxyModel proxy2;
+ proxy2.setSourceModel(&proxy1);
+ proxy2.setFilterRole(Qt::DisplayRole);
+ setupFilter(&proxy2, QLatin1String("^[^ ]*$"));
+ proxy2.setDynamicSortFilter(true);
+
+ QSignalSpy proxy1BeforeSpy(&proxy1, &QSortFilterProxyModel::layoutAboutToBeChanged);
+ QSignalSpy proxy1AfterSpy(&proxy1, &QSortFilterProxyModel::layoutChanged);
+ QSignalSpy proxy2BeforeSpy(&proxy2, &QSortFilterProxyModel::layoutAboutToBeChanged);
+ QSignalSpy proxy2AfterSpy(&proxy2, &QSortFilterProxyModel::layoutChanged);
+
+ model.setData(model.index(2), QStringLiteral("modified three"), Qt::DisplayRole);
+
+ // The first proxy was re-sorted as one item as changed.
+ QCOMPARE(proxy1BeforeSpy.size(), 1);
+ QCOMPARE(proxy1BeforeSpy.first().at(1).value<QAbstractItemModel::LayoutChangeHint>(),
+ QAbstractItemModel::VerticalSortHint);
+ QCOMPARE(proxy1AfterSpy.size(), 1);
+ QCOMPARE(proxy1AfterSpy.first().at(1).value<QAbstractItemModel::LayoutChangeHint>(),
+ QAbstractItemModel::VerticalSortHint);
+
+ // But the second proxy must not have the VerticalSortHint since an item was filtered
+ QCOMPARE(proxy2BeforeSpy.size(), 1);
+ QCOMPARE(proxy2BeforeSpy.first().at(1).value<QAbstractItemModel::LayoutChangeHint>(),
+ QAbstractItemModel::NoLayoutChangeHint);
+ QCOMPARE(proxy2AfterSpy.size(), 1);
+ QCOMPARE(proxy2AfterSpy.first().at(1).value<QAbstractItemModel::LayoutChangeHint>(),
+ QAbstractItemModel::NoLayoutChangeHint);
+}
+
+/**
+
+ Creates a model where each item has one child, to a set depth,
+ and the last item has no children. For a model created with
+ setDepth(4):
+
+ - 1
+ - - 2
+ - - - 3
+ - - - - 4
+*/
+class StepTreeModel : public QAbstractItemModel
+{
+ Q_OBJECT
+public:
+ StepTreeModel(QObject * parent = 0)
+ : QAbstractItemModel(parent), m_depth(0) {}
+
+ int columnCount(const QModelIndex& = QModelIndex()) const override { return 1; }
+
+ int rowCount(const QModelIndex& parent = QModelIndex()) const override
+ {
+ quintptr parentId = (parent.isValid()) ? parent.internalId() : 0;
+ return (parentId < m_depth) ? 1 : 0;
+ }
+
+ QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override
+ {
+ if (role != Qt::DisplayRole)
+ return QVariant();
+
+ return QString::number(index.internalId());
+ }
+
+ QModelIndex index(int, int, const QModelIndex& parent = QModelIndex()) const override
+ {
+ // QTBUG-44962: Would we always expect the parent to belong to the model
+ qDebug() << parent.model() << this;
+ Q_ASSERT(!parent.isValid() || parent.model() == this);
+
+ quintptr parentId = (parent.isValid()) ? parent.internalId() : 0;
+ if (parentId >= m_depth)
+ return QModelIndex();
+
+ return createIndex(0, 0, parentId + 1);
+ }
+
+ QModelIndex parent(const QModelIndex& index) const override
+ {
+ if (index.internalId() == 0)
+ return QModelIndex();
+
+ return createIndex(0, 0, index.internalId() - 1);
+ }
+
+ void setDepth(quintptr depth)
+ {
+ int parentIdWithLayoutChange = (m_depth < depth) ? m_depth : depth;
+
+ QList<QPersistentModelIndex> parentsOfLayoutChange;
+ parentsOfLayoutChange.push_back(createIndex(0, 0, parentIdWithLayoutChange));
+
+ layoutAboutToBeChanged(parentsOfLayoutChange);
+
+ auto existing = persistentIndexList();
+
+ QList<QModelIndex> updated;
+
+ for (auto idx : existing) {
+ if (indexDepth(idx) <= depth)
+ updated.push_back(idx);
+ else
+ updated.push_back({});
+ }
+
+ m_depth = depth;
+
+ changePersistentIndexList(existing, updated);
+
+ layoutChanged(parentsOfLayoutChange);
+ }
+
+private:
+ static quintptr indexDepth(QModelIndex const& index)
+ {
+ return (index.isValid()) ? 1 + indexDepth(index.parent()) : 0;
+ }
+
+private:
+ quintptr m_depth;
+};
+
+void tst_QSortFilterProxyModel::sourceLayoutChangeLeavesValidPersistentIndexes()
+{
+ StepTreeModel model;
+ Q_SET_OBJECT_NAME(model);
+ model.setDepth(4);
+
+ QSortFilterProxyModel proxy1;
+ proxy1.setSourceModel(&model);
+ Q_SET_OBJECT_NAME(proxy1);
+ setupFilter(&proxy1, QLatin1String("1|2"));
+
+ // The current state of things:
+ // model proxy
+ // - 1 - 1
+ // - - 2 - - 2
+ // - - - 3
+ // - - - - 4
+
+ // The setDepth call below removes '4' with a layoutChanged call.
+ // Because the proxy filters that out anyway, the proxy doesn't need
+ // to emit any signals or update persistent indexes.
+
+ QPersistentModelIndex persistentIndex = proxy1.index(0, 0, proxy1.index(0, 0));
+
+ model.setDepth(3);
+
+ // Calling parent() causes the internalPointer to be used.
+ // Before fixing QTBUG-47711, that could be a dangling pointer.
+ // The use of qDebug here makes sufficient use of the heap to
+ // cause corruption at runtime with normal use on linux (before
+ // the fix). valgrind confirms the fix.
+ qDebug() << persistentIndex.parent();
+ QVERIFY(persistentIndex.parent().isValid());
+}
+
+void tst_QSortFilterProxyModel::rowMoveLeavesValidPersistentIndexes()
+{
+ DynamicTreeModel model;
+ Q_SET_OBJECT_NAME(model);
+
+ QList<int> ancestors;
+ for (auto i = 0; i < 5; ++i)
+ {
+ Q_UNUSED(i);
+ ModelInsertCommand insertCommand(&model);
+ insertCommand.setAncestorRowNumbers(ancestors);
+ insertCommand.setStartRow(0);
+ insertCommand.setEndRow(0);
+ insertCommand.doCommand();
+ ancestors.push_back(0);
+ }
+
+ QSortFilterProxyModel proxy1;
+ proxy1.setSourceModel(&model);
+ Q_SET_OBJECT_NAME(proxy1);
+
+ setupFilter(&proxy1, QLatin1String("1|2"));
+
+ auto item5 = model.match(model.index(0, 0), Qt::DisplayRole, "5", 1, Qt::MatchRecursive).first();
+ auto item3 = model.match(model.index(0, 0), Qt::DisplayRole, "3", 1, Qt::MatchRecursive).first();
+
+ Q_ASSERT(item5.isValid());
+ Q_ASSERT(item3.isValid());
+
+ QPersistentModelIndex persistentIndex = proxy1.match(proxy1.index(0, 0), Qt::DisplayRole, "2", 1, Qt::MatchRecursive).first();
+
+ ModelMoveCommand moveCommand(&model, 0);
+ moveCommand.setAncestorRowNumbers(QList<int>{0, 0, 0, 0});
+ moveCommand.setStartRow(0);
+ moveCommand.setEndRow(0);
+ moveCommand.setDestRow(0);
+ moveCommand.setDestAncestors(QList<int>{0, 0, 0});
+ moveCommand.doCommand();
+
+ // Calling parent() causes the internalPointer to be used.
+ // Before fixing QTBUG-47711 (moveRows case), that could be
+ // a dangling pointer.
+ QVERIFY(persistentIndex.parent().isValid());
+}
+
+void tst_QSortFilterProxyModel::emitLayoutChangedOnlyIfSortingChanged_data()
+{
+ QTest::addColumn<int>("changedRow");
+ QTest::addColumn<Qt::ItemDataRole>("changedRole");
+ QTest::addColumn<QString>("newData");
+ QTest::addColumn<QString>("expectedSourceRowTexts");
+ QTest::addColumn<QString>("expectedProxyRowTexts");
+ QTest::addColumn<int>("expectedLayoutChanged");
+
+ // Starting point:
+ // a source model with 8,7,6,5,4,3,2,1
+ // a proxy model keeping only even rows and sorting them, therefore showing 2,4,6,8
+
+ // When setData changes ordering, layoutChanged should be emitted
+ QTest::newRow("ordering_change") << 0 << Qt::DisplayRole << "0" << "07654321" << "0246" << 1;
+
+ // When setData on visible row doesn't change ordering, layoutChanged should not be emitted
+ QTest::newRow("no_ordering_change") << 6 << Qt::DisplayRole << "0" << "87654301" << "0468" << 0;
+
+ // When setData happens on a filtered out row, layoutChanged should not be emitted
+ QTest::newRow("filtered_out") << 1 << Qt::DisplayRole << "9" << "89654321" << "2468" << 0;
+
+ // When setData makes a row visible, layoutChanged should not be emitted (rowsInserted is emitted instead)
+ QTest::newRow("make_row_visible") << 7 << Qt::DisplayRole << "0" << "87654320" << "02468" << 0;
+
+ // When setData makes a row hidden, layoutChanged should not be emitted (rowsRemoved is emitted instead)
+ QTest::newRow("make_row_hidden") << 4 << Qt::DisplayRole << "1" << "87651321" << "268" << 0;
+
+ // When setData happens on an unrelated role, layoutChanged should not be emitted
+ QTest::newRow("unrelated_role") << 0 << Qt::DecorationRole << "" << "87654321" << "2468" << 0;
+
+ // When many changes happen together... and trigger removal, insertion, and layoutChanged
+ QTest::newRow("many_changes") << -1 << Qt::DisplayRole << "3,4,2,5,6,0,7,9" << "34256079" << "0246" << 1;
+
+ // When many changes happen together... and trigger removal, insertion, but no change in ordering of visible rows => no layoutChanged
+ QTest::newRow("many_changes_no_layoutChanged") << -1 << Qt::DisplayRole << "7,5,4,3,2,1,0,8" << "75432108" << "0248" << 0;
+}
+
+// Custom version of QStringListModel which supports emitting dataChanged for many rows at once
+class CustomStringListModel : public QAbstractListModel
+{
+public:
+ bool setData(const QModelIndex &index, const QVariant &value, int role) override
+ {
+ if (index.row() >= 0 && index.row() < lst.size()
+ && (role == Qt::EditRole || role == Qt::DisplayRole)) {
+ lst.replace(index.row(), value.toString());
+ emit dataChanged(index, index, { Qt::DisplayRole, Qt::EditRole });
+ return true;
+ }
+ return false;
+ }
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
+ {
+ if (role == Qt::DisplayRole || role == Qt::EditRole)
+ return lst.at(index.row());
+ return QVariant();
+ }
+ int rowCount(const QModelIndex & = QModelIndex()) const override { return lst.count(); }
+
+ void replaceData(const QStringList &newData)
+ {
+ lst = newData;
+ emit dataChanged(index(0, 0), index(rowCount() - 1, 0), { Qt::DisplayRole, Qt::EditRole });
+ }
+
+ void emitDecorationChangedSignal()
+ {
+ const QModelIndex idx = index(0, 0);
+ emit dataChanged(idx, idx, { Qt::DecorationRole });
+ }
+
+private:
+ QStringList lst;
+};
+
+void tst_QSortFilterProxyModel::emitLayoutChangedOnlyIfSortingChanged()
+{
+ QFETCH(int, changedRow);
+ QFETCH(QString, newData);
+ QFETCH(Qt::ItemDataRole, changedRole);
+ QFETCH(QString, expectedSourceRowTexts);
+ QFETCH(QString, expectedProxyRowTexts);
+ QFETCH(int, expectedLayoutChanged);
+
+ CustomStringListModel model;
+ QStringList strings;
+ for (auto i = 8; i >= 1; --i)
+ strings.append(QString::number(i));
+ model.replaceData(strings);
+ QCOMPARE(rowTexts(&model), QStringLiteral("87654321"));
+
+ class FilterEvenRowsProxyModel : public QSortFilterProxyModel
+ {
+ public:
+ bool filterAcceptsRow(int srcRow, const QModelIndex& srcParent) const override
+ {
+ return sourceModel()->index(srcRow, 0, srcParent).data().toInt() % 2 == 0;
+ }
+ };
+
+ FilterEvenRowsProxyModel proxy;
+ proxy.sort(0);
+ proxy.setSourceModel(&model);
+ QCOMPARE(rowTexts(&proxy), QStringLiteral("2468"));
+
+ QSignalSpy modelDataChangedSpy(&model, &QAbstractItemModel::dataChanged);
+ QSignalSpy proxyLayoutChangedSpy(&proxy, &QAbstractItemModel::layoutChanged);
+
+ if (changedRole == Qt::DecorationRole)
+ model.emitDecorationChangedSignal();
+ else if (changedRow == -1)
+ model.replaceData(newData.split(QLatin1Char(',')));
+ else
+ model.setData(model.index(changedRow, 0), newData, changedRole);
+
+ QCOMPARE(rowTexts(&model), expectedSourceRowTexts);
+ QCOMPARE(rowTexts(&proxy), expectedProxyRowTexts);
+ QCOMPARE(modelDataChangedSpy.size(), 1);
+ QCOMPARE(proxyLayoutChangedSpy.size(), expectedLayoutChanged);
+}
+
+void tst_QSortFilterProxyModel::removeIntervals_data()
+{
+ QTest::addColumn<QStringList>("sourceItems");
+ QTest::addColumn<int>("sortOrder");
+ QTest::addColumn<QString>("filter");
+ QTest::addColumn<QStringList>("replacementSourceItems");
+ QTest::addColumn<IntPairList>("expectedRemovedProxyIntervals");
+ QTest::addColumn<QStringList>("expectedProxyItems");
+
+ QTest::newRow("filter all, sort ascending")
+ << (QStringList() << "a"
+ << "b"
+ << "c") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "[^x]" // filter
+ << (QStringList() << "x"
+ << "x"
+ << "x") // replacementSourceItems
+ << (IntPairList() << IntPair(0, 2)) // expectedRemovedIntervals
+ << QStringList() // expectedProxyItems
+ ;
+
+ QTest::newRow("filter all, sort descending")
+ << (QStringList() << "a"
+ << "b"
+ << "c") // sourceItems
+ << static_cast<int>(Qt::DescendingOrder) // sortOrder
+ << "[^x]" // filter
+ << (QStringList() << "x"
+ << "x"
+ << "x") // replacementSourceItems
+ << (IntPairList() << IntPair(0, 2)) // expectedRemovedIntervals
+ << QStringList() // expectedProxyItems
+ ;
+
+ QTest::newRow("filter first and last, sort ascending")
+ << (QStringList() << "a"
+ << "b"
+ << "c") // sourceItems
+ << static_cast<int>(Qt::AscendingOrder) // sortOrder
+ << "[^x]" // filter
+ << (QStringList() << "x"
+ << "b"
+ << "x") // replacementSourceItems
+ << (IntPairList() << IntPair(2, 2) << IntPair(0, 0)) // expectedRemovedIntervals
+ << (QStringList() << "b") // expectedProxyItems
+ ;
+
+ QTest::newRow("filter first and last, sort descending")
+ << (QStringList() << "a"
+ << "b"
+ << "c") // sourceItems
+ << static_cast<int>(Qt::DescendingOrder) // sortOrder
+ << "[^x]" // filter
+ << (QStringList() << "x"
+ << "b"
+ << "x") // replacementSourceItems
+ << (IntPairList() << IntPair(2, 2) << IntPair(0, 0)) // expectedRemovedIntervals
+ << (QStringList() << "b") // expectedProxyItems
+ ;
+}
+
+void tst_QSortFilterProxyModel::removeIntervals()
+{
+ QFETCH(QStringList, sourceItems);
+ QFETCH(int, sortOrder);
+ QFETCH(QString, filter);
+ QFETCH(QStringList, replacementSourceItems);
+ QFETCH(IntPairList, expectedRemovedProxyIntervals);
+ QFETCH(QStringList, expectedProxyItems);
+
+ CustomStringListModel model;
+ QSortFilterProxyModel proxy;
+
+ model.replaceData(sourceItems);
+ proxy.setSourceModel(&model);
+
+ for (int i = 0; i < sourceItems.count(); ++i) {
+ QModelIndex sindex = model.index(i, 0, QModelIndex());
+ QModelIndex pindex = proxy.index(i, 0, QModelIndex());
+ QCOMPARE(proxy.data(pindex, Qt::DisplayRole), model.data(sindex, Qt::DisplayRole));
+ }
+
+ proxy.setDynamicSortFilter(true);
+
+ if (sortOrder != -1)
+ proxy.sort(0, static_cast<Qt::SortOrder>(sortOrder));
+ if (!filter.isEmpty())
+ setupFilter(&proxy, filter);
+
+ (void)proxy.rowCount(QModelIndex()); // force mapping
+
+ QSignalSpy removeSpy(&proxy, &QSortFilterProxyModel::rowsRemoved);
+ QSignalSpy insertSpy(&proxy, &QSortFilterProxyModel::rowsInserted);
+ QSignalSpy aboutToRemoveSpy(&proxy, &QSortFilterProxyModel::rowsAboutToBeRemoved);
+ QSignalSpy aboutToInsertSpy(&proxy, &QSortFilterProxyModel::rowsAboutToBeInserted);
+
+ QVERIFY(removeSpy.isValid());
+ QVERIFY(insertSpy.isValid());
+ QVERIFY(aboutToRemoveSpy.isValid());
+ QVERIFY(aboutToInsertSpy.isValid());
+
+ model.replaceData(replacementSourceItems);
+
+ QCOMPARE(aboutToRemoveSpy.count(), expectedRemovedProxyIntervals.count());
+ for (int i = 0; i < aboutToRemoveSpy.count(); ++i) {
+ QList<QVariant> args = aboutToRemoveSpy.at(i);
+ QCOMPARE(args.at(1).type(), QVariant::Int);
+ QCOMPARE(args.at(2).type(), QVariant::Int);
+ QCOMPARE(args.at(1).toInt(), expectedRemovedProxyIntervals.at(i).first);
+ QCOMPARE(args.at(2).toInt(), expectedRemovedProxyIntervals.at(i).second);
+ }
+ QCOMPARE(removeSpy.count(), expectedRemovedProxyIntervals.count());
+ for (int i = 0; i < removeSpy.count(); ++i) {
+ QList<QVariant> args = removeSpy.at(i);
+ QCOMPARE(args.at(1).type(), QVariant::Int);
+ QCOMPARE(args.at(2).type(), QVariant::Int);
+ QCOMPARE(args.at(1).toInt(), expectedRemovedProxyIntervals.at(i).first);
+ QCOMPARE(args.at(2).toInt(), expectedRemovedProxyIntervals.at(i).second);
+ }
+
+ QCOMPARE(insertSpy.count(), 0);
+ QCOMPARE(aboutToInsertSpy.count(), 0);
+
+ QCOMPARE(proxy.rowCount(QModelIndex()), expectedProxyItems.count());
+ for (int i = 0; i < expectedProxyItems.count(); ++i) {
+ QModelIndex pindex = proxy.index(i, 0, QModelIndex());
+ QCOMPARE(proxy.data(pindex, Qt::DisplayRole).toString(), expectedProxyItems.at(i));
+ }
+}
+
+void tst_QSortFilterProxyModel::dynamicFilterWithoutSort()
+{
+ QStringListModel model;
+ const QStringList initial = QString("bravo charlie delta echo").split(QLatin1Char(' '));
+ model.setStringList(initial);
+ QSortFilterProxyModel proxy;
+ proxy.setDynamicSortFilter(true);
+ proxy.setSourceModel(&model);
+
+ QSignalSpy layoutChangeSpy(&proxy, &QAbstractItemModel::layoutChanged);
+ QSignalSpy resetSpy(&proxy, &QAbstractItemModel::modelReset);
+
+ QVERIFY(layoutChangeSpy.isValid());
+ QVERIFY(resetSpy.isValid());
+
+ model.setStringList(QStringList() << "Monday" << "Tuesday" << "Wednesday" << "Thursday" << "Friday");
+
+ QVERIFY(layoutChangeSpy.isEmpty());
+
+ QCOMPARE(model.stringList(), QStringList() << "Monday" << "Tuesday" << "Wednesday" << "Thursday" << "Friday");
+
+ QCOMPARE(resetSpy.count(), 1);
+}
+
+void tst_QSortFilterProxyModel::checkSetNewModel()
+{
+ QTreeView tv;
+ StepTreeModel model1;
+ model1.setDepth(4);
+
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model1);
+ tv.setModel(&proxy);
+ tv.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&tv));
+ tv.expandAll();
+ {
+ StepTreeModel model2;
+ model2.setDepth(4);
+ proxy.setSourceModel(&model2);
+ tv.expandAll();
+ proxy.setSourceModel(&model1);
+ tv.expandAll();
+ // the destruction of model2 here caused a proxy model reset due to
+ // missing disconnect in setSourceModel()
+ }
+ // handle repaint events, will assert when qsortfilterproxymodel is in wrong state
+ QCoreApplication::processEvents();
+}
+
+enum ColumnFilterMode {
+ FilterNothing,
+ FilterOutMiddle,
+ FilterOutBeginEnd,
+ FilterAll
+};
+Q_DECLARE_METATYPE(ColumnFilterMode)
+
+void tst_QSortFilterProxyModel::filterAndInsertColumn_data()
+{
+
+ QTest::addColumn<int>("insertCol");
+ QTest::addColumn<ColumnFilterMode>("filterMode");
+ QTest::addColumn<QStringList>("expectedModelList");
+ QTest::addColumn<QStringList>("expectedProxyModelList");
+
+ QTest::newRow("at_beginning_filter_out_middle")
+ << 0
+ << FilterOutMiddle
+ << QStringList{{"", "A1", "B1", "C1", "D1"}}
+ << QStringList{{"", "D1"}}
+ ;
+ QTest::newRow("at_end_filter_out_middle")
+ << 2
+ << FilterOutMiddle
+ << QStringList{{"A1", "B1", "C1", "D1", ""}}
+ << QStringList{{"A1", ""}}
+ ;
+ QTest::newRow("in_the_middle_filter_out_middle")
+ << 1
+ << FilterOutMiddle
+ << QStringList{{"A1", "B1", "C1", "", "D1"}}
+ << QStringList{{"A1", "D1"}}
+ ;
+ QTest::newRow("at_beginning_filter_out_begin_and_end")
+ << 0
+ << FilterOutBeginEnd
+ << QStringList{{"A1", "", "B1", "C1", "D1"}}
+ << QStringList{{"", "B1", "C1"}}
+ ;
+ QTest::newRow("at_end_filter_out_begin_and_end")
+ << 2
+ << FilterOutBeginEnd
+ << QStringList{{"A1", "B1", "C1", "D1", ""}}
+ << QStringList{{"B1", "C1", "D1"}}
+ ;
+ QTest::newRow("in_the_middle_filter_out_begin_and_end")
+ << 1
+ << FilterOutBeginEnd
+ << QStringList{{"A1", "B1", "", "C1", "D1"}}
+ << QStringList{{"B1", "", "C1"}}
+ ;
+
+ QTest::newRow("at_beginning_filter_nothing")
+ << 0
+ << FilterAll
+ << QStringList{{"", "A1", "B1", "C1", "D1"}}
+ << QStringList{{"", "A1", "B1", "C1", "D1"}}
+ ;
+ QTest::newRow("at_end_filter_nothing")
+ << 4
+ << FilterAll
+ << QStringList{{"A1", "B1", "C1", "D1", ""}}
+ << QStringList{{"A1", "B1", "C1", "D1", ""}}
+ ;
+ QTest::newRow("in_the_middle_nothing")
+ << 2
+ << FilterAll
+ << QStringList{{"A1", "B1", "", "C1", "D1"}}
+ << QStringList{{"A1", "B1", "", "C1", "D1"}}
+ ;
+
+ QTest::newRow("filter_all")
+ << 0
+ << FilterNothing
+ << QStringList{{"A1", "B1", "C1", "D1", ""}}
+ << QStringList{}
+ ;
+}
+void tst_QSortFilterProxyModel::filterAndInsertColumn()
+{
+
+ class ColumnFilterProxy : public QSortFilterProxyModel {
+ Q_DISABLE_COPY(ColumnFilterProxy)
+ ColumnFilterMode filerMode;
+ public:
+ ColumnFilterProxy(ColumnFilterMode mode)
+ : filerMode(mode)
+ {}
+ bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const override
+ {
+ Q_UNUSED(source_parent)
+ switch (filerMode){
+ case FilterAll:
+ return true;
+ case FilterNothing:
+ return false;
+ case FilterOutMiddle:
+ return source_column == 0 || source_column == sourceModel()->columnCount() - 1;
+ case FilterOutBeginEnd:
+ return source_column > 0 && source_column< sourceModel()->columnCount() - 1;
+ }
+ Q_UNREACHABLE();
+ }
+ };
+ QFETCH(int, insertCol);
+ QFETCH(ColumnFilterMode, filterMode);
+ QFETCH(QStringList, expectedModelList);
+ QFETCH(QStringList, expectedProxyModelList);
+ QStandardItemModel model;
+ model.insertColumns(0, 4);
+ model.insertRows(0, 1);
+ for (int i = 0; i < model.rowCount(); ++i) {
+ for (int j = 0; j < model.columnCount(); ++j)
+ model.setData(model.index(i, j), QString('A' + j) + QString::number(i + 1));
+ }
+ ColumnFilterProxy proxy(filterMode);
+ proxy.setSourceModel(&model);
+ QVERIFY(proxy.insertColumn(insertCol));
+ proxy.invalidate();
+ QStringList modelStringList;
+ for (int i = 0; i < model.rowCount(); ++i) {
+ for (int j = 0; j < model.columnCount(); ++j)
+ modelStringList.append(model.index(i, j).data().toString());
+ }
+ QCOMPARE(expectedModelList, modelStringList);
+ modelStringList.clear();
+ for (int i = 0; i < proxy.rowCount(); ++i) {
+ for (int j = 0; j < proxy.columnCount(); ++j)
+ modelStringList.append(proxy.index(i, j).data().toString());
+ }
+ QCOMPARE(expectedProxyModelList, modelStringList);
+}
+
+void tst_QSortFilterProxyModel::filterAndInsertRow_data()
+{
+ QTest::addColumn<QStringList>("initialModelList");
+ QTest::addColumn<int>("row");
+ QTest::addColumn<QString>("filterRegExp");
+ QTest::addColumn<QStringList>("expectedModelList");
+ QTest::addColumn<QStringList>("expectedProxyModelList");
+
+ QTest::newRow("at_beginning_filter_out_middle")
+ << QStringList{{"A5", "B5", "B6", "A7"}}
+ << 0
+ << "^A"
+ << QStringList{{"", "A5", "B5", "B6", "A7"}}
+ << QStringList{{"A5", "A7"}};
+ QTest::newRow("at_end_filter_out_middle")
+ << QStringList{{"A5", "B5", "B6", "A7"}}
+ << 2
+ << "^A"
+ << QStringList{{"A5", "B5", "B6", "A7", ""}}
+ << QStringList{{"A5", "A7"}};
+ QTest::newRow("in_the_middle_filter_out_middle")
+ << QStringList{{"A5", "B5", "B6", "A7"}}
+ << 1
+ << "^A"
+ << QStringList{{"A5", "B5", "B6", "", "A7"}}
+ << QStringList{{"A5", "A7"}};
+
+ QTest::newRow("at_beginning_filter_out_first_and_last")
+ << QStringList{{"A5", "B5", "B6", "A7"}}
+ << 0
+ << "^B"
+ << QStringList{{"A5", "", "B5", "B6", "A7"}}
+ << QStringList{{"B5", "B6"}};
+ QTest::newRow("at_end_filter_out_first_and_last")
+ << QStringList{{"A5", "B5", "B6", "A7"}}
+ << 2
+ << "^B"
+ << QStringList{{"A5", "B5", "B6", "A7", ""}}
+ << QStringList{{"B5", "B6"}};
+ QTest::newRow("in_the_middle_filter_out_first_and_last")
+ << QStringList{{"A5", "B5", "B6", "A7"}}
+ << 1
+ << "^B"
+ << QStringList{{"A5", "B5", "", "B6", "A7"}}
+ << QStringList{{"B5", "B6"}};
+
+ QTest::newRow("at_beginning_no_filter")
+ << QStringList{{"A5", "B5", "B6", "A7"}}
+ << 0
+ << ".*"
+ << QStringList{{"", "A5", "B5", "B6", "A7"}}
+ << QStringList{{"", "A5", "B5", "B6", "A7"}};
+ QTest::newRow("at_end_no_filter")
+ << QStringList{{"A5", "B5", "B6", "A7"}}
+ << 4
+ << ".*"
+ << QStringList{{"A5", "B5", "B6", "A7", ""}}
+ << QStringList{{"A5", "B5", "B6", "A7", ""}};
+ QTest::newRow("in_the_middle_no_filter")
+ << QStringList{{"A5", "B5", "B6", "A7"}}
+ << 2
+ << ".*"
+ << QStringList{{"A5", "B5", "", "B6", "A7"}}
+ << QStringList{{"A5", "B5", "", "B6", "A7"}};
+
+ QTest::newRow("filter_all")
+ << QStringList{{"A5", "B5", "B6", "A7"}}
+ << 0
+ << "$a"
+ << QStringList{{"A5", "B5", "B6", "A7", ""}}
+ << QStringList{};
+}
+
+void tst_QSortFilterProxyModel::filterAndInsertRow()
+{
+ QFETCH(QStringList, initialModelList);
+ QFETCH(int, row);
+ QFETCH(QString, filterRegExp);
+ QFETCH(QStringList, expectedModelList);
+ QFETCH(QStringList, expectedProxyModelList);
+ QStringListModel model;
+ QSortFilterProxyModel proxyModel;
+
+ model.setStringList(initialModelList);
+ proxyModel.setSourceModel(&model);
+ proxyModel.setDynamicSortFilter(true);
+ proxyModel.setFilterRegExp(filterRegExp);
+
+ QVERIFY(proxyModel.insertRow(row));
+ QCOMPARE(model.stringList(), expectedModelList);
+ QCOMPARE(proxyModel.rowCount(), expectedProxyModelList.count());
+ for (int r = 0; r < proxyModel.rowCount(); ++r) {
+ QModelIndex index = proxyModel.index(r, 0);
+ QVERIFY(index.isValid());
+ QCOMPARE(proxyModel.data(index).toString(), expectedProxyModelList.at(r));
+ }
+}
+
+#include "tst_qsortfilterproxymodel.moc"
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h
new file mode 100644
index 0000000000..82d4b7344e
--- /dev/null
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TST_QSORTFILTERPROXYMODEL_H
+#define TST_QSORTFILTERPROXYMODEL_H
+
+#include <QtTest/QtTest>
+#include "dynamictreemodel.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtGui/QStandardItem>
+#include <QtWidgets/QTreeView>
+#include <QtWidgets/QTableView>
+
+#include <qdebug.h>
+
+typedef QList<int> IntList;
+typedef QPair<int, int> IntPair;
+typedef QList<IntPair> IntPairList;
+
+enum class FilterType {
+ RegExp,
+ RegularExpression
+};
+
+Q_DECLARE_METATYPE(QList<QPersistentModelIndex>)
+
+class tst_QSortFilterProxyModel : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QSortFilterProxyModel();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void cleanup();
+
+private slots:
+ void getSetCheck();
+ void sort_data();
+ void sort();
+ void sortHierarchy_data();
+ void sortHierarchy();
+
+ void insertRows_data();
+ void insertRows();
+ void prependRow();
+ void appendRowFromCombobox_data();
+ void appendRowFromCombobox();
+ void removeRows_data();
+ void removeRows();
+ void removeColumns_data();
+ void removeColumns();
+ void insertAfterSelect();
+ void removeAfterSelect();
+ void filter_data();
+ void filter();
+ void filterHierarchy_data();
+ void filterHierarchy();
+ void filterColumns_data();
+ void filterColumns();
+
+ void filterTable();
+ void filterCurrent();
+ void filter_qtbug30662();
+
+ void changeSourceLayout();
+ void changeSourceLayoutFilteredOut();
+ void removeSourceRows_data();
+ void removeSourceRows();
+ void insertSourceRows_data();
+ void insertSourceRows();
+ void changeFilter_data();
+ void changeFilter();
+ void changeSourceData_data();
+ void changeSourceData();
+ void changeSourceDataKeepsStableSorting_qtbug1548();
+ void changeSourceDataForwardsRoles_qtbug35440();
+ void resortingDoesNotBreakTreeModels();
+ void dynamicFilterWithoutSort();
+ void sortFilterRole();
+ void selectionFilteredOut();
+ void match_data();
+ void match();
+ void insertIntoChildrenlessItem();
+ void invalidateMappedChildren();
+ void insertRowIntoFilteredParent();
+ void filterOutParentAndFilterInChild();
+
+ void sourceInsertRows();
+ void sourceModelDeletion();
+
+ void sortColumnTracking1();
+ void sortColumnTracking2();
+
+ void sortStable();
+
+ void hiddenColumns();
+ void insertRowsSort();
+ void staticSorting();
+ void dynamicSorting();
+ void fetchMore();
+ void hiddenChildren();
+ void mapFromToSource();
+ void removeRowsRecursive();
+ void doubleProxySelectionSetSourceModel();
+ void appearsAndSort();
+ void unnecessaryDynamicSorting();
+ void unnecessaryMapCreation();
+ void resetInvalidate_data();
+ void resetInvalidate();
+
+ void testMultipleProxiesWithSelection();
+ void mapSelectionFromSource();
+ void testResetInternalData();
+ void filteredColumns();
+ void headerDataChanged();
+
+ void testParentLayoutChanged();
+ void moveSourceRows();
+
+ void hierarchyFilterInvalidation();
+ void simpleFilterInvalidation();
+
+ void chainedProxyModelRoleNames();
+
+ void noMapAfterSourceDelete();
+ void forwardDropApi();
+ void canDropMimeData();
+ void filterHint();
+
+ void sourceLayoutChangeLeavesValidPersistentIndexes();
+ void rowMoveLeavesValidPersistentIndexes();
+
+ void emitLayoutChangedOnlyIfSortingChanged_data();
+ void emitLayoutChangedOnlyIfSortingChanged();
+
+ void checkSetNewModel();
+ void filterAndInsertRow_data();
+ void filterAndInsertRow();
+ void filterAndInsertColumn_data();
+ void filterAndInsertColumn();
+
+ void removeIntervals_data();
+ void removeIntervals();
+
+protected:
+ void buildHierarchy(const QStringList &data, QAbstractItemModel *model);
+ void checkHierarchy(const QStringList &data, const QAbstractItemModel *model);
+ void setupFilter(QSortFilterProxyModel *model, const QString& pattern);
+
+protected:
+ FilterType m_filterType;
+
+private:
+ QStandardItemModel *m_model;
+ QSortFilterProxyModel *m_proxy;
+};
+
+Q_DECLARE_METATYPE(QAbstractItemModel::LayoutChangeHint)
+
+#endif // TST_QSORTFILTERPROXYMODEL_H
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/.gitignore b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/.gitignore
new file mode 100644
index 0000000000..4fdaebc09d
--- /dev/null
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/.gitignore
@@ -0,0 +1 @@
+tst_qsortfilterproxymodel_regexp
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/qsortfilterproxymodel_regexp.pro b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/qsortfilterproxymodel_regexp.pro
new file mode 100644
index 0000000000..7c510930f4
--- /dev/null
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/qsortfilterproxymodel_regexp.pro
@@ -0,0 +1,16 @@
+CONFIG += testcase
+TARGET = tst_qsortfilterproxymodel_regexp
+
+QT += widgets testlib
+mtdir = ../../../other/qabstractitemmodelutils
+qsfpmdir = ../qsortfilterproxymodel_common
+
+INCLUDEPATH += $$PWD/$${mtdir} $$PWD/$${qsfpmdir}
+SOURCES += \
+ tst_qsortfilterproxymodel_regexp.cpp \
+ $${qsfpmdir}/tst_qsortfilterproxymodel.cpp \
+ $${mtdir}/dynamictreemodel.cpp
+
+HEADERS += \
+ $${qsfpmdir}/tst_qsortfilterproxymodel.h \
+ $${mtdir}/dynamictreemodel.h
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/tst_qsortfilterproxymodel_regexp.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/tst_qsortfilterproxymodel_regexp.cpp
new file mode 100644
index 0000000000..38607f1378
--- /dev/null
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/tst_qsortfilterproxymodel_regexp.cpp
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include "tst_qsortfilterproxymodel.h"
+
+class tst_QSortFilterProxyModelRegExp : public tst_QSortFilterProxyModel
+{
+ Q_OBJECT
+public:
+ tst_QSortFilterProxyModelRegExp();
+private slots:
+ void tst_invalid();
+ void tst_caseSensitivity();
+};
+
+tst_QSortFilterProxyModelRegExp::tst_QSortFilterProxyModelRegExp() :
+ tst_QSortFilterProxyModel()
+{
+ m_filterType = FilterType::RegExp;
+}
+
+void tst_QSortFilterProxyModelRegExp::tst_invalid()
+{
+ const QLatin1String pattern("test");
+ QSortFilterProxyModel model;
+ model.setFilterRegExp(pattern);
+ QCOMPARE(model.filterRegExp(), QRegExp(pattern));
+ model.setFilterRegularExpression(pattern);
+ QCOMPARE(model.filterRegExp(), QRegExp());
+}
+
+void tst_QSortFilterProxyModelRegExp::tst_caseSensitivity()
+{
+ const QLatin1String pattern("test");
+ QSortFilterProxyModel model;
+ model.setFilterCaseSensitivity(Qt::CaseInsensitive);
+ model.setFilterRegExp(pattern);
+ QCOMPARE(model.filterCaseSensitivity(), Qt::CaseInsensitive);
+}
+
+QTEST_MAIN(tst_QSortFilterProxyModelRegExp)
+#include "tst_qsortfilterproxymodel_regexp.moc"
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/.gitignore b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/.gitignore
new file mode 100644
index 0000000000..286771e250
--- /dev/null
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/.gitignore
@@ -0,0 +1 @@
+tst_qsortfilterproxymodel_regularexpression
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/qsortfilterproxymodel_regularexpression.pro b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/qsortfilterproxymodel_regularexpression.pro
new file mode 100644
index 0000000000..e993d07126
--- /dev/null
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/qsortfilterproxymodel_regularexpression.pro
@@ -0,0 +1,16 @@
+CONFIG += testcase
+TARGET = tst_qsortfilterproxymodel_regularexpression
+
+QT += widgets testlib
+mtdir = ../../../other/qabstractitemmodelutils
+qsfpmdir = ../qsortfilterproxymodel_common
+
+INCLUDEPATH += $$PWD/$${mtdir} $${qsfpmdir}
+SOURCES += \
+ tst_qsortfilterproxymodel_regularexpression.cpp \
+ $${qsfpmdir}/tst_qsortfilterproxymodel.cpp \
+ $${mtdir}/dynamictreemodel.cpp
+
+HEADERS += \
+ $${qsfpmdir}/tst_qsortfilterproxymodel.h \
+ $${mtdir}/dynamictreemodel.h
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/tst_qsortfilterproxymodel_regularexpression.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/tst_qsortfilterproxymodel_regularexpression.cpp
new file mode 100644
index 0000000000..821e199bcb
--- /dev/null
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/tst_qsortfilterproxymodel_regularexpression.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include "tst_qsortfilterproxymodel.h"
+
+class tst_QSortFilterProxyModelRegularExpression : public tst_QSortFilterProxyModel
+{
+ Q_OBJECT
+public:
+ tst_QSortFilterProxyModelRegularExpression();
+private slots:
+ void tst_invalid();
+};
+
+tst_QSortFilterProxyModelRegularExpression::tst_QSortFilterProxyModelRegularExpression() :
+ tst_QSortFilterProxyModel()
+{
+ m_filterType = FilterType::RegularExpression;
+}
+
+void tst_QSortFilterProxyModelRegularExpression::tst_invalid()
+{
+ const QLatin1String pattern("test");
+ QSortFilterProxyModel model;
+ model.setFilterRegularExpression(pattern);
+ QCOMPARE(model.filterRegularExpression(), QRegularExpression(pattern));
+ model.setFilterRegExp(pattern);
+ QCOMPARE(model.filterRegularExpression(), QRegularExpression());
+}
+
+QTEST_MAIN(tst_QSortFilterProxyModelRegularExpression)
+#include "tst_qsortfilterproxymodel_regularexpression.moc"
diff --git a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
index 5e9dbdd226..a53501b9dd 100644
--- a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
+++ b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
@@ -415,7 +415,7 @@ void tst_QCoreApplication::removePostedEvents()
expected.clear();
}
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
class DeliverInDefinedOrderThread : public QThread
{
Q_OBJECT
@@ -532,7 +532,7 @@ void tst_QCoreApplication::deliverInDefinedOrder()
QObject::connect(&obj, SIGNAL(done()), &app, SLOT(quit()));
app.exec();
}
-#endif // QT_NO_QTHREAD
+#endif // QT_CONFIG(thread)
void tst_QCoreApplication::applicationPid()
{
diff --git a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.h b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.h
index b6c20a915f..105cca5174 100644
--- a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.h
+++ b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.h
@@ -43,7 +43,7 @@ private slots:
void argc();
void postEvent();
void removePostedEvents();
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
void deliverInDefinedOrder();
#endif
void applicationPid();
diff --git a/tests/auto/corelib/kernel/qelapsedtimer/BLACKLIST b/tests/auto/corelib/kernel/qelapsedtimer/BLACKLIST
index 4cd3c2f0c8..4dd71ca9f4 100644
--- a/tests/auto/corelib/kernel/qelapsedtimer/BLACKLIST
+++ b/tests/auto/corelib/kernel/qelapsedtimer/BLACKLIST
@@ -1,3 +1,4 @@
[elapsed]
windows
osx-10.12
+osx-10.13
diff --git a/tests/auto/corelib/kernel/qeventdispatcher/BLACKLIST b/tests/auto/corelib/kernel/qeventdispatcher/BLACKLIST
index 402d87b82f..b1590a5ccf 100644
--- a/tests/auto/corelib/kernel/qeventdispatcher/BLACKLIST
+++ b/tests/auto/corelib/kernel/qeventdispatcher/BLACKLIST
@@ -1,6 +1,5 @@
[sendPostedEvents]
windows
-osx
[registerTimer]
windows
-osx
+winrt
diff --git a/tests/auto/corelib/kernel/qmetaenum/tst_qmetaenum.cpp b/tests/auto/corelib/kernel/qmetaenum/tst_qmetaenum.cpp
index e4aa8b80c0..6ed0a6caa9 100644
--- a/tests/auto/corelib/kernel/qmetaenum/tst_qmetaenum.cpp
+++ b/tests/auto/corelib/kernel/qmetaenum/tst_qmetaenum.cpp
@@ -37,19 +37,33 @@ class tst_QMetaEnum : public QObject
Q_OBJECT
public:
enum SuperEnum { SuperValue1 = 1 , SuperValue2 = 2 };
+ enum Flag { Flag1 = 1 , Flag2 = 2 };
+ Q_DECLARE_FLAGS(Flags, Flag)
Q_ENUM(SuperEnum)
+ Q_FLAG(Flags)
private slots:
void fromType();
void valuesToKeys_data();
void valuesToKeys();
+ void defaultConstructed();
};
void tst_QMetaEnum::fromType()
{
QMetaEnum meta = QMetaEnum::fromType<SuperEnum>();
QVERIFY(meta.isValid());
+ QVERIFY(!meta.isFlag());
QCOMPARE(meta.name(), "SuperEnum");
+ QCOMPARE(meta.enumName(), "SuperEnum");
+ QCOMPARE(meta.enclosingMetaObject(), &staticMetaObject);
+ QCOMPARE(meta.keyCount(), 2);
+
+ meta = QMetaEnum::fromType<Flags>();
+ QVERIFY(meta.isValid());
+ QVERIFY(meta.isFlag());
+ QCOMPARE(meta.name(), "Flags");
+ QCOMPARE(meta.enumName(), "Flag");
QCOMPARE(meta.enclosingMetaObject(), &staticMetaObject);
QCOMPARE(meta.keyCount(), 2);
}
@@ -86,6 +100,15 @@ void tst_QMetaEnum::valuesToKeys()
QCOMPARE(me.valueToKeys(windowFlags), expected);
}
+void tst_QMetaEnum::defaultConstructed()
+{
+ QMetaEnum e;
+ QVERIFY(!e.isValid());
+ QVERIFY(!e.isScoped());
+ QVERIFY(!e.isFlag());
+ QCOMPARE(e.name(), QByteArray());
+}
+
Q_STATIC_ASSERT(QtPrivate::IsQEnumHelper<tst_QMetaEnum::SuperEnum>::Value);
Q_STATIC_ASSERT(QtPrivate::IsQEnumHelper<Qt::WindowFlags>::Value);
Q_STATIC_ASSERT(QtPrivate::IsQEnumHelper<Qt::Orientation>::Value);
diff --git a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
index 431a9ebdea..9855bec520 100644
--- a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
+++ b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
@@ -54,6 +54,11 @@ namespace MyNamespace {
MyEnum2,
MyEnum3
};
+ enum class MyScopedEnum {
+ Enum1,
+ Enum2,
+ Enum3
+ };
enum MyAnotherEnum {
MyAnotherEnum1 = 1,
MyAnotherEnum2 = 2,
@@ -64,7 +69,13 @@ namespace MyNamespace {
MyFlag2 = 0x02,
MyFlag3 = 0x04
};
+ enum class MyScopedFlag {
+ MyFlag1 = 0x10,
+ MyFlag2 = 0x20,
+ MyFlag3 = 0x40
+ };
Q_DECLARE_FLAGS(MyFlags, MyFlag)
+ Q_DECLARE_FLAGS(MyScopedFlags, MyScopedFlag)
MyEnum myEnum() const { return m_enum; }
void setMyEnum(MyEnum val) { m_enum = val; }
@@ -79,8 +90,10 @@ namespace MyNamespace {
{ }
private:
Q_ENUM(MyEnum)
+ Q_ENUM(MyScopedEnum)
Q_ENUM(MyAnotherEnum)
Q_FLAG(MyFlags)
+ Q_FLAG(MyScopedFlags)
MyEnum m_enum;
MyFlags m_flags;
@@ -1730,20 +1743,35 @@ void tst_QMetaObject::signalIndex()
void tst_QMetaObject::enumDebugStream()
{
- QTest::ignoreMessage(QtDebugMsg, "hello MyNamespace::MyClass::MyEnum(MyEnum2) world ");
- MyNamespace::MyClass::MyEnum e = MyNamespace::MyClass::MyEnum2;
- qDebug() << "hello" << e << "world";
+ QTest::ignoreMessage(QtDebugMsg, "hello MyNamespace::MyClass::MyEnum2 world ");
+ qDebug() << "hello" << MyNamespace::MyClass::MyEnum2 << "world";
+
+ QTest::ignoreMessage(QtDebugMsg, "hello MyNamespace::MyClass::MyScopedEnum::Enum3 scoped world ");
+ qDebug() << "hello" << MyNamespace::MyClass::MyScopedEnum::Enum3 << "scoped world";
- QTest::ignoreMessage(QtDebugMsg, "Qt::WindowType(WindowTitleHint) Qt::WindowType(Window) Qt::WindowType(Desktop) Qt::WindowType(WindowSystemMenuHint)");
- qDebug() << Qt::WindowTitleHint << Qt::Window <<Qt::Desktop << Qt::WindowSystemMenuHint;
+ QTest::ignoreMessage(QtDebugMsg, "Qt::WindowTitleHint Qt::Window Qt::Desktop Qt::WindowSystemMenuHint");
+ qDebug() << Qt::WindowTitleHint << Qt::Window << Qt::Desktop << Qt::WindowSystemMenuHint;
- QTest::ignoreMessage(QtDebugMsg, "hello QFlags<MyNamespace::MyClass::MyFlags>(MyFlag1) world");
+ QTest::ignoreMessage(QtDebugMsg, "hello QFlags<MyNamespace::MyClass::MyFlag>(MyFlag1) world");
MyNamespace::MyClass::MyFlags f1 = MyNamespace::MyClass::MyFlag1;
qDebug() << "hello" << f1 << "world";
MyNamespace::MyClass::MyFlags f2 = MyNamespace::MyClass::MyFlag2 | MyNamespace::MyClass::MyFlag3;
- QTest::ignoreMessage(QtDebugMsg, "QFlags<MyNamespace::MyClass::MyFlags>(MyFlag1) QFlags<MyNamespace::MyClass::MyFlags>(MyFlag2|MyFlag3)");
+ QTest::ignoreMessage(QtDebugMsg, "QFlags<MyNamespace::MyClass::MyFlag>(MyFlag1) QFlags<MyNamespace::MyClass::MyFlag>(MyFlag2|MyFlag3)");
qDebug() << f1 << f2;
+
+ QTest::ignoreMessage(QtDebugMsg, "QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2)");
+ MyNamespace::MyClass::MyScopedFlags f3 = MyNamespace::MyClass::MyScopedFlag::MyFlag2;
+ qDebug() << f3;
+
+ QTest::ignoreMessage(QtDebugMsg, "QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2|MyFlag3)");
+ f3 |= MyNamespace::MyClass::MyScopedFlag::MyFlag3;
+ qDebug() << f3;
+
+ // Single flag recognized as enum:
+ QTest::ignoreMessage(QtDebugMsg, "MyNamespace::MyClass::MyFlag1");
+ MyNamespace::MyClass::MyFlag f4 = MyNamespace::MyClass::MyFlag1;
+ qDebug() << f4;
}
void tst_QMetaObject::inherits_data()
diff --git a/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp b/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
index 6bb031e357..56623773a2 100644
--- a/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
+++ b/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
@@ -830,6 +830,7 @@ void tst_QMetaObjectBuilder::enumerator()
// Modify the attributes on enum1.
enum1.setIsFlag(true);
enum1.setIsScoped(true);
+ enum1.setEnumName(QByteArrayLiteral("fooFlag"));
QCOMPARE(enum1.addKey("ABC", 0), 0);
QCOMPARE(enum1.addKey("DEF", 1), 1);
QCOMPARE(enum1.addKey("GHI", -1), 2);
@@ -838,6 +839,7 @@ void tst_QMetaObjectBuilder::enumerator()
QCOMPARE(enum1.name(), QByteArray("foo"));
QVERIFY(enum1.isFlag());
QVERIFY(enum1.isScoped());
+ QCOMPARE(enum1.enumName(), QByteArray("fooFlag"));
QCOMPARE(enum1.keyCount(), 3);
QCOMPARE(enum1.index(), 0);
QCOMPARE(enum1.key(0), QByteArray("ABC"));
diff --git a/tests/auto/corelib/kernel/qmetatype/qmetatype.pro b/tests/auto/corelib/kernel/qmetatype/qmetatype.pro
index ad148ccc7f..d70befecfd 100644
--- a/tests/auto/corelib/kernel/qmetatype/qmetatype.pro
+++ b/tests/auto/corelib/kernel/qmetatype/qmetatype.pro
@@ -1,6 +1,6 @@
CONFIG += testcase
TARGET = tst_qmetatype
-QT = core testlib
+QT = core-private testlib
INCLUDEPATH += $$PWD/../../../other/qvariant_common
SOURCES = tst_qmetatype.cpp
TESTDATA=./typeFlags.bin
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
index e312199980..5d9b5ca95c 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
@@ -29,6 +29,7 @@
#include <QtCore>
#include <QtTest/QtTest>
+#include <QtCore/private/qmetaobjectbuilder_p.h>
#include "tst_qmetatype.h"
#include "tst_qvariant_common.h"
@@ -38,6 +39,7 @@
#endif
#include <algorithm>
+#include <memory>
// mingw gcc 4.8 also takes way too long, letting the CI system abort the test
#if defined(__MINGW32__)
@@ -52,12 +54,19 @@ class tst_QMetaType: public QObject
Q_PROPERTY(QList<QVariant> prop READ prop WRITE setProp)
public:
+ struct GadgetPropertyType {
+ QByteArray type;
+ QByteArray name;
+ QVariant testData;
+ };
+
tst_QMetaType() { propList << 42 << "Hello"; }
QList<QVariant> prop() const { return propList; }
void setProp(const QList<QVariant> &list) { propList = list; }
private:
+ void registerGadget(const char * name, const QVector<GadgetPropertyType> &gadgetProperties);
QList<QVariant> propList;
private slots:
@@ -89,6 +98,7 @@ private slots:
void flagsBinaryCompatibility5_0();
void construct_data();
void construct();
+ void typedConstruct();
void constructCopy_data();
void constructCopy();
void typedefs();
@@ -115,6 +125,128 @@ private slots:
void customDebugStream();
};
+struct BaseGenericType
+{
+ int m_typeId = -1;
+ virtual void *constructor(int typeId, void *where, const void *copy) = 0;
+ virtual void staticMetacallFunction(QMetaObject::Call _c, int _id, void **_a) = 0;
+ virtual void saveOperator(QDataStream & out) const = 0;
+ virtual void loadOperator(QDataStream &in) = 0;
+ virtual ~BaseGenericType() {}
+};
+
+struct GenericGadgetType : BaseGenericType
+{
+ void *constructor(int typeId, void *where, const void *copy) override
+ {
+ GenericGadgetType *ret = where ? new(where) GenericGadgetType : new GenericGadgetType;
+ ret->m_typeId = typeId;
+ if (copy) {
+ Q_ASSERT(ret->m_typeId == reinterpret_cast<const GenericGadgetType*>(copy)->m_typeId);
+ *ret = *reinterpret_cast<const GenericGadgetType*>(copy);
+ } else {
+ ret->properties = properties;
+ }
+ return ret;
+ }
+
+ void staticMetacallFunction(QMetaObject::Call _c, int _id, void **_a) override
+ {
+ if (_c == QMetaObject::ReadProperty) {
+ if (_id < properties.size()) {
+ const auto &prop = properties.at(_id);
+ QMetaType::destruct(int(prop.userType()), _a[0]);
+ QMetaType::construct(int(prop.userType()), _a[0], prop.constData());
+ }
+ } else if (_c == QMetaObject::WriteProperty) {
+ if (_id < properties.size()) {
+ auto & prop = properties[_id];
+ prop = QVariant(prop.userType(), _a[0]);
+ }
+ }
+ }
+
+ void saveOperator(QDataStream & out) const override
+ {
+ for (const auto &prop : properties)
+ out << prop;
+ }
+
+ void loadOperator(QDataStream &in) override
+ {
+ for (auto &prop : properties)
+ in >> prop;
+ }
+ QVector<QVariant> properties;
+};
+
+struct GenericPODType : BaseGenericType
+{
+ // BaseGenericType interface
+ void *constructor(int typeId, void *where, const void *copy) override
+ {
+ GenericPODType *ret = where ? new(where) GenericPODType : new GenericPODType;
+ ret->m_typeId = typeId;
+ if (copy) {
+ Q_ASSERT(ret->m_typeId == reinterpret_cast<const GenericPODType*>(copy)->m_typeId);
+ *ret = *reinterpret_cast<const GenericPODType*>(copy);
+ } else {
+ ret->podData = podData;
+ }
+ return ret;
+ }
+
+ void staticMetacallFunction(QMetaObject::Call _c, int _id, void **_a) override
+ {
+ Q_UNUSED(_c);
+ Q_UNUSED(_id);
+ Q_UNUSED(_a);
+ Q_ASSERT(false);
+ }
+
+ void saveOperator(QDataStream &out) const override
+ {
+ out << podData;
+ }
+ void loadOperator(QDataStream &in) override
+ {
+ in >> podData;
+ }
+ QByteArray podData;
+};
+
+using RegisteredType = QPair<std::shared_ptr<BaseGenericType>, std::shared_ptr<QMetaObject>>;
+static QHash<int, RegisteredType> s_managedTypes;
+
+static void GadgetsStaticMetacallFunction(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
+{
+ reinterpret_cast<BaseGenericType*>(_o)->staticMetacallFunction(_c, _id, _a);
+}
+
+static void GadgetTypedDestructor(int typeId, void *ptr)
+{
+ QCOMPARE(typeId, reinterpret_cast<BaseGenericType*>(ptr)->m_typeId);
+ reinterpret_cast<BaseGenericType*>(ptr)->~BaseGenericType();
+}
+
+static void *GadgetTypedConstructor(int type, void *where, const void *copy)
+{
+ auto it = s_managedTypes.find(type);
+ if (it == s_managedTypes.end())
+ return nullptr; // crash the test
+ return it->first->constructor(type, where, copy);
+}
+
+static void GadgetSaveOperator(QDataStream & out, const void *data)
+{
+ reinterpret_cast<const BaseGenericType *>(data)->saveOperator(out);
+}
+
+static void GadgetLoadOperator(QDataStream &in, void *data)
+{
+ reinterpret_cast<BaseGenericType *>(data)->loadOperator(in);
+}
+
struct Foo { int i; };
@@ -149,6 +281,34 @@ class GadgetDerivedAndTyped : public CustomGadget {};
Q_DECLARE_METATYPE(GadgetDerivedAndTyped<int>)
Q_DECLARE_METATYPE(GadgetDerivedAndTyped<int>*)
+void tst_QMetaType::registerGadget(const char *name, const QVector<GadgetPropertyType> &gadgetProperties)
+{
+ QMetaObjectBuilder gadgetBuilder;
+ gadgetBuilder.setClassName(name);
+ QMetaObjectBuilder::MetaObjectFlags metaObjectflags = QMetaObjectBuilder::DynamicMetaObject | QMetaObjectBuilder::PropertyAccessInStaticMetaCall;
+ gadgetBuilder.setFlags(metaObjectflags);
+ auto dynamicGadgetProperties = std::make_shared<GenericGadgetType>();
+ for (const auto &prop : gadgetProperties) {
+ int propertyType = QMetaType::type(prop.type);
+ dynamicGadgetProperties->properties.push_back(QVariant(QVariant::Type(propertyType)));
+ auto dynamicPropery = gadgetBuilder.addProperty(prop.name, prop.type);
+ dynamicPropery.setWritable(true);
+ dynamicPropery.setReadable(true);
+ }
+ auto meta = gadgetBuilder.toMetaObject();
+ meta->d.static_metacall = &GadgetsStaticMetacallFunction;
+ meta->d.superdata = nullptr;
+ const auto flags = QMetaType::WasDeclaredAsMetaType | QMetaType::IsGadget | QMetaType::NeedsConstruction | QMetaType::NeedsDestruction;
+ int gadgetTypeId = QMetaType::registerType(name,
+ &GadgetTypedDestructor,
+ &GadgetTypedConstructor,
+ sizeof(GenericGadgetType),
+ flags, meta);
+ QVERIFY(gadgetTypeId > 0);
+ QMetaType::registerStreamOperators(gadgetTypeId, &GadgetSaveOperator, &GadgetLoadOperator);
+ s_managedTypes[gadgetTypeId] = qMakePair(dynamicGadgetProperties, std::shared_ptr<QMetaObject>{meta, [](QMetaObject *ptr){ ::free(ptr); }});
+}
+
void tst_QMetaType::defined()
{
QCOMPARE(int(QMetaTypeId2<QString>::Defined), 1);
@@ -906,6 +1066,90 @@ FOR_EACH_CORE_METATYPE(RETURN_CONSTRUCT_FUNCTION)
TypeTestFunctionGetter::get(type)();
}
+void tst_QMetaType::typedConstruct()
+{
+ auto testMetaObjectWriteOnGadget = [](QVariant &gadget, const QVector<GadgetPropertyType> &properties)
+ {
+ auto metaObject = QMetaType::metaObjectForType(gadget.userType());
+ QVERIFY(metaObject != nullptr);
+ QCOMPARE(metaObject->methodCount(), 0);
+ QCOMPARE(metaObject->propertyCount(), properties.size());
+ for (int i = 0; i < metaObject->propertyCount(); ++i) {
+ auto prop = metaObject->property(i);
+ QCOMPARE(properties[i].name, prop.name());
+ QCOMPARE(properties[i].type, prop.typeName());
+ prop.writeOnGadget(gadget.data(), properties[i].testData);
+ }
+ };
+
+ auto testMetaObjectReadOnGadget = [](QVariant gadget, const QVector<GadgetPropertyType> &properties)
+ {
+ auto metaObject = QMetaType::metaObjectForType(gadget.userType());
+ QVERIFY(metaObject != nullptr);
+ QCOMPARE(metaObject->methodCount(), 0);
+ QCOMPARE(metaObject->propertyCount(), properties.size());
+ for (int i = 0; i < metaObject->propertyCount(); ++i) {
+ auto prop = metaObject->property(i);
+ QCOMPARE(properties[i].name, prop.name());
+ QCOMPARE(properties[i].type, prop.typeName());
+ if (!QMetaType::typeFlags(prop.userType()).testFlag(QMetaType::IsGadget))
+ QCOMPARE(properties[i].testData, prop.readOnGadget(gadget.constData()));
+ }
+ };
+
+ QVector<GadgetPropertyType> dynamicGadget1 = {
+ {"int", "int_prop", 34526},
+ {"float", "float_prop", 1.23f},
+ {"QString", "string_prop", QString{"Test QString"}}
+ };
+ registerGadget("DynamicGadget1", dynamicGadget1);
+
+ QVariant testGadget1(QVariant::Type(QMetaType::type("DynamicGadget1")));
+ testMetaObjectWriteOnGadget(testGadget1, dynamicGadget1);
+ testMetaObjectReadOnGadget(testGadget1, dynamicGadget1);
+
+
+ QVector<GadgetPropertyType> dynamicGadget2 = {
+ {"int", "int_prop", 512},
+ {"double", "double_prop", 4.56},
+ {"QString", "string_prop", QString{"Another String"}},
+ {"DynamicGadget1", "dynamicGadget1_prop", testGadget1}
+ };
+ registerGadget("DynamicGadget2", dynamicGadget2);
+ QVariant testGadget2(QVariant::Type(QMetaType::type("DynamicGadget2")));
+ testMetaObjectWriteOnGadget(testGadget2, dynamicGadget2);
+ testMetaObjectReadOnGadget(testGadget2, dynamicGadget2);
+ auto g2mo = QMetaType::metaObjectForType(testGadget2.userType());
+ auto dynamicGadget1_prop = g2mo->property(g2mo->indexOfProperty("dynamicGadget1_prop"));
+ testMetaObjectReadOnGadget(dynamicGadget1_prop.readOnGadget(testGadget2.constData()), dynamicGadget1);
+
+
+ // Register POD
+ const QByteArray myPodTesData = "My POD test data";
+ const char podTypeName[] = "DynamicPOD";
+ auto dynamicGadgetProperties = std::make_shared<GenericPODType>();
+ dynamicGadgetProperties->podData = myPodTesData;
+ const auto flags = QMetaType::NeedsConstruction | QMetaType::NeedsDestruction;
+ int podTypeId = QMetaType::registerType(podTypeName,
+ &GadgetTypedDestructor,
+ &GadgetTypedConstructor,
+ sizeof(GenericGadgetType),
+ flags, nullptr);
+ QVERIFY(podTypeId > 0);
+ QMetaType::registerStreamOperators(podTypeId, &GadgetSaveOperator, &GadgetLoadOperator);
+ s_managedTypes[podTypeId] = qMakePair(dynamicGadgetProperties, std::shared_ptr<QMetaObject>{});
+
+ // Test POD
+ QCOMPARE(podTypeId, QMetaType::type(podTypeName));
+ QVariant podVariant{QVariant::Type(podTypeId)};
+ QCOMPARE(myPodTesData, static_cast<const GenericPODType *>(reinterpret_cast<const BaseGenericType *>(podVariant.constData()))->podData);
+
+ QVariant podVariant1{podVariant};
+ podVariant1.detach(); // Test stream operators
+ static_cast<GenericPODType *>(reinterpret_cast<BaseGenericType *>(podVariant.data()))->podData.clear();
+ QCOMPARE(myPodTesData, static_cast<const GenericPODType *>(reinterpret_cast<const BaseGenericType *>(podVariant1.constData()))->podData);
+}
+
template<int ID>
static void testConstructCopyHelper()
{
@@ -1574,6 +1818,9 @@ DECLARE_NONSTREAMABLE(QJsonValue)
DECLARE_NONSTREAMABLE(QJsonObject)
DECLARE_NONSTREAMABLE(QJsonArray)
DECLARE_NONSTREAMABLE(QJsonDocument)
+DECLARE_NONSTREAMABLE(QCborValue)
+DECLARE_NONSTREAMABLE(QCborArray)
+DECLARE_NONSTREAMABLE(QCborMap)
DECLARE_NONSTREAMABLE(QObject*)
DECLARE_NONSTREAMABLE(QWidget*)
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
index 93ff33bb67..6bda9638f7 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
@@ -273,6 +273,24 @@ template<> struct TestValueFactory<QMetaType::QJsonDocument> {
);
}
};
+
+template<> struct TestValueFactory<QMetaType::QCborSimpleType> {
+ static QCborSimpleType *create() { return new QCborSimpleType(QCborSimpleType::True); }
+};
+template<> struct TestValueFactory<QMetaType::QCborValue> {
+ static QCborValue *create() { return new QCborValue(123.); }
+};
+template<> struct TestValueFactory<QMetaType::QCborMap> {
+ static QCborMap *create() {
+ return new QCborMap{{0, 0}, {"Hello", 1}, {1, nullptr}};
+ }
+};
+template<> struct TestValueFactory<QMetaType::QCborArray> {
+ static QCborArray *create() {
+ return new QCborArray{0, 1, -2, 2.5, false, nullptr, "Hello", QByteArray("World") };
+ }
+};
+
template<> struct TestValueFactory<QMetaType::QVariant> {
static QVariant *create() { return new QVariant(QStringList(QStringList() << "Q" << "t")); }
};
diff --git a/tests/auto/corelib/kernel/qobject/.gitignore b/tests/auto/corelib/kernel/qobject/.gitignore
index 7970e32c8f..d609065333 100644
--- a/tests/auto/corelib/kernel/qobject/.gitignore
+++ b/tests/auto/corelib/kernel/qobject/.gitignore
@@ -1,3 +1,7 @@
tst_qobject
-signalbug/signalbug
-signalbug/signalbug.exe
+signalbug_helper
+signalbug_helper.exe
+debug/signalbug_helper
+release/signalbug_helper
+debug/signalbug_helper.exe
+release/signalbug_helper.exe
diff --git a/tests/auto/corelib/kernel/qobject/qobject.pro b/tests/auto/corelib/kernel/qobject/qobject.pro
index 978aab86c1..75ad7b5f14 100644
--- a/tests/auto/corelib/kernel/qobject/qobject.pro
+++ b/tests/auto/corelib/kernel/qobject/qobject.pro
@@ -1,8 +1,4 @@
TEMPLATE = subdirs
-!winrt {
- test.depends = signalbug
- SUBDIRS += signalbug
-}
-
-SUBDIRS += test
+SUBDIRS += test.pro
+!winrt: SUBDIRS += signalbug
diff --git a/tests/auto/corelib/kernel/qobject/signalbug/signalbug.pro b/tests/auto/corelib/kernel/qobject/signalbug/signalbug.pro
index cc51b4c661..d21b3a62a9 100644
--- a/tests/auto/corelib/kernel/qobject/signalbug/signalbug.pro
+++ b/tests/auto/corelib/kernel/qobject/signalbug/signalbug.pro
@@ -1,11 +1,6 @@
-CONFIG -= app_bundle debug_and_release
-CONFIG += console
-DESTDIR = ./
QT = core
HEADERS += signalbug.h
SOURCES += signalbug.cpp
-# This app is testdata for tst_qobject
-target.path = $$[QT_INSTALL_TESTS]/tst_qobject/$$TARGET
-INSTALLS += target
+load(qt_test_helper)
diff --git a/tests/auto/corelib/kernel/qobject/test.pro b/tests/auto/corelib/kernel/qobject/test.pro
new file mode 100644
index 0000000000..af5203e152
--- /dev/null
+++ b/tests/auto/corelib/kernel/qobject/test.pro
@@ -0,0 +1,10 @@
+CONFIG += testcase console
+
+QT = core-private network testlib
+TARGET = tst_qobject
+SOURCES = tst_qobject.cpp
+
+# Force C++17 if available (needed due to P0012R1)
+contains(QT_CONFIG, c++1z): CONFIG += c++1z
+
+DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/corelib/kernel/qobject/test/test.pro b/tests/auto/corelib/kernel/qobject/test/test.pro
deleted file mode 100644
index 4e77cb48c5..0000000000
--- a/tests/auto/corelib/kernel/qobject/test/test.pro
+++ /dev/null
@@ -1,10 +0,0 @@
-CONFIG += testcase console
-TARGET = ../tst_qobject
-QT = core-private network testlib
-SOURCES = ../tst_qobject.cpp
-
-# Force C++17 if available (needed due to P0012R1)
-contains(QT_CONFIG, c++1z): CONFIG += c++1z
-
-!winrt: TEST_HELPER_INSTALLS = ../signalbug/signalbug
-DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
index ec57522f48..68c6ece583 100644
--- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
+++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
@@ -55,7 +55,6 @@ class tst_QObject : public QObject
{
Q_OBJECT
private slots:
- void initTestCase();
void disconnect();
void connectSlotsByName();
void connectSignalsToSignalsWithDefaultArguments();
@@ -145,6 +144,7 @@ private slots:
void disconnectDoesNotLeakFunctor();
void contextDoesNotLeakFunctor();
void connectBase();
+ void connectWarnings();
void qmlConnect();
void exceptions();
void noDeclarativeParentChangedOnDestruction();
@@ -282,14 +282,6 @@ static void playWithObjects()
}
}
-void tst_QObject::initTestCase()
-{
-#if QT_CONFIG(process)
- const QString testDataDir = QFileInfo(QFINDTESTDATA("signalbug")).absolutePath();
- QVERIFY2(QDir::setCurrent(testDataDir), qPrintable("Could not chdir to " + testDataDir));
-#endif
-}
-
void tst_QObject::disconnect()
{
SenderObject *s = new SenderObject;
@@ -3026,7 +3018,7 @@ void tst_QObject::recursiveSignalEmission()
#else
QProcess proc;
// signalbug helper app should always be next to this test binary
- const QString path = QStringLiteral("signalbug/signalbug");
+ const QString path = QStringLiteral("signalbug_helper");
proc.start(path);
QVERIFY2(proc.waitForStarted(), qPrintable(QString::fromLatin1("Cannot start '%1': %2").arg(path, proc.errorString())));
QVERIFY(proc.waitForFinished());
@@ -6697,6 +6689,26 @@ void tst_QObject::connectBase()
QCOMPARE( r1.count_slot3, 1 );
}
+void tst_QObject::connectWarnings()
+{
+ SubSender sub;
+ SenderObject obj;
+ ReceiverObject r1;
+ r1.reset();
+
+ QTest::ignoreMessage(QtWarningMsg, "QObject::connect(SenderObject, ReceiverObject): invalid null parameter");
+ connect(nullptr, &SubSender::signal1, &r1, &ReceiverObject::slot1);
+
+ QTest::ignoreMessage(QtWarningMsg, "QObject::connect(SubSender, Unknown): invalid null parameter");
+ connect(&sub, &SubSender::signal1, nullptr, &ReceiverObject::slot1);
+
+ QTest::ignoreMessage(QtWarningMsg, "QObject::connect(SenderObject, ReceiverObject): invalid null parameter");
+ connect(nullptr, &SenderObject::signal1, &r1, &ReceiverObject::slot1);
+
+ QTest::ignoreMessage(QtWarningMsg, "QObject::connect(SenderObject, Unknown): invalid null parameter");
+ connect(&obj, &SenderObject::signal1, nullptr, &ReceiverObject::slot1);
+}
+
struct QmlReceiver : public QtPrivate::QSlotObjectBase
{
int callCount;
diff --git a/tests/auto/corelib/kernel/qsharedmemory/sharedmemoryhelper/main.cpp b/tests/auto/corelib/kernel/qsharedmemory/producerconsumer/main.cpp
index ffbad37d82..ffbad37d82 100644
--- a/tests/auto/corelib/kernel/qsharedmemory/sharedmemoryhelper/main.cpp
+++ b/tests/auto/corelib/kernel/qsharedmemory/producerconsumer/main.cpp
diff --git a/tests/auto/corelib/kernel/qsharedmemory/producerconsumer/producerconsumer.pro b/tests/auto/corelib/kernel/qsharedmemory/producerconsumer/producerconsumer.pro
new file mode 100644
index 0000000000..a6156ed5b6
--- /dev/null
+++ b/tests/auto/corelib/kernel/qsharedmemory/producerconsumer/producerconsumer.pro
@@ -0,0 +1,5 @@
+QT = core testlib
+
+SOURCES += main.cpp
+
+load(qt_test_helper)
diff --git a/tests/auto/corelib/kernel/qsharedmemory/qsharedmemory.pro b/tests/auto/corelib/kernel/qsharedmemory/qsharedmemory.pro
index 3a4697750e..323d5bbd37 100644
--- a/tests/auto/corelib/kernel/qsharedmemory/qsharedmemory.pro
+++ b/tests/auto/corelib/kernel/qsharedmemory/qsharedmemory.pro
@@ -1,6 +1,6 @@
TEMPLATE = subdirs
qtConfig(sharedmemory) {
- !winrt: SUBDIRS = sharedmemoryhelper
- SUBDIRS += test
+ !winrt: SUBDIRS = producerconsumer
+ SUBDIRS += test.pro
}
diff --git a/tests/auto/corelib/kernel/qsharedmemory/sharedmemoryhelper/sharedmemoryhelper.pro b/tests/auto/corelib/kernel/qsharedmemory/sharedmemoryhelper/sharedmemoryhelper.pro
deleted file mode 100644
index 389015d504..0000000000
--- a/tests/auto/corelib/kernel/qsharedmemory/sharedmemoryhelper/sharedmemoryhelper.pro
+++ /dev/null
@@ -1,17 +0,0 @@
-QT = core testlib
-
-win32: CONFIG += console
-mac:CONFIG -= app_bundle
-
-SOURCES += main.cpp
-TARGET = helperbinary
-
-CONFIG(debug_and_release) {
- CONFIG(debug, debug|release) {
- DESTDIR = ../debug
- } else {
- DESTDIR = ../release
- }
-} else {
- DESTDIR = ..
-}
diff --git a/tests/auto/corelib/kernel/qsharedmemory/test.pro b/tests/auto/corelib/kernel/qsharedmemory/test.pro
new file mode 100644
index 0000000000..8b3badadb0
--- /dev/null
+++ b/tests/auto/corelib/kernel/qsharedmemory/test.pro
@@ -0,0 +1,8 @@
+CONFIG += testcase
+
+QT = core-private testlib
+
+TARGET = tst_qsharedmemory
+SOURCES += tst_qsharedmemory.cpp
+
+linux: LIBS += -lrt
diff --git a/tests/auto/corelib/kernel/qsharedmemory/test/test.pro b/tests/auto/corelib/kernel/qsharedmemory/test/test.pro
deleted file mode 100644
index 61124c27ee..0000000000
--- a/tests/auto/corelib/kernel/qsharedmemory/test/test.pro
+++ /dev/null
@@ -1,18 +0,0 @@
-CONFIG += testcase
-
-QT = core-private testlib
-
-linux:LIBS += -lrt
-
-SOURCES += tst_qsharedmemory.cpp
-TARGET = tst_qsharedmemory
-
-CONFIG(debug_and_release) {
- CONFIG(debug, debug|release) {
- DESTDIR = ../debug
- } else {
- DESTDIR = ../release
- }
-} else {
- DESTDIR = ..
-}
diff --git a/tests/auto/corelib/kernel/qsharedmemory/test/tst_qsharedmemory.cpp b/tests/auto/corelib/kernel/qsharedmemory/test/tst_qsharedmemory.cpp
deleted file mode 100644
index f81324b894..0000000000
--- a/tests/auto/corelib/kernel/qsharedmemory/test/tst_qsharedmemory.cpp
+++ /dev/null
@@ -1,839 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QDebug>
-#include <QFile>
-#if QT_CONFIG(process)
-# include <QProcess>
-#endif
-#include <QSharedMemory>
-#include <QTest>
-#include <QThread>
-
-#define EXISTING_SHARE "existing"
-#define EXISTING_SIZE 1024
-
-Q_DECLARE_METATYPE(QSharedMemory::SharedMemoryError)
-Q_DECLARE_METATYPE(QSharedMemory::AccessMode)
-
-class tst_QSharedMemory : public QObject
-{
- Q_OBJECT
-
-public:
- tst_QSharedMemory();
- virtual ~tst_QSharedMemory();
-
-public Q_SLOTS:
- void init();
- void initTestCase();
- void cleanup();
-
-
-private slots:
- // basics
- void constructor();
- void key_data();
- void key();
- void create_data();
- void create();
- void attach_data();
- void attach();
- void lock();
-
- // custom edge cases
-#ifndef Q_OS_HPUX
- void removeWhileAttached();
-#endif
- void emptyMemory();
-#if !defined(Q_OS_WIN)
- void readOnly();
-#endif
-
- // basics all together
-#ifndef Q_OS_HPUX
- void simpleProducerConsumer_data();
- void simpleProducerConsumer();
- void simpleDoubleProducerConsumer();
-#endif
-
- // with threads
- void simpleThreadedProducerConsumer_data();
- void simpleThreadedProducerConsumer();
-
- // with processes
- void simpleProcessProducerConsumer_data();
- void simpleProcessProducerConsumer();
-
- // extreme cases
- void useTooMuchMemory();
-#if !defined(Q_OS_HPUX)
- void attachTooMuch();
-#endif
-
- // unique keys
- void uniqueKey_data();
- void uniqueKey();
-
-protected:
- static QString helperBinary();
- int remove(const QString &key);
-
- QString rememberKey(const QString &key)
- {
- if (key == EXISTING_SHARE)
- return key;
- if (!keys.contains(key)) {
- keys.append(key);
- remove(key);
- }
- return key;
- }
-
- QStringList keys;
- QList<QSharedMemory*> jail;
- QSharedMemory *existingSharedMemory;
-
-private:
- const QString m_helperBinary;
-};
-
-tst_QSharedMemory::tst_QSharedMemory()
- : existingSharedMemory(0)
- , m_helperBinary(tst_QSharedMemory::helperBinary())
-{
-}
-
-tst_QSharedMemory::~tst_QSharedMemory()
-{
-}
-
-void tst_QSharedMemory::initTestCase()
-{
-#if QT_CONFIG(process)
- QVERIFY2(!m_helperBinary.isEmpty(), "Could not find helper binary");
-#endif
-}
-
-void tst_QSharedMemory::init()
-{
- existingSharedMemory = new QSharedMemory(EXISTING_SHARE);
- if (!existingSharedMemory->create(EXISTING_SIZE)) {
- QCOMPARE(existingSharedMemory->error(), QSharedMemory::AlreadyExists);
- }
-}
-
-void tst_QSharedMemory::cleanup()
-{
- delete existingSharedMemory;
- qDeleteAll(jail.begin(), jail.end());
- jail.clear();
-
- keys.append(EXISTING_SHARE);
- for (int i = 0; i < keys.count(); ++i) {
- QSharedMemory sm(keys.at(i));
- if (!sm.create(1024)) {
- //if (sm.error() != QSharedMemory::KeyError)
- // qWarning() << "test cleanup: remove failed:" << keys.at(i) << sm.error() << sm.errorString();
- sm.attach();
- sm.detach();
- remove(keys.at(i));
- }
- }
-}
-
-#ifndef Q_OS_WIN
-#include <private/qsharedmemory_p.h>
-#include <sys/types.h>
-#ifndef QT_POSIX_IPC
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#else
-#include <sys/mman.h>
-#endif // QT_POSIX_IPC
-#include <errno.h>
-#endif
-
-QString tst_QSharedMemory::helperBinary()
-{
- QString binary = QStringLiteral("helperbinary");
-#ifdef Q_OS_WIN
- binary += QStringLiteral(".exe");
-#endif
- return QFINDTESTDATA(binary);
-}
-
-int tst_QSharedMemory::remove(const QString &key)
-{
-#ifdef Q_OS_WIN
- Q_UNUSED(key);
- return 0;
-#else
- // On unix the shared memory might exists from a previously failed test
- // or segfault, remove it it does
- if (key.isEmpty())
- return -1;
-
- // ftok requires that an actual file exists somewhere
- QString fileName = QSharedMemoryPrivate::makePlatformSafeKey(key);
- if (!QFile::exists(fileName)) {
- //qDebug() << "exits failed";
- return -2;
- }
-
-#ifndef QT_POSIX_IPC
- int unix_key = ftok(fileName.toLatin1().constData(), 'Q');
- if (-1 == unix_key) {
- qDebug() << "ftok failed";
- return -3;
- }
-
- int id = shmget(unix_key, 0, 0600);
- if (-1 == id) {
- qDebug() << "shmget failed" << strerror(errno);
- return -4;
- }
-
- struct shmid_ds shmid_ds;
- if (-1 == shmctl(id, IPC_RMID, &shmid_ds)) {
- qDebug() << "shmctl failed";
- return -5;
- }
-#else
- if (shm_unlink(QFile::encodeName(fileName).constData()) == -1) {
- qDebug() << "shm_unlink failed";
- return -5;
- }
-#endif // QT_POSIX_IPC
-
- return QFile::remove(fileName);
-#endif // Q_OS_WIN
-}
-
-/*!
- Tests the default values
- */
-void tst_QSharedMemory::constructor()
-{
- QSharedMemory sm;
- QCOMPARE(sm.key(), QString());
- QVERIFY(!sm.isAttached());
- QVERIFY(!sm.data());
- QCOMPARE(sm.size(), 0);
- QCOMPARE(sm.error(), QSharedMemory::NoError);
- QCOMPARE(sm.errorString(), QString());
-}
-
-void tst_QSharedMemory::key_data()
-{
- QTest::addColumn<QString>("constructorKey");
- QTest::addColumn<QString>("setKey");
- QTest::addColumn<QString>("setNativeKey");
-
- QTest::newRow("null, null, null") << QString() << QString() << QString();
- QTest::newRow("one, null, null") << QString("one") << QString() << QString();
- QTest::newRow("null, one, null") << QString() << QString("one") << QString();
- QTest::newRow("null, null, one") << QString() << QString() << QString("one");
- QTest::newRow("one, two, null") << QString("one") << QString("two") << QString();
- QTest::newRow("one, null, two") << QString("one") << QString() << QString("two");
- QTest::newRow("null, one, two") << QString() << QString("one") << QString("two");
- QTest::newRow("one, two, three") << QString("one") << QString("two") << QString("three");
- QTest::newRow("invalid") << QString("o/e") << QString("t/o") << QString("|x");
-}
-
-/*!
- Basic key testing
- */
-void tst_QSharedMemory::key()
-{
- QFETCH(QString, constructorKey);
- QFETCH(QString, setKey);
- QFETCH(QString, setNativeKey);
-
- QSharedMemory sm(constructorKey);
- QCOMPARE(sm.key(), constructorKey);
- QCOMPARE(sm.nativeKey().isEmpty(), constructorKey.isEmpty());
- sm.setKey(setKey);
- QCOMPARE(sm.key(), setKey);
- QCOMPARE(sm.nativeKey().isEmpty(), setKey.isEmpty());
- sm.setNativeKey(setNativeKey);
- QVERIFY(sm.key().isNull());
- QCOMPARE(sm.nativeKey(), setNativeKey);
- QCOMPARE(sm.isAttached(), false);
-
- QCOMPARE(sm.error(), QSharedMemory::NoError);
- QCOMPARE(sm.errorString(), QString());
- QVERIFY(!sm.data());
- QCOMPARE(sm.size(), 0);
-
- QCOMPARE(sm.detach(), false);
-}
-
-void tst_QSharedMemory::create_data()
-{
- QTest::addColumn<QString>("key");
- QTest::addColumn<int>("size");
- QTest::addColumn<bool>("canCreate");
- QTest::addColumn<QSharedMemory::SharedMemoryError>("error");
-
- QTest::newRow("null key") << QString() << 1024
- << false << QSharedMemory::KeyError;
- QTest::newRow("-1 size") << QString("negsize") << -1
- << false << QSharedMemory::InvalidSize;
- QTest::newRow("nor size") << QString("norsize") << 1024
- << true << QSharedMemory::NoError;
- QTest::newRow("already exists") << QString(EXISTING_SHARE) << EXISTING_SIZE
- << false << QSharedMemory::AlreadyExists;
-}
-
-/*!
- Basic create testing
- */
-void tst_QSharedMemory::create()
-{
- QFETCH(QString, key);
- QFETCH(int, size);
- QFETCH(bool, canCreate);
- QFETCH(QSharedMemory::SharedMemoryError, error);
-
- QSharedMemory sm(rememberKey(key));
- QCOMPARE(sm.create(size), canCreate);
- if (sm.error() != error)
- qDebug() << sm.errorString();
- QCOMPARE(sm.key(), key);
- if (canCreate) {
- QCOMPARE(sm.errorString(), QString());
- QVERIFY(sm.data() != 0);
- QVERIFY(sm.size() != 0);
- } else {
- QVERIFY(!sm.data());
- QVERIFY(sm.errorString() != QString());
- }
-}
-
-void tst_QSharedMemory::attach_data()
-{
- QTest::addColumn<QString>("key");
- QTest::addColumn<bool>("exists");
- QTest::addColumn<QSharedMemory::SharedMemoryError>("error");
-
- QTest::newRow("null key") << QString() << false << QSharedMemory::KeyError;
- QTest::newRow("doesn't exists") << QString("doesntexists") << false << QSharedMemory::NotFound;
-
- // HPUX doesn't allow for multiple attaches per process.
-#ifndef Q_OS_HPUX
- QTest::newRow("already exists") << QString(EXISTING_SHARE) << true << QSharedMemory::NoError;
-#endif
-}
-
-/*!
- Basic attach/detach testing
- */
-void tst_QSharedMemory::attach()
-{
- QFETCH(QString, key);
- QFETCH(bool, exists);
- QFETCH(QSharedMemory::SharedMemoryError, error);
-
- QSharedMemory sm(key);
- QCOMPARE(sm.attach(), exists);
- QCOMPARE(sm.isAttached(), exists);
- QCOMPARE(sm.error(), error);
- QCOMPARE(sm.key(), key);
- if (exists) {
- QVERIFY(sm.data() != 0);
- QVERIFY(sm.size() != 0);
- QCOMPARE(sm.errorString(), QString());
- QVERIFY(sm.detach());
- // Make sure detach doesn't screw up something and we can't re-attach.
- QVERIFY(sm.attach());
- QVERIFY(sm.data() != 0);
- QVERIFY(sm.size() != 0);
- QVERIFY(sm.detach());
- QCOMPARE(sm.size(), 0);
- QVERIFY(!sm.data());
- } else {
- QVERIFY(!sm.data());
- QCOMPARE(sm.size(), 0);
- QVERIFY(sm.errorString() != QString());
- QVERIFY(!sm.detach());
- }
-}
-
-void tst_QSharedMemory::lock()
-{
- QSharedMemory shm;
- QVERIFY(!shm.lock());
- QCOMPARE(shm.error(), QSharedMemory::LockError);
-
- shm.setKey(QLatin1String("qsharedmemory"));
-
- QVERIFY(!shm.lock());
- QCOMPARE(shm.error(), QSharedMemory::LockError);
-
- QVERIFY(shm.create(100));
- QVERIFY(shm.lock());
- QTest::ignoreMessage(QtWarningMsg, "QSharedMemory::lock: already locked");
- QVERIFY(shm.lock());
- // we didn't unlock(), so ignore the warning from auto-detach in destructor
- QTest::ignoreMessage(QtWarningMsg, "QSharedMemory::lock: already locked");
-}
-
-/*!
- Other shared memory are allowed to be attached after we remove,
- but new shared memory are not allowed to attach after a remove.
- */
-// HPUX doesn't allow for multiple attaches per process.
-#ifndef Q_OS_HPUX
-void tst_QSharedMemory::removeWhileAttached()
-{
- rememberKey("one");
-
- // attach 1
- QSharedMemory *smOne = new QSharedMemory(QLatin1String("one"));
- QVERIFY(smOne->create(1024));
- QVERIFY(smOne->isAttached());
-
- // attach 2
- QSharedMemory *smTwo = new QSharedMemory(QLatin1String("one"));
- QVERIFY(smTwo->attach());
- QVERIFY(smTwo->isAttached());
-
- // detach 1 and remove, remove one first to catch another error.
- delete smOne;
- delete smTwo;
-
- // three shouldn't be able to attach
- QSharedMemory smThree(QLatin1String("one"));
- QVERIFY(!smThree.attach());
- QCOMPARE(smThree.error(), QSharedMemory::NotFound);
-}
-#endif
-
-/*!
- The memory should be set to 0 after created.
- */
-void tst_QSharedMemory::emptyMemory()
-{
- QSharedMemory sm(rememberKey(QLatin1String("voidland")));
- int size = 1024;
- QVERIFY(sm.create(size, QSharedMemory::ReadOnly));
- char *get = (char*)sm.data();
- char null = 0;
- for (int i = 0; i < size; ++i)
- QCOMPARE(get[i], null);
-}
-
-/*!
- Verify that attach with ReadOnly is actually read only
- by writing to data and causing a segfault.
-*/
-// This test opens a crash dialog on Windows.
-#if !defined(Q_OS_WIN)
-void tst_QSharedMemory::readOnly()
-{
-#if !QT_CONFIG(process)
- QSKIP("No qprocess support", SkipAll);
-#elif defined(Q_OS_MACOS)
- QSKIP("QTBUG-59936: Times out on macOS", SkipAll);
-#else
- rememberKey("readonly_segfault");
- // ### on windows disable the popup somehow
- QProcess p;
- p.start(m_helperBinary, QStringList("readonly_segfault"));
- p.setProcessChannelMode(QProcess::ForwardedChannels);
- p.waitForFinished();
- QCOMPARE(p.error(), QProcess::Crashed);
-#endif
-}
-#endif
-
-/*!
- Keep making shared memory until the kernel stops us.
- */
-void tst_QSharedMemory::useTooMuchMemory()
-{
-#ifdef Q_OS_LINUX
- bool success = true;
- int count = 0;
- while (success) {
- QString key = QLatin1String("maxmemorytest_") + QString::number(count++);
- QSharedMemory *sm = new QSharedMemory(rememberKey(key));
- QVERIFY(sm);
- jail.append(sm);
- int size = 32768 * 1024;
- success = sm->create(size);
- if (!success && sm->error() == QSharedMemory::AlreadyExists) {
- // left over from a crash, clean it up
- sm->attach();
- sm->detach();
- success = sm->create(size);
- }
-
- if (!success) {
- QVERIFY(!sm->isAttached());
- QCOMPARE(sm->key(), key);
- QCOMPARE(sm->size(), 0);
- QVERIFY(!sm->data());
- if (sm->error() != QSharedMemory::OutOfResources)
- qDebug() << sm->error() << sm->errorString();
- // ### Linux won't return OutOfResources if there are not enough semaphores to use.
- QVERIFY(sm->error() == QSharedMemory::OutOfResources
- || sm->error() == QSharedMemory::LockError);
- QVERIFY(sm->errorString() != QString());
- QVERIFY(!sm->attach());
- QVERIFY(!sm->detach());
- } else {
- QVERIFY(sm->isAttached());
- }
- }
-#endif
-}
-
-/*!
- Create one shared memory (government) and see how many other shared memories (wars) we can
- attach before the system runs out of resources.
- */
-// HPUX doesn't allow for multiple attaches per process.
-#if !defined(Q_OS_HPUX)
-void tst_QSharedMemory::attachTooMuch()
-{
- QSKIP("disabled");
-
- QSharedMemory government(rememberKey("government"));
- QVERIFY(government.create(1024));
- while (true) {
- QSharedMemory *war = new QSharedMemory(government.key());
- QVERIFY(war);
- jail.append(war);
- if (!war->attach()) {
- QVERIFY(!war->isAttached());
- QCOMPARE(war->key(), government.key());
- QCOMPARE(war->size(), 0);
- QVERIFY(!war->data());
- QCOMPARE(war->error(), QSharedMemory::OutOfResources);
- QVERIFY(war->errorString() != QString());
- QVERIFY(!war->detach());
- break;
- } else {
- QVERIFY(war->isAttached());
- }
- }
-}
-#endif
-
-// HPUX doesn't allow for multiple attaches per process.
-#ifndef Q_OS_HPUX
-void tst_QSharedMemory::simpleProducerConsumer_data()
-{
- QTest::addColumn<QSharedMemory::AccessMode>("mode");
-
- QTest::newRow("readonly") << QSharedMemory::ReadOnly;
- QTest::newRow("readwrite") << QSharedMemory::ReadWrite;
-}
-
-/*!
- The basic consumer producer that rounds out the basic testing.
- If this fails then any muli-threading/process might fail (but be
- harder to debug)
-
- This doesn't require nor test any locking system.
- */
-void tst_QSharedMemory::simpleProducerConsumer()
-{
- QFETCH(QSharedMemory::AccessMode, mode);
-
- rememberKey(QLatin1String("market"));
- QSharedMemory producer(QLatin1String("market"));
- QSharedMemory consumer(QLatin1String("market"));
- int size = 512;
- QVERIFY(producer.create(size));
- QVERIFY(consumer.attach(mode));
-
- char *put = (char*)producer.data();
- char *get = (char*)consumer.data();
- // On Windows CE you always have ReadWrite access. Thus
- // ViewMapOfFile returns the same pointer
- QVERIFY(put != get);
- for (int i = 0; i < size; ++i) {
- put[i] = 'Q';
- QCOMPARE(get[i], 'Q');
- }
- QVERIFY(consumer.detach());
-}
-#endif
-
-// HPUX doesn't allow for multiple attaches per process.
-#ifndef Q_OS_HPUX
-void tst_QSharedMemory::simpleDoubleProducerConsumer()
-{
- rememberKey(QLatin1String("market"));
- QSharedMemory producer(QLatin1String("market"));
- int size = 512;
- QVERIFY(producer.create(size));
- QVERIFY(producer.detach());
- QVERIFY(producer.create(size));
-
- {
- QSharedMemory consumer(QLatin1String("market"));
- QVERIFY(consumer.attach());
- }
-}
-#endif
-
-class Consumer : public QThread
-{
-
-public:
- void run()
- {
- QSharedMemory consumer(QLatin1String("market"));
- while (!consumer.attach()) {
- if (consumer.error() != QSharedMemory::NotFound)
- qDebug() << "consumer: failed to connect" << consumer.error() << consumer.errorString();
- QVERIFY(consumer.error() == QSharedMemory::NotFound || consumer.error() == QSharedMemory::KeyError);
- QTest::qWait(1);
- }
-
- char *memory = (char*)consumer.data();
-
- int i = 0;
- while (true) {
- if (!consumer.lock())
- break;
- if (memory[0] == 'Q')
- memory[0] = ++i;
- if (memory[0] == 'E') {
- memory[1]++;
- QVERIFY(consumer.unlock());
- break;
- }
- QVERIFY(consumer.unlock());
- QTest::qWait(1);
- }
-
- QVERIFY(consumer.detach());
- }
-};
-
-class Producer : public QThread
-{
-
-public:
- Producer() : producer(QLatin1String("market"))
- {
- int size = 1024;
- if (!producer.create(size)) {
- // left over from a crash...
- if (producer.error() == QSharedMemory::AlreadyExists) {
- producer.attach();
- producer.detach();
- QVERIFY(producer.create(size));
- }
- }
- }
-
- void run()
- {
-
- char *memory = (char*)producer.data();
- memory[1] = '0';
- QTime timer;
- timer.start();
- int i = 0;
- while (i < 5 && timer.elapsed() < 5000) {
- QVERIFY(producer.lock());
- if (memory[0] == 'Q') {
- QVERIFY(producer.unlock());
- QTest::qWait(1);
- continue;
- }
- ++i;
- memory[0] = 'Q';
- QVERIFY(producer.unlock());
- QTest::qWait(1);
- }
-
- // tell everyone to quit
- QVERIFY(producer.lock());
- memory[0] = 'E';
- QVERIFY(producer.unlock());
-
- }
-
- QSharedMemory producer;
-private:
-
-};
-
-void tst_QSharedMemory::simpleThreadedProducerConsumer_data()
-{
- QTest::addColumn<bool>("producerIsThread");
- QTest::addColumn<int>("threads");
- for (int i = 0; i < 5; ++i) {
- QTest::newRow("1 consumer, producer is thread") << true << 1;
- QTest::newRow("1 consumer, producer is this") << false << 1;
- QTest::newRow("5 consumers, producer is thread") << true << 5;
- QTest::newRow("5 consumers, producer is this") << false << 5;
- }
-}
-
-/*!
- The basic producer/consumer, but this time using threads.
- */
-void tst_QSharedMemory::simpleThreadedProducerConsumer()
-{
- QFETCH(bool, producerIsThread);
- QFETCH(int, threads);
- rememberKey(QLatin1String("market"));
-
-#if defined Q_OS_HPUX && defined __ia64
- QSKIP("This test locks up on gravlaks.troll.no");
-#endif
-
- Producer p;
- QVERIFY(p.producer.isAttached());
- if (producerIsThread)
- p.start();
-
- QList<Consumer*> consumers;
- for (int i = 0; i < threads; ++i) {
- consumers.append(new Consumer());
- consumers.last()->start();
- }
-
- if (!producerIsThread)
- p.run();
-
- p.wait(5000);
- while (!consumers.isEmpty()) {
- Consumer *c = consumers.first();
- QVERIFY(c->isFinished() || c->wait(5000));
- delete consumers.takeFirst();
- }
-}
-
-void tst_QSharedMemory::simpleProcessProducerConsumer_data()
-{
-#if QT_CONFIG(process)
- QTest::addColumn<int>("processes");
- int tries = 5;
- for (int i = 0; i < tries; ++i) {
- QTest::newRow("1 process") << 1;
- QTest::newRow("5 processes") << 5;
- }
-#endif
-}
-
-/*!
- Create external processes that produce and consume.
- */
-void tst_QSharedMemory::simpleProcessProducerConsumer()
-{
-#if !QT_CONFIG(process)
- QSKIP("No qprocess support", SkipAll);
-#else
- QFETCH(int, processes);
-
- QSKIP("This test is unstable: QTBUG-25655");
-
- rememberKey("market");
-
- QProcess producer;
- producer.start(m_helperBinary, QStringList("producer"));
- QVERIFY2(producer.waitForStarted(), "Could not start helper binary");
- QVERIFY2(producer.waitForReadyRead(), "Helper process failed to create shared memory segment: " +
- producer.readAllStandardError());
-
- QList<QProcess*> consumers;
- unsigned int failedProcesses = 0;
- const QStringList consumerArguments = QStringList("consumer");
- for (int i = 0; i < processes; ++i) {
- QProcess *p = new QProcess;
- p->setProcessChannelMode(QProcess::ForwardedChannels);
- p->start(m_helperBinary, consumerArguments);
- if (p->waitForStarted(2000))
- consumers.append(p);
- else
- ++failedProcesses;
- }
-
- bool consumerFailed = false;
-
- while (!consumers.isEmpty()) {
- QVERIFY(consumers.first()->waitForFinished(3000));
- if (consumers.first()->state() == QProcess::Running ||
- consumers.first()->exitStatus() != QProcess::NormalExit ||
- consumers.first()->exitCode() != 0) {
- consumerFailed = true;
- }
- delete consumers.takeFirst();
- }
- QCOMPARE(consumerFailed, false);
- QCOMPARE(failedProcesses, (unsigned int)(0));
-
- // tell the producer to exit now
- producer.write("", 1);
- producer.waitForBytesWritten();
- QVERIFY(producer.waitForFinished(5000));
-#endif
-}
-
-void tst_QSharedMemory::uniqueKey_data()
-{
- QTest::addColumn<QString>("key1");
- QTest::addColumn<QString>("key2");
-
- QTest::newRow("null == null") << QString() << QString();
- QTest::newRow("key == key") << QString("key") << QString("key");
- QTest::newRow("key1 == key1") << QString("key1") << QString("key1");
- QTest::newRow("key != key1") << QString("key") << QString("key1");
- QTest::newRow("ke1y != key1") << QString("ke1y") << QString("key1");
- QTest::newRow("key1 != key2") << QString("key1") << QString("key2");
- QTest::newRow("Noël -> Nol") << QString::fromUtf8("N\xc3\xabl") << QString("Nol");
-}
-
-void tst_QSharedMemory::uniqueKey()
-{
- QFETCH(QString, key1);
- QFETCH(QString, key2);
-
- QSharedMemory sm1(key1);
- QSharedMemory sm2(key2);
-
- bool setEqual = (key1 == key2);
- bool keyEqual = (sm1.key() == sm2.key());
- bool nativeEqual = (sm1.nativeKey() == sm2.nativeKey());
-
- QCOMPARE(keyEqual, setEqual);
- QCOMPARE(nativeEqual, setEqual);
-}
-
-QTEST_MAIN(tst_QSharedMemory)
-#include "tst_qsharedmemory.moc"
-
diff --git a/tests/auto/corelib/kernel/qsharedmemory/tst_qsharedmemory.cpp b/tests/auto/corelib/kernel/qsharedmemory/tst_qsharedmemory.cpp
new file mode 100644
index 0000000000..55deb8eb1a
--- /dev/null
+++ b/tests/auto/corelib/kernel/qsharedmemory/tst_qsharedmemory.cpp
@@ -0,0 +1,821 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QDebug>
+#include <QFile>
+#if QT_CONFIG(process)
+# include <QProcess>
+#endif
+#include <QSharedMemory>
+#include <QTest>
+#include <QThread>
+
+#define EXISTING_SHARE "existing"
+#define EXISTING_SIZE 1024
+
+Q_DECLARE_METATYPE(QSharedMemory::SharedMemoryError)
+Q_DECLARE_METATYPE(QSharedMemory::AccessMode)
+
+class tst_QSharedMemory : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QSharedMemory();
+ virtual ~tst_QSharedMemory();
+
+public Q_SLOTS:
+ void init();
+ void cleanup();
+
+
+private slots:
+ // basics
+ void constructor();
+ void key_data();
+ void key();
+ void create_data();
+ void create();
+ void attach_data();
+ void attach();
+ void lock();
+
+ // custom edge cases
+#ifndef Q_OS_HPUX
+ void removeWhileAttached();
+#endif
+ void emptyMemory();
+#if !defined(Q_OS_WIN)
+ void readOnly();
+#endif
+
+ // basics all together
+#ifndef Q_OS_HPUX
+ void simpleProducerConsumer_data();
+ void simpleProducerConsumer();
+ void simpleDoubleProducerConsumer();
+#endif
+
+ // with threads
+ void simpleThreadedProducerConsumer_data();
+ void simpleThreadedProducerConsumer();
+
+ // with processes
+ void simpleProcessProducerConsumer_data();
+ void simpleProcessProducerConsumer();
+
+ // extreme cases
+ void useTooMuchMemory();
+#if !defined(Q_OS_HPUX)
+ void attachTooMuch();
+#endif
+
+ // unique keys
+ void uniqueKey_data();
+ void uniqueKey();
+
+protected:
+ int remove(const QString &key);
+
+ QString rememberKey(const QString &key)
+ {
+ if (key == EXISTING_SHARE)
+ return key;
+ if (!keys.contains(key)) {
+ keys.append(key);
+ remove(key);
+ }
+ return key;
+ }
+
+ QStringList keys;
+ QList<QSharedMemory*> jail;
+ QSharedMemory *existingSharedMemory;
+
+private:
+ const QString m_helperBinary;
+};
+
+tst_QSharedMemory::tst_QSharedMemory()
+ : existingSharedMemory(0)
+ , m_helperBinary("producerconsumer_helper")
+{
+}
+
+tst_QSharedMemory::~tst_QSharedMemory()
+{
+}
+
+void tst_QSharedMemory::init()
+{
+ existingSharedMemory = new QSharedMemory(EXISTING_SHARE);
+ if (!existingSharedMemory->create(EXISTING_SIZE)) {
+ QCOMPARE(existingSharedMemory->error(), QSharedMemory::AlreadyExists);
+ }
+}
+
+void tst_QSharedMemory::cleanup()
+{
+ delete existingSharedMemory;
+ qDeleteAll(jail.begin(), jail.end());
+ jail.clear();
+
+ keys.append(EXISTING_SHARE);
+ for (int i = 0; i < keys.count(); ++i) {
+ QSharedMemory sm(keys.at(i));
+ if (!sm.create(1024)) {
+ //if (sm.error() != QSharedMemory::KeyError)
+ // qWarning() << "test cleanup: remove failed:" << keys.at(i) << sm.error() << sm.errorString();
+ sm.attach();
+ sm.detach();
+ remove(keys.at(i));
+ }
+ }
+}
+
+#ifndef Q_OS_WIN
+#include <private/qsharedmemory_p.h>
+#include <sys/types.h>
+#ifndef QT_POSIX_IPC
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#else
+#include <sys/mman.h>
+#endif // QT_POSIX_IPC
+#include <errno.h>
+#endif
+
+int tst_QSharedMemory::remove(const QString &key)
+{
+#ifdef Q_OS_WIN
+ Q_UNUSED(key);
+ return 0;
+#else
+ // On unix the shared memory might exists from a previously failed test
+ // or segfault, remove it it does
+ if (key.isEmpty())
+ return -1;
+
+ // ftok requires that an actual file exists somewhere
+ QString fileName = QSharedMemoryPrivate::makePlatformSafeKey(key);
+ if (!QFile::exists(fileName)) {
+ //qDebug() << "exits failed";
+ return -2;
+ }
+
+#ifndef QT_POSIX_IPC
+ int unix_key = ftok(fileName.toLatin1().constData(), 'Q');
+ if (-1 == unix_key) {
+ qDebug() << "ftok failed";
+ return -3;
+ }
+
+ int id = shmget(unix_key, 0, 0600);
+ if (-1 == id) {
+ qDebug() << "shmget failed" << strerror(errno);
+ return -4;
+ }
+
+ struct shmid_ds shmid_ds;
+ if (-1 == shmctl(id, IPC_RMID, &shmid_ds)) {
+ qDebug() << "shmctl failed";
+ return -5;
+ }
+#else
+ if (shm_unlink(QFile::encodeName(fileName).constData()) == -1) {
+ qDebug() << "shm_unlink failed";
+ return -5;
+ }
+#endif // QT_POSIX_IPC
+
+ return QFile::remove(fileName);
+#endif // Q_OS_WIN
+}
+
+/*!
+ Tests the default values
+ */
+void tst_QSharedMemory::constructor()
+{
+ QSharedMemory sm;
+ QCOMPARE(sm.key(), QString());
+ QVERIFY(!sm.isAttached());
+ QVERIFY(!sm.data());
+ QCOMPARE(sm.size(), 0);
+ QCOMPARE(sm.error(), QSharedMemory::NoError);
+ QCOMPARE(sm.errorString(), QString());
+}
+
+void tst_QSharedMemory::key_data()
+{
+ QTest::addColumn<QString>("constructorKey");
+ QTest::addColumn<QString>("setKey");
+ QTest::addColumn<QString>("setNativeKey");
+
+ QTest::newRow("null, null, null") << QString() << QString() << QString();
+ QTest::newRow("one, null, null") << QString("one") << QString() << QString();
+ QTest::newRow("null, one, null") << QString() << QString("one") << QString();
+ QTest::newRow("null, null, one") << QString() << QString() << QString("one");
+ QTest::newRow("one, two, null") << QString("one") << QString("two") << QString();
+ QTest::newRow("one, null, two") << QString("one") << QString() << QString("two");
+ QTest::newRow("null, one, two") << QString() << QString("one") << QString("two");
+ QTest::newRow("one, two, three") << QString("one") << QString("two") << QString("three");
+ QTest::newRow("invalid") << QString("o/e") << QString("t/o") << QString("|x");
+}
+
+/*!
+ Basic key testing
+ */
+void tst_QSharedMemory::key()
+{
+ QFETCH(QString, constructorKey);
+ QFETCH(QString, setKey);
+ QFETCH(QString, setNativeKey);
+
+ QSharedMemory sm(constructorKey);
+ QCOMPARE(sm.key(), constructorKey);
+ QCOMPARE(sm.nativeKey().isEmpty(), constructorKey.isEmpty());
+ sm.setKey(setKey);
+ QCOMPARE(sm.key(), setKey);
+ QCOMPARE(sm.nativeKey().isEmpty(), setKey.isEmpty());
+ sm.setNativeKey(setNativeKey);
+ QVERIFY(sm.key().isNull());
+ QCOMPARE(sm.nativeKey(), setNativeKey);
+ QCOMPARE(sm.isAttached(), false);
+
+ QCOMPARE(sm.error(), QSharedMemory::NoError);
+ QCOMPARE(sm.errorString(), QString());
+ QVERIFY(!sm.data());
+ QCOMPARE(sm.size(), 0);
+
+ QCOMPARE(sm.detach(), false);
+}
+
+void tst_QSharedMemory::create_data()
+{
+ QTest::addColumn<QString>("key");
+ QTest::addColumn<int>("size");
+ QTest::addColumn<bool>("canCreate");
+ QTest::addColumn<QSharedMemory::SharedMemoryError>("error");
+
+ QTest::newRow("null key") << QString() << 1024
+ << false << QSharedMemory::KeyError;
+ QTest::newRow("-1 size") << QString("negsize") << -1
+ << false << QSharedMemory::InvalidSize;
+ QTest::newRow("nor size") << QString("norsize") << 1024
+ << true << QSharedMemory::NoError;
+ QTest::newRow("already exists") << QString(EXISTING_SHARE) << EXISTING_SIZE
+ << false << QSharedMemory::AlreadyExists;
+}
+
+/*!
+ Basic create testing
+ */
+void tst_QSharedMemory::create()
+{
+ QFETCH(QString, key);
+ QFETCH(int, size);
+ QFETCH(bool, canCreate);
+ QFETCH(QSharedMemory::SharedMemoryError, error);
+
+ QSharedMemory sm(rememberKey(key));
+ QCOMPARE(sm.create(size), canCreate);
+ if (sm.error() != error)
+ qDebug() << sm.errorString();
+ QCOMPARE(sm.key(), key);
+ if (canCreate) {
+ QCOMPARE(sm.errorString(), QString());
+ QVERIFY(sm.data() != 0);
+ QVERIFY(sm.size() != 0);
+ } else {
+ QVERIFY(!sm.data());
+ QVERIFY(sm.errorString() != QString());
+ }
+}
+
+void tst_QSharedMemory::attach_data()
+{
+ QTest::addColumn<QString>("key");
+ QTest::addColumn<bool>("exists");
+ QTest::addColumn<QSharedMemory::SharedMemoryError>("error");
+
+ QTest::newRow("null key") << QString() << false << QSharedMemory::KeyError;
+ QTest::newRow("doesn't exists") << QString("doesntexists") << false << QSharedMemory::NotFound;
+
+ // HPUX doesn't allow for multiple attaches per process.
+#ifndef Q_OS_HPUX
+ QTest::newRow("already exists") << QString(EXISTING_SHARE) << true << QSharedMemory::NoError;
+#endif
+}
+
+/*!
+ Basic attach/detach testing
+ */
+void tst_QSharedMemory::attach()
+{
+ QFETCH(QString, key);
+ QFETCH(bool, exists);
+ QFETCH(QSharedMemory::SharedMemoryError, error);
+
+ QSharedMemory sm(key);
+ QCOMPARE(sm.attach(), exists);
+ QCOMPARE(sm.isAttached(), exists);
+ QCOMPARE(sm.error(), error);
+ QCOMPARE(sm.key(), key);
+ if (exists) {
+ QVERIFY(sm.data() != 0);
+ QVERIFY(sm.size() != 0);
+ QCOMPARE(sm.errorString(), QString());
+ QVERIFY(sm.detach());
+ // Make sure detach doesn't screw up something and we can't re-attach.
+ QVERIFY(sm.attach());
+ QVERIFY(sm.data() != 0);
+ QVERIFY(sm.size() != 0);
+ QVERIFY(sm.detach());
+ QCOMPARE(sm.size(), 0);
+ QVERIFY(!sm.data());
+ } else {
+ QVERIFY(!sm.data());
+ QCOMPARE(sm.size(), 0);
+ QVERIFY(sm.errorString() != QString());
+ QVERIFY(!sm.detach());
+ }
+}
+
+void tst_QSharedMemory::lock()
+{
+ QSharedMemory shm;
+ QVERIFY(!shm.lock());
+ QCOMPARE(shm.error(), QSharedMemory::LockError);
+
+ shm.setKey(QLatin1String("qsharedmemory"));
+
+ QVERIFY(!shm.lock());
+ QCOMPARE(shm.error(), QSharedMemory::LockError);
+
+ QVERIFY(shm.create(100));
+ QVERIFY(shm.lock());
+ QTest::ignoreMessage(QtWarningMsg, "QSharedMemory::lock: already locked");
+ QVERIFY(shm.lock());
+ // we didn't unlock(), so ignore the warning from auto-detach in destructor
+ QTest::ignoreMessage(QtWarningMsg, "QSharedMemory::lock: already locked");
+}
+
+/*!
+ Other shared memory are allowed to be attached after we remove,
+ but new shared memory are not allowed to attach after a remove.
+ */
+// HPUX doesn't allow for multiple attaches per process.
+#ifndef Q_OS_HPUX
+void tst_QSharedMemory::removeWhileAttached()
+{
+ rememberKey("one");
+
+ // attach 1
+ QSharedMemory *smOne = new QSharedMemory(QLatin1String("one"));
+ QVERIFY(smOne->create(1024));
+ QVERIFY(smOne->isAttached());
+
+ // attach 2
+ QSharedMemory *smTwo = new QSharedMemory(QLatin1String("one"));
+ QVERIFY(smTwo->attach());
+ QVERIFY(smTwo->isAttached());
+
+ // detach 1 and remove, remove one first to catch another error.
+ delete smOne;
+ delete smTwo;
+
+ // three shouldn't be able to attach
+ QSharedMemory smThree(QLatin1String("one"));
+ QVERIFY(!smThree.attach());
+ QCOMPARE(smThree.error(), QSharedMemory::NotFound);
+}
+#endif
+
+/*!
+ The memory should be set to 0 after created.
+ */
+void tst_QSharedMemory::emptyMemory()
+{
+ QSharedMemory sm(rememberKey(QLatin1String("voidland")));
+ int size = 1024;
+ QVERIFY(sm.create(size, QSharedMemory::ReadOnly));
+ char *get = (char*)sm.data();
+ char null = 0;
+ for (int i = 0; i < size; ++i)
+ QCOMPARE(get[i], null);
+}
+
+/*!
+ Verify that attach with ReadOnly is actually read only
+ by writing to data and causing a segfault.
+*/
+// This test opens a crash dialog on Windows.
+#if !defined(Q_OS_WIN)
+void tst_QSharedMemory::readOnly()
+{
+#if !QT_CONFIG(process)
+ QSKIP("No qprocess support", SkipAll);
+#elif defined(Q_OS_MACOS)
+ QSKIP("QTBUG-59936: Times out on macOS", SkipAll);
+#else
+ rememberKey("readonly_segfault");
+ // ### on windows disable the popup somehow
+ QProcess p;
+ p.start(m_helperBinary, QStringList("readonly_segfault"));
+ p.setProcessChannelMode(QProcess::ForwardedChannels);
+ p.waitForFinished();
+ QCOMPARE(p.error(), QProcess::Crashed);
+#endif
+}
+#endif
+
+/*!
+ Keep making shared memory until the kernel stops us.
+ */
+void tst_QSharedMemory::useTooMuchMemory()
+{
+#ifdef Q_OS_LINUX
+ bool success = true;
+ int count = 0;
+ while (success) {
+ QString key = QLatin1String("maxmemorytest_") + QString::number(count++);
+ QSharedMemory *sm = new QSharedMemory(rememberKey(key));
+ QVERIFY(sm);
+ jail.append(sm);
+ int size = 32768 * 1024;
+ success = sm->create(size);
+ if (!success && sm->error() == QSharedMemory::AlreadyExists) {
+ // left over from a crash, clean it up
+ sm->attach();
+ sm->detach();
+ success = sm->create(size);
+ }
+
+ if (!success) {
+ QVERIFY(!sm->isAttached());
+ QCOMPARE(sm->key(), key);
+ QCOMPARE(sm->size(), 0);
+ QVERIFY(!sm->data());
+ if (sm->error() != QSharedMemory::OutOfResources)
+ qDebug() << sm->error() << sm->errorString();
+ // ### Linux won't return OutOfResources if there are not enough semaphores to use.
+ QVERIFY(sm->error() == QSharedMemory::OutOfResources
+ || sm->error() == QSharedMemory::LockError);
+ QVERIFY(sm->errorString() != QString());
+ QVERIFY(!sm->attach());
+ QVERIFY(!sm->detach());
+ } else {
+ QVERIFY(sm->isAttached());
+ }
+ }
+#endif
+}
+
+/*!
+ Create one shared memory (government) and see how many other shared memories (wars) we can
+ attach before the system runs out of resources.
+ */
+// HPUX doesn't allow for multiple attaches per process.
+#if !defined(Q_OS_HPUX)
+void tst_QSharedMemory::attachTooMuch()
+{
+ QSKIP("disabled");
+
+ QSharedMemory government(rememberKey("government"));
+ QVERIFY(government.create(1024));
+ while (true) {
+ QSharedMemory *war = new QSharedMemory(government.key());
+ QVERIFY(war);
+ jail.append(war);
+ if (!war->attach()) {
+ QVERIFY(!war->isAttached());
+ QCOMPARE(war->key(), government.key());
+ QCOMPARE(war->size(), 0);
+ QVERIFY(!war->data());
+ QCOMPARE(war->error(), QSharedMemory::OutOfResources);
+ QVERIFY(war->errorString() != QString());
+ QVERIFY(!war->detach());
+ break;
+ } else {
+ QVERIFY(war->isAttached());
+ }
+ }
+}
+#endif
+
+// HPUX doesn't allow for multiple attaches per process.
+#ifndef Q_OS_HPUX
+void tst_QSharedMemory::simpleProducerConsumer_data()
+{
+ QTest::addColumn<QSharedMemory::AccessMode>("mode");
+
+ QTest::newRow("readonly") << QSharedMemory::ReadOnly;
+ QTest::newRow("readwrite") << QSharedMemory::ReadWrite;
+}
+
+/*!
+ The basic consumer producer that rounds out the basic testing.
+ If this fails then any muli-threading/process might fail (but be
+ harder to debug)
+
+ This doesn't require nor test any locking system.
+ */
+void tst_QSharedMemory::simpleProducerConsumer()
+{
+ QFETCH(QSharedMemory::AccessMode, mode);
+
+ rememberKey(QLatin1String("market"));
+ QSharedMemory producer(QLatin1String("market"));
+ QSharedMemory consumer(QLatin1String("market"));
+ int size = 512;
+ QVERIFY(producer.create(size));
+ QVERIFY(consumer.attach(mode));
+
+ char *put = (char*)producer.data();
+ char *get = (char*)consumer.data();
+ // On Windows CE you always have ReadWrite access. Thus
+ // ViewMapOfFile returns the same pointer
+ QVERIFY(put != get);
+ for (int i = 0; i < size; ++i) {
+ put[i] = 'Q';
+ QCOMPARE(get[i], 'Q');
+ }
+ QVERIFY(consumer.detach());
+}
+#endif
+
+// HPUX doesn't allow for multiple attaches per process.
+#ifndef Q_OS_HPUX
+void tst_QSharedMemory::simpleDoubleProducerConsumer()
+{
+ rememberKey(QLatin1String("market"));
+ QSharedMemory producer(QLatin1String("market"));
+ int size = 512;
+ QVERIFY(producer.create(size));
+ QVERIFY(producer.detach());
+ QVERIFY(producer.create(size));
+
+ {
+ QSharedMemory consumer(QLatin1String("market"));
+ QVERIFY(consumer.attach());
+ }
+}
+#endif
+
+class Consumer : public QThread
+{
+
+public:
+ void run()
+ {
+ QSharedMemory consumer(QLatin1String("market"));
+ while (!consumer.attach()) {
+ if (consumer.error() != QSharedMemory::NotFound)
+ qDebug() << "consumer: failed to connect" << consumer.error() << consumer.errorString();
+ QVERIFY(consumer.error() == QSharedMemory::NotFound || consumer.error() == QSharedMemory::KeyError);
+ QTest::qWait(1);
+ }
+
+ char *memory = (char*)consumer.data();
+
+ int i = 0;
+ while (true) {
+ if (!consumer.lock())
+ break;
+ if (memory[0] == 'Q')
+ memory[0] = ++i;
+ if (memory[0] == 'E') {
+ memory[1]++;
+ QVERIFY(consumer.unlock());
+ break;
+ }
+ QVERIFY(consumer.unlock());
+ QTest::qWait(1);
+ }
+
+ QVERIFY(consumer.detach());
+ }
+};
+
+class Producer : public QThread
+{
+
+public:
+ Producer() : producer(QLatin1String("market"))
+ {
+ int size = 1024;
+ if (!producer.create(size)) {
+ // left over from a crash...
+ if (producer.error() == QSharedMemory::AlreadyExists) {
+ producer.attach();
+ producer.detach();
+ QVERIFY(producer.create(size));
+ }
+ }
+ }
+
+ void run()
+ {
+
+ char *memory = (char*)producer.data();
+ memory[1] = '0';
+ QTime timer;
+ timer.start();
+ int i = 0;
+ while (i < 5 && timer.elapsed() < 5000) {
+ QVERIFY(producer.lock());
+ if (memory[0] == 'Q') {
+ QVERIFY(producer.unlock());
+ QTest::qWait(1);
+ continue;
+ }
+ ++i;
+ memory[0] = 'Q';
+ QVERIFY(producer.unlock());
+ QTest::qWait(1);
+ }
+
+ // tell everyone to quit
+ QVERIFY(producer.lock());
+ memory[0] = 'E';
+ QVERIFY(producer.unlock());
+
+ }
+
+ QSharedMemory producer;
+private:
+
+};
+
+void tst_QSharedMemory::simpleThreadedProducerConsumer_data()
+{
+ QTest::addColumn<bool>("producerIsThread");
+ QTest::addColumn<int>("threads");
+ for (int i = 0; i < 5; ++i) {
+ QTest::newRow("1 consumer, producer is thread") << true << 1;
+ QTest::newRow("1 consumer, producer is this") << false << 1;
+ QTest::newRow("5 consumers, producer is thread") << true << 5;
+ QTest::newRow("5 consumers, producer is this") << false << 5;
+ }
+}
+
+/*!
+ The basic producer/consumer, but this time using threads.
+ */
+void tst_QSharedMemory::simpleThreadedProducerConsumer()
+{
+ QFETCH(bool, producerIsThread);
+ QFETCH(int, threads);
+ rememberKey(QLatin1String("market"));
+
+#if defined Q_OS_HPUX && defined __ia64
+ QSKIP("This test locks up on gravlaks.troll.no");
+#endif
+
+ Producer p;
+ QVERIFY(p.producer.isAttached());
+ if (producerIsThread)
+ p.start();
+
+ QList<Consumer*> consumers;
+ for (int i = 0; i < threads; ++i) {
+ consumers.append(new Consumer());
+ consumers.last()->start();
+ }
+
+ if (!producerIsThread)
+ p.run();
+
+ p.wait(5000);
+ while (!consumers.isEmpty()) {
+ Consumer *c = consumers.first();
+ QVERIFY(c->isFinished() || c->wait(5000));
+ delete consumers.takeFirst();
+ }
+}
+
+void tst_QSharedMemory::simpleProcessProducerConsumer_data()
+{
+#if QT_CONFIG(process)
+ QTest::addColumn<int>("processes");
+ int tries = 5;
+ for (int i = 0; i < tries; ++i) {
+ QTest::newRow("1 process") << 1;
+ QTest::newRow("5 processes") << 5;
+ }
+#endif
+}
+
+/*!
+ Create external processes that produce and consume.
+ */
+void tst_QSharedMemory::simpleProcessProducerConsumer()
+{
+#if !QT_CONFIG(process)
+ QSKIP("No qprocess support", SkipAll);
+#else
+ QFETCH(int, processes);
+
+ QSKIP("This test is unstable: QTBUG-25655");
+
+ rememberKey("market");
+
+ QProcess producer;
+ producer.start(m_helperBinary, QStringList("producer"));
+ QVERIFY2(producer.waitForStarted(), "Could not start helper binary");
+ QVERIFY2(producer.waitForReadyRead(), "Helper process failed to create shared memory segment: " +
+ producer.readAllStandardError());
+
+ QList<QProcess*> consumers;
+ unsigned int failedProcesses = 0;
+ const QStringList consumerArguments = QStringList("consumer");
+ for (int i = 0; i < processes; ++i) {
+ QProcess *p = new QProcess;
+ p->setProcessChannelMode(QProcess::ForwardedChannels);
+ p->start(m_helperBinary, consumerArguments);
+ if (p->waitForStarted(2000))
+ consumers.append(p);
+ else
+ ++failedProcesses;
+ }
+
+ bool consumerFailed = false;
+
+ while (!consumers.isEmpty()) {
+ QVERIFY(consumers.first()->waitForFinished(3000));
+ if (consumers.first()->state() == QProcess::Running ||
+ consumers.first()->exitStatus() != QProcess::NormalExit ||
+ consumers.first()->exitCode() != 0) {
+ consumerFailed = true;
+ }
+ delete consumers.takeFirst();
+ }
+ QCOMPARE(consumerFailed, false);
+ QCOMPARE(failedProcesses, (unsigned int)(0));
+
+ // tell the producer to exit now
+ producer.write("", 1);
+ producer.waitForBytesWritten();
+ QVERIFY(producer.waitForFinished(5000));
+#endif
+}
+
+void tst_QSharedMemory::uniqueKey_data()
+{
+ QTest::addColumn<QString>("key1");
+ QTest::addColumn<QString>("key2");
+
+ QTest::newRow("null == null") << QString() << QString();
+ QTest::newRow("key == key") << QString("key") << QString("key");
+ QTest::newRow("key1 == key1") << QString("key1") << QString("key1");
+ QTest::newRow("key != key1") << QString("key") << QString("key1");
+ QTest::newRow("ke1y != key1") << QString("ke1y") << QString("key1");
+ QTest::newRow("key1 != key2") << QString("key1") << QString("key2");
+ QTest::newRow("Noël -> Nol") << QString::fromUtf8("N\xc3\xabl") << QString("Nol");
+}
+
+void tst_QSharedMemory::uniqueKey()
+{
+ QFETCH(QString, key1);
+ QFETCH(QString, key2);
+
+ QSharedMemory sm1(key1);
+ QSharedMemory sm2(key2);
+
+ bool setEqual = (key1 == key2);
+ bool keyEqual = (sm1.key() == sm2.key());
+ bool nativeEqual = (sm1.nativeKey() == sm2.nativeKey());
+
+ QCOMPARE(keyEqual, setEqual);
+ QCOMPARE(nativeEqual, setEqual);
+}
+
+QTEST_MAIN(tst_QSharedMemory)
+#include "tst_qsharedmemory.moc"
+
diff --git a/tests/auto/corelib/kernel/qsystemsemaphore/acquirerelease/acquirerelease.pro b/tests/auto/corelib/kernel/qsystemsemaphore/acquirerelease/acquirerelease.pro
new file mode 100644
index 0000000000..a6156ed5b6
--- /dev/null
+++ b/tests/auto/corelib/kernel/qsystemsemaphore/acquirerelease/acquirerelease.pro
@@ -0,0 +1,5 @@
+QT = core testlib
+
+SOURCES += main.cpp
+
+load(qt_test_helper)
diff --git a/tests/auto/corelib/kernel/qsystemsemaphore/systemsemaphorehelper/main.cpp b/tests/auto/corelib/kernel/qsystemsemaphore/acquirerelease/main.cpp
index 7bfb6b16cc..7bfb6b16cc 100644
--- a/tests/auto/corelib/kernel/qsystemsemaphore/systemsemaphorehelper/main.cpp
+++ b/tests/auto/corelib/kernel/qsystemsemaphore/acquirerelease/main.cpp
diff --git a/tests/auto/corelib/kernel/qsystemsemaphore/qsystemsemaphore.pro b/tests/auto/corelib/kernel/qsystemsemaphore/qsystemsemaphore.pro
index f8a49254d2..70526426aa 100644
--- a/tests/auto/corelib/kernel/qsystemsemaphore/qsystemsemaphore.pro
+++ b/tests/auto/corelib/kernel/qsystemsemaphore/qsystemsemaphore.pro
@@ -1,3 +1,3 @@
TEMPLATE = subdirs
-SUBDIRS = systemsemaphorehelper test
+SUBDIRS = acquirerelease test.pro
diff --git a/tests/auto/corelib/kernel/qsystemsemaphore/systemsemaphorehelper/systemsemaphorehelper.pro b/tests/auto/corelib/kernel/qsystemsemaphore/systemsemaphorehelper/systemsemaphorehelper.pro
deleted file mode 100644
index 389015d504..0000000000
--- a/tests/auto/corelib/kernel/qsystemsemaphore/systemsemaphorehelper/systemsemaphorehelper.pro
+++ /dev/null
@@ -1,17 +0,0 @@
-QT = core testlib
-
-win32: CONFIG += console
-mac:CONFIG -= app_bundle
-
-SOURCES += main.cpp
-TARGET = helperbinary
-
-CONFIG(debug_and_release) {
- CONFIG(debug, debug|release) {
- DESTDIR = ../debug
- } else {
- DESTDIR = ../release
- }
-} else {
- DESTDIR = ..
-}
diff --git a/tests/auto/corelib/kernel/qsystemsemaphore/test.pro b/tests/auto/corelib/kernel/qsystemsemaphore/test.pro
new file mode 100644
index 0000000000..13bd1fa270
--- /dev/null
+++ b/tests/auto/corelib/kernel/qsystemsemaphore/test.pro
@@ -0,0 +1,7 @@
+CONFIG += testcase
+QT = core testlib
+
+SOURCES += tst_qsystemsemaphore.cpp
+TARGET = tst_qsystemsemaphore
+
+win32: CONFIG += console
diff --git a/tests/auto/corelib/kernel/qsystemsemaphore/test/test.pro b/tests/auto/corelib/kernel/qsystemsemaphore/test/test.pro
deleted file mode 100644
index f60207eb01..0000000000
--- a/tests/auto/corelib/kernel/qsystemsemaphore/test/test.pro
+++ /dev/null
@@ -1,17 +0,0 @@
-CONFIG += testcase
-QT = core testlib
-
-win32: CONFIG += console
-
-SOURCES += tst_qsystemsemaphore.cpp
-TARGET = tst_qsystemsemaphore
-
-CONFIG(debug_and_release) {
- CONFIG(debug, debug|release) {
- DESTDIR = ../debug
- } else {
- DESTDIR = ../release
- }
-} else {
- DESTDIR = ..
-}
diff --git a/tests/auto/corelib/kernel/qsystemsemaphore/test/tst_qsystemsemaphore.cpp b/tests/auto/corelib/kernel/qsystemsemaphore/test/tst_qsystemsemaphore.cpp
deleted file mode 100644
index 6ff1e14976..0000000000
--- a/tests/auto/corelib/kernel/qsystemsemaphore/test/tst_qsystemsemaphore.cpp
+++ /dev/null
@@ -1,307 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtTest/QtTest>
-#include <QtCore/QSystemSemaphore>
-#include <QtCore/QVector>
-#include <QtCore/QTemporaryDir>
-
-#define EXISTING_SHARE "existing"
-#define HELPERWAITTIME 10000
-
-class tst_QSystemSemaphore : public QObject
-{
- Q_OBJECT
-
-public:
- tst_QSystemSemaphore();
-
-public Q_SLOTS:
- void initTestCase();
- void init();
- void cleanup();
-
-private slots:
- void key_data();
- void key();
-
- void basicacquire();
- void complexacquire();
- void release();
-
- void basicProcesses();
-
- void processes_data();
- void processes();
-
-#if !defined(Q_OS_WIN) && !defined(QT_POSIX_IPC)
- void undo();
-#endif
- void initialValue();
-
-private:
- static QString helperBinary();
- QSystemSemaphore *existingLock;
-
- const QString m_helperBinary;
-};
-
-tst_QSystemSemaphore::tst_QSystemSemaphore()
- : m_helperBinary(helperBinary())
-{
-}
-
-void tst_QSystemSemaphore::initTestCase()
-{
- QVERIFY2(!m_helperBinary.isEmpty(), "Could not find helper binary");
-}
-
-void tst_QSystemSemaphore::init()
-{
- existingLock = new QSystemSemaphore(EXISTING_SHARE, 1, QSystemSemaphore::Create);
-}
-
-void tst_QSystemSemaphore::cleanup()
-{
- delete existingLock;
-}
-
-void tst_QSystemSemaphore::key_data()
-{
- QTest::addColumn<QString>("constructorKey");
- QTest::addColumn<QString>("setKey");
-
- QTest::newRow("null, null") << QString() << QString();
- QTest::newRow("null, one") << QString() << QString("one");
- QTest::newRow("one, two") << QString("one") << QString("two");
-}
-
-/*!
- Basic key testing
- */
-void tst_QSystemSemaphore::key()
-{
- QFETCH(QString, constructorKey);
- QFETCH(QString, setKey);
-
- QSystemSemaphore sem(constructorKey);
- QCOMPARE(sem.key(), constructorKey);
- QCOMPARE(sem.error(), QSystemSemaphore::NoError);
- QCOMPARE(sem.errorString(), QString());
-
- sem.setKey(setKey);
- QCOMPARE(sem.key(), setKey);
- QCOMPARE(sem.error(), QSystemSemaphore::NoError);
- QCOMPARE(sem.errorString(), QString());
-}
-
-void tst_QSystemSemaphore::basicacquire()
-{
- QSystemSemaphore sem("QSystemSemaphore_basicacquire", 1, QSystemSemaphore::Create);
- QVERIFY(sem.acquire());
- QCOMPARE(sem.error(), QSystemSemaphore::NoError);
- QVERIFY(sem.release());
- QCOMPARE(sem.error(), QSystemSemaphore::NoError);
- QCOMPARE(sem.errorString(), QString());
-}
-
-void tst_QSystemSemaphore::complexacquire()
-{
- QSystemSemaphore sem("QSystemSemaphore_complexacquire", 2, QSystemSemaphore::Create);
- QVERIFY(sem.acquire());
- QCOMPARE(sem.error(), QSystemSemaphore::NoError);
- QVERIFY(sem.release());
- QCOMPARE(sem.error(), QSystemSemaphore::NoError);
- QVERIFY(sem.acquire());
- QCOMPARE(sem.error(), QSystemSemaphore::NoError);
- QVERIFY(sem.release());
- QCOMPARE(sem.error(), QSystemSemaphore::NoError);
- QVERIFY(sem.acquire());
- QCOMPARE(sem.error(), QSystemSemaphore::NoError);
- QVERIFY(sem.acquire());
- QCOMPARE(sem.error(), QSystemSemaphore::NoError);
- QVERIFY(sem.release());
- QCOMPARE(sem.error(), QSystemSemaphore::NoError);
- QVERIFY(sem.release());
- QCOMPARE(sem.error(), QSystemSemaphore::NoError);
- QCOMPARE(sem.errorString(), QString());
-}
-
-void tst_QSystemSemaphore::release()
-{
- QSystemSemaphore sem("QSystemSemaphore_release", 0, QSystemSemaphore::Create);
- QVERIFY(sem.release());
- QCOMPARE(sem.error(), QSystemSemaphore::NoError);
- QVERIFY(sem.release());
- QCOMPARE(sem.error(), QSystemSemaphore::NoError);
- QVERIFY(sem.acquire());
- QCOMPARE(sem.error(), QSystemSemaphore::NoError);
- QVERIFY(sem.acquire());
- QCOMPARE(sem.error(), QSystemSemaphore::NoError);
- QVERIFY(sem.release());
- QCOMPARE(sem.error(), QSystemSemaphore::NoError);
- QVERIFY(sem.release());
- QCOMPARE(sem.error(), QSystemSemaphore::NoError);
- QCOMPARE(sem.errorString(), QString());
-}
-
-void tst_QSystemSemaphore::basicProcesses()
-{
-#if !QT_CONFIG(process)
- QSKIP("No qprocess support", SkipAll);
-#else
- QSystemSemaphore sem("store", 0, QSystemSemaphore::Create);
-
- QProcess acquire;
- acquire.setProcessChannelMode(QProcess::ForwardedChannels);
-
- QProcess release;
- release.setProcessChannelMode(QProcess::ForwardedChannels);
-
- acquire.start(m_helperBinary, QStringList("acquire"));
- QVERIFY2(acquire.waitForStarted(), "Could not start helper binary");
- acquire.waitForFinished(HELPERWAITTIME);
- QCOMPARE(acquire.state(), QProcess::Running);
- acquire.kill();
- release.start(m_helperBinary, QStringList("release"));
- QVERIFY2(release.waitForStarted(), "Could not start helper binary");
- acquire.waitForFinished(HELPERWAITTIME);
- release.waitForFinished(HELPERWAITTIME);
- QCOMPARE(acquire.state(), QProcess::NotRunning);
-#endif
-}
-
-void tst_QSystemSemaphore::processes_data()
-{
- QTest::addColumn<int>("processes");
- for (int i = 0; i < 5; ++i) {
- QTest::newRow("1 process") << 1;
- QTest::newRow("3 process") << 3;
- QTest::newRow("10 process") << 10;
- }
-}
-
-void tst_QSystemSemaphore::processes()
-{
-#if !QT_CONFIG(process)
- QSKIP("No qprocess support", SkipAll);
-#else
- QSystemSemaphore sem("store", 1, QSystemSemaphore::Create);
-
- QFETCH(int, processes);
- QVector<QString> scripts(processes, "acquirerelease");
-
- QList<QProcess*> consumers;
- for (int i = 0; i < scripts.count(); ++i) {
- QProcess *p = new QProcess;
- p->setProcessChannelMode(QProcess::ForwardedChannels);
- consumers.append(p);
- p->start(m_helperBinary, QStringList(scripts.at(i)));
- }
-
- while (!consumers.isEmpty()) {
- consumers.first()->waitForFinished();
- QCOMPARE(consumers.first()->exitStatus(), QProcess::NormalExit);
- QCOMPARE(consumers.first()->exitCode(), 0);
- delete consumers.takeFirst();
- }
-#endif
-}
-
-// This test only checks a system v unix behavior.
-#if !defined(Q_OS_WIN) && !defined(QT_POSIX_IPC)
-void tst_QSystemSemaphore::undo()
-{
-#if !QT_CONFIG(process)
- QSKIP("No qprocess support", SkipAll);
-#else
- QSystemSemaphore sem("store", 1, QSystemSemaphore::Create);
-
- QStringList acquireArguments = QStringList("acquire");
- QProcess acquire;
- acquire.setProcessChannelMode(QProcess::ForwardedChannels);
- acquire.start(m_helperBinary, acquireArguments);
- QVERIFY2(acquire.waitForStarted(), "Could not start helper binary");
- acquire.waitForFinished(HELPERWAITTIME);
- QVERIFY(acquire.state()== QProcess::NotRunning);
-
- // At process exit the kernel should auto undo
-
- acquire.start(m_helperBinary, acquireArguments);
- QVERIFY2(acquire.waitForStarted(), "Could not start helper binary");
- acquire.waitForFinished(HELPERWAITTIME);
- QVERIFY(acquire.state()== QProcess::NotRunning);
-#endif
-}
-#endif
-
-void tst_QSystemSemaphore::initialValue()
-{
-#if !QT_CONFIG(process)
- QSKIP("No qprocess support", SkipAll);
-#else
- QSystemSemaphore sem("store", 1, QSystemSemaphore::Create);
-
- QStringList acquireArguments = QStringList("acquire");
- QStringList releaseArguments = QStringList("release");
- QProcess acquire;
- acquire.setProcessChannelMode(QProcess::ForwardedChannels);
-
- QProcess release;
- release.setProcessChannelMode(QProcess::ForwardedChannels);
-
- acquire.start(m_helperBinary, acquireArguments);
- QVERIFY2(acquire.waitForStarted(), "Could not start helper binary");
- acquire.waitForFinished(HELPERWAITTIME);
- QVERIFY(acquire.state()== QProcess::NotRunning);
-
- acquire.start(m_helperBinary, acquireArguments << QLatin1String("2"));
- QVERIFY2(acquire.waitForStarted(), "Could not start helper binary");
- acquire.waitForFinished(HELPERWAITTIME);
- QVERIFY(acquire.state()== QProcess::Running);
- acquire.kill();
-
- release.start(m_helperBinary, releaseArguments);
- QVERIFY2(release.waitForStarted(), "Could not start helper binary");
- acquire.waitForFinished(HELPERWAITTIME);
- release.waitForFinished(HELPERWAITTIME);
- QVERIFY(acquire.state()== QProcess::NotRunning);
-#endif
-}
-
-QString tst_QSystemSemaphore::helperBinary()
-{
- QString binary = QStringLiteral("helperbinary");
-#ifdef Q_OS_WIN
- binary += QStringLiteral(".exe");
-#endif
- return QFINDTESTDATA(binary);
-}
-QTEST_MAIN(tst_QSystemSemaphore)
-#include "tst_qsystemsemaphore.moc"
-
diff --git a/tests/auto/corelib/kernel/qsystemsemaphore/tst_qsystemsemaphore.cpp b/tests/auto/corelib/kernel/qsystemsemaphore/tst_qsystemsemaphore.cpp
new file mode 100644
index 0000000000..5f010ae3d1
--- /dev/null
+++ b/tests/auto/corelib/kernel/qsystemsemaphore/tst_qsystemsemaphore.cpp
@@ -0,0 +1,292 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtCore/QSystemSemaphore>
+#include <QtCore/QVector>
+#include <QtCore/QTemporaryDir>
+
+#define EXISTING_SHARE "existing"
+#define HELPERWAITTIME 10000
+
+class tst_QSystemSemaphore : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QSystemSemaphore();
+
+public Q_SLOTS:
+ void init();
+ void cleanup();
+
+private slots:
+ void key_data();
+ void key();
+
+ void basicacquire();
+ void complexacquire();
+ void release();
+
+ void basicProcesses();
+
+ void processes_data();
+ void processes();
+
+#if !defined(Q_OS_WIN) && !defined(QT_POSIX_IPC)
+ void undo();
+#endif
+ void initialValue();
+
+private:
+ QSystemSemaphore *existingLock;
+
+ const QString m_helperBinary;
+};
+
+tst_QSystemSemaphore::tst_QSystemSemaphore()
+ : m_helperBinary("acquirerelease_helper")
+{
+}
+
+void tst_QSystemSemaphore::init()
+{
+ existingLock = new QSystemSemaphore(EXISTING_SHARE, 1, QSystemSemaphore::Create);
+}
+
+void tst_QSystemSemaphore::cleanup()
+{
+ delete existingLock;
+}
+
+void tst_QSystemSemaphore::key_data()
+{
+ QTest::addColumn<QString>("constructorKey");
+ QTest::addColumn<QString>("setKey");
+
+ QTest::newRow("null, null") << QString() << QString();
+ QTest::newRow("null, one") << QString() << QString("one");
+ QTest::newRow("one, two") << QString("one") << QString("two");
+}
+
+/*!
+ Basic key testing
+ */
+void tst_QSystemSemaphore::key()
+{
+ QFETCH(QString, constructorKey);
+ QFETCH(QString, setKey);
+
+ QSystemSemaphore sem(constructorKey);
+ QCOMPARE(sem.key(), constructorKey);
+ QCOMPARE(sem.error(), QSystemSemaphore::NoError);
+ QCOMPARE(sem.errorString(), QString());
+
+ sem.setKey(setKey);
+ QCOMPARE(sem.key(), setKey);
+ QCOMPARE(sem.error(), QSystemSemaphore::NoError);
+ QCOMPARE(sem.errorString(), QString());
+}
+
+void tst_QSystemSemaphore::basicacquire()
+{
+ QSystemSemaphore sem("QSystemSemaphore_basicacquire", 1, QSystemSemaphore::Create);
+ QVERIFY(sem.acquire());
+ QCOMPARE(sem.error(), QSystemSemaphore::NoError);
+ QVERIFY(sem.release());
+ QCOMPARE(sem.error(), QSystemSemaphore::NoError);
+ QCOMPARE(sem.errorString(), QString());
+}
+
+void tst_QSystemSemaphore::complexacquire()
+{
+ QSystemSemaphore sem("QSystemSemaphore_complexacquire", 2, QSystemSemaphore::Create);
+ QVERIFY(sem.acquire());
+ QCOMPARE(sem.error(), QSystemSemaphore::NoError);
+ QVERIFY(sem.release());
+ QCOMPARE(sem.error(), QSystemSemaphore::NoError);
+ QVERIFY(sem.acquire());
+ QCOMPARE(sem.error(), QSystemSemaphore::NoError);
+ QVERIFY(sem.release());
+ QCOMPARE(sem.error(), QSystemSemaphore::NoError);
+ QVERIFY(sem.acquire());
+ QCOMPARE(sem.error(), QSystemSemaphore::NoError);
+ QVERIFY(sem.acquire());
+ QCOMPARE(sem.error(), QSystemSemaphore::NoError);
+ QVERIFY(sem.release());
+ QCOMPARE(sem.error(), QSystemSemaphore::NoError);
+ QVERIFY(sem.release());
+ QCOMPARE(sem.error(), QSystemSemaphore::NoError);
+ QCOMPARE(sem.errorString(), QString());
+}
+
+void tst_QSystemSemaphore::release()
+{
+ QSystemSemaphore sem("QSystemSemaphore_release", 0, QSystemSemaphore::Create);
+ QVERIFY(sem.release());
+ QCOMPARE(sem.error(), QSystemSemaphore::NoError);
+ QVERIFY(sem.release());
+ QCOMPARE(sem.error(), QSystemSemaphore::NoError);
+ QVERIFY(sem.acquire());
+ QCOMPARE(sem.error(), QSystemSemaphore::NoError);
+ QVERIFY(sem.acquire());
+ QCOMPARE(sem.error(), QSystemSemaphore::NoError);
+ QVERIFY(sem.release());
+ QCOMPARE(sem.error(), QSystemSemaphore::NoError);
+ QVERIFY(sem.release());
+ QCOMPARE(sem.error(), QSystemSemaphore::NoError);
+ QCOMPARE(sem.errorString(), QString());
+}
+
+void tst_QSystemSemaphore::basicProcesses()
+{
+#if !QT_CONFIG(process)
+ QSKIP("No qprocess support", SkipAll);
+#else
+ QSystemSemaphore sem("store", 0, QSystemSemaphore::Create);
+
+ QProcess acquire;
+ acquire.setProcessChannelMode(QProcess::ForwardedChannels);
+
+ QProcess release;
+ release.setProcessChannelMode(QProcess::ForwardedChannels);
+
+ acquire.start(m_helperBinary, QStringList("acquire"));
+ QVERIFY2(acquire.waitForStarted(), "Could not start helper binary");
+ acquire.waitForFinished(HELPERWAITTIME);
+ QCOMPARE(acquire.state(), QProcess::Running);
+ acquire.kill();
+ release.start(m_helperBinary, QStringList("release"));
+ QVERIFY2(release.waitForStarted(), "Could not start helper binary");
+ acquire.waitForFinished(HELPERWAITTIME);
+ release.waitForFinished(HELPERWAITTIME);
+ QCOMPARE(acquire.state(), QProcess::NotRunning);
+#endif
+}
+
+void tst_QSystemSemaphore::processes_data()
+{
+ QTest::addColumn<int>("processes");
+ for (int i = 0; i < 5; ++i) {
+ QTest::newRow("1 process") << 1;
+ QTest::newRow("3 process") << 3;
+ QTest::newRow("10 process") << 10;
+ }
+}
+
+void tst_QSystemSemaphore::processes()
+{
+#if !QT_CONFIG(process)
+ QSKIP("No qprocess support", SkipAll);
+#else
+ QSystemSemaphore sem("store", 1, QSystemSemaphore::Create);
+
+ QFETCH(int, processes);
+ QVector<QString> scripts(processes, "acquirerelease");
+
+ QList<QProcess*> consumers;
+ for (int i = 0; i < scripts.count(); ++i) {
+ QProcess *p = new QProcess;
+ p->setProcessChannelMode(QProcess::ForwardedChannels);
+ consumers.append(p);
+ p->start(m_helperBinary, QStringList(scripts.at(i)));
+ }
+
+ while (!consumers.isEmpty()) {
+ consumers.first()->waitForFinished();
+ QCOMPARE(consumers.first()->exitStatus(), QProcess::NormalExit);
+ QCOMPARE(consumers.first()->exitCode(), 0);
+ delete consumers.takeFirst();
+ }
+#endif
+}
+
+// This test only checks a system v unix behavior.
+#if !defined(Q_OS_WIN) && !defined(QT_POSIX_IPC)
+void tst_QSystemSemaphore::undo()
+{
+#if !QT_CONFIG(process)
+ QSKIP("No qprocess support", SkipAll);
+#else
+ QSystemSemaphore sem("store", 1, QSystemSemaphore::Create);
+
+ QStringList acquireArguments = QStringList("acquire");
+ QProcess acquire;
+ acquire.setProcessChannelMode(QProcess::ForwardedChannels);
+ acquire.start(m_helperBinary, acquireArguments);
+ QVERIFY2(acquire.waitForStarted(), "Could not start helper binary");
+ acquire.waitForFinished(HELPERWAITTIME);
+ QVERIFY(acquire.state()== QProcess::NotRunning);
+
+ // At process exit the kernel should auto undo
+
+ acquire.start(m_helperBinary, acquireArguments);
+ QVERIFY2(acquire.waitForStarted(), "Could not start helper binary");
+ acquire.waitForFinished(HELPERWAITTIME);
+ QVERIFY(acquire.state()== QProcess::NotRunning);
+#endif
+}
+#endif
+
+void tst_QSystemSemaphore::initialValue()
+{
+#if !QT_CONFIG(process)
+ QSKIP("No qprocess support", SkipAll);
+#else
+ QSystemSemaphore sem("store", 1, QSystemSemaphore::Create);
+
+ QStringList acquireArguments = QStringList("acquire");
+ QStringList releaseArguments = QStringList("release");
+ QProcess acquire;
+ acquire.setProcessChannelMode(QProcess::ForwardedChannels);
+
+ QProcess release;
+ release.setProcessChannelMode(QProcess::ForwardedChannels);
+
+ acquire.start(m_helperBinary, acquireArguments);
+ QVERIFY2(acquire.waitForStarted(), "Could not start helper binary");
+ acquire.waitForFinished(HELPERWAITTIME);
+ QVERIFY(acquire.state()== QProcess::NotRunning);
+
+ acquire.start(m_helperBinary, acquireArguments << QLatin1String("2"));
+ QVERIFY2(acquire.waitForStarted(), "Could not start helper binary");
+ acquire.waitForFinished(HELPERWAITTIME);
+ QVERIFY(acquire.state()== QProcess::Running);
+ acquire.kill();
+
+ release.start(m_helperBinary, releaseArguments);
+ QVERIFY2(release.waitForStarted(), "Could not start helper binary");
+ acquire.waitForFinished(HELPERWAITTIME);
+ release.waitForFinished(HELPERWAITTIME);
+ QVERIFY(acquire.state()== QProcess::NotRunning);
+#endif
+}
+
+QTEST_MAIN(tst_QSystemSemaphore)
+#include "tst_qsystemsemaphore.moc"
+
diff --git a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
index 5b2d77a02c..8d194dafc1 100644
--- a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
+++ b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
@@ -75,6 +75,7 @@ private slots:
void dontBlockEvents();
void postedEventsShouldNotStarveTimers();
+ void callOnTimeout();
};
void tst_QTimer::zeroTimer()
@@ -455,8 +456,7 @@ void tst_QTimer::moveToThread()
#if defined(Q_OS_WIN32)
QSKIP("Does not work reliably on Windows :(");
#elif defined(Q_OS_MACOS)
- if (__builtin_available(macOS 10.12, *))
- QSKIP("Does not work reliably on macOS 10.12 (QTBUG-59679)");
+ QSKIP("Does not work reliably on macOS 10.12+ (QTBUG-59679)");
#endif
QTimer ti1;
QTimer ti2;
@@ -979,5 +979,30 @@ void tst_QTimer::crossThreadSingleShotToFunctor()
delete o;
}
+void tst_QTimer::callOnTimeout()
+{
+ QTimer timer;
+ QSignalSpy timeoutSpy(&timer, &QTimer::timeout);
+ timer.setInterval(0);
+ timer.start();
+
+ auto context = new QObject();
+
+ int count = 0;
+ timer.callOnTimeout([&count] { count++; });
+ QMetaObject::Connection connection = timer.callOnTimeout(context, [&count] { count++; });
+ timer.callOnTimeout(&timer, &QTimer::stop);
+
+
+ QTest::qWait(100);
+ QCOMPARE(count, 2);
+ QCOMPARE(timeoutSpy.count(), 1);
+
+ // Test that connection is bound to context lifetime
+ QVERIFY(connection);
+ delete context;
+ QVERIFY(!connection);
+}
+
QTEST_MAIN(tst_QTimer)
#include "tst_qtimer.moc"
diff --git a/tests/auto/corelib/kernel/qtranslator/android_testdata.qrc b/tests/auto/corelib/kernel/qtranslator/android_testdata.qrc
index b33995ef21..39b85db664 100644
--- a/tests/auto/corelib/kernel/qtranslator/android_testdata.qrc
+++ b/tests/auto/corelib/kernel/qtranslator/android_testdata.qrc
@@ -1,6 +1,7 @@
<RCC>
<qresource prefix="/android_testdata">
<file>hellotr_la.qm</file>
+ <file>hellotr_empty.qm</file>
<file>msgfmt_from_po.qm</file>
<file>dependencies_la.qm</file>
</qresource>
diff --git a/tests/auto/corelib/kernel/qtranslator/hellotr_empty.qm b/tests/auto/corelib/kernel/qtranslator/hellotr_empty.qm
new file mode 100644
index 0000000000..be651eede2
--- /dev/null
+++ b/tests/auto/corelib/kernel/qtranslator/hellotr_empty.qm
@@ -0,0 +1 @@
+<¸dÊÍ!¿`¡½Ý \ No newline at end of file
diff --git a/tests/auto/corelib/kernel/qtranslator/hellotr_empty.ts b/tests/auto/corelib/kernel/qtranslator/hellotr_empty.ts
new file mode 100644
index 0000000000..85e0d3992b
--- /dev/null
+++ b/tests/auto/corelib/kernel/qtranslator/hellotr_empty.ts
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1"/>
diff --git a/tests/auto/corelib/kernel/qtranslator/qtranslator.pro b/tests/auto/corelib/kernel/qtranslator/qtranslator.pro
index d8924c2d5f..a985f35a14 100644
--- a/tests/auto/corelib/kernel/qtranslator/qtranslator.pro
+++ b/tests/auto/corelib/kernel/qtranslator/qtranslator.pro
@@ -5,5 +5,5 @@ SOURCES = tst_qtranslator.cpp
RESOURCES += qtranslator.qrc
android:!android-embedded: RESOURCES += android_testdata.qrc
-else: TESTDATA += dependencies_la.qm hellotr_la.qm msgfmt_from_po.qm
+else: TESTDATA += dependencies_la.qm hellotr_empty.qm hellotr_la.qm msgfmt_from_po.qm
diff --git a/tests/auto/corelib/kernel/qtranslator/qtranslator.qrc b/tests/auto/corelib/kernel/qtranslator/qtranslator.qrc
index 333dcfaa21..cb82c6cc95 100644
--- a/tests/auto/corelib/kernel/qtranslator/qtranslator.qrc
+++ b/tests/auto/corelib/kernel/qtranslator/qtranslator.qrc
@@ -1,5 +1,6 @@
<RCC>
<qresource prefix="/tst_qtranslator">
<file>hellotr_la.qm</file>
+ <file>hellotr_empty.qm</file>
</qresource>
</RCC>
diff --git a/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp b/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp
index 451f96339e..40a29c723c 100644
--- a/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp
+++ b/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp
@@ -41,13 +41,12 @@ protected:
private slots:
void initTestCase();
+ void load_data();
void load();
- void load2();
void threadLoad();
void testLanguageChange();
void plural();
void translate_qm_file_generated_with_msgfmt();
- void loadFromResource();
void loadDirectory();
void dependencies();
void translationInThreadWhileInstallingTranslator();
@@ -106,24 +105,45 @@ bool tst_QTranslator::eventFilter(QObject *, QEvent *event)
return false;
}
-void tst_QTranslator::load()
+void tst_QTranslator::load_data()
{
+ QTest::addColumn<QString>("filepath");
+ QTest::addColumn<bool>("isEmpty");
+ QTest::addColumn<QString>("translation");
- QTranslator tor( 0 );
- tor.load("hellotr_la");
- QVERIFY(!tor.isEmpty());
- QCOMPARE(tor.translate("QPushButton", "Hello world!"), QLatin1String("Hallo Welt!"));
+ QTest::newRow("hellotr_la") << "hellotr_la.qm" << false << "Hallo Welt!";
+ QTest::newRow("hellotr_empty") << "hellotr_empty.qm" << true << "";
}
-void tst_QTranslator::load2()
+void tst_QTranslator::load()
{
- QTranslator tor( 0 );
- QFile file("hellotr_la.qm");
- file.open(QFile::ReadOnly);
- QByteArray data = file.readAll();
- tor.load((const uchar *)data.constData(), data.length());
- QVERIFY(!tor.isEmpty());
- QCOMPARE(tor.translate("QPushButton", "Hello world!"), QLatin1String("Hallo Welt!"));
+ QFETCH(QString, filepath);
+ QFETCH(bool, isEmpty);
+ QFETCH(QString, translation);
+
+ {
+ QTranslator tor;
+ QVERIFY(tor.load(QFileInfo(filepath).baseName()));
+ QCOMPARE(tor.isEmpty(), isEmpty);
+ QCOMPARE(tor.translate("QPushButton", "Hello world!"), translation);
+ }
+
+ {
+ QFile file(filepath);
+ file.open(QFile::ReadOnly);
+ QByteArray data = file.readAll();
+ QTranslator tor;
+ QVERIFY(tor.load((const uchar *)data.constData(), data.length()));
+ QCOMPARE(tor.isEmpty(), isEmpty);
+ QCOMPARE(tor.translate("QPushButton", "Hello world!"), translation);
+ }
+
+ {
+ QTranslator tor;
+ QVERIFY(tor.load(QString(":/tst_qtranslator/%1").arg(filepath)));
+ QCOMPARE(tor.isEmpty(), isEmpty);
+ QCOMPARE(tor.translate("QPushButton", "Hello world!"), translation);
+ }
}
class TranslatorThread : public QThread
@@ -240,14 +260,6 @@ void tst_QTranslator::translate_qm_file_generated_with_msgfmt()
qApp->removeTranslator(&translator);
}
-void tst_QTranslator::loadFromResource()
-{
- QTranslator tor;
- tor.load(":/tst_qtranslator/hellotr_la.qm");
- QVERIFY(!tor.isEmpty());
- QCOMPARE(tor.translate("QPushButton", "Hello world!"), QLatin1String("Hallo Welt!"));
-}
-
void tst_QTranslator::loadDirectory()
{
QString current_base = QDir::current().dirName();
diff --git a/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp b/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp
index e2a0c2dad3..ac8aaa1327 100644
--- a/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp
+++ b/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp
@@ -46,6 +46,7 @@ protected slots:
private slots:
void simple_data();
void simple();
+ void blockedWaiting();
void manyNotifiers();
void disableNotifiersInActivatedSlot_data();
void disableNotifiersInActivatedSlot();
@@ -104,6 +105,26 @@ void tst_QWinEventNotifier::simple()
QVERIFY(simpleActivated);
}
+void tst_QWinEventNotifier::blockedWaiting()
+{
+ simpleHEvent = CreateEvent(0, true, false, 0);
+ QWinEventNotifier n(simpleHEvent);
+ QObject::connect(&n, &QWinEventNotifier::activated,
+ this, &tst_QWinEventNotifier::simple_activated);
+ simpleActivated = false;
+
+ SetEvent(simpleHEvent);
+ QCOMPARE(WaitForSingleObject(simpleHEvent, 1000), WAIT_OBJECT_0);
+
+ n.setEnabled(false);
+ ResetEvent(simpleHEvent);
+ n.setEnabled(true);
+
+ QTestEventLoop::instance().enterLoop(1);
+ QVERIFY(QTestEventLoop::instance().timeout());
+ QVERIFY(!simpleActivated);
+}
+
class EventWithNotifier : public QObject
{
Q_OBJECT
diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy.foo b/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy.foo
new file mode 100644
index 0000000000..ed5e761417
--- /dev/null
+++ b/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy.foo
@@ -0,0 +1,3 @@
+<?foo>
+<blah>
+</blah>
diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy.xml b/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy.xml
new file mode 100644
index 0000000000..27b5bd7e1f
--- /dev/null
+++ b/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
+ <!-- The real life example would be that this mime type is a sub class of application/xml
+ which has a magic that matches &lt;?xml .
+ XML files with an early appearing qnx tag are detected as
+ application/vnd.qnx.bar-descriptor. We want that XML files without the qnx tag to be
+ identified as application/xml, independent of the order in which the two are registered. -->
+ <mime-type type="application/vnd.qnx.bar-descriptor">
+ <sub-class-of type="application/foo"/>
+ <glob pattern="*.foo"/>
+ <magic><!-- higher priority than the parent magic -->
+ <match value="&lt;qnx&gt;" type="string" offset="0:200"/>
+ </magic>
+ </mime-type>
+ <mime-type type="application/foo">
+ <glob pattern="*.foo"/>
+ <magic priority="40">
+ <match value="&lt;?foo" type="string" offset="0"/>
+ </magic>
+ </mime-type>
+</mime-info>
diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy2.foo b/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy2.foo
new file mode 100644
index 0000000000..fd90ed04b3
--- /dev/null
+++ b/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy2.foo
@@ -0,0 +1,3 @@
+<?foo>
+<qnx>
+</qnx>
diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/testdata.qrc b/tests/auto/corelib/mimetypes/qmimedatabase/testdata.qrc
index 29666627a1..1002d0195d 100644
--- a/tests/auto/corelib/mimetypes/qmimedatabase/testdata.qrc
+++ b/tests/auto/corelib/mimetypes/qmimedatabase/testdata.qrc
@@ -7,5 +7,8 @@
<file>invalid-magic1.xml</file>
<file>invalid-magic2.xml</file>
<file>invalid-magic3.xml</file>
+ <file>magic-and-hierarchy.xml</file>
+ <file>magic-and-hierarchy.foo</file>
+ <file>magic-and-hierarchy2.foo</file>
</qresource>
</RCC>
diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp
index 3144c3071c..597d51e7e0 100644
--- a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp
+++ b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp
@@ -52,6 +52,7 @@ static const char *const additionalMimeFiles[] = {
"invalid-magic1.xml",
"invalid-magic2.xml",
"invalid-magic3.xml",
+ "magic-and-hierarchy.xml",
0
};
@@ -985,6 +986,12 @@ void tst_QMimeDatabase::installNewGlobalMimeType()
qDebug() << objcsrc.globPatterns();
}
+ const QString fooTestFile = QLatin1String(RESOURCE_PREFIX "magic-and-hierarchy.foo");
+ QCOMPARE(db.mimeTypeForFile(fooTestFile).name(), QString::fromLatin1("application/foo"));
+
+ const QString fooTestFile2 = QLatin1String(RESOURCE_PREFIX "magic-and-hierarchy2.foo");
+ QCOMPARE(db.mimeTypeForFile(fooTestFile2).name(), QString::fromLatin1("application/vnd.qnx.bar-descriptor"));
+
// Now test removing the mimetype definitions again
for (int i = 0; i < m_additionalMimeFileNames.size(); ++i)
QFile::remove(destDir + m_additionalMimeFileNames.at(i));
diff --git a/tests/auto/corelib/plugin/plugin.pro b/tests/auto/corelib/plugin/plugin.pro
index b094c24e55..240608fddf 100644
--- a/tests/auto/corelib/plugin/plugin.pro
+++ b/tests/auto/corelib/plugin/plugin.pro
@@ -11,6 +11,5 @@ qtConfig(library): SUBDIRS += \
contains(CONFIG, static) {
message(Disabling tests requiring shared build of Qt)
SUBDIRS -= qfactoryloader \
- qplugin \
- qpluginloader
+ qplugin
}
diff --git a/tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp b/tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp
index d285ed79c0..a290c012df 100644
--- a/tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp
+++ b/tests/auto/corelib/plugin/qplugin/tst_qplugin.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -30,8 +31,11 @@
#include <QCoreApplication>
#include <QDebug>
#include <QDir>
+#include <qplugin.h>
#include <QPluginLoader>
+#include <private/qplugin_p.h>
+
class tst_QPlugin : public QObject
{
Q_OBJECT
@@ -124,7 +128,10 @@ void tst_QPlugin::scanInvalidPlugin_data()
{
QTest::addColumn<QByteArray>("metadata");
QTest::addColumn<bool>("loads");
+ QTest::addColumn<QString>("errMsg");
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ // Binary JSON metadata
QByteArray prefix = "QTMETADATA ";
{
@@ -138,27 +145,65 @@ void tst_QPlugin::scanInvalidPlugin_data()
obj.insert("debug", true);
#endif
obj.insert("MetaData", QJsonObject());
- QTest::newRow("control") << (prefix + QJsonDocument(obj).toBinaryData()) << true;
+ QTest::newRow("json-control") << (prefix + QJsonDocument(obj).toBinaryData()) << true << "";
}
- QTest::newRow("zeroes") << prefix << false;
+ QTest::newRow("json-zeroes") << prefix << false << " ";
prefix += "qbjs";
- QTest::newRow("bad-json-version0") << prefix << false;
- QTest::newRow("bad-json-version2") << (prefix + QByteArray("\2\0\0\0", 4)) << false;
+ QTest::newRow("bad-json-version0") << prefix << false << " ";
+ QTest::newRow("bad-json-version2") << (prefix + QByteArray("\2\0\0\0", 4)) << false << " ";
// valid qbjs version 1
prefix += QByteArray("\1\0\0\0");
// too large for the file (100 MB)
- QTest::newRow("bad-json-size-large1") << (prefix + QByteArray("\0\0\x40\x06")) << false;
+ QTest::newRow("bad-json-size-large1") << (prefix + QByteArray("\0\0\x40\x06")) << false << " ";
// too large for binary JSON (512 MB)
- QTest::newRow("bad-json-size-large2") << (prefix + QByteArray("\0\0\0\x20")) << false;
+ QTest::newRow("bad-json-size-large2") << (prefix + QByteArray("\0\0\0\x20")) << false << " ";
// could overflow
- QTest::newRow("bad-json-size-large3") << (prefix + "\xff\xff\xff\x7f") << false;
+ QTest::newRow("bad-json-size-large3") << (prefix + "\xff\xff\xff\x7f") << false << " ";
+#endif
+ // CBOR metadata
+ QByteArray cprefix = "QTMETADATA !1234";
+ cprefix[12] = 0; // current version
+ cprefix[13] = QT_VERSION_MAJOR;
+ cprefix[14] = QT_VERSION_MINOR;
+ cprefix[15] = qPluginArchRequirements();
+
+ QByteArray cborValid = [] {
+ QCborMap m;
+ m.insert(int(QtPluginMetaDataKeys::IID), QLatin1String("org.qt-project.tst_qplugin"));
+ m.insert(int(QtPluginMetaDataKeys::ClassName), QLatin1String("tst"));
+ m.insert(int(QtPluginMetaDataKeys::MetaData), QCborMap());
+ return QCborValue(m).toCbor();
+ }();
+ QTest::newRow("cbor-control") << (cprefix + cborValid) << true << "";
+
+ cprefix[12] = 1;
+ QTest::newRow("cbor-major-too-new") << (cprefix + cborValid) << false
+ << " Invalid metadata version";
+
+ cprefix[12] = 0;
+ cprefix[13] = QT_VERSION_MAJOR + 1;
+ QTest::newRow("cbor-major-too-new") << (cprefix + cborValid) << false << "";
+
+ cprefix[13] = QT_VERSION_MAJOR - 1;
+ QTest::newRow("cbor-major-too-old") << (cprefix + cborValid) << false << "";
+
+ cprefix[13] = QT_VERSION_MAJOR;
+ cprefix[14] = QT_VERSION_MINOR + 1;
+ QTest::newRow("cbor-minor-too-new") << (cprefix + cborValid) << false << "";
+
+ QTest::newRow("cbor-invalid") << (cprefix + "\xff") << false
+ << " Metadata parsing error: Invalid CBOR stream: unexpected 'break' byte";
+ QTest::newRow("cbor-not-map1") << (cprefix + "\x01") << false
+ << " Unexpected metadata contents";
+ QTest::newRow("cbor-not-map2") << (cprefix + "\x81\x01") << false
+ << " Unexpected metadata contents";
}
static const char invalidPluginSignature[] = "qplugin testfile";
@@ -214,6 +259,11 @@ void tst_QPlugin::scanInvalidPlugin()
// now try to load this
QFETCH(bool, loads);
+ QFETCH(QString, errMsg);
+ if (!errMsg.isEmpty())
+ QTest::ignoreMessage(QtWarningMsg,
+ "Found invalid metadata in lib " + QFile::encodeName(newName) +
+ ":" + errMsg.toUtf8());
QPluginLoader loader(newName);
QCOMPARE(loader.load(), loads);
if (loads)
diff --git a/tests/auto/corelib/plugin/qplugin/tst_qplugin.pro b/tests/auto/corelib/plugin/qplugin/tst_qplugin.pro
index 8c6540fe87..4432ee20c1 100644
--- a/tests/auto/corelib/plugin/qplugin/tst_qplugin.pro
+++ b/tests/auto/corelib/plugin/qplugin/tst_qplugin.pro
@@ -1,6 +1,6 @@
CONFIG += testcase
TARGET = tst_qplugin
-QT = core testlib
+QT = core-private testlib
SOURCES = tst_qplugin.cpp
TESTDATA += plugins/*
diff --git a/tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.h b/tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.h
index 04ce042e24..ac349c2f75 100644
--- a/tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.h
+++ b/tests/auto/corelib/plugin/qpluginloader/theplugin/theplugin.h
@@ -35,7 +35,7 @@
class ThePlugin : public QObject, public PluginInterface
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.autotests.plugininterface" FILE "../empty.json")
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.autotests.plugininterface" FILE "../utf8_data.json")
Q_INTERFACES(PluginInterface)
public:
diff --git a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
index f34741281c..c517c0809a 100644
--- a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
+++ b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp
@@ -140,6 +140,10 @@ void tst_QPluginLoader::cleanup()
void tst_QPluginLoader::errorString()
{
+#if !defined(QT_SHARED)
+ QSKIP("This test requires Qt to create shared libraries.");
+#endif
+
const QString unknown(QLatin1String("Unknown error"));
{
@@ -206,6 +210,14 @@ void tst_QPluginLoader::errorString()
{
QPluginLoader loader( sys_qualifiedLibraryName("theplugin")); //a plugin
+
+ // Check metadata
+ const QJsonObject metaData = loader.metaData();
+ QCOMPARE(metaData.value("IID").toString(), QStringLiteral("org.qt-project.Qt.autotests.plugininterface"));
+ const QJsonObject kpluginObject = metaData.value("MetaData").toObject().value("KPlugin").toObject();
+ QCOMPARE(kpluginObject.value("Name[mr]").toString(), QString::fromUtf8("चौकट भूमिती"));
+
+ // Load
QCOMPARE(loader.load(), true);
QCOMPARE(loader.errorString(), unknown);
@@ -224,6 +236,9 @@ void tst_QPluginLoader::errorString()
void tst_QPluginLoader::loadHints()
{
+#if !defined(QT_SHARED)
+ QSKIP("This test requires Qt to create shared libraries.");
+#endif
QPluginLoader loader;
QCOMPARE(loader.loadHints(), (QLibrary::LoadHints)0); //Do not crash
loader.setLoadHints(QLibrary::ResolveAllSymbolsHint);
@@ -233,6 +248,9 @@ void tst_QPluginLoader::loadHints()
void tst_QPluginLoader::deleteinstanceOnUnload()
{
+#if !defined(QT_SHARED)
+ QSKIP("This test requires Qt to create shared libraries.");
+#endif
for (int pass = 0; pass < 2; ++pass) {
QPluginLoader loader1;
loader1.setFileName( sys_qualifiedLibraryName("theplugin")); //a plugin
@@ -268,6 +286,9 @@ void tst_QPluginLoader::deleteinstanceOnUnload()
void tst_QPluginLoader::loadDebugObj()
{
+#if !defined(QT_SHARED)
+ QSKIP("This test requires a shared build of Qt, as QPluginLoader::setFileName is a no-op in static builds");
+#endif
#if defined (__ELF__)
QVERIFY(QFile::exists(QFINDTESTDATA("elftest/debugobj.so")));
QPluginLoader lib1(QFINDTESTDATA("elftest/debugobj.so"));
@@ -277,6 +298,9 @@ void tst_QPluginLoader::loadDebugObj()
void tst_QPluginLoader::loadCorruptElf()
{
+#if !defined(QT_SHARED)
+ QSKIP("This test requires a shared build of Qt, as QPluginLoader::setFileName is a no-op in static builds");
+#endif
#if defined (__ELF__)
if (sizeof(void*) == 8) {
QVERIFY(QFile::exists(QFINDTESTDATA("elftest/corrupt1.elf64.so")));
@@ -377,6 +401,9 @@ void tst_QPluginLoader::loadMachO()
#if defined (Q_OS_UNIX)
void tst_QPluginLoader::loadGarbage()
{
+#if !defined(QT_SHARED)
+ QSKIP("This test requires a shared build of Qt, as QPluginLoader::setFileName is a no-op in static builds");
+#endif
for (int i=0; i<5; i++) {
const QString name = QLatin1String("elftest/garbage") + QString::number(i + 1) + QLatin1String(".so");
QPluginLoader lib(QFINDTESTDATA(name));
@@ -388,6 +415,9 @@ void tst_QPluginLoader::loadGarbage()
void tst_QPluginLoader::relativePath()
{
+#if !defined(QT_SHARED)
+ QSKIP("This test requires Qt to create shared libraries.");
+#endif
// Windows binaries run from release and debug subdirs, so we can't rely on the current dir.
const QString binDir = QFINDTESTDATA("bin");
QVERIFY(!binDir.isEmpty());
@@ -402,6 +432,9 @@ void tst_QPluginLoader::relativePath()
void tst_QPluginLoader::absolutePath()
{
+#if !defined(QT_SHARED)
+ QSKIP("This test requires Qt to create shared libraries.");
+#endif
// Windows binaries run from release and debug subdirs, so we can't rely on the current dir.
const QString binDir = QFINDTESTDATA("bin");
QVERIFY(!binDir.isEmpty());
@@ -416,6 +449,9 @@ void tst_QPluginLoader::absolutePath()
void tst_QPluginLoader::reloadPlugin()
{
+#if !defined(QT_SHARED)
+ QSKIP("This test requires Qt to create shared libraries.");
+#endif
QPluginLoader loader;
loader.setFileName( sys_qualifiedLibraryName("theplugin")); //a plugin
loader.load(); // not recommended, instance() should do the job.
@@ -451,6 +487,9 @@ void tst_QPluginLoader::preloadedPlugin_data()
void tst_QPluginLoader::preloadedPlugin()
{
+#if !defined(QT_SHARED)
+ QSKIP("This test requires Qt to create shared libraries.");
+#endif
// check that using QPluginLoader does not interfere with QLibrary
QFETCH(QString, libname);
QLibrary lib(libname);
diff --git a/tests/auto/corelib/plugin/qpluginloader/utf8_data.json b/tests/auto/corelib/plugin/qpluginloader/utf8_data.json
new file mode 100644
index 0000000000..7763b65178
--- /dev/null
+++ b/tests/auto/corelib/plugin/qpluginloader/utf8_data.json
@@ -0,0 +1,17 @@
+{
+ "KPlugin": {
+ "Name": "WindowGeometry",
+ "Name[mr]": "चौकट भूमिती",
+ "Name[pa]": "ਵਿੰਡੋਜà©à¨®à©ˆà¨Ÿà¨°à©€",
+ "Name[th]": "มิติขนาดของหน้าต่าง",
+ "Name[uk]": "Розміри вікна",
+ "Name[zh_CN]": "窗å£å½¢çŠ¶",
+ "Name[zh_TW]": "視窗ä½ç½®",
+ "ServiceTypes": [
+ "KCModule"
+ ]
+ },
+ "X-KDE-ParentComponents": [
+ "windowgeometry"
+ ]
+}
diff --git a/tests/auto/corelib/serialization/qcborstreamreader/qcborstreamreader.pro b/tests/auto/corelib/serialization/qcborstreamreader/qcborstreamreader.pro
new file mode 100644
index 0000000000..5df331314a
--- /dev/null
+++ b/tests/auto/corelib/serialization/qcborstreamreader/qcborstreamreader.pro
@@ -0,0 +1,11 @@
+QT = core testlib
+TARGET = tst_qcborstreamreader
+CONFIG += testcase
+SOURCES += \
+ tst_qcborstreamreader.cpp
+
+INCLUDEPATH += \
+ ../../../../../src/3rdparty/tinycbor/src \
+ ../../../../../src/3rdparty/tinycbor/tests/parser
+
+DEFINES += SRCDIR=\\\"$$PWD/\\\"
diff --git a/tests/auto/corelib/serialization/qcborstreamreader/tst_qcborstreamreader.cpp b/tests/auto/corelib/serialization/qcborstreamreader/tst_qcborstreamreader.cpp
new file mode 100644
index 0000000000..24d9c7409e
--- /dev/null
+++ b/tests/auto/corelib/serialization/qcborstreamreader/tst_qcborstreamreader.cpp
@@ -0,0 +1,1091 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://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 <QtCore/qcborstream.h>
+#include <QtTest>
+
+class tst_QCborStreamReader : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void initTestCase_data();
+ void basics();
+ void clear_data();
+ void clear();
+ void integers_data();
+ void integers();
+ void fixed_data();
+ void fixed();
+ void strings_data();
+ void strings();
+ void tags_data();
+ void tags() { fixed(); }
+ void emptyContainers_data();
+ void emptyContainers();
+
+ void arrays_data();
+ void arrays();
+ void maps_data() { arrays_data(); }
+ void maps();
+ void undefLengthArrays_data() { arrays_data(); }
+ void undefLengthArrays();
+ void undefLengthMaps_data() { arrays_data(); }
+ void undefLengthMaps();
+
+ void next_data() { arrays_data(); }
+ void next();
+ void validation_data();
+ void validation();
+ void recursionLimit_data();
+ void recursionLimit();
+
+ void addData_singleElement_data();
+ void addData_singleElement();
+ void addData_complex_data() { arrays_data(); }
+ void addData_complex();
+};
+
+#define FOR_CBOR_TYPE(F) \
+ F(QCborStreamReader::UnsignedInteger) \
+ F(QCborStreamReader::NegativeInteger) \
+ F(QCborStreamReader::ByteArray) \
+ F(QCborStreamReader::String) \
+ F(QCborStreamReader::Array) \
+ F(QCborStreamReader::Map) \
+ F(QCborStreamReader::Tag) \
+ F(QCborStreamReader::SimpleType) \
+ F(QCborStreamReader::Float16) \
+ F(QCborStreamReader::Float) \
+ F(QCborStreamReader::Double) \
+ F(QCborStreamReader::Invalid)
+
+QT_BEGIN_NAMESPACE
+namespace QTest {
+template<> char *toString<QCborStreamReader::Type>(const QCborStreamReader::Type &t)
+{
+ return qstrdup([=]() {
+ switch (t) {
+#define TYPE(t) \
+ case t: return QT_STRINGIFY(t);
+ FOR_CBOR_TYPE(TYPE)
+#undef TYPE
+ }
+ return "<huh?>";
+ }());
+}
+} // namespace QTest
+QT_END_NAMESPACE
+
+// Get the data from TinyCBOR (see src/3rdparty/tinycbor/tests/parser/data.cpp)
+#include "data.cpp"
+
+void tst_QCborStreamReader::initTestCase_data()
+{
+ QTest::addColumn<bool>("useDevice");
+ QTest::newRow("QByteArray") << false;
+ QTest::newRow("QBuffer") << true;
+}
+
+void tst_QCborStreamReader::basics()
+{
+ QFETCH_GLOBAL(bool, useDevice);
+ QBuffer buffer;
+ QCborStreamReader reader;
+
+ if (useDevice) {
+ buffer.open(QIODevice::ReadOnly);
+ reader.setDevice(&buffer);
+ QVERIFY(reader.device() != nullptr);
+ } else {
+ QCOMPARE(reader.device(), nullptr);
+ }
+
+ QCOMPARE(reader.currentOffset(), 0);
+ QCOMPARE(reader.lastError(), QCborError::EndOfFile);
+
+ QCOMPARE(reader.type(), QCborStreamReader::Invalid);
+ QVERIFY(!reader.isUnsignedInteger());
+ QVERIFY(!reader.isNegativeInteger());
+ QVERIFY(!reader.isByteArray());
+ QVERIFY(!reader.isString());
+ QVERIFY(!reader.isArray());
+ QVERIFY(!reader.isContainer());
+ QVERIFY(!reader.isMap());
+ QVERIFY(!reader.isTag());
+ QVERIFY(!reader.isSimpleType());
+ QVERIFY(!reader.isBool());
+ QVERIFY(!reader.isNull());
+ QVERIFY(!reader.isUndefined());
+ QVERIFY(!reader.isFloat16());
+ QVERIFY(!reader.isFloat());
+ QVERIFY(!reader.isDouble());
+ QVERIFY(!reader.isValid());
+ QVERIFY(reader.isInvalid());
+
+ QCOMPARE(reader.containerDepth(), 0);
+ QCOMPARE(reader.parentContainerType(), QCborStreamReader::Invalid);
+ QVERIFY(!reader.hasNext());
+ QVERIFY(!reader.next());
+ QCOMPARE(reader.lastError(), QCborError::EndOfFile);
+
+ QVERIFY(reader.isLengthKnown()); // well, it's not unknown
+ QCOMPARE(reader.length(), ~0ULL);
+
+ if (useDevice) {
+ reader.reparse();
+ QVERIFY(reader.device() != nullptr);
+ } else {
+ reader.addData(QByteArray());
+ QCOMPARE(reader.device(), nullptr);
+ }
+
+ // nothing changes, we added nothing
+ QCOMPARE(reader.currentOffset(), 0);
+ QCOMPARE(reader.lastError(), QCborError::EndOfFile);
+
+ QCOMPARE(reader.type(), QCborStreamReader::Invalid);
+ QVERIFY(!reader.isUnsignedInteger());
+ QVERIFY(!reader.isNegativeInteger());
+ QVERIFY(!reader.isByteArray());
+ QVERIFY(!reader.isString());
+ QVERIFY(!reader.isArray());
+ QVERIFY(!reader.isContainer());
+ QVERIFY(!reader.isMap());
+ QVERIFY(!reader.isTag());
+ QVERIFY(!reader.isSimpleType());
+ QVERIFY(!reader.isBool());
+ QVERIFY(!reader.isNull());
+ QVERIFY(!reader.isUndefined());
+ QVERIFY(!reader.isFloat16());
+ QVERIFY(!reader.isFloat());
+ QVERIFY(!reader.isDouble());
+ QVERIFY(!reader.isValid());
+ QVERIFY(reader.isInvalid());
+
+ QVERIFY(reader.isLengthKnown()); // well, it's not unknown
+ QCOMPARE(reader.length(), ~0ULL);
+
+ QCOMPARE(reader.containerDepth(), 0);
+ QCOMPARE(reader.parentContainerType(), QCborStreamReader::Invalid);
+ QVERIFY(!reader.hasNext());
+ QVERIFY(!reader.next());
+
+ reader.clear();
+ QCOMPARE(reader.device(), nullptr);
+ QCOMPARE(reader.currentOffset(), 0);
+ QCOMPARE(reader.lastError(), QCborError::EndOfFile);
+}
+
+void tst_QCborStreamReader::clear_data()
+{
+ QTest::addColumn<QByteArray>("data");
+ QTest::addColumn<QCborError>("firstError");
+ QTest::addColumn<int>("offsetAfterSkip");
+ QTest::newRow("invalid") << QByteArray(512, '\xff') << QCborError{QCborError::UnexpectedBreak} << 0;
+ QTest::newRow("valid") << QByteArray(512, '\0') << QCborError{QCborError::NoError} << 0;
+ QTest::newRow("skipped") << QByteArray(512, '\0') << QCborError{QCborError::NoError} << 1;
+}
+
+void tst_QCborStreamReader::clear()
+{
+ QFETCH_GLOBAL(bool, useDevice);
+ QFETCH(QByteArray, data);
+ QFETCH(QCborError, firstError);
+ QFETCH(int, offsetAfterSkip);
+
+ QBuffer buffer(&data);
+ QCborStreamReader reader(data);
+ if (useDevice) {
+ buffer.open(QIODevice::ReadOnly);
+ reader.setDevice(&buffer);
+ }
+ QCOMPARE(reader.isValid(), !firstError);
+ QCOMPARE(reader.currentOffset(), 0);
+ QCOMPARE(reader.lastError(), firstError);
+
+ if (offsetAfterSkip) {
+ reader.next();
+ QVERIFY(!reader.isValid());
+ QCOMPARE(reader.currentOffset(), 1);
+ QCOMPARE(reader.lastError(), QCborError::NoError);
+ }
+
+ reader.clear();
+ QCOMPARE(reader.device(), nullptr);
+ QCOMPARE(reader.currentOffset(), 0);
+ QCOMPARE(reader.lastError(), QCborError::EndOfFile);
+}
+
+void tst_QCborStreamReader::integers_data()
+{
+ addIntegers();
+}
+
+void tst_QCborStreamReader::integers()
+{
+ QFETCH_GLOBAL(bool, useDevice);
+ QFETCH(QByteArray, data);
+ QFETCH(bool, isNegative);
+ QFETCH(quint64, expectedRaw);
+ QFETCH(qint64, expectedValue);
+ QFETCH(bool, inInt64Range);
+ quint64 absolute = (isNegative ? expectedRaw + 1 : expectedRaw);
+
+ QBuffer buffer(&data);
+ QCborStreamReader reader(data);
+ if (useDevice) {
+ buffer.open(QIODevice::ReadOnly);
+ reader.setDevice(&buffer);
+ }
+ QVERIFY(reader.isValid());
+ QCOMPARE(reader.lastError(), QCborError::NoError);
+ QVERIFY(reader.isInteger());
+
+ if (inInt64Range)
+ QCOMPARE(reader.toInteger(), expectedValue);
+ if (isNegative)
+ QCOMPARE(quint64(reader.toNegativeInteger()), absolute);
+ else
+ QCOMPARE(reader.toUnsignedInteger(), absolute);
+}
+
+void escapedAppendTo(QString &result, const QByteArray &data)
+{
+ result += "h'" + QString::fromLatin1(data.toHex()) + '\'';
+}
+
+void escapedAppendTo(QString &result, const QString &data)
+{
+ result += '"';
+ for (int i = 0; i <= data.size(); i += 245) {
+ // hopefully we won't have a surrogate pair split here
+ QScopedArrayPointer<char> escaped(QTest::toPrettyUnicode(data.mid(i, 245)));
+ QLatin1String s(escaped.data() + 1); // skip opening "
+ s.chop(1); // drop the closing "
+ result += s;
+ }
+ result += '"';
+}
+
+template <typename S, QCborStreamReader::StringResult<S> (QCborStreamReader:: *Decoder)()>
+static QString parseOneString_helper(QCborStreamReader &reader)
+{
+ QString result;
+ bool parens = !reader.isLengthKnown();
+ if (parens)
+ result += '(';
+
+ auto r = (reader.*Decoder)();
+ const char *comma = "";
+ while (r.status == QCborStreamReader::Ok) {
+ result += comma;
+ escapedAppendTo(result, r.data);
+
+ r = (reader.*Decoder)();
+ comma = ", ";
+ }
+
+ if (r.status == QCborStreamReader::Error)
+ return QString();
+
+ if (parens)
+ result += ')';
+ return result;
+}
+
+static QString parseOneByteArray(QCborStreamReader &reader)
+{
+ return parseOneString_helper<QByteArray, &QCborStreamReader::readByteArray>(reader);
+}
+
+static QString parseOneString(QCborStreamReader &reader)
+{
+ return parseOneString_helper<QString, &QCborStreamReader::readString>(reader);
+}
+
+static QString makeNegativeString(QCborNegativeInteger n)
+{
+ return n == QCborNegativeInteger(0) ?
+ QString("-18446744073709551616") :
+ QString("-%1").arg(quint64(n));
+}
+
+template <typename T> static inline bool canConvertTo(double v)
+{
+ // The [conv.fpint] (7.10 Floating-integral conversions) section of the
+ // standard says only exact conversions are guaranteed. Converting
+ // integrals to floating-point with loss of precision has implementation-
+ // defined behavior whether the next higher or next lower is returned;
+ // converting FP to integral is UB if it can't be represented.;
+ Q_STATIC_ASSERT(std::numeric_limits<T>::is_integer);
+
+ double supremum = ldexp(1, std::numeric_limits<T>::digits);
+ if (v >= supremum)
+ return false;
+
+ if (v < std::numeric_limits<T>::min()) // either zero or a power of two, so it's exact
+ return false;
+
+ // we're in range
+ return v == floor(v);
+}
+
+static QString makeFpString(double v)
+{
+ if (canConvertTo<qint64>(v))
+ return QString::number(qint64(v)) + '.';
+ if (canConvertTo<quint64>(v))
+ return QString::number(quint64(v)) + '.';
+
+ QString s = QString::number(v, 'g', std::numeric_limits<double>::digits10 + 2);
+ if (!s.contains('.') && !s.contains('e') && !qIsInf(v) && !qIsNaN(v))
+ s += '.';
+ return s;
+}
+
+static QString makeFpString(float v)
+{
+ if (qIsInf(v))
+ return v > 0 ? "inf" : "-inf";
+ if (qIsNaN(v))
+ return "nan";
+ return makeFpString(double(v)) + 'f';
+}
+
+static QString makeFpString(qfloat16 v)
+{
+ if (qIsInf(v))
+ return v > 0 ? "inf" : "-inf";
+ if (qIsNaN(v))
+ return "nan";
+ return makeFpString(double(v)) + "f16";
+}
+
+static QString parseOne(QCborStreamReader &reader)
+{
+ QString result;
+
+ switch (reader.type()) {
+ case QCborStreamReader::UnsignedInteger:
+ result = QString::number(reader.toUnsignedInteger());
+ break;
+ case QCborStreamReader::NegativeInteger:
+ result = makeNegativeString(reader.toNegativeInteger());
+ break;
+ case QCborStreamReader::ByteArray:
+ return parseOneByteArray(reader);
+ case QCborStreamReader::String:
+ return parseOneString(reader);
+ case QCborStreamReader::Array:
+ case QCborStreamReader::Map: {
+ const char *delimiters = (reader.isArray() ? "[]" : "{}");
+ result += delimiters[0];
+ reader.enterContainer();
+
+ QLatin1String comma("");
+ while (reader.lastError() == QCborError::NoError && reader.hasNext()) {
+ result += comma + parseOne(reader);
+ comma = QLatin1String(", ");
+
+ if (reader.parentContainerType() == QCborStreamReader::Map
+ && reader.lastError() == QCborError::NoError)
+ result += ": " + parseOne(reader);
+ }
+
+ if (reader.isValid())
+ return QString();
+ if (reader.lastError() != QCborError::NoError)
+ return QString();
+ reader.leaveContainer();
+ result += delimiters[1];
+ return result;
+ }
+ case QCborStreamReader::Tag: {
+ QCborTag tag = reader.toTag();
+ if (!reader.next())
+ return QString();
+ return QString("%1(%2)").arg(quint64(tag)).arg(parseOne(reader));
+ }
+ case QCborStreamReader::SimpleType:
+ switch (reader.toSimpleType()) {
+ case QCborSimpleType::False:
+ result = QStringLiteral("false");
+ break;
+ case QCborSimpleType::True:
+ result = QStringLiteral("true");
+ break;
+ case QCborSimpleType::Null:
+ result = QStringLiteral("null");
+ break;
+ case QCborSimpleType::Undefined:
+ result = QStringLiteral("undefined");
+ break;
+ default:
+ result = QString("simple(%1)").arg(quint8(reader.toSimpleType()));
+ break;
+ }
+ break;
+ case QCborStreamReader::Float16:
+ result = makeFpString(reader.toFloat16());
+ break;
+ case QCborStreamReader::Float:
+ result = makeFpString(reader.toFloat());
+ break;
+ case QCborStreamReader::Double:
+ result = makeFpString(reader.toDouble());
+ break;
+ case QCborStreamReader::Invalid:
+ return QStringLiteral("<invalid>");
+ }
+
+ if (!reader.next())
+ return QString();
+ return result;
+}
+
+bool parseNonRecursive(QString &result, bool &printingStringChunks, QCborStreamReader &reader)
+{
+ while (reader.lastError() == QCborError::NoError) {
+ if (!reader.hasNext()) {
+ if (result.endsWith(", "))
+ result.chop(2);
+ if (reader.containerDepth() == 0)
+ return true;
+ result += reader.parentContainerType() == QCborStreamReader::Map ? "}, " : "], ";
+ reader.leaveContainer();
+ continue;
+ }
+
+ switch (reader.type()) {
+ case QCborStreamReader::UnsignedInteger:
+ result += QString::number(reader.toUnsignedInteger());
+ break;
+ case QCborStreamReader::NegativeInteger:
+ result += makeNegativeString(reader.toNegativeInteger());
+ break;
+ case QCborStreamReader::ByteArray:
+ case QCborStreamReader::String: {
+ QCborStreamReader::StringResultCode status;
+ if (!printingStringChunks && !reader.isLengthKnown()) {
+ printingStringChunks = true;
+ result += '(';
+ }
+ if (reader.isByteArray()) {
+ auto r = reader.readByteArray();
+ status = r.status;
+ if (r.status == QCborStreamReader::Ok)
+ escapedAppendTo(result, r.data);
+ } else {
+ auto r = reader.readString();
+ status = r.status;
+ if (r.status == QCborStreamReader::Ok)
+ escapedAppendTo(result, r.data);
+ }
+
+ if (status == QCborStreamReader::EndOfString) {
+ if (result.endsWith(", "))
+ result.chop(2);
+ if (printingStringChunks)
+ result += ')';
+ result += ", ";
+ printingStringChunks = false;
+ }
+ if (status == QCborStreamReader::Ok && printingStringChunks)
+ result += ", ";
+
+ continue;
+ }
+ case QCborStreamReader::Array:
+ result += '[';
+ reader.enterContainer();
+ continue;
+ case QCborStreamReader::Map:
+ result += '{';
+ reader.enterContainer();
+ continue;
+ case QCborStreamReader::Tag:
+ result += QString("Tag:%1:").arg(quint64(reader.toTag()));
+ reader.next();
+ continue; // skip the comma
+ case QCborStreamReader::SimpleType:
+ switch (reader.toSimpleType()) {
+ case QCborSimpleType::False:
+ result += QStringLiteral("false");
+ break;
+ case QCborSimpleType::True:
+ result += QStringLiteral("true");
+ break;
+ case QCborSimpleType::Null:
+ result += QStringLiteral("null");
+ break;
+ case QCborSimpleType::Undefined:
+ result += QStringLiteral("undefined");
+ break;
+ default:
+ result += QString("simple(%1)").arg(quint8(reader.toSimpleType()));
+ break;
+ }
+ break;
+ case QCborStreamReader::Float16:
+ result += makeFpString(reader.toFloat16());
+ break;
+ case QCborStreamReader::Float:
+ result += makeFpString(reader.toFloat());
+ break;
+ case QCborStreamReader::Double:
+ result += makeFpString(reader.toDouble());
+ break;
+ case QCborStreamReader::Invalid:
+ break;
+ }
+
+ reader.next();
+ result += ", ";
+ }
+ return false;
+};
+
+
+static QString &removeIndicators(QString &str)
+{
+ // remove any CBOR encoding indicators from the string, since parseOne above
+ // doesn't produce them
+ static QRegularExpression rx("_(\\d+)? ?");
+ return str.replace(rx, QString());
+}
+
+void tst_QCborStreamReader::fixed_data()
+{
+ addColumns();
+ addFixedData();
+}
+
+void tst_QCborStreamReader::fixed()
+{
+ QFETCH_GLOBAL(bool, useDevice);
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+ removeIndicators(expected);
+
+ QBuffer buffer(&data);
+ QCborStreamReader reader(data);
+ if (useDevice) {
+ buffer.open(QIODevice::ReadOnly);
+ reader.setDevice(&buffer);
+ }
+ QVERIFY(reader.isValid());
+ QCOMPARE(reader.lastError(), QCborError::NoError);
+ QCOMPARE(parseOne(reader), expected);
+
+ // verify that we can re-read
+ reader.reset();
+ QVERIFY(reader.isValid());
+ QCOMPARE(reader.lastError(), QCborError::NoError);
+ QCOMPARE(parseOne(reader), expected);
+}
+
+void tst_QCborStreamReader::strings_data()
+{
+ addColumns();
+ addStringsData();
+}
+
+void tst_QCborStreamReader::strings()
+{
+ fixed();
+ if (QTest::currentTestFailed())
+ return;
+
+ // Extra string checks:
+ // We'll compare the reads using readString() and readByteArray()
+ // (henceforth "control data" because fixed() above tested them) with those
+ // obtained with readStringChunk().
+
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+ QFETCH_GLOBAL(bool, useDevice);
+ bool isChunked = expected.startsWith('(');
+
+ QBuffer buffer(&data), controlBuffer(&data);
+ QCborStreamReader reader(data), controlReader(data);
+ if (useDevice) {
+ buffer.open(QIODevice::ReadOnly);
+ controlBuffer.open(QIODevice::ReadOnly);
+ reader.setDevice(&buffer);
+ controlReader.setDevice(&controlBuffer);
+ }
+ QVERIFY(reader.isString() || reader.isByteArray());
+ QCOMPARE(reader.isLengthKnown(), !isChunked);
+
+ if (!isChunked)
+ QCOMPARE(reader.currentStringChunkSize(), qsizetype(reader.length()));
+
+ int chunks = 0;
+ forever {
+ QCborStreamReader::StringResult<QByteArray> controlData;
+ if (reader.isString()) {
+ auto r = controlReader.readString();
+ controlData.data = r.data.toUtf8();
+ controlData.status = r.status;
+ } else {
+ controlData = controlReader.readByteArray();
+ }
+ QVERIFY(controlData.status != QCborStreamReader::Error);
+
+ for (int i = 0; i < 10; ++i) {
+ // this call must work several times with the same result
+ QCOMPARE(reader.currentStringChunkSize(), controlData.data.size());
+ }
+
+ QByteArray chunk(controlData.data.size(), Qt::Uninitialized);
+ auto r = reader.readStringChunk(chunk.data(), chunk.size());
+ QCOMPARE(r.status, controlData.status);
+ if (r.status == QCborStreamReader::Ok)
+ QCOMPARE(r.data, controlData.data.size());
+ else
+ QCOMPARE(r.data, 0);
+ QCOMPARE(chunk, controlData.data);
+
+ if (r.status == QCborStreamReader::EndOfString)
+ break;
+ ++chunks;
+ }
+
+ if (!isChunked)
+ QCOMPARE(chunks, 1);
+}
+
+void tst_QCborStreamReader::tags_data()
+{
+ addColumns();
+ addTagsData();
+}
+
+void tst_QCborStreamReader::emptyContainers_data()
+{
+ addColumns();
+ addEmptyContainersData();
+}
+
+void tst_QCborStreamReader::emptyContainers()
+{
+ QFETCH_GLOBAL(bool, useDevice);
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+ removeIndicators(expected);
+
+ QBuffer buffer(&data);
+ QCborStreamReader reader(data);
+ if (useDevice) {
+ buffer.open(QIODevice::ReadOnly);
+ reader.setDevice(&buffer);
+ }
+ QVERIFY(reader.isValid());
+ QCOMPARE(reader.lastError(), QCborError::NoError);
+ if (reader.isLengthKnown())
+ QCOMPARE(reader.length(), 0U);
+ QCOMPARE(parseOne(reader), expected);
+
+ // verify that we can re-read
+ reader.reset();
+ QVERIFY(reader.isValid());
+ QCOMPARE(reader.lastError(), QCborError::NoError);
+ if (reader.isLengthKnown())
+ QCOMPARE(reader.length(), 0U);
+ QCOMPARE(parseOne(reader), expected);
+}
+
+void tst_QCborStreamReader::arrays_data()
+{
+ addColumns();
+ addFixedData();
+ addStringsData();
+ addTagsData();
+ addEmptyContainersData();
+}
+
+static void checkContainer(int len, const QByteArray &data, const QString &expected)
+{
+ QFETCH_GLOBAL(bool, useDevice);
+
+ QByteArray copy = data;
+ QBuffer buffer(&copy);
+ QCborStreamReader reader(data);
+ if (useDevice) {
+ buffer.open(QIODevice::ReadOnly);
+ reader.setDevice(&buffer);
+ }
+ QVERIFY(reader.isValid());
+ QCOMPARE(reader.lastError(), QCborError::NoError);
+ if (len >= 0) {
+ QVERIFY(reader.isLengthKnown());
+ QCOMPARE(reader.length(), uint(len));
+ }
+ QCOMPARE(parseOne(reader), expected);
+
+ // verify that we can re-read
+ reader.reset();
+ QVERIFY(reader.isValid());
+ QCOMPARE(reader.lastError(), QCborError::NoError);
+ if (len >= 0) {
+ QVERIFY(reader.isLengthKnown());
+ QCOMPARE(reader.length(), uint(len));
+ }
+ QCOMPARE(parseOne(reader), expected);
+}
+
+void tst_QCborStreamReader::arrays()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+ removeIndicators(expected);
+
+ checkContainer(1, '\x81' + data, '[' + expected + ']');
+ if (QTest::currentTestFailed())
+ return;
+
+ checkContainer(2, '\x82' + data + data, '[' + expected + ", " + expected + ']');
+}
+
+void tst_QCborStreamReader::maps()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+ removeIndicators(expected);
+
+ // int keys
+ checkContainer(1, "\xa1\1" + data, "{1: " + expected + '}');
+ if (QTest::currentTestFailed())
+ return;
+
+ checkContainer(2, "\xa2\1" + data + '\x20' + data,
+ "{1: " + expected + ", -1: " + expected + '}');
+ if (QTest::currentTestFailed())
+ return;
+
+ // string keys
+ checkContainer(1, "\xa1\x65Hello" + data, "{\"Hello\": " + expected + '}');
+ if (QTest::currentTestFailed())
+ return;
+
+ checkContainer(2, "\xa2\x65World" + data + "\x65Hello" + data,
+ "{\"World\": " + expected + ", \"Hello\": " + expected + '}');
+}
+
+void tst_QCborStreamReader::undefLengthArrays()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+ removeIndicators(expected);
+
+ checkContainer(-1, '\x9f' + data + '\xff', '[' + expected + ']');
+ if (QTest::currentTestFailed())
+ return;
+
+ checkContainer(-2, '\x9f' + data + data + '\xff', '[' + expected + ", " + expected + ']');
+}
+
+void tst_QCborStreamReader::undefLengthMaps()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+ removeIndicators(expected);
+
+ // int keys
+ checkContainer(-1, "\xbf\1" + data + '\xff', "{1: " + expected + '}');
+ if (QTest::currentTestFailed())
+ return;
+
+ checkContainer(-2, "\xbf\1" + data + '\x20' + data + '\xff',
+ "{1: " + expected + ", -1: " + expected + '}');
+ if (QTest::currentTestFailed())
+ return;
+
+ // string keys
+ checkContainer(-1, "\xbf\x65Hello" + data + '\xff', "{\"Hello\": " + expected + '}');
+ if (QTest::currentTestFailed())
+ return;
+
+ checkContainer(-2, "\xbf\x65World" + data + "\x65Hello" + data + '\xff',
+ "{\"World\": " + expected + ", \"Hello\": " + expected + '}');
+}
+
+void tst_QCborStreamReader::next()
+{
+ QFETCH(QByteArray, data);
+
+ auto doit = [](QByteArray data) {
+ QFETCH_GLOBAL(bool, useDevice);
+
+ QBuffer buffer(&data);
+ QCborStreamReader reader(data);
+ if (useDevice) {
+ buffer.open(QIODevice::ReadOnly);
+ reader.setDevice(&buffer);
+ }
+ return reader.next();
+ };
+
+ QVERIFY(doit('\x81' + data));
+ QVERIFY(doit('\x82' + data + data));
+ QVERIFY(doit('\x9f' + data + '\xff'));
+ QVERIFY(doit("\x81\x9f" + data + '\xff'));
+ QVERIFY(doit("\x9f\x81" + data + '\xff'));
+
+ QVERIFY(doit("\xa1\1" + data));
+ QVERIFY(doit("\xa2\1" + data + '\x20' + data));
+ QVERIFY(doit("\xbf\1" + data + '\xff'));
+ QVERIFY(doit("\xbf\x9f\1\xff\x9f" + data + "\xff\xff"));
+}
+
+void tst_QCborStreamReader::validation_data()
+{
+ addValidationColumns();
+ addValidationData();
+}
+
+void tst_QCborStreamReader::validation()
+{
+ QFETCH_GLOBAL(bool, useDevice);
+ QFETCH(QByteArray, data);
+
+ QBuffer buffer(&data);
+ QCborStreamReader reader(data);
+ if (useDevice) {
+ buffer.open(QIODevice::ReadOnly);
+ reader.setDevice(&buffer);
+ }
+ parseOne(reader);
+ QVERIFY(reader.lastError() != QCborError::NoError);
+
+ // next() should fail
+ reader.reset();
+ QVERIFY(!reader.next());
+ QVERIFY(reader.lastError() != QCborError::NoError);
+}
+
+static const int Recursions = 3;
+void tst_QCborStreamReader::recursionLimit_data()
+{
+ static const int recursions = Recursions + 2;
+ QTest::addColumn<QByteArray>("data");
+
+ QTest::newRow("array") << QByteArray(recursions, '\x81') + '\x20';
+ QTest::newRow("_array") << QByteArray(recursions, '\x9f') + '\x20' + QByteArray(recursions, '\xff');
+
+ QByteArray data;
+ for (int i = 0; i < recursions; ++i)
+ data += "\xa1\x65Hello";
+ data += '\2';
+ QTest::newRow("map-recursive-values") << data;
+
+ data.clear();
+ for (int i = 0; i < recursions; ++i)
+ data += "\xbf\x65World";
+ data += '\2';
+ for (int i = 0; i < recursions; ++i)
+ data += "\xff";
+ QTest::newRow("_map-recursive-values") << data;
+
+ data = QByteArray(recursions, '\xa1');
+ data += '\2';
+ for (int i = 0; i < recursions; ++i)
+ data += "\x7f\x64quux\xff";
+ QTest::newRow("map-recursive-keys") << data;
+
+ data = QByteArray(recursions, '\xbf');
+ data += '\2';
+ for (int i = 0; i < recursions; ++i)
+ data += "\1\xff";
+ QTest::newRow("_map-recursive-keys") << data;
+
+ data.clear();
+ for (int i = 0; i < recursions / 2; ++i)
+ data += "\x81\xa1\1";
+ data += '\2';
+ QTest::newRow("mixed") << data;
+}
+
+void tst_QCborStreamReader::recursionLimit()
+{
+ QFETCH_GLOBAL(bool, useDevice);
+ QFETCH(QByteArray, data);
+
+ data.prepend('\x81');
+ QBuffer buffer(&data);
+ QCborStreamReader reader(data);
+ if (useDevice) {
+ buffer.open(QIODevice::ReadOnly);
+ reader.setDevice(&buffer);
+ }
+
+ // verify that it works normally:
+ QVERIFY(reader.enterContainer());
+ QVERIFY(reader.next());
+ QVERIFY(!reader.hasNext());
+
+ reader.reset();
+ QVERIFY(reader.enterContainer());
+ QVERIFY(!reader.next(Recursions));
+ QCOMPARE(reader.lastError(), QCborError::NestingTooDeep);
+}
+
+void tst_QCborStreamReader::addData_singleElement_data()
+{
+ addColumns();
+ addFixedData();
+ addNonChunkedStringsData();
+}
+
+void tst_QCborStreamReader::addData_singleElement()
+{
+ QFETCH_GLOBAL(bool, useDevice);
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+ removeIndicators(expected);
+
+ QByteArray growing;
+ QBuffer buffer(&growing);
+ QCborStreamReader reader;
+ if (useDevice) {
+ buffer.open(QIODevice::ReadOnly);
+ reader.setDevice(&buffer);
+ }
+ for (int i = 0; i < data.size() - 1; ++i) {
+ // add one byte from the data
+ if (useDevice) {
+ growing.append(data.at(i));
+ reader.reparse();
+ } else {
+ reader.addData(data.constData() + i, 1);
+ }
+
+ parseOne(reader);
+ QCOMPARE(reader.lastError(), QCborError::EndOfFile);
+ }
+
+ // add the last byte
+ if (useDevice) {
+ growing.append(data.right(1));
+ reader.reparse();
+ } else {
+ reader.addData(data.right(1));
+ }
+ QCOMPARE(reader.lastError(), QCborError::NoError);
+ QCOMPARE(parseOne(reader), expected);
+}
+
+void tst_QCborStreamReader::addData_complex()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(QString, expected);
+ removeIndicators(expected);
+
+ // transform tags (parseNonRecursive can't produce the usual form)
+ expected.replace(QRegularExpression(R"/((\d+)\(([^)]+)\))/"), "Tag:\\1:\\2");
+
+ auto doit = [](const QByteArray &data) {
+ QFETCH_GLOBAL(bool, useDevice);
+
+ // start with one byte
+ int added = 1;
+ QByteArray growing = data.left(added);
+ QBuffer buffer(&growing);
+ QCborStreamReader reader(growing);
+ if (useDevice) {
+ buffer.open(QIODevice::ReadOnly);
+ reader.setDevice(&buffer);
+ }
+
+ QString result;
+ bool printingStringChunks = false;
+ forever {
+ if (parseNonRecursive(result, printingStringChunks, reader))
+ return result;
+ if (reader.lastError() != QCborError::EndOfFile)
+ return reader.lastError().toString();
+
+ while (reader.lastError() == QCborError::EndOfFile) {
+ // add more data
+ if (added == data.size())
+ return QStringLiteral("Couldn't parse even with all data");
+
+ if (useDevice) {
+ growing.append(data.at(added));
+ reader.reparse();
+ } else {
+ reader.addData(data.constData() + added, 1);
+ }
+ ++added;
+ }
+ }
+ };
+
+ // plain:
+ QCOMPARE(doit(data), expected);
+
+ // in an array
+ QCOMPARE(doit('\x81' + data), '[' + expected + ']');
+ QCOMPARE(doit('\x82' + data + data), '[' + expected + ", " + expected + ']');
+
+ QCOMPARE(doit('\x9f' + data + '\xff'), '[' + expected + ']');
+ QCOMPARE(doit('\x9f' + data + data + '\xff'), '[' + expected + ", " + expected + ']');
+
+ // in a map
+ QCOMPARE(doit("\xa1\x01" + data), "{1, " + expected + '}');
+ QCOMPARE(doit("\xa1\x65Hello" + data), "{\"Hello\", " + expected + '}');
+ QCOMPARE(doit("\xa1\x7f\x65Hello\x65World\xff" + data), "{(\"Hello\", \"World\"), " + expected + '}');
+ QCOMPARE(doit("\xa2\x01" + data + "\x65Hello" + data),
+ "{1, " + expected + ", \"Hello\", " + expected + '}');
+
+ QCOMPARE(doit("\xbf\x01" + data + '\xff'), "{1, " + expected + '}');
+
+ // mixed
+ QCOMPARE(doit("\xbf\x01\x81" + data + '\xff'), "{1, [" + expected + "]}");
+ QCOMPARE(doit("\xbf\x01\x82" + data + data + '\xff'),
+ "{1, [" + expected + ", " + expected + "]}");
+ QCOMPARE(doit("\xbf\x01\x9f" + data + data + "\xff\xff"),
+ "{1, [" + expected + ", " + expected + "]}");
+}
+
+
+QTEST_MAIN(tst_QCborStreamReader)
+
+#include "tst_qcborstreamreader.moc"
diff --git a/tests/auto/corelib/serialization/qcborstreamwriter/qcborstreamwriter.pro b/tests/auto/corelib/serialization/qcborstreamwriter/qcborstreamwriter.pro
new file mode 100644
index 0000000000..3391b5a296
--- /dev/null
+++ b/tests/auto/corelib/serialization/qcborstreamwriter/qcborstreamwriter.pro
@@ -0,0 +1,8 @@
+QT = core testlib
+TARGET = tst_qcborstreamwriter
+CONFIG += testcase
+SOURCES += \
+ tst_qcborstreamwriter.cpp
+
+INCLUDEPATH += ../../../../../src/3rdparty/tinycbor/tests/encoder
+DEFINES += SRCDIR=\\\"$$PWD/\\\"
diff --git a/tests/auto/corelib/serialization/qcborstreamwriter/tst_qcborstreamwriter.cpp b/tests/auto/corelib/serialization/qcborstreamwriter/tst_qcborstreamwriter.cpp
new file mode 100644
index 0000000000..6995b4d08b
--- /dev/null
+++ b/tests/auto/corelib/serialization/qcborstreamwriter/tst_qcborstreamwriter.cpp
@@ -0,0 +1,313 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://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 <QtTest>
+
+class tst_QCborStreamWriter : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void initTestCase_data();
+ void fixed_data();
+ void fixed();
+ void strings_data();
+ void strings() { fixed(); }
+ void nonAsciiStrings_data();
+ void nonAsciiStrings();
+ void arraysAndMaps_data();
+ void arraysAndMaps() { fixed(); }
+ void tags_data();
+ void tags();
+ void arrays_data() { tags_data(); }
+ void arrays();
+ void maps_data() { tags_data(); }
+ void maps();
+};
+
+// Get the data from TinyCBOR (see src/3rdparty/tinycbor/tests/encoder/data.cpp)
+typedef quint64 CborTag;
+#include "data.cpp"
+
+void encodeVariant(QCborStreamWriter &writer, const QVariant &v)
+{
+ int type = v.userType();
+ switch (type) {
+ case QVariant::Int:
+ case QVariant::LongLong:
+ return writer.append(v.toLongLong());
+
+ case QVariant::UInt:
+ case QVariant::ULongLong:
+ return writer.append(v.toULongLong());
+
+ case QVariant::Bool:
+ return writer.append(v.toBool());
+
+ case QVariant::Invalid:
+ return writer.appendUndefined();
+
+ case QMetaType::VoidStar:
+ return writer.append(nullptr);
+
+ case QVariant::Double:
+ return writer.append(v.toDouble());
+
+ case QMetaType::Float:
+ return writer.append(v.toFloat());
+
+ case QVariant::String:
+ return writer.append(v.toString());
+
+ case QVariant::ByteArray:
+ return writer.append(v.toByteArray());
+
+ default:
+ if (type == qMetaTypeId<NegativeInteger>())
+ return writer.append(QCborNegativeInteger(v.value<NegativeInteger>().abs));
+ if (type == qMetaTypeId<SimpleType>())
+ return writer.append(QCborSimpleType(v.value<SimpleType>().type));
+ if (type == qMetaTypeId<qfloat16>())
+ return writer.append(v.value<qfloat16>());
+ if (type == qMetaTypeId<Tag>()) {
+ writer.append(QCborTag(v.value<Tag>().tag));
+ return encodeVariant(writer, v.value<Tag>().tagged);
+ }
+ if (type == QVariant::List || type == qMetaTypeId<IndeterminateLengthArray>()) {
+ QVariantList list = v.toList();
+ if (type == qMetaTypeId<IndeterminateLengthArray>()) {
+ list = v.value<IndeterminateLengthArray>();
+ writer.startArray();
+ } else {
+ writer.startArray(list.length());
+ }
+ for (const QVariant &v2 : qAsConst(list))
+ encodeVariant(writer, v2);
+ QVERIFY(writer.endArray());
+ return;
+ }
+ if (type == qMetaTypeId<Map>() || type == qMetaTypeId<IndeterminateLengthMap>()) {
+ Map map = v.value<Map>();
+ if (type == qMetaTypeId<IndeterminateLengthMap>()) {
+ map = v.value<IndeterminateLengthMap>();
+ writer.startMap();
+ } else {
+ writer.startMap(map.length());
+ }
+ for (auto pair : qAsConst(map)) {
+ encodeVariant(writer, pair.first);
+ encodeVariant(writer, pair.second);
+ }
+ QVERIFY(writer.endMap());
+ return;
+ }
+ }
+ QFAIL("Shouldn't have got here");
+}
+
+void compare(const QVariant &input, const QByteArray &output)
+{
+ QFETCH_GLOBAL(bool, useDevice);
+
+ if (useDevice) {
+ QBuffer buffer;
+ buffer.open(QIODevice::WriteOnly);
+ QCborStreamWriter writer(&buffer);
+ encodeVariant(writer, input);
+ QCOMPARE(buffer.data(), output);
+ } else {
+ QByteArray buffer;
+ QCborStreamWriter writer(&buffer);
+ encodeVariant(writer, input);
+ QCOMPARE(buffer, output);
+ }
+}
+
+void tst_QCborStreamWriter::initTestCase_data()
+{
+ QTest::addColumn<bool>("useDevice");
+ QTest::newRow("QByteArray") << false;
+ QTest::newRow("QIODevice") << true;
+}
+
+void tst_QCborStreamWriter::fixed_data()
+{
+ addColumns();
+ addFixedData();
+}
+
+void tst_QCborStreamWriter::fixed()
+{
+ QFETCH(QVariant, input);
+ QFETCH(QByteArray, output);
+ compare(input, output);
+}
+
+void tst_QCborStreamWriter::strings_data()
+{
+ addColumns();
+ addStringsData();
+}
+
+void tst_QCborStreamWriter::nonAsciiStrings_data()
+{
+ QTest::addColumn<QByteArray>("output");
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<bool>("isLatin1");
+
+ QByteArray latin1 = u8"Résumé";
+ QTest::newRow("shortlatin1")
+ << ("\x68" + latin1) << QString::fromUtf8(latin1) << true;
+
+ // replicate it 5 times (total 40 bytes)
+ latin1 += latin1 + latin1 + latin1 + latin1;
+ QTest::newRow("longlatin1")
+ << ("\x78\x28" + latin1) << QString::fromUtf8(latin1) << true;
+
+ QByteArray nonlatin1 = u8"ΧαίÏετε";
+ QTest::newRow("shortnonlatin1")
+ << ("\x6e" + nonlatin1) << QString::fromUtf8(nonlatin1) << false;
+
+ // replicate it 4 times (total 56 bytes)
+ nonlatin1 = nonlatin1 + nonlatin1 + nonlatin1 + nonlatin1;
+ QTest::newRow("longnonlatin1")
+ << ("\x78\x38" + nonlatin1) << QString::fromUtf8(nonlatin1) << false;
+}
+
+void tst_QCborStreamWriter::nonAsciiStrings()
+{
+ QFETCH(QByteArray, output);
+ QFETCH(QString, input);
+ QFETCH(bool, isLatin1);
+ QFETCH_GLOBAL(bool, useDevice);
+
+ // will be wrong if !isLatin1
+ QByteArray latin1 = input.toLatin1();
+
+ if (useDevice) {
+ {
+ QBuffer buffer;
+ buffer.open(QIODevice::WriteOnly);
+ QCborStreamWriter writer(&buffer);
+ writer.append(input);
+ QCOMPARE(buffer.data(), output);
+ }
+
+ if (isLatin1) {
+ QBuffer buffer;
+ buffer.open(QIODevice::WriteOnly);
+ QCborStreamWriter writer(&buffer);
+ writer.append(QLatin1String(latin1.constData(), latin1.size()));
+ QCOMPARE(buffer.data(), output);
+ }
+ } else {
+ {
+ QByteArray buffer;
+ QCborStreamWriter writer(&buffer);
+ encodeVariant(writer, input);
+ QCOMPARE(buffer, output);
+ }
+
+ if (isLatin1) {
+ QByteArray buffer;
+ QCborStreamWriter writer(&buffer);
+ writer.append(QLatin1String(latin1.constData(), latin1.size()));
+ QCOMPARE(buffer, output);
+ }
+ }
+}
+
+void tst_QCborStreamWriter::arraysAndMaps_data()
+{
+ addColumns();
+ addArraysAndMaps();
+}
+
+void tst_QCborStreamWriter::tags_data()
+{
+ addColumns();
+ addFixedData();
+ addStringsData();
+ addArraysAndMaps();
+}
+
+void tst_QCborStreamWriter::tags()
+{
+ QFETCH(QVariant, input);
+ QFETCH(QByteArray, output);
+
+ compare(QVariant::fromValue(Tag{1, input}), "\xc1" + output);
+}
+
+void tst_QCborStreamWriter::arrays()
+{
+ QFETCH(QVariant, input);
+ QFETCH(QByteArray, output);
+
+ compare(make_list(input), "\x81" + output);
+ if (QTest::currentTestFailed())
+ return;
+
+ compare(make_list(input, input), "\x82" + output + output);
+ if (QTest::currentTestFailed())
+ return;
+
+ // nested lists
+ compare(make_list(make_list(input)), "\x81\x81" + output);
+ if (QTest::currentTestFailed())
+ return;
+
+ compare(make_list(make_list(input), make_list(input)), "\x82\x81" + output + "\x81" + output);
+}
+
+void tst_QCborStreamWriter::maps()
+{
+ QFETCH(QVariant, input);
+ QFETCH(QByteArray, output);
+
+ compare(make_map({{1, input}}), "\xa1\1" + output);
+ if (QTest::currentTestFailed())
+ return;
+
+ compare(make_map({{1, input}, {input, 24}}), "\xa2\1" + output + output + "\x18\x18");
+}
+
+QTEST_MAIN(tst_QCborStreamWriter)
+
+#include "tst_qcborstreamwriter.moc"
diff --git a/tests/auto/corelib/serialization/qcborvalue/qcborvalue.pro b/tests/auto/corelib/serialization/qcborvalue/qcborvalue.pro
new file mode 100644
index 0000000000..9dd67da1f0
--- /dev/null
+++ b/tests/auto/corelib/serialization/qcborvalue/qcborvalue.pro
@@ -0,0 +1,11 @@
+QT = core testlib
+TARGET = tst_qcborvalue
+CONFIG += testcase
+SOURCES += \
+ tst_qcborvalue.cpp
+
+INCLUDEPATH += \
+ ../../../../../src/3rdparty/tinycbor/src \
+ ../../../../../src/3rdparty/tinycbor/tests/parser
+
+DEFINES += SRCDIR=\\\"$$PWD/\\\"
diff --git a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp
new file mode 100644
index 0000000000..38b26e7de4
--- /dev/null
+++ b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp
@@ -0,0 +1,1695 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://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 <QtCore/qcborvalue.h>
+#include <QtTest>
+
+Q_DECLARE_METATYPE(QCborValue)
+Q_DECLARE_METATYPE(QCborValue::EncodingOptions)
+
+class tst_QCborValue : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void basics_data();
+ void basics();
+ void tagged_data() { basics_data(); }
+ void tagged();
+ void extendedTypes_data();
+ void extendedTypes();
+ void copyCompare_data() { basics_data(); }
+ void copyCompare();
+
+ void arrayDefaultInitialization();
+ void arrayEmptyInitializerList();
+ void arrayEmptyDetach();
+ void arrayInitializerList();
+ void arrayMutation();
+ void arrayPrepend();
+ void arrayInsertRemove_data() { basics_data(); }
+ void arrayInsertRemove();
+ void arrayInsertTagged_data() { basics_data(); }
+ void arrayInsertTagged();
+ void arrayStringElements();
+ void arraySelfAssign_data() { basics_data(); }
+ void arraySelfAssign();
+
+ void mapDefaultInitialization();
+ void mapEmptyInitializerList();
+ void mapEmptyDetach();
+ void mapSimpleInitializerList();
+ void mapMutation();
+ void mapStringValues();
+ void mapStringKeys();
+ void mapInsertRemove_data() { basics_data(); }
+ void mapInsertRemove();
+ void mapInsertTagged_data() { basics_data(); }
+ void mapInsertTagged();
+ void mapSelfAssign_data() { basics_data(); }
+ void mapSelfAssign();
+ void mapComplexKeys_data() { basics_data(); }
+ void mapComplexKeys();
+
+ void sorting();
+
+ void toCbor_data();
+ void toCbor();
+ void fromCbor_data();
+ void fromCbor();
+ void validation_data();
+ void validation();
+ void toDiagnosticNotation_data();
+ void toDiagnosticNotation();
+};
+
+// Get the validation data from TinyCBOR (see src/3rdparty/tinycbor/tests/parser/data.cpp)
+#include "data.cpp"
+
+struct SimpleTypeWrapper
+{
+ // QCborSimpleType is an enum, so QVariant knows how to convert it to
+ // integer and we don't want it to do that.
+ SimpleTypeWrapper(QCborSimpleType type = {}) : st(type) {}
+ QCborSimpleType st;
+};
+Q_DECLARE_METATYPE(SimpleTypeWrapper)
+
+void tst_QCborValue::basics_data()
+{
+ QTest::addColumn<QCborValue::Type>("type");
+ QTest::addColumn<QCborValue>("v");
+ QTest::addColumn<QVariant>("expectedValue");
+ QDateTime dt = QDateTime::currentDateTimeUtc();
+ QUuid uuid = QUuid::createUuid();
+
+ QMetaEnum me = QMetaEnum::fromType<QCborValue::Type>();
+ auto add = [me](QCborValue::Type t, const QCborValue &v, const QVariant &exp) {
+ auto addRow = [=]() -> QTestData & {
+ const char *typeString = me.valueToKey(t);
+ if (t == QCborValue::Integer)
+ return QTest::addRow("Integer:%lld", exp.toLongLong());
+ if (t == QCborValue::Double)
+ return QTest::addRow("Double:%g", exp.toDouble());
+ if (t == QCborValue::ByteArray || t == QCborValue::String)
+ return QTest::addRow("%s:%d", typeString, exp.toString().size());
+ return QTest::newRow(typeString);
+ };
+ addRow() << t << v << exp;
+ };
+ auto st = [](QCborSimpleType t) { return QVariant::fromValue<SimpleTypeWrapper>(t); };
+
+ add(QCborValue::Undefined, QCborValue(), st(QCborSimpleType::Undefined));
+ add(QCborValue::Null, QCborValue::Null, st(QCborSimpleType::Null));
+ QTest::newRow("nullptr") << QCborValue::Null << QCborValue(nullptr)
+ << st(QCborSimpleType::Null);
+ add(QCborValue::False, false, st(QCborSimpleType::False));
+ QTest::newRow("false") << QCborValue::False << QCborValue(QCborValue::False)
+ << st(QCborSimpleType::False);
+ add(QCborValue::True, true, st(QCborSimpleType::True));
+ QTest::newRow("true") << QCborValue::True << QCborValue(QCborValue::True)
+ << st(QCborSimpleType::True);
+ QTest::newRow("simpletype") << QCborValue::Type(QCborValue::SimpleType + 255)
+ << QCborValue(QCborSimpleType(255))
+ << st(QCborSimpleType(255));
+ add(QCborValue::Integer, 0, 0);
+ add(QCborValue::Integer, 1, 1);
+ add(QCborValue::Integer, -1, -1);
+ add(QCborValue::Integer, std::numeric_limits<qint64>::min(), std::numeric_limits<qint64>::min());
+ add(QCborValue::Integer, std::numeric_limits<qint64>::max(), std::numeric_limits<qint64>::max());
+ add(QCborValue::Double, 0., 0.);
+ add(QCborValue::Double, 1.25, 1.25);
+ add(QCborValue::Double, -1.25, -1.25);
+ add(QCborValue::Double, qInf(), qInf());
+ add(QCborValue::Double, -qInf(), -qInf());
+ add(QCborValue::Double, qQNaN(), qQNaN());
+ add(QCborValue::ByteArray, QByteArray("Hello"), QByteArray("Hello"));
+ add(QCborValue::ByteArray, QByteArray(), QByteArray());
+ add(QCborValue::String, "Hello", "Hello");
+ add(QCborValue::String, QLatin1String(), QString());
+ add(QCborValue::DateTime, QCborValue(dt), dt);
+ add(QCborValue::Url, QCborValue(QUrl("http://example.com")), QUrl("http://example.com"));
+ add(QCborValue::RegularExpression, QCborValue(QRegularExpression("^.*$")), QRegularExpression("^.*$"));
+ add(QCborValue::Uuid, QCborValue(uuid), uuid);
+
+ // empty arrays and maps
+ add(QCborValue::Array, QCborArray(), QVariantList());
+ add(QCborValue::Map, QCborMap(), QVariantMap());
+}
+
+static void basicTypeCheck(QCborValue::Type type, const QCborValue &v, const QVariant &expectedValue)
+{
+ bool isSimpleType = (expectedValue.userType() == qMetaTypeId<SimpleTypeWrapper>());
+ QCborSimpleType st = expectedValue.value<SimpleTypeWrapper>().st;
+
+ QCOMPARE(v.type(), type);
+ QCOMPARE(v.isInteger(), type == QCborValue::Integer);
+ QCOMPARE(v.isByteArray(), type == QCborValue::ByteArray);
+ QCOMPARE(v.isString(), type == QCborValue::String);
+ QCOMPARE(v.isArray(), type == QCborValue::Array);
+ QCOMPARE(v.isMap(), type == QCborValue::Map);
+ QCOMPARE(v.isFalse(), type == QCborValue::False);
+ QCOMPARE(v.isTrue(), type == QCborValue::True);
+ QCOMPARE(v.isBool(), type == QCborValue::False || type == QCborValue::True);
+ QCOMPARE(v.isNull(), type == QCborValue::Null);
+ QCOMPARE(v.isUndefined(), type == QCborValue::Undefined);
+ QCOMPARE(v.isDouble(), type == QCborValue::Double);
+ QCOMPARE(v.isDateTime(), type == QCborValue::DateTime);
+ QCOMPARE(v.isUrl(), type == QCborValue::Url);
+ QCOMPARE(v.isUuid(), type == QCborValue::Uuid);
+ QCOMPARE(v.isInvalid(), type == QCborValue::Invalid);
+ QCOMPARE(v.isContainer(), type == QCborValue::Array || type == QCborValue::Map);
+ QCOMPARE(v.isSimpleType(), isSimpleType);
+ QCOMPARE(v.isSimpleType(QCborSimpleType::False), st == QCborSimpleType::False);
+ QCOMPARE(v.isSimpleType(QCborSimpleType::True), st == QCborSimpleType::True);
+ QCOMPARE(v.isSimpleType(QCborSimpleType::Null), st == QCborSimpleType::Null);
+ QCOMPARE(v.isSimpleType(QCborSimpleType::Undefined), st == QCborSimpleType::Undefined);
+ QCOMPARE(v.isSimpleType(QCborSimpleType(255)), st == QCborSimpleType(255));
+
+ if (v.isInteger()) {
+ QCOMPARE(v.toInteger(), expectedValue.toLongLong());
+ QCOMPARE(v.toDouble(), 0. + expectedValue.toLongLong());
+ } else {
+ QCOMPARE(v.toInteger(), qint64(expectedValue.toDouble()));
+ QCOMPARE(v.toDouble(), expectedValue.toDouble());
+ }
+ QCOMPARE(v.toBool(true), st != QCborSimpleType::False);
+ QCOMPARE(v.toBool(), st == QCborSimpleType::True);
+ if (st == QCborSimpleType::Undefined)
+ QCOMPARE(v.toSimpleType(QCborSimpleType::Null), QCborSimpleType::Undefined);
+ else if (isSimpleType)
+ QCOMPARE(v.toSimpleType(), st);
+ else
+ QCOMPARE(v.toSimpleType(), QCborSimpleType::Undefined);
+
+#define CMP(expr, T, validexpr) \
+ if (expectedValue.userType() == qMetaTypeId<T>()) \
+ QCOMPARE(expr, expectedValue.value<T>()); \
+ else \
+ QVERIFY(validexpr)
+ CMP(v.toByteArray(), QByteArray, v.toByteArray().isNull());
+ CMP(v.toString(), QString, v.toString().isNull());
+ CMP(v.toDateTime(), QDateTime, !v.toDateTime().isValid());
+ CMP(v.toUrl(), QUrl, !v.toUrl().isValid());
+ CMP(v.toRegularExpression(), QRegularExpression, v.toRegularExpression().pattern().isNull());
+ CMP(v.toUuid(), QUuid, v.toUuid().isNull());
+#undef CMP
+
+ QVERIFY(v.toArray().isEmpty());
+ QVERIFY(v.toMap().isEmpty());
+
+ QVERIFY(v["Hello"].isUndefined());
+ QVERIFY(v[0].isUndefined());
+}
+
+void tst_QCborValue::basics()
+{
+ QFETCH(QCborValue::Type, type);
+ QFETCH(QCborValue, v);
+ QFETCH(QVariant, expectedValue);
+
+ basicTypeCheck(type, v, expectedValue);
+}
+
+void tst_QCborValue::tagged()
+{
+ QFETCH(QCborValue::Type, type);
+ QFETCH(QCborValue, v);
+ QFETCH(QVariant, expectedValue);
+
+ // make it tagged
+ QCborValue tagged(QCborKnownTags::Signature, v);
+ QVERIFY(tagged.isTag());
+ QCOMPARE(tagged.tag(), QCborTag(QCborKnownTags::Signature));
+
+ // shouldn't compare equal
+ QVERIFY(tagged != v);
+ QVERIFY(v != tagged);
+
+ // ensure we can reach the original value
+ basicTypeCheck(type, tagged.taggedValue(), expectedValue);
+ QVERIFY(tagged.taggedValue() == v);
+ QVERIFY(v == tagged.taggedValue());
+
+ // nested tagging should work too
+ QCborValue tagged2(QCborKnownTags::EncodedCbor, tagged);
+ QVERIFY(tagged2.isTag());
+ QCOMPARE(tagged2.tag(), QCborTag(QCborKnownTags::EncodedCbor));
+
+ QVERIFY(tagged2 != tagged);
+ QVERIFY(tagged != tagged2);
+
+ QVERIFY(tagged2.taggedValue() == tagged);
+ QVERIFY(tagged == tagged2.taggedValue());
+ QVERIFY(tagged2.taggedValue().taggedValue() == v);
+ QVERIFY(v == tagged2.taggedValue().taggedValue());
+}
+
+void tst_QCborValue::extendedTypes_data()
+{
+ QTest::addColumn<QCborValue>("extended");
+ QTest::addColumn<QCborValue>("tagged");
+ QDateTime dt = QDateTime::currentDateTimeUtc();
+ QUuid uuid = QUuid::createUuid();
+
+ QTest::newRow("DateTime") << QCborValue(dt)
+ << QCborValue(QCborKnownTags::DateTimeString, dt.toString(Qt::ISODateWithMs));
+ QTest::newRow("Url:Empty") << QCborValue(QUrl())
+ << QCborValue(QCborKnownTags::Url, QString());
+ QTest::newRow("Url:Authority") << QCborValue(QUrl("https://example.com"))
+ << QCborValue(QCborKnownTags::Url, "https://example.com");
+ QTest::newRow("Url:Path") << QCborValue(QUrl("file:///tmp/none"))
+ << QCborValue(QCborKnownTags::Url, "file:///tmp/none");
+ QTest::newRow("Url:QueryFragment") << QCborValue(QUrl("whatever:?a=b&c=d#e"))
+ << QCborValue(QCborKnownTags::Url, "whatever:?a=b&c=d#e");
+ QTest::newRow("Regex:Empty") << QCborValue(QRegularExpression())
+ << QCborValue(QCborKnownTags::RegularExpression, QString());
+ QTest::newRow("Regex") << QCborValue(QRegularExpression("^.*$"))
+ << QCborValue(QCborKnownTags::RegularExpression, QString("^.*$"));
+ QTest::newRow("Uuid") << QCborValue(uuid)
+ << QCborValue(QCborKnownTags::Uuid, uuid.toRfc4122());
+}
+
+void tst_QCborValue::extendedTypes()
+{
+ QFETCH(QCborValue, extended);
+ QFETCH(QCborValue, tagged);
+ QVERIFY(extended.isTag());
+ QVERIFY(tagged.isTag());
+ QVERIFY(extended == tagged);
+ QVERIFY(tagged == extended);
+
+ QCOMPARE(extended.tag(), tagged.tag());
+ QCOMPARE(extended.taggedValue(), tagged.taggedValue());
+}
+
+void tst_QCborValue::copyCompare()
+{
+ QFETCH(QCborValue, v);
+ QCborValue other = v;
+ other = v;
+ v = other;
+
+ QCOMPARE(v.compare(other), 0);
+ QCOMPARE(v, other);
+ QVERIFY(!(v != other));
+ QVERIFY(!(v < other));
+#if QT_HAS_INCLUDE(<compare>)
+ QVERIFY(v <= other);
+ QVERIFY(v >= other);
+ QVERIFY(!(v > other));
+#endif
+
+ if (v.isUndefined())
+ other = nullptr;
+ else
+ other = {};
+ QVERIFY(v.type() != other.type());
+ QVERIFY(!(v == other));
+ QVERIFY(v != other);
+
+ // they're different types, so they can't compare equal
+ QVERIFY(v.compare(other) != 0);
+ QVERIFY((v < other) || (other < v));
+}
+
+void tst_QCborValue::arrayDefaultInitialization()
+{
+ QCborArray a;
+ QVERIFY(a.isEmpty());
+ QCOMPARE(a.size(), 0);
+ QVERIFY(!a.contains(0));
+ QVERIFY(!a.contains(-1));
+ QVERIFY(!a.contains(false));
+ QVERIFY(!a.contains(true));
+ QVERIFY(!a.contains(nullptr));
+ QVERIFY(!a.contains({}));
+ QVERIFY(!a.contains(1.0));
+ QVERIFY(!a.contains(QByteArray("Hello")));
+ QVERIFY(!a.contains("Hello"));
+ QVERIFY(!a.contains(QCborArray()));
+ QVERIFY(!a.contains(QCborMap()));
+ QVERIFY(!a.contains(QCborValue(QDateTime::currentDateTimeUtc())));
+ QVERIFY(!a.contains(QCborValue(QUrl("http://example.com"))));
+ QVERIFY(!a.contains(QCborValue(QUuid::createUuid())));
+
+ QVERIFY(a.at(0).isUndefined());
+ QCOMPARE(a.constBegin(), a.constEnd());
+
+ QVERIFY(a == a);
+ QVERIFY(a == QCborArray());
+ QVERIFY(QCborArray() == a);
+
+ QCborValue v(a);
+ QVERIFY(v.isArray());
+ QVERIFY(!v.isMap());
+ QVERIFY(!v.isTag());
+ QVERIFY(v[0].isUndefined());
+
+ QCborArray a2 = v.toArray();
+ QVERIFY(a2.isEmpty());
+ QCOMPARE(a2, a);
+}
+
+void tst_QCborValue::mapDefaultInitialization()
+{
+ QCborMap m;
+ QVERIFY(m.isEmpty());
+ QCOMPARE(m.size(), 0);
+ QVERIFY(m.keys().isEmpty());
+ QVERIFY(!m.contains(0));
+ QVERIFY(!m.contains(-1));
+ QVERIFY(!m.contains(false));
+ QVERIFY(!m.contains(true));
+ QVERIFY(!m.contains(QCborValue::Null));
+ QVERIFY(!m.contains({}));
+ QVERIFY(!m.contains(1.0));
+ QVERIFY(!m.contains(QLatin1String("Hello")));
+ QVERIFY(!m.contains(QStringLiteral("Hello")));
+ QVERIFY(!m.contains(QCborValue(QByteArray("Hello"))));
+ QVERIFY(!m.contains(QCborArray()));
+ QVERIFY(!m.contains(QCborMap()));
+ QVERIFY(!m.contains(QCborValue(QDateTime::currentDateTimeUtc())));
+ QVERIFY(!m.contains(QCborValue(QUrl("http://example.com"))));
+ QVERIFY(!m.contains(QCborValue(QUuid::createUuid())));
+
+ QVERIFY(m.value(0).isUndefined());
+ QVERIFY(m.value(QLatin1String("Hello")).isUndefined());
+ QVERIFY(m.value(QStringLiteral("Hello")).isUndefined());
+ QVERIFY(m.value(QCborValue()).isUndefined());
+#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
+ QVERIFY(m.value("Hello").isUndefined());
+#endif
+
+ QVERIFY(m == m);
+ QVERIFY(m == QCborMap{});
+ QVERIFY(QCborMap{} == m);
+
+ QCborValue v(m);
+ QVERIFY(v.isMap());
+ QVERIFY(!v.isArray());
+ QVERIFY(!v.isTag());
+ QVERIFY(v[0].isUndefined());
+ QVERIFY(v[QLatin1String("Hello")].isUndefined());
+ QVERIFY(v["Hello"].isUndefined());
+
+ QCborMap m2 = v.toMap();
+ QVERIFY(m2.isEmpty());
+ QCOMPARE(m2.size(), 0);
+ QCOMPARE(m2, m);
+}
+
+void tst_QCborValue::arrayEmptyInitializerList()
+{
+ QCborArray a{};
+ QVERIFY(a.isEmpty());
+ QCOMPARE(a.size(), 0);
+ QVERIFY(a == a);
+ QVERIFY(a == QCborArray());
+ QVERIFY(QCborArray() == a);
+}
+
+void tst_QCborValue::mapEmptyInitializerList()
+{
+ QCborMap m{};
+ QVERIFY(m.isEmpty());
+ QCOMPARE(m.size(), 0);
+ QVERIFY(m == m);
+ QVERIFY(m == QCborMap{});
+ QVERIFY(QCborMap{} == m);
+}
+
+void tst_QCborValue::arrayEmptyDetach()
+{
+ QCborArray a;
+ QCOMPARE(a.begin(), a.end());
+ QVERIFY(a.isEmpty());
+ QCOMPARE(a.size(), 0);
+
+ QVERIFY(a == a);
+ QVERIFY(a == QCborArray());
+ QVERIFY(QCborArray() == a);
+
+ QCborValue v(a);
+ QVERIFY(v.isArray());
+ QVERIFY(!v.isMap());
+ QVERIFY(!v.isTag());
+
+ QCborArray a2 = v.toArray();
+ QVERIFY(a2.isEmpty());
+ QCOMPARE(a2, a);
+}
+
+void tst_QCborValue::mapEmptyDetach()
+{
+ QCborMap m;
+ QCOMPARE(m.begin(), m.end());
+ QVERIFY(m.isEmpty());
+ QCOMPARE(m.size(), 0);
+
+ QVERIFY(m == m);
+ QVERIFY(m == QCborMap{});
+ QVERIFY(QCborMap{} == m);
+
+ QCborValue v(m);
+ QVERIFY(v.isMap());
+ QVERIFY(!v.isArray());
+ QVERIFY(!v.isTag());
+
+ QCborMap m2 = v.toMap();
+ QVERIFY(m2.isEmpty());
+ QCOMPARE(m2, m);
+}
+
+void tst_QCborValue::arrayInitializerList()
+{
+ QCborArray a{0, -1, false, true, nullptr, {}, 1.0};
+ QVERIFY(!a.isEmpty());
+ QCOMPARE(a.size(), 7);
+ QCOMPARE(a.at(0), QCborValue(0));
+ QCOMPARE(a.at(1), QCborValue(-1));
+ QCOMPARE(a.at(2), QCborValue(QCborValue::False));
+ QCOMPARE(a.at(3), QCborValue(QCborValue::True));
+ QCOMPARE(a.at(4), QCborValue(QCborValue::Null));
+ QCOMPARE(a.at(5), QCborValue(QCborValue::Undefined));
+ QCOMPARE(a.at(6), QCborValue(1.0));
+
+ QVERIFY(a == a);
+ QVERIFY(a != QCborArray{});
+ QVERIFY(QCborArray{} != a);
+ QVERIFY(a == QCborArray({0, -1, false, true, nullptr, {}, 1.0}));
+
+ QCborValue v = a;
+ QCOMPARE(v[0], QCborValue(0));
+ QCOMPARE(v[1], QCborValue(-1));
+ QCOMPARE(v[2], QCborValue(QCborValue::False));
+ QCOMPARE(v[3], QCborValue(QCborValue::True));
+ QCOMPARE(v[4], QCborValue(QCborValue::Null));
+ QCOMPARE(v[5], QCborValue(QCborValue::Undefined));
+ QCOMPARE(v[6], QCborValue(1.0));
+
+ QVERIFY(a.contains(0));
+ QVERIFY(a.contains(-1));
+ QVERIFY(a.contains(false));
+ QVERIFY(a.contains(true));
+ QVERIFY(a.contains(nullptr));
+ QVERIFY(a.contains({}));
+ QVERIFY(a.contains(1.0));
+ QVERIFY(!a.contains(QByteArray("Hello")));
+ QVERIFY(!a.contains("Hello"));
+ QVERIFY(!a.contains(QCborArray()));
+ QVERIFY(!a.contains(QCborMap()));
+ QVERIFY(!a.contains(QCborValue(QDateTime::currentDateTimeUtc())));
+ QVERIFY(!a.contains(QCborValue(QUrl("http://example.com"))));
+ QVERIFY(!a.contains(QCborValue(QUuid::createUuid())));
+
+ // iterators
+ auto it = a.constBegin();
+ auto end = a.constEnd();
+ QCOMPARE(end - it, 7);
+ QCOMPARE(it + 7, end);
+ QVERIFY(it->isInteger());
+ QCOMPARE(*it, QCborValue(0));
+ QCOMPARE(it[1], QCborValue(-1));
+ QCOMPARE(*(it + 2), QCborValue(false));
+ it += 3;
+ QCOMPARE(*it, QCborValue(true));
+ ++it;
+ QCOMPARE(*it, QCborValue(nullptr));
+ it++;
+ QCOMPARE(*it, QCborValue());
+ --end;
+ QCOMPARE(*end, QCborValue(1.0));
+ end--;
+ QCOMPARE(it, end);
+
+ // range for
+ int i = 0;
+ for (const QCborValue &v : qAsConst(a)) {
+ QVERIFY(!v.isInvalid());
+ QCOMPARE(v.isUndefined(), i == 5); // 6th element is Undefined
+ ++i;
+ }
+ QCOMPARE(i, a.size());
+}
+
+void tst_QCborValue::mapSimpleInitializerList()
+{
+ QCborMap m{{0, 0}, {1, 0}, {2, "Hello"}, {"Hello", 2}, {3, QLatin1String("World")}, {QLatin1String("World"), 3}};
+ QCOMPARE(m.size(), 6);
+ QVERIFY(m == m);
+ QVERIFY(m != QCborMap{});
+ QVERIFY(QCborMap{} != m);
+ QVERIFY(m == QCborMap({{0, 0}, {1, 0}, {2, "Hello"}, {"Hello", 2}, {3, QLatin1String("World")}, {QLatin1String("World"), 3}}));
+
+ QCborValue vmap = m;
+ {
+ QVERIFY(m.contains(0));
+ QCborValue v = m.value(0);
+ QVERIFY(v.isInteger());
+ QCOMPARE(v.toInteger(), 0);
+ QCOMPARE(vmap[0], v);
+ }
+ {
+ QVERIFY(m.contains(1));
+ QCborValue v = m.value(1);
+ QVERIFY(v.isInteger());
+ QCOMPARE(v.toInteger(), 0);
+ QCOMPARE(vmap[1], v);
+ }
+ {
+ QVERIFY(m.contains(2));
+ QCborValue v = m.value(2);
+ QVERIFY(v.isString());
+ QCOMPARE(v.toString(), "Hello");
+ QCOMPARE(vmap[2], v);
+ }
+ {
+ QVERIFY(m.contains(3));
+ QCborValue v = m.value(3);
+ QVERIFY(v.isString());
+ QCOMPARE(v.toString(), "World");
+ QCOMPARE(vmap[3], v);
+ }
+ {
+ QVERIFY(m.contains(QStringLiteral("Hello")));
+ QCborValue v = m.value(QLatin1String("Hello"));
+ QVERIFY(v.isInteger());
+ QCOMPARE(v.toInteger(), 2);
+ QCOMPARE(vmap[QStringLiteral("Hello")], v);
+ }
+ {
+ QVERIFY(m.contains(QLatin1String("World")));
+ QCborValue v = m.value(QStringLiteral("World"));
+ QVERIFY(v.isInteger());
+ QCOMPARE(v.toInteger(), 3);
+ QCOMPARE(vmap[QLatin1String("World")], v);
+ }
+
+ QVERIFY(!m.contains(QCborValue::Null));
+ QVERIFY(!m.contains(QCborValue()));
+ QVERIFY(!m.contains(QCborValue(1.0))); // Important: 1.0 does not match 1
+ QVERIFY(!m.contains(QCborValue(QByteArray("Hello"))));
+ QVERIFY(!m.contains(QCborArray()));
+ QVERIFY(!m.contains(QCborMap()));
+ QVERIFY(!m.contains(QCborValue(QDateTime::currentDateTimeUtc())));
+ QVERIFY(!m.contains(QCborValue(QUrl("http://example.com"))));
+ QVERIFY(!m.contains(QCborValue(QUuid::createUuid())));
+
+ // iterators (QCborMap is not sorted)
+ auto it = m.constBegin();
+ auto end = m.constEnd();
+ QCOMPARE(end - it, 6);
+ QCOMPARE(it + 6, end);
+ QCOMPARE(it.key(), QCborValue(0));
+ QCOMPARE(it.value(), QCborValue(0));
+ QVERIFY(it->isInteger());
+ ++it;
+ QCOMPARE(it.key(), QCborValue(1));
+ QCOMPARE(it.value(), QCborValue(0));
+ QCOMPARE((it + 1).key(), QCborValue(2));
+ QVERIFY((it + 1)->isString());
+ QCOMPARE((it + 1)->toString(), "Hello");
+ it += 2;
+ QCOMPARE(it.key(), QCborValue("Hello"));
+ QVERIFY(it->isInteger());
+ it++;
+ QCOMPARE(it.key(), QCborValue(3));
+ QVERIFY(it->isString());
+ QCOMPARE(it.value().toString(), "World");
+ --end;
+ QCOMPARE(end.key(), QCborValue("World"));
+ QCOMPARE(end.value(), QCborValue(3));
+ end--;
+ QCOMPARE(it, end);
+
+ // range for
+ int i = 0;
+ for (auto pair : qAsConst(m)) {
+ QVERIFY(!pair.first.isUndefined());
+ QVERIFY(!pair.second.isUndefined());
+ ++i;
+ }
+ QCOMPARE(i, m.size());
+}
+
+void tst_QCborValue::arrayMutation()
+{
+ QCborArray a{42};
+ {
+ QCborValueRef v = a[0];
+ QVERIFY(!a.isEmpty());
+ QVERIFY(v.isInteger());
+ QCOMPARE(v.toInteger(), 42);
+
+ // now mutate the list
+ v = true;
+ QVERIFY(v.isBool());
+ QVERIFY(v.isTrue());
+ QVERIFY(a.at(0).isTrue());
+ QVERIFY(a.at(0) == v);
+ QVERIFY(v == a.at(0));
+ }
+
+ QVERIFY(a == a);
+ QVERIFY(a == QCborArray{true});
+
+ QCborArray a2 = a;
+ a.append(nullptr);
+ QCOMPARE(a.size(), 2);
+ QCOMPARE(a2.size(), 1);
+
+ // self-insertion
+ a2.append(a2);
+ QCOMPARE(a2.size(), 2);
+ QCOMPARE(a2.last().toArray().size(), 1);
+
+ QCborValueRef v = a[0];
+ QVERIFY(v.isTrue());
+ v = 2.5;
+ QVERIFY(v.isDouble());
+ QVERIFY(a.first().isDouble());
+ QVERIFY(a.last().isNull());
+ QVERIFY(a2.first().isTrue());
+
+ a2 = a;
+ auto it = a.begin(); // detaches again
+ auto end = a.end();
+ QCOMPARE(end - it, 2);
+ QCOMPARE(it + 2, end);
+ QCOMPARE(*it, QCborValue(2.5));
+ QCOMPARE(*++it, QCborValue(nullptr));
+ QVERIFY(a2 == a);
+ QVERIFY(a == a2);
+
+ *it = -1;
+ QCOMPARE(*it, QCborValue(-1));
+ QCOMPARE(a.at(1), QCborValue(-1));
+ QCOMPARE(a2.at(1), QCborValue(nullptr));
+ QCOMPARE(++it, end);
+}
+
+void tst_QCborValue::mapMutation()
+{
+ QCborMap m;
+ QVERIFY(m.isEmpty());
+
+ {
+ QCborValueRef v = m[42];
+ QCOMPARE(m.size(), 1);
+ QVERIFY(v.isUndefined());
+
+ // now mutate the list
+ v = true;
+ QVERIFY(v.isBool());
+ QVERIFY(v.isTrue());
+ QVERIFY(m.begin()->isTrue());
+ QVERIFY(m.begin().value() == v);
+ QVERIFY(v == m.begin().value());
+ }
+
+ QVERIFY(m == QCborMap({{42, true}}));
+ QVERIFY(QCborMap({{42, true}}) == m);
+
+ QCborMap m2 = m;
+ m.insert({nullptr, nullptr});
+ QCOMPARE(m.size(), 2);
+ QCOMPARE(m2.size(), 1);
+
+ QCborValueRef v = m[42];
+ QVERIFY(v.isTrue());
+ v = 2.5;
+ QVERIFY(v.isDouble());
+ QVERIFY(m.begin()->isDouble());
+ QVERIFY((m.end() - 1)->isNull());
+ QVERIFY(m2.begin()->isTrue());
+
+ m2 = m;
+ auto it = m.begin(); // detaches again
+ auto end = m.end();
+ QCOMPARE(end - it, 2);
+ QCOMPARE(it + 2, end);
+ QCOMPARE(it.key(), QCborValue(42));
+ QCOMPARE(it.value(), QCborValue(2.5));
+ QCOMPARE((++it).value(), QCborValue(nullptr));
+ QCOMPARE(it.key(), QCborValue(nullptr));
+ QVERIFY(m2 == m);
+ QVERIFY(m == m2);
+
+ it.value() = -1;
+ QCOMPARE(it.key(), QCborValue(nullptr));
+ QCOMPARE(it.value(), QCborValue(-1));
+ QCOMPARE((m.end() - 1)->toInteger(), -1);
+ QVERIFY((m2.end() - 1)->isNull());
+ QCOMPARE(++it, end);
+}
+
+void tst_QCborValue::arrayPrepend()
+{
+ QCborArray a;
+ a.prepend(0);
+ a.prepend(nullptr);
+ QCOMPARE(a.at(1), QCborValue(0));
+ QCOMPARE(a.at(0), QCborValue(nullptr));
+ QCOMPARE(a.size(), 2);
+}
+
+void tst_QCborValue::arrayInsertRemove()
+{
+ QFETCH(QCborValue, v);
+ QCborArray a;
+ a.append(42);
+ a.append(v);
+ a.insert(1, QCborValue(nullptr));
+ QCOMPARE(a.at(0), QCborValue(42));
+ QCOMPARE(a.at(1), QCborValue(nullptr));
+ QCOMPARE(a.at(2), v);
+
+ // remove 42
+ a.removeAt(0);
+ QCOMPARE(a.size(), 2);
+ QCOMPARE(a.at(0), QCborValue(nullptr));
+ QCOMPARE(a.at(1), v);
+
+ auto it = a.begin();
+ it = a.erase(it); // removes nullptr
+ QCOMPARE(a.size(), 1);
+ QCOMPARE(a.at(0), v);
+
+ it = a.erase(it);
+ QVERIFY(a.isEmpty());
+ QCOMPARE(it, a.end());
+
+ // reinsert the element so we can take it
+ a.append(v);
+ QCOMPARE(a.takeAt(0), v);
+ QVERIFY(a.isEmpty());
+}
+
+void tst_QCborValue::arrayStringElements()
+{
+ QCborArray a{"Hello"};
+ a.append(QByteArray("Hello"));
+ a.append(QLatin1String("World"));
+ QVERIFY(a == a);
+ QVERIFY(a == QCborArray({QLatin1String("Hello"),
+ QByteArray("Hello"), QStringLiteral("World")}));
+
+ QCborValueRef r1 = a[0];
+ QCOMPARE(r1.toString(), "Hello");
+ QCOMPARE(r1.operator QCborValue(), QCborValue("Hello"));
+ QVERIFY(r1 == QCborValue("Hello"));
+
+ QCborValue v2 = a.at(1);
+ QCOMPARE(v2.toByteArray(), QByteArray("Hello"));
+ QCOMPARE(v2, QCborValue(QByteArray("Hello")));
+
+ // v2 must continue to be valid after the entry getting removed
+ a.removeAt(1);
+ QCOMPARE(v2.toByteArray(), QByteArray("Hello"));
+ QCOMPARE(v2, QCborValue(QByteArray("Hello")));
+
+ v2 = a.at(1);
+ QCOMPARE(v2.toString(), "World");
+ QCOMPARE(v2, QCborValue("World"));
+
+ QCOMPARE(a.takeAt(1).toString(), "World");
+ QCOMPARE(a.takeAt(0).toString(), "Hello");
+ QVERIFY(a.isEmpty());
+}
+
+void tst_QCborValue::mapStringValues()
+{
+ QCborMap m{{0, "Hello"}};
+ m.insert({1, QByteArray("Hello")});
+ m.insert({2, QLatin1String("World")});
+ QVERIFY(m == m);
+
+ QCborValueRef r1 = m[0];
+ QCOMPARE(r1.toString(), "Hello");
+ QCOMPARE(r1.operator QCborValue(), QCborValue("Hello"));
+ QVERIFY(r1 == QCborValue("Hello"));
+
+ QCborValue v2 = m.value(1);
+ QCOMPARE(v2.toByteArray(), QByteArray("Hello"));
+ QCOMPARE(v2, QCborValue(QByteArray("Hello")));
+
+ // v2 must continue to be valid after the entry getting removed
+ m.erase(m.constFind(1));
+ QCOMPARE(v2.toByteArray(), QByteArray("Hello"));
+ QCOMPARE(v2, QCborValue(QByteArray("Hello")));
+
+ v2 = (m.begin() + 1).value();
+ QCOMPARE(v2.toString(), "World");
+ QCOMPARE(v2, QCborValue("World"));
+
+ QCOMPARE(m.extract(m.begin() + 1).toString(), "World");
+ QCOMPARE(m.take(0).toString(), "Hello");
+ QVERIFY(m.isEmpty());
+}
+
+void tst_QCborValue::mapStringKeys()
+{
+ QCborMap m{{QLatin1String("Hello"), 1}, {QStringLiteral("World"), 2}};
+ QCOMPARE(m.value(QStringLiteral("Hello")), QCborValue(1));
+ QCOMPARE(m.value(QLatin1String("World")), QCborValue(2));
+
+ QCborMap m2 = m;
+ QVERIFY(m2 == m);
+ QVERIFY(m == m2);
+
+ m.insert({QByteArray("foo"), "bar"});
+ QCOMPARE(m.size(), 3);
+ QCOMPARE(m2.size(), 2);
+ QVERIFY(m2 != m);
+ QVERIFY(m != m2);
+
+ QVERIFY(m2.value(QCborValue(QByteArray("foo"))).isUndefined());
+ QVERIFY(m.value(QCborValue(QLatin1String("foo"))).isUndefined());
+ QCOMPARE(m.value(QCborValue(QByteArray("foo"))).toString(), "bar");
+}
+
+void tst_QCborValue::mapInsertRemove()
+{
+ QFETCH(QCborValue, v);
+ QCborMap m{{1, v}};
+
+ m.remove(1);
+ QVERIFY(m.isEmpty());
+ QVERIFY(!m.contains(1));
+
+ m.insert(2, v);
+ QVERIFY(m.contains(2));
+ QVERIFY(m[2] == v);
+ QVERIFY(v == m[2]);
+
+ auto it = m.find(2);
+ it = m.erase(it);
+ QVERIFY(m.isEmpty());
+
+ // creates m[2] and m[42] just by referencing them
+ m[2];
+ QCborValueRef r = m[42];
+ QCOMPARE(m.size(), 2);
+
+ r = v;
+ it = m.find(42);
+ QVERIFY(it.value() == v);
+ QVERIFY(v == it.value());
+ QVERIFY(it.value() == r);
+ QVERIFY(r == it.value());
+
+ QCOMPARE(m.extract(it), v);
+ QVERIFY(!m.contains(42));
+
+ m[2] = v;
+ QCOMPARE(m.take(2), v);
+ QVERIFY(m.take(2).isUndefined());
+ QVERIFY(m.isEmpty());
+}
+
+void tst_QCborValue::arrayInsertTagged()
+{
+ QFETCH(QCborValue, v);
+
+ // make it tagged
+ QCborValue tagged(QCborKnownTags::Signature, v);
+
+ QCborArray a{tagged};
+ a.insert(1, tagged);
+ QCOMPARE(a.size(), 2);
+ QCOMPARE(a.at(0), tagged);
+ QCOMPARE(a.at(1), tagged);
+ QCOMPARE(a.at(0).taggedValue(), v);
+ QCOMPARE(a.at(1).taggedValue(), v);
+ QCOMPARE(a.takeAt(0).taggedValue(), v);
+ QCOMPARE(a.takeAt(0).taggedValue(), v);
+ QVERIFY(a.isEmpty());
+}
+
+void tst_QCborValue::mapInsertTagged()
+{
+ QFETCH(QCborValue, v);
+
+ // make it tagged
+ QCborValue tagged(QCborKnownTags::Signature, v);
+
+ QCborMap m{{11, tagged}};
+ m.insert({-21, tagged});
+ QCOMPARE(m.size(), 2);
+ QCOMPARE(m.constBegin().value(), tagged);
+ QCOMPARE(m.value(-21), tagged);
+ QCOMPARE(m.value(11).taggedValue(), v);
+ QCOMPARE((m.end() - 1).value().taggedValue(), v);
+ QCOMPARE(m.extract(m.end() - 1).taggedValue(), v);
+ QVERIFY(!m.contains(-21));
+ QCOMPARE(m.take(11).taggedValue(), v);
+ QVERIFY(m.isEmpty());
+}
+
+void tst_QCborValue::arraySelfAssign()
+{
+ QFETCH(QCborValue, v);
+ QCborArray a;
+
+ a = {v};
+
+ // Test 1: QCborValue created first, so
+ // QCborArray::insert() detaches
+ {
+ a.append(a);
+ QCOMPARE(a.size(), 2);
+ QCOMPARE(a.last().toArray().size(), 1);
+ }
+
+ a = {v};
+
+ // Test 2: QCborValueRef created first
+ {
+ a.append(36);
+ auto it = a.end() - 1;
+ *it = a;
+
+ QCOMPARE(a.size(), 2);
+ QCOMPARE(it->toArray().size(), 2);
+ QCOMPARE(it->toArray().last(), QCborValue(36));
+ }
+}
+
+void tst_QCborValue::mapSelfAssign()
+{
+ QFETCH(QCborValue, v);
+ QCborMap m;
+
+ m = {{0, v}};
+ QCOMPARE(m.size(), 1);
+
+ // Test 1: create a QCborValue first
+ // in this case, QCborMap::operator[] detaches first
+ {
+ QCborValue vm = m;
+ m[1] = vm; // self-assign
+ QCOMPARE(m.size(), 2);
+ QCOMPARE(m.value(0), v);
+
+ QCborMap m2 = m.value(1).toMap();
+ // there mustn't be an element with key 1
+ QCOMPARE(m2.size(), 1);
+ QCOMPARE(m2.value(0), v);
+ QVERIFY(!m2.contains(1));
+ }
+
+ m = {{0, v}};
+
+ // Test 2: create the QCborValueRef first
+ // in this case, there's no opportunity to detach
+ {
+ QCborValueRef rv = m[1];
+ rv = m; // self-assign (implicit QCborValue creation)
+ QCOMPARE(m.size(), 2);
+ QCOMPARE(m.value(0), v);
+
+ QCborMap m2 = m.value(1).toMap();
+ // there must be an element with key 1
+ QCOMPARE(m2.size(), 2);
+ QCOMPARE(m2.value(0), v);
+ QVERIFY(m2.contains(1));
+ QCOMPARE(m2.value(1), QCborValue());
+ }
+
+ m = {{0, v}};
+
+ // Test 3: don't force creation of either before
+ // in this case, it's up to the compiler to choose
+ {
+ m[1] = m; // self-assign
+ QCOMPARE(m.size(), 2);
+
+ QCborMap m2 = m.value(1).toMap();
+ QVERIFY(m2.size() == 1 || m2.size() == 2);
+ }
+
+ m = {{0, v}};
+
+ // Test 4: self-assign as key
+ // in this scase, QCborMap::operator[] must detach
+ {
+ m[m] = v;
+ QCOMPARE(m.size(), 2);
+
+ auto it = m.constEnd() - 1;
+ QCOMPARE(it.value(), v);
+ QCOMPARE(it.key(), QCborMap({{0, v}}));
+ }
+}
+
+void tst_QCborValue::mapComplexKeys()
+{
+ QFETCH(QCborValue, v);
+ QCborValue tagged(QCborKnownTags::Signature, v);
+
+ QCborMap m{{42, true}, {v, 42}, {-3, nullptr}};
+ QCOMPARE(m.size(), 3);
+ QVERIFY(m.contains(42));
+ QVERIFY(m.contains(-3));
+ QVERIFY(m.contains(v));
+ QVERIFY(!m.contains(tagged));
+
+ auto it = m.constFind(v);
+ QVERIFY(it != m.constEnd());
+ QVERIFY(it.key() == v);
+ QVERIFY(v == it.key());
+ QCOMPARE(it.value().toInteger(), 42);
+
+ QCborArray a{0, 1, 2, 3, v};
+ m[a] = 1;
+ QCOMPARE(m.size(), 4);
+ QCOMPARE((m.constEnd() - 1).value(), QCborValue(1));
+ if (v != QCborValue(QCborValue::Array))
+ QVERIFY(!m.contains(QCborArray{}));
+ QVERIFY(!m.contains(QCborArray{0}));
+ QVERIFY(!m.contains(QCborArray{0, 1}));
+ QVERIFY(!m.contains(QCborArray{0, 1, 2}));
+ QVERIFY(!m.contains(QCborArray{0, 1, 2, 4}));
+ QVERIFY(!m.contains(QCborArray{0, 1, 2, 3, v, 4}));
+
+ it = m.constFind(QCborArray{0, 1, 2, 3, v});
+ QVERIFY(it != m.constEnd());
+ QCOMPARE(it.key(), a);
+ QCOMPARE(it.value(), QCborValue(1));
+
+ m[m] = 1; // assign itself as a key -- this necessarily detaches before
+ QCOMPARE(m.size(), 5);
+ QCOMPARE((m.end() - 1).value(), 1);
+ QCOMPARE((m.end() - 1).key().toMap().size(), 4);
+
+ QCborValue mv(m);
+ if (v.isInteger()) {
+ // we should be able to find using the overloads too
+ QCOMPARE(m[v.toInteger()].toInteger(), 42);
+ QCOMPARE(mv[v.toInteger()].toInteger(), 42);
+ } else if (v.isString()) {
+ // ditto
+ QCOMPARE(m[v.toString()].toInteger(), 42);
+ QCOMPARE(mv[v.toString()].toInteger(), 42);
+
+ // basics_data() strings are Latin1
+ QByteArray latin1 = v.toString().toLatin1();
+ Q_ASSERT(v.toString() == QString::fromLatin1(latin1));
+ QCOMPARE(m[QLatin1String(latin1)].toInteger(), 42);
+ }
+
+ m.remove(v);
+ QVERIFY(!m.contains(v));
+ QVERIFY(!m.contains(tagged));
+
+ QCborValueRef r = m[tagged];
+ QVERIFY(!m.contains(v));
+ QVERIFY(m.contains(tagged));
+ r = 47;
+ QCOMPARE(m[tagged].toInteger(), 47);
+ QCOMPARE(m.take(tagged).toInteger(), 47);
+ QVERIFY(!m.contains(tagged));
+}
+
+void tst_QCborValue::sorting()
+{
+ QCborValue vundef, vnull(nullptr);
+ QCborValue vtrue(true), vfalse(false);
+ QCborValue vint1(1), vint2(2);
+ QCborValue vneg1(-1), vneg2(-2);
+ QCborValue vba2(QByteArray("Hello")), vba3(QByteArray("World")), vba1(QByteArray("foo"));
+ QCborValue vs2("Hello"), vs3("World"), vs1("foo");
+ QCborValue va1(QCborValue::Array), va2(QCborArray{1}), va3(QCborArray{0, 0});
+ QCborValue vm1(QCborValue::Map), vm2(QCborMap{{1, 0}}), vm3(QCborMap{{0, 0}, {1, 0}});
+ QCborValue vdt1(QDateTime::fromMSecsSinceEpoch(0, Qt::UTC)), vdt2(QDateTime::currentDateTimeUtc());
+ QCborValue vtagged1(QCborKnownTags::UnixTime_t, 0), vtagged2(QCborKnownTags::UnixTime_t, 0.0),
+ vtagged3(QCborKnownTags::Signature, 0), vtagged4(QCborTag(-2), 0), vtagged5(QCborTag(-1), 0);
+ QCborValue vurl1(QUrl("https://example.net")), vurl2(QUrl("https://example.com/"));
+ QCborValue vuuid1{QUuid()}, vuuid2(QUuid::createUuid());
+ QCborValue vsimple1(QCborSimpleType(1)), vsimple32(QCborSimpleType(32)), vsimple255(QCborSimpleType(255));
+ QCborValue vdouble1(1.5), vdouble2(qInf());
+ QCborValue vndouble1(-1.5), vndouble2(-qInf());
+
+#define CHECK_ORDER(v1, v2) \
+ QVERIFY(v1 < v2); \
+ QVERIFY(!(v2 < v2))
+
+ // intra-type comparisons
+ CHECK_ORDER(vfalse, vtrue);
+ CHECK_ORDER(vsimple1, vsimple32);
+ CHECK_ORDER(vsimple32, vsimple255);
+ CHECK_ORDER(vint1, vint2);
+ CHECK_ORDER(vdouble1, vdouble2);
+ CHECK_ORDER(vndouble1, vndouble2);
+ // note: shorter length sorts first
+ CHECK_ORDER(vba1, vba2);
+ CHECK_ORDER(vba2, vba3);
+ CHECK_ORDER(vs1, vs2);
+ CHECK_ORDER(vs2, vs3);
+ CHECK_ORDER(va1, va2);
+ CHECK_ORDER(va2, va3);
+ CHECK_ORDER(vm1, vm2);
+ CHECK_ORDER(vm2, vm3);
+ CHECK_ORDER(vdt1, vdt2);
+ CHECK_ORDER(vtagged1, vtagged2);
+ CHECK_ORDER(vtagged2, vtagged3);
+ CHECK_ORDER(vtagged3, vtagged4);
+ CHECK_ORDER(vtagged4, vtagged5);
+ CHECK_ORDER(vurl1, vurl2);
+ CHECK_ORDER(vuuid1, vuuid2);
+
+ // surprise 1: CBOR sorts integrals by absolute value
+ CHECK_ORDER(vneg1, vneg2);
+
+ // surprise 2: CBOR sorts negatives after positives (sign+magnitude)
+ CHECK_ORDER(vint2, vneg1);
+ QVERIFY(vint2.toInteger() > vneg1.toInteger());
+ CHECK_ORDER(vdouble2, vndouble1);
+ QVERIFY(vdouble2.toDouble() > vndouble1.toDouble());
+
+ // inter-type comparisons
+ CHECK_ORDER(vneg2, vba1);
+ CHECK_ORDER(vba3, vs1);
+ CHECK_ORDER(vs3, va1);
+ CHECK_ORDER(va2, vm1);
+ CHECK_ORDER(vm2, vdt1);
+ CHECK_ORDER(vdt2, vtagged1);
+ CHECK_ORDER(vtagged2, vurl1);
+ CHECK_ORDER(vurl1, vuuid1);
+ CHECK_ORDER(vuuid2, vtagged3);
+ CHECK_ORDER(vtagged4, vsimple1);
+ CHECK_ORDER(vsimple1, vfalse);
+ CHECK_ORDER(vtrue, vnull);
+ CHECK_ORDER(vnull, vundef);
+ CHECK_ORDER(vundef, vsimple32);
+ CHECK_ORDER(vsimple255, vdouble1);
+
+ // which shows all doubles sorted after integrals
+ CHECK_ORDER(vint2, vdouble1);
+ QVERIFY(vint2.toInteger() > vdouble1.toDouble());
+#undef CHECK_ORDER
+}
+
+static void addCommonCborData()
+{
+ // valid for both decoding and encoding
+ QTest::addColumn<QCborValue>("v");
+ QTest::addColumn<QByteArray>("result");
+ QTest::addColumn<QCborValue::EncodingOptions>("options");
+ QDateTime dt = QDateTime::currentDateTimeUtc();
+ QUuid uuid = QUuid::createUuid();
+ QCborValue::EncodingOptions noxfrm = QCborValue::NoTransformation;
+
+ // integrals
+ QTest::newRow("Integer:0") << QCborValue(0) << raw("\x00") << noxfrm;
+ QTest::newRow("Integer:1") << QCborValue(1) << raw("\x01") << noxfrm;
+ QTest::newRow("Integer:-1") << QCborValue(-1) << raw("\x20") << noxfrm;
+ QTest::newRow("Integer:INT64_MAX") << QCborValue(std::numeric_limits<qint64>::max())
+ << raw("\x1b\x7f\xff\xff\xff""\xff\xff\xff\xff")
+ << noxfrm;
+ QTest::newRow("Integer:INT64_MIN") << QCborValue(std::numeric_limits<qint64>::min())
+ << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xff")
+ << noxfrm;
+
+ QTest::newRow("simple0") << QCborValue(QCborValue::SimpleType) << raw("\xe0") << noxfrm;
+ QTest::newRow("simple1") << QCborValue(QCborSimpleType(1)) << raw("\xe1") << noxfrm;
+ QTest::newRow("simple255") << QCborValue(QCborSimpleType(255)) << raw("\xf8\xff") << noxfrm;
+ QTest::newRow("Undefined") << QCborValue() << raw("\xf7") << noxfrm;
+ QTest::newRow("Null") << QCborValue(nullptr) << raw("\xf6") << noxfrm;
+ QTest::newRow("True") << QCborValue(true) << raw("\xf5") << noxfrm;
+ QTest::newRow("False") << QCborValue(false) << raw("\xf4") << noxfrm;
+ QTest::newRow("simple32") << QCborValue(QCborSimpleType(32)) << raw("\xf8\x20") << noxfrm;
+ QTest::newRow("simple255") << QCborValue(QCborSimpleType(255)) << raw("\xf8\xff") << noxfrm;
+
+ QTest::newRow("Double:0") << QCborValue(0.) << raw("\xfb\0\0\0\0""\0\0\0\0") << noxfrm;
+ QTest::newRow("Double:1.5") << QCborValue(1.5) << raw("\xfb\x3f\xf8\0\0""\0\0\0\0") << noxfrm;
+ QTest::newRow("Double:-1.5") << QCborValue(-1.5) << raw("\xfb\xbf\xf8\0\0""\0\0\0\0") << noxfrm;
+ QTest::newRow("Double:INT64_MAX+1") << QCborValue(std::numeric_limits<qint64>::max() + 1.)
+ << raw("\xfb\x43\xe0\0\0""\0\0\0\0") << noxfrm;
+ QTest::newRow("Double:maxintegralfp") << QCborValue(18446744073709551616.0 - 2048)
+ << raw("\xfb\x43\xef\xff\xff""\xff\xff\xff\xff")
+ << noxfrm;
+ QTest::newRow("Double:minintegralfp") << QCborValue(-18446744073709551616.0 + 2048)
+ << raw("\xfb\xc3\xef\xff\xff""\xff\xff\xff\xff")
+ << noxfrm;
+ QTest::newRow("Double:inf") << QCborValue(qInf()) << raw("\xfb\x7f\xf0\0\0""\0\0\0\0") << noxfrm;
+ QTest::newRow("Double:-inf") << QCborValue(-qInf()) << raw("\xfb\xff\xf0\0""\0\0\0\0\0") << noxfrm;
+ QTest::newRow("Double:nan") << QCborValue(qQNaN()) << raw("\xfb\x7f\xf8\0\0""\0\0\0\0") << noxfrm;
+
+ QTest::newRow("Float:0") << QCborValue(0.) << raw("\xfa\0\0\0\0") << QCborValue::EncodingOptions(QCborValue::UseFloat);
+ QTest::newRow("Float:1.5") << QCborValue(1.5) << raw("\xfa\x3f\xc0\0\0") << QCborValue::EncodingOptions(QCborValue::UseFloat);
+ QTest::newRow("Float:-1.5") << QCborValue(-1.5) << raw("\xfa\xbf\xc0\0\0") << QCborValue::EncodingOptions(QCborValue::UseFloat);
+ QTest::newRow("Float:inf") << QCborValue(qInf()) << raw("\xfa\x7f\x80\0\0") << QCborValue::EncodingOptions(QCborValue::UseFloat);
+ QTest::newRow("Float:-inf") << QCborValue(-qInf()) << raw("\xfa\xff\x80\0\0") << QCborValue::EncodingOptions(QCborValue::UseFloat);
+ QTest::newRow("Float:nan") << QCborValue(qQNaN()) << raw("\xfa\x7f\xc0\0\0") << QCborValue::EncodingOptions(QCborValue::UseFloat);
+
+ QTest::newRow("Float16:0") << QCborValue(0.) << raw("\xf9\0\0") << QCborValue::EncodingOptions(QCborValue::UseFloat16);
+ QTest::newRow("Float16:1.5") << QCborValue(1.5) << raw("\xf9\x3e\0") << QCborValue::EncodingOptions(QCborValue::UseFloat16);
+ QTest::newRow("Float16:-1.5") << QCborValue(-1.5) << raw("\xf9\xbe\0") << QCborValue::EncodingOptions(QCborValue::UseFloat16);
+ QTest::newRow("Float16:inf") << QCborValue(qInf()) << raw("\xf9\x7c\0") << QCborValue::EncodingOptions(QCborValue::UseFloat16);
+ QTest::newRow("Float16:-inf") << QCborValue(-qInf()) << raw("\xf9\xfc\0") << QCborValue::EncodingOptions(QCborValue::UseFloat16);
+ QTest::newRow("Float16:nan") << QCborValue(qQNaN()) << raw("\xf9\x7e\0") << QCborValue::EncodingOptions(QCborValue::UseFloat16);
+
+ // out of range of qint64, but in range for CBOR, so these do get converted
+ // to integrals on write and back to double on read
+ QTest::newRow("UseInteger:INT64_MAX+1") << QCborValue(std::numeric_limits<qint64>::max() + 1.)
+ << raw("\x1b\x80\0\0\0""\0\0\0\0")
+ << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+ QTest::newRow("UseInteger:maxintegralfp") << QCborValue(18446744073709551616.0 - 2048)
+ << raw("\x1b\xff\xff\xff\xff""\xff\xff\xf8\0")
+ << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+ QTest::newRow("UseInteger:minintegralfp") << QCborValue(-18446744073709551616.0 + 2048)
+ << raw("\x3b\xff\xff\xff\xff""\xff\xff\xf7\xff")
+ << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+
+ QTest::newRow("ByteArray:Empty") << QCborValue(QByteArray()) << raw("\x40") << noxfrm;
+ QTest::newRow("ByteArray") << QCborValue(QByteArray("Hello")) << raw("\x45Hello") << noxfrm;
+ QTest::newRow("ByteArray:WithNull") << QCborValue(raw("\0\1\2\xff")) << raw("\x44\0\1\2\xff") << noxfrm;
+
+ QTest::newRow("String:Empty") << QCborValue(QString()) << raw("\x60") << noxfrm;
+ QTest::newRow("String:UsAscii") << QCborValue("Hello") << raw("\x65Hello") << noxfrm;
+ QTest::newRow("String:Latin1") << QCborValue(QLatin1String("R\xe9sum\xe9"))
+ << raw("\x68R\xc3\xa9sum\xc3\xa9") << noxfrm;
+ QTest::newRow("String:Unicode") << QCborValue(QStringLiteral(u"éś α €"))
+ << raw("\x6b\xc3\xa9\xc5\x9b \xce\xb1 \xe2\x82\xac") << noxfrm;
+
+ QTest::newRow("DateTime") << QCborValue(dt) // this is UTC
+ << "\xc0\x78\x18" + dt.toString(Qt::ISODateWithMs).toLatin1()
+ << noxfrm;
+ QTest::newRow("DateTime-UTC") << QCborValue(QDateTime({2018, 1, 1}, {9, 0, 0}, Qt::UTC))
+ << raw("\xc0\x78\x18" "2018-01-01T09:00:00.000Z")
+ << noxfrm;
+ QTest::newRow("DateTime-Local") << QCborValue(QDateTime({2018, 1, 1}, {9, 0, 0}, Qt::LocalTime))
+ << raw("\xc0\x77" "2018-01-01T09:00:00.000")
+ << noxfrm;
+ QTest::newRow("DateTime+01:00") << QCborValue(QDateTime({2018, 1, 1}, {9, 0, 0}, Qt::OffsetFromUTC, 3600))
+ << raw("\xc0\x78\x1d" "2018-01-01T09:00:00.000+01:00")
+ << noxfrm;
+ QTest::newRow("Url:Empty") << QCborValue(QUrl()) << raw("\xd8\x20\x60") << noxfrm;
+ QTest::newRow("Url") << QCborValue(QUrl("HTTPS://example.com/{%30%31}?q=%3Ca+b%20%C2%A9%3E&%26"))
+ << raw("\xd8\x20\x78\x27" "https://example.com/{01}?q=<a+b \xC2\xA9>&%26")
+ << noxfrm;
+ QTest::newRow("Regex:Empty") << QCborValue(QRegularExpression()) << raw("\xd8\x23\x60") << noxfrm;
+ QTest::newRow("Regex") << QCborValue(QRegularExpression("^.*$"))
+ << raw("\xd8\x23\x64" "^.*$") << noxfrm;
+ QTest::newRow("Uuid") << QCborValue(uuid) << raw("\xd8\x25\x50") + uuid.toRfc4122() << noxfrm;
+
+ // empty arrays and maps
+ QTest::newRow("Array") << QCborValue(QCborArray()) << raw("\x80") << noxfrm;
+ QTest::newRow("Map") << QCborValue(QCborMap()) << raw("\xa0") << noxfrm;
+
+ QTest::newRow("Tagged:ByteArray") << QCborValue(QCborKnownTags::PositiveBignum, raw("\1\0\0\0\0""\0\0\0\0"))
+ << raw("\xc2\x49\1\0\0\0\0""\0\0\0\0") << noxfrm;
+ QTest::newRow("Tagged:Array") << QCborValue(QCborKnownTags::Decimal, QCborArray{-2, 27315})
+ << raw("\xc4\x82\x21\x19\x6a\xb3") << noxfrm;
+}
+
+void tst_QCborValue::toCbor_data()
+{
+ addCommonCborData();
+
+ // The rest of these tests are conversions whose decoding does not yield
+ // back the same QCborValue.
+
+ // Signalling NaN get normalized to quiet ones
+ QTest::newRow("Double:snan") << QCborValue(qSNaN()) << raw("\xfb\x7f\xf8\0""\0\0\0\0\0") << QCborValue::EncodingOptions();
+ QTest::newRow("Float:snan") << QCborValue(qSNaN()) << raw("\xfa\x7f\xc0\0\0") << QCborValue::EncodingOptions(QCborValue::UseFloat);
+ QTest::newRow("Float16:snan") << QCborValue(qSNaN()) << raw("\xf9\x7e\0") << QCborValue::EncodingOptions(QCborValue::UseFloat16);
+
+ // Floating point written as integers are read back as integers
+ QTest::newRow("UseInteger:0") << QCborValue(0.) << raw("\x00") << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+ QTest::newRow("UseInteger:1") << QCborValue(1.) << raw("\x01") << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+ QTest::newRow("UseInteger:-1") << QCborValue(-1.) << raw("\x20") << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+ QTest::newRow("UseInteger:INT64_MIN") << QCborValue(std::numeric_limits<qint64>::min() + 0.)
+ << raw("\x3b\x7f\xff\xff\xff""\xff\xff\xff\xff")
+ << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+
+ // but obviously non-integral or out of range floating point stay FP
+ QTest::newRow("UseInteger:1.5") << QCborValue(1.5) << raw("\xfb\x3f\xf8\0\0""\0\0\0\0") << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+ QTest::newRow("UseInteger:-1.5") << QCborValue(-1.5) << raw("\xfb\xbf\xf8\0\0""\0\0\0\0") << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+ QTest::newRow("UseInteger:inf") << QCborValue(qInf()) << raw("\xfb\x7f\xf0\0\0""\0\0\0\0") << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+ QTest::newRow("UseInteger:-inf") << QCborValue(-qInf()) << raw("\xfb\xff\xf0\0""\0\0\0\0\0") << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+ QTest::newRow("UseInteger:nan") << QCborValue(qQNaN()) << raw("\xfb\x7f\xf8\0\0""\0\0\0\0") << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+ QTest::newRow("UseInteger:2^64") << QCborValue(18446744073709551616.0) << raw("\xfb\x43\xf0\0\0""\0\0\0\0") << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+ QTest::newRow("UseInteger:-2^65") << QCborValue(-2 * 18446744073709551616.0) << raw("\xfb\xc4\0\0\0""\0\0\0\0") << QCborValue::EncodingOptions(QCborValue::UseIntegers);
+}
+
+void tst_QCborValue::toCbor()
+{
+ QFETCH(QCborValue, v);
+ QFETCH(QByteArray, result);
+ QFETCH(QCborValue::EncodingOptions, options);
+
+ QCOMPARE(v.toCbor(options), result);
+
+ // in maps and arrays
+ QCOMPARE(QCborArray{v}.toCborValue().toCbor(options), "\x81" + result);
+ QCOMPARE(QCborArray({v, v}).toCborValue().toCbor(options),
+ "\x82" + result + result);
+ QCOMPARE(QCborMap({{1, v}}).toCborValue().toCbor(options),
+ "\xa1\x01" + result);
+
+ // tagged
+ QCborValue t(QCborKnownTags::Signature, v);
+ QCOMPARE(t.toCbor(options), "\xd9\xd9\xf7" + result);
+ QCOMPARE(QCborArray({t, t}).toCborValue().toCbor(options),
+ "\x82\xd9\xd9\xf7" + result + "\xd9\xd9\xf7" + result);
+ QCOMPARE(QCborMap({{1, t}}).toCborValue().toCbor(options),
+ "\xa1\x01\xd9\xd9\xf7" + result);
+}
+
+void tst_QCborValue::fromCbor_data()
+{
+ addCommonCborData();
+
+ // chunked strings
+ QTest::newRow("ByteArray:Chunked") << QCborValue(QByteArray("Hello"))
+ << raw("\x5f\x43Hel\x42lo\xff");
+ QTest::newRow("ByteArray:Chunked:Empty") << QCborValue(QByteArray()) << raw("\x5f\xff");
+ QTest::newRow("String:Chunked") << QCborValue("Hello")
+ << raw("\x7f\x63Hel\x62lo\xff");
+ QTest::newRow("String:Chunked:Empty") << QCborValue(QString())
+ << raw("\x7f\xff");
+
+ QTest::newRow("DateTime:NoMilli") << QCborValue(QDateTime::fromSecsSinceEpoch(1515565477, Qt::UTC))
+ << raw("\xc0\x74" "2018-01-10T06:24:37Z");
+ QTest::newRow("UnixTime_t:Integer") << QCborValue(QDateTime::fromSecsSinceEpoch(1515565477, Qt::UTC))
+ << raw("\xc1\x1a\x5a\x55\xb1\xa5");
+ QTest::newRow("UnixTime_t:Double") << QCborValue(QDateTime::fromMSecsSinceEpoch(1515565477125, Qt::UTC))
+ << raw("\xc1\xfb\x41\xd6\x95\x6c""\x69\x48\x00\x00");
+
+ QTest::newRow("Url:NotNormalized") << QCborValue(QUrl("https://example.com/\xc2\xa9 "))
+ << raw("\xd8\x20\x78\x1dHTTPS://EXAMPLE.COM/%c2%a9%20");
+
+ QTest::newRow("Uuid:Zero") << QCborValue(QUuid()) << raw("\xd8\x25\x40");
+ QTest::newRow("Uuid:TooShort") << QCborValue(QUuid::fromRfc4122(raw("\1\2\3\4""\4\3\2\0""\0\0\0\0""\0\0\0\0")))
+ << raw("\xd8\x25\x47" "\1\2\3\4\4\3\2");
+ QTest::newRow("Uuid:TooLong") << QCborValue(QUuid::fromRfc4122(raw("\1\2\3\4""\4\3\2\0""\0\0\0\0""\0\0\0\1")))
+ << raw("\xd8\x25\x51" "\1\2\3\4""\4\3\2\0""\0\0\0\0""\0\0\0\1""\2");
+}
+
+void tst_QCborValue::fromCbor()
+{
+ QFETCH(QCborValue, v);
+ QFETCH(QByteArray, result);
+
+ auto doCheck = [](const QCborValue &v, const QByteArray &result) {
+ QCborParserError error;
+ QCborValue decoded = QCborValue::fromCbor(result, &error);
+ QVERIFY2(error.error == QCborError(), qPrintable(error.errorString()));
+ QCOMPARE(error.offset, result.size());
+ QVERIFY(decoded == v);
+ QVERIFY(v == decoded);
+ };
+
+ doCheck(v, result);
+ if (QTest::currentTestFailed())
+ return;
+
+ // in an array
+ doCheck(QCborArray{v}, "\x81" + result);
+ if (QTest::currentTestFailed())
+ return;
+
+ doCheck(QCborArray{v, v}, "\x82" + result + result);
+ if (QTest::currentTestFailed())
+ return;
+
+ // in a map
+ doCheck(QCborMap{{1, v}}, "\xa1\1" + result);
+ if (QTest::currentTestFailed())
+ return;
+
+ // undefined-length arrays and maps
+ doCheck(QCborArray{v}, "\x9f" + result + "\xff");
+ if (QTest::currentTestFailed())
+ return;
+ doCheck(QCborArray{v, v}, "\x9f" + result + result + "\xff");
+ if (QTest::currentTestFailed())
+ return;
+ doCheck(QCborMap{{1, v}}, "\xbf\1" + result + "\xff");
+ if (QTest::currentTestFailed())
+ return;
+
+ // tagged
+ QCborValue t(QCborKnownTags::Signature, v);
+ doCheck(t, "\xd9\xd9\xf7" + result);
+ if (QTest::currentTestFailed())
+ return;
+
+ // in an array
+ doCheck(QCborArray{t}, "\x81\xd9\xd9\xf7" + result);
+ if (QTest::currentTestFailed())
+ return;
+
+ doCheck(QCborArray{t, t}, "\x82\xd9\xd9\xf7" + result + "\xd9\xd9\xf7" + result);
+ if (QTest::currentTestFailed())
+ return;
+
+ // in a map
+ doCheck(QCborMap{{1, t}}, "\xa1\1\xd9\xd9\xf7" + result);
+ if (QTest::currentTestFailed())
+ return;
+}
+
+void tst_QCborValue::validation_data()
+{
+ addValidationColumns();
+ addValidationData();
+
+ // These tests say we have arrays and maps with very large item counts.
+ // They are meant to ensure we don't pre-allocate a lot of memory
+ // unnecessarily and possibly crash the application. The actual number of
+ // elements in the stream is only 2, so we should get an unexpected EOF
+ // error. QCborValue internally uses 16 bytes per element, so we get to
+ // 2 GB at 2^27 elements.
+ QTest::addRow("very-large-array-no-overflow") << raw("\x9a\x07\xff\xff\xff" "\0\0");
+ QTest::addRow("very-large-array-overflow1") << raw("\x9a\x40\0\0\0" "\0\0");
+
+ // this makes sure we don't accidentally clip to 32-bit: sending 2^32+2 elements
+ QTest::addRow("very-large-array-overflow2") << raw("\x9b\0\0\0\1""\0\0\0\2" "\0\0");
+}
+
+void tst_QCborValue::validation()
+{
+ QFETCH(QByteArray, data);
+
+ QCborParserError error;
+ QCborValue decoded = QCborValue::fromCbor(data, &error);
+ QVERIFY(error.error != QCborError{});
+
+ if (data.startsWith('\x81')) {
+ // decode without the array prefix
+ decoded = QCborValue::fromCbor(data.mid(1), &error);
+ QVERIFY(error.error != QCborError{});
+ }
+}
+
+void tst_QCborValue::toDiagnosticNotation_data()
+{
+ QTest::addColumn<QCborValue>("v");
+ QTest::addColumn<int>("opts");
+ QTest::addColumn<QString>("expected");
+ QDateTime dt = QDateTime::currentDateTimeUtc();
+ QUuid uuid = QUuid::createUuid();
+
+ QMetaEnum me = QMetaEnum::fromType<QCborValue::Type>();
+ auto add = [me](const QCborValue &v, const QString &exp) {
+ auto addRow = [=](const char *prefix) -> QTestData & {
+ QCborValue::Type t = v.type();
+ if (t == QCborValue::Integer)
+ return QTest::addRow("%sInteger:%lld", prefix, v.toInteger());
+ if (t == QCborValue::Double)
+ return QTest::addRow("%sDouble:%g", prefix, v.toDouble());
+ if (t == QCborValue::ByteArray)
+ return QTest::addRow("%sByteArray:%d", prefix, v.toByteArray().size());
+ if (t == QCborValue::String)
+ return QTest::addRow("%sString:%d", prefix, v.toString().size());
+
+ QByteArray typeString = me.valueToKey(t);
+ Q_ASSERT(!typeString.isEmpty());
+ return QTest::newRow(prefix + typeString);
+ };
+ addRow("") << v << int(QCborValue::DiagnosticNotationOptions{}) << exp;
+ addRow("LW:") << v << int(QCborValue::LineWrapped) << exp;
+ addRow("Array:") << QCborValue(QCborArray{v}) << int(QCborValue::DiagnosticNotationOptions{}) << '[' + exp + ']';
+ addRow("Mapped:") << QCborValue(QCborMap{{2, v}}) << int(QCborValue::DiagnosticNotationOptions{}) << "{2: " + exp + '}';
+ addRow("Mapping:") << QCborValue(QCborMap{{v, 2}}) << int(QCborValue::DiagnosticNotationOptions{}) << '{' + exp + ": 2}";
+ };
+
+ // empty arrays and maps
+ QTest::newRow("EmptyArray")
+ << QCborValue(QCborArray()) << int(QCborValue::DiagnosticNotationOptions{})
+ << "[]";
+ QTest::newRow("EmptyMap")
+ << QCborValue(QCborMap()) << int(QCborValue::DiagnosticNotationOptions{})
+ << "{}";
+
+ add(QCborValue(), "undefined");
+ add(QCborValue::Null, "null");
+ add(false, "false");
+ add(true, "true");
+ add(QCborSimpleType(0), "simple(0)");
+ QTest::newRow("SimpleType-255")
+ << QCborValue(QCborSimpleType(255)) << int(QCborValue::DiagnosticNotationOptions{})
+ << "simple(255)";
+ add(0, "0");
+ add(1, "1");
+ add(-1, "-1");
+ add(std::numeric_limits<qint64>::min(), QString::number(std::numeric_limits<qint64>::min()));
+ add(std::numeric_limits<qint64>::max(), QString::number(std::numeric_limits<qint64>::max()));
+ add(0., "0.0");
+ add(1.25, "1.25");
+ add(-1.25, "-1.25");
+ add(qInf(), "inf");
+ add(-qInf(), "-inf");
+ add(qQNaN(), "nan");
+ add(QByteArray(), "h''");
+ add(QByteArray("Hello"), "h'48656c6c6f'");
+ add(QLatin1String(), QLatin1String("\"\""));
+ add("Hello", "\"Hello\"");
+ add("\"Hello\\World\"", "\"\\\"Hello\\\\World\\\"\"");
+ add(QCborValue(dt), "0(\"" + dt.toString(Qt::ISODateWithMs) + "\")");
+ add(QCborValue(QUrl("http://example.com")), "32(\"http://example.com\")");
+ add(QCborValue(QRegularExpression("^.*$")), "35(\"^.*$\")");
+ add(QCborValue(uuid), "37(h'" + uuid.toString(QUuid::Id128) + "')");
+
+ // arrays and maps with more than one element
+ QTest::newRow("2Array")
+ << QCborValue(QCborArray{0, 1}) << int(QCborValue::DiagnosticNotationOptions{})
+ << "[0, 1]";
+ QTest::newRow("2Map")
+ << QCborValue(QCborMap{{0, 1}, {"foo", "bar"}}) << int(QCborValue::DiagnosticNotationOptions{})
+ << "{0: 1, \"foo\": \"bar\"}";
+
+ // line wrapping in arrays and maps
+ QTest::newRow("LW:EmptyArray")
+ << QCborValue(QCborArray()) << int(QCborValue::LineWrapped)
+ << "[\n]";
+ QTest::newRow("LW:EmptyMap")
+ << QCborValue(QCborMap()) << int(QCborValue::LineWrapped)
+ << "{\n}";
+ QTest::newRow("LW:Array:Integer:0")
+ << QCborValue(QCborArray{0}) << int(QCborValue::LineWrapped)
+ << "[\n 0\n]";
+ QTest::newRow("LW:Array:String:5")
+ << QCborValue(QCborArray{"Hello"}) << int(QCborValue::LineWrapped)
+ << "[\n \"Hello\"\n]";
+ QTest::newRow("LW:Map:0-0")
+ << QCborValue(QCborMap{{0, 0}}) << int(QCborValue::LineWrapped)
+ << "{\n 0: 0\n}";
+ QTest::newRow("LW:Map:String:5")
+ << QCborValue(QCborMap{{0, "Hello"}}) << int(QCborValue::LineWrapped)
+ << "{\n 0: \"Hello\"\n}";
+ QTest::newRow("LW:2Array")
+ << QCborValue(QCborArray{0, 1}) << int(QCborValue::LineWrapped)
+ << "[\n 0,\n 1\n]";
+ QTest::newRow("LW:2Map")
+ << QCborValue(QCborMap{{0, 0}, {"foo", "bar"}}) << int(QCborValue::LineWrapped)
+ << "{\n 0: 0,\n \"foo\": \"bar\"\n}";
+
+ // nested arrays and maps
+ QTest::newRow("Array:EmptyArray")
+ << QCborValue(QCborArray() << QCborArray()) << int(QCborValue::DiagnosticNotationOptions{})
+ << "[[]]";
+ QTest::newRow("Array:EmptyMap")
+ << QCborValue(QCborArray() << QCborMap()) << int(QCborValue::DiagnosticNotationOptions{})
+ << "[{}]";
+ QTest::newRow("LW:Array:EmptyArray")
+ << QCborValue(QCborArray() << QCborArray()) << int(QCborValue::LineWrapped)
+ << "[\n [\n ]\n]";
+ QTest::newRow("LW:Array:EmptyMap")
+ << QCborValue(QCborArray() << QCborMap()) << int(QCborValue::LineWrapped)
+ << "[\n {\n }\n]";
+ QTest::newRow("LW:Array:2Array")
+ << QCborValue(QCborArray() << QCborArray{0, 1}) << int(QCborValue::LineWrapped)
+ << "[\n [\n 0,\n 1\n ]\n]";
+ QTest::newRow("LW:Map:2Array")
+ << QCborValue(QCborMap{{0, QCborArray{0, 1}}}) << int(QCborValue::LineWrapped)
+ << "{\n 0: [\n 0,\n 1\n ]\n}";
+ QTest::newRow("LW:Map:2Map")
+ << QCborValue(QCborMap{{-1, QCborMap{{0, 0}, {"foo", "bar"}}}}) << int(QCborValue::LineWrapped)
+ << "{\n -1: {\n 0: 0,\n \"foo\": \"bar\"\n }\n}";
+
+ // string escaping
+ QTest::newRow("String:escaping")
+ << QCborValue("\1\a\b\t\f\r\n\v\x1f\x7f \"\xc2\xa0\xe2\x82\xac\xf0\x90\x80\x80\\\"")
+ << int(QCborValue::DiagnosticNotationOptions{})
+ << "\"\\u0001\\a\\b\\t\\f\\r\\n\\v\\u001F\\u007F \\\"\\u00A0\\u20AC\\U00010000\\\\\\\"\"";
+
+ // extended formatting for byte arrays
+ QTest::newRow("Extended:ByteArray:0")
+ << QCborValue(QByteArray()) << int(QCborValue::ExtendedFormat)
+ << "h''";
+ QTest::newRow("Extended:ByteArray:5")
+ << QCborValue(QByteArray("Hello")) << int(QCborValue::ExtendedFormat)
+ << "h'48 65 6c 6c 6f'";
+ QTest::newRow("Extended:ByteArray:Base64url")
+ << QCborValue(QCborKnownTags::ExpectedBase64url, QByteArray("\xff\xef"))
+ << int(QCborValue::ExtendedFormat) << "21(b64'_-8')";
+ QTest::newRow("Extended:ByteArray:Base64")
+ << QCborValue(QCborKnownTags::ExpectedBase64, QByteArray("\xff\xef"))
+ << int(QCborValue::ExtendedFormat) << "22(b64'/+8=')";
+
+ // formatting applies through arrays too
+ QTest::newRow("Extended:Array:ByteArray:Base64url")
+ << QCborValue(QCborKnownTags::ExpectedBase64url, QCborArray{QByteArray("\xff\xef")})
+ << int(QCborValue::ExtendedFormat) << "21([b64'_-8'])";
+ // and only the innermost applies
+ QTest::newRow("ByteArray:multiple-tags")
+ << QCborValue(QCborKnownTags::ExpectedBase64url,
+ QCborArray{QCborValue(QCborKnownTags::ExpectedBase16, QByteArray("Hello")),
+ QByteArray("\xff\xef")})
+ << int(QCborValue::ExtendedFormat) << "21([23(h'48 65 6c 6c 6f'), b64'_-8'])";
+}
+
+void tst_QCborValue::toDiagnosticNotation()
+{
+ QFETCH(QCborValue, v);
+ QFETCH(QString, expected);
+ QFETCH(int, opts);
+
+ QString result = v.toDiagnosticNotation(QCborValue::DiagnosticNotationOptions(opts));
+ QCOMPARE(result, expected);
+}
+
+QTEST_MAIN(tst_QCborValue)
+
+#include "tst_qcborvalue.moc"
diff --git a/tests/auto/corelib/serialization/qcborvalue_json/qcborvalue_json.pro b/tests/auto/corelib/serialization/qcborvalue_json/qcborvalue_json.pro
new file mode 100644
index 0000000000..c11000b7c2
--- /dev/null
+++ b/tests/auto/corelib/serialization/qcborvalue_json/qcborvalue_json.pro
@@ -0,0 +1,7 @@
+QT = core testlib
+TARGET = tst_qcborvalue_json
+CONFIG += testcase
+SOURCES += \
+ tst_qcborvalue_json.cpp
+
+DEFINES += SRCDIR=\\\"$$PWD/\\\"
diff --git a/tests/auto/corelib/serialization/qcborvalue_json/tst_qcborvalue_json.cpp b/tests/auto/corelib/serialization/qcborvalue_json/tst_qcborvalue_json.cpp
new file mode 100644
index 0000000000..56245a7173
--- /dev/null
+++ b/tests/auto/corelib/serialization/qcborvalue_json/tst_qcborvalue_json.cpp
@@ -0,0 +1,348 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Intel Corporation.
+** Contact: https://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 <QtCore/qcborvalue.h>
+#include <QtTest>
+
+Q_DECLARE_METATYPE(QCborValue)
+
+class tst_QCborValue_Json : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void toVariant_data();
+ void toVariant();
+ void toJson_data() { toVariant_data(); }
+ void toJson();
+ void taggedByteArrayToJson_data();
+ void taggedByteArrayToJson();
+
+ void fromVariant_data() { toVariant_data(); }
+ void fromVariant();
+ void fromJson_data();
+ void fromJson();
+
+ void nonStringKeysInMaps_data();
+ void nonStringKeysInMaps();
+};
+
+void tst_QCborValue_Json::toVariant_data()
+{
+ QTest::addColumn<QCborValue>("v");
+ QTest::addColumn<QVariant>("variant");
+ QTest::addColumn<QJsonValue>("json");
+ QDateTime dt = QDateTime::currentDateTimeUtc();
+ QUuid uuid = QUuid::createUuid();
+
+ QMetaEnum me = QMetaEnum::fromType<QCborValue::Type>();
+ auto add = [me](const QCborValue &v, const QVariant &exp, const QJsonValue &json) {
+ auto addRow = [=]() -> QTestData & {
+ const char *typeString = me.valueToKey(v.type());
+ if (v.type() == QCborValue::Integer)
+ return QTest::addRow("Integer:%lld", exp.toLongLong());
+ if (v.type() == QCborValue::Double)
+ return QTest::addRow("Double:%g", exp.toDouble());
+ if (v.type() == QCborValue::ByteArray || v.type() == QCborValue::String)
+ return QTest::addRow("%s:%d", typeString, exp.toString().size());
+ if (v.type() >= 0x10000)
+ return QTest::newRow(exp.typeName());
+ return QTest::newRow(typeString);
+ };
+ addRow() << v << exp << json;
+ };
+
+ // good JSON matching:
+ add(QCborValue(), QVariant(), QJsonValue::Undefined);
+ add(nullptr, QVariant::fromValue(nullptr), QJsonValue::Null);
+ add(false, false, false);
+ add(true, true, true);
+ add(0, 0, 0);
+ add(1, 1, 1);
+ add(-1, -1, -1);
+ add(0., 0., 0.);
+ add(1.25, 1.25, 1.25);
+ add(-1.25, -1.25, -1.25);
+ add("Hello", "Hello", "Hello");
+
+ // converts to string in JSON:
+ add(QByteArray("Hello"), QByteArray("Hello"), "SGVsbG8");
+ add(QCborValue(dt), dt, dt.toString(Qt::ISODateWithMs));
+ add(QCborValue(QUrl("http://example.com/{q}")), QUrl("http://example.com/{q}"),
+ "http://example.com/%7Bq%7D"); // note the encoded form in JSON
+ add(QCborValue(QRegularExpression(".")), QRegularExpression("."), ".");
+ add(QCborValue(uuid), uuid, uuid.toString(QUuid::WithoutBraces));
+
+ // not valid in JSON
+ QTest::newRow("simpletype") << QCborValue(QCborSimpleType(255))
+ << QVariant::fromValue(QCborSimpleType(255))
+ << QJsonValue("simple(255)");
+ QTest::newRow("Double:inf") << QCborValue(qInf())
+ << QVariant(qInf())
+ << QJsonValue();
+ QTest::newRow("Double:-inf") << QCborValue(-qInf())
+ << QVariant(-qInf())
+ << QJsonValue();
+ QTest::newRow("Double:nan") << QCborValue(qQNaN())
+ << QVariant(qQNaN())
+ << QJsonValue();
+
+ // large integral values lose precision in JSON
+ QTest::newRow("Integer:max") << QCborValue(std::numeric_limits<qint64>::max())
+ << QVariant(std::numeric_limits<qint64>::max())
+ << QJsonValue(std::numeric_limits<qint64>::max());
+ QTest::newRow("Integer:min") << QCborValue(std::numeric_limits<qint64>::min())
+ << QVariant(std::numeric_limits<qint64>::min())
+ << QJsonValue(std::numeric_limits<qint64>::min());
+
+ // empty arrays and maps
+ add(QCborArray(), QVariantList(), QJsonArray());
+ add(QCborMap(), QVariantMap(), QJsonObject());
+}
+
+void tst_QCborValue_Json::toVariant()
+{
+ QFETCH(QCborValue, v);
+ QFETCH(QVariant, variant);
+
+ if (qIsNaN(variant.toDouble())) {
+ // because NaN != NaN, QVariant(NaN) != QVariant(NaN), so we
+ // only need to compare the classification
+ QVERIFY(qIsNaN(v.toVariant().toDouble()));
+
+ // the rest of this function depends on the variant comparison
+ return;
+ }
+
+ QCOMPARE(v.toVariant(), variant);
+ if (variant.isValid()) {
+ QVariant variant2 = QVariant::fromValue(v);
+ QVERIFY(variant2.canConvert(variant.userType()));
+ QVERIFY(variant2.convert(variant.userType()));
+ QCOMPARE(variant2, variant);
+ }
+
+ // tags get ignored:
+ QCOMPARE(QCborValue(QCborKnownTags::Signature, v).toVariant(), variant);
+
+ // make arrays with this item
+ QCOMPARE(QCborArray({v}).toVariantList(), QVariantList({variant}));
+ QCOMPARE(QCborArray({v, v}).toVariantList(), QVariantList({variant, variant}));
+
+ // and maps
+ QCOMPARE(QCborMap({{"foo", v}}).toVariantMap(), QVariantMap({{"foo", variant}}));
+ QCOMPARE(QCborMap({{"foo", v}}).toVariantHash(), QVariantHash({{"foo", variant}}));
+
+ // finally, mixed
+ QCOMPARE(QCborArray{QCborMap({{"foo", v}})}.toVariantList(),
+ QVariantList{QVariantMap({{"foo", variant}})});
+}
+
+void tst_QCborValue_Json::toJson()
+{
+ QFETCH(QCborValue, v);
+ QFETCH(QJsonValue, json);
+
+ QCOMPARE(v.toJsonValue(), json);
+ QCOMPARE(QVariant::fromValue(v).toJsonValue(), json);
+
+ // most tags get ignored:
+ QCOMPARE(QCborValue(QCborKnownTags::Signature, v).toJsonValue(), json);
+
+ // make arrays with this item
+ QCOMPARE(QCborArray({v}).toJsonArray(), QJsonArray({json}));
+ QCOMPARE(QCborArray({v, v}).toJsonArray(), QJsonArray({json, json}));
+
+ // and maps
+ QCOMPARE(QCborMap({{"foo", v}}).toJsonObject(), QJsonObject({{"foo", json}}));
+
+ // finally, mixed
+ QCOMPARE(QCborArray{QCborMap({{"foo", v}})}.toJsonArray(),
+ QJsonArray{QJsonObject({{"foo", json}})});
+}
+
+void tst_QCborValue_Json::taggedByteArrayToJson_data()
+{
+ QTest::addColumn<QCborValue>("v");
+ QTest::addColumn<QJsonValue>("json");
+
+ QByteArray data("\xff\x01");
+ QTest::newRow("base64url") << QCborValue(QCborKnownTags::ExpectedBase64url, data) << QJsonValue("_wE");
+ QTest::newRow("base64") << QCborValue(QCborKnownTags::ExpectedBase64, data) << QJsonValue("/wE=");
+ QTest::newRow("hex") << QCborValue(QCborKnownTags::ExpectedBase16, data) << QJsonValue("ff01");
+}
+
+void tst_QCborValue_Json::taggedByteArrayToJson()
+{
+ QFETCH(QCborValue, v);
+ QFETCH(QJsonValue, json);
+
+ QCOMPARE(v.toJsonValue(), json);
+ QCOMPARE(QCborArray({v}).toJsonArray(), QJsonArray({json}));
+}
+
+void tst_QCborValue_Json::fromVariant()
+{
+ QFETCH(QCborValue, v);
+ QFETCH(QVariant, variant);
+
+ QCOMPARE(QCborValue::fromVariant(variant), v);
+ QCOMPARE(variant.value<QCborValue>(), v);
+
+ // try arrays
+ QCOMPARE(QCborArray::fromVariantList({variant}), QCborArray{v});
+ QCOMPARE(QCborArray::fromVariantList({variant, variant}), QCborArray({v, v}));
+
+ if (variant.type() == QVariant::String) {
+ QString s = variant.toString();
+ QCOMPARE(QCborArray::fromStringList({s}), QCborArray{v});
+ QCOMPARE(QCborArray::fromStringList({s, s}), QCborArray({v, v}));
+ }
+
+ // maps...
+ QVariantMap map{{"foo", variant}};
+ QCOMPARE(QCborMap::fromVariantMap(map), QCborMap({{"foo", v}}));
+ QCOMPARE(QCborMap::fromVariantHash({{"foo", variant}}), QCborMap({{"foo", v}}));
+
+ // nested
+ QVariantMap outer{{"bar", QVariantList{0, map, true}}};
+ QCOMPARE(QCborMap::fromVariantMap(outer),
+ QCborMap({{"bar", QCborArray{0, QCborMap{{"foo", v}}, true}}}));
+}
+
+void tst_QCborValue_Json::fromJson_data()
+{
+ QTest::addColumn<QCborValue>("v");
+ QTest::addColumn<QJsonValue>("json");
+
+ QTest::newRow("null") << QCborValue(QCborValue::Null) << QJsonValue(QJsonValue::Null);
+ QTest::newRow("false") << QCborValue(false) << QJsonValue(false);
+ QTest::newRow("true") << QCborValue(true) << QJsonValue(true);
+ QTest::newRow("0") << QCborValue(0) << QJsonValue(0.);
+ QTest::newRow("1") << QCborValue(1) << QJsonValue(1);
+ QTest::newRow("1.5") << QCborValue(1.5) << QJsonValue(1.5);
+ QTest::newRow("string") << QCborValue("Hello") << QJsonValue("Hello");
+ QTest::newRow("array") << QCborValue(QCborValue::Array) << QJsonValue(QJsonValue::Array);
+ QTest::newRow("map") << QCborValue(QCborValue::Map) << QJsonValue(QJsonValue::Object);
+}
+
+void tst_QCborValue_Json::fromJson()
+{
+ QFETCH(QCborValue, v);
+ QFETCH(QJsonValue, json);
+
+ QCOMPARE(QCborValue::fromJsonValue(json), v);
+ QCOMPARE(QVariant(json).value<QCborValue>(), v);
+ QCOMPARE(QCborArray::fromJsonArray({json}), QCborArray({v}));
+ QCOMPARE(QCborArray::fromJsonArray({json, json}), QCborArray({v, v}));
+ QCOMPARE(QCborMap::fromJsonObject({{"foo", json}}), QCborMap({{"foo", v}}));
+
+ // confirm we can roundtrip back to JSON
+ QCOMPARE(QCborValue::fromJsonValue(json).toJsonValue(), json);
+}
+
+void tst_QCborValue_Json::nonStringKeysInMaps_data()
+{
+ QTest::addColumn<QCborValue>("key");
+ QTest::addColumn<QString>("converted");
+
+ auto add = [](const char *str, const QCborValue &v) {
+ QTest::newRow(str) << v << str;
+ };
+ add("0", 0);
+ add("-1", -1);
+ add("false", false);
+ add("true", true);
+ add("null", nullptr);
+ add("undefined", {}); // should this be ""?
+ add("simple(255)", QCborSimpleType(255));
+ add("2.5", 2.5);
+
+ QByteArray data("\xff\x01");
+ QTest::newRow("bytearray") << QCborValue(data) << "_wE";
+ QTest::newRow("base64url") << QCborValue(QCborKnownTags::ExpectedBase64url, data) << "_wE";
+ QTest::newRow("base64") << QCborValue(QCborKnownTags::ExpectedBase64, data) << "/wE=";
+ QTest::newRow("hex") << QCborValue(QCborKnownTags::ExpectedBase16, data) << "ff01";
+
+ QTest::newRow("emptyarray") << QCborValue(QCborValue::Array) << "[]";
+ QTest::newRow("emptymap") << QCborValue(QCborValue::Map) << "{}";
+ QTest::newRow("array") << QCborValue(QCborArray{1, true, 2.5, "Hello"})
+ << "[1, true, 2.5, \"Hello\"]";
+ QTest::newRow("map") << QCborValue(QCborMap{{"Hello", 0}, {0, "Hello"}})
+ << "{\"Hello\": 0, 0: \"Hello\"}";
+
+ QDateTime dt = QDateTime::currentDateTimeUtc();
+ QUrl url("https://example.com");
+ QUuid uuid = QUuid::createUuid();
+ QTest::newRow("QDateTime") << QCborValue(dt) << dt.toString(Qt::ISODateWithMs);
+ QTest::newRow("QUrl") << QCborValue(url) << url.toString(QUrl::FullyEncoded);
+ QTest::newRow("QRegularExpression") << QCborValue(QRegularExpression(".*")) << ".*";
+ QTest::newRow("QUuid") << QCborValue(uuid) << uuid.toString(QUuid::WithoutBraces);
+}
+
+void tst_QCborValue_Json::nonStringKeysInMaps()
+{
+ QFETCH(QCborValue, key);
+ QFETCH(QString, converted);
+
+ QCborMap m;
+ m.insert(key, 0);
+
+ {
+ QVariantMap vm = m.toVariantMap();
+ auto it = vm.begin();
+ QVERIFY(it != vm.end());
+ QCOMPARE(it.key(), converted);
+ QCOMPARE(it.value(), 0);
+ QCOMPARE(++it, vm.end());
+ }
+
+ {
+ QJsonObject o = m.toJsonObject();
+ auto it = o.begin();
+ QVERIFY(it != o.end());
+ QCOMPARE(it.key(), converted);
+ QCOMPARE(it.value(), 0);
+ QCOMPARE(++it, o.end());
+ }
+}
+
+QTEST_MAIN(tst_QCborValue_Json)
+
+#include "tst_qcborvalue_json.moc"
diff --git a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp
index 14a2528cc6..011a0e1a85 100644
--- a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp
+++ b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp
@@ -260,16 +260,16 @@ static int NColorRoles[] = {
QPalette::HighlightedText + 1, // Qt_4_0, Qt_4_1
QPalette::HighlightedText + 1, // Qt_4_2
QPalette::AlternateBase + 1, // Qt_4_3
- QPalette::ToolTipText + 1, // Qt_4_4
- QPalette::ToolTipText + 1, // Qt_4_5
- QPalette::ToolTipText + 1, // Qt_4_6
- QPalette::ToolTipText + 1, // Qt_5_0
- QPalette::ToolTipText + 1, // Qt_5_1
- QPalette::ToolTipText + 1, // Qt_5_2
- QPalette::ToolTipText + 1, // Qt_5_3
- QPalette::ToolTipText + 1, // Qt_5_4
- QPalette::ToolTipText + 1, // Qt_5_5
- QPalette::ToolTipText + 1, // Qt_5_6
+ QPalette::PlaceholderText + 1, // Qt_4_4
+ QPalette::PlaceholderText + 1, // Qt_4_5
+ QPalette::PlaceholderText + 1, // Qt_4_6
+ QPalette::PlaceholderText + 1, // Qt_5_0
+ QPalette::PlaceholderText + 1, // Qt_5_1
+ QPalette::PlaceholderText + 1, // Qt_5_2
+ QPalette::PlaceholderText + 1, // Qt_5_3
+ QPalette::PlaceholderText + 1, // Qt_5_4
+ QPalette::PlaceholderText + 1, // Qt_5_5
+ QPalette::PlaceholderText + 1, // Qt_5_6
0 // add the correct value for Qt_5_7 here later
};
@@ -2139,7 +2139,7 @@ void tst_QDataStream::setVersion()
*/
// revise the test if new color roles or color groups are added
- QVERIFY(QPalette::NColorRoles == QPalette::ToolTipText + 1);
+ QVERIFY(QPalette::NColorRoles == QPalette::PlaceholderText + 1);
QCOMPARE(int(QPalette::NColorGroups), 3);
QByteArray ba2;
@@ -2211,25 +2211,22 @@ void tst_QDataStream::setVersion()
}
}
-class SequentialBuffer : public QBuffer
+class SequentialBuffer : public QIODevice
{
public:
- SequentialBuffer(QByteArray *data) : QBuffer(data) { offset = 0; }
+ SequentialBuffer(QByteArray *data) : QIODevice() { buf.setBuffer(data); }
- bool isSequential() const { return true; }
- bool seek(qint64 pos) { offset = pos; return QBuffer::seek(pos); }
- qint64 pos() const { return qint64(offset); }
+ bool isSequential() const override { return true; }
+ bool open(OpenMode mode) override { return buf.open(mode) && QIODevice::open(mode | QIODevice::Unbuffered); }
+ void close() override { buf.close(); QIODevice::close(); }
+ qint64 bytesAvailable() const override { return QIODevice::bytesAvailable() + buf.bytesAvailable(); }
protected:
- qint64 readData(char *data, qint64 maxSize)
- {
- qint64 ret = QBuffer::readData(data, maxSize);
- offset += ret;
- return ret;
- }
+ qint64 readData(char *data, qint64 maxSize) override { return buf.read(data, maxSize); }
+ qint64 writeData(const char *data, qint64 maxSize) override { return buf.write(data, maxSize); }
private:
- int offset;
+ QBuffer buf;
};
void tst_QDataStream::skipRawData_data()
@@ -3329,15 +3326,21 @@ void tst_QDataStream::transaction_data()
QTest::addColumn<bool>("bData");
QTest::addColumn<float>("fData");
QTest::addColumn<double>("dData");
+ QTest::addColumn<QImage>("imgData");
QTest::addColumn<QByteArray>("strData");
QTest::addColumn<QByteArray>("rawData");
+ QImage img1(open_xpm);
+ QImage img2;
+ QImage img3(50, 50, QImage::Format_ARGB32);
+ img3.fill(qRgba(12, 34, 56, 78));
+
QTest::newRow("1") << qint8(1) << qint16(2) << qint32(3) << qint64(4) << true << 5.0f
- << double(6.0) << QByteArray("Hello world!") << QByteArray("Qt rocks!");
+ << double(6.0) << img1 << QByteArray("Hello world!") << QByteArray("Qt rocks!");
QTest::newRow("2") << qint8(1 << 6) << qint16(1 << 14) << qint32(1 << 30) << qint64Data(3) << false << 123.0f
- << double(234.0) << stringData(5).toUtf8() << stringData(6).toUtf8();
+ << double(234.0) << img2 << stringData(5).toUtf8() << stringData(6).toUtf8();
QTest::newRow("3") << qint8(-1) << qint16(-2) << qint32(-3) << qint64(-4) << true << -123.0f
- << double(-234.0) << stringData(3).toUtf8() << stringData(4).toUtf8();
+ << double(-234.0) << img3 << stringData(3).toUtf8() << stringData(4).toUtf8();
}
void tst_QDataStream::transaction()
@@ -3351,6 +3354,7 @@ void tst_QDataStream::transaction()
QFETCH(bool, bData);
QFETCH(float, fData);
QFETCH(double, dData);
+ QFETCH(QImage, imgData);
QFETCH(QByteArray, strData);
QFETCH(QByteArray, rawData);
@@ -3358,12 +3362,13 @@ void tst_QDataStream::transaction()
QDataStream stream(&testBuffer, QIODevice::WriteOnly);
stream << i8Data << i16Data << i32Data << i64Data
- << bData << fData << dData << strData.constData();
+ << bData << fData << dData << imgData << strData.constData();
stream.writeRawData(rawData.constData(), rawData.size());
}
for (int splitPos = 0; splitPos <= testBuffer.size(); ++splitPos) {
QByteArray readBuffer(testBuffer.left(splitPos));
+
SequentialBuffer dev(&readBuffer);
dev.open(QIODevice::ReadOnly);
QDataStream stream(&dev);
@@ -3375,12 +3380,13 @@ void tst_QDataStream::transaction()
bool b;
float f;
double d;
+ QImage img;
char *str;
QByteArray raw(rawData.size(), 0);
forever {
stream.startTransaction();
- stream >> i8 >> i16 >> i32 >> i64 >> b >> f >> d >> str;
+ stream >> i8 >> i16 >> i32 >> i64 >> b >> f >> d >> img >> str;
stream.readRawData(raw.data(), raw.size());
if (stream.commitTransaction())
@@ -3402,6 +3408,7 @@ void tst_QDataStream::transaction()
QCOMPARE(b, bData);
QCOMPARE(f, fData);
QCOMPARE(d, dData);
+ QCOMPARE(img, imgData);
QVERIFY(strData == str);
delete [] str;
QCOMPARE(raw, rawData);
diff --git a/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp b/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp
index df8746e518..edea4713a1 100644
--- a/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp
+++ b/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp
@@ -161,6 +161,7 @@ private slots:
void string_write_operator_ToDevice();
void latin1String_write_operator_ToDevice();
void stringref_write_operator_ToDevice();
+ void stringview_write_operator_ToDevice();
// other
void skipWhiteSpace_data();
@@ -2573,6 +2574,17 @@ void tst_QTextStream::stringref_write_operator_ToDevice()
QCOMPARE(buf.buffer().constData(), "No explicit lengthExplicit length");
}
+void tst_QTextStream::stringview_write_operator_ToDevice()
+{
+ QBuffer buf;
+ buf.open(QBuffer::WriteOnly);
+ QTextStream stream(&buf);
+ const QStringView expected = QStringViewLiteral("expectedStringView");
+ stream << expected;
+ stream.flush();
+ QCOMPARE(buf.buffer().constData(), "expectedStringView");
+}
+
// ------------------------------------------------------------------------------
void tst_QTextStream::useCase1()
{
diff --git a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
index 16a4200b5d..8fdf91b090 100644
--- a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
+++ b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp
@@ -577,6 +577,8 @@ private slots:
void invalidStringCharacters() const;
void hasError() const;
void readBack() const;
+ void roundTrip() const;
+ void roundTrip_data() const;
private:
static QByteArray readFile(const QString &filename);
@@ -1741,5 +1743,35 @@ void tst_QXmlStream::readBack() const
}
}
+void tst_QXmlStream::roundTrip_data() const
+{
+ QTest::addColumn<QString>("in");
+
+ QTest::newRow("QTBUG-63434") <<
+ "<?xml version=\"1.0\"?>"
+ "<root>"
+ "<father>"
+ "<child xmlns:unknown=\"http://mydomain\">Text</child>"
+ "</father>"
+ "</root>\n";
+}
+
+void tst_QXmlStream::roundTrip() const
+{
+ QFETCH(QString, in);
+ QString out;
+
+ QXmlStreamReader reader(in);
+ QXmlStreamWriter writer(&out);
+
+ while (!reader.atEnd()) {
+ reader.readNext();
+ QVERIFY(!reader.hasError());
+ writer.writeCurrentToken(reader);
+ QVERIFY(!writer.hasError());
+ }
+ QCOMPARE(out, in);
+}
+
#include "tst_qxmlstream.moc"
// vim: et:ts=4:sw=4:sts=4
diff --git a/tests/auto/corelib/serialization/serialization.pro b/tests/auto/corelib/serialization/serialization.pro
index afb9c5b61c..9187de1bc5 100644
--- a/tests/auto/corelib/serialization/serialization.pro
+++ b/tests/auto/corelib/serialization/serialization.pro
@@ -1,6 +1,10 @@
TEMPLATE = subdirs
SUBDIRS = \
json \
+ qcborstreamreader \
+ qcborstreamwriter \
+ qcborvalue \
+ qcborvalue_json \
qdatastream \
qtextstream \
qxmlstream
diff --git a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
index d4a3ee6054..b8c82c2ea0 100644
--- a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
+++ b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
@@ -1021,6 +1021,8 @@ void tst_QFuture::iterators()
QCOMPARE(i2, c2);
QCOMPARE(c2, i2);
QCOMPARE(c2, c2);
+ QCOMPARE(1 + i1, i1 + 1);
+ QCOMPARE(1 + c1, c1 + 1);
QVERIFY(i1 != i2);
QVERIFY(i1 != c2);
@@ -1070,6 +1072,8 @@ void tst_QFuture::iterators()
QCOMPARE(i2, c2);
QCOMPARE(c2, i2);
QCOMPARE(c2, c2);
+ QCOMPARE(1 + i1, i1 + 1);
+ QCOMPARE(1 + c1, c1 + 1);
QVERIFY(i1 != i2);
QVERIFY(i1 != c2);
diff --git a/tests/auto/corelib/thread/qsemaphore/BLACKLIST b/tests/auto/corelib/thread/qsemaphore/BLACKLIST
index eb83b03556..0786f50417 100644
--- a/tests/auto/corelib/thread/qsemaphore/BLACKLIST
+++ b/tests/auto/corelib/thread/qsemaphore/BLACKLIST
@@ -1,6 +1,8 @@
[tryAcquireWithTimeout:0.2s]
windows
osx-10.12
+osx-10.13
[tryAcquireWithTimeout:2s]
windows
osx-10.12
+osx-10.13
diff --git a/tests/auto/corelib/thread/qthreadonce/qthreadonce.cpp b/tests/auto/corelib/thread/qthreadonce/qthreadonce.cpp
index 9179750218..d27884197a 100644
--- a/tests/auto/corelib/thread/qthreadonce/qthreadonce.cpp
+++ b/tests/auto/corelib/thread/qthreadonce/qthreadonce.cpp
@@ -30,7 +30,6 @@
#include "qplatformdefs.h"
#include "qthreadonce.h"
-#ifndef QT_NO_THREAD
#include "qmutex.h"
Q_GLOBAL_STATIC_WITH_ARGS(QMutex, onceInitializationMutex, (QMutex::Recursive))
@@ -104,5 +103,3 @@ void QOnceControl::done()
{
extra &= ~MustRunCode;
}
-
-#endif // QT_NO_THREAD
diff --git a/tests/auto/corelib/thread/qthreadonce/qthreadonce.h b/tests/auto/corelib/thread/qthreadonce/qthreadonce.h
index 71e830ca16..e5918b8fa5 100644
--- a/tests/auto/corelib/thread/qthreadonce/qthreadonce.h
+++ b/tests/auto/corelib/thread/qthreadonce/qthreadonce.h
@@ -34,8 +34,6 @@
#include <QtCore/qatomic.h>
-#ifndef QT_NO_THREAD
-
class QOnceControl
{
public:
@@ -91,6 +89,4 @@ public:
inline operator T*() { return value(); }
};
-#endif // QT_NO_THREAD
-
#endif
diff --git a/tests/auto/corelib/thread/qthreadstorage/crashonexit/crashonexit.pro b/tests/auto/corelib/thread/qthreadstorage/crashonexit/crashonexit.pro
index 94a0a01e94..d5c09ebc84 100644
--- a/tests/auto/corelib/thread/qthreadstorage/crashonexit/crashonexit.pro
+++ b/tests/auto/corelib/thread/qthreadstorage/crashonexit/crashonexit.pro
@@ -1,5 +1,13 @@
SOURCES += crashOnExit.cpp
-DESTDIR = ./
+debug_and_release {
+ CONFIG(debug, debug|release) {
+ TARGET = ../../debug/crashOnExit_helper
+ } else {
+ TARGET = ../../release/crashOnExit_helper
+ }
+} else {
+ TARGET = ../crashOnExit_helper
+}
QT = core
CONFIG -= app_bundle
CONFIG += console
diff --git a/tests/auto/corelib/thread/qthreadstorage/test/test.pro b/tests/auto/corelib/thread/qthreadstorage/test/test.pro
index d7190f7e7b..d2f21f48f0 100644
--- a/tests/auto/corelib/thread/qthreadstorage/test/test.pro
+++ b/tests/auto/corelib/thread/qthreadstorage/test/test.pro
@@ -1,9 +1,16 @@
CONFIG += testcase
-TARGET = ../tst_qthreadstorage
-CONFIG -= debug_and_release_target
+debug_and_release {
+ CONFIG(debug, debug|release) {
+ TARGET = ../../debug/tst_qthreadstorage
+ !android:!winrt: TEST_HELPER_INSTALLS = ../../debug/crashonexit_helper
+ } else {
+ TARGET = ../../release/tst_qthreadstorage
+ !android:!winrt: TEST_HELPER_INSTALLS = ../../release/crashonexit_helper
+ }
+} else {
+ TARGET = ../tst_qthreadstorage
+ !android:!winrt: TEST_HELPER_INSTALLS = ../crashonexit_helper
+}
CONFIG += console
QT = core testlib
SOURCES = ../tst_qthreadstorage.cpp
-
-!android:!winrt: TEST_HELPER_INSTALLS = ../crashonexit/crashonexit
-
diff --git a/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp b/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp
index 403e28b07b..ef5d3452d5 100644
--- a/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp
+++ b/tests/auto/corelib/thread/qthreadstorage/tst_qthreadstorage.cpp
@@ -48,7 +48,6 @@ class tst_QThreadStorage : public QObject
{
Q_OBJECT
private slots:
- void initTestCase();
void hasLocalData();
void localData();
void localData_const();
@@ -60,9 +59,6 @@ private slots:
void leakInDestructor();
void resetInDestructor();
void valueBased();
-
-private:
- QString m_crashOnExit;
};
class Pointer
@@ -74,22 +70,6 @@ public:
};
int Pointer::count = 0;
-void tst_QThreadStorage::initTestCase()
-{
-#if QT_CONFIG(process)
- const QString crashOnExitDir = QFINDTESTDATA("crashonexit");
- QVERIFY2(!crashOnExitDir.isEmpty(),
- qPrintable(QString::fromLatin1("Could not find 'crashonexit' starting from '%1'")
- .arg(QDir::toNativeSeparators(QDir::currentPath()))));
- m_crashOnExit = crashOnExitDir + QStringLiteral("/crashonexit");
-#ifdef Q_OS_WIN
- m_crashOnExit += QStringLiteral(".exe");
-#endif
- QVERIFY2(QFileInfo(m_crashOnExit).isExecutable(),
- qPrintable(QDir::toNativeSeparators(m_crashOnExit) + QStringLiteral(" does not exist or is not executable.")));
-#endif
-}
-
void tst_QThreadStorage::hasLocalData()
{
QThreadStorage<Pointer *> pointers;
@@ -329,7 +309,7 @@ void tst_QThreadStorage::crashOnExit()
QSKIP("No qprocess support", SkipAll);
#else
QString errorMessage;
- QVERIFY2(runCrashOnExit(m_crashOnExit, &errorMessage),
+ QVERIFY2(runCrashOnExit("crashOnExit_helper", &errorMessage),
qPrintable(errorMessage));
#endif
}
diff --git a/tests/auto/corelib/thread/thread.pro b/tests/auto/corelib/thread/thread.pro
index d3c669859b..90b8d6806e 100644
--- a/tests/auto/corelib/thread/thread.pro
+++ b/tests/auto/corelib/thread/thread.pro
@@ -1,22 +1,25 @@
TEMPLATE=subdirs
-SUBDIRS=\
- qatomicint \
- qatomicinteger \
- qatomicpointer \
- qresultstore \
- qfuture \
- qfuturesynchronizer \
- qmutex \
- qmutexlocker \
- qreadlocker \
- qreadwritelock \
- qsemaphore \
- qthread \
- qthreadonce \
- qthreadpool \
- qthreadstorage \
- qwaitcondition \
- qwritelocker
+
+qtConfig(thread) {
+ SUBDIRS=\
+ qatomicint \
+ qatomicinteger \
+ qatomicpointer \
+ qresultstore \
+ qfuture \
+ qfuturesynchronizer \
+ qmutex \
+ qmutexlocker \
+ qreadlocker \
+ qreadwritelock \
+ qsemaphore \
+ qthread \
+ qthreadonce \
+ qthreadpool \
+ qthreadstorage \
+ qwaitcondition \
+ qwritelocker
+}
qtHaveModule(concurrent) {
SUBDIRS += \
diff --git a/tests/auto/corelib/tools/collections/tst_collections.cpp b/tests/auto/corelib/tools/collections/tst_collections.cpp
index 38366e86ff..b40b1f0624 100644
--- a/tests/auto/corelib/tools/collections/tst_collections.cpp
+++ b/tests/auto/corelib/tools/collections/tst_collections.cpp
@@ -2620,6 +2620,8 @@ void testLinkedListLikeStlIterators()
QVERIFY(i2 == c2);
QVERIFY(c2 == i2);
QVERIFY(c2 == c2);
+ QVERIFY(1 + i1 == i1 + 1);
+ QVERIFY(1 + c1 == c1 + 1);
QVERIFY(i1 != i2);
QVERIFY(i1 != c2);
@@ -2731,6 +2733,8 @@ void testMapLikeStlIterators()
QVERIFY(i2 == c2);
QVERIFY(c2 == i2);
QVERIFY(c2 == c2);
+ QVERIFY(1 + i1 == i1 + 1);
+ QVERIFY(1 + c1 == c1 + 1);
QVERIFY(i1 != i2);
QVERIFY(i1 != c2);
diff --git a/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp b/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp
index 338adaabf7..1ed41793dc 100644
--- a/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp
+++ b/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp
@@ -106,6 +106,8 @@ private slots:
void number();
void toInt_data();
void toInt();
+ void toDouble_data();
+ void toDouble();
void blockSizeCalculations();
void resizeAfterFromRawData();
@@ -141,6 +143,8 @@ private slots:
#endif
void toUpperLower_data();
void toUpperLower();
+ void isUpper();
+ void isLower();
void macTypes();
@@ -856,15 +860,38 @@ void tst_QByteArray::qstricmp()
if ( actual != 0 ) {
actual = (actual < 0 ? -1 : 1);
}
- QCOMPARE(expected, actual);
+ QCOMPARE(actual, expected);
+
+ actual = ::qstricmp("012345679abcd" + str1.toLatin1(), "012345679AbCd" + str2.toLatin1());
+ if ( actual != 0 ) {
+ actual = (actual < 0 ? -1 : 1);
+ }
+ QCOMPARE(actual, expected);
+
+ actual = str1.toLatin1().compare(str2.toLatin1(), Qt::CaseInsensitive);
+ if ( actual != 0 ) {
+ actual = (actual < 0 ? -1 : 1);
+ }
+ QCOMPARE(actual, expected);
+
+ actual = str1.toLatin1().compare(str2.toLatin1().constData(), Qt::CaseInsensitive);
+ if ( actual != 0 ) {
+ actual = (actual < 0 ? -1 : 1);
+ }
+ QCOMPARE(actual, expected);
}
void tst_QByteArray::qstricmp_singularities()
{
QCOMPARE(::qstricmp(0, 0), 0);
- QVERIFY(::qstricmp(0, "a") != 0);
- QVERIFY(::qstricmp("a", 0) != 0);
+ QVERIFY(::qstricmp(0, "a") < 0);
+ QVERIFY(::qstricmp("a", 0) > 0);
QCOMPARE(::qstricmp("", ""), 0);
+ QCOMPARE(QByteArray().compare(nullptr, Qt::CaseInsensitive), 0);
+ QCOMPARE(QByteArray().compare("", Qt::CaseInsensitive), 0);
+ QVERIFY(QByteArray("a").compare(nullptr, Qt::CaseInsensitive) > 0);
+ QVERIFY(QByteArray("a").compare("", Qt::CaseInsensitive) > 0);
+ QVERIFY(QByteArray().compare("a", Qt::CaseInsensitive) < 0);
}
void tst_QByteArray::qstrnicmp_singularities()
@@ -874,6 +901,9 @@ void tst_QByteArray::qstrnicmp_singularities()
QVERIFY(::qstrnicmp("a", 0, 123) != 0);
QCOMPARE(::qstrnicmp("", "", 123), 0);
QCOMPARE(::qstrnicmp("a", "B", 0), 0);
+ QCOMPARE(QByteArray().compare(QByteArray(), Qt::CaseInsensitive), 0);
+ QVERIFY(QByteArray().compare(QByteArray("a"), Qt::CaseInsensitive) < 0);
+ QVERIFY(QByteArray("a").compare(QByteArray(), Qt::CaseInsensitive) > 0);
}
void tst_QByteArray::chop_data()
@@ -1289,6 +1319,11 @@ void tst_QByteArray::toInt_data()
QTest::newRow("base 0-3") << QByteArray("010") << 0 << int(8) << true;
QTest::newRow("empty") << QByteArray() << 0 << int(0) << false;
+ QTest::newRow("leading space") << QByteArray(" 100") << 10 << int(100) << true;
+ QTest::newRow("trailing space") << QByteArray("100 ") << 10 << int(100) << true;
+ QTest::newRow("leading junk") << QByteArray("x100") << 10 << int(0) << false;
+ QTest::newRow("trailing junk") << QByteArray("100x") << 10 << int(0) << false;
+
// using fromRawData
QTest::newRow("raw1") << QByteArray::fromRawData("1", 1) << 10 << 1 << true;
QTest::newRow("raw2") << QByteArray::fromRawData("1foo", 1) << 10 << 1 << true;
@@ -1313,6 +1348,34 @@ void tst_QByteArray::toInt()
QCOMPARE( number, expectednumber );
}
+void tst_QByteArray::toDouble_data()
+{
+ QTest::addColumn<QByteArray>("string");
+ QTest::addColumn<double>("expectedNumber");
+ QTest::addColumn<bool>("expectedOk");
+
+ QTest::newRow("decimal") << QByteArray("1.2345") << 1.2345 << true;
+ QTest::newRow("exponent lowercase") << QByteArray("1.2345e+01") << 12.345 << true;
+ QTest::newRow("exponent uppercase") << QByteArray("1.2345E+02") << 123.45 << true;
+ QTest::newRow("leading spaces") << QByteArray(" \n\r\t1.2345") << 1.2345 << true;
+ QTest::newRow("trailing spaces") << QByteArray("1.2345 \n\r\t") << 1.2345 << true;
+ QTest::newRow("leading junk") << QByteArray("x1.2345") << 0.0 << false;
+ QTest::newRow("trailing junk") << QByteArray("1.2345x") << 0.0 << false;
+}
+
+void tst_QByteArray::toDouble()
+{
+ QFETCH(QByteArray, string);
+ QFETCH(double, expectedNumber);
+ QFETCH(bool, expectedOk);
+
+ bool ok;
+ const double number = string.toDouble(&ok);
+
+ QCOMPARE(ok, expectedOk);
+ QCOMPARE(number, expectedNumber);
+}
+
void tst_QByteArray::toULong_data()
{
QTest::addColumn<QByteArray>("str");
@@ -1326,6 +1389,11 @@ void tst_QByteArray::toULong_data()
QTest::newRow("empty") << QByteArray("") << 10 << 0UL << false;
QTest::newRow("ulong1") << QByteArray("3234567890") << 10 << 3234567890UL << true;
QTest::newRow("ulong2") << QByteArray("fFFfFfFf") << 16 << 0xFFFFFFFFUL << true;
+
+ QTest::newRow("leading spaces") << QByteArray(" \n\r\t100") << 10 << 100UL << true;
+ QTest::newRow("trailing spaces") << QByteArray("100 \n\r\t") << 10 << 100UL << true;
+ QTest::newRow("leading junk") << QByteArray("x100") << 10 << 0UL << false;
+ QTest::newRow("trailing junk") << QByteArray("100x") << 10 << 0UL << false;
}
void tst_QByteArray::toULong()
@@ -1351,6 +1419,10 @@ void tst_QByteArray::toULongLong_data()
QTest::newRow("default") << QByteArray() << 10 << (qulonglong)0 << false;
QTest::newRow("out of base bound") << QByteArray("c") << 10 << (qulonglong)0 << false;
+ QTest::newRow("leading spaces") << QByteArray(" \n\r\t100") << 10 << qulonglong(100) << true;
+ QTest::newRow("trailing spaces") << QByteArray("100 \n\r\t") << 10 << qulonglong(100) << true;
+ QTest::newRow("leading junk") << QByteArray("x100") << 10 << qulonglong(0) << false;
+ QTest::newRow("trailing junk") << QByteArray("100x") << 10 << qulonglong(0) << false;
}
void tst_QByteArray::toULongLong()
@@ -1757,6 +1829,12 @@ void tst_QByteArray::compare()
const bool isLess = result < 0;
const bool isGreater = result > 0;
+ int cmp = str1.compare(str2);
+ if (cmp)
+ cmp = (cmp < 0 ? -1 : 1);
+
+ QCOMPARE(cmp, result);
+
// basic tests:
QCOMPARE(str1 == str2, isEqual);
QCOMPARE(str1 < str2, isLess);
@@ -2188,6 +2266,51 @@ void tst_QByteArray::toUpperLower()
QCOMPARE(qMove(copy).toUpper(), upper);
}
+void tst_QByteArray::isUpper()
+{
+ QVERIFY(!QByteArray().isUpper());
+ QVERIFY(!QByteArray("").isUpper());
+ QVERIFY(QByteArray("TEXT").isUpper());
+ QVERIFY(QByteArray("\xD0\xDE").isUpper());
+ QVERIFY(!QByteArray("\xD7").isUpper()); // multiplication sign is not upper
+ QVERIFY(!QByteArray("\xDF").isUpper()); // sz ligature is not upper
+ QVERIFY(!QByteArray("text").isUpper());
+ QVERIFY(!QByteArray("Text").isUpper());
+ QVERIFY(!QByteArray("tExt").isUpper());
+ QVERIFY(!QByteArray("teXt").isUpper());
+ QVERIFY(!QByteArray("texT").isUpper());
+ QVERIFY(!QByteArray("TExt").isUpper());
+ QVERIFY(!QByteArray("teXT").isUpper());
+ QVERIFY(!QByteArray("tEXt").isUpper());
+ QVERIFY(!QByteArray("tExT").isUpper());
+ QVERIFY(!QByteArray("@ABYZ[").isUpper());
+ QVERIFY(!QByteArray("@abyz[").isUpper());
+ QVERIFY(!QByteArray("`ABYZ{").isUpper());
+ QVERIFY(!QByteArray("`abyz{").isUpper());
+}
+
+void tst_QByteArray::isLower()
+{
+ QVERIFY(!QByteArray().isLower());
+ QVERIFY(!QByteArray("").isLower());
+ QVERIFY(QByteArray("text").isLower());
+ QVERIFY(QByteArray("\xE0\xFF").isLower());
+ QVERIFY(!QByteArray("\xF7").isLower()); // division sign is not lower
+ QVERIFY(!QByteArray("Text").isLower());
+ QVERIFY(!QByteArray("tExt").isLower());
+ QVERIFY(!QByteArray("teXt").isLower());
+ QVERIFY(!QByteArray("texT").isLower());
+ QVERIFY(!QByteArray("TExt").isLower());
+ QVERIFY(!QByteArray("teXT").isLower());
+ QVERIFY(!QByteArray("tEXt").isLower());
+ QVERIFY(!QByteArray("tExT").isLower());
+ QVERIFY(!QByteArray("TEXT").isLower());
+ QVERIFY(!QByteArray("@ABYZ[").isLower());
+ QVERIFY(!QByteArray("@abyz[").isLower());
+ QVERIFY(!QByteArray("`ABYZ{").isLower());
+ QVERIFY(!QByteArray("`abyz{").isLower());
+}
+
void tst_QByteArray::macTypes()
{
#ifndef Q_OS_MAC
diff --git a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp
index 4b362a9825..62c29229e1 100644
--- a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp
+++ b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp
@@ -100,7 +100,7 @@ void tst_QCommandLineParser::testInvalidOptions()
QCoreApplication app(empty_argc, empty_argv);
QCommandLineParser parser;
QTest::ignoreMessage(QtWarningMsg, "QCommandLineOption: Option names cannot start with a '-'");
- parser.addOption(QCommandLineOption(QStringLiteral("-v"), QStringLiteral("Displays version information.")));
+ QVERIFY(!parser.addOption(QCommandLineOption(QStringLiteral("-v"), QStringLiteral("Displays version information."))));
}
void tst_QCommandLineParser::testPositionalArguments()
@@ -336,7 +336,7 @@ void tst_QCommandLineParser::testDoubleDash()
QCoreApplication app(empty_argc, empty_argv);
QCommandLineParser parser;
- parser.addOption(QCommandLineOption(QStringList() << "o" << "output", QStringLiteral("Output file"), QStringLiteral("filename")));
+ QVERIFY(parser.addOption(QCommandLineOption(QStringList() << "o" << "output", QStringLiteral("Output file"), QStringLiteral("filename"))));
parser.setSingleDashWordOptionMode(parsingMode);
QVERIFY(parser.parse(QStringList() << "tst_qcommandlineparser" << "--output" << "foo"));
QCOMPARE(parser.value("output"), QString("foo"));
@@ -382,7 +382,7 @@ void tst_QCommandLineParser::testMissingOptionValue()
{
QCoreApplication app(empty_argc, empty_argv);
QCommandLineParser parser;
- parser.addOption(QCommandLineOption(QStringLiteral("option"), QStringLiteral("An option"), "value"));
+ QVERIFY(parser.addOption(QCommandLineOption(QStringLiteral("option"), QStringLiteral("An option"), "value")));
QVERIFY(!parser.parse(QStringList() << "argv0" << "--option")); // the user forgot to pass a value for --option
QCOMPARE(parser.value("option"), QString());
QCOMPARE(parser.errorText(), QString("Missing value after '--option'."));
@@ -400,8 +400,8 @@ void tst_QCommandLineParser::testStdinArgument()
QCoreApplication app(empty_argc, empty_argv);
QCommandLineParser parser;
parser.setSingleDashWordOptionMode(parsingMode);
- parser.addOption(QCommandLineOption(QStringList() << "i" << "input", QStringLiteral("Input file."), QStringLiteral("filename")));
- parser.addOption(QCommandLineOption("b", QStringLiteral("Boolean option.")));
+ QVERIFY(parser.addOption(QCommandLineOption(QStringList() << "i" << "input", QStringLiteral("Input file."), QStringLiteral("filename"))));
+ QVERIFY(parser.addOption(QCommandLineOption("b", QStringLiteral("Boolean option."))));
QVERIFY(parser.parse(QStringList() << "tst_qcommandlineparser" << "--input" << "-"));
QCOMPARE(parser.value("input"), QString("-"));
QCOMPARE(parser.positionalArguments(), QStringList());
@@ -471,14 +471,14 @@ void tst_QCommandLineParser::testSingleDashWordOptionModes()
QCoreApplication app(empty_argc, empty_argv);
QCommandLineParser parser;
parser.setSingleDashWordOptionMode(parsingMode);
- parser.addOption(QCommandLineOption("a", QStringLiteral("a option.")));
- parser.addOption(QCommandLineOption("b", QStringLiteral("b option.")));
- parser.addOption(QCommandLineOption(QStringList() << "c" << "abc", QStringLiteral("c option."), QStringLiteral("value")));
- parser.addOption(QCommandLineOption("nn", QStringLiteral("nn option.")));
+ QVERIFY(parser.addOption(QCommandLineOption("a", QStringLiteral("a option."))));
+ QVERIFY(parser.addOption(QCommandLineOption("b", QStringLiteral("b option."))));
+ QVERIFY(parser.addOption(QCommandLineOption(QStringList() << "c" << "abc", QStringLiteral("c option."), QStringLiteral("value"))));
+ QVERIFY(parser.addOption(QCommandLineOption("nn", QStringLiteral("nn option."))));
QCommandLineOption forceShort(QStringLiteral("I"), QStringLiteral("always short option"),
QStringLiteral("path"), QStringLiteral("default"));
forceShort.setFlags(QCommandLineOption::ShortOptionStyle);
- parser.addOption(forceShort);
+ QVERIFY(parser.addOption(forceShort));
QVERIFY(parser.parse(commandLine));
QCOMPARE(parser.optionNames(), expectedOptionNames);
for (int i = 0; i < expectedOptionValues.count(); ++i)
@@ -493,11 +493,11 @@ void tst_QCommandLineParser::testCpp11StyleInitialization()
QCommandLineParser parser;
// primarily check that this compiles:
- parser.addOptions({
+ QVERIFY(parser.addOptions({
{ "a", "The A option." },
{ { "v", "verbose" }, "The verbose option." },
{ { "i", "infile" }, "The input file.", "value" },
- });
+ }));
// but do a very basic functionality test, too:
QVERIFY(parser.parse({"tst_QCommandLineParser", "-a", "-vvv", "--infile=in.txt"}));
QCOMPARE(parser.optionNames(), (QStringList{"a", "v", "v", "v", "infile"}));
diff --git a/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp b/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp
index 17a0f3edd9..3eef7631c8 100644
--- a/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp
+++ b/tests/auto/corelib/tools/qcryptographichash/tst_qcryptographichash.cpp
@@ -29,6 +29,7 @@
#include <QtCore/QCoreApplication>
#include <QtTest/QtTest>
+#include <QtCore/QMetaEnum>
Q_DECLARE_METATYPE(QCryptographicHash::Algorithm)
@@ -45,6 +46,7 @@ private slots:
void sha3();
void files_data();
void files();
+ void hashLength();
};
void tst_QCryptographicHash::repeated_result_data()
@@ -291,6 +293,15 @@ void tst_QCryptographicHash::files()
}
}
+void tst_QCryptographicHash::hashLength()
+{
+ auto metaEnum = QMetaEnum::fromType<QCryptographicHash::Algorithm>();
+ for (int i = 0, value = metaEnum.value(i); value != -1; value = metaEnum.value(++i)) {
+ auto algorithm = QCryptographicHash::Algorithm(value);
+ QByteArray output = QCryptographicHash::hash(QByteArrayLiteral("test"), algorithm);
+ QCOMPARE(QCryptographicHash::hashLength(algorithm), output.length());
+ }
+}
QTEST_MAIN(tst_QCryptographicHash)
#include "tst_qcryptographichash.moc"
diff --git a/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp b/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp
index 79309f960d..0196dd2d23 100644
--- a/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp
+++ b/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp
@@ -423,7 +423,12 @@ void tst_QEasingCurve::setCustomType()
QCOMPARE(curve.valueForProgress(0.15), 0.1);
QCOMPARE(curve.valueForProgress(0.20), 0.2);
QCOMPARE(curve.valueForProgress(0.25), 0.2);
+ // QTBUG-69947, MinGW 7.3 returns 0.2
+#if defined(Q_CC_MINGW)
+#if !defined(__GNUC__) || __GNUC__ != 7 || __GNUC_MINOR__ < 3
QCOMPARE(curve.valueForProgress(0.30), 0.3);
+#endif
+#endif
QCOMPARE(curve.valueForProgress(0.35), 0.3);
QCOMPARE(curve.valueForProgress(0.999999), 0.9);
diff --git a/tests/auto/corelib/tools/qexplicitlyshareddatapointer/tst_qexplicitlyshareddatapointer.cpp b/tests/auto/corelib/tools/qexplicitlyshareddatapointer/tst_qexplicitlyshareddatapointer.cpp
index f545ead1f1..e89e634841 100644
--- a/tests/auto/corelib/tools/qexplicitlyshareddatapointer/tst_qexplicitlyshareddatapointer.cpp
+++ b/tests/auto/corelib/tools/qexplicitlyshareddatapointer/tst_qexplicitlyshareddatapointer.cpp
@@ -159,6 +159,8 @@ void tst_QExplicitlySharedDataPointer::data() const
{
QExplicitlySharedDataPointer<const MyClass> pointer;
QCOMPARE(pointer.data(), static_cast<const MyClass *>(0));
+ QVERIFY(pointer == nullptr);
+ QVERIFY(nullptr == pointer);
}
/* On const pointer. Must not mutate the pointer. */
@@ -168,6 +170,9 @@ void tst_QExplicitlySharedDataPointer::data() const
/* Check that this cast is possible. */
static_cast<const MyClass *>(pointer.data());
+
+ QVERIFY(! (pointer == nullptr));
+ QVERIFY(! (nullptr == pointer));
}
/* On mutatable pointer. Must not mutate the pointer. */
diff --git a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
index b7cb8a1bdc..261689d401 100644
--- a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
+++ b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
@@ -78,6 +78,7 @@ private slots:
#endif
void ctor();
+ void emptyCtor_data();
void emptyCtor();
void consistentC();
void matchingLocales();
@@ -118,8 +119,10 @@ private slots:
void monthName();
void standaloneMonthName();
- void defaultNumeringSystem();
+ void defaultNumberingSystem_data();
+ void defaultNumberingSystem();
+ void ampm_data();
void ampm();
void currency();
void quoteString();
@@ -127,6 +130,7 @@ private slots:
void weekendDays();
void listPatterns();
+ void measurementSystems_data();
void measurementSystems();
void QTBUG_26035_positivesign();
@@ -135,6 +139,7 @@ private slots:
void formattedDataSize_data();
void formattedDataSize();
+ void bcp47Name_data();
void bcp47Name();
void systemLocale_data();
@@ -145,6 +150,7 @@ private slots:
// QLocale::setDefault() *must* appear *after* all other tests !
void defaulted_ctor(); // This one must be the first of these.
void legacyNames();
+ void unixLocaleName_data();
void unixLocaleName();
void testNames_data();
void testNames();
@@ -152,6 +158,7 @@ private slots:
private:
QString m_decimal, m_thousand, m_sdate, m_ldate, m_time;
QString m_sysapp;
+ QStringList cleanEnv;
bool europeanTimeZone;
};
@@ -184,6 +191,14 @@ void tst_QLocale::initTestCase()
QVERIFY2(fi.exists() && fi.isExecutable(),
qPrintable(QDir::toNativeSeparators(m_sysapp)
+ QStringLiteral(" does not exist or is not executable.")));
+
+ // Get an environment free of any locale-related variables
+ cleanEnv.clear();
+ foreach (QString const& entry, QProcess::systemEnvironment()) {
+ if (entry.startsWith("LANG=") || entry.startsWith("LC_") || entry.startsWith("LANGUAGE="))
+ continue;
+ cleanEnv << entry;
+ }
#endif // QT_CONFIG(process)
}
@@ -214,32 +229,48 @@ void tst_QLocale::ctor()
}
// Exact matches
- TEST_CTOR(Chinese, SimplifiedHanScript, China, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
- TEST_CTOR(Chinese, TraditionalHanScript, Taiwan, QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
- TEST_CTOR(Chinese, TraditionalHanScript, HongKong, QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::HongKong);
+ TEST_CTOR(Chinese, SimplifiedHanScript, China,
+ QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
+ TEST_CTOR(Chinese, TraditionalHanScript, Taiwan,
+ QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
+ TEST_CTOR(Chinese, TraditionalHanScript, HongKong,
+ QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::HongKong);
// Best match for AnyCountry
- TEST_CTOR(Chinese, SimplifiedHanScript, AnyCountry, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
- TEST_CTOR(Chinese, TraditionalHanScript, AnyCountry, QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
+ TEST_CTOR(Chinese, SimplifiedHanScript, AnyCountry,
+ QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
+ TEST_CTOR(Chinese, TraditionalHanScript, AnyCountry,
+ QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
// Best match for AnyScript (and change country to supported one, if necessary)
- TEST_CTOR(Chinese, AnyScript, China, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
- TEST_CTOR(Chinese, AnyScript, Taiwan, QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
- TEST_CTOR(Chinese, AnyScript, HongKong, QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::HongKong);
- TEST_CTOR(Chinese, AnyScript, UnitedStates, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
+ TEST_CTOR(Chinese, AnyScript, China,
+ QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
+ TEST_CTOR(Chinese, AnyScript, Taiwan,
+ QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
+ TEST_CTOR(Chinese, AnyScript, HongKong,
+ QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::HongKong);
+ TEST_CTOR(Chinese, AnyScript, UnitedStates,
+ QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
// Fully-specified not found; find best alternate country
- TEST_CTOR(Chinese, SimplifiedHanScript, Taiwan, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
- TEST_CTOR(Chinese, SimplifiedHanScript, UnitedStates, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
- TEST_CTOR(Chinese, TraditionalHanScript, China, QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
- TEST_CTOR(Chinese, TraditionalHanScript, UnitedStates, QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
+ TEST_CTOR(Chinese, SimplifiedHanScript, Taiwan,
+ QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
+ TEST_CTOR(Chinese, SimplifiedHanScript, UnitedStates,
+ QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
+ TEST_CTOR(Chinese, TraditionalHanScript, China,
+ QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
+ TEST_CTOR(Chinese, TraditionalHanScript, UnitedStates,
+ QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
// Fully-specified not found; find best alternate script
- TEST_CTOR(Chinese, LatinScript, China, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
- TEST_CTOR(Chinese, LatinScript, Taiwan, QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
+ TEST_CTOR(Chinese, LatinScript, China,
+ QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
+ TEST_CTOR(Chinese, LatinScript, Taiwan,
+ QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
// Fully-specified not found; find best alternate country and script
- TEST_CTOR(Chinese, LatinScript, UnitedStates, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
+ TEST_CTOR(Chinese, LatinScript, UnitedStates,
+ QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
#undef TEST_CTOR
}
@@ -278,7 +309,8 @@ void tst_QLocale::defaulted_ctor()
TEST_CTOR(French, France, QLocale::French, QLocale::France)
TEST_CTOR(C, France, QLocale::C, QLocale::AnyCountry)
- TEST_CTOR(Spanish, LatinAmericaAndTheCaribbean, QLocale::Spanish, QLocale::LatinAmericaAndTheCaribbean)
+ TEST_CTOR(Spanish, LatinAmerica, QLocale::Spanish,
+ QLocale::LatinAmerica)
QLocale::setDefault(QLocale(QLocale::English, QLocale::France));
@@ -370,8 +402,9 @@ void tst_QLocale::defaulted_ctor()
QVERIFY2(l.language() == QLocale::exp_lang \
&& l.country() == QLocale::exp_country, \
QString("requested: \"" + QString(req_lc) + "\", got: " \
- + QLocale::languageToString(l.language()) \
- + QLatin1Char('/') + QLocale::countryToString(l.country())).toLatin1().constData()); \
+ + QLocale::languageToString(l.language()) \
+ + QLatin1Char('/') \
+ + QLocale::countryToString(l.country())).toLatin1().constData()); \
QCOMPARE(l, QLocale(QLocale::exp_lang, QLocale::exp_country)); \
QCOMPARE(qHash(l), qHash(QLocale(QLocale::exp_lang, QLocale::exp_country))); \
}
@@ -405,6 +438,8 @@ void tst_QLocale::defaulted_ctor()
TEST_CTOR("en_GB@bla", English, UnitedKingdom)
TEST_CTOR("en-GB", English, UnitedKingdom)
TEST_CTOR("en-GB@bla", English, UnitedKingdom)
+ TEST_CTOR("eo", Esperanto, World)
+ TEST_CTOR("yi", Yiddish, World)
QVERIFY(QLocale::Norwegian == QLocale::NorwegianBokmal);
TEST_CTOR("no", Norwegian, Norway)
@@ -414,8 +449,8 @@ void tst_QLocale::defaulted_ctor()
TEST_CTOR("nb_NO", Norwegian, Norway)
TEST_CTOR("nn_NO", NorwegianNynorsk, Norway)
TEST_CTOR("es_ES", Spanish, Spain)
- TEST_CTOR("es_419", Spanish, LatinAmericaAndTheCaribbean)
- TEST_CTOR("es-419", Spanish, LatinAmericaAndTheCaribbean)
+ TEST_CTOR("es_419", Spanish, LatinAmerica)
+ TEST_CTOR("es-419", Spanish, LatinAmerica)
TEST_CTOR("fr_MA", French, Morocco)
// test default countries for languages
@@ -464,7 +499,8 @@ static inline bool runSysApp(const QString &binary,
process.start(binary);
process.closeWriteChannel();
if (!process.waitForStarted()) {
- *errorMessage = QString::fromLatin1("Cannot start '%1': %2").arg(binary, process.errorString());
+ *errorMessage = QLatin1String("Cannot start '") + binary
+ + QLatin1String("': ") + process.errorString();
return false;
}
if (!process.waitForFinished()) {
@@ -488,94 +524,121 @@ static inline bool runSysAppTest(const QString &binary,
return false;
if (output.isEmpty()) {
- *errorMessage = QString::fromLatin1("Empty output received for requested '%1' (expected '%2')").
- arg(requestedLocale, expectedOutput);
+ *errorMessage = QLatin1String("Empty output received for requested '") + requestedLocale
+ + QLatin1String("' (expected '") + expectedOutput + QLatin1String("')");
return false;
}
if (output != expectedOutput) {
- *errorMessage = QString::fromLatin1("Output mismatch for requested '%1': Expected '%2', got '%3'").
- arg(requestedLocale, expectedOutput, output);
+ *errorMessage = QLatin1String("Output mismatch for requested '") + requestedLocale
+ + QLatin1String("': Expected '") + expectedOutput + QLatin1String("', got '")
+ + output + QLatin1String("'");
return false;
}
return true;
}
#endif
-void tst_QLocale::emptyCtor()
+void tst_QLocale::emptyCtor_data()
{
#if !QT_CONFIG(process)
QSKIP("No qprocess support", SkipAll);
-#else
+#endif
#ifdef Q_OS_ANDROID
QSKIP("This test crashes on Android");
#endif
-#define TEST_CTOR(req_lc, exp_str) \
- { \
- /* Test constructor without arguments. Needs separate process */ \
- /* because of caching of the system locale. */ \
- QString errorMessage; \
- QVERIFY2(runSysAppTest(m_sysapp, env, QLatin1String(req_lc), QLatin1String(exp_str), &errorMessage), \
- qPrintable(errorMessage)); \
- }
- // Get an environment free of any locale-related variables
- QStringList env;
- foreach (QString const& entry, QProcess::systemEnvironment()) {
- if (entry.startsWith("LANG=") || entry.startsWith("LC_") || entry.startsWith("LANGUAGE="))
- continue;
- env << entry;
- }
+ QTest::addColumn<QString>("expected");
+
+#define ADD_CTOR_TEST(give, expect) QTest::newRow(give) << QStringLiteral(expect);
+
+ // For format and meaning, see:
+ // http://pubs.opengroup.org/onlinepubs/7908799/xbd/envvar.html
+ // Note that the accepted values for fields are implementation-dependent;
+ // the template is language[_territory][.codeset][@modifier]
+
+ // Vanilla:
+ ADD_CTOR_TEST("C", "C");
+
+ // Standard forms:
+ ADD_CTOR_TEST("en", "en_US");
+ ADD_CTOR_TEST("en_GB", "en_GB");
+ ADD_CTOR_TEST("de", "de_DE");
+ // Norsk has some quirks:
+ ADD_CTOR_TEST("no", "nb_NO");
+ ADD_CTOR_TEST("nb", "nb_NO");
+ ADD_CTOR_TEST("nn", "nn_NO");
+ ADD_CTOR_TEST("no_NO", "nb_NO");
+ ADD_CTOR_TEST("nb_NO", "nb_NO");
+ ADD_CTOR_TEST("nn_NO", "nn_NO");
+
+ // Not too fussy about case:
+ ADD_CTOR_TEST("DE", "de_DE");
+ ADD_CTOR_TEST("EN", "en_US");
+
+ // Invalid fields
+ ADD_CTOR_TEST("bla", "C");
+ ADD_CTOR_TEST("zz", "C");
+ ADD_CTOR_TEST("zz_zz", "C");
+ ADD_CTOR_TEST("zz...", "C");
+ ADD_CTOR_TEST("en.bla", "en_US");
+#if !(defined(Q_OS_DARWIN) && QT_HAS_FEATURE(address_sanitizer))
+ // See QTBUG-69875
+ ADD_CTOR_TEST("en@bla", "en_US");
+#endif
+ ADD_CTOR_TEST("en_blaaa", "en_US");
+ ADD_CTOR_TEST("en_zz", "en_US");
+ ADD_CTOR_TEST("en_GB.bla", "en_GB");
+ ADD_CTOR_TEST("en_GB@.bla", "en_GB");
+ ADD_CTOR_TEST("en_GB@bla", "en_GB");
+
+ // Empty optional fields, but with punctuators supplied
+ ADD_CTOR_TEST("en.", "en_US");
+#if !(defined(Q_OS_DARWIN) && QT_HAS_FEATURE(address_sanitizer))
+ // See QTBUG-69875
+ ADD_CTOR_TEST("en@", "en_US");
+#endif
+ ADD_CTOR_TEST("en.@", "en_US");
+ ADD_CTOR_TEST("en_", "en_US");
+ ADD_CTOR_TEST("en_.", "en_US");
+ ADD_CTOR_TEST("en_.@", "en_US");
+#undef ADD_CTOR_TEST
+#if QT_CONFIG(process) // for runSysApp
// Get default locale.
QString defaultLoc;
QString errorMessage;
- QVERIFY2(runSysApp(m_sysapp, env, &defaultLoc, &errorMessage),
- qPrintable(errorMessage));
-
- TEST_CTOR("C", "C")
- TEST_CTOR("bla", "C")
- TEST_CTOR("zz", "C")
- TEST_CTOR("zz_zz", "C")
- TEST_CTOR("zz...", "C")
- TEST_CTOR("en", "en_US")
- TEST_CTOR("en", "en_US")
- TEST_CTOR("en.", "en_US")
- TEST_CTOR("en@", "en_US")
- TEST_CTOR("en.@", "en_US")
- TEST_CTOR("en_", "en_US")
- TEST_CTOR("en_.", "en_US")
- TEST_CTOR("en_.@", "en_US")
- TEST_CTOR("en.bla", "en_US")
- TEST_CTOR("en@bla", "en_US")
- TEST_CTOR("en_blaaa", "en_US")
- TEST_CTOR("en_zz", "en_US")
- TEST_CTOR("en_GB", "en_GB")
- TEST_CTOR("en_GB.bla", "en_GB")
- TEST_CTOR("en_GB@.bla", "en_GB")
- TEST_CTOR("en_GB@bla", "en_GB")
- TEST_CTOR("de", "de_DE")
-
- QVERIFY(QLocale::Norwegian == QLocale::NorwegianBokmal);
- TEST_CTOR("no", "nb_NO")
- TEST_CTOR("nb", "nb_NO")
- TEST_CTOR("nn", "nn_NO")
- TEST_CTOR("no_NO", "nb_NO")
- TEST_CTOR("nb_NO", "nb_NO")
- TEST_CTOR("nn_NO", "nn_NO")
+ if (runSysApp(m_sysapp, cleanEnv, &defaultLoc, &errorMessage)) {
+#define ADD_CTOR_TEST(give) QTest::newRow(give) << defaultLoc;
+ ADD_CTOR_TEST("en/");
+ ADD_CTOR_TEST("asdfghj");
+ ADD_CTOR_TEST("123456");
+#undef ADD_CTOR_TEST
+ } else {
+ qDebug() << "Skipping tests based on default locale" << qPrintable(errorMessage);
+ }
+#endif // process
+}
- TEST_CTOR("DE", "de_DE");
- TEST_CTOR("EN", "en_US");
+void tst_QLocale::emptyCtor()
+{
+#if QT_CONFIG(process) // for runSysAppTest
+ QLatin1String request(QTest::currentDataTag());
+ QFETCH(QString, expected);
- TEST_CTOR("en/", defaultLoc.toLatin1())
- TEST_CTOR("asdfghj", defaultLoc.toLatin1());
- TEST_CTOR("123456", defaultLoc.toLatin1());
+ // Test constructor without arguments (see syslocaleapp/syslocaleapp.cpp)
+ // Needs separate process because of caching of the system locale.
+ QString errorMessage;
+ QVERIFY2(runSysAppTest(m_sysapp, cleanEnv, request, expected, &errorMessage),
+ qPrintable(errorMessage));
-#undef TEST_CTOR
-#endif
+#else
+ // This won't be called, as _data() skipped out early.
+#endif // process
}
void tst_QLocale::legacyNames()
{
+ QVERIFY(QLocale::Norwegian == QLocale::NorwegianBokmal);
QLocale::setDefault(QLocale(QLocale::C));
#define TEST_CTOR(req_lang, req_country, exp_lang, exp_country) \
@@ -598,8 +661,9 @@ void tst_QLocale::legacyNames()
QVERIFY2(l.language() == QLocale::exp_lang \
&& l.country() == QLocale::exp_country, \
QString("requested: \"" + QString(req_lc) + "\", got: " \
- + QLocale::languageToString(l.language()) \
- + QLatin1Char('/') + QLocale::countryToString(l.country())).toLatin1().constData()); \
+ + QLocale::languageToString(l.language()) \
+ + QLatin1Char('/') \
+ + QLocale::countryToString(l.country())).toLatin1().constData()); \
}
TEST_CTOR("mo_MD", Romanian, Moldova)
@@ -649,22 +713,32 @@ void tst_QLocale::matchingLocales()
QVERIFY(locales.contains(ru_RU));
}
+void tst_QLocale::unixLocaleName_data()
+{
+ QTest::addColumn<QLocale::Language>("lang");
+ QTest::addColumn<QLocale::Country>("land");
+ QTest::addColumn<QString>("expect");
+
+#define ADDROW(nom, lang, land, name) \
+ QTest::newRow(nom) << QLocale::lang << QLocale::land << QStringLiteral(name)
+
+ ADDROW("C_any", C, AnyCountry, "C");
+ ADDROW("en_any", English, AnyCountry, "en_US");
+ ADDROW("en_GB", English, UnitedKingdom, "en_GB");
+ ADDROW("ay_GB", Aymara, UnitedKingdom, "C");
+#undef ADDROW
+}
+
void tst_QLocale::unixLocaleName()
{
-#define TEST_NAME(req_lang, req_country, exp_name) \
- { \
- QLocale l(QLocale::req_lang, QLocale::req_country); \
- QCOMPARE(l.name(), QString(exp_name)); \
- }
+ QFETCH(QLocale::Language, lang);
+ QFETCH(QLocale::Country, land);
+ QFETCH(QString, expect);
QLocale::setDefault(QLocale(QLocale::C));
- TEST_NAME(C, AnyCountry, "C")
- TEST_NAME(English, AnyCountry, "en_US")
- TEST_NAME(English, UnitedKingdom, "en_GB")
- TEST_NAME(Aymara, UnitedKingdom, "C")
-
-#undef TEST_NAME
+ QLocale locale(lang, land);
+ QCOMPARE(locale.name(), expect);
}
void tst_QLocale::stringToDouble_data()
@@ -1282,7 +1356,8 @@ void tst_QLocale::formatDate_data()
QTest::newRow("26") << QDate(1974, 12, 1) << "\"yy\"" << "\"74\"";
QTest::newRow("27") << QDate(1974, 12, 1) << "'\"yy\"'" << "\"yy\"";
QTest::newRow("28") << QDate() << "'\"yy\"'" << "";
- QTest::newRow("29") << QDate(1974, 12, 1) << "hh:mm:ss.zzz ap d'd'dd/M/yy" << "hh:mm:ss.zzz ap 1d01/12/74";
+ QTest::newRow("29")
+ << QDate(1974, 12, 1) << "hh:mm:ss.zzz ap d'd'dd/M/yy" << "hh:mm:ss.zzz ap 1d01/12/74";
QTest::newRow("dd MMMM yyyy") << QDate(1, 1, 1) << "dd MMMM yyyy" << "01 January 0001";
}
@@ -1298,7 +1373,6 @@ void tst_QLocale::formatDate()
QCOMPARE(l.toString(date, QStringView(format)), result);
}
-
void tst_QLocale::formatTime_data()
{
QTest::addColumn<QTime>("time");
@@ -1577,7 +1651,8 @@ void tst_QLocale::formatTimeZone()
QDateTime::currentDateTime().timeZoneAbbreviation());
// Time on its own will always be current local time zone
- QCOMPARE(enUS.toString(QTime(1, 2, 3), "t"), QDateTime::currentDateTime().timeZoneAbbreviation());
+ QCOMPARE(enUS.toString(QTime(1, 2, 3), "t"),
+ QDateTime::currentDateTime().timeZoneAbbreviation());
}
void tst_QLocale::toDateTime_data()
@@ -1614,7 +1689,8 @@ void tst_QLocale::toDateTime_data()
QTest::newRow("bad-hour-C") << "C" << QDateTime() << "d-MMM-yy hh:m" << "4-Jun-11 1:2";
QTest::newRow("bad-min-C") << "C" << QDateTime() << "d-MMM-yy h:mm" << "4-Jun-11 1:2";
QTest::newRow("bad-sec-C") << "C" << QDateTime() << "d-MMM-yy h:m:ss" << "4-Jun-11 1:2:3";
- QTest::newRow("bad-milli-C") << "C" << QDateTime() << "d-MMM-yy h:m:s.zzz" << "4-Jun-11 1:2:3.4";
+ QTest::newRow("bad-milli-C")
+ << "C" << QDateTime() << "d-MMM-yy h:m:s.zzz" << "4-Jun-11 1:2:3.4";
QTest::newRow("ok-C") << "C" << QDateTime(QDate(1911, 6, 4), QTime(1, 2, 3, 400))
<< "d-MMM-yy h:m:s.z" << "4-Jun-11 1:2:3.4";
@@ -1637,11 +1713,13 @@ void tst_QLocale::toDateTime_data()
QTest::newRow("12no_NO") << "no_NO" << QDateTime(QDate(1974, 12, 1), QTime(15, 0, 0))
<< "d'd'dd/M/yyh" << "1d01/12/7415";
- QTest::newRow("RFC-1123") << "C" << QDateTime(QDate(2007, 11, 1), QTime(18, 8, 30))
- << "ddd, dd MMM yyyy hh:mm:ss 'GMT'" << "Thu, 01 Nov 2007 18:08:30 GMT";
+ QTest::newRow("RFC-1123")
+ << "C" << QDateTime(QDate(2007, 11, 1), QTime(18, 8, 30))
+ << "ddd, dd MMM yyyy hh:mm:ss 'GMT'" << "Thu, 01 Nov 2007 18:08:30 GMT";
- QTest::newRow("longFormat") << "en_US" << QDateTime(QDate(2009, 1, 5), QTime(11, 48, 32))
- << "dddd, MMMM d, yyyy h:mm:ss AP " << "Monday, January 5, 2009 11:48:32 AM ";
+ QTest::newRow("longFormat")
+ << "en_US" << QDateTime(QDate(2009, 1, 5), QTime(11, 48, 32))
+ << "dddd, MMMM d, yyyy h:mm:ss AP " << "Monday, January 5, 2009 11:48:32 AM ";
}
void tst_QLocale::toDateTime()
@@ -1716,36 +1794,40 @@ void tst_QLocale::macDefaultLocale()
// To run this test make sure "Curreny" is US Dollar in System Preferences->Language & Region->Advanced.
if (locale.currencySymbol() == QString("$")) {
- QCOMPARE(locale.toCurrencyString(qulonglong(1234)), systemLocaleFormatNumber(QString("$1,234.00")));
- QCOMPARE(locale.toCurrencyString(double(1234.56)), systemLocaleFormatNumber(QString("$1,234.56")));
+ QCOMPARE(locale.toCurrencyString(qulonglong(1234)),
+ systemLocaleFormatNumber(QString("$1,234.00")));
+ QCOMPARE(locale.toCurrencyString(double(1234.56)),
+ systemLocaleFormatNumber(QString("$1,234.56")));
}
// Depending on the configured time zone, the time string might not
// contain a GMT specifier. (Sometimes it just names the zone, like "CEST")
- if (timeString.contains(QString("GMT"))) {
- QString expectedGMTSpecifierBase("GMT");
- if (diff >= 0)
- expectedGMTSpecifierBase.append(QLatin1Char('+'));
- else
- expectedGMTSpecifierBase.append(QLatin1Char('-'));
-
- QString expectedGMTSpecifier = expectedGMTSpecifierBase + QString("%1").arg(qAbs(diff));
- QString expectedGMTSpecifierZeroExtended = expectedGMTSpecifierBase + QString("0%1").arg(qAbs(diff));
-
- QVERIFY2(timeString.contains(expectedGMTSpecifier)
- || timeString.contains(expectedGMTSpecifierZeroExtended),
- qPrintable(QString("timeString `%1', expectedGMTSpecifier `%2' or `%3'")
- .arg(timeString)
- .arg(expectedGMTSpecifier)
- .arg(expectedGMTSpecifierZeroExtended)
- ));
+ QLatin1String gmt("GMT");
+ if (timeString.contains(gmt) && diff) {
+ QLatin1Char sign(diff < 0 ? '-' : '+');
+ QString number(QString::number(qAbs(diff)));
+ const QString expect = gmt + sign + number;
+
+ if (diff < 10) {
+ const QString zeroed = gmt + sign + QLatin1Char('0') + number;
+
+ QVERIFY2(timeString.contains(expect) || timeString.contains(zeroed),
+ qPrintable(QString("timeString `%1', expected GMT specifier `%2' or `%3'")
+ .arg(timeString).arg(expect).arg(zeroed)));
+ } else {
+ QVERIFY2(timeString.contains(expect),
+ qPrintable(QString("timeString `%1', expected GMT specifier `%2'")
+ .arg(timeString).arg(expect)));
+ }
}
QCOMPARE(locale.dayName(1), QString("Monday"));
QCOMPARE(locale.dayName(7), QString("Sunday"));
QCOMPARE(locale.monthName(1), QString("January"));
QCOMPARE(locale.monthName(12), QString("December"));
- QCOMPARE(locale.quoteString("string"), QString::fromUtf8("\xe2\x80\x9c" "string" "\xe2\x80\x9d"));
- QCOMPARE(locale.quoteString("string", QLocale::AlternateQuotation), QString::fromUtf8("\xe2\x80\x98" "string" "\xe2\x80\x99"));
+ QCOMPARE(locale.quoteString("string"),
+ QString::fromUtf8("\xe2\x80\x9c" "string" "\xe2\x80\x9d"));
+ QCOMPARE(locale.quoteString("string", QLocale::AlternateQuotation),
+ QString::fromUtf8("\xe2\x80\x98" "string" "\xe2\x80\x99"));
QList<Qt::DayOfWeek> days;
days << Qt::Monday << Qt::Tuesday << Qt::Wednesday << Qt::Thursday << Qt::Friday;
@@ -1787,12 +1869,6 @@ static void setWinLocaleInfo(LCTYPE type, const QString &value)
# define LOCALE_SSHORTTIME 0x00000079
#endif
-static inline LCTYPE shortTimeType()
-{
- return (QSysInfo::windowsVersion() & QSysInfo::WV_NT_based) && QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7 ?
- LOCALE_SSHORTTIME : LOCALE_STIMEFORMAT;
-}
-
class RestoreLocaleHelper {
public:
RestoreLocaleHelper() {
@@ -1800,7 +1876,7 @@ public:
m_thousand = getWinLocaleInfo(LOCALE_STHOUSAND);
m_sdate = getWinLocaleInfo(LOCALE_SSHORTDATE);
m_ldate = getWinLocaleInfo(LOCALE_SLONGDATE);
- m_time = getWinLocaleInfo(shortTimeType());
+ m_time = getWinLocaleInfo(LOCALE_SSHORTTIME);
}
~RestoreLocaleHelper() {
@@ -1809,7 +1885,7 @@ public:
setWinLocaleInfo(LOCALE_STHOUSAND, m_thousand);
setWinLocaleInfo(LOCALE_SSHORTDATE, m_sdate);
setWinLocaleInfo(LOCALE_SLONGDATE, m_ldate);
- setWinLocaleInfo(shortTimeType(), m_time);
+ setWinLocaleInfo(LOCALE_SSHORTTIME, m_time);
// make sure QLocale::system() gets updated
QLocalePrivate::updateSystemPrivate();
@@ -1819,14 +1895,9 @@ public:
};
-#endif // Q_OS_WIN
-
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
-
void tst_QLocale::windowsDefaultLocale()
{
RestoreLocaleHelper systemLocale;
- const bool win7OrLater = (QSysInfo::windowsVersion() & QSysInfo::WV_NT_based) && QSysInfo::windowsVersion();
// set weird system defaults and make sure we're using them
setWinLocaleInfo(LOCALE_SDECIMAL, QLatin1String("@"));
setWinLocaleInfo(LOCALE_STHOUSAND, QLatin1String("?"));
@@ -1835,7 +1906,7 @@ void tst_QLocale::windowsDefaultLocale()
const QString longDateFormat = QStringLiteral("d@M@yyyy");
setWinLocaleInfo(LOCALE_SLONGDATE, longDateFormat);
const QString shortTimeFormat = QStringLiteral("h^m^s");
- setWinLocaleInfo(shortTimeType(), shortTimeFormat);
+ setWinLocaleInfo(LOCALE_SSHORTTIME, shortTimeFormat);
// make sure QLocale::system() gets updated
QLocalePrivate::updateSystemPrivate();
@@ -1847,21 +1918,24 @@ void tst_QLocale::windowsDefaultLocale()
QCOMPARE(locale.dateFormat(QLocale::ShortFormat), shortDateFormat);
QCOMPARE(locale.dateFormat(QLocale::LongFormat), longDateFormat);
QCOMPARE(locale.timeFormat(QLocale::ShortFormat), shortTimeFormat);
- QCOMPARE(locale.dateTimeFormat(QLocale::ShortFormat), shortDateFormat + QLatin1Char(' ') + shortTimeFormat);
- const QString expectedLongDateTimeFormat = longDateFormat + QLatin1Char(' ')
- + (win7OrLater ? QStringLiteral("h:mm:ss AP") : shortTimeFormat);
+ QCOMPARE(locale.dateTimeFormat(QLocale::ShortFormat),
+ shortDateFormat + QLatin1Char(' ') + shortTimeFormat);
+ const QString expectedLongDateTimeFormat
+ = longDateFormat + QLatin1Char(' ') + QStringLiteral("h:mm:ss AP");
QCOMPARE(locale.dateTimeFormat(QLocale::LongFormat), expectedLongDateTimeFormat);
// make sure we are using the system to parse them
QCOMPARE(locale.toString(1234.56), QString("1?234@56"));
QCOMPARE(locale.toString(QDate(1974, 12, 1), QLocale::ShortFormat), QString("1*12*1974"));
- QCOMPARE(locale.toString(QDate(1974, 12, 1), QLocale::NarrowFormat), locale.toString(QDate(1974, 12, 1), QLocale::ShortFormat));
+ QCOMPARE(locale.toString(QDate(1974, 12, 1), QLocale::NarrowFormat),
+ locale.toString(QDate(1974, 12, 1), QLocale::ShortFormat));
QCOMPARE(locale.toString(QDate(1974, 12, 1), QLocale::LongFormat), QString("1@12@1974"));
const QString expectedFormattedShortTimeSeconds = QStringLiteral("1^2^3");
- const QString expectedFormattedShortTime = win7OrLater ? QStringLiteral("1^2") : expectedFormattedShortTimeSeconds;
+ const QString expectedFormattedShortTime = QStringLiteral("1^2");
QCOMPARE(locale.toString(QTime(1,2,3), QLocale::ShortFormat), expectedFormattedShortTime);
- QCOMPARE(locale.toString(QTime(1,2,3), QLocale::NarrowFormat), locale.toString(QTime(1,2,3), QLocale::ShortFormat));
- const QString expectedFormattedLongTime = win7OrLater ? QStringLiteral("1:02:03 AM") : expectedFormattedShortTimeSeconds;
+ QCOMPARE(locale.toString(QTime(1,2,3), QLocale::NarrowFormat),
+ locale.toString(QTime(1,2,3), QLocale::ShortFormat));
+ const QString expectedFormattedLongTime = QStringLiteral("1:02:03 AM");
QCOMPARE(locale.toString(QTime(1,2,3), QLocale::LongFormat), expectedFormattedLongTime);
QCOMPARE(locale.toString(QDateTime(QDate(1974, 12, 1), QTime(1,2,3)), QLocale::ShortFormat),
QStringLiteral("1*12*1974 ") + expectedFormattedShortTime);
@@ -1871,7 +1945,7 @@ void tst_QLocale::windowsDefaultLocale()
QStringLiteral("1@12@1974 ") + expectedFormattedLongTime);
QCOMPARE(locale.toString(QTime(1,2,3), QLocale::LongFormat), expectedFormattedLongTime);
}
-#endif // #ifdef Q_OS_WIN
+#endif // Q_OS_WIN but !Q_OS_WINRT
void tst_QLocale::numberOptions()
{
@@ -2056,17 +2130,23 @@ void tst_QLocale::dayName_data()
QTest::addColumn<int>("day");
QTest::addColumn<QLocale::FormatType>("format");
- QTest::newRow("no_NO") << QString("no_NO") << QString("tirsdag") << 2 << QLocale::LongFormat;
- QTest::newRow("nb_NO") << QString("nb_NO") << QString("tirsdag") << 2 << QLocale::LongFormat;
- QTest::newRow("nn_NO") << QString("nn_NO") << QString("tysdag") << 2 << QLocale::LongFormat;
+ QTest::newRow("no_NO") << QString("no_NO") << QString("tirsdag") << 2 << QLocale::LongFormat;
+ QTest::newRow("nb_NO") << QString("nb_NO") << QString("tirsdag") << 2 << QLocale::LongFormat;
+ QTest::newRow("nn_NO") << QString("nn_NO") << QString("tysdag") << 2 << QLocale::LongFormat;
- QTest::newRow("C long") << QString("C") << QString("Sunday") << 7 << QLocale::LongFormat;
- QTest::newRow("C short") << QString("C") << QString("Sun") << 7 << QLocale::ShortFormat;
- QTest::newRow("C narrow") << QString("C") << QString("7") << 7 << QLocale::NarrowFormat;
+ QTest::newRow("C long") << QString("C") << QString("Sunday") << 7 << QLocale::LongFormat;
+ QTest::newRow("C short") << QString("C") << QString("Sun") << 7 << QLocale::ShortFormat;
+ QTest::newRow("C narrow") << QString("C") << QString("7") << 7 << QLocale::NarrowFormat;
- QTest::newRow("ru_RU long") << QString("ru_RU") << QString::fromUtf8("\320\262\320\276\321\201\320\272\321\200\320\265\321\201\320\265\320\275\321\214\320\265") << 7 << QLocale::LongFormat;
- QTest::newRow("ru_RU short") << QString("ru_RU") << QString::fromUtf8("\320\262\321\201") << 7 << QLocale::ShortFormat;
- QTest::newRow("ru_RU narrow") << QString("ru_RU") << QString::fromUtf8("\320\262\321\201") << 7 << QLocale::NarrowFormat;
+ QTest::newRow("ru_RU long")
+ << QString("ru_RU")
+ << QString::fromUtf8("\320\262\320\276\321\201\320\272\321\200\320"
+ "\265\321\201\320\265\320\275\321\214\320\265")
+ << 7 << QLocale::LongFormat;
+ QTest::newRow("ru_RU short")
+ << QString("ru_RU") << QString::fromUtf8("\320\262\321\201") << 7 << QLocale::ShortFormat;
+ QTest::newRow("ru_RU narrow")
+ << QString("ru_RU") << QString::fromUtf8("\320\262\321\201") << 7 << QLocale::NarrowFormat;
}
void tst_QLocale::dayName()
@@ -2096,24 +2176,30 @@ void tst_QLocale::standaloneDayName_data()
QTest::addColumn<int>("day");
QTest::addColumn<QLocale::FormatType>("format");
- QTest::newRow("no_NO") << QString("no_NO") << QString("tirsdag") << 2 << QLocale::LongFormat;
- QTest::newRow("nb_NO") << QString("nb_NO") << QString("tirsdag") << 2 << QLocale::LongFormat;
- QTest::newRow("nn_NO") << QString("nn_NO") << QString("tysdag") << 2 << QLocale::LongFormat;
+ QTest::newRow("no_NO") << QString("no_NO") << QString("tirsdag") << 2 << QLocale::LongFormat;
+ QTest::newRow("nb_NO") << QString("nb_NO") << QString("tirsdag") << 2 << QLocale::LongFormat;
+ QTest::newRow("nn_NO") << QString("nn_NO") << QString("tysdag") << 2 << QLocale::LongFormat;
- QTest::newRow("C invalid: 0 long") << QString("C") << QString() << 0 << QLocale::LongFormat;
- QTest::newRow("C invalid: 0 short") << QString("C") << QString() << 0 << QLocale::ShortFormat;
- QTest::newRow("C invalid: 0 narrow") << QString("C") << QString() << 0 << QLocale::NarrowFormat;
- QTest::newRow("C invalid: 8 long") << QString("C") << QString() << 8 << QLocale::LongFormat;
- QTest::newRow("C invalid: 8 short") << QString("C") << QString() << 8 << QLocale::ShortFormat;
- QTest::newRow("C invalid: 8 narrow") << QString("C") << QString() << 8 << QLocale::NarrowFormat;
+ QTest::newRow("C invalid: 0 long") << QString("C") << QString() << 0 << QLocale::LongFormat;
+ QTest::newRow("C invalid: 0 short") << QString("C") << QString() << 0 << QLocale::ShortFormat;
+ QTest::newRow("C invalid: 0 narrow") << QString("C") << QString() << 0 << QLocale::NarrowFormat;
+ QTest::newRow("C invalid: 8 long") << QString("C") << QString() << 8 << QLocale::LongFormat;
+ QTest::newRow("C invalid: 8 short") << QString("C") << QString() << 8 << QLocale::ShortFormat;
+ QTest::newRow("C invalid: 8 narrow") << QString("C") << QString() << 8 << QLocale::NarrowFormat;
- QTest::newRow("C long") << QString("C") << QString("Sunday") << 7 << QLocale::LongFormat;
- QTest::newRow("C short") << QString("C") << QString("Sun") << 7 << QLocale::ShortFormat;
- QTest::newRow("C narrow") << QString("C") << QString("S") << 7 << QLocale::NarrowFormat;
+ QTest::newRow("C long") << QString("C") << QString("Sunday") << 7 << QLocale::LongFormat;
+ QTest::newRow("C short") << QString("C") << QString("Sun") << 7 << QLocale::ShortFormat;
+ QTest::newRow("C narrow") << QString("C") << QString("S") << 7 << QLocale::NarrowFormat;
- QTest::newRow("ru_RU long") << QString("ru_RU") << QString::fromUtf8("\320\262\320\276\321\201\320\272\321\200\320\265\321\201\320\265\320\275\321\214\320\265") << 7 << QLocale::LongFormat;
- QTest::newRow("ru_RU short") << QString("ru_RU") << QString::fromUtf8("\320\262\321\201") << 7 << QLocale::ShortFormat;
- QTest::newRow("ru_RU narrow") << QString("ru_RU") << QString::fromUtf8("\320\222") << 7 << QLocale::NarrowFormat;
+ QTest::newRow("ru_RU long")
+ << QString("ru_RU")
+ << QString::fromUtf8("\320\262\320\276\321\201\320\272\321\200\320"
+ "\265\321\201\320\265\320\275\321\214\320\265")
+ << 7 << QLocale::LongFormat;
+ QTest::newRow("ru_RU short")
+ << QString("ru_RU") << QString::fromUtf8("\320\262\321\201") << 7 << QLocale::ShortFormat;
+ QTest::newRow("ru_RU narrow")
+ << QString("ru_RU") << QString::fromUtf8("\320\222") << 7 << QLocale::NarrowFormat;
}
void tst_QLocale::standaloneDayName()
@@ -2129,9 +2215,7 @@ void tst_QLocale::standaloneDayName()
void tst_QLocale::underflowOverflow()
{
- QString
-a(QLatin1String("0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e10"));
-
+ QString a(QLatin1String("0.") + QString(546, QLatin1Char('0')) + QLatin1String("1e10"));
bool ok = false;
double d = a.toDouble(&ok);
QVERIFY(!ok);
@@ -2160,75 +2244,56 @@ a(QLatin1String("0.0000000000000000000000000000000000000000000000000000000000000
QVERIFY(!ok);
}
-void tst_QLocale::defaultNumeringSystem()
+void tst_QLocale::defaultNumberingSystem_data()
{
- QLocale sk("sk_SK");
- QCOMPARE(sk.toString(123), QLatin1String("123"));
+ QTest::addColumn<QString>("expect");
- QLocale ta("ta_IN");
- QCOMPARE(ta.toString(123), QLatin1String("123"));
-
- QLocale te("te_IN");
- QCOMPARE(te.toString(123), QLatin1String("123"));
-
- QLocale hi("hi_IN");
- QCOMPARE(hi.toString(123), QLatin1String("123"));
-
- QLocale gu("gu_IN");
- QCOMPARE(gu.toString(123), QLatin1String("123"));
-
- QLocale kn("kn_IN");
- QCOMPARE(kn.toString(123), QLatin1String("123"));
-
- QLocale pa("pa_IN");
- QCOMPARE(pa.toString(123), QLatin1String("123"));
-
- QLocale ne("ne_IN");
- QCOMPARE(ne.toString(123), QString::fromUtf8("१२३"));
+ QTest::newRow("sk_SK") << QStringLiteral("123");
+ QTest::newRow("ta_IN") << QStringLiteral("123");
+ QTest::newRow("te_IN") << QStringLiteral("123");
+ QTest::newRow("hi_IN") << QStringLiteral("123");
+ QTest::newRow("gu_IN") << QStringLiteral("123");
+ QTest::newRow("kn_IN") << QStringLiteral("123");
+ QTest::newRow("pa_IN") << QStringLiteral("123");
+ QTest::newRow("ne_IN") << QString::fromUtf8("१२३");
+ QTest::newRow("mr_IN") << QString::fromUtf8("१२३");
+ QTest::newRow("ml_IN") << QStringLiteral("123");
+ QTest::newRow("kok_IN") << QStringLiteral("123");
+}
- QLocale mr("mr_IN");
- QCOMPARE(mr.toString(123), QString::fromUtf8("१२३"));
+void tst_QLocale::defaultNumberingSystem()
+{
+ QFETCH(QString, expect);
+ QLatin1String name(QTest::currentDataTag());
+ QLocale locale(name);
+ QCOMPARE(locale.toString(123), expect);
+}
- QLocale ml("ml_IN");
- QCOMPARE(ml.toString(123), QLatin1String("123"));
+void tst_QLocale::ampm_data()
+{
+ QTest::addColumn<QString>("morn");
+ QTest::addColumn<QString>("even");
- QLocale kok("kok_IN");
- QCOMPARE(kok.toString(123), QLatin1String("123"));
+ QTest::newRow("C") << QStringLiteral("AM") << QStringLiteral("PM");
+ QTest::newRow("de_DE") << QStringLiteral("AM") << QStringLiteral("PM");
+ QTest::newRow("sv_SE") << QStringLiteral("fm") << QStringLiteral("em");
+ QTest::newRow("nl_NL") << QStringLiteral("a.m.") << QStringLiteral("p.m.");
+ QTest::newRow("uk_UA") << QString::fromUtf8("\320\264\320\277")
+ << QString::fromUtf8("\320\277\320\277");
+ QTest::newRow("tr_TR") << QString::fromUtf8("\303\226\303\226")
+ << QString::fromUtf8("\303\226\123");
+ QTest::newRow("id_ID") << QStringLiteral("AM") << QStringLiteral("PM");
+ QTest::newRow("ta_LK") << QString::fromUtf8("à®®à¯à®±à¯à®ªà®•à®²à¯") << QString::fromUtf8("பிறà¯à®ªà®•à®²à¯");
}
void tst_QLocale::ampm()
{
- QLocale c(QLocale::C);
- QCOMPARE(c.amText(), QLatin1String("AM"));
- QCOMPARE(c.pmText(), QLatin1String("PM"));
-
- QLocale de("de_DE");
- QCOMPARE(de.amText(), QLatin1String("vorm."));
- QCOMPARE(de.pmText(), QLatin1String("nachm."));
-
- QLocale sv("sv_SE");
- QCOMPARE(sv.amText(), QLatin1String("fm"));
- QCOMPARE(sv.pmText(), QLatin1String("em"));
-
- QLocale nn("nl_NL");
- QCOMPARE(nn.amText(), QLatin1String("a.m."));
- QCOMPARE(nn.pmText(), QLatin1String("p.m."));
-
- QLocale ua("uk_UA");
- QCOMPARE(ua.amText(), QString::fromUtf8("\320\264\320\277"));
- QCOMPARE(ua.pmText(), QString::fromUtf8("\320\277\320\277"));
-
- QLocale tr("tr_TR");
- QCOMPARE(tr.amText(), QString::fromUtf8("\303\226\303\226"));
- QCOMPARE(tr.pmText(), QString::fromUtf8("\303\226\123"));
-
- QLocale id("id_ID");
- QCOMPARE(id.amText(), QLatin1String("AM"));
- QCOMPARE(id.pmText(), QLatin1String("PM"));
-
- QLocale ta("ta_LK");
- QCOMPARE(ta.amText(), QString::fromUtf8("à®®à¯à®±à¯à®ªà®•à®²à¯"));
- QCOMPARE(ta.pmText(), QString::fromUtf8("பிறà¯à®ªà®•à®²à¯"));
+ QFETCH(QString, morn);
+ QFETCH(QString, even);
+ QLatin1String name(QTest::currentDataTag());
+ QLocale locale(name == QLatin1String("C") ? QLocale(QLocale::C) : QLocale(name));
+ QCOMPARE(locale.amText(), morn);
+ QCOMPARE(locale.pmText(), even);
}
void tst_QLocale::dateFormat()
@@ -2310,8 +2375,10 @@ void tst_QLocale::monthName()
QCOMPARE(de.monthName(12, QLocale::NarrowFormat), QLatin1String("D"));
QLocale ru("ru_RU");
- QCOMPARE(ru.monthName(1, QLocale::LongFormat), QString::fromUtf8("\321\217\320\275\320\262\320\260\321\200\321\217"));
- QCOMPARE(ru.monthName(1, QLocale::ShortFormat), QString::fromUtf8("\321\217\320\275\320\262\56"));
+ QCOMPARE(ru.monthName(1, QLocale::LongFormat),
+ QString::fromUtf8("\321\217\320\275\320\262\320\260\321\200\321\217"));
+ QCOMPARE(ru.monthName(1, QLocale::ShortFormat),
+ QString::fromUtf8("\321\217\320\275\320\262\56"));
QCOMPARE(ru.monthName(1, QLocale::NarrowFormat), QString::fromUtf8("\320\257"));
QLocale ir("ga_IE");
@@ -2340,13 +2407,16 @@ void tst_QLocale::standaloneMonthName()
// For de_DE locale Unicode CLDR database doesn't contain standalone long months
// so just checking if the return value is the same as in monthName().
QCOMPARE(de.standaloneMonthName(12, QLocale::LongFormat), QLatin1String("Dezember"));
- QCOMPARE(de.standaloneMonthName(12, QLocale::LongFormat), de.monthName(12, QLocale::LongFormat));
+ QCOMPARE(de.standaloneMonthName(12, QLocale::LongFormat),
+ de.monthName(12, QLocale::LongFormat));
QCOMPARE(de.standaloneMonthName(12, QLocale::ShortFormat), QLatin1String("Dez"));
QCOMPARE(de.standaloneMonthName(12, QLocale::NarrowFormat), QLatin1String("D"));
QLocale ru("ru_RU");
- QCOMPARE(ru.standaloneMonthName(1, QLocale::LongFormat), QString::fromUtf8("\xd1\x8f\xd0\xbd\xd0\xb2\xd0\xb0\xd1\x80\xd1\x8c"));
- QCOMPARE(ru.standaloneMonthName(1, QLocale::ShortFormat), QString::fromUtf8("\xd1\x8f\xd0\xbd\xd0\xb2."));
+ QCOMPARE(ru.standaloneMonthName(1, QLocale::LongFormat),
+ QString::fromUtf8("\xd1\x8f\xd0\xbd\xd0\xb2\xd0\xb0\xd1\x80\xd1\x8c"));
+ QCOMPARE(ru.standaloneMonthName(1, QLocale::ShortFormat),
+ QString::fromUtf8("\xd1\x8f\xd0\xbd\xd0\xb2."));
QCOMPARE(ru.standaloneMonthName(1, QLocale::NarrowFormat), QString::fromUtf8("\xd0\xaf"));
}
@@ -2371,19 +2441,30 @@ void tst_QLocale::currency()
QCOMPARE(en_US.toCurrencyString(double(-1234.56), NULL, 4), QString("$-1,234.5600"));
const QLocale ru_RU("ru_RU");
- QCOMPARE(ru_RU.toCurrencyString(qulonglong(1234)), QString::fromUtf8("1" "\xc2\xa0" "234\xc2\xa0\xe2\x82\xbd"));
- QCOMPARE(ru_RU.toCurrencyString(qlonglong(-1234)), QString::fromUtf8("-1" "\xc2\xa0" "234\xc2\xa0\xe2\x82\xbd"));
- QCOMPARE(ru_RU.toCurrencyString(double(1234.56)), QString::fromUtf8("1" "\xc2\xa0" "234,56\xc2\xa0\xe2\x82\xbd"));
- QCOMPARE(ru_RU.toCurrencyString(double(-1234.56)), QString::fromUtf8("-1" "\xc2\xa0" "234,56\xc2\xa0\xe2\x82\xbd"));
+ QCOMPARE(ru_RU.toCurrencyString(qulonglong(1234)),
+ QString::fromUtf8("1" "\xc2\xa0" "234\xc2\xa0\xe2\x82\xbd"));
+ QCOMPARE(ru_RU.toCurrencyString(qlonglong(-1234)),
+ QString::fromUtf8("-1" "\xc2\xa0" "234\xc2\xa0\xe2\x82\xbd"));
+ QCOMPARE(ru_RU.toCurrencyString(double(1234.56)),
+ QString::fromUtf8("1" "\xc2\xa0" "234,56\xc2\xa0\xe2\x82\xbd"));
+ QCOMPARE(ru_RU.toCurrencyString(double(-1234.56)),
+ QString::fromUtf8("-1" "\xc2\xa0" "234,56\xc2\xa0\xe2\x82\xbd"));
const QLocale de_DE("de_DE");
- QCOMPARE(de_DE.toCurrencyString(qulonglong(1234)), QString::fromUtf8("1.234\xc2\xa0\xe2\x82\xac"));
- QCOMPARE(de_DE.toCurrencyString(qulonglong(1234), QLatin1String("BAZ")), QString::fromUtf8("1.234\xc2\xa0" "BAZ"));
- QCOMPARE(de_DE.toCurrencyString(qlonglong(-1234)), QString::fromUtf8("-1.234\xc2\xa0\xe2\x82\xac"));
- QCOMPARE(de_DE.toCurrencyString(qlonglong(-1234), QLatin1String("BAZ")), QString::fromUtf8("-1.234\xc2\xa0" "BAZ"));
- QCOMPARE(de_DE.toCurrencyString(double(1234.56)), QString::fromUtf8("1.234,56\xc2\xa0\xe2\x82\xac"));
- QCOMPARE(de_DE.toCurrencyString(double(-1234.56)), QString::fromUtf8("-1.234,56\xc2\xa0\xe2\x82\xac"));
- QCOMPARE(de_DE.toCurrencyString(double(-1234.56), QLatin1String("BAZ")), QString::fromUtf8("-1.234,56\xc2\xa0" "BAZ"));
+ QCOMPARE(de_DE.toCurrencyString(qulonglong(1234)),
+ QString::fromUtf8("1.234\xc2\xa0\xe2\x82\xac"));
+ QCOMPARE(de_DE.toCurrencyString(qulonglong(1234), QLatin1String("BAZ")),
+ QString::fromUtf8("1.234\xc2\xa0" "BAZ"));
+ QCOMPARE(de_DE.toCurrencyString(qlonglong(-1234)),
+ QString::fromUtf8("-1.234\xc2\xa0\xe2\x82\xac"));
+ QCOMPARE(de_DE.toCurrencyString(qlonglong(-1234), QLatin1String("BAZ")),
+ QString::fromUtf8("-1.234\xc2\xa0" "BAZ"));
+ QCOMPARE(de_DE.toCurrencyString(double(1234.56)),
+ QString::fromUtf8("1.234,56\xc2\xa0\xe2\x82\xac"));
+ QCOMPARE(de_DE.toCurrencyString(double(-1234.56)),
+ QString::fromUtf8("-1.234,56\xc2\xa0\xe2\x82\xac"));
+ QCOMPARE(de_DE.toCurrencyString(double(-1234.56), QLatin1String("BAZ")),
+ QString::fromUtf8("-1.234,56\xc2\xa0" "BAZ"));
const QLocale es_CR(QLocale::Spanish, QLocale::CostaRica);
QCOMPARE(es_CR.toCurrencyString(double(1565.25)),
@@ -2398,11 +2479,13 @@ void tst_QLocale::quoteString()
const QString someText("text");
const QLocale c(QLocale::C);
QCOMPARE(c.quoteString(someText), QString::fromUtf8("\x22" "text" "\x22"));
- QCOMPARE(c.quoteString(someText, QLocale::AlternateQuotation), QString::fromUtf8("\x27" "text" "\x27"));
+ QCOMPARE(c.quoteString(someText, QLocale::AlternateQuotation),
+ QString::fromUtf8("\x27" "text" "\x27"));
const QLocale de_CH("de_CH");
QCOMPARE(de_CH.quoteString(someText), QString::fromUtf8("\xe2\x80\x9e" "text" "\xe2\x80\x9c"));
- QCOMPARE(de_CH.quoteString(someText, QLocale::AlternateQuotation), QString::fromUtf8("\xe2\x80\x9a" "text" "\xe2\x80\x98"));
+ QCOMPARE(de_CH.quoteString(someText, QLocale::AlternateQuotation),
+ QString::fromUtf8("\xe2\x80\x9a" "text" "\xe2\x80\x98"));
}
@@ -2484,23 +2567,28 @@ void tst_QLocale::listPatterns()
QCOMPARE(zh_CN.createSeparatedList(sl1), QString(""));
QCOMPARE(zh_CN.createSeparatedList(sl2), QString("aaa"));
QCOMPARE(zh_CN.createSeparatedList(sl3), QString::fromUtf8("aaa" "\xe5\x92\x8c" "bbb"));
- QCOMPARE(zh_CN.createSeparatedList(sl4), QString::fromUtf8("aaa" "\xe3\x80\x81" "bbb" "\xe5\x92\x8c" "ccc"));
- QCOMPARE(zh_CN.createSeparatedList(sl5), QString::fromUtf8("aaa" "\xe3\x80\x81" "bbb" "\xe3\x80\x81" "ccc" "\xe5\x92\x8c" "ddd"));
+ QCOMPARE(zh_CN.createSeparatedList(sl4),
+ QString::fromUtf8("aaa" "\xe3\x80\x81" "bbb" "\xe5\x92\x8c" "ccc"));
+ QCOMPARE(zh_CN.createSeparatedList(sl5),
+ QString::fromUtf8("aaa" "\xe3\x80\x81" "bbb" "\xe3\x80\x81"
+ "ccc" "\xe5\x92\x8c" "ddd"));
}
-void tst_QLocale::measurementSystems()
+void tst_QLocale::measurementSystems_data()
{
- QLocale locale(QLocale::English, QLocale::UnitedStates);
- QCOMPARE(locale.measurementSystem(), QLocale::ImperialUSSystem);
-
- locale = QLocale(QLocale::English, QLocale::UnitedKingdom);
- QCOMPARE(locale.measurementSystem(), QLocale::ImperialUKSystem);
-
- locale = QLocale(QLocale::English, QLocale::Australia);
- QCOMPARE(locale.measurementSystem(), QLocale::MetricSystem);
+ QTest::addColumn<QLocale>("locale");
+ QTest::addColumn<QLocale::MeasurementSystem>("system");
+ QTest::newRow("en_US") << QLocale(QLocale::English, QLocale::UnitedStates) << QLocale::ImperialUSSystem;
+ QTest::newRow("en_GB") << QLocale(QLocale::English, QLocale::UnitedKingdom) << QLocale::ImperialUKSystem;
+ QTest::newRow("en_AU") << QLocale(QLocale::English, QLocale::Australia) << QLocale::MetricSystem;
+ QTest::newRow("de") << QLocale(QLocale::German) << QLocale::MetricSystem;
+}
- locale = QLocale(QLocale::German);
- QCOMPARE(locale.measurementSystem(), QLocale::MetricSystem);
+void tst_QLocale::measurementSystems()
+{
+ QFETCH(QLocale, locale);
+ QFETCH(QLocale::MeasurementSystem, system);
+ QCOMPARE(locale.measurementSystem(), system);
}
void tst_QLocale::QTBUG_26035_positivesign()
@@ -2566,7 +2654,9 @@ void tst_QLocale::textDirection_data()
case QLocale::Uighur:
case QLocale::Urdu:
case QLocale::Yiddish:
- rightToLeft = QLocale(QLocale::Language(language)).language() == QLocale::Language(language); // false if there is no locale data for language
+ // false if there is no locale data for language:
+ rightToLeft = (QLocale(QLocale::Language(language)).language()
+ == QLocale::Language(language));
break;
default:
break;
@@ -2651,6 +2741,37 @@ void tst_QLocale::formattedDataSize_data()
#undef ROWQ
#undef ROWB
}
+
+ // Languages which don't use a Latin alphabet
+
+ const QLocale::DataSizeFormats iecFormat = QLocale::DataSizeIecFormat;
+ const QLocale::DataSizeFormats traditionalFormat = QLocale::DataSizeTraditionalFormat;
+ const QLocale::DataSizeFormats siFormat = QLocale::DataSizeSIFormat;
+ const QLocale::Language lang = QLocale::Russian;
+
+ QTest::newRow("Russian-IEC-0") << lang << 2 << iecFormat << 0 << QString("0 \u0431\u0430\u0439\u0442\u044B");
+ QTest::newRow("Russian-IEC-10") << lang << 2 << iecFormat << 10 << QString("10 \u0431\u0430\u0439\u0442\u044B");
+ // CLDR doesn't provide IEC prefixes (yet?) so they aren't getting translated
+ QTest::newRow("Russian-IEC-12Ki") << lang << 2 << iecFormat << 12345 << QString("12,06 KiB");
+ QTest::newRow("Russian-IEC-16Ki") << lang << 2 << iecFormat << 16384 << QString("16,00 KiB");
+ QTest::newRow("Russian-IEC-1235k") << lang << 2 << iecFormat << 1234567 << QString("1,18 MiB");
+ QTest::newRow("Russian-IEC-1374k") << lang << 2 << iecFormat << 1374744 << QString("1,31 MiB");
+ QTest::newRow("Russian-IEC-1234M") << lang << 2 << iecFormat << 1234567890 << QString("1,15 GiB");
+
+ QTest::newRow("Russian-Trad-0") << lang << 2 << traditionalFormat << 0 << QString("0 \u0431\u0430\u0439\u0442\u044B");
+ QTest::newRow("Russian-Trad-10") << lang << 2 << traditionalFormat << 10 << QString("10 \u0431\u0430\u0439\u0442\u044B");
+ QTest::newRow("Russian-Trad-12Ki") << lang << 2 << traditionalFormat << 12345 << QString("12,06 \u043A\u0411");
+ QTest::newRow("Russian-Trad-16Ki") << lang << 2 << traditionalFormat << 16384 << QString("16,00 \u043A\u0411");
+ QTest::newRow("Russian-Trad-1235k") << lang << 2 << traditionalFormat << 1234567 << QString("1,18 \u041C\u0411");
+ QTest::newRow("Russian-Trad-1374k") << lang << 2 << traditionalFormat << 1374744 << QString("1,31 \u041C\u0411");
+ QTest::newRow("Russian-Trad-1234M") << lang << 2 << traditionalFormat << 1234567890 << QString("1,15 \u0413\u0411");
+
+ QTest::newRow("Russian-Decimal-0") << lang << 2 << siFormat << 0 << QString("0 \u0431\u0430\u0439\u0442\u044B");
+ QTest::newRow("Russian-Decimal-10") << lang << 2 << siFormat << 10 << QString("10 \u0431\u0430\u0439\u0442\u044B");
+ QTest::newRow("Russian-Decimal-16Ki") << lang << 2 << siFormat << 16384 << QString("16,38 \u043A\u0411");
+ QTest::newRow("Russian-Decimal-1234k") << lang << 2 << siFormat << 1234567 << QString("1,23 \u041C\u0411");
+ QTest::newRow("Russian-Decimal-1374k") << lang << 2 << siFormat << 1374744 << QString("1,37 \u041C\u0411");
+ QTest::newRow("Russian-Decimal-1234M") << lang << 2 << siFormat << 1234567890 << QString("1,23 \u0413\u0411");
}
void tst_QLocale::formattedDataSize()
@@ -2663,25 +2784,33 @@ void tst_QLocale::formattedDataSize()
QCOMPARE(QLocale(language).formattedDataSize(bytes, decimalPlaces, units), output);
}
-void tst_QLocale::bcp47Name()
+void tst_QLocale::bcp47Name_data()
{
- QCOMPARE(QLocale("C").bcp47Name(), QStringLiteral("en"));
- QCOMPARE(QLocale("en").bcp47Name(), QStringLiteral("en"));
- QCOMPARE(QLocale("en_US").bcp47Name(), QStringLiteral("en"));
- QCOMPARE(QLocale("en_GB").bcp47Name(), QStringLiteral("en-GB"));
- QCOMPARE(QLocale("en_DE").bcp47Name(), QStringLiteral("en-DE"));
- QCOMPARE(QLocale("de_DE").bcp47Name(), QStringLiteral("de"));
- QCOMPARE(QLocale("sr_RS").bcp47Name(), QStringLiteral("sr"));
- QCOMPARE(QLocale("sr_Cyrl_RS").bcp47Name(), QStringLiteral("sr"));
- QCOMPARE(QLocale("sr_Latn_RS").bcp47Name(), QStringLiteral("sr-Latn"));
- QCOMPARE(QLocale("sr_ME").bcp47Name(), QStringLiteral("sr-ME"));
- QCOMPARE(QLocale("sr_Cyrl_ME").bcp47Name(), QStringLiteral("sr-Cyrl-ME"));
- QCOMPARE(QLocale("sr_Latn_ME").bcp47Name(), QStringLiteral("sr-ME"));
+ QTest::addColumn<QString>("expect");
+
+ QTest::newRow("C") << QStringLiteral("en");
+ QTest::newRow("en") << QStringLiteral("en");
+ QTest::newRow("en_US") << QStringLiteral("en");
+ QTest::newRow("en_GB") << QStringLiteral("en-GB");
+ QTest::newRow("en_DE") << QStringLiteral("en-DE");
+ QTest::newRow("de_DE") << QStringLiteral("de");
+ QTest::newRow("sr_RS") << QStringLiteral("sr");
+ QTest::newRow("sr_Cyrl_RS") << QStringLiteral("sr");
+ QTest::newRow("sr_Latn_RS") << QStringLiteral("sr-Latn");
+ QTest::newRow("sr_ME") << QStringLiteral("sr-ME");
+ QTest::newRow("sr_Cyrl_ME") << QStringLiteral("sr-Cyrl-ME");
+ QTest::newRow("sr_Latn_ME") << QStringLiteral("sr-ME");
// Fall back to defaults when country isn't in CLDR for this language:
- QCOMPARE(QLocale("sr_HR").bcp47Name(), QStringLiteral("sr"));
- QCOMPARE(QLocale("sr_Cyrl_HR").bcp47Name(), QStringLiteral("sr"));
- QCOMPARE(QLocale("sr_Latn_HR").bcp47Name(), QStringLiteral("sr-Latn"));
+ QTest::newRow("sr_HR") << QStringLiteral("sr");
+ QTest::newRow("sr_Cyrl_HR") << QStringLiteral("sr");
+ QTest::newRow("sr_Latn_HR") << QStringLiteral("sr-Latn");
+}
+
+void tst_QLocale::bcp47Name()
+{
+ QFETCH(QString, expect);
+ QCOMPARE(QLocale(QLatin1String(QTest::currentDataTag())).bcp47Name(), expect);
}
class MySystemLocale : public QSystemLocale
diff --git a/tests/auto/corelib/tools/qmacautoreleasepool/qmacautoreleasepool.pro b/tests/auto/corelib/tools/qmacautoreleasepool/qmacautoreleasepool.pro
index 26b3a47472..8599596344 100644
--- a/tests/auto/corelib/tools/qmacautoreleasepool/qmacautoreleasepool.pro
+++ b/tests/auto/corelib/tools/qmacautoreleasepool/qmacautoreleasepool.pro
@@ -2,3 +2,4 @@ CONFIG += testcase
TARGET = tst_qmacautoreleasepool
QT = core testlib
SOURCES = tst_qmacautoreleasepool.mm
+LIBS += -framework Foundation
diff --git a/tests/auto/corelib/tools/qmakearray/qmakearray.pro b/tests/auto/corelib/tools/qmakearray/qmakearray.pro
new file mode 100644
index 0000000000..abb3d9fdbc
--- /dev/null
+++ b/tests/auto/corelib/tools/qmakearray/qmakearray.pro
@@ -0,0 +1,4 @@
+CONFIG += testcase
+TARGET = tst_qmakearray
+QT = core testlib core-private
+SOURCES = $$PWD/tst_qmakearray.cpp
diff --git a/tests/auto/corelib/tools/qmakearray/tst_qmakearray.cpp b/tests/auto/corelib/tools/qmakearray/tst_qmakearray.cpp
new file mode 100644
index 0000000000..e0d3f52719
--- /dev/null
+++ b/tests/auto/corelib/tools/qmakearray/tst_qmakearray.cpp
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include <private/qmakearray_p.h>
+
+
+class tst_QMakeArray : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void quicksort();
+};
+
+struct Pair {
+ unsigned int key;
+ unsigned int val;
+
+ constexpr bool operator <=(const Pair &that) const noexcept
+ {
+ return key <= that.key;
+ }
+
+ constexpr bool operator<(const Pair &that) const noexcept
+ {
+ return key < that.key;
+ }
+
+ constexpr bool operator==(const Pair &that) const noexcept
+ {
+ return key == that.key;
+ }
+};
+
+template<std::size_t Key, std::size_t Val>
+struct PairQuickSortElem
+{
+ using Type = Pair;
+ static constexpr Type data() noexcept { return Type{Key, Val}; }
+};
+
+void tst_QMakeArray::quicksort()
+{
+ constexpr const auto sorted_array = qMakeArray(
+ QSortedData<
+ PairQuickSortElem<10, 0>,
+ PairQuickSortElem<5, 0>,
+ PairQuickSortElem<7, 0>,
+ PairQuickSortElem<1, 0>,
+ PairQuickSortElem<8, 0>,
+ PairQuickSortElem<6, 0>,
+ PairQuickSortElem<4, 0>,
+ PairQuickSortElem<3, 0>,
+ PairQuickSortElem<1, 0>,
+ PairQuickSortElem<2, 0>,
+ PairQuickSortElem<10, 0>,
+ PairQuickSortElem<5, 0>
+ >::Data{});
+ static_assert(sorted_array.size() == 12, "sorted_array.size() != 12");
+ QCOMPARE(sorted_array[0].key, 1u);
+ QCOMPARE(sorted_array[1].key, 1u);
+ QCOMPARE(sorted_array[2].key, 2u);
+ QCOMPARE(sorted_array[3].key, 3u);
+ QCOMPARE(sorted_array[4].key, 4u);
+ QCOMPARE(sorted_array[5].key, 5u);
+ QCOMPARE(sorted_array[6].key, 5u);
+ QCOMPARE(sorted_array[7].key, 6u);
+ QCOMPARE(sorted_array[8].key, 7u);
+ QCOMPARE(sorted_array[9].key, 8u);
+ QCOMPARE(sorted_array[10].key, 10u);
+ QCOMPARE(sorted_array[11].key, 10u);
+}
+
+
+QTEST_APPLESS_MAIN(tst_QMakeArray)
+#include "tst_qmakearray.moc"
diff --git a/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/alwaysoptimize.pro b/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/alwaysoptimize.pro
deleted file mode 100644
index a27286ff20..0000000000
--- a/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/alwaysoptimize.pro
+++ /dev/null
@@ -1,7 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qregularexpression_alwaysoptimize
-QT = core testlib
-HEADERS = ../tst_qregularexpression.h
-SOURCES = \
- tst_qregularexpression_alwaysoptimize.cpp \
- ../tst_qregularexpression.cpp
diff --git a/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/tst_qregularexpression_alwaysoptimize.cpp b/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/tst_qregularexpression_alwaysoptimize.cpp
deleted file mode 100644
index 6d2ae48235..0000000000
--- a/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/tst_qregularexpression_alwaysoptimize.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Giuseppe D'Angelo <dangelog@gmail.com>.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtTest/QtTest>
-#include "../tst_qregularexpression.h"
-
-class tst_QRegularExpression_AlwaysOptimize : public tst_QRegularExpression
-{
- Q_OBJECT
-
-private slots:
- void initTestCase();
-};
-
-QT_BEGIN_NAMESPACE
-extern Q_CORE_EXPORT unsigned int qt_qregularexpression_optimize_after_use_count; // from qregularexpression.cpp
-QT_END_NAMESPACE
-
-void tst_QRegularExpression_AlwaysOptimize::initTestCase()
-{
- qt_qregularexpression_optimize_after_use_count = 1;
-}
-
-QTEST_APPLESS_MAIN(tst_QRegularExpression_AlwaysOptimize)
-
-#include "tst_qregularexpression_alwaysoptimize.moc"
diff --git a/tests/auto/corelib/tools/qregularexpression/defaultoptimize/defaultoptimize.pro b/tests/auto/corelib/tools/qregularexpression/defaultoptimize/defaultoptimize.pro
deleted file mode 100644
index 0b36c79c1b..0000000000
--- a/tests/auto/corelib/tools/qregularexpression/defaultoptimize/defaultoptimize.pro
+++ /dev/null
@@ -1,7 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qregularexpression_defaultoptimize
-QT = core testlib
-HEADERS = ../tst_qregularexpression.h
-SOURCES = \
- tst_qregularexpression_defaultoptimize.cpp \
- ../tst_qregularexpression.cpp
diff --git a/tests/auto/corelib/tools/qregularexpression/defaultoptimize/tst_qregularexpression_defaultoptimize.cpp b/tests/auto/corelib/tools/qregularexpression/defaultoptimize/tst_qregularexpression_defaultoptimize.cpp
deleted file mode 100644
index a815c6cab9..0000000000
--- a/tests/auto/corelib/tools/qregularexpression/defaultoptimize/tst_qregularexpression_defaultoptimize.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Giuseppe D'Angelo <dangelog@gmail.com>.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtTest/QtTest>
-#include "../tst_qregularexpression.h"
-
-class tst_QRegularExpression_DefaultOptimize : public tst_QRegularExpression
-{
- Q_OBJECT
-};
-
-QTEST_APPLESS_MAIN(tst_QRegularExpression_DefaultOptimize)
-
-#include "tst_qregularexpression_defaultoptimize.moc"
diff --git a/tests/auto/corelib/tools/qregularexpression/forceoptimize/forceoptimize.pro b/tests/auto/corelib/tools/qregularexpression/forceoptimize/forceoptimize.pro
deleted file mode 100644
index 1db77781dd..0000000000
--- a/tests/auto/corelib/tools/qregularexpression/forceoptimize/forceoptimize.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qregularexpression_forceoptimize
-QT = core testlib
-HEADERS = ../tst_qregularexpression.h
-SOURCES = \
- tst_qregularexpression_forceoptimize.cpp \
- ../tst_qregularexpression.cpp
-DEFINES += forceOptimize=true
diff --git a/tests/auto/corelib/tools/qregularexpression/forceoptimize/tst_qregularexpression_forceoptimize.cpp b/tests/auto/corelib/tools/qregularexpression/forceoptimize/tst_qregularexpression_forceoptimize.cpp
deleted file mode 100644
index 38a3a64fa3..0000000000
--- a/tests/auto/corelib/tools/qregularexpression/forceoptimize/tst_qregularexpression_forceoptimize.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtTest/QtTest>
-#include "../tst_qregularexpression.h"
-
-class tst_QRegularExpression_ForceOptimize : public tst_QRegularExpression
-{
- Q_OBJECT
-};
-
-QTEST_APPLESS_MAIN(tst_QRegularExpression_ForceOptimize)
-
-#include "tst_qregularexpression_forceoptimize.moc"
diff --git a/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro b/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro
index e1840808ff..ec8189717e 100644
--- a/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro
+++ b/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro
@@ -1,3 +1,4 @@
-TEMPLATE = subdirs
-SUBDIRS = defaultoptimize forceoptimize
-qtConfig(private_tests): SUBDIRS += alwaysoptimize
+CONFIG += testcase
+TARGET = tst_qregularexpression
+QT = core testlib
+SOURCES = tst_qregularexpression.cpp
diff --git a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp
index c828551e44..f520e9742a 100644
--- a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp
+++ b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp
@@ -33,11 +33,60 @@
#include <qstringlist.h>
#include <qhash.h>
-#include "tst_qregularexpression.h"
+#include <qobject.h>
+#include <qregularexpression.h>
+#include <qthread.h>
-#ifndef forceOptimize
-#define forceOptimize false
-#endif
+Q_DECLARE_METATYPE(QRegularExpression::PatternOptions)
+Q_DECLARE_METATYPE(QRegularExpression::MatchType)
+Q_DECLARE_METATYPE(QRegularExpression::MatchOptions)
+
+class tst_QRegularExpression : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void defaultConstructors();
+ void gettersSetters_data();
+ void gettersSetters();
+ void escape_data();
+ void escape();
+ void validity_data();
+ void validity();
+ void patternOptions_data();
+ void patternOptions();
+ void normalMatch_data();
+ void normalMatch();
+ void partialMatch_data();
+ void partialMatch();
+ void globalMatch_data();
+ void globalMatch();
+ void serialize_data();
+ void serialize();
+ void operatoreq_data();
+ void operatoreq();
+ void captureCount_data();
+ void captureCount();
+ void captureNames_data();
+ void captureNames();
+ void pcreJitStackUsage_data();
+ void pcreJitStackUsage();
+ void regularExpressionMatch_data();
+ void regularExpressionMatch();
+ void JOptionUsage_data();
+ void JOptionUsage();
+ void QStringAndQStringRefEquivalence();
+ void threadSafety_data();
+ void threadSafety();
+
+ void wildcard_data();
+ void wildcard();
+ void testInvalidWildcard_data();
+ void testInvalidWildcard();
+
+private:
+ void provideRegularExpressions();
+};
struct Match
{
@@ -292,9 +341,6 @@ static void testMatch(const QRegularExpression &regexp,
QRegularExpression::MatchOptions matchOptions,
const Result &result)
{
- if (forceOptimize)
- regexp.optimize();
-
// test with QString as subject type
testMatchImpl<QREMatch>(regexp, matchingMethodForString, subject, offset, matchType, matchOptions, result);
@@ -401,30 +447,22 @@ void tst_QRegularExpression::gettersSetters()
{
QRegularExpression re;
re.setPattern(pattern);
- if (forceOptimize)
- re.optimize();
QCOMPARE(re.pattern(), pattern);
QCOMPARE(re.patternOptions(), QRegularExpression::NoPatternOption);
}
{
QRegularExpression re;
re.setPatternOptions(patternOptions);
- if (forceOptimize)
- re.optimize();
QCOMPARE(re.pattern(), QString());
QCOMPARE(re.patternOptions(), patternOptions);
}
{
QRegularExpression re(pattern);
- if (forceOptimize)
- re.optimize();
QCOMPARE(re.pattern(), pattern);
QCOMPARE(re.patternOptions(), QRegularExpression::NoPatternOption);
}
{
QRegularExpression re(pattern, patternOptions);
- if (forceOptimize)
- re.optimize();
QCOMPARE(re.pattern(), pattern);
QCOMPARE(re.patternOptions(), patternOptions);
}
@@ -465,8 +503,6 @@ void tst_QRegularExpression::escape()
QFETCH(QString, escaped);
QCOMPARE(QRegularExpression::escape(string), escaped);
QRegularExpression re(escaped);
- if (forceOptimize)
- re.optimize();
QCOMPARE(re.isValid(), true);
}
@@ -497,8 +533,6 @@ void tst_QRegularExpression::validity()
QFETCH(QString, pattern);
QFETCH(bool, validity);
QRegularExpression re(pattern);
- if (forceOptimize)
- re.optimize();
QCOMPARE(re.isValid(), validity);
if (!validity)
QTest::ignoreMessage(QtWarningMsg, "QRegularExpressionPrivate::doMatch(): called on an invalid QRegularExpression object");
@@ -585,9 +619,6 @@ void tst_QRegularExpression::patternOptions()
QFETCH(QString, subject);
QFETCH(Match, match);
- if (forceOptimize)
- regexp.optimize();
-
QRegularExpressionMatch m = regexp.match(subject);
consistencyCheck(m);
QVERIFY(m == match);
@@ -1403,9 +1434,6 @@ void tst_QRegularExpression::serialize()
QFETCH(QRegularExpression::PatternOptions, patternOptions);
QRegularExpression outRe(pattern, patternOptions);
- if (forceOptimize)
- outRe.optimize();
-
QByteArray buffer;
{
QDataStream out(&buffer, QIODevice::WriteOnly);
@@ -1468,33 +1496,18 @@ void tst_QRegularExpression::operatoreq()
QRegularExpression re1(pattern);
QRegularExpression re2(pattern);
- if (forceOptimize)
- re1.optimize();
- if (forceOptimize)
- re2.optimize();
-
verifyEquality(re1, re2);
}
{
QRegularExpression re1(QString(), patternOptions);
QRegularExpression re2(QString(), patternOptions);
- if (forceOptimize)
- re1.optimize();
- if (forceOptimize)
- re2.optimize();
-
verifyEquality(re1, re2);
}
{
QRegularExpression re1(pattern, patternOptions);
QRegularExpression re2(pattern, patternOptions);
- if (forceOptimize)
- re1.optimize();
- if (forceOptimize)
- re2.optimize();
-
verifyEquality(re1, re2);
}
}
@@ -1524,9 +1537,6 @@ void tst_QRegularExpression::captureCount()
QFETCH(QString, pattern);
QRegularExpression re(pattern);
- if (forceOptimize)
- re.optimize();
-
QTEST(re.captureCount(), "captureCount");
if (!re.isValid())
QCOMPARE(re.captureCount(), -1);
@@ -1595,9 +1605,6 @@ void tst_QRegularExpression::captureNames()
QRegularExpression re(pattern);
- if (forceOptimize)
- re.optimize();
-
QStringList namedCaptureGroups = re.namedCaptureGroups();
int namedCaptureGroupsCount = namedCaptureGroups.size();
@@ -1633,9 +1640,6 @@ void tst_QRegularExpression::pcreJitStackUsage()
QRegularExpression re(pattern);
- if (forceOptimize)
- re.optimize();
-
QVERIFY(re.isValid());
QRegularExpressionMatch match = re.match(subject);
consistencyCheck(match);
@@ -1663,9 +1667,6 @@ void tst_QRegularExpression::regularExpressionMatch()
QRegularExpression re(pattern);
- if (forceOptimize)
- re.optimize();
-
QVERIFY(re.isValid());
QRegularExpressionMatch match = re.match(subject);
consistencyCheck(match);
@@ -1705,8 +1706,6 @@ void tst_QRegularExpression::JOptionUsage()
QRegularExpression re(pattern);
if (isValid && JOptionUsed)
QTest::ignoreMessage(QtWarningMsg, qPrintable(warningMessage.arg(pattern)));
- if (forceOptimize)
- re.optimize();
QCOMPARE(re.isValid(), isValid);
}
@@ -2066,3 +2065,185 @@ void tst_QRegularExpression::QStringAndQStringRefEquivalence()
}
}
}
+
+class MatcherThread : public QThread
+{
+public:
+ explicit MatcherThread(const QRegularExpression &re, const QString &subject, QObject *parent = nullptr)
+ : QThread(parent),
+ m_re(re),
+ m_subject(subject)
+ {
+ }
+
+private:
+ static const int MATCH_ITERATIONS = 50;
+
+ void run() override
+ {
+ yieldCurrentThread();
+ for (int i = 0; i < MATCH_ITERATIONS; ++i)
+ m_re.match(m_subject);
+ }
+
+ const QRegularExpression &m_re;
+ const QString &m_subject;
+};
+
+void tst_QRegularExpression::threadSafety_data()
+{
+ QTest::addColumn<QString>("pattern");
+ QTest::addColumn<QString>("subject");
+
+ int i = 0;
+ QTest::addRow("pattern%d", ++i) << "ab.*cd" << "abcd";
+ QTest::addRow("pattern%d", ++i) << "ab.*cd" << "abd";
+ QTest::addRow("pattern%d", ++i) << "ab.*cd" << "abbbbcccd";
+ QTest::addRow("pattern%d", ++i) << "ab.*cd" << "abababcd";
+ QTest::addRow("pattern%d", ++i) << "ab.*cd" << "abcabcd";
+ QTest::addRow("pattern%d", ++i) << "ab.*cd" << "abccccccababd";
+
+ {
+ QString subject(512*1024, QLatin1Char('x'));
+ QTest::addRow("pattern%d", ++i) << "ab.*cd" << subject;
+ }
+
+ {
+ QString subject = "ab";
+ subject.append(QString(512*1024, QLatin1Char('x')));
+ subject.append("c");
+ QTest::addRow("pattern%d", ++i) << "ab.*cd" << subject;
+ }
+
+ {
+ QString subject = "ab";
+ subject.append(QString(512*1024, QLatin1Char('x')));
+ subject.append("cd");
+ QTest::addRow("pattern%d", ++i) << "ab.*cd" << subject;
+ }
+
+ QTest::addRow("pattern%d", ++i) << "(?(R)a*(?1)|((?R))b)" << "aaaabcde";
+ QTest::addRow("pattern%d", ++i) << "(?(R)a*(?1)|((?R))b)" << "aaaaaaabcde";
+}
+
+void tst_QRegularExpression::threadSafety()
+{
+ QFETCH(QString, pattern);
+ QFETCH(QString, subject);
+
+ static const int THREAD_SAFETY_ITERATIONS = 50;
+
+ const int threadCount = qMax(QThread::idealThreadCount(), 4);
+
+ for (int threadSafetyIteration = 0; threadSafetyIteration < THREAD_SAFETY_ITERATIONS; ++threadSafetyIteration) {
+ QRegularExpression re(pattern);
+
+ QVector<MatcherThread *> threads;
+ for (int i = 0; i < threadCount; ++i) {
+ MatcherThread *thread = new MatcherThread(re, subject);
+ thread->start();
+ threads.push_back(thread);
+ }
+
+ for (int i = 0; i < threadCount; ++i)
+ threads[i]->wait();
+
+ qDeleteAll(threads);
+ }
+}
+
+void tst_QRegularExpression::wildcard_data()
+{
+ QTest::addColumn<QString>("pattern");
+ QTest::addColumn<QString>("string");
+ QTest::addColumn<int>("foundIndex");
+
+ auto addRow = [](const char *pattern, const char *string, int foundIndex) {
+ QTest::newRow(pattern) << pattern << string << foundIndex;
+ };
+
+ addRow("*.html", "test.html", 0);
+ addRow("*.html", "test.htm", -1);
+ addRow("bar*", "foobarbaz", 3);
+ addRow("*", "Qt Rocks!", 0);
+ addRow(".html", "test.html", 4);
+ addRow(".h", "test.cpp", -1);
+ addRow(".???l", "test.html", 4);
+ addRow("?", "test.html", 0);
+ addRow("?m", "test.html", 6);
+ addRow("[*]", "test.html", -1);
+ addRow("[?]","test.html", -1);
+ addRow("[?]","test.h?ml", 6);
+ addRow("[[]","test.h[ml", 6);
+ addRow("[]]","test.h]ml", 6);
+ addRow(".h[a-z]ml", "test.html", 4);
+ addRow(".h[A-Z]ml", "test.html", -1);
+ addRow(".h[A-Z]ml", "test.hTml", 4);
+ addRow(".h[!A-Z]ml", "test.hTml", -1);
+ addRow(".h[!A-Z]ml", "test.html", 4);
+ addRow(".h[!T]ml", "test.hTml", -1);
+ addRow(".h[!T]ml", "test.html", 4);
+ addRow(".h[!T]m[!L]", "test.htmL", -1);
+ addRow(".h[!T]m[!L]", "test.html", 4);
+ addRow(".h[][!]", "test.h]ml", 4);
+ addRow(".h[][!]", "test.h[ml", 4);
+ addRow(".h[][!]", "test.h!ml", 4);
+
+ addRow("foo/*/bar", "Qt/foo/baz/bar", 3);
+ addRow("foo/(*)/bar", "Qt/foo/baz/bar", -1);
+ addRow("foo/(*)/bar", "Qt/foo/(baz)/bar", 3);
+ addRow("foo/?/bar", "Qt/foo/Q/bar", 3);
+ addRow("foo/?/bar", "Qt/foo/Qt/bar", -1);
+ addRow("foo/(?)/bar", "Qt/foo/Q/bar", -1);
+ addRow("foo/(?)/bar", "Qt/foo/(Q)/bar", 3);
+
+#ifdef Q_OS_WIN
+ addRow("foo\\*\\bar", "Qt\\foo\\baz\\bar", 3);
+ addRow("foo\\(*)\\bar", "Qt\\foo\\baz\\bar", -1);
+ addRow("foo\\(*)\\bar", "Qt\\foo\\(baz)\\bar", 3);
+ addRow("foo\\?\\bar", "Qt\\foo\\Q\\bar", 3);
+ addRow("foo\\?\\bar", "Qt\\foo\\Qt\\bar", -1);
+ addRow("foo\\(?)\\bar", "Qt\\foo\\Q\\bar", -1);
+ addRow("foo\\(?)\\bar", "Qt\\foo\\(Q)\\bar", 3);
+#endif
+}
+
+void tst_QRegularExpression::wildcard()
+{
+ QFETCH(QString, pattern);
+ QFETCH(QString, string);
+ QFETCH(int, foundIndex);
+
+ QRegularExpression re(QRegularExpression::wildcardToRegularExpression(pattern));
+ QRegularExpressionMatch match = re.match(string);
+
+ QCOMPARE(match.capturedStart(), foundIndex);
+}
+
+void tst_QRegularExpression::testInvalidWildcard_data()
+{
+ QTest::addColumn<QString>("pattern");
+ QTest::addColumn<bool>("isValid");
+
+ QTest::newRow("valid []") << "[abc]" << true;
+ QTest::newRow("valid ending ]") << "abc]" << true;
+ QTest::newRow("invalid [") << "[abc" << false;
+ QTest::newRow("ending [") << "abc[" << false;
+ QTest::newRow("ending [^") << "abc[^" << false;
+ QTest::newRow("ending [\\") << "abc[\\" << false;
+ QTest::newRow("ending []") << "abc[]" << false;
+ QTest::newRow("ending [[") << "abc[[" << false;
+}
+
+void tst_QRegularExpression::testInvalidWildcard()
+{
+ QFETCH(QString, pattern);
+ QFETCH(bool, isValid);
+
+ QRegularExpression re(QRegularExpression::wildcardToRegularExpression(pattern));
+ QCOMPARE(re.isValid(), isValid);
+}
+
+QTEST_APPLESS_MAIN(tst_QRegularExpression)
+
+#include "tst_qregularexpression.moc"
diff --git a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.h b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.h
deleted file mode 100644
index 8bb4aa0cce..0000000000
--- a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Giuseppe D'Angelo <dangelog@gmail.com>.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <qobject.h>
-#include <qregularexpression.h>
-
-Q_DECLARE_METATYPE(QRegularExpression::PatternOptions)
-Q_DECLARE_METATYPE(QRegularExpression::MatchType)
-Q_DECLARE_METATYPE(QRegularExpression::MatchOptions)
-
-class tst_QRegularExpression : public QObject
-{
- Q_OBJECT
-
-private slots:
- void defaultConstructors();
- void gettersSetters_data();
- void gettersSetters();
- void escape_data();
- void escape();
- void validity_data();
- void validity();
- void patternOptions_data();
- void patternOptions();
- void normalMatch_data();
- void normalMatch();
- void partialMatch_data();
- void partialMatch();
- void globalMatch_data();
- void globalMatch();
- void serialize_data();
- void serialize();
- void operatoreq_data();
- void operatoreq();
- void captureCount_data();
- void captureCount();
- void captureNames_data();
- void captureNames();
- void pcreJitStackUsage_data();
- void pcreJitStackUsage();
- void regularExpressionMatch_data();
- void regularExpressionMatch();
- void JOptionUsage_data();
- void JOptionUsage();
- void QStringAndQStringRefEquivalence();
-
-private:
- void provideRegularExpressions();
-};
diff --git a/tests/auto/corelib/tools/qscopeguard/qscopeguard.pro b/tests/auto/corelib/tools/qscopeguard/qscopeguard.pro
new file mode 100644
index 0000000000..070d4b077c
--- /dev/null
+++ b/tests/auto/corelib/tools/qscopeguard/qscopeguard.pro
@@ -0,0 +1,4 @@
+CONFIG += testcase
+TARGET = tst_qscopeguard
+QT = core testlib
+SOURCES = tst_qscopeguard.cpp
diff --git a/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp b/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp
new file mode 100644
index 0000000000..f95d48f042
--- /dev/null
+++ b/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Sérgio Martins <sergio.martins@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtCore/QScopeGuard>
+
+/*!
+ \class tst_QScopedGuard
+ \internal
+ \since 5.11
+ \brief Tests class QScopedCleanup and function qScopeGuard
+
+ */
+class tst_QScopedGuard : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void leavingScope();
+ void exceptions();
+};
+
+static int s_globalState = 0;
+
+void tst_QScopedGuard::leavingScope()
+{
+ auto cleanup = qScopeGuard([] { s_globalState++; QCOMPARE(s_globalState, 3); });
+ QCOMPARE(s_globalState, 0);
+
+ {
+ auto cleanup = qScopeGuard([] { s_globalState++; });
+ QCOMPARE(s_globalState, 0);
+ }
+
+ QCOMPARE(s_globalState, 1);
+ s_globalState++;
+}
+
+void tst_QScopedGuard::exceptions()
+{
+ s_globalState = 0;
+ bool caught = false;
+ QT_TRY
+ {
+ auto cleanup = qScopeGuard([&caught] { s_globalState++; });
+ QT_THROW(std::bad_alloc()); //if Qt compiled without exceptions this is noop
+ s_globalState = 100;
+ }
+ QT_CATCH(...)
+ {
+ caught = true;
+ QCOMPARE(s_globalState, 1);
+ }
+
+ QVERIFY((caught && s_globalState == 1) || (!caught && s_globalState == 101));
+
+}
+
+QTEST_MAIN(tst_QScopedGuard)
+#include "tst_qscopeguard.moc"
diff --git a/tests/auto/corelib/tools/qsharedpointer/externaltests.cpp b/tests/auto/corelib/tools/qsharedpointer/externaltests.cpp
index 3e1668522e..4dc620e6ab 100644
--- a/tests/auto/corelib/tools/qsharedpointer/externaltests.cpp
+++ b/tests/auto/corelib/tools/qsharedpointer/externaltests.cpp
@@ -53,6 +53,12 @@
# include <unistd.h>
#endif
+enum {
+ QMakeTimeout = 300000, // 5 minutes
+ CompileTimeout = 600000, // 10 minutes
+ RunTimeout = 300000 // 5 minutes
+};
+
static QString makespec()
{
static const char default_makespec[] = DEFAULT_MAKESPEC;
@@ -143,7 +149,7 @@ namespace QTest {
bool prepareSourceCode(const QByteArray &body);
bool createProjectFile();
bool runQmake();
- bool runMake(Target target);
+ bool runMake(Target target, int timeout);
bool commonSetup(const QByteArray &body);
};
@@ -602,7 +608,7 @@ namespace QTest {
std_err += "qmake: ";
std_err += qmake.errorString().toLocal8Bit();
} else {
- ok = qmake.waitForFinished();
+ ok = qmake.waitForFinished(QMakeTimeout);
exitCode = qmake.exitCode();
if (!ok)
QTest::ensureStopped(qmake);
@@ -617,7 +623,7 @@ namespace QTest {
#endif // QT_CONFIG(process)
}
- bool QExternalTestPrivate::runMake(Target target)
+ bool QExternalTestPrivate::runMake(Target target, int timeout)
{
#if !QT_CONFIG(process)
return false;
@@ -670,7 +676,7 @@ namespace QTest {
}
make.closeWriteChannel();
- bool ok = make.waitForFinished(channelMode == QProcess::ForwardedChannels ? -1 : 60000);
+ bool ok = make.waitForFinished(channelMode == QProcess::ForwardedChannels ? -1 : timeout);
if (!ok)
QTest::ensureStopped(make);
exitCode = make.exitCode();
@@ -705,7 +711,7 @@ namespace QTest {
failedStage = QExternalTest::CompilationStage;
std_out += "\n### --- stdout from make (compilation) --- ###\n";
std_err += "\n### --- stderr from make (compilation) --- ###\n";
- return runMake(Compile);
+ return runMake(Compile, CompileTimeout);
}
bool QExternalTestPrivate::tryLink(const QByteArray &body)
@@ -717,7 +723,7 @@ namespace QTest {
failedStage = QExternalTest::LinkStage;
std_out += "\n### --- stdout from make (linking) --- ###\n";
std_err += "\n### --- stderr from make (linking) --- ###\n";
- return runMake(Link);
+ return runMake(Link, CompileTimeout);
}
bool QExternalTestPrivate::tryRun(const QByteArray &body)
@@ -729,7 +735,7 @@ namespace QTest {
failedStage = QExternalTest::RunStage;
std_out += "\n### --- stdout from process --- ###\n";
std_err += "\n### --- stderr from process --- ###\n";
- return runMake(Run);
+ return runMake(Run, RunTimeout);
}
}
QT_END_NAMESPACE
diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp
index 2074c9789a..f429bda804 100644
--- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp
+++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp
@@ -450,6 +450,8 @@ private slots:
void trimmed();
void toUpper();
void toLower();
+ void isUpper();
+ void isLower();
void toCaseFolded();
void rightJustified();
void leftJustified();
@@ -529,10 +531,8 @@ private slots:
void integer_conversion();
void tortureSprintfDouble();
void toNum();
-#if !defined(Q_OS_WIN)
void localeAwareCompare_data();
void localeAwareCompare();
-#endif
void reverseIterators();
void split_data();
void split();
@@ -2315,6 +2315,46 @@ void tst_QString::toLower()
#endif
}
+void tst_QString::isUpper()
+{
+ QVERIFY(!QString().isUpper());
+ QVERIFY(!QString("").isUpper());
+ QVERIFY(QString("TEXT").isUpper());
+ QVERIFY(!QString("text").isUpper());
+ QVERIFY(!QString("Text").isUpper());
+ QVERIFY(!QString("tExt").isUpper());
+ QVERIFY(!QString("teXt").isUpper());
+ QVERIFY(!QString("texT").isUpper());
+ QVERIFY(!QString("TExt").isUpper());
+ QVERIFY(!QString("teXT").isUpper());
+ QVERIFY(!QString("tEXt").isUpper());
+ QVERIFY(!QString("tExT").isUpper());
+ QVERIFY(!QString("@ABYZ[").isUpper());
+ QVERIFY(!QString("@abyz[").isUpper());
+ QVERIFY(!QString("`ABYZ{").isUpper());
+ QVERIFY(!QString("`abyz{").isUpper());
+}
+
+void tst_QString::isLower()
+{
+ QVERIFY(!QString().isLower());
+ QVERIFY(!QString("").isLower());
+ QVERIFY(QString("text").isLower());
+ QVERIFY(!QString("Text").isLower());
+ QVERIFY(!QString("tExt").isLower());
+ QVERIFY(!QString("teXt").isLower());
+ QVERIFY(!QString("texT").isLower());
+ QVERIFY(!QString("TExt").isLower());
+ QVERIFY(!QString("teXT").isLower());
+ QVERIFY(!QString("tEXt").isLower());
+ QVERIFY(!QString("tExT").isLower());
+ QVERIFY(!QString("TEXT").isLower());
+ QVERIFY(!QString("@ABYZ[").isLower());
+ QVERIFY(!QString("@abyz[").isLower());
+ QVERIFY(!QString("`ABYZ{").isLower());
+ QVERIFY(!QString("`abyz{").isLower());
+}
+
void tst_QString::toCaseFolded()
{
QCOMPARE( QString().toCaseFolded(), QString() );
@@ -5468,8 +5508,6 @@ void tst_QString::tortureSprintfDouble()
#include <locale.h>
-#if !defined(Q_OS_WIN)
-// On Q_OS_WIN, we cannot set the system or user locale
void tst_QString::localeAwareCompare_data()
{
QTest::addColumn<QString>("locale");
@@ -5477,6 +5515,46 @@ void tst_QString::localeAwareCompare_data()
QTest::addColumn<QString>("s2");
QTest::addColumn<int>("result");
+ // Compare decomposed and composed form
+ {
+ // From ES6 test262 test suite (built-ins/String/prototype/localeCompare/15.5.4.9_CE.js). The test cases boil down to code like this:
+ // console.log("\u1111\u1171\u11B6".localeCompare("\ud4db")
+
+ // example from Unicode 5.0, section 3.7, definition D70
+ QTest::newRow("normalize1") << QString() << QString::fromUtf8("o\xCC\x88") << QString::fromUtf8("\xC3\xB6") << 0;
+ // examples from Unicode 5.0, chapter 3.11
+ QTest::newRow("normalize2") << QString() << QString::fromUtf8("\xC3\xA4\xCC\xA3") << QString::fromUtf8("a\xCC\xA3\xCC\x88") << 0;
+ QTest::newRow("normalize3") << QString() << QString::fromUtf8("a\xCC\x88\xCC\xA3") << QString::fromUtf8("a\xCC\xA3\xCC\x88") << 0;
+ QTest::newRow("normalize4") << QString() << QString::fromUtf8("\xE1\xBA\xA1\xCC\x88") << QString::fromUtf8("a\xCC\xA3\xCC\x88") << 0;
+ QTest::newRow("normalize5") << QString() << QString::fromUtf8("\xC3\xA4\xCC\x86") << QString::fromUtf8("a\xCC\x88\xCC\x86") << 0;
+ QTest::newRow("normalize6") << QString() << QString::fromUtf8("\xC4\x83\xCC\x88") << QString::fromUtf8("a\xCC\x86\xCC\x88") << 0;
+ // example from Unicode 5.0, chapter 3.12
+ QTest::newRow("normalize7") << QString() << QString::fromUtf8("\xE1\x84\x91\xE1\x85\xB1\xE1\x86\xB6") << QString::fromUtf8("\xED\x93\x9B") << 0;
+ // examples from UTS 10, Unicode Collation Algorithm
+ QTest::newRow("normalize8") << QString() << QString::fromUtf8("\xE2\x84\xAB") << QString::fromUtf8("\xC3\x85") << 0;
+ QTest::newRow("normalize9") << QString() << QString::fromUtf8("\xE2\x84\xAB") << QString::fromUtf8("A\xCC\x8A") << 0;
+ QTest::newRow("normalize10") << QString() << QString::fromUtf8("x\xCC\x9B\xCC\xA3") << QString::fromUtf8("x\xCC\xA3\xCC\x9B") << 0;
+ QTest::newRow("normalize11") << QString() << QString::fromUtf8("\xE1\xBB\xB1") << QString::fromUtf8("\xE1\xBB\xA5\xCC\x9B") << 0;
+ QTest::newRow("normalize12") << QString() << QString::fromUtf8("\xE1\xBB\xB1") << QString::fromUtf8("u\xCC\x9B\xCC\xA3") << 0;
+ QTest::newRow("normalize13") << QString() << QString::fromUtf8("\xE1\xBB\xB1") << QString::fromUtf8("\xC6\xB0\xCC\xA3") << 0;
+ QTest::newRow("normalize14") << QString() << QString::fromUtf8("\xE1\xBB\xB1") << QString::fromUtf8("u\xCC\xA3\xCC\x9B") << 0;
+ // examples from UAX 15, Unicode Normalization Forms
+ QTest::newRow("normalize15") << QString() << QString::fromUtf8("\xC3\x87") << QString::fromUtf8("C\xCC\xA7") << 0;
+ QTest::newRow("normalize16") << QString() << QString::fromUtf8("q\xCC\x87\xCC\xA3") << QString::fromUtf8("q\xCC\xA3\xCC\x87") << 0;
+ QTest::newRow("normalize17") << QString() << QString::fromUtf8("\xEA\xB0\x80") << QString::fromUtf8("\xE1\x84\x80\xE1\x85\xA1") << 0;
+ QTest::newRow("normalize18") << QString() << QString::fromUtf8("\xE2\x84\xAB") << QString::fromUtf8("A\xCC\x8A") << 0;
+ QTest::newRow("normalize19") << QString() << QString::fromUtf8("\xE2\x84\xA6") << QString::fromUtf8("\xCE\xA9") << 0;
+ QTest::newRow("normalize20") << QString() << QString::fromUtf8("\xC3\x85") << QString::fromUtf8("A\xCC\x8A") << 0;
+ QTest::newRow("normalize21") << QString() << QString::fromUtf8("\xC3\xB4") << QString::fromUtf8("o\xCC\x82") << 0;
+ QTest::newRow("normalize22") << QString() << QString::fromUtf8("\xE1\xB9\xA9") << QString::fromUtf8("s\xCC\xA3\xCC\x87") << 0;
+ QTest::newRow("normalize23") << QString() << QString::fromUtf8("\xE1\xB8\x8B\xCC\xA3") << QString::fromUtf8("d\xCC\xA3\xCC\x87") << 0;
+ QTest::newRow("normalize24") << QString() << QString::fromUtf8("\xE1\xB8\x8B\xCC\xA3") << QString::fromUtf8("\xE1\xB8\x8D\xCC\x87") << 0;
+ QTest::newRow("normalize25") << QString() << QString::fromUtf8("q\xCC\x87\xCC\xA3") << QString::fromUtf8("q\xCC\xA3\xCC\x87") << 0;
+
+ }
+
+#if !defined(Q_OS_WIN)
+// On Q_OS_WIN, we cannot set the system or user locale
/*
The C locale performs pure byte comparisons for
Latin-1-specific characters (I think). Compare with Swedish
@@ -5537,6 +5615,7 @@ void tst_QString::localeAwareCompare_data()
QTest::newRow("german2") << QString("de_DE") << QString::fromLatin1("\xe4") << QString::fromLatin1("\xf6") << -1;
QTest::newRow("german3") << QString("de_DE") << QString::fromLatin1("z") << QString::fromLatin1("\xf6") << 1;
#endif
+#endif //!defined(Q_OS_WIN)
}
void tst_QString::localeAwareCompare()
@@ -5549,17 +5628,17 @@ void tst_QString::localeAwareCompare()
QStringRef r1(&s1, 0, s1.length());
QStringRef r2(&s2, 0, s2.length());
+ if (!locale.isEmpty()) {
#if defined (Q_OS_DARWIN) || defined(QT_USE_ICU)
- QSKIP("Setting the locale is not supported on OS X or ICU (you can set the C locale, but that won't affect localeAwareCompare)");
+ QSKIP("Setting the locale is not supported on OS X or ICU (you can set the C locale, but that won't affect localeAwareCompare)");
#else
- if (!locale.isEmpty()) {
const char *newLocale = setlocale(LC_ALL, locale.toLatin1());
if (!newLocale) {
setlocale(LC_ALL, "");
QSKIP("Please install the proper locale on this machine to test properly");
}
- }
#endif
+ }
#ifdef QT_USE_ICU
// ### for c1, ICU disagrees with libc on how to compare
@@ -5614,7 +5693,6 @@ void tst_QString::localeAwareCompare()
if (!locale.isEmpty())
setlocale(LC_ALL, "");
}
-#endif //!defined(Q_OS_WIN)
void tst_QString::reverseIterators()
{
@@ -6160,11 +6238,14 @@ void tst_QString::compare()
QStringRef r1(&s1, 0, s1.length());
QStringRef r2(&s2, 0, s2.length());
+ const QStringView v2(s2);
+
QCOMPARE(sign(QString::compare(s1, s2)), csr);
QCOMPARE(sign(QStringRef::compare(r1, r2)), csr);
QCOMPARE(sign(s1.compare(s2)), csr);
QCOMPARE(sign(s1.compare(r2)), csr);
QCOMPARE(sign(r1.compare(r2)), csr);
+ QCOMPARE(sign(s1.compare(v2)), csr);
QCOMPARE(sign(s1.compare(s2, Qt::CaseSensitive)), csr);
QCOMPARE(sign(s1.compare(s2, Qt::CaseInsensitive)), cir);
@@ -6172,6 +6253,8 @@ void tst_QString::compare()
QCOMPARE(sign(s1.compare(r2, Qt::CaseInsensitive)), cir);
QCOMPARE(sign(r1.compare(r2, Qt::CaseSensitive)), csr);
QCOMPARE(sign(r1.compare(r2, Qt::CaseInsensitive)), cir);
+ QCOMPARE(sign(s1.compare(v2, Qt::CaseSensitive)), csr);
+ QCOMPARE(sign(s1.compare(v2, Qt::CaseInsensitive)), cir);
QCOMPARE(sign(QString::compare(s1, s2, Qt::CaseSensitive)), csr);
QCOMPARE(sign(QString::compare(s1, s2, Qt::CaseInsensitive)), cir);
diff --git a/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp b/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp
index 9f054190e5..a3aec4c299 100644
--- a/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp
+++ b/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp
@@ -273,6 +273,15 @@ void tst_QStringList::contains()
QVERIFY(list.contains(QLatin1String("ARTHUR"), Qt::CaseInsensitive));
QVERIFY(list.contains(QLatin1String("dent"), Qt::CaseInsensitive));
QVERIFY(!list.contains(QLatin1String("hans"), Qt::CaseInsensitive));
+
+ QVERIFY(list.contains(QStringView(QString("arthur"))));
+ QVERIFY(!list.contains(QStringView(QString("ArthuR"))));
+ QVERIFY(!list.contains(QStringView(QString("Hans"))));
+ QVERIFY(list.contains(QStringView(QString("arthur")), Qt::CaseInsensitive));
+ QVERIFY(list.contains(QStringView(QString("ArthuR")), Qt::CaseInsensitive));
+ QVERIFY(list.contains(QStringView(QString("ARTHUR")), Qt::CaseInsensitive));
+ QVERIFY(list.contains(QStringView(QString("dent")), Qt::CaseInsensitive));
+ QVERIFY(!list.contains(QStringView(QString("hans")), Qt::CaseInsensitive));
}
void tst_QStringList::removeDuplicates_data()
diff --git a/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp b/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp
index 4ae96005d0..e800a0d794 100644
--- a/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp
+++ b/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp
@@ -217,6 +217,8 @@ private Q_SLOTS:
#endif
}
+ void comparison();
+
private:
template <typename String>
void conversion_tests(String arg) const;
@@ -615,5 +617,23 @@ void tst_QStringView::conversion_tests(String string) const
}
}
+void tst_QStringView::comparison()
+{
+ const QStringView aa = QStringViewLiteral("aa");
+ const QStringView upperAa = QStringViewLiteral("AA");
+ const QStringView bb = QStringViewLiteral("bb");
+
+ QVERIFY(aa == aa);
+ QVERIFY(aa != bb);
+ QVERIFY(aa < bb);
+ QVERIFY(bb > aa);
+
+ QCOMPARE(aa.compare(aa), 0);
+ QVERIFY(aa.compare(upperAa) != 0);
+ QCOMPARE(aa.compare(upperAa, Qt::CaseInsensitive), 0);
+ QVERIFY(aa.compare(bb) < 0);
+ QVERIFY(bb.compare(aa) > 0);
+}
+
QTEST_APPLESS_MAIN(tst_QStringView)
#include "tst_qstringview.moc"
diff --git a/tests/auto/corelib/tools/qtimeline/BLACKLIST b/tests/auto/corelib/tools/qtimeline/BLACKLIST
index 74f84a4a6d..5611969b4d 100644
--- a/tests/auto/corelib/tools/qtimeline/BLACKLIST
+++ b/tests/auto/corelib/tools/qtimeline/BLACKLIST
@@ -1,7 +1,9 @@
[interpolation]
windows
osx-10.12
+osx-10.13
[duration]
windows
[frameRate]
osx-10.12
+osx-10.13
diff --git a/tests/auto/corelib/tools/qtimezone/qtimezone.pro b/tests/auto/corelib/tools/qtimezone/qtimezone.pro
index 19ebc13306..5ec8d008e7 100644
--- a/tests/auto/corelib/tools/qtimezone/qtimezone.pro
+++ b/tests/auto/corelib/tools/qtimezone/qtimezone.pro
@@ -3,7 +3,7 @@ TARGET = tst_qtimezone
QT = core-private testlib
SOURCES = tst_qtimezone.cpp
qtConfig(icu) {
- DEFINES += QT_USE_ICU
+ QMAKE_USE_PRIVATE += icu
}
darwin {
diff --git a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp
index ed80d4528d..d335dae7bc 100644
--- a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp
+++ b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp
@@ -31,6 +31,10 @@
#include <private/qtimezoneprivate_p.h>
#include <qlocale.h>
+#if defined(Q_OS_WIN) && !QT_CONFIG(icu)
+# define USING_WIN_TZ
+#endif
+
class tst_QTimeZone : public QObject
{
Q_OBJECT
@@ -413,7 +417,7 @@ void tst_QTimeZone::specificTransition_data()
QTest::addColumn<int>("dstoff");
// Moscow ditched DST on 2010-10-31 but has since changed standard offset twice.
-#ifdef Q_OS_WIN
+#ifdef USING_WIN_TZ
// Win7 is too old to know about this transition:
if (QOperatingSystemVersion::current() > QOperatingSystemVersion::Windows7)
#endif
@@ -477,8 +481,9 @@ void tst_QTimeZone::transitionEachZone_data()
};
QString name;
+ const auto zones = QTimeZone::availableTimeZoneIds();
for (int k = sizeof(table) / sizeof(table[0]); k-- > 0; ) {
- foreach (QByteArray zone, QTimeZone::availableTimeZoneIds()) {
+ for (const QByteArray &zone : zones) {
name.sprintf("%s@%d", zone.constData(), table[k].year);
QTest::newRow(name.toUtf8().constData())
<< zone
@@ -500,7 +505,7 @@ void tst_QTimeZone::transitionEachZone()
QTimeZone named(zone);
for (int i = start; i < stop; i++) {
-#ifdef Q_OS_WIN
+#ifdef USING_WIN_TZ
// See QTBUG-64985: MS's TZ APIs' misdescription of Europe/Samara leads
// to mis-disambiguation of its fall-back here.
if (QOperatingSystemVersion::current() <= QOperatingSystemVersion::Windows7
@@ -833,7 +838,7 @@ void tst_QTimeZone::utcTest()
void tst_QTimeZone::icuTest()
{
-#if defined(QT_BUILD_INTERNAL) && defined(QT_USE_ICU)
+#if defined(QT_BUILD_INTERNAL) && QT_CONFIG(icu)
// Known datetimes
qint64 std = QDateTime(QDate(2012, 1, 1), QTime(0, 0, 0), Qt::UTC).toMSecsSinceEpoch();
qint64 dst = QDateTime(QDate(2012, 6, 1), QTime(0, 0, 0), Qt::UTC).toMSecsSinceEpoch();
@@ -881,7 +886,7 @@ void tst_QTimeZone::icuTest()
testCetPrivate(tzp);
testEpochTranPrivate(QIcuTimeZonePrivate("America/Toronto"));
-#endif // QT_USE_ICU
+#endif // icu
}
void tst_QTimeZone::tzTest()
@@ -907,7 +912,7 @@ void tst_QTimeZone::tzTest()
QLocale enUS("en_US");
// Only test names in debug mode, names used can vary by ICU version installed
if (debug) {
-#ifdef QT_USE_ICU
+#if QT_CONFIG(icu)
QCOMPARE(tzp.displayName(QTimeZone::StandardTime, QTimeZone::LongName, enUS),
QString("Central European Standard Time"));
QCOMPARE(tzp.displayName(QTimeZone::StandardTime, QTimeZone::ShortName, enUS),
@@ -946,7 +951,7 @@ void tst_QTimeZone::tzTest()
QString("CET"));
QCOMPARE(tzp.displayName(QTimeZone::GenericTime, QTimeZone::OffsetName, enUS),
QString("CET"));
-#endif // QT_USE_ICU
+#endif // icu
// Test Abbreviations
QCOMPARE(tzp.abbreviation(std), QString("CET"));
@@ -1123,7 +1128,7 @@ void tst_QTimeZone::darwinTypes()
void tst_QTimeZone::winTest()
{
-#if defined(QT_BUILD_INTERNAL) && defined(Q_OS_WIN)
+#if defined(QT_BUILD_INTERNAL) && defined(USING_WIN_TZ)
// Known datetimes
qint64 std = QDateTime(QDate(2012, 1, 1), QTime(0, 0, 0), Qt::UTC).toMSecsSinceEpoch();
qint64 dst = QDateTime(QDate(2012, 6, 1), QTime(0, 0, 0), Qt::UTC).toMSecsSinceEpoch();
@@ -1174,7 +1179,7 @@ void tst_QTimeZone::winTest()
testCetPrivate(tzp);
testEpochTranPrivate(QWinTimeZonePrivate("America/Toronto"));
-#endif // Q_OS_WIN
+#endif // QT_BUILD_INTERNAL && USING_WIN_TZ
}
#ifdef QT_BUILD_INTERNAL
@@ -1286,7 +1291,7 @@ void tst_QTimeZone::testEpochTranPrivate(const QTimeZonePrivate &tzp)
// 1970-04-26 02:00 EST, -5 -> -4
const QDateTime after = QDateTime(QDate(1970, 4, 26), QTime(2, 0), Qt::OffsetFromUTC, -5 * 3600);
const QDateTime found = QDateTime::fromMSecsSinceEpoch(tran.atMSecsSinceEpoch, Qt::UTC);
-#ifdef Q_OS_WIN // MS gets the date wrong: 5th April instead of 26th.
+#ifdef USING_WIN_TZ // MS gets the date wrong: 5th April instead of 26th.
QCOMPARE(found.toOffsetFromUtc(-5 * 3600).time(), after.time());
#else
QCOMPARE(found, after);
diff --git a/tests/auto/corelib/tools/tools.pro b/tests/auto/corelib/tools/tools.pro
index f35ed026ac..f28cf21b8b 100644
--- a/tests/auto/corelib/tools/tools.pro
+++ b/tests/auto/corelib/tools/tools.pro
@@ -30,6 +30,7 @@ SUBDIRS=\
qlist \
qlist_strictiterators \
qlocale \
+ qmakearray \
qmap \
qmap_strictiterators \
qmargins \
diff --git a/tests/auto/dbus/qdbusinterface/qdbusinterface/qdbusinterface.pro b/tests/auto/dbus/qdbusinterface/qdbusinterface/qdbusinterface.pro
index b7dedad133..67709105a6 100644
--- a/tests/auto/dbus/qdbusinterface/qdbusinterface/qdbusinterface.pro
+++ b/tests/auto/dbus/qdbusinterface/qdbusinterface/qdbusinterface.pro
@@ -4,4 +4,11 @@ HEADERS += ../myobject.h
TARGET = ../tst_qdbusinterface
DESTDIR = ./
-QT = core core-private dbus testlib
+QT = core core-private dbus dbus-private testlib
+
+qtConfig(dbus-linked) {
+ DEFINES += QT_LINKED_LIBDBUS
+ QMAKE_USE += dbus
+} else {
+ SOURCES += ../../../../../src/dbus/qdbus_symbols.cpp
+}
diff --git a/tests/auto/dbus/qdbusinterface/qmyserver/qmyserver.cpp b/tests/auto/dbus/qdbusinterface/qmyserver/qmyserver.cpp
index da24429b9e..535d2f756b 100644
--- a/tests/auto/dbus/qdbusinterface/qmyserver/qmyserver.cpp
+++ b/tests/auto/dbus/qdbusinterface/qmyserver/qmyserver.cpp
@@ -115,6 +115,16 @@ public slots:
return obj.m_complexProp;
}
+ bool interactiveAuthorization()
+ {
+ if (message().isInteractiveAuthorizationAllowed())
+ return true;
+
+ sendErrorReply(QStringLiteral("org.freedesktop.DBus.Error.InteractiveAuthorizationRequired"),
+ QStringLiteral("Interactive authentication required."));
+ return false;
+ }
+
void quit()
{
qApp->quit();
diff --git a/tests/auto/dbus/qdbusinterface/tst_qdbusinterface.cpp b/tests/auto/dbus/qdbusinterface/tst_qdbusinterface.cpp
index 5494959aaf..05480c6dd2 100644
--- a/tests/auto/dbus/qdbusinterface/tst_qdbusinterface.cpp
+++ b/tests/auto/dbus/qdbusinterface/tst_qdbusinterface.cpp
@@ -33,6 +33,7 @@
#include <QtTest/QtTest>
#include <QtCore/qvariant.h>
#include <QtDBus/QtDBus>
+#include <QtDBus/private/qdbus_symbols_p.h>
#include <qdebug.h>
#include "../qdbusmarshall/common.h"
#include "myobject.h"
@@ -213,6 +214,8 @@ private slots:
void propertyWritePeer();
void complexPropertyReadPeer();
void complexPropertyWritePeer();
+
+ void interactiveAuthorizationRequired();
private:
QProcess proc;
};
@@ -1127,6 +1130,30 @@ void tst_QDBusInterface::complexPropertyWritePeer()
QCOMPARE(complexPropPeer(), arg);
}
+void tst_QDBusInterface::interactiveAuthorizationRequired()
+{
+ int major;
+ int minor;
+ int micro;
+ q_dbus_get_version(&major, &minor, &micro);
+
+ QVersionNumber dbusVersion(major, minor, micro);
+ if (dbusVersion < QVersionNumber(1, 9, 2))
+ QSKIP("Your DBus library is too old to support interactive authorization");
+
+ QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "interactiveAuthorization");
+ QDBusMessage reply = QDBusConnection::sessionBus().call(req);
+
+ QCOMPARE(reply.type(), QDBusMessage::ErrorMessage);
+ QCOMPARE(reply.errorName(), QStringLiteral("org.freedesktop.DBus.Error.InteractiveAuthorizationRequired"));
+
+ req.setInteractiveAuthorizationAllowed(true);
+ reply = QDBusConnection::sessionBus().call(req);
+
+ QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
+ QVERIFY(reply.arguments().at(0).toBool());
+}
+
QTEST_MAIN(tst_QDBusInterface)
#include "tst_qdbusinterface.moc"
diff --git a/tests/auto/gui/gui.pro b/tests/auto/gui/gui.pro
index d7cda11513..e0c8123f26 100644
--- a/tests/auto/gui/gui.pro
+++ b/tests/auto/gui/gui.pro
@@ -14,6 +14,6 @@ SUBDIRS = \
util \
itemmodels \
-!qtConfig(opengl): SUBDIRS -= qopengl qopenglconfig
+!qtConfig(opengl)|winrt: SUBDIRS -= qopengl qopenglconfig
!qtConfig(vulkan): SUBDIRS -= qvulkan
diff --git a/tests/auto/gui/image/qimage/images/jpeg_exif_utf8_comment.jpg b/tests/auto/gui/image/qimage/images/jpeg_exif_utf8_comment.jpg
new file mode 100644
index 0000000000..42b305f5b8
--- /dev/null
+++ b/tests/auto/gui/image/qimage/images/jpeg_exif_utf8_comment.jpg
Binary files differ
diff --git a/tests/auto/gui/image/qimage/qimage.pro b/tests/auto/gui/image/qimage/qimage.pro
index 56618e0bfa..b40866892e 100644
--- a/tests/auto/gui/image/qimage/qimage.pro
+++ b/tests/auto/gui/image/qimage/qimage.pro
@@ -7,4 +7,7 @@ qtConfig(c++11): CONFIG += c++11
android:!android-embedded: RESOURCES += qimage.qrc
+win32:!winrt: LIBS += -lgdi32 -luser32
+darwin: LIBS += -framework CoreGraphics
+
TESTDATA += images/*
diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp
index 34b20a5cca..5ffd75f931 100644
--- a/tests/auto/gui/image/qimage/tst_qimage.cpp
+++ b/tests/auto/gui/image/qimage/tst_qimage.cpp
@@ -44,6 +44,10 @@
#include <CoreGraphics/CoreGraphics.h>
#endif
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+# include <qt_windows.h>
+#endif
+
Q_DECLARE_METATYPE(QImage::Format)
Q_DECLARE_METATYPE(Qt::GlobalColor)
@@ -116,6 +120,7 @@ private slots:
void smoothScale2();
void smoothScale3_data();
void smoothScale3();
+ void smoothScale4_data();
void smoothScale4();
void smoothScaleBig();
@@ -192,6 +197,7 @@ private slots:
void exif_QTBUG45865();
void exifInvalidData_data();
void exifInvalidData();
+ void exifReadComments();
void cleanupFunctions();
@@ -224,6 +230,11 @@ private slots:
void convertColorTable();
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+ void toWinHBITMAP_data();
+ void toWinHBITMAP();
+#endif // Q_OS_WIN && !Q_OS_WINRT
+
private:
const QString m_prefix;
};
@@ -281,6 +292,12 @@ static QLatin1String formatToString(QImage::Format format)
return QLatin1String("Alpha8");
case QImage::Format_Grayscale8:
return QLatin1String("Grayscale8");
+ case QImage::Format_RGBX64:
+ return QLatin1String("RGBx64");
+ case QImage::Format_RGBA64:
+ return QLatin1String("RGBA64");
+ case QImage::Format_RGBA64_Premultiplied:
+ return QLatin1String("RGBA64pm");
default:
break;
};
@@ -1665,29 +1682,30 @@ void tst_QImage::smoothScale()
// test area sampling
void tst_QImage::smoothScale2_data()
{
- QTest::addColumn<int>("format");
+ QTest::addColumn<QImage::Format>("format");
QTest::addColumn<int>("size");
int sizes[] = { 2, 3, 4, 6, 7, 8, 10, 16, 20, 32, 40, 64, 100, 101, 128, 0 };
- QImage::Format formats[] = { QImage::Format_RGB32, QImage::Format_ARGB32_Premultiplied, QImage::Format_Invalid };
+ QImage::Format formats[] = { QImage::Format_RGB32, QImage::Format_ARGB32_Premultiplied, QImage::Format_RGBX64, QImage::Format_RGBA64_Premultiplied, QImage::Format_Invalid };
for (int j = 0; formats[j] != QImage::Format_Invalid; ++j) {
- QByteArray formatstr = formats[j] == QImage::Format_RGB32 ? QByteArrayLiteral("rgb32") : QByteArrayLiteral("argb32pm");
+ QString formatstr = formatToString(formats[j]);
for (int i = 0; sizes[i] != 0; ++i) {
const QByteArray sizeB = QByteArray::number(sizes[i]);
- QTest::newRow((formatstr + ' ' + sizeB + 'x' + sizeB).constData())
- << (int)formats[j] << sizes[i];
+ QTest::newRow(QString("%1 %2x%2").arg(formatstr).arg(sizes[i]).toUtf8()) << formats[j] << sizes[i];
}
}
}
void tst_QImage::smoothScale2()
{
- QFETCH(int, format);
+ QFETCH(QImage::Format, format);
QFETCH(int, size);
- QRgb expected = format == QImage::Format_RGB32 ? qRgb(63, 127, 255) : qRgba(31, 63, 127, 127);
+ bool opaque = (format == QImage::Format_RGB32 || format == QImage::Format_RGBX64);
- QImage img(size, size, (QImage::Format)format);
+ QRgb expected = opaque ? qRgb(63, 127, 255) : qRgba(31, 63, 127, 127);
+
+ QImage img(size, size, format);
img.fill(expected);
// scale x down, y down
@@ -1824,21 +1842,31 @@ void tst_QImage::smoothScale3()
}
// Tests smooth upscale is smooth
+void tst_QImage::smoothScale4_data()
+{
+ QTest::addColumn<QImage::Format>("format");
+
+ QTest::newRow("RGB32") << QImage::Format_RGB32;
+ QTest::newRow("RGBx64") << QImage::Format_RGBX64;
+}
+
void tst_QImage::smoothScale4()
{
- QImage img(4, 4, QImage::Format_RGB32);
+ QFETCH(QImage::Format, format);
+ QImage img(4, 4, format);
for (int y = 0; y < 4; ++y) {
for (int x = 0; x < 4; ++x) {
img.setPixel(x, y, qRgb(x * 255 / 3, y * 255 / 3, 0));
}
}
QImage scaled = img.scaled(37, 23, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ QCOMPARE(scaled.format(), format);
for (int y = 0; y < scaled.height(); ++y) {
for (int x = 0; x < scaled.width(); ++x) {
if (x > 0)
- QVERIFY(qRed(scaled.pixel(x, y)) >= qRed(scaled.pixel(x - 1, y)));
+ QVERIFY(scaled.pixelColor(x, y).redF() >= scaled.pixelColor(x - 1, y).redF());
if (y > 0)
- QVERIFY(qGreen(scaled.pixel(x, y)) >= qGreen(scaled.pixel(x, y - 1)));
+ QVERIFY(scaled.pixelColor(x, y).greenF() >= scaled.pixelColor(x, y - 1).greenF());
}
}
}
@@ -2337,7 +2365,9 @@ void tst_QImage::rgbSwapped_data()
{
QTest::addColumn<QImage::Format>("format");
- for (int i = QImage::Format_Indexed8; i < QImage::Format_Alpha8; ++i) {
+ for (int i = QImage::Format_Indexed8; i < QImage::NImageFormats; ++i) {
+ if (i == QImage::Format_Alpha8 || i == QImage::Format_Grayscale8)
+ continue;
QTest::addRow("%s", formatToString(QImage::Format(i)).data()) << QImage::Format(i);
}
}
@@ -2505,14 +2535,7 @@ void tst_QImage::mirrored()
void tst_QImage::inplaceRgbSwapped_data()
{
- QTest::addColumn<QImage::Format>("format");
-
- QTest::newRow("Format_ARGB32_Premultiplied") << QImage::Format_ARGB32_Premultiplied;
- QTest::newRow("Format_RGBA8888") << QImage::Format_RGBA8888;
- QTest::newRow("Format_A2RGB30_Premultiplied") << QImage::Format_A2RGB30_Premultiplied;
- QTest::newRow("Format_RGB888") << QImage::Format_RGB888;
- QTest::newRow("Format_RGB16") << QImage::Format_RGB16;
- QTest::newRow("Format_Indexed8") << QImage::Format_Indexed8;
+ rgbSwapped_data();
}
void tst_QImage::inplaceRgbSwapped()
@@ -2543,9 +2566,9 @@ void tst_QImage::inplaceRgbSwapped()
for (int i = 0; i < imageSwapped.width(); ++i) {
QRgb referenceColor = testColor[i];
QRgb swappedColor = imageSwapped.pixel(i, 0);
- QCOMPARE(qRed(swappedColor) & 0xf8, qBlue(referenceColor) & 0xf8);
- QCOMPARE(qGreen(swappedColor) & 0xf8, qGreen(referenceColor) & 0xf8);
- QCOMPARE(qBlue(swappedColor) & 0xf8, qRed(referenceColor) & 0xf8);
+ QCOMPARE(qRed(swappedColor) & 0xf0, qBlue(referenceColor) & 0xf0);
+ QCOMPARE(qGreen(swappedColor) & 0xf0, qGreen(referenceColor) & 0xf0);
+ QCOMPARE(qBlue(swappedColor) & 0xf0, qRed(referenceColor) & 0xf0);
}
QCOMPARE(imageSwapped.constScanLine(0), orginalPtr);
@@ -2761,9 +2784,13 @@ void tst_QImage::genericRgbConversion_data()
QTest::addColumn<QImage::Format>("format");
QTest::addColumn<QImage::Format>("dest_format");
- for (int i = QImage::Format_RGB32; i < QImage::Format_Alpha8; ++i) {
+ for (int i = QImage::Format_RGB32; i < QImage::NImageFormats; ++i) {
+ if (i == QImage::Format_Alpha8 || i == QImage::Format_Grayscale8)
+ continue;
const QLatin1String formatI = formatToString(QImage::Format(i));
- for (int j = QImage::Format_RGB32; j < QImage::Format_Alpha8; ++j) {
+ for (int j = QImage::Format_RGB32; j < QImage::NImageFormats; ++j) {
+ if (j == QImage::Format_Alpha8 || j == QImage::Format_Grayscale8)
+ continue;
if (i == j)
continue;
QTest::addRow("%s -> %s", formatI.data(), formatToString(QImage::Format(j)).data())
@@ -2800,8 +2827,12 @@ void tst_QImage::inplaceRgbConversion_data()
QTest::addColumn<QImage::Format>("format");
QTest::addColumn<QImage::Format>("dest_format");
- for (int i = QImage::Format_RGB32; i < QImage::Format_Alpha8; ++i) {
- for (int j = QImage::Format_RGB32; j < QImage::Format_Alpha8; ++j) {
+ for (int i = QImage::Format_RGB32; i < QImage::NImageFormats; ++i) {
+ if (i == QImage::Format_Alpha8 || i == QImage::Format_Grayscale8)
+ continue;
+ for (int j = QImage::Format_RGB32; j < QImage::NImageFormats; ++j) {
+ if (j == QImage::Format_Alpha8 || j == QImage::Format_Grayscale8)
+ continue;
if (i == j)
continue;
QTest::addRow("%s -> %s", formatToString(QImage::Format(i)).data(), formatToString(QImage::Format(j)).data())
@@ -2834,10 +2865,10 @@ void tst_QImage::inplaceRgbConversion()
QCOMPARE(qGreen(convertedColor) & 0xF0, i * 16);
}
}
- if (image.depth() == imageConverted.depth())
+ if (qt_depthForFormat(format) == qt_depthForFormat(dest_format))
QCOMPARE(imageConverted.constScanLine(0), originalPtr);
- {
+ if (qt_depthForFormat(format) <= 32) {
// Test attempted inplace conversion of images created on existing buffer
static const quint32 readOnlyData[] = { 0xff0102ffU, 0xff0506ffU, 0xff0910ffU, 0xff1314ffU };
quint32 readWriteData[] = { 0xff0102ffU, 0xff0506ffU, 0xff0910ffU, 0xff1314ffU };
@@ -2970,7 +3001,9 @@ void tst_QImage::invertPixelsRGB_data()
{
QTest::addColumn<QImage::Format>("image_format");
- for (int i = QImage::Format_RGB32; i < QImage::Format_Alpha8; ++i) {
+ for (int i = QImage::Format_RGB32; i < QImage::NImageFormats; ++i) {
+ if (i == QImage::Format_Alpha8 || i == QImage::Format_Grayscale8)
+ continue;
QTest::addRow("%s", formatToString(QImage::Format(i)).data()) << QImage::Format(i);
}
}
@@ -3068,6 +3101,34 @@ void tst_QImage::exifInvalidData()
QVERIFY(!image.isNull());
}
+void tst_QImage::exifReadComments()
+{
+ QImage image;
+ QVERIFY(image.load(m_prefix + "jpeg_exif_utf8_comment.jpg"));
+ QVERIFY(!image.isNull());
+ QCOMPARE(image.textKeys().size(), 1);
+ QCOMPARE(image.textKeys().first(), "Description");
+ // check if exif comment is read as utf-8
+ QCOMPARE(image.text("Description"), QString::fromUtf8("some unicode chars: ÖÄÜ€@"));
+
+ QByteArray ba;
+ {
+ QBuffer buf(&ba);
+ QVERIFY(buf.open(QIODevice::WriteOnly));
+ QVERIFY(image.save(&buf, "JPG"));
+ }
+ QVERIFY(!ba.isEmpty());
+ image = QImage();
+ QCOMPARE(image.textKeys().size(), 0);
+ {
+ QBuffer buf(&ba);
+ QVERIFY(buf.open(QIODevice::ReadOnly));
+ QVERIFY(image.load(&buf, "JPG"));
+ }
+ // compare written (and reread) description text
+ QCOMPARE(image.text("Description"), QString::fromUtf8("some unicode chars: ÖÄÜ€@"));
+}
+
static void cleanupFunction(void* info)
{
bool *called = static_cast<bool*>(info);
@@ -3473,5 +3534,108 @@ void tst_QImage::convertColorTable()
QCOMPARE(rgb32.pixel(0,0), 0xffffffff);
}
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+QT_BEGIN_NAMESPACE
+Q_GUI_EXPORT HBITMAP qt_imageToWinHBITMAP(const QImage &p, int hbitmapFormat = 0);
+Q_GUI_EXPORT QImage qt_imageFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0);
+QT_END_NAMESPACE
+
+static inline QColor COLORREFToQColor(COLORREF cr)
+{
+ return QColor(GetRValue(cr), GetGValue(cr), GetBValue(cr));
+}
+
+void tst_QImage::toWinHBITMAP_data()
+{
+ QTest::addColumn<QImage::Format>("format");
+ QTest::addColumn<QColor>("color");
+ QTest::addColumn<QColor>("bottomRightColor");
+
+ const QColor red(Qt::red);
+ const QColor green(Qt::green);
+ const QColor blue(Qt::blue);
+ const QColor gray(Qt::gray);
+ const QColor gray555(0x5a, 0x5a, 0x5a); // Note: Interpolation 8<->5 bit occurs.
+ const QColor white(Qt::white);
+ const QColor black(Qt::black);
+
+ QTest::newRow("argb32p-red") << QImage::Format_ARGB32_Premultiplied << red << gray;
+ QTest::newRow("argb32p-green") << QImage::Format_ARGB32_Premultiplied << green << gray;
+ QTest::newRow("argb32p-blue") << QImage::Format_ARGB32_Premultiplied << blue << gray;
+ QTest::newRow("rgb888-red") << QImage::Format_RGB888 << red << gray;
+ QTest::newRow("rgb888-green") << QImage::Format_RGB888 << green << gray;
+ QTest::newRow("rgb888-blue") << QImage::Format_RGB888 << blue << gray;
+ QTest::newRow("indexed8-red") << QImage::Format_Indexed8 << red << gray;
+ QTest::newRow("indexed8-green") << QImage::Format_Indexed8 << green << gray;
+ QTest::newRow("indexed8-blue") << QImage::Format_Indexed8 << blue << gray;
+ QTest::newRow("rgb555-red") << QImage::Format_RGB555 << red << gray555;
+ QTest::newRow("rgb555-green") << QImage::Format_RGB555 << green << gray555;
+ QTest::newRow("rgb555-blue") << QImage::Format_RGB555 << blue << gray555;
+ QTest::newRow("mono") << QImage::Format_Mono << white << black;
+}
+
+// Test image filled with color, black pixel at botttom right corner.
+static inline QImage createTestImage(QImage::Format format, int width, int height,
+ const QColor &fillColor, const QColor &bottomRightColor)
+{
+ QImage image(QSize(width, height), format);
+ image.fill(fillColor);
+ QPainter painter(&image);
+ QPen pen = painter.pen();
+ pen.setColor(bottomRightColor);
+ painter.setPen(pen);
+ painter.drawPoint(width -1, height - 1);
+ return image;
+}
+
+void tst_QImage::toWinHBITMAP()
+{
+ static const int width = 73;
+ static const int height = 57;
+
+ QFETCH(QImage::Format, format);
+ QFETCH(QColor, color);
+ QFETCH(QColor, bottomRightColor);
+
+ // Cannot paint on indexed/mono images.
+ const QImage image = format == QImage::Format_Indexed8 || format == QImage::Format_Mono
+ ? createTestImage(QImage::Format_RGB32, width, height, color, bottomRightColor).convertToFormat(format)
+ : createTestImage(format, width, height, color, bottomRightColor);
+
+ const HBITMAP bitmap = qt_imageToWinHBITMAP(image);
+
+ QVERIFY(bitmap != 0);
+
+ // Verify size
+ BITMAP bitmapInfo;
+ memset(&bitmapInfo, 0, sizeof(BITMAP));
+
+ const int res = GetObject(bitmap, sizeof(BITMAP), &bitmapInfo);
+ QVERIFY(res);
+ QCOMPARE(width, int(bitmapInfo.bmWidth));
+ QCOMPARE(height, int(bitmapInfo.bmHeight));
+
+ const HDC displayDc = GetDC(0);
+ const HDC bitmapDc = CreateCompatibleDC(displayDc);
+
+ const HBITMAP nullBitmap = static_cast<HBITMAP>(SelectObject(bitmapDc, bitmap));
+
+ QCOMPARE(COLORREFToQColor(GetPixel(bitmapDc, 0, 0)), color);
+ QCOMPARE(COLORREFToQColor(GetPixel(bitmapDc, width - 1, 3)), color);
+ QCOMPARE(COLORREFToQColor(GetPixel(bitmapDc, 3, height - 1)), color);
+ QCOMPARE(COLORREFToQColor(GetPixel(bitmapDc, width - 1, height - 1)), bottomRightColor);
+
+ const QImage convertedBack = qt_imageFromWinHBITMAP(bitmap);
+ QCOMPARE(convertedBack.convertToFormat(QImage::Format_ARGB32_Premultiplied),
+ image.convertToFormat(QImage::Format_ARGB32_Premultiplied));
+
+ // Clean up
+ SelectObject(bitmapDc, nullBitmap);
+ DeleteObject(bitmap);
+ DeleteDC(bitmapDc);
+ ReleaseDC(0, displayDc);
+}
+#endif // Q_OS_WIN && !Q_OS_WINRT
+
QTEST_GUILESS_MAIN(tst_QImage)
#include "tst_qimage.moc"
diff --git a/tests/auto/gui/image/qimagereader/images/basn0g16.png b/tests/auto/gui/image/qimagereader/images/basn0g16.png
new file mode 100644
index 0000000000..318ebcadf4
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/basn0g16.png
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/basn2c16.png b/tests/auto/gui/image/qimagereader/images/basn2c16.png
new file mode 100644
index 0000000000..1bd4a4d0e2
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/basn2c16.png
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/basn4a16.png b/tests/auto/gui/image/qimagereader/images/basn4a16.png
new file mode 100644
index 0000000000..6dbee9fbdb
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/basn4a16.png
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/basn6a16.png b/tests/auto/gui/image/qimagereader/images/basn6a16.png
new file mode 100644
index 0000000000..a9bf3cb461
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/basn6a16.png
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/kollada-16bpc.png b/tests/auto/gui/image/qimagereader/images/kollada-16bpc.png
new file mode 100644
index 0000000000..b99d5f8a6f
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/kollada-16bpc.png
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/images/tbwn0g16.png b/tests/auto/gui/image/qimagereader/images/tbwn0g16.png
new file mode 100644
index 0000000000..99bdeed2b3
--- /dev/null
+++ b/tests/auto/gui/image/qimagereader/images/tbwn0g16.png
Binary files differ
diff --git a/tests/auto/gui/image/qimagereader/qimagereader.pro b/tests/auto/gui/image/qimagereader/qimagereader.pro
index b06f56dddf..623d45ffe2 100644
--- a/tests/auto/gui/image/qimagereader/qimagereader.pro
+++ b/tests/auto/gui/image/qimagereader/qimagereader.pro
@@ -3,7 +3,8 @@ TARGET = tst_qimagereader
SOURCES += tst_qimagereader.cpp
MOC_DIR=tmp
QT += core-private gui-private network testlib
-RESOURCES += qimagereader.qrc
+
+RESOURCES += $$files(images/*)
android:!android-embedded {
RESOURCES += android_testdata.qrc
diff --git a/tests/auto/gui/image/qimagereader/qimagereader.qrc b/tests/auto/gui/image/qimagereader/qimagereader.qrc
deleted file mode 100644
index 2522154b1f..0000000000
--- a/tests/auto/gui/image/qimagereader/qimagereader.qrc
+++ /dev/null
@@ -1,69 +0,0 @@
-<RCC>
- <qresource prefix="/">
- <file>images/16bpp.bmp</file>
- <file>images/4bpp-rle.bmp</file>
- <file>images/YCbCr_cmyk.jpg</file>
- <file>images/YCbCr_cmyk.png</file>
- <file>images/YCbCr_rgb.jpg</file>
- <file>images/away.png</file>
- <file>images/bat1.gif</file>
- <file>images/bat2.gif</file>
- <file>images/beavis.jpg</file>
- <file>images/black.png</file>
- <file>images/black.xpm</file>
- <file>images/colorful.bmp</file>
- <file>images/corrupt-colors.xpm</file>
- <file>images/corrupt-pixels.xpm</file>
- <file>images/corrupt.bmp</file>
- <file>images/corrupt.gif</file>
- <file>images/corrupt.jpg</file>
- <file>images/corrupt.png</file>
- <file>images/corrupt.xbm</file>
- <file>images/crash-signed-char.bmp</file>
- <file>images/earth.gif</file>
- <file>images/font.bmp</file>
- <file>images/gnus.xbm</file>
- <file>images/image.pbm</file>
- <file>images/image.pgm</file>
- <file>images/image.png</file>
- <file>images/image.ppm</file>
- <file>images/kollada.png</file>
- <file>images/marble.xpm</file>
- <file>images/namedcolors.xpm</file>
- <file>images/negativeheight.bmp</file>
- <file>images/noclearcode.bmp</file>
- <file>images/noclearcode.gif</file>
- <file>images/nontransparent.xpm</file>
- <file>images/rgb32bf.bmp</file>
- <file>images/runners.ppm</file>
- <file>images/teapot.ppm</file>
- <file>images/test.ppm</file>
- <file>images/test.xpm</file>
- <file>images/test32bfv4.bmp</file>
- <file>images/test32v5.bmp</file>
- <file>images/tst7.bmp</file>
- <file>images/tst7.png</file>
- <file>images/transparent.xpm</file>
- <file>images/trolltech.gif</file>
- <file>images/qt.gif</file>
- <file>images/qt1.gif</file>
- <file>images/qt2.gif</file>
- <file>images/qt3.gif</file>
- <file>images/qt4.gif</file>
- <file>images/qt5.gif</file>
- <file>images/qt6.gif</file>
- <file>images/qt7.gif</file>
- <file>images/qt8.gif</file>
- <file>images/endless-anim.gif</file>
- <file>images/four-frames.gif</file>
- <file>images/qt-gif-anim.gif</file>
- <file>images/qt-gif-noanim.gif</file>
- <file>images/rect.svg</file>
- <file>images/rect.svgz</file>
- <file>images/corrupt.svg</file>
- <file>images/corrupt.svgz</file>
- <file>images/qtbug13653-no_eoi.jpg</file>
- <file>images/txts.jpg</file>
- <file>images/txts.png</file>
- </qresource>
-</RCC>
diff --git a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp
index 170f551dbf..c2ec5b8925 100644
--- a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp
+++ b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp
@@ -234,6 +234,7 @@ void tst_QImageReader::readImage_data()
QTest::newRow("BMP: high mask bit set") << QString("rgb32bf.bmp") << true << QByteArray("bmp");
QTest::newRow("XPM: marble") << QString("marble.xpm") << true << QByteArray("xpm");
QTest::newRow("PNG: kollada") << QString("kollada.png") << true << QByteArray("png");
+ QTest::newRow("PNG: kollada 16bpc") << QString("kollada-16bpc.png") << true << QByteArray("png");
QTest::newRow("PPM: teapot") << QString("teapot.ppm") << true << QByteArray("ppm");
QTest::newRow("PPM: runners") << QString("runners.ppm") << true << QByteArray("ppm");
QTest::newRow("PPM: test") << QString("test.ppm") << true << QByteArray("ppm");
@@ -523,6 +524,12 @@ void tst_QImageReader::imageFormat_data()
QTest::newRow("bmp-4") << QString("test32v5.bmp") << QByteArray("bmp") << QImage::Format_RGB32;
QTest::newRow("png") << QString("kollada.png") << QByteArray("png") << QImage::Format_ARGB32;
QTest::newRow("png-2") << QString("YCbCr_cmyk.png") << QByteArray("png") << QImage::Format_RGB32;
+ QTest::newRow("png-3") << QString("kollada-16bpc.png") << QByteArray("png") << QImage::Format_RGBA64;
+ QTest::newRow("png-4") << QString("basn0g16.png") << QByteArray("png") << QImage::Format_RGBX64; // Grayscale16
+ QTest::newRow("png-5") << QString("basn2c16.png") << QByteArray("png") << QImage::Format_RGBX64;
+ QTest::newRow("png-6") << QString("basn4a16.png") << QByteArray("png") << QImage::Format_RGBA64; // Grayscale16Alpha16
+ QTest::newRow("png-7") << QString("basn6a16.png") << QByteArray("png") << QImage::Format_RGBA64;
+ QTest::newRow("png-8") << QString("tbwn0g16.png") << QByteArray("png") << QImage::Format_RGBA64; // Grayscale16+tRNS
QTest::newRow("svg") << QString("rect.svg") << QByteArray("svg") << QImage::Format_ARGB32_Premultiplied;
QTest::newRow("svgz") << QString("rect.svgz") << QByteArray("svgz") << QImage::Format_ARGB32_Premultiplied;
}
@@ -1596,6 +1603,7 @@ void tst_QImageReader::supportsOption_data()
<< (QIntList() << QImageIOHandler::Gamma
<< QImageIOHandler::Description
<< QImageIOHandler::Quality
+ << QImageIOHandler::CompressionRatio
<< QImageIOHandler::Size
<< QImageIOHandler::ScaledSize);
}
@@ -1850,6 +1858,8 @@ void tst_QImageReader::saveFormat_data()
QTest::newRow("Format_RGB888") << QImage::Format_RGB888;
QTest::newRow("Format_RGB444") << QImage::Format_RGB444;
QTest::newRow("Format_ARGB4444_Premultiplied") << QImage::Format_ARGB4444_Premultiplied;
+ QTest::newRow("Format_RGBA64") << QImage::Format_RGBA64;
+ QTest::newRow("Format_RGBA64_Premultiplied") << QImage::Format_RGBA64_Premultiplied;
}
void tst_QImageReader::saveFormat()
diff --git a/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp
index a53c2ddb5b..77851cd7d0 100644
--- a/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp
+++ b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp
@@ -408,6 +408,7 @@ void tst_QImageWriter::supportsOption_data()
<< (QIntList() << QImageIOHandler::Gamma
<< QImageIOHandler::Description
<< QImageIOHandler::Quality
+ << QImageIOHandler::CompressionRatio
<< QImageIOHandler::Size
<< QImageIOHandler::ScaledSize);
}
diff --git a/tests/auto/gui/image/qpicture/qpicture.pro b/tests/auto/gui/image/qpicture/qpicture.pro
index 0fc851ce11..7f967f33b9 100644
--- a/tests/auto/gui/image/qpicture/qpicture.pro
+++ b/tests/auto/gui/image/qpicture/qpicture.pro
@@ -1,7 +1,6 @@
CONFIG += testcase
TARGET = tst_qpicture
QT += testlib
-qtHaveModule(widgets): QT += widgets
SOURCES += tst_qpicture.cpp
diff --git a/tests/auto/gui/image/qpicture/tst_qpicture.cpp b/tests/auto/gui/image/qpicture/tst_qpicture.cpp
index 5c812fd1b2..ec6bb8dcee 100644
--- a/tests/auto/gui/image/qpicture/tst_qpicture.cpp
+++ b/tests/auto/gui/image/qpicture/tst_qpicture.cpp
@@ -33,10 +33,8 @@
#include <qpainter.h>
#include <qimage.h>
#include <qpaintengine.h>
-#ifndef QT_NO_WIDGETS
-#include <qdesktopwidget.h>
-#include <qapplication.h>
-#endif
+#include <qguiapplication.h>
+#include <qscreen.h>
#include <limits.h>
class tst_QPicture : public QObject
@@ -53,11 +51,7 @@ private slots:
void boundingRect();
void swap();
void serialization();
-
-#ifndef QT_NO_WIDGETS
void save_restore();
-#endif
-
void boundaryValues_data();
void boundaryValues();
};
@@ -244,30 +238,23 @@ void tst_QPicture::serialization()
}
}
-
-#ifndef QT_NO_WIDGETS
-static QPointF scalePoint(const QPointF &point, QPaintDevice *sourceDevice, QPaintDevice *destDevice)
-{
- return QPointF(point.x() * qreal(destDevice->logicalDpiX()) / qreal(sourceDevice->logicalDpiX()),
- point.y() * qreal(destDevice->logicalDpiY()) / qreal(sourceDevice->logicalDpiY()));
-}
-
-static QRectF scaleRect(const QRectF &rect, QPaintDevice *sourceDevice, QPaintDevice *destDevice)
+static QRectF scaleRect(const QRectF &rect, qreal xf, qreal yf)
{
- return QRectF(rect.left() * qreal(destDevice->logicalDpiX()) / qreal(sourceDevice->logicalDpiX()),
- rect.top() * qreal(destDevice->logicalDpiY()) / qreal(sourceDevice->logicalDpiY()),
- rect.width() * qreal(destDevice->logicalDpiX()) / qreal(sourceDevice->logicalDpiX()),
- rect.height() * qreal(destDevice->logicalDpiY()) / qreal(sourceDevice->logicalDpiY()));
+ return QRectF(rect.left() * xf, rect.top() * yf, rect.width() * xf, rect.height() * yf);
}
static void paintStuff(QPainter *p)
{
- QPaintDevice *screenDevice = QApplication::desktop();
- p->drawRect(scaleRect(QRectF(100, 100, 100, 100), screenDevice, p->device()));
+ const QScreen *screen = QGuiApplication::primaryScreen();
+ // Calculate factors from the screen resolution against QPicture's 96DPI
+ // (enforced by Qt::AA_Use96Dpi as set by QTEST_MAIN).
+ const qreal xf = qreal(p->device()->logicalDpiX()) / screen->logicalDotsPerInchX();
+ const qreal yf = qreal(p->device()->logicalDpiY()) / screen->logicalDotsPerInchY();
+ p->drawRect(scaleRect(QRectF(100, 100, 100, 100), xf, yf));
p->save();
- p->translate(scalePoint(QPointF(10, 10), screenDevice, p->device()));
+ p->translate(10 * xf, 10 * yf);
p->restore();
- p->drawRect(scaleRect(QRectF(100, 100, 100, 100), screenDevice, p->device()));
+ p->drawRect(scaleRect(QRectF(100, 100, 100, 100), xf, yf));
}
/* See task: 41469
@@ -298,7 +285,6 @@ void tst_QPicture::save_restore()
QVERIFY( pix1.toImage() == pix2.toImage() );
}
-#endif
void tst_QPicture::boundaryValues_data()
{
diff --git a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp
index e3bda6c2df..9a338ad55a 100644
--- a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp
+++ b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp
@@ -90,6 +90,7 @@ private slots:
void mask();
void bitmapMask();
+ void bitmapFromImageRvalue();
void setGetMask_data();
void setGetMask();
void cacheKey();
@@ -596,6 +597,27 @@ void tst_QPixmap::bitmapMask()
QVERIFY(image.pixel(1, 1));
}
+void tst_QPixmap::bitmapFromImageRvalue()
+{
+ auto makeImage = [](){
+ QImage image(3, 3, QImage::Format_MonoLSB);
+ image.setColor(0, Qt::color0);
+ image.setColor(1, Qt::color1);
+ image.fill(Qt::color0);
+ image.setPixel(1, 1, Qt::color1);
+ image.setPixel(0, 0, Qt::color1);
+ return image;
+ };
+
+ auto image1 = makeImage();
+ auto image2 = makeImage();
+ auto bitmap1 = QBitmap::fromImage(image1);
+ auto bitmap2 = QBitmap::fromImage(std::move(image2));
+ QCOMPARE(bitmap1.toImage(), bitmap2.toImage());
+ QVERIFY(!image1.isNull());
+ QVERIFY(image2.isNull());
+}
+
void tst_QPixmap::setGetMask_data()
{
QTest::addColumn<QPixmap>("pixmap");
diff --git a/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp b/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp
index 8a2a35f86c..158530428d 100644
--- a/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp
+++ b/tests/auto/gui/image/qpixmapcache/tst_qpixmapcache.cpp
@@ -92,6 +92,9 @@ void tst_QPixmapCache::cacheLimit()
// it was between 2048 and 10240 last time I looked at it
QVERIFY(originalCacheLimit >= 1024 && originalCacheLimit <= 20480);
+ QPixmapCache::setCacheLimit(std::numeric_limits<int>::max());
+ QCOMPARE(QPixmapCache::cacheLimit(), std::numeric_limits<int>::max());
+
QPixmapCache::setCacheLimit(100);
QCOMPARE(QPixmapCache::cacheLimit(), 100);
diff --git a/tests/auto/gui/itemmodels/qstandarditem/tst_qstandarditem.cpp b/tests/auto/gui/itemmodels/qstandarditem/tst_qstandarditem.cpp
index a45539a041..d19aa9b54f 100644
--- a/tests/auto/gui/itemmodels/qstandarditem/tst_qstandarditem.cpp
+++ b/tests/auto/gui/itemmodels/qstandarditem/tst_qstandarditem.cpp
@@ -69,8 +69,20 @@ private slots:
void sortChildren();
void subclassing();
void lessThan();
+ void clearData();
};
+void tst_QStandardItem::clearData()
+{
+ QStandardItem item;
+ item.setData(QStringLiteral("Test"), Qt::EditRole);
+ item.setData(5, Qt::UserRole);
+ item.clearData();
+ QCOMPARE(item.data(Qt::EditRole), QVariant());
+ QCOMPARE(item.data(Qt::UserRole), QVariant());
+ QCOMPARE(item.data(Qt::DisplayRole), QVariant());
+}
+
void tst_QStandardItem::ctor()
{
QStandardItem item;
diff --git a/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp b/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp
index 9399ebce34..e2d7a41bd1 100644
--- a/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp
+++ b/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp
@@ -98,6 +98,7 @@ private slots:
void checkChildren();
void data();
void clear();
+ void clearItemData();
void sort_data();
void sort();
void sortRole_data();
@@ -749,7 +750,32 @@ void tst_QStandardItemModel::data()
QCOMPARE(m_model->data(m_model->index(0, 0), Qt::DisplayRole).toString(), QLatin1String("initialitem"));
QCOMPARE(m_model->data(m_model->index(0, 0), Qt::ToolTipRole).toString(), QLatin1String("tooltip"));
+ const QMap<int, QVariant> itmData = m_model->itemData(m_model->index(0, 0));
+ QCOMPARE(itmData.value(Qt::DisplayRole), QLatin1String("initialitem"));
+ QCOMPARE(itmData.value(Qt::ToolTipRole), QLatin1String("tooltip"));
+ QVERIFY(!itmData.contains(Qt::UserRole - 1));
+ QVERIFY(m_model->itemData(QModelIndex()).isEmpty());
+}
+void tst_QStandardItemModel::clearItemData()
+{
+ currentRoles.clear();
+ QVERIFY(!m_model->clearItemData(QModelIndex()));
+ QCOMPARE(currentRoles, {});
+ const QModelIndex idx = m_model->index(0, 0);
+ const QMap<int, QVariant> oldData = m_model->itemData(idx);
+ m_model->setData(idx, QLatin1String("initialitem"), Qt::DisplayRole);
+ m_model->setData(idx, QLatin1String("tooltip"), Qt::ToolTipRole);
+ m_model->setData(idx, 5, Qt::UserRole);
+ currentRoles.clear();
+ QVERIFY(m_model->clearItemData(idx));
+ QCOMPARE(idx.data(Qt::UserRole), QVariant());
+ QCOMPARE(idx.data(Qt::ToolTipRole), QVariant());
+ QCOMPARE(idx.data(Qt::DisplayRole), QVariant());
+ QCOMPARE(idx.data(Qt::EditRole), QVariant());
+ QCOMPARE(currentRoles, {});
+ m_model->setItemData(idx, oldData);
+ currentRoles.clear();
}
void tst_QStandardItemModel::clear()
diff --git a/tests/auto/gui/kernel/qguiapplication/BLACKLIST b/tests/auto/gui/kernel/qguiapplication/BLACKLIST
new file mode 100644
index 0000000000..9a670237b7
--- /dev/null
+++ b/tests/auto/gui/kernel/qguiapplication/BLACKLIST
@@ -0,0 +1,4 @@
+[focusObject]
+opensuse
+opensuse-leap
+ubuntu
diff --git a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp
index fc011d726d..a304981cd1 100644
--- a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp
+++ b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp
@@ -374,6 +374,9 @@ public:
void tst_QGuiApplication::changeFocusWindow()
{
+#ifdef Q_OS_WINRT
+ QSKIP("WinRt does not support multiple native windows.");
+#endif
int argc = 0;
QGuiApplication app(argc, 0);
@@ -594,6 +597,9 @@ public:
void tst_QGuiApplication::modalWindow()
{
+#ifdef Q_OS_WINRT
+ QSKIP("WinRt does not support multiple native windows.");
+#endif
int argc = 0;
QGuiApplication app(argc, 0);
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
diff --git a/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp b/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp
index ca6f677ba6..a0ac1b3631 100644
--- a/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp
+++ b/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp
@@ -67,9 +67,10 @@ void tst_QPalette::roleValues_data()
QTest::newRow("QPalette::NoRole") << int(QPalette::NoRole) << 17;
QTest::newRow("QPalette::ToolTipBase") << int(QPalette::ToolTipBase) << 18;
QTest::newRow("QPalette::ToolTipText") << int(QPalette::ToolTipText) << 19;
+ QTest::newRow("QPalette::PlaceholderText") << int(QPalette::PlaceholderText) << 20;
// Change this value as you add more roles.
- QTest::newRow("QPalette::NColorRoles") << int(QPalette::NColorRoles) << 20;
+ QTest::newRow("QPalette::NColorRoles") << int(QPalette::NColorRoles) << 21;
}
void tst_QPalette::roleValues()
diff --git a/tests/auto/gui/kernel/qtouchevent/qtouchevent.pro b/tests/auto/gui/kernel/qtouchevent/qtouchevent.pro
index b1e3c10724..8506a005bc 100644
--- a/tests/auto/gui/kernel/qtouchevent/qtouchevent.pro
+++ b/tests/auto/gui/kernel/qtouchevent/qtouchevent.pro
@@ -1,5 +1,4 @@
CONFIG += testcase
-osx: CONFIG += insignificant_test # QTBUG-46266, crashes
SOURCES=tst_qtouchevent.cpp
TARGET=tst_qtouchevent
QT += testlib widgets gui-private
diff --git a/tests/auto/gui/kernel/qwindow/BLACKLIST b/tests/auto/gui/kernel/qwindow/BLACKLIST
index df02b5b33e..e9a0d44ba7 100644
--- a/tests/auto/gui/kernel/qwindow/BLACKLIST
+++ b/tests/auto/gui/kernel/qwindow/BLACKLIST
@@ -1,12 +1,14 @@
[positioning:default]
linux
osx-10.12 ci
+winrt
[positioning:fake]
osx-10.12 ci
[modalWithChildWindow]
ubuntu-16.04
# QTBUG-66851
opensuse
+opensuse-leap
# QTBUG-69160
android
[setVisible]
diff --git a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp
index 722405377e..9415908383 100644
--- a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp
+++ b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp
@@ -29,6 +29,7 @@
#include <qrasterwindow.h>
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatformintegration.h>
+#include <qpa/qplatformwindow.h>
#include <private/qguiapplication_p.h>
#include <private/qhighdpiscaling_p.h>
#include <QtGui/QPainter>
@@ -48,6 +49,12 @@
Q_DECLARE_METATYPE(Qt::ScreenOrientation)
Q_DECLARE_METATYPE(QWindow::Visibility)
+static bool isPlatformWinRT()
+{
+ static const bool isWinRT = !QGuiApplication::platformName().compare(QLatin1String("winrt"), Qt::CaseInsensitive);
+ return isWinRT;
+}
+
class tst_QWindow: public QObject
{
Q_OBJECT
@@ -97,6 +104,7 @@ private slots:
void modalWindowPosition();
#ifndef QT_NO_CURSOR
void modalWindowEnterEventOnHide_QTBUG35109();
+ void spuriousMouseMove();
#endif
void windowsTransientChildren();
void requestUpdate();
@@ -107,6 +115,7 @@ private slots:
void cleanup();
void testBlockingWindowShownAfterModalDialog();
void generatedMouseMove();
+ void keepPendingUpdateRequests();
private:
QPoint m_availableTopLeft;
@@ -234,6 +243,8 @@ void tst_QWindow::setVisible()
QVERIFY(h.handle());
i.setParent(&h);
QVERIFY2(i.handle(), "Making a visible but not created child window child of a created window should create it");
+ if (isPlatformWinRT())
+ QEXPECT_FAIL("", "Child windows are unsupported on winrt", Continue);
QVERIFY(QTest::qWaitForWindowExposed(&i));
}
@@ -398,11 +409,15 @@ void tst_QWindow::resizeEventAfterResize()
// Make sure we get a resizeEvent after calling resize
window.resize(m_testWindowSize);
+ if (isPlatformWinRT())
+ QEXPECT_FAIL("", "Winrt windows are fullscreen by default.", Continue);
QTRY_COMPARE(window.received(QEvent::Resize), 2);
}
void tst_QWindow::exposeEventOnShrink_QTBUG54040()
{
+ if (isPlatformWinRT())
+ QSKIP("", "WinRT does not support non-maximized/non-fullscreen top level windows. QTBUG-54528", Continue);
Window window;
window.setGeometry(QRect(m_availableTopLeft + QPoint(80, 80), m_testWindowSize));
window.setTitle(QTest::currentTestFunction());
@@ -479,7 +494,7 @@ void tst_QWindow::positioning()
}
if (isPlatformWayland())
- QSKIP("Wayland: This fails. Figure out why.");
+ QSKIP("Wayland: This fails. See QTBUG-68660.");
// Some platforms enforce minimum widths for windows, which can cause extra resize
// events, so set the width to suitably large value to avoid those.
@@ -590,6 +605,8 @@ void tst_QWindow::childWindowPositioning()
{
if (isPlatformWayland())
QSKIP("Wayland: This is flaky (protocol errors for xdg-shell v6). See QTBUG-67648.");
+ else if (isPlatformWinRT())
+ QSKIP("WinRT does not support child windows.");
const QPoint topLeftOrigin(0, 0);
@@ -787,11 +804,10 @@ void tst_QWindow::isExposed()
window.hide();
- if (isPlatformWayland())
- QSKIP("Wayland: This is flaky. Figure out why.");
-
QCoreApplication::processEvents();
QTRY_VERIFY(window.received(QEvent::Expose) > 1);
+ if (isPlatformWinRT())
+ QEXPECT_FAIL("", "WinRT does not destroy the window. Figure out why. QTBUG-68297", Continue);
QTRY_VERIFY(!window.isExposed());
}
@@ -825,6 +841,8 @@ void tst_QWindow::isActive()
child.setGeometry(10, 10, 20, 20);
child.show();
+ if (isPlatformWinRT())
+ QEXPECT_FAIL("", "WinRT does not support native child windows.", Abort);
QTRY_VERIFY(child.isExposed());
child.requestActivate();
@@ -895,7 +913,7 @@ void tst_QWindow::isActive()
QVERIFY(child.isActive());
}
-class InputTestWindow : public QWindow
+class InputTestWindow : public ColoredWindow
{
public:
void keyPressEvent(QKeyEvent *event) {
@@ -989,7 +1007,9 @@ public:
enterEventCount = leaveEventCount = 0;
}
- InputTestWindow() {
+ explicit InputTestWindow(const QColor &color = Qt::white, QWindow *parent = nullptr)
+ : ColoredWindow(color, parent)
+ {
keyPressCode = keyReleaseCode = 0;
mousePressButton = mouseReleaseButton = mouseMoveButton = 0;
ignoreMouse = ignoreTouch = false;
@@ -1843,7 +1863,7 @@ void tst_QWindow::mask()
void tst_QWindow::initialSize()
{
if (isPlatformWayland())
- QSKIP("Wayland: This fails. Figure out why.");
+ QSKIP("Wayland: This fails. See QTBUG-66818.");
QSize defaultSize(0,0);
{
@@ -1857,6 +1877,8 @@ void tst_QWindow::initialSize()
Window w;
w.setWidth(m_testWindowSize.width());
w.showNormal();
+ if (isPlatformWinRT())
+ QEXPECT_FAIL("", "WinRT shows windows as fullscreen by default.", Continue);
QTRY_COMPARE(w.width(), m_testWindowSize.width());
QTRY_VERIFY(w.height() > 0);
}
@@ -1867,6 +1889,8 @@ void tst_QWindow::initialSize()
w.showNormal();
const QSize expectedSize = testSize;
+ if (isPlatformWinRT())
+ QEXPECT_FAIL("", "WinRT shows windows as fullscreen by default.", Continue);
QTRY_COMPARE(w.size(), expectedSize);
}
}
@@ -1910,13 +1934,15 @@ void tst_QWindow::modalDialog()
return;
}
+ if (isPlatformWinRT())
+ QEXPECT_FAIL("", "WinRT only support one native window.", Continue);
QTRY_COMPARE(QGuiApplication::focusWindow(), &dialog);
}
void tst_QWindow::modalDialogClosingOneOfTwoModal()
{
- if (isPlatformWayland())
- QSKIP("Wayland: This fails. Figure out why.");
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("QWindow::requestActivate() is not supported.");
QWindow normalWindow;
normalWindow.setFramePosition(m_availableTopLeft + QPoint(80, 80));
@@ -1955,6 +1981,8 @@ void tst_QWindow::modalDialogClosingOneOfTwoModal()
return;
}
+ if (isPlatformWinRT())
+ QEXPECT_FAIL("", "WinRT only support one native window.", Continue);
QTRY_COMPARE(QGuiApplication::focusWindow(), &first_dialog);
}
@@ -1982,6 +2010,8 @@ void tst_QWindow::modalWithChildWindow()
tlw_dialog.show();
QVERIFY(QTest::qWaitForWindowExposed(&tlw_dialog));
+ if (isPlatformWinRT())
+ QEXPECT_FAIL("", "WinRT only support one native window.", Abort);
QVERIFY(QTest::qWaitForWindowExposed(&sub_window));
QTRY_COMPARE(QGuiApplication::focusWindow(), &tlw_dialog);
@@ -2034,6 +2064,8 @@ void tst_QWindow::modalWindowPosition()
window.setModality(Qt::WindowModal);
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
+ if (isPlatformWinRT())
+ QEXPECT_FAIL("", "WinRT windows are fullscreen by default.", Continue);
QCOMPARE(window.geometry(), origGeo);
}
@@ -2094,6 +2126,9 @@ void tst_QWindow::modalWindowEnterEventOnHide_QTBUG35109()
root.resetCounters();
modal.close();
+ if (isPlatformWinRT())
+ QEXPECT_FAIL("", "WinRT does not trigger the enter event correctly"
+ "- QTBUG-68297.", Abort);
// Check for the enter event
QTRY_COMPARE(root.enterEventCount, 1);
}
@@ -2213,7 +2248,53 @@ void tst_QWindow::modalWindowEnterEventOnHide_QTBUG35109()
QTRY_COMPARE(root.enterEventCount, 1);
}
}
-#endif
+
+// Verify that no spurious mouse move events are received. On Windows, there is
+// no enter event, the OS sends mouse move events instead. Test that the QPA
+// plugin properly suppresses those since they can interfere with tests.
+// Simulate a main window setup with a modal dialog on top, keep the cursor
+// in the center and check that no mouse events are recorded.
+void tst_QWindow::spuriousMouseMove()
+{
+ const QString &platformName = QGuiApplication::platformName();
+ if (platformName == QLatin1String("offscreen") || platformName == QLatin1String("cocoa"))
+ QSKIP("No enter events sent");
+ if (isPlatformWayland() || isPlatformWinRT())
+ QSKIP("QCursor::setPos() is not supported on this platform");
+ const QRect screenGeometry = QGuiApplication::primaryScreen()->geometry();
+ const QPoint center = screenGeometry.center();
+ QCursor::setPos(center);
+ QRect windowGeometry(QPoint(), 2 * m_testWindowSize);
+ windowGeometry.moveCenter(center);
+ QTRY_COMPARE(QCursor::pos(), center);
+ InputTestWindow topLevel;
+ topLevel.setTitle(QTest::currentTestFunction());
+ topLevel.setGeometry(windowGeometry);
+ topLevel.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
+ QTRY_VERIFY(topLevel.enterEventCount > 0);
+ InputTestWindow dialog(Qt::yellow);
+ dialog.setTransientParent(&topLevel);
+ dialog.setTitle("Dialog " + topLevel.title());
+ dialog.setModality(Qt::ApplicationModal);
+ windowGeometry.setSize(m_testWindowSize);
+ windowGeometry.moveCenter(center);
+ dialog.setGeometry(windowGeometry);
+ dialog.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&dialog));
+ QTRY_VERIFY(dialog.enterEventCount > 0);
+ dialog.setVisible(false);
+ QCOMPARE(dialog.mousePressedCount, 0);
+ QCOMPARE(dialog.mouseReleasedCount, 0);
+ QCOMPARE(dialog.mouseMovedCount, 0);
+ QCOMPARE(dialog.mouseDoubleClickedCount, 0);
+ topLevel.setVisible(false);
+ QCOMPARE(topLevel.mousePressedCount, 0);
+ QCOMPARE(topLevel.mouseReleasedCount, 0);
+ QCOMPARE(topLevel.mouseMovedCount, 0);
+ QCOMPARE(topLevel.mouseDoubleClickedCount, 0);
+}
+#endif // !QT_NO_CURSOR
static bool isNativeWindowVisible(const QWindow *window)
{
@@ -2372,6 +2453,27 @@ void tst_QWindow::generatedMouseMove()
QVERIFY(w.mouseMovedCount == 5);
}
+void tst_QWindow::keepPendingUpdateRequests()
+{
+ QRect geometry(m_availableTopLeft + QPoint(80, 80), m_testWindowSize);
+
+ Window window;
+ window.setGeometry(geometry);
+ window.show();
+ QCoreApplication::processEvents();
+ QTRY_VERIFY(window.isExposed());
+
+ window.requestUpdate();
+ window.close();
+ window.setVisible(true);
+
+ QPlatformWindow *platformWindow = window.handle();
+ QVERIFY(platformWindow);
+
+ QVERIFY(platformWindow->hasPendingUpdateRequest());
+ QTRY_VERIFY(!platformWindow->hasPendingUpdateRequest());
+}
+
#include <tst_qwindow.moc>
QTEST_MAIN(tst_QWindow)
diff --git a/tests/auto/gui/painting/qbrush/tst_qbrush.cpp b/tests/auto/gui/painting/qbrush/tst_qbrush.cpp
index 9098bb0f6e..cd3eaa1478 100644
--- a/tests/auto/gui/painting/qbrush/tst_qbrush.cpp
+++ b/tests/auto/gui/painting/qbrush/tst_qbrush.cpp
@@ -58,6 +58,7 @@ private slots:
void testQGradientCopyConstructor();
void gradientStops();
+ void gradientPresets();
void textures();
@@ -326,6 +327,26 @@ void tst_QBrush::gradientStops()
QCOMPARE(gradient.stops().at(0).second, QColor());
}
+void tst_QBrush::gradientPresets()
+{
+ QGradient gradient(QGradient::WarmFlame);
+ QCOMPARE(gradient.type(), QGradient::LinearGradient);
+ QCOMPARE(gradient.coordinateMode(), QGradient::ObjectMode);
+
+ QLinearGradient *lg = static_cast<QLinearGradient *>(&gradient);
+ QCOMPARE(lg->start(), QPointF(0, 1));
+ QCOMPARE(lg->finalStop(), QPointF(1, 0));
+
+ QCOMPARE(lg->stops().size(), 3);
+ QCOMPARE(lg->stops().at(0), QGradientStop(0, QColor(QLatin1Literal("#ff9a9e"))));
+ QCOMPARE(lg->stops().at(1), QGradientStop(0.99, QColor(QLatin1Literal("#fad0c4"))));
+ QCOMPARE(lg->stops().at(2), QGradientStop(1, QColor(QLatin1Literal("#fad0c4"))));
+
+
+ QGradient invalidPreset(QGradient::Preset(-1));
+ QCOMPARE(invalidPreset.type(), QGradient::NoGradient);
+}
+
void fill(QPaintDevice *pd) {
QPainter p(pd);
diff --git a/tests/auto/gui/painting/qcolor/tst_qcolor.cpp b/tests/auto/gui/painting/qcolor/tst_qcolor.cpp
index 67d30d7c9a..ece7a30830 100644
--- a/tests/auto/gui/painting/qcolor/tst_qcolor.cpp
+++ b/tests/auto/gui/painting/qcolor/tst_qcolor.cpp
@@ -1492,10 +1492,28 @@ void tst_QColor::unpremultiply_sse4()
// Tests that qUnpremultiply_sse4 returns the same as qUnpremultiply.
#if QT_COMPILER_SUPPORTS_HERE(SSE4_1)
if (qCpuHasFeature(SSE4_1)) {
+ int minorDifferences = 0;
+ for (uint a = 0; a < 256; a++) {
+ for (uint c = 0; c <= a; c++) {
+ const QRgb p = qRgba(c, a-c, c/2, a);
+ const uint u = qUnpremultiply(p);
+ const uint usse4 = qUnpremultiply_sse4(p);
+ if (u != usse4) {
+ QCOMPARE(qAlpha(u), qAlpha(usse4));
+ QVERIFY(qAbs(qRed(u) - qRed(usse4)) <= 1);
+ QVERIFY(qAbs(qGreen(u) - qGreen(usse4)) <= 1);
+ QVERIFY(qAbs(qBlue(u) - qBlue(usse4)) <= 1);
+ ++minorDifferences;
+ }
+ }
+ }
+ // Allow a few rounding differences as long as it still obeys
+ // the qPremultiply(qUnpremultiply(x)) == x invariant
+ QVERIFY(minorDifferences <= 16 * 255);
for (uint a = 0; a < 256; a++) {
for (uint c = 0; c <= a; c++) {
QRgb p = qRgba(c, a-c, c, a);
- QCOMPARE(qUnpremultiply(p), qUnpremultiply_sse4(p));
+ QCOMPARE(p, qPremultiply(qUnpremultiply_sse4(p)));
}
}
return;
diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
index 181c609c6e..9bf9e99bf9 100644
--- a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
+++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
@@ -31,9 +31,9 @@
#include <qpainter.h>
#ifndef QT_NO_WIDGETS
#include <qdrawutil.h>
-#include <qapplication.h>
#include <qwidget.h>
#endif
+#include <qguiapplication.h>
#include <qfontmetrics.h>
#include <qbitmap.h>
#include <qimage.h>
@@ -41,26 +41,18 @@
#include <limits.h>
#include <math.h>
#include <qpaintengine.h>
-#ifndef QT_NO_WIDGETS
-#include <qdesktopwidget.h>
-#endif
#include <qpixmap.h>
#include <qrandom.h>
#include <private/qdrawhelper_p.h>
#include <qpainter.h>
-
-#ifndef QT_NO_WIDGETS
-#include <qlabel.h>
-#endif
-
#include <qqueue.h>
+#include <qscreen.h>
#ifndef QT_NO_WIDGETS
#include <qgraphicsview.h>
#include <qgraphicsscene.h>
#include <qgraphicsproxywidget.h>
-#include <qlayout.h>
#endif
#include <qfontdatabase.h>
@@ -404,7 +396,7 @@ void tst_QPainter::cleanupTestCase()
#ifndef QT_NO_WIDGETS
void tst_QPainter::drawPixmap_comp_data()
{
- if (qApp->desktop()->depth() < 24)
+ if (QGuiApplication::primaryScreen()->depth() < 24)
QSKIP("Test only works on 32 bit displays");
QTest::addColumn<uint>("dest");
@@ -1099,6 +1091,7 @@ void tst_QPainter::fillRect_data()
QTest::newRow("argb32pm") << QImage::Format_ARGB32_Premultiplied;
QTest::newRow("rgba8888pm") << QImage::Format_RGBA8888_Premultiplied;
+ QTest::newRow("rgba64pm") << QImage::Format_RGBA64_Premultiplied;
}
void tst_QPainter::fillRect()
@@ -2451,6 +2444,24 @@ void tst_QPainter::setOpacity_data()
QTest::newRow("A2RGB30P on RGB30") << QImage::Format_RGB30
<< QImage::Format_A2RGB30_Premultiplied;
+ QTest::newRow("RGBA64P on RGBA64P") << QImage::Format_RGBA64_Premultiplied
+ << QImage::Format_RGBA64_Premultiplied;
+
+ QTest::newRow("RGBA64 on RGBA64") << QImage::Format_RGBA64
+ << QImage::Format_RGBA64;
+
+ QTest::newRow("RGBx64 on RGBx64") << QImage::Format_RGBX64
+ << QImage::Format_RGBX64;
+
+ QTest::newRow("RGBA64P on ARGB32P") << QImage::Format_ARGB32_Premultiplied
+ << QImage::Format_RGBA64_Premultiplied;
+
+ QTest::newRow("RGBx64 on ARGB32P") << QImage::Format_ARGB32_Premultiplied
+ << QImage::Format_RGBX64;
+
+ QTest::newRow("ARGB32P on RGBA64P") << QImage::Format_RGBA64_Premultiplied
+ << QImage::Format_ARGB32_Premultiplied;
+
}
void tst_QPainter::setOpacity()
@@ -3855,6 +3866,8 @@ void tst_QPainter::gradientPixelFormat_data()
QTest::newRow("rgbx8888") << QImage::Format_RGBX8888;
QTest::newRow("rgba8888") << QImage::Format_RGBA8888;
QTest::newRow("rgba8888_pm") << QImage::Format_RGBA8888_Premultiplied;
+ QTest::newRow("rgbx64") << QImage::Format_RGBX64;
+ QTest::newRow("rgba64_pm") << QImage::Format_RGBA64_Premultiplied;
}
void tst_QPainter::gradientPixelFormat()
@@ -4792,7 +4805,19 @@ void tst_QPainter::blendARGBonRGB_data()
<< QPainter::CompositionMode_SourceIn << qRgba(255, 0, 0, 127) << 255 ;
QTest::newRow("ARGB_PM source-in ARGB32") << QImage::Format_ARGB32 << QImage::Format_ARGB32_Premultiplied
<< QPainter::CompositionMode_SourceIn << qRgba(127, 0, 0, 127) << 255;
- // Only ARGB does inverse premultiply, on the rest over and source gives similar results:
+ QTest::newRow("ARGB over RGBA8888") << QImage::Format_RGBA8888 << QImage::Format_ARGB32
+ << QPainter::CompositionMode_SourceOver << qRgba(255, 0, 0, 127) << 127;
+ QTest::newRow("ARGB_PM over RGBA8888") << QImage::Format_RGBA8888 << QImage::Format_ARGB32_Premultiplied
+ << QPainter::CompositionMode_SourceOver << qRgba(127, 0, 0, 127) << 127;
+ QTest::newRow("ARGB source RGBA8888") << QImage::Format_RGBA8888 << QImage::Format_ARGB32
+ << QPainter::CompositionMode_Source << qRgba(255, 0, 0, 127) << 255;
+ QTest::newRow("ARGB_PM source RGBA8888") << QImage::Format_RGBA8888 << QImage::Format_ARGB32_Premultiplied
+ << QPainter::CompositionMode_Source << qRgba(127, 0, 0, 127) << 255;
+ QTest::newRow("ARGB source-in RGBA8888") << QImage::Format_RGBA8888 << QImage::Format_ARGB32
+ << QPainter::CompositionMode_SourceIn << qRgba(255, 0, 0, 127) << 255;
+ QTest::newRow("ARGB_PM source-in RGBA8888") << QImage::Format_RGBA8888 << QImage::Format_ARGB32_Premultiplied
+ << QPainter::CompositionMode_SourceIn << qRgba(127, 0, 0, 127) << 255;
+ // Only ARGB32 and RGBA8888 does inverse premultiply, on the rest over and source gives similar results:
QTest::newRow("ARGB over RGB32") << QImage::Format_RGB32 << QImage::Format_ARGB32
<< QPainter::CompositionMode_SourceOver << qRgba(255, 0, 0, 127) << 127;
QTest::newRow("ARGB_PM over RGB32") << QImage::Format_RGB32 << QImage::Format_ARGB32_Premultiplied
@@ -4829,18 +4854,6 @@ void tst_QPainter::blendARGBonRGB_data()
<< QPainter::CompositionMode_SourceIn << qRgba(255, 0, 0, 127) << 127;
QTest::newRow("ARGB_PM source-in RGBx8888") << QImage::Format_RGBX8888 << QImage::Format_ARGB32_Premultiplied
<< QPainter::CompositionMode_SourceIn << qRgba(127, 0, 0, 127) << 127;
- QTest::newRow("ARGB over RGBA8888") << QImage::Format_RGBA8888 << QImage::Format_ARGB32
- << QPainter::CompositionMode_SourceOver << qRgba(255, 0, 0, 127) << 127;
- QTest::newRow("ARGB_PM over RGBA8888") << QImage::Format_RGBA8888 << QImage::Format_ARGB32_Premultiplied
- << QPainter::CompositionMode_SourceOver << qRgba(127, 0, 0, 127) << 127;
- QTest::newRow("ARGB source RGBA8888") << QImage::Format_RGBA8888 << QImage::Format_ARGB32
- << QPainter::CompositionMode_Source << qRgba(255, 0, 0, 127) << 255;
- QTest::newRow("ARGB_PM source RGBA8888") << QImage::Format_RGBA8888 << QImage::Format_ARGB32_Premultiplied
- << QPainter::CompositionMode_Source << qRgba(127, 0, 0, 127) << 255;
- QTest::newRow("ARGB source-in RGBA8888") << QImage::Format_RGBA8888 << QImage::Format_ARGB32
- << QPainter::CompositionMode_SourceIn << qRgba(255, 0, 0, 127) << 255;
- QTest::newRow("ARGB_PM source-in RGBA8888") << QImage::Format_RGBA8888 << QImage::Format_ARGB32_Premultiplied
- << QPainter::CompositionMode_SourceIn << qRgba(127, 0, 0, 127) << 255;
QTest::newRow("ARGB over RGB16") << QImage::Format_RGB16 << QImage::Format_ARGB32
<< QPainter::CompositionMode_SourceOver << qRgba(255, 0, 0, 127) << 123;
QTest::newRow("ARGB_PM over RGB16") << QImage::Format_RGB16 << QImage::Format_ARGB32_Premultiplied
@@ -5011,7 +5024,7 @@ void tst_QPainter::drawPolyline_data()
{
QTest::addColumn< QVector<QPointF> >("points");
- QTest::newRow("basic") << (QVector<QPointF>() << QPointF(10, 10) << QPointF(20, 10) << QPointF(20, 20) << QPointF(10, 20));
+ QTest::newRow("basic") << (QVector<QPointF>() << QPointF(10, 10) << QPointF(20, 10) << QPointF(20, 20));
QTest::newRow("clipped") << (QVector<QPointF>() << QPoint(-10, 100) << QPoint(-1, 100) << QPoint(-1, -2) << QPoint(100, -2) << QPoint(100, 40)); // QTBUG-31579
QTest::newRow("shortsegment") << (QVector<QPointF>() << QPoint(20, 100) << QPoint(20, 99) << QPoint(21, 99) << QPoint(21, 104)); // QTBUG-42398
QTest::newRow("edge") << (QVector<QPointF>() << QPointF(4.5, 121.6) << QPointF(9.4, 150.9) << QPointF(14.2, 184.8) << QPointF(19.1, 130.4));
diff --git a/tests/auto/gui/qopengl/tst_qopengl.cpp b/tests/auto/gui/qopengl/tst_qopengl.cpp
index 5b1af9b6c9..f1360b9efe 100644
--- a/tests/auto/gui/qopengl/tst_qopengl.cpp
+++ b/tests/auto/gui/qopengl/tst_qopengl.cpp
@@ -82,6 +82,8 @@ private slots:
void fboRendering();
void fboRenderingRGB30_data();
void fboRenderingRGB30();
+ void fboRenderingRGB64_data();
+ void fboRenderingRGB64();
void fboHandleNulledAfterContextDestroyed();
void fboMRT();
void fboMRT_differentFormats();
@@ -614,6 +616,10 @@ void tst_QOpenGL::fboRenderingRGB30_data()
#define GL_RGB10_A2 0x8059
#endif
+#ifndef GL_RGBA16
+#define GL_RGBA16 0x805B
+#endif
+
#ifndef GL_FRAMEBUFFER_RENDERABLE
#define GL_FRAMEBUFFER_RENDERABLE 0x8289
#endif
@@ -622,7 +628,7 @@ void tst_QOpenGL::fboRenderingRGB30_data()
#define GL_FULL_SUPPORT 0x82B7
#endif
-static bool hasRGB10A2(QOpenGLContext *ctx)
+static bool supportsInternalFboFormat(QOpenGLContext *ctx, int glFormat)
{
if (ctx->format().majorVersion() < 3)
return false;
@@ -631,7 +637,7 @@ static bool hasRGB10A2(QOpenGLContext *ctx)
GLint value = -1;
QOpenGLFunctions_4_2_Core* vFuncs = ctx->versionFunctions<QOpenGLFunctions_4_2_Core>();
if (vFuncs && vFuncs->initializeOpenGLFunctions()) {
- vFuncs->glGetInternalformativ(GL_TEXTURE_2D, GL_RGB10_A2, GL_FRAMEBUFFER_RENDERABLE, 1, &value);
+ vFuncs->glGetInternalformativ(GL_TEXTURE_2D, glFormat, GL_FRAMEBUFFER_RENDERABLE, 1, &value);
if (value != GL_FULL_SUPPORT)
return false;
}
@@ -657,7 +663,7 @@ void tst_QOpenGL::fboRenderingRGB30()
if (!QOpenGLFramebufferObject::hasOpenGLFramebufferObjects())
QSKIP("QOpenGLFramebufferObject not supported on this platform");
- if (!hasRGB10A2(&ctx))
+ if (!supportsInternalFboFormat(&ctx, GL_RGB10_A2))
QSKIP("An internal RGB30_A2 format is not guaranteed on this platform");
// No multisample with combined depth/stencil attachment:
@@ -713,6 +719,71 @@ void tst_QOpenGL::fboRenderingRGB30()
QVERIFY(((pixel >> 20) & 0x3f) > 0);
}
+void tst_QOpenGL::fboRenderingRGB64_data()
+{
+ common_data();
+}
+
+void tst_QOpenGL::fboRenderingRGB64()
+{
+#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(__x86_64__)
+ QSKIP("QTBUG-22617");
+#endif
+
+ QFETCH(int, surfaceClass);
+ QScopedPointer<QSurface> surface(createSurface(surfaceClass));
+
+ QOpenGLContext ctx;
+ QVERIFY(ctx.create());
+
+ QVERIFY(ctx.makeCurrent(surface.data()));
+
+ if (!QOpenGLFramebufferObject::hasOpenGLFramebufferObjects())
+ QSKIP("QOpenGLFramebufferObject not supported on this platform");
+
+ if (!supportsInternalFboFormat(&ctx, GL_RGBA16))
+ QSKIP("An internal RGBA16 format is not guaranteed on this platform");
+
+ // No multisample with combined depth/stencil attachment:
+ QOpenGLFramebufferObjectFormat fboFormat;
+ fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ fboFormat.setInternalTextureFormat(GL_RGBA16);
+
+ // Uncomplicate things by using POT:
+ const QSize size(256, 128);
+ QOpenGLFramebufferObject fbo(size, fboFormat);
+
+ if (fbo.attachment() != QOpenGLFramebufferObject::CombinedDepthStencil)
+ QSKIP("FBOs missing combined depth~stencil support");
+
+ QVERIFY(fbo.bind());
+
+ QPainter fboPainter;
+ QOpenGLPaintDevice device(fbo.width(), fbo.height());
+ bool painterBegun = fboPainter.begin(&device);
+ QVERIFY(painterBegun);
+
+ qt_opengl_draw_test_pattern(&fboPainter, fbo.width(), fbo.height());
+
+ fboPainter.end();
+
+ QImage fb = fbo.toImage();
+ QCOMPARE(fb.format(), QImage::Format_RGBA64_Premultiplied);
+ QCOMPARE(fb.size(), size);
+
+ qt_opengl_check_test_pattern(fb);
+
+ // Check rendering can handle precise 16 bit color values.
+ fboPainter.begin(&device);
+ fboPainter.fillRect(QRect(0, 0, 256, 128), QColor::fromRgba64(5, 1002, 8001, 65535));
+ fboPainter.end();
+ fb = fbo.toImage();
+ QRgba64 pixel = ((QRgba64*)fb.bits())[0];
+ QCOMPARE(pixel.red(), 5);
+ QCOMPARE(pixel.green(), 1002);
+ QCOMPARE(pixel.blue(), 8001);
+}
+
void tst_QOpenGL::fboHandleNulledAfterContextDestroyed()
{
QWindow window;
@@ -844,7 +915,7 @@ void tst_QOpenGL::fboMRT_differentFormats()
if (!f->hasOpenGLFeature(QOpenGLFunctions::MultipleRenderTargets))
QSKIP("Multiple render targets not supported on this platform");
- if (!hasRGB10A2(&ctx))
+ if (!supportsInternalFboFormat(&ctx, GL_RGB10_A2))
QSKIP("RGB10_A2 not supported on this platform");
// 3 color attachments, same size, different internal format, depth/stencil.
diff --git a/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp b/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp
index 2a53f5d633..cfd24a8701 100644
--- a/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp
+++ b/tests/auto/gui/text/qcssparser/tst_qcssparser.cpp
@@ -1509,6 +1509,12 @@ void tst_QCssParser::gradient_data()
"spread: repeat, stop:0.2 rgb(1, 2, 3), stop:0.5 rgba(1, 2, 3, 4))" << "conical" << QPointF(4, 2) << QPointF()
<< 2 << qreal(0.2) << QColor(1, 2, 3) << qreal(0.5) << QColor(1, 2, 3, 4);
+ // spaces before first function parameter lead to parser errors
+ QTest::newRow("QTBUG-61795") <<
+ "selection-background-color: qconicalgradient( cx: 4, cy : 2, angle: 23, "
+ "spread: repeat, stop:0.2 rgb( 1, 2, 3), stop:0.5 rgba( 1, 2, 3, 4))" << "conical" << QPointF(4, 2) << QPointF()
+ << 2 << qreal(0.2) << QColor(1, 2, 3) << qreal(0.5) << QColor(1, 2, 3, 4);
+
/* won't pass: stop values are expected to be sorted
QTest::newRow("unsorted-stop") <<
"selection-background: lineargradient(x1:0, y1:0, x2:0, y2:1, "
diff --git a/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp b/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
index 79058e5073..da2f100c0b 100644
--- a/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
+++ b/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
@@ -65,6 +65,7 @@ private slots:
void fallbackFonts();
void condensedFontWidth();
+ void condensedFontWidthNoFontMerging();
void condensedFontMatching();
void rasterFonts();
@@ -297,6 +298,29 @@ static QString testString()
return QStringLiteral("foo bar");
}
+void tst_QFontDatabase::condensedFontWidthNoFontMerging()
+{
+ int regularFontId = QFontDatabase::addApplicationFont(m_testFont);
+ int condensedFontId = QFontDatabase::addApplicationFont(m_testFontCondensed);
+
+ QVERIFY(!QFontDatabase::applicationFontFamilies(regularFontId).isEmpty());
+ QVERIFY(!QFontDatabase::applicationFontFamilies(condensedFontId).isEmpty());
+
+ QString regularFontName = QFontDatabase::applicationFontFamilies(regularFontId).first();
+ QString condensedFontName = QFontDatabase::applicationFontFamilies(condensedFontId).first();
+
+ QFont condensedFont1(condensedFontName);
+ if (regularFontName == condensedFontName)
+ condensedFont1.setStyleName(QStringLiteral("Condensed"));
+ condensedFont1.setStyleStrategy(QFont::PreferMatch);
+
+ QFont condensedFont2 = condensedFont1;
+ condensedFont2.setStyleStrategy(QFont::StyleStrategy(QFont::NoFontMerging | QFont::PreferMatch));
+
+ QCOMPARE(QFontMetricsF(condensedFont2).horizontalAdvance(QStringLiteral("foobar")),
+ QFontMetricsF(condensedFont1).horizontalAdvance(QStringLiteral("foobar")));
+ }
+
void tst_QFontDatabase::condensedFontWidth()
{
QFontDatabase db;
diff --git a/tests/auto/gui/text/qglyphrun/BLACKLIST b/tests/auto/gui/text/qglyphrun/BLACKLIST
new file mode 100644
index 0000000000..57f32c683d
--- /dev/null
+++ b/tests/auto/gui/text/qglyphrun/BLACKLIST
@@ -0,0 +1,3 @@
+[mixedScripts]
+ubuntu-18.04
+b2qt
diff --git a/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp b/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp
index 21b2697b90..b7f014d0e2 100644
--- a/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp
+++ b/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp
@@ -731,6 +731,9 @@ void tst_QGlyphRun::mixedScripts()
layout.endLayout();
QList<QGlyphRun> glyphRuns = layout.glyphRuns();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Hangul character not rendered on winrt", Continue);
+#endif
QCOMPARE(glyphRuns.size(), 2);
}
diff --git a/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp b/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp
index 0089aeb43e..d00dc251d8 100644
--- a/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp
+++ b/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp
@@ -61,6 +61,8 @@ private slots:
void drawToPoint();
void drawToRect_data();
void drawToRect();
+ void compareToDrawText_data();
+ void compareToDrawText();
void setFont();
void setTextWidth();
void prepareToCorrectData();
@@ -212,6 +214,66 @@ void tst_QStaticText::drawToRect()
QCOMPARE(imageDrawStaticText, imageDrawText);
}
+void tst_QStaticText::compareToDrawText_data()
+{
+ QTest::addColumn<QFont>("font");
+
+ QTest::newRow("default") << QFont();
+ QFont sansserif; sansserif.setStyleHint(QFont::SansSerif);
+ QFont serif; serif.setStyleHint(QFont::Serif);
+ QFont monospace; monospace.setStyleHint(QFont::Monospace);
+ QTest::newRow("sans-serif") << QFont(sansserif.defaultFamily());
+ QTest::newRow("serif") << QFont(serif.defaultFamily());
+ QTest::newRow("monospace") << QFont(monospace.defaultFamily());
+}
+
+void tst_QStaticText::compareToDrawText()
+{
+ QFETCH(QFont, font);
+
+ QPixmap imageDrawText(1000, 1000);
+ imageDrawText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawText);
+ p.setFont(font);
+ p.drawText(QRectF(11, 12, 30, 500), "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ }
+
+ QPixmap imageDrawStaticPlainText(1000, 1000);
+ imageDrawStaticPlainText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawStaticPlainText);
+ p.setFont(font);
+ QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ text.setTextWidth(10),
+ p.setClipRect(QRectF(11, 12, 30, 500));
+ text.setTextFormat(Qt::PlainText);
+ p.drawStaticText(QPointF(11, 12), text);
+ }
+
+ QPixmap imageDrawStaticRichText(1000, 1000);
+ imageDrawStaticRichText.fill(Qt::white);
+ {
+ QPainter p(&imageDrawStaticRichText);
+ p.setFont(font);
+ QStaticText text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.");
+ text.setTextWidth(10),
+ p.setClipRect(QRectF(11, 12, 30, 500));
+ text.setTextFormat(Qt::RichText);
+ p.drawStaticText(QPointF(11, 12), text);
+ }
+
+#if defined(DEBUG_SAVE_IMAGE)
+ imageDrawText.save("compareToDrawText_imageDrawText.png");
+ imageDrawStaticText.save("compareToDrawText_imageDrawStaticPlainText.png");
+ imageDrawStaticText.save("compareToDrawText_imageDrawStaticRichText.png");
+#endif
+
+ QVERIFY(imageDrawText.toImage() != m_whiteSquare);
+ QCOMPARE(imageDrawStaticPlainText, imageDrawText);
+ QCOMPARE(imageDrawStaticRichText, imageDrawText);
+}
+
void tst_QStaticText::prepareToCorrectData()
{
QTransform transform;
diff --git a/tests/auto/gui/text/qtextcursor/tst_qtextcursor.cpp b/tests/auto/gui/text/qtextcursor/tst_qtextcursor.cpp
index d2c4adb888..2bc611fe93 100644
--- a/tests/auto/gui/text/qtextcursor/tst_qtextcursor.cpp
+++ b/tests/auto/gui/text/qtextcursor/tst_qtextcursor.cpp
@@ -137,6 +137,7 @@ private slots:
void cursorPositionWithBlockUndoAndRedo3();
void joinNonEmptyRemovedBlockUserState();
+ void crashOnDetachingDanglingCursor();
private:
int blockCount();
@@ -1974,5 +1975,14 @@ void tst_QTextCursor::joinNonEmptyRemovedBlockUserState()
QCOMPARE(cursor.block().userState(), 10);
}
+void tst_QTextCursor::crashOnDetachingDanglingCursor()
+{
+ QTextDocument *document = new QTextDocument;
+ QTextCursor cursor(document);
+ QTextCursor cursor2 = cursor;
+ delete document;
+ cursor2.setPosition(0); // Don't crash here
+}
+
QTEST_MAIN(tst_QTextCursor)
#include "tst_qtextcursor.moc"
diff --git a/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp b/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
index ed69802d95..3e354b7523 100644
--- a/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
+++ b/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
@@ -1692,6 +1692,9 @@ void tst_QTextDocumentFragment::html_bodyBackground()
const char html[] = "<body background=\"foo.png\">Foo</body>";
doc->setHtml(html);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Fails on winrt. Investigate - QTBUG-68297", Continue);
+#endif
QCOMPARE(doc->rootFrame()->frameFormat().background().style(), Qt::TexturePattern);
}
@@ -1706,6 +1709,9 @@ void tst_QTextDocumentFragment::html_tableCellBackground()
QVERIFY(table);
QTextTableCell cell = table->cellAt(0, 0);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Fails on winrt. Investigate - QTBUG-68297", Continue);
+#endif
QCOMPARE(cell.format().background().style(), Qt::TexturePattern);
}
@@ -1714,6 +1720,9 @@ void tst_QTextDocumentFragment::css_bodyBackground()
const char html[] = "<body style=\"background-image:url('foo.png')\">Foo</body>";
doc->setHtml(html);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Fails on winrt. Investigate - QTBUG-68297", Continue);
+#endif
QCOMPARE(doc->rootFrame()->frameFormat().background().style(), Qt::TexturePattern);
}
@@ -1728,6 +1737,9 @@ void tst_QTextDocumentFragment::css_tableCellBackground()
QVERIFY(table);
QTextTableCell cell = table->cellAt(0, 0);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Fails on winrt. Investigate - QTBUG-68297", Continue);
+#endif
QCOMPARE(cell.format().background().style(), Qt::TexturePattern);
}
diff --git a/tests/auto/gui/text/qtextdocumentlayout/tst_qtextdocumentlayout.cpp b/tests/auto/gui/text/qtextdocumentlayout/tst_qtextdocumentlayout.cpp
index 082d16f62d..c79f787547 100644
--- a/tests/auto/gui/text/qtextdocumentlayout/tst_qtextdocumentlayout.cpp
+++ b/tests/auto/gui/text/qtextdocumentlayout/tst_qtextdocumentlayout.cpp
@@ -299,8 +299,11 @@ void tst_QTextDocumentLayout::imageAtRightAlignedTab()
imgFormat.setName(name);
cursor.insertImage(imgFormat);
- // Everything should fit into the 300 pixels
- QCOMPARE(doc->idealWidth(), 300.0);
+ // Everything should fit into the 300 pixels
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Fails on winrt. Figure out why - QTBUG-68297", Continue);
+#endif
+ QCOMPARE(doc->idealWidth(), 300.0);
}
void tst_QTextDocumentLayout::blockVisibility()
diff --git a/tests/auto/gui/text/qtextodfwriter/tst_qtextodfwriter.cpp b/tests/auto/gui/text/qtextodfwriter/tst_qtextodfwriter.cpp
index fb92b5a20f..bbb90ec82a 100644
--- a/tests/auto/gui/text/qtextodfwriter/tst_qtextodfwriter.cpp
+++ b/tests/auto/gui/text/qtextodfwriter/tst_qtextodfwriter.cpp
@@ -131,7 +131,7 @@ void tst_QTextOdfWriter::testWriteParagraph_data()
QTest::newRow("misc2") << "\t \tFoo" <<
"<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\"><text:tab/> <text:s text:c=\"4\"/><text:tab/>Foo</text:span></text:p>";
QTest::newRow("linefeed") << (QStringLiteral("line1") + QChar(0x2028) + QStringLiteral("line2")) <<
- "<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\">line1<text:line-break/>line2</text:span></text:p>";
+ "<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\">line1<text:tab/><text:line-break/>line2</text:span></text:p>";
QTest::newRow("spaces") << "The quick brown fox jumped over the lazy dog" <<
"<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\">The quick brown fox jumped over the lazy dog</text:span></text:p>";
}
@@ -378,7 +378,7 @@ void tst_QTextOdfWriter::testWriteTable()
odfWriter->writeFrame(*xmlWriter, document->rootFrame());
QString xml = QString::fromLatin1(
"<text:p text:style-name=\"p1\"/>"
- "<table:table>"
+ "<table:table table:style-name=\"Table2\">"
"<table:table-column table:number-columns-repeated=\"3\"/>"
"<table:table-row>"
"<table:table-cell table:style-name=\"T3\">"
diff --git a/tests/auto/gui/util/qdoublevalidator/tst_qdoublevalidator.cpp b/tests/auto/gui/util/qdoublevalidator/tst_qdoublevalidator.cpp
index 4705fc3ed7..012a7e2ce3 100644
--- a/tests/auto/gui/util/qdoublevalidator/tst_qdoublevalidator.cpp
+++ b/tests/auto/gui/util/qdoublevalidator/tst_qdoublevalidator.cpp
@@ -155,6 +155,10 @@ void tst_QDoubleValidator::validate_data()
QTest::newRow("data48") << "C" << 0.0 << 100.0 << 1 << QString("0.0") << ACC << ACC;
QTest::newRow("data49") << "C" << 0.0 << 100.0 << 0 << QString(".") << ITM << ITM;
QTest::newRow("data50") << "C" << 0.0 << 100.0 << 1 << QString(".") << ITM << ITM;
+ QTest::newRow("data51") << "C" << 0.0 << 2.0 << 2 << QString("9.99") << ITM << ITM;
+ QTest::newRow("data52") << "C" << 100.0 << 200.0 << 4 << QString("999.9999") << ITM << ITM;
+ QTest::newRow("data53") << "C" << 0.0 << 2.0 << 2 << QString("9.9999") << INV << INV;
+ QTest::newRow("data54") << "C" << 100.0 << 200.0 << 4 << QString("9999.9999") << ITM << INV;
QTest::newRow("data_de0") << "de" << 0.0 << 100.0 << 1 << QString("50,0") << ACC << ACC;
QTest::newRow("data_de1") << "de" << 00.0 << 100.0 << 1 << QString("500,0") << ITM << ITM;
@@ -206,6 +210,10 @@ void tst_QDoubleValidator::validate_data()
QTest::newRow("data_de43") << "de" << 0.01 << 0.09 << 2 << QString("0") << ITM << ITM;
QTest::newRow("data_de44") << "de" << 0.0 << 10.0 << 1 << QString("11") << ITM << ITM;
QTest::newRow("data_de45") << "de" << 0.0 << 10.0 << 2 << QString("11") << ITM << ITM;
+ QTest::newRow("data_de46") << "de" << 0.0 << 2.0 << 2 << QString("9,99") << ITM << ITM;
+ QTest::newRow("data_de47") << "de" << 100.0 << 200.0 << 4 << QString("999,9999") << ITM << ITM;
+ QTest::newRow("data_de48") << "de" << 0.0 << 2.0 << 2 << QString("9,9999") << INV << INV;
+ QTest::newRow("data_de49") << "de" << 100.0 << 200.0 << 4 << QString("9999,9999") << ITM << INV;
QString arabicNum;
arabicNum += QChar(1633); // "18.4" in arabic
diff --git a/tests/auto/gui/util/qintvalidator/tst_qintvalidator.cpp b/tests/auto/gui/util/qintvalidator/tst_qintvalidator.cpp
index 57f55c3121..ec0d63f67c 100644
--- a/tests/auto/gui/util/qintvalidator/tst_qintvalidator.cpp
+++ b/tests/auto/gui/util/qintvalidator/tst_qintvalidator.cpp
@@ -54,7 +54,7 @@ void tst_QIntValidator::validate_data()
QTest::addColumn<QValidator::State>("state");
QTest::newRow("data0") << 0 << 100 << QString("50") << ACC;
- QTest::newRow("data1") << 0 << 100 << QString("500") << INV;
+ QTest::newRow("data1") << 0 << 100 << QString("500") << INT;
QTest::newRow("data1a") << 0 << 100 << QString("5000") << INV;
QTest::newRow("data1b") << -100 << 0 << QString("50") << INT;
QTest::newRow("data1c") << -100 << 0 << QString("500") << INV;
@@ -121,7 +121,7 @@ void tst_QIntValidator::validate_data()
QTest::newRow("5.1") << 6 << 8 << QString("5") << INT;
QTest::newRow("5.2") << 6 << 8 << QString("7") << ACC;
- QTest::newRow("5.3") << 6 << 8 << QString("9") << INV;
+ QTest::newRow("5.3") << 6 << 8 << QString("9") << INT;
QTest::newRow("5.3a") << 6 << 8 << QString("19") << INV;
QTest::newRow("5.4") << -8 << -6 << QString("-5") << INT;
QTest::newRow("5.5") << -8 << -6 << QString("-7") << ACC;
@@ -129,13 +129,13 @@ void tst_QIntValidator::validate_data()
QTest::newRow("5.6a") << -8 << -6 << QString("-19") << INV;
QTest::newRow("5.7") << -8 << -6 << QString("5") << INT;
QTest::newRow("5.8") << -8 << -6 << QString("7") << INT;
- QTest::newRow("5.9") << -8 << -6 << QString("9") << INV;
+ QTest::newRow("5.9") << -8 << -6 << QString("9") << INT;
QTest::newRow("5.10") << -6 << 8 << QString("-5") << ACC;
QTest::newRow("5.11") << -6 << 8 << QString("5") << ACC;
QTest::newRow("5.12") << -6 << 8 << QString("-7") << INV;
QTest::newRow("5.13") << -6 << 8 << QString("7") << ACC;
QTest::newRow("5.14") << -6 << 8 << QString("-9") << INV;
- QTest::newRow("5.15") << -6 << 8 << QString("9") << INV;
+ QTest::newRow("5.15") << -6 << 8 << QString("9") << INT;
QTest::newRow("6.1") << 100 << 102 << QString("11") << INT;
QTest::newRow("6.2") << 100 << 102 << QString("-11") << INV;
diff --git a/tests/auto/gui/util/qtexturefilereader/qtexturefilereader.pro b/tests/auto/gui/util/qtexturefilereader/qtexturefilereader.pro
new file mode 100644
index 0000000000..43951fe722
--- /dev/null
+++ b/tests/auto/gui/util/qtexturefilereader/qtexturefilereader.pro
@@ -0,0 +1,5 @@
+CONFIG += testcase
+QT += testlib gui-private
+SOURCES += tst_qtexturefilereader.cpp
+TARGET = tst_qtexturefilereader
+RESOURCES += qtexturefilereader.qrc
diff --git a/tests/auto/gui/util/qtexturefilereader/qtexturefilereader.qrc b/tests/auto/gui/util/qtexturefilereader/qtexturefilereader.qrc
new file mode 100644
index 0000000000..ab882b5db2
--- /dev/null
+++ b/tests/auto/gui/util/qtexturefilereader/qtexturefilereader.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file>texturefiles/car.ktx</file>
+ <file>texturefiles/pattern.pkm</file>
+ <file>texturefiles/car_mips.ktx</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/gui/util/qtexturefilereader/texturefiles/car.ktx b/tests/auto/gui/util/qtexturefilereader/texturefiles/car.ktx
new file mode 100644
index 0000000000..2aefdd306b
--- /dev/null
+++ b/tests/auto/gui/util/qtexturefilereader/texturefiles/car.ktx
Binary files differ
diff --git a/tests/auto/gui/util/qtexturefilereader/texturefiles/car_mips.ktx b/tests/auto/gui/util/qtexturefilereader/texturefiles/car_mips.ktx
new file mode 100644
index 0000000000..82822e6c0b
--- /dev/null
+++ b/tests/auto/gui/util/qtexturefilereader/texturefiles/car_mips.ktx
Binary files differ
diff --git a/tests/auto/gui/util/qtexturefilereader/texturefiles/pattern.pkm b/tests/auto/gui/util/qtexturefilereader/texturefiles/pattern.pkm
new file mode 100644
index 0000000000..d986e89b2d
--- /dev/null
+++ b/tests/auto/gui/util/qtexturefilereader/texturefiles/pattern.pkm
Binary files differ
diff --git a/tests/auto/gui/util/qtexturefilereader/tst_qtexturefilereader.cpp b/tests/auto/gui/util/qtexturefilereader/tst_qtexturefilereader.cpp
new file mode 100644
index 0000000000..9ff4f0ccf2
--- /dev/null
+++ b/tests/auto/gui/util/qtexturefilereader/tst_qtexturefilereader.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qtexturefilereader_p.h>
+#include <QtTest>
+
+class tst_qtexturefilereader : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void checkHandlers_data();
+ void checkHandlers();
+};
+
+void tst_qtexturefilereader::checkHandlers_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<QSize>("size");
+ QTest::addColumn<quint32>("glFormat");
+ QTest::addColumn<quint32>("glInternalFormat");
+ QTest::addColumn<quint32>("glBaseInternalFormat");
+ QTest::addColumn<int>("levels");
+ QTest::addColumn<QList<int>>("dataOffsets");
+ QTest::addColumn<QList<int>>("dataLengths");
+
+ QTest::addRow("pattern.pkm") << QStringLiteral(":/texturefiles/pattern.pkm")
+ << QSize(64, 64)
+ << quint32(0x0)
+ << quint32(0x8d64)
+ << quint32(0x0)
+ << 1
+ << (QList<int>() << 16)
+ << (QList<int>() << 2048);
+
+ QTest::addRow("car.ktx") << QStringLiteral(":/texturefiles/car.ktx")
+ << QSize(146, 80)
+ << quint32(0x0)
+ << quint32(0x9278)
+ << quint32(0x1908)
+ << 1
+ << (QList<int>() << 68)
+ << (QList<int>() << 11840);
+
+ QTest::addRow("car_mips.ktx") << QStringLiteral(":/texturefiles/car_mips.ktx")
+ << QSize(146, 80)
+ << quint32(0x0)
+ << quint32(0x9274)
+ << quint32(0x1907)
+ << 8
+ << (QList<int>() << 68 << 5992 << 7516 << 7880 << 8004 << 8056 << 8068 << 8080)
+ << (QList<int>() << 5920 << 1520 << 360 << 120 << 48 << 8 << 8 << 8);
+
+}
+
+void tst_qtexturefilereader::checkHandlers()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QSize, size);
+ QFETCH(quint32, glFormat);
+ QFETCH(quint32, glInternalFormat);
+ QFETCH(int, levels);
+ QFETCH(QList<int>, dataOffsets);
+ QFETCH(QList<int>, dataLengths);
+
+ QFile f(fileName);
+ QVERIFY(f.open(QIODevice::ReadOnly));
+ QTextureFileReader r(&f, fileName);
+ QVERIFY(r.canRead());
+
+ QTextureFileData tex = r.read();
+ QVERIFY(!tex.isNull());
+ QVERIFY(tex.isValid());
+ QCOMPARE(tex.size(), size);
+ QCOMPARE(tex.glFormat(), glFormat);
+ QCOMPARE(tex.glInternalFormat(), glInternalFormat);
+ QCOMPARE(tex.numLevels(), levels);
+ for (int i = 0; i < tex.numLevels(); i++) {
+ QCOMPARE(tex.dataOffset(i), dataOffsets.at(i));
+ QCOMPARE(tex.dataLength(i), dataLengths.at(i));
+ }
+}
+
+QTEST_MAIN(tst_qtexturefilereader)
+
+#include "tst_qtexturefilereader.moc"
diff --git a/tests/auto/gui/util/util.pro b/tests/auto/gui/util/util.pro
index 940e892e5f..2789ffb55d 100644
--- a/tests/auto/gui/util/util.pro
+++ b/tests/auto/gui/util/util.pro
@@ -10,4 +10,4 @@ SUBDIRS= \
qshadergraphloader \
qshadernodes \
qshadernodesloader \
-
+ qtexturefilereader
diff --git a/tests/auto/network-settings.h b/tests/auto/network-settings.h
index 16966ced4e..a3c318420f 100644
--- a/tests/auto/network-settings.h
+++ b/tests/auto/network-settings.h
@@ -27,10 +27,12 @@
****************************************************************************/
#include <QString>
+#include <QtTest/QtTest>
#ifdef QT_NETWORK_LIB
#include <QtNetwork/QHostInfo>
#include <QtNetwork/QHostAddress>
#include <QtNetwork/QAbstractSocket>
+#include <QtNetwork/QTcpSocket>
#endif
#ifdef Q_OS_UNIX
@@ -50,7 +52,11 @@ public:
}
static QString serverDomainName()
{
+#ifdef QT_TEST_SERVER_DOMAIN
+ return QString(QT_TEST_SERVER_DOMAIN); // Defined in testserver feature
+#else
return QString("qt-test-net");
+#endif
}
static QString serverName()
{
@@ -137,6 +143,20 @@ public:
return true;
}
+ static bool verifyConnection(QString serverName, quint16 port, quint32 retry = 10)
+ {
+ QTcpSocket socket;
+ for (quint32 i = 1; i < retry; i++) {
+ socket.connectToHost(serverName, port);
+ if (socket.waitForConnected(1000))
+ return true;
+ // Wait for service to start up
+ QTest::qWait(1000);
+ }
+ socket.connectToHost(serverName, port);
+ return socket.waitForConnected(1000);
+ }
+
// Helper function for usage with QVERIFY2 on sockets.
static QByteArray msgSocketError(const QAbstractSocket &s)
{
@@ -153,4 +173,45 @@ public:
return result.toLocal8Bit();
}
#endif // QT_NETWORK_LIB
+
+ static QString ftpServerName()
+ {
+#ifdef QT_TEST_SERVER
+ return QString("vsftpd.") % serverDomainName();
+#else
+ return serverName();
+#endif
+ }
+ static QString ftpProxyServerName()
+ {
+#ifdef QT_TEST_SERVER
+ return QString("ftp-proxy.") % serverDomainName();
+#else
+ return serverName();
+#endif
+ }
+ static QString httpServerName()
+ {
+#ifdef QT_TEST_SERVER
+ return QString("apache2.") % serverDomainName();
+#else
+ return serverName();
+#endif
+ }
+ static QString httpProxyServerName()
+ {
+#ifdef QT_TEST_SERVER
+ return QString("squid.") % serverDomainName();
+#else
+ return serverName();
+#endif
+ }
+ static QString socksProxyServerName()
+ {
+#ifdef QT_TEST_SERVER
+ return QString("danted.") % serverDomainName();
+#else
+ return serverName();
+#endif
+ }
};
diff --git a/tests/auto/network/access/hpack/hpack.pro b/tests/auto/network/access/hpack/hpack.pro
index 3c8b8e7944..2823ae4d0c 100644
--- a/tests/auto/network/access/hpack/hpack.pro
+++ b/tests/auto/network/access/hpack/hpack.pro
@@ -1,5 +1,5 @@
-QT += core core-private network network-private testlib
-CONFIG += testcase parallel_test c++14
+QT = core core-private network network-private testlib
+CONFIG += testcase parallel_test c++11
TEMPLATE = app
TARGET = tst_hpack
diff --git a/tests/auto/network/access/hsts/hsts.pro b/tests/auto/network/access/hsts/hsts.pro
index 07bdea5f62..dad6638364 100644
--- a/tests/auto/network/access/hsts/hsts.pro
+++ b/tests/auto/network/access/hsts/hsts.pro
@@ -1,4 +1,4 @@
-QT += core core-private network network-private testlib
+QT = core core-private network network-private testlib
CONFIG += testcase parallel_test c++11
TEMPLATE = app
TARGET = tst_qhsts
diff --git a/tests/auto/network/access/http2/http2.pro b/tests/auto/network/access/http2/http2.pro
index e130f30784..62b685e556 100644
--- a/tests/auto/network/access/http2/http2.pro
+++ b/tests/auto/network/access/http2/http2.pro
@@ -1,4 +1,4 @@
-QT += core core-private network network-private testlib
+QT = core core-private network network-private testlib
CONFIG += testcase parallel_test c++11
TARGET = tst_http2
diff --git a/tests/auto/network/access/http2/http2srv.cpp b/tests/auto/network/access/http2/http2srv.cpp
index b0bae13bad..1f9ffb8985 100644
--- a/tests/auto/network/access/http2/http2srv.cpp
+++ b/tests/auto/network/access/http2/http2srv.cpp
@@ -212,13 +212,30 @@ void Http2Server::sendDATA(quint32 streamID, quint32 windowSize)
const quint32 offset = it->second;
Q_ASSERT(offset < quint32(responseBody.size()));
- const quint32 bytes = std::min<quint32>(windowSize, responseBody.size() - offset);
+ quint32 bytesToSend = std::min<quint32>(windowSize, responseBody.size() - offset);
+ quint32 bytesSent = 0;
const quint32 frameSizeLimit(clientSetting(Settings::MAX_FRAME_SIZE_ID, Http2::maxFrameSize));
const uchar *src = reinterpret_cast<const uchar *>(responseBody.constData() + offset);
- const bool last = offset + bytes == quint32(responseBody.size());
+ const bool last = offset + bytesToSend == quint32(responseBody.size());
+
+ // The payload can significantly exceed frameSizeLimit. Internally, writer
+ // will do needed fragmentation, but if some test failed, there is no need
+ // to wait for writer to send all DATA frames, we check 'interrupted' and
+ // stop early instead.
+ const quint32 framesInChunk = 10;
+ while (bytesToSend) {
+ if (interrupted.loadAcquire())
+ return;
+ const quint32 chunkSize = std::min<quint32>(framesInChunk * frameSizeLimit, bytesToSend);
+ writer.start(FrameType::DATA, FrameFlag::EMPTY, streamID);
+ writer.writeDATA(*socket, frameSizeLimit, src, chunkSize);
+ src += chunkSize;
+ bytesToSend -= chunkSize;
+ bytesSent += chunkSize;
+ }
- writer.start(FrameType::DATA, FrameFlag::EMPTY, streamID);
- writer.writeDATA(*socket, frameSizeLimit, src, bytes);
+ if (interrupted.loadAcquire())
+ return;
if (last) {
writer.start(FrameType::DATA, FrameFlag::END_STREAM, streamID);
@@ -230,7 +247,7 @@ void Http2Server::sendDATA(quint32 streamID, quint32 windowSize)
Q_ASSERT(closedStreams.find(streamID) == closedStreams.end());
closedStreams.insert(streamID);
} else {
- it->second += bytes;
+ it->second += bytesSent;
}
}
@@ -819,6 +836,11 @@ void Http2Server::sendResponse(quint32 streamID, bool emptyBody)
}
}
+void Http2Server::stopSendingDATAFrames()
+{
+ interrupted.storeRelease(1);
+}
+
void Http2Server::processRequest()
{
Q_ASSERT(continuedRequest.size());
diff --git a/tests/auto/network/access/http2/http2srv.h b/tests/auto/network/access/http2/http2srv.h
index 14b41cc67d..87a17ced8b 100644
--- a/tests/auto/network/access/http2/http2srv.h
+++ b/tests/auto/network/access/http2/http2srv.h
@@ -40,6 +40,7 @@
#include <QtCore/qscopedpointer.h>
#include <QtNetwork/qtcpserver.h>
#include <QtCore/qbytearray.h>
+#include <QtCore/qatomic.h>
#include <QtCore/qglobal.h>
#include <vector>
@@ -96,6 +97,8 @@ public:
Q_INVOKABLE void sendResponse(quint32 streamID, bool emptyBody);
+ void stopSendingDATAFrames();
+
private:
void processRequest();
@@ -191,6 +194,7 @@ private:
// may still be sending DATA frames. See tst_Http2::earlyResponse().
bool redirectWhileReading = false;
quint16 targetPort = 0;
+ QAtomicInt interrupted;
protected slots:
void ignoreErrorSlot();
};
diff --git a/tests/auto/network/access/http2/tst_http2.cpp b/tests/auto/network/access/http2/tst_http2.cpp
index ecf4c5814a..49daedf32c 100644
--- a/tests/auto/network/access/http2/tst_http2.cpp
+++ b/tests/auto/network/access/http2/tst_http2.cpp
@@ -110,8 +110,7 @@ private:
QThread *workerThread = nullptr;
QNetworkAccessManager manager;
- QEventLoop eventLoop;
- QTimer timer;
+ QTestEventLoop eventLoop;
int nRequests = 0;
int nSentRequests = 0;
@@ -133,8 +132,10 @@ struct ServerDeleter
{
static void cleanup(Http2Server *srv)
{
- if (srv)
+ if (srv) {
+ srv->stopSendingDATAFrames();
QMetaObject::invokeMethod(srv, "deleteLater", Qt::QueuedConnection);
+ }
}
};
@@ -146,11 +147,6 @@ tst_Http2::tst_Http2()
: workerThread(new QThread)
{
workerThread->start();
-
- timer.setInterval(10000);
- timer.setSingleShot(true);
-
- connect(&timer, SIGNAL(timeout()), &eventLoop, SLOT(quit()));
}
tst_Http2::~tst_Http2()
@@ -497,15 +493,12 @@ void tst_Http2::clearHTTP2State()
void tst_Http2::runEventLoop(int ms)
{
- timer.setInterval(ms);
- timer.start();
- eventLoop.exec();
+ eventLoop.enterLoopMSecs(ms);
}
void tst_Http2::stopEventLoop()
{
- timer.stop();
- eventLoop.quit();
+ eventLoop.exitLoop();
}
Http2Server *tst_Http2::newServer(const Http2::RawSettings &serverSettings,
diff --git a/tests/auto/network/access/qnetworkreply/certs/qt-test-net-cacert.pem b/tests/auto/network/access/qnetworkreply/certs/qt-test-net-cacert.pem
new file mode 100644
index 0000000000..43c8794ce2
--- /dev/null
+++ b/tests/auto/network/access/qnetworkreply/certs/qt-test-net-cacert.pem
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIIClTCCAf4CCQC2xMhNhwvATDANBgkqhkiG9w0BAQQFADCBjjELMAkGA1UEChMC
+UXQxGTAXBgNVBAsTEENvcmUgQW5kIE5ldHdvcmsxGzAZBgkqhkiG9w0BCQEWDG5v
+Ym9keS5xdC5pbzENMAsGA1UEBxMET3NsbzENMAsGA1UECBMET3NsbzELMAkGA1UE
+BhMCTk8xHDAaBgNVBAMUEyoudGVzdC1uZXQucXQubG9jYWwwHhcNMTgwNzAxMTgz
+NjI3WhcNNDgwNjIzMTgzNjI3WjCBjjELMAkGA1UEChMCUXQxGTAXBgNVBAsTEENv
+cmUgQW5kIE5ldHdvcmsxGzAZBgkqhkiG9w0BCQEWDG5vYm9keS5xdC5pbzENMAsG
+A1UEBxMET3NsbzENMAsGA1UECBMET3NsbzELMAkGA1UEBhMCTk8xHDAaBgNVBAMU
+EyoudGVzdC1uZXQucXQubG9jYWwwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
+AM2q22/WNMmn8cC+5EEYGeICySLmp9W6Ay6eKHr0Xxp3X3epETuPfvAuxp7rOtkS
+18EMUegkUj8jw0IMEcbyHKFC/rTCaYOt93CxGBXMIChiMPAsFeYzGa/D6xzAkfcR
+aJRQ+Ek3CDLXPnXfo7xpABXezYcPXAJrgsgBfWrwHdxzAgMBAAEwDQYJKoZIhvcN
+AQEEBQADgYEAZu/lQPy8PXeyyYGamOVms/FZKJ48BH1y8KC3BeBU5FYnhvgG7pz8
+Wz9JKvt2t/r45wQeAkNL6HnGUBhPJsHMjPHl5KktqN+db3D+FQygBeS2V1+zmC0X
+UZNRE4aWiHvt1Lq+pTx89SOMOpfqWfh4qTQKiE5jC2V4DeCNQ3u7uI8=
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/access/qnetworkreply/test/test.pro b/tests/auto/network/access/qnetworkreply/test/test.pro
index e8464e81af..9d36352abc 100644
--- a/tests/auto/network/access/qnetworkreply/test/test.pro
+++ b/tests/auto/network/access/qnetworkreply/test/test.pro
@@ -14,3 +14,6 @@ TESTDATA += ../empty ../rfc3252.txt ../resource ../bigfile ../*.jpg ../certs \
../index.html ../smb-file.txt
!android:!winrt: TEST_HELPER_INSTALLS = ../echo/echo
+
+QT_TEST_SERVER_LIST = vsftpd apache2 ftp-proxy danted squid
+include($$dirname(_QMAKE_CONF_)/tests/auto/testserver.pri)
diff --git a/tests/auto/network/access/qnetworkreply/testserver_index.html b/tests/auto/network/access/qnetworkreply/testserver_index.html
new file mode 100644
index 0000000000..abc1df188d
--- /dev/null
+++ b/tests/auto/network/access/qnetworkreply/testserver_index.html
@@ -0,0 +1,3 @@
+<h1>Welcome to qt-test-server</h1>
+<img src="fluke.gif" alt="fluke">
+<p>This is a network test server. It serves as a caching ftp and http proxy, transparent http/socks5 proxy, imap, ftp and http server, and more.</p>
diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
index 9c77e156d7..30b41da515 100644
--- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
@@ -156,6 +156,7 @@ class tst_QNetworkReply: public QObject
#ifndef QT_NO_SSL
QSslConfiguration storedSslConfiguration;
QList<QSslError> storedExpectedSslErrors;
+ static const QString certsFilePath;
#endif
#ifndef QT_NO_BEARERMANAGEMENT
QNetworkConfigurationManager *netConfMan;
@@ -547,8 +548,15 @@ static void setupSslServer(QSslSocket* serverSocket)
serverSocket->setPrivateKey(testDataDir + "/certs/server.key");
serverSocket->startServerEncryption();
}
+
+#ifdef QT_TEST_SERVER
+const QString tst_QNetworkReply::certsFilePath = "/certs/qt-test-net-cacert.pem";
+#else
+const QString tst_QNetworkReply::certsFilePath = "/certs/qt-test-server-cacert.pem";
#endif
+#endif // !QT_NO_SSL
+
// NOTE: MiniHttpServer has a very limited support of PUT/POST requests! Make
// sure you understand the server's code before PUTting/POSTing data (and
// probably you'll have to update the logic).
@@ -1270,18 +1278,23 @@ tst_QNetworkReply::tst_QNetworkReply()
manager.setCookieJar(cookieJar);
#ifndef QT_NO_NETWORKPROXY
- QHostInfo hostInfo = QHostInfo::fromName(QtNetworkSettings::serverName());
+ QHostInfo hostInfo = QHostInfo::fromName(QtNetworkSettings::httpProxyServerName());
proxies << ProxyData(QNetworkProxy::NoProxy, "", false);
if (hostInfo.error() == QHostInfo::NoError && !hostInfo.addresses().isEmpty()) {
- QString proxyserver = hostInfo.addresses().first().toString();
- proxies << ProxyData(QNetworkProxy(QNetworkProxy::HttpProxy, proxyserver, 3128), "+proxy", false)
- << ProxyData(QNetworkProxy(QNetworkProxy::HttpProxy, proxyserver, 3129), "+proxyauth", true)
+ QString httpProxy = QtNetworkSettings::httpProxyServerName();
+ QString socksProxy = QtNetworkSettings::socksProxyServerName();
+ proxies << ProxyData(QNetworkProxy(QNetworkProxy::HttpProxy, httpProxy, 3128),
+ "+proxy", false)
+ << ProxyData(QNetworkProxy(QNetworkProxy::HttpProxy, httpProxy, 3129),
+ "+proxyauth", true)
// currently unsupported
// << ProxyData(QNetworkProxy(QNetworkProxy::HttpProxy, proxyserver, 3130), "+proxyauth-ntlm", true);
- << ProxyData(QNetworkProxy(QNetworkProxy::Socks5Proxy, proxyserver, 1080), "+socks", false)
- << ProxyData(QNetworkProxy(QNetworkProxy::Socks5Proxy, proxyserver, 1081), "+socksauth", true);
+ << ProxyData(QNetworkProxy(QNetworkProxy::Socks5Proxy, socksProxy, 1080),
+ "+socks", false)
+ << ProxyData(QNetworkProxy(QNetworkProxy::Socks5Proxy, socksProxy, 1081),
+ "+socksauth", true);
} else {
#endif // !QT_NO_NETWORKPROXY
printf("==================================================================\n");
@@ -1508,8 +1521,20 @@ void tst_QNetworkReply::initTestCase()
if (testDataDir.isEmpty())
testDataDir = QCoreApplication::applicationDirPath();
+#if defined(QT_TEST_SERVER)
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::ftpServerName(), 21));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::ftpProxyServerName(), 2121));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpServerName(), 80));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpServerName(), 443));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3128));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3129));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::httpProxyServerName(), 3130));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1080));
+ QVERIFY(QtNetworkSettings::verifyConnection(QtNetworkSettings::socksProxyServerName(), 1081));
+#else
if (!QtNetworkSettings::verifyTestNetworkSettings())
QSKIP("No network test server available");
+#endif
#if !defined Q_OS_WIN
wronlyFileName = testDataDir + "/write-only" + uniqueExtension;
QFile wr(wronlyFileName);
@@ -1808,8 +1833,13 @@ void tst_QNetworkReply::getFromFtp_data()
QTest::addColumn<QString>("referenceName");
QTest::addColumn<QString>("url");
- QTest::newRow("rfc3252.txt") << (testDataDir + "/rfc3252.txt") << "ftp://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt";
- QTest::newRow("bigfile") << (testDataDir + "/bigfile") << "ftp://" + QtNetworkSettings::serverName() + "/qtest/bigfile";
+ QTest::newRow("rfc3252.txt")
+ << testDataDir + "/rfc3252.txt"
+ << "ftp://" + QtNetworkSettings::ftpServerName() + "/qtest/rfc3252.txt";
+
+ QTest::newRow("bigfile")
+ << testDataDir + "/bigfile"
+ << "ftp://" + QtNetworkSettings::ftpServerName() + "/qtest/bigfile";
}
void tst_QNetworkReply::getFromFtp()
@@ -1833,7 +1863,7 @@ void tst_QNetworkReply::getFromFtp()
void tst_QNetworkReply::getFromFtpAfterError()
{
- QNetworkRequest invalidRequest(QUrl("ftp://" + QtNetworkSettings::serverName() + "/qtest/invalid.txt"));
+ QNetworkRequest invalidRequest(QUrl("ftp://" + QtNetworkSettings::ftpServerName() + "/qtest/invalid.txt"));
QNetworkReplyPtr invalidReply;
invalidReply.reset(manager.get(invalidRequest));
QSignalSpy spy(invalidReply.data(), SIGNAL(error(QNetworkReply::NetworkError)));
@@ -1842,7 +1872,7 @@ void tst_QNetworkReply::getFromFtpAfterError()
QFile reference(testDataDir + "/rfc3252.txt");
QVERIFY(reference.open(QIODevice::ReadOnly));
- QNetworkRequest validRequest(QUrl("ftp://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"));
+ QNetworkRequest validRequest(QUrl("ftp://" + QtNetworkSettings::ftpServerName() + "/qtest/rfc3252.txt"));
QNetworkReplyPtr validReply;
RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::GetOperation, validRequest, validReply));
QCOMPARE(validReply->url(), validRequest.url());
@@ -1856,9 +1886,17 @@ void tst_QNetworkReply::getFromHttp_data()
QTest::addColumn<QString>("referenceName");
QTest::addColumn<QString>("url");
- QTest::newRow("success-internal") << (testDataDir + "/rfc3252.txt") << "http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt";
- QTest::newRow("success-external") << (testDataDir + "/rfc3252.txt") << "http://www.ietf.org/rfc/rfc3252.txt";
- QTest::newRow("bigfile-internal") << (testDataDir + "/bigfile") << "http://" + QtNetworkSettings::serverName() + "/qtest/bigfile";
+ QTest::newRow("success-internal")
+ << testDataDir + "/rfc3252.txt"
+ << "http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt";
+
+ QTest::newRow("success-external")
+ << testDataDir + "/rfc3252.txt"
+ << "http://www.ietf.org/rfc/rfc3252.txt";
+
+ QTest::newRow("bigfile-internal")
+ << testDataDir + "/bigfile"
+ << "http://" + QtNetworkSettings::httpServerName() + "/qtest/bigfile";
}
void tst_QNetworkReply::getFromHttp()
@@ -1898,15 +1936,45 @@ void tst_QNetworkReply::headFromHttp_data()
qint64 rfcsize = QFileInfo(testDataDir + "/rfc3252.txt").size();
qint64 bigfilesize = QFileInfo(testDataDir + "/bigfile").size();
+
+#if defined(QT_TEST_SERVER)
+ qint64 indexsize = QFileInfo(testDataDir + "/testserver_index.html").size();
+#else
qint64 indexsize = QFileInfo(testDataDir + "/index.html").size();
+#endif
+ QString httpServer = QtNetworkSettings::httpServerName();
//testing proxies, mainly for the 407 response from http proxy
for (int i = 0; i < proxies.count(); ++i) {
- QTest::newRow("rfc" + proxies.at(i).tag) << rfcsize << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt") << "text/plain" << proxies.at(i).proxy;
- QTest::newRow("bigfile" + proxies.at(i).tag) << bigfilesize << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/bigfile") << "text/plain" << proxies.at(i).proxy;
- QTest::newRow("index" + proxies.at(i).tag) << indexsize << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/") << "text/html" << proxies.at(i).proxy;
- QTest::newRow("with-authentication" + proxies.at(i).tag) << rfcsize << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfcs-auth/rfc3252.txt") << "text/plain" << proxies.at(i).proxy;
- QTest::newRow("cgi" + proxies.at(i).tag) << (qint64)-1 << QUrl("http://qt-test-server/qtest/cgi-bin/httpcachetest_expires500.cgi") << "text/html" << proxies.at(i).proxy;
+ QTest::newRow("rfc" + proxies.at(i).tag)
+ << rfcsize
+ << QUrl("http://" + httpServer + "/qtest/rfc3252.txt")
+ << "text/plain"
+ << proxies.at(i).proxy;
+
+ QTest::newRow("bigfile" + proxies.at(i).tag)
+ << bigfilesize
+ << QUrl("http://" + httpServer + "/qtest/bigfile")
+ << "text/plain"
+ << proxies.at(i).proxy;
+
+ QTest::newRow("index" + proxies.at(i).tag)
+ << indexsize
+ << QUrl("http://" + httpServer + "/qtest/")
+ << "text/html"
+ << proxies.at(i).proxy;
+
+ QTest::newRow("with-authentication" + proxies.at(i).tag)
+ << rfcsize
+ << QUrl("http://" + httpServer + "/qtest/rfcs-auth/rfc3252.txt")
+ << "text/plain"
+ << proxies.at(i).proxy;
+
+ QTest::newRow("cgi" + proxies.at(i).tag)
+ << (qint64)-1
+ << QUrl("http://" + httpServer + "/qtest/cgi-bin/httpcachetest_expires500.cgi")
+ << "text/html"
+ << proxies.at(i).proxy;
}
}
@@ -1988,23 +2056,23 @@ void tst_QNetworkReply::getErrors_data()
// ftp: errors
QTest::newRow("ftp-host") << "ftp://invalid.test.qt-project.org/foo.txt"
<< int(QNetworkReply::HostNotFoundError) << 0 << true;
- QTest::newRow("ftp-no-path") << "ftp://" + QtNetworkSettings::serverName()
+ QTest::newRow("ftp-no-path") << "ftp://" + QtNetworkSettings::ftpServerName()
<< int(QNetworkReply::ContentOperationNotPermittedError) << 0 << true;
- QTest::newRow("ftp-is-dir") << "ftp://" + QtNetworkSettings::serverName() + "/qtest"
+ QTest::newRow("ftp-is-dir") << "ftp://" + QtNetworkSettings::ftpServerName() + "/qtest"
<< int(QNetworkReply::ContentOperationNotPermittedError) << 0 << true;
- QTest::newRow("ftp-dir-not-readable") << "ftp://" + QtNetworkSettings::serverName() + "/pub/dir-not-readable/foo.txt"
+ QTest::newRow("ftp-dir-not-readable") << "ftp://" + QtNetworkSettings::ftpServerName() + "/pub/dir-not-readable/foo.txt"
<< int(QNetworkReply::ContentAccessDenied) << 0 << true;
- QTest::newRow("ftp-file-not-readable") << "ftp://" + QtNetworkSettings::serverName() + "/pub/file-not-readable.txt"
+ QTest::newRow("ftp-file-not-readable") << "ftp://" + QtNetworkSettings::ftpServerName() + "/pub/file-not-readable.txt"
<< int(QNetworkReply::ContentAccessDenied) << 0 << true;
- QTest::newRow("ftp-exist") << "ftp://" + QtNetworkSettings::serverName() + "/pub/this-file-doesnt-exist.txt"
+ QTest::newRow("ftp-exist") << "ftp://" + QtNetworkSettings::ftpServerName() + "/pub/this-file-doesnt-exist.txt"
<< int(QNetworkReply::ContentNotFoundError) << 0 << true;
// http: errors
QTest::newRow("http-host") << "http://invalid.test.qt-project.org/"
<< int(QNetworkReply::HostNotFoundError) << 0 << true;
- QTest::newRow("http-exist") << "http://" + QtNetworkSettings::serverName() + "/this-file-doesnt-exist.txt"
+ QTest::newRow("http-exist") << "http://" + QtNetworkSettings::httpServerName() + "/this-file-doesnt-exist.txt"
<< int(QNetworkReply::ContentNotFoundError) << 404 << false;
- QTest::newRow("http-authentication") << "http://" + QtNetworkSettings::serverName() + "/qtest/rfcs-auth"
+ QTest::newRow("http-authentication") << "http://" + QtNetworkSettings::httpServerName() + "/qtest/rfcs-auth"
<< int(QNetworkReply::AuthenticationRequiredError) << 401 << false;
}
@@ -2130,7 +2198,7 @@ void tst_QNetworkReply::putToFtp_data()
void tst_QNetworkReply::putToFtp()
{
- QUrl url("ftp://" + QtNetworkSettings::serverName());
+ QUrl url("ftp://" + QtNetworkSettings::ftpServerName());
url.setPath(QString("/qtest/upload/qnetworkaccess-putToFtp-%1-%2")
.arg(QTest::currentDataTag())
.arg(uniqueExtension));
@@ -2176,7 +2244,7 @@ void tst_QNetworkReply::putToFtp()
void tst_QNetworkReply::putToFtpWithInvalidCredentials()
{
- QUrl url("ftp://" + QtNetworkSettings::serverName());
+ QUrl url("ftp://" + QtNetworkSettings::ftpServerName());
url.setPath(QString("/qtest/upload/qnetworkaccess-putToFtp-%1-%2")
.arg(QTest::currentDataTag())
.arg(uniqueExtension));
@@ -2203,7 +2271,7 @@ void tst_QNetworkReply::putToHttp_data()
void tst_QNetworkReply::putToHttp()
{
- QUrl url("http://" + QtNetworkSettings::serverName());
+ QUrl url("http://" + QtNetworkSettings::httpServerName());
url.setPath(QString("/dav/qnetworkaccess-putToHttp-%1-%2")
.arg(QTest::currentDataTag())
.arg(uniqueExtension));
@@ -2223,7 +2291,7 @@ void tst_QNetworkReply::putToHttp()
// download the file again from HTTP to make sure it was uploaded
// correctly. HTTP/0.9 is enough
QTcpSocket socket;
- socket.connectToHost(QtNetworkSettings::serverName(), 80);
+ socket.connectToHost(QtNetworkSettings::httpServerName(), 80);
socket.write("GET " + url.toEncoded(QUrl::RemoveScheme | QUrl::RemoveAuthority) + "\r\n");
if (!socket.waitForDisconnected(10000))
QFAIL("Network timeout");
@@ -2240,7 +2308,7 @@ void tst_QNetworkReply::putToHttpSynchronous_data()
void tst_QNetworkReply::putToHttpSynchronous()
{
- QUrl url("http://" + QtNetworkSettings::serverName());
+ QUrl url("http://" + QtNetworkSettings::httpServerName());
url.setPath(QString("/dav/qnetworkaccess-putToHttp-%1-%2")
.arg(QTest::currentDataTag())
.arg(uniqueExtension));
@@ -2264,7 +2332,7 @@ void tst_QNetworkReply::putToHttpSynchronous()
// download the file again from HTTP to make sure it was uploaded
// correctly. HTTP/0.9 is enough
QTcpSocket socket;
- socket.connectToHost(QtNetworkSettings::serverName(), 80);
+ socket.connectToHost(QtNetworkSettings::httpServerName(), 80);
socket.write("GET " + url.toEncoded(QUrl::RemoveScheme | QUrl::RemoveAuthority) + "\r\n");
if (!socket.waitForDisconnected(10000))
QFAIL("Network timeout");
@@ -2280,7 +2348,7 @@ void tst_QNetworkReply::postToHttp_data()
void tst_QNetworkReply::postToHttp()
{
- QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi");
+ QUrl url("http://" + QtNetworkSettings::httpServerName() + "/qtest/cgi-bin/md5sum.cgi");
QNetworkRequest request(url);
request.setRawHeader("Content-Type", "application/octet-stream");
@@ -2307,7 +2375,7 @@ void tst_QNetworkReply::postToHttpSynchronous_data()
void tst_QNetworkReply::postToHttpSynchronous()
{
- QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi");
+ QUrl url("http://" + QtNetworkSettings::httpServerName() + "/qtest/cgi-bin/md5sum.cgi");
QNetworkRequest request(url);
request.setRawHeader("Content-Type", "application/octet-stream");
@@ -2339,7 +2407,7 @@ void tst_QNetworkReply::postToHttpMultipart_data()
QTest::addColumn<QByteArray>("expectedReplyData");
QTest::addColumn<QByteArray>("contentType");
- QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/multipart.cgi");
+ QUrl url("http://" + QtNetworkSettings::httpServerName() + "/qtest/cgi-bin/multipart.cgi");
QByteArray expectedData;
@@ -2388,8 +2456,13 @@ void tst_QNetworkReply::postToHttpMultipart_data()
multiPart2->setContentType(QHttpMultiPart::FormDataType);
multiPart2->append(textPart);
multiPart2->append(textPart2);
+#ifdef QT_TEST_SERVER
+ expectedData = "key: text, value: 7 bytes\n"
+ "key: text2, value: some more bytes\n";
+#else
expectedData = "key: text2, value: some more bytes\n"
"key: text, value: 7 bytes\n";
+#endif
QTest::newRow("text-text") << url << multiPart2 << expectedData << QByteArray("form-data");
@@ -2457,9 +2530,15 @@ void tst_QNetworkReply::postToHttpMultipart_data()
imagePart22.setBodyDevice(file22);
imageMultiPart2->append(imagePart22);
file22->setParent(imageMultiPart2);
+#ifdef QT_TEST_SERVER
+ expectedData = "key: text, value: 7 bytes\n"
+ "key: testImage1, value: 87ef3bb319b004ba9e5e9c9fa713776e\n"
+ "key: testImage2, value: 483761b893f7fb1bd2414344cd1f3dfb\n";
+#else
expectedData = "key: testImage1, value: 87ef3bb319b004ba9e5e9c9fa713776e\n"
"key: text, value: 7 bytes\n"
"key: testImage2, value: 483761b893f7fb1bd2414344cd1f3dfb\n";
+#endif
QTest::newRow("text-image-image") << url << imageMultiPart2 << expectedData << QByteArray("form-data");
@@ -2591,7 +2670,7 @@ void tst_QNetworkReply::postToHttpMultipart()
void tst_QNetworkReply::multipartSkipIndices() // QTBUG-32534
{
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::MixedType);
- QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/multipart.cgi");
+ QUrl url("http://" + QtNetworkSettings::httpServerName() + "/qtest/cgi-bin/multipart.cgi");
QNetworkRequest request(url);
QList<QByteArray> parts;
parts << QByteArray(56083, 'X') << QByteArray(468, 'X') << QByteArray(24952, 'X');
@@ -2685,13 +2764,13 @@ void tst_QNetworkReply::putToHttps_data()
void tst_QNetworkReply::putToHttps()
{
- QUrl url("https://" + QtNetworkSettings::serverName());
+ QUrl url("https://" + QtNetworkSettings::httpServerName());
url.setPath(QString("/dav/qnetworkaccess-putToHttp-%1-%2")
.arg(QTest::currentDataTag())
.arg(uniqueExtension));
QNetworkRequest request(url);
- QList<QSslCertificate> certs = QSslCertificate::fromPath(testDataDir + "/certs/qt-test-server-cacert.pem");
+ QList<QSslCertificate> certs = QSslCertificate::fromPath(testDataDir + certsFilePath);
QSslConfiguration conf;
conf.setCaCertificates(certs);
request.setSslConfiguration(conf);
@@ -2709,7 +2788,7 @@ void tst_QNetworkReply::putToHttps()
// download the file again from HTTP to make sure it was uploaded
// correctly. HTTP/0.9 is enough
QTcpSocket socket;
- socket.connectToHost(QtNetworkSettings::serverName(), 80);
+ socket.connectToHost(QtNetworkSettings::httpServerName(), 80);
socket.write("GET " + url.toEncoded(QUrl::RemoveScheme | QUrl::RemoveAuthority) + "\r\n");
if (!socket.waitForDisconnected(10000))
QFAIL("Network timeout");
@@ -2726,13 +2805,13 @@ void tst_QNetworkReply::putToHttpsSynchronous_data()
void tst_QNetworkReply::putToHttpsSynchronous()
{
- QUrl url("https://" + QtNetworkSettings::serverName());
+ QUrl url("https://" + QtNetworkSettings::httpServerName());
url.setPath(QString("/dav/qnetworkaccess-putToHttp-%1-%2")
.arg(QTest::currentDataTag())
.arg(uniqueExtension));
QNetworkRequest request(url);
- QList<QSslCertificate> certs = QSslCertificate::fromPath(testDataDir + "/certs/qt-test-server-cacert.pem");
+ QList<QSslCertificate> certs = QSslCertificate::fromPath(testDataDir + certsFilePath);
QSslConfiguration conf;
conf.setCaCertificates(certs);
request.setSslConfiguration(conf);
@@ -2754,7 +2833,7 @@ void tst_QNetworkReply::putToHttpsSynchronous()
// download the file again from HTTP to make sure it was uploaded
// correctly. HTTP/0.9 is enough
QTcpSocket socket;
- socket.connectToHost(QtNetworkSettings::serverName(), 80);
+ socket.connectToHost(QtNetworkSettings::httpServerName(), 80);
socket.write("GET " + url.toEncoded(QUrl::RemoveScheme | QUrl::RemoveAuthority) + "\r\n");
if (!socket.waitForDisconnected(10000))
QFAIL("Network timeout");
@@ -2770,10 +2849,10 @@ void tst_QNetworkReply::postToHttps_data()
void tst_QNetworkReply::postToHttps()
{
- QUrl url("https://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi");
+ QUrl url("https://" + QtNetworkSettings::httpServerName() + "/qtest/cgi-bin/md5sum.cgi");
QNetworkRequest request(url);
- QList<QSslCertificate> certs = QSslCertificate::fromPath(testDataDir + "/certs/qt-test-server-cacert.pem");
+ QList<QSslCertificate> certs = QSslCertificate::fromPath(testDataDir + certsFilePath);
QSslConfiguration conf;
conf.setCaCertificates(certs);
request.setSslConfiguration(conf);
@@ -2801,10 +2880,10 @@ void tst_QNetworkReply::postToHttpsSynchronous_data()
void tst_QNetworkReply::postToHttpsSynchronous()
{
- QUrl url("https://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi");
+ QUrl url("https://" + QtNetworkSettings::httpServerName() + "/qtest/cgi-bin/md5sum.cgi");
QNetworkRequest request(url);
- QList<QSslCertificate> certs = QSslCertificate::fromPath(testDataDir + "/certs/qt-test-server-cacert.pem");
+ QList<QSslCertificate> certs = QSslCertificate::fromPath(testDataDir + certsFilePath);
QSslConfiguration conf;
conf.setCaCertificates(certs);
request.setSslConfiguration(conf);
@@ -2843,7 +2922,7 @@ void tst_QNetworkReply::postToHttpsMultipart()
static QSet<QByteArray> boundaries;
QNetworkRequest request(url);
- QList<QSslCertificate> certs = QSslCertificate::fromPath(testDataDir + "/certs/qt-test-server-cacert.pem");
+ QList<QSslCertificate> certs = QSslCertificate::fromPath(testDataDir + certsFilePath);
QSslConfiguration conf;
conf.setCaCertificates(certs);
request.setSslConfiguration(conf);
@@ -2888,11 +2967,26 @@ void tst_QNetworkReply::deleteFromHttp_data()
// for status codes to expect, see http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
- QTest::newRow("405-method-not-allowed") << QUrl("http://" + QtNetworkSettings::serverName() + "/index.html") << 405 << QNetworkReply::ContentOperationNotPermittedError;
- QTest::newRow("200-ok") << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/http-delete.cgi?200-ok") << 200 << QNetworkReply::NoError;
- QTest::newRow("202-accepted") << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/http-delete.cgi?202-accepted") << 202 << QNetworkReply::NoError;
- QTest::newRow("204-no-content") << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/http-delete.cgi?204-no-content") << 204 << QNetworkReply::NoError;
- QTest::newRow("404-not-found") << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/http-delete.cgi?404-not-found") << 404 << QNetworkReply::ContentNotFoundError;
+ QString httpServer = QtNetworkSettings::httpServerName();
+ QTest::newRow("405-method-not-allowed")
+ << QUrl("http://" + httpServer + "/index.html")
+ << 405 << QNetworkReply::ContentOperationNotPermittedError;
+
+ QTest::newRow("200-ok")
+ << QUrl("http://" + httpServer + "/qtest/cgi-bin/http-delete.cgi?200-ok")
+ << 200 << QNetworkReply::NoError;
+
+ QTest::newRow("202-accepted")
+ << QUrl("http://" + httpServer + "/qtest/cgi-bin/http-delete.cgi?202-accepted")
+ << 202 << QNetworkReply::NoError;
+
+ QTest::newRow("204-no-content")
+ << QUrl("http://" + httpServer + "/qtest/cgi-bin/http-delete.cgi?204-no-content")
+ << 204 << QNetworkReply::NoError;
+
+ QTest::newRow("404-not-found")
+ << QUrl("http://" + httpServer + "/qtest/cgi-bin/http-delete.cgi?404-not-found")
+ << 404 << QNetworkReply::ContentNotFoundError;
}
void tst_QNetworkReply::deleteFromHttp()
@@ -2920,7 +3014,7 @@ void tst_QNetworkReply::putGetDeleteGetFromHttp_data()
QTest::addColumn<int>("get2ResultCode");
QTest::addColumn<QNetworkReply::NetworkError>("get2Error");
- QUrl url("http://" + QtNetworkSettings::serverName());
+ QUrl url("http://" + QtNetworkSettings::httpServerName());
url.setPath(QString("/dav/qnetworkaccess-putToHttp-%1-%2")
.arg(QTest::currentDataTag())
.arg(uniqueExtension));
@@ -2928,7 +3022,7 @@ void tst_QNetworkReply::putGetDeleteGetFromHttp_data()
// first use case: put, get (to check it is there), delete, get (to check it is not there anymore)
QTest::newRow("success") << url << 201 << QNetworkReply::NoError << url << 204 << QNetworkReply::NoError << url << 404 << QNetworkReply::ContentNotFoundError;
- QUrl wrongUrl("http://" + QtNetworkSettings::serverName());
+ QUrl wrongUrl("http://" + QtNetworkSettings::httpServerName());
wrongUrl.setPath(QString("/dav/qnetworkaccess-thisURLisNotAvailable"));
// second use case: put, get (to check it is there), delete wrong URL, get (to check it is still there)
@@ -3023,27 +3117,27 @@ void tst_QNetworkReply::sendCustomRequestToHttp_data()
QTest::addColumn<QNetworkReply::NetworkError>("error");
QTest::addColumn<QByteArray>("expectedContent");
- QTest::newRow("options") << QUrl("http://" + QtNetworkSettings::serverName()) <<
+ QTest::newRow("options") << QUrl("http://" + QtNetworkSettings::httpServerName()) <<
QByteArray("OPTIONS") << (QBuffer *) 0 << 200 << QNetworkReply::NoError << QByteArray();
- QTest::newRow("trace") << QUrl("http://" + QtNetworkSettings::serverName()) <<
+ QTest::newRow("trace") << QUrl("http://" + QtNetworkSettings::httpServerName()) <<
QByteArray("TRACE") << (QBuffer *) 0 << 200 << QNetworkReply::NoError << QByteArray();
- QTest::newRow("connect") << QUrl("http://" + QtNetworkSettings::serverName()) <<
+ QTest::newRow("connect") << QUrl("http://" + QtNetworkSettings::httpServerName()) <<
QByteArray("CONNECT") << (QBuffer *) 0 << 400 << QNetworkReply::ProtocolInvalidOperationError << QByteArray(); // 400 = Bad Request
- QTest::newRow("nonsense") << QUrl("http://" + QtNetworkSettings::serverName()) <<
+ QTest::newRow("nonsense") << QUrl("http://" + QtNetworkSettings::httpServerName()) <<
QByteArray("NONSENSE") << (QBuffer *) 0 << 501 << QNetworkReply::OperationNotImplementedError << QByteArray(); // 501 = Method Not Implemented
QByteArray ba("test");
QBuffer *buffer = new QBuffer;
buffer->setData(ba);
buffer->open(QIODevice::ReadOnly);
- QTest::newRow("post") << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi") << QByteArray("POST")
+ QTest::newRow("post") << QUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/cgi-bin/md5sum.cgi") << QByteArray("POST")
<< buffer << 200 << QNetworkReply::NoError << QByteArray("098f6bcd4621d373cade4e832627b4f6\n");
QByteArray ba2("test");
QBuffer *buffer2 = new QBuffer;
buffer2->setData(ba2);
buffer2->open(QIODevice::ReadOnly);
- QTest::newRow("put") << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi") << QByteArray("PUT")
+ QTest::newRow("put") << QUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/cgi-bin/md5sum.cgi") << QByteArray("PUT")
<< buffer2 << 200 << QNetworkReply::NoError << QByteArray("098f6bcd4621d373cade4e832627b4f6\n");
}
@@ -3181,7 +3275,7 @@ void tst_QNetworkReply::ioGetFromFtp()
QFile reference(fileName);
reference.open(QIODevice::ReadOnly); // will fail for bigfile
- QNetworkRequest request("ftp://" + QtNetworkSettings::serverName() + "/qtest/" + fileName);
+ QNetworkRequest request("ftp://" + QtNetworkSettings::ftpServerName() + "/qtest/" + fileName);
QNetworkReplyPtr reply(manager.get(request));
DataReader reader(reply);
@@ -3204,7 +3298,7 @@ void tst_QNetworkReply::ioGetFromFtpWithReuse()
QFile reference(fileName);
reference.open(QIODevice::ReadOnly);
- QNetworkRequest request(QUrl("ftp://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"));
+ QNetworkRequest request(QUrl("ftp://" + QtNetworkSettings::ftpServerName() + "/qtest/rfc3252.txt"));
// two concurrent (actually, consecutive) gets:
QNetworkReplyPtr reply1(manager.get(request));
@@ -3236,7 +3330,7 @@ void tst_QNetworkReply::ioGetFromHttp()
QFile reference(testDataDir + "/rfc3252.txt");
QVERIFY(reference.open(QIODevice::ReadOnly));
- QNetworkRequest request(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"));
+ QNetworkRequest request(QUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"));
QNetworkReplyPtr reply(manager.get(request));
DataReader reader(reply);
@@ -3257,7 +3351,7 @@ void tst_QNetworkReply::ioGetFromHttpWithReuseParallel()
QFile reference(testDataDir + "/rfc3252.txt");
QVERIFY(reference.open(QIODevice::ReadOnly));
- QNetworkRequest request(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"));
+ QNetworkRequest request(QUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"));
QNetworkReplyPtr reply1(manager.get(request));
QNetworkReplyPtr reply2(manager.get(request));
DataReader reader1(reply1);
@@ -3289,7 +3383,7 @@ void tst_QNetworkReply::ioGetFromHttpWithReuseSequential()
QFile reference(testDataDir + "/rfc3252.txt");
QVERIFY(reference.open(QIODevice::ReadOnly));
- QNetworkRequest request(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"));
+ QNetworkRequest request(QUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"));
{
QNetworkReplyPtr reply(manager.get(request));
DataReader reader(reply);
@@ -3334,16 +3428,40 @@ void tst_QNetworkReply::ioGetFromHttpWithAuth_data()
QFile reference(testDataDir + "/rfc3252.txt");
reference.open(QIODevice::ReadOnly);
QByteArray referenceData = reference.readAll();
- QTest::newRow("basic") << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfcs-auth/rfc3252.txt") << referenceData << 1;
- QTest::newRow("digest") << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/auth-digest/") << QByteArray("digest authentication successful\n") << 1;
+ QString httpServer = QtNetworkSettings::httpServerName();
+ QTest::newRow("basic")
+ << QUrl("http://" + httpServer + "/qtest/rfcs-auth/rfc3252.txt")
+ << referenceData << 1;
+
+ QTest::newRow("digest")
+ << QUrl("http://" + httpServer + "/qtest/auth-digest/")
+ << QByteArray("digest authentication successful\n") << 1;
+
//if url contains username & password, then it should be used
- QTest::newRow("basic-in-url") << QUrl("http://httptest:httptest@" + QtNetworkSettings::serverName() + "/qtest/rfcs-auth/rfc3252.txt") << referenceData << 0;
- QTest::newRow("digest-in-url") << QUrl("http://httptest:httptest@" + QtNetworkSettings::serverName() + "/qtest/auth-digest/") << QByteArray("digest authentication successful\n") << 0;
+ QTest::newRow("basic-in-url")
+ << QUrl("http://httptest:httptest@" + httpServer + "/qtest/rfcs-auth/rfc3252.txt")
+ << referenceData << 0;
+
+ QTest::newRow("digest-in-url")
+ << QUrl("http://httptest:httptest@" + httpServer + "/qtest/auth-digest/")
+ << QByteArray("digest authentication successful\n") << 0;
+
// if url contains incorrect credentials, expect QNAM to ask for good ones (even if cached - matches behaviour of browsers)
- QTest::newRow("basic-bad-user-in-url") << QUrl("http://baduser:httptest@" + QtNetworkSettings::serverName() + "/qtest/rfcs-auth/rfc3252.txt") << referenceData << 3;
- QTest::newRow("basic-bad-password-in-url") << QUrl("http://httptest:wrong@" + QtNetworkSettings::serverName() + "/qtest/rfcs-auth/rfc3252.txt") << referenceData << 3;
- QTest::newRow("digest-bad-user-in-url") << QUrl("http://baduser:httptest@" + QtNetworkSettings::serverName() + "/qtest/auth-digest/") << QByteArray("digest authentication successful\n") << 3;
- QTest::newRow("digest-bad-password-in-url") << QUrl("http://httptest:wrong@" + QtNetworkSettings::serverName() + "/qtest/auth-digest/") << QByteArray("digest authentication successful\n") << 3;
+ QTest::newRow("basic-bad-user-in-url")
+ << QUrl("http://baduser:httptest@" + httpServer + "/qtest/rfcs-auth/rfc3252.txt")
+ << referenceData << 3;
+
+ QTest::newRow("basic-bad-password-in-url")
+ << QUrl("http://httptest:wrong@" + httpServer + "/qtest/rfcs-auth/rfc3252.txt")
+ << referenceData << 3;
+
+ QTest::newRow("digest-bad-user-in-url")
+ << QUrl("http://baduser:httptest@" + httpServer + "/qtest/auth-digest/")
+ << QByteArray("digest authentication successful\n") << 3;
+
+ QTest::newRow("digest-bad-password-in-url")
+ << QUrl("http://httptest:wrong@" + httpServer + "/qtest/auth-digest/")
+ << QByteArray("digest authentication successful\n") << 3;
}
void tst_QNetworkReply::ioGetFromHttpWithAuth()
@@ -3459,7 +3577,7 @@ void tst_QNetworkReply::ioGetFromHttpWithAuthSynchronous()
// verify that we do not enter an endless loop with synchronous calls and wrong credentials
// the case when we succeed with the login is tested in ioGetFromHttpWithAuth()
- QNetworkRequest request(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfcs-auth/rfc3252.txt"));
+ QNetworkRequest request(QUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/rfcs-auth/rfc3252.txt"));
request.setAttribute(
QNetworkRequest::SynchronousRequestAttribute,
true);
@@ -3481,8 +3599,8 @@ void tst_QNetworkReply::ioGetFromHttpWithProxyAuth()
QFile reference(testDataDir + "/rfc3252.txt");
QVERIFY(reference.open(QIODevice::ReadOnly));
- QNetworkProxy proxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129);
- QNetworkRequest request(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"));
+ QNetworkProxy proxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129);
+ QNetworkRequest request(QUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"));
{
manager.setProxy(proxy);
QNetworkReplyPtr reply1(manager.get(request));
@@ -3561,8 +3679,8 @@ void tst_QNetworkReply::ioGetFromHttpWithProxyAuthSynchronous()
// verify that we do not enter an endless loop with synchronous calls and wrong credentials
// the case when we succeed with the login is tested in ioGetFromHttpWithAuth()
- QNetworkProxy proxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129);
- QNetworkRequest request(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"));
+ QNetworkProxy proxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129);
+ QNetworkRequest request(QUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"));
manager.setProxy(proxy);
request.setAttribute(
QNetworkRequest::SynchronousRequestAttribute,
@@ -3585,8 +3703,8 @@ void tst_QNetworkReply::ioGetFromHttpWithSocksProxy()
QFile reference(testDataDir + "/rfc3252.txt");
QVERIFY(reference.open(QIODevice::ReadOnly));
- QNetworkProxy proxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080);
- QNetworkRequest request(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"));
+ QNetworkProxy proxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1080);
+ QNetworkRequest request(QUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"));
{
manager.setProxy(proxy);
QNetworkReplyPtr reply(manager.get(request));
@@ -3609,7 +3727,7 @@ void tst_QNetworkReply::ioGetFromHttpWithSocksProxy()
}
// set an invalid proxy just to make sure that we can't load
- proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1079);
+ proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1079);
{
manager.setProxy(proxy);
QNetworkReplyPtr reply(manager.get(request));
@@ -3643,7 +3761,7 @@ void tst_QNetworkReply::ioGetFromHttpsWithSslErrors()
QFile reference(testDataDir + "/rfc3252.txt");
QVERIFY(reference.open(QIODevice::ReadOnly));
- QNetworkRequest request(QUrl("https://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"));
+ QNetworkRequest request(QUrl("https://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"));
QNetworkReplyPtr reply(manager.get(request));
DataReader reader(reply);
@@ -3674,7 +3792,7 @@ void tst_QNetworkReply::ioGetFromHttpsWithIgnoreSslErrors()
QFile reference(testDataDir + "/rfc3252.txt");
QVERIFY(reference.open(QIODevice::ReadOnly));
- QNetworkRequest request(QUrl("https://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"));
+ QNetworkRequest request(QUrl("https://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"));
QNetworkReplyPtr reply(manager.get(request));
reply->ignoreSslErrors();
@@ -3699,7 +3817,7 @@ void tst_QNetworkReply::ioGetFromHttpsWithSslHandshakeError()
QFile reference(testDataDir + "/rfc3252.txt");
QVERIFY(reference.open(QIODevice::ReadOnly));
- QNetworkRequest request(QUrl("https://" + QtNetworkSettings::serverName() + ":80"));
+ QNetworkRequest request(QUrl("https://" + QtNetworkSettings::httpServerName() + ":80"));
QNetworkReplyPtr reply(manager.get(request));
reply->ignoreSslErrors();
@@ -4013,34 +4131,34 @@ void tst_QNetworkReply::ioGetWithManyProxies_data()
// Simple tests that work:
// HTTP request with HTTP caching proxy
- proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129);
+ proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129);
QTest::newRow("http-on-http")
<< proxyList << proxyList.at(0)
- << "http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"
+ << "http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
<< QNetworkReply::NoError;
// HTTP request with HTTP transparent proxy
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3129);
+ proxyList << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::httpProxyServerName(), 3129);
QTest::newRow("http-on-http2")
<< proxyList << proxyList.at(0)
- << "http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"
+ << "http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
<< QNetworkReply::NoError;
// HTTP request with SOCKS transparent proxy
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1081);
+ proxyList << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1081);
QTest::newRow("http-on-socks")
<< proxyList << proxyList.at(0)
- << "http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"
+ << "http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
<< QNetworkReply::NoError;
// FTP request with FTP caching proxy
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121);
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121);
QTest::newRow("ftp-on-ftp")
<< proxyList << proxyList.at(0)
- << "ftp://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"
+ << "ftp://" + QtNetworkSettings::ftpServerName() + "/qtest/rfc3252.txt"
<< QNetworkReply::NoError;
// The following test doesn't work because QFtp is too limited
@@ -4048,27 +4166,27 @@ void tst_QNetworkReply::ioGetWithManyProxies_data()
// FTP request with SOCKSv5 transparent proxy
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1081);
+ proxyList << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1081);
QTest::newRow("ftp-on-socks")
<< proxyList << proxyList.at(0)
- << "ftp://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"
+ << "ftp://" + QtNetworkSettings::ftpServerName() + "/qtest/rfc3252.txt"
<< QNetworkReply::NoError;
#ifndef QT_NO_SSL
// HTTPS with HTTP transparent proxy
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3129);
+ proxyList << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::httpProxyServerName(), 3129);
QTest::newRow("https-on-http")
<< proxyList << proxyList.at(0)
- << "https://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"
+ << "https://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
<< QNetworkReply::NoError;
// HTTPS request with SOCKS transparent proxy
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1081);
+ proxyList << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1081);
QTest::newRow("https-on-socks")
<< proxyList << proxyList.at(0)
- << "https://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"
+ << "https://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
<< QNetworkReply::NoError;
#endif
@@ -4076,44 +4194,44 @@ void tst_QNetworkReply::ioGetWithManyProxies_data()
// HTTP request with FTP caching proxy
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121);
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121);
QTest::newRow("http-on-ftp")
<< proxyList << QNetworkProxy()
- << "http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"
+ << "http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
<< QNetworkReply::ProxyNotFoundError;
// FTP request with HTTP caching proxy
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129);
+ proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129);
QTest::newRow("ftp-on-http")
<< proxyList << QNetworkProxy()
- << "ftp://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"
+ << "ftp://" + QtNetworkSettings::ftpServerName() + "/qtest/rfc3252.txt"
<< QNetworkReply::ProxyNotFoundError;
// FTP request with HTTP caching proxies
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129)
- << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3130);
+ proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129)
+ << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3130);
QTest::newRow("ftp-on-multiple-http")
<< proxyList << QNetworkProxy()
- << "ftp://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"
+ << "ftp://" + QtNetworkSettings::ftpServerName() + "/qtest/rfc3252.txt"
<< QNetworkReply::ProxyNotFoundError;
#ifndef QT_NO_SSL
// HTTPS with HTTP caching proxy
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129);
+ proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129);
QTest::newRow("https-on-httptransparent")
<< proxyList << QNetworkProxy()
- << "https://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"
+ << "https://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
<< QNetworkReply::ProxyNotFoundError;
// HTTPS with FTP caching proxy
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121);
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121);
QTest::newRow("https-on-ftp")
<< proxyList << QNetworkProxy()
- << "https://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"
+ << "https://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
<< QNetworkReply::ProxyNotFoundError;
#endif
@@ -4121,77 +4239,77 @@ void tst_QNetworkReply::ioGetWithManyProxies_data()
// HTTP request with more than one HTTP proxy
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129)
- << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3130);
+ proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129)
+ << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3130);
QTest::newRow("http-on-multiple-http")
<< proxyList << proxyList.at(0)
- << "http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"
+ << "http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
<< QNetworkReply::NoError;
// HTTP request with HTTP + SOCKS
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129)
- << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1081);
+ proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129)
+ << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1081);
QTest::newRow("http-on-http+socks")
<< proxyList << proxyList.at(0)
- << "http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"
+ << "http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
<< QNetworkReply::NoError;
// HTTP request with FTP + HTTP + SOCKS
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121)
- << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129)
- << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1081);
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121)
+ << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129)
+ << QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::socksProxyServerName(), 1081);
QTest::newRow("http-on-ftp+http+socks")
<< proxyList << proxyList.at(1) // second proxy should be used
- << "http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"
+ << "http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
<< QNetworkReply::NoError;
// HTTP request with NoProxy + HTTP
proxyList.clear();
proxyList << QNetworkProxy(QNetworkProxy::NoProxy)
- << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129);
+ << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129);
QTest::newRow("http-on-noproxy+http")
<< proxyList << proxyList.at(0)
- << "http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"
+ << "http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
<< QNetworkReply::NoError;
// HTTP request with FTP + NoProxy
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121)
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121)
<< QNetworkProxy(QNetworkProxy::NoProxy);
QTest::newRow("http-on-ftp+noproxy")
<< proxyList << proxyList.at(1) // second proxy should be used
- << "http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"
+ << "http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
<< QNetworkReply::NoError;
// FTP request with HTTP Caching + FTP
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129)
- << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121);
+ proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129)
+ << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121);
QTest::newRow("ftp-on-http+ftp")
<< proxyList << proxyList.at(1) // second proxy should be used
- << "ftp://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"
+ << "ftp://" + QtNetworkSettings::ftpServerName() + "/qtest/rfc3252.txt"
<< QNetworkReply::NoError;
#ifndef QT_NO_SSL
// HTTPS request with HTTP Caching + HTTP transparent
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129)
- << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3129);
+ proxyList << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129)
+ << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::httpProxyServerName(), 3129);
QTest::newRow("https-on-httpcaching+http")
<< proxyList << proxyList.at(1) // second proxy should be used
- << "https://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"
+ << "https://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
<< QNetworkReply::NoError;
// HTTPS request with FTP + HTTP C + HTTP T
proxyList.clear();
- proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::serverName(), 2121)
- << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::serverName(), 3129)
- << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3129);
+ proxyList << QNetworkProxy(QNetworkProxy::FtpCachingProxy, QtNetworkSettings::ftpProxyServerName(), 2121)
+ << QNetworkProxy(QNetworkProxy::HttpCachingProxy, QtNetworkSettings::httpProxyServerName(), 3129)
+ << QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::httpProxyServerName(), 3129);
QTest::newRow("https-on-ftp+httpcaching+http")
<< proxyList << proxyList.at(2) // skip the first two
- << "https://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"
+ << "https://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"
<< QNetworkReply::NoError;
#endif
}
@@ -4442,7 +4560,7 @@ void tst_QNetworkReply::ioPutToFtpFromFile()
QFile sourceFile(fileName);
QVERIFY(sourceFile.open(QIODevice::ReadOnly));
- QUrl url("ftp://" + QtNetworkSettings::serverName());
+ QUrl url("ftp://" + QtNetworkSettings::ftpServerName());
url.setPath(QString("/qtest/upload/qnetworkaccess-ioPutToFtpFromFile-%1-%2")
.arg(QTest::currentDataTag())
.arg(uniqueExtension));
@@ -4491,7 +4609,7 @@ void tst_QNetworkReply::ioPutToHttpFromFile()
QFile sourceFile(fileName);
QVERIFY(sourceFile.open(QIODevice::ReadOnly));
- QUrl url("http://" + QtNetworkSettings::serverName());
+ QUrl url("http://" + QtNetworkSettings::httpServerName());
url.setPath(QString("/dav/qnetworkaccess-ioPutToHttpFromFile-%1-%2")
.arg(QTest::currentDataTag())
.arg(uniqueExtension));
@@ -4534,7 +4652,7 @@ void tst_QNetworkReply::ioPostToHttpFromFile()
QFile sourceFile(fileName);
QVERIFY(sourceFile.open(QIODevice::ReadOnly));
- QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi");
+ QUrl url("http://" + QtNetworkSettings::httpServerName() + "/qtest/cgi-bin/md5sum.cgi");
QNetworkRequest request(url);
request.setRawHeader("Content-Type", "application/octet-stream");
@@ -4568,9 +4686,9 @@ void tst_QNetworkReply::ioPostToHttpFromSocket_data()
for (int auth = 0; auth < 2; ++auth) {
QUrl url;
if (auth)
- url = "http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi";
+ url = "http://" + QtNetworkSettings::httpServerName() + "/qtest/protected/cgi-bin/md5sum.cgi";
else
- url = "http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi";
+ url = "http://" + QtNetworkSettings::httpServerName() + "/qtest/cgi-bin/md5sum.cgi";
QNetworkProxy proxy = proxies.at(i).proxy;
QByteArray testsuffix = QByteArray(auth ? "+auth" : "") + proxies.at(i).tag;
@@ -4685,7 +4803,7 @@ void tst_QNetworkReply::ioPostToHttpFromSocketSynchronous()
// ### for 4.8: make the socket pair unbuffered, to not read everything in one go in QNetworkReplyImplPrivate::setup()
QTestEventLoop::instance().enterLoop(3);
- QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi");
+ QUrl url("http://" + QtNetworkSettings::httpServerName() + "/qtest/cgi-bin/md5sum.cgi");
QNetworkRequest request(url);
request.setRawHeader("Content-Type", "application/octet-stream");
request.setAttribute(
@@ -4716,7 +4834,7 @@ void tst_QNetworkReply::ioPostToHttpFromMiddleOfFileToEnd()
// seeking to the middle
sourceFile.seek(sourceFile.size() / 2);
- QUrl url = "http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi";
+ QUrl url = "http://" + QtNetworkSettings::httpServerName() + "/qtest/protected/cgi-bin/md5sum.cgi";
QNetworkRequest request(url);
request.setRawHeader("Content-Type", "application/octet-stream");
QNetworkReplyPtr reply(manager.post(request, &sourceFile));
@@ -4742,7 +4860,7 @@ void tst_QNetworkReply::ioPostToHttpFromMiddleOfFileFiveBytes()
// seeking to the middle
sourceFile.seek(sourceFile.size() / 2);
- QUrl url = "http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi";
+ QUrl url = "http://" + QtNetworkSettings::httpServerName() + "/qtest/protected/cgi-bin/md5sum.cgi";
QNetworkRequest request(url);
request.setRawHeader("Content-Type", "application/octet-stream");
// only send 5 bytes
@@ -4773,7 +4891,7 @@ void tst_QNetworkReply::ioPostToHttpFromMiddleOfQBufferFiveBytes()
uploadBuffer.write("1234567890");
uploadBuffer.seek(5);
- QUrl url = "http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi";
+ QUrl url = "http://" + QtNetworkSettings::httpServerName() + "/qtest/protected/cgi-bin/md5sum.cgi";
QNetworkRequest request(url);
request.setRawHeader("Content-Type", "application/octet-stream");
QNetworkReplyPtr reply(manager.post(request, &uploadBuffer));
@@ -4801,7 +4919,7 @@ void tst_QNetworkReply::ioPostToHttpNoBufferFlag()
QTRY_VERIFY(socketpair.create()); //QTRY_VERIFY as a workaround for QTBUG-24451
socketpair.endPoints[0]->write(data);
- QUrl url = "http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi";
+ QUrl url = "http://" + QtNetworkSettings::httpServerName() + "/qtest/protected/cgi-bin/md5sum.cgi";
QNetworkRequest request(url);
request.setRawHeader("Content-Type", "application/octet-stream");
// disallow buffering
@@ -5216,7 +5334,7 @@ void tst_QNetworkReply::lastModifiedHeaderForFile()
void tst_QNetworkReply::lastModifiedHeaderForHttp()
{
// Tue, 22 May 2007 12:04:57 GMT according to webserver
- QUrl url = "http://" + QtNetworkSettings::serverName() + "/qtest/fluke.gif";
+ QUrl url = "http://" + QtNetworkSettings::httpServerName() + "/qtest/fluke.gif";
QNetworkRequest request(url);
QNetworkReplyPtr reply(manager.head(request));
@@ -5232,7 +5350,7 @@ void tst_QNetworkReply::lastModifiedHeaderForHttp()
void tst_QNetworkReply::httpCanReadLine()
{
- QNetworkRequest request(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"));
+ QNetworkRequest request(QUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt"));
QNetworkReplyPtr reply(manager.get(request));
QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply));
@@ -5312,11 +5430,11 @@ void tst_QNetworkReply::downloadProgress_data()
QTest::addColumn<int>("expectedSize");
QTest::newRow("empty") << QUrl::fromLocalFile(QFINDTESTDATA("empty")) << 0;
- QTest::newRow("http:small") << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt") << 25962;
- QTest::newRow("http:big") << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/bigfile") << 519240;
- QTest::newRow("http:no-length") << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/deflate/rfc2616.html") << -1;
- QTest::newRow("ftp:small") << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt") << 25962;
- QTest::newRow("ftp:big") << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/bigfile") << 519240;
+ QTest::newRow("http:small") << QUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt") << 25962;
+ QTest::newRow("http:big") << QUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/bigfile") << 519240;
+ QTest::newRow("http:no-length") << QUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/deflate/rfc2616.html") << -1;
+ QTest::newRow("ftp:small") << QUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt") << 25962;
+ QTest::newRow("ftp:big") << QUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/bigfile") << 519240;
}
class SlowReader : public QObject
@@ -5473,7 +5591,7 @@ void tst_QNetworkReply::receiveCookiesFromHttp_data()
QList<QNetworkCookie> header, jar;
QNetworkCookie cookie("a", "b");
header << cookie;
- cookie.setDomain(QtNetworkSettings::serverName());
+ cookie.setDomain(QtNetworkSettings::httpServerName());
cookie.setPath("/qtest/cgi-bin/");
jar << cookie;
QTest::newRow("simple-cookie") << "a=b" << header << jar;
@@ -5497,7 +5615,7 @@ void tst_QNetworkReply::receiveCookiesFromHttp_data()
cookie = QNetworkCookie("a", "b");
cookie.setPath("/not/part-of-path");
header << cookie;
- cookie.setDomain(QtNetworkSettings::serverName());
+ cookie.setDomain(QtNetworkSettings::httpServerName());
jar << cookie;
QTest::newRow("invalid-cookie-path") << "a=b; path=/not/part-of-path" << header << jar;
@@ -5514,7 +5632,7 @@ void tst_QNetworkReply::receiveCookiesFromHttp()
QFETCH(QString, cookieString);
QByteArray data = cookieString.toLatin1() + '\n';
- QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/set-cookie.cgi");
+ QUrl url("http://" + QtNetworkSettings::httpServerName() + "/qtest/cgi-bin/set-cookie.cgi");
QNetworkRequest request(url);
request.setRawHeader("Content-Type", "application/octet-stream");
QNetworkReplyPtr reply;
@@ -5541,7 +5659,7 @@ void tst_QNetworkReply::receiveCookiesFromHttpSynchronous()
QFETCH(QString, cookieString);
QByteArray data = cookieString.toLatin1() + '\n';
- QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/set-cookie.cgi");
+ QUrl url("http://" + QtNetworkSettings::httpServerName() + "/qtest/cgi-bin/set-cookie.cgi");
QNetworkRequest request(url);
request.setRawHeader("Content-Type", "application/octet-stream");
@@ -5577,7 +5695,7 @@ void tst_QNetworkReply::sendCookies_data()
list << cookie;
QTest::newRow("no-match-domain") << list << "";
- cookie.setDomain(QtNetworkSettings::serverName());
+ cookie.setDomain(QtNetworkSettings::httpServerName());
cookie.setPath("/something/else");
list << cookie;
QTest::newRow("no-match-path") << list << "";
@@ -5610,7 +5728,7 @@ void tst_QNetworkReply::sendCookies()
QFETCH(QList<QNetworkCookie>, cookiesToSet);
cookieJar->setAllCookies(cookiesToSet);
- QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/get-cookie.cgi");
+ QUrl url("http://" + QtNetworkSettings::httpServerName() + "/qtest/cgi-bin/get-cookie.cgi");
QNetworkRequest request(url);
QNetworkReplyPtr reply;
RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::GetOperation, request, reply));
@@ -5634,7 +5752,7 @@ void tst_QNetworkReply::sendCookiesSynchronous()
QFETCH(QList<QNetworkCookie>, cookiesToSet);
cookieJar->setAllCookies(cookiesToSet);
- QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/get-cookie.cgi");
+ QUrl url("http://" + QtNetworkSettings::httpServerName() + "/qtest/cgi-bin/get-cookie.cgi");
QNetworkRequest request(url);
request.setAttribute(
@@ -5682,7 +5800,7 @@ void tst_QNetworkReply::nestedEventLoops()
qDebug("Takes 16 seconds to run, please wait");
- QUrl url("http://" + QtNetworkSettings::serverName());
+ QUrl url("http://" + QtNetworkSettings::httpServerName());
QNetworkRequest request(url);
QNetworkReplyPtr reply(manager.get(request));
@@ -5840,7 +5958,7 @@ void tst_QNetworkReply::proxyChange()
"HTTP/1.0 200 OK\r\nProxy-Connection: keep-alive\r\n"
"Content-Length: 1\r\n\r\n1");
QNetworkProxy dummyProxy(QNetworkProxy::HttpProxy, "127.0.0.1", proxyServer.serverPort());
- QNetworkRequest req(QUrl("http://" + QtNetworkSettings::serverName()));
+ QNetworkRequest req(QUrl("http://" + QtNetworkSettings::httpServerName()));
proxyServer.doClose = false;
{
@@ -5899,13 +6017,17 @@ void tst_QNetworkReply::authorizationError_data()
QTest::addColumn<int>("httpStatusCode");
QTest::addColumn<QString>("httpBody");
- QTest::newRow("unknown-authorization-method") << "http://" + QtNetworkSettings::serverName() +
- "/qtest/cgi-bin/http-unknown-authentication-method.cgi?401-authorization-required" << 1 << 1
- << int(QNetworkReply::AuthenticationRequiredError) << 401 << "authorization required";
- QTest::newRow("unknown-proxy-authorization-method") << "http://" + QtNetworkSettings::serverName() +
- "/qtest/cgi-bin/http-unknown-authentication-method.cgi?407-proxy-authorization-required" << 1 << 1
- << int(QNetworkReply::ProxyAuthenticationRequiredError) << 407
- << "authorization required";
+ QTest::newRow("unknown-authorization-method")
+ << "http://" + QtNetworkSettings::httpServerName()
+ + "/qtest/cgi-bin/http-unknown-authentication-method.cgi?401-authorization-required"
+ << 1 << 1 << int(QNetworkReply::AuthenticationRequiredError)
+ << 401 << "authorization required";
+
+ QTest::newRow("unknown-proxy-authorization-method")
+ << "http://" + QtNetworkSettings::httpServerName()
+ + "/qtest/cgi-bin/http-unknown-authentication-method.cgi?407-proxy-authorization-required"
+ << 1 << 1 << int(QNetworkReply::ProxyAuthenticationRequiredError)
+ << 407 << "authorization required";
}
void tst_QNetworkReply::authorizationError()
@@ -6124,7 +6246,7 @@ public slots:
}
void startOne()
{
- QUrl url = "http://" + QtNetworkSettings::serverName() + "/qtest/fluke.gif";
+ QUrl url = "http://" + QtNetworkSettings::httpServerName() + "/qtest/fluke.gif";
QNetworkRequest request(url);
QNetworkReply *reply = manager.get(request);
reply->setParent(this);
@@ -6146,29 +6268,28 @@ void tst_QNetworkReply::httpRecursiveCreation()
#ifndef QT_NO_SSL
void tst_QNetworkReply::ignoreSslErrorsList_data()
{
- QTest::addColumn<QString>("url");
QTest::addColumn<QList<QSslError> >("expectedSslErrors");
QTest::addColumn<QNetworkReply::NetworkError>("expectedNetworkError");
QList<QSslError> expectedSslErrors;
- QList<QSslCertificate> certs = QSslCertificate::fromPath(testDataDir + "/certs/qt-test-server-cacert.pem");
+ QList<QSslCertificate> certs = QSslCertificate::fromPath(testDataDir + certsFilePath);
QSslError rightError(FLUKE_CERTIFICATE_ERROR, certs.at(0));
QSslError wrongError(FLUKE_CERTIFICATE_ERROR);
- QTest::newRow("SSL-failure-empty-list") << "https://" + QtNetworkSettings::serverName() + "/index.html" << expectedSslErrors << QNetworkReply::SslHandshakeFailedError;
+ QTest::newRow("SSL-failure-empty-list") << expectedSslErrors << QNetworkReply::SslHandshakeFailedError;
expectedSslErrors.append(wrongError);
- QTest::newRow("SSL-failure-wrong-error") << "https://" + QtNetworkSettings::serverName() + "/index.html" << expectedSslErrors << QNetworkReply::SslHandshakeFailedError;
+ QTest::newRow("SSL-failure-wrong-error") << expectedSslErrors << QNetworkReply::SslHandshakeFailedError;
expectedSslErrors.append(rightError);
- QTest::newRow("allErrorsInExpectedList1") << "https://" + QtNetworkSettings::serverName() + "/index.html" << expectedSslErrors << QNetworkReply::NoError;
+ QTest::newRow("allErrorsInExpectedList1") << expectedSslErrors << QNetworkReply::NoError;
expectedSslErrors.removeAll(wrongError);
- QTest::newRow("allErrorsInExpectedList2") << "https://" + QtNetworkSettings::serverName() + "/index.html" << expectedSslErrors << QNetworkReply::NoError;
+ QTest::newRow("allErrorsInExpectedList2") << expectedSslErrors << QNetworkReply::NoError;
expectedSslErrors.removeAll(rightError);
- QTest::newRow("SSL-failure-empty-list-again") << "https://" + QtNetworkSettings::serverName() + "/index.html" << expectedSslErrors << QNetworkReply::SslHandshakeFailedError;
+ QTest::newRow("SSL-failure-empty-list-again") << expectedSslErrors << QNetworkReply::SslHandshakeFailedError;
}
void tst_QNetworkReply::ignoreSslErrorsList()
{
- QFETCH(QString, url);
+ QString url(QLatin1String("https://") + QtNetworkSettings::httpServerName() + QLatin1String("/index.html"));
QNetworkRequest request(url);
QNetworkReplyPtr reply(manager.get(request));
@@ -6195,7 +6316,7 @@ void tst_QNetworkReply::ignoreSslErrorListSlot(QNetworkReply *reply, const QList
// do the same as in ignoreSslErrorsList, but ignore the errors in the slot
void tst_QNetworkReply::ignoreSslErrorsListWithSlot()
{
- QFETCH(QString, url);
+ QString url(QLatin1String("https://") + QtNetworkSettings::httpServerName() + QLatin1String("/index.html"));
QNetworkRequest request(url);
QNetworkReplyPtr reply(manager.get(request));
@@ -6220,7 +6341,7 @@ void tst_QNetworkReply::sslConfiguration_data()
QTest::newRow("empty") << QSslConfiguration() << false;
QSslConfiguration conf = QSslConfiguration::defaultConfiguration();
QTest::newRow("default") << conf << false; // does not contain test server cert
- QList<QSslCertificate> testServerCert = QSslCertificate::fromPath(testDataDir + "/certs/qt-test-server-cacert.pem");
+ QList<QSslCertificate> testServerCert = QSslCertificate::fromPath(testDataDir + certsFilePath);
conf.setCaCertificates(testServerCert);
QTest::newRow("set-root-cert") << conf << true;
conf.setProtocol(QSsl::SecureProtocols);
@@ -6229,8 +6350,8 @@ void tst_QNetworkReply::sslConfiguration_data()
void tst_QNetworkReply::encrypted()
{
- qDebug() << QtNetworkSettings::serverName();
- QUrl url("https://" + QtNetworkSettings::serverName());
+ qDebug() << QtNetworkSettings::httpServerName();
+ QUrl url("https://" + QtNetworkSettings::httpServerName());
QNetworkRequest request(url);
QNetworkReply *reply = manager.get(request);
reply->ignoreSslErrors();
@@ -6278,7 +6399,7 @@ void tst_QNetworkReply::abortOnEncrypted()
void tst_QNetworkReply::sslConfiguration()
{
- QNetworkRequest request(QUrl("https://" + QtNetworkSettings::serverName() + "/index.html"));
+ QNetworkRequest request(QUrl("https://" + QtNetworkSettings::httpServerName() + "/index.html"));
QFETCH(QSslConfiguration, configuration);
request.setSslConfiguration(configuration);
QNetworkReplyPtr reply(manager.get(request));
@@ -6305,7 +6426,7 @@ void tst_QNetworkReply::sslSessionSharing()
QSKIP("Not implemented with SecureTransport");
#endif
- QString urlString("https://" + QtNetworkSettings::serverName());
+ QString urlString("https://" + QtNetworkSettings::httpServerName());
QList<QNetworkReplyPtr> replies;
// warm up SSL session cache
@@ -6373,7 +6494,7 @@ void tst_QNetworkReply::sslSessionSharingFromPersistentSession()
QSKIP("Not implemented with SecureTransport");
#endif
- QString urlString("https://" + QtNetworkSettings::serverName());
+ QString urlString("https://" + QtNetworkSettings::httpServerName());
// warm up SSL session cache to get a working session
QNetworkRequest warmupRequest(urlString);
@@ -6439,7 +6560,7 @@ void tst_QNetworkReply::getAndThenDeleteObject()
QSKIP("unstable test - reply may be finished too early");
// yes, this will leak if the testcase fails. I don't care. It must not fail then :P
QNetworkAccessManager *manager = new QNetworkAccessManager();
- QNetworkRequest request("http://" + QtNetworkSettings::serverName() + "/qtest/bigfile");
+ QNetworkRequest request("http://" + QtNetworkSettings::httpServerName() + "/qtest/bigfile");
QNetworkReply *reply = manager->get(request);
reply->setReadBufferSize(1);
reply->setParent((QObject*)0); // must be 0 because else it is the manager
@@ -6479,7 +6600,7 @@ void tst_QNetworkReply::getFromHttpIntoBuffer_data()
{
QTest::addColumn<QUrl>("url");
- QTest::newRow("rfc-internal") << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt");
+ QTest::newRow("rfc-internal") << QUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt");
}
// Please note that the whole "zero copy" download buffer API is private right now. Do not use it.
@@ -6892,9 +7013,15 @@ void tst_QNetworkReply::authenticationCacheAfterCancel_data()
QTest::addColumn<bool>("proxyAuth");
QTest::addColumn<QUrl>("url");
for (int i = 0; i < proxies.count(); ++i) {
- QTest::newRow("http" + proxies.at(i).tag) << proxies.at(i).proxy << proxies.at(i).requiresAuthentication << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfcs-auth/rfc3252.txt");
+ QTest::newRow("http" + proxies.at(i).tag)
+ << proxies.at(i).proxy
+ << proxies.at(i).requiresAuthentication
+ << QUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/rfcs-auth/rfc3252.txt");
#ifndef QT_NO_SSL
- QTest::newRow("https" + proxies.at(i).tag) << proxies.at(i).proxy << proxies.at(i).requiresAuthentication << QUrl("https://" + QtNetworkSettings::serverName() + "/qtest/rfcs-auth/rfc3252.txt");
+ QTest::newRow("https" + proxies.at(i).tag)
+ << proxies.at(i).proxy
+ << proxies.at(i).requiresAuthentication
+ << QUrl("https://" + QtNetworkSettings::httpServerName() + "/qtest/rfcs-auth/rfc3252.txt");
#endif
}
}
@@ -7083,7 +7210,7 @@ void tst_QNetworkReply::authenticationWithDifferentRealm()
helper.httpUserName = "httptest";
helper.httpPassword = "httptest";
- QNetworkRequest request(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfcs-auth/rfc3252.txt"));
+ QNetworkRequest request(QUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/rfcs-auth/rfc3252.txt"));
QNetworkReply* reply = manager.get(request);
connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection);
QTestEventLoop::instance().enterLoop(10);
@@ -7093,7 +7220,7 @@ void tst_QNetworkReply::authenticationWithDifferentRealm()
helper.httpUserName = "httptest";
helper.httpPassword = "httptest";
- request.setUrl(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/auth-digest/"));
+ request.setUrl(QUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/auth-digest/"));
reply = manager.get(request);
connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection);
QTestEventLoop::instance().enterLoop(10);
@@ -7135,7 +7262,7 @@ void tst_QNetworkReply::qtbug13431replyThrottling()
connect(&nam, SIGNAL(finished(QNetworkReply*)), &helper, SLOT(replyFinished(QNetworkReply*)));
// Download a bigger file
- QNetworkRequest netRequest(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/bigfile"));
+ QNetworkRequest netRequest(QUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/bigfile"));
helper.m_reply = nam.get(netRequest);
// Set the throttle
helper.m_reply->setReadBufferSize(36000);
@@ -7161,7 +7288,7 @@ void tst_QNetworkReply::httpWithNoCredentialUsage()
// Get with credentials, to preload authentication cache
{
- QNetworkRequest request(QUrl("http://httptest:httptest@" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi"));
+ QNetworkRequest request(QUrl("http://httptest:httptest@" + QtNetworkSettings::httpServerName() + "/qtest/protected/cgi-bin/md5sum.cgi"));
QNetworkReplyPtr reply(manager.get(request));
QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply));
// credentials in URL, so don't expect authentication signal
@@ -7172,7 +7299,7 @@ void tst_QNetworkReply::httpWithNoCredentialUsage()
// Get with cached credentials (normal usage)
{
- QNetworkRequest request(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi"));
+ QNetworkRequest request(QUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/protected/cgi-bin/md5sum.cgi"));
QNetworkReplyPtr reply(manager.get(request));
QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply));
// credentials in cache, so don't expect authentication signal
@@ -7183,7 +7310,7 @@ void tst_QNetworkReply::httpWithNoCredentialUsage()
// Do not use cached credentials (webkit cross origin usage)
{
- QNetworkRequest request(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi"));
+ QNetworkRequest request(QUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/protected/cgi-bin/md5sum.cgi"));
request.setAttribute(QNetworkRequest::AuthenticationReuseAttribute, QNetworkRequest::Manual);
QNetworkReplyPtr reply(manager.get(request));
@@ -7502,13 +7629,13 @@ void tst_QNetworkReply::synchronousRequest_data()
// ### cache, auth, proxies
QTest::newRow("http")
- << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt")
+ << QUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt")
<< QString("file:" + testDataDir + "/rfc3252.txt")
<< true
<< QString("text/plain");
QTest::newRow("http-gzip")
- << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/deflate/rfc3252.txt")
+ << QUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/deflate/rfc3252.txt")
<< QString("file:" + testDataDir + "/rfc3252.txt")
<< false // don't check content length, because it's gzip encoded
// ### we would need to enflate (un-deflate) the file content and compare the sizes
@@ -7516,7 +7643,7 @@ void tst_QNetworkReply::synchronousRequest_data()
#ifndef QT_NO_SSL
QTest::newRow("https")
- << QUrl("https://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt")
+ << QUrl("https://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt")
<< QString("file:" + testDataDir + "/rfc3252.txt")
<< true
<< QString("text/plain");
@@ -7552,7 +7679,7 @@ void tst_QNetworkReply::synchronousRequest()
// QNetworkRequest, see QTBUG-14774
if (url.scheme() == "https") {
QSslConfiguration sslConf;
- QList<QSslCertificate> certs = QSslCertificate::fromPath(testDataDir + "/certs/qt-test-server-cacert.pem");
+ QList<QSslCertificate> certs = QSslCertificate::fromPath(testDataDir + certsFilePath);
sslConf.setCaCertificates(certs);
request.setSslConfiguration(sslConf);
}
@@ -7597,7 +7724,7 @@ void tst_QNetworkReply::synchronousRequestSslFailure()
// and that we do not emit the sslError signal (in the manager that is,
// in the reply we don't care)
- QUrl url("https://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt");
+ QUrl url("https://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt");
QNetworkRequest request(url);
request.setAttribute(
QNetworkRequest::SynchronousRequestAttribute,
@@ -7643,7 +7770,7 @@ void tst_QNetworkReply::httpAbort()
// It must not crash either.
// Abort after the first readyRead()
- QNetworkRequest request("http://" + QtNetworkSettings::serverName() + "/qtest/bigfile");
+ QNetworkRequest request("http://" + QtNetworkSettings::httpServerName() + "/qtest/bigfile");
QNetworkReplyPtr reply(manager.get(request));
HttpAbortHelper replyHolder(reply.data());
QTestEventLoop::instance().enterLoop(10);
@@ -7659,7 +7786,7 @@ void tst_QNetworkReply::httpAbort()
QVERIFY(reply2->isFinished());
// Abort after the finished()
- QNetworkRequest request3("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt");
+ QNetworkRequest request3("http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt");
QNetworkReplyPtr reply3(manager.get(request3));
QCOMPARE(waitForFinish(reply3), int(Success));
@@ -7795,7 +7922,7 @@ void tst_QNetworkReply::synchronousAuthenticationCache()
void tst_QNetworkReply::pipelining()
{
- QString urlString("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/echo.cgi?");
+ QString urlString("http://" + QtNetworkSettings::httpServerName() + "/qtest/cgi-bin/echo.cgi?");
QList<QNetworkReplyPtr> replies;
for (int a = 0; a < 20; a++) {
QNetworkRequest request(urlString + QString::number(a));
@@ -7839,8 +7966,8 @@ void tst_QNetworkReply::emitErrorForAllRepliesSlot() {
void tst_QNetworkReply::closeDuringDownload_data()
{
QTest::addColumn<QUrl>("url");
- QTest::newRow("http") << QUrl("http://" + QtNetworkSettings::serverName() + "/bigfile");
- QTest::newRow("ftp") << QUrl("ftp://" + QtNetworkSettings::serverName() + "/qtest/bigfile");
+ QTest::newRow("http") << QUrl("http://" + QtNetworkSettings::httpServerName() + "/bigfile");
+ QTest::newRow("ftp") << QUrl("ftp://" + QtNetworkSettings::ftpServerName() + "/qtest/bigfile");
}
void tst_QNetworkReply::closeDuringDownload()
@@ -7864,8 +7991,8 @@ void tst_QNetworkReply::ftpAuthentication_data()
QTest::addColumn<QString>("url");
QTest::addColumn<int>("error");
- QTest::newRow("invalidPassword") << (testDataDir + "/rfc3252.txt") << "ftp://ftptest:invalid@" + QtNetworkSettings::serverName() + "/home/qt-test-server/ftp/qtest/rfc3252.txt" << int(QNetworkReply::AuthenticationRequiredError);
- QTest::newRow("validPassword") << (testDataDir + "/rfc3252.txt") << "ftp://ftptest:password@" + QtNetworkSettings::serverName() + "/home/qt-test-server/ftp/qtest/rfc3252.txt" << int(QNetworkReply::NoError);
+ QTest::newRow("invalidPassword") << (testDataDir + "/rfc3252.txt") << "ftp://ftptest:invalid@" + QtNetworkSettings::ftpServerName() + "/home/qt-test-server/ftp/qtest/rfc3252.txt" << int(QNetworkReply::AuthenticationRequiredError);
+ QTest::newRow("validPassword") << (testDataDir + "/rfc3252.txt") << "ftp://ftptest:password@" + QtNetworkSettings::ftpServerName() + "/home/qt-test-server/ftp/qtest/rfc3252.txt" << int(QNetworkReply::NoError);
}
void tst_QNetworkReply::ftpAuthentication()
@@ -7925,9 +8052,9 @@ void tst_QNetworkReply::backgroundRequest_data()
QTest::addColumn<int>("policy");
QTest::addColumn<QNetworkReply::NetworkError>("error");
- QUrl httpurl("http://" + QtNetworkSettings::serverName());
- QUrl httpsurl("https://" + QtNetworkSettings::serverName());
- QUrl ftpurl("ftp://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt");
+ QUrl httpurl("http://" + QtNetworkSettings::httpServerName());
+ QUrl httpsurl("https://" + QtNetworkSettings::httpServerName());
+ QUrl ftpurl("ftp://" + QtNetworkSettings::ftpServerName() + "/qtest/rfc3252.txt");
QTest::newRow("http, fg, normal") << httpurl << false << (int)QNetworkSession::NoPolicy << QNetworkReply::NoError;
QTest::newRow("http, bg, normal") << httpurl << true << (int)QNetworkSession::NoPolicy << QNetworkReply::NoError;
@@ -7996,9 +8123,9 @@ void tst_QNetworkReply::backgroundRequestInterruption_data()
QTest::addColumn<bool>("background");
QTest::addColumn<QNetworkReply::NetworkError>("error");
- QUrl httpurl("http://" + QtNetworkSettings::serverName() + "/qtest/mediumfile");
- QUrl httpsurl("https://" + QtNetworkSettings::serverName() + "/qtest/mediumfile");
- QUrl ftpurl("ftp://" + QtNetworkSettings::serverName() + "/qtest/bigfile");
+ QUrl httpurl("http://" + QtNetworkSettings::httpServerName() + "/qtest/mediumfile");
+ QUrl httpsurl("https://" + QtNetworkSettings::httpServerName() + "/qtest/mediumfile");
+ QUrl ftpurl("ftp://" + QtNetworkSettings::ftpServerName() + "/qtest/bigfile");
QTest::newRow("http, fg, nobg") << httpurl << false << QNetworkReply::NoError;
QTest::newRow("http, bg, nobg") << httpurl << true << QNetworkReply::BackgroundRequestNotAllowedError;
@@ -8069,8 +8196,8 @@ void tst_QNetworkReply::backgroundRequestConnectInBackground_data()
QTest::addColumn<QUrl>("url");
QTest::addColumn<bool>("background");
- QUrl httpurl("http://" + QtNetworkSettings::serverName());
- QUrl ftpurl("ftp://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt");
+ QUrl httpurl("http://" + QtNetworkSettings::httpServerName());
+ QUrl ftpurl("ftp://" + QtNetworkSettings::ftpServerName() + "/qtest/rfc3252.txt");
QTest::newRow("http, fg") << httpurl << false;
QTest::newRow("http, bg") << httpurl << true;
@@ -8196,7 +8323,7 @@ void tst_QNetworkReply::putWithRateLimiting()
QByteArray data = reference.readAll();
QVERIFY(data.length() > 0);
- QUrl url = QUrl::fromUserInput("http://" + QtNetworkSettings::serverName()+ "/qtest/cgi-bin/echo.cgi?");
+ QUrl url = QUrl::fromUserInput("http://" + QtNetworkSettings::httpServerName()+ "/qtest/cgi-bin/echo.cgi?");
QNetworkRequest request(url);
QNetworkReplyPtr reply;
@@ -8641,7 +8768,7 @@ void tst_QNetworkReply::ioHttpRedirect()
void tst_QNetworkReply::ioHttpRedirectFromLocalToRemote()
{
- QUrl targetUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt");
+ QUrl targetUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt");
QString redirectReply = tempRedirectReplyStr().arg(targetUrl.toString());
MiniHttpServer redirectServer(redirectReply.toLatin1(), false);
@@ -8710,7 +8837,7 @@ void tst_QNetworkReply::ioHttpRedirectPostPut()
QFETCH(QByteArray, data);
QFETCH(QString, contentType);
- QUrl targetUrl("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi");
+ QUrl targetUrl("http://" + QtNetworkSettings::httpServerName() + "/qtest/cgi-bin/md5sum.cgi");
QString redirectReply = QStringLiteral("HTTP/1.1 %1\r\n"
"Content-Type: text/plain\r\n"
@@ -8999,7 +9126,7 @@ void tst_QNetworkReply::putWithServerClosingConnectionImmediately()
// NOTE: This test must be last testcase in tst_qnetworkreply!
void tst_QNetworkReply::parentingRepliesToTheApp()
{
- QNetworkRequest request (QUrl("http://" + QtNetworkSettings::serverName()));
+ QNetworkRequest request(QUrl("http://" + QtNetworkSettings::httpServerName()));
manager.get(request)->setParent(this); // parent to this object
manager.get(request)->setParent(qApp); // parent to the app
}
diff --git a/tests/auto/network/access/qnetworkrequest/tst_qnetworkrequest.cpp b/tests/auto/network/access/qnetworkrequest/tst_qnetworkrequest.cpp
index 50c7ddb0b6..7a3def410a 100644
--- a/tests/auto/network/access/qnetworkrequest/tst_qnetworkrequest.cpp
+++ b/tests/auto/network/access/qnetworkrequest/tst_qnetworkrequest.cpp
@@ -236,6 +236,46 @@ void tst_QNetworkRequest::setHeader_data()
<< true << "Last-Modified"
<< "Thu, 01 Nov 2007 18:08:30 GMT";
+ QTest::newRow("If-Modified-Since-Date") << QNetworkRequest::IfModifiedSinceHeader
+ << QVariant(QDate(2017, 7, 01))
+ << true << "If-Modified-Since"
+ << "Sat, 01 Jul 2017 00:00:00 GMT";
+ QTest::newRow("If-Modified-Since-DateTime") << QNetworkRequest::IfModifiedSinceHeader
+ << QVariant(QDateTime(QDate(2017, 7, 01),
+ QTime(3, 14, 15),
+ Qt::UTC))
+ << true << "If-Modified-Since"
+ << "Sat, 01 Jul 2017 03:14:15 GMT";
+
+ QTest::newRow("Etag-strong") << QNetworkRequest::ETagHeader << QVariant(R"("xyzzy")")
+ << true << "ETag" << R"("xyzzy")";
+ QTest::newRow("Etag-weak") << QNetworkRequest::ETagHeader << QVariant(R"(W/"xyzzy")")
+ << true << "ETag" << R"(W/"xyzzy")";
+ QTest::newRow("Etag-empty") << QNetworkRequest::ETagHeader << QVariant(R"("")")
+ << true << "ETag" << R"("")";
+
+ QTest::newRow("If-Match-empty") << QNetworkRequest::IfMatchHeader << QVariant(R"("")")
+ << true << "If-Match" << R"("")";
+ QTest::newRow("If-Match-any") << QNetworkRequest::IfMatchHeader << QVariant(R"("*")")
+ << true << "If-Match" << R"("*")";
+ QTest::newRow("If-Match-single") << QNetworkRequest::IfMatchHeader << QVariant(R"("xyzzy")")
+ << true << "If-Match" << R"("xyzzy")";
+ QTest::newRow("If-Match-multiple") << QNetworkRequest::IfMatchHeader
+ << QVariant(R"("xyzzy", "r2d2xxxx", "c3piozzzz")")
+ << true << "If-Match"
+ << R"("xyzzy", "r2d2xxxx", "c3piozzzz")";
+
+ QTest::newRow("If-None-Match-empty") << QNetworkRequest::IfNoneMatchHeader << QVariant(R"("")")
+ << true << "If-None-Match" << R"("")";
+ QTest::newRow("If-None-Match-any") << QNetworkRequest::IfNoneMatchHeader << QVariant(R"("*")")
+ << true << "If-None-Match" << R"("*")";
+ QTest::newRow("If-None-Match-single") << QNetworkRequest::IfNoneMatchHeader << QVariant(R"("xyzzy")")
+ << true << "If-None-Match" << R"("xyzzy")";
+ QTest::newRow("If-None-Match-multiple") << QNetworkRequest::IfNoneMatchHeader
+ << QVariant(R"("xyzzy", W/"r2d2xxxx", "c3piozzzz")")
+ << true << "If-None-Match"
+ << R"("xyzzy", W/"r2d2xxxx", "c3piozzzz")";
+
QNetworkCookie cookie;
cookie.setName("a");
cookie.setValue("b");
@@ -327,6 +367,62 @@ void tst_QNetworkRequest::rawHeaderParsing_data()
<< true << "Last-Modified"
<< "Sun Nov 6 08:49:37 1994";
+ QTest::newRow("If-Modified-Since-RFC1123") << QNetworkRequest::IfModifiedSinceHeader
+ << QVariant(QDateTime(QDate(1994, 8, 06),
+ QTime(8, 49, 37),
+ Qt::UTC))
+ << true << "If-Modified-Since"
+ << "Sun, 06 Aug 1994 08:49:37 GMT";
+ QTest::newRow("If-Modified-Since-RFC850") << QNetworkRequest::IfModifiedSinceHeader
+ << QVariant(QDateTime(QDate(1994, 8, 06),
+ QTime(8, 49, 37),
+ Qt::UTC))
+ << true << "If-Modified-Since"
+ << "Sunday, 06-Aug-94 08:49:37 GMT";
+ QTest::newRow("If-Modified-Since-asctime") << QNetworkRequest::IfModifiedSinceHeader
+ << QVariant(QDateTime(QDate(1994, 8, 06),
+ QTime(8, 49, 37),
+ Qt::UTC))
+ << true << "If-Modified-Since"
+ << "Sun Aug 6 08:49:37 1994";
+
+ QTest::newRow("Etag-strong") << QNetworkRequest::ETagHeader << QVariant(R"("xyzzy")")
+ << true << "ETag" << R"("xyzzy")";
+ QTest::newRow("Etag-weak") << QNetworkRequest::ETagHeader << QVariant(R"(W/"xyzzy")")
+ << true << "ETag" << R"(W/"xyzzy")";
+ QTest::newRow("Etag-empty") << QNetworkRequest::ETagHeader << QVariant(R"("")")
+ << true << "ETag" << R"("")";
+
+ QTest::newRow("If-Match-empty") << QNetworkRequest::IfMatchHeader << QVariant(QStringList(R"("")"))
+ << true << "If-Match" << R"("")";
+ QTest::newRow("If-Match-any") << QNetworkRequest::IfMatchHeader << QVariant(QStringList(R"("*")"))
+ << true << "If-Match" << R"("*")";
+ QTest::newRow("If-Match-single") << QNetworkRequest::IfMatchHeader
+ << QVariant(QStringList(R"("xyzzy")"))
+ << true << "If-Match" << R"("xyzzy")";
+ QTest::newRow("If-Match-multiple") << QNetworkRequest::IfMatchHeader
+ << QVariant(QStringList({R"("xyzzy")",
+ R"("r2d2xxxx")",
+ R"("c3piozzzz")"}))
+ << true << "If-Match"
+ << R"("xyzzy", "r2d2xxxx", "c3piozzzz")";
+
+ QTest::newRow("If-None-Match-empty") << QNetworkRequest::IfNoneMatchHeader
+ << QVariant(QStringList(R"("")"))
+ << true << "If-None-Match" << R"("")";
+ QTest::newRow("If-None-Match-any") << QNetworkRequest::IfNoneMatchHeader
+ << QVariant(QStringList(R"("*")"))
+ << true << "If-None-Match" << R"("*")";
+ QTest::newRow("If-None-Match-single") << QNetworkRequest::IfNoneMatchHeader
+ << QVariant(QStringList(R"("xyzzy")"))
+ << true << "If-None-Match" << R"("xyzzy")";
+ QTest::newRow("If-None-Match-multiple") << QNetworkRequest::IfNoneMatchHeader
+ << QVariant(QStringList({R"("xyzzy")",
+ R"(W/"r2d2xxxx")",
+ R"("c3piozzzz")"}))
+ << true << "If-None-Match"
+ << R"("xyzzy", W/"r2d2xxxx", "c3piozzzz")";
+
QTest::newRow("Content-Length-invalid1") << QNetworkRequest::ContentLengthHeader << QVariant()
<< false << "Content-Length" << "1a";
QTest::newRow("Content-Length-invalid2") << QNetworkRequest::ContentLengthHeader << QVariant()
diff --git a/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp b/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp
index bc53faf106..01168cc0d6 100644
--- a/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp
+++ b/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp
@@ -29,10 +29,6 @@
#include <QtTest/QTest>
-#ifdef Q_OS_WIN
-#include <winsock2.h>
-#endif
-
#include <qcoreapplication.h>
#include <qdatastream.h>
#include <qhostaddress.h>
diff --git a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp
index 779d55a77a..45ab275510 100644
--- a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp
+++ b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp
@@ -962,9 +962,6 @@ void tst_QLocalSocket::processConnection()
#if !QT_CONFIG(process)
QSKIP("No qprocess support", SkipAll);
#else
-#ifdef Q_OS_MAC
- QSKIP("The processConnection test is unstable on Mac. See QTBUG-39986.");
-#endif
#ifdef Q_OS_WIN
const QString exeSuffix = QStringLiteral(".exe");
diff --git a/tests/auto/network/ssl/qdtls/certs/bogus-ca.crt b/tests/auto/network/ssl/qdtls/certs/bogus-ca.crt
new file mode 100644
index 0000000000..cf5893e98d
--- /dev/null
+++ b/tests/auto/network/ssl/qdtls/certs/bogus-ca.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDMzCCAhugAwIBAgIJAJBdFtmKuuELMA0GCSqGSIb3DQEBCwUAMC8xGjAYBgNV
+BAoMEUJvZ3VzIENvcnBvcmF0aW9uMREwDwYDVQQDDAhCb2d1cyBDQTAgFw0xNTAx
+MzAxNzM0NDdaGA8yMTE1MDEwNjE3MzQ0N1owLzEaMBgGA1UECgwRQm9ndXMgQ29y
+cG9yYXRpb24xETAPBgNVBAMMCEJvZ3VzIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAnXt/X69lmfvWampP88f20yNs1VZroG9VjdR4GaJM6pbWu5Wn
+SYBfS81osnHC7dTW2FvKZUGnz7KX+ImkbE2qUvj6yTeFu6ILj3o+8ws7A4iOTkiH
+84CHb6T/HxWO5fW6mS5v+tvPDp3rQ7JpPVYvoh7dSv8X1+JCdDmkepRveN6Pzo47
+9VFVC0oscc5I4Y0wPwnaXZ4X26vmRfbhqtoKL57lz1lJ0R6bvLC9mf4DGFPx7WXQ
+eOtlKX2dtuKj+Cl3vyHff6gHNMKM0bq3KfsT+vDO6eIs/ayqVRdd0XBIMj+bZYd9
+7QI/+3XTNR3TwTisrjo71XZtHdA1DkcMaSGoJwIDAQABo1AwTjAdBgNVHQ4EFgQU
+xVZK4BIjBgmluCLIespCbne4BIUwHwYDVR0jBBgwFoAUxVZK4BIjBgmluCLIespC
+bne4BIUwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAgZn6odHr2y1G
+1OStblBdsXNxmsW7WzhLUYFUhSzBw9KS/O7uG2HAFLwJNM4sQHeuc0JjxqXG5n7s
+mGbmWpUYt8+KJDRnUssmKwwg2u6Rqp+0I9leCk9KTtYpXX7d9wprSsgwjQKhTEeQ
+fNImbNR6Br7GDO7Om2MnOALvZmp0KJgUFIH0J630LJTrsrTvwfX7wKhYb1wgud5N
+SXdGjBuJxKK3Y0VBMsbqwI0y+wHIYE+qLzlFWNRHmKaYeGtg0T8CVK6XWUrLcjcr
+rQINqW3rb1OlWF7YZ5dg7vXoZrza6YSQLWha6/FQMCaKtJHxIE1NBw0ZXK6txnkI
+f4HXoPvSGg==
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qdtls/certs/bogus-ca.key b/tests/auto/network/ssl/qdtls/certs/bogus-ca.key
new file mode 100644
index 0000000000..1c2db7932e
--- /dev/null
+++ b/tests/auto/network/ssl/qdtls/certs/bogus-ca.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAnXt/X69lmfvWampP88f20yNs1VZroG9VjdR4GaJM6pbWu5Wn
+SYBfS81osnHC7dTW2FvKZUGnz7KX+ImkbE2qUvj6yTeFu6ILj3o+8ws7A4iOTkiH
+84CHb6T/HxWO5fW6mS5v+tvPDp3rQ7JpPVYvoh7dSv8X1+JCdDmkepRveN6Pzo47
+9VFVC0oscc5I4Y0wPwnaXZ4X26vmRfbhqtoKL57lz1lJ0R6bvLC9mf4DGFPx7WXQ
+eOtlKX2dtuKj+Cl3vyHff6gHNMKM0bq3KfsT+vDO6eIs/ayqVRdd0XBIMj+bZYd9
+7QI/+3XTNR3TwTisrjo71XZtHdA1DkcMaSGoJwIDAQABAoIBAGKkKmJq4L8UyXca
+ZD4UcHxL4i221e9GDVarURbtXDRMivAwivo1GHvIi93J+Ak0meYniJzoBQ7JlPsu
+a/kSpK8YGS3UQ0YF+CvErI1b6XkLHefW8qEJTswVk1+LB1jvFBRCzA1bhVRogiaD
+J/wtceSgZIhHRE4LAQj/2hCVzUTtV6Zr0GIJGjB7hdF9MHGlTwkPrkjvERlK/PTc
+dVjyNbinYGJNA2i701u/atplH2eSBUresMhHu3AZUUXZKfFQ2m07FDBNAtsoYNnO
+d17EXDaoQRDVWSP83GN4b/hpmngvHl1fuFBZ1ms375FNPQo/K33QBaUsLsqiIS/v
+k3LBkeECgYEAyqv5dkgte9c2mxT5zUQySr1fDms4nwZTth8477jRnOZND1M9VoIv
+1EjBfxq3y7gJVd34VWYeCxNBYwK8C45SDXtlU9X2hLeKWU6yfdegyxv950P5AahT
+J80YtYSez+mTLPOC42GeTg7l01NXlTHmPpraIkdNniHc8bqyAEK9w+kCgYEAxuuO
+Ln84GkAm1gr6gyFkOMVwVEfszKjRGIqp4BnSwM9bFgWvhyj4jpr+bpe4gQKQQE5q
+E/GoxYOtdZ3yYupd2Ki0irGhhm3u0ywgmbomurOw46AInONWcHTU6kZY/dd8wfvW
+8YcmFq/LNupwFOEw18mKaQXygMnUYci+uOSw0Y8CgYEAkcX0XjE4FdUL/6usqQme
+KsfesR5J0YfZeism5rXGftXfI2C5w5lMEaJrGqL7A9pRTKOlVLdocIrfAvoaiy1I
+s03H6e8Bqx/gsK+8DmujybNOgqMPXTPW68/HL/g9ykm0hCZ6RFYYaQiqIb/WRQdp
+FiqHLxSeLVkp8+xWz30xxNECgYAA7P23Z64qKRxFKL3ruE8QGJMiQUdv2GVIuPR7
+b4NUlGJ3IsWjWmR1vXDrsNcR+qITOoox15ESgj9facHEBhUzue1FK/h1eLOA1ha8
+wGoHumhbVtZTbJdtZI3NHVCytbsF6Bci/p8FwgGvGr40yquAhZaYUIfFY6sSXW3N
+zHqqLwKBgQCUGrePDhjjUZZNQya0TQZ95HL8OQB2e9bx8RwypYdC3pAZ6uDfl+Ne
+IZoA8EoDHVbsxDXmLTGil/kyvmYBnzvkVz/yMyFm/7I0zXEOr8bTgqE5wJ8BMGSp
+yil5jDoN28KL6D+HsDsWUEOvvHieDYP3cxfpZWiQuWIZ6gfDDVjIwQ==
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qdtls/certs/bogus-client.crt b/tests/auto/network/ssl/qdtls/certs/bogus-client.crt
new file mode 100644
index 0000000000..c9d43ce662
--- /dev/null
+++ b/tests/auto/network/ssl/qdtls/certs/bogus-client.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIC/zCCAeegAwIBAgIBADANBgkqhkiG9w0BAQsFADAvMRowGAYDVQQKDBFCb2d1
+cyBDb3Jwb3JhdGlvbjERMA8GA1UEAwwIQm9ndXMgQ0EwIBcNMTUwMTMwMTczNTI0
+WhgPMjExNTAxMDYxNzM1MjRaMDMxGjAYBgNVBAoMEUJvZ3VzIENvcnBvcmF0aW9u
+MRUwEwYDVQQDDAxCb2d1cyBDbGllbnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDa28y3b2qcrFTjr3GIgjx78qlbRZomBt/A//ZW5qx00+QXT30bu8F0
+jCfHaBTDSnabP86856C/kL1d6oRtc7jmaxNoj39uRh3NcV3VmFEiLI9XmJ0gOIBN
+vMQ0voi4gvRBzjFMnVOFML8FePV4OUX1QUZK4eAvZCsDhaJv1cCEERsfcttv7X31
+CT3+a3geZsb0cMDqicq/uaX2IONhqoNYwGlmgF+bWICIxJmEnaK3e/LnKKpvvfTt
+n2M0Fx0W4150HSZxQ9Iz6fQQ8oLNn3qNL5i9377XKpck2uxC39yt5WXK2d5m8xBF
+5+qwMMqlEW4LoE/dTU9mJ1lZLwV7m7QJAgMBAAGjIDAeMAkGA1UdEwQCMAAwEQYJ
+YIZIAYb4QgEBBAQDAgeAMA0GCSqGSIb3DQEBCwUAA4IBAQBBeGwXbU/WRLkfxDoI
+Js2nPqzpfEXAcrJhurHKlm/wMIHnHHhTM69O7yTl/VUdKIXPzC1bGkAiSBQo+51B
+SJkyWo3vt47g8rqAnUs4oM+bPD2t1YkJVeGLu+Nfw5SHlc+HdojdAcpKtnCbqtrd
+vnV4QyB70nxKXC3jmWVBu/jeim0RzUacO+lF9vRPqwnlDINopx8ZpEjaXxABtaQA
+cVUosFGEPRjOYAbw9j4fK7J7EXh/124j81OfawkfaMMDt2EedmSdlhPy+Io7VaBo
+ho+39cX/oO3Ek+C9v+4aGF7rgp3VyKOGtC5rIy+YiwjcI09pRVPuqEqXC6C4nQcS
+SjjF
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qdtls/certs/bogus-client.key b/tests/auto/network/ssl/qdtls/certs/bogus-client.key
new file mode 100644
index 0000000000..f676af73d4
--- /dev/null
+++ b/tests/auto/network/ssl/qdtls/certs/bogus-client.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEA2tvMt29qnKxU469xiII8e/KpW0WaJgbfwP/2VuasdNPkF099
+G7vBdIwnx2gUw0p2mz/OvOegv5C9XeqEbXO45msTaI9/bkYdzXFd1ZhRIiyPV5id
+IDiATbzENL6IuIL0Qc4xTJ1ThTC/BXj1eDlF9UFGSuHgL2QrA4Wib9XAhBEbH3Lb
+b+199Qk9/mt4HmbG9HDA6onKv7ml9iDjYaqDWMBpZoBfm1iAiMSZhJ2it3vy5yiq
+b7307Z9jNBcdFuNedB0mcUPSM+n0EPKCzZ96jS+Yvd++1yqXJNrsQt/creVlytne
+ZvMQRefqsDDKpRFuC6BP3U1PZidZWS8Fe5u0CQIDAQABAoIBAQDOzZlA0CgWiYTh
+bLvEOQQ8Pw0msLs7KY2vCm7UqL3W2w4RtMvMM/tWTMWd2EyeSLOQeZe5ysmLmpJF
+tz+RSSMzn4REbiwEoH6yzWfUWEx6FU8Rf6UheCJM0o04Jb59U0jJEbRl59eu6GPo
+IOcaxkvDtv1b7tnvDiDTACiAsqNqZhs54QlqwpadSYe4QgK9KH0WxqBzLpXr8eEq
+ZV1uuuNpaf+mitVaJhXHyVt7Od1yPfohbTYaXjko3xt3BcStt4tzRZkGQk2kjMWd
+d53wqcFlc+zxSW9/ogLr+TCDttTEa1oV+JLpXLkV5J0/saf/LYw96r6f98XhLrd1
+5otsbQ+dAoGBAP0nCzd6otnuUsLX+dz0ed61zDzyTVBXLxuOOvDpuPItVUKPI8yZ
+mwveIm97/4u50HGSWUgLR5v+ABfMVG/DqkEP50dDbIhQ2uBhkR5xVgSlZSiZ7S03
+1AErADaeViphKjfAuHraGgC6SRv8HBZadbYW+ZQRVTF6IRJmstiLNJIDAoGBAN1S
+AYtYhH0tJSQxyL+sdeuPGhY5RDdlSeLRAStpoGjmaOC4Rc8uDsts2xuInkCcTW2y
+nogoR5YxFvcly3vGL5kOzLuscLbueqkz/rbTlZPruqL7fMyPI7Y3YgGER5XNwPpE
++DlW1fu2aE42WUU49mkUNaT2WBtOLnbZKShAWKoDAoGAOGZfeF/JMnaHV8OYdmK9
+WCH2u8lb8j9KToBUn2HjA4mYCjkrx6SdR3qY/2+H0pB2YScy3vssXBOt3591XGUi
+ZFZvt4/M+V3SNdVm6HplqKlUrUQF9GIQyKXU6VZDajO1nTBBqZU339ug+Cwl8dD7
+krLxrcxix6AnCBt7UwVIlBMCgYEAydQADogxgknKJiC0Vn86pg9BFeUxXWckIxDA
+hUt0+lSsbcn993qkCUUC5zAGSRuAzLnoMnixF7k6nTW9Q+mu/GBvufH+dAQ0ndsJ
+vMZlEJkXAYxf+dfLFF+bI5DzCxywkEqXJwsWZs6ofjK35BWXOKoyZXY1UOlSHBXb
+n5ZWhOsCgYBRLqEjUehkZfqjZj8VClyPQ/6bAgtfjMRqpgsLgvqG9gBraDs4DXJr
+K8Ac3+vCP8rqVwIUC0iu/5MFX75WJ7Go7wbAg7m91P9tmzSiLEm5H1toXJpla6nv
+oLZW+jN9O1BaVow8f2qIEJMjHnDbuZnMPQlMGUD+g2tNgczfxT3MOA==
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qdtls/certs/bogus-server.crt b/tests/auto/network/ssl/qdtls/certs/bogus-server.crt
new file mode 100644
index 0000000000..7e59f6128d
--- /dev/null
+++ b/tests/auto/network/ssl/qdtls/certs/bogus-server.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIC/zCCAeegAwIBAgIBATANBgkqhkiG9w0BAQsFADAvMRowGAYDVQQKDBFCb2d1
+cyBDb3Jwb3JhdGlvbjERMA8GA1UEAwwIQm9ndXMgQ0EwIBcNMTUwMTMxMTc0MjI3
+WhgPMjExNTAxMDcxNzQyMjdaMDMxGjAYBgNVBAoMEUJvZ3VzIENvcnBvcmF0aW9u
+MRUwEwYDVQQDDAxCb2d1cyBTZXJ2ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCv899JQxy/mpaQzscopmoKOkgbmwGwty1KiTpT09MU1+gtMHCfhmVp
+nAiNIlQlDa+5mjhvyy1fSf+mgdjnvT5pdUAro633gfCv318EViwYsvA7/0ZumFqU
+UyPWw4/2of/ZfJv2ewzMLoYEDKiLcXxInBsMlt5Lr7IBS8SNitDU+TAM7HLEIkMz
+c0JpxY09H707tO8G3e93yfB5l8H+JdeEdPe+7PDfnsZZuMmaImiNYRByPTTuGvrN
+I9I+OxcE4ZOMMNb3mzAoEFnyfHiCO2ehHl58y0a49ayAKJdP/FV3n2LtL/Zc5Ilq
+b3VJgaShevrfIiItURjOAjDA9B95hYuZAgMBAAGjIDAeMAkGA1UdEwQCMAAwEQYJ
+YIZIAYb4QgEBBAQDAgZAMA0GCSqGSIb3DQEBCwUAA4IBAQBhTqwD3HxamZGopq0K
+r8KUdtliiPwo4GBFp0zg6VdSxo01WfpwFGOaeKNmV0JadtJ1DhcsdIUv2OvrxiWQ
+1n0IGHULeazQnst1q1t/Vlup3IggKTGCLi8yd3acY8tr2wj9lGjWhsR+BcrCUTEB
+BCpIsQiFA8+PTf/8SHuzMokDBP+j02fWCqwR749H4NDQgqrFsgzxLDA69XgvkNM3
++HOsOR/QxeYIp54mqPnsNVhzV0JbpQpF4j9R5kMI/bsPmWH6W0GbSSyA07o8iVw7
+eqPbwHnIlHXzafvaGmF0QituAzU0nPgMc9OMxuoqacBSmSvmSdMmh///vr7O2KHO
+7s+g
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qdtls/certs/bogus-server.key b/tests/auto/network/ssl/qdtls/certs/bogus-server.key
new file mode 100644
index 0000000000..bda8dae678
--- /dev/null
+++ b/tests/auto/network/ssl/qdtls/certs/bogus-server.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAr/PfSUMcv5qWkM7HKKZqCjpIG5sBsLctSok6U9PTFNfoLTBw
+n4ZlaZwIjSJUJQ2vuZo4b8stX0n/poHY570+aXVAK6Ot94Hwr99fBFYsGLLwO/9G
+bphalFMj1sOP9qH/2Xyb9nsMzC6GBAyoi3F8SJwbDJbeS6+yAUvEjYrQ1PkwDOxy
+xCJDM3NCacWNPR+9O7TvBt3vd8nweZfB/iXXhHT3vuzw357GWbjJmiJojWEQcj00
+7hr6zSPSPjsXBOGTjDDW95swKBBZ8nx4gjtnoR5efMtGuPWsgCiXT/xVd59i7S/2
+XOSJam91SYGkoXr63yIiLVEYzgIwwPQfeYWLmQIDAQABAoIBAHVRJJLjpZp3h2a8
+CHypIND69TM60hCywgcNoo9cEES4hL0ErEMhSCL3f5giyHoAOyeElZasoO8FFuk9
+cJNrUd7c59FxDECYKhQJ2n+4uSQqwxUt6xc4jESTfrTmpemrMD0h4ZehifHmH0M5
+8XMwUs7TDxIA0e0jE4vbqg05/m3RMHoeJ4W5K4dMxkJbjmyjjCr8aT8WP/KSTABS
+YQPql0rs6WL5Q2s1I/i3I4qIS4CKk8Ym7O5/Wk1fxbCh2ABL2PhW8PZDzvsFYo2T
+cwX0cc0EILBc3tOG11Iua6mK8y9Zz1BpUT02ZvGaPf9R6vI0Shk1yWbZ0NYLx0MH
+Zu8HIYECgYEA5awzjNcnDYQY9f6C/0TNj54Z8I7UFmGJX7XhPVVMceNieUiLvrsH
+Zmf4Q51PLM1iz0S2qGA/c7lngHDXwFe++MANIK7KNwL2LtPF/83mYgBUxBKJaNHD
+4B/6CCitjSwAfMNBnE70zg0F9chqy+9p+fTEwUFW6Y4y9U5jO4kw5HECgYEAxB8+
+YYMUGeIt9TnMKrC2YK/o8jo+5ZEOpEIPwleeAIUMujVVonu3TX2nKos2MgaZg/F0
+OpvDlcQZqb4Em73ctf3ZgBYEs9tt2qdB5qGlg4Hs2wyfgKUPQGLX2RseUQCYsOWT
+cPPKvYDTZ6yhW6gGBd5ufl5tnG93CsIpcNV1DakCgYEAwByZhi6V4Q1k36eDpcjE
+dWRW6ExghVQS17dIb8hAyGbeAPs4wVKqbvN6y/vytVQbWapta0wO51rng51gKuh6
+upHSqUrrpLZafHLyBPYSxljmjpe+zqnfwUKeH2L/QL3UroeZAwlcZlqoaJ27D1j0
++XrPdaOU8onagCyQfsVT21ECgYAafW3blezdIiO6/7eH/J5lqNz5+swMDe/AV/vw
+8AyzXUU+0X1jmPpFSTePE4aaczHBFJfyYp+kVvxwZO4Say6olkUOe+resEDCS90m
+3aaRgLcRTz8sDR9mPvOQq40Iu9/j5N5pX0R/HCtx0WtqCePmXwjloLOFcbjOhzM5
+vls1IQKBgEF8DEk8T4ycjwBXC3U7Duj9jPL815417BAHdGstLP1yNcI05ubN2T56
+ITbf625YS7OdtYfrf1/jBnUVXsJspsQqkOUB97M224CVWI+vJiv8jPX+KCnR7/Zh
+A/7OrtZ6FCzLyBeu/2p1NHAttqSUqu9t6wCeeBcelnAUcrjfLmlw
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qdtls/certs/fake-login.live.com.key b/tests/auto/network/ssl/qdtls/certs/fake-login.live.com.key
new file mode 100644
index 0000000000..692a7bd85d
--- /dev/null
+++ b/tests/auto/network/ssl/qdtls/certs/fake-login.live.com.key
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQDOtxdvMa0VHUQYG5q7Tsi1Jj4qKEJppyZEkmuRXOi0fDbd1SwE
+bwHrLGMvDO6OMrYBbq3WDNrtnIfF9CvzUOEch+gjr4hEVQqecU5fb45Wor7yNel3
+/C/gxfbzuXHrsj/gUjNghL2i10+c2NW+hUo/sWO6OusaBT6d6s7ee+YBcQIDAQAB
+AoGAb8cVhu0HuLkgjyCuJMbPRRUu3ED02Iin6sB6JhplQuNAD+grayJTmUVhRJnr
+jTziqhedLHe7Em1oBaSo92MutfMpXvWiccSlbNygI61VgmrJpVB+qIN5H9cQc9ql
+Zymc+nIPa1+i5rsrOzlpUytTh7AsbZ27QG4tQXR/kQejEiECQQD6BgTxBeT8D7x9
+DuukoBaSCkLwx7U7P1NXx15EI3lA1nO51t6UHfvk/jGPp8Sl4wv4alJ7AQxr5uQ/
+vC3kzA/1AkEA06gNu10se8pe3n8qL2RRt+FmVjHkQdD9Mm2Dx9oWCs2A4wOSOrlo
+6/nKYF1CaQNYn9HgsNbHVEUpnICVO18qDQJBALEw/uOJ1+TDikPfBSWgxx4s45Ad
+GNWqZXh6NNZ5hX9r/IwiOZAjR9fcRmeW8IjYRi2BvH6sGY+HDRAWXzgdXtkCQCma
+dOiJTf8fLjqp4E7kdzOfuI/kyqstOze4Uxjrgz2oW1dEEnA8laUcumzqp+0gXUE8
+7d+UuCWWWrGKjMrYz9kCQQDh5E5+b6Djn082Jo6gvyuXWC5eXju6IdmihlJ2SMzD
+s2y3IDjOUtTeQQRDymLneteMz0ha79KeUp6VnAvZCOVe
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qdtls/certs/fake-login.live.com.pem b/tests/auto/network/ssl/qdtls/certs/fake-login.live.com.pem
new file mode 100644
index 0000000000..429f95187c
--- /dev/null
+++ b/tests/auto/network/ssl/qdtls/certs/fake-login.live.com.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDDjCCAnegAwIBAgIRALC3Ez7Qlvm1b66RyHS9OsAwDQYJKoZIhvcNAQEFBQAw
+XjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGElu
+dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEXMBUGA1UEAxMObG9naW4ubGl2ZS5jb20w
+HhcNMTEwMzI1MTMyODUwWhcNMTEwNDI0MTMyODUwWjBeMQswCQYDVQQGEwJBVTET
+MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
+dHkgTHRkMRcwFQYDVQQDEw5sb2dpbi5saXZlLmNvbTCBnzANBgkqhkiG9w0BAQEF
+AAOBjQAwgYkCgYEAzrcXbzGtFR1EGBuau07ItSY+KihCaacmRJJrkVzotHw23dUs
+BG8B6yxjLwzujjK2AW6t1gza7ZyHxfQr81DhHIfoI6+IRFUKnnFOX2+OVqK+8jXp
+d/wv4MX287lx67I/4FIzYIS9otdPnNjVvoVKP7FjujrrGgU+nerO3nvmAXECAwEA
+AaOByzCByDAdBgNVHQ4EFgQUpSOEcmtkQITvBdM2IDfcXnJ0FCAwgZgGA1UdIwSB
+kDCBjYAUpSOEcmtkQITvBdM2IDfcXnJ0FCChYqRgMF4xCzAJBgNVBAYTAkFVMRMw
+EQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0
+eSBMdGQxFzAVBgNVBAMTDmxvZ2luLmxpdmUuY29tghEAsLcTPtCW+bVvrpHIdL06
+wDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAD+2HT4GSHHKCdbl9VkX
+zsl+D+drMm2b0ksxz9SgPihP7aW50EEIJDEEihNMTa27mhpeOXHc/sLqDi4ECUao
+/0Ns/5uoVuAIrAKCydmtPsonVFh9XWjyrfUzPOHAc9p2bmJ1i9a3kTsLB6jlrVDO
+VufGzsowHlHZ0TtKf5omojU5
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qdtls/certs/fluke.cert b/tests/auto/network/ssl/qdtls/certs/fluke.cert
new file mode 100644
index 0000000000..ace4e4f0eb
--- /dev/null
+++ b/tests/auto/network/ssl/qdtls/certs/fluke.cert
@@ -0,0 +1,75 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=NO, ST=Oslo, L=Nydalen, O=Nokia Corporation and/or its subsidiary(-ies), OU=Development, CN=fluke.troll.no/emailAddress=ahanssen@trolltech.com
+ Validity
+ Not Before: Dec 4 01:10:32 2007 GMT
+ Not After : Apr 21 01:10:32 2035 GMT
+ Subject: C=NO, ST=Oslo, O=Nokia Corporation and/or its subsidiary(-ies), OU=Development, CN=fluke.troll.no
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:a7:c8:a0:4a:c4:19:05:1b:66:ba:32:e2:d2:f1:
+ 1c:6f:17:82:e4:39:2e:01:51:90:db:04:34:32:11:
+ 21:c2:0d:6f:59:d8:53:90:54:3f:83:8f:a9:d3:b3:
+ d5:ee:1a:9b:80:ae:c3:25:c9:5e:a5:af:4b:60:05:
+ aa:a0:d1:91:01:1f:ca:04:83:e3:58:1c:99:32:45:
+ 84:70:72:58:03:98:4a:63:8b:41:f5:08:49:d2:91:
+ 02:60:6b:e4:64:fe:dd:a0:aa:74:08:e9:34:4c:91:
+ 5f:12:3d:37:4d:54:2c:ad:7f:5b:98:60:36:02:8c:
+ 3b:f6:45:f3:27:6a:9b:94:9d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 21:85:04:3D:23:01:66:E5:F7:9F:1A:84:24:8A:AF:0A:79:F4:E5:AC
+ X509v3 Authority Key Identifier:
+ DirName:/C=NO/ST=Oslo/L=Nydalen/O=Nokia Corporation and/or its subsidiary(-ies)/OU=Development/CN=fluke.troll.no/emailAddress=ahanssen@trolltech.com
+ serial:8E:A8:B4:E8:91:B7:54:2E
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 6d:57:5f:d1:05:43:f0:62:05:ec:2a:71:a5:dc:19:08:f2:c4:
+ a6:bd:bb:25:d9:ca:89:01:0e:e4:cf:1f:c1:8c:c8:24:18:35:
+ 53:59:7b:c0:43:b4:32:e6:98:b2:a6:ef:15:05:0b:48:5f:e1:
+ a0:0c:97:a9:a1:77:d8:35:18:30:bc:a9:8f:d3:b7:54:c7:f1:
+ a9:9e:5d:e6:19:bf:f6:3c:5b:2b:d8:e4:3e:62:18:88:8b:d3:
+ 24:e1:40:9b:0c:e6:29:16:62:ab:ea:05:24:70:36:aa:55:93:
+ ef:02:81:1b:23:10:a2:04:eb:56:95:75:fc:f8:94:b1:5d:42:
+ c5:3f:36:44:85:5d:3a:2e:90:46:8a:a2:b9:6f:87:ae:0c:15:
+ 40:19:31:90:fc:3b:25:bb:ae:f1:66:13:0d:85:90:d9:49:34:
+ 8f:f2:5d:f9:7a:db:4d:5d:27:f6:76:9d:35:8c:06:a6:4c:a3:
+ b1:b2:b6:6f:1d:d7:a3:00:fd:72:eb:9e:ea:44:a1:af:21:34:
+ 7d:c7:42:e2:49:91:19:8b:c0:ad:ba:82:80:a8:71:70:f4:35:
+ 31:91:63:84:20:95:e9:60:af:64:8b:cc:ff:3d:8a:76:74:3d:
+ c8:55:6d:e4:8e:c3:2b:1c:e8:42:18:ae:9f:e6:6b:9c:34:06:
+ ec:6a:f2:c3
+-----BEGIN CERTIFICATE-----
+MIIEEzCCAvugAwIBAgIBADANBgkqhkiG9w0BAQUFADCBnDELMAkGA1UEBhMCTk8x
+DTALBgNVBAgTBE9zbG8xEDAOBgNVBAcTB055ZGFsZW4xFjAUBgNVBAoTDVRyb2xs
+dGVjaCBBU0ExFDASBgNVBAsTC0RldmVsb3BtZW50MRcwFQYDVQQDEw5mbHVrZS50
+cm9sbC5ubzElMCMGCSqGSIb3DQEJARYWYWhhbnNzZW5AdHJvbGx0ZWNoLmNvbTAe
+Fw0wNzEyMDQwMTEwMzJaFw0zNTA0MjEwMTEwMzJaMGMxCzAJBgNVBAYTAk5PMQ0w
+CwYDVQQIEwRPc2xvMRYwFAYDVQQKEw1Ucm9sbHRlY2ggQVNBMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEXMBUGA1UEAxMOZmx1a2UudHJvbGwubm8wgZ8wDQYJKoZIhvcN
+AQEBBQADgY0AMIGJAoGBAKfIoErEGQUbZroy4tLxHG8XguQ5LgFRkNsENDIRIcIN
+b1nYU5BUP4OPqdOz1e4am4CuwyXJXqWvS2AFqqDRkQEfygSD41gcmTJFhHByWAOY
+SmOLQfUISdKRAmBr5GT+3aCqdAjpNEyRXxI9N01ULK1/W5hgNgKMO/ZF8ydqm5Sd
+AgMBAAGjggEaMIIBFjAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NM
+IEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUIYUEPSMBZuX3nxqEJIqv
+Cnn05awwgbsGA1UdIwSBszCBsKGBoqSBnzCBnDELMAkGA1UEBhMCTk8xDTALBgNV
+BAgTBE9zbG8xEDAOBgNVBAcTB055ZGFsZW4xFjAUBgNVBAoTDVRyb2xsdGVjaCBB
+U0ExFDASBgNVBAsTC0RldmVsb3BtZW50MRcwFQYDVQQDEw5mbHVrZS50cm9sbC5u
+bzElMCMGCSqGSIb3DQEJARYWYWhhbnNzZW5AdHJvbGx0ZWNoLmNvbYIJAI6otOiR
+t1QuMA0GCSqGSIb3DQEBBQUAA4IBAQBtV1/RBUPwYgXsKnGl3BkI8sSmvbsl2cqJ
+AQ7kzx/BjMgkGDVTWXvAQ7Qy5piypu8VBQtIX+GgDJepoXfYNRgwvKmP07dUx/Gp
+nl3mGb/2PFsr2OQ+YhiIi9Mk4UCbDOYpFmKr6gUkcDaqVZPvAoEbIxCiBOtWlXX8
++JSxXULFPzZEhV06LpBGiqK5b4euDBVAGTGQ/Dslu67xZhMNhZDZSTSP8l35ettN
+XSf2dp01jAamTKOxsrZvHdejAP1y657qRKGvITR9x0LiSZEZi8CtuoKAqHFw9DUx
+kWOEIJXpYK9ki8z/PYp2dD3IVW3kjsMrHOhCGK6f5mucNAbsavLD
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qdtls/certs/fluke.key b/tests/auto/network/ssl/qdtls/certs/fluke.key
new file mode 100644
index 0000000000..9d1664d609
--- /dev/null
+++ b/tests/auto/network/ssl/qdtls/certs/fluke.key
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQCnyKBKxBkFG2a6MuLS8RxvF4LkOS4BUZDbBDQyESHCDW9Z2FOQ
+VD+Dj6nTs9XuGpuArsMlyV6lr0tgBaqg0ZEBH8oEg+NYHJkyRYRwclgDmEpji0H1
+CEnSkQJga+Rk/t2gqnQI6TRMkV8SPTdNVCytf1uYYDYCjDv2RfMnapuUnQIDAQAB
+AoGANFzLkanTeSGNFM0uttBipFT9F4a00dqHz6JnO7zXAT26I5r8sU1pqQBb6uLz
+/+Qz5Zwk8RUAQcsMRgJetuPQUb0JZjF6Duv24hNazqXBCu7AZzUenjafwmKC/8ri
+KpX3fTwqzfzi//FKGgbXQ80yykSSliDL3kn/drATxsLCgQECQQDXhEFWLJ0vVZ1s
+1Ekf+3NITE+DR16X+LQ4W6vyEHAjTbaNWtcTKdAWLA2l6N4WAAPYSi6awm+zMxx4
+VomVTsjdAkEAx0z+e7natLeFcrrq8pbU+wa6SAP1VfhQWKitxL1e7u/QO90NCpxE
+oQYKzMkmmpOOFjQwEMAy1dvFMbm4LHlewQJAC/ksDBaUcQHHqjktCtrUb8rVjAyW
+A8lscckeB2fEYyG5J6dJVaY4ClNOOs5yMDS2Afk1F6H/xKvtQ/5CzInA/QJATDub
+K+BPU8jO9q+gpuIi3VIZdupssVGmCgObVCHLakG4uO04y9IyPhV9lA9tALtoIf4c
+VIvv5fWGXBrZ48kZAQJBAJmVCdzQxd9LZI5vxijUCj5EI4e+x5DRqVUvyP8KCZrC
+AiNyoDP85T+hBZaSXK3aYGpVwelyj3bvo1GrTNwNWLw=
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qdtls/certs/ss-srv-cert.pem b/tests/auto/network/ssl/qdtls/certs/ss-srv-cert.pem
new file mode 100644
index 0000000000..2c3d2e180d
--- /dev/null
+++ b/tests/auto/network/ssl/qdtls/certs/ss-srv-cert.pem
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC5TCCAk6gAwIBAgIJAP0E+KApnERsMA0GCSqGSIb3DQEBCwUAMIGJMQswCQYD
+VQQGEwJOTzENMAsGA1UECAwET3NsbzENMAsGA1UEBwwET3NsbzELMAkGA1UECgwC
+UXQxHzAdBgNVBAsMFlImRCAoQ29yZSBhbmQgTmV0d29yaykxEDAOBgNVBAMMB2Jv
+Yi5vcmcxHDAaBgkqhkiG9w0BCQEWDWJvYkBnbWFpbC5jb20wHhcNMTgwNDI2MDgw
+NDAxWhcNMjgwNDIzMDgwNDAxWjCBiTELMAkGA1UEBhMCTk8xDTALBgNVBAgMBE9z
+bG8xDTALBgNVBAcMBE9zbG8xCzAJBgNVBAoMAlF0MR8wHQYDVQQLDBZSJkQgKENv
+cmUgYW5kIE5ldHdvcmspMRAwDgYDVQQDDAdib2Iub3JnMRwwGgYJKoZIhvcNAQkB
+Fg1ib2JAZ21haWwuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDWSh+1
+Xp5l3MgpzfTtiiuT4jMh8uQug/N7fyZlo+obMarT51dYWt1L5yFYyPw92FCtWgTi
+rWFUh6Z8O/wIRkLRd/meKAqQsqRMnEVt4WSE9fA41XecWw1FJl2Ehwnl2C3Nj3GF
+XonG+4Wg5EzH7JGEUUQIGQnuUTj06BkHLq0R8QIDAQABo1MwUTAdBgNVHQ4EFgQU
+TRydf45RdKVcjhzNUYgfNq4f/W8wHwYDVR0jBBgwFoAUTRydf45RdKVcjhzNUYgf
+Nq4f/W8wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQAsn1aZTcZU
+4qD+ciziSYFM0Qk1GTCHtWf5nufB35AyuUqOK3h6QgRHovvNm+IMJIPMlnnwj5gF
+G8UZ6mCYBUQPBuofZz8+XEL+N0QtvzUXA2/jVKn2TkcSvFXV90juC9KfhGhM93kQ
+1R3qNPgxkuQqteffCbUyWnugv3/axNCjsQ==
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qdtls/certs/ss-srv-key.pem b/tests/auto/network/ssl/qdtls/certs/ss-srv-key.pem
new file mode 100644
index 0000000000..c2d912bf4d
--- /dev/null
+++ b/tests/auto/network/ssl/qdtls/certs/ss-srv-key.pem
@@ -0,0 +1,18 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIC1DBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIBoCUfXYbG50CAggA
+MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECHsb5ejBIDukBIICgFiMs6LbW0L4
+fxGDVNQWEbWf+1h4HJZsetWVqX5kh+9R3yfvK6vMVI5EQZ3mm8t5NDIKRFON6dN/
+uKGvZA+4vR6Vc5yeOOzL6sC8NsIU6eJOzkxXdyBahBHORm51dJCRtCdsoaWnx00I
+jEAIvdv/dWh+kx9iMF6cZeOvIXbdVPuadjeh62cjPU/zyZSKCFd59zqWRMvIMIIM
+kUOy2In5dVBb8/W9Zz0S8OG7KRJ+KdxxR5ev324L70XtRbb/tDVnGuMz+K83xbQC
+ySJgIEvaz9lmhFeWiJ9HPGqcYtMAUUk4XgF5mcQDete8uCndDnxCy3uCyNxWtIm3
+dXRYzWZh+nbsbjYQWT3Lo3z3zkchB8vNDBfVcp6m0nx7spaUFlptrXujYKU9VQTK
+2vAMhT9uUstLaHm+TEI1SuDBeugbvxy1DNI5lEQ3SG50L8r0m/OuQkV9zPVreHLX
+nJdx7POS69WW+yac2SJX9mMSXICksLvaSGxSnFf1hMyozIp3xM4jGsxV+ckGw2I/
+CNUW2QHMuJ2/AvZo8cJY5iwbRgCaewAKkUiPZbGMDLeRapm9nrRFyTkLGyjI+4wG
+wByzJ8ZZ2IlnZexXbcs0o8qoFmUxgA2R5Q3AvDYAg9/XGWtRcbIOhly4gRv4B/OF
+pWfqYrCK6ZbTNSNZNifMDJfjx5T9qSnnLbAZRjuVwOgvqWTcBZpzpn97YS7XnsrU
+5qMOiaP+VgpWeO2Fcf5zq9CJaBLO8sBUWWJW7mPgrOpxbBOio6x1GbRMT2niOiPN
+wSXWPfw5Kp/P43ORJEttudEGJYpIMAzZ88hmF2j8n3hGC9FHAw5RGaV+3vsonsZq
+iwE2rYxs3RI=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qdtls/qdtls.pro b/tests/auto/network/ssl/qdtls/qdtls.pro
new file mode 100644
index 0000000000..19e13a965c
--- /dev/null
+++ b/tests/auto/network/ssl/qdtls/qdtls.pro
@@ -0,0 +1,16 @@
+CONFIG += testcase
+
+SOURCES += tst_qdtls.cpp
+QT = core network-private testlib
+
+TARGET = tst_qdtls
+
+win32 {
+ CONFIG(debug, debug|release) {
+ DESTDIR = debug
+ } else {
+ DESTDIR = release
+ }
+}
+
+TESTDATA += certs
diff --git a/tests/auto/network/ssl/qdtls/tst_qdtls.cpp b/tests/auto/network/ssl/qdtls/tst_qdtls.cpp
new file mode 100644
index 0000000000..6a94eee389
--- /dev/null
+++ b/tests/auto/network/ssl/qdtls/tst_qdtls.cpp
@@ -0,0 +1,1324 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include <QtNetwork/qsslpresharedkeyauthenticator.h>
+#include <QtNetwork/qsslconfiguration.h>
+#include <QtNetwork/qhostaddress.h>
+#include <QtNetwork/qsslsocket.h>
+#include <QtNetwork/qsslcipher.h>
+#include <QtNetwork/qudpsocket.h>
+#include <QtNetwork/qsslerror.h>
+#include <QtNetwork/qsslkey.h>
+#include <QtNetwork/qdtls.h>
+#include <QtNetwork/qssl.h>
+
+#include <QtCore/qcryptographichash.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qobject.h>
+
+#include <algorithm>
+
+QT_BEGIN_NAMESPACE
+
+namespace
+{
+
+bool dtlsErrorIsCleared(const QDtls &dtls)
+{
+ return dtls.dtlsError() == QDtlsError::NoError && dtls.dtlsErrorString().isEmpty();
+}
+
+using DtlsPtr = QScopedPointer<QDtls>;
+
+bool dtlsErrorIsCleared(DtlsPtr &dtls)
+{
+ return dtlsErrorIsCleared(*dtls);
+}
+
+} // unnamed namespace
+
+#define QDTLS_VERIFY_NO_ERROR(obj) QVERIFY(dtlsErrorIsCleared(obj))
+
+#define QDTLS_VERIFY_HANDSHAKE_SUCCESS(obj) \
+ QVERIFY(obj->isConnectionEncrypted()); \
+ QCOMPARE(obj->handshakeState(), QDtls::HandshakeComplete); \
+ QDTLS_VERIFY_NO_ERROR(obj); \
+ QCOMPARE(obj->peerVerificationErrors().size(), 0)
+
+class tst_QDtls : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void init();
+
+private slots:
+ // Tests:
+ void construction_data();
+ void construction();
+ void configuration_data();
+ void configuration();
+ void invalidConfiguration();
+ void setPeer_data();
+ void setPeer();
+ void handshake_data();
+ void handshake();
+ void handshakeWithRetransmission();
+ void sessionCipher();
+ void cipherPreferences_data();
+ void cipherPreferences();
+ void protocolVersionMatching_data();
+ void protocolVersionMatching();
+ void verificationErrors_data();
+ void verificationErrors();
+ void presetExpectedErrors_data();
+ void presetExpectedErrors();
+ void verifyServerCertificate_data();
+ void verifyServerCertificate();
+ void verifyClientCertificate_data();
+ void verifyClientCertificate();
+ void blacklistedCerificate();
+ void readWriteEncrypted_data();
+ void readWriteEncrypted();
+ void datagramFragmentation();
+
+protected slots:
+ void handshakeReadyRead();
+ void encryptedReadyRead();
+ void pskRequested(QSslPreSharedKeyAuthenticator *auth);
+ void handleHandshakeTimeout();
+
+private:
+ void clientServerData();
+ void connectHandshakeReadingSlots();
+ void connectEncryptedReadingSlots();
+ bool verificationErrorDetected(QSslError::SslError code) const;
+
+ static QHostAddress toNonAny(const QHostAddress &addr);
+
+ QUdpSocket serverSocket;
+ QHostAddress serverAddress;
+ quint16 serverPort = 0;
+ QSslConfiguration defaultServerConfig;
+ QSslCertificate selfSignedCert;
+ QString hostName;
+ QSslKey serverKeySS;
+ bool serverDropDgram = false;
+ const QByteArray serverExpectedPlainText = "Hello W ... hmm, I mean DTLS server!";
+ QByteArray serverReceivedPlainText;
+
+ QUdpSocket clientSocket;
+ QHostAddress clientAddress;
+ quint16 clientPort = 0;
+ bool clientDropDgram = false;
+ const QByteArray clientExpectedPlainText = "Hello DTLS client.";
+ QByteArray clientReceivedPlainText;
+
+ DtlsPtr serverCrypto;
+ DtlsPtr clientCrypto;
+
+ QTestEventLoop testLoop;
+ const int handshakeTimeoutMS = 5000;
+ const int dataExchangeTimeoutMS = 1000;
+
+ const QByteArray presharedKey = "DEADBEEFDEADBEEF";
+ QString certDirPath;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QSsl::SslProtocol)
+Q_DECLARE_METATYPE(QSslSocket::SslMode)
+Q_DECLARE_METATYPE(QSslSocket::PeerVerifyMode)
+Q_DECLARE_METATYPE(QList<QSslCertificate>)
+Q_DECLARE_METATYPE(QSslKey)
+Q_DECLARE_METATYPE(QVector<QSslError>)
+
+QT_BEGIN_NAMESPACE
+
+void tst_QDtls::initTestCase()
+{
+ certDirPath = QFileInfo(QFINDTESTDATA("certs")).absolutePath();
+ QVERIFY(certDirPath.size() > 0);
+ certDirPath += QDir::separator() + QStringLiteral("certs") + QDir::separator();
+
+ QVERIFY(QSslSocket::supportsSsl());
+
+ QFile keyFile(certDirPath + QStringLiteral("ss-srv-key.pem"));
+ QVERIFY(keyFile.open(QIODevice::ReadOnly));
+ serverKeySS = QSslKey(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, "foobar");
+ QVERIFY(!serverKeySS.isNull());
+
+ QList<QSslCertificate> certificates = QSslCertificate::fromPath(certDirPath + QStringLiteral("ss-srv-cert.pem"));
+ QVERIFY(!certificates.isEmpty());
+ QVERIFY(!certificates.first().isNull());
+ selfSignedCert = certificates.first();
+
+ defaultServerConfig = QSslConfiguration::defaultDtlsConfiguration();
+ defaultServerConfig.setPeerVerifyMode(QSslSocket::VerifyNone);
+ defaultServerConfig.setDtlsCookieVerificationEnabled(false);
+
+ hostName = QStringLiteral("bob.org");
+}
+
+void tst_QDtls::init()
+{
+ if (serverSocket.state() != QAbstractSocket::UnconnectedState) {
+ serverSocket.close();
+ // disconnect signals/slots:
+ serverSocket.disconnect();
+ }
+
+ QVERIFY(serverSocket.bind());
+ serverAddress = toNonAny(serverSocket.localAddress());
+ serverPort = serverSocket.localPort();
+
+ if (clientSocket.localPort()) {
+ clientSocket.close();
+ // disconnect signals/slots:
+ clientSocket.disconnect();
+ }
+
+ clientAddress = {};
+ clientPort = 0;
+
+ serverCrypto.reset(new QDtls(QSslSocket::SslServerMode));
+ serverDropDgram = false;
+ serverReceivedPlainText.clear();
+
+ clientCrypto.reset(new QDtls(QSslSocket::SslClientMode));
+ clientDropDgram = false;
+ clientReceivedPlainText.clear();
+
+ connect(clientCrypto.data(), &QDtls::handshakeTimeout,
+ this, &tst_QDtls::handleHandshakeTimeout);
+ connect(serverCrypto.data(), &QDtls::handshakeTimeout,
+ this, &tst_QDtls::handleHandshakeTimeout);
+}
+
+void tst_QDtls::construction_data()
+{
+ clientServerData();
+}
+
+void tst_QDtls::construction()
+{
+ QFETCH(const QSslSocket::SslMode, mode);
+
+ QDtls dtls(mode);
+ QCOMPARE(dtls.peerAddress(), QHostAddress());
+ QCOMPARE(dtls.peerPort(), quint16());
+ QCOMPARE(dtls.peerVerificationName(), QString());
+ QCOMPARE(dtls.sslMode(), mode);
+
+ QCOMPARE(dtls.mtuHint(), quint16());
+
+ const auto params = dtls.cookieGeneratorParameters();
+ QVERIFY(params.secret.size() > 0);
+#ifdef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
+ QCOMPARE(params.hash, QCryptographicHash::Sha1);
+#else
+ QCOMPARE(params.hash, QCryptographicHash::Sha256);
+#endif
+
+ QCOMPARE(dtls.dtlsConfiguration(), QSslConfiguration::defaultDtlsConfiguration());
+
+ QCOMPARE(dtls.handshakeState(), QDtls::HandshakeNotStarted);
+ QCOMPARE(dtls.isConnectionEncrypted(), false);
+ QCOMPARE(dtls.sessionCipher(), QSslCipher());
+ QCOMPARE(dtls.sessionProtocol(), QSsl::UnknownProtocol);
+
+ QCOMPARE(dtls.dtlsError(), QDtlsError::NoError);
+ QCOMPARE(dtls.dtlsErrorString(), QString());
+ QCOMPARE(dtls.peerVerificationErrors().size(), 0);
+}
+
+void tst_QDtls::configuration_data()
+{
+ clientServerData();
+}
+
+void tst_QDtls::configuration()
+{
+ // There is a proper auto-test for QSslConfiguration in our TLS test suite,
+ // here we only test several DTLS-related details.
+ auto config = QSslConfiguration::defaultDtlsConfiguration();
+ QCOMPARE(config.protocol(), QSsl::DtlsV1_2OrLater);
+
+ const QList<QSslCipher> ciphers = config.ciphers();
+ QVERIFY(ciphers.size() > 0);
+ for (const auto &cipher : ciphers)
+ QVERIFY(cipher.usedBits() >= 128);
+
+ QCOMPARE(config.dtlsCookieVerificationEnabled(), true);
+
+ QFETCH(const QSslSocket::SslMode, mode);
+ QDtls dtls(mode);
+ QCOMPARE(dtls.dtlsConfiguration(), config);
+ config.setProtocol(QSsl::DtlsV1_0OrLater);
+ config.setDtlsCookieVerificationEnabled(false);
+ QCOMPARE(config.dtlsCookieVerificationEnabled(), false);
+
+ QVERIFY(dtls.setDtlsConfiguration(config));
+ QDTLS_VERIFY_NO_ERROR(dtls);
+ QCOMPARE(dtls.dtlsConfiguration(), config);
+
+ if (mode == QSslSocket::SslClientMode) {
+ // Testing a DTLS server would be more complicated, we'd need a DTLS
+ // client sending ClientHello(s), running an event loop etc. - way too
+ // much dancing for a simple setter/getter test.
+ QVERIFY(dtls.setPeer(serverAddress, serverPort));
+ QDTLS_VERIFY_NO_ERROR(dtls);
+
+ QUdpSocket clientSocket;
+ QVERIFY(dtls.doHandshake(&clientSocket));
+ QDTLS_VERIFY_NO_ERROR(dtls);
+ QCOMPARE(dtls.handshakeState(), QDtls::HandshakeInProgress);
+ // As soon as handshake started, it's not allowed to change configuration:
+ QVERIFY(!dtls.setDtlsConfiguration(QSslConfiguration::defaultDtlsConfiguration()));
+ QCOMPARE(dtls.dtlsError(), QDtlsError::InvalidOperation);
+ QCOMPARE(dtls.dtlsConfiguration(), config);
+ }
+}
+
+void tst_QDtls::invalidConfiguration()
+{
+ QUdpSocket socket;
+ QDtls crypto(QSslSocket::SslClientMode);
+ QVERIFY(crypto.setPeer(serverAddress, serverPort));
+ // Note: not defaultDtlsConfiguration(), so the protocol is TLS (without D):
+ QVERIFY(crypto.setDtlsConfiguration(QSslConfiguration::defaultConfiguration()));
+ QDTLS_VERIFY_NO_ERROR(crypto);
+ QCOMPARE(crypto.dtlsConfiguration(), QSslConfiguration::defaultConfiguration());
+ // Try to start the handshake:
+ QCOMPARE(crypto.doHandshake(&socket), false);
+ QCOMPARE(crypto.dtlsError(), QDtlsError::TlsInitializationError);
+}
+
+void tst_QDtls::setPeer_data()
+{
+ clientServerData();
+}
+
+void tst_QDtls::setPeer()
+{
+ static const QHostAddress invalid[] = {QHostAddress(),
+ QHostAddress(QHostAddress::Broadcast),
+ QHostAddress(QStringLiteral("224.0.0.0"))};
+ static const QString peerName = QStringLiteral("does not matter actually");
+
+ QFETCH(const QSslSocket::SslMode, mode);
+ QDtls dtls(mode);
+
+ for (const auto &addr : invalid) {
+ QCOMPARE(dtls.setPeer(addr, 100, peerName), false);
+ QCOMPARE(dtls.dtlsError(), QDtlsError::InvalidInputParameters);
+ QCOMPARE(dtls.peerAddress(), QHostAddress());
+ QCOMPARE(dtls.peerPort(), quint16());
+ QCOMPARE(dtls.peerVerificationName(), QString());
+ }
+
+ QVERIFY(dtls.setPeer(serverAddress, serverPort, peerName));
+ QDTLS_VERIFY_NO_ERROR(dtls);
+ QCOMPARE(dtls.peerAddress(), serverAddress);
+ QCOMPARE(dtls.peerPort(), serverPort);
+ QCOMPARE(dtls.peerVerificationName(), peerName);
+
+ if (mode == QSslSocket::SslClientMode) {
+ // We test for client mode only, for server mode we'd have to run event
+ // loop etc. too much work for a simple setter/getter test.
+ QUdpSocket clientSocket;
+ QVERIFY(dtls.doHandshake(&clientSocket));
+ QDTLS_VERIFY_NO_ERROR(dtls);
+ QCOMPARE(dtls.handshakeState(), QDtls::HandshakeInProgress);
+ QCOMPARE(dtls.setPeer(serverAddress, serverPort), false);
+ QCOMPARE(dtls.dtlsError(), QDtlsError::InvalidOperation);
+ }
+}
+
+void tst_QDtls::handshake_data()
+{
+ QTest::addColumn<bool>("withCertificate");
+
+ QTest::addRow("no-cert") << false;
+ QTest::addRow("with-cert") << true;
+}
+
+void tst_QDtls::handshake()
+{
+ connectHandshakeReadingSlots();
+
+ QFETCH(const bool, withCertificate);
+
+ auto serverConfig = defaultServerConfig;
+ auto clientConfig = QSslConfiguration::defaultDtlsConfiguration();
+
+ if (!withCertificate) {
+ connect(serverCrypto.data(), &QDtls::pskRequired, this, &tst_QDtls::pskRequested);
+ connect(clientCrypto.data(), &QDtls::pskRequired, this, &tst_QDtls::pskRequested);
+ clientConfig.setPeerVerifyMode(QSslSocket::VerifyNone);
+ QVERIFY(clientConfig.peerCertificate().isNull());
+ } else {
+ serverConfig.setPrivateKey(serverKeySS);
+ serverConfig.setLocalCertificate(selfSignedCert);
+ clientConfig.setCaCertificates({selfSignedCert});
+ }
+
+ QVERIFY(serverCrypto->setDtlsConfiguration(serverConfig));
+ QVERIFY(clientCrypto->setDtlsConfiguration(clientConfig));
+
+ // Some early checks before we run event loop.
+ // Remote was not set yet:
+ QVERIFY(!clientCrypto->doHandshake(&clientSocket));
+ QCOMPARE(clientCrypto->dtlsError(), QDtlsError::InvalidOperation);
+ QVERIFY(!serverCrypto->doHandshake(&serverSocket, QByteArray("ClientHello")));
+ QCOMPARE(serverCrypto->dtlsError(), QDtlsError::InvalidOperation);
+
+ QVERIFY(clientCrypto->setPeer(serverAddress, serverPort, hostName));
+
+ // Invalid socket:
+ QVERIFY(!clientCrypto->doHandshake(nullptr));
+ QCOMPARE(clientCrypto->dtlsError(), QDtlsError::InvalidInputParameters);
+
+ // Now we are ready for handshake:
+ QVERIFY(clientCrypto->doHandshake(&clientSocket));
+ QDTLS_VERIFY_NO_ERROR(clientCrypto);
+ QCOMPARE(clientCrypto->handshakeState(), QDtls::HandshakeInProgress);
+
+ testLoop.enterLoopMSecs(handshakeTimeoutMS);
+
+ QVERIFY(!testLoop.timeout());
+
+ QVERIFY(serverCrypto->isConnectionEncrypted());
+ QDTLS_VERIFY_NO_ERROR(serverCrypto);
+ QCOMPARE(serverCrypto->handshakeState(), QDtls::HandshakeComplete);
+ QCOMPARE(serverCrypto->peerVerificationErrors().size(), 0);
+
+ QVERIFY(clientCrypto->isConnectionEncrypted());
+ QDTLS_VERIFY_NO_ERROR(clientCrypto);
+ QCOMPARE(clientCrypto->handshakeState(), QDtls::HandshakeComplete);
+ QCOMPARE(clientCrypto->peerVerificationErrors().size(), 0);
+
+ if (withCertificate) {
+ const auto serverCert = clientCrypto->dtlsConfiguration().peerCertificate();
+ QVERIFY(!serverCert.isNull());
+ QCOMPARE(serverCert, selfSignedCert);
+ }
+
+ // Already in 'HandshakeComplete' state/encrypted.
+ QVERIFY(!clientCrypto->doHandshake(&clientSocket));
+ QCOMPARE(clientCrypto->dtlsError(), QDtlsError::InvalidOperation);
+ QVERIFY(!serverCrypto->doHandshake(&serverSocket, {"ServerHello"}));
+ QCOMPARE(serverCrypto->dtlsError(), QDtlsError::InvalidOperation);
+ // Cannot change a remote without calling shutdown first.
+ QVERIFY(!clientCrypto->setPeer(serverAddress, serverPort));
+ QCOMPARE(clientCrypto->dtlsError(), QDtlsError::InvalidOperation);
+ QVERIFY(!serverCrypto->setPeer(clientAddress, clientPort));
+ QCOMPARE(serverCrypto->dtlsError(), QDtlsError::InvalidOperation);
+}
+
+void tst_QDtls::handshakeWithRetransmission()
+{
+ connectHandshakeReadingSlots();
+
+ auto serverConfig = defaultServerConfig;
+ serverConfig.setPrivateKey(serverKeySS);
+ serverConfig.setLocalCertificate(selfSignedCert);
+ QVERIFY(serverCrypto->setDtlsConfiguration(serverConfig));
+
+ auto clientConfig = QSslConfiguration::defaultDtlsConfiguration();
+ clientConfig.setCaCertificates({selfSignedCert});
+ QVERIFY(clientCrypto->setDtlsConfiguration(clientConfig));
+ QVERIFY(clientCrypto->setPeer(serverAddress, serverPort, hostName));
+
+ // Now we are ready for handshake:
+ QVERIFY(clientCrypto->doHandshake(&clientSocket));
+ QDTLS_VERIFY_NO_ERROR(clientCrypto);
+ QCOMPARE(clientCrypto->handshakeState(), QDtls::HandshakeInProgress);
+
+ serverDropDgram = true;
+ clientDropDgram = true;
+ // Every failed re-transmission doubles the next timeout. We don't want to
+ // slow down the test just to check the re-transmission ability, so we'll
+ // drop only the first 'ClientHello' and 'ServerHello' datagrams. The
+ // arithmetic is approximately this: the first ClientHello to be dropped -
+ // client will re-transmit in 1s., the first part of 'ServerHello' to be
+ // dropped, the client then will re-transmit after another 2 s. Thus it's ~3.
+ // We err on safe side and double our (already quite generous) 5s.
+ testLoop.enterLoopMSecs(handshakeTimeoutMS * 2);
+
+ QVERIFY(!testLoop.timeout());
+ QDTLS_VERIFY_HANDSHAKE_SUCCESS(serverCrypto);
+ QDTLS_VERIFY_HANDSHAKE_SUCCESS(clientCrypto);
+}
+
+void tst_QDtls::sessionCipher()
+{
+ connectHandshakeReadingSlots();
+
+ auto serverConfig = defaultServerConfig;
+ serverConfig.setPrivateKey(serverKeySS);
+ serverConfig.setLocalCertificate(selfSignedCert);
+ QVERIFY(serverCrypto->setDtlsConfiguration(serverConfig));
+
+ auto clientConfig = QSslConfiguration::defaultDtlsConfiguration();
+ clientConfig.setCaCertificates({selfSignedCert});
+ QVERIFY(clientCrypto->setDtlsConfiguration(clientConfig));
+
+ QVERIFY(clientCrypto->setPeer(serverAddress, serverPort, hostName));
+ QVERIFY(clientCrypto->doHandshake(&clientSocket));
+
+ testLoop.enterLoopMSecs(handshakeTimeoutMS);
+
+ QVERIFY(!testLoop.timeout());
+ QDTLS_VERIFY_HANDSHAKE_SUCCESS(clientCrypto);
+ QDTLS_VERIFY_HANDSHAKE_SUCCESS(serverCrypto);
+
+ const auto defaultDtlsConfig = QSslConfiguration::defaultDtlsConfiguration();
+
+ const auto clCipher = clientCrypto->sessionCipher();
+ QVERIFY(!clCipher.isNull());
+ QVERIFY(defaultDtlsConfig.ciphers().contains(clCipher));
+
+ const auto srvCipher = serverCrypto->sessionCipher();
+ QVERIFY(!srvCipher.isNull());
+ QVERIFY(defaultDtlsConfig.ciphers().contains(srvCipher));
+
+ QCOMPARE(clCipher, srvCipher);
+}
+
+void tst_QDtls::cipherPreferences_data()
+{
+ QTest::addColumn<bool>("preferClient");
+
+ QTest::addRow("prefer-server") << true;
+ QTest::addRow("prefer-client") << false;
+}
+
+void tst_QDtls::cipherPreferences()
+{
+ // This test is based on the similar case in tst_QSslSocket. We test it for QDtls
+ // because it's possible to set ciphers and corresponding ('server preferred')
+ // options via QSslConfiguration.
+ const QSslCipher aes128(QStringLiteral("AES128-SHA"));
+ const QSslCipher aes256(QStringLiteral("AES256-SHA"));
+
+ auto serverConfig = defaultServerConfig;
+ const QList<QSslCipher> ciphers = serverConfig.ciphers();
+ if (!ciphers.contains(aes128) || !ciphers.contains(aes256))
+ QSKIP("The ciphers needed by this test were not found in the default DTLS configuration");
+
+ serverConfig.setCiphers({aes128, aes256});
+ serverConfig.setLocalCertificate(selfSignedCert);
+ serverConfig.setPrivateKey(serverKeySS);
+
+ QFETCH(const bool, preferClient);
+ if (preferClient)
+ serverConfig.setSslOption(QSsl::SslOptionDisableServerCipherPreference, true);
+
+ QVERIFY(serverCrypto->setDtlsConfiguration(serverConfig));
+ QDTLS_VERIFY_NO_ERROR(serverCrypto);
+
+ auto clientConfig = QSslConfiguration::defaultDtlsConfiguration();
+ clientConfig.setPeerVerifyMode(QSslSocket::VerifyNone);
+ clientConfig.setCiphers({aes256, aes128});
+ QVERIFY(clientCrypto->setDtlsConfiguration(clientConfig));
+ QVERIFY(clientCrypto->setPeer(serverAddress, serverPort));
+ QDTLS_VERIFY_NO_ERROR(clientCrypto);
+
+ connectHandshakeReadingSlots();
+
+ QVERIFY(clientCrypto->doHandshake(&clientSocket));
+ QDTLS_VERIFY_NO_ERROR(clientCrypto);
+
+ testLoop.enterLoopMSecs(handshakeTimeoutMS);
+ QVERIFY(!testLoop.timeout());
+ QDTLS_VERIFY_HANDSHAKE_SUCCESS(clientCrypto);
+ QDTLS_VERIFY_HANDSHAKE_SUCCESS(serverCrypto);
+
+ if (preferClient) {
+ QCOMPARE(clientCrypto->sessionCipher(), aes256);
+ QCOMPARE(serverCrypto->sessionCipher(), aes256);
+ } else {
+ QCOMPARE(clientCrypto->sessionCipher(), aes128);
+ QCOMPARE(serverCrypto->sessionCipher(), aes128);
+ }
+}
+
+void tst_QDtls::protocolVersionMatching_data()
+{
+ QTest::addColumn<QSsl::SslProtocol>("serverProtocol");
+ QTest::addColumn<QSsl::SslProtocol>("clientProtocol");
+ QTest::addColumn<bool>("works");
+
+ QTest::addRow("DtlsV1_0 <-> DtlsV1_0") << QSsl::DtlsV1_0 << QSsl::DtlsV1_0 << true;
+ QTest::addRow("DtlsV1_0OrLater <-> DtlsV1_0") << QSsl::DtlsV1_0OrLater << QSsl::DtlsV1_0 << true;
+ QTest::addRow("DtlsV1_0 <-> DtlsV1_0OrLater") << QSsl::DtlsV1_0 << QSsl::DtlsV1_0OrLater << true;
+ QTest::addRow("DtlsV1_0OrLater <-> DtlsV1_0OrLater") << QSsl::DtlsV1_0OrLater << QSsl::DtlsV1_0OrLater << true;
+
+ QTest::addRow("DtlsV1_2 <-> DtlsV1_2") << QSsl::DtlsV1_2 << QSsl::DtlsV1_2 << true;
+ QTest::addRow("DtlsV1_2OrLater <-> DtlsV1_2") << QSsl::DtlsV1_2OrLater << QSsl::DtlsV1_2 << true;
+ QTest::addRow("DtlsV1_2 <-> DtlsV1_2OrLater") << QSsl::DtlsV1_2 << QSsl::DtlsV1_2OrLater << true;
+ QTest::addRow("DtlsV1_2OrLater <-> DtlsV1_2OrLater") << QSsl::DtlsV1_2OrLater << QSsl::DtlsV1_2OrLater << true;
+
+ QTest::addRow("DtlsV1_0 <-> DtlsV1_2") << QSsl::DtlsV1_0 << QSsl::DtlsV1_2 << false;
+ QTest::addRow("DtlsV1_0 <-> DtlsV1_2OrLater") << QSsl::DtlsV1_0 << QSsl::DtlsV1_2OrLater << false;
+ QTest::addRow("DtlsV1_2 <-> DtlsV1_0") << QSsl::DtlsV1_2 << QSsl::DtlsV1_0 << false;
+ QTest::addRow("DtlsV1_2OrLater <-> DtlsV1_0") << QSsl::DtlsV1_2OrLater << QSsl::DtlsV1_0 << false;
+}
+
+void tst_QDtls::protocolVersionMatching()
+{
+ QFETCH(const QSsl::SslProtocol, serverProtocol);
+ QFETCH(const QSsl::SslProtocol, clientProtocol);
+ QFETCH(const bool, works);
+
+ connectHandshakeReadingSlots();
+
+ connect(serverCrypto.data(), &QDtls::pskRequired, this, &tst_QDtls::pskRequested);
+ connect(clientCrypto.data(), &QDtls::pskRequired, this, &tst_QDtls::pskRequested);
+
+ auto serverConfig = defaultServerConfig;
+ serverConfig.setProtocol(serverProtocol);
+ QVERIFY(serverCrypto->setDtlsConfiguration(serverConfig));
+
+ auto clientConfig = QSslConfiguration::defaultDtlsConfiguration();
+ clientConfig.setPeerVerifyMode(QSslSocket::VerifyNone);
+ clientConfig.setProtocol(clientProtocol);
+ QVERIFY(clientCrypto->setDtlsConfiguration(clientConfig));
+
+ QVERIFY(clientCrypto->setPeer(serverAddress, serverPort));
+ QVERIFY(clientCrypto->doHandshake(&clientSocket));
+
+ testLoop.enterLoopMSecs(handshakeTimeoutMS);
+
+ if (works) {
+ QDTLS_VERIFY_HANDSHAKE_SUCCESS(serverCrypto);
+ QDTLS_VERIFY_HANDSHAKE_SUCCESS(clientCrypto);
+ } else {
+ QCOMPARE(serverCrypto->isConnectionEncrypted(), false);
+ QVERIFY(serverCrypto->handshakeState() != QDtls::HandshakeComplete);
+ QCOMPARE(clientCrypto->isConnectionEncrypted(), false);
+ QVERIFY(clientCrypto->handshakeState() != QDtls::HandshakeComplete);
+ }
+}
+
+void tst_QDtls::verificationErrors_data()
+{
+ QTest::addColumn<bool>("abortHandshake");
+
+ QTest::addRow("abort-handshake") << true;
+ QTest::addRow("ignore-errors") << false;
+}
+
+void tst_QDtls::verificationErrors()
+{
+ connectHandshakeReadingSlots();
+
+ auto serverConfig = defaultServerConfig;
+ serverConfig.setPrivateKey(serverKeySS);
+ serverConfig.setLocalCertificate(selfSignedCert);
+ QVERIFY(serverCrypto->setDtlsConfiguration(serverConfig));
+ // And our client already has the default DTLS configuration.
+
+ QVERIFY(clientCrypto->setPeer(serverAddress, serverPort));
+ // Now we are ready for handshake:
+ QVERIFY(clientCrypto->doHandshake(&clientSocket));
+
+ testLoop.enterLoopMSecs(handshakeTimeoutMS);
+
+ QVERIFY(!testLoop.timeout());
+ QDTLS_VERIFY_NO_ERROR(serverCrypto);
+
+ QCOMPARE(clientCrypto->dtlsError(), QDtlsError::PeerVerificationError);
+ QCOMPARE(clientCrypto->handshakeState(), QDtls::PeerVerificationFailed);
+ QVERIFY(!clientCrypto->isConnectionEncrypted());
+
+ QVERIFY(verificationErrorDetected(QSslError::HostNameMismatch));
+ QVERIFY(verificationErrorDetected(QSslError::SelfSignedCertificate));
+
+ const auto serverCert = clientCrypto->dtlsConfiguration().peerCertificate();
+ QVERIFY(!serverCert.isNull());
+ QCOMPARE(selfSignedCert, serverCert);
+
+ QFETCH(const bool, abortHandshake);
+
+ if (abortHandshake) {
+ QVERIFY(!clientCrypto->abortHandshake(nullptr));
+ QCOMPARE(clientCrypto->dtlsError(), QDtlsError::InvalidInputParameters);
+ QVERIFY(clientCrypto->abortHandshake(&clientSocket));
+ QDTLS_VERIFY_NO_ERROR(clientCrypto);
+ QVERIFY(!clientCrypto->isConnectionEncrypted());
+ QCOMPARE(clientCrypto->handshakeState(), QDtls::HandshakeNotStarted);
+ QCOMPARE(clientCrypto->sessionCipher(), QSslCipher());
+ QCOMPARE(clientCrypto->sessionProtocol(), QSsl::UnknownProtocol);
+ const auto config = clientCrypto->dtlsConfiguration();
+ QVERIFY(config.peerCertificate().isNull());
+ QCOMPARE(config.peerCertificateChain().size(), 0);
+ QCOMPARE(clientCrypto->peerVerificationErrors().size(), 0);
+ } else {
+ clientCrypto->ignoreVerificationErrors(clientCrypto->peerVerificationErrors());
+ QVERIFY(!clientCrypto->resumeHandshake(nullptr));
+ QCOMPARE(clientCrypto->dtlsError(), QDtlsError::InvalidInputParameters);
+ QVERIFY(clientCrypto->resumeHandshake(&clientSocket));
+ QDTLS_VERIFY_HANDSHAKE_SUCCESS(clientCrypto);
+ QVERIFY(clientCrypto->isConnectionEncrypted());
+ QCOMPARE(clientCrypto->handshakeState(), QDtls::HandshakeComplete);
+ QCOMPARE(clientCrypto->peerVerificationErrors().size(), 0);
+ }
+}
+
+void tst_QDtls::presetExpectedErrors_data()
+{
+ QTest::addColumn<QVector<QSslError>>("expectedTlsErrors");
+ QTest::addColumn<bool>("works");
+
+ QVector<QSslError> expectedErrors{{QSslError::HostNameMismatch, selfSignedCert}};
+ QTest::addRow("unexpected-self-signed") << expectedErrors << false;
+ expectedErrors.push_back({QSslError::SelfSignedCertificate, selfSignedCert});
+ QTest::addRow("all-errors-ignored") << expectedErrors << true;
+}
+
+void tst_QDtls::presetExpectedErrors()
+{
+ QFETCH(const QVector<QSslError>, expectedTlsErrors);
+ QFETCH(const bool, works);
+
+ connectHandshakeReadingSlots();
+
+ auto serverConfig = defaultServerConfig;
+ serverConfig.setPrivateKey(serverKeySS);
+ serverConfig.setLocalCertificate(selfSignedCert);
+ QVERIFY(serverCrypto->setDtlsConfiguration(serverConfig));
+
+ clientCrypto->ignoreVerificationErrors(expectedTlsErrors);
+ QVERIFY(clientCrypto->setPeer(serverAddress, serverPort));
+ QVERIFY(clientCrypto->doHandshake(&clientSocket));
+
+ testLoop.enterLoopMSecs(handshakeTimeoutMS);
+
+ QVERIFY(!testLoop.timeout());
+
+ if (works) {
+ QDTLS_VERIFY_HANDSHAKE_SUCCESS(serverCrypto);
+ QCOMPARE(clientCrypto->handshakeState(), QDtls::HandshakeComplete);
+ QVERIFY(clientCrypto->isConnectionEncrypted());
+ } else {
+ QCOMPARE(clientCrypto->dtlsError(), QDtlsError::PeerVerificationError);
+ QVERIFY(!clientCrypto->isConnectionEncrypted());
+ QCOMPARE(clientCrypto->handshakeState(), QDtls::PeerVerificationFailed);
+ }
+}
+
+void tst_QDtls::verifyServerCertificate_data()
+{
+ QTest::addColumn<QSslSocket::PeerVerifyMode>("verifyMode");
+ QTest::addColumn<QList<QSslCertificate>>("serverCerts");
+ QTest::addColumn<QSslKey>("serverKey");
+ QTest::addColumn<QString>("peerName");
+ QTest::addColumn<bool>("encrypted");
+
+ {
+ // A special case - null key (but with certificate):
+ const auto chain = QSslCertificate::fromPath(certDirPath + QStringLiteral("bogus-server.crt"));
+ QCOMPARE(chain.size(), 1);
+
+ QSslKey nullKey;
+ // Only one row - server must fail to start handshake immediately.
+ QTest::newRow("valid-server-cert-no-key : VerifyPeer") << QSslSocket::VerifyPeer << chain << nullKey << QString() << false;
+ }
+ {
+ // Valid certificate:
+ auto chain = QSslCertificate::fromPath(certDirPath + QStringLiteral("bogus-server.crt"));
+ QCOMPARE(chain.size(), 1);
+
+ const auto caCert = QSslCertificate::fromPath(certDirPath + QStringLiteral("bogus-ca.crt"));
+ QCOMPARE(caCert.size(), 1);
+ chain += caCert;
+
+ QFile keyFile(certDirPath + QStringLiteral("bogus-server.key"));
+ QVERIFY(keyFile.open(QIODevice::ReadOnly));
+ const QSslKey key(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
+ QVERIFY(!key.isNull());
+
+ auto cert = chain.first();
+ const QString name(cert.subjectInfo(QSslCertificate::CommonName).first());
+ QTest::newRow("valid-server-cert : AutoVerifyPeer") << QSslSocket::AutoVerifyPeer << chain << key << name << true;
+ QTest::newRow("valid-server-cert : QueryPeer") << QSslSocket::QueryPeer << chain << key << name << true;
+ QTest::newRow("valid-server-cert : VerifyNone") << QSslSocket::VerifyNone << chain << key << name << true;
+ QTest::newRow("valid-server-cert : VerifyPeer (add CA)") << QSslSocket::VerifyPeer << chain << key << name << true;
+ QTest::newRow("valid-server-cert : VerifyPeer (no CA)") << QSslSocket::VerifyPeer << chain << key << name << false;
+ QTest::newRow("valid-server-cert : VerifyPeer (name mismatch)") << QSslSocket::VerifyPeer << chain << key << QString() << false;
+ }
+}
+
+void tst_QDtls::verifyServerCertificate()
+{
+ QFETCH(const QSslSocket::PeerVerifyMode, verifyMode);
+ QFETCH(const QList<QSslCertificate>, serverCerts);
+ QFETCH(const QSslKey, serverKey);
+ QFETCH(const QString, peerName);
+ QFETCH(const bool, encrypted);
+
+ auto serverConfig = defaultServerConfig;
+ serverConfig.setLocalCertificateChain(serverCerts);
+ serverConfig.setPrivateKey(serverKey);
+ QVERIFY(serverCrypto->setDtlsConfiguration(serverConfig));
+
+ auto clientConfig = QSslConfiguration::defaultDtlsConfiguration();
+
+ if (serverCerts.size() == 2 && encrypted) {
+ auto caCerts = clientConfig.caCertificates();
+ caCerts.append(serverCerts.at(1));
+ clientConfig.setCaCertificates(caCerts);
+ }
+
+ clientConfig.setPeerVerifyMode(verifyMode);
+
+ QVERIFY(clientCrypto->setDtlsConfiguration(clientConfig));
+ QVERIFY(clientCrypto->setPeer(serverAddress, serverPort, peerName));
+
+ connectHandshakeReadingSlots();
+
+ QVERIFY(clientCrypto->doHandshake(&clientSocket));
+
+ testLoop.enterLoopMSecs(handshakeTimeoutMS);
+ QVERIFY(!testLoop.timeout());
+
+ if (serverKey.isNull() && !serverCerts.isEmpty()) {
+ QDTLS_VERIFY_NO_ERROR(clientCrypto);
+ QCOMPARE(clientCrypto->handshakeState(), QDtls::HandshakeInProgress);
+ QCOMPARE(serverCrypto->dtlsError(), QDtlsError::TlsInitializationError);
+ QCOMPARE(serverCrypto->handshakeState(), QDtls::HandshakeNotStarted);
+ return;
+ }
+
+ if (encrypted) {
+ QDTLS_VERIFY_HANDSHAKE_SUCCESS(serverCrypto);
+ QDTLS_VERIFY_HANDSHAKE_SUCCESS(clientCrypto);
+ } else {
+ QVERIFY(!clientCrypto->isConnectionEncrypted());
+ QCOMPARE(clientCrypto->handshakeState(), QDtls::PeerVerificationFailed);
+ QVERIFY(clientCrypto->peerVerificationErrors().size());
+ QVERIFY(clientCrypto->writeDatagramEncrypted(&clientSocket, "something") < 0);
+ QCOMPARE(clientCrypto->dtlsError(), QDtlsError::InvalidOperation);
+ }
+}
+
+void tst_QDtls::verifyClientCertificate_data()
+{
+#if !QT_CONFIG(opensslv11)
+ QSKIP("This test is not supposed to work with OpenSSL version below 1.1");
+#endif
+
+ QTest::addColumn<QSslSocket::PeerVerifyMode>("verifyMode");
+ QTest::addColumn<QList<QSslCertificate>>("clientCerts");
+ QTest::addColumn<QSslKey>("clientKey");
+ QTest::addColumn<bool>("encrypted");
+ {
+ // No certficates, no key:
+ QList<QSslCertificate> chain;
+ QSslKey key;
+ QTest::newRow("no-cert : AutoVerifyPeer") << QSslSocket::AutoVerifyPeer << chain << key << true;
+ QTest::newRow("no-cert : QueryPeer") << QSslSocket::QueryPeer << chain << key << true;
+ QTest::newRow("no-cert : VerifyNone") << QSslSocket::VerifyNone << chain << key << true;
+ QTest::newRow("no-cert : VerifyPeer") << QSslSocket::VerifyPeer << chain << key << false;
+ }
+ {
+ const auto chain = QSslCertificate::fromPath(certDirPath + QStringLiteral("fluke.cert"));
+ QCOMPARE(chain.size(), 1);
+
+ QFile keyFile(certDirPath + QStringLiteral("fluke.key"));
+ QVERIFY(keyFile.open(QIODevice::ReadOnly));
+ const QSslKey key(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
+ QVERIFY(!key.isNull());
+
+ QTest::newRow("self-signed-cert : AutoVerifyPeer") << QSslSocket::AutoVerifyPeer << chain << key << true;
+ QTest::newRow("self-signed-cert : QueryPeer") << QSslSocket::QueryPeer << chain << key << true;
+ QTest::newRow("self-signed-cert : VerifyNone") << QSslSocket::VerifyNone << chain << key << true;
+ QTest::newRow("self-signed-cert : VerifyPeer") << QSslSocket::VerifyPeer << chain << key << false;
+ }
+ {
+ // Valid certificate, but wrong usage (server certificate):
+ const auto chain = QSslCertificate::fromPath(certDirPath + QStringLiteral("bogus-server.crt"));
+ QCOMPARE(chain.size(), 1);
+
+ QFile keyFile(certDirPath + QStringLiteral("bogus-server.key"));
+ QVERIFY(keyFile.open(QIODevice::ReadOnly));
+ const QSslKey key(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
+ QVERIFY(!key.isNull());
+
+ QTest::newRow("valid-server-cert : AutoVerifyPeer") << QSslSocket::AutoVerifyPeer << chain << key << true;
+ QTest::newRow("valid-server-cert : QueryPeer") << QSslSocket::QueryPeer << chain << key << true;
+ QTest::newRow("valid-server-cert : VerifyNone") << QSslSocket::VerifyNone << chain << key << true;
+ QTest::newRow("valid-server-cert : VerifyPeer") << QSslSocket::VerifyPeer << chain << key << false;
+ }
+ {
+ // Valid certificate, correct usage (client certificate):
+ auto chain = QSslCertificate::fromPath(certDirPath + QStringLiteral("bogus-client.crt"));
+ QCOMPARE(chain.size(), 1);
+
+ QFile keyFile(certDirPath + QStringLiteral("bogus-client.key"));
+ QVERIFY(keyFile.open(QIODevice::ReadOnly));
+ const QSslKey key(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
+ QVERIFY(!key.isNull());
+
+ QTest::newRow("valid-client-cert : AutoVerifyPeer") << QSslSocket::AutoVerifyPeer << chain << key << true;
+ QTest::newRow("valid-client-cert : QueryPeer") << QSslSocket::QueryPeer << chain << key << true;
+ QTest::newRow("valid-client-cert : VerifyNone") << QSslSocket::VerifyNone << chain << key << true;
+ QTest::newRow("valid-client-cert : VerifyPeer") << QSslSocket::VerifyPeer << chain << key << true;
+
+ // Valid certificate, correct usage (client certificate), with chain:
+ chain += QSslCertificate::fromPath(certDirPath + QStringLiteral("bogus-ca.crt"));
+ QCOMPARE(chain.size(), 2);
+
+ QTest::newRow("valid-client-chain : AutoVerifyPeer") << QSslSocket::AutoVerifyPeer << chain << key << true;
+ QTest::newRow("valid-client-chain : QueryPeer") << QSslSocket::QueryPeer << chain << key << true;
+ QTest::newRow("valid-client-chain : VerifyNone") << QSslSocket::VerifyNone << chain << key << true;
+ QTest::newRow("valid-client-chain : VerifyPeer") << QSslSocket::VerifyPeer << chain << key << true;
+ }
+}
+
+void tst_QDtls::verifyClientCertificate()
+{
+ connectHandshakeReadingSlots();
+
+ QFETCH(const QSslSocket::PeerVerifyMode, verifyMode);
+ QFETCH(const QList<QSslCertificate>, clientCerts);
+ QFETCH(const QSslKey, clientKey);
+ QFETCH(const bool, encrypted);
+
+ QSslConfiguration serverConfig = defaultServerConfig;
+ serverConfig.setLocalCertificate(selfSignedCert);
+ serverConfig.setPrivateKey(serverKeySS);
+ serverConfig.setPeerVerifyMode(verifyMode);
+
+ if (verifyMode == QSslSocket::VerifyPeer && clientCerts.size()) {
+ // Not always needed even if these conditions met, but does not hurt
+ // either.
+ const auto certs = QSslCertificate::fromPath(certDirPath + QStringLiteral("bogus-ca.crt"));
+ QCOMPARE(certs.size(), 1);
+ serverConfig.setCaCertificates(serverConfig.caCertificates() + certs);
+ }
+
+ QVERIFY(serverCrypto->setDtlsConfiguration(serverConfig));
+ serverConfig = serverCrypto->dtlsConfiguration();
+ QVERIFY(serverConfig.peerCertificate().isNull());
+ QCOMPARE(serverConfig.peerCertificateChain().size(), 0);
+
+ auto clientConfig = QSslConfiguration::defaultDtlsConfiguration();
+ clientConfig.setLocalCertificateChain(clientCerts);
+ clientConfig.setPrivateKey(clientKey);
+ clientConfig.setPeerVerifyMode(QSslSocket::VerifyNone);
+ QVERIFY(clientCrypto->setDtlsConfiguration(clientConfig));
+ QVERIFY(clientCrypto->setPeer(serverAddress, serverPort));
+
+ QVERIFY(clientCrypto->doHandshake(&clientSocket));
+ QDTLS_VERIFY_NO_ERROR(clientCrypto);
+
+ testLoop.enterLoopMSecs(handshakeTimeoutMS);
+
+ serverConfig = serverCrypto->dtlsConfiguration();
+
+ if (verifyMode == QSslSocket::VerifyNone || clientCerts.isEmpty()) {
+ QVERIFY(serverConfig.peerCertificate().isNull());
+ QCOMPARE(serverConfig.peerCertificateChain().size(), 0);
+ } else {
+ QCOMPARE(serverConfig.peerCertificate(), clientCerts.first());
+ QCOMPARE(serverConfig.peerCertificateChain(), clientCerts);
+ }
+
+ if (encrypted) {
+ QDTLS_VERIFY_HANDSHAKE_SUCCESS(serverCrypto);
+ QDTLS_VERIFY_HANDSHAKE_SUCCESS(clientCrypto);
+ } else {
+ QVERIFY(!serverCrypto->isConnectionEncrypted());
+ QCOMPARE(serverCrypto->handshakeState(), QDtls::PeerVerificationFailed);
+ QVERIFY(serverCrypto->dtlsErrorString().size() > 0);
+ QVERIFY(serverCrypto->peerVerificationErrors().size() > 0);
+
+ QVERIFY(!clientCrypto->isConnectionEncrypted());
+ QDTLS_VERIFY_NO_ERROR(clientCrypto);
+ QCOMPARE(clientCrypto->handshakeState(), QDtls::HandshakeInProgress);
+ }
+}
+
+void tst_QDtls::blacklistedCerificate()
+{
+ const auto serverChain = QSslCertificate::fromPath(certDirPath + QStringLiteral("fake-login.live.com.pem"));
+ QCOMPARE(serverChain.size(), 1);
+
+ QFile keyFile(certDirPath + QStringLiteral("fake-login.live.com.key"));
+ QVERIFY(keyFile.open(QIODevice::ReadOnly));
+ const QSslKey key(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
+ QVERIFY(!key.isNull());
+
+ auto serverConfig = defaultServerConfig;
+ serverConfig.setLocalCertificateChain(serverChain);
+ serverConfig.setPrivateKey(key);
+ QVERIFY(serverCrypto->setDtlsConfiguration(serverConfig));
+
+ connectHandshakeReadingSlots();
+ const QString name(serverChain.first().subjectInfo(QSslCertificate::CommonName).first());
+ QVERIFY(clientCrypto->setPeer(serverAddress, serverPort, name));
+ QVERIFY(clientCrypto->doHandshake(&clientSocket));
+
+ testLoop.enterLoopMSecs(handshakeTimeoutMS);
+ QVERIFY(!testLoop.timeout());
+ QCOMPARE(clientCrypto->handshakeState(), QDtls::PeerVerificationFailed);
+ QCOMPARE(clientCrypto->dtlsError(), QDtlsError::PeerVerificationError);
+ QVERIFY(!clientCrypto->isConnectionEncrypted());
+ QVERIFY(verificationErrorDetected(QSslError::CertificateBlacklisted));
+}
+
+void tst_QDtls::readWriteEncrypted_data()
+{
+ QTest::addColumn<bool>("serverSideShutdown");
+
+ QTest::addRow("client-shutdown") << false;
+ QTest::addRow("server-shutdown") << true;
+}
+
+void tst_QDtls::readWriteEncrypted()
+{
+ connectHandshakeReadingSlots();
+
+ auto serverConfig = defaultServerConfig;
+ serverConfig.setLocalCertificate(selfSignedCert);
+ serverConfig.setPrivateKey(serverKeySS);
+ QVERIFY(serverCrypto->setDtlsConfiguration(serverConfig));
+
+ auto clientConfig = QSslConfiguration::defaultDtlsConfiguration();
+ clientConfig.setCaCertificates({selfSignedCert});
+ QVERIFY(clientCrypto->setDtlsConfiguration(clientConfig));
+ QVERIFY(clientCrypto->setPeer(serverAddress, serverPort, hostName));
+
+ // 0. Verify we cannot write any encrypted message without handshake done
+ QDTLS_VERIFY_NO_ERROR(clientCrypto);
+ QVERIFY(clientCrypto->writeDatagramEncrypted(&clientSocket, serverExpectedPlainText) <= 0);
+ QCOMPARE(clientCrypto->dtlsError(), QDtlsError::InvalidOperation);
+ QVERIFY(!clientCrypto->shutdown(&clientSocket));
+ QCOMPARE(clientCrypto->dtlsError(), QDtlsError::InvalidOperation);
+ QDTLS_VERIFY_NO_ERROR(serverCrypto);
+ QVERIFY(serverCrypto->writeDatagramEncrypted(&serverSocket, clientExpectedPlainText) <= 0);
+ QCOMPARE(serverCrypto->dtlsError(), QDtlsError::InvalidOperation);
+ QVERIFY(!serverCrypto->shutdown(&serverSocket));
+ QCOMPARE(serverCrypto->dtlsError(), QDtlsError::InvalidOperation);
+
+ // 1. Initiate a handshake:
+ QVERIFY(clientCrypto->doHandshake(&clientSocket));
+ QDTLS_VERIFY_NO_ERROR(clientCrypto);
+ // 1.1 Verify we cannot read yet. What the datagram is - not really important,
+ // invalid state/operation - is what we verify:
+ const QByteArray dummy = clientCrypto->decryptDatagram(&clientSocket, "BS dgram");
+ QCOMPARE(dummy.size(), 0);
+ QCOMPARE(clientCrypto->dtlsError(), QDtlsError::InvalidOperation);
+
+ // 1.2 Finish the handshake:
+ testLoop.enterLoopMSecs(handshakeTimeoutMS);
+ QVERIFY(!testLoop.timeout());
+
+ QDTLS_VERIFY_HANDSHAKE_SUCCESS(clientCrypto);
+ QDTLS_VERIFY_HANDSHAKE_SUCCESS(serverCrypto);
+
+ // 2. Change reading slots:
+ connectEncryptedReadingSlots();
+
+ // 3. Test parameter validation:
+ QVERIFY(clientCrypto->writeDatagramEncrypted(nullptr, serverExpectedPlainText) <= 0);
+ QCOMPARE(clientCrypto->dtlsError(), QDtlsError::InvalidInputParameters);
+ // 4. Write the client's message:
+ qint64 clientBytesWritten = clientCrypto->writeDatagramEncrypted(&clientSocket, serverExpectedPlainText);
+ QDTLS_VERIFY_NO_ERROR(clientCrypto);
+ QVERIFY(clientBytesWritten > 0);
+
+ // 5. Exchange client/server messages:
+ testLoop.enterLoopMSecs(dataExchangeTimeoutMS);
+ QVERIFY(!testLoop.timeout());
+
+ QCOMPARE(serverExpectedPlainText, serverReceivedPlainText);
+ QCOMPARE(clientExpectedPlainText, clientReceivedPlainText);
+
+ QFETCH(const bool, serverSideShutdown);
+ DtlsPtr &crypto = serverSideShutdown ? serverCrypto : clientCrypto;
+ QUdpSocket *socket = serverSideShutdown ? &serverSocket : &clientSocket;
+ // 6. Parameter validation:
+ QVERIFY(!crypto->shutdown(nullptr));
+ QCOMPARE(crypto->dtlsError(), QDtlsError::InvalidInputParameters);
+ // 7. Send shutdown alert:
+ QVERIFY(crypto->shutdown(socket));
+ QDTLS_VERIFY_NO_ERROR(crypto);
+ QCOMPARE(crypto->handshakeState(), QDtls::HandshakeNotStarted);
+ QVERIFY(!crypto->isConnectionEncrypted());
+ // 8. Receive this read notification and handle it:
+ testLoop.enterLoopMSecs(dataExchangeTimeoutMS);
+ QVERIFY(!testLoop.timeout());
+
+ DtlsPtr &peerCrypto = serverSideShutdown ? clientCrypto : serverCrypto;
+ QVERIFY(!peerCrypto->isConnectionEncrypted());
+ QCOMPARE(peerCrypto->handshakeState(), QDtls::HandshakeNotStarted);
+ QCOMPARE(peerCrypto->dtlsError(), QDtlsError::RemoteClosedConnectionError);
+}
+
+void tst_QDtls::datagramFragmentation()
+{
+ connectHandshakeReadingSlots();
+
+ auto serverConfig = defaultServerConfig;
+ serverConfig.setLocalCertificate(selfSignedCert);
+ serverConfig.setPrivateKey(serverKeySS);
+ QVERIFY(serverCrypto->setDtlsConfiguration(serverConfig));
+
+ auto clientConfig = QSslConfiguration::defaultDtlsConfiguration();
+ clientConfig.setPeerVerifyMode(QSslSocket::VerifyNone);
+ QVERIFY(clientCrypto->setDtlsConfiguration(clientConfig));
+ QVERIFY(clientCrypto->setPeer(serverAddress, serverPort));
+
+ QVERIFY(clientCrypto->doHandshake(&clientSocket));
+
+ testLoop.enterLoopMSecs(handshakeTimeoutMS);
+ QVERIFY(!testLoop.timeout());
+
+ QDTLS_VERIFY_HANDSHAKE_SUCCESS(clientCrypto);
+ QDTLS_VERIFY_HANDSHAKE_SUCCESS(serverCrypto);
+
+ // Done with handshake, reconnect readyRead:
+ connectEncryptedReadingSlots();
+
+ // Verify our dgram is not fragmented and some error set (either UnderlyingSocketError
+ // if OpenSSL somehow had attempted a write or TlsFatalError in case OpenSSL
+ // noticed how big the chunk is).
+ QVERIFY(clientCrypto->writeDatagramEncrypted(&clientSocket, QByteArray(1024 * 17, Qt::Uninitialized)) <= 0);
+ QVERIFY(clientCrypto->dtlsError() != QDtlsError::NoError);
+ // Error to write does not mean QDtls is broken:
+ QVERIFY(clientCrypto->isConnectionEncrypted());
+ QVERIFY(clientCrypto->writeDatagramEncrypted(&clientSocket, "Hello, I'm a tiny datagram") > 0);
+ QDTLS_VERIFY_NO_ERROR(clientCrypto);
+}
+
+void tst_QDtls::handshakeReadyRead()
+{
+ QUdpSocket *socket = qobject_cast<QUdpSocket *>(sender());
+ Q_ASSERT(socket);
+
+ if (!socket->pendingDatagramSize())
+ return;
+
+ const bool isServer = socket == &serverSocket;
+ DtlsPtr &crypto = isServer ? serverCrypto : clientCrypto;
+ DtlsPtr &peerCrypto = isServer ? clientCrypto : serverCrypto;
+ QHostAddress addr;
+ quint16 port = 0;
+
+ QByteArray dgram(socket->pendingDatagramSize(), Qt::Uninitialized);
+ const qint64 size = socket->readDatagram(dgram.data(), dgram.size(), &addr, &port);
+ if (size != dgram.size())
+ return;
+
+ if (isServer) {
+ if (!clientPort) {
+ // It's probably an initial 'ClientHello' message. Let's set remote's
+ // address/port. But first we make sure it is, indeed, 'ClientHello'.
+ if (int(dgram.constData()[0]) != 22)
+ return;
+
+ if (addr.isNull() || addr.isBroadcast()) // Could never be us (client), bail out
+ return;
+
+ if (!crypto->setPeer(addr, port))
+ return testLoop.exitLoop();
+
+ // Check parameter validation:
+ if (crypto->doHandshake(nullptr, dgram) || crypto->dtlsError() != QDtlsError::InvalidInputParameters)
+ return testLoop.exitLoop();
+
+ if (crypto->doHandshake(&serverSocket, {}) || crypto->dtlsError() != QDtlsError::InvalidInputParameters)
+ return testLoop.exitLoop();
+
+ // Make sure we cannot decrypt yet:
+ const QByteArray dummyDgram = crypto->decryptDatagram(&serverSocket, dgram);
+ if (dummyDgram.size() > 0 || crypto->dtlsError() != QDtlsError::InvalidOperation)
+ return testLoop.exitLoop();
+
+ clientAddress = addr;
+ clientPort = port;
+ } else if (clientPort != port || clientAddress != addr) {
+ return;
+ }
+
+ if (serverDropDgram) {
+ serverDropDgram = false;
+ return;
+ }
+ } else if (clientDropDgram) {
+ clientDropDgram = false;
+ return;
+ }
+
+ if (!crypto->doHandshake(socket, dgram))
+ return testLoop.exitLoop();
+
+ const auto state = crypto->handshakeState();
+ if (state != QDtls::HandshakeInProgress && state != QDtls::HandshakeComplete)
+ return testLoop.exitLoop();
+
+ if (state == QDtls::HandshakeComplete && peerCrypto->handshakeState() == QDtls::HandshakeComplete)
+ testLoop.exitLoop();
+}
+
+void tst_QDtls::encryptedReadyRead()
+{
+ QUdpSocket *socket = qobject_cast<QUdpSocket *>(sender());
+ Q_ASSERT(socket);
+
+ if (socket->pendingDatagramSize() <= 0)
+ return;
+
+ QByteArray dtlsMessage(int(socket->pendingDatagramSize()), Qt::Uninitialized);
+ QHostAddress addr;
+ quint16 port = 0;
+ const qint64 bytesRead = socket->readDatagram(dtlsMessage.data(), dtlsMessage.size(), &addr, &port);
+ if (bytesRead <= 0)
+ return;
+
+ dtlsMessage.resize(int(bytesRead));
+
+ if (socket == &serverSocket) {
+ if (addr != clientAddress || port != clientPort)
+ return;
+
+ if (serverExpectedPlainText == dtlsMessage) // No way it can happen!
+ return testLoop.exitLoop();
+
+ serverReceivedPlainText = serverCrypto->decryptDatagram(nullptr, dtlsMessage);
+ if (serverReceivedPlainText.size() > 0 || serverCrypto->dtlsError() != QDtlsError::InvalidInputParameters)
+ return testLoop.exitLoop();
+
+ serverReceivedPlainText = serverCrypto->decryptDatagram(&serverSocket, dtlsMessage);
+
+ const int messageType = dtlsMessage.data()[0];
+ if (serverReceivedPlainText != serverExpectedPlainText
+ && (messageType == 23 || messageType == 21)) {
+ // Type 23 is for application data, 21 is shutdown alert. Here we test
+ // write/read operations and shutdown alerts, not expecting and thus
+ // ignoring any other types of messages.
+ return testLoop.exitLoop();
+ }
+
+ if (serverCrypto->dtlsError() != QDtlsError::NoError)
+ return testLoop.exitLoop();
+
+ // Verify it cannot be done twice:
+ const QByteArray replayed = serverCrypto->decryptDatagram(&serverSocket, dtlsMessage);
+ if (replayed.size() > 0)
+ return testLoop.exitLoop();
+
+ if (serverCrypto->writeDatagramEncrypted(&serverSocket, clientExpectedPlainText) <= 0)
+ testLoop.exitLoop();
+ } else {
+ if (port != serverPort)
+ return;
+
+ if (clientExpectedPlainText == dtlsMessage) // What a disaster!
+ return testLoop.exitLoop();
+
+ clientReceivedPlainText = clientCrypto->decryptDatagram(&clientSocket, dtlsMessage);
+ testLoop.exitLoop();
+ }
+}
+
+void tst_QDtls::pskRequested(QSslPreSharedKeyAuthenticator *auth)
+{
+ Q_ASSERT(auth);
+
+ auth->setPreSharedKey(presharedKey);
+}
+
+void tst_QDtls::handleHandshakeTimeout()
+{
+ auto crypto = qobject_cast<QDtls *>(sender());
+ Q_ASSERT(crypto);
+
+ if (!crypto->handleTimeout(&clientSocket))
+ testLoop.exitLoop();
+}
+
+void tst_QDtls::clientServerData()
+{
+ QTest::addColumn<QSslSocket::SslMode>("mode");
+
+ QTest::addRow("client") << QSslSocket::SslClientMode;
+ QTest::addRow("server") << QSslSocket::SslServerMode;
+}
+
+void tst_QDtls::connectHandshakeReadingSlots()
+{
+ connect(&serverSocket, &QUdpSocket::readyRead, this, &tst_QDtls::handshakeReadyRead);
+ connect(&clientSocket, &QUdpSocket::readyRead, this, &tst_QDtls::handshakeReadyRead);
+}
+
+void tst_QDtls::connectEncryptedReadingSlots()
+{
+ serverSocket.disconnect();
+ clientSocket.disconnect();
+ connect(&serverSocket, &QUdpSocket::readyRead, this, &tst_QDtls::encryptedReadyRead);
+ connect(&clientSocket, &QUdpSocket::readyRead, this, &tst_QDtls::encryptedReadyRead);
+}
+
+bool tst_QDtls::verificationErrorDetected(QSslError::SslError code) const
+{
+ Q_ASSERT(clientCrypto.data());
+
+ const auto errors = clientCrypto->peerVerificationErrors();
+ for (const QSslError &error : errors) {
+ if (error.error() == code)
+ return true;
+ }
+
+ return false;
+}
+
+QHostAddress tst_QDtls::toNonAny(const QHostAddress &addr)
+{
+ if (addr == QHostAddress::Any || addr == QHostAddress::AnyIPv4)
+ return QHostAddress::LocalHost;
+ if (addr == QHostAddress::AnyIPv6)
+ return QHostAddress::LocalHostIPv6;
+ return addr;
+}
+
+QT_END_NAMESPACE
+
+QTEST_MAIN(tst_QDtls)
+
+#include "tst_qdtls.moc"
diff --git a/tests/auto/network/ssl/qdtlscookie/qdtlscookie.pro b/tests/auto/network/ssl/qdtlscookie/qdtlscookie.pro
new file mode 100644
index 0000000000..4caa89fe49
--- /dev/null
+++ b/tests/auto/network/ssl/qdtlscookie/qdtlscookie.pro
@@ -0,0 +1,15 @@
+CONFIG += testcase
+
+SOURCES += tst_qdtlscookie.cpp
+QT = core network-private testlib
+
+TARGET = tst_qdtlscookie
+
+win32 {
+ CONFIG(debug, debug|release) {
+ DESTDIR = debug
+ } else {
+ DESTDIR = release
+ }
+}
+
diff --git a/tests/auto/network/ssl/qdtlscookie/tst_qdtlscookie.cpp b/tests/auto/network/ssl/qdtlscookie/tst_qdtlscookie.cpp
new file mode 100644
index 0000000000..c90e9cb2c8
--- /dev/null
+++ b/tests/auto/network/ssl/qdtlscookie/tst_qdtlscookie.cpp
@@ -0,0 +1,478 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include <QtNetwork/qhostaddress.h>
+#include <QtNetwork/qsslsocket.h>
+#include <QtNetwork/qudpsocket.h>
+#include <QtNetwork/qdtls.h>
+
+#include <QtCore/qcryptographichash.h>
+#include <QtCore/qsharedpointer.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qtimer.h>
+#include <QtCore/qdebug.h>
+
+#include <utility>
+#include <vector>
+
+QT_BEGIN_NAMESPACE
+
+#define STOP_ON_FAILURE \
+ if (QTest::currentTestFailed()) \
+ return;
+
+class tst_QDtlsCookie : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void init();
+
+private slots:
+ // Tests:
+ void construction();
+ void validateParameters_data();
+ void validateParameters();
+ void verifyClient();
+ void cookieGeneratorParameters();
+ void verifyMultipleClients();
+
+protected slots:
+ // Aux. functions:
+ void stopLoopOnMessage();
+ void serverReadyRead();
+ void clientReadyRead();
+ void handleClientTimeout();
+ void makeNoise();
+ void spawnClients();
+
+private:
+ void sendClientHello(QUdpSocket *socket, QDtls *handshake,
+ const QByteArray &serverMessage = {});
+ void receiveMessage(QUdpSocket *socket, QByteArray *message,
+ QHostAddress *address = nullptr,
+ quint16 *port = nullptr);
+
+ static QHostAddress toNonAny(const QHostAddress &addr);
+
+ enum AddressType
+ {
+ ValidAddress,
+ NullAddress,
+ BroadcastAddress,
+ MulticastAddress
+ };
+
+ QUdpSocket serverSocket;
+ QHostAddress serverAddress;
+ quint16 serverPort = 0;
+
+ QTestEventLoop testLoop;
+ int handshakeTimeoutMS = 500;
+
+ QDtlsClientVerifier listener;
+ using HandshakePtr = QSharedPointer<QDtls>;
+ HandshakePtr dtls;
+
+ const QCryptographicHash::Algorithm defaultHash =
+#ifdef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
+ QCryptographicHash::Sha1;
+#else
+ QCryptographicHash::Sha256;
+#endif
+
+ using CookieParams = QDtlsClientVerifier::GeneratorParameters;
+
+ QUdpSocket noiseMaker;
+ QHostAddress spammerAddress;
+ QTimer noiseTimer;
+ quint16 spammerPort = 0;
+ const int noiseTimeoutMS = 5;
+
+ using SocketPtr = QSharedPointer<QUdpSocket>;
+ using ValidClient = QPair<SocketPtr, HandshakePtr>;
+ unsigned clientsToWait = 0;
+ unsigned clientsToAdd = 0;
+ std::vector<ValidClient> dtlsClients;
+ QTimer spawnTimer;
+};
+
+QHostAddress tst_QDtlsCookie::toNonAny(const QHostAddress &addr)
+{
+ if (addr == QHostAddress::Any || addr == QHostAddress::AnyIPv4)
+ return QHostAddress::LocalHost;
+ if (addr == QHostAddress::AnyIPv6)
+ return QHostAddress::LocalHostIPv6;
+ return addr;
+}
+
+void tst_QDtlsCookie::initTestCase()
+{
+ QVERIFY(noiseMaker.bind());
+ spammerAddress = toNonAny(noiseMaker.localAddress());
+ spammerPort = noiseMaker.localPort();
+}
+
+void tst_QDtlsCookie::init()
+{
+ if (serverSocket.state() != QAbstractSocket::UnconnectedState) {
+ serverSocket.close();
+ // Disconnect stopLoopOnMessage or serverReadyRead slots:
+ serverSocket.disconnect();
+ }
+
+ QCOMPARE(serverSocket.state(), QAbstractSocket::UnconnectedState);
+ QVERIFY(serverSocket.bind());
+
+ serverAddress = toNonAny(serverSocket.localAddress());
+ serverPort = serverSocket.localPort();
+
+ dtls.reset(new QDtls(QSslSocket::SslClientMode));
+ dtls->setPeer(serverAddress, serverPort);
+}
+
+void tst_QDtlsCookie::construction()
+{
+ QDtlsClientVerifier verifier;
+
+ QCOMPARE(verifier.dtlsError(), QDtlsError::NoError);
+ QCOMPARE(verifier.dtlsErrorString(), QString());
+ QCOMPARE(verifier.verifiedHello(), QByteArray());
+
+ const auto params = verifier.cookieGeneratorParameters();
+ QCOMPARE(params.hash, defaultHash);
+ QVERIFY(params.secret.size() > 0);
+}
+
+void tst_QDtlsCookie::validateParameters_data()
+{
+ QTest::addColumn<bool>("invalidSocket");
+ QTest::addColumn<bool>("emptyDatagram");
+ QTest::addColumn<int>("addressType");
+
+ QTest::addRow("socket") << true << false << int(ValidAddress);
+ QTest::addRow("dgram") << false << true << int(ValidAddress);
+ QTest::addRow("addr(invalid)") << false << false << int(NullAddress);
+ QTest::addRow("addr(broadcast)") << false << false << int(BroadcastAddress);
+ QTest::addRow("addr(multicast)") << false << false << int(MulticastAddress);
+
+ QTest::addRow("socket-dgram") << true << true << int(ValidAddress);
+ QTest::addRow("socket-dgram-addr(invalid)") << true << true << int(NullAddress);
+ QTest::addRow("socket-dgram-addr(broadcast)") << true << true << int(BroadcastAddress);
+ QTest::addRow("socket-dgram-addr(multicast)") << true << true << int(MulticastAddress);
+
+ QTest::addRow("dgram-addr(invalid)") << false << true << int(NullAddress);
+ QTest::addRow("dgram-addr(broadcast)") << false << true << int(BroadcastAddress);
+ QTest::addRow("dgram-addr(multicast)") << false << true << int(MulticastAddress);
+
+ QTest::addRow("socket-addr(invalid)") << true << false << int(NullAddress);
+ QTest::addRow("socket-addr(broadcast)") << true << false << int(BroadcastAddress);
+ QTest::addRow("socket-addr(multicast)") << true << false << int(MulticastAddress);
+}
+
+void tst_QDtlsCookie::validateParameters()
+{
+ connect(&serverSocket, &QUdpSocket::readyRead, this,
+ &tst_QDtlsCookie::stopLoopOnMessage);
+
+ QFETCH(const bool, invalidSocket);
+ QFETCH(const bool, emptyDatagram);
+ QFETCH(const int, addressType);
+
+ QUdpSocket clientSocket;
+ QByteArray hello;
+ QHostAddress clientAddress;
+ quint16 clientPort = 0;
+
+ sendClientHello(&clientSocket, dtls.data());
+ STOP_ON_FAILURE
+ receiveMessage(&serverSocket, &hello, &clientAddress, &clientPort);
+ STOP_ON_FAILURE
+
+ switch (addressType) {
+ case MulticastAddress:
+ clientAddress.setAddress(QStringLiteral("224.0.0.0"));
+ break;
+ case BroadcastAddress:
+ clientAddress = QHostAddress::Broadcast;
+ break;
+ case NullAddress:
+ clientAddress = {};
+ break;
+ }
+
+ if (emptyDatagram)
+ hello.clear();
+
+ QUdpSocket *socket = invalidSocket ? nullptr : &serverSocket;
+ QCOMPARE(listener.verifyClient(socket, hello, clientAddress, clientPort), false);
+ QCOMPARE(listener.verifiedHello(), QByteArray());
+ QCOMPARE(listener.dtlsError(), QDtlsError::InvalidInputParameters);
+}
+
+void tst_QDtlsCookie::verifyClient()
+{
+ connect(&serverSocket, &QUdpSocket::readyRead, this,
+ &tst_QDtlsCookie::stopLoopOnMessage);
+
+ QUdpSocket clientSocket;
+ connect(&clientSocket, &QUdpSocket::readyRead, this,
+ &tst_QDtlsCookie::stopLoopOnMessage);
+
+ // Client: send an initial ClientHello message without any cookie:
+ sendClientHello(&clientSocket, dtls.data());
+ STOP_ON_FAILURE
+ // Server: read the first ClientHello message:
+ QByteArray dgram;
+ QHostAddress clientAddress;
+ quint16 clientPort = 0;
+ receiveMessage(&serverSocket, &dgram, &clientAddress, &clientPort);
+ STOP_ON_FAILURE
+ // Server: reply with a verify hello request (the client is not verified yet):
+ QCOMPARE(listener.verifyClient(&serverSocket, dgram, clientAddress, clientPort), false);
+ QCOMPARE(listener.verifiedHello(), QByteArray());
+ QCOMPARE(listener.dtlsError(), QDtlsError::NoError);
+ // Client: read hello verify request:
+ receiveMessage(&clientSocket, &dgram);
+ STOP_ON_FAILURE
+ // Client: send a new hello message, this time with a cookie attached:
+ sendClientHello(&clientSocket, dtls.data(), dgram);
+ STOP_ON_FAILURE
+ // Server: read a client-verified message:
+ receiveMessage(&serverSocket, &dgram, &clientAddress, &clientPort);
+ STOP_ON_FAILURE
+ // Client's readyRead is not interesting anymore:
+ clientSocket.close();
+
+ // Verify with the address and port we extracted, do it twice (DTLS "listen"
+ // must be stateless and work as many times as needed):
+ for (int i = 0; i < 2; ++i) {
+ QCOMPARE(listener.verifyClient(&serverSocket, dgram, clientAddress, clientPort), true);
+ QCOMPARE(listener.verifiedHello(), dgram);
+ QCOMPARE(listener.dtlsError(), QDtlsError::NoError);
+ }
+
+ // Test that another freshly created (stateless) verifier can verify:
+ QDtlsClientVerifier anotherListener;
+ QCOMPARE(anotherListener.verifyClient(&serverSocket, dgram, clientAddress,
+ clientPort), true);
+ QCOMPARE(anotherListener.verifiedHello(), dgram);
+ QCOMPARE(anotherListener.dtlsError(), QDtlsError::NoError);
+ // Now let's use a wrong port:
+ QCOMPARE(listener.verifyClient(&serverSocket, dgram, clientAddress, serverPort), false);
+ // Invalid cookie, no verified hello message:
+ QCOMPARE(listener.verifiedHello(), QByteArray());
+ // But it's UDP so we ignore this "fishy datagram", no error expected:
+ QCOMPARE(listener.dtlsError(), QDtlsError::NoError);
+}
+
+void tst_QDtlsCookie::cookieGeneratorParameters()
+{
+ CookieParams params;// By defualt, 'secret' is empty.
+ QCOMPARE(listener.setCookieGeneratorParameters(params), false);
+ QCOMPARE(listener.dtlsError(), QDtlsError::InvalidInputParameters);
+ params.secret = "abcdefghijklmnopqrstuvwxyz";
+ QCOMPARE(listener.setCookieGeneratorParameters(params), true);
+ QCOMPARE(listener.dtlsError(), QDtlsError::NoError);
+}
+
+void tst_QDtlsCookie::verifyMultipleClients()
+{
+ // 'verifyClient' above was quite simple - it's like working with blocking
+ // sockets, step by step - we write, then make sure we read a datagram back
+ // etc. This test is more asynchronous - we are running an event loop and don't
+ // stop on the first datagram received, instead, we spawn many clients
+ // with which to exchange handshake messages and verify requests, while at
+ // the same time dealing with a 'noise maker' - a fake DTLS client, who keeps
+ // spamming our server with non-DTLS datagrams and initial ClientHello
+ // messages, but never replies to client verify requests.
+ connect(&serverSocket, &QUdpSocket::readyRead, this, &tst_QDtlsCookie::serverReadyRead);
+
+ noiseTimer.setInterval(noiseTimeoutMS);
+ connect(&noiseTimer, &QTimer::timeout, this, &tst_QDtlsCookie::makeNoise);
+
+ spawnTimer.setInterval(noiseTimeoutMS * 10);
+ connect(&spawnTimer, &QTimer::timeout, this, &tst_QDtlsCookie::spawnClients);
+
+ noiseTimer.start();
+ spawnTimer.start();
+
+ clientsToAdd = clientsToWait = 100;
+
+ testLoop.enterLoop(handshakeTimeoutMS * clientsToWait);
+ QVERIFY(!testLoop.timeout());
+ QVERIFY(clientsToWait == 0);
+}
+
+void tst_QDtlsCookie::sendClientHello(QUdpSocket *socket, QDtls *dtls,
+ const QByteArray &serverMessage)
+{
+ Q_ASSERT(socket && dtls);
+ dtls->doHandshake(socket, serverMessage);
+ // We don't really care about QDtls in this auto-test, but must be
+ // sure that we, indeed, sent our hello and if not - stop early without
+ // running event loop:
+ QCOMPARE(dtls->dtlsError(), QDtlsError::NoError);
+ // We never complete a handshake, so it must be 'HandshakeInProgress':
+ QCOMPARE(dtls->handshakeState(), QDtls::HandshakeInProgress);
+}
+
+void tst_QDtlsCookie::receiveMessage(QUdpSocket *socket, QByteArray *message,
+ QHostAddress *address, quint16 *port)
+{
+ Q_ASSERT(socket && message);
+
+ if (!socket->pendingDatagramSize())
+ testLoop.enterLoopMSecs(handshakeTimeoutMS);
+
+ QVERIFY(!testLoop.timeout());
+ QVERIFY(socket->pendingDatagramSize());
+
+ message->resize(socket->pendingDatagramSize());
+ const qint64 read = socket->readDatagram(message->data(), message->size(),
+ address, port);
+ QVERIFY(read > 0);
+
+ message->resize(read);
+ if (address)
+ QVERIFY(!address->isNull());
+}
+
+void tst_QDtlsCookie::stopLoopOnMessage()
+{
+ testLoop.exitLoop();
+}
+
+void tst_QDtlsCookie::serverReadyRead()
+{
+ Q_ASSERT(clientsToWait);
+
+ if (!serverSocket.pendingDatagramSize())
+ return;
+
+ QByteArray hello;
+ QHostAddress clientAddress;
+ quint16 clientPort = 0;
+
+ receiveMessage(&serverSocket, &hello, &clientAddress, &clientPort);
+ if (QTest::currentTestFailed())
+ return testLoop.exitLoop();
+
+ const bool ok = listener.verifyClient(&serverSocket, hello, clientAddress, clientPort);
+ if (listener.dtlsError() != QDtlsError::NoError) {
+ // exit early, let the test fail.
+ return testLoop.exitLoop();
+ }
+
+ if (!ok) // not verified yet.
+ return;
+
+ if (clientAddress == spammerAddress && clientPort == spammerPort) // should never happen
+ return testLoop.exitLoop();
+
+ --clientsToWait;
+ if (!clientsToWait) // done, success.
+ testLoop.exitLoop();
+}
+
+void tst_QDtlsCookie::clientReadyRead()
+{
+ QUdpSocket *clientSocket = qobject_cast<QUdpSocket *>(sender());
+ Q_ASSERT(clientSocket);
+
+ if (!clientSocket->pendingDatagramSize())
+ return;
+
+ QDtls *handshake = nullptr;
+ for (ValidClient &client : dtlsClients) {
+ if (client.first.data() == clientSocket) {
+ handshake = client.second.data();
+ break;
+ }
+ }
+
+ Q_ASSERT(handshake);
+
+ QByteArray response;
+ receiveMessage(clientSocket, &response);
+ if (QTest::currentTestFailed() || !handshake->doHandshake(clientSocket, response))
+ testLoop.exitLoop();
+}
+
+void tst_QDtlsCookie::makeNoise()
+{
+ noiseMaker.writeDatagram({"Hello, my little DTLS server, take this useless dgram!"},
+ serverAddress, serverPort);
+ QDtls fakeHandshake(QSslSocket::SslClientMode);
+ fakeHandshake.setPeer(serverAddress, serverPort);
+ fakeHandshake.doHandshake(&noiseMaker, {});
+}
+
+void tst_QDtlsCookie::spawnClients()
+{
+ for (int i = 0; i < 10 && clientsToAdd; ++i, --clientsToAdd) {
+ ValidClient newClient;
+ newClient.first.reset(new QUdpSocket);
+ connect(newClient.first.data(), &QUdpSocket::readyRead,
+ this, &tst_QDtlsCookie::clientReadyRead);
+ newClient.second.reset(new QDtls(QSslSocket::SslClientMode));
+ newClient.second->setPeer(serverAddress, serverPort);
+ connect(newClient.second.data(), &QDtls::handshakeTimeout,
+ this, &tst_QDtlsCookie::handleClientTimeout);
+ newClient.second->doHandshake(newClient.first.data(), {});
+ dtlsClients.push_back(std::move(newClient));
+ }
+}
+
+void tst_QDtlsCookie::handleClientTimeout()
+{
+ QDtls *handshake = qobject_cast<QDtls *>(sender());
+ Q_ASSERT(handshake);
+
+ QUdpSocket *clientSocket = nullptr;
+ for (ValidClient &client : dtlsClients) {
+ if (client.second.data() == handshake) {
+ clientSocket = client.first.data();
+ break;
+ }
+ }
+
+ Q_ASSERT(clientSocket);
+ handshake->handleTimeout(clientSocket);
+}
+
+QT_END_NAMESPACE
+
+QTEST_MAIN(tst_QDtlsCookie)
+
+#include "tst_qdtlscookie.moc"
diff --git a/tests/auto/network/ssl/qpassworddigestor/qpassworddigestor.pro b/tests/auto/network/ssl/qpassworddigestor/qpassworddigestor.pro
new file mode 100644
index 0000000000..3e2685f579
--- /dev/null
+++ b/tests/auto/network/ssl/qpassworddigestor/qpassworddigestor.pro
@@ -0,0 +1,4 @@
+CONFIG += testcase
+TARGET = tst_qpassworddigestor
+QT = core network testlib
+SOURCES = tst_qpassworddigestor.cpp
diff --git a/tests/auto/network/ssl/qpassworddigestor/tst_qpassworddigestor.cpp b/tests/auto/network/ssl/qpassworddigestor/tst_qpassworddigestor.cpp
new file mode 100644
index 0000000000..bbd6c72ca8
--- /dev/null
+++ b/tests/auto/network/ssl/qpassworddigestor/tst_qpassworddigestor.cpp
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtNetwork/qpassworddigestor.h>
+#include <QtCore/QByteArray>
+
+class tst_QPasswordDigestor : public QObject
+{
+ Q_OBJECT
+private Q_SLOTS:
+ void pbkdf1Vectors_data();
+ void pbkdf1Vectors();
+ void pbkdf2Vectors_data();
+ void pbkdf2Vectors();
+};
+
+void tst_QPasswordDigestor::pbkdf1Vectors_data()
+{
+ QTest::addColumn<QCryptographicHash::Algorithm>("algorithm");
+ QTest::addColumn<QByteArray>("password");
+ QTest::addColumn<QByteArray>("salt");
+ QTest::addColumn<int>("iterations");
+ QTest::addColumn<int>("dkLen");
+ QTest::addColumn<QByteArray>("result");
+
+ // data from
+ // https://web.archive.org/web/20160912052752/https://www.di-mgt.com.au/cryptoKDFs.html#examplespbkdf
+ // (Note: this is not official, but at least it's something to compare with.)
+ QTest::newRow("di-mgt") << QCryptographicHash::Sha1 << QByteArray::fromHex("70617373776F7264")
+ << QByteArray::fromHex("78578E5A5D63CB06") << 1000 << 16
+ << QByteArray::fromHex("DC19847E05C64D2FAF10EBFB4A3D2A20");
+}
+
+void tst_QPasswordDigestor::pbkdf1Vectors()
+{
+ QFETCH(QCryptographicHash::Algorithm, algorithm);
+ QFETCH(QByteArray, password);
+ QFETCH(QByteArray, salt);
+ QFETCH(int, iterations);
+ QFETCH(int, dkLen);
+ QFETCH(QByteArray, result);
+
+ QCOMPARE(QPasswordDigestor::deriveKeyPbkdf1(algorithm, password, salt, iterations, dkLen), result);
+}
+
+void tst_QPasswordDigestor::pbkdf2Vectors_data()
+{
+ QTest::addColumn<QCryptographicHash::Algorithm>("algorithm");
+ QTest::addColumn<QByteArray>("password");
+ QTest::addColumn<QByteArray>("salt");
+ QTest::addColumn<int>("iterations");
+ QTest::addColumn<int>("dkLen");
+ QTest::addColumn<QByteArray>("result");
+
+ // data from https://tools.ietf.org/html/rfc6070
+ auto hash = QCryptographicHash::Sha1;
+ QTest::newRow("rfc6070-1") << hash << QByteArrayLiteral("password") << QByteArrayLiteral("salt")
+ << 1 << 20
+ << QByteArray::fromHex("0c60c80f961f0e71f3a9b524af6012062fe037a6");
+ QTest::newRow("rfc6070-2") << hash << QByteArrayLiteral("password") << QByteArrayLiteral("salt")
+ << 2 << 20
+ << QByteArray::fromHex("ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957");
+ QTest::newRow("rfc6070-3") << hash << QByteArrayLiteral("password") << QByteArrayLiteral("salt")
+ << 4096 << 20
+ << QByteArray::fromHex("4b007901b765489abead49d926f721d065a429c1");
+#if 0
+ // Excluding: takes about 3 minutes to run
+ QTest::newRow("rfc6070-4") << hash << QByteArrayLiteral("password") << QByteArrayLiteral("salt")
+ << 16777216 << 20
+ << QByteArray::fromHex("eefe3d61cd4da4e4e9945b3d6ba2158c2634e984");
+#endif
+ QTest::newRow("rfc6070-5") << hash << QByteArrayLiteral("passwordPASSWORDpassword")
+ << QByteArrayLiteral("saltSALTsaltSALTsaltSALTsaltSALTsalt") << 4096
+ << 25
+ << QByteArray::fromHex(
+ "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038");
+ QTest::newRow("rfc6070-6") << hash << QByteArrayLiteral("pass\0word")
+ << QByteArrayLiteral("sa\0lt") << 4096 << 16
+ << QByteArray::fromHex("56fa6aa75548099dcc37d7f03425e0c3");
+
+ // the next few bits of data are from https://tools.ietf.org/html/rfc3962#appendix-B
+ QByteArray password = QByteArrayLiteral("password");
+ QByteArray salt = QByteArrayLiteral("ATHENA.MIT.EDUraeburn");
+ QTest::newRow("rfc3962-1") << hash << password << salt << 1 << 16
+ << QByteArray::fromHex("cdedb5281bb2f801565a1122b2563515");
+ QTest::newRow("rfc3962-2")
+ << hash << password << salt << 1 << 32
+ << QByteArray::fromHex("cdedb5281bb2f801565a1122b25635150ad1f7a04bb9f3a333ecc0e2e1f70837");
+ QTest::newRow("rfc3962-3") << hash << password << salt << 2 << 16
+ << QByteArray::fromHex("01dbee7f4a9e243e988b62c73cda935d");
+ QTest::newRow("rfc3962-4")
+ << hash << QByteArrayLiteral("password") << salt << 2 << 32
+ << QByteArray::fromHex("01dbee7f4a9e243e988b62c73cda935da05378b93244ec8f48a99e61ad799d86");
+ QTest::newRow("rfc3962-5") << hash << password << salt << 1200 << 16
+ << QByteArray::fromHex("5c08eb61fdf71e4e4ec3cf6ba1f5512b");
+ QTest::newRow("rfc3962-6")
+ << hash << password << salt << 1200 << 32
+ << QByteArray::fromHex("5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddbc5e5142f708a31e2e62b1e13");
+
+ salt = QByteArray::fromHex("1234567878563412"); // 0x1234567878563412
+ QTest::newRow("rfc3962-7") << hash << password << salt << 5 << 16
+ << QByteArray::fromHex("d1daa78615f287e6a1c8b120d7062a49");
+ QTest::newRow("rfc3962-8")
+ << hash << password << salt << 5 << 32
+ << QByteArray::fromHex("d1daa78615f287e6a1c8b120d7062a493f98d203e6be49a6adf4fa574b6e64ee");
+
+ password = QByteArray(64, 'X');
+ salt = "pass phrase equals block size";
+ QTest::newRow("rfc3962-9") << hash << password << salt << 1200 << 16
+ << QByteArray::fromHex("139c30c0966bc32ba55fdbf212530ac9");
+ QTest::newRow("rfc3962-10")
+ << hash << password << salt << 1200 << 32
+ << QByteArray::fromHex("139c30c0966bc32ba55fdbf212530ac9c5ec59f1a452f5cc9ad940fea0598ed1");
+
+ password.append('X');
+ salt = "pass phrase exceeds block size";
+ QTest::newRow("rfc3962-11") << hash << password << salt << 1200 << 16
+ << QByteArray::fromHex("9ccad6d468770cd51b10e6a68721be61");
+ QTest::newRow("rfc3962-12")
+ << hash << password << salt << 1200 << 32
+ << QByteArray::fromHex("9ccad6d468770cd51b10e6a68721be611a8b4d282601db3b36be9246915ec82a");
+
+ password = QByteArray::fromHex("f09d849e"); // 0xf09d849e
+ salt = "EXAMPLE.COMpianist";
+ QTest::newRow("rfc3962-13") << hash << password << salt << 50 << 16
+ << QByteArray::fromHex("6b9cf26d45455a43a5b8bb276a403b39");
+ QTest::newRow("rfc3962-14")
+ << hash << password << salt << 50 << 32
+ << QByteArray::fromHex("6b9cf26d45455a43a5b8bb276a403b39e7fe37a0c41e02c281ff3069e1e94f52");
+}
+
+void tst_QPasswordDigestor::pbkdf2Vectors()
+{
+ QFETCH(QCryptographicHash::Algorithm, algorithm);
+ QFETCH(QByteArray, password);
+ QFETCH(QByteArray, salt);
+ QFETCH(int, iterations);
+ QFETCH(int, dkLen);
+ QFETCH(QByteArray, result);
+
+ QCOMPARE(QPasswordDigestor::deriveKeyPbkdf2(algorithm, password, salt, iterations, dkLen), result);
+}
+
+QTEST_MAIN(tst_QPasswordDigestor)
+#include "tst_qpassworddigestor.moc"
diff --git a/tests/auto/network/ssl/qsslcertificate/qsslcertificate.pro b/tests/auto/network/ssl/qsslcertificate/qsslcertificate.pro
index 7c1cd5b66b..7e6870f74b 100644
--- a/tests/auto/network/ssl/qsslcertificate/qsslcertificate.pro
+++ b/tests/auto/network/ssl/qsslcertificate/qsslcertificate.pro
@@ -1,7 +1,6 @@
CONFIG += testcase
SOURCES += tst_qsslcertificate.cpp
-win32:LIBS += -lws2_32
QT = core network testlib
TARGET = tst_qsslcertificate
diff --git a/tests/auto/network/ssl/qsslcipher/qsslcipher.pro b/tests/auto/network/ssl/qsslcipher/qsslcipher.pro
index 81ef2d8d9a..392d22c054 100644
--- a/tests/auto/network/ssl/qsslcipher/qsslcipher.pro
+++ b/tests/auto/network/ssl/qsslcipher/qsslcipher.pro
@@ -1,7 +1,6 @@
CONFIG += testcase
SOURCES += tst_qsslcipher.cpp
-win32:LIBS += -lws2_32
QT = core network testlib
TARGET = tst_qsslcipher
diff --git a/tests/auto/network/ssl/qssldiffiehellmanparameters/qssldiffiehellmanparameters.pro b/tests/auto/network/ssl/qssldiffiehellmanparameters/qssldiffiehellmanparameters.pro
index dee95886e0..2d45f4476c 100644
--- a/tests/auto/network/ssl/qssldiffiehellmanparameters/qssldiffiehellmanparameters.pro
+++ b/tests/auto/network/ssl/qssldiffiehellmanparameters/qssldiffiehellmanparameters.pro
@@ -2,7 +2,6 @@ CONFIG += testcase
CONFIG += parallel_test
SOURCES += tst_qssldiffiehellmanparameters.cpp
-win32: LIBS += -lws2_32
QT = core network testlib
TARGET = tst_qssldiffiehellmanparameters
diff --git a/tests/auto/network/ssl/qsslellipticcurve/qsslellipticcurve.pro b/tests/auto/network/ssl/qsslellipticcurve/qsslellipticcurve.pro
index a180086c5e..7eae6ae864 100644
--- a/tests/auto/network/ssl/qsslellipticcurve/qsslellipticcurve.pro
+++ b/tests/auto/network/ssl/qsslellipticcurve/qsslellipticcurve.pro
@@ -1,7 +1,6 @@
CONFIG += testcase
SOURCES += tst_qsslellipticcurve.cpp
-win32:LIBS += -lws2_32
QT = core network testlib
TARGET = tst_qsslellipticcurve
diff --git a/tests/auto/network/ssl/qsslerror/qsslerror.pro b/tests/auto/network/ssl/qsslerror/qsslerror.pro
index 117fd4ac27..83644d093c 100644
--- a/tests/auto/network/ssl/qsslerror/qsslerror.pro
+++ b/tests/auto/network/ssl/qsslerror/qsslerror.pro
@@ -1,7 +1,6 @@
CONFIG += testcase
SOURCES += tst_qsslerror.cpp
-win32:LIBS += -lws2_32
QT = core network testlib
TARGET = tst_qsslerror
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-MD5-DES.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-MD5-DES.der
new file mode 100644
index 0000000000..e70bde5820
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-MD5-DES.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-MD5-DES.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-MD5-DES.pem
new file mode 100644
index 0000000000..fd62743d94
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-MD5-DES.pem
@@ -0,0 +1,8 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIHwMBsGCSqGSIb3DQEFAzAOBAiBYHv8jvBwMQICCAAEgdCwfamafrN1nvpdnF5t
+KCPgBvRGfV9zStK+XItBAe72CZdAy1Jjr2UJHc8Rl3OEo2hmCr+892/lhK7GIugj
+oLOvON3VEqrUvrvmH0Qtm+/A/ypq14Lr4sBfq7bViM44bv/DUwHMD5/xmLtSzXlC
+AjjioBJ/k4K+6DzD3+eMDNr6Z9rCUcvJP6q8+PPhpIXEJquA3RYuyuDhdIbazO5A
+iMts7PbzBzW/4YhENPWaUdviuRZo/ap+WDJ/SdwiNxOxx7KrWgj3y2dAtNnVAv5T
+njE4
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-MD5-RC2-64.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-MD5-RC2-64.der
new file mode 100644
index 0000000000..40bbe6a441
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-MD5-RC2-64.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-MD5-RC2-64.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-MD5-RC2-64.pem
new file mode 100644
index 0000000000..6a8a8484e0
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-MD5-RC2-64.pem
@@ -0,0 +1,8 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIHwMBsGCSqGSIb3DQEFBjAOBAga2K6FvYk1ygICCAAEgdCV9m57p+DrBrVafXUq
+8pgdr+1FEX9YaFXNRMKyPZ5Ca6t5RsPpWC3RdGlieH4iVp03/rlTttx0rLUWx3IG
+gsrd2adrP6Bl/lbEJnZ6lIeZz2KvPbbhfmRMCIhr/h24JSi5lmGl5KzxQXSm9ujb
+/5jtN/QtoQ3cLWpNn1SwMNdIAYgEpnCghwqITbBwMovD8yd2YNbNbejG/T+q6bwl
+GJE46OSX+IAWQ/wJejdq//ozD3m2PxjK6nktWeqAeoqcycYGYGKvta27lNqyuE3M
+BdGT
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-SHA1-DES.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-SHA1-DES.der
new file mode 100644
index 0000000000..6ebe9c4011
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-SHA1-DES.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-SHA1-DES.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-SHA1-DES.pem
new file mode 100644
index 0000000000..3422931606
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-SHA1-DES.pem
@@ -0,0 +1,8 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIHwMBsGCSqGSIb3DQEFCjAOBAjj2EIj8WAOWwICCAAEgdB4G1oLnLtLAGaZtpGb
+vU2g4g3pJtQLJX1H0a/cmXO1OrX7YRcESvw8nocZjNKKWCehfQqinRBpVUsoaGUw
+QssIDKlWkW3LbM11F6YMI5GCzN5bpWcJazQRyHEnIk/OTQN3aeKjnYQXep1nt7tN
+INKsCAVyx1cYfr3izxGRwN2hTraz5fBdeBpEye+Essn5KziwET32EbW+kt+wsule
+k4tvnKgCOvbvVzqIdafH/FfP04KRv39O+HR3evoBjhGudUxXJ0OLp8IZkG+34f3P
+ZQxC
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-SHA1-RC2-64.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-SHA1-RC2-64.der
new file mode 100644
index 0000000000..c8ae94c4f8
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-SHA1-RC2-64.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-SHA1-RC2-64.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-SHA1-RC2-64.pem
new file mode 100644
index 0000000000..93857f010b
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-PBE-SHA1-RC2-64.pem
@@ -0,0 +1,8 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIHwMBsGCSqGSIb3DQEFCzAOBAgrv/kKBXNFAwICCAAEgdAFpWxMmQygufWZpeAI
+heJ3uqyb5bnahW75t2HWQZTb1qEqp62/iLr1IlbHmZAQbJc0+VLhXz/2QtK3q/BB
+bHpa9cWGFi2HVgO4dFjSI7X68QrM93GPGHqwtnVZnlo2aPHgA6BzotEEwklXl4Db
+BbPKo0vBUVA9ZKaN0lH+Pzj/Rb37kC6xRWBjNd87jaszykcNFYkTNrrG8nESHJAw
+fTeHwrsGsmIz8FfOxRfqXrPwOiA5AZZ/S/8Jt2gtoOW5ydY6/Bfp0aEwAIhwxjFJ
+cy6N
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes128-hmacWithSHA1.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes128-hmacWithSHA1.der
new file mode 100644
index 0000000000..2c2caa0665
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes128-hmacWithSHA1.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes128-hmacWithSHA1.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes128-hmacWithSHA1.pem
new file mode 100644
index 0000000000..0797d9167f
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes128-hmacWithSHA1.pem
@@ -0,0 +1,9 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBHjBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQI8mhki8A7ijgCAggA
+MB0GCWCGSAFlAwQBAgQQbVjLreAybYGwsnk4ZMQUIgSB0Ozr2DfP+rkb58tT748m
++7xe+bhpT3xrrSpUsB2RXUH/6M7hVjb+XZ/JSAegqkuZq08df+ezpHjWX/W+IVL4
+Sx0wZWNW51TiwGymNFuBwSVliqCvndAaY+EIY3bsME5RFik86R4iAbtrxalWPFoR
+jscLkGtNstQR5JQCOccTN7h5jRBwEFrArqfPv+XZb5ysy9FjFnVDuspFg/CysIJD
+V7WEJcxOzEIk2bbxY4UEpLhfFv8RHrV8M7jmjVRC+mN094zMnzBVSv8KIjk0Ljff
+ysY=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes128-hmacWithSHA256.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes128-hmacWithSHA256.der
new file mode 100644
index 0000000000..3f3bd2e8ea
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes128-hmacWithSHA256.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes128-hmacWithSHA256.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes128-hmacWithSHA256.pem
new file mode 100644
index 0000000000..e78d69ae8a
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes128-hmacWithSHA256.pem
@@ -0,0 +1,9 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBLDBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQICIPD0G0X/sECAggA
+MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAECBBDSrIv/kITtQ/RL5j675WqsBIHQ
+oSiQJLyXPOmnNYmWLw4Biom8Utn/I8109mUujVPhUA63njp0I/jGwNn4FcdilZlO
+TTCKIxlzG3zhztS5xqxQFuzWNQdTgfqzO7DSi/ZtGErvZi+ShaiQU7ri7LYRIw8C
+7YtXiPrfPSKpfyU0adD2socAa1OlnvinoaHYd/QNs4EEv3hahIiq/nHpzRkb2qdX
+XIruJhlvF4B07aYfmRvMK4CVd6VGXfGfGXECFqMk5b7HwJzkMTbtB2bsMTNguGxK
+o1+Hf3PHRst6q1776z8ENw==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes256-hmacWithSHA1.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes256-hmacWithSHA1.der
new file mode 100644
index 0000000000..f078644544
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes256-hmacWithSHA1.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes256-hmacWithSHA1.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes256-hmacWithSHA1.pem
new file mode 100644
index 0000000000..9a6b147602
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes256-hmacWithSHA1.pem
@@ -0,0 +1,9 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBHjBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIdlQB+08q40gCAggA
+MB0GCWCGSAFlAwQBKgQQ3dY2cSZfdPyeYlHRO+M63wSB0DjoR/cQ2rLkW1Ur8V1q
+LG/0nv0O1mVK8Sj+BcOje/nqMU67lRdkXVI1yICmpwrwFEkwIV6zHIx+Dwriliel
+h0yXsTLaBmMQeJo17J6kOyuW+C0Mr8CqlnAVEoEQI7FPes7rtw6W0wkuuPPw3vEs
+RKB8xwdfS5t5ot5DtKZ5rN+6XbtRA/jdfi1O6ekKzeT0fpRGP+ppTEmCh77+8Ity
+/BwPKGXepZpHkOcDOvWGdDiuy7vhA5gaYyzpXPD2Fo3V5cobFzgLzT3in+b6YtV4
+s/4=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes256-hmacWithSHA256.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes256-hmacWithSHA256.der
new file mode 100644
index 0000000000..618be6ad9c
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes256-hmacWithSHA256.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes256-hmacWithSHA256.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes256-hmacWithSHA256.pem
new file mode 100644
index 0000000000..a82c2fbc94
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-aes256-hmacWithSHA256.pem
@@ -0,0 +1,9 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBLDBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIVsIsQ3kPm5gCAggA
+MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBAOdrxyNKYeoKCTuDXeYiwpBIHQ
+DheVgnsmJ7bYb5Y02qOdCjfYEUje8bvendhIsG41recaNjdHcWQB1JOV8anmZPJ+
+4buMQhE9Lfw5Hvg2x0pqkvQCV0aUWUwwybnoQ9T8z0z67WJG6f03m9eE+Mzw9Q0D
+wavghqO/lnh9uGd4Tdfzuj0NWHbrey7ags81fZ9jWOdX/M5LywFr7oThokfq6LlH
+rpnK13j9MUVrmmSvsjVXGjWErEaTXbJOpCeyDn1510iI5pyGRZpicmfHzE6YNHvF
+dKSlxRWO+cOxE9Ax9dm5mg==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-des3-hmacWithSHA1.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-des3-hmacWithSHA1.der
new file mode 100644
index 0000000000..33ca45e2c9
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-des3-hmacWithSHA1.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-des3-hmacWithSHA1.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-des3-hmacWithSHA1.pem
new file mode 100644
index 0000000000..ec276fd807
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-des3-hmacWithSHA1.pem
@@ -0,0 +1,8 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBFTBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIwE9ZHpXAOK8CAggA
+MBQGCCqGSIb3DQMHBAgOtF6y98HdvQSB0KtvnVtpFqjG8OLzPyZrugisgiYBgvoU
+62D+rfO5Ji4cbWwuQEeS3ywI7rHH6BG8+mxcVeQHSmGZi336M/j0erO/yo6MnkrU
+a8pfrqfPvLJPa+2FPSWlM/+ppj+kcaZa0B8pF/mioBThID8KhDFm8CG4UwP4P2Kn
+GUUGmM9cyNdPFWuVg8PyY1zHcx2GNiL4XZcKp1qsGf75uso8DmgrvI+c9yDD+5ag
+rPmsgFSy3XtlNmYGyLq1pW4rQ6ivLknZc5oweqjISVT3jKjJqowgJYo=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-des3-hmacWithSHA256.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-des3-hmacWithSHA256.der
new file mode 100644
index 0000000000..6d23cd3604
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-des3-hmacWithSHA256.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-des3-hmacWithSHA256.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-des3-hmacWithSHA256.pem
new file mode 100644
index 0000000000..f33f0dc4c4
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-des3-hmacWithSHA256.pem
@@ -0,0 +1,9 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBIzBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQI584onGZg/sMCAggA
+MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECMEvKBdjD2B+BIHQlCNsdhKhN8ce
+l73RzS4AUNbPamaLPV+l+vy8F4jjziCux0RwS/83ju/XlD/TntSYH4RYx/2vNHo5
+/YVGinOSTHZD7BqHHOxTjMqlVY4uFU2oJcGQ2VIsbVuPiL78Tq6XcuaIy5ElXjte
+g/qa8y9/cJM9wm6O1XMfIIL6AboBdbVloStvij3HOOOOlZp6161+QlmADdo2yJJ2
+byP7SoC4I6fLDrKZub8+AEcPFCjvLZ6a9HmCF8aw/rvVqOZ91YJOxgsPYYmOXJtG
+sYzN48y81w==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-2DES.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-2DES.der
new file mode 100644
index 0000000000..f195c03e3b
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-2DES.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-2DES.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-2DES.pem
new file mode 100644
index 0000000000..d317c53836
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-2DES.pem
@@ -0,0 +1,8 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIHxMBwGCiqGSIb3DQEMAQQwDgQIcCYglgSeP+sCAggABIHQXnZlcc/CDvsT/3aQ
+o2E6AgnJgaq6P2l41yQ6BuomXRSI+KoP+nYWC2fAtb/URgdoNstrflNjTGysSdyl
+CU7A1FnrQkoSvvLElcy25/ttuH9LE4adbhCiKgv2NQXXY/2Lzeeq1e3iqLg7/5wx
+7B2XmgQvMV3EHN1uJWVDKuevOOJ5ULKYONELDaicrlm8IumdhWMvp3ypUrHe6hSD
+i2YYZf8eXfCY0NIRFeXluEgK4MFz/iEkl7aYpNDSA9F7Uk6TC3IRQu3yFs0GR37b
+4fDtpg==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-3DES.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-3DES.der
new file mode 100644
index 0000000000..96b54c3f5d
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-3DES.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-3DES.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-3DES.pem
new file mode 100644
index 0000000000..2fe8300613
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-3DES.pem
@@ -0,0 +1,8 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIHxMBwGCiqGSIb3DQEMAQMwDgQIwZ3Xa+/tptsCAggABIHQmdPeV+Zd96TBIGM+
+kYRNqxckxWbVWE8EBWzJOwjlvrOxhVi3hbSl4QM3cMyNFv0ssyuJiXGQQ7+6/dkp
+UxPWigaSJkemDMtDTQNpHcK/4Ekao+PlAvzgi6wG0lUfL4ioSiEqrE5DlcdfctdR
+Nj9mF4u0rekPWthXhfHcmDxQKSORDi8gYfyQUaV59niKQGIYMsVz4Bu2fwrrTLFn
+NjzyHhYsva2GLAfEWNB13/VtIv4gJaB5mZpzLf81VWe52rR7rZWb3R/rWEz9FFQm
+vrgagw==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-128.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-128.der
new file mode 100644
index 0000000000..7fd85f55db
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-128.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-128.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-128.pem
new file mode 100644
index 0000000000..e9faf30e61
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-128.pem
@@ -0,0 +1,8 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIHxMBwGCiqGSIb3DQEMAQUwDgQIMLBXkL2mR68CAggABIHQkquhoK6Ep0EtnjC7
+V2FbRzYrFSvOakBOGuU6U6p+JeStbTRp4gLQ9hY/8xG7l0GrzM8dlcrO5QnI9Ypk
+zw6a/9FTE+ROpQYGiRjnhdegRguIn6aaCdejfu5s4g09kz/Y6saM1LBkA/hby0m9
+YWB8IFg+/B8qLScjnhn7UOBm4HAW/UywXGH7IFH87ml1g87xlDu88GhcP8iqenco
+TrfPCQDoa+C0EBLV8yTR5aG66kK6BrWXNkyZgUiuhUF1TYmZhZDaiUJ4Er4gMlgA
+C8o6qw==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-40.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-40.der
new file mode 100644
index 0000000000..c0d8b9bb3f
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-40.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-40.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-40.pem
new file mode 100644
index 0000000000..a1d968b912
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-40.pem
@@ -0,0 +1,8 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIHxMBwGCiqGSIb3DQEMAQYwDgQI3y3PINAU1csCAggABIHQEPD8M7YheSdikqwW
+tem/Oz+CZxAXWCBYokpxSeGexFR85Ni2bd/wr8tT4Mv5nNrPLlcNMrKLYCTWryEu
+PtW1XtMp881xmPM9QMgrFRfhiGeVfveEmKZzdGrXN5RRqa20Xa0ufEqaJpvfJHIz
+meWfNkAUtr0RhwK1tMfjxg3CvnSXG1l/cegvUgsc5Nq4VfCOwLYAPY24ltYIZrAp
+JKuc9XkbBx+Uow4kOVpOBTA28giB9gywSbpn1/bCgrm1iBltlrC1bOI2UEYLXAK8
+S8kOew==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-128.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-128.der
new file mode 100644
index 0000000000..59f01c9057
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-128.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-128.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-128.pem
new file mode 100644
index 0000000000..29da203ac1
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-128.pem
@@ -0,0 +1,7 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIHqMBwGCiqGSIb3DQEMAQEwDgQIS1fq1s4wBy4CAggABIHJsEjsk3aow+m3DXPe
+1KCnwl0qXzzh96JCrtAa+2pWytp52+mZphUgnNXYkIoj0rdqJbr1y4/3t73ffVFG
+TU/4401k2QTSKo2mObTxY811fnWImBbNG3BJVmoq8zvJuHrctfVQuKBQb9UFA7RF
+E5WrYwkNXfRxgSsuUgtMvklHyxeAjxdZ0vWennUuPkJIa4XQhIY5gqMiume8dCGl
+mDujTHUPhBjRKifaGQv2hvc8l7FgjUlUY1DcZIl0AapzF3jEXS/Se90FOE2M
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-40.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-40.der
new file mode 100644
index 0000000000..f185d58b51
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-40.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-40.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-40.pem
new file mode 100644
index 0000000000..3dd08fd969
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-40.pem
@@ -0,0 +1,7 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIHqMBwGCiqGSIb3DQEMAQIwDgQICCPn/nJOcwECAggABIHJY1EqBsfnKkOsytQR
+ujblH/MciuYQ5PIkhS+rfEyYvNaQAM4ELbZjBOhqhPxpWgV/nwzl5lbjGHGaBojp
+uH6Tm9L/J/DUVXt5U6i0bmuJ3vUQL9t8WlLwWKEUbszMOJfzgn+q7pr2AViOwcgA
+kL9JD3fTL7KspScIvYo8JD5YomwzDTMyhJFtkvKpjDtBsBkZxvmDRtBnjYYDAvie
+ICGKQ5ojeZD2p2v69ra9bhAOXi/wz+AMotLVWa8myrOb7B+X/b0xEnoOqxKL
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-rc2-hmacWithSHA1.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-rc2-hmacWithSHA1.der
new file mode 100644
index 0000000000..a3d1fa4c9b
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-rc2-hmacWithSHA1.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-rc2-hmacWithSHA1.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-rc2-hmacWithSHA1.pem
new file mode 100644
index 0000000000..9adf8802c3
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-rc2-hmacWithSHA1.pem
@@ -0,0 +1,9 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBHTBIBgkqhkiG9w0BBQ0wOzAeBgkqhkiG9w0BBQwwEQQI7hWoVS10HvICAggA
+AgEQMBkGCCqGSIb3DQMCMA0CAToECLPHM3qUvtYPBIHQl36zBfnW7J89+Kl+tLa4
+rm9Iu8KpMNJm2bnuLptltF/e5Vyp92xRvuCoaAVQka0dq4jKOVOkruMfHHHOf22g
+mxpwtJfYvKqqjW2KH2FE0Y3l1XPV6o4Of5FbhvcULDmNtCoFlme0hoAoHm1kUUzS
+Ed4CJqc6VpYpHGCv8X6k+0j274XnPqRJaY8KizrD0+/i6vS/nu/srxLqt9COT9nS
+tVTQL/CRmmXf8/jSdVLDMKjjboFU1FtVZnOq4yAAuJiBZFtfmIF5+EI1dbXMbMdF
+MA==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-rc2-hmacWithSHA256.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-rc2-hmacWithSHA256.der
new file mode 100644
index 0000000000..398d47b4c4
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-rc2-hmacWithSHA256.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-rc2-hmacWithSHA256.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-rc2-hmacWithSHA256.pem
new file mode 100644
index 0000000000..de0d9179a2
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8-rc2-hmacWithSHA256.pem
@@ -0,0 +1,9 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBKzBWBgkqhkiG9w0BBQ0wSTAsBgkqhkiG9w0BBQwwHwQIysmtT0sgtmsCAggA
+AgEQMAwGCCqGSIb3DQIJBQAwGQYIKoZIhvcNAwIwDQIBOgQI3Lf5sOaUEmsEgdDE
+0UkzkZdDMLBn9gGk9plFNb+2QKT2l0M1byplj92l8+eSv9stLTSf3v9STP7c/plJ
+PMj4RUym4W7URvFhIEicyLDYNL7nD9JELC2i7E6S3NaSAZVeOxSl4gxEVtOPC00i
+Dy/AISKSeNNBJkdUwT+m7as8Uc4+M1eitfMBQFUjRWQONpzw/2NtIeqI14VKPAM0
+1kVQTsO7TLEAwj7Jd1iscGakz+Ib7zMl1pCbVHrlh6nHrKvF+gvMDw5eC952CbpD
+XCcPq3tU2j6KGGzK3ksd
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8.der
new file mode 100644
index 0000000000..ecd0670072
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8.pem
new file mode 100644
index 0000000000..a6f6f734eb
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512-pkcs8.pem
@@ -0,0 +1,7 @@
+-----BEGIN PRIVATE KEY-----
+MIHIAgEAMIGpBgcqhkjOOAQBMIGdAkEA+7WshnhYKUIf+71hYgDUGQcSk2JxzOw6
+rpKt3fkIafnkm6KnXeTIPrWlSLAhtHpsCX56HDzYu69BRyVjuYiFxwIVAJljwa1Y
+uxEZ/+w73/UFLgvb0juZAkEAhk+R4vDxKY6w78hLyCfhSwnT4L3BWn6pINaAM4NU
+lVzsYP6ye4R9vCvc2h+254GszhsjvKrCzl1RDI3UyJenAgQXAhUAl95kGzNYPVm5
+Y+2jpGA9N2PkcCU=
+-----END PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-MD5-DES.der b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-MD5-DES.der
new file mode 100644
index 0000000000..7af45943cb
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-MD5-DES.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-MD5-DES.pem b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-MD5-DES.pem
new file mode 100644
index 0000000000..91874a9b29
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-MD5-DES.pem
@@ -0,0 +1,6 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIGgMBsGCSqGSIb3DQEFAzAOBAihGk2iurZE8wICCAAEgYCaneaK9dlMsDGD11jl
+F5etfmvAbUbpzVmooM4ORHweCnP/DiwJVyQ02dU3PlB0teLCG6DyJCl6CaOhZjRc
+cDE4fYIBBVtLlcqwr8oc73DWi3azJ+/KdkuUQyHZEkzNo9Thi1owDI6XMlWbFZwd
+wSlfuk9AghDAN8/n3iMu87veSQ==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-MD5-RC2-64.der b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-MD5-RC2-64.der
new file mode 100644
index 0000000000..14bb01d10d
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-MD5-RC2-64.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-MD5-RC2-64.pem b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-MD5-RC2-64.pem
new file mode 100644
index 0000000000..30b186b796
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-MD5-RC2-64.pem
@@ -0,0 +1,6 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIGgMBsGCSqGSIb3DQEFBjAOBAgQKZdqJ6i7cQICCAAEgYCfJQJakYch640S/EA0
+tLuO7xxLgeI9gxeooy0GM9FeHiDencz9BXJrFFpXLs8J5IgVuj2zjfMDOuf/3zCa
+gn1itwByKWPLXHx5vRUAT5zds2F3uBo7RCQj+FlR3xv4Xuqwx34qfYJpafORpi7/
+eO6M4V2BnAkws1b5UK0WDjFfSQ==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-SHA1-DES.der b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-SHA1-DES.der
new file mode 100644
index 0000000000..689780f8a1
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-SHA1-DES.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-SHA1-DES.pem b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-SHA1-DES.pem
new file mode 100644
index 0000000000..1f737d9803
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-SHA1-DES.pem
@@ -0,0 +1,6 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIGgMBsGCSqGSIb3DQEFCjAOBAjruvWW+JZt7wICCAAEgYAgvrADpBoAMNrS8uYX
+9FTnHUsGr5Sg3e2ueEwMUGsnGliJJTa58r9634RffN6uyB8jBihCdQw5iBbzLkC2
+ltEVcOR8pNQvprGXX4X/jwOY4RhyKrb89YdZ2BZ4orzY5cL+6nGYQKEm3WlrXW+a
+Ncq6UvRpVmHqQ0OW+zuCbi5/nA==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-SHA1-RC2-64.der b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-SHA1-RC2-64.der
new file mode 100644
index 0000000000..a06790a254
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-SHA1-RC2-64.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-SHA1-RC2-64.pem b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-SHA1-RC2-64.pem
new file mode 100644
index 0000000000..814c341760
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-PBE-SHA1-RC2-64.pem
@@ -0,0 +1,6 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIGgMBsGCSqGSIb3DQEFCzAOBAg95ivo7up6egICCAAEgYDAMawlX0a61+iLgab0
+Zi62Ef7g0Jdj0KG4NeKmWrmuCXI3HBiAVv878vWkL8cMx5DqhBDw8A14aOxCkIm9
+uZ5twNwunINclMQtYxL7mtQLjUr50sFFY/Dd2PH669Qb6dqZC6efO7y31n93+fUI
+gyntTIXfeuUSg8uw/qG9Vfa6oQ==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes128-hmacWithSHA1.der b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes128-hmacWithSHA1.der
new file mode 100644
index 0000000000..fe071489cb
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes128-hmacWithSHA1.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes128-hmacWithSHA1.pem b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes128-hmacWithSHA1.pem
new file mode 100644
index 0000000000..d7c41b121d
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes128-hmacWithSHA1.pem
@@ -0,0 +1,7 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIHOMEkGCSqGSIb3DQEFDTA8MBsGCSqGSIb3DQEFDDAOBAhC3xITYW8eRQICCAAw
+HQYJYIZIAWUDBAECBBDUQa3ddOnliyQ/qIYEFmK2BIGASDcmbEFHEwmV9uJzQEI4
+hfZTOVaR0lYHCTTnJjEsbM8oyvVvMxJkefNqPVkBF1Oc4nHaN6LEPIZRpHYJxjDH
+tk7RFlcvSlS2Dcv41y+2Bcj1dMtocXM1t6jxo5nioeBnHCUQr3VsDT9+eJvithY9
+UyUqUt+P5f1H1LCpqD3BYcc=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes128-hmacWithSHA256.der b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes128-hmacWithSHA256.der
new file mode 100644
index 0000000000..62113a1e6b
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes128-hmacWithSHA256.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes128-hmacWithSHA256.pem b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes128-hmacWithSHA256.pem
new file mode 100644
index 0000000000..83e58214fb
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes128-hmacWithSHA256.pem
@@ -0,0 +1,7 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIHcMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAjv/NQpQZwZbgICCAAw
+DAYIKoZIhvcNAgkFADAdBglghkgBZQMEAQIEEPMGCKos4+H6cwxOhDR8UbQEgYC6
+01v9qHJnnFkHBbQ7L4xpWY3RVHTalKfCfLQErqwPx1akV7BPdCZmjd4rAdIGLImy
+kaaAPVrJ3GVjF6fW+E9UIGoDEbFeZ1hlnTzhOTqUwGiBrCM0SY3XDyBxSdqv/Pk/
+M4Ibk/lDycV/kWm26j2I9OYPxedj4vdPgXPxEi7FeQ==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes256-hmacWithSHA1.der b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes256-hmacWithSHA1.der
new file mode 100644
index 0000000000..232a6cf2cd
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes256-hmacWithSHA1.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes256-hmacWithSHA1.pem b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes256-hmacWithSHA1.pem
new file mode 100644
index 0000000000..294278ea44
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes256-hmacWithSHA1.pem
@@ -0,0 +1,7 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIHOMEkGCSqGSIb3DQEFDTA8MBsGCSqGSIb3DQEFDDAOBAgYx6Cuor4IHQICCAAw
+HQYJYIZIAWUDBAEqBBDc1FODsp0BBJI/EOjU/nA1BIGAUIe6lzmR2cWVQUAW6gF8
+UdykIWS5E4AnbPtaiVdFNmhyjtUq10gf67jX3/hfA3QXwDCTT1aot+5Vjrb57M8S
+hjxrs871w0UvzBmrTLJA2/BWPz5gni72fj1N5JGYUKI4MFKHGhv53iUzW/E8KiRW
+ab4KY+hUF9zFcXOBwOGvG7E=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes256-hmacWithSHA256.der b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes256-hmacWithSHA256.der
new file mode 100644
index 0000000000..0f4075965a
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes256-hmacWithSHA256.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes256-hmacWithSHA256.pem b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes256-hmacWithSHA256.pem
new file mode 100644
index 0000000000..90ab751415
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-aes256-hmacWithSHA256.pem
@@ -0,0 +1,7 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIHcMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAg+0vyp4rA5hgICCAAw
+DAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEDlKgIIcdKfiQcsZLfQt97cEgYAD
+TrjldhQKT8SjAnmChT/knsUeJzThLxKpdpRwbr8qYTZbCmngbb2oYBkrNzAwGoVM
++cj+6p3EgP7T/zjJYj7EArRvs7FM0spxqre2bQY3GG5E3PDGyR/h4nwdVTzorqNw
+/35Dtl8ifbnVI4SCwTtifnCDsz9TjIXszixrCm354g==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-des3-hmacWithSHA1.der b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-des3-hmacWithSHA1.der
new file mode 100644
index 0000000000..669cb1f9cc
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-des3-hmacWithSHA1.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-des3-hmacWithSHA1.pem b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-des3-hmacWithSHA1.pem
new file mode 100644
index 0000000000..233dd94a18
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-des3-hmacWithSHA1.pem
@@ -0,0 +1,7 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIHFMEAGCSqGSIb3DQEFDTAzMBsGCSqGSIb3DQEFDDAOBAjU9TMJNWzzUAICCAAw
+FAYIKoZIhvcNAwcECEd8I4R+1rlZBIGABNupNKmIR5j2lAyQAbDjXX2PtpOGH0+k
+KXnS7i6rmseQFjwDiF+xMefhj9ZamEgypDjyWaYz/EwV7dP0dUzZuQpzGsN/JLZS
+i1IhRV9sVABs4SbCn/KZsy8bLW/7/3e5qloRkXskB6dR4nVrq4kz1qMmQVO+9Ojo
+Td+SUeCdhd0=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-des3-hmacWithSHA256.der b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-des3-hmacWithSHA256.der
new file mode 100644
index 0000000000..9f444d6350
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-des3-hmacWithSHA256.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-des3-hmacWithSHA256.pem b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-des3-hmacWithSHA256.pem
new file mode 100644
index 0000000000..29f17933bd
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-des3-hmacWithSHA256.pem
@@ -0,0 +1,7 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIHTME4GCSqGSIb3DQEFDTBBMCkGCSqGSIb3DQEFDDAcBAgf2AMm0URGvQICCAAw
+DAYIKoZIhvcNAgkFADAUBggqhkiG9w0DBwQI/4fa6rbvznsEgYBImRLhwGbEgcLm
++yHcsohX1uQyqPfP8PVHGtM6ITaAJ16djxQKfXRoffS4DSTnhFgHnXm42V7epgJO
+ZHRe0dVbKynbp1ZCnNIXsvsgyP4ghfw70j2u+45fiBK2ZqhVaQns/1t02eIa7Kud
+308ffy9xR8xbCV9H1hu978sWDPRgmA==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-2DES.der b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-2DES.der
new file mode 100644
index 0000000000..e7939899c8
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-2DES.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-2DES.pem b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-2DES.pem
new file mode 100644
index 0000000000..eba00a5597
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-2DES.pem
@@ -0,0 +1,6 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIGhMBwGCiqGSIb3DQEMAQQwDgQIASNN5nArudcCAggABIGAsi5Ta25v+vkS7qc0
+b10/Hv1H2SVhhOA4iYMdjB2XgpRFXBduYIFfROdAT8pJvspZ2EIJGu975H+SKeJ3
+ndULrOFmaDknlsAyVW8HslnOiuQVpNE0vTWWJYVg1xq9Hwg5YU7C1PsCMy8f5g4O
+gbsHxVy7AGF2FSrJqy2PVdoEADI=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-3DES.der b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-3DES.der
new file mode 100644
index 0000000000..9dd3f9d42c
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-3DES.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-3DES.pem b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-3DES.pem
new file mode 100644
index 0000000000..01f62cf5f2
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-3DES.pem
@@ -0,0 +1,6 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIGhMBwGCiqGSIb3DQEMAQMwDgQINArkfLom3CoCAggABIGAaqrWHE+VgTLr/TQk
+x86KYu88/eiO5jxGUxbFwUCOtTbw8g40MY4tuXNhhm9lQ5zVSrC7fdjagqr6Flz5
+YV8NWpURbA4CKXgX+JKUMzZclHUwfe/M/CI5tKIU8vu7O2jl8gL5mOAFagLmFUld
+iS5+KYtWvuOy1jQd9Cn4pOrF0yA=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC2-128.der b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC2-128.der
new file mode 100644
index 0000000000..2f1148d1ea
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC2-128.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC2-128.pem b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC2-128.pem
new file mode 100644
index 0000000000..fdddcfb02c
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC2-128.pem
@@ -0,0 +1,6 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIGhMBwGCiqGSIb3DQEMAQUwDgQIBOJoKaHoCH8CAggABIGA5ekhEhokinZUh8Su
+FU9XT9TmpJI6+uSUnV6dCI5F7jxUC4BKYUDLQ/wjassasP/z7NYgIUFXiSsx8+u9
+rIOd83qJly/QL3MI8HA/gwrUOK1mcQCdHM7WcDxgTDfA8iXvE7ipxkqWWh+vjWVg
+QIBy+Mik4f8m6qRJtHvkn1+QVUQ=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC2-40.der b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC2-40.der
new file mode 100644
index 0000000000..f8a47e1127
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC2-40.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC2-40.pem b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC2-40.pem
new file mode 100644
index 0000000000..368b1d9fd7
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC2-40.pem
@@ -0,0 +1,6 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIGhMBwGCiqGSIb3DQEMAQYwDgQIYoqh4a7jy44CAggABIGAhOjw9xEXhMSaBJM6
+Opu29QK4+h7/RJJ+NcrzFBPV5p6t0bjqONRxdq8LwXA5nimlUq3ZbRqjhu0BCKh5
++jvfjs0R9qD2cAv3QXjk6eh2YEx+wuDbc50SSL1Y826sLD06V4KThrQwfaLHE7r1
+mjx5N5Jg5rPFdTGe4umThyGlGPo=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC4-128.der b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC4-128.der
new file mode 100644
index 0000000000..a2e71ed488
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC4-128.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC4-128.pem b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC4-128.pem
new file mode 100644
index 0000000000..91c71a3df0
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC4-128.pem
@@ -0,0 +1,6 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIGaMBwGCiqGSIb3DQEMAQEwDgQIvutMegO9IYICAggABHoRfn/sZK/NRxF7jwF2
++/0zh3Y/8cCm4xeGaCP7NOcJoJXOisXXxT05tgQEa5mfymOFK1PYjnHHVVLGs6CQ
+TDPI2kb6XteXjkzR8Q0WQUtLSgAQ9/uEMmr43jAabaw+qnIcJrjaTt3rlbezZioR
+Q3xbb38W5QBFcUIpCg==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC4-40.der b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC4-40.der
new file mode 100644
index 0000000000..cf6373b642
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC4-40.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC4-40.pem b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC4-40.pem
new file mode 100644
index 0000000000..cc5ec63996
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-pkcs12-PBE-SHA1-RC4-40.pem
@@ -0,0 +1,6 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIGaMBwGCiqGSIb3DQEMAQIwDgQIGgo8eWJg23YCAggABHp/EXYSQmp35zzgLl8l
+paNqOjR3Ku19rhrN9QiW1dagTztFuqzezlZC7WjbycWz9qRZeQFLLAEi/DIipIAf
+sLsnbtfBypqcUCoO2AysmI31hPSaXSsHDH4cJ5LH+1DK6KVeQoVGJw/xTvrmaBD8
+lD9zOO313VgMIGe7wg==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-rc2-hmacWithSHA1.der b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-rc2-hmacWithSHA1.der
new file mode 100644
index 0000000000..be137430e6
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-rc2-hmacWithSHA1.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-rc2-hmacWithSHA1.pem b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-rc2-hmacWithSHA1.pem
new file mode 100644
index 0000000000..b52d270e42
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-rc2-hmacWithSHA1.pem
@@ -0,0 +1,7 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIHNMEgGCSqGSIb3DQEFDTA7MB4GCSqGSIb3DQEFDDARBAjwbKdmEddIYQICCAAC
+ARAwGQYIKoZIhvcNAwIwDQIBOgQIvopesgNCATUEgYDQ7uOTZ+cUnxDAVh3z845L
+QyZ2KkSbna0NmiKZGy9e1kh5iAQ1RhZ2iKaTTyGlpCi4i2mlZo3gvJbEHp+Do2vc
+nq9g57AP6dU9+1LsLsTeVFbdJ7OymlcwUoSfF723g9IGlQa0D5K4RTR3y34lHMNC
+NmrOwaAH4DPKDyC5EWYV0Q==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-rc2-hmacWithSHA256.der b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-rc2-hmacWithSHA256.der
new file mode 100644
index 0000000000..fecff8a2bd
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-rc2-hmacWithSHA256.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-rc2-hmacWithSHA256.pem b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-rc2-hmacWithSHA256.pem
new file mode 100644
index 0000000000..67931bbbac
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8-rc2-hmacWithSHA256.pem
@@ -0,0 +1,7 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIHbMFYGCSqGSIb3DQEFDTBJMCwGCSqGSIb3DQEFDDAfBAhdjCzod22WFQICCAAC
+ARAwDAYIKoZIhvcNAgkFADAZBggqhkiG9w0DAjANAgE6BAj2j6TpIIho6QSBgK4/
+Kgspc57C+rWNbf3c0+o/bJ7ga3tTfq0iw8TYqZ8jV9+FZGjS4NVvh9EK8+L6f2w1
+NuyiGbKfsq7Lf1O1dlHNu2TagxYAWbJUwzoy0uUkfpRnfe5M/dl/l5Gx0cR4y9SH
+yKOhuX3YxUvOtkwxEb6iyNg8vaq0yRG/1F5O2jI3
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8.der b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8.der
new file mode 100644
index 0000000000..c8e51cc01b
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8.pem b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8.pem
new file mode 100644
index 0000000000..741f007304
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/ec-pri-224-secp224r1-pkcs8.pem
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MHgCAQAwEAYHKoZIzj0CAQYFK4EEACEEYTBfAgEBBBxr31AB6pNVnFUfX9rNKpZc
+Ps+RbUj5PYdpHLtIoTwDOgAEg7Qj4reRDs3ot/r/rp2orzU/g07BIYsZCsLLrf8j
+8wq50FHUIdwDRZEfpfGBPBXGgd/9DS9T7hU=
+-----END PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/genkeys.sh b/tests/auto/network/ssl/qsslkey/keys/genkeys.sh
index 7fb15e91ee..6210b42ab4 100755
--- a/tests/auto/network/ssl/qsslkey/keys/genkeys.sh
+++ b/tests/auto/network/ssl/qsslkey/keys/genkeys.sh
@@ -87,3 +87,58 @@ do
echo -e "\ngenerating EC public key to DER file ..."
openssl ec -in ec-pri-$size-$curve.pem -pubout -out ec-pub-$size-$curve.der -outform DER
done
+
+#--- PKCS#8 ------------------------------------------------------------------------
+# Note: We'll just grab some of the keys generated earlier and convert those
+# https://www.openssl.org/docs/manmaster/man1/pkcs8.html#PKCS-5-v1.5-and-PKCS-12-algorithms
+echo -e "\ngenerating unencrypted PKCS#8-format RSA PEM file ..."
+openssl pkcs8 -topk8 -nocrypt -in rsa-pri-512.pem -out rsa-pri-512-pkcs8.pem
+echo -e "\ngenerating unencrypted PKCS#8-format RSA DER file ..."
+openssl pkcs8 -topk8 -nocrypt -in rsa-pri-512.pem -outform DER -out rsa-pri-512-pkcs8.der
+
+echo -e "\ngenerating unencrypted PKCS#8-format DSA PEM file ..."
+openssl pkcs8 -topk8 -nocrypt -in dsa-pri-512.pem -out dsa-pri-512-pkcs8.pem
+echo -e "\ngenerating unencrypted PKCS#8-format DSA DER file ..."
+openssl pkcs8 -topk8 -nocrypt -in dsa-pri-512.pem -outform DER -out dsa-pri-512-pkcs8.der
+
+echo -e "\ngenerating unencrypted PKCS#8-format EC PEM file ..."
+openssl pkcs8 -topk8 -nocrypt -in ec-pri-224-secp224r1.pem -out ec-pri-224-secp224r1-pkcs8.pem
+echo -e "\ngenerating unencrypted PKCS#8-format EC DER file ..."
+openssl pkcs8 -topk8 -nocrypt -in ec-pri-224-secp224r1.pem -outform DER -out ec-pri-224-secp224r1-pkcs8.der
+
+for pkey in rsa-pri-512 dsa-pri-512 ec-pri-224-secp224r1
+do
+ pkeystem=`echo "$pkey" | cut -d- -f 1`
+ # List: https://www.openssl.org/docs/manmaster/man1/pkcs8.html#PKCS-5-v1.5-and-PKCS-12-algorithms
+ # These are technically supported, but fail to generate. Probably because MD2 is deprecated/removed
+ # PBE-MD2-DES PBE-MD2-RC2-64
+ for algorithm in PBE-MD5-DES PBE-SHA1-RC2-64 PBE-MD5-RC2-64 PBE-SHA1-DES
+ do
+ echo -e "\ngenerating encrypted PKCS#8-format (v1) PEM-encoded $pkeystem key using $algorithm ..."
+ openssl pkcs8 -topk8 -in $pkey.pem -v1 $algorithm -out $pkey-pkcs8-$algorithm.pem -passout pass:1234
+
+ echo -e "\ngenerating encrypted PKCS#8-format (v1) DER-encoded $pkeystem key using $algorithm ..."
+ openssl pkcs8 -topk8 -in $pkey.pem -v1 $algorithm -outform DER -out $pkey-pkcs8-$algorithm.der -passout pass:1234
+ done
+
+ for algorithm in PBE-SHA1-RC4-128 PBE-SHA1-RC4-40 PBE-SHA1-3DES PBE-SHA1-2DES PBE-SHA1-RC2-128 PBE-SHA1-RC2-40
+ do
+ echo -e "\ngenerating encrypted PKCS#8-format (v1 PKCS#12) PEM-encoded $pkeystem key using $algorithm ..."
+ openssl pkcs8 -topk8 -in $pkey.pem -v1 $algorithm -out $pkey-pkcs8-pkcs12-$algorithm.pem -passout pass:1234
+
+ echo -e "\ngenerating encrypted PKCS#8-format (v1 PKCS#12) DER-encoded $pkeystem key using $algorithm ..."
+ openssl pkcs8 -topk8 -in $pkey.pem -v1 $algorithm -outform DER -out $pkey-pkcs8-pkcs12-$algorithm.der -passout pass:1234
+ done
+
+ for algorithm in des3 aes128 aes256 rc2
+ do
+ for prf in hmacWithSHA1 hmacWithSHA256
+ do
+ echo -e "\ngenerating encrypted PKCS#8-format (v2) PEM-encoded $pkeystem key using $algorithm and $prf ..."
+ openssl pkcs8 -topk8 -in $pkey.pem -v2 $algorithm -v2prf $prf -out $pkey-pkcs8-$algorithm-$prf.pem -passout pass:1234
+
+ echo -e "\ngenerating encrypted PKCS#8-format (v2) DER-encoded $pkeystem key using $algorithm and $prf ..."
+ openssl pkcs8 -topk8 -in $pkey.pem -v2 $algorithm -v2prf $prf -outform DER -out $pkey-pkcs8-$algorithm-$prf.der -passout pass:1234
+ done
+ done
+done
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-MD5-DES.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-MD5-DES.der
new file mode 100644
index 0000000000..293001c629
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-MD5-DES.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-MD5-DES.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-MD5-DES.pem
new file mode 100644
index 0000000000..e9aa918a11
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-MD5-DES.pem
@@ -0,0 +1,11 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBgTAbBgkqhkiG9w0BBQMwDgQIbdPEAuKuoSgCAggABIIBYAo3BSb8H60g9eyM
+2QajPdxRT5RJBQeSmlYCG4NEhiXYCXkGx2btS20w7yeX2ESqKPTSTMTB6XY1o44x
+DLnDF2FEjvrk89ADZraMaOKnUxcZiawXOi9chNf+S6PclRC+ZRMRfbCxTnqb6y8q
+42aD4oMmHv48f+/27/kFVwj4o/5ls6Hfwc6/YpXZXfT/8hIrkVaPd8QErhY+pAau
+H/ObrYXu7Hm1deBLdZD1+u19yFv/uGRg7E7S7/Ku2GSe0i9DpYlYpsz1lydubAp1
+RfxAARfMjEoo0gwUfGCvP6drh16fnLcu9GnxuPKacUTCRd3Pk6hm59TXdcLtXB+W
+tzQ/TpPY4u0oL2NU/aF9jqZuDWW89TAjvwekYpqrtq5cbU4VHpFLLc2yO1n4flRm
+pfHP4BXjW8D9frPMyLiOSJAdKoJnHfM4y9bG8SHbukmTaJCOUD2MJ5uXW8pVejxU
+gnYbceU=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-MD5-RC2-64.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-MD5-RC2-64.der
new file mode 100644
index 0000000000..3bb492bc5e
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-MD5-RC2-64.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-MD5-RC2-64.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-MD5-RC2-64.pem
new file mode 100644
index 0000000000..08115431df
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-MD5-RC2-64.pem
@@ -0,0 +1,11 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBgTAbBgkqhkiG9w0BBQYwDgQIHQKYle7B6TECAggABIIBYP7M3ZLd+cmLd7HG
+avwLJdK7dq1hUxdpDMYIIHXQMqR7yhrr271v6Sqlkq8i97CrdlmzWgWNiv8uok88
+z9CxT79Y6/sLcvKVfCkoI7Z/p86Pc2/P7otvhoc9GlRNIvU8r/nMtigf3FZDQWrp
+3XmBSabIERSQZxNwVjmSQzAVFd+SgfcqrNpKD0kErrphcySF7M4SfyTm3/dfFbrO
+gUdg0ULs0rbKbTpYyBgVhrdCXYFAQLajHlE6UVIAK21Ifq2EvJ3LQDUEXg6RADbf
+s2easyTlKfssoRzTDkBo60J2OsgmS5ls7fxOBndjxMZYPJI55k/ct4FPJraXPIsj
+j5iBIOJBdW7Fi42O/ezaLtSFC/TUwZf+rgsVQaqpz67ynp3V7K/wJqdR0P3WmO3T
+XkL3quUX+GFtm1htiqT9EGX6c1UZFfqmTJ3juLP4YpgOgUVLSIrOPauk2txH9E/R
+JATHbjg=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-SHA1-DES.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-SHA1-DES.der
new file mode 100644
index 0000000000..82e2f79cd8
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-SHA1-DES.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-SHA1-DES.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-SHA1-DES.pem
new file mode 100644
index 0000000000..82b997804a
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-SHA1-DES.pem
@@ -0,0 +1,11 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBgTAbBgkqhkiG9w0BBQowDgQIQPSp44KDjkUCAggABIIBYLdDgiRyUnAkUhLW
+pqaNMqrK0iaSKpwHvsw1S4PhOQdFclVUEZKs+2oBedtrr3VysWRg/ZKNBdBAnzLi
+E3nw7RubL4WH2y3QNx6eLsMJsI1thF9pK0yWWfy+zQP3+oZVG+JTmctCLQDAToCa
+1OoRGnaHrZxcGzg/B1yI2hRSDdcuFCelMTIG4fGJ3dyrQHR/Gyxr4m27kV25H4t2
+Vxc6DSb1qWmSgauvUKLMlnvqtFVJ/OxjTz3BWPKUJqOyDd80PdfX8t5ttdK9Ebca
+DwIUHvAmblES9mknhUwJUym/JGQFd3GXPc7WNyTsqwV4x9xp/8WTmJvM8qPk8fNz
+x5kj3+VZgcAIh0ePKdF0TBAaAz5nKg611UwIOI/ShdMeyc1B3iWA71Y+uPElPEf+
+6+Zp8DwJNaOZ1SEqfNyB6aNMuYlTmbwctEKjokaIvyakSI6nFs63ycq5/s+HrMHT
+KHF9A4Q=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-SHA1-RC2-64.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-SHA1-RC2-64.der
new file mode 100644
index 0000000000..ea6b0d6134
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-SHA1-RC2-64.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-SHA1-RC2-64.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-SHA1-RC2-64.pem
new file mode 100644
index 0000000000..14edbd1f09
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-PBE-SHA1-RC2-64.pem
@@ -0,0 +1,11 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBgTAbBgkqhkiG9w0BBQswDgQI+m9oVxROlkYCAggABIIBYBRYVJdSaW3fR2zh
+t/s5PFJ+9ebZUxhSRoc7lxk5LU76xJIH6EUa5k2sPH2WnWfu/V0Hi6t7FC0wkPLZ
+QUNcr8VPESfjDkzqmU9H+37mfrUG63P5hGgyoWzMEaok2uFfjt1e1XVfVLe8P1Z+
+zxy4+BNoLzWQ/Wb/gTwVVc0kkttmjUiRIqSQLCEh8ntWF2ws0JS+ihiR9NUdPdEe
+niQWskeAxWvO758m6kfTQeRY7WnVWPaqoosH1+uC8UZ2TmuWqTxJlHTvqEJzjPTK
+n7EzwIFHhZVJ+p+IT/6SvwL5i1h0dtlNwOfTlcU6W//U76cYmwwtrzjwVsKJNbBw
+vuPboJ2asZSzXa8887zI8O3+5ClkTCvJpk46QJHuNTQhJc1/R7aXgWbpiGu8CBCo
+PNB1OEbs+lTU8DYp8cIxdc/aTKnSxPm4d73jCaOEJ1Sj4tA97rPQVEFu0w/HLtP+
+6MxHjI0=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes128-hmacWithSHA1.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes128-hmacWithSHA1.der
new file mode 100644
index 0000000000..a42fb92161
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes128-hmacWithSHA1.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes128-hmacWithSHA1.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes128-hmacWithSHA1.pem
new file mode 100644
index 0000000000..11b1032852
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes128-hmacWithSHA1.pem
@@ -0,0 +1,12 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBrzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQINZqXAZw29eMCAggA
+MB0GCWCGSAFlAwQBAgQQMN7uviOQj5Hdt8Zb9sCtrQSCAWCsMtmLiGbnaleRuRh5
+mRWDqJ0PYXNaaTwQ24WKjl8dquPPJZz0QU2hDZGtuhBL90A2lqvG9oHJmFBpMg4E
+RPHS33R04BtCTdpfCUziKcBomHbrh8ttQ/Y1UA9OgSgob3GQIDxwNS+0p0wApyWC
+InPBE4DXByp9o1lQxNZj2wkmWLfkXCT75aMxevM30lf33SOCXDPTvtHlz/YcB6Yh
+i/b31YUAEOilXaqaCu427BMPKCanshJAjX3wwOROQ+yh8R8HiSPu+x55gJlU+yCn
+9S/oNwtTMimpI21cZTUIOkIRYyKJhgvUxjlQ0CjcMOjJvDms2rRgNhD6IFZrXoks
+FRF/Z9pUH0n/m3208uckyPkilwoFNoYLec0lq1SdtBq2LOBV0hgCmR0J0Fokpo/p
+8T/rzlb48JowOfZLnLqMtC6uqccQWmiEY3691exhFf5muUYsd8uOVkeWgMTfVnua
+jwVr
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes128-hmacWithSHA256.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes128-hmacWithSHA256.der
new file mode 100644
index 0000000000..74b870d490
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes128-hmacWithSHA256.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes128-hmacWithSHA256.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes128-hmacWithSHA256.pem
new file mode 100644
index 0000000000..371448ae69
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes128-hmacWithSHA256.pem
@@ -0,0 +1,12 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBvTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIadJLdxsx0GsCAggA
+MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAECBBDc7IW9CVmuaaYtM4KFXpsUBIIB
+YC1qJ4WQa6f2uxeaojvzpgYHmrh4gR9gXa2cNwCNQir557amVsPqiXEiSYmqrCy/
+Y9tN5ubLxu3z5TtscC1Y9bqP8oY3bQj+AleqzmywVI7dJhwGoTaM9lD574cknKVo
+Fn5oe6a4dTTg8wxcic+zWFc5EPi3g3swu3jqmjrLaOM8gd0RlWkAFmM60F8LX9G1
+mxnNZXHcRmkpugpICwaNYhROlzVfvLQvqtlJNccGc6QvYq/zY0nX6R3ISkbW/Bzn
+kadVaA4hNrao9RA9TT61v4H95+BGF6CLDTyU1z3jtaEvm4ihygeA5mS/pjBd7lAi
+V9YCNazgfMlgNv1ynwU67e8to89SFvzrv2sjUEDEAx1cN6zLGl42dz7ZDk1ytmsO
+grVc9vON+HhwrVIZiu8bMjj4lSD6E1XqsffpNzEhOAy2INp9ArvakCVP4mE06dv4
+4LHAAqaYj8jIHSBDPYw3F7w=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes256-hmacWithSHA1.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes256-hmacWithSHA1.der
new file mode 100644
index 0000000000..112aca5d9f
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes256-hmacWithSHA1.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes256-hmacWithSHA1.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes256-hmacWithSHA1.pem
new file mode 100644
index 0000000000..74aa2eb50a
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes256-hmacWithSHA1.pem
@@ -0,0 +1,12 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBrzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQILWdaWkH3cTMCAggA
+MB0GCWCGSAFlAwQBKgQQSj7y41B6JDjCn6mV9g3/EgSCAWBipZOOZk5C6IuwElK6
+1aGy8r4cmh6hbJ+IJIj5pNphE3IeLXfBQAUzJCD2wKKzgkL4bofdZYndIGqdBU/1
+0P27kCYKDIN0iixPr+gW6N0yEmD+R0v8fUFyQF+RiiZ0lCznAmKhc5d8C5r4zE5y
+QN4E6RTAoiaTGM85jEpb2qP0Ju/2lhFJ85z0Dn2xXtH/y4O2UYQklufYpPxDX9xQ
+DdgDPgdBXj7nH2a165CqFhA5b9PXCVjzSG8+u/PlWkO0UOCobL7YTlg0z88iAkWx
+VWX6DG7UJovp8boqJ6CL8AeroSKDsNRzO5inROWeanj8t00vsSadXUtKTlFRBSaM
+1Gzn81X5EZnhPzCkrmOmmK8+DZwgncRhLk6voFBfga9lSt9PZaDNEeNrVLixQvbc
+fc5nAIp4SwkFbo/n11YRjHyBZsYqm1ugQIaEW0jGsQxGxKAzeN342emBm0KHBqr6
+liGH
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes256-hmacWithSHA256.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes256-hmacWithSHA256.der
new file mode 100644
index 0000000000..45ebba1975
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes256-hmacWithSHA256.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes256-hmacWithSHA256.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes256-hmacWithSHA256.pem
new file mode 100644
index 0000000000..ecf4acf311
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-aes256-hmacWithSHA256.pem
@@ -0,0 +1,12 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBvTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQINZe2ZZmkA6ECAggA
+MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBBrqs2JUotuTr374kCzYAyoBIIB
+YDqyE1zTjItA+UhQ2jZ53NnaTCWTccqSVtb11jizZCOSvVEN0vayyr2OoQKsOw1y
+Uane3niV4MX8H98u5Vz+ijHuebBTiSbtSAlEqeeWTtzNfsQa4PN633n4ov1Ybn2+
+ZiW2n5d3cbC+bqPGs5cjTA6GPxLsojx6ZZEQBAyiUZ8Ikn2UsLxBV7RMiS1MK+wg
+1cvtOzDuA1SbAtLbv4GOFTYrZZrzrmtIJvxD9C0Nlsa4ci9PkVclE/tzTQxqHOq6
+DLC7LErqrWfZI3KNlw4c33CV3VaXiB1dFHcTohlYhYbrJZPz6wiKN5c1IxxD0fj8
+2BseKG3iV3jrp0yt9zSgquJL3OOAHk1rG4zvjQySJ29SVEH0TyvsLSPiV87U5u64
+rpHC8yRNz3ut//ZVPQKnz/dftFw5b80vXT2UT0BZQTzj4HHDkIBKDc8USteag91O
+SBmhwK5Vuuph6o8ILY3YoUA=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-des3-hmacWithSHA1.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-des3-hmacWithSHA1.der
new file mode 100644
index 0000000000..4f07e0cb50
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-des3-hmacWithSHA1.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-des3-hmacWithSHA1.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-des3-hmacWithSHA1.pem
new file mode 100644
index 0000000000..8040f68152
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-des3-hmacWithSHA1.pem
@@ -0,0 +1,11 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBpjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIjA3V6epUyL4CAggA
+MBQGCCqGSIb3DQMHBAin4GYIwaJohQSCAWC1BTA4MHvRL83mHd6lFsC/UgvGf5/4
+csPetxLj+foMBL9A6rspxB07WxB929Ayxy5rRWq4jeYhPCAg46PL+Ne5MYp9PnDm
+OjYIJjLNPk8wDuDYMDyMYH8+U4o+WaSz612YpcHIM5GEJ2TD0ngx6LctBNRtyWsR
+9Ehn2/NLxrBI0MS93gUxFA/8XkYsQp569kITAfomEjvlsJaNVI+h98cNYdD8Oi0d
+tveEPLh3xHYhNCRYpx34a/RaoAAP7KTGXXR6rjVjPWnNzG9sICBvLOve8Ro/c1cs
+EFynJ56Xd2UJCS/yMnIhlRehVl9IhN5XJ+7Dv0JKHx2BG6N+ME7YZMM9jDZb0WzH
+2+YJqPx99ERnDsRTIdQYgShWsTbMHTdz7MNzox/Zz6l4p7kipQOZLrknoNMb2hy8
+xh1f4SPT9kHwCV/obKSYzv7bGCYjBraetyBavIwl5LjlUySKQ+HC4zFS
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-des3-hmacWithSHA256.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-des3-hmacWithSHA256.der
new file mode 100644
index 0000000000..764d2f68ca
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-des3-hmacWithSHA256.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-des3-hmacWithSHA256.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-des3-hmacWithSHA256.pem
new file mode 100644
index 0000000000..4327d31f43
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-des3-hmacWithSHA256.pem
@@ -0,0 +1,12 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBtDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIFcxat+WIQSYCAggA
+MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECHOnq5nGmYd0BIIBYNxOhizI4irA
+fq63+fV0k/C2HYCN7TEexoU+PiJlIm2/vlusPrTl6LnJqXTA6Y+iVelTWynnkKws
+c13oHCPMTx702JwzNntsLlQo+w8cShjc02SdbJrPUxE/RCtqWo85sEZTYteGk/Lr
+8GnPR3iDhB+m456PgdatqdpEsmy5EGcL3UT0kWmM5knVZfqHkx03kNxtMLV4rkcO
+SPsnezcI2MjyfC4DhXGBBaso48RYZ/905INvmLIRbBX1MHeYtRDpKQlyGQZiSyew
+TqyougDnYqSUs8yKhSsdHqUwltnZmIuJXEtcvtiA/Wmpt4fxxiPtJ8XYWyHreEMf
+w1CevyEbkUdOWsa7zsW10337Lr8DY4Ax/tOTqtARioOBSYdRwlhluBuh91bK5eBt
+ABidgQolNZ3SqIaBV+sEOX+gBDtpu/Lg4jAUO4eokKbhOlKL5YwueiSVrj/cWuKe
+6Js/MZGBcX0=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-2DES.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-2DES.der
new file mode 100644
index 0000000000..c89a60b8ef
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-2DES.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-2DES.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-2DES.pem
new file mode 100644
index 0000000000..46a31fa316
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-2DES.pem
@@ -0,0 +1,11 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBgjAcBgoqhkiG9w0BDAEEMA4ECEOdj9GT2jg/AgIIAASCAWARTCBBDzPLkY0e
+Y60arOJ+bkKuaJJ/OX0IGH3znnFQ5ZmtoToZtoNOaNXG0rAc3PVmkGOW6Uh5nIp8
+D5DrESPzbxltyONQb1TGW5InZKGpO/Vajqy6gDQ/QMR3eXDJsnvSvQ/eCEwqNHXA
+64V1A7Nw0Wfcv6M9qnFMB1LJmcC6Jpt3GTJeoqq+OlsUWqlUWfgIAdOng0ouvVJ0
+u04hGbOJyd5Ejov3PxWc7uXT1X4kcqUNiWFYwvjGocDByzFrW9tmoxyU3ESULdP2
+Fx910xvZnalZBFHQFIOufim/eHKdpND/c4YohgaTULsDwH4EAuZGyqB5kfP0lt8R
+gx3I3jpHiRZXTdzZW7LWIXqGYF+2AaQMTU7qNiNrgWCQ7k8h9YzM1Upzk6YLYsZ9
+UhlbbzkSbJOhlU/1Rce2q0Y7Fsi3bbJqZZ9o0xBK2aP3ApBau9/+ErNtAmuB6EXh
+aKIfeqqn
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-3DES.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-3DES.der
new file mode 100644
index 0000000000..cf1811f406
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-3DES.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-3DES.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-3DES.pem
new file mode 100644
index 0000000000..492b530b00
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-3DES.pem
@@ -0,0 +1,11 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBgjAcBgoqhkiG9w0BDAEDMA4ECEil5BSrj6LeAgIIAASCAWC/kwcthGmbTuVE
+ebfLDlGvn4tnSHzINEquDg3nz555OHreT0DDj0OWtsUY9IqVv/OrukJUXfQnj+jk
+j1TfMi0/MHRRbjmSHf3wGl8LUBtYzn0tmhfvoBtlCt7v3+VQo6QY/hXWbQmOopmx
+vNb8OfRWj0uLjGxeJpaOqsj0gZjbXUQcSXwaZyAG74qNCQMHs6Y/h93Xu9dVhe5h
+B+PtPgT4kFAHV72wiWkxZlyDkonAlhX4wpoEuzYFl+Mc+IZ0ss/bvhswVjjBYx5d
+v1fpOQcVPvjOFPdlm67WYfPyXWgIwP69JSwi7ywyg8GABPfgsNL4Kz9VhH/tanZL
+ZCFnZvHUAX12x39F6RAWxSw8r22jDtsDQQ9sO39PleIhtvfndquEQVx9rswrqKXD
+PxYTOiZ5fEoCxQb1/p9SBMC3rvVotMyuHueLyRYdxwYQOqagRwikJuYLYUK9ibMU
+bBDHp4Mc
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-128.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-128.der
new file mode 100644
index 0000000000..0cb3d5c28e
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-128.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-128.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-128.pem
new file mode 100644
index 0000000000..e74b99eb29
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-128.pem
@@ -0,0 +1,11 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBgjAcBgoqhkiG9w0BDAEFMA4ECC8vkmUmfY3WAgIIAASCAWDzODlrgQ+L8c/5
+YMHk8uVGYRK2cmFRVUIgHz8pnxx7BPnR3mb2igUVk55fi74bIgmk+KGnoRhG2jsq
+dXV2rfTHGZ/AdjwgwA1yLNinhy0BUObMQ4QOrtkNpq4K2MUK8fcvLNRvEhMni0dx
+r41Q4C+bnnx70td2iT7/0efgs4YfT2uxQq//MvI5vfyvCSx71GY6xJdc1wwGbqT7
+KoY5ARvL78Tb1wi6UmdsJza+DU1yO5z1TPAu+a0bawT4LWWAOj2+x/cglsq/La0g
+lJ797NBFWI0Uq5YCMBGzwv3RY2fHtVbt/TSav2Q4oIuaoxLkYRZ2HwUDseMJ4O5A
+46QZqHZyKSQX25pm/gq7kr6bbX/JrGVoWD5ynlaUiVBxyoKHaHRojlbyQTASxjMb
+XZG7jUDpcM4JQ1LKtrNmU72YYGyfrNZhr1TFmSw5ayVfw8vgO4U3Y+JeHXKZOqW/
+QTisuu3L
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-40.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-40.der
new file mode 100644
index 0000000000..404b593068
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-40.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-40.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-40.pem
new file mode 100644
index 0000000000..ddd0106a71
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC2-40.pem
@@ -0,0 +1,11 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBgjAcBgoqhkiG9w0BDAEGMA4ECAicFoXG2QPWAgIIAASCAWB0Uk5k6u0IoN6G
+CB6y4EpIc8lgEGIxO0iAMGYdQd/b/yYVSH5yWBJTM/WJCtIx0GPSYQUjnFh9IQOr
+AAimL90mlzCfdYHAJ7kS2rNCTWJeqXwPeOJmFpmI8oySUE6uflu16ZHXLuZoDIrZ
+O8JZnKF7KlQLIgFn5qiqRuuQrDKiildLChXtsU8nW1B+xBy89qkqWekw7nyN4J68
+3wsm7gzrT7PUNFl9XnWFw+FmSZag8sdqgvDZ0RiFdMAYeFWfTx70KY3PnSYOzoSw
+kYVgviMhcLFxulMsvIsVPaG4cr9JX/eNZfVFH8jnkm3Nqtdl647oO3LfwkXPKz/W
+1JNyd3/p2IOPnkMi8KMFvuhce3zoD77wZJ85PhbsW4YEsB+hxfk8N5ILJysrMf7J
+4BDxc4yYmV4mWna6aUiWnn4gD5ux1qxTUUGWf3tgnyHRGYS0d0xQUQzbCffeW7vj
+PDGpGqbl
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-128.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-128.der
new file mode 100644
index 0000000000..4d13899e1b
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-128.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-128.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-128.pem
new file mode 100644
index 0000000000..a9939f278c
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-128.pem
@@ -0,0 +1,10 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBfDAcBgoqhkiG9w0BDAEBMA4ECJJ4g6/+vh0mAgIIAASCAVo/PESsuYWux3ET
+RNX7Hk3fhm/ZFx5/lvpTFqRy1hMpA6i9liFeLpI13FHarasc92chFLhj+s5JZ+Qg
+WMlDz1nQf4c79dTxVpXGjf4pByXpqr+ksyb0Wo1/NayhjurqrVDpQf0kOdlCNKqn
+8IW2CB5zftsOn8PVkPF3/riUih4xYwvW2w+8rs8RRN0vX9PUsYjtqmq0KnpiWzut
+Tt/D0WJhJTlWVb5dp3nYXEZPM3IOHzvmqBDgbv66JgofpiKn7YXmDUx+edNuWwX2
++GTih5yaRp2IqGbVYT/3eeiyJCpeNLlHJdUDui7zWkiTKpL+RU5VsV4DSjVT7SGV
+tpMQM6HnaCDEr+y4GxUB3/2w8Ua9vZwJ/DRa0vS+N6N+gZfrD78j511h1JOl5EbD
+35P6xNWZBeQbO6pJMKGq5qj/IBgbOQp9xpRtmdTezcY/lys27qN+35vhJSTQy7XG
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-40.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-40.der
new file mode 100644
index 0000000000..cec667ea89
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-40.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-40.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-40.pem
new file mode 100644
index 0000000000..22667c1d9c
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-pkcs12-PBE-SHA1-RC4-40.pem
@@ -0,0 +1,10 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBfDAcBgoqhkiG9w0BDAECMA4ECE5xFtUDnxEJAgIIAASCAVri1/I0SyDAH3Zf
+N4WTxaXJj94JqNOrHC07kckm23evvqGtINC141iSUuPz+zInB0wd0IyDZj+v8ExB
+eFwKOblHhr7ZRCR0zN9IT0CHxjIVmU5W50lpJWTXcALgH+SW97K6jCjVdfAwSEkW
+8X5/iiuhbNXu/8BTy+CBfsiVl8R4CMGhAxD922JoiQqSFA1HzrcxZiIUJ+etN6BF
+YmiF5sCEhiMYMd7FbTDZ3u20dnNPu5Fn+L31aioZ+jtSyRNglVwWYZrdqGyZLlFO
+QAx3AlQdiiqOPJ5rwnezTWdjac9luxhhIFFFq14b02QPu7SeYG56MvruWkwM3raf
+73qbwtNE19yZ9DiWVXaeXpI84tL38E8sIQ1vthVuHtJ+6U1HUgPafVYZn+eKqiPz
+UrJYbJTPL27GS2zXJnr9OrwRlGpKHQGjHo6hyg0UmZ71xuurVuHPty00Oap1CV13
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-rc2-hmacWithSHA1.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-rc2-hmacWithSHA1.der
new file mode 100644
index 0000000000..3860600474
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-rc2-hmacWithSHA1.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-rc2-hmacWithSHA1.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-rc2-hmacWithSHA1.pem
new file mode 100644
index 0000000000..61de0e9893
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-rc2-hmacWithSHA1.pem
@@ -0,0 +1,11 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBpjBIBgkqhkiG9w0BBQ0wOzAeBgkqhkiG9w0BBQwwEQQIQYOeTgwR/LsCAggA
+AgEQMBkGCCqGSIb3DQMCMA0CAToECMd9tvoaH7I8BIIBWNGNJ3RipB+HrN0t6rsA
+C3iOTcc4LEo03gguQ4Uxf0KyDMt7fyLpo/77m0QXLVBMW7mDjDASsaFWDzqM1OxZ
+3kmV2+thdyLfnnA2l6tCDdImKWrNBYK2ogmpkJy15piwFZ/XUBrm63zP/NYCyRsF
+jXOzy0FGv/xxaw9RAiGJMsvdoopHr2Lo37DeeBoXCR6gzfvyyuqzr5fbrV7agk5i
+pGMAbJNKtbbCrzXOKCBDTGDUFiOtxNoDEsJy2Tx6YqotNJedyMzhZAatcL5h0a9w
+r4jRLSWmHqo9WTFgcibhcXuy6cko3/wGov0Z2Pq1bPga8tWeuta74IaGLCuVWwHE
+ze2nii7RWIU1oQ9ZgD6CuZnggyRT8b3/TYTQ6pra+yp99lvH48MySVJU5QEdpoOq
+tUU+7z0BdEl5SALfBlQhBCEP13KhPitKcppVphxMv1cAidIHBne1YGKo
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-rc2-hmacWithSHA256.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-rc2-hmacWithSHA256.der
new file mode 100644
index 0000000000..f4ca23ba74
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-rc2-hmacWithSHA256.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-rc2-hmacWithSHA256.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-rc2-hmacWithSHA256.pem
new file mode 100644
index 0000000000..c09da71121
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8-rc2-hmacWithSHA256.pem
@@ -0,0 +1,12 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIBtDBWBgkqhkiG9w0BBQ0wSTAsBgkqhkiG9w0BBQwwHwQIi1jllb1PqZcCAggA
+AgEQMAwGCCqGSIb3DQIJBQAwGQYIKoZIhvcNAwIwDQIBOgQIQDijmMtzY+UEggFY
+gItLu4+5cGLUWeqbt9L7tKBoLpMSYGScvjcPwiKX1tygqg1lD9saeOqSZFx3AEyd
+3AlEpZSPaQpAqp61zrKV1cSYzafRyYV2R6NArgWpSZP3LggquoQHnZN/8hRtbidC
+7KgB/kXP7sCWKiUj4Smh/HhkS/w0K5doxt34VicijP4q29NZ0UDQDGABC1gA7L5l
+FvZrZJi6laawHJbZDb6zaHVbvL2OMclXrzLpHF269H/NYwE+3/xtUa8AhTYVRRq/
+oOByi++ap2QL32IyHbdgNEj7a9WGM58iWVW+jS9G45ChylIDG9oCg4KeHp+5sjPv
+rkDsXdzXeCwFQuJ1nj/pRVR6aI3qUMM1jjQFoOQ/XrPWIBvVzXC8eYRud/rHaOdV
+IH7B9kFFqwSAzzi9GtTNj1hfQ8adm54N+qq2c4JRKN/a6cSRAlwtoI344OO20ejv
+2RO9QGJkkSU=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8.der
new file mode 100644
index 0000000000..b6ef9a15a2
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8.pem
new file mode 100644
index 0000000000..2a71a861bf
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512-pkcs8.pem
@@ -0,0 +1,10 @@
+-----BEGIN PRIVATE KEY-----
+MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAwDsb+Kv6gzwj4qqN
+kD5pZigHwVq+TgsAua++RsXnaWGiOWA2m2a5vM+TC9trcIAHHU2xaGjxt2UGi9b9
+mPNMoQIDAQABAkB64062Yfr7+m5WcQGevMdUbzLGAOS3r4D/M8JILCwLySrni0rV
+sti1UF1X2ypna24tsRKN0CD/a8111k+yZXeBAiEA4ats1RjWHIA9tIimdi3Qj9LO
+BtBs5wBaaryExZyQDFUCIQDaESne8AcqQ08gst1Ykyj0bKwl+ybSWxAzSb/52fFL
+HQIgKFX9s/EmhB2f6d7q8gCqYKqrTKiAbqGvh5h+mturG6kCIQDYAeRt92nBjYcW
+JtdnY+5PoE4uGUhtWtMDWuyVfDOuaQIgU9/flj81ZByBxXk5sULHUa3+eqfQKSgi
+xYZorAtL3xg=
+-----END PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/qsslkey.pro b/tests/auto/network/ssl/qsslkey/qsslkey.pro
index 0074513878..8ed65e68ad 100644
--- a/tests/auto/network/ssl/qsslkey/qsslkey.pro
+++ b/tests/auto/network/ssl/qsslkey/qsslkey.pro
@@ -1,7 +1,6 @@
CONFIG += testcase
SOURCES += tst_qsslkey.cpp
-win32:LIBS += -lws2_32
QT = core network testlib
qtConfig(private_tests) {
QT += core-private network-private
diff --git a/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp b/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp
index 27d92db3bf..ddfe52c5e4 100644
--- a/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp
+++ b/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp
@@ -110,10 +110,10 @@ void tst_QSslKey::initTestCase()
testDataDir += QLatin1String("/");
QDir dir(testDataDir + "keys");
- QFileInfoList fileInfoList = dir.entryInfoList(QDir::Files | QDir::Readable);
- QRegExp rx(QLatin1String("^(rsa|dsa|ec)-(pub|pri)-(\\d+)-?\\w*\\.(pem|der)$"));
- foreach (QFileInfo fileInfo, fileInfoList) {
- if (rx.indexIn(fileInfo.fileName()) >= 0)
+ const QFileInfoList fileInfoList = dir.entryInfoList(QDir::Files | QDir::Readable);
+ QRegExp rx(QLatin1String("^(rsa|dsa|ec)-(pub|pri)-(\\d+)-?[\\w-]*\\.(pem|der)$"));
+ for (const QFileInfo &fileInfo : fileInfoList) {
+ if (rx.indexIn(fileInfo.fileName()) >= 0) {
keyInfoList << KeyInfo(
fileInfo,
rx.cap(1) == QLatin1String("rsa") ? QSsl::Rsa :
@@ -121,6 +121,7 @@ void tst_QSslKey::initTestCase()
rx.cap(2) == QLatin1String("pub") ? QSsl::PublicKey : QSsl::PrivateKey,
rx.cap(3).toInt(),
rx.cap(4) == QLatin1String("pem") ? QSsl::Pem : QSsl::Der);
+ }
}
}
@@ -163,6 +164,16 @@ void tst_QSslKey::createPlainTestRows(bool filter, QSsl::EncodingFormat format)
foreach (KeyInfo keyInfo, keyInfoList) {
if (filter && keyInfo.format != format)
continue;
+#ifdef Q_OS_WINRT
+ if (keyInfo.fileInfo.fileName().contains("RC2-64"))
+ continue; // WinRT treats RC2 as 128 bit
+#endif
+#if !defined(QT_NO_SSL) && defined(QT_NO_OPENSSL) // generic backend
+ if (keyInfo.fileInfo.fileName().contains(QRegularExpression("-aes\\d\\d\\d-")))
+ continue; // No AES support in the generic back-end
+ if (keyInfo.fileInfo.fileName().contains("pkcs8-pkcs12"))
+ continue; // The generic back-end doesn't support PKCS#12 algorithms
+#endif
QTest::newRow(keyInfo.fileInfo.fileName().toLatin1())
<< keyInfo.fileInfo.absoluteFilePath() << keyInfo.algorithm << keyInfo.type
@@ -186,7 +197,10 @@ void tst_QSslKey::constructor()
QFETCH(QSsl::EncodingFormat, format);
QByteArray encoded = readFile(absFilePath);
- QSslKey key(encoded, algorithm, format, type);
+ QByteArray passphrase;
+ if (QByteArray(QTest::currentDataTag()).contains("-pkcs8-"))
+ passphrase = QByteArray("1234");
+ QSslKey key(encoded, algorithm, format, type, passphrase);
QVERIFY(!key.isNull());
}
@@ -215,9 +229,12 @@ void tst_QSslKey::constructorHandle()
? q_PEM_read_bio_PUBKEY
: q_PEM_read_bio_PrivateKey);
+ QByteArray passphrase;
+ if (QByteArray(QTest::currentDataTag()).contains("-pkcs8-"))
+ passphrase = "1234";
BIO* bio = q_BIO_new(q_BIO_s_mem());
q_BIO_write(bio, pem.constData(), pem.length());
- QSslKey key(func(bio, nullptr, nullptr, nullptr), type);
+ QSslKey key(func(bio, nullptr, nullptr, static_cast<void *>(passphrase.data())), type);
q_BIO_free(bio);
QVERIFY(!key.isNull());
@@ -245,7 +262,10 @@ void tst_QSslKey::copyAndAssign()
QFETCH(QSsl::EncodingFormat, format);
QByteArray encoded = readFile(absFilePath);
- QSslKey key(encoded, algorithm, format, type);
+ QByteArray passphrase;
+ if (QByteArray(QTest::currentDataTag()).contains("-pkcs8-"))
+ passphrase = QByteArray("1234");
+ QSslKey key(encoded, algorithm, format, type, passphrase);
QSslKey copied(key);
QCOMPARE(key, copied);
@@ -286,7 +306,10 @@ void tst_QSslKey::length()
QFETCH(QSsl::EncodingFormat, format);
QByteArray encoded = readFile(absFilePath);
- QSslKey key(encoded, algorithm, format, type);
+ QByteArray passphrase;
+ if (QByteArray(QTest::currentDataTag()).contains("-pkcs8-"))
+ passphrase = QByteArray("1234");
+ QSslKey key(encoded, algorithm, format, type, passphrase);
QVERIFY(!key.isNull());
QCOMPARE(key.length(), length);
}
@@ -306,6 +329,17 @@ void tst_QSslKey::toPemOrDer()
QFETCH(QSsl::KeyType, type);
QFETCH(QSsl::EncodingFormat, format);
+ QByteArray dataTag = QByteArray(QTest::currentDataTag());
+ if (dataTag.contains("-pkcs8-")) // these are encrypted
+ QSKIP("Encrypted PKCS#8 keys gets decrypted when loaded. So we can't compare it to the encrypted version.");
+#ifndef QT_NO_OPENSSL
+ if (dataTag.contains("pkcs8"))
+ QSKIP("OpenSSL converts PKCS#8 keys to other formats, invalidating comparisons.");
+#else // !openssl
+ if (dataTag.contains("pkcs8") && dataTag.contains("rsa"))
+ QSKIP("PKCS#8 RSA keys are changed into a different format in the generic back-end, meaning the comparison fails.");
+#endif // openssl
+
QByteArray encoded = readFile(absFilePath);
QSslKey key(encoded, algorithm, format, type);
QVERIFY(!key.isNull());
@@ -326,6 +360,8 @@ void tst_QSslKey::toEncryptedPemOrDer_data()
passwords << " " << "foobar" << "foo bar"
<< "aAzZ`1234567890-=~!@#$%^&*()_+[]{}\\|;:'\",.<>/?"; // ### add more (?)
foreach (KeyInfo keyInfo, keyInfoList) {
+ if (keyInfo.fileInfo.fileName().contains("pkcs8"))
+ continue; // pkcs8 keys are encrypted in a different way than the other keys
foreach (QString password, passwords) {
const QByteArray testName = keyInfo.fileInfo.fileName().toLatin1()
+ '-' + (keyInfo.algorithm == QSsl::Rsa ? "RSA" :
diff --git a/tests/auto/network/ssl/qsslsocket/qsslsocket.pro b/tests/auto/network/ssl/qsslsocket/qsslsocket.pro
index f45857b02d..1260dc9410 100644
--- a/tests/auto/network/ssl/qsslsocket/qsslsocket.pro
+++ b/tests/auto/network/ssl/qsslsocket/qsslsocket.pro
@@ -1,7 +1,6 @@
CONFIG += testcase
SOURCES += tst_qsslsocket.cpp
-win32:LIBS += -lws2_32
QT = core core-private network-private testlib
TARGET = tst_qsslsocket
diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
index e32fa7c724..b759aed074 100644
--- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
+++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
@@ -202,6 +202,9 @@ private slots:
void verifyDepth();
void disconnectFromHostWhenConnecting();
void disconnectFromHostWhenConnected();
+#ifndef QT_NO_OPENSSL
+ void closeWhileEmittingSocketError();
+#endif
void resetProxy();
void ignoreSslErrorsList_data();
void ignoreSslErrorsList();
@@ -2336,6 +2339,66 @@ void tst_QSslSocket::disconnectFromHostWhenConnected()
QCOMPARE(socket->bytesToWrite(), qint64(0));
}
+#ifndef QT_NO_OPENSSL
+
+class BrokenPskHandshake : public QTcpServer
+{
+public:
+ void socketError(QAbstractSocket::SocketError error)
+ {
+ Q_UNUSED(error);
+ QSslSocket *clientSocket = qobject_cast<QSslSocket *>(sender());
+ Q_ASSERT(clientSocket);
+ clientSocket->close();
+ QTestEventLoop::instance().exitLoop();
+ }
+private:
+
+ void incomingConnection(qintptr handle) override
+ {
+ if (!socket.setSocketDescriptor(handle))
+ return;
+
+ QSslConfiguration serverConfig(QSslConfiguration::defaultConfiguration());
+ serverConfig.setPreSharedKeyIdentityHint("abcdefghijklmnop");
+ socket.setSslConfiguration(serverConfig);
+ socket.startServerEncryption();
+ }
+
+ QSslSocket socket;
+};
+
+void tst_QSslSocket::closeWhileEmittingSocketError()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ BrokenPskHandshake handshake;
+ if (!handshake.listen())
+ QSKIP("failed to start TLS server");
+
+ QSslSocket clientSocket;
+ QSslConfiguration clientConfig(QSslConfiguration::defaultConfiguration());
+ clientConfig.setPeerVerifyMode(QSslSocket::VerifyNone);
+ clientSocket.setSslConfiguration(clientConfig);
+
+ QSignalSpy socketErrorSpy(&clientSocket, SIGNAL(error(QAbstractSocket::SocketError)));
+ void (QSslSocket::*errorSignal)(QAbstractSocket::SocketError) = &QSslSocket::error;
+ connect(&clientSocket, errorSignal, &handshake, &BrokenPskHandshake::socketError);
+
+ clientSocket.connectToHostEncrypted(QStringLiteral("127.0.0.1"), handshake.serverPort());
+ // Make sure we have some data buffered so that close will try to flush:
+ clientSocket.write(QByteArray(1000000, Qt::Uninitialized));
+
+ QTestEventLoop::instance().enterLoopMSecs(1000);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ QCOMPARE(socketErrorSpy.count(), 1);
+}
+
+#endif // QT_NO_OPENSSL
+
void tst_QSslSocket::resetProxy()
{
#ifndef QT_NO_NETWORKPROXY
@@ -2809,13 +2872,13 @@ class SslServer4 : public QTcpServer
{
Q_OBJECT
public:
- SslServer4() : socket(0) {}
- WebSocket *socket;
+
+ QScopedPointer<WebSocket> socket;
protected:
- void incomingConnection(qintptr socketDescriptor)
+ void incomingConnection(qintptr socketDescriptor) override
{
- socket = new WebSocket(socketDescriptor);
+ socket.reset(new WebSocket(socketDescriptor));
}
};
@@ -2829,38 +2892,36 @@ void tst_QSslSocket::qtbug18498_peek()
return;
SslServer4 server;
- QSslSocket *client = new QSslSocket(this);
-
QVERIFY(server.listen(QHostAddress::LocalHost));
- client->connectToHost("127.0.0.1", server.serverPort());
- QVERIFY(client->waitForConnected(5000));
+
+ QSslSocket client;
+ client.connectToHost("127.0.0.1", server.serverPort());
+ QVERIFY(client.waitForConnected(5000));
QVERIFY(server.waitForNewConnection(1000));
- client->setObjectName("client");
- client->ignoreSslErrors();
+ client.ignoreSslErrors();
int encryptedCounter = 2;
- connect(client, &QSslSocket::encrypted, this, [&encryptedCounter, this](){
+ connect(&client, &QSslSocket::encrypted, this, [&encryptedCounter](){
if (!--encryptedCounter)
exitLoop();
});
- WebSocket *serversocket = server.socket;
- connect(serversocket, &QSslSocket::encrypted, this, [&encryptedCounter, this](){
+ WebSocket *serversocket = server.socket.data();
+ connect(serversocket, &QSslSocket::encrypted, this, [&encryptedCounter](){
if (!--encryptedCounter)
exitLoop();
});
- connect(client, SIGNAL(disconnected()), this, SLOT(exitLoop()));
+ connect(&client, SIGNAL(disconnected()), this, SLOT(exitLoop()));
- client->startClientEncryption();
+ client.startClientEncryption();
QVERIFY(serversocket);
- serversocket->setObjectName("server");
enterLoop(1);
QVERIFY(!timeout());
QVERIFY(serversocket->isEncrypted());
- QVERIFY(client->isEncrypted());
+ QVERIFY(client.isEncrypted());
QByteArray data("abc123");
- client->write(data.data());
+ client.write(data.data());
connect(serversocket, SIGNAL(readyRead()), this, SLOT(exitLoop()));
enterLoop(1);
diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro
index c862b3d3ae..05755ff606 100644
--- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro
+++ b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro
@@ -2,7 +2,6 @@ CONFIG += testcase
testcase.timeout = 300 # this test is slow
SOURCES += tst_qsslsocket_onDemandCertificates_member.cpp
-win32:LIBS += -lws2_32
QT = core core-private network-private testlib
TARGET = tst_qsslsocket_onDemandCertificates_member
diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro
index c27a58fcd2..c345d7379f 100644
--- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro
+++ b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro
@@ -1,7 +1,6 @@
CONFIG += testcase
SOURCES += tst_qsslsocket_onDemandCertificates_static.cpp
-win32:LIBS += -lws2_32
QT = core core-private network-private testlib
TARGET = tst_qsslsocket_onDemandCertificates_static
diff --git a/tests/auto/network/ssl/ssl.pro b/tests/auto/network/ssl/ssl.pro
index 175f361071..e89443ef4e 100644
--- a/tests/auto/network/ssl/ssl.pro
+++ b/tests/auto/network/ssl/ssl.pro
@@ -1,7 +1,8 @@
TEMPLATE=subdirs
-QT_FOR_CONFIG += network
+QT_FOR_CONFIG += network-private
SUBDIRS=\
+ qpassworddigestor \
qsslcertificate \
qsslcipher \
qsslellipticcurve \
@@ -13,7 +14,13 @@ qtConfig(ssl) {
SUBDIRS += \
qsslsocket \
qsslsocket_onDemandCertificates_member \
- qsslsocket_onDemandCertificates_static \
+ qsslsocket_onDemandCertificates_static
+
+ qtConfig(dtls) {
+ SUBDIRS += \
+ qdtlscookie \
+ qdtls
+ }
}
}
diff --git a/tests/auto/opengl/qgl/BLACKLIST b/tests/auto/opengl/qgl/BLACKLIST
index 71be4bf19d..d3165a51e5 100644
--- a/tests/auto/opengl/qgl/BLACKLIST
+++ b/tests/auto/opengl/qgl/BLACKLIST
@@ -19,6 +19,7 @@ winrt
[graphicsViewClipping]
windows
winrt
+linux ci
[glFBOUseInGLWidget]
windows
winrt
diff --git a/tests/auto/opengl/qglthreads/tst_qglthreads.cpp b/tests/auto/opengl/qglthreads/tst_qglthreads.cpp
index 76186f5575..09bea20d26 100644
--- a/tests/auto/opengl/qglthreads/tst_qglthreads.cpp
+++ b/tests/auto/opengl/qglthreads/tst_qglthreads.cpp
@@ -131,6 +131,13 @@ public:
setAutoBufferSwap(false);
}
+ void resizeEvent(QResizeEvent *e)
+ {
+ m_thread->lock();
+ QGLWidget::resizeEvent(e);
+ m_thread->unlock();
+ }
+
void paintEvent(QPaintEvent *)
{
m_thread->lock();
diff --git a/tests/auto/other/gestures/BLACKLIST b/tests/auto/other/gestures/BLACKLIST
index 169117b36a..269bac5750 100644
--- a/tests/auto/other/gestures/BLACKLIST
+++ b/tests/auto/other/gestures/BLACKLIST
@@ -1,6 +1,18 @@
[]
rhel-7.4
+ubuntu-18.04
[customGesture]
# QTBUG-67254
ubuntu
opensuse
+opensuse-leap
+[graphicsItemGesture]
+ubuntu-18.04
+[graphicsItemTreeGesture]
+ubuntu-18.04
+[graphicsView]
+ubuntu-18.04
+[explicitGraphicsObjectTarget]
+ubuntu-18.04
+[autoCancelGestures2]
+ubuntu-18.04
diff --git a/tests/auto/other/lancelot/paintcommands.cpp b/tests/auto/other/lancelot/paintcommands.cpp
index 074644393d..65a688ec40 100644
--- a/tests/auto/other/lancelot/paintcommands.cpp
+++ b/tests/auto/other/lancelot/paintcommands.cpp
@@ -106,7 +106,8 @@ const char *PaintCommands::spreadMethodTable[] = {
const char *PaintCommands::coordinateMethodTable[] = {
"LogicalMode",
"StretchToDeviceMode",
- "ObjectBoundingMode"
+ "ObjectBoundingMode",
+ "ObjectMode"
};
const char *PaintCommands::sizeModeTable[] = {
@@ -176,6 +177,9 @@ const char *PaintCommands::imageFormatTable[] = {
"Format_A2RGB30_Premultiplied",
"Alpha8",
"Grayscale8",
+ "RGBx64",
+ "RGBA64",
+ "RGBA64_Premultiplied",
};
int PaintCommands::translateEnum(const char *table[], const QString &pattern, int limit)
@@ -561,6 +565,10 @@ void PaintCommands::staticInit()
"^bitmap_load\\s+([\\w.:\\/]*)\\s*([\\w.:\\/]*)$",
"bitmap_load <bitmap filename> <bitmapName>\n - note that the image is stored as a pixmap",
"bitmap_load :/images/bitmap.png myBitmap");
+ DECL_PAINTCOMMAND("pixmap_setDevicePixelRatio", command_pixmap_setDevicePixelRatio,
+ "^pixmap_setDevicePixelRatio\\s+([\\w.:\\/]*)\\s+([.0-9]*)$",
+ "pixmap_setDevicePixelRatio <pixmapName> <dpr>",
+ "pixmap_setDevicePixelRatio myPixmap 2.0");
DECL_PAINTCOMMAND("image_convertToFormat", command_image_convertToFormat,
"^image_convertToFormat\\s+([\\w.:\\/]*)\\s+([\\w.:\\/]+)\\s+([\\w0-9_]*)$",
"image_convertToFormat <sourceImageName> <destImageName> <image format enum>",
@@ -577,6 +585,10 @@ void PaintCommands::staticInit()
"^image_setColorCount\\s+([\\w.:\\/]*)\\s+([0-9]*)$",
"image_setColorCount <imageName> <nbColors>",
"image_setColorCount myImage 128");
+ DECL_PAINTCOMMAND("image_setDevicePixelRatio", command_image_setDevicePixelRatio,
+ "^image_setDevicePixelRatio\\s+([\\w.:\\/]*)\\s+([.0-9]*)$",
+ "image_setDevicePixelRatio <imageName> <dpr>",
+ "image_setDevicePixelRatio myImage 2.0");
DECL_PAINTCOMMANDSECTION("transformations");
DECL_PAINTCOMMAND("resetMatrix", command_resetMatrix,
@@ -1761,7 +1773,9 @@ void PaintCommands::command_setBrush(QRegularExpressionMatch re)
{
QStringList caps = re.capturedTexts();
- QImage img = image_load<QImage>(caps.at(1));
+ QImage img = m_imageMap[caps.at(1)]; // try cache first
+ if (img.isNull())
+ img = image_load<QImage>(caps.at(1));
if (!img.isNull()) { // Assume image brush
if (m_verboseMode)
printf(" -(lance) setBrush(image=%s, width=%d, height=%d)\n",
@@ -2132,6 +2146,20 @@ void PaintCommands::command_bitmap_load(QRegularExpressionMatch re)
m_pixmapMap[name] = bm;
}
+void PaintCommands::command_pixmap_setDevicePixelRatio(QRegularExpressionMatch re)
+{
+ QStringList caps = re.capturedTexts();
+
+ QString name = caps.at(1);
+ double dpr = convertToDouble(caps.at(2));
+
+ if (m_verboseMode)
+ printf(" -(lance) pixmap_setDevicePixelRatio(%s), %.1f -> %.1f\n",
+ qPrintable(name), m_pixmapMap[name].devicePixelRatioF(), dpr);
+
+ m_pixmapMap[name].setDevicePixelRatio(dpr);
+}
+
/***************************************************************************************************/
void PaintCommands::command_pixmap_setMask(QRegularExpressionMatch re)
{
@@ -2197,6 +2225,21 @@ void PaintCommands::command_image_setColor(QRegularExpressionMatch re)
}
/***************************************************************************************************/
+void PaintCommands::command_image_setDevicePixelRatio(QRegularExpressionMatch re)
+{
+ QStringList caps = re.capturedTexts();
+
+ QString name = caps.at(1);
+ double dpr = convertToDouble(caps.at(2));
+
+ if (m_verboseMode)
+ printf(" -(lance) image_setDevicePixelRatio(%s), %.1f -> %.1f\n",
+ qPrintable(name), m_imageMap[name].devicePixelRatioF(), dpr);
+
+ m_imageMap[name].setDevicePixelRatio(dpr);
+}
+
+/***************************************************************************************************/
void PaintCommands::command_abort(QRegularExpressionMatch)
{
m_abort = true;
@@ -2355,7 +2398,7 @@ void PaintCommands::command_gradient_setSpread(QRegularExpressionMatch re)
void PaintCommands::command_gradient_setCoordinateMode(QRegularExpressionMatch re)
{
- int coord = translateEnum(coordinateMethodTable, re.captured(1), 3);
+ int coord = translateEnum(coordinateMethodTable, re.captured(1), 4);
if (m_verboseMode)
printf(" -(lance) gradient_setCoordinateMode %d=[%s]\n", coord,
diff --git a/tests/auto/other/lancelot/paintcommands.h b/tests/auto/other/lancelot/paintcommands.h
index e3fb96744c..83e3bbc11c 100644
--- a/tests/auto/other/lancelot/paintcommands.h
+++ b/tests/auto/other/lancelot/paintcommands.h
@@ -229,10 +229,12 @@ private:
void command_pixmap_load(QRegularExpressionMatch re);
void command_pixmap_setMask(QRegularExpressionMatch re);
void command_bitmap_load(QRegularExpressionMatch re);
+ void command_pixmap_setDevicePixelRatio(QRegularExpressionMatch re);
void command_image_convertToFormat(QRegularExpressionMatch re);
void command_image_load(QRegularExpressionMatch re);
void command_image_setColor(QRegularExpressionMatch re);
void command_image_setColorCount(QRegularExpressionMatch re);
+ void command_image_setDevicePixelRatio(QRegularExpressionMatch re);
// commands: transformation
void command_resetMatrix(QRegularExpressionMatch re);
diff --git a/tests/auto/other/lancelot/scripts/gradientxform_object.qps b/tests/auto/other/lancelot/scripts/gradientxform_object.qps
index d785a008c0..dcc718072f 100644
--- a/tests/auto/other/lancelot/scripts/gradientxform_object.qps
+++ b/tests/auto/other/lancelot/scripts/gradientxform_object.qps
@@ -62,7 +62,22 @@ repeat_block row
restore
end_block block
+save
translate 400 0
brushRotate 30.0
brushScale 1.5 .5
repeat_block block
+restore
+
+drawText 80 400 "BRUSH XFORM, OBJECT BOUNDING MODE"
+drawText 500 400 "BRUSH XFORM, OBJECT MODE"
+
+translate 0 400
+brushTranslate 0.5 0.5
+brushRotate 180.0
+brushTranslate -0.5 -0.5
+repeat_block block
+
+translate 400 0
+gradient_setCoordinateMode ObjectMode
+repeat_block block
diff --git a/tests/auto/other/lancelot/scripts/image_dpr.qps b/tests/auto/other/lancelot/scripts/image_dpr.qps
new file mode 100644
index 0000000000..7d3ca3099c
--- /dev/null
+++ b/tests/auto/other/lancelot/scripts/image_dpr.qps
@@ -0,0 +1,43 @@
+
+setRenderHint Antialiasing true
+setRenderHint SmoothPixmapTransform true
+
+image_load sign.png img1
+pixmap_load sign.png pix1
+
+begin_block drawIt
+save
+
+drawImage img1 20 20 -1 -1
+drawRect 17.5 17.5 85 85
+
+setBrush img1
+setPen NoPen
+drawRect 20 120 120 120
+
+brushRotate 45
+drawRect 20 260 120 120
+
+setBrush NoBrush
+drawTiledPixmap pix1 20 400 120 120
+
+restore
+end_block
+
+save
+translate 150 0
+rotate -5
+repeat_block drawIt
+restore
+
+image_setDevicePixelRatio img1 2.0
+pixmap_setDevicePixelRatio pix1 2.0
+translate 400 0
+repeat_block drawIt
+
+save
+translate 150 0
+rotate -5
+repeat_block drawIt
+restore
+
diff --git a/tests/auto/other/macnativeevents/macnativeevents.pro b/tests/auto/other/macnativeevents/macnativeevents.pro
index 0611377d0b..0fe5949a1d 100644
--- a/tests/auto/other/macnativeevents/macnativeevents.pro
+++ b/tests/auto/other/macnativeevents/macnativeevents.pro
@@ -8,3 +8,5 @@ SOURCES += tst_macnativeevents.cpp
requires(mac)
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
+
+LIBS += -framework AppKit
diff --git a/tests/auto/other/other.pro b/tests/auto/other/other.pro
index ea2e1dabf2..d70c895dec 100644
--- a/tests/auto/other/other.pro
+++ b/tests/auto/other/other.pro
@@ -7,7 +7,7 @@ SUBDIRS=\
lancelot \
languagechange \
macgui \
- macnativeevents \
+ #macnativeevents \
macplist \
networkselftest \
qaccessibility \
@@ -39,7 +39,7 @@ SUBDIRS=\
qaccessibilitylinux \
qaccessibilitymac \
-!qtHaveModule(network): SUBDIRS -= \
+winrt|!qtHaveModule(network): SUBDIRS -= \
lancelot \
networkselftest \
qnetworkaccessmanager_and_qprogressdialog \
@@ -48,9 +48,9 @@ cross_compile: SUBDIRS -= \
atwrapper \
compiler
-!qtConfig(accessibility): SUBDIRS -= qaccessibility
+winrt|!qtHaveModule(gui)|!qtConfig(accessibility): SUBDIRS -= qaccessibility
-!qtConfig(accessibility-atspi-bridge): SUBDIRS -= qaccessibilitylinux
+!qtHaveModule(gui)|!qtConfig(accessibility-atspi-bridge): SUBDIRS -= qaccessibilitylinux
!qtConfig(process): SUBDIRS -= qprocess_and_guieventloop
diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
index 8cf039c06a..8b24937079 100644
--- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
+++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
@@ -876,6 +876,10 @@ void tst_QAccessibility::applicationTest()
QCOMPARE(interface->child(1), static_cast<QAccessibleInterface*>(0));
QCOMPARE(interface->childCount(), 0);
+ // Check that asking for the application interface twice returns the same object
+ QAccessibleInterface *app2 = QAccessible::queryAccessibleInterface(qApp);
+ QCOMPARE(interface, app2);
+
QWidget widget;
widget.show();
qApp->setActiveWindow(&widget);
diff --git a/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp b/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp
index 2575f22309..47d24ce171 100644
--- a/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp
+++ b/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp
@@ -211,6 +211,27 @@ void tst_QAccessibilityLinux::registerDbus()
mainWindow = getInterface(window, "org.a11y.atspi.Accessible");
}
+quint64 getAtspiState(QDBusInterface *interface)
+{
+ QDBusMessage msg = interface->call(QDBus::Block, "GetState");
+ const QDBusArgument arg = msg.arguments().at(0).value<QDBusArgument>();
+ quint32 state1 = 0;
+ quint64 state2 = 0;
+ arg.beginArray();
+ arg >> state1;
+ arg >> state2;
+ arg.endArray();
+
+ state2 = state2 << 32;
+ return state2 | state1;
+}
+
+bool hasState(QDBusInterface *interface, AtspiStateType state)
+{
+ quint64 intState = quint64(1) << state;
+ return getAtspiState(interface) & intState;
+}
+
#define ROOTPATH "/org/a11y/atspi/accessible"
void tst_QAccessibilityLinux::testLabel()
@@ -353,13 +374,21 @@ void tst_QAccessibilityLinux::testTreeWidget()
QDBusInterface *cell3 = getInterface(tableChildren.at(2), "org.a11y.atspi.Accessible");
QCOMPARE(cell3->property("Name").toString(), QLatin1String("0.0"));
+ QVERIFY(!hasState(cell3, ATSPI_STATE_EXPANDABLE));
+ QVERIFY(!hasState(cell3, ATSPI_STATE_EXPANDED));
QDBusInterface *cell4 = getInterface(tableChildren.at(3), "org.a11y.atspi.Accessible");
QCOMPARE(cell4->property("Name").toString(), QLatin1String("0.1"));
+ QDBusInterface *dbus_top2 = getInterface(tableChildren.at(4), "org.a11y.atspi.Accessible");
+ QCOMPARE(dbus_top2->property("Name").toString(), QLatin1String("1.0"));
+ QVERIFY(hasState(dbus_top2, ATSPI_STATE_EXPANDABLE));
+ QVERIFY(!hasState(dbus_top2, ATSPI_STATE_EXPANDED));
+
tree->expandItem(top2);
tableChildren = getChildren(treeIface);
QCOMPARE(tableChildren.size(), 8);
+ QVERIFY(hasState(dbus_top2, ATSPI_STATE_EXPANDED));
QDBusInterface *cell5 = getInterface(tableChildren.at(6), "org.a11y.atspi.Accessible");
QCOMPARE(cell5->property("Name").toString(), QLatin1String("1.0 0.0"));
@@ -471,21 +500,6 @@ void tst_QAccessibilityLinux::testSlider()
m_window->clearChildren();
}
-quint64 getAtspiState(QDBusInterface *interface)
-{
- QDBusMessage msg = interface->call(QDBus::Block, "GetState");
- const QDBusArgument arg = msg.arguments().at(0).value<QDBusArgument>();
- quint32 state1 = 0;
- quint64 state2 = 0;
- arg.beginArray();
- arg >> state1;
- arg >> state2;
- arg.endArray();
-
- state2 = state2 << 32;
- return state2 | state1;
-}
-
void tst_QAccessibilityLinux::testFocus()
{
QLineEdit *lineEdit1 = new QLineEdit(m_window);
@@ -508,15 +522,14 @@ void tst_QAccessibilityLinux::testFocus()
QDBusInterface *componentInterfaceLineEdit2 = getInterface(children.at(1), "org.a11y.atspi.Component");
QVERIFY(componentInterfaceLineEdit2->isValid());
- quint64 focusedState = quint64(1) << ATSPI_STATE_FOCUSED;
- QVERIFY(getAtspiState(accessibleInterfaceLineEdit1) & focusedState);
- QVERIFY(!(getAtspiState(accessibleInterfaceLineEdit2) & focusedState));
+ QVERIFY(hasState(accessibleInterfaceLineEdit1, ATSPI_STATE_FOCUSED));
+ QVERIFY(!hasState(accessibleInterfaceLineEdit2, ATSPI_STATE_FOCUSED));
QDBusMessage focusReply = componentInterfaceLineEdit2->call(QDBus::Block, "GrabFocus");
QVERIFY(focusReply.arguments().at(0).toBool());
QVERIFY(lineEdit2->hasFocus());
- QVERIFY(!(getAtspiState(accessibleInterfaceLineEdit1) & focusedState));
- QVERIFY(getAtspiState(accessibleInterfaceLineEdit2) & focusedState);
+ QVERIFY(!hasState(accessibleInterfaceLineEdit1, ATSPI_STATE_FOCUSED));
+ QVERIFY(hasState(accessibleInterfaceLineEdit2, ATSPI_STATE_FOCUSED));
m_window->clearChildren();
delete accessibleInterfaceLineEdit1;
delete accessibleInterfaceLineEdit2;
diff --git a/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.mm b/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.mm
index e9407fd903..4ebf7a37f9 100644
--- a/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.mm
+++ b/tests/auto/other/qaccessibilitymac/tst_qaccessibilitymac_helpers.mm
@@ -101,9 +101,9 @@ QDebug operator<<(QDebug dbg, AXErrorTag err)
@implementation TestAXObject
-- (id) initWithAXUIElementRef: (AXUIElementRef) ref {
+- (instancetype)initWithAXUIElementRef:(AXUIElementRef)ref {
- if ( self = [super init] ) {
+ if ((self = [super init])) {
reference = ref;
}
return self;
diff --git a/tests/auto/other/qfocusevent/BLACKLIST b/tests/auto/other/qfocusevent/BLACKLIST
index 502820fa12..0b03472587 100644
--- a/tests/auto/other/qfocusevent/BLACKLIST
+++ b/tests/auto/other/qfocusevent/BLACKLIST
@@ -2,4 +2,5 @@
osx-10.12 ci
[checkReason_ActiveWindow]
osx-10.12 ci
+winrt
diff --git a/tests/auto/other/qfocusevent/tst_qfocusevent.cpp b/tests/auto/other/qfocusevent/tst_qfocusevent.cpp
index ceac02279e..260ba12a97 100644
--- a/tests/auto/other/qfocusevent/tst_qfocusevent.cpp
+++ b/tests/auto/other/qfocusevent/tst_qfocusevent.cpp
@@ -351,9 +351,10 @@ void tst_QFocusEvent::checkReason_ActiveWindow()
d->hide();
if (!QGuiApplication::platformName().compare(QLatin1String("offscreen"), Qt::CaseInsensitive)
- || !QGuiApplication::platformName().compare(QLatin1String("minimal"), Qt::CaseInsensitive)) {
+ || !QGuiApplication::platformName().compare(QLatin1String("minimal"), Qt::CaseInsensitive)
+ || !QGuiApplication::platformName().compare(QLatin1String("winrt"), Qt::CaseInsensitive)) {
// Activate window of testFocusWidget, focus in that window goes to childFocusWidgetOne
- QWARN("Platforms offscreen and minimal require explicit activateWindow()");
+ QWARN("Platforms offscreen, minimal, and winrt require explicit activateWindow()");
testFocusWidget->activateWindow();
}
diff --git a/tests/auto/printsupport/dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp b/tests/auto/printsupport/dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp
index bb3624a51d..7f874a843d 100644
--- a/tests/auto/printsupport/dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp
+++ b/tests/auto/printsupport/dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp
@@ -101,8 +101,7 @@ void tst_QAbstractPrintDialog::setMinMax()
QPrinter printer;
MyAbstractPrintDialog obj1(&printer);
obj1.setEnabledOptions(QAbstractPrintDialog::PrintDialogOptions(QAbstractPrintDialog::None));
- QEXPECT_FAIL("", "QTBUG-22637", Abort);
- QCOMPARE(obj1.minPage(), 1);
+ QCOMPARE(obj1.minPage(), 0);
QCOMPARE(obj1.maxPage(), INT_MAX);
QVERIFY(!obj1.isOptionEnabled(QAbstractPrintDialog::PrintPageRange));
obj1.setMinMax(2,5);
diff --git a/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp b/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp
index 4f86e74117..a65dd0bf8f 100644
--- a/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp
+++ b/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp
@@ -1026,7 +1026,7 @@ void tst_QPrinter::duplex()
pdf.setOutputFormat(QPrinter::PdfFormat);
QCOMPARE(pdf.duplex(), QPrinter::DuplexNone);
pdf.setDuplex(QPrinter::DuplexAuto);
- QCOMPARE(pdf.duplex(), QPrinter::DuplexAuto);
+ QCOMPARE(pdf.duplex(), QPrinter::DuplexNone); // pdf doesn't have the concept of duplex
QPrinter native;
if (native.outputFormat() == QPrinter::NativeFormat) {
@@ -1071,7 +1071,7 @@ void tst_QPrinter::doubleSidedPrinting()
pdf.setOutputFormat(QPrinter::PdfFormat);
QCOMPARE(pdf.doubleSidedPrinting(), false);
pdf.setDoubleSidedPrinting(true);
- QCOMPARE(pdf.doubleSidedPrinting(), true);
+ QCOMPARE(pdf.doubleSidedPrinting(), false); // pdf doesn't have the concept of duplex
QPrinter native;
if (native.outputFormat() == QPrinter::NativeFormat) {
diff --git a/tests/auto/sql/kernel/qsqldriver/tst_qsqldriver.cpp b/tests/auto/sql/kernel/qsqldriver/tst_qsqldriver.cpp
index 7bfa29ec8e..15190b0f3e 100644
--- a/tests/auto/sql/kernel/qsqldriver/tst_qsqldriver.cpp
+++ b/tests/auto/sql/kernel/qsqldriver/tst_qsqldriver.cpp
@@ -54,6 +54,18 @@ private slots:
void formatValue();
};
+static bool driverSupportsDefaultValues(QSqlDriver::DbmsType dbType)
+{
+ switch (dbType) {
+ case QSqlDriver::SQLite:
+ case QSqlDriver::PostgreSQL:
+ case QSqlDriver::Oracle:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
void tst_QSqlDriver::initTestCase_data()
{
@@ -81,8 +93,9 @@ void tst_QSqlDriver::recreateTestTables(QSqlDatabase db)
doubleField = "more_data double precision";
else
doubleField = "more_data double(8,7)";
+ const QString defValue(driverSupportsDefaultValues(dbType) ? QStringLiteral("DEFAULT 'defaultVal'") : QString());
QVERIFY_SQL( q, exec("create table " + relTEST1 +
- " (id int not null primary key, name varchar(20), title_key int, another_title_key int, " + doubleField + QLatin1Char(')')));
+ " (id int not null primary key, name varchar(20) " + defValue + ", title_key int, another_title_key int, " + doubleField + QLatin1Char(')')));
QVERIFY_SQL( q, exec("insert into " + relTEST1 + " values(1, 'harry', 1, 2, 1.234567)"));
QVERIFY_SQL( q, exec("insert into " + relTEST1 + " values(2, 'trond', 2, 1, 8.901234)"));
QVERIFY_SQL( q, exec("insert into " + relTEST1 + " values(3, 'vohi', 1, 2, 5.678901)"));
@@ -127,7 +140,7 @@ void tst_QSqlDriver::record()
//check we can get records using an unquoted mixed case table name
QSqlRecord rec = db.driver()->record(tablename);
- QCOMPARE(rec.count(), 5);
+ QCOMPARE(rec.count(), fields.size());
QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
// QTBUG-1363: QSqlField::length() always return -1 when using QODBC3 driver and QSqlDatabase::record()
@@ -141,6 +154,9 @@ void tst_QSqlDriver::record()
for (int i = 0; i < fields.count(); ++i)
QCOMPARE(rec.fieldName(i), fields[i]);
+ if (driverSupportsDefaultValues(dbType))
+ QCOMPARE(rec.field(QStringLiteral("name")).defaultValue().toString(), QStringLiteral("defaultVal"));
+
if (dbType == QSqlDriver::Interbase || dbType == QSqlDriver::Oracle || dbType == QSqlDriver::DB2)
tablename = tablename.toUpper();
else if (dbType == QSqlDriver::PostgreSQL)
diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
index c64310a715..4ce1009c90 100644
--- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
+++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
@@ -180,6 +180,8 @@ private slots:
void timeStampParsing();
void sqliteVirtualTable_data() { generic_data("QSQLITE"); }
void sqliteVirtualTable();
+ void mysql_timeType_data() { generic_data("QMYSQL"); }
+ void mysql_timeType();
#ifdef NOT_READY_YET
void task_229811();
@@ -4722,5 +4724,58 @@ void tst_QSqlQuery::sqliteVirtualTable()
QCOMPARE(qry.value(1).toString(), "Peter");
}
+void tst_QSqlQuery::mysql_timeType()
+{
+ // The TIME data type is different to the standard with MySQL as it has a range of
+ // '-838:59:59' to '838:59:59'.
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+ const auto tableName = qTableName("mysqlTimeType", __FILE__, db);
+ tst_Databases::safeDropTables(db, { tableName });
+ QSqlQuery qry(db);
+ QVERIFY_SQL(qry, exec("create table " + tableName + " (t time(6))"));
+
+ // MySQL will convert days into hours and add them together so 17 days 11 hours becomes 419 hours
+ const QStringList timeData = { "-838:59:59.000000", "-123:45:56.789", "000:00:00.0", "123:45:56.789",
+ "838:59:59.000000", "15:50", "12", "1213", "0 1:2:3", "17 11:22:33" };
+ const QStringList resultTimeData = { "-838:59:59.000000", "-123:45:56.789000", "00:00:00.000000",
+ "123:45:56.789000", "838:59:59.000000", "15:50:00.000000", "00:00:12.000000", "00:12:13.000000",
+ "01:02:03.000000", "419:22:33.000000" };
+ for (const QString &time : timeData)
+ QVERIFY_SQL(qry, exec("insert into " + tableName + " (t) VALUES ('" + time + "')"));
+
+ QVERIFY_SQL(qry, exec("select * from " + tableName));
+ for (const QString &time : qAsConst(resultTimeData)) {
+ QVERIFY(qry.next());
+ QCOMPARE(qry.value(0).toString(), time);
+ }
+
+ QVERIFY_SQL(qry, exec("delete from " + tableName));
+ for (const QString &time : timeData) {
+ QVERIFY_SQL(qry, prepare("insert into " + tableName + " (t) VALUES (:time)"));
+ qry.bindValue(0, time);
+ QVERIFY_SQL(qry, exec());
+ }
+ QVERIFY_SQL(qry, exec("select * from " + tableName));
+ for (const QString &time : resultTimeData) {
+ QVERIFY(qry.next());
+ QCOMPARE(qry.value(0).toString(), time);
+ }
+
+ QVERIFY_SQL(qry, exec("delete from " + tableName));
+ const QList<QTime> qTimeBasedData = { QTime(), QTime(1, 2, 3, 4), QTime(0, 0, 0, 0), QTime(23,59,59,999) };
+ for (const QTime &time : qTimeBasedData) {
+ QVERIFY_SQL(qry, prepare("insert into " + tableName + " (t) VALUES (:time)"));
+ qry.bindValue(0, time);
+ QVERIFY_SQL(qry, exec());
+ }
+ QVERIFY_SQL(qry, exec("select * from " + tableName));
+ for (const QTime &time : qTimeBasedData) {
+ QVERIFY(qry.next());
+ QCOMPARE(qry.value(0).toTime(), time);
+ }
+}
+
QTEST_MAIN( tst_QSqlQuery )
#include "tst_qsqlquery.moc"
diff --git a/tests/auto/sql/kernel/qsqlresult/qsqlresult.pro b/tests/auto/sql/kernel/qsqlresult/qsqlresult.pro
index 2e4c3f998d..5c567ad771 100644
--- a/tests/auto/sql/kernel/qsqlresult/qsqlresult.pro
+++ b/tests/auto/sql/kernel/qsqlresult/qsqlresult.pro
@@ -6,5 +6,3 @@ QT = core core-private sql sql-private testlib
SOURCES += tst_qsqlresult.cpp
HEADERS += testsqldriver.h
-mingw: LIBS += -lws2_32
-
diff --git a/tests/auto/sql/kernel/qsqlthread/tst_qsqlthread.cpp b/tests/auto/sql/kernel/qsqlthread/tst_qsqlthread.cpp
index 5482dc393b..09a842eb83 100644
--- a/tests/auto/sql/kernel/qsqlthread/tst_qsqlthread.cpp
+++ b/tests/auto/sql/kernel/qsqlthread/tst_qsqlthread.cpp
@@ -401,8 +401,10 @@ void tst_QSqlThread::readWriteThreading()
QTRY_VERIFY_WITH_TIMEOUT(threadFinishedCount >= 2, 10000);
}
+#ifdef QOCI_THREADED
// run with n threads in parallel. Change this constant to hammer the poor DB server even more
static const int maxThreadCount = 4;
+#endif
void tst_QSqlThread::readFromSingleConnection()
{
diff --git a/tests/auto/sql/models/qsqlrelationaldelegate/qsqlrelationaldelegate.pro b/tests/auto/sql/models/qsqlrelationaldelegate/qsqlrelationaldelegate.pro
new file mode 100644
index 0000000000..d911a46259
--- /dev/null
+++ b/tests/auto/sql/models/qsqlrelationaldelegate/qsqlrelationaldelegate.pro
@@ -0,0 +1,5 @@
+CONFIG += testcase
+TARGET = tst_qsqlrelationaldelegate
+SOURCES += tst_qsqlrelationaldelegate.cpp
+
+QT = core sql testlib core-private sql-private widgets
diff --git a/tests/auto/sql/models/qsqlrelationaldelegate/tst_qsqlrelationaldelegate.cpp b/tests/auto/sql/models/qsqlrelationaldelegate/tst_qsqlrelationaldelegate.cpp
new file mode 100644
index 0000000000..36f592395e
--- /dev/null
+++ b/tests/auto/sql/models/qsqlrelationaldelegate/tst_qsqlrelationaldelegate.cpp
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtSql/QtSql>
+#include <QTableView>
+#include <QComboBox>
+
+#include "../../kernel/qsqldatabase/tst_databases.h"
+
+const QString reltest1(qTableName("reltest1", __FILE__, QSqlDatabase())),
+ reltest2(qTableName("reltest2", __FILE__, QSqlDatabase()));
+
+class tst_QSqlRelationalDelegate : public QObject
+{
+ Q_OBJECT
+
+public:
+ void recreateTestTables(QSqlDatabase);
+
+ tst_Databases dbs;
+
+public slots:
+ void initTestCase_data();
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void comboBoxEditor();
+private:
+ void dropTestTables(QSqlDatabase db);
+};
+
+
+void tst_QSqlRelationalDelegate::initTestCase_data()
+{
+ QVERIFY(dbs.open());
+ if (dbs.fillTestTable() == 0)
+ QSKIP("No database drivers are available in this Qt configuration");
+}
+
+void tst_QSqlRelationalDelegate::recreateTestTables(QSqlDatabase db)
+{
+ dropTestTables(db);
+
+ QSqlQuery q(db);
+ QVERIFY_SQL(q, exec("create table " + reltest1 +
+ " (id int not null primary key, name varchar(20), title_key int, another_title_key int)"));
+ QVERIFY_SQL(q, exec("insert into " + reltest1 + " values(1, 'harry', 1, 2)"));
+ QVERIFY_SQL(q, exec("insert into " + reltest1 + " values(2, 'trond', 2, 1)"));
+ QVERIFY_SQL(q, exec("insert into " + reltest1 + " values(3, 'vohi', 1, 2)"));
+ QVERIFY_SQL(q, exec("insert into " + reltest1 + " values(4, 'boris', 2, 2)"));
+ QVERIFY_SQL(q, exec("insert into " + reltest1 + " values(5, 'nat', NULL, NULL)"));
+ QVERIFY_SQL(q, exec("insert into " + reltest1 + " values(6, 'ale', NULL, 2)"));
+
+ QVERIFY_SQL(q, exec("create table " + reltest2 + " (id int not null primary key, title varchar(20))"));
+ QVERIFY_SQL(q, exec("insert into " + reltest2 + " values(1, 'herr')"));
+ QVERIFY_SQL(q, exec("insert into " + reltest2 + " values(2, 'mister')"));
+}
+
+void tst_QSqlRelationalDelegate::initTestCase()
+{
+ foreach (const QString &dbname, dbs.dbNames) {
+ QSqlDatabase db=QSqlDatabase::database(dbname);
+ QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db);
+ if (dbType == QSqlDriver::Interbase) {
+ db.exec("SET DIALECT 3");
+ } else if (dbType == QSqlDriver::MSSqlServer) {
+ db.exec("SET ANSI_DEFAULTS ON");
+ db.exec("SET IMPLICIT_TRANSACTIONS OFF");
+ } else if (dbType == QSqlDriver::PostgreSQL) {
+ db.exec("set client_min_messages='warning'");
+ }
+ recreateTestTables(db);
+ }
+}
+
+void tst_QSqlRelationalDelegate::cleanupTestCase()
+{
+ foreach (const QString &dbName, dbs.dbNames) {
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+ dropTestTables(QSqlDatabase::database(dbName));
+ }
+ dbs.close();
+}
+
+void tst_QSqlRelationalDelegate::dropTestTables(QSqlDatabase db)
+{
+ QStringList tableNames = { reltest1, reltest2 };
+ tst_Databases::safeDropTables(db, tableNames);
+}
+
+void tst_QSqlRelationalDelegate::init()
+{
+}
+
+void tst_QSqlRelationalDelegate::cleanup()
+{
+}
+
+void tst_QSqlRelationalDelegate::comboBoxEditor()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QTableView tv;
+ QSqlRelationalTableModel model(0, db);
+ model.setEditStrategy(QSqlTableModel::OnManualSubmit);
+ model.setTable(reltest1);
+ model.setRelation(2, QSqlRelation(reltest2, "id", "title"));
+ model.setRelation(3, QSqlRelation(reltest2, "id", "title"));
+ tv.setModel(&model);
+ QVERIFY_SQL(model, select());
+
+ QSqlRelationalDelegate delegate;
+ tv.setItemDelegate(&delegate);
+ tv.show();
+ QVERIFY(QTest::qWaitForWindowActive(&tv));
+
+ QModelIndex index = model.index(0, 2);
+ tv.setCurrentIndex(index);
+ tv.edit(index);
+ QList<QComboBox*> comboBoxes = tv.viewport()->findChildren<QComboBox *>();
+ QCOMPARE(comboBoxes.count(), 1);
+
+ QComboBox *editor = comboBoxes.at(0);
+ QCOMPARE(editor->currentText(), "herr");
+ QTest::keyClick(editor, Qt::Key_Down);
+ QTest::keyClick(editor, Qt::Key_Enter);
+ QCOMPARE(editor->currentText(), "mister");
+ QVERIFY_SQL(model, submitAll());
+
+ QSqlQuery qry(db);
+ QVERIFY_SQL(qry, exec("SELECT title_key FROM " + reltest1 + " WHERE id=1"));
+ QVERIFY(qry.next());
+ QCOMPARE(qry.value(0).toString(), "mister");
+}
+
+QTEST_MAIN(tst_QSqlRelationalDelegate)
+#include "tst_qsqlrelationaldelegate.moc"
diff --git a/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp b/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp
index 430fa981d5..da31f437d9 100644
--- a/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp
+++ b/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp
@@ -31,11 +31,29 @@
#include "../../kernel/qsqldatabase/tst_databases.h"
#include <QtSql>
#include <QtSql/private/qsqltablemodel_p.h>
+#include <QThread>
const QString test(qTableName("test", __FILE__, QSqlDatabase())),
test2(qTableName("test2", __FILE__, QSqlDatabase())),
test3(qTableName("test3", __FILE__, QSqlDatabase()));
+// In order to catch when the warning message occurs, indicating that the database belongs to another
+// thread, we have to install our own message handler. To ensure that the test reporting still happens
+// as before, we call the originating one.
+//
+// For now, this is only called inside the modelInAnotherThread() test
+QtMessageHandler oldHandler = nullptr;
+
+void sqlTableModelMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
+{
+ if (type == QtWarningMsg &&
+ msg == "QSqlDatabasePrivate::database: requested database does not "
+ "belong to the calling thread.") {
+ QFAIL("Requested database does not belong to the calling thread.");
+ }
+ if (oldHandler)
+ oldHandler(type, context, msg);
+}
class tst_QSqlTableModel : public QObject
{
@@ -116,6 +134,7 @@ private slots:
void sqlite_bigTable_data() { generic_data("QSQLITE"); }
void sqlite_bigTable();
+ void modelInAnotherThread();
// bug specific tests
void insertRecordBeforeSelect_data() { generic_data(); }
@@ -276,6 +295,10 @@ void tst_QSqlTableModel::init()
void tst_QSqlTableModel::cleanup()
{
recreateTestTables();
+ if (oldHandler) {
+ qInstallMessageHandler(oldHandler);
+ oldHandler = nullptr;
+ }
}
void tst_QSqlTableModel::select()
@@ -2100,5 +2123,29 @@ void tst_QSqlTableModel::invalidFilterAndHeaderData()
QVERIFY(!v.isValid());
}
+class SqlThread : public QThread
+{
+public:
+ SqlThread() : QThread() {}
+ void run()
+ {
+ QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "non-default-connection");
+ QSqlTableModel stm(nullptr, db);
+ isDone = true;
+ }
+ bool isDone = false;
+};
+
+void tst_QSqlTableModel::modelInAnotherThread()
+{
+ oldHandler = qInstallMessageHandler(sqlTableModelMessageHandler);
+ QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
+ CHECK_DATABASE(db);
+ SqlThread t;
+ t.start();
+ QTRY_VERIFY(t.isDone);
+ QVERIFY(t.isFinished());
+}
+
QTEST_MAIN(tst_QSqlTableModel)
#include "tst_qsqltablemodel.moc"
diff --git a/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp b/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
index a662fea615..8e2c7694a5 100644
--- a/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+++ b/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
@@ -130,6 +130,10 @@ private slots:
void compare_unregistered_enums();
void compare_registered_enums();
void compare_class_enums();
+ void test_windowflags_data();
+ void test_windowflags();
+ void test_unregistered_flags_data();
+ void test_unregistered_flags();
void compare_boolfuncs();
void compare_to_nullptr();
void compare_pointerfuncs();
@@ -180,6 +184,64 @@ void tst_Cmptest::compare_class_enums()
QCOMPARE(MyClassEnum::MyClassEnumValue1, MyClassEnum::MyClassEnumValue2);
}
+void tst_Cmptest::test_windowflags_data()
+{
+ QTest::addColumn<Qt::WindowFlags>("actualWindowFlags");
+ QTest::addColumn<Qt::WindowFlags>("expectedWindowFlags");
+
+ const Qt::WindowFlags windowFlags = Qt::Window
+ | Qt::WindowSystemMenuHint | Qt::WindowStaysOnBottomHint;
+ QTest::newRow("pass")
+ << windowFlags
+ << windowFlags;
+ QTest::newRow("fail1")
+ << windowFlags
+ << (windowFlags | Qt::FramelessWindowHint);
+ QTest::newRow("fail2")
+ << Qt::WindowFlags(Qt::Window)
+ << Qt::WindowFlags(Qt::Window | Qt::FramelessWindowHint);
+}
+
+void tst_Cmptest::test_windowflags()
+{
+ QFETCH(Qt::WindowFlags, actualWindowFlags);
+ QFETCH(Qt::WindowFlags, expectedWindowFlags);
+ QCOMPARE(actualWindowFlags, expectedWindowFlags);
+}
+
+enum UnregisteredEnum {
+ UnregisteredEnumValue1 = 0x1,
+ UnregisteredEnumValue2 = 0x2,
+ UnregisteredEnumValue3 = 0x4
+};
+
+typedef QFlags<UnregisteredEnum> UnregisteredFlags;
+
+Q_DECLARE_METATYPE(UnregisteredFlags);
+
+void tst_Cmptest::test_unregistered_flags_data()
+{
+ QTest::addColumn<UnregisteredFlags>("actualFlags");
+ QTest::addColumn<UnregisteredFlags>("expectedFlags");
+
+ QTest::newRow("pass")
+ << UnregisteredFlags(UnregisteredEnumValue1)
+ << UnregisteredFlags(UnregisteredEnumValue1);
+ QTest::newRow("fail1")
+ << UnregisteredFlags(UnregisteredEnumValue1 | UnregisteredEnumValue2)
+ << UnregisteredFlags(UnregisteredEnumValue1 | UnregisteredEnumValue3);
+ QTest::newRow("fail2")
+ << UnregisteredFlags(UnregisteredEnumValue1)
+ << UnregisteredFlags(UnregisteredEnumValue1 | UnregisteredEnumValue3);
+}
+
+void tst_Cmptest::test_unregistered_flags()
+{
+ QFETCH(UnregisteredFlags, actualFlags);
+ QFETCH(UnregisteredFlags, expectedFlags);
+ QCOMPARE(actualFlags, expectedFlags);
+}
+
static bool boolfunc() { return true; }
static bool boolfunc2() { return true; }
diff --git a/tests/auto/testlib/selftests/expected_assert.tap b/tests/auto/testlib/selftests/expected_assert.tap
new file mode 100644
index 0000000000..4cd26848ac
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_assert.tap
@@ -0,0 +1,16 @@
+TAP version 13
+# tst_Assert
+ok 1 - initTestCase()
+ok 2 - testNumber1()
+# ASSERT: "false" in file qtbase/tests/auto/testlib/selftests/assert/tst_assert.cpp, line 0
+not ok 3 - testNumber2()
+ ---
+ # Received a fatal error.
+ at: tst_Assert::testNumber2() (Unknown file:0)
+ file: Unknown file
+ line: 0
+ ...
+1..3
+# tests 3
+# pass 2
+# fail 1
diff --git a/tests/auto/testlib/selftests/expected_badxml.tap b/tests/auto/testlib/selftests/expected_badxml.tap
new file mode 100644
index 0000000000..7aa4f11829
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_badxml.tap
@@ -0,0 +1,61 @@
+TAP version 13
+# tst_BadXml
+ok 1 - initTestCase()
+# a message
+not ok 2 - badDataTag(fail end cdata ]]> text ]]> more text)
+ ---
+ # a failure
+ at: tst_BadXml::badDataTag() (qtbase/tests/auto/testlib/selftests/badxml/tst_badxml.cpp:101)
+ file: qtbase/tests/auto/testlib/selftests/badxml/tst_badxml.cpp
+ line: 101
+ ...
+# a message
+ok 3 - badDataTag(pass end cdata ]]> text ]]> more text)
+# a message
+not ok 4 - badDataTag(fail quotes " text" more text)
+ ---
+ # a failure
+ at: tst_BadXml::badDataTag() (qtbase/tests/auto/testlib/selftests/badxml/tst_badxml.cpp:101)
+ file: qtbase/tests/auto/testlib/selftests/badxml/tst_badxml.cpp
+ line: 101
+ ...
+# a message
+ok 5 - badDataTag(pass quotes " text" more text)
+# a message
+not ok 6 - badDataTag(fail xml close > open < tags < text)
+ ---
+ # a failure
+ at: tst_BadXml::badDataTag() (qtbase/tests/auto/testlib/selftests/badxml/tst_badxml.cpp:101)
+ file: qtbase/tests/auto/testlib/selftests/badxml/tst_badxml.cpp
+ line: 101
+ ...
+# a message
+ok 7 - badDataTag(pass xml close > open < tags < text)
+# a message
+not ok 8 - badDataTag(fail all > " mixed ]]> up > " in < the ]]> hopes < of triggering "< ]]> bugs)
+ ---
+ # a failure
+ at: tst_BadXml::badDataTag() (qtbase/tests/auto/testlib/selftests/badxml/tst_badxml.cpp:101)
+ file: qtbase/tests/auto/testlib/selftests/badxml/tst_badxml.cpp
+ line: 101
+ ...
+# a message
+ok 9 - badDataTag(pass all > " mixed ]]> up > " in < the ]]> hopes < of triggering "< ]]> bugs)
+# end cdata ]]> text ]]> more text
+ok 10 - badMessage(string 0)
+# quotes " text" more text
+ok 11 - badMessage(string 1)
+# xml close > open < tags < text
+ok 12 - badMessage(string 2)
+# all > " mixed ]]> up > " in < the ]]> hopes < of triggering "< ]]> bugs
+ok 13 - badMessage(string 3)
+not ok 14 - failWithNoFile()
+ ---
+ # failure message
+ ...
+ok 15 - encoding() # SKIP Skipped for text due to unpredictable console encoding.
+ok 16 - cleanupTestCase()
+1..16
+# tests 16
+# pass 10
+# fail 5
diff --git a/tests/auto/testlib/selftests/expected_benchlibcounting.tap b/tests/auto/testlib/selftests/expected_benchlibcounting.tap
new file mode 100644
index 0000000000..e7a4280278
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_benchlibcounting.tap
@@ -0,0 +1,17 @@
+TAP version 13
+# tst_BenchlibCounting
+ok 1 - initTestCase()
+ok 2 - passingBenchmark()
+ok 3 - skippingBenchmark() # SKIP This is a skipping benchmark
+not ok 4 - failingBenchmark()
+ ---
+ # This is a failing benchmark
+ at: tst_BenchlibCounting::failingBenchmark() (qtbase/tests/auto/testlib/selftests/benchlibcounting/tst_benchlibcounting.cpp:58)
+ file: qtbase/tests/auto/testlib/selftests/benchlibcounting/tst_benchlibcounting.cpp
+ line: 58
+ ...
+ok 5 - cleanupTestCase()
+1..5
+# tests 5
+# pass 3
+# fail 1
diff --git a/tests/auto/testlib/selftests/expected_benchlibeventcounter.tap b/tests/auto/testlib/selftests/expected_benchlibeventcounter.tap
new file mode 100644
index 0000000000..02c65e59da
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_benchlibeventcounter.tap
@@ -0,0 +1,15 @@
+TAP version 13
+# tst_BenchlibEventCounter
+ok 1 - initTestCase()
+ok 2 - events(0)
+ok 3 - events(1)
+ok 4 - events(10)
+ok 5 - events(100)
+ok 6 - events(500)
+ok 7 - events(5000)
+ok 8 - events(100000)
+ok 9 - cleanupTestCase()
+1..9
+# tests 9
+# pass 9
+# fail 0
diff --git a/tests/auto/testlib/selftests/expected_benchlibtickcounter.tap b/tests/auto/testlib/selftests/expected_benchlibtickcounter.tap
new file mode 100644
index 0000000000..85d7f10ea0
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_benchlibtickcounter.tap
@@ -0,0 +1,9 @@
+TAP version 13
+# tst_BenchlibTickCounter
+ok 1 - initTestCase()
+ok 2 - threeBillionTicks()
+ok 3 - cleanupTestCase()
+1..3
+# tests 3
+# pass 3
+# fail 0
diff --git a/tests/auto/testlib/selftests/expected_benchlibwalltime.tap b/tests/auto/testlib/selftests/expected_benchlibwalltime.tap
new file mode 100644
index 0000000000..7653ccbeb3
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_benchlibwalltime.tap
@@ -0,0 +1,11 @@
+TAP version 13
+# tst_BenchlibWalltime
+ok 1 - initTestCase()
+ok 2 - waitForOneThousand()
+ok 3 - waitForFourThousand()
+ok 4 - qbenchmark_once()
+ok 5 - cleanupTestCase()
+1..5
+# tests 5
+# pass 5
+# fail 0
diff --git a/tests/auto/testlib/selftests/expected_cmptest.lightxml b/tests/auto/testlib/selftests/expected_cmptest.lightxml
index d47967a445..58b5a5e530 100644
--- a/tests/auto/testlib/selftests/expected_cmptest.lightxml
+++ b/tests/auto/testlib/selftests/expected_cmptest.lightxml
@@ -29,6 +29,42 @@
</Incident>
<Duration msecs="0"/>
</TestFunction>
+<TestFunction name="test_windowflags">
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[pass]]></DataTag>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="0">
+ <DataTag><![CDATA[fail1]]></DataTag>
+ <Description><![CDATA[Compared values are not the same
+ Actual (actualWindowFlags) : Window|WindowSystemMenuHint|WindowStaysOnBottomHint
+ Expected (expectedWindowFlags): Window|FramelessWindowHint|WindowSystemMenuHint|WindowStaysOnBottomHint]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="0">
+ <DataTag><![CDATA[fail2]]></DataTag>
+ <Description><![CDATA[Compared values are not the same
+ Actual (actualWindowFlags) : Window
+ Expected (expectedWindowFlags): Window|FramelessWindowHint]]></Description>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="test_unregistered_flags">
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[pass]]></DataTag>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="0">
+ <DataTag><![CDATA[fail1]]></DataTag>
+ <Description><![CDATA[Compared values are not the same
+ Actual (actualFlags) : 0x3
+ Expected (expectedFlags): 0x5]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="0">
+ <DataTag><![CDATA[fail2]]></DataTag>
+ <Description><![CDATA[Compared values are not the same
+ Actual (actualFlags) : 0x1
+ Expected (expectedFlags): 0x5]]></Description>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
<TestFunction name="compare_boolfuncs">
<Incident type="pass" file="" line="0" />
<Duration msecs="0"/>
diff --git a/tests/auto/testlib/selftests/expected_cmptest.tap b/tests/auto/testlib/selftests/expected_cmptest.tap
new file mode 100644
index 0000000000..238db2fc2b
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_cmptest.tap
@@ -0,0 +1,456 @@
+TAP version 13
+# tst_Cmptest
+ok 1 - initTestCase()
+not ok 2 - compare_unregistered_enums()
+ ---
+ # Compared values are not the same
+ at: tst_Cmptest::compare_unregistered_enums() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:171)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 171
+ ...
+not ok 3 - compare_registered_enums()
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: Sunday (Qt::Sunday)
+ found: Monday (Qt::Monday)
+ expected: Sunday (Qt::Sunday)
+ actual: Monday (Qt::Monday)
+ at: tst_Cmptest::compare_registered_enums() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:178)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 178
+ ...
+not ok 4 - compare_class_enums()
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: MyClassEnumValue2 (MyClassEnum::MyClassEnumValue2)
+ found: MyClassEnumValue1 (MyClassEnum::MyClassEnumValue1)
+ expected: MyClassEnumValue2 (MyClassEnum::MyClassEnumValue2)
+ actual: MyClassEnumValue1 (MyClassEnum::MyClassEnumValue1)
+ at: tst_Cmptest::compare_class_enums() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:184)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 184
+ ...
+ok 5 - test_windowflags(pass)
+not ok 6 - test_windowflags(fail1)
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: Window|FramelessWindowHint|WindowSystemMenuHint|WindowStaysOnBottomHint (expectedWindowFlags)
+ found: Window|WindowSystemMenuHint|WindowStaysOnBottomHint (actualWindowFlags)
+ expected: Window|FramelessWindowHint|WindowSystemMenuHint|WindowStaysOnBottomHint (expectedWindowFlags)
+ actual: Window|WindowSystemMenuHint|WindowStaysOnBottomHint (actualWindowFlags)
+ at: tst_Cmptest::test_windowflags() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:209)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 209
+ ...
+not ok 7 - test_windowflags(fail2)
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: Window|FramelessWindowHint (expectedWindowFlags)
+ found: Window (actualWindowFlags)
+ expected: Window|FramelessWindowHint (expectedWindowFlags)
+ actual: Window (actualWindowFlags)
+ at: tst_Cmptest::test_windowflags() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:209)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 209
+ ...
+ok 8 - test_unregistered_flags(pass)
+not ok 9 - test_unregistered_flags(fail1)
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: 0x5 (expectedFlags)
+ found: 0x3 (actualFlags)
+ expected: 0x5 (expectedFlags)
+ actual: 0x3 (actualFlags)
+ at: tst_Cmptest::test_unregistered_flags() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:242)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 242
+ ...
+not ok 10 - test_unregistered_flags(fail2)
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: 0x5 (expectedFlags)
+ found: 0x1 (actualFlags)
+ expected: 0x5 (expectedFlags)
+ actual: 0x1 (actualFlags)
+ at: tst_Cmptest::test_unregistered_flags() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:242)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 242
+ ...
+ok 11 - compare_boolfuncs()
+ok 12 - compare_to_nullptr()
+ok 13 - compare_pointerfuncs()
+not ok 14 - compare_tostring(int, string)
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: QVariant(QString,hi) (expected)
+ found: QVariant(int,123) (actual)
+ expected: QVariant(QString,hi) (expected)
+ actual: QVariant(int,123) (actual)
+ at: tst_Cmptest::compare_tostring() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:331)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 331
+ ...
+ok 15 - compare_tostring(both invalid)
+not ok 16 - compare_tostring(null hash, invalid)
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: QVariant() (expected)
+ found: QVariant(QVariantHash) (actual)
+ expected: QVariant() (expected)
+ actual: QVariant(QVariantHash) (actual)
+ at: tst_Cmptest::compare_tostring() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:331)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 331
+ ...
+not ok 17 - compare_tostring(string, null user type)
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: QVariant(PhonyClass) (expected)
+ found: QVariant(QString,A simple string) (actual)
+ expected: QVariant(PhonyClass) (expected)
+ actual: QVariant(QString,A simple string) (actual)
+ at: tst_Cmptest::compare_tostring() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:331)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 331
+ ...
+not ok 18 - compare_tostring(both non-null user type)
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: QVariant(PhonyClass,<value not representable as string>) (expected)
+ found: QVariant(PhonyClass,<value not representable as string>) (actual)
+ expected: QVariant(PhonyClass,<value not representable as string>) (expected)
+ actual: QVariant(PhonyClass,<value not representable as string>) (actual)
+ at: tst_Cmptest::compare_tostring() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:331)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 331
+ ...
+ok 19 - compareQStringLists(empty lists)
+ok 20 - compareQStringLists(equal lists)
+not ok 21 - compareQStringLists(last item different)
+ ---
+ type: QCOMPARE
+ message: Compared lists differ at index 2.
+ wanted: "DIFFERS" (opB)
+ found: "string3" (opA)
+ expected: "DIFFERS" (opB)
+ actual: "string3" (opA)
+ at: tst_Cmptest::compareQStringLists() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:425)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 425
+ ...
+not ok 22 - compareQStringLists(second-last item different)
+ ---
+ type: QCOMPARE
+ message: Compared lists differ at index 2.
+ wanted: "DIFFERS" (opB)
+ found: "string3" (opA)
+ expected: "DIFFERS" (opB)
+ actual: "string3" (opA)
+ at: tst_Cmptest::compareQStringLists() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:425)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 425
+ ...
+not ok 23 - compareQStringLists(prefix)
+ ---
+ # Compared lists have different sizes.
+ Actual (opA) size: 2
+ Expected (opB) size: 1
+ at: tst_Cmptest::compareQStringLists() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:425)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 425
+ ...
+not ok 24 - compareQStringLists(short list second)
+ ---
+ # Compared lists have different sizes.
+ Actual (opA) size: 12
+ Expected (opB) size: 1
+ at: tst_Cmptest::compareQStringLists() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:425)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 425
+ ...
+not ok 25 - compareQStringLists(short list first)
+ ---
+ # Compared lists have different sizes.
+ Actual (opA) size: 1
+ Expected (opB) size: 12
+ at: tst_Cmptest::compareQStringLists() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:425)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 425
+ ...
+not ok 26 - compareQListInt()
+ ---
+ type: QCOMPARE
+ message: Compared lists differ at index 2.
+ wanted: 4 (int2)
+ found: 3 (int1)
+ expected: 4 (int2)
+ actual: 3 (int1)
+ at: tst_Cmptest::compareQListInt() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:432)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 432
+ ...
+not ok 27 - compareQListDouble()
+ ---
+ type: QCOMPARE
+ message: Compared lists differ at index 0.
+ wanted: 1 (double2)
+ found: 1.5 (double1)
+ expected: 1 (double2)
+ actual: 1.5 (double1)
+ at: tst_Cmptest::compareQListDouble() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:439)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 439
+ ...
+ok 28 - compareQColor(Qt::yellow vs "yellow")
+not ok 29 - compareQColor(Qt::yellow vs Qt::green)
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: #ff00ff00 (colorB)
+ found: #ffffff00 (colorA)
+ expected: #ff00ff00 (colorB)
+ actual: #ffffff00 (colorA)
+ at: tst_Cmptest::compareQColor() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:458)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 458
+ ...
+not ok 30 - compareQColor(0x88ff0000 vs 0xffff0000)
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: #ffff0000 (colorB)
+ found: #88ff0000 (colorA)
+ expected: #ffff0000 (colorB)
+ actual: #88ff0000 (colorA)
+ at: tst_Cmptest::compareQColor() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:458)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 458
+ ...
+ok 31 - compareQPixmaps(both null)
+not ok 32 - compareQPixmaps(one null)
+ ---
+ type: QCOMPARE
+ message: Compared QPixmaps differ.
+ wanted: 0 (opB).isNull()
+ found: 1 (opA).isNull()
+ expected: 0 (opB).isNull()
+ actual: 1 (opA).isNull()
+ at: tst_Cmptest::compareQPixmaps() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:483)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 483
+ ...
+not ok 33 - compareQPixmaps(other null)
+ ---
+ type: QCOMPARE
+ message: Compared QPixmaps differ.
+ wanted: 1 (opB).isNull()
+ found: 0 (opA).isNull()
+ expected: 1 (opB).isNull()
+ actual: 0 (opA).isNull()
+ at: tst_Cmptest::compareQPixmaps() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:483)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 483
+ ...
+ok 34 - compareQPixmaps(equal)
+not ok 35 - compareQPixmaps(different size)
+ ---
+ type: QCOMPARE
+ message: Compared QPixmaps differ in size.
+ wanted: 20x20 (opB)
+ found: 11x20 (opA)
+ expected: 20x20 (opB)
+ actual: 11x20 (opA)
+ at: tst_Cmptest::compareQPixmaps() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:483)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 483
+ ...
+not ok 36 - compareQPixmaps(different pixels)
+ ---
+ # Compared values are not the same
+ at: tst_Cmptest::compareQPixmaps() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:483)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 483
+ ...
+ok 37 - compareQImages(both null)
+not ok 38 - compareQImages(one null)
+ ---
+ type: QCOMPARE
+ message: Compared QImages differ.
+ wanted: 0 (opB).isNull()
+ found: 1 (opA).isNull()
+ expected: 0 (opB).isNull()
+ actual: 1 (opA).isNull()
+ at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:510)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 510
+ ...
+not ok 39 - compareQImages(other null)
+ ---
+ type: QCOMPARE
+ message: Compared QImages differ.
+ wanted: 1 (opB).isNull()
+ found: 0 (opA).isNull()
+ expected: 1 (opB).isNull()
+ actual: 0 (opA).isNull()
+ at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:510)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 510
+ ...
+ok 40 - compareQImages(equal)
+not ok 41 - compareQImages(different size)
+ ---
+ type: QCOMPARE
+ message: Compared QImages differ in size.
+ wanted: 20x20 (opB)
+ found: 11x20 (opA)
+ expected: 20x20 (opB)
+ actual: 11x20 (opA)
+ at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:510)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 510
+ ...
+not ok 42 - compareQImages(different format)
+ ---
+ type: QCOMPARE
+ message: Compared QImages differ in format.
+ wanted: 3 (opB)
+ found: 6 (opA)
+ expected: 3 (opB)
+ actual: 6 (opA)
+ at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:510)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 510
+ ...
+not ok 43 - compareQImages(different pixels)
+ ---
+ # Compared values are not the same
+ at: tst_Cmptest::compareQImages() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:510)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 510
+ ...
+ok 44 - compareQRegion(equal-empty)
+not ok 45 - compareQRegion(1-empty)
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: QRegion(null) (rB)
+ found: QRegion(200x50+10+10) (rA)
+ expected: QRegion(null) (rB)
+ actual: QRegion(200x50+10+10) (rA)
+ at: tst_Cmptest::compareQRegion() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:533)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 533
+ ...
+ok 46 - compareQRegion(equal)
+not ok 47 - compareQRegion(different lists)
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: QRegion(2 rectangles, 50x200+100+200, 200x50+10+10) (rB)
+ found: QRegion(200x50+10+10) (rA)
+ expected: QRegion(2 rectangles, 50x200+100+200, 200x50+10+10) (rB)
+ actual: QRegion(200x50+10+10) (rA)
+ at: tst_Cmptest::compareQRegion() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:533)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 533
+ ...
+not ok 48 - compareQVector2D()
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: QVector2D(1, 3) (v2b)
+ found: QVector2D(1, 2) (v2a)
+ expected: QVector2D(1, 3) (v2b)
+ actual: QVector2D(1, 2) (v2a)
+ at: tst_Cmptest::compareQVector2D() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:542)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 542
+ ...
+not ok 49 - compareQVector3D()
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: QVector3D(1, 3, 3) (v3b)
+ found: QVector3D(1, 2, 3) (v3a)
+ expected: QVector3D(1, 3, 3) (v3b)
+ actual: QVector3D(1, 2, 3) (v3a)
+ at: tst_Cmptest::compareQVector3D() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:551)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 551
+ ...
+not ok 50 - compareQVector4D()
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: QVector4D(1, 3, 3, 4) (v4b)
+ found: QVector4D(1, 2, 3, 4) (v4a)
+ expected: QVector4D(1, 3, 3, 4) (v4b)
+ actual: QVector4D(1, 2, 3, 4) (v4a)
+ at: tst_Cmptest::compareQVector4D() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:560)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 560
+ ...
+not ok 51 - verify()
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (opaqueFunc() < 2)
+ found: false (opaqueFunc() < 2)
+ expected: true (opaqueFunc() < 2)
+ actual: false (opaqueFunc() < 2)
+ at: tst_Cmptest::verify() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:572)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 572
+ ...
+not ok 52 - verify2()
+ ---
+ type: QVERIFY
+ message: 42
+ wanted: true (opaqueFunc() < 2)
+ found: false (opaqueFunc() < 2)
+ expected: true (opaqueFunc() < 2)
+ actual: false (opaqueFunc() < 2)
+ at: tst_Cmptest::verify2() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:578)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 578
+ ...
+not ok 53 - tryVerify()
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (opaqueFunc() < 2)
+ found: false (opaqueFunc() < 2)
+ expected: true (opaqueFunc() < 2)
+ actual: false (opaqueFunc() < 2)
+ at: tst_Cmptest::tryVerify() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:584)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 584
+ ...
+not ok 54 - tryVerify2()
+ ---
+ type: QVERIFY
+ message: 42
+ wanted: true (opaqueFunc() < 2)
+ found: false (opaqueFunc() < 2)
+ expected: true (opaqueFunc() < 2)
+ actual: false (opaqueFunc() < 2)
+ at: tst_Cmptest::tryVerify2() (qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp:590)
+ file: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp
+ line: 590
+ ...
+ok 55 - verifyExplicitOperatorBool()
+ok 56 - cleanupTestCase()
+1..56
+# tests 56
+# pass 18
+# fail 38
diff --git a/tests/auto/testlib/selftests/expected_cmptest.teamcity b/tests/auto/testlib/selftests/expected_cmptest.teamcity
index a0dc509279..422d0cbfdf 100644
--- a/tests/auto/testlib/selftests/expected_cmptest.teamcity
+++ b/tests/auto/testlib/selftests/expected_cmptest.teamcity
@@ -10,6 +10,22 @@
##teamcity[testStarted name='compare_class_enums()' flowId='tst_Cmptest']
##teamcity[testFailed name='compare_class_enums()' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)|]' details='Compared values are not the same|n Actual (MyClassEnum::MyClassEnumValue1): MyClassEnumValue1|n Expected (MyClassEnum::MyClassEnumValue2): MyClassEnumValue2' flowId='tst_Cmptest']
##teamcity[testFinished name='compare_class_enums()' flowId='tst_Cmptest']
+##teamcity[testStarted name='test_windowflags(pass)' flowId='tst_Cmptest']
+##teamcity[testFinished name='test_windowflags(pass)' flowId='tst_Cmptest']
+##teamcity[testStarted name='test_windowflags(fail1)' flowId='tst_Cmptest']
+##teamcity[testFailed name='test_windowflags(fail1)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)|]' details='Compared values are not the same|n Actual (actualWindowFlags) : Window||WindowSystemMenuHint||WindowStaysOnBottomHint|n Expected (expectedWindowFlags): Window||FramelessWindowHint||WindowSystemMenuHint||WindowStaysOnBottomHint' flowId='tst_Cmptest']
+##teamcity[testFinished name='test_windowflags(fail1)' flowId='tst_Cmptest']
+##teamcity[testStarted name='test_windowflags(fail2)' flowId='tst_Cmptest']
+##teamcity[testFailed name='test_windowflags(fail2)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)|]' details='Compared values are not the same|n Actual (actualWindowFlags) : Window|n Expected (expectedWindowFlags): Window||FramelessWindowHint' flowId='tst_Cmptest']
+##teamcity[testFinished name='test_windowflags(fail2)' flowId='tst_Cmptest']
+##teamcity[testStarted name='test_unregistered_flags(pass)' flowId='tst_Cmptest']
+##teamcity[testFinished name='test_unregistered_flags(pass)' flowId='tst_Cmptest']
+##teamcity[testStarted name='test_unregistered_flags(fail1)' flowId='tst_Cmptest']
+##teamcity[testFailed name='test_unregistered_flags(fail1)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)|]' details='Compared values are not the same|n Actual (actualFlags) : 0x3|n Expected (expectedFlags): 0x5' flowId='tst_Cmptest']
+##teamcity[testFinished name='test_unregistered_flags(fail1)' flowId='tst_Cmptest']
+##teamcity[testStarted name='test_unregistered_flags(fail2)' flowId='tst_Cmptest']
+##teamcity[testFailed name='test_unregistered_flags(fail2)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)|]' details='Compared values are not the same|n Actual (actualFlags) : 0x1|n Expected (expectedFlags): 0x5' flowId='tst_Cmptest']
+##teamcity[testFinished name='test_unregistered_flags(fail2)' flowId='tst_Cmptest']
##teamcity[testStarted name='compare_boolfuncs()' flowId='tst_Cmptest']
##teamcity[testFinished name='compare_boolfuncs()' flowId='tst_Cmptest']
##teamcity[testStarted name='compare_to_nullptr()' flowId='tst_Cmptest']
diff --git a/tests/auto/testlib/selftests/expected_cmptest.txt b/tests/auto/testlib/selftests/expected_cmptest.txt
index 78df990dea..e1aa81c1a1 100644
--- a/tests/auto/testlib/selftests/expected_cmptest.txt
+++ b/tests/auto/testlib/selftests/expected_cmptest.txt
@@ -11,6 +11,24 @@ FAIL! : tst_Cmptest::compare_class_enums() Compared values are not the same
Actual (MyClassEnum::MyClassEnumValue1): MyClassEnumValue1
Expected (MyClassEnum::MyClassEnumValue2): MyClassEnumValue2
Loc: [qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)]
+PASS : tst_Cmptest::test_windowflags(pass)
+FAIL! : tst_Cmptest::test_windowflags(fail1) Compared values are not the same
+ Actual (actualWindowFlags) : Window|WindowSystemMenuHint|WindowStaysOnBottomHint
+ Expected (expectedWindowFlags): Window|FramelessWindowHint|WindowSystemMenuHint|WindowStaysOnBottomHint
+ Loc: [qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)]
+FAIL! : tst_Cmptest::test_windowflags(fail2) Compared values are not the same
+ Actual (actualWindowFlags) : Window
+ Expected (expectedWindowFlags): Window|FramelessWindowHint
+ Loc: [qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)]
+PASS : tst_Cmptest::test_unregistered_flags(pass)
+FAIL! : tst_Cmptest::test_unregistered_flags(fail1) Compared values are not the same
+ Actual (actualFlags) : 0x3
+ Expected (expectedFlags): 0x5
+ Loc: [qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)]
+FAIL! : tst_Cmptest::test_unregistered_flags(fail2) Compared values are not the same
+ Actual (actualFlags) : 0x1
+ Expected (expectedFlags): 0x5
+ Loc: [qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)]
PASS : tst_Cmptest::compare_boolfuncs()
PASS : tst_Cmptest::compare_to_nullptr()
PASS : tst_Cmptest::compare_pointerfuncs()
@@ -138,5 +156,5 @@ FAIL! : tst_Cmptest::tryVerify2() 'opaqueFunc() < 2' returned FALSE. (42)
Loc: [qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(0)]
PASS : tst_Cmptest::verifyExplicitOperatorBool()
PASS : tst_Cmptest::cleanupTestCase()
-Totals: 16 passed, 34 failed, 0 skipped, 0 blacklisted, 0ms
+Totals: 18 passed, 38 failed, 0 skipped, 0 blacklisted, 0ms
********* Finished testing of tst_Cmptest *********
diff --git a/tests/auto/testlib/selftests/expected_cmptest.xml b/tests/auto/testlib/selftests/expected_cmptest.xml
index 01b725f247..1c5a17631a 100644
--- a/tests/auto/testlib/selftests/expected_cmptest.xml
+++ b/tests/auto/testlib/selftests/expected_cmptest.xml
@@ -31,6 +31,42 @@
</Incident>
<Duration msecs="0"/>
</TestFunction>
+<TestFunction name="test_windowflags">
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[pass]]></DataTag>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="0">
+ <DataTag><![CDATA[fail1]]></DataTag>
+ <Description><![CDATA[Compared values are not the same
+ Actual (actualWindowFlags) : Window|WindowSystemMenuHint|WindowStaysOnBottomHint
+ Expected (expectedWindowFlags): Window|FramelessWindowHint|WindowSystemMenuHint|WindowStaysOnBottomHint]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="0">
+ <DataTag><![CDATA[fail2]]></DataTag>
+ <Description><![CDATA[Compared values are not the same
+ Actual (actualWindowFlags) : Window
+ Expected (expectedWindowFlags): Window|FramelessWindowHint]]></Description>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="test_unregistered_flags">
+<Incident type="pass" file="" line="0">
+ <DataTag><![CDATA[pass]]></DataTag>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="0">
+ <DataTag><![CDATA[fail1]]></DataTag>
+ <Description><![CDATA[Compared values are not the same
+ Actual (actualFlags) : 0x3
+ Expected (expectedFlags): 0x5]]></Description>
+</Incident>
+<Incident type="fail" file="qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp" line="0">
+ <DataTag><![CDATA[fail2]]></DataTag>
+ <Description><![CDATA[Compared values are not the same
+ Actual (actualFlags) : 0x1
+ Expected (expectedFlags): 0x5]]></Description>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
<TestFunction name="compare_boolfuncs">
<Incident type="pass" file="" line="0" />
<Duration msecs="0"/>
diff --git a/tests/auto/testlib/selftests/expected_cmptest.xunitxml b/tests/auto/testlib/selftests/expected_cmptest.xunitxml
index 812696ffcf..99823d1c1c 100644
--- a/tests/auto/testlib/selftests/expected_cmptest.xunitxml
+++ b/tests/auto/testlib/selftests/expected_cmptest.xunitxml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<testsuite errors="0" failures="34" tests="24" name="tst_Cmptest">
+<testsuite errors="0" failures="38" tests="26" name="tst_Cmptest">
<properties>
<property value="@INSERT_QT_VERSION_HERE@" name="QTestVersion"/>
<property value="@INSERT_QT_VERSION_HERE@" name="QtVersion"/>
@@ -19,6 +19,22 @@
Actual (MyClassEnum::MyClassEnumValue1): MyClassEnumValue1
Expected (MyClassEnum::MyClassEnumValue2): MyClassEnumValue2" result="fail"/>
</testcase>
+ <testcase result="fail" name="test_windowflags">
+ <failure tag="fail1" message="Compared values are not the same
+ Actual (actualWindowFlags) : Window|WindowSystemMenuHint|WindowStaysOnBottomHint
+ Expected (expectedWindowFlags): Window|FramelessWindowHint|WindowSystemMenuHint|WindowStaysOnBottomHint" result="fail"/>
+ <failure tag="fail2" message="Compared values are not the same
+ Actual (actualWindowFlags) : Window
+ Expected (expectedWindowFlags): Window|FramelessWindowHint" result="fail"/>
+ </testcase>
+ <testcase result="fail" name="test_unregistered_flags">
+ <failure tag="fail1" message="Compared values are not the same
+ Actual (actualFlags) : 0x3
+ Expected (expectedFlags): 0x5" result="fail"/>
+ <failure tag="fail2" message="Compared values are not the same
+ Actual (actualFlags) : 0x1
+ Expected (expectedFlags): 0x5" result="fail"/>
+ </testcase>
<testcase result="pass" name="compare_boolfuncs"/>
<testcase result="pass" name="compare_to_nullptr"/>
<testcase result="pass" name="compare_pointerfuncs"/>
diff --git a/tests/auto/testlib/selftests/expected_commandlinedata.tap b/tests/auto/testlib/selftests/expected_commandlinedata.tap
new file mode 100644
index 0000000000..1e1abfba50
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_commandlinedata.tap
@@ -0,0 +1,20 @@
+TAP version 13
+# tst_DataTable
+ok 1 - initTestCase()
+# QVERIFY(test)
+ok 2 - fiveTablePasses(fiveTablePasses_data1)
+# QVERIFY(test)
+ok 3 - fiveTablePasses(fiveTablePasses_data2)
+# QVERIFY(test)
+ok 4 - fiveTablePasses(fiveTablePasses_data3)
+# QVERIFY(test)
+ok 5 - fiveTablePasses(fiveTablePasses_data4)
+# QVERIFY(test)
+ok 6 - fiveTablePasses(fiveTablePasses_data5)
+# QVERIFY(test)
+ok 7 - fiveTablePasses(fiveTablePasses_data1)
+ok 8 - cleanupTestCase()
+1..8
+# tests 8
+# pass 8
+# fail 0
diff --git a/tests/auto/testlib/selftests/expected_counting.tap b/tests/auto/testlib/selftests/expected_counting.tap
new file mode 100644
index 0000000000..ad53e8f14e
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_counting.tap
@@ -0,0 +1,118 @@
+TAP version 13
+# tst_Counting
+ok 1 - initTestCase()
+ok 2 - testPassPass(row 1)
+ok 3 - testPassPass(row 2)
+ok 4 - testPassSkip(row 1)
+ok 5 - testPassSkip(row 2) # SKIP Skipping
+ok 6 - testPassFail(row 1)
+not ok 7 - testPassFail(row 2)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (false)
+ found: false (false)
+ expected: true (false)
+ actual: false (false)
+ at: tst_Counting::testPassFail() (qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp:102)
+ file: qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp
+ line: 102
+ ...
+ok 8 - testSkipPass(row 1) # SKIP Skipping
+ok 9 - testSkipPass(row 2)
+ok 10 - testSkipSkip(row 1) # SKIP Skipping
+ok 11 - testSkipSkip(row 2) # SKIP Skipping
+ok 12 - testSkipFail(row 1) # SKIP Skipping
+not ok 13 - testSkipFail(row 2)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (false)
+ found: false (false)
+ expected: true (false)
+ actual: false (false)
+ at: tst_Counting::testSkipFail() (qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp:102)
+ file: qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp
+ line: 102
+ ...
+not ok 14 - testFailPass(row 1)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (false)
+ found: false (false)
+ expected: true (false)
+ actual: false (false)
+ at: tst_Counting::testFailPass() (qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp:102)
+ file: qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp
+ line: 102
+ ...
+ok 15 - testFailPass(row 2)
+not ok 16 - testFailSkip(row 1)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (false)
+ found: false (false)
+ expected: true (false)
+ actual: false (false)
+ at: tst_Counting::testFailSkip() (qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp:102)
+ file: qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp
+ line: 102
+ ...
+ok 17 - testFailSkip(row 2) # SKIP Skipping
+not ok 18 - testFailFail(row 1)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (false)
+ found: false (false)
+ expected: true (false)
+ actual: false (false)
+ at: tst_Counting::testFailFail() (qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp:102)
+ file: qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp
+ line: 102
+ ...
+not ok 19 - testFailFail(row 2)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (false)
+ found: false (false)
+ expected: true (false)
+ actual: false (false)
+ at: tst_Counting::testFailFail() (qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp:102)
+ file: qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp
+ line: 102
+ ...
+ok 20 - testFailInInit(before)
+not ok 21 - testFailInInit(fail)
+ ---
+ # Fail in init()
+ at: tst_Counting::testFailInInit() (qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp:221)
+ file: qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp
+ line: 221
+ ...
+ok 22 - testFailInInit(after)
+ok 23 - testFailInCleanup(before)
+# This test function should execute and then QFAIL in cleanup()
+not ok 24 - testFailInCleanup(fail)
+ ---
+ # Fail in cleanup()
+ at: tst_Counting::testFailInCleanup() (qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp:229)
+ file: qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp
+ line: 229
+ ...
+ok 25 - testFailInCleanup(after)
+ok 26 - testSkipInInit(before)
+ok 27 - testSkipInInit(skip) # SKIP Skip in init()
+ok 28 - testSkipInInit(after)
+ok 29 - testSkipInCleanup(before)
+# This test function should execute and then QSKIP in cleanup()
+ok 30 - testSkipInCleanup(skip) # SKIP Skip in cleanup()
+ok 31 - testSkipInCleanup(after)
+ok 32 - cleanupTestCase()
+1..32
+# tests 32
+# pass 16
+# fail 8
diff --git a/tests/auto/testlib/selftests/expected_crashes_4.txt b/tests/auto/testlib/selftests/expected_crashes_4.txt
new file mode 100644
index 0000000000..e0e4d27b0a
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_crashes_4.txt
@@ -0,0 +1,7 @@
+********* Start testing of tst_Crashes *********
+Config: Using QtTest library @INSERT_QT_VERSION_HERE@, Qt @INSERT_QT_VERSION_HERE@
+PASS : tst_Crashes::initTestCase()
+QFATAL : tst_Crashes::crash() Received signal 11
+ Function time: ms Total time: ms
+FAIL! : tst_Crashes::crash() Received a fatal error.
+ Loc: [Unknown file(0)]
diff --git a/tests/auto/testlib/selftests/expected_datatable.tap b/tests/auto/testlib/selftests/expected_datatable.tap
new file mode 100644
index 0000000000..8a3d473b6c
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_datatable.tap
@@ -0,0 +1,183 @@
+TAP version 13
+# tst_DataTable
+ok 1 - initTestCase()
+ok 2 - singleTestFunction1()
+ok 3 - singleTestFunction2()
+ok 4 - fiveTablePasses(fiveTablePasses_data 1)
+ok 5 - fiveTablePasses(fiveTablePasses_data 2)
+ok 6 - fiveTablePasses(fiveTablePasses_data 3)
+ok 7 - fiveTablePasses(fiveTablePasses_data 4)
+ok 8 - fiveTablePasses(fiveTablePasses_data 5)
+not ok 9 - fiveTableFailures(fiveTableFailures_data 1)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (test)
+ found: false (test)
+ expected: true (test)
+ actual: false (test)
+ at: tst_DataTable::fiveTableFailures() (qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp:78)
+ file: qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp
+ line: 78
+ ...
+not ok 10 - fiveTableFailures(fiveTableFailures_data 2)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (test)
+ found: false (test)
+ expected: true (test)
+ actual: false (test)
+ at: tst_DataTable::fiveTableFailures() (qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp:78)
+ file: qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp
+ line: 78
+ ...
+not ok 11 - fiveTableFailures(fiveTableFailures_data 3)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (test)
+ found: false (test)
+ expected: true (test)
+ actual: false (test)
+ at: tst_DataTable::fiveTableFailures() (qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp:78)
+ file: qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp
+ line: 78
+ ...
+not ok 12 - fiveTableFailures(fiveTableFailures_data 4)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (test)
+ found: false (test)
+ expected: true (test)
+ actual: false (test)
+ at: tst_DataTable::fiveTableFailures() (qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp:78)
+ file: qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp
+ line: 78
+ ...
+not ok 13 - fiveTableFailures(fiveTableFailures_data 5)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (test)
+ found: false (test)
+ expected: true (test)
+ actual: false (test)
+ at: tst_DataTable::fiveTableFailures() (qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp:78)
+ file: qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp
+ line: 78
+ ...
+not ok 14 - startsWithFailure(startsWithFailure_data 1)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (test)
+ found: false (test)
+ expected: true (test)
+ actual: false (test)
+ at: tst_DataTable::startsWithFailure() (qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp:78)
+ file: qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp
+ line: 78
+ ...
+ok 15 - startsWithFailure(startsWithFailure_data 2)
+ok 16 - startsWithFailure(startsWithFailure_data 3)
+ok 17 - startsWithFailure(startsWithFailure_data 4)
+ok 18 - startsWithFailure(startsWithFailure_data 5)
+ok 19 - endsWithFailure(endsWithFailure 1)
+ok 20 - endsWithFailure(endsWithFailure 2)
+ok 21 - endsWithFailure(endsWithFailure 3)
+ok 22 - endsWithFailure(endsWithFailure 4)
+not ok 23 - endsWithFailure(endsWithFailure 5)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (test)
+ found: false (test)
+ expected: true (test)
+ actual: false (test)
+ at: tst_DataTable::endsWithFailure() (qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp:78)
+ file: qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp
+ line: 78
+ ...
+ok 24 - failureInMiddle(failureInMiddle_data 1)
+ok 25 - failureInMiddle(failureInMiddle_data 2)
+not ok 26 - failureInMiddle(failureInMiddle_data 3)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (test)
+ found: false (test)
+ expected: true (test)
+ actual: false (test)
+ at: tst_DataTable::failureInMiddle() (qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp:78)
+ file: qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp
+ line: 78
+ ...
+ok 27 - failureInMiddle(failureInMiddle_data 4)
+ok 28 - failureInMiddle(failureInMiddle_data 5)
+not ok 29 - fiveIsolatedFailures(fiveIsolatedFailures_data 1)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (!test)
+ found: false (!test)
+ expected: true (!test)
+ actual: false (!test)
+ at: tst_DataTable::fiveIsolatedFailures() (qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp:160)
+ file: qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp
+ line: 160
+ ...
+not ok 30 - fiveIsolatedFailures(fiveIsolatedFailures_data 2)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (!test)
+ found: false (!test)
+ expected: true (!test)
+ actual: false (!test)
+ at: tst_DataTable::fiveIsolatedFailures() (qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp:160)
+ file: qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp
+ line: 160
+ ...
+not ok 31 - fiveIsolatedFailures(fiveIsolatedFailures_data 3)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (!test)
+ found: false (!test)
+ expected: true (!test)
+ actual: false (!test)
+ at: tst_DataTable::fiveIsolatedFailures() (qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp:160)
+ file: qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp
+ line: 160
+ ...
+not ok 32 - fiveIsolatedFailures(fiveIsolatedFailures_data 4)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (!test)
+ found: false (!test)
+ expected: true (!test)
+ actual: false (!test)
+ at: tst_DataTable::fiveIsolatedFailures() (qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp:160)
+ file: qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp
+ line: 160
+ ...
+not ok 33 - fiveIsolatedFailures(fiveIsolatedFailures_data 5)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (!test)
+ found: false (!test)
+ expected: true (!test)
+ actual: false (!test)
+ at: tst_DataTable::fiveIsolatedFailures() (qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp:160)
+ file: qtbase/tests/auto/testlib/selftests/datatable/tst_datatable.cpp
+ line: 160
+ ...
+ok 34 - cleanupTestCase()
+1..34
+# tests 34
+# pass 21
+# fail 13
diff --git a/tests/auto/testlib/selftests/expected_datetime.tap b/tests/auto/testlib/selftests/expected_datetime.tap
new file mode 100644
index 0000000000..896aeafa37
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_datetime.tap
@@ -0,0 +1,46 @@
+TAP version 13
+# tst_DateTime
+ok 1 - initTestCase()
+not ok 2 - dateTime()
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: 2000/05/03 04:03:04.000[UTC] (utc)
+ found: 2000/05/03 04:03:04.000[UTC+00:02] (local)
+ expected: 2000/05/03 04:03:04.000[UTC] (utc)
+ actual: 2000/05/03 04:03:04.000[UTC+00:02] (local)
+ at: tst_DateTime::dateTime() (qtbase/tests/auto/testlib/selftests/datetime/tst_datetime.cpp:52)
+ file: qtbase/tests/auto/testlib/selftests/datetime/tst_datetime.cpp
+ line: 52
+ ...
+ok 3 - qurl(empty urls)
+not ok 4 - qurl(empty rhs)
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: Invalid URL: (operandB)
+ found: http://example.com (operandA)
+ expected: Invalid URL: (operandB)
+ actual: http://example.com (operandA)
+ at: tst_DateTime::qurl() (qtbase/tests/auto/testlib/selftests/datetime/tst_datetime.cpp:60)
+ file: qtbase/tests/auto/testlib/selftests/datetime/tst_datetime.cpp
+ line: 60
+ ...
+not ok 5 - qurl(empty lhs)
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: http://example.com (operandB)
+ found: Invalid URL: (operandA)
+ expected: http://example.com (operandB)
+ actual: Invalid URL: (operandA)
+ at: tst_DateTime::qurl() (qtbase/tests/auto/testlib/selftests/datetime/tst_datetime.cpp:60)
+ file: qtbase/tests/auto/testlib/selftests/datetime/tst_datetime.cpp
+ line: 60
+ ...
+ok 6 - qurl(same urls)
+ok 7 - cleanupTestCase()
+1..7
+# tests 7
+# pass 4
+# fail 3
diff --git a/tests/auto/testlib/selftests/expected_exceptionthrow.tap b/tests/auto/testlib/selftests/expected_exceptionthrow.tap
new file mode 100644
index 0000000000..d8dbf173d6
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_exceptionthrow.tap
@@ -0,0 +1,14 @@
+TAP version 13
+# tst_Exception
+ok 1 - initTestCase()
+not ok 2 - throwException()
+ ---
+ # Caught unhandled exception
+ at: tst_Exception::throwException() (qtbase/src/testlib/qtestcase.cpp:1846)
+ file: qtbase/src/testlib/qtestcase.cpp
+ line: 1846
+ ...
+1..2
+# tests 2
+# pass 1
+# fail 1
diff --git a/tests/auto/testlib/selftests/expected_expectfail.tap b/tests/auto/testlib/selftests/expected_expectfail.tap
new file mode 100644
index 0000000000..0e5dc4d982
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_expectfail.tap
@@ -0,0 +1,96 @@
+TAP version 13
+# tst_ExpectFail
+ok 1 - initTestCase()
+# begin
+not ok 2 - xfailAndContinue() # TODO This should xfail
+ ---
+ at: tst_ExpectFail::xfailAndContinue() (qtbase/tests/auto/testlib/selftests/expectfail/tst_expectfail.cpp:65)
+ file: qtbase/tests/auto/testlib/selftests/expectfail/tst_expectfail.cpp
+ line: 65
+ ...
+# after
+# begin
+not ok 3 - xfailAndAbort() # TODO This should xfail
+ ---
+ at: tst_ExpectFail::xfailAndAbort() (qtbase/tests/auto/testlib/selftests/expectfail/tst_expectfail.cpp:73)
+ file: qtbase/tests/auto/testlib/selftests/expectfail/tst_expectfail.cpp
+ line: 73
+ ...
+not ok 4 - xfailTwice()
+ ---
+ # Already expecting a fail
+ at: tst_ExpectFail::xfailTwice() (qtbase/tests/auto/testlib/selftests/expectfail/tst_expectfail.cpp:83)
+ file: qtbase/tests/auto/testlib/selftests/expectfail/tst_expectfail.cpp
+ line: 83
+ ...
+not ok 5 - xfailWithQString() # TODO A string
+ ---
+ at: tst_ExpectFail::xfailWithQString() (qtbase/tests/auto/testlib/selftests/expectfail/tst_expectfail.cpp:92)
+ file: qtbase/tests/auto/testlib/selftests/expectfail/tst_expectfail.cpp
+ line: 92
+ ...
+not ok 5 - xfailWithQString() # TODO Bug 5 (The message)
+ ---
+ at: tst_ExpectFail::xfailWithQString() (qtbase/tests/auto/testlib/selftests/expectfail/tst_expectfail.cpp:97)
+ file: qtbase/tests/auto/testlib/selftests/expectfail/tst_expectfail.cpp
+ line: 97
+ ...
+ok 6 - xfailDataDrivenWithQVerify(Pass 1)
+ok 7 - xfailDataDrivenWithQVerify(Pass 2)
+not ok 8 - xfailDataDrivenWithQVerify(Abort) # TODO This test should xfail
+ ---
+ at: tst_ExpectFail::xfailDataDrivenWithQVerify() (qtbase/tests/auto/testlib/selftests/expectfail/tst_expectfail.cpp:126)
+ file: qtbase/tests/auto/testlib/selftests/expectfail/tst_expectfail.cpp
+ line: 126
+ ...
+not ok 9 - xfailDataDrivenWithQVerify(Continue) # TODO This test should xfail
+ ---
+ at: tst_ExpectFail::xfailDataDrivenWithQVerify() (qtbase/tests/auto/testlib/selftests/expectfail/tst_expectfail.cpp:126)
+ file: qtbase/tests/auto/testlib/selftests/expectfail/tst_expectfail.cpp
+ line: 126
+ ...
+ok 10 - xfailDataDrivenWithQCompare(Pass 1)
+ok 11 - xfailDataDrivenWithQCompare(Pass 2)
+not ok 12 - xfailDataDrivenWithQCompare(Abort) # TODO This test should xfail
+ ---
+ at: tst_ExpectFail::xfailDataDrivenWithQCompare() (qtbase/tests/auto/testlib/selftests/expectfail/tst_expectfail.cpp:160)
+ file: qtbase/tests/auto/testlib/selftests/expectfail/tst_expectfail.cpp
+ line: 160
+ ...
+not ok 13 - xfailDataDrivenWithQCompare(Continue) # TODO This test should xfail
+ ---
+ at: tst_ExpectFail::xfailDataDrivenWithQCompare() (qtbase/tests/auto/testlib/selftests/expectfail/tst_expectfail.cpp:160)
+ file: qtbase/tests/auto/testlib/selftests/expectfail/tst_expectfail.cpp
+ line: 160
+ ...
+ok 14 - xfailOnWrongRow(right row)
+not ok 15 - xfailOnAnyRow(first row) # TODO This test should xfail
+ ---
+ at: tst_ExpectFail::xfailOnAnyRow() (qtbase/tests/auto/testlib/selftests/expectfail/tst_expectfail.cpp:195)
+ file: qtbase/tests/auto/testlib/selftests/expectfail/tst_expectfail.cpp
+ line: 195
+ ...
+not ok 16 - xfailOnAnyRow(second row) # TODO This test should xfail
+ ---
+ at: tst_ExpectFail::xfailOnAnyRow() (qtbase/tests/auto/testlib/selftests/expectfail/tst_expectfail.cpp:195)
+ file: qtbase/tests/auto/testlib/selftests/expectfail/tst_expectfail.cpp
+ line: 195
+ ...
+not ok 17 - xfailWithoutVerify(first row)
+ ---
+ # QEXPECT_FAIL was called without any subsequent verification statements
+ ...
+not ok 18 - xfailWithoutVerify(second row)
+ ---
+ # QEXPECT_FAIL was called without any subsequent verification statements
+ ...
+ok 19 - xpass() # TODO 'true' returned TRUE unexpectedly. ()
+ok 20 - xpassDataDrivenWithQVerify(XPass) # TODO 'true' returned TRUE unexpectedly. ()
+ok 21 - xpassDataDrivenWithQVerify(Pass)
+ok 22 - xpassDataDrivenWithQCompare(XPass) # TODO QCOMPARE(1, 1) returned TRUE unexpectedly.
+ok 23 - xpassDataDrivenWithQCompare(Pass)
+ok 24 - cleanupTestCase()
+1..24
+# tests 24
+# pass 18
+# fail 6
diff --git a/tests/auto/testlib/selftests/expected_failcleanup.tap b/tests/auto/testlib/selftests/expected_failcleanup.tap
new file mode 100644
index 0000000000..2098cc1e17
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_failcleanup.tap
@@ -0,0 +1,20 @@
+TAP version 13
+# tst_FailCleanup
+ok 1 - initTestCase()
+ok 2 - aTestFunction()
+not ok 3 - cleanupTestCase()
+ ---
+ type: QVERIFY
+ message: Fail inside cleanupTestCase
+ wanted: true (false)
+ found: false (false)
+ expected: true (false)
+ actual: false (false)
+ at: tst_FailCleanup::cleanupTestCase() (qtbase/tests/auto/testlib/selftests/failcleanup/tst_failcleanup.cpp:46)
+ file: qtbase/tests/auto/testlib/selftests/failcleanup/tst_failcleanup.cpp
+ line: 46
+ ...
+1..3
+# tests 3
+# pass 2
+# fail 1
diff --git a/tests/auto/testlib/selftests/expected_failinit.tap b/tests/auto/testlib/selftests/expected_failinit.tap
new file mode 100644
index 0000000000..d99a71fd51
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_failinit.tap
@@ -0,0 +1,19 @@
+TAP version 13
+# tst_FailInit
+not ok 1 - initTestCase()
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (false)
+ found: false (false)
+ expected: true (false)
+ actual: false (false)
+ at: tst_FailInit::initTestCase() (qtbase/tests/auto/testlib/selftests/failinit/tst_failinit.cpp:42)
+ file: qtbase/tests/auto/testlib/selftests/failinit/tst_failinit.cpp
+ line: 42
+ ...
+ok 2 - cleanupTestCase()
+1..2
+# tests 2
+# pass 1
+# fail 1
diff --git a/tests/auto/testlib/selftests/expected_failinitdata.tap b/tests/auto/testlib/selftests/expected_failinitdata.tap
new file mode 100644
index 0000000000..27bdda5a13
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_failinitdata.tap
@@ -0,0 +1,18 @@
+TAP version 13
+# tst_FailInitData
+not ok 1 - initTestCase()
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (false)
+ found: false (false)
+ expected: true (false)
+ actual: false (false)
+ at: tst_FailInitData::initTestCase() (qtbase/tests/auto/testlib/selftests/failinitdata/tst_failinitdata.cpp:43)
+ file: qtbase/tests/auto/testlib/selftests/failinitdata/tst_failinitdata.cpp
+ line: 43
+ ...
+1..1
+# tests 1
+# pass 0
+# fail 1
diff --git a/tests/auto/testlib/selftests/expected_fetchbogus.tap b/tests/auto/testlib/selftests/expected_fetchbogus.tap
new file mode 100644
index 0000000000..c6761b2301
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_fetchbogus.tap
@@ -0,0 +1,15 @@
+TAP version 13
+# tst_FetchBogus
+ok 1 - initTestCase()
+# QFETCH: Requested testdata 'bubu' not available, check your _data function.
+not ok 2 - fetchBogus(foo)
+ ---
+ # Received a fatal error.
+ at: tst_FetchBogus::fetchBogus() (Unknown file:0)
+ file: Unknown file
+ line: 0
+ ...
+1..2
+# tests 2
+# pass 1
+# fail 1
diff --git a/tests/auto/testlib/selftests/expected_findtestdata.tap b/tests/auto/testlib/selftests/expected_findtestdata.tap
new file mode 100644
index 0000000000..0fb38d2822
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_findtestdata.tap
@@ -0,0 +1,10 @@
+TAP version 13
+# FindTestData
+ok 1 - initTestCase()
+# testdata testfile could not be located!
+ok 2 - paths()
+ok 3 - cleanupTestCase()
+1..3
+# tests 3
+# pass 3
+# fail 0
diff --git a/tests/auto/testlib/selftests/expected_float.tap b/tests/auto/testlib/selftests/expected_float.tap
new file mode 100644
index 0000000000..fae2dc9796
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_float.tap
@@ -0,0 +1,82 @@
+TAP version 13
+# tst_float
+ok 1 - initTestCase()
+ok 2 - floatComparisons(should SUCCEED 1)
+not ok 3 - floatComparisons(should FAIL 1)
+ ---
+ type: QCOMPARE
+ message: Compared floats are not the same (fuzzy compare)
+ wanted: 3 (operandRight)
+ found: 1 (operandLeft)
+ expected: 3 (operandRight)
+ actual: 1 (operandLeft)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:48)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 48
+ ...
+not ok 4 - floatComparisons(should FAIL 2)
+ ---
+ type: QCOMPARE
+ message: Compared floats are not the same (fuzzy compare)
+ wanted: 3e-07 (operandRight)
+ found: 1e-07 (operandLeft)
+ expected: 3e-07 (operandRight)
+ actual: 1e-07 (operandLeft)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:48)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 48
+ ...
+not ok 5 - floatComparisons(should FAIL 3)
+ ---
+ type: QCOMPARE
+ message: Compared floats are not the same (fuzzy compare)
+ wanted: 99999 (operandRight)
+ found: 99998 (operandLeft)
+ expected: 99999 (operandRight)
+ actual: 99998 (operandLeft)
+ at: tst_float::floatComparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:48)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 48
+ ...
+ok 6 - floatComparisons(should SUCCEED 2)
+not ok 7 - compareFloatTests(1e0)
+ ---
+ type: QCOMPARE
+ message: Compared floats are not the same (fuzzy compare)
+ wanted: 3 (t3)
+ found: 1 (t1)
+ expected: 3 (t3)
+ actual: 1 (t1)
+ at: tst_float::compareFloatTests() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:96)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 96
+ ...
+not ok 8 - compareFloatTests(1e-7)
+ ---
+ type: QCOMPARE
+ message: Compared floats are not the same (fuzzy compare)
+ wanted: 3e-07 (t3)
+ found: 1e-07 (t1)
+ expected: 3e-07 (t3)
+ actual: 1e-07 (t1)
+ at: tst_float::compareFloatTests() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:96)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 96
+ ...
+not ok 9 - compareFloatTests(1e+7)
+ ---
+ type: QCOMPARE
+ message: Compared floats are not the same (fuzzy compare)
+ wanted: 3e+07 (t3)
+ found: 1e+07 (t1)
+ expected: 3e+07 (t3)
+ actual: 1e+07 (t1)
+ at: tst_float::compareFloatTests() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:96)
+ file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp
+ line: 96
+ ...
+ok 10 - cleanupTestCase()
+1..10
+# tests 10
+# pass 4
+# fail 6
diff --git a/tests/auto/testlib/selftests/expected_globaldata.tap b/tests/auto/testlib/selftests/expected_globaldata.tap
new file mode 100644
index 0000000000..580cf3a7a8
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_globaldata.tap
@@ -0,0 +1,52 @@
+TAP version 13
+# tst_globaldata
+# initTestCase initTestCase (null)
+ok 1 - initTestCase()
+# init testGlobal local 1
+# global: false
+# local: false
+# cleanup testGlobal local 1
+ok 2 - testGlobal(1:local 1)
+# init testGlobal local 2
+# global: false
+# local: true
+# cleanup testGlobal local 2
+ok 3 - testGlobal(1:local 2)
+# init testGlobal local 1
+# global: true
+# local: false
+# cleanup testGlobal local 1
+ok 4 - testGlobal(2:local 1)
+# init testGlobal local 2
+# global: true
+# local: true
+# cleanup testGlobal local 2
+ok 5 - testGlobal(2:local 2)
+ok 6 - skip(1) # SKIP skipping
+# init skipLocal local 1
+ok 7 - skipLocal(1:local 1) # SKIP skipping
+# cleanup skipLocal local 1
+# init skipLocal local 2
+ok 8 - skipLocal(1:local 2) # SKIP skipping
+# cleanup skipLocal local 2
+# init skipSingle local 1
+# global: false local: false
+# cleanup skipSingle local 1
+ok 9 - skipSingle(1:local 1)
+# init skipSingle local 2
+# global: false local: true
+# cleanup skipSingle local 2
+ok 10 - skipSingle(1:local 2)
+# init skipSingle local 1
+ok 11 - skipSingle(2:local 1) # SKIP skipping
+# cleanup skipSingle local 1
+# init skipSingle local 2
+# global: true local: true
+# cleanup skipSingle local 2
+ok 12 - skipSingle(2:local 2)
+# cleanupTestCase cleanupTestCase (null)
+ok 13 - cleanupTestCase()
+1..13
+# tests 13
+# pass 9
+# fail 0
diff --git a/tests/auto/testlib/selftests/expected_keyboard.lightxml b/tests/auto/testlib/selftests/expected_keyboard.lightxml
new file mode 100644
index 0000000000..5699fba3bf
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_keyboard.lightxml
@@ -0,0 +1,18 @@
+<Environment>
+ <QtVersion>@INSERT_QT_VERSION_HERE@</QtVersion>
+ <QtBuild/>
+ <QTestVersion>@INSERT_QT_VERSION_HERE@</QTestVersion>
+</Environment>
+<TestFunction name="initTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="keyPressAndRelease">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="cleanupTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<Duration msecs="0"/>
diff --git a/tests/auto/testlib/selftests/expected_keyboard.tap b/tests/auto/testlib/selftests/expected_keyboard.tap
new file mode 100644
index 0000000000..0725434f8c
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_keyboard.tap
@@ -0,0 +1,9 @@
+TAP version 13
+# tst_Keyboard
+ok 1 - initTestCase()
+ok 2 - keyPressAndRelease()
+ok 3 - cleanupTestCase()
+1..3
+# tests 3
+# pass 3
+# fail 0
diff --git a/tests/auto/testlib/selftests/expected_keyboard.teamcity b/tests/auto/testlib/selftests/expected_keyboard.teamcity
new file mode 100644
index 0000000000..dc01f86ff0
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_keyboard.teamcity
@@ -0,0 +1,8 @@
+##teamcity[testSuiteStarted name='tst_Keyboard' flowId='tst_Keyboard']
+##teamcity[testStarted name='initTestCase()' flowId='tst_Keyboard']
+##teamcity[testFinished name='initTestCase()' flowId='tst_Keyboard']
+##teamcity[testStarted name='keyPressAndRelease()' flowId='tst_Keyboard']
+##teamcity[testFinished name='keyPressAndRelease()' flowId='tst_Keyboard']
+##teamcity[testStarted name='cleanupTestCase()' flowId='tst_Keyboard']
+##teamcity[testFinished name='cleanupTestCase()' flowId='tst_Keyboard']
+##teamcity[testSuiteFinished name='tst_Keyboard' flowId='tst_Keyboard']
diff --git a/tests/auto/testlib/selftests/expected_keyboard.txt b/tests/auto/testlib/selftests/expected_keyboard.txt
new file mode 100644
index 0000000000..13b7c70672
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_keyboard.txt
@@ -0,0 +1,7 @@
+********* Start testing of tst_Keyboard *********
+Config: Using QtTest library
+PASS : tst_Keyboard::initTestCase()
+PASS : tst_Keyboard::keyPressAndRelease()
+PASS : tst_Keyboard::cleanupTestCase()
+Totals: 3 passed, 0 failed, 0 skipped, 0 blacklisted, 0ms
+********* Finished testing of tst_Keyboard *********
diff --git a/tests/auto/testlib/selftests/expected_keyboard.xml b/tests/auto/testlib/selftests/expected_keyboard.xml
new file mode 100644
index 0000000000..f5ad1b2287
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_keyboard.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestCase name="tst_Keyboard">
+<Environment>
+ <QtVersion>@INSERT_QT_VERSION_HERE@</QtVersion>
+ <QtBuild/>
+ <QTestVersion>@INSERT_QT_VERSION_HERE@</QTestVersion>
+</Environment>
+<TestFunction name="initTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="keyPressAndRelease">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="cleanupTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<Duration msecs="0"/>
+</TestCase>
diff --git a/tests/auto/testlib/selftests/expected_keyboard.xunitxml b/tests/auto/testlib/selftests/expected_keyboard.xunitxml
new file mode 100644
index 0000000000..93b5f7bfff
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_keyboard.xunitxml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<testsuite errors="0" failures="0" tests="3" name="tst_Keyboard">
+ <properties>
+ <property value="@INSERT_QT_VERSION_HERE@" name="QTestVersion"/>
+ <property value="@INSERT_QT_VERSION_HERE@" name="QtVersion"/>
+ <property value="" name="QtBuild"/>
+ </properties>
+ <testcase result="pass" name="initTestCase"/>
+ <testcase result="pass" name="keyPressAndRelease"/>
+ <testcase result="pass" name="cleanupTestCase"/>
+ <system-err/>
+</testsuite>
diff --git a/tests/auto/testlib/selftests/expected_longstring.tap b/tests/auto/testlib/selftests/expected_longstring.tap
new file mode 100644
index 0000000000..ac870f2d53
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_longstring.tap
@@ -0,0 +1,23 @@
+TAP version 13
+# tst_LongString
+ok 1 - initTestCase()
+not ok 2 - failWithLongString()
+ ---
+ # Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui.
+
+Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc, quis gravida magna mi a libero. Fusce vulputate eleifend sapien. Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Nullam accumsan lorem in dui. Cras ultricies mi eu turpis hendrerit fringilla. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; In ac dui quis mi consectetuer lacinia.
+
+Nam pretium turpis et arcu. Duis arcu tortor, suscipit eget, imperdiet nec, imperdiet iaculis, ipsum. Sed aliquam ultrices mauris. Integer ante arcu, accumsan a, consectetuer eget, posuere ut, mauris. Praesent adipiscing. Phasellus ullamcorper ipsum rutrum nunc. Nunc nonummy metus. Vestibulum volutpat pretium libero. Cras id dui. Aenean ut eros et nisl sagittis vestibulum. Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Sed lectus. Donec mollis hendrerit risus. Phasellus nec sem in justo pellentesque facilisis. Etiam imperdiet imperdiet orci. Nunc nec neque. Phasellus leo dolor, tempus non, auctor et, hendrerit quis, nisi.
+
+Curabitur ligula sapien, tincidunt non, euismod vitae, posuere imperdiet, leo. Maecenas malesuada. Praesent congue erat at massa. Sed cursus turpis vitae tortor. Donec posuere vulputate arcu. Phasellus accumsan cursus velit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed aliquam, nisi quis porttitor congue, elit erat euismod orci, ac placerat dolor lectus quis orci. Phasellus consectetuer vestibulum elit. Aenean tellus metus, bibendum sed, posuere ac, mattis non, nunc. Vestibulum fringilla pede sit amet augue. In turpis. Pellentesque posuere. Praesent turpis.
+
+Aenean posuere, tortor sed cursus feugiat, nunc augue blandit nunc, eu sollicitudin urna dolor sagittis lacus. Donec elit libero, sodales nec, volutpat a, suscipit non, turpis. Nullam sagittis. Suspendisse pulvinar, augue ac venenatis condimentum, sem libero volutpat nibh, nec pellentesque velit pede quis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Fusce id purus. Ut varius tincidunt libero. Phasellus dolor. Maecenas vestibulum mollis diam. Pellentesque ut neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
+ at: tst_LongString::failWithLongString() (qtbase/tests/auto/testlib/selftests/longstring/tst_longstring.cpp:54)
+ file: qtbase/tests/auto/testlib/selftests/longstring/tst_longstring.cpp
+ line: 54
+ ...
+ok 3 - cleanupTestCase()
+1..3
+# tests 3
+# pass 2
+# fail 1
diff --git a/tests/auto/testlib/selftests/expected_maxwarnings.tap b/tests/auto/testlib/selftests/expected_maxwarnings.tap
new file mode 100644
index 0000000000..57bfbd8f8d
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_maxwarnings.tap
@@ -0,0 +1,2011 @@
+TAP version 13
+# MaxWarnings
+ok 1 - initTestCase()
+# 0
+# 1
+# 2
+# 3
+# 4
+# 5
+# 6
+# 7
+# 8
+# 9
+# 10
+# 11
+# 12
+# 13
+# 14
+# 15
+# 16
+# 17
+# 18
+# 19
+# 20
+# 21
+# 22
+# 23
+# 24
+# 25
+# 26
+# 27
+# 28
+# 29
+# 30
+# 31
+# 32
+# 33
+# 34
+# 35
+# 36
+# 37
+# 38
+# 39
+# 40
+# 41
+# 42
+# 43
+# 44
+# 45
+# 46
+# 47
+# 48
+# 49
+# 50
+# 51
+# 52
+# 53
+# 54
+# 55
+# 56
+# 57
+# 58
+# 59
+# 60
+# 61
+# 62
+# 63
+# 64
+# 65
+# 66
+# 67
+# 68
+# 69
+# 70
+# 71
+# 72
+# 73
+# 74
+# 75
+# 76
+# 77
+# 78
+# 79
+# 80
+# 81
+# 82
+# 83
+# 84
+# 85
+# 86
+# 87
+# 88
+# 89
+# 90
+# 91
+# 92
+# 93
+# 94
+# 95
+# 96
+# 97
+# 98
+# 99
+# 100
+# 101
+# 102
+# 103
+# 104
+# 105
+# 106
+# 107
+# 108
+# 109
+# 110
+# 111
+# 112
+# 113
+# 114
+# 115
+# 116
+# 117
+# 118
+# 119
+# 120
+# 121
+# 122
+# 123
+# 124
+# 125
+# 126
+# 127
+# 128
+# 129
+# 130
+# 131
+# 132
+# 133
+# 134
+# 135
+# 136
+# 137
+# 138
+# 139
+# 140
+# 141
+# 142
+# 143
+# 144
+# 145
+# 146
+# 147
+# 148
+# 149
+# 150
+# 151
+# 152
+# 153
+# 154
+# 155
+# 156
+# 157
+# 158
+# 159
+# 160
+# 161
+# 162
+# 163
+# 164
+# 165
+# 166
+# 167
+# 168
+# 169
+# 170
+# 171
+# 172
+# 173
+# 174
+# 175
+# 176
+# 177
+# 178
+# 179
+# 180
+# 181
+# 182
+# 183
+# 184
+# 185
+# 186
+# 187
+# 188
+# 189
+# 190
+# 191
+# 192
+# 193
+# 194
+# 195
+# 196
+# 197
+# 198
+# 199
+# 200
+# 201
+# 202
+# 203
+# 204
+# 205
+# 206
+# 207
+# 208
+# 209
+# 210
+# 211
+# 212
+# 213
+# 214
+# 215
+# 216
+# 217
+# 218
+# 219
+# 220
+# 221
+# 222
+# 223
+# 224
+# 225
+# 226
+# 227
+# 228
+# 229
+# 230
+# 231
+# 232
+# 233
+# 234
+# 235
+# 236
+# 237
+# 238
+# 239
+# 240
+# 241
+# 242
+# 243
+# 244
+# 245
+# 246
+# 247
+# 248
+# 249
+# 250
+# 251
+# 252
+# 253
+# 254
+# 255
+# 256
+# 257
+# 258
+# 259
+# 260
+# 261
+# 262
+# 263
+# 264
+# 265
+# 266
+# 267
+# 268
+# 269
+# 270
+# 271
+# 272
+# 273
+# 274
+# 275
+# 276
+# 277
+# 278
+# 279
+# 280
+# 281
+# 282
+# 283
+# 284
+# 285
+# 286
+# 287
+# 288
+# 289
+# 290
+# 291
+# 292
+# 293
+# 294
+# 295
+# 296
+# 297
+# 298
+# 299
+# 300
+# 301
+# 302
+# 303
+# 304
+# 305
+# 306
+# 307
+# 308
+# 309
+# 310
+# 311
+# 312
+# 313
+# 314
+# 315
+# 316
+# 317
+# 318
+# 319
+# 320
+# 321
+# 322
+# 323
+# 324
+# 325
+# 326
+# 327
+# 328
+# 329
+# 330
+# 331
+# 332
+# 333
+# 334
+# 335
+# 336
+# 337
+# 338
+# 339
+# 340
+# 341
+# 342
+# 343
+# 344
+# 345
+# 346
+# 347
+# 348
+# 349
+# 350
+# 351
+# 352
+# 353
+# 354
+# 355
+# 356
+# 357
+# 358
+# 359
+# 360
+# 361
+# 362
+# 363
+# 364
+# 365
+# 366
+# 367
+# 368
+# 369
+# 370
+# 371
+# 372
+# 373
+# 374
+# 375
+# 376
+# 377
+# 378
+# 379
+# 380
+# 381
+# 382
+# 383
+# 384
+# 385
+# 386
+# 387
+# 388
+# 389
+# 390
+# 391
+# 392
+# 393
+# 394
+# 395
+# 396
+# 397
+# 398
+# 399
+# 400
+# 401
+# 402
+# 403
+# 404
+# 405
+# 406
+# 407
+# 408
+# 409
+# 410
+# 411
+# 412
+# 413
+# 414
+# 415
+# 416
+# 417
+# 418
+# 419
+# 420
+# 421
+# 422
+# 423
+# 424
+# 425
+# 426
+# 427
+# 428
+# 429
+# 430
+# 431
+# 432
+# 433
+# 434
+# 435
+# 436
+# 437
+# 438
+# 439
+# 440
+# 441
+# 442
+# 443
+# 444
+# 445
+# 446
+# 447
+# 448
+# 449
+# 450
+# 451
+# 452
+# 453
+# 454
+# 455
+# 456
+# 457
+# 458
+# 459
+# 460
+# 461
+# 462
+# 463
+# 464
+# 465
+# 466
+# 467
+# 468
+# 469
+# 470
+# 471
+# 472
+# 473
+# 474
+# 475
+# 476
+# 477
+# 478
+# 479
+# 480
+# 481
+# 482
+# 483
+# 484
+# 485
+# 486
+# 487
+# 488
+# 489
+# 490
+# 491
+# 492
+# 493
+# 494
+# 495
+# 496
+# 497
+# 498
+# 499
+# 500
+# 501
+# 502
+# 503
+# 504
+# 505
+# 506
+# 507
+# 508
+# 509
+# 510
+# 511
+# 512
+# 513
+# 514
+# 515
+# 516
+# 517
+# 518
+# 519
+# 520
+# 521
+# 522
+# 523
+# 524
+# 525
+# 526
+# 527
+# 528
+# 529
+# 530
+# 531
+# 532
+# 533
+# 534
+# 535
+# 536
+# 537
+# 538
+# 539
+# 540
+# 541
+# 542
+# 543
+# 544
+# 545
+# 546
+# 547
+# 548
+# 549
+# 550
+# 551
+# 552
+# 553
+# 554
+# 555
+# 556
+# 557
+# 558
+# 559
+# 560
+# 561
+# 562
+# 563
+# 564
+# 565
+# 566
+# 567
+# 568
+# 569
+# 570
+# 571
+# 572
+# 573
+# 574
+# 575
+# 576
+# 577
+# 578
+# 579
+# 580
+# 581
+# 582
+# 583
+# 584
+# 585
+# 586
+# 587
+# 588
+# 589
+# 590
+# 591
+# 592
+# 593
+# 594
+# 595
+# 596
+# 597
+# 598
+# 599
+# 600
+# 601
+# 602
+# 603
+# 604
+# 605
+# 606
+# 607
+# 608
+# 609
+# 610
+# 611
+# 612
+# 613
+# 614
+# 615
+# 616
+# 617
+# 618
+# 619
+# 620
+# 621
+# 622
+# 623
+# 624
+# 625
+# 626
+# 627
+# 628
+# 629
+# 630
+# 631
+# 632
+# 633
+# 634
+# 635
+# 636
+# 637
+# 638
+# 639
+# 640
+# 641
+# 642
+# 643
+# 644
+# 645
+# 646
+# 647
+# 648
+# 649
+# 650
+# 651
+# 652
+# 653
+# 654
+# 655
+# 656
+# 657
+# 658
+# 659
+# 660
+# 661
+# 662
+# 663
+# 664
+# 665
+# 666
+# 667
+# 668
+# 669
+# 670
+# 671
+# 672
+# 673
+# 674
+# 675
+# 676
+# 677
+# 678
+# 679
+# 680
+# 681
+# 682
+# 683
+# 684
+# 685
+# 686
+# 687
+# 688
+# 689
+# 690
+# 691
+# 692
+# 693
+# 694
+# 695
+# 696
+# 697
+# 698
+# 699
+# 700
+# 701
+# 702
+# 703
+# 704
+# 705
+# 706
+# 707
+# 708
+# 709
+# 710
+# 711
+# 712
+# 713
+# 714
+# 715
+# 716
+# 717
+# 718
+# 719
+# 720
+# 721
+# 722
+# 723
+# 724
+# 725
+# 726
+# 727
+# 728
+# 729
+# 730
+# 731
+# 732
+# 733
+# 734
+# 735
+# 736
+# 737
+# 738
+# 739
+# 740
+# 741
+# 742
+# 743
+# 744
+# 745
+# 746
+# 747
+# 748
+# 749
+# 750
+# 751
+# 752
+# 753
+# 754
+# 755
+# 756
+# 757
+# 758
+# 759
+# 760
+# 761
+# 762
+# 763
+# 764
+# 765
+# 766
+# 767
+# 768
+# 769
+# 770
+# 771
+# 772
+# 773
+# 774
+# 775
+# 776
+# 777
+# 778
+# 779
+# 780
+# 781
+# 782
+# 783
+# 784
+# 785
+# 786
+# 787
+# 788
+# 789
+# 790
+# 791
+# 792
+# 793
+# 794
+# 795
+# 796
+# 797
+# 798
+# 799
+# 800
+# 801
+# 802
+# 803
+# 804
+# 805
+# 806
+# 807
+# 808
+# 809
+# 810
+# 811
+# 812
+# 813
+# 814
+# 815
+# 816
+# 817
+# 818
+# 819
+# 820
+# 821
+# 822
+# 823
+# 824
+# 825
+# 826
+# 827
+# 828
+# 829
+# 830
+# 831
+# 832
+# 833
+# 834
+# 835
+# 836
+# 837
+# 838
+# 839
+# 840
+# 841
+# 842
+# 843
+# 844
+# 845
+# 846
+# 847
+# 848
+# 849
+# 850
+# 851
+# 852
+# 853
+# 854
+# 855
+# 856
+# 857
+# 858
+# 859
+# 860
+# 861
+# 862
+# 863
+# 864
+# 865
+# 866
+# 867
+# 868
+# 869
+# 870
+# 871
+# 872
+# 873
+# 874
+# 875
+# 876
+# 877
+# 878
+# 879
+# 880
+# 881
+# 882
+# 883
+# 884
+# 885
+# 886
+# 887
+# 888
+# 889
+# 890
+# 891
+# 892
+# 893
+# 894
+# 895
+# 896
+# 897
+# 898
+# 899
+# 900
+# 901
+# 902
+# 903
+# 904
+# 905
+# 906
+# 907
+# 908
+# 909
+# 910
+# 911
+# 912
+# 913
+# 914
+# 915
+# 916
+# 917
+# 918
+# 919
+# 920
+# 921
+# 922
+# 923
+# 924
+# 925
+# 926
+# 927
+# 928
+# 929
+# 930
+# 931
+# 932
+# 933
+# 934
+# 935
+# 936
+# 937
+# 938
+# 939
+# 940
+# 941
+# 942
+# 943
+# 944
+# 945
+# 946
+# 947
+# 948
+# 949
+# 950
+# 951
+# 952
+# 953
+# 954
+# 955
+# 956
+# 957
+# 958
+# 959
+# 960
+# 961
+# 962
+# 963
+# 964
+# 965
+# 966
+# 967
+# 968
+# 969
+# 970
+# 971
+# 972
+# 973
+# 974
+# 975
+# 976
+# 977
+# 978
+# 979
+# 980
+# 981
+# 982
+# 983
+# 984
+# 985
+# 986
+# 987
+# 988
+# 989
+# 990
+# 991
+# 992
+# 993
+# 994
+# 995
+# 996
+# 997
+# 998
+# 999
+# 1000
+# 1001
+# 1002
+# 1003
+# 1004
+# 1005
+# 1006
+# 1007
+# 1008
+# 1009
+# 1010
+# 1011
+# 1012
+# 1013
+# 1014
+# 1015
+# 1016
+# 1017
+# 1018
+# 1019
+# 1020
+# 1021
+# 1022
+# 1023
+# 1024
+# 1025
+# 1026
+# 1027
+# 1028
+# 1029
+# 1030
+# 1031
+# 1032
+# 1033
+# 1034
+# 1035
+# 1036
+# 1037
+# 1038
+# 1039
+# 1040
+# 1041
+# 1042
+# 1043
+# 1044
+# 1045
+# 1046
+# 1047
+# 1048
+# 1049
+# 1050
+# 1051
+# 1052
+# 1053
+# 1054
+# 1055
+# 1056
+# 1057
+# 1058
+# 1059
+# 1060
+# 1061
+# 1062
+# 1063
+# 1064
+# 1065
+# 1066
+# 1067
+# 1068
+# 1069
+# 1070
+# 1071
+# 1072
+# 1073
+# 1074
+# 1075
+# 1076
+# 1077
+# 1078
+# 1079
+# 1080
+# 1081
+# 1082
+# 1083
+# 1084
+# 1085
+# 1086
+# 1087
+# 1088
+# 1089
+# 1090
+# 1091
+# 1092
+# 1093
+# 1094
+# 1095
+# 1096
+# 1097
+# 1098
+# 1099
+# 1100
+# 1101
+# 1102
+# 1103
+# 1104
+# 1105
+# 1106
+# 1107
+# 1108
+# 1109
+# 1110
+# 1111
+# 1112
+# 1113
+# 1114
+# 1115
+# 1116
+# 1117
+# 1118
+# 1119
+# 1120
+# 1121
+# 1122
+# 1123
+# 1124
+# 1125
+# 1126
+# 1127
+# 1128
+# 1129
+# 1130
+# 1131
+# 1132
+# 1133
+# 1134
+# 1135
+# 1136
+# 1137
+# 1138
+# 1139
+# 1140
+# 1141
+# 1142
+# 1143
+# 1144
+# 1145
+# 1146
+# 1147
+# 1148
+# 1149
+# 1150
+# 1151
+# 1152
+# 1153
+# 1154
+# 1155
+# 1156
+# 1157
+# 1158
+# 1159
+# 1160
+# 1161
+# 1162
+# 1163
+# 1164
+# 1165
+# 1166
+# 1167
+# 1168
+# 1169
+# 1170
+# 1171
+# 1172
+# 1173
+# 1174
+# 1175
+# 1176
+# 1177
+# 1178
+# 1179
+# 1180
+# 1181
+# 1182
+# 1183
+# 1184
+# 1185
+# 1186
+# 1187
+# 1188
+# 1189
+# 1190
+# 1191
+# 1192
+# 1193
+# 1194
+# 1195
+# 1196
+# 1197
+# 1198
+# 1199
+# 1200
+# 1201
+# 1202
+# 1203
+# 1204
+# 1205
+# 1206
+# 1207
+# 1208
+# 1209
+# 1210
+# 1211
+# 1212
+# 1213
+# 1214
+# 1215
+# 1216
+# 1217
+# 1218
+# 1219
+# 1220
+# 1221
+# 1222
+# 1223
+# 1224
+# 1225
+# 1226
+# 1227
+# 1228
+# 1229
+# 1230
+# 1231
+# 1232
+# 1233
+# 1234
+# 1235
+# 1236
+# 1237
+# 1238
+# 1239
+# 1240
+# 1241
+# 1242
+# 1243
+# 1244
+# 1245
+# 1246
+# 1247
+# 1248
+# 1249
+# 1250
+# 1251
+# 1252
+# 1253
+# 1254
+# 1255
+# 1256
+# 1257
+# 1258
+# 1259
+# 1260
+# 1261
+# 1262
+# 1263
+# 1264
+# 1265
+# 1266
+# 1267
+# 1268
+# 1269
+# 1270
+# 1271
+# 1272
+# 1273
+# 1274
+# 1275
+# 1276
+# 1277
+# 1278
+# 1279
+# 1280
+# 1281
+# 1282
+# 1283
+# 1284
+# 1285
+# 1286
+# 1287
+# 1288
+# 1289
+# 1290
+# 1291
+# 1292
+# 1293
+# 1294
+# 1295
+# 1296
+# 1297
+# 1298
+# 1299
+# 1300
+# 1301
+# 1302
+# 1303
+# 1304
+# 1305
+# 1306
+# 1307
+# 1308
+# 1309
+# 1310
+# 1311
+# 1312
+# 1313
+# 1314
+# 1315
+# 1316
+# 1317
+# 1318
+# 1319
+# 1320
+# 1321
+# 1322
+# 1323
+# 1324
+# 1325
+# 1326
+# 1327
+# 1328
+# 1329
+# 1330
+# 1331
+# 1332
+# 1333
+# 1334
+# 1335
+# 1336
+# 1337
+# 1338
+# 1339
+# 1340
+# 1341
+# 1342
+# 1343
+# 1344
+# 1345
+# 1346
+# 1347
+# 1348
+# 1349
+# 1350
+# 1351
+# 1352
+# 1353
+# 1354
+# 1355
+# 1356
+# 1357
+# 1358
+# 1359
+# 1360
+# 1361
+# 1362
+# 1363
+# 1364
+# 1365
+# 1366
+# 1367
+# 1368
+# 1369
+# 1370
+# 1371
+# 1372
+# 1373
+# 1374
+# 1375
+# 1376
+# 1377
+# 1378
+# 1379
+# 1380
+# 1381
+# 1382
+# 1383
+# 1384
+# 1385
+# 1386
+# 1387
+# 1388
+# 1389
+# 1390
+# 1391
+# 1392
+# 1393
+# 1394
+# 1395
+# 1396
+# 1397
+# 1398
+# 1399
+# 1400
+# 1401
+# 1402
+# 1403
+# 1404
+# 1405
+# 1406
+# 1407
+# 1408
+# 1409
+# 1410
+# 1411
+# 1412
+# 1413
+# 1414
+# 1415
+# 1416
+# 1417
+# 1418
+# 1419
+# 1420
+# 1421
+# 1422
+# 1423
+# 1424
+# 1425
+# 1426
+# 1427
+# 1428
+# 1429
+# 1430
+# 1431
+# 1432
+# 1433
+# 1434
+# 1435
+# 1436
+# 1437
+# 1438
+# 1439
+# 1440
+# 1441
+# 1442
+# 1443
+# 1444
+# 1445
+# 1446
+# 1447
+# 1448
+# 1449
+# 1450
+# 1451
+# 1452
+# 1453
+# 1454
+# 1455
+# 1456
+# 1457
+# 1458
+# 1459
+# 1460
+# 1461
+# 1462
+# 1463
+# 1464
+# 1465
+# 1466
+# 1467
+# 1468
+# 1469
+# 1470
+# 1471
+# 1472
+# 1473
+# 1474
+# 1475
+# 1476
+# 1477
+# 1478
+# 1479
+# 1480
+# 1481
+# 1482
+# 1483
+# 1484
+# 1485
+# 1486
+# 1487
+# 1488
+# 1489
+# 1490
+# 1491
+# 1492
+# 1493
+# 1494
+# 1495
+# 1496
+# 1497
+# 1498
+# 1499
+# 1500
+# 1501
+# 1502
+# 1503
+# 1504
+# 1505
+# 1506
+# 1507
+# 1508
+# 1509
+# 1510
+# 1511
+# 1512
+# 1513
+# 1514
+# 1515
+# 1516
+# 1517
+# 1518
+# 1519
+# 1520
+# 1521
+# 1522
+# 1523
+# 1524
+# 1525
+# 1526
+# 1527
+# 1528
+# 1529
+# 1530
+# 1531
+# 1532
+# 1533
+# 1534
+# 1535
+# 1536
+# 1537
+# 1538
+# 1539
+# 1540
+# 1541
+# 1542
+# 1543
+# 1544
+# 1545
+# 1546
+# 1547
+# 1548
+# 1549
+# 1550
+# 1551
+# 1552
+# 1553
+# 1554
+# 1555
+# 1556
+# 1557
+# 1558
+# 1559
+# 1560
+# 1561
+# 1562
+# 1563
+# 1564
+# 1565
+# 1566
+# 1567
+# 1568
+# 1569
+# 1570
+# 1571
+# 1572
+# 1573
+# 1574
+# 1575
+# 1576
+# 1577
+# 1578
+# 1579
+# 1580
+# 1581
+# 1582
+# 1583
+# 1584
+# 1585
+# 1586
+# 1587
+# 1588
+# 1589
+# 1590
+# 1591
+# 1592
+# 1593
+# 1594
+# 1595
+# 1596
+# 1597
+# 1598
+# 1599
+# 1600
+# 1601
+# 1602
+# 1603
+# 1604
+# 1605
+# 1606
+# 1607
+# 1608
+# 1609
+# 1610
+# 1611
+# 1612
+# 1613
+# 1614
+# 1615
+# 1616
+# 1617
+# 1618
+# 1619
+# 1620
+# 1621
+# 1622
+# 1623
+# 1624
+# 1625
+# 1626
+# 1627
+# 1628
+# 1629
+# 1630
+# 1631
+# 1632
+# 1633
+# 1634
+# 1635
+# 1636
+# 1637
+# 1638
+# 1639
+# 1640
+# 1641
+# 1642
+# 1643
+# 1644
+# 1645
+# 1646
+# 1647
+# 1648
+# 1649
+# 1650
+# 1651
+# 1652
+# 1653
+# 1654
+# 1655
+# 1656
+# 1657
+# 1658
+# 1659
+# 1660
+# 1661
+# 1662
+# 1663
+# 1664
+# 1665
+# 1666
+# 1667
+# 1668
+# 1669
+# 1670
+# 1671
+# 1672
+# 1673
+# 1674
+# 1675
+# 1676
+# 1677
+# 1678
+# 1679
+# 1680
+# 1681
+# 1682
+# 1683
+# 1684
+# 1685
+# 1686
+# 1687
+# 1688
+# 1689
+# 1690
+# 1691
+# 1692
+# 1693
+# 1694
+# 1695
+# 1696
+# 1697
+# 1698
+# 1699
+# 1700
+# 1701
+# 1702
+# 1703
+# 1704
+# 1705
+# 1706
+# 1707
+# 1708
+# 1709
+# 1710
+# 1711
+# 1712
+# 1713
+# 1714
+# 1715
+# 1716
+# 1717
+# 1718
+# 1719
+# 1720
+# 1721
+# 1722
+# 1723
+# 1724
+# 1725
+# 1726
+# 1727
+# 1728
+# 1729
+# 1730
+# 1731
+# 1732
+# 1733
+# 1734
+# 1735
+# 1736
+# 1737
+# 1738
+# 1739
+# 1740
+# 1741
+# 1742
+# 1743
+# 1744
+# 1745
+# 1746
+# 1747
+# 1748
+# 1749
+# 1750
+# 1751
+# 1752
+# 1753
+# 1754
+# 1755
+# 1756
+# 1757
+# 1758
+# 1759
+# 1760
+# 1761
+# 1762
+# 1763
+# 1764
+# 1765
+# 1766
+# 1767
+# 1768
+# 1769
+# 1770
+# 1771
+# 1772
+# 1773
+# 1774
+# 1775
+# 1776
+# 1777
+# 1778
+# 1779
+# 1780
+# 1781
+# 1782
+# 1783
+# 1784
+# 1785
+# 1786
+# 1787
+# 1788
+# 1789
+# 1790
+# 1791
+# 1792
+# 1793
+# 1794
+# 1795
+# 1796
+# 1797
+# 1798
+# 1799
+# 1800
+# 1801
+# 1802
+# 1803
+# 1804
+# 1805
+# 1806
+# 1807
+# 1808
+# 1809
+# 1810
+# 1811
+# 1812
+# 1813
+# 1814
+# 1815
+# 1816
+# 1817
+# 1818
+# 1819
+# 1820
+# 1821
+# 1822
+# 1823
+# 1824
+# 1825
+# 1826
+# 1827
+# 1828
+# 1829
+# 1830
+# 1831
+# 1832
+# 1833
+# 1834
+# 1835
+# 1836
+# 1837
+# 1838
+# 1839
+# 1840
+# 1841
+# 1842
+# 1843
+# 1844
+# 1845
+# 1846
+# 1847
+# 1848
+# 1849
+# 1850
+# 1851
+# 1852
+# 1853
+# 1854
+# 1855
+# 1856
+# 1857
+# 1858
+# 1859
+# 1860
+# 1861
+# 1862
+# 1863
+# 1864
+# 1865
+# 1866
+# 1867
+# 1868
+# 1869
+# 1870
+# 1871
+# 1872
+# 1873
+# 1874
+# 1875
+# 1876
+# 1877
+# 1878
+# 1879
+# 1880
+# 1881
+# 1882
+# 1883
+# 1884
+# 1885
+# 1886
+# 1887
+# 1888
+# 1889
+# 1890
+# 1891
+# 1892
+# 1893
+# 1894
+# 1895
+# 1896
+# 1897
+# 1898
+# 1899
+# 1900
+# 1901
+# 1902
+# 1903
+# 1904
+# 1905
+# 1906
+# 1907
+# 1908
+# 1909
+# 1910
+# 1911
+# 1912
+# 1913
+# 1914
+# 1915
+# 1916
+# 1917
+# 1918
+# 1919
+# 1920
+# 1921
+# 1922
+# 1923
+# 1924
+# 1925
+# 1926
+# 1927
+# 1928
+# 1929
+# 1930
+# 1931
+# 1932
+# 1933
+# 1934
+# 1935
+# 1936
+# 1937
+# 1938
+# 1939
+# 1940
+# 1941
+# 1942
+# 1943
+# 1944
+# 1945
+# 1946
+# 1947
+# 1948
+# 1949
+# 1950
+# 1951
+# 1952
+# 1953
+# 1954
+# 1955
+# 1956
+# 1957
+# 1958
+# 1959
+# 1960
+# 1961
+# 1962
+# 1963
+# 1964
+# 1965
+# 1966
+# 1967
+# 1968
+# 1969
+# 1970
+# 1971
+# 1972
+# 1973
+# 1974
+# 1975
+# 1976
+# 1977
+# 1978
+# 1979
+# 1980
+# 1981
+# 1982
+# 1983
+# 1984
+# 1985
+# 1986
+# 1987
+# 1988
+# 1989
+# 1990
+# 1991
+# 1992
+# 1993
+# 1994
+# 1995
+# 1996
+# 1997
+# 1998
+# 1999
+# 2000
+# Maximum amount of warnings exceeded. Use -maxwarnings to override.
+ok 2 - warn()
+ok 3 - cleanupTestCase()
+1..3
+# tests 3
+# pass 3
+# fail 0
diff --git a/tests/auto/testlib/selftests/expected_pairdiagnostics.tap b/tests/auto/testlib/selftests/expected_pairdiagnostics.tap
new file mode 100644
index 0000000000..9c45880c2d
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_pairdiagnostics.tap
@@ -0,0 +1,32 @@
+TAP version 13
+# tst_PairDiagnostics
+ok 1 - initTestCase()
+not ok 2 - testQPair()
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: "QPair(1,2)" (pair2)
+ found: "QPair(1,1)" (pair1)
+ expected: "QPair(1,2)" (pair2)
+ actual: "QPair(1,1)" (pair1)
+ at: tst_PairDiagnostics::testQPair() (qtbase/tests/auto/testlib/selftests/pairdiagnostics/tst_pairdiagnostics.cpp:51)
+ file: qtbase/tests/auto/testlib/selftests/pairdiagnostics/tst_pairdiagnostics.cpp
+ line: 51
+ ...
+not ok 3 - testStdPair()
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: "std::pair(1,2)" (pair2)
+ found: "std::pair(1,1)" (pair1)
+ expected: "std::pair(1,2)" (pair2)
+ actual: "std::pair(1,1)" (pair1)
+ at: tst_PairDiagnostics::testStdPair() (qtbase/tests/auto/testlib/selftests/pairdiagnostics/tst_pairdiagnostics.cpp:58)
+ file: qtbase/tests/auto/testlib/selftests/pairdiagnostics/tst_pairdiagnostics.cpp
+ line: 58
+ ...
+ok 4 - cleanupTestCase()
+1..4
+# tests 4
+# pass 2
+# fail 2
diff --git a/tests/auto/testlib/selftests/expected_singleskip.tap b/tests/auto/testlib/selftests/expected_singleskip.tap
new file mode 100644
index 0000000000..2cc09e7d26
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_singleskip.tap
@@ -0,0 +1,9 @@
+TAP version 13
+# tst_SingleSkip
+ok 1 - initTestCase()
+ok 2 - myTest() # SKIP skipping test
+ok 3 - cleanupTestCase()
+1..3
+# tests 3
+# pass 2
+# fail 0
diff --git a/tests/auto/testlib/selftests/expected_skip.tap b/tests/auto/testlib/selftests/expected_skip.tap
new file mode 100644
index 0000000000..adf9f692a9
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_skip.tap
@@ -0,0 +1,13 @@
+TAP version 13
+# tst_Skip
+ok 1 - initTestCase()
+ok 2 - test() # SKIP skipping all
+ok 3 - emptytest() # SKIP skipping all
+ok 4 - singleSkip(local 1) # SKIP skipping one
+# this line should only be reached once (true)
+ok 5 - singleSkip(local 2)
+ok 6 - cleanupTestCase()
+1..6
+# tests 6
+# pass 3
+# fail 0
diff --git a/tests/auto/testlib/selftests/expected_skipcleanup.tap b/tests/auto/testlib/selftests/expected_skipcleanup.tap
new file mode 100644
index 0000000000..4a3f8f852c
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_skipcleanup.tap
@@ -0,0 +1,9 @@
+TAP version 13
+# tst_SkipCleanup
+ok 1 - initTestCase()
+ok 2 - aTestFunction()
+ok 3 - cleanupTestCase() # SKIP Skip inside cleanupTestCase.
+1..3
+# tests 3
+# pass 2
+# fail 0
diff --git a/tests/auto/testlib/selftests/expected_skipinit.tap b/tests/auto/testlib/selftests/expected_skipinit.tap
new file mode 100644
index 0000000000..1fc38e79aa
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_skipinit.tap
@@ -0,0 +1,8 @@
+TAP version 13
+# tst_SkipInit
+ok 1 - initTestCase() # SKIP Skip inside initTestCase. This should skip all tests in the class.
+ok 2 - cleanupTestCase()
+1..2
+# tests 2
+# pass 1
+# fail 0
diff --git a/tests/auto/testlib/selftests/expected_skipinitdata.tap b/tests/auto/testlib/selftests/expected_skipinitdata.tap
new file mode 100644
index 0000000000..1ea96ca74e
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_skipinitdata.tap
@@ -0,0 +1,7 @@
+TAP version 13
+# tst_SkipInitData
+ok 1 - initTestCase() # SKIP Skip inside initTestCase_data. This should skip all tests in the class.
+1..1
+# tests 1
+# pass 0
+# fail 0
diff --git a/tests/auto/testlib/selftests/expected_sleep.tap b/tests/auto/testlib/selftests/expected_sleep.tap
new file mode 100644
index 0000000000..7caef214d2
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_sleep.tap
@@ -0,0 +1,9 @@
+TAP version 13
+# tst_Sleep
+ok 1 - initTestCase()
+ok 2 - sleep()
+ok 3 - cleanupTestCase()
+1..3
+# tests 3
+# pass 3
+# fail 0
diff --git a/tests/auto/testlib/selftests/expected_strcmp.tap b/tests/auto/testlib/selftests/expected_strcmp.tap
new file mode 100644
index 0000000000..af368e4745
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_strcmp.tap
@@ -0,0 +1,87 @@
+TAP version 13
+# tst_StrCmp
+ok 1 - initTestCase()
+ok 2 - compareCharStars()
+not ok 3 - compareByteArray() # TODO Next test should fail
+ ---
+ at: tst_StrCmp::compareByteArray() (qtbase/tests/auto/testlib/selftests/strcmp/tst_strcmp.cpp:75)
+ file: qtbase/tests/auto/testlib/selftests/strcmp/tst_strcmp.cpp
+ line: 75
+ ...
+not ok 3 - compareByteArray() # TODO Next test should fail
+ ---
+ at: tst_StrCmp::compareByteArray() (qtbase/tests/auto/testlib/selftests/strcmp/tst_strcmp.cpp:82)
+ file: qtbase/tests/auto/testlib/selftests/strcmp/tst_strcmp.cpp
+ line: 82
+ ...
+not ok 3 - compareByteArray() # TODO Next test should fail
+ ---
+ at: tst_StrCmp::compareByteArray() (qtbase/tests/auto/testlib/selftests/strcmp/tst_strcmp.cpp:89)
+ file: qtbase/tests/auto/testlib/selftests/strcmp/tst_strcmp.cpp
+ line: 89
+ ...
+not ok 3 - compareByteArray()
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"... (b)
+ found: "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"... (a)
+ expected: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"... (b)
+ actual: "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"... (a)
+ at: tst_StrCmp::compareByteArray() (qtbase/tests/auto/testlib/selftests/strcmp/tst_strcmp.cpp:96)
+ file: qtbase/tests/auto/testlib/selftests/strcmp/tst_strcmp.cpp
+ line: 96
+ ...
+not ok 4 - failByteArray()
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: "cba" (QByteArray("cba"))
+ found: "abc" (QByteArray("abc"))
+ expected: "cba" (QByteArray("cba"))
+ actual: "abc" (QByteArray("abc"))
+ at: tst_StrCmp::failByteArray() (qtbase/tests/auto/testlib/selftests/strcmp/tst_strcmp.cpp:102)
+ file: qtbase/tests/auto/testlib/selftests/strcmp/tst_strcmp.cpp
+ line: 102
+ ...
+not ok 5 - failByteArrayNull()
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: "" (QByteArray())
+ found: "foo" (QByteArray("foo"))
+ expected: "" (QByteArray())
+ actual: "foo" (QByteArray("foo"))
+ at: tst_StrCmp::failByteArrayNull() (qtbase/tests/auto/testlib/selftests/strcmp/tst_strcmp.cpp:108)
+ file: qtbase/tests/auto/testlib/selftests/strcmp/tst_strcmp.cpp
+ line: 108
+ ...
+not ok 6 - failByteArrayEmpty()
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: "foo" (QByteArray("foo"))
+ found: "" (QByteArray(""))
+ expected: "foo" (QByteArray("foo"))
+ actual: "" (QByteArray(""))
+ at: tst_StrCmp::failByteArrayEmpty() (qtbase/tests/auto/testlib/selftests/strcmp/tst_strcmp.cpp:113)
+ file: qtbase/tests/auto/testlib/selftests/strcmp/tst_strcmp.cpp
+ line: 113
+ ...
+not ok 7 - failByteArraySingleChars()
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: "7" (QByteArray("7"))
+ found: "6" (QByteArray("6"))
+ expected: "7" (QByteArray("7"))
+ actual: "6" (QByteArray("6"))
+ at: tst_StrCmp::failByteArraySingleChars() (qtbase/tests/auto/testlib/selftests/strcmp/tst_strcmp.cpp:120)
+ file: qtbase/tests/auto/testlib/selftests/strcmp/tst_strcmp.cpp
+ line: 120
+ ...
+ok 8 - cleanupTestCase()
+1..8
+# tests 8
+# pass 3
+# fail 5
diff --git a/tests/auto/testlib/selftests/expected_subtest.tap b/tests/auto/testlib/selftests/expected_subtest.tap
new file mode 100644
index 0000000000..67fe7be570
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_subtest.tap
@@ -0,0 +1,68 @@
+TAP version 13
+# tst_Subtest
+# initTestCase initTestCase (null)
+ok 1 - initTestCase()
+# init test1 (null)
+# test1 test1 (null)
+# cleanup test1 (null)
+ok 2 - test1()
+# test2_data test2 (null)
+# test2_data end
+# init test2 data0
+# test2 test2 data0
+# test2 end
+# cleanup test2 data0
+ok 3 - test2(data0)
+# init test2 data1
+# test2 test2 data1
+# test2 end
+# cleanup test2 data1
+ok 4 - test2(data1)
+# init test2 data2
+# test2 test2 data2
+# test2 end
+# cleanup test2 data2
+ok 5 - test2(data2)
+# test3_data test3 (null)
+# test3_data end
+# init test3 data0
+# test2 test3 data0
+# test2 end
+# cleanup test3 data0
+ok 6 - test3(data0)
+# init test3 data1
+# test2 test3 data1
+not ok 7 - test3(data1)
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: "hello0" (QString("hello0"))
+ found: "hello1" (str)
+ expected: "hello0" (QString("hello0"))
+ actual: "hello1" (str)
+ at: tst_Subtest::test3() (qtbase/tests/auto/testlib/selftests/subtest/tst_subtest.cpp:141)
+ file: qtbase/tests/auto/testlib/selftests/subtest/tst_subtest.cpp
+ line: 141
+ ...
+# cleanup test3 data1
+# init test3 data2
+# test2 test3 data2
+not ok 8 - test3(data2)
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: "hello0" (QString("hello0"))
+ found: "hello2" (str)
+ expected: "hello0" (QString("hello0"))
+ actual: "hello2" (str)
+ at: tst_Subtest::test3() (qtbase/tests/auto/testlib/selftests/subtest/tst_subtest.cpp:141)
+ file: qtbase/tests/auto/testlib/selftests/subtest/tst_subtest.cpp
+ line: 141
+ ...
+# cleanup test3 data2
+# cleanupTestCase cleanupTestCase (null)
+ok 9 - cleanupTestCase()
+1..9
+# tests 9
+# pass 7
+# fail 2
diff --git a/tests/auto/testlib/selftests/expected_tuplediagnostics.lightxml b/tests/auto/testlib/selftests/expected_tuplediagnostics.lightxml
new file mode 100644
index 0000000000..810941d894
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_tuplediagnostics.lightxml
@@ -0,0 +1,34 @@
+<Environment>
+ <QtVersion>@INSERT_QT_VERSION_HERE@</QtVersion>
+ <QtBuild/>
+ <QTestVersion>@INSERT_QT_VERSION_HERE@</QTestVersion>
+</Environment>
+<TestFunction name="initTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="testEmptyTuple">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="testSimpleTuple">
+<Incident type="fail" file="/localqtbase/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp" line="0">
+ <Description><![CDATA[Compared values are not the same
+ Actual (std::tuple<int>{1}): std::tuple(1)
+ Expected (std::tuple<int>{2}): std::tuple(2)]]></Description>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="testTuple">
+<Incident type="fail" file="/localqtbase/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp" line="0">
+ <Description><![CDATA[Compared values are not the same
+ Actual (tuple1): std::tuple(42, 'Y', "tuple1")
+ Expected (tuple2): std::tuple(42, 'Y', "tuple2")]]></Description>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="cleanupTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<Duration msecs="0"/>
diff --git a/tests/auto/testlib/selftests/expected_tuplediagnostics.tap b/tests/auto/testlib/selftests/expected_tuplediagnostics.tap
new file mode 100644
index 0000000000..9e007c14e1
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_tuplediagnostics.tap
@@ -0,0 +1,33 @@
+TAP version 13
+# tst_TupleDiagnostics
+ok 1 - initTestCase()
+ok 2 - testEmptyTuple()
+not ok 3 - testSimpleTuple()
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: std::tuple(2) (std::tuple<int>{2})
+ found: std::tuple(1) (std::tuple<int>{1})
+ expected: std::tuple(2) (std::tuple<int>{2})
+ actual: std::tuple(1) (std::tuple<int>{1})
+ at: tst_TupleDiagnostics::testSimpleTuple() (/localqtbase/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp:53)
+ file: /localqtbase/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp
+ line: 53
+ ...
+not ok 4 - testTuple()
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: std::tuple(42, 'Y', "tuple2") (tuple2)
+ found: std::tuple(42, 'Y', "tuple1") (tuple1)
+ expected: std::tuple(42, 'Y', "tuple2") (tuple2)
+ actual: std::tuple(42, 'Y', "tuple1") (tuple1)
+ at: tst_TupleDiagnostics::testTuple() (/localqtbase/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp:60)
+ file: /localqtbase/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp
+ line: 60
+ ...
+ok 5 - cleanupTestCase()
+1..5
+# tests 5
+# pass 3
+# fail 2
diff --git a/tests/auto/testlib/selftests/expected_tuplediagnostics.teamcity b/tests/auto/testlib/selftests/expected_tuplediagnostics.teamcity
new file mode 100644
index 0000000000..a395857c60
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_tuplediagnostics.teamcity
@@ -0,0 +1,14 @@
+##teamcity[testSuiteStarted name='tst_TupleDiagnostics' flowId='tst_TupleDiagnostics']
+##teamcity[testStarted name='initTestCase()' flowId='tst_TupleDiagnostics']
+##teamcity[testFinished name='initTestCase()' flowId='tst_TupleDiagnostics']
+##teamcity[testStarted name='testEmptyTuple()' flowId='tst_TupleDiagnostics']
+##teamcity[testFinished name='testEmptyTuple()' flowId='tst_TupleDiagnostics']
+##teamcity[testStarted name='testSimpleTuple()' flowId='tst_TupleDiagnostics']
+##teamcity[testFailed name='testSimpleTuple()' message='Failure! |[Loc: /localqtbase/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp(0)|]' details='Compared values are not the same|n Actual (std::tuple<int>{1}): std::tuple(1)|n Expected (std::tuple<int>{2}): std::tuple(2)' flowId='tst_TupleDiagnostics']
+##teamcity[testFinished name='testSimpleTuple()' flowId='tst_TupleDiagnostics']
+##teamcity[testStarted name='testTuple()' flowId='tst_TupleDiagnostics']
+##teamcity[testFailed name='testTuple()' message='Failure! |[Loc: /localqtbase/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp(0)|]' details='Compared values are not the same|n Actual (tuple1): std::tuple(42, |'Y|', "tuple1")|n Expected (tuple2): std::tuple(42, |'Y|', "tuple2")' flowId='tst_TupleDiagnostics']
+##teamcity[testFinished name='testTuple()' flowId='tst_TupleDiagnostics']
+##teamcity[testStarted name='cleanupTestCase()' flowId='tst_TupleDiagnostics']
+##teamcity[testFinished name='cleanupTestCase()' flowId='tst_TupleDiagnostics']
+##teamcity[testSuiteFinished name='tst_TupleDiagnostics' flowId='tst_TupleDiagnostics']
diff --git a/tests/auto/testlib/selftests/expected_tuplediagnostics.txt b/tests/auto/testlib/selftests/expected_tuplediagnostics.txt
new file mode 100644
index 0000000000..ce568bf6c0
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_tuplediagnostics.txt
@@ -0,0 +1,15 @@
+********* Start testing of tst_TupleDiagnostics *********
+Config: Using QtTest library
+PASS : tst_TupleDiagnostics::initTestCase()
+PASS : tst_TupleDiagnostics::testEmptyTuple()
+FAIL! : tst_TupleDiagnostics::testSimpleTuple() Compared values are not the same
+ Actual (std::tuple<int>{1}): std::tuple(1)
+ Expected (std::tuple<int>{2}): std::tuple(2)
+ Loc: [/localqtbase/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp(0)]
+FAIL! : tst_TupleDiagnostics::testTuple() Compared values are not the same
+ Actual (tuple1): std::tuple(42, 'Y', "tuple1")
+ Expected (tuple2): std::tuple(42, 'Y', "tuple2")
+ Loc: [/localqtbase/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp(0)]
+PASS : tst_TupleDiagnostics::cleanupTestCase()
+Totals: 3 passed, 2 failed, 0 skipped, 0 blacklisted, 0ms
+********* Finished testing of tst_TupleDiagnostics *********
diff --git a/tests/auto/testlib/selftests/expected_tuplediagnostics.xml b/tests/auto/testlib/selftests/expected_tuplediagnostics.xml
new file mode 100644
index 0000000000..4c55a6d393
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_tuplediagnostics.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestCase name="tst_TupleDiagnostics">
+<Environment>
+ <QtVersion>@INSERT_QT_VERSION_HERE@</QtVersion>
+ <QtBuild/>
+ <QTestVersion>@INSERT_QT_VERSION_HERE@</QTestVersion>
+</Environment>
+<TestFunction name="initTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="testEmptyTuple">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="testSimpleTuple">
+<Incident type="fail" file="/localqtbase/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp" line="0">
+ <Description><![CDATA[Compared values are not the same
+ Actual (std::tuple<int>{1}): std::tuple(1)
+ Expected (std::tuple<int>{2}): std::tuple(2)]]></Description>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="testTuple">
+<Incident type="fail" file="/localqtbase/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp" line="0">
+ <Description><![CDATA[Compared values are not the same
+ Actual (tuple1): std::tuple(42, 'Y', "tuple1")
+ Expected (tuple2): std::tuple(42, 'Y', "tuple2")]]></Description>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="cleanupTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<Duration msecs="0"/>
+</TestCase>
diff --git a/tests/auto/testlib/selftests/expected_tuplediagnostics.xunitxml b/tests/auto/testlib/selftests/expected_tuplediagnostics.xunitxml
new file mode 100644
index 0000000000..0a276a17f5
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_tuplediagnostics.xunitxml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<testsuite errors="0" failures="2" tests="5" name="tst_TupleDiagnostics">
+ <properties>
+ <property value="@INSERT_QT_VERSION_HERE@" name="QTestVersion"/>
+ <property value="@INSERT_QT_VERSION_HERE@" name="QtVersion"/>
+ <property value="" name="QtBuild"/>
+ </properties>
+ <testcase result="pass" name="initTestCase"/>
+ <testcase result="pass" name="testEmptyTuple"/>
+ <testcase result="fail" name="testSimpleTuple">
+ <failure message="Compared values are not the same
+ Actual (std::tuple&lt;int&gt;{1}): std::tuple(1)
+ Expected (std::tuple&lt;int&gt;{2}): std::tuple(2)" result="fail"/>
+ </testcase>
+ <testcase result="fail" name="testTuple">
+ <failure message="Compared values are not the same
+ Actual (tuple1): std::tuple(42, &apos;Y&apos;, &quot;tuple1&quot;)
+ Expected (tuple2): std::tuple(42, &apos;Y&apos;, &quot;tuple2&quot;)" result="fail"/>
+ </testcase>
+ <testcase result="pass" name="cleanupTestCase"/>
+ <system-err/>
+</testsuite>
diff --git a/tests/auto/testlib/selftests/expected_verbose1.tap b/tests/auto/testlib/selftests/expected_verbose1.tap
new file mode 100644
index 0000000000..ad53e8f14e
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_verbose1.tap
@@ -0,0 +1,118 @@
+TAP version 13
+# tst_Counting
+ok 1 - initTestCase()
+ok 2 - testPassPass(row 1)
+ok 3 - testPassPass(row 2)
+ok 4 - testPassSkip(row 1)
+ok 5 - testPassSkip(row 2) # SKIP Skipping
+ok 6 - testPassFail(row 1)
+not ok 7 - testPassFail(row 2)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (false)
+ found: false (false)
+ expected: true (false)
+ actual: false (false)
+ at: tst_Counting::testPassFail() (qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp:102)
+ file: qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp
+ line: 102
+ ...
+ok 8 - testSkipPass(row 1) # SKIP Skipping
+ok 9 - testSkipPass(row 2)
+ok 10 - testSkipSkip(row 1) # SKIP Skipping
+ok 11 - testSkipSkip(row 2) # SKIP Skipping
+ok 12 - testSkipFail(row 1) # SKIP Skipping
+not ok 13 - testSkipFail(row 2)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (false)
+ found: false (false)
+ expected: true (false)
+ actual: false (false)
+ at: tst_Counting::testSkipFail() (qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp:102)
+ file: qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp
+ line: 102
+ ...
+not ok 14 - testFailPass(row 1)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (false)
+ found: false (false)
+ expected: true (false)
+ actual: false (false)
+ at: tst_Counting::testFailPass() (qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp:102)
+ file: qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp
+ line: 102
+ ...
+ok 15 - testFailPass(row 2)
+not ok 16 - testFailSkip(row 1)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (false)
+ found: false (false)
+ expected: true (false)
+ actual: false (false)
+ at: tst_Counting::testFailSkip() (qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp:102)
+ file: qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp
+ line: 102
+ ...
+ok 17 - testFailSkip(row 2) # SKIP Skipping
+not ok 18 - testFailFail(row 1)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (false)
+ found: false (false)
+ expected: true (false)
+ actual: false (false)
+ at: tst_Counting::testFailFail() (qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp:102)
+ file: qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp
+ line: 102
+ ...
+not ok 19 - testFailFail(row 2)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (false)
+ found: false (false)
+ expected: true (false)
+ actual: false (false)
+ at: tst_Counting::testFailFail() (qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp:102)
+ file: qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp
+ line: 102
+ ...
+ok 20 - testFailInInit(before)
+not ok 21 - testFailInInit(fail)
+ ---
+ # Fail in init()
+ at: tst_Counting::testFailInInit() (qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp:221)
+ file: qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp
+ line: 221
+ ...
+ok 22 - testFailInInit(after)
+ok 23 - testFailInCleanup(before)
+# This test function should execute and then QFAIL in cleanup()
+not ok 24 - testFailInCleanup(fail)
+ ---
+ # Fail in cleanup()
+ at: tst_Counting::testFailInCleanup() (qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp:229)
+ file: qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp
+ line: 229
+ ...
+ok 25 - testFailInCleanup(after)
+ok 26 - testSkipInInit(before)
+ok 27 - testSkipInInit(skip) # SKIP Skip in init()
+ok 28 - testSkipInInit(after)
+ok 29 - testSkipInCleanup(before)
+# This test function should execute and then QSKIP in cleanup()
+ok 30 - testSkipInCleanup(skip) # SKIP Skip in cleanup()
+ok 31 - testSkipInCleanup(after)
+ok 32 - cleanupTestCase()
+1..32
+# tests 32
+# pass 16
+# fail 8
diff --git a/tests/auto/testlib/selftests/expected_verbose2.tap b/tests/auto/testlib/selftests/expected_verbose2.tap
new file mode 100644
index 0000000000..7e6a7280a4
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_verbose2.tap
@@ -0,0 +1,136 @@
+TAP version 13
+# tst_Counting
+ok 1 - initTestCase()
+# QVERIFY(true)
+# QCOMPARE(2 + 1, 3)
+ok 2 - testPassPass(row 1)
+# QVERIFY(true)
+# QCOMPARE(2 + 1, 3)
+ok 3 - testPassPass(row 2)
+# QVERIFY(true)
+# QCOMPARE(2 + 1, 3)
+ok 4 - testPassSkip(row 1)
+ok 5 - testPassSkip(row 2) # SKIP Skipping
+# QVERIFY(true)
+# QCOMPARE(2 + 1, 3)
+ok 6 - testPassFail(row 1)
+# QVERIFY(false)
+not ok 7 - testPassFail(row 2)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (false)
+ found: false (false)
+ expected: true (false)
+ actual: false (false)
+ at: tst_Counting::testPassFail() (qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp:102)
+ file: qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp
+ line: 102
+ ...
+ok 8 - testSkipPass(row 1) # SKIP Skipping
+# QVERIFY(true)
+# QCOMPARE(2 + 1, 3)
+ok 9 - testSkipPass(row 2)
+ok 10 - testSkipSkip(row 1) # SKIP Skipping
+ok 11 - testSkipSkip(row 2) # SKIP Skipping
+ok 12 - testSkipFail(row 1) # SKIP Skipping
+# QVERIFY(false)
+not ok 13 - testSkipFail(row 2)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (false)
+ found: false (false)
+ expected: true (false)
+ actual: false (false)
+ at: tst_Counting::testSkipFail() (qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp:102)
+ file: qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp
+ line: 102
+ ...
+# QVERIFY(false)
+not ok 14 - testFailPass(row 1)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (false)
+ found: false (false)
+ expected: true (false)
+ actual: false (false)
+ at: tst_Counting::testFailPass() (qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp:102)
+ file: qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp
+ line: 102
+ ...
+# QVERIFY(true)
+# QCOMPARE(2 + 1, 3)
+ok 15 - testFailPass(row 2)
+# QVERIFY(false)
+not ok 16 - testFailSkip(row 1)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (false)
+ found: false (false)
+ expected: true (false)
+ actual: false (false)
+ at: tst_Counting::testFailSkip() (qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp:102)
+ file: qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp
+ line: 102
+ ...
+ok 17 - testFailSkip(row 2) # SKIP Skipping
+# QVERIFY(false)
+not ok 18 - testFailFail(row 1)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (false)
+ found: false (false)
+ expected: true (false)
+ actual: false (false)
+ at: tst_Counting::testFailFail() (qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp:102)
+ file: qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp
+ line: 102
+ ...
+# QVERIFY(false)
+not ok 19 - testFailFail(row 2)
+ ---
+ type: QVERIFY
+ message: Verification failed
+ wanted: true (false)
+ found: false (false)
+ expected: true (false)
+ actual: false (false)
+ at: tst_Counting::testFailFail() (qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp:102)
+ file: qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp
+ line: 102
+ ...
+ok 20 - testFailInInit(before)
+not ok 21 - testFailInInit(fail)
+ ---
+ # Fail in init()
+ at: tst_Counting::testFailInInit() (qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp:221)
+ file: qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp
+ line: 221
+ ...
+ok 22 - testFailInInit(after)
+ok 23 - testFailInCleanup(before)
+# This test function should execute and then QFAIL in cleanup()
+not ok 24 - testFailInCleanup(fail)
+ ---
+ # Fail in cleanup()
+ at: tst_Counting::testFailInCleanup() (qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp:229)
+ file: qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp
+ line: 229
+ ...
+ok 25 - testFailInCleanup(after)
+ok 26 - testSkipInInit(before)
+ok 27 - testSkipInInit(skip) # SKIP Skip in init()
+ok 28 - testSkipInInit(after)
+ok 29 - testSkipInCleanup(before)
+# This test function should execute and then QSKIP in cleanup()
+ok 30 - testSkipInCleanup(skip) # SKIP Skip in cleanup()
+ok 31 - testSkipInCleanup(after)
+ok 32 - cleanupTestCase()
+1..32
+# tests 32
+# pass 16
+# fail 8
diff --git a/tests/auto/testlib/selftests/expected_verifyexceptionthrown.tap b/tests/auto/testlib/selftests/expected_verifyexceptionthrown.tap
new file mode 100644
index 0000000000..2b04c08cdb
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_verifyexceptionthrown.tap
@@ -0,0 +1,53 @@
+TAP version 13
+# tst_VerifyExceptionThrown
+ok 1 - initTestCase()
+ok 2 - testCorrectStdTypes()
+ok 3 - testCorrectStdExceptions()
+ok 4 - testCorrectMyExceptions()
+not ok 5 - testFailInt()
+ ---
+ # Expected exception of type double to be thrown but unknown exception caught
+ at: tst_VerifyExceptionThrown::testFailInt() (qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp:115)
+ file: qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp
+ line: 115
+ ...
+not ok 6 - testFailStdString()
+ ---
+ # Expected exception of type char* to be thrown but unknown exception caught
+ at: tst_VerifyExceptionThrown::testFailStdString() (qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp:120)
+ file: qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp
+ line: 120
+ ...
+not ok 7 - testFailStdRuntimeError()
+ ---
+ # Expected exception of type std::runtime_error to be thrown but std::exception caught with message: logic error
+ at: tst_VerifyExceptionThrown::testFailStdRuntimeError() (qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp:125)
+ file: qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp
+ line: 125
+ ...
+not ok 8 - testFailMyException()
+ ---
+ # Expected exception of type MyBaseException to be thrown but std::exception caught with message: logic error
+ at: tst_VerifyExceptionThrown::testFailMyException() (qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp:130)
+ file: qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp
+ line: 130
+ ...
+not ok 9 - testFailMyDerivedException()
+ ---
+ # Expected exception of type std::runtime_error to be thrown but std::exception caught with message: MyDerivedException
+ at: tst_VerifyExceptionThrown::testFailMyDerivedException() (qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp:135)
+ file: qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp
+ line: 135
+ ...
+not ok 10 - testFailNoException()
+ ---
+ # Expected exception of type std::exception to be thrown but no exception caught
+ at: tst_VerifyExceptionThrown::testFailNoException() (qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp:140)
+ file: qtbase/tests/auto/testlib/selftests/verifyexceptionthrown/tst_verifyexceptionthrown.cpp
+ line: 140
+ ...
+ok 11 - cleanupTestCase()
+1..11
+# tests 11
+# pass 5
+# fail 6
diff --git a/tests/auto/testlib/selftests/expected_warnings.tap b/tests/auto/testlib/selftests/expected_warnings.tap
new file mode 100644
index 0000000000..0e357cb770
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_warnings.tap
@@ -0,0 +1,42 @@
+TAP version 13
+# tst_Warnings
+ok 1 - initTestCase()
+# Warning
+# Warning
+# Debug
+# Debug
+# Info
+# Info
+# Baba
+# Baba
+# Bubublabla
+# Babablabla
+ok 2 - testWarnings()
+# Did not receive message: "Warning0"
+# Did not receive message: "Warning1"
+not ok 3 - testMissingWarnings()
+ ---
+ # Not all expected messages were received
+ ...
+# Did not receive any message matching: "Warning\s\d"
+not ok 4 - testMissingWarningsRegularExpression()
+ ---
+ # Not all expected messages were received
+ ...
+# Did not receive message: "Warning0"
+# Did not receive message: "Warning1"
+not ok 5 - testMissingWarningsWithData(first row)
+ ---
+ # Not all expected messages were received
+ ...
+# Did not receive message: "Warning0"
+# Did not receive message: "Warning1"
+not ok 6 - testMissingWarningsWithData(second row)
+ ---
+ # Not all expected messages were received
+ ...
+ok 7 - cleanupTestCase()
+1..7
+# tests 7
+# pass 3
+# fail 4
diff --git a/tests/auto/testlib/selftests/expected_xunit.tap b/tests/auto/testlib/selftests/expected_xunit.tap
new file mode 100644
index 0000000000..13ff7e45a3
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_xunit.tap
@@ -0,0 +1,44 @@
+TAP version 13
+# tst_Xunit
+ok 1 - initTestCase()
+# just a QWARN() !
+ok 2 - testFunc1()
+# a qDebug() call with comment-ending stuff -->
+not ok 3 - testFunc2()
+ ---
+ type: QCOMPARE
+ message: Compared values are not the same
+ wanted: 3 (3)
+ found: 2 (2)
+ expected: 3 (3)
+ actual: 2 (2)
+ at: tst_Xunit::testFunc2() (qtbase/tests/auto/testlib/selftests/xunit/tst_xunit.cpp:61)
+ file: qtbase/tests/auto/testlib/selftests/xunit/tst_xunit.cpp
+ line: 61
+ ...
+ok 4 - testFunc3() # SKIP skipping this function!
+not ok 5 - testFunc4()
+ ---
+ # a forced failure!
+ at: tst_Xunit::testFunc4() (qtbase/tests/auto/testlib/selftests/xunit/tst_xunit.cpp:71)
+ file: qtbase/tests/auto/testlib/selftests/xunit/tst_xunit.cpp
+ line: 71
+ ...
+not ok 6 - testFunc5() # TODO this failure is expected
+ ---
+ at: tst_Xunit::testFunc5() (qtbase/tests/auto/testlib/selftests/xunit/tst_xunit.cpp:85)
+ file: qtbase/tests/auto/testlib/selftests/xunit/tst_xunit.cpp
+ line: 85
+ ...
+not ok 7 - testFunc6() # TODO this failure is also expected
+ ---
+ at: tst_Xunit::testFunc6() (qtbase/tests/auto/testlib/selftests/xunit/tst_xunit.cpp:91)
+ file: qtbase/tests/auto/testlib/selftests/xunit/tst_xunit.cpp
+ line: 91
+ ...
+ok 8 - testFunc7() # TODO 'true' returned TRUE unexpectedly. ()
+ok 9 - cleanupTestCase()
+1..9
+# tests 9
+# pass 5
+# fail 3
diff --git a/tests/auto/testlib/selftests/generate_expected_output.py b/tests/auto/testlib/selftests/generate_expected_output.py
index aa11ca4fe7..1996416e8c 100755
--- a/tests/auto/testlib/selftests/generate_expected_output.py
+++ b/tests/auto/testlib/selftests/generate_expected_output.py
@@ -37,9 +37,7 @@
# it to the output of each test, ignoring various boring changes.
# This script canonicalises the parts that would exhibit those boring
# changes, so as to avoid noise in git (and conflicts in merges) for
-# the saved copies of the output. If you add or remove any files, be
-# sure to update selftests.qrc to match; the selftest only sees files
-# listed there.
+# the saved copies of the output.
import os
import subprocess
@@ -116,10 +114,13 @@ class Cleaner (object):
raise Fail('Unable to find', command, 'in $PATH')
# Are we being run from the right place ?
- myNames = scriptPath.split(os.path.sep)
- if not (here.split(os.path.sep)[-5:] == myNames[-6:-1]
+ scriptPath, myName = os.path.split(scriptPath)
+ hereNames, depth = scriptPath.split(os.path.sep), 5
+ hereNames = hereNames[-depth:] # path components from qtbase down
+ assert hereNames[0] == 'qtbase', ('Script moved: please correct depth', hereNames)
+ if not (here.split(os.path.sep)[-depth:] == hereNames
and os.path.isfile(qmake)):
- raise Fail('Run', myNames[-1], 'in its directory of a completed build')
+ raise Fail('Run', myName, 'in its directory of a completed build')
try:
qtver = subprocess.check_output([qmake, '-query', 'QT_VERSION'])
@@ -127,8 +128,17 @@ class Cleaner (object):
raise Fail(what.strerror)
qtver = qtver.strip().decode('utf-8')
- scriptPath = os.path.dirname(scriptPath) # ditch leaf file-name
- sentinel = os.path.sep + 'qtbase' + os.path.sep # '/qtbase/'
+ hereNames = tuple(hereNames)
+ # Add path to specific sources and to tst_*.cpp if missing (for in-source builds):
+ patterns += ((r'(^|[^/])\b(qtestcase.cpp)\b', r'\1qtbase/src/testlib/\2'),
+ # Add more special cases here, if they show up !
+ (r'([[" ])\.\./(counting/tst_counting.cpp)\b',
+ r'\1' + os.path.sep.join(hereNames + (r'\2',))),
+ # The common pattern:
+ (r'(^|[^/])\b(tst_)?([a-z]+\d*)\.cpp\b',
+ r'\1' + os.path.sep.join(hereNames + (r'\3', r'\2\3.cpp'))))
+
+ sentinel = os.path.sep + hereNames[0] + os.path.sep # '/qtbase/'
# Identify the path prefix of our qtbase ancestor directory
# (source, build and $PWD, when different); trim such prefixes
# off all paths we see.
@@ -212,7 +222,7 @@ class Scanner (object):
del re
def generateTestData(testname, clean,
- formats = ('xml', 'txt', 'xunitxml', 'lightxml', 'teamcity'),
+ formats = ('xml', 'txt', 'xunitxml', 'lightxml', 'teamcity', 'tap'),
extraArgs = {
"commandlinedata": "fiveTablePasses fiveTablePasses:fiveTablePasses_data1 -v2",
"benchlibcallgrind": "-callgrind",
diff --git a/tests/auto/testlib/selftests/keyboard/keyboard.pro b/tests/auto/testlib/selftests/keyboard/keyboard.pro
new file mode 100644
index 0000000000..0097318797
--- /dev/null
+++ b/tests/auto/testlib/selftests/keyboard/keyboard.pro
@@ -0,0 +1,7 @@
+SOURCES += tst_keyboard.cpp
+QT += testlib testlib-private gui gui-private
+
+macos:CONFIG -= app_bundle
+CONFIG -= debug_and_release_target
+
+TARGET = keyboard
diff --git a/tests/auto/testlib/selftests/keyboard/tst_keyboard.cpp b/tests/auto/testlib/selftests/keyboard/tst_keyboard.cpp
new file mode 100644
index 0000000000..e185be8532
--- /dev/null
+++ b/tests/auto/testlib/selftests/keyboard/tst_keyboard.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/qtest.h>
+#include <QtGui/qwindow.h>
+
+class tst_Keyboard : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void keyPressAndRelease();
+};
+
+class KeyWindow : public QWindow
+{
+public:
+ void keyPressEvent(QKeyEvent *event) override
+ {
+ QSharedPointer<QKeyEvent> copiedEvent(new QKeyEvent(event->type(), event->key(),
+ event->modifiers(), event->text(), event->isAutoRepeat(), event->count()));
+ mEventOrder.append(copiedEvent);
+ }
+
+ void keyReleaseEvent(QKeyEvent *event) override
+ {
+ QSharedPointer<QKeyEvent> copiedEvent(new QKeyEvent(event->type(), event->key(),
+ event->modifiers(), event->text(), event->isAutoRepeat(), event->count()));
+ mEventOrder.append(copiedEvent);
+ }
+
+ QVector<QSharedPointer<QKeyEvent>> mEventOrder;
+};
+
+void tst_Keyboard::keyPressAndRelease()
+{
+ KeyWindow window;
+ window.show();
+ window.setGeometry(100, 100, 200, 200);
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+ QVERIFY(QTest::qWaitForWindowActive(&window));
+
+ QTest::keyPress(&window, Qt::Key_A);
+ QTest::keyRelease(&window, Qt::Key_A);
+ QCOMPARE(window.mEventOrder.size(), 2);
+
+ const auto pressEvent = window.mEventOrder.at(0);
+ QCOMPARE(pressEvent->type(), QEvent::KeyPress);
+ QCOMPARE(pressEvent->key(), Qt::Key_A);
+ QCOMPARE(pressEvent->modifiers(), Qt::NoModifier);
+ QCOMPARE(pressEvent->text(), "a");
+ QCOMPARE(pressEvent->isAutoRepeat(), false);
+
+ const auto releaseEvent = window.mEventOrder.at(1);
+ QCOMPARE(releaseEvent->type(), QEvent::KeyRelease);
+ QCOMPARE(releaseEvent->key(), Qt::Key_A);
+ QCOMPARE(releaseEvent->modifiers(), Qt::NoModifier);
+ QCOMPARE(releaseEvent->text(), "a");
+ QCOMPARE(releaseEvent->isAutoRepeat(), false);
+}
+
+QTEST_MAIN(tst_Keyboard)
+#include "tst_keyboard.moc"
diff --git a/tests/auto/testlib/selftests/selftests.pri b/tests/auto/testlib/selftests/selftests.pri
index 079f3f7959..05ed6d9905 100644
--- a/tests/auto/testlib/selftests/selftests.pri
+++ b/tests/auto/testlib/selftests/selftests.pri
@@ -43,12 +43,16 @@ SUBPROGRAMS = \
sleep \
strcmp \
subtest \
+ tuplediagnostics \
verbose1 \
verbose2 \
verifyexceptionthrown \
warnings \
- xunit \
- mouse
+ xunit
+
+qtHaveModule(gui): SUBPROGRAMS += \
+ keyboard \
+ mouse
INCLUDEPATH += ../../../../shared/
HEADERS += ../../../../shared/emulationdetector.h
diff --git a/tests/auto/testlib/selftests/selftests.qrc b/tests/auto/testlib/selftests/selftests.qrc
deleted file mode 100644
index 75d3375394..0000000000
--- a/tests/auto/testlib/selftests/selftests.qrc
+++ /dev/null
@@ -1,219 +0,0 @@
-<RCC>
- <qresource prefix="/">
- <file>expected_assert.lightxml</file>
- <file>expected_assert.teamcity</file>
- <file>expected_assert.txt</file>
- <file>expected_assert.xml</file>
- <file>expected_assert.xunitxml</file>
- <file>expected_badxml.lightxml</file>
- <file>expected_badxml.teamcity</file>
- <file>expected_badxml.txt</file>
- <file>expected_badxml.xml</file>
- <file>expected_badxml.xunitxml</file>
- <file>expected_benchlibcallgrind_0.txt</file>
- <file>expected_benchlibcallgrind_1.txt</file>
- <file>expected_benchlibcallgrind.csv</file>
- <file>expected_benchlibcallgrind.lightxml</file>
- <file>expected_benchlibcallgrind.xml</file>
- <file>expected_benchlibcallgrind.xunitxml</file>
- <file>expected_benchlibcounting.csv</file>
- <file>expected_benchlibcounting.lightxml</file>
- <file>expected_benchlibcounting.txt</file>
- <file>expected_benchlibcounting.xml</file>
- <file>expected_benchlibcounting.xunitxml</file>
- <file>expected_benchlibeventcounter.csv</file>
- <file>expected_benchlibeventcounter.lightxml</file>
- <file>expected_benchlibeventcounter.txt</file>
- <file>expected_benchlibeventcounter.xml</file>
- <file>expected_benchlibeventcounter.xunitxml</file>
- <file>expected_benchliboptions.lightxml</file>
- <file>expected_benchliboptions.txt</file>
- <file>expected_benchliboptions.xml</file>
- <file>expected_benchliboptions.xunitxml</file>
- <file>expected_benchlibtickcounter.csv</file>
- <file>expected_benchlibtickcounter.lightxml</file>
- <file>expected_benchlibtickcounter.txt</file>
- <file>expected_benchlibtickcounter.xml</file>
- <file>expected_benchlibtickcounter.xunitxml</file>
- <file>expected_benchlibwalltime.csv</file>
- <file>expected_benchlibwalltime.lightxml</file>
- <file>expected_benchlibwalltime.txt</file>
- <file>expected_benchlibwalltime.xml</file>
- <file>expected_benchlibwalltime.xunitxml</file>
- <file>expected_blacklisted.lightxml</file>
- <file>expected_blacklisted.txt</file>
- <file>expected_blacklisted.xml</file>
- <file>expected_blacklisted.xunitxml</file>
- <file>expected_cmptest.lightxml</file>
- <file>expected_cmptest.teamcity</file>
- <file>expected_cmptest.txt</file>
- <file>expected_cmptest.xml</file>
- <file>expected_cmptest.xunitxml</file>
- <file>expected_commandlinedata.lightxml</file>
- <file>expected_commandlinedata.teamcity</file>
- <file>expected_commandlinedata.txt</file>
- <file>expected_commandlinedata.xml</file>
- <file>expected_commandlinedata.xunitxml</file>
- <file>expected_counting.lightxml</file>
- <file>expected_counting.teamcity</file>
- <file>expected_counting.txt</file>
- <file>expected_counting.xml</file>
- <file>expected_counting.xunitxml</file>
- <file>expected_crashes_1.txt</file>
- <file>expected_crashes_2.txt</file>
- <file>expected_crashes_3.txt</file>
- <file>expected_datatable.lightxml</file>
- <file>expected_datatable.teamcity</file>
- <file>expected_datatable.txt</file>
- <file>expected_datatable.xml</file>
- <file>expected_datatable.xunitxml</file>
- <file>expected_datetime.lightxml</file>
- <file>expected_datetime.teamcity</file>
- <file>expected_datetime.txt</file>
- <file>expected_datetime.xml</file>
- <file>expected_datetime.xunitxml</file>
- <file>expected_differentexec.lightxml</file>
- <file>expected_differentexec.txt</file>
- <file>expected_differentexec.xml</file>
- <file>expected_differentexec.xunitxml</file>
- <file>expected_exceptionthrow.lightxml</file>
- <file>expected_exceptionthrow.teamcity</file>
- <file>expected_exceptionthrow.txt</file>
- <file>expected_exceptionthrow.xml</file>
- <file>expected_exceptionthrow.xunitxml</file>
- <file>expected_expectfail.lightxml</file>
- <file>expected_expectfail.teamcity</file>
- <file>expected_expectfail.txt</file>
- <file>expected_expectfail.xml</file>
- <file>expected_expectfail.xunitxml</file>
- <file>expected_failcleanup.lightxml</file>
- <file>expected_failcleanup.teamcity</file>
- <file>expected_failcleanup.txt</file>
- <file>expected_failcleanup.xml</file>
- <file>expected_failcleanup.xunitxml</file>
- <file>expected_failinit.lightxml</file>
- <file>expected_failinit.teamcity</file>
- <file>expected_failinit.txt</file>
- <file>expected_failinit.xml</file>
- <file>expected_failinit.xunitxml</file>
- <file>expected_failinitdata.lightxml</file>
- <file>expected_failinitdata.teamcity</file>
- <file>expected_failinitdata.txt</file>
- <file>expected_failinitdata.xml</file>
- <file>expected_failinitdata.xunitxml</file>
- <file>expected_fetchbogus.lightxml</file>
- <file>expected_fetchbogus.teamcity</file>
- <file>expected_fetchbogus.txt</file>
- <file>expected_fetchbogus.xml</file>
- <file>expected_fetchbogus.xunitxml</file>
- <file>expected_findtestdata.lightxml</file>
- <file>expected_findtestdata.teamcity</file>
- <file>expected_findtestdata.txt</file>
- <file>expected_findtestdata.xml</file>
- <file>expected_findtestdata.xunitxml</file>
- <file>expected_float.lightxml</file>
- <file>expected_float.txt</file>
- <file>expected_float.xml</file>
- <file>expected_float.xunitxml</file>
- <file>expected_globaldata.lightxml</file>
- <file>expected_globaldata.teamcity</file>
- <file>expected_globaldata.txt</file>
- <file>expected_globaldata.xml</file>
- <file>expected_globaldata.xunitxml</file>
- <file>expected_longstring.lightxml</file>
- <file>expected_longstring.teamcity</file>
- <file>expected_longstring.txt</file>
- <file>expected_longstring.xml</file>
- <file>expected_longstring.xunitxml</file>
- <file>expected_maxwarnings.lightxml</file>
- <file>expected_maxwarnings.teamcity</file>
- <file>expected_maxwarnings.txt</file>
- <file>expected_maxwarnings.xml</file>
- <file>expected_maxwarnings.xunitxml</file>
- <file>expected_multiexec.lightxml</file>
- <file>expected_multiexec.txt</file>
- <file>expected_multiexec.xml</file>
- <file>expected_multiexec.xunitxml</file>
- <file>expected_pairdiagnostics.lightxml</file>
- <file>expected_pairdiagnostics.teamcity</file>
- <file>expected_pairdiagnostics.txt</file>
- <file>expected_pairdiagnostics.xml</file>
- <file>expected_pairdiagnostics.xunitxml</file>
- <file>expected_printdatatags.txt</file>
- <file>expected_printdatatagswithglobaltags.txt</file>
- <file>expected_qexecstringlist.lightxml</file>
- <file>expected_qexecstringlist.txt</file>
- <file>expected_qexecstringlist.xml</file>
- <file>expected_qexecstringlist.xunitxml</file>
- <file>expected_silent.lightxml</file>
- <file>expected_silent.teamcity</file>
- <file>expected_silent.txt</file>
- <file>expected_silent.xml</file>
- <file>expected_silent.xunitxml</file>
- <file>expected_singleskip.lightxml</file>
- <file>expected_singleskip.teamcity</file>
- <file>expected_singleskip.txt</file>
- <file>expected_singleskip.xml</file>
- <file>expected_singleskip.xunitxml</file>
- <file>expected_skip.lightxml</file>
- <file>expected_skip.teamcity</file>
- <file>expected_skip.txt</file>
- <file>expected_skip.xml</file>
- <file>expected_skip.xunitxml</file>
- <file>expected_skipcleanup.lightxml</file>
- <file>expected_skipcleanup.teamcity</file>
- <file>expected_skipcleanup.txt</file>
- <file>expected_skipcleanup.xml</file>
- <file>expected_skipcleanup.xunitxml</file>
- <file>expected_skipinit.lightxml</file>
- <file>expected_skipinit.txt</file>
- <file>expected_skipinit.teamcity</file>
- <file>expected_skipinit.xml</file>
- <file>expected_skipinit.xunitxml</file>
- <file>expected_skipinitdata.lightxml</file>
- <file>expected_skipinitdata.teamcity</file>
- <file>expected_skipinitdata.txt</file>
- <file>expected_skipinitdata.xml</file>
- <file>expected_skipinitdata.xunitxml</file>
- <file>expected_sleep.lightxml</file>
- <file>expected_sleep.teamcity</file>
- <file>expected_sleep.txt</file>
- <file>expected_sleep.xml</file>
- <file>expected_sleep.xunitxml</file>
- <file>expected_strcmp.lightxml</file>
- <file>expected_strcmp.teamcity</file>
- <file>expected_strcmp.txt</file>
- <file>expected_strcmp.xml</file>
- <file>expected_strcmp.xunitxml</file>
- <file>expected_subtest.lightxml</file>
- <file>expected_subtest.txt</file>
- <file>expected_subtest.teamcity</file>
- <file>expected_subtest.xml</file>
- <file>expected_subtest.xunitxml</file>
- <file>expected_verbose1.lightxml</file>
- <file>expected_verbose1.teamcity</file>
- <file>expected_verbose1.txt</file>
- <file>expected_verbose1.xml</file>
- <file>expected_verbose1.xunitxml</file>
- <file>expected_verbose2.lightxml</file>
- <file>expected_verbose2.teamcity</file>
- <file>expected_verbose2.txt</file>
- <file>expected_verbose2.xml</file>
- <file>expected_verbose2.xunitxml</file>
- <file>expected_verifyexceptionthrown.lightxml</file>
- <file>expected_verifyexceptionthrown.teamcity</file>
- <file>expected_verifyexceptionthrown.txt</file>
- <file>expected_verifyexceptionthrown.xml</file>
- <file>expected_verifyexceptionthrown.xunitxml</file>
- <file>expected_warnings.lightxml</file>
- <file>expected_warnings.teamcity</file>
- <file>expected_warnings.txt</file>
- <file>expected_warnings.xml</file>
- <file>expected_warnings.xunitxml</file>
- <file>expected_xunit.lightxml</file>
- <file>expected_xunit.teamcity</file>
- <file>expected_xunit.txt</file>
- <file>expected_xunit.xml</file>
- <file>expected_xunit.xunitxml</file>
- </qresource>
-</RCC>
diff --git a/tests/auto/testlib/selftests/test/test.pro b/tests/auto/testlib/selftests/test/test.pro
index bd2366f3e8..ec1633ebff 100644
--- a/tests/auto/testlib/selftests/test/test.pro
+++ b/tests/auto/testlib/selftests/test/test.pro
@@ -12,7 +12,9 @@ win32 {
}
}
-RESOURCES += ../selftests.qrc
+expected_files.files = $$files($$PWD/../expected_*)
+expected_files.base = $$PWD/..
+RESOURCES += expected_files
include(../selftests.pri)
!android:!winrt: for(file, SUBPROGRAMS): TEST_HELPER_INSTALLS += "../$${file}/$${file}"
diff --git a/tests/auto/testlib/selftests/tst_selftests.cpp b/tests/auto/testlib/selftests/tst_selftests.cpp
index 63e5721e7e..c5f847562e 100644
--- a/tests/auto/testlib/selftests/tst_selftests.cpp
+++ b/tests/auto/testlib/selftests/tst_selftests.cpp
@@ -62,11 +62,22 @@ private slots:
private:
void doRunSubTest(QString const& subdir, QStringList const& loggers, QStringList const& arguments, bool crashes);
+ bool compareOutput(const QString &logger, const QString &subdir,
+ const QByteArray &rawOutput, const QByteArrayList &actual,
+ const QByteArrayList &expected,
+ QString *errorMessage) const;
+ bool compareLine(const QString &logger, const QString &subdir, bool benchmark,
+ const QString &actualLine, const QString &expLine,
+ QString *errorMessage) const;
+ bool checkXml(const QString &logger, QByteArray rawOutput,
+ QString *errorMessage) const;
+
QString logName(const QString &logger) const;
QList<LoggerSet> allLoggerSets() const;
QTemporaryDir tempDir;
QRegularExpression durationRegExp;
+ QRegularExpression teamcityLocRegExp;
};
struct BenchmarkResult
@@ -81,46 +92,50 @@ struct BenchmarkResult
static BenchmarkResult parse(QString const&, QString*);
};
-QT_BEGIN_NAMESPACE
-namespace QTest
+static QString msgMismatch(const QString &actual, const QString &expected)
{
-template <>
-inline bool qCompare
- (BenchmarkResult const &r1, BenchmarkResult const &r2,
- const char* actual, const char* expected, const char* file, int line)
+ return QLatin1String("Mismatch:\n'") + actual + QLatin1String("'\n !=\n'")
+ + expected + QLatin1Char('\'');
+}
+
+static bool compareBenchmarkResult(BenchmarkResult const &r1, BenchmarkResult const &r2,
+ QString *errorMessage)
{
// First make sure the iterations and unit match.
if (r1.iterations != r2.iterations || r1.unit != r2.unit) {
// Nope - compare whole string for best failure message
- return qCompare(r1.toString(), r2.toString(), actual, expected, file, line);
+ *errorMessage = msgMismatch(r1.toString(), r2.toString());
+ return false;
}
// Now check the value. Some variance is allowed, and how much depends on
// the measured unit.
qreal variance = 0.;
- if (r1.unit == "msecs" || r1.unit == "WalltimeMilliseconds") {
+ if (r1.unit == QLatin1String("msecs") || r1.unit == QLatin1String("WalltimeMilliseconds"))
variance = 0.1;
- }
- else if (r1.unit == "instruction reads") {
+ else if (r1.unit == QLatin1String("instruction reads"))
variance = 0.001;
- }
- else if (r1.unit == "CPU ticks" || r1.unit == "CPUTicks") {
+ else if (r1.unit == QLatin1String("CPU ticks") || r1.unit == QLatin1String("CPUTicks"))
variance = 0.001;
- }
+
if (variance == 0.) {
// No variance allowed - compare whole string
- return qCompare(r1.toString(), r2.toString(), actual, expected, file, line);
+ const QString r1S = r1.toString();
+ const QString r2S = r2.toString();
+ if (r1S != r2S) {
+ *errorMessage = msgMismatch(r1S, r2S);
+ return false;
+ }
+ return true;
}
- if (qAbs(qreal(r1.total) - qreal(r2.total)) <= qreal(r1.total)*variance) {
- return compare_helper(true, 0, 0, 0, actual, expected, file, line);
+ if (qAbs(qreal(r1.total) - qreal(r2.total)) > qreal(r1.total) * variance) {
+ // Whoops, didn't match. Compare the whole string for the most useful failure message.
+ *errorMessage = msgMismatch(r1.toString(), r2.toString());
+ return false;
}
-
- // Whoops, didn't match. Compare the whole string for the most useful failure message.
- return qCompare(r1.toString(), r2.toString(), actual, expected, file, line);
-}
+ return true;
}
-QT_END_NAMESPACE
// Split the passed block of text into an array of lines, replacing any
// filenames and line numbers with generic markers to avoid failing the test
@@ -227,26 +242,6 @@ static QByteArray runDiff(const QByteArrayList &expected, const QByteArrayList &
return result;
}
-// Print the difference preferably using 'diff', else just print lines
-static void printDifference(const QByteArrayList &expected, const QByteArrayList &actual)
-{
- QDebug info = qInfo();
- info.noquote();
- info.nospace();
- const QByteArray diff = runDiff(expected, actual);
- if (diff.isEmpty()) {
- info << "<<<<<<\n";
- for (const QByteArray &line : actual)
- info << line << '\n';
- info << "======\n";
- for (const QByteArray &line : expected)
- info << line << '\n';
- info << ">>>>>>\n";
- } else {
- info << diff;
- }
-}
-
// Each test is run with a set of one or more test output loggers.
// This struct holds information about one such test.
struct LoggerSet
@@ -315,6 +310,14 @@ QList<LoggerSet> tst_Selftests::allLoggerSets() const
QStringList() << "teamcity",
QStringList() << "-teamcity" << "-o" << logName("teamcity")
)
+ << LoggerSet("old stdout tap",
+ QStringList() << "stdout tap",
+ QStringList() << "-tap"
+ )
+ << LoggerSet("old tap",
+ QStringList() << "tap",
+ QStringList() << "-tap" << "-o" << logName("tap")
+ )
// Test with new-style options for a single logger
<< LoggerSet("new stdout txt",
QStringList() << "stdout txt",
@@ -362,6 +365,14 @@ QList<LoggerSet> tst_Selftests::allLoggerSets() const
QStringList() << "teamcity",
QStringList() << "-o" << logName("teamcity")+",teamcity"
)
+ << LoggerSet("new stdout tap",
+ QStringList() << "stdout tap",
+ QStringList() << "-o" << "-,tap"
+ )
+ << LoggerSet("new tap",
+ QStringList() << "tap",
+ QStringList() << "-o" << logName("tap")+",tap"
+ )
// Test with two loggers (don't test all 32 combinations, just a sample)
<< LoggerSet("stdout txt + txt",
QStringList() << "stdout txt" << "txt",
@@ -385,13 +396,14 @@ QList<LoggerSet> tst_Selftests::allLoggerSets() const
)
// All loggers at the same time (except csv)
<< LoggerSet("all loggers",
- QStringList() << "txt" << "xml" << "lightxml" << "stdout txt" << "xunitxml",
+ QStringList() << "txt" << "xml" << "lightxml" << "stdout txt" << "xunitxml" << "tap",
QStringList() << "-o" << logName("txt")+",txt"
<< "-o" << logName("xml")+",xml"
<< "-o" << logName("lightxml")+",lightxml"
<< "-o" << "-,txt"
<< "-o" << logName("xunitxml")+",xunitxml"
<< "-o" << logName("teamcity")+",teamcity"
+ << "-o" << logName("tap")+",tap"
)
;
}
@@ -399,6 +411,7 @@ QList<LoggerSet> tst_Selftests::allLoggerSets() const
tst_Selftests::tst_Selftests()
: tempDir(QDir::tempPath() + "/tst_selftests.XXXXXX")
, durationRegExp("<Duration msecs=\"[\\d\\.]+\"/>")
+ , teamcityLocRegExp("\\|\\[Loc: .*\\(\\d*\\)\\|\\]")
{}
void tst_Selftests::initTestCase()
@@ -464,6 +477,7 @@ void tst_Selftests::runSubTest_data()
<< "findtestdata"
<< "float"
<< "globaldata"
+ << "keyboard"
<< "longstring"
<< "maxwarnings"
<< "multiexec"
@@ -480,6 +494,7 @@ void tst_Selftests::runSubTest_data()
<< "sleep"
<< "strcmp"
<< "subtest"
+ << "tuplediagnostics"
<< "verbose1"
<< "verbose2"
#ifndef QT_NO_EXCEPTIONS
@@ -760,147 +775,203 @@ void tst_Selftests::doRunSubTest(QString const& subdir, QStringList const& logge
}
QList<QByteArray> res = splitLines(actualOutputs[n]);
- const QString expectedFileName = expectedFileNameFromTest(subdir, logger);
- QList<QByteArray> exp = expectedResult(expectedFileName);
+ QString errorMessage;
+ QString expectedFileName = expectedFileNameFromTest(subdir, logger);
+ QByteArrayList exp = expectedResult(expectedFileName);
+ if (!exp.isEmpty()) {
#ifdef Q_CC_MINGW
- // MinGW formats double numbers differently
- if (n == 0 && subdir == QStringLiteral("float")) {
- for (int i = 0; i < exp.size(); ++i) {
- exp[i].replace("e-07", "e-007");
- exp[i].replace("e+07", "e+007");
- }
- }
-#endif
-
- // For the "crashes" test, there are multiple versions of the
- // expected output. Load the one with the same line count as
- // the actual output.
- if (exp.count() == 0) {
- QList<QList<QByteArray> > expArr;
- QList<QByteArray> tmp;
- int i = 1;
- do {
- tmp = expectedResult(expectedFileNameFromTest(subdir + QLatin1Char('_') + QString::number(i++), logger));
- if (tmp.count())
- expArr += tmp;
- } while (tmp.count());
-
- for (int j = 0; j < expArr.count(); ++j) {
- if (res.count() == expArr.at(j).count()) {
- exp = expArr.at(j);
- break;
+ // MinGW formats double numbers differently (last verified with 7.1)
+ if (n == 0 && subdir == QStringLiteral("float")) {
+ for (int i = 0; i < exp.size(); ++i) {
+ exp[i].replace("e-07", "e-007");
+ exp[i].replace("e+07", "e+007");
}
}
-
- if (expArr.count()) {
- QVERIFY2(exp.count(),
- qPrintable(QString::fromLatin1("None of the expected output files for "
- "%1 format has matching line count.")
- .arg(loggers.at(n))));
+#endif
+ if (!compareOutput(logger, subdir, actualOutputs[n], res, exp, &errorMessage)) {
+ errorMessage.prepend(QLatin1Char('"') + logger + QLatin1String("\", ")
+ + expectedFileName + QLatin1Char(' '));
+ errorMessage += QLatin1String("\nActual:\n") + QLatin1String(actualOutputs[n]);
+ const QByteArray diff = runDiff(exp, res);
+ if (!diff.isEmpty())
+ errorMessage += QLatin1String("\nDiff:\n") + QLatin1String(diff);
+ QFAIL(qPrintable(errorMessage));
}
} else {
- if (res.count() != exp.count()) {
- printDifference(exp, res);
- QVERIFY2(res.count() == exp.count(),
- qPrintable(QString::fromLatin1("Mismatch in line count: %1 != %2 (%3, %4).")
- .arg(res.count()).arg(exp.count()).arg(loggers.at(n), expectedFileName)));
+ // For the "crashes" and other tests, there are multiple versions of the
+ // expected output. Loop until a matching one is found.
+ bool ok = false;
+ for (int i = 1; !ok; ++i) {
+ expectedFileName = expectedFileNameFromTest(subdir + QLatin1Char('_') + QString::number(i), logger);
+ const QByteArrayList exp = expectedResult(expectedFileName);
+ if (exp.isEmpty())
+ break;
+ QString errorMessage2;
+ ok = compareOutput(logger, subdir, actualOutputs[n], res, exp, &errorMessage2);
+ if (!ok)
+ errorMessage += QLatin1Char('\n') + expectedFileName + QLatin1String(": ") + errorMessage2;
+ }
+ if (!ok) { // Use QDebug's quote mechanism to report potentially garbled output.
+ errorMessage.prepend(QLatin1String("Cannot find a matching file for ") + subdir);
+ errorMessage += QLatin1String("\nActual:\n");
+ QDebug(&errorMessage) << actualOutputs[n];
+ QFAIL(qPrintable(errorMessage));
}
}
+ }
+}
- // By this point, we should have loaded a non-empty expected data file.
- QVERIFY2(exp.count(),
- qPrintable(QString::fromLatin1("Expected test data for %1 format is empty or not found.")
- .arg(loggers.at(n))));
-
- // For xml output formats, verify that the log is valid XML.
- if (logFormat(logger) == "xunitxml" || logFormat(logger) == "xml" || logFormat(logger) == "lightxml") {
- QByteArray xml(actualOutputs[n]);
- // lightxml intentionally skips the root element, which technically makes it
- // not valid XML.
- // We'll add that ourselves for the purpose of validation.
- if (logFormat(logger) == "lightxml") {
- xml.prepend("<root>");
- xml.append("</root>");
- }
+static QString teamCityLocation() { return QStringLiteral("|[Loc: _FILE_(_LINE_)|]"); }
+static QString qtVersionPlaceHolder() { return QStringLiteral("@INSERT_QT_VERSION_HERE@"); }
- QXmlStreamReader reader(xml);
+bool tst_Selftests::compareOutput(const QString &logger, const QString &subdir,
+ const QByteArray &rawOutput, const QByteArrayList &actual,
+ const QByteArrayList &expected,
+ QString *errorMessage) const
+{
- while (!reader.atEnd())
- reader.readNext();
+ if (actual.size() != expected.size()) {
+ *errorMessage = QString::fromLatin1("Mismatch in line count: %1 != %2.")
+ .arg(actual.size()).arg(expected.size());
+ return false;
+ }
- QVERIFY2(!reader.error(), qPrintable(QString("line %1, col %2: %3")
- .arg(reader.lineNumber())
- .arg(reader.columnNumber())
- .arg(reader.errorString())
- ));
+ // For xml output formats, verify that the log is valid XML.
+ if (logger.endsWith(QLatin1String("xml")) && !checkXml(logger, rawOutput, errorMessage))
+ return false;
+
+ // Verify that the actual output is an acceptable match for the
+ // expected output.
+
+ const QString qtVersion = QLatin1String(QT_VERSION_STR);
+ bool benchmark = false;
+ for (int i = 0, size = actual.size(); i < size; ++i) {
+ const QByteArray &actualLineBA = actual.at(i);
+ // the __FILE__ __LINE__ output is compiler dependent, skip it
+ if (actualLineBA.startsWith(" Loc: [") && actualLineBA.endsWith(")]"))
+ continue;
+ if (actualLineBA.endsWith(" : failure location"))
+ continue;
+
+ if (actualLineBA.startsWith("Config: Using QtTest library") // Text build string
+ || actualLineBA.startsWith(" <QtBuild") // XML, Light XML build string
+ || (actualLineBA.startsWith(" <property value=") && actualLineBA.endsWith("name=\"QtBuild\"/>"))) { // XUNIT-XML build string
+ continue;
}
- // Verify that the actual output is an acceptable match for the
- // expected output.
- bool benchmark = false;
- for (int i = 0; i < res.count(); ++i) {
- QByteArray line = res.at(i);
- // the __FILE__ __LINE__ output is compiler dependent, skip it
- if (line.startsWith(" Loc: [") && line.endsWith(")]"))
- continue;
- if (line.endsWith(" : failure location"))
- continue;
+ QString actualLine = QString::fromLatin1(actualLineBA);
+ QString expectedLine = QString::fromLatin1(expected.at(i));
+ expectedLine.replace(qtVersionPlaceHolder(), qtVersion);
- if (line.startsWith("Config: Using QtTest library") // Text build string
- || line.startsWith(" <QtBuild") // XML, Light XML build string
- || (line.startsWith(" <property value=") && line.endsWith("name=\"QtBuild\"/>"))) { // XUNIT-XML build string
- continue;
- }
+ // Special handling for ignoring _FILE_ and _LINE_ if logger is teamcity
+ if (logger.endsWith(QLatin1String("teamcity"))) {
+ actualLine.replace(teamcityLocRegExp, teamCityLocation());
+ expectedLine.replace(teamcityLocRegExp, teamCityLocation());
+ }
- QByteArray expLine = exp.at(i);
+ if (logger.endsWith(QLatin1String("tap"))) {
+ if (expectedLine.contains(QLatin1String("at:"))
+ || expectedLine.contains(QLatin1String("file:"))
+ || expectedLine.contains(QLatin1String("line:")))
+ actualLine = expectedLine;
+ }
- // Special handling for ignoring _FILE_ and _LINE_ if logger is teamcity
- if (logFormat(logger) == "teamcity") {
- QRegularExpression teamcityLocRegExp("\\|\\[Loc: .*\\(\\d*\\)\\|\\]");
- line = QString(line).replace(teamcityLocRegExp, "|[Loc: _FILE_(_LINE_)|]").toLatin1();
- expLine = QString(expLine).replace(teamcityLocRegExp, "|[Loc: _FILE_(_LINE_)|]").toLatin1();
- }
+ if (!compareLine(logger, subdir, benchmark, actualLine,
+ expectedLine, errorMessage)) {
+ errorMessage->prepend(QLatin1String("Line ") + QString::number(i + 1)
+ + QLatin1String(": "));
+ return false;
+ }
- const QString output(QString::fromLatin1(line));
- const QString expected(QString::fromLatin1(expLine).replace("@INSERT_QT_VERSION_HERE@", QT_VERSION_STR));
+ benchmark = actualLineBA.startsWith("RESULT : ");
+ }
+ return true;
+}
- if (subdir == "assert" && output.contains("ASSERT: ") && expected.contains("ASSERT: ") && output != expected)
- // Q_ASSERT uses __FILE__, the exact contents of which are
- // undefined. If we something that looks like a Q_ASSERT and we
- // were expecting to see a Q_ASSERT, we'll skip the line.
- continue;
- else if (expected.startsWith(QLatin1String("FAIL! : tst_Exception::throwException() Caught unhandled exce")) && expected != output)
- // On some platforms we compile without RTTI, and as a result we never throw an exception.
- QCOMPARE(output.simplified(), QString::fromLatin1("tst_Exception::throwException()").simplified());
- else if (benchmark || line.startsWith("<BenchmarkResult") || (logFormat(logger) == "csv" && line.startsWith('"'))) {
- // Don't do a literal comparison for benchmark results, since
- // results have some natural variance.
- QString error;
-
- BenchmarkResult actualResult = BenchmarkResult::parse(output, &error);
- QVERIFY2(error.isEmpty(), qPrintable(QString("Actual line didn't parse as benchmark result: %1\nLine: %2").arg(error).arg(output)));
-
- BenchmarkResult expectedResult = BenchmarkResult::parse(expected, &error);
- QVERIFY2(error.isEmpty(), qPrintable(QString("Expected line didn't parse as benchmark result: %1\nLine: %2").arg(error).arg(expected)));
-
- QCOMPARE(actualResult, expectedResult);
- } else if (line.startsWith(" <Duration msecs=") || line.startsWith("<Duration msecs=")) {
- QRegularExpressionMatch match = durationRegExp.match(line);
- QVERIFY2(match.hasMatch(), qPrintable(QString::fromLatin1("Invalid Duration tag at line %1 (%2): '%3'")
- .arg(i).arg(loggers.at(n), output)));
- } else if (line.startsWith("Totals:")) {
- const int lastCommaPos = line.lastIndexOf(',');
- if (lastCommaPos > 0)
- line.truncate(lastCommaPos); // Plain text logger: strip time (", 2323dms").
- } else {
- QVERIFY2(output == expected,
- qPrintable(QString::fromLatin1("Mismatch at line %1 (%2, %3):\n'%4'\n !=\n'%5'")
- .arg(i + 1).arg(loggers.at(n), expectedFileName, output, expected)));
- }
+bool tst_Selftests::compareLine(const QString &logger, const QString &subdir,
+ bool benchmark,
+ const QString &actualLine, const QString &expectedLine,
+ QString *errorMessage) const
+{
+ if (subdir == QLatin1String("assert") && actualLine.contains(QLatin1String("ASSERT: "))
+ && expectedLine.contains(QLatin1String("ASSERT: ")) && actualLine != expectedLine) {
+ // Q_ASSERT uses __FILE__, the exact contents of which are
+ // undefined. If have we something that looks like a Q_ASSERT and we
+ // were expecting to see a Q_ASSERT, we'll skip the line.
+ return true;
+ }
- benchmark = line.startsWith("RESULT : ");
+ if (expectedLine.startsWith(QLatin1String("FAIL! : tst_Exception::throwException() Caught unhandled exce"))
+ && actualLine != expectedLine) {
+ // On some platforms we compile without RTTI, and as a result we never throw an exception
+ if (actualLine.simplified() != QLatin1String("tst_Exception::throwException()")) {
+ *errorMessage = QString::fromLatin1("'%1' != 'tst_Exception::throwException()'").arg(actualLine);
+ return false;
}
+ return true;
+ }
+
+ if (benchmark || actualLine.startsWith(QLatin1String("<BenchmarkResult"))
+ || (logger == QLatin1String("csv") && actualLine.startsWith(QLatin1Char('"')))) {
+ // Don't do a literal comparison for benchmark results, since
+ // results have some natural variance.
+ QString error;
+ BenchmarkResult actualResult = BenchmarkResult::parse(actualLine, &error);
+ if (!error.isEmpty()) {
+ *errorMessage = QString::fromLatin1("Actual line didn't parse as benchmark result: %1\nLine: %2").arg(error, actualLine);
+ return false;
+ }
+ BenchmarkResult expectedResult = BenchmarkResult::parse(expectedLine, &error);
+ if (!error.isEmpty()) {
+ *errorMessage = QString::fromLatin1("Expected line didn't parse as benchmark result: %1\nLine: %2").arg(error, expectedLine);
+ return false;
+ }
+ return compareBenchmarkResult(actualResult, expectedResult, errorMessage);
+ }
+
+ if (actualLine.startsWith(QLatin1String(" <Duration msecs="))
+ || actualLine.startsWith(QLatin1String("<Duration msecs="))) {
+ QRegularExpressionMatch match = durationRegExp.match(actualLine);
+ if (match.hasMatch())
+ return true;
+ *errorMessage = QString::fromLatin1("Invalid Duration tag: '%1'").arg(actualLine);
+ return false;
+ }
+
+ if (actualLine.startsWith(QLatin1String("Totals:")) && expectedLine.startsWith(QLatin1String("Totals:")))
+ return true;
+
+ if (actualLine == expectedLine)
+ return true;
+
+ *errorMessage = msgMismatch(actualLine, expectedLine);
+ return false;
+}
+
+bool tst_Selftests::checkXml(const QString &logger, QByteArray xml,
+ QString *errorMessage) const
+{
+ // lightxml intentionally skips the root element, which technically makes it
+ // not valid XML.
+ // We'll add that ourselves for the purpose of validation.
+ if (logger.endsWith(QLatin1String("lightxml"))) {
+ xml.prepend("<root>");
+ xml.append("</root>");
+ }
+
+ QXmlStreamReader reader(xml);
+ while (!reader.atEnd())
+ reader.readNext();
+
+ if (reader.hasError()) {
+ const int lineNumber = int(reader.lineNumber());
+ const QByteArray line = xml.split('\n').value(lineNumber - 1);
+ *errorMessage = QString::fromLatin1("line %1, col %2 '%3': %4")
+ .arg(lineNumber).arg(reader.columnNumber())
+ .arg(QString::fromLatin1(line), reader.errorString());
+ return false;
}
+ return true;
}
#endif // QT_CONFIG(process)
diff --git a/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp b/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp
new file mode 100644
index 0000000000..17da52eaba
--- /dev/null
+++ b/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Samuel Gaist <samuel.gaist@edeltech.ch>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// Make sure we get a real Q_ASSERT even in release builds
+#ifdef QT_NO_DEBUG
+# undef QT_NO_DEBUG
+#endif
+
+#include <QtTest/QtTest>
+
+class tst_TupleDiagnostics: public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testEmptyTuple() const;
+ void testSimpleTuple() const;
+ void testTuple() const;
+};
+
+void tst_TupleDiagnostics::testEmptyTuple() const
+{
+ QCOMPARE(std::tuple<>{}, std::tuple<>{});
+}
+
+void tst_TupleDiagnostics::testSimpleTuple() const
+{
+ QCOMPARE(std::tuple<int>{1}, std::tuple<int>{2});
+}
+
+void tst_TupleDiagnostics::testTuple() const
+{
+ std::tuple<int, char, QString> tuple1{42, 'Y', QStringLiteral("tuple1")};
+ std::tuple<int, char, QString> tuple2{42, 'Y', QStringLiteral("tuple2")};
+ QCOMPARE(tuple1, tuple2);
+}
+
+QTEST_MAIN(tst_TupleDiagnostics)
+
+#include "tst_tuplediagnostics.moc"
diff --git a/tests/auto/testlib/selftests/tuplediagnostics/tuplediagnostics.pro b/tests/auto/testlib/selftests/tuplediagnostics/tuplediagnostics.pro
new file mode 100644
index 0000000000..7a29e0e5e1
--- /dev/null
+++ b/tests/auto/testlib/selftests/tuplediagnostics/tuplediagnostics.pro
@@ -0,0 +1,6 @@
+SOURCES += tst_tuplediagnostics.cpp
+QT = core testlib
+
+CONFIG -= app_bundle debug_and_release_target
+
+TARGET = tuplediagnostics
diff --git a/tests/auto/testserver.pri b/tests/auto/testserver.pri
new file mode 100644
index 0000000000..b2f593235f
--- /dev/null
+++ b/tests/auto/testserver.pri
@@ -0,0 +1,109 @@
+# Integrating docker-based test servers into Qt Test framework
+#
+# This file adds support for docker-based test servers built by testcase
+# projects that need them. To enable this feature, any automated test can
+# include testserver.pri in its project file. This instructs qmake to insert
+# additional targets into the generated Makefile. The 'check' target then brings
+# up test servers before running the testcase, and shuts them down afterwards.
+#
+# TESTSERVER_COMPOSE_FILE
+# - Contains the path of docker-compose file
+# This configuration file defines the services used for autotests. It tells the
+# docker engine how to build up the docker images and containers. In qtbase, a
+# shared docker-compose file is located in the tests folder.
+# Example: TESTSERVER_COMPOSE_FILE = \
+# $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose.yml
+#
+# The user must run the provisioning scripts in advance before attempting to
+# build the test servers. The docker_testserver.sh script is used to build up
+# the docker images into the docker-cache. It handles the immutable parts of the
+# server installation that rarely need adjustment, such as downloading packages.
+# Example: qt5/coin/provisioning/.../testserver/docker_testserver.sh
+#
+# QT_TEST_SERVER_LIST
+# - A list of test servers to bring up for this testcase
+# These test servers should be defined in $$TESTSERVER_COMPOSE_FILE. Each
+# testcase can define the test servers it depends on.
+# Example: QT_TEST_SERVER_LIST = apache2 squid vsftpd ftp-proxy danted
+#
+# Pre-processor defines needed for the application:
+# QT_TEST_SERVER
+# - A preprocessor macro used for testcase to change testing parameters at
+# compile time
+# This macro is predefined for docker-based test servers and is passed as a
+# compiler option (-DQT_TEST_SERVER). The testcase can then check whether
+# docker-based servers are in use and change the testing parameters, such as
+# host name or port number, at compile time. An example can be found in
+# network-settings.h.
+#
+# Example:
+# #if defined(QT_TEST_SERVER)
+# Change the testing parameters at compile time
+# #endif
+#
+# QT_TEST_SERVER_DOMAIN
+# - A preprocessor macro that holds the server domain name
+# Provided for the helper functions in network-settings.h. Use function
+# serverDomainName() in your application instead.
+#
+# Additional make targets:
+# 1. check_network - A renamed target from the check target of testcase feature.
+# 2. testserver_clean - Clean up server containers/images and tidy away related
+# files.
+
+TESTSERVER_COMPOSE_FILE = $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose.yml
+TESTSERVER_VERSION = $$system(docker-compose --version)
+
+equals(QMAKE_HOST.os, Windows)|isEmpty(TESTSERVER_VERSION) {
+ # Make check with server "qt-test-server.qt-test-net" as a fallback
+ message("testserver: qt-test-server.qt-test-net")
+} else {
+ # Make check with test servers
+ message("testserver:" $$TESTSERVER_VERSION)
+
+ # Ensure that the docker-compose file is provided. It is a configuration
+ # file which is mandatory for all docker-compose commands. You can get more
+ # detail from the description of TESTSERVER_COMPOSE_FILE above. There is
+ # also an example showing how to configure it manually.
+ FILE_PRETEST_MSG = "Project variable 'TESTSERVER_COMPOSE_FILE' is not set"
+ testserver_pretest.commands = $(if $$TESTSERVER_COMPOSE_FILE,,$(error $$FILE_PRETEST_MSG))
+
+ # Before starting the test servers, it requires the user to run the setup
+ # script (coin/provisioning/.../testserver/docker_testserver.sh) in advance.
+ IMAGE_PRETEST_CMD = docker images -aq "qt-test-server-*"
+ IMAGE_PRETEST_MSG = "Docker image qt-test-server-* not found"
+ testserver_pretest.commands += $(if $(shell $$IMAGE_PRETEST_CMD),,$(error $$IMAGE_PRETEST_MSG))
+
+ # The domain name is relevant to https keycert (qnetworkreply/crts/qt-test-net-cacert.pem).
+ DNSDOMAIN = test-net.qt.local
+ TEST_ENV += TESTSERVER_DOMAIN=$$DNSDOMAIN
+ DEFINES += QT_TEST_SERVER QT_TEST_SERVER_DOMAIN=$$shell_quote(\"$${DNSDOMAIN}\")
+
+ # There is no docker bridge on macOS. It is impossible to ping a container.
+ # Docker docs recommends using port mapping to connect to a container.
+ equals(QMAKE_HOST.os, Darwin): TEST_ENV += TESTSERVER_BIND_LOCAL=1
+
+ # Rename the check target of testcase feature
+ check.target = check_network
+ testserver_test.target = check
+
+ # Pretesting test servers environment
+ testserver_test.depends = testserver_pretest
+
+ # Bring up test servers and make sure the services are ready.
+ testserver_test.commands = $$TEST_ENV docker-compose -f $$TESTSERVER_COMPOSE_FILE up -d \
+ --force-recreate --timeout 1 $${QT_TEST_SERVER_LIST} &&
+
+ # Check test cases with docker-based test servers.
+ testserver_test.commands += $(MAKE) check_network;
+
+ # Stop and remove test servers after testing.
+ testserver_test.commands += $$TEST_ENV docker-compose -f $$TESTSERVER_COMPOSE_FILE down \
+ --timeout 1
+
+ # Destroy test servers and tidy away related files.
+ testserver_clean.commands = $$TEST_ENV docker-compose -f $$TESTSERVER_COMPOSE_FILE down \
+ --rmi all
+
+ QMAKE_EXTRA_TARGETS += testserver_pretest testserver_test testserver_clean
+}
diff --git a/tests/auto/tools/moc/cxx11-enums.h b/tests/auto/tools/moc/cxx11-enums.h
index 47a4857cd0..93ab16c157 100644
--- a/tests/auto/tools/moc/cxx11-enums.h
+++ b/tests/auto/tools/moc/cxx11-enums.h
@@ -39,10 +39,14 @@ public:
enum TypedEnum : char { B0, B1 , B2, B3 };
enum class TypedEnumClass : char { C0, C1, C2, C3 };
enum NormalEnum { D2 = 2, D3, D0 =0 , D1 };
+ enum class ClassFlag { F0 = 1, F1 = 2, F2 = 4, F3 = 8};
+ Q_DECLARE_FLAGS(ClassFlags, ClassFlag)
+
Q_ENUM(EnumClass)
Q_ENUM(TypedEnum)
Q_ENUM(TypedEnumClass)
Q_ENUM(NormalEnum)
+ Q_FLAG(ClassFlags)
};
// Also test the Q_ENUMS macro
@@ -54,7 +58,10 @@ public:
enum TypedEnum : char { B0, B1 , B2, B3 };
enum class TypedEnumClass : char { C0, C1, C2, C3 };
enum NormalEnum { D2 = 2, D3, D0 =0 , D1 };
+ enum class ClassFlag { F0 = 1, F1 = 2, F2 = 4, F3 = 8 };
+ Q_DECLARE_FLAGS(ClassFlags, ClassFlag)
Q_ENUMS(EnumClass TypedEnum TypedEnumClass NormalEnum)
+ Q_FLAGS(ClassFlags)
};
#else
diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp
index 753da401a2..92a94055a4 100644
--- a/tests/auto/tools/moc/tst_moc.cpp
+++ b/tests/auto/tools/moc/tst_moc.cpp
@@ -2248,6 +2248,7 @@ void tst_Moc::privateClass()
void tst_Moc::cxx11Enums_data()
{
QTest::addColumn<const QMetaObject *>("meta");
+ QTest::addColumn<QByteArray>("typeName");
QTest::addColumn<QByteArray>("enumName");
QTest::addColumn<char>("prefix");
QTest::addColumn<bool>("isScoped");
@@ -2255,14 +2256,16 @@ void tst_Moc::cxx11Enums_data()
const QMetaObject *meta1 = &CXX11Enums::staticMetaObject;
const QMetaObject *meta2 = &CXX11Enums2::staticMetaObject;
- QTest::newRow("EnumClass") << meta1 << QByteArray("EnumClass") << 'A' << true;
- QTest::newRow("EnumClass 2") << meta2 << QByteArray("EnumClass") << 'A' << true;
- QTest::newRow("TypedEnum") << meta1 << QByteArray("TypedEnum") << 'B' << false;
- QTest::newRow("TypedEnum 2") << meta2 << QByteArray("TypedEnum") << 'B' << false;
- QTest::newRow("TypedEnumClass") << meta1 << QByteArray("TypedEnumClass") << 'C' << true;
- QTest::newRow("TypedEnumClass 2") << meta2 << QByteArray("TypedEnumClass") << 'C' << true;
- QTest::newRow("NormalEnum") << meta1 << QByteArray("NormalEnum") << 'D' << false;
- QTest::newRow("NormalEnum 2") << meta2 << QByteArray("NormalEnum") << 'D' << false;
+ QTest::newRow("EnumClass") << meta1 << QByteArray("EnumClass") << QByteArray("EnumClass") << 'A' << true;
+ QTest::newRow("EnumClass 2") << meta2 << QByteArray("EnumClass") << QByteArray("EnumClass") << 'A' << true;
+ QTest::newRow("TypedEnum") << meta1 << QByteArray("TypedEnum") << QByteArray("TypedEnum") << 'B' << false;
+ QTest::newRow("TypedEnum 2") << meta2 << QByteArray("TypedEnum") << QByteArray("TypedEnum") << 'B' << false;
+ QTest::newRow("TypedEnumClass") << meta1 << QByteArray("TypedEnumClass") << QByteArray("TypedEnumClass") << 'C' << true;
+ QTest::newRow("TypedEnumClass 2") << meta2 << QByteArray("TypedEnumClass") << QByteArray("TypedEnumClass") << 'C' << true;
+ QTest::newRow("NormalEnum") << meta1 << QByteArray("NormalEnum") << QByteArray("NormalEnum") << 'D' << false;
+ QTest::newRow("NormalEnum 2") << meta2 << QByteArray("NormalEnum") << QByteArray("NormalEnum") << 'D' << false;
+ QTest::newRow("ClassFlags") << meta1 << QByteArray("ClassFlags") << QByteArray("ClassFlag") << 'F' << true;
+ QTest::newRow("ClassFlags 2") << meta2 << QByteArray("ClassFlags") << QByteArray("ClassFlag") << 'F' << true;
}
void tst_Moc::cxx11Enums()
@@ -2270,21 +2273,26 @@ void tst_Moc::cxx11Enums()
QFETCH(const QMetaObject *,meta);
QCOMPARE(meta->enumeratorOffset(), 0);
+ QFETCH(QByteArray, typeName);
QFETCH(QByteArray, enumName);
QFETCH(char, prefix);
QFETCH(bool, isScoped);
- int idx;
- idx = meta->indexOfEnumerator(enumName);
+ int idx = meta->indexOfEnumerator(typeName);
QVERIFY(idx != -1);
+ QCOMPARE(meta->indexOfEnumerator(enumName), idx);
+
QCOMPARE(meta->enumerator(idx).enclosingMetaObject(), meta);
QCOMPARE(meta->enumerator(idx).isValid(), true);
QCOMPARE(meta->enumerator(idx).keyCount(), 4);
- QCOMPARE(meta->enumerator(idx).name(), enumName.constData());
+ QCOMPARE(meta->enumerator(idx).name(), typeName.constData());
+ QCOMPARE(meta->enumerator(idx).enumName(), enumName.constData());
+ bool isFlag = meta->enumerator(idx).isFlag();
for (int i = 0; i < 4; i++) {
QByteArray v = prefix + QByteArray::number(i);
- QCOMPARE(meta->enumerator(idx).keyToValue(v), i);
- QCOMPARE(meta->enumerator(idx).valueToKey(i), v.constData());
+ const int value = isFlag ? (1 << i) : i;
+ QCOMPARE(meta->enumerator(idx).keyToValue(v), value);
+ QCOMPARE(meta->enumerator(idx).valueToKey(value), v.constData());
}
QCOMPARE(meta->enumerator(idx).isScoped(), isScoped);
}
diff --git a/tests/auto/tools/qmakelib/evaltest.cpp b/tests/auto/tools/qmakelib/evaltest.cpp
index aeedf4ae32..948e2b3121 100644
--- a/tests/auto/tools/qmakelib/evaltest.cpp
+++ b/tests/auto/tools/qmakelib/evaltest.cpp
@@ -819,7 +819,7 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir)
QTest::newRow("$$member(): bad number of arguments")
<< "VAR = $$member(1, 2, 3, 4)"
<< "VAR ="
- << "##:1: member(var, start, end) requires one to three arguments."
+ << "##:1: member(var, [start, [end]]) requires one to three arguments."
<< true;
QTest::newRow("$$member(): bad args (1)")
@@ -1030,8 +1030,8 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir)
QTest::newRow("$$fromfile(): bad number of arguments")
<< "VAR = $$fromfile(1) \\\n$$fromfile(1, 2, 3)"
<< "VAR ="
- << "##:1: fromfile(file, variable) requires two arguments.\n"
- "##:2: fromfile(file, variable) requires two arguments."
+ << "##:1: fromfile(file, var) requires two arguments.\n"
+ "##:2: fromfile(file, var) requires two arguments."
<< true;
QTest::newRow("$$eval()")
@@ -1043,7 +1043,7 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir)
QTest::newRow("$$eval(): bad number of arguments")
<< "VAR = $$eval(1, 2)"
<< "VAR ="
- << "##:1: eval(variable) requires one argument."
+ << "##:1: eval(var) requires one argument."
<< true;
QTest::newRow("$$list()")
@@ -1128,7 +1128,7 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir)
QTest::newRow("$$format_number(): bad number of arguments")
<< "VAR = $$format_number(13, 1, 2)"
<< "VAR ="
- << "##:1: format_number(number[, options...]) requires one or two arguments."
+ << "##:1: format_number(number, [options...]) requires one or two arguments."
<< true;
QTest::newRow("$$format_number(): invalid option")
@@ -1200,7 +1200,7 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir)
QTest::newRow("$$join(): bad number of arguments")
<< "VAR = $$join(1, 2, 3, 4, 5)"
<< "VAR ="
- << "##:1: join(var, glue, before, after) requires one to four arguments."
+ << "##:1: join(var, [glue, [before, [after]]]) requires one to four arguments."
<< true;
QTest::newRow("$$split(): default sep")
@@ -1296,8 +1296,8 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir)
QTest::newRow("$$section(): bad number of arguments")
<< "VAR = $$section(1, 2) \\\n$$section(1, 2, 3, 4, 5)"
<< "VAR ="
- << "##:1: section(var, sep, begin, end) requires three or four arguments.\n"
- "##:2: section(var, sep, begin, end) requires three or four arguments."
+ << "##:1: section(var, sep, begin, [end]) requires three or four arguments.\n"
+ "##:2: section(var, sep, begin, [end]) requires three or four arguments."
<< true;
QTest::newRow("$$find()")
@@ -1333,7 +1333,7 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir)
QTest::newRow("$$cat(): bad number of arguments")
<< "VAR = $$cat(1, 2, 3)"
<< "VAR ="
- << "##:1: cat(file, singleline=true) requires one or two arguments."
+ << "##:1: cat(file, [mode=true|blob|lines]) requires one or two arguments."
<< true;
QTest::newRow("$$system(): default mode")
@@ -1473,7 +1473,7 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir)
QTest::newRow("$$files(): bad number of arguments")
<< "VAR = $$files(1, 2, 3)"
<< "VAR ="
- << "##:1: files(pattern, recursive=false) requires one or two arguments."
+ << "##:1: files(pattern, [recursive=false]) requires one or two arguments."
<< true;
#if 0
@@ -1639,7 +1639,7 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir)
QTest::newRow("$$absolute_path(): bad number of arguments")
<< "VAR = $$absolute_path(1, 2, 3)"
<< "VAR ="
- << "##:1: absolute_path(path[, base]) requires one or two arguments."
+ << "##:1: absolute_path(path, [base]) requires one or two arguments."
<< true;
QTest::newRow("$$relative_path(): relative file")
@@ -1683,7 +1683,7 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir)
QTest::newRow("$$relative_path(): bad number of arguments")
<< "VAR = $$relative_path(1, 2, 3)"
<< "VAR ="
- << "##:1: relative_path(path[, base]) requires one or two arguments."
+ << "##:1: relative_path(path, [base]) requires one or two arguments."
<< true;
QTest::newRow("$$clean_path()")
@@ -1847,7 +1847,7 @@ void tst_qmakelib::addTestFunctions(const QString &qindir)
QTest::newRow("defined(): bad number of arguments")
<< "defined(1, 2, 3): OK = 1"
<< "OK = UNDEF"
- << "##:1: defined(function, [\"test\"|\"replace\"|\"var\"]) requires one or two arguments."
+ << "##:1: defined(object, [\"test\"|\"replace\"|\"var\"]) requires one or two arguments."
<< true;
QTest::newRow("export()")
@@ -1864,7 +1864,7 @@ void tst_qmakelib::addTestFunctions(const QString &qindir)
QTest::newRow("export(): bad number of arguments")
<< "export(1, 2): OK = 1"
<< "OK = UNDEF"
- << "##:1: export(variable) requires one argument."
+ << "##:1: export(var) requires one argument."
<< true;
QTest::newRow("infile(): found")
@@ -2006,7 +2006,7 @@ void tst_qmakelib::addTestFunctions(const QString &qindir)
QTest::newRow("CONFIG(): bad number of arguments")
<< "CONFIG(1, 2, 3): OK = 1"
<< "OK = UNDEF"
- << "##:1: CONFIG(config) requires one or two arguments."
+ << "##:1: CONFIG(config, [mutuals]) requires one or two arguments."
<< true;
QTest::newRow("contains(simple plain): true")
@@ -2072,8 +2072,8 @@ void tst_qmakelib::addTestFunctions(const QString &qindir)
QTest::newRow("contains(): bad number of arguments")
<< "contains(1): OK = 1\ncontains(1, 2, 3, 4): OK = 1"
<< "OK = UNDEF"
- << "##:1: contains(var, val) requires two or three arguments.\n"
- "##:2: contains(var, val) requires two or three arguments."
+ << "##:1: contains(var, val, [mutuals]) requires two or three arguments.\n"
+ "##:2: contains(var, val, [mutuals]) requires two or three arguments."
<< true;
QTest::newRow("count(): true")
@@ -2133,8 +2133,8 @@ void tst_qmakelib::addTestFunctions(const QString &qindir)
QTest::newRow("count(): bad number of arguments")
<< "count(1): OK = 1\ncount(1, 2, 3, 4): OK = 1"
<< "OK = UNDEF"
- << "##:1: count(var, count, op=\"equals\") requires two or three arguments.\n"
- "##:2: count(var, count, op=\"equals\") requires two or three arguments."
+ << "##:1: count(var, count, [op=operator]) requires two or three arguments.\n"
+ "##:2: count(var, count, [op=operator]) requires two or three arguments."
<< true;
QTest::newRow("greaterThan(int): true")
@@ -2164,8 +2164,8 @@ void tst_qmakelib::addTestFunctions(const QString &qindir)
QTest::newRow("greaterThan(): bad number of arguments")
<< "greaterThan(1): OK = 1\ngreaterThan(1, 2, 3): OK = 1"
<< "OK = UNDEF"
- << "##:1: greaterThan(variable, value) requires two arguments.\n"
- "##:2: greaterThan(variable, value) requires two arguments."
+ << "##:1: greaterThan(var, val) requires two arguments.\n"
+ "##:2: greaterThan(var, val) requires two arguments."
<< true;
QTest::newRow("lessThan(int): true")
@@ -2195,8 +2195,8 @@ void tst_qmakelib::addTestFunctions(const QString &qindir)
QTest::newRow("lessThan(): bad number of arguments")
<< "lessThan(1): OK = 1\nlessThan(1, 2, 3): OK = 1"
<< "OK = UNDEF"
- << "##:1: lessThan(variable, value) requires two arguments.\n"
- "##:2: lessThan(variable, value) requires two arguments."
+ << "##:1: lessThan(var, val) requires two arguments.\n"
+ "##:2: lessThan(var, val) requires two arguments."
<< true;
QTest::newRow("equals(): true")
@@ -2214,8 +2214,8 @@ void tst_qmakelib::addTestFunctions(const QString &qindir)
QTest::newRow("equals(): bad number of arguments")
<< "equals(1): OK = 1\nequals(1, 2, 3): OK = 1"
<< "OK = UNDEF"
- << "##:1: equals(variable, value) requires two arguments.\n"
- "##:2: equals(variable, value) requires two arguments."
+ << "##:1: equals(var, val) requires two arguments.\n"
+ "##:2: equals(var, val) requires two arguments."
<< true;
// That's just an alias, so don't test much.
@@ -2240,8 +2240,8 @@ void tst_qmakelib::addTestFunctions(const QString &qindir)
QTest::newRow("versionAtLeast(): bad number of arguments")
<< "versionAtLeast(1): OK = 1\nversionAtLeast(1, 2, 3): OK = 1"
<< "OK = UNDEF"
- << "##:1: versionAtLeast(variable, versionNumber) requires two arguments.\n"
- "##:2: versionAtLeast(variable, versionNumber) requires two arguments."
+ << "##:1: versionAtLeast(var, version) requires two arguments.\n"
+ "##:2: versionAtLeast(var, version) requires two arguments."
<< true;
QTest::newRow("versionAtMost(): true")
@@ -2259,8 +2259,8 @@ void tst_qmakelib::addTestFunctions(const QString &qindir)
QTest::newRow("versionAtMost(): bad number of arguments")
<< "versionAtMost(1): OK = 1\nversionAtMost(1, 2, 3): OK = 1"
<< "OK = UNDEF"
- << "##:1: versionAtMost(variable, versionNumber) requires two arguments.\n"
- "##:2: versionAtMost(variable, versionNumber) requires two arguments."
+ << "##:1: versionAtMost(var, version) requires two arguments.\n"
+ "##:2: versionAtMost(var, version) requires two arguments."
<< true;
QTest::newRow("clear(): top-level")
@@ -2288,7 +2288,7 @@ void tst_qmakelib::addTestFunctions(const QString &qindir)
QTest::newRow("clear(): bad number of arguments")
<< "clear(1, 2): OK = 1"
<< "OK = UNDEF"
- << "##:1: clear(variable) requires one argument."
+ << "##:1: clear(var) requires one argument."
<< true;
QTest::newRow("unset(): top-level")
@@ -2316,7 +2316,7 @@ void tst_qmakelib::addTestFunctions(const QString &qindir)
QTest::newRow("unset(): bad number of arguments")
<< "unset(1, 2): OK = 1"
<< "OK = UNDEF"
- << "##:1: unset(variable) requires one argument."
+ << "##:1: unset(var) requires one argument."
<< true;
// This function does not follow the established naming pattern.
@@ -2362,8 +2362,8 @@ void tst_qmakelib::addTestFunctions(const QString &qindir)
QTest::newRow("parseJson(): bad number of arguments")
<< "parseJson(1): OK = 1\nparseJson(1, 2, 3): OK = 1"
<< "OK = UNDEF"
- << "##:1: parseJson(variable, into) requires two arguments.\n"
- "##:2: parseJson(variable, into) requires two arguments."
+ << "##:1: parseJson(var, into) requires two arguments.\n"
+ "##:2: parseJson(var, into) requires two arguments."
<< true;
QTest::newRow("include()")
@@ -2395,7 +2395,7 @@ void tst_qmakelib::addTestFunctions(const QString &qindir)
QTest::newRow("include(): bad number of arguments")
<< "include(1, 2, 3, 4): OK = 1"
<< "OK = UNDEF"
- << "##:1: include(file, [into, [silent]]) requires one, two or three arguments."
+ << "##:1: include(file, [into, [silent]]) requires one to three arguments."
<< true;
QTest::newRow("load()")
@@ -2419,7 +2419,7 @@ void tst_qmakelib::addTestFunctions(const QString &qindir)
QTest::newRow("load(): bad number of arguments")
<< "load(1, 2, 3): OK = 1"
<< "OK = UNDEF"
- << "##:1: load(feature) requires one or two arguments."
+ << "##:1: load(feature, [ignore_errors=false]) requires one or two arguments."
<< true;
QTest::newRow("discard_from()")
@@ -2668,7 +2668,7 @@ void tst_qmakelib::addTestFunctions(const QString &qindir)
QTest::newRow("mkpath(): bad number of arguments")
<< "mkpath(1, 2): OK = 1"
<< "OK = UNDEF"
- << "##:1: mkpath(file) requires one argument."
+ << "##:1: mkpath(path) requires one argument."
<< true;
#if 0
diff --git a/tests/auto/tools/uic/baseline/Dialog_with_Buttons_Bottom.ui.h b/tests/auto/tools/uic/baseline/Dialog_with_Buttons_Bottom.ui.h
index d8db966b76..1f5004b2aa 100644
--- a/tests/auto/tools/uic/baseline/Dialog_with_Buttons_Bottom.ui.h
+++ b/tests/auto/tools/uic/baseline/Dialog_with_Buttons_Bottom.ui.h
@@ -24,10 +24,10 @@ public:
void setupUi(QDialog *Dialog)
{
if (Dialog->objectName().isEmpty())
- Dialog->setObjectName(QStringLiteral("Dialog"));
+ Dialog->setObjectName(QString::fromUtf8("Dialog"));
Dialog->resize(400, 300);
buttonBox = new QDialogButtonBox(Dialog);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setGeometry(QRect(30, 240, 341, 32));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
diff --git a/tests/auto/tools/uic/baseline/Dialog_with_Buttons_Right.ui.h b/tests/auto/tools/uic/baseline/Dialog_with_Buttons_Right.ui.h
index b167eaec8a..8dd8b11b62 100644
--- a/tests/auto/tools/uic/baseline/Dialog_with_Buttons_Right.ui.h
+++ b/tests/auto/tools/uic/baseline/Dialog_with_Buttons_Right.ui.h
@@ -24,10 +24,10 @@ public:
void setupUi(QDialog *Dialog)
{
if (Dialog->objectName().isEmpty())
- Dialog->setObjectName(QStringLiteral("Dialog"));
+ Dialog->setObjectName(QString::fromUtf8("Dialog"));
Dialog->resize(400, 300);
buttonBox = new QDialogButtonBox(Dialog);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setGeometry(QRect(290, 20, 81, 241));
buttonBox->setOrientation(Qt::Vertical);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
diff --git a/tests/auto/tools/uic/baseline/Dialog_without_Buttons.ui.h b/tests/auto/tools/uic/baseline/Dialog_without_Buttons.ui.h
index 52e9f3b931..95acabf3f8 100644
--- a/tests/auto/tools/uic/baseline/Dialog_without_Buttons.ui.h
+++ b/tests/auto/tools/uic/baseline/Dialog_without_Buttons.ui.h
@@ -22,7 +22,7 @@ public:
void setupUi(QDialog *Dialog)
{
if (Dialog->objectName().isEmpty())
- Dialog->setObjectName(QStringLiteral("Dialog"));
+ Dialog->setObjectName(QString::fromUtf8("Dialog"));
Dialog->resize(400, 300);
retranslateUi(Dialog);
diff --git a/tests/auto/tools/uic/baseline/Main_Window.ui.h b/tests/auto/tools/uic/baseline/Main_Window.ui.h
index eba78c1a2b..9e59e9f2e5 100644
--- a/tests/auto/tools/uic/baseline/Main_Window.ui.h
+++ b/tests/auto/tools/uic/baseline/Main_Window.ui.h
@@ -28,16 +28,16 @@ public:
void setupUi(QMainWindow *MainWindow)
{
if (MainWindow->objectName().isEmpty())
- MainWindow->setObjectName(QStringLiteral("MainWindow"));
+ MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
MainWindow->resize(800, 600);
menubar = new QMenuBar(MainWindow);
- menubar->setObjectName(QStringLiteral("menubar"));
+ menubar->setObjectName(QString::fromUtf8("menubar"));
MainWindow->setMenuBar(menubar);
centralwidget = new QWidget(MainWindow);
- centralwidget->setObjectName(QStringLiteral("centralwidget"));
+ centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
MainWindow->setCentralWidget(centralwidget);
statusbar = new QStatusBar(MainWindow);
- statusbar->setObjectName(QStringLiteral("statusbar"));
+ statusbar->setObjectName(QString::fromUtf8("statusbar"));
MainWindow->setStatusBar(statusbar);
retranslateUi(MainWindow);
diff --git a/tests/auto/tools/uic/baseline/Widget.ui.h b/tests/auto/tools/uic/baseline/Widget.ui.h
index 8cb31b4589..4318c2262f 100644
--- a/tests/auto/tools/uic/baseline/Widget.ui.h
+++ b/tests/auto/tools/uic/baseline/Widget.ui.h
@@ -30,22 +30,22 @@ public:
void setupUi(QWidget *Form)
{
if (Form->objectName().isEmpty())
- Form->setObjectName(QStringLiteral("Form"));
+ Form->setObjectName(QString::fromUtf8("Form"));
Form->resize(400, 300);
vboxLayout = new QVBoxLayout(Form);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
Alabel = new QLabel(Form);
- Alabel->setObjectName(QStringLiteral("Alabel"));
+ Alabel->setObjectName(QString::fromUtf8("Alabel"));
vboxLayout->addWidget(Alabel);
groupBox = new QGroupBox(Form);
- groupBox->setObjectName(QStringLiteral("groupBox"));
+ groupBox->setObjectName(QString::fromUtf8("groupBox"));
vboxLayout->addWidget(groupBox);
pushButton = new QPushButton(Form);
- pushButton->setObjectName(QStringLiteral("pushButton"));
+ pushButton->setObjectName(QString::fromUtf8("pushButton"));
vboxLayout->addWidget(pushButton);
diff --git a/tests/auto/tools/uic/baseline/addlinkdialog.ui.h b/tests/auto/tools/uic/baseline/addlinkdialog.ui.h
index 71d091380a..17f51a92f8 100644
--- a/tests/auto/tools/uic/baseline/addlinkdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/addlinkdialog.ui.h
@@ -38,31 +38,31 @@ public:
void setupUi(QDialog *AddLinkDialog)
{
if (AddLinkDialog->objectName().isEmpty())
- AddLinkDialog->setObjectName(QStringLiteral("AddLinkDialog"));
+ AddLinkDialog->setObjectName(QString::fromUtf8("AddLinkDialog"));
AddLinkDialog->setSizeGripEnabled(false);
AddLinkDialog->setModal(true);
verticalLayout = new QVBoxLayout(AddLinkDialog);
- verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
+ verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
formLayout = new QFormLayout();
- formLayout->setObjectName(QStringLiteral("formLayout"));
+ formLayout->setObjectName(QString::fromUtf8("formLayout"));
label = new QLabel(AddLinkDialog);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
formLayout->setWidget(0, QFormLayout::LabelRole, label);
titleInput = new QLineEdit(AddLinkDialog);
- titleInput->setObjectName(QStringLiteral("titleInput"));
+ titleInput->setObjectName(QString::fromUtf8("titleInput"));
titleInput->setMinimumSize(QSize(337, 0));
formLayout->setWidget(0, QFormLayout::FieldRole, titleInput);
label_2 = new QLabel(AddLinkDialog);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
formLayout->setWidget(1, QFormLayout::LabelRole, label_2);
urlInput = new QLineEdit(AddLinkDialog);
- urlInput->setObjectName(QStringLiteral("urlInput"));
+ urlInput->setObjectName(QString::fromUtf8("urlInput"));
formLayout->setWidget(1, QFormLayout::FieldRole, urlInput);
@@ -74,14 +74,14 @@ public:
verticalLayout->addItem(verticalSpacer);
line = new QFrame(AddLinkDialog);
- line->setObjectName(QStringLiteral("line"));
+ line->setObjectName(QString::fromUtf8("line"));
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
verticalLayout->addWidget(line);
buttonBox = new QDialogButtonBox(AddLinkDialog);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
diff --git a/tests/auto/tools/uic/baseline/addtorrentform.ui.h b/tests/auto/tools/uic/baseline/addtorrentform.ui.h
index e76f05f1de..d259a011bf 100644
--- a/tests/auto/tools/uic/baseline/addtorrentform.ui.h
+++ b/tests/auto/tools/uic/baseline/addtorrentform.ui.h
@@ -56,7 +56,7 @@ public:
void setupUi(QDialog *AddTorrentFile)
{
if (AddTorrentFile->objectName().isEmpty())
- AddTorrentFile->setObjectName(QStringLiteral("AddTorrentFile"));
+ AddTorrentFile->setObjectName(QString::fromUtf8("AddTorrentFile"));
AddTorrentFile->resize(464, 385);
AddTorrentFile->setSizeGripEnabled(false);
AddTorrentFile->setModal(true);
@@ -65,56 +65,56 @@ public:
vboxLayout->setSpacing(6);
#endif
vboxLayout->setContentsMargins(8, 8, 8, 8);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
groupBox = new QGroupBox(AddTorrentFile);
- groupBox->setObjectName(QStringLiteral("groupBox"));
+ groupBox->setObjectName(QString::fromUtf8("groupBox"));
widget = new QWidget(groupBox);
- widget->setObjectName(QStringLiteral("widget"));
+ widget->setObjectName(QString::fromUtf8("widget"));
widget->setGeometry(QRect(10, 40, 364, 33));
gridLayout = new QGridLayout(groupBox);
#ifndef Q_OS_MAC
gridLayout->setSpacing(6);
#endif
gridLayout->setContentsMargins(8, 8, 8, 8);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
label_4 = new QLabel(groupBox);
- label_4->setObjectName(QStringLiteral("label_4"));
+ label_4->setObjectName(QString::fromUtf8("label_4"));
gridLayout->addWidget(label_4, 6, 0, 1, 1);
torrentFile = new QLineEdit(groupBox);
- torrentFile->setObjectName(QStringLiteral("torrentFile"));
+ torrentFile->setObjectName(QString::fromUtf8("torrentFile"));
gridLayout->addWidget(torrentFile, 0, 1, 1, 2);
label_2 = new QLabel(groupBox);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
gridLayout->addWidget(label_2, 1, 0, 1, 1);
browseTorrents = new QPushButton(groupBox);
- browseTorrents->setObjectName(QStringLiteral("browseTorrents"));
+ browseTorrents->setObjectName(QString::fromUtf8("browseTorrents"));
gridLayout->addWidget(browseTorrents, 0, 3, 1, 1);
label_5 = new QLabel(groupBox);
- label_5->setObjectName(QStringLiteral("label_5"));
+ label_5->setObjectName(QString::fromUtf8("label_5"));
label_5->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop);
gridLayout->addWidget(label_5, 5, 0, 1, 1);
label_3 = new QLabel(groupBox);
- label_3->setObjectName(QStringLiteral("label_3"));
+ label_3->setObjectName(QString::fromUtf8("label_3"));
gridLayout->addWidget(label_3, 4, 0, 1, 1);
label_6 = new QLabel(groupBox);
- label_6->setObjectName(QStringLiteral("label_6"));
+ label_6->setObjectName(QString::fromUtf8("label_6"));
gridLayout->addWidget(label_6, 2, 0, 1, 1);
torrentContents = new QTextEdit(groupBox);
- torrentContents->setObjectName(QStringLiteral("torrentContents"));
+ torrentContents->setObjectName(QString::fromUtf8("torrentContents"));
torrentContents->setFocusPolicy(Qt::NoFocus);
torrentContents->setTabChangesFocus(true);
torrentContents->setLineWrapMode(QTextEdit::NoWrap);
@@ -123,43 +123,43 @@ public:
gridLayout->addWidget(torrentContents, 5, 1, 1, 3);
destinationFolder = new QLineEdit(groupBox);
- destinationFolder->setObjectName(QStringLiteral("destinationFolder"));
+ destinationFolder->setObjectName(QString::fromUtf8("destinationFolder"));
destinationFolder->setFocusPolicy(Qt::StrongFocus);
gridLayout->addWidget(destinationFolder, 6, 1, 1, 2);
announceUrl = new QLabel(groupBox);
- announceUrl->setObjectName(QStringLiteral("announceUrl"));
+ announceUrl->setObjectName(QString::fromUtf8("announceUrl"));
gridLayout->addWidget(announceUrl, 1, 1, 1, 3);
label = new QLabel(groupBox);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
gridLayout->addWidget(label, 0, 0, 1, 1);
browseDestination = new QPushButton(groupBox);
- browseDestination->setObjectName(QStringLiteral("browseDestination"));
+ browseDestination->setObjectName(QString::fromUtf8("browseDestination"));
gridLayout->addWidget(browseDestination, 6, 3, 1, 1);
label_7 = new QLabel(groupBox);
- label_7->setObjectName(QStringLiteral("label_7"));
+ label_7->setObjectName(QString::fromUtf8("label_7"));
gridLayout->addWidget(label_7, 3, 0, 1, 1);
commentLabel = new QLabel(groupBox);
- commentLabel->setObjectName(QStringLiteral("commentLabel"));
+ commentLabel->setObjectName(QString::fromUtf8("commentLabel"));
gridLayout->addWidget(commentLabel, 3, 1, 1, 3);
creatorLabel = new QLabel(groupBox);
- creatorLabel->setObjectName(QStringLiteral("creatorLabel"));
+ creatorLabel->setObjectName(QString::fromUtf8("creatorLabel"));
gridLayout->addWidget(creatorLabel, 2, 1, 1, 3);
sizeLabel = new QLabel(groupBox);
- sizeLabel->setObjectName(QStringLiteral("sizeLabel"));
+ sizeLabel->setObjectName(QString::fromUtf8("sizeLabel"));
gridLayout->addWidget(sizeLabel, 4, 1, 1, 3);
@@ -171,19 +171,19 @@ public:
hboxLayout->setSpacing(6);
#endif
hboxLayout->setContentsMargins(0, 0, 0, 0);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
spacerItem = new QSpacerItem(131, 31, QSizePolicy::Expanding, QSizePolicy::Minimum);
hboxLayout->addItem(spacerItem);
okButton = new QPushButton(AddTorrentFile);
- okButton->setObjectName(QStringLiteral("okButton"));
+ okButton->setObjectName(QString::fromUtf8("okButton"));
okButton->setEnabled(false);
hboxLayout->addWidget(okButton);
cancelButton = new QPushButton(AddTorrentFile);
- cancelButton->setObjectName(QStringLiteral("cancelButton"));
+ cancelButton->setObjectName(QString::fromUtf8("cancelButton"));
hboxLayout->addWidget(cancelButton);
diff --git a/tests/auto/tools/uic/baseline/authenticationdialog.ui.h b/tests/auto/tools/uic/baseline/authenticationdialog.ui.h
index 331770b5e0..16c9ce16a8 100644
--- a/tests/auto/tools/uic/baseline/authenticationdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/authenticationdialog.ui.h
@@ -37,50 +37,50 @@ public:
void setupUi(QDialog *Dialog)
{
if (Dialog->objectName().isEmpty())
- Dialog->setObjectName(QStringLiteral("Dialog"));
+ Dialog->setObjectName(QString::fromUtf8("Dialog"));
Dialog->resize(389, 243);
gridLayout = new QGridLayout(Dialog);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
label = new QLabel(Dialog);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
label->setWordWrap(false);
gridLayout->addWidget(label, 0, 0, 1, 2);
label_2 = new QLabel(Dialog);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
gridLayout->addWidget(label_2, 2, 0, 1, 1);
userEdit = new QLineEdit(Dialog);
- userEdit->setObjectName(QStringLiteral("userEdit"));
+ userEdit->setObjectName(QString::fromUtf8("userEdit"));
gridLayout->addWidget(userEdit, 2, 1, 1, 1);
label_3 = new QLabel(Dialog);
- label_3->setObjectName(QStringLiteral("label_3"));
+ label_3->setObjectName(QString::fromUtf8("label_3"));
gridLayout->addWidget(label_3, 3, 0, 1, 1);
passwordEdit = new QLineEdit(Dialog);
- passwordEdit->setObjectName(QStringLiteral("passwordEdit"));
+ passwordEdit->setObjectName(QString::fromUtf8("passwordEdit"));
gridLayout->addWidget(passwordEdit, 3, 1, 1, 1);
buttonBox = new QDialogButtonBox(Dialog);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
gridLayout->addWidget(buttonBox, 5, 0, 1, 2);
label_4 = new QLabel(Dialog);
- label_4->setObjectName(QStringLiteral("label_4"));
+ label_4->setObjectName(QString::fromUtf8("label_4"));
gridLayout->addWidget(label_4, 1, 0, 1, 1);
siteDescription = new QLabel(Dialog);
- siteDescription->setObjectName(QStringLiteral("siteDescription"));
+ siteDescription->setObjectName(QString::fromUtf8("siteDescription"));
QFont font;
font.setBold(true);
font.setWeight(75);
diff --git a/tests/auto/tools/uic/baseline/backside.ui.h b/tests/auto/tools/uic/baseline/backside.ui.h
index 963eb082ae..e7053c632f 100644
--- a/tests/auto/tools/uic/baseline/backside.ui.h
+++ b/tests/auto/tools/uic/baseline/backside.ui.h
@@ -47,47 +47,47 @@ public:
void setupUi(QWidget *BackSide)
{
if (BackSide->objectName().isEmpty())
- BackSide->setObjectName(QStringLiteral("BackSide"));
+ BackSide->setObjectName(QString::fromUtf8("BackSide"));
BackSide->resize(378, 385);
verticalLayout_2 = new QVBoxLayout(BackSide);
- verticalLayout_2->setObjectName(QStringLiteral("verticalLayout_2"));
+ verticalLayout_2->setObjectName(QString::fromUtf8("verticalLayout_2"));
groupBox = new QGroupBox(BackSide);
- groupBox->setObjectName(QStringLiteral("groupBox"));
+ groupBox->setObjectName(QString::fromUtf8("groupBox"));
groupBox->setFlat(true);
groupBox->setCheckable(true);
gridLayout = new QGridLayout(groupBox);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
label = new QLabel(groupBox);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
gridLayout->addWidget(label, 0, 0, 1, 1);
hostName = new QLineEdit(groupBox);
- hostName->setObjectName(QStringLiteral("hostName"));
+ hostName->setObjectName(QString::fromUtf8("hostName"));
gridLayout->addWidget(hostName, 0, 1, 1, 1);
label_2 = new QLabel(groupBox);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
gridLayout->addWidget(label_2, 1, 0, 1, 1);
label_3 = new QLabel(groupBox);
- label_3->setObjectName(QStringLiteral("label_3"));
+ label_3->setObjectName(QString::fromUtf8("label_3"));
gridLayout->addWidget(label_3, 2, 0, 1, 1);
horizontalLayout = new QHBoxLayout();
- horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
+ horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
horizontalSlider = new QSlider(groupBox);
- horizontalSlider->setObjectName(QStringLiteral("horizontalSlider"));
+ horizontalSlider->setObjectName(QString::fromUtf8("horizontalSlider"));
horizontalSlider->setValue(42);
horizontalSlider->setOrientation(Qt::Horizontal);
horizontalLayout->addWidget(horizontalSlider);
spinBox = new QSpinBox(groupBox);
- spinBox->setObjectName(QStringLiteral("spinBox"));
+ spinBox->setObjectName(QString::fromUtf8("spinBox"));
spinBox->setValue(42);
horizontalLayout->addWidget(spinBox);
@@ -96,7 +96,7 @@ public:
gridLayout->addLayout(horizontalLayout, 2, 1, 1, 1);
dateTimeEdit = new QDateTimeEdit(groupBox);
- dateTimeEdit->setObjectName(QStringLiteral("dateTimeEdit"));
+ dateTimeEdit->setObjectName(QString::fromUtf8("dateTimeEdit"));
gridLayout->addWidget(dateTimeEdit, 1, 1, 1, 1);
@@ -104,11 +104,11 @@ public:
verticalLayout_2->addWidget(groupBox);
groupBox_2 = new QGroupBox(BackSide);
- groupBox_2->setObjectName(QStringLiteral("groupBox_2"));
+ groupBox_2->setObjectName(QString::fromUtf8("groupBox_2"));
groupBox_2->setFlat(true);
groupBox_2->setCheckable(true);
horizontalLayout_2 = new QHBoxLayout(groupBox_2);
- horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2"));
+ horizontalLayout_2->setObjectName(QString::fromUtf8("horizontalLayout_2"));
treeWidget = new QTreeWidget(groupBox_2);
QTreeWidgetItem *__qtreewidgetitem = new QTreeWidgetItem(treeWidget);
QTreeWidgetItem *__qtreewidgetitem1 = new QTreeWidgetItem(__qtreewidgetitem);
@@ -121,7 +121,7 @@ public:
QTreeWidgetItem *__qtreewidgetitem4 = new QTreeWidgetItem(treeWidget);
QTreeWidgetItem *__qtreewidgetitem5 = new QTreeWidgetItem(__qtreewidgetitem4);
new QTreeWidgetItem(__qtreewidgetitem5);
- treeWidget->setObjectName(QStringLiteral("treeWidget"));
+ treeWidget->setObjectName(QString::fromUtf8("treeWidget"));
horizontalLayout_2->addWidget(treeWidget);
diff --git a/tests/auto/tools/uic/baseline/batchtranslation.ui.h b/tests/auto/tools/uic/baseline/batchtranslation.ui.h
index 1f55b6230e..8a4dc7a677 100644
--- a/tests/auto/tools/uic/baseline/batchtranslation.ui.h
+++ b/tests/auto/tools/uic/baseline/batchtranslation.ui.h
@@ -78,7 +78,7 @@ public:
void setupUi(QDialog *databaseTranslationDialog)
{
if (databaseTranslationDialog->objectName().isEmpty())
- databaseTranslationDialog->setObjectName(QStringLiteral("databaseTranslationDialog"));
+ databaseTranslationDialog->setObjectName(QString::fromUtf8("databaseTranslationDialog"));
databaseTranslationDialog->resize(425, 370);
vboxLayout = new QVBoxLayout(databaseTranslationDialog);
#ifndef Q_OS_MAC
@@ -87,9 +87,9 @@ public:
#ifndef Q_OS_MAC
vboxLayout->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
groupBox = new QGroupBox(databaseTranslationDialog);
- groupBox->setObjectName(QStringLiteral("groupBox"));
+ groupBox->setObjectName(QString::fromUtf8("groupBox"));
QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(5), static_cast<QSizePolicy::Policy>(4));
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -102,15 +102,15 @@ public:
#ifndef Q_OS_MAC
vboxLayout1->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout1->setObjectName(QStringLiteral("vboxLayout1"));
+ vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
ckOnlyUntranslated = new QCheckBox(groupBox);
- ckOnlyUntranslated->setObjectName(QStringLiteral("ckOnlyUntranslated"));
+ ckOnlyUntranslated->setObjectName(QString::fromUtf8("ckOnlyUntranslated"));
ckOnlyUntranslated->setChecked(true);
vboxLayout1->addWidget(ckOnlyUntranslated);
ckMarkFinished = new QCheckBox(groupBox);
- ckMarkFinished->setObjectName(QStringLiteral("ckMarkFinished"));
+ ckMarkFinished->setObjectName(QString::fromUtf8("ckMarkFinished"));
ckMarkFinished->setChecked(true);
vboxLayout1->addWidget(ckMarkFinished);
@@ -119,7 +119,7 @@ public:
vboxLayout->addWidget(groupBox);
groupBox_2 = new QGroupBox(databaseTranslationDialog);
- groupBox_2->setObjectName(QStringLiteral("groupBox_2"));
+ groupBox_2->setObjectName(QString::fromUtf8("groupBox_2"));
QSizePolicy sizePolicy1(static_cast<QSizePolicy::Policy>(5), static_cast<QSizePolicy::Policy>(1));
sizePolicy1.setHorizontalStretch(0);
sizePolicy1.setVerticalStretch(0);
@@ -132,7 +132,7 @@ public:
#ifndef Q_OS_MAC
vboxLayout2->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout2->setObjectName(QStringLiteral("vboxLayout2"));
+ vboxLayout2->setObjectName(QString::fromUtf8("vboxLayout2"));
hboxLayout = new QHBoxLayout();
#ifndef Q_OS_MAC
hboxLayout->setSpacing(6);
@@ -140,9 +140,9 @@ public:
#ifndef Q_OS_MAC
hboxLayout->setContentsMargins(0, 0, 0, 0);
#endif
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
phrasebookList = new QListView(groupBox_2);
- phrasebookList->setObjectName(QStringLiteral("phrasebookList"));
+ phrasebookList->setObjectName(QString::fromUtf8("phrasebookList"));
phrasebookList->setUniformItemSizes(true);
hboxLayout->addWidget(phrasebookList);
@@ -152,14 +152,14 @@ public:
vboxLayout3->setSpacing(6);
#endif
vboxLayout3->setContentsMargins(0, 0, 0, 0);
- vboxLayout3->setObjectName(QStringLiteral("vboxLayout3"));
+ vboxLayout3->setObjectName(QString::fromUtf8("vboxLayout3"));
moveUpButton = new QPushButton(groupBox_2);
- moveUpButton->setObjectName(QStringLiteral("moveUpButton"));
+ moveUpButton->setObjectName(QString::fromUtf8("moveUpButton"));
vboxLayout3->addWidget(moveUpButton);
moveDownButton = new QPushButton(groupBox_2);
- moveDownButton->setObjectName(QStringLiteral("moveDownButton"));
+ moveDownButton->setObjectName(QString::fromUtf8("moveDownButton"));
vboxLayout3->addWidget(moveDownButton);
@@ -174,7 +174,7 @@ public:
vboxLayout2->addLayout(hboxLayout);
label = new QLabel(groupBox_2);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
label->setWordWrap(true);
vboxLayout2->addWidget(label);
@@ -187,18 +187,18 @@ public:
hboxLayout1->setSpacing(6);
#endif
hboxLayout1->setContentsMargins(0, 0, 0, 0);
- hboxLayout1->setObjectName(QStringLiteral("hboxLayout1"));
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
spacerItem1 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
hboxLayout1->addItem(spacerItem1);
runButton = new QPushButton(databaseTranslationDialog);
- runButton->setObjectName(QStringLiteral("runButton"));
+ runButton->setObjectName(QString::fromUtf8("runButton"));
hboxLayout1->addWidget(runButton);
cancelButton = new QPushButton(databaseTranslationDialog);
- cancelButton->setObjectName(QStringLiteral("cancelButton"));
+ cancelButton->setObjectName(QString::fromUtf8("cancelButton"));
hboxLayout1->addWidget(cancelButton);
diff --git a/tests/auto/tools/uic/baseline/bookmarkdialog.ui.h b/tests/auto/tools/uic/baseline/bookmarkdialog.ui.h
index c2bb062bb8..b5a44998be 100644
--- a/tests/auto/tools/uic/baseline/bookmarkdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/bookmarkdialog.ui.h
@@ -48,7 +48,7 @@ public:
void setupUi(QDialog *BookmarkDialog)
{
if (BookmarkDialog->objectName().isEmpty())
- BookmarkDialog->setObjectName(QStringLiteral("BookmarkDialog"));
+ BookmarkDialog->setObjectName(QString::fromUtf8("BookmarkDialog"));
BookmarkDialog->resize(450, 135);
QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
sizePolicy.setHorizontalStretch(0);
@@ -56,18 +56,18 @@ public:
sizePolicy.setHeightForWidth(BookmarkDialog->sizePolicy().hasHeightForWidth());
BookmarkDialog->setSizePolicy(sizePolicy);
verticalLayout_3 = new QVBoxLayout(BookmarkDialog);
- verticalLayout_3->setObjectName(QStringLiteral("verticalLayout_3"));
+ verticalLayout_3->setObjectName(QString::fromUtf8("verticalLayout_3"));
horizontalLayout = new QHBoxLayout();
- horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
+ horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
verticalLayout_2 = new QVBoxLayout();
- verticalLayout_2->setObjectName(QStringLiteral("verticalLayout_2"));
+ verticalLayout_2->setObjectName(QString::fromUtf8("verticalLayout_2"));
label = new QLabel(BookmarkDialog);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
verticalLayout_2->addWidget(label);
label_2 = new QLabel(BookmarkDialog);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
verticalLayout_2->addWidget(label_2);
@@ -75,14 +75,14 @@ public:
horizontalLayout->addLayout(verticalLayout_2);
verticalLayout = new QVBoxLayout();
- verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
+ verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
bookmarkEdit = new QLineEdit(BookmarkDialog);
- bookmarkEdit->setObjectName(QStringLiteral("bookmarkEdit"));
+ bookmarkEdit->setObjectName(QString::fromUtf8("bookmarkEdit"));
verticalLayout->addWidget(bookmarkEdit);
bookmarkFolders = new QComboBox(BookmarkDialog);
- bookmarkFolders->setObjectName(QStringLiteral("bookmarkFolders"));
+ bookmarkFolders->setObjectName(QString::fromUtf8("bookmarkFolders"));
verticalLayout->addWidget(bookmarkFolders);
@@ -93,15 +93,15 @@ public:
verticalLayout_3->addLayout(horizontalLayout);
horizontalLayout_3 = new QHBoxLayout();
- horizontalLayout_3->setObjectName(QStringLiteral("horizontalLayout_3"));
+ horizontalLayout_3->setObjectName(QString::fromUtf8("horizontalLayout_3"));
toolButton = new QToolButton(BookmarkDialog);
- toolButton->setObjectName(QStringLiteral("toolButton"));
+ toolButton->setObjectName(QString::fromUtf8("toolButton"));
toolButton->setMinimumSize(QSize(25, 20));
horizontalLayout_3->addWidget(toolButton);
line = new QFrame(BookmarkDialog);
- line->setObjectName(QStringLiteral("line"));
+ line->setObjectName(QString::fromUtf8("line"));
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
@@ -111,7 +111,7 @@ public:
verticalLayout_3->addLayout(horizontalLayout_3);
bookmarkWidget = new BookmarkWidget(BookmarkDialog);
- bookmarkWidget->setObjectName(QStringLiteral("bookmarkWidget"));
+ bookmarkWidget->setObjectName(QString::fromUtf8("bookmarkWidget"));
bookmarkWidget->setEnabled(true);
QSizePolicy sizePolicy1(QSizePolicy::Expanding, QSizePolicy::Ignored);
sizePolicy1.setHorizontalStretch(0);
@@ -122,14 +122,14 @@ public:
verticalLayout_3->addWidget(bookmarkWidget);
horizontalLayout_4 = new QHBoxLayout();
- horizontalLayout_4->setObjectName(QStringLiteral("horizontalLayout_4"));
+ horizontalLayout_4->setObjectName(QString::fromUtf8("horizontalLayout_4"));
newFolderButton = new QPushButton(BookmarkDialog);
- newFolderButton->setObjectName(QStringLiteral("newFolderButton"));
+ newFolderButton->setObjectName(QString::fromUtf8("newFolderButton"));
horizontalLayout_4->addWidget(newFolderButton);
buttonBox = new QDialogButtonBox(BookmarkDialog);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
diff --git a/tests/auto/tools/uic/baseline/bookwindow.ui.h b/tests/auto/tools/uic/baseline/bookwindow.ui.h
index 89b1e04c6c..8fe5f000e2 100644
--- a/tests/auto/tools/uic/baseline/bookwindow.ui.h
+++ b/tests/auto/tools/uic/baseline/bookwindow.ui.h
@@ -49,10 +49,10 @@ public:
void setupUi(QMainWindow *BookWindow)
{
if (BookWindow->objectName().isEmpty())
- BookWindow->setObjectName(QStringLiteral("BookWindow"));
+ BookWindow->setObjectName(QString::fromUtf8("BookWindow"));
BookWindow->resize(601, 420);
centralWidget = new QWidget(BookWindow);
- centralWidget->setObjectName(QStringLiteral("centralWidget"));
+ centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
vboxLayout = new QVBoxLayout(centralWidget);
#ifndef Q_OS_MAC
vboxLayout->setSpacing(6);
@@ -60,9 +60,9 @@ public:
#ifndef Q_OS_MAC
vboxLayout->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
groupBox = new QGroupBox(centralWidget);
- groupBox->setObjectName(QStringLiteral("groupBox"));
+ groupBox->setObjectName(QString::fromUtf8("groupBox"));
vboxLayout1 = new QVBoxLayout(groupBox);
#ifndef Q_OS_MAC
vboxLayout1->setSpacing(6);
@@ -70,57 +70,57 @@ public:
#ifndef Q_OS_MAC
vboxLayout1->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout1->setObjectName(QStringLiteral("vboxLayout1"));
+ vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
bookTable = new QTableView(groupBox);
- bookTable->setObjectName(QStringLiteral("bookTable"));
+ bookTable->setObjectName(QString::fromUtf8("bookTable"));
bookTable->setSelectionBehavior(QAbstractItemView::SelectRows);
vboxLayout1->addWidget(bookTable);
groupBox_2 = new QGroupBox(groupBox);
- groupBox_2->setObjectName(QStringLiteral("groupBox_2"));
+ groupBox_2->setObjectName(QString::fromUtf8("groupBox_2"));
formLayout = new QFormLayout(groupBox_2);
- formLayout->setObjectName(QStringLiteral("formLayout"));
+ formLayout->setObjectName(QString::fromUtf8("formLayout"));
label_5 = new QLabel(groupBox_2);
- label_5->setObjectName(QStringLiteral("label_5"));
+ label_5->setObjectName(QString::fromUtf8("label_5"));
formLayout->setWidget(0, QFormLayout::LabelRole, label_5);
titleEdit = new QLineEdit(groupBox_2);
- titleEdit->setObjectName(QStringLiteral("titleEdit"));
+ titleEdit->setObjectName(QString::fromUtf8("titleEdit"));
titleEdit->setEnabled(true);
formLayout->setWidget(0, QFormLayout::FieldRole, titleEdit);
label_2_2_2_2 = new QLabel(groupBox_2);
- label_2_2_2_2->setObjectName(QStringLiteral("label_2_2_2_2"));
+ label_2_2_2_2->setObjectName(QString::fromUtf8("label_2_2_2_2"));
formLayout->setWidget(1, QFormLayout::LabelRole, label_2_2_2_2);
authorEdit = new QComboBox(groupBox_2);
- authorEdit->setObjectName(QStringLiteral("authorEdit"));
+ authorEdit->setObjectName(QString::fromUtf8("authorEdit"));
authorEdit->setEnabled(true);
formLayout->setWidget(1, QFormLayout::FieldRole, authorEdit);
label_3 = new QLabel(groupBox_2);
- label_3->setObjectName(QStringLiteral("label_3"));
+ label_3->setObjectName(QString::fromUtf8("label_3"));
formLayout->setWidget(2, QFormLayout::LabelRole, label_3);
genreEdit = new QComboBox(groupBox_2);
- genreEdit->setObjectName(QStringLiteral("genreEdit"));
+ genreEdit->setObjectName(QString::fromUtf8("genreEdit"));
genreEdit->setEnabled(true);
formLayout->setWidget(2, QFormLayout::FieldRole, genreEdit);
label_4 = new QLabel(groupBox_2);
- label_4->setObjectName(QStringLiteral("label_4"));
+ label_4->setObjectName(QString::fromUtf8("label_4"));
formLayout->setWidget(3, QFormLayout::LabelRole, label_4);
yearEdit = new QSpinBox(groupBox_2);
- yearEdit->setObjectName(QStringLiteral("yearEdit"));
+ yearEdit->setObjectName(QString::fromUtf8("yearEdit"));
yearEdit->setEnabled(true);
yearEdit->setMaximum(2100);
yearEdit->setMinimum(-1000);
@@ -128,12 +128,12 @@ public:
formLayout->setWidget(3, QFormLayout::FieldRole, yearEdit);
label = new QLabel(groupBox_2);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
formLayout->setWidget(4, QFormLayout::LabelRole, label);
ratingEdit = new QSpinBox(groupBox_2);
- ratingEdit->setObjectName(QStringLiteral("ratingEdit"));
+ ratingEdit->setObjectName(QString::fromUtf8("ratingEdit"));
ratingEdit->setMaximum(5);
formLayout->setWidget(4, QFormLayout::FieldRole, ratingEdit);
diff --git a/tests/auto/tools/uic/baseline/browserwidget.ui.h b/tests/auto/tools/uic/baseline/browserwidget.ui.h
index 491f51ce94..3db93c34cf 100644
--- a/tests/auto/tools/uic/baseline/browserwidget.ui.h
+++ b/tests/auto/tools/uic/baseline/browserwidget.ui.h
@@ -46,22 +46,22 @@ public:
void setupUi(QWidget *Browser)
{
if (Browser->objectName().isEmpty())
- Browser->setObjectName(QStringLiteral("Browser"));
+ Browser->setObjectName(QString::fromUtf8("Browser"));
Browser->resize(765, 515);
insertRowAction = new QAction(Browser);
- insertRowAction->setObjectName(QStringLiteral("insertRowAction"));
+ insertRowAction->setObjectName(QString::fromUtf8("insertRowAction"));
insertRowAction->setEnabled(false);
deleteRowAction = new QAction(Browser);
- deleteRowAction->setObjectName(QStringLiteral("deleteRowAction"));
+ deleteRowAction->setObjectName(QString::fromUtf8("deleteRowAction"));
deleteRowAction->setEnabled(false);
vboxLayout = new QVBoxLayout(Browser);
#ifndef Q_OS_MAC
vboxLayout->setSpacing(6);
#endif
vboxLayout->setContentsMargins(8, 8, 8, 8);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
splitter_2 = new QSplitter(Browser);
- splitter_2->setObjectName(QStringLiteral("splitter_2"));
+ splitter_2->setObjectName(QString::fromUtf8("splitter_2"));
QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(7), static_cast<QSizePolicy::Policy>(7));
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -69,7 +69,7 @@ public:
splitter_2->setSizePolicy(sizePolicy);
splitter_2->setOrientation(Qt::Horizontal);
connectionWidget = new ConnectionWidget(splitter_2);
- connectionWidget->setObjectName(QStringLiteral("connectionWidget"));
+ connectionWidget->setObjectName(QString::fromUtf8("connectionWidget"));
QSizePolicy sizePolicy1(static_cast<QSizePolicy::Policy>(13), static_cast<QSizePolicy::Policy>(7));
sizePolicy1.setHorizontalStretch(1);
sizePolicy1.setVerticalStretch(0);
@@ -77,7 +77,7 @@ public:
connectionWidget->setSizePolicy(sizePolicy1);
splitter_2->addWidget(connectionWidget);
table = new QTableView(splitter_2);
- table->setObjectName(QStringLiteral("table"));
+ table->setObjectName(QString::fromUtf8("table"));
QSizePolicy sizePolicy2(static_cast<QSizePolicy::Policy>(7), static_cast<QSizePolicy::Policy>(7));
sizePolicy2.setHorizontalStretch(2);
sizePolicy2.setVerticalStretch(0);
@@ -90,7 +90,7 @@ public:
vboxLayout->addWidget(splitter_2);
groupBox = new QGroupBox(Browser);
- groupBox->setObjectName(QStringLiteral("groupBox"));
+ groupBox->setObjectName(QString::fromUtf8("groupBox"));
QSizePolicy sizePolicy3(static_cast<QSizePolicy::Policy>(5), static_cast<QSizePolicy::Policy>(3));
sizePolicy3.setHorizontalStretch(0);
sizePolicy3.setVerticalStretch(0);
@@ -104,9 +104,9 @@ public:
#ifndef Q_OS_MAC
vboxLayout1->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout1->setObjectName(QStringLiteral("vboxLayout1"));
+ vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
sqlEdit = new QTextEdit(groupBox);
- sqlEdit->setObjectName(QStringLiteral("sqlEdit"));
+ sqlEdit->setObjectName(QString::fromUtf8("sqlEdit"));
QSizePolicy sizePolicy4(static_cast<QSizePolicy::Policy>(7), static_cast<QSizePolicy::Policy>(3));
sizePolicy4.setHorizontalStretch(0);
sizePolicy4.setVerticalStretch(0);
@@ -122,18 +122,18 @@ public:
hboxLayout->setSpacing(6);
#endif
hboxLayout->setContentsMargins(1, 1, 1, 1);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
spacerItem = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
hboxLayout->addItem(spacerItem);
clearButton = new QPushButton(groupBox);
- clearButton->setObjectName(QStringLiteral("clearButton"));
+ clearButton->setObjectName(QString::fromUtf8("clearButton"));
hboxLayout->addWidget(clearButton);
submitButton = new QPushButton(groupBox);
- submitButton->setObjectName(QStringLiteral("submitButton"));
+ submitButton->setObjectName(QString::fromUtf8("submitButton"));
hboxLayout->addWidget(submitButton);
diff --git a/tests/auto/tools/uic/baseline/bug18156QTreeWidget.ui.h b/tests/auto/tools/uic/baseline/bug18156QTreeWidget.ui.h
index 5a545485e3..47f8f22132 100644
--- a/tests/auto/tools/uic/baseline/bug18156QTreeWidget.ui.h
+++ b/tests/auto/tools/uic/baseline/bug18156QTreeWidget.ui.h
@@ -29,19 +29,19 @@ public:
void setupUi(QDialog *Dialog)
{
if (Dialog->objectName().isEmpty())
- Dialog->setObjectName(QStringLiteral("Dialog"));
+ Dialog->setObjectName(QString::fromUtf8("Dialog"));
Dialog->resize(400, 300);
gridLayout = new QGridLayout(Dialog);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
treeWidget = new QTreeWidget(Dialog);
treeWidget->headerItem()->setText(0, QString());
treeWidget->headerItem()->setText(2, QString());
- treeWidget->setObjectName(QStringLiteral("treeWidget"));
+ treeWidget->setObjectName(QString::fromUtf8("treeWidget"));
gridLayout->addWidget(treeWidget, 0, 0, 1, 1);
buttonBox = new QDialogButtonBox(Dialog);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
diff --git a/tests/auto/tools/uic/baseline/buttongroup.ui.h b/tests/auto/tools/uic/baseline/buttongroup.ui.h
index 38029df7ec..87814dcba1 100644
--- a/tests/auto/tools/uic/baseline/buttongroup.ui.h
+++ b/tests/auto/tools/uic/baseline/buttongroup.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'buttongroup.ui'
**
-** Created by: Qt User Interface Compiler version 5.10.1
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -51,12 +51,12 @@ public:
void setupUi(QWidget *Form)
{
if (Form->objectName().isEmpty())
- Form->setObjectName(QStringLiteral("Form"));
+ Form->setObjectName(QString::fromUtf8("Form"));
Form->resize(545, 471);
gridLayout = new QGridLayout(Form);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
easingCurvePicker = new QListWidget(Form);
- easingCurvePicker->setObjectName(QStringLiteral("easingCurvePicker"));
+ easingCurvePicker->setObjectName(QString::fromUtf8("easingCurvePicker"));
QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -72,17 +72,17 @@ public:
gridLayout->addWidget(easingCurvePicker, 0, 0, 1, 2);
verticalLayout = new QVBoxLayout();
- verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
+ verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
groupBox_2 = new QGroupBox(Form);
- groupBox_2->setObjectName(QStringLiteral("groupBox_2"));
+ groupBox_2->setObjectName(QString::fromUtf8("groupBox_2"));
groupBox_2->setMaximumSize(QSize(16777215, 16777215));
gridLayout_2 = new QGridLayout(groupBox_2);
- gridLayout_2->setObjectName(QStringLiteral("gridLayout_2"));
+ gridLayout_2->setObjectName(QString::fromUtf8("gridLayout_2"));
lineRadio = new QRadioButton(groupBox_2);
buttonGroup = new QButtonGroup(Form);
- buttonGroup->setObjectName(QStringLiteral("buttonGroup"));
+ buttonGroup->setObjectName(QString::fromUtf8("buttonGroup"));
buttonGroup->addButton(lineRadio);
- lineRadio->setObjectName(QStringLiteral("lineRadio"));
+ lineRadio->setObjectName(QString::fromUtf8("lineRadio"));
lineRadio->setMaximumSize(QSize(16777215, 40));
lineRadio->setLayoutDirection(Qt::LeftToRight);
lineRadio->setChecked(true);
@@ -91,7 +91,7 @@ public:
circleRadio = new QRadioButton(groupBox_2);
buttonGroup->addButton(circleRadio);
- circleRadio->setObjectName(QStringLiteral("circleRadio"));
+ circleRadio->setObjectName(QString::fromUtf8("circleRadio"));
circleRadio->setMaximumSize(QSize(16777215, 40));
gridLayout_2->addWidget(circleRadio, 1, 0, 1, 1);
@@ -100,17 +100,17 @@ public:
verticalLayout->addWidget(groupBox_2);
groupBox = new QGroupBox(Form);
- groupBox->setObjectName(QStringLiteral("groupBox"));
+ groupBox->setObjectName(QString::fromUtf8("groupBox"));
QSizePolicy sizePolicy1(QSizePolicy::Fixed, QSizePolicy::Preferred);
sizePolicy1.setHorizontalStretch(0);
sizePolicy1.setVerticalStretch(0);
sizePolicy1.setHeightForWidth(groupBox->sizePolicy().hasHeightForWidth());
groupBox->setSizePolicy(sizePolicy1);
formLayout = new QFormLayout(groupBox);
- formLayout->setObjectName(QStringLiteral("formLayout"));
+ formLayout->setObjectName(QString::fromUtf8("formLayout"));
formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
label = new QLabel(groupBox);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
QSizePolicy sizePolicy2(QSizePolicy::Preferred, QSizePolicy::Preferred);
sizePolicy2.setHorizontalStretch(0);
sizePolicy2.setVerticalStretch(0);
@@ -121,7 +121,7 @@ public:
formLayout->setWidget(0, QFormLayout::LabelRole, label);
periodSpinBox = new QDoubleSpinBox(groupBox);
- periodSpinBox->setObjectName(QStringLiteral("periodSpinBox"));
+ periodSpinBox->setObjectName(QString::fromUtf8("periodSpinBox"));
periodSpinBox->setEnabled(false);
QSizePolicy sizePolicy3(QSizePolicy::Minimum, QSizePolicy::Fixed);
sizePolicy3.setHorizontalStretch(0);
@@ -129,40 +129,40 @@ public:
sizePolicy3.setHeightForWidth(periodSpinBox->sizePolicy().hasHeightForWidth());
periodSpinBox->setSizePolicy(sizePolicy3);
periodSpinBox->setMinimumSize(QSize(0, 30));
- periodSpinBox->setMinimum(-1);
- periodSpinBox->setSingleStep(0.1);
- periodSpinBox->setValue(-1);
+ periodSpinBox->setMinimum(-1.000000000000000);
+ periodSpinBox->setSingleStep(0.100000000000000);
+ periodSpinBox->setValue(-1.000000000000000);
formLayout->setWidget(0, QFormLayout::FieldRole, periodSpinBox);
amplitudeSpinBox = new QDoubleSpinBox(groupBox);
- amplitudeSpinBox->setObjectName(QStringLiteral("amplitudeSpinBox"));
+ amplitudeSpinBox->setObjectName(QString::fromUtf8("amplitudeSpinBox"));
amplitudeSpinBox->setEnabled(false);
amplitudeSpinBox->setMinimumSize(QSize(0, 30));
- amplitudeSpinBox->setMinimum(-1);
- amplitudeSpinBox->setSingleStep(0.1);
- amplitudeSpinBox->setValue(-1);
+ amplitudeSpinBox->setMinimum(-1.000000000000000);
+ amplitudeSpinBox->setSingleStep(0.100000000000000);
+ amplitudeSpinBox->setValue(-1.000000000000000);
formLayout->setWidget(2, QFormLayout::FieldRole, amplitudeSpinBox);
label_3 = new QLabel(groupBox);
- label_3->setObjectName(QStringLiteral("label_3"));
+ label_3->setObjectName(QString::fromUtf8("label_3"));
label_3->setMinimumSize(QSize(0, 30));
formLayout->setWidget(4, QFormLayout::LabelRole, label_3);
overshootSpinBox = new QDoubleSpinBox(groupBox);
- overshootSpinBox->setObjectName(QStringLiteral("overshootSpinBox"));
+ overshootSpinBox->setObjectName(QString::fromUtf8("overshootSpinBox"));
overshootSpinBox->setEnabled(false);
overshootSpinBox->setMinimumSize(QSize(0, 30));
- overshootSpinBox->setMinimum(-1);
- overshootSpinBox->setSingleStep(0.1);
- overshootSpinBox->setValue(-1);
+ overshootSpinBox->setMinimum(-1.000000000000000);
+ overshootSpinBox->setSingleStep(0.100000000000000);
+ overshootSpinBox->setValue(-1.000000000000000);
formLayout->setWidget(4, QFormLayout::FieldRole, overshootSpinBox);
label_2 = new QLabel(groupBox);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
label_2->setMinimumSize(QSize(0, 30));
formLayout->setWidget(2, QFormLayout::LabelRole, label_2);
@@ -178,7 +178,7 @@ public:
gridLayout->addLayout(verticalLayout, 1, 0, 1, 1);
graphicsView = new QGraphicsView(Form);
- graphicsView->setObjectName(QStringLiteral("graphicsView"));
+ graphicsView->setObjectName(QString::fromUtf8("graphicsView"));
QSizePolicy sizePolicy4(QSizePolicy::Expanding, QSizePolicy::Expanding);
sizePolicy4.setHorizontalStretch(0);
sizePolicy4.setVerticalStretch(0);
diff --git a/tests/auto/tools/uic/baseline/calculator.ui.h b/tests/auto/tools/uic/baseline/calculator.ui.h
index ad738d7afc..0387ee472b 100644
--- a/tests/auto/tools/uic/baseline/calculator.ui.h
+++ b/tests/auto/tools/uic/baseline/calculator.ui.h
@@ -52,7 +52,7 @@ public:
void setupUi(QWidget *Calculator)
{
if (Calculator->objectName().isEmpty())
- Calculator->setObjectName(QStringLiteral("Calculator"));
+ Calculator->setObjectName(QString::fromUtf8("Calculator"));
Calculator->resize(314, 301);
QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
sizePolicy.setHorizontalStretch(0);
@@ -62,88 +62,88 @@ public:
Calculator->setMinimumSize(QSize(314, 301));
Calculator->setMaximumSize(QSize(314, 301));
backspaceButton = new QToolButton(Calculator);
- backspaceButton->setObjectName(QStringLiteral("backspaceButton"));
+ backspaceButton->setObjectName(QString::fromUtf8("backspaceButton"));
backspaceButton->setGeometry(QRect(10, 50, 91, 41));
clearButton = new QToolButton(Calculator);
- clearButton->setObjectName(QStringLiteral("clearButton"));
+ clearButton->setObjectName(QString::fromUtf8("clearButton"));
clearButton->setGeometry(QRect(110, 50, 91, 41));
clearAllButton = new QToolButton(Calculator);
- clearAllButton->setObjectName(QStringLiteral("clearAllButton"));
+ clearAllButton->setObjectName(QString::fromUtf8("clearAllButton"));
clearAllButton->setGeometry(QRect(210, 50, 91, 41));
clearMemoryButton = new QToolButton(Calculator);
- clearMemoryButton->setObjectName(QStringLiteral("clearMemoryButton"));
+ clearMemoryButton->setObjectName(QString::fromUtf8("clearMemoryButton"));
clearMemoryButton->setGeometry(QRect(10, 100, 41, 41));
readMemoryButton = new QToolButton(Calculator);
- readMemoryButton->setObjectName(QStringLiteral("readMemoryButton"));
+ readMemoryButton->setObjectName(QString::fromUtf8("readMemoryButton"));
readMemoryButton->setGeometry(QRect(10, 150, 41, 41));
setMemoryButton = new QToolButton(Calculator);
- setMemoryButton->setObjectName(QStringLiteral("setMemoryButton"));
+ setMemoryButton->setObjectName(QString::fromUtf8("setMemoryButton"));
setMemoryButton->setGeometry(QRect(10, 200, 41, 41));
addToMemoryButton = new QToolButton(Calculator);
- addToMemoryButton->setObjectName(QStringLiteral("addToMemoryButton"));
+ addToMemoryButton->setObjectName(QString::fromUtf8("addToMemoryButton"));
addToMemoryButton->setGeometry(QRect(10, 250, 41, 41));
sevenButton = new QToolButton(Calculator);
- sevenButton->setObjectName(QStringLiteral("sevenButton"));
+ sevenButton->setObjectName(QString::fromUtf8("sevenButton"));
sevenButton->setGeometry(QRect(60, 100, 41, 41));
eightButton = new QToolButton(Calculator);
- eightButton->setObjectName(QStringLiteral("eightButton"));
+ eightButton->setObjectName(QString::fromUtf8("eightButton"));
eightButton->setGeometry(QRect(110, 100, 41, 41));
nineButton = new QToolButton(Calculator);
- nineButton->setObjectName(QStringLiteral("nineButton"));
+ nineButton->setObjectName(QString::fromUtf8("nineButton"));
nineButton->setGeometry(QRect(160, 100, 41, 41));
fourButton = new QToolButton(Calculator);
- fourButton->setObjectName(QStringLiteral("fourButton"));
+ fourButton->setObjectName(QString::fromUtf8("fourButton"));
fourButton->setGeometry(QRect(60, 150, 41, 41));
fiveButton = new QToolButton(Calculator);
- fiveButton->setObjectName(QStringLiteral("fiveButton"));
+ fiveButton->setObjectName(QString::fromUtf8("fiveButton"));
fiveButton->setGeometry(QRect(110, 150, 41, 41));
sixButton = new QToolButton(Calculator);
- sixButton->setObjectName(QStringLiteral("sixButton"));
+ sixButton->setObjectName(QString::fromUtf8("sixButton"));
sixButton->setGeometry(QRect(160, 150, 41, 41));
oneButton = new QToolButton(Calculator);
- oneButton->setObjectName(QStringLiteral("oneButton"));
+ oneButton->setObjectName(QString::fromUtf8("oneButton"));
oneButton->setGeometry(QRect(60, 200, 41, 41));
twoButton = new QToolButton(Calculator);
- twoButton->setObjectName(QStringLiteral("twoButton"));
+ twoButton->setObjectName(QString::fromUtf8("twoButton"));
twoButton->setGeometry(QRect(110, 200, 41, 41));
threeButton = new QToolButton(Calculator);
- threeButton->setObjectName(QStringLiteral("threeButton"));
+ threeButton->setObjectName(QString::fromUtf8("threeButton"));
threeButton->setGeometry(QRect(160, 200, 41, 41));
zeroButton = new QToolButton(Calculator);
- zeroButton->setObjectName(QStringLiteral("zeroButton"));
+ zeroButton->setObjectName(QString::fromUtf8("zeroButton"));
zeroButton->setGeometry(QRect(60, 250, 41, 41));
pointButton = new QToolButton(Calculator);
- pointButton->setObjectName(QStringLiteral("pointButton"));
+ pointButton->setObjectName(QString::fromUtf8("pointButton"));
pointButton->setGeometry(QRect(110, 250, 41, 41));
changeSignButton = new QToolButton(Calculator);
- changeSignButton->setObjectName(QStringLiteral("changeSignButton"));
+ changeSignButton->setObjectName(QString::fromUtf8("changeSignButton"));
changeSignButton->setGeometry(QRect(160, 250, 41, 41));
plusButton = new QToolButton(Calculator);
- plusButton->setObjectName(QStringLiteral("plusButton"));
+ plusButton->setObjectName(QString::fromUtf8("plusButton"));
plusButton->setGeometry(QRect(210, 250, 41, 41));
divisionButton = new QToolButton(Calculator);
- divisionButton->setObjectName(QStringLiteral("divisionButton"));
+ divisionButton->setObjectName(QString::fromUtf8("divisionButton"));
divisionButton->setGeometry(QRect(210, 100, 41, 41));
timesButton = new QToolButton(Calculator);
- timesButton->setObjectName(QStringLiteral("timesButton"));
+ timesButton->setObjectName(QString::fromUtf8("timesButton"));
timesButton->setGeometry(QRect(210, 150, 41, 41));
minusButton = new QToolButton(Calculator);
- minusButton->setObjectName(QStringLiteral("minusButton"));
+ minusButton->setObjectName(QString::fromUtf8("minusButton"));
minusButton->setGeometry(QRect(210, 200, 41, 41));
squareRootButton = new QToolButton(Calculator);
- squareRootButton->setObjectName(QStringLiteral("squareRootButton"));
+ squareRootButton->setObjectName(QString::fromUtf8("squareRootButton"));
squareRootButton->setGeometry(QRect(260, 100, 41, 41));
powerButton = new QToolButton(Calculator);
- powerButton->setObjectName(QStringLiteral("powerButton"));
+ powerButton->setObjectName(QString::fromUtf8("powerButton"));
powerButton->setGeometry(QRect(260, 150, 41, 41));
reciprocalButton = new QToolButton(Calculator);
- reciprocalButton->setObjectName(QStringLiteral("reciprocalButton"));
+ reciprocalButton->setObjectName(QString::fromUtf8("reciprocalButton"));
reciprocalButton->setGeometry(QRect(260, 200, 41, 41));
equalButton = new QToolButton(Calculator);
- equalButton->setObjectName(QStringLiteral("equalButton"));
+ equalButton->setObjectName(QString::fromUtf8("equalButton"));
equalButton->setGeometry(QRect(260, 250, 41, 41));
display = new QLineEdit(Calculator);
- display->setObjectName(QStringLiteral("display"));
+ display->setObjectName(QString::fromUtf8("display"));
display->setGeometry(QRect(10, 10, 291, 31));
display->setMaxLength(15);
display->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
diff --git a/tests/auto/tools/uic/baseline/calculatorform.ui.h b/tests/auto/tools/uic/baseline/calculatorform.ui.h
index ced29d5eab..f4661c6237 100644
--- a/tests/auto/tools/uic/baseline/calculatorform.ui.h
+++ b/tests/auto/tools/uic/baseline/calculatorform.ui.h
@@ -43,7 +43,7 @@ public:
void setupUi(QWidget *CalculatorForm)
{
if (CalculatorForm->objectName().isEmpty())
- CalculatorForm->setObjectName(QStringLiteral("CalculatorForm"));
+ CalculatorForm->setObjectName(QString::fromUtf8("CalculatorForm"));
CalculatorForm->resize(276, 98);
QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(5), static_cast<QSizePolicy::Policy>(5));
sizePolicy.setHorizontalStretch(0);
@@ -57,30 +57,30 @@ public:
#ifndef Q_OS_MAC
gridLayout->setContentsMargins(9, 9, 9, 9);
#endif
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
- gridLayout->setObjectName(QStringLiteral(""));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8(""));
hboxLayout = new QHBoxLayout();
#ifndef Q_OS_MAC
hboxLayout->setSpacing(6);
#endif
hboxLayout->setContentsMargins(1, 1, 1, 1);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
- hboxLayout->setObjectName(QStringLiteral(""));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8(""));
vboxLayout = new QVBoxLayout();
#ifndef Q_OS_MAC
vboxLayout->setSpacing(6);
#endif
vboxLayout->setContentsMargins(1, 1, 1, 1);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
- vboxLayout->setObjectName(QStringLiteral(""));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8(""));
label = new QLabel(CalculatorForm);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
label->setGeometry(QRect(1, 1, 45, 19));
vboxLayout->addWidget(label);
inputSpinBox1 = new QSpinBox(CalculatorForm);
- inputSpinBox1->setObjectName(QStringLiteral("inputSpinBox1"));
+ inputSpinBox1->setObjectName(QString::fromUtf8("inputSpinBox1"));
inputSpinBox1->setGeometry(QRect(1, 26, 45, 25));
inputSpinBox1->setMouseTracking(true);
@@ -90,7 +90,7 @@ public:
hboxLayout->addLayout(vboxLayout);
label_3 = new QLabel(CalculatorForm);
- label_3->setObjectName(QStringLiteral("label_3"));
+ label_3->setObjectName(QString::fromUtf8("label_3"));
label_3->setGeometry(QRect(54, 1, 7, 52));
label_3->setAlignment(Qt::AlignCenter);
@@ -101,16 +101,16 @@ public:
vboxLayout1->setSpacing(6);
#endif
vboxLayout1->setContentsMargins(1, 1, 1, 1);
- vboxLayout1->setObjectName(QStringLiteral("vboxLayout1"));
- vboxLayout1->setObjectName(QStringLiteral(""));
+ vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
+ vboxLayout1->setObjectName(QString::fromUtf8(""));
label_2 = new QLabel(CalculatorForm);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
label_2->setGeometry(QRect(1, 1, 45, 19));
vboxLayout1->addWidget(label_2);
inputSpinBox2 = new QSpinBox(CalculatorForm);
- inputSpinBox2->setObjectName(QStringLiteral("inputSpinBox2"));
+ inputSpinBox2->setObjectName(QString::fromUtf8("inputSpinBox2"));
inputSpinBox2->setGeometry(QRect(1, 26, 45, 25));
inputSpinBox2->setMouseTracking(true);
@@ -120,7 +120,7 @@ public:
hboxLayout->addLayout(vboxLayout1);
label_3_2 = new QLabel(CalculatorForm);
- label_3_2->setObjectName(QStringLiteral("label_3_2"));
+ label_3_2->setObjectName(QString::fromUtf8("label_3_2"));
label_3_2->setGeometry(QRect(120, 1, 7, 52));
label_3_2->setAlignment(Qt::AlignCenter);
@@ -131,16 +131,16 @@ public:
vboxLayout2->setSpacing(6);
#endif
vboxLayout2->setContentsMargins(1, 1, 1, 1);
- vboxLayout2->setObjectName(QStringLiteral("vboxLayout2"));
- vboxLayout2->setObjectName(QStringLiteral(""));
+ vboxLayout2->setObjectName(QString::fromUtf8("vboxLayout2"));
+ vboxLayout2->setObjectName(QString::fromUtf8(""));
label_2_2_2 = new QLabel(CalculatorForm);
- label_2_2_2->setObjectName(QStringLiteral("label_2_2_2"));
+ label_2_2_2->setObjectName(QString::fromUtf8("label_2_2_2"));
label_2_2_2->setGeometry(QRect(1, 1, 37, 17));
vboxLayout2->addWidget(label_2_2_2);
outputWidget = new QLabel(CalculatorForm);
- outputWidget->setObjectName(QStringLiteral("outputWidget"));
+ outputWidget->setObjectName(QString::fromUtf8("outputWidget"));
outputWidget->setGeometry(QRect(1, 24, 37, 27));
outputWidget->setFrameShape(QFrame::Box);
outputWidget->setFrameShadow(QFrame::Sunken);
diff --git a/tests/auto/tools/uic/baseline/certificateinfo.ui.h b/tests/auto/tools/uic/baseline/certificateinfo.ui.h
index 07263bcdd7..2aa47d40ad 100644
--- a/tests/auto/tools/uic/baseline/certificateinfo.ui.h
+++ b/tests/auto/tools/uic/baseline/certificateinfo.ui.h
@@ -38,16 +38,16 @@ public:
void setupUi(QDialog *CertificateInfo)
{
if (CertificateInfo->objectName().isEmpty())
- CertificateInfo->setObjectName(QStringLiteral("CertificateInfo"));
+ CertificateInfo->setObjectName(QString::fromUtf8("CertificateInfo"));
CertificateInfo->resize(400, 397);
vboxLayout = new QVBoxLayout(CertificateInfo);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
groupBox = new QGroupBox(CertificateInfo);
- groupBox->setObjectName(QStringLiteral("groupBox"));
+ groupBox->setObjectName(QString::fromUtf8("groupBox"));
hboxLayout = new QHBoxLayout(groupBox);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
certificationPathView = new QListWidget(groupBox);
- certificationPathView->setObjectName(QStringLiteral("certificationPathView"));
+ certificationPathView->setObjectName(QString::fromUtf8("certificationPathView"));
hboxLayout->addWidget(certificationPathView);
@@ -55,11 +55,11 @@ public:
vboxLayout->addWidget(groupBox);
groupBox_2 = new QGroupBox(CertificateInfo);
- groupBox_2->setObjectName(QStringLiteral("groupBox_2"));
+ groupBox_2->setObjectName(QString::fromUtf8("groupBox_2"));
hboxLayout1 = new QHBoxLayout(groupBox_2);
- hboxLayout1->setObjectName(QStringLiteral("hboxLayout1"));
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
certificateInfoView = new QListWidget(groupBox_2);
- certificateInfoView->setObjectName(QStringLiteral("certificateInfoView"));
+ certificateInfoView->setObjectName(QString::fromUtf8("certificateInfoView"));
hboxLayout1->addWidget(certificateInfoView);
@@ -67,13 +67,13 @@ public:
vboxLayout->addWidget(groupBox_2);
hboxLayout2 = new QHBoxLayout();
- hboxLayout2->setObjectName(QStringLiteral("hboxLayout2"));
+ hboxLayout2->setObjectName(QString::fromUtf8("hboxLayout2"));
spacerItem = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
hboxLayout2->addItem(spacerItem);
buttonBox = new QDialogButtonBox(CertificateInfo);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setStandardButtons(QDialogButtonBox::Close);
hboxLayout2->addWidget(buttonBox);
diff --git a/tests/auto/tools/uic/baseline/chatdialog.ui.h b/tests/auto/tools/uic/baseline/chatdialog.ui.h
index 32b083fbc4..ace6951669 100644
--- a/tests/auto/tools/uic/baseline/chatdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/chatdialog.ui.h
@@ -35,7 +35,7 @@ public:
void setupUi(QDialog *ChatDialog)
{
if (ChatDialog->objectName().isEmpty())
- ChatDialog->setObjectName(QStringLiteral("ChatDialog"));
+ ChatDialog->setObjectName(QString::fromUtf8("ChatDialog"));
ChatDialog->resize(513, 349);
vboxLayout = new QVBoxLayout(ChatDialog);
#ifndef Q_OS_MAC
@@ -44,7 +44,7 @@ public:
#ifndef Q_OS_MAC
vboxLayout->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
hboxLayout = new QHBoxLayout();
#ifndef Q_OS_MAC
hboxLayout->setSpacing(6);
@@ -52,16 +52,16 @@ public:
#ifndef Q_OS_MAC
hboxLayout->setContentsMargins(0, 0, 0, 0);
#endif
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
textEdit = new QTextEdit(ChatDialog);
- textEdit->setObjectName(QStringLiteral("textEdit"));
+ textEdit->setObjectName(QString::fromUtf8("textEdit"));
textEdit->setFocusPolicy(Qt::NoFocus);
textEdit->setReadOnly(true);
hboxLayout->addWidget(textEdit);
listWidget = new QListWidget(ChatDialog);
- listWidget->setObjectName(QStringLiteral("listWidget"));
+ listWidget->setObjectName(QString::fromUtf8("listWidget"));
listWidget->setMaximumSize(QSize(180, 16777215));
listWidget->setFocusPolicy(Qt::NoFocus);
@@ -75,14 +75,14 @@ public:
hboxLayout1->setSpacing(6);
#endif
hboxLayout1->setContentsMargins(0, 0, 0, 0);
- hboxLayout1->setObjectName(QStringLiteral("hboxLayout1"));
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
label = new QLabel(ChatDialog);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
hboxLayout1->addWidget(label);
lineEdit = new QLineEdit(ChatDialog);
- lineEdit->setObjectName(QStringLiteral("lineEdit"));
+ lineEdit->setObjectName(QString::fromUtf8("lineEdit"));
hboxLayout1->addWidget(lineEdit);
diff --git a/tests/auto/tools/uic/baseline/chatmainwindow.ui.h b/tests/auto/tools/uic/baseline/chatmainwindow.ui.h
index 921eb376de..8d4ccd53ae 100644
--- a/tests/auto/tools/uic/baseline/chatmainwindow.ui.h
+++ b/tests/auto/tools/uic/baseline/chatmainwindow.ui.h
@@ -48,16 +48,16 @@ public:
void setupUi(QMainWindow *ChatMainWindow)
{
if (ChatMainWindow->objectName().isEmpty())
- ChatMainWindow->setObjectName(QStringLiteral("ChatMainWindow"));
+ ChatMainWindow->setObjectName(QString::fromUtf8("ChatMainWindow"));
ChatMainWindow->resize(800, 600);
actionQuit = new QAction(ChatMainWindow);
- actionQuit->setObjectName(QStringLiteral("actionQuit"));
+ actionQuit->setObjectName(QString::fromUtf8("actionQuit"));
actionAboutQt = new QAction(ChatMainWindow);
- actionAboutQt->setObjectName(QStringLiteral("actionAboutQt"));
+ actionAboutQt->setObjectName(QString::fromUtf8("actionAboutQt"));
actionChangeNickname = new QAction(ChatMainWindow);
- actionChangeNickname->setObjectName(QStringLiteral("actionChangeNickname"));
+ actionChangeNickname->setObjectName(QString::fromUtf8("actionChangeNickname"));
centralwidget = new QWidget(ChatMainWindow);
- centralwidget->setObjectName(QStringLiteral("centralwidget"));
+ centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
hboxLayout = new QHBoxLayout(centralwidget);
#ifndef Q_OS_MAC
hboxLayout->setSpacing(6);
@@ -65,7 +65,7 @@ public:
#ifndef Q_OS_MAC
hboxLayout->setContentsMargins(9, 9, 9, 9);
#endif
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
vboxLayout = new QVBoxLayout();
#ifndef Q_OS_MAC
vboxLayout->setSpacing(6);
@@ -73,9 +73,9 @@ public:
#ifndef Q_OS_MAC
vboxLayout->setContentsMargins(0, 0, 0, 0);
#endif
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
chatHistory = new QTextBrowser(centralwidget);
- chatHistory->setObjectName(QStringLiteral("chatHistory"));
+ chatHistory->setObjectName(QString::fromUtf8("chatHistory"));
chatHistory->setAcceptDrops(false);
chatHistory->setAcceptRichText(true);
@@ -86,19 +86,19 @@ public:
hboxLayout1->setSpacing(6);
#endif
hboxLayout1->setContentsMargins(0, 0, 0, 0);
- hboxLayout1->setObjectName(QStringLiteral("hboxLayout1"));
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
label = new QLabel(centralwidget);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
hboxLayout1->addWidget(label);
messageLineEdit = new QLineEdit(centralwidget);
- messageLineEdit->setObjectName(QStringLiteral("messageLineEdit"));
+ messageLineEdit->setObjectName(QString::fromUtf8("messageLineEdit"));
hboxLayout1->addWidget(messageLineEdit);
sendButton = new QPushButton(centralwidget);
- sendButton->setObjectName(QStringLiteral("sendButton"));
+ sendButton->setObjectName(QString::fromUtf8("sendButton"));
QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(1), static_cast<QSizePolicy::Policy>(0));
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -115,15 +115,15 @@ public:
ChatMainWindow->setCentralWidget(centralwidget);
menubar = new QMenuBar(ChatMainWindow);
- menubar->setObjectName(QStringLiteral("menubar"));
+ menubar->setObjectName(QString::fromUtf8("menubar"));
menubar->setGeometry(QRect(0, 0, 800, 31));
menuQuit = new QMenu(menubar);
- menuQuit->setObjectName(QStringLiteral("menuQuit"));
+ menuQuit->setObjectName(QString::fromUtf8("menuQuit"));
menuFile = new QMenu(menubar);
- menuFile->setObjectName(QStringLiteral("menuFile"));
+ menuFile->setObjectName(QString::fromUtf8("menuFile"));
ChatMainWindow->setMenuBar(menubar);
statusbar = new QStatusBar(ChatMainWindow);
- statusbar->setObjectName(QStringLiteral("statusbar"));
+ statusbar->setObjectName(QString::fromUtf8("statusbar"));
ChatMainWindow->setStatusBar(statusbar);
#ifndef QT_NO_SHORTCUT
label->setBuddy(messageLineEdit);
diff --git a/tests/auto/tools/uic/baseline/chatsetnickname.ui.h b/tests/auto/tools/uic/baseline/chatsetnickname.ui.h
index 6aaa47f84e..c73dfb2c6e 100644
--- a/tests/auto/tools/uic/baseline/chatsetnickname.ui.h
+++ b/tests/auto/tools/uic/baseline/chatsetnickname.ui.h
@@ -37,7 +37,7 @@ public:
void setupUi(QDialog *NicknameDialog)
{
if (NicknameDialog->objectName().isEmpty())
- NicknameDialog->setObjectName(QStringLiteral("NicknameDialog"));
+ NicknameDialog->setObjectName(QString::fromUtf8("NicknameDialog"));
NicknameDialog->resize(396, 105);
QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(1), static_cast<QSizePolicy::Policy>(1));
sizePolicy.setHorizontalStretch(0);
@@ -51,7 +51,7 @@ public:
#ifndef Q_OS_MAC
vboxLayout->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
vboxLayout1 = new QVBoxLayout();
#ifndef Q_OS_MAC
vboxLayout1->setSpacing(6);
@@ -59,16 +59,16 @@ public:
#ifndef Q_OS_MAC
vboxLayout1->setContentsMargins(0, 0, 0, 0);
#endif
- vboxLayout1->setObjectName(QStringLiteral("vboxLayout1"));
+ vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
label = new QLabel(NicknameDialog);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
sizePolicy.setHeightForWidth(label->sizePolicy().hasHeightForWidth());
label->setSizePolicy(sizePolicy);
vboxLayout1->addWidget(label);
nickname = new QLineEdit(NicknameDialog);
- nickname->setObjectName(QStringLiteral("nickname"));
+ nickname->setObjectName(QString::fromUtf8("nickname"));
vboxLayout1->addWidget(nickname);
@@ -80,18 +80,18 @@ public:
hboxLayout->setSpacing(6);
#endif
hboxLayout->setContentsMargins(0, 0, 0, 0);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
spacerItem = new QSpacerItem(131, 31, QSizePolicy::Expanding, QSizePolicy::Minimum);
hboxLayout->addItem(spacerItem);
okButton = new QPushButton(NicknameDialog);
- okButton->setObjectName(QStringLiteral("okButton"));
+ okButton->setObjectName(QString::fromUtf8("okButton"));
hboxLayout->addWidget(okButton);
cancelButton = new QPushButton(NicknameDialog);
- cancelButton->setObjectName(QStringLiteral("cancelButton"));
+ cancelButton->setObjectName(QString::fromUtf8("cancelButton"));
hboxLayout->addWidget(cancelButton);
diff --git a/tests/auto/tools/uic/baseline/config.ui.h b/tests/auto/tools/uic/baseline/config.ui.h
index 7948f6b4ba..8287e0b1ac 100644
--- a/tests/auto/tools/uic/baseline/config.ui.h
+++ b/tests/auto/tools/uic/baseline/config.ui.h
@@ -118,20 +118,20 @@ public:
void setupUi(QDialog *Config)
{
if (Config->objectName().isEmpty())
- Config->setObjectName(QStringLiteral("Config"));
+ Config->setObjectName(QString::fromUtf8("Config"));
Config->resize(600, 650);
Config->setSizeGripEnabled(true);
vboxLayout = new QVBoxLayout(Config);
vboxLayout->setSpacing(6);
vboxLayout->setContentsMargins(11, 11, 11, 11);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
vboxLayout->setContentsMargins(8, 8, 8, 8);
hboxLayout = new QHBoxLayout();
hboxLayout->setSpacing(6);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
hboxLayout->setContentsMargins(0, 0, 0, 0);
ButtonGroup1 = new QGroupBox(Config);
- ButtonGroup1->setObjectName(QStringLiteral("ButtonGroup1"));
+ ButtonGroup1->setObjectName(QString::fromUtf8("ButtonGroup1"));
QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -140,44 +140,44 @@ public:
vboxLayout1 = new QVBoxLayout(ButtonGroup1);
vboxLayout1->setSpacing(6);
vboxLayout1->setContentsMargins(11, 11, 11, 11);
- vboxLayout1->setObjectName(QStringLiteral("vboxLayout1"));
+ vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
vboxLayout1->setContentsMargins(11, 11, 11, 11);
size_176_220 = new QRadioButton(ButtonGroup1);
- size_176_220->setObjectName(QStringLiteral("size_176_220"));
+ size_176_220->setObjectName(QString::fromUtf8("size_176_220"));
vboxLayout1->addWidget(size_176_220);
size_240_320 = new QRadioButton(ButtonGroup1);
- size_240_320->setObjectName(QStringLiteral("size_240_320"));
+ size_240_320->setObjectName(QString::fromUtf8("size_240_320"));
vboxLayout1->addWidget(size_240_320);
size_320_240 = new QRadioButton(ButtonGroup1);
- size_320_240->setObjectName(QStringLiteral("size_320_240"));
+ size_320_240->setObjectName(QString::fromUtf8("size_320_240"));
vboxLayout1->addWidget(size_320_240);
size_640_480 = new QRadioButton(ButtonGroup1);
- size_640_480->setObjectName(QStringLiteral("size_640_480"));
+ size_640_480->setObjectName(QString::fromUtf8("size_640_480"));
vboxLayout1->addWidget(size_640_480);
size_800_600 = new QRadioButton(ButtonGroup1);
- size_800_600->setObjectName(QStringLiteral("size_800_600"));
+ size_800_600->setObjectName(QString::fromUtf8("size_800_600"));
vboxLayout1->addWidget(size_800_600);
size_1024_768 = new QRadioButton(ButtonGroup1);
- size_1024_768->setObjectName(QStringLiteral("size_1024_768"));
+ size_1024_768->setObjectName(QString::fromUtf8("size_1024_768"));
vboxLayout1->addWidget(size_1024_768);
hboxLayout1 = new QHBoxLayout();
hboxLayout1->setSpacing(6);
- hboxLayout1->setObjectName(QStringLiteral("hboxLayout1"));
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
hboxLayout1->setContentsMargins(0, 0, 0, 0);
size_custom = new QRadioButton(ButtonGroup1);
- size_custom->setObjectName(QStringLiteral("size_custom"));
+ size_custom->setObjectName(QString::fromUtf8("size_custom"));
QSizePolicy sizePolicy1(QSizePolicy::Fixed, QSizePolicy::Fixed);
sizePolicy1.setHorizontalStretch(0);
sizePolicy1.setVerticalStretch(0);
@@ -187,7 +187,7 @@ public:
hboxLayout1->addWidget(size_custom);
size_width = new QSpinBox(ButtonGroup1);
- size_width->setObjectName(QStringLiteral("size_width"));
+ size_width->setObjectName(QString::fromUtf8("size_width"));
size_width->setMinimum(1);
size_width->setMaximum(1280);
size_width->setSingleStep(16);
@@ -196,7 +196,7 @@ public:
hboxLayout1->addWidget(size_width);
size_height = new QSpinBox(ButtonGroup1);
- size_height->setObjectName(QStringLiteral("size_height"));
+ size_height->setObjectName(QString::fromUtf8("size_height"));
size_height->setMinimum(1);
size_height->setMaximum(1024);
size_height->setSingleStep(16);
@@ -211,59 +211,59 @@ public:
hboxLayout->addWidget(ButtonGroup1);
ButtonGroup2 = new QGroupBox(Config);
- ButtonGroup2->setObjectName(QStringLiteral("ButtonGroup2"));
+ ButtonGroup2->setObjectName(QString::fromUtf8("ButtonGroup2"));
vboxLayout2 = new QVBoxLayout(ButtonGroup2);
vboxLayout2->setSpacing(6);
vboxLayout2->setContentsMargins(11, 11, 11, 11);
- vboxLayout2->setObjectName(QStringLiteral("vboxLayout2"));
+ vboxLayout2->setObjectName(QString::fromUtf8("vboxLayout2"));
vboxLayout2->setContentsMargins(11, 11, 11, 11);
depth_1 = new QRadioButton(ButtonGroup2);
- depth_1->setObjectName(QStringLiteral("depth_1"));
+ depth_1->setObjectName(QString::fromUtf8("depth_1"));
vboxLayout2->addWidget(depth_1);
depth_4gray = new QRadioButton(ButtonGroup2);
- depth_4gray->setObjectName(QStringLiteral("depth_4gray"));
+ depth_4gray->setObjectName(QString::fromUtf8("depth_4gray"));
vboxLayout2->addWidget(depth_4gray);
depth_8 = new QRadioButton(ButtonGroup2);
- depth_8->setObjectName(QStringLiteral("depth_8"));
+ depth_8->setObjectName(QString::fromUtf8("depth_8"));
vboxLayout2->addWidget(depth_8);
depth_12 = new QRadioButton(ButtonGroup2);
- depth_12->setObjectName(QStringLiteral("depth_12"));
+ depth_12->setObjectName(QString::fromUtf8("depth_12"));
vboxLayout2->addWidget(depth_12);
depth_15 = new QRadioButton(ButtonGroup2);
- depth_15->setObjectName(QStringLiteral("depth_15"));
+ depth_15->setObjectName(QString::fromUtf8("depth_15"));
vboxLayout2->addWidget(depth_15);
depth_16 = new QRadioButton(ButtonGroup2);
- depth_16->setObjectName(QStringLiteral("depth_16"));
+ depth_16->setObjectName(QString::fromUtf8("depth_16"));
vboxLayout2->addWidget(depth_16);
depth_18 = new QRadioButton(ButtonGroup2);
- depth_18->setObjectName(QStringLiteral("depth_18"));
+ depth_18->setObjectName(QString::fromUtf8("depth_18"));
vboxLayout2->addWidget(depth_18);
depth_24 = new QRadioButton(ButtonGroup2);
- depth_24->setObjectName(QStringLiteral("depth_24"));
+ depth_24->setObjectName(QString::fromUtf8("depth_24"));
vboxLayout2->addWidget(depth_24);
depth_32 = new QRadioButton(ButtonGroup2);
- depth_32->setObjectName(QStringLiteral("depth_32"));
+ depth_32->setObjectName(QString::fromUtf8("depth_32"));
vboxLayout2->addWidget(depth_32);
depth_32_argb = new QRadioButton(ButtonGroup2);
- depth_32_argb->setObjectName(QStringLiteral("depth_32_argb"));
+ depth_32_argb->setObjectName(QString::fromUtf8("depth_32_argb"));
vboxLayout2->addWidget(depth_32_argb);
@@ -275,16 +275,16 @@ public:
hboxLayout2 = new QHBoxLayout();
hboxLayout2->setSpacing(6);
- hboxLayout2->setObjectName(QStringLiteral("hboxLayout2"));
+ hboxLayout2->setObjectName(QString::fromUtf8("hboxLayout2"));
hboxLayout2->setContentsMargins(0, 0, 0, 0);
TextLabel1_3 = new QLabel(Config);
- TextLabel1_3->setObjectName(QStringLiteral("TextLabel1_3"));
+ TextLabel1_3->setObjectName(QString::fromUtf8("TextLabel1_3"));
hboxLayout2->addWidget(TextLabel1_3);
skin = new QComboBox(Config);
skin->addItem(QString());
- skin->setObjectName(QStringLiteral("skin"));
+ skin->setObjectName(QString::fromUtf8("skin"));
QSizePolicy sizePolicy2(QSizePolicy::Expanding, QSizePolicy::Fixed);
sizePolicy2.setHorizontalStretch(0);
sizePolicy2.setVerticalStretch(0);
@@ -297,12 +297,12 @@ public:
vboxLayout->addLayout(hboxLayout2);
touchScreen = new QCheckBox(Config);
- touchScreen->setObjectName(QStringLiteral("touchScreen"));
+ touchScreen->setObjectName(QString::fromUtf8("touchScreen"));
vboxLayout->addWidget(touchScreen);
lcdScreen = new QCheckBox(Config);
- lcdScreen->setObjectName(QStringLiteral("lcdScreen"));
+ lcdScreen->setObjectName(QString::fromUtf8("lcdScreen"));
vboxLayout->addWidget(lcdScreen);
@@ -311,7 +311,7 @@ public:
vboxLayout->addItem(spacerItem);
TextLabel1 = new QLabel(Config);
- TextLabel1->setObjectName(QStringLiteral("TextLabel1"));
+ TextLabel1->setObjectName(QString::fromUtf8("TextLabel1"));
sizePolicy.setHeightForWidth(TextLabel1->sizePolicy().hasHeightForWidth());
TextLabel1->setSizePolicy(sizePolicy);
TextLabel1->setWordWrap(true);
@@ -319,21 +319,21 @@ public:
vboxLayout->addWidget(TextLabel1);
GroupBox1 = new QGroupBox(Config);
- GroupBox1->setObjectName(QStringLiteral("GroupBox1"));
+ GroupBox1->setObjectName(QString::fromUtf8("GroupBox1"));
gridLayout = new QGridLayout(GroupBox1);
gridLayout->setSpacing(6);
gridLayout->setContentsMargins(11, 11, 11, 11);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
gridLayout->setHorizontalSpacing(6);
gridLayout->setVerticalSpacing(6);
gridLayout->setContentsMargins(11, 11, 11, 11);
TextLabel3 = new QLabel(GroupBox1);
- TextLabel3->setObjectName(QStringLiteral("TextLabel3"));
+ TextLabel3->setObjectName(QString::fromUtf8("TextLabel3"));
gridLayout->addWidget(TextLabel3, 6, 0, 1, 1);
bslider = new QSlider(GroupBox1);
- bslider->setObjectName(QStringLiteral("bslider"));
+ bslider->setObjectName(QString::fromUtf8("bslider"));
QPalette palette;
QBrush brush(QColor(128, 128, 128, 255));
brush.setStyle(Qt::SolidPattern);
@@ -416,17 +416,17 @@ public:
gridLayout->addWidget(bslider, 6, 1, 1, 1);
blabel = new QLabel(GroupBox1);
- blabel->setObjectName(QStringLiteral("blabel"));
+ blabel->setObjectName(QString::fromUtf8("blabel"));
gridLayout->addWidget(blabel, 6, 2, 1, 1);
TextLabel2 = new QLabel(GroupBox1);
- TextLabel2->setObjectName(QStringLiteral("TextLabel2"));
+ TextLabel2->setObjectName(QString::fromUtf8("TextLabel2"));
gridLayout->addWidget(TextLabel2, 4, 0, 1, 1);
gslider = new QSlider(GroupBox1);
- gslider->setObjectName(QStringLiteral("gslider"));
+ gslider->setObjectName(QString::fromUtf8("gslider"));
QPalette palette1;
palette1.setBrush(QPalette::Active, QPalette::WindowText, brush);
QBrush brush11(QColor(0, 255, 0, 255));
@@ -497,22 +497,22 @@ public:
gridLayout->addWidget(gslider, 4, 1, 1, 1);
glabel = new QLabel(GroupBox1);
- glabel->setObjectName(QStringLiteral("glabel"));
+ glabel->setObjectName(QString::fromUtf8("glabel"));
gridLayout->addWidget(glabel, 4, 2, 1, 1);
TextLabel7 = new QLabel(GroupBox1);
- TextLabel7->setObjectName(QStringLiteral("TextLabel7"));
+ TextLabel7->setObjectName(QString::fromUtf8("TextLabel7"));
gridLayout->addWidget(TextLabel7, 0, 0, 1, 1);
TextLabel8 = new QLabel(GroupBox1);
- TextLabel8->setObjectName(QStringLiteral("TextLabel8"));
+ TextLabel8->setObjectName(QString::fromUtf8("TextLabel8"));
gridLayout->addWidget(TextLabel8, 0, 2, 1, 1);
gammaslider = new QSlider(GroupBox1);
- gammaslider->setObjectName(QStringLiteral("gammaslider"));
+ gammaslider->setObjectName(QString::fromUtf8("gammaslider"));
QPalette palette2;
palette2.setBrush(QPalette::Active, QPalette::WindowText, brush);
palette2.setBrush(QPalette::Active, QPalette::Button, brush7);
@@ -577,17 +577,17 @@ public:
gridLayout->addWidget(gammaslider, 0, 1, 1, 1);
TextLabel1_2 = new QLabel(GroupBox1);
- TextLabel1_2->setObjectName(QStringLiteral("TextLabel1_2"));
+ TextLabel1_2->setObjectName(QString::fromUtf8("TextLabel1_2"));
gridLayout->addWidget(TextLabel1_2, 2, 0, 1, 1);
rlabel = new QLabel(GroupBox1);
- rlabel->setObjectName(QStringLiteral("rlabel"));
+ rlabel->setObjectName(QString::fromUtf8("rlabel"));
gridLayout->addWidget(rlabel, 2, 2, 1, 1);
rslider = new QSlider(GroupBox1);
- rslider->setObjectName(QStringLiteral("rslider"));
+ rslider->setObjectName(QString::fromUtf8("rslider"));
QPalette palette3;
palette3.setBrush(QPalette::Active, QPalette::WindowText, brush);
QBrush brush18(QColor(255, 0, 0, 255));
@@ -658,12 +658,12 @@ public:
gridLayout->addWidget(rslider, 2, 1, 1, 1);
PushButton3 = new QPushButton(GroupBox1);
- PushButton3->setObjectName(QStringLiteral("PushButton3"));
+ PushButton3->setObjectName(QString::fromUtf8("PushButton3"));
gridLayout->addWidget(PushButton3, 8, 0, 1, 3);
MyCustomWidget1 = new GammaView(GroupBox1);
- MyCustomWidget1->setObjectName(QStringLiteral("MyCustomWidget1"));
+ MyCustomWidget1->setObjectName(QString::fromUtf8("MyCustomWidget1"));
gridLayout->addWidget(MyCustomWidget1, 0, 3, 9, 1);
@@ -672,20 +672,20 @@ public:
hboxLayout3 = new QHBoxLayout();
hboxLayout3->setSpacing(6);
- hboxLayout3->setObjectName(QStringLiteral("hboxLayout3"));
+ hboxLayout3->setObjectName(QString::fromUtf8("hboxLayout3"));
hboxLayout3->setContentsMargins(0, 0, 0, 0);
spacerItem1 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
hboxLayout3->addItem(spacerItem1);
buttonOk = new QPushButton(Config);
- buttonOk->setObjectName(QStringLiteral("buttonOk"));
+ buttonOk->setObjectName(QString::fromUtf8("buttonOk"));
buttonOk->setAutoDefault(true);
hboxLayout3->addWidget(buttonOk);
buttonCancel = new QPushButton(Config);
- buttonCancel->setObjectName(QStringLiteral("buttonCancel"));
+ buttonCancel->setObjectName(QString::fromUtf8("buttonCancel"));
buttonCancel->setAutoDefault(true);
hboxLayout3->addWidget(buttonCancel);
diff --git a/tests/auto/tools/uic/baseline/connectdialog.ui.h b/tests/auto/tools/uic/baseline/connectdialog.ui.h
index 935f8a21a1..a470a6705d 100644
--- a/tests/auto/tools/uic/baseline/connectdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/connectdialog.ui.h
@@ -46,24 +46,24 @@ public:
void setupUi(QDialog *ConnectDialog)
{
if (ConnectDialog->objectName().isEmpty())
- ConnectDialog->setObjectName(QStringLiteral("ConnectDialog"));
+ ConnectDialog->setObjectName(QString::fromUtf8("ConnectDialog"));
ConnectDialog->resize(585, 361);
gridLayout = new QGridLayout(ConnectDialog);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
signalGroupBox = new QGroupBox(ConnectDialog);
- signalGroupBox->setObjectName(QStringLiteral("signalGroupBox"));
+ signalGroupBox->setObjectName(QString::fromUtf8("signalGroupBox"));
vboxLayout = new QVBoxLayout(signalGroupBox);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
signalList = new QListWidget(signalGroupBox);
- signalList->setObjectName(QStringLiteral("signalList"));
+ signalList->setObjectName(QString::fromUtf8("signalList"));
signalList->setTextElideMode(Qt::ElideMiddle);
vboxLayout->addWidget(signalList);
hboxLayout = new QHBoxLayout();
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
editSignalsButton = new QToolButton(signalGroupBox);
- editSignalsButton->setObjectName(QStringLiteral("editSignalsButton"));
+ editSignalsButton->setObjectName(QString::fromUtf8("editSignalsButton"));
hboxLayout->addWidget(editSignalsButton);
@@ -78,19 +78,19 @@ public:
gridLayout->addWidget(signalGroupBox, 0, 0, 1, 2);
slotGroupBox = new QGroupBox(ConnectDialog);
- slotGroupBox->setObjectName(QStringLiteral("slotGroupBox"));
+ slotGroupBox->setObjectName(QString::fromUtf8("slotGroupBox"));
vboxLayout1 = new QVBoxLayout(slotGroupBox);
- vboxLayout1->setObjectName(QStringLiteral("vboxLayout1"));
+ vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
slotList = new QListWidget(slotGroupBox);
- slotList->setObjectName(QStringLiteral("slotList"));
+ slotList->setObjectName(QString::fromUtf8("slotList"));
slotList->setTextElideMode(Qt::ElideMiddle);
vboxLayout1->addWidget(slotList);
hboxLayout1 = new QHBoxLayout();
- hboxLayout1->setObjectName(QStringLiteral("hboxLayout1"));
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
editSlotsButton = new QToolButton(slotGroupBox);
- editSlotsButton->setObjectName(QStringLiteral("editSlotsButton"));
+ editSlotsButton->setObjectName(QString::fromUtf8("editSlotsButton"));
hboxLayout1->addWidget(editSlotsButton);
@@ -105,12 +105,12 @@ public:
gridLayout->addWidget(slotGroupBox, 0, 2, 1, 1);
showAllCheckBox = new QCheckBox(ConnectDialog);
- showAllCheckBox->setObjectName(QStringLiteral("showAllCheckBox"));
+ showAllCheckBox->setObjectName(QString::fromUtf8("showAllCheckBox"));
gridLayout->addWidget(showAllCheckBox, 1, 0, 1, 1);
buttonBox = new QDialogButtonBox(ConnectDialog);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok);
diff --git a/tests/auto/tools/uic/baseline/controller.ui.h b/tests/auto/tools/uic/baseline/controller.ui.h
index e3382e2c17..72b0956472 100644
--- a/tests/auto/tools/uic/baseline/controller.ui.h
+++ b/tests/auto/tools/uic/baseline/controller.ui.h
@@ -31,7 +31,7 @@ public:
void setupUi(QWidget *Controller)
{
if (Controller->objectName().isEmpty())
- Controller->setObjectName(QStringLiteral("Controller"));
+ Controller->setObjectName(QString::fromUtf8("Controller"));
Controller->resize(255, 111);
gridLayout = new QGridLayout(Controller);
#ifndef Q_OS_MAC
@@ -40,30 +40,30 @@ public:
#ifndef Q_OS_MAC
gridLayout->setContentsMargins(9, 9, 9, 9);
#endif
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
label = new QLabel(Controller);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
label->setAlignment(Qt::AlignCenter);
gridLayout->addWidget(label, 1, 1, 1, 1);
decelerate = new QPushButton(Controller);
- decelerate->setObjectName(QStringLiteral("decelerate"));
+ decelerate->setObjectName(QString::fromUtf8("decelerate"));
gridLayout->addWidget(decelerate, 2, 1, 1, 1);
accelerate = new QPushButton(Controller);
- accelerate->setObjectName(QStringLiteral("accelerate"));
+ accelerate->setObjectName(QString::fromUtf8("accelerate"));
gridLayout->addWidget(accelerate, 0, 1, 1, 1);
right = new QPushButton(Controller);
- right->setObjectName(QStringLiteral("right"));
+ right->setObjectName(QString::fromUtf8("right"));
gridLayout->addWidget(right, 1, 2, 1, 1);
left = new QPushButton(Controller);
- left->setObjectName(QStringLiteral("left"));
+ left->setObjectName(QString::fromUtf8("left"));
gridLayout->addWidget(left, 1, 0, 1, 1);
diff --git a/tests/auto/tools/uic/baseline/cookies.ui.h b/tests/auto/tools/uic/baseline/cookies.ui.h
index 2702fb489f..144c306874 100644
--- a/tests/auto/tools/uic/baseline/cookies.ui.h
+++ b/tests/auto/tools/uic/baseline/cookies.ui.h
@@ -39,33 +39,33 @@ public:
void setupUi(QDialog *CookiesDialog)
{
if (CookiesDialog->objectName().isEmpty())
- CookiesDialog->setObjectName(QStringLiteral("CookiesDialog"));
+ CookiesDialog->setObjectName(QString::fromUtf8("CookiesDialog"));
CookiesDialog->resize(550, 370);
gridLayout = new QGridLayout(CookiesDialog);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
spacerItem = new QSpacerItem(252, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
gridLayout->addItem(spacerItem, 0, 0, 1, 1);
search = new SearchLineEdit(CookiesDialog);
- search->setObjectName(QStringLiteral("search"));
+ search->setObjectName(QString::fromUtf8("search"));
gridLayout->addWidget(search, 0, 1, 1, 1);
cookiesTable = new EditTableView(CookiesDialog);
- cookiesTable->setObjectName(QStringLiteral("cookiesTable"));
+ cookiesTable->setObjectName(QString::fromUtf8("cookiesTable"));
gridLayout->addWidget(cookiesTable, 1, 0, 1, 2);
hboxLayout = new QHBoxLayout();
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
removeButton = new QPushButton(CookiesDialog);
- removeButton->setObjectName(QStringLiteral("removeButton"));
+ removeButton->setObjectName(QString::fromUtf8("removeButton"));
hboxLayout->addWidget(removeButton);
removeAllButton = new QPushButton(CookiesDialog);
- removeAllButton->setObjectName(QStringLiteral("removeAllButton"));
+ removeAllButton->setObjectName(QString::fromUtf8("removeAllButton"));
hboxLayout->addWidget(removeAllButton);
@@ -74,7 +74,7 @@ public:
hboxLayout->addItem(spacerItem1);
buttonBox = new QDialogButtonBox(CookiesDialog);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setStandardButtons(QDialogButtonBox::Ok);
hboxLayout->addWidget(buttonBox);
diff --git a/tests/auto/tools/uic/baseline/cookiesexceptions.ui.h b/tests/auto/tools/uic/baseline/cookiesexceptions.ui.h
index eaa39e3e78..a3bf7a449e 100644
--- a/tests/auto/tools/uic/baseline/cookiesexceptions.ui.h
+++ b/tests/auto/tools/uic/baseline/cookiesexceptions.ui.h
@@ -54,23 +54,23 @@ public:
void setupUi(QDialog *CookiesExceptionsDialog)
{
if (CookiesExceptionsDialog->objectName().isEmpty())
- CookiesExceptionsDialog->setObjectName(QStringLiteral("CookiesExceptionsDialog"));
+ CookiesExceptionsDialog->setObjectName(QString::fromUtf8("CookiesExceptionsDialog"));
CookiesExceptionsDialog->resize(466, 446);
vboxLayout = new QVBoxLayout(CookiesExceptionsDialog);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
newExceptionGroupBox = new QGroupBox(CookiesExceptionsDialog);
- newExceptionGroupBox->setObjectName(QStringLiteral("newExceptionGroupBox"));
+ newExceptionGroupBox->setObjectName(QString::fromUtf8("newExceptionGroupBox"));
gridLayout = new QGridLayout(newExceptionGroupBox);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
hboxLayout = new QHBoxLayout();
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
label = new QLabel(newExceptionGroupBox);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
hboxLayout->addWidget(label);
domainLineEdit = new QLineEdit(newExceptionGroupBox);
- domainLineEdit->setObjectName(QStringLiteral("domainLineEdit"));
+ domainLineEdit->setObjectName(QString::fromUtf8("domainLineEdit"));
hboxLayout->addWidget(domainLineEdit);
@@ -78,25 +78,25 @@ public:
gridLayout->addLayout(hboxLayout, 0, 0, 1, 1);
hboxLayout1 = new QHBoxLayout();
- hboxLayout1->setObjectName(QStringLiteral("hboxLayout1"));
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
spacerItem = new QSpacerItem(81, 25, QSizePolicy::Expanding, QSizePolicy::Minimum);
hboxLayout1->addItem(spacerItem);
blockButton = new QPushButton(newExceptionGroupBox);
- blockButton->setObjectName(QStringLiteral("blockButton"));
+ blockButton->setObjectName(QString::fromUtf8("blockButton"));
blockButton->setEnabled(false);
hboxLayout1->addWidget(blockButton);
allowForSessionButton = new QPushButton(newExceptionGroupBox);
- allowForSessionButton->setObjectName(QStringLiteral("allowForSessionButton"));
+ allowForSessionButton->setObjectName(QString::fromUtf8("allowForSessionButton"));
allowForSessionButton->setEnabled(false);
hboxLayout1->addWidget(allowForSessionButton);
allowButton = new QPushButton(newExceptionGroupBox);
- allowButton->setObjectName(QStringLiteral("allowButton"));
+ allowButton->setObjectName(QString::fromUtf8("allowButton"));
allowButton->setEnabled(false);
hboxLayout1->addWidget(allowButton);
@@ -108,30 +108,30 @@ public:
vboxLayout->addWidget(newExceptionGroupBox);
ExceptionsGroupBox = new QGroupBox(CookiesExceptionsDialog);
- ExceptionsGroupBox->setObjectName(QStringLiteral("ExceptionsGroupBox"));
+ ExceptionsGroupBox->setObjectName(QString::fromUtf8("ExceptionsGroupBox"));
gridLayout1 = new QGridLayout(ExceptionsGroupBox);
- gridLayout1->setObjectName(QStringLiteral("gridLayout1"));
+ gridLayout1->setObjectName(QString::fromUtf8("gridLayout1"));
spacerItem1 = new QSpacerItem(252, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
gridLayout1->addItem(spacerItem1, 0, 0, 1, 3);
search = new SearchLineEdit(ExceptionsGroupBox);
- search->setObjectName(QStringLiteral("search"));
+ search->setObjectName(QString::fromUtf8("search"));
gridLayout1->addWidget(search, 0, 3, 1, 1);
exceptionTable = new EditTableView(ExceptionsGroupBox);
- exceptionTable->setObjectName(QStringLiteral("exceptionTable"));
+ exceptionTable->setObjectName(QString::fromUtf8("exceptionTable"));
gridLayout1->addWidget(exceptionTable, 1, 0, 1, 4);
removeButton = new QPushButton(ExceptionsGroupBox);
- removeButton->setObjectName(QStringLiteral("removeButton"));
+ removeButton->setObjectName(QString::fromUtf8("removeButton"));
gridLayout1->addWidget(removeButton, 2, 0, 1, 1);
removeAllButton = new QPushButton(ExceptionsGroupBox);
- removeAllButton->setObjectName(QStringLiteral("removeAllButton"));
+ removeAllButton->setObjectName(QString::fromUtf8("removeAllButton"));
gridLayout1->addWidget(removeAllButton, 2, 1, 1, 1);
@@ -143,7 +143,7 @@ public:
vboxLayout->addWidget(ExceptionsGroupBox);
buttonBox = new QDialogButtonBox(CookiesExceptionsDialog);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Ok);
diff --git a/tests/auto/tools/uic/baseline/default.ui.h b/tests/auto/tools/uic/baseline/default.ui.h
index 4fae8e7130..fafff9d728 100644
--- a/tests/auto/tools/uic/baseline/default.ui.h
+++ b/tests/auto/tools/uic/baseline/default.ui.h
@@ -63,18 +63,18 @@ public:
void setupUi(QMainWindow *MainWindow)
{
if (MainWindow->objectName().isEmpty())
- MainWindow->setObjectName(QStringLiteral("MainWindow"));
+ MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
MainWindow->resize(388, 413);
exitAction = new QAction(MainWindow);
- exitAction->setObjectName(QStringLiteral("exitAction"));
+ exitAction->setObjectName(QString::fromUtf8("exitAction"));
aboutQtAction = new QAction(MainWindow);
- aboutQtAction->setObjectName(QStringLiteral("aboutQtAction"));
+ aboutQtAction->setObjectName(QString::fromUtf8("aboutQtAction"));
editStyleAction = new QAction(MainWindow);
- editStyleAction->setObjectName(QStringLiteral("editStyleAction"));
+ editStyleAction->setObjectName(QString::fromUtf8("editStyleAction"));
aboutAction = new QAction(MainWindow);
- aboutAction->setObjectName(QStringLiteral("aboutAction"));
+ aboutAction->setObjectName(QString::fromUtf8("aboutAction"));
centralwidget = new QWidget(MainWindow);
- centralwidget->setObjectName(QStringLiteral("centralwidget"));
+ centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
gridLayout = new QGridLayout(centralwidget);
#ifndef Q_OS_MAC
gridLayout->setSpacing(6);
@@ -82,9 +82,9 @@ public:
#ifndef Q_OS_MAC
gridLayout->setContentsMargins(9, 9, 9, 9);
#endif
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
nameLabel = new QLabel(centralwidget);
- nameLabel->setObjectName(QStringLiteral("nameLabel"));
+ nameLabel->setObjectName(QString::fromUtf8("nameLabel"));
gridLayout->addWidget(nameLabel, 0, 0, 1, 1);
@@ -93,7 +93,7 @@ public:
nameCombo->addItem(QString());
nameCombo->addItem(QString());
nameCombo->addItem(QString());
- nameCombo->setObjectName(QStringLiteral("nameCombo"));
+ nameCombo->setObjectName(QString::fromUtf8("nameCombo"));
nameCombo->setEditable(true);
gridLayout->addWidget(nameCombo, 0, 1, 1, 3);
@@ -103,62 +103,62 @@ public:
gridLayout->addItem(spacerItem, 1, 3, 1, 1);
femaleRadioButton = new QRadioButton(centralwidget);
- femaleRadioButton->setObjectName(QStringLiteral("femaleRadioButton"));
+ femaleRadioButton->setObjectName(QString::fromUtf8("femaleRadioButton"));
gridLayout->addWidget(femaleRadioButton, 1, 2, 1, 1);
agreeCheckBox = new QCheckBox(centralwidget);
- agreeCheckBox->setObjectName(QStringLiteral("agreeCheckBox"));
+ agreeCheckBox->setObjectName(QString::fromUtf8("agreeCheckBox"));
gridLayout->addWidget(agreeCheckBox, 6, 0, 1, 4);
maleRadioButton = new QRadioButton(centralwidget);
- maleRadioButton->setObjectName(QStringLiteral("maleRadioButton"));
+ maleRadioButton->setObjectName(QString::fromUtf8("maleRadioButton"));
gridLayout->addWidget(maleRadioButton, 1, 1, 1, 1);
genderLabel = new QLabel(centralwidget);
- genderLabel->setObjectName(QStringLiteral("genderLabel"));
+ genderLabel->setObjectName(QString::fromUtf8("genderLabel"));
gridLayout->addWidget(genderLabel, 1, 0, 1, 1);
ageSpinBox = new QSpinBox(centralwidget);
- ageSpinBox->setObjectName(QStringLiteral("ageSpinBox"));
+ ageSpinBox->setObjectName(QString::fromUtf8("ageSpinBox"));
ageSpinBox->setMinimum(12);
ageSpinBox->setValue(22);
gridLayout->addWidget(ageSpinBox, 2, 1, 1, 3);
buttonBox = new QDialogButtonBox(centralwidget);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok);
gridLayout->addWidget(buttonBox, 7, 2, 1, 2);
ageLabel = new QLabel(centralwidget);
- ageLabel->setObjectName(QStringLiteral("ageLabel"));
+ ageLabel->setObjectName(QString::fromUtf8("ageLabel"));
gridLayout->addWidget(ageLabel, 2, 0, 1, 1);
passwordLabel = new QLabel(centralwidget);
- passwordLabel->setObjectName(QStringLiteral("passwordLabel"));
+ passwordLabel->setObjectName(QString::fromUtf8("passwordLabel"));
gridLayout->addWidget(passwordLabel, 3, 0, 1, 1);
passwordEdit = new QLineEdit(centralwidget);
- passwordEdit->setObjectName(QStringLiteral("passwordEdit"));
+ passwordEdit->setObjectName(QString::fromUtf8("passwordEdit"));
passwordEdit->setEchoMode(QLineEdit::Password);
gridLayout->addWidget(passwordEdit, 3, 1, 1, 3);
label = new QLabel(centralwidget);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
gridLayout->addWidget(label, 5, 0, 1, 1);
countryLabel = new QLabel(centralwidget);
- countryLabel->setObjectName(QStringLiteral("countryLabel"));
+ countryLabel->setObjectName(QString::fromUtf8("countryLabel"));
gridLayout->addWidget(countryLabel, 4, 0, 1, 1);
@@ -166,7 +166,7 @@ public:
new QListWidgetItem(professionList);
new QListWidgetItem(professionList);
new QListWidgetItem(professionList);
- professionList->setObjectName(QStringLiteral("professionList"));
+ professionList->setObjectName(QString::fromUtf8("professionList"));
gridLayout->addWidget(professionList, 5, 1, 1, 3);
@@ -176,21 +176,21 @@ public:
countryCombo->addItem(QString());
countryCombo->addItem(QString());
countryCombo->addItem(QString());
- countryCombo->setObjectName(QStringLiteral("countryCombo"));
+ countryCombo->setObjectName(QString::fromUtf8("countryCombo"));
gridLayout->addWidget(countryCombo, 4, 1, 1, 3);
MainWindow->setCentralWidget(centralwidget);
menubar = new QMenuBar(MainWindow);
- menubar->setObjectName(QStringLiteral("menubar"));
+ menubar->setObjectName(QString::fromUtf8("menubar"));
menubar->setGeometry(QRect(0, 0, 388, 21));
menu_File = new QMenu(menubar);
- menu_File->setObjectName(QStringLiteral("menu_File"));
+ menu_File->setObjectName(QString::fromUtf8("menu_File"));
menu_Help = new QMenu(menubar);
- menu_Help->setObjectName(QStringLiteral("menu_Help"));
+ menu_Help->setObjectName(QString::fromUtf8("menu_Help"));
MainWindow->setMenuBar(menubar);
statusbar = new QStatusBar(MainWindow);
- statusbar->setObjectName(QStringLiteral("statusbar"));
+ statusbar->setObjectName(QString::fromUtf8("statusbar"));
MainWindow->setStatusBar(statusbar);
#ifndef QT_NO_SHORTCUT
nameLabel->setBuddy(nameCombo);
diff --git a/tests/auto/tools/uic/baseline/dialog.ui.h b/tests/auto/tools/uic/baseline/dialog.ui.h
index 1aa41c2ac8..2a159312b9 100644
--- a/tests/auto/tools/uic/baseline/dialog.ui.h
+++ b/tests/auto/tools/uic/baseline/dialog.ui.h
@@ -29,24 +29,24 @@ public:
void setupUi(QDialog *Dialog)
{
if (Dialog->objectName().isEmpty())
- Dialog->setObjectName(QStringLiteral("Dialog"));
+ Dialog->setObjectName(QString::fromUtf8("Dialog"));
Dialog->resize(451, 322);
gridLayout = new QGridLayout(Dialog);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
loadFromFileButton = new QPushButton(Dialog);
- loadFromFileButton->setObjectName(QStringLiteral("loadFromFileButton"));
+ loadFromFileButton->setObjectName(QString::fromUtf8("loadFromFileButton"));
gridLayout->addWidget(loadFromFileButton, 0, 0, 1, 1);
label = new QLabel(Dialog);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
label->setAlignment(Qt::AlignCenter);
label->setWordWrap(true);
gridLayout->addWidget(label, 1, 0, 1, 1);
loadFromSharedMemoryButton = new QPushButton(Dialog);
- loadFromSharedMemoryButton->setObjectName(QStringLiteral("loadFromSharedMemoryButton"));
+ loadFromSharedMemoryButton->setObjectName(QString::fromUtf8("loadFromSharedMemoryButton"));
gridLayout->addWidget(loadFromSharedMemoryButton, 2, 0, 1, 1);
diff --git a/tests/auto/tools/uic/baseline/downloaditem.ui.h b/tests/auto/tools/uic/baseline/downloaditem.ui.h
index 2e854aa9ed..f0e8e88307 100644
--- a/tests/auto/tools/uic/baseline/downloaditem.ui.h
+++ b/tests/auto/tools/uic/baseline/downloaditem.ui.h
@@ -41,13 +41,13 @@ public:
void setupUi(QWidget *DownloadItem)
{
if (DownloadItem->objectName().isEmpty())
- DownloadItem->setObjectName(QStringLiteral("DownloadItem"));
+ DownloadItem->setObjectName(QString::fromUtf8("DownloadItem"));
DownloadItem->resize(423, 110);
horizontalLayout = new QHBoxLayout(DownloadItem);
horizontalLayout->setContentsMargins(0, 0, 0, 0);
- horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
+ horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
fileIcon = new QLabel(DownloadItem);
- fileIcon->setObjectName(QStringLiteral("fileIcon"));
+ fileIcon->setObjectName(QString::fromUtf8("fileIcon"));
QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -57,9 +57,9 @@ public:
horizontalLayout->addWidget(fileIcon);
verticalLayout_2 = new QVBoxLayout();
- verticalLayout_2->setObjectName(QStringLiteral("verticalLayout_2"));
+ verticalLayout_2->setObjectName(QString::fromUtf8("verticalLayout_2"));
fileNameLabel = new SqueezeLabel(DownloadItem);
- fileNameLabel->setObjectName(QStringLiteral("fileNameLabel"));
+ fileNameLabel->setObjectName(QString::fromUtf8("fileNameLabel"));
QSizePolicy sizePolicy1(QSizePolicy::Expanding, QSizePolicy::Preferred);
sizePolicy1.setHorizontalStretch(0);
sizePolicy1.setVerticalStretch(0);
@@ -69,13 +69,13 @@ public:
verticalLayout_2->addWidget(fileNameLabel);
progressBar = new QProgressBar(DownloadItem);
- progressBar->setObjectName(QStringLiteral("progressBar"));
+ progressBar->setObjectName(QString::fromUtf8("progressBar"));
progressBar->setValue(0);
verticalLayout_2->addWidget(progressBar);
downloadInfoLabel = new SqueezeLabel(DownloadItem);
- downloadInfoLabel->setObjectName(QStringLiteral("downloadInfoLabel"));
+ downloadInfoLabel->setObjectName(QString::fromUtf8("downloadInfoLabel"));
QSizePolicy sizePolicy2(QSizePolicy::Minimum, QSizePolicy::Preferred);
sizePolicy2.setHorizontalStretch(0);
sizePolicy2.setVerticalStretch(0);
@@ -88,24 +88,24 @@ public:
horizontalLayout->addLayout(verticalLayout_2);
verticalLayout = new QVBoxLayout();
- verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
+ verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
verticalSpacer = new QSpacerItem(17, 1, QSizePolicy::Minimum, QSizePolicy::Expanding);
verticalLayout->addItem(verticalSpacer);
tryAgainButton = new QPushButton(DownloadItem);
- tryAgainButton->setObjectName(QStringLiteral("tryAgainButton"));
+ tryAgainButton->setObjectName(QString::fromUtf8("tryAgainButton"));
tryAgainButton->setEnabled(false);
verticalLayout->addWidget(tryAgainButton);
stopButton = new QPushButton(DownloadItem);
- stopButton->setObjectName(QStringLiteral("stopButton"));
+ stopButton->setObjectName(QString::fromUtf8("stopButton"));
verticalLayout->addWidget(stopButton);
openButton = new QPushButton(DownloadItem);
- openButton->setObjectName(QStringLiteral("openButton"));
+ openButton->setObjectName(QString::fromUtf8("openButton"));
verticalLayout->addWidget(openButton);
diff --git a/tests/auto/tools/uic/baseline/downloads.ui.h b/tests/auto/tools/uic/baseline/downloads.ui.h
index 5ac40a9581..1df992d30f 100644
--- a/tests/auto/tools/uic/baseline/downloads.ui.h
+++ b/tests/auto/tools/uic/baseline/downloads.ui.h
@@ -36,21 +36,21 @@ public:
void setupUi(QDialog *DownloadDialog)
{
if (DownloadDialog->objectName().isEmpty())
- DownloadDialog->setObjectName(QStringLiteral("DownloadDialog"));
+ DownloadDialog->setObjectName(QString::fromUtf8("DownloadDialog"));
DownloadDialog->resize(332, 252);
gridLayout = new QGridLayout(DownloadDialog);
gridLayout->setSpacing(0);
gridLayout->setContentsMargins(0, 0, 0, 0);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
downloadsView = new EditTableView(DownloadDialog);
- downloadsView->setObjectName(QStringLiteral("downloadsView"));
+ downloadsView->setObjectName(QString::fromUtf8("downloadsView"));
gridLayout->addWidget(downloadsView, 0, 0, 1, 3);
horizontalLayout = new QHBoxLayout();
- horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
+ horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
cleanupButton = new QPushButton(DownloadDialog);
- cleanupButton->setObjectName(QStringLiteral("cleanupButton"));
+ cleanupButton->setObjectName(QString::fromUtf8("cleanupButton"));
cleanupButton->setEnabled(false);
horizontalLayout->addWidget(cleanupButton);
@@ -63,7 +63,7 @@ public:
gridLayout->addLayout(horizontalLayout, 1, 0, 1, 1);
itemCount = new QLabel(DownloadDialog);
- itemCount->setObjectName(QStringLiteral("itemCount"));
+ itemCount->setObjectName(QString::fromUtf8("itemCount"));
gridLayout->addWidget(itemCount, 1, 1, 1, 1);
diff --git a/tests/auto/tools/uic/baseline/embeddeddialog.ui.h b/tests/auto/tools/uic/baseline/embeddeddialog.ui.h
index 67ef6e1de1..194ff578e8 100644
--- a/tests/auto/tools/uic/baseline/embeddeddialog.ui.h
+++ b/tests/auto/tools/uic/baseline/embeddeddialog.ui.h
@@ -36,49 +36,49 @@ public:
void setupUi(QDialog *embeddedDialog)
{
if (embeddedDialog->objectName().isEmpty())
- embeddedDialog->setObjectName(QStringLiteral("embeddedDialog"));
+ embeddedDialog->setObjectName(QString::fromUtf8("embeddedDialog"));
embeddedDialog->resize(407, 134);
formLayout = new QFormLayout(embeddedDialog);
- formLayout->setObjectName(QStringLiteral("formLayout"));
+ formLayout->setObjectName(QString::fromUtf8("formLayout"));
label = new QLabel(embeddedDialog);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
formLayout->setWidget(0, QFormLayout::LabelRole, label);
layoutDirection = new QComboBox(embeddedDialog);
layoutDirection->addItem(QString());
layoutDirection->addItem(QString());
- layoutDirection->setObjectName(QStringLiteral("layoutDirection"));
+ layoutDirection->setObjectName(QString::fromUtf8("layoutDirection"));
formLayout->setWidget(0, QFormLayout::FieldRole, layoutDirection);
label_2 = new QLabel(embeddedDialog);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
formLayout->setWidget(1, QFormLayout::LabelRole, label_2);
fontComboBox = new QFontComboBox(embeddedDialog);
- fontComboBox->setObjectName(QStringLiteral("fontComboBox"));
+ fontComboBox->setObjectName(QString::fromUtf8("fontComboBox"));
formLayout->setWidget(1, QFormLayout::FieldRole, fontComboBox);
label_3 = new QLabel(embeddedDialog);
- label_3->setObjectName(QStringLiteral("label_3"));
+ label_3->setObjectName(QString::fromUtf8("label_3"));
formLayout->setWidget(2, QFormLayout::LabelRole, label_3);
style = new QComboBox(embeddedDialog);
- style->setObjectName(QStringLiteral("style"));
+ style->setObjectName(QString::fromUtf8("style"));
formLayout->setWidget(2, QFormLayout::FieldRole, style);
label_4 = new QLabel(embeddedDialog);
- label_4->setObjectName(QStringLiteral("label_4"));
+ label_4->setObjectName(QString::fromUtf8("label_4"));
formLayout->setWidget(3, QFormLayout::LabelRole, label_4);
spacing = new QSlider(embeddedDialog);
- spacing->setObjectName(QStringLiteral("spacing"));
+ spacing->setObjectName(QString::fromUtf8("spacing"));
spacing->setOrientation(Qt::Horizontal);
formLayout->setWidget(3, QFormLayout::FieldRole, spacing);
diff --git a/tests/auto/tools/uic/baseline/enumnostdset.ui.h b/tests/auto/tools/uic/baseline/enumnostdset.ui.h
index 451cbd6a68..233fc616ac 100644
--- a/tests/auto/tools/uic/baseline/enumnostdset.ui.h
+++ b/tests/auto/tools/uic/baseline/enumnostdset.ui.h
@@ -24,10 +24,10 @@ public:
void setupUi(QWidget *Form)
{
if (Form->objectName().isEmpty())
- Form->setObjectName(QStringLiteral("Form"));
+ Form->setObjectName(QString::fromUtf8("Form"));
Form->resize(400, 300);
worldTimeClock = new WorldTimeClock(Form);
- worldTimeClock->setObjectName(QStringLiteral("worldTimeClock"));
+ worldTimeClock->setObjectName(QString::fromUtf8("worldTimeClock"));
worldTimeClock->setGeometry(QRect(100, 100, 100, 100));
worldTimeClock->setProperty("penStyle", QVariant::fromValue(Qt::DashDotLine));
diff --git a/tests/auto/tools/uic/baseline/filespage.ui.h b/tests/auto/tools/uic/baseline/filespage.ui.h
index 8ab8d09768..29ed981a8a 100644
--- a/tests/auto/tools/uic/baseline/filespage.ui.h
+++ b/tests/auto/tools/uic/baseline/filespage.ui.h
@@ -34,23 +34,23 @@ public:
void setupUi(QWidget *FilesPage)
{
if (FilesPage->objectName().isEmpty())
- FilesPage->setObjectName(QStringLiteral("FilesPage"));
+ FilesPage->setObjectName(QString::fromUtf8("FilesPage"));
FilesPage->resize(417, 242);
gridLayout = new QGridLayout(FilesPage);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
fileLabel = new QLabel(FilesPage);
- fileLabel->setObjectName(QStringLiteral("fileLabel"));
+ fileLabel->setObjectName(QString::fromUtf8("fileLabel"));
fileLabel->setWordWrap(true);
gridLayout->addWidget(fileLabel, 0, 0, 1, 2);
fileListWidget = new QListWidget(FilesPage);
- fileListWidget->setObjectName(QStringLiteral("fileListWidget"));
+ fileListWidget->setObjectName(QString::fromUtf8("fileListWidget"));
gridLayout->addWidget(fileListWidget, 1, 0, 3, 1);
removeButton = new QPushButton(FilesPage);
- removeButton->setObjectName(QStringLiteral("removeButton"));
+ removeButton->setObjectName(QString::fromUtf8("removeButton"));
QSizePolicy sizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -60,7 +60,7 @@ public:
gridLayout->addWidget(removeButton, 1, 1, 1, 1);
removeAllButton = new QPushButton(FilesPage);
- removeAllButton->setObjectName(QStringLiteral("removeAllButton"));
+ removeAllButton->setObjectName(QString::fromUtf8("removeAllButton"));
gridLayout->addWidget(removeAllButton, 2, 1, 1, 1);
diff --git a/tests/auto/tools/uic/baseline/filternamedialog.ui.h b/tests/auto/tools/uic/baseline/filternamedialog.ui.h
index 60642c29f6..716c291fdd 100644
--- a/tests/auto/tools/uic/baseline/filternamedialog.ui.h
+++ b/tests/auto/tools/uic/baseline/filternamedialog.ui.h
@@ -34,24 +34,24 @@ public:
void setupUi(QDialog *FilterNameDialogClass)
{
if (FilterNameDialogClass->objectName().isEmpty())
- FilterNameDialogClass->setObjectName(QStringLiteral("FilterNameDialogClass"));
+ FilterNameDialogClass->setObjectName(QString::fromUtf8("FilterNameDialogClass"));
FilterNameDialogClass->resize(312, 95);
gridLayout = new QGridLayout(FilterNameDialogClass);
gridLayout->setSpacing(6);
gridLayout->setContentsMargins(9, 9, 9, 9);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
label = new QLabel(FilterNameDialogClass);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
gridLayout->addWidget(label, 0, 0, 1, 1);
lineEdit = new QLineEdit(FilterNameDialogClass);
- lineEdit->setObjectName(QStringLiteral("lineEdit"));
+ lineEdit->setObjectName(QString::fromUtf8("lineEdit"));
gridLayout->addWidget(lineEdit, 0, 1, 1, 2);
line = new QFrame(FilterNameDialogClass);
- line->setObjectName(QStringLiteral("line"));
+ line->setObjectName(QString::fromUtf8("line"));
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
@@ -62,7 +62,7 @@ public:
gridLayout->addItem(spacerItem, 2, 0, 1, 2);
buttonBox = new QDialogButtonBox(FilterNameDialogClass);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok);
diff --git a/tests/auto/tools/uic/baseline/filterpage.ui.h b/tests/auto/tools/uic/baseline/filterpage.ui.h
index a20dffc09a..f6610fdc4d 100644
--- a/tests/auto/tools/uic/baseline/filterpage.ui.h
+++ b/tests/auto/tools/uic/baseline/filterpage.ui.h
@@ -42,37 +42,37 @@ public:
void setupUi(QWidget *FilterPage)
{
if (FilterPage->objectName().isEmpty())
- FilterPage->setObjectName(QStringLiteral("FilterPage"));
+ FilterPage->setObjectName(QString::fromUtf8("FilterPage"));
FilterPage->resize(419, 243);
gridLayout = new QGridLayout(FilterPage);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
label = new QLabel(FilterPage);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
gridLayout->addWidget(label, 1, 0, 1, 1);
filterLineEdit = new QLineEdit(FilterPage);
- filterLineEdit->setObjectName(QStringLiteral("filterLineEdit"));
+ filterLineEdit->setObjectName(QString::fromUtf8("filterLineEdit"));
gridLayout->addWidget(filterLineEdit, 2, 0, 1, 1);
groupBox = new QGroupBox(FilterPage);
- groupBox->setObjectName(QStringLiteral("groupBox"));
+ groupBox->setObjectName(QString::fromUtf8("groupBox"));
gridLayout1 = new QGridLayout(groupBox);
- gridLayout1->setObjectName(QStringLiteral("gridLayout1"));
+ gridLayout1->setObjectName(QString::fromUtf8("gridLayout1"));
customFilterWidget = new QTreeWidget(groupBox);
- customFilterWidget->setObjectName(QStringLiteral("customFilterWidget"));
+ customFilterWidget->setObjectName(QString::fromUtf8("customFilterWidget"));
customFilterWidget->setColumnCount(2);
gridLayout1->addWidget(customFilterWidget, 0, 0, 3, 1);
addButton = new QPushButton(groupBox);
- addButton->setObjectName(QStringLiteral("addButton"));
+ addButton->setObjectName(QString::fromUtf8("addButton"));
gridLayout1->addWidget(addButton, 0, 1, 1, 1);
removeButton = new QPushButton(groupBox);
- removeButton->setObjectName(QStringLiteral("removeButton"));
+ removeButton->setObjectName(QString::fromUtf8("removeButton"));
gridLayout1->addWidget(removeButton, 1, 1, 1, 1);
diff --git a/tests/auto/tools/uic/baseline/finddialog.ui.h b/tests/auto/tools/uic/baseline/finddialog.ui.h
index 0bb1ec4286..a427be3614 100644
--- a/tests/auto/tools/uic/baseline/finddialog.ui.h
+++ b/tests/auto/tools/uic/baseline/finddialog.ui.h
@@ -77,7 +77,7 @@ public:
void setupUi(QDialog *FindDialog)
{
if (FindDialog->objectName().isEmpty())
- FindDialog->setObjectName(QStringLiteral("FindDialog"));
+ FindDialog->setObjectName(QString::fromUtf8("FindDialog"));
FindDialog->resize(414, 170);
QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
sizePolicy.setHorizontalStretch(0);
@@ -87,22 +87,22 @@ public:
hboxLayout = new QHBoxLayout(FindDialog);
hboxLayout->setSpacing(6);
hboxLayout->setContentsMargins(11, 11, 11, 11);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
vboxLayout = new QVBoxLayout();
vboxLayout->setSpacing(6);
vboxLayout->setContentsMargins(0, 0, 0, 0);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
hboxLayout1 = new QHBoxLayout();
hboxLayout1->setSpacing(6);
hboxLayout1->setContentsMargins(0, 0, 0, 0);
- hboxLayout1->setObjectName(QStringLiteral("hboxLayout1"));
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
findWhat = new QLabel(FindDialog);
- findWhat->setObjectName(QStringLiteral("findWhat"));
+ findWhat->setObjectName(QString::fromUtf8("findWhat"));
hboxLayout1->addWidget(findWhat);
led = new QLineEdit(FindDialog);
- led->setObjectName(QStringLiteral("led"));
+ led->setObjectName(QString::fromUtf8("led"));
hboxLayout1->addWidget(led);
@@ -110,36 +110,36 @@ public:
vboxLayout->addLayout(hboxLayout1);
groupBox = new QGroupBox(FindDialog);
- groupBox->setObjectName(QStringLiteral("groupBox"));
+ groupBox->setObjectName(QString::fromUtf8("groupBox"));
gridLayout = new QGridLayout(groupBox);
gridLayout->setSpacing(6);
gridLayout->setContentsMargins(9, 9, 9, 9);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
sourceText = new QCheckBox(groupBox);
- sourceText->setObjectName(QStringLiteral("sourceText"));
+ sourceText->setObjectName(QString::fromUtf8("sourceText"));
sourceText->setChecked(true);
gridLayout->addWidget(sourceText, 1, 0, 1, 1);
translations = new QCheckBox(groupBox);
- translations->setObjectName(QStringLiteral("translations"));
+ translations->setObjectName(QString::fromUtf8("translations"));
translations->setChecked(true);
gridLayout->addWidget(translations, 2, 0, 1, 1);
matchCase = new QCheckBox(groupBox);
- matchCase->setObjectName(QStringLiteral("matchCase"));
+ matchCase->setObjectName(QString::fromUtf8("matchCase"));
gridLayout->addWidget(matchCase, 0, 1, 1, 1);
comments = new QCheckBox(groupBox);
- comments->setObjectName(QStringLiteral("comments"));
+ comments->setObjectName(QString::fromUtf8("comments"));
comments->setChecked(true);
gridLayout->addWidget(comments, 0, 0, 1, 1);
ignoreAccelerators = new QCheckBox(groupBox);
- ignoreAccelerators->setObjectName(QStringLiteral("ignoreAccelerators"));
+ ignoreAccelerators->setObjectName(QString::fromUtf8("ignoreAccelerators"));
ignoreAccelerators->setChecked(true);
gridLayout->addWidget(ignoreAccelerators, 1, 1, 1, 1);
@@ -153,15 +153,15 @@ public:
vboxLayout1 = new QVBoxLayout();
vboxLayout1->setSpacing(6);
vboxLayout1->setContentsMargins(0, 0, 0, 0);
- vboxLayout1->setObjectName(QStringLiteral("vboxLayout1"));
+ vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
findNxt = new QPushButton(FindDialog);
- findNxt->setObjectName(QStringLiteral("findNxt"));
+ findNxt->setObjectName(QString::fromUtf8("findNxt"));
findNxt->setFlat(false);
vboxLayout1->addWidget(findNxt);
cancel = new QPushButton(FindDialog);
- cancel->setObjectName(QStringLiteral("cancel"));
+ cancel->setObjectName(QString::fromUtf8("cancel"));
vboxLayout1->addWidget(cancel);
diff --git a/tests/auto/tools/uic/baseline/form.ui.h b/tests/auto/tools/uic/baseline/form.ui.h
index fc4f3e079c..ecc63e339b 100644
--- a/tests/auto/tools/uic/baseline/form.ui.h
+++ b/tests/auto/tools/uic/baseline/form.ui.h
@@ -40,7 +40,7 @@ public:
void setupUi(QWidget *WorldTimeForm)
{
if (WorldTimeForm->objectName().isEmpty())
- WorldTimeForm->setObjectName(QStringLiteral("WorldTimeForm"));
+ WorldTimeForm->setObjectName(QString::fromUtf8("WorldTimeForm"));
WorldTimeForm->resize(400, 300);
hboxLayout = new QHBoxLayout(WorldTimeForm);
#ifndef Q_OS_MAC
@@ -49,9 +49,9 @@ public:
#ifndef Q_OS_MAC
hboxLayout->setContentsMargins(9, 9, 9, 9);
#endif
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
worldTimeClock = new WorldTimeClock(WorldTimeForm);
- worldTimeClock->setObjectName(QStringLiteral("worldTimeClock"));
+ worldTimeClock->setObjectName(QString::fromUtf8("worldTimeClock"));
hboxLayout->addWidget(worldTimeClock);
@@ -60,7 +60,7 @@ public:
vboxLayout->setSpacing(6);
#endif
vboxLayout->setContentsMargins(1, 1, 1, 1);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
spacerItem = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
vboxLayout->addItem(spacerItem);
@@ -70,14 +70,14 @@ public:
hboxLayout1->setSpacing(6);
#endif
hboxLayout1->setContentsMargins(1, 1, 1, 1);
- hboxLayout1->setObjectName(QStringLiteral("hboxLayout1"));
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
label = new QLabel(WorldTimeForm);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
hboxLayout1->addWidget(label);
timeEdit = new QTimeEdit(WorldTimeForm);
- timeEdit->setObjectName(QStringLiteral("timeEdit"));
+ timeEdit->setObjectName(QString::fromUtf8("timeEdit"));
timeEdit->setReadOnly(true);
hboxLayout1->addWidget(timeEdit);
@@ -90,14 +90,14 @@ public:
hboxLayout2->setSpacing(6);
#endif
hboxLayout2->setContentsMargins(1, 1, 1, 1);
- hboxLayout2->setObjectName(QStringLiteral("hboxLayout2"));
+ hboxLayout2->setObjectName(QString::fromUtf8("hboxLayout2"));
label_2 = new QLabel(WorldTimeForm);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
hboxLayout2->addWidget(label_2);
spinBox = new QSpinBox(WorldTimeForm);
- spinBox->setObjectName(QStringLiteral("spinBox"));
+ spinBox->setObjectName(QString::fromUtf8("spinBox"));
spinBox->setMaximum(12);
spinBox->setMinimum(-12);
diff --git a/tests/auto/tools/uic/baseline/formwindowsettings.ui.h b/tests/auto/tools/uic/baseline/formwindowsettings.ui.h
index 349ef9ac80..d2cfa03edb 100644
--- a/tests/auto/tools/uic/baseline/formwindowsettings.ui.h
+++ b/tests/auto/tools/uic/baseline/formwindowsettings.ui.h
@@ -92,19 +92,19 @@ public:
void setupUi(QDialog *FormWindowSettings)
{
if (FormWindowSettings->objectName().isEmpty())
- FormWindowSettings->setObjectName(QStringLiteral("FormWindowSettings"));
+ FormWindowSettings->setObjectName(QString::fromUtf8("FormWindowSettings"));
FormWindowSettings->resize(433, 465);
gridLayout = new QGridLayout(FormWindowSettings);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
buttonBox = new QDialogButtonBox(FormWindowSettings);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok);
gridLayout->addWidget(buttonBox, 6, 0, 1, 2);
line = new QFrame(FormWindowSettings);
- line->setObjectName(QStringLiteral("line"));
+ line->setObjectName(QString::fromUtf8("line"));
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
@@ -115,33 +115,33 @@ public:
hboxLayout->setSpacing(6);
#endif
hboxLayout->setContentsMargins(0, 0, 0, 0);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
layoutDefaultGroupBox = new QGroupBox(FormWindowSettings);
- layoutDefaultGroupBox->setObjectName(QStringLiteral("layoutDefaultGroupBox"));
+ layoutDefaultGroupBox->setObjectName(QString::fromUtf8("layoutDefaultGroupBox"));
layoutDefaultGroupBox->setCheckable(true);
gridLayout1 = new QGridLayout(layoutDefaultGroupBox);
#ifndef Q_OS_MAC
gridLayout1->setSpacing(6);
#endif
gridLayout1->setContentsMargins(8, 8, 8, 8);
- gridLayout1->setObjectName(QStringLiteral("gridLayout1"));
+ gridLayout1->setObjectName(QString::fromUtf8("gridLayout1"));
label_2 = new QLabel(layoutDefaultGroupBox);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
gridLayout1->addWidget(label_2, 1, 0, 1, 1);
label = new QLabel(layoutDefaultGroupBox);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
gridLayout1->addWidget(label, 0, 0, 1, 1);
defaultSpacingSpinBox = new QSpinBox(layoutDefaultGroupBox);
- defaultSpacingSpinBox->setObjectName(QStringLiteral("defaultSpacingSpinBox"));
+ defaultSpacingSpinBox->setObjectName(QString::fromUtf8("defaultSpacingSpinBox"));
gridLayout1->addWidget(defaultSpacingSpinBox, 1, 1, 1, 1);
defaultMarginSpinBox = new QSpinBox(layoutDefaultGroupBox);
- defaultMarginSpinBox->setObjectName(QStringLiteral("defaultMarginSpinBox"));
+ defaultMarginSpinBox->setObjectName(QString::fromUtf8("defaultMarginSpinBox"));
gridLayout1->addWidget(defaultMarginSpinBox, 0, 1, 1, 1);
@@ -149,31 +149,31 @@ public:
hboxLayout->addWidget(layoutDefaultGroupBox);
layoutFunctionGroupBox = new QGroupBox(FormWindowSettings);
- layoutFunctionGroupBox->setObjectName(QStringLiteral("layoutFunctionGroupBox"));
+ layoutFunctionGroupBox->setObjectName(QString::fromUtf8("layoutFunctionGroupBox"));
layoutFunctionGroupBox->setCheckable(true);
gridLayout2 = new QGridLayout(layoutFunctionGroupBox);
#ifndef Q_OS_MAC
gridLayout2->setSpacing(6);
#endif
gridLayout2->setContentsMargins(8, 8, 8, 8);
- gridLayout2->setObjectName(QStringLiteral("gridLayout2"));
+ gridLayout2->setObjectName(QString::fromUtf8("gridLayout2"));
spacingFunctionLineEdit = new QLineEdit(layoutFunctionGroupBox);
- spacingFunctionLineEdit->setObjectName(QStringLiteral("spacingFunctionLineEdit"));
+ spacingFunctionLineEdit->setObjectName(QString::fromUtf8("spacingFunctionLineEdit"));
gridLayout2->addWidget(spacingFunctionLineEdit, 1, 1, 1, 1);
marginFunctionLineEdit = new QLineEdit(layoutFunctionGroupBox);
- marginFunctionLineEdit->setObjectName(QStringLiteral("marginFunctionLineEdit"));
+ marginFunctionLineEdit->setObjectName(QString::fromUtf8("marginFunctionLineEdit"));
gridLayout2->addWidget(marginFunctionLineEdit, 0, 1, 1, 1);
label_3 = new QLabel(layoutFunctionGroupBox);
- label_3->setObjectName(QStringLiteral("label_3"));
+ label_3->setObjectName(QString::fromUtf8("label_3"));
gridLayout2->addWidget(label_3, 0, 0, 1, 1);
label_3_2 = new QLabel(layoutFunctionGroupBox);
- label_3_2->setObjectName(QStringLiteral("label_3_2"));
+ label_3_2->setObjectName(QString::fromUtf8("label_3_2"));
gridLayout2->addWidget(label_3_2, 1, 0, 1, 1);
@@ -184,15 +184,15 @@ public:
gridLayout->addLayout(hboxLayout, 2, 0, 1, 2);
pixmapFunctionGroupBox_2 = new QGroupBox(FormWindowSettings);
- pixmapFunctionGroupBox_2->setObjectName(QStringLiteral("pixmapFunctionGroupBox_2"));
+ pixmapFunctionGroupBox_2->setObjectName(QString::fromUtf8("pixmapFunctionGroupBox_2"));
vboxLayout = new QVBoxLayout(pixmapFunctionGroupBox_2);
#ifndef Q_OS_MAC
vboxLayout->setSpacing(6);
#endif
vboxLayout->setContentsMargins(8, 8, 8, 8);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
authorLineEdit = new QLineEdit(pixmapFunctionGroupBox_2);
- authorLineEdit->setObjectName(QStringLiteral("authorLineEdit"));
+ authorLineEdit->setObjectName(QString::fromUtf8("authorLineEdit"));
vboxLayout->addWidget(authorLineEdit);
@@ -200,15 +200,15 @@ public:
gridLayout->addWidget(pixmapFunctionGroupBox_2, 0, 0, 1, 2);
includeHintsGroupBox = new QGroupBox(FormWindowSettings);
- includeHintsGroupBox->setObjectName(QStringLiteral("includeHintsGroupBox"));
+ includeHintsGroupBox->setObjectName(QString::fromUtf8("includeHintsGroupBox"));
vboxLayout1 = new QVBoxLayout(includeHintsGroupBox);
#ifndef Q_OS_MAC
vboxLayout1->setSpacing(6);
#endif
vboxLayout1->setContentsMargins(8, 8, 8, 8);
- vboxLayout1->setObjectName(QStringLiteral("vboxLayout1"));
+ vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
includeHintsTextEdit = new QTextEdit(includeHintsGroupBox);
- includeHintsTextEdit->setObjectName(QStringLiteral("includeHintsTextEdit"));
+ includeHintsTextEdit->setObjectName(QString::fromUtf8("includeHintsTextEdit"));
vboxLayout1->addWidget(includeHintsTextEdit);
@@ -220,18 +220,18 @@ public:
hboxLayout1->setSpacing(6);
#endif
hboxLayout1->setContentsMargins(0, 0, 0, 0);
- hboxLayout1->setObjectName(QStringLiteral("hboxLayout1"));
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
pixmapFunctionGroupBox = new QGroupBox(FormWindowSettings);
- pixmapFunctionGroupBox->setObjectName(QStringLiteral("pixmapFunctionGroupBox"));
+ pixmapFunctionGroupBox->setObjectName(QString::fromUtf8("pixmapFunctionGroupBox"));
pixmapFunctionGroupBox->setCheckable(true);
vboxLayout2 = new QVBoxLayout(pixmapFunctionGroupBox);
#ifndef Q_OS_MAC
vboxLayout2->setSpacing(6);
#endif
vboxLayout2->setContentsMargins(8, 8, 8, 8);
- vboxLayout2->setObjectName(QStringLiteral("vboxLayout2"));
+ vboxLayout2->setObjectName(QString::fromUtf8("vboxLayout2"));
pixmapFunctionLineEdit = new QLineEdit(pixmapFunctionGroupBox);
- pixmapFunctionLineEdit->setObjectName(QStringLiteral("pixmapFunctionLineEdit"));
+ pixmapFunctionLineEdit->setObjectName(QString::fromUtf8("pixmapFunctionLineEdit"));
vboxLayout2->addWidget(pixmapFunctionLineEdit);
@@ -246,7 +246,7 @@ public:
gridLayout->addItem(spacerItem, 4, 1, 1, 1);
gridPanel = new qdesigner_internal::GridPanel(FormWindowSettings);
- gridPanel->setObjectName(QStringLiteral("gridPanel"));
+ gridPanel->setObjectName(QString::fromUtf8("gridPanel"));
gridLayout->addWidget(gridPanel, 1, 0, 1, 2);
diff --git a/tests/auto/tools/uic/baseline/generalpage.ui.h b/tests/auto/tools/uic/baseline/generalpage.ui.h
index cb0c4e92c4..bd04285d28 100644
--- a/tests/auto/tools/uic/baseline/generalpage.ui.h
+++ b/tests/auto/tools/uic/baseline/generalpage.ui.h
@@ -33,27 +33,27 @@ public:
void setupUi(QWidget *GeneralPage)
{
if (GeneralPage->objectName().isEmpty())
- GeneralPage->setObjectName(QStringLiteral("GeneralPage"));
+ GeneralPage->setObjectName(QString::fromUtf8("GeneralPage"));
GeneralPage->resize(417, 243);
gridLayout = new QGridLayout(GeneralPage);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
label = new QLabel(GeneralPage);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
gridLayout->addWidget(label, 1, 0, 1, 1);
namespaceLineEdit = new QLineEdit(GeneralPage);
- namespaceLineEdit->setObjectName(QStringLiteral("namespaceLineEdit"));
+ namespaceLineEdit->setObjectName(QString::fromUtf8("namespaceLineEdit"));
gridLayout->addWidget(namespaceLineEdit, 1, 1, 1, 1);
label_2 = new QLabel(GeneralPage);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
gridLayout->addWidget(label_2, 2, 0, 1, 1);
folderLineEdit = new QLineEdit(GeneralPage);
- folderLineEdit->setObjectName(QStringLiteral("folderLineEdit"));
+ folderLineEdit->setObjectName(QString::fromUtf8("folderLineEdit"));
gridLayout->addWidget(folderLineEdit, 2, 1, 1, 1);
diff --git a/tests/auto/tools/uic/baseline/gridalignment.ui.h b/tests/auto/tools/uic/baseline/gridalignment.ui.h
index 8e243ce800..421f257c9a 100644
--- a/tests/auto/tools/uic/baseline/gridalignment.ui.h
+++ b/tests/auto/tools/uic/baseline/gridalignment.ui.h
@@ -29,27 +29,27 @@ public:
void setupUi(QWidget *Form)
{
if (Form->objectName().isEmpty())
- Form->setObjectName(QStringLiteral("Form"));
+ Form->setObjectName(QString::fromUtf8("Form"));
Form->resize(279, 163);
gridLayout = new QGridLayout(Form);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
pushButton = new QPushButton(Form);
- pushButton->setObjectName(QStringLiteral("pushButton"));
+ pushButton->setObjectName(QString::fromUtf8("pushButton"));
gridLayout->addWidget(pushButton, 0, 0, 1, 1, Qt::AlignLeft);
pushButton_3 = new QPushButton(Form);
- pushButton_3->setObjectName(QStringLiteral("pushButton_3"));
+ pushButton_3->setObjectName(QString::fromUtf8("pushButton_3"));
gridLayout->addWidget(pushButton_3, 0, 1, 1, 1, Qt::AlignTop);
pushButton_2 = new QPushButton(Form);
- pushButton_2->setObjectName(QStringLiteral("pushButton_2"));
+ pushButton_2->setObjectName(QString::fromUtf8("pushButton_2"));
gridLayout->addWidget(pushButton_2, 1, 0, 1, 1, Qt::AlignRight);
pushButton_4 = new QPushButton(Form);
- pushButton_4->setObjectName(QStringLiteral("pushButton_4"));
+ pushButton_4->setObjectName(QString::fromUtf8("pushButton_4"));
gridLayout->addWidget(pushButton_4, 1, 1, 1, 1, Qt::AlignBottom);
diff --git a/tests/auto/tools/uic/baseline/gridpanel.ui.h b/tests/auto/tools/uic/baseline/gridpanel.ui.h
index feeff26013..858b71d0cc 100644
--- a/tests/auto/tools/uic/baseline/gridpanel.ui.h
+++ b/tests/auto/tools/uic/baseline/gridpanel.ui.h
@@ -46,17 +46,17 @@ public:
void setupUi(QWidget *qdesigner_internal__GridPanel)
{
if (qdesigner_internal__GridPanel->objectName().isEmpty())
- qdesigner_internal__GridPanel->setObjectName(QStringLiteral("qdesigner_internal__GridPanel"));
+ qdesigner_internal__GridPanel->setObjectName(QString::fromUtf8("qdesigner_internal__GridPanel"));
qdesigner_internal__GridPanel->resize(393, 110);
vboxLayout = new QVBoxLayout(qdesigner_internal__GridPanel);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
vboxLayout->setContentsMargins(0, 0, 0, 0);
m_gridGroupBox = new QGroupBox(qdesigner_internal__GridPanel);
- m_gridGroupBox->setObjectName(QStringLiteral("m_gridGroupBox"));
+ m_gridGroupBox->setObjectName(QString::fromUtf8("m_gridGroupBox"));
gridLayout = new QGridLayout(m_gridGroupBox);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
m_visibleCheckBox = new QCheckBox(m_gridGroupBox);
- m_visibleCheckBox->setObjectName(QStringLiteral("m_visibleCheckBox"));
+ m_visibleCheckBox->setObjectName(QString::fromUtf8("m_visibleCheckBox"));
QSizePolicy sizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -66,28 +66,28 @@ public:
gridLayout->addWidget(m_visibleCheckBox, 0, 0, 1, 1);
label = new QLabel(m_gridGroupBox);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
gridLayout->addWidget(label, 0, 1, 1, 1);
m_deltaXSpinBox = new QSpinBox(m_gridGroupBox);
- m_deltaXSpinBox->setObjectName(QStringLiteral("m_deltaXSpinBox"));
+ m_deltaXSpinBox->setObjectName(QString::fromUtf8("m_deltaXSpinBox"));
m_deltaXSpinBox->setMinimum(2);
m_deltaXSpinBox->setMaximum(100);
gridLayout->addWidget(m_deltaXSpinBox, 0, 2, 1, 1);
m_snapXCheckBox = new QCheckBox(m_gridGroupBox);
- m_snapXCheckBox->setObjectName(QStringLiteral("m_snapXCheckBox"));
+ m_snapXCheckBox->setObjectName(QString::fromUtf8("m_snapXCheckBox"));
sizePolicy.setHeightForWidth(m_snapXCheckBox->sizePolicy().hasHeightForWidth());
m_snapXCheckBox->setSizePolicy(sizePolicy);
gridLayout->addWidget(m_snapXCheckBox, 0, 3, 1, 1);
hboxLayout = new QHBoxLayout();
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
m_resetButton = new QPushButton(m_gridGroupBox);
- m_resetButton->setObjectName(QStringLiteral("m_resetButton"));
+ m_resetButton->setObjectName(QString::fromUtf8("m_resetButton"));
hboxLayout->addWidget(m_resetButton);
@@ -99,19 +99,19 @@ public:
gridLayout->addLayout(hboxLayout, 1, 0, 1, 1);
label_2 = new QLabel(m_gridGroupBox);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
gridLayout->addWidget(label_2, 1, 1, 1, 1);
m_deltaYSpinBox = new QSpinBox(m_gridGroupBox);
- m_deltaYSpinBox->setObjectName(QStringLiteral("m_deltaYSpinBox"));
+ m_deltaYSpinBox->setObjectName(QString::fromUtf8("m_deltaYSpinBox"));
m_deltaYSpinBox->setMinimum(2);
m_deltaYSpinBox->setMaximum(100);
gridLayout->addWidget(m_deltaYSpinBox, 1, 2, 1, 1);
m_snapYCheckBox = new QCheckBox(m_gridGroupBox);
- m_snapYCheckBox->setObjectName(QStringLiteral("m_snapYCheckBox"));
+ m_snapYCheckBox->setObjectName(QString::fromUtf8("m_snapYCheckBox"));
sizePolicy.setHeightForWidth(m_snapYCheckBox->sizePolicy().hasHeightForWidth());
m_snapYCheckBox->setSizePolicy(sizePolicy);
diff --git a/tests/auto/tools/uic/baseline/helpdialog.ui.h b/tests/auto/tools/uic/baseline/helpdialog.ui.h
index 7c584639c2..abcf280cf9 100644
--- a/tests/auto/tools/uic/baseline/helpdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/helpdialog.ui.h
@@ -98,26 +98,26 @@ public:
void setupUi(QWidget *HelpDialog)
{
if (HelpDialog->objectName().isEmpty())
- HelpDialog->setObjectName(QStringLiteral("HelpDialog"));
+ HelpDialog->setObjectName(QString::fromUtf8("HelpDialog"));
HelpDialog->resize(274, 417);
vboxLayout = new QVBoxLayout(HelpDialog);
#ifndef Q_OS_MAC
vboxLayout->setSpacing(6);
#endif
vboxLayout->setContentsMargins(0, 0, 0, 0);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
tabWidget = new QTabWidget(HelpDialog);
- tabWidget->setObjectName(QStringLiteral("tabWidget"));
+ tabWidget->setObjectName(QString::fromUtf8("tabWidget"));
contentPage = new QWidget();
- contentPage->setObjectName(QStringLiteral("contentPage"));
+ contentPage->setObjectName(QString::fromUtf8("contentPage"));
vboxLayout1 = new QVBoxLayout(contentPage);
#ifndef Q_OS_MAC
vboxLayout1->setSpacing(6);
#endif
vboxLayout1->setContentsMargins(5, 5, 5, 5);
- vboxLayout1->setObjectName(QStringLiteral("vboxLayout1"));
+ vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
listContents = new QTreeWidget(contentPage);
- listContents->setObjectName(QStringLiteral("listContents"));
+ listContents->setObjectName(QString::fromUtf8("listContents"));
listContents->setContextMenuPolicy(Qt::CustomContextMenu);
listContents->setRootIsDecorated(true);
listContents->setUniformRowHeights(true);
@@ -126,40 +126,40 @@ public:
tabWidget->addTab(contentPage, QString());
indexPage = new QWidget();
- indexPage->setObjectName(QStringLiteral("indexPage"));
+ indexPage->setObjectName(QString::fromUtf8("indexPage"));
vboxLayout2 = new QVBoxLayout(indexPage);
#ifndef Q_OS_MAC
vboxLayout2->setSpacing(6);
#endif
vboxLayout2->setContentsMargins(5, 5, 5, 5);
- vboxLayout2->setObjectName(QStringLiteral("vboxLayout2"));
+ vboxLayout2->setObjectName(QString::fromUtf8("vboxLayout2"));
TextLabel1 = new QLabel(indexPage);
- TextLabel1->setObjectName(QStringLiteral("TextLabel1"));
+ TextLabel1->setObjectName(QString::fromUtf8("TextLabel1"));
vboxLayout2->addWidget(TextLabel1);
editIndex = new QLineEdit(indexPage);
- editIndex->setObjectName(QStringLiteral("editIndex"));
+ editIndex->setObjectName(QString::fromUtf8("editIndex"));
vboxLayout2->addWidget(editIndex);
listIndex = new QListView(indexPage);
- listIndex->setObjectName(QStringLiteral("listIndex"));
+ listIndex->setObjectName(QString::fromUtf8("listIndex"));
listIndex->setContextMenuPolicy(Qt::CustomContextMenu);
vboxLayout2->addWidget(listIndex);
tabWidget->addTab(indexPage, QString());
bookmarkPage = new QWidget();
- bookmarkPage->setObjectName(QStringLiteral("bookmarkPage"));
+ bookmarkPage->setObjectName(QString::fromUtf8("bookmarkPage"));
vboxLayout3 = new QVBoxLayout(bookmarkPage);
#ifndef Q_OS_MAC
vboxLayout3->setSpacing(6);
#endif
vboxLayout3->setContentsMargins(5, 5, 5, 5);
- vboxLayout3->setObjectName(QStringLiteral("vboxLayout3"));
+ vboxLayout3->setObjectName(QString::fromUtf8("vboxLayout3"));
listBookmarks = new QTreeWidget(bookmarkPage);
- listBookmarks->setObjectName(QStringLiteral("listBookmarks"));
+ listBookmarks->setObjectName(QString::fromUtf8("listBookmarks"));
listBookmarks->setContextMenuPolicy(Qt::CustomContextMenu);
listBookmarks->setUniformRowHeights(true);
@@ -170,18 +170,18 @@ public:
hboxLayout->setSpacing(6);
#endif
hboxLayout->setContentsMargins(0, 0, 0, 0);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
spacerItem = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
hboxLayout->addItem(spacerItem);
buttonAdd = new QPushButton(bookmarkPage);
- buttonAdd->setObjectName(QStringLiteral("buttonAdd"));
+ buttonAdd->setObjectName(QString::fromUtf8("buttonAdd"));
hboxLayout->addWidget(buttonAdd);
buttonRemove = new QPushButton(bookmarkPage);
- buttonRemove->setObjectName(QStringLiteral("buttonRemove"));
+ buttonRemove->setObjectName(QString::fromUtf8("buttonRemove"));
hboxLayout->addWidget(buttonRemove);
@@ -190,35 +190,35 @@ public:
tabWidget->addTab(bookmarkPage, QString());
searchPage = new QWidget();
- searchPage->setObjectName(QStringLiteral("searchPage"));
+ searchPage->setObjectName(QString::fromUtf8("searchPage"));
gridLayout = new QGridLayout(searchPage);
#ifndef Q_OS_MAC
gridLayout->setSpacing(6);
#endif
gridLayout->setContentsMargins(5, 5, 5, 5);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
spacerItem1 = new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Fixed);
gridLayout->addItem(spacerItem1, 3, 0, 1, 1);
TextLabel1_2 = new QLabel(searchPage);
- TextLabel1_2->setObjectName(QStringLiteral("TextLabel1_2"));
+ TextLabel1_2->setObjectName(QString::fromUtf8("TextLabel1_2"));
gridLayout->addWidget(TextLabel1_2, 0, 0, 1, 1);
termsEdit = new QLineEdit(searchPage);
- termsEdit->setObjectName(QStringLiteral("termsEdit"));
+ termsEdit->setObjectName(QString::fromUtf8("termsEdit"));
gridLayout->addWidget(termsEdit, 1, 0, 1, 1);
resultBox = new QListWidget(searchPage);
- resultBox->setObjectName(QStringLiteral("resultBox"));
+ resultBox->setObjectName(QString::fromUtf8("resultBox"));
resultBox->setContextMenuPolicy(Qt::CustomContextMenu);
gridLayout->addWidget(resultBox, 5, 0, 1, 1);
TextLabel2 = new QLabel(searchPage);
- TextLabel2->setObjectName(QStringLiteral("TextLabel2"));
+ TextLabel2->setObjectName(QString::fromUtf8("TextLabel2"));
gridLayout->addWidget(TextLabel2, 4, 0, 1, 1);
@@ -227,9 +227,9 @@ public:
hboxLayout1->setSpacing(6);
#endif
hboxLayout1->setContentsMargins(1, 1, 1, 1);
- hboxLayout1->setObjectName(QStringLiteral("hboxLayout1"));
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
helpButton = new QPushButton(searchPage);
- helpButton->setObjectName(QStringLiteral("helpButton"));
+ helpButton->setObjectName(QString::fromUtf8("helpButton"));
hboxLayout1->addWidget(helpButton);
@@ -238,7 +238,7 @@ public:
hboxLayout1->addItem(spacerItem2);
searchButton = new QPushButton(searchPage);
- searchButton->setObjectName(QStringLiteral("searchButton"));
+ searchButton->setObjectName(QString::fromUtf8("searchButton"));
searchButton->setEnabled(false);
hboxLayout1->addWidget(searchButton);
@@ -251,7 +251,7 @@ public:
vboxLayout->addWidget(tabWidget);
framePrepare = new QFrame(HelpDialog);
- framePrepare->setObjectName(QStringLiteral("framePrepare"));
+ framePrepare->setObjectName(QString::fromUtf8("framePrepare"));
framePrepare->setFrameShape(QFrame::StyledPanel);
framePrepare->setFrameShadow(QFrame::Raised);
hboxLayout2 = new QHBoxLayout(framePrepare);
@@ -259,14 +259,14 @@ public:
hboxLayout2->setSpacing(6);
#endif
hboxLayout2->setContentsMargins(3, 3, 3, 3);
- hboxLayout2->setObjectName(QStringLiteral("hboxLayout2"));
+ hboxLayout2->setObjectName(QString::fromUtf8("hboxLayout2"));
labelPrepare = new QLabel(framePrepare);
- labelPrepare->setObjectName(QStringLiteral("labelPrepare"));
+ labelPrepare->setObjectName(QString::fromUtf8("labelPrepare"));
hboxLayout2->addWidget(labelPrepare);
progressPrepare = new QProgressBar(framePrepare);
- progressPrepare->setObjectName(QStringLiteral("progressPrepare"));
+ progressPrepare->setObjectName(QString::fromUtf8("progressPrepare"));
hboxLayout2->addWidget(progressPrepare);
diff --git a/tests/auto/tools/uic/baseline/history.ui.h b/tests/auto/tools/uic/baseline/history.ui.h
index f9050de854..715312d11a 100644
--- a/tests/auto/tools/uic/baseline/history.ui.h
+++ b/tests/auto/tools/uic/baseline/history.ui.h
@@ -39,33 +39,33 @@ public:
void setupUi(QDialog *HistoryDialog)
{
if (HistoryDialog->objectName().isEmpty())
- HistoryDialog->setObjectName(QStringLiteral("HistoryDialog"));
+ HistoryDialog->setObjectName(QString::fromUtf8("HistoryDialog"));
HistoryDialog->resize(758, 450);
gridLayout = new QGridLayout(HistoryDialog);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
spacerItem = new QSpacerItem(252, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
gridLayout->addItem(spacerItem, 0, 0, 1, 1);
search = new SearchLineEdit(HistoryDialog);
- search->setObjectName(QStringLiteral("search"));
+ search->setObjectName(QString::fromUtf8("search"));
gridLayout->addWidget(search, 0, 1, 1, 1);
tree = new EditTreeView(HistoryDialog);
- tree->setObjectName(QStringLiteral("tree"));
+ tree->setObjectName(QString::fromUtf8("tree"));
gridLayout->addWidget(tree, 1, 0, 1, 2);
hboxLayout = new QHBoxLayout();
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
removeButton = new QPushButton(HistoryDialog);
- removeButton->setObjectName(QStringLiteral("removeButton"));
+ removeButton->setObjectName(QString::fromUtf8("removeButton"));
hboxLayout->addWidget(removeButton);
removeAllButton = new QPushButton(HistoryDialog);
- removeAllButton->setObjectName(QStringLiteral("removeAllButton"));
+ removeAllButton->setObjectName(QString::fromUtf8("removeAllButton"));
hboxLayout->addWidget(removeAllButton);
@@ -74,7 +74,7 @@ public:
hboxLayout->addItem(spacerItem1);
buttonBox = new QDialogButtonBox(HistoryDialog);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setStandardButtons(QDialogButtonBox::Ok);
hboxLayout->addWidget(buttonBox);
diff --git a/tests/auto/tools/uic/baseline/icontheme.ui.h b/tests/auto/tools/uic/baseline/icontheme.ui.h
index 75a1b648cd..936d6b5cf7 100644
--- a/tests/auto/tools/uic/baseline/icontheme.ui.h
+++ b/tests/auto/tools/uic/baseline/icontheme.ui.h
@@ -29,39 +29,39 @@ public:
void setupUi(QWidget *Form)
{
if (Form->objectName().isEmpty())
- Form->setObjectName(QStringLiteral("Form"));
+ Form->setObjectName(QString::fromUtf8("Form"));
Form->resize(122, 117);
verticalLayout = new QVBoxLayout(Form);
- verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
+ verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
fileicon = new QPushButton(Form);
- fileicon->setObjectName(QStringLiteral("fileicon"));
+ fileicon->setObjectName(QString::fromUtf8("fileicon"));
QIcon icon;
- icon.addFile(QStringLiteral("image1.png"), QSize(), QIcon::Normal, QIcon::Off);
+ icon.addFile(QString::fromUtf8("image1.png"), QSize(), QIcon::Normal, QIcon::Off);
fileicon->setIcon(icon);
verticalLayout->addWidget(fileicon);
fileandthemeicon = new QPushButton(Form);
- fileandthemeicon->setObjectName(QStringLiteral("fileandthemeicon"));
+ fileandthemeicon->setObjectName(QString::fromUtf8("fileandthemeicon"));
QIcon icon1;
- QString iconThemeName = QStringLiteral("edit-copy");
+ QString iconThemeName = QString::fromUtf8("edit-copy");
if (QIcon::hasThemeIcon(iconThemeName)) {
icon1 = QIcon::fromTheme(iconThemeName);
} else {
- icon1.addFile(QStringLiteral("image7.png"), QSize(), QIcon::Normal, QIcon::Off);
+ icon1.addFile(QString::fromUtf8("image7.png"), QSize(), QIcon::Normal, QIcon::Off);
}
fileandthemeicon->setIcon(icon1);
verticalLayout->addWidget(fileandthemeicon);
themeicon = new QPushButton(Form);
- themeicon->setObjectName(QStringLiteral("themeicon"));
+ themeicon->setObjectName(QString::fromUtf8("themeicon"));
QIcon icon2;
- iconThemeName = QStringLiteral("edit-copy");
+ iconThemeName = QString::fromUtf8("edit-copy");
if (QIcon::hasThemeIcon(iconThemeName)) {
icon2 = QIcon::fromTheme(iconThemeName);
} else {
- icon2.addFile(QStringLiteral(""), QSize(), QIcon::Normal, QIcon::Off);
+ icon2.addFile(QString::fromUtf8(""), QSize(), QIcon::Normal, QIcon::Off);
}
themeicon->setIcon(icon2);
diff --git a/tests/auto/tools/uic/baseline/idbased.ui.h b/tests/auto/tools/uic/baseline/idbased.ui.h
index dbcd92a839..e246313e11 100644
--- a/tests/auto/tools/uic/baseline/idbased.ui.h
+++ b/tests/auto/tools/uic/baseline/idbased.ui.h
@@ -26,12 +26,12 @@ public:
void setupUi(QWidget *Form)
{
if (Form->objectName().isEmpty())
- Form->setObjectName(QStringLiteral("Form"));
+ Form->setObjectName(QString::fromUtf8("Form"));
Form->resize(400, 300);
verticalLayout = new QVBoxLayout(Form);
- verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
+ verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
pushButton = new QPushButton(Form);
- pushButton->setObjectName(QStringLiteral("pushButton"));
+ pushButton->setObjectName(QString::fromUtf8("pushButton"));
verticalLayout->addWidget(pushButton);
diff --git a/tests/auto/tools/uic/baseline/identifierpage.ui.h b/tests/auto/tools/uic/baseline/identifierpage.ui.h
index d16333cc9c..322a9cf30a 100644
--- a/tests/auto/tools/uic/baseline/identifierpage.ui.h
+++ b/tests/auto/tools/uic/baseline/identifierpage.ui.h
@@ -36,16 +36,16 @@ public:
void setupUi(QWidget *IdentifierPage)
{
if (IdentifierPage->objectName().isEmpty())
- IdentifierPage->setObjectName(QStringLiteral("IdentifierPage"));
+ IdentifierPage->setObjectName(QString::fromUtf8("IdentifierPage"));
IdentifierPage->resize(417, 242);
gridLayout = new QGridLayout(IdentifierPage);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
spacerItem = new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Fixed);
gridLayout->addItem(spacerItem, 0, 1, 1, 1);
identifierCheckBox = new QCheckBox(IdentifierPage);
- identifierCheckBox->setObjectName(QStringLiteral("identifierCheckBox"));
+ identifierCheckBox->setObjectName(QString::fromUtf8("identifierCheckBox"));
gridLayout->addWidget(identifierCheckBox, 1, 0, 1, 3);
@@ -58,20 +58,20 @@ public:
gridLayout->addItem(spacerItem2, 2, 0, 1, 1);
globalButton = new QRadioButton(IdentifierPage);
- globalButton->setObjectName(QStringLiteral("globalButton"));
+ globalButton->setObjectName(QString::fromUtf8("globalButton"));
globalButton->setEnabled(false);
globalButton->setChecked(true);
gridLayout->addWidget(globalButton, 2, 1, 1, 1);
prefixLineEdit = new QLineEdit(IdentifierPage);
- prefixLineEdit->setObjectName(QStringLiteral("prefixLineEdit"));
+ prefixLineEdit->setObjectName(QString::fromUtf8("prefixLineEdit"));
prefixLineEdit->setEnabled(false);
gridLayout->addWidget(prefixLineEdit, 2, 2, 1, 1);
fileNameButton = new QRadioButton(IdentifierPage);
- fileNameButton->setObjectName(QStringLiteral("fileNameButton"));
+ fileNameButton->setObjectName(QString::fromUtf8("fileNameButton"));
fileNameButton->setEnabled(false);
gridLayout->addWidget(fileNameButton, 3, 1, 1, 2);
diff --git a/tests/auto/tools/uic/baseline/imagedialog.ui.h b/tests/auto/tools/uic/baseline/imagedialog.ui.h
index 29a30d1996..e32e7639fa 100644
--- a/tests/auto/tools/uic/baseline/imagedialog.ui.h
+++ b/tests/auto/tools/uic/baseline/imagedialog.ui.h
@@ -46,8 +46,8 @@ public:
void setupUi(QDialog *dialog)
{
if (dialog->objectName().isEmpty())
- dialog->setObjectName(QStringLiteral("dialog"));
- dialog->setObjectName(QStringLiteral("ImageDialog"));
+ dialog->setObjectName(QString::fromUtf8("dialog"));
+ dialog->setObjectName(QString::fromUtf8("ImageDialog"));
dialog->resize(320, 180);
vboxLayout = new QVBoxLayout(dialog);
#ifndef Q_OS_MAC
@@ -56,17 +56,17 @@ public:
#ifndef Q_OS_MAC
vboxLayout->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
- vboxLayout->setObjectName(QStringLiteral(""));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8(""));
gridLayout = new QGridLayout();
#ifndef Q_OS_MAC
gridLayout->setSpacing(6);
#endif
gridLayout->setContentsMargins(1, 1, 1, 1);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
- gridLayout->setObjectName(QStringLiteral(""));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8(""));
widthLabel = new QLabel(dialog);
- widthLabel->setObjectName(QStringLiteral("widthLabel"));
+ widthLabel->setObjectName(QString::fromUtf8("widthLabel"));
widthLabel->setGeometry(QRect(1, 27, 67, 22));
widthLabel->setFrameShape(QFrame::NoFrame);
widthLabel->setFrameShadow(QFrame::Plain);
@@ -75,7 +75,7 @@ public:
gridLayout->addWidget(widthLabel, 1, 0, 1, 1);
heightLabel = new QLabel(dialog);
- heightLabel->setObjectName(QStringLiteral("heightLabel"));
+ heightLabel->setObjectName(QString::fromUtf8("heightLabel"));
heightLabel->setGeometry(QRect(1, 55, 67, 22));
heightLabel->setFrameShape(QFrame::NoFrame);
heightLabel->setFrameShadow(QFrame::Plain);
@@ -84,7 +84,7 @@ public:
gridLayout->addWidget(heightLabel, 2, 0, 1, 1);
colorDepthCombo = new QComboBox(dialog);
- colorDepthCombo->setObjectName(QStringLiteral("colorDepthCombo"));
+ colorDepthCombo->setObjectName(QString::fromUtf8("colorDepthCombo"));
colorDepthCombo->setGeometry(QRect(74, 83, 227, 22));
QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(5), static_cast<QSizePolicy::Policy>(0));
sizePolicy.setHorizontalStretch(0);
@@ -96,7 +96,7 @@ public:
gridLayout->addWidget(colorDepthCombo, 3, 1, 1, 1);
nameLineEdit = new QLineEdit(dialog);
- nameLineEdit->setObjectName(QStringLiteral("nameLineEdit"));
+ nameLineEdit->setObjectName(QString::fromUtf8("nameLineEdit"));
nameLineEdit->setGeometry(QRect(74, 83, 227, 22));
QSizePolicy sizePolicy1(static_cast<QSizePolicy::Policy>(5), static_cast<QSizePolicy::Policy>(0));
sizePolicy1.setHorizontalStretch(1);
@@ -108,7 +108,7 @@ public:
gridLayout->addWidget(nameLineEdit, 0, 1, 1, 1);
spinBox = new QSpinBox(dialog);
- spinBox->setObjectName(QStringLiteral("spinBox"));
+ spinBox->setObjectName(QString::fromUtf8("spinBox"));
spinBox->setGeometry(QRect(74, 1, 227, 20));
sizePolicy.setHeightForWidth(spinBox->sizePolicy().hasHeightForWidth());
spinBox->setSizePolicy(sizePolicy);
@@ -120,7 +120,7 @@ public:
gridLayout->addWidget(spinBox, 1, 1, 1, 1);
spinBox_2 = new QSpinBox(dialog);
- spinBox_2->setObjectName(QStringLiteral("spinBox_2"));
+ spinBox_2->setObjectName(QString::fromUtf8("spinBox_2"));
spinBox_2->setGeometry(QRect(74, 27, 227, 22));
sizePolicy.setHeightForWidth(spinBox_2->sizePolicy().hasHeightForWidth());
spinBox_2->setSizePolicy(sizePolicy);
@@ -132,7 +132,7 @@ public:
gridLayout->addWidget(spinBox_2, 2, 1, 1, 1);
nameLabel = new QLabel(dialog);
- nameLabel->setObjectName(QStringLiteral("nameLabel"));
+ nameLabel->setObjectName(QString::fromUtf8("nameLabel"));
nameLabel->setGeometry(QRect(1, 1, 67, 20));
nameLabel->setFrameShape(QFrame::NoFrame);
nameLabel->setFrameShadow(QFrame::Plain);
@@ -141,7 +141,7 @@ public:
gridLayout->addWidget(nameLabel, 0, 0, 1, 1);
colorDepthLabel = new QLabel(dialog);
- colorDepthLabel->setObjectName(QStringLiteral("colorDepthLabel"));
+ colorDepthLabel->setObjectName(QString::fromUtf8("colorDepthLabel"));
colorDepthLabel->setGeometry(QRect(1, 83, 67, 22));
colorDepthLabel->setFrameShape(QFrame::NoFrame);
colorDepthLabel->setFrameShadow(QFrame::Plain);
@@ -161,20 +161,20 @@ public:
hboxLayout->setSpacing(6);
#endif
hboxLayout->setContentsMargins(1, 1, 1, 1);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
- hboxLayout->setObjectName(QStringLiteral(""));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8(""));
spacerItem1 = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
hboxLayout->addItem(spacerItem1);
okButton = new QPushButton(dialog);
- okButton->setObjectName(QStringLiteral("okButton"));
+ okButton->setObjectName(QString::fromUtf8("okButton"));
okButton->setGeometry(QRect(135, 1, 80, 24));
hboxLayout->addWidget(okButton);
cancelButton = new QPushButton(dialog);
- cancelButton->setObjectName(QStringLiteral("cancelButton"));
+ cancelButton->setObjectName(QString::fromUtf8("cancelButton"));
cancelButton->setGeometry(QRect(221, 1, 80, 24));
hboxLayout->addWidget(cancelButton);
diff --git a/tests/auto/tools/uic/baseline/inputpage.ui.h b/tests/auto/tools/uic/baseline/inputpage.ui.h
index fb7ae1ea6f..9367dec6df 100644
--- a/tests/auto/tools/uic/baseline/inputpage.ui.h
+++ b/tests/auto/tools/uic/baseline/inputpage.ui.h
@@ -35,16 +35,16 @@ public:
void setupUi(QWidget *InputPage)
{
if (InputPage->objectName().isEmpty())
- InputPage->setObjectName(QStringLiteral("InputPage"));
+ InputPage->setObjectName(QString::fromUtf8("InputPage"));
InputPage->resize(417, 242);
gridLayout = new QGridLayout(InputPage);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
spacerItem = new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Fixed);
gridLayout->addItem(spacerItem, 0, 2, 1, 1);
label = new QLabel(InputPage);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
QSizePolicy sizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -55,14 +55,14 @@ public:
hboxLayout = new QHBoxLayout();
hboxLayout->setSpacing(0);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
fileLineEdit = new QLineEdit(InputPage);
- fileLineEdit->setObjectName(QStringLiteral("fileLineEdit"));
+ fileLineEdit->setObjectName(QString::fromUtf8("fileLineEdit"));
hboxLayout->addWidget(fileLineEdit);
browseButton = new QToolButton(InputPage);
- browseButton->setObjectName(QStringLiteral("browseButton"));
+ browseButton->setObjectName(QString::fromUtf8("browseButton"));
hboxLayout->addWidget(browseButton);
diff --git a/tests/auto/tools/uic/baseline/installdialog.ui.h b/tests/auto/tools/uic/baseline/installdialog.ui.h
index 885488d2a7..3ec7f69b76 100644
--- a/tests/auto/tools/uic/baseline/installdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/installdialog.ui.h
@@ -44,32 +44,32 @@ public:
void setupUi(QDialog *InstallDialog)
{
if (InstallDialog->objectName().isEmpty())
- InstallDialog->setObjectName(QStringLiteral("InstallDialog"));
+ InstallDialog->setObjectName(QString::fromUtf8("InstallDialog"));
InstallDialog->resize(436, 245);
gridLayout = new QGridLayout(InstallDialog);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
label = new QLabel(InstallDialog);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
gridLayout->addWidget(label, 0, 0, 1, 4);
listWidget = new QListWidget(InstallDialog);
- listWidget->setObjectName(QStringLiteral("listWidget"));
+ listWidget->setObjectName(QString::fromUtf8("listWidget"));
gridLayout->addWidget(listWidget, 1, 0, 4, 4);
installButton = new QPushButton(InstallDialog);
- installButton->setObjectName(QStringLiteral("installButton"));
+ installButton->setObjectName(QString::fromUtf8("installButton"));
gridLayout->addWidget(installButton, 1, 4, 1, 1);
cancelButton = new QPushButton(InstallDialog);
- cancelButton->setObjectName(QStringLiteral("cancelButton"));
+ cancelButton->setObjectName(QString::fromUtf8("cancelButton"));
gridLayout->addWidget(cancelButton, 2, 4, 1, 1);
closeButton = new QPushButton(InstallDialog);
- closeButton->setObjectName(QStringLiteral("closeButton"));
+ closeButton->setObjectName(QString::fromUtf8("closeButton"));
gridLayout->addWidget(closeButton, 3, 4, 1, 1);
@@ -78,34 +78,34 @@ public:
gridLayout->addItem(spacerItem, 4, 4, 1, 1);
label_4 = new QLabel(InstallDialog);
- label_4->setObjectName(QStringLiteral("label_4"));
+ label_4->setObjectName(QString::fromUtf8("label_4"));
gridLayout->addWidget(label_4, 5, 0, 1, 1);
pathLineEdit = new QLineEdit(InstallDialog);
- pathLineEdit->setObjectName(QStringLiteral("pathLineEdit"));
+ pathLineEdit->setObjectName(QString::fromUtf8("pathLineEdit"));
gridLayout->addWidget(pathLineEdit, 5, 1, 1, 2);
browseButton = new QToolButton(InstallDialog);
- browseButton->setObjectName(QStringLiteral("browseButton"));
+ browseButton->setObjectName(QString::fromUtf8("browseButton"));
gridLayout->addWidget(browseButton, 5, 3, 1, 1);
line = new QFrame(InstallDialog);
- line->setObjectName(QStringLiteral("line"));
+ line->setObjectName(QString::fromUtf8("line"));
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
gridLayout->addWidget(line, 6, 0, 1, 5);
statusLabel = new QLabel(InstallDialog);
- statusLabel->setObjectName(QStringLiteral("statusLabel"));
+ statusLabel->setObjectName(QString::fromUtf8("statusLabel"));
gridLayout->addWidget(statusLabel, 7, 0, 1, 2);
progressBar = new QProgressBar(InstallDialog);
- progressBar->setObjectName(QStringLiteral("progressBar"));
+ progressBar->setObjectName(QString::fromUtf8("progressBar"));
progressBar->setValue(0);
progressBar->setOrientation(Qt::Horizontal);
diff --git a/tests/auto/tools/uic/baseline/languagesdialog.ui.h b/tests/auto/tools/uic/baseline/languagesdialog.ui.h
index 6f722a4e74..cf2599fd07 100644
--- a/tests/auto/tools/uic/baseline/languagesdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/languagesdialog.ui.h
@@ -39,50 +39,50 @@ public:
void setupUi(QDialog *LanguagesDialog)
{
if (LanguagesDialog->objectName().isEmpty())
- LanguagesDialog->setObjectName(QStringLiteral("LanguagesDialog"));
+ LanguagesDialog->setObjectName(QString::fromUtf8("LanguagesDialog"));
LanguagesDialog->resize(400, 300);
verticalLayout = new QVBoxLayout(LanguagesDialog);
- verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
+ verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
languagesList = new QTreeWidget(LanguagesDialog);
- languagesList->setObjectName(QStringLiteral("languagesList"));
+ languagesList->setObjectName(QString::fromUtf8("languagesList"));
languagesList->setIndentation(0);
verticalLayout->addWidget(languagesList);
hboxLayout = new QHBoxLayout();
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
upButton = new QToolButton(LanguagesDialog);
- upButton->setObjectName(QStringLiteral("upButton"));
+ upButton->setObjectName(QString::fromUtf8("upButton"));
upButton->setEnabled(false);
QIcon icon;
- icon.addFile(QStringLiteral(":/images/up.png"), QSize(), QIcon::Normal, QIcon::Off);
+ icon.addFile(QString::fromUtf8(":/images/up.png"), QSize(), QIcon::Normal, QIcon::Off);
upButton->setIcon(icon);
hboxLayout->addWidget(upButton);
downButton = new QToolButton(LanguagesDialog);
- downButton->setObjectName(QStringLiteral("downButton"));
+ downButton->setObjectName(QString::fromUtf8("downButton"));
downButton->setEnabled(false);
QIcon icon1;
- icon1.addFile(QStringLiteral(":/images/down.png"), QSize(), QIcon::Normal, QIcon::Off);
+ icon1.addFile(QString::fromUtf8(":/images/down.png"), QSize(), QIcon::Normal, QIcon::Off);
downButton->setIcon(icon1);
hboxLayout->addWidget(downButton);
removeButton = new QToolButton(LanguagesDialog);
- removeButton->setObjectName(QStringLiteral("removeButton"));
+ removeButton->setObjectName(QString::fromUtf8("removeButton"));
removeButton->setEnabled(false);
QIcon icon2;
- icon2.addFile(QStringLiteral(":/images/editdelete.png"), QSize(), QIcon::Normal, QIcon::Off);
+ icon2.addFile(QString::fromUtf8(":/images/editdelete.png"), QSize(), QIcon::Normal, QIcon::Off);
removeButton->setIcon(icon2);
hboxLayout->addWidget(removeButton);
openFileButton = new QToolButton(LanguagesDialog);
- openFileButton->setObjectName(QStringLiteral("openFileButton"));
+ openFileButton->setObjectName(QString::fromUtf8("openFileButton"));
openFileButton->setEnabled(true);
QIcon icon3;
- icon3.addFile(QStringLiteral(":/images/mac/fileopen.png"), QSize(), QIcon::Normal, QIcon::Off);
+ icon3.addFile(QString::fromUtf8(":/images/mac/fileopen.png"), QSize(), QIcon::Normal, QIcon::Off);
openFileButton->setIcon(icon3);
hboxLayout->addWidget(openFileButton);
@@ -92,7 +92,7 @@ public:
hboxLayout->addItem(spacerItem);
okButton = new QPushButton(LanguagesDialog);
- okButton->setObjectName(QStringLiteral("okButton"));
+ okButton->setObjectName(QString::fromUtf8("okButton"));
hboxLayout->addWidget(okButton);
diff --git a/tests/auto/tools/uic/baseline/listwidgeteditor.ui.h b/tests/auto/tools/uic/baseline/listwidgeteditor.ui.h
index 06f55dba4c..14067ced18 100644
--- a/tests/auto/tools/uic/baseline/listwidgeteditor.ui.h
+++ b/tests/auto/tools/uic/baseline/listwidgeteditor.ui.h
@@ -79,7 +79,7 @@ public:
void setupUi(QDialog *qdesigner_internal__ListWidgetEditor)
{
if (qdesigner_internal__ListWidgetEditor->objectName().isEmpty())
- qdesigner_internal__ListWidgetEditor->setObjectName(QStringLiteral("qdesigner_internal__ListWidgetEditor"));
+ qdesigner_internal__ListWidgetEditor->setObjectName(QString::fromUtf8("qdesigner_internal__ListWidgetEditor"));
qdesigner_internal__ListWidgetEditor->resize(223, 245);
vboxLayout = new QVBoxLayout(qdesigner_internal__ListWidgetEditor);
#ifndef Q_OS_MAC
@@ -88,25 +88,25 @@ public:
#ifndef Q_OS_MAC
vboxLayout->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
groupBox = new QGroupBox(qdesigner_internal__ListWidgetEditor);
- groupBox->setObjectName(QStringLiteral("groupBox"));
+ groupBox->setObjectName(QString::fromUtf8("groupBox"));
gridLayout = new QGridLayout(groupBox);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
listWidget = new QListWidget(groupBox);
- listWidget->setObjectName(QStringLiteral("listWidget"));
+ listWidget->setObjectName(QString::fromUtf8("listWidget"));
gridLayout->addWidget(listWidget, 0, 0, 1, 1);
horizontalLayout_2 = new QHBoxLayout();
- horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2"));
+ horizontalLayout_2->setObjectName(QString::fromUtf8("horizontalLayout_2"));
newItemButton = new QToolButton(groupBox);
- newItemButton->setObjectName(QStringLiteral("newItemButton"));
+ newItemButton->setObjectName(QString::fromUtf8("newItemButton"));
horizontalLayout_2->addWidget(newItemButton);
deleteItemButton = new QToolButton(groupBox);
- deleteItemButton->setObjectName(QStringLiteral("deleteItemButton"));
+ deleteItemButton->setObjectName(QString::fromUtf8("deleteItemButton"));
horizontalLayout_2->addWidget(deleteItemButton);
@@ -115,12 +115,12 @@ public:
horizontalLayout_2->addItem(spacerItem);
moveItemUpButton = new QToolButton(groupBox);
- moveItemUpButton->setObjectName(QStringLiteral("moveItemUpButton"));
+ moveItemUpButton->setObjectName(QString::fromUtf8("moveItemUpButton"));
horizontalLayout_2->addWidget(moveItemUpButton);
moveItemDownButton = new QToolButton(groupBox);
- moveItemDownButton->setObjectName(QStringLiteral("moveItemDownButton"));
+ moveItemDownButton->setObjectName(QString::fromUtf8("moveItemDownButton"));
horizontalLayout_2->addWidget(moveItemDownButton);
@@ -128,14 +128,14 @@ public:
gridLayout->addLayout(horizontalLayout_2, 1, 0, 1, 1);
horizontalLayout = new QHBoxLayout();
- horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
+ horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
label = new QLabel(groupBox);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
horizontalLayout->addWidget(label);
itemIconSelector = new qdesigner_internal::IconSelector(groupBox);
- itemIconSelector->setObjectName(QStringLiteral("itemIconSelector"));
+ itemIconSelector->setObjectName(QString::fromUtf8("itemIconSelector"));
horizontalLayout->addWidget(itemIconSelector);
@@ -150,7 +150,7 @@ public:
vboxLayout->addWidget(groupBox);
buttonBox = new QDialogButtonBox(qdesigner_internal__ListWidgetEditor);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
diff --git a/tests/auto/tools/uic/baseline/mainwindow.ui.h b/tests/auto/tools/uic/baseline/mainwindow.ui.h
index 950040aeed..fe84d0baa3 100644
--- a/tests/auto/tools/uic/baseline/mainwindow.ui.h
+++ b/tests/auto/tools/uic/baseline/mainwindow.ui.h
@@ -86,14 +86,14 @@ public:
void setupUi(QMainWindow *MainWindow)
{
if (MainWindow->objectName().isEmpty())
- MainWindow->setObjectName(QStringLiteral("MainWindow"));
+ MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
MainWindow->resize(829, 813);
actionAdd_Custom_Font = new QAction(MainWindow);
- actionAdd_Custom_Font->setObjectName(QStringLiteral("actionAdd_Custom_Font"));
+ actionAdd_Custom_Font->setObjectName(QString::fromUtf8("actionAdd_Custom_Font"));
action_Exit = new QAction(MainWindow);
- action_Exit->setObjectName(QStringLiteral("action_Exit"));
+ action_Exit->setObjectName(QString::fromUtf8("action_Exit"));
centralwidget = new QWidget(MainWindow);
- centralwidget->setObjectName(QStringLiteral("centralwidget"));
+ centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
vboxLayout = new QVBoxLayout(centralwidget);
#ifndef Q_OS_MAC
vboxLayout->setSpacing(6);
@@ -101,9 +101,9 @@ public:
#ifndef Q_OS_MAC
vboxLayout->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
groupBox = new QGroupBox(centralwidget);
- groupBox->setObjectName(QStringLiteral("groupBox"));
+ groupBox->setObjectName(QString::fromUtf8("groupBox"));
hboxLayout = new QHBoxLayout(groupBox);
#ifndef Q_OS_MAC
hboxLayout->setSpacing(6);
@@ -111,40 +111,40 @@ public:
#ifndef Q_OS_MAC
hboxLayout->setContentsMargins(9, 9, 9, 9);
#endif
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
label = new QLabel(groupBox);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
hboxLayout->addWidget(label);
fontComboBox = new QFontComboBox(groupBox);
- fontComboBox->setObjectName(QStringLiteral("fontComboBox"));
+ fontComboBox->setObjectName(QString::fromUtf8("fontComboBox"));
hboxLayout->addWidget(fontComboBox);
label_2 = new QLabel(groupBox);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
hboxLayout->addWidget(label_2);
pixelSize = new QSpinBox(groupBox);
- pixelSize->setObjectName(QStringLiteral("pixelSize"));
+ pixelSize->setObjectName(QString::fromUtf8("pixelSize"));
pixelSize->setMinimum(1);
hboxLayout->addWidget(pixelSize);
label_7 = new QLabel(groupBox);
- label_7->setObjectName(QStringLiteral("label_7"));
+ label_7->setObjectName(QString::fromUtf8("label_7"));
hboxLayout->addWidget(label_7);
weightCombo = new QComboBox(groupBox);
- weightCombo->setObjectName(QStringLiteral("weightCombo"));
+ weightCombo->setObjectName(QString::fromUtf8("weightCombo"));
hboxLayout->addWidget(weightCombo);
italic = new QCheckBox(groupBox);
- italic->setObjectName(QStringLiteral("italic"));
+ italic->setObjectName(QString::fromUtf8("italic"));
hboxLayout->addWidget(italic);
@@ -156,7 +156,7 @@ public:
vboxLayout->addWidget(groupBox);
groupBox_2 = new QGroupBox(centralwidget);
- groupBox_2->setObjectName(QStringLiteral("groupBox_2"));
+ groupBox_2->setObjectName(QString::fromUtf8("groupBox_2"));
vboxLayout1 = new QVBoxLayout(groupBox_2);
#ifndef Q_OS_MAC
vboxLayout1->setSpacing(6);
@@ -164,9 +164,9 @@ public:
#ifndef Q_OS_MAC
vboxLayout1->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout1->setObjectName(QStringLiteral("vboxLayout1"));
+ vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
chooseFromCodePoints = new QRadioButton(groupBox_2);
- chooseFromCodePoints->setObjectName(QStringLiteral("chooseFromCodePoints"));
+ chooseFromCodePoints->setObjectName(QString::fromUtf8("chooseFromCodePoints"));
chooseFromCodePoints->setChecked(true);
vboxLayout1->addWidget(chooseFromCodePoints);
@@ -176,9 +176,9 @@ public:
vboxLayout2->setSpacing(6);
#endif
vboxLayout2->setContentsMargins(0, 0, 0, 0);
- vboxLayout2->setObjectName(QStringLiteral("vboxLayout2"));
+ vboxLayout2->setObjectName(QString::fromUtf8("vboxLayout2"));
characterRangeView = new QListWidget(groupBox_2);
- characterRangeView->setObjectName(QStringLiteral("characterRangeView"));
+ characterRangeView->setObjectName(QString::fromUtf8("characterRangeView"));
vboxLayout2->addWidget(characterRangeView);
@@ -187,19 +187,19 @@ public:
hboxLayout1->setSpacing(6);
#endif
hboxLayout1->setContentsMargins(0, 0, 0, 0);
- hboxLayout1->setObjectName(QStringLiteral("hboxLayout1"));
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
selectAll = new QPushButton(groupBox_2);
- selectAll->setObjectName(QStringLiteral("selectAll"));
+ selectAll->setObjectName(QString::fromUtf8("selectAll"));
hboxLayout1->addWidget(selectAll);
deselectAll = new QPushButton(groupBox_2);
- deselectAll->setObjectName(QStringLiteral("deselectAll"));
+ deselectAll->setObjectName(QString::fromUtf8("deselectAll"));
hboxLayout1->addWidget(deselectAll);
invertSelection = new QPushButton(groupBox_2);
- invertSelection->setObjectName(QStringLiteral("invertSelection"));
+ invertSelection->setObjectName(QString::fromUtf8("invertSelection"));
hboxLayout1->addWidget(invertSelection);
@@ -214,7 +214,7 @@ public:
vboxLayout1->addLayout(vboxLayout2);
chooseFromSampleFile = new QRadioButton(groupBox_2);
- chooseFromSampleFile->setObjectName(QStringLiteral("chooseFromSampleFile"));
+ chooseFromSampleFile->setObjectName(QString::fromUtf8("chooseFromSampleFile"));
vboxLayout1->addWidget(chooseFromSampleFile);
@@ -223,27 +223,27 @@ public:
hboxLayout2->setSpacing(6);
#endif
hboxLayout2->setContentsMargins(0, 0, 0, 0);
- hboxLayout2->setObjectName(QStringLiteral("hboxLayout2"));
+ hboxLayout2->setObjectName(QString::fromUtf8("hboxLayout2"));
label_5 = new QLabel(groupBox_2);
- label_5->setObjectName(QStringLiteral("label_5"));
+ label_5->setObjectName(QString::fromUtf8("label_5"));
label_5->setEnabled(false);
hboxLayout2->addWidget(label_5);
sampleFile = new QLineEdit(groupBox_2);
- sampleFile->setObjectName(QStringLiteral("sampleFile"));
+ sampleFile->setObjectName(QString::fromUtf8("sampleFile"));
sampleFile->setEnabled(false);
hboxLayout2->addWidget(sampleFile);
browseSampleFile = new QPushButton(groupBox_2);
- browseSampleFile->setObjectName(QStringLiteral("browseSampleFile"));
+ browseSampleFile->setObjectName(QString::fromUtf8("browseSampleFile"));
browseSampleFile->setEnabled(false);
hboxLayout2->addWidget(browseSampleFile);
charCount = new QLabel(groupBox_2);
- charCount->setObjectName(QStringLiteral("charCount"));
+ charCount->setObjectName(QString::fromUtf8("charCount"));
charCount->setEnabled(false);
hboxLayout2->addWidget(charCount);
@@ -255,7 +255,7 @@ public:
vboxLayout->addWidget(groupBox_2);
groupBox_3 = new QGroupBox(centralwidget);
- groupBox_3->setObjectName(QStringLiteral("groupBox_3"));
+ groupBox_3->setObjectName(QString::fromUtf8("groupBox_3"));
hboxLayout3 = new QHBoxLayout(groupBox_3);
#ifndef Q_OS_MAC
hboxLayout3->setSpacing(6);
@@ -263,9 +263,9 @@ public:
#ifndef Q_OS_MAC
hboxLayout3->setContentsMargins(9, 9, 9, 9);
#endif
- hboxLayout3->setObjectName(QStringLiteral("hboxLayout3"));
+ hboxLayout3->setObjectName(QString::fromUtf8("hboxLayout3"));
preview = new QLineEdit(groupBox_3);
- preview->setObjectName(QStringLiteral("preview"));
+ preview->setObjectName(QString::fromUtf8("preview"));
hboxLayout3->addWidget(preview);
@@ -273,7 +273,7 @@ public:
vboxLayout->addWidget(groupBox_3);
groupBox_4 = new QGroupBox(centralwidget);
- groupBox_4->setObjectName(QStringLiteral("groupBox_4"));
+ groupBox_4->setObjectName(QString::fromUtf8("groupBox_4"));
hboxLayout4 = new QHBoxLayout(groupBox_4);
#ifndef Q_OS_MAC
hboxLayout4->setSpacing(6);
@@ -281,29 +281,29 @@ public:
#ifndef Q_OS_MAC
hboxLayout4->setContentsMargins(9, 9, 9, 9);
#endif
- hboxLayout4->setObjectName(QStringLiteral("hboxLayout4"));
+ hboxLayout4->setObjectName(QString::fromUtf8("hboxLayout4"));
label_3 = new QLabel(groupBox_4);
- label_3->setObjectName(QStringLiteral("label_3"));
+ label_3->setObjectName(QString::fromUtf8("label_3"));
hboxLayout4->addWidget(label_3);
path = new QLineEdit(groupBox_4);
- path->setObjectName(QStringLiteral("path"));
+ path->setObjectName(QString::fromUtf8("path"));
hboxLayout4->addWidget(path);
browsePath = new QPushButton(groupBox_4);
- browsePath->setObjectName(QStringLiteral("browsePath"));
+ browsePath->setObjectName(QString::fromUtf8("browsePath"));
hboxLayout4->addWidget(browsePath);
label_4 = new QLabel(groupBox_4);
- label_4->setObjectName(QStringLiteral("label_4"));
+ label_4->setObjectName(QString::fromUtf8("label_4"));
hboxLayout4->addWidget(label_4);
fileName = new QLineEdit(groupBox_4);
- fileName->setObjectName(QStringLiteral("fileName"));
+ fileName->setObjectName(QString::fromUtf8("fileName"));
fileName->setEnabled(false);
hboxLayout4->addWidget(fileName);
@@ -316,9 +316,9 @@ public:
hboxLayout5->setSpacing(6);
#endif
hboxLayout5->setContentsMargins(0, 0, 0, 0);
- hboxLayout5->setObjectName(QStringLiteral("hboxLayout5"));
+ hboxLayout5->setObjectName(QString::fromUtf8("hboxLayout5"));
generate = new QPushButton(centralwidget);
- generate->setObjectName(QStringLiteral("generate"));
+ generate->setObjectName(QString::fromUtf8("generate"));
hboxLayout5->addWidget(generate);
@@ -331,13 +331,13 @@ public:
MainWindow->setCentralWidget(centralwidget);
menubar = new QMenuBar(MainWindow);
- menubar->setObjectName(QStringLiteral("menubar"));
+ menubar->setObjectName(QString::fromUtf8("menubar"));
menubar->setGeometry(QRect(0, 0, 829, 29));
menuFile = new QMenu(menubar);
- menuFile->setObjectName(QStringLiteral("menuFile"));
+ menuFile->setObjectName(QString::fromUtf8("menuFile"));
MainWindow->setMenuBar(menubar);
statusbar = new QStatusBar(MainWindow);
- statusbar->setObjectName(QStringLiteral("statusbar"));
+ statusbar->setObjectName(QString::fromUtf8("statusbar"));
MainWindow->setStatusBar(statusbar);
menubar->addAction(menuFile->menuAction());
diff --git a/tests/auto/tools/uic/baseline/mydialog.ui.h b/tests/auto/tools/uic/baseline/mydialog.ui.h
index 95864d5195..1a784d1b0a 100644
--- a/tests/auto/tools/uic/baseline/mydialog.ui.h
+++ b/tests/auto/tools/uic/baseline/mydialog.ui.h
@@ -28,7 +28,7 @@ public:
void setupUi(QDialog *MyDialog)
{
if (MyDialog->objectName().isEmpty())
- MyDialog->setObjectName(QStringLiteral("MyDialog"));
+ MyDialog->setObjectName(QString::fromUtf8("MyDialog"));
MyDialog->resize(401, 70);
vboxLayout = new QVBoxLayout(MyDialog);
#ifndef Q_OS_MAC
@@ -37,14 +37,14 @@ public:
#ifndef Q_OS_MAC
vboxLayout->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
aLabel = new QLabel(MyDialog);
- aLabel->setObjectName(QStringLiteral("aLabel"));
+ aLabel->setObjectName(QString::fromUtf8("aLabel"));
vboxLayout->addWidget(aLabel);
aButton = new QPushButton(MyDialog);
- aButton->setObjectName(QStringLiteral("aButton"));
+ aButton->setObjectName(QString::fromUtf8("aButton"));
vboxLayout->addWidget(aButton);
diff --git a/tests/auto/tools/uic/baseline/myform.ui.h b/tests/auto/tools/uic/baseline/myform.ui.h
index d52c1ecf75..d3a08e04c9 100644
--- a/tests/auto/tools/uic/baseline/myform.ui.h
+++ b/tests/auto/tools/uic/baseline/myform.ui.h
@@ -41,35 +41,35 @@ public:
void setupUi(QWidget *Form)
{
if (Form->objectName().isEmpty())
- Form->setObjectName(QStringLiteral("Form"));
+ Form->setObjectName(QString::fromUtf8("Form"));
Form->resize(258, 224);
vboxLayout = new QVBoxLayout(Form);
#ifndef Q_OS_MAC
vboxLayout->setSpacing(6);
#endif
vboxLayout->setContentsMargins(8, 8, 8, 8);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
groupBox = new QGroupBox(Form);
- groupBox->setObjectName(QStringLiteral("groupBox"));
+ groupBox->setObjectName(QString::fromUtf8("groupBox"));
gridLayout = new QGridLayout(groupBox);
#ifndef Q_OS_MAC
gridLayout->setSpacing(6);
#endif
gridLayout->setContentsMargins(8, 8, 8, 8);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
radioButton_2 = new QRadioButton(groupBox);
- radioButton_2->setObjectName(QStringLiteral("radioButton_2"));
+ radioButton_2->setObjectName(QString::fromUtf8("radioButton_2"));
gridLayout->addWidget(radioButton_2, 1, 0, 1, 1);
radioButton = new QRadioButton(groupBox);
- radioButton->setObjectName(QStringLiteral("radioButton"));
+ radioButton->setObjectName(QString::fromUtf8("radioButton"));
radioButton->setChecked(true);
gridLayout->addWidget(radioButton, 0, 0, 1, 1);
checkBox_2 = new QCheckBox(groupBox);
- checkBox_2->setObjectName(QStringLiteral("checkBox_2"));
+ checkBox_2->setObjectName(QString::fromUtf8("checkBox_2"));
checkBox_2->setChecked(true);
gridLayout->addWidget(checkBox_2, 1, 1, 1, 1);
@@ -79,32 +79,32 @@ public:
gridLayout->addItem(spacerItem, 5, 0, 1, 1);
checkBox = new QCheckBox(groupBox);
- checkBox->setObjectName(QStringLiteral("checkBox"));
+ checkBox->setObjectName(QString::fromUtf8("checkBox"));
gridLayout->addWidget(checkBox, 0, 1, 1, 1);
radioButton_2_2 = new QRadioButton(groupBox);
- radioButton_2_2->setObjectName(QStringLiteral("radioButton_2_2"));
+ radioButton_2_2->setObjectName(QString::fromUtf8("radioButton_2_2"));
gridLayout->addWidget(radioButton_2_2, 2, 0, 1, 1);
radioButton_3 = new QRadioButton(groupBox);
- radioButton_3->setObjectName(QStringLiteral("radioButton_3"));
+ radioButton_3->setObjectName(QString::fromUtf8("radioButton_3"));
gridLayout->addWidget(radioButton_3, 3, 0, 1, 1);
radioButton_4 = new QRadioButton(groupBox);
- radioButton_4->setObjectName(QStringLiteral("radioButton_4"));
+ radioButton_4->setObjectName(QString::fromUtf8("radioButton_4"));
gridLayout->addWidget(radioButton_4, 4, 0, 1, 1);
checkBox_3 = new QCheckBox(groupBox);
- checkBox_3->setObjectName(QStringLiteral("checkBox_3"));
+ checkBox_3->setObjectName(QString::fromUtf8("checkBox_3"));
gridLayout->addWidget(checkBox_3, 2, 1, 1, 1);
checkBox_4 = new QCheckBox(groupBox);
- checkBox_4->setObjectName(QStringLiteral("checkBox_4"));
+ checkBox_4->setObjectName(QString::fromUtf8("checkBox_4"));
checkBox_4->setChecked(true);
gridLayout->addWidget(checkBox_4, 3, 1, 1, 1);
diff --git a/tests/auto/tools/uic/baseline/newactiondialog.ui.h b/tests/auto/tools/uic/baseline/newactiondialog.ui.h
index 993ff456b8..ca99ab8356 100644
--- a/tests/auto/tools/uic/baseline/newactiondialog.ui.h
+++ b/tests/auto/tools/uic/baseline/newactiondialog.ui.h
@@ -76,42 +76,42 @@ public:
void setupUi(QDialog *qdesigner_internal__NewActionDialog)
{
if (qdesigner_internal__NewActionDialog->objectName().isEmpty())
- qdesigner_internal__NewActionDialog->setObjectName(QStringLiteral("qdesigner_internal__NewActionDialog"));
+ qdesigner_internal__NewActionDialog->setObjectName(QString::fromUtf8("qdesigner_internal__NewActionDialog"));
qdesigner_internal__NewActionDialog->resize(363, 156);
verticalLayout = new QVBoxLayout(qdesigner_internal__NewActionDialog);
- verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
+ verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
formLayout = new QFormLayout();
- formLayout->setObjectName(QStringLiteral("formLayout"));
+ formLayout->setObjectName(QString::fromUtf8("formLayout"));
label = new QLabel(qdesigner_internal__NewActionDialog);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
formLayout->setWidget(0, QFormLayout::LabelRole, label);
editActionText = new QLineEdit(qdesigner_internal__NewActionDialog);
- editActionText->setObjectName(QStringLiteral("editActionText"));
+ editActionText->setObjectName(QString::fromUtf8("editActionText"));
editActionText->setMinimumSize(QSize(255, 0));
formLayout->setWidget(0, QFormLayout::FieldRole, editActionText);
label_3 = new QLabel(qdesigner_internal__NewActionDialog);
- label_3->setObjectName(QStringLiteral("label_3"));
+ label_3->setObjectName(QString::fromUtf8("label_3"));
formLayout->setWidget(1, QFormLayout::LabelRole, label_3);
editObjectName = new QLineEdit(qdesigner_internal__NewActionDialog);
- editObjectName->setObjectName(QStringLiteral("editObjectName"));
+ editObjectName->setObjectName(QString::fromUtf8("editObjectName"));
formLayout->setWidget(1, QFormLayout::FieldRole, editObjectName);
label_2 = new QLabel(qdesigner_internal__NewActionDialog);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
formLayout->setWidget(2, QFormLayout::LabelRole, label_2);
horizontalLayout = new QHBoxLayout();
- horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
+ horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
iconSelector = new qdesigner_internal::IconSelector(qdesigner_internal__NewActionDialog);
- iconSelector->setObjectName(QStringLiteral("iconSelector"));
+ iconSelector->setObjectName(QString::fromUtf8("iconSelector"));
horizontalLayout->addWidget(iconSelector);
@@ -130,14 +130,14 @@ public:
verticalLayout->addItem(verticalSpacer);
line = new QFrame(qdesigner_internal__NewActionDialog);
- line->setObjectName(QStringLiteral("line"));
+ line->setObjectName(QString::fromUtf8("line"));
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
verticalLayout->addWidget(line);
buttonBox = new QDialogButtonBox(qdesigner_internal__NewActionDialog);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
diff --git a/tests/auto/tools/uic/baseline/newdynamicpropertydialog.ui.h b/tests/auto/tools/uic/baseline/newdynamicpropertydialog.ui.h
index d0279cf21f..f5fd6f1fa4 100644
--- a/tests/auto/tools/uic/baseline/newdynamicpropertydialog.ui.h
+++ b/tests/auto/tools/uic/baseline/newdynamicpropertydialog.ui.h
@@ -42,20 +42,20 @@ public:
void setupUi(QDialog *qdesigner_internal__NewDynamicPropertyDialog)
{
if (qdesigner_internal__NewDynamicPropertyDialog->objectName().isEmpty())
- qdesigner_internal__NewDynamicPropertyDialog->setObjectName(QStringLiteral("qdesigner_internal__NewDynamicPropertyDialog"));
+ qdesigner_internal__NewDynamicPropertyDialog->setObjectName(QString::fromUtf8("qdesigner_internal__NewDynamicPropertyDialog"));
qdesigner_internal__NewDynamicPropertyDialog->resize(340, 118);
verticalLayout = new QVBoxLayout(qdesigner_internal__NewDynamicPropertyDialog);
- verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
+ verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
formLayout = new QFormLayout();
- formLayout->setObjectName(QStringLiteral("formLayout"));
+ formLayout->setObjectName(QString::fromUtf8("formLayout"));
m_lineEdit = new QLineEdit(qdesigner_internal__NewDynamicPropertyDialog);
- m_lineEdit->setObjectName(QStringLiteral("m_lineEdit"));
+ m_lineEdit->setObjectName(QString::fromUtf8("m_lineEdit"));
m_lineEdit->setMinimumSize(QSize(220, 0));
formLayout->setWidget(0, QFormLayout::FieldRole, m_lineEdit);
label = new QLabel(qdesigner_internal__NewDynamicPropertyDialog);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -65,9 +65,9 @@ public:
formLayout->setWidget(0, QFormLayout::LabelRole, label);
horizontalLayout = new QHBoxLayout();
- horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
+ horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
m_comboBox = new QComboBox(qdesigner_internal__NewDynamicPropertyDialog);
- m_comboBox->setObjectName(QStringLiteral("m_comboBox"));
+ m_comboBox->setObjectName(QString::fromUtf8("m_comboBox"));
horizontalLayout->addWidget(m_comboBox);
@@ -79,7 +79,7 @@ public:
formLayout->setLayout(1, QFormLayout::FieldRole, horizontalLayout);
label_2 = new QLabel(qdesigner_internal__NewDynamicPropertyDialog);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
sizePolicy.setHeightForWidth(label_2->sizePolicy().hasHeightForWidth());
label_2->setSizePolicy(sizePolicy);
@@ -93,7 +93,7 @@ public:
verticalLayout->addItem(spacerItem);
m_buttonBox = new QDialogButtonBox(qdesigner_internal__NewDynamicPropertyDialog);
- m_buttonBox->setObjectName(QStringLiteral("m_buttonBox"));
+ m_buttonBox->setObjectName(QString::fromUtf8("m_buttonBox"));
m_buttonBox->setOrientation(Qt::Horizontal);
m_buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
m_buttonBox->setCenterButtons(false);
diff --git a/tests/auto/tools/uic/baseline/newform.ui.h b/tests/auto/tools/uic/baseline/newform.ui.h
index 26da1b6fc2..80e70dcf66 100644
--- a/tests/auto/tools/uic/baseline/newform.ui.h
+++ b/tests/auto/tools/uic/baseline/newform.ui.h
@@ -67,7 +67,7 @@ public:
void setupUi(QDialog *NewForm)
{
if (NewForm->objectName().isEmpty())
- NewForm->setObjectName(QStringLiteral("NewForm"));
+ NewForm->setObjectName(QString::fromUtf8("NewForm"));
NewForm->resize(495, 319);
vboxLayout = new QVBoxLayout(NewForm);
#ifndef Q_OS_MAC
@@ -76,15 +76,15 @@ public:
#ifndef Q_OS_MAC
vboxLayout->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
hboxLayout = new QHBoxLayout();
#ifndef Q_OS_MAC
hboxLayout->setSpacing(6);
#endif
hboxLayout->setContentsMargins(1, 1, 1, 1);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
treeWidget = new QTreeWidget(NewForm);
- treeWidget->setObjectName(QStringLiteral("treeWidget"));
+ treeWidget->setObjectName(QString::fromUtf8("treeWidget"));
treeWidget->setIconSize(QSize(128, 128));
treeWidget->setRootIsDecorated(false);
treeWidget->setColumnCount(1);
@@ -92,7 +92,7 @@ public:
hboxLayout->addWidget(treeWidget);
lblPreview = new QLabel(NewForm);
- lblPreview->setObjectName(QStringLiteral("lblPreview"));
+ lblPreview->setObjectName(QString::fromUtf8("lblPreview"));
QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(7), static_cast<QSizePolicy::Policy>(5));
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -108,19 +108,19 @@ public:
vboxLayout->addLayout(hboxLayout);
horizontalLine = new QFrame(NewForm);
- horizontalLine->setObjectName(QStringLiteral("horizontalLine"));
+ horizontalLine->setObjectName(QString::fromUtf8("horizontalLine"));
horizontalLine->setFrameShape(QFrame::HLine);
horizontalLine->setFrameShadow(QFrame::Sunken);
vboxLayout->addWidget(horizontalLine);
chkShowOnStartup = new QCheckBox(NewForm);
- chkShowOnStartup->setObjectName(QStringLiteral("chkShowOnStartup"));
+ chkShowOnStartup->setObjectName(QString::fromUtf8("chkShowOnStartup"));
vboxLayout->addWidget(chkShowOnStartup);
buttonBox = new QDialogButtonBox(NewForm);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
vboxLayout->addWidget(buttonBox);
diff --git a/tests/auto/tools/uic/baseline/orderdialog.ui.h b/tests/auto/tools/uic/baseline/orderdialog.ui.h
index e2b9762510..0ee08257f4 100644
--- a/tests/auto/tools/uic/baseline/orderdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/orderdialog.ui.h
@@ -70,18 +70,18 @@ public:
void setupUi(QDialog *qdesigner_internal__OrderDialog)
{
if (qdesigner_internal__OrderDialog->objectName().isEmpty())
- qdesigner_internal__OrderDialog->setObjectName(QStringLiteral("qdesigner_internal__OrderDialog"));
+ qdesigner_internal__OrderDialog->setObjectName(QString::fromUtf8("qdesigner_internal__OrderDialog"));
qdesigner_internal__OrderDialog->resize(467, 310);
vboxLayout = new QVBoxLayout(qdesigner_internal__OrderDialog);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
groupBox = new QGroupBox(qdesigner_internal__OrderDialog);
- groupBox->setObjectName(QStringLiteral("groupBox"));
+ groupBox->setObjectName(QString::fromUtf8("groupBox"));
hboxLayout = new QHBoxLayout(groupBox);
hboxLayout->setSpacing(6);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
hboxLayout->setContentsMargins(9, 9, 9, 9);
pageList = new QListWidget(groupBox);
- pageList->setObjectName(QStringLiteral("pageList"));
+ pageList->setObjectName(QString::fromUtf8("pageList"));
pageList->setMinimumSize(QSize(344, 0));
pageList->setDragDropMode(QAbstractItemView::InternalMove);
pageList->setSelectionMode(QAbstractItemView::ContiguousSelection);
@@ -91,15 +91,15 @@ public:
vboxLayout1 = new QVBoxLayout();
vboxLayout1->setSpacing(6);
- vboxLayout1->setObjectName(QStringLiteral("vboxLayout1"));
+ vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
vboxLayout1->setContentsMargins(0, 0, 0, 0);
upButton = new QToolButton(groupBox);
- upButton->setObjectName(QStringLiteral("upButton"));
+ upButton->setObjectName(QString::fromUtf8("upButton"));
vboxLayout1->addWidget(upButton);
downButton = new QToolButton(groupBox);
- downButton->setObjectName(QStringLiteral("downButton"));
+ downButton->setObjectName(QString::fromUtf8("downButton"));
vboxLayout1->addWidget(downButton);
@@ -114,7 +114,7 @@ public:
vboxLayout->addWidget(groupBox);
buttonBox = new QDialogButtonBox(qdesigner_internal__OrderDialog);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Reset);
diff --git a/tests/auto/tools/uic/baseline/outputpage.ui.h b/tests/auto/tools/uic/baseline/outputpage.ui.h
index 1024ba1c19..00491bb3d8 100644
--- a/tests/auto/tools/uic/baseline/outputpage.ui.h
+++ b/tests/auto/tools/uic/baseline/outputpage.ui.h
@@ -33,16 +33,16 @@ public:
void setupUi(QWidget *OutputPage)
{
if (OutputPage->objectName().isEmpty())
- OutputPage->setObjectName(QStringLiteral("OutputPage"));
+ OutputPage->setObjectName(QString::fromUtf8("OutputPage"));
OutputPage->resize(417, 242);
gridLayout = new QGridLayout(OutputPage);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
spacerItem = new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Fixed);
gridLayout->addItem(spacerItem, 0, 1, 1, 1);
label = new QLabel(OutputPage);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -52,7 +52,7 @@ public:
gridLayout->addWidget(label, 1, 0, 1, 1);
projectLineEdit = new QLineEdit(OutputPage);
- projectLineEdit->setObjectName(QStringLiteral("projectLineEdit"));
+ projectLineEdit->setObjectName(QString::fromUtf8("projectLineEdit"));
QSizePolicy sizePolicy1(QSizePolicy::Expanding, QSizePolicy::Fixed);
sizePolicy1.setHorizontalStretch(0);
sizePolicy1.setVerticalStretch(0);
@@ -62,14 +62,14 @@ public:
gridLayout->addWidget(projectLineEdit, 1, 1, 1, 1);
label_2 = new QLabel(OutputPage);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
sizePolicy.setHeightForWidth(label_2->sizePolicy().hasHeightForWidth());
label_2->setSizePolicy(sizePolicy);
gridLayout->addWidget(label_2, 2, 0, 1, 1);
collectionLineEdit = new QLineEdit(OutputPage);
- collectionLineEdit->setObjectName(QStringLiteral("collectionLineEdit"));
+ collectionLineEdit->setObjectName(QString::fromUtf8("collectionLineEdit"));
sizePolicy1.setHeightForWidth(collectionLineEdit->sizePolicy().hasHeightForWidth());
collectionLineEdit->setSizePolicy(sizePolicy1);
diff --git a/tests/auto/tools/uic/baseline/pagefold.ui.h b/tests/auto/tools/uic/baseline/pagefold.ui.h
index c0ec214e85..c1ff03648d 100644
--- a/tests/auto/tools/uic/baseline/pagefold.ui.h
+++ b/tests/auto/tools/uic/baseline/pagefold.ui.h
@@ -67,18 +67,18 @@ public:
void setupUi(QMainWindow *MainWindow)
{
if (MainWindow->objectName().isEmpty())
- MainWindow->setObjectName(QStringLiteral("MainWindow"));
+ MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
MainWindow->resize(392, 412);
exitAction = new QAction(MainWindow);
- exitAction->setObjectName(QStringLiteral("exitAction"));
+ exitAction->setObjectName(QString::fromUtf8("exitAction"));
aboutQtAction = new QAction(MainWindow);
- aboutQtAction->setObjectName(QStringLiteral("aboutQtAction"));
+ aboutQtAction->setObjectName(QString::fromUtf8("aboutQtAction"));
editStyleAction = new QAction(MainWindow);
- editStyleAction->setObjectName(QStringLiteral("editStyleAction"));
+ editStyleAction->setObjectName(QString::fromUtf8("editStyleAction"));
aboutAction = new QAction(MainWindow);
- aboutAction->setObjectName(QStringLiteral("aboutAction"));
+ aboutAction->setObjectName(QString::fromUtf8("aboutAction"));
centralwidget = new QWidget(MainWindow);
- centralwidget->setObjectName(QStringLiteral("centralwidget"));
+ centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
vboxLayout = new QVBoxLayout(centralwidget);
#ifndef Q_OS_MAC
vboxLayout->setSpacing(6);
@@ -86,9 +86,9 @@ public:
#ifndef Q_OS_MAC
vboxLayout->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
mainFrame = new QFrame(centralwidget);
- mainFrame->setObjectName(QStringLiteral("mainFrame"));
+ mainFrame->setObjectName(QString::fromUtf8("mainFrame"));
mainFrame->setFrameShape(QFrame::StyledPanel);
mainFrame->setFrameShadow(QFrame::Raised);
gridLayout = new QGridLayout(mainFrame);
@@ -98,13 +98,13 @@ public:
#ifndef Q_OS_MAC
gridLayout->setContentsMargins(9, 9, 9, 9);
#endif
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
nameCombo = new QComboBox(mainFrame);
nameCombo->addItem(QString());
nameCombo->addItem(QString());
nameCombo->addItem(QString());
nameCombo->addItem(QString());
- nameCombo->setObjectName(QStringLiteral("nameCombo"));
+ nameCombo->setObjectName(QString::fromUtf8("nameCombo"));
nameCombo->setEditable(true);
gridLayout->addWidget(nameCombo, 0, 1, 1, 3);
@@ -114,56 +114,56 @@ public:
gridLayout->addItem(spacerItem, 1, 3, 1, 1);
femaleRadioButton = new QRadioButton(mainFrame);
- femaleRadioButton->setObjectName(QStringLiteral("femaleRadioButton"));
+ femaleRadioButton->setObjectName(QString::fromUtf8("femaleRadioButton"));
gridLayout->addWidget(femaleRadioButton, 1, 2, 1, 1);
genderLabel = new QLabel(mainFrame);
- genderLabel->setObjectName(QStringLiteral("genderLabel"));
+ genderLabel->setObjectName(QString::fromUtf8("genderLabel"));
gridLayout->addWidget(genderLabel, 1, 0, 1, 1);
ageLabel = new QLabel(mainFrame);
- ageLabel->setObjectName(QStringLiteral("ageLabel"));
+ ageLabel->setObjectName(QString::fromUtf8("ageLabel"));
gridLayout->addWidget(ageLabel, 2, 0, 1, 1);
maleRadioButton = new QRadioButton(mainFrame);
- maleRadioButton->setObjectName(QStringLiteral("maleRadioButton"));
+ maleRadioButton->setObjectName(QString::fromUtf8("maleRadioButton"));
gridLayout->addWidget(maleRadioButton, 1, 1, 1, 1);
nameLabel = new QLabel(mainFrame);
- nameLabel->setObjectName(QStringLiteral("nameLabel"));
+ nameLabel->setObjectName(QString::fromUtf8("nameLabel"));
gridLayout->addWidget(nameLabel, 0, 0, 1, 1);
passwordLabel = new QLabel(mainFrame);
- passwordLabel->setObjectName(QStringLiteral("passwordLabel"));
+ passwordLabel->setObjectName(QString::fromUtf8("passwordLabel"));
gridLayout->addWidget(passwordLabel, 3, 0, 1, 1);
ageSpinBox = new QSpinBox(mainFrame);
- ageSpinBox->setObjectName(QStringLiteral("ageSpinBox"));
+ ageSpinBox->setObjectName(QString::fromUtf8("ageSpinBox"));
ageSpinBox->setMinimum(12);
ageSpinBox->setValue(22);
gridLayout->addWidget(ageSpinBox, 2, 1, 1, 3);
buttonBox = new QDialogButtonBox(mainFrame);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok);
gridLayout->addWidget(buttonBox, 7, 2, 1, 2);
agreeCheckBox = new QCheckBox(mainFrame);
- agreeCheckBox->setObjectName(QStringLiteral("agreeCheckBox"));
+ agreeCheckBox->setObjectName(QString::fromUtf8("agreeCheckBox"));
gridLayout->addWidget(agreeCheckBox, 6, 0, 1, 4);
passwordEdit = new QLineEdit(mainFrame);
- passwordEdit->setObjectName(QStringLiteral("passwordEdit"));
+ passwordEdit->setObjectName(QString::fromUtf8("passwordEdit"));
passwordEdit->setEchoMode(QLineEdit::Password);
gridLayout->addWidget(passwordEdit, 3, 1, 1, 3);
@@ -172,12 +172,12 @@ public:
new QListWidgetItem(professionList);
new QListWidgetItem(professionList);
new QListWidgetItem(professionList);
- professionList->setObjectName(QStringLiteral("professionList"));
+ professionList->setObjectName(QString::fromUtf8("professionList"));
gridLayout->addWidget(professionList, 5, 1, 1, 3);
label = new QLabel(mainFrame);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
gridLayout->addWidget(label, 5, 0, 1, 1);
@@ -189,12 +189,12 @@ public:
countryCombo->addItem(QString());
countryCombo->addItem(QString());
countryCombo->addItem(QString());
- countryCombo->setObjectName(QStringLiteral("countryCombo"));
+ countryCombo->setObjectName(QString::fromUtf8("countryCombo"));
gridLayout->addWidget(countryCombo, 4, 1, 1, 3);
countryLabel = new QLabel(mainFrame);
- countryLabel->setObjectName(QStringLiteral("countryLabel"));
+ countryLabel->setObjectName(QString::fromUtf8("countryLabel"));
gridLayout->addWidget(countryLabel, 4, 0, 1, 1);
@@ -203,15 +203,15 @@ public:
MainWindow->setCentralWidget(centralwidget);
menubar = new QMenuBar(MainWindow);
- menubar->setObjectName(QStringLiteral("menubar"));
+ menubar->setObjectName(QString::fromUtf8("menubar"));
menubar->setGeometry(QRect(0, 0, 392, 25));
menu_File = new QMenu(menubar);
- menu_File->setObjectName(QStringLiteral("menu_File"));
+ menu_File->setObjectName(QString::fromUtf8("menu_File"));
menu_Help = new QMenu(menubar);
- menu_Help->setObjectName(QStringLiteral("menu_Help"));
+ menu_Help->setObjectName(QString::fromUtf8("menu_Help"));
MainWindow->setMenuBar(menubar);
statusbar = new QStatusBar(MainWindow);
- statusbar->setObjectName(QStringLiteral("statusbar"));
+ statusbar->setObjectName(QString::fromUtf8("statusbar"));
MainWindow->setStatusBar(statusbar);
#ifndef QT_NO_SHORTCUT
ageLabel->setBuddy(ageSpinBox);
diff --git a/tests/auto/tools/uic/baseline/paletteeditor.ui.h b/tests/auto/tools/uic/baseline/paletteeditor.ui.h
index 3ccdf6082d..0061164960 100644
--- a/tests/auto/tools/uic/baseline/paletteeditor.ui.h
+++ b/tests/auto/tools/uic/baseline/paletteeditor.ui.h
@@ -79,7 +79,7 @@ public:
void setupUi(QDialog *qdesigner_internal__PaletteEditor)
{
if (qdesigner_internal__PaletteEditor->objectName().isEmpty())
- qdesigner_internal__PaletteEditor->setObjectName(QStringLiteral("qdesigner_internal__PaletteEditor"));
+ qdesigner_internal__PaletteEditor->setObjectName(QString::fromUtf8("qdesigner_internal__PaletteEditor"));
qdesigner_internal__PaletteEditor->resize(365, 409);
QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(7), static_cast<QSizePolicy::Policy>(7));
sizePolicy.setHorizontalStretch(0);
@@ -93,9 +93,9 @@ public:
#ifndef Q_OS_MAC
vboxLayout->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
advancedBox = new QGroupBox(qdesigner_internal__PaletteEditor);
- advancedBox->setObjectName(QStringLiteral("advancedBox"));
+ advancedBox->setObjectName(QString::fromUtf8("advancedBox"));
advancedBox->setMinimumSize(QSize(0, 0));
advancedBox->setMaximumSize(QSize(16777215, 16777215));
gridLayout = new QGridLayout(advancedBox);
@@ -105,9 +105,9 @@ public:
#ifndef Q_OS_MAC
gridLayout->setContentsMargins(9, 9, 9, 9);
#endif
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
buildButton = new QtColorButton(advancedBox);
- buildButton->setObjectName(QStringLiteral("buildButton"));
+ buildButton->setObjectName(QString::fromUtf8("buildButton"));
QSizePolicy sizePolicy1(static_cast<QSizePolicy::Policy>(7), static_cast<QSizePolicy::Policy>(13));
sizePolicy1.setHorizontalStretch(0);
sizePolicy1.setVerticalStretch(0);
@@ -117,24 +117,24 @@ public:
gridLayout->addWidget(buildButton, 0, 1, 1, 1);
paletteView = new QTreeView(advancedBox);
- paletteView->setObjectName(QStringLiteral("paletteView"));
+ paletteView->setObjectName(QString::fromUtf8("paletteView"));
paletteView->setMinimumSize(QSize(0, 200));
gridLayout->addWidget(paletteView, 1, 0, 1, 4);
detailsRadio = new QRadioButton(advancedBox);
- detailsRadio->setObjectName(QStringLiteral("detailsRadio"));
+ detailsRadio->setObjectName(QString::fromUtf8("detailsRadio"));
gridLayout->addWidget(detailsRadio, 0, 3, 1, 1);
computeRadio = new QRadioButton(advancedBox);
- computeRadio->setObjectName(QStringLiteral("computeRadio"));
+ computeRadio->setObjectName(QString::fromUtf8("computeRadio"));
computeRadio->setChecked(true);
gridLayout->addWidget(computeRadio, 0, 2, 1, 1);
label = new QLabel(advancedBox);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
gridLayout->addWidget(label, 0, 0, 1, 1);
@@ -142,7 +142,7 @@ public:
vboxLayout->addWidget(advancedBox);
GroupBox126 = new QGroupBox(qdesigner_internal__PaletteEditor);
- GroupBox126->setObjectName(QStringLiteral("GroupBox126"));
+ GroupBox126->setObjectName(QString::fromUtf8("GroupBox126"));
QSizePolicy sizePolicy2(static_cast<QSizePolicy::Policy>(5), static_cast<QSizePolicy::Policy>(7));
sizePolicy2.setHorizontalStretch(0);
sizePolicy2.setVerticalStretch(0);
@@ -153,25 +153,25 @@ public:
gridLayout1->setSpacing(6);
#endif
gridLayout1->setContentsMargins(8, 8, 8, 8);
- gridLayout1->setObjectName(QStringLiteral("gridLayout1"));
+ gridLayout1->setObjectName(QString::fromUtf8("gridLayout1"));
disabledRadio = new QRadioButton(GroupBox126);
- disabledRadio->setObjectName(QStringLiteral("disabledRadio"));
+ disabledRadio->setObjectName(QString::fromUtf8("disabledRadio"));
gridLayout1->addWidget(disabledRadio, 0, 2, 1, 1);
inactiveRadio = new QRadioButton(GroupBox126);
- inactiveRadio->setObjectName(QStringLiteral("inactiveRadio"));
+ inactiveRadio->setObjectName(QString::fromUtf8("inactiveRadio"));
gridLayout1->addWidget(inactiveRadio, 0, 1, 1, 1);
activeRadio = new QRadioButton(GroupBox126);
- activeRadio->setObjectName(QStringLiteral("activeRadio"));
+ activeRadio->setObjectName(QString::fromUtf8("activeRadio"));
activeRadio->setChecked(true);
gridLayout1->addWidget(activeRadio, 0, 0, 1, 1);
previewFrame = new qdesigner_internal::PreviewFrame(GroupBox126);
- previewFrame->setObjectName(QStringLiteral("previewFrame"));
+ previewFrame->setObjectName(QString::fromUtf8("previewFrame"));
sizePolicy.setHeightForWidth(previewFrame->sizePolicy().hasHeightForWidth());
previewFrame->setSizePolicy(sizePolicy);
@@ -181,7 +181,7 @@ public:
vboxLayout->addWidget(GroupBox126);
buttonBox = new QDialogButtonBox(qdesigner_internal__PaletteEditor);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok);
diff --git a/tests/auto/tools/uic/baseline/passworddialog.ui.h b/tests/auto/tools/uic/baseline/passworddialog.ui.h
index d47835b57b..9ab95c4de9 100644
--- a/tests/auto/tools/uic/baseline/passworddialog.ui.h
+++ b/tests/auto/tools/uic/baseline/passworddialog.ui.h
@@ -36,19 +36,19 @@ public:
void setupUi(QDialog *PasswordDialog)
{
if (PasswordDialog->objectName().isEmpty())
- PasswordDialog->setObjectName(QStringLiteral("PasswordDialog"));
+ PasswordDialog->setObjectName(QString::fromUtf8("PasswordDialog"));
PasswordDialog->resize(399, 148);
gridLayout = new QGridLayout(PasswordDialog);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
hboxLayout = new QHBoxLayout();
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
iconLabel = new QLabel(PasswordDialog);
- iconLabel->setObjectName(QStringLiteral("iconLabel"));
+ iconLabel->setObjectName(QString::fromUtf8("iconLabel"));
hboxLayout->addWidget(iconLabel);
introLabel = new QLabel(PasswordDialog);
- introLabel->setObjectName(QStringLiteral("introLabel"));
+ introLabel->setObjectName(QString::fromUtf8("introLabel"));
QSizePolicy sizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -61,28 +61,28 @@ public:
gridLayout->addLayout(hboxLayout, 0, 0, 1, 2);
label = new QLabel(PasswordDialog);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
gridLayout->addWidget(label, 1, 0, 1, 1);
userNameLineEdit = new QLineEdit(PasswordDialog);
- userNameLineEdit->setObjectName(QStringLiteral("userNameLineEdit"));
+ userNameLineEdit->setObjectName(QString::fromUtf8("userNameLineEdit"));
gridLayout->addWidget(userNameLineEdit, 1, 1, 1, 1);
lblPassword = new QLabel(PasswordDialog);
- lblPassword->setObjectName(QStringLiteral("lblPassword"));
+ lblPassword->setObjectName(QString::fromUtf8("lblPassword"));
gridLayout->addWidget(lblPassword, 2, 0, 1, 1);
passwordLineEdit = new QLineEdit(PasswordDialog);
- passwordLineEdit->setObjectName(QStringLiteral("passwordLineEdit"));
+ passwordLineEdit->setObjectName(QString::fromUtf8("passwordLineEdit"));
passwordLineEdit->setEchoMode(QLineEdit::Password);
gridLayout->addWidget(passwordLineEdit, 2, 1, 1, 1);
buttonBox = new QDialogButtonBox(PasswordDialog);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
diff --git a/tests/auto/tools/uic/baseline/pathpage.ui.h b/tests/auto/tools/uic/baseline/pathpage.ui.h
index 361831721b..eb151f9550 100644
--- a/tests/auto/tools/uic/baseline/pathpage.ui.h
+++ b/tests/auto/tools/uic/baseline/pathpage.ui.h
@@ -38,12 +38,12 @@ public:
void setupUi(QWidget *PathPage)
{
if (PathPage->objectName().isEmpty())
- PathPage->setObjectName(QStringLiteral("PathPage"));
+ PathPage->setObjectName(QString::fromUtf8("PathPage"));
PathPage->resize(417, 243);
gridLayout = new QGridLayout(PathPage);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
label_2 = new QLabel(PathPage);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
QSizePolicy sizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -53,7 +53,7 @@ public:
gridLayout->addWidget(label_2, 0, 0, 1, 1);
filterLineEdit = new QLineEdit(PathPage);
- filterLineEdit->setObjectName(QStringLiteral("filterLineEdit"));
+ filterLineEdit->setObjectName(QString::fromUtf8("filterLineEdit"));
gridLayout->addWidget(filterLineEdit, 0, 1, 1, 2);
@@ -62,17 +62,17 @@ public:
gridLayout->addItem(spacerItem, 1, 1, 1, 1);
label = new QLabel(PathPage);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
gridLayout->addWidget(label, 2, 0, 1, 3);
pathListWidget = new QListWidget(PathPage);
- pathListWidget->setObjectName(QStringLiteral("pathListWidget"));
+ pathListWidget->setObjectName(QString::fromUtf8("pathListWidget"));
gridLayout->addWidget(pathListWidget, 3, 0, 3, 3);
addButton = new QPushButton(PathPage);
- addButton->setObjectName(QStringLiteral("addButton"));
+ addButton->setObjectName(QString::fromUtf8("addButton"));
QSizePolicy sizePolicy1(QSizePolicy::Maximum, QSizePolicy::Fixed);
sizePolicy1.setHorizontalStretch(0);
sizePolicy1.setVerticalStretch(0);
@@ -82,7 +82,7 @@ public:
gridLayout->addWidget(addButton, 3, 3, 1, 1);
removeButton = new QPushButton(PathPage);
- removeButton->setObjectName(QStringLiteral("removeButton"));
+ removeButton->setObjectName(QString::fromUtf8("removeButton"));
sizePolicy1.setHeightForWidth(removeButton->sizePolicy().hasHeightForWidth());
removeButton->setSizePolicy(sizePolicy1);
diff --git a/tests/auto/tools/uic/baseline/phrasebookbox.ui.h b/tests/auto/tools/uic/baseline/phrasebookbox.ui.h
index e41a7061b4..27a0fa79ed 100644
--- a/tests/auto/tools/uic/baseline/phrasebookbox.ui.h
+++ b/tests/auto/tools/uic/baseline/phrasebookbox.ui.h
@@ -77,45 +77,45 @@ public:
void setupUi(QDialog *PhraseBookBox)
{
if (PhraseBookBox->objectName().isEmpty())
- PhraseBookBox->setObjectName(QStringLiteral("PhraseBookBox"));
+ PhraseBookBox->setObjectName(QString::fromUtf8("PhraseBookBox"));
PhraseBookBox->resize(596, 454);
unnamed = new QHBoxLayout(PhraseBookBox);
unnamed->setSpacing(6);
unnamed->setContentsMargins(11, 11, 11, 11);
- unnamed->setObjectName(QStringLiteral("unnamed"));
+ unnamed->setObjectName(QString::fromUtf8("unnamed"));
inputsLayout = new QVBoxLayout();
inputsLayout->setSpacing(6);
- inputsLayout->setObjectName(QStringLiteral("inputsLayout"));
+ inputsLayout->setObjectName(QString::fromUtf8("inputsLayout"));
gridLayout = new QGridLayout();
gridLayout->setSpacing(6);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
target = new QLabel(PhraseBookBox);
- target->setObjectName(QStringLiteral("target"));
+ target->setObjectName(QString::fromUtf8("target"));
gridLayout->addWidget(target, 1, 0, 1, 1);
targetLed = new QLineEdit(PhraseBookBox);
- targetLed->setObjectName(QStringLiteral("targetLed"));
+ targetLed->setObjectName(QString::fromUtf8("targetLed"));
gridLayout->addWidget(targetLed, 1, 1, 1, 1);
source = new QLabel(PhraseBookBox);
- source->setObjectName(QStringLiteral("source"));
+ source->setObjectName(QString::fromUtf8("source"));
gridLayout->addWidget(source, 0, 0, 1, 1);
definitionLed = new QLineEdit(PhraseBookBox);
- definitionLed->setObjectName(QStringLiteral("definitionLed"));
+ definitionLed->setObjectName(QString::fromUtf8("definitionLed"));
gridLayout->addWidget(definitionLed, 2, 1, 1, 1);
sourceLed = new QLineEdit(PhraseBookBox);
- sourceLed->setObjectName(QStringLiteral("sourceLed"));
+ sourceLed->setObjectName(QString::fromUtf8("sourceLed"));
gridLayout->addWidget(sourceLed, 0, 1, 1, 1);
definition = new QLabel(PhraseBookBox);
- definition->setObjectName(QStringLiteral("definition"));
+ definition->setObjectName(QString::fromUtf8("definition"));
gridLayout->addWidget(definition, 2, 0, 1, 1);
@@ -123,7 +123,7 @@ public:
inputsLayout->addLayout(gridLayout);
phraseList = new QTreeView(PhraseBookBox);
- phraseList->setObjectName(QStringLiteral("phraseList"));
+ phraseList->setObjectName(QString::fromUtf8("phraseList"));
phraseList->setRootIsDecorated(false);
phraseList->setUniformRowHeights(true);
phraseList->setItemsExpandable(false);
@@ -137,24 +137,24 @@ public:
buttonLayout = new QVBoxLayout();
buttonLayout->setSpacing(6);
- buttonLayout->setObjectName(QStringLiteral("buttonLayout"));
+ buttonLayout->setObjectName(QString::fromUtf8("buttonLayout"));
newBut = new QPushButton(PhraseBookBox);
- newBut->setObjectName(QStringLiteral("newBut"));
+ newBut->setObjectName(QString::fromUtf8("newBut"));
buttonLayout->addWidget(newBut);
removeBut = new QPushButton(PhraseBookBox);
- removeBut->setObjectName(QStringLiteral("removeBut"));
+ removeBut->setObjectName(QString::fromUtf8("removeBut"));
buttonLayout->addWidget(removeBut);
saveBut = new QPushButton(PhraseBookBox);
- saveBut->setObjectName(QStringLiteral("saveBut"));
+ saveBut->setObjectName(QString::fromUtf8("saveBut"));
buttonLayout->addWidget(saveBut);
closeBut = new QPushButton(PhraseBookBox);
- closeBut->setObjectName(QStringLiteral("closeBut"));
+ closeBut->setObjectName(QString::fromUtf8("closeBut"));
buttonLayout->addWidget(closeBut);
diff --git a/tests/auto/tools/uic/baseline/pixmapfunction.ui b/tests/auto/tools/uic/baseline/pixmapfunction.ui
new file mode 100644
index 0000000000..8edafc7248
--- /dev/null
+++ b/tests/auto/tools/uic/baseline/pixmapfunction.ui
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>149</width>
+ <height>112</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string/>
+ </property>
+ <property name="pixmap">
+ <pixmap>labelPixmap</pixmap>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButton">
+ <property name="text">
+ <string>PushButton</string>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>buttonIconNormalOff</normaloff>
+ <normalon>buttonIconNormalOn</normalon>
+ <disabledoff>buttonIconDisabledOff</disabledoff>
+ <disabledon>buttonIconDisabledOn</disabledon>
+ </iconset>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <pixmapfunction>pixmapFunction</pixmapfunction>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/tests/auto/tools/uic/baseline/pixmapfunction.ui.h b/tests/auto/tools/uic/baseline/pixmapfunction.ui.h
new file mode 100644
index 0000000000..1644380c15
--- /dev/null
+++ b/tests/auto/tools/uic/baseline/pixmapfunction.ui.h
@@ -0,0 +1,74 @@
+/********************************************************************************
+** Form generated from reading UI file 'pixmapfunction.ui'
+**
+** Created by: Qt User Interface Compiler version 5.12.0
+**
+** WARNING! All changes made in this file will be lost when recompiling UI file!
+********************************************************************************/
+
+#ifndef PIXMAPFUNCTION_H
+#define PIXMAPFUNCTION_H
+
+#include <QtCore/QVariant>
+#include <QtGui/QIcon>
+#include <QtWidgets/QApplication>
+#include <QtWidgets/QLabel>
+#include <QtWidgets/QPushButton>
+#include <QtWidgets/QVBoxLayout>
+#include <QtWidgets/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class Ui_Form
+{
+public:
+ QVBoxLayout *verticalLayout;
+ QLabel *label;
+ QPushButton *pushButton;
+
+ void setupUi(QWidget *Form)
+ {
+ if (Form->objectName().isEmpty())
+ Form->setObjectName(QString::fromUtf8("Form"));
+ Form->resize(149, 112);
+ verticalLayout = new QVBoxLayout(Form);
+ verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
+ label = new QLabel(Form);
+ label->setObjectName(QString::fromUtf8("label"));
+ label->setPixmap(QPixmap(pixmapFunction("labelPixmap")));
+
+ verticalLayout->addWidget(label);
+
+ pushButton = new QPushButton(Form);
+ pushButton->setObjectName(QString::fromUtf8("pushButton"));
+ QIcon icon;
+ icon.addPixmap(QPixmap(pixmapFunction("buttonIconNormalOff")), QIcon::Normal, QIcon::Off);
+ icon.addPixmap(QPixmap(pixmapFunction("buttonIconNormalOn")), QIcon::Normal, QIcon::On);
+ icon.addPixmap(QPixmap(pixmapFunction("buttonIconDisabledOff")), QIcon::Disabled, QIcon::Off);
+ icon.addPixmap(QPixmap(pixmapFunction("buttonIconDisabledOn")), QIcon::Disabled, QIcon::On);
+ pushButton->setIcon(icon);
+
+ verticalLayout->addWidget(pushButton);
+
+
+ retranslateUi(Form);
+
+ QMetaObject::connectSlotsByName(Form);
+ } // setupUi
+
+ void retranslateUi(QWidget *Form)
+ {
+ Form->setWindowTitle(QApplication::translate("Form", "Form", nullptr));
+ label->setText(QString());
+ pushButton->setText(QApplication::translate("Form", "PushButton", nullptr));
+ } // retranslateUi
+
+};
+
+namespace Ui {
+ class Form: public Ui_Form {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // PIXMAPFUNCTION_H
diff --git a/tests/auto/tools/uic/baseline/plugindialog.ui.h b/tests/auto/tools/uic/baseline/plugindialog.ui.h
index 30256a35c2..3634b8436f 100644
--- a/tests/auto/tools/uic/baseline/plugindialog.ui.h
+++ b/tests/auto/tools/uic/baseline/plugindialog.ui.h
@@ -64,39 +64,39 @@ public:
void setupUi(QDialog *PluginDialog)
{
if (PluginDialog->objectName().isEmpty())
- PluginDialog->setObjectName(QStringLiteral("PluginDialog"));
+ PluginDialog->setObjectName(QString::fromUtf8("PluginDialog"));
PluginDialog->resize(401, 331);
vboxLayout = new QVBoxLayout(PluginDialog);
vboxLayout->setSpacing(6);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
vboxLayout->setContentsMargins(8, 8, 8, 8);
label = new QLabel(PluginDialog);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
label->setWordWrap(true);
vboxLayout->addWidget(label);
treeWidget = new QTreeWidget(PluginDialog);
- treeWidget->setObjectName(QStringLiteral("treeWidget"));
+ treeWidget->setObjectName(QString::fromUtf8("treeWidget"));
treeWidget->setTextElideMode(Qt::ElideNone);
vboxLayout->addWidget(treeWidget);
message = new QLabel(PluginDialog);
- message->setObjectName(QStringLiteral("message"));
+ message->setObjectName(QString::fromUtf8("message"));
message->setWordWrap(true);
vboxLayout->addWidget(message);
hboxLayout = new QHBoxLayout();
hboxLayout->setSpacing(6);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
hboxLayout->setContentsMargins(0, 0, 0, 0);
vboxLayout->addLayout(hboxLayout);
buttonBox = new QDialogButtonBox(PluginDialog);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Close);
diff --git a/tests/auto/tools/uic/baseline/preferencesdialog.ui.h b/tests/auto/tools/uic/baseline/preferencesdialog.ui.h
index 15761b2cdc..289e6775b4 100644
--- a/tests/auto/tools/uic/baseline/preferencesdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/preferencesdialog.ui.h
@@ -53,21 +53,21 @@ public:
void setupUi(QDialog *PreferencesDialog)
{
if (PreferencesDialog->objectName().isEmpty())
- PreferencesDialog->setObjectName(QStringLiteral("PreferencesDialog"));
+ PreferencesDialog->setObjectName(QString::fromUtf8("PreferencesDialog"));
PreferencesDialog->resize(455, 359);
PreferencesDialog->setModal(true);
vboxLayout = new QVBoxLayout(PreferencesDialog);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
hboxLayout = new QHBoxLayout();
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
vboxLayout1 = new QVBoxLayout();
- vboxLayout1->setObjectName(QStringLiteral("vboxLayout1"));
+ vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
m_uiModeGroupBox = new QGroupBox(PreferencesDialog);
- m_uiModeGroupBox->setObjectName(QStringLiteral("m_uiModeGroupBox"));
+ m_uiModeGroupBox->setObjectName(QString::fromUtf8("m_uiModeGroupBox"));
vboxLayout2 = new QVBoxLayout(m_uiModeGroupBox);
- vboxLayout2->setObjectName(QStringLiteral("vboxLayout2"));
+ vboxLayout2->setObjectName(QString::fromUtf8("vboxLayout2"));
m_uiModeCombo = new QComboBox(m_uiModeGroupBox);
- m_uiModeCombo->setObjectName(QStringLiteral("m_uiModeCombo"));
+ m_uiModeCombo->setObjectName(QString::fromUtf8("m_uiModeCombo"));
vboxLayout2->addWidget(m_uiModeCombo);
@@ -75,12 +75,12 @@ public:
vboxLayout1->addWidget(m_uiModeGroupBox);
m_fontPanel = new FontPanel(PreferencesDialog);
- m_fontPanel->setObjectName(QStringLiteral("m_fontPanel"));
+ m_fontPanel->setObjectName(QString::fromUtf8("m_fontPanel"));
vboxLayout1->addWidget(m_fontPanel);
m_previewConfigurationWidget = new qdesigner_internal::PreviewConfigurationWidget(PreferencesDialog);
- m_previewConfigurationWidget->setObjectName(QStringLiteral("m_previewConfigurationWidget"));
+ m_previewConfigurationWidget->setObjectName(QString::fromUtf8("m_previewConfigurationWidget"));
vboxLayout1->addWidget(m_previewConfigurationWidget);
@@ -88,23 +88,23 @@ public:
hboxLayout->addLayout(vboxLayout1);
vboxLayout3 = new QVBoxLayout();
- vboxLayout3->setObjectName(QStringLiteral("vboxLayout3"));
+ vboxLayout3->setObjectName(QString::fromUtf8("vboxLayout3"));
m_templatePathGroupBox = new QGroupBox(PreferencesDialog);
- m_templatePathGroupBox->setObjectName(QStringLiteral("m_templatePathGroupBox"));
+ m_templatePathGroupBox->setObjectName(QString::fromUtf8("m_templatePathGroupBox"));
gridLayout = new QGridLayout(m_templatePathGroupBox);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
m_templatePathListWidget = new QListWidget(m_templatePathGroupBox);
- m_templatePathListWidget->setObjectName(QStringLiteral("m_templatePathListWidget"));
+ m_templatePathListWidget->setObjectName(QString::fromUtf8("m_templatePathListWidget"));
gridLayout->addWidget(m_templatePathListWidget, 0, 0, 1, 3);
m_addTemplatePathButton = new QToolButton(m_templatePathGroupBox);
- m_addTemplatePathButton->setObjectName(QStringLiteral("m_addTemplatePathButton"));
+ m_addTemplatePathButton->setObjectName(QString::fromUtf8("m_addTemplatePathButton"));
gridLayout->addWidget(m_addTemplatePathButton, 1, 0, 1, 1);
m_removeTemplatePathButton = new QToolButton(m_templatePathGroupBox);
- m_removeTemplatePathButton->setObjectName(QStringLiteral("m_removeTemplatePathButton"));
+ m_removeTemplatePathButton->setObjectName(QString::fromUtf8("m_removeTemplatePathButton"));
gridLayout->addWidget(m_removeTemplatePathButton, 1, 1, 1, 1);
@@ -116,7 +116,7 @@ public:
vboxLayout3->addWidget(m_templatePathGroupBox);
m_gridPanel = new qdesigner_internal::GridPanel(PreferencesDialog);
- m_gridPanel->setObjectName(QStringLiteral("m_gridPanel"));
+ m_gridPanel->setObjectName(QString::fromUtf8("m_gridPanel"));
vboxLayout3->addWidget(m_gridPanel);
@@ -127,14 +127,14 @@ public:
vboxLayout->addLayout(hboxLayout);
line = new QFrame(PreferencesDialog);
- line->setObjectName(QStringLiteral("line"));
+ line->setObjectName(QString::fromUtf8("line"));
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
vboxLayout->addWidget(line);
m_dialogButtonBox = new QDialogButtonBox(PreferencesDialog);
- m_dialogButtonBox->setObjectName(QStringLiteral("m_dialogButtonBox"));
+ m_dialogButtonBox->setObjectName(QString::fromUtf8("m_dialogButtonBox"));
m_dialogButtonBox->setOrientation(Qt::Horizontal);
m_dialogButtonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
diff --git a/tests/auto/tools/uic/baseline/previewconfigurationwidget.ui.h b/tests/auto/tools/uic/baseline/previewconfigurationwidget.ui.h
index 60bf65af45..3c729b9c65 100644
--- a/tests/auto/tools/uic/baseline/previewconfigurationwidget.ui.h
+++ b/tests/auto/tools/uic/baseline/previewconfigurationwidget.ui.h
@@ -40,40 +40,40 @@ public:
void setupUi(QGroupBox *PreviewConfigurationWidget)
{
if (PreviewConfigurationWidget->objectName().isEmpty())
- PreviewConfigurationWidget->setObjectName(QStringLiteral("PreviewConfigurationWidget"));
+ PreviewConfigurationWidget->setObjectName(QString::fromUtf8("PreviewConfigurationWidget"));
PreviewConfigurationWidget->setCheckable(true);
formLayout = new QFormLayout(PreviewConfigurationWidget);
- formLayout->setObjectName(QStringLiteral("formLayout"));
+ formLayout->setObjectName(QString::fromUtf8("formLayout"));
m_styleLabel = new QLabel(PreviewConfigurationWidget);
- m_styleLabel->setObjectName(QStringLiteral("m_styleLabel"));
+ m_styleLabel->setObjectName(QString::fromUtf8("m_styleLabel"));
formLayout->setWidget(0, QFormLayout::LabelRole, m_styleLabel);
m_styleCombo = new QComboBox(PreviewConfigurationWidget);
- m_styleCombo->setObjectName(QStringLiteral("m_styleCombo"));
+ m_styleCombo->setObjectName(QString::fromUtf8("m_styleCombo"));
formLayout->setWidget(0, QFormLayout::FieldRole, m_styleCombo);
m_appStyleSheetLabel = new QLabel(PreviewConfigurationWidget);
- m_appStyleSheetLabel->setObjectName(QStringLiteral("m_appStyleSheetLabel"));
+ m_appStyleSheetLabel->setObjectName(QString::fromUtf8("m_appStyleSheetLabel"));
formLayout->setWidget(1, QFormLayout::LabelRole, m_appStyleSheetLabel);
hboxLayout = new QHBoxLayout();
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
m_appStyleSheetLineEdit = new qdesigner_internal::TextPropertyEditor(PreviewConfigurationWidget);
- m_appStyleSheetLineEdit->setObjectName(QStringLiteral("m_appStyleSheetLineEdit"));
+ m_appStyleSheetLineEdit->setObjectName(QString::fromUtf8("m_appStyleSheetLineEdit"));
m_appStyleSheetLineEdit->setMinimumSize(QSize(149, 0));
hboxLayout->addWidget(m_appStyleSheetLineEdit);
m_appStyleSheetChangeButton = new QToolButton(PreviewConfigurationWidget);
- m_appStyleSheetChangeButton->setObjectName(QStringLiteral("m_appStyleSheetChangeButton"));
+ m_appStyleSheetChangeButton->setObjectName(QString::fromUtf8("m_appStyleSheetChangeButton"));
hboxLayout->addWidget(m_appStyleSheetChangeButton);
m_appStyleSheetClearButton = new QToolButton(PreviewConfigurationWidget);
- m_appStyleSheetClearButton->setObjectName(QStringLiteral("m_appStyleSheetClearButton"));
+ m_appStyleSheetClearButton->setObjectName(QString::fromUtf8("m_appStyleSheetClearButton"));
hboxLayout->addWidget(m_appStyleSheetClearButton);
@@ -81,19 +81,19 @@ public:
formLayout->setLayout(1, QFormLayout::FieldRole, hboxLayout);
m_skinLabel = new QLabel(PreviewConfigurationWidget);
- m_skinLabel->setObjectName(QStringLiteral("m_skinLabel"));
+ m_skinLabel->setObjectName(QString::fromUtf8("m_skinLabel"));
formLayout->setWidget(2, QFormLayout::LabelRole, m_skinLabel);
hboxLayout1 = new QHBoxLayout();
- hboxLayout1->setObjectName(QStringLiteral("hboxLayout1"));
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
m_skinCombo = new QComboBox(PreviewConfigurationWidget);
- m_skinCombo->setObjectName(QStringLiteral("m_skinCombo"));
+ m_skinCombo->setObjectName(QString::fromUtf8("m_skinCombo"));
hboxLayout1->addWidget(m_skinCombo);
m_skinRemoveButton = new QToolButton(PreviewConfigurationWidget);
- m_skinRemoveButton->setObjectName(QStringLiteral("m_skinRemoveButton"));
+ m_skinRemoveButton->setObjectName(QString::fromUtf8("m_skinRemoveButton"));
hboxLayout1->addWidget(m_skinRemoveButton);
diff --git a/tests/auto/tools/uic/baseline/previewdialogbase.ui.h b/tests/auto/tools/uic/baseline/previewdialogbase.ui.h
index 7ea1e72e04..8d4c0dae9f 100644
--- a/tests/auto/tools/uic/baseline/previewdialogbase.ui.h
+++ b/tests/auto/tools/uic/baseline/previewdialogbase.ui.h
@@ -45,7 +45,7 @@ public:
void setupUi(QDialog *PreviewDialogBase)
{
if (PreviewDialogBase->objectName().isEmpty())
- PreviewDialogBase->setObjectName(QStringLiteral("PreviewDialogBase"));
+ PreviewDialogBase->setObjectName(QString::fromUtf8("PreviewDialogBase"));
PreviewDialogBase->resize(733, 479);
vboxLayout = new QVBoxLayout(PreviewDialogBase);
#ifndef Q_OS_MAC
@@ -54,7 +54,7 @@ public:
#ifndef Q_OS_MAC
vboxLayout->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
hboxLayout = new QHBoxLayout();
#ifndef Q_OS_MAC
hboxLayout->setSpacing(6);
@@ -62,14 +62,14 @@ public:
#ifndef Q_OS_MAC
hboxLayout->setContentsMargins(0, 0, 0, 0);
#endif
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
label = new QLabel(PreviewDialogBase);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
hboxLayout->addWidget(label);
paperSizeCombo = new QComboBox(PreviewDialogBase);
- paperSizeCombo->setObjectName(QStringLiteral("paperSizeCombo"));
+ paperSizeCombo->setObjectName(QString::fromUtf8("paperSizeCombo"));
QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(1), static_cast<QSizePolicy::Policy>(0));
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -79,12 +79,12 @@ public:
hboxLayout->addWidget(paperSizeCombo);
label_2 = new QLabel(PreviewDialogBase);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
hboxLayout->addWidget(label_2);
paperOrientationCombo = new QComboBox(PreviewDialogBase);
- paperOrientationCombo->setObjectName(QStringLiteral("paperOrientationCombo"));
+ paperOrientationCombo->setObjectName(QString::fromUtf8("paperOrientationCombo"));
sizePolicy.setHeightForWidth(paperOrientationCombo->sizePolicy().hasHeightForWidth());
paperOrientationCombo->setSizePolicy(sizePolicy);
@@ -102,9 +102,9 @@ public:
hboxLayout1->setSpacing(6);
#endif
hboxLayout1->setContentsMargins(0, 0, 0, 0);
- hboxLayout1->setObjectName(QStringLiteral("hboxLayout1"));
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
pageList = new QTreeWidget(PreviewDialogBase);
- pageList->setObjectName(QStringLiteral("pageList"));
+ pageList->setObjectName(QString::fromUtf8("pageList"));
pageList->setIndentation(0);
pageList->setRootIsDecorated(false);
pageList->setUniformRowHeights(true);
@@ -114,7 +114,7 @@ public:
hboxLayout1->addWidget(pageList);
previewArea = new QScrollArea(PreviewDialogBase);
- previewArea->setObjectName(QStringLiteral("previewArea"));
+ previewArea->setObjectName(QString::fromUtf8("previewArea"));
QSizePolicy sizePolicy1(static_cast<QSizePolicy::Policy>(5), static_cast<QSizePolicy::Policy>(5));
sizePolicy1.setHorizontalStretch(1);
sizePolicy1.setVerticalStretch(0);
@@ -131,9 +131,9 @@ public:
hboxLayout2->setSpacing(6);
#endif
hboxLayout2->setContentsMargins(0, 0, 0, 0);
- hboxLayout2->setObjectName(QStringLiteral("hboxLayout2"));
+ hboxLayout2->setObjectName(QString::fromUtf8("hboxLayout2"));
progressBar = new QProgressBar(PreviewDialogBase);
- progressBar->setObjectName(QStringLiteral("progressBar"));
+ progressBar->setObjectName(QString::fromUtf8("progressBar"));
progressBar->setEnabled(false);
QSizePolicy sizePolicy2(static_cast<QSizePolicy::Policy>(7), static_cast<QSizePolicy::Policy>(0));
sizePolicy2.setHorizontalStretch(1);
@@ -147,7 +147,7 @@ public:
hboxLayout2->addWidget(progressBar);
buttonBox = new QDialogButtonBox(PreviewDialogBase);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok);
diff --git a/tests/auto/tools/uic/baseline/previewwidget.ui.h b/tests/auto/tools/uic/baseline/previewwidget.ui.h
index a86fec7c0d..6e359416c8 100644
--- a/tests/auto/tools/uic/baseline/previewwidget.ui.h
+++ b/tests/auto/tools/uic/baseline/previewwidget.ui.h
@@ -90,7 +90,7 @@ public:
void setupUi(QWidget *qdesigner_internal__PreviewWidget)
{
if (qdesigner_internal__PreviewWidget->objectName().isEmpty())
- qdesigner_internal__PreviewWidget->setObjectName(QStringLiteral("qdesigner_internal__PreviewWidget"));
+ qdesigner_internal__PreviewWidget->setObjectName(QString::fromUtf8("qdesigner_internal__PreviewWidget"));
qdesigner_internal__PreviewWidget->resize(471, 251);
QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(1), static_cast<QSizePolicy::Policy>(1));
sizePolicy.setHorizontalStretch(0);
@@ -104,7 +104,7 @@ public:
#ifndef Q_OS_MAC
gridLayout->setContentsMargins(9, 9, 9, 9);
#endif
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
vboxLayout = new QVBoxLayout();
#ifndef Q_OS_MAC
vboxLayout->setSpacing(6);
@@ -112,15 +112,15 @@ public:
#ifndef Q_OS_MAC
vboxLayout->setContentsMargins(0, 0, 0, 0);
#endif
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
LineEdit1 = new QLineEdit(qdesigner_internal__PreviewWidget);
- LineEdit1->setObjectName(QStringLiteral("LineEdit1"));
+ LineEdit1->setObjectName(QString::fromUtf8("LineEdit1"));
vboxLayout->addWidget(LineEdit1);
ComboBox1 = new QComboBox(qdesigner_internal__PreviewWidget);
ComboBox1->addItem(QString());
- ComboBox1->setObjectName(QStringLiteral("ComboBox1"));
+ ComboBox1->setObjectName(QString::fromUtf8("ComboBox1"));
vboxLayout->addWidget(ComboBox1);
@@ -129,14 +129,14 @@ public:
hboxLayout->setSpacing(6);
#endif
hboxLayout->setContentsMargins(0, 0, 0, 0);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
SpinBox1 = new QSpinBox(qdesigner_internal__PreviewWidget);
- SpinBox1->setObjectName(QStringLiteral("SpinBox1"));
+ SpinBox1->setObjectName(QString::fromUtf8("SpinBox1"));
hboxLayout->addWidget(SpinBox1);
PushButton1 = new QPushButton(qdesigner_internal__PreviewWidget);
- PushButton1->setObjectName(QStringLiteral("PushButton1"));
+ PushButton1->setObjectName(QString::fromUtf8("PushButton1"));
hboxLayout->addWidget(PushButton1);
@@ -144,19 +144,19 @@ public:
vboxLayout->addLayout(hboxLayout);
ScrollBar1 = new QScrollBar(qdesigner_internal__PreviewWidget);
- ScrollBar1->setObjectName(QStringLiteral("ScrollBar1"));
+ ScrollBar1->setObjectName(QString::fromUtf8("ScrollBar1"));
ScrollBar1->setOrientation(Qt::Horizontal);
vboxLayout->addWidget(ScrollBar1);
Slider1 = new QSlider(qdesigner_internal__PreviewWidget);
- Slider1->setObjectName(QStringLiteral("Slider1"));
+ Slider1->setObjectName(QString::fromUtf8("Slider1"));
Slider1->setOrientation(Qt::Horizontal);
vboxLayout->addWidget(Slider1);
listWidget = new QListWidget(qdesigner_internal__PreviewWidget);
- listWidget->setObjectName(QStringLiteral("listWidget"));
+ listWidget->setObjectName(QString::fromUtf8("listWidget"));
listWidget->setMaximumSize(QSize(32767, 50));
vboxLayout->addWidget(listWidget);
@@ -169,13 +169,13 @@ public:
gridLayout->addItem(spacerItem, 3, 0, 1, 2);
ProgressBar1 = new QProgressBar(qdesigner_internal__PreviewWidget);
- ProgressBar1->setObjectName(QStringLiteral("ProgressBar1"));
+ ProgressBar1->setObjectName(QString::fromUtf8("ProgressBar1"));
ProgressBar1->setOrientation(Qt::Horizontal);
gridLayout->addWidget(ProgressBar1, 2, 0, 1, 1);
ButtonGroup2 = new QGroupBox(qdesigner_internal__PreviewWidget);
- ButtonGroup2->setObjectName(QStringLiteral("ButtonGroup2"));
+ ButtonGroup2->setObjectName(QString::fromUtf8("ButtonGroup2"));
vboxLayout1 = new QVBoxLayout(ButtonGroup2);
#ifndef Q_OS_MAC
vboxLayout1->setSpacing(6);
@@ -183,15 +183,15 @@ public:
#ifndef Q_OS_MAC
vboxLayout1->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout1->setObjectName(QStringLiteral("vboxLayout1"));
+ vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
CheckBox1 = new QCheckBox(ButtonGroup2);
- CheckBox1->setObjectName(QStringLiteral("CheckBox1"));
+ CheckBox1->setObjectName(QString::fromUtf8("CheckBox1"));
CheckBox1->setChecked(true);
vboxLayout1->addWidget(CheckBox1);
CheckBox2 = new QCheckBox(ButtonGroup2);
- CheckBox2->setObjectName(QStringLiteral("CheckBox2"));
+ CheckBox2->setObjectName(QString::fromUtf8("CheckBox2"));
vboxLayout1->addWidget(CheckBox2);
@@ -199,7 +199,7 @@ public:
gridLayout->addWidget(ButtonGroup2, 1, 0, 1, 1);
ButtonGroup1 = new QGroupBox(qdesigner_internal__PreviewWidget);
- ButtonGroup1->setObjectName(QStringLiteral("ButtonGroup1"));
+ ButtonGroup1->setObjectName(QString::fromUtf8("ButtonGroup1"));
vboxLayout2 = new QVBoxLayout(ButtonGroup1);
#ifndef Q_OS_MAC
vboxLayout2->setSpacing(6);
@@ -207,20 +207,20 @@ public:
#ifndef Q_OS_MAC
vboxLayout2->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout2->setObjectName(QStringLiteral("vboxLayout2"));
+ vboxLayout2->setObjectName(QString::fromUtf8("vboxLayout2"));
RadioButton1 = new QRadioButton(ButtonGroup1);
- RadioButton1->setObjectName(QStringLiteral("RadioButton1"));
+ RadioButton1->setObjectName(QString::fromUtf8("RadioButton1"));
RadioButton1->setChecked(true);
vboxLayout2->addWidget(RadioButton1);
RadioButton2 = new QRadioButton(ButtonGroup1);
- RadioButton2->setObjectName(QStringLiteral("RadioButton2"));
+ RadioButton2->setObjectName(QString::fromUtf8("RadioButton2"));
vboxLayout2->addWidget(RadioButton2);
RadioButton3 = new QRadioButton(ButtonGroup1);
- RadioButton3->setObjectName(QStringLiteral("RadioButton3"));
+ RadioButton3->setObjectName(QString::fromUtf8("RadioButton3"));
vboxLayout2->addWidget(RadioButton3);
diff --git a/tests/auto/tools/uic/baseline/proxy.ui.h b/tests/auto/tools/uic/baseline/proxy.ui.h
index 2112324eae..a1bc287190 100644
--- a/tests/auto/tools/uic/baseline/proxy.ui.h
+++ b/tests/auto/tools/uic/baseline/proxy.ui.h
@@ -34,44 +34,44 @@ public:
void setupUi(QDialog *ProxyDialog)
{
if (ProxyDialog->objectName().isEmpty())
- ProxyDialog->setObjectName(QStringLiteral("ProxyDialog"));
+ ProxyDialog->setObjectName(QString::fromUtf8("ProxyDialog"));
ProxyDialog->resize(369, 144);
gridLayout = new QGridLayout(ProxyDialog);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
iconLabel = new QLabel(ProxyDialog);
- iconLabel->setObjectName(QStringLiteral("iconLabel"));
+ iconLabel->setObjectName(QString::fromUtf8("iconLabel"));
gridLayout->addWidget(iconLabel, 0, 0, 1, 1);
introLabel = new QLabel(ProxyDialog);
- introLabel->setObjectName(QStringLiteral("introLabel"));
+ introLabel->setObjectName(QString::fromUtf8("introLabel"));
introLabel->setWordWrap(true);
gridLayout->addWidget(introLabel, 0, 1, 1, 2);
usernameLabel = new QLabel(ProxyDialog);
- usernameLabel->setObjectName(QStringLiteral("usernameLabel"));
+ usernameLabel->setObjectName(QString::fromUtf8("usernameLabel"));
gridLayout->addWidget(usernameLabel, 1, 0, 1, 2);
userNameLineEdit = new QLineEdit(ProxyDialog);
- userNameLineEdit->setObjectName(QStringLiteral("userNameLineEdit"));
+ userNameLineEdit->setObjectName(QString::fromUtf8("userNameLineEdit"));
gridLayout->addWidget(userNameLineEdit, 1, 2, 1, 1);
passwordLabel = new QLabel(ProxyDialog);
- passwordLabel->setObjectName(QStringLiteral("passwordLabel"));
+ passwordLabel->setObjectName(QString::fromUtf8("passwordLabel"));
gridLayout->addWidget(passwordLabel, 2, 0, 1, 2);
passwordLineEdit = new QLineEdit(ProxyDialog);
- passwordLineEdit->setObjectName(QStringLiteral("passwordLineEdit"));
+ passwordLineEdit->setObjectName(QString::fromUtf8("passwordLineEdit"));
passwordLineEdit->setEchoMode(QLineEdit::Password);
gridLayout->addWidget(passwordLineEdit, 2, 2, 1, 1);
buttonBox = new QDialogButtonBox(ProxyDialog);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
diff --git a/tests/auto/tools/uic/baseline/qfiledialog.ui.h b/tests/auto/tools/uic/baseline/qfiledialog.ui.h
index cd1891c58c..53607db449 100644
--- a/tests/auto/tools/uic/baseline/qfiledialog.ui.h
+++ b/tests/auto/tools/uic/baseline/qfiledialog.ui.h
@@ -92,20 +92,20 @@ public:
void setupUi(QDialog *QFileDialog)
{
if (QFileDialog->objectName().isEmpty())
- QFileDialog->setObjectName(QStringLiteral("QFileDialog"));
+ QFileDialog->setObjectName(QString::fromUtf8("QFileDialog"));
QFileDialog->resize(521, 316);
QFileDialog->setSizeGripEnabled(true);
gridLayout = new QGridLayout(QFileDialog);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
lookInLabel = new QLabel(QFileDialog);
- lookInLabel->setObjectName(QStringLiteral("lookInLabel"));
+ lookInLabel->setObjectName(QString::fromUtf8("lookInLabel"));
gridLayout->addWidget(lookInLabel, 0, 0, 1, 1);
hboxLayout = new QHBoxLayout();
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
lookInCombo = new QFileDialogComboBox(QFileDialog);
- lookInCombo->setObjectName(QStringLiteral("lookInCombo"));
+ lookInCombo->setObjectName(QString::fromUtf8("lookInCombo"));
QSizePolicy sizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
sizePolicy.setHorizontalStretch(1);
sizePolicy.setVerticalStretch(0);
@@ -116,32 +116,32 @@ public:
hboxLayout->addWidget(lookInCombo);
backButton = new QToolButton(QFileDialog);
- backButton->setObjectName(QStringLiteral("backButton"));
+ backButton->setObjectName(QString::fromUtf8("backButton"));
hboxLayout->addWidget(backButton);
forwardButton = new QToolButton(QFileDialog);
- forwardButton->setObjectName(QStringLiteral("forwardButton"));
+ forwardButton->setObjectName(QString::fromUtf8("forwardButton"));
hboxLayout->addWidget(forwardButton);
toParentButton = new QToolButton(QFileDialog);
- toParentButton->setObjectName(QStringLiteral("toParentButton"));
+ toParentButton->setObjectName(QString::fromUtf8("toParentButton"));
hboxLayout->addWidget(toParentButton);
newFolderButton = new QToolButton(QFileDialog);
- newFolderButton->setObjectName(QStringLiteral("newFolderButton"));
+ newFolderButton->setObjectName(QString::fromUtf8("newFolderButton"));
hboxLayout->addWidget(newFolderButton);
listModeButton = new QToolButton(QFileDialog);
- listModeButton->setObjectName(QStringLiteral("listModeButton"));
+ listModeButton->setObjectName(QString::fromUtf8("listModeButton"));
hboxLayout->addWidget(listModeButton);
detailModeButton = new QToolButton(QFileDialog);
- detailModeButton->setObjectName(QStringLiteral("detailModeButton"));
+ detailModeButton->setObjectName(QString::fromUtf8("detailModeButton"));
hboxLayout->addWidget(detailModeButton);
@@ -149,7 +149,7 @@ public:
gridLayout->addLayout(hboxLayout, 0, 1, 1, 2);
splitter = new QSplitter(QFileDialog);
- splitter->setObjectName(QStringLiteral("splitter"));
+ splitter->setObjectName(QString::fromUtf8("splitter"));
QSizePolicy sizePolicy1(QSizePolicy::Expanding, QSizePolicy::Expanding);
sizePolicy1.setHorizontalStretch(0);
sizePolicy1.setVerticalStretch(0);
@@ -157,38 +157,38 @@ public:
splitter->setSizePolicy(sizePolicy1);
splitter->setOrientation(Qt::Horizontal);
sidebar = new QSidebar(splitter);
- sidebar->setObjectName(QStringLiteral("sidebar"));
+ sidebar->setObjectName(QString::fromUtf8("sidebar"));
splitter->addWidget(sidebar);
frame = new QFrame(splitter);
- frame->setObjectName(QStringLiteral("frame"));
+ frame->setObjectName(QString::fromUtf8("frame"));
frame->setFrameShape(QFrame::NoFrame);
frame->setFrameShadow(QFrame::Raised);
vboxLayout = new QVBoxLayout(frame);
vboxLayout->setSpacing(0);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
vboxLayout->setContentsMargins(0, 0, 0, 0);
stackedWidget = new QStackedWidget(frame);
- stackedWidget->setObjectName(QStringLiteral("stackedWidget"));
+ stackedWidget->setObjectName(QString::fromUtf8("stackedWidget"));
page = new QWidget();
- page->setObjectName(QStringLiteral("page"));
+ page->setObjectName(QString::fromUtf8("page"));
vboxLayout1 = new QVBoxLayout(page);
vboxLayout1->setSpacing(0);
- vboxLayout1->setObjectName(QStringLiteral("vboxLayout1"));
+ vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
vboxLayout1->setContentsMargins(0, 0, 0, 0);
listView = new QFileDialogListView(page);
- listView->setObjectName(QStringLiteral("listView"));
+ listView->setObjectName(QString::fromUtf8("listView"));
vboxLayout1->addWidget(listView);
stackedWidget->addWidget(page);
page_2 = new QWidget();
- page_2->setObjectName(QStringLiteral("page_2"));
+ page_2->setObjectName(QString::fromUtf8("page_2"));
vboxLayout2 = new QVBoxLayout(page_2);
vboxLayout2->setSpacing(0);
- vboxLayout2->setObjectName(QStringLiteral("vboxLayout2"));
+ vboxLayout2->setObjectName(QString::fromUtf8("vboxLayout2"));
vboxLayout2->setContentsMargins(0, 0, 0, 0);
treeView = new QFileDialogTreeView(page_2);
- treeView->setObjectName(QStringLiteral("treeView"));
+ treeView->setObjectName(QString::fromUtf8("treeView"));
vboxLayout2->addWidget(treeView);
@@ -201,7 +201,7 @@ public:
gridLayout->addWidget(splitter, 1, 0, 1, 3);
fileNameLabel = new QLabel(QFileDialog);
- fileNameLabel->setObjectName(QStringLiteral("fileNameLabel"));
+ fileNameLabel->setObjectName(QString::fromUtf8("fileNameLabel"));
QSizePolicy sizePolicy2(QSizePolicy::Minimum, QSizePolicy::Preferred);
sizePolicy2.setHorizontalStretch(0);
sizePolicy2.setVerticalStretch(0);
@@ -212,7 +212,7 @@ public:
gridLayout->addWidget(fileNameLabel, 2, 0, 1, 1);
fileNameEdit = new QFileDialogLineEdit(QFileDialog);
- fileNameEdit->setObjectName(QStringLiteral("fileNameEdit"));
+ fileNameEdit->setObjectName(QString::fromUtf8("fileNameEdit"));
QSizePolicy sizePolicy3(QSizePolicy::Expanding, QSizePolicy::Fixed);
sizePolicy3.setHorizontalStretch(1);
sizePolicy3.setVerticalStretch(0);
@@ -222,14 +222,14 @@ public:
gridLayout->addWidget(fileNameEdit, 2, 1, 1, 1);
buttonBox = new QDialogButtonBox(QFileDialog);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Vertical);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok);
gridLayout->addWidget(buttonBox, 2, 2, 2, 1);
fileTypeLabel = new QLabel(QFileDialog);
- fileTypeLabel->setObjectName(QStringLiteral("fileTypeLabel"));
+ fileTypeLabel->setObjectName(QString::fromUtf8("fileTypeLabel"));
QSizePolicy sizePolicy4(QSizePolicy::Preferred, QSizePolicy::Fixed);
sizePolicy4.setHorizontalStretch(0);
sizePolicy4.setVerticalStretch(0);
@@ -239,7 +239,7 @@ public:
gridLayout->addWidget(fileTypeLabel, 3, 0, 1, 1);
fileTypeCombo = new QComboBox(QFileDialog);
- fileTypeCombo->setObjectName(QStringLiteral("fileTypeCombo"));
+ fileTypeCombo->setObjectName(QString::fromUtf8("fileTypeCombo"));
QSizePolicy sizePolicy5(QSizePolicy::Expanding, QSizePolicy::Fixed);
sizePolicy5.setHorizontalStretch(0);
sizePolicy5.setVerticalStretch(0);
diff --git a/tests/auto/tools/uic/baseline/qpagesetupwidget.ui.h b/tests/auto/tools/uic/baseline/qpagesetupwidget.ui.h
index 5b0a5b9dc6..a5379bc468 100644
--- a/tests/auto/tools/uic/baseline/qpagesetupwidget.ui.h
+++ b/tests/auto/tools/uic/baseline/qpagesetupwidget.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'qpagesetupwidget.ui'
**
-** Created by: Qt User Interface Compiler version 5.9.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -76,46 +76,46 @@ public:
void setupUi(QWidget *QPageSetupWidget)
{
if (QPageSetupWidget->objectName().isEmpty())
- QPageSetupWidget->setObjectName(QStringLiteral("QPageSetupWidget"));
+ QPageSetupWidget->setObjectName(QString::fromUtf8("QPageSetupWidget"));
QPageSetupWidget->resize(416, 515);
gridLayout_3 = new QGridLayout(QPageSetupWidget);
gridLayout_3->setContentsMargins(0, 0, 0, 0);
- gridLayout_3->setObjectName(QStringLiteral("gridLayout_3"));
+ gridLayout_3->setObjectName(QString::fromUtf8("gridLayout_3"));
groupBox_2 = new QGroupBox(QPageSetupWidget);
- groupBox_2->setObjectName(QStringLiteral("groupBox_2"));
+ groupBox_2->setObjectName(QString::fromUtf8("groupBox_2"));
gridLayout_2 = new QGridLayout(groupBox_2);
- gridLayout_2->setObjectName(QStringLiteral("gridLayout_2"));
+ gridLayout_2->setObjectName(QString::fromUtf8("gridLayout_2"));
pageSizeLabel = new QLabel(groupBox_2);
- pageSizeLabel->setObjectName(QStringLiteral("pageSizeLabel"));
+ pageSizeLabel->setObjectName(QString::fromUtf8("pageSizeLabel"));
gridLayout_2->addWidget(pageSizeLabel, 0, 0, 1, 1);
pageSizeCombo = new QComboBox(groupBox_2);
- pageSizeCombo->setObjectName(QStringLiteral("pageSizeCombo"));
+ pageSizeCombo->setObjectName(QString::fromUtf8("pageSizeCombo"));
gridLayout_2->addWidget(pageSizeCombo, 0, 1, 1, 1);
widthLabel = new QLabel(groupBox_2);
- widthLabel->setObjectName(QStringLiteral("widthLabel"));
+ widthLabel->setObjectName(QString::fromUtf8("widthLabel"));
gridLayout_2->addWidget(widthLabel, 1, 0, 1, 1);
horizontalLayout_3 = new QHBoxLayout();
- horizontalLayout_3->setObjectName(QStringLiteral("horizontalLayout_3"));
+ horizontalLayout_3->setObjectName(QString::fromUtf8("horizontalLayout_3"));
pageWidth = new QDoubleSpinBox(groupBox_2);
- pageWidth->setObjectName(QStringLiteral("pageWidth"));
- pageWidth->setMaximum(9999.99);
+ pageWidth->setObjectName(QString::fromUtf8("pageWidth"));
+ pageWidth->setMaximum(9999.989999999999782);
horizontalLayout_3->addWidget(pageWidth);
heightLabel = new QLabel(groupBox_2);
- heightLabel->setObjectName(QStringLiteral("heightLabel"));
+ heightLabel->setObjectName(QString::fromUtf8("heightLabel"));
horizontalLayout_3->addWidget(heightLabel);
pageHeight = new QDoubleSpinBox(groupBox_2);
- pageHeight->setObjectName(QStringLiteral("pageHeight"));
- pageHeight->setMaximum(9999.99);
+ pageHeight->setObjectName(QString::fromUtf8("pageHeight"));
+ pageHeight->setMaximum(9999.989999999999782);
horizontalLayout_3->addWidget(pageHeight);
@@ -123,12 +123,12 @@ public:
gridLayout_2->addLayout(horizontalLayout_3, 1, 1, 1, 1);
paperSourceLabel = new QLabel(groupBox_2);
- paperSourceLabel->setObjectName(QStringLiteral("paperSourceLabel"));
+ paperSourceLabel->setObjectName(QString::fromUtf8("paperSourceLabel"));
gridLayout_2->addWidget(paperSourceLabel, 2, 0, 1, 1);
paperSource = new QComboBox(groupBox_2);
- paperSource->setObjectName(QStringLiteral("paperSource"));
+ paperSource->setObjectName(QString::fromUtf8("paperSource"));
gridLayout_2->addWidget(paperSource, 2, 1, 1, 1);
@@ -140,9 +140,9 @@ public:
gridLayout_3->addWidget(groupBox_2, 1, 0, 1, 2);
horizontalLayout_4 = new QHBoxLayout();
- horizontalLayout_4->setObjectName(QStringLiteral("horizontalLayout_4"));
+ horizontalLayout_4->setObjectName(QString::fromUtf8("horizontalLayout_4"));
unitCombo = new QComboBox(QPageSetupWidget);
- unitCombo->setObjectName(QStringLiteral("unitCombo"));
+ unitCombo->setObjectName(QString::fromUtf8("unitCombo"));
horizontalLayout_4->addWidget(unitCombo);
@@ -154,32 +154,32 @@ public:
gridLayout_3->addLayout(horizontalLayout_4, 0, 0, 1, 2);
preview = new QWidget(QPageSetupWidget);
- preview->setObjectName(QStringLiteral("preview"));
+ preview->setObjectName(QString::fromUtf8("preview"));
gridLayout_3->addWidget(preview, 2, 1, 2, 1);
groupBox_3 = new QGroupBox(QPageSetupWidget);
- groupBox_3->setObjectName(QStringLiteral("groupBox_3"));
+ groupBox_3->setObjectName(QString::fromUtf8("groupBox_3"));
verticalLayout = new QVBoxLayout(groupBox_3);
- verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
+ verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
portrait = new QRadioButton(groupBox_3);
- portrait->setObjectName(QStringLiteral("portrait"));
+ portrait->setObjectName(QString::fromUtf8("portrait"));
portrait->setChecked(true);
verticalLayout->addWidget(portrait);
landscape = new QRadioButton(groupBox_3);
- landscape->setObjectName(QStringLiteral("landscape"));
+ landscape->setObjectName(QString::fromUtf8("landscape"));
verticalLayout->addWidget(landscape);
reverseLandscape = new QRadioButton(groupBox_3);
- reverseLandscape->setObjectName(QStringLiteral("reverseLandscape"));
+ reverseLandscape->setObjectName(QString::fromUtf8("reverseLandscape"));
verticalLayout->addWidget(reverseLandscape);
reversePortrait = new QRadioButton(groupBox_3);
- reversePortrait->setObjectName(QStringLiteral("reversePortrait"));
+ reversePortrait->setObjectName(QString::fromUtf8("reversePortrait"));
verticalLayout->addWidget(reversePortrait);
@@ -191,28 +191,28 @@ public:
gridLayout_3->addWidget(groupBox_3, 2, 0, 1, 1);
groupBox = new QGroupBox(QPageSetupWidget);
- groupBox->setObjectName(QStringLiteral("groupBox"));
+ groupBox->setObjectName(QString::fromUtf8("groupBox"));
horizontalLayout_2 = new QHBoxLayout(groupBox);
- horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2"));
+ horizontalLayout_2->setObjectName(QString::fromUtf8("horizontalLayout_2"));
gridLayout = new QGridLayout();
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
topMargin = new QDoubleSpinBox(groupBox);
- topMargin->setObjectName(QStringLiteral("topMargin"));
+ topMargin->setObjectName(QString::fromUtf8("topMargin"));
topMargin->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
- topMargin->setMaximum(999.99);
+ topMargin->setMaximum(999.990000000000009);
gridLayout->addWidget(topMargin, 0, 1, 1, 1);
horizontalLayout = new QHBoxLayout();
- horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
+ horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
horizontalSpacer_7 = new QSpacerItem(0, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout->addItem(horizontalSpacer_7);
leftMargin = new QDoubleSpinBox(groupBox);
- leftMargin->setObjectName(QStringLiteral("leftMargin"));
+ leftMargin->setObjectName(QString::fromUtf8("leftMargin"));
leftMargin->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
- leftMargin->setMaximum(999.99);
+ leftMargin->setMaximum(999.990000000000009);
horizontalLayout->addWidget(leftMargin);
@@ -221,9 +221,9 @@ public:
horizontalLayout->addItem(horizontalSpacer);
rightMargin = new QDoubleSpinBox(groupBox);
- rightMargin->setObjectName(QStringLiteral("rightMargin"));
+ rightMargin->setObjectName(QString::fromUtf8("rightMargin"));
rightMargin->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
- rightMargin->setMaximum(999.99);
+ rightMargin->setMaximum(999.990000000000009);
horizontalLayout->addWidget(rightMargin);
@@ -239,9 +239,9 @@ public:
gridLayout->addItem(horizontalSpacer_2, 0, 2, 1, 1);
bottomMargin = new QDoubleSpinBox(groupBox);
- bottomMargin->setObjectName(QStringLiteral("bottomMargin"));
+ bottomMargin->setObjectName(QString::fromUtf8("bottomMargin"));
bottomMargin->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
- bottomMargin->setMaximum(999.99);
+ bottomMargin->setMaximum(999.990000000000009);
gridLayout->addWidget(bottomMargin, 2, 1, 1, 1);
@@ -256,11 +256,11 @@ public:
gridLayout_3->addWidget(groupBox, 3, 0, 1, 1);
pagesPerSheetButtonGroup = new QGroupBox(QPageSetupWidget);
- pagesPerSheetButtonGroup->setObjectName(QStringLiteral("pagesPerSheetButtonGroup"));
+ pagesPerSheetButtonGroup->setObjectName(QString::fromUtf8("pagesPerSheetButtonGroup"));
gridLayout_4 = new QGridLayout(pagesPerSheetButtonGroup);
- gridLayout_4->setObjectName(QStringLiteral("gridLayout_4"));
+ gridLayout_4->setObjectName(QString::fromUtf8("gridLayout_4"));
pagesPerSheetCombo = new QComboBox(pagesPerSheetButtonGroup);
- pagesPerSheetCombo->setObjectName(QStringLiteral("pagesPerSheetCombo"));
+ pagesPerSheetCombo->setObjectName(QString::fromUtf8("pagesPerSheetCombo"));
gridLayout_4->addWidget(pagesPerSheetCombo, 0, 1, 1, 1);
@@ -269,17 +269,17 @@ public:
gridLayout_4->addItem(horizontalSpacer_6, 0, 2, 1, 1);
label = new QLabel(pagesPerSheetButtonGroup);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
gridLayout_4->addWidget(label, 1, 0, 1, 1);
pagesPerSheetLayoutCombo = new QComboBox(pagesPerSheetButtonGroup);
- pagesPerSheetLayoutCombo->setObjectName(QStringLiteral("pagesPerSheetLayoutCombo"));
+ pagesPerSheetLayoutCombo->setObjectName(QString::fromUtf8("pagesPerSheetLayoutCombo"));
gridLayout_4->addWidget(pagesPerSheetLayoutCombo, 1, 1, 1, 1);
label_2 = new QLabel(pagesPerSheetButtonGroup);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
gridLayout_4->addWidget(label_2, 0, 0, 1, 1);
diff --git a/tests/auto/tools/uic/baseline/qprintpropertieswidget.ui.h b/tests/auto/tools/uic/baseline/qprintpropertieswidget.ui.h
index baa9bbec38..8626a9fc3c 100644
--- a/tests/auto/tools/uic/baseline/qprintpropertieswidget.ui.h
+++ b/tests/auto/tools/uic/baseline/qprintpropertieswidget.ui.h
@@ -36,30 +36,30 @@ public:
void setupUi(QWidget *QPrintPropertiesWidget)
{
if (QPrintPropertiesWidget->objectName().isEmpty())
- QPrintPropertiesWidget->setObjectName(QStringLiteral("QPrintPropertiesWidget"));
+ QPrintPropertiesWidget->setObjectName(QString::fromUtf8("QPrintPropertiesWidget"));
QPrintPropertiesWidget->resize(396, 288);
verticalLayout_4 = new QVBoxLayout(QPrintPropertiesWidget);
verticalLayout_4->setContentsMargins(0, 0, 0, 0);
- verticalLayout_4->setObjectName(QStringLiteral("verticalLayout_4"));
+ verticalLayout_4->setObjectName(QString::fromUtf8("verticalLayout_4"));
tabs = new QTabWidget(QPrintPropertiesWidget);
- tabs->setObjectName(QStringLiteral("tabs"));
+ tabs->setObjectName(QString::fromUtf8("tabs"));
tabPage = new QWidget();
- tabPage->setObjectName(QStringLiteral("tabPage"));
+ tabPage->setObjectName(QString::fromUtf8("tabPage"));
tabPage->setGeometry(QRect(0, 0, 392, 261));
horizontalLayout = new QHBoxLayout(tabPage);
- horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
+ horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
pageSetup = new QPageSetupWidget(tabPage);
- pageSetup->setObjectName(QStringLiteral("pageSetup"));
+ pageSetup->setObjectName(QString::fromUtf8("pageSetup"));
horizontalLayout->addWidget(pageSetup);
tabs->addTab(tabPage, QString());
cupsPropertiesPage = new QWidget();
- cupsPropertiesPage->setObjectName(QStringLiteral("cupsPropertiesPage"));
+ cupsPropertiesPage->setObjectName(QString::fromUtf8("cupsPropertiesPage"));
horizontalLayout_2 = new QHBoxLayout(cupsPropertiesPage);
- horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2"));
+ horizontalLayout_2->setObjectName(QString::fromUtf8("horizontalLayout_2"));
treeView = new QTreeView(cupsPropertiesPage);
- treeView->setObjectName(QStringLiteral("treeView"));
+ treeView->setObjectName(QString::fromUtf8("treeView"));
treeView->setAlternatingRowColors(true);
horizontalLayout_2->addWidget(treeView);
diff --git a/tests/auto/tools/uic/baseline/qprintsettingsoutput.ui.h b/tests/auto/tools/uic/baseline/qprintsettingsoutput.ui.h
index a0f16c998b..656b5f9deb 100644
--- a/tests/auto/tools/uic/baseline/qprintsettingsoutput.ui.h
+++ b/tests/auto/tools/uic/baseline/qprintsettingsoutput.ui.h
@@ -70,20 +70,20 @@ public:
void setupUi(QWidget *QPrintSettingsOutput)
{
if (QPrintSettingsOutput->objectName().isEmpty())
- QPrintSettingsOutput->setObjectName(QStringLiteral("QPrintSettingsOutput"));
+ QPrintSettingsOutput->setObjectName(QString::fromUtf8("QPrintSettingsOutput"));
QPrintSettingsOutput->resize(416, 166);
horizontalLayout_2 = new QHBoxLayout(QPrintSettingsOutput);
horizontalLayout_2->setContentsMargins(0, 0, 0, 0);
- horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2"));
+ horizontalLayout_2->setObjectName(QString::fromUtf8("horizontalLayout_2"));
tabs = new QTabWidget(QPrintSettingsOutput);
- tabs->setObjectName(QStringLiteral("tabs"));
+ tabs->setObjectName(QString::fromUtf8("tabs"));
copiesTab = new QWidget();
- copiesTab->setObjectName(QStringLiteral("copiesTab"));
+ copiesTab->setObjectName(QString::fromUtf8("copiesTab"));
copiesTab->setGeometry(QRect(0, 0, 412, 139));
horizontalLayout = new QHBoxLayout(copiesTab);
- horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
+ horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
gbPrintRange = new QGroupBox(copiesTab);
- gbPrintRange->setObjectName(QStringLiteral("gbPrintRange"));
+ gbPrintRange->setObjectName(QString::fromUtf8("gbPrintRange"));
QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -92,9 +92,9 @@ public:
_3 = new QVBoxLayout(gbPrintRange);
_3->setSpacing(4);
_3->setContentsMargins(6, 6, 6, 6);
- _3->setObjectName(QStringLiteral("_3"));
+ _3->setObjectName(QString::fromUtf8("_3"));
printAll = new QRadioButton(gbPrintRange);
- printAll->setObjectName(QStringLiteral("printAll"));
+ printAll->setObjectName(QString::fromUtf8("printAll"));
printAll->setChecked(true);
_3->addWidget(printAll);
@@ -104,14 +104,14 @@ public:
_4->setSpacing(6);
#endif
_4->setContentsMargins(0, 0, 0, 0);
- _4->setObjectName(QStringLiteral("_4"));
+ _4->setObjectName(QString::fromUtf8("_4"));
printRange = new QRadioButton(gbPrintRange);
- printRange->setObjectName(QStringLiteral("printRange"));
+ printRange->setObjectName(QString::fromUtf8("printRange"));
_4->addWidget(printRange);
from = new QSpinBox(gbPrintRange);
- from->setObjectName(QStringLiteral("from"));
+ from->setObjectName(QString::fromUtf8("from"));
from->setEnabled(false);
from->setMinimum(1);
from->setMaximum(999);
@@ -119,12 +119,12 @@ public:
_4->addWidget(from);
label_3 = new QLabel(gbPrintRange);
- label_3->setObjectName(QStringLiteral("label_3"));
+ label_3->setObjectName(QString::fromUtf8("label_3"));
_4->addWidget(label_3);
to = new QSpinBox(gbPrintRange);
- to->setObjectName(QStringLiteral("to"));
+ to->setObjectName(QString::fromUtf8("to"));
to->setEnabled(false);
to->setMinimum(1);
to->setMaximum(999);
@@ -139,7 +139,7 @@ public:
_3->addLayout(_4);
printSelection = new QRadioButton(gbPrintRange);
- printSelection->setObjectName(QStringLiteral("printSelection"));
+ printSelection->setObjectName(QString::fromUtf8("printSelection"));
_3->addWidget(printSelection);
@@ -151,16 +151,16 @@ public:
horizontalLayout->addWidget(gbPrintRange);
groupBox = new QGroupBox(copiesTab);
- groupBox->setObjectName(QStringLiteral("groupBox"));
+ groupBox->setObjectName(QString::fromUtf8("groupBox"));
gridLayout = new QGridLayout(groupBox);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
label = new QLabel(groupBox);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
gridLayout->addWidget(label, 0, 0, 1, 1);
copies = new QSpinBox(groupBox);
- copies->setObjectName(QStringLiteral("copies"));
+ copies->setObjectName(QString::fromUtf8("copies"));
copies->setMinimum(1);
copies->setMaximum(999);
@@ -171,12 +171,12 @@ public:
gridLayout->addItem(horizontalSpacer, 0, 3, 1, 1);
collate = new QCheckBox(groupBox);
- collate->setObjectName(QStringLiteral("collate"));
+ collate->setObjectName(QString::fromUtf8("collate"));
gridLayout->addWidget(collate, 1, 0, 1, 2);
outputIcon = new QLabel(groupBox);
- outputIcon->setObjectName(QStringLiteral("outputIcon"));
+ outputIcon->setObjectName(QString::fromUtf8("outputIcon"));
QSizePolicy sizePolicy1(QSizePolicy::Ignored, QSizePolicy::Ignored);
sizePolicy1.setHorizontalStretch(0);
sizePolicy1.setVerticalStretch(0);
@@ -186,7 +186,7 @@ public:
gridLayout->addWidget(outputIcon, 1, 2, 2, 2);
reverse = new QCheckBox(groupBox);
- reverse->setObjectName(QStringLiteral("reverse"));
+ reverse->setObjectName(QString::fromUtf8("reverse"));
gridLayout->addWidget(reverse, 2, 0, 1, 2);
@@ -199,30 +199,30 @@ public:
tabs->addTab(copiesTab, QString());
optionsTab = new QWidget();
- optionsTab->setObjectName(QStringLiteral("optionsTab"));
+ optionsTab->setObjectName(QString::fromUtf8("optionsTab"));
optionsTab->setGeometry(QRect(0, 0, 412, 139));
gridLayout_2 = new QGridLayout(optionsTab);
- gridLayout_2->setObjectName(QStringLiteral("gridLayout_2"));
+ gridLayout_2->setObjectName(QString::fromUtf8("gridLayout_2"));
colorMode = new QGroupBox(optionsTab);
- colorMode->setObjectName(QStringLiteral("colorMode"));
+ colorMode->setObjectName(QString::fromUtf8("colorMode"));
gridLayout_4 = new QGridLayout(colorMode);
- gridLayout_4->setObjectName(QStringLiteral("gridLayout_4"));
+ gridLayout_4->setObjectName(QString::fromUtf8("gridLayout_4"));
verticalSpacer_6 = new QSpacerItem(1, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
gridLayout_4->addItem(verticalSpacer_6, 2, 0, 1, 1);
color = new QRadioButton(colorMode);
- color->setObjectName(QStringLiteral("color"));
+ color->setObjectName(QString::fromUtf8("color"));
gridLayout_4->addWidget(color, 0, 0, 1, 1);
colorIcon = new QLabel(colorMode);
- colorIcon->setObjectName(QStringLiteral("colorIcon"));
+ colorIcon->setObjectName(QString::fromUtf8("colorIcon"));
gridLayout_4->addWidget(colorIcon, 0, 1, 3, 1);
grayscale = new QRadioButton(colorMode);
- grayscale->setObjectName(QStringLiteral("grayscale"));
+ grayscale->setObjectName(QString::fromUtf8("grayscale"));
gridLayout_4->addWidget(grayscale, 1, 0, 1, 1);
@@ -230,22 +230,22 @@ public:
gridLayout_2->addWidget(colorMode, 0, 1, 1, 1);
duplex = new QGroupBox(optionsTab);
- duplex->setObjectName(QStringLiteral("duplex"));
+ duplex->setObjectName(QString::fromUtf8("duplex"));
verticalLayout = new QVBoxLayout(duplex);
- verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
+ verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
noDuplex = new QRadioButton(duplex);
- noDuplex->setObjectName(QStringLiteral("noDuplex"));
+ noDuplex->setObjectName(QString::fromUtf8("noDuplex"));
noDuplex->setChecked(true);
verticalLayout->addWidget(noDuplex);
duplexLong = new QRadioButton(duplex);
- duplexLong->setObjectName(QStringLiteral("duplexLong"));
+ duplexLong->setObjectName(QString::fromUtf8("duplexLong"));
verticalLayout->addWidget(duplexLong);
duplexShort = new QRadioButton(duplex);
- duplexShort->setObjectName(QStringLiteral("duplexShort"));
+ duplexShort->setObjectName(QString::fromUtf8("duplexShort"));
verticalLayout->addWidget(duplexShort);
diff --git a/tests/auto/tools/uic/baseline/qprintwidget.ui.h b/tests/auto/tools/uic/baseline/qprintwidget.ui.h
index 73fa2cfcfa..04b05143c6 100644
--- a/tests/auto/tools/uic/baseline/qprintwidget.ui.h
+++ b/tests/auto/tools/uic/baseline/qprintwidget.ui.h
@@ -46,22 +46,22 @@ public:
void setupUi(QWidget *QPrintWidget)
{
if (QPrintWidget->objectName().isEmpty())
- QPrintWidget->setObjectName(QStringLiteral("QPrintWidget"));
+ QPrintWidget->setObjectName(QString::fromUtf8("QPrintWidget"));
QPrintWidget->resize(443, 175);
horizontalLayout_2 = new QHBoxLayout(QPrintWidget);
horizontalLayout_2->setContentsMargins(0, 0, 0, 0);
- horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2"));
+ horizontalLayout_2->setObjectName(QString::fromUtf8("horizontalLayout_2"));
printerGroup = new QGroupBox(QPrintWidget);
- printerGroup->setObjectName(QStringLiteral("printerGroup"));
+ printerGroup->setObjectName(QString::fromUtf8("printerGroup"));
gridLayout = new QGridLayout(printerGroup);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
label = new QLabel(printerGroup);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
gridLayout->addWidget(label, 0, 0, 1, 1);
printers = new QComboBox(printerGroup);
- printers->setObjectName(QStringLiteral("printers"));
+ printers->setObjectName(QString::fromUtf8("printers"));
QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
sizePolicy.setHorizontalStretch(3);
sizePolicy.setVerticalStretch(0);
@@ -71,7 +71,7 @@ public:
gridLayout->addWidget(printers, 0, 1, 1, 1);
properties = new QPushButton(printerGroup);
- properties->setObjectName(QStringLiteral("properties"));
+ properties->setObjectName(QString::fromUtf8("properties"));
QSizePolicy sizePolicy1(QSizePolicy::Minimum, QSizePolicy::Fixed);
sizePolicy1.setHorizontalStretch(1);
sizePolicy1.setVerticalStretch(0);
@@ -81,44 +81,44 @@ public:
gridLayout->addWidget(properties, 0, 2, 1, 1);
label_2 = new QLabel(printerGroup);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
gridLayout->addWidget(label_2, 1, 0, 1, 1);
location = new QLabel(printerGroup);
- location->setObjectName(QStringLiteral("location"));
+ location->setObjectName(QString::fromUtf8("location"));
gridLayout->addWidget(location, 1, 1, 1, 1);
preview = new QCheckBox(printerGroup);
- preview->setObjectName(QStringLiteral("preview"));
+ preview->setObjectName(QString::fromUtf8("preview"));
gridLayout->addWidget(preview, 1, 2, 1, 1);
label_3 = new QLabel(printerGroup);
- label_3->setObjectName(QStringLiteral("label_3"));
+ label_3->setObjectName(QString::fromUtf8("label_3"));
gridLayout->addWidget(label_3, 2, 0, 1, 1);
type = new QLabel(printerGroup);
- type->setObjectName(QStringLiteral("type"));
+ type->setObjectName(QString::fromUtf8("type"));
gridLayout->addWidget(type, 2, 1, 1, 1);
lOutput = new QLabel(printerGroup);
- lOutput->setObjectName(QStringLiteral("lOutput"));
+ lOutput->setObjectName(QString::fromUtf8("lOutput"));
gridLayout->addWidget(lOutput, 3, 0, 1, 1);
horizontalLayout = new QHBoxLayout();
- horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
+ horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
filename = new QLineEdit(printerGroup);
- filename->setObjectName(QStringLiteral("filename"));
+ filename->setObjectName(QString::fromUtf8("filename"));
horizontalLayout->addWidget(filename);
fileBrowser = new QToolButton(printerGroup);
- fileBrowser->setObjectName(QStringLiteral("fileBrowser"));
+ fileBrowser->setObjectName(QString::fromUtf8("fileBrowser"));
horizontalLayout->addWidget(fileBrowser);
diff --git a/tests/auto/tools/uic/baseline/qsqlconnectiondialog.ui.h b/tests/auto/tools/uic/baseline/qsqlconnectiondialog.ui.h
index 5ed3ff1acd..2131bc6d9b 100644
--- a/tests/auto/tools/uic/baseline/qsqlconnectiondialog.ui.h
+++ b/tests/auto/tools/uic/baseline/qsqlconnectiondialog.ui.h
@@ -55,44 +55,44 @@ public:
void setupUi(QDialog *QSqlConnectionDialogUi)
{
if (QSqlConnectionDialogUi->objectName().isEmpty())
- QSqlConnectionDialogUi->setObjectName(QStringLiteral("QSqlConnectionDialogUi"));
+ QSqlConnectionDialogUi->setObjectName(QString::fromUtf8("QSqlConnectionDialogUi"));
QSqlConnectionDialogUi->resize(315, 302);
vboxLayout = new QVBoxLayout(QSqlConnectionDialogUi);
#ifndef Q_OS_MAC
vboxLayout->setSpacing(6);
#endif
vboxLayout->setContentsMargins(8, 8, 8, 8);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
connGroupBox = new QGroupBox(QSqlConnectionDialogUi);
- connGroupBox->setObjectName(QStringLiteral("connGroupBox"));
+ connGroupBox->setObjectName(QString::fromUtf8("connGroupBox"));
gridLayout = new QGridLayout(connGroupBox);
#ifndef Q_OS_MAC
gridLayout->setSpacing(6);
#endif
gridLayout->setContentsMargins(8, 8, 8, 8);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
comboDriver = new QComboBox(connGroupBox);
- comboDriver->setObjectName(QStringLiteral("comboDriver"));
+ comboDriver->setObjectName(QString::fromUtf8("comboDriver"));
gridLayout->addWidget(comboDriver, 0, 1, 1, 1);
textLabel4 = new QLabel(connGroupBox);
- textLabel4->setObjectName(QStringLiteral("textLabel4"));
+ textLabel4->setObjectName(QString::fromUtf8("textLabel4"));
gridLayout->addWidget(textLabel4, 2, 0, 1, 1);
textLabel2 = new QLabel(connGroupBox);
- textLabel2->setObjectName(QStringLiteral("textLabel2"));
+ textLabel2->setObjectName(QString::fromUtf8("textLabel2"));
gridLayout->addWidget(textLabel2, 0, 0, 1, 1);
editDatabase = new QLineEdit(connGroupBox);
- editDatabase->setObjectName(QStringLiteral("editDatabase"));
+ editDatabase->setObjectName(QString::fromUtf8("editDatabase"));
gridLayout->addWidget(editDatabase, 1, 1, 1, 1);
portSpinBox = new QSpinBox(connGroupBox);
- portSpinBox->setObjectName(QStringLiteral("portSpinBox"));
+ portSpinBox->setObjectName(QString::fromUtf8("portSpinBox"));
portSpinBox->setMaximum(65535);
portSpinBox->setMinimum(-1);
portSpinBox->setValue(-1);
@@ -100,38 +100,38 @@ public:
gridLayout->addWidget(portSpinBox, 5, 1, 1, 1);
textLabel3 = new QLabel(connGroupBox);
- textLabel3->setObjectName(QStringLiteral("textLabel3"));
+ textLabel3->setObjectName(QString::fromUtf8("textLabel3"));
gridLayout->addWidget(textLabel3, 1, 0, 1, 1);
editPassword = new QLineEdit(connGroupBox);
- editPassword->setObjectName(QStringLiteral("editPassword"));
+ editPassword->setObjectName(QString::fromUtf8("editPassword"));
editPassword->setEchoMode(QLineEdit::Password);
gridLayout->addWidget(editPassword, 3, 1, 1, 1);
editUsername = new QLineEdit(connGroupBox);
- editUsername->setObjectName(QStringLiteral("editUsername"));
+ editUsername->setObjectName(QString::fromUtf8("editUsername"));
gridLayout->addWidget(editUsername, 2, 1, 1, 1);
editHostname = new QLineEdit(connGroupBox);
- editHostname->setObjectName(QStringLiteral("editHostname"));
+ editHostname->setObjectName(QString::fromUtf8("editHostname"));
gridLayout->addWidget(editHostname, 4, 1, 1, 1);
textLabel5 = new QLabel(connGroupBox);
- textLabel5->setObjectName(QStringLiteral("textLabel5"));
+ textLabel5->setObjectName(QString::fromUtf8("textLabel5"));
gridLayout->addWidget(textLabel5, 4, 0, 1, 1);
textLabel5_2 = new QLabel(connGroupBox);
- textLabel5_2->setObjectName(QStringLiteral("textLabel5_2"));
+ textLabel5_2->setObjectName(QString::fromUtf8("textLabel5_2"));
gridLayout->addWidget(textLabel5_2, 5, 0, 1, 1);
textLabel4_2 = new QLabel(connGroupBox);
- textLabel4_2->setObjectName(QStringLiteral("textLabel4_2"));
+ textLabel4_2->setObjectName(QString::fromUtf8("textLabel4_2"));
gridLayout->addWidget(textLabel4_2, 3, 0, 1, 1);
@@ -143,13 +143,13 @@ public:
hboxLayout->setSpacing(6);
#endif
hboxLayout->setContentsMargins(0, 0, 0, 0);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
spacerItem = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
hboxLayout->addItem(spacerItem);
dbCheckBox = new QCheckBox(QSqlConnectionDialogUi);
- dbCheckBox->setObjectName(QStringLiteral("dbCheckBox"));
+ dbCheckBox->setObjectName(QString::fromUtf8("dbCheckBox"));
hboxLayout->addWidget(dbCheckBox);
@@ -161,18 +161,18 @@ public:
hboxLayout1->setSpacing(6);
#endif
hboxLayout1->setContentsMargins(0, 0, 0, 0);
- hboxLayout1->setObjectName(QStringLiteral("hboxLayout1"));
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
spacerItem1 = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
hboxLayout1->addItem(spacerItem1);
okButton = new QPushButton(QSqlConnectionDialogUi);
- okButton->setObjectName(QStringLiteral("okButton"));
+ okButton->setObjectName(QString::fromUtf8("okButton"));
hboxLayout1->addWidget(okButton);
cancelButton = new QPushButton(QSqlConnectionDialogUi);
- cancelButton->setObjectName(QStringLiteral("cancelButton"));
+ cancelButton->setObjectName(QString::fromUtf8("cancelButton"));
hboxLayout1->addWidget(cancelButton);
diff --git a/tests/auto/tools/uic/baseline/qtgradientdialog.ui.h b/tests/auto/tools/uic/baseline/qtgradientdialog.ui.h
index 53fd59295b..805f70e60d 100644
--- a/tests/auto/tools/uic/baseline/qtgradientdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/qtgradientdialog.ui.h
@@ -58,12 +58,12 @@ public:
void setupUi(QDialog *QtGradientDialog)
{
if (QtGradientDialog->objectName().isEmpty())
- QtGradientDialog->setObjectName(QStringLiteral("QtGradientDialog"));
+ QtGradientDialog->setObjectName(QString::fromUtf8("QtGradientDialog"));
QtGradientDialog->resize(178, 81);
vboxLayout = new QVBoxLayout(QtGradientDialog);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
gradientEditor = new QtGradientEditor(QtGradientDialog);
- gradientEditor->setObjectName(QStringLiteral("gradientEditor"));
+ gradientEditor->setObjectName(QString::fromUtf8("gradientEditor"));
QSizePolicy sizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -73,7 +73,7 @@ public:
vboxLayout->addWidget(gradientEditor);
buttonBox = new QDialogButtonBox(QtGradientDialog);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok);
diff --git a/tests/auto/tools/uic/baseline/qtgradienteditor.ui.h b/tests/auto/tools/uic/baseline/qtgradienteditor.ui.h
index 6e63c4863d..9db07f35ac 100644
--- a/tests/auto/tools/uic/baseline/qtgradienteditor.ui.h
+++ b/tests/auto/tools/uic/baseline/qtgradienteditor.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'qtgradienteditor.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -145,10 +145,10 @@ public:
void setupUi(QWidget *QtGradientEditor)
{
if (QtGradientEditor->objectName().isEmpty())
- QtGradientEditor->setObjectName(QStringLiteral("QtGradientEditor"));
+ QtGradientEditor->setObjectName(QString::fromUtf8("QtGradientEditor"));
QtGradientEditor->resize(364, 518);
frame = new QFrame(QtGradientEditor);
- frame->setObjectName(QStringLiteral("frame"));
+ frame->setObjectName(QString::fromUtf8("frame"));
frame->setGeometry(QRect(10, 69, 193, 150));
QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
sizePolicy.setHorizontalStretch(0);
@@ -159,73 +159,73 @@ public:
frame->setFrameShadow(QFrame::Raised);
vboxLayout = new QVBoxLayout(frame);
vboxLayout->setSpacing(6);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
vboxLayout->setContentsMargins(0, 0, 0, 0);
gradientWidget = new QtGradientWidget(frame);
- gradientWidget->setObjectName(QStringLiteral("gradientWidget"));
+ gradientWidget->setObjectName(QString::fromUtf8("gradientWidget"));
sizePolicy.setHeightForWidth(gradientWidget->sizePolicy().hasHeightForWidth());
gradientWidget->setSizePolicy(sizePolicy);
vboxLayout->addWidget(gradientWidget);
label1 = new QLabel(QtGradientEditor);
- label1->setObjectName(QStringLiteral("label1"));
+ label1->setObjectName(QString::fromUtf8("label1"));
label1->setGeometry(QRect(209, 69, 64, 23));
spinBox1 = new QDoubleSpinBox(QtGradientEditor);
- spinBox1->setObjectName(QStringLiteral("spinBox1"));
+ spinBox1->setObjectName(QString::fromUtf8("spinBox1"));
spinBox1->setGeometry(QRect(279, 69, 73, 23));
spinBox1->setKeyboardTracking(false);
spinBox1->setDecimals(3);
- spinBox1->setMaximum(1);
- spinBox1->setSingleStep(0.01);
+ spinBox1->setMaximum(1.000000000000000);
+ spinBox1->setSingleStep(0.010000000000000);
label2 = new QLabel(QtGradientEditor);
- label2->setObjectName(QStringLiteral("label2"));
+ label2->setObjectName(QString::fromUtf8("label2"));
label2->setGeometry(QRect(209, 99, 64, 23));
spinBox2 = new QDoubleSpinBox(QtGradientEditor);
- spinBox2->setObjectName(QStringLiteral("spinBox2"));
+ spinBox2->setObjectName(QString::fromUtf8("spinBox2"));
spinBox2->setGeometry(QRect(279, 99, 73, 23));
spinBox2->setKeyboardTracking(false);
spinBox2->setDecimals(3);
- spinBox2->setMaximum(1);
- spinBox2->setSingleStep(0.01);
+ spinBox2->setMaximum(1.000000000000000);
+ spinBox2->setSingleStep(0.010000000000000);
label3 = new QLabel(QtGradientEditor);
- label3->setObjectName(QStringLiteral("label3"));
+ label3->setObjectName(QString::fromUtf8("label3"));
label3->setGeometry(QRect(209, 129, 64, 23));
spinBox3 = new QDoubleSpinBox(QtGradientEditor);
- spinBox3->setObjectName(QStringLiteral("spinBox3"));
+ spinBox3->setObjectName(QString::fromUtf8("spinBox3"));
spinBox3->setGeometry(QRect(279, 129, 73, 23));
spinBox3->setKeyboardTracking(false);
spinBox3->setDecimals(3);
- spinBox3->setMaximum(1);
- spinBox3->setSingleStep(0.01);
+ spinBox3->setMaximum(1.000000000000000);
+ spinBox3->setSingleStep(0.010000000000000);
label4 = new QLabel(QtGradientEditor);
- label4->setObjectName(QStringLiteral("label4"));
+ label4->setObjectName(QString::fromUtf8("label4"));
label4->setGeometry(QRect(209, 159, 64, 23));
spinBox4 = new QDoubleSpinBox(QtGradientEditor);
- spinBox4->setObjectName(QStringLiteral("spinBox4"));
+ spinBox4->setObjectName(QString::fromUtf8("spinBox4"));
spinBox4->setGeometry(QRect(279, 159, 73, 23));
spinBox4->setKeyboardTracking(false);
spinBox4->setDecimals(3);
- spinBox4->setMaximum(1);
- spinBox4->setSingleStep(0.01);
+ spinBox4->setMaximum(1.000000000000000);
+ spinBox4->setSingleStep(0.010000000000000);
label5 = new QLabel(QtGradientEditor);
- label5->setObjectName(QStringLiteral("label5"));
+ label5->setObjectName(QString::fromUtf8("label5"));
label5->setGeometry(QRect(209, 189, 64, 23));
spinBox5 = new QDoubleSpinBox(QtGradientEditor);
- spinBox5->setObjectName(QStringLiteral("spinBox5"));
+ spinBox5->setObjectName(QString::fromUtf8("spinBox5"));
spinBox5->setGeometry(QRect(279, 189, 73, 23));
spinBox5->setKeyboardTracking(false);
spinBox5->setDecimals(3);
- spinBox5->setMaximum(1);
- spinBox5->setSingleStep(0.01);
+ spinBox5->setMaximum(1.000000000000000);
+ spinBox5->setSingleStep(0.010000000000000);
gradientStopsWidget = new QtGradientStopsWidget(QtGradientEditor);
- gradientStopsWidget->setObjectName(QStringLiteral("gradientStopsWidget"));
+ gradientStopsWidget->setObjectName(QString::fromUtf8("gradientStopsWidget"));
gradientStopsWidget->setGeometry(QRect(10, 225, 193, 67));
zoomLabel = new QLabel(QtGradientEditor);
- zoomLabel->setObjectName(QStringLiteral("zoomLabel"));
+ zoomLabel->setObjectName(QString::fromUtf8("zoomLabel"));
zoomLabel->setGeometry(QRect(209, 231, 64, 23));
zoomAllButton = new QToolButton(QtGradientEditor);
- zoomAllButton->setObjectName(QStringLiteral("zoomAllButton"));
+ zoomAllButton->setObjectName(QString::fromUtf8("zoomAllButton"));
zoomAllButton->setGeometry(QRect(279, 260, 72, 26));
QSizePolicy sizePolicy1(QSizePolicy::Preferred, QSizePolicy::Fixed);
sizePolicy1.setHorizontalStretch(0);
@@ -233,15 +233,15 @@ public:
sizePolicy1.setHeightForWidth(zoomAllButton->sizePolicy().hasHeightForWidth());
zoomAllButton->setSizePolicy(sizePolicy1);
positionLabel = new QLabel(QtGradientEditor);
- positionLabel->setObjectName(QStringLiteral("positionLabel"));
+ positionLabel->setObjectName(QString::fromUtf8("positionLabel"));
positionLabel->setGeometry(QRect(209, 304, 64, 23));
hLabel = new QLabel(QtGradientEditor);
- hLabel->setObjectName(QStringLiteral("hLabel"));
+ hLabel->setObjectName(QString::fromUtf8("hLabel"));
hLabel->setGeometry(QRect(10, 335, 32, 18));
sizePolicy1.setHeightForWidth(hLabel->sizePolicy().hasHeightForWidth());
hLabel->setSizePolicy(sizePolicy1);
frame_2 = new QFrame(QtGradientEditor);
- frame_2->setObjectName(QStringLiteral("frame_2"));
+ frame_2->setObjectName(QString::fromUtf8("frame_2"));
frame_2->setGeometry(QRect(48, 333, 155, 23));
QSizePolicy sizePolicy2(QSizePolicy::Ignored, QSizePolicy::Preferred);
sizePolicy2.setHorizontalStretch(0);
@@ -251,10 +251,10 @@ public:
frame_2->setFrameShape(QFrame::StyledPanel);
frame_2->setFrameShadow(QFrame::Raised);
hboxLayout = new QHBoxLayout(frame_2);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
hboxLayout->setContentsMargins(0, 0, 0, 0);
hueColorLine = new QtColorLine(frame_2);
- hueColorLine->setObjectName(QStringLiteral("hueColorLine"));
+ hueColorLine->setObjectName(QString::fromUtf8("hueColorLine"));
QSizePolicy sizePolicy3(QSizePolicy::Expanding, QSizePolicy::Preferred);
sizePolicy3.setHorizontalStretch(0);
sizePolicy3.setVerticalStretch(0);
@@ -264,99 +264,99 @@ public:
hboxLayout->addWidget(hueColorLine);
hueLabel = new QLabel(QtGradientEditor);
- hueLabel->setObjectName(QStringLiteral("hueLabel"));
+ hueLabel->setObjectName(QString::fromUtf8("hueLabel"));
hueLabel->setGeometry(QRect(209, 335, 64, 18));
sizePolicy1.setHeightForWidth(hueLabel->sizePolicy().hasHeightForWidth());
hueLabel->setSizePolicy(sizePolicy1);
sLabel = new QLabel(QtGradientEditor);
- sLabel->setObjectName(QStringLiteral("sLabel"));
+ sLabel->setObjectName(QString::fromUtf8("sLabel"));
sLabel->setGeometry(QRect(10, 364, 32, 18));
sizePolicy1.setHeightForWidth(sLabel->sizePolicy().hasHeightForWidth());
sLabel->setSizePolicy(sizePolicy1);
frame_5 = new QFrame(QtGradientEditor);
- frame_5->setObjectName(QStringLiteral("frame_5"));
+ frame_5->setObjectName(QString::fromUtf8("frame_5"));
frame_5->setGeometry(QRect(48, 362, 155, 23));
sizePolicy2.setHeightForWidth(frame_5->sizePolicy().hasHeightForWidth());
frame_5->setSizePolicy(sizePolicy2);
frame_5->setFrameShape(QFrame::StyledPanel);
frame_5->setFrameShadow(QFrame::Raised);
hboxLayout1 = new QHBoxLayout(frame_5);
- hboxLayout1->setObjectName(QStringLiteral("hboxLayout1"));
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
hboxLayout1->setContentsMargins(0, 0, 0, 0);
saturationColorLine = new QtColorLine(frame_5);
- saturationColorLine->setObjectName(QStringLiteral("saturationColorLine"));
+ saturationColorLine->setObjectName(QString::fromUtf8("saturationColorLine"));
sizePolicy3.setHeightForWidth(saturationColorLine->sizePolicy().hasHeightForWidth());
saturationColorLine->setSizePolicy(sizePolicy3);
hboxLayout1->addWidget(saturationColorLine);
saturationLabel = new QLabel(QtGradientEditor);
- saturationLabel->setObjectName(QStringLiteral("saturationLabel"));
+ saturationLabel->setObjectName(QString::fromUtf8("saturationLabel"));
saturationLabel->setGeometry(QRect(209, 364, 64, 18));
sizePolicy1.setHeightForWidth(saturationLabel->sizePolicy().hasHeightForWidth());
saturationLabel->setSizePolicy(sizePolicy1);
vLabel = new QLabel(QtGradientEditor);
- vLabel->setObjectName(QStringLiteral("vLabel"));
+ vLabel->setObjectName(QString::fromUtf8("vLabel"));
vLabel->setGeometry(QRect(10, 393, 32, 18));
sizePolicy1.setHeightForWidth(vLabel->sizePolicy().hasHeightForWidth());
vLabel->setSizePolicy(sizePolicy1);
frame_3 = new QFrame(QtGradientEditor);
- frame_3->setObjectName(QStringLiteral("frame_3"));
+ frame_3->setObjectName(QString::fromUtf8("frame_3"));
frame_3->setGeometry(QRect(48, 391, 155, 23));
sizePolicy2.setHeightForWidth(frame_3->sizePolicy().hasHeightForWidth());
frame_3->setSizePolicy(sizePolicy2);
frame_3->setFrameShape(QFrame::StyledPanel);
frame_3->setFrameShadow(QFrame::Raised);
hboxLayout2 = new QHBoxLayout(frame_3);
- hboxLayout2->setObjectName(QStringLiteral("hboxLayout2"));
+ hboxLayout2->setObjectName(QString::fromUtf8("hboxLayout2"));
hboxLayout2->setContentsMargins(0, 0, 0, 0);
valueColorLine = new QtColorLine(frame_3);
- valueColorLine->setObjectName(QStringLiteral("valueColorLine"));
+ valueColorLine->setObjectName(QString::fromUtf8("valueColorLine"));
sizePolicy3.setHeightForWidth(valueColorLine->sizePolicy().hasHeightForWidth());
valueColorLine->setSizePolicy(sizePolicy3);
hboxLayout2->addWidget(valueColorLine);
valueLabel = new QLabel(QtGradientEditor);
- valueLabel->setObjectName(QStringLiteral("valueLabel"));
+ valueLabel->setObjectName(QString::fromUtf8("valueLabel"));
valueLabel->setGeometry(QRect(209, 393, 64, 18));
sizePolicy1.setHeightForWidth(valueLabel->sizePolicy().hasHeightForWidth());
valueLabel->setSizePolicy(sizePolicy1);
aLabel = new QLabel(QtGradientEditor);
- aLabel->setObjectName(QStringLiteral("aLabel"));
+ aLabel->setObjectName(QString::fromUtf8("aLabel"));
aLabel->setGeometry(QRect(10, 422, 32, 18));
sizePolicy1.setHeightForWidth(aLabel->sizePolicy().hasHeightForWidth());
aLabel->setSizePolicy(sizePolicy1);
frame_4 = new QFrame(QtGradientEditor);
- frame_4->setObjectName(QStringLiteral("frame_4"));
+ frame_4->setObjectName(QString::fromUtf8("frame_4"));
frame_4->setGeometry(QRect(48, 420, 155, 23));
sizePolicy2.setHeightForWidth(frame_4->sizePolicy().hasHeightForWidth());
frame_4->setSizePolicy(sizePolicy2);
frame_4->setFrameShape(QFrame::StyledPanel);
frame_4->setFrameShadow(QFrame::Raised);
hboxLayout3 = new QHBoxLayout(frame_4);
- hboxLayout3->setObjectName(QStringLiteral("hboxLayout3"));
+ hboxLayout3->setObjectName(QString::fromUtf8("hboxLayout3"));
hboxLayout3->setContentsMargins(0, 0, 0, 0);
alphaColorLine = new QtColorLine(frame_4);
- alphaColorLine->setObjectName(QStringLiteral("alphaColorLine"));
+ alphaColorLine->setObjectName(QString::fromUtf8("alphaColorLine"));
sizePolicy3.setHeightForWidth(alphaColorLine->sizePolicy().hasHeightForWidth());
alphaColorLine->setSizePolicy(sizePolicy3);
hboxLayout3->addWidget(alphaColorLine);
alphaLabel = new QLabel(QtGradientEditor);
- alphaLabel->setObjectName(QStringLiteral("alphaLabel"));
+ alphaLabel->setObjectName(QString::fromUtf8("alphaLabel"));
alphaLabel->setGeometry(QRect(209, 422, 64, 18));
sizePolicy1.setHeightForWidth(alphaLabel->sizePolicy().hasHeightForWidth());
alphaLabel->setSizePolicy(sizePolicy1);
typeComboBox = new QComboBox(QtGradientEditor);
- typeComboBox->setObjectName(QStringLiteral("typeComboBox"));
+ typeComboBox->setObjectName(QString::fromUtf8("typeComboBox"));
typeComboBox->setGeometry(QRect(10, 40, 79, 22));
spreadComboBox = new QComboBox(QtGradientEditor);
- spreadComboBox->setObjectName(QStringLiteral("spreadComboBox"));
+ spreadComboBox->setObjectName(QString::fromUtf8("spreadComboBox"));
spreadComboBox->setGeometry(QRect(96, 40, 72, 22));
colorLabel = new QLabel(QtGradientEditor);
- colorLabel->setObjectName(QStringLiteral("colorLabel"));
+ colorLabel->setObjectName(QString::fromUtf8("colorLabel"));
colorLabel->setGeometry(QRect(10, 298, 32, 29));
QSizePolicy sizePolicy4(QSizePolicy::Fixed, QSizePolicy::Preferred);
sizePolicy4.setHorizontalStretch(0);
@@ -364,10 +364,10 @@ public:
sizePolicy4.setHeightForWidth(colorLabel->sizePolicy().hasHeightForWidth());
colorLabel->setSizePolicy(sizePolicy4);
colorButton = new QtColorButton(QtGradientEditor);
- colorButton->setObjectName(QStringLiteral("colorButton"));
+ colorButton->setObjectName(QString::fromUtf8("colorButton"));
colorButton->setGeometry(QRect(48, 300, 26, 25));
hsvRadioButton = new QRadioButton(QtGradientEditor);
- hsvRadioButton->setObjectName(QStringLiteral("hsvRadioButton"));
+ hsvRadioButton->setObjectName(QString::fromUtf8("hsvRadioButton"));
hsvRadioButton->setGeometry(QRect(80, 301, 49, 23));
QSizePolicy sizePolicy5(QSizePolicy::Fixed, QSizePolicy::Fixed);
sizePolicy5.setHorizontalStretch(0);
@@ -376,87 +376,87 @@ public:
hsvRadioButton->setSizePolicy(sizePolicy5);
hsvRadioButton->setChecked(true);
rgbRadioButton = new QRadioButton(QtGradientEditor);
- rgbRadioButton->setObjectName(QStringLiteral("rgbRadioButton"));
+ rgbRadioButton->setObjectName(QString::fromUtf8("rgbRadioButton"));
rgbRadioButton->setGeometry(QRect(135, 301, 49, 23));
sizePolicy5.setHeightForWidth(rgbRadioButton->sizePolicy().hasHeightForWidth());
rgbRadioButton->setSizePolicy(sizePolicy5);
positionWidget = new QWidget(QtGradientEditor);
- positionWidget->setObjectName(QStringLiteral("positionWidget"));
+ positionWidget->setObjectName(QString::fromUtf8("positionWidget"));
positionWidget->setGeometry(QRect(279, 304, 73, 23));
vboxLayout1 = new QVBoxLayout(positionWidget);
- vboxLayout1->setObjectName(QStringLiteral("vboxLayout1"));
+ vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
vboxLayout1->setContentsMargins(0, 0, 0, 0);
positionSpinBox = new QDoubleSpinBox(positionWidget);
- positionSpinBox->setObjectName(QStringLiteral("positionSpinBox"));
+ positionSpinBox->setObjectName(QString::fromUtf8("positionSpinBox"));
positionSpinBox->setKeyboardTracking(false);
positionSpinBox->setDecimals(3);
- positionSpinBox->setMinimum(0);
- positionSpinBox->setMaximum(1);
- positionSpinBox->setSingleStep(0.01);
- positionSpinBox->setValue(0);
+ positionSpinBox->setMinimum(0.000000000000000);
+ positionSpinBox->setMaximum(1.000000000000000);
+ positionSpinBox->setSingleStep(0.010000000000000);
+ positionSpinBox->setValue(0.000000000000000);
vboxLayout1->addWidget(positionSpinBox);
hueWidget = new QWidget(QtGradientEditor);
- hueWidget->setObjectName(QStringLiteral("hueWidget"));
+ hueWidget->setObjectName(QString::fromUtf8("hueWidget"));
hueWidget->setGeometry(QRect(279, 333, 73, 23));
vboxLayout2 = new QVBoxLayout(hueWidget);
- vboxLayout2->setObjectName(QStringLiteral("vboxLayout2"));
+ vboxLayout2->setObjectName(QString::fromUtf8("vboxLayout2"));
vboxLayout2->setContentsMargins(0, 0, 0, 0);
hueSpinBox = new QSpinBox(hueWidget);
- hueSpinBox->setObjectName(QStringLiteral("hueSpinBox"));
+ hueSpinBox->setObjectName(QString::fromUtf8("hueSpinBox"));
hueSpinBox->setKeyboardTracking(false);
hueSpinBox->setMaximum(359);
vboxLayout2->addWidget(hueSpinBox);
saturationWidget = new QWidget(QtGradientEditor);
- saturationWidget->setObjectName(QStringLiteral("saturationWidget"));
+ saturationWidget->setObjectName(QString::fromUtf8("saturationWidget"));
saturationWidget->setGeometry(QRect(279, 362, 73, 23));
vboxLayout3 = new QVBoxLayout(saturationWidget);
- vboxLayout3->setObjectName(QStringLiteral("vboxLayout3"));
+ vboxLayout3->setObjectName(QString::fromUtf8("vboxLayout3"));
vboxLayout3->setContentsMargins(0, 0, 0, 0);
saturationSpinBox = new QSpinBox(saturationWidget);
- saturationSpinBox->setObjectName(QStringLiteral("saturationSpinBox"));
+ saturationSpinBox->setObjectName(QString::fromUtf8("saturationSpinBox"));
saturationSpinBox->setKeyboardTracking(false);
saturationSpinBox->setMaximum(255);
vboxLayout3->addWidget(saturationSpinBox);
valueWidget = new QWidget(QtGradientEditor);
- valueWidget->setObjectName(QStringLiteral("valueWidget"));
+ valueWidget->setObjectName(QString::fromUtf8("valueWidget"));
valueWidget->setGeometry(QRect(279, 391, 73, 23));
vboxLayout4 = new QVBoxLayout(valueWidget);
- vboxLayout4->setObjectName(QStringLiteral("vboxLayout4"));
+ vboxLayout4->setObjectName(QString::fromUtf8("vboxLayout4"));
vboxLayout4->setContentsMargins(0, 0, 0, 0);
valueSpinBox = new QSpinBox(valueWidget);
- valueSpinBox->setObjectName(QStringLiteral("valueSpinBox"));
+ valueSpinBox->setObjectName(QString::fromUtf8("valueSpinBox"));
valueSpinBox->setKeyboardTracking(false);
valueSpinBox->setMaximum(255);
vboxLayout4->addWidget(valueSpinBox);
alphaWidget = new QWidget(QtGradientEditor);
- alphaWidget->setObjectName(QStringLiteral("alphaWidget"));
+ alphaWidget->setObjectName(QString::fromUtf8("alphaWidget"));
alphaWidget->setGeometry(QRect(279, 420, 73, 23));
vboxLayout5 = new QVBoxLayout(alphaWidget);
- vboxLayout5->setObjectName(QStringLiteral("vboxLayout5"));
+ vboxLayout5->setObjectName(QString::fromUtf8("vboxLayout5"));
vboxLayout5->setContentsMargins(0, 0, 0, 0);
alphaSpinBox = new QSpinBox(alphaWidget);
- alphaSpinBox->setObjectName(QStringLiteral("alphaSpinBox"));
+ alphaSpinBox->setObjectName(QString::fromUtf8("alphaSpinBox"));
alphaSpinBox->setKeyboardTracking(false);
alphaSpinBox->setMaximum(255);
vboxLayout5->addWidget(alphaSpinBox);
zoomWidget = new QWidget(QtGradientEditor);
- zoomWidget->setObjectName(QStringLiteral("zoomWidget"));
+ zoomWidget->setObjectName(QString::fromUtf8("zoomWidget"));
zoomWidget->setGeometry(QRect(279, 231, 73, 23));
vboxLayout6 = new QVBoxLayout(zoomWidget);
- vboxLayout6->setObjectName(QStringLiteral("vboxLayout6"));
+ vboxLayout6->setObjectName(QString::fromUtf8("vboxLayout6"));
vboxLayout6->setContentsMargins(0, 0, 0, 0);
zoomSpinBox = new QSpinBox(zoomWidget);
- zoomSpinBox->setObjectName(QStringLiteral("zoomSpinBox"));
+ zoomSpinBox->setObjectName(QString::fromUtf8("zoomSpinBox"));
zoomSpinBox->setKeyboardTracking(false);
zoomSpinBox->setMinimum(100);
zoomSpinBox->setMaximum(10000);
@@ -466,33 +466,33 @@ public:
vboxLayout6->addWidget(zoomSpinBox);
line1Widget = new QWidget(QtGradientEditor);
- line1Widget->setObjectName(QStringLiteral("line1Widget"));
+ line1Widget->setObjectName(QString::fromUtf8("line1Widget"));
line1Widget->setGeometry(QRect(209, 219, 143, 16));
vboxLayout7 = new QVBoxLayout(line1Widget);
- vboxLayout7->setObjectName(QStringLiteral("vboxLayout7"));
+ vboxLayout7->setObjectName(QString::fromUtf8("vboxLayout7"));
vboxLayout7->setContentsMargins(0, 0, 0, 0);
line1 = new QFrame(line1Widget);
- line1->setObjectName(QStringLiteral("line1"));
+ line1->setObjectName(QString::fromUtf8("line1"));
line1->setFrameShape(QFrame::HLine);
line1->setFrameShadow(QFrame::Sunken);
vboxLayout7->addWidget(line1);
line2Widget = new QWidget(QtGradientEditor);
- line2Widget->setObjectName(QStringLiteral("line2Widget"));
+ line2Widget->setObjectName(QString::fromUtf8("line2Widget"));
line2Widget->setGeometry(QRect(209, 292, 143, 16));
vboxLayout8 = new QVBoxLayout(line2Widget);
- vboxLayout8->setObjectName(QStringLiteral("vboxLayout8"));
+ vboxLayout8->setObjectName(QString::fromUtf8("vboxLayout8"));
vboxLayout8->setContentsMargins(0, 0, 0, 0);
line2 = new QFrame(line2Widget);
- line2->setObjectName(QStringLiteral("line2"));
+ line2->setObjectName(QString::fromUtf8("line2"));
line2->setFrameShape(QFrame::HLine);
line2->setFrameShadow(QFrame::Sunken);
vboxLayout8->addWidget(line2);
zoomButtonsWidget = new QWidget(QtGradientEditor);
- zoomButtonsWidget->setObjectName(QStringLiteral("zoomButtonsWidget"));
+ zoomButtonsWidget->setObjectName(QString::fromUtf8("zoomButtonsWidget"));
zoomButtonsWidget->setGeometry(QRect(209, 260, 64, 26));
QSizePolicy sizePolicy6(QSizePolicy::Maximum, QSizePolicy::Preferred);
sizePolicy6.setHorizontalStretch(0);
@@ -500,15 +500,15 @@ public:
sizePolicy6.setHeightForWidth(zoomButtonsWidget->sizePolicy().hasHeightForWidth());
zoomButtonsWidget->setSizePolicy(sizePolicy6);
hboxLayout4 = new QHBoxLayout(zoomButtonsWidget);
- hboxLayout4->setObjectName(QStringLiteral("hboxLayout4"));
+ hboxLayout4->setObjectName(QString::fromUtf8("hboxLayout4"));
hboxLayout4->setContentsMargins(0, 0, 0, 0);
zoomInButton = new QToolButton(zoomButtonsWidget);
- zoomInButton->setObjectName(QStringLiteral("zoomInButton"));
+ zoomInButton->setObjectName(QString::fromUtf8("zoomInButton"));
hboxLayout4->addWidget(zoomInButton);
zoomOutButton = new QToolButton(zoomButtonsWidget);
- zoomOutButton->setObjectName(QStringLiteral("zoomOutButton"));
+ zoomOutButton->setObjectName(QString::fromUtf8("zoomOutButton"));
hboxLayout4->addWidget(zoomOutButton);
@@ -517,7 +517,7 @@ public:
hboxLayout4->addItem(spacerItem);
detailsButton = new QToolButton(QtGradientEditor);
- detailsButton->setObjectName(QStringLiteral("detailsButton"));
+ detailsButton->setObjectName(QString::fromUtf8("detailsButton"));
detailsButton->setGeometry(QRect(176, 40, 25, 22));
QSizePolicy sizePolicy7(QSizePolicy::Fixed, QSizePolicy::Ignored);
sizePolicy7.setHorizontalStretch(0);
@@ -527,32 +527,32 @@ public:
detailsButton->setCheckable(true);
detailsButton->setAutoRaise(true);
linearButton = new QToolButton(QtGradientEditor);
- linearButton->setObjectName(QStringLiteral("linearButton"));
+ linearButton->setObjectName(QString::fromUtf8("linearButton"));
linearButton->setGeometry(QRect(10, 10, 30, 26));
linearButton->setCheckable(true);
linearButton->setAutoRaise(true);
radialButton = new QToolButton(QtGradientEditor);
- radialButton->setObjectName(QStringLiteral("radialButton"));
+ radialButton->setObjectName(QString::fromUtf8("radialButton"));
radialButton->setGeometry(QRect(40, 10, 30, 26));
radialButton->setCheckable(true);
radialButton->setAutoRaise(true);
conicalButton = new QToolButton(QtGradientEditor);
- conicalButton->setObjectName(QStringLiteral("conicalButton"));
+ conicalButton->setObjectName(QString::fromUtf8("conicalButton"));
conicalButton->setGeometry(QRect(70, 10, 30, 26));
conicalButton->setCheckable(true);
conicalButton->setAutoRaise(true);
padButton = new QToolButton(QtGradientEditor);
- padButton->setObjectName(QStringLiteral("padButton"));
+ padButton->setObjectName(QString::fromUtf8("padButton"));
padButton->setGeometry(QRect(110, 10, 30, 26));
padButton->setCheckable(true);
padButton->setAutoRaise(true);
repeatButton = new QToolButton(QtGradientEditor);
- repeatButton->setObjectName(QStringLiteral("repeatButton"));
+ repeatButton->setObjectName(QString::fromUtf8("repeatButton"));
repeatButton->setGeometry(QRect(140, 10, 30, 26));
repeatButton->setCheckable(true);
repeatButton->setAutoRaise(true);
reflectButton = new QToolButton(QtGradientEditor);
- reflectButton->setObjectName(QStringLiteral("reflectButton"));
+ reflectButton->setObjectName(QString::fromUtf8("reflectButton"));
reflectButton->setGeometry(QRect(170, 10, 30, 26));
reflectButton->setCheckable(true);
reflectButton->setAutoRaise(true);
diff --git a/tests/auto/tools/uic/baseline/qtgradientview.ui.h b/tests/auto/tools/uic/baseline/qtgradientview.ui.h
index 4d51c2400e..aa3c03b02f 100644
--- a/tests/auto/tools/uic/baseline/qtgradientview.ui.h
+++ b/tests/auto/tools/uic/baseline/qtgradientview.ui.h
@@ -35,15 +35,15 @@ public:
void setupUi(QWidget *QtGradientView)
{
if (QtGradientView->objectName().isEmpty())
- QtGradientView->setObjectName(QStringLiteral("QtGradientView"));
+ QtGradientView->setObjectName(QString::fromUtf8("QtGradientView"));
QtGradientView->resize(484, 228);
vboxLayout = new QVBoxLayout(QtGradientView);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
vboxLayout->setContentsMargins(0, 0, 0, 0);
hboxLayout = new QHBoxLayout();
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
newButton = new QToolButton(QtGradientView);
- newButton->setObjectName(QStringLiteral("newButton"));
+ newButton->setObjectName(QString::fromUtf8("newButton"));
QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -55,7 +55,7 @@ public:
hboxLayout->addWidget(newButton);
editButton = new QToolButton(QtGradientView);
- editButton->setObjectName(QStringLiteral("editButton"));
+ editButton->setObjectName(QString::fromUtf8("editButton"));
sizePolicy.setHeightForWidth(editButton->sizePolicy().hasHeightForWidth());
editButton->setSizePolicy(sizePolicy);
editButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
@@ -64,7 +64,7 @@ public:
hboxLayout->addWidget(editButton);
renameButton = new QToolButton(QtGradientView);
- renameButton->setObjectName(QStringLiteral("renameButton"));
+ renameButton->setObjectName(QString::fromUtf8("renameButton"));
sizePolicy.setHeightForWidth(renameButton->sizePolicy().hasHeightForWidth());
renameButton->setSizePolicy(sizePolicy);
renameButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
@@ -73,7 +73,7 @@ public:
hboxLayout->addWidget(renameButton);
removeButton = new QToolButton(QtGradientView);
- removeButton->setObjectName(QStringLiteral("removeButton"));
+ removeButton->setObjectName(QString::fromUtf8("removeButton"));
sizePolicy.setHeightForWidth(removeButton->sizePolicy().hasHeightForWidth());
removeButton->setSizePolicy(sizePolicy);
removeButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
@@ -89,7 +89,7 @@ public:
vboxLayout->addLayout(hboxLayout);
listWidget = new QListWidget(QtGradientView);
- listWidget->setObjectName(QStringLiteral("listWidget"));
+ listWidget->setObjectName(QString::fromUtf8("listWidget"));
vboxLayout->addWidget(listWidget);
diff --git a/tests/auto/tools/uic/baseline/qtgradientviewdialog.ui.h b/tests/auto/tools/uic/baseline/qtgradientviewdialog.ui.h
index 74fe3745c9..e6d98ed4f0 100644
--- a/tests/auto/tools/uic/baseline/qtgradientviewdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/qtgradientviewdialog.ui.h
@@ -58,12 +58,12 @@ public:
void setupUi(QDialog *QtGradientViewDialog)
{
if (QtGradientViewDialog->objectName().isEmpty())
- QtGradientViewDialog->setObjectName(QStringLiteral("QtGradientViewDialog"));
+ QtGradientViewDialog->setObjectName(QString::fromUtf8("QtGradientViewDialog"));
QtGradientViewDialog->resize(178, 72);
vboxLayout = new QVBoxLayout(QtGradientViewDialog);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
gradientView = new QtGradientView(QtGradientViewDialog);
- gradientView->setObjectName(QStringLiteral("gradientView"));
+ gradientView->setObjectName(QString::fromUtf8("gradientView"));
QSizePolicy sizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -73,7 +73,7 @@ public:
vboxLayout->addWidget(gradientView);
buttonBox = new QDialogButtonBox(QtGradientViewDialog);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
diff --git a/tests/auto/tools/uic/baseline/qtresourceeditordialog.ui.h b/tests/auto/tools/uic/baseline/qtresourceeditordialog.ui.h
index 62d99b3235..6a8c9c7172 100644
--- a/tests/auto/tools/uic/baseline/qtresourceeditordialog.ui.h
+++ b/tests/auto/tools/uic/baseline/qtresourceeditordialog.ui.h
@@ -49,20 +49,20 @@ public:
void setupUi(QDialog *QtResourceEditorDialog)
{
if (QtResourceEditorDialog->objectName().isEmpty())
- QtResourceEditorDialog->setObjectName(QStringLiteral("QtResourceEditorDialog"));
+ QtResourceEditorDialog->setObjectName(QString::fromUtf8("QtResourceEditorDialog"));
QtResourceEditorDialog->resize(469, 317);
verticalLayout = new QVBoxLayout(QtResourceEditorDialog);
- verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
+ verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
splitter = new QSplitter(QtResourceEditorDialog);
- splitter->setObjectName(QStringLiteral("splitter"));
+ splitter->setObjectName(QString::fromUtf8("splitter"));
splitter->setOrientation(Qt::Horizontal);
layoutWidget = new QWidget(splitter);
- layoutWidget->setObjectName(QStringLiteral("layoutWidget"));
+ layoutWidget->setObjectName(QString::fromUtf8("layoutWidget"));
gridLayout = new QGridLayout(layoutWidget);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
gridLayout->setContentsMargins(0, 0, 0, 0);
qrcFileList = new QListWidget(layoutWidget);
- qrcFileList->setObjectName(QStringLiteral("qrcFileList"));
+ qrcFileList->setObjectName(QString::fromUtf8("qrcFileList"));
QSizePolicy sizePolicy(QSizePolicy::Ignored, QSizePolicy::Expanding);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -72,12 +72,12 @@ public:
gridLayout->addWidget(qrcFileList, 0, 0, 1, 4);
newQrcButton = new QToolButton(layoutWidget);
- newQrcButton->setObjectName(QStringLiteral("newQrcButton"));
+ newQrcButton->setObjectName(QString::fromUtf8("newQrcButton"));
gridLayout->addWidget(newQrcButton, 1, 0, 1, 1);
removeQrcButton = new QToolButton(layoutWidget);
- removeQrcButton->setObjectName(QStringLiteral("removeQrcButton"));
+ removeQrcButton->setObjectName(QString::fromUtf8("removeQrcButton"));
gridLayout->addWidget(removeQrcButton, 1, 2, 1, 1);
@@ -86,33 +86,33 @@ public:
gridLayout->addItem(spacerItem, 1, 3, 1, 1);
importQrcButton = new QToolButton(layoutWidget);
- importQrcButton->setObjectName(QStringLiteral("importQrcButton"));
+ importQrcButton->setObjectName(QString::fromUtf8("importQrcButton"));
gridLayout->addWidget(importQrcButton, 1, 1, 1, 1);
splitter->addWidget(layoutWidget);
widget = new QWidget(splitter);
- widget->setObjectName(QStringLiteral("widget"));
+ widget->setObjectName(QString::fromUtf8("widget"));
gridLayout1 = new QGridLayout(widget);
- gridLayout1->setObjectName(QStringLiteral("gridLayout1"));
+ gridLayout1->setObjectName(QString::fromUtf8("gridLayout1"));
gridLayout1->setContentsMargins(0, 0, 0, 0);
resourceTreeView = new QTreeView(widget);
- resourceTreeView->setObjectName(QStringLiteral("resourceTreeView"));
+ resourceTreeView->setObjectName(QString::fromUtf8("resourceTreeView"));
gridLayout1->addWidget(resourceTreeView, 0, 0, 1, 4);
newResourceButton = new QToolButton(widget);
- newResourceButton->setObjectName(QStringLiteral("newResourceButton"));
+ newResourceButton->setObjectName(QString::fromUtf8("newResourceButton"));
gridLayout1->addWidget(newResourceButton, 1, 0, 1, 1);
addResourceButton = new QToolButton(widget);
- addResourceButton->setObjectName(QStringLiteral("addResourceButton"));
+ addResourceButton->setObjectName(QString::fromUtf8("addResourceButton"));
gridLayout1->addWidget(addResourceButton, 1, 1, 1, 1);
removeResourceButton = new QToolButton(widget);
- removeResourceButton->setObjectName(QStringLiteral("removeResourceButton"));
+ removeResourceButton->setObjectName(QString::fromUtf8("removeResourceButton"));
gridLayout1->addWidget(removeResourceButton, 1, 2, 1, 1);
@@ -125,7 +125,7 @@ public:
verticalLayout->addWidget(splitter);
buttonBox = new QDialogButtonBox(QtResourceEditorDialog);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
diff --git a/tests/auto/tools/uic/baseline/qttoolbardialog.ui.h b/tests/auto/tools/uic/baseline/qttoolbardialog.ui.h
index 1c546aa196..e893386d9b 100644
--- a/tests/auto/tools/uic/baseline/qttoolbardialog.ui.h
+++ b/tests/auto/tools/uic/baseline/qttoolbardialog.ui.h
@@ -50,21 +50,21 @@ public:
void setupUi(QDialog *QtToolBarDialog)
{
if (QtToolBarDialog->objectName().isEmpty())
- QtToolBarDialog->setObjectName(QStringLiteral("QtToolBarDialog"));
+ QtToolBarDialog->setObjectName(QString::fromUtf8("QtToolBarDialog"));
QtToolBarDialog->resize(583, 508);
gridLayout = new QGridLayout(QtToolBarDialog);
#ifndef Q_OS_MAC
gridLayout->setSpacing(6);
#endif
gridLayout->setContentsMargins(8, 8, 8, 8);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
actionTree = new QTreeWidget(QtToolBarDialog);
- actionTree->setObjectName(QStringLiteral("actionTree"));
+ actionTree->setObjectName(QString::fromUtf8("actionTree"));
gridLayout->addWidget(actionTree, 1, 0, 3, 1);
label = new QLabel(QtToolBarDialog);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
gridLayout->addWidget(label, 0, 0, 1, 1);
@@ -73,24 +73,24 @@ public:
hboxLayout->setSpacing(6);
#endif
hboxLayout->setContentsMargins(0, 0, 0, 0);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
label_2 = new QLabel(QtToolBarDialog);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
hboxLayout->addWidget(label_2);
newButton = new QToolButton(QtToolBarDialog);
- newButton->setObjectName(QStringLiteral("newButton"));
+ newButton->setObjectName(QString::fromUtf8("newButton"));
hboxLayout->addWidget(newButton);
removeButton = new QToolButton(QtToolBarDialog);
- removeButton->setObjectName(QStringLiteral("removeButton"));
+ removeButton->setObjectName(QString::fromUtf8("removeButton"));
hboxLayout->addWidget(removeButton);
renameButton = new QToolButton(QtToolBarDialog);
- renameButton->setObjectName(QStringLiteral("renameButton"));
+ renameButton->setObjectName(QString::fromUtf8("renameButton"));
hboxLayout->addWidget(renameButton);
@@ -102,9 +102,9 @@ public:
vboxLayout->setSpacing(6);
#endif
vboxLayout->setContentsMargins(0, 0, 0, 0);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
upButton = new QToolButton(QtToolBarDialog);
- upButton->setObjectName(QStringLiteral("upButton"));
+ upButton->setObjectName(QString::fromUtf8("upButton"));
QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -114,21 +114,21 @@ public:
vboxLayout->addWidget(upButton);
leftButton = new QToolButton(QtToolBarDialog);
- leftButton->setObjectName(QStringLiteral("leftButton"));
+ leftButton->setObjectName(QString::fromUtf8("leftButton"));
sizePolicy.setHeightForWidth(leftButton->sizePolicy().hasHeightForWidth());
leftButton->setSizePolicy(sizePolicy);
vboxLayout->addWidget(leftButton);
rightButton = new QToolButton(QtToolBarDialog);
- rightButton->setObjectName(QStringLiteral("rightButton"));
+ rightButton->setObjectName(QString::fromUtf8("rightButton"));
sizePolicy.setHeightForWidth(rightButton->sizePolicy().hasHeightForWidth());
rightButton->setSizePolicy(sizePolicy);
vboxLayout->addWidget(rightButton);
downButton = new QToolButton(QtToolBarDialog);
- downButton->setObjectName(QStringLiteral("downButton"));
+ downButton->setObjectName(QString::fromUtf8("downButton"));
sizePolicy.setHeightForWidth(downButton->sizePolicy().hasHeightForWidth());
downButton->setSizePolicy(sizePolicy);
@@ -142,22 +142,22 @@ public:
gridLayout->addLayout(vboxLayout, 3, 1, 1, 1);
currentToolBarList = new QListWidget(QtToolBarDialog);
- currentToolBarList->setObjectName(QStringLiteral("currentToolBarList"));
+ currentToolBarList->setObjectName(QString::fromUtf8("currentToolBarList"));
gridLayout->addWidget(currentToolBarList, 3, 2, 1, 1);
label_3 = new QLabel(QtToolBarDialog);
- label_3->setObjectName(QStringLiteral("label_3"));
+ label_3->setObjectName(QString::fromUtf8("label_3"));
gridLayout->addWidget(label_3, 2, 1, 1, 2);
toolBarList = new QListWidget(QtToolBarDialog);
- toolBarList->setObjectName(QStringLiteral("toolBarList"));
+ toolBarList->setObjectName(QString::fromUtf8("toolBarList"));
gridLayout->addWidget(toolBarList, 1, 1, 1, 2);
buttonBox = new QDialogButtonBox(QtToolBarDialog);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setStandardButtons(QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults);
gridLayout->addWidget(buttonBox, 5, 0, 1, 3);
diff --git a/tests/auto/tools/uic/baseline/qttrid.ui.h b/tests/auto/tools/uic/baseline/qttrid.ui.h
index b7ec1062de..890ffc7789 100644
--- a/tests/auto/tools/uic/baseline/qttrid.ui.h
+++ b/tests/auto/tools/uic/baseline/qttrid.ui.h
@@ -67,28 +67,28 @@ public:
void setupUi(QMainWindow *RemoteControlClass)
{
if (RemoteControlClass->objectName().isEmpty())
- RemoteControlClass->setObjectName(QStringLiteral("RemoteControlClass"));
+ RemoteControlClass->setObjectName(QString::fromUtf8("RemoteControlClass"));
RemoteControlClass->resize(344, 364);
actionQuit = new QAction(RemoteControlClass);
- actionQuit->setObjectName(QStringLiteral("actionQuit"));
+ actionQuit->setObjectName(QString::fromUtf8("actionQuit"));
centralWidget = new QWidget(RemoteControlClass);
- centralWidget->setObjectName(QStringLiteral("centralWidget"));
+ centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
gridLayout = new QGridLayout(centralWidget);
gridLayout->setSpacing(6);
gridLayout->setContentsMargins(11, 11, 11, 11);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
label = new QLabel(centralWidget);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
gridLayout->addWidget(label, 0, 0, 1, 1);
startUrlLineEdit = new QLineEdit(centralWidget);
- startUrlLineEdit->setObjectName(QStringLiteral("startUrlLineEdit"));
+ startUrlLineEdit->setObjectName(QString::fromUtf8("startUrlLineEdit"));
gridLayout->addWidget(startUrlLineEdit, 0, 1, 1, 2);
launchButton = new QPushButton(centralWidget);
- launchButton->setObjectName(QStringLiteral("launchButton"));
+ launchButton->setObjectName(QString::fromUtf8("launchButton"));
gridLayout->addWidget(launchButton, 1, 1, 1, 1);
@@ -101,27 +101,27 @@ public:
gridLayout->addItem(spacerItem1, 2, 1, 1, 1);
actionGroupBox = new QGroupBox(centralWidget);
- actionGroupBox->setObjectName(QStringLiteral("actionGroupBox"));
+ actionGroupBox->setObjectName(QString::fromUtf8("actionGroupBox"));
actionGroupBox->setEnabled(false);
gridLayout1 = new QGridLayout(actionGroupBox);
gridLayout1->setSpacing(6);
gridLayout1->setContentsMargins(11, 11, 11, 11);
- gridLayout1->setObjectName(QStringLiteral("gridLayout1"));
+ gridLayout1->setObjectName(QString::fromUtf8("gridLayout1"));
label_2 = new QLabel(actionGroupBox);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
gridLayout1->addWidget(label_2, 0, 0, 1, 1);
hboxLayout = new QHBoxLayout();
hboxLayout->setSpacing(0);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
indexLineEdit = new QLineEdit(actionGroupBox);
- indexLineEdit->setObjectName(QStringLiteral("indexLineEdit"));
+ indexLineEdit->setObjectName(QString::fromUtf8("indexLineEdit"));
hboxLayout->addWidget(indexLineEdit);
indexButton = new QToolButton(actionGroupBox);
- indexButton->setObjectName(QStringLiteral("indexButton"));
+ indexButton->setObjectName(QString::fromUtf8("indexButton"));
const QIcon icon = QIcon(QString::fromUtf8(":/remotecontrol/enter.png"));
indexButton->setIcon(icon);
@@ -131,20 +131,20 @@ public:
gridLayout1->addLayout(hboxLayout, 0, 1, 1, 2);
label_4 = new QLabel(actionGroupBox);
- label_4->setObjectName(QStringLiteral("label_4"));
+ label_4->setObjectName(QString::fromUtf8("label_4"));
gridLayout1->addWidget(label_4, 1, 0, 1, 1);
hboxLayout1 = new QHBoxLayout();
hboxLayout1->setSpacing(0);
- hboxLayout1->setObjectName(QStringLiteral("hboxLayout1"));
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
identifierLineEdit = new QLineEdit(actionGroupBox);
- identifierLineEdit->setObjectName(QStringLiteral("identifierLineEdit"));
+ identifierLineEdit->setObjectName(QString::fromUtf8("identifierLineEdit"));
hboxLayout1->addWidget(identifierLineEdit);
identifierButton = new QToolButton(actionGroupBox);
- identifierButton->setObjectName(QStringLiteral("identifierButton"));
+ identifierButton->setObjectName(QString::fromUtf8("identifierButton"));
identifierButton->setIcon(icon);
hboxLayout1->addWidget(identifierButton);
@@ -153,20 +153,20 @@ public:
gridLayout1->addLayout(hboxLayout1, 1, 1, 1, 2);
label_3 = new QLabel(actionGroupBox);
- label_3->setObjectName(QStringLiteral("label_3"));
+ label_3->setObjectName(QString::fromUtf8("label_3"));
gridLayout1->addWidget(label_3, 2, 0, 1, 1);
hboxLayout2 = new QHBoxLayout();
hboxLayout2->setSpacing(0);
- hboxLayout2->setObjectName(QStringLiteral("hboxLayout2"));
+ hboxLayout2->setObjectName(QString::fromUtf8("hboxLayout2"));
urlLineEdit = new QLineEdit(actionGroupBox);
- urlLineEdit->setObjectName(QStringLiteral("urlLineEdit"));
+ urlLineEdit->setObjectName(QString::fromUtf8("urlLineEdit"));
hboxLayout2->addWidget(urlLineEdit);
urlButton = new QToolButton(actionGroupBox);
- urlButton->setObjectName(QStringLiteral("urlButton"));
+ urlButton->setObjectName(QString::fromUtf8("urlButton"));
urlButton->setIcon(icon);
hboxLayout2->addWidget(urlButton);
@@ -175,7 +175,7 @@ public:
gridLayout1->addLayout(hboxLayout2, 2, 1, 1, 2);
syncContentsButton = new QPushButton(actionGroupBox);
- syncContentsButton->setObjectName(QStringLiteral("syncContentsButton"));
+ syncContentsButton->setObjectName(QString::fromUtf8("syncContentsButton"));
gridLayout1->addWidget(syncContentsButton, 3, 1, 1, 1);
@@ -184,17 +184,17 @@ public:
gridLayout1->addItem(spacerItem2, 3, 2, 1, 1);
contentsCheckBox = new QCheckBox(actionGroupBox);
- contentsCheckBox->setObjectName(QStringLiteral("contentsCheckBox"));
+ contentsCheckBox->setObjectName(QString::fromUtf8("contentsCheckBox"));
gridLayout1->addWidget(contentsCheckBox, 4, 0, 1, 3);
indexCheckBox = new QCheckBox(actionGroupBox);
- indexCheckBox->setObjectName(QStringLiteral("indexCheckBox"));
+ indexCheckBox->setObjectName(QString::fromUtf8("indexCheckBox"));
gridLayout1->addWidget(indexCheckBox, 5, 0, 1, 1);
bookmarksCheckBox = new QCheckBox(actionGroupBox);
- bookmarksCheckBox->setObjectName(QStringLiteral("bookmarksCheckBox"));
+ bookmarksCheckBox->setObjectName(QString::fromUtf8("bookmarksCheckBox"));
gridLayout1->addWidget(bookmarksCheckBox, 6, 0, 1, 3);
@@ -203,13 +203,13 @@ public:
RemoteControlClass->setCentralWidget(centralWidget);
menuBar = new QMenuBar(RemoteControlClass);
- menuBar->setObjectName(QStringLiteral("menuBar"));
+ menuBar->setObjectName(QString::fromUtf8("menuBar"));
menuBar->setGeometry(QRect(0, 0, 344, 21));
menuFile = new QMenu(menuBar);
- menuFile->setObjectName(QStringLiteral("menuFile"));
+ menuFile->setObjectName(QString::fromUtf8("menuFile"));
RemoteControlClass->setMenuBar(menuBar);
statusBar = new QStatusBar(RemoteControlClass);
- statusBar->setObjectName(QStringLiteral("statusBar"));
+ statusBar->setObjectName(QString::fromUtf8("statusBar"));
RemoteControlClass->setStatusBar(statusBar);
menuBar->addAction(menuFile->menuAction());
diff --git a/tests/auto/tools/uic/baseline/querywidget.ui.h b/tests/auto/tools/uic/baseline/querywidget.ui.h
index 0e941a0e5e..81516722d5 100644
--- a/tests/auto/tools/uic/baseline/querywidget.ui.h
+++ b/tests/auto/tools/uic/baseline/querywidget.ui.h
@@ -46,13 +46,13 @@ public:
void setupUi(QMainWindow *QueryWidget)
{
if (QueryWidget->objectName().isEmpty())
- QueryWidget->setObjectName(QStringLiteral("QueryWidget"));
+ QueryWidget->setObjectName(QString::fromUtf8("QueryWidget"));
QueryWidget->resize(545, 531);
centralwidget = new QWidget(QueryWidget);
- centralwidget->setObjectName(QStringLiteral("centralwidget"));
+ centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
centralwidget->setGeometry(QRect(0, 29, 545, 480));
verticalLayout = new QVBoxLayout(centralwidget);
- verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
+ verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
vboxLayout = new QVBoxLayout();
#ifndef Q_OS_MAC
vboxLayout->setSpacing(6);
@@ -60,12 +60,12 @@ public:
#ifndef Q_OS_MAC
vboxLayout->setContentsMargins(0, 0, 0, 0);
#endif
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
inputGroupBox = new QGroupBox(centralwidget);
- inputGroupBox->setObjectName(QStringLiteral("inputGroupBox"));
+ inputGroupBox->setObjectName(QString::fromUtf8("inputGroupBox"));
inputGroupBox->setMinimumSize(QSize(550, 120));
verticalLayout_4 = new QVBoxLayout(inputGroupBox);
- verticalLayout_4->setObjectName(QStringLiteral("verticalLayout_4"));
+ verticalLayout_4->setObjectName(QString::fromUtf8("verticalLayout_4"));
_2 = new QVBoxLayout();
#ifndef Q_OS_MAC
_2->setSpacing(6);
@@ -73,9 +73,9 @@ public:
#ifndef Q_OS_MAC
_2->setContentsMargins(0, 0, 0, 0);
#endif
- _2->setObjectName(QStringLiteral("_2"));
+ _2->setObjectName(QString::fromUtf8("_2"));
inputTextEdit = new QTextEdit(inputGroupBox);
- inputTextEdit->setObjectName(QStringLiteral("inputTextEdit"));
+ inputTextEdit->setObjectName(QString::fromUtf8("inputTextEdit"));
_2->addWidget(inputTextEdit);
@@ -86,17 +86,17 @@ public:
vboxLayout->addWidget(inputGroupBox);
queryGroupBox = new QGroupBox(centralwidget);
- queryGroupBox->setObjectName(QStringLiteral("queryGroupBox"));
+ queryGroupBox->setObjectName(QString::fromUtf8("queryGroupBox"));
queryGroupBox->setMinimumSize(QSize(550, 120));
verticalLayout_5 = new QVBoxLayout(queryGroupBox);
- verticalLayout_5->setObjectName(QStringLiteral("verticalLayout_5"));
+ verticalLayout_5->setObjectName(QString::fromUtf8("verticalLayout_5"));
defaultQueries = new QComboBox(queryGroupBox);
- defaultQueries->setObjectName(QStringLiteral("defaultQueries"));
+ defaultQueries->setObjectName(QString::fromUtf8("defaultQueries"));
verticalLayout_5->addWidget(defaultQueries);
queryTextEdit = new QTextEdit(queryGroupBox);
- queryTextEdit->setObjectName(QStringLiteral("queryTextEdit"));
+ queryTextEdit->setObjectName(QString::fromUtf8("queryTextEdit"));
queryTextEdit->setMinimumSize(QSize(400, 60));
queryTextEdit->setReadOnly(true);
queryTextEdit->setAcceptRichText(false);
@@ -107,10 +107,10 @@ public:
vboxLayout->addWidget(queryGroupBox);
outputGroupBox = new QGroupBox(centralwidget);
- outputGroupBox->setObjectName(QStringLiteral("outputGroupBox"));
+ outputGroupBox->setObjectName(QString::fromUtf8("outputGroupBox"));
outputGroupBox->setMinimumSize(QSize(550, 120));
verticalLayout_6 = new QVBoxLayout(outputGroupBox);
- verticalLayout_6->setObjectName(QStringLiteral("verticalLayout_6"));
+ verticalLayout_6->setObjectName(QString::fromUtf8("verticalLayout_6"));
_3 = new QVBoxLayout();
#ifndef Q_OS_MAC
_3->setSpacing(6);
@@ -118,9 +118,9 @@ public:
#ifndef Q_OS_MAC
_3->setContentsMargins(0, 0, 0, 0);
#endif
- _3->setObjectName(QStringLiteral("_3"));
+ _3->setObjectName(QString::fromUtf8("_3"));
outputTextEdit = new QTextEdit(outputGroupBox);
- outputTextEdit->setObjectName(QStringLiteral("outputTextEdit"));
+ outputTextEdit->setObjectName(QString::fromUtf8("outputTextEdit"));
outputTextEdit->setMinimumSize(QSize(500, 80));
outputTextEdit->setReadOnly(true);
outputTextEdit->setAcceptRichText(false);
@@ -138,11 +138,11 @@ public:
QueryWidget->setCentralWidget(centralwidget);
menubar = new QMenuBar(QueryWidget);
- menubar->setObjectName(QStringLiteral("menubar"));
+ menubar->setObjectName(QString::fromUtf8("menubar"));
menubar->setGeometry(QRect(0, 0, 545, 29));
QueryWidget->setMenuBar(menubar);
statusbar = new QStatusBar(QueryWidget);
- statusbar->setObjectName(QStringLiteral("statusbar"));
+ statusbar->setObjectName(QString::fromUtf8("statusbar"));
statusbar->setGeometry(QRect(0, 509, 545, 22));
QueryWidget->setStatusBar(statusbar);
diff --git a/tests/auto/tools/uic/baseline/remotecontrol.ui.h b/tests/auto/tools/uic/baseline/remotecontrol.ui.h
index c883637dc4..5893ff42af 100644
--- a/tests/auto/tools/uic/baseline/remotecontrol.ui.h
+++ b/tests/auto/tools/uic/baseline/remotecontrol.ui.h
@@ -67,28 +67,28 @@ public:
void setupUi(QMainWindow *RemoteControlClass)
{
if (RemoteControlClass->objectName().isEmpty())
- RemoteControlClass->setObjectName(QStringLiteral("RemoteControlClass"));
+ RemoteControlClass->setObjectName(QString::fromUtf8("RemoteControlClass"));
RemoteControlClass->resize(344, 364);
actionQuit = new QAction(RemoteControlClass);
- actionQuit->setObjectName(QStringLiteral("actionQuit"));
+ actionQuit->setObjectName(QString::fromUtf8("actionQuit"));
centralWidget = new QWidget(RemoteControlClass);
- centralWidget->setObjectName(QStringLiteral("centralWidget"));
+ centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
gridLayout = new QGridLayout(centralWidget);
gridLayout->setSpacing(6);
gridLayout->setContentsMargins(11, 11, 11, 11);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
label = new QLabel(centralWidget);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
gridLayout->addWidget(label, 0, 0, 1, 1);
startUrlLineEdit = new QLineEdit(centralWidget);
- startUrlLineEdit->setObjectName(QStringLiteral("startUrlLineEdit"));
+ startUrlLineEdit->setObjectName(QString::fromUtf8("startUrlLineEdit"));
gridLayout->addWidget(startUrlLineEdit, 0, 1, 1, 2);
launchButton = new QPushButton(centralWidget);
- launchButton->setObjectName(QStringLiteral("launchButton"));
+ launchButton->setObjectName(QString::fromUtf8("launchButton"));
gridLayout->addWidget(launchButton, 1, 1, 1, 1);
@@ -101,27 +101,27 @@ public:
gridLayout->addItem(spacerItem1, 2, 1, 1, 1);
actionGroupBox = new QGroupBox(centralWidget);
- actionGroupBox->setObjectName(QStringLiteral("actionGroupBox"));
+ actionGroupBox->setObjectName(QString::fromUtf8("actionGroupBox"));
actionGroupBox->setEnabled(false);
gridLayout1 = new QGridLayout(actionGroupBox);
gridLayout1->setSpacing(6);
gridLayout1->setContentsMargins(11, 11, 11, 11);
- gridLayout1->setObjectName(QStringLiteral("gridLayout1"));
+ gridLayout1->setObjectName(QString::fromUtf8("gridLayout1"));
label_2 = new QLabel(actionGroupBox);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
gridLayout1->addWidget(label_2, 0, 0, 1, 1);
hboxLayout = new QHBoxLayout();
hboxLayout->setSpacing(0);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
indexLineEdit = new QLineEdit(actionGroupBox);
- indexLineEdit->setObjectName(QStringLiteral("indexLineEdit"));
+ indexLineEdit->setObjectName(QString::fromUtf8("indexLineEdit"));
hboxLayout->addWidget(indexLineEdit);
indexButton = new QToolButton(actionGroupBox);
- indexButton->setObjectName(QStringLiteral("indexButton"));
+ indexButton->setObjectName(QString::fromUtf8("indexButton"));
const QIcon icon = QIcon(QString::fromUtf8(":/remotecontrol/enter.png"));
indexButton->setIcon(icon);
@@ -131,20 +131,20 @@ public:
gridLayout1->addLayout(hboxLayout, 0, 1, 1, 2);
label_4 = new QLabel(actionGroupBox);
- label_4->setObjectName(QStringLiteral("label_4"));
+ label_4->setObjectName(QString::fromUtf8("label_4"));
gridLayout1->addWidget(label_4, 1, 0, 1, 1);
hboxLayout1 = new QHBoxLayout();
hboxLayout1->setSpacing(0);
- hboxLayout1->setObjectName(QStringLiteral("hboxLayout1"));
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
identifierLineEdit = new QLineEdit(actionGroupBox);
- identifierLineEdit->setObjectName(QStringLiteral("identifierLineEdit"));
+ identifierLineEdit->setObjectName(QString::fromUtf8("identifierLineEdit"));
hboxLayout1->addWidget(identifierLineEdit);
identifierButton = new QToolButton(actionGroupBox);
- identifierButton->setObjectName(QStringLiteral("identifierButton"));
+ identifierButton->setObjectName(QString::fromUtf8("identifierButton"));
identifierButton->setIcon(icon);
hboxLayout1->addWidget(identifierButton);
@@ -153,20 +153,20 @@ public:
gridLayout1->addLayout(hboxLayout1, 1, 1, 1, 2);
label_3 = new QLabel(actionGroupBox);
- label_3->setObjectName(QStringLiteral("label_3"));
+ label_3->setObjectName(QString::fromUtf8("label_3"));
gridLayout1->addWidget(label_3, 2, 0, 1, 1);
hboxLayout2 = new QHBoxLayout();
hboxLayout2->setSpacing(0);
- hboxLayout2->setObjectName(QStringLiteral("hboxLayout2"));
+ hboxLayout2->setObjectName(QString::fromUtf8("hboxLayout2"));
urlLineEdit = new QLineEdit(actionGroupBox);
- urlLineEdit->setObjectName(QStringLiteral("urlLineEdit"));
+ urlLineEdit->setObjectName(QString::fromUtf8("urlLineEdit"));
hboxLayout2->addWidget(urlLineEdit);
urlButton = new QToolButton(actionGroupBox);
- urlButton->setObjectName(QStringLiteral("urlButton"));
+ urlButton->setObjectName(QString::fromUtf8("urlButton"));
urlButton->setIcon(icon);
hboxLayout2->addWidget(urlButton);
@@ -175,7 +175,7 @@ public:
gridLayout1->addLayout(hboxLayout2, 2, 1, 1, 2);
syncContentsButton = new QPushButton(actionGroupBox);
- syncContentsButton->setObjectName(QStringLiteral("syncContentsButton"));
+ syncContentsButton->setObjectName(QString::fromUtf8("syncContentsButton"));
gridLayout1->addWidget(syncContentsButton, 3, 1, 1, 1);
@@ -184,17 +184,17 @@ public:
gridLayout1->addItem(spacerItem2, 3, 2, 1, 1);
contentsCheckBox = new QCheckBox(actionGroupBox);
- contentsCheckBox->setObjectName(QStringLiteral("contentsCheckBox"));
+ contentsCheckBox->setObjectName(QString::fromUtf8("contentsCheckBox"));
gridLayout1->addWidget(contentsCheckBox, 4, 0, 1, 3);
indexCheckBox = new QCheckBox(actionGroupBox);
- indexCheckBox->setObjectName(QStringLiteral("indexCheckBox"));
+ indexCheckBox->setObjectName(QString::fromUtf8("indexCheckBox"));
gridLayout1->addWidget(indexCheckBox, 5, 0, 1, 1);
bookmarksCheckBox = new QCheckBox(actionGroupBox);
- bookmarksCheckBox->setObjectName(QStringLiteral("bookmarksCheckBox"));
+ bookmarksCheckBox->setObjectName(QString::fromUtf8("bookmarksCheckBox"));
gridLayout1->addWidget(bookmarksCheckBox, 6, 0, 1, 3);
@@ -203,13 +203,13 @@ public:
RemoteControlClass->setCentralWidget(centralWidget);
menuBar = new QMenuBar(RemoteControlClass);
- menuBar->setObjectName(QStringLiteral("menuBar"));
+ menuBar->setObjectName(QString::fromUtf8("menuBar"));
menuBar->setGeometry(QRect(0, 0, 344, 21));
menuFile = new QMenu(menuBar);
- menuFile->setObjectName(QStringLiteral("menuFile"));
+ menuFile->setObjectName(QString::fromUtf8("menuFile"));
RemoteControlClass->setMenuBar(menuBar);
statusBar = new QStatusBar(RemoteControlClass);
- statusBar->setObjectName(QStringLiteral("statusBar"));
+ statusBar->setObjectName(QString::fromUtf8("statusBar"));
RemoteControlClass->setStatusBar(statusBar);
menuBar->addAction(menuFile->menuAction());
diff --git a/tests/auto/tools/uic/baseline/saveformastemplate.ui.h b/tests/auto/tools/uic/baseline/saveformastemplate.ui.h
index 6cd8726d07..9ef6eedb4c 100644
--- a/tests/auto/tools/uic/baseline/saveformastemplate.ui.h
+++ b/tests/auto/tools/uic/baseline/saveformastemplate.ui.h
@@ -67,13 +67,13 @@ public:
void setupUi(QDialog *SaveFormAsTemplate)
{
if (SaveFormAsTemplate->objectName().isEmpty())
- SaveFormAsTemplate->setObjectName(QStringLiteral("SaveFormAsTemplate"));
+ SaveFormAsTemplate->setObjectName(QString::fromUtf8("SaveFormAsTemplate"));
vboxLayout = new QVBoxLayout(SaveFormAsTemplate);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
formLayout = new QFormLayout();
- formLayout->setObjectName(QStringLiteral("formLayout"));
+ formLayout->setObjectName(QString::fromUtf8("formLayout"));
label = new QLabel(SaveFormAsTemplate);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
label->setFrameShape(QFrame::NoFrame);
label->setFrameShadow(QFrame::Plain);
label->setTextFormat(Qt::AutoText);
@@ -81,14 +81,14 @@ public:
formLayout->setWidget(0, QFormLayout::LabelRole, label);
templateNameEdit = new QLineEdit(SaveFormAsTemplate);
- templateNameEdit->setObjectName(QStringLiteral("templateNameEdit"));
+ templateNameEdit->setObjectName(QString::fromUtf8("templateNameEdit"));
templateNameEdit->setMinimumSize(QSize(222, 0));
templateNameEdit->setEchoMode(QLineEdit::Normal);
formLayout->setWidget(0, QFormLayout::FieldRole, templateNameEdit);
label_2 = new QLabel(SaveFormAsTemplate);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
label_2->setFrameShape(QFrame::NoFrame);
label_2->setFrameShadow(QFrame::Plain);
label_2->setTextFormat(Qt::AutoText);
@@ -96,7 +96,7 @@ public:
formLayout->setWidget(1, QFormLayout::LabelRole, label_2);
categoryCombo = new QComboBox(SaveFormAsTemplate);
- categoryCombo->setObjectName(QStringLiteral("categoryCombo"));
+ categoryCombo->setObjectName(QString::fromUtf8("categoryCombo"));
formLayout->setWidget(1, QFormLayout::FieldRole, categoryCombo);
@@ -104,14 +104,14 @@ public:
vboxLayout->addLayout(formLayout);
horizontalLine = new QFrame(SaveFormAsTemplate);
- horizontalLine->setObjectName(QStringLiteral("horizontalLine"));
+ horizontalLine->setObjectName(QString::fromUtf8("horizontalLine"));
horizontalLine->setFrameShape(QFrame::HLine);
horizontalLine->setFrameShadow(QFrame::Sunken);
vboxLayout->addWidget(horizontalLine);
buttonBox = new QDialogButtonBox(SaveFormAsTemplate);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
diff --git a/tests/auto/tools/uic/baseline/settings.ui.h b/tests/auto/tools/uic/baseline/settings.ui.h
index 6a1f11fa85..cc680c8033 100644
--- a/tests/auto/tools/uic/baseline/settings.ui.h
+++ b/tests/auto/tools/uic/baseline/settings.ui.h
@@ -47,14 +47,14 @@ public:
void setupUi(QDialog *Dialog)
{
if (Dialog->objectName().isEmpty())
- Dialog->setObjectName(QStringLiteral("Dialog"));
+ Dialog->setObjectName(QString::fromUtf8("Dialog"));
Dialog->resize(392, 176);
verticalLayout = new QVBoxLayout(Dialog);
- verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
+ verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
hboxLayout = new QHBoxLayout();
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
label = new QLabel(Dialog);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
QSizePolicy sizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -66,7 +66,7 @@ public:
hboxLayout->addWidget(label);
deviceCombo = new QComboBox(Dialog);
- deviceCombo->setObjectName(QStringLiteral("deviceCombo"));
+ deviceCombo->setObjectName(QString::fromUtf8("deviceCombo"));
QSizePolicy sizePolicy1(QSizePolicy::Minimum, QSizePolicy::Fixed);
sizePolicy1.setHorizontalStretch(0);
sizePolicy1.setVerticalStretch(0);
@@ -79,9 +79,9 @@ public:
verticalLayout->addLayout(hboxLayout);
hboxLayout1 = new QHBoxLayout();
- hboxLayout1->setObjectName(QStringLiteral("hboxLayout1"));
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
label_6 = new QLabel(Dialog);
- label_6->setObjectName(QStringLiteral("label_6"));
+ label_6->setObjectName(QString::fromUtf8("label_6"));
sizePolicy.setHeightForWidth(label_6->sizePolicy().hasHeightForWidth());
label_6->setSizePolicy(sizePolicy);
label_6->setMinimumSize(QSize(90, 0));
@@ -90,7 +90,7 @@ public:
hboxLayout1->addWidget(label_6);
audioEffectsCombo = new QComboBox(Dialog);
- audioEffectsCombo->setObjectName(QStringLiteral("audioEffectsCombo"));
+ audioEffectsCombo->setObjectName(QString::fromUtf8("audioEffectsCombo"));
sizePolicy1.setHeightForWidth(audioEffectsCombo->sizePolicy().hasHeightForWidth());
audioEffectsCombo->setSizePolicy(sizePolicy1);
@@ -100,9 +100,9 @@ public:
verticalLayout->addLayout(hboxLayout1);
hboxLayout2 = new QHBoxLayout();
- hboxLayout2->setObjectName(QStringLiteral("hboxLayout2"));
+ hboxLayout2->setObjectName(QString::fromUtf8("hboxLayout2"));
crossFadeLabel = new QLabel(Dialog);
- crossFadeLabel->setObjectName(QStringLiteral("crossFadeLabel"));
+ crossFadeLabel->setObjectName(QString::fromUtf8("crossFadeLabel"));
sizePolicy.setHeightForWidth(crossFadeLabel->sizePolicy().hasHeightForWidth());
crossFadeLabel->setSizePolicy(sizePolicy);
crossFadeLabel->setMinimumSize(QSize(90, 0));
@@ -111,9 +111,9 @@ public:
hboxLayout2->addWidget(crossFadeLabel);
vboxLayout = new QVBoxLayout();
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
crossFadeSlider = new QSlider(Dialog);
- crossFadeSlider->setObjectName(QStringLiteral("crossFadeSlider"));
+ crossFadeSlider->setObjectName(QString::fromUtf8("crossFadeSlider"));
sizePolicy1.setHeightForWidth(crossFadeSlider->sizePolicy().hasHeightForWidth());
crossFadeSlider->setSizePolicy(sizePolicy1);
crossFadeSlider->setMinimum(-20);
@@ -127,9 +127,9 @@ public:
vboxLayout->addWidget(crossFadeSlider);
hboxLayout3 = new QHBoxLayout();
- hboxLayout3->setObjectName(QStringLiteral("hboxLayout3"));
+ hboxLayout3->setObjectName(QString::fromUtf8("hboxLayout3"));
label_3 = new QLabel(Dialog);
- label_3->setObjectName(QStringLiteral("label_3"));
+ label_3->setObjectName(QString::fromUtf8("label_3"));
QFont font;
font.setPointSize(9);
label_3->setFont(font);
@@ -141,7 +141,7 @@ public:
hboxLayout3->addItem(spacerItem);
label_5 = new QLabel(Dialog);
- label_5->setObjectName(QStringLiteral("label_5"));
+ label_5->setObjectName(QString::fromUtf8("label_5"));
label_5->setFont(font);
hboxLayout3->addWidget(label_5);
@@ -151,7 +151,7 @@ public:
hboxLayout3->addItem(spacerItem1);
label_4 = new QLabel(Dialog);
- label_4->setObjectName(QStringLiteral("label_4"));
+ label_4->setObjectName(QString::fromUtf8("label_4"));
label_4->setFont(font);
hboxLayout3->addWidget(label_4);
@@ -166,7 +166,7 @@ public:
verticalLayout->addLayout(hboxLayout2);
buttonBox = new QDialogButtonBox(Dialog);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
diff --git a/tests/auto/tools/uic/baseline/signalslotdialog.ui.h b/tests/auto/tools/uic/baseline/signalslotdialog.ui.h
index ad6c5776e1..5833a25a8b 100644
--- a/tests/auto/tools/uic/baseline/signalslotdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/signalslotdialog.ui.h
@@ -45,33 +45,33 @@ public:
void setupUi(QDialog *SignalSlotDialogClass)
{
if (SignalSlotDialogClass->objectName().isEmpty())
- SignalSlotDialogClass->setObjectName(QStringLiteral("SignalSlotDialogClass"));
+ SignalSlotDialogClass->setObjectName(QString::fromUtf8("SignalSlotDialogClass"));
SignalSlotDialogClass->resize(617, 535);
vboxLayout = new QVBoxLayout(SignalSlotDialogClass);
vboxLayout->setSpacing(6);
vboxLayout->setContentsMargins(11, 11, 11, 11);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
slotGroupBox = new QGroupBox(SignalSlotDialogClass);
- slotGroupBox->setObjectName(QStringLiteral("slotGroupBox"));
+ slotGroupBox->setObjectName(QString::fromUtf8("slotGroupBox"));
vboxLayout1 = new QVBoxLayout(slotGroupBox);
vboxLayout1->setSpacing(6);
vboxLayout1->setContentsMargins(11, 11, 11, 11);
- vboxLayout1->setObjectName(QStringLiteral("vboxLayout1"));
+ vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
slotListView = new QListView(slotGroupBox);
- slotListView->setObjectName(QStringLiteral("slotListView"));
+ slotListView->setObjectName(QString::fromUtf8("slotListView"));
vboxLayout1->addWidget(slotListView);
hboxLayout = new QHBoxLayout();
hboxLayout->setSpacing(6);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
addSlotButton = new QToolButton(slotGroupBox);
- addSlotButton->setObjectName(QStringLiteral("addSlotButton"));
+ addSlotButton->setObjectName(QString::fromUtf8("addSlotButton"));
hboxLayout->addWidget(addSlotButton);
removeSlotButton = new QToolButton(slotGroupBox);
- removeSlotButton->setObjectName(QStringLiteral("removeSlotButton"));
+ removeSlotButton->setObjectName(QString::fromUtf8("removeSlotButton"));
hboxLayout->addWidget(removeSlotButton);
@@ -86,26 +86,26 @@ public:
vboxLayout->addWidget(slotGroupBox);
signalGroupBox = new QGroupBox(SignalSlotDialogClass);
- signalGroupBox->setObjectName(QStringLiteral("signalGroupBox"));
+ signalGroupBox->setObjectName(QString::fromUtf8("signalGroupBox"));
vboxLayout2 = new QVBoxLayout(signalGroupBox);
vboxLayout2->setSpacing(6);
vboxLayout2->setContentsMargins(11, 11, 11, 11);
- vboxLayout2->setObjectName(QStringLiteral("vboxLayout2"));
+ vboxLayout2->setObjectName(QString::fromUtf8("vboxLayout2"));
signalListView = new QListView(signalGroupBox);
- signalListView->setObjectName(QStringLiteral("signalListView"));
+ signalListView->setObjectName(QString::fromUtf8("signalListView"));
vboxLayout2->addWidget(signalListView);
hboxLayout1 = new QHBoxLayout();
hboxLayout1->setSpacing(6);
- hboxLayout1->setObjectName(QStringLiteral("hboxLayout1"));
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
addSignalButton = new QToolButton(signalGroupBox);
- addSignalButton->setObjectName(QStringLiteral("addSignalButton"));
+ addSignalButton->setObjectName(QString::fromUtf8("addSignalButton"));
hboxLayout1->addWidget(addSignalButton);
removeSignalButton = new QToolButton(signalGroupBox);
- removeSignalButton->setObjectName(QStringLiteral("removeSignalButton"));
+ removeSignalButton->setObjectName(QString::fromUtf8("removeSignalButton"));
hboxLayout1->addWidget(removeSignalButton);
@@ -120,7 +120,7 @@ public:
vboxLayout->addWidget(signalGroupBox);
buttonBox = new QDialogButtonBox(SignalSlotDialogClass);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
vboxLayout->addWidget(buttonBox);
diff --git a/tests/auto/tools/uic/baseline/sslclient.ui.h b/tests/auto/tools/uic/baseline/sslclient.ui.h
index 3e7feab75a..382889648e 100644
--- a/tests/auto/tools/uic/baseline/sslclient.ui.h
+++ b/tests/auto/tools/uic/baseline/sslclient.ui.h
@@ -48,29 +48,29 @@ public:
void setupUi(QWidget *Form)
{
if (Form->objectName().isEmpty())
- Form->setObjectName(QStringLiteral("Form"));
+ Form->setObjectName(QString::fromUtf8("Form"));
Form->resize(343, 320);
vboxLayout = new QVBoxLayout(Form);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
gridLayout = new QGridLayout();
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
hostNameLabel = new QLabel(Form);
- hostNameLabel->setObjectName(QStringLiteral("hostNameLabel"));
+ hostNameLabel->setObjectName(QString::fromUtf8("hostNameLabel"));
gridLayout->addWidget(hostNameLabel, 0, 0, 1, 1);
hostNameEdit = new QLineEdit(Form);
- hostNameEdit->setObjectName(QStringLiteral("hostNameEdit"));
+ hostNameEdit->setObjectName(QString::fromUtf8("hostNameEdit"));
gridLayout->addWidget(hostNameEdit, 0, 1, 1, 1);
portLabel = new QLabel(Form);
- portLabel->setObjectName(QStringLiteral("portLabel"));
+ portLabel->setObjectName(QString::fromUtf8("portLabel"));
gridLayout->addWidget(portLabel, 1, 0, 1, 1);
portBox = new QSpinBox(Form);
- portBox->setObjectName(QStringLiteral("portBox"));
+ portBox->setObjectName(QString::fromUtf8("portBox"));
portBox->setMinimum(1);
portBox->setMaximum(65535);
portBox->setValue(993);
@@ -81,25 +81,25 @@ public:
vboxLayout->addLayout(gridLayout);
connectButton = new QPushButton(Form);
- connectButton->setObjectName(QStringLiteral("connectButton"));
+ connectButton->setObjectName(QString::fromUtf8("connectButton"));
connectButton->setEnabled(true);
vboxLayout->addWidget(connectButton);
sessionBox = new QGroupBox(Form);
- sessionBox->setObjectName(QStringLiteral("sessionBox"));
+ sessionBox->setObjectName(QString::fromUtf8("sessionBox"));
sessionBox->setEnabled(false);
vboxLayout1 = new QVBoxLayout(sessionBox);
- vboxLayout1->setObjectName(QStringLiteral("vboxLayout1"));
+ vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
hboxLayout = new QHBoxLayout();
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
cipherText = new QLabel(sessionBox);
- cipherText->setObjectName(QStringLiteral("cipherText"));
+ cipherText->setObjectName(QString::fromUtf8("cipherText"));
hboxLayout->addWidget(cipherText);
cipherLabel = new QLabel(sessionBox);
- cipherLabel->setObjectName(QStringLiteral("cipherLabel"));
+ cipherLabel->setObjectName(QString::fromUtf8("cipherLabel"));
cipherLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
hboxLayout->addWidget(cipherLabel);
@@ -108,7 +108,7 @@ public:
vboxLayout1->addLayout(hboxLayout);
sessionOutput = new QTextEdit(sessionBox);
- sessionOutput->setObjectName(QStringLiteral("sessionOutput"));
+ sessionOutput->setObjectName(QString::fromUtf8("sessionOutput"));
sessionOutput->setEnabled(false);
sessionOutput->setFocusPolicy(Qt::NoFocus);
sessionOutput->setReadOnly(true);
@@ -116,20 +116,20 @@ public:
vboxLayout1->addWidget(sessionOutput);
hboxLayout1 = new QHBoxLayout();
- hboxLayout1->setObjectName(QStringLiteral("hboxLayout1"));
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
sessionInputLabel = new QLabel(sessionBox);
- sessionInputLabel->setObjectName(QStringLiteral("sessionInputLabel"));
+ sessionInputLabel->setObjectName(QString::fromUtf8("sessionInputLabel"));
hboxLayout1->addWidget(sessionInputLabel);
sessionInput = new QLineEdit(sessionBox);
- sessionInput->setObjectName(QStringLiteral("sessionInput"));
+ sessionInput->setObjectName(QString::fromUtf8("sessionInput"));
sessionInput->setEnabled(false);
hboxLayout1->addWidget(sessionInput);
sendButton = new QPushButton(sessionBox);
- sendButton->setObjectName(QStringLiteral("sendButton"));
+ sendButton->setObjectName(QString::fromUtf8("sendButton"));
sendButton->setEnabled(false);
sendButton->setFocusPolicy(Qt::TabFocus);
diff --git a/tests/auto/tools/uic/baseline/sslerrors.ui.h b/tests/auto/tools/uic/baseline/sslerrors.ui.h
index d920908de6..04f21ded43 100644
--- a/tests/auto/tools/uic/baseline/sslerrors.ui.h
+++ b/tests/auto/tools/uic/baseline/sslerrors.ui.h
@@ -36,25 +36,25 @@ public:
void setupUi(QDialog *SslErrors)
{
if (SslErrors->objectName().isEmpty())
- SslErrors->setObjectName(QStringLiteral("SslErrors"));
+ SslErrors->setObjectName(QString::fromUtf8("SslErrors"));
SslErrors->resize(371, 216);
vboxLayout = new QVBoxLayout(SslErrors);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
label = new QLabel(SslErrors);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
label->setWordWrap(true);
vboxLayout->addWidget(label);
sslErrorList = new QListWidget(SslErrors);
- sslErrorList->setObjectName(QStringLiteral("sslErrorList"));
+ sslErrorList->setObjectName(QString::fromUtf8("sslErrorList"));
vboxLayout->addWidget(sslErrorList);
hboxLayout = new QHBoxLayout();
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
certificateChainButton = new QPushButton(SslErrors);
- certificateChainButton->setObjectName(QStringLiteral("certificateChainButton"));
+ certificateChainButton->setObjectName(QString::fromUtf8("certificateChainButton"));
certificateChainButton->setAutoDefault(false);
hboxLayout->addWidget(certificateChainButton);
@@ -64,12 +64,12 @@ public:
hboxLayout->addItem(spacerItem);
pushButton = new QPushButton(SslErrors);
- pushButton->setObjectName(QStringLiteral("pushButton"));
+ pushButton->setObjectName(QString::fromUtf8("pushButton"));
hboxLayout->addWidget(pushButton);
pushButton_2 = new QPushButton(SslErrors);
- pushButton_2->setObjectName(QStringLiteral("pushButton_2"));
+ pushButton_2->setObjectName(QString::fromUtf8("pushButton_2"));
hboxLayout->addWidget(pushButton_2);
diff --git a/tests/auto/tools/uic/baseline/statistics.ui.h b/tests/auto/tools/uic/baseline/statistics.ui.h
index ab0f4f9b8d..0b508836f2 100644
--- a/tests/auto/tools/uic/baseline/statistics.ui.h
+++ b/tests/auto/tools/uic/baseline/statistics.ui.h
@@ -76,24 +76,24 @@ public:
void setupUi(QDialog *Statistics)
{
if (Statistics->objectName().isEmpty())
- Statistics->setObjectName(QStringLiteral("Statistics"));
- Statistics->setObjectName(QStringLiteral("linguist_stats"));
+ Statistics->setObjectName(QString::fromUtf8("Statistics"));
+ Statistics->setObjectName(QString::fromUtf8("linguist_stats"));
Statistics->resize(336, 164);
gridLayout = new QGridLayout(Statistics);
gridLayout->setSpacing(6);
gridLayout->setContentsMargins(11, 11, 11, 11);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
- gridLayout->setObjectName(QStringLiteral("unnamed"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("unnamed"));
hboxLayout = new QHBoxLayout();
hboxLayout->setSpacing(6);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
- hboxLayout->setObjectName(QStringLiteral("unnamed"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("unnamed"));
spacer4_2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
hboxLayout->addItem(spacer4_2);
closeBtn = new QPushButton(Statistics);
- closeBtn->setObjectName(QStringLiteral("closeBtn"));
+ closeBtn->setObjectName(QString::fromUtf8("closeBtn"));
hboxLayout->addWidget(closeBtn);
@@ -105,66 +105,66 @@ public:
gridLayout->addLayout(hboxLayout, 1, 0, 1, 1);
frame4 = new QFrame(Statistics);
- frame4->setObjectName(QStringLiteral("frame4"));
+ frame4->setObjectName(QString::fromUtf8("frame4"));
frame4->setFrameShape(QFrame::StyledPanel);
frame4->setFrameShadow(QFrame::Raised);
gridLayout1 = new QGridLayout(frame4);
gridLayout1->setSpacing(6);
gridLayout1->setContentsMargins(11, 11, 11, 11);
- gridLayout1->setObjectName(QStringLiteral("gridLayout1"));
- gridLayout1->setObjectName(QStringLiteral("unnamed"));
+ gridLayout1->setObjectName(QString::fromUtf8("gridLayout1"));
+ gridLayout1->setObjectName(QString::fromUtf8("unnamed"));
textLabel4 = new QLabel(frame4);
- textLabel4->setObjectName(QStringLiteral("textLabel4"));
+ textLabel4->setObjectName(QString::fromUtf8("textLabel4"));
gridLayout1->addWidget(textLabel4, 0, 2, 1, 1);
textLabel5 = new QLabel(frame4);
- textLabel5->setObjectName(QStringLiteral("textLabel5"));
+ textLabel5->setObjectName(QString::fromUtf8("textLabel5"));
gridLayout1->addWidget(textLabel5, 0, 1, 1, 1);
untrWords = new QLabel(frame4);
- untrWords->setObjectName(QStringLiteral("untrWords"));
+ untrWords->setObjectName(QString::fromUtf8("untrWords"));
gridLayout1->addWidget(untrWords, 1, 1, 1, 1);
trWords = new QLabel(frame4);
- trWords->setObjectName(QStringLiteral("trWords"));
+ trWords->setObjectName(QString::fromUtf8("trWords"));
gridLayout1->addWidget(trWords, 1, 2, 1, 1);
textLabel1 = new QLabel(frame4);
- textLabel1->setObjectName(QStringLiteral("textLabel1"));
+ textLabel1->setObjectName(QString::fromUtf8("textLabel1"));
gridLayout1->addWidget(textLabel1, 1, 0, 1, 1);
trChars = new QLabel(frame4);
- trChars->setObjectName(QStringLiteral("trChars"));
+ trChars->setObjectName(QString::fromUtf8("trChars"));
gridLayout1->addWidget(trChars, 2, 2, 1, 1);
untrChars = new QLabel(frame4);
- untrChars->setObjectName(QStringLiteral("untrChars"));
+ untrChars->setObjectName(QString::fromUtf8("untrChars"));
gridLayout1->addWidget(untrChars, 2, 1, 1, 1);
textLabel3 = new QLabel(frame4);
- textLabel3->setObjectName(QStringLiteral("textLabel3"));
+ textLabel3->setObjectName(QString::fromUtf8("textLabel3"));
gridLayout1->addWidget(textLabel3, 2, 0, 1, 1);
textLabel6 = new QLabel(frame4);
- textLabel6->setObjectName(QStringLiteral("textLabel6"));
+ textLabel6->setObjectName(QString::fromUtf8("textLabel6"));
gridLayout1->addWidget(textLabel6, 3, 0, 1, 1);
trCharsSpc = new QLabel(frame4);
- trCharsSpc->setObjectName(QStringLiteral("trCharsSpc"));
+ trCharsSpc->setObjectName(QString::fromUtf8("trCharsSpc"));
gridLayout1->addWidget(trCharsSpc, 3, 2, 1, 1);
untrCharsSpc = new QLabel(frame4);
- untrCharsSpc->setObjectName(QStringLiteral("untrCharsSpc"));
+ untrCharsSpc->setObjectName(QString::fromUtf8("untrCharsSpc"));
gridLayout1->addWidget(untrCharsSpc, 3, 1, 1, 1);
diff --git a/tests/auto/tools/uic/baseline/stringlisteditor.ui.h b/tests/auto/tools/uic/baseline/stringlisteditor.ui.h
index 44603f1e8a..fd78ce91c1 100644
--- a/tests/auto/tools/uic/baseline/stringlisteditor.ui.h
+++ b/tests/auto/tools/uic/baseline/stringlisteditor.ui.h
@@ -82,7 +82,7 @@ public:
void setupUi(QDialog *qdesigner_internal__Dialog)
{
if (qdesigner_internal__Dialog->objectName().isEmpty())
- qdesigner_internal__Dialog->setObjectName(QStringLiteral("qdesigner_internal__Dialog"));
+ qdesigner_internal__Dialog->setObjectName(QString::fromUtf8("qdesigner_internal__Dialog"));
qdesigner_internal__Dialog->resize(400, 300);
vboxLayout = new QVBoxLayout(qdesigner_internal__Dialog);
#ifndef Q_OS_MAC
@@ -91,9 +91,9 @@ public:
#ifndef Q_OS_MAC
vboxLayout->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
groupBox = new QGroupBox(qdesigner_internal__Dialog);
- groupBox->setObjectName(QStringLiteral("groupBox"));
+ groupBox->setObjectName(QString::fromUtf8("groupBox"));
gridLayout = new QGridLayout(groupBox);
#ifndef Q_OS_MAC
gridLayout->setSpacing(6);
@@ -101,7 +101,7 @@ public:
#ifndef Q_OS_MAC
gridLayout->setContentsMargins(9, 9, 9, 9);
#endif
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
vboxLayout1 = new QVBoxLayout();
#ifndef Q_OS_MAC
vboxLayout1->setSpacing(6);
@@ -109,7 +109,7 @@ public:
#ifndef Q_OS_MAC
vboxLayout1->setContentsMargins(0, 0, 0, 0);
#endif
- vboxLayout1->setObjectName(QStringLiteral("vboxLayout1"));
+ vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
hboxLayout = new QHBoxLayout();
#ifndef Q_OS_MAC
hboxLayout->setSpacing(6);
@@ -117,15 +117,15 @@ public:
#ifndef Q_OS_MAC
hboxLayout->setContentsMargins(0, 0, 0, 0);
#endif
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
newButton = new QToolButton(groupBox);
- newButton->setObjectName(QStringLiteral("newButton"));
+ newButton->setObjectName(QString::fromUtf8("newButton"));
newButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
hboxLayout->addWidget(newButton);
deleteButton = new QToolButton(groupBox);
- deleteButton->setObjectName(QStringLiteral("deleteButton"));
+ deleteButton->setObjectName(QString::fromUtf8("deleteButton"));
deleteButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
hboxLayout->addWidget(deleteButton);
@@ -142,14 +142,14 @@ public:
hboxLayout1->setSpacing(6);
#endif
hboxLayout1->setContentsMargins(0, 0, 0, 0);
- hboxLayout1->setObjectName(QStringLiteral("hboxLayout1"));
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
label = new QLabel(groupBox);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
hboxLayout1->addWidget(label);
valueEdit = new QLineEdit(groupBox);
- valueEdit->setObjectName(QStringLiteral("valueEdit"));
+ valueEdit->setObjectName(QString::fromUtf8("valueEdit"));
hboxLayout1->addWidget(valueEdit);
@@ -164,18 +164,18 @@ public:
vboxLayout2->setSpacing(6);
#endif
vboxLayout2->setContentsMargins(0, 0, 0, 0);
- vboxLayout2->setObjectName(QStringLiteral("vboxLayout2"));
+ vboxLayout2->setObjectName(QString::fromUtf8("vboxLayout2"));
spacerItem1 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
vboxLayout2->addItem(spacerItem1);
upButton = new QToolButton(groupBox);
- upButton->setObjectName(QStringLiteral("upButton"));
+ upButton->setObjectName(QString::fromUtf8("upButton"));
vboxLayout2->addWidget(upButton);
downButton = new QToolButton(groupBox);
- downButton->setObjectName(QStringLiteral("downButton"));
+ downButton->setObjectName(QString::fromUtf8("downButton"));
vboxLayout2->addWidget(downButton);
@@ -187,7 +187,7 @@ public:
gridLayout->addLayout(vboxLayout2, 0, 1, 1, 1);
listView = new QListView(groupBox);
- listView->setObjectName(QStringLiteral("listView"));
+ listView->setObjectName(QString::fromUtf8("listView"));
gridLayout->addWidget(listView, 0, 0, 1, 1);
@@ -195,7 +195,7 @@ public:
vboxLayout->addWidget(groupBox);
buttonBox = new QDialogButtonBox(qdesigner_internal__Dialog);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok);
diff --git a/tests/auto/tools/uic/baseline/stylesheeteditor.ui.h b/tests/auto/tools/uic/baseline/stylesheeteditor.ui.h
index a867317820..5ae254ebab 100644
--- a/tests/auto/tools/uic/baseline/stylesheeteditor.ui.h
+++ b/tests/auto/tools/uic/baseline/stylesheeteditor.ui.h
@@ -41,7 +41,7 @@ public:
void setupUi(QWidget *StyleSheetEditor)
{
if (StyleSheetEditor->objectName().isEmpty())
- StyleSheetEditor->setObjectName(QStringLiteral("StyleSheetEditor"));
+ StyleSheetEditor->setObjectName(QString::fromUtf8("StyleSheetEditor"));
StyleSheetEditor->resize(445, 289);
gridLayout = new QGridLayout(StyleSheetEditor);
#ifndef Q_OS_MAC
@@ -50,7 +50,7 @@ public:
#ifndef Q_OS_MAC
gridLayout->setContentsMargins(9, 9, 9, 9);
#endif
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
spacerItem = new QSpacerItem(32, 20, QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
gridLayout->addItem(spacerItem, 0, 6, 1, 1);
@@ -63,7 +63,7 @@ public:
styleSheetCombo->addItem(QString());
styleSheetCombo->addItem(QString());
styleSheetCombo->addItem(QString());
- styleSheetCombo->setObjectName(QStringLiteral("styleSheetCombo"));
+ styleSheetCombo->setObjectName(QString::fromUtf8("styleSheetCombo"));
gridLayout->addWidget(styleSheetCombo, 0, 5, 1, 1);
@@ -72,7 +72,7 @@ public:
gridLayout->addItem(spacerItem2, 0, 3, 1, 1);
styleCombo = new QComboBox(StyleSheetEditor);
- styleCombo->setObjectName(QStringLiteral("styleCombo"));
+ styleCombo->setObjectName(QString::fromUtf8("styleCombo"));
QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(5), static_cast<QSizePolicy::Policy>(0));
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -82,7 +82,7 @@ public:
gridLayout->addWidget(styleCombo, 0, 2, 1, 1);
label_7 = new QLabel(StyleSheetEditor);
- label_7->setObjectName(QStringLiteral("label_7"));
+ label_7->setObjectName(QString::fromUtf8("label_7"));
QSizePolicy sizePolicy1(static_cast<QSizePolicy::Policy>(0), static_cast<QSizePolicy::Policy>(5));
sizePolicy1.setHorizontalStretch(0);
sizePolicy1.setVerticalStretch(0);
@@ -96,13 +96,13 @@ public:
hboxLayout->setSpacing(6);
#endif
hboxLayout->setContentsMargins(0, 0, 0, 0);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
spacerItem3 = new QSpacerItem(321, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
hboxLayout->addItem(spacerItem3);
applyButton = new QPushButton(StyleSheetEditor);
- applyButton->setObjectName(QStringLiteral("applyButton"));
+ applyButton->setObjectName(QString::fromUtf8("applyButton"));
applyButton->setEnabled(false);
hboxLayout->addWidget(applyButton);
@@ -111,12 +111,12 @@ public:
gridLayout->addLayout(hboxLayout, 2, 0, 1, 7);
styleTextEdit = new QTextEdit(StyleSheetEditor);
- styleTextEdit->setObjectName(QStringLiteral("styleTextEdit"));
+ styleTextEdit->setObjectName(QString::fromUtf8("styleTextEdit"));
gridLayout->addWidget(styleTextEdit, 1, 0, 1, 7);
label_8 = new QLabel(StyleSheetEditor);
- label_8->setObjectName(QStringLiteral("label_8"));
+ label_8->setObjectName(QString::fromUtf8("label_8"));
sizePolicy1.setHeightForWidth(label_8->sizePolicy().hasHeightForWidth());
label_8->setSizePolicy(sizePolicy1);
diff --git a/tests/auto/tools/uic/baseline/tabbedbrowser.ui.h b/tests/auto/tools/uic/baseline/tabbedbrowser.ui.h
index 5d670b46af..09b230f5df 100644
--- a/tests/auto/tools/uic/baseline/tabbedbrowser.ui.h
+++ b/tests/auto/tools/uic/baseline/tabbedbrowser.ui.h
@@ -77,28 +77,28 @@ public:
void setupUi(QWidget *TabbedBrowser)
{
if (TabbedBrowser->objectName().isEmpty())
- TabbedBrowser->setObjectName(QStringLiteral("TabbedBrowser"));
+ TabbedBrowser->setObjectName(QString::fromUtf8("TabbedBrowser"));
TabbedBrowser->resize(710, 664);
vboxLayout = new QVBoxLayout(TabbedBrowser);
vboxLayout->setSpacing(0);
vboxLayout->setContentsMargins(0, 0, 0, 0);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
tab = new QTabWidget(TabbedBrowser);
- tab->setObjectName(QStringLiteral("tab"));
+ tab->setObjectName(QString::fromUtf8("tab"));
frontpage = new QWidget();
- frontpage->setObjectName(QStringLiteral("frontpage"));
+ frontpage->setObjectName(QString::fromUtf8("frontpage"));
gridLayout = new QGridLayout(frontpage);
#ifndef Q_OS_MAC
gridLayout->setSpacing(6);
#endif
gridLayout->setContentsMargins(8, 8, 8, 8);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
tab->addTab(frontpage, QString());
vboxLayout->addWidget(tab);
frameFind = new QFrame(TabbedBrowser);
- frameFind->setObjectName(QStringLiteral("frameFind"));
+ frameFind->setObjectName(QString::fromUtf8("frameFind"));
frameFind->setFrameShape(QFrame::StyledPanel);
frameFind->setFrameShadow(QFrame::Raised);
hboxLayout = new QHBoxLayout(frameFind);
@@ -106,9 +106,9 @@ public:
hboxLayout->setSpacing(6);
#endif
hboxLayout->setContentsMargins(0, 0, 0, 0);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
toolClose = new QToolButton(frameFind);
- toolClose->setObjectName(QStringLiteral("toolClose"));
+ toolClose->setObjectName(QString::fromUtf8("toolClose"));
const QIcon icon = QIcon(QString::fromUtf8(":/qt-project.org/assistant/images/close.png"));
toolClose->setIcon(icon);
toolClose->setAutoRaise(true);
@@ -116,7 +116,7 @@ public:
hboxLayout->addWidget(toolClose);
editFind = new QLineEdit(frameFind);
- editFind->setObjectName(QStringLiteral("editFind"));
+ editFind->setObjectName(QString::fromUtf8("editFind"));
QSizePolicy sizePolicy(static_cast<QSizePolicy::Policy>(0), static_cast<QSizePolicy::Policy>(0));
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -127,7 +127,7 @@ public:
hboxLayout->addWidget(editFind);
toolPrevious = new QToolButton(frameFind);
- toolPrevious->setObjectName(QStringLiteral("toolPrevious"));
+ toolPrevious->setObjectName(QString::fromUtf8("toolPrevious"));
const QIcon icon1 = QIcon(QString::fromUtf8(":/qt-project.org/assistant/images/win/previous.png"));
toolPrevious->setIcon(icon1);
toolPrevious->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
@@ -136,7 +136,7 @@ public:
hboxLayout->addWidget(toolPrevious);
toolNext = new QToolButton(frameFind);
- toolNext->setObjectName(QStringLiteral("toolNext"));
+ toolNext->setObjectName(QString::fromUtf8("toolNext"));
toolNext->setMinimumSize(QSize(0, 0));
const QIcon icon2 = QIcon(QString::fromUtf8(":/qt-project.org/assistant/images/win/next.png"));
toolNext->setIcon(icon2);
@@ -147,17 +147,17 @@ public:
hboxLayout->addWidget(toolNext);
checkCase = new QCheckBox(frameFind);
- checkCase->setObjectName(QStringLiteral("checkCase"));
+ checkCase->setObjectName(QString::fromUtf8("checkCase"));
hboxLayout->addWidget(checkCase);
checkWholeWords = new QCheckBox(frameFind);
- checkWholeWords->setObjectName(QStringLiteral("checkWholeWords"));
+ checkWholeWords->setObjectName(QString::fromUtf8("checkWholeWords"));
hboxLayout->addWidget(checkWholeWords);
labelWrapped = new QLabel(frameFind);
- labelWrapped->setObjectName(QStringLiteral("labelWrapped"));
+ labelWrapped->setObjectName(QString::fromUtf8("labelWrapped"));
labelWrapped->setMinimumSize(QSize(0, 20));
labelWrapped->setMaximumSize(QSize(105, 20));
labelWrapped->setTextFormat(Qt::RichText);
diff --git a/tests/auto/tools/uic/baseline/tablewidgeteditor.ui.h b/tests/auto/tools/uic/baseline/tablewidgeteditor.ui.h
index ff000305cc..e3ba00095e 100644
--- a/tests/auto/tools/uic/baseline/tablewidgeteditor.ui.h
+++ b/tests/auto/tools/uic/baseline/tablewidgeteditor.ui.h
@@ -104,28 +104,28 @@ public:
void setupUi(QDialog *qdesigner_internal__TableWidgetEditor)
{
if (qdesigner_internal__TableWidgetEditor->objectName().isEmpty())
- qdesigner_internal__TableWidgetEditor->setObjectName(QStringLiteral("qdesigner_internal__TableWidgetEditor"));
+ qdesigner_internal__TableWidgetEditor->setObjectName(QString::fromUtf8("qdesigner_internal__TableWidgetEditor"));
qdesigner_internal__TableWidgetEditor->resize(591, 455);
gridLayout_4 = new QGridLayout(qdesigner_internal__TableWidgetEditor);
- gridLayout_4->setObjectName(QStringLiteral("gridLayout_4"));
+ gridLayout_4->setObjectName(QString::fromUtf8("gridLayout_4"));
itemsBox = new QGroupBox(qdesigner_internal__TableWidgetEditor);
- itemsBox->setObjectName(QStringLiteral("itemsBox"));
+ itemsBox->setObjectName(QString::fromUtf8("itemsBox"));
gridLayout = new QGridLayout(itemsBox);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
tableWidget = new QTableWidget(itemsBox);
- tableWidget->setObjectName(QStringLiteral("tableWidget"));
+ tableWidget->setObjectName(QString::fromUtf8("tableWidget"));
gridLayout->addWidget(tableWidget, 0, 0, 1, 1);
horizontalLayout_5 = new QHBoxLayout();
- horizontalLayout_5->setObjectName(QStringLiteral("horizontalLayout_5"));
+ horizontalLayout_5->setObjectName(QString::fromUtf8("horizontalLayout_5"));
label_3 = new QLabel(itemsBox);
- label_3->setObjectName(QStringLiteral("label_3"));
+ label_3->setObjectName(QString::fromUtf8("label_3"));
horizontalLayout_5->addWidget(label_3);
itemIconSelector = new qdesigner_internal::IconSelector(itemsBox);
- itemIconSelector->setObjectName(QStringLiteral("itemIconSelector"));
+ itemIconSelector->setObjectName(QString::fromUtf8("itemIconSelector"));
horizontalLayout_5->addWidget(itemIconSelector);
@@ -140,14 +140,14 @@ public:
gridLayout_4->addWidget(itemsBox, 0, 0, 1, 1);
buttonBox = new QDialogButtonBox(qdesigner_internal__TableWidgetEditor);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
gridLayout_4->addWidget(buttonBox, 1, 0, 1, 2);
widget = new QWidget(qdesigner_internal__TableWidgetEditor);
- widget->setObjectName(QStringLiteral("widget"));
+ widget->setObjectName(QString::fromUtf8("widget"));
QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -155,13 +155,13 @@ public:
widget->setSizePolicy(sizePolicy);
verticalLayout = new QVBoxLayout(widget);
verticalLayout->setContentsMargins(0, 0, 0, 0);
- verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
+ verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
columnsBox = new QGroupBox(widget);
- columnsBox->setObjectName(QStringLiteral("columnsBox"));
+ columnsBox->setObjectName(QString::fromUtf8("columnsBox"));
gridLayout_2 = new QGridLayout(columnsBox);
- gridLayout_2->setObjectName(QStringLiteral("gridLayout_2"));
+ gridLayout_2->setObjectName(QString::fromUtf8("gridLayout_2"));
columnsListWidget = new QListWidget(columnsBox);
- columnsListWidget->setObjectName(QStringLiteral("columnsListWidget"));
+ columnsListWidget->setObjectName(QString::fromUtf8("columnsListWidget"));
QSizePolicy sizePolicy1(QSizePolicy::Ignored, QSizePolicy::Expanding);
sizePolicy1.setHorizontalStretch(0);
sizePolicy1.setVerticalStretch(0);
@@ -172,14 +172,14 @@ public:
gridLayout_2->addWidget(columnsListWidget, 0, 0, 1, 1);
horizontalLayout_3 = new QHBoxLayout();
- horizontalLayout_3->setObjectName(QStringLiteral("horizontalLayout_3"));
+ horizontalLayout_3->setObjectName(QString::fromUtf8("horizontalLayout_3"));
newColumnButton = new QToolButton(columnsBox);
- newColumnButton->setObjectName(QStringLiteral("newColumnButton"));
+ newColumnButton->setObjectName(QString::fromUtf8("newColumnButton"));
horizontalLayout_3->addWidget(newColumnButton);
deleteColumnButton = new QToolButton(columnsBox);
- deleteColumnButton->setObjectName(QStringLiteral("deleteColumnButton"));
+ deleteColumnButton->setObjectName(QString::fromUtf8("deleteColumnButton"));
horizontalLayout_3->addWidget(deleteColumnButton);
@@ -188,12 +188,12 @@ public:
horizontalLayout_3->addItem(spacerItem);
moveColumnUpButton = new QToolButton(columnsBox);
- moveColumnUpButton->setObjectName(QStringLiteral("moveColumnUpButton"));
+ moveColumnUpButton->setObjectName(QString::fromUtf8("moveColumnUpButton"));
horizontalLayout_3->addWidget(moveColumnUpButton);
moveColumnDownButton = new QToolButton(columnsBox);
- moveColumnDownButton->setObjectName(QStringLiteral("moveColumnDownButton"));
+ moveColumnDownButton->setObjectName(QString::fromUtf8("moveColumnDownButton"));
horizontalLayout_3->addWidget(moveColumnDownButton);
@@ -201,14 +201,14 @@ public:
gridLayout_2->addLayout(horizontalLayout_3, 1, 0, 1, 1);
horizontalLayout_2 = new QHBoxLayout();
- horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2"));
+ horizontalLayout_2->setObjectName(QString::fromUtf8("horizontalLayout_2"));
label = new QLabel(columnsBox);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
horizontalLayout_2->addWidget(label);
columnIconSelector = new qdesigner_internal::IconSelector(columnsBox);
- columnIconSelector->setObjectName(QStringLiteral("columnIconSelector"));
+ columnIconSelector->setObjectName(QString::fromUtf8("columnIconSelector"));
horizontalLayout_2->addWidget(columnIconSelector);
@@ -223,11 +223,11 @@ public:
verticalLayout->addWidget(columnsBox);
rowsBox = new QGroupBox(widget);
- rowsBox->setObjectName(QStringLiteral("rowsBox"));
+ rowsBox->setObjectName(QString::fromUtf8("rowsBox"));
gridLayout_3 = new QGridLayout(rowsBox);
- gridLayout_3->setObjectName(QStringLiteral("gridLayout_3"));
+ gridLayout_3->setObjectName(QString::fromUtf8("gridLayout_3"));
rowsListWidget = new QListWidget(rowsBox);
- rowsListWidget->setObjectName(QStringLiteral("rowsListWidget"));
+ rowsListWidget->setObjectName(QString::fromUtf8("rowsListWidget"));
sizePolicy1.setHeightForWidth(rowsListWidget->sizePolicy().hasHeightForWidth());
rowsListWidget->setSizePolicy(sizePolicy1);
rowsListWidget->setFocusPolicy(Qt::TabFocus);
@@ -235,14 +235,14 @@ public:
gridLayout_3->addWidget(rowsListWidget, 0, 0, 1, 1);
horizontalLayout_4 = new QHBoxLayout();
- horizontalLayout_4->setObjectName(QStringLiteral("horizontalLayout_4"));
+ horizontalLayout_4->setObjectName(QString::fromUtf8("horizontalLayout_4"));
newRowButton = new QToolButton(rowsBox);
- newRowButton->setObjectName(QStringLiteral("newRowButton"));
+ newRowButton->setObjectName(QString::fromUtf8("newRowButton"));
horizontalLayout_4->addWidget(newRowButton);
deleteRowButton = new QToolButton(rowsBox);
- deleteRowButton->setObjectName(QStringLiteral("deleteRowButton"));
+ deleteRowButton->setObjectName(QString::fromUtf8("deleteRowButton"));
horizontalLayout_4->addWidget(deleteRowButton);
@@ -251,12 +251,12 @@ public:
horizontalLayout_4->addItem(spacerItem2);
moveRowUpButton = new QToolButton(rowsBox);
- moveRowUpButton->setObjectName(QStringLiteral("moveRowUpButton"));
+ moveRowUpButton->setObjectName(QString::fromUtf8("moveRowUpButton"));
horizontalLayout_4->addWidget(moveRowUpButton);
moveRowDownButton = new QToolButton(rowsBox);
- moveRowDownButton->setObjectName(QStringLiteral("moveRowDownButton"));
+ moveRowDownButton->setObjectName(QString::fromUtf8("moveRowDownButton"));
horizontalLayout_4->addWidget(moveRowDownButton);
@@ -264,14 +264,14 @@ public:
gridLayout_3->addLayout(horizontalLayout_4, 1, 0, 1, 1);
horizontalLayout = new QHBoxLayout();
- horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
+ horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
label_2 = new QLabel(rowsBox);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
horizontalLayout->addWidget(label_2);
rowIconSelector = new qdesigner_internal::IconSelector(rowsBox);
- rowIconSelector->setObjectName(QStringLiteral("rowIconSelector"));
+ rowIconSelector->setObjectName(QString::fromUtf8("rowIconSelector"));
horizontalLayout->addWidget(rowIconSelector);
diff --git a/tests/auto/tools/uic/baseline/tetrixwindow.ui.h b/tests/auto/tools/uic/baseline/tetrixwindow.ui.h
index 32c6464209..dc1033ce3a 100644
--- a/tests/auto/tools/uic/baseline/tetrixwindow.ui.h
+++ b/tests/auto/tools/uic/baseline/tetrixwindow.ui.h
@@ -42,7 +42,7 @@ public:
void setupUi(QWidget *TetrixWindow)
{
if (TetrixWindow->objectName().isEmpty())
- TetrixWindow->setObjectName(QStringLiteral("TetrixWindow"));
+ TetrixWindow->setObjectName(QString::fromUtf8("TetrixWindow"));
TetrixWindow->resize(537, 475);
vboxLayout = new QVBoxLayout(TetrixWindow);
#ifndef Q_OS_MAC
@@ -51,7 +51,7 @@ public:
#ifndef Q_OS_MAC
vboxLayout->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
gridLayout = new QGridLayout();
#ifndef Q_OS_MAC
gridLayout->setSpacing(6);
@@ -59,39 +59,39 @@ public:
#ifndef Q_OS_MAC
gridLayout->setContentsMargins(0, 0, 0, 0);
#endif
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
startButton = new QPushButton(TetrixWindow);
- startButton->setObjectName(QStringLiteral("startButton"));
+ startButton->setObjectName(QString::fromUtf8("startButton"));
startButton->setFocusPolicy(Qt::NoFocus);
gridLayout->addWidget(startButton, 4, 0, 1, 1);
linesLcd = new QLCDNumber(TetrixWindow);
- linesLcd->setObjectName(QStringLiteral("linesLcd"));
+ linesLcd->setObjectName(QString::fromUtf8("linesLcd"));
linesLcd->setSegmentStyle(QLCDNumber::Filled);
gridLayout->addWidget(linesLcd, 3, 2, 1, 1);
linesRemovedLabel = new QLabel(TetrixWindow);
- linesRemovedLabel->setObjectName(QStringLiteral("linesRemovedLabel"));
+ linesRemovedLabel->setObjectName(QString::fromUtf8("linesRemovedLabel"));
linesRemovedLabel->setAlignment(Qt::AlignBottom|Qt::AlignHCenter);
gridLayout->addWidget(linesRemovedLabel, 2, 2, 1, 1);
pauseButton = new QPushButton(TetrixWindow);
- pauseButton->setObjectName(QStringLiteral("pauseButton"));
+ pauseButton->setObjectName(QString::fromUtf8("pauseButton"));
pauseButton->setFocusPolicy(Qt::NoFocus);
gridLayout->addWidget(pauseButton, 5, 2, 1, 1);
scoreLcd = new QLCDNumber(TetrixWindow);
- scoreLcd->setObjectName(QStringLiteral("scoreLcd"));
+ scoreLcd->setObjectName(QString::fromUtf8("scoreLcd"));
scoreLcd->setSegmentStyle(QLCDNumber::Filled);
gridLayout->addWidget(scoreLcd, 1, 2, 1, 1);
board = new TetrixBoard(TetrixWindow);
- board->setObjectName(QStringLiteral("board"));
+ board->setObjectName(QString::fromUtf8("board"));
board->setFocusPolicy(Qt::StrongFocus);
board->setFrameShape(QFrame::Panel);
board->setFrameShadow(QFrame::Sunken);
@@ -99,31 +99,31 @@ public:
gridLayout->addWidget(board, 0, 1, 6, 1);
levelLabel = new QLabel(TetrixWindow);
- levelLabel->setObjectName(QStringLiteral("levelLabel"));
+ levelLabel->setObjectName(QString::fromUtf8("levelLabel"));
levelLabel->setAlignment(Qt::AlignBottom|Qt::AlignHCenter);
gridLayout->addWidget(levelLabel, 2, 0, 1, 1);
nextLabel = new QLabel(TetrixWindow);
- nextLabel->setObjectName(QStringLiteral("nextLabel"));
+ nextLabel->setObjectName(QString::fromUtf8("nextLabel"));
nextLabel->setAlignment(Qt::AlignBottom|Qt::AlignHCenter);
gridLayout->addWidget(nextLabel, 0, 0, 1, 1);
levelLcd = new QLCDNumber(TetrixWindow);
- levelLcd->setObjectName(QStringLiteral("levelLcd"));
+ levelLcd->setObjectName(QString::fromUtf8("levelLcd"));
levelLcd->setSegmentStyle(QLCDNumber::Filled);
gridLayout->addWidget(levelLcd, 3, 0, 1, 1);
scoreLabel = new QLabel(TetrixWindow);
- scoreLabel->setObjectName(QStringLiteral("scoreLabel"));
+ scoreLabel->setObjectName(QString::fromUtf8("scoreLabel"));
scoreLabel->setAlignment(Qt::AlignBottom|Qt::AlignHCenter);
gridLayout->addWidget(scoreLabel, 0, 2, 1, 1);
nextPieceLabel = new QLabel(TetrixWindow);
- nextPieceLabel->setObjectName(QStringLiteral("nextPieceLabel"));
+ nextPieceLabel->setObjectName(QString::fromUtf8("nextPieceLabel"));
nextPieceLabel->setFrameShape(QFrame::Box);
nextPieceLabel->setFrameShadow(QFrame::Raised);
nextPieceLabel->setAlignment(Qt::AlignCenter);
@@ -131,7 +131,7 @@ public:
gridLayout->addWidget(nextPieceLabel, 1, 0, 1, 1);
quitButton = new QPushButton(TetrixWindow);
- quitButton->setObjectName(QStringLiteral("quitButton"));
+ quitButton->setObjectName(QString::fromUtf8("quitButton"));
quitButton->setFocusPolicy(Qt::NoFocus);
gridLayout->addWidget(quitButton, 4, 2, 1, 1);
diff --git a/tests/auto/tools/uic/baseline/textfinder.ui.h b/tests/auto/tools/uic/baseline/textfinder.ui.h
index beae214e19..2f6bfebf98 100644
--- a/tests/auto/tools/uic/baseline/textfinder.ui.h
+++ b/tests/auto/tools/uic/baseline/textfinder.ui.h
@@ -36,7 +36,7 @@ public:
void setupUi(QWidget *Form)
{
if (Form->objectName().isEmpty())
- Form->setObjectName(QStringLiteral("Form"));
+ Form->setObjectName(QString::fromUtf8("Form"));
Form->resize(378, 158);
vboxLayout = new QVBoxLayout(Form);
#ifndef Q_OS_MAC
@@ -45,7 +45,7 @@ public:
#ifndef Q_OS_MAC
vboxLayout->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
gridLayout = new QGridLayout();
#ifndef Q_OS_MAC
gridLayout->setSpacing(6);
@@ -53,19 +53,19 @@ public:
#ifndef Q_OS_MAC
gridLayout->setContentsMargins(0, 0, 0, 0);
#endif
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
lineEdit = new QLineEdit(Form);
- lineEdit->setObjectName(QStringLiteral("lineEdit"));
+ lineEdit->setObjectName(QString::fromUtf8("lineEdit"));
gridLayout->addWidget(lineEdit, 0, 1, 1, 1);
searchLabel = new QLabel(Form);
- searchLabel->setObjectName(QStringLiteral("searchLabel"));
+ searchLabel->setObjectName(QString::fromUtf8("searchLabel"));
gridLayout->addWidget(searchLabel, 0, 0, 1, 1);
findButton = new QPushButton(Form);
- findButton->setObjectName(QStringLiteral("findButton"));
+ findButton->setObjectName(QString::fromUtf8("findButton"));
gridLayout->addWidget(findButton, 0, 2, 1, 1);
@@ -73,7 +73,7 @@ public:
vboxLayout->addLayout(gridLayout);
textEdit = new QTextEdit(Form);
- textEdit->setObjectName(QStringLiteral("textEdit"));
+ textEdit->setObjectName(QString::fromUtf8("textEdit"));
vboxLayout->addWidget(textEdit);
diff --git a/tests/auto/tools/uic/baseline/topicchooser.ui.h b/tests/auto/tools/uic/baseline/topicchooser.ui.h
index 2770553775..90ec485e39 100644
--- a/tests/auto/tools/uic/baseline/topicchooser.ui.h
+++ b/tests/auto/tools/uic/baseline/topicchooser.ui.h
@@ -37,7 +37,7 @@ public:
void setupUi(QDialog *TopicChooser)
{
if (TopicChooser->objectName().isEmpty())
- TopicChooser->setObjectName(QStringLiteral("TopicChooser"));
+ TopicChooser->setObjectName(QString::fromUtf8("TopicChooser"));
TopicChooser->resize(391, 223);
TopicChooser->setSizeGripEnabled(true);
vboxLayout = new QVBoxLayout(TopicChooser);
@@ -45,40 +45,40 @@ public:
vboxLayout->setSpacing(6);
#endif
vboxLayout->setContentsMargins(11, 11, 11, 11);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
- vboxLayout->setObjectName(QStringLiteral("unnamed"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("unnamed"));
label = new QLabel(TopicChooser);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
vboxLayout->addWidget(label);
listWidget = new QListWidget(TopicChooser);
- listWidget->setObjectName(QStringLiteral("listWidget"));
+ listWidget->setObjectName(QString::fromUtf8("listWidget"));
vboxLayout->addWidget(listWidget);
Layout16 = new QWidget(TopicChooser);
- Layout16->setObjectName(QStringLiteral("Layout16"));
+ Layout16->setObjectName(QString::fromUtf8("Layout16"));
hboxLayout = new QHBoxLayout(Layout16);
#ifndef Q_OS_MAC
hboxLayout->setSpacing(6);
#endif
hboxLayout->setContentsMargins(0, 0, 0, 0);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
- hboxLayout->setObjectName(QStringLiteral("unnamed"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("unnamed"));
hboxLayout->setContentsMargins(0, 0, 0, 0);
Horizontal_Spacing2 = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
hboxLayout->addItem(Horizontal_Spacing2);
buttonDisplay = new QPushButton(Layout16);
- buttonDisplay->setObjectName(QStringLiteral("buttonDisplay"));
+ buttonDisplay->setObjectName(QString::fromUtf8("buttonDisplay"));
buttonDisplay->setAutoDefault(true);
hboxLayout->addWidget(buttonDisplay);
buttonCancel = new QPushButton(Layout16);
- buttonCancel->setObjectName(QStringLiteral("buttonCancel"));
+ buttonCancel->setObjectName(QString::fromUtf8("buttonCancel"));
buttonCancel->setAutoDefault(true);
hboxLayout->addWidget(buttonCancel);
diff --git a/tests/auto/tools/uic/baseline/translatedialog.ui.h b/tests/auto/tools/uic/baseline/translatedialog.ui.h
index 32b73be37a..5bea11f9f2 100644
--- a/tests/auto/tools/uic/baseline/translatedialog.ui.h
+++ b/tests/auto/tools/uic/baseline/translatedialog.ui.h
@@ -79,7 +79,7 @@ public:
void setupUi(QDialog *TranslateDialog)
{
if (TranslateDialog->objectName().isEmpty())
- TranslateDialog->setObjectName(QStringLiteral("TranslateDialog"));
+ TranslateDialog->setObjectName(QString::fromUtf8("TranslateDialog"));
TranslateDialog->resize(407, 145);
QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
sizePolicy.setHorizontalStretch(0);
@@ -89,35 +89,35 @@ public:
hboxLayout = new QHBoxLayout(TranslateDialog);
hboxLayout->setSpacing(6);
hboxLayout->setContentsMargins(11, 11, 11, 11);
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
hboxLayout->setContentsMargins(9, 9, 9, 9);
vboxLayout = new QVBoxLayout();
vboxLayout->setSpacing(6);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
vboxLayout->setContentsMargins(0, 0, 0, 0);
gridLayout = new QGridLayout();
gridLayout->setSpacing(6);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
gridLayout->setHorizontalSpacing(6);
gridLayout->setVerticalSpacing(6);
gridLayout->setContentsMargins(0, 0, 0, 0);
ledTranslateTo = new QLineEdit(TranslateDialog);
- ledTranslateTo->setObjectName(QStringLiteral("ledTranslateTo"));
+ ledTranslateTo->setObjectName(QString::fromUtf8("ledTranslateTo"));
gridLayout->addWidget(ledTranslateTo, 1, 1, 1, 1);
findWhat = new QLabel(TranslateDialog);
- findWhat->setObjectName(QStringLiteral("findWhat"));
+ findWhat->setObjectName(QString::fromUtf8("findWhat"));
gridLayout->addWidget(findWhat, 0, 0, 1, 1);
translateTo = new QLabel(TranslateDialog);
- translateTo->setObjectName(QStringLiteral("translateTo"));
+ translateTo->setObjectName(QString::fromUtf8("translateTo"));
gridLayout->addWidget(translateTo, 1, 0, 1, 1);
ledFindWhat = new QLineEdit(TranslateDialog);
- ledFindWhat->setObjectName(QStringLiteral("ledFindWhat"));
+ ledFindWhat->setObjectName(QString::fromUtf8("ledFindWhat"));
gridLayout->addWidget(ledFindWhat, 0, 1, 1, 1);
@@ -125,18 +125,18 @@ public:
vboxLayout->addLayout(gridLayout);
groupBox = new QGroupBox(TranslateDialog);
- groupBox->setObjectName(QStringLiteral("groupBox"));
+ groupBox->setObjectName(QString::fromUtf8("groupBox"));
vboxLayout1 = new QVBoxLayout(groupBox);
vboxLayout1->setSpacing(6);
vboxLayout1->setContentsMargins(11, 11, 11, 11);
- vboxLayout1->setObjectName(QStringLiteral("vboxLayout1"));
+ vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
ckMatchCase = new QCheckBox(groupBox);
- ckMatchCase->setObjectName(QStringLiteral("ckMatchCase"));
+ ckMatchCase->setObjectName(QString::fromUtf8("ckMatchCase"));
vboxLayout1->addWidget(ckMatchCase);
ckMarkFinished = new QCheckBox(groupBox);
- ckMarkFinished->setObjectName(QStringLiteral("ckMarkFinished"));
+ ckMarkFinished->setObjectName(QString::fromUtf8("ckMarkFinished"));
vboxLayout1->addWidget(ckMarkFinished);
@@ -152,26 +152,26 @@ public:
vboxLayout2 = new QVBoxLayout();
vboxLayout2->setSpacing(6);
- vboxLayout2->setObjectName(QStringLiteral("vboxLayout2"));
+ vboxLayout2->setObjectName(QString::fromUtf8("vboxLayout2"));
vboxLayout2->setContentsMargins(0, 0, 0, 0);
findNxt = new QPushButton(TranslateDialog);
- findNxt->setObjectName(QStringLiteral("findNxt"));
+ findNxt->setObjectName(QString::fromUtf8("findNxt"));
findNxt->setFlat(false);
vboxLayout2->addWidget(findNxt);
translate = new QPushButton(TranslateDialog);
- translate->setObjectName(QStringLiteral("translate"));
+ translate->setObjectName(QString::fromUtf8("translate"));
vboxLayout2->addWidget(translate);
translateAll = new QPushButton(TranslateDialog);
- translateAll->setObjectName(QStringLiteral("translateAll"));
+ translateAll->setObjectName(QString::fromUtf8("translateAll"));
vboxLayout2->addWidget(translateAll);
cancel = new QPushButton(TranslateDialog);
- cancel->setObjectName(QStringLiteral("cancel"));
+ cancel->setObjectName(QString::fromUtf8("cancel"));
vboxLayout2->addWidget(cancel);
diff --git a/tests/auto/tools/uic/baseline/translation/Dialog_without_Buttons_tr.h b/tests/auto/tools/uic/baseline/translation/Dialog_without_Buttons_tr.h
index 1da7140f97..eea7b7335d 100644
--- a/tests/auto/tools/uic/baseline/translation/Dialog_without_Buttons_tr.h
+++ b/tests/auto/tools/uic/baseline/translation/Dialog_without_Buttons_tr.h
@@ -23,7 +23,7 @@ public:
void setupUi(QDialog *Dialog)
{
if (Dialog->objectName().isEmpty())
- Dialog->setObjectName(QStringLiteral("Dialog"));
+ Dialog->setObjectName(QString::fromUtf8("Dialog"));
Dialog->resize(400, 300);
retranslateUi(Dialog);
diff --git a/tests/auto/tools/uic/baseline/translationsettings.ui.h b/tests/auto/tools/uic/baseline/translationsettings.ui.h
index 522c9bd4e0..764e3a85b6 100644
--- a/tests/auto/tools/uic/baseline/translationsettings.ui.h
+++ b/tests/auto/tools/uic/baseline/translationsettings.ui.h
@@ -36,7 +36,7 @@ public:
void setupUi(QDialog *TranslationSettings)
{
if (TranslationSettings->objectName().isEmpty())
- TranslationSettings->setObjectName(QStringLiteral("TranslationSettings"));
+ TranslationSettings->setObjectName(QString::fromUtf8("TranslationSettings"));
TranslationSettings->resize(346, 125);
vboxLayout = new QVBoxLayout(TranslationSettings);
#ifndef Q_OS_MAC
@@ -45,9 +45,9 @@ public:
#ifndef Q_OS_MAC
vboxLayout->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
groupBox = new QGroupBox(TranslationSettings);
- groupBox->setObjectName(QStringLiteral("groupBox"));
+ groupBox->setObjectName(QString::fromUtf8("groupBox"));
gridLayout = new QGridLayout(groupBox);
#ifndef Q_OS_MAC
gridLayout->setSpacing(6);
@@ -55,24 +55,24 @@ public:
#ifndef Q_OS_MAC
gridLayout->setContentsMargins(9, 9, 9, 9);
#endif
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
cbLanguageList = new QComboBox(groupBox);
- cbLanguageList->setObjectName(QStringLiteral("cbLanguageList"));
+ cbLanguageList->setObjectName(QString::fromUtf8("cbLanguageList"));
gridLayout->addWidget(cbLanguageList, 0, 1, 1, 1);
label = new QLabel(groupBox);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
gridLayout->addWidget(label, 0, 0, 1, 1);
cbCountryList = new QComboBox(groupBox);
- cbCountryList->setObjectName(QStringLiteral("cbCountryList"));
+ cbCountryList->setObjectName(QString::fromUtf8("cbCountryList"));
gridLayout->addWidget(cbCountryList, 1, 1, 1, 1);
lblCountry = new QLabel(groupBox);
- lblCountry->setObjectName(QStringLiteral("lblCountry"));
+ lblCountry->setObjectName(QString::fromUtf8("lblCountry"));
gridLayout->addWidget(lblCountry, 1, 0, 1, 1);
@@ -80,7 +80,7 @@ public:
vboxLayout->addWidget(groupBox);
buttonBox = new QDialogButtonBox(TranslationSettings);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok);
diff --git a/tests/auto/tools/uic/baseline/treewidgeteditor.ui.h b/tests/auto/tools/uic/baseline/treewidgeteditor.ui.h
index 13957e843c..d432195648 100644
--- a/tests/auto/tools/uic/baseline/treewidgeteditor.ui.h
+++ b/tests/auto/tools/uic/baseline/treewidgeteditor.ui.h
@@ -96,34 +96,34 @@ public:
void setupUi(QDialog *qdesigner_internal__TreeWidgetEditor)
{
if (qdesigner_internal__TreeWidgetEditor->objectName().isEmpty())
- qdesigner_internal__TreeWidgetEditor->setObjectName(QStringLiteral("qdesigner_internal__TreeWidgetEditor"));
+ qdesigner_internal__TreeWidgetEditor->setObjectName(QString::fromUtf8("qdesigner_internal__TreeWidgetEditor"));
qdesigner_internal__TreeWidgetEditor->resize(619, 321);
gridLayout_3 = new QGridLayout(qdesigner_internal__TreeWidgetEditor);
- gridLayout_3->setObjectName(QStringLiteral("gridLayout_3"));
+ gridLayout_3->setObjectName(QString::fromUtf8("gridLayout_3"));
itemsBox = new QGroupBox(qdesigner_internal__TreeWidgetEditor);
- itemsBox->setObjectName(QStringLiteral("itemsBox"));
+ itemsBox->setObjectName(QString::fromUtf8("itemsBox"));
gridLayout = new QGridLayout(itemsBox);
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
treeWidget = new QTreeWidget(itemsBox);
- treeWidget->setObjectName(QStringLiteral("treeWidget"));
+ treeWidget->setObjectName(QString::fromUtf8("treeWidget"));
treeWidget->setFocusPolicy(Qt::TabFocus);
gridLayout->addWidget(treeWidget, 0, 0, 1, 1);
horizontalLayout_4 = new QHBoxLayout();
- horizontalLayout_4->setObjectName(QStringLiteral("horizontalLayout_4"));
+ horizontalLayout_4->setObjectName(QString::fromUtf8("horizontalLayout_4"));
newItemButton = new QToolButton(itemsBox);
- newItemButton->setObjectName(QStringLiteral("newItemButton"));
+ newItemButton->setObjectName(QString::fromUtf8("newItemButton"));
horizontalLayout_4->addWidget(newItemButton);
newSubItemButton = new QToolButton(itemsBox);
- newSubItemButton->setObjectName(QStringLiteral("newSubItemButton"));
+ newSubItemButton->setObjectName(QString::fromUtf8("newSubItemButton"));
horizontalLayout_4->addWidget(newSubItemButton);
deleteItemButton = new QToolButton(itemsBox);
- deleteItemButton->setObjectName(QStringLiteral("deleteItemButton"));
+ deleteItemButton->setObjectName(QString::fromUtf8("deleteItemButton"));
horizontalLayout_4->addWidget(deleteItemButton);
@@ -132,22 +132,22 @@ public:
horizontalLayout_4->addItem(spacerItem);
moveItemLeftButton = new QToolButton(itemsBox);
- moveItemLeftButton->setObjectName(QStringLiteral("moveItemLeftButton"));
+ moveItemLeftButton->setObjectName(QString::fromUtf8("moveItemLeftButton"));
horizontalLayout_4->addWidget(moveItemLeftButton);
moveItemRightButton = new QToolButton(itemsBox);
- moveItemRightButton->setObjectName(QStringLiteral("moveItemRightButton"));
+ moveItemRightButton->setObjectName(QString::fromUtf8("moveItemRightButton"));
horizontalLayout_4->addWidget(moveItemRightButton);
moveItemUpButton = new QToolButton(itemsBox);
- moveItemUpButton->setObjectName(QStringLiteral("moveItemUpButton"));
+ moveItemUpButton->setObjectName(QString::fromUtf8("moveItemUpButton"));
horizontalLayout_4->addWidget(moveItemUpButton);
moveItemDownButton = new QToolButton(itemsBox);
- moveItemDownButton->setObjectName(QStringLiteral("moveItemDownButton"));
+ moveItemDownButton->setObjectName(QString::fromUtf8("moveItemDownButton"));
horizontalLayout_4->addWidget(moveItemDownButton);
@@ -155,14 +155,14 @@ public:
gridLayout->addLayout(horizontalLayout_4, 1, 0, 1, 1);
horizontalLayout_2 = new QHBoxLayout();
- horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2"));
+ horizontalLayout_2->setObjectName(QString::fromUtf8("horizontalLayout_2"));
label_2 = new QLabel(itemsBox);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
horizontalLayout_2->addWidget(label_2);
itemIconSelector = new qdesigner_internal::IconSelector(itemsBox);
- itemIconSelector->setObjectName(QStringLiteral("itemIconSelector"));
+ itemIconSelector->setObjectName(QString::fromUtf8("itemIconSelector"));
horizontalLayout_2->addWidget(itemIconSelector);
@@ -177,16 +177,16 @@ public:
gridLayout_3->addWidget(itemsBox, 0, 0, 1, 1);
columnsBox = new QGroupBox(qdesigner_internal__TreeWidgetEditor);
- columnsBox->setObjectName(QStringLiteral("columnsBox"));
+ columnsBox->setObjectName(QString::fromUtf8("columnsBox"));
QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(columnsBox->sizePolicy().hasHeightForWidth());
columnsBox->setSizePolicy(sizePolicy);
gridLayout_2 = new QGridLayout(columnsBox);
- gridLayout_2->setObjectName(QStringLiteral("gridLayout_2"));
+ gridLayout_2->setObjectName(QString::fromUtf8("gridLayout_2"));
listWidget = new QListWidget(columnsBox);
- listWidget->setObjectName(QStringLiteral("listWidget"));
+ listWidget->setObjectName(QString::fromUtf8("listWidget"));
QSizePolicy sizePolicy1(QSizePolicy::Ignored, QSizePolicy::Expanding);
sizePolicy1.setHorizontalStretch(0);
sizePolicy1.setVerticalStretch(0);
@@ -197,14 +197,14 @@ public:
gridLayout_2->addWidget(listWidget, 0, 0, 1, 1);
horizontalLayout_3 = new QHBoxLayout();
- horizontalLayout_3->setObjectName(QStringLiteral("horizontalLayout_3"));
+ horizontalLayout_3->setObjectName(QString::fromUtf8("horizontalLayout_3"));
newColumnButton = new QToolButton(columnsBox);
- newColumnButton->setObjectName(QStringLiteral("newColumnButton"));
+ newColumnButton->setObjectName(QString::fromUtf8("newColumnButton"));
horizontalLayout_3->addWidget(newColumnButton);
deleteColumnButton = new QToolButton(columnsBox);
- deleteColumnButton->setObjectName(QStringLiteral("deleteColumnButton"));
+ deleteColumnButton->setObjectName(QString::fromUtf8("deleteColumnButton"));
horizontalLayout_3->addWidget(deleteColumnButton);
@@ -213,12 +213,12 @@ public:
horizontalLayout_3->addItem(spacerItem1);
moveColumnUpButton = new QToolButton(columnsBox);
- moveColumnUpButton->setObjectName(QStringLiteral("moveColumnUpButton"));
+ moveColumnUpButton->setObjectName(QString::fromUtf8("moveColumnUpButton"));
horizontalLayout_3->addWidget(moveColumnUpButton);
moveColumnDownButton = new QToolButton(columnsBox);
- moveColumnDownButton->setObjectName(QStringLiteral("moveColumnDownButton"));
+ moveColumnDownButton->setObjectName(QString::fromUtf8("moveColumnDownButton"));
horizontalLayout_3->addWidget(moveColumnDownButton);
@@ -226,14 +226,14 @@ public:
gridLayout_2->addLayout(horizontalLayout_3, 1, 0, 1, 1);
horizontalLayout = new QHBoxLayout();
- horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
+ horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
label = new QLabel(columnsBox);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
horizontalLayout->addWidget(label);
columnIconSelector = new qdesigner_internal::IconSelector(columnsBox);
- columnIconSelector->setObjectName(QStringLiteral("columnIconSelector"));
+ columnIconSelector->setObjectName(QString::fromUtf8("columnIconSelector"));
horizontalLayout->addWidget(columnIconSelector);
@@ -248,7 +248,7 @@ public:
gridLayout_3->addWidget(columnsBox, 0, 1, 1, 1);
buttonBox = new QDialogButtonBox(qdesigner_internal__TreeWidgetEditor);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
diff --git a/tests/auto/tools/uic/baseline/trpreviewtool.ui.h b/tests/auto/tools/uic/baseline/trpreviewtool.ui.h
index da6e86a8ce..3fbf125a1f 100644
--- a/tests/auto/tools/uic/baseline/trpreviewtool.ui.h
+++ b/tests/auto/tools/uic/baseline/trpreviewtool.ui.h
@@ -79,58 +79,58 @@ public:
void setupUi(QMainWindow *TrPreviewToolClass)
{
if (TrPreviewToolClass->objectName().isEmpty())
- TrPreviewToolClass->setObjectName(QStringLiteral("TrPreviewToolClass"));
+ TrPreviewToolClass->setObjectName(QString::fromUtf8("TrPreviewToolClass"));
TrPreviewToolClass->resize(593, 466);
actionOpenForm = new QAction(TrPreviewToolClass);
- actionOpenForm->setObjectName(QStringLiteral("actionOpenForm"));
+ actionOpenForm->setObjectName(QString::fromUtf8("actionOpenForm"));
const QIcon icon = QIcon(QString::fromUtf8(":/images/open_form.png"));
actionOpenForm->setIcon(icon);
actionLoadTranslation = new QAction(TrPreviewToolClass);
- actionLoadTranslation->setObjectName(QStringLiteral("actionLoadTranslation"));
+ actionLoadTranslation->setObjectName(QString::fromUtf8("actionLoadTranslation"));
const QIcon icon1 = QIcon(QString::fromUtf8(":/images/load_translation.png"));
actionLoadTranslation->setIcon(icon1);
actionReloadTranslations = new QAction(TrPreviewToolClass);
- actionReloadTranslations->setObjectName(QStringLiteral("actionReloadTranslations"));
+ actionReloadTranslations->setObjectName(QString::fromUtf8("actionReloadTranslations"));
const QIcon icon2 = QIcon(QString::fromUtf8(":/images/reload_translations.png"));
actionReloadTranslations->setIcon(icon2);
actionClose = new QAction(TrPreviewToolClass);
- actionClose->setObjectName(QStringLiteral("actionClose"));
+ actionClose->setObjectName(QString::fromUtf8("actionClose"));
actionAbout = new QAction(TrPreviewToolClass);
- actionAbout->setObjectName(QStringLiteral("actionAbout"));
+ actionAbout->setObjectName(QString::fromUtf8("actionAbout"));
actionAbout_Qt = new QAction(TrPreviewToolClass);
- actionAbout_Qt->setObjectName(QStringLiteral("actionAbout_Qt"));
+ actionAbout_Qt->setObjectName(QString::fromUtf8("actionAbout_Qt"));
centralWidget = new QWidget(TrPreviewToolClass);
- centralWidget->setObjectName(QStringLiteral("centralWidget"));
+ centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
TrPreviewToolClass->setCentralWidget(centralWidget);
menuBar = new QMenuBar(TrPreviewToolClass);
- menuBar->setObjectName(QStringLiteral("menuBar"));
+ menuBar->setObjectName(QString::fromUtf8("menuBar"));
menuBar->setGeometry(QRect(0, 0, 593, 21));
menuView = new QMenu(menuBar);
- menuView->setObjectName(QStringLiteral("menuView"));
+ menuView->setObjectName(QString::fromUtf8("menuView"));
menuViewViews = new QMenu(menuView);
- menuViewViews->setObjectName(QStringLiteral("menuViewViews"));
+ menuViewViews->setObjectName(QString::fromUtf8("menuViewViews"));
menuHelp = new QMenu(menuBar);
- menuHelp->setObjectName(QStringLiteral("menuHelp"));
+ menuHelp->setObjectName(QString::fromUtf8("menuHelp"));
menuFile = new QMenu(menuBar);
- menuFile->setObjectName(QStringLiteral("menuFile"));
+ menuFile->setObjectName(QString::fromUtf8("menuFile"));
TrPreviewToolClass->setMenuBar(menuBar);
mainToolBar = new QToolBar(TrPreviewToolClass);
- mainToolBar->setObjectName(QStringLiteral("mainToolBar"));
+ mainToolBar->setObjectName(QString::fromUtf8("mainToolBar"));
mainToolBar->setOrientation(Qt::Horizontal);
TrPreviewToolClass->addToolBar(static_cast<Qt::ToolBarArea>(4), mainToolBar);
statusBar = new QStatusBar(TrPreviewToolClass);
- statusBar->setObjectName(QStringLiteral("statusBar"));
+ statusBar->setObjectName(QString::fromUtf8("statusBar"));
TrPreviewToolClass->setStatusBar(statusBar);
dwForms = new QDockWidget(TrPreviewToolClass);
- dwForms->setObjectName(QStringLiteral("dwForms"));
+ dwForms->setObjectName(QString::fromUtf8("dwForms"));
dockWidgetContents = new QWidget();
- dockWidgetContents->setObjectName(QStringLiteral("dockWidgetContents"));
+ dockWidgetContents->setObjectName(QString::fromUtf8("dockWidgetContents"));
vboxLayout = new QVBoxLayout(dockWidgetContents);
vboxLayout->setSpacing(0);
vboxLayout->setContentsMargins(0, 0, 0, 0);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
viewForms = new QListView(dockWidgetContents);
- viewForms->setObjectName(QStringLiteral("viewForms"));
+ viewForms->setObjectName(QString::fromUtf8("viewForms"));
viewForms->setEditTriggers(QAbstractItemView::NoEditTriggers);
viewForms->setAlternatingRowColors(true);
viewForms->setUniformItemSizes(true);
diff --git a/tests/auto/tools/uic/baseline/validators.ui.h b/tests/auto/tools/uic/baseline/validators.ui.h
index a28f9e8390..d0ae777f65 100644
--- a/tests/auto/tools/uic/baseline/validators.ui.h
+++ b/tests/auto/tools/uic/baseline/validators.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'validators.ui'
**
-** Created by: Qt User Interface Compiler version 5.10.0
+** Created by: Qt User Interface Compiler version 5.12.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -76,7 +76,7 @@ public:
void setupUi(QWidget *ValidatorsForm)
{
if (ValidatorsForm->objectName().isEmpty())
- ValidatorsForm->setObjectName(QStringLiteral("ValidatorsForm"));
+ ValidatorsForm->setObjectName(QString::fromUtf8("ValidatorsForm"));
ValidatorsForm->resize(526, 668);
vboxLayout = new QVBoxLayout(ValidatorsForm);
#ifndef Q_OS_MAC
@@ -85,7 +85,7 @@ public:
#ifndef Q_OS_MAC
vboxLayout->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
hboxLayout = new QHBoxLayout();
#ifndef Q_OS_MAC
hboxLayout->setSpacing(6);
@@ -93,9 +93,9 @@ public:
#ifndef Q_OS_MAC
hboxLayout->setContentsMargins(0, 0, 0, 0);
#endif
- hboxLayout->setObjectName(QStringLiteral("hboxLayout"));
+ hboxLayout->setObjectName(QString::fromUtf8("hboxLayout"));
localeSelector = new LocaleSelector(ValidatorsForm);
- localeSelector->setObjectName(QStringLiteral("localeSelector"));
+ localeSelector->setObjectName(QString::fromUtf8("localeSelector"));
hboxLayout->addWidget(localeSelector);
@@ -107,7 +107,7 @@ public:
vboxLayout->addLayout(hboxLayout);
groupBox = new QGroupBox(ValidatorsForm);
- groupBox->setObjectName(QStringLiteral("groupBox"));
+ groupBox->setObjectName(QString::fromUtf8("groupBox"));
vboxLayout1 = new QVBoxLayout(groupBox);
#ifndef Q_OS_MAC
vboxLayout1->setSpacing(6);
@@ -115,7 +115,7 @@ public:
#ifndef Q_OS_MAC
vboxLayout1->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout1->setObjectName(QStringLiteral("vboxLayout1"));
+ vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1"));
hboxLayout1 = new QHBoxLayout();
#ifndef Q_OS_MAC
hboxLayout1->setSpacing(6);
@@ -123,7 +123,7 @@ public:
#ifndef Q_OS_MAC
hboxLayout1->setContentsMargins(0, 0, 0, 0);
#endif
- hboxLayout1->setObjectName(QStringLiteral("hboxLayout1"));
+ hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1"));
gridLayout = new QGridLayout();
#ifndef Q_OS_MAC
gridLayout->setSpacing(6);
@@ -131,15 +131,15 @@ public:
#ifndef Q_OS_MAC
gridLayout->setContentsMargins(0, 0, 0, 0);
#endif
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
label = new QLabel(groupBox);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
label->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
gridLayout->addWidget(label, 0, 0, 1, 1);
minVal = new QSpinBox(groupBox);
- minVal->setObjectName(QStringLiteral("minVal"));
+ minVal->setObjectName(QString::fromUtf8("minVal"));
QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
sizePolicy.setHorizontalStretch(1);
sizePolicy.setVerticalStretch(0);
@@ -151,13 +151,13 @@ public:
gridLayout->addWidget(minVal, 0, 1, 1, 1);
label_2 = new QLabel(groupBox);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
label_2->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
gridLayout->addWidget(label_2, 1, 0, 1, 1);
maxVal = new QSpinBox(groupBox);
- maxVal->setObjectName(QStringLiteral("maxVal"));
+ maxVal->setObjectName(QString::fromUtf8("maxVal"));
sizePolicy.setHeightForWidth(maxVal->sizePolicy().hasHeightForWidth());
maxVal->setSizePolicy(sizePolicy);
maxVal->setMinimum(-1000000);
@@ -170,7 +170,7 @@ public:
hboxLayout1->addLayout(gridLayout);
frame = new QFrame(groupBox);
- frame->setObjectName(QStringLiteral("frame"));
+ frame->setObjectName(QString::fromUtf8("frame"));
frame->setFrameShape(QFrame::StyledPanel);
frame->setFrameShadow(QFrame::Sunken);
vboxLayout2 = new QVBoxLayout(frame);
@@ -180,9 +180,9 @@ public:
#ifndef Q_OS_MAC
vboxLayout2->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout2->setObjectName(QStringLiteral("vboxLayout2"));
+ vboxLayout2->setObjectName(QString::fromUtf8("vboxLayout2"));
ledWidget = new LEDWidget(frame);
- ledWidget->setObjectName(QStringLiteral("ledWidget"));
+ ledWidget->setObjectName(QString::fromUtf8("ledWidget"));
QSizePolicy sizePolicy1(QSizePolicy::Preferred, QSizePolicy::Fixed);
sizePolicy1.setHorizontalStretch(0);
sizePolicy1.setVerticalStretch(0);
@@ -194,7 +194,7 @@ public:
vboxLayout2->addWidget(ledWidget);
label_7 = new QLabel(frame);
- label_7->setObjectName(QStringLiteral("label_7"));
+ label_7->setObjectName(QString::fromUtf8("label_7"));
vboxLayout2->addWidget(label_7);
@@ -209,7 +209,7 @@ public:
vboxLayout1->addItem(spacerItem1);
editor = new QLineEdit(groupBox);
- editor->setObjectName(QStringLiteral("editor"));
+ editor->setObjectName(QString::fromUtf8("editor"));
vboxLayout1->addWidget(editor);
@@ -217,7 +217,7 @@ public:
vboxLayout->addWidget(groupBox);
groupBox_2 = new QGroupBox(ValidatorsForm);
- groupBox_2->setObjectName(QStringLiteral("groupBox_2"));
+ groupBox_2->setObjectName(QString::fromUtf8("groupBox_2"));
vboxLayout3 = new QVBoxLayout(groupBox_2);
#ifndef Q_OS_MAC
vboxLayout3->setSpacing(6);
@@ -225,7 +225,7 @@ public:
#ifndef Q_OS_MAC
vboxLayout3->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout3->setObjectName(QStringLiteral("vboxLayout3"));
+ vboxLayout3->setObjectName(QString::fromUtf8("vboxLayout3"));
hboxLayout2 = new QHBoxLayout();
#ifndef Q_OS_MAC
hboxLayout2->setSpacing(6);
@@ -233,7 +233,7 @@ public:
#ifndef Q_OS_MAC
hboxLayout2->setContentsMargins(0, 0, 0, 0);
#endif
- hboxLayout2->setObjectName(QStringLiteral("hboxLayout2"));
+ hboxLayout2->setObjectName(QString::fromUtf8("hboxLayout2"));
gridLayout1 = new QGridLayout();
#ifndef Q_OS_MAC
gridLayout1->setSpacing(6);
@@ -241,25 +241,25 @@ public:
#ifndef Q_OS_MAC
gridLayout1->setContentsMargins(0, 0, 0, 0);
#endif
- gridLayout1->setObjectName(QStringLiteral("gridLayout1"));
+ gridLayout1->setObjectName(QString::fromUtf8("gridLayout1"));
label_3 = new QLabel(groupBox_2);
- label_3->setObjectName(QStringLiteral("label_3"));
+ label_3->setObjectName(QString::fromUtf8("label_3"));
label_3->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
gridLayout1->addWidget(label_3, 0, 0, 1, 1);
doubleMinVal = new QDoubleSpinBox(groupBox_2);
- doubleMinVal->setObjectName(QStringLiteral("doubleMinVal"));
+ doubleMinVal->setObjectName(QString::fromUtf8("doubleMinVal"));
sizePolicy.setHeightForWidth(doubleMinVal->sizePolicy().hasHeightForWidth());
doubleMinVal->setSizePolicy(sizePolicy);
- doubleMinVal->setMinimum(-100000);
- doubleMinVal->setMaximum(100000);
- doubleMinVal->setValue(0);
+ doubleMinVal->setMinimum(-100000.000000000000000);
+ doubleMinVal->setMaximum(100000.000000000000000);
+ doubleMinVal->setValue(0.000000000000000);
gridLayout1->addWidget(doubleMinVal, 0, 1, 1, 1);
label_5 = new QLabel(groupBox_2);
- label_5->setObjectName(QStringLiteral("label_5"));
+ label_5->setObjectName(QString::fromUtf8("label_5"));
label_5->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
gridLayout1->addWidget(label_5, 0, 2, 1, 1);
@@ -267,34 +267,34 @@ public:
doubleFormat = new QComboBox(groupBox_2);
doubleFormat->addItem(QString());
doubleFormat->addItem(QString());
- doubleFormat->setObjectName(QStringLiteral("doubleFormat"));
+ doubleFormat->setObjectName(QString::fromUtf8("doubleFormat"));
gridLayout1->addWidget(doubleFormat, 0, 3, 1, 1);
label_4 = new QLabel(groupBox_2);
- label_4->setObjectName(QStringLiteral("label_4"));
+ label_4->setObjectName(QString::fromUtf8("label_4"));
label_4->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
gridLayout1->addWidget(label_4, 1, 0, 1, 1);
doubleMaxVal = new QDoubleSpinBox(groupBox_2);
- doubleMaxVal->setObjectName(QStringLiteral("doubleMaxVal"));
+ doubleMaxVal->setObjectName(QString::fromUtf8("doubleMaxVal"));
sizePolicy.setHeightForWidth(doubleMaxVal->sizePolicy().hasHeightForWidth());
doubleMaxVal->setSizePolicy(sizePolicy);
- doubleMaxVal->setMinimum(-100000);
- doubleMaxVal->setMaximum(100000);
- doubleMaxVal->setValue(1000);
+ doubleMaxVal->setMinimum(-100000.000000000000000);
+ doubleMaxVal->setMaximum(100000.000000000000000);
+ doubleMaxVal->setValue(1000.000000000000000);
gridLayout1->addWidget(doubleMaxVal, 1, 1, 1, 1);
label_6 = new QLabel(groupBox_2);
- label_6->setObjectName(QStringLiteral("label_6"));
+ label_6->setObjectName(QString::fromUtf8("label_6"));
label_6->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
gridLayout1->addWidget(label_6, 1, 2, 1, 1);
doubleDecimals = new QSpinBox(groupBox_2);
- doubleDecimals->setObjectName(QStringLiteral("doubleDecimals"));
+ doubleDecimals->setObjectName(QString::fromUtf8("doubleDecimals"));
doubleDecimals->setValue(2);
gridLayout1->addWidget(doubleDecimals, 1, 3, 1, 1);
@@ -303,7 +303,7 @@ public:
hboxLayout2->addLayout(gridLayout1);
frame_2 = new QFrame(groupBox_2);
- frame_2->setObjectName(QStringLiteral("frame_2"));
+ frame_2->setObjectName(QString::fromUtf8("frame_2"));
frame_2->setFrameShape(QFrame::StyledPanel);
frame_2->setFrameShadow(QFrame::Sunken);
vboxLayout4 = new QVBoxLayout(frame_2);
@@ -313,16 +313,16 @@ public:
#ifndef Q_OS_MAC
vboxLayout4->setContentsMargins(9, 9, 9, 9);
#endif
- vboxLayout4->setObjectName(QStringLiteral("vboxLayout4"));
+ vboxLayout4->setObjectName(QString::fromUtf8("vboxLayout4"));
doubleLedWidget = new LEDWidget(frame_2);
- doubleLedWidget->setObjectName(QStringLiteral("doubleLedWidget"));
+ doubleLedWidget->setObjectName(QString::fromUtf8("doubleLedWidget"));
doubleLedWidget->setPixmap(QPixmap(QString::fromUtf8(":/ledoff.png")));
doubleLedWidget->setAlignment(Qt::AlignCenter);
vboxLayout4->addWidget(doubleLedWidget);
label_8 = new QLabel(frame_2);
- label_8->setObjectName(QStringLiteral("label_8"));
+ label_8->setObjectName(QString::fromUtf8("label_8"));
vboxLayout4->addWidget(label_8);
@@ -337,7 +337,7 @@ public:
vboxLayout3->addItem(spacerItem2);
doubleEditor = new QLineEdit(groupBox_2);
- doubleEditor->setObjectName(QStringLiteral("doubleEditor"));
+ doubleEditor->setObjectName(QString::fromUtf8("doubleEditor"));
vboxLayout3->addWidget(doubleEditor);
@@ -353,13 +353,13 @@ public:
hboxLayout3->setSpacing(6);
#endif
hboxLayout3->setContentsMargins(0, 0, 0, 0);
- hboxLayout3->setObjectName(QStringLiteral("hboxLayout3"));
+ hboxLayout3->setObjectName(QString::fromUtf8("hboxLayout3"));
spacerItem4 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
hboxLayout3->addItem(spacerItem4);
pushButton = new QPushButton(ValidatorsForm);
- pushButton->setObjectName(QStringLiteral("pushButton"));
+ pushButton->setObjectName(QString::fromUtf8("pushButton"));
hboxLayout3->addWidget(pushButton);
diff --git a/tests/auto/tools/uic/baseline/wateringconfigdialog.ui.h b/tests/auto/tools/uic/baseline/wateringconfigdialog.ui.h
index 1254eee3f7..d6f7ff5526 100644
--- a/tests/auto/tools/uic/baseline/wateringconfigdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/wateringconfigdialog.ui.h
@@ -64,14 +64,14 @@ public:
void setupUi(QDialog *WateringConfigDialog)
{
if (WateringConfigDialog->objectName().isEmpty())
- WateringConfigDialog->setObjectName(QStringLiteral("WateringConfigDialog"));
+ WateringConfigDialog->setObjectName(QString::fromUtf8("WateringConfigDialog"));
WateringConfigDialog->resize(334, 550);
vboxLayout = new QVBoxLayout(WateringConfigDialog);
- vboxLayout->setObjectName(QStringLiteral("vboxLayout"));
+ vboxLayout->setObjectName(QString::fromUtf8("vboxLayout"));
gridLayout = new QGridLayout();
- gridLayout->setObjectName(QStringLiteral("gridLayout"));
+ gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
label_3 = new QLabel(WateringConfigDialog);
- label_3->setObjectName(QStringLiteral("label_3"));
+ label_3->setObjectName(QString::fromUtf8("label_3"));
gridLayout->addWidget(label_3, 0, 0, 1, 1);
@@ -82,7 +82,7 @@ public:
plantComboBox->addItem(QString());
plantComboBox->addItem(QString());
plantComboBox->addItem(QString());
- plantComboBox->setObjectName(QStringLiteral("plantComboBox"));
+ plantComboBox->setObjectName(QString::fromUtf8("plantComboBox"));
QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
@@ -96,12 +96,12 @@ public:
gridLayout->addItem(spacerItem, 1, 0, 1, 1);
label_2 = new QLabel(WateringConfigDialog);
- label_2->setObjectName(QStringLiteral("label_2"));
+ label_2->setObjectName(QString::fromUtf8("label_2"));
gridLayout->addWidget(label_2, 2, 0, 1, 1);
temperatureCheckBox = new QCheckBox(WateringConfigDialog);
- temperatureCheckBox->setObjectName(QStringLiteral("temperatureCheckBox"));
+ temperatureCheckBox->setObjectName(QString::fromUtf8("temperatureCheckBox"));
gridLayout->addWidget(temperatureCheckBox, 3, 1, 1, 3);
@@ -110,7 +110,7 @@ public:
gridLayout->addItem(spacerItem1, 4, 1, 1, 1);
temperatureSpinBox = new QSpinBox(WateringConfigDialog);
- temperatureSpinBox->setObjectName(QStringLiteral("temperatureSpinBox"));
+ temperatureSpinBox->setObjectName(QString::fromUtf8("temperatureSpinBox"));
temperatureSpinBox->setEnabled(false);
temperatureSpinBox->setMinimum(10);
temperatureSpinBox->setMaximum(60);
@@ -123,7 +123,7 @@ public:
gridLayout->addItem(spacerItem2, 4, 3, 1, 1);
rainCheckBox = new QCheckBox(WateringConfigDialog);
- rainCheckBox->setObjectName(QStringLiteral("rainCheckBox"));
+ rainCheckBox->setObjectName(QString::fromUtf8("rainCheckBox"));
gridLayout->addWidget(rainCheckBox, 5, 1, 1, 3);
@@ -132,7 +132,7 @@ public:
gridLayout->addItem(spacerItem3, 6, 1, 1, 1);
rainSpinBox = new QSpinBox(WateringConfigDialog);
- rainSpinBox->setObjectName(QStringLiteral("rainSpinBox"));
+ rainSpinBox->setObjectName(QString::fromUtf8("rainSpinBox"));
rainSpinBox->setEnabled(false);
rainSpinBox->setMinimum(1);
@@ -147,22 +147,22 @@ public:
gridLayout->addItem(spacerItem5, 7, 2, 1, 1);
label = new QLabel(WateringConfigDialog);
- label->setObjectName(QStringLiteral("label"));
+ label->setObjectName(QString::fromUtf8("label"));
gridLayout->addWidget(label, 8, 0, 1, 1);
startTimeEdit = new QTimeEdit(WateringConfigDialog);
- startTimeEdit->setObjectName(QStringLiteral("startTimeEdit"));
+ startTimeEdit->setObjectName(QString::fromUtf8("startTimeEdit"));
gridLayout->addWidget(startTimeEdit, 8, 1, 1, 3);
label_4 = new QLabel(WateringConfigDialog);
- label_4->setObjectName(QStringLiteral("label_4"));
+ label_4->setObjectName(QString::fromUtf8("label_4"));
gridLayout->addWidget(label_4, 9, 0, 1, 1);
amountSpinBox = new QSpinBox(WateringConfigDialog);
- amountSpinBox->setObjectName(QStringLiteral("amountSpinBox"));
+ amountSpinBox->setObjectName(QString::fromUtf8("amountSpinBox"));
amountSpinBox->setMinimum(100);
amountSpinBox->setMaximum(10000);
amountSpinBox->setSingleStep(100);
@@ -171,7 +171,7 @@ public:
gridLayout->addWidget(amountSpinBox, 9, 1, 1, 3);
label_5 = new QLabel(WateringConfigDialog);
- label_5->setObjectName(QStringLiteral("label_5"));
+ label_5->setObjectName(QString::fromUtf8("label_5"));
gridLayout->addWidget(label_5, 10, 0, 1, 1);
@@ -180,17 +180,17 @@ public:
sourceComboBox->addItem(QString());
sourceComboBox->addItem(QString());
sourceComboBox->addItem(QString());
- sourceComboBox->setObjectName(QStringLiteral("sourceComboBox"));
+ sourceComboBox->setObjectName(QString::fromUtf8("sourceComboBox"));
gridLayout->addWidget(sourceComboBox, 10, 1, 1, 3);
label_6 = new QLabel(WateringConfigDialog);
- label_6->setObjectName(QStringLiteral("label_6"));
+ label_6->setObjectName(QString::fromUtf8("label_6"));
gridLayout->addWidget(label_6, 11, 0, 1, 1);
filterCheckBox = new QCheckBox(WateringConfigDialog);
- filterCheckBox->setObjectName(QStringLiteral("filterCheckBox"));
+ filterCheckBox->setObjectName(QString::fromUtf8("filterCheckBox"));
gridLayout->addWidget(filterCheckBox, 11, 1, 1, 2);
@@ -206,18 +206,18 @@ public:
vboxLayout->addLayout(gridLayout);
gridLayout1 = new QGridLayout();
- gridLayout1->setObjectName(QStringLiteral("gridLayout1"));
+ gridLayout1->setObjectName(QString::fromUtf8("gridLayout1"));
spacerItem8 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
gridLayout1->addItem(spacerItem8, 0, 1, 1, 1);
helpBrowser = new HelpBrowser(WateringConfigDialog);
- helpBrowser->setObjectName(QStringLiteral("helpBrowser"));
+ helpBrowser->setObjectName(QString::fromUtf8("helpBrowser"));
gridLayout1->addWidget(helpBrowser, 1, 0, 1, 2);
helpLabel = new QLabel(WateringConfigDialog);
- helpLabel->setObjectName(QStringLiteral("helpLabel"));
+ helpLabel->setObjectName(QString::fromUtf8("helpLabel"));
gridLayout1->addWidget(helpLabel, 0, 0, 1, 1);
@@ -225,14 +225,14 @@ public:
vboxLayout->addLayout(gridLayout1);
line = new QFrame(WateringConfigDialog);
- line->setObjectName(QStringLiteral("line"));
+ line->setObjectName(QString::fromUtf8("line"));
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
vboxLayout->addWidget(line);
buttonBox = new QDialogButtonBox(WateringConfigDialog);
- buttonBox->setObjectName(QStringLiteral("buttonBox"));
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok);
diff --git a/tests/auto/widgets/dialogs/dialogs.pro b/tests/auto/widgets/dialogs/dialogs.pro
index cf548f2dea..e0ebe78f33 100644
--- a/tests/auto/widgets/dialogs/dialogs.pro
+++ b/tests/auto/widgets/dialogs/dialogs.pro
@@ -18,3 +18,4 @@ SUBDIRS=\
mac:qinputdialog.CONFIG += no_check_target # QTBUG-25496
mingw: SUBDIRS -= qfilesystemmodel # QTBUG-29403
+winrt: SUBDIRS -= qfiledialog qfiledialog2 qmessagebox # QTBUG-68297
diff --git a/tests/auto/widgets/dialogs/qcolordialog/qcolordialog.pro b/tests/auto/widgets/dialogs/qcolordialog/qcolordialog.pro
index c8ddedb401..563db6e887 100644
--- a/tests/auto/widgets/dialogs/qcolordialog/qcolordialog.pro
+++ b/tests/auto/widgets/dialogs/qcolordialog/qcolordialog.pro
@@ -2,5 +2,3 @@ CONFIG += testcase
TARGET = tst_qcolordialog
QT += widgets testlib
SOURCES += tst_qcolordialog.cpp
-
-linux*: CONFIG += insignificant_test # Crashes on different Linux distros
diff --git a/tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp b/tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp
index 0df0544a06..6a0ad4b3a4 100644
--- a/tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp
+++ b/tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp
@@ -84,6 +84,9 @@ void tst_QColorDialog::testNativeActiveModalWidget()
// Check that QApplication::activeModalWidget retruns the
// color dialog when it is executing, even when using a native
// dialog:
+#if defined(Q_OS_LINUX)
+ QSKIP("This test crashes sometimes. Although rarely, but it happens. See QTBUG-50842.");
+#endif
TestNativeDialog d;
QTimer::singleShot(1000, &d, SLOT(hide()));
d.exec();
@@ -121,6 +124,9 @@ void tst_QColorDialog::testGetRgba()
void tst_QColorDialog::defaultOkButton()
{
+#if defined(Q_OS_LINUX)
+ QSKIP("This test crashes sometimes. Although rarely, but it happens. See QTBUG-50842.");
+#endif
QTimer::singleShot(4000, qApp, SLOT(quit()));
QTimer::singleShot(0, this, SLOT(testGetRgba()));
qApp->exec();
diff --git a/tests/auto/widgets/dialogs/qdialog/BLACKLIST b/tests/auto/widgets/dialogs/qdialog/BLACKLIST
index 3da7337784..dd6a8bfff9 100644
--- a/tests/auto/widgets/dialogs/qdialog/BLACKLIST
+++ b/tests/auto/widgets/dialogs/qdialog/BLACKLIST
@@ -1,2 +1,4 @@
[snapToDefaultButton]
osx
+[showFullScreen]
+osx-10.13 ci
diff --git a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp
index 7e246b5366..afe49368ae 100644
--- a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp
+++ b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp
@@ -369,6 +369,10 @@ void tst_QDialog::showAsTool()
testWidget.activateWindow();
QVERIFY(QTest::qWaitForWindowActive(&testWidget));
dialog.exec();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "As winrt does not support child widgets, the dialog is being activated"
+ "together with the main widget.", Continue);
+#endif
if (testWidget.style()->styleHint(QStyle::SH_Widget_ShareActivation, 0, &testWidget)) {
QCOMPARE(dialog.wasActive(), true);
} else {
@@ -551,10 +555,11 @@ void tst_QDialog::snapToDefaultButton()
#ifdef QT_NO_CURSOR
QSKIP("Test relies on there being a cursor");
#else
- if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
- QSKIP("Wayland: Wayland does not support setting the cursor position.");
+ if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive)
+ || !QGuiApplication::platformName().compare(QLatin1String("winrt"), Qt::CaseInsensitive))
+ QSKIP("This platform does not support setting the cursor position.");
- const QRect dialogGeometry(QApplication::desktop()->availableGeometry().topLeft()
+ const QRect dialogGeometry(QGuiApplication::primaryScreen()->availableGeometry().topLeft()
+ QPoint(100, 100), QSize(200, 200));
const QPoint startingPos = dialogGeometry.bottomRight() + QPoint(100, 100);
QCursor::setPos(startingPos);
diff --git a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
index 47d63b7d53..ae8e4f7e04 100644
--- a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
+++ b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
@@ -49,6 +49,7 @@
#include <qsortfilterproxymodel.h>
#include <qlineedit.h>
#include <qlayout.h>
+#include <qtemporarydir.h>
#include <private/qfiledialog_p.h>
#if defined QT_BUILD_INTERNAL
#include <private/qsidebar_p.h>
@@ -933,7 +934,6 @@ void tst_QFiledialog::selectFiles()
QSignalSpy spyDirectoryEntered(&fd, SIGNAL(directoryEntered(QString)));
QSignalSpy spyFilesSelected(&fd, SIGNAL(filesSelected(QStringList)));
QSignalSpy spyFilterSelected(&fd, SIGNAL(filterSelected(QString)));
- fd.show();
fd.setFileMode(QFileDialog::ExistingFiles);
QString filesPath = fd.directory().absolutePath();
@@ -1311,57 +1311,116 @@ void tst_QFiledialog::saveButtonText()
QCOMPARE(button->text(), caption);
}
+// Predicate for use with QTRY_VERIFY() that checks whether the file dialog list
+// has been populated (contains an entry).
+class DirPopulatedPredicate
+{
+public:
+ explicit DirPopulatedPredicate(QListView *list, const QString &needle) :
+ m_list(list), m_needle(needle) {}
+
+ operator bool() const
+ {
+ const auto model = m_list->model();
+ const auto root = m_list->rootIndex();
+ for (int r = 0, count = model->rowCount(root); r < count; ++r) {
+ if (m_needle == model->index(r, 0, root).data(Qt::DisplayRole).toString())
+ return true;
+ }
+ return false;
+ }
+
+private:
+ QListView *m_list;
+ QString m_needle;
+};
+
+// A predicate for use with QTRY_VERIFY() that ensures an entry of the file dialog
+// list is selected by pressing cursor down.
+class SelectDirTestPredicate
+{
+public:
+ explicit SelectDirTestPredicate(QListView *list, const QString &needle) :
+ m_list(list), m_needle(needle) {}
+
+ operator bool() const
+ {
+ if (m_needle == m_list->currentIndex().data(Qt::DisplayRole).toString())
+ return true;
+ QCoreApplication::processEvents();
+ QTest::keyClick(m_list, Qt::Key_Down);
+ return false;
+ }
+
+private:
+ QListView *m_list;
+ QString m_needle;
+};
+
void tst_QFiledialog::clearLineEdit()
{
- QFileDialog fd(0, "caption", "foo");
+ // Play it really safe by creating a directory which should show first in
+ // a temporary dir
+ QTemporaryDir workDir(QDir::tempPath() + QLatin1String("/tst_qfd_clearXXXXXX"));
+ QVERIFY2(workDir.isValid(), qPrintable(workDir.errorString()));
+ const QString workDirPath = workDir.path();
+ const QString dirName = QLatin1String("aaaaa");
+ QVERIFY(QDir(workDirPath).mkdir(dirName));
+
+ QFileDialog fd(nullptr,
+ QLatin1String(QTest::currentTestFunction()) + QLatin1String(" AnyFile"),
+ "foo");
fd.setViewMode(QFileDialog::List);
fd.setFileMode(QFileDialog::AnyFile);
fd.show();
- //play it really safe by creating a directory
- QDir::home().mkdir("_____aaaaaaaaaaaaaaaaaaaaaa");
-
QLineEdit *lineEdit = fd.findChild<QLineEdit*>("fileNameEdit");
QVERIFY(lineEdit);
QCOMPARE(lineEdit->text(), QLatin1String("foo"));
- fd.setDirectory(QDir::home());
QListView* list = fd.findChild<QListView*>("listView");
QVERIFY(list);
- // saving a file the text shouldn't be cleared
- fd.setDirectory(QDir::home());
+ // When in AnyFile mode, lineEdit's text shouldn't be cleared when entering
+ // a directory by activating one in the list
+ fd.setDirectory(workDirPath);
+ DirPopulatedPredicate dirPopulated(list, dirName);
+ QTRY_VERIFY(dirPopulated);
#ifdef QT_KEYPAD_NAVIGATION
list->setEditFocus(true);
#endif
- QTest::keyClick(list, Qt::Key_Down);
+
+ SelectDirTestPredicate selectTestDir(list, dirName);
+ QTRY_VERIFY(selectTestDir);
+
#ifndef Q_OS_MAC
QTest::keyClick(list, Qt::Key_Return);
#else
QTest::keyClick(list, Qt::Key_O, Qt::ControlModifier);
#endif
- QTRY_VERIFY(fd.directory().absolutePath() != QDir::home().absolutePath());
+ QTRY_VERIFY(fd.directory().absolutePath() != workDirPath);
QVERIFY(!lineEdit->text().isEmpty());
- // selecting a dir the text should be cleared so one can just hit ok
+ // When in Directory mode, lineEdit's text should be cleared when entering
+ // a directory by activating one in the list so one can just hit ok
// and it selects that directory
fd.setFileMode(QFileDialog::Directory);
- fd.setDirectory(QDir::home());
+ fd.setWindowTitle(QLatin1String(QTest::currentTestFunction()) + QLatin1String(" Directory"));
+ fd.setDirectory(workDirPath);
+ QTRY_VERIFY(dirPopulated);
+
+ QTRY_VERIFY(selectTestDir);
- QTest::keyClick(list, Qt::Key_Down);
#ifndef Q_OS_MAC
QTest::keyClick(list, Qt::Key_Return);
#else
QTest::keyClick(list, Qt::Key_O, Qt::ControlModifier);
#endif
- QTRY_VERIFY(fd.directory().absolutePath() != QDir::home().absolutePath());
+ QTRY_VERIFY(fd.directory().absolutePath() != workDirPath);
QVERIFY(lineEdit->text().isEmpty());
-
- //remove the dir
- QDir::home().rmdir("_____aaaaaaaaaaaaaaaaaaaaaa");
}
void tst_QFiledialog::enableChooseButton()
@@ -1521,7 +1580,8 @@ public:
const QWindow *window = QGuiApplication::topLevelWindows().constFirst();
const QFileDialog *fileDialog = qobject_cast<QFileDialog*>(QApplication::activeModalWidget());
- QVERIFY(fileDialog);
+ if (!fileDialog)
+ return;
// The problem in QTBUG-57193 was from a platform input context plugin that was
// connected to QWindow::focusObjectChanged(), and consequently accessed the focus
diff --git a/tests/auto/widgets/dialogs/qfiledialog2/BLACKLIST b/tests/auto/widgets/dialogs/qfiledialog2/BLACKLIST
new file mode 100644
index 0000000000..e0887d8ad1
--- /dev/null
+++ b/tests/auto/widgets/dialogs/qfiledialog2/BLACKLIST
@@ -0,0 +1,2 @@
+[QTBUG4419_lineEditSelectAll]
+osx
diff --git a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp
index fca1f17a4d..8f9a8c11a7 100644
--- a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp
+++ b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp
@@ -1176,7 +1176,7 @@ void tst_QFileDialog2::QTBUG4419_lineEditSelectAll()
fd.setFileMode(QFileDialog::AnyFile);
fd.show();
- QApplication::setActiveWindow(&fd);
+ fd.activateWindow();
QVERIFY(QTest::qWaitForWindowActive(&fd));
QCOMPARE(fd.isVisible(), true);
QCOMPARE(QApplication::activeWindow(), static_cast<QWidget*>(&fd));
diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp
index d8a680881a..9ee5292fcb 100644
--- a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp
+++ b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp
@@ -51,10 +51,15 @@
// Will try to wait for the condition while allowing event processing
// for a maximum of 5 seconds.
-#define TRY_WAIT(expr) \
+#define TRY_WAIT(expr, timedOut) \
do { \
+ *timedOut = true; \
const int step = 50; \
- for (int __i = 0; __i < 5000 && !(expr); __i+=step) { \
+ for (int __i = 0; __i < 5000; __i += step) { \
+ if (expr) { \
+ *timedOut = false; \
+ break; \
+ } \
QTest::qWait(step); \
} \
} while(0)
@@ -123,6 +128,8 @@ private slots:
protected:
bool createFiles(const QString &test_path, const QStringList &initial_files, int existingFileCount = 0, const QStringList &intial_dirs = QStringList());
+ QModelIndex prepareTestModelRoot(const QString &test_path, QSignalSpy **spy2 = nullptr,
+ QSignalSpy **spy3 = nullptr);
private:
QFileSystemModel *model;
@@ -306,7 +313,11 @@ void tst_QFileSystemModel::iconProvider()
bool tst_QFileSystemModel::createFiles(const QString &test_path, const QStringList &initial_files, int existingFileCount, const QStringList &initial_dirs)
{
//qDebug() << (model->rowCount(model->index(test_path))) << existingFileCount << initial_files;
- TRY_WAIT((model->rowCount(model->index(test_path)) == existingFileCount));
+ bool timedOut = false;
+ TRY_WAIT((model->rowCount(model->index(test_path)) == existingFileCount), &timedOut);
+ if (timedOut)
+ return false;
+
for (int i = 0; i < initial_dirs.count(); ++i) {
QDir dir(test_path);
if (!dir.exists()) {
@@ -363,23 +374,45 @@ bool tst_QFileSystemModel::createFiles(const QString &test_path, const QStringLi
return true;
}
-void tst_QFileSystemModel::rowCount()
+QModelIndex tst_QFileSystemModel::prepareTestModelRoot(const QString &test_path, QSignalSpy **spy2,
+ QSignalSpy **spy3)
{
- QString tmp = flatDirTestPath;
- QVERIFY(createFiles(tmp, QStringList()));
+ if (model->rowCount(model->index(test_path)) != 0)
+ return QModelIndex();
- QSignalSpy spy2(model, SIGNAL(rowsInserted(QModelIndex,int,int)));
- QSignalSpy spy3(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)));
+ if (spy2)
+ *spy2 = new QSignalSpy(model, &QFileSystemModel::rowsInserted);
+ if (spy3)
+ *spy3 = new QSignalSpy(model, &QFileSystemModel::rowsAboutToBeInserted);
- QStringList files = QStringList() << "b" << "d" << "f" << "h" << "j" << ".a" << ".c" << ".e" << ".g";
+ QStringList files = { "b", "d", "f", "h", "j", ".a", ".c", ".e", ".g" };
QString l = "b,d,f,h,j,.a,.c,.e,.g";
- QVERIFY(createFiles(tmp, files));
+ if (!createFiles(test_path, files))
+ return QModelIndex();
- QModelIndex root = model->setRootPath(tmp);
- QTRY_COMPARE(model->rowCount(root), 5);
- QVERIFY(spy2.count() > 0);
- QVERIFY(spy3.count() > 0);
+ QModelIndex root = model->setRootPath(test_path);
+ if (!root.isValid())
+ return QModelIndex();
+
+ bool timedOut = false;
+ TRY_WAIT(model->rowCount(root) == 5, &timedOut);
+ if (timedOut)
+ return QModelIndex();
+
+ return root;
+}
+
+void tst_QFileSystemModel::rowCount()
+{
+ const QString tmp = flatDirTestPath;
+ QSignalSpy *spy2 = nullptr;
+ QSignalSpy *spy3 = nullptr;
+ QModelIndex root = prepareTestModelRoot(flatDirTestPath, &spy2, &spy3);
+ QVERIFY(root.isValid());
+
+ QVERIFY(spy2 && spy2->count() > 0);
+ QVERIFY(spy3 && spy3->count() > 0);
}
void tst_QFileSystemModel::rowsInserted_data()
@@ -401,9 +434,9 @@ static inline QString lastEntry(const QModelIndex &root)
void tst_QFileSystemModel::rowsInserted()
{
- QString tmp = flatDirTestPath;
- rowCount();
- QModelIndex root = model->index(model->rootPath());
+ const QString tmp = flatDirTestPath;
+ QModelIndex root = prepareTestModelRoot(tmp);
+ QVERIFY(root.isValid());
QFETCH(int, ascending);
QFETCH(int, count);
@@ -454,9 +487,9 @@ void tst_QFileSystemModel::rowsRemoved_data()
void tst_QFileSystemModel::rowsRemoved()
{
- QString tmp = flatDirTestPath;
- rowCount();
- QModelIndex root = model->index(model->rootPath());
+ const QString tmp = flatDirTestPath;
+ QModelIndex root = prepareTestModelRoot(tmp);
+ QVERIFY(root.isValid());
QFETCH(int, count);
QFETCH(int, ascending);
@@ -509,9 +542,9 @@ void tst_QFileSystemModel::dataChanged()
{
QSKIP("This can't be tested right now since we don't watch files, only directories.");
- QString tmp = flatDirTestPath;
- rowCount();
- QModelIndex root = model->index(model->rootPath());
+ const QString tmp = flatDirTestPath;
+ QModelIndex root = prepareTestModelRoot(tmp);
+ QVERIFY(root.isValid());
QFETCH(int, count);
QFETCH(int, assending);
diff --git a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
index 70f5c40bcc..049468fd7c 100644
--- a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
+++ b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
@@ -190,6 +190,8 @@ void tst_QMessageBox::sanityTest()
QSKIP("Test hangs on macOS 10.12 -- QTQAINFRA-1362");
return;
}
+#elif defined(Q_OS_WINRT)
+ QSKIP("Test hangs on winrt -- QTBUG-68297");
#endif
QMessageBox msgBox;
msgBox.setText("This is insane");
diff --git a/tests/auto/widgets/dialogs/qsidebar/tst_qsidebar.cpp b/tests/auto/widgets/dialogs/qsidebar/tst_qsidebar.cpp
index 3c189f92cc..9c5e226731 100644
--- a/tests/auto/widgets/dialogs/qsidebar/tst_qsidebar.cpp
+++ b/tests/auto/widgets/dialogs/qsidebar/tst_qsidebar.cpp
@@ -55,6 +55,9 @@ void tst_QSidebar::setUrls()
QCOMPARE(model->rowCount(), 0);
qsidebar.setUrls(urls);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "One of the URLs is not seen as valid on WinRT - QTBUG-68297", Abort);
+#endif
QCOMPARE(qsidebar.urls(), urls);
QCOMPARE(model->rowCount(), urls.count());
qsidebar.setUrls(urls);
@@ -99,6 +102,9 @@ void tst_QSidebar::addUrls()
// test < 0
qsidebar.addUrls(urls, -1);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "One of the URLs is not seen as valid on WinRT - QTBUG-68297", Abort);
+#endif
QCOMPARE(model->rowCount(), 2);
// test = 0
@@ -185,6 +191,9 @@ void tst_QSidebar::goToUrl()
QSignalSpy spy(&qsidebar, SIGNAL(goToUrl(QUrl)));
QTest::mousePress(qsidebar.viewport(), Qt::LeftButton, 0, qsidebar.visualRect(qsidebar.model()->index(0, 0)).center());
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Fails on WinRT - QTBUG-68297", Abort);
+#endif
QCOMPARE(spy.count(), 1);
QCOMPARE((spy.value(0)).at(0).toUrl(), urls.first());
}
diff --git a/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp b/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp
index 6ad93b2666..a5b8646d40 100644
--- a/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp
+++ b/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp
@@ -2596,6 +2596,9 @@ void tst_QWizard::task161658_alignments()
void tst_QWizard::task177022_setFixedSize()
{
+#ifdef Q_OS_WINRT
+ QSKIP("Widgets cannot have a fixed size on WinRT.");
+#endif
int width = 300;
int height = 200;
QWizard wiz;
diff --git a/tests/auto/widgets/effects/qgraphicseffect/BLACKLIST b/tests/auto/widgets/effects/qgraphicseffect/BLACKLIST
new file mode 100644
index 0000000000..4833af527f
--- /dev/null
+++ b/tests/auto/widgets/effects/qgraphicseffect/BLACKLIST
@@ -0,0 +1,3 @@
+[prepareGeometryChangeInvalidateCache]
+opensuse
+opensuse-leap
diff --git a/tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp b/tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp
index 5b142048b5..95662a49a0 100644
--- a/tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp
+++ b/tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp
@@ -731,12 +731,12 @@ void tst_QGraphicsEffect::itemHasNoContents()
CustomEffect *effect = new CustomEffect;
parent->setGraphicsEffect(effect);
- QTRY_COMPARE(effect->numRepaints, 1);
+ QTRY_VERIFY(effect->numRepaints >= 1);
for (int i = 0; i < 3; ++i) {
effect->reset();
effect->update();
- QTRY_COMPARE(effect->numRepaints, 1);
+ QTRY_VERIFY(effect->numRepaints >= 1);
}
}
diff --git a/tests/auto/widgets/graphicsview/graphicsview.pro b/tests/auto/widgets/graphicsview/graphicsview.pro
index e99897a4f6..0f4c1721e3 100644
--- a/tests/auto/widgets/graphicsview/graphicsview.pro
+++ b/tests/auto/widgets/graphicsview/graphicsview.pro
@@ -30,3 +30,5 @@ SUBDIRS=\
!contains(styles, fusion):SUBDIRS -= \
qgraphicsproxywidget \
qgraphicswidget \
+
+winrt: SUBDIRS -= qgraphicsview # QTBUG-68297
diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
index 6c1abaedb3..27eac03880 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -477,7 +477,7 @@ private:
void tst_QGraphicsItem::construction()
{
for (int i = 0; i < 7; ++i) {
- QGraphicsItem *item;
+ QGraphicsItem *item = nullptr;
switch (i) {
case 0:
item = new QGraphicsEllipseItem;
@@ -986,6 +986,7 @@ void tst_QGraphicsItem::inputMethodHints()
QGraphicsView view(&scene);
QApplication::setActiveWindow(&view);
view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
item->setFocus();
QTRY_VERIFY(item->hasFocus());
@@ -1036,6 +1037,7 @@ void tst_QGraphicsItem::toolTip()
view.setFixedSize(200, 200);
view.show();
QApplication::setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
{
QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().topLeft(),
@@ -2204,10 +2206,11 @@ void tst_QGraphicsItem::setMatrix()
QCOMPARE(spy.count(), 3);
QList<QRectF> rlist = qvariant_cast<QList<QRectF> >(spy.last().at(0));
- QCOMPARE(rlist.size(), 3);
- QCOMPARE(rlist.at(0), rotatedRect); // From item.setMatrix() (clearing rotated rect)
- QCOMPARE(rlist.at(1), rotatedRect); // From scene.update() (updating scene rect)
- QCOMPARE(rlist.at(2), unrotatedRect); // From post-update (update current state)
+ QCOMPARE(rlist.size(), 2);
+ // From item.setMatrix() (clearing rotated rect), from scene.update() (updating scene rect),
+ // squashed into one
+ QCOMPARE(rlist.at(0), rotatedRect);
+ QCOMPARE(rlist.at(1), unrotatedRect); // From post-update (update current state)
}
static QList<QGraphicsItem *> _paintedItems;
@@ -3226,6 +3229,7 @@ void tst_QGraphicsItem::hoverEventsGenerateRepaints()
QGraphicsScene scene;
QGraphicsView view(&scene);
view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
EventTester *tester = new EventTester;
@@ -4143,10 +4147,13 @@ void tst_QGraphicsItem::ensureVisible()
void tst_QGraphicsItem::cursor()
{
QGraphicsScene scene;
- QGraphicsRectItem *item1 = scene.addRect(QRectF(0, 0, 50, 50));
- QGraphicsRectItem *item2 = scene.addRect(QRectF(0, 0, 50, 50));
- item1->setPos(-100, 0);
- item2->setPos(50, 0);
+ QWidget topLevel;
+ QGraphicsView view(&scene,&topLevel);
+ topLevel.showMaximized();
+ QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
+ view.setFixedSize(topLevel.size());
+ QGraphicsRectItem *item1 = scene.addRect(QRectF(-100, 0, 50, 50));
+ QGraphicsRectItem *item2 = scene.addRect(QRectF(50, 0, 50, 50));
QVERIFY(!item1->hasCursor());
QVERIFY(!item2->hasCursor());
@@ -4172,14 +4179,6 @@ void tst_QGraphicsItem::cursor()
item1->setCursor(Qt::IBeamCursor);
item2->setCursor(Qt::PointingHandCursor);
- QWidget topLevel;
- topLevel.resize(250, 150);
- QTestPrivate::centerOnScreen(&topLevel);
- QGraphicsView view(&scene,&topLevel);
- view.setFixedSize(200, 100);
- topLevel.show();
- QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
-
QTest::mouseMove(&view, view.rect().center());
const Qt::CursorShape viewportShape = view.viewport()->cursor().shape();
@@ -4938,6 +4937,7 @@ void tst_QGraphicsItem::sceneEventFilter()
QGraphicsView view(&scene);
view.show();
QApplication::setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
QGraphicsTextItem *text1 = scene.addText(QLatin1String("Text1"));
@@ -5078,6 +5078,9 @@ void tst_QGraphicsItem::paint()
PaintTester tester2;
scene2.addItem(&tester2);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Fails on WinRT. Figure out why - QTBUG-68297", Abort);
+#endif
//First show one paint
QTRY_COMPARE(tester2.painted, 1);
@@ -6533,6 +6536,9 @@ void tst_QGraphicsItem::ensureUpdateOnTextItem()
QVERIFY(QTest::qWaitForWindowExposed(&view));
TextItem *text1 = new TextItem(QLatin1String("123"));
scene.addItem(text1);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Fails on WinRT. Figure out why - QTBUG-68297", Abort);
+#endif
QTRY_COMPARE(text1->updates,1);
//same bouding rect but we have to update
@@ -6802,6 +6808,7 @@ void tst_QGraphicsItem::opacity2()
MyGraphicsView view(&scene);
view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
QTRY_VERIFY(view.repaints >= 1);
@@ -6874,6 +6881,7 @@ void tst_QGraphicsItem::opacityZeroUpdates()
MyGraphicsView view(&scene);
view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
QTRY_VERIFY(view.repaints > 0);
@@ -6891,6 +6899,9 @@ void tst_QGraphicsItem::opacityZeroUpdates()
QRegion expectedRegion = parentDeviceBoundingRect.adjusted(-2, -2, 2, 2);
expectedRegion += childDeviceBoundingRect.adjusted(-2, -2, 2, 2);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Fails on WinRT. Figure out why - QTBUG-68297", Abort);
+#endif
COMPARE_REGIONS(view.paintedRegion, expectedRegion);
}
@@ -7262,6 +7273,7 @@ void tst_QGraphicsItem::cacheMode()
view.resize(150, 150);
view.show();
QApplication::setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
EventTester *tester = new EventTester;
@@ -7440,6 +7452,7 @@ void tst_QGraphicsItem::cacheMode2()
view.resize(150, 150);
view.show();
QApplication::setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
EventTester *tester = new EventTester;
@@ -8093,6 +8106,7 @@ void tst_QGraphicsItem::moveLineItem()
MyGraphicsView view(&scene);
view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
view.reset();
@@ -8108,6 +8122,9 @@ void tst_QGraphicsItem::moveLineItem()
// Make sure the calculated region is correct.
item->update();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Fails on WinRT. Figure out why - QTBUG-68297", Abort);
+#endif
QTRY_COMPARE(view.paintedRegion, expectedRegion);
view.reset();
@@ -8161,6 +8178,7 @@ void tst_QGraphicsItem::sorting()
view.setFrameStyle(0);
view.show();
qApp->setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
QTRY_VERIFY(_paintedItems.count() > 0);
@@ -8197,6 +8215,7 @@ void tst_QGraphicsItem::itemHasNoContents()
QGraphicsView view(&scene);
view.show();
qApp->setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
QTRY_VERIFY(!_paintedItems.isEmpty());
@@ -9204,6 +9223,7 @@ void tst_QGraphicsItem::ensureDirtySceneTransform()
QGraphicsView view(&scene);
view.show();
QApplication::setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
@@ -9590,6 +9610,7 @@ void tst_QGraphicsItem::QTBUG_4233_updateCachedWithSceneRect()
QGraphicsView view(&scene);
view.show();
QApplication::setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
QCOMPARE(QApplication::activeWindow(), (QWidget *)&view);
@@ -10720,6 +10741,7 @@ void tst_QGraphicsItem::scroll()
MyGraphicsView view(&scene);
view.setFrameStyle(0);
view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
QTRY_VERIFY(view.repaints > 0);
@@ -11242,6 +11264,7 @@ void tst_QGraphicsItem::QTBUG_6738_missingUpdateWithSetParent()
MyGraphicsView view(&scene);
view.show();
qApp->setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
QTRY_VERIFY(view.repaints > 0);
@@ -11290,6 +11313,7 @@ void tst_QGraphicsItem::QT_2653_fullUpdateDiscardingOpacityUpdate()
parentGreen->setFlag(QGraphicsItem::ItemIgnoresTransformations);
view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
view.reset();
@@ -11332,10 +11356,14 @@ void tst_QGraphicsItem::QTBUG_7714_fullUpdateDiscardingOpacityUpdate2()
origView.reset();
childYellow->setOpacity(0.0);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Fails on WinRT. Figure out why - QTBUG-68297", Abort);
+#endif
QTRY_COMPARE(origView.repaints, 1);
view.show();
qApp->setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
view.reset();
origView.reset();
@@ -11475,6 +11503,7 @@ void tst_QGraphicsItem::doNotMarkFullUpdateIfNotInScene()
item2->setParentItem(item);
scene.addItem(item);
view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(view.windowHandle()));
QVERIFY(QTest::qWaitForWindowActive(view.windowHandle()));
view.activateWindow();
QTRY_VERIFY(view.isActiveWindow());
@@ -11506,6 +11535,7 @@ void tst_QGraphicsItem::itemDiesDuringDraggingOperation()
scene.addItem(item);
view.show();
QApplication::setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
QCOMPARE(QApplication::activeWindow(), (QWidget *)&view);
QGraphicsSceneDragDropEvent dragEnter(QEvent::GraphicsSceneDragEnter);
@@ -11533,6 +11563,7 @@ void tst_QGraphicsItem::QTBUG_12112_focusItem()
view.show();
QApplication::setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
QCOMPARE(QApplication::activeWindow(), (QWidget *)&view);
diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/qgraphicsproxywidget.pro b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/qgraphicsproxywidget.pro
index e7bcccb495..c10cbe1b1a 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/qgraphicsproxywidget.pro
+++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/qgraphicsproxywidget.pro
@@ -4,5 +4,6 @@ TARGET = tst_qgraphicsproxywidget
QT += widgets widgets-private testlib
QT += core-private gui-private
+DEFINES += QTEST_QPA_MOUSE_HANDLING
SOURCES += tst_qgraphicsproxywidget.cpp
diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
index 4cd2fef2dc..49afc5f369 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
@@ -33,12 +33,6 @@
#include <private/qgraphicsproxywidget_p.h>
#include <private/qlayoutengine_p.h> // qSmartMin functions...
-static void sendMouseMove(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::NoButton)
-{
- QMouseEvent event(QEvent::MouseMove, point, widget->mapToGlobal(point), button, button, 0);
- QApplication::sendEvent(widget, &event);
-}
-
/*
Notes:
@@ -95,10 +89,8 @@ private slots:
void focusNextPrevChild();
void focusOutEvent_data();
void focusOutEvent();
-#ifndef QT_NO_CURSOR
void hoverEnterLeaveEvent_data();
void hoverEnterLeaveEvent();
-#endif
void hoverMoveEvent_data();
void hoverMoveEvent();
void keyPressEvent_data();
@@ -138,9 +130,7 @@ private slots:
void setFocus_complexTwoWidgets();
void popup_basic();
void popup_subwidget();
-#ifndef QT_NO_CURSOR
void changingCursor_basic();
-#endif
void tooltip_basic();
void childPos_data();
void childPos();
@@ -685,7 +675,6 @@ void tst_QGraphicsProxyWidget::focusInEvent()
SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
proxy->setEnabled(true);
scene.addItem(proxy);
- proxy->setVisible(true);
QWidget *widget = new QWidget;
widget->resize(100, 100);
@@ -716,7 +705,6 @@ void tst_QGraphicsProxyWidget::focusInEventNoWidget()
SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
proxy->setEnabled(true);
scene.addItem(proxy);
- proxy->setVisible(true);
view.show();
proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // <- shouldn't need to do this
@@ -931,7 +919,6 @@ protected:
}
};
-#ifndef QT_NO_CURSOR
void tst_QGraphicsProxyWidget::hoverEnterLeaveEvent_data()
{
QTest::addColumn<bool>("hasWidget");
@@ -952,8 +939,6 @@ void tst_QGraphicsProxyWidget::hoverEnterLeaveEvent()
QGraphicsScene scene;
QGraphicsView view(&scene);
- //do not let the window manager move the window while we are moving the mouse on it
- view.setWindowFlags(Qt::X11BypassWindowManagerHint);
view.show();
QApplication::setActiveWindow(&view);
QVERIFY(QTest::qWaitForWindowActive(&view));
@@ -968,31 +953,30 @@ void tst_QGraphicsProxyWidget::hoverEnterLeaveEvent()
if (hasWidget)
proxy->setWidget(widgetGuard.take());
proxy->setPos(50, 0);
+ QSignalSpy sceneChangedSpy(&scene, &QGraphicsScene::changed);
scene.addItem(proxy);
- QTest::qWait(30);
+ QTRY_VERIFY(sceneChangedSpy.count() > 0);
+
+ // outside graphics item
QTest::mouseMove(&view, QPoint(10, 10));
- QTest::qWait(30);
- // in
+ QCOMPARE(widget->testAttribute(Qt::WA_UnderMouse), false);
+ QCOMPARE(widget->enterCount, 0);
+ QCOMPARE(widget->hoverEnter, 0);
+ // over graphics item
QTest::mouseMove(&view, QPoint(50, 50));
- QSKIP("QTBUG-25294");
QTRY_COMPARE(widget->testAttribute(Qt::WA_UnderMouse), hasWidget);
- // ### this attribute isn't supported
QCOMPARE(widget->enterCount, hasWidget ? 1 : 0);
QCOMPARE(widget->hoverEnter, (hasWidget && hoverEnabled) ? 1 : 0);
- // does not work on all platforms
- //QCOMPARE(widget->moveCount, 0);
- // out
+ QTRY_COMPARE(widget->leaveCount, 0);
+ QTRY_COMPARE(widget->hoverLeave, 0);
+ // outside graphics item
QTest::mouseMove(&view, QPoint(10, 10));
- // QTRY_COMPARE(widget->testAttribute(Qt::WA_UnderMouse), false);
- // ### this attribute isn't supported
+ QTRY_COMPARE(widget->testAttribute(Qt::WA_UnderMouse), false);
QTRY_COMPARE(widget->leaveCount, hasWidget ? 1 : 0);
QTRY_COMPARE(widget->hoverLeave, (hasWidget && hoverEnabled) ? 1 : 0);
- // does not work on all platforms
- //QCOMPARE(widget->moveCount, 0);
}
-#endif
void tst_QGraphicsProxyWidget::hoverMoveEvent_data()
{
@@ -1174,19 +1158,20 @@ void tst_QGraphicsProxyWidget::mouseDoubleClickEvent()
widget->setText("foo");
widget->resize(50, 50);
view.resize(100, 100);
- if (hasWidget) {
+ if (hasWidget)
proxy->setWidget(widget);
- proxy->show();
- }
proxy->setPos(50, 0);
+ QSignalSpy sceneChangedSpy(&scene, &QGraphicsScene::changed);
scene.addItem(proxy);
proxy->setFocus();
- QTest::mouseMove(view.viewport(), view.mapFromScene(proxy->mapToScene(15, proxy->boundingRect().center().y())));
- QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(proxy->mapToScene(15, proxy->boundingRect().center().y())));
- QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(proxy->mapToScene(15, proxy->boundingRect().center().y())));
- QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(proxy->mapToScene(15, proxy->boundingRect().center().y())));
- QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(proxy->mapToScene(15, proxy->boundingRect().center().y())));
+ // wait for scene to be updated before doing any coordinate mappings on it
+ QTRY_VERIFY(sceneChangedSpy.count() > 0);
+
+ QPoint pointInLineEdit = view.mapFromScene(proxy->mapToScene(15, proxy->boundingRect().center().y()));
+ QTest::mousePress(view.viewport(), Qt::LeftButton, 0, pointInLineEdit);
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, pointInLineEdit);
+ QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, pointInLineEdit);
QTRY_COMPARE(widget->selectedText(), hasWidget ? QString("foo") : QString());
@@ -1217,19 +1202,20 @@ void tst_QGraphicsProxyWidget::mousePressReleaseEvent()
QPushButton *widget = new QPushButton;
QSignalSpy spy(widget, SIGNAL(clicked()));
widget->resize(50, 50);
- if (hasWidget) {
+ if (hasWidget)
proxy->setWidget(widget);
- proxy->show();
- }
proxy->setPos(50, 0);
+ QSignalSpy sceneChangedSpy(&scene, &QGraphicsScene::changed);
scene.addItem(proxy);
proxy->setFocus();
- QTest::mousePress(view.viewport(), Qt::LeftButton, 0,
- view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())));
+ // wait for scene to be updated before doing any coordinate mappings on it
+ QTRY_VERIFY(sceneChangedSpy.count() > 0);
+
+ QPoint buttonCenter = view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center()));
+ QTest::mousePress(view.viewport(), Qt::LeftButton, 0, buttonCenter);
QTRY_COMPARE(spy.count(), 0);
- QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0,
- view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())));
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, buttonCenter);
QTRY_COMPARE(spy.count(), (hasWidget) ? 1 : 0);
if (!hasWidget)
@@ -1282,16 +1268,13 @@ void tst_QGraphicsProxyWidget::paintEvent()
w->show();
QVERIFY(QTest::qWaitForWindowExposed(w));
- QApplication::processEvents();
- QTest::qWait(30);
proxy.setWidget(w);
+ QSignalSpy sceneChangedSpy(&scene, &QGraphicsScene::changed);
scene.addItem(&proxy);
- //make sure we flush all the paint events
- QTRY_VERIFY(proxy.paintCount > 1);
- QTest::qWait(30);
- proxy.paintCount = 0;
+ QTRY_VERIFY(sceneChangedSpy.count() > 0); // make sure the scene is ready
+ proxy.paintCount = 0;
w->update();
QTRY_VERIFY(proxy.paintCount >= 1); //the widget should have been painted now
}
@@ -2545,35 +2528,34 @@ void tst_QGraphicsProxyWidget::popup_subwidget()
QCOMPARE(popup->size(), child->size().toSize());
}
-#ifndef QT_NO_CURSOR
void tst_QGraphicsProxyWidget::changingCursor_basic()
{
+#if !QT_CONFIG(cursor)
+ QSKIP("This test requires the QCursor API");
+#else
// Confirm that mouse events are working properly by checking that
// when moving the mouse over a line edit it will change the cursor into the I
QGraphicsScene scene;
QGraphicsView view(&scene);
view.show();
+ QVERIFY(QTest::qWaitForWindowActive(&view));
SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
QLineEdit *widget = new QLineEdit;
proxy->setWidget(widget);
- proxy->show();
+ QSignalSpy sceneChangedSpy(&scene, &QGraphicsScene::changed);
scene.addItem(proxy);
- QApplication::setActiveWindow(&view);
- QVERIFY(QTest::qWaitForWindowActive(&view));
- QVERIFY(view.isActiveWindow());
+ QTRY_VERIFY(sceneChangedSpy.count() > 0); // make sure the scene is ready
// in
QTest::mouseMove(view.viewport(), view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())));
- sendMouseMove(view.viewport(), view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())));
QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
// out
QTest::mouseMove(view.viewport(), QPoint(1, 1));
- sendMouseMove(view.viewport(), QPoint(1, 1));
QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::ArrowCursor);
+#endif // !QT_CONFIG(cursor)
}
-#endif
static bool findViewAndTipLabel(const QWidget *view)
{
@@ -2972,7 +2954,7 @@ void tst_QGraphicsProxyWidget::dontCrashWhenDie()
MainWidget *w = new MainWidget();
w->show();
QVERIFY(QTest::qWaitForWindowExposed(w));
- QTest::qWait(100);
+
QTest::mouseMove(w->view->viewport(), w->view->mapFromScene(w->widget->mapToScene(w->widget->boundingRect().center())));
delete w->item;
@@ -3219,9 +3201,6 @@ void tst_QGraphicsProxyWidget::bypassGraphicsProxyWidget_data()
void tst_QGraphicsProxyWidget::bypassGraphicsProxyWidget()
{
-#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
- QSKIP("Test case unstable on this platform, QTBUG-33067");
-#endif
QFETCH(bool, bypass);
QWidget *widget = new QWidget;
@@ -3230,6 +3209,7 @@ void tst_QGraphicsProxyWidget::bypassGraphicsProxyWidget()
QGraphicsScene scene;
QGraphicsView view(&scene);
view.show();
+ QVERIFY(QTest::qWaitForWindowActive(&view));
QGraphicsProxyWidget *proxy = scene.addWidget(widget);
@@ -3243,6 +3223,7 @@ void tst_QGraphicsProxyWidget::bypassGraphicsProxyWidget()
QFileDialog *dialog = new QFileDialog(widget, flags);
dialog->setOption(QFileDialog::DontUseNativeDialog, true);
dialog->show();
+ QVERIFY(QTest::qWaitForWindowActive(dialog));
QCOMPARE(proxy->childItems().size(), bypass ? 0 : 1);
if (!bypass)
@@ -3637,25 +3618,21 @@ public:
QPushButton *hideButton = new QPushButton("I'm a button with a very very long text");
hideButton->setGeometry(10, 10, 400, 50);
topButton = addWidget(hideButton);
- connect(hideButton, SIGNAL(clicked()), this, SLOT(hideButton()));
+ connect(hideButton, &QPushButton::clicked, this, [&]() { topButton->hide(); });
topButton->setFocus();
}
QGraphicsProxyWidget *topButton;
HoverButton *hoverButton;
-
-public slots:
- void hideButton() {
- QCursor::setPos(600,600);
- topButton->hide();
- }
};
void tst_QGraphicsProxyWidget::QTBUG_6986_sendMouseEventToAlienWidget()
{
-#if defined(Q_OS_DARWIN) || defined(Q_OS_WIN) || defined(QT_NO_CURSOR)
- QSKIP("Test case unstable on this platform");
-#endif
+ if (QGuiApplication::platformName() == QLatin1String("cocoa")) {
+ // The "Second button" does not receive QEvent::HoverLeave
+ QSKIP("This test fails only on Cocoa. Investigate why. See QTBUG-69219");
+ }
+
QGraphicsView view;
Scene scene;
view.setScene(&scene);
@@ -3663,9 +3640,12 @@ void tst_QGraphicsProxyWidget::QTBUG_6986_sendMouseEventToAlienWidget()
QApplication::setActiveWindow(&view);
view.show();
QVERIFY(QTest::qWaitForWindowActive(&view));
- QCOMPARE(QApplication::activeWindow(), &view);
- QCursor::setPos(view.mapToGlobal(view.mapFromScene(scene.topButton->boundingRect().center())));
- QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(scene.topButton->scenePos()));
+
+ QPoint topButtonTopLeftCorner = view.mapFromScene(scene.topButton->scenePos());
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, topButtonTopLeftCorner);
+ // move to the bottom right corner (buttons are placed in the top left corner)
+ QCOMPARE(scene.hoverButton->hoverLeaveReceived, false);
+ QTest::mouseMove(view.viewport(), view.viewport()->rect().bottomRight());
QTRY_COMPARE(scene.hoverButton->hoverLeaveReceived, true);
}
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/BLACKLIST b/tests/auto/widgets/graphicsview/qgraphicsscene/BLACKLIST
index 70170d2822..0e7a1b451f 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsscene/BLACKLIST
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/BLACKLIST
@@ -3,3 +3,15 @@
osx-10.11 ci
[isActive]
opensuse-42.3 ci
+[removeFullyTransparentItem]
+osx-10.11
+osx-10.12
+[tabFocus_sceneWithNestedFocusWidgets]
+opensuse
+opensuse-leap
+[inputMethod]
+opensuse
+opensuse-leap
+[hoverEvents_parentChild]
+ubuntu
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp
index b256aab3e7..838b1f4be6 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp
@@ -254,6 +254,7 @@ private slots:
void zeroScale();
void focusItemChangedSignal();
void minimumRenderSize();
+ void focusOnTouch();
// task specific tests below me
void task139710_bspTreeCrash();
@@ -1275,10 +1276,10 @@ void tst_QGraphicsScene::removeItem()
view.show();
QApplication::setActiveWindow(&view);
QVERIFY(QTest::qWaitForWindowActive(&view));
- QTest::mouseMove(view.viewport(), view.mapFromScene(hoverItem->scenePos() + QPointF(20, 20)), Qt::NoButton);
+ QTest::mouseMove(view.windowHandle(), view.mapFromScene(hoverItem->scenePos() + QPointF(20, 20)));
QTRY_VERIFY(!hoverItem->isHovered);
- QTest::mouseMove(view.viewport(), view.mapFromScene(hoverItem->scenePos()), Qt::NoButton);
+ QTest::mouseMove(view.windowHandle(), view.mapFromScene(hoverItem->scenePos()));
QTRY_VERIFY(hoverItem->isHovered);
scene.removeItem(hoverItem);
@@ -2657,7 +2658,7 @@ void tst_QGraphicsScene::render()
void tst_QGraphicsScene::renderItemsWithNegativeWidthOrHeight()
{
-#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
+#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) || defined(Q_OS_WINRT)
QSKIP("Test only works on platforms with resizable windows");
#endif
@@ -4758,6 +4759,41 @@ void tst_QGraphicsScene::minimumRenderSize()
QVERIFY(smallChild->repaints > smallerGrandChild->repaints);
}
+void tst_QGraphicsScene::focusOnTouch()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ scene.setSceneRect(0, 0, 100, 100);
+ QGraphicsRectItem *rect = scene.addRect(0, 0, 100, 100);
+ rect->setFlag(QGraphicsItem::ItemIsFocusable, true);
+
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowActive(&view));
+
+ QVERIFY(!rect->hasFocus());
+
+ scene.setFocusOnTouch(false);
+
+ QTouchDevice device;
+ device.setType(QTouchDevice::TouchPad);
+ QList<QTouchEvent::TouchPoint> touchPoints;
+ QTouchEvent::TouchPoint point;
+ point.setScenePos(QPointF(10, 10));
+ point.setState(Qt::TouchPointPressed);
+ touchPoints.append(point);
+ QTouchEvent event(QEvent::TouchBegin, &device, Qt::NoModifier, Qt::TouchPointStates(),
+ touchPoints);
+
+ QApplication::sendEvent(&scene, &event);
+
+ QVERIFY(!rect->hasFocus());
+ scene.setFocusOnTouch(true);
+
+ QApplication::sendEvent(&scene, &event);
+ QVERIFY(rect->hasFocus());
+}
+
void tst_QGraphicsScene::taskQTBUG_15977_renderWithDeviceCoordinateCache()
{
QGraphicsScene scene;
diff --git a/tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp
index f3ac70ddb5..baccf7bff8 100644
--- a/tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp
@@ -355,6 +355,9 @@ void tst_QGraphicsSceneIndex::clear()
MyItem *item = new MyItem;
scene.addItem(item);
qApp->processEvents();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "There is one additional paint event on WinRT - QTBUG-68297", Abort);
+#endif
QTRY_COMPARE(item->numPaints, 1);
}
diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
index fe5b320492..3dc110298a 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
@@ -48,7 +48,6 @@
#include <QtWidgets/QBoxLayout>
#include <QtWidgets/QStyle>
#include <QtWidgets/QPushButton>
-#include <QtWidgets/QDesktopWidget>
#ifndef QT_NO_OPENGL
#include <QtWidgets/QOpenGLWidget>
#endif
@@ -262,11 +261,11 @@ private slots:
void QTBUG_4151_clipAndIgnore_data();
void QTBUG_4151_clipAndIgnore();
void QTBUG_5859_exposedRect();
+ void hoverLeave();
+ void QTBUG_16063_microFocusRect();
#ifndef QT_NO_CURSOR
void QTBUG_7438_cursor();
#endif
- void hoverLeave();
- void QTBUG_16063_microFocusRect();
public slots:
void dummySlot() {}
@@ -431,6 +430,7 @@ void tst_QGraphicsView::interactive()
QCOMPARE(item->events.size(), 0);
view.show();
view.activateWindow();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
QTRY_COMPARE(item->events.size(), 1); // activate
@@ -1646,6 +1646,7 @@ void tst_QGraphicsView::itemsInRect_cosmeticAdjust()
view.setFrameStyle(0);
view.resize(300, 300);
view.showNormal();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
QTRY_VERIFY(rect->numPaints > 0);
@@ -2140,6 +2141,7 @@ void tst_QGraphicsView::sendEvent()
QGraphicsView view(&scene);
view.show();
QApplication::setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
@@ -2207,6 +2209,7 @@ void tst_QGraphicsView::wheelEvent()
QGraphicsView view(&scene);
view.show();
QApplication::setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
@@ -2435,14 +2438,15 @@ void tst_QGraphicsView::viewportUpdateMode()
scene.setBackgroundBrush(Qt::red);
CustomView view;
- QDesktopWidget desktop;
- view.setFixedSize(QSize(500, 500).boundedTo(desktop.availableGeometry().size())); // 500 is too big for all common smartphones
+ QScreen *screen = QGuiApplication::primaryScreen();
+ view.setFixedSize(QSize(500, 500).boundedTo(screen->availableGeometry().size())); // 500 is too big for all common smartphones
view.setScene(&scene);
QCOMPARE(view.viewportUpdateMode(), QGraphicsView::MinimalViewportUpdate);
// Show the view, and initialize our test.
view.show();
qApp->setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
QTRY_VERIFY(!view.lastUpdateRegions.isEmpty());
view.lastUpdateRegions.clear();
@@ -2526,6 +2530,7 @@ void tst_QGraphicsView::viewportUpdateMode2()
view.resize(200 + left + right, 200 + top + bottom);
toplevel.show();
qApp->setActiveWindow(&toplevel);
+ QVERIFY(QTest::qWaitForWindowExposed(&toplevel));
QVERIFY(QTest::qWaitForWindowActive(&toplevel));
QTRY_VERIFY(view.painted);
const QRect viewportRect = view.viewport()->rect();
@@ -3170,6 +3175,7 @@ void tst_QGraphicsView::task172231_untransformableItems()
view.scale(2, 1);
view.show();
QApplication::setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
@@ -3969,6 +3975,7 @@ void tst_QGraphicsView::exposeRegion()
view.setScene(&scene);
view.show();
qApp->setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
QTRY_VERIFY(item->paints > 0);
@@ -4123,6 +4130,7 @@ void tst_QGraphicsView::update2()
view.resize(200, 200);
view.show();
qApp->setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
QTRY_VERIFY(rect->numPaints > 0);
@@ -4192,6 +4200,7 @@ void tst_QGraphicsView::update_ancestorClipsChildrenToShape()
CustomView view(&scene);
view.show();
qApp->setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
QTRY_VERIFY(view.painted);
@@ -4245,6 +4254,7 @@ void tst_QGraphicsView::update_ancestorClipsChildrenToShape2()
CustomView view(&scene);
view.show();
qApp->setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
QTRY_VERIFY(view.painted);
@@ -4305,6 +4315,7 @@ void tst_QGraphicsView::inputMethodSensitivity()
QGraphicsView view(&scene);
view.show();
QApplication::setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
@@ -4399,6 +4410,7 @@ void tst_QGraphicsView::inputContextReset()
view.show();
QApplication::setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
@@ -4546,6 +4558,7 @@ void tst_QGraphicsView::task255529_transformationAnchorMouseAndViewportMargins()
view.setWindowFlags(Qt::X11BypassWindowManagerHint);
view.show();
qApp->setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
// This is highly unstable (observed to pass on Windows and some Linux configurations).
#ifndef Q_OS_MAC
@@ -4673,6 +4686,7 @@ void tst_QGraphicsView::QTBUG_4151_clipAndIgnore()
view.resize(75, 75);
view.show();
view.activateWindow();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
QCOMPARE(QApplication::activeWindow(), (QWidget *)&view);
@@ -4710,6 +4724,7 @@ void tst_QGraphicsView::QTBUG_5859_exposedRect()
view.scale(4.15, 4.15);
view.showNormal();
qApp->setActiveWindow(&view);
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
view.viewport()->repaint(10,10,20,20);
@@ -4834,6 +4849,7 @@ void tst_QGraphicsView::QTBUG_16063_microFocusRect()
view.setFixedSize(40, 40);
view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
scene.setFocusItem(item);
diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
index 58a66f99b4..45c86800d6 100644
--- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
+++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
@@ -1217,6 +1217,9 @@ void tst_QAbstractItemView::task250754_fontChange()
font.setPixelSize(60);
tree.setFont(font);
+#ifdef Q_OS_WINRT
+ QSKIP("Resizing the widget does not work as expected for WinRT, so the scroll bar might not be visible");
+#endif
//now with the huge items, the scrollbar must be visible
QTRY_VERIFY(tree.verticalScrollBar()->isVisible());
@@ -1534,6 +1537,9 @@ void tst_QAbstractItemView::testClickedSignal()
QSignalSpy clickedSpy(&view, SIGNAL(clicked(QModelIndex)));
QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Fails on WinRT - QTBUG-68297", Abort);
+#endif
QCOMPARE(clickedSpy.count(), 1);
QTest::mouseClick(view.viewport(), Qt::RightButton, 0, p);
@@ -2257,6 +2263,9 @@ void tst_QAbstractItemView::QTBUG46785_mouseout_hover_state()
QTest::mouseMove(table.viewport(), QPoint(-50, 0));
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "QTest::mouseMove does not work on WinRT", Abort);
+#endif
QTRY_VERIFY(delegate.m_paintedWithoutHover);
}
diff --git a/tests/auto/widgets/itemviews/qcolumnview/tst_qcolumnview.cpp b/tests/auto/widgets/itemviews/qcolumnview/tst_qcolumnview.cpp
index 58b34e8aea..c58dbf599c 100644
--- a/tests/auto/widgets/itemviews/qcolumnview/tst_qcolumnview.cpp
+++ b/tests/auto/widgets/itemviews/qcolumnview/tst_qcolumnview.cpp
@@ -948,8 +948,10 @@ void tst_QColumnView::parentCurrentIndex()
QTRY_COMPARE(view.createdColumns[0]->currentIndex(), first);
QTRY_COMPARE(view.createdColumns[1]->currentIndex(), second);
+#ifndef Q_OS_WINRT
// The next two lines should be removed when QTBUG-22707 is resolved.
QEXPECT_FAIL("", "QTBUG-22707", Abort);
+#endif
QVERIFY(view.createdColumns[2]);
QTRY_COMPARE(view.createdColumns[2]->currentIndex(), third);
diff --git a/tests/auto/widgets/itemviews/qdirmodel/tst_qdirmodel.cpp b/tests/auto/widgets/itemviews/qdirmodel/tst_qdirmodel.cpp
index 48d39bbb11..d401154228 100644
--- a/tests/auto/widgets/itemviews/qdirmodel/tst_qdirmodel.cpp
+++ b/tests/auto/widgets/itemviews/qdirmodel/tst_qdirmodel.cpp
@@ -314,6 +314,9 @@ void tst_QDirModel::mkdir()
model.setReadOnly(false);
QModelIndex parent = model.index(SRCDIR "dirtest");
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Sandboxed applications cannot access SRCDIR - QTBUG-68297", Abort);
+#endif
QVERIFY(parent.isValid());
QCOMPARE(model.rowCount(parent), 1); // start out with only 'test1' - in's in the depot
@@ -351,6 +354,9 @@ void tst_QDirModel::rmdir()
model.setReadOnly(false);
QModelIndex parent = model.index(SRCDIR "/dirtest");
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Sandboxed applications cannot access SRCDIR - QTBUG-68297", Abort);
+#endif
QVERIFY(parent.isValid());
QCOMPARE(model.rowCount(parent), 1); // start out with only 'test1' - in's in the depot
@@ -460,6 +466,9 @@ bool tst_QDirModel::rowsAboutToBeRemoved_cleanup(const QString &test_path)
void tst_QDirModel::rowsAboutToBeRemoved()
{
+#ifdef Q_OS_WINRT
+ QSKIP("Test fails on WinRT - QTBUG-68297");
+#endif
QFETCH(QString, test_path);
QFETCH(QStringList, initial_files);
QFETCH(int, remove_row);
@@ -571,6 +580,9 @@ void tst_QDirModel::unreadable()
void tst_QDirModel::filePath()
{
QFile::remove(SRCDIR "test.lnk");
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Sandboxed applications cannot access SRCDIR - QTBUG-68297", Abort);
+#endif
QVERIFY(QFile(SRCDIR "tst_qdirmodel.cpp").link(SRCDIR "test.lnk"));
QDirModel model;
model.setResolveSymlinks(false);
@@ -629,6 +641,9 @@ void tst_QDirModel::filter()
QDirModel model;
model.setNameFilters(QStringList() << "*.nada");
QModelIndex index = model.index(SRCDIR "test");
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Sandboxed applications cannot access SRCDIR - QTBUG-68297", Abort);
+#endif
QCOMPARE(model.rowCount(index), 0);
QModelIndex index2 = model.index(SRCDIR "test/file01.tst");
QVERIFY(!index2.isValid());
@@ -638,6 +653,9 @@ void tst_QDirModel::filter()
void tst_QDirModel::task244669_remove()
{
QFile f1(SRCDIR "dirtest/f1.txt");
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Sandboxed applications cannot access SRCDIR - QTBUG-68297", Abort);
+#endif
QVERIFY(f1.open(QIODevice::WriteOnly));
f1.close();
QFile f2(SRCDIR "dirtest/f2.txt");
diff --git a/tests/auto/widgets/itemviews/qheaderview/BLACKLIST b/tests/auto/widgets/itemviews/qheaderview/BLACKLIST
new file mode 100644
index 0000000000..efb813f7d2
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qheaderview/BLACKLIST
@@ -0,0 +1,3 @@
+[stretchAndRestoreLastSection]
+opensuse
+opensuse-leap
diff --git a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
index 0dd98cf61c..b6932d4892 100644
--- a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
+++ b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
@@ -244,7 +244,9 @@ private slots:
void testMinMaxSectionSize_data();
void testMinMaxSectionSize();
void sizeHintCrash();
+ void testResetCachedSizeHint();
void statusTips();
+
protected:
void setupTestData(bool use_reset_model = false);
void additionalInit();
@@ -266,9 +268,9 @@ Q_OBJECT
public:
QtTestModel(QObject *parent = 0): QAbstractTableModel(parent),
- cols(0), rows(0), wrongIndex(false) {}
- int rowCount(const QModelIndex&) const { return rows; }
- int columnCount(const QModelIndex&) const { return cols; }
+ cols(0), rows(0), wrongIndex(false), m_bMultiLine(false) {}
+ int rowCount(const QModelIndex&) const override { return rows; }
+ int columnCount(const QModelIndex&) const override { return cols; }
bool isEditable(const QModelIndex &) const { return true; }
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const
{
@@ -280,11 +282,15 @@ public:
return QVariant();
if (orientation == Qt::Horizontal && col >= cols)
return QVariant();
+ if (m_bMultiLine)
+ return QString("%1\n%1").arg(section);
return QLatin1Char('[') + QString::number(row) + QLatin1Char(',')
+ QString::number(col) + QLatin1String(",0] -- Header");
}
- QVariant data(const QModelIndex &idx, int) const
+ QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const override
{
+ if (role != Qt::DisplayRole)
+ return QVariant();
if (idx.row() < 0 || idx.column() < 0 || idx.column() >= cols || idx.row() >= rows) {
wrongIndex = true;
qWarning("Invalid modelIndex [%d,%d,%p]", idx.row(), idx.column(), idx.internalPointer());
@@ -367,8 +373,16 @@ public:
emit layoutChanged();
}
+ void setMultiLineHeader(bool bEnable)
+ {
+ beginResetModel();
+ m_bMultiLine = bEnable;
+ endResetModel();
+ }
+
int cols, rows;
mutable bool wrongIndex;
+ bool m_bMultiLine;
};
// Testing get/set functions
@@ -391,6 +405,7 @@ void tst_QHeaderView::getSetCheck()
// int QHeaderView::defaultSectionSize()
// void QHeaderView::setDefaultSectionSize(int)
+ obj1.setMinimumSectionSize(0);
obj1.setDefaultSectionSize(-1);
QVERIFY(obj1.defaultSectionSize() >= 0);
obj1.setDefaultSectionSize(0);
@@ -657,6 +672,8 @@ void tst_QHeaderView::sectionSize()
{
#if defined Q_OS_QNX
QSKIP("The section size is dpi dependent on QNX");
+#elif defined Q_OS_WINRT
+ QSKIP("Fails on WinRT - QTBUG-68297");
#endif
QFETCH(QList<int>, boundsCheck);
QFETCH(QList<int>, defaultSizes);
@@ -761,6 +778,8 @@ void tst_QHeaderView::visualIndexAt()
{
#if defined Q_OS_QNX
QSKIP("The section size is dpi dependent on QNX");
+#elif defined Q_OS_WINRT
+ QSKIP("Fails on WinRT - QTBUG-68297");
#endif
QFETCH(QList<int>, hidden);
QFETCH(QList<int>, from);
@@ -830,11 +849,9 @@ void tst_QHeaderView::offset()
void tst_QHeaderView::sectionSizeHint()
{
- // Test bad arguments
- view->sectionSizeHint(-1);
- view->sectionSizeHint(99999);
-
- // TODO how to test the return value?
+ QCOMPARE(view->sectionSizeHint(-1), -1);
+ QCOMPARE(view->sectionSizeHint(99999), -1);
+ QVERIFY(view->sectionSizeHint(0) >= 0);
}
void tst_QHeaderView::logicalIndex()
@@ -2044,6 +2061,7 @@ void tst_QHeaderView::defaultSectionSize()
QHeaderView h((Qt::Orientation)direction);
h.setModel(&m);
+ h.setMinimumSectionSize(0);
QCOMPARE(h.defaultSectionSize(), oldDefaultSize);
h.setDefaultSectionSize(newDefaultSize);
@@ -2144,6 +2162,9 @@ void tst_QHeaderView::preserveHiddenSectionWidth()
void tst_QHeaderView::invisibleStretchLastSection()
{
+#ifdef Q_OS_WINRT
+ QSKIP("Fails on WinRT - QTBUG-68297");
+#endif
int count = 6;
QStandardItemModel model(1, count);
QHeaderView view(Qt::Horizontal);
@@ -2281,6 +2302,7 @@ void tst_QHeaderView::QTBUG6058_reset()
QHeaderView view(Qt::Vertical);
view.setModel(&proxy);
view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
QVERIFY(QTest::qWaitForWindowActive(&view));
proxy.setSourceModel(&model1);
@@ -3306,8 +3328,16 @@ void tst_QHeaderView::testMinMaxSectionSize()
QHeaderView &header = *tv.horizontalHeader();
header.setMinimumSectionSize(sectionSizeMin);
header.setMaximumSectionSize(sectionSizeMax);
+ // check bounds for default section size
+ header.setDefaultSectionSize(sectionSizeMin - 1);
+ QCOMPARE(header.defaultSectionSize(), sectionSizeMin);
+ header.setDefaultSectionSize(sectionSizeMax + 1);
+ QCOMPARE(header.defaultSectionSize(), sectionSizeMax);
+
header.setDefaultSectionSize(defaultSectionSize);
+ QCOMPARE(header.defaultSectionSize(), defaultSectionSize);
header.setStretchLastSection(stretchLastSection);
+ QCOMPARE(header.stretchLastSection(), stretchLastSection);
// check defaults
QCOMPARE(header.sectionSize(0), defaultSectionSize);
@@ -3338,6 +3368,26 @@ void tst_QHeaderView::testMinMaxSectionSize()
QTRY_COMPARE(header.sectionSize(0), defaultSectionSize);
}
+void tst_QHeaderView::testResetCachedSizeHint()
+{
+ QtTestModel model;
+ model.rows = model.cols = 10;
+
+ QTableView tv;
+ tv.setModel(&model);
+ tv.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&tv));
+
+ QSize s1 = tv.horizontalHeader()->sizeHint();
+ model.setMultiLineHeader(true);
+ QSize s2 = tv.horizontalHeader()->sizeHint();
+ model.setMultiLineHeader(false);
+ QSize s3 = tv.horizontalHeader()->sizeHint();
+ QCOMPARE(s1, s3);
+ QVERIFY(s1 != s2);
+}
+
+
class StatusTipHeaderView : public QHeaderView
{
public:
@@ -3372,7 +3422,7 @@ void tst_QHeaderView::statusTips()
// Ensure it is moved away first and then moved to the relevant section
QTest::mouseMove(QApplication::desktop(),
headerView.rect().bottomLeft() + QPoint(20, 20));
- QPoint centerPoint = QRect(headerView.sectionPosition(0), headerView.y(),
+ QPoint centerPoint = QRect(headerView.sectionPosition(0), 0,
headerView.sectionSize(0), headerView.height()).center();
QTest::mouseMove(headerView.windowHandle(), centerPoint);
QTRY_VERIFY(headerView.gotStatusTipEvent);
@@ -3380,7 +3430,7 @@ void tst_QHeaderView::statusTips()
headerView.gotStatusTipEvent = false;
headerView.statusTipText.clear();
- centerPoint = QRect(headerView.sectionPosition(1), headerView.y(),
+ centerPoint = QRect(headerView.sectionPosition(1), 0,
headerView.sectionSize(1), headerView.height()).center();
QTest::mouseMove(headerView.windowHandle(), centerPoint);
QTRY_VERIFY(headerView.gotStatusTipEvent);
diff --git a/tests/auto/widgets/itemviews/qitemdelegate/BLACKLIST b/tests/auto/widgets/itemviews/qitemdelegate/BLACKLIST
index 0f7c377194..c6aeebc8f8 100644
--- a/tests/auto/widgets/itemviews/qitemdelegate/BLACKLIST
+++ b/tests/auto/widgets/itemviews/qitemdelegate/BLACKLIST
@@ -5,3 +5,4 @@ opensuse-42.3 ci
[comboBox]
# QTBUG-67282
opensuse
+opensuse-leap
diff --git a/tests/auto/widgets/itemviews/qitemview/BLACKLIST b/tests/auto/widgets/itemviews/qitemview/BLACKLIST
new file mode 100644
index 0000000000..d5fc89f204
--- /dev/null
+++ b/tests/auto/widgets/itemviews/qitemview/BLACKLIST
@@ -0,0 +1,2 @@
+[scrollTo]
+winrt
diff --git a/tests/auto/widgets/itemviews/qitemview/tst_qitemview.cpp b/tests/auto/widgets/itemviews/qitemview/tst_qitemview.cpp
index afd6d84486..bbdaac5c6f 100644
--- a/tests/auto/widgets/itemviews/qitemview/tst_qitemview.cpp
+++ b/tests/auto/widgets/itemviews/qitemview/tst_qitemview.cpp
@@ -546,23 +546,26 @@ void tst_QItemView::walkScreen(QAbstractItemView *view)
}
}
-void walkIndex(QModelIndex index, QAbstractItemView *view)
+void walkIndex(const QModelIndex &index, const QAbstractItemView *view)
{
- QRect visualRect = view->visualRect(index);
- //if (index.column() == 0)
- //qDebug() << index << visualRect;
- int width = visualRect.width();
- int height = visualRect.height();
+ const QRect visualRect = view->visualRect(index);
+ const int width = visualRect.width();
+ const int height = visualRect.height();
- for (int w = 0; w < width; ++w)
+ if (width == 0 || height == 0)
+ return;
+
+ const auto widths = (width < 2) ? QVector<int>({ 0, 1 }) : QVector<int>({ 0, 1, width / 2, width - 2, width - 1 });
+ const auto heights = (height < 2) ? QVector<int>({ 0, 1 }) : QVector<int>({ 0, 1, height / 2, height - 2, height - 1 });
+ for (int w : widths)
{
- for (int h = 0; h < height; ++h)
+ for (int h : heights)
{
- QPoint point(visualRect.x()+w, visualRect.y()+h);
- if (view->indexAt(point) != index) {
+ const QPoint point(visualRect.x() + w, visualRect.y() + h);
+ const auto idxAt = view->indexAt(point);
+ if (idxAt != index)
qDebug() << "index" << index << "visualRect" << visualRect << point << view->indexAt(point);
- }
- QCOMPARE(view->indexAt(point), index);
+ QCOMPARE(idxAt, index);
}
}
@@ -579,7 +582,7 @@ void walkIndex(QModelIndex index, QAbstractItemView *view)
a bug it will point it out, but the above tests should have already found the basic bugs
because it is easier to figure out the problem in those tests then this one.
*/
-void checkChildren(QAbstractItemView *currentView, const QModelIndex &parent = QModelIndex(), int currentDepth=0)
+void checkChildren(const QAbstractItemView *currentView, const QModelIndex &parent = QModelIndex(), int currentDepth = 0)
{
QAbstractItemModel *currentModel = currentView->model();
@@ -623,7 +626,6 @@ void tst_QItemView::indexAt()
view->setHorizontalScrollMode((QAbstractItemView::ScrollMode)hscroll);
view->show();
view->setModel(treeModel);
-#if 0
checkChildren(view);
QModelIndex index = view->model()->index(0, 0);
@@ -636,7 +638,6 @@ void tst_QItemView::indexAt()
QPoint p(1, view->height()/2);
QModelIndex idx = view->indexAt(p);
QCOMPARE(idx, QModelIndex());
-#endif
}
void tst_QItemView::scrollTo_data()
diff --git a/tests/auto/widgets/itemviews/qlistview/qlistview.pro b/tests/auto/widgets/itemviews/qlistview/qlistview.pro
index e49a0c5fbf..75f45ab432 100644
--- a/tests/auto/widgets/itemviews/qlistview/qlistview.pro
+++ b/tests/auto/widgets/itemviews/qlistview/qlistview.pro
@@ -3,4 +3,3 @@ TARGET = tst_qlistview
QT += widgets gui-private widgets-private core-private testlib testlib-private
SOURCES += tst_qlistview.cpp
win32:!winrt: LIBS += -luser32
-linux*: CONFIG += insignificant_test # Crashes
diff --git a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
index d0c9dae313..5227db64ec 100644
--- a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
+++ b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp
@@ -149,6 +149,8 @@ private slots:
void taskQTBUG_7232_AllowUserToControlSingleStep();
void taskQTBUG_51086_skippingIndexesInSelectedIndexes();
void taskQTBUG_47694_indexOutOfBoundBatchLayout();
+ void itemAlignment();
+ void internalDragDropMove();
};
// Testing get/set functions
@@ -1462,6 +1464,9 @@ void tst_QListView::wordWrap()
QApplication::processEvents();
QTRY_COMPARE(lv.horizontalScrollBar()->isVisible(), false);
+#ifdef Q_OS_WINRT
+QSKIP("setFixedSize does not work on WinRT. Vertical scroll bar will not be visible.");
+#endif
QTRY_COMPARE(lv.verticalScrollBar()->isVisible(), true);
}
@@ -2083,6 +2088,9 @@ void tst_QListView::taskQTBUG_21115_scrollToAndHiddenItems_data()
void tst_QListView::taskQTBUG_21115_scrollToAndHiddenItems()
{
QFETCH(int, flow);
+#ifdef Q_OS_WINRT
+ QSKIP("Fails on WinRT - QTBUG-68297");
+#endif
ScrollPerItemListView lv;
lv.setUniformItemSizes(true);
@@ -2293,6 +2301,9 @@ void tst_QListView::testScrollToWithHidden()
lv.scrollTo(model.index(26, 0));
int expectedScrollBarValue = lv.verticalScrollBar()->value();
+#ifdef Q_OS_WINRT
+ QSKIP("Might fail on WinRT - QTBUG-68297");
+#endif
QVERIFY(expectedScrollBarValue != 0);
lv.scrollTo(model.index(25, 0));
@@ -2419,6 +2430,7 @@ void tst_QListView::taskQTBUG_39902_mutualScrollBars()
void tst_QListView::horizontalScrollingByVerticalWheelEvents()
{
+#if QT_CONFIG(wheelevent)
QListView lv;
lv.setWrapping(true);
@@ -2460,6 +2472,9 @@ void tst_QListView::horizontalScrollingByVerticalWheelEvents()
int vValue = lv.verticalScrollBar()->value();
QApplication::sendEvent(lv.viewport(), &wheelDownEvent);
QVERIFY(lv.verticalScrollBar()->value() > vValue);
+#else
+ QSKIP("Built with --no-feature-wheelevent");
+#endif
}
void tst_QListView::taskQTBUG_7232_AllowUserToControlSingleStep()
@@ -2540,5 +2555,76 @@ void tst_QListView::taskQTBUG_47694_indexOutOfBoundBatchLayout()
view.scrollTo(model.index(batchSize - 1, 0));
}
+void tst_QListView::itemAlignment()
+{
+ auto item1 = new QStandardItem("111");
+ auto item2 = new QStandardItem("111111");
+ QStandardItemModel model;
+ model.appendRow(item1);
+ model.appendRow(item2);
+
+ QListView w;
+ w.setModel(&model);
+ w.setWrapping(true);
+ w.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&w));
+
+ QVERIFY(w.visualRect(item1->index()).width() > 0);
+ QVERIFY(w.visualRect(item1->index()).width() == w.visualRect(item2->index()).width());
+
+ w.setItemAlignment(Qt::AlignLeft);
+ QApplication::processEvents();
+
+ QVERIFY(w.visualRect(item1->index()).width() < w.visualRect(item2->index()).width());
+}
+
+void tst_QListView::internalDragDropMove()
+{
+ const QString platform(QGuiApplication::platformName().toLower());
+ if (platform != QLatin1String("xcb"))
+ QSKIP("Need a window system with proper DnD support via injected mouse events");
+
+ // on an internal move, the item was deleted which should not happen
+ // see QTBUG-67440
+ class QListViewWithPublicStartDrag : public QListView
+ {
+ public:
+ using QListView::startDrag;
+ };
+
+ QStandardItemModel data(0, 1);
+ QPixmap pixmap(32, 32);
+ for (int i = 0; i < 10; ++i) {
+ pixmap.fill(Qt::GlobalColor(i + 1));
+ data.appendRow(new QStandardItem(QIcon(pixmap), QString::number(i)));
+ }
+ QItemSelectionModel selections(&data);
+ QListViewWithPublicStartDrag list;
+ list.setWindowTitle(QTest::currentTestFunction());
+ list.setViewMode(QListView::IconMode);
+ list.setDefaultDropAction(Qt::MoveAction);
+ list.setModel(&data);
+ list.setSelectionModel(&selections);
+ list.resize(300, 300);
+ list.show();
+ selections.select(data.index(1, 0), QItemSelectionModel::Select);
+ QVERIFY(QTest::qWaitForWindowExposed(&list));
+
+ // execute as soon as the eventloop is running again
+ // which is the case inside list.startDrag()
+ QTimer::singleShot(0, [&list]()
+ {
+ const QPoint pos = list.rect().center();
+ QMouseEvent mouseMove(QEvent::MouseMove, pos, list.mapToGlobal(pos), Qt::NoButton, 0, 0);
+ QApplication::sendEvent(&list, &mouseMove);
+ QMouseEvent mouseRelease(QEvent::MouseButtonRelease, pos, list.mapToGlobal(pos), Qt::LeftButton, 0, 0);
+ QApplication::sendEvent(&list, &mouseRelease);
+ });
+ const int expectedCount = data.rowCount();
+ list.startDrag(Qt::MoveAction|Qt::CopyAction);
+ QCOMPARE(expectedCount, data.rowCount());
+}
+
+
QTEST_MAIN(tst_QListView)
#include "tst_qlistview.moc"
diff --git a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
index 8427b04be7..ab746dfee8 100644
--- a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
+++ b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp
@@ -1353,6 +1353,11 @@ void tst_QTableView::moveCursorBiggerJump()
QCOMPARE(view.indexAt(QPoint(0,0)), model.index(7,0));
QTest::keyClick(&view, Qt::Key_PageUp);
QCOMPARE(view.indexAt(QPoint(0,0)), model.index(0,0));
+
+ QTest::keyClick(&view, Qt::Key_PageDown);
+ view.verticalHeader()->hideSection(0);
+ QTest::keyClick(&view, Qt::Key_PageUp);
+ QTRY_COMPARE(view.currentIndex().row(), view.rowAt(0));
}
void tst_QTableView::hideRows_data()
@@ -2329,6 +2334,14 @@ void tst_QTableView::rowViewportPosition()
view.setVerticalScrollMode((QAbstractItemView::ScrollMode)verticalScrollMode);
view.verticalScrollBar()->setValue(verticalScrollValue);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("row 1, scroll per item, 1", "Fails on WinRT - QTBUG-68297", Abort);
+ QEXPECT_FAIL("row 5, scroll per item, 5", "Fails on WinRT - QTBUG-68297", Abort);
+ QEXPECT_FAIL("row 9, scroll per item, 5", "Fails on WinRT - QTBUG-68297", Abort);
+ QEXPECT_FAIL("row 1, scroll per pixel, 1", "Fails on WinRT - QTBUG-68297", Abort);
+ QEXPECT_FAIL("row 5, scroll per pixel, 5", "Fails on WinRT - QTBUG-68297", Abort);
+ QEXPECT_FAIL("row 9, scroll per pixel, 5", "Fails on WinRT - QTBUG-68297", Abort);
+#endif
QCOMPARE(view.rowViewportPosition(row), rowViewportPosition);
}
@@ -2492,6 +2505,14 @@ void tst_QTableView::columnViewportPosition()
view.setHorizontalScrollMode((QAbstractItemView::ScrollMode)horizontalScrollMode);
view.horizontalScrollBar()->setValue(horizontalScrollValue);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("column 1, scroll per item, 1", "Fails on WinRT - QTBUG-68297", Abort);
+ QEXPECT_FAIL("column 5, scroll per item, 5", "Fails on WinRT - QTBUG-68297", Abort);
+ QEXPECT_FAIL("column 9, scroll per item, 5", "Fails on WinRT - QTBUG-68297", Abort);
+ QEXPECT_FAIL("column 1, scroll per pixel 1", "Fails on WinRT - QTBUG-68297", Abort);
+ QEXPECT_FAIL("column 5, scroll per pixel 5", "Fails on WinRT - QTBUG-68297", Abort);
+ QEXPECT_FAIL("column 9, scroll per pixel 5", "Fails on WinRT - QTBUG-68297", Abort);
+#endif
QCOMPARE(view.columnViewportPosition(column), columnViewportPosition);
}
diff --git a/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp b/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp
index 4d4a95b3f5..4155ff1ec6 100644
--- a/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp
+++ b/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp
@@ -32,6 +32,7 @@
#include <qlist.h>
#include <qpair.h>
#include <qheaderview.h>
+#include <qlineedit.h>
#include <qtablewidget.h>
@@ -81,6 +82,7 @@ private slots:
void itemData();
void setItemData();
void cellWidget();
+ void cellWidgetGeometry();
void task231094();
void task219380_removeLastRow();
void task262056_sortDuplicate();
@@ -360,11 +362,18 @@ void tst_QTableWidget::takeItem()
for (int c = 0; c < testWidget->columnCount(); ++c)
QCOMPARE(testWidget->item(r, c)->text(), QString::number(r * c + c));
+ QSignalSpy spy(testWidget, &QTableWidget::cellChanged);
QTableWidgetItem *item = testWidget->takeItem(row, column);
QCOMPARE(!!item, expectItem);
if (expectItem) {
QCOMPARE(item->text(), QString::number(row * column + column));
delete item;
+
+ QTRY_COMPARE(spy.count(), 1);
+ const QList<QVariant> arguments = spy.takeFirst();
+ QCOMPARE(arguments.size(), 2);
+ QCOMPARE(arguments.at(0).toInt(), row);
+ QCOMPARE(arguments.at(1).toInt(), column);
}
QVERIFY(!testWidget->takeItem(row, column));
}
@@ -1343,27 +1352,45 @@ void tst_QTableWidget::setItemWithSorting()
}
}
+class QTableWidgetDataChanged : public QTableWidget
+{
+ Q_OBJECT
+public:
+ using QTableWidget::QTableWidget;
+
+ void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) override
+ {
+ QTableWidget::dataChanged(topLeft, bottomRight, roles);
+ currentRoles = roles;
+ }
+ QVector<int> currentRoles;
+};
+
void tst_QTableWidget::itemData()
{
- QTableWidget widget(2, 2);
+ QTableWidgetDataChanged widget(2, 2);
widget.setItem(0, 0, new QTableWidgetItem());
QTableWidgetItem *item = widget.item(0, 0);
QVERIFY(item);
item->setFlags(item->flags() | Qt::ItemIsEditable);
item->setData(Qt::DisplayRole, QString("0"));
+ QCOMPARE(widget.currentRoles, QVector<int>({Qt::DisplayRole, Qt::EditRole}));
item->setData(Qt::CheckStateRole, Qt::PartiallyChecked);
- item->setData(Qt::UserRole + 0, QString("1"));
- item->setData(Qt::UserRole + 1, QString("2"));
- item->setData(Qt::UserRole + 2, QString("3"));
- item->setData(Qt::UserRole + 3, QString("4"));
+ QCOMPARE(widget.currentRoles, {Qt::CheckStateRole});
+ for (int i = 0; i < 4; ++i)
+ {
+ item->setData(Qt::UserRole + i, QString::number(i + 1));
+ QCOMPARE(widget.currentRoles, {Qt::UserRole + i});
+ }
QMap<int, QVariant> flags = widget.model()->itemData(widget.model()->index(0, 0));
QCOMPARE(flags.count(), 6);
- QCOMPARE(flags[(Qt::UserRole + 0)].toString(), QString("1"));
+ for (int i = 0; i < 4; ++i)
+ QCOMPARE(flags[Qt::UserRole + i].toString(), QString::number(i + 1));
}
void tst_QTableWidget::setItemData()
{
- QTableWidget table(10, 10);
+ QTableWidgetDataChanged table(10, 10);
table.setSortingEnabled(false);
QSignalSpy dataChangedSpy(table.model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)));
@@ -1376,6 +1403,7 @@ void tst_QTableWidget::setItemData()
data.insert(Qt::DisplayRole, QLatin1String("Display"));
data.insert(Qt::ToolTipRole, QLatin1String("ToolTip"));
table.model()->setItemData(idx, data);
+ QCOMPARE(table.currentRoles, QVector<int>({Qt::DisplayRole, Qt::EditRole, Qt::ToolTipRole}));
QCOMPARE(table.model()->data(idx, Qt::DisplayRole).toString(), QLatin1String("Display"));
QCOMPARE(table.model()->data(idx, Qt::ToolTipRole).toString(), QLatin1String("ToolTip"));
@@ -1404,6 +1432,28 @@ void tst_QTableWidget::cellWidget()
QCOMPARE(table.cellWidget(5, 5), static_cast<QWidget*>(0));
}
+void tst_QTableWidget::cellWidgetGeometry()
+{
+ QTableWidget tw(3,2);
+ tw.show();
+ // make sure the next row added is not completely visibile
+ tw.resize(300, tw.rowHeight(0) * 3 + tw.rowHeight(0) / 2);
+ QVERIFY(QTest::qWaitForWindowExposed(&tw));
+
+ tw.scrollToBottom();
+ tw.setRowCount(tw.rowCount() + 1);
+ auto item = new QTableWidgetItem("Hello");
+ tw.setItem(0,0,item);
+ auto le = new QLineEdit("world");
+ tw.setCellWidget(0,1,le);
+ // process delayedPendingLayout triggered by setting the row count
+ tw.doItemsLayout();
+ // so y pos is 0 for the first row
+ tw.scrollToTop();
+ // check if updateEditorGeometries has set the correct y pos for the editors
+ QCOMPARE(tw.visualItemRect(item).top(), le->geometry().top());
+}
+
void tst_QTableWidget::task231094()
{
QTableWidget tw(5, 3);
diff --git a/tests/auto/widgets/itemviews/qtreeview/BLACKLIST b/tests/auto/widgets/itemviews/qtreeview/BLACKLIST
deleted file mode 100644
index 5eb80007c4..0000000000
--- a/tests/auto/widgets/itemviews/qtreeview/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[setSortingEnabledChild]
-windows
diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
index 34cdcd5bf7..8f9afeea4d 100644
--- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
+++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
@@ -839,6 +839,9 @@ void tst_QTreeView::horizontalScrollMode()
QCOMPARE(view.horizontalScrollMode(), QAbstractItemView::ScrollPerPixel);
QCOMPARE(view.horizontalScrollBar()->minimum(), 0);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "setFixedSize does not work on WinRT - QTBUG-68297", Abort);
+#endif
QVERIFY(view.horizontalScrollBar()->maximum() > 2);
view.setHorizontalScrollMode(QAbstractItemView::ScrollPerItem);
@@ -1975,6 +1978,10 @@ void tst_QTreeView::setSelection()
QVERIFY(selectionModel);
QModelIndexList selectedIndexes = selectionModel->selectedIndexes();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("(0,-20,20,50),rows", "Fails on WinRT - QTBUG-68297", Abort);
+ QEXPECT_FAIL("(0,-50,20,90),rows", "Fails on WinRT - QTBUG-68297", Abort);
+#endif
QCOMPARE(selectedIndexes.count(), expectedItems.count());
for (int i = 0; i < selectedIndexes.count(); ++i) {
QModelIndex idx = selectedIndexes.at(i);
@@ -2600,8 +2607,10 @@ void tst_QTreeView::setSortingEnabledChild()
{
QMainWindow win;
QTreeView view;
- QStandardItemModel model(1,1);
+ // two columns to not get in trouble with stretchLastSection
+ QStandardItemModel model(1,2);
view.setModel(&model);
+ view.header()->setDefaultSectionSize(92);
win.setCentralWidget(&view);
const int size = view.header()->sectionSize(0);
view.setSortingEnabled(true);
diff --git a/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp b/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp
index 321e4bcd0e..8c93df9073 100644
--- a/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp
+++ b/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp
@@ -160,6 +160,7 @@ private slots:
void task20345_sortChildren();
void getMimeDataWithInvalidItem();
void testVisualItemRect();
+ void reparentHiddenItem();
public slots:
void itemSelectionChanged();
@@ -1938,23 +1939,38 @@ void tst_QTreeWidget::setData()
}
}
+class QTreeWidgetDataChanged : public QTreeWidget
+{
+ Q_OBJECT
+public:
+ using QTreeWidget::QTreeWidget;
+
+ void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) override
+ {
+ QTreeWidget::dataChanged(topLeft, bottomRight, roles);
+ currentRoles = roles;
+ }
+ QVector<int> currentRoles;
+};
+
void tst_QTreeWidget::itemData()
{
- QTreeWidget widget;
+ QTreeWidgetDataChanged widget;
QTreeWidgetItem item(&widget);
widget.setColumnCount(2);
item.setFlags(item.flags() | Qt::ItemIsEditable);
item.setData(0, Qt::DisplayRole, QString("0"));
+ QCOMPARE(widget.currentRoles, QVector<int>({Qt::DisplayRole, Qt::EditRole}));
item.setData(0, Qt::CheckStateRole, Qt::PartiallyChecked);
- item.setData(0, Qt::UserRole + 0, QString("1"));
- item.setData(0, Qt::UserRole + 1, QString("2"));
- item.setData(0, Qt::UserRole + 2, QString("3"));
- item.setData(0, Qt::UserRole + 3, QString("4"));
-
+ QCOMPARE(widget.currentRoles, {Qt::CheckStateRole});
+ for (int i = 0; i < 4; ++i) {
+ item.setData(0, Qt::UserRole + i, QString::number(i + 1));
+ QCOMPARE(widget.currentRoles, {Qt::UserRole + i});
+ }
QMap<int, QVariant> flags = widget.model()->itemData(widget.model()->index(0, 0));
QCOMPARE(flags.count(), 6);
- QCOMPARE(flags[Qt::UserRole + 0].toString(), QString("1"));
-
+ for (int i = 0; i < 4; ++i)
+ QCOMPARE(flags[Qt::UserRole + i].toString(), QString::number(i + 1));
flags = widget.model()->itemData(widget.model()->index(0, 1));
QCOMPARE(flags.count(), 0);
}
@@ -3412,8 +3428,9 @@ void tst_QTreeWidget::taskQTBUG_34717_collapseAtBottom()
void tst_QTreeWidget::task20345_sortChildren()
{
- if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
- QSKIP("Wayland: This causes a crash triggered by setVisible(false)");
+ if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive)
+ || !QGuiApplication::platformName().compare(QLatin1String("winrt"), Qt::CaseInsensitive))
+ QSKIP("Wayland/WinRT: This causes a crash triggered by setVisible(false)");
// This test case is considered successful if it is executed (no crash in sorting)
QTreeWidget tw;
@@ -3483,5 +3500,34 @@ void tst_QTreeWidget::testVisualItemRect()
QCOMPARE(r.width(), sectionSize);
}
+void tst_QTreeWidget::reparentHiddenItem()
+{
+ QTreeWidgetItem *parent = new QTreeWidgetItem(testWidget);
+ parent->setText(0, "parent");
+ QTreeWidgetItem *otherParent = new QTreeWidgetItem(testWidget);
+ otherParent->setText(0, "other parent");
+ QTreeWidgetItem *child = new QTreeWidgetItem(parent);
+ child->setText(0, "child");
+ QTreeWidgetItem *grandChild = new QTreeWidgetItem(child);
+ grandChild->setText(0, "grandchild");
+ QVERIFY(child->parent());
+ QVERIFY(grandChild->parent());
+
+ testWidget->expandItem(parent);
+ testWidget->expandItem(otherParent);
+ testWidget->expandItem(child);
+
+ QVERIFY(!parent->isHidden());
+ QVERIFY(!child->isHidden());
+ QVERIFY(!grandChild->isHidden());
+
+ grandChild->setHidden(true);
+
+ QVERIFY(grandChild->isHidden());
+ parent->removeChild(child);
+ otherParent->addChild(child);
+ QVERIFY(grandChild->isHidden());
+}
+
QTEST_MAIN(tst_QTreeWidget)
#include "tst_qtreewidget.moc"
diff --git a/tests/auto/widgets/kernel/qapplication/BLACKLIST b/tests/auto/widgets/kernel/qapplication/BLACKLIST
index ca0efdff8a..d7de7bf16e 100644
--- a/tests/auto/widgets/kernel/qapplication/BLACKLIST
+++ b/tests/auto/widgets/kernel/qapplication/BLACKLIST
@@ -1,3 +1,4 @@
[touchEventPropagation]
# QTBUG-66745
opensuse
+opensuse-leap
diff --git a/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/desktopsettingsaware.pro b/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/desktopsettingsaware.pro
index a10ff71b05..442bf33b61 100644
--- a/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/desktopsettingsaware.pro
+++ b/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/desktopsettingsaware.pro
@@ -1,6 +1,14 @@
QT += widgets
-CONFIG -= app_bundle debug_and_release_target
+CONFIG -= app_bundle
-DESTDIR = ./
+debug_and_release {
+ CONFIG(debug, debug|release) {
+ TARGET = ../../debug/desktopsettingsaware_helper
+ } else {
+ TARGET = ../../release/desktopsettingsaware_helper
+ }
+} else {
+ TARGET = ../desktopsettingsaware_helper
+}
SOURCES += main.cpp
diff --git a/tests/auto/widgets/kernel/qapplication/modal/modal.pro b/tests/auto/widgets/kernel/qapplication/modal/modal.pro
index a34871d2aa..e832d90821 100644
--- a/tests/auto/widgets/kernel/qapplication/modal/modal.pro
+++ b/tests/auto/widgets/kernel/qapplication/modal/modal.pro
@@ -1,7 +1,15 @@
QT += widgets
SOURCES += main.cpp \
base.cpp
-DESTDIR = ./
-CONFIG -= app_bundle debug_and_release_target
+debug_and_release {
+ CONFIG(debug, debug|release) {
+ TARGET = ../../debug/modal_helper
+ } else {
+ TARGET = ../../release/modal_helper
+ }
+} else {
+ TARGET = ../modal_helper
+}
+CONFIG -= app_bundle
HEADERS += base.h
diff --git a/tests/auto/widgets/kernel/qapplication/test/test.pro b/tests/auto/widgets/kernel/qapplication/test/test.pro
index 41aad02a1b..8ade4d8364 100644
--- a/tests/auto/widgets/kernel/qapplication/test/test.pro
+++ b/tests/auto/widgets/kernel/qapplication/test/test.pro
@@ -1,18 +1,28 @@
CONFIG += testcase
-CONFIG -= debug_and_release_target
QT += widgets widgets-private testlib
QT += core-private gui-private
SOURCES += ../tst_qapplication.cpp
-TARGET = ../tst_qapplication
-TESTDATA = ../test/test.pro ../tmp/README
+builtin_testdata: DEFINES += BUILTIN_TESTDATA
-!android:!winrt {
- SUBPROGRAMS = desktopsettingsaware modal
- win32:SUBPROGRAMS += wincmdline
+TESTDATA = ../test/test.pro ../tmp/README ../modal
- for(file, SUBPROGRAMS): TEST_HELPER_INSTALLS += "../$${file}/$${file}"
-}
+!android:!winrt: SUBPROGRAMS = desktopsettingsaware modal
+debug_and_release {
+ CONFIG(debug, debug|release) {
+ TARGET = ../../debug/tst_qapplication
+ !android:!winrt: TEST_HELPER_INSTALLS = ../debug/helper
+ for(file, SUBPROGRAMS): TEST_HELPER_INSTALLS += "../debug/$${file}"
+ } else {
+ TARGET = ../../release/tst_qapplication
+ !android:!winrt: TEST_HELPER_INSTALLS = ../release/helper
+ for(file, SUBPROGRAMS): TEST_HELPER_INSTALLS += "../release/$${file}"
+ }
+} else {
+ TARGET = ../tst_qapplication
+ !android:!winrt: TEST_HELPER_INSTALLS = ../helper
+ for(file, SUBPROGRAMS): TEST_HELPER_INSTALLS += "../$${file}"
+}
diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
index bd4dc3d6f3..d2a244b762 100644
--- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
+++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
@@ -96,7 +96,6 @@ public:
tst_QApplication();
private slots:
- void initTestCase();
void cleanup();
void sendEventsOnProcessEvents(); // this must be the first test
void staticSetup();
@@ -187,13 +186,6 @@ public:
}
};
-void tst_QApplication::initTestCase()
-{
- // chdir to our testdata path and execute helper apps relative to that.
- const QString testdataDir = QFileInfo(QFINDTESTDATA("desktopsettingsaware")).absolutePath();
- QVERIFY2(QDir::setCurrent(testdataDir), qPrintable("Could not chdir to " + testdataDir));
-}
-
void tst_QApplication::sendEventsOnProcessEvents()
{
int argc = 0;
@@ -277,6 +269,9 @@ public:
void tst_QApplication::alert()
{
+#ifdef Q_OS_WINRT
+ QSKIP("WinRT does not support more than 1 native widget at the same time");
+#endif
int argc = 0;
QApplication app(argc, 0);
app.alert(0, 0);
@@ -820,6 +815,9 @@ public:
void tst_QApplication::closeAllWindows()
{
+#ifdef Q_OS_WINRT
+ QSKIP("PromptOnCloseWidget does not work on WinRT - QTBUG-68297");
+#endif
int argc = 0;
QApplication app(argc, 0);
@@ -888,7 +886,11 @@ bool isPathListIncluded(const QStringList &l, const QStringList &r)
#define QT_TST_QAPP_DEBUG
void tst_QApplication::libraryPaths()
{
+#ifndef BUILTIN_TESTDATA
const QString testDir = QFileInfo(QFINDTESTDATA("test/test.pro")).absolutePath();
+#else
+ const QString testDir = QFileInfo(QFINDTESTDATA("test.pro")).absolutePath();
+#endif
QVERIFY(!testDir.isEmpty());
{
QApplication::setLibraryPaths(QStringList() << testDir);
@@ -921,6 +923,9 @@ void tst_QApplication::libraryPaths()
QStringList expected = QSet<QString>::fromList((QStringList() << installPathPlugins << appDirPath)).toList();
expected.sort();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "On WinRT PluginsPath is outside of sandbox. QTBUG-68297", Abort);
+#endif
QVERIFY2(isPathListIncluded(actual, expected),
qPrintable("actual:\n - " + actual.join("\n - ") +
"\nexpected:\n - " + expected.join("\n - ")));
@@ -1040,6 +1045,9 @@ void tst_QApplication::libraryPaths_qt_plugin_path_2()
<< QDir(app.applicationDirPath()).canonicalPath()
<< QDir(QDir::fromNativeSeparators(QString::fromLatin1(validPath))).canonicalPath();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "On WinRT PluginsPath is outside of sandbox. QTBUG-68297", Abort);
+#endif
QVERIFY2(isPathListIncluded(app.libraryPaths(), expected),
qPrintable("actual:\n - " + app.libraryPaths().join("\n - ") +
"\nexpected:\n - " + expected.join("\n - ")));
@@ -1434,20 +1442,10 @@ void tst_QApplication::testDeleteLaterProcessEvents()
void tst_QApplication::desktopSettingsAware()
{
#if QT_CONFIG(process)
- QString path;
- {
- // We need an application object for QFINDTESTDATA to work
- // properly in all cases.
- int argc = 0;
- QCoreApplication app(argc, 0);
- path = QFINDTESTDATA("desktopsettingsaware/");
- }
- QVERIFY2(!path.isEmpty(), "Cannot locate desktopsettingsaware helper application");
- path += "desktopsettingsaware";
QProcess testProcess;
- testProcess.start(path);
+ testProcess.start("desktopsettingsaware_helper");
QVERIFY2(testProcess.waitForStarted(),
- qPrintable(QString::fromLatin1("Cannot start '%1': %2").arg(path, testProcess.errorString())));
+ qPrintable(QString::fromLatin1("Cannot start 'desktopsettingsaware_helper': %1").arg(testProcess.errorString())));
QVERIFY(testProcess.waitForFinished(10000));
QCOMPARE(int(testProcess.state()), int(QProcess::NotRunning));
QVERIFY(int(testProcess.error()) != int(QProcess::Crashed));
@@ -1744,6 +1742,9 @@ void tst_QApplication::focusMouseClick()
QSpontaneKeyEvent::setSpontaneous(&ev);
QVERIFY(ev.spontaneous());
qApp->notify(&w2, &ev);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Fails on WinRT - QTBUG-68297", Abort);
+#endif
QTRY_COMPARE(QApplication::focusWidget(), &w2);
// now back to tab focus and click again (it already had focus) -> focus should stay
@@ -2112,23 +2113,12 @@ void tst_QApplication::touchEventPropagation()
void tst_QApplication::qtbug_12673()
{
- QString path;
- {
- // We need an application object for QFINDTESTDATA to work
- // properly in all cases.
- int argc = 0;
- QCoreApplication app(argc, 0);
- path = QFINDTESTDATA("modal/");
- }
- QVERIFY2(!path.isEmpty(), "Cannot locate modal helper application");
- path += "modal";
-
#if QT_CONFIG(process)
QProcess testProcess;
QStringList arguments;
- testProcess.start(path, arguments);
+ testProcess.start("modal_helper", arguments);
QVERIFY2(testProcess.waitForStarted(),
- qPrintable(QString::fromLatin1("Cannot start '%1': %2").arg(path, testProcess.errorString())));
+ qPrintable(QString::fromLatin1("Cannot start 'modal_helper': %1").arg(testProcess.errorString())));
QVERIFY(testProcess.waitForFinished(20000));
QCOMPARE(testProcess.exitStatus(), QProcess::NormalExit);
#else
diff --git a/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp b/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp
index 8314dbedf5..b2650d1f32 100644
--- a/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp
+++ b/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp
@@ -56,6 +56,7 @@ private slots:
void taskQTBUG_40609_addingWidgetToItsOwnLayout();
void taskQTBUG_40609_addingLayoutToItself();
void replaceWidget();
+ void indexOf();
};
class CustomLayoutStyle : public QProxyStyle
@@ -512,5 +513,24 @@ void tst_QBoxLayout::replaceWidget()
QCOMPARE(boxLayout->indexOf(replaceTo), 1);
}
+void tst_QBoxLayout::indexOf()
+{
+ QWidget w;
+ auto outer = new QVBoxLayout(&w);
+ auto inner = new QHBoxLayout();
+ outer->addLayout(inner);
+ auto widget1 = new QWidget();
+ QWidget widget2;
+ inner->addWidget(widget1);
+
+ QCOMPARE(inner->indexOf(widget1), 0);
+ QCOMPARE(inner->indexOf(&widget2), -1);
+ QCOMPARE(outer->indexOf(widget1), -1);
+ QCOMPARE(outer->indexOf(&widget2), -1);
+ QCOMPARE(outer->indexOf(outer), -1);
+ QCOMPARE(outer->indexOf(inner), 0);
+ QCOMPARE(inner->indexOf(inner->itemAt(0)), 0);
+}
+
QTEST_MAIN(tst_QBoxLayout)
#include "tst_qboxlayout.moc"
diff --git a/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp b/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp
index 162da61584..cff3dad35e 100644
--- a/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp
+++ b/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp
@@ -273,6 +273,9 @@ void tst_QFormLayout::wrapping()
w.setWindowTitle(QTest::currentTestFunction());
w.show();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "setFixedWidth does not work on WinRT", Abort);
+#endif
QCOMPARE(le->geometry().y() > lbl->geometry().y(), true);
//TODO: additional tests covering different wrapping cases
diff --git a/tests/auto/widgets/kernel/qgesturerecognizer/BLACKLIST b/tests/auto/widgets/kernel/qgesturerecognizer/BLACKLIST
deleted file mode 100644
index 7f55c2dae0..0000000000
--- a/tests/auto/widgets/kernel/qgesturerecognizer/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[panGesture:Two finger]
-xcb
diff --git a/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp b/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp
index 300a8878ba..936f581d89 100644
--- a/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp
+++ b/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp
@@ -337,7 +337,7 @@ void tst_QLayout::adjustSizeShouldMakeSureLayoutIsActivated()
void tst_QLayout::testRetainSizeWhenHidden()
{
-#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
+#if (defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)) || defined(Q_OS_WINRT)
QSKIP("Test does not work on platforms which default to showMaximized()");
#endif
diff --git a/tests/auto/widgets/kernel/qsizepolicy/tst_qsizepolicy.cpp b/tests/auto/widgets/kernel/qsizepolicy/tst_qsizepolicy.cpp
index eb3264be53..89bb946be9 100644
--- a/tests/auto/widgets/kernel/qsizepolicy/tst_qsizepolicy.cpp
+++ b/tests/auto/widgets/kernel/qsizepolicy/tst_qsizepolicy.cpp
@@ -116,8 +116,16 @@ void tst_QSizePolicy::constExpr()
{ Q_CONSTEXPR QSizePolicy sp = QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); Q_UNUSED(sp); }
{ Q_CONSTEXPR QSizePolicy sp = QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding, QSizePolicy::DefaultType);
Q_CONSTEXPR QSizePolicy tp = sp.transposed(); Q_UNUSED(tp); }
- { Q_RELAXED_CONSTEXPR auto sp = QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed, QSizePolicy::CheckBox);
- Q_RELAXED_CONSTEXPR auto tp = sp.transposed(); Q_UNUSED(tp); }
+ {
+ // QTBUG-69983: For ControlType != QSizePolicy::DefaultType, qCountTrailingZeroBits()
+ // is used, which MSVC 15.8.1 does not consider constexpr due to built-ins
+# if defined(QT_HAS_CONSTEXPR_BUILTINS) && (!defined(Q_CC_MSVC) || _MSC_VER < 1915)
+ Q_RELAXED_CONSTEXPR auto sp = QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed, QSizePolicy::CheckBox);
+# else
+ Q_CONSTEXPR auto sp = QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding, QSizePolicy::DefaultType);
+# endif
+ Q_RELAXED_CONSTEXPR auto tp = sp.transposed(); Q_UNUSED(tp);
+ }
#else
QSKIP("QSizePolicy cannot be constexpr with this version of the compiler.");
#endif
diff --git a/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp b/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp
index e02573f8e8..3d609d0b9c 100644
--- a/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp
+++ b/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp
@@ -46,6 +46,7 @@ private slots:
void whatsThis();
void setPalette();
void qtbug64550_stylesheet();
+ void dontCrashOutsideScreenGeometry();
};
void tst_QToolTip::init()
@@ -218,5 +219,11 @@ void tst_QToolTip::qtbug64550_stylesheet()
msgSizeTooSmall(toolTipSize, boundingRect.size()).constData());
}
+void tst_QToolTip::dontCrashOutsideScreenGeometry() {
+ QToolTip::showText(QPoint(-10000, -10000), "tip outside monitor", nullptr);
+ QTRY_VERIFY(QToolTip::isVisible());
+ QToolTip::hideText();
+}
+
QTEST_MAIN(tst_QToolTip)
#include "tst_qtooltip.moc"
diff --git a/tests/auto/widgets/kernel/qwidget/BLACKLIST b/tests/auto/widgets/kernel/qwidget/BLACKLIST
index 6cebce26e8..d8654e5768 100644
--- a/tests/auto/widgets/kernel/qwidget/BLACKLIST
+++ b/tests/auto/widgets/kernel/qwidget/BLACKLIST
@@ -2,35 +2,27 @@
[normalGeometry]
ubuntu-16.04
[saveRestoreGeometry]
-ubuntu-16.04
+xcb
b2qt
-# QTBUG-66708
-opensuse
[restoreVersion1Geometry]
-xcb
osx
[updateWhileMinimized]
ubuntu-16.04
+ubuntu-18.04
rhel-7.4
osx
[focusProxyAndInputMethods]
linux
-[showMaximized]
-osx
-[setGeometry]
-osx
[raise]
# QTBUG-68175
opensuse
-osx
-[resizeEvent]
-osx
+opensuse-leap
[setWindowGeometry]
osx
[windowMoveResize]
osx
[childEvents]
-osx
+osx ci
[renderInvisible]
osx
[optimizedResizeMove]
@@ -42,27 +34,10 @@ osx
[showMinimizedKeepsFocus]
osx-10.11 ci
osx-10.12 ci
-[moveWindowInShowEvent:1]
-osx
-[moveWindowInShowEvent:2]
-osx
-[taskQTBUG_4055_sendSyntheticEnterLeave]
-osx
-[syntheticEnterLeave]
-osx
+osx-10.13 ci
[maskedUpdate]
-osx
-opensuse-42.3
-[hideOpaqueChildWhileHidden]
-osx
-[resizeStaticContentsChildWidget_QTBUG35282]
-osx
-[lower]
-osx
-[setClearAndResizeMask]
-osx
-[setToolTip]
-osx
+opensuse
+opensuse-leap
[moveInResizeEvent]
ubuntu-16.04
[moveChild:right]
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index 6a049aedf1..360e6986f6 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -188,7 +188,8 @@ private slots:
void reverseTabOrder();
void tabOrderWithProxy();
void tabOrderWithCompoundWidgets();
-#ifdef Q_OS_WIN
+ void tabOrderNoChange();
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
void activation();
#endif
void reparent();
@@ -416,8 +417,7 @@ private:
bool tst_QWidget::ensureScreenSize(int width, int height)
{
- QSize available;
- available = QDesktopWidget().availableGeometry().size();
+ const QSize available = QGuiApplication::primaryScreen()->availableGeometry().size();
return (available.width() >= width && available.height() >= height);
}
@@ -1426,7 +1426,7 @@ void tst_QWidget::mapFromAndTo()
subWindow2->setGeometry(75, 75, 100, 100);
subSubWindow->setGeometry(10, 10, 10, 10);
-#if !defined(Q_OS_QNX)
+#if !defined(Q_OS_QNX) && !defined(Q_OS_WINRT)
//update visibility
if (windowMinimized) {
if (!windowHidden) {
@@ -1931,7 +1931,35 @@ void tst_QWidget::tabOrderWithCompoundWidgets()
QVERIFY(lastEdit->hasFocus());
}
-#ifdef Q_OS_WIN
+static QVector<QWidget*> getFocusChain(QWidget *start, bool bForward)
+{
+ QVector<QWidget*> ret;
+ QWidget *cur = start;
+ do {
+ ret += cur;
+ auto widgetPrivate = static_cast<QWidgetPrivate *>(qt_widget_private(cur));
+ cur = bForward ? widgetPrivate->focus_next : widgetPrivate->focus_prev;
+ } while (cur != start);
+ return ret;
+}
+
+void tst_QWidget::tabOrderNoChange()
+{
+ QWidget w;
+ auto *verticalLayout = new QVBoxLayout(&w);
+ auto *tabWidget = new QTabWidget(&w);
+ auto *tv = new QTreeView(tabWidget);
+ tabWidget->addTab(tv, QStringLiteral("Tab 1"));
+ verticalLayout->addWidget(tabWidget);
+
+ const auto focusChainForward = getFocusChain(&w, true);
+ const auto focusChainBackward = getFocusChain(&w, false);
+ QWidget::setTabOrder(tabWidget, tv);
+ QCOMPARE(focusChainForward, getFocusChain(&w, true));
+ QCOMPARE(focusChainBackward, getFocusChain(&w, false));
+}
+
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
void tst_QWidget::activation()
{
Q_CHECK_PAINTEVENTS
@@ -1976,7 +2004,8 @@ void tst_QWidget::windowState()
QPoint pos;
QSize size = m_testWidgetSize;
if (QGuiApplicationPrivate::platformIntegration()->defaultWindowState(Qt::Widget)
- == Qt::WindowFullScreen) {
+ == Qt::WindowFullScreen
+ || m_platform == QStringLiteral("winrt")) {
size = QGuiApplication::primaryScreen()->size();
} else {
pos = QPoint(10, 10);
@@ -2181,8 +2210,8 @@ void tst_QWidget::showFullScreen()
QSKIP("QTBUG-52974");
#endif
- if (m_platform == QStringLiteral("wayland"))
- QSKIP("Wayland: This fails. Figure out why.");
+ if (m_platform == QStringLiteral("winrt"))
+ QSKIP("WinRT: This fails. QTBUG-68297");
QWidget plain;
QHBoxLayout *layout;
QWidget layouted;
@@ -2304,6 +2333,8 @@ void tst_QWidget::resizeEvent()
wTopLevel.resize(200, 200);
wTopLevel.show();
QVERIFY(QTest::qWaitForWindowExposed(&wTopLevel));
+ if (m_platform == QStringLiteral("winrt"))
+ QEXPECT_FAIL("", "WinRT does not support resize", Abort);
QCOMPARE (wTopLevel.m_resizeEventCount, 1); // initial resize event before paint for toplevels
wTopLevel.hide();
QSize safeSize(640,480);
@@ -2319,6 +2350,12 @@ void tst_QWidget::resizeEvent()
void tst_QWidget::showMinimized()
{
+ if (m_platform == QStringLiteral("wayland")) {
+ QSKIP("Wayland: Neither xdg_shell, wl_shell or ivi_application support "
+ "letting a client know whether it's minimized. So on these shells "
+ "Qt Wayland will always report that it's unmimized.");
+ }
+
QWidget plain;
plain.move(100, 100);
plain.resize(200, 200);
@@ -2327,6 +2364,9 @@ void tst_QWidget::showMinimized()
plain.showMinimized();
QVERIFY(plain.isMinimized());
QVERIFY(plain.isVisible());
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Winrt does not support move and resize", Abort);
+#endif
QCOMPARE(plain.pos(), pos);
plain.showNormal();
@@ -2478,11 +2518,15 @@ void tst_QWidget::showMinimizedKeepsFocus()
#ifdef Q_OS_OSX
if (!macHasAccessToWindowsServer())
QEXPECT_FAIL("", "When not having WindowServer access, we lose focus.", Continue);
+#elif defined(Q_OS_WINRT)
+ QEXPECT_FAIL("", "Winrt fails here - QTBUG-68297", Continue);
#endif
QTRY_COMPARE(window.focusWidget(), firstchild);
#ifdef Q_OS_OSX
if (!macHasAccessToWindowsServer())
QEXPECT_FAIL("", "When not having WindowServer access, we lose focus.", Continue);
+#elif defined(Q_OS_WINRT)
+ QEXPECT_FAIL("", "Winrt fails here - QTBUG-68297", Continue);
#endif
QTRY_COMPARE(qApp->focusWidget(), firstchild);
}
@@ -2513,6 +2557,9 @@ void tst_QWidget::reparent()
parent.show();
childTLW.show();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "WinRT does not support more than 1 top level widget", Abort);
+#endif
QVERIFY(QTest::qWaitForWindowExposed(&parent));
parent.move(parentPosition);
@@ -2610,6 +2657,8 @@ void tst_QWidget::normalGeometry()
if (m_platform == QStringLiteral("wayland"))
QSKIP("Wayland: This fails. Figure out why.");
+ else if (m_platform == QStringLiteral("winrt"))
+ QSKIP("WinRT: This fails. Figure out why - QTBUG-68297.");
QWidget parent;
parent.setWindowTitle("NormalGeometry parent");
QWidget *child = new QWidget(&parent);
@@ -2719,12 +2768,14 @@ void tst_QWidget::setGeometry()
tlw.setGeometry(tr);
child.setGeometry(cr);
tlw.showNormal();
+ if (m_platform == QStringLiteral("winrt"))
+ QEXPECT_FAIL("", "WinRT does not support setGeometry", Abort);
QTRY_COMPARE(tlw.geometry().size(), tr.size());
QCOMPARE(child.geometry(), cr);
tlw.setParent(0, Qt::Window|Qt::FramelessWindowHint);
tr = QRect(0,0,100,100);
- tr.moveTopLeft(QApplication::desktop()->availableGeometry().topLeft());
+ tr.moveTopLeft(QGuiApplication::primaryScreen()->availableGeometry().topLeft());
tlw.setGeometry(tr);
QCOMPARE(tlw.geometry(), tr);
tlw.showNormal();
@@ -3198,6 +3249,8 @@ void tst_QWidget::saveRestoreGeometry()
QVERIFY(QTest::qWaitForWindowExposed(&widget));
QApplication::processEvents();
+ if (m_platform == QStringLiteral("winrt"))
+ QEXPECT_FAIL("", "WinRT does not support move/resize", Abort);
QTRY_COMPARE(widget.pos(), position);
QCOMPARE(widget.size(), size);
savedGeometry = widget.saveGeometry();
@@ -3338,6 +3391,7 @@ void tst_QWidget::restoreVersion1Geometry()
QFETCH(QString, fileName);
QFETCH(uint, expectedWindowState);
QFETCH(QPoint, expectedPosition);
+ Q_UNUSED(expectedPosition);
QFETCH(QSize, expectedSize);
QFETCH(QRect, expectedNormalGeometry);
@@ -3357,28 +3411,28 @@ void tst_QWidget::restoreVersion1Geometry()
QCOMPARE(uint(widget.windowState() & WindowStateMask), expectedWindowState);
if (expectedWindowState == Qt::WindowNoState) {
- QCOMPARE(widget.pos(), expectedPosition);
+ QTRY_COMPARE(widget.geometry(), expectedNormalGeometry);
QCOMPARE(widget.size(), expectedSize);
}
+
widget.showNormal();
QVERIFY(QTest::qWaitForWindowExposed(&widget));
QTest::qWait(100);
+ if (m_platform == QStringLiteral("winrt"))
+ QEXPECT_FAIL("", "WinRT does not support restoreGeometry", Abort);
+
if (expectedWindowState == Qt::WindowNoState) {
- QTRY_COMPARE(widget.pos(), expectedPosition);
QTRY_COMPARE(widget.size(), expectedSize);
+ QCOMPARE(widget.geometry(), expectedNormalGeometry);
}
widget.showNormal();
QTest::qWait(10);
- if (expectedWindowState != Qt::WindowNoState) {
- // restoring from maximized or fullscreen, we can only restore to the normal geometry
- QTRY_COMPARE(widget.geometry(), expectedNormalGeometry);
- } else {
- QTRY_COMPARE(widget.pos(), expectedPosition);
- QTRY_COMPARE(widget.size(), expectedSize);
- }
+ QTRY_COMPARE(widget.geometry(), expectedNormalGeometry);
+ if (expectedWindowState == Qt::WindowNoState)
+ QCOMPARE(widget.size(), expectedSize);
#if 0
// Code for saving a new geometry*.dat files
@@ -3413,6 +3467,8 @@ void tst_QWidget::widgetAt()
QSKIP("Wayland: This fails. Figure out why.");
if (m_platform == QStringLiteral("offscreen"))
QSKIP("Platform offscreen does not support lower()/raise() or WindowMasks");
+ if (m_platform == QStringLiteral("winrt"))
+ QSKIP("WinRT does not support more than 1 top level widget");
Q_CHECK_PAINTEVENTS
@@ -3714,6 +3770,8 @@ void tst_QWidget::optimizedResizeMove()
staticWidget.gotPaintEvent = false;
staticWidget.move(staticWidget.pos() + QPoint(10, 10));
QTest::qWait(20);
+ if (m_platform == QStringLiteral("winrt"))
+ QEXPECT_FAIL("", "WinRT does not support move/resize", Abort);
QCOMPARE(staticWidget.gotPaintEvent, false);
staticWidget.gotPaintEvent = false;
@@ -3798,9 +3856,10 @@ void tst_QWidget::optimizedResize_topLevel()
// a native function call works (it basically has to go through
// WM_RESIZE in QApplication). This is a corner case, though.
// See task 243708
- const QRect frame = topLevel.frameGeometry();
- MoveWindow(winHandleOf(&topLevel), frame.x(), frame.y(),
- frame.width() + 10, frame.height() + 10,
+ RECT rect;
+ GetWindowRect(winHandleOf(&topLevel), &rect);
+ MoveWindow(winHandleOf(&topLevel), rect.left, rect.top,
+ rect.right - rect.left + 10, rect.bottom - rect.top + 10,
true);
QTest::qWait(100);
#endif
@@ -3812,6 +3871,8 @@ void tst_QWidget::optimizedResize_topLevel()
QTRY_VERIFY(topLevel.gotPaintEvent);
if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("offscreen"))
QSKIP("QTBUG-26424");
+ else if (m_platform == QStringLiteral("winrt"))
+ QEXPECT_FAIL("", "WinRT does not support move/resize", Abort);
QCOMPARE(topLevel.partial, true);
QCOMPARE(topLevel.paintedRegion, expectedUpdateRegion);
}
@@ -3860,7 +3921,7 @@ void tst_QWidget::setMinimumSize()
QSize nonDefaultSize = defaultSize + QSize(5,5);
w.setMinimumSize(nonDefaultSize);
w.showNormal();
- QVERIFY(QTest::qWaitForWindowActive(&w));
+ QVERIFY(QTest::qWaitForWindowExposed(&w));
QVERIFY2(w.height() >= nonDefaultSize.height(),
msgComparisonFailed(w.height(), ">=", nonDefaultSize.height()));
QVERIFY2(w.width() >= nonDefaultSize.width(),
@@ -3915,6 +3976,8 @@ void tst_QWidget::setFixedSize()
QVERIFY(QTest::qWaitForWindowActive(&w));
if (m_platform == QStringLiteral("xcb"))
QSKIP("QTBUG-26424");
+ else if (m_platform == QStringLiteral("winrt"))
+ QEXPECT_FAIL("", "WinRT does not support move/resize", Abort);
QCOMPARE(w.size(), defaultSize + QSize(150,150));
}
@@ -4115,6 +4178,8 @@ void tst_QWidget::transientParent()
void tst_QWidget::showNativeChild()
{
+ if (m_platform == QStringLiteral("winrt"))
+ QSKIP("WinRT does not support setGeometry");
QWidget topLevel;
topLevel.setGeometry(QRect(m_availableTopLeft + QPoint(100, 100), m_testWidgetSize));
topLevel.setWindowTitle(__FUNCTION__);
@@ -4297,6 +4362,8 @@ void tst_QWidget::update()
// widgets are transparent by default, so both should get repaints
{
+ if (m_platform == QStringLiteral("winrt"))
+ QEXPECT_FAIL("", "WinRT does not support setGeometry", Abort);
QApplication::processEvents();
QApplication::processEvents();
QCOMPARE(child.numPaintEvents, 1);
@@ -4518,8 +4585,9 @@ void tst_QWidget::scroll()
{
if (m_platform == QStringLiteral("wayland"))
QSKIP("Wayland: This fails. Figure out why.");
- const int w = qMin(500, qApp->desktop()->availableGeometry().width() / 2);
- const int h = qMin(500, qApp->desktop()->availableGeometry().height() / 2);
+ QScreen *screen = QGuiApplication::primaryScreen();
+ const int w = qMin(500, screen->availableGeometry().width() / 2);
+ const int h = qMin(500, screen->availableGeometry().height() / 2);
UpdateWidget updateWidget;
updateWidget.resize(w, h);
@@ -4536,6 +4604,8 @@ void tst_QWidget::scroll()
qApp->processEvents();
QRegion dirty(QRect(0, 0, w, 10));
dirty += QRegion(QRect(0, 10, 10, h - 10));
+ if (m_platform == QStringLiteral("winrt"))
+ QEXPECT_FAIL("", "WinRT does not support move/resize", Abort);
QTRY_COMPARE(updateWidget.paintedRegion, dirty);
}
@@ -4647,7 +4717,7 @@ void tst_QWidget::setWindowGeometry_data()
QList<QList<QRect> > rects;
const int width = m_testWidgetSize.width();
const int height = m_testWidgetSize.height();
- const QRect availableAdjusted = QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100);
+ const QRect availableAdjusted = QGuiApplication::primaryScreen()->availableGeometry().adjusted(100, 100, -100, -100);
rects << (QList<QRect>()
<< QRect(m_availableTopLeft + QPoint(100, 100), m_testWidgetSize)
<< availableAdjusted
@@ -4711,6 +4781,8 @@ void tst_QWidget::setWindowGeometry()
{
if (m_platform == QStringLiteral("xcb"))
QSKIP("X11: Skip this test due to Window manager positioning issues.");
+ else if (m_platform == QStringLiteral("winrt"))
+ QSKIP("WinRT does not support setWindowGeometry");
QFETCH(QList<QRect>, rects);
QFETCH(int, windowFlags);
@@ -4877,6 +4949,8 @@ void tst_QWidget::windowMoveResize()
QSKIP("X11: Skip this test due to Window manager positioning issues.");
if (m_platform == QStringLiteral("wayland"))
QSKIP("Wayland: This fails. Figure out why.");
+ if (m_platform == QStringLiteral("winrt"))
+ QSKIP("WinRT does not support move/resize");
QFETCH(QList<QRect>, rects);
QFETCH(int, windowFlags);
@@ -5197,6 +5271,9 @@ void tst_QWidget::moveChild()
QTRY_COMPARE(parent.r, QRegion(parent.rect()) - child.geometry());
QTRY_COMPARE(child.r, QRegion(child.rect()));
+
+ if (m_platform == QStringLiteral("winrt"))
+ QSKIP("WinRT does not support setGeometry (and we cannot use QEXPECT_FAIL because of VERIFY_COLOR)");
VERIFY_COLOR(child, child.rect(),
child.color);
VERIFY_COLOR(parent, QRegion(parent.rect()) - child.geometry(), parent.color);
@@ -5253,6 +5330,8 @@ void tst_QWidget::showAndMoveChild()
child.move(desktopDimensions.width()/2, desktopDimensions.height()/2);
qApp->processEvents();
+ if (m_platform == QStringLiteral("winrt"))
+ QSKIP("WinRT does not support setGeometry (and we cannot use QEXPECT_FAIL because of VERIFY_COLOR)");
VERIFY_COLOR(child, child.rect(), Qt::blue);
VERIFY_COLOR(parent, QRegion(parent.rect()) - child.geometry(), Qt::red);
}
@@ -5341,6 +5420,8 @@ void tst_QWidget::multipleToplevelFocusCheck()
if (m_platform == QStringLiteral("wayland"))
QSKIP("Wayland: This fails. Figure out why.");
+ else if (m_platform == QStringLiteral("winrt"))
+ QSKIP("Winrt: Sometimes crashes in QTextLayout. - QTBUG-68297");
TopLevelFocusCheck w1;
TopLevelFocusCheck w2;
@@ -5499,6 +5580,8 @@ void tst_QWidget::setFocus()
testWidget->clearFocus();
child1.setFocus();
+ if (m_platform == QStringLiteral("winrt"))
+ QEXPECT_FAIL("", "WinRT fails here - QTBUG-68297", Abort);
QVERIFY(!child1.hasFocus());
QCOMPARE(window.focusWidget(), &child1);
QCOMPARE(QApplication::focusWidget(), nullptr);
@@ -6185,8 +6268,8 @@ QByteArray EventRecorder::msgEventListMismatch(const EventList &expected, const
void tst_QWidget::childEvents()
{
- if (m_platform == QStringLiteral("wayland"))
- QSKIP("Wayland: This fails. Figure out why.");
+ if (m_platform == QStringLiteral("winrt"))
+ QSKIP("WinRT: This fails. QTBUG-68297.");
EventRecorder::EventList expected;
// Move away the cursor; otherwise it might result in an enter event if it's
@@ -6582,6 +6665,8 @@ void tst_QWidget::renderInvisible()
{
if (m_platform == QStringLiteral("xcb"))
QSKIP("QTBUG-26424");
+ if (m_platform == QStringLiteral("winrt"))
+ QSKIP("WinRT: This fails. QTBUG-68297.");
QScopedPointer<QCalendarWidget> calendar(new QCalendarWidget);
calendar->move(m_availableTopLeft + QPoint(100, 100));
@@ -7430,7 +7515,7 @@ void tst_QWidget::moveWindowInShowEvent_data()
QTest::addColumn<QPoint>("initial");
QTest::addColumn<QPoint>("position");
- QPoint p = QApplication::desktop()->availableGeometry().topLeft();
+ QPoint p = QGuiApplication::primaryScreen()->availableGeometry().topLeft();
QTest::newRow("1") << p << (p + QPoint(10, 10));
QTest::newRow("2") << (p + QPoint(10,10)) << p;
@@ -7455,7 +7540,8 @@ void tst_QWidget::moveWindowInShowEvent()
};
MoveWindowInShowEventWidget widget;
- widget.resize(QSize(qApp->desktop()->availableGeometry().size() / 3).expandedTo(QSize(1, 1)));
+ QScreen *screen = QGuiApplication::primaryScreen();
+ widget.resize(QSize(screen->availableGeometry().size() / 3).expandedTo(QSize(1, 1)));
// move to this position in showEvent()
widget.position = position;
@@ -7524,6 +7610,8 @@ void tst_QWidget::hideOpaqueChildWhileHidden()
child.hide();
child2.hide();
+ if (m_platform == QStringLiteral("winrt"))
+ QEXPECT_FAIL("", "WinRT: This fails. QTBUG-68297.", Abort);
QTRY_COMPARE(w.r, QRegion(child.geometry()));
child.show();
@@ -7561,6 +7649,8 @@ void tst_QWidget::updateWhileMinimized()
// Make sure update requests are discarded until the widget is shown again.
widget.update(0, 0, 50, 50);
QTest::qWait(10);
+ if (m_platform == QStringLiteral("winrt"))
+ QEXPECT_FAIL("", "WinRT: This fails. QTBUG-68297.", Abort);
QCOMPARE(widget.numPaintEvents, 0);
// Restore window.
@@ -8088,6 +8178,8 @@ void tst_QWidget::doubleRepaint()
#if defined(Q_OS_QNX)
QEXPECT_FAIL("", "Platform does not support showMinimized()", Continue);
#endif
+ if (m_platform == QStringLiteral("winrt"))
+ QEXPECT_FAIL("", "WinRT: This fails. QTBUG-68297.", Abort);
QCOMPARE(widget.numPaintEvents, 0);
widget.numPaintEvents = 0;
@@ -8105,7 +8197,7 @@ void tst_QWidget::resizeInPaintEvent()
window.resize(200, 200);
window.show();
qApp->setActiveWindow(&window);
- QVERIFY(QTest::qWaitForWindowActive(&window));
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
QTRY_VERIFY(widget.numPaintEvents > 0);
widget.reset();
@@ -8217,6 +8309,8 @@ void tst_QWidget::setMaskInResizeEvent()
QRegion expectedParentUpdate(0, 0, 100, 10); // Old testWidget area.
expectedParentUpdate += testWidget.geometry(); // New testWidget area.
+ if (m_platform == QStringLiteral("winrt"))
+ QEXPECT_FAIL("", "WinRT: This fails. QTBUG-68297.", Abort);
QTRY_COMPARE(w.paintedRegion, expectedParentUpdate);
QTRY_COMPARE(testWidget.paintedRegion, testWidget.mask());
@@ -8645,7 +8739,7 @@ void tst_QWidget::translucentWidget()
ColorRedWidget label;
label.setFixedSize(16,16);
label.setAttribute(Qt::WA_TranslucentBackground);
- const QPoint labelPos = qApp->desktop()->availableGeometry().topLeft();
+ const QPoint labelPos = QGuiApplication::primaryScreen()->availableGeometry().topLeft();
label.move(labelPos);
label.show();
QVERIFY(QTest::qWaitForWindowExposed(&label));
@@ -8661,6 +8755,8 @@ void tst_QWidget::translucentWidget()
widgetSnapshot = label.grab(QRect(QPoint(0, 0), label.size()));
const QImage actual = widgetSnapshot.toImage().convertToFormat(QImage::Format_RGB32);
const QImage expected = pm.toImage().scaled(label.devicePixelRatioF() * pm.size());
+ if (m_platform == QStringLiteral("winrt"))
+ QEXPECT_FAIL("", "WinRT: This fails. QTBUG-68297.", Abort);
QCOMPARE(actual.size(),expected.size());
QCOMPARE(actual,expected);
}
@@ -8704,7 +8800,7 @@ void tst_QWidget::setClearAndResizeMask()
centerOnScreen(&topLevel);
topLevel.show();
qApp->setActiveWindow(&topLevel);
- QVERIFY(QTest::qWaitForWindowActive(&topLevel));
+ QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
QTRY_VERIFY(topLevel.numPaintEvents > 0);
topLevel.reset();
@@ -9104,7 +9200,7 @@ void tst_QWidget::syntheticEnterLeave()
void tst_QWidget::taskQTBUG_4055_sendSyntheticEnterLeave()
{
if (m_platform == QStringLiteral("wayland"))
- QSKIP("Wayland: This fails. Figure out why.");
+ QSKIP("Wayland: Clients can't set cursor position on wayland.");
class SELParent : public QWidget
{
public:
@@ -9122,7 +9218,8 @@ void tst_QWidget::taskQTBUG_4055_sendSyntheticEnterLeave()
void mouseMoveEvent(QMouseEvent *event)
{
QCOMPARE(event->button(), Qt::NoButton);
- QCOMPARE(event->buttons(), Qt::MouseButtons(Qt::NoButton));
+ QCOMPARE(event->buttons(), QApplication::mouseButtons());
+ QCOMPARE(event->modifiers(), QApplication::keyboardModifiers());
++numMouseMoveEvents;
}
void reset() { numEnterEvents = numMouseMoveEvents = 0; }
@@ -9156,11 +9253,11 @@ void tst_QWidget::taskQTBUG_4055_sendSyntheticEnterLeave()
child.setMouseTracking(true);
child.show();
- // Make sure the child gets enter event and mouse move event.
+ // Make sure the child gets enter event.
// Note that we verify event->button() and event->buttons()
// in SELChild::mouseMoveEvent().
QTRY_COMPARE(child.numEnterEvents, 1);
- QCOMPARE(child.numMouseMoveEvents, 1);
+ QCOMPARE(child.numMouseMoveEvents, 0);
// Sending synthetic enter/leave trough the parent's mousePressEvent handler.
parent.child = &child;
@@ -9169,12 +9266,21 @@ void tst_QWidget::taskQTBUG_4055_sendSyntheticEnterLeave()
child.reset();
QTest::mouseClick(&parent, Qt::LeftButton);
- // Make sure the child gets enter event and one mouse move event.
+ // Make sure the child gets enter event.
QTRY_COMPARE(child.numEnterEvents, 1);
- QCOMPARE(child.numMouseMoveEvents, 1);
+ QCOMPARE(child.numMouseMoveEvents, 0);
child.hide();
child.reset();
+ QTest::keyPress(&parent, Qt::Key_Shift);
+ QTest::mouseClick(&parent, Qt::LeftButton);
+
+ // Make sure the child gets enter event
+ QTRY_COMPARE(child.numEnterEvents, 1);
+ QCOMPARE(child.numMouseMoveEvents, 0);
+ QTest::keyRelease(&child, Qt::Key_Shift);
+ child.hide();
+ child.reset();
child.setMouseTracking(false);
QTest::mouseClick(&parent, Qt::LeftButton);
@@ -9351,6 +9457,8 @@ void tst_QWidget::rectOutsideCoordinatesLimit_task144779()
correct.fill(Qt::green);
const QPixmap mainPixmap = grabFromWidget(&main, QRect(QPoint(0, 0), QSize(-1, -1)));
+ if (m_platform == QStringLiteral("winrt"))
+ QEXPECT_FAIL("", "WinRT: This fails. QTBUG-68297.", Abort);
QTRY_COMPARE(mainPixmap.toImage().convertToFormat(QImage::Format_RGB32),
correct.toImage().convertToFormat(QImage::Format_RGB32));
#ifndef QT_NO_CURSOR
@@ -9442,6 +9550,8 @@ void tst_QWidget::activateWindow()
qApp->processEvents();
QTRY_VERIFY(mainwindow->isActiveWindow());
+ if (m_platform == QStringLiteral("winrt"))
+ QEXPECT_FAIL("", "WinRT: This fails. QTBUG-68297.", Abort);
QTRY_VERIFY(!mainwindow2->isActiveWindow());
}
@@ -9960,9 +10070,6 @@ public:
void tst_QWidget::touchEventSynthesizedMouseEvent()
{
- if (m_platform == QStringLiteral("wayland"))
- QSKIP("Wayland: This fails. Figure out why.");
-
{
// Simple case, we ignore the touch events, we get mouse events instead
TouchMouseWidget widget;
@@ -10544,7 +10651,7 @@ void tst_QWidget::keyboardModifiers()
KeyboardWidget w;
w.resize(300, 300);
w.show();
- QVERIFY(QTest::qWaitForWindowActive(&w));
+ QVERIFY(QTest::qWaitForWindowExposed(&w));
QTest::mouseClick(&w, Qt::LeftButton, Qt::ControlModifier);
QCOMPARE(w.m_eventCounter, 1);
QCOMPARE(int(w.m_modifiers), int(Qt::ControlModifier));
@@ -10605,6 +10712,8 @@ void tst_QWidget::resizeStaticContentsChildWidget_QTBUG35282()
widget.showNormal();
QVERIFY(QTest::qWaitForWindowExposed(&widget));
+ if (m_platform == QStringLiteral("winrt"))
+ QEXPECT_FAIL("", "WinRT: This fails. QTBUG-68297.", Abort);
QCOMPARE(childWidget.numPaintEvents, 0);
childWidget.reset();
diff --git a/tests/auto/widgets/kernel/qwidget_window/BLACKLIST b/tests/auto/widgets/kernel/qwidget_window/BLACKLIST
index d3bfaba433..c980325d9a 100644
--- a/tests/auto/widgets/kernel/qwidget_window/BLACKLIST
+++ b/tests/auto/widgets/kernel/qwidget_window/BLACKLIST
@@ -2,3 +2,6 @@
# QTBUG-66345
opensuse-42.3
ubuntu-16.04
+ubuntu-18.04
+[setWindowState]
+ubuntu-18.04
diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
index b143555b0d..f4da4c3e5f 100644
--- a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
+++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
@@ -44,6 +44,8 @@
#include <qmainwindow.h>
#include <qtoolbar.h>
#include <private/qwindow_p.h>
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformintegration.h>
#include <QtTest/private/qtesthelpers_p.h>
@@ -79,10 +81,12 @@ private slots:
void tst_showWithoutActivating();
void tst_paintEventOnSecondShow();
+ void tst_exposeObscuredMapped_QTBUG39220();
void tst_paintEventOnResize_QTBUG50796();
#if QT_CONFIG(draganddrop)
void tst_dnd();
+ void tst_dnd_events();
#endif
void tst_qtbug35600();
@@ -156,6 +160,9 @@ void tst_QWidget_window::tst_move_show()
QWidget w;
w.move(100, 100);
w.show();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Winrt does not support move", Abort);
+#endif
QCOMPARE(w.pos(), QPoint(100, 100));
// QCoreApplication::processEvents(QEventLoop::AllEvents, 3000);
}
@@ -185,6 +192,9 @@ void tst_QWidget_window::tst_resize_show()
QWidget w;
w.resize(200, 200);
w.show();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Winrt does not support resize", Abort);
+#endif
QCOMPARE(w.size(), QSize(200, 200));
// QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
}
@@ -370,6 +380,33 @@ void tst_QWidget_window::tst_paintEventOnSecondShow()
QTRY_VERIFY(w.paintEventCount > 0);
}
+void tst_QWidget_window::tst_exposeObscuredMapped_QTBUG39220()
+{
+ const auto integration = QGuiApplicationPrivate::platformIntegration();
+ if (!integration->hasCapability(QPlatformIntegration::MultipleWindows)
+ || !integration->hasCapability(QPlatformIntegration::NonFullScreenWindows)
+ || QGuiApplication::platformName() == QLatin1String("winrt")) {
+ QSKIP("The platform does not have the required capabilities");
+ }
+ // QTBUG-39220: Fully obscured parent widgets may not receive expose
+ // events (as is the case for frameless, obscured parents on Windows).
+ // Ensure Qt::WA_Mapped is set so updating works.
+ const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry();
+ const QSize size = availableGeometry.size() / 6;
+ QWidget topLevel;
+ setFrameless(&topLevel);
+ topLevel.resize(size);
+ const QPoint sizeP(size.width(), size.height());
+ topLevel.move(availableGeometry.center() - sizeP / 2);
+ QWidget *child = new QWidget(&topLevel);
+ child->resize(size);
+ child->move(0, 0);
+ QVERIFY(child->winId());
+ topLevel.show();
+ QTRY_VERIFY(child->testAttribute(Qt::WA_Mapped));
+ QVERIFY(topLevel.testAttribute(Qt::WA_Mapped));
+}
+
void tst_QWidget_window::tst_paintEventOnResize_QTBUG50796()
{
const QRect availableGeo = QGuiApplication::primaryScreen()->availableGeometry();
@@ -416,6 +453,7 @@ static const char *expectedLogC[] = {
"Event at 11,81 ignored",
"Event at 11,101 ignored",
"acceptingDropsWidget1::dragEnterEvent at 1,11 action=1 MIME_DATA_ADDRESS 'testmimetext'",
+ "acceptingDropsWidget1::dragMoveEvent at 1,11 action=1 MIME_DATA_ADDRESS 'testmimetext'",
"Event at 11,121 accepted",
"acceptingDropsWidget1::dragMoveEvent at 1,31 action=1 MIME_DATA_ADDRESS 'testmimetext'",
"Event at 11,141 accepted",
@@ -426,6 +464,7 @@ static const char *expectedLogC[] = {
"acceptingDropsWidget1::dragLeaveEvent QDragLeaveEvent",
"Event at 11,201 ignored",
"acceptingDropsWidget2::dragEnterEvent at 1,11 action=1 MIME_DATA_ADDRESS 'testmimetext'",
+ "acceptingDropsWidget2::dragMoveEvent at 1,11 action=1 MIME_DATA_ADDRESS 'testmimetext'",
"Event at 11,221 accepted",
"acceptingDropsWidget2::dragMoveEvent at 1,31 action=1 MIME_DATA_ADDRESS 'testmimetext'",
"Event at 11,241 accepted",
@@ -591,6 +630,92 @@ void tst_QWidget_window::tst_dnd()
QCOMPARE(log, expectedLog);
}
+
+class DnDEventRecorder : public QWidget
+{
+ Q_OBJECT
+public:
+ QString _dndEvents;
+ DnDEventRecorder() { setAcceptDrops(true); }
+
+protected:
+ void mousePressEvent(QMouseEvent *)
+ {
+ QMimeData *mimeData = new QMimeData;
+ mimeData->setData("application/x-dnditemdata", "some data");
+ QDrag *drag = new QDrag(this);
+ drag->setMimeData(mimeData);
+ drag->exec();
+ }
+
+ void dragEnterEvent(QDragEnterEvent *e)
+ {
+ e->accept();
+ _dndEvents.append(QStringLiteral("DragEnter "));
+ }
+ void dragMoveEvent(QDragMoveEvent *e)
+ {
+ e->accept();
+ _dndEvents.append(QStringLiteral("DragMove "));
+ emit releaseMouseButton();
+ }
+ void dragLeaveEvent(QDragLeaveEvent *e)
+ {
+ e->accept();
+ _dndEvents.append(QStringLiteral("DragLeave "));
+ }
+ void dropEvent(QDropEvent *e)
+ {
+ e->accept();
+ _dndEvents.append(QStringLiteral("DropEvent "));
+ }
+
+signals:
+ void releaseMouseButton();
+};
+
+void tst_QWidget_window::tst_dnd_events()
+{
+ // Note: This test is somewhat a hack as testing DnD with qtestlib is not
+ // supported at the moment. The test verifies that we get an expected event
+ // sequence on dnd operation that does not move a mouse. This logic is implemented
+ // in QGuiApplication, so we have to go via QWindowSystemInterface API (QTest::mouse*).
+ const auto platformName = QGuiApplication::platformName().toLower();
+ // The test is known to work with XCB and platforms that use the default dnd
+ // implementation QSimpleDrag (e.g. qnx). Running on XCB should be sufficient to
+ // catch regressions at cross platform code: QGuiApplication::processDrag/Leave().
+ if (platformName != "xcb")
+ return;
+
+ const QString expectedDndEvents = "DragEnter DragMove DropEvent DragEnter DragMove "
+ "DropEvent DragEnter DragMove DropEvent ";
+ DnDEventRecorder dndWidget;
+ dndWidget.setGeometry(100, 100, 200, 200);
+ dndWidget.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&dndWidget));
+ QVERIFY(QTest::qWaitForWindowActive(&dndWidget));
+
+ // ### FIXME - QTBUG-35117 ???
+ auto targetCenter = QPoint(dndWidget.width(), dndWidget.height()) / 2;
+ auto targetCenterGlobal = dndWidget.mapToGlobal(targetCenter);
+ QCursor::setPos(targetCenterGlobal);
+ QVERIFY(QTest::qWaitFor([&]() { return QCursor::pos() == targetCenterGlobal; }));
+ QCoreApplication::processEvents(); // clear mouse events generated from cursor
+
+ auto window = dndWidget.window()->windowHandle();
+
+ // Some dnd implementation rely on running internal event loops, so we have to use
+ // the following queued signal hack to simulate mouse clicks in the widget.
+ QObject::connect(&dndWidget, &DnDEventRecorder::releaseMouseButton, this, [=]() {
+ QTest::mouseRelease(window, Qt::LeftButton);
+ }, Qt::QueuedConnection);
+
+ QTest::mousePress(window, Qt::LeftButton);
+ QTest::mousePress(window, Qt::LeftButton);
+ QTest::mousePress(window, Qt::LeftButton);
+
+ QCOMPARE(dndWidget._dndEvents, expectedDndEvents);
+}
#endif
void tst_QWidget_window::tst_qtbug35600()
@@ -704,6 +829,9 @@ void tst_QWidget_window::tst_resize_count()
ResizeWidget resize;
resize.show();
QVERIFY(QTest::qWaitForWindowExposed(&resize));
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Winrt does not support resize", Abort);
+#endif
QCOMPARE(resize.resizeCount, 1);
resize.resizeCount = 0;
QSize size = resize.size();
@@ -901,6 +1029,11 @@ void tst_QWidget_window::setWindowState()
w.setWindowState(state);
QCOMPARE(w.windowState(), state);
w.show();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("0", "Winrt windows are maximized by default", Abort);
+ QEXPECT_FAIL("Qt::WindowMinimized", "Winrt windows are maximized by default", Abort);
+ QEXPECT_FAIL("Qt::WindowFullScreen", "Winrt windows are maximized by default", Abort);
+#endif
QCOMPARE(w.windowState(), state);
QCOMPARE(w.windowHandle()->windowStates(), state);
if (!(state & Qt::WindowMinimized))
diff --git a/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp b/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp
index c9c8e193b3..693a792f0a 100644
--- a/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp
+++ b/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp
@@ -104,6 +104,9 @@ void tst_QWindowContainer::testShow()
root.show();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Fails on WinRT - QTBUG-68297", Abort);
+#endif
QVERIFY(QTest::qWaitForWindowExposed(window));
}
@@ -140,6 +143,9 @@ void tst_QWindowContainer::testExposeObscure()
container->show();
QVERIFY(QTest::qWaitForWindowExposed(container.data()));
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Fails on WinRT - QTBUG-68297", Abort);
+#endif
QVERIFY(QTest::qWaitForWindowExposed(window));
QVERIFY(window->numberOfExposes > 0);
@@ -255,6 +261,9 @@ void tst_QWindowContainer::testUnparentReparent()
QTRY_VERIFY(!window->isVisible());
container->show();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Fails on WinRT - QTBUG-68297", Abort);
+#endif
QVERIFY(QTest::qWaitForWindowExposed(window));
QTRY_VERIFY(window->isVisible());
@@ -359,6 +368,9 @@ void tst_QWindowContainer::testNativeContainerParent()
root.show();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Fails on WinRT - QTBUG-68297", Abort);
+#endif
QVERIFY(QTest::qWaitForWindowExposed(window));
QTRY_COMPARE(window->parent(), container->windowHandle());
}
diff --git a/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp b/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp
index e49fd701d6..587e8a080d 100644
--- a/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp
+++ b/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp
@@ -82,7 +82,7 @@ private slots:
void testFusionStyle();
#endif
void testWindowsStyle();
-#if defined(Q_OS_WIN) && !defined(QT_NO_STYLE_WINDOWSVISTA)
+#if defined(Q_OS_WIN) && !defined(QT_NO_STYLE_WINDOWSVISTA) && !defined(Q_OS_WINRT)
void testWindowsVistaStyle();
#endif
#ifdef Q_OS_MAC
@@ -198,6 +198,9 @@ void tst_QStyle::drawItemPixmap()
QVERIFY(image.reinterpretAsFormat(QImage::Format_RGB32));
const QRgb *bits = reinterpret_cast<const QRgb *>(image.constBits());
const QRgb *end = bits + image.byteCount() / sizeof(QRgb);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "QWidget::resize does not work on WinRT", Continue);
+#endif
QVERIFY(std::all_of(bits, end, [green] (QRgb r) { return r == green; }));
testWidget->hide();
}
@@ -344,7 +347,7 @@ QImage readImage(const QString &fileName)
}
-#if defined(Q_OS_WIN) && !defined(QT_NO_STYLE_WINDOWSVISTA)
+#if defined(Q_OS_WIN) && !defined(QT_NO_STYLE_WINDOWSVISTA) && !defined(Q_OS_WINRT)
void tst_QStyle::testWindowsVistaStyle()
{
QStyle *vistastyle = QStyleFactory::create("WindowsVista");
@@ -716,6 +719,9 @@ void tst_QStyle::testFrameOnlyAroundContents()
area.verticalScrollBar()->setStyle(&frameStyle);
area.setStyle(&frameStyle);
// Test that we reserve space for scrollbar spacing
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "QWidget::setGeometry does not work on WinRT", Continue);
+#endif
QVERIFY(viewPortWidth == area.viewport()->width() + SCROLLBAR_SPACING);
delete winStyle;
}
diff --git a/tests/auto/widgets/styles/qstylesheetstyle/images/testimage.png b/tests/auto/widgets/styles/qstylesheetstyle/images/testimage.png
index 06fb34f0d6..a4adc7a47f 100644
--- a/tests/auto/widgets/styles/qstylesheetstyle/images/testimage.png
+++ b/tests/auto/widgets/styles/qstylesheetstyle/images/testimage.png
Binary files differ
diff --git a/tests/auto/widgets/styles/qstylesheetstyle/images/testimage@2x.png b/tests/auto/widgets/styles/qstylesheetstyle/images/testimage@2x.png
new file mode 100644
index 0000000000..d55f0c507b
--- /dev/null
+++ b/tests/auto/widgets/styles/qstylesheetstyle/images/testimage@2x.png
Binary files differ
diff --git a/tests/auto/widgets/styles/qstylesheetstyle/resources.qrc b/tests/auto/widgets/styles/qstylesheetstyle/resources.qrc
index 248bf80f50..f523070073 100644
--- a/tests/auto/widgets/styles/qstylesheetstyle/resources.qrc
+++ b/tests/auto/widgets/styles/qstylesheetstyle/resources.qrc
@@ -2,5 +2,6 @@
<RCC version="1.0">
<qresource>
<file>images/testimage.png</file>
+ <file>images/testimage@2x.png</file>
</qresource>
</RCC> \ No newline at end of file
diff --git a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
index 6d47d5cfb6..f5d9433f70 100644
--- a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
+++ b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp
@@ -33,6 +33,7 @@
#include <QMetaObject>
#include <private/qstylesheetstyle_p.h>
+#include <private/qhighdpiscaling_p.h>
#include <QtTest/private/qtesthelpers_p.h>
using namespace QTestPrivate;
@@ -98,7 +99,12 @@ private slots:
void widgetStyle();
void appStyle();
void QTBUG11658_cachecrash();
+ void styleSheetTargetAttribute();
void unpolish();
+
+ void highdpiImages_data();
+ void highdpiImages();
+
private:
QColor COLOR(const QWidget& w) {
w.ensurePolished();
@@ -2000,6 +2006,59 @@ void tst_QStyleSheetStyle::widgetStylePropagation()
QCOMPARE(COLOR(childLabel), childExpectedColor);
}
+void tst_QStyleSheetStyle::styleSheetTargetAttribute()
+{
+ QGroupBox gb;
+ QLabel lb(&gb);
+ QPushButton pb(&lb);
+
+ gb.ensurePolished(); lb.ensurePolished(); pb.ensurePolished();
+ QCOMPARE(gb.testAttribute(Qt::WA_StyleSheetTarget), false);
+ QCOMPARE(lb.testAttribute(Qt::WA_StyleSheetTarget), false);
+ QCOMPARE(pb.testAttribute(Qt::WA_StyleSheetTarget), false);
+
+ qApp->setStyleSheet("QPushButton { background-color: blue; }");
+
+ gb.ensurePolished(); lb.ensurePolished(); pb.ensurePolished();
+ QCOMPARE(gb.testAttribute(Qt::WA_StyleSheetTarget), false);
+ QCOMPARE(lb.testAttribute(Qt::WA_StyleSheetTarget), false);
+ QCOMPARE(pb.testAttribute(Qt::WA_StyleSheetTarget), true);
+
+ qApp->setStyleSheet("QGroupBox { background-color: blue; }");
+
+ gb.ensurePolished(); lb.ensurePolished(); pb.ensurePolished();
+ QCOMPARE(gb.testAttribute(Qt::WA_StyleSheetTarget), true);
+ QCOMPARE(lb.testAttribute(Qt::WA_StyleSheetTarget), false);
+ QCOMPARE(pb.testAttribute(Qt::WA_StyleSheetTarget), false);
+
+ qApp->setStyleSheet("QGroupBox * { background-color: blue; }");
+
+ gb.ensurePolished(); lb.ensurePolished(); pb.ensurePolished();
+ QCOMPARE(gb.testAttribute(Qt::WA_StyleSheetTarget), false);
+ QCOMPARE(lb.testAttribute(Qt::WA_StyleSheetTarget), true);
+ QCOMPARE(pb.testAttribute(Qt::WA_StyleSheetTarget), true);
+
+ qApp->setStyleSheet("* { background-color: blue; }");
+ gb.ensurePolished(); lb.ensurePolished(); pb.ensurePolished();
+ QCOMPARE(gb.testAttribute(Qt::WA_StyleSheetTarget), true);
+ QCOMPARE(lb.testAttribute(Qt::WA_StyleSheetTarget), true);
+ QCOMPARE(pb.testAttribute(Qt::WA_StyleSheetTarget), true);
+
+ qApp->setStyleSheet("QLabel { font-size: 32pt; }");
+
+ gb.ensurePolished(); lb.ensurePolished(); pb.ensurePolished();
+ QCOMPARE(gb.testAttribute(Qt::WA_StyleSheetTarget), false);
+ QCOMPARE(lb.testAttribute(Qt::WA_StyleSheetTarget), true);
+ QCOMPARE(pb.testAttribute(Qt::WA_StyleSheetTarget), false);
+
+ qApp->setStyleSheet("");
+
+ gb.ensurePolished(); lb.ensurePolished(); pb.ensurePolished();
+ QCOMPARE(gb.testAttribute(Qt::WA_StyleSheetTarget), false);
+ QCOMPARE(lb.testAttribute(Qt::WA_StyleSheetTarget), false);
+ QCOMPARE(pb.testAttribute(Qt::WA_StyleSheetTarget), false);
+}
+
void tst_QStyleSheetStyle::unpolish()
{
QWidget w;
@@ -2011,6 +2070,35 @@ void tst_QStyleSheetStyle::unpolish()
QCOMPARE(w.minimumWidth(), 0);
}
+void tst_QStyleSheetStyle::highdpiImages_data()
+{
+ QTest::addColumn<qreal>("screenFactor");
+ QTest::addColumn<QColor>("color");
+
+ QTest::newRow("highdpi") << 2.0 << QColor(0x00, 0xFF, 0x00);
+ QTest::newRow("lowdpi") << 1.0 << QColor(0xFF, 0x00, 0x00);
+}
+
+void tst_QStyleSheetStyle::highdpiImages()
+{
+ QFETCH(qreal, screenFactor);
+ QFETCH(QColor, color);
+
+ QWidget w;
+ QScreen *screen = QGuiApplication::screenAt(w.pos());
+ QHighDpiScaling::setScreenFactor(screen, screenFactor);
+ w.setStyleSheet("QWidget { background-image: url(\":/images/testimage.png\"); }");
+ w.show();
+
+ QVERIFY(QTest::qWaitForWindowExposed(&w));
+ QImage image(w.size(), QImage::Format_ARGB32);
+ w.render(&image);
+ QVERIFY(testForColors(image, color));
+
+ QHighDpiScaling::setScreenFactor(screen, 1.0);
+ QHighDpiScaling::updateHighDpiScaling(); // reset to normal
+}
+
QTEST_MAIN(tst_QStyleSheetStyle)
#include "tst_qstylesheetstyle.moc"
diff --git a/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp b/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp
index 0511c278d5..ad64f1aef7 100644
--- a/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp
+++ b/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp
@@ -621,6 +621,9 @@ void tst_QCompleter::directoryModel_data()
void tst_QCompleter::directoryModel()
{
+#ifdef Q_OS_WINRT
+ QSKIP("WinRT cannot access directories outside of the application's sandbox");
+#endif
filter();
}
@@ -667,6 +670,9 @@ void tst_QCompleter::fileSystemModel_data()
void tst_QCompleter::fileSystemModel()
{
+#ifdef Q_OS_WINRT
+ QSKIP("WinRT cannot access directories outside of the application's sandbox");
+#endif
//QFileSystemModel is assync.
filter(true);
}
@@ -1696,6 +1702,9 @@ void tst_QCompleter::QTBUG_14292_filesystem()
// Wait for all file system model slots/timers to trigger
// until the model sees the subdirectories.
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Fails on WinRT - QTBUG-68297", Abort);
+#endif
QTRY_VERIFY(testFileSystemReady(model));
// But this should not cause the combo to pop up.
QVERIFY(!comp.popup()->isVisible());
diff --git a/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp b/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp
index 372a467ada..007825d39c 100644
--- a/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp
+++ b/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp
@@ -334,6 +334,10 @@ void tst_QAbstractScrollArea::task214488_layoutDirection()
int refValue = hbar->value();
qApp->sendEvent(&scrollArea, new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier));
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "WinRT: Scrollbar is not guaranteed to be visible, as QWidget::resize does not"
+ "work", Abort);
+#endif
QVERIFY(lessThan ? (hbar->value() < refValue) : (hbar->value() > refValue));
}
diff --git a/tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp b/tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp
index 5c0f4b1536..312ec0b1ec 100644
--- a/tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp
+++ b/tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp
@@ -153,6 +153,9 @@ void tst_QCalendarWidget::getSetCheck()
void tst_QCalendarWidget::buttonClickCheck()
{
+#ifdef Q_OS_WINRT
+ QSKIP("Fails on WinRT - QTBUG-68297");
+#endif
QCalendarWidget object;
QSize size = object.sizeHint();
object.setGeometry(0,0,size.width(), size.height());
@@ -283,6 +286,10 @@ void tst_QCalendarWidget::showPrevNext()
QFETCH(QDate, dateOrigin);
QFETCH(QDate, expectedDate);
+#ifdef Q_OS_WINRT
+ QSKIP("Fails on WinRT - QTBUG-68297");
+#endif
+
QCalendarWidget calWidget;
calWidget.show();
QVERIFY(QTest::qWaitForWindowExposed(&calWidget));
diff --git a/tests/auto/widgets/widgets/qcombobox/qcombobox.pro b/tests/auto/widgets/widgets/qcombobox/qcombobox.pro
index 939153dc88..ba25a85634 100644
--- a/tests/auto/widgets/widgets/qcombobox/qcombobox.pro
+++ b/tests/auto/widgets/widgets/qcombobox/qcombobox.pro
@@ -1,4 +1,7 @@
CONFIG += testcase
TARGET = tst_qcombobox
QT += widgets widgets-private gui-private core-private testlib testlib-private
+DEFINES += QTEST_QPA_MOUSE_HANDLING
SOURCES += tst_qcombobox.cpp
+
+TESTDATA += qtlogo.png qtlogoinverted.png
diff --git a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
index 7c1deb8fff..943fb997cd 100644
--- a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
+++ b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
@@ -1672,6 +1672,9 @@ void tst_QComboBox::setCustomModelAndView()
const QRect subItemRect = view->visualRect(model->indexFromItem(subItem));
QWidget *window = view->window();
QTest::mouseClick(window->windowHandle(), Qt::LeftButton, 0, view->mapTo(window, subItemRect.center()));
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Fails on WinRT - QTBUG-68297", Abort);
+#endif
QTRY_COMPARE(combo.currentText(), subItem21Text);
}
@@ -2188,8 +2191,8 @@ void tst_QComboBox::itemListPosition()
if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
useFullScreenForPopupMenu = theme->themeHint(QPlatformTheme::UseFullScreenForPopupMenu).toBool();
const QRect screen = useFullScreenForPopupMenu ?
- QApplication::desktop()->screenGeometry(scrNumber) :
- QApplication::desktop()->availableGeometry(scrNumber);
+ QApplication::screens().at(scrNumber)->geometry() :
+ QApplication::screens().at(scrNumber)->availableGeometry();
topLevel.move(screen.width() - topLevel.sizeHint().width() - 10, 0); //puts the combo to the top-right corner
@@ -2311,7 +2314,7 @@ void tst_QComboBox::task191329_size()
setFrameless(&tableCombo);
tableCombo.move(200, 200);
int rows;
- if (QApplication::desktop()->screenGeometry().height() < 480)
+ if (QApplication::primaryScreen()->geometry().height() < 480)
rows = 8;
else
rows = 15;
@@ -2376,6 +2379,9 @@ void tst_QComboBox::task190205_setModelAdjustToContents()
correctBox.addItems(finalContent);
correctBox.showNormal();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "WinRT does not support more than 1 native top level widget", Abort);
+#endif
QVERIFY(QTest::qWaitForWindowExposed(&box));
QVERIFY(QTest::qWaitForWindowExposed(&correctBox));
@@ -2390,8 +2396,7 @@ void tst_QComboBox::task248169_popupWithMinimalSize()
QComboBox comboBox;
comboBox.addItems(initialContent);
- QDesktopWidget desktop;
- QRect desktopSize = desktop.availableGeometry();
+ QRect desktopSize = QGuiApplication::primaryScreen()->availableGeometry();
comboBox.view()->setMinimumWidth(desktopSize.width() / 2);
comboBox.setGeometry(desktopSize.width() - (desktopSize.width() / 4), (desktopSize.width() / 4), (desktopSize.width() / 2), (desktopSize.width() / 4));
@@ -2407,6 +2412,7 @@ void tst_QComboBox::task248169_popupWithMinimalSize()
#if defined QT_BUILD_INTERNAL
QFrame *container = comboBox.findChild<QComboBoxPrivateContainer *>();
QVERIFY(container);
+ QDesktopWidget desktop;
QTRY_VERIFY(desktop.screenGeometry(container).contains(container->geometry()));
#endif
}
@@ -2719,32 +2725,18 @@ void tst_QComboBox::resetModel()
}
-static inline void centerCursor(const QWidget *w)
-{
-#ifndef QT_NO_CURSOR
- // Force cursor movement to prevent QCursor::setPos() from returning prematurely on QPA:
- const QPoint target(w->mapToGlobal(w->rect().center()));
- QCursor::setPos(QPoint(target.x() + 1, target.y()));
- QCursor::setPos(target);
-#else // !QT_NO_CURSOR
- Q_UNUSED(w)
-#endif
-}
-
void tst_QComboBox::keyBoardNavigationWithMouse()
{
QComboBox combo;
combo.setEditable(false);
setFrameless(&combo);
- combo.move(200, 200);
- for (int i = 0; i < 80; i++)
- combo.addItem( QString::number(i));
+ for (int i = 0; i < 200; i++)
+ combo.addItem(QString::number(i));
+ combo.move(200, 200);
combo.showNormal();
- centerCursor(&combo); // QTBUG-33973, cursor needs to be within view from start on Mac.
QApplication::setActiveWindow(&combo);
QVERIFY(QTest::qWaitForWindowActive(&combo));
- QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&combo));
QCOMPARE(combo.currentText(), QLatin1String("0"));
@@ -2752,18 +2744,12 @@ void tst_QComboBox::keyBoardNavigationWithMouse()
QTRY_VERIFY(combo.hasFocus());
QTest::keyClick(combo.lineEdit(), Qt::Key_Space);
- QTest::qWait(30);
QTRY_VERIFY(combo.view());
QTRY_VERIFY(combo.view()->isVisible());
- QTest::qWait(130);
QCOMPARE(combo.currentText(), QLatin1String("0"));
- // When calling cursor function, Windows CE responds with: This function is not supported on this system.
-#if !defined Q_OS_QNX
- // Force cursor movement to prevent QCursor::setPos() from returning prematurely on QPA:
- centerCursor(combo.view());
- QTest::qWait(200);
+ QTest::mouseMove(&combo, combo.rect().center());
#define GET_SELECTION(SEL) \
QCOMPARE(combo.view()->selectionModel()->selection().count(), 1); \
@@ -2771,23 +2757,19 @@ void tst_QComboBox::keyBoardNavigationWithMouse()
SEL = combo.view()->selectionModel()->selection().indexes().first().row()
int selection;
- GET_SELECTION(selection);
+ GET_SELECTION(selection); // get initial selection
- //since we moved the mouse is in the middle it should even be around 5;
- QVERIFY2(selection > 3, (QByteArrayLiteral("selection=") + QByteArray::number(selection)).constData());
-
- static const int final = 40;
+ const int final = 40;
for (int i = selection + 1; i <= final; i++)
{
QTest::keyClick(combo.view(), Qt::Key_Down);
- QTest::qWait(20);
GET_SELECTION(selection);
QCOMPARE(selection, i);
}
QTest::keyClick(combo.view(), Qt::Key_Enter);
QTRY_COMPARE(combo.currentText(), QString::number(final));
-#endif
+#undef GET_SELECTION
}
void tst_QComboBox::task_QTBUG_1071_changingFocusEmitsActivated()
@@ -3334,6 +3316,9 @@ void tst_QComboBox::task_QTBUG_56693_itemFontFromModel()
QVERIFY(container);
QVERIFY(QTest::qWaitForWindowExposed(container));
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Fails on WinRT - QTBUG-68297", Abort);
+#endif
QCOMPARE(proxyStyle->italicItemsNo, 5);
box.hidePopup();
diff --git a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp
index fa28ec2575..20aad6ba97 100644
--- a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp
+++ b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp
@@ -70,6 +70,7 @@
#include <QSignalSpy>
#include <QTestEventList>
#include <QDateEdit>
+#include <QProxyStyle>
#include <private/qdatetimeedit_p.h>
@@ -93,6 +94,46 @@ public:
friend class tst_QDateTimeEdit;
};
+class PressAndHoldStyle : public QProxyStyle
+{
+ Q_OBJECT
+public:
+ using QProxyStyle::QProxyStyle;
+
+ int styleHint(QStyle::StyleHint hint, const QStyleOption *option = nullptr,
+ const QWidget *widget = nullptr, QStyleHintReturn *returnData = nullptr) const override
+ {
+ switch (hint) {
+ case QStyle::SH_SpinBox_ClickAutoRepeatRate:
+ return 5;
+ case QStyle::SH_SpinBox_ClickAutoRepeatThreshold:
+ return 10;
+ default:
+ return QProxyStyle::styleHint(hint, option, widget, returnData);
+ }
+ }
+};
+
+class StepModifierStyle : public QProxyStyle
+{
+ Q_OBJECT
+public:
+ using QProxyStyle::QProxyStyle;
+
+ int styleHint(QStyle::StyleHint hint, const QStyleOption *option = nullptr,
+ const QWidget *widget = nullptr, QStyleHintReturn *returnData = nullptr) const override
+ {
+ switch (hint) {
+ case QStyle::SH_SpinBox_StepModifier:
+ return stepModifier;
+ default:
+ return QProxyStyle::styleHint(hint, option, widget, returnData);
+ }
+ }
+
+ Qt::KeyboardModifier stepModifier = Qt::ControlModifier;
+};
+
class tst_QDateTimeEdit : public QObject
{
Q_OBJECT
@@ -205,9 +246,8 @@ private slots:
void reverseTest();
void ddMMMMyyyy();
-#if QT_CONFIG(wheelevent)
+ void wheelEvent_data();
void wheelEvent();
-#endif
void specialValueCornerCase();
void cursorPositionOnInit();
@@ -245,14 +285,105 @@ private slots:
void dateEditCorrectSectionSize_data();
void dateEditCorrectSectionSize();
#endif
+
+ void stepModifierKeys_data();
+ void stepModifierKeys();
+
+ void stepModifierButtons_data();
+ void stepModifierButtons();
+
+ void stepModifierPressAndHold_data();
+ void stepModifierPressAndHold();
private:
EditorDateEdit* testWidget;
QWidget *testFocusWidget;
};
+typedef QList<QDate> DateList;
typedef QList<QTime> TimeList;
typedef QList<Qt::Key> KeyList;
+static QLatin1String modifierToName(Qt::KeyboardModifier modifier)
+{
+ switch (modifier) {
+ case Qt::NoModifier:
+ return QLatin1Literal("No");
+ break;
+ case Qt::ControlModifier:
+ return QLatin1Literal("Ctrl");
+ break;
+ case Qt::ShiftModifier:
+ return QLatin1Literal("Shift");
+ break;
+ case Qt::AltModifier:
+ return QLatin1Literal("Alt");
+ break;
+ case Qt::MetaModifier:
+ return QLatin1Literal("Meta");
+ break;
+ default:
+ qFatal("Unexpected keyboard modifier");
+ return QLatin1String();
+ }
+}
+
+static QLatin1String sectionToName(const QDateTimeEdit::Section section)
+{
+ switch (section) {
+ case QDateTimeEdit::SecondSection:
+ return QLatin1Literal("Second");
+ case QDateTimeEdit::MinuteSection:
+ return QLatin1Literal("Minute");
+ case QDateTimeEdit::HourSection:
+ return QLatin1Literal("Hours");
+ case QDateTimeEdit::DaySection:
+ return QLatin1Literal("Day");
+ case QDateTimeEdit::MonthSection:
+ return QLatin1Literal("Month");
+ case QDateTimeEdit::YearSection:
+ return QLatin1Literal("Year");
+ default:
+ qFatal("Unexpected section");
+ return QLatin1String();
+ }
+}
+
+static QDate stepDate(const QDate& startDate, const QDateTimeEdit::Section section,
+ const int steps)
+{
+ switch (section) {
+ case QDateTimeEdit::DaySection:
+ return startDate.addDays(steps);
+ case QDateTimeEdit::MonthSection:
+ return startDate.addMonths(steps);
+ case QDateTimeEdit::YearSection:
+ return startDate.addYears(steps);
+ default:
+ qFatal("Unexpected section");
+ return QDate();
+ }
+}
+
+static QTime stepTime(const QTime& startTime, const QDateTimeEdit::Section section,
+ const int steps)
+{
+ switch (section) {
+ case QDateTimeEdit::SecondSection:
+ return startTime.addSecs(steps);
+ case QDateTimeEdit::MinuteSection:
+ return QTime(startTime.hour(),
+ startTime.minute() + steps,
+ startTime.second());
+ case QDateTimeEdit::HourSection:
+ return QTime(startTime.hour() + steps,
+ startTime.minute(),
+ startTime.second());
+ default:
+ qFatal("Unexpected section");
+ return QTime();
+ }
+}
+
// Testing get/set functions
void tst_QDateTimeEdit::getSetCheck()
{
@@ -326,6 +457,8 @@ void tst_QDateTimeEdit::cleanup()
testWidget->setTimeSpec(Qt::LocalTime);
testWidget->setSpecialValueText(QString());
testWidget->setWrapping(false);
+ // Restore the default.
+ testWidget->setCalendarPopup(false);
}
void tst_QDateTimeEdit::constructor_qwidget()
@@ -3000,20 +3133,176 @@ void tst_QDateTimeEdit::ddMMMMyyyy()
QCOMPARE(testWidget->lineEdit()->text(), "01." + QDate::longMonthName(1) + ".200");
}
+void tst_QDateTimeEdit::wheelEvent_data()
+{
#if QT_CONFIG(wheelevent)
+ QTest::addColumn<QPoint>("angleDelta");
+ QTest::addColumn<int>("qt4Delta");
+ QTest::addColumn<int>("stepModifier");
+ QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
+ QTest::addColumn<Qt::MouseEventSource>("source");
+ QTest::addColumn<QDateTimeEdit::Section>("section");
+ QTest::addColumn<QDate>("startDate");
+ QTest::addColumn<DateList>("expectedDates");
+
+ const auto fractions = {false, true};
+
+ const auto directions = {true, false};
+
+ const auto modifierList = {Qt::NoModifier,
+ Qt::ShiftModifier,
+ Qt::ControlModifier,
+ Qt::AltModifier,
+ Qt::MetaModifier};
+
+ const auto validStepModifierList = {Qt::NoModifier,
+ Qt::ControlModifier,
+ Qt::ShiftModifier};
+
+ const auto sources = {Qt::MouseEventNotSynthesized,
+ Qt::MouseEventSynthesizedBySystem,
+ Qt::MouseEventSynthesizedByQt,
+ Qt::MouseEventSynthesizedByApplication};
+
+ const auto sections = {QDateTimeEdit::DaySection,
+ QDateTimeEdit::MonthSection,
+ QDateTimeEdit::YearSection};
+
+ for (auto fraction : fractions) {
+ for (auto up : directions) {
+
+ const QDate startDate(2000, up ? 2 : 12, 17);
+
+ const int units = (fraction ? 60 : 120) * (up ? 1 : -1);
+
+ for (auto modifier : modifierList) {
+
+ const Qt::KeyboardModifiers modifiers(modifier);
+
+ const auto modifierName = modifierToName(modifier);
+ if (modifierName.isEmpty())
+ continue;
+
+ for (auto stepModifier : validStepModifierList) {
+
+ const auto stepModifierName = modifierToName(stepModifier);
+ if (stepModifierName.isEmpty())
+ continue;
+
+ const int steps = (modifier & stepModifier ? 10 : 1)
+ * (up ? 1 : -1);
+
+ for (auto source : sources) {
+
+#ifdef Q_OS_MACOS
+ QPoint angleDelta;
+ if ((modifier & Qt::ShiftModifier) &&
+ source == Qt::MouseEventNotSynthesized) {
+ // On macOS the Shift modifier converts vertical
+ // mouse wheel events to horizontal.
+ angleDelta = { units, 0 };
+ } else {
+ // However, this is not the case for trackpad scroll
+ // events.
+ angleDelta = { 0, units };
+ }
+#else
+ const QPoint angleDelta(0, units);
+#endif
+
+ QLatin1String sourceName;
+ switch (source) {
+ case Qt::MouseEventNotSynthesized:
+ sourceName = QLatin1Literal("NotSynthesized");
+ break;
+ case Qt::MouseEventSynthesizedBySystem:
+ sourceName = QLatin1Literal("SynthesizedBySystem");
+ break;
+ case Qt::MouseEventSynthesizedByQt:
+ sourceName = QLatin1Literal("SynthesizedByQt");
+ break;
+ case Qt::MouseEventSynthesizedByApplication:
+ sourceName = QLatin1Literal("SynthesizedByApplication");
+ break;
+ default:
+ qFatal("Unexpected wheel event source");
+ continue;
+ }
+
+ for (const auto section : sections) {
+
+ DateList expectedDates;
+ if (fraction)
+ expectedDates << startDate;
+
+ const auto expectedDate = stepDate(startDate, section, steps);
+ if (!expectedDate.isValid())
+ continue;
+
+ expectedDates << expectedDate;
+
+ const QLatin1String sectionName = sectionToName(section);
+
+ QTest::addRow("%s%s%s%sWith%sKeyboardModifier%s",
+ fraction ? "half" : "full",
+ up ? "Up" : "Down",
+ stepModifierName.latin1(),
+ sectionName.latin1(),
+ modifierName.latin1(),
+ sourceName.latin1())
+ << angleDelta
+ << units
+ << static_cast<int>(stepModifier)
+ << modifiers
+ << source
+ << section
+ << startDate
+ << expectedDates;
+ }
+ }
+ }
+ }
+ }
+ }
+#else
+ QSKIP("Built with --no-feature-wheelevent");
+#endif
+}
+
void tst_QDateTimeEdit::wheelEvent()
{
- testWidget->setDisplayFormat("dddd/MM");
- testWidget->setDate(QDate(2000, 2, 21));
- testWidget->setCurrentSection(QDateTimeEdit::DaySection);
- QWheelEvent w(testWidget->lineEdit()->geometry().center(), 120, 0, 0);
- qApp->sendEvent(testWidget, &w);
- QCOMPARE(testWidget->date(), QDate(2000, 2, 22));
- testWidget->setCurrentSection(QDateTimeEdit::MonthSection);
- qApp->sendEvent(testWidget, &w);
- QCOMPARE(testWidget->date(), QDate(2000, 3, 22));
-}
+#if QT_CONFIG(wheelevent)
+ QFETCH(QPoint, angleDelta);
+ QFETCH(int, qt4Delta);
+ QFETCH(int, stepModifier);
+ QFETCH(Qt::KeyboardModifiers, modifiers);
+ QFETCH(Qt::MouseEventSource, source);
+ QFETCH(QDateTimeEdit::Section, section);
+ QFETCH(QDate, startDate);
+ QFETCH(DateList, expectedDates);
+
+ EditorDateEdit edit(0);
+ edit.setDate(startDate);
+ edit.setCurrentSection(section);
+
+ QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> style(
+ new StepModifierStyle);
+ style->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
+ edit.setStyle(style.data());
+
+ QWheelEvent event(QPointF(), QPointF(), QPoint(), angleDelta, qt4Delta,
+ Qt::Vertical, Qt::NoButton, modifiers, Qt::NoScrollPhase,
+ source);
+
+ QCOMPARE(edit.date(), startDate);
+ for (QDate expected : expectedDates) {
+ qApp->sendEvent(&edit, &event);
+ QCOMPARE(edit.date(), expected);
+ }
+#else
+ QSKIP("Built with --no-feature-wheelevent");
#endif // QT_CONFIG(wheelevent)
+}
void tst_QDateTimeEdit::specialValueCornerCase()
{
@@ -3559,7 +3848,7 @@ void tst_QDateTimeEdit::dateEditCorrectSectionSize_data()
<< threeDigitDayIssueKeypresses_DayName << QString::fromLatin1("00/2/Tuesday");
QTest::newRow("no fixday, leap, yy/M/ddd") << defaultLocale << defaultDate << QString::fromLatin1("yy/M/ddd")
- << threeDigitDayIssueKeypresses_DayName << QString::fromLatin1("00/2/Tue.");
+ << threeDigitDayIssueKeypresses_DayName << QString::fromLatin1("00/2/Tue");
QTest::newRow("no fixday, leap, yy/MM/dddd") << defaultLocale << defaultDate << QString::fromLatin1("yy/MM/dddd")
<< threeDigitDayIssueKeypresses_DayName << QString::fromLatin1("00/02/Tuesday");
@@ -3607,13 +3896,13 @@ void tst_QDateTimeEdit::dateEditCorrectSectionSize_data()
<< threeDigitDayIssueKeypresses_YearDayMonth << QString::fromLatin1("2000/29/2");
QTest::newRow("fixday, leap, yyyy/MMM/dd") << defaultLocale << defaultDate << QString::fromLatin1("yyyy/MMM/dd")
- << threeDigitDayIssueKeypresses_ShortMonthName << QString::fromLatin1("2000/Feb./29");
+ << threeDigitDayIssueKeypresses_ShortMonthName << QString::fromLatin1("2000/Feb/29");
QTest::newRow("fixday, leap, yyyy/MMM/d") << defaultLocale << defaultDate << QString::fromLatin1("yyyy/MMM/d")
- << threeDigitDayIssueKeypresses_ShortMonthName << QString::fromLatin1("2000/Feb./29");
+ << threeDigitDayIssueKeypresses_ShortMonthName << QString::fromLatin1("2000/Feb/29");
QTest::newRow("fixday, leap, yy/MMM/dd") << defaultLocale << defaultDate << QString::fromLatin1("yy/MMM/dd")
- << threeDigitDayIssueKeypresses_ShortMonthName << QString::fromLatin1("00/Feb./29");
+ << threeDigitDayIssueKeypresses_ShortMonthName << QString::fromLatin1("00/Feb/29");
QTest::newRow("fixday, leap, yyyy/dddd/M") << defaultLocale << defaultDate << QString::fromLatin1("yyyy/dddd/M")
<< threeDigitDayIssueKeypresses_DayName_YearDayMonth << QString::fromLatin1("2000/Tuesday/2");
@@ -3688,16 +3977,16 @@ void tst_QDateTimeEdit::dateEditCorrectSectionSize_data()
<< threeDigitDayIssueKeypresses_MonthYearDay << QString::fromLatin1("02/2000/29");
QTest::newRow("fixday, leap, MMM/yy/d") << defaultLocale << defaultDate << QString::fromLatin1("MMM/yy/d")
- << threeDigitDayIssueKeypresses_ShortMonthName_MonthYearDay << QString::fromLatin1("Feb./00/29");
+ << threeDigitDayIssueKeypresses_ShortMonthName_MonthYearDay << QString::fromLatin1("Feb/00/29");
QTest::newRow("fixday, leap, MMM/yyyy/d") << defaultLocale << defaultDate << QString::fromLatin1("MMM/yyyy/d")
- << threeDigitDayIssueKeypresses_ShortMonthName_MonthYearDay << QString::fromLatin1("Feb./2000/29");
+ << threeDigitDayIssueKeypresses_ShortMonthName_MonthYearDay << QString::fromLatin1("Feb/2000/29");
QTest::newRow("fixday, MMM/yyyy/d") << defaultLocale << defaultDate.addYears(1) << QString::fromLatin1("MMM/yyyy/d")
- << threeDigitDayIssueKeypresses_ShortMonthName_MonthYearDay << QString::fromLatin1("Feb./2001/28");
+ << threeDigitDayIssueKeypresses_ShortMonthName_MonthYearDay << QString::fromLatin1("Feb/2001/28");
QTest::newRow("fixday, leap, MMM/yyyy/dd") << defaultLocale << defaultDate << QString::fromLatin1("MMM/yyyy/dd")
- << threeDigitDayIssueKeypresses_ShortMonthName_MonthYearDay << QString::fromLatin1("Feb./2000/29");
+ << threeDigitDayIssueKeypresses_ShortMonthName_MonthYearDay << QString::fromLatin1("Feb/2000/29");
QTest::newRow("fixday, leap, dddd, dd. MMMM yyyy") << defaultLocale
<< defaultDate << QString::fromLatin1("dddd, dd. MMMM yyyy")
@@ -3735,5 +4024,308 @@ void tst_QDateTimeEdit::dateEditCorrectSectionSize()
}
#endif
+void tst_QDateTimeEdit::stepModifierKeys_data()
+{
+ QTest::addColumn<QDate>("startDate");
+ QTest::addColumn<int>("stepModifier");
+ QTest::addColumn<QDateTimeEdit::Section>("section");
+ QTest::addColumn<QTestEventList>("keys");
+ QTest::addColumn<QDate>("expectedDate");
+
+ const auto keyList = {Qt::Key_Up, Qt::Key_Down};
+
+ const auto modifierList = {Qt::NoModifier,
+ Qt::ShiftModifier,
+ Qt::ControlModifier,
+ Qt::AltModifier,
+ Qt::MetaModifier};
+
+ const auto validStepModifierList = {Qt::NoModifier,
+ Qt::ControlModifier,
+ Qt::ShiftModifier};
+
+ const auto sections = {QDateTimeEdit::DaySection,
+ QDateTimeEdit::MonthSection,
+ QDateTimeEdit::YearSection};
+
+ for (auto key : keyList) {
+
+ const bool up = key == Qt::Key_Up;
+ Q_ASSERT(up || key == Qt::Key_Down);
+
+ const QDate startDate(2000, up ? 2 : 12, 17);
+
+ for (auto modifier : modifierList) {
+
+ QTestEventList keys;
+ keys.addKeyClick(key, modifier);
+
+ const auto modifierName = modifierToName(modifier);
+ if (modifierName.isEmpty())
+ continue;
+
+ for (auto stepModifier : validStepModifierList) {
+
+ const auto stepModifierName = modifierToName(stepModifier);
+ if (stepModifierName.isEmpty())
+ continue;
+
+ const int steps = (modifier & stepModifier ? 10 : 1)
+ * (up ? 1 : -1);
+
+ for (const auto section : sections) {
+
+ const auto expectedDate = stepDate(startDate, section, steps);
+ if (!expectedDate.isValid())
+ continue;
+
+ const auto sectionName = sectionToName(section);
+
+ QTest::addRow("%s%s%sWith%sKeyboardModifier",
+ up ? "up" : "down",
+ stepModifierName.latin1(),
+ sectionName.latin1(),
+ modifierName.latin1())
+ << startDate
+ << static_cast<int>(stepModifier)
+ << section
+ << keys
+ << expectedDate;
+ }
+ }
+ }
+ }
+}
+
+void tst_QDateTimeEdit::stepModifierKeys()
+{
+ QFETCH(QDate, startDate);
+ QFETCH(int, stepModifier);
+ QFETCH(QDateTimeEdit::Section, section);
+ QFETCH(QTestEventList, keys);
+ QFETCH(QDate, expectedDate);
+
+ // This can interfere with our stuff.
+ testWidget->hide();
+
+ QDateTimeEdit edit(0);
+ edit.setDate(startDate);
+ edit.show();
+ QVERIFY(QTest::qWaitForWindowActive(&edit));
+ edit.setCurrentSection(section);
+
+ QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> style(
+ new StepModifierStyle);
+ style->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
+ edit.setStyle(style.data());
+
+ QCOMPARE(edit.date(), startDate);
+ keys.simulate(&edit);
+ QCOMPARE(edit.date(), expectedDate);
+}
+
+void tst_QDateTimeEdit::stepModifierButtons_data()
+{
+ QTest::addColumn<QStyle::SubControl>("subControl");
+ QTest::addColumn<int>("stepModifier");
+ QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
+ QTest::addColumn<QDateTimeEdit::Section>("section");
+ QTest::addColumn<QTime>("startTime");
+ QTest::addColumn<QTime>("expectedTime");
+
+ const auto subControls = {QStyle::SC_SpinBoxUp, QStyle::SC_SpinBoxDown};
+
+ const auto modifierList = {Qt::NoModifier,
+ Qt::ShiftModifier,
+ Qt::ControlModifier,
+ Qt::AltModifier,
+ Qt::MetaModifier};
+
+ const auto validStepModifierList = {Qt::NoModifier,
+ Qt::ControlModifier,
+ Qt::ShiftModifier};
+
+ const auto sections = {QDateTimeEdit::SecondSection,
+ QDateTimeEdit::MinuteSection,
+ QDateTimeEdit::HourSection};
+
+ const QTime startTime(12, 36, 24);
+
+ for (auto subControl : subControls) {
+
+ const bool up = subControl == QStyle::SC_SpinBoxUp;
+ Q_ASSERT(up || subControl == QStyle::SC_SpinBoxDown);
+
+ for (auto modifier : modifierList) {
+
+ const Qt::KeyboardModifiers modifiers(modifier);
+
+ const auto modifierName = modifierToName(modifier);
+ if (modifierName.isEmpty())
+ continue;
+
+ for (auto stepModifier : validStepModifierList) {
+
+ const auto stepModifierName = modifierToName(stepModifier);
+ if (stepModifierName.isEmpty())
+ continue;
+
+ const int steps = (modifier & stepModifier ? 10 : 1)
+ * (up ? 1 : -1);
+
+ for (const auto section : sections) {
+
+ const auto expectedTime = stepTime(startTime, section, steps);
+ if (!expectedTime.isValid())
+ continue;
+
+ const auto sectionName = sectionToName(section);
+
+ QTest::addRow("%s%s%sWith%sKeyboardModifier",
+ up ? "up" : "down",
+ stepModifierName.latin1(),
+ sectionName.latin1(),
+ modifierName.latin1())
+ << subControl
+ << static_cast<int>(stepModifier)
+ << modifiers
+ << section
+ << startTime
+ << expectedTime;
+ }
+ }
+ }
+ }
+}
+
+void tst_QDateTimeEdit::stepModifierButtons()
+{
+ QFETCH(QStyle::SubControl, subControl);
+ QFETCH(int, stepModifier);
+ QFETCH(Qt::KeyboardModifiers, modifiers);
+ QFETCH(QDateTimeEdit::Section, section);
+ QFETCH(QTime, startTime);
+ QFETCH(QTime, expectedTime);
+
+ testWidget->hide();
+
+ EditorDateEdit edit(0);
+ edit.setTime(startTime);
+ edit.show();
+ QVERIFY(QTest::qWaitForWindowActive(&edit));
+ edit.setCurrentSection(section);
+
+ QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> style(
+ new StepModifierStyle);
+ style->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
+ edit.setStyle(style.data());
+
+ QStyleOptionSpinBox spinBoxStyleOption;
+ edit.initStyleOption(&spinBoxStyleOption);
+
+ const QRect buttonRect = edit.style()->subControlRect(
+ QStyle::CC_SpinBox, &spinBoxStyleOption, subControl, &edit);
+
+ QCOMPARE(edit.time(), startTime);
+ QTest::mouseClick(&edit, Qt::LeftButton, modifiers, buttonRect.center());
+ QCOMPARE(edit.time(), expectedTime);
+}
+
+void tst_QDateTimeEdit::stepModifierPressAndHold_data()
+{
+ QTest::addColumn<QStyle::SubControl>("subControl");
+ QTest::addColumn<int>("stepModifier");
+ QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
+ QTest::addColumn<int>("expectedStepModifier");
+
+ const auto subControls = {QStyle::SC_SpinBoxUp, QStyle::SC_SpinBoxDown};
+
+ const auto modifierList = {Qt::NoModifier,
+ Qt::ShiftModifier,
+ Qt::ControlModifier,
+ Qt::AltModifier,
+ Qt::MetaModifier};
+
+ const auto validStepModifierList = {Qt::NoModifier,
+ Qt::ControlModifier,
+ Qt::ShiftModifier};
+
+ for (auto subControl : subControls) {
+
+ const bool up = subControl == QStyle::SC_SpinBoxUp;
+ Q_ASSERT(up || subControl == QStyle::SC_SpinBoxDown);
+
+ for (auto modifier : modifierList) {
+
+ const Qt::KeyboardModifiers modifiers(modifier);
+
+ const auto modifierName = modifierToName(modifier);
+ if (modifierName.isEmpty())
+ continue;
+
+ for (auto stepModifier : validStepModifierList) {
+
+ const auto stepModifierName = modifierToName(stepModifier);
+ if (stepModifierName.isEmpty())
+ continue;
+
+ const int steps = (modifier & stepModifier ? 10 : 1)
+ * (up ? 1 : -1);
+
+ QTest::addRow("%s%sWith%sKeyboardModifier",
+ up ? "up" : "down",
+ stepModifierName.latin1(),
+ modifierName.latin1())
+ << subControl
+ << static_cast<int>(stepModifier)
+ << modifiers
+ << steps;
+ }
+ }
+ }
+}
+
+void tst_QDateTimeEdit::stepModifierPressAndHold()
+{
+ QFETCH(QStyle::SubControl, subControl);
+ QFETCH(int, stepModifier);
+ QFETCH(Qt::KeyboardModifiers, modifiers);
+ QFETCH(int, expectedStepModifier);
+
+ const QDate startDate(2000, 1, 1);
+
+ testWidget->hide();
+
+ EditorDateEdit edit(0);
+ edit.setDate(startDate);
+
+ QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> stepModifierStyle(
+ new StepModifierStyle(new PressAndHoldStyle));
+ stepModifierStyle->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
+ edit.setStyle(stepModifierStyle.data());
+
+ QSignalSpy spy(&edit, &EditorDateEdit::dateChanged);
+
+ edit.show();
+ QVERIFY(QTest::qWaitForWindowActive(&edit));
+ edit.setCurrentSection(QDateTimeEdit::YearSection);
+
+ QStyleOptionSpinBox spinBoxStyleOption;
+ edit.initStyleOption(&spinBoxStyleOption);
+
+ const QRect buttonRect = edit.style()->subControlRect(
+ QStyle::CC_SpinBox, &spinBoxStyleOption, subControl, &edit);
+
+ QTest::mousePress(&edit, Qt::LeftButton, modifiers, buttonRect.center());
+ QTRY_VERIFY(spy.length() >= 3);
+ QTest::mouseRelease(&edit, Qt::LeftButton, modifiers, buttonRect.center());
+
+ const auto value = spy.last().at(0);
+ QVERIFY(value.type() == QVariant::Date);
+ const QDate expectedDate = startDate.addYears(spy.length() *
+ expectedStepModifier);
+ QCOMPARE(value.toDate(), expectedDate);
+}
+
QTEST_MAIN(tst_QDateTimeEdit)
#include "tst_qdatetimeedit.moc"
diff --git a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
index 7d1e736f42..078a3215fd 100644
--- a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
+++ b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
@@ -36,7 +36,7 @@
#include <qmainwindow.h>
#include <qlineedit.h>
#include <qtabbar.h>
-#include <QDesktopWidget>
+#include <QScreen>
#include <QtGui/QPainter>
#include "private/qdockwidget_p.h"
@@ -338,7 +338,7 @@ void tst_QDockWidget::features()
void tst_QDockWidget::setFloating()
{
- const QRect deskRect = QApplication::desktop()->availableGeometry();
+ const QRect deskRect = QGuiApplication::primaryScreen()->availableGeometry();
QMainWindow mw;
mw.move(deskRect.left() + deskRect.width() * 2 / 3, deskRect.top() + deskRect.height() / 3);
QDockWidget dw;
@@ -756,7 +756,7 @@ void tst_QDockWidget::restoreStateWhileStillFloating()
// When the dock widget is already floating then it takes a different code path
// so this test covers the case where the restoreState() is effectively just
// moving it back and resizing it
- const QRect availGeom = QApplication::desktop()->availableGeometry();
+ const QRect availGeom = QGuiApplication::primaryScreen()->availableGeometry();
const QPoint startingDockPos = availGeom.center();
QMainWindow mw;
QDockWidget *dock = createTestDock(mw);
@@ -781,10 +781,8 @@ void tst_QDockWidget::restoreDockWidget()
QByteArray geometry;
QByteArray state;
- const bool isXcb = !QGuiApplication::platformName().compare("xcb", Qt::CaseInsensitive);
-
const QString name = QStringLiteral("main");
- const QRect availableGeometry = QApplication::desktop()->availableGeometry();
+ const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry();
const QSize size = availableGeometry.size() / 5;
const QPoint mainWindowPos = availableGeometry.bottomRight() - QPoint(size.width(), size.height()) - QPoint(100, 100);
const QPoint dockPos = availableGeometry.center();
@@ -815,8 +813,7 @@ void tst_QDockWidget::restoreDockWidget()
dock->show();
QVERIFY(QTest::qWaitForWindowExposed(dock));
QTRY_VERIFY(dock->isFloating());
- if (!isXcb) // Avoid Window manager positioning issues
- QTRY_COMPARE(dock->pos(), dockPos);
+ QTRY_COMPARE(dock->pos(), dockPos);
}
QVERIFY(!geometry.isEmpty());
@@ -837,8 +834,6 @@ void tst_QDockWidget::restoreDockWidget()
restoreWindow.show();
QVERIFY(QTest::qWaitForWindowExposed(&restoreWindow));
QTRY_VERIFY(dock->isFloating());
- if (isXcb)
- QSKIP("Skip due to Window manager positioning issues", Abort);
QTRY_COMPARE(dock->pos(), dockPos);
}
}
@@ -868,7 +863,7 @@ void tst_QDockWidget::task169808_setFloating()
public:
QSize sizeHint() const
{
- const QRect& deskRect = qApp->desktop()->availableGeometry();
+ const QRect& deskRect = QGuiApplication::primaryScreen()->availableGeometry();
return QSize(qMin(300, deskRect.width() / 2), qMin(300, deskRect.height() / 2));
}
@@ -892,6 +887,9 @@ void tst_QDockWidget::task169808_setFloating()
mw.show();
QVERIFY(QTest::qWaitForWindowExposed(&mw));
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Widgets are maximized on WinRT by default", Abort);
+#endif
QCOMPARE(dw->widget()->size(), dw->widget()->sizeHint());
//and now we try to test if the contents margin is taken into account
@@ -934,6 +932,9 @@ void tst_QDockWidget::task248604_infiniteResize()
d.setContentsMargins(2, 2, 2, 2);
d.setMinimumSize(320, 240);
d.showNormal();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Widgets are maximized on WinRT by default", Abort);
+#endif
QTRY_COMPARE(d.size(), QSize(320, 240));
}
diff --git a/tests/auto/widgets/widgets/qdoublespinbox/BLACKLIST b/tests/auto/widgets/widgets/qdoublespinbox/BLACKLIST
new file mode 100644
index 0000000000..c1b6c9693e
--- /dev/null
+++ b/tests/auto/widgets/widgets/qdoublespinbox/BLACKLIST
@@ -0,0 +1,2 @@
+[editingFinished]
+*
diff --git a/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp b/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp
index d44cc40527..b1610c297d 100644
--- a/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp
+++ b/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp
@@ -31,6 +31,7 @@
#include <qapplication.h>
#include <limits.h>
+#include <cmath>
#include <float.h>
#include <qspinbox.h>
@@ -40,6 +41,10 @@
#include <qlineedit.h>
#include <qdebug.h>
+#include <QStyleOptionSpinBox>
+#include <QStyle>
+#include <QProxyStyle>
+
class DoubleSpinBox : public QDoubleSpinBox
{
Q_OBJECT
@@ -59,6 +64,16 @@ public:
{
return QDoubleSpinBox::valueFromText(text);
}
+#if QT_CONFIG(wheelevent)
+ void wheelEvent(QWheelEvent *event)
+ {
+ QDoubleSpinBox::wheelEvent(event);
+ }
+#endif
+ void initStyleOption(QStyleOptionSpinBox *option) const
+ {
+ QDoubleSpinBox::initStyleOption(option);
+ }
QLineEdit* lineEdit() const { return QDoubleSpinBox::lineEdit(); }
public slots:
@@ -68,6 +83,46 @@ public slots:
}
};
+class PressAndHoldStyle : public QProxyStyle
+{
+ Q_OBJECT
+public:
+ using QProxyStyle::QProxyStyle;
+
+ int styleHint(QStyle::StyleHint hint, const QStyleOption *option = nullptr,
+ const QWidget *widget = nullptr, QStyleHintReturn *returnData = nullptr) const override
+ {
+ switch (hint) {
+ case QStyle::SH_SpinBox_ClickAutoRepeatRate:
+ return 5;
+ case QStyle::SH_SpinBox_ClickAutoRepeatThreshold:
+ return 10;
+ default:
+ return QProxyStyle::styleHint(hint, option, widget, returnData);
+ }
+ }
+};
+
+class StepModifierStyle : public QProxyStyle
+{
+ Q_OBJECT
+public:
+ using QProxyStyle::QProxyStyle;
+
+ int styleHint(QStyle::StyleHint hint, const QStyleOption *option = nullptr,
+ const QWidget *widget = nullptr, QStyleHintReturn *returnData = nullptr) const override
+ {
+ switch (hint) {
+ case QStyle::SH_SpinBox_StepModifier:
+ return stepModifier;
+ default:
+ return QProxyStyle::styleHint(hint, option, widget, returnData);
+ }
+ }
+
+ Qt::KeyboardModifier stepModifier = Qt::ControlModifier;
+};
+
class tst_QDoubleSpinBox : public QObject
{
@@ -135,6 +190,19 @@ private slots:
void setGroupSeparatorShown_data();
void setGroupSeparatorShown();
+ void adaptiveDecimalStep();
+
+ void wheelEvents_data();
+ void wheelEvents();
+
+ void stepModifierKeys_data();
+ void stepModifierKeys();
+
+ void stepModifierButtons_data();
+ void stepModifierButtons();
+
+ void stepModifierPressAndHold_data();
+ void stepModifierPressAndHold();
public slots:
void valueChangedHelper(const QString &);
void valueChangedHelper(double);
@@ -149,6 +217,30 @@ typedef QList<double> DoubleList;
Q_DECLARE_METATYPE(QLocale::Language)
Q_DECLARE_METATYPE(QLocale::Country)
+static QLatin1String modifierToName(Qt::KeyboardModifier modifier)
+{
+ switch (modifier) {
+ case Qt::NoModifier:
+ return QLatin1Literal("No");
+ break;
+ case Qt::ControlModifier:
+ return QLatin1Literal("Ctrl");
+ break;
+ case Qt::ShiftModifier:
+ return QLatin1Literal("Shift");
+ break;
+ case Qt::AltModifier:
+ return QLatin1Literal("Alt");
+ break;
+ case Qt::MetaModifier:
+ return QLatin1Literal("Meta");
+ break;
+ default:
+ qFatal("Unexpected keyboard modifier");
+ return QLatin1String();
+ }
+}
+
tst_QDoubleSpinBox::tst_QDoubleSpinBox()
{
@@ -1139,5 +1231,548 @@ void tst_QDoubleSpinBox::setGroupSeparatorShown()
QCOMPARE(spinBox.value()+1000, 33000.44);
}
+void tst_QDoubleSpinBox::adaptiveDecimalStep()
+{
+ DoubleSpinBox spinBox;
+ spinBox.setRange(-100000, 100000);
+ spinBox.setDecimals(4);
+ spinBox.setStepType(DoubleSpinBox::StepType::AdaptiveDecimalStepType);
+
+ // Positive values
+
+ spinBox.setValue(0);
+
+ // Go from 0 to 0.01
+ for (double i = 0; i < 0.00999; i += 0.0001) {
+ QVERIFY(qFuzzyCompare(spinBox.value(), i));
+ spinBox.stepBy(1);
+ }
+
+ // Go from 0.01 to 0.1
+ for (double i = 0.01; i < 0.0999; i += 0.001) {
+ QVERIFY(qFuzzyCompare(spinBox.value(), i));
+ spinBox.stepBy(1);
+ }
+
+ // Go from 0.1 to 1
+ for (double i = 0.1; i < 0.999; i += 0.01) {
+ QVERIFY(qFuzzyCompare(spinBox.value(), i));
+ spinBox.stepBy(1);
+ }
+
+ // Go from 1 to 10
+ for (double i = 1; i < 9.99; i += 0.1) {
+ QVERIFY(qFuzzyCompare(spinBox.value(), i));
+ spinBox.stepBy(1);
+ }
+
+ // Go from 10 to 100
+ for (int i = 10; i < 100; i++) {
+ QVERIFY(qFuzzyCompare(spinBox.value(), i));
+ spinBox.stepBy(1);
+ }
+
+ // Go from 100 to 1000
+ for (int i = 100; i < 1000; i += 10) {
+ QVERIFY(qFuzzyCompare(spinBox.value(), i));
+ spinBox.stepBy(1);
+ }
+
+ // Go from 1000 to 10000
+ for (int i = 1000; i < 10000; i += 100) {
+ QVERIFY(qFuzzyCompare(spinBox.value(), i));
+ spinBox.stepBy(1);
+ }
+
+ // Test decreasing the values now
+
+ // Go from 10000 down to 1000
+ for (int i = 10000; i > 1000; i -= 100) {
+ QVERIFY(qFuzzyCompare(spinBox.value(), i));
+ spinBox.stepBy(-1);
+ }
+
+ // Go from 1000 down to 100
+ for (int i = 1000; i > 100; i -= 10) {
+ QVERIFY(qFuzzyCompare(spinBox.value(), i));
+ spinBox.stepBy(-1);
+ }
+
+ // Negative values
+
+ spinBox.setValue(0);
+
+ // Go from 0 to -0.01
+ for (double i = 0; i > -0.00999; i -= 0.0001) {
+ QVERIFY(qFuzzyCompare(spinBox.value(), i));
+ spinBox.stepBy(-1);
+ }
+
+ // Go from -0.01 to -0.1
+ for (double i = -0.01; i > -0.0999; i -= 0.001) {
+ QVERIFY(qFuzzyCompare(spinBox.value(), i));
+ spinBox.stepBy(-1);
+ }
+
+ // Go from -0.1 to -1
+ for (double i = -0.1; i > -0.999; i -= 0.01) {
+ QVERIFY(qFuzzyCompare(spinBox.value(), i));
+ spinBox.stepBy(-1);
+ }
+
+ // Go from -1 to -10
+ for (double i = -1; i > -9.99; i -= 0.1) {
+ QVERIFY(qFuzzyCompare(spinBox.value(), i));
+ spinBox.stepBy(-1);
+ }
+
+ // Go from -10 to -100
+ for (int i = -10; i > -100; i--) {
+ QVERIFY(qFuzzyCompare(spinBox.value(), i));
+ spinBox.stepBy(-1);
+ }
+
+ // Go from -100 to -1000
+ for (int i = -100; i > -1000; i -= 10) {
+ QVERIFY(qFuzzyCompare(spinBox.value(), i));
+ spinBox.stepBy(-1);
+ }
+
+ // Go from 1000 to 10000
+ for (int i = -1000; i > -10000; i -= 100) {
+ QVERIFY(qFuzzyCompare(spinBox.value(), i));
+ spinBox.stepBy(-1);
+ }
+
+ // Test increasing the values now
+
+ // Go from -10000 up to -1000
+ for (int i = -10000; i < -1000; i += 100) {
+ QVERIFY(qFuzzyCompare(spinBox.value(), i));
+ spinBox.stepBy(1);
+ }
+
+ // Go from -1000 up to -100
+ for (int i = -1000; i < -100; i += 10) {
+ QVERIFY(qFuzzyCompare(spinBox.value(), i));
+ spinBox.stepBy(1);
+ }
+}
+
+void tst_QDoubleSpinBox::wheelEvents_data()
+{
+#if QT_CONFIG(wheelevent)
+ QTest::addColumn<QPoint>("angleDelta");
+ QTest::addColumn<int>("qt4Delta");
+ QTest::addColumn<int>("stepModifier");
+ QTest::addColumn<Qt::KeyboardModifiers>("modifier");
+ QTest::addColumn<Qt::MouseEventSource>("source");
+ QTest::addColumn<double>("start");
+ QTest::addColumn<DoubleList>("expectedValues");
+
+ const auto fractions = {false, true};
+
+ const auto directions = {true, false};
+
+ const auto modifierList = {Qt::NoModifier,
+ Qt::ShiftModifier,
+ Qt::ControlModifier,
+ Qt::AltModifier,
+ Qt::MetaModifier};
+
+ const auto validStepModifierList = {Qt::NoModifier,
+ Qt::ControlModifier,
+ Qt::ShiftModifier};
+
+ const auto sources = {Qt::MouseEventNotSynthesized,
+ Qt::MouseEventSynthesizedBySystem,
+ Qt::MouseEventSynthesizedByQt,
+ Qt::MouseEventSynthesizedByApplication};
+
+ const double startValue = 0.0;
+
+ for (auto fraction : fractions) {
+ for (auto up : directions) {
+
+ const int units = (fraction ? 60 : 120) * (up ? 1 : -1);
+
+ for (auto modifier : modifierList) {
+
+ const Qt::KeyboardModifiers modifiers(modifier);
+
+ const auto modifierName = modifierToName(modifier);
+ if (modifierName.isEmpty())
+ continue;
+
+ for (auto stepModifier : validStepModifierList) {
+
+ const auto stepModifierName = modifierToName(stepModifier);
+ if (stepModifierName.isEmpty())
+ continue;
+
+ const int steps = (modifier & stepModifier ? 10 : 1)
+ * (up ? 1 : -1);
+
+ for (auto source : sources) {
+
+#ifdef Q_OS_MACOS
+ QPoint angleDelta;
+ if ((modifier & Qt::ShiftModifier) &&
+ source == Qt::MouseEventNotSynthesized) {
+ // On macOS the Shift modifier converts vertical
+ // mouse wheel events to horizontal.
+ angleDelta = { units, 0 };
+ } else {
+ // However, this is not the case for trackpad scroll
+ // events.
+ angleDelta = { 0, units };
+ }
+#else
+ const QPoint angleDelta(0, units);
+#endif
+
+ QLatin1String sourceName;
+ switch (source) {
+ case Qt::MouseEventNotSynthesized:
+ sourceName = QLatin1Literal("NotSynthesized");
+ break;
+ case Qt::MouseEventSynthesizedBySystem:
+ sourceName = QLatin1Literal("SynthesizedBySystem");
+ break;
+ case Qt::MouseEventSynthesizedByQt:
+ sourceName = QLatin1Literal("SynthesizedByQt");
+ break;
+ case Qt::MouseEventSynthesizedByApplication:
+ sourceName = QLatin1Literal("SynthesizedByApplication");
+ break;
+ default:
+ qFatal("Unexpected wheel event source");
+ continue;
+ }
+
+ DoubleList expectedValues;
+ if (fraction)
+ expectedValues << startValue;
+ expectedValues << startValue + steps;
+
+ QTest::addRow("%s%s%sWith%sKeyboardModifier%s",
+ fraction ? "half" : "full",
+ up ? "Up" : "Down",
+ stepModifierName.latin1(),
+ modifierName.latin1(),
+ sourceName.latin1())
+ << angleDelta
+ << units
+ << static_cast<int>(stepModifier)
+ << modifiers
+ << source
+ << startValue
+ << expectedValues;
+ }
+ }
+ }
+ }
+ }
+#else
+ QSKIP("Built with --no-feature-wheelevent");
+#endif
+}
+
+void tst_QDoubleSpinBox::wheelEvents()
+{
+#if QT_CONFIG(wheelevent)
+ QFETCH(QPoint, angleDelta);
+ QFETCH(int, qt4Delta);
+ QFETCH(int, stepModifier);
+ QFETCH(Qt::KeyboardModifiers, modifier);
+ QFETCH(Qt::MouseEventSource, source);
+ QFETCH(double, start);
+ QFETCH(DoubleList, expectedValues);
+
+ DoubleSpinBox spinBox;
+ spinBox.setRange(-20, 20);
+ spinBox.setValue(start);
+
+ QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> style(
+ new StepModifierStyle);
+ style->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
+ spinBox.setStyle(style.data());
+
+ QWheelEvent event(QPointF(), QPointF(), QPoint(), angleDelta, qt4Delta,
+ Qt::Vertical, Qt::NoButton, modifier, Qt::NoScrollPhase,
+ source);
+ for (int expected : expectedValues) {
+ qApp->sendEvent(&spinBox, &event);
+ QCOMPARE(spinBox.value(), expected);
+ }
+#else
+ QSKIP("Built with --no-feature-wheelevent");
+#endif
+}
+
+void tst_QDoubleSpinBox::stepModifierKeys_data()
+{
+ QTest::addColumn<double>("startValue");
+ QTest::addColumn<int>("stepModifier");
+ QTest::addColumn<QTestEventList>("keys");
+ QTest::addColumn<double>("expectedValue");
+
+ const auto keyList = {Qt::Key_Up, Qt::Key_Down};
+
+ const auto modifierList = {Qt::NoModifier,
+ Qt::ShiftModifier,
+ Qt::ControlModifier,
+ Qt::AltModifier,
+ Qt::MetaModifier};
+
+ const auto validStepModifierList = {Qt::NoModifier,
+ Qt::ControlModifier,
+ Qt::ShiftModifier};
+
+
+ for (auto key : keyList) {
+
+ const bool up = key == Qt::Key_Up;
+ Q_ASSERT(up || key == Qt::Key_Down);
+
+ const double startValue = up ? 0.0 : 10.0;
+
+ for (auto modifier : modifierList) {
+
+ QTestEventList keys;
+ keys.addKeyClick(key, modifier);
+
+ const auto modifierName = modifierToName(modifier);
+ if (modifierName.isEmpty())
+ continue;
+
+ for (auto stepModifier : validStepModifierList) {
+
+ const auto stepModifierName = modifierToName(stepModifier);
+ if (stepModifierName.isEmpty())
+ continue;
+
+ const int steps = (modifier & stepModifier ? 10 : 1)
+ * (up ? 1 : -1);
+
+ const double expectedValue = startValue + steps;
+
+ QTest::addRow("%s%sWith%sKeyboardModifier",
+ up ? "up" : "down",
+ stepModifierName.latin1(),
+ modifierName.latin1())
+ << startValue
+ << static_cast<int>(stepModifier)
+ << keys
+ << expectedValue;
+ }
+ }
+ }
+}
+
+void tst_QDoubleSpinBox::stepModifierKeys()
+{
+ QFETCH(double, startValue);
+ QFETCH(int, stepModifier);
+ QFETCH(QTestEventList, keys);
+ QFETCH(double, expectedValue);
+
+ QDoubleSpinBox spin(0);
+ spin.setValue(startValue);
+
+ QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> style(
+ new StepModifierStyle);
+ style->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
+ spin.setStyle(style.data());
+
+ spin.show();
+ QVERIFY(QTest::qWaitForWindowActive(&spin));
+
+ QCOMPARE(spin.value(), startValue);
+ keys.simulate(&spin);
+ QCOMPARE(spin.value(), expectedValue);
+}
+
+void tst_QDoubleSpinBox::stepModifierButtons_data()
+{
+ QTest::addColumn<QStyle::SubControl>("subControl");
+ QTest::addColumn<int>("stepModifier");
+ QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
+ QTest::addColumn<double>("startValue");
+ QTest::addColumn<double>("expectedValue");
+
+ const auto subControls = {QStyle::SC_SpinBoxUp, QStyle::SC_SpinBoxDown};
+
+ const auto modifierList = {Qt::NoModifier,
+ Qt::ShiftModifier,
+ Qt::ControlModifier,
+ Qt::AltModifier,
+ Qt::MetaModifier};
+
+ const auto validStepModifierList = {Qt::NoModifier,
+ Qt::ControlModifier,
+ Qt::ShiftModifier};
+
+ for (auto subControl : subControls) {
+
+ const bool up = subControl == QStyle::SC_SpinBoxUp;
+ Q_ASSERT(up || subControl == QStyle::SC_SpinBoxDown);
+
+ const double startValue = up ? 0 : 10;
+
+ for (auto modifier : modifierList) {
+
+ const Qt::KeyboardModifiers modifiers(modifier);
+
+ const auto modifierName = modifierToName(modifier);
+ if (modifierName.isEmpty())
+ continue;
+
+ for (auto stepModifier : validStepModifierList) {
+
+ const auto stepModifierName = modifierToName(stepModifier);
+ if (stepModifierName.isEmpty())
+ continue;
+
+ const int steps = (modifier & stepModifier ? 10 : 1)
+ * (up ? 1 : -1);
+
+ const double expectedValue = startValue + steps;
+
+ QTest::addRow("%s%sWith%sKeyboardModifier",
+ up ? "up" : "down",
+ stepModifierName.latin1(),
+ modifierName.latin1())
+ << subControl
+ << static_cast<int>(stepModifier)
+ << modifiers
+ << startValue
+ << expectedValue;
+ }
+ }
+ }
+}
+
+void tst_QDoubleSpinBox::stepModifierButtons()
+{
+ QFETCH(QStyle::SubControl, subControl);
+ QFETCH(int, stepModifier);
+ QFETCH(Qt::KeyboardModifiers, modifiers);
+ QFETCH(double, startValue);
+ QFETCH(double, expectedValue);
+
+ DoubleSpinBox spin(0);
+ spin.setRange(-20, 20);
+ spin.setValue(startValue);
+
+ QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> style(
+ new StepModifierStyle);
+ style->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
+ spin.setStyle(style.data());
+
+ spin.show();
+ QVERIFY(QTest::qWaitForWindowActive(&spin));
+
+ QStyleOptionSpinBox spinBoxStyleOption;
+ spin.initStyleOption(&spinBoxStyleOption);
+
+ const QRect buttonRect = spin.style()->subControlRect(
+ QStyle::CC_SpinBox, &spinBoxStyleOption, subControl, &spin);
+
+ QCOMPARE(spin.value(), startValue);
+ QTest::mouseClick(&spin, Qt::LeftButton, modifiers, buttonRect.center());
+ QCOMPARE(spin.value(), expectedValue);
+}
+
+void tst_QDoubleSpinBox::stepModifierPressAndHold_data()
+{
+ QTest::addColumn<QStyle::SubControl>("subControl");
+ QTest::addColumn<int>("stepModifier");
+ QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
+ QTest::addColumn<int>("expectedStepModifier");
+
+ const auto subControls = {QStyle::SC_SpinBoxUp, QStyle::SC_SpinBoxDown};
+
+ const auto modifierList = {Qt::NoModifier,
+ Qt::ShiftModifier,
+ Qt::ControlModifier,
+ Qt::AltModifier,
+ Qt::MetaModifier};
+
+ const auto validStepModifierList = {Qt::NoModifier,
+ Qt::ControlModifier,
+ Qt::ShiftModifier};
+
+ for (auto subControl : subControls) {
+
+ const bool up = subControl == QStyle::SC_SpinBoxUp;
+ Q_ASSERT(up || subControl == QStyle::SC_SpinBoxDown);
+
+ for (auto modifier : modifierList) {
+
+ const Qt::KeyboardModifiers modifiers(modifier);
+
+ const auto modifierName = modifierToName(modifier);
+ if (modifierName.isEmpty())
+ continue;
+
+ for (auto stepModifier : validStepModifierList) {
+
+ const auto stepModifierName = modifierToName(stepModifier);
+ if (stepModifierName.isEmpty())
+ continue;
+
+ const int steps = (modifier & stepModifier ? 10 : 1)
+ * (up ? 1 : -1);
+
+ QTest::addRow("%s%sWith%sKeyboardModifier",
+ up ? "up" : "down",
+ stepModifierName.latin1(),
+ modifierName.latin1())
+ << subControl
+ << static_cast<int>(stepModifier)
+ << modifiers
+ << steps;
+ }
+ }
+ }
+}
+
+void tst_QDoubleSpinBox::stepModifierPressAndHold()
+{
+ QFETCH(QStyle::SubControl, subControl);
+ QFETCH(int, stepModifier);
+ QFETCH(Qt::KeyboardModifiers, modifiers);
+ QFETCH(int, expectedStepModifier);
+
+ DoubleSpinBox spin(0);
+ spin.setRange(-100.0, 100.0);
+ spin.setValue(0.0);
+
+ QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> stepModifierStyle(
+ new StepModifierStyle(new PressAndHoldStyle));
+ stepModifierStyle->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
+ spin.setStyle(stepModifierStyle.data());
+
+ QSignalSpy spy(&spin, QOverload<double>::of(&DoubleSpinBox::valueChanged));
+
+ spin.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&spin));
+
+ QStyleOptionSpinBox spinBoxStyleOption;
+ spin.initStyleOption(&spinBoxStyleOption);
+
+ const QRect buttonRect = spin.style()->subControlRect(
+ QStyle::CC_SpinBox, &spinBoxStyleOption, subControl, &spin);
+
+ QTest::mousePress(&spin, Qt::LeftButton, modifiers, buttonRect.center());
+ QTRY_VERIFY(spy.length() >= 3);
+ QTest::mouseRelease(&spin, Qt::LeftButton, modifiers, buttonRect.center());
+
+ const auto value = spy.last().at(0);
+ QVERIFY(value.type() == QVariant::Double);
+ QCOMPARE(value.toDouble(), spy.length() * expectedStepModifier);
+}
+
QTEST_MAIN(tst_QDoubleSpinBox)
#include "tst_qdoublespinbox.moc"
diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
index 17462a5f86..448e2030bc 100644
--- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
+++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
@@ -304,7 +304,7 @@ private slots:
void QTBUG59957_clearButtonLeftmostAction();
void QTBUG_60319_setInputMaskCheckImSurroundingText();
void testQuickSelectionWithMouse();
-
+ void inputRejected();
protected slots:
void editingFinished();
@@ -2279,6 +2279,16 @@ void tst_QLineEdit::deleteSelectedText()
}
+class ToUpperValidator : public QValidator
+{
+public:
+ ToUpperValidator() {}
+ State validate(QString &input, int &) const override
+ {
+ input = input.toUpper();
+ return QValidator::Acceptable;
+ }
+};
void tst_QLineEdit::textChangedAndTextEdited()
{
@@ -2320,6 +2330,23 @@ void tst_QLineEdit::textChangedAndTextEdited()
QCOMPARE(edited_count, 0);
QVERIFY(changed_string.isEmpty());
QVERIFY(!changed_string.isNull());
+
+ changed_count = 0;
+ edited_count = 0;
+ changed_string.clear();
+
+ QScopedPointer<ToUpperValidator> validator(new ToUpperValidator());
+ testWidget->setValidator(validator.data());
+ testWidget->setText("foo");
+ QCOMPARE(changed_count, 1);
+ QCOMPARE(edited_count, 0);
+ QCOMPARE(changed_string, QLatin1String("FOO"));
+ testWidget->setCursorPosition(sizeof("foo"));
+ QTest::keyClick(testWidget, 'b');
+ QCOMPARE(changed_count, 2);
+ QCOMPARE(edited_count, 1);
+ QCOMPARE(changed_string, QLatin1String("FOOB"));
+ testWidget->setValidator(nullptr);
}
void tst_QLineEdit::onTextChanged(const QString &text)
@@ -2637,9 +2664,9 @@ void tst_QLineEdit::setValidator_QIntValidator_data()
<< 0
<< 100
<< QString("153")
- << QString(useKeys ? "15" : "")
+ << QString("153")
<< bool(useKeys)
- << bool(useKeys ? true : false)
+ << bool(false)
<< uint(QLineEdit::Normal);
QTest::newRow(QString(inputMode + "range [-100,100] int '-153'").toLatin1())
<< -100
@@ -2660,7 +2687,7 @@ void tst_QLineEdit::setValidator_QIntValidator_data()
QTest::newRow(QString(inputMode + "range [3,7] int '8'").toLatin1())
<< 3
<< 7
- << QString("8")
+ << QString("")
<< QString("")
<< bool(useKeys)
<< bool(false)
@@ -3265,7 +3292,7 @@ void tst_QLineEdit::editInvalidText()
{
QLineEdit *testWidget = ensureTestWidget();
testWidget->clear();
- testWidget->setValidator(new QIntValidator(0, 120, 0));
+ testWidget->setValidator(new QIntValidator(0, 12, 0));
testWidget->setText("1234");
QVERIFY(!testWidget->hasAcceptableInput());
@@ -4726,6 +4753,9 @@ void tst_QLineEdit::testQuickSelectionWithMouse()
QTest::mousePress(lineEdit.windowHandle(), Qt::LeftButton, Qt::NoModifier, center);
QTest::mouseMove(lineEdit.windowHandle(), center + QPoint(20, 0));
qCDebug(lcTests) << "Selected text:" << lineEdit.selectedText();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "WinRT does not support QTest::mousePress/-Move", Abort);
+#endif
QVERIFY(!lineEdit.selectedText().isEmpty());
QVERIFY(!lineEdit.selectedText().endsWith(suffix));
@@ -4793,5 +4823,56 @@ void tst_QLineEdit::testQuickSelectionWithMouse()
QVERIFY(lineEdit.selectedText().endsWith(suffix));
}
+void tst_QLineEdit::inputRejected()
+{
+ QLineEdit *testWidget = ensureTestWidget();
+ QSignalSpy spyInputRejected(testWidget, SIGNAL(inputRejected()));
+
+ QTest::keyClicks(testWidget, "abcde");
+ QCOMPARE(spyInputRejected.count(), 0);
+ testWidget->setText("fghij");
+ QCOMPARE(spyInputRejected.count(), 0);
+ testWidget->insert("k");
+ QCOMPARE(spyInputRejected.count(), 0);
+
+ testWidget->clear();
+ testWidget->setMaxLength(5);
+ QTest::keyClicks(testWidget, "abcde");
+ QCOMPARE(spyInputRejected.count(), 0);
+ QTest::keyClicks(testWidget, "fgh");
+ QCOMPARE(spyInputRejected.count(), 3);
+ testWidget->clear();
+ spyInputRejected.clear();
+ QApplication::clipboard()->setText("ijklmno");
+ testWidget->paste();
+ // The first 5 characters are accepted, but
+ // the last 2 are not.
+ QCOMPARE(spyInputRejected.count(), 1);
+
+ testWidget->setMaxLength(INT_MAX);
+ testWidget->clear();
+ spyInputRejected.clear();
+ QIntValidator intValidator(1, 100);
+ testWidget->setValidator(&intValidator);
+ QTest::keyClicks(testWidget, "11");
+ QCOMPARE(spyInputRejected.count(), 0);
+ QTest::keyClicks(testWidget, "a#");
+ QCOMPARE(spyInputRejected.count(), 2);
+ testWidget->clear();
+ spyInputRejected.clear();
+ QApplication::clipboard()->setText("a#");
+ testWidget->paste();
+ QCOMPARE(spyInputRejected.count(), 1);
+
+ testWidget->clear();
+ testWidget->setValidator(0);
+ spyInputRejected.clear();
+ testWidget->setInputMask("999.999.999.999;_");
+ QTest::keyClicks(testWidget, "11");
+ QCOMPARE(spyInputRejected.count(), 0);
+ QTest::keyClicks(testWidget, "a#");
+ QCOMPARE(spyInputRejected.count(), 2);
+}
+
QTEST_MAIN(tst_QLineEdit)
#include "tst_qlineedit.moc"
diff --git a/tests/auto/widgets/widgets/qmainwindow/BLACKLIST b/tests/auto/widgets/widgets/qmainwindow/BLACKLIST
new file mode 100644
index 0000000000..a03ea11f40
--- /dev/null
+++ b/tests/auto/widgets/widgets/qmainwindow/BLACKLIST
@@ -0,0 +1,2 @@
+[resizeDocks]
+winrt
diff --git a/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp b/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp
index ae71663036..1acf07301c 100644
--- a/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp
+++ b/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp
@@ -43,7 +43,7 @@
#include <qlabel.h>
#include <qtextedit.h>
#include <qstylehints.h>
-#include <qdesktopwidget.h>
+#include <qscreen.h>
#include <private/qmainwindowlayout_p.h>
#include <private/qdockarealayout_p.h>
@@ -768,7 +768,7 @@ void tst_QMainWindow::contentsMargins()
QFETCH(int, contentsMargin);
QMainWindow mw;
- const QRect availGeometry = QApplication::desktop()->availableGeometry();
+ const QRect availGeometry = QGuiApplication::primaryScreen()->availableGeometry();
mw.menuBar()->addMenu("File");
mw.setWindowTitle(QLatin1String(QTest::currentTestFunction())
+ QLatin1Char(' ') + QLatin1String(QTest::currentDataTag()));
@@ -1782,6 +1782,9 @@ void tst_QMainWindow::centralWidgetSize()
mainWindow.setCentralWidget(&widget);
mainWindow.show();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Widgets are maximized by default on WinRT - QTBUG-68297", Abort);
+#endif
QTRY_COMPARE(widget.size(), widget.sizeHint());
}
@@ -1826,6 +1829,9 @@ void tst_QMainWindow::fixedSizeCentralWidget()
// finally verify that we get the space back when we resize to the old size
mainWindow.resize(mwSize);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "QMainWindow::resize does not work on WinRT", Continue);
+#endif
QTRY_COMPARE(child->height(), childHeight);
}
diff --git a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp
index ecad7267dd..6cc19051d2 100644
--- a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp
+++ b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp
@@ -357,6 +357,9 @@ void tst_QMdiArea::subWindowActivated()
QMdiSubWindow *window = windows.at(i);
window->showNormal();
qApp->processEvents();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("data2", "Broken on WinRT - QTBUG-68297", Abort);
+#endif
QVERIFY( window == activeWindow );
QVERIFY( activeWindow == workspace->activeSubWindow() );
}
@@ -517,6 +520,9 @@ void tst_QMdiArea::subWindowActivated2()
mdiArea.showNormal();
mdiArea.activateWindow();
QVERIFY(QTest::qWaitForWindowActive(&mdiArea));
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Broken on WinRT - QTBUG-68297", Abort);
+#endif
QTRY_COMPARE(spy.count(), 1);
QCOMPARE(mdiArea.activeSubWindow(), activeSubWindow);
spy.clear();
@@ -1191,6 +1197,9 @@ void tst_QMdiArea::addAndRemoveWindows()
// Don't occupy space.
QMdiSubWindow *window3 = workspace.addSubWindow(new QWidget);
window3->show();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Windows are maximized by default on WinRT", Abort);
+#endif
QCOMPARE(window3->geometry().topLeft(), QPoint(window2RestoreGeometry.right() + 1, 0));
}
@@ -1451,6 +1460,9 @@ void tst_QMdiArea::subWindowList()
QList<QMdiSubWindow *> widgets = workspace.subWindowList(windowOrder);
QCOMPARE(widgets.count(), windowCount);
if (windowOrder == QMdiArea::StackingOrder) {
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Broken on WinRT - QTBUG-68297", Abort);
+#endif
QCOMPARE(widgets.at(widgets.count() - 1), windows[staysOnTop2]);
QCOMPARE(widgets.at(widgets.count() - 2), windows[staysOnTop1]);
QCOMPARE(widgets.at(widgets.count() - 3), windows[activeSubWindow]);
@@ -1666,6 +1678,9 @@ void tst_QMdiArea::tileSubWindows()
// Re-tile.
workspace.tileSubWindows();
workspace.setActiveSubWindow(0);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Broken on WinRT - QTBUG-68297", Abort);
+#endif
QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
// Cascade and verify that the views are not tiled anymore.
@@ -1965,6 +1980,9 @@ void tst_QMdiArea::dontMaximizeSubWindowOnActivation()
// Verify that new windows are not maximized.
mdiArea.addSubWindow(new QWidget)->show();
QVERIFY(mdiArea.activeSubWindow());
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Broken on WinRT - QTBUG-68297", Abort);
+#endif
QVERIFY(!mdiArea.activeSubWindow()->isMaximized());
}
@@ -1986,6 +2004,9 @@ void tst_QMdiArea::delayedPlacement()
QVERIFY(QTest::qWaitForWindowExposed(&mdiArea));
QCOMPARE(window1->geometry().topLeft(), QPoint(0, 0));
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Broken on WinRT - QTBUG-68297", Abort);
+#endif
QCOMPARE(window2->geometry().topLeft(), window1->geometry().topRight() + QPoint(1, 0));
QCOMPARE(window3->geometry().topLeft(), window2->geometry().topRight() + QPoint(1, 0));
}
@@ -2117,6 +2138,10 @@ void tst_QMdiArea::updateScrollBars()
subWindow1->showNormal();
qApp->processEvents();
QVERIFY(!subWindow1->isMaximized());
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Widgets are maximized by default on WinRT, so scroll bars might not be"
+ "visible", Abort);
+#endif
QVERIFY(hbar->style()->styleHint(QStyle::SH_ScrollBar_Transient) || hbar->isVisible());
QVERIFY(vbar->style()->styleHint(QStyle::SH_ScrollBar_Transient) || vbar->isVisible());
if (i == 0) {
@@ -2318,6 +2343,10 @@ void tst_QMdiArea::setViewMode()
QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList();
// Default.
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Widgets are maximized by default on WinRT, so scroll bars might not be"
+ "visible", Abort);
+#endif
QVERIFY(!activeSubWindow->isMaximized());
QTabBar *tabBar = mdiArea.findChild<QTabBar *>();
QVERIFY(!tabBar);
diff --git a/tests/auto/widgets/widgets/qmdisubwindow/qmdisubwindow.pro b/tests/auto/widgets/widgets/qmdisubwindow/qmdisubwindow.pro
index 4299f7711e..e33271428f 100644
--- a/tests/auto/widgets/widgets/qmdisubwindow/qmdisubwindow.pro
+++ b/tests/auto/widgets/widgets/qmdisubwindow/qmdisubwindow.pro
@@ -1,6 +1,6 @@
CONFIG += testcase
TARGET = tst_qmdisubwindow
-QT += widgets testlib
+QT += widgets widgets-private testlib
INCLUDEPATH += .
SOURCES += tst_qmdisubwindow.cpp
DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII
diff --git a/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp b/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp
index 360e0c93c4..8b2f032172 100644
--- a/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp
+++ b/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp
@@ -30,6 +30,7 @@
#include <QtTest/QtTest>
#include "qmdisubwindow.h"
+#include "private/qmdisubwindow_p.h"
#include "qmdiarea.h"
#include <QLayout>
@@ -517,6 +518,9 @@ void tst_QMdiSubWindow::emittingOfSignals()
}
}
}
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("windowMaximized", "Broken on WinRT - QTBUG-68297", Abort);
+#endif
QCOMPARE(count, 1);
window->setParent(0);
@@ -542,6 +546,9 @@ void tst_QMdiSubWindow::showShaded()
QVERIFY(QTest::qWaitForWindowExposed(&workspace));
QVERIFY(!window->isShaded());
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Windows are maximized per default on WinRt ", Abort);
+#endif
QVERIFY(!window->isMaximized());
QCOMPARE(window->size(), QSize(300, 300));
@@ -634,6 +641,10 @@ void tst_QMdiSubWindow::showNormal()
qApp->processEvents();
window->showNormal();
qApp->processEvents();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("showMinimized", "Windows are maximized per default on WinRt ", Abort);
+ QEXPECT_FAIL("showMaximized", "Windows are maximized per default on WinRt ", Abort);
+#endif
QCOMPARE(window->geometry(), originalGeometry);
}
@@ -713,7 +724,9 @@ void tst_QMdiSubWindow::setOpaqueResizeAndMove()
resizeSpy.clear();
QCOMPARE(resizeSpy.count(), 0);
- QTest::qWait(250); // delayed update of dirty regions
+ // we need to wait for the resizeTimer to make sure updateDirtyRegions is called
+ auto priv = static_cast<QMdiSubWindowPrivate*>(qt_widget_private(window));
+ QTRY_COMPARE(priv->resizeTimerId, -1);
// Enter resize mode.
int offset = window->style()->pixelMetric(QStyle::PM_MDIFrameWidth) / 2;
@@ -740,6 +753,9 @@ void tst_QMdiSubWindow::setOpaqueResizeAndMove()
// Leave resize mode
sendMouseRelease(mouseReceiver, mousePosition);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Fails on WinRT - QTBUG-68297", Abort);
+#endif
QCOMPARE(resizeSpy.count(), expectedGeometryCount);
QCOMPARE(window->size(), windowSize + QSize(geometryCount, geometryCount));
}
@@ -903,6 +919,9 @@ void tst_QMdiSubWindow::mouseDoubleClick()
workspace.show();
window->show();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Windows are maximized per default on WinRt ", Abort);
+#endif
QVERIFY(!window->isMaximized());
QVERIFY(!window->isShaded());
@@ -971,6 +990,9 @@ void tst_QMdiSubWindow::setSystemMenu()
QVERIFY(!qApp->activePopupWidget());
subWindow->showSystemMenu();
QTRY_COMPARE(qApp->activePopupWidget(), qobject_cast<QWidget *>(systemMenu));
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Broken on WinRT - QTBUG-68297", Abort);
+#endif
QTRY_COMPARE(systemMenu->mapToGlobal(QPoint(0, 0)),
(globalPopupPos = subWindow->mapToGlobal(subWindow->contentsRect().topLeft())) );
@@ -1196,6 +1218,9 @@ void tst_QMdiSubWindow::restoreFocusOverCreation()
QTRY_COMPARE(QApplication::focusWidget(), subWidget2->m_lineEdit1);
mdiArea.setActiveSubWindow(subWindow1);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Broken on WinRt - QTBUG-68297", Abort);
+#endif
QTRY_COMPARE(QApplication::focusWidget(), subWidget1->m_lineEdit2);
}
@@ -1404,6 +1429,9 @@ void tst_QMdiSubWindow::resizeEvents()
QCOMPARE(window->widget()->windowState(), windowState);
// Make sure we got as many resize events as expected.
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("maximized", "Broken on WinRT - QTBUG-68297", Abort);
+#endif
QCOMPARE(windowResizeEventSpy.count(), expectedWindowResizeEvents);
QCOMPARE(widgetResizeEventSpy.count(), expectedWidgetResizeEvents);
windowResizeEventSpy.clear();
@@ -1413,6 +1441,10 @@ void tst_QMdiSubWindow::resizeEvents()
window->showNormal();
// Check that the window state is correct.
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("minimized", "Broken on WinRT - QTBUG-68297", Abort);
+ QEXPECT_FAIL("shaded", "Broken on WinRT - QTBUG-68297", Abort);
+#endif
QCOMPARE(window->windowState(), Qt::WindowNoState | Qt::WindowActive);
QCOMPARE(window->widget()->windowState(), Qt::WindowNoState);
@@ -1673,6 +1705,9 @@ void tst_QMdiSubWindow::fixedMinMaxSize()
QCOMPARE(subWindow->maximumSize(), maximumSize);
mdiArea.addSubWindow(subWindow);
subWindow->show();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Windows are maximized per default on WinRt ", Abort);
+#endif
QCOMPARE(subWindow->size(), minimumSize);
// Calculate the size of a minimized sub window.
@@ -2057,6 +2092,9 @@ void tst_QMdiSubWindow::testFullScreenState()
subWindow->showFullScreen(); // QMdiSubWindow does not support the fullscreen state. This call
// should be equivalent to setVisible(true) (and not showNormal())
QVERIFY(QTest::qWaitForWindowExposed(&mdiArea));
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Windows are maximized per default on WinRt ", Abort);
+#endif
QCOMPARE(subWindow->size(), QSize(300, 300));
}
diff --git a/tests/auto/widgets/widgets/qmenu/BLACKLIST b/tests/auto/widgets/widgets/qmenu/BLACKLIST
index 1c970c43b3..89d12a259f 100644
--- a/tests/auto/widgets/widgets/qmenu/BLACKLIST
+++ b/tests/auto/widgets/widgets/qmenu/BLACKLIST
@@ -10,3 +10,5 @@ osx ci
osx
[tearOff]
osx
+[activeSubMenuPosition]
+winrt
diff --git a/tests/auto/widgets/widgets/qmenu/qmenu.pro b/tests/auto/widgets/widgets/qmenu/qmenu.pro
index 84b6530184..4a492ee941 100644
--- a/tests/auto/widgets/widgets/qmenu/qmenu.pro
+++ b/tests/auto/widgets/widgets/qmenu/qmenu.pro
@@ -5,4 +5,6 @@ SOURCES += tst_qmenu.cpp
macx:{
OBJECTIVE_SOURCES += tst_qmenu_mac.mm
LIBS += -lobjc
+} else {
+ DEFINES += QTEST_QPA_MOUSE_HANDLING
}
diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp
index 0dde385bdb..a88fd8d19c 100644
--- a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp
+++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp
@@ -29,6 +29,7 @@
#include <QtTest/QtTest>
#include <QtTest/private/qtesthelpers_p.h>
#include <qapplication.h>
+#include <private/qguiapplication_p.h>
#include <QPushButton>
#include <QMainWindow>
#include <QMenuBar>
@@ -48,6 +49,7 @@
#include <qdebug.h>
#include <qpa/qplatformtheme.h>
+#include <qpa/qplatformintegration.h>
using namespace QTestPrivate;
@@ -459,6 +461,9 @@ void tst_QMenu::focus()
void tst_QMenu::overrideMenuAction()
{
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("Window activation is not supported");
+
//test the override menu action by first creating an action to which we set its menu
QMainWindow w;
w.resize(300, 200);
@@ -614,6 +619,9 @@ static QMenu *getTornOffMenu()
void tst_QMenu::tearOff()
{
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("Window activation is not supported");
+
QWidget widget;
QScopedPointer<QMenu> menu(new QMenu(&widget));
QVERIFY(!menu->isTearOffEnabled()); //default value
@@ -686,6 +694,9 @@ void tst_QMenu::tearOff()
void tst_QMenu::submenuTearOffDontClose()
{
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("Window activation is not supported");
+
QWidget widget;
QMenu *menu = new QMenu(&widget);
QVERIFY(!menu->isTearOffEnabled()); //default value
@@ -713,7 +724,8 @@ void tst_QMenu::submenuTearOffDontClose()
// Move then click to avoid the submenu moves from causing it to close
QTest::mouseMove(menu, submenuPos, 100);
QTest::mouseClick(menu, Qt::LeftButton, 0, submenuPos, 100);
- QTRY_VERIFY(QTest::qWaitForWindowActive(submenu));
+ QVERIFY(QTest::qWaitFor([&]() { return submenu->window()->windowHandle(); }));
+ QVERIFY(QTest::qWaitForWindowActive(submenu));
// Make sure we enter the submenu frame directly on the tear-off area
QTest::mouseMove(submenu, QPoint(10, 3), 100);
if (submenu->style()->styleHint(QStyle::SH_Menu_SubMenuDontStartSloppyOnLeave)) {
@@ -843,6 +855,10 @@ private:
void tst_QMenu::activeSubMenuPositionExec()
{
+
+#ifdef Q_OS_WINRT
+ QSKIP("Broken on WinRT - QTBUG-68297");
+#endif
SubMenuPositionExecMenu menu;
menu.exec(QGuiApplication::primaryScreen()->availableGeometry().center());
}
@@ -986,9 +1002,6 @@ void tst_QMenu::task258920_mouseBorder()
QAction *action = menu.addAction("test");
const QPoint center = QApplication::desktop()->availableGeometry().center();
-#ifndef QT_NO_CURSOR
- QCursor::setPos(center - QPoint(100, 100)); // Mac: Ensure cursor is outside
-#endif
menu.popup(center);
QVERIFY(QTest::qWaitForWindowExposed(&menu));
QRect actionRect = menu.actionGeometry(action);
@@ -1082,6 +1095,9 @@ void tst_QMenu::pushButtonPopulateOnAboutToShow()
QTimer::singleShot(300, buttonMenu, SLOT(hide()));
QTest::mouseClick(&b, Qt::LeftButton, Qt::NoModifier, b.rect().center());
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "WinRT does not support QTest::mouseClick", Abort);
+#endif
QVERIFY2(!buttonMenu->geometry().intersects(b.geometry()), msgGeometryIntersects(buttonMenu->geometry(), b.geometry()));
// note: we're assuming that, if we previously got the desired geometry, we'll get it here too
@@ -1180,6 +1196,9 @@ void tst_QMenu::click_while_dismissing_submenu()
//this opens the submenu, move two times to emulate user interaction (d->motions > 0 in QMenu)
QTest::mouseMove(menuWindow, menu.rect().center() + QPoint(0,2));
QTest::mouseMove(menuWindow, menu.rect().center() + QPoint(1,3), 60);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "WinRT does not support QTest::mouseMove", Abort);
+#endif
QVERIFY(menuShownSpy.wait());
QVERIFY(sub.isVisible());
QVERIFY(QTest::qWaitForWindowExposed(&sub));
@@ -1229,96 +1248,95 @@ public:
void tst_QMenu::QTBUG47515_widgetActionEnterLeave()
{
-#if !QT_CONFIG(cursor)
- QSKIP("This test requires QCursor API");
-#else
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("Window activation is not supported");
if (QGuiApplication::platformName() == QLatin1String("cocoa"))
QSKIP("See QTBUG-63031");
- QPoint screenCenter = QGuiApplication::primaryScreen()->availableGeometry().center();
- QPoint pointOutsideMenu = screenCenter - QPoint(100, 100);
+ const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry();
+ QRect geometry(QPoint(), availableGeometry.size() / 3);
+ geometry.moveCenter(availableGeometry.center());
+ QPoint pointOutsideMenu = geometry.bottomRight() - QPoint(5, 5);
- QMenu menu("Menu1");
- QMenu submenu("Menu2");
+ QMainWindow topLevel;
+ topLevel.setGeometry(geometry);
- QWidgetAction menuAction(&menu);
- MyWidget w1(&menu);
- menuAction.setDefaultWidget(&w1);
+ QMenuBar *menuBar = topLevel.menuBar();
+ menuBar->setNativeMenuBar(false);
+ QMenu *menu = menuBar->addMenu("Menu1");
+ QMenu *submenu = menu->addMenu("Menu2");
- QWidgetAction submenuAction(&submenu);
- MyWidget w2(&submenu);
- submenuAction.setDefaultWidget(&w2);
+ QWidgetAction *menuAction = new QWidgetAction(menu);
+ MyWidget *w1 = new MyWidget(menu);
+ menuAction->setDefaultWidget(w1);
- QAction *nextMenuAct = menu.addMenu(&submenu);
+ QWidgetAction *submenuAction = new QWidgetAction(submenu);
+ MyWidget *w2 = new MyWidget(submenu);
+ submenuAction->setDefaultWidget(w2);
- menu.addAction(&menuAction);
- submenu.addAction(&submenuAction);
+ QAction *nextMenuAct = menu->addMenu(submenu);
- // Root menu
- {
- QCursor::setPos(pointOutsideMenu);
- QTRY_COMPARE(QCursor::pos(), pointOutsideMenu);
- menu.popup(screenCenter);
- QVERIFY(QTest::qWaitForWindowExposed(&menu));
+ menu->addAction(menuAction);
+ submenu->addAction(submenuAction);
+
+ topLevel.show();
+ topLevel.setWindowTitle(QTest::currentTestFunction());
+ QVERIFY(QTest::qWaitForWindowActive(&topLevel));
+ QWindow *topLevelWindow = topLevel.windowHandle();
+ QVERIFY(topLevelWindow);
- w1.enter = 0;
- w1.leave = 0;
- QPoint w1Center = w1.rect().center();
- const QPoint w1CenterGlobal = w1.mapToGlobal(w1Center);
- QCursor::setPos(w1CenterGlobal);
- QTRY_COMPARE(QCursor::pos(), w1CenterGlobal);
- QVERIFY(w1.isVisible());
- QTRY_COMPARE(w1.leave, 0);
- QTRY_COMPARE(w1.enter, 1);
+ // Root menu: Click on menu bar to open menu1
+ {
+ const QPoint menuActionPos = menuBar->mapTo(&topLevel, menuBar->actionGeometry(menu->menuAction()).center());
+ QTest::mouseClick(topLevelWindow, Qt::LeftButton, Qt::KeyboardModifiers(), menuActionPos);
+ QVERIFY(QTest::qWaitForWindowExposed(menu));
+
+ w1->enter = 0;
+ w1->leave = 0;
+ QPoint w1Center = topLevel.mapFromGlobal(w1->mapToGlobal(w1->rect().center()));
+ QTest::mouseMove(topLevelWindow, w1Center);
+ QVERIFY(w1->isVisible());
+ QTRY_COMPARE(w1->leave, 0);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "WinRT does not support QTest::mouseMove", Abort);
+#endif
+ QTRY_COMPARE(w1->enter, 1);
// Check whether leave event is not delivered on mouse move
- w1.move = 0;
- QWidget *nativeParent = w1.nativeParentWidget();
- QVERIFY(nativeParent);
- QWindow *window = nativeParent->windowHandle();
- QVERIFY(window);
- QTest::mouseMove(window, w1.mapTo(nativeParent, w1Center + QPoint(1, 1)));
- QTRY_COMPARE(w1.move, 1);
- QTRY_COMPARE(w1.leave, 0);
- QTRY_COMPARE(w1.enter, 1);
-
- QCursor::setPos(pointOutsideMenu);
- QTRY_COMPARE(QCursor::pos(), pointOutsideMenu);
- QTRY_COMPARE(w1.leave, 1);
- QTRY_COMPARE(w1.enter, 1);
+ w1->move = 0;
+ QTest::mouseMove(topLevelWindow, w1Center + QPoint(1, 1));
+ QTRY_COMPARE(w1->move, 1);
+ QTRY_COMPARE(w1->leave, 0);
+ QTRY_COMPARE(w1->enter, 1);
+
+ QTest::mouseMove(topLevelWindow, topLevel.mapFromGlobal(pointOutsideMenu));
+ QTRY_COMPARE(w1->leave, 1);
+ QTRY_COMPARE(w1->enter, 1);
}
// Submenu
{
- menu.setActiveAction(nextMenuAct);
- QVERIFY(QTest::qWaitForWindowExposed(&submenu));
+ menu->setActiveAction(nextMenuAct);
+ QVERIFY(QTest::qWaitForWindowExposed(submenu));
- QPoint w2Center = w2.rect().center();
- const QPoint w2CenterGlobal = w2.mapToGlobal(w2Center);
- QCursor::setPos(w2CenterGlobal);
- QTRY_COMPARE(QCursor::pos(), w2CenterGlobal);
+ QPoint w2Center = topLevel.mapFromGlobal(w2->mapToGlobal(w2->rect().center()));
+ QTest::mouseMove(topLevelWindow, w2Center);
- QVERIFY(w2.isVisible());
- QTRY_COMPARE(w2.leave, 0);
- QTRY_COMPARE(w2.enter, 1);
+ QVERIFY(w2->isVisible());
+ QTRY_COMPARE(w2->leave, 0);
+ QTRY_COMPARE(w2->enter, 1);
// Check whether leave event is not delivered on mouse move
- w2.move = 0;
- QWidget *nativeParent = w2.nativeParentWidget();
- QVERIFY(nativeParent);
- QWindow *window = nativeParent->windowHandle();
- QVERIFY(window);
- QTest::mouseMove(window, w2.mapTo(nativeParent, w2Center + QPoint(1, 1)));
- QTRY_COMPARE(w2.move, 1);
- QTRY_COMPARE(w2.leave, 0);
- QTRY_COMPARE(w2.enter, 1);
-
- QCursor::setPos(pointOutsideMenu);
- QTRY_COMPARE(QCursor::pos(), pointOutsideMenu);
- QTRY_COMPARE(w2.leave, 1);
- QTRY_COMPARE(w2.enter, 1);
+ w2->move = 0;
+ QTest::mouseMove(topLevelWindow, w2Center + QPoint(1, 1));
+ QTRY_COMPARE(w2->move, 1);
+ QTRY_COMPARE(w2->leave, 0);
+ QTRY_COMPARE(w2->enter, 1);
+
+ QTest::mouseMove(topLevelWindow, topLevel.mapFromGlobal(pointOutsideMenu));
+ QTRY_COMPARE(w2->leave, 1);
+ QTRY_COMPARE(w2->enter, 1);
}
-#endif // QT_NO_CURSOR
}
class MyMenu : public QMenu
@@ -1407,6 +1425,9 @@ void tst_QMenu::QTBUG_56917_wideMenuSize()
menu.popup(QPoint());
QVERIFY(QTest::qWaitForWindowExposed(&menu));
QVERIFY(menu.isVisible());
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Broken on WinRT - QTBUG-68297", Abort);
+#endif
QVERIFY(menu.height() <= menuSizeHint.height());
}
@@ -1542,6 +1563,9 @@ void tst_QMenu::menuSize_Scrolling()
getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin);
QRect lastItem = actionGeometry(actions().at(actions().length() - 1));
QSize s = size();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Broken on WinRT - QTBUG-68297", Abort);
+#endif
QCOMPARE( s.width(), lastItem.right() + fw + hmargin + rightMargin + 1);
QMenu::showEvent(e);
}
@@ -1610,6 +1634,12 @@ void tst_QMenu::menuSize_Scrolling()
return;
QTest::keyClick(&menu, Qt::Key_End);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("data8", "Broken on WinRT - QTBUG-68297", Abort);
+ QEXPECT_FAIL("data9", "Broken on WinRT - QTBUG-68297", Abort);
+ QEXPECT_FAIL("data10", "Broken on WinRT - QTBUG-68297", Abort);
+ QEXPECT_FAIL("data11", "Broken on WinRT - QTBUG-68297", Abort);
+#endif
QTRY_COMPARE(menu.actionGeometry(actions.last()).right(),
menu.width() - mm.fw - mm.hmargin - leftMargin - 1);
QCOMPARE(menu.actionGeometry(actions.last()).bottom(),
@@ -1618,6 +1648,8 @@ void tst_QMenu::menuSize_Scrolling()
void tst_QMenu::tearOffMenuNotDisplayed()
{
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("Window activation is not supported");
QWidget widget;
QScopedPointer<QMenu> menu(new QMenu(&widget));
menu->setTearOffEnabled(true);
@@ -1653,6 +1685,9 @@ void tst_QMenu::tearOffMenuNotDisplayed()
void tst_QMenu::QTBUG_61039_menu_shortcuts()
{
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
+ QSKIP("Window activation is not supported");
+
QAction *actionKamen = new QAction("Action Kamen");
actionKamen->setShortcut(QKeySequence(QLatin1String("K")));
diff --git a/tests/auto/widgets/widgets/qmenubar/BLACKLIST b/tests/auto/widgets/widgets/qmenubar/BLACKLIST
index 9b8e07312d..f897797f00 100644
--- a/tests/auto/widgets/widgets/qmenubar/BLACKLIST
+++ b/tests/auto/widgets/widgets/qmenubar/BLACKLIST
@@ -1,5 +1,8 @@
[check_menuPosition]
ubuntu-16.04
#QTBUG-66255
+ubuntu-18.04
[activatedCount]
*
+[QTBUG_65488_hiddenActionTriggered]
+winrt
diff --git a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp
index ab82268578..3063d43aa6 100644
--- a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp
+++ b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp
@@ -1184,6 +1184,9 @@ void tst_QMenuBar::check_menuPosition()
mbItemRect.moveTo(w.menuBar()->mapToGlobal(mbItemRect.topLeft()));
QTest::keyClick(&w, Qt::Key_M, Qt::AltModifier );
QVERIFY(menu.isActiveWindow());
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "QTest::keyClick does not work on WinRT.", Abort);
+#endif
QCOMPARE(menu.pos(), QPoint(mbItemRect.x(), mbItemRect.top() - menu.height()));
menu.close();
}
@@ -1512,6 +1515,9 @@ void tst_QMenuBar::cornerWidgets()
case Qt::TopLeftCorner:
QVERIFY2(fileMenuGeometry.left() >= cornerWidgetWidth,
msgComparison(fileMenuGeometry.left(), ">=", cornerWidgetWidth));
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Broken on WinRT - QTBUG-68297", Abort);
+#endif
QVERIFY2(menuBarWidth - editMenuGeometry.right() < cornerWidgetWidth,
msgComparison(menuBarWidth - editMenuGeometry.right(), "<", cornerWidgetWidth));
break;
@@ -1754,7 +1760,6 @@ void tst_QMenuBar::QTBUG_57404_existingMenuItemException()
mb->addMenu(editMenu);
QAction *copyAction = editMenu->addAction("&Copy");
copyAction->setShortcut(QKeySequence("Ctrl+C"));
- QTest::ignoreMessage(QtWarningMsg, "Menu item \"&Copy\" has unsupported role QPlatformMenuItem::MenuRole(NoRole)");
copyAction->setMenuRole(QAction::NoRole);
QVERIFY(QTest::qWaitForWindowExposed(&mw2));
diff --git a/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp b/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp
index a08a8862b8..cfa2ddc4cc 100644
--- a/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp
+++ b/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp
@@ -1352,6 +1352,9 @@ void tst_QPlainTextEdit::adjustScrollbars()
QLatin1String txt("\nabc def ghi jkl mno pqr stu vwx");
ed->setPlainText(txt + txt + txt + txt);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "WinRT does not support setMinimum/MaximumSize", Abort);
+#endif
QVERIFY(ed->verticalScrollBar()->maximum() > 0);
ed->moveCursor(QTextCursor::End);
diff --git a/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp b/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp
index 39989c6dbb..df5ff9d448 100644
--- a/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp
+++ b/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp
@@ -255,6 +255,9 @@ void tst_QProgressBar::setMinMaxRepaint()
pbar.repainted = false;
pbar.setMinimum(0);
QTest::qWait(50);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Broken on WinRT - QTBUG-68297", Abort);
+#endif
QTRY_VERIFY(!pbar.repainted);
// No repaint when setting maximum to the current maximum
diff --git a/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp b/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp
index 625f38d8ae..66f4df4498 100644
--- a/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp
+++ b/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp
@@ -507,7 +507,7 @@ void tst_QPushButton::sizeHint_data()
#if !defined(QT_NO_STYLE_FUSION)
QTest::newRow("fusion") << QString::fromLatin1("fusion");
#endif
-#if defined(Q_OS_WIN) && !defined(QT_NO_STYLE_WINDOWSVISTA)
+#if defined(Q_OS_WIN) && !defined(QT_NO_STYLE_WINDOWSVISTA) && !defined(Q_OS_WINRT)
QTest::newRow("windowsvista") << QString::fromLatin1("windowsvista");
#endif
}
diff --git a/tests/auto/widgets/widgets/qsizegrip/BLACKLIST b/tests/auto/widgets/widgets/qsizegrip/BLACKLIST
deleted file mode 100644
index 2c874bcb57..0000000000
--- a/tests/auto/widgets/widgets/qsizegrip/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[hideAndShowOnWindowStateChange:Qt::Window]
-xcb
diff --git a/tests/auto/widgets/widgets/qsizegrip/tst_qsizegrip.cpp b/tests/auto/widgets/widgets/qsizegrip/tst_qsizegrip.cpp
index 7610adc155..4cc1810cd4 100644
--- a/tests/auto/widgets/widgets/qsizegrip/tst_qsizegrip.cpp
+++ b/tests/auto/widgets/widgets/qsizegrip/tst_qsizegrip.cpp
@@ -107,6 +107,9 @@ void tst_QSizeGrip::hideAndShowOnWindowStateChange_data()
void tst_QSizeGrip::hideAndShowOnWindowStateChange()
{
QFETCH(Qt::WindowType, windowType);
+#ifdef Q_OS_WINRT
+ QSKIP("Broken on WinRT - QTBUG-68297");
+#endif
QWidget *parentWidget = windowType == Qt::Window ? 0 : new QWidget;
TestWidget *widget = new TestWidget(parentWidget, Qt::WindowFlags(windowType));
@@ -152,6 +155,10 @@ void tst_QSizeGrip::hideAndShowOnWindowStateChange()
void tst_QSizeGrip::orientation()
{
+#ifdef Q_OS_WINRT
+ QSKIP("Broken on WinRT - QTBUG-68297");
+#endif
+
TestWidget widget;
widget.setLayout(new QVBoxLayout);
QSizeGrip *sizeGrip = new QSizeGrip(&widget);
@@ -198,7 +205,9 @@ void tst_QSizeGrip::dontCrashOnTLWChange()
// the above setup causes a change of TLW for the size grip,
// and it must not crash.
-
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Broken on WinRT - QTBUG-68297", Abort);
+#endif
QVERIFY(QTest::qWaitForWindowExposed(&mdiArea));
QVERIFY(QTest::qWaitForWindowExposed(mw));
}
diff --git a/tests/auto/widgets/widgets/qspinbox/BLACKLIST b/tests/auto/widgets/widgets/qspinbox/BLACKLIST
new file mode 100644
index 0000000000..a38511bfb4
--- /dev/null
+++ b/tests/auto/widgets/widgets/qspinbox/BLACKLIST
@@ -0,0 +1,3 @@
+[stepModifierPressAndHold]
+opensuse ci # QTBUG-69492
+opensuse-leap ci
diff --git a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp
index 57816f9f70..37bb28dec9 100644
--- a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp
+++ b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp
@@ -50,6 +50,9 @@
#include <QKeySequence>
#include <QStackedWidget>
#include <QDebug>
+#include <QStyleOptionSpinBox>
+#include <QStyle>
+#include <QProxyStyle>
class SpinBox : public QSpinBox
{
@@ -75,10 +78,54 @@ public:
QSpinBox::wheelEvent(event);
}
#endif
+ void initStyleOption(QStyleOptionSpinBox *option) const
+ {
+ QSpinBox::initStyleOption(option);
+ }
QLineEdit *lineEdit() const { return QSpinBox::lineEdit(); }
};
+class PressAndHoldStyle : public QProxyStyle
+{
+ Q_OBJECT
+public:
+ using QProxyStyle::QProxyStyle;
+
+ int styleHint(QStyle::StyleHint hint, const QStyleOption *option = nullptr,
+ const QWidget *widget = nullptr, QStyleHintReturn *returnData = nullptr) const override
+ {
+ switch (hint) {
+ case QStyle::SH_SpinBox_ClickAutoRepeatRate:
+ return 5;
+ case QStyle::SH_SpinBox_ClickAutoRepeatThreshold:
+ return 10;
+ default:
+ return QProxyStyle::styleHint(hint, option, widget, returnData);
+ }
+ }
+};
+
+class StepModifierStyle : public QProxyStyle
+{
+ Q_OBJECT
+public:
+ using QProxyStyle::QProxyStyle;
+
+ int styleHint(QStyle::StyleHint hint, const QStyleOption *option = nullptr,
+ const QWidget *widget = nullptr, QStyleHintReturn *returnData = nullptr) const override
+ {
+ switch (hint) {
+ case QStyle::SH_SpinBox_StepModifier:
+ return stepModifier;
+ default:
+ return QProxyStyle::styleHint(hint, option, widget, returnData);
+ }
+ }
+
+ Qt::KeyboardModifier stepModifier = Qt::ControlModifier;
+};
+
class tst_QSpinBox : public QObject
{
Q_OBJECT
@@ -143,8 +190,19 @@ private slots:
void setGroupSeparatorShown_data();
void setGroupSeparatorShown();
+ void wheelEvents_data();
void wheelEvents();
+ void adaptiveDecimalStep();
+
+ void stepModifierKeys_data();
+ void stepModifierKeys();
+
+ void stepModifierButtons_data();
+ void stepModifierButtons();
+
+ void stepModifierPressAndHold_data();
+ void stepModifierPressAndHold();
public slots:
void valueChangedHelper(const QString &);
void valueChangedHelper(int);
@@ -158,6 +216,30 @@ typedef QList<int> IntList;
Q_DECLARE_METATYPE(QLocale::Language)
Q_DECLARE_METATYPE(QLocale::Country)
+static QLatin1String modifierToName(Qt::KeyboardModifier modifier)
+{
+ switch (modifier) {
+ case Qt::NoModifier:
+ return QLatin1Literal("No");
+ break;
+ case Qt::ControlModifier:
+ return QLatin1Literal("Ctrl");
+ break;
+ case Qt::ShiftModifier:
+ return QLatin1Literal("Shift");
+ break;
+ case Qt::AltModifier:
+ return QLatin1Literal("Alt");
+ break;
+ case Qt::MetaModifier:
+ return QLatin1Literal("Meta");
+ break;
+ default:
+ qFatal("Unexpected keyboard modifier");
+ return QLatin1String();
+ }
+}
+
// Testing get/set functions
void tst_QSpinBox::getSetCheck()
{
@@ -410,13 +492,17 @@ void tst_QSpinBox::setReadOnly()
QTest::keyClick(&spin, Qt::Key_Up);
QCOMPARE(spin.value(), 1);
spin.setReadOnly(true);
+#ifndef Q_OS_WINRT // QTBUG-68297
QCOMPARE(spin.eventsReceived, QList<QEvent::Type>() << QEvent::ReadOnlyChange);
+#endif
QTest::keyClick(&spin, Qt::Key_Up);
QCOMPARE(spin.value(), 1);
spin.stepBy(1);
QCOMPARE(spin.value(), 2);
spin.setReadOnly(false);
+#ifndef Q_OS_WINRT // QTBUG-68297
QCOMPARE(spin.eventsReceived, QList<QEvent::Type>() << QEvent::ReadOnlyChange << QEvent::ReadOnlyChange);
+#endif
QTest::keyClick(&spin, Qt::Key_Up);
QCOMPARE(spin.value(), 3);
}
@@ -1215,28 +1301,505 @@ void tst_QSpinBox::setGroupSeparatorShown()
QCOMPARE(spinBox.value()+1000, 33000);
}
+void tst_QSpinBox::wheelEvents_data()
+{
+#if QT_CONFIG(wheelevent)
+ QTest::addColumn<QPoint>("angleDelta");
+ QTest::addColumn<int>("qt4Delta");
+ QTest::addColumn<int>("stepModifier");
+ QTest::addColumn<Qt::KeyboardModifiers>("modifier");
+ QTest::addColumn<Qt::MouseEventSource>("source");
+ QTest::addColumn<int>("start");
+ QTest::addColumn<IntList>("expectedValues");
+
+ const auto fractions = {false, true};
+
+ const auto directions = {true, false};
+
+ const auto modifierList = {Qt::NoModifier,
+ Qt::ShiftModifier,
+ Qt::ControlModifier,
+ Qt::AltModifier,
+ Qt::MetaModifier};
+
+ const auto validStepModifierList = {Qt::NoModifier,
+ Qt::ControlModifier,
+ Qt::ShiftModifier};
+
+ const auto sources = {Qt::MouseEventNotSynthesized,
+ Qt::MouseEventSynthesizedBySystem,
+ Qt::MouseEventSynthesizedByQt,
+ Qt::MouseEventSynthesizedByApplication};
+
+ const int startValue = 0;
+
+ for (auto fraction : fractions) {
+ for (auto up : directions) {
+
+ const int units = (fraction ? 60 : 120) * (up ? 1 : -1);
+
+ for (auto modifier : modifierList) {
+
+ const Qt::KeyboardModifiers modifiers(modifier);
+
+ const auto modifierName = modifierToName(modifier);
+ if (modifierName.isEmpty())
+ continue;
+
+ for (auto stepModifier : validStepModifierList) {
+
+ const auto stepModifierName = modifierToName(stepModifier);
+ if (stepModifierName.isEmpty())
+ continue;
+
+ const int steps = (modifier & stepModifier ? 10 : 1)
+ * (up ? 1 : -1);
+
+ for (auto source : sources) {
+
+#ifdef Q_OS_MACOS
+ QPoint angleDelta;
+ if ((modifier & Qt::ShiftModifier) &&
+ source == Qt::MouseEventNotSynthesized) {
+ // On macOS the Shift modifier converts vertical
+ // mouse wheel events to horizontal.
+ angleDelta = { units, 0 };
+ } else {
+ // However, this is not the case for trackpad scroll
+ // events.
+ angleDelta = { 0, units };
+ }
+#else
+ const QPoint angleDelta(0, units);
+#endif
+
+ QLatin1String sourceName;
+ switch (source) {
+ case Qt::MouseEventNotSynthesized:
+ sourceName = QLatin1Literal("NotSynthesized");
+ break;
+ case Qt::MouseEventSynthesizedBySystem:
+ sourceName = QLatin1Literal("SynthesizedBySystem");
+ break;
+ case Qt::MouseEventSynthesizedByQt:
+ sourceName = QLatin1Literal("SynthesizedByQt");
+ break;
+ case Qt::MouseEventSynthesizedByApplication:
+ sourceName = QLatin1Literal("SynthesizedByApplication");
+ break;
+ default:
+ qFatal("Unexpected wheel event source");
+ continue;
+ }
+
+ IntList expectedValues;
+ if (fraction)
+ expectedValues << startValue;
+ expectedValues << startValue + steps;
+
+ QTest::addRow("%s%s%sWith%sKeyboardModifier%s",
+ fraction ? "half" : "full",
+ up ? "Up" : "Down",
+ stepModifierName.latin1(),
+ modifierName.latin1(),
+ sourceName.latin1())
+ << angleDelta
+ << units
+ << static_cast<int>(stepModifier)
+ << modifiers
+ << source
+ << startValue
+ << expectedValues;
+ }
+ }
+ }
+ }
+ }
+#else
+ QSKIP("Built with --no-feature-wheelevent");
+#endif
+}
+
void tst_QSpinBox::wheelEvents()
{
#if QT_CONFIG(wheelevent)
+ QFETCH(QPoint, angleDelta);
+ QFETCH(int, qt4Delta);
+ QFETCH(int, stepModifier);
+ QFETCH(Qt::KeyboardModifiers, modifier);
+ QFETCH(Qt::MouseEventSource, source);
+ QFETCH(int, start);
+ QFETCH(IntList, expectedValues);
+
SpinBox spinBox;
spinBox.setRange(-20, 20);
+ spinBox.setValue(start);
+
+ QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> style(
+ new StepModifierStyle);
+ style->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
+ spinBox.setStyle(style.data());
+
+ QWheelEvent event(QPointF(), QPointF(), QPoint(), angleDelta, qt4Delta,
+ Qt::Vertical, Qt::NoButton, modifier, Qt::NoScrollPhase,
+ source);
+ for (int expected : expectedValues) {
+ qApp->sendEvent(&spinBox, &event);
+ QCOMPARE(spinBox.value(), expected);
+ }
+#else
+ QSKIP("Built with --no-feature-wheelevent");
+#endif
+}
+
+void tst_QSpinBox::adaptiveDecimalStep()
+{
+ SpinBox spinBox;
+ spinBox.setRange(-100000, 100000);
+ spinBox.setStepType(SpinBox::StepType::AdaptiveDecimalStepType);
+
+ // Positive values
+
spinBox.setValue(0);
- QWheelEvent wheelUp(QPointF(), QPointF(), QPoint(), QPoint(0, 120), 120, Qt::Vertical, Qt::NoButton, Qt::NoModifier);
- spinBox.wheelEvent(&wheelUp);
- QCOMPARE(spinBox.value(), 1);
+ // Go from 0 to 100
+ for (int i = 0; i < 100; i++) {
+ QCOMPARE(spinBox.value(), i);
+ spinBox.stepBy(1);
+ }
- QWheelEvent wheelDown(QPointF(), QPointF(), QPoint(), QPoint(0, -120), -120, Qt::Vertical, Qt::NoButton, Qt::NoModifier);
- spinBox.wheelEvent(&wheelDown);
- spinBox.wheelEvent(&wheelDown);
- QCOMPARE(spinBox.value(), -1);
+ // Go from 100 to 1000
+ for (int i = 100; i < 1000; i += 10) {
+ QCOMPARE(spinBox.value(), i);
+ spinBox.stepBy(1);
+ }
- QWheelEvent wheelHalfUp(QPointF(), QPointF(), QPoint(), QPoint(0, 60), 60, Qt::Vertical, Qt::NoButton, Qt::NoModifier);
- spinBox.wheelEvent(&wheelHalfUp);
- QCOMPARE(spinBox.value(), -1);
- spinBox.wheelEvent(&wheelHalfUp);
- QCOMPARE(spinBox.value(), 0);
-#endif
+ // Go from 1000 to 10000
+ for (int i = 1000; i < 10000; i += 100) {
+ QCOMPARE(spinBox.value(), i);
+ spinBox.stepBy(1);
+ }
+
+ // Test decreasing the values now
+
+ // Go from 10000 down to 1000
+ for (int i = 10000; i > 1000; i -= 100) {
+ QCOMPARE(spinBox.value(), i);
+ spinBox.stepBy(-1);
+ }
+
+ // Go from 1000 down to 100
+ for (int i = 1000; i > 100; i -= 10) {
+ QCOMPARE(spinBox.value(), i);
+ spinBox.stepBy(-1);
+ }
+
+ // Negative values
+
+ spinBox.setValue(0);
+
+ // Go from 0 to -100
+ for (int i = 0; i > -100; i--) {
+ QCOMPARE(spinBox.value(), i);
+ spinBox.stepBy(-1);
+ }
+
+ // Go from -100 to -1000
+ for (int i = -100; i > -1000; i -= 10) {
+ QCOMPARE(spinBox.value(), i);
+ spinBox.stepBy(-1);
+ }
+
+ // Go from 1000 to 10000
+ for (int i = -1000; i > -10000; i -= 100) {
+ QCOMPARE(spinBox.value(), i);
+ spinBox.stepBy(-1);
+ }
+
+ // Test increasing the values now
+
+ // Go from -10000 up to -1000
+ for (int i = -10000; i < -1000; i += 100) {
+ QCOMPARE(spinBox.value(), i);
+ spinBox.stepBy(1);
+ }
+
+ // Go from -1000 up to -100
+ for (int i = -1000; i < -100; i += 10) {
+ QCOMPARE(spinBox.value(), i);
+ spinBox.stepBy(1);
+ }
+}
+
+void tst_QSpinBox::stepModifierKeys_data()
+{
+ QTest::addColumn<int>("startValue");
+ QTest::addColumn<int>("stepModifier");
+ QTest::addColumn<QTestEventList>("keys");
+ QTest::addColumn<int>("expectedValue");
+
+ const auto keyList = {Qt::Key_Up, Qt::Key_Down};
+
+ const auto modifierList = {Qt::NoModifier,
+ Qt::ShiftModifier,
+ Qt::ControlModifier,
+ Qt::AltModifier,
+ Qt::MetaModifier};
+
+ const auto validStepModifierList = {Qt::NoModifier,
+ Qt::ControlModifier,
+ Qt::ShiftModifier};
+
+ for (auto key : keyList) {
+
+ const bool up = key == Qt::Key_Up;
+ Q_ASSERT(up || key == Qt::Key_Down);
+
+ const int startValue = up ? 0.0 : 10.0;
+
+ for (auto modifier : modifierList) {
+
+ QTestEventList keys;
+ keys.addKeyClick(key, modifier);
+
+ const auto modifierName = modifierToName(modifier);
+ if (modifierName.isEmpty())
+ continue;
+
+ for (auto stepModifier : validStepModifierList) {
+
+ const auto stepModifierName = modifierToName(stepModifier);
+ if (stepModifierName.isEmpty())
+ continue;
+
+ const int steps = (modifier & stepModifier ? 10 : 1)
+ * (up ? 1 : -1);
+
+ const int expectedValue = startValue + steps;
+
+ QTest::addRow("%s%sWith%sKeyboardModifier",
+ up ? "up" : "down",
+ stepModifierName.latin1(),
+ modifierName.latin1())
+ << startValue
+ << static_cast<int>(stepModifier)
+ << keys
+ << expectedValue;
+ }
+ }
+ }
+}
+
+void tst_QSpinBox::stepModifierKeys()
+{
+ QFETCH(int, startValue);
+ QFETCH(int, stepModifier);
+ QFETCH(QTestEventList, keys);
+ QFETCH(int, expectedValue);
+
+ QSpinBox spin(0);
+ spin.setValue(startValue);
+
+ QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> style(
+ new StepModifierStyle);
+ style->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
+ spin.setStyle(style.data());
+
+ spin.show();
+ QVERIFY(QTest::qWaitForWindowActive(&spin));
+
+ QCOMPARE(spin.value(), startValue);
+ keys.simulate(&spin);
+ QCOMPARE(spin.value(), expectedValue);
+}
+
+void tst_QSpinBox::stepModifierButtons_data()
+{
+ QTest::addColumn<QStyle::SubControl>("subControl");
+ QTest::addColumn<int>("stepModifier");
+ QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
+ QTest::addColumn<int>("startValue");
+ QTest::addColumn<int>("expectedValue");
+
+ const auto subControls = {QStyle::SC_SpinBoxUp, QStyle::SC_SpinBoxDown};
+
+ const auto modifierList = {Qt::NoModifier,
+ Qt::ShiftModifier,
+ Qt::ControlModifier,
+ Qt::AltModifier,
+ Qt::MetaModifier};
+
+ const auto validStepModifierList = {Qt::NoModifier,
+ Qt::ControlModifier,
+ Qt::ShiftModifier};
+
+ for (auto subControl : subControls) {
+
+ const bool up = subControl == QStyle::SC_SpinBoxUp;
+ Q_ASSERT(up || subControl == QStyle::SC_SpinBoxDown);
+
+ const int startValue = up ? 0 : 10;
+
+ for (auto modifier : modifierList) {
+
+ const Qt::KeyboardModifiers modifiers(modifier);
+
+ const auto modifierName = modifierToName(modifier);
+ if (modifierName.isEmpty())
+ continue;
+
+ for (auto stepModifier : validStepModifierList) {
+
+ const auto stepModifierName = modifierToName(stepModifier);
+ if (stepModifierName.isEmpty())
+ continue;
+
+ const int steps = (modifier & stepModifier ? 10 : 1)
+ * (up ? 1 : -1);
+
+ const int expectedValue = startValue + steps;
+
+ QTest::addRow("%s%sWith%sKeyboardModifier",
+ up ? "up" : "down",
+ stepModifierName.latin1(),
+ modifierName.latin1())
+ << subControl
+ << static_cast<int>(stepModifier)
+ << modifiers
+ << startValue
+ << expectedValue;
+ }
+ }
+ }
+}
+
+void tst_QSpinBox::stepModifierButtons()
+{
+ QFETCH(QStyle::SubControl, subControl);
+ QFETCH(int, stepModifier);
+ QFETCH(Qt::KeyboardModifiers, modifiers);
+ QFETCH(int, startValue);
+ QFETCH(int, expectedValue);
+
+ SpinBox spin(0);
+ spin.setRange(-20, 20);
+ spin.setValue(startValue);
+
+ QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> style(
+ new StepModifierStyle);
+ style->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
+ spin.setStyle(style.data());
+
+ spin.show();
+ QVERIFY(QTest::qWaitForWindowActive(&spin));
+
+ QStyleOptionSpinBox spinBoxStyleOption;
+ spin.initStyleOption(&spinBoxStyleOption);
+
+ const QRect buttonRect = spin.style()->subControlRect(
+ QStyle::CC_SpinBox, &spinBoxStyleOption, subControl, &spin);
+
+ QCOMPARE(spin.value(), startValue);
+ QTest::mouseClick(&spin, Qt::LeftButton, modifiers, buttonRect.center());
+ QCOMPARE(spin.value(), expectedValue);
+}
+
+void tst_QSpinBox::stepModifierPressAndHold_data()
+{
+ QTest::addColumn<QStyle::SubControl>("subControl");
+ QTest::addColumn<int>("stepModifier");
+ QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
+ QTest::addColumn<int>("expectedStepModifier");
+
+ const auto subControls = {QStyle::SC_SpinBoxUp, QStyle::SC_SpinBoxDown};
+
+ const auto modifierList = {Qt::NoModifier,
+ Qt::ShiftModifier,
+ Qt::ControlModifier,
+ Qt::AltModifier,
+ Qt::MetaModifier};
+
+ const auto validStepModifierList = {Qt::NoModifier,
+ Qt::ControlModifier,
+ Qt::ShiftModifier};
+
+ for (auto subControl : subControls) {
+
+ const bool up = subControl == QStyle::SC_SpinBoxUp;
+ Q_ASSERT(up || subControl == QStyle::SC_SpinBoxDown);
+
+ for (auto modifier : modifierList) {
+
+ const Qt::KeyboardModifiers modifiers(modifier);
+
+ const auto modifierName = modifierToName(modifier);
+ if (modifierName.isEmpty())
+ continue;
+
+ for (auto stepModifier : validStepModifierList) {
+
+ const auto stepModifierName = modifierToName(stepModifier);
+ if (stepModifierName.isEmpty())
+ continue;
+
+ const int steps = (modifier & stepModifier ? 10 : 1)
+ * (up ? 1 : -1);
+
+ QTest::addRow("%s%sWith%sKeyboardModifier",
+ up ? "up" : "down",
+ stepModifierName.latin1(),
+ modifierName.latin1())
+ << subControl
+ << static_cast<int>(stepModifier)
+ << modifiers
+ << steps;
+ }
+ }
+ }
+}
+
+void tst_QSpinBox::stepModifierPressAndHold()
+{
+ QFETCH(QStyle::SubControl, subControl);
+ QFETCH(int, stepModifier);
+ QFETCH(Qt::KeyboardModifiers, modifiers);
+ QFETCH(int, expectedStepModifier);
+
+ SpinBox spin(0);
+ spin.setRange(-100, 100);
+ spin.setValue(0);
+
+ QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> stepModifierStyle(
+ new StepModifierStyle(new PressAndHoldStyle));
+ stepModifierStyle->stepModifier = static_cast<Qt::KeyboardModifier>(stepModifier);
+ spin.setStyle(stepModifierStyle.data());
+
+ QSignalSpy spy(&spin, QOverload<int>::of(&SpinBox::valueChanged));
+ // TODO: remove debug output when QTBUG-69492 is fixed
+ connect(&spin, QOverload<int>::of(&SpinBox::valueChanged), [=]() {
+ qDebug() << QTime::currentTime() << "valueChanged emitted";
+ });
+
+ spin.show();
+ QVERIFY(QTest::qWaitForWindowActive(&spin));
+
+ QStyleOptionSpinBox spinBoxStyleOption;
+ spin.initStyleOption(&spinBoxStyleOption);
+
+ const QRect buttonRect = spin.style()->subControlRect(
+ QStyle::CC_SpinBox, &spinBoxStyleOption, subControl, &spin);
+
+ // TODO: remove debug output when QTBUG-69492 is fixed
+ qDebug() << "QGuiApplication::focusWindow():" << QGuiApplication::focusWindow();
+ qDebug() << "QGuiApplication::topLevelWindows():" << QGuiApplication::topLevelWindows();
+ QTest::mousePress(&spin, Qt::LeftButton, modifiers, buttonRect.center());
+ QTRY_VERIFY2(spy.length() >= 3, qPrintable(QString::fromLatin1(
+ "Expected valueChanged() to be emitted 3 or more times, but it was only emitted %1 times").arg(spy.length())));
+ QTest::mouseRelease(&spin, Qt::LeftButton, modifiers, buttonRect.center());
+
+ const auto value = spy.last().at(0);
+ QVERIFY(value.type() == QVariant::Int);
+ QCOMPARE(value.toInt(), spy.length() * expectedStepModifier);
}
QTEST_MAIN(tst_QSpinBox)
diff --git a/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp b/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp
index 77abf5e5a7..d744cece9c 100644
--- a/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp
+++ b/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp
@@ -773,12 +773,16 @@ void tst_QSplitter::replaceWidget()
const int expectedResizeCount = visible ? 1 : 0; // new widget only
const int expectedPaintCount = visible && !collapsed ? 2 : 0; // splitter and new widget
QTRY_COMPARE(ef.resizeCount, expectedResizeCount);
+#ifndef Q_OS_WINRT // QTBUG-68297
QTRY_COMPARE(ef.paintCount, expectedPaintCount);
+#endif
QCOMPARE(newWidget->parentWidget(), &sp);
QCOMPARE(newWidget->isVisible(), visible);
if (visible && !collapsed)
QCOMPARE(newWidget->geometry(), oldGeom);
+#ifndef Q_OS_WINRT // QTBUG-68297
QCOMPARE(newWidget->size().isEmpty(), !visible || collapsed);
+#endif
delete res;
}
QCOMPARE(sp.count(), count);
@@ -830,7 +834,9 @@ void tst_QSplitter::replaceWidgetWithSplitterChild()
QTRY_VERIFY(ef.resizeCount > 0);
QTRY_VERIFY(ef.paintCount > 0);
QCOMPARE(sp.count(), count + 1);
+#ifndef Q_OS_WINRT // QTBUG-68297
QCOMPARE(sp.sizes().mid(0, count), sizes);
+#endif
QCOMPARE(sp.sizes().last(), sibling->width());
} else {
// No-op for the rest
diff --git a/tests/auto/widgets/widgets/qstatusbar/tst_qstatusbar.cpp b/tests/auto/widgets/widgets/qstatusbar/tst_qstatusbar.cpp
index 14ee6cb9bd..928910344c 100644
--- a/tests/auto/widgets/widgets/qstatusbar/tst_qstatusbar.cpp
+++ b/tests/auto/widgets/widgets/qstatusbar/tst_qstatusbar.cpp
@@ -141,6 +141,9 @@ void tst_QStatusBar::setSizeGripEnabled()
QTRY_VERIFY(statusBar->isVisible());
QPointer<QSizeGrip> sizeGrip = statusBar->findChild<QSizeGrip *>();
QVERIFY(sizeGrip);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Fails on WinRT - QTBUG-68297", Abort);
+#endif
QVERIFY(sizeGrip->isVisible());
statusBar->setSizeGripEnabled(true);
diff --git a/tests/auto/widgets/widgets/qtextbrowser/qtextbrowser.pro b/tests/auto/widgets/widgets/qtextbrowser/qtextbrowser.pro
index 5416c1c71f..9680ffd871 100644
--- a/tests/auto/widgets/widgets/qtextbrowser/qtextbrowser.pro
+++ b/tests/auto/widgets/widgets/qtextbrowser/qtextbrowser.pro
@@ -5,3 +5,5 @@ SOURCES += tst_qtextbrowser.cpp
QT += widgets testlib
TESTDATA += *.html subdir/*
+
+builtin_testdata: DEFINES += BUILTIN_TESTDATA
diff --git a/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp b/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp
index 700fa505c1..8a1b228c71 100644
--- a/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp
+++ b/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp
@@ -29,7 +29,6 @@
#include <QtTest/QtTest>
#include <qtextbrowser.h>
-#include <qdatetime.h>
#include <qapplication.h>
#include <qscrollbar.h>
@@ -114,7 +113,7 @@ void tst_QTextBrowser::cleanup()
void tst_QTextBrowser::noReloadOnAnchorJump()
{
- QUrl url = QUrl::fromLocalFile("anchor.html");
+ QUrl url = QUrl::fromLocalFile(QFINDTESTDATA("anchor.html"));
browser->htmlLoadAttempts = 0;
browser->setSource(url);
@@ -130,11 +129,11 @@ void tst_QTextBrowser::noReloadOnAnchorJump()
void tst_QTextBrowser::bgColorOnSourceChange()
{
- browser->setSource(QUrl::fromLocalFile("pagewithbg.html"));
+ browser->setSource(QUrl::fromLocalFile(QFINDTESTDATA("pagewithbg.html")));
QVERIFY(browser->document()->rootFrame()->frameFormat().hasProperty(QTextFormat::BackgroundBrush));
QCOMPARE(browser->document()->rootFrame()->frameFormat().background().color(), QColor(Qt::blue));
- browser->setSource(QUrl::fromLocalFile("pagewithoutbg.html"));
+ browser->setSource(QUrl::fromLocalFile(QFINDTESTDATA("pagewithoutbg.html")));
QVERIFY(!browser->document()->rootFrame()->frameFormat().hasProperty(QTextFormat::BackgroundBrush));
}
@@ -147,7 +146,7 @@ void tst_QTextBrowser::forwardButton()
QVERIFY(browser->historyTitle(0).isEmpty());
QVERIFY(browser->historyTitle(1).isEmpty());
- browser->setSource(QUrl::fromLocalFile("pagewithbg.html"));
+ browser->setSource(QUrl::fromLocalFile(QFINDTESTDATA("pagewithbg.html")));
QVERIFY(!forwardEmissions.isEmpty());
QVariant val = forwardEmissions.takeLast()[0];
@@ -160,12 +159,12 @@ void tst_QTextBrowser::forwardButton()
QVERIFY(!val.toBool());
QVERIFY(browser->historyTitle(-1).isEmpty());
- QCOMPARE(browser->historyUrl(0), QUrl::fromLocalFile("pagewithbg.html"));
+ QCOMPARE(browser->historyUrl(0), QUrl::fromLocalFile(QFINDTESTDATA("pagewithbg.html")));
QCOMPARE(browser->documentTitle(), QString("Page With BG"));
QCOMPARE(browser->historyTitle(0), QString("Page With BG"));
QVERIFY(browser->historyTitle(1).isEmpty());
- browser->setSource(QUrl::fromLocalFile("anchor.html"));
+ browser->setSource(QUrl::fromLocalFile(QFINDTESTDATA("anchor.html")));
QVERIFY(!forwardEmissions.isEmpty());
val = forwardEmissions.takeLast()[0];
@@ -197,8 +196,11 @@ void tst_QTextBrowser::forwardButton()
QCOMPARE(browser->historyTitle(0), QString("Page With BG"));
QCOMPARE(browser->historyTitle(1), QString("Sample Anchor"));
- browser->setSource(QUrl("pagewithoutbg.html"));
+ browser->setSource(QUrl(QFINDTESTDATA("pagewithoutbg.html")));
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Fails on WinRT - QTBUG-68297", Abort);
+#endif
QVERIFY(!forwardEmissions.isEmpty());
val = forwardEmissions.takeLast()[0];
QCOMPARE(val.type(), QVariant::Bool);
@@ -212,11 +214,11 @@ void tst_QTextBrowser::forwardButton()
void tst_QTextBrowser::viewportPositionInHistory()
{
- browser->setSource(QUrl::fromLocalFile("bigpage.html"));
+ browser->setSource(QUrl::fromLocalFile(QFINDTESTDATA("bigpage.html")));
browser->scrollToAnchor("bottom");
QVERIFY(browser->verticalScrollBar()->value() > 0);
- browser->setSource(QUrl::fromLocalFile("pagewithbg.html"));
+ browser->setSource(QUrl::fromLocalFile(QFINDTESTDATA("pagewithbg.html")));
QCOMPARE(browser->verticalScrollBar()->value(), 0);
browser->backward();
@@ -225,6 +227,9 @@ void tst_QTextBrowser::viewportPositionInHistory()
void tst_QTextBrowser::relativeLinks()
{
+#ifdef BUILTIN_TESTDATA
+ QSKIP("Relative links cannot be checked when resources are used to package tests.");
+#endif
QSignalSpy sourceChangedSpy(browser, SIGNAL(sourceChanged(QUrl)));
browser->setSource(QUrl("subdir/../qtextbrowser.html"));
QVERIFY(!browser->document()->isEmpty());
@@ -256,11 +261,11 @@ void tst_QTextBrowser::relativeLinks()
void tst_QTextBrowser::anchors()
{
- browser->setSource(QUrl::fromLocalFile("bigpage.html"));
+ browser->setSource(QUrl::fromLocalFile(QFINDTESTDATA("bigpage.html")));
browser->setSource(QUrl("#bottom"));
QVERIFY(browser->verticalScrollBar()->value() > 0);
- browser->setSource(QUrl::fromLocalFile("bigpage.html"));
+ browser->setSource(QUrl::fromLocalFile(QFINDTESTDATA("bigpage.html")));
browser->setSource(QUrl("#id-anchor"));
QVERIFY(browser->verticalScrollBar()->value() > 0);
}
@@ -420,6 +425,9 @@ void tst_QTextBrowser::clearHistory()
void tst_QTextBrowser::sourceInsideLoadResource()
{
+#ifdef Q_OS_WINRT
+ QSKIP("Paths cannot be compared if applications are sandboxed.");
+#endif
QUrl url = QUrl::fromLocalFile("pagewithimage.html");
browser->setSource(url);
QCOMPARE(browser->lastResource, QUrl::fromLocalFile(QDir::current().filePath("foobar.png")));
@@ -515,7 +523,11 @@ void tst_QTextBrowser::adjacentAnchors()
void tst_QTextBrowser::loadResourceOnRelativeLocalFiles()
{
+#ifndef BUILTIN_TESTDATA
browser->setSource(QUrl::fromLocalFile("subdir/index.html"));
+#else
+ browser->setSource(QUrl::fromLocalFile(QFINDTESTDATA("subdir/index.html")));
+#endif
QVERIFY(!browser->toPlainText().isEmpty());
QVariant v = browser->loadResource(QTextDocument::HtmlResource, QUrl("../anchor.html"));
QVERIFY(v.isValid());
@@ -526,7 +538,7 @@ void tst_QTextBrowser::loadResourceOnRelativeLocalFiles()
void tst_QTextBrowser::focusIndicator()
{
HackBrowser *browser = new HackBrowser;
- browser->setSource(QUrl::fromLocalFile("firstpage.html"));
+ browser->setSource(QUrl::fromLocalFile(QFINDTESTDATA("firstpage.html")));
QVERIFY(!browser->textCursor().hasSelection());
browser->focusTheNextChild();
@@ -578,7 +590,7 @@ void tst_QTextBrowser::focusIndicator()
void tst_QTextBrowser::focusHistory()
{
HackBrowser *browser = new HackBrowser;
- browser->setSource(QUrl::fromLocalFile("firstpage.html"));
+ browser->setSource(QUrl::fromLocalFile(QFINDTESTDATA("firstpage.html")));
QVERIFY(!browser->textCursor().hasSelection());
browser->focusTheNextChild();
diff --git a/tests/auto/widgets/widgets/qtextedit/qtextedit.pro b/tests/auto/widgets/widgets/qtextedit/qtextedit.pro
index 8b39ab59b7..de8531daec 100644
--- a/tests/auto/widgets/widgets/qtextedit/qtextedit.pro
+++ b/tests/auto/widgets/widgets/qtextedit/qtextedit.pro
@@ -6,3 +6,5 @@ QT += widgets widgets-private gui-private core-private testlib
SOURCES += tst_qtextedit.cpp
osx: LIBS += -framework AppKit
+
+TESTDATA += fullWidthSelection
diff --git a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp
index f383d430d6..6a2ae4951b 100644
--- a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp
+++ b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp
@@ -1702,6 +1702,9 @@ void tst_QTextEdit::adjustScrollbars()
QLatin1String txt("\nabc def ghi jkl mno pqr stu vwx");
ed->setText(txt + txt + txt + txt);
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "setMinimum/MaximumSize does not work on WinRT", Abort);
+#endif
QVERIFY(ed->verticalScrollBar()->maximum() > 0);
ed->moveCursor(QTextCursor::End);
@@ -1882,6 +1885,9 @@ void tst_QTextEdit::copyPasteBackgroundImage()
QBrush ba = a->cellAt(0, 0).format().background();
QBrush bb = b->cellAt(0, 0).format().background();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Fails on WinRT - QTBUG-68297", Abort);
+#endif
QCOMPARE(ba.style(), Qt::TexturePattern);
QCOMPARE(ba.style(), bb.style());
diff --git a/tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp b/tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp
index a7a62496e6..44b30fa794 100644
--- a/tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp
+++ b/tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp
@@ -272,6 +272,9 @@ void tst_QToolButton::qtbug_34759_sizeHintResetWhenSettingMenu()
button1.show();
button2.show();
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "Winrt does not support more than 1 native top level widget.", Abort);
+#endif
QVERIFY(QTest::qWaitForWindowExposed(&button1));
QVERIFY(QTest::qWaitForWindowExposed(&button2));
diff --git a/tests/auto/widgets/widgets/widgets.pro b/tests/auto/widgets/widgets/widgets.pro
index c098108edc..c6325aac15 100644
--- a/tests/auto/widgets/widgets/widgets.pro
+++ b/tests/auto/widgets/widgets/widgets.pro
@@ -55,4 +55,4 @@ SUBDIRS=\
qtextedit \
qtoolbar \
-qtConfig(opengl): SUBDIRS += qopenglwidget
+!winrt:qtConfig(opengl): SUBDIRS += qopenglwidget
diff --git a/tests/baselineserver/shared/qbaselinetest.cpp b/tests/baselineserver/shared/qbaselinetest.cpp
index ef38e21edb..11fb208f20 100644
--- a/tests/baselineserver/shared/qbaselinetest.cpp
+++ b/tests/baselineserver/shared/qbaselinetest.cpp
@@ -46,6 +46,7 @@ static BaselineProtocol proto;
static bool connected = false;
static bool triedConnecting = false;
static bool dryRunMode = false;
+static enum { UploadMissing, UploadAll, UploadNone } baselinePolicy = UploadMissing;
static QByteArray curFunction;
static ImageItemList itemList;
@@ -71,12 +72,26 @@ void handleCmdLineArgs(int *argcp, char ***argvp)
if (arg == "-simfail") {
simfail = true;
+ } else if (arg == "-fuzzlevel") {
+ i++;
+ bool ok = false;
+ (void)nextArg.toInt(&ok);
+ if (!ok) {
+ qWarning() << "-fuzzlevel requires integer parameter";
+ showHelp = true;
+ break;
+ }
+ customInfo.insert("FuzzLevel", QString::fromLatin1(nextArg));
} else if (arg == "-auto") {
customAutoModeSet = true;
customInfo.setAdHocRun(false);
} else if (arg == "-adhoc") {
customAutoModeSet = true;
customInfo.setAdHocRun(true);
+ } else if (arg == "-setbaselines") {
+ baselinePolicy = UploadAll;
+ } else if (arg == "-nosetbaselines") {
+ baselinePolicy = UploadNone;
} else if (arg == "-compareto") {
i++;
int split = qMax(0, nextArg.indexOf('='));
@@ -106,8 +121,11 @@ void handleCmdLineArgs(int *argcp, char ***argvp)
QTextStream out(stdout);
out << "\n Baseline testing (lancelot) options:\n";
out << " -simfail : Force an image comparison mismatch. For testing purposes.\n";
+ out << " -fuzzlevel <int> : Specify the percentage of fuzziness in comparison. Overrides server default. 0 means exact match.\n";
out << " -auto : Inform server that this run is done by a daemon, CI system or similar.\n";
out << " -adhoc (default) : The inverse of -auto; this run is done by human, e.g. for testing.\n";
+ out << " -setbaselines : Store ALL rendered images as new baselines. Forces replacement of previous baselines.\n";
+ out << " -nosetbaselines : Do not store rendered images as new baselines when previous baselines are missing.\n";
out << " -compareto KEY=VAL : Force comparison to baselines from a different client,\n";
out << " for example: -compareto QtVersion=4.8.0\n";
out << " Multiple -compareto client specifications may be given.\n";
@@ -276,8 +294,8 @@ bool compareItem(const ImageItem &baseline, const QImage &img, QByteArray *msg,
return true;
break;
case ImageItem::BaselineNotFound:
- if (!customInfo.overrides().isEmpty()) {
- qWarning() << "Cannot compare to other system's baseline: No such baseline found on server.";
+ if (!customInfo.overrides().isEmpty() || baselinePolicy == UploadNone) {
+ qWarning() << "Cannot compare to baseline: No such baseline found on server.";
return true;
}
if (proto.submitNewBaseline(item, &srvMsg))
@@ -298,6 +316,14 @@ bool compareItem(const ImageItem &baseline, const QImage &img, QByteArray *msg,
qWarning() << "Failed to report image match to server:" << srvMsg;
return true;
}
+ // At this point, we have established a legitimate mismatch
+ if (baselinePolicy == UploadAll) {
+ if (proto.submitNewBaseline(item, &srvMsg))
+ qDebug() << msg->constData() << "Forcing new baseline; uploaded ok.";
+ else
+ qDebug() << msg->constData() << "Forcing new baseline; uploading failed:" << srvMsg;
+ return true;
+ }
bool fuzzyMatch = false;
bool res = proto.submitMismatch(item, &srvMsg, &fuzzyMatch);
if (res && fuzzyMatch) {
diff --git a/tests/benchmarks/corelib/tools/qtimezone/main.cpp b/tests/benchmarks/corelib/tools/qtimezone/main.cpp
new file mode 100644
index 0000000000..65455a7261
--- /dev/null
+++ b/tests/benchmarks/corelib/tools/qtimezone/main.cpp
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QTimeZone>
+#include <QTest>
+#include <qdebug.h>
+
+class tst_QTimeZone : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void isTimeZoneIdAvailable();
+};
+
+void tst_QTimeZone::isTimeZoneIdAvailable()
+{
+ const QList<QByteArray> available = QTimeZone::availableTimeZoneIds();
+ QBENCHMARK {
+ for (const QByteArray &id : available)
+ QVERIFY(QTimeZone::isTimeZoneIdAvailable(id));
+ }
+}
+
+QTEST_MAIN(tst_QTimeZone)
+
+#include "main.moc"
diff --git a/tests/benchmarks/corelib/tools/qtimezone/qtimezone.pro b/tests/benchmarks/corelib/tools/qtimezone/qtimezone.pro
new file mode 100644
index 0000000000..d0531b568b
--- /dev/null
+++ b/tests/benchmarks/corelib/tools/qtimezone/qtimezone.pro
@@ -0,0 +1,4 @@
+TARGET = tst_bench_qtimezone
+QT = core testlib
+
+SOURCES += main.cpp
diff --git a/tests/benchmarks/corelib/tools/tools.pro b/tests/benchmarks/corelib/tools/tools.pro
index af9b7d241d..ca9c0a6f89 100644
--- a/tests/benchmarks/corelib/tools/tools.pro
+++ b/tests/benchmarks/corelib/tools/tools.pro
@@ -15,6 +15,7 @@ SUBDIRS = \
qstring \
qstringbuilder \
qstringlist \
+ qtimezone \
qvector \
qalgorithms
diff --git a/tests/benchmarks/gui/graphicsview/graphicsview.pro b/tests/benchmarks/gui/graphicsview/graphicsview.pro
deleted file mode 100644
index d89a00c4b9..0000000000
--- a/tests/benchmarks/gui/graphicsview/graphicsview.pro
+++ /dev/null
@@ -1,16 +0,0 @@
-TEMPLATE = subdirs
-SUBDIRS = \
- functional \
- qgraphicsanchorlayout \
- qgraphicsitem \
- #qgraphicslayout \ # FIXME: broken
- qgraphicsscene \
- qgraphicsview \
- qgraphicswidget
-
-!qtHaveModule(widgets): SUBDIRS -= \
- qgraphicsanchorlayout \
- qgraphicsitem \
- qgraphicsscene \
- qgraphicsview \
- qgraphicswidget
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/benchmarks/gui/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
deleted file mode 100644
index 313cc56b0b..0000000000
--- a/tests/benchmarks/gui/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
+++ /dev/null
@@ -1,234 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <qtest.h>
-#include <QGraphicsItem>
-#include <QGraphicsScene>
-#include <QGraphicsView>
-
-class tst_QGraphicsItem : public QObject
-{
- Q_OBJECT
-
-public:
- tst_QGraphicsItem();
- virtual ~tst_QGraphicsItem();
-
-public slots:
- void initTestCase();
- void init();
- void cleanup();
-
-private slots:
- void setParentItem();
- void setParentItem_deep();
- void setParentItem_deep_reversed();
- void deleteItemWithManyChildren();
- void setPos_data();
- void setPos();
- void setTransform_data();
- void setTransform();
- void rotate();
- void scale();
- void shear();
- void translate();
-};
-
-tst_QGraphicsItem::tst_QGraphicsItem()
-{
-}
-
-tst_QGraphicsItem::~tst_QGraphicsItem()
-{
-}
-
-static inline void processEvents()
-{
- QApplication::processEvents();
- QApplication::processEvents();
-}
-
-void tst_QGraphicsItem::initTestCase()
-{
- processEvents();
- QTest::qWait(1500);
- processEvents();
-}
-
-void tst_QGraphicsItem::init()
-{
- processEvents();
-}
-
-void tst_QGraphicsItem::cleanup()
-{
-}
-
-void tst_QGraphicsItem::setParentItem()
-{
- QBENCHMARK {
- QGraphicsRectItem rect;
- QGraphicsRectItem *childRect = new QGraphicsRectItem;
- childRect->setParentItem(&rect);
- }
-}
-
-void tst_QGraphicsItem::setParentItem_deep()
-{
- QBENCHMARK {
- QGraphicsRectItem rect;
- QGraphicsRectItem *lastRect = &rect;
- for (int i = 0; i < 10; ++i) {
- QGraphicsRectItem *childRect = new QGraphicsRectItem;
- childRect->setParentItem(lastRect);
- lastRect = childRect;
- }
- QGraphicsItem *first = rect.childItems().first();
- first->setParentItem(0);
- }
-}
-
-void tst_QGraphicsItem::setParentItem_deep_reversed()
-{
- QBENCHMARK {
- QGraphicsRectItem *lastRect = new QGraphicsRectItem;
- for (int i = 0; i < 100; ++i) {
- QGraphicsRectItem *parentRect = new QGraphicsRectItem;
- lastRect->setParentItem(parentRect);
- lastRect = parentRect;
- }
- delete lastRect;
- }
-}
-
-void tst_QGraphicsItem::deleteItemWithManyChildren()
-{
- QBENCHMARK {
- QGraphicsRectItem *rect = new QGraphicsRectItem;
- for (int i = 0; i < 1000; ++i)
- new QGraphicsRectItem(rect);
- delete rect;
- }
-}
-
-void tst_QGraphicsItem::setPos_data()
-{
- QTest::addColumn<QPointF>("pos");
-
- QTest::newRow("0, 0") << QPointF(0, 0);
- QTest::newRow("10, 10") << QPointF(10, 10);
- QTest::newRow("-10, -10") << QPointF(-10, -10);
-}
-
-void tst_QGraphicsItem::setPos()
-{
- QFETCH(QPointF, pos);
-
- QGraphicsScene scene;
- QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100));
- processEvents();
-
- QBENCHMARK {
- rect->setPos(10, 10);
- }
-}
-
-void tst_QGraphicsItem::setTransform_data()
-{
- QTest::addColumn<QTransform>("transform");
-
- QTest::newRow("rotate 45z") << QTransform().rotate(45);
- QTest::newRow("scale 2x2") << QTransform().scale(2, 2);
- QTest::newRow("translate 100, 100") << QTransform().translate(100, 100);
- QTest::newRow("rotate 45x 45y 45z") << QTransform().rotate(45, Qt::XAxis)
- .rotate(45, Qt::YAxis).rotate(45, Qt::ZAxis);
-}
-
-void tst_QGraphicsItem::setTransform()
-{
- QFETCH(QTransform, transform);
-
- QGraphicsScene scene;
- QGraphicsRectItem *item = scene.addRect(QRectF(0, 0, 100, 100));
- processEvents();
-
- QBENCHMARK {
- item->setTransform(transform);
- }
-}
-
-void tst_QGraphicsItem::rotate()
-{
- QGraphicsScene scene;
- QGraphicsItem *item = scene.addRect(QRectF(0, 0, 100, 100));
- processEvents();
-
- const QTransform rotate(QTransform().rotate(45));
- QBENCHMARK {
- item->setTransform(rotate, true);
- }
-}
-
-void tst_QGraphicsItem::scale()
-{
- QGraphicsScene scene;
- QGraphicsItem *item = scene.addRect(QRectF(0, 0, 100, 100));
- processEvents();
-
- const QTransform scale(QTransform::fromScale(2, 2));
- QBENCHMARK {
- item->setTransform(scale, true);
- }
-}
-
-void tst_QGraphicsItem::shear()
-{
- QGraphicsScene scene;
- QGraphicsItem *item = scene.addRect(QRectF(0, 0, 100, 100));
- processEvents();
-
- const QTransform shear = QTransform().shear(1.5, 1.5);
- QBENCHMARK {
- item->setTransform(shear, true);
- }
-}
-
-void tst_QGraphicsItem::translate()
-{
- QGraphicsScene scene;
- QGraphicsItem *item = scene.addRect(QRectF(0, 0, 100, 100));
- processEvents();
-
- const QTransform translate = QTransform::fromTranslate(100, 100);
- QBENCHMARK {
- item->setTransform(translate, true);
- }
-}
-
-QTEST_MAIN(tst_QGraphicsItem)
-#include "tst_qgraphicsitem.moc"
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicslayout/qgraphicslayout.pro b/tests/benchmarks/gui/graphicsview/qgraphicslayout/qgraphicslayout.pro
deleted file mode 100644
index 9026fb37d8..0000000000
--- a/tests/benchmarks/gui/graphicsview/qgraphicslayout/qgraphicslayout.pro
+++ /dev/null
@@ -1,5 +0,0 @@
-TEMPLATE = app
-TARGET = tst_bench_qgraphicslayout
-QT += testlib
-SOURCES += tst_qgraphicslayout.cpp
-
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp b/tests/benchmarks/gui/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp
deleted file mode 100644
index 1db130203a..0000000000
--- a/tests/benchmarks/gui/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtTest/QtTest>
-#include <QtGui/qgraphicslayout.h>
-#include <QtGui/qgraphicslinearlayout.h>
-#include <QtGui/qgraphicswidget.h>
-#include <QtGui/qgraphicsview.h>
-
-class tst_QGraphicsLayout : public QObject
-{
- Q_OBJECT
-public:
- tst_QGraphicsLayout() {}
- ~tst_QGraphicsLayout() {}
-
-private slots:
- void invalidate();
-};
-
-
-class RectWidget : public QGraphicsWidget
-{
-public:
- RectWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0) : QGraphicsWidget(parent, wFlags), setGeometryCalls(0) {}
-
- void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
- {
- Q_UNUSED(option);
- Q_UNUSED(widget);
- painter->drawRoundRect(rect());
- painter->drawLine(rect().topLeft(), rect().bottomRight());
- painter->drawLine(rect().bottomLeft(), rect().topRight());
- }
-
- void setGeometry(const QRectF &rect)
- {
- //qDebug() << "setGeometry():" << this->data(0).toString();
- setGeometryCalls->insert(this, rect);
- QGraphicsWidget::setGeometry(rect);
- }
-
- void callUpdateGeometry() {
- QGraphicsWidget::updateGeometry();
- }
-
- QMap<RectWidget*, QRectF> *setGeometryCalls;
-};
-
-/**
- * Test to see how much time is needed to resize all widgets in a
- * layout-widget-layout-widget-.... hierarchy from the point where a
- * leaf widget changes its size hint. (updateGeometry() is called).
- *
- * If you run the test for 4.7 you'll get some really high numbers, but
- * that's because they also include painting (and possible processing of
- * some other events).
- */
-void tst_QGraphicsLayout::invalidate()
-{
- QGraphicsLayout::setInstantInvalidatePropagation(true);
- QGraphicsScene scene;
- QGraphicsView *view = new QGraphicsView(&scene);
- QMap<RectWidget*, QRectF> setGeometryCalls;
-
- RectWidget *window = new RectWidget(0, Qt::Window);
- window->setGeometryCalls = &setGeometryCalls;
- window->setData(0, QString(QChar('a')));
-
- scene.addItem(window);
- RectWidget *leaf = 0;
- const int depth = 100;
- RectWidget *parent = window;
- for (int i = 1; i < depth; ++i) {
- QGraphicsLinearLayout *l = new QGraphicsLinearLayout(parent);
- l->setContentsMargins(0,0,0,0);
- RectWidget *child = new RectWidget;
- child->setData(0, QString(QChar('a' + i)));
- child->setGeometryCalls = &setGeometryCalls;
- l->addItem(child);
- parent = child;
- }
- leaf = parent;
- leaf->setMinimumSize(QSizeF(1,1));
-
- view->show();
-
- QVERIFY(QTest::qWaitForWindowShown(view));
-
- // ...then measure...
-
- int pass = 1;
-
- // should be as small as possible, to reduce overhead of painting
- QSizeF size(1, 1);
- setGeometryCalls.clear();
- QBENCHMARK {
- leaf->setMinimumSize(size);
- leaf->setMaximumSize(size);
- while (setGeometryCalls.count() < depth) {
- QApplication::sendPostedEvents();
- }
- // force a resize on each widget, this will ensure
- // that each iteration will resize all 50 widgets
- int w = int(size.width());
- w^=2;
- size.setWidth(w);
- }
- delete view;
- QGraphicsLayout::setInstantInvalidatePropagation(false);
-}
-
-QTEST_MAIN(tst_QGraphicsLayout)
-
-#include "tst_qgraphicslayout.moc"
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicslinearlayout/qgraphicslinearlayout.pro b/tests/benchmarks/gui/graphicsview/qgraphicslinearlayout/qgraphicslinearlayout.pro
deleted file mode 100644
index 7126c8ecd6..0000000000
--- a/tests/benchmarks/gui/graphicsview/qgraphicslinearlayout/qgraphicslinearlayout.pro
+++ /dev/null
@@ -1,5 +0,0 @@
-TEMPLATE = app
-TARGET = tst_bench_qgraphicslinearlayout
-QT += testlib
-SOURCES += tst_qgraphicslinearlayout.cpp
-
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp b/tests/benchmarks/gui/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp
deleted file mode 100644
index 325fcfbb09..0000000000
--- a/tests/benchmarks/gui/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtTest/QtTest>
-#include <QtGui/qgraphicslinearlayout.h>
-#include <QtGui/qgraphicswidget.h>
-#include <QtGui/qgraphicsview.h>
-
-class tst_QGraphicsLinearLayout : public QObject
-{
- Q_OBJECT
-public:
- tst_QGraphicsLinearLayout() {}
- ~tst_QGraphicsLinearLayout() {}
-
-private slots:
- void heightForWidth_data();
- void heightForWidth();
-};
-
-
-struct MySquareWidget : public QGraphicsWidget
-{
- MySquareWidget() {}
- virtual QSizeF sizeHint ( Qt::SizeHint which, const QSizeF & constraint = QSizeF() ) const
- {
- if (which != Qt::PreferredSize)
- return QGraphicsWidget::sizeHint(which, constraint);
- if (constraint.width() < 0)
- return QGraphicsWidget::sizeHint(which, constraint);
- return QSizeF(constraint.width(), constraint.width());
- }
-};
-
-void tst_QGraphicsLinearLayout::heightForWidth_data()
-{
- QTest::addColumn<bool>("hfw");
- QTest::addColumn<bool>("nested");
-
- QTest::newRow("hfw") << true << false;
- QTest::newRow("hfw, nested") << true << true;
- QTest::newRow("not hfw") << false << false;
- QTest::newRow("not hfw, nested") << false << true;
-}
-
-void tst_QGraphicsLinearLayout::heightForWidth()
-{
- QFETCH(bool, hfw);
- QFETCH(bool, nested);
-
- QGraphicsScene scene;
- QGraphicsWidget *form = new QGraphicsWidget;
- scene.addItem(form);
-
- QGraphicsLinearLayout *outerlayout = 0;
- if (nested) {
- outerlayout = new QGraphicsLinearLayout(form);
- for (int i = 0; i < 8; i++) {
- QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical);
- outerlayout->addItem(layout);
- outerlayout = layout;
- }
- }
-
- QGraphicsLinearLayout *qlayout = 0;
- qlayout = new QGraphicsLinearLayout(Qt::Vertical);
- if (nested)
- outerlayout->addItem(qlayout);
- else
- form->setLayout(qlayout);
-
- MySquareWidget *widget = new MySquareWidget;
- for (int i = 0; i < 1; i++) {
- widget = new MySquareWidget;
- QSizePolicy sizepolicy = widget->sizePolicy();
- sizepolicy.setHeightForWidth(hfw);
- widget->setSizePolicy(sizepolicy);
- qlayout->addItem(widget);
- }
- // make sure only one iteration is done.
- // run with tst_QGraphicsLinearLayout.exe "heightForWidth" -tickcounter -iterations 6
- // this will iterate 6 times the whole test, (not only the benchmark)
- // which should reduce warmup time and give a realistic picture of the performance of
- // effectiveSizeHint()
- QSizeF constraint(hfw ? 100 : -1, -1);
- QBENCHMARK {
- (void)form->effectiveSizeHint(Qt::PreferredSize, constraint);
- }
-
-}
-
-
-QTEST_MAIN(tst_QGraphicsLinearLayout)
-
-#include "tst_qgraphicslinearlayout.moc"
diff --git a/tests/benchmarks/gui/gui.pro b/tests/benchmarks/gui/gui.pro
index e943347938..b5853c9e81 100644
--- a/tests/benchmarks/gui/gui.pro
+++ b/tests/benchmarks/gui/gui.pro
@@ -1,21 +1,13 @@
TEMPLATE = subdirs
SUBDIRS = \
animation \
- graphicsview \
image \
- itemviews \
kernel \
math3d \
painting \
- styles \
text
TRUSTED_BENCHMARKS += \
- graphicsview/functional/GraphicsViewBenchmark \
- graphicsview/qgraphicsview \
painting/qtracebench
include(../trusted-benchmarks.pri)
-
-!qtHaveModule(widgets): SUBDIRS -= \
- itemviews
diff --git a/tests/benchmarks/gui/image/image.pro b/tests/benchmarks/gui/image/image.pro
index 89008290fc..8dfb4d0ae9 100644
--- a/tests/benchmarks/gui/image/image.pro
+++ b/tests/benchmarks/gui/image/image.pro
@@ -6,6 +6,3 @@ SUBDIRS = \
qimagescale \
qpixmap \
qpixmapcache
-
-!qtHaveModule(widgets)|!qtHaveModule(network): SUBDIRS -= \
- qimagereader
diff --git a/tests/benchmarks/gui/image/qimagereader/qimagereader.pro b/tests/benchmarks/gui/image/qimagereader/qimagereader.pro
index 33e0c50bba..29f7f6b16e 100644
--- a/tests/benchmarks/gui/image/qimagereader/qimagereader.pro
+++ b/tests/benchmarks/gui/image/qimagereader/qimagereader.pro
@@ -8,4 +8,3 @@ SOURCES += tst_qimagereader.cpp
qtConfig(gif): DEFINES += QTEST_HAVE_GIF
qtConfig(jpeg): DEFINES += QTEST_HAVE_JPEG
-QT += network
diff --git a/tests/benchmarks/gui/image/qimagereader/tst_qimagereader.cpp b/tests/benchmarks/gui/image/qimagereader/tst_qimagereader.cpp
index 76d46f9484..d81d5bb01a 100644
--- a/tests/benchmarks/gui/image/qimagereader/tst_qimagereader.cpp
+++ b/tests/benchmarks/gui/image/qimagereader/tst_qimagereader.cpp
@@ -35,8 +35,6 @@
#include <QImageWriter>
#include <QPixmap>
#include <QSet>
-#include <QTcpSocket>
-#include <QTcpServer>
#include <QTimer>
typedef QMap<QString, QString> QStringMap;
diff --git a/tests/benchmarks/gui/kernel/kernel.pro b/tests/benchmarks/gui/kernel/kernel.pro
index 607e58b6c0..acc6dc402d 100644
--- a/tests/benchmarks/gui/kernel/kernel.pro
+++ b/tests/benchmarks/gui/kernel/kernel.pro
@@ -1,6 +1,4 @@
TEMPLATE = subdirs
-qtHaveModule(widgets): SUBDIRS = \
- qapplication \
- qwidget \
+SUBDIRS = \
qguimetatype \
qguivariant
diff --git a/tests/benchmarks/gui/painting/painting.pro b/tests/benchmarks/gui/painting/painting.pro
index d08dfa707b..400c2994a6 100644
--- a/tests/benchmarks/gui/painting/painting.pro
+++ b/tests/benchmarks/gui/painting/painting.pro
@@ -10,5 +10,4 @@ SUBDIRS = \
!qtHaveModule(widgets): SUBDIRS -= \
qpainter \
- qtracebench \
qtbench
diff --git a/tests/benchmarks/gui/painting/qpainter/tst_qpainter.cpp b/tests/benchmarks/gui/painting/qpainter/tst_qpainter.cpp
index 0248d6f855..485306a8ac 100644
--- a/tests/benchmarks/gui/painting/qpainter/tst_qpainter.cpp
+++ b/tests/benchmarks/gui/painting/qpainter/tst_qpainter.cpp
@@ -29,7 +29,6 @@
#include <qtest.h>
#include <QPainter>
#include <QPixmap>
-#include <QDialog>
#include <QImage>
#include <QPaintEngine>
#include <QTileRules>
@@ -650,6 +649,9 @@ void tst_QPainter::drawPixmapImage_data_helper(bool pixmaps)
"A2RGB30_pm",
"Alpha8",
"Grayscale8",
+ "RGBx64",
+ "RGBA64",
+ "RGBA64_pm",
};
const QImage::Format pixmapFormats[] = {
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/GraphicsViewBenchmark.pro b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/GraphicsViewBenchmark.pro
index ded6a06795..ded6a06795 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/GraphicsViewBenchmark.pro
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/GraphicsViewBenchmark.pro
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/GraphicsViewBenchmark.qrc b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/GraphicsViewBenchmark.qrc
index 18ae04dd69..18ae04dd69 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/GraphicsViewBenchmark.qrc
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/GraphicsViewBenchmark.qrc
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/main.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/main.cpp
index 87ab80d74f..87ab80d74f 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/main.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/main.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_001_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_001_58x58.png
index 525b5559a0..525b5559a0 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_001_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_001_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_002_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_002_58x58.png
index 3d932985a6..3d932985a6 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_002_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_002_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_003_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_003_58x58.png
index 556cfcba6a..556cfcba6a 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_003_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_003_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_004_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_004_58x58.png
index 94acf9e669..94acf9e669 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_004_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_004_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_005_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_005_58x58.png
index ed0c7c42f0..ed0c7c42f0 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_005_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_005_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_006_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_006_58x58.png
index d4b4dc3a8e..d4b4dc3a8e 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_006_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_006_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_007_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_007_58x58.png
index 0e45d18e4d..0e45d18e4d 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_007_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_007_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_008_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_008_58x58.png
index 0c25540ac9..0c25540ac9 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_008_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_008_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_009_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_009_58x58.png
index ce435ea537..ce435ea537 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_009_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_009_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_010_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_010_58x58.png
index 021db25882..021db25882 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_010_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_man_010_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_001_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_001_58x58.png
index 0051da326f..0051da326f 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_001_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_001_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_002_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_002_58x58.png
index e8a946a8ba..e8a946a8ba 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_002_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_002_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_003_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_003_58x58.png
index b2bb851f69..b2bb851f69 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_003_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_003_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_004_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_004_58x58.png
index 871c075d05..871c075d05 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_004_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_004_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_005_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_005_58x58.png
index d4c18b8bb0..d4c18b8bb0 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_005_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_picture_005_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_001_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_001_58x58.png
index 10a5947234..10a5947234 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_001_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_001_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_002_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_002_58x58.png
index 65b4e03c5b..65b4e03c5b 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_002_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_002_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_003_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_003_58x58.png
index 935ec07171..935ec07171 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_003_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_003_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_004_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_004_58x58.png
index fbc1a937fd..fbc1a937fd 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_004_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_004_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_005_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_005_58x58.png
index af96d3e149..af96d3e149 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_005_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_005_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_006_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_006_58x58.png
index fb4192d35f..fb4192d35f 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_006_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_006_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_007_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_007_58x58.png
index f5d6dea0b0..f5d6dea0b0 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_007_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_007_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_008_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_008_58x58.png
index d08b8dc364..d08b8dc364 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_008_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_008_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_009_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_009_58x58.png
index 768b97de6e..768b97de6e 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_009_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_009_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_010_58x58.png b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_010_58x58.png
index d1fe28e61e..d1fe28e61e 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_010_58x58.png
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/avatars/avatar_woman_010_58x58.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_background_360x640px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_background_360x640px.svg
index 1552bafa17..1552bafa17 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_background_360x640px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_background_360x640px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_background_horisontal_640x360px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_background_horisontal_640x360px.svg
index 5589110950..5589110950 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_background_horisontal_640x360px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_background_horisontal_640x360px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_default_icon_52x52px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_default_icon_52x52px.svg
index 665675b1e8..665675b1e8 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_default_icon_52x52px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_default_icon_52x52px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_list_divider_360x76px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_list_divider_360x76px.svg
index db9fc7af33..db9fc7af33 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_list_divider_360x76px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_list_divider_360x76px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_list_highlighter_360x76px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_list_highlighter_360x76px.svg
index dae2bd4842..dae2bd4842 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_list_highlighter_360x76px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_list_highlighter_360x76px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_status_idle_33x33px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_status_idle_33x33px.svg
index fe12e782a6..fe12e782a6 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_status_idle_33x33px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_status_idle_33x33px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_status_offline_33x33px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_status_offline_33x33px.svg
index 0c973f1bc9..0c973f1bc9 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_status_offline_33x33px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_status_offline_33x33px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_status_online_33x33px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_status_online_33x33px.svg
index fcb434afda..fcb434afda 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_status_online_33x33px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_contact_status_online_33x33px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_scroll_16x80px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_scroll_16x80px.svg
index 897be81dc5..897be81dc5 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_scroll_16x80px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_scroll_16x80px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_scrollbar_7x14px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_scrollbar_7x14px.svg
index 3baec2f4b6..3baec2f4b6 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_scrollbar_7x14px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_scrollbar_7x14px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_status_field_left_14x24px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_status_field_left_14x24px.svg
index dd6fb70a8d..dd6fb70a8d 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_status_field_left_14x24px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_status_field_left_14x24px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_status_field_middle_14x24px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_status_field_middle_14x24px.svg
index cabf9285a7..cabf9285a7 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_status_field_middle_14x24px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_status_field_middle_14x24px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_status_field_right_14x24px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_status_field_right_14x24px.svg
index f3a795b88d..f3a795b88d 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_status_field_right_14x24px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_status_field_right_14x24px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_topbar_356x96px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_topbar_356x96px.svg
index a0efd347fb..a0efd347fb 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_topbar_356x96px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_topbar_356x96px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_topbar_horisontal_636x96px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_topbar_horisontal_636x96px.svg
index 0a3efd8111..0a3efd8111 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_topbar_horisontal_636x96px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_topbar_horisontal_636x96px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_user_default_icon_68x68px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_user_default_icon_68x68px.svg
index 1ffeedde1b..1ffeedde1b 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_user_default_icon_68x68px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_user_default_icon_68x68px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_user_status_idle_38x38px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_user_status_idle_38x38px.svg
index 71f49aa719..71f49aa719 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_user_status_idle_38x38px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_user_status_idle_38x38px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_user_status_offline_38x38px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_user_status_offline_38x38px.svg
index 84c2514adc..84c2514adc 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_user_status_offline_38x38px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_user_status_offline_38x38px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_user_status_online_38x38px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_user_status_online_38x38px.svg
index 76daf31809..76daf31809 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_user_status_online_38x38px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/blue_SVG/blue_user_status_online_38x38px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/contacts/areacodes.txt b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/contacts/areacodes.txt
index dc7e7d81b6..dc7e7d81b6 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/contacts/areacodes.txt
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/contacts/areacodes.txt
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/contacts/firstnamesF.txt b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/contacts/firstnamesF.txt
index 4bf14924a7..4bf14924a7 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/contacts/firstnamesF.txt
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/contacts/firstnamesF.txt
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/contacts/firstnamesM.txt b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/contacts/firstnamesM.txt
index 189d8d015f..189d8d015f 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/contacts/firstnamesM.txt
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/contacts/firstnamesM.txt
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/contacts/lastnames.txt b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/contacts/lastnames.txt
index 35b3f9f9c2..35b3f9f9c2 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/contacts/lastnames.txt
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/contacts/lastnames.txt
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_background_360x640px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_background_360x640px.svg
index 8daf275b19..8daf275b19 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_background_360x640px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_background_360x640px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_background_horisontal_640x360px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_background_horisontal_640x360px.svg
index c2b070a3b1..c2b070a3b1 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_background_horisontal_640x360px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_background_horisontal_640x360px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_default_icon_53x53px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_default_icon_53x53px.svg
index 6e34f255b2..6e34f255b2 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_default_icon_53x53px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_default_icon_53x53px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_default_icon_highlight_53x53px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_default_icon_highlight_53x53px.svg
index 29c284de08..29c284de08 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_default_icon_highlight_53x53px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_default_icon_highlight_53x53px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_list_divider_360x76px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_list_divider_360x76px.svg
index db9fc7af33..db9fc7af33 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_list_divider_360x76px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_list_divider_360x76px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_list_highlighter_357x80px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_list_highlighter_357x80px.svg
index 0ee3ea23e6..0ee3ea23e6 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_list_highlighter_357x80px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_list_highlighter_357x80px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_status_idle_27x47.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_status_idle_27x47.svg
index 925d3eb36e..925d3eb36e 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_status_idle_27x47.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_status_idle_27x47.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_status_offline_27x47.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_status_offline_27x47.svg
index 6f74723f09..6f74723f09 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_status_offline_27x47.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_status_offline_27x47.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_status_online_27x47.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_status_online_27x47.svg
index 56951605de..56951605de 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_status_online_27x47.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_contact_status_online_27x47.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_scroll_5x80px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_scroll_5x80px.svg
index 4f6482afa5..4f6482afa5 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_scroll_5x80px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_scroll_5x80px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_scrollbar_5x14px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_scrollbar_5x14px.svg
index 54a40c3cc8..54a40c3cc8 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_scrollbar_5x14px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_scrollbar_5x14px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_status_field_left_14x24px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_status_field_left_14x24px.svg
index a21c91df48..a21c91df48 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_status_field_left_14x24px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_status_field_left_14x24px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_status_field_middle_10x24px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_status_field_middle_10x24px.svg
index b84200d9b1..b84200d9b1 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_status_field_middle_10x24px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_status_field_middle_10x24px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_status_field_right_14x24px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_status_field_right_14x24px.svg
index 231560dd9e..231560dd9e 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_status_field_right_14x24px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_status_field_right_14x24px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_topbar_356x96px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_topbar_356x96px.svg
index 679d9a5305..679d9a5305 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_topbar_356x96px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_topbar_356x96px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_topbar_horisontal_636x96px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_topbar_horisontal_636x96px.svg
index 1ef4fb9224..1ef4fb9224 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_topbar_horisontal_636x96px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_topbar_horisontal_636x96px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_user_default_icon_84x68px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_user_default_icon_84x68px.svg
index 4df0214e56..4df0214e56 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_user_default_icon_84x68px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_user_default_icon_84x68px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_user_status_idle_24x24px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_user_status_idle_24x24px.svg
index 2d6da38ad0..2d6da38ad0 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_user_status_idle_24x24px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_user_status_idle_24x24px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_user_status_offline_24x24px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_user_status_offline_24x24px.svg
index d5920268b1..d5920268b1 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_user_status_offline_24x24px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_user_status_offline_24x24px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_user_status_online_24x24px.svg b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_user_status_online_24x24px.svg
index 46ad07dbbd..46ad07dbbd 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_user_status_online_24x24px.svg
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/resources/lime_SVG/lime_user_status_online_24x24px.svg
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemcontainer.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemcontainer.cpp
index 00481a638d..00481a638d 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemcontainer.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemcontainer.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemcontainer.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemcontainer.h
index 7373f66deb..7373f66deb 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemcontainer.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemcontainer.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemview.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemview.cpp
index 961cf4e03c..961cf4e03c 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemview.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemview.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemview.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemview.h
index 8cd295ba89..8cd295ba89 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemview.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractitemview.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractscrollarea.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractscrollarea.cpp
index 39847b8edb..39847b8edb 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractscrollarea.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractscrollarea.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractscrollarea.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractscrollarea.h
index f681ca9fce..f681ca9fce 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractscrollarea.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractscrollarea.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractviewitem.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractviewitem.cpp
index 6a6df15e23..6a6df15e23 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractviewitem.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractviewitem.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractviewitem.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractviewitem.h
index 4f9fbf4623..4f9fbf4623 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractviewitem.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/abstractviewitem.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/backgrounditem.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/backgrounditem.cpp
index 9f5f16d373..9f5f16d373 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/backgrounditem.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/backgrounditem.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/backgrounditem.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/backgrounditem.h
index 0cb0ee778c..0cb0ee778c 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/backgrounditem.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/backgrounditem.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/button.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/button.cpp
index b8bd55789d..b8bd55789d 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/button.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/button.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/button.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/button.h
index 8e76b88463..8e76b88463 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/button.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/button.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/commandline.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/commandline.cpp
index 226c60cec8..226c60cec8 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/commandline.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/commandline.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/commandline.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/commandline.h
index eaddeac59d..eaddeac59d 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/commandline.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/commandline.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/dummydatagen.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/dummydatagen.cpp
index 7809b38050..7809b38050 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/dummydatagen.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/dummydatagen.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/dummydatagen.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/dummydatagen.h
index bcb9681d5d..bcb9681d5d 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/dummydatagen.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/dummydatagen.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/gvbwidget.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/gvbwidget.cpp
index 3682ae55e1..3682ae55e1 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/gvbwidget.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/gvbwidget.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/gvbwidget.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/gvbwidget.h
index 7e247b63a4..7e247b63a4 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/gvbwidget.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/gvbwidget.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/iconitem.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/iconitem.cpp
index a081e1b064..a081e1b064 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/iconitem.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/iconitem.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/iconitem.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/iconitem.h
index 48d1bafe9f..48d1bafe9f 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/iconitem.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/iconitem.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglist.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglist.cpp
index eabe3671e5..eabe3671e5 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglist.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglist.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglist.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglist.h
index a69b60c9e2..a69b60c9e2 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglist.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglist.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglist.pri b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglist.pri
index 55b551ef8f..55b551ef8f 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglist.pri
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglist.pri
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglistview.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglistview.cpp
index 5aa93256ff..5aa93256ff 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglistview.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglistview.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglistview.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglistview.h
index 467f193604..467f193604 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglistview.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/itemrecyclinglistview.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/label.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/label.cpp
index 5fb2ee1a51..5fb2ee1a51 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/label.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/label.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/label.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/label.h
index 2c1f14b20e..2c1f14b20e 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/label.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/label.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listitem.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listitem.cpp
index 1872bcc9d3..1872bcc9d3 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listitem.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listitem.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listitem.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listitem.h
index 4f033803ac..4f033803ac 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listitem.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listitem.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listitemcache.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listitemcache.cpp
index 0e4520d0a8..0e4520d0a8 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listitemcache.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listitemcache.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listitemcache.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listitemcache.h
index ba35023bbc..ba35023bbc 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listitemcache.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listitemcache.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listitemcontainer.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listitemcontainer.cpp
index 496919214d..496919214d 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listitemcontainer.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listitemcontainer.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listitemcontainer.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listitemcontainer.h
index 62c9450c38..62c9450c38 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listitemcontainer.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listitemcontainer.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listmodel.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listmodel.cpp
index fe87a2abc4..fe87a2abc4 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listmodel.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listmodel.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listmodel.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listmodel.h
index 623c90dedc..623c90dedc 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listmodel.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listmodel.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listwidget.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listwidget.cpp
index 6e09a09d81..6e09a09d81 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listwidget.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listwidget.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listwidget.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listwidget.h
index 0dfd41a1c3..0dfd41a1c3 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/listwidget.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/listwidget.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/mainview.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/mainview.cpp
index c8ccb60dbb..c8ccb60dbb 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/mainview.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/mainview.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/mainview.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/mainview.h
index d7fe404023..d7fe404023 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/mainview.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/mainview.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/menu.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/menu.cpp
index 1cc75d569b..1cc75d569b 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/menu.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/menu.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/menu.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/menu.h
index 074d5b9d95..074d5b9d95 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/menu.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/menu.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/recycledlistitem.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/recycledlistitem.cpp
index c0aed25abb..c0aed25abb 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/recycledlistitem.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/recycledlistitem.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/recycledlistitem.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/recycledlistitem.h
index 021a8b8902..021a8b8902 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/recycledlistitem.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/recycledlistitem.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/resourcemoninterface.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/resourcemoninterface.h
index b03f09048a..b03f09048a 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/resourcemoninterface.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/resourcemoninterface.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/scrollbar.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/scrollbar.cpp
index 81f123e2b7..81f123e2b7 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/scrollbar.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/scrollbar.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/scrollbar.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/scrollbar.h
index 966052676c..966052676c 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/scrollbar.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/scrollbar.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/scroller.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/scroller.cpp
index 203ea7e046..203ea7e046 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/scroller.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/scroller.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/scroller.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/scroller.h
index 8f40dcfd16..8f40dcfd16 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/scroller.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/scroller.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/scroller_p.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/scroller_p.h
index cf11c7fa02..cf11c7fa02 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/scroller_p.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/scroller_p.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/settings.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/settings.cpp
index 9cb44882a6..9cb44882a6 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/settings.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/settings.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/settings.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/settings.h
index dc228162c4..dc228162c4 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/settings.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/settings.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/simplelist.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/simplelist.cpp
index 941cab8c21..941cab8c21 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/simplelist.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/simplelist.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/simplelist.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/simplelist.h
index 3c1ec4f82a..3c1ec4f82a 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/simplelist.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/simplelist.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/simplelistview.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/simplelistview.cpp
index 67f34859c1..67f34859c1 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/simplelistview.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/simplelistview.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/simplelistview.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/simplelistview.h
index ad606cda8f..ad606cda8f 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/simplelistview.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/simplelistview.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/theme.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/theme.cpp
index 06851b0fd8..06851b0fd8 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/theme.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/theme.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/theme.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/theme.h
index 4aafd0c288..4aafd0c288 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/theme.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/theme.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/themeevent.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/themeevent.cpp
index 1209b4a0f7..1209b4a0f7 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/themeevent.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/themeevent.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/themeevent.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/themeevent.h
index 4ae63d8755..4ae63d8755 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/themeevent.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/themeevent.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/topbar.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/topbar.cpp
index 7c3d97b859..7c3d97b859 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/topbar.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/topbar.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/topbar.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/topbar.h
index 53750ca706..53750ca706 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/topbar.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/topbar.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/webview.cpp b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/webview.cpp
index 59ed50157b..59ed50157b 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/webview.cpp
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/webview.cpp
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/webview.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/webview.h
index a18df35957..a18df35957 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/webview.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/webview.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/webview_p.h b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/webview_p.h
index bd4047c134..bd4047c134 100644
--- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/webview_p.h
+++ b/tests/benchmarks/widgets/graphicsview/functional/GraphicsViewBenchmark/widgets/webview_p.h
diff --git a/tests/benchmarks/gui/graphicsview/functional/functional.pro b/tests/benchmarks/widgets/graphicsview/functional/functional.pro
index 3c2979448b..3c2979448b 100644
--- a/tests/benchmarks/gui/graphicsview/functional/functional.pro
+++ b/tests/benchmarks/widgets/graphicsview/functional/functional.pro
diff --git a/tests/benchmarks/widgets/graphicsview/graphicsview.pro b/tests/benchmarks/widgets/graphicsview/graphicsview.pro
new file mode 100644
index 0000000000..8344cd4edf
--- /dev/null
+++ b/tests/benchmarks/widgets/graphicsview/graphicsview.pro
@@ -0,0 +1,10 @@
+TEMPLATE = subdirs
+SUBDIRS = \
+ functional \
+ qgraphicsanchorlayout \
+ qgraphicsitem \
+ qgraphicslayout \
+ qgraphicslinearlayout \
+ qgraphicsscene \
+ qgraphicsview \
+ qgraphicswidget
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsanchorlayout/qgraphicsanchorlayout.pro b/tests/benchmarks/widgets/graphicsview/qgraphicsanchorlayout/qgraphicsanchorlayout.pro
index 01c0dbd653..01c0dbd653 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsanchorlayout/qgraphicsanchorlayout.pro
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsanchorlayout/qgraphicsanchorlayout.pro
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp
index b15aad04cd..b15aad04cd 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsitem/qgraphicsitem.pro b/tests/benchmarks/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro
index 461ec13263..461ec13263 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsitem/qgraphicsitem.pro
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro
diff --git a/tests/benchmarks/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
new file mode 100644
index 0000000000..56b34fff2a
--- /dev/null
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -0,0 +1,234 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QGraphicsItem>
+#include <QGraphicsScene>
+#include <QGraphicsView>
+
+class tst_QGraphicsItem : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QGraphicsItem();
+ virtual ~tst_QGraphicsItem();
+
+public slots:
+ void initTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void setParentItem();
+ void setParentItem_deep();
+ void setParentItem_deep_reversed();
+ void deleteItemWithManyChildren();
+ void setPos_data();
+ void setPos();
+ void setTransform_data();
+ void setTransform();
+ void rotate();
+ void scale();
+ void shear();
+ void translate();
+};
+
+tst_QGraphicsItem::tst_QGraphicsItem()
+{
+}
+
+tst_QGraphicsItem::~tst_QGraphicsItem()
+{
+}
+
+static inline void processEvents()
+{
+ QApplication::processEvents();
+ QApplication::processEvents();
+}
+
+void tst_QGraphicsItem::initTestCase()
+{
+ processEvents();
+ QTest::qWait(1500);
+ processEvents();
+}
+
+void tst_QGraphicsItem::init()
+{
+ processEvents();
+}
+
+void tst_QGraphicsItem::cleanup()
+{
+}
+
+void tst_QGraphicsItem::setParentItem()
+{
+ QBENCHMARK {
+ QGraphicsRectItem rect;
+ QGraphicsRectItem *childRect = new QGraphicsRectItem;
+ childRect->setParentItem(&rect);
+ }
+}
+
+void tst_QGraphicsItem::setParentItem_deep()
+{
+ QBENCHMARK {
+ QGraphicsRectItem rect;
+ QGraphicsRectItem *lastRect = &rect;
+ for (int i = 0; i < 10; ++i) {
+ QGraphicsRectItem *childRect = new QGraphicsRectItem;
+ childRect->setParentItem(lastRect);
+ lastRect = childRect;
+ }
+ QGraphicsItem *first = rect.childItems().first();
+ first->setParentItem(0);
+ }
+}
+
+void tst_QGraphicsItem::setParentItem_deep_reversed()
+{
+ QBENCHMARK {
+ QGraphicsRectItem *lastRect = new QGraphicsRectItem;
+ for (int i = 0; i < 100; ++i) {
+ QGraphicsRectItem *parentRect = new QGraphicsRectItem;
+ lastRect->setParentItem(parentRect);
+ lastRect = parentRect;
+ }
+ delete lastRect;
+ }
+}
+
+void tst_QGraphicsItem::deleteItemWithManyChildren()
+{
+ QBENCHMARK {
+ QGraphicsRectItem *rect = new QGraphicsRectItem;
+ for (int i = 0; i < 1000; ++i)
+ new QGraphicsRectItem(rect);
+ delete rect;
+ }
+}
+
+void tst_QGraphicsItem::setPos_data()
+{
+ QTest::addColumn<QPointF>("pos");
+
+ QTest::newRow("0, 0") << QPointF(0, 0);
+ QTest::newRow("10, 10") << QPointF(10, 10);
+ QTest::newRow("-10, -10") << QPointF(-10, -10);
+}
+
+void tst_QGraphicsItem::setPos()
+{
+ QFETCH(QPointF, pos);
+
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100));
+ processEvents();
+
+ QBENCHMARK {
+ rect->setPos(pos);
+ }
+}
+
+void tst_QGraphicsItem::setTransform_data()
+{
+ QTest::addColumn<QTransform>("transform");
+
+ QTest::newRow("rotate 45z") << QTransform().rotate(45);
+ QTest::newRow("scale 2x2") << QTransform().scale(2, 2);
+ QTest::newRow("translate 100, 100") << QTransform().translate(100, 100);
+ QTest::newRow("rotate 45x 45y 45z") << QTransform().rotate(45, Qt::XAxis)
+ .rotate(45, Qt::YAxis).rotate(45, Qt::ZAxis);
+}
+
+void tst_QGraphicsItem::setTransform()
+{
+ QFETCH(QTransform, transform);
+
+ QGraphicsScene scene;
+ QGraphicsRectItem *item = scene.addRect(QRectF(0, 0, 100, 100));
+ processEvents();
+
+ QBENCHMARK {
+ item->setTransform(transform);
+ }
+}
+
+void tst_QGraphicsItem::rotate()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *item = scene.addRect(QRectF(0, 0, 100, 100));
+ processEvents();
+
+ const QTransform rotate(QTransform().rotate(45));
+ QBENCHMARK {
+ item->setTransform(rotate, true);
+ }
+}
+
+void tst_QGraphicsItem::scale()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *item = scene.addRect(QRectF(0, 0, 100, 100));
+ processEvents();
+
+ const QTransform scale(QTransform::fromScale(2, 2));
+ QBENCHMARK {
+ item->setTransform(scale, true);
+ }
+}
+
+void tst_QGraphicsItem::shear()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *item = scene.addRect(QRectF(0, 0, 100, 100));
+ processEvents();
+
+ const QTransform shear = QTransform().shear(1.5, 1.5);
+ QBENCHMARK {
+ item->setTransform(shear, true);
+ }
+}
+
+void tst_QGraphicsItem::translate()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *item = scene.addRect(QRectF(0, 0, 100, 100));
+ processEvents();
+
+ const QTransform translate = QTransform::fromTranslate(100, 100);
+ QBENCHMARK {
+ item->setTransform(translate, true);
+ }
+}
+
+QTEST_MAIN(tst_QGraphicsItem)
+#include "tst_qgraphicsitem.moc"
diff --git a/tests/benchmarks/widgets/graphicsview/qgraphicslayout/qgraphicslayout.pro b/tests/benchmarks/widgets/graphicsview/qgraphicslayout/qgraphicslayout.pro
new file mode 100644
index 0000000000..a20d9e0921
--- /dev/null
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicslayout/qgraphicslayout.pro
@@ -0,0 +1,5 @@
+TEMPLATE = app
+TARGET = tst_bench_qgraphicslayout
+QT += testlib widgets
+SOURCES += tst_qgraphicslayout.cpp
+
diff --git a/tests/benchmarks/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp
new file mode 100644
index 0000000000..5c97d7f738
--- /dev/null
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest>
+#include <QGraphicsLayout>
+#include <QGraphicsLinearLayout>
+#include <QGraphicsWidget>
+#include <QGraphicsView>
+
+class tst_QGraphicsLayout : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QGraphicsLayout() {}
+ ~tst_QGraphicsLayout() {}
+
+private slots:
+ void invalidate();
+};
+
+
+class RectWidget : public QGraphicsWidget
+{
+public:
+ RectWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0) : QGraphicsWidget(parent, wFlags), setGeometryCalls(0) {}
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+ painter->drawRoundRect(rect());
+ painter->drawLine(rect().topLeft(), rect().bottomRight());
+ painter->drawLine(rect().bottomLeft(), rect().topRight());
+ }
+
+ void setGeometry(const QRectF &rect)
+ {
+ //qDebug() << "setGeometry():" << this->data(0).toString();
+ setGeometryCalls->insert(this, rect);
+ QGraphicsWidget::setGeometry(rect);
+ }
+
+ void callUpdateGeometry() {
+ QGraphicsWidget::updateGeometry();
+ }
+
+ QMap<RectWidget*, QRectF> *setGeometryCalls;
+};
+
+/**
+ * Test to see how much time is needed to resize all widgets in a
+ * layout-widget-layout-widget-.... hierarchy from the point where a
+ * leaf widget changes its size hint. (updateGeometry() is called).
+ *
+ * If you run the test for 4.7 you'll get some really high numbers, but
+ * that's because they also include painting (and possible processing of
+ * some other events).
+ */
+void tst_QGraphicsLayout::invalidate()
+{
+ QGraphicsLayout::setInstantInvalidatePropagation(true);
+ QGraphicsScene *scene = new QGraphicsScene;
+ QGraphicsView *view = new QGraphicsView(scene);
+ QMap<RectWidget*, QRectF> *setGeometryCalls = new QMap<RectWidget*, QRectF>;
+
+ RectWidget *window = new RectWidget(0, Qt::Window);
+ window->setGeometryCalls = setGeometryCalls;
+ window->setData(0, QString(QChar('a')));
+
+ scene->addItem(window);
+ RectWidget *leaf = 0;
+ const int depth = 100;
+ RectWidget *parent = window;
+ for (int i = 1; i < depth; ++i) {
+ QGraphicsLinearLayout *l = new QGraphicsLinearLayout(parent);
+ l->setContentsMargins(0,0,0,0);
+ RectWidget *child = new RectWidget;
+ child->setData(0, QString(QChar('a' + i)));
+ child->setGeometryCalls = setGeometryCalls;
+ l->addItem(child);
+ parent = child;
+ }
+ leaf = parent;
+ leaf->setMinimumSize(QSizeF(1,1));
+
+ view->show();
+
+ QVERIFY(QTest::qWaitForWindowExposed(view));
+
+ // ...then measure...
+
+ int pass = 1;
+
+ // should be as small as possible, to reduce overhead of painting
+ QSizeF size(1, 1);
+ setGeometryCalls->clear();
+ QBENCHMARK {
+ leaf->setMinimumSize(size);
+ leaf->setMaximumSize(size);
+ while (setGeometryCalls->count() < depth) {
+ QApplication::sendPostedEvents();
+ }
+ // force a resize on each widget, this will ensure
+ // that each iteration will resize all 50 widgets
+ int w = int(size.width());
+ w^=2;
+ size.setWidth(w);
+ }
+ window->setGeometryCalls = nullptr;
+ delete view;
+ delete scene;
+ QGraphicsLayout::setInstantInvalidatePropagation(false);
+ delete setGeometryCalls;
+}
+
+QTEST_MAIN(tst_QGraphicsLayout)
+
+#include "tst_qgraphicslayout.moc"
diff --git a/tests/benchmarks/widgets/graphicsview/qgraphicslinearlayout/qgraphicslinearlayout.pro b/tests/benchmarks/widgets/graphicsview/qgraphicslinearlayout/qgraphicslinearlayout.pro
new file mode 100644
index 0000000000..e9a9e9353e
--- /dev/null
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicslinearlayout/qgraphicslinearlayout.pro
@@ -0,0 +1,5 @@
+TEMPLATE = app
+TARGET = tst_bench_qgraphicslinearlayout
+QT += testlib widgets
+SOURCES += tst_qgraphicslinearlayout.cpp
+
diff --git a/tests/benchmarks/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp
new file mode 100644
index 0000000000..254d147e52
--- /dev/null
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest>
+#include <QGraphicsLinearLayout>
+#include <QGraphicsWidget>
+#include <QGraphicsView>
+
+class tst_QGraphicsLinearLayout : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QGraphicsLinearLayout() {}
+ ~tst_QGraphicsLinearLayout() {}
+
+private slots:
+ void heightForWidth_data();
+ void heightForWidth();
+};
+
+
+struct MySquareWidget : public QGraphicsWidget
+{
+ MySquareWidget() {}
+ virtual QSizeF sizeHint ( Qt::SizeHint which, const QSizeF & constraint = QSizeF() ) const
+ {
+ if (which != Qt::PreferredSize)
+ return QGraphicsWidget::sizeHint(which, constraint);
+ if (constraint.width() < 0)
+ return QGraphicsWidget::sizeHint(which, constraint);
+ return QSizeF(constraint.width(), constraint.width());
+ }
+};
+
+void tst_QGraphicsLinearLayout::heightForWidth_data()
+{
+ QTest::addColumn<bool>("hfw");
+ QTest::addColumn<bool>("nested");
+
+ QTest::newRow("hfw") << true << false;
+ QTest::newRow("hfw, nested") << true << true;
+ QTest::newRow("not hfw") << false << false;
+ QTest::newRow("not hfw, nested") << false << true;
+}
+
+void tst_QGraphicsLinearLayout::heightForWidth()
+{
+ QFETCH(bool, hfw);
+ QFETCH(bool, nested);
+
+ QGraphicsScene scene;
+ QGraphicsWidget *form = new QGraphicsWidget;
+ scene.addItem(form);
+
+ QGraphicsLinearLayout *outerlayout = 0;
+ if (nested) {
+ outerlayout = new QGraphicsLinearLayout(form);
+ for (int i = 0; i < 8; i++) {
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical);
+ outerlayout->addItem(layout);
+ outerlayout = layout;
+ }
+ }
+
+ QGraphicsLinearLayout *qlayout = 0;
+ qlayout = new QGraphicsLinearLayout(Qt::Vertical);
+ if (nested)
+ outerlayout->addItem(qlayout);
+ else
+ form->setLayout(qlayout);
+
+ MySquareWidget *widget = new MySquareWidget;
+ for (int i = 0; i < 1; i++) {
+ widget = new MySquareWidget;
+ QSizePolicy sizepolicy = widget->sizePolicy();
+ sizepolicy.setHeightForWidth(hfw);
+ widget->setSizePolicy(sizepolicy);
+ qlayout->addItem(widget);
+ }
+ // make sure only one iteration is done.
+ // run with tst_QGraphicsLinearLayout.exe "heightForWidth" -tickcounter -iterations 6
+ // this will iterate 6 times the whole test, (not only the benchmark)
+ // which should reduce warmup time and give a realistic picture of the performance of
+ // effectiveSizeHint()
+ QSizeF constraint(hfw ? 100 : -1, -1);
+ QBENCHMARK {
+ (void)form->effectiveSizeHint(Qt::PreferredSize, constraint);
+ }
+
+}
+
+
+QTEST_MAIN(tst_QGraphicsLinearLayout)
+
+#include "tst_qgraphicslinearlayout.moc"
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsscene/qgraphicsscene.pro b/tests/benchmarks/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro
index 769f84423e..769f84423e 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsscene/qgraphicsscene.pro
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp
index 6145fabbf8..6145fabbf8 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/chip.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/chip.cpp
index 57ab62b1c3..57ab62b1c3 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/chip.cpp
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/chip.cpp
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/chip.debug b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/chip.debug
index 8fe1e5b0f1..8fe1e5b0f1 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/chip.debug
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/chip.debug
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/chip.h b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/chip.h
index c14f8c41de..c14f8c41de 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/chip.h
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/chip.h
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/chip.pro b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/chip.pro
index 8ef79cef23..8ef79cef23 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/chip.pro
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/chip.pro
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/fileprint.png b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/fileprint.png
index ba7c02dc18..ba7c02dc18 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/fileprint.png
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/fileprint.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/images.qrc b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/images.qrc
index c7cdf0c4c0..c7cdf0c4c0 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/images.qrc
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/images.qrc
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/main.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/main.cpp
index 53fcfa7192..53fcfa7192 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/main.cpp
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/main.cpp
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/mainwindow.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/mainwindow.cpp
index b162461403..b162461403 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/mainwindow.cpp
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/mainwindow.cpp
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/mainwindow.h b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/mainwindow.h
index b0e12b448a..b0e12b448a 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/mainwindow.h
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/mainwindow.h
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/qt4logo.png b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/qt4logo.png
index 157e86ed64..157e86ed64 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/qt4logo.png
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/qt4logo.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/rotateleft.png b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/rotateleft.png
index 8cfa931986..8cfa931986 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/rotateleft.png
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/rotateleft.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/rotateright.png b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/rotateright.png
index ec5e8664a1..ec5e8664a1 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/rotateright.png
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/rotateright.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/view.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/view.cpp
index de4e9e5ad7..de4e9e5ad7 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/view.cpp
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/view.cpp
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/view.h b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/view.h
index e20543858b..e20543858b 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/view.h
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/view.h
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/zoomin.png b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/zoomin.png
index 8b0daeea48..8b0daeea48 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/zoomin.png
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/zoomin.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/zoomout.png b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/zoomout.png
index 1575dd24f6..1575dd24f6 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/chipTest/zoomout.png
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/chipTest/zoomout.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/moveItems/main.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/moveItems/main.cpp
index e0cc0f8eb4..e0cc0f8eb4 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/moveItems/main.cpp
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/moveItems/main.cpp
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/moveItems/moveItems.pro b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/moveItems/moveItems.pro
index 28dcadcbfa..28dcadcbfa 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/moveItems/moveItems.pro
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/moveItems/moveItems.pro
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/scrolltest/main.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/scrolltest/main.cpp
index 1fbb229cd8..1fbb229cd8 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/scrolltest/main.cpp
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/scrolltest/main.cpp
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/scrolltest/scrolltest.pro b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/scrolltest/scrolltest.pro
index 28dcadcbfa..28dcadcbfa 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/benchapps/scrolltest/scrolltest.pro
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/benchapps/scrolltest/scrolltest.pro
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/chip.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/chip.cpp
index cf82282bfe..cf82282bfe 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/chip.cpp
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/chip.cpp
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/chip.h b/tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/chip.h
index d991f771e2..d991f771e2 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/chip.h
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/chip.h
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/chiptester.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/chiptester.cpp
index dfa08b6869..dfa08b6869 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/chiptester.cpp
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/chiptester.cpp
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/chiptester.h b/tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/chiptester.h
index d85686c94e..d85686c94e 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/chiptester.h
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/chiptester.h
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/chiptester.pri b/tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/chiptester.pri
index 105117de30..105117de30 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/chiptester.pri
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/chiptester.pri
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/images.qrc b/tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/images.qrc
index 73e8620b25..73e8620b25 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/images.qrc
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/images.qrc
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/qt4logo.png b/tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/qt4logo.png
index 157e86ed64..157e86ed64 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/chiptester/qt4logo.png
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/chiptester/qt4logo.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/images/designer.png b/tests/benchmarks/widgets/graphicsview/qgraphicsview/images/designer.png
index 0988fcee3f..0988fcee3f 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/images/designer.png
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/images/designer.png
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/images/wine-big.jpeg b/tests/benchmarks/widgets/graphicsview/qgraphicsview/images/wine-big.jpeg
index 9900a50f94..9900a50f94 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/images/wine-big.jpeg
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/images/wine-big.jpeg
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/images/wine.jpeg b/tests/benchmarks/widgets/graphicsview/qgraphicsview/images/wine.jpeg
index 8fe1d3a67d..8fe1d3a67d 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/images/wine.jpeg
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/images/wine.jpeg
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/qgraphicsview.pro b/tests/benchmarks/widgets/graphicsview/qgraphicsview/qgraphicsview.pro
index 3d48959f3c..3d48959f3c 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/qgraphicsview.pro
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/qgraphicsview.pro
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/qgraphicsview.qrc b/tests/benchmarks/widgets/graphicsview/qgraphicsview/qgraphicsview.qrc
index 3681648f56..3681648f56 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/qgraphicsview.qrc
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/qgraphicsview.qrc
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/random.data b/tests/benchmarks/widgets/graphicsview/qgraphicsview/random.data
index 190a36c707..190a36c707 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/random.data
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/random.data
Binary files differ
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
index 9bb5231528..9bb5231528 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicswidget/qgraphicswidget.pro b/tests/benchmarks/widgets/graphicsview/qgraphicswidget/qgraphicswidget.pro
index 00becec216..00becec216 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicswidget/qgraphicswidget.pro
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicswidget/qgraphicswidget.pro
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/benchmarks/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
index d9bc7f21b6..d9bc7f21b6 100644
--- a/tests/benchmarks/gui/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
+++ b/tests/benchmarks/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
diff --git a/tests/benchmarks/gui/itemviews/itemviews.pro b/tests/benchmarks/widgets/itemviews/itemviews.pro
index a23cdf7b97..a23cdf7b97 100644
--- a/tests/benchmarks/gui/itemviews/itemviews.pro
+++ b/tests/benchmarks/widgets/itemviews/itemviews.pro
diff --git a/tests/benchmarks/gui/itemviews/qheaderview/qheaderview.pro b/tests/benchmarks/widgets/itemviews/qheaderview/qheaderview.pro
index 7e8415e495..7e8415e495 100644
--- a/tests/benchmarks/gui/itemviews/qheaderview/qheaderview.pro
+++ b/tests/benchmarks/widgets/itemviews/qheaderview/qheaderview.pro
diff --git a/tests/benchmarks/gui/itemviews/qheaderview/qheaderviewbench.cpp b/tests/benchmarks/widgets/itemviews/qheaderview/qheaderviewbench.cpp
index 49ce060580..49ce060580 100644
--- a/tests/benchmarks/gui/itemviews/qheaderview/qheaderviewbench.cpp
+++ b/tests/benchmarks/widgets/itemviews/qheaderview/qheaderviewbench.cpp
diff --git a/tests/benchmarks/gui/itemviews/qtableview/qtableview.pro b/tests/benchmarks/widgets/itemviews/qtableview/qtableview.pro
index bd2306d646..bd2306d646 100644
--- a/tests/benchmarks/gui/itemviews/qtableview/qtableview.pro
+++ b/tests/benchmarks/widgets/itemviews/qtableview/qtableview.pro
diff --git a/tests/benchmarks/gui/itemviews/qtableview/tst_qtableview.cpp b/tests/benchmarks/widgets/itemviews/qtableview/tst_qtableview.cpp
index 9ce214e5ff..9ce214e5ff 100644
--- a/tests/benchmarks/gui/itemviews/qtableview/tst_qtableview.cpp
+++ b/tests/benchmarks/widgets/itemviews/qtableview/tst_qtableview.cpp
diff --git a/tests/benchmarks/widgets/kernel/kernel.pro b/tests/benchmarks/widgets/kernel/kernel.pro
new file mode 100644
index 0000000000..a50aad2014
--- /dev/null
+++ b/tests/benchmarks/widgets/kernel/kernel.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+SUBDIRS = \
+ qapplication \
+ qwidget
diff --git a/tests/benchmarks/gui/kernel/qapplication/main.cpp b/tests/benchmarks/widgets/kernel/qapplication/main.cpp
index 49de765ef0..49de765ef0 100644
--- a/tests/benchmarks/gui/kernel/qapplication/main.cpp
+++ b/tests/benchmarks/widgets/kernel/qapplication/main.cpp
diff --git a/tests/benchmarks/gui/kernel/qapplication/qapplication.pro b/tests/benchmarks/widgets/kernel/qapplication/qapplication.pro
index 86a016d42e..86a016d42e 100644
--- a/tests/benchmarks/gui/kernel/qapplication/qapplication.pro
+++ b/tests/benchmarks/widgets/kernel/qapplication/qapplication.pro
diff --git a/tests/benchmarks/gui/kernel/qwidget/qwidget.pro b/tests/benchmarks/widgets/kernel/qwidget/qwidget.pro
index 758c9c5b98..758c9c5b98 100644
--- a/tests/benchmarks/gui/kernel/qwidget/qwidget.pro
+++ b/tests/benchmarks/widgets/kernel/qwidget/qwidget.pro
diff --git a/tests/benchmarks/gui/kernel/qwidget/tst_qwidget.cpp b/tests/benchmarks/widgets/kernel/qwidget/tst_qwidget.cpp
index b9af7a55cd..b9af7a55cd 100644
--- a/tests/benchmarks/gui/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/benchmarks/widgets/kernel/qwidget/tst_qwidget.cpp
diff --git a/tests/benchmarks/gui/styles/qstylesheetstyle/main.cpp b/tests/benchmarks/widgets/styles/qstylesheetstyle/main.cpp
index 9dbf618dd9..9dbf618dd9 100644
--- a/tests/benchmarks/gui/styles/qstylesheetstyle/main.cpp
+++ b/tests/benchmarks/widgets/styles/qstylesheetstyle/main.cpp
diff --git a/tests/benchmarks/gui/styles/qstylesheetstyle/qstylesheetstyle.pro b/tests/benchmarks/widgets/styles/qstylesheetstyle/qstylesheetstyle.pro
index 5aef3520c0..5aef3520c0 100644
--- a/tests/benchmarks/gui/styles/qstylesheetstyle/qstylesheetstyle.pro
+++ b/tests/benchmarks/widgets/styles/qstylesheetstyle/qstylesheetstyle.pro
diff --git a/tests/benchmarks/gui/styles/styles.pro b/tests/benchmarks/widgets/styles/styles.pro
index 2c1d10b48c..2c1d10b48c 100644
--- a/tests/benchmarks/gui/styles/styles.pro
+++ b/tests/benchmarks/widgets/styles/styles.pro
diff --git a/tests/benchmarks/widgets/widgets.pro b/tests/benchmarks/widgets/widgets.pro
index 8fe49ff2c6..d241e31d0b 100644
--- a/tests/benchmarks/widgets/widgets.pro
+++ b/tests/benchmarks/widgets/widgets.pro
@@ -1,3 +1,13 @@
TEMPLATE = subdirs
SUBDIRS = \
+ graphicsview \
+ itemviews \
+ kernel \
+ styles \
widgets \
+
+TRUSTED_BENCHMARKS += \
+ graphicsview/functional/GraphicsViewBenchmark \
+ graphicsview/qgraphicsview
+
+include(../trusted-benchmarks.pri)
diff --git a/tests/manual/cocoa/menurama/main.cpp b/tests/manual/cocoa/menurama/main.cpp
index 00594b6d1f..e39c01ea4d 100644
--- a/tests/manual/cocoa/menurama/main.cpp
+++ b/tests/manual/cocoa/menurama/main.cpp
@@ -29,9 +29,46 @@
#include "mainwindow.h"
#include "menuramaapplication.h"
+#include <QtWidgets/QAction>
+#include <QtWidgets/QMenu>
+
int main(int argc, char *argv[])
{
MenuramaApplication a(argc, argv);
+ a.setQuitOnLastWindowClosed(false);
+
+ auto *dockMenu = new QMenu();
+ dockMenu->setAsDockMenu();
+ dockMenu->addAction(QLatin1String("New Window"), [=] {
+ auto *w = new MainWindow;
+ w->setAttribute(Qt::WA_DeleteOnClose, true);
+ w->show();
+ });
+ auto *disabledAction = dockMenu->addAction(QLatin1String("Disabled Item"), [=] {
+ qDebug() << "Should not happen!";
+ Q_UNREACHABLE();
+ });
+ disabledAction->setEnabled(false);
+ dockMenu->addAction(QLatin1String("Last Item Before Separator"), [=] {
+ qDebug() << "Last Item triggered";
+ });
+ auto *hiddenAction = dockMenu->addAction(QLatin1String("Invisible Item (FIXME rdar:39615815)"), [=] {
+ qDebug() << "Should not happen!";
+ Q_UNREACHABLE();
+ });
+ hiddenAction->setVisible(false);
+ dockMenu->addSeparator();
+ auto *toolsMenu = dockMenu->addMenu(QLatin1String("Menurama Tools"));
+ toolsMenu->addAction(QLatin1String("Hammer"), [=] {
+ qDebug() << "Bang! Bang!";
+ });
+ toolsMenu->addAction(QLatin1String("Wrench"), [=] {
+ qDebug() << "Clang! Clang!";
+ });
+ toolsMenu->addAction(QLatin1String("Screwdriver"), [=] {
+ qDebug() << "Squeak! Squeak!";
+ });
+
MainWindow w;
w.show();
diff --git a/tests/manual/cocoa/menurama/mainwindow.ui b/tests/manual/cocoa/menurama/mainwindow.ui
index 4fb3e3420e..2c6ac52f58 100644
--- a/tests/manual/cocoa/menurama/mainwindow.ui
+++ b/tests/manual/cocoa/menurama/mainwindow.ui
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>486</width>
- <height>288</height>
+ <height>376</height>
</rect>
</property>
<property name="windowTitle">
@@ -58,7 +58,7 @@ Click on &quot;Dynamic Stuff&quot; then move left and right to other menus. Disa
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
- <item>
+ <item alignment="Qt::AlignTop">
<widget class="QPushButton" name="addManyButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
@@ -71,7 +71,7 @@ Click on &quot;Dynamic Stuff&quot; then move left and right to other menus. Disa
</property>
</widget>
</item>
- <item>
+ <item alignment="Qt::AlignTop">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Adding hundreds of items should not block the UI for noticeable periods of time. Odd numbered items should be disabled, those with 2nd LSB on should be hidden.</string>
@@ -83,6 +83,16 @@ Click on &quot;Dynamic Stuff&quot; then move left and right to other menus. Disa
</item>
</layout>
</item>
+ <item alignment="Qt::AlignTop">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Check out the dock menu. You can close this window to verify that its actions will trigger in the absence of any window. And you can add more windows from there too.</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
diff --git a/tests/manual/cocoa/qmaccocoaviewcontainer/TestMouseMovedNSView.h b/tests/manual/cocoa/qmaccocoaviewcontainer/TestMouseMovedNSView.h
index be716aa582..4a145a729f 100644
--- a/tests/manual/cocoa/qmaccocoaviewcontainer/TestMouseMovedNSView.h
+++ b/tests/manual/cocoa/qmaccocoaviewcontainer/TestMouseMovedNSView.h
@@ -28,10 +28,5 @@
#import <AppKit/AppKit.h>
-@interface TestMouseMovedNSView : NSView {
- NSPoint mouseMovedPoint_;
- BOOL wasAcceptingMouseEvents_;
- NSTrackingRectTag trackingRect_;
- NSTrackingArea* trackingArea_;
-}
+@interface TestMouseMovedNSView : NSView
@end
diff --git a/tests/manual/cocoa/qmaccocoaviewcontainer/TestMouseMovedNSView.m b/tests/manual/cocoa/qmaccocoaviewcontainer/TestMouseMovedNSView.m
index 65b42dbb2f..20a3fcc513 100644
--- a/tests/manual/cocoa/qmaccocoaviewcontainer/TestMouseMovedNSView.m
+++ b/tests/manual/cocoa/qmaccocoaviewcontainer/TestMouseMovedNSView.m
@@ -28,9 +28,14 @@
#import "TestMouseMovedNSView.h"
-@implementation TestMouseMovedNSView
+@implementation TestMouseMovedNSView {
+ NSPoint mouseMovedPoint_;
+ BOOL wasAcceptingMouseEvents_;
+ NSTrackingRectTag trackingRect_;
+ NSTrackingArea* trackingArea_;
+}
-- (id)initWithFrame:(NSRect)frame
+- (instancetype)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self)
@@ -40,13 +45,13 @@
- (void)viewDidMoveToWindow
{
- trackingArea_ = [[NSTrackingArea alloc] initWithRect:[self bounds] options: (NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways) owner:self userInfo:nil];
+ trackingArea_ = [[NSTrackingArea alloc] initWithRect:self.bounds options:(NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways) owner:self userInfo:nil];
[self addTrackingArea:trackingArea_];
}
- (void)viewWillMoveToWindow:(NSWindow *)newWindow
{
- if ([self window] && trackingArea_)
+ if (self.window && trackingArea_)
[self removeTrackingArea:trackingArea_];
}
@@ -54,7 +59,7 @@
{
[super updateTrackingAreas];
[self removeTrackingArea: trackingArea_];
- trackingArea_ = [[NSTrackingArea alloc] initWithRect:[self bounds] options: (NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways) owner:self userInfo:nil];
+ trackingArea_ = [[NSTrackingArea alloc] initWithRect:self.bounds options:(NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways) owner:self userInfo:nil];
[self addTrackingArea:trackingArea_];
}
@@ -64,20 +69,20 @@
- (void)mouseEntered:(NSEvent *)theEvent
{
wasAcceptingMouseEvents_ = [[self window] acceptsMouseMovedEvents];
- [[self window] setAcceptsMouseMovedEvents:YES];
- [[self window] makeFirstResponder:self];
+ [self.window setAcceptsMouseMovedEvents:YES];
+ [self.window makeFirstResponder:self];
}
- (void)mouseExited:(NSEvent *)theEvent
{
- [[self window] setAcceptsMouseMovedEvents:wasAcceptingMouseEvents_];
+ [self.window setAcceptsMouseMovedEvents:wasAcceptingMouseEvents_];
[self setNeedsDisplay:YES];
[self displayIfNeeded];
}
-(void)mouseMoved:(NSEvent *)pTheEvent
{
- mouseMovedPoint_ = [self convertPoint:[pTheEvent locationInWindow] fromView:nil];
+ mouseMovedPoint_ = [self convertPoint:pTheEvent.locationInWindow fromView:nil];
[self setNeedsDisplay:YES];
[self displayIfNeeded];
}
@@ -88,7 +93,7 @@
NSRectFill(dirtyRect);
NSGraphicsContext *nsGraphicsContext = [NSGraphicsContext currentContext];
- CGContextRef cgContextRef = (CGContextRef) [nsGraphicsContext graphicsPort];
+ CGContextRef cgContextRef = nsGraphicsContext.CGContext;
CGContextSetRGBStrokeColor(cgContextRef, 0, 0, 0, .5);
CGContextSetLineWidth(cgContextRef, 1.0);
diff --git a/tests/manual/cocoa/qmaccocoaviewcontainer/main.mm b/tests/manual/cocoa/qmaccocoaviewcontainer/main.mm
index 9cf06391ca..8b05b64a1e 100644
--- a/tests/manual/cocoa/qmaccocoaviewcontainer/main.mm
+++ b/tests/manual/cocoa/qmaccocoaviewcontainer/main.mm
@@ -83,7 +83,7 @@ int main(int argc, char **argv)
w.resize(300, 300);
w.setWindowTitle("QMacCocoaViewContainer");
NSRect r = NSMakeRect(0, 0, 100, 100);
- NSView *view = [[TestMouseMovedNSView alloc] initWithFrame: r];
+ NSView *view = [[TestMouseMovedNSView alloc] initWithFrame:r];
QMacCocoaViewContainer *nativeChild = new QMacCocoaViewContainer(view, &w);
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(nativeChild);
diff --git a/tests/manual/cocoa/qt_on_cocoa/main.mm b/tests/manual/cocoa/qt_on_cocoa/main.mm
index 805ef0d7c2..e6218e48ac 100644
--- a/tests/manual/cocoa/qt_on_cocoa/main.mm
+++ b/tests/manual/cocoa/qt_on_cocoa/main.mm
@@ -50,31 +50,30 @@
}
@end
-@interface AppDelegate : NSObject <NSApplicationDelegate> {
+@interface AppDelegate : NSObject <NSApplicationDelegate>
+@end
+
+@implementation AppDelegate {
QGuiApplication *m_app;
QWindow *m_window;
}
-- (AppDelegate *) initWithArgc:(int)argc argv:(const char **)argv;
-- (void) applicationWillFinishLaunching: (NSNotification *)notification;
-- (void)applicationWillTerminate:(NSNotification *)notification;
-@end
-
-@implementation AppDelegate
-- (AppDelegate *) initWithArgc:(int)argc argv:(const char **)argv
+- (instancetype)initWithArgc:(int)argc argv:(const char **)argv
{
- m_app = new QGuiApplication(argc, const_cast<char **>(argv));
+ if ((self = [self init])) {
+ m_app = new QGuiApplication(argc, const_cast<char **>(argv));
+ }
return self;
}
-- (void) applicationWillFinishLaunching: (NSNotification *)notification
+- (void)applicationWillFinishLaunching:(NSNotification *)notification
{
Q_UNUSED(notification);
// Create the NSWindow
NSRect frame = NSMakeRect(500, 500, 500, 500);
- NSWindow* window = [[NSWindow alloc] initWithContentRect:frame
- styleMask:NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask
+ NSWindow *window = [[NSWindow alloc] initWithContentRect:frame
+ styleMask:NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask
backing:NSBackingStoreBuffered
defer:NO];
@@ -100,7 +99,7 @@
childWindow->setGeometry(50, 50, 100, 100);
NSTextField *textField = [[NSTextField alloc] initWithFrame:NSMakeRect(10, 10, 80, 25)];
- [(NSView*)childWindow->winId() addSubview:textField];
+ [reinterpret_cast<NSView *>(childWindow->winId()) addSubview:textField];
[contentView addSubview:reinterpret_cast<NSView *>(m_window->winId())];
@@ -125,10 +124,7 @@
int main(int argc, const char *argv[])
{
// Create NSApplicaiton with delgate
- NSApplication *app =[NSApplication sharedApplication];
+ NSApplication *app = [NSApplication sharedApplication];
app.delegate = [[AppDelegate alloc] initWithArgc:argc argv:argv];
- return NSApplicationMain (argc, argv);
+ return NSApplicationMain(argc, argv);
}
-
-
-
diff --git a/tests/manual/highdpi/dragwidget.cpp b/tests/manual/highdpi/dragwidget.cpp
index fc1ea72963..46a8ea8090 100644
--- a/tests/manual/highdpi/dragwidget.cpp
+++ b/tests/manual/highdpi/dragwidget.cpp
@@ -42,7 +42,7 @@ public:
};
DragWidget::DragWidget(QString text, QWidget *parent)
- : QWidget(parent), otherWindow(0)
+ : QWidget(parent), otherWindow(nullptr)
{
int x = 5;
int y = 5;
diff --git a/tests/manual/highdpi/main.cpp b/tests/manual/highdpi/main.cpp
index bd6af75b16..7225587ac0 100644
--- a/tests/manual/highdpi/main.cpp
+++ b/tests/manual/highdpi/main.cpp
@@ -45,6 +45,8 @@
#include <QPainter>
#include <QWindow>
#include <QScreen>
+#include <QGraphicsView>
+#include <QGraphicsTextItem>
#include <QFile>
#include <QMouseEvent>
#include <QTemporaryDir>
@@ -59,7 +61,7 @@
class DemoContainerBase
{
public:
- DemoContainerBase() : m_widget(0) {}
+ DemoContainerBase() : m_widget(nullptr) {}
virtual ~DemoContainerBase() {}
QString name() { return option().names().first(); }
virtual QCommandLineOption &option() = 0;
@@ -155,7 +157,7 @@ static qreal getScreenFactorWithoutPixelDensity(const QScreen *screen)
static inline qreal getGlobalScaleFactor()
{
- QScreen *noScreen = 0;
+ QScreen *noScreen = nullptr;
return QHighDpiScaling::factor(noScreen);
}
@@ -334,6 +336,60 @@ void PixmapPainter::paintEvent(QPaintEvent *)
x+=dx * 2; p.drawImage(QRect(x, y, pixmapPointSize * 2, pixmapPointSize * 2), imageLarge);
}
+class TiledPixmapPainter : public QWidget
+{
+public:
+ QPixmap pixmap1X;
+ QPixmap pixmap2X;
+ QPixmap pixmapLarge;
+
+ TiledPixmapPainter();
+ void paintEvent(QPaintEvent *event);
+};
+
+TiledPixmapPainter::TiledPixmapPainter()
+{
+ pixmap1X = QPixmap(":/qticon32.png");
+ pixmap2X = QPixmap(":/qticon32@2x.png");
+ pixmapLarge = QPixmap(":/qticon64.png");
+}
+
+void TiledPixmapPainter::paintEvent(QPaintEvent *event)
+{
+ Q_UNUSED(event);
+ QPainter p(this);
+
+ int xoff = 10;
+ int yoff = 10;
+ int tiles = 4;
+ int pixmapEdge = 32;
+ int tileAreaEdge = pixmapEdge * tiles;
+
+ // Expected behavior for both 1x and 2x dislays:
+ // 1x pixmap : 4 x 4 tiles
+ // large pixmap: 2 x 2 tiles
+ // 2x pixmap : 4 x 4 tiles
+ //
+ // On a 2x display the 2x pimxap tiles
+ // will be drawn in high resolution.
+ p.drawTiledPixmap(QRect(xoff, yoff, tileAreaEdge, tileAreaEdge), pixmap1X);
+ yoff += tiles * pixmapEdge + 10;
+ p.drawTiledPixmap(QRect(xoff, yoff, tileAreaEdge, tileAreaEdge), pixmapLarge);
+ yoff += tiles * pixmapEdge + 10;
+ p.drawTiledPixmap(QRect(xoff, yoff, tileAreaEdge, tileAreaEdge), pixmap2X);
+
+ // Again, with an offset. The offset is in
+ // device-independent pixels.
+ QPoint offset(40, 40); // larger than the pixmap edge size to exercise that code path
+ yoff = 10;
+ xoff = 20 + tiles * pixmapEdge ;
+ p.drawTiledPixmap(QRect(xoff, yoff, tileAreaEdge, tileAreaEdge), pixmap1X, offset);
+ yoff += tiles * pixmapEdge + 10;
+ p.drawTiledPixmap(QRect(xoff, yoff, tileAreaEdge, tileAreaEdge), pixmapLarge, offset);
+ yoff += tiles * pixmapEdge + 10;
+ p.drawTiledPixmap(QRect(xoff, yoff, tileAreaEdge, tileAreaEdge), pixmap2X, offset);
+}
+
class Labels : public QWidget
{
public:
@@ -579,7 +635,7 @@ template <typename T>
void apiTestdevicePixelRatioGetter()
{
if (0) {
- T *t = 0;
+ T *t = nullptr;
t->devicePixelRatio();
}
}
@@ -588,7 +644,7 @@ template <typename T>
void apiTestdevicePixelRatioSetter()
{
if (0) {
- T *t = 0;
+ T *t = nullptr;
t->setDevicePixelRatio(2.0);
}
}
@@ -791,7 +847,7 @@ class CursorTester : public QWidget
{
public:
CursorTester()
- :moveLabel(0), moving(false)
+ :moveLabel(nullptr), moving(false)
{
}
@@ -889,7 +945,7 @@ class ScreenDisplayer : public QWidget
{
public:
ScreenDisplayer()
- : QWidget(), moveLabel(0), scaleFactor(1.0)
+ : QWidget(), moveLabel(nullptr), scaleFactor(1.0)
{
}
@@ -1098,6 +1154,28 @@ void PhysicalSizeTest::paintEvent(QPaintEvent *)
}
+class GraphicsViewCaching : public QGraphicsView
+{
+public:
+ GraphicsViewCaching() {
+ QGraphicsScene *scene = new QGraphicsScene(0, 0, 400, 400);
+
+ QGraphicsTextItem *item = scene->addText("NoCache");
+ item->setCacheMode(QGraphicsItem::NoCache);
+ item->setPos(10, 10);
+
+ item = scene->addText("ItemCoordinateCache");
+ item->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+ item->setPos(10, 30);
+
+ item = scene->addText("DeviceCoordinateCache");
+ item->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ item->setPos(10, 50);
+
+ setScene(scene);
+ }
+};
+
int main(int argc, char **argv)
{
QApplication app(argc, argv);
@@ -1119,6 +1197,7 @@ int main(int argc, char **argv)
DemoContainerList demoList;
demoList << new DemoContainer<PixmapPainter>("pixmap", "Test pixmap painter");
+ demoList << new DemoContainer<TiledPixmapPainter>("tiledpixmap", "Test tiled pixmap painter");
demoList << new DemoContainer<Labels>("label", "Test Labels");
demoList << new DemoContainer<MainWindow>("mainwindow", "Test QMainWindow");
demoList << new DemoContainer<StandardIcons>("standard-icons", "Test standard icons");
@@ -1132,7 +1211,7 @@ int main(int argc, char **argv)
demoList << new DemoContainer<CursorTester>("cursorpos", "Test cursor and window positioning");
demoList << new DemoContainer<ScreenDisplayer>("screens", "Test screen and window positioning");
demoList << new DemoContainer<PhysicalSizeTest>("physicalsize", "Test manual highdpi support using physicalDotsPerInch");
-
+ demoList << new DemoContainer<GraphicsViewCaching>("graphicsview", "Test QGraphicsView caching");
foreach (DemoContainerBase *demo, demoList)
parser.addOption(demo->option());
diff --git a/tests/manual/windowchildgeometry/controllerwidget.cpp b/tests/manual/windowchildgeometry/controllerwidget.cpp
index 871313d983..396fad53dc 100644
--- a/tests/manual/windowchildgeometry/controllerwidget.cpp
+++ b/tests/manual/windowchildgeometry/controllerwidget.cpp
@@ -236,7 +236,7 @@ private:
WidgetWindowControl::WidgetWindowControl(QWidget *w )
: BaseWindowControl(w)
- , m_statesControl(new WindowStatesControl(WindowStatesControl::WantVisibleCheckBox | WindowStatesControl::WantActiveCheckBox))
+ , m_statesControl(new WindowStatesControl)
{
setTitle(w->windowTitle());
m_layout->addWidget(m_statesControl, 2, 0);
@@ -364,14 +364,14 @@ private:
virtual void setObjectWindowFlags(QObject *o, Qt::WindowFlags f)
{ static_cast<QWindow *>(o)->setFlags(f); }
- WindowStateControl *m_stateControl;
+ WindowStatesControl *m_statesControl;
QWindow *m_window;
QWindow *m_detachedParent; // set when this window is detached. This is the window we should re-attach to.
};
WindowControl::WindowControl(QWindow *w )
: BaseWindowControl(w)
- , m_stateControl(new WindowStateControl(WindowStateControl::WantVisibleCheckBox | WindowStateControl::WantMinimizeRadioButton))
+ , m_statesControl(new WindowStatesControl)
, m_window(w)
, m_detachedParent(0)
{
diff --git a/tests/manual/windowgeometry/controllerwidget.cpp b/tests/manual/windowgeometry/controllerwidget.cpp
index 7620d2df56..b05ea2907e 100644
--- a/tests/manual/windowgeometry/controllerwidget.cpp
+++ b/tests/manual/windowgeometry/controllerwidget.cpp
@@ -256,7 +256,7 @@ private:
WidgetWindowControl::WidgetWindowControl(QWidget *w )
: BaseWindowControl(w)
- , m_statesControl(new WindowStatesControl(WindowStatesControl::WantVisibleCheckBox | WindowStatesControl::WantActiveCheckBox))
+ , m_statesControl(new WindowStatesControl)
{
setTitle(w->windowTitle());
m_layout->addWidget(m_statesControl, 2, 0);
@@ -354,34 +354,34 @@ private:
virtual void setObjectWindowFlags(QObject *o, Qt::WindowFlags f)
{ static_cast<QWindow *>(o)->setFlags(f); }
- WindowStateControl *m_stateControl;
+ WindowStatesControl *m_statesControl;
};
WindowControl::WindowControl(QWindow *w )
: BaseWindowControl(w)
- , m_stateControl(new WindowStateControl(WindowStateControl::WantVisibleCheckBox | WindowStateControl::WantMinimizeRadioButton))
+ , m_statesControl(new WindowStatesControl)
{
setTitle(w->title());
QGroupBox *stateGroupBox = new QGroupBox(tr("State"));
QVBoxLayout *l = new QVBoxLayout(stateGroupBox);
- l->addWidget(m_stateControl);
+ l->addWidget(m_statesControl);
m_layout->addWidget(stateGroupBox, 2, 0);
- connect(m_stateControl, SIGNAL(changed()), this, SLOT(stateChanged()));
+ connect(m_statesControl, SIGNAL(changed()), this, SLOT(stateChanged()));
}
void WindowControl::refresh()
{
const QWindow *w = static_cast<const QWindow *>(m_object);
BaseWindowControl::refresh();
- m_stateControl->setVisibleValue(w->isVisible());
- m_stateControl->setState(w->windowState());
+ m_statesControl->setVisibleValue(w->isVisible());
+ m_statesControl->setStates(w->windowStates());
}
void WindowControl::stateChanged()
{
QWindow *w = static_cast<QWindow *>(m_object);
- w->setVisible(m_stateControl->visibleValue());
- w->setWindowState(m_stateControl->state());
+ w->setVisible(m_statesControl->visibleValue());
+ w->setWindowStates(m_statesControl->states());
}
#endif
diff --git a/tests/testserver/apache2/apache2.sh b/tests/testserver/apache2/apache2.sh
new file mode 100755
index 0000000000..4b0c74e2c4
--- /dev/null
+++ b/tests/testserver/apache2/apache2.sh
@@ -0,0 +1,77 @@
+#!/usr/bin/env bash
+
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the test suite of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:GPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 or (at your option) any later version
+## approved by the KDE Free Qt Foundation. The licenses are as published by
+## the Free Software Foundation and appearing in the file LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+set -ex
+
+# package apache2
+
+# add users
+useradd httptest; echo "httptest:httptest" | chpasswd
+
+# enable apache2 module
+/usr/sbin/a2enmod ssl dav_fs headers deflate auth_digest cgi
+
+# enable apache2 config
+cp $TESTDATA/{main,security,ssl,dav}.conf /etc/apache2/conf-available/
+/usr/sbin/a2enconf main security ssl dav
+
+# install configurations and test data
+cp $TESTDATA/deflate.conf /etc/apache2/mods-available/
+mkdir -p -m 1777 /home/writeables/dav # dav.conf
+a2dissite '*' # disable all of the default apache2 sites
+
+# Populate the web-site:
+su $USER -c "cp -r $TESTDATA/www ~/www"
+
+# tst_QNetworkReply::getFromHttp(success-internal)
+su $USER -c "cp rfc3252.txt ~/www/htdocs/"; rm rfc3252.txt
+
+# tst_QNetworkReply::synchronousRequest_data()
+su $USER -c "mkdir -p ~/www/htdocs/deflate/"
+su $USER -c "ln -s ~/www/htdocs/rfc3252.txt ~/www/htdocs/deflate/"
+
+# tst_QNetworkReply::headFromHttp(with-authentication)
+su $USER -c "ln -s ~/www/htdocs/rfc3252.txt ~/www/htdocs/rfcs-auth/"
+
+# Duplicate rfc3252.txt 20 times for bigfile tests:
+su $USER -c "seq 20 | xargs -i cat ~/www/htdocs/rfc3252.txt >> ~/www/htdocs/bigfile"
+
+# tst_QNetworkReply::postToHttp(empty)
+su $USER -c "ln -s ~/www/htdocs/protected/cgi-bin/md5sum.cgi ~/www/cgi-bin/"
+
+# tst_QNetworkReply::lastModifiedHeaderForHttp() expects this time-stamp:
+touch -d "2007-05-22 12:04:57 GMT" /home/$USER/www/htdocs/fluke.gif
+
+# Create 10MB file for use by tst_Q*::downloadBigFile and interruption tests:
+su $USER -c "/bin/dd if=/dev/zero of=~/www/htdocs/mediumfile bs=1 count=0 seek=10000000"
+
+# enable service with installed configurations
+service apache2 restart
diff --git a/tests/testserver/apache2/testdata/dav.conf b/tests/testserver/apache2/testdata/dav.conf
new file mode 100644
index 0000000000..c207c2734b
--- /dev/null
+++ b/tests/testserver/apache2/testdata/dav.conf
@@ -0,0 +1,7 @@
+Alias /dav /home/writeables/dav
+<Location /dav>
+ DAV On
+ order allow,deny
+ allow from all
+ Require all granted
+</Location>
diff --git a/tests/testserver/apache2/testdata/deflate.conf b/tests/testserver/apache2/testdata/deflate.conf
new file mode 100644
index 0000000000..6a15701d49
--- /dev/null
+++ b/tests/testserver/apache2/testdata/deflate.conf
@@ -0,0 +1,5 @@
+# The default configuration will turn on DEFLATE for files served up
+# from everywhere.
+#
+# For testing purposes, we want DEFLATE off by default, and on only for
+# specific paths (which is set elsewhere).
diff --git a/tests/testserver/apache2/testdata/main.conf b/tests/testserver/apache2/testdata/main.conf
new file mode 100644
index 0000000000..f3b13bb571
--- /dev/null
+++ b/tests/testserver/apache2/testdata/main.conf
@@ -0,0 +1,56 @@
+ServerName apache2.test-net.qt.local:80
+
+NameVirtualHost *:443
+
+<VirtualHost *:80>
+</VirtualHost>
+
+<VirtualHost *:443>
+SSLEngine On
+CustomLog /var/log/apache2/ssl_access.log combined
+ErrorLog /var/log/apache2/ssl_error.log
+</VirtualHost>
+
+# default ubuntu config turns off SSLv2 because it is deprecated.
+# Turn it back on so we can test it.
+SSLProtocol all
+
+DocumentRoot /home/qt-test-server/www/htdocs
+ScriptAlias /qtest/cgi-bin/ "/home/qt-test-server/www/cgi-bin/"
+ScriptAlias /qtest/protected/cgi-bin/ "/home/qt-test-server/www/htdocs/protected/cgi-bin/"
+Alias /qtest "/home/qt-test-server/www/htdocs/"
+
+<Directory "/home/qt-test-server/www/htdocs">
+ Require all granted
+</Directory>
+
+<Directory "/home/qt-test-server/www/htdocs/rfcs-auth">
+ AuthType Basic
+ AuthName "Restricted Files"
+ AuthUserFile /home/qt-test-server/passwords
+ Require user httptest
+</Directory>
+
+<Directory "/home/qt-test-server/www/htdocs/auth-digest">
+ AuthType Digest
+ AuthName "Digest testing"
+ AuthDigestProvider file
+ AuthUserFile /home/qt-test-server/www/htdocs/digest-authfile
+ Require user httptest
+</Directory>
+
+<Directory "/home/qt-test-server/www/htdocs/deflate">
+ AddOutputFilterByType DEFLATE text/html text/plain text/xml
+ Header append Vary User-Agent env=!dont-vary
+</Directory>
+
+<Directory "/home/qt-test-server/www/cgi-bin">
+ Options +ExecCGI -Includes
+ AddHandler cgi-script .cgi .pl
+ Require all granted
+</Directory>
+
+
+<Directory "/home/qt-test-server/www/htdocs/protected/">
+ AllowOverride AuthConfig Options
+</Directory>
diff --git a/tests/testserver/apache2/testdata/security.conf b/tests/testserver/apache2/testdata/security.conf
new file mode 100644
index 0000000000..30a8ee3765
--- /dev/null
+++ b/tests/testserver/apache2/testdata/security.conf
@@ -0,0 +1,51 @@
+#
+# Disable access to the entire file system except for the directories that
+# are explicitly allowed later.
+#
+# This currently breaks the configurations that come with some web application
+# Debian packages. It will be made the default for the release after lenny.
+#
+#<Directory />
+# AllowOverride None
+# Order Deny,Allow
+# Deny from all
+#</Directory>
+
+
+# Changing the following options will not really affect the security of the
+# server, but might make attacks slightly more difficult in some cases.
+
+#
+# ServerTokens
+# This directive configures what you return as the Server HTTP response
+# Header. The default is 'Full' which sends information about the OS-Type
+# and compiled in modules.
+# Set to one of: Full | OS | Minimal | Minor | Major | Prod
+# where Full conveys the most information, and Prod the least.
+#
+#ServerTokens Minimal
+ServerTokens OS
+#ServerTokens Full
+
+#
+# Optionally add a line containing the server version and virtual host
+# name to server-generated pages (internal error documents, FTP directory
+# listings, mod_status and mod_info output etc., but not CGI generated
+# documents or custom error documents).
+# Set to "EMail" to also include a mailto: link to the ServerAdmin.
+# Set to one of: On | Off | EMail
+#
+#ServerSignature Off
+ServerSignature On
+
+#
+# Allow TRACE method
+#
+# Set to "extended" to also reflect the request body (only for testing and
+# diagnostic purposes).
+#
+# Set to one of: On | Off | extended
+#
+#TraceEnable Off
+TraceEnable On
+
diff --git a/tests/testserver/apache2/testdata/ssl.conf b/tests/testserver/apache2/testdata/ssl.conf
new file mode 100644
index 0000000000..d6bbaf0da0
--- /dev/null
+++ b/tests/testserver/apache2/testdata/ssl.conf
@@ -0,0 +1,2 @@
+SSLCertificateFile /home/qt-test-server/ssl-certs/qt-test-server-cert.pem
+SSLCertificateKeyFile /home/qt-test-server/ssl-certs/private/qt-test-server-key.pem
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/echo.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/echo.cgi
new file mode 100755
index 0000000000..16315a3db6
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/echo.cgi
@@ -0,0 +1,11 @@
+#!/usr/bin/perl
+
+if ($ENV{'REQUEST_METHOD'} eq "GET") {
+ $request = $ENV{'QUERY_STRING'};
+} elsif ($ENV{'REQUEST_METHOD'} eq "POST") {
+ read(STDIN, $request, $ENV{'CONTENT_LENGTH'}) || die "Could not get query\n";
+}
+
+print "Content-type: text/plain\n\n";
+print $request;
+
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/get-cookie.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/get-cookie.cgi
new file mode 100755
index 0000000000..59f40ac78b
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/get-cookie.cgi
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+echo "Content-Type: text/plain"
+echo
+echo "$HTTP_COOKIE"
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/http-delete.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/http-delete.cgi
new file mode 100755
index 0000000000..18000c9f4c
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/http-delete.cgi
@@ -0,0 +1,22 @@
+#!/usr/bin/perl
+
+use CGI;
+
+if ($ENV{'REQUEST_METHOD'} eq "DELETE") {
+ $queryString = $ENV{'QUERY_STRING'};
+ if ($queryString eq "200-ok") {
+ $returnCode = 200;
+ } elsif ($queryString eq "202-accepted") {
+ $returnCode = 202;
+ } elsif ($queryString eq "204-no-content") {
+ $returnCode = 204;
+ } else {
+ $returnCode = 404;
+ }
+} else {
+ # 405 = Method Not Allowed
+ $returnCode = 405;
+}
+
+$q = new CGI;
+print $q->header(-status=>$returnCode);
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/http-unknown-authentication-method.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/http-unknown-authentication-method.cgi
new file mode 100755
index 0000000000..ce47e8384c
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/http-unknown-authentication-method.cgi
@@ -0,0 +1,17 @@
+#!/usr/bin/perl
+
+use CGI;
+
+$queryString = $ENV{'QUERY_STRING'};
+my $message;
+if ($queryString eq "407-proxy-authorization-required") {
+ $status = 407;
+} else {
+ $status = 401;
+}
+
+$q = new CGI;
+print $q->header(-status=>$status,
+ -type=>"text/plain",
+ -WWW_Authenticate=>'WSSE realm="Test", profile="TestProfile"'),
+ "authorization required";
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_expires500.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_expires500.cgi
new file mode 100755
index 0000000000..66a3741641
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/httpcachetest_expires500.cgi
@@ -0,0 +1,12 @@
+#!/bin/bash
+if [ "${HTTP_IF_MODIFIED_SINCE}" ]
+then
+ echo "Status: 500"
+ echo ""
+ exit;
+fi
+
+echo "Expires: Mon, 30 Oct 2028 14:19:41 GMT"
+echo "Content-type: text/html";
+echo ""
+echo "Hello World!"
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/multipart.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/multipart.cgi
new file mode 100755
index 0000000000..6973875cc9
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/multipart.cgi
@@ -0,0 +1,42 @@
+#!/usr/bin/perl
+
+use CGI;
+use Digest::MD5 qw(md5_hex);
+
+$q = new CGI;
+print $q->header();
+
+$contentType = $ENV{"CONTENT_TYPE"};
+print "content type: $contentType\n";
+
+if ($contentType =~ /^multipart\/form-data/) {
+ foreach my $key ($q->param) {
+ foreach my $value ($q->param($key)) {
+ if ($key =~ /text/) {
+ $retValue = $value;
+ } else {
+ $retValue = md5_hex($value);
+ }
+ print "key: $key, value: $retValue\n";
+ }
+ }
+} else {
+ #$contentLength = $ENV{"CONTENT_LENGTH"};
+ #print "content length: $contentLength\r\n";
+
+ $data = $q->param('POSTDATA');
+ $data =~ s/--\S*--$//; # remove ending boundary
+ @parts = split(/--\S*\r\n/, $data);
+ shift(@parts);
+ foreach (@parts) {
+ #print "raw: $_";
+ ($header, $content) = split("\r\n\r\n");
+ @headerFields = split("\r\n", $header);
+ foreach (@headerFields) {
+ ($fieldName, $value) = split(": ");
+ print "header: $fieldName, value: '$value'\n";
+ }
+ $content =~ s/\r\n//;
+ print "content: $content\n\n";
+ }
+}
diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/set-cookie.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/set-cookie.cgi
new file mode 100755
index 0000000000..dc463f00f3
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/cgi-bin/set-cookie.cgi
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+echo "Content-type: text/plain"
+while read line; do
+ echo "Set-Cookie: $line"
+done
+
+echo
+echo "Success"
diff --git a/tests/testserver/apache2/testdata/www/htdocs/auth-digest/index.html b/tests/testserver/apache2/testdata/www/htdocs/auth-digest/index.html
new file mode 100644
index 0000000000..fa96496aa0
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/htdocs/auth-digest/index.html
@@ -0,0 +1 @@
+digest authentication successful
diff --git a/tests/testserver/apache2/testdata/www/htdocs/digest-authfile b/tests/testserver/apache2/testdata/www/htdocs/digest-authfile
new file mode 100644
index 0000000000..99963901ce
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/htdocs/digest-authfile
@@ -0,0 +1 @@
+httptest:Digest testing:5f68f4bc3cd2873a3d547558fe7d9782
diff --git a/tests/testserver/apache2/testdata/www/htdocs/fluke.gif b/tests/testserver/apache2/testdata/www/htdocs/fluke.gif
new file mode 100644
index 0000000000..6060cbd4d7
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/htdocs/fluke.gif
Binary files differ
diff --git a/tests/testserver/apache2/testdata/www/htdocs/index.html b/tests/testserver/apache2/testdata/www/htdocs/index.html
new file mode 100644
index 0000000000..abc1df188d
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/htdocs/index.html
@@ -0,0 +1,3 @@
+<h1>Welcome to qt-test-server</h1>
+<img src="fluke.gif" alt="fluke">
+<p>This is a network test server. It serves as a caching ftp and http proxy, transparent http/socks5 proxy, imap, ftp and http server, and more.</p>
diff --git a/tests/testserver/apache2/testdata/www/htdocs/protected/.htaccess b/tests/testserver/apache2/testdata/www/htdocs/protected/.htaccess
new file mode 100644
index 0000000000..c465494167
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/htdocs/protected/.htaccess
@@ -0,0 +1,5 @@
+Require valid-user
+AuthUserFile /home/qt-test-server/passwords
+AuthType basic
+AuthName "password-protected area"
+Options Indexes
diff --git a/tests/testserver/apache2/testdata/www/htdocs/protected/cgi-bin/md5sum.cgi b/tests/testserver/apache2/testdata/www/htdocs/protected/cgi-bin/md5sum.cgi
new file mode 100755
index 0000000000..e580462b85
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/htdocs/protected/cgi-bin/md5sum.cgi
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+echo "Content-type: text/plain";
+echo "Content-length: 33"
+echo
+md5sum | cut -f 1 -d " "
diff --git a/tests/testserver/apache2/testdata/www/htdocs/rfcs-auth/index.html b/tests/testserver/apache2/testdata/www/htdocs/rfcs-auth/index.html
new file mode 100644
index 0000000000..472e6ce55d
--- /dev/null
+++ b/tests/testserver/apache2/testdata/www/htdocs/rfcs-auth/index.html
@@ -0,0 +1 @@
+you found the secret
diff --git a/tests/testserver/common/ssl.sh b/tests/testserver/common/ssl.sh
new file mode 100755
index 0000000000..8a4728ad4d
--- /dev/null
+++ b/tests/testserver/common/ssl.sh
@@ -0,0 +1,39 @@
+#!/usr/bin/env bash
+
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the test suite of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:GPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 or (at your option) any later version
+## approved by the KDE Free Qt Foundation. The licenses are as published by
+## the Free Software Foundation and appearing in the file LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+set -ex
+
+# package ssl
+
+# install ssl_certs and test data
+su $USER -c "mkdir -p -m 700 ~/ssl-certs/private"
+su $USER -c "cp $CONFIG/ssl/qt-test-server-cert.pem ~/ssl-certs/"
+su $USER -c "cp $CONFIG/ssl/private/qt-test-server-key.pem ~/ssl-certs/private/"
diff --git a/tests/testserver/common/startup.sh b/tests/testserver/common/startup.sh
new file mode 100755
index 0000000000..84d4003f86
--- /dev/null
+++ b/tests/testserver/common/startup.sh
@@ -0,0 +1,57 @@
+#!/usr/bin/env bash
+
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the test suite of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:GPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 or (at your option) any later version
+## approved by the KDE Free Qt Foundation. The licenses are as published by
+## the Free Software Foundation and appearing in the file LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+set -ex
+
+# export variables
+export USER=qt-test-server
+export PASS=password
+export CONFIG=common/testdata
+export TESTDATA=service/testdata
+
+# add users
+useradd -m -s /bin/bash $USER; echo "$USER:$PASS" | chpasswd
+
+# install configurations and test data
+su $USER -c "cp $CONFIG/system/passwords ~/"
+
+# modules initialization (apache2.sh, ftp-proxy.sh ...)
+for RUN_CMD
+do $RUN_CMD
+done
+
+# start multicast DNS service discovery (mDNS)
+sed -i "s,#domain-name=local,domain-name=test-net.qt.local," /etc/avahi/avahi-daemon.conf
+service dbus restart
+service avahi-daemon restart
+
+# keep-alive in docker detach mode
+sleep infinity
diff --git a/tests/testserver/common/testdata/ssl/private/qt-test-server-key.pem b/tests/testserver/common/testdata/ssl/private/qt-test-server-key.pem
new file mode 100644
index 0000000000..8b7ce5811a
--- /dev/null
+++ b/tests/testserver/common/testdata/ssl/private/qt-test-server-key.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXgIBAAKBgQDNqttv1jTJp/HAvuRBGBniAski5qfVugMunih69F8ad193qRE7
+j37wLsae6zrZEtfBDFHoJFI/I8NCDBHG8hyhQv60wmmDrfdwsRgVzCAoYjDwLBXm
+Mxmvw+scwJH3EWiUUPhJNwgy1z5136O8aQAV3s2HD1wCa4LIAX1q8B3ccwIDAQAB
+AoGAGiDou+6UykHB3uDhkruDHkmIUBzJmceF+/gv4F8Hbg9YW5VpEQ4L7Guk5C+y
+TD2ul2H/TeS/ZjIe7lcmMwYzSLcyeKfaiaV1EhPGjIdvB4ysTN79pfWXQtlpt/Z9
+I/EOoW9XosJ/EOFdpgV0MC9QMTQKMyS0qQLwhBsoAW4DcEECQQDmrWEPNprbEDIH
+Sm+KlMH6rdybIvzR3IPlYE6kMjQIWbUmGNxSUT7B/UDh2QeaTT54Rb1Ygnq7gVjC
+RHU3wnGxAkEA5D6jI/E/xtQSq0KKVpbOxN1dIo0MVPbO/hI7/pO2DdZIM0O4GL55
+ks83O5ZDTfrVy2Ys/9lqbbq+5FSs+NZ1YwJBANzAXRsO+YDcbdP2Uun+0+fOjEhW
+YjV/XyWaVYfil1LKboXn0qhgIbvJXVcEt7bdZwP4UWwracKY1NUMaFSVGvECQQC/
+L3iX8szpT1sT+XjHbytj28jX2C4sPVDFoaB/bltg280+o8rhbyuGvewWDZfzCdlr
+tvqalROBNpwPxp3dEkbhAkEAl7N7/7hWbw7Xv69ww7i0jcPduukbtbEY1DTmARhR
+rOF5AiztOAe+R94iLzkj63ZU0LcoSAixehp2tdkdtTI4CQ==
+-----END RSA PRIVATE KEY-----
diff --git a/tests/testserver/common/testdata/ssl/qt-test-server-cert.pem b/tests/testserver/common/testdata/ssl/qt-test-server-cert.pem
new file mode 100644
index 0000000000..43c8794ce2
--- /dev/null
+++ b/tests/testserver/common/testdata/ssl/qt-test-server-cert.pem
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIIClTCCAf4CCQC2xMhNhwvATDANBgkqhkiG9w0BAQQFADCBjjELMAkGA1UEChMC
+UXQxGTAXBgNVBAsTEENvcmUgQW5kIE5ldHdvcmsxGzAZBgkqhkiG9w0BCQEWDG5v
+Ym9keS5xdC5pbzENMAsGA1UEBxMET3NsbzENMAsGA1UECBMET3NsbzELMAkGA1UE
+BhMCTk8xHDAaBgNVBAMUEyoudGVzdC1uZXQucXQubG9jYWwwHhcNMTgwNzAxMTgz
+NjI3WhcNNDgwNjIzMTgzNjI3WjCBjjELMAkGA1UEChMCUXQxGTAXBgNVBAsTEENv
+cmUgQW5kIE5ldHdvcmsxGzAZBgkqhkiG9w0BCQEWDG5vYm9keS5xdC5pbzENMAsG
+A1UEBxMET3NsbzENMAsGA1UECBMET3NsbzELMAkGA1UEBhMCTk8xHDAaBgNVBAMU
+EyoudGVzdC1uZXQucXQubG9jYWwwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
+AM2q22/WNMmn8cC+5EEYGeICySLmp9W6Ay6eKHr0Xxp3X3epETuPfvAuxp7rOtkS
+18EMUegkUj8jw0IMEcbyHKFC/rTCaYOt93CxGBXMIChiMPAsFeYzGa/D6xzAkfcR
+aJRQ+Ek3CDLXPnXfo7xpABXezYcPXAJrgsgBfWrwHdxzAgMBAAEwDQYJKoZIhvcN
+AQEEBQADgYEAZu/lQPy8PXeyyYGamOVms/FZKJ48BH1y8KC3BeBU5FYnhvgG7pz8
+Wz9JKvt2t/r45wQeAkNL6HnGUBhPJsHMjPHl5KktqN+db3D+FQygBeS2V1+zmC0X
+UZNRE4aWiHvt1Lq+pTx89SOMOpfqWfh4qTQKiE5jC2V4DeCNQ3u7uI8=
+-----END CERTIFICATE-----
diff --git a/tests/testserver/common/testdata/system/passwords b/tests/testserver/common/testdata/system/passwords
new file mode 100644
index 0000000000..4e911b3f0e
--- /dev/null
+++ b/tests/testserver/common/testdata/system/passwords
@@ -0,0 +1,12 @@
+# user: foo; passwd: bar
+foo:bab.5ZXQdbvEo
+
+# user: qsockstest; passwd: qsockstest
+#qsockstest:S7oOqMpoG6aTk
+
+# user: qsockstest; passwd: password
+qsockstest:Cd3Lv2aD0aiBs
+
+#user httptest password httptest
+httptest:v2fwkDMgrRjRA
+# added by mgoetz for tst_qnetworkreply ioPostToHttpFromSocket
diff --git a/tests/testserver/danted/danted.sh b/tests/testserver/danted/danted.sh
new file mode 100755
index 0000000000..bf3d154f33
--- /dev/null
+++ b/tests/testserver/danted/danted.sh
@@ -0,0 +1,44 @@
+#!/usr/bin/env bash
+
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the test suite of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:GPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 or (at your option) any later version
+## approved by the KDE Free Qt Foundation. The licenses are as published by
+## the Free Software Foundation and appearing in the file LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+set -ex
+
+# package dante-server
+
+# add users
+useradd -d /dev/null -s /bin/false qsockstest; echo "qsockstest:$PASS" | chpasswd
+
+# install configurations and test data
+cp $TESTDATA/danted{,-authenticating}.conf /etc/
+
+# enable service with installed configurations
+service danted start
+service danted-authenticating start
diff --git a/tests/testserver/danted/testdata/danted-authenticating.conf b/tests/testserver/danted/testdata/danted-authenticating.conf
new file mode 100644
index 0000000000..ccb4acc801
--- /dev/null
+++ b/tests/testserver/danted/testdata/danted-authenticating.conf
@@ -0,0 +1,19 @@
+# A sample danted-authenticating.conf
+# See: https://www.inet.no/dante/doc/1.4.x/config/
+logoutput: /var/log/sockd-authenticating.log
+internal: eth0 port = 1081
+external: eth0
+method: username
+user.privileged: root
+user.notprivileged: nobody
+user.libwrap: nobody
+
+client pass {
+ from: 0.0.0.0/0 to: 0.0.0.0/0
+ log: error connect disconnect
+}
+
+pass {
+ from: 0.0.0.0/0 to: 0.0.0.0/0
+ log: error connect disconnect
+}
diff --git a/tests/testserver/danted/testdata/danted.conf b/tests/testserver/danted/testdata/danted.conf
new file mode 100644
index 0000000000..bd0e6a8343
--- /dev/null
+++ b/tests/testserver/danted/testdata/danted.conf
@@ -0,0 +1,19 @@
+# A sample danted.conf
+# See: https://www.inet.no/dante/doc/1.4.x/config/
+logoutput: /var/log/sockd.log
+internal: eth0 port = 1080
+external: eth0
+method: username none
+user.privileged: proxy
+user.notprivileged: nobody
+user.libwrap: nobody
+
+client pass {
+ from: 0.0.0.0/0 to: 0.0.0.0/0
+ log: error connect disconnect
+}
+
+pass {
+ from: 0.0.0.0/0 to: 0.0.0.0/0
+ log: error connect disconnect
+}
diff --git a/tests/testserver/docker-compose.yml b/tests/testserver/docker-compose.yml
new file mode 100644
index 0000000000..a151d6bfb0
--- /dev/null
+++ b/tests/testserver/docker-compose.yml
@@ -0,0 +1,83 @@
+version: '3.4'
+
+# The tag of images is used by docker compose file to launch the corresponding
+# docker containers. The value of tag comes from the provisioning script
+# (coin/provisioning/.../testserver/docker_testserver.sh). The script gets SHA-1
+# of each server context as the tag of docker images. If one of the server
+# contexts gets changes, please make sure to update this compose file as well.
+# You can run command 'docker images' to list all the tag of test server images.
+# For example:
+# REPOSITORY TAG IMAGE ID
+# qt-test-server-apache2 e2a70c8b169c204e762b375885bd3a26cc40ba48 2ad5c8720317
+
+services:
+ apache2:
+ image: qt-test-server-apache2:cc9ea678b92bdda33acb9fa0159bb4ad0f3cd947
+ container_name: qt-test-server-apache2
+ domainname: test-net.qt.local
+ hostname: apache2
+ volumes:
+ - ./common:/common:ro
+ - ./apache2:/service:ro
+ entrypoint: common/startup.sh
+ command: [common/ssl.sh, service/apache2.sh]
+
+ squid:
+ image: qt-test-server-squid:577d99307eea9a8cccfec944d25be2bce2fe99cc
+ container_name: qt-test-server-squid
+ domainname: test-net.qt.local
+ hostname: squid
+ depends_on:
+ - apache2
+ external_links:
+ - apache2:apache2.test-net.qt.local
+ volumes:
+ - ./common:/common:ro
+ - ./squid:/service:ro
+ entrypoint: common/startup.sh
+ command: service/squid.sh
+
+ vsftpd:
+ image: qt-test-server-vsftpd:18896604c7e90b543e56d80c8a8aabdb65a590d0
+ container_name: qt-test-server-vsftpd
+ domainname: test-net.qt.local
+ hostname: vsftpd
+ volumes:
+ - ./common:/common:ro
+ - ./vsftpd:/service:ro
+ entrypoint: common/startup.sh
+ command: service/vsftpd.sh
+
+ ftp-proxy:
+ image: qt-test-server-ftp-proxy:2c6c8f1ab6a364b540c43d705fb6f15a585cb2af
+ container_name: qt-test-server-ftp-proxy
+ domainname: test-net.qt.local
+ hostname: ftp-proxy
+ depends_on:
+ - vsftpd
+ external_links:
+ - vsftpd:vsftpd.test-net.qt.local
+ volumes:
+ - ./common:/common:ro
+ - ./ftp-proxy:/service:ro
+ entrypoint: common/startup.sh
+ command: service/ftp-proxy.sh
+
+ danted:
+ image: qt-test-server-danted:327dd56c3c35db85b26fac93213a5a1918475bc7
+ container_name: qt-test-server-danted
+ domainname: test-net.qt.local
+ hostname: danted
+ depends_on:
+ - apache2
+ - vsftpd
+ - ftp-proxy
+ external_links:
+ - apache2:apache2.test-net.qt.local
+ - vsftpd:vsftpd.test-net.qt.local
+ - ftp-proxy:ftp-proxy.test-net.qt.local
+ volumes:
+ - ./common:/common:ro
+ - ./danted:/service:ro
+ entrypoint: common/startup.sh
+ command: service/danted.sh
diff --git a/tests/testserver/ftp-proxy/ftp-proxy.sh b/tests/testserver/ftp-proxy/ftp-proxy.sh
new file mode 100755
index 0000000000..087a7b7bcc
--- /dev/null
+++ b/tests/testserver/ftp-proxy/ftp-proxy.sh
@@ -0,0 +1,40 @@
+#!/usr/bin/env bash
+
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the test suite of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:GPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 or (at your option) any later version
+## approved by the KDE Free Qt Foundation. The licenses are as published by
+## the Free Software Foundation and appearing in the file LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+set -ex
+
+# package ftp-proxy
+
+# install configurations and test data
+sed -i 's/# AllowMagicUser\tno/AllowMagicUser\tyes/' /etc/proxy-suite/ftp-proxy.conf
+
+# enable service with installed configurations
+ftp-proxy -d
diff --git a/tests/testserver/squid/squid.sh b/tests/testserver/squid/squid.sh
new file mode 100755
index 0000000000..8e413f2f14
--- /dev/null
+++ b/tests/testserver/squid/squid.sh
@@ -0,0 +1,46 @@
+#!/usr/bin/env bash
+
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the test suite of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:GPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 or (at your option) any later version
+## approved by the KDE Free Qt Foundation. The licenses are as published by
+## the Free Software Foundation and appearing in the file LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+set -ex
+
+# package squid
+
+# install configurations and test data
+cp $TESTDATA/squid{,-authenticating-ntlm}.conf /etc/squid/
+sed -e 's,NAME=squid,NAME=squid-authenticating-ntlm,' \
+ -e 's,CONFIG=/etc/squid/squid.conf,CONFIG=/etc/squid/squid-authenticating-ntlm.conf,' \
+ -e 's,SQUID_ARGS="-YC -f $CONFIG",SQUID_ARGS="-D -YC -f $CONFIG",' \
+ /etc/init.d/squid >/etc/init.d/squid-authenticating-ntlm
+chmod +x /etc/init.d/squid-authenticating-ntlm
+
+# enable service with installed configurations
+service squid start
+service squid-authenticating-ntlm start
diff --git a/tests/testserver/squid/testdata/squid-authenticating-ntlm.conf b/tests/testserver/squid/testdata/squid-authenticating-ntlm.conf
new file mode 100644
index 0000000000..55a74498e9
--- /dev/null
+++ b/tests/testserver/squid/testdata/squid-authenticating-ntlm.conf
@@ -0,0 +1,41 @@
+pid_filename /var/run/squid-authenticating-ntlm.pid
+access_log /var/log/squid/access-authenticating-ntlm.log
+cache_log /var/log/squid/cache-authenticating-ntlm.log
+cache_store_log /var/log/squid/store-authenticating-ntlm.log
+http_port 3130
+hierarchy_stoplist cgi-bin ?
+acl QUERY urlpath_regex cgi-bin \?
+no_cache deny QUERY
+refresh_pattern ^ftp: 1440 20% 10080
+refresh_pattern ^gopher: 1440 0% 1440
+refresh_pattern . 0 20% 4320
+acl port3130 myport 3130
+acl manager proto cache_object
+acl localhost src 127.0.0.1/255.255.255.255
+acl to_localhost dst 127.0.0.0/8
+acl SSL_ports port 443 563
+acl Safe_ports port 80 # http
+acl Safe_ports port 21 # ftp
+acl Safe_ports port 443 563 # https, snews
+acl Safe_ports port 70 # gopher
+acl Safe_ports port 210 # wais
+acl Safe_ports port 1025-65535 # unregistered ports
+acl Safe_ports port 280 # http-mgmt
+acl Safe_ports port 488 # gss-http
+acl Safe_ports port 591 # filemaker
+acl Safe_ports port 777 # multiling http
+acl CONNECT method CONNECT
+http_access allow manager localhost
+http_access deny manager
+http_access allow localhost
+
+
+# port 3130: ntlm auth
+auth_param ntlm program /usr/lib/squid/ntlm_smb_lm_auth --debuglevel=5 --logfile=/var/log/ntlm --log-basename=/var/log/ntlm --helper-protocol=squid-2.5-ntlmssp
+auth_param ntlm children 2
+acl ntlm_users proxy_auth REQUIRED
+http_access allow port3130 ntlm_users
+http_reply_access allow port3130 ntlm_users
+
+icp_access allow all
+coredump_dir /var/cache/squid
diff --git a/tests/testserver/squid/testdata/squid.conf b/tests/testserver/squid/testdata/squid.conf
new file mode 100644
index 0000000000..da1b13af8c
--- /dev/null
+++ b/tests/testserver/squid/testdata/squid.conf
@@ -0,0 +1,46 @@
+http_port 3128
+http_port 3129
+hierarchy_stoplist cgi-bin ?
+acl QUERY urlpath_regex cgi-bin \?
+no_cache deny QUERY
+refresh_pattern ^ftp: 1440 20% 10080
+refresh_pattern ^gopher: 1440 0% 1440
+refresh_pattern . 0 20% 4320
+acl port3128 myport 3128
+acl port3129 myport 3129
+acl manager proto cache_object
+acl localhost src 127.0.0.1/255.255.255.255
+acl to_localhost dst 127.0.0.0/8
+acl SSL_ports port 443 563
+acl Safe_ports port 80 # http
+acl Safe_ports port 21 # ftp
+acl Safe_ports port 443 563 # https, snews
+acl Safe_ports port 70 # gopher
+acl Safe_ports port 210 # wais
+acl Safe_ports port 1025-65535 # unregistered ports
+acl Safe_ports port 280 # http-mgmt
+acl Safe_ports port 488 # gss-http
+acl Safe_ports port 591 # filemaker
+acl Safe_ports port 777 # multiling http
+acl CONNECT method CONNECT
+http_access allow manager localhost
+http_access deny manager
+http_access allow localhost
+
+
+# port 3128: no auth required
+http_access allow port3128
+http_reply_access allow port3128
+
+# port 3129: basic auth
+auth_param basic program /usr/lib/squid/basic_ncsa_auth /home/qt-test-server/passwords
+auth_param basic children 5
+auth_param basic realm Squid proxy-caching web server
+auth_param basic credentialsttl 2 hours
+auth_param basic casesensitive off
+acl ncsa_users proxy_auth REQUIRED
+http_access allow port3129 ncsa_users
+http_reply_access allow port3129 ncsa_users
+
+icp_access allow all
+coredump_dir /var/cache/squid
diff --git a/tests/testserver/vsftpd/testdata/ftp/pub/file-not-readable.txt b/tests/testserver/vsftpd/testdata/ftp/pub/file-not-readable.txt
new file mode 100644
index 0000000000..235fa4d28b
--- /dev/null
+++ b/tests/testserver/vsftpd/testdata/ftp/pub/file-not-readable.txt
@@ -0,0 +1 @@
+If you can read this, you are too close.
diff --git a/tests/testserver/vsftpd/testdata/vsftpd.conf b/tests/testserver/vsftpd/testdata/vsftpd.conf
new file mode 100644
index 0000000000..6bdb186c9f
--- /dev/null
+++ b/tests/testserver/vsftpd/testdata/vsftpd.conf
@@ -0,0 +1,112 @@
+# Allow anonymous FTP? (Beware - allowed by default if you comment this out).
+anonymous_enable=YES
+#
+# Uncomment this to allow local users to log in.
+local_enable=YES
+#
+# Uncomment this to enable any form of FTP write command.
+write_enable=YES
+#
+# Default umask for local users is 077. You may wish to change this to 022,
+# if your users expect that (022 is used by most other ftpd's)
+local_umask=022
+#
+# Uncomment this to allow the anonymous FTP user to upload files. This only
+# has an effect if the above global write enable is activated. Also, you will
+# obviously need to create a directory writable by the FTP user.
+anon_upload_enable=YES
+anon_umask=022
+#
+# Uncomment this if you want the anonymous FTP user to be able to create
+# new directories.
+anon_mkdir_write_enable=YES
+anon_other_write_enable=YES
+anon_world_readable_only=YES
+#
+# Activate directory messages - messages given to remote users when they
+# go into a certain directory.
+dirmessage_enable=YES
+#
+# Activate logging of uploads/downloads.
+xferlog_enable=YES
+#
+# Make sure PORT transfer connections originate from port 20 (ftp-data).
+connect_from_port_20=YES
+#
+# If you want, you can arrange for uploaded anonymous files to be owned by
+# a different user. Note! Using "root" for uploaded files is not
+# recommended!
+#chown_uploads=YES
+#chown_username=ftp
+#chown_groupname=ftp
+#
+# You may override where the log file goes if you like. The default is shown
+# below.
+#xferlog_file=/var/log/vsftpd.log
+#
+# If you want, you can have your log file in standard ftpd xferlog format
+xferlog_std_format=YES
+#
+# You may change the default value for timing out an idle session.
+#idle_session_timeout=600
+#
+# You may change the default value for timing out a data connection.
+#data_connection_timeout=120
+#
+# It is recommended that you define on your system a unique user which the
+# ftp server can use as a totally isolated and unprivileged user.
+#nopriv_user=ftpsecure
+#
+# Enable this and the server will recognize asynchronous ABOR requests. Not
+# recommended for security (the code is non-trivial). Not enabling it,
+# however, may confuse older FTP clients.
+#async_abor_enable=YES
+#
+# By default the server will pretend to allow ASCII mode but in fact ignore
+# the request. Turn on the below options to have the server actually do ASCII
+# mangling on files when in ASCII mode.
+# Beware that on some FTP servers, ASCII support allows a denial of service
+# attack (DoS) via the command "SIZE /big/file" in ASCII mode. vsftpd
+# predicted this attack and has always been safe, reporting the size of the
+# raw file.
+# ASCII mangling is a horrible feature of the protocol.
+ascii_upload_enable=YES
+ascii_download_enable=YES
+#
+# You may fully customize the login banner string:
+#ftpd_banner=Welcome to blah FTP service.
+#
+# You may specify a file of disallowed anonymous e-mail addresses. Apparently
+# useful for combatting certain DoS attacks.
+#deny_email_enable=YES
+# (default follows)
+#banned_email_file=/etc/vsftpd/banned_emails
+#
+# You may specify an explicit list of local users to chroot() to their home
+# directory. If chroot_local_user is YES, then this list becomes a list of
+# users to NOT chroot().
+#chroot_list_enable=YES
+# (default follows)
+#chroot_list_file=/etc/vsftpd/chroot_list
+#
+# You may activate the "-R" option to the builtin ls. This is disabled by
+# default to avoid remote users being able to cause excessive I/O on large
+# sites. However, some broken FTP clients such as "ncftp" and "mirror" assume
+# the presence of the "-R" option, so there is a strong case for enabling it.
+ls_recurse_enable=YES
+
+pam_service_name=vsftpd
+userlist_enable=YES
+#enable for standalone mode
+listen=YES
+tcp_wrappers=YES
+
+# Enabling SFTP
+#ssl_enable=YES
+#allow_anon_ssl=YES
+#force_local_data_ssl=NO
+#force_local_logins_ssl=NO
+#ssl_tlsv1=YES
+#ssl_sslv2=NO
+#ssl_sslv3=NO
+#rsa_cert_file=/etc/vsftpd/vsftpd.pem
diff --git a/tests/testserver/vsftpd/testdata/vsftpd.user_list b/tests/testserver/vsftpd/testdata/vsftpd.user_list
new file mode 100644
index 0000000000..d283e3d260
--- /dev/null
+++ b/tests/testserver/vsftpd/testdata/vsftpd.user_list
@@ -0,0 +1,20 @@
+# vsftpd userlist
+# If userlist_deny=NO, only allow users in this file
+# If userlist_deny=YES (default), never allow users in this file, and
+# do not even prompt for a password.
+# Note that the default vsftpd pam config also checks /etc/vsftpd.ftpusers
+# for users that are denied.
+root
+bin
+daemon
+adm
+lp
+sync
+shutdown
+halt
+mail
+news
+uucp
+operator
+games
+nobody
diff --git a/tests/testserver/vsftpd/vsftpd.sh b/tests/testserver/vsftpd/vsftpd.sh
new file mode 100755
index 0000000000..1ba1a8c347
--- /dev/null
+++ b/tests/testserver/vsftpd/vsftpd.sh
@@ -0,0 +1,66 @@
+#!/usr/bin/env bash
+
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the test suite of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:GPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 or (at your option) any later version
+## approved by the KDE Free Qt Foundation. The licenses are as published by
+## the Free Software Foundation and appearing in the file LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+set -ex
+
+# package vsftpd
+
+# add users
+usermod -d "/home/$USER/ftp/" ftp #existing user
+useradd -d "/home/$USER/ftp" -s /bin/bash ftptest; echo "ftptest:$PASS" | chpasswd
+
+# install configurations and test data
+cp $TESTDATA/vsftpd.{conf,user_list} /etc/
+
+# Resolve error message "vsftpd failed - probably invalid config" during boot
+command='start-stop-daemon --start --background -m --oknodo --pidfile /var/run/vsftpd/vsftpd.pid'
+command+=' --exec ${DAEMON}'
+sed -i "s,$command.*$,$command; sleep 1," /etc/init.d/vsftpd
+
+# Populate the FTP sites:
+su $USER -c "cp -r $TESTDATA/ftp ~/ftp"
+ln -s /home/$USER/ftp /var/ftp
+
+# tst_QNetworkReply::getFromFtp_data()
+su $USER -c "mkdir -p ~/ftp/qtest/"
+su $USER -c "cp rfc3252.txt ~/ftp/qtest/"; rm rfc3252.txt
+
+# Duplicate rfc3252.txt 20 times for bigfile tests:
+su $USER -c "seq 20 | xargs -i cat ~/ftp/qtest/rfc3252.txt >> ~/ftp/qtest/bigfile"
+
+# tst_QNetworkReply::getErrors_data(), testdata with special permissions
+su $USER -c "chmod 0600 ~/ftp/pub/file-not-readable.txt"
+
+# Shared FTP folder (sticky bit)
+su $USER -c "mkdir -p -m 1777 ~/ftp/qtest/upload" # FTP incoming dir
+
+# enable service with installed configurations
+service vsftpd restart
diff --git a/util/edid/qedidvendortable.py b/util/edid/qedidvendortable.py
index bac8417326..6fc45dbc17 100755
--- a/util/edid/qedidvendortable.py
+++ b/util/edid/qedidvendortable.py
@@ -29,7 +29,10 @@
import urllib.request
-url = 'https://git.fedorahosted.org/cgit/hwdata.git/plain/pnp.ids'
+# The original source for this data used to be
+# 'https://git.fedorahosted.org/cgit/hwdata.git/plain/pnp.ids'
+# which is discontinued. For now there seems to be a fork at:
+url = 'https://github.com/vcrhonek/hwdata/raw/master/pnp.ids'
copyright = """/****************************************************************************
**
@@ -74,7 +77,7 @@ copyright = """/****************************************************************
notice = """/*
* This lookup table was generated from {}
*
- * Do not change directly this file, instead edit the
+ * Do not change this file directly, instead edit the
* qtbase/util/edid/qedidvendortable.py script and regenerate this file.
*/""".format(url)
@@ -129,6 +132,6 @@ for line in data.split('\n'):
print(copyright)
print(notice)
print(header % (max_vendor_length + 1))
-for pnp_id in vendors.keys():
+for pnp_id in sorted(vendors.keys()):
print(' { "%s", "%s" },' % (pnp_id, vendors[pnp_id]))
print(footer)
diff --git a/util/gradientgen/.gitignore b/util/gradientgen/.gitignore
new file mode 100644
index 0000000000..1a8e824bee
--- /dev/null
+++ b/util/gradientgen/.gitignore
@@ -0,0 +1,2 @@
+node_modules
+tobinaryjson
diff --git a/util/gradientgen/gradientgen.js b/util/gradientgen/gradientgen.js
new file mode 100755
index 0000000000..434f05b2bb
--- /dev/null
+++ b/util/gradientgen/gradientgen.js
@@ -0,0 +1,133 @@
+#! /usr/bin/env node
+
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the utils of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+const _ = require('lodash');
+const fs = require('fs');
+
+const postcss = require('postcss');
+const minifyGradients = require('postcss-minify-gradients');
+const valueParser = require('postcss-value-parser');
+const parseColor = require('parse-color');
+const math = require('mathjs');
+
+const argc = process.argv.length;
+if (argc < 3) {
+ console.log("usage: gradientgen [mode] <filename>");
+ process.exit(1);
+}
+
+const filename = process.argv[argc - 1];
+const mode = argc > 3 ? process.argv[argc - 2] : 'json';
+
+fs.readFile(filename, (err, css) => {
+ postcss([minifyGradients]).process(css)
+ .then(result => {
+ let enums = [];
+ let gradients = [];
+
+ result.root.walkRules(rule => {
+ gradients.push(null); // Placeholder
+
+ const name = _.startCase(rule.selector).replace(/\s/g, '');
+ if (enums.indexOf(name) >= 0)
+ return; // Duplicate entry
+
+ // We can only support single gradient declarations
+ if (rule.nodes.length > 1)
+ return;
+
+ valueParser(rule.nodes[0].value).walk(node => {
+ if (node.type !== 'function')
+ return;
+
+ if (node.value !== 'linear-gradient')
+ return;
+
+ const args = node.nodes.reduce((args, arg) => {
+ if (arg.type === 'div')
+ args.push([]);
+ else if (arg.type !== 'space')
+ args[args.length - 1].push(arg.value);
+ return args;
+ }, [[]]);
+
+ let angle = valueParser.unit(args[0][0]);
+ if (angle.unit !== 'deg')
+ return;
+
+ angle = parseInt(angle.number);
+ if (angle < 0)
+ angle += 360;
+
+ // Angle is in degrees, but we need radians
+ const radians = angle * math.pi / 180;
+
+ const gradientLine = (math.abs(math.sin(radians)) + math.abs(math.cos(radians)));
+ const cathetus = fn => math.round(fn(radians - math.pi / 2) * gradientLine / 2, 10);
+
+ const x = cathetus(math.cos);
+ const y = cathetus(math.sin);
+
+ const start = { x: 0.5 - x, y: 0.5 - y };
+ const end = { x: 0.5 + x, y: 0.5 + y };
+
+ let stops = []
+
+ let lastPosition = 0;
+ args.slice(1).forEach((arg, index) => {
+ let [color, position = !index ? '0%' : '100%'] = arg;
+ position = parseInt(position) / 100;
+ if (position < lastPosition)
+ position = lastPosition;
+ lastPosition = position;
+ color = parseColor(color).hex;
+ color = parseInt(color.slice(1), 16)
+ stops.push({ color, position })
+ });
+
+ gradients[gradients.length - 1] = { start, end, stops };
+ });
+
+ if (!gradients[gradients.length - 1])
+ return; // Not supported
+
+ enums.push(name);
+
+ if (mode == 'debug')
+ console.log(name, args, gradients[gradients.length - 1])
+ else if (mode == 'enums')
+ console.log(`${name} = ${gradients.length},`)
+ });
+
+ // Done walking declarations
+ if (mode == 'json')
+ console.log(JSON.stringify(gradients, undefined, 4));
+ });
+});
diff --git a/util/gradientgen/package-lock.json b/util/gradientgen/package-lock.json
new file mode 100644
index 0000000000..77939b7fe3
--- /dev/null
+++ b/util/gradientgen/package-lock.json
@@ -0,0 +1,183 @@
+{
+ "name": "gradientgen",
+ "version": "0.0.1",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+ },
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "requires": {
+ "ansi-styles": "2.2.1",
+ "escape-string-regexp": "1.0.5",
+ "has-ansi": "2.0.0",
+ "strip-ansi": "3.0.1",
+ "supports-color": "2.0.0"
+ },
+ "dependencies": {
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
+ }
+ }
+ },
+ "complex.js": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.0.4.tgz",
+ "integrity": "sha512-Syl95HpxUTS0QjwNxencZsKukgh1zdS9uXeXX2Us0pHaqBR6kiZZi0AkZ9VpZFwHJyVIUVzI4EumjWdXP3fy6w=="
+ },
+ "decimal.js": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-9.0.1.tgz",
+ "integrity": "sha512-2h0iKbJwnImBk4TGk7CG1xadoA0g3LDPlQhQzbZ221zvG0p2YVUedbKIPsOZXKZGx6YmZMJKYOalpCMxSdDqTQ=="
+ },
+ "escape-latex": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.0.3.tgz",
+ "integrity": "sha512-GfKaG/7FOKdIdciylIzgaShBTPjdGQ5LJ2EcKLKXPLpcMO1MvCEVotkhydEShwCINRacZr2r3fk5A1PwZ4e5sA=="
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
+ },
+ "fraction.js": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.0.4.tgz",
+ "integrity": "sha512-aK/oGatyYLTtXRHjfEsytX5fieeR5H4s8sLorzcT12taFS+dbMZejnvm9gRa8mZAPwci24ucjq9epDyaq5u8Iw=="
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "requires": {
+ "ansi-regex": "2.1.1"
+ }
+ },
+ "has-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
+ "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo="
+ },
+ "javascript-natural-sort": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz",
+ "integrity": "sha1-+eIwPUUH9tdDVac2ZNFED7Wg71k="
+ },
+ "js-base64": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.3.tgz",
+ "integrity": "sha512-H7ErYLM34CvDMto3GbD6xD0JLUGYXR3QTcH6B/tr4Hi/QpSThnCsIp+Sy5FRTw3B0d6py4HcNkW7nO/wdtGWEw=="
+ },
+ "lodash": {
+ "version": "4.17.10",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
+ "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg=="
+ },
+ "mathjs": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-4.2.2.tgz",
+ "integrity": "sha512-AKrRfTeGrCBqYN1TYEpLIwrfZh9rKu9lH4n7K0MwTiYqN5crJ7BKh/TnErFvbUmyRVQDv87UjSfNTqeO0JA0JQ==",
+ "requires": {
+ "complex.js": "2.0.4",
+ "decimal.js": "9.0.1",
+ "escape-latex": "1.0.3",
+ "fraction.js": "4.0.4",
+ "javascript-natural-sort": "0.7.1",
+ "seed-random": "2.2.0",
+ "tiny-emitter": "2.0.2",
+ "typed-function": "1.0.3"
+ }
+ },
+ "parse-color": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/parse-color/-/parse-color-1.0.0.tgz",
+ "integrity": "sha1-e3SLlag/A/FqlPU15S1/PZRlhhk=",
+ "requires": {
+ "color-convert": "0.5.3"
+ },
+ "dependencies": {
+ "color-convert": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz",
+ "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0="
+ }
+ }
+ },
+ "postcss": {
+ "version": "5.2.18",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
+ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
+ "requires": {
+ "chalk": "1.1.3",
+ "js-base64": "2.4.3",
+ "source-map": "0.5.7",
+ "supports-color": "3.2.3"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
+ }
+ }
+ },
+ "postcss-minify-gradients": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz",
+ "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=",
+ "requires": {
+ "postcss": "5.2.18",
+ "postcss-value-parser": "3.3.0"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz",
+ "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU="
+ },
+ "seed-random": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/seed-random/-/seed-random-2.2.0.tgz",
+ "integrity": "sha1-KpsZ4lCoFwmSMaW5mk2vgLf77VQ="
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "requires": {
+ "ansi-regex": "2.1.1"
+ }
+ },
+ "supports-color": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
+ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
+ "requires": {
+ "has-flag": "1.0.0"
+ }
+ },
+ "tiny-emitter": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.0.2.tgz",
+ "integrity": "sha512-2NM0auVBGft5tee/OxP4PI3d8WItkDM+fPnaRAVo6xTDI2knbz9eC5ArWGqtGlYqiH3RU5yMpdyTTO7MguC4ow=="
+ },
+ "typed-function": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/typed-function/-/typed-function-1.0.3.tgz",
+ "integrity": "sha512-sVC/1pm70oELDFMdYtFXMFqyawenLoaDiAXA3QvOAwKF/WvFNTSJN23cY2lFNL8iP0kh3T0PPKewrboO8XUVGQ=="
+ }
+ }
+}
diff --git a/util/gradientgen/package.json b/util/gradientgen/package.json
new file mode 100644
index 0000000000..35c324b8cc
--- /dev/null
+++ b/util/gradientgen/package.json
@@ -0,0 +1,13 @@
+{
+ "name": "gradientgen",
+ "version": "0.0.1",
+ "description": "Generates gradient presets for QGradient",
+ "main": "gradientgen.js",
+ "dependencies": {
+ "lodash": "^4.17.10",
+ "mathjs": "^4.2.2",
+ "parse-color": "^1.0.0",
+ "postcss-minify-gradients": "^1.0.5",
+ "postcss-value-parser": "^3.3.0"
+ }
+}
diff --git a/util/gradientgen/tobinaryjson.cpp b/util/gradientgen/tobinaryjson.cpp
new file mode 100644
index 0000000000..65fe07f4b8
--- /dev/null
+++ b/util/gradientgen/tobinaryjson.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the utils of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <iostream>
+
+#include <qdebug.h>
+#include <qjsondocument.h>
+
+using namespace std;
+
+int main()
+{
+ QByteArray json;
+ while (!cin.eof()) {
+ char arr[1024];
+ cin.read(arr, sizeof(arr));
+ json.append(arr, cin.gcount());
+ }
+
+ QJsonParseError error;
+ QJsonDocument document = QJsonDocument::fromJson(json, &error);
+ if (document.isNull()) {
+ qDebug() << "error:" << qPrintable(error.errorString()) << "at offset" << error.offset;
+ return 1;
+ }
+
+ QByteArray binaryJson = document.toBinaryData();
+ cout.write(binaryJson.constData(), binaryJson.size());
+}
diff --git a/util/gradientgen/tobinaryjson.pro b/util/gradientgen/tobinaryjson.pro
new file mode 100644
index 0000000000..8ed3509278
--- /dev/null
+++ b/util/gradientgen/tobinaryjson.pro
@@ -0,0 +1,4 @@
+SOURCES += tobinaryjson.cpp
+QT = core
+CONFIG += console
+CONFIG -= app_bundle
diff --git a/util/local_database/cldr2qlocalexml.py b/util/local_database/cldr2qlocalexml.py
index 58ea21edab..ce45f631a6 100755
--- a/util/local_database/cldr2qlocalexml.py
+++ b/util/local_database/cldr2qlocalexml.py
@@ -37,6 +37,14 @@ pass the path of that sub-directory to this script as its single
command-line argument. Save its standard output (but not error) to a
file for later processing by ``./qlocalexml2cpp.py``
+When you update the CLDR data, be sure to also update
+src/corelib/tools/qt_attribution.json's entry for unicode-cldr. Check
+this script's output for unknown language, country or script messages;
+if any can be resolved, use their entry in common/main/en.xml to
+append new entries to enumdata.py's lists and update documentation in
+src/corelib/tools/qlocale.qdoc, adding the new entries in alphabetic
+order.
+
.. _CLDR: ftp://unicode.org/Public/cldr/
"""
@@ -142,6 +150,28 @@ def generateLocaleInfo(path):
return _generateLocaleInfo(path, code('language'), code('script'),
code('territory'), code('variant'))
+def getNumberSystems(cache={}):
+ """Cached look-up of number system information.
+
+ Pass no arguments. Returns a mapping from number system names to,
+ for each system, a mapping with keys u'digits', u'type' and
+ u'id'\n"""
+ if not cache:
+ for ns in findTagsInFile(os.path.join(cldr_dir, '..', 'supplemental',
+ 'numberingSystems.xml'),
+ 'numberingSystems'):
+ # ns has form: [u'numberingSystem', [(u'digits', u'0123456789'), (u'type', u'numeric'), (u'id', u'latn')]]
+ entry = dict(ns[1])
+ name = entry[u'id']
+ if u'digits' in entry and ord(entry[u'digits'][0]) > 0xffff:
+ # FIXME: make this redundant:
+ # omit number system if zero doesn't fit in single-char16 UTF-16 :-(
+ sys.stderr.write('skipping number system "%s" [can\'t represent its zero, U+%X, QTBUG-69324]\n'
+ % (name, ord(entry[u'digits'][0])))
+ else:
+ cache[name] = entry
+ return cache
+
def _generateLocaleInfo(path, language_code, script_code, country_code, variant_code=""):
if not path.endswith(".xml"):
return {}
@@ -239,20 +269,9 @@ def _generateLocaleInfo(path, language_code, script_code, country_code, variant_
result['list'] = get_number_in_system(path, "numbers/symbols/list", numbering_system)
result['percent'] = get_number_in_system(path, "numbers/symbols/percentSign", numbering_system)
try:
- numbering_systems = {}
- for ns in findTagsInFile(os.path.join(cldr_dir, '..', 'supplemental',
- 'numberingSystems.xml'),
- 'numberingSystems'):
- tmp = {}
- id = ""
- for data in ns[1:][0]: # ns looks like this: [u'numberingSystem', [(u'digits', u'0123456789'), (u'type', u'numeric'), (u'id', u'latn')]]
- tmp[data[0]] = data[1]
- if data[0] == u"id":
- id = data[1]
- numbering_systems[id] = tmp
- result['zero'] = numbering_systems[numbering_system][u"digits"][0]
- except e:
- sys.stderr.write("Native zero detection problem:\n" + str(e) + "\n")
+ result['zero'] = getNumberSystems()[numbering_system][u"digits"][0]
+ except Exception as e:
+ sys.stderr.write("Native zero detection problem: %s\n" % repr(e))
result['zero'] = get_number_in_system(path, "numbers/symbols/nativeZeroDigit", numbering_system)
result['minus'] = get_number_in_system(path, "numbers/symbols/minusSign", numbering_system)
result['plus'] = get_number_in_system(path, "numbers/symbols/plusSign", numbering_system)
diff --git a/util/local_database/enumdata.py b/util/local_database/enumdata.py
index 2d16e5851d..e24ac02b07 100644
--- a/util/local_database/enumdata.py
+++ b/util/local_database/enumdata.py
@@ -27,779 +27,825 @@
##
#############################################################################
-# language_list and country_list reflect the current values of enums in qlocale.h
-# If new xml language files are available in CLDR, these languages and countries
-# need to be *appended* to this list.
+# Each *_list reflects the current values of its enums in qlocale.h;
+# if new xml language files are available in CLDR, these languages and
+# countries need to be *appended* to this list (for compatibility
+# between versions). Include any spaces present in names (scripts
+# shall squish them out for the enum entries) in *_list, but use the
+# squished forms of names in the *_aliases mappings.
+
+### Qt 6: restore alphabetic order in each list.
language_list = {
- 0 : [ "AnyLanguage", " " ],
- 1 : [ "C", " " ],
- 2 : [ "Abkhazian", "ab" ],
- 3 : [ "Oromo", "om" ], # macrolanguage
- 4 : [ "Afar", "aa" ],
- 5 : [ "Afrikaans", "af" ],
- 6 : [ "Albanian", "sq" ], # macrolanguage
- 7 : [ "Amharic", "am" ],
- 8 : [ "Arabic", "ar" ], # macrolanguage
- 9 : [ "Armenian", "hy" ],
- 10 : [ "Assamese", "as" ],
- 11 : [ "Aymara", "ay" ], # macrolanguage
- 12 : [ "Azerbaijani", "az" ], # macrolanguage
- 13 : [ "Bashkir", "ba" ],
- 14 : [ "Basque", "eu" ],
- 15 : [ "Bengali", "bn" ],
- 16 : [ "Dzongkha", "dz" ],
- 17 : [ "Bihari", "bh" ],
- 18 : [ "Bislama", "bi" ],
- 19 : [ "Breton", "br" ],
- 20 : [ "Bulgarian", "bg" ],
- 21 : [ "Burmese", "my" ],
- 22 : [ "Belarusian", "be" ],
- 23 : [ "Khmer", "km" ],
- 24 : [ "Catalan", "ca" ],
- 25 : [ "Chinese", "zh" ], # macrolanguage
- 26 : [ "Corsican", "co" ],
- 27 : [ "Croatian", "hr" ],
- 28 : [ "Czech", "cs" ],
- 29 : [ "Danish", "da" ],
- 30 : [ "Dutch", "nl" ],
- 31 : [ "English", "en" ],
- 32 : [ "Esperanto", "eo" ],
- 33 : [ "Estonian", "et" ], # macrolanguage
- 34 : [ "Faroese", "fo" ],
- 35 : [ "Fijian", "fj" ],
- 36 : [ "Finnish", "fi" ],
- 37 : [ "French", "fr" ],
- 38 : [ "Western Frisian", "fy" ],
- 39 : [ "Gaelic", "gd" ],
- 40 : [ "Galician", "gl" ],
- 41 : [ "Georgian", "ka" ],
- 42 : [ "German", "de" ],
- 43 : [ "Greek", "el" ],
- 44 : [ "Greenlandic", "kl" ],
- 45 : [ "Guarani", "gn" ], # macrolanguage
- 46 : [ "Gujarati", "gu" ],
- 47 : [ "Hausa", "ha" ],
- 48 : [ "Hebrew", "he" ],
- 49 : [ "Hindi", "hi" ],
- 50 : [ "Hungarian", "hu" ],
- 51 : [ "Icelandic", "is" ],
- 52 : [ "Indonesian", "id" ],
- 53 : [ "Interlingua", "ia" ],
- 54 : [ "Interlingue", "ie" ],
- 55 : [ "Inuktitut", "iu" ], # macrolanguage
- 56 : [ "Inupiak", "ik" ], # macrolanguage
- 57 : [ "Irish", "ga" ],
- 58 : [ "Italian", "it" ],
- 59 : [ "Japanese", "ja" ],
- 60 : [ "Javanese", "jv" ],
- 61 : [ "Kannada", "kn" ],
- 62 : [ "Kashmiri", "ks" ],
- 63 : [ "Kazakh", "kk" ],
- 64 : [ "Kinyarwanda", "rw" ],
- 65 : [ "Kirghiz", "ky" ],
- 66 : [ "Korean", "ko" ],
- 67 : [ "Kurdish", "ku" ], # macrolanguage
- 68 : [ "Rundi", "rn" ],
- 69 : [ "Lao", "lo" ],
- 70 : [ "Latin", "la" ],
- 71 : [ "Latvian", "lv" ], # macrolanguage
- 72 : [ "Lingala", "ln" ],
- 73 : [ "Lithuanian", "lt" ],
- 74 : [ "Macedonian", "mk" ],
- 75 : [ "Malagasy", "mg" ], # macrolanguage
- 76 : [ "Malay", "ms" ], # macrolanguage
- 77 : [ "Malayalam", "ml" ],
- 78 : [ "Maltese", "mt" ],
- 79 : [ "Maori", "mi" ],
- 80 : [ "Marathi", "mr" ],
- 81 : [ "Marshallese", "mh" ],
- 82 : [ "Mongolian", "mn" ], # macrolanguage
- 83 : [ "Nauru", "na" ],
- 84 : [ "Nepali", "ne" ], # macrolanguage
- 85 : [ "NorwegianBokmal", "nb" ],
- 86 : [ "Occitan", "oc" ],
- 87 : [ "Oriya", "or" ], # macrolanguage
- 88 : [ "Pashto", "ps" ], # macrolanguage
- 89 : [ "Persian", "fa" ], # macrolanguage
- 90 : [ "Polish", "pl" ],
- 91 : [ "Portuguese", "pt" ],
- 92 : [ "Punjabi", "pa" ],
- 93 : [ "Quechua", "qu" ], # macrolanguage
- 94 : [ "Romansh", "rm" ],
- 95 : [ "Romanian", "ro" ],
- 96 : [ "Russian", "ru" ],
- 97 : [ "Samoan", "sm" ],
- 98 : [ "Sango", "sg" ],
- 99 : [ "Sanskrit", "sa" ],
- 100 : [ "Serbian", "sr" ],
- 101 : [ "Ossetic", "os" ],
- 102 : [ "Southern Sotho", "st" ],
- 103 : [ "Tswana", "tn" ],
- 104 : [ "Shona", "sn" ],
- 105 : [ "Sindhi", "sd" ],
- 106 : [ "Sinhala", "si" ],
- 107 : [ "Swati", "ss" ],
- 108 : [ "Slovak", "sk" ],
- 109 : [ "Slovenian", "sl" ],
- 110 : [ "Somali", "so" ],
- 111 : [ "Spanish", "es" ],
- 112 : [ "Sundanese", "su" ],
- 113 : [ "Swahili", "sw" ], # macrolanguage
- 114 : [ "Swedish", "sv" ],
- 115 : [ "Sardinian", "sc" ], # macrolanguage
- 116 : [ "Tajik", "tg" ],
- 117 : [ "Tamil", "ta" ],
- 118 : [ "Tatar", "tt" ],
- 119 : [ "Telugu", "te" ],
- 120 : [ "Thai", "th" ],
- 121 : [ "Tibetan", "bo" ],
- 122 : [ "Tigrinya", "ti" ],
- 123 : [ "Tongan", "to" ],
- 124 : [ "Tsonga", "ts" ],
- 125 : [ "Turkish", "tr" ],
- 126 : [ "Turkmen", "tk" ],
- 127 : [ "Tahitian", "ty" ],
- 128 : [ "Uighur", "ug" ],
- 129 : [ "Ukrainian", "uk" ],
- 130 : [ "Urdu", "ur" ],
- 131 : [ "Uzbek", "uz" ], # macrolanguage
- 132 : [ "Vietnamese", "vi" ],
- 133 : [ "Volapuk", "vo" ],
- 134 : [ "Welsh", "cy" ],
- 135 : [ "Wolof", "wo" ],
- 136 : [ "Xhosa", "xh" ],
- 137 : [ "Yiddish", "yi" ], # macrolanguage
- 138 : [ "Yoruba", "yo" ],
- 139 : [ "Zhuang", "za" ], # macrolanguage
- 140 : [ "Zulu", "zu" ],
- 141 : [ "NorwegianNynorsk", "nn" ],
- 142 : [ "Bosnian", "bs" ],
- 143 : [ "Divehi", "dv" ],
- 144 : [ "Manx", "gv" ],
- 145 : [ "Cornish", "kw" ],
- 146 : [ "Akan", "ak" ], # macrolanguage
- 147 : [ "Konkani", "kok" ],
- 148 : [ "Ga", "gaa" ],
- 149 : [ "Igbo", "ig" ],
- 150 : [ "Kamba", "kam" ],
- 151 : [ "Syriac", "syr" ],
- 152 : [ "Blin", "byn" ],
- 153 : [ "Geez", "gez" ],
- 154 : [ "Koro", "kfo" ],
- 155 : [ "Sidamo", "sid" ],
- 156 : [ "Atsam", "cch" ],
- 157 : [ "Tigre", "tig" ],
- 158 : [ "Jju", "kaj" ],
- 159 : [ "Friulian", "fur" ],
- 160 : [ "Venda", "ve" ],
- 161 : [ "Ewe", "ee" ],
- 162 : [ "Walamo", "wal" ],
- 163 : [ "Hawaiian", "haw" ],
- 164 : [ "Tyap", "kcg" ],
- 165 : [ "Nyanja", "ny" ],
- 166 : [ "Filipino", "fil" ],
- 167 : [ "Swiss German", "gsw" ],
- 168 : [ "Sichuan Yi", "ii" ],
- 169 : [ "Kpelle", "kpe" ],
- 170 : [ "Low German", "nds" ],
- 171 : [ "South Ndebele", "nr" ],
- 172 : [ "Northern Sotho", "nso" ],
- 173 : [ "Northern Sami", "se" ],
- 174 : [ "Taroko", "trv" ],
- 175 : [ "Gusii", "guz" ],
- 176 : [ "Taita", "dav" ],
- 177 : [ "Fulah", "ff" ], # macrolanguage
- 178 : [ "Kikuyu", "ki" ],
- 179 : [ "Samburu", "saq" ],
- 180 : [ "Sena", "seh" ],
- 181 : [ "North Ndebele", "nd" ],
- 182 : [ "Rombo", "rof" ],
- 183 : [ "Tachelhit", "shi" ],
- 184 : [ "Kabyle", "kab" ],
- 185 : [ "Nyankole", "nyn" ],
- 186 : [ "Bena", "bez" ],
- 187 : [ "Vunjo", "vun" ],
- 188 : [ "Bambara", "bm" ],
- 189 : [ "Embu", "ebu" ],
- 190 : [ "Cherokee", "chr" ],
- 191 : [ "Morisyen", "mfe" ],
- 192 : [ "Makonde", "kde" ],
- 193 : [ "Langi", "lag" ],
- 194 : [ "Ganda", "lg" ],
- 195 : [ "Bemba", "bem" ],
- 196 : [ "Kabuverdianu", "kea" ],
- 197 : [ "Meru", "mer" ],
- 198 : [ "Kalenjin", "kln" ],
- 199 : [ "Nama", "naq" ],
- 200 : [ "Machame", "jmc" ],
- 201 : [ "Colognian", "ksh" ],
- 202 : [ "Masai", "mas" ],
- 203 : [ "Soga", "xog" ],
- 204 : [ "Luyia", "luy" ],
- 205 : [ "Asu", "asa" ],
- 206 : [ "Teso", "teo" ],
- 207 : [ "Saho", "ssy" ],
- 208 : [ "Koyra Chiini", "khq" ],
- 209 : [ "Rwa", "rwk" ],
- 210 : [ "Luo", "luo" ],
- 211 : [ "Chiga", "cgg" ],
- 212 : [ "Central Morocco Tamazight", "tzm" ],
- 213 : [ "Koyraboro Senni", "ses" ],
- 214 : [ "Shambala", "ksb" ],
- 215 : [ "Bodo", "brx" ],
- 216 : [ "Avaric", "av" ],
- 217 : [ "Chamorro", "ch" ],
- 218 : [ "Chechen", "ce" ],
- 219 : [ "Church", "cu" ], # macrolanguage
- 220 : [ "Chuvash", "cv" ],
- 221 : [ "Cree", "cr" ], # macrolanguage
- 222 : [ "Haitian", "ht" ],
- 223 : [ "Herero", "hz" ],
- 224 : [ "Hiri Motu", "ho" ],
- 225 : [ "Kanuri", "kr" ], # macrolanguage
- 226 : [ "Komi", "kv" ], # macrolanguage
- 227 : [ "Kongo", "kg" ], # macrolanguage
- 228 : [ "Kwanyama", "kj" ],
- 229 : [ "Limburgish", "li" ],
- 230 : [ "LubaKatanga", "lu" ],
- 231 : [ "Luxembourgish", "lb" ],
- 232 : [ "Navaho", "nv" ],
- 233 : [ "Ndonga", "ng" ],
- 234 : [ "Ojibwa", "oj" ], # macrolanguage
- 235 : [ "Pali", "pi" ], # macrolanguage
- 236 : [ "Walloon", "wa" ],
- 237 : [ "Aghem", "agq" ],
- 238 : [ "Basaa", "bas" ],
- 239 : [ "Zarma", "dje" ],
- 240 : [ "Duala", "dua" ],
- 241 : [ "JolaFonyi", "dyo" ],
- 242 : [ "Ewondo", "ewo" ],
- 243 : [ "Bafia", "ksf" ],
- 244 : [ "MakhuwaMeetto", "mgh" ],
- 245 : [ "Mundang", "mua" ],
- 246 : [ "Kwasio", "nmg" ],
- 247 : [ "Nuer", "nus" ],
- 248 : [ "Sakha", "sah" ],
- 249 : [ "Sangu", "sbp" ],
- 250 : [ "Congo Swahili", "swc" ],
- 251 : [ "Tasawaq", "twq" ],
- 252 : [ "Vai", "vai" ],
- 253 : [ "Walser", "wae" ],
- 254 : [ "Yangben", "yav" ],
- 255 : [ "Avestan", "ae" ],
- 256 : [ "Asturian", "ast" ],
- 257 : [ "Ngomba", "jgo" ],
- 258 : [ "Kako", "kkj" ],
- 259 : [ "Meta", "mgo" ],
- 260 : [ "Ngiemboon", "nnh" ],
- 261 : [ "Aragonese", "an" ],
- 262 : [ "Akkadian", "akk" ],
- 263 : [ "AncientEgyptian", "egy" ],
- 264 : [ "AncientGreek", "grc" ],
- 265 : [ "Aramaic", "arc" ],
- 266 : [ "Balinese", "ban" ],
- 267 : [ "Bamun", "bax" ],
- 268 : [ "BatakToba", "bbc" ],
- 269 : [ "Buginese", "bug" ],
- 270 : [ "Buhid", "bku" ],
- 271 : [ "Carian", "xcr" ],
- 272 : [ "Chakma", "ccp" ],
- 273 : [ "ClassicalMandaic", "myz" ],
- 274 : [ "Coptic", "cop" ],
- 275 : [ "Dogri", "doi" ], # macrolanguage
- 276 : [ "EasternCham", "cjm" ],
- 277 : [ "EasternKayah", "eky" ],
- 278 : [ "Etruscan", "ett" ],
- 279 : [ "Gothic", "got" ],
- 280 : [ "Hanunoo", "hnn" ],
- 281 : [ "Ingush", "inh" ],
- 282 : [ "LargeFloweryMiao", "hmd" ],
- 283 : [ "Lepcha", "lep" ],
- 284 : [ "Limbu", "lif" ],
- 285 : [ "Lisu", "lis" ],
- 286 : [ "Lu", "khb" ],
- 287 : [ "Lycian", "xlc" ],
- 288 : [ "Lydian", "xld" ],
- 289 : [ "Mandingo", "man" ], # macrolanguage
- 290 : [ "Manipuri", "mni" ],
- 291 : [ "Meroitic", "xmr" ],
- 292 : [ "NorthernThai", "nod" ],
- 293 : [ "OldIrish", "sga" ],
- 294 : [ "OldNorse", "non" ],
- 295 : [ "OldPersian", "peo" ],
- 296 : [ "OldTurkish", "otk" ],
- 297 : [ "Pahlavi", "pal" ],
- 298 : [ "Parthian", "xpr" ],
- 299 : [ "Phoenician", "phn" ],
- 300 : [ "PrakritLanguage", "pra" ],
- 301 : [ "Rejang", "rej" ],
- 302 : [ "Sabaean", "xsa" ],
- 303 : [ "Samaritan", "smp" ],
- 304 : [ "Santali", "sat" ],
- 305 : [ "Saurashtra", "saz" ],
- 306 : [ "Sora", "srb" ],
- 307 : [ "Sylheti", "syl" ],
- 308 : [ "Tagbanwa", "tbw" ],
- 309 : [ "TaiDam", "blt" ],
- 310 : [ "TaiNua", "tdd" ],
- 311 : [ "Ugaritic", "uga" ],
- 312 : [ "Akoose", "bss" ],
- 313 : [ "Lakota", "lkt" ],
- 314 : [ "Standard Moroccan Tamazight", "zgh" ],
- 315 : [ "Mapuche", "arn" ],
- 316 : [ "Central Kurdish", "ckb" ],
- 317 : [ "LowerSorbian", "dsb" ],
- 318 : [ "UpperSorbian", "hsb" ],
- 319 : [ "Kenyang", "ken" ],
- 320 : [ "Mohawk", "moh" ],
- 321 : [ "Nko", "nqo" ],
- 322 : [ "Prussian", "prg" ],
- 323 : [ "Kiche", "quc" ],
- 324 : [ "Southern Sami", "sma" ],
- 325 : [ "Lule Sami", "smj" ],
- 326 : [ "Inari Sami", "smn" ],
- 327 : [ "Skolt Sami", "sms" ],
- 328 : [ "Warlpiri", "wbp" ],
- 329 : [ "Manichaean Middle Persian", "xmn" ],
- 330 : [ "Mende", "men" ],
- 331 : [ "Ancient North Arabian", "xna" ],
- 332 : [ "Linear A", "lab" ],
- 333 : [ "Hmong Njua", "hnj" ],
- 334 : [ "Ho", "hoc" ],
- 335 : [ "Lezghian", "lez" ],
- 336 : [ "Bassa", "bsq" ],
- 337 : [ "Mono", "mru" ],
- 338 : [ "Tedim Chin", "ctd" ],
- 339 : [ "Maithili", "mai" ],
- 340 : [ "Ahom", "aho" ],
- 341 : [ "American Sign Language", "ase" ],
- 342 : [ "Ardhamagadhi Prakrit", "pka" ],
- 343 : [ "Bhojpuri", "bho" ],
- 344 : [ "Hieroglyphic Luwian", "hlu" ],
- 345 : [ "Literary Chinese", "lzh" ],
- 346 : [ "Mazanderani", "mzn" ],
- 347 : [ "Mru", "mro" ],
- 348 : [ "Newari", "new" ],
- 349 : [ "Northern Luri", "lrc" ],
- 350 : [ "Palauan", "pau" ],
- 351 : [ "Papiamento", "pap" ],
- 352 : [ "Saraiki", "skr" ],
- 353 : [ "Tokelau", "tkl" ],
- 354 : [ "Tok Pisin", "tpi" ],
- 355 : [ "Tuvalu", "tvl" ],
- 356 : [ "UncodedLanguages", "mis" ],
- 357 : [ "Cantonese", "yue" ],
- 358 : [ "Osage", "osa" ],
- 359 : [ "Tangut", "txg" ]
+ 0 : ["AnyLanguage", " "],
+ 1 : ["C", " "],
+ 2 : ["Abkhazian", "ab"],
+ 3 : ["Oromo", "om"], # macrolanguage
+ 4 : ["Afar", "aa"],
+ 5 : ["Afrikaans", "af"],
+ 6 : ["Albanian", "sq"], # macrolanguage
+ 7 : ["Amharic", "am"],
+ 8 : ["Arabic", "ar"], # macrolanguage
+ 9 : ["Armenian", "hy"],
+ 10 : ["Assamese", "as"],
+ 11 : ["Aymara", "ay"], # macrolanguage
+ 12 : ["Azerbaijani", "az"], # macrolanguage
+ 13 : ["Bashkir", "ba"],
+ 14 : ["Basque", "eu"],
+ 15 : ["Bengali", "bn"],
+ 16 : ["Dzongkha", "dz"],
+ 17 : ["Bihari", "bh"],
+ 18 : ["Bislama", "bi"],
+ 19 : ["Breton", "br"],
+ 20 : ["Bulgarian", "bg"],
+ 21 : ["Burmese", "my"],
+ 22 : ["Belarusian", "be"],
+ 23 : ["Khmer", "km"],
+ 24 : ["Catalan", "ca"],
+ 25 : ["Chinese", "zh"], # macrolanguage
+ 26 : ["Corsican", "co"],
+ 27 : ["Croatian", "hr"],
+ 28 : ["Czech", "cs"],
+ 29 : ["Danish", "da"],
+ 30 : ["Dutch", "nl"],
+ 31 : ["English", "en"],
+ 32 : ["Esperanto", "eo"],
+ 33 : ["Estonian", "et"], # macrolanguage
+ 34 : ["Faroese", "fo"],
+ 35 : ["Fijian", "fj"],
+ 36 : ["Finnish", "fi"],
+ 37 : ["French", "fr"],
+ 38 : ["Western Frisian", "fy"],
+ 39 : ["Gaelic", "gd"],
+ 40 : ["Galician", "gl"],
+ 41 : ["Georgian", "ka"],
+ 42 : ["German", "de"],
+ 43 : ["Greek", "el"],
+ 44 : ["Greenlandic", "kl"],
+ 45 : ["Guarani", "gn"], # macrolanguage
+ 46 : ["Gujarati", "gu"],
+ 47 : ["Hausa", "ha"],
+ 48 : ["Hebrew", "he"],
+ 49 : ["Hindi", "hi"],
+ 50 : ["Hungarian", "hu"],
+ 51 : ["Icelandic", "is"],
+ 52 : ["Indonesian", "id"],
+ 53 : ["Interlingua", "ia"],
+ 54 : ["Interlingue", "ie"],
+ 55 : ["Inuktitut", "iu"], # macrolanguage
+ 56 : ["Inupiak", "ik"], # macrolanguage
+ 57 : ["Irish", "ga"],
+ 58 : ["Italian", "it"],
+ 59 : ["Japanese", "ja"],
+ 60 : ["Javanese", "jv"],
+ 61 : ["Kannada", "kn"],
+ 62 : ["Kashmiri", "ks"],
+ 63 : ["Kazakh", "kk"],
+ 64 : ["Kinyarwanda", "rw"],
+ 65 : ["Kirghiz", "ky"],
+ 66 : ["Korean", "ko"],
+ 67 : ["Kurdish", "ku"], # macrolanguage
+ 68 : ["Rundi", "rn"],
+ 69 : ["Lao", "lo"],
+ 70 : ["Latin", "la"],
+ 71 : ["Latvian", "lv"], # macrolanguage
+ 72 : ["Lingala", "ln"],
+ 73 : ["Lithuanian", "lt"],
+ 74 : ["Macedonian", "mk"],
+ 75 : ["Malagasy", "mg"], # macrolanguage
+ 76 : ["Malay", "ms"], # macrolanguage
+ 77 : ["Malayalam", "ml"],
+ 78 : ["Maltese", "mt"],
+ 79 : ["Maori", "mi"],
+ 80 : ["Marathi", "mr"],
+ 81 : ["Marshallese", "mh"],
+ 82 : ["Mongolian", "mn"], # macrolanguage
+ 83 : ["Nauru", "na"],
+ 84 : ["Nepali", "ne"], # macrolanguage
+ 85 : ["Norwegian Bokmal", "nb"],
+ 86 : ["Occitan", "oc"],
+ 87 : ["Oriya", "or"], # macrolanguage
+ 88 : ["Pashto", "ps"], # macrolanguage
+ 89 : ["Persian", "fa"], # macrolanguage
+ 90 : ["Polish", "pl"],
+ 91 : ["Portuguese", "pt"],
+ 92 : ["Punjabi", "pa"],
+ 93 : ["Quechua", "qu"], # macrolanguage
+ 94 : ["Romansh", "rm"],
+ 95 : ["Romanian", "ro"],
+ 96 : ["Russian", "ru"],
+ 97 : ["Samoan", "sm"],
+ 98 : ["Sango", "sg"],
+ 99 : ["Sanskrit", "sa"],
+ 100 : ["Serbian", "sr"],
+ 101 : ["Ossetic", "os"],
+ 102 : ["Southern Sotho", "st"],
+ 103 : ["Tswana", "tn"],
+ 104 : ["Shona", "sn"],
+ 105 : ["Sindhi", "sd"],
+ 106 : ["Sinhala", "si"],
+ 107 : ["Swati", "ss"],
+ 108 : ["Slovak", "sk"],
+ 109 : ["Slovenian", "sl"],
+ 110 : ["Somali", "so"],
+ 111 : ["Spanish", "es"],
+ 112 : ["Sundanese", "su"],
+ 113 : ["Swahili", "sw"], # macrolanguage
+ 114 : ["Swedish", "sv"],
+ 115 : ["Sardinian", "sc"], # macrolanguage
+ 116 : ["Tajik", "tg"],
+ 117 : ["Tamil", "ta"],
+ 118 : ["Tatar", "tt"],
+ 119 : ["Telugu", "te"],
+ 120 : ["Thai", "th"],
+ 121 : ["Tibetan", "bo"],
+ 122 : ["Tigrinya", "ti"],
+ 123 : ["Tongan", "to"],
+ 124 : ["Tsonga", "ts"],
+ 125 : ["Turkish", "tr"],
+ 126 : ["Turkmen", "tk"],
+ 127 : ["Tahitian", "ty"],
+ 128 : ["Uighur", "ug"],
+ 129 : ["Ukrainian", "uk"],
+ 130 : ["Urdu", "ur"],
+ 131 : ["Uzbek", "uz"], # macrolanguage
+ 132 : ["Vietnamese", "vi"],
+ 133 : ["Volapuk", "vo"],
+ 134 : ["Welsh", "cy"],
+ 135 : ["Wolof", "wo"],
+ 136 : ["Xhosa", "xh"],
+ 137 : ["Yiddish", "yi"], # macrolanguage
+ 138 : ["Yoruba", "yo"],
+ 139 : ["Zhuang", "za"], # macrolanguage
+ 140 : ["Zulu", "zu"],
+ 141 : ["Norwegian Nynorsk", "nn"],
+ 142 : ["Bosnian", "bs"],
+ 143 : ["Divehi", "dv"],
+ 144 : ["Manx", "gv"],
+ 145 : ["Cornish", "kw"],
+ 146 : ["Akan", "ak"], # macrolanguage
+ 147 : ["Konkani", "kok"],
+ 148 : ["Ga", "gaa"],
+ 149 : ["Igbo", "ig" ],
+ 150 : ["Kamba", "kam"],
+ 151 : ["Syriac", "syr"],
+ 152 : ["Blin", "byn"],
+ 153 : ["Geez", "gez"],
+ 154 : ["Koro", "kfo"],
+ 155 : ["Sidamo", "sid"],
+ 156 : ["Atsam", "cch"],
+ 157 : ["Tigre", "tig"],
+ 158 : ["Jju", "kaj"],
+ 159 : ["Friulian", "fur"],
+ 160 : ["Venda", "ve" ],
+ 161 : ["Ewe", "ee" ],
+ 162 : ["Walamo", "wal"],
+ 163 : ["Hawaiian", "haw"],
+ 164 : ["Tyap", "kcg"],
+ 165 : ["Nyanja", "ny" ],
+ 166 : ["Filipino", "fil"],
+ 167 : ["Swiss German", "gsw"],
+ 168 : ["Sichuan Yi", "ii" ],
+ 169 : ["Kpelle", "kpe"],
+ 170 : ["Low German", "nds"],
+ 171 : ["South Ndebele", "nr" ],
+ 172 : ["Northern Sotho", "nso"],
+ 173 : ["Northern Sami", "se" ],
+ 174 : ["Taroko", "trv"],
+ 175 : ["Gusii", "guz"],
+ 176 : ["Taita", "dav"],
+ 177 : ["Fulah", "ff"], # macrolanguage
+ 178 : ["Kikuyu", "ki"],
+ 179 : ["Samburu", "saq"],
+ 180 : ["Sena", "seh"],
+ 181 : ["North Ndebele", "nd"],
+ 182 : ["Rombo", "rof"],
+ 183 : ["Tachelhit", "shi"],
+ 184 : ["Kabyle", "kab"],
+ 185 : ["Nyankole", "nyn"],
+ 186 : ["Bena", "bez"],
+ 187 : ["Vunjo", "vun"],
+ 188 : ["Bambara", "bm"],
+ 189 : ["Embu", "ebu"],
+ 190 : ["Cherokee", "chr"],
+ 191 : ["Morisyen", "mfe"],
+ 192 : ["Makonde", "kde"],
+ 193 : ["Langi", "lag"],
+ 194 : ["Ganda", "lg"],
+ 195 : ["Bemba", "bem"],
+ 196 : ["Kabuverdianu", "kea"],
+ 197 : ["Meru", "mer"],
+ 198 : ["Kalenjin", "kln"],
+ 199 : ["Nama", "naq"],
+ 200 : ["Machame", "jmc"],
+ 201 : ["Colognian", "ksh"],
+ 202 : ["Masai", "mas"],
+ 203 : ["Soga", "xog"],
+ 204 : ["Luyia", "luy"],
+ 205 : ["Asu", "asa"],
+ 206 : ["Teso", "teo"],
+ 207 : ["Saho", "ssy"],
+ 208 : ["Koyra Chiini", "khq"],
+ 209 : ["Rwa", "rwk"],
+ 210 : ["Luo", "luo"],
+ 211 : ["Chiga", "cgg"],
+ 212 : ["Central Morocco Tamazight", "tzm"],
+ 213 : ["Koyraboro Senni", "ses"],
+ 214 : ["Shambala", "ksb"],
+ 215 : ["Bodo", "brx"],
+ 216 : ["Avaric", "av"],
+ 217 : ["Chamorro", "ch"],
+ 218 : ["Chechen", "ce"],
+ 219 : ["Church", "cu"], # macrolanguage
+ 220 : ["Chuvash", "cv"],
+ 221 : ["Cree", "cr"], # macrolanguage
+ 222 : ["Haitian", "ht"],
+ 223 : ["Herero", "hz"],
+ 224 : ["Hiri Motu", "ho"],
+ 225 : ["Kanuri", "kr"], # macrolanguage
+ 226 : ["Komi", "kv"], # macrolanguage
+ 227 : ["Kongo", "kg"], # macrolanguage
+ 228 : ["Kwanyama", "kj"],
+ 229 : ["Limburgish", "li"],
+ 230 : ["Luba Katanga", "lu"],
+ 231 : ["Luxembourgish", "lb"],
+ 232 : ["Navaho", "nv"],
+ 233 : ["Ndonga", "ng"],
+ 234 : ["Ojibwa", "oj"], # macrolanguage
+ 235 : ["Pali", "pi"], # macrolanguage
+ 236 : ["Walloon", "wa"],
+ 237 : ["Aghem", "agq"],
+ 238 : ["Basaa", "bas"],
+ 239 : ["Zarma", "dje"],
+ 240 : ["Duala", "dua"],
+ 241 : ["Jola Fonyi", "dyo"],
+ 242 : ["Ewondo", "ewo"],
+ 243 : ["Bafia", "ksf"],
+ 244 : ["Makhuwa Meetto", "mgh"],
+ 245 : ["Mundang", "mua"],
+ 246 : ["Kwasio", "nmg"],
+ 247 : ["Nuer", "nus"],
+ 248 : ["Sakha", "sah"],
+ 249 : ["Sangu", "sbp"],
+ 250 : ["Congo Swahili", "swc"],
+ 251 : ["Tasawaq", "twq"],
+ 252 : ["Vai", "vai"],
+ 253 : ["Walser", "wae"],
+ 254 : ["Yangben", "yav"],
+ 255 : ["Avestan", "ae"],
+ 256 : ["Asturian", "ast"],
+ 257 : ["Ngomba", "jgo"],
+ 258 : ["Kako", "kkj"],
+ 259 : ["Meta", "mgo"],
+ 260 : ["Ngiemboon", "nnh"],
+ 261 : ["Aragonese", "an"],
+ 262 : ["Akkadian", "akk"],
+ 263 : ["Ancient Egyptian", "egy"],
+ 264 : ["Ancient Greek", "grc"],
+ 265 : ["Aramaic", "arc"],
+ 266 : ["Balinese", "ban"],
+ 267 : ["Bamun", "bax"],
+ 268 : ["Batak Toba", "bbc"],
+ 269 : ["Buginese", "bug"],
+ 270 : ["Buhid", "bku"],
+ 271 : ["Carian", "xcr"],
+ 272 : ["Chakma", "ccp"],
+ 273 : ["Classical Mandaic", "myz"],
+ 274 : ["Coptic", "cop"],
+ 275 : ["Dogri", "doi"], # macrolanguage
+ 276 : ["Eastern Cham", "cjm"],
+ 277 : ["Eastern Kayah", "eky"],
+ 278 : ["Etruscan", "ett"],
+ 279 : ["Gothic", "got"],
+ 280 : ["Hanunoo", "hnn"],
+ 281 : ["Ingush", "inh"],
+ 282 : ["Large Flowery Miao", "hmd"],
+ 283 : ["Lepcha", "lep"],
+ 284 : ["Limbu", "lif"],
+ 285 : ["Lisu", "lis"],
+ 286 : ["Lu", "khb"],
+ 287 : ["Lycian", "xlc"],
+ 288 : ["Lydian", "xld"],
+ 289 : ["Mandingo", "man"], # macrolanguage
+ 290 : ["Manipuri", "mni"],
+ 291 : ["Meroitic", "xmr"],
+ 292 : ["Northern Thai", "nod"],
+ 293 : ["Old Irish", "sga"],
+ 294 : ["Old Norse", "non"],
+ 295 : ["Old Persian", "peo"],
+ 296 : ["Old Turkish", "otk"],
+ 297 : ["Pahlavi", "pal"],
+ 298 : ["Parthian", "xpr"],
+ 299 : ["Phoenician", "phn"],
+ 300 : ["Prakrit Language", "pra"],
+ 301 : ["Rejang", "rej"],
+ 302 : ["Sabaean", "xsa"],
+ 303 : ["Samaritan", "smp"],
+ 304 : ["Santali", "sat"],
+ 305 : ["Saurashtra", "saz"],
+ 306 : ["Sora", "srb"],
+ 307 : ["Sylheti", "syl"],
+ 308 : ["Tagbanwa", "tbw"],
+ 309 : ["Tai Dam", "blt"],
+ 310 : ["Tai Nua", "tdd"],
+ 311 : ["Ugaritic", "uga"],
+ 312 : ["Akoose", "bss"],
+ 313 : ["Lakota", "lkt"],
+ 314 : ["Standard Moroccan Tamazight", "zgh"],
+ 315 : ["Mapuche", "arn"],
+ 316 : ["Central Kurdish", "ckb"],
+ 317 : ["Lower Sorbian", "dsb"],
+ 318 : ["Upper Sorbian", "hsb"],
+ 319 : ["Kenyang", "ken"],
+ 320 : ["Mohawk", "moh"],
+ 321 : ["Nko", "nqo"],
+ 322 : ["Prussian", "prg"],
+ 323 : ["Kiche", "quc"],
+ 324 : ["Southern Sami", "sma"],
+ 325 : ["Lule Sami", "smj"],
+ 326 : ["Inari Sami", "smn"],
+ 327 : ["Skolt Sami", "sms"],
+ 328 : ["Warlpiri", "wbp"],
+ 329 : ["Manichaean Middle Persian", "xmn"],
+ 330 : ["Mende", "men"],
+ 331 : ["Ancient North Arabian", "xna"],
+ 332 : ["Linear A", "lab"],
+ 333 : ["Hmong Njua", "hnj"],
+ 334 : ["Ho", "hoc"],
+ 335 : ["Lezghian", "lez"],
+ 336 : ["Bassa", "bsq"],
+ 337 : ["Mono", "mru"],
+ 338 : ["Tedim Chin", "ctd"],
+ 339 : ["Maithili", "mai"],
+ 340 : ["Ahom", "aho"],
+ 341 : ["American Sign Language", "ase"],
+ 342 : ["Ardhamagadhi Prakrit", "pka"],
+ 343 : ["Bhojpuri", "bho"],
+ 344 : ["Hieroglyphic Luwian", "hlu"],
+ 345 : ["Literary Chinese", "lzh"],
+ 346 : ["Mazanderani", "mzn"],
+ 347 : ["Mru", "mro"],
+ 348 : ["Newari", "new"],
+ 349 : ["Northern Luri", "lrc"],
+ 350 : ["Palauan", "pau"],
+ 351 : ["Papiamento", "pap"],
+ 352 : ["Saraiki", "skr"],
+ 353 : ["Tokelau", "tkl"],
+ 354 : ["Tok Pisin", "tpi"],
+ 355 : ["Tuvalu", "tvl"],
+ 356 : ["Uncoded Languages", "mis"],
+ 357 : ["Cantonese", "yue"],
+ 358 : ["Osage", "osa"],
+ 359 : ["Tangut", "txg"]
+}
+
+language_aliases = {
+ # Legacy - should disappear at some point:
+ 'Norwegian': 'NorwegianBokmal',
+ 'Moldavian': 'Romanian',
+ 'SerboCroatian': 'Serbian',
+ 'Tagalog': 'Filipino',
+ 'Twi': 'Akan',
+ # Renamings:
+ 'Afan': 'Oromo',
+ 'Byelorussian': 'Belarusian',
+ 'Bhutani': 'Dzongkha',
+ 'Cambodian': 'Khmer',
+ 'Kurundi': 'Rundi',
+ 'RhaetoRomance': 'Romansh',
+ 'Chewa': 'Nyanja',
+ 'Frisian': 'WesternFrisian',
+ 'Uigur': 'Uighur',
}
country_list = {
- 0 : [ "AnyCountry", "ZZ" ],
- 1 : [ "Afghanistan", "AF" ],
- 2 : [ "Albania", "AL" ],
- 3 : [ "Algeria", "DZ" ],
- 4 : [ "AmericanSamoa", "AS" ],
- 5 : [ "Andorra", "AD" ],
- 6 : [ "Angola", "AO" ],
- 7 : [ "Anguilla", "AI" ],
- 8 : [ "Antarctica", "AQ" ],
- 9 : [ "AntiguaAndBarbuda", "AG" ],
- 10 : [ "Argentina", "AR" ],
- 11 : [ "Armenia", "AM" ],
- 12 : [ "Aruba", "AW" ],
- 13 : [ "Australia", "AU" ],
- 14 : [ "Austria", "AT" ],
- 15 : [ "Azerbaijan", "AZ" ],
- 16 : [ "Bahamas", "BS" ],
- 17 : [ "Bahrain", "BH" ],
- 18 : [ "Bangladesh", "BD" ],
- 19 : [ "Barbados", "BB" ],
- 20 : [ "Belarus", "BY" ],
- 21 : [ "Belgium", "BE" ],
- 22 : [ "Belize", "BZ" ],
- 23 : [ "Benin", "BJ" ],
- 24 : [ "Bermuda", "BM" ],
- 25 : [ "Bhutan", "BT" ],
- 26 : [ "Bolivia", "BO" ],
- 27 : [ "BosniaAndHerzegowina", "BA" ],
- 28 : [ "Botswana", "BW" ],
- 29 : [ "BouvetIsland", "BV" ],
- 30 : [ "Brazil", "BR" ],
- 31 : [ "BritishIndianOceanTerritory", "IO" ],
- 32 : [ "Brunei", "BN" ],
- 33 : [ "Bulgaria", "BG" ],
- 34 : [ "BurkinaFaso", "BF" ],
- 35 : [ "Burundi", "BI" ],
- 36 : [ "Cambodia", "KH" ],
- 37 : [ "Cameroon", "CM" ],
- 38 : [ "Canada", "CA" ],
- 39 : [ "CapeVerde", "CV" ],
- 40 : [ "CaymanIslands", "KY" ],
- 41 : [ "CentralAfricanRepublic", "CF" ],
- 42 : [ "Chad", "TD" ],
- 43 : [ "Chile", "CL" ],
- 44 : [ "China", "CN" ],
- 45 : [ "ChristmasIsland", "CX" ],
- 46 : [ "CocosIslands", "CC" ],
- 47 : [ "Colombia", "CO" ],
- 48 : [ "Comoros", "KM" ],
- 49 : [ "CongoKinshasa", "CD" ],
- 50 : [ "CongoBrazzaville", "CG" ],
- 51 : [ "CookIslands", "CK" ],
- 52 : [ "CostaRica", "CR" ],
- 53 : [ "IvoryCoast", "CI" ],
- 54 : [ "Croatia", "HR" ],
- 55 : [ "Cuba", "CU" ],
- 56 : [ "Cyprus", "CY" ],
- 57 : [ "CzechRepublic", "CZ" ],
- 58 : [ "Denmark", "DK" ],
- 59 : [ "Djibouti", "DJ" ],
- 60 : [ "Dominica", "DM" ],
- 61 : [ "DominicanRepublic", "DO" ],
- 62 : [ "EastTimor", "TL" ],
- 63 : [ "Ecuador", "EC" ],
- 64 : [ "Egypt", "EG" ],
- 65 : [ "ElSalvador", "SV" ],
- 66 : [ "EquatorialGuinea", "GQ" ],
- 67 : [ "Eritrea", "ER" ],
- 68 : [ "Estonia", "EE" ],
- 69 : [ "Ethiopia", "ET" ],
- 70 : [ "FalklandIslands", "FK" ],
- 71 : [ "FaroeIslands", "FO" ],
- 72 : [ "Fiji", "FJ" ],
- 73 : [ "Finland", "FI" ],
- 74 : [ "France", "FR" ],
- 75 : [ "Guernsey", "GG" ],
- 76 : [ "FrenchGuiana", "GF" ],
- 77 : [ "FrenchPolynesia", "PF" ],
- 78 : [ "FrenchSouthernTerritories", "TF" ],
- 79 : [ "Gabon", "GA" ],
- 80 : [ "Gambia", "GM" ],
- 81 : [ "Georgia", "GE" ],
- 82 : [ "Germany", "DE" ],
- 83 : [ "Ghana", "GH" ],
- 84 : [ "Gibraltar", "GI" ],
- 85 : [ "Greece", "GR" ],
- 86 : [ "Greenland", "GL" ],
- 87 : [ "Grenada", "GD" ],
- 88 : [ "Guadeloupe", "GP" ],
- 89 : [ "Guam", "GU" ],
- 90 : [ "Guatemala", "GT" ],
- 91 : [ "Guinea", "GN" ],
- 92 : [ "GuineaBissau", "GW" ],
- 93 : [ "Guyana", "GY" ],
- 94 : [ "Haiti", "HT" ],
- 95 : [ "HeardAndMcDonaldIslands", "HM" ],
- 96 : [ "Honduras", "HN" ],
- 97 : [ "HongKong", "HK" ],
- 98 : [ "Hungary", "HU" ],
- 99 : [ "Iceland", "IS" ],
- 100 : [ "India", "IN" ],
- 101 : [ "Indonesia", "ID" ],
- 102 : [ "Iran", "IR" ],
- 103 : [ "Iraq", "IQ" ],
- 104 : [ "Ireland", "IE" ],
- 105 : [ "Israel", "IL" ],
- 106 : [ "Italy", "IT" ],
- 107 : [ "Jamaica", "JM" ],
- 108 : [ "Japan", "JP" ],
- 109 : [ "Jordan", "JO" ],
- 110 : [ "Kazakhstan", "KZ" ],
- 111 : [ "Kenya", "KE" ],
- 112 : [ "Kiribati", "KI" ],
- 113 : [ "NorthKorea", "KP" ],
- 114 : [ "SouthKorea", "KR" ],
- 115 : [ "Kuwait", "KW" ],
- 116 : [ "Kyrgyzstan", "KG" ],
- 117 : [ "Laos", "LA" ],
- 118 : [ "Latvia", "LV" ],
- 119 : [ "Lebanon", "LB" ],
- 120 : [ "Lesotho", "LS" ],
- 121 : [ "Liberia", "LR" ],
- 122 : [ "Libya", "LY" ],
- 123 : [ "Liechtenstein", "LI" ],
- 124 : [ "Lithuania", "LT" ],
- 125 : [ "Luxembourg", "LU" ],
- 126 : [ "Macau", "MO" ],
- 127 : [ "Macedonia", "MK" ],
- 128 : [ "Madagascar", "MG" ],
- 129 : [ "Malawi", "MW" ],
- 130 : [ "Malaysia", "MY" ],
- 131 : [ "Maldives", "MV" ],
- 132 : [ "Mali", "ML" ],
- 133 : [ "Malta", "MT" ],
- 134 : [ "MarshallIslands", "MH" ],
- 135 : [ "Martinique", "MQ" ],
- 136 : [ "Mauritania", "MR" ],
- 137 : [ "Mauritius", "MU" ],
- 138 : [ "Mayotte", "YT" ],
- 139 : [ "Mexico", "MX" ],
- 140 : [ "Micronesia", "FM" ],
- 141 : [ "Moldova", "MD" ],
- 142 : [ "Monaco", "MC" ],
- 143 : [ "Mongolia", "MN" ],
- 144 : [ "Montserrat", "MS" ],
- 145 : [ "Morocco", "MA" ],
- 146 : [ "Mozambique", "MZ" ],
- 147 : [ "Myanmar", "MM" ],
- 148 : [ "Namibia", "NA" ],
- 149 : [ "Nauru", "NR" ],
- 150 : [ "Nepal", "NP" ],
- 151 : [ "Netherlands", "NL" ],
- 152 : [ "CuraSao", "CW" ],
- 153 : [ "NewCaledonia", "NC" ],
- 154 : [ "NewZealand", "NZ" ],
- 155 : [ "Nicaragua", "NI" ],
- 156 : [ "Niger", "NE" ],
- 157 : [ "Nigeria", "NG" ],
- 158 : [ "Niue", "NU" ],
- 159 : [ "NorfolkIsland", "NF" ],
- 160 : [ "NorthernMarianaIslands", "MP" ],
- 161 : [ "Norway", "NO" ],
- 162 : [ "Oman", "OM" ],
- 163 : [ "Pakistan", "PK" ],
- 164 : [ "Palau", "PW" ],
- 165 : [ "PalestinianTerritories", "PS" ],
- 166 : [ "Panama", "PA" ],
- 167 : [ "PapuaNewGuinea", "PG" ],
- 168 : [ "Paraguay", "PY" ],
- 169 : [ "Peru", "PE" ],
- 170 : [ "Philippines", "PH" ],
- 171 : [ "Pitcairn", "PN" ],
- 172 : [ "Poland", "PL" ],
- 173 : [ "Portugal", "PT" ],
- 174 : [ "PuertoRico", "PR" ],
- 175 : [ "Qatar", "QA" ],
- 176 : [ "Reunion", "RE" ],
- 177 : [ "Romania", "RO" ],
- 178 : [ "Russia", "RU" ],
- 179 : [ "Rwanda", "RW" ],
- 180 : [ "SaintKittsAndNevis", "KN" ],
- 181 : [ "SaintLucia", "LC" ],
- 182 : [ "SaintVincentAndTheGrenadines", "VC" ],
- 183 : [ "Samoa", "WS" ],
- 184 : [ "SanMarino", "SM" ],
- 185 : [ "SaoTomeAndPrincipe", "ST" ],
- 186 : [ "SaudiArabia", "SA" ],
- 187 : [ "Senegal", "SN" ],
- 188 : [ "Seychelles", "SC" ],
- 189 : [ "SierraLeone", "SL" ],
- 190 : [ "Singapore", "SG" ],
- 191 : [ "Slovakia", "SK" ],
- 192 : [ "Slovenia", "SI" ],
- 193 : [ "SolomonIslands", "SB" ],
- 194 : [ "Somalia", "SO" ],
- 195 : [ "SouthAfrica", "ZA" ],
- 196 : [ "SouthGeorgiaAndTheSouthSandwichIslands", "GS" ],
- 197 : [ "Spain", "ES" ],
- 198 : [ "SriLanka", "LK" ],
- 199 : [ "SaintHelena", "SH" ],
- 200 : [ "SaintPierreAndMiquelon", "PM" ],
- 201 : [ "Sudan", "SD" ],
- 202 : [ "Suriname", "SR" ],
- 203 : [ "SvalbardAndJanMayenIslands", "SJ" ],
- 204 : [ "Swaziland", "SZ" ],
- 205 : [ "Sweden", "SE" ],
- 206 : [ "Switzerland", "CH" ],
- 207 : [ "Syria", "SY" ],
- 208 : [ "Taiwan", "TW" ],
- 209 : [ "Tajikistan", "TJ" ],
- 210 : [ "Tanzania", "TZ" ],
- 211 : [ "Thailand", "TH" ],
- 212 : [ "Togo", "TG" ],
- 213 : [ "Tokelau", "TK" ],
- 214 : [ "Tonga", "TO" ],
- 215 : [ "TrinidadAndTobago", "TT" ],
- 216 : [ "Tunisia", "TN" ],
- 217 : [ "Turkey", "TR" ],
- 218 : [ "Turkmenistan", "TM" ],
- 219 : [ "TurksAndCaicosIslands", "TC" ],
- 220 : [ "Tuvalu", "TV" ],
- 221 : [ "Uganda", "UG" ],
- 222 : [ "Ukraine", "UA" ],
- 223 : [ "UnitedArabEmirates", "AE" ],
- 224 : [ "UnitedKingdom", "GB" ],
- 225 : [ "UnitedStates", "US" ],
- 226 : [ "UnitedStatesMinorOutlyingIslands", "UM" ],
- 227 : [ "Uruguay", "UY" ],
- 228 : [ "Uzbekistan", "UZ" ],
- 229 : [ "Vanuatu", "VU" ],
- 230 : [ "VaticanCityState", "VA" ],
- 231 : [ "Venezuela", "VE" ],
- 232 : [ "Vietnam", "VN" ],
- 233 : [ "BritishVirginIslands", "VG" ],
- 234 : [ "UnitedStatesVirginIslands", "VI" ],
- 235 : [ "WallisAndFutunaIslands", "WF" ],
- 236 : [ "WesternSahara", "EH" ],
- 237 : [ "Yemen", "YE" ],
- 238 : [ "CanaryIslands", "IC" ],
- 239 : [ "Zambia", "ZM" ],
- 240 : [ "Zimbabwe", "ZW" ],
- 241 : [ "ClippertonIsland", "CP" ],
- 242 : [ "Montenegro", "ME" ],
- 243 : [ "Serbia", "RS" ],
- 244 : [ "Saint Barthelemy", "BL" ],
- 245 : [ "Saint Martin", "MF" ],
- 246 : [ "LatinAmericaAndTheCaribbean", "419" ],
- 247 : [ "AscensionIsland", "AC" ],
- 248 : [ "AlandIslands", "AX" ],
- 249 : [ "DiegoGarcia", "DG" ],
- 250 : [ "CeutaAndMelilla", "EA" ],
- 251 : [ "IsleOfMan", "IM" ],
- 252 : [ "Jersey", "JE" ],
- 253 : [ "TristanDaCunha", "TA" ],
- 254 : [ "SouthSudan", "SS" ],
- 255 : [ "Bonaire", "BQ" ],
- 256 : [ "SintMaarten", "SX" ],
- 257 : [ "Kosovo", "XK" ],
- 258 : [ "European Union", "EU" ],
- 259 : [ "Outlying Oceania", "QO" ]
+ 0 : ["AnyCountry", "ZZ"],
+ 1 : ["Afghanistan", "AF"],
+ 2 : ["Albania", "AL"],
+ 3 : ["Algeria", "DZ"],
+ 4 : ["American Samoa", "AS"],
+ 5 : ["Andorra", "AD"],
+ 6 : ["Angola", "AO"],
+ 7 : ["Anguilla", "AI"],
+ 8 : ["Antarctica", "AQ"],
+ 9 : ["Antigua And Barbuda", "AG"],
+ 10 : ["Argentina", "AR"],
+ 11 : ["Armenia", "AM"],
+ 12 : ["Aruba", "AW"],
+ 13 : ["Australia", "AU"],
+ 14 : ["Austria", "AT"],
+ 15 : ["Azerbaijan", "AZ"],
+ 16 : ["Bahamas", "BS"],
+ 17 : ["Bahrain", "BH"],
+ 18 : ["Bangladesh", "BD"],
+ 19 : ["Barbados", "BB"],
+ 20 : ["Belarus", "BY"],
+ 21 : ["Belgium", "BE"],
+ 22 : ["Belize", "BZ"],
+ 23 : ["Benin", "BJ"],
+ 24 : ["Bermuda", "BM"],
+ 25 : ["Bhutan", "BT"],
+ 26 : ["Bolivia", "BO"],
+ 27 : ["Bosnia And Herzegowina", "BA"],
+ 28 : ["Botswana", "BW"],
+ 29 : ["Bouvet Island", "BV"],
+ 30 : ["Brazil", "BR"],
+ 31 : ["British Indian Ocean Territory", "IO"],
+ 32 : ["Brunei", "BN"],
+ 33 : ["Bulgaria", "BG"],
+ 34 : ["Burkina Faso", "BF"],
+ 35 : ["Burundi", "BI"],
+ 36 : ["Cambodia", "KH"],
+ 37 : ["Cameroon", "CM"],
+ 38 : ["Canada", "CA"],
+ 39 : ["Cape Verde", "CV"],
+ 40 : ["Cayman Islands", "KY"],
+ 41 : ["Central African Republic", "CF"],
+ 42 : ["Chad", "TD"],
+ 43 : ["Chile", "CL"],
+ 44 : ["China", "CN"],
+ 45 : ["Christmas Island", "CX"],
+ 46 : ["Cocos Islands", "CC"],
+ 47 : ["Colombia", "CO"],
+ 48 : ["Comoros", "KM"],
+ 49 : ["Congo Kinshasa", "CD"],
+ 50 : ["Congo Brazzaville", "CG"],
+ 51 : ["Cook Islands", "CK"],
+ 52 : ["Costa Rica", "CR"],
+ 53 : ["Ivory Coast", "CI"],
+ 54 : ["Croatia", "HR"],
+ 55 : ["Cuba", "CU"],
+ 56 : ["Cyprus", "CY"],
+ 57 : ["Czech Republic", "CZ"],
+ 58 : ["Denmark", "DK"],
+ 59 : ["Djibouti", "DJ"],
+ 60 : ["Dominica", "DM"],
+ 61 : ["Dominican Republic", "DO"],
+ 62 : ["East Timor", "TL"],
+ 63 : ["Ecuador", "EC"],
+ 64 : ["Egypt", "EG"],
+ 65 : ["El Salvador", "SV"],
+ 66 : ["Equatorial Guinea", "GQ"],
+ 67 : ["Eritrea", "ER"],
+ 68 : ["Estonia", "EE"],
+ 69 : ["Ethiopia", "ET"],
+ 70 : ["Falkland Islands", "FK"],
+ 71 : ["Faroe Islands", "FO"],
+ 72 : ["Fiji", "FJ"],
+ 73 : ["Finland", "FI"],
+ 74 : ["France", "FR"],
+ 75 : ["Guernsey", "GG"],
+ 76 : ["French Guiana", "GF"],
+ 77 : ["French Polynesia", "PF"],
+ 78 : ["French Southern Territories", "TF"],
+ 79 : ["Gabon", "GA"],
+ 80 : ["Gambia", "GM"],
+ 81 : ["Georgia", "GE"],
+ 82 : ["Germany", "DE"],
+ 83 : ["Ghana", "GH"],
+ 84 : ["Gibraltar", "GI"],
+ 85 : ["Greece", "GR"],
+ 86 : ["Greenland", "GL"],
+ 87 : ["Grenada", "GD"],
+ 88 : ["Guadeloupe", "GP"],
+ 89 : ["Guam", "GU"],
+ 90 : ["Guatemala", "GT"],
+ 91 : ["Guinea", "GN"],
+ 92 : ["Guinea Bissau", "GW"],
+ 93 : ["Guyana", "GY"],
+ 94 : ["Haiti", "HT"],
+ 95 : ["Heard And McDonald Islands", "HM"],
+ 96 : ["Honduras", "HN"],
+ 97 : ["Hong Kong", "HK"],
+ 98 : ["Hungary", "HU"],
+ 99 : ["Iceland", "IS"],
+ 100 : ["India", "IN"],
+ 101 : ["Indonesia", "ID"],
+ 102 : ["Iran", "IR"],
+ 103 : ["Iraq", "IQ"],
+ 104 : ["Ireland", "IE"],
+ 105 : ["Israel", "IL"],
+ 106 : ["Italy", "IT"],
+ 107 : ["Jamaica", "JM"],
+ 108 : ["Japan", "JP"],
+ 109 : ["Jordan", "JO"],
+ 110 : ["Kazakhstan", "KZ"],
+ 111 : ["Kenya", "KE"],
+ 112 : ["Kiribati", "KI"],
+ 113 : ["North Korea", "KP"],
+ 114 : ["South Korea", "KR"],
+ 115 : ["Kuwait", "KW"],
+ 116 : ["Kyrgyzstan", "KG"],
+ 117 : ["Laos", "LA"],
+ 118 : ["Latvia", "LV"],
+ 119 : ["Lebanon", "LB"],
+ 120 : ["Lesotho", "LS"],
+ 121 : ["Liberia", "LR"],
+ 122 : ["Libya", "LY"],
+ 123 : ["Liechtenstein", "LI"],
+ 124 : ["Lithuania", "LT"],
+ 125 : ["Luxembourg", "LU"],
+ 126 : ["Macau", "MO"],
+ 127 : ["Macedonia", "MK"],
+ 128 : ["Madagascar", "MG"],
+ 129 : ["Malawi", "MW"],
+ 130 : ["Malaysia", "MY"],
+ 131 : ["Maldives", "MV"],
+ 132 : ["Mali", "ML"],
+ 133 : ["Malta", "MT"],
+ 134 : ["Marshall Islands", "MH"],
+ 135 : ["Martinique", "MQ"],
+ 136 : ["Mauritania", "MR"],
+ 137 : ["Mauritius", "MU"],
+ 138 : ["Mayotte", "YT"],
+ 139 : ["Mexico", "MX"],
+ 140 : ["Micronesia", "FM"],
+ 141 : ["Moldova", "MD"],
+ 142 : ["Monaco", "MC"],
+ 143 : ["Mongolia", "MN"],
+ 144 : ["Montserrat", "MS"],
+ 145 : ["Morocco", "MA"],
+ 146 : ["Mozambique", "MZ"],
+ 147 : ["Myanmar", "MM"],
+ 148 : ["Namibia", "NA"],
+ 149 : ["Nauru", "NR"],
+ 150 : ["Nepal", "NP"],
+ 151 : ["Netherlands", "NL"],
+ 152 : ["Cura Sao", "CW"],
+ 153 : ["New Caledonia", "NC"],
+ 154 : ["New Zealand", "NZ"],
+ 155 : ["Nicaragua", "NI"],
+ 156 : ["Niger", "NE"],
+ 157 : ["Nigeria", "NG"],
+ 158 : ["Niue", "NU"],
+ 159 : ["Norfolk Island", "NF"],
+ 160 : ["Northern Mariana Islands", "MP"],
+ 161 : ["Norway", "NO"],
+ 162 : ["Oman", "OM"],
+ 163 : ["Pakistan", "PK"],
+ 164 : ["Palau", "PW"],
+ 165 : ["Palestinian Territories", "PS"],
+ 166 : ["Panama", "PA"],
+ 167 : ["Papua New Guinea", "PG"],
+ 168 : ["Paraguay", "PY"],
+ 169 : ["Peru", "PE"],
+ 170 : ["Philippines", "PH"],
+ 171 : ["Pitcairn", "PN"],
+ 172 : ["Poland", "PL"],
+ 173 : ["Portugal", "PT"],
+ 174 : ["Puerto Rico", "PR"],
+ 175 : ["Qatar", "QA"],
+ 176 : ["Reunion", "RE"],
+ 177 : ["Romania", "RO"],
+ 178 : ["Russia", "RU"],
+ 179 : ["Rwanda", "RW"],
+ 180 : ["Saint Kitts And Nevis", "KN"],
+ 181 : ["Saint Lucia", "LC"],
+ 182 : ["Saint Vincent And The Grenadines", "VC"],
+ 183 : ["Samoa", "WS"],
+ 184 : ["San Marino", "SM"],
+ 185 : ["Sao Tome And Principe", "ST"],
+ 186 : ["Saudi Arabia", "SA"],
+ 187 : ["Senegal", "SN"],
+ 188 : ["Seychelles", "SC"],
+ 189 : ["Sierra Leone", "SL"],
+ 190 : ["Singapore", "SG"],
+ 191 : ["Slovakia", "SK"],
+ 192 : ["Slovenia", "SI"],
+ 193 : ["Solomon Islands", "SB"],
+ 194 : ["Somalia", "SO"],
+ 195 : ["South Africa", "ZA"],
+ 196 : ["South Georgia And The South Sandwich Islands", "GS"],
+ 197 : ["Spain", "ES"],
+ 198 : ["Sri Lanka", "LK"],
+ 199 : ["Saint Helena", "SH"],
+ 200 : ["Saint Pierre And Miquelon", "PM"],
+ 201 : ["Sudan", "SD"],
+ 202 : ["Suriname", "SR"],
+ 203 : ["Svalbard And Jan Mayen Islands", "SJ"],
+ 204 : ["Swaziland", "SZ"],
+ 205 : ["Sweden", "SE"],
+ 206 : ["Switzerland", "CH"],
+ 207 : ["Syria", "SY"],
+ 208 : ["Taiwan", "TW"],
+ 209 : ["Tajikistan", "TJ"],
+ 210 : ["Tanzania", "TZ"],
+ 211 : ["Thailand", "TH"],
+ 212 : ["Togo", "TG"],
+ 213 : ["Tokelau", "TK"],
+ 214 : ["Tonga", "TO"],
+ 215 : ["Trinidad And Tobago", "TT"],
+ 216 : ["Tunisia", "TN"],
+ 217 : ["Turkey", "TR"],
+ 218 : ["Turkmenistan", "TM"],
+ 219 : ["Turks And Caicos Islands", "TC"],
+ 220 : ["Tuvalu", "TV"],
+ 221 : ["Uganda", "UG"],
+ 222 : ["Ukraine", "UA"],
+ 223 : ["United Arab Emirates", "AE"],
+ 224 : ["United Kingdom", "GB"],
+ 225 : ["United States", "US"],
+ 226 : ["United States Minor Outlying Islands", "UM"],
+ 227 : ["Uruguay", "UY"],
+ 228 : ["Uzbekistan", "UZ"],
+ 229 : ["Vanuatu", "VU"],
+ 230 : ["Vatican City State", "VA"],
+ 231 : ["Venezuela", "VE"],
+ 232 : ["Vietnam", "VN"],
+ 233 : ["British Virgin Islands", "VG"],
+ 234 : ["United States Virgin Islands", "VI"],
+ 235 : ["Wallis And Futuna Islands", "WF"],
+ 236 : ["Western Sahara", "EH"],
+ 237 : ["Yemen", "YE"],
+ 238 : ["Canary Islands", "IC"],
+ 239 : ["Zambia", "ZM"],
+ 240 : ["Zimbabwe", "ZW"],
+ 241 : ["Clipperton Island", "CP"],
+ 242 : ["Montenegro", "ME"],
+ 243 : ["Serbia", "RS"],
+ 244 : ["Saint Barthelemy", "BL"],
+ 245 : ["Saint Martin", "MF"],
+ 246 : ["Latin America", "419"],
+ 247 : ["Ascension Island", "AC"],
+ 248 : ["Aland Islands", "AX"],
+ 249 : ["Diego Garcia", "DG"],
+ 250 : ["Ceuta And Melilla", "EA"],
+ 251 : ["Isle Of Man", "IM"],
+ 252 : ["Jersey", "JE"],
+ 253 : ["Tristan Da Cunha", "TA"],
+ 254 : ["South Sudan", "SS"],
+ 255 : ["Bonaire", "BQ"],
+ 256 : ["Sint Maarten", "SX"],
+ 257 : ["Kosovo", "XK"],
+ 258 : ["European Union", "EU"],
+ 259 : ["Outlying Oceania", "QO"],
+ 260 : ["World", "001"],
+ 261 : ["Europe", "150"]
+}
+
+country_aliases = {
+ # Deprecated:
+ 'Tokelau': 'TokelauCountry',
+ 'Tuvalu': 'TuvaluCountry',
+ # Renamings:
+ 'DemocraticRepublicOfCongo': 'CongoKinshasa',
+ 'PeoplesRepublicOfCongo': 'CongoBrazzaville',
+ 'DemocraticRepublicOfKorea': 'NorthKorea',
+ 'RepublicOfKorea': 'SouthKorea',
+ 'RussianFederation': 'Russia',
+ 'SyrianArabRepublic': 'Syria',
+ 'LatinAmericaAndTheCaribbean': 'LatinAmerica',
}
script_list = {
- 0 : [ "AnyScript", "Zzzz" ],
- 1 : [ "Arabic", "Arab" ],
- 2 : [ "Cyrillic", "Cyrl" ],
- 3 : [ "Deseret", "Dsrt" ],
- 4 : [ "Gurmukhi", "Guru" ],
- 5 : [ "Simplified Han", "Hans" ],
- 6 : [ "Traditional Han", "Hant" ],
- 7 : [ "Latin", "Latn" ],
- 8 : [ "Mongolian", "Mong" ],
- 9 : [ "Tifinagh", "Tfng" ],
- 10 : [ "Armenian", "Armn" ],
- 11 : [ "Bengali", "Beng" ],
- 12 : [ "Cherokee", "Cher" ],
- 13 : [ "Devanagari", "Deva" ],
- 14 : [ "Ethiopic", "Ethi" ],
- 15 : [ "Georgian", "Geor" ],
- 16 : [ "Greek", "Grek" ],
- 17 : [ "Gujarati", "Gujr" ],
- 18 : [ "Hebrew", "Hebr" ],
- 19 : [ "Japanese", "Jpan" ],
- 20 : [ "Khmer", "Khmr" ],
- 21 : [ "Kannada", "Knda" ],
- 22 : [ "Korean", "Kore" ],
- 23 : [ "Lao", "Laoo" ],
- 24 : [ "Malayalam", "Mlym" ],
- 25 : [ "Myanmar", "Mymr" ],
- 26 : [ "Oriya", "Orya" ],
- 27 : [ "Tamil", "Taml" ],
- 28 : [ "Telugu", "Telu" ],
- 29 : [ "Thaana", "Thaa" ],
- 30 : [ "Thai", "Thai" ],
- 31 : [ "Tibetan", "Tibt" ],
- 32 : [ "Sinhala", "Sinh" ],
- 33 : [ "Syriac", "Syrc" ],
- 34 : [ "Yi", "Yiii" ],
- 35 : [ "Vai", "Vaii" ],
- 36 : [ "Avestan", "Avst" ],
- 37 : [ "Balinese", "Bali" ],
- 38 : [ "Bamum", "Bamu" ],
- 39 : [ "Batak", "Batk" ],
- 40 : [ "Bopomofo", "Bopo" ],
- 41 : [ "Brahmi", "Brah" ],
- 42 : [ "Buginese", "Bugi" ],
- 43 : [ "Buhid", "Buhd" ],
- 44 : [ "CanadianAboriginal", "Cans" ],
- 45 : [ "Carian", "Cari" ],
- 46 : [ "Chakma", "Cakm" ],
- 47 : [ "Cham", "Cham" ],
- 48 : [ "Coptic", "Copt" ],
- 49 : [ "Cypriot", "Cprt" ],
- 50 : [ "Egyptian Hieroglyphs", "Egyp" ],
- 51 : [ "Fraser", "Lisu" ],
- 52 : [ "Glagolitic", "Glag" ],
- 53 : [ "Gothic", "Goth" ],
- 54 : [ "Han", "Hani" ],
- 55 : [ "Hangul", "Hang" ],
- 56 : [ "Hanunoo", "Hano" ],
- 57 : [ "Imperial Aramaic", "Armi" ],
- 58 : [ "Inscriptional Pahlavi", "Phli" ],
- 59 : [ "Inscriptional Parthian", "Prti" ],
- 60 : [ "Javanese", "Java" ],
- 61 : [ "Kaithi", "Kthi" ],
- 62 : [ "Katakana", "Kana" ],
- 63 : [ "Kayah Li", "Kali" ],
- 64 : [ "Kharoshthi", "Khar" ],
- 65 : [ "Lanna", "Lana" ],
- 66 : [ "Lepcha", "Lepc" ],
- 67 : [ "Limbu", "Limb" ],
- 68 : [ "Linear B", "Linb" ],
- 69 : [ "Lycian", "Lyci" ],
- 70 : [ "Lydian", "Lydi" ],
- 71 : [ "Mandaean", "Mand" ],
- 72 : [ "Meitei Mayek", "Mtei" ],
- 73 : [ "Meroitic", "Mero" ],
- 74 : [ "Meroitic Cursive", "Merc" ],
- 75 : [ "Nko", "Nkoo" ],
- 76 : [ "New Tai Lue", "Talu" ],
- 77 : [ "Ogham", "Ogam" ],
- 78 : [ "Ol Chiki", "Olck" ],
- 79 : [ "Old Italic", "Ital" ],
- 80 : [ "Old Persian", "Xpeo" ],
- 81 : [ "Old South Arabian", "Sarb" ],
- 82 : [ "Orkhon", "Orkh" ],
- 83 : [ "Osmanya", "Osma" ],
- 84 : [ "Phags Pa", "Phag" ],
- 85 : [ "Phoenician", "Phnx" ],
- 86 : [ "Pollard Phonetic", "Plrd" ],
- 87 : [ "Rejang", "Rjng" ],
- 88 : [ "Runic", "Runr" ],
- 89 : [ "Samaritan", "Samr" ],
- 90 : [ "Saurashtra", "Saur" ],
- 91 : [ "Sharada", "Shrd" ],
- 92 : [ "Shavian", "Shaw" ],
- 93 : [ "Sora Sompeng", "Sora" ],
- 94 : [ "Cuneiform", "Xsux" ],
- 95 : [ "Sundanese", "Sund" ],
- 96 : [ "Syloti Nagri", "Sylo" ],
- 97 : [ "Tagalog", "Tglg" ],
- 98 : [ "Tagbanwa", "Tagb" ],
- 99 : [ "Tai Le", "Tale" ],
- 100 : [ "Tai Viet", "Tavt" ],
- 101 : [ "Takri", "Takr" ],
- 102 : [ "Ugaritic", "Ugar" ],
- 103 : [ "Braille", "Brai" ],
- 104 : [ "Hiragana", "Hira" ],
- 105 : [ "Caucasian Albanian", "Aghb" ],
- 106 : [ "Bassa Vah", "Bass" ],
- 107 : [ "Duployan", "Dupl" ],
- 108 : [ "Elbasan", "Elba" ],
- 109 : [ "Grantha", "Gran" ],
- 110 : [ "Pahawh Hmong", "Hmng" ],
- 111 : [ "Khojki", "Khoj" ],
- 112 : [ "Linear A", "Lina" ],
- 113 : [ "Mahajani", "Mahj" ],
- 114 : [ "Manichaean", "Mani" ],
- 115 : [ "Mende Kikakui", "Mend" ],
- 116 : [ "Modi", "Modi" ],
- 117 : [ "Mro", "Mroo" ],
- 118 : [ "Old North Arabian", "Narb" ],
- 119 : [ "Nabataean", "Nbat" ],
- 120 : [ "Palmyrene", "Palm" ],
- 121 : [ "Pau Cin Hau", "Pauc" ],
- 122 : [ "Old Permic", "Perm" ],
- 123 : [ "Psalter Pahlavi", "Phlp" ],
- 124 : [ "Siddham", "Sidd" ],
- 125 : [ "Khudawadi", "Sind" ],
- 126 : [ "Tirhuta", "Tirh" ],
- 127 : [ "Varang Kshiti", "Wara" ],
- 128 : [ "Ahom", "Ahom" ],
- 129 : [ "Anatolian Hieroglyphs", "Hluw" ],
- 130 : [ "Hatran", "Hatr" ],
- 131 : [ "Multani", "Mult" ],
- 132 : [ "Old Hungarian", "Hung" ],
- 133 : [ "SignWriting", "Sgnw" ],
- 134 : [ "Adlam", "Adlm" ],
- 135 : [ "Bhaiksuki", "Bhks" ],
- 136 : [ "Marchen", "Marc" ],
- 137 : [ "Newa", "Newa" ],
- 138 : [ "Osage", "Osge" ],
- 139 : [ "Tangut", "Tang" ],
- 140 : [ "Han with Bopomofo", "Hanb" ],
- 141 : [ "Jamo", "Jamo" ]
+ 0 : ["AnyScript", "Zzzz"],
+ 1 : ["Arabic", "Arab"],
+ 2 : ["Cyrillic", "Cyrl"],
+ 3 : ["Deseret", "Dsrt"],
+ 4 : ["Gurmukhi", "Guru"],
+ 5 : ["Simplified Han", "Hans"],
+ 6 : ["Traditional Han", "Hant"],
+ 7 : ["Latin", "Latn"],
+ 8 : ["Mongolian", "Mong"],
+ 9 : ["Tifinagh", "Tfng"],
+ 10 : ["Armenian", "Armn"],
+ 11 : ["Bengali", "Beng"],
+ 12 : ["Cherokee", "Cher"],
+ 13 : ["Devanagari", "Deva"],
+ 14 : ["Ethiopic", "Ethi"],
+ 15 : ["Georgian", "Geor"],
+ 16 : ["Greek", "Grek"],
+ 17 : ["Gujarati", "Gujr"],
+ 18 : ["Hebrew", "Hebr"],
+ 19 : ["Japanese", "Jpan"],
+ 20 : ["Khmer", "Khmr"],
+ 21 : ["Kannada", "Knda"],
+ 22 : ["Korean", "Kore"],
+ 23 : ["Lao", "Laoo"],
+ 24 : ["Malayalam", "Mlym"],
+ 25 : ["Myanmar", "Mymr"],
+ 26 : ["Oriya", "Orya"],
+ 27 : ["Tamil", "Taml"],
+ 28 : ["Telugu", "Telu"],
+ 29 : ["Thaana", "Thaa"],
+ 30 : ["Thai", "Thai"],
+ 31 : ["Tibetan", "Tibt"],
+ 32 : ["Sinhala", "Sinh"],
+ 33 : ["Syriac", "Syrc"],
+ 34 : ["Yi", "Yiii"],
+ 35 : ["Vai", "Vaii"],
+ 36 : ["Avestan", "Avst"],
+ 37 : ["Balinese", "Bali"],
+ 38 : ["Bamum", "Bamu"],
+ 39 : ["Batak", "Batk"],
+ 40 : ["Bopomofo", "Bopo"],
+ 41 : ["Brahmi", "Brah"],
+ 42 : ["Buginese", "Bugi"],
+ 43 : ["Buhid", "Buhd"],
+ 44 : ["Canadian Aboriginal", "Cans"],
+ 45 : ["Carian", "Cari"],
+ 46 : ["Chakma", "Cakm"],
+ 47 : ["Cham", "Cham"],
+ 48 : ["Coptic", "Copt"],
+ 49 : ["Cypriot", "Cprt"],
+ 50 : ["Egyptian Hieroglyphs", "Egyp"],
+ 51 : ["Fraser", "Lisu"],
+ 52 : ["Glagolitic", "Glag"],
+ 53 : ["Gothic", "Goth"],
+ 54 : ["Han", "Hani"],
+ 55 : ["Hangul", "Hang"],
+ 56 : ["Hanunoo", "Hano"],
+ 57 : ["Imperial Aramaic", "Armi"],
+ 58 : ["Inscriptional Pahlavi", "Phli"],
+ 59 : ["Inscriptional Parthian", "Prti"],
+ 60 : ["Javanese", "Java"],
+ 61 : ["Kaithi", "Kthi"],
+ 62 : ["Katakana", "Kana"],
+ 63 : ["Kayah Li", "Kali"],
+ 64 : ["Kharoshthi", "Khar"],
+ 65 : ["Lanna", "Lana"],
+ 66 : ["Lepcha", "Lepc"],
+ 67 : ["Limbu", "Limb"],
+ 68 : ["Linear B", "Linb"],
+ 69 : ["Lycian", "Lyci"],
+ 70 : ["Lydian", "Lydi"],
+ 71 : ["Mandaean", "Mand"],
+ 72 : ["Meitei Mayek", "Mtei"],
+ 73 : ["Meroitic", "Mero"],
+ 74 : ["Meroitic Cursive", "Merc"],
+ 75 : ["Nko", "Nkoo"],
+ 76 : ["New Tai Lue", "Talu"],
+ 77 : ["Ogham", "Ogam"],
+ 78 : ["Ol Chiki", "Olck"],
+ 79 : ["Old Italic", "Ital"],
+ 80 : ["Old Persian", "Xpeo"],
+ 81 : ["Old South Arabian", "Sarb"],
+ 82 : ["Orkhon", "Orkh"],
+ 83 : ["Osmanya", "Osma"],
+ 84 : ["Phags Pa", "Phag"],
+ 85 : ["Phoenician", "Phnx"],
+ 86 : ["Pollard Phonetic", "Plrd"],
+ 87 : ["Rejang", "Rjng"],
+ 88 : ["Runic", "Runr"],
+ 89 : ["Samaritan", "Samr"],
+ 90 : ["Saurashtra", "Saur"],
+ 91 : ["Sharada", "Shrd"],
+ 92 : ["Shavian", "Shaw"],
+ 93 : ["Sora Sompeng", "Sora"],
+ 94 : ["Cuneiform", "Xsux"],
+ 95 : ["Sundanese", "Sund"],
+ 96 : ["Syloti Nagri", "Sylo"],
+ 97 : ["Tagalog", "Tglg"],
+ 98 : ["Tagbanwa", "Tagb"],
+ 99 : ["Tai Le", "Tale"],
+ 100 : ["Tai Viet", "Tavt"],
+ 101 : ["Takri", "Takr"],
+ 102 : ["Ugaritic", "Ugar"],
+ 103 : ["Braille", "Brai"],
+ 104 : ["Hiragana", "Hira"],
+ 105 : ["Caucasian Albanian", "Aghb"],
+ 106 : ["Bassa Vah", "Bass"],
+ 107 : ["Duployan", "Dupl"],
+ 108 : ["Elbasan", "Elba"],
+ 109 : ["Grantha", "Gran"],
+ 110 : ["Pahawh Hmong", "Hmng"],
+ 111 : ["Khojki", "Khoj"],
+ 112 : ["Linear A", "Lina"],
+ 113 : ["Mahajani", "Mahj"],
+ 114 : ["Manichaean", "Mani"],
+ 115 : ["Mende Kikakui", "Mend"],
+ 116 : ["Modi", "Modi"],
+ 117 : ["Mro", "Mroo"],
+ 118 : ["Old North Arabian", "Narb"],
+ 119 : ["Nabataean", "Nbat"],
+ 120 : ["Palmyrene", "Palm"],
+ 121 : ["Pau Cin Hau", "Pauc"],
+ 122 : ["Old Permic", "Perm"],
+ 123 : ["Psalter Pahlavi", "Phlp"],
+ 124 : ["Siddham", "Sidd"],
+ 125 : ["Khudawadi", "Sind"],
+ 126 : ["Tirhuta", "Tirh"],
+ 127 : ["Varang Kshiti", "Wara"],
+ 128 : ["Ahom", "Ahom"],
+ 129 : ["Anatolian Hieroglyphs", "Hluw"],
+ 130 : ["Hatran", "Hatr"],
+ 131 : ["Multani", "Mult"],
+ 132 : ["Old Hungarian", "Hung"],
+ 133 : ["Sign Writing", "Sgnw"],
+ 134 : ["Adlam", "Adlm"],
+ 135 : ["Bhaiksuki", "Bhks"],
+ 136 : ["Marchen", "Marc"],
+ 137 : ["Newa", "Newa"],
+ 138 : ["Osage", "Osge"],
+ 139 : ["Tangut", "Tang"],
+ 140 : ["Han with Bopomofo", "Hanb"],
+ 141 : ["Jamo", "Jamo"]
+}
+
+script_aliases = {
+ # Renamings:
+ 'SimplifiedChineseScript': 'SimplifiedHanScript',
+ 'TraditionalChineseScript': 'TraditionalHanScript',
}
def countryCodeToId(code):
diff --git a/util/local_database/qlocalexml2cpp.py b/util/local_database/qlocalexml2cpp.py
index 0f10f8ce2d..fb5ae5ba54 100755
--- a/util/local_database/qlocalexml2cpp.py
+++ b/util/local_database/qlocalexml2cpp.py
@@ -38,6 +38,7 @@ import sys
import tempfile
import datetime
import xml.dom.minidom
+from enumdata import language_aliases, country_aliases, script_aliases
from localexml import Locale
@@ -751,27 +752,15 @@ def main():
# Language enum
qlocaleh_temp_file.write(" enum Language {\n")
- language = ""
- for key in language_map.keys():
- language = fixedLanguageName(language_map[key][0], dupes)
+ language = None
+ for key, value in language_map.items():
+ language = fixedLanguageName(value[0], dupes)
qlocaleh_temp_file.write(" " + language + " = " + str(key) + ",\n")
- # legacy. should disappear at some point
- qlocaleh_temp_file.write("\n")
- qlocaleh_temp_file.write(" Norwegian = NorwegianBokmal,\n")
- qlocaleh_temp_file.write(" Moldavian = Romanian,\n")
- qlocaleh_temp_file.write(" SerboCroatian = Serbian,\n")
- qlocaleh_temp_file.write(" Tagalog = Filipino,\n")
- qlocaleh_temp_file.write(" Twi = Akan,\n")
- # renamings
- qlocaleh_temp_file.write(" Afan = Oromo,\n")
- qlocaleh_temp_file.write(" Byelorussian = Belarusian,\n")
- qlocaleh_temp_file.write(" Bhutani = Dzongkha,\n")
- qlocaleh_temp_file.write(" Cambodian = Khmer,\n")
- qlocaleh_temp_file.write(" Kurundi = Rundi,\n")
- qlocaleh_temp_file.write(" RhaetoRomance = Romansh,\n")
- qlocaleh_temp_file.write(" Chewa = Nyanja,\n")
- qlocaleh_temp_file.write(" Frisian = WesternFrisian,\n")
- qlocaleh_temp_file.write(" Uigur = Uighur,\n")
+
+ qlocaleh_temp_file.write("\n " +
+ ",\n ".join('%s = %s' % pair
+ for pair in sorted(language_aliases.items())) +
+ ",\n")
qlocaleh_temp_file.write("\n")
qlocaleh_temp_file.write(" LastLanguage = " + language + "\n")
qlocaleh_temp_file.write(" };\n")
@@ -780,35 +769,28 @@ def main():
# Script enum
qlocaleh_temp_file.write(" enum Script {\n")
- script = ""
- for key in script_map.keys():
- script = fixedScriptName(script_map[key][0], dupes)
+ script = None
+ for key, value in script_map.items():
+ script = fixedScriptName(value[0], dupes)
qlocaleh_temp_file.write(" " + script + " = " + str(key) + ",\n")
- # renamings
- qlocaleh_temp_file.write("\n")
- qlocaleh_temp_file.write(" SimplifiedChineseScript = SimplifiedHanScript,\n")
- qlocaleh_temp_file.write(" TraditionalChineseScript = TraditionalHanScript,\n")
+ qlocaleh_temp_file.write("\n " +
+ ",\n ".join('%s = %s' % pair
+ for pair in sorted(script_aliases.items())) +
+ ",\n")
qlocaleh_temp_file.write("\n")
qlocaleh_temp_file.write(" LastScript = " + script + "\n")
qlocaleh_temp_file.write(" };\n")
# Country enum
qlocaleh_temp_file.write(" enum Country {\n")
- country = ""
- for key in country_map.keys():
- country = fixedCountryName(country_map[key][0], dupes)
+ country = None
+ for key, value in country_map.items():
+ country = fixedCountryName(value[0], dupes)
qlocaleh_temp_file.write(" " + country + " = " + str(key) + ",\n")
- # deprecated
- qlocaleh_temp_file.write("\n")
- qlocaleh_temp_file.write(" Tokelau = TokelauCountry,\n")
- qlocaleh_temp_file.write(" Tuvalu = TuvaluCountry,\n")
- # renamings
- qlocaleh_temp_file.write(" DemocraticRepublicOfCongo = CongoKinshasa,\n")
- qlocaleh_temp_file.write(" PeoplesRepublicOfCongo = CongoBrazzaville,\n")
- qlocaleh_temp_file.write(" DemocraticRepublicOfKorea = NorthKorea,\n")
- qlocaleh_temp_file.write(" RepublicOfKorea = SouthKorea,\n")
- qlocaleh_temp_file.write(" RussianFederation = Russia,\n")
- qlocaleh_temp_file.write(" SyrianArabRepublic = Syria,\n")
+ qlocaleh_temp_file.write("\n " +
+ ",\n ".join('%s = %s' % pair
+ for pair in sorted(country_aliases.items())) +
+ ",\n")
qlocaleh_temp_file.write("\n")
qlocaleh_temp_file.write(" LastCountry = " + country + "\n")
qlocaleh_temp_file.write(" };\n")
@@ -835,7 +817,7 @@ def main():
qlocaleqdoc_temp_file = os.fdopen(qlocaleqdoc_temp_file, "w")
qlocaleqdoc_file = open(qtsrcdir + "/src/corelib/tools/qlocale.qdoc", "r")
s = qlocaleqdoc_file.readline()
- DOCSTRING=" QLocale's data is based on Common Locale Data Repository "
+ DOCSTRING = " QLocale's data is based on Common Locale Data Repository "
while s:
if DOCSTRING in s:
qlocaleqdoc_temp_file.write(DOCSTRING + "v" + cldr_version + ".\n")
diff --git a/util/unicode/main.cpp b/util/unicode/main.cpp
index 0f3c28137d..0c3c0b2ee1 100644
--- a/util/unicode/main.cpp
+++ b/util/unicode/main.cpp
@@ -2473,6 +2473,10 @@ static QByteArray createPropertyInfo()
out += ", ";
out += QByteArray::number( p.lowerCaseDiff );
out += ", ";
+ out += "#ifdef Q_OS_WASM \n"
+// " unsigned char : 0; //wasm 64 packing trick QTBUG-65259\n"
+ out += "#endif \n"
+ out += ", ";
// " ushort upperCaseSpecial : 1;\n"
// " signed short upperCaseDiff : 15;\n"
out += QByteArray::number( p.upperCaseSpecial );
@@ -2497,6 +2501,10 @@ static QByteArray createPropertyInfo()
// " ushort nfQuickCheck : 8;\n"
out += QByteArray::number( p.nfQuickCheck );
out += ", ";
+ out += "#ifdef Q_OS_WASM \n"
+// " unsigned char : 0; //wasm 64 packing trick QTBUG-65259\n"
+ out += "#endif \n"
+ out += ", ";
// " ushort graphemeBreakClass : 5; /* 5 used */\n"
// " ushort wordBreakClass : 5; /* 5 used */\n"
// " ushort sentenceBreakClass : 8; /* 4 used */\n"
diff --git a/util/x86simdgen/generate.pl b/util/x86simdgen/generate.pl
new file mode 100755
index 0000000000..5df2f4d526
--- /dev/null
+++ b/util/x86simdgen/generate.pl
@@ -0,0 +1,199 @@
+#!/usr/bin/env perl
+#############################################################################
+##
+## Copyright (C) 2018 Intel Corporation.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the build configuration tools of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:MIT$
+## Permission is hereby granted, free of charge, to any person obtaining a copy
+## of this software and associated documentation files (the "Software"), to deal
+## in the Software without restriction, including without limitation the rights
+## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+## copies of the Software, and to permit persons to whom the Software is
+## furnished to do so, subject to the following conditions:
+##
+## The above copyright notice and this permission notice shall be included in
+## all copies or substantial portions of the Software.
+##
+## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+## THE SOFTWARE.
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+use strict;
+$\ = "\n";
+$/ = "\n";
+my %leaves = (
+ Leaf1EDX => "CPUID Leaf 1, EDX",
+ Leaf1ECX => "CPUID Leaf 1, ECX",
+ Leaf7_0EBX => "CPUID Leaf 7, Sub-leaf 0, EBX",
+ Leaf7_0ECX => "CPUID Leaf 7, Sub-leaf 0, ECX",
+ Leaf7_0EDX => "CPUID Leaf 7, Sub-leaf 0, EDX",
+);
+my @leafNames = sort keys %leaves;
+
+# Read data from stdin
+my $i = 1;
+my @features;
+while (<STDIN>) {
+ s/#.*$//;
+ chomp;
+ next if $_ eq "";
+
+ my ($name, $function, $bit, $depends) = split /\s+/;
+ die("Unknown CPUID function \"$function\"")
+ unless grep $function, @leafNames;
+
+ my $id = uc($name);
+ $id =~ s/[^A-Z0-9_]/_/g;
+ push @features,
+ { name => $name, depends => $depends, id => $id, bit => $bit, leaf => $function };
+ ++$i;
+}
+
+if (my $h = shift @ARGV) {
+ open HEADER, ">", $h;
+ select HEADER;
+}
+
+# Print the qsimd_x86_p.h output
+print q{// This is a generated file. DO NOT EDIT.
+// Please see util/x86simdgen/generate.pl";
+#ifndef QSIMD_P_H
+# error "Please include <private/qsimd_p.h> instead"
+#endif
+#ifndef QSIMD_X86_P_H
+#define QSIMD_X86_P_H
+
+#include "qsimd_p.h"
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+// used only to indicate that the CPU detection was initialized
+#define QSimdInitialized (Q_UINT64_C(1) << 0)};
+
+# Print the enum
+my $lastleaf;
+for (my $i = 0; $i < scalar @features; ++$i) {
+ my $feature = $features[$i];
+ # Leaf header:
+ printf "\n// in %s:\n", $leaves{$feature->{leaf}}
+ if $feature->{leaf} ne $lastleaf;
+ $lastleaf = $feature->{leaf};
+
+ # Feature
+ printf "#define CpuFeature%-33s (Q_UINT64_C(1) << %d)\n", $feature->{id}, $i + 1;
+
+ # Feature string names for Clang and GCC
+ my $str = $feature->{name};
+ $str .= ",$feature->{depends}" if defined($feature->{depends});
+ printf "#define QT_FUNCTION_TARGET_STRING_%-17s \"%s\"\n",
+ $feature->{id}, $str;
+}
+
+print q{
+static const quint64 qCompilerCpuFeatures = 0};
+
+# And print the compiler-enabled features part:
+for (my $i = 0; $i < scalar @features; ++$i) {
+ my $feature = $features[$i];
+ printf
+ "#ifdef __%s__\n" .
+ " | CpuFeature%s\n" .
+ "#endif\n",
+ $feature->{id}, $feature->{id};
+}
+
+print q{ ;
+
+QT_END_NAMESPACE
+
+#endif // QSIMD_X86_P_H
+};
+
+if (my $cpp = shift @ARGV) {
+ open CPP, ">", $cpp;
+ select CPP;
+} else {
+ print q{
+
+---- cut here, paste the rest into qsimd_x86.cpp ---
+
+
+};
+};
+
+print "// This is a generated file. DO NOT EDIT.";
+print "// Please see util/x86simdgen/generate.pl";
+print '#include "qsimd_p.h"';
+print "";
+
+# Now generate the string table and bit-location array
+my $offset = 0;
+my @offsets;
+print "static const char features_string[] =";
+for my $feature (@features) {
+ print " \" $feature->{name}\\0\"";
+ push @offsets, $offset;
+ $offset += 2 + length($feature->{name});
+}
+print " \"\\0\";";
+
+# Print the string offset table
+printf "\nstatic const %s features_indices[] = {\n %3d",
+ $offset > 255 ? "quint16" : "quint8", $offset;
+for (my $j = 0; $j < scalar @offsets; ++$j) {
+ printf ",%s%3d",
+ ($j + 1) % 8 ? " " : "\n ", $offsets[$j];
+}
+print "\n};";
+
+# Print the locator enum and table
+print "\nenum X86CpuidLeaves {";
+map { print " $_," } @leafNames;
+print " X86CpuidMaxLeaf\n};";
+
+my $type = scalar %leaves > 8 ? "quint16" : "quint8";
+printf "\nstatic const %s x86_locators[] = {",
+ $type, $type;
+my $lastname;
+for (my $j = 0; $j < scalar @features; ++$j) {
+ my $feature = $features[$j];
+ printf ", // %s", $lastname
+ if defined($lastname);
+ printf "\n %s*32 + %2d",
+ $feature->{leaf}, $feature->{bit};
+ $lastname = $feature->{name};
+}
+printf qq{ // $lastname
+\};
+
+// List of AVX512 features (see detectProcessorFeatures())
+static const quint64 AllAVX512 = 0};
+
+# Print AVX512 features
+for (my $j = 0; $j < scalar @features; ++$j) {
+ my $feature = $features[$j];
+ $_ = $feature->{id};
+ printf "\n | CpuFeature%s", $_ if /AVX512/;
+}
+print ";";
diff --git a/util/x86simdgen/simd.txt b/util/x86simdgen/simd.txt
new file mode 100644
index 0000000000..1fce7b9497
--- /dev/null
+++ b/util/x86simdgen/simd.txt
@@ -0,0 +1,37 @@
+# Feature CPUID function Bit Required feature
+sse2 Leaf1EDX 26
+sse3 Leaf1ECX 0
+ssse3 Leaf1ECX 9
+fma Leaf1ECX 12
+sse4.1 Leaf1ECX 19
+sse4.2 Leaf1ECX 20
+movbe Leaf1ECX 22
+popcnt Leaf1ECX 23
+aes Leaf1ECX 25 sse4.2
+avx Leaf1ECX 28
+f16c Leaf1ECX 29
+rdrnd Leaf1ECX 30
+bmi Leaf7_0EBX 3
+hle Leaf7_0EBX 4
+avx2 Leaf7_0EBX 5
+bmi2 Leaf7_0EBX 8
+rtm Leaf7_0EBX 11
+avx512f Leaf7_0EBX 16
+avx512dq Leaf7_0EBX 17
+rdseed Leaf7_0EBX 18
+avx512ifma Leaf7_0EBX 21
+avx512pf Leaf7_0EBX 26
+avx512er Leaf7_0EBX 27
+avx512cd Leaf7_0EBX 28
+sha Leaf7_0EBX 29
+avx512bw Leaf7_0EBX 30
+avx512vl Leaf7_0EBX 31
+avx512vbmi Leaf7_0ECX 1
+avx512vbmi2 Leaf7_0ECX 6
+gfni Leaf7_0ECX 8
+vaes Leaf7_0ECX 9
+avx512vnni Leaf7_0ECX 11
+avx512bitalg Leaf7_0ECX 12
+avx512vpopcntdq Leaf7_0ECX 14
+avx5124nniw Leaf7_0EDX 2
+avx5124fmaps Leaf7_0EDX 3